From c6a33e2464edd87f8c12cc2d11369a5b44c65b77 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Wed, 12 Oct 2005 15:12:26 +0800 Subject: [PATCH] libata CHS: LBA28/LBA48 optimization (revise #6) - add lba_28_ok() and lba_48_ok() to ata.h. - check ending block number instead of staring block number. - use lba_28_ok() for CHS range check - LBA28/LBA48 optimization Suggested by Mark Lord and Alan Cox. Signed-off-by: Albert Lee ===== Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 48 ++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 90bf22204668..efbe6fe65442 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -636,9 +636,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; - if (dev->flags & ATA_DFLAG_LBA48) { - if (n_block > (64 * 1024)) - goto invalid_fld; + if (lba_28_ok(block, n_block)) { + /* use LBA28 */ + tf->command = ATA_CMD_VERIFY; + tf->device |= (block >> 24) & 0xf; + } else if (lba_48_ok(block, n_block)) { + if (!(dev->flags & ATA_DFLAG_LBA48)) + goto out_of_range; /* use LBA48 */ tf->flags |= ATA_TFLAG_LBA48; @@ -649,15 +653,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; - } else { - if (n_block > 256) - goto invalid_fld; - - /* use LBA28 */ - tf->command = ATA_CMD_VERIFY; - - tf->device |= (block >> 24) & 0xf; - } + } else + /* request too large even for LBA48 */ + goto out_of_range; tf->nsect = n_block & 0xff; @@ -670,8 +668,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) /* CHS */ u32 sect, head, cyl, track; - if (n_block > 256) - goto invalid_fld; + if (!lba_28_ok(block, n_block)) + goto out_of_range; /* Convert LBA to CHS */ track = (u32)block / dev->sectors; @@ -784,9 +782,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; - if (dev->flags & ATA_DFLAG_LBA48) { - /* The request -may- be too large for LBA48. */ - if ((block >> 48) || (n_block > 65536)) + if (lba_28_ok(block, n_block)) { + /* use LBA28 */ + tf->device |= (block >> 24) & 0xf; + } else if (lba_48_ok(block, n_block)) { + if (!(dev->flags & ATA_DFLAG_LBA48)) goto out_of_range; /* use LBA48 */ @@ -797,15 +797,9 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; - } else { - /* use LBA28 */ - - /* The request -may- be too large for LBA28. */ - if ((block >> 28) || (n_block > 256)) - goto out_of_range; - - tf->device |= (block >> 24) & 0xf; - } + } else + /* request too large even for LBA48 */ + goto out_of_range; ata_rwcmd_protocol(qc); @@ -822,7 +816,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) u32 sect, head, cyl, track; /* The request -may- be too large for CHS addressing. */ - if ((block >> 28) || (n_block > 256)) + if (!lba_28_ok(block, n_block)) goto out_of_range; ata_rwcmd_protocol(qc); -- cgit v1.2.3-59-g8ed1b From e03d72b99e4027504ada134bf1804d6ea792b206 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 9 Jan 2006 18:34:08 -0800 Subject: [PATCH] drivers/net/sk98lin/: possible cleanups This patch contains the following possible cleanups: - make needlessly global functions static - remove unused code Signed-off-by: Adrian Bunk Cc: Stephen Hemminger Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/sk98lin/h/skaddr.h | 48 ---- drivers/net/sk98lin/h/skcsum.h | 6 - drivers/net/sk98lin/h/skgeinit.h | 56 ----- drivers/net/sk98lin/h/skgepnmi.h | 4 - drivers/net/sk98lin/h/skgesirq.h | 1 - drivers/net/sk98lin/h/ski2c.h | 3 - drivers/net/sk98lin/h/skvpd.h | 15 -- drivers/net/sk98lin/skaddr.c | 35 ++- drivers/net/sk98lin/skgeinit.c | 148 +------------ drivers/net/sk98lin/skgemib.c | 7 - drivers/net/sk98lin/skgepnmi.c | 153 +------------ drivers/net/sk98lin/skgesirq.c | 24 +- drivers/net/sk98lin/ski2c.c | 6 +- drivers/net/sk98lin/sklm80.c | 72 ------ drivers/net/sk98lin/skrlmt.c | 1 - drivers/net/sk98lin/skvpd.c | 108 +-------- drivers/net/sk98lin/skxmac2.c | 461 +-------------------------------------- 17 files changed, 40 insertions(+), 1108 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h index 3a2ea4a4b539..423ad063d09b 100644 --- a/drivers/net/sk98lin/h/skaddr.h +++ b/drivers/net/sk98lin/h/skaddr.h @@ -236,18 +236,6 @@ extern int SkAddrMcClear( SK_U32 PortNumber, int Flags); -extern int SkAddrXmacMcClear( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int Flags); - -extern int SkAddrGmacMcClear( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int Flags); - extern int SkAddrMcAdd( SK_AC *pAC, SK_IOC IoC, @@ -255,35 +243,11 @@ extern int SkAddrMcAdd( SK_MAC_ADDR *pMc, int Flags); -extern int SkAddrXmacMcAdd( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - SK_MAC_ADDR *pMc, - int Flags); - -extern int SkAddrGmacMcAdd( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - SK_MAC_ADDR *pMc, - int Flags); - extern int SkAddrMcUpdate( SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber); -extern int SkAddrXmacMcUpdate( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber); - -extern int SkAddrGmacMcUpdate( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber); - extern int SkAddrOverride( SK_AC *pAC, SK_IOC IoC, @@ -297,18 +261,6 @@ extern int SkAddrPromiscuousChange( SK_U32 PortNumber, int NewPromMode); -extern int SkAddrXmacPromiscuousChange( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int NewPromMode); - -extern int SkAddrGmacPromiscuousChange( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int NewPromMode); - #ifndef SK_SLIM extern int SkAddrSwap( SK_AC *pAC, diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h index 2b94adb93331..6e256bd9a28c 100644 --- a/drivers/net/sk98lin/h/skcsum.h +++ b/drivers/net/sk98lin/h/skcsum.h @@ -203,12 +203,6 @@ extern SKCS_STATUS SkCsGetReceiveInfo( unsigned Checksum2, int NetNumber); -extern void SkCsGetSendInfo( - SK_AC *pAc, - void *pIpHeader, - SKCS_PACKET_INFO *pPacketInfo, - int NetNumber); - extern void SkCsSetReceiveFlags( SK_AC *pAc, unsigned ReceiveFlags, diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h index 184f47c5a60f..143e635ec24d 100644 --- a/drivers/net/sk98lin/h/skgeinit.h +++ b/drivers/net/sk98lin/h/skgeinit.h @@ -464,12 +464,6 @@ typedef struct s_GeInit { /* * public functions in skgeinit.c */ -extern void SkGePollRxD( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL PollRxD); - extern void SkGePollTxD( SK_AC *pAC, SK_IOC IoC, @@ -522,10 +516,6 @@ extern void SkGeXmitLED( int Led, int Mode); -extern void SkGeInitRamIface( - SK_AC *pAC, - SK_IOC IoC); - extern int SkGeInitAssignRamToQueues( SK_AC *pAC, int ActivePort, @@ -549,11 +539,6 @@ extern void SkMacHardRst( SK_IOC IoC, int Port); -extern void SkMacClearRst( - SK_AC *pAC, - SK_IOC IoC, - int Port); - extern void SkXmInitMac( SK_AC *pAC, SK_IOC IoC, @@ -580,11 +565,6 @@ extern void SkMacFlushTxFifo( SK_IOC IoC, int Port); -extern void SkMacFlushRxFifo( - SK_AC *pAC, - SK_IOC IoC, - int Port); - extern void SkMacIrq( SK_AC *pAC, SK_IOC IoC, @@ -601,12 +581,6 @@ extern void SkMacAutoNegLipaPhy( int Port, SK_U16 IStatus); -extern void SkMacSetRxTxEn( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Para); - extern int SkMacRxTxEnable( SK_AC *pAC, SK_IOC IoC, @@ -659,16 +633,6 @@ extern void SkXmClrExactAddr( int StartNum, int StopNum); -extern void SkXmInitDupMd( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkXmInitPauseMd( - SK_AC *pAC, - SK_IOC IoC, - int Port); - extern void SkXmAutoNegLipaXmac( SK_AC *pAC, SK_IOC IoC, @@ -729,17 +693,6 @@ extern int SkGmCableDiagStatus( int Port, SK_BOOL StartTest); -extern int SkGmEnterLowPowerMode( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U8 Mode); - -extern int SkGmLeaveLowPowerMode( - SK_AC *pAC, - SK_IOC IoC, - int Port); - #ifdef SK_DIAG extern void SkGePhyRead( SK_AC *pAC, @@ -782,7 +735,6 @@ extern void SkXmSendCont( /* * public functions in skgeinit.c */ -extern void SkGePollRxD(); extern void SkGePollTxD(); extern void SkGeYellowLED(); extern int SkGeCfgSync(); @@ -792,7 +744,6 @@ extern int SkGeInit(); extern void SkGeDeInit(); extern int SkGeInitPort(); extern void SkGeXmitLED(); -extern void SkGeInitRamIface(); extern int SkGeInitAssignRamToQueues(); /* @@ -801,18 +752,15 @@ extern int SkGeInitAssignRamToQueues(); extern void SkMacRxTxDisable(); extern void SkMacSoftRst(); extern void SkMacHardRst(); -extern void SkMacClearRst(); extern void SkMacInitPhy(); extern int SkMacRxTxEnable(); extern void SkMacPromiscMode(); extern void SkMacHashing(); extern void SkMacIrqDisable(); extern void SkMacFlushTxFifo(); -extern void SkMacFlushRxFifo(); extern void SkMacIrq(); extern int SkMacAutoNegDone(); extern void SkMacAutoNegLipaPhy(); -extern void SkMacSetRxTxEn(); extern void SkXmInitMac(); extern void SkXmPhyRead(); extern void SkXmPhyWrite(); @@ -820,8 +768,6 @@ extern void SkGmInitMac(); extern void SkGmPhyRead(); extern void SkGmPhyWrite(); extern void SkXmClrExactAddr(); -extern void SkXmInitDupMd(); -extern void SkXmInitPauseMd(); extern void SkXmAutoNegLipaXmac(); extern int SkXmUpdateStats(); extern int SkGmUpdateStats(); @@ -832,8 +778,6 @@ extern int SkGmResetCounter(); extern int SkXmOverflowStatus(); extern int SkGmOverflowStatus(); extern int SkGmCableDiagStatus(); -extern int SkGmEnterLowPowerMode(); -extern int SkGmLeaveLowPowerMode(); #ifdef SK_DIAG extern void SkGePhyRead(); diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h index 3b2773e6f822..1ed214ccb253 100644 --- a/drivers/net/sk98lin/h/skgepnmi.h +++ b/drivers/net/sk98lin/h/skgepnmi.h @@ -946,10 +946,6 @@ typedef struct s_PnmiData { * Function prototypes */ extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level); -extern int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf, - unsigned int* pLen, SK_U32 Instance, SK_U32 NetIndex); -extern int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, - void* pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf, diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h index b486bd9b6628..3eec6274e413 100644 --- a/drivers/net/sk98lin/h/skgesirq.h +++ b/drivers/net/sk98lin/h/skgesirq.h @@ -105,7 +105,6 @@ extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus); extern int SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); -extern void SkHWLinkUp(SK_AC *pAC, SK_IOC IoC, int Port); extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port); #endif /* _INC_SKGESIRQ_H_ */ diff --git a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h index 598bb42ccc3d..6a63f4a15de6 100644 --- a/drivers/net/sk98lin/h/ski2c.h +++ b/drivers/net/sk98lin/h/ski2c.h @@ -162,9 +162,6 @@ typedef struct s_I2c { } SK_I2C; extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level); -extern int SkI2cWrite(SK_AC *pAC, SK_IOC IoC, SK_U32 Data, int Dev, int Size, - int Reg, int Burst); -extern int SkI2cReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen); #ifdef SK_DIAG extern SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg, int Burst); diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h index daa9a8d154fc..fdd9e48e8040 100644 --- a/drivers/net/sk98lin/h/skvpd.h +++ b/drivers/net/sk98lin/h/skvpd.h @@ -183,14 +183,6 @@ extern SK_U32 VpdReadDWord( int addr); #endif /* SKDIAG */ -extern int VpdSetupPara( - SK_AC *pAC, - const char *key, - const char *buf, - int len, - int type, - int op); - extern SK_VPD_STATUS *VpdStat( SK_AC *pAC, SK_IOC IoC); @@ -227,11 +219,6 @@ extern int VpdUpdate( SK_AC *pAC, SK_IOC IoC); -extern void VpdErrLog( - SK_AC *pAC, - SK_IOC IoC, - char *msg); - #ifdef SKDIAG extern int VpdReadBlock( SK_AC *pAC, @@ -249,7 +236,6 @@ extern int VpdWriteBlock( #endif /* SKDIAG */ #else /* SK_KR_PROTO */ extern SK_U32 VpdReadDWord(); -extern int VpdSetupPara(); extern SK_VPD_STATUS *VpdStat(); extern int VpdKeys(); extern int VpdRead(); @@ -257,7 +243,6 @@ extern SK_BOOL VpdMayWrite(); extern int VpdWrite(); extern int VpdDelete(); extern int VpdUpdate(); -extern void VpdErrLog(); #endif /* SK_KR_PROTO */ #endif /* __INC_SKVPD_H_ */ diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c index a7e25edc7fc4..6e6c56aa6d6f 100644 --- a/drivers/net/sk98lin/skaddr.c +++ b/drivers/net/sk98lin/skaddr.c @@ -87,6 +87,21 @@ static const SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; static int Next0[SK_MAX_MACS] = {0}; #endif /* DEBUG */ +static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, + SK_MAC_ADDR *pMc, int Flags); +static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, + int Flags); +static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber); +static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC, + SK_U32 PortNumber, int NewPromMode); +static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, + SK_MAC_ADDR *pMc, int Flags); +static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, + int Flags); +static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber); +static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC, + SK_U32 PortNumber, int NewPromMode); + /* functions ******************************************************************/ /****************************************************************************** @@ -372,7 +387,7 @@ int Flags) /* permanent/non-perm, sw-only */ * SK_ADDR_SUCCESS * SK_ADDR_ILLEGAL_PORT */ -int SkAddrXmacMcClear( +static int SkAddrXmacMcClear( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber, /* Index of affected port */ @@ -429,7 +444,7 @@ int Flags) /* permanent/non-perm, sw-only */ * SK_ADDR_SUCCESS * SK_ADDR_ILLEGAL_PORT */ -int SkAddrGmacMcClear( +static int SkAddrGmacMcClear( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber, /* Index of affected port */ @@ -519,7 +534,7 @@ int Flags) /* permanent/non-perm, sw-only */ * Returns: * Hash value of multicast address. */ -SK_U32 SkXmacMcHash( +static SK_U32 SkXmacMcHash( unsigned char *pMc) /* Multicast address */ { SK_U32 Idx; @@ -557,7 +572,7 @@ unsigned char *pMc) /* Multicast address */ * Returns: * Hash value of multicast address. */ -SK_U32 SkGmacMcHash( +static SK_U32 SkGmacMcHash( unsigned char *pMc) /* Multicast address */ { SK_U32 Data; @@ -672,7 +687,7 @@ int Flags) /* permanent/non-permanent */ * SK_MC_ILLEGAL_ADDRESS * SK_MC_RLMT_OVERFLOW */ -int SkAddrXmacMcAdd( +static int SkAddrXmacMcAdd( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber, /* Port Number */ @@ -778,7 +793,7 @@ int Flags) /* permanent/non-permanent */ * SK_MC_FILTERING_INEXACT * SK_MC_ILLEGAL_ADDRESS */ -int SkAddrGmacMcAdd( +static int SkAddrGmacMcAdd( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber, /* Port Number */ @@ -937,7 +952,7 @@ SK_U32 PortNumber) /* Port Number */ * SK_MC_FILTERING_INEXACT * SK_ADDR_ILLEGAL_PORT */ -int SkAddrXmacMcUpdate( +static int SkAddrXmacMcUpdate( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber) /* Port Number */ @@ -1082,7 +1097,7 @@ SK_U32 PortNumber) /* Port Number */ * SK_MC_FILTERING_INEXACT * SK_ADDR_ILLEGAL_PORT */ -int SkAddrGmacMcUpdate( +static int SkAddrGmacMcUpdate( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber) /* Port Number */ @@ -1468,7 +1483,7 @@ int NewPromMode) /* new promiscuous mode */ * SK_ADDR_SUCCESS * SK_ADDR_ILLEGAL_PORT */ -int SkAddrXmacPromiscuousChange( +static int SkAddrXmacPromiscuousChange( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber, /* port whose promiscuous mode changes */ @@ -1585,7 +1600,7 @@ int NewPromMode) /* new promiscuous mode */ * SK_ADDR_SUCCESS * SK_ADDR_ILLEGAL_PORT */ -int SkAddrGmacPromiscuousChange( +static int SkAddrGmacPromiscuousChange( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber, /* port whose promiscuous mode changes */ diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c index 6cb49dd02251..67f1d6a5c15d 100644 --- a/drivers/net/sk98lin/skgeinit.c +++ b/drivers/net/sk98lin/skgeinit.c @@ -57,34 +57,6 @@ static struct s_Config OemConfig = { #endif }; -/****************************************************************************** - * - * SkGePollRxD() - Enable / Disable Descriptor Polling of RxD Ring - * - * Description: - * Enable or disable the descriptor polling of the receive descriptor - * ring (RxD) for port 'Port'. - * The new configuration is *not* saved over any SkGeStopPort() and - * SkGeInitPort() calls. - * - * Returns: - * nothing - */ -void SkGePollRxD( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL PollRxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), (PollRxD) ? - CSR_ENA_POL : CSR_DIS_POL); -} /* SkGePollRxD */ - - /****************************************************************************** * * SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings @@ -952,7 +924,7 @@ int Port) /* Port Index (MAC_1 + n) */ * Returns: * nothing */ -void SkGeInitRamIface( +static void SkGeInitRamIface( SK_AC *pAC, /* adapter context */ SK_IOC IoC) /* IO context */ { @@ -1409,83 +1381,6 @@ SK_IOC IoC) /* IO context */ } /* SkGeInit0*/ -#ifdef SK_PCI_RESET - -/****************************************************************************** - * - * SkGePciReset() - Reset PCI interface - * - * Description: - * o Read PCI configuration. - * o Change power state to 3. - * o Change power state to 0. - * o Restore PCI configuration. - * - * Returns: - * 0: Success. - * 1: Power state could not be changed to 3. - */ -static int SkGePciReset( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - int i; - SK_U16 PmCtlSts; - SK_U32 Bp1; - SK_U32 Bp2; - SK_U16 PciCmd; - SK_U8 Cls; - SK_U8 Lat; - SK_U8 ConfigSpace[PCI_CFG_SIZE]; - - /* - * Note: Switching to D3 state is like a software reset. - * Switching from D3 to D0 is a hardware reset. - * We have to save and restore the configuration space. - */ - for (i = 0; i < PCI_CFG_SIZE; i++) { - SkPciReadCfgDWord(pAC, i*4, &ConfigSpace[i]); - } - - /* We know the RAM Interface Arbiter is enabled. */ - SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PCI_PM_STATE_D3); - SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts); - - if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D3) { - return(1); - } - - /* Return to D0 state. */ - SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PCI_PM_STATE_D0); - - /* Check for D0 state. */ - SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts); - - if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D0) { - return(1); - } - - /* Check PCI Config Registers. */ - SkPciReadCfgWord(pAC, PCI_COMMAND, &PciCmd); - SkPciReadCfgByte(pAC, PCI_CACHE_LSZ, &Cls); - SkPciReadCfgDWord(pAC, PCI_BASE_1ST, &Bp1); - SkPciReadCfgDWord(pAC, PCI_BASE_2ND, &Bp2); - SkPciReadCfgByte(pAC, PCI_LAT_TIM, &Lat); - - if (PciCmd != 0 || Cls != (SK_U8)0 || Lat != (SK_U8)0 || - (Bp1 & 0xfffffff0L) != 0 || Bp2 != 1) { - return(1); - } - - /* Restore PCI Config Space. */ - for (i = 0; i < PCI_CFG_SIZE; i++) { - SkPciWriteCfgDWord(pAC, i*4, ConfigSpace[i]); - } - - return(0); -} /* SkGePciReset */ - -#endif /* SK_PCI_RESET */ /****************************************************************************** * @@ -1524,10 +1419,6 @@ SK_IOC IoC) /* IO context */ /* save CLK_RUN bits (YUKON-Lite) */ SK_IN16(IoC, B0_CTST, &CtrlStat); -#ifdef SK_PCI_RESET - (void)SkGePciReset(pAC, IoC); -#endif /* SK_PCI_RESET */ - /* do the SW-reset */ SK_OUT8(IoC, B0_CTST, CS_RST_SET); @@ -1991,11 +1882,6 @@ SK_IOC IoC) /* IO context */ int i; SK_U16 Word; -#ifdef SK_PHY_LP_MODE - SK_U8 Byte; - SK_U16 PmCtlSts; -#endif /* SK_PHY_LP_MODE */ - #if (!defined(SK_SLIM) && !defined(VCPU)) /* ensure I2C is ready */ SkI2cWaitIrq(pAC, IoC); @@ -2010,38 +1896,6 @@ SK_IOC IoC) /* IO context */ } } -#ifdef SK_PHY_LP_MODE - /* - * for power saving purposes within mobile environments - * we set the PHY to coma mode and switch to D3 power state. - */ - if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { - - /* for all ports switch PHY to coma mode */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - - SkGmEnterLowPowerMode(pAC, IoC, i, PHY_PM_DEEP_SLEEP); - } - - if (pAC->GIni.GIVauxAvail) { - /* switch power to VAUX */ - Byte = PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF; - - SK_OUT8(IoC, B0_POWER_CTRL, Byte); - } - - /* switch to D3 state */ - SK_IN16(IoC, PCI_C(PCI_PM_CTL_STS), &PmCtlSts); - - PmCtlSts |= PCI_PM_STATE_D3; - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - - SK_OUT16(IoC, PCI_C(PCI_PM_CTL_STS), PmCtlSts); - } -#endif /* SK_PHY_LP_MODE */ - /* Reset all bits in the PCI STATUS register */ /* * Note: PCI Cfg cycles cannot be used, because they are not diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c index 2991bc85cf2c..0a6f67a7a395 100644 --- a/drivers/net/sk98lin/skgemib.c +++ b/drivers/net/sk98lin/skgemib.c @@ -871,13 +871,6 @@ PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = { sizeof(SK_PNMI_CONF), SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType), SK_PNMI_RO, MacPrivateConf, 0}, -#ifdef SK_PHY_LP_MODE - {OID_SKGE_PHY_LP_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyMode), - SK_PNMI_RW, MacPrivateConf, 0}, -#endif {OID_SKGE_LINK_CAP, SK_PNMI_MAC_ENTRIES, sizeof(SK_PNMI_CONF), diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c index a386172107e8..b36dd9ac6b29 100644 --- a/drivers/net/sk98lin/skgepnmi.c +++ b/drivers/net/sk98lin/skgepnmi.c @@ -56,10 +56,6 @@ static const char SysKonnectFileId[] = * Public Function prototypes */ int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level); -int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, @@ -587,7 +583,7 @@ int Level) /* Initialization level */ * exist (e.g. port instance 3 on a two port * adapter. */ -int SkPnmiGetVar( +static int SkPnmiGetVar( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 Id, /* Object ID that is to be processed */ @@ -629,7 +625,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ * exist (e.g. port instance 3 on a two port * adapter. */ -int SkPnmiPreSetVar( +static int SkPnmiPreSetVar( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 Id, /* Object ID that is to be processed */ @@ -5062,9 +5058,6 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ case OID_SKGE_SPEED_CAP: case OID_SKGE_SPEED_MODE: case OID_SKGE_SPEED_STATUS: -#ifdef SK_PHY_LP_MODE - case OID_SKGE_PHY_LP_MODE: -#endif if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) { *pLen = (Limit - LogPortIndex) * sizeof(SK_U8); @@ -5140,28 +5133,6 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ Offset += sizeof(SK_U32); break; -#ifdef SK_PHY_LP_MODE - case OID_SKGE_PHY_LP_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - continue; - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); - Val8 = (SK_U8) pAC->GIni.GP[PhysPortIndex].PPhyPowerState; - *pBufPtr = Val8; - } - } - else { /* DualNetMode */ - - Val8 = (SK_U8) pAC->GIni.GP[PhysPortIndex].PPhyPowerState; - *pBufPtr = Val8; - } - Offset += sizeof(SK_U8); - break; -#endif - case OID_SKGE_LINK_CAP: if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ if (LogPortIndex == 0) { @@ -5478,16 +5449,6 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ } break; -#ifdef SK_PHY_LP_MODE - case OID_SKGE_PHY_LP_MODE: - if (*pLen < Limit - LogPortIndex) { - - *pLen = Limit - LogPortIndex; - return (SK_PNMI_ERR_TOO_SHORT); - } - break; -#endif - case OID_SKGE_MTU: if (*pLen < sizeof(SK_U32)) { @@ -5845,116 +5806,6 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ Offset += sizeof(SK_U32); break; -#ifdef SK_PHY_LP_MODE - case OID_SKGE_PHY_LP_MODE: - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - Offset = 0; - continue; - } - else { - /* Set value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); - - switch (*(pBuf + Offset)) { - case 0: - /* If LowPowerMode is active, we can leave it. */ - if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState) { - - Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex); - - if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState < 3) { - - SkDrvInitAdapter(pAC); - } - break; - } - else { - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - case 1: - case 2: - case 3: - case 4: - /* If no LowPowerMode is active, we can enter it. */ - if (!pAC->GIni.GP[PhysPortIndex].PPhyPowerState) { - - if ((*(pBuf + Offset)) < 3) { - - SkDrvDeInitAdapter(pAC); - } - - Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf); - break; - } - else { - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - default: - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - } - } - else { /* DualNetMode */ - - switch (*(pBuf + Offset)) { - case 0: - /* If we are in a LowPowerMode, we can leave it. */ - if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState) { - - Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex); - - if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState < 3) { - - SkDrvInitAdapter(pAC); - } - break; - } - else { - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - case 1: - case 2: - case 3: - case 4: - /* If we are not already in LowPowerMode, we can enter it. */ - if (!pAC->GIni.GP[PhysPortIndex].PPhyPowerState) { - - if ((*(pBuf + Offset)) < 3) { - - SkDrvDeInitAdapter(pAC); - } - else { - - Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf); - } - break; - } - else { - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - default: - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - } - Offset += sizeof(SK_U8); - break; -#endif - default: SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, ("MacPrivateConf: Unknown OID should be handled before set")); diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c index 87520f0057d7..ab66d80a4455 100644 --- a/drivers/net/sk98lin/skgesirq.c +++ b/drivers/net/sk98lin/skgesirq.c @@ -265,7 +265,7 @@ int Port) /* Port Index (MAC_1 + n) */ * * Returns: N/A */ -void SkHWLinkUp( +static void SkHWLinkUp( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* IO context */ int Port) /* Port Index (MAC_1 + n) */ @@ -612,14 +612,6 @@ SK_U32 Istatus) /* Interrupt status word */ * we ignore those */ pPrt->HalfDupTimerActive = SK_TRUE; -#ifdef XXX - Len = sizeof(SK_U64); - SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, - &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 0), - pAC->Rlmt.Port[0].Net->NetNumber); - - pPrt->LastOctets = Octets; -#endif /* XXX */ /* Snap statistic counters */ (void)SkXmUpdateStats(pAC, IoC, 0); @@ -653,14 +645,6 @@ SK_U32 Istatus) /* Interrupt status word */ pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && !pPrt->HalfDupTimerActive) { pPrt->HalfDupTimerActive = SK_TRUE; -#ifdef XXX - Len = sizeof(SK_U64); - SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, - &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 1), - pAC->Rlmt.Port[1].Net->NetNumber); - - pPrt->LastOctets = Octets; -#endif /* XXX */ /* Snap statistic counters */ (void)SkXmUpdateStats(pAC, IoC, 1); @@ -2085,12 +2069,6 @@ SK_EVPARA Para) /* Event specific Parameter */ pPrt->HalfDupTimerActive = SK_FALSE; if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) { -#ifdef XXX - Len = sizeof(SK_U64); - SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, - &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port), - pAC->Rlmt.Port[Port].Net->NetNumber); -#endif /* XXX */ /* Snap statistic counters */ (void)SkXmUpdateStats(pAC, IoC, Port); diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c index 075a0464e56b..79bf57cb5326 100644 --- a/drivers/net/sk98lin/ski2c.c +++ b/drivers/net/sk98lin/ski2c.c @@ -396,7 +396,7 @@ int Rw) /* Read / Write Flag */ * 1: error, transfer does not complete, I2C transfer * killed, wait loop terminated. */ -int SkI2cWait( +static int SkI2cWait( SK_AC *pAC, /* Adapter Context */ SK_IOC IoC, /* I/O Context */ int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */ @@ -481,7 +481,7 @@ SK_IOC IoC) /* I/O Context */ * returns 0: success * 1: error */ -int SkI2cWrite( +static int SkI2cWrite( SK_AC *pAC, /* Adapter Context */ SK_IOC IoC, /* I/O Context */ SK_U32 I2cData, /* I2C Data to write */ @@ -538,7 +538,7 @@ int I2cBurst) /* I2C Burst Flag */ * 1 if the read is completed * 0 if the read must be continued (I2C Bus still allocated) */ -int SkI2cReadSensor( +static int SkI2cReadSensor( SK_AC *pAC, /* Adapter Context */ SK_IOC IoC, /* I/O Context */ SK_SENSOR *pSen) /* Sensor to be read */ diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c index 68292d18175b..a204f5bb55d4 100644 --- a/drivers/net/sk98lin/sklm80.c +++ b/drivers/net/sk98lin/sklm80.c @@ -34,79 +34,7 @@ static const char SysKonnectFileId[] = #include "h/lm80.h" #include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ -#ifdef SK_DIAG -#define BREAK_OR_WAIT(pAC,IoC,Event) SkI2cWait(pAC,IoC,Event) -#else /* nSK_DIAG */ #define BREAK_OR_WAIT(pAC,IoC,Event) break -#endif /* nSK_DIAG */ - -#ifdef SK_DIAG -/* - * read the register 'Reg' from the device 'Dev' - * - * return read error -1 - * success the read value - */ -int SkLm80RcvReg( -SK_IOC IoC, /* Adapter Context */ -int Dev, /* I2C device address */ -int Reg) /* register to read */ -{ - int Val = 0; - int TempExt; - - /* Signal device number */ - if (SkI2cSndDev(IoC, Dev, I2C_WRITE)) { - return(-1); - } - - if (SkI2cSndByte(IoC, Reg)) { - return(-1); - } - - /* repeat start */ - if (SkI2cSndDev(IoC, Dev, I2C_READ)) { - return(-1); - } - - switch (Reg) { - case LM80_TEMP_IN: - Val = (int)SkI2cRcvByte(IoC, 1); - - /* First: correct the value: it might be negative */ - if ((Val & 0x80) != 0) { - /* Value is negative */ - Val = Val - 256; - } - Val = Val * SK_LM80_TEMP_LSB; - SkI2cStop(IoC); - - TempExt = (int)SkLm80RcvReg(IoC, LM80_ADDR, LM80_TEMP_CTRL); - - if (Val > 0) { - Val += ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB); - } - else { - Val -= ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB); - } - return(Val); - break; - case LM80_VT0_IN: - case LM80_VT1_IN: - case LM80_VT2_IN: - case LM80_VT3_IN: - Val = (int)SkI2cRcvByte(IoC, 1) * SK_LM80_VT_LSB; - break; - - default: - Val = (int)SkI2cRcvByte(IoC, 1); - break; - } - - SkI2cStop(IoC); - return(Val); -} -#endif /* SK_DIAG */ /* * read a sensors value (LM80 specific) diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c index 9ea11ab2296a..be8d1ccddf6d 100644 --- a/drivers/net/sk98lin/skrlmt.c +++ b/drivers/net/sk98lin/skrlmt.c @@ -282,7 +282,6 @@ typedef struct s_SpTreeRlmtPacket { SK_MAC_ADDR SkRlmtMcAddr = {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}}; SK_MAC_ADDR BridgeMcAddr = {{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00}}; -SK_MAC_ADDR BcAddr = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; /* local variables ************************************************************/ diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c index eb3c8988ced1..17786056c66a 100644 --- a/drivers/net/sk98lin/skvpd.c +++ b/drivers/net/sk98lin/skvpd.c @@ -132,65 +132,6 @@ int addr) /* VPD address */ #endif /* SKDIAG */ -#if 0 - -/* - Write the dword 'data' at address 'addr' into the VPD EEPROM, and - verify that the data is written. - - Needed Time: - -. MIN MAX -. ------------------------------------------------------------------- -. write 1.8 ms 3.6 ms -. internal write cyles 0.7 ms 7.0 ms -. ------------------------------------------------------------------- -. over all program time 2.5 ms 10.6 ms -. read 1.3 ms 2.6 ms -. ------------------------------------------------------------------- -. over all 3.8 ms 13.2 ms -. - - - Returns 0: success - 1: error, I2C transfer does not terminate - 2: error, data verify error - - */ -static int VpdWriteDWord( -SK_AC *pAC, /* pAC pointer */ -SK_IOC IoC, /* IO Context */ -int addr, /* VPD address */ -SK_U32 data) /* VPD data to write */ -{ - /* start VPD write */ - /* Don't swap here, it's a data stream of bytes */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD write dword at addr 0x%x, data = 0x%x\n",addr,data)); - VPD_OUT32(pAC, IoC, PCI_VPD_DAT_REG, (SK_U32)data); - /* But do it here */ - addr |= VPD_WRITE; - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)(addr | VPD_WRITE)); - - /* this may take up to 10,6 ms */ - if (VpdWait(pAC, IoC, VPD_WRITE)) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Write Timed Out\n")); - return(1); - }; - - /* verify data */ - if (VpdReadDWord(pAC, IoC, addr) != data) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Data Verify Error\n")); - return(2); - } - return(0); -} /* VpdWriteDWord */ - -#endif /* 0 */ - /* * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from * or to the I2C EEPROM. @@ -728,7 +669,7 @@ char *etp) /* end pointer input position */ * 6: fatal VPD error * */ -int VpdSetupPara( +static int VpdSetupPara( SK_AC *pAC, /* common data base */ const char *key, /* keyword to insert */ const char *buf, /* buffer with the keyword value */ @@ -1148,50 +1089,3 @@ SK_IOC IoC) /* IO Context */ return(0); } - - -/* - * Read the contents of the VPD EEPROM and copy it to the VPD buffer - * if not already done. If the keyword "VF" is not present it will be - * created and the error log message will be stored to this keyword. - * If "VF" is not present the error log message will be stored to the - * keyword "VL". "VL" will created or overwritten if "VF" is present. - * The VPD read/write area is saved to the VPD EEPROM. - * - * returns nothing, errors will be ignored. - */ -void VpdErrLog( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -char *msg) /* error log message */ -{ - SK_VPD_PARA *v, vf; /* VF */ - int len; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, - ("VPD error log msg %s\n", msg)); - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD init error\n")); - return; - } - } - - len = strlen(msg); - if (len > VPD_MAX_LEN) { - /* cut it */ - len = VPD_MAX_LEN; - } - if ((v = vpd_find_para(pAC, VPD_VF, &vf)) != NULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("overwrite VL\n")); - (void)VpdSetupPara(pAC, VPD_VL, msg, len, VPD_RW_KEY, OWR_KEY); - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("write VF\n")); - (void)VpdSetupPara(pAC, VPD_VF, msg, len, VPD_RW_KEY, ADD_KEY); - } - - (void)VpdUpdate(pAC, IoC); -} - diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c index 42d2d963150a..b4e75022a657 100644 --- a/drivers/net/sk98lin/skxmac2.c +++ b/drivers/net/sk98lin/skxmac2.c @@ -41,13 +41,13 @@ static const char SysKonnectFileId[] = #endif #ifdef GENESIS -BCOM_HACK BcomRegA1Hack[] = { +static BCOM_HACK BcomRegA1Hack[] = { { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 }, { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 }, { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 }, { 0, 0 } }; -BCOM_HACK BcomRegC0Hack[] = { +static BCOM_HACK BcomRegC0Hack[] = { { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 }, { 0, 0 } @@ -790,7 +790,7 @@ int Port) /* Port Index (MAC_1 + n) */ * Returns: * nothing */ -void SkMacFlushRxFifo( +static void SkMacFlushRxFifo( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* IO context */ int Port) /* Port Index (MAC_1 + n) */ @@ -1231,38 +1231,6 @@ int Port) /* Port Index (MAC_1 + n) */ } /* SkMacHardRst */ -/****************************************************************************** - * - * SkMacClearRst() - Clear the MAC reset - * - * Description: calls a clear MAC reset routine dep. on board type - * - * Returns: - * nothing - */ -void SkMacClearRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - SkXmClearRst(pAC, IoC, Port); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - SkGmClearRst(pAC, IoC, Port); - } -#endif /* YUKON */ - -} /* SkMacClearRst */ - - #ifdef GENESIS /****************************************************************************** * @@ -1713,7 +1681,7 @@ int Port) /* Port Index (MAC_1 + n) */ * Returns: * nothing */ -void SkXmInitDupMd( +static void SkXmInitDupMd( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* IO context */ int Port) /* Port Index (MAC_1 + n) */ @@ -1761,7 +1729,7 @@ int Port) /* Port Index (MAC_1 + n) */ * Returns: * nothing */ -void SkXmInitPauseMd( +static void SkXmInitPauseMd( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* IO context */ int Port) /* Port Index (MAC_1 + n) */ @@ -2076,283 +2044,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ } /* SkXmInitPhyBcom */ #endif /* GENESIS */ - #ifdef YUKON -#ifndef SK_SLIM -/****************************************************************************** - * - * SkGmEnterLowPowerMode() - * - * Description: - * This function sets the Marvell Alaska PHY to the low power mode - * given by parameter mode. - * The following low power modes are available: - * - * - Coma Mode (Deep Sleep): - * Power consumption: ~15 - 30 mW - * The PHY cannot wake up on its own. - * - * - IEEE 22.2.4.1.5 compatible power down mode - * Power consumption: ~240 mW - * The PHY cannot wake up on its own. - * - * - energy detect mode - * Power consumption: ~160 mW - * The PHY can wake up on its own by detecting activity - * on the CAT 5 cable. - * - * - energy detect plus mode - * Power consumption: ~150 mW - * The PHY can wake up on its own by detecting activity - * on the CAT 5 cable. - * Connected devices can be woken up by sending normal link - * pulses every one second. - * - * Note: - * - * Returns: - * 0: ok - * 1: error - */ -int SkGmEnterLowPowerMode( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (e.g. MAC_1) */ -SK_U8 Mode) /* low power mode */ -{ - SK_U16 Word; - SK_U32 DWord; - SK_U8 LastMode; - int Ret = 0; - - if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { - - /* save current power mode */ - LastMode = pAC->GIni.GP[Port].PPhyPowerState; - pAC->GIni.GP[Port].PPhyPowerState = Mode; - - switch (Mode) { - /* coma mode (deep sleep) */ - case PHY_PM_DEEP_SLEEP: - /* setup General Purpose Control Register */ - GM_OUT16(IoC, 0, GM_GP_CTRL, GM_GPCR_FL_PASS | - GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS); - - /* apply COMA mode workaround */ - SkGmPhyWrite(pAC, IoC, Port, 29, 0x001f); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xfff3); - - SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - - /* Set PHY to Coma Mode */ - SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord | PCI_PHY_COMA); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - break; - - /* IEEE 22.2.4.1.5 compatible power down mode */ - case PHY_PM_IEEE_POWER_DOWN: - /* - * - disable MAC 125 MHz clock - * - allow MAC power down - */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); - Word |= PHY_M_PC_DIS_125CLK; - Word &= ~PHY_M_PC_MAC_POW_UP; - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); - - /* - * register changes must be followed by a software - * reset to take effect - */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); - Word |= PHY_CT_RESET; - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); - - /* switch IEEE compatible power down mode on */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); - Word |= PHY_CT_PDOWN; - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); - break; - - /* energy detect and energy detect plus mode */ - case PHY_PM_ENERGY_DETECT: - case PHY_PM_ENERGY_DETECT_PLUS: - /* - * - disable MAC 125 MHz clock - */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); - Word |= PHY_M_PC_DIS_125CLK; - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); - - /* activate energy detect mode 1 */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); - - /* energy detect mode */ - if (Mode == PHY_PM_ENERGY_DETECT) { - Word |= PHY_M_PC_EN_DET; - } - /* energy detect plus mode */ - else { - Word |= PHY_M_PC_EN_DET_PLUS; - } - - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); - - /* - * reinitialize the PHY to force a software reset - * which is necessary after the register settings - * for the energy detect modes. - * Furthermore reinitialisation prevents that the - * PHY is running out of a stable state. - */ - SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE); - break; - - /* don't change current power mode */ - default: - pAC->GIni.GP[Port].PPhyPowerState = LastMode; - Ret = 1; - break; - } - } - /* low power modes are not supported by this chip */ - else { - Ret = 1; - } - - return(Ret); - -} /* SkGmEnterLowPowerMode */ - -/****************************************************************************** - * - * SkGmLeaveLowPowerMode() - * - * Description: - * Leave the current low power mode and switch to normal mode - * - * Note: - * - * Returns: - * 0: ok - * 1: error - */ -int SkGmLeaveLowPowerMode( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (e.g. MAC_1) */ -{ - SK_U32 DWord; - SK_U16 Word; - SK_U8 LastMode; - int Ret = 0; - - if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { - - /* save current power mode */ - LastMode = pAC->GIni.GP[Port].PPhyPowerState; - pAC->GIni.GP[Port].PPhyPowerState = PHY_PM_OPERATIONAL_MODE; - - switch (LastMode) { - /* coma mode (deep sleep) */ - case PHY_PM_DEEP_SLEEP: - SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - - /* Release PHY from Coma Mode */ - SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord & ~PCI_PHY_COMA); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - SK_IN32(IoC, B2_GP_IO, &DWord); - - /* set to output */ - DWord |= (GP_DIR_9 | GP_IO_9); - - /* set PHY reset */ - SK_OUT32(IoC, B2_GP_IO, DWord); - - DWord &= ~GP_IO_9; /* clear PHY reset (active high) */ - - /* clear PHY reset */ - SK_OUT32(IoC, B2_GP_IO, DWord); - break; - - /* IEEE 22.2.4.1.5 compatible power down mode */ - case PHY_PM_IEEE_POWER_DOWN: - /* - * - enable MAC 125 MHz clock - * - set MAC power up - */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); - Word &= ~PHY_M_PC_DIS_125CLK; - Word |= PHY_M_PC_MAC_POW_UP; - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); - - /* - * register changes must be followed by a software - * reset to take effect - */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); - Word |= PHY_CT_RESET; - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); - - /* switch IEEE compatible power down mode off */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); - Word &= ~PHY_CT_PDOWN; - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); - break; - - /* energy detect and energy detect plus mode */ - case PHY_PM_ENERGY_DETECT: - case PHY_PM_ENERGY_DETECT_PLUS: - /* - * - enable MAC 125 MHz clock - */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); - Word &= ~PHY_M_PC_DIS_125CLK; - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); - - /* disable energy detect mode */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); - Word &= ~PHY_M_PC_EN_DET_MSK; - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); - - /* - * reinitialize the PHY to force a software reset - * which is necessary after the register settings - * for the energy detect modes. - * Furthermore reinitialisation prevents that the - * PHY is running out of a stable state. - */ - SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE); - break; - - /* don't change current power mode */ - default: - pAC->GIni.GP[Port].PPhyPowerState = LastMode; - Ret = 1; - break; - } - } - /* low power modes are not supported by this chip */ - else { - Ret = 1; - } - - return(Ret); - -} /* SkGmLeaveLowPowerMode */ -#endif /* !SK_SLIM */ - - /****************************************************************************** * * SkGmInitPhyMarv() - Initialize the Marvell Phy registers @@ -3420,145 +3112,6 @@ int Port) /* Port Index (MAC_1 + n) */ } /* SkMacAutoNegDone */ -#ifdef GENESIS -/****************************************************************************** - * - * SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC - * - * Description: - * sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg. - * enables Rx/Tx - * - * Returns: N/A - */ -static void SkXmSetRxTxEn( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */ -{ - SK_U16 Word; - - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - - switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) { - case SK_MAC_LOOPB_ON: - Word |= XM_MMU_MAC_LB; - break; - case SK_MAC_LOOPB_OFF: - Word &= ~XM_MMU_MAC_LB; - break; - } - - switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) { - case SK_PHY_LOOPB_ON: - Word |= XM_MMU_GMII_LOOP; - break; - case SK_PHY_LOOPB_OFF: - Word &= ~XM_MMU_GMII_LOOP; - break; - } - - switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) { - case SK_PHY_FULLD_ON: - Word |= XM_MMU_GMII_FD; - break; - case SK_PHY_FULLD_OFF: - Word &= ~XM_MMU_GMII_FD; - break; - } - - XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX); - - /* dummy read to ensure writing */ - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - -} /* SkXmSetRxTxEn */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC - * - * Description: - * sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg. - * enables Rx/Tx - * - * Returns: N/A - */ -static void SkGmSetRxTxEn( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Para) /* Parameter to set: MAC LoopBack, Duplex Mode */ -{ - SK_U16 Ctrl; - - GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl); - - switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) { - case SK_MAC_LOOPB_ON: - Ctrl |= GM_GPCR_LOOP_ENA; - break; - case SK_MAC_LOOPB_OFF: - Ctrl &= ~GM_GPCR_LOOP_ENA; - break; - } - - switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) { - case SK_PHY_FULLD_ON: - Ctrl |= GM_GPCR_DUP_FULL; - break; - case SK_PHY_FULLD_OFF: - Ctrl &= ~GM_GPCR_DUP_FULL; - break; - } - - GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Ctrl | GM_GPCR_RX_ENA | - GM_GPCR_TX_ENA)); - - /* dummy read to ensure writing */ - GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl); - -} /* SkGmSetRxTxEn */ -#endif /* YUKON */ - - -#ifndef SK_SLIM -/****************************************************************************** - * - * SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters - * - * Description: calls the Special Set Rx/Tx Enable routines dep. on board type - * - * Returns: N/A - */ -void SkMacSetRxTxEn( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Para) -{ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - SkXmSetRxTxEn(pAC, IoC, Port, Para); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - SkGmSetRxTxEn(pAC, IoC, Port, Para); - } -#endif /* YUKON */ - -} /* SkMacSetRxTxEn */ -#endif /* !SK_SLIM */ - - /****************************************************************************** * * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up @@ -3976,7 +3529,7 @@ SK_U16 PhyStat) /* PHY Status word to analyse */ * Returns: * nothing */ -void SkXmIrq( +static void SkXmIrq( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* IO context */ int Port) /* Port Index (MAC_1 + n) */ @@ -4112,7 +3665,7 @@ int Port) /* Port Index (MAC_1 + n) */ * Returns: * nothing */ -void SkGmIrq( +static void SkGmIrq( SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* IO context */ int Port) /* Port Index (MAC_1 + n) */ -- cgit v1.2.3-59-g8ed1b From ff5688ae1cedfb175b5ed0f319d03ad2e5ee005d Mon Sep 17 00:00:00 2001 From: Marcelo Feitoza Parisi Date: Mon, 9 Jan 2006 18:37:15 -0800 Subject: [PATCH] drivers/net/*: use time_after() and friends They deal with wrapping correctly and are nicer to read. Also make jiffies-holding variables unsigned long. Signed-off-by: Marcelo Feitoza Parisi Signed-off-by: Alexey Dobriyan Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/3c523.c | 9 +++++---- drivers/net/3c59x.c | 3 ++- drivers/net/apne.c | 7 ++++--- drivers/net/arcnet/arcnet.c | 3 ++- drivers/net/arm/etherh.c | 3 ++- drivers/net/eth16i.c | 11 ++++++----- drivers/net/hamradio/baycom_epp.c | 2 +- drivers/net/hp100.c | 5 +++-- drivers/net/ne-h8300.c | 5 +++-- drivers/net/ne.c | 7 ++++--- drivers/net/ne2.c | 7 ++++--- drivers/net/ns83820.c | 5 +++-- drivers/net/oaknet.c | 3 ++- drivers/net/pcmcia/3c589_cs.c | 3 ++- drivers/net/ppp_async.c | 3 ++- drivers/net/seeq8005.c | 5 +++-- drivers/net/shaper.c | 3 ++- drivers/net/tokenring/lanstreamer.c | 3 ++- drivers/net/tokenring/olympic.c | 9 +++++---- drivers/net/tulip/pnic.c | 3 ++- drivers/net/wireless/strip.c | 4 ++-- drivers/net/zorro8390.c | 7 ++++--- 22 files changed, 65 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 9e1fe2e0478c..b40885d41680 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -105,6 +105,7 @@ #include #include #include +#include #include #include @@ -658,7 +659,7 @@ static int init586(struct net_device *dev) s = jiffies; /* warning: only active with interrupts on !! */ while (!(cfg_cmd->cmd_status & STAT_COMPL)) { - if (jiffies - s > 30*HZ/100) + if (time_after(jiffies, s + 30*HZ/100)) break; } @@ -684,7 +685,7 @@ static int init586(struct net_device *dev) s = jiffies; while (!(ias_cmd->cmd_status & STAT_COMPL)) { - if (jiffies - s > 30*HZ/100) + if (time_after(jiffies, s + 30*HZ/100)) break; } @@ -709,7 +710,7 @@ static int init586(struct net_device *dev) s = jiffies; while (!(tdr_cmd->cmd_status & STAT_COMPL)) { - if (jiffies - s > 30*HZ/100) { + if (time_after(jiffies, s + 30*HZ/100)) { printk(KERN_WARNING "%s: %d Problems while running the TDR.\n", dev->name, __LINE__); result = 1; break; @@ -798,7 +799,7 @@ static int init586(struct net_device *dev) elmc_id_attn586(); s = jiffies; while (!(mc_cmd->cmd_status & STAT_COMPL)) { - if (jiffies - s > 30*HZ/100) + if (time_after(jiffies, s + 30*HZ/100)) break; } if (!(mc_cmd->cmd_status & STAT_COMPL)) { diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 7488ee7f7caf..3dde1df33487 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -258,6 +258,7 @@ static int vortex_debug = 1; #include #include #include +#include #include /* For NR_IRQS only. */ #include #include @@ -2717,7 +2718,7 @@ boomerang_rx(struct net_device *dev) skb = dev_alloc_skb(PKT_BUF_SZ); if (skb == NULL) { static unsigned long last_jif; - if ((jiffies - last_jif) > 10 * HZ) { + if (time_after(jiffies, last_jif + 10 * HZ)) { printk(KERN_WARNING "%s: memory shortage\n", dev->name); last_jif = jiffies; } diff --git a/drivers/net/apne.c b/drivers/net/apne.c index a94216b87184..b9820b86cdcc 100644 --- a/drivers/net/apne.c +++ b/drivers/net/apne.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -216,7 +217,7 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr) outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET); while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { + if (time_after(jiffies, reset_start_time + 2*HZ/100)) { printk(" not found (no reset ack).\n"); return -ENODEV; } @@ -382,7 +383,7 @@ apne_reset_8390(struct net_device *dev) /* This check _should_not_ be necessary, omit eventually. */ while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { + if (time_after(jiffies, reset_start_time + 2*HZ/100)) { printk("%s: ne_reset_8390() did not complete.\n", dev->name); break; } @@ -530,7 +531,7 @@ apne_block_output(struct net_device *dev, int count, dma_start = jiffies; while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ + if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ printk("%s: timeout waiting for Tx RDC.\n", dev->name); apne_reset_8390(dev); NS8390_init(dev,1); diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 12ef52c193a3..409d61d8d083 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -52,6 +52,7 @@ #include #include #include +#include /* "do nothing" functions for protocol drivers */ static void null_rx(struct net_device *dev, int bufnum, @@ -733,7 +734,7 @@ static void arcnet_timeout(struct net_device *dev) spin_unlock_irqrestore(&lp->lock, flags); - if (jiffies - lp->last_timeout > 10*HZ) { + if (time_after(jiffies, lp->last_timeout + 10*HZ)) { BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n", msg, status, lp->intmask, lp->lasttrans_dest); lp->last_timeout = jiffies; diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 6a93b666eb72..d52deb8d2075 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -355,7 +356,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf dma_start = jiffies; while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ + if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ printk(KERN_ERR "%s: timeout waiting for TX RDC\n", dev->name); etherh_reset (dev); diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c index f32a6b3acb2a..b67545be2caa 100644 --- a/drivers/net/eth16i.c +++ b/drivers/net/eth16i.c @@ -161,6 +161,7 @@ static char *version = #include #include #include +#include #include #include @@ -754,7 +755,7 @@ static void eth16i_set_port(int ioaddr, int porttype) static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l) { - int starttime; + unsigned long starttime; outb(0xff, ioaddr + TX_STATUS_REG); @@ -765,7 +766,7 @@ static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l) outb(TX_START | 1, ioaddr + TRANSMIT_START_REG); while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) { - if( (jiffies - starttime) > TX_TIMEOUT) { + if( time_after(jiffies, starttime + TX_TIMEOUT)) { return -1; } } @@ -775,18 +776,18 @@ static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l) static int eth16i_receive_probe_packet(int ioaddr) { - int starttime; + unsigned long starttime; starttime = jiffies; while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) { - if( (jiffies - starttime) > TX_TIMEOUT) { + if( time_after(jiffies, starttime + TX_TIMEOUT)) { if(eth16i_debug > 1) printk(KERN_DEBUG "Timeout occurred waiting transmit packet received\n"); starttime = jiffies; while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) { - if( (jiffies - starttime) > TX_TIMEOUT) { + if( time_after(jiffies, starttime + TX_TIMEOUT)) { if(eth16i_debug > 1) printk(KERN_DEBUG "Timeout occurred waiting receive packet\n"); return -1; diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index e4188d082f01..9220de9f4fe7 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -905,7 +905,7 @@ static int epp_open(struct net_device *dev) /* autoprobe baud rate */ tstart = jiffies; i = 0; - while ((signed)(jiffies-tstart-HZ/3) < 0) { + while (time_before(jiffies, tstart + HZ/3)) { if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) goto epptimeout; if ((stat & (EPP_NRAEF|EPP_NRHF)) == EPP_NRHF) { diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 55c7ed608391..a37b82ebca37 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -115,6 +115,7 @@ #include #include #include +#include #include @@ -1499,7 +1500,7 @@ static int hp100_start_xmit_bm(struct sk_buff *skb, struct net_device *dev) printk("hp100: %s: start_xmit_bm: No TX PDL available.\n", dev->name); #endif /* not waited long enough since last tx? */ - if (jiffies - dev->trans_start < HZ) + if (time_before(jiffies, dev->trans_start + HZ)) return -EAGAIN; if (hp100_check_lan(dev)) @@ -1652,7 +1653,7 @@ static int hp100_start_xmit(struct sk_buff *skb, struct net_device *dev) printk("hp100: %s: start_xmit: tx free mem = 0x%x\n", dev->name, i); #endif /* not waited long enough since last failed tx try? */ - if (jiffies - dev->trans_start < HZ) { + if (time_before(jiffies, dev->trans_start + HZ)) { #ifdef HP100_DEBUG printk("hp100: %s: trans_start timing problem\n", dev->name); diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c index 8f40368cf2e9..aaebd28a1920 100644 --- a/drivers/net/ne-h8300.c +++ b/drivers/net/ne-h8300.c @@ -27,6 +27,7 @@ static const char version1[] = #include #include #include +#include #include #include @@ -365,7 +366,7 @@ static void ne_reset_8390(struct net_device *dev) /* This check _should_not_ be necessary, omit eventually. */ while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { + if (time_after(jiffies, reset_start_time + 2*HZ/100)) { printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name); break; } @@ -580,7 +581,7 @@ retry: #endif while ((inb_p(NE_BASE + EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ + if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); ne_reset_8390(dev); NS8390_init(dev,1); diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 94f782d51f0f..08b218c5bfbc 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -50,6 +50,7 @@ static const char version2[] = #include #include #include +#include #include #include @@ -341,7 +342,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET); while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { + if (time_after(jiffies, reset_start_time + 2*HZ/100)) { if (bad_card) { printk(" (warning: no reset ack)"); break; @@ -580,7 +581,7 @@ static void ne_reset_8390(struct net_device *dev) /* This check _should_not_ be necessary, omit eventually. */ while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { + if (time_after(jiffies, reset_start_time + 2*HZ/100)) { printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name); break; } @@ -787,7 +788,7 @@ retry: #endif while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ + if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); ne_reset_8390(dev); NS8390_init(dev,1); diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c index e6df375a1d4b..2aa7b77f84f8 100644 --- a/drivers/net/ne2.c +++ b/drivers/net/ne2.c @@ -75,6 +75,7 @@ static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon #include #include +#include #include #include @@ -395,7 +396,7 @@ static int __init ne2_probe1(struct net_device *dev, int slot) outb(inb(base_addr + NE_RESET), base_addr + NE_RESET); while ((inb_p(base_addr + EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { + if (time_after(jiffies, reset_start_time + 2*HZ/100)) { printk(" not found (no reset ack).\n"); retval = -ENODEV; goto out; @@ -548,7 +549,7 @@ static void ne_reset_8390(struct net_device *dev) /* This check _should_not_ be necessary, omit eventually. */ while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { + if (time_after(jiffies, reset_start_time + 2*HZ/100)) { printk("%s: ne_reset_8390() did not complete.\n", dev->name); break; @@ -749,7 +750,7 @@ retry: #endif while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ + if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ printk("%s: timeout waiting for Tx RDC.\n", dev->name); ne_reset_8390(dev); NS8390_init(dev,1); diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index b0c3b6ab6263..253cf018dfba 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -116,6 +116,7 @@ #include #include #include +#include #include #include @@ -1607,7 +1608,7 @@ static void ns83820_run_bist(struct net_device *ndev, const char *name, u32 enab { struct ns83820 *dev = PRIV(ndev); int timed_out = 0; - long start; + unsigned long start; u32 status; int loops = 0; @@ -1625,7 +1626,7 @@ static void ns83820_run_bist(struct net_device *ndev, const char *name, u32 enab break; if (status & fail) break; - if ((jiffies - start) >= HZ) { + if (time_after_eq(jiffies, start + HZ)) { timed_out = 1; break; } diff --git a/drivers/net/oaknet.c b/drivers/net/oaknet.c index 62167a29debe..d0f686d6eaaa 100644 --- a/drivers/net/oaknet.c +++ b/drivers/net/oaknet.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -606,7 +607,7 @@ retry: #endif while ((ei_ibp(base + EN0_ISR) & ENISR_RDC) == 0) { - if (jiffies - start > OAKNET_WAIT) { + if (time_after(jiffies, start + OAKNET_WAIT)) { printk("%s: timeout waiting for Tx RDC.\n", dev->name); oaknet_reset_8390(dev); NS8390_init(dev, TRUE); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 1c3c9c666f74..c4abc9365f8e 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -796,7 +797,7 @@ static void media_check(unsigned long arg) media = inw(ioaddr+WN4_MEDIA) & 0xc810; /* Ignore collisions unless we've had no irq's recently */ - if (jiffies - lp->last_irq < HZ) { + if (time_before(jiffies, lp->last_irq + HZ)) { media &= ~0x0010; } else { /* Try harder to detect carrier errors */ diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index aa6540b39466..23659fd7c3a6 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -570,7 +571,7 @@ ppp_async_encode(struct asyncppp *ap) * character if necessary. */ if (islcp || flag_time == 0 - || jiffies - ap->last_xmit >= flag_time) + || time_after_eq(jiffies, ap->last_xmit + flag_time)) *buf++ = PPP_FLAG; ap->last_xmit = jiffies; fcs = PPP_INITFCS; diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index 79dca398f3ac..bcef03feb2fc 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -46,6 +46,7 @@ static const char version[] = #include #include #include +#include #include #include @@ -699,7 +700,7 @@ static void hardware_send_packet(struct net_device * dev, char *buf, int length) int ioaddr = dev->base_addr; int status = inw(SEEQ_STATUS); int transmit_ptr = 0; - int tmp; + unsigned long tmp; if (net_debug>4) { printk("%s: send 0x%04x\n",dev->name,length); @@ -724,7 +725,7 @@ static void hardware_send_packet(struct net_device * dev, char *buf, int length) /* drain FIFO */ tmp = jiffies; - while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && (jiffies - tmp < HZ)) + while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && time_before(jiffies, tmp + HZ)) mb(); /* doit ! */ diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c index 221354eea21f..88e212043a43 100644 --- a/drivers/net/shaper.c +++ b/drivers/net/shaper.c @@ -83,6 +83,7 @@ #include #include #include +#include #include #include @@ -168,7 +169,7 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev) /* * Queue over time. Spill packet. */ - if(SHAPERCB(skb)->shapeclock-jiffies > SHAPER_LATENCY) { + if(time_after(SHAPERCB(skb)->shapeclock,jiffies + SHAPER_LATENCY)) { dev_kfree_skb(skb); shaper->stats.tx_dropped++; } else diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index 97712c3c4e07..c58a4c31d0dd 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -122,6 +122,7 @@ #include #include #include +#include #include @@ -512,7 +513,7 @@ static int streamer_reset(struct net_device *dev) while (!((readw(streamer_mmio + SISR)) & SISR_SRB_REPLY)) { msleep_interruptible(100); - if (jiffies - t > 40 * HZ) { + if (time_after(jiffies, t + 40 * HZ)) { printk(KERN_ERR "IBM PCI tokenring card not responding\n"); release_region(dev->base_addr, STREAMER_IO_SPACE); diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index 05477d24fd49..23032a7bc0a9 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -100,6 +100,7 @@ #include #include #include +#include #include @@ -307,7 +308,7 @@ static int __devinit olympic_init(struct net_device *dev) t=jiffies; while((readl(olympic_mmio+BCTL)) & BCTL_SOFTRESET) { schedule(); - if(jiffies-t > 40*HZ) { + if(time_after(jiffies, t + 40*HZ)) { printk(KERN_ERR "IBM PCI tokenring card not responding.\n"); return -ENODEV; } @@ -359,7 +360,7 @@ static int __devinit olympic_init(struct net_device *dev) t=jiffies; while (!readl(olympic_mmio+CLKCTL) & CLKCTL_PAUSE) { schedule() ; - if(jiffies-t > 2*HZ) { + if(time_after(jiffies, t + 2*HZ)) { printk(KERN_ERR "IBM Cardbus tokenring adapter not responsing.\n") ; return -ENODEV; } @@ -373,7 +374,7 @@ static int __devinit olympic_init(struct net_device *dev) t=jiffies; while(!((readl(olympic_mmio+SISR_RR)) & SISR_SRB_REPLY)) { schedule(); - if(jiffies-t > 15*HZ) { + if(time_after(jiffies, t + 15*HZ)) { printk(KERN_ERR "IBM PCI tokenring card not responding.\n"); return -ENODEV; } @@ -519,7 +520,7 @@ static int olympic_open(struct net_device *dev) olympic_priv->srb_queued=0; break; } - if ((jiffies-t) > 10*HZ) { + if (time_after(jiffies, t + 10*HZ)) { printk(KERN_WARNING "%s: SRB timed out. \n",dev->name) ; olympic_priv->srb_queued=0; break ; diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c index d9980bde7508..ca7e53246adb 100644 --- a/drivers/net/tulip/pnic.c +++ b/drivers/net/tulip/pnic.c @@ -16,6 +16,7 @@ #include #include +#include #include "tulip.h" @@ -68,7 +69,7 @@ void pnic_lnk_change(struct net_device *dev, int csr5) */ if (tulip_media_cap[dev->if_port] & MediaIsMII) return; - if (! tp->nwayset || jiffies - dev->trans_start > 1*HZ) { + if (! tp->nwayset || time_after(jiffies, dev->trans_start + 1*HZ)) { tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff); iowrite32(tp->csr6, ioaddr + CSR6); iowrite32(0x30, ioaddr + CSR12); diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 18baacfc5a2c..18a44580b53b 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -112,7 +112,7 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE"; #include #include #include - +#include /************************************************************************/ /* Useful structures and definitions */ @@ -1569,7 +1569,7 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev) del_timer(&strip_info->idle_timer); - if (jiffies - strip_info->pps_timer > HZ) { + if (time_after(jiffies, strip_info->pps_timer + HZ)) { unsigned long t = jiffies - strip_info->pps_timer; unsigned long rx_pps_count = (strip_info->rx_pps_count * HZ * 8 + t / 2) / t; unsigned long tx_pps_count = (strip_info->tx_pps_count * HZ * 8 + t / 2) / t; diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index 8ab6e12153ba..761021603597 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -151,7 +152,7 @@ static int __devinit zorro8390_init(struct net_device *dev, z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET); while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { + if (time_after(jiffies, reset_start_time + 2*HZ/100)) { printk(KERN_WARNING " not found (no reset ack).\n"); return -ENODEV; } @@ -273,7 +274,7 @@ static void zorro8390_reset_8390(struct net_device *dev) /* This check _should_not_ be necessary, omit eventually. */ while ((z_readb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { + if (time_after(jiffies, reset_start_time + 2*HZ/100)) { printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name); break; @@ -400,7 +401,7 @@ static void zorro8390_block_output(struct net_device *dev, int count, dma_start = jiffies; while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ + if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ printk(KERN_ERR "%s: timeout waiting for Tx RDC.\n", dev->name); zorro8390_reset_8390(dev); -- cgit v1.2.3-59-g8ed1b From f03aa2d89ad600a1ed21a223f196776f217cfe00 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 14 Jan 2006 03:10:22 +0100 Subject: [PATCH] drivers/net/arcnet/: possible cleanups This patch contains the following possible cleanups: - make needlessly global code static - arcnet.c: remove the unneeded EXPORT_SYMBOL(arc_proto_null) - arcnet.c: remove the unneeded EXPORT_SYMBOL(arcnet_dump_packet) To make Jeff happy, arcnet.c still prints arcnet: v3.93 BETA 2000/04/29 - by Avery Pennarun et al. Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik --- drivers/net/arcnet/arc-rawmode.c | 2 +- drivers/net/arcnet/arcnet.c | 17 ++++++++++------- drivers/net/arcnet/rfc1051.c | 2 +- drivers/net/arcnet/rfc1201.c | 2 +- include/linux/arcdevice.h | 9 --------- 5 files changed, 13 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index e1ea29b0cd14..e7555d4e6ff1 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -42,7 +42,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); -struct ArcProto rawmode_proto = +static struct ArcProto rawmode_proto = { .suffix = 'r', .mtu = XMTU, diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 409d61d8d083..64e2caf3083d 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -62,6 +62,7 @@ static int null_build_header(struct sk_buff *skb, struct net_device *dev, static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); +static void arcnet_rx(struct net_device *dev, int bufnum); /* * one ArcProto per possible proto ID. None of the elements of @@ -72,7 +73,7 @@ static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, struct ArcProto *arc_proto_map[256], *arc_proto_default, *arc_bcast_proto, *arc_raw_proto; -struct ArcProto arc_proto_null = +static struct ArcProto arc_proto_null = { .suffix = '?', .mtu = XMTU, @@ -91,7 +92,6 @@ EXPORT_SYMBOL(arc_proto_map); EXPORT_SYMBOL(arc_proto_default); EXPORT_SYMBOL(arc_bcast_proto); EXPORT_SYMBOL(arc_raw_proto); -EXPORT_SYMBOL(arc_proto_null); EXPORT_SYMBOL(arcnet_unregister_proto); EXPORT_SYMBOL(arcnet_debug); EXPORT_SYMBOL(alloc_arcdev); @@ -119,7 +119,7 @@ static int __init arcnet_init(void) arcnet_debug = debug; - printk(VERSION); + printk("arcnet loaded.\n"); #ifdef ALPHA_WARNING BUGLVL(D_EXTRA) { @@ -179,8 +179,8 @@ EXPORT_SYMBOL(arcnet_dump_skb); * Dump the contents of an ARCnet buffer */ #if (ARCNET_DEBUG_MAX & (D_RX | D_TX)) -void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc, - int take_arcnet_lock) +static void arcnet_dump_packet(struct net_device *dev, int bufnum, + char *desc, int take_arcnet_lock) { struct arcnet_local *lp = dev->priv; int i, length; @@ -209,7 +209,10 @@ void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc, } -EXPORT_SYMBOL(arcnet_dump_packet); +#else + +#define arcnet_dump_packet(dev, bufnum, desc,take_arcnet_lock) do { } while (0) + #endif @@ -997,7 +1000,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) * This is a generic packet receiver that calls arcnet??_rx depending on the * protocol ID found. */ -void arcnet_rx(struct net_device *dev, int bufnum) +static void arcnet_rx(struct net_device *dev, int bufnum) { struct arcnet_local *lp = dev->priv; struct archdr pkt; diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index 6d7913704fb5..6d6c69f036ef 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -43,7 +43,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); -struct ArcProto rfc1051_proto = +static struct ArcProto rfc1051_proto = { .suffix = 's', .mtu = XMTU - RFC1051_HDR_SIZE, diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 6b6ae4bf3d39..bee34226abfa 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -43,7 +43,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); static int continue_tx(struct net_device *dev, int bufnum); -struct ArcProto rfc1201_proto = +static struct ArcProto rfc1201_proto = { .suffix = 'a', .mtu = 1500, /* could be more, but some receivers can't handle it... */ diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index 7198f129e135..231ba090ae34 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -206,7 +206,6 @@ struct ArcProto { extern struct ArcProto *arc_proto_map[256], *arc_proto_default, *arc_bcast_proto, *arc_raw_proto; -extern struct ArcProto arc_proto_null; /* @@ -334,17 +333,9 @@ void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); #define arcnet_dump_skb(dev,skb,desc) ; #endif -#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX) -void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc, - int take_arcnet_lock); -#else -#define arcnet_dump_packet(dev, bufnum, desc,take_arcnet_lock) ; -#endif - void arcnet_unregister_proto(struct ArcProto *proto); irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs); struct net_device *alloc_arcdev(char *name); -void arcnet_rx(struct net_device *dev, int bufnum); #endif /* __KERNEL__ */ #endif /* _LINUX_ARCDEVICE_H */ -- cgit v1.2.3-59-g8ed1b From 26df54bffd90977fbc6fe8284f2beaed19fea44f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 14 Jan 2006 03:09:40 +0100 Subject: [PATCH] drivers/net/s2io.c: make code static This patch makes some needlessly global code static. Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik --- drivers/net/s2io.c | 22 +++++++++++----------- drivers/net/s2io.h | 17 +++++++---------- 2 files changed, 18 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 89c46787676c..41c75616e913 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -72,8 +72,8 @@ static char s2io_driver_name[] = "Neterion"; static char s2io_driver_version[] = DRV_VERSION; -int rxd_size[4] = {32,48,48,64}; -int rxd_count[4] = {127,85,85,63}; +static int rxd_size[4] = {32,48,48,64}; +static int rxd_count[4] = {127,85,85,63}; static inline int RXD_IS_UP2DT(RxD_t *rxdp) { @@ -2127,7 +2127,7 @@ static void stop_nic(struct s2io_nic *nic) } } -int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb) +static int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb) { struct net_device *dev = nic->dev; struct sk_buff *frag_list; @@ -2852,7 +2852,7 @@ static int wait_for_cmd_complete(nic_t * sp) * void. */ -void s2io_reset(nic_t * sp) +static void s2io_reset(nic_t * sp) { XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; @@ -2940,7 +2940,7 @@ void s2io_reset(nic_t * sp) * SUCCESS on success and FAILURE on failure. */ -int s2io_set_swapper(nic_t * sp) +static int s2io_set_swapper(nic_t * sp) { struct net_device *dev = sp->dev; XENA_dev_config_t __iomem *bar0 = sp->bar0; @@ -3089,7 +3089,7 @@ static int wait_for_msix_trans(nic_t *nic, int i) return ret; } -void restore_xmsi_data(nic_t *nic) +static void restore_xmsi_data(nic_t *nic) { XENA_dev_config_t __iomem *bar0 = nic->bar0; u64 val64; @@ -3180,7 +3180,7 @@ int s2io_enable_msi(nic_t *nic) return 0; } -int s2io_enable_msi_x(nic_t *nic) +static int s2io_enable_msi_x(nic_t *nic) { XENA_dev_config_t __iomem *bar0 = nic->bar0; u64 tx_mat, rx_mat; @@ -4128,7 +4128,7 @@ static void s2io_set_multicast(struct net_device *dev) * as defined in errno.h file on failure. */ -int s2io_set_mac_addr(struct net_device *dev, u8 * addr) +static int s2io_set_mac_addr(struct net_device *dev, u8 * addr) { nic_t *sp = dev->priv; XENA_dev_config_t __iomem *bar0 = sp->bar0; @@ -5713,7 +5713,7 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp) * void. */ -void s2io_link(nic_t * sp, int link) +static void s2io_link(nic_t * sp, int link) { struct net_device *dev = (struct net_device *) sp->dev; @@ -5738,7 +5738,7 @@ void s2io_link(nic_t * sp, int link) * returns the revision ID of the device. */ -int get_xena_rev_id(struct pci_dev *pdev) +static int get_xena_rev_id(struct pci_dev *pdev) { u8 id = 0; int ret; @@ -6343,7 +6343,7 @@ int __init s2io_starter(void) * Description: This function is the cleanup routine for the driver. It unregist * ers the driver. */ -void s2io_closer(void) +static void s2io_closer(void) { pci_unregister_driver(&s2io_driver); DBG_PRINT(INIT_DBG, "cleanup done\n"); diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 852a6a899d07..68ae33651947 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -64,7 +64,7 @@ typedef enum xena_max_outstanding_splits { #define INTR_DBG 4 /* Global variable that defines the present debug level of the driver. */ -int debug_level = ERR_DBG; /* Default level. */ +static int debug_level = ERR_DBG; /* DEBUG message print. */ #define DBG_PRINT(dbg_level, args...) if(!(debug_level Date: Tue, 17 Jan 2006 22:52:51 +0100 Subject: [PATCH] starfire: Implement suspend/resume This patch implements suspend and resume methods for the starfire driver. It allows me to put my desktop PC with a starfire dual board into S4. Signed-Off-By: Stefan Rompf Signed-off-by: Jeff Garzik --- drivers/net/starfire.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index d167deda9a53..ed5458c45446 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -2084,6 +2084,38 @@ static int netdev_close(struct net_device *dev) return 0; } +#ifdef CONFIG_PM +static int starfire_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + if (netif_running(dev)) { + netif_device_detach(dev); + netdev_close(dev); + } + + pci_save_state(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev,state)); + + return 0; +} + +static int starfire_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if (netif_running(dev)) { + netdev_open(dev); + netif_device_attach(dev); + } + + return 0; +} +#endif /* CONFIG_PM */ + static void __devexit starfire_remove_one (struct pci_dev *pdev) { @@ -2115,6 +2147,10 @@ static struct pci_driver starfire_driver = { .name = DRV_NAME, .probe = starfire_init_one, .remove = __devexit_p(starfire_remove_one), +#ifdef CONFIG_PM + .suspend = starfire_suspend, + .resume = starfire_resume, +#endif /* CONFIG_PM */ .id_table = starfire_pci_tbl, }; -- cgit v1.2.3-59-g8ed1b From 3be680b7329e65b9165d6d8dc81baa1e9e89dfc7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 19 Dec 2005 22:35:02 +0900 Subject: [PATCH] libata: separate out ata_sata_print_link_status Separate out sata_print_link_status() from __sata_phy_reset(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 58 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 46c4cdbaee86..a07bd35da912 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1525,6 +1525,41 @@ void ata_port_probe(struct ata_port *ap) ap->flags &= ~ATA_FLAG_PORT_DISABLED; } +/** + * sata_print_link_status - Print SATA link status + * @ap: SATA port to printk link status about + * + * This function prints link speed and status of a SATA link. + * + * LOCKING: + * None. + */ +static void sata_print_link_status(struct ata_port *ap) +{ + u32 sstatus, tmp; + const char *speed; + + if (!ap->ops->scr_read) + return; + + sstatus = scr_read(ap, SCR_STATUS); + + 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); + } else { + printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n", + ap->id, sstatus); + } +} + /** * __sata_phy_reset - Wake/reset a low-level SATA PHY * @ap: SATA port associated with target SATA PHY. @@ -1559,27 +1594,14 @@ void __sata_phy_reset(struct ata_port *ap) break; } while (time_before(jiffies, timeout)); - /* TODO: phy layer with polling, timeouts, etc. */ - sstatus = scr_read(ap, SCR_STATUS); - if (sata_dev_present(ap)) { - const char *speed; - u32 tmp; + /* print link status */ + sata_print_link_status(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); + /* TODO: phy layer with polling, timeouts, etc. */ + if (sata_dev_present(ap)) ata_port_probe(ap); - } else { - printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n", - ap->id, sstatus); + else ata_port_disable(ap); - } if (ap->flags & ATA_FLAG_PORT_DISABLED) return; -- cgit v1.2.3-59-g8ed1b From 7c76d1e83961a4e355c3ebd53191bc6072c238bd Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 19 Dec 2005 22:36:34 +0900 Subject: [PATCH] ahci: separate out ahci_stop/start_engine Separate out ahci_stop/start_engine(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 58 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 19bd346951dd..f3dfdab173f2 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -446,6 +446,43 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in, writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); } +static int ahci_stop_engine(struct ata_port *ap) +{ + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + int work; + u32 tmp; + + tmp = readl(port_mmio + PORT_CMD); + tmp &= ~PORT_CMD_START; + writel(tmp, port_mmio + PORT_CMD); + + /* wait for engine to stop. TODO: this could be + * as long as 500 msec + */ + work = 1000; + while (work-- > 0) { + tmp = readl(port_mmio + PORT_CMD); + if ((tmp & PORT_CMD_LIST_ON) == 0) + return 0; + udelay(10); + } + + return -EIO; +} + +static void ahci_start_engine(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; + + tmp = readl(port_mmio + PORT_CMD); + tmp |= PORT_CMD_START; + writel(tmp, port_mmio + PORT_CMD); + readl(port_mmio + PORT_CMD); /* flush */ +} + static void ahci_phy_reset(struct ata_port *ap) { void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; @@ -572,7 +609,6 @@ static void ahci_restart_port(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; - int work; if ((ap->device[0].class != ATA_DEV_ATAPI) || ((irq_stat & PORT_IRQ_TF_ERR) == 0)) @@ -588,20 +624,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) readl(port_mmio + PORT_SCR_ERR)); /* stop DMA */ - tmp = readl(port_mmio + PORT_CMD); - tmp &= ~PORT_CMD_START; - writel(tmp, port_mmio + PORT_CMD); - - /* wait for engine to stop. TODO: this could be - * as long as 500 msec - */ - work = 1000; - while (work-- > 0) { - tmp = readl(port_mmio + PORT_CMD); - if ((tmp & PORT_CMD_LIST_ON) == 0) - break; - udelay(10); - } + ahci_stop_engine(ap); /* clear SATA phy error, if any */ tmp = readl(port_mmio + PORT_SCR_ERR); @@ -620,10 +643,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) } /* re-start DMA */ - tmp = readl(port_mmio + PORT_CMD); - tmp |= PORT_CMD_START; - writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ + ahci_start_engine(ap); } static void ahci_eng_timeout(struct ata_port *ap) -- cgit v1.2.3-59-g8ed1b From 422b75956cd11f9d9214e6e2a99d6e52d98812d4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 19 Dec 2005 22:37:17 +0900 Subject: [PATCH] ahci: separate out ahci_dev_classify Separate out ahci_dev_classify(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index f3dfdab173f2..30676b0eb366 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -483,10 +483,24 @@ static void ahci_start_engine(struct ata_port *ap) readl(port_mmio + PORT_CMD); /* flush */ } -static void ahci_phy_reset(struct ata_port *ap) +static unsigned int ahci_dev_classify(struct ata_port *ap) { void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; struct ata_taskfile tf; + u32 tmp; + + tmp = readl(port_mmio + PORT_SIG); + tf.lbah = (tmp >> 24) & 0xff; + tf.lbam = (tmp >> 16) & 0xff; + tf.lbal = (tmp >> 8) & 0xff; + tf.nsect = (tmp) & 0xff; + + return ata_dev_classify(&tf); +} + +static void ahci_phy_reset(struct ata_port *ap) +{ + void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; struct ata_device *dev = &ap->device[0]; u32 new_tmp, tmp; @@ -495,13 +509,7 @@ static void ahci_phy_reset(struct ata_port *ap) if (ap->flags & ATA_FLAG_PORT_DISABLED) return; - tmp = readl(port_mmio + PORT_SIG); - tf.lbah = (tmp >> 24) & 0xff; - tf.lbam = (tmp >> 16) & 0xff; - tf.lbal = (tmp >> 8) & 0xff; - tf.nsect = (tmp) & 0xff; - - dev->class = ata_dev_classify(&tf); + dev->class = ahci_dev_classify(ap); if (!ata_dev_present(dev)) { ata_port_disable(ap); return; -- cgit v1.2.3-59-g8ed1b From 9c4b562abc9005e4b413de02c85d3d29da707cba Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 19 Jan 2006 18:07:10 +0100 Subject: Move ip2.c and ip2main.c to drivers/char/ip2/ where the other files used by this driver reside. Renamed ip2.c to ip2base.c to allow ip2.o to be built from multiple objects. Signed-off-by: Adrian Bunk Acked-by: Michael H. Warfield --- drivers/char/Makefile | 2 +- drivers/char/ip2.c | 109 -- drivers/char/ip2/Makefile | 8 + drivers/char/ip2/ip2base.c | 109 ++ drivers/char/ip2/ip2main.c | 3260 ++++++++++++++++++++++++++++++++++++++++++++ drivers/char/ip2main.c | 3260 -------------------------------------------- 6 files changed, 3378 insertions(+), 3370 deletions(-) delete mode 100644 drivers/char/ip2.c create mode 100644 drivers/char/ip2/Makefile create mode 100644 drivers/char/ip2/ip2base.c create mode 100644 drivers/char/ip2/ip2main.c delete mode 100644 drivers/char/ip2main.c (limited to 'drivers') diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 503dd901d406..090d154098bb 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -31,7 +31,7 @@ obj-$(CONFIG_MOXA_INTELLIO) += moxa.o obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o obj-$(CONFIG_MOXA_SMARTIO) += mxser.o -obj-$(CONFIG_COMPUTONE) += ip2.o ip2main.o +obj-$(CONFIG_COMPUTONE) += ip2/ obj-$(CONFIG_RISCOM8) += riscom8.o obj-$(CONFIG_ISI) += isicom.o obj-$(CONFIG_SYNCLINK) += synclink.o diff --git a/drivers/char/ip2.c b/drivers/char/ip2.c deleted file mode 100644 index 7cadfc6ef352..000000000000 --- a/drivers/char/ip2.c +++ /dev/null @@ -1,109 +0,0 @@ -// ip2.c -// This is a dummy module to make the firmware available when needed -// and allows it to be unloaded when not. Rumor is the __initdata -// macro doesn't always works on all platforms so we use this kludge. -// If not compiled as a module it just makes fip_firm avaliable then -// __initdata should work as advertized -// - -#include -#include -#include - -#ifndef __init -#define __init -#endif -#ifndef __initfunc -#define __initfunc(a) a -#endif -#ifndef __initdata -#define __initdata -#endif - -#include "./ip2/ip2types.h" -#include "./ip2/fip_firm.h" // the meat - -int -ip2_loadmain(int *, int *, unsigned char *, int ); // ref into ip2main.c - -/* Note: Add compiled in defaults to these arrays, not to the structure - in ip2/ip2.h any longer. That structure WILL get overridden - by these values, or command line values, or insmod values!!! =mhw= -*/ -static int io[IP2_MAX_BOARDS]= { 0, 0, 0, 0 }; -static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 }; - -static int poll_only = 0; - -MODULE_AUTHOR("Doug McNash"); -MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); -module_param_array(irq, int, NULL, 0); -MODULE_PARM_DESC(irq,"Interrupts for IntelliPort Cards"); -module_param_array(io, int, NULL, 0); -MODULE_PARM_DESC(io,"I/O ports for IntelliPort Cards"); -module_param(poll_only, bool, 0); -MODULE_PARM_DESC(poll_only,"Do not use card interrupts"); - - -static int __init ip2_init(void) -{ - if( poll_only ) { - /* Hard lock the interrupts to zero */ - irq[0] = irq[1] = irq[2] = irq[3] = 0; - } - - return ip2_loadmain(io,irq,(unsigned char *)fip_firm,sizeof(fip_firm)); -} -module_init(ip2_init); - -MODULE_LICENSE("GPL"); - -#ifndef MODULE -/****************************************************************************** - * ip2_setup: - * str: kernel command line string - * - * Can't autoprobe the boards so user must specify configuration on - * kernel command line. Sane people build it modular but the others - * come here. - * - * Alternating pairs of io,irq for up to 4 boards. - * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3 - * - * io=0 => No board - * io=1 => PCI - * io=2 => EISA - * else => ISA I/O address - * - * irq=0 or invalid for ISA will revert to polling mode - * - * Any value = -1, do not overwrite compiled in value. - * - ******************************************************************************/ -static int __init ip2_setup(char *str) -{ - int ints[10]; /* 4 boards, 2 parameters + 2 */ - int i, j; - - str = get_options (str, ARRAY_SIZE(ints), ints); - - for( i = 0, j = 1; i < 4; i++ ) { - if( j > ints[0] ) { - break; - } - if( ints[j] >= 0 ) { - io[i] = ints[j]; - } - j++; - if( j > ints[0] ) { - break; - } - if( ints[j] >= 0 ) { - irq[i] = ints[j]; - } - j++; - } - return 1; -} -__setup("ip2=", ip2_setup); -#endif /* !MODULE */ diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile new file mode 100644 index 000000000000..6bfe2543ddc2 --- /dev/null +++ b/drivers/char/ip2/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the Computone IntelliPort Plus Driver +# + +obj-$(CONFIG_COMPUTONE) += ip2.o ip2main.o + +ip2-objs := ip2base.o + diff --git a/drivers/char/ip2/ip2base.c b/drivers/char/ip2/ip2base.c new file mode 100644 index 000000000000..435ccfc74958 --- /dev/null +++ b/drivers/char/ip2/ip2base.c @@ -0,0 +1,109 @@ +// ip2.c +// This is a dummy module to make the firmware available when needed +// and allows it to be unloaded when not. Rumor is the __initdata +// macro doesn't always works on all platforms so we use this kludge. +// If not compiled as a module it just makes fip_firm avaliable then +// __initdata should work as advertized +// + +#include +#include +#include + +#ifndef __init +#define __init +#endif +#ifndef __initfunc +#define __initfunc(a) a +#endif +#ifndef __initdata +#define __initdata +#endif + +#include "ip2types.h" +#include "fip_firm.h" // the meat + +int +ip2_loadmain(int *, int *, unsigned char *, int ); // ref into ip2main.c + +/* Note: Add compiled in defaults to these arrays, not to the structure + in ip2.h any longer. That structure WILL get overridden + by these values, or command line values, or insmod values!!! =mhw= +*/ +static int io[IP2_MAX_BOARDS]= { 0, 0, 0, 0 }; +static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 }; + +static int poll_only = 0; + +MODULE_AUTHOR("Doug McNash"); +MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); +module_param_array(irq, int, NULL, 0); +MODULE_PARM_DESC(irq,"Interrupts for IntelliPort Cards"); +module_param_array(io, int, NULL, 0); +MODULE_PARM_DESC(io,"I/O ports for IntelliPort Cards"); +module_param(poll_only, bool, 0); +MODULE_PARM_DESC(poll_only,"Do not use card interrupts"); + + +static int __init ip2_init(void) +{ + if( poll_only ) { + /* Hard lock the interrupts to zero */ + irq[0] = irq[1] = irq[2] = irq[3] = 0; + } + + return ip2_loadmain(io,irq,(unsigned char *)fip_firm,sizeof(fip_firm)); +} +module_init(ip2_init); + +MODULE_LICENSE("GPL"); + +#ifndef MODULE +/****************************************************************************** + * ip2_setup: + * str: kernel command line string + * + * Can't autoprobe the boards so user must specify configuration on + * kernel command line. Sane people build it modular but the others + * come here. + * + * Alternating pairs of io,irq for up to 4 boards. + * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3 + * + * io=0 => No board + * io=1 => PCI + * io=2 => EISA + * else => ISA I/O address + * + * irq=0 or invalid for ISA will revert to polling mode + * + * Any value = -1, do not overwrite compiled in value. + * + ******************************************************************************/ +static int __init ip2_setup(char *str) +{ + int ints[10]; /* 4 boards, 2 parameters + 2 */ + int i, j; + + str = get_options (str, ARRAY_SIZE(ints), ints); + + for( i = 0, j = 1; i < 4; i++ ) { + if( j > ints[0] ) { + break; + } + if( ints[j] >= 0 ) { + io[i] = ints[j]; + } + j++; + if( j > ints[0] ) { + break; + } + if( ints[j] >= 0 ) { + irq[i] = ints[j]; + } + j++; + } + return 1; +} +__setup("ip2=", ip2_setup); +#endif /* !MODULE */ diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c new file mode 100644 index 000000000000..52f64bfb0dc6 --- /dev/null +++ b/drivers/char/ip2/ip2main.c @@ -0,0 +1,3260 @@ +/* +* +* (c) 1999 by Computone Corporation +* +******************************************************************************** +* +* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport +* serial I/O controllers. +* +* DESCRIPTION: Mainline code for the device driver +* +*******************************************************************************/ +// ToDo: +// +// Fix the immediate DSS_NOW problem. +// Work over the channel stats return logic in ip2_ipl_ioctl so they +// make sense for all 256 possible channels and so the user space +// utilities will compile and work properly. +// +// Done: +// +// 1.2.14 /\/\|=mhw=|\/\/ +// Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts. +// Changed the definition of ip2trace to be more consistent with kernel style +// Thanks to Andreas Dilger for these updates +// +// 1.2.13 /\/\|=mhw=|\/\/ +// DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform +// to agreed devfs serial device naming convention. +// +// 1.2.12 /\/\|=mhw=|\/\/ +// Cleaned up some remove queue cut and paste errors +// +// 1.2.11 /\/\|=mhw=|\/\/ +// Clean up potential NULL pointer dereferences +// Clean up devfs registration +// Add kernel command line parsing for io and irq +// Compile defaults for io and irq are now set in ip2.c not ip2.h! +// Reworked poll_only hack for explicit parameter setting +// You must now EXPLICITLY set poll_only = 1 or set all irqs to 0 +// Merged ip2_loadmain and old_ip2_init +// Converted all instances of interruptible_sleep_on into queue calls +// Most of these had no race conditions but better to clean up now +// +// 1.2.10 /\/\|=mhw=|\/\/ +// Fixed the bottom half interrupt handler and enabled USE_IQI +// to split the interrupt handler into a formal top-half / bottom-half +// Fixed timing window on high speed processors that queued messages to +// the outbound mail fifo faster than the board could handle. +// +// 1.2.9 +// Four box EX was barfing on >128k kmalloc, made structure smaller by +// reducing output buffer size +// +// 1.2.8 +// Device file system support (MHW) +// +// 1.2.7 +// Fixed +// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules +// +// 1.2.6 +//Fixes DCD problems +// DCD was not reported when CLOCAL was set on call to TIOCMGET +// +//Enhancements: +// TIOCMGET requests and waits for status return +// No DSS interrupts enabled except for DCD when needed +// +// For internal use only +// +//#define IP2DEBUG_INIT +//#define IP2DEBUG_OPEN +//#define IP2DEBUG_WRITE +//#define IP2DEBUG_READ +//#define IP2DEBUG_IOCTL +//#define IP2DEBUG_IPL + +//#define IP2DEBUG_TRACE +//#define DEBUG_FIFO + +/************/ +/* Includes */ +/************/ +#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 "ip2types.h" +#include "ip2trace.h" +#include "ip2ioctl.h" +#include "ip2.h" +#include "i2ellis.h" +#include "i2lib.h" + +/***************** + * /proc/ip2mem * + *****************/ + +#include + +static int ip2_read_procmem(char *, char **, off_t, int); +static int ip2_read_proc(char *, char **, off_t, int, int *, void * ); + +/********************/ +/* Type Definitions */ +/********************/ + +/*************/ +/* Constants */ +/*************/ + +/* String constants to identify ourselves */ +static char *pcName = "Computone IntelliPort Plus multiport driver"; +static char *pcVersion = "1.2.14"; + +/* String constants for port names */ +static char *pcDriver_name = "ip2"; +static char *pcIpl = "ip2ipl"; + +/* Serial subtype definitions */ +#define SERIAL_TYPE_NORMAL 1 + +// cheezy kludge or genius - you decide? +int ip2_loadmain(int *, int *, unsigned char *, int); +static unsigned char *Fip_firmware; +static int Fip_firmware_size; + +/***********************/ +/* Function Prototypes */ +/***********************/ + +/* Global module entry functions */ + +/* Private (static) functions */ +static int ip2_open(PTTY, struct file *); +static void ip2_close(PTTY, struct file *); +static int ip2_write(PTTY, const unsigned char *, int); +static void ip2_putchar(PTTY, unsigned char); +static void ip2_flush_chars(PTTY); +static int ip2_write_room(PTTY); +static int ip2_chars_in_buf(PTTY); +static void ip2_flush_buffer(PTTY); +static int ip2_ioctl(PTTY, struct file *, UINT, ULONG); +static void ip2_set_termios(PTTY, struct termios *); +static void ip2_set_line_discipline(PTTY); +static void ip2_throttle(PTTY); +static void ip2_unthrottle(PTTY); +static void ip2_stop(PTTY); +static void ip2_start(PTTY); +static void ip2_hangup(PTTY); +static int ip2_tiocmget(struct tty_struct *tty, struct file *file); +static int ip2_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); + +static void set_irq(int, int); +static void ip2_interrupt_bh(i2eBordStrPtr pB); +static irqreturn_t ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs); +static void ip2_poll(unsigned long arg); +static inline void service_all_boards(void); +static void do_input(void *p); +static void do_status(void *p); + +static void ip2_wait_until_sent(PTTY,int); + +static void set_params (i2ChanStrPtr, struct termios *); +static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *); +static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); + +static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); +static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); +static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG); +static int ip2_ipl_open(struct inode *, struct file *); + +static int DumpTraceBuffer(char __user *, int); +static int DumpFifoBuffer( char __user *, int); + +static void ip2_init_board(int); +static unsigned short find_eisa_board(int); + +/***************/ +/* Static Data */ +/***************/ + +static struct tty_driver *ip2_tty_driver; + +/* Here, then is a table of board pointers which the interrupt routine should + * scan through to determine who it must service. + */ +static unsigned short i2nBoards; // Number of boards here + +static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS]; + +static i2ChanStrPtr DevTable[IP2_MAX_PORTS]; +//DevTableMem just used to save addresses for kfree +static void *DevTableMem[IP2_MAX_BOARDS]; + +/* This is the driver descriptor for the ip2ipl device, which is used to + * download the loadware to the boards. + */ +static struct file_operations ip2_ipl = { + .owner = THIS_MODULE, + .read = ip2_ipl_read, + .write = ip2_ipl_write, + .ioctl = ip2_ipl_ioctl, + .open = ip2_ipl_open, +}; + +static unsigned long irq_counter = 0; +static unsigned long bh_counter = 0; + +// Use immediate queue to service interrupts +#define USE_IQI +//#define USE_IQ // PCI&2.2 needs work + +/* The timer_list entry for our poll routine. If interrupt operation is not + * selected, the board is serviced periodically to see if anything needs doing. + */ +#define POLL_TIMEOUT (jiffies + 1) +static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); +static char TimerOn; + +#ifdef IP2DEBUG_TRACE +/* Trace (debug) buffer data */ +#define TRACEMAX 1000 +static unsigned long tracebuf[TRACEMAX]; +static int tracestuff; +static int tracestrip; +static int tracewrap; +#endif + +/**********/ +/* Macros */ +/**********/ + +#if defined(MODULE) && defined(IP2DEBUG_OPEN) +#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \ + tty->name,(pCh->flags),ip2_tty_driver->refcount, \ + tty->count,/*GET_USE_COUNT(module)*/0,s) +#else +#define DBG_CNT(s) +#endif + +/********/ +/* Code */ +/********/ + +#include "i2ellis.c" /* Extremely low-level interface services */ +#include "i2cmd.c" /* Standard loadware command definitions */ +#include "i2lib.c" /* High level interface services */ + +/* Configuration area for modprobe */ + +MODULE_AUTHOR("Doug McNash"); +MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); + +static int poll_only = 0; + +static int Eisa_irq; +static int Eisa_slot; + +static int iindx; +static char rirqs[IP2_MAX_BOARDS]; +static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; + +/* for sysfs class support */ +static struct class *ip2_class; + +// Some functions to keep track of what irq's we have + +static int __init +is_valid_irq(int irq) +{ + int *i = Valid_Irqs; + + while ((*i != 0) && (*i != irq)) { + i++; + } + return (*i); +} + +static void __init +mark_requested_irq( char irq ) +{ + rirqs[iindx++] = irq; +} + +#ifdef MODULE +static int __init +clear_requested_irq( char irq ) +{ + int i; + for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { + if (rirqs[i] == irq) { + rirqs[i] = 0; + return 1; + } + } + return 0; +} +#endif + +static int __init +have_requested_irq( char irq ) +{ + // array init to zeros so 0 irq will not be requested as a side effect + int i; + for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { + if (rirqs[i] == irq) + return 1; + } + return 0; +} + +/******************************************************************************/ +/* Function: init_module() */ +/* Parameters: None */ +/* Returns: Success (0) */ +/* */ +/* Description: */ +/* This is a required entry point for an installable module. It simply calls */ +/* the driver initialisation function and returns what it returns. */ +/******************************************************************************/ +#ifdef MODULE +int +init_module(void) +{ +#ifdef IP2DEBUG_INIT + printk (KERN_DEBUG "Loading module ...\n" ); +#endif + return 0; +} +#endif /* MODULE */ + +/******************************************************************************/ +/* Function: cleanup_module() */ +/* Parameters: None */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This is a required entry point for an installable module. It has to return */ +/* the device and the driver to a passive state. It should not be necessary */ +/* to reset the board fully, especially as the loadware is downloaded */ +/* externally rather than in the driver. We just want to disable the board */ +/* and clear the loadware to a reset state. To allow this there has to be a */ +/* way to detect whether the board has the loadware running at init time to */ +/* handle subsequent installations of the driver. All memory allocated by the */ +/* driver should be returned since it may be unloaded from memory. */ +/******************************************************************************/ +#ifdef MODULE +void +cleanup_module(void) +{ + int err; + int i; + +#ifdef IP2DEBUG_INIT + printk (KERN_DEBUG "Unloading %s: version %s\n", pcName, pcVersion ); +#endif + /* Stop poll timer if we had one. */ + if ( TimerOn ) { + del_timer ( &PollTimer ); + TimerOn = 0; + } + + /* Reset the boards we have. */ + for( i = 0; i < IP2_MAX_BOARDS; ++i ) { + if ( i2BoardPtrTable[i] ) { + iiReset( i2BoardPtrTable[i] ); + } + } + + /* The following is done at most once, if any boards were installed. */ + for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { + if ( i2BoardPtrTable[i] ) { + iiResetDelay( i2BoardPtrTable[i] ); + /* free io addresses and Tibet */ + release_region( ip2config.addr[i], 8 ); + class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); + devfs_remove("ip2/ipl%d", i); + class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); + devfs_remove("ip2/stat%d", i); + } + /* Disable and remove interrupt handler. */ + if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) { + free_irq ( ip2config.irq[i], (void *)&pcName); + clear_requested_irq( ip2config.irq[i]); + } + } + class_destroy(ip2_class); + devfs_remove("ip2"); + if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) { + printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err); + } + put_tty_driver(ip2_tty_driver); + if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) { + printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err); + } + remove_proc_entry("ip2mem", &proc_root); + + // free memory + for (i = 0; i < IP2_MAX_BOARDS; i++) { + void *pB; +#ifdef CONFIG_PCI + if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) { + pci_disable_device(ip2config.pci_dev[i]); + ip2config.pci_dev[i] = NULL; + } +#endif + if ((pB = i2BoardPtrTable[i]) != 0 ) { + kfree ( pB ); + i2BoardPtrTable[i] = NULL; + } + if ((DevTableMem[i]) != NULL ) { + kfree ( DevTableMem[i] ); + DevTableMem[i] = NULL; + } + } + + /* Cleanup the iiEllis subsystem. */ + iiEllisCleanup(); +#ifdef IP2DEBUG_INIT + printk (KERN_DEBUG "IP2 Unloaded\n" ); +#endif +} +#endif /* MODULE */ + +static struct tty_operations ip2_ops = { + .open = ip2_open, + .close = ip2_close, + .write = ip2_write, + .put_char = ip2_putchar, + .flush_chars = ip2_flush_chars, + .write_room = ip2_write_room, + .chars_in_buffer = ip2_chars_in_buf, + .flush_buffer = ip2_flush_buffer, + .ioctl = ip2_ioctl, + .throttle = ip2_throttle, + .unthrottle = ip2_unthrottle, + .set_termios = ip2_set_termios, + .set_ldisc = ip2_set_line_discipline, + .stop = ip2_stop, + .start = ip2_start, + .hangup = ip2_hangup, + .read_proc = ip2_read_proc, + .tiocmget = ip2_tiocmget, + .tiocmset = ip2_tiocmset, +}; + +/******************************************************************************/ +/* Function: ip2_loadmain() */ +/* Parameters: irq, io from command line of insmod et. al. */ +/* pointer to fip firmware and firmware size for boards */ +/* Returns: Success (0) */ +/* */ +/* Description: */ +/* This was the required entry point for all drivers (now in ip2.c) */ +/* It performs all */ +/* initialisation of the devices and driver structures, and registers itself */ +/* with the relevant kernel modules. */ +/******************************************************************************/ +/* SA_INTERRUPT- if set blocks all interrupts else only this line */ +/* SA_SHIRQ - for shared irq PCI or maybe EISA only */ +/* SA_RANDOM - can be source for cert. random number generators */ +#define IP2_SA_FLAGS 0 + +int +ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) +{ + int i, j, box; + int err = 0; + int status = 0; + static int loaded; + i2eBordStrPtr pB = NULL; + int rc = -1; + + ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 ); + + /* process command line arguments to modprobe or + insmod i.e. iop & irqp */ + /* irqp and iop should ALWAYS be specified now... But we check + them individually just to be sure, anyways... */ + for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { + if (iop) { + ip2config.addr[i] = iop[i]; + if (irqp) { + if( irqp[i] >= 0 ) { + ip2config.irq[i] = irqp[i]; + } else { + ip2config.irq[i] = 0; + } + // This is a little bit of a hack. If poll_only=1 on command + // line back in ip2.c OR all IRQs on all specified boards are + // explicitly set to 0, then drop to poll only mode and override + // PCI or EISA interrupts. This superceeds the old hack of + // triggering if all interrupts were zero (like da default). + // Still a hack but less prone to random acts of terrorism. + // + // What we really should do, now that the IRQ default is set + // to -1, is to use 0 as a hard coded, do not probe. + // + // /\/\|=mhw=|\/\/ + poll_only |= irqp[i]; + } + } + } + poll_only = !poll_only; + + Fip_firmware = firmware; + Fip_firmware_size = firmsize; + + /* Announce our presence */ + printk( KERN_INFO "%s version %s\n", pcName, pcVersion ); + + // ip2 can be unloaded and reloaded for no good reason + // we can't let that happen here or bad things happen + // second load hoses board but not system - fixme later + if (loaded) { + printk( KERN_INFO "Still loaded\n" ); + return 0; + } + loaded++; + + ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS); + if (!ip2_tty_driver) + return -ENOMEM; + + /* Initialise the iiEllis subsystem. */ + iiEllisInit(); + + /* Initialize arrays. */ + memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable ); + memset( DevTable, 0, sizeof DevTable ); + + /* Initialise all the boards we can find (up to the maximum). */ + for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { + switch ( ip2config.addr[i] ) { + case 0: /* skip this slot even if card is present */ + break; + default: /* ISA */ + /* ISA address must be specified */ + if ( (ip2config.addr[i] < 0x100) || (ip2config.addr[i] > 0x3f8) ) { + printk ( KERN_ERR "IP2: Bad ISA board %d address %x\n", + i, ip2config.addr[i] ); + ip2config.addr[i] = 0; + } else { + ip2config.type[i] = ISA; + + /* Check for valid irq argument, set for polling if invalid */ + if (ip2config.irq[i] && !is_valid_irq(ip2config.irq[i])) { + printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",ip2config.irq[i]); + ip2config.irq[i] = 0;// 0 is polling and is valid in that sense + } + } + break; + case PCI: +#ifdef CONFIG_PCI + { + struct pci_dev *pci_dev_i = NULL; + pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE, + PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); + if (pci_dev_i != NULL) { + unsigned int addr; + + if (pci_enable_device(pci_dev_i)) { + printk( KERN_ERR "IP2: can't enable PCI device at %s\n", + pci_name(pci_dev_i)); + break; + } + ip2config.type[i] = PCI; + ip2config.pci_dev[i] = pci_dev_i; + status = + pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr); + if ( addr & 1 ) { + ip2config.addr[i]=(USHORT)(addr&0xfffe); + } else { + printk( KERN_ERR "IP2: PCI I/O address error\n"); + } + +// If the PCI BIOS assigned it, lets try and use it. If we +// can't acquire it or it screws up, deal with it then. + +// if (!is_valid_irq(pci_irq)) { +// printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq); +// pci_irq = 0; +// } + ip2config.irq[i] = pci_dev_i->irq; + } else { // ann error + ip2config.addr[i] = 0; + if (status == PCIBIOS_DEVICE_NOT_FOUND) { + printk( KERN_ERR "IP2: PCI board %d not found\n", i ); + } else { + printk( KERN_ERR "IP2: PCI error 0x%x \n", status ); + } + } + } +#else + printk( KERN_ERR "IP2: PCI card specified but PCI support not\n"); + printk( KERN_ERR "IP2: configured in this kernel.\n"); + printk( KERN_ERR "IP2: Recompile kernel with CONFIG_PCI defined!\n"); +#endif /* CONFIG_PCI */ + break; + case EISA: + if ( (ip2config.addr[i] = find_eisa_board( Eisa_slot + 1 )) != 0) { + /* Eisa_irq set as side effect, boo */ + ip2config.type[i] = EISA; + } + ip2config.irq[i] = Eisa_irq; + break; + } /* switch */ + } /* for */ + for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { + if ( ip2config.addr[i] ) { + pB = kmalloc( sizeof(i2eBordStr), GFP_KERNEL); + if ( pB != NULL ) { + i2BoardPtrTable[i] = pB; + memset( pB, 0, sizeof(i2eBordStr) ); + iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer ); + iiReset( pB ); + } else { + printk(KERN_ERR "IP2: board memory allocation error\n"); + } + } + } + for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { + if ( ( pB = i2BoardPtrTable[i] ) != NULL ) { + iiResetDelay( pB ); + break; + } + } + for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { + if ( i2BoardPtrTable[i] != NULL ) { + ip2_init_board( i ); + } + } + + ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 ); + + ip2_tty_driver->owner = THIS_MODULE; + ip2_tty_driver->name = "ttyF"; + ip2_tty_driver->devfs_name = "tts/F"; + ip2_tty_driver->driver_name = pcDriver_name; + ip2_tty_driver->major = IP2_TTY_MAJOR; + ip2_tty_driver->minor_start = 0; + ip2_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL; + ip2_tty_driver->init_termios = tty_std_termios; + ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; + ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; + tty_set_operations(ip2_tty_driver, &ip2_ops); + + ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 ); + + /* Register the tty devices. */ + if ( ( err = tty_register_driver ( ip2_tty_driver ) ) ) { + printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err); + put_tty_driver(ip2_tty_driver); + return -EINVAL; + } else + /* Register the IPL driver. */ + if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) { + printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err ); + } else { + /* create the sysfs class */ + ip2_class = class_create(THIS_MODULE, "ip2"); + if (IS_ERR(ip2_class)) { + err = PTR_ERR(ip2_class); + goto out_chrdev; + } + } + /* Register the read_procmem thing */ + if (!create_proc_info_entry("ip2mem",0,&proc_root,ip2_read_procmem)) { + printk(KERN_ERR "IP2: failed to register read_procmem\n"); + } else { + + ip2trace (ITRC_NO_PORT, ITRC_INIT, 4, 0 ); + /* Register the interrupt handler or poll handler, depending upon the + * specified interrupt. + */ + + for( i = 0; i < IP2_MAX_BOARDS; ++i ) { + if ( 0 == ip2config.addr[i] ) { + continue; + } + + if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { + class_device_create(ip2_class, NULL, + MKDEV(IP2_IPL_MAJOR, 4 * i), + NULL, "ipl%d", i); + err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i), + S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, + "ip2/ipl%d", i); + if (err) { + class_device_destroy(ip2_class, + MKDEV(IP2_IPL_MAJOR, 4 * i)); + goto out_class; + } + + class_device_create(ip2_class, NULL, + MKDEV(IP2_IPL_MAJOR, 4 * i + 1), + NULL, "stat%d", i); + err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1), + S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, + "ip2/stat%d", i); + if (err) { + class_device_destroy(ip2_class, + MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); + goto out_class; + } + + for ( box = 0; box < ABS_MAX_BOXES; ++box ) + { + for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) + { + if ( pB->i2eChannelMap[box] & (1 << j) ) + { + tty_register_device(ip2_tty_driver, + j + ABS_BIGGEST_BOX * + (box+i*ABS_MAX_BOXES), NULL); + } + } + } + } + + if (poll_only) { +// Poll only forces driver to only use polling and +// to ignore the probed PCI or EISA interrupts. + ip2config.irq[i] = CIR_POLL; + } + if ( ip2config.irq[i] == CIR_POLL ) { +retry: + if (!TimerOn) { + PollTimer.expires = POLL_TIMEOUT; + add_timer ( &PollTimer ); + TimerOn = 1; + printk( KERN_INFO "IP2: polling\n"); + } + } else { + if (have_requested_irq(ip2config.irq[i])) + continue; + rc = request_irq( ip2config.irq[i], ip2_interrupt, + IP2_SA_FLAGS | (ip2config.type[i] == PCI ? SA_SHIRQ : 0), + pcName, (void *)&pcName); + if (rc) { + printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc); + ip2config.irq[i] = CIR_POLL; + printk( KERN_INFO "IP2: Polling %ld/sec.\n", + (POLL_TIMEOUT - jiffies)); + goto retry; + } + mark_requested_irq(ip2config.irq[i]); + /* Initialise the interrupt handler bottom half (aka slih). */ + } + } + for( i = 0; i < IP2_MAX_BOARDS; ++i ) { + if ( i2BoardPtrTable[i] ) { + set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */ + } + } + } + ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 ); + goto out; + +out_class: + class_destroy(ip2_class); +out_chrdev: + unregister_chrdev(IP2_IPL_MAJOR, "ip2"); +out: + return err; +} + +EXPORT_SYMBOL(ip2_loadmain); + +/******************************************************************************/ +/* Function: ip2_init_board() */ +/* Parameters: Index of board in configuration structure */ +/* Returns: Success (0) */ +/* */ +/* Description: */ +/* This function initializes the specified board. The loadware is copied to */ +/* the board, the channel structures are initialized, and the board details */ +/* are reported on the console. */ +/******************************************************************************/ +static void __init +ip2_init_board( int boardnum ) +{ + int i; + int nports = 0, nboxes = 0; + i2ChanStrPtr pCh; + i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; + + if ( !iiInitialize ( pB ) ) { + printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n", + pB->i2eBase, pB->i2eError ); + goto err_initialize; + } + printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1, + ip2config.addr[boardnum], ip2config.irq[boardnum] ); + + if (!request_region( ip2config.addr[boardnum], 8, pcName )) { + printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]); + goto err_initialize; + } + + if ( iiDownloadAll ( pB, (loadHdrStrPtr)Fip_firmware, 1, Fip_firmware_size ) + != II_DOWN_GOOD ) { + printk ( KERN_ERR "IP2: failed to download loadware\n" ); + goto err_release_region; + } else { + printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n", + pB->i2ePom.e.porVersion, + pB->i2ePom.e.porRevision, + pB->i2ePom.e.porSubRev, pB->i2eLVersion, + pB->i2eLRevision, pB->i2eLSub ); + } + + switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) { + + default: + printk( KERN_ERR "IP2: Unknown board type, ID = %x\n", + pB->i2ePom.e.porID ); + nports = 0; + goto err_release_region; + break; + + case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */ + printk ( KERN_INFO "IP2: ISA-4\n" ); + nports = 4; + break; + + case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */ + printk ( KERN_INFO "IP2: ISA-8 std\n" ); + nports = 8; + break; + + case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */ + printk ( KERN_INFO "IP2: ISA-8 RJ11\n" ); + nports = 8; + break; + + case POR_ID_FIIEX: /* IntelliPort IIEX */ + { + int portnum = IP2_PORTS_PER_BOARD * boardnum; + int box; + + for( box = 0; box < ABS_MAX_BOXES; ++box ) { + if ( pB->i2eChannelMap[box] != 0 ) { + ++nboxes; + } + for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { + if ( pB->i2eChannelMap[box] & 1<< i ) { + ++nports; + } + } + } + DevTableMem[boardnum] = pCh = + kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL ); + if ( !pCh ) { + printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); + goto err_release_region; + } + if ( !i2InitChannels( pB, nports, pCh ) ) { + printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); + kfree ( pCh ); + goto err_release_region; + } + pB->i2eChannelPtr = &DevTable[portnum]; + pB->i2eChannelCnt = ABS_MOST_PORTS; + + for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) { + for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { + if ( pB->i2eChannelMap[box] & (1 << i) ) { + DevTable[portnum + i] = pCh; + pCh->port_index = portnum + i; + pCh++; + } + } + } + printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n", + nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 ); + } + goto ex_exit; + } + DevTableMem[boardnum] = pCh = + kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL ); + if ( !pCh ) { + printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); + goto err_release_region; + } + pB->i2eChannelPtr = pCh; + pB->i2eChannelCnt = nports; + if ( !i2InitChannels( pB, nports, pCh ) ) { + printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); + kfree ( pCh ); + goto err_release_region; + } + pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum]; + + for( i = 0; i < pB->i2eChannelCnt; ++i ) { + DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh; + pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i; + pCh++; + } +ex_exit: + INIT_WORK(&pB->tqueue_interrupt, (void(*)(void*)) ip2_interrupt_bh, pB); + return; + +err_release_region: + release_region(ip2config.addr[boardnum], 8); +err_initialize: + kfree ( pB ); + i2BoardPtrTable[boardnum] = NULL; + return; +} + +/******************************************************************************/ +/* Function: find_eisa_board ( int start_slot ) */ +/* Parameters: First slot to check */ +/* Returns: Address of EISA IntelliPort II controller */ +/* */ +/* Description: */ +/* This function searches for an EISA IntelliPort controller, starting */ +/* from the specified slot number. If the motherboard is not identified as an */ +/* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */ +/* it returns the base address of the controller. */ +/******************************************************************************/ +static unsigned short __init +find_eisa_board( int start_slot ) +{ + int i, j; + unsigned int idm = 0; + unsigned int idp = 0; + unsigned int base = 0; + unsigned int value; + int setup_address; + int setup_irq; + int ismine = 0; + + /* + * First a check for an EISA motherboard, which we do by comparing the + * EISA ID registers for the system board and the first couple of slots. + * No slot ID should match the system board ID, but on an ISA or PCI + * machine the odds are that an empty bus will return similar values for + * each slot. + */ + i = 0x0c80; + value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3); + for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) { + j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3); + if ( value == j ) + return 0; + } + + /* + * OK, so we are inclined to believe that this is an EISA machine. Find + * an IntelliPort controller. + */ + for( i = start_slot; i < 16; i++ ) { + base = i << 12; + idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff); + idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff); + ismine = 0; + if ( idm == 0x0e8e ) { + if ( idp == 0x0281 || idp == 0x0218 ) { + ismine = 1; + } else if ( idp == 0x0282 || idp == 0x0283 ) { + ismine = 3; /* Can do edge-trigger */ + } + if ( ismine ) { + Eisa_slot = i; + break; + } + } + } + if ( !ismine ) + return 0; + + /* It's some sort of EISA card, but at what address is it configured? */ + + setup_address = base + 0xc88; + value = inb(base + 0xc86); + setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0; + + if ( (ismine & 2) && !(value & 0x10) ) { + ismine = 1; /* Could be edging, but not */ + } + + if ( Eisa_irq == 0 ) { + Eisa_irq = setup_irq; + } else if ( Eisa_irq != setup_irq ) { + printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" ); + } + +#ifdef IP2DEBUG_INIT +printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x", + base >> 12, idm, idp, setup_address); + if ( Eisa_irq ) { + printk(KERN_DEBUG ", Interrupt %d %s\n", + setup_irq, (ismine & 2) ? "(edge)" : "(level)"); + } else { + printk(KERN_DEBUG ", (polled)\n"); + } +#endif + return setup_address; +} + +/******************************************************************************/ +/* Function: set_irq() */ +/* Parameters: index to board in board table */ +/* IRQ to use */ +/* Returns: Success (0) */ +/* */ +/* Description: */ +/******************************************************************************/ +static void +set_irq( int boardnum, int boardIrq ) +{ + unsigned char tempCommand[16]; + i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; + unsigned long flags; + + /* + * Notify the boards they may generate interrupts. This is done by + * sending an in-line command to channel 0 on each board. This is why + * the channels have to be defined already. For each board, if the + * interrupt has never been defined, we must do so NOW, directly, since + * board will not send flow control or even give an interrupt until this + * is done. If polling we must send 0 as the interrupt parameter. + */ + + // We will get an interrupt here at the end of this function + + iiDisableMailIrq(pB); + + /* We build up the entire packet header. */ + CHANNEL_OF(tempCommand) = 0; + PTYPE_OF(tempCommand) = PTYPE_INLINE; + CMD_COUNT_OF(tempCommand) = 2; + (CMD_OF(tempCommand))[0] = CMDVALUE_IRQ; + (CMD_OF(tempCommand))[1] = boardIrq; + /* + * Write to FIFO; don't bother to adjust fifo capacity for this, since + * board will respond almost immediately after SendMail hit. + */ + WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags); + iiWriteBuf(pB, tempCommand, 4); + WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags); + pB->i2eUsingIrq = boardIrq; + pB->i2eOutMailWaiting |= MB_OUT_STUFFED; + + /* Need to update number of boards before you enable mailbox int */ + ++i2nBoards; + + CHANNEL_OF(tempCommand) = 0; + PTYPE_OF(tempCommand) = PTYPE_BYPASS; + CMD_COUNT_OF(tempCommand) = 6; + (CMD_OF(tempCommand))[0] = 88; // SILO + (CMD_OF(tempCommand))[1] = 64; // chars + (CMD_OF(tempCommand))[2] = 32; // ms + + (CMD_OF(tempCommand))[3] = 28; // MAX_BLOCK + (CMD_OF(tempCommand))[4] = 64; // chars + + (CMD_OF(tempCommand))[5] = 87; // HW_TEST + WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags); + iiWriteBuf(pB, tempCommand, 8); + WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags); + + CHANNEL_OF(tempCommand) = 0; + PTYPE_OF(tempCommand) = PTYPE_BYPASS; + CMD_COUNT_OF(tempCommand) = 1; + (CMD_OF(tempCommand))[0] = 84; /* get BOX_IDS */ + iiWriteBuf(pB, tempCommand, 3); + +#ifdef XXX + // enable heartbeat for test porpoises + CHANNEL_OF(tempCommand) = 0; + PTYPE_OF(tempCommand) = PTYPE_BYPASS; + CMD_COUNT_OF(tempCommand) = 2; + (CMD_OF(tempCommand))[0] = 44; /* get ping */ + (CMD_OF(tempCommand))[1] = 200; /* 200 ms */ + WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags); + iiWriteBuf(pB, tempCommand, 4); + WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags); +#endif + + iiEnableMailIrq(pB); + iiSendPendingMail(pB); +} + +/******************************************************************************/ +/* Interrupt Handler Section */ +/******************************************************************************/ + +static inline void +service_all_boards(void) +{ + int i; + i2eBordStrPtr pB; + + /* Service every board on the list */ + for( i = 0; i < IP2_MAX_BOARDS; ++i ) { + pB = i2BoardPtrTable[i]; + if ( pB ) { + i2ServiceBoard( pB ); + } + } +} + + +/******************************************************************************/ +/* Function: ip2_interrupt_bh(pB) */ +/* Parameters: pB - pointer to the board structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* Service the board in a bottom half interrupt handler and then */ +/* reenable the board's interrupts if it has an IRQ number */ +/* */ +/******************************************************************************/ +static void +ip2_interrupt_bh(i2eBordStrPtr pB) +{ +// pB better well be set or we have a problem! We can only get +// here from the IMMEDIATE queue. Here, we process the boards. +// Checking pB doesn't cost much and it saves us from the sanity checkers. + + bh_counter++; + + if ( pB ) { + i2ServiceBoard( pB ); + if( pB->i2eUsingIrq ) { +// Re-enable his interrupts + iiEnableMailIrq(pB); + } + } +} + + +/******************************************************************************/ +/* Function: ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs) */ +/* Parameters: irq - interrupt number */ +/* pointer to optional device ID structure */ +/* pointer to register structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* Our task here is simply to identify each board which needs servicing. */ +/* If we are queuing then, queue it to be serviced, and disable its irq */ +/* mask otherwise process the board directly. */ +/* */ +/* We could queue by IRQ but that just complicates things on both ends */ +/* with very little gain in performance (how many instructions does */ +/* it take to iterate on the immediate queue). */ +/* */ +/* */ +/******************************************************************************/ +static irqreturn_t +ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + int i; + i2eBordStrPtr pB; + int handled = 0; + + ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq ); + + /* Service just the boards on the list using this irq */ + for( i = 0; i < i2nBoards; ++i ) { + pB = i2BoardPtrTable[i]; + +// Only process those boards which match our IRQ. +// IRQ = 0 for polled boards, we won't poll "IRQ" boards + + if ( pB && (pB->i2eUsingIrq == irq) ) { + handled = 1; +#ifdef USE_IQI + + if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) { +// Disable his interrupt (will be enabled when serviced) +// This is mostly to protect from reentrancy. + iiDisableMailIrq(pB); + +// Park the board on the immediate queue for processing. + schedule_work(&pB->tqueue_interrupt); + +// Make sure the immediate queue is flagged to fire. + } +#else +// We are using immediate servicing here. This sucks and can +// cause all sorts of havoc with ppp and others. The failsafe +// check on iiSendPendingMail could also throw a hairball. + i2ServiceBoard( pB ); +#endif /* USE_IQI */ + } + } + + ++irq_counter; + + ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); + return IRQ_RETVAL(handled); +} + +/******************************************************************************/ +/* Function: ip2_poll(unsigned long arg) */ +/* Parameters: ? */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This function calls the library routine i2ServiceBoard for each board in */ +/* the board table. This is used instead of the interrupt routine when polled */ +/* mode is specified. */ +/******************************************************************************/ +static void +ip2_poll(unsigned long arg) +{ + ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 ); + + TimerOn = 0; // it's the truth but not checked in service + + // Just polled boards, IRQ = 0 will hit all non-interrupt boards. + // It will NOT poll boards handled by hard interrupts. + // The issue of queued BH interrups is handled in ip2_interrupt(). + ip2_interrupt(0, NULL, NULL); + + PollTimer.expires = POLL_TIMEOUT; + add_timer( &PollTimer ); + TimerOn = 1; + + ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); +} + +static void do_input(void *p) +{ + i2ChanStrPtr pCh = p; + unsigned long flags; + + ip2trace(CHANN, ITRC_INPUT, 21, 0 ); + + // Data input + if ( pCh->pTTY != NULL ) { + READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags) + if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) { + READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags) + i2Input( pCh ); + } else + READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags) + } else { + ip2trace(CHANN, ITRC_INPUT, 22, 0 ); + + i2InputFlush( pCh ); + } +} + +// code duplicated from n_tty (ldisc) +static inline void isig(int sig, struct tty_struct *tty, int flush) +{ + if (tty->pgrp > 0) + kill_pg(tty->pgrp, sig, 1); + if (flush || !L_NOFLSH(tty)) { + if ( tty->ldisc.flush_buffer ) + tty->ldisc.flush_buffer(tty); + i2InputFlush( tty->driver_data ); + } +} + +static void do_status(void *p) +{ + i2ChanStrPtr pCh = p; + int status; + + status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) ); + + ip2trace (CHANN, ITRC_STATUS, 21, 1, status ); + + if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) { + if ( (status & I2_BRK) ) { + // code duplicated from n_tty (ldisc) + if (I_IGNBRK(pCh->pTTY)) + goto skip_this; + if (I_BRKINT(pCh->pTTY)) { + isig(SIGINT, pCh->pTTY, 1); + goto skip_this; + } + wake_up_interruptible(&pCh->pTTY->read_wait); + } +#ifdef NEVER_HAPPENS_AS_SETUP_XXX + // and can't work because we don't know the_char + // as the_char is reported on a separate path + // The intelligent board does this stuff as setup + { + char brkf = TTY_NORMAL; + unsigned char brkc = '\0'; + unsigned char tmp; + if ( (status & I2_BRK) ) { + brkf = TTY_BREAK; + brkc = '\0'; + } + else if (status & I2_PAR) { + brkf = TTY_PARITY; + brkc = the_char; + } else if (status & I2_FRA) { + brkf = TTY_FRAME; + brkc = the_char; + } else if (status & I2_OVR) { + brkf = TTY_OVERRUN; + brkc = the_char; + } + tmp = pCh->pTTY->real_raw; + pCh->pTTY->real_raw = 0; + pCh->pTTY->ldisc.receive_buf( pCh->pTTY, &brkc, &brkf, 1 ); + pCh->pTTY->real_raw = tmp; + } +#endif /* NEVER_HAPPENS_AS_SETUP_XXX */ + } +skip_this: + + if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) { + wake_up_interruptible(&pCh->delta_msr_wait); + + if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) { + if ( status & I2_DCD ) { + if ( pCh->wopen ) { + wake_up_interruptible ( &pCh->open_wait ); + } + } else { + if (pCh->pTTY && (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) { + tty_hangup( pCh->pTTY ); + } + } + } + } + + ip2trace (CHANN, ITRC_STATUS, 26, 0 ); +} + +/******************************************************************************/ +/* Device Open/Close/Ioctl Entry Point Section */ +/******************************************************************************/ + +/******************************************************************************/ +/* Function: open_sanity_check() */ +/* Parameters: Pointer to tty structure */ +/* Pointer to file structure */ +/* Returns: Success or failure */ +/* */ +/* Description: */ +/* Verifies the structure magic numbers and cross links. */ +/******************************************************************************/ +#ifdef IP2DEBUG_OPEN +static void +open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd ) +{ + if ( pBrd->i2eValid != I2E_MAGIC ) { + printk(KERN_ERR "IP2: invalid board structure\n" ); + } else if ( pBrd != pCh->pMyBord ) { + printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n", + pCh->pMyBord ); + } else if ( pBrd->i2eChannelCnt < pCh->port_index ) { + printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index ); + } else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) { + } else { + printk(KERN_INFO "IP2: all pointers check out!\n" ); + } +} +#endif + + +/******************************************************************************/ +/* Function: ip2_open() */ +/* Parameters: Pointer to tty structure */ +/* Pointer to file structure */ +/* Returns: Success or failure */ +/* */ +/* Description: (MANDATORY) */ +/* A successful device open has to run a gauntlet of checks before it */ +/* completes. After some sanity checking and pointer setup, the function */ +/* blocks until all conditions are satisfied. It then initialises the port to */ +/* the default characteristics and returns. */ +/******************************************************************************/ +static int +ip2_open( PTTY tty, struct file *pFile ) +{ + wait_queue_t wait; + int rc = 0; + int do_clocal = 0; + i2ChanStrPtr pCh = DevTable[tty->index]; + + ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 ); + + if ( pCh == NULL ) { + return -ENODEV; + } + /* Setup pointer links in device and tty structures */ + pCh->pTTY = tty; + tty->driver_data = pCh; + +#ifdef IP2DEBUG_OPEN + printk(KERN_DEBUG \ + "IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n", + tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index); + open_sanity_check ( pCh, pCh->pMyBord ); +#endif + + i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP); + pCh->dataSetOut |= (I2_DTR | I2_RTS); + serviceOutgoingFifo( pCh->pMyBord ); + + /* Block here until the port is ready (per serial and istallion) */ + /* + * 1. If the port is in the middle of closing wait for the completion + * and then return the appropriate error. + */ + init_waitqueue_entry(&wait, current); + add_wait_queue(&pCh->close_wait, &wait); + set_current_state( TASK_INTERRUPTIBLE ); + + if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { + if ( pCh->flags & ASYNC_CLOSING ) { + schedule(); + } + if ( tty_hung_up_p(pFile) ) { + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->close_wait, &wait); + return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS; + } + } + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->close_wait, &wait); + + /* + * 3. Handle a non-blocking open of a normal port. + */ + if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<flags |= ASYNC_NORMAL_ACTIVE; + goto noblock; + } + /* + * 4. Now loop waiting for the port to be free and carrier present + * (if required). + */ + if ( tty->termios->c_cflag & CLOCAL ) + do_clocal = 1; + +#ifdef IP2DEBUG_OPEN + printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal); +#endif + + ++pCh->wopen; + + init_waitqueue_entry(&wait, current); + add_wait_queue(&pCh->open_wait, &wait); + + for(;;) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); + pCh->dataSetOut |= (I2_DTR | I2_RTS); + set_current_state( TASK_INTERRUPTIBLE ); + serviceOutgoingFifo( pCh->pMyBord ); + if ( tty_hung_up_p(pFile) ) { + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->open_wait, &wait); + return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS; + } + if (!(pCh->flags & ASYNC_CLOSING) && + (do_clocal || (pCh->dataSetIn & I2_DCD) )) { + rc = 0; + break; + } + +#ifdef IP2DEBUG_OPEN + printk(KERN_DEBUG "ASYNC_CLOSING = %s\n", + (pCh->flags & ASYNC_CLOSING)?"True":"False"); + printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n"); +#endif + ip2trace (CHANN, ITRC_OPEN, 3, 2, 0, + (pCh->flags & ASYNC_CLOSING) ); + /* check for signal */ + if (signal_pending(current)) { + rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); + break; + } + schedule(); + } + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->open_wait, &wait); + + --pCh->wopen; //why count? + + ip2trace (CHANN, ITRC_OPEN, 4, 0 ); + + if (rc != 0 ) { + return rc; + } + pCh->flags |= ASYNC_NORMAL_ACTIVE; + +noblock: + + /* first open - Assign termios structure to port */ + if ( tty->count == 1 ) { + i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); + /* Now we must send the termios settings to the loadware */ + set_params( pCh, NULL ); + } + + /* + * Now set any i2lib options. These may go away if the i2lib code ends + * up rolled into the mainline. + */ + pCh->channelOptions |= CO_NBLOCK_WRITE; + +#ifdef IP2DEBUG_OPEN + printk (KERN_DEBUG "IP2: open completed\n" ); +#endif + serviceOutgoingFifo( pCh->pMyBord ); + + ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 ); + + return 0; +} + +/******************************************************************************/ +/* Function: ip2_close() */ +/* Parameters: Pointer to tty structure */ +/* Pointer to file structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_close( PTTY tty, struct file *pFile ) +{ + i2ChanStrPtr pCh = tty->driver_data; + + if ( !pCh ) { + return; + } + + ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 ); + +#ifdef IP2DEBUG_OPEN + printk(KERN_DEBUG "IP2:close %s:\n",tty->name); +#endif + + if ( tty_hung_up_p ( pFile ) ) { + + ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 ); + + return; + } + if ( tty->count > 1 ) { /* not the last close */ + + ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 ); + + return; + } + pCh->flags |= ASYNC_CLOSING; // last close actually + + tty->closing = 1; + + if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) { + /* + * Before we drop DTR, make sure the transmitter has completely drained. + * This uses an timeout, after which the close + * completes. + */ + ip2_wait_until_sent(tty, pCh->ClosingWaitTime ); + } + /* + * At this point we stop accepting input. Here we flush the channel + * input buffer which will allow the board to send up more data. Any + * additional input is tossed at interrupt/poll time. + */ + i2InputFlush( pCh ); + + /* disable DSS reporting */ + i2QueueCommands(PTYPE_INLINE, pCh, 100, 4, + CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); + if ( !tty || (tty->termios->c_cflag & HUPCL) ) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); + pCh->dataSetOut &= ~(I2_DTR | I2_RTS); + i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); + } + + serviceOutgoingFifo ( pCh->pMyBord ); + + if ( tty->driver->flush_buffer ) + tty->driver->flush_buffer(tty); + if ( tty->ldisc.flush_buffer ) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + + pCh->pTTY = NULL; + + if (pCh->wopen) { + if (pCh->ClosingDelay) { + msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay)); + } + wake_up_interruptible(&pCh->open_wait); + } + + pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + wake_up_interruptible(&pCh->close_wait); + +#ifdef IP2DEBUG_OPEN + DBG_CNT("ip2_close: after wakeups--"); +#endif + + + ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 ); + + return; +} + +/******************************************************************************/ +/* Function: ip2_hangup() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_hangup ( PTTY tty ) +{ + i2ChanStrPtr pCh = tty->driver_data; + + if( !pCh ) { + return; + } + + ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 ); + + ip2_flush_buffer(tty); + + /* disable DSS reporting */ + + i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP); + i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); + if ( (tty->termios->c_cflag & HUPCL) ) { + i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN); + pCh->dataSetOut &= ~(I2_DTR | I2_RTS); + i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); + } + i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, + CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); + serviceOutgoingFifo ( pCh->pMyBord ); + + wake_up_interruptible ( &pCh->delta_msr_wait ); + + pCh->flags &= ~ASYNC_NORMAL_ACTIVE; + pCh->pTTY = NULL; + wake_up_interruptible ( &pCh->open_wait ); + + ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 ); +} + +/******************************************************************************/ +/******************************************************************************/ +/* Device Output Section */ +/******************************************************************************/ +/******************************************************************************/ + +/******************************************************************************/ +/* Function: ip2_write() */ +/* Parameters: Pointer to tty structure */ +/* Flag denoting data is in user (1) or kernel (0) space */ +/* Pointer to data */ +/* Number of bytes to write */ +/* Returns: Number of bytes actually written */ +/* */ +/* Description: (MANDATORY) */ +/* */ +/* */ +/******************************************************************************/ +static int +ip2_write( PTTY tty, const unsigned char *pData, int count) +{ + i2ChanStrPtr pCh = tty->driver_data; + int bytesSent = 0; + unsigned long flags; + + ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 ); + + /* Flush out any buffered data left over from ip2_putchar() calls. */ + ip2_flush_chars( tty ); + + /* This is the actual move bit. Make sure it does what we need!!!!! */ + WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); + bytesSent = i2Output( pCh, pData, count, 0 ); + WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); + + ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent ); + + return bytesSent > 0 ? bytesSent : 0; +} + +/******************************************************************************/ +/* Function: ip2_putchar() */ +/* Parameters: Pointer to tty structure */ +/* Character to write */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_putchar( PTTY tty, unsigned char ch ) +{ + i2ChanStrPtr pCh = tty->driver_data; + unsigned long flags; + +// ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch ); + + WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); + pCh->Pbuf[pCh->Pbuf_stuff++] = ch; + if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) { + WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); + ip2_flush_chars( tty ); + } else + WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); + +// ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch ); +} + +/******************************************************************************/ +/* Function: ip2_flush_chars() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/******************************************************************************/ +static void +ip2_flush_chars( PTTY tty ) +{ + int strip; + i2ChanStrPtr pCh = tty->driver_data; + unsigned long flags; + + WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); + if ( pCh->Pbuf_stuff ) { + +// ip2trace (CHANN, ITRC_PUTC, 10, 1, strip ); + + // + // We may need to restart i2Output if it does not fullfill this request + // + strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff, 0 ); + if ( strip != pCh->Pbuf_stuff ) { + memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip ); + } + pCh->Pbuf_stuff -= strip; + } + WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); +} + +/******************************************************************************/ +/* Function: ip2_write_room() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Number of bytes that the driver can accept */ +/* */ +/* Description: */ +/* */ +/******************************************************************************/ +static int +ip2_write_room ( PTTY tty ) +{ + int bytesFree; + i2ChanStrPtr pCh = tty->driver_data; + unsigned long flags; + + READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); + bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff; + READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); + + ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree ); + + return ((bytesFree > 0) ? bytesFree : 0); +} + +/******************************************************************************/ +/* Function: ip2_chars_in_buf() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Number of bytes queued for transmission */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static int +ip2_chars_in_buf ( PTTY tty ) +{ + i2ChanStrPtr pCh = tty->driver_data; + int rc; + unsigned long flags; + + ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff ); + +#ifdef IP2DEBUG_WRITE + printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n", + pCh->Obuf_char_count + pCh->Pbuf_stuff, + pCh->Obuf_char_count, pCh->Pbuf_stuff ); +#endif + READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags); + rc = pCh->Obuf_char_count; + READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags); + READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); + rc += pCh->Pbuf_stuff; + READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); + return rc; +} + +/******************************************************************************/ +/* Function: ip2_flush_buffer() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_flush_buffer( PTTY tty ) +{ + i2ChanStrPtr pCh = tty->driver_data; + unsigned long flags; + + ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 ); + +#ifdef IP2DEBUG_WRITE + printk (KERN_DEBUG "IP2: flush buffer\n" ); +#endif + WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); + pCh->Pbuf_stuff = 0; + WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); + i2FlushOutput( pCh ); + ip2_owake(tty); + + ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 ); + +} + +/******************************************************************************/ +/* Function: ip2_wait_until_sent() */ +/* Parameters: Pointer to tty structure */ +/* Timeout for wait. */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This function is used in place of the normal tty_wait_until_sent, which */ +/* only waits for the driver buffers to be empty (or rather, those buffers */ +/* reported by chars_in_buffer) which doesn't work for IP2 due to the */ +/* indeterminate number of bytes buffered on the board. */ +/******************************************************************************/ +static void +ip2_wait_until_sent ( PTTY tty, int timeout ) +{ + int i = jiffies; + i2ChanStrPtr pCh = tty->driver_data; + + tty_wait_until_sent(tty, timeout ); + if ( (i = timeout - (jiffies -i)) > 0) + i2DrainOutput( pCh, i ); +} + +/******************************************************************************/ +/******************************************************************************/ +/* Device Input Section */ +/******************************************************************************/ +/******************************************************************************/ + +/******************************************************************************/ +/* Function: ip2_throttle() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_throttle ( PTTY tty ) +{ + i2ChanStrPtr pCh = tty->driver_data; + +#ifdef IP2DEBUG_READ + printk (KERN_DEBUG "IP2: throttle\n" ); +#endif + /* + * Signal the poll/interrupt handlers not to forward incoming data to + * the line discipline. This will cause the buffers to fill up in the + * library and thus cause the library routines to send the flow control + * stuff. + */ + pCh->throttled = 1; +} + +/******************************************************************************/ +/* Function: ip2_unthrottle() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_unthrottle ( PTTY tty ) +{ + i2ChanStrPtr pCh = tty->driver_data; + unsigned long flags; + +#ifdef IP2DEBUG_READ + printk (KERN_DEBUG "IP2: unthrottle\n" ); +#endif + + /* Pass incoming data up to the line discipline again. */ + pCh->throttled = 0; + i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); + serviceOutgoingFifo( pCh->pMyBord ); + READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags) + if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) { + READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags) +#ifdef IP2DEBUG_READ + printk (KERN_DEBUG "i2Input called from unthrottle\n" ); +#endif + i2Input( pCh ); + } else + READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags) +} + +static void +ip2_start ( PTTY tty ) +{ + i2ChanStrPtr pCh = DevTable[tty->index]; + + i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND); + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME); +#ifdef IP2DEBUG_WRITE + printk (KERN_DEBUG "IP2: start tx\n" ); +#endif +} + +static void +ip2_stop ( PTTY tty ) +{ + i2ChanStrPtr pCh = DevTable[tty->index]; + + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND); +#ifdef IP2DEBUG_WRITE + printk (KERN_DEBUG "IP2: stop tx\n" ); +#endif +} + +/******************************************************************************/ +/* Device Ioctl Section */ +/******************************************************************************/ + +static int ip2_tiocmget(struct tty_struct *tty, struct file *file) +{ + i2ChanStrPtr pCh = DevTable[tty->index]; +#ifdef ENABLE_DSSNOW + wait_queue_t wait; +#endif + + if (pCh == NULL) + return -ENODEV; + +/* + FIXME - the following code is causing a NULL pointer dereference in + 2.3.51 in an interrupt handler. It's suppose to prompt the board + to return the DSS signal status immediately. Why doesn't it do + the same thing in 2.2.14? +*/ + +/* This thing is still busted in the 1.2.12 driver on 2.4.x + and even hoses the serial console so the oops can be trapped. + /\/\|=mhw=|\/\/ */ + +#ifdef ENABLE_DSSNOW + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW); + + init_waitqueue_entry(&wait, current); + add_wait_queue(&pCh->dss_now_wait, &wait); + set_current_state( TASK_INTERRUPTIBLE ); + + serviceOutgoingFifo( pCh->pMyBord ); + + schedule(); + + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->dss_now_wait, &wait); + + if (signal_pending(current)) { + return -EINTR; + } +#endif + return ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0) + | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0) + | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0) + | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0) + | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0) + | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0); +} + +static int ip2_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + i2ChanStrPtr pCh = DevTable[tty->index]; + + if (pCh == NULL) + return -ENODEV; + + if (set & TIOCM_RTS) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP); + pCh->dataSetOut |= I2_RTS; + } + if (set & TIOCM_DTR) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP); + pCh->dataSetOut |= I2_DTR; + } + + if (clear & TIOCM_RTS) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN); + pCh->dataSetOut &= ~I2_RTS; + } + if (clear & TIOCM_DTR) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN); + pCh->dataSetOut &= ~I2_DTR; + } + serviceOutgoingFifo( pCh->pMyBord ); + return 0; +} + +/******************************************************************************/ +/* Function: ip2_ioctl() */ +/* Parameters: Pointer to tty structure */ +/* Pointer to file structure */ +/* Command */ +/* Argument */ +/* Returns: Success or failure */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static int +ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) +{ + wait_queue_t wait; + i2ChanStrPtr pCh = DevTable[tty->index]; + i2eBordStrPtr pB; + struct async_icount cprev, cnow; /* kernel counter temps */ + struct serial_icounter_struct __user *p_cuser; + int rc = 0; + unsigned long flags; + void __user *argp = (void __user *)arg; + + if ( pCh == NULL ) + return -ENODEV; + + pB = pCh->pMyBord; + + ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg ); + +#ifdef IP2DEBUG_IOCTL + printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg ); +#endif + + switch(cmd) { + case TIOCGSERIAL: + + ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc ); + + rc = get_serial_info(pCh, argp); + if (rc) + return rc; + break; + + case TIOCSSERIAL: + + ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc ); + + rc = set_serial_info(pCh, argp); + if (rc) + return rc; + break; + + case TCXONC: + rc = tty_check_change(tty); + if (rc) + return rc; + switch (arg) { + case TCOOFF: + //return -ENOIOCTLCMD; + break; + case TCOON: + //return -ENOIOCTLCMD; + break; + case TCIOFF: + if (STOP_CHAR(tty) != __DISABLED_CHAR) { + i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, + CMD_XMIT_NOW(STOP_CHAR(tty))); + } + break; + case TCION: + if (START_CHAR(tty) != __DISABLED_CHAR) { + i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, + CMD_XMIT_NOW(START_CHAR(tty))); + } + break; + default: + return -EINVAL; + } + return 0; + + case TCSBRK: /* SVID version: non-zero arg --> no break */ + rc = tty_check_change(tty); + + ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc ); + + if (!rc) { + ip2_wait_until_sent(tty,0); + if (!arg) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250)); + serviceOutgoingFifo( pCh->pMyBord ); + } + } + break; + + case TCSBRKP: /* support for POSIX tcsendbreak() */ + rc = tty_check_change(tty); + + ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc ); + + if (!rc) { + ip2_wait_until_sent(tty,0); + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, + CMD_SEND_BRK(arg ? arg*100 : 250)); + serviceOutgoingFifo ( pCh->pMyBord ); + } + break; + + case TIOCGSOFTCAR: + + ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc ); + + rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); + if (rc) + return rc; + break; + + case TIOCSSOFTCAR: + + ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc ); + + rc = get_user(arg,(unsigned long __user *) argp); + if (rc) + return rc; + tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) + | (arg ? CLOCAL : 0)); + + break; + + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask + * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS + * for masking). Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags); + cprev = pCh->icount; /* note the counters on entry */ + WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags); + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, + CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP); + init_waitqueue_entry(&wait, current); + add_wait_queue(&pCh->delta_msr_wait, &wait); + set_current_state( TASK_INTERRUPTIBLE ); + + serviceOutgoingFifo( pCh->pMyBord ); + for(;;) { + ip2trace (CHANN, ITRC_IOCTL, 10, 0 ); + + schedule(); + + ip2trace (CHANN, ITRC_IOCTL, 11, 0 ); + + /* see if a signal did it */ + if (signal_pending(current)) { + rc = -ERESTARTSYS; + break; + } + WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags); + cnow = pCh->icount; /* atomic copy */ + WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags); + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { + rc = -EIO; /* no change => rc */ + break; + } + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { + rc = 0; + break; + } + cprev = cnow; + } + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->delta_msr_wait, &wait); + + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, + CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); + if ( ! (pCh->flags & ASYNC_CHECK_CD)) { + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP); + } + serviceOutgoingFifo( pCh->pMyBord ); + return rc; + break; + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for RI where + * only 0->1 is counted. The controller is quite capable of counting + * both, but this done to preserve compatibility with the standard + * serial driver. + */ + case TIOCGICOUNT: + ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc ); + + WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags); + cnow = pCh->icount; + WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags); + p_cuser = argp; + rc = put_user(cnow.cts, &p_cuser->cts); + rc = put_user(cnow.dsr, &p_cuser->dsr); + rc = put_user(cnow.rng, &p_cuser->rng); + rc = put_user(cnow.dcd, &p_cuser->dcd); + rc = put_user(cnow.rx, &p_cuser->rx); + rc = put_user(cnow.tx, &p_cuser->tx); + rc = put_user(cnow.frame, &p_cuser->frame); + rc = put_user(cnow.overrun, &p_cuser->overrun); + rc = put_user(cnow.parity, &p_cuser->parity); + rc = put_user(cnow.brk, &p_cuser->brk); + rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); + break; + + /* + * The rest are not supported by this driver. By returning -ENOIOCTLCMD they + * will be passed to the line discipline for it to handle. + */ + case TIOCSERCONFIG: + case TIOCSERGWILD: + case TIOCSERGETLSR: + case TIOCSERSWILD: + case TIOCSERGSTRUCT: + case TIOCSERGETMULTI: + case TIOCSERSETMULTI: + + default: + ip2trace (CHANN, ITRC_IOCTL, 12, 0 ); + + rc = -ENOIOCTLCMD; + break; + } + + ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 ); + + return rc; +} + +/******************************************************************************/ +/* Function: GetSerialInfo() */ +/* Parameters: Pointer to channel structure */ +/* Pointer to old termios structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This is to support the setserial command, and requires processing of the */ +/* standard Linux serial structure. */ +/******************************************************************************/ +static int +get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo ) +{ + struct serial_struct tmp; + + memset ( &tmp, 0, sizeof(tmp) ); + tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16]; + if (BID_HAS_654(tmp.type)) { + tmp.type = PORT_16650; + } else { + tmp.type = PORT_CIRRUS; + } + tmp.line = pCh->port_index; + tmp.port = pCh->pMyBord->i2eBase; + tmp.irq = ip2config.irq[pCh->port_index/64]; + tmp.flags = pCh->flags; + tmp.baud_base = pCh->BaudBase; + tmp.close_delay = pCh->ClosingDelay; + tmp.closing_wait = pCh->ClosingWaitTime; + tmp.custom_divisor = pCh->BaudDivisor; + return copy_to_user(retinfo,&tmp,sizeof(*retinfo)); +} + +/******************************************************************************/ +/* Function: SetSerialInfo() */ +/* Parameters: Pointer to channel structure */ +/* Pointer to old termios structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This function provides support for setserial, which uses the TIOCSSERIAL */ +/* ioctl. Not all setserial parameters are relevant. If the user attempts to */ +/* change the IRQ, address or type of the port the ioctl fails. */ +/******************************************************************************/ +static int +set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info ) +{ + struct serial_struct ns; + int old_flags, old_baud_divisor; + + if (copy_from_user(&ns, new_info, sizeof (ns))) + return -EFAULT; + + /* + * We don't allow setserial to change IRQ, board address, type or baud + * base. Also line nunber as such is meaningless but we use it for our + * array index so it is fixed also. + */ + if ( (ns.irq != ip2config.irq[pCh->port_index]) + || ((int) ns.port != ((int) (pCh->pMyBord->i2eBase))) + || (ns.baud_base != pCh->BaudBase) + || (ns.line != pCh->port_index) ) { + return -EINVAL; + } + + old_flags = pCh->flags; + old_baud_divisor = pCh->BaudDivisor; + + if ( !capable(CAP_SYS_ADMIN) ) { + if ( ( ns.close_delay != pCh->ClosingDelay ) || + ( (ns.flags & ~ASYNC_USR_MASK) != + (pCh->flags & ~ASYNC_USR_MASK) ) ) { + return -EPERM; + } + + pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) | + (ns.flags & ASYNC_USR_MASK); + pCh->BaudDivisor = ns.custom_divisor; + } else { + pCh->flags = (pCh->flags & ~ASYNC_FLAGS) | + (ns.flags & ASYNC_FLAGS); + pCh->BaudDivisor = ns.custom_divisor; + pCh->ClosingDelay = ns.close_delay * HZ/100; + pCh->ClosingWaitTime = ns.closing_wait * HZ/100; + } + + if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) ) + || (old_baud_divisor != pCh->BaudDivisor) ) { + // Invalidate speed and reset parameters + set_params( pCh, NULL ); + } + + return 0; +} + +/******************************************************************************/ +/* Function: ip2_set_termios() */ +/* Parameters: Pointer to tty structure */ +/* Pointer to old termios structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_set_termios( PTTY tty, struct termios *old_termios ) +{ + i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data; + +#ifdef IP2DEBUG_IOCTL + printk (KERN_DEBUG "IP2: set termios %p\n", old_termios ); +#endif + + set_params( pCh, old_termios ); +} + +/******************************************************************************/ +/* Function: ip2_set_line_discipline() */ +/* Parameters: Pointer to tty structure */ +/* Returns: Nothing */ +/* */ +/* Description: Does nothing */ +/* */ +/* */ +/******************************************************************************/ +static void +ip2_set_line_discipline ( PTTY tty ) +{ +#ifdef IP2DEBUG_IOCTL + printk (KERN_DEBUG "IP2: set line discipline\n" ); +#endif + + ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 ); + +} + +/******************************************************************************/ +/* Function: SetLine Characteristics() */ +/* Parameters: Pointer to channel structure */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* This routine is called to update the channel structure with the new line */ +/* characteristics, and send the appropriate commands to the board when they */ +/* change. */ +/******************************************************************************/ +static void +set_params( i2ChanStrPtr pCh, struct termios *o_tios ) +{ + tcflag_t cflag, iflag, lflag; + char stop_char, start_char; + struct termios dummy; + + lflag = pCh->pTTY->termios->c_lflag; + cflag = pCh->pTTY->termios->c_cflag; + iflag = pCh->pTTY->termios->c_iflag; + + if (o_tios == NULL) { + dummy.c_lflag = ~lflag; + dummy.c_cflag = ~cflag; + dummy.c_iflag = ~iflag; + o_tios = &dummy; + } + + { + switch ( cflag & CBAUD ) { + case B0: + i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); + pCh->dataSetOut &= ~(I2_DTR | I2_RTS); + i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); + pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag); + goto service_it; + break; + case B38400: + /* + * This is the speed that is overloaded with all the other high + * speeds, depending upon the flag settings. + */ + if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) { + pCh->speed = CBR_57600; + } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) { + pCh->speed = CBR_115200; + } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) { + pCh->speed = CBR_C1; + } else { + pCh->speed = CBR_38400; + } + break; + case B50: pCh->speed = CBR_50; break; + case B75: pCh->speed = CBR_75; break; + case B110: pCh->speed = CBR_110; break; + case B134: pCh->speed = CBR_134; break; + case B150: pCh->speed = CBR_150; break; + case B200: pCh->speed = CBR_200; break; + case B300: pCh->speed = CBR_300; break; + case B600: pCh->speed = CBR_600; break; + case B1200: pCh->speed = CBR_1200; break; + case B1800: pCh->speed = CBR_1800; break; + case B2400: pCh->speed = CBR_2400; break; + case B4800: pCh->speed = CBR_4800; break; + case B9600: pCh->speed = CBR_9600; break; + case B19200: pCh->speed = CBR_19200; break; + case B57600: pCh->speed = CBR_57600; break; + case B115200: pCh->speed = CBR_115200; break; + case B153600: pCh->speed = CBR_153600; break; + case B230400: pCh->speed = CBR_230400; break; + case B307200: pCh->speed = CBR_307200; break; + case B460800: pCh->speed = CBR_460800; break; + case B921600: pCh->speed = CBR_921600; break; + default: pCh->speed = CBR_9600; break; + } + if ( pCh->speed == CBR_C1 ) { + // Process the custom speed parameters. + int bps = pCh->BaudBase / pCh->BaudDivisor; + if ( bps == 921600 ) { + pCh->speed = CBR_921600; + } else { + bps = bps/10; + i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) ); + } + } + i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed)); + + i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); + pCh->dataSetOut |= (I2_DTR | I2_RTS); + } + if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) + { + i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, + CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1)); + } + if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) + { + i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, + CMD_SETPAR( + (cflag & PARENB ? (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP) + ) + ); + } + /* byte size and parity */ + if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) + { + int datasize; + switch ( cflag & CSIZE ) { + case CS5: datasize = CSZ_5; break; + case CS6: datasize = CSZ_6; break; + case CS7: datasize = CSZ_7; break; + case CS8: datasize = CSZ_8; break; + default: datasize = CSZ_5; break; /* as per serial.c */ + } + i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) ); + } + /* Process CTS flow control flag setting */ + if ( (cflag & CRTSCTS) ) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, + 2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB); + } else { + i2QueueCommands(PTYPE_INLINE, pCh, 100, + 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); + } + // + // Process XON/XOFF flow control flags settings + // + stop_char = STOP_CHAR(pCh->pTTY); + start_char = START_CHAR(pCh->pTTY); + + //////////// can't be \000 + if (stop_char == __DISABLED_CHAR ) + { + stop_char = ~__DISABLED_CHAR; + } + if (start_char == __DISABLED_CHAR ) + { + start_char = ~__DISABLED_CHAR; + } + ///////////////////////////////// + + if ( o_tios->c_cc[VSTART] != start_char ) + { + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char)); + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char)); + } + if ( o_tios->c_cc[VSTOP] != stop_char ) + { + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char)); + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char)); + } + if (stop_char == __DISABLED_CHAR ) + { + stop_char = ~__DISABLED_CHAR; //TEST123 + goto no_xoff; + } + if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) + { + if ( iflag & IXOFF ) { // Enable XOFF output flow control + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON)); + } else { // Disable XOFF output flow control +no_xoff: + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE)); + } + } + if (start_char == __DISABLED_CHAR ) + { + goto no_xon; + } + if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) + { + if ( iflag & IXON ) { + if ( iflag & IXANY ) { // Enable XON/XANY output flow control + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY)); + } else { // Enable XON output flow control + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON)); + } + } else { // Disable XON output flow control +no_xon: + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE)); + } + } + if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) + { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, + CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0))); + } + if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) + { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, + CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB)); + } + + if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) + ^ ( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) + { + char brkrpt = 0; + char parrpt = 0; + + if ( iflag & IGNBRK ) { /* Ignore breaks altogether */ + /* Ignore breaks altogether */ + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP); + } else { + if ( iflag & BRKINT ) { + if ( iflag & PARMRK ) { + brkrpt = 0x0a; // exception an inline triple + } else { + brkrpt = 0x1a; // exception and NULL + } + brkrpt |= 0x04; // flush input + } else { + if ( iflag & PARMRK ) { + brkrpt = 0x0b; //POSIX triple \0377 \0 \0 + } else { + brkrpt = 0x01; // Null only + } + } + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt)); + } + + if (iflag & IGNPAR) { + parrpt = 0x20; + /* would be 2 for not cirrus bug */ + /* would be 0x20 cept for cirrus bug */ + } else { + if ( iflag & PARMRK ) { + /* + * Replace error characters with 3-byte sequence (\0377,\0,char) + */ + parrpt = 0x04 ; + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0)); + } else { + parrpt = 0x03; + } + } + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt)); + } + if (cflag & CLOCAL) { + // Status reporting fails for DCD if this is off + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP); + pCh->flags &= ~ASYNC_CHECK_CD; + } else { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP); + pCh->flags |= ASYNC_CHECK_CD; + } + +service_it: + i2DrainOutput( pCh, 100 ); +} + +/******************************************************************************/ +/* IPL Device Section */ +/******************************************************************************/ + +/******************************************************************************/ +/* Function: ip2_ipl_read() */ +/* Parameters: Pointer to device inode */ +/* Pointer to file structure */ +/* Pointer to data */ +/* Number of bytes to read */ +/* Returns: Success or failure */ +/* */ +/* Description: Ugly */ +/* */ +/* */ +/******************************************************************************/ + +static +ssize_t +ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off ) +{ + unsigned int minor = iminor(pFile->f_dentry->d_inode); + int rc = 0; + +#ifdef IP2DEBUG_IPL + printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count ); +#endif + + switch( minor ) { + case 0: // IPL device + rc = -EINVAL; + break; + case 1: // Status dump + rc = -EINVAL; + break; + case 2: // Ping device + rc = -EINVAL; + break; + case 3: // Trace device + rc = DumpTraceBuffer ( pData, count ); + break; + case 4: // Trace device + rc = DumpFifoBuffer ( pData, count ); + break; + default: + rc = -ENODEV; + break; + } + return rc; +} + +static int +DumpFifoBuffer ( char __user *pData, int count ) +{ +#ifdef DEBUG_FIFO + int rc; + rc = copy_to_user(pData, DBGBuf, count); + + printk(KERN_DEBUG "Last index %d\n", I ); + + return count; +#endif /* DEBUG_FIFO */ + return 0; +} + +static int +DumpTraceBuffer ( char __user *pData, int count ) +{ +#ifdef IP2DEBUG_TRACE + int rc; + int dumpcount; + int chunk; + int *pIndex = (int __user *)pData; + + if ( count < (sizeof(int) * 6) ) { + return -EIO; + } + rc = put_user(tracewrap, pIndex ); + rc = put_user(TRACEMAX, ++pIndex ); + rc = put_user(tracestrip, ++pIndex ); + rc = put_user(tracestuff, ++pIndex ); + pData += sizeof(int) * 6; + count -= sizeof(int) * 6; + + dumpcount = tracestuff - tracestrip; + if ( dumpcount < 0 ) { + dumpcount += TRACEMAX; + } + if ( dumpcount > count ) { + dumpcount = count; + } + chunk = TRACEMAX - tracestrip; + if ( dumpcount > chunk ) { + rc = copy_to_user(pData, &tracebuf[tracestrip], + chunk * sizeof(tracebuf[0]) ); + pData += chunk * sizeof(tracebuf[0]); + tracestrip = 0; + chunk = dumpcount - chunk; + } else { + chunk = dumpcount; + } + rc = copy_to_user(pData, &tracebuf[tracestrip], + chunk * sizeof(tracebuf[0]) ); + tracestrip += chunk; + tracewrap = 0; + + rc = put_user(tracestrip, ++pIndex ); + rc = put_user(tracestuff, ++pIndex ); + + return dumpcount; +#else + return 0; +#endif +} + +/******************************************************************************/ +/* Function: ip2_ipl_write() */ +/* Parameters: */ +/* Pointer to file structure */ +/* Pointer to data */ +/* Number of bytes to write */ +/* Returns: Success or failure */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static ssize_t +ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off) +{ +#ifdef IP2DEBUG_IPL + printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count ); +#endif + return 0; +} + +/******************************************************************************/ +/* Function: ip2_ipl_ioctl() */ +/* Parameters: Pointer to device inode */ +/* Pointer to file structure */ +/* Command */ +/* Argument */ +/* Returns: Success or failure */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static int +ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) +{ + unsigned int iplminor = iminor(pInode); + int rc = 0; + void __user *argp = (void __user *)arg; + ULONG __user *pIndex = argp; + i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4]; + i2ChanStrPtr pCh; + +#ifdef IP2DEBUG_IPL + printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); +#endif + + switch ( iplminor ) { + case 0: // IPL device + rc = -EINVAL; + break; + case 1: // Status dump + case 5: + case 9: + case 13: + switch ( cmd ) { + case 64: /* Driver - ip2stat */ + rc = put_user(ip2_tty_driver->refcount, pIndex++ ); + rc = put_user(irq_counter, pIndex++ ); + rc = put_user(bh_counter, pIndex++ ); + break; + + case 65: /* Board - ip2stat */ + if ( pB ) { + rc = copy_to_user(argp, pB, sizeof(i2eBordStr)); + rc = put_user(INB(pB->i2eStatus), + (ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) ); + } else { + rc = -ENODEV; + } + break; + + default: + if (cmd < IP2_MAX_PORTS) { + pCh = DevTable[cmd]; + if ( pCh ) + { + rc = copy_to_user(argp, pCh, sizeof(i2ChanStr)); + } else { + rc = -ENODEV; + } + } else { + rc = -EINVAL; + } + } + break; + + case 2: // Ping device + rc = -EINVAL; + break; + case 3: // Trace device + if ( cmd == 1 ) { + rc = put_user(iiSendPendingMail, pIndex++ ); + rc = put_user(i2InitChannels, pIndex++ ); + rc = put_user(i2QueueNeeds, pIndex++ ); + rc = put_user(i2QueueCommands, pIndex++ ); + rc = put_user(i2GetStatus, pIndex++ ); + rc = put_user(i2Input, pIndex++ ); + rc = put_user(i2InputFlush, pIndex++ ); + rc = put_user(i2Output, pIndex++ ); + rc = put_user(i2FlushOutput, pIndex++ ); + rc = put_user(i2DrainWakeup, pIndex++ ); + rc = put_user(i2DrainOutput, pIndex++ ); + rc = put_user(i2OutputFree, pIndex++ ); + rc = put_user(i2StripFifo, pIndex++ ); + rc = put_user(i2StuffFifoBypass, pIndex++ ); + rc = put_user(i2StuffFifoFlow, pIndex++ ); + rc = put_user(i2StuffFifoInline, pIndex++ ); + rc = put_user(i2ServiceBoard, pIndex++ ); + rc = put_user(serviceOutgoingFifo, pIndex++ ); + // rc = put_user(ip2_init, pIndex++ ); + rc = put_user(ip2_init_board, pIndex++ ); + rc = put_user(find_eisa_board, pIndex++ ); + rc = put_user(set_irq, pIndex++ ); + rc = put_user(ip2_interrupt, pIndex++ ); + rc = put_user(ip2_poll, pIndex++ ); + rc = put_user(service_all_boards, pIndex++ ); + rc = put_user(do_input, pIndex++ ); + rc = put_user(do_status, pIndex++ ); +#ifndef IP2DEBUG_OPEN + rc = put_user(0, pIndex++ ); +#else + rc = put_user(open_sanity_check, pIndex++ ); +#endif + rc = put_user(ip2_open, pIndex++ ); + rc = put_user(ip2_close, pIndex++ ); + rc = put_user(ip2_hangup, pIndex++ ); + rc = put_user(ip2_write, pIndex++ ); + rc = put_user(ip2_putchar, pIndex++ ); + rc = put_user(ip2_flush_chars, pIndex++ ); + rc = put_user(ip2_write_room, pIndex++ ); + rc = put_user(ip2_chars_in_buf, pIndex++ ); + rc = put_user(ip2_flush_buffer, pIndex++ ); + + //rc = put_user(ip2_wait_until_sent, pIndex++ ); + rc = put_user(0, pIndex++ ); + + rc = put_user(ip2_throttle, pIndex++ ); + rc = put_user(ip2_unthrottle, pIndex++ ); + rc = put_user(ip2_ioctl, pIndex++ ); + rc = put_user(0, pIndex++ ); + rc = put_user(get_serial_info, pIndex++ ); + rc = put_user(set_serial_info, pIndex++ ); + rc = put_user(ip2_set_termios, pIndex++ ); + rc = put_user(ip2_set_line_discipline, pIndex++ ); + rc = put_user(set_params, pIndex++ ); + } else { + rc = -EINVAL; + } + + break; + + default: + rc = -ENODEV; + break; + } + return rc; +} + +/******************************************************************************/ +/* Function: ip2_ipl_open() */ +/* Parameters: Pointer to device inode */ +/* Pointer to file structure */ +/* Returns: Success or failure */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +static int +ip2_ipl_open( struct inode *pInode, struct file *pFile ) +{ + unsigned int iplminor = iminor(pInode); + i2eBordStrPtr pB; + i2ChanStrPtr pCh; + +#ifdef IP2DEBUG_IPL + printk (KERN_DEBUG "IP2IPL: open\n" ); +#endif + + switch(iplminor) { + // These are the IPL devices + case 0: + case 4: + case 8: + case 12: + break; + + // These are the status devices + case 1: + case 5: + case 9: + case 13: + break; + + // These are the debug devices + case 2: + case 6: + case 10: + case 14: + pB = i2BoardPtrTable[iplminor / 4]; + pCh = (i2ChanStrPtr) pB->i2eChannelPtr; + break; + + // This is the trace device + case 3: + break; + } + return 0; +} +/******************************************************************************/ +/* Function: ip2_read_procmem */ +/* Parameters: */ +/* */ +/* Returns: Length of output */ +/* */ +/* Description: */ +/* Supplies some driver operating parameters */ +/* Not real useful unless your debugging the fifo */ +/* */ +/******************************************************************************/ + +#define LIMIT (PAGE_SIZE - 120) + +static int +ip2_read_procmem(char *buf, char **start, off_t offset, int len) +{ + i2eBordStrPtr pB; + i2ChanStrPtr pCh; + PTTY tty; + int i; + + len = 0; + +#define FMTLINE "%3d: 0x%08x 0x%08x 0%011o 0%011o\n" +#define FMTLIN2 " 0x%04x 0x%04x tx flow 0x%x\n" +#define FMTLIN3 " 0x%04x 0x%04x rc flow\n" + + len += sprintf(buf+len,"\n"); + + for( i = 0; i < IP2_MAX_BOARDS; ++i ) { + pB = i2BoardPtrTable[i]; + if ( pB ) { + len += sprintf(buf+len,"board %d:\n",i); + len += sprintf(buf+len,"\tFifo rem: %d mty: %x outM %x\n", + pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting); + } + } + + len += sprintf(buf+len,"#: tty flags, port flags, cflags, iflags\n"); + for (i=0; i < IP2_MAX_PORTS; i++) { + if (len > LIMIT) + break; + pCh = DevTable[i]; + if (pCh) { + tty = pCh->pTTY; + if (tty && tty->count) { + len += sprintf(buf+len,FMTLINE,i,(int)tty->flags,pCh->flags, + tty->termios->c_cflag,tty->termios->c_iflag); + + len += sprintf(buf+len,FMTLIN2, + pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds); + len += sprintf(buf+len,FMTLIN3,pCh->infl.asof,pCh->infl.room); + } + } + } + return len; +} + +/* + * This is the handler for /proc/tty/driver/ip2 + * + * This stretch of code has been largely plagerized from at least three + * different sources including ip2mkdev.c and a couple of other drivers. + * The bugs are all mine. :-) =mhw= + */ +static int ip2_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int i, j, box; + int len = 0; + int boxes = 0; + int ports = 0; + int tports = 0; + off_t begin = 0; + i2eBordStrPtr pB; + + len += sprintf(page, "ip2info: 1.0 driver: %s\n", pcVersion ); + len += sprintf(page+len, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", + IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, + IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); + + for( i = 0; i < IP2_MAX_BOARDS; ++i ) { + /* This need to be reset for a board by board count... */ + boxes = 0; + pB = i2BoardPtrTable[i]; + if( pB ) { + switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) + { + case POR_ID_FIIEX: + len += sprintf( page+len, "Board %d: EX ports=", i ); + for( box = 0; box < ABS_MAX_BOXES; ++box ) + { + ports = 0; + + if( pB->i2eChannelMap[box] != 0 ) ++boxes; + for( j = 0; j < ABS_BIGGEST_BOX; ++j ) + { + if( pB->i2eChannelMap[box] & 1<< j ) { + ++ports; + } + } + len += sprintf( page+len, "%d,", ports ); + tports += ports; + } + + --len; /* Backup over that last comma */ + + len += sprintf( page+len, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8 ); + break; + + case POR_ID_II_4: + len += sprintf(page+len, "Board %d: ISA-4 ports=4 boxes=1", i ); + tports = ports = 4; + break; + + case POR_ID_II_8: + len += sprintf(page+len, "Board %d: ISA-8-std ports=8 boxes=1", i ); + tports = ports = 8; + break; + + case POR_ID_II_8R: + len += sprintf(page+len, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i ); + tports = ports = 8; + break; + + default: + len += sprintf(page+len, "Board %d: unknown", i ); + /* Don't try and probe for minor numbers */ + tports = ports = 0; + } + + } else { + /* Don't try and probe for minor numbers */ + len += sprintf(page+len, "Board %d: vacant", i ); + tports = ports = 0; + } + + if( tports ) { + len += sprintf(page+len, " minors=" ); + + for ( box = 0; box < ABS_MAX_BOXES; ++box ) + { + for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) + { + if ( pB->i2eChannelMap[box] & (1 << j) ) + { + len += sprintf (page+len,"%d,", + j + ABS_BIGGEST_BOX * + (box+i*ABS_MAX_BOXES)); + } + } + } + + page[ len - 1 ] = '\n'; /* Overwrite that last comma */ + } else { + len += sprintf (page+len,"\n" ); + } + + if (len+begin > off+count) + break; + if (len+begin < off) { + begin += len; + len = 0; + } + } + + if (i >= IP2_MAX_BOARDS) + *eof = 1; + if (off >= len+begin) + return 0; + + *start = page + (off-begin); + return ((count < begin+len-off) ? count : begin+len-off); + } + +/******************************************************************************/ +/* Function: ip2trace() */ +/* Parameters: Value to add to trace buffer */ +/* Returns: Nothing */ +/* */ +/* Description: */ +/* */ +/* */ +/******************************************************************************/ +#ifdef IP2DEBUG_TRACE +void +ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...) +{ + long flags; + unsigned long *pCode = &codes; + union ip2breadcrumb bc; + i2ChanStrPtr pCh; + + + tracebuf[tracestuff++] = jiffies; + if ( tracestuff == TRACEMAX ) { + tracestuff = 0; + } + if ( tracestuff == tracestrip ) { + if ( ++tracestrip == TRACEMAX ) { + tracestrip = 0; + } + ++tracewrap; + } + + bc.hdr.port = 0xff & pn; + bc.hdr.cat = cat; + bc.hdr.codes = (unsigned char)( codes & 0xff ); + bc.hdr.label = label; + tracebuf[tracestuff++] = bc.value; + + for (;;) { + if ( tracestuff == TRACEMAX ) { + tracestuff = 0; + } + if ( tracestuff == tracestrip ) { + if ( ++tracestrip == TRACEMAX ) { + tracestrip = 0; + } + ++tracewrap; + } + + if ( !codes-- ) + break; + + tracebuf[tracestuff++] = *++pCode; + } +} +#endif + + +MODULE_LICENSE("GPL"); diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c deleted file mode 100644 index 56e93a5a1e24..000000000000 --- a/drivers/char/ip2main.c +++ /dev/null @@ -1,3260 +0,0 @@ -/* -* -* (c) 1999 by Computone Corporation -* -******************************************************************************** -* -* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport -* serial I/O controllers. -* -* DESCRIPTION: Mainline code for the device driver -* -*******************************************************************************/ -// ToDo: -// -// Fix the immediate DSS_NOW problem. -// Work over the channel stats return logic in ip2_ipl_ioctl so they -// make sense for all 256 possible channels and so the user space -// utilities will compile and work properly. -// -// Done: -// -// 1.2.14 /\/\|=mhw=|\/\/ -// Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts. -// Changed the definition of ip2trace to be more consistent with kernel style -// Thanks to Andreas Dilger for these updates -// -// 1.2.13 /\/\|=mhw=|\/\/ -// DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform -// to agreed devfs serial device naming convention. -// -// 1.2.12 /\/\|=mhw=|\/\/ -// Cleaned up some remove queue cut and paste errors -// -// 1.2.11 /\/\|=mhw=|\/\/ -// Clean up potential NULL pointer dereferences -// Clean up devfs registration -// Add kernel command line parsing for io and irq -// Compile defaults for io and irq are now set in ip2.c not ip2/ip2.h! -// Reworked poll_only hack for explicit parameter setting -// You must now EXPLICITLY set poll_only = 1 or set all irqs to 0 -// Merged ip2_loadmain and old_ip2_init -// Converted all instances of interruptible_sleep_on into queue calls -// Most of these had no race conditions but better to clean up now -// -// 1.2.10 /\/\|=mhw=|\/\/ -// Fixed the bottom half interrupt handler and enabled USE_IQI -// to split the interrupt handler into a formal top-half / bottom-half -// Fixed timing window on high speed processors that queued messages to -// the outbound mail fifo faster than the board could handle. -// -// 1.2.9 -// Four box EX was barfing on >128k kmalloc, made structure smaller by -// reducing output buffer size -// -// 1.2.8 -// Device file system support (MHW) -// -// 1.2.7 -// Fixed -// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules -// -// 1.2.6 -//Fixes DCD problems -// DCD was not reported when CLOCAL was set on call to TIOCMGET -// -//Enhancements: -// TIOCMGET requests and waits for status return -// No DSS interrupts enabled except for DCD when needed -// -// For internal use only -// -//#define IP2DEBUG_INIT -//#define IP2DEBUG_OPEN -//#define IP2DEBUG_WRITE -//#define IP2DEBUG_READ -//#define IP2DEBUG_IOCTL -//#define IP2DEBUG_IPL - -//#define IP2DEBUG_TRACE -//#define DEBUG_FIFO - -/************/ -/* Includes */ -/************/ -#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 "./ip2/ip2types.h" -#include "./ip2/ip2trace.h" -#include "./ip2/ip2ioctl.h" -#include "./ip2/ip2.h" -#include "./ip2/i2ellis.h" -#include "./ip2/i2lib.h" - -/***************** - * /proc/ip2mem * - *****************/ - -#include - -static int ip2_read_procmem(char *, char **, off_t, int); -static int ip2_read_proc(char *, char **, off_t, int, int *, void * ); - -/********************/ -/* Type Definitions */ -/********************/ - -/*************/ -/* Constants */ -/*************/ - -/* String constants to identify ourselves */ -static char *pcName = "Computone IntelliPort Plus multiport driver"; -static char *pcVersion = "1.2.14"; - -/* String constants for port names */ -static char *pcDriver_name = "ip2"; -static char *pcIpl = "ip2ipl"; - -/* Serial subtype definitions */ -#define SERIAL_TYPE_NORMAL 1 - -// cheezy kludge or genius - you decide? -int ip2_loadmain(int *, int *, unsigned char *, int); -static unsigned char *Fip_firmware; -static int Fip_firmware_size; - -/***********************/ -/* Function Prototypes */ -/***********************/ - -/* Global module entry functions */ - -/* Private (static) functions */ -static int ip2_open(PTTY, struct file *); -static void ip2_close(PTTY, struct file *); -static int ip2_write(PTTY, const unsigned char *, int); -static void ip2_putchar(PTTY, unsigned char); -static void ip2_flush_chars(PTTY); -static int ip2_write_room(PTTY); -static int ip2_chars_in_buf(PTTY); -static void ip2_flush_buffer(PTTY); -static int ip2_ioctl(PTTY, struct file *, UINT, ULONG); -static void ip2_set_termios(PTTY, struct termios *); -static void ip2_set_line_discipline(PTTY); -static void ip2_throttle(PTTY); -static void ip2_unthrottle(PTTY); -static void ip2_stop(PTTY); -static void ip2_start(PTTY); -static void ip2_hangup(PTTY); -static int ip2_tiocmget(struct tty_struct *tty, struct file *file); -static int ip2_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear); - -static void set_irq(int, int); -static void ip2_interrupt_bh(i2eBordStrPtr pB); -static irqreturn_t ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs); -static void ip2_poll(unsigned long arg); -static inline void service_all_boards(void); -static void do_input(void *p); -static void do_status(void *p); - -static void ip2_wait_until_sent(PTTY,int); - -static void set_params (i2ChanStrPtr, struct termios *); -static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *); -static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); - -static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); -static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); -static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG); -static int ip2_ipl_open(struct inode *, struct file *); - -static int DumpTraceBuffer(char __user *, int); -static int DumpFifoBuffer( char __user *, int); - -static void ip2_init_board(int); -static unsigned short find_eisa_board(int); - -/***************/ -/* Static Data */ -/***************/ - -static struct tty_driver *ip2_tty_driver; - -/* Here, then is a table of board pointers which the interrupt routine should - * scan through to determine who it must service. - */ -static unsigned short i2nBoards; // Number of boards here - -static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS]; - -static i2ChanStrPtr DevTable[IP2_MAX_PORTS]; -//DevTableMem just used to save addresses for kfree -static void *DevTableMem[IP2_MAX_BOARDS]; - -/* This is the driver descriptor for the ip2ipl device, which is used to - * download the loadware to the boards. - */ -static struct file_operations ip2_ipl = { - .owner = THIS_MODULE, - .read = ip2_ipl_read, - .write = ip2_ipl_write, - .ioctl = ip2_ipl_ioctl, - .open = ip2_ipl_open, -}; - -static unsigned long irq_counter = 0; -static unsigned long bh_counter = 0; - -// Use immediate queue to service interrupts -#define USE_IQI -//#define USE_IQ // PCI&2.2 needs work - -/* The timer_list entry for our poll routine. If interrupt operation is not - * selected, the board is serviced periodically to see if anything needs doing. - */ -#define POLL_TIMEOUT (jiffies + 1) -static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); -static char TimerOn; - -#ifdef IP2DEBUG_TRACE -/* Trace (debug) buffer data */ -#define TRACEMAX 1000 -static unsigned long tracebuf[TRACEMAX]; -static int tracestuff; -static int tracestrip; -static int tracewrap; -#endif - -/**********/ -/* Macros */ -/**********/ - -#if defined(MODULE) && defined(IP2DEBUG_OPEN) -#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \ - tty->name,(pCh->flags),ip2_tty_driver->refcount, \ - tty->count,/*GET_USE_COUNT(module)*/0,s) -#else -#define DBG_CNT(s) -#endif - -/********/ -/* Code */ -/********/ - -#include "./ip2/i2ellis.c" /* Extremely low-level interface services */ -#include "./ip2/i2cmd.c" /* Standard loadware command definitions */ -#include "./ip2/i2lib.c" /* High level interface services */ - -/* Configuration area for modprobe */ - -MODULE_AUTHOR("Doug McNash"); -MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); - -static int poll_only = 0; - -static int Eisa_irq; -static int Eisa_slot; - -static int iindx; -static char rirqs[IP2_MAX_BOARDS]; -static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; - -/* for sysfs class support */ -static struct class *ip2_class; - -// Some functions to keep track of what irq's we have - -static int __init -is_valid_irq(int irq) -{ - int *i = Valid_Irqs; - - while ((*i != 0) && (*i != irq)) { - i++; - } - return (*i); -} - -static void __init -mark_requested_irq( char irq ) -{ - rirqs[iindx++] = irq; -} - -#ifdef MODULE -static int __init -clear_requested_irq( char irq ) -{ - int i; - for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { - if (rirqs[i] == irq) { - rirqs[i] = 0; - return 1; - } - } - return 0; -} -#endif - -static int __init -have_requested_irq( char irq ) -{ - // array init to zeros so 0 irq will not be requested as a side effect - int i; - for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { - if (rirqs[i] == irq) - return 1; - } - return 0; -} - -/******************************************************************************/ -/* Function: init_module() */ -/* Parameters: None */ -/* Returns: Success (0) */ -/* */ -/* Description: */ -/* This is a required entry point for an installable module. It simply calls */ -/* the driver initialisation function and returns what it returns. */ -/******************************************************************************/ -#ifdef MODULE -int -init_module(void) -{ -#ifdef IP2DEBUG_INIT - printk (KERN_DEBUG "Loading module ...\n" ); -#endif - return 0; -} -#endif /* MODULE */ - -/******************************************************************************/ -/* Function: cleanup_module() */ -/* Parameters: None */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This is a required entry point for an installable module. It has to return */ -/* the device and the driver to a passive state. It should not be necessary */ -/* to reset the board fully, especially as the loadware is downloaded */ -/* externally rather than in the driver. We just want to disable the board */ -/* and clear the loadware to a reset state. To allow this there has to be a */ -/* way to detect whether the board has the loadware running at init time to */ -/* handle subsequent installations of the driver. All memory allocated by the */ -/* driver should be returned since it may be unloaded from memory. */ -/******************************************************************************/ -#ifdef MODULE -void -cleanup_module(void) -{ - int err; - int i; - -#ifdef IP2DEBUG_INIT - printk (KERN_DEBUG "Unloading %s: version %s\n", pcName, pcVersion ); -#endif - /* Stop poll timer if we had one. */ - if ( TimerOn ) { - del_timer ( &PollTimer ); - TimerOn = 0; - } - - /* Reset the boards we have. */ - for( i = 0; i < IP2_MAX_BOARDS; ++i ) { - if ( i2BoardPtrTable[i] ) { - iiReset( i2BoardPtrTable[i] ); - } - } - - /* The following is done at most once, if any boards were installed. */ - for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { - if ( i2BoardPtrTable[i] ) { - iiResetDelay( i2BoardPtrTable[i] ); - /* free io addresses and Tibet */ - release_region( ip2config.addr[i], 8 ); - class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); - devfs_remove("ip2/ipl%d", i); - class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); - devfs_remove("ip2/stat%d", i); - } - /* Disable and remove interrupt handler. */ - if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) { - free_irq ( ip2config.irq[i], (void *)&pcName); - clear_requested_irq( ip2config.irq[i]); - } - } - class_destroy(ip2_class); - devfs_remove("ip2"); - if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) { - printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err); - } - put_tty_driver(ip2_tty_driver); - if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) { - printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err); - } - remove_proc_entry("ip2mem", &proc_root); - - // free memory - for (i = 0; i < IP2_MAX_BOARDS; i++) { - void *pB; -#ifdef CONFIG_PCI - if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) { - pci_disable_device(ip2config.pci_dev[i]); - ip2config.pci_dev[i] = NULL; - } -#endif - if ((pB = i2BoardPtrTable[i]) != 0 ) { - kfree ( pB ); - i2BoardPtrTable[i] = NULL; - } - if ((DevTableMem[i]) != NULL ) { - kfree ( DevTableMem[i] ); - DevTableMem[i] = NULL; - } - } - - /* Cleanup the iiEllis subsystem. */ - iiEllisCleanup(); -#ifdef IP2DEBUG_INIT - printk (KERN_DEBUG "IP2 Unloaded\n" ); -#endif -} -#endif /* MODULE */ - -static struct tty_operations ip2_ops = { - .open = ip2_open, - .close = ip2_close, - .write = ip2_write, - .put_char = ip2_putchar, - .flush_chars = ip2_flush_chars, - .write_room = ip2_write_room, - .chars_in_buffer = ip2_chars_in_buf, - .flush_buffer = ip2_flush_buffer, - .ioctl = ip2_ioctl, - .throttle = ip2_throttle, - .unthrottle = ip2_unthrottle, - .set_termios = ip2_set_termios, - .set_ldisc = ip2_set_line_discipline, - .stop = ip2_stop, - .start = ip2_start, - .hangup = ip2_hangup, - .read_proc = ip2_read_proc, - .tiocmget = ip2_tiocmget, - .tiocmset = ip2_tiocmset, -}; - -/******************************************************************************/ -/* Function: ip2_loadmain() */ -/* Parameters: irq, io from command line of insmod et. al. */ -/* pointer to fip firmware and firmware size for boards */ -/* Returns: Success (0) */ -/* */ -/* Description: */ -/* This was the required entry point for all drivers (now in ip2.c) */ -/* It performs all */ -/* initialisation of the devices and driver structures, and registers itself */ -/* with the relevant kernel modules. */ -/******************************************************************************/ -/* SA_INTERRUPT- if set blocks all interrupts else only this line */ -/* SA_SHIRQ - for shared irq PCI or maybe EISA only */ -/* SA_RANDOM - can be source for cert. random number generators */ -#define IP2_SA_FLAGS 0 - -int -ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) -{ - int i, j, box; - int err = 0; - int status = 0; - static int loaded; - i2eBordStrPtr pB = NULL; - int rc = -1; - - ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 ); - - /* process command line arguments to modprobe or - insmod i.e. iop & irqp */ - /* irqp and iop should ALWAYS be specified now... But we check - them individually just to be sure, anyways... */ - for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { - if (iop) { - ip2config.addr[i] = iop[i]; - if (irqp) { - if( irqp[i] >= 0 ) { - ip2config.irq[i] = irqp[i]; - } else { - ip2config.irq[i] = 0; - } - // This is a little bit of a hack. If poll_only=1 on command - // line back in ip2.c OR all IRQs on all specified boards are - // explicitly set to 0, then drop to poll only mode and override - // PCI or EISA interrupts. This superceeds the old hack of - // triggering if all interrupts were zero (like da default). - // Still a hack but less prone to random acts of terrorism. - // - // What we really should do, now that the IRQ default is set - // to -1, is to use 0 as a hard coded, do not probe. - // - // /\/\|=mhw=|\/\/ - poll_only |= irqp[i]; - } - } - } - poll_only = !poll_only; - - Fip_firmware = firmware; - Fip_firmware_size = firmsize; - - /* Announce our presence */ - printk( KERN_INFO "%s version %s\n", pcName, pcVersion ); - - // ip2 can be unloaded and reloaded for no good reason - // we can't let that happen here or bad things happen - // second load hoses board but not system - fixme later - if (loaded) { - printk( KERN_INFO "Still loaded\n" ); - return 0; - } - loaded++; - - ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS); - if (!ip2_tty_driver) - return -ENOMEM; - - /* Initialise the iiEllis subsystem. */ - iiEllisInit(); - - /* Initialize arrays. */ - memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable ); - memset( DevTable, 0, sizeof DevTable ); - - /* Initialise all the boards we can find (up to the maximum). */ - for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { - switch ( ip2config.addr[i] ) { - case 0: /* skip this slot even if card is present */ - break; - default: /* ISA */ - /* ISA address must be specified */ - if ( (ip2config.addr[i] < 0x100) || (ip2config.addr[i] > 0x3f8) ) { - printk ( KERN_ERR "IP2: Bad ISA board %d address %x\n", - i, ip2config.addr[i] ); - ip2config.addr[i] = 0; - } else { - ip2config.type[i] = ISA; - - /* Check for valid irq argument, set for polling if invalid */ - if (ip2config.irq[i] && !is_valid_irq(ip2config.irq[i])) { - printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",ip2config.irq[i]); - ip2config.irq[i] = 0;// 0 is polling and is valid in that sense - } - } - break; - case PCI: -#ifdef CONFIG_PCI - { - struct pci_dev *pci_dev_i = NULL; - pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE, - PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); - if (pci_dev_i != NULL) { - unsigned int addr; - - if (pci_enable_device(pci_dev_i)) { - printk( KERN_ERR "IP2: can't enable PCI device at %s\n", - pci_name(pci_dev_i)); - break; - } - ip2config.type[i] = PCI; - ip2config.pci_dev[i] = pci_dev_i; - status = - pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr); - if ( addr & 1 ) { - ip2config.addr[i]=(USHORT)(addr&0xfffe); - } else { - printk( KERN_ERR "IP2: PCI I/O address error\n"); - } - -// If the PCI BIOS assigned it, lets try and use it. If we -// can't acquire it or it screws up, deal with it then. - -// if (!is_valid_irq(pci_irq)) { -// printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq); -// pci_irq = 0; -// } - ip2config.irq[i] = pci_dev_i->irq; - } else { // ann error - ip2config.addr[i] = 0; - if (status == PCIBIOS_DEVICE_NOT_FOUND) { - printk( KERN_ERR "IP2: PCI board %d not found\n", i ); - } else { - printk( KERN_ERR "IP2: PCI error 0x%x \n", status ); - } - } - } -#else - printk( KERN_ERR "IP2: PCI card specified but PCI support not\n"); - printk( KERN_ERR "IP2: configured in this kernel.\n"); - printk( KERN_ERR "IP2: Recompile kernel with CONFIG_PCI defined!\n"); -#endif /* CONFIG_PCI */ - break; - case EISA: - if ( (ip2config.addr[i] = find_eisa_board( Eisa_slot + 1 )) != 0) { - /* Eisa_irq set as side effect, boo */ - ip2config.type[i] = EISA; - } - ip2config.irq[i] = Eisa_irq; - break; - } /* switch */ - } /* for */ - for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { - if ( ip2config.addr[i] ) { - pB = kmalloc( sizeof(i2eBordStr), GFP_KERNEL); - if ( pB != NULL ) { - i2BoardPtrTable[i] = pB; - memset( pB, 0, sizeof(i2eBordStr) ); - iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer ); - iiReset( pB ); - } else { - printk(KERN_ERR "IP2: board memory allocation error\n"); - } - } - } - for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { - if ( ( pB = i2BoardPtrTable[i] ) != NULL ) { - iiResetDelay( pB ); - break; - } - } - for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { - if ( i2BoardPtrTable[i] != NULL ) { - ip2_init_board( i ); - } - } - - ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 ); - - ip2_tty_driver->owner = THIS_MODULE; - ip2_tty_driver->name = "ttyF"; - ip2_tty_driver->devfs_name = "tts/F"; - ip2_tty_driver->driver_name = pcDriver_name; - ip2_tty_driver->major = IP2_TTY_MAJOR; - ip2_tty_driver->minor_start = 0; - ip2_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL; - ip2_tty_driver->init_termios = tty_std_termios; - ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; - ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; - tty_set_operations(ip2_tty_driver, &ip2_ops); - - ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 ); - - /* Register the tty devices. */ - if ( ( err = tty_register_driver ( ip2_tty_driver ) ) ) { - printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err); - put_tty_driver(ip2_tty_driver); - return -EINVAL; - } else - /* Register the IPL driver. */ - if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) { - printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err ); - } else { - /* create the sysfs class */ - ip2_class = class_create(THIS_MODULE, "ip2"); - if (IS_ERR(ip2_class)) { - err = PTR_ERR(ip2_class); - goto out_chrdev; - } - } - /* Register the read_procmem thing */ - if (!create_proc_info_entry("ip2mem",0,&proc_root,ip2_read_procmem)) { - printk(KERN_ERR "IP2: failed to register read_procmem\n"); - } else { - - ip2trace (ITRC_NO_PORT, ITRC_INIT, 4, 0 ); - /* Register the interrupt handler or poll handler, depending upon the - * specified interrupt. - */ - - for( i = 0; i < IP2_MAX_BOARDS; ++i ) { - if ( 0 == ip2config.addr[i] ) { - continue; - } - - if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { - class_device_create(ip2_class, NULL, - MKDEV(IP2_IPL_MAJOR, 4 * i), - NULL, "ipl%d", i); - err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i), - S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, - "ip2/ipl%d", i); - if (err) { - class_device_destroy(ip2_class, - MKDEV(IP2_IPL_MAJOR, 4 * i)); - goto out_class; - } - - class_device_create(ip2_class, NULL, - MKDEV(IP2_IPL_MAJOR, 4 * i + 1), - NULL, "stat%d", i); - err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1), - S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, - "ip2/stat%d", i); - if (err) { - class_device_destroy(ip2_class, - MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); - goto out_class; - } - - for ( box = 0; box < ABS_MAX_BOXES; ++box ) - { - for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) - { - if ( pB->i2eChannelMap[box] & (1 << j) ) - { - tty_register_device(ip2_tty_driver, - j + ABS_BIGGEST_BOX * - (box+i*ABS_MAX_BOXES), NULL); - } - } - } - } - - if (poll_only) { -// Poll only forces driver to only use polling and -// to ignore the probed PCI or EISA interrupts. - ip2config.irq[i] = CIR_POLL; - } - if ( ip2config.irq[i] == CIR_POLL ) { -retry: - if (!TimerOn) { - PollTimer.expires = POLL_TIMEOUT; - add_timer ( &PollTimer ); - TimerOn = 1; - printk( KERN_INFO "IP2: polling\n"); - } - } else { - if (have_requested_irq(ip2config.irq[i])) - continue; - rc = request_irq( ip2config.irq[i], ip2_interrupt, - IP2_SA_FLAGS | (ip2config.type[i] == PCI ? SA_SHIRQ : 0), - pcName, (void *)&pcName); - if (rc) { - printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc); - ip2config.irq[i] = CIR_POLL; - printk( KERN_INFO "IP2: Polling %ld/sec.\n", - (POLL_TIMEOUT - jiffies)); - goto retry; - } - mark_requested_irq(ip2config.irq[i]); - /* Initialise the interrupt handler bottom half (aka slih). */ - } - } - for( i = 0; i < IP2_MAX_BOARDS; ++i ) { - if ( i2BoardPtrTable[i] ) { - set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */ - } - } - } - ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 ); - goto out; - -out_class: - class_destroy(ip2_class); -out_chrdev: - unregister_chrdev(IP2_IPL_MAJOR, "ip2"); -out: - return err; -} - -EXPORT_SYMBOL(ip2_loadmain); - -/******************************************************************************/ -/* Function: ip2_init_board() */ -/* Parameters: Index of board in configuration structure */ -/* Returns: Success (0) */ -/* */ -/* Description: */ -/* This function initializes the specified board. The loadware is copied to */ -/* the board, the channel structures are initialized, and the board details */ -/* are reported on the console. */ -/******************************************************************************/ -static void __init -ip2_init_board( int boardnum ) -{ - int i; - int nports = 0, nboxes = 0; - i2ChanStrPtr pCh; - i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; - - if ( !iiInitialize ( pB ) ) { - printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n", - pB->i2eBase, pB->i2eError ); - goto err_initialize; - } - printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1, - ip2config.addr[boardnum], ip2config.irq[boardnum] ); - - if (!request_region( ip2config.addr[boardnum], 8, pcName )) { - printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]); - goto err_initialize; - } - - if ( iiDownloadAll ( pB, (loadHdrStrPtr)Fip_firmware, 1, Fip_firmware_size ) - != II_DOWN_GOOD ) { - printk ( KERN_ERR "IP2: failed to download loadware\n" ); - goto err_release_region; - } else { - printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n", - pB->i2ePom.e.porVersion, - pB->i2ePom.e.porRevision, - pB->i2ePom.e.porSubRev, pB->i2eLVersion, - pB->i2eLRevision, pB->i2eLSub ); - } - - switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) { - - default: - printk( KERN_ERR "IP2: Unknown board type, ID = %x\n", - pB->i2ePom.e.porID ); - nports = 0; - goto err_release_region; - break; - - case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */ - printk ( KERN_INFO "IP2: ISA-4\n" ); - nports = 4; - break; - - case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */ - printk ( KERN_INFO "IP2: ISA-8 std\n" ); - nports = 8; - break; - - case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */ - printk ( KERN_INFO "IP2: ISA-8 RJ11\n" ); - nports = 8; - break; - - case POR_ID_FIIEX: /* IntelliPort IIEX */ - { - int portnum = IP2_PORTS_PER_BOARD * boardnum; - int box; - - for( box = 0; box < ABS_MAX_BOXES; ++box ) { - if ( pB->i2eChannelMap[box] != 0 ) { - ++nboxes; - } - for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { - if ( pB->i2eChannelMap[box] & 1<< i ) { - ++nports; - } - } - } - DevTableMem[boardnum] = pCh = - kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL ); - if ( !pCh ) { - printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); - goto err_release_region; - } - if ( !i2InitChannels( pB, nports, pCh ) ) { - printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); - kfree ( pCh ); - goto err_release_region; - } - pB->i2eChannelPtr = &DevTable[portnum]; - pB->i2eChannelCnt = ABS_MOST_PORTS; - - for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) { - for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { - if ( pB->i2eChannelMap[box] & (1 << i) ) { - DevTable[portnum + i] = pCh; - pCh->port_index = portnum + i; - pCh++; - } - } - } - printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n", - nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 ); - } - goto ex_exit; - } - DevTableMem[boardnum] = pCh = - kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL ); - if ( !pCh ) { - printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); - goto err_release_region; - } - pB->i2eChannelPtr = pCh; - pB->i2eChannelCnt = nports; - if ( !i2InitChannels( pB, nports, pCh ) ) { - printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); - kfree ( pCh ); - goto err_release_region; - } - pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum]; - - for( i = 0; i < pB->i2eChannelCnt; ++i ) { - DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh; - pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i; - pCh++; - } -ex_exit: - INIT_WORK(&pB->tqueue_interrupt, (void(*)(void*)) ip2_interrupt_bh, pB); - return; - -err_release_region: - release_region(ip2config.addr[boardnum], 8); -err_initialize: - kfree ( pB ); - i2BoardPtrTable[boardnum] = NULL; - return; -} - -/******************************************************************************/ -/* Function: find_eisa_board ( int start_slot ) */ -/* Parameters: First slot to check */ -/* Returns: Address of EISA IntelliPort II controller */ -/* */ -/* Description: */ -/* This function searches for an EISA IntelliPort controller, starting */ -/* from the specified slot number. If the motherboard is not identified as an */ -/* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */ -/* it returns the base address of the controller. */ -/******************************************************************************/ -static unsigned short __init -find_eisa_board( int start_slot ) -{ - int i, j; - unsigned int idm = 0; - unsigned int idp = 0; - unsigned int base = 0; - unsigned int value; - int setup_address; - int setup_irq; - int ismine = 0; - - /* - * First a check for an EISA motherboard, which we do by comparing the - * EISA ID registers for the system board and the first couple of slots. - * No slot ID should match the system board ID, but on an ISA or PCI - * machine the odds are that an empty bus will return similar values for - * each slot. - */ - i = 0x0c80; - value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3); - for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) { - j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3); - if ( value == j ) - return 0; - } - - /* - * OK, so we are inclined to believe that this is an EISA machine. Find - * an IntelliPort controller. - */ - for( i = start_slot; i < 16; i++ ) { - base = i << 12; - idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff); - idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff); - ismine = 0; - if ( idm == 0x0e8e ) { - if ( idp == 0x0281 || idp == 0x0218 ) { - ismine = 1; - } else if ( idp == 0x0282 || idp == 0x0283 ) { - ismine = 3; /* Can do edge-trigger */ - } - if ( ismine ) { - Eisa_slot = i; - break; - } - } - } - if ( !ismine ) - return 0; - - /* It's some sort of EISA card, but at what address is it configured? */ - - setup_address = base + 0xc88; - value = inb(base + 0xc86); - setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0; - - if ( (ismine & 2) && !(value & 0x10) ) { - ismine = 1; /* Could be edging, but not */ - } - - if ( Eisa_irq == 0 ) { - Eisa_irq = setup_irq; - } else if ( Eisa_irq != setup_irq ) { - printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" ); - } - -#ifdef IP2DEBUG_INIT -printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x", - base >> 12, idm, idp, setup_address); - if ( Eisa_irq ) { - printk(KERN_DEBUG ", Interrupt %d %s\n", - setup_irq, (ismine & 2) ? "(edge)" : "(level)"); - } else { - printk(KERN_DEBUG ", (polled)\n"); - } -#endif - return setup_address; -} - -/******************************************************************************/ -/* Function: set_irq() */ -/* Parameters: index to board in board table */ -/* IRQ to use */ -/* Returns: Success (0) */ -/* */ -/* Description: */ -/******************************************************************************/ -static void -set_irq( int boardnum, int boardIrq ) -{ - unsigned char tempCommand[16]; - i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; - unsigned long flags; - - /* - * Notify the boards they may generate interrupts. This is done by - * sending an in-line command to channel 0 on each board. This is why - * the channels have to be defined already. For each board, if the - * interrupt has never been defined, we must do so NOW, directly, since - * board will not send flow control or even give an interrupt until this - * is done. If polling we must send 0 as the interrupt parameter. - */ - - // We will get an interrupt here at the end of this function - - iiDisableMailIrq(pB); - - /* We build up the entire packet header. */ - CHANNEL_OF(tempCommand) = 0; - PTYPE_OF(tempCommand) = PTYPE_INLINE; - CMD_COUNT_OF(tempCommand) = 2; - (CMD_OF(tempCommand))[0] = CMDVALUE_IRQ; - (CMD_OF(tempCommand))[1] = boardIrq; - /* - * Write to FIFO; don't bother to adjust fifo capacity for this, since - * board will respond almost immediately after SendMail hit. - */ - WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags); - iiWriteBuf(pB, tempCommand, 4); - WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags); - pB->i2eUsingIrq = boardIrq; - pB->i2eOutMailWaiting |= MB_OUT_STUFFED; - - /* Need to update number of boards before you enable mailbox int */ - ++i2nBoards; - - CHANNEL_OF(tempCommand) = 0; - PTYPE_OF(tempCommand) = PTYPE_BYPASS; - CMD_COUNT_OF(tempCommand) = 6; - (CMD_OF(tempCommand))[0] = 88; // SILO - (CMD_OF(tempCommand))[1] = 64; // chars - (CMD_OF(tempCommand))[2] = 32; // ms - - (CMD_OF(tempCommand))[3] = 28; // MAX_BLOCK - (CMD_OF(tempCommand))[4] = 64; // chars - - (CMD_OF(tempCommand))[5] = 87; // HW_TEST - WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags); - iiWriteBuf(pB, tempCommand, 8); - WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags); - - CHANNEL_OF(tempCommand) = 0; - PTYPE_OF(tempCommand) = PTYPE_BYPASS; - CMD_COUNT_OF(tempCommand) = 1; - (CMD_OF(tempCommand))[0] = 84; /* get BOX_IDS */ - iiWriteBuf(pB, tempCommand, 3); - -#ifdef XXX - // enable heartbeat for test porpoises - CHANNEL_OF(tempCommand) = 0; - PTYPE_OF(tempCommand) = PTYPE_BYPASS; - CMD_COUNT_OF(tempCommand) = 2; - (CMD_OF(tempCommand))[0] = 44; /* get ping */ - (CMD_OF(tempCommand))[1] = 200; /* 200 ms */ - WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags); - iiWriteBuf(pB, tempCommand, 4); - WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags); -#endif - - iiEnableMailIrq(pB); - iiSendPendingMail(pB); -} - -/******************************************************************************/ -/* Interrupt Handler Section */ -/******************************************************************************/ - -static inline void -service_all_boards(void) -{ - int i; - i2eBordStrPtr pB; - - /* Service every board on the list */ - for( i = 0; i < IP2_MAX_BOARDS; ++i ) { - pB = i2BoardPtrTable[i]; - if ( pB ) { - i2ServiceBoard( pB ); - } - } -} - - -/******************************************************************************/ -/* Function: ip2_interrupt_bh(pB) */ -/* Parameters: pB - pointer to the board structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* Service the board in a bottom half interrupt handler and then */ -/* reenable the board's interrupts if it has an IRQ number */ -/* */ -/******************************************************************************/ -static void -ip2_interrupt_bh(i2eBordStrPtr pB) -{ -// pB better well be set or we have a problem! We can only get -// here from the IMMEDIATE queue. Here, we process the boards. -// Checking pB doesn't cost much and it saves us from the sanity checkers. - - bh_counter++; - - if ( pB ) { - i2ServiceBoard( pB ); - if( pB->i2eUsingIrq ) { -// Re-enable his interrupts - iiEnableMailIrq(pB); - } - } -} - - -/******************************************************************************/ -/* Function: ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs) */ -/* Parameters: irq - interrupt number */ -/* pointer to optional device ID structure */ -/* pointer to register structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* Our task here is simply to identify each board which needs servicing. */ -/* If we are queuing then, queue it to be serviced, and disable its irq */ -/* mask otherwise process the board directly. */ -/* */ -/* We could queue by IRQ but that just complicates things on both ends */ -/* with very little gain in performance (how many instructions does */ -/* it take to iterate on the immediate queue). */ -/* */ -/* */ -/******************************************************************************/ -static irqreturn_t -ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - int i; - i2eBordStrPtr pB; - int handled = 0; - - ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq ); - - /* Service just the boards on the list using this irq */ - for( i = 0; i < i2nBoards; ++i ) { - pB = i2BoardPtrTable[i]; - -// Only process those boards which match our IRQ. -// IRQ = 0 for polled boards, we won't poll "IRQ" boards - - if ( pB && (pB->i2eUsingIrq == irq) ) { - handled = 1; -#ifdef USE_IQI - - if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) { -// Disable his interrupt (will be enabled when serviced) -// This is mostly to protect from reentrancy. - iiDisableMailIrq(pB); - -// Park the board on the immediate queue for processing. - schedule_work(&pB->tqueue_interrupt); - -// Make sure the immediate queue is flagged to fire. - } -#else -// We are using immediate servicing here. This sucks and can -// cause all sorts of havoc with ppp and others. The failsafe -// check on iiSendPendingMail could also throw a hairball. - i2ServiceBoard( pB ); -#endif /* USE_IQI */ - } - } - - ++irq_counter; - - ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); - return IRQ_RETVAL(handled); -} - -/******************************************************************************/ -/* Function: ip2_poll(unsigned long arg) */ -/* Parameters: ? */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This function calls the library routine i2ServiceBoard for each board in */ -/* the board table. This is used instead of the interrupt routine when polled */ -/* mode is specified. */ -/******************************************************************************/ -static void -ip2_poll(unsigned long arg) -{ - ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 ); - - TimerOn = 0; // it's the truth but not checked in service - - // Just polled boards, IRQ = 0 will hit all non-interrupt boards. - // It will NOT poll boards handled by hard interrupts. - // The issue of queued BH interrups is handled in ip2_interrupt(). - ip2_interrupt(0, NULL, NULL); - - PollTimer.expires = POLL_TIMEOUT; - add_timer( &PollTimer ); - TimerOn = 1; - - ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); -} - -static void do_input(void *p) -{ - i2ChanStrPtr pCh = p; - unsigned long flags; - - ip2trace(CHANN, ITRC_INPUT, 21, 0 ); - - // Data input - if ( pCh->pTTY != NULL ) { - READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags) - if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) { - READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags) - i2Input( pCh ); - } else - READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags) - } else { - ip2trace(CHANN, ITRC_INPUT, 22, 0 ); - - i2InputFlush( pCh ); - } -} - -// code duplicated from n_tty (ldisc) -static inline void isig(int sig, struct tty_struct *tty, int flush) -{ - if (tty->pgrp > 0) - kill_pg(tty->pgrp, sig, 1); - if (flush || !L_NOFLSH(tty)) { - if ( tty->ldisc.flush_buffer ) - tty->ldisc.flush_buffer(tty); - i2InputFlush( tty->driver_data ); - } -} - -static void do_status(void *p) -{ - i2ChanStrPtr pCh = p; - int status; - - status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) ); - - ip2trace (CHANN, ITRC_STATUS, 21, 1, status ); - - if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) { - if ( (status & I2_BRK) ) { - // code duplicated from n_tty (ldisc) - if (I_IGNBRK(pCh->pTTY)) - goto skip_this; - if (I_BRKINT(pCh->pTTY)) { - isig(SIGINT, pCh->pTTY, 1); - goto skip_this; - } - wake_up_interruptible(&pCh->pTTY->read_wait); - } -#ifdef NEVER_HAPPENS_AS_SETUP_XXX - // and can't work because we don't know the_char - // as the_char is reported on a separate path - // The intelligent board does this stuff as setup - { - char brkf = TTY_NORMAL; - unsigned char brkc = '\0'; - unsigned char tmp; - if ( (status & I2_BRK) ) { - brkf = TTY_BREAK; - brkc = '\0'; - } - else if (status & I2_PAR) { - brkf = TTY_PARITY; - brkc = the_char; - } else if (status & I2_FRA) { - brkf = TTY_FRAME; - brkc = the_char; - } else if (status & I2_OVR) { - brkf = TTY_OVERRUN; - brkc = the_char; - } - tmp = pCh->pTTY->real_raw; - pCh->pTTY->real_raw = 0; - pCh->pTTY->ldisc.receive_buf( pCh->pTTY, &brkc, &brkf, 1 ); - pCh->pTTY->real_raw = tmp; - } -#endif /* NEVER_HAPPENS_AS_SETUP_XXX */ - } -skip_this: - - if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) { - wake_up_interruptible(&pCh->delta_msr_wait); - - if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) { - if ( status & I2_DCD ) { - if ( pCh->wopen ) { - wake_up_interruptible ( &pCh->open_wait ); - } - } else { - if (pCh->pTTY && (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) { - tty_hangup( pCh->pTTY ); - } - } - } - } - - ip2trace (CHANN, ITRC_STATUS, 26, 0 ); -} - -/******************************************************************************/ -/* Device Open/Close/Ioctl Entry Point Section */ -/******************************************************************************/ - -/******************************************************************************/ -/* Function: open_sanity_check() */ -/* Parameters: Pointer to tty structure */ -/* Pointer to file structure */ -/* Returns: Success or failure */ -/* */ -/* Description: */ -/* Verifies the structure magic numbers and cross links. */ -/******************************************************************************/ -#ifdef IP2DEBUG_OPEN -static void -open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd ) -{ - if ( pBrd->i2eValid != I2E_MAGIC ) { - printk(KERN_ERR "IP2: invalid board structure\n" ); - } else if ( pBrd != pCh->pMyBord ) { - printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n", - pCh->pMyBord ); - } else if ( pBrd->i2eChannelCnt < pCh->port_index ) { - printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index ); - } else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) { - } else { - printk(KERN_INFO "IP2: all pointers check out!\n" ); - } -} -#endif - - -/******************************************************************************/ -/* Function: ip2_open() */ -/* Parameters: Pointer to tty structure */ -/* Pointer to file structure */ -/* Returns: Success or failure */ -/* */ -/* Description: (MANDATORY) */ -/* A successful device open has to run a gauntlet of checks before it */ -/* completes. After some sanity checking and pointer setup, the function */ -/* blocks until all conditions are satisfied. It then initialises the port to */ -/* the default characteristics and returns. */ -/******************************************************************************/ -static int -ip2_open( PTTY tty, struct file *pFile ) -{ - wait_queue_t wait; - int rc = 0; - int do_clocal = 0; - i2ChanStrPtr pCh = DevTable[tty->index]; - - ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 ); - - if ( pCh == NULL ) { - return -ENODEV; - } - /* Setup pointer links in device and tty structures */ - pCh->pTTY = tty; - tty->driver_data = pCh; - -#ifdef IP2DEBUG_OPEN - printk(KERN_DEBUG \ - "IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n", - tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index); - open_sanity_check ( pCh, pCh->pMyBord ); -#endif - - i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP); - pCh->dataSetOut |= (I2_DTR | I2_RTS); - serviceOutgoingFifo( pCh->pMyBord ); - - /* Block here until the port is ready (per serial and istallion) */ - /* - * 1. If the port is in the middle of closing wait for the completion - * and then return the appropriate error. - */ - init_waitqueue_entry(&wait, current); - add_wait_queue(&pCh->close_wait, &wait); - set_current_state( TASK_INTERRUPTIBLE ); - - if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { - if ( pCh->flags & ASYNC_CLOSING ) { - schedule(); - } - if ( tty_hung_up_p(pFile) ) { - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->close_wait, &wait); - return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS; - } - } - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->close_wait, &wait); - - /* - * 3. Handle a non-blocking open of a normal port. - */ - if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<flags |= ASYNC_NORMAL_ACTIVE; - goto noblock; - } - /* - * 4. Now loop waiting for the port to be free and carrier present - * (if required). - */ - if ( tty->termios->c_cflag & CLOCAL ) - do_clocal = 1; - -#ifdef IP2DEBUG_OPEN - printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal); -#endif - - ++pCh->wopen; - - init_waitqueue_entry(&wait, current); - add_wait_queue(&pCh->open_wait, &wait); - - for(;;) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); - pCh->dataSetOut |= (I2_DTR | I2_RTS); - set_current_state( TASK_INTERRUPTIBLE ); - serviceOutgoingFifo( pCh->pMyBord ); - if ( tty_hung_up_p(pFile) ) { - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->open_wait, &wait); - return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS; - } - if (!(pCh->flags & ASYNC_CLOSING) && - (do_clocal || (pCh->dataSetIn & I2_DCD) )) { - rc = 0; - break; - } - -#ifdef IP2DEBUG_OPEN - printk(KERN_DEBUG "ASYNC_CLOSING = %s\n", - (pCh->flags & ASYNC_CLOSING)?"True":"False"); - printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n"); -#endif - ip2trace (CHANN, ITRC_OPEN, 3, 2, 0, - (pCh->flags & ASYNC_CLOSING) ); - /* check for signal */ - if (signal_pending(current)) { - rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); - break; - } - schedule(); - } - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->open_wait, &wait); - - --pCh->wopen; //why count? - - ip2trace (CHANN, ITRC_OPEN, 4, 0 ); - - if (rc != 0 ) { - return rc; - } - pCh->flags |= ASYNC_NORMAL_ACTIVE; - -noblock: - - /* first open - Assign termios structure to port */ - if ( tty->count == 1 ) { - i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); - /* Now we must send the termios settings to the loadware */ - set_params( pCh, NULL ); - } - - /* - * Now set any i2lib options. These may go away if the i2lib code ends - * up rolled into the mainline. - */ - pCh->channelOptions |= CO_NBLOCK_WRITE; - -#ifdef IP2DEBUG_OPEN - printk (KERN_DEBUG "IP2: open completed\n" ); -#endif - serviceOutgoingFifo( pCh->pMyBord ); - - ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 ); - - return 0; -} - -/******************************************************************************/ -/* Function: ip2_close() */ -/* Parameters: Pointer to tty structure */ -/* Pointer to file structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_close( PTTY tty, struct file *pFile ) -{ - i2ChanStrPtr pCh = tty->driver_data; - - if ( !pCh ) { - return; - } - - ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 ); - -#ifdef IP2DEBUG_OPEN - printk(KERN_DEBUG "IP2:close %s:\n",tty->name); -#endif - - if ( tty_hung_up_p ( pFile ) ) { - - ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 ); - - return; - } - if ( tty->count > 1 ) { /* not the last close */ - - ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 ); - - return; - } - pCh->flags |= ASYNC_CLOSING; // last close actually - - tty->closing = 1; - - if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) { - /* - * Before we drop DTR, make sure the transmitter has completely drained. - * This uses an timeout, after which the close - * completes. - */ - ip2_wait_until_sent(tty, pCh->ClosingWaitTime ); - } - /* - * At this point we stop accepting input. Here we flush the channel - * input buffer which will allow the board to send up more data. Any - * additional input is tossed at interrupt/poll time. - */ - i2InputFlush( pCh ); - - /* disable DSS reporting */ - i2QueueCommands(PTYPE_INLINE, pCh, 100, 4, - CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); - if ( !tty || (tty->termios->c_cflag & HUPCL) ) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); - pCh->dataSetOut &= ~(I2_DTR | I2_RTS); - i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); - } - - serviceOutgoingFifo ( pCh->pMyBord ); - - if ( tty->driver->flush_buffer ) - tty->driver->flush_buffer(tty); - if ( tty->ldisc.flush_buffer ) - tty->ldisc.flush_buffer(tty); - tty->closing = 0; - - pCh->pTTY = NULL; - - if (pCh->wopen) { - if (pCh->ClosingDelay) { - msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay)); - } - wake_up_interruptible(&pCh->open_wait); - } - - pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&pCh->close_wait); - -#ifdef IP2DEBUG_OPEN - DBG_CNT("ip2_close: after wakeups--"); -#endif - - - ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 ); - - return; -} - -/******************************************************************************/ -/* Function: ip2_hangup() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_hangup ( PTTY tty ) -{ - i2ChanStrPtr pCh = tty->driver_data; - - if( !pCh ) { - return; - } - - ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 ); - - ip2_flush_buffer(tty); - - /* disable DSS reporting */ - - i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP); - i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); - if ( (tty->termios->c_cflag & HUPCL) ) { - i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN); - pCh->dataSetOut &= ~(I2_DTR | I2_RTS); - i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); - } - i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, - CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); - serviceOutgoingFifo ( pCh->pMyBord ); - - wake_up_interruptible ( &pCh->delta_msr_wait ); - - pCh->flags &= ~ASYNC_NORMAL_ACTIVE; - pCh->pTTY = NULL; - wake_up_interruptible ( &pCh->open_wait ); - - ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 ); -} - -/******************************************************************************/ -/******************************************************************************/ -/* Device Output Section */ -/******************************************************************************/ -/******************************************************************************/ - -/******************************************************************************/ -/* Function: ip2_write() */ -/* Parameters: Pointer to tty structure */ -/* Flag denoting data is in user (1) or kernel (0) space */ -/* Pointer to data */ -/* Number of bytes to write */ -/* Returns: Number of bytes actually written */ -/* */ -/* Description: (MANDATORY) */ -/* */ -/* */ -/******************************************************************************/ -static int -ip2_write( PTTY tty, const unsigned char *pData, int count) -{ - i2ChanStrPtr pCh = tty->driver_data; - int bytesSent = 0; - unsigned long flags; - - ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 ); - - /* Flush out any buffered data left over from ip2_putchar() calls. */ - ip2_flush_chars( tty ); - - /* This is the actual move bit. Make sure it does what we need!!!!! */ - WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); - bytesSent = i2Output( pCh, pData, count, 0 ); - WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); - - ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent ); - - return bytesSent > 0 ? bytesSent : 0; -} - -/******************************************************************************/ -/* Function: ip2_putchar() */ -/* Parameters: Pointer to tty structure */ -/* Character to write */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_putchar( PTTY tty, unsigned char ch ) -{ - i2ChanStrPtr pCh = tty->driver_data; - unsigned long flags; - -// ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch ); - - WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); - pCh->Pbuf[pCh->Pbuf_stuff++] = ch; - if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) { - WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); - ip2_flush_chars( tty ); - } else - WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); - -// ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch ); -} - -/******************************************************************************/ -/* Function: ip2_flush_chars() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/******************************************************************************/ -static void -ip2_flush_chars( PTTY tty ) -{ - int strip; - i2ChanStrPtr pCh = tty->driver_data; - unsigned long flags; - - WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); - if ( pCh->Pbuf_stuff ) { - -// ip2trace (CHANN, ITRC_PUTC, 10, 1, strip ); - - // - // We may need to restart i2Output if it does not fullfill this request - // - strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff, 0 ); - if ( strip != pCh->Pbuf_stuff ) { - memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip ); - } - pCh->Pbuf_stuff -= strip; - } - WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); -} - -/******************************************************************************/ -/* Function: ip2_write_room() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Number of bytes that the driver can accept */ -/* */ -/* Description: */ -/* */ -/******************************************************************************/ -static int -ip2_write_room ( PTTY tty ) -{ - int bytesFree; - i2ChanStrPtr pCh = tty->driver_data; - unsigned long flags; - - READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); - bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff; - READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); - - ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree ); - - return ((bytesFree > 0) ? bytesFree : 0); -} - -/******************************************************************************/ -/* Function: ip2_chars_in_buf() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Number of bytes queued for transmission */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static int -ip2_chars_in_buf ( PTTY tty ) -{ - i2ChanStrPtr pCh = tty->driver_data; - int rc; - unsigned long flags; - - ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff ); - -#ifdef IP2DEBUG_WRITE - printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n", - pCh->Obuf_char_count + pCh->Pbuf_stuff, - pCh->Obuf_char_count, pCh->Pbuf_stuff ); -#endif - READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags); - rc = pCh->Obuf_char_count; - READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags); - READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); - rc += pCh->Pbuf_stuff; - READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); - return rc; -} - -/******************************************************************************/ -/* Function: ip2_flush_buffer() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_flush_buffer( PTTY tty ) -{ - i2ChanStrPtr pCh = tty->driver_data; - unsigned long flags; - - ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 ); - -#ifdef IP2DEBUG_WRITE - printk (KERN_DEBUG "IP2: flush buffer\n" ); -#endif - WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); - pCh->Pbuf_stuff = 0; - WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); - i2FlushOutput( pCh ); - ip2_owake(tty); - - ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 ); - -} - -/******************************************************************************/ -/* Function: ip2_wait_until_sent() */ -/* Parameters: Pointer to tty structure */ -/* Timeout for wait. */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This function is used in place of the normal tty_wait_until_sent, which */ -/* only waits for the driver buffers to be empty (or rather, those buffers */ -/* reported by chars_in_buffer) which doesn't work for IP2 due to the */ -/* indeterminate number of bytes buffered on the board. */ -/******************************************************************************/ -static void -ip2_wait_until_sent ( PTTY tty, int timeout ) -{ - int i = jiffies; - i2ChanStrPtr pCh = tty->driver_data; - - tty_wait_until_sent(tty, timeout ); - if ( (i = timeout - (jiffies -i)) > 0) - i2DrainOutput( pCh, i ); -} - -/******************************************************************************/ -/******************************************************************************/ -/* Device Input Section */ -/******************************************************************************/ -/******************************************************************************/ - -/******************************************************************************/ -/* Function: ip2_throttle() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_throttle ( PTTY tty ) -{ - i2ChanStrPtr pCh = tty->driver_data; - -#ifdef IP2DEBUG_READ - printk (KERN_DEBUG "IP2: throttle\n" ); -#endif - /* - * Signal the poll/interrupt handlers not to forward incoming data to - * the line discipline. This will cause the buffers to fill up in the - * library and thus cause the library routines to send the flow control - * stuff. - */ - pCh->throttled = 1; -} - -/******************************************************************************/ -/* Function: ip2_unthrottle() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_unthrottle ( PTTY tty ) -{ - i2ChanStrPtr pCh = tty->driver_data; - unsigned long flags; - -#ifdef IP2DEBUG_READ - printk (KERN_DEBUG "IP2: unthrottle\n" ); -#endif - - /* Pass incoming data up to the line discipline again. */ - pCh->throttled = 0; - i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); - serviceOutgoingFifo( pCh->pMyBord ); - READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags) - if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) { - READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags) -#ifdef IP2DEBUG_READ - printk (KERN_DEBUG "i2Input called from unthrottle\n" ); -#endif - i2Input( pCh ); - } else - READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags) -} - -static void -ip2_start ( PTTY tty ) -{ - i2ChanStrPtr pCh = DevTable[tty->index]; - - i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND); - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME); -#ifdef IP2DEBUG_WRITE - printk (KERN_DEBUG "IP2: start tx\n" ); -#endif -} - -static void -ip2_stop ( PTTY tty ) -{ - i2ChanStrPtr pCh = DevTable[tty->index]; - - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND); -#ifdef IP2DEBUG_WRITE - printk (KERN_DEBUG "IP2: stop tx\n" ); -#endif -} - -/******************************************************************************/ -/* Device Ioctl Section */ -/******************************************************************************/ - -static int ip2_tiocmget(struct tty_struct *tty, struct file *file) -{ - i2ChanStrPtr pCh = DevTable[tty->index]; -#ifdef ENABLE_DSSNOW - wait_queue_t wait; -#endif - - if (pCh == NULL) - return -ENODEV; - -/* - FIXME - the following code is causing a NULL pointer dereference in - 2.3.51 in an interrupt handler. It's suppose to prompt the board - to return the DSS signal status immediately. Why doesn't it do - the same thing in 2.2.14? -*/ - -/* This thing is still busted in the 1.2.12 driver on 2.4.x - and even hoses the serial console so the oops can be trapped. - /\/\|=mhw=|\/\/ */ - -#ifdef ENABLE_DSSNOW - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW); - - init_waitqueue_entry(&wait, current); - add_wait_queue(&pCh->dss_now_wait, &wait); - set_current_state( TASK_INTERRUPTIBLE ); - - serviceOutgoingFifo( pCh->pMyBord ); - - schedule(); - - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->dss_now_wait, &wait); - - if (signal_pending(current)) { - return -EINTR; - } -#endif - return ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0) - | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0) - | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0) - | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0) - | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0) - | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0); -} - -static int ip2_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) -{ - i2ChanStrPtr pCh = DevTable[tty->index]; - - if (pCh == NULL) - return -ENODEV; - - if (set & TIOCM_RTS) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP); - pCh->dataSetOut |= I2_RTS; - } - if (set & TIOCM_DTR) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP); - pCh->dataSetOut |= I2_DTR; - } - - if (clear & TIOCM_RTS) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN); - pCh->dataSetOut &= ~I2_RTS; - } - if (clear & TIOCM_DTR) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN); - pCh->dataSetOut &= ~I2_DTR; - } - serviceOutgoingFifo( pCh->pMyBord ); - return 0; -} - -/******************************************************************************/ -/* Function: ip2_ioctl() */ -/* Parameters: Pointer to tty structure */ -/* Pointer to file structure */ -/* Command */ -/* Argument */ -/* Returns: Success or failure */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static int -ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) -{ - wait_queue_t wait; - i2ChanStrPtr pCh = DevTable[tty->index]; - i2eBordStrPtr pB; - struct async_icount cprev, cnow; /* kernel counter temps */ - struct serial_icounter_struct __user *p_cuser; - int rc = 0; - unsigned long flags; - void __user *argp = (void __user *)arg; - - if ( pCh == NULL ) - return -ENODEV; - - pB = pCh->pMyBord; - - ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg ); - -#ifdef IP2DEBUG_IOCTL - printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg ); -#endif - - switch(cmd) { - case TIOCGSERIAL: - - ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc ); - - rc = get_serial_info(pCh, argp); - if (rc) - return rc; - break; - - case TIOCSSERIAL: - - ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc ); - - rc = set_serial_info(pCh, argp); - if (rc) - return rc; - break; - - case TCXONC: - rc = tty_check_change(tty); - if (rc) - return rc; - switch (arg) { - case TCOOFF: - //return -ENOIOCTLCMD; - break; - case TCOON: - //return -ENOIOCTLCMD; - break; - case TCIOFF: - if (STOP_CHAR(tty) != __DISABLED_CHAR) { - i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, - CMD_XMIT_NOW(STOP_CHAR(tty))); - } - break; - case TCION: - if (START_CHAR(tty) != __DISABLED_CHAR) { - i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, - CMD_XMIT_NOW(START_CHAR(tty))); - } - break; - default: - return -EINVAL; - } - return 0; - - case TCSBRK: /* SVID version: non-zero arg --> no break */ - rc = tty_check_change(tty); - - ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc ); - - if (!rc) { - ip2_wait_until_sent(tty,0); - if (!arg) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250)); - serviceOutgoingFifo( pCh->pMyBord ); - } - } - break; - - case TCSBRKP: /* support for POSIX tcsendbreak() */ - rc = tty_check_change(tty); - - ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc ); - - if (!rc) { - ip2_wait_until_sent(tty,0); - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, - CMD_SEND_BRK(arg ? arg*100 : 250)); - serviceOutgoingFifo ( pCh->pMyBord ); - } - break; - - case TIOCGSOFTCAR: - - ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc ); - - rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); - if (rc) - return rc; - break; - - case TIOCSSOFTCAR: - - ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc ); - - rc = get_user(arg,(unsigned long __user *) argp); - if (rc) - return rc; - tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) - | (arg ? CLOCAL : 0)); - - break; - - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask - * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS - * for masking). Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags); - cprev = pCh->icount; /* note the counters on entry */ - WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags); - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, - CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP); - init_waitqueue_entry(&wait, current); - add_wait_queue(&pCh->delta_msr_wait, &wait); - set_current_state( TASK_INTERRUPTIBLE ); - - serviceOutgoingFifo( pCh->pMyBord ); - for(;;) { - ip2trace (CHANN, ITRC_IOCTL, 10, 0 ); - - schedule(); - - ip2trace (CHANN, ITRC_IOCTL, 11, 0 ); - - /* see if a signal did it */ - if (signal_pending(current)) { - rc = -ERESTARTSYS; - break; - } - WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags); - cnow = pCh->icount; /* atomic copy */ - WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags); - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { - rc = -EIO; /* no change => rc */ - break; - } - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { - rc = 0; - break; - } - cprev = cnow; - } - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->delta_msr_wait, &wait); - - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, - CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); - if ( ! (pCh->flags & ASYNC_CHECK_CD)) { - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP); - } - serviceOutgoingFifo( pCh->pMyBord ); - return rc; - break; - - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for RI where - * only 0->1 is counted. The controller is quite capable of counting - * both, but this done to preserve compatibility with the standard - * serial driver. - */ - case TIOCGICOUNT: - ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc ); - - WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags); - cnow = pCh->icount; - WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags); - p_cuser = argp; - rc = put_user(cnow.cts, &p_cuser->cts); - rc = put_user(cnow.dsr, &p_cuser->dsr); - rc = put_user(cnow.rng, &p_cuser->rng); - rc = put_user(cnow.dcd, &p_cuser->dcd); - rc = put_user(cnow.rx, &p_cuser->rx); - rc = put_user(cnow.tx, &p_cuser->tx); - rc = put_user(cnow.frame, &p_cuser->frame); - rc = put_user(cnow.overrun, &p_cuser->overrun); - rc = put_user(cnow.parity, &p_cuser->parity); - rc = put_user(cnow.brk, &p_cuser->brk); - rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); - break; - - /* - * The rest are not supported by this driver. By returning -ENOIOCTLCMD they - * will be passed to the line discipline for it to handle. - */ - case TIOCSERCONFIG: - case TIOCSERGWILD: - case TIOCSERGETLSR: - case TIOCSERSWILD: - case TIOCSERGSTRUCT: - case TIOCSERGETMULTI: - case TIOCSERSETMULTI: - - default: - ip2trace (CHANN, ITRC_IOCTL, 12, 0 ); - - rc = -ENOIOCTLCMD; - break; - } - - ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 ); - - return rc; -} - -/******************************************************************************/ -/* Function: GetSerialInfo() */ -/* Parameters: Pointer to channel structure */ -/* Pointer to old termios structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This is to support the setserial command, and requires processing of the */ -/* standard Linux serial structure. */ -/******************************************************************************/ -static int -get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo ) -{ - struct serial_struct tmp; - - memset ( &tmp, 0, sizeof(tmp) ); - tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16]; - if (BID_HAS_654(tmp.type)) { - tmp.type = PORT_16650; - } else { - tmp.type = PORT_CIRRUS; - } - tmp.line = pCh->port_index; - tmp.port = pCh->pMyBord->i2eBase; - tmp.irq = ip2config.irq[pCh->port_index/64]; - tmp.flags = pCh->flags; - tmp.baud_base = pCh->BaudBase; - tmp.close_delay = pCh->ClosingDelay; - tmp.closing_wait = pCh->ClosingWaitTime; - tmp.custom_divisor = pCh->BaudDivisor; - return copy_to_user(retinfo,&tmp,sizeof(*retinfo)); -} - -/******************************************************************************/ -/* Function: SetSerialInfo() */ -/* Parameters: Pointer to channel structure */ -/* Pointer to old termios structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This function provides support for setserial, which uses the TIOCSSERIAL */ -/* ioctl. Not all setserial parameters are relevant. If the user attempts to */ -/* change the IRQ, address or type of the port the ioctl fails. */ -/******************************************************************************/ -static int -set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info ) -{ - struct serial_struct ns; - int old_flags, old_baud_divisor; - - if (copy_from_user(&ns, new_info, sizeof (ns))) - return -EFAULT; - - /* - * We don't allow setserial to change IRQ, board address, type or baud - * base. Also line nunber as such is meaningless but we use it for our - * array index so it is fixed also. - */ - if ( (ns.irq != ip2config.irq[pCh->port_index]) - || ((int) ns.port != ((int) (pCh->pMyBord->i2eBase))) - || (ns.baud_base != pCh->BaudBase) - || (ns.line != pCh->port_index) ) { - return -EINVAL; - } - - old_flags = pCh->flags; - old_baud_divisor = pCh->BaudDivisor; - - if ( !capable(CAP_SYS_ADMIN) ) { - if ( ( ns.close_delay != pCh->ClosingDelay ) || - ( (ns.flags & ~ASYNC_USR_MASK) != - (pCh->flags & ~ASYNC_USR_MASK) ) ) { - return -EPERM; - } - - pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) | - (ns.flags & ASYNC_USR_MASK); - pCh->BaudDivisor = ns.custom_divisor; - } else { - pCh->flags = (pCh->flags & ~ASYNC_FLAGS) | - (ns.flags & ASYNC_FLAGS); - pCh->BaudDivisor = ns.custom_divisor; - pCh->ClosingDelay = ns.close_delay * HZ/100; - pCh->ClosingWaitTime = ns.closing_wait * HZ/100; - } - - if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) ) - || (old_baud_divisor != pCh->BaudDivisor) ) { - // Invalidate speed and reset parameters - set_params( pCh, NULL ); - } - - return 0; -} - -/******************************************************************************/ -/* Function: ip2_set_termios() */ -/* Parameters: Pointer to tty structure */ -/* Pointer to old termios structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_set_termios( PTTY tty, struct termios *old_termios ) -{ - i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data; - -#ifdef IP2DEBUG_IOCTL - printk (KERN_DEBUG "IP2: set termios %p\n", old_termios ); -#endif - - set_params( pCh, old_termios ); -} - -/******************************************************************************/ -/* Function: ip2_set_line_discipline() */ -/* Parameters: Pointer to tty structure */ -/* Returns: Nothing */ -/* */ -/* Description: Does nothing */ -/* */ -/* */ -/******************************************************************************/ -static void -ip2_set_line_discipline ( PTTY tty ) -{ -#ifdef IP2DEBUG_IOCTL - printk (KERN_DEBUG "IP2: set line discipline\n" ); -#endif - - ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 ); - -} - -/******************************************************************************/ -/* Function: SetLine Characteristics() */ -/* Parameters: Pointer to channel structure */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This routine is called to update the channel structure with the new line */ -/* characteristics, and send the appropriate commands to the board when they */ -/* change. */ -/******************************************************************************/ -static void -set_params( i2ChanStrPtr pCh, struct termios *o_tios ) -{ - tcflag_t cflag, iflag, lflag; - char stop_char, start_char; - struct termios dummy; - - lflag = pCh->pTTY->termios->c_lflag; - cflag = pCh->pTTY->termios->c_cflag; - iflag = pCh->pTTY->termios->c_iflag; - - if (o_tios == NULL) { - dummy.c_lflag = ~lflag; - dummy.c_cflag = ~cflag; - dummy.c_iflag = ~iflag; - o_tios = &dummy; - } - - { - switch ( cflag & CBAUD ) { - case B0: - i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); - pCh->dataSetOut &= ~(I2_DTR | I2_RTS); - i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); - pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag); - goto service_it; - break; - case B38400: - /* - * This is the speed that is overloaded with all the other high - * speeds, depending upon the flag settings. - */ - if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) { - pCh->speed = CBR_57600; - } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) { - pCh->speed = CBR_115200; - } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) { - pCh->speed = CBR_C1; - } else { - pCh->speed = CBR_38400; - } - break; - case B50: pCh->speed = CBR_50; break; - case B75: pCh->speed = CBR_75; break; - case B110: pCh->speed = CBR_110; break; - case B134: pCh->speed = CBR_134; break; - case B150: pCh->speed = CBR_150; break; - case B200: pCh->speed = CBR_200; break; - case B300: pCh->speed = CBR_300; break; - case B600: pCh->speed = CBR_600; break; - case B1200: pCh->speed = CBR_1200; break; - case B1800: pCh->speed = CBR_1800; break; - case B2400: pCh->speed = CBR_2400; break; - case B4800: pCh->speed = CBR_4800; break; - case B9600: pCh->speed = CBR_9600; break; - case B19200: pCh->speed = CBR_19200; break; - case B57600: pCh->speed = CBR_57600; break; - case B115200: pCh->speed = CBR_115200; break; - case B153600: pCh->speed = CBR_153600; break; - case B230400: pCh->speed = CBR_230400; break; - case B307200: pCh->speed = CBR_307200; break; - case B460800: pCh->speed = CBR_460800; break; - case B921600: pCh->speed = CBR_921600; break; - default: pCh->speed = CBR_9600; break; - } - if ( pCh->speed == CBR_C1 ) { - // Process the custom speed parameters. - int bps = pCh->BaudBase / pCh->BaudDivisor; - if ( bps == 921600 ) { - pCh->speed = CBR_921600; - } else { - bps = bps/10; - i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) ); - } - } - i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed)); - - i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); - pCh->dataSetOut |= (I2_DTR | I2_RTS); - } - if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) - { - i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, - CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1)); - } - if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) - { - i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, - CMD_SETPAR( - (cflag & PARENB ? (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP) - ) - ); - } - /* byte size and parity */ - if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) - { - int datasize; - switch ( cflag & CSIZE ) { - case CS5: datasize = CSZ_5; break; - case CS6: datasize = CSZ_6; break; - case CS7: datasize = CSZ_7; break; - case CS8: datasize = CSZ_8; break; - default: datasize = CSZ_5; break; /* as per serial.c */ - } - i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) ); - } - /* Process CTS flow control flag setting */ - if ( (cflag & CRTSCTS) ) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, - 2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB); - } else { - i2QueueCommands(PTYPE_INLINE, pCh, 100, - 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); - } - // - // Process XON/XOFF flow control flags settings - // - stop_char = STOP_CHAR(pCh->pTTY); - start_char = START_CHAR(pCh->pTTY); - - //////////// can't be \000 - if (stop_char == __DISABLED_CHAR ) - { - stop_char = ~__DISABLED_CHAR; - } - if (start_char == __DISABLED_CHAR ) - { - start_char = ~__DISABLED_CHAR; - } - ///////////////////////////////// - - if ( o_tios->c_cc[VSTART] != start_char ) - { - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char)); - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char)); - } - if ( o_tios->c_cc[VSTOP] != stop_char ) - { - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char)); - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char)); - } - if (stop_char == __DISABLED_CHAR ) - { - stop_char = ~__DISABLED_CHAR; //TEST123 - goto no_xoff; - } - if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) - { - if ( iflag & IXOFF ) { // Enable XOFF output flow control - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON)); - } else { // Disable XOFF output flow control -no_xoff: - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE)); - } - } - if (start_char == __DISABLED_CHAR ) - { - goto no_xon; - } - if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) - { - if ( iflag & IXON ) { - if ( iflag & IXANY ) { // Enable XON/XANY output flow control - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY)); - } else { // Enable XON output flow control - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON)); - } - } else { // Disable XON output flow control -no_xon: - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE)); - } - } - if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) - { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, - CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0))); - } - if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) - { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, - CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB)); - } - - if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) - ^ ( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) - { - char brkrpt = 0; - char parrpt = 0; - - if ( iflag & IGNBRK ) { /* Ignore breaks altogether */ - /* Ignore breaks altogether */ - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP); - } else { - if ( iflag & BRKINT ) { - if ( iflag & PARMRK ) { - brkrpt = 0x0a; // exception an inline triple - } else { - brkrpt = 0x1a; // exception and NULL - } - brkrpt |= 0x04; // flush input - } else { - if ( iflag & PARMRK ) { - brkrpt = 0x0b; //POSIX triple \0377 \0 \0 - } else { - brkrpt = 0x01; // Null only - } - } - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt)); - } - - if (iflag & IGNPAR) { - parrpt = 0x20; - /* would be 2 for not cirrus bug */ - /* would be 0x20 cept for cirrus bug */ - } else { - if ( iflag & PARMRK ) { - /* - * Replace error characters with 3-byte sequence (\0377,\0,char) - */ - parrpt = 0x04 ; - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0)); - } else { - parrpt = 0x03; - } - } - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt)); - } - if (cflag & CLOCAL) { - // Status reporting fails for DCD if this is off - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP); - pCh->flags &= ~ASYNC_CHECK_CD; - } else { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP); - pCh->flags |= ASYNC_CHECK_CD; - } - -service_it: - i2DrainOutput( pCh, 100 ); -} - -/******************************************************************************/ -/* IPL Device Section */ -/******************************************************************************/ - -/******************************************************************************/ -/* Function: ip2_ipl_read() */ -/* Parameters: Pointer to device inode */ -/* Pointer to file structure */ -/* Pointer to data */ -/* Number of bytes to read */ -/* Returns: Success or failure */ -/* */ -/* Description: Ugly */ -/* */ -/* */ -/******************************************************************************/ - -static -ssize_t -ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off ) -{ - unsigned int minor = iminor(pFile->f_dentry->d_inode); - int rc = 0; - -#ifdef IP2DEBUG_IPL - printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count ); -#endif - - switch( minor ) { - case 0: // IPL device - rc = -EINVAL; - break; - case 1: // Status dump - rc = -EINVAL; - break; - case 2: // Ping device - rc = -EINVAL; - break; - case 3: // Trace device - rc = DumpTraceBuffer ( pData, count ); - break; - case 4: // Trace device - rc = DumpFifoBuffer ( pData, count ); - break; - default: - rc = -ENODEV; - break; - } - return rc; -} - -static int -DumpFifoBuffer ( char __user *pData, int count ) -{ -#ifdef DEBUG_FIFO - int rc; - rc = copy_to_user(pData, DBGBuf, count); - - printk(KERN_DEBUG "Last index %d\n", I ); - - return count; -#endif /* DEBUG_FIFO */ - return 0; -} - -static int -DumpTraceBuffer ( char __user *pData, int count ) -{ -#ifdef IP2DEBUG_TRACE - int rc; - int dumpcount; - int chunk; - int *pIndex = (int __user *)pData; - - if ( count < (sizeof(int) * 6) ) { - return -EIO; - } - rc = put_user(tracewrap, pIndex ); - rc = put_user(TRACEMAX, ++pIndex ); - rc = put_user(tracestrip, ++pIndex ); - rc = put_user(tracestuff, ++pIndex ); - pData += sizeof(int) * 6; - count -= sizeof(int) * 6; - - dumpcount = tracestuff - tracestrip; - if ( dumpcount < 0 ) { - dumpcount += TRACEMAX; - } - if ( dumpcount > count ) { - dumpcount = count; - } - chunk = TRACEMAX - tracestrip; - if ( dumpcount > chunk ) { - rc = copy_to_user(pData, &tracebuf[tracestrip], - chunk * sizeof(tracebuf[0]) ); - pData += chunk * sizeof(tracebuf[0]); - tracestrip = 0; - chunk = dumpcount - chunk; - } else { - chunk = dumpcount; - } - rc = copy_to_user(pData, &tracebuf[tracestrip], - chunk * sizeof(tracebuf[0]) ); - tracestrip += chunk; - tracewrap = 0; - - rc = put_user(tracestrip, ++pIndex ); - rc = put_user(tracestuff, ++pIndex ); - - return dumpcount; -#else - return 0; -#endif -} - -/******************************************************************************/ -/* Function: ip2_ipl_write() */ -/* Parameters: */ -/* Pointer to file structure */ -/* Pointer to data */ -/* Number of bytes to write */ -/* Returns: Success or failure */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static ssize_t -ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off) -{ -#ifdef IP2DEBUG_IPL - printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count ); -#endif - return 0; -} - -/******************************************************************************/ -/* Function: ip2_ipl_ioctl() */ -/* Parameters: Pointer to device inode */ -/* Pointer to file structure */ -/* Command */ -/* Argument */ -/* Returns: Success or failure */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static int -ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) -{ - unsigned int iplminor = iminor(pInode); - int rc = 0; - void __user *argp = (void __user *)arg; - ULONG __user *pIndex = argp; - i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4]; - i2ChanStrPtr pCh; - -#ifdef IP2DEBUG_IPL - printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); -#endif - - switch ( iplminor ) { - case 0: // IPL device - rc = -EINVAL; - break; - case 1: // Status dump - case 5: - case 9: - case 13: - switch ( cmd ) { - case 64: /* Driver - ip2stat */ - rc = put_user(ip2_tty_driver->refcount, pIndex++ ); - rc = put_user(irq_counter, pIndex++ ); - rc = put_user(bh_counter, pIndex++ ); - break; - - case 65: /* Board - ip2stat */ - if ( pB ) { - rc = copy_to_user(argp, pB, sizeof(i2eBordStr)); - rc = put_user(INB(pB->i2eStatus), - (ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) ); - } else { - rc = -ENODEV; - } - break; - - default: - if (cmd < IP2_MAX_PORTS) { - pCh = DevTable[cmd]; - if ( pCh ) - { - rc = copy_to_user(argp, pCh, sizeof(i2ChanStr)); - } else { - rc = -ENODEV; - } - } else { - rc = -EINVAL; - } - } - break; - - case 2: // Ping device - rc = -EINVAL; - break; - case 3: // Trace device - if ( cmd == 1 ) { - rc = put_user(iiSendPendingMail, pIndex++ ); - rc = put_user(i2InitChannels, pIndex++ ); - rc = put_user(i2QueueNeeds, pIndex++ ); - rc = put_user(i2QueueCommands, pIndex++ ); - rc = put_user(i2GetStatus, pIndex++ ); - rc = put_user(i2Input, pIndex++ ); - rc = put_user(i2InputFlush, pIndex++ ); - rc = put_user(i2Output, pIndex++ ); - rc = put_user(i2FlushOutput, pIndex++ ); - rc = put_user(i2DrainWakeup, pIndex++ ); - rc = put_user(i2DrainOutput, pIndex++ ); - rc = put_user(i2OutputFree, pIndex++ ); - rc = put_user(i2StripFifo, pIndex++ ); - rc = put_user(i2StuffFifoBypass, pIndex++ ); - rc = put_user(i2StuffFifoFlow, pIndex++ ); - rc = put_user(i2StuffFifoInline, pIndex++ ); - rc = put_user(i2ServiceBoard, pIndex++ ); - rc = put_user(serviceOutgoingFifo, pIndex++ ); - // rc = put_user(ip2_init, pIndex++ ); - rc = put_user(ip2_init_board, pIndex++ ); - rc = put_user(find_eisa_board, pIndex++ ); - rc = put_user(set_irq, pIndex++ ); - rc = put_user(ip2_interrupt, pIndex++ ); - rc = put_user(ip2_poll, pIndex++ ); - rc = put_user(service_all_boards, pIndex++ ); - rc = put_user(do_input, pIndex++ ); - rc = put_user(do_status, pIndex++ ); -#ifndef IP2DEBUG_OPEN - rc = put_user(0, pIndex++ ); -#else - rc = put_user(open_sanity_check, pIndex++ ); -#endif - rc = put_user(ip2_open, pIndex++ ); - rc = put_user(ip2_close, pIndex++ ); - rc = put_user(ip2_hangup, pIndex++ ); - rc = put_user(ip2_write, pIndex++ ); - rc = put_user(ip2_putchar, pIndex++ ); - rc = put_user(ip2_flush_chars, pIndex++ ); - rc = put_user(ip2_write_room, pIndex++ ); - rc = put_user(ip2_chars_in_buf, pIndex++ ); - rc = put_user(ip2_flush_buffer, pIndex++ ); - - //rc = put_user(ip2_wait_until_sent, pIndex++ ); - rc = put_user(0, pIndex++ ); - - rc = put_user(ip2_throttle, pIndex++ ); - rc = put_user(ip2_unthrottle, pIndex++ ); - rc = put_user(ip2_ioctl, pIndex++ ); - rc = put_user(0, pIndex++ ); - rc = put_user(get_serial_info, pIndex++ ); - rc = put_user(set_serial_info, pIndex++ ); - rc = put_user(ip2_set_termios, pIndex++ ); - rc = put_user(ip2_set_line_discipline, pIndex++ ); - rc = put_user(set_params, pIndex++ ); - } else { - rc = -EINVAL; - } - - break; - - default: - rc = -ENODEV; - break; - } - return rc; -} - -/******************************************************************************/ -/* Function: ip2_ipl_open() */ -/* Parameters: Pointer to device inode */ -/* Pointer to file structure */ -/* Returns: Success or failure */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -static int -ip2_ipl_open( struct inode *pInode, struct file *pFile ) -{ - unsigned int iplminor = iminor(pInode); - i2eBordStrPtr pB; - i2ChanStrPtr pCh; - -#ifdef IP2DEBUG_IPL - printk (KERN_DEBUG "IP2IPL: open\n" ); -#endif - - switch(iplminor) { - // These are the IPL devices - case 0: - case 4: - case 8: - case 12: - break; - - // These are the status devices - case 1: - case 5: - case 9: - case 13: - break; - - // These are the debug devices - case 2: - case 6: - case 10: - case 14: - pB = i2BoardPtrTable[iplminor / 4]; - pCh = (i2ChanStrPtr) pB->i2eChannelPtr; - break; - - // This is the trace device - case 3: - break; - } - return 0; -} -/******************************************************************************/ -/* Function: ip2_read_procmem */ -/* Parameters: */ -/* */ -/* Returns: Length of output */ -/* */ -/* Description: */ -/* Supplies some driver operating parameters */ -/* Not real useful unless your debugging the fifo */ -/* */ -/******************************************************************************/ - -#define LIMIT (PAGE_SIZE - 120) - -static int -ip2_read_procmem(char *buf, char **start, off_t offset, int len) -{ - i2eBordStrPtr pB; - i2ChanStrPtr pCh; - PTTY tty; - int i; - - len = 0; - -#define FMTLINE "%3d: 0x%08x 0x%08x 0%011o 0%011o\n" -#define FMTLIN2 " 0x%04x 0x%04x tx flow 0x%x\n" -#define FMTLIN3 " 0x%04x 0x%04x rc flow\n" - - len += sprintf(buf+len,"\n"); - - for( i = 0; i < IP2_MAX_BOARDS; ++i ) { - pB = i2BoardPtrTable[i]; - if ( pB ) { - len += sprintf(buf+len,"board %d:\n",i); - len += sprintf(buf+len,"\tFifo rem: %d mty: %x outM %x\n", - pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting); - } - } - - len += sprintf(buf+len,"#: tty flags, port flags, cflags, iflags\n"); - for (i=0; i < IP2_MAX_PORTS; i++) { - if (len > LIMIT) - break; - pCh = DevTable[i]; - if (pCh) { - tty = pCh->pTTY; - if (tty && tty->count) { - len += sprintf(buf+len,FMTLINE,i,(int)tty->flags,pCh->flags, - tty->termios->c_cflag,tty->termios->c_iflag); - - len += sprintf(buf+len,FMTLIN2, - pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds); - len += sprintf(buf+len,FMTLIN3,pCh->infl.asof,pCh->infl.room); - } - } - } - return len; -} - -/* - * This is the handler for /proc/tty/driver/ip2 - * - * This stretch of code has been largely plagerized from at least three - * different sources including ip2mkdev.c and a couple of other drivers. - * The bugs are all mine. :-) =mhw= - */ -static int ip2_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int i, j, box; - int len = 0; - int boxes = 0; - int ports = 0; - int tports = 0; - off_t begin = 0; - i2eBordStrPtr pB; - - len += sprintf(page, "ip2info: 1.0 driver: %s\n", pcVersion ); - len += sprintf(page+len, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", - IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, - IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); - - for( i = 0; i < IP2_MAX_BOARDS; ++i ) { - /* This need to be reset for a board by board count... */ - boxes = 0; - pB = i2BoardPtrTable[i]; - if( pB ) { - switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) - { - case POR_ID_FIIEX: - len += sprintf( page+len, "Board %d: EX ports=", i ); - for( box = 0; box < ABS_MAX_BOXES; ++box ) - { - ports = 0; - - if( pB->i2eChannelMap[box] != 0 ) ++boxes; - for( j = 0; j < ABS_BIGGEST_BOX; ++j ) - { - if( pB->i2eChannelMap[box] & 1<< j ) { - ++ports; - } - } - len += sprintf( page+len, "%d,", ports ); - tports += ports; - } - - --len; /* Backup over that last comma */ - - len += sprintf( page+len, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8 ); - break; - - case POR_ID_II_4: - len += sprintf(page+len, "Board %d: ISA-4 ports=4 boxes=1", i ); - tports = ports = 4; - break; - - case POR_ID_II_8: - len += sprintf(page+len, "Board %d: ISA-8-std ports=8 boxes=1", i ); - tports = ports = 8; - break; - - case POR_ID_II_8R: - len += sprintf(page+len, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i ); - tports = ports = 8; - break; - - default: - len += sprintf(page+len, "Board %d: unknown", i ); - /* Don't try and probe for minor numbers */ - tports = ports = 0; - } - - } else { - /* Don't try and probe for minor numbers */ - len += sprintf(page+len, "Board %d: vacant", i ); - tports = ports = 0; - } - - if( tports ) { - len += sprintf(page+len, " minors=" ); - - for ( box = 0; box < ABS_MAX_BOXES; ++box ) - { - for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) - { - if ( pB->i2eChannelMap[box] & (1 << j) ) - { - len += sprintf (page+len,"%d,", - j + ABS_BIGGEST_BOX * - (box+i*ABS_MAX_BOXES)); - } - } - } - - page[ len - 1 ] = '\n'; /* Overwrite that last comma */ - } else { - len += sprintf (page+len,"\n" ); - } - - if (len+begin > off+count) - break; - if (len+begin < off) { - begin += len; - len = 0; - } - } - - if (i >= IP2_MAX_BOARDS) - *eof = 1; - if (off >= len+begin) - return 0; - - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); - } - -/******************************************************************************/ -/* Function: ip2trace() */ -/* Parameters: Value to add to trace buffer */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* */ -/* */ -/******************************************************************************/ -#ifdef IP2DEBUG_TRACE -void -ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...) -{ - long flags; - unsigned long *pCode = &codes; - union ip2breadcrumb bc; - i2ChanStrPtr pCh; - - - tracebuf[tracestuff++] = jiffies; - if ( tracestuff == TRACEMAX ) { - tracestuff = 0; - } - if ( tracestuff == tracestrip ) { - if ( ++tracestrip == TRACEMAX ) { - tracestrip = 0; - } - ++tracewrap; - } - - bc.hdr.port = 0xff & pn; - bc.hdr.cat = cat; - bc.hdr.codes = (unsigned char)( codes & 0xff ); - bc.hdr.label = label; - tracebuf[tracestuff++] = bc.value; - - for (;;) { - if ( tracestuff == TRACEMAX ) { - tracestuff = 0; - } - if ( tracestuff == tracestrip ) { - if ( ++tracestrip == TRACEMAX ) { - tracestrip = 0; - } - ++tracewrap; - } - - if ( !codes-- ) - break; - - tracebuf[tracestuff++] = *++pCode; - } -} -#endif - - -MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From f74a6b395a6dea5028a1604e721dfb2b5c18fc86 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 17 Jan 2006 03:50:23 -0200 Subject: V4L/DVB (3392): Add PCI ID for DigitalNow DVB-T Dual, rebranded DViCO FusionHDTV DVB-T Dual. - Add PCI ID for DigitalNow DVB-T Dual, rebranded DViCO FusionHDTV DVB-T Dual. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 2 +- drivers/media/video/cx88/cx88-cards.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 56e194f1a0b0..8bea3fbd0548 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -42,4 +42,4 @@ 41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile) [0070:9800,0070:9802] 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025] 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1] - 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50] + 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index ad2f565f522c..517257b4d2d4 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1244,6 +1244,11 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x18ac, .subdevice = 0xdb50, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, + },{ + .subvendor = 0x18ac, + .subdevice = 0xdb54, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, + /* Re-branded DViCO: DigitalNow DVB-T Dual */ },{ .subvendor = 0x18ac, .subdevice = 0xdb11, -- cgit v1.2.3-59-g8ed1b From bf47e4e43e4dcf88fef61b1b4139ce2da20e1f73 Mon Sep 17 00:00:00 2001 From: "J.O. Aho" Date: Mon, 23 Jan 2006 09:34:06 -0200 Subject: V4L/DVB (3395): Hauppauge Grey Remote support - For the Hauppauge PVR cards there are at least two different remotes, one completly black and one that is Grey and black, they keys differ in values eg Black remotes 'mute' has the same value as Grey remotes 'menu'. - This enables the user to select which keymapping to use by using the hauppauge parm. Unlike to the black remote keys, all keys are mapped for the grey remote and the ATi usb remote mappings has been followed. Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ir-kbd-i2c.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 58b0e6982822..3963481b3130 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -89,6 +89,11 @@ static IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { static int debug; module_param(debug, int, 0644); /* debug level (0,1,2) */ +static int hauppauge = 0; +module_param(hauppauge, int, 0644); /* Choose Hauppauge remote */ +MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)"); + + #define DEVNAME "ir-kbd-i2c" #define dprintk(level, fmt, arg...) if (debug >= level) \ printk(KERN_DEBUG DEVNAME ": " fmt , ## arg) @@ -336,7 +341,11 @@ static int ir_attach(struct i2c_adapter *adap, int addr, name = "Hauppauge"; ir->get_key = get_key_haup; ir_type = IR_TYPE_RC5; - ir_codes = ir_codes_rc5_tv; + if (hauppauge == 1) { + ir_codes = ir_codes_rc5_tv_grey; + } else { + ir_codes = ir_codes_rc5_tv; + } break; case 0x30: name = "KNC One"; -- cgit v1.2.3-59-g8ed1b From 4c0f631e14b849782259519c749414b1f1ddbfa8 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Mon, 23 Jan 2006 09:42:06 -0200 Subject: V4L/DVB (3393): Move all IR keymaps to ir-common module - All the keymaps have the same structure, and can be shared between different chips, so it makes no sense having them scattered between the input files. This aggregates them all at ir-common module. - Added new Hauppauge remote (Hauppauge grey), contributed by J.O. Aho (with some small changes) Changed KEY_KPx (keypad numerals) references to KEY_x, to avoid problems when NumLock is off (suggested by Peter Missel ) - Some cleanups at IR code Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/Makefile | 1 + drivers/media/common/ir-common.c | 519 --------- drivers/media/common/ir-keymaps.c | 1537 +++++++++++++++++++++++++++ drivers/media/video/bttv-input.c | 245 ----- drivers/media/video/cx88/cx88-input.c | 331 ------ drivers/media/video/em28xx/em28xx-input.c | 85 -- drivers/media/video/ir-kbd-i2c.c | 41 +- drivers/media/video/saa7134/saa7134-input.c | 501 +-------- include/media/ir-common.h | 42 +- 9 files changed, 1585 insertions(+), 1717 deletions(-) delete mode 100644 drivers/media/common/ir-common.c create mode 100644 drivers/media/common/ir-keymaps.c (limited to 'drivers') diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index bd458cb9b4ea..61b89617a967 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile @@ -1,5 +1,6 @@ saa7146-objs := saa7146_i2c.o saa7146_core.o saa7146_vv-objs := saa7146_vv_ksyms.o saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o +ir-common-objs := ir-functions.o ir-keymaps.o obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c deleted file mode 100644 index 97fa3fc571c4..000000000000 --- a/drivers/media/common/ir-common.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * - * some common structs and functions to handle infrared remotes via - * input layer ... - * - * (c) 2003 Gerd Knorr [SuSE Labs] - * - * 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 - -/* -------------------------------------------------------------------------- */ - -MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); -MODULE_LICENSE("GPL"); - -static int repeat = 1; -module_param(repeat, int, 0444); -MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); - -static int debug = 0; /* debug level (0,1,2) */ -module_param(debug, int, 0644); - -#define dprintk(level, fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG fmt , ## arg) - -/* -------------------------------------------------------------------------- */ - -/* generic RC5 keytable */ -/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ -/* used by old (black) Hauppauge remotes */ -IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { - /* Keys 0 to 9 */ - [ 0x00 ] = KEY_KP0, - [ 0x01 ] = KEY_KP1, - [ 0x02 ] = KEY_KP2, - [ 0x03 ] = KEY_KP3, - [ 0x04 ] = KEY_KP4, - [ 0x05 ] = KEY_KP5, - [ 0x06 ] = KEY_KP6, - [ 0x07 ] = KEY_KP7, - [ 0x08 ] = KEY_KP8, - [ 0x09 ] = KEY_KP9, - - [ 0x0b ] = KEY_CHANNEL, /* channel / program (japan: 11) */ - [ 0x0c ] = KEY_POWER, /* standby */ - [ 0x0d ] = KEY_MUTE, /* mute / demute */ - [ 0x0f ] = KEY_TV, /* display */ - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x12 ] = KEY_BRIGHTNESSUP, - [ 0x13 ] = KEY_BRIGHTNESSDOWN, - [ 0x1e ] = KEY_SEARCH, /* search + */ - [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ - [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ - [ 0x22 ] = KEY_CHANNEL, /* alt / channel */ - [ 0x23 ] = KEY_LANGUAGE, /* 1st / 2nd language */ - [ 0x26 ] = KEY_SLEEP, /* sleeptimer */ - [ 0x2e ] = KEY_MENU, /* 2nd controls (USA: menu) */ - [ 0x30 ] = KEY_PAUSE, - [ 0x32 ] = KEY_REWIND, - [ 0x33 ] = KEY_GOTO, - [ 0x35 ] = KEY_PLAY, - [ 0x36 ] = KEY_STOP, - [ 0x37 ] = KEY_RECORD, /* recording */ - [ 0x3c ] = KEY_TEXT, /* teletext submode (Japan: 12) */ - [ 0x3d ] = KEY_SUSPEND, /* system standby */ - -}; -EXPORT_SYMBOL_GPL(ir_codes_rc5_tv); - -/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ -IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { - /* Keys 0 to 9 */ - [ 18 ] = KEY_KP0, - [ 5 ] = KEY_KP1, - [ 6 ] = KEY_KP2, - [ 7 ] = KEY_KP3, - [ 9 ] = KEY_KP4, - [ 10 ] = KEY_KP5, - [ 11 ] = KEY_KP6, - [ 13 ] = KEY_KP7, - [ 14 ] = KEY_KP8, - [ 15 ] = KEY_KP9, - - [ 0 ] = KEY_POWER, - [ 2 ] = KEY_TUNER, /* TV/FM */ - [ 30 ] = KEY_VIDEO, - [ 4 ] = KEY_VOLUMEUP, - [ 8 ] = KEY_VOLUMEDOWN, - [ 12 ] = KEY_CHANNELUP, - [ 16 ] = KEY_CHANNELDOWN, - [ 3 ] = KEY_ZOOM, /* fullscreen */ - [ 31 ] = KEY_SUBTITLE, /* closed caption/teletext */ - [ 32 ] = KEY_SLEEP, - [ 20 ] = KEY_MUTE, - [ 43 ] = KEY_RED, - [ 44 ] = KEY_GREEN, - [ 45 ] = KEY_YELLOW, - [ 46 ] = KEY_BLUE, - [ 24 ] = KEY_KPPLUS, /* fine tune + */ - [ 25 ] = KEY_KPMINUS, /* fine tune - */ - [ 33 ] = KEY_KPDOT, - [ 19 ] = KEY_KPENTER, - [ 34 ] = KEY_BACK, - [ 35 ] = KEY_PLAYPAUSE, - [ 36 ] = KEY_NEXT, - [ 38 ] = KEY_STOP, - [ 39 ] = KEY_RECORD -}; -EXPORT_SYMBOL_GPL(ir_codes_winfast); - -IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { - [ 0x59 ] = KEY_MUTE, - [ 0x4a ] = KEY_POWER, - - [ 0x18 ] = KEY_TEXT, - [ 0x26 ] = KEY_TV, - [ 0x3d ] = KEY_PRINT, - - [ 0x48 ] = KEY_RED, - [ 0x04 ] = KEY_GREEN, - [ 0x11 ] = KEY_YELLOW, - [ 0x00 ] = KEY_BLUE, - - [ 0x2d ] = KEY_VOLUMEUP, - [ 0x1e ] = KEY_VOLUMEDOWN, - - [ 0x49 ] = KEY_MENU, - - [ 0x16 ] = KEY_CHANNELUP, - [ 0x17 ] = KEY_CHANNELDOWN, - - [ 0x20 ] = KEY_UP, - [ 0x21 ] = KEY_DOWN, - [ 0x22 ] = KEY_LEFT, - [ 0x23 ] = KEY_RIGHT, - [ 0x0d ] = KEY_SELECT, - - - - [ 0x08 ] = KEY_BACK, - [ 0x07 ] = KEY_REFRESH, - - [ 0x2f ] = KEY_ZOOM, - [ 0x29 ] = KEY_RECORD, - - [ 0x4b ] = KEY_PAUSE, - [ 0x4d ] = KEY_REWIND, - [ 0x2e ] = KEY_PLAY, - [ 0x4e ] = KEY_FORWARD, - [ 0x53 ] = KEY_PREVIOUS, - [ 0x4c ] = KEY_STOP, - [ 0x54 ] = KEY_NEXT, - - [ 0x69 ] = KEY_KP0, - [ 0x6a ] = KEY_KP1, - [ 0x6b ] = KEY_KP2, - [ 0x6c ] = KEY_KP3, - [ 0x6d ] = KEY_KP4, - [ 0x6e ] = KEY_KP5, - [ 0x6f ] = KEY_KP6, - [ 0x70 ] = KEY_KP7, - [ 0x71 ] = KEY_KP8, - [ 0x72 ] = KEY_KP9, - - [ 0x74 ] = KEY_CHANNEL, - [ 0x0a ] = KEY_BACKSPACE, -}; - -EXPORT_SYMBOL_GPL(ir_codes_pinnacle); - -/* empty keytable, can be used as placeholder for not-yet created keytables */ -IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { - [ 42 ] = KEY_COFFEE, -}; -EXPORT_SYMBOL_GPL(ir_codes_empty); - -/* Hauppauge: the newer, gray remotes (seems there are multiple - * slightly different versions), shipped with cx88+ivtv cards. - * almost rc5 coding, but some non-standard keys */ -IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { - /* Keys 0 to 9 */ - [ 0x00 ] = KEY_KP0, - [ 0x01 ] = KEY_KP1, - [ 0x02 ] = KEY_KP2, - [ 0x03 ] = KEY_KP3, - [ 0x04 ] = KEY_KP4, - [ 0x05 ] = KEY_KP5, - [ 0x06 ] = KEY_KP6, - [ 0x07 ] = KEY_KP7, - [ 0x08 ] = KEY_KP8, - [ 0x09 ] = KEY_KP9, - - [ 0x0a ] = KEY_TEXT, /* keypad asterisk as well */ - [ 0x0b ] = KEY_RED, /* red button */ - [ 0x0c ] = KEY_RADIO, - [ 0x0d ] = KEY_MENU, - [ 0x0e ] = KEY_SUBTITLE, /* also the # key */ - [ 0x0f ] = KEY_MUTE, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x12 ] = KEY_PREVIOUS, /* previous channel */ - [ 0x14 ] = KEY_UP, - [ 0x15 ] = KEY_DOWN, - [ 0x16 ] = KEY_LEFT, - [ 0x17 ] = KEY_RIGHT, - [ 0x18 ] = KEY_VIDEO, /* Videos */ - [ 0x19 ] = KEY_AUDIO, /* Music */ - /* 0x1a: Pictures - presume this means - "Multimedia Home Platform" - - no "PICTURES" key in input.h - */ - [ 0x1a ] = KEY_MHP, - - [ 0x1b ] = KEY_EPG, /* Guide */ - [ 0x1c ] = KEY_TV, - [ 0x1e ] = KEY_NEXTSONG, /* skip >| */ - [ 0x1f ] = KEY_EXIT, /* back/exit */ - [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ - [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ - [ 0x22 ] = KEY_CHANNEL, /* source (old black remote) */ - [ 0x24 ] = KEY_PREVIOUSSONG, /* replay |< */ - [ 0x25 ] = KEY_ENTER, /* OK */ - [ 0x26 ] = KEY_SLEEP, /* minimize (old black remote) */ - [ 0x29 ] = KEY_BLUE, /* blue key */ - [ 0x2e ] = KEY_GREEN, /* green button */ - [ 0x30 ] = KEY_PAUSE, /* pause */ - [ 0x32 ] = KEY_REWIND, /* backward << */ - [ 0x34 ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x35 ] = KEY_PLAY, - [ 0x36 ] = KEY_STOP, - [ 0x37 ] = KEY_RECORD, /* recording */ - [ 0x38 ] = KEY_YELLOW, /* yellow key */ - [ 0x3b ] = KEY_SELECT, /* top right button */ - [ 0x3c ] = KEY_ZOOM, /* full */ - [ 0x3d ] = KEY_POWER, /* system power (green button) */ -}; -EXPORT_SYMBOL(ir_codes_hauppauge_new); - -IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { - [ 2 ] = KEY_KP0, - [ 1 ] = KEY_KP1, - [ 11 ] = KEY_KP2, - [ 27 ] = KEY_KP3, - [ 5 ] = KEY_KP4, - [ 9 ] = KEY_KP5, - [ 21 ] = KEY_KP6, - [ 6 ] = KEY_KP7, - [ 10 ] = KEY_KP8, - [ 18 ] = KEY_KP9, - - [ 3 ] = KEY_TUNER, /* TV/FM */ - [ 7 ] = KEY_SEARCH, /* scan */ - [ 28 ] = KEY_ZOOM, /* full screen */ - [ 30 ] = KEY_POWER, - [ 23 ] = KEY_VOLUMEDOWN, - [ 31 ] = KEY_VOLUMEUP, - [ 20 ] = KEY_CHANNELDOWN, - [ 22 ] = KEY_CHANNELUP, - [ 24 ] = KEY_MUTE, - - [ 0 ] = KEY_LIST, /* source */ - [ 19 ] = KEY_INFO, /* loop */ - [ 16 ] = KEY_LAST, /* +100 */ - [ 13 ] = KEY_CLEAR, /* reset */ - [ 12 ] = BTN_RIGHT, /* fun++ */ - [ 4 ] = BTN_LEFT, /* fun-- */ - [ 14 ] = KEY_GOTO, /* function */ - [ 15 ] = KEY_STOP, /* freeze */ -}; -EXPORT_SYMBOL(ir_codes_pixelview); - -/* -------------------------------------------------------------------------- */ - -static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) -{ - if (KEY_RESERVED == ir->keycode) { - printk(KERN_INFO "%s: unknown key: key=0x%02x raw=0x%02x down=%d\n", - dev->name,ir->ir_key,ir->ir_raw,ir->keypressed); - return; - } - dprintk(1,"%s: key event code=%d down=%d\n", - dev->name,ir->keycode,ir->keypressed); - input_report_key(dev,ir->keycode,ir->keypressed); - input_sync(dev); -} - -/* -------------------------------------------------------------------------- */ - -void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, - int ir_type, IR_KEYTAB_TYPE *ir_codes) -{ - int i; - - ir->ir_type = ir_type; - if (ir_codes) - memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes)); - - - dev->keycode = ir->ir_codes; - dev->keycodesize = sizeof(IR_KEYTAB_TYPE); - dev->keycodemax = IR_KEYTAB_SIZE; - for (i = 0; i < IR_KEYTAB_SIZE; i++) - set_bit(ir->ir_codes[i], dev->keybit); - clear_bit(0, dev->keybit); - - set_bit(EV_KEY, dev->evbit); - if (repeat) - set_bit(EV_REP, dev->evbit); -} - -void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir) -{ - if (ir->keypressed) { - ir->keypressed = 0; - ir_input_key_event(dev,ir); - } -} - -void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, - u32 ir_key, u32 ir_raw) -{ - u32 keycode = IR_KEYCODE(ir->ir_codes, ir_key); - - if (ir->keypressed && ir->keycode != keycode) { - ir->keypressed = 0; - ir_input_key_event(dev,ir); - } - if (!ir->keypressed) { - ir->ir_key = ir_key; - ir->ir_raw = ir_raw; - ir->keycode = keycode; - ir->keypressed = 1; - ir_input_key_event(dev,ir); - } -} - -/* -------------------------------------------------------------------------- */ - -u32 ir_extract_bits(u32 data, u32 mask) -{ - int mbit, vbit; - u32 value; - - value = 0; - vbit = 0; - for (mbit = 0; mbit < 32; mbit++) { - if (!(mask & ((u32)1 << mbit))) - continue; - if (data & ((u32)1 << mbit)) - value |= (1 << vbit); - vbit++; - } - return value; -} - -static int inline getbit(u32 *samples, int bit) -{ - return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0; -} - -/* sump raw samples for visual debugging ;) */ -int ir_dump_samples(u32 *samples, int count) -{ - int i, bit, start; - - printk(KERN_DEBUG "ir samples: "); - start = 0; - for (i = 0; i < count * 32; i++) { - bit = getbit(samples,i); - if (bit) - start = 1; - if (0 == start) - continue; - printk("%s", bit ? "#" : "_"); - } - printk("\n"); - return 0; -} - -/* decode raw samples, pulse distance coding used by NEC remotes */ -int ir_decode_pulsedistance(u32 *samples, int count, int low, int high) -{ - int i,last,bit,len; - u32 curBit; - u32 value; - - /* find start burst */ - for (i = len = 0; i < count * 32; i++) { - bit = getbit(samples,i); - if (bit) { - len++; - } else { - if (len >= 29) - break; - len = 0; - } - } - - /* start burst to short */ - if (len < 29) - return 0xffffffff; - - /* find start silence */ - for (len = 0; i < count * 32; i++) { - bit = getbit(samples,i); - if (bit) { - break; - } else { - len++; - } - } - - /* silence to short */ - if (len < 7) - return 0xffffffff; - - /* go decoding */ - len = 0; - last = 1; - value = 0; curBit = 1; - for (; i < count * 32; i++) { - bit = getbit(samples,i); - if (last) { - if(bit) { - continue; - } else { - len = 1; - } - } else { - if (bit) { - if (len > (low + high) /2) - value |= curBit; - curBit <<= 1; - if (curBit == 1) - break; - } else { - len++; - } - } - last = bit; - } - - return value; -} - -/* decode raw samples, biphase coding, used by rc5 for example */ -int ir_decode_biphase(u32 *samples, int count, int low, int high) -{ - int i,last,bit,len,flips; - u32 value; - - /* find start bit (1) */ - for (i = 0; i < 32; i++) { - bit = getbit(samples,i); - if (bit) - break; - } - - /* go decoding */ - len = 0; - flips = 0; - value = 1; - for (; i < count * 32; i++) { - if (len > high) - break; - if (flips > 1) - break; - last = bit; - bit = getbit(samples,i); - if (last == bit) { - len++; - continue; - } - if (len < low) { - len++; - flips++; - continue; - } - value <<= 1; - value |= bit; - flips = 0; - len = 1; - } - return value; -} - -EXPORT_SYMBOL_GPL(ir_input_init); -EXPORT_SYMBOL_GPL(ir_input_nokey); -EXPORT_SYMBOL_GPL(ir_input_keydown); - -EXPORT_SYMBOL_GPL(ir_extract_bits); -EXPORT_SYMBOL_GPL(ir_dump_samples); -EXPORT_SYMBOL_GPL(ir_decode_biphase); -EXPORT_SYMBOL_GPL(ir_decode_pulsedistance); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ - diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c new file mode 100644 index 000000000000..468f66013393 --- /dev/null +++ b/drivers/media/common/ir-keymaps.c @@ -0,0 +1,1537 @@ +/* + + + Keytables for supported remote controls. This file is part of + video4linux. + + 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 + +/* empty keytable, can be used as placeholder for not-yet created keytables */ +IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { + [ 0x2a ] = KEY_COFFEE, +}; + +EXPORT_SYMBOL_GPL(ir_codes_empty); + +IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { + [ 0x22 ] = KEY_0, + [ 0x28 ] = KEY_1, + [ 0x18 ] = KEY_2, + [ 0x38 ] = KEY_3, + [ 0x24 ] = KEY_4, + [ 0x14 ] = KEY_5, + [ 0x34 ] = KEY_6, + [ 0x2c ] = KEY_7, + [ 0x1c ] = KEY_8, + [ 0x3c ] = KEY_9, + + [ 0x30 ] = KEY_EJECTCD, // Unmarked on my controller + [ 0x00 ] = KEY_POWER, + [ 0x12 ] = BTN_LEFT, // DISPLAY/L + [ 0x32 ] = BTN_RIGHT, // LOOP/R + [ 0x0a ] = KEY_MUTE, + [ 0x26 ] = KEY_RECORD, + [ 0x16 ] = KEY_PAUSE, + [ 0x36 ] = KEY_STOP, + [ 0x1e ] = KEY_VOLUMEDOWN, + [ 0x3e ] = KEY_VOLUMEUP, + + [ 0x20 ] = KEY_TUNER, // TV/FM + [ 0x10 ] = KEY_CD, + [ 0x08 ] = KEY_VIDEO, + [ 0x04 ] = KEY_AUDIO, + [ 0x0c ] = KEY_ZOOM, // full screen + [ 0x02 ] = KEY_INFO, // preview + [ 0x2a ] = KEY_SEARCH, // autoscan + [ 0x1a ] = KEY_STOP, // freeze + [ 0x3a ] = KEY_RECORD, // capture + [ 0x06 ] = KEY_PLAY, // unmarked + [ 0x2e ] = KEY_RED, // unmarked + [ 0x0e ] = KEY_GREEN, // unmarked + + [ 0x21 ] = KEY_YELLOW, // unmarked + [ 0x11 ] = KEY_CHANNELDOWN, + [ 0x31 ] = KEY_CHANNELUP, + [ 0x01 ] = KEY_BLUE, // unmarked +}; + +EXPORT_SYMBOL_GPL(ir_codes_avermedia); + +/* Matt Jesson >' + [ 0x3a ] = KEY_RECORD, // 'capture' + [ 0x0a ] = KEY_MUTE, // 'mute' + [ 0x2c ] = KEY_RECORD, // 'record' + [ 0x1c ] = KEY_PAUSE, // 'pause' + [ 0x3c ] = KEY_STOP, // 'stop' + [ 0x0c ] = KEY_PLAY, // 'play' + [ 0x2e ] = KEY_RED, // 'red' + [ 0x01 ] = KEY_BLUE, // 'blue' / 'cancel' + [ 0x0e ] = KEY_YELLOW, // 'yellow' / 'ok' + [ 0x21 ] = KEY_GREEN, // 'green' + [ 0x11 ] = KEY_CHANNELDOWN, // 'channel -' + [ 0x31 ] = KEY_CHANNELUP, // 'channel +' + [ 0x1e ] = KEY_VOLUMEDOWN, // 'volume -' + [ 0x3e ] = KEY_VOLUMEUP, // 'volume +' +}; + +EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); + +/* Attila Kondoros */ +IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { + + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + [ 0x00 ] = KEY_0, + [ 0x17 ] = KEY_LAST, // +100 + [ 0x0a ] = KEY_LIST, // recall + + + [ 0x1c ] = KEY_TUNER, // TV/FM + [ 0x15 ] = KEY_SEARCH, // scan + [ 0x12 ] = KEY_POWER, // power + [ 0x1f ] = KEY_VOLUMEDOWN, // vol up + [ 0x1b ] = KEY_VOLUMEUP, // vol down + [ 0x1e ] = KEY_CHANNELDOWN, // chn up + [ 0x1a ] = KEY_CHANNELUP, // chn down + + [ 0x11 ] = KEY_VIDEO, // video + [ 0x0f ] = KEY_ZOOM, // full screen + [ 0x13 ] = KEY_MUTE, // mute/unmute + [ 0x10 ] = KEY_TEXT, // min + + [ 0x0d ] = KEY_STOP, // freeze + [ 0x0e ] = KEY_RECORD, // record + [ 0x1d ] = KEY_PLAYPAUSE, // stop + [ 0x19 ] = KEY_PLAY, // play + + [ 0x16 ] = KEY_GOTO, // osd + [ 0x14 ] = KEY_REFRESH, // default + [ 0x0c ] = KEY_KPPLUS, // fine tune >>>> + [ 0x18 ] = KEY_KPMINUS // fine tune <<<< +}; + +EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); + +/* ---------------------------------------------------------------------- */ + +IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = { + + [ 0x1e ] = KEY_POWER, // power + [ 0x07 ] = KEY_MEDIA, // source + [ 0x1c ] = KEY_SEARCH, // scan + +/* FIXME: duplicate keycodes? + * + * These four keys seem to share the same GPIO as CH+, CH-, <<< and >>> + * The GPIO values are + * 6397fb for both "Scan <" and "CH -", + * 639ffb for "Scan >" and "CH+", + * 6384fb for "Tune <" and "<<<", + * 638cfb for "Tune >" and ">>>", regardless of the mask. + * + * [ 0x17 ] = KEY_BACK, // fm scan << + * [ 0x1f ] = KEY_FORWARD, // fm scan >> + * + * [ 0x04 ] = KEY_LEFT, // fm tuning < + * [ 0x0c ] = KEY_RIGHT, // fm tuning > + * + * For now, these four keys are disabled. Pressing them will generate + * the CH+/CH-/<<>> events + */ + + [ 0x03 ] = KEY_TUNER, // TV/FM + + [ 0x00 ] = KEY_RECORD, + [ 0x08 ] = KEY_STOP, + [ 0x11 ] = KEY_PLAY, + + [ 0x1a ] = KEY_PLAYPAUSE, // freeze + [ 0x19 ] = KEY_ZOOM, // zoom + [ 0x0f ] = KEY_TEXT, // min + + [ 0x01 ] = KEY_1, + [ 0x0b ] = KEY_2, + [ 0x1b ] = KEY_3, + [ 0x05 ] = KEY_4, + [ 0x09 ] = KEY_5, + [ 0x15 ] = KEY_6, + [ 0x06 ] = KEY_7, + [ 0x0a ] = KEY_8, + [ 0x12 ] = KEY_9, + [ 0x02 ] = KEY_0, + [ 0x10 ] = KEY_LAST, // +100 + [ 0x13 ] = KEY_LIST, // recall + + [ 0x1f ] = KEY_CHANNELUP, // chn down + [ 0x17 ] = KEY_CHANNELDOWN, // chn up + [ 0x16 ] = KEY_VOLUMEUP, // vol down + [ 0x14 ] = KEY_VOLUMEDOWN, // vol up + + [ 0x04 ] = KEY_KPMINUS, // <<< + [ 0x0e ] = KEY_SETUP, // function + [ 0x0c ] = KEY_KPPLUS, // >>> + + [ 0x0d ] = KEY_GOTO, // mts + [ 0x1d ] = KEY_REFRESH, // reset + [ 0x18 ] = KEY_MUTE // mute/unmute +}; + +EXPORT_SYMBOL_GPL(ir_codes_conceptronic); + +IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + [ 0x0a ] = KEY_TV, + [ 0x0b ] = KEY_AUX, + [ 0x0c ] = KEY_DVD, + [ 0x0d ] = KEY_POWER, + [ 0x0e ] = KEY_MHP, /* labelled 'Picture' */ + [ 0x0f ] = KEY_AUDIO, + [ 0x10 ] = KEY_INFO, + [ 0x11 ] = KEY_F13, /* 16:9 */ + [ 0x12 ] = KEY_F14, /* 14:9 */ + [ 0x13 ] = KEY_EPG, + [ 0x14 ] = KEY_EXIT, + [ 0x15 ] = KEY_MENU, + [ 0x16 ] = KEY_UP, + [ 0x17 ] = KEY_DOWN, + [ 0x18 ] = KEY_LEFT, + [ 0x19 ] = KEY_RIGHT, + [ 0x1a ] = KEY_ENTER, + [ 0x1b ] = KEY_CHANNELUP, + [ 0x1c ] = KEY_CHANNELDOWN, + [ 0x1d ] = KEY_VOLUMEUP, + [ 0x1e ] = KEY_VOLUMEDOWN, + [ 0x1f ] = KEY_RED, + [ 0x20 ] = KEY_GREEN, + [ 0x21 ] = KEY_YELLOW, + [ 0x22 ] = KEY_BLUE, + [ 0x23 ] = KEY_SUBTITLE, + [ 0x24 ] = KEY_F15, /* AD */ + [ 0x25 ] = KEY_TEXT, + [ 0x26 ] = KEY_MUTE, + [ 0x27 ] = KEY_REWIND, + [ 0x28 ] = KEY_STOP, + [ 0x29 ] = KEY_PLAY, + [ 0x2a ] = KEY_FASTFORWARD, + [ 0x2b ] = KEY_F16, /* chapter */ + [ 0x2c ] = KEY_PAUSE, + [ 0x2d ] = KEY_PLAY, + [ 0x2e ] = KEY_RECORD, + [ 0x2f ] = KEY_F17, /* picture in picture */ + [ 0x30 ] = KEY_KPPLUS, /* zoom in */ + [ 0x31 ] = KEY_KPMINUS, /* zoom out */ + [ 0x32 ] = KEY_F18, /* capture */ + [ 0x33 ] = KEY_F19, /* web */ + [ 0x34 ] = KEY_EMAIL, + [ 0x35 ] = KEY_PHONE, + [ 0x36 ] = KEY_PC +}; + +EXPORT_SYMBOL_GPL(ir_codes_nebula); + +/* DigitalNow DNTV Live DVB-T Remote */ +IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { + [ 0x00 ] = KEY_ESC, /* 'go up a level?' */ + /* Keys 0 to 9 */ + [ 0x0a ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0b ] = KEY_TUNER, /* tv/fm */ + [ 0x0c ] = KEY_SEARCH, /* scan */ + [ 0x0d ] = KEY_STOP, + [ 0x0e ] = KEY_PAUSE, + [ 0x0f ] = KEY_LIST, /* source */ + + [ 0x10 ] = KEY_MUTE, + [ 0x11 ] = KEY_REWIND, /* backward << */ + [ 0x12 ] = KEY_POWER, + [ 0x13 ] = KEY_S, /* snap */ + [ 0x14 ] = KEY_AUDIO, /* stereo */ + [ 0x15 ] = KEY_CLEAR, /* reset */ + [ 0x16 ] = KEY_PLAY, + [ 0x17 ] = KEY_ENTER, + [ 0x18 ] = KEY_ZOOM, /* full screen */ + [ 0x19 ] = KEY_FASTFORWARD, /* forward >> */ + [ 0x1a ] = KEY_CHANNELUP, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x1c ] = KEY_INFO, /* preview */ + [ 0x1d ] = KEY_RECORD, /* record */ + [ 0x1e ] = KEY_CHANNELDOWN, + [ 0x1f ] = KEY_VOLUMEDOWN, +}; + +EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t); + +/* ---------------------------------------------------------------------- */ + +/* IO-DATA BCTV7E Remote */ +IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { + [ 0x40 ] = KEY_TV, + [ 0x20 ] = KEY_RADIO, /* FM */ + [ 0x60 ] = KEY_EPG, + [ 0x00 ] = KEY_POWER, + + /* Keys 0 to 9 */ + [ 0x44 ] = KEY_0, /* 10 */ + [ 0x50 ] = KEY_1, + [ 0x30 ] = KEY_2, + [ 0x70 ] = KEY_3, + [ 0x48 ] = KEY_4, + [ 0x28 ] = KEY_5, + [ 0x68 ] = KEY_6, + [ 0x58 ] = KEY_7, + [ 0x38 ] = KEY_8, + [ 0x78 ] = KEY_9, + + [ 0x10 ] = KEY_L, /* Live */ + [ 0x08 ] = KEY_T, /* Time Shift */ + + [ 0x18 ] = KEY_PLAYPAUSE, /* Play */ + + [ 0x24 ] = KEY_ENTER, /* 11 */ + [ 0x64 ] = KEY_ESC, /* 12 */ + [ 0x04 ] = KEY_M, /* Multi */ + + [ 0x54 ] = KEY_VIDEO, + [ 0x34 ] = KEY_CHANNELUP, + [ 0x74 ] = KEY_VOLUMEUP, + [ 0x14 ] = KEY_MUTE, + + [ 0x4c ] = KEY_S, /* SVIDEO */ + [ 0x2c ] = KEY_CHANNELDOWN, + [ 0x6c ] = KEY_VOLUMEDOWN, + [ 0x0c ] = KEY_ZOOM, + + [ 0x5c ] = KEY_PAUSE, + [ 0x3c ] = KEY_C, /* || (red) */ + [ 0x7c ] = KEY_RECORD, /* recording */ + [ 0x1c ] = KEY_STOP, + + [ 0x41 ] = KEY_REWIND, /* backward << */ + [ 0x21 ] = KEY_PLAY, + [ 0x61 ] = KEY_FASTFORWARD, /* forward >> */ + [ 0x01 ] = KEY_NEXT, /* skip >| */ +}; + +EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e); + +/* ---------------------------------------------------------------------- */ + +/* ADS Tech Instant TV DVB-T PCI Remote */ +IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = { + /* Keys 0 to 9 */ + [ 0x4d ] = KEY_0, + [ 0x57 ] = KEY_1, + [ 0x4f ] = KEY_2, + [ 0x53 ] = KEY_3, + [ 0x56 ] = KEY_4, + [ 0x4e ] = KEY_5, + [ 0x5e ] = KEY_6, + [ 0x54 ] = KEY_7, + [ 0x4c ] = KEY_8, + [ 0x5c ] = KEY_9, + + [ 0x5b ] = KEY_POWER, + [ 0x5f ] = KEY_MUTE, + [ 0x55 ] = KEY_GOTO, + [ 0x5d ] = KEY_SEARCH, + [ 0x17 ] = KEY_EPG, /* Guide */ + [ 0x1f ] = KEY_MENU, + [ 0x0f ] = KEY_UP, + [ 0x46 ] = KEY_DOWN, + [ 0x16 ] = KEY_LEFT, + [ 0x1e ] = KEY_RIGHT, + [ 0x0e ] = KEY_SELECT, /* Enter */ + [ 0x5a ] = KEY_INFO, + [ 0x52 ] = KEY_EXIT, + [ 0x59 ] = KEY_PREVIOUS, + [ 0x51 ] = KEY_NEXT, + [ 0x58 ] = KEY_REWIND, + [ 0x50 ] = KEY_FORWARD, + [ 0x44 ] = KEY_PLAYPAUSE, + [ 0x07 ] = KEY_STOP, + [ 0x1b ] = KEY_RECORD, + [ 0x13 ] = KEY_TUNER, /* Live */ + [ 0x0a ] = KEY_A, + [ 0x12 ] = KEY_B, + [ 0x03 ] = KEY_PROG1, /* 1 */ + [ 0x01 ] = KEY_PROG2, /* 2 */ + [ 0x00 ] = KEY_PROG3, /* 3 */ + [ 0x06 ] = KEY_DVD, + [ 0x48 ] = KEY_AUX, /* Photo */ + [ 0x40 ] = KEY_VIDEO, + [ 0x19 ] = KEY_AUDIO, /* Music */ + [ 0x0b ] = KEY_CHANNELUP, + [ 0x08 ] = KEY_CHANNELDOWN, + [ 0x15 ] = KEY_VOLUMEUP, + [ 0x1c ] = KEY_VOLUMEDOWN, +}; + +EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci); + +/* ---------------------------------------------------------------------- */ + +/* MSI TV@nywhere remote */ +IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { + /* Keys 0 to 9 */ + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0c ] = KEY_MUTE, + [ 0x0f ] = KEY_SCREEN, /* Full Screen */ + [ 0x10 ] = KEY_F, /* Funtion */ + [ 0x11 ] = KEY_T, /* Time shift */ + [ 0x12 ] = KEY_POWER, + [ 0x13 ] = KEY_MEDIA, /* MTS */ + [ 0x14 ] = KEY_SLOW, + [ 0x16 ] = KEY_REWIND, /* backward << */ + [ 0x17 ] = KEY_ENTER, /* Return */ + [ 0x18 ] = KEY_FASTFORWARD, /* forward >> */ + [ 0x1a ] = KEY_CHANNELUP, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x1e ] = KEY_CHANNELDOWN, + [ 0x1f ] = KEY_VOLUMEDOWN, +}; + +EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere); + +/* ---------------------------------------------------------------------- */ + +/* Cinergy 1400 DVB-T */ +IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { + [ 0x01 ] = KEY_POWER, + [ 0x02 ] = KEY_1, + [ 0x03 ] = KEY_2, + [ 0x04 ] = KEY_3, + [ 0x05 ] = KEY_4, + [ 0x06 ] = KEY_5, + [ 0x07 ] = KEY_6, + [ 0x08 ] = KEY_7, + [ 0x09 ] = KEY_8, + [ 0x0a ] = KEY_9, + [ 0x0c ] = KEY_0, + + [ 0x0b ] = KEY_VIDEO, + [ 0x0d ] = KEY_REFRESH, + [ 0x0e ] = KEY_SELECT, + [ 0x0f ] = KEY_EPG, + [ 0x10 ] = KEY_UP, + [ 0x11 ] = KEY_LEFT, + [ 0x12 ] = KEY_OK, + [ 0x13 ] = KEY_RIGHT, + [ 0x14 ] = KEY_DOWN, + [ 0x15 ] = KEY_TEXT, + [ 0x16 ] = KEY_INFO, + + [ 0x17 ] = KEY_RED, + [ 0x18 ] = KEY_GREEN, + [ 0x19 ] = KEY_YELLOW, + [ 0x1a ] = KEY_BLUE, + + [ 0x1b ] = KEY_CHANNELUP, + [ 0x1c ] = KEY_VOLUMEUP, + [ 0x1d ] = KEY_MUTE, + [ 0x1e ] = KEY_VOLUMEDOWN, + [ 0x1f ] = KEY_CHANNELDOWN, + + [ 0x40 ] = KEY_PAUSE, + [ 0x4c ] = KEY_PLAY, + [ 0x58 ] = KEY_RECORD, + [ 0x54 ] = KEY_PREVIOUS, + [ 0x48 ] = KEY_STOP, + [ 0x5c ] = KEY_NEXT, +}; + +EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400); + +/* ---------------------------------------------------------------------- */ + +/* AVERTV STUDIO 303 Remote */ +IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = { + [ 0x2a ] = KEY_1, + [ 0x32 ] = KEY_2, + [ 0x3a ] = KEY_3, + [ 0x4a ] = KEY_4, + [ 0x52 ] = KEY_5, + [ 0x5a ] = KEY_6, + [ 0x6a ] = KEY_7, + [ 0x72 ] = KEY_8, + [ 0x7a ] = KEY_9, + [ 0x0e ] = KEY_0, + + [ 0x02 ] = KEY_POWER, + [ 0x22 ] = KEY_VIDEO, + [ 0x42 ] = KEY_AUDIO, + [ 0x62 ] = KEY_ZOOM, + [ 0x0a ] = KEY_TV, + [ 0x12 ] = KEY_CD, + [ 0x1a ] = KEY_TEXT, + + [ 0x16 ] = KEY_SUBTITLE, + [ 0x1e ] = KEY_REWIND, + [ 0x06 ] = KEY_PRINT, + + [ 0x2e ] = KEY_SEARCH, + [ 0x36 ] = KEY_SLEEP, + [ 0x3e ] = KEY_SHUFFLE, + [ 0x26 ] = KEY_MUTE, + + [ 0x4e ] = KEY_RECORD, + [ 0x56 ] = KEY_PAUSE, + [ 0x5e ] = KEY_STOP, + [ 0x46 ] = KEY_PLAY, + + [ 0x6e ] = KEY_RED, + [ 0x0b ] = KEY_GREEN, + [ 0x66 ] = KEY_YELLOW, + [ 0x03 ] = KEY_BLUE, + + [ 0x76 ] = KEY_LEFT, + [ 0x7e ] = KEY_RIGHT, + [ 0x13 ] = KEY_DOWN, + [ 0x1b ] = KEY_UP, +}; + +EXPORT_SYMBOL_GPL(ir_codes_avertv_303); + +/* ---------------------------------------------------------------------- */ + +/* DigitalNow DNTV Live! DVB-T Pro Remote */ +IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { + [ 0x16 ] = KEY_POWER, + [ 0x5b ] = KEY_HOME, + + [ 0x55 ] = KEY_TV, /* live tv */ + [ 0x58 ] = KEY_TUNER, /* digital Radio */ + [ 0x5a ] = KEY_RADIO, /* FM radio */ + [ 0x59 ] = KEY_DVD, /* dvd menu */ + [ 0x03 ] = KEY_1, + [ 0x01 ] = KEY_2, + [ 0x06 ] = KEY_3, + [ 0x09 ] = KEY_4, + [ 0x1d ] = KEY_5, + [ 0x1f ] = KEY_6, + [ 0x0d ] = KEY_7, + [ 0x19 ] = KEY_8, + [ 0x1b ] = KEY_9, + [ 0x0c ] = KEY_CANCEL, + [ 0x15 ] = KEY_0, + [ 0x4a ] = KEY_CLEAR, + [ 0x13 ] = KEY_BACK, + [ 0x00 ] = KEY_TAB, + [ 0x4b ] = KEY_UP, + [ 0x4e ] = KEY_LEFT, + [ 0x4f ] = KEY_OK, + [ 0x52 ] = KEY_RIGHT, + [ 0x51 ] = KEY_DOWN, + [ 0x1e ] = KEY_VOLUMEUP, + [ 0x0a ] = KEY_VOLUMEDOWN, + [ 0x02 ] = KEY_CHANNELDOWN, + [ 0x05 ] = KEY_CHANNELUP, + [ 0x11 ] = KEY_RECORD, + [ 0x14 ] = KEY_PLAY, + [ 0x4c ] = KEY_PAUSE, + [ 0x1a ] = KEY_STOP, + [ 0x40 ] = KEY_REWIND, + [ 0x12 ] = KEY_FASTFORWARD, + [ 0x41 ] = KEY_PREVIOUSSONG, /* replay |< */ + [ 0x42 ] = KEY_NEXTSONG, /* skip >| */ + [ 0x54 ] = KEY_CAMERA, /* capture */ + [ 0x50 ] = KEY_LANGUAGE, /* sap */ + [ 0x47 ] = KEY_TV2, /* pip */ + [ 0x4d ] = KEY_SCREEN, + [ 0x43 ] = KEY_SUBTITLE, + [ 0x10 ] = KEY_MUTE, + [ 0x49 ] = KEY_AUDIO, /* l/r */ + [ 0x07 ] = KEY_SLEEP, + [ 0x08 ] = KEY_VIDEO, /* a/v */ + [ 0x0e ] = KEY_PREVIOUS, /* recall */ + [ 0x45 ] = KEY_ZOOM, /* zoom + */ + [ 0x46 ] = KEY_ANGLE, /* zoom - */ + [ 0x56 ] = KEY_RED, + [ 0x57 ] = KEY_GREEN, + [ 0x5c ] = KEY_YELLOW, + [ 0x5d ] = KEY_BLUE, +}; + +EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro); + +IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { + [ 0x01 ] = KEY_CHANNEL, + [ 0x02 ] = KEY_SELECT, + [ 0x03 ] = KEY_MUTE, + [ 0x04 ] = KEY_POWER, + [ 0x05 ] = KEY_1, + [ 0x06 ] = KEY_2, + [ 0x07 ] = KEY_3, + [ 0x08 ] = KEY_CHANNELUP, + [ 0x09 ] = KEY_4, + [ 0x0a ] = KEY_5, + [ 0x0b ] = KEY_6, + [ 0x0c ] = KEY_CHANNELDOWN, + [ 0x0d ] = KEY_7, + [ 0x0e ] = KEY_8, + [ 0x0f ] = KEY_9, + [ 0x10 ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_0, + [ 0x12 ] = KEY_MENU, + [ 0x13 ] = KEY_PRINT, + [ 0x14 ] = KEY_VOLUMEDOWN, + [ 0x16 ] = KEY_PAUSE, + [ 0x18 ] = KEY_RECORD, + [ 0x19 ] = KEY_REWIND, + [ 0x1a ] = KEY_PLAY, + [ 0x1b ] = KEY_FORWARD, + [ 0x1c ] = KEY_BACKSPACE, + [ 0x1e ] = KEY_STOP, + [ 0x40 ] = KEY_ZOOM, +}; + +EXPORT_SYMBOL_GPL(ir_codes_em_terratec); + +IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = { + [ 0x3a ] = KEY_0, + [ 0x31 ] = KEY_1, + [ 0x32 ] = KEY_2, + [ 0x33 ] = KEY_3, + [ 0x34 ] = KEY_4, + [ 0x35 ] = KEY_5, + [ 0x36 ] = KEY_6, + [ 0x37 ] = KEY_7, + [ 0x38 ] = KEY_8, + [ 0x39 ] = KEY_9, + + [ 0x2f ] = KEY_POWER, + + [ 0x2e ] = KEY_P, + [ 0x1f ] = KEY_L, + [ 0x2b ] = KEY_I, + + [ 0x2d ] = KEY_ZOOM, + [ 0x1e ] = KEY_ZOOM, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x0f ] = KEY_VOLUMEDOWN, + [ 0x17 ] = KEY_CHANNELUP, + [ 0x1c ] = KEY_CHANNELDOWN, + [ 0x25 ] = KEY_INFO, + + [ 0x3c ] = KEY_MUTE, + + [ 0x3d ] = KEY_LEFT, + [ 0x3b ] = KEY_RIGHT, + + [ 0x3f ] = KEY_UP, + [ 0x3e ] = KEY_DOWN, + [ 0x1a ] = KEY_PAUSE, + + [ 0x1d ] = KEY_MENU, + [ 0x19 ] = KEY_PLAY, + [ 0x16 ] = KEY_REWIND, + [ 0x13 ] = KEY_FORWARD, + [ 0x15 ] = KEY_PAUSE, + [ 0x0e ] = KEY_REWIND, + [ 0x0d ] = KEY_PLAY, + [ 0x0b ] = KEY_STOP, + [ 0x07 ] = KEY_FORWARD, + [ 0x27 ] = KEY_RECORD, + [ 0x26 ] = KEY_TUNER, + [ 0x29 ] = KEY_TEXT, + [ 0x2a ] = KEY_MEDIA, + [ 0x18 ] = KEY_EPG, + [ 0x27 ] = KEY_RECORD, +}; + +EXPORT_SYMBOL_GPL(ir_codes_em_pinnacle_usb); + +IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { + [ 0x0f ] = KEY_0, + [ 0x03 ] = KEY_1, + [ 0x04 ] = KEY_2, + [ 0x05 ] = KEY_3, + [ 0x07 ] = KEY_4, + [ 0x08 ] = KEY_5, + [ 0x09 ] = KEY_6, + [ 0x0b ] = KEY_7, + [ 0x0c ] = KEY_8, + [ 0x0d ] = KEY_9, + + [ 0x0e ] = KEY_MODE, // Air/Cable + [ 0x11 ] = KEY_VIDEO, // Video + [ 0x15 ] = KEY_AUDIO, // Audio + [ 0x00 ] = KEY_POWER, // Power + [ 0x18 ] = KEY_TUNER, // AV Source + [ 0x02 ] = KEY_ZOOM, // Fullscreen + [ 0x1a ] = KEY_LANGUAGE, // Stereo + [ 0x1b ] = KEY_MUTE, // Mute + [ 0x14 ] = KEY_VOLUMEUP, // Volume + + [ 0x17 ] = KEY_VOLUMEDOWN, // Volume - + [ 0x12 ] = KEY_CHANNELUP, // Channel + + [ 0x13 ] = KEY_CHANNELDOWN, // Channel - + [ 0x06 ] = KEY_AGAIN, // Recall + [ 0x10 ] = KEY_ENTER, // Enter +}; + +EXPORT_SYMBOL_GPL(ir_codes_flyvideo); + +IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { + [ 0x01 ] = KEY_ZOOM, // Full Screen + [ 0x00 ] = KEY_POWER, // Power + + [ 0x03 ] = KEY_1, + [ 0x04 ] = KEY_2, + [ 0x05 ] = KEY_3, + [ 0x07 ] = KEY_4, + [ 0x08 ] = KEY_5, + [ 0x09 ] = KEY_6, + [ 0x0b ] = KEY_7, + [ 0x0c ] = KEY_8, + [ 0x0d ] = KEY_9, + [ 0x06 ] = KEY_AGAIN, // Recall + [ 0x0f ] = KEY_0, + [ 0x10 ] = KEY_MUTE, // Mute + [ 0x02 ] = KEY_RADIO, // TV/Radio + [ 0x1b ] = KEY_LANGUAGE, // SAP (Second Audio Program) + + [ 0x14 ] = KEY_VOLUMEUP, // VOL+ + [ 0x17 ] = KEY_VOLUMEDOWN, // VOL- + [ 0x12 ] = KEY_CHANNELUP, // CH+ + [ 0x13 ] = KEY_CHANNELDOWN, // CH- + [ 0x1d ] = KEY_ENTER, // Enter + + [ 0x1a ] = KEY_MODE, // PIP + [ 0x18 ] = KEY_TUNER, // Source + + [ 0x1e ] = KEY_RECORD, // Record/Pause + [ 0x15 ] = KEY_ANGLE, // Swap (no label on key) + [ 0x1c ] = KEY_PAUSE, // Timeshift/Pause + [ 0x19 ] = KEY_BACK, // Rewind << + [ 0x0a ] = KEY_PLAYPAUSE, // Play/Pause + [ 0x1f ] = KEY_FORWARD, // Forward >> + [ 0x16 ] = KEY_PREVIOUS, // Back |<< + [ 0x11 ] = KEY_STOP, // Stop + [ 0x0e ] = KEY_NEXT, // End >>| +}; + +EXPORT_SYMBOL_GPL(ir_codes_flydvb); + +IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0a ] = KEY_POWER, + [ 0x0b ] = KEY_PROG1, // app + [ 0x0c ] = KEY_ZOOM, // zoom/fullscreen + [ 0x0d ] = KEY_CHANNELUP, // channel + [ 0x0e ] = KEY_CHANNELDOWN, // channel- + [ 0x0f ] = KEY_VOLUMEUP, + [ 0x10 ] = KEY_VOLUMEDOWN, + [ 0x11 ] = KEY_TUNER, // AV + [ 0x12 ] = KEY_NUMLOCK, // -/-- + [ 0x13 ] = KEY_AUDIO, // audio + [ 0x14 ] = KEY_MUTE, + [ 0x15 ] = KEY_UP, + [ 0x16 ] = KEY_DOWN, + [ 0x17 ] = KEY_LEFT, + [ 0x18 ] = KEY_RIGHT, + [ 0x19 ] = BTN_LEFT, + [ 0x1a ] = BTN_RIGHT, + [ 0x1b ] = KEY_WWW, // text + [ 0x1c ] = KEY_REWIND, + [ 0x1d ] = KEY_FORWARD, + [ 0x1e ] = KEY_RECORD, + [ 0x1f ] = KEY_PLAY, + [ 0x20 ] = KEY_PREVIOUSSONG, + [ 0x21 ] = KEY_NEXTSONG, + [ 0x22 ] = KEY_PAUSE, + [ 0x23 ] = KEY_STOP, +}; + +EXPORT_SYMBOL_GPL(ir_codes_cinergy); + +/* Alfons Geser + * updates from Job D. R. Borges */ +IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { + [ 0x12 ] = KEY_POWER, + [ 0x01 ] = KEY_TV, // DVR + [ 0x15 ] = KEY_DVD, // DVD + [ 0x17 ] = KEY_AUDIO, // music + // DVR mode / DVD mode / music mode + + [ 0x1b ] = KEY_MUTE, // mute + [ 0x02 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek + [ 0x1e ] = KEY_SUBTITLE, // closed captioning / subtitle / seek + [ 0x16 ] = KEY_ZOOM, // full screen + [ 0x1c ] = KEY_VIDEO, // video source / eject / delall + [ 0x1d ] = KEY_RESTART, // playback / angle / del + [ 0x2f ] = KEY_SEARCH, // scan / menu / playlist + [ 0x30 ] = KEY_CHANNEL, // CH surfing / bookmark / memo + + [ 0x31 ] = KEY_HELP, // help + [ 0x32 ] = KEY_MODE, // num/memo + [ 0x33 ] = KEY_ESC, // cancel + + [ 0x0c ] = KEY_UP, // up + [ 0x10 ] = KEY_DOWN, // down + [ 0x08 ] = KEY_LEFT, // left + [ 0x04 ] = KEY_RIGHT, // right + [ 0x03 ] = KEY_SELECT, // select + + [ 0x1f ] = KEY_REWIND, // rewind + [ 0x20 ] = KEY_PLAYPAUSE, // play/pause + [ 0x29 ] = KEY_FORWARD, // forward + [ 0x14 ] = KEY_AGAIN, // repeat + [ 0x2b ] = KEY_RECORD, // recording + [ 0x2c ] = KEY_STOP, // stop + [ 0x2d ] = KEY_PLAY, // play + [ 0x2e ] = KEY_SHUFFLE, // snapshot / shuffle + + [ 0x00 ] = KEY_0, + [ 0x05 ] = KEY_1, + [ 0x06 ] = KEY_2, + [ 0x07 ] = KEY_3, + [ 0x09 ] = KEY_4, + [ 0x0a ] = KEY_5, + [ 0x0b ] = KEY_6, + [ 0x0d ] = KEY_7, + [ 0x0e ] = KEY_8, + [ 0x0f ] = KEY_9, + + [ 0x2a ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_VOLUMEDOWN, + [ 0x18 ] = KEY_CHANNELUP, // CH.tracking up + [ 0x19 ] = KEY_CHANNELDOWN, // CH.tracking down + + [ 0x13 ] = KEY_ENTER, // enter + [ 0x21 ] = KEY_DOT, // . (decimal dot) +}; + +EXPORT_SYMBOL_GPL(ir_codes_eztv); + +IR_KEYTAB_TYPE ir_codes_avacssmart[IR_KEYTAB_SIZE] = { + [ 0x1e ] = KEY_POWER, // power + [ 0x1c ] = KEY_SEARCH, // scan + [ 0x07 ] = KEY_SELECT, // source + + [ 0x16 ] = KEY_VOLUMEUP, + [ 0x14 ] = KEY_VOLUMEDOWN, + [ 0x1f ] = KEY_CHANNELUP, + [ 0x17 ] = KEY_CHANNELDOWN, + [ 0x18 ] = KEY_MUTE, + + [ 0x02 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x0b ] = KEY_2, + [ 0x1b ] = KEY_3, + [ 0x05 ] = KEY_4, + [ 0x09 ] = KEY_5, + [ 0x15 ] = KEY_6, + [ 0x06 ] = KEY_7, + [ 0x0a ] = KEY_8, + [ 0x12 ] = KEY_9, + [ 0x10 ] = KEY_DOT, + + [ 0x03 ] = KEY_TUNER, // tv/fm + [ 0x04 ] = KEY_REWIND, // fm tuning left or function left + [ 0x0c ] = KEY_FORWARD, // fm tuning right or function right + + [ 0x00 ] = KEY_RECORD, + [ 0x08 ] = KEY_STOP, + [ 0x11 ] = KEY_PLAY, + + [ 0x19 ] = KEY_ZOOM, + [ 0x0e ] = KEY_MENU, // function + [ 0x13 ] = KEY_AGAIN, // recall + [ 0x1d ] = KEY_RESTART, // reset + [ 0x1a ] = KEY_SHUFFLE, // snapshot/shuffle + +// FIXME + [ 0x0d ] = KEY_F21, // mts + [ 0x0f ] = KEY_F22, // min +}; + +EXPORT_SYMBOL_GPL(ir_codes_avacssmart); + +/* Alex Hermann */ +IR_KEYTAB_TYPE ir_codes_md2819[IR_KEYTAB_SIZE] = { + [ 0x28 ] = KEY_1, + [ 0x18 ] = KEY_2, + [ 0x38 ] = KEY_3, + [ 0x24 ] = KEY_4, + [ 0x14 ] = KEY_5, + [ 0x34 ] = KEY_6, + [ 0x2c ] = KEY_7, + [ 0x1c ] = KEY_8, + [ 0x3c ] = KEY_9, + [ 0x22 ] = KEY_0, + + [ 0x20 ] = KEY_TV, // TV/FM + [ 0x10 ] = KEY_CD, // CD + [ 0x30 ] = KEY_TEXT, // TELETEXT + [ 0x00 ] = KEY_POWER, // POWER + + [ 0x08 ] = KEY_VIDEO, // VIDEO + [ 0x04 ] = KEY_AUDIO, // AUDIO + [ 0x0c ] = KEY_ZOOM, // FULL SCREEN + + [ 0x12 ] = KEY_SUBTITLE, // DISPLAY - ??? + [ 0x32 ] = KEY_REWIND, // LOOP - ??? + [ 0x02 ] = KEY_PRINT, // PREVIEW - ??? + + [ 0x2a ] = KEY_SEARCH, // AUTOSCAN + [ 0x1a ] = KEY_SLEEP, // FREEZE - ??? + [ 0x3a ] = KEY_SHUFFLE, // SNAPSHOT - ??? + [ 0x0a ] = KEY_MUTE, // MUTE + + [ 0x26 ] = KEY_RECORD, // RECORD + [ 0x16 ] = KEY_PAUSE, // PAUSE + [ 0x36 ] = KEY_STOP, // STOP + [ 0x06 ] = KEY_PLAY, // PLAY + + [ 0x2e ] = KEY_RED, // + [ 0x21 ] = KEY_GREEN, // + [ 0x0e ] = KEY_YELLOW, // + [ 0x01 ] = KEY_BLUE, // + + [ 0x1e ] = KEY_VOLUMEDOWN, // VOLUME- + [ 0x3e ] = KEY_VOLUMEUP, // VOLUME+ + [ 0x11 ] = KEY_CHANNELDOWN, // CHANNEL/PAGE- + [ 0x31 ] = KEY_CHANNELUP // CHANNEL/PAGE+ +}; + +EXPORT_SYMBOL_GPL(ir_codes_md2819); + +IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE] = { + [ 0x14 ] = KEY_MUTE, + [ 0x24 ] = KEY_ZOOM, + + [ 0x01 ] = KEY_DVD, + [ 0x23 ] = KEY_RADIO, + [ 0x00 ] = KEY_TV, + + [ 0x0a ] = KEY_REWIND, + [ 0x08 ] = KEY_PLAYPAUSE, + [ 0x0f ] = KEY_FORWARD, + + [ 0x02 ] = KEY_PREVIOUS, + [ 0x07 ] = KEY_STOP, + [ 0x06 ] = KEY_NEXT, + + [ 0x0c ] = KEY_UP, + [ 0x0e ] = KEY_DOWN, + [ 0x0b ] = KEY_LEFT, + [ 0x0d ] = KEY_RIGHT, + [ 0x11 ] = KEY_OK, + + [ 0x03 ] = KEY_MENU, + [ 0x09 ] = KEY_SETUP, + [ 0x05 ] = KEY_VIDEO, + [ 0x22 ] = KEY_CHANNEL, + + [ 0x12 ] = KEY_VOLUMEUP, + [ 0x15 ] = KEY_VOLUMEDOWN, + [ 0x10 ] = KEY_CHANNELUP, + [ 0x13 ] = KEY_CHANNELDOWN, + + [ 0x04 ] = KEY_RECORD, + + [ 0x16 ] = KEY_1, + [ 0x17 ] = KEY_2, + [ 0x18 ] = KEY_3, + [ 0x19 ] = KEY_4, + [ 0x1a ] = KEY_5, + [ 0x1b ] = KEY_6, + [ 0x1c ] = KEY_7, + [ 0x1d ] = KEY_8, + [ 0x1e ] = KEY_9, + [ 0x1f ] = KEY_0, + + [ 0x20 ] = KEY_LANGUAGE, + [ 0x21 ] = KEY_SLEEP, +}; + +EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr); + +/* Michael Tokarev + http://www.corpit.ru/mjt/beholdTV/remote_control.jpg + keytable is used by MANLI MTV00[ 0x0c ] and BeholdTV 40[13] at + least, and probably other cards too. + The "ascii-art picture" below (in comments, first row + is the keycode in hex, and subsequent row(s) shows + the button labels (several variants when appropriate) + helps to descide which keycodes to assign to the buttons. + */ +IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { + + /* 0x1c 0x12 * + * FUNCTION POWER * + * FM (|) * + * */ + [ 0x1c ] = KEY_RADIO, /*XXX*/ + [ 0x12 ] = KEY_POWER, + + /* 0x01 0x02 0x03 * + * 1 2 3 * + * * + * 0x04 0x05 0x06 * + * 4 5 6 * + * * + * 0x07 0x08 0x09 * + * 7 8 9 * + * */ + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + /* 0x0a 0x00 0x17 * + * RECALL 0 +100 * + * PLUS * + * */ + [ 0x0a ] = KEY_AGAIN, /*XXX KEY_REWIND? */ + [ 0x00 ] = KEY_0, + [ 0x17 ] = KEY_DIGITS, /*XXX*/ + + /* 0x14 0x10 * + * MENU INFO * + * OSD */ + [ 0x14 ] = KEY_MENU, + [ 0x10 ] = KEY_INFO, + + /* 0x0b * + * Up * + * * + * 0x18 0x16 0x0c * + * Left Ok Right * + * * + * 0x015 * + * Down * + * */ + [ 0x0b ] = KEY_UP, /*XXX KEY_SCROLLUP? */ + [ 0x18 ] = KEY_LEFT, /*XXX KEY_BACK? */ + [ 0x16 ] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ + [ 0x0c ] = KEY_RIGHT, /*XXX KEY_FORWARD? */ + [ 0x15 ] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */ + + /* 0x11 0x0d * + * TV/AV MODE * + * SOURCE STEREO * + * */ + [ 0x11 ] = KEY_TV, /*XXX*/ + [ 0x0d ] = KEY_MODE, /*XXX there's no KEY_STEREO */ + + /* 0x0f 0x1b 0x1a * + * AUDIO Vol+ Chan+ * + * TIMESHIFT??? * + * * + * 0x0e 0x1f 0x1e * + * SLEEP Vol- Chan- * + * */ + [ 0x0f ] = KEY_AUDIO, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x1a ] = KEY_CHANNELUP, + [ 0x0e ] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ + [ 0x1f ] = KEY_VOLUMEDOWN, + [ 0x1e ] = KEY_CHANNELDOWN, + + /* 0x13 0x19 * + * MUTE SNAPSHOT* + * */ + [ 0x13 ] = KEY_MUTE, + [ 0x19 ] = KEY_RECORD, /*XXX*/ + + // 0x1d unused ? +}; + +EXPORT_SYMBOL_GPL(ir_codes_manli); + +/* Mike Baikov */ +IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { + + [ 0x21 ] = KEY_POWER, + [ 0x69 ] = KEY_TV, + [ 0x33 ] = KEY_0, + [ 0x51 ] = KEY_1, + [ 0x31 ] = KEY_2, + [ 0x71 ] = KEY_3, + [ 0x3b ] = KEY_4, + [ 0x58 ] = KEY_5, + [ 0x41 ] = KEY_6, + [ 0x48 ] = KEY_7, + [ 0x30 ] = KEY_8, + [ 0x53 ] = KEY_9, + [ 0x73 ] = KEY_AGAIN, /* LOOP */ + [ 0x0a ] = KEY_AUDIO, + [ 0x61 ] = KEY_PRINT, /* PREVIEW */ + [ 0x7a ] = KEY_VIDEO, + [ 0x20 ] = KEY_CHANNELUP, + [ 0x40 ] = KEY_CHANNELDOWN, + [ 0x18 ] = KEY_VOLUMEDOWN, + [ 0x50 ] = KEY_VOLUMEUP, + [ 0x10 ] = KEY_MUTE, + [ 0x4a ] = KEY_SEARCH, + [ 0x7b ] = KEY_SHUFFLE, /* SNAPSHOT */ + [ 0x22 ] = KEY_RECORD, + [ 0x62 ] = KEY_STOP, + [ 0x78 ] = KEY_PLAY, + [ 0x39 ] = KEY_REWIND, + [ 0x59 ] = KEY_PAUSE, + [ 0x19 ] = KEY_FORWARD, + [ 0x09 ] = KEY_ZOOM, + + [ 0x52 ] = KEY_F21, /* LIVE TIMESHIFT */ + [ 0x1a ] = KEY_F22, /* MIN TIMESHIFT */ + [ 0x3a ] = KEY_F23, /* TIMESHIFT */ + [ 0x70 ] = KEY_F24, /* NORMAL TIMESHIFT */ +}; + +EXPORT_SYMBOL_GPL(ir_codes_gotview7135); + +IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { + [ 0x03 ] = KEY_POWER, + [ 0x6f ] = KEY_MUTE, + [ 0x10 ] = KEY_BACKSPACE, /* Recall */ + + [ 0x11 ] = KEY_0, + [ 0x04 ] = KEY_1, + [ 0x05 ] = KEY_2, + [ 0x06 ] = KEY_3, + [ 0x08 ] = KEY_4, + [ 0x09 ] = KEY_5, + [ 0x0a ] = KEY_6, + [ 0x0c ] = KEY_7, + [ 0x0d ] = KEY_8, + [ 0x0e ] = KEY_9, + [ 0x12 ] = KEY_DOT, /* 100+ */ + + [ 0x07 ] = KEY_VOLUMEUP, + [ 0x0b ] = KEY_VOLUMEDOWN, + [ 0x1a ] = KEY_KPPLUS, + [ 0x18 ] = KEY_KPMINUS, + [ 0x15 ] = KEY_UP, + [ 0x1d ] = KEY_DOWN, + [ 0x0f ] = KEY_CHANNELUP, + [ 0x13 ] = KEY_CHANNELDOWN, + [ 0x48 ] = KEY_ZOOM, + + [ 0x1b ] = KEY_VIDEO, /* Video source */ + [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */ + [ 0x19 ] = KEY_SEARCH, /* Auto Scan */ + + [ 0x4b ] = KEY_RECORD, + [ 0x46 ] = KEY_PLAY, + [ 0x45 ] = KEY_PAUSE, /* Pause */ + [ 0x44 ] = KEY_STOP, + [ 0x40 ] = KEY_FORWARD, /* Forward ? */ + [ 0x42 ] = KEY_REWIND, /* Backward ? */ + +}; + +EXPORT_SYMBOL_GPL(ir_codes_purpletv); + +/* Mapping for the 28 key remote control as seen at + http://www.sednacomputer.com/photo/cardbus-tv.jpg + Pavel Mihaylov */ +IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0a ] = KEY_AGAIN, /* Recall */ + [ 0x0b ] = KEY_CHANNELUP, + [ 0x0c ] = KEY_VOLUMEUP, + [ 0x0d ] = KEY_MODE, /* Stereo */ + [ 0x0e ] = KEY_STOP, + [ 0x0f ] = KEY_PREVIOUSSONG, + [ 0x10 ] = KEY_ZOOM, + [ 0x11 ] = KEY_TUNER, /* Source */ + [ 0x12 ] = KEY_POWER, + [ 0x13 ] = KEY_MUTE, + [ 0x15 ] = KEY_CHANNELDOWN, + [ 0x18 ] = KEY_VOLUMEDOWN, + [ 0x19 ] = KEY_SHUFFLE, /* Snapshot */ + [ 0x1a ] = KEY_NEXTSONG, + [ 0x1b ] = KEY_TEXT, /* Time Shift */ + [ 0x1c ] = KEY_RADIO, /* FM Radio */ + [ 0x1d ] = KEY_RECORD, + [ 0x1e ] = KEY_PAUSE, +}; + +EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna); + +/* Mark Phalan */ +IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x12 ] = KEY_POWER, + [ 0x10 ] = KEY_MUTE, + [ 0x1f ] = KEY_VOLUMEDOWN, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x1a ] = KEY_CHANNELUP, + [ 0x1e ] = KEY_CHANNELDOWN, + [ 0x0e ] = KEY_PAGEUP, + [ 0x1d ] = KEY_PAGEDOWN, + [ 0x13 ] = KEY_SOUND, + + [ 0x18 ] = KEY_KPPLUSMINUS, /* CH +/- */ + [ 0x16 ] = KEY_SUBTITLE, /* CC */ + [ 0x0d ] = KEY_TEXT, /* TTX */ + [ 0x0b ] = KEY_TV, /* AIR/CBL */ + [ 0x11 ] = KEY_PC, /* PC/TV */ + [ 0x17 ] = KEY_OK, /* CH RTN */ + [ 0x19 ] = KEY_MODE, /* FUNC */ + [ 0x0c ] = KEY_SEARCH, /* AUTOSCAN */ + + /* Not sure what to do with these ones! */ + [ 0x0f ] = KEY_SELECT, /* SOURCE */ + [ 0x0a ] = KEY_KPPLUS, /* +100 */ + [ 0x14 ] = KEY_EQUAL, /* SYNC */ + [ 0x1c ] = KEY_MEDIA, /* PC/TV */ +}; + +EXPORT_SYMBOL_GPL(ir_codes_pv951); + +/* generic RC5 keytable */ +/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ +/* used by old (black) Hauppauge remotes */ +IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { + /* Keys 0 to 9 */ + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0b ] = KEY_CHANNEL, /* channel / program (japan: 11) */ + [ 0x0c ] = KEY_POWER, /* standby */ + [ 0x0d ] = KEY_MUTE, /* mute / demute */ + [ 0x0f ] = KEY_TV, /* display */ + [ 0x10 ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_VOLUMEDOWN, + [ 0x12 ] = KEY_BRIGHTNESSUP, + [ 0x13 ] = KEY_BRIGHTNESSDOWN, + [ 0x1e ] = KEY_SEARCH, /* search + */ + [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ + [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ + [ 0x22 ] = KEY_CHANNEL, /* alt / channel */ + [ 0x23 ] = KEY_LANGUAGE, /* 1st / 2nd language */ + [ 0x26 ] = KEY_SLEEP, /* sleeptimer */ + [ 0x2e ] = KEY_MENU, /* 2nd controls (USA: menu) */ + [ 0x30 ] = KEY_PAUSE, + [ 0x32 ] = KEY_REWIND, + [ 0x33 ] = KEY_GOTO, + [ 0x35 ] = KEY_PLAY, + [ 0x36 ] = KEY_STOP, + [ 0x37 ] = KEY_RECORD, /* recording */ + [ 0x3c ] = KEY_TEXT, /* teletext submode (Japan: 12) */ + [ 0x3d ] = KEY_SUSPEND, /* system standby */ + +}; + +EXPORT_SYMBOL_GPL(ir_codes_rc5_tv); + +/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ +IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { + /* Keys 0 to 9 */ + [ 0x12 ] = KEY_0, + [ 0x05 ] = KEY_1, + [ 0x06 ] = KEY_2, + [ 0x07 ] = KEY_3, + [ 0x09 ] = KEY_4, + [ 0x0a ] = KEY_5, + [ 0x0b ] = KEY_6, + [ 0x0d ] = KEY_7, + [ 0x0e ] = KEY_8, + [ 0x0f ] = KEY_9, + + [ 0x00 ] = KEY_POWER, + [ 0x02 ] = KEY_TUNER, /* TV/FM */ + [ 0x1e ] = KEY_VIDEO, + [ 0x04 ] = KEY_VOLUMEUP, + [ 0x08 ] = KEY_VOLUMEDOWN, + [ 0x0c ] = KEY_CHANNELUP, + [ 0x10 ] = KEY_CHANNELDOWN, + [ 0x03 ] = KEY_ZOOM, /* fullscreen */ + [ 0x1f ] = KEY_SUBTITLE, /* closed caption/teletext */ + [ 0x20 ] = KEY_SLEEP, + [ 0x14 ] = KEY_MUTE, + [ 0x2b ] = KEY_RED, + [ 0x2c ] = KEY_GREEN, + [ 0x2d ] = KEY_YELLOW, + [ 0x2e ] = KEY_BLUE, + [ 0x18 ] = KEY_KPPLUS, /* fine tune + */ + [ 0x19 ] = KEY_KPMINUS, /* fine tune - */ + [ 0x21 ] = KEY_DOT, + [ 0x13 ] = KEY_ENTER, + [ 0x22 ] = KEY_BACK, + [ 0x23 ] = KEY_PLAYPAUSE, + [ 0x24 ] = KEY_NEXT, + [ 0x26 ] = KEY_STOP, + [ 0x27 ] = KEY_RECORD +}; + +EXPORT_SYMBOL_GPL(ir_codes_winfast); + +IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { + [ 0x59 ] = KEY_MUTE, + [ 0x4a ] = KEY_POWER, + + [ 0x18 ] = KEY_TEXT, + [ 0x26 ] = KEY_TV, + [ 0x3d ] = KEY_PRINT, + + [ 0x48 ] = KEY_RED, + [ 0x04 ] = KEY_GREEN, + [ 0x11 ] = KEY_YELLOW, + [ 0x00 ] = KEY_BLUE, + + [ 0x2d ] = KEY_VOLUMEUP, + [ 0x1e ] = KEY_VOLUMEDOWN, + + [ 0x49 ] = KEY_MENU, + + [ 0x16 ] = KEY_CHANNELUP, + [ 0x17 ] = KEY_CHANNELDOWN, + + [ 0x20 ] = KEY_UP, + [ 0x21 ] = KEY_DOWN, + [ 0x22 ] = KEY_LEFT, + [ 0x23 ] = KEY_RIGHT, + [ 0x0d ] = KEY_SELECT, + + + + [ 0x08 ] = KEY_BACK, + [ 0x07 ] = KEY_REFRESH, + + [ 0x2f ] = KEY_ZOOM, + [ 0x29 ] = KEY_RECORD, + + [ 0x4b ] = KEY_PAUSE, + [ 0x4d ] = KEY_REWIND, + [ 0x2e ] = KEY_PLAY, + [ 0x4e ] = KEY_FORWARD, + [ 0x53 ] = KEY_PREVIOUS, + [ 0x4c ] = KEY_STOP, + [ 0x54 ] = KEY_NEXT, + + [ 0x69 ] = KEY_0, + [ 0x6a ] = KEY_1, + [ 0x6b ] = KEY_2, + [ 0x6c ] = KEY_3, + [ 0x6d ] = KEY_4, + [ 0x6e ] = KEY_5, + [ 0x6f ] = KEY_6, + [ 0x70 ] = KEY_7, + [ 0x71 ] = KEY_8, + [ 0x72 ] = KEY_9, + + [ 0x74 ] = KEY_CHANNEL, + [ 0x0a ] = KEY_BACKSPACE, +}; + +EXPORT_SYMBOL_GPL(ir_codes_pinnacle); + +/* Hauppauge: the newer, gray remotes (seems there are multiple + * slightly different versions), shipped with cx88+ivtv cards. + * almost rc5 coding, but some non-standard keys */ +IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { + /* Keys 0 to 9 */ + [ 0x00 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + [ 0x0a ] = KEY_TEXT, /* keypad asterisk as well */ + [ 0x0b ] = KEY_RED, /* red button */ + [ 0x0c ] = KEY_RADIO, + [ 0x0d ] = KEY_MENU, + [ 0x0e ] = KEY_SUBTITLE, /* also the # key */ + [ 0x0f ] = KEY_MUTE, + [ 0x10 ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_VOLUMEDOWN, + [ 0x12 ] = KEY_PREVIOUS, /* previous channel */ + [ 0x14 ] = KEY_UP, + [ 0x15 ] = KEY_DOWN, + [ 0x16 ] = KEY_LEFT, + [ 0x17 ] = KEY_RIGHT, + [ 0x18 ] = KEY_VIDEO, /* Videos */ + [ 0x19 ] = KEY_AUDIO, /* Music */ + /* 0x1a: Pictures - presume this means + "Multimedia Home Platform" - + no "PICTURES" key in input.h + */ + [ 0x1a ] = KEY_MHP, + + [ 0x1b ] = KEY_EPG, /* Guide */ + [ 0x1c ] = KEY_TV, + [ 0x1e ] = KEY_NEXTSONG, /* skip >| */ + [ 0x1f ] = KEY_EXIT, /* back/exit */ + [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ + [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ + [ 0x22 ] = KEY_CHANNEL, /* source (old black remote) */ + [ 0x24 ] = KEY_PREVIOUSSONG, /* replay |< */ + [ 0x25 ] = KEY_ENTER, /* OK */ + [ 0x26 ] = KEY_SLEEP, /* minimize (old black remote) */ + [ 0x29 ] = KEY_BLUE, /* blue key */ + [ 0x2e ] = KEY_GREEN, /* green button */ + [ 0x30 ] = KEY_PAUSE, /* pause */ + [ 0x32 ] = KEY_REWIND, /* backward << */ + [ 0x34 ] = KEY_FASTFORWARD, /* forward >> */ + [ 0x35 ] = KEY_PLAY, + [ 0x36 ] = KEY_STOP, + [ 0x37 ] = KEY_RECORD, /* recording */ + [ 0x38 ] = KEY_YELLOW, /* yellow key */ + [ 0x3b ] = KEY_SELECT, /* top right button */ + [ 0x3c ] = KEY_ZOOM, /* full */ + [ 0x3d ] = KEY_POWER, /* system power (green button) */ +}; + +EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); + +IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { + [ 0x02 ] = KEY_0, + [ 0x01 ] = KEY_1, + [ 0x0b ] = KEY_2, + [ 0x1b ] = KEY_3, + [ 0x05 ] = KEY_4, + [ 0x09 ] = KEY_5, + [ 0x15 ] = KEY_6, + [ 0x06 ] = KEY_7, + [ 0x0a ] = KEY_8, + [ 0x12 ] = KEY_9, + + [ 0x03 ] = KEY_TUNER, /* TV/FM */ + [ 0x07 ] = KEY_SEARCH, /* scan */ + [ 0x1c ] = KEY_ZOOM, /* full screen */ + [ 0x1e ] = KEY_POWER, + [ 0x17 ] = KEY_VOLUMEDOWN, + [ 0x1f ] = KEY_VOLUMEUP, + [ 0x14 ] = KEY_CHANNELDOWN, + [ 0x16 ] = KEY_CHANNELUP, + [ 0x18 ] = KEY_MUTE, + + [ 0x00 ] = KEY_LIST, /* source */ + [ 0x13 ] = KEY_INFO, /* loop */ + [ 0x10 ] = KEY_LAST, /* +100 */ + [ 0x0d ] = KEY_CLEAR, /* reset */ + [ 0x0c ] = BTN_RIGHT, /* fun++ */ + [ 0x04 ] = BTN_LEFT, /* fun-- */ + [ 0x0e ] = KEY_GOTO, /* function */ + [ 0x0f ] = KEY_STOP, /* freeze */ +}; + +EXPORT_SYMBOL_GPL(ir_codes_pixelview); + diff --git a/drivers/media/video/bttv-input.c b/drivers/media/video/bttv-input.c index 221b36e7f392..42760ae867d6 100644 --- a/drivers/media/video/bttv-input.c +++ b/drivers/media/video/bttv-input.c @@ -28,251 +28,6 @@ #include "bttv.h" #include "bttvp.h" -/* ---------------------------------------------------------------------- */ - -static IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { - [ 34 ] = KEY_KP0, - [ 40 ] = KEY_KP1, - [ 24 ] = KEY_KP2, - [ 56 ] = KEY_KP3, - [ 36 ] = KEY_KP4, - [ 20 ] = KEY_KP5, - [ 52 ] = KEY_KP6, - [ 44 ] = KEY_KP7, - [ 28 ] = KEY_KP8, - [ 60 ] = KEY_KP9, - - [ 48 ] = KEY_EJECTCD, // Unmarked on my controller - [ 0 ] = KEY_POWER, - [ 18 ] = BTN_LEFT, // DISPLAY/L - [ 50 ] = BTN_RIGHT, // LOOP/R - [ 10 ] = KEY_MUTE, - [ 38 ] = KEY_RECORD, - [ 22 ] = KEY_PAUSE, - [ 54 ] = KEY_STOP, - [ 30 ] = KEY_VOLUMEDOWN, - [ 62 ] = KEY_VOLUMEUP, - - [ 32 ] = KEY_TUNER, // TV/FM - [ 16 ] = KEY_CD, - [ 8 ] = KEY_VIDEO, - [ 4 ] = KEY_AUDIO, - [ 12 ] = KEY_ZOOM, // full screen - [ 2 ] = KEY_INFO, // preview - [ 42 ] = KEY_SEARCH, // autoscan - [ 26 ] = KEY_STOP, // freeze - [ 58 ] = KEY_RECORD, // capture - [ 6 ] = KEY_PLAY, // unmarked - [ 46 ] = KEY_RED, // unmarked - [ 14 ] = KEY_GREEN, // unmarked - - [ 33 ] = KEY_YELLOW, // unmarked - [ 17 ] = KEY_CHANNELDOWN, - [ 49 ] = KEY_CHANNELUP, - [ 1 ] = KEY_BLUE, // unmarked -}; - -/* Matt Jesson >' - [ 0x3a ] = KEY_RECORD, // 'capture' - [ 0x0a ] = KEY_MUTE, // 'mute' - [ 0x2c ] = KEY_RECORD, // 'record' - [ 0x1c ] = KEY_PAUSE, // 'pause' - [ 0x3c ] = KEY_STOP, // 'stop' - [ 0x0c ] = KEY_PLAY, // 'play' - [ 0x2e ] = KEY_RED, // 'red' - [ 0x01 ] = KEY_BLUE, // 'blue' / 'cancel' - [ 0x0e ] = KEY_YELLOW, // 'yellow' / 'ok' - [ 0x21 ] = KEY_GREEN, // 'green' - [ 0x11 ] = KEY_CHANNELDOWN, // 'channel -' - [ 0x31 ] = KEY_CHANNELUP, // 'channel +' - [ 0x1e ] = KEY_VOLUMEDOWN, // 'volume -' - [ 0x3e ] = KEY_VOLUMEUP, // 'volume +' -}; - -/* Attila Kondoros */ -static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { - - [ 1 ] = KEY_KP1, - [ 2 ] = KEY_KP2, - [ 3 ] = KEY_KP3, - [ 4 ] = KEY_KP4, - [ 5 ] = KEY_KP5, - [ 6 ] = KEY_KP6, - [ 7 ] = KEY_KP7, - [ 8 ] = KEY_KP8, - [ 9 ] = KEY_KP9, - [ 0 ] = KEY_KP0, - [ 23 ] = KEY_LAST, // +100 - [ 10 ] = KEY_LIST, // recall - - - [ 28 ] = KEY_TUNER, // TV/FM - [ 21 ] = KEY_SEARCH, // scan - [ 18 ] = KEY_POWER, // power - [ 31 ] = KEY_VOLUMEDOWN, // vol up - [ 27 ] = KEY_VOLUMEUP, // vol down - [ 30 ] = KEY_CHANNELDOWN, // chn up - [ 26 ] = KEY_CHANNELUP, // chn down - - [ 17 ] = KEY_VIDEO, // video - [ 15 ] = KEY_ZOOM, // full screen - [ 19 ] = KEY_MUTE, // mute/unmute - [ 16 ] = KEY_TEXT, // min - - [ 13 ] = KEY_STOP, // freeze - [ 14 ] = KEY_RECORD, // record - [ 29 ] = KEY_PLAYPAUSE, // stop - [ 25 ] = KEY_PLAY, // play - - [ 22 ] = KEY_GOTO, // osd - [ 20 ] = KEY_REFRESH, // default - [ 12 ] = KEY_KPPLUS, // fine tune >>>> - [ 24 ] = KEY_KPMINUS // fine tune <<<< -}; - -/* ---------------------------------------------------------------------- */ - -static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = { - - [ 30 ] = KEY_POWER, // power - [ 7 ] = KEY_MEDIA, // source - [ 28 ] = KEY_SEARCH, // scan - -/* FIXME: duplicate keycodes? - * - * These four keys seem to share the same GPIO as CH+, CH-, <<< and >>> - * The GPIO values are - * 6397fb for both "Scan <" and "CH -", - * 639ffb for "Scan >" and "CH+", - * 6384fb for "Tune <" and "<<<", - * 638cfb for "Tune >" and ">>>", regardless of the mask. - * - * [ 23 ] = KEY_BACK, // fm scan << - * [ 31 ] = KEY_FORWARD, // fm scan >> - * - * [ 4 ] = KEY_LEFT, // fm tuning < - * [ 12 ] = KEY_RIGHT, // fm tuning > - * - * For now, these four keys are disabled. Pressing them will generate - * the CH+/CH-/<<>> events - */ - - [ 3 ] = KEY_TUNER, // TV/FM - - [ 0 ] = KEY_RECORD, - [ 8 ] = KEY_STOP, - [ 17 ] = KEY_PLAY, - - [ 26 ] = KEY_PLAYPAUSE, // freeze - [ 25 ] = KEY_ZOOM, // zoom - [ 15 ] = KEY_TEXT, // min - - [ 1 ] = KEY_KP1, - [ 11 ] = KEY_KP2, - [ 27 ] = KEY_KP3, - [ 5 ] = KEY_KP4, - [ 9 ] = KEY_KP5, - [ 21 ] = KEY_KP6, - [ 6 ] = KEY_KP7, - [ 10 ] = KEY_KP8, - [ 18 ] = KEY_KP9, - [ 2 ] = KEY_KP0, - [ 16 ] = KEY_LAST, // +100 - [ 19 ] = KEY_LIST, // recall - - [ 31 ] = KEY_CHANNELUP, // chn down - [ 23 ] = KEY_CHANNELDOWN, // chn up - [ 22 ] = KEY_VOLUMEUP, // vol down - [ 20 ] = KEY_VOLUMEDOWN, // vol up - - [ 4 ] = KEY_KPMINUS, // <<< - [ 14 ] = KEY_SETUP, // function - [ 12 ] = KEY_KPPLUS, // >>> - - [ 13 ] = KEY_GOTO, // mts - [ 29 ] = KEY_REFRESH, // reset - [ 24 ] = KEY_MUTE // mute/unmute -}; - -static IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { - [0x00] = KEY_KP0, - [0x01] = KEY_KP1, - [0x02] = KEY_KP2, - [0x03] = KEY_KP3, - [0x04] = KEY_KP4, - [0x05] = KEY_KP5, - [0x06] = KEY_KP6, - [0x07] = KEY_KP7, - [0x08] = KEY_KP8, - [0x09] = KEY_KP9, - [0x0a] = KEY_TV, - [0x0b] = KEY_AUX, - [0x0c] = KEY_DVD, - [0x0d] = KEY_POWER, - [0x0e] = KEY_MHP, /* labelled 'Picture' */ - [0x0f] = KEY_AUDIO, - [0x10] = KEY_INFO, - [0x11] = KEY_F13, /* 16:9 */ - [0x12] = KEY_F14, /* 14:9 */ - [0x13] = KEY_EPG, - [0x14] = KEY_EXIT, - [0x15] = KEY_MENU, - [0x16] = KEY_UP, - [0x17] = KEY_DOWN, - [0x18] = KEY_LEFT, - [0x19] = KEY_RIGHT, - [0x1a] = KEY_ENTER, - [0x1b] = KEY_CHANNELUP, - [0x1c] = KEY_CHANNELDOWN, - [0x1d] = KEY_VOLUMEUP, - [0x1e] = KEY_VOLUMEDOWN, - [0x1f] = KEY_RED, - [0x20] = KEY_GREEN, - [0x21] = KEY_YELLOW, - [0x22] = KEY_BLUE, - [0x23] = KEY_SUBTITLE, - [0x24] = KEY_F15, /* AD */ - [0x25] = KEY_TEXT, - [0x26] = KEY_MUTE, - [0x27] = KEY_REWIND, - [0x28] = KEY_STOP, - [0x29] = KEY_PLAY, - [0x2a] = KEY_FASTFORWARD, - [0x2b] = KEY_F16, /* chapter */ - [0x2c] = KEY_PAUSE, - [0x2d] = KEY_PLAY, - [0x2e] = KEY_RECORD, - [0x2f] = KEY_F17, /* picture in picture */ - [0x30] = KEY_KPPLUS, /* zoom in */ - [0x31] = KEY_KPMINUS, /* zoom out */ - [0x32] = KEY_F18, /* capture */ - [0x33] = KEY_F19, /* web */ - [0x34] = KEY_EMAIL, - [0x35] = KEY_PHONE, - [0x36] = KEY_PC -}; static int debug; module_param(debug, int, 0644); /* debug level (0,1,2) */ diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index da2ad5c4b553..a4fa92c1b0c7 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -34,337 +34,6 @@ /* ---------------------------------------------------------------------- */ -/* DigitalNow DNTV Live DVB-T Remote */ -static IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { - [0x00] = KEY_ESC, /* 'go up a level?' */ - /* Keys 0 to 9 */ - [0x0a] = KEY_KP0, - [0x01] = KEY_KP1, - [0x02] = KEY_KP2, - [0x03] = KEY_KP3, - [0x04] = KEY_KP4, - [0x05] = KEY_KP5, - [0x06] = KEY_KP6, - [0x07] = KEY_KP7, - [0x08] = KEY_KP8, - [0x09] = KEY_KP9, - - [0x0b] = KEY_TUNER, /* tv/fm */ - [0x0c] = KEY_SEARCH, /* scan */ - [0x0d] = KEY_STOP, - [0x0e] = KEY_PAUSE, - [0x0f] = KEY_LIST, /* source */ - - [0x10] = KEY_MUTE, - [0x11] = KEY_REWIND, /* backward << */ - [0x12] = KEY_POWER, - [0x13] = KEY_S, /* snap */ - [0x14] = KEY_AUDIO, /* stereo */ - [0x15] = KEY_CLEAR, /* reset */ - [0x16] = KEY_PLAY, - [0x17] = KEY_ENTER, - [0x18] = KEY_ZOOM, /* full screen */ - [0x19] = KEY_FASTFORWARD, /* forward >> */ - [0x1a] = KEY_CHANNELUP, - [0x1b] = KEY_VOLUMEUP, - [0x1c] = KEY_INFO, /* preview */ - [0x1d] = KEY_RECORD, /* record */ - [0x1e] = KEY_CHANNELDOWN, - [0x1f] = KEY_VOLUMEDOWN, -}; - -/* ---------------------------------------------------------------------- */ - -/* IO-DATA BCTV7E Remote */ -static IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { - [0x40] = KEY_TV, - [0x20] = KEY_RADIO, /* FM */ - [0x60] = KEY_EPG, - [0x00] = KEY_POWER, - - /* Keys 0 to 9 */ - [0x44] = KEY_KP0, /* 10 */ - [0x50] = KEY_KP1, - [0x30] = KEY_KP2, - [0x70] = KEY_KP3, - [0x48] = KEY_KP4, - [0x28] = KEY_KP5, - [0x68] = KEY_KP6, - [0x58] = KEY_KP7, - [0x38] = KEY_KP8, - [0x78] = KEY_KP9, - - [0x10] = KEY_L, /* Live */ - [0x08] = KEY_T, /* Time Shift */ - - [0x18] = KEY_PLAYPAUSE, /* Play */ - - [0x24] = KEY_ENTER, /* 11 */ - [0x64] = KEY_ESC, /* 12 */ - [0x04] = KEY_M, /* Multi */ - - [0x54] = KEY_VIDEO, - [0x34] = KEY_CHANNELUP, - [0x74] = KEY_VOLUMEUP, - [0x14] = KEY_MUTE, - - [0x4c] = KEY_S, /* SVIDEO */ - [0x2c] = KEY_CHANNELDOWN, - [0x6c] = KEY_VOLUMEDOWN, - [0x0c] = KEY_ZOOM, - - [0x5c] = KEY_PAUSE, - [0x3c] = KEY_C, /* || (red) */ - [0x7c] = KEY_RECORD, /* recording */ - [0x1c] = KEY_STOP, - - [0x41] = KEY_REWIND, /* backward << */ - [0x21] = KEY_PLAY, - [0x61] = KEY_FASTFORWARD, /* forward >> */ - [0x01] = KEY_NEXT, /* skip >| */ -}; - -/* ---------------------------------------------------------------------- */ - -/* ADS Tech Instant TV DVB-T PCI Remote */ -static IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = { - /* Keys 0 to 9 */ - [0x4d] = KEY_0, - [0x57] = KEY_1, - [0x4f] = KEY_2, - [0x53] = KEY_3, - [0x56] = KEY_4, - [0x4e] = KEY_5, - [0x5e] = KEY_6, - [0x54] = KEY_7, - [0x4c] = KEY_8, - [0x5c] = KEY_9, - - [0x5b] = KEY_POWER, - [0x5f] = KEY_MUTE, - [0x55] = KEY_GOTO, - [0x5d] = KEY_SEARCH, - [0x17] = KEY_EPG, /* Guide */ - [0x1f] = KEY_MENU, - [0x0f] = KEY_UP, - [0x46] = KEY_DOWN, - [0x16] = KEY_LEFT, - [0x1e] = KEY_RIGHT, - [0x0e] = KEY_SELECT, /* Enter */ - [0x5a] = KEY_INFO, - [0x52] = KEY_EXIT, - [0x59] = KEY_PREVIOUS, - [0x51] = KEY_NEXT, - [0x58] = KEY_REWIND, - [0x50] = KEY_FORWARD, - [0x44] = KEY_PLAYPAUSE, - [0x07] = KEY_STOP, - [0x1b] = KEY_RECORD, - [0x13] = KEY_TUNER, /* Live */ - [0x0a] = KEY_A, - [0x12] = KEY_B, - [0x03] = KEY_PROG1, /* 1 */ - [0x01] = KEY_PROG2, /* 2 */ - [0x00] = KEY_PROG3, /* 3 */ - [0x06] = KEY_DVD, - [0x48] = KEY_AUX, /* Photo */ - [0x40] = KEY_VIDEO, - [0x19] = KEY_AUDIO, /* Music */ - [0x0b] = KEY_CHANNELUP, - [0x08] = KEY_CHANNELDOWN, - [0x15] = KEY_VOLUMEUP, - [0x1c] = KEY_VOLUMEDOWN, -}; - -/* ---------------------------------------------------------------------- */ - -/* MSI TV@nywhere remote */ -static IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { - /* Keys 0 to 9 */ - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - - [0x0c] = KEY_MUTE, - [0x0f] = KEY_SCREEN, /* Full Screen */ - [0x10] = KEY_F, /* Funtion */ - [0x11] = KEY_T, /* Time shift */ - [0x12] = KEY_POWER, - [0x13] = KEY_MEDIA, /* MTS */ - [0x14] = KEY_SLOW, - [0x16] = KEY_REWIND, /* backward << */ - [0x17] = KEY_ENTER, /* Return */ - [0x18] = KEY_FASTFORWARD, /* forward >> */ - [0x1a] = KEY_CHANNELUP, - [0x1b] = KEY_VOLUMEUP, - [0x1e] = KEY_CHANNELDOWN, - [0x1f] = KEY_VOLUMEDOWN, -}; - -/* ---------------------------------------------------------------------- */ - -/* Cinergy 1400 DVB-T */ -static IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { - [0x01] = KEY_POWER, - [0x02] = KEY_1, - [0x03] = KEY_2, - [0x04] = KEY_3, - [0x05] = KEY_4, - [0x06] = KEY_5, - [0x07] = KEY_6, - [0x08] = KEY_7, - [0x09] = KEY_8, - [0x0a] = KEY_9, - [0x0c] = KEY_0, - - [0x0b] = KEY_VIDEO, - [0x0d] = KEY_REFRESH, - [0x0e] = KEY_SELECT, - [0x0f] = KEY_EPG, - [0x10] = KEY_UP, - [0x11] = KEY_LEFT, - [0x12] = KEY_OK, - [0x13] = KEY_RIGHT, - [0x14] = KEY_DOWN, - [0x15] = KEY_TEXT, - [0x16] = KEY_INFO, - - [0x17] = KEY_RED, - [0x18] = KEY_GREEN, - [0x19] = KEY_YELLOW, - [0x1a] = KEY_BLUE, - - [0x1b] = KEY_CHANNELUP, - [0x1c] = KEY_VOLUMEUP, - [0x1d] = KEY_MUTE, - [0x1e] = KEY_VOLUMEDOWN, - [0x1f] = KEY_CHANNELDOWN, - - [0x40] = KEY_PAUSE, - [0x4c] = KEY_PLAY, - [0x58] = KEY_RECORD, - [0x54] = KEY_PREVIOUS, - [0x48] = KEY_STOP, - [0x5c] = KEY_NEXT, -}; - -/* ---------------------------------------------------------------------- */ - -/* AVERTV STUDIO 303 Remote */ -static IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = { - [ 0x2a ] = KEY_KP1, - [ 0x32 ] = KEY_KP2, - [ 0x3a ] = KEY_KP3, - [ 0x4a ] = KEY_KP4, - [ 0x52 ] = KEY_KP5, - [ 0x5a ] = KEY_KP6, - [ 0x6a ] = KEY_KP7, - [ 0x72 ] = KEY_KP8, - [ 0x7a ] = KEY_KP9, - [ 0x0e ] = KEY_KP0, - - [ 0x02 ] = KEY_POWER, - [ 0x22 ] = KEY_VIDEO, - [ 0x42 ] = KEY_AUDIO, - [ 0x62 ] = KEY_ZOOM, - [ 0x0a ] = KEY_TV, - [ 0x12 ] = KEY_CD, - [ 0x1a ] = KEY_TEXT, - - [ 0x16 ] = KEY_SUBTITLE, - [ 0x1e ] = KEY_REWIND, - [ 0x06 ] = KEY_PRINT, - - [ 0x2e ] = KEY_SEARCH, - [ 0x36 ] = KEY_SLEEP, - [ 0x3e ] = KEY_SHUFFLE, - [ 0x26 ] = KEY_MUTE, - - [ 0x4e ] = KEY_RECORD, - [ 0x56 ] = KEY_PAUSE, - [ 0x5e ] = KEY_STOP, - [ 0x46 ] = KEY_PLAY, - - [ 0x6e ] = KEY_RED, - [ 0x0b ] = KEY_GREEN, - [ 0x66 ] = KEY_YELLOW, - [ 0x03 ] = KEY_BLUE, - - [ 0x76 ] = KEY_LEFT, - [ 0x7e ] = KEY_RIGHT, - [ 0x13 ] = KEY_DOWN, - [ 0x1b ] = KEY_UP, -}; - -/* ---------------------------------------------------------------------- */ - -/* DigitalNow DNTV Live! DVB-T Pro Remote */ -static IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { - [ 0x16 ] = KEY_POWER, - [ 0x5b ] = KEY_HOME, - - [ 0x55 ] = KEY_TV, /* live tv */ - [ 0x58 ] = KEY_TUNER, /* digital Radio */ - [ 0x5a ] = KEY_RADIO, /* FM radio */ - [ 0x59 ] = KEY_DVD, /* dvd menu */ - [ 0x03 ] = KEY_1, - [ 0x01 ] = KEY_2, - [ 0x06 ] = KEY_3, - [ 0x09 ] = KEY_4, - [ 0x1d ] = KEY_5, - [ 0x1f ] = KEY_6, - [ 0x0d ] = KEY_7, - [ 0x19 ] = KEY_8, - [ 0x1b ] = KEY_9, - [ 0x0c ] = KEY_CANCEL, - [ 0x15 ] = KEY_0, - [ 0x4a ] = KEY_CLEAR, - [ 0x13 ] = KEY_BACK, - [ 0x00 ] = KEY_TAB, - [ 0x4b ] = KEY_UP, - [ 0x4e ] = KEY_LEFT, - [ 0x4f ] = KEY_OK, - [ 0x52 ] = KEY_RIGHT, - [ 0x51 ] = KEY_DOWN, - [ 0x1e ] = KEY_VOLUMEUP, - [ 0x0a ] = KEY_VOLUMEDOWN, - [ 0x02 ] = KEY_CHANNELDOWN, - [ 0x05 ] = KEY_CHANNELUP, - [ 0x11 ] = KEY_RECORD, - [ 0x14 ] = KEY_PLAY, - [ 0x4c ] = KEY_PAUSE, - [ 0x1a ] = KEY_STOP, - [ 0x40 ] = KEY_REWIND, - [ 0x12 ] = KEY_FASTFORWARD, - [ 0x41 ] = KEY_PREVIOUSSONG, /* replay |< */ - [ 0x42 ] = KEY_NEXTSONG, /* skip >| */ - [ 0x54 ] = KEY_CAMERA, /* capture */ - [ 0x50 ] = KEY_LANGUAGE, /* sap */ - [ 0x47 ] = KEY_TV2, /* pip */ - [ 0x4d ] = KEY_SCREEN, - [ 0x43 ] = KEY_SUBTITLE, - [ 0x10 ] = KEY_MUTE, - [ 0x49 ] = KEY_AUDIO, /* l/r */ - [ 0x07 ] = KEY_SLEEP, - [ 0x08 ] = KEY_VIDEO, /* a/v */ - [ 0x0e ] = KEY_PREVIOUS, /* recall */ - [ 0x45 ] = KEY_ZOOM, /* zoom + */ - [ 0x46 ] = KEY_ANGLE, /* zoom - */ - [ 0x56 ] = KEY_RED, - [ 0x57 ] = KEY_GREEN, - [ 0x5c ] = KEY_YELLOW, - [ 0x5d ] = KEY_BLUE, -}; - -/* ---------------------------------------------------------------------- */ - struct cx88_IR { struct cx88_core *core; struct input_dev *input; diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 30dfa5370c73..31e89e4f18be 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -43,91 +43,6 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); #define dprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) -/* ---------------------------------------------------------------------- */ - -static IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_CHANNEL, - [ 0x02 ] = KEY_SELECT, - [ 0x03 ] = KEY_MUTE, - [ 0x04 ] = KEY_POWER, - [ 0x05 ] = KEY_KP1, - [ 0x06 ] = KEY_KP2, - [ 0x07 ] = KEY_KP3, - [ 0x08 ] = KEY_CHANNELUP, - [ 0x09 ] = KEY_KP4, - [ 0x0a ] = KEY_KP5, - [ 0x0b ] = KEY_KP6, - [ 0x0c ] = KEY_CHANNELDOWN, - [ 0x0d ] = KEY_KP7, - [ 0x0e ] = KEY_KP8, - [ 0x0f ] = KEY_KP9, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_KP0, - [ 0x12 ] = KEY_MENU, - [ 0x13 ] = KEY_PRINT, - [ 0x14 ] = KEY_VOLUMEDOWN, - [ 0x16 ] = KEY_PAUSE, - [ 0x18 ] = KEY_RECORD, - [ 0x19 ] = KEY_REWIND, - [ 0x1a ] = KEY_PLAY, - [ 0x1b ] = KEY_FORWARD, - [ 0x1c ] = KEY_BACKSPACE, - [ 0x1e ] = KEY_STOP, - [ 0x40 ] = KEY_ZOOM, -}; - -static IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = { - [ 0x3a ] = KEY_KP0, - [ 0x31 ] = KEY_KP1, - [ 0x32 ] = KEY_KP2, - [ 0x33 ] = KEY_KP3, - [ 0x34 ] = KEY_KP4, - [ 0x35 ] = KEY_KP5, - [ 0x36 ] = KEY_KP6, - [ 0x37 ] = KEY_KP7, - [ 0x38 ] = KEY_KP8, - [ 0x39 ] = KEY_KP9, - - [ 0x2f ] = KEY_POWER, - - [ 0x2e ] = KEY_P, - [ 0x1f ] = KEY_L, - [ 0x2b ] = KEY_I, - - [ 0x2d ] = KEY_ZOOM, - [ 0x1e ] = KEY_ZOOM, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x0f ] = KEY_VOLUMEDOWN, - [ 0x17 ] = KEY_CHANNELUP, - [ 0x1c ] = KEY_CHANNELDOWN, - [ 0x25 ] = KEY_INFO, - - [ 0x3c ] = KEY_MUTE, - - [ 0x3d ] = KEY_LEFT, - [ 0x3b ] = KEY_RIGHT, - - [ 0x3f ] = KEY_UP, - [ 0x3e ] = KEY_DOWN, - [ 0x1a ] = KEY_PAUSE, - - [ 0x1d ] = KEY_MENU, - [ 0x19 ] = KEY_PLAY, - [ 0x16 ] = KEY_REWIND, - [ 0x13 ] = KEY_FORWARD, - [ 0x15 ] = KEY_PAUSE, - [ 0x0e ] = KEY_REWIND, - [ 0x0d ] = KEY_PLAY, - [ 0x0b ] = KEY_STOP, - [ 0x07 ] = KEY_FORWARD, - [ 0x27 ] = KEY_RECORD, - [ 0x26 ] = KEY_TUNER, - [ 0x29 ] = KEY_TEXT, - [ 0x2a ] = KEY_MEDIA, - [ 0x18 ] = KEY_EPG, - [ 0x27 ] = KEY_RECORD, -}; - /* ----------------------------------------------------------------------- */ static int get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 3963481b3130..95bacf435414 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -44,45 +44,6 @@ #include #include -/* Mark Phalan */ -static IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { - [ 0 ] = KEY_KP0, - [ 1 ] = KEY_KP1, - [ 2 ] = KEY_KP2, - [ 3 ] = KEY_KP3, - [ 4 ] = KEY_KP4, - [ 5 ] = KEY_KP5, - [ 6 ] = KEY_KP6, - [ 7 ] = KEY_KP7, - [ 8 ] = KEY_KP8, - [ 9 ] = KEY_KP9, - - [ 18 ] = KEY_POWER, - [ 16 ] = KEY_MUTE, - [ 31 ] = KEY_VOLUMEDOWN, - [ 27 ] = KEY_VOLUMEUP, - [ 26 ] = KEY_CHANNELUP, - [ 30 ] = KEY_CHANNELDOWN, - [ 14 ] = KEY_PAGEUP, - [ 29 ] = KEY_PAGEDOWN, - [ 19 ] = KEY_SOUND, - - [ 24 ] = KEY_KPPLUSMINUS, /* CH +/- */ - [ 22 ] = KEY_SUBTITLE, /* CC */ - [ 13 ] = KEY_TEXT, /* TTX */ - [ 11 ] = KEY_TV, /* AIR/CBL */ - [ 17 ] = KEY_PC, /* PC/TV */ - [ 23 ] = KEY_OK, /* CH RTN */ - [ 25 ] = KEY_MODE, /* FUNC */ - [ 12 ] = KEY_SEARCH, /* AUTOSCAN */ - - /* Not sure what to do with these ones! */ - [ 15 ] = KEY_SELECT, /* SOURCE */ - [ 10 ] = KEY_KPPLUS, /* +100 */ - [ 20 ] = KEY_KPEQUAL, /* SYNC */ - [ 28 ] = KEY_MEDIA, /* PC/TV */ -}; - /* ----------------------------------------------------------------------- */ /* insmod parameters */ @@ -342,7 +303,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir->get_key = get_key_haup; ir_type = IR_TYPE_RC5; if (hauppauge == 1) { - ir_codes = ir_codes_rc5_tv_grey; + ir_codes = ir_codes_hauppauge_new; } else { ir_codes = ir_codes_rc5_tv; } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 82d28cbf289f..342568cf728f 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -42,485 +42,6 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); #define i2cdprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) -/* ---------------------------------------------------------------------- */ - -static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = { - [ 15 ] = KEY_KP0, - [ 3 ] = KEY_KP1, - [ 4 ] = KEY_KP2, - [ 5 ] = KEY_KP3, - [ 7 ] = KEY_KP4, - [ 8 ] = KEY_KP5, - [ 9 ] = KEY_KP6, - [ 11 ] = KEY_KP7, - [ 12 ] = KEY_KP8, - [ 13 ] = KEY_KP9, - - [ 14 ] = KEY_MODE, // Air/Cable - [ 17 ] = KEY_VIDEO, // Video - [ 21 ] = KEY_AUDIO, // Audio - [ 0 ] = KEY_POWER, // Power - [ 24 ] = KEY_TUNER, // AV Source - [ 2 ] = KEY_ZOOM, // Fullscreen - [ 26 ] = KEY_LANGUAGE, // Stereo - [ 27 ] = KEY_MUTE, // Mute - [ 20 ] = KEY_VOLUMEUP, // Volume + - [ 23 ] = KEY_VOLUMEDOWN, // Volume - - [ 18 ] = KEY_CHANNELUP, // Channel + - [ 19 ] = KEY_CHANNELDOWN, // Channel - - [ 6 ] = KEY_AGAIN, // Recall - [ 16 ] = KEY_ENTER, // Enter -}; - - -static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = { - [ 0 ] = KEY_KP0, - [ 1 ] = KEY_KP1, - [ 2 ] = KEY_KP2, - [ 3 ] = KEY_KP3, - [ 4 ] = KEY_KP4, - [ 5 ] = KEY_KP5, - [ 6 ] = KEY_KP6, - [ 7 ] = KEY_KP7, - [ 8 ] = KEY_KP8, - [ 9 ] = KEY_KP9, - - [ 0x0a ] = KEY_POWER, - [ 0x0b ] = KEY_PROG1, // app - [ 0x0c ] = KEY_ZOOM, // zoom/fullscreen - [ 0x0d ] = KEY_CHANNELUP, // channel - [ 0x0e ] = KEY_CHANNELDOWN, // channel- - [ 0x0f ] = KEY_VOLUMEUP, - [ 0x10 ] = KEY_VOLUMEDOWN, - [ 0x11 ] = KEY_TUNER, // AV - [ 0x12 ] = KEY_NUMLOCK, // -/-- - [ 0x13 ] = KEY_AUDIO, // audio - [ 0x14 ] = KEY_MUTE, - [ 0x15 ] = KEY_UP, - [ 0x16 ] = KEY_DOWN, - [ 0x17 ] = KEY_LEFT, - [ 0x18 ] = KEY_RIGHT, - [ 0x19 ] = BTN_LEFT, - [ 0x1a ] = BTN_RIGHT, - [ 0x1b ] = KEY_WWW, // text - [ 0x1c ] = KEY_REWIND, - [ 0x1d ] = KEY_FORWARD, - [ 0x1e ] = KEY_RECORD, - [ 0x1f ] = KEY_PLAY, - [ 0x20 ] = KEY_PREVIOUSSONG, - [ 0x21 ] = KEY_NEXTSONG, - [ 0x22 ] = KEY_PAUSE, - [ 0x23 ] = KEY_STOP, -}; - -/* Alfons Geser - * updates from Job D. R. Borges */ -static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { - [ 18 ] = KEY_POWER, - [ 1 ] = KEY_TV, // DVR - [ 21 ] = KEY_DVD, // DVD - [ 23 ] = KEY_AUDIO, // music - // DVR mode / DVD mode / music mode - - [ 27 ] = KEY_MUTE, // mute - [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek - [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek - [ 22 ] = KEY_ZOOM, // full screen - [ 28 ] = KEY_VIDEO, // video source / eject / delall - [ 29 ] = KEY_RESTART, // playback / angle / del - [ 47 ] = KEY_SEARCH, // scan / menu / playlist - [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo - - [ 49 ] = KEY_HELP, // help - [ 50 ] = KEY_MODE, // num/memo - [ 51 ] = KEY_ESC, // cancel - - [ 12 ] = KEY_UP, // up - [ 16 ] = KEY_DOWN, // down - [ 8 ] = KEY_LEFT, // left - [ 4 ] = KEY_RIGHT, // right - [ 3 ] = KEY_SELECT, // select - - [ 31 ] = KEY_REWIND, // rewind - [ 32 ] = KEY_PLAYPAUSE, // play/pause - [ 41 ] = KEY_FORWARD, // forward - [ 20 ] = KEY_AGAIN, // repeat - [ 43 ] = KEY_RECORD, // recording - [ 44 ] = KEY_STOP, // stop - [ 45 ] = KEY_PLAY, // play - [ 46 ] = KEY_SHUFFLE, // snapshot / shuffle - - [ 0 ] = KEY_KP0, - [ 5 ] = KEY_KP1, - [ 6 ] = KEY_KP2, - [ 7 ] = KEY_KP3, - [ 9 ] = KEY_KP4, - [ 10 ] = KEY_KP5, - [ 11 ] = KEY_KP6, - [ 13 ] = KEY_KP7, - [ 14 ] = KEY_KP8, - [ 15 ] = KEY_KP9, - - [ 42 ] = KEY_VOLUMEUP, - [ 17 ] = KEY_VOLUMEDOWN, - [ 24 ] = KEY_CHANNELUP, // CH.tracking up - [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down - - [ 19 ] = KEY_KPENTER, // enter - [ 33 ] = KEY_KPDOT, // . (decimal dot) -}; - -static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = { - [ 30 ] = KEY_POWER, // power - [ 28 ] = KEY_SEARCH, // scan - [ 7 ] = KEY_SELECT, // source - - [ 22 ] = KEY_VOLUMEUP, - [ 20 ] = KEY_VOLUMEDOWN, - [ 31 ] = KEY_CHANNELUP, - [ 23 ] = KEY_CHANNELDOWN, - [ 24 ] = KEY_MUTE, - - [ 2 ] = KEY_KP0, - [ 1 ] = KEY_KP1, - [ 11 ] = KEY_KP2, - [ 27 ] = KEY_KP3, - [ 5 ] = KEY_KP4, - [ 9 ] = KEY_KP5, - [ 21 ] = KEY_KP6, - [ 6 ] = KEY_KP7, - [ 10 ] = KEY_KP8, - [ 18 ] = KEY_KP9, - [ 16 ] = KEY_KPDOT, - - [ 3 ] = KEY_TUNER, // tv/fm - [ 4 ] = KEY_REWIND, // fm tuning left or function left - [ 12 ] = KEY_FORWARD, // fm tuning right or function right - - [ 0 ] = KEY_RECORD, - [ 8 ] = KEY_STOP, - [ 17 ] = KEY_PLAY, - - [ 25 ] = KEY_ZOOM, - [ 14 ] = KEY_MENU, // function - [ 19 ] = KEY_AGAIN, // recall - [ 29 ] = KEY_RESTART, // reset - [ 26 ] = KEY_SHUFFLE, // snapshot/shuffle - -// FIXME - [ 13 ] = KEY_F21, // mts - [ 15 ] = KEY_F22, // min -}; - -/* Alex Hermann */ -static IR_KEYTAB_TYPE md2819_codes[IR_KEYTAB_SIZE] = { - [ 40 ] = KEY_KP1, - [ 24 ] = KEY_KP2, - [ 56 ] = KEY_KP3, - [ 36 ] = KEY_KP4, - [ 20 ] = KEY_KP5, - [ 52 ] = KEY_KP6, - [ 44 ] = KEY_KP7, - [ 28 ] = KEY_KP8, - [ 60 ] = KEY_KP9, - [ 34 ] = KEY_KP0, - - [ 32 ] = KEY_TV, // TV/FM - [ 16 ] = KEY_CD, // CD - [ 48 ] = KEY_TEXT, // TELETEXT - [ 0 ] = KEY_POWER, // POWER - - [ 8 ] = KEY_VIDEO, // VIDEO - [ 4 ] = KEY_AUDIO, // AUDIO - [ 12 ] = KEY_ZOOM, // FULL SCREEN - - [ 18 ] = KEY_SUBTITLE, // DISPLAY - ??? - [ 50 ] = KEY_REWIND, // LOOP - ??? - [ 2 ] = KEY_PRINT, // PREVIEW - ??? - - [ 42 ] = KEY_SEARCH, // AUTOSCAN - [ 26 ] = KEY_SLEEP, // FREEZE - ??? - [ 58 ] = KEY_SHUFFLE, // SNAPSHOT - ??? - [ 10 ] = KEY_MUTE, // MUTE - - [ 38 ] = KEY_RECORD, // RECORD - [ 22 ] = KEY_PAUSE, // PAUSE - [ 54 ] = KEY_STOP, // STOP - [ 6 ] = KEY_PLAY, // PLAY - - [ 46 ] = KEY_RED, // - [ 33 ] = KEY_GREEN, // - [ 14 ] = KEY_YELLOW, // - [ 1 ] = KEY_BLUE, // - - [ 30 ] = KEY_VOLUMEDOWN, // VOLUME- - [ 62 ] = KEY_VOLUMEUP, // VOLUME+ - [ 17 ] = KEY_CHANNELDOWN, // CHANNEL/PAGE- - [ 49 ] = KEY_CHANNELUP // CHANNEL/PAGE+ -}; - -static IR_KEYTAB_TYPE videomate_tv_pvr_codes[IR_KEYTAB_SIZE] = { - [ 20 ] = KEY_MUTE, - [ 36 ] = KEY_ZOOM, - - [ 1 ] = KEY_DVD, - [ 35 ] = KEY_RADIO, - [ 0 ] = KEY_TV, - - [ 10 ] = KEY_REWIND, - [ 8 ] = KEY_PLAYPAUSE, - [ 15 ] = KEY_FORWARD, - - [ 2 ] = KEY_PREVIOUS, - [ 7 ] = KEY_STOP, - [ 6 ] = KEY_NEXT, - - [ 12 ] = KEY_UP, - [ 14 ] = KEY_DOWN, - [ 11 ] = KEY_LEFT, - [ 13 ] = KEY_RIGHT, - [ 17 ] = KEY_OK, - - [ 3 ] = KEY_MENU, - [ 9 ] = KEY_SETUP, - [ 5 ] = KEY_VIDEO, - [ 34 ] = KEY_CHANNEL, - - [ 18 ] = KEY_VOLUMEUP, - [ 21 ] = KEY_VOLUMEDOWN, - [ 16 ] = KEY_CHANNELUP, - [ 19 ] = KEY_CHANNELDOWN, - - [ 4 ] = KEY_RECORD, - - [ 22 ] = KEY_KP1, - [ 23 ] = KEY_KP2, - [ 24 ] = KEY_KP3, - [ 25 ] = KEY_KP4, - [ 26 ] = KEY_KP5, - [ 27 ] = KEY_KP6, - [ 28 ] = KEY_KP7, - [ 29 ] = KEY_KP8, - [ 30 ] = KEY_KP9, - [ 31 ] = KEY_KP0, - - [ 32 ] = KEY_LANGUAGE, - [ 33 ] = KEY_SLEEP, -}; - -/* Michael Tokarev - http://www.corpit.ru/mjt/beholdTV/remote_control.jpg - keytable is used by MANLI MTV00[12] and BeholdTV 40[13] at - least, and probably other cards too. - The "ascii-art picture" below (in comments, first row - is the keycode in hex, and subsequent row(s) shows - the button labels (several variants when appropriate) - helps to descide which keycodes to assign to the buttons. - */ -static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = { - - /* 0x1c 0x12 * - * FUNCTION POWER * - * FM (|) * - * */ - [ 0x1c ] = KEY_RADIO, /*XXX*/ - [ 0x12 ] = KEY_POWER, - - /* 0x01 0x02 0x03 * - * 1 2 3 * - * * - * 0x04 0x05 0x06 * - * 4 5 6 * - * * - * 0x07 0x08 0x09 * - * 7 8 9 * - * */ - [ 0x01 ] = KEY_KP1, - [ 0x02 ] = KEY_KP2, - [ 0x03 ] = KEY_KP3, - [ 0x04 ] = KEY_KP4, - [ 0x05 ] = KEY_KP5, - [ 0x06 ] = KEY_KP6, - [ 0x07 ] = KEY_KP7, - [ 0x08 ] = KEY_KP8, - [ 0x09 ] = KEY_KP9, - - /* 0x0a 0x00 0x17 * - * RECALL 0 +100 * - * PLUS * - * */ - [ 0x0a ] = KEY_AGAIN, /*XXX KEY_REWIND? */ - [ 0x00 ] = KEY_KP0, - [ 0x17 ] = KEY_DIGITS, /*XXX*/ - - /* 0x14 0x10 * - * MENU INFO * - * OSD */ - [ 0x14 ] = KEY_MENU, - [ 0x10 ] = KEY_INFO, - - /* 0x0b * - * Up * - * * - * 0x18 0x16 0x0c * - * Left Ok Right * - * * - * 0x015 * - * Down * - * */ - [ 0x0b ] = KEY_UP, /*XXX KEY_SCROLLUP? */ - [ 0x18 ] = KEY_LEFT, /*XXX KEY_BACK? */ - [ 0x16 ] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ - [ 0x0c ] = KEY_RIGHT, /*XXX KEY_FORWARD? */ - [ 0x15 ] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */ - - /* 0x11 0x0d * - * TV/AV MODE * - * SOURCE STEREO * - * */ - [ 0x11 ] = KEY_TV, /*XXX*/ - [ 0x0d ] = KEY_MODE, /*XXX there's no KEY_STEREO */ - - /* 0x0f 0x1b 0x1a * - * AUDIO Vol+ Chan+ * - * TIMESHIFT??? * - * * - * 0x0e 0x1f 0x1e * - * SLEEP Vol- Chan- * - * */ - [ 0x0f ] = KEY_AUDIO, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1a ] = KEY_CHANNELUP, - [ 0x0e ] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ - [ 0x1f ] = KEY_VOLUMEDOWN, - [ 0x1e ] = KEY_CHANNELDOWN, - - /* 0x13 0x19 * - * MUTE SNAPSHOT* - * */ - [ 0x13 ] = KEY_MUTE, - [ 0x19 ] = KEY_RECORD, /*XXX*/ - - // 0x1d unused ? -}; - - -/* Mike Baikov */ -static IR_KEYTAB_TYPE gotview7135_codes[IR_KEYTAB_SIZE] = { - - [ 33 ] = KEY_POWER, - [ 105] = KEY_TV, - [ 51 ] = KEY_KP0, - [ 81 ] = KEY_KP1, - [ 49 ] = KEY_KP2, - [ 113] = KEY_KP3, - [ 59 ] = KEY_KP4, - [ 88 ] = KEY_KP5, - [ 65 ] = KEY_KP6, - [ 72 ] = KEY_KP7, - [ 48 ] = KEY_KP8, - [ 83 ] = KEY_KP9, - [ 115] = KEY_AGAIN, /* LOOP */ - [ 10 ] = KEY_AUDIO, - [ 97 ] = KEY_PRINT, /* PREVIEW */ - [ 122] = KEY_VIDEO, - [ 32 ] = KEY_CHANNELUP, - [ 64 ] = KEY_CHANNELDOWN, - [ 24 ] = KEY_VOLUMEDOWN, - [ 80 ] = KEY_VOLUMEUP, - [ 16 ] = KEY_MUTE, - [ 74 ] = KEY_SEARCH, - [ 123] = KEY_SHUFFLE, /* SNAPSHOT */ - [ 34 ] = KEY_RECORD, - [ 98 ] = KEY_STOP, - [ 120] = KEY_PLAY, - [ 57 ] = KEY_REWIND, - [ 89 ] = KEY_PAUSE, - [ 25 ] = KEY_FORWARD, - [ 9 ] = KEY_ZOOM, - - [ 82 ] = KEY_F21, /* LIVE TIMESHIFT */ - [ 26 ] = KEY_F22, /* MIN TIMESHIFT */ - [ 58 ] = KEY_F23, /* TIMESHIFT */ - [ 112] = KEY_F24, /* NORMAL TIMESHIFT */ -}; - -static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { - [ 0x3 ] = KEY_POWER, - [ 0x6f ] = KEY_MUTE, - [ 0x10 ] = KEY_BACKSPACE, /* Recall */ - - [ 0x11 ] = KEY_KP0, - [ 0x4 ] = KEY_KP1, - [ 0x5 ] = KEY_KP2, - [ 0x6 ] = KEY_KP3, - [ 0x8 ] = KEY_KP4, - [ 0x9 ] = KEY_KP5, - [ 0xa ] = KEY_KP6, - [ 0xc ] = KEY_KP7, - [ 0xd ] = KEY_KP8, - [ 0xe ] = KEY_KP9, - [ 0x12 ] = KEY_KPDOT, /* 100+ */ - - [ 0x7 ] = KEY_VOLUMEUP, - [ 0xb ] = KEY_VOLUMEDOWN, - [ 0x1a ] = KEY_KPPLUS, - [ 0x18 ] = KEY_KPMINUS, - [ 0x15 ] = KEY_UP, - [ 0x1d ] = KEY_DOWN, - [ 0xf ] = KEY_CHANNELUP, - [ 0x13 ] = KEY_CHANNELDOWN, - [ 0x48 ] = KEY_ZOOM, - - [ 0x1b ] = KEY_VIDEO, /* Video source */ - [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */ - [ 0x19 ] = KEY_SEARCH, /* Auto Scan */ - - [ 0x4b ] = KEY_RECORD, - [ 0x46 ] = KEY_PLAY, - [ 0x45 ] = KEY_PAUSE, /* Pause */ - [ 0x44 ] = KEY_STOP, - [ 0x40 ] = KEY_FORWARD, /* Forward ? */ - [ 0x42 ] = KEY_REWIND, /* Backward ? */ - -}; - -/* Mapping for the 28 key remote control as seen at - http://www.sednacomputer.com/photo/cardbus-tv.jpg - Pavel Mihaylov */ -static IR_KEYTAB_TYPE pctv_sedna_codes[IR_KEYTAB_SIZE] = { - [ 0 ] = KEY_KP0, - [ 1 ] = KEY_KP1, - [ 2 ] = KEY_KP2, - [ 3 ] = KEY_KP3, - [ 4 ] = KEY_KP4, - [ 5 ] = KEY_KP5, - [ 6 ] = KEY_KP6, - [ 7 ] = KEY_KP7, - [ 8 ] = KEY_KP8, - [ 9 ] = KEY_KP9, - - [ 0x0a ] = KEY_AGAIN, /* Recall */ - [ 0x0b ] = KEY_CHANNELUP, - [ 0x0c ] = KEY_VOLUMEUP, - [ 0x0d ] = KEY_MODE, /* Stereo */ - [ 0x0e ] = KEY_STOP, - [ 0x0f ] = KEY_PREVIOUSSONG, - [ 0x10 ] = KEY_ZOOM, - [ 0x11 ] = KEY_TUNER, /* Source */ - [ 0x12 ] = KEY_POWER, - [ 0x13 ] = KEY_MUTE, - [ 0x15 ] = KEY_CHANNELDOWN, - [ 0x18 ] = KEY_VOLUMEDOWN, - [ 0x19 ] = KEY_SHUFFLE, /* Snapshot */ - [ 0x1a ] = KEY_NEXTSONG, - [ 0x1b ] = KEY_TEXT, /* Time Shift */ - [ 0x1c ] = KEY_RADIO, /* FM Radio */ - [ 0x1d ] = KEY_RECORD, - [ 0x1e ] = KEY_PAUSE, -}; - - /* -------------------- GPIO generic keycode builder -------------------- */ static int build_key(struct saa7134_dev *dev) @@ -628,27 +149,27 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_FLYVIDEO3000: case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_FLYTVPLATINUM_MINI2: - ir_codes = flyvideo_codes; + ir_codes = ir_codes_flyvideo; mask_keycode = 0xEC00000; mask_keydown = 0x0040000; break; case SAA7134_BOARD_CINERGY400: case SAA7134_BOARD_CINERGY600: case SAA7134_BOARD_CINERGY600_MK3: - ir_codes = cinergy_codes; + ir_codes = ir_codes_cinergy; mask_keycode = 0x00003f; mask_keyup = 0x040000; break; case SAA7134_BOARD_ECS_TVP3XP: case SAA7134_BOARD_ECS_TVP3XP_4CB5: - ir_codes = eztv_codes; + ir_codes = ir_codes_eztv; mask_keycode = 0x00017c; mask_keyup = 0x000002; polling = 50; // ms break; case SAA7134_BOARD_KWORLD_XPERT: case SAA7134_BOARD_AVACSSMARTTV: - ir_codes = avacssmart_codes; + ir_codes = ir_codes_avacssmart; mask_keycode = 0x00001F; mask_keyup = 0x000020; polling = 50; // ms @@ -660,7 +181,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_STUDIO_305: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: - ir_codes = md2819_codes; + ir_codes = ir_codes_md2819; mask_keycode = 0x0007C8; mask_keydown = 0x000010; polling = 50; // ms @@ -669,7 +190,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; case SAA7134_BOARD_KWORLD_TERMINATOR: - ir_codes = avacssmart_codes; + ir_codes = ir_codes_avacssmart; mask_keycode = 0x00001f; mask_keyup = 0x000060; polling = 50; // ms @@ -677,19 +198,19 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: - ir_codes = manli_codes; + ir_codes = ir_codes_manli; mask_keycode = 0x001f00; mask_keyup = 0x004000; polling = 50; // ms break; case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: - ir_codes = pctv_sedna_codes; + ir_codes = ir_codes_pctv_sedna; mask_keycode = 0x001f00; mask_keyup = 0x004000; polling = 50; // ms break; case SAA7134_BOARD_GOTVIEW_7135: - ir_codes = gotview7135_codes; + ir_codes = ir_codes_gotview7135; mask_keycode = 0x0003EC; mask_keyup = 0x008000; mask_keydown = 0x000010; @@ -698,14 +219,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: - ir_codes = videomate_tv_pvr_codes; + ir_codes = ir_codes_videomate_tv_pvr; mask_keycode = 0x00003F; mask_keyup = 0x400000; polling = 50; // ms break; case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: - ir_codes = videomate_tv_pvr_codes; + ir_codes = ir_codes_videomate_tv_pvr; mask_keycode = 0x003F00; mask_keyup = 0x040000; break; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index ad3e9bb670c3..50fe522bad33 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -47,13 +47,6 @@ struct ir_input_state { int keypressed; /* current state */ }; -extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; - void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, int ir_type, IR_KEYTAB_TYPE *ir_codes); void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir); @@ -64,6 +57,41 @@ int ir_dump_samples(u32 *samples, int count); int ir_decode_biphase(u32 *samples, int count, int low, int high); int ir_decode_pulsedistance(u32 *samples, int count, int low, int high); +/* Keymaps to be used by other modules */ + +extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avacssmart[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_md2819[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; + #endif /* -- cgit v1.2.3-59-g8ed1b From b639f9d286f2216795492eac2a39b8ed6b4d555c Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Mon, 23 Jan 2006 09:44:10 -0200 Subject: V4L/DVB (3400): Remove duplicated keymaps and add keymap for KWorld LTV883IR. - Remove duplicated keymaps and add keymap for KWorld LTV883IR. Thanks to Jon Ferguson . Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 194 ++++++---------------------- drivers/media/video/bttv-input.c | 2 +- drivers/media/video/cx88/cx88-input.c | 7 + drivers/media/video/saa7134/saa7134-input.c | 6 +- include/media/ir-common.h | 6 +- 5 files changed, 49 insertions(+), 166 deletions(-) (limited to 'drivers') diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 468f66013393..a294d5c2c73f 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -32,50 +32,6 @@ IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_empty); -IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { - [ 0x22 ] = KEY_0, - [ 0x28 ] = KEY_1, - [ 0x18 ] = KEY_2, - [ 0x38 ] = KEY_3, - [ 0x24 ] = KEY_4, - [ 0x14 ] = KEY_5, - [ 0x34 ] = KEY_6, - [ 0x2c ] = KEY_7, - [ 0x1c ] = KEY_8, - [ 0x3c ] = KEY_9, - - [ 0x30 ] = KEY_EJECTCD, // Unmarked on my controller - [ 0x00 ] = KEY_POWER, - [ 0x12 ] = BTN_LEFT, // DISPLAY/L - [ 0x32 ] = BTN_RIGHT, // LOOP/R - [ 0x0a ] = KEY_MUTE, - [ 0x26 ] = KEY_RECORD, - [ 0x16 ] = KEY_PAUSE, - [ 0x36 ] = KEY_STOP, - [ 0x1e ] = KEY_VOLUMEDOWN, - [ 0x3e ] = KEY_VOLUMEUP, - - [ 0x20 ] = KEY_TUNER, // TV/FM - [ 0x10 ] = KEY_CD, - [ 0x08 ] = KEY_VIDEO, - [ 0x04 ] = KEY_AUDIO, - [ 0x0c ] = KEY_ZOOM, // full screen - [ 0x02 ] = KEY_INFO, // preview - [ 0x2a ] = KEY_SEARCH, // autoscan - [ 0x1a ] = KEY_STOP, // freeze - [ 0x3a ] = KEY_RECORD, // capture - [ 0x06 ] = KEY_PLAY, // unmarked - [ 0x2e ] = KEY_RED, // unmarked - [ 0x0e ] = KEY_GREEN, // unmarked - - [ 0x21 ] = KEY_YELLOW, // unmarked - [ 0x11 ] = KEY_CHANNELDOWN, - [ 0x31 ] = KEY_CHANNELUP, - [ 0x01 ] = KEY_BLUE, // unmarked -}; - -EXPORT_SYMBOL_GPL(ir_codes_avermedia); - /* Matt Jesson */ -IR_KEYTAB_TYPE ir_codes_md2819[IR_KEYTAB_SIZE] = { +IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [ 0x28 ] = KEY_1, [ 0x18 ] = KEY_2, [ 0x38 ] = KEY_3, @@ -945,41 +857,41 @@ IR_KEYTAB_TYPE ir_codes_md2819[IR_KEYTAB_SIZE] = { [ 0x3c ] = KEY_9, [ 0x22 ] = KEY_0, - [ 0x20 ] = KEY_TV, // TV/FM - [ 0x10 ] = KEY_CD, // CD - [ 0x30 ] = KEY_TEXT, // TELETEXT - [ 0x00 ] = KEY_POWER, // POWER - - [ 0x08 ] = KEY_VIDEO, // VIDEO - [ 0x04 ] = KEY_AUDIO, // AUDIO - [ 0x0c ] = KEY_ZOOM, // FULL SCREEN - - [ 0x12 ] = KEY_SUBTITLE, // DISPLAY - ??? - [ 0x32 ] = KEY_REWIND, // LOOP - ??? - [ 0x02 ] = KEY_PRINT, // PREVIEW - ??? - - [ 0x2a ] = KEY_SEARCH, // AUTOSCAN - [ 0x1a ] = KEY_SLEEP, // FREEZE - ??? - [ 0x3a ] = KEY_SHUFFLE, // SNAPSHOT - ??? - [ 0x0a ] = KEY_MUTE, // MUTE - - [ 0x26 ] = KEY_RECORD, // RECORD - [ 0x16 ] = KEY_PAUSE, // PAUSE - [ 0x36 ] = KEY_STOP, // STOP - [ 0x06 ] = KEY_PLAY, // PLAY - - [ 0x2e ] = KEY_RED, // - [ 0x21 ] = KEY_GREEN, // - [ 0x0e ] = KEY_YELLOW, // - [ 0x01 ] = KEY_BLUE, // - - [ 0x1e ] = KEY_VOLUMEDOWN, // VOLUME- - [ 0x3e ] = KEY_VOLUMEUP, // VOLUME+ - [ 0x11 ] = KEY_CHANNELDOWN, // CHANNEL/PAGE- - [ 0x31 ] = KEY_CHANNELUP // CHANNEL/PAGE+ + [ 0x20 ] = KEY_TV, /* TV/FM */ + [ 0x10 ] = KEY_CD, /* CD */ + [ 0x30 ] = KEY_TEXT, /* TELETEXT */ + [ 0x00 ] = KEY_POWER, /* POWER */ + + [ 0x08 ] = KEY_VIDEO, /* VIDEO */ + [ 0x04 ] = KEY_AUDIO, /* AUDIO */ + [ 0x0c ] = KEY_ZOOM, /* FULL SCREEN */ + + [ 0x12 ] = KEY_SUBTITLE, /* DISPLAY */ + [ 0x32 ] = KEY_REWIND, /* LOOP */ + [ 0x02 ] = KEY_PRINT, /* PREVIEW */ + + [ 0x2a ] = KEY_SEARCH, /* AUTOSCAN */ + [ 0x1a ] = KEY_SLEEP, /* FREEZE */ + [ 0x3a ] = KEY_SHUFFLE, /* SNAPSHOT */ + [ 0x0a ] = KEY_MUTE, /* MUTE */ + + [ 0x26 ] = KEY_RECORD, /* RECORD */ + [ 0x16 ] = KEY_PAUSE, /* PAUSE */ + [ 0x36 ] = KEY_STOP, /* STOP */ + [ 0x06 ] = KEY_PLAY, /* PLAY */ + + [ 0x2e ] = KEY_RED, /* RED */ + [ 0x21 ] = KEY_GREEN, /* GREEN */ + [ 0x0e ] = KEY_YELLOW, /* YELLOW */ + [ 0x01 ] = KEY_BLUE, /* BLUE */ + + [ 0x1e ] = KEY_VOLUMEDOWN, /* VOLUME- */ + [ 0x3e ] = KEY_VOLUMEUP, /* VOLUME+ */ + [ 0x11 ] = KEY_CHANNELDOWN, /* CHANNEL/PAGE- */ + [ 0x31 ] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ }; -EXPORT_SYMBOL_GPL(ir_codes_md2819); +EXPORT_SYMBOL_GPL(ir_codes_avermedia); IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE] = { [ 0x14 ] = KEY_MUTE, @@ -1501,37 +1413,3 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); -IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { - [ 0x02 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x0b ] = KEY_2, - [ 0x1b ] = KEY_3, - [ 0x05 ] = KEY_4, - [ 0x09 ] = KEY_5, - [ 0x15 ] = KEY_6, - [ 0x06 ] = KEY_7, - [ 0x0a ] = KEY_8, - [ 0x12 ] = KEY_9, - - [ 0x03 ] = KEY_TUNER, /* TV/FM */ - [ 0x07 ] = KEY_SEARCH, /* scan */ - [ 0x1c ] = KEY_ZOOM, /* full screen */ - [ 0x1e ] = KEY_POWER, - [ 0x17 ] = KEY_VOLUMEDOWN, - [ 0x1f ] = KEY_VOLUMEUP, - [ 0x14 ] = KEY_CHANNELDOWN, - [ 0x16 ] = KEY_CHANNELUP, - [ 0x18 ] = KEY_MUTE, - - [ 0x00 ] = KEY_LIST, /* source */ - [ 0x13 ] = KEY_INFO, /* loop */ - [ 0x10 ] = KEY_LAST, /* +100 */ - [ 0x0d ] = KEY_CLEAR, /* reset */ - [ 0x0c ] = BTN_RIGHT, /* fun++ */ - [ 0x04 ] = BTN_LEFT, /* fun-- */ - [ 0x0e ] = KEY_GOTO, /* function */ - [ 0x0f ] = KEY_STOP, /* freeze */ -}; - -EXPORT_SYMBOL_GPL(ir_codes_pixelview); - diff --git a/drivers/media/video/bttv-input.c b/drivers/media/video/bttv-input.c index 42760ae867d6..c637677acefd 100644 --- a/drivers/media/video/bttv-input.c +++ b/drivers/media/video/bttv-input.c @@ -328,7 +328,7 @@ int bttv_input_init(struct bttv *btv) ir->polling = 50; // ms break; case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: - ir_codes = ir_codes_conceptronic; + ir_codes = ir_codes_pixelview; ir->mask_keycode = 0x001F00; ir->mask_keyup = 0x006000; ir->polling = 50; // ms diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index a4fa92c1b0c7..800e2b31ac7b 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -192,6 +192,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->mask_keyup = 0x80; ir->polling = 1; /* ms */ break; + case CX88_BOARD_KWORLD_LTV883: + ir_codes = ir_codes_pixelview; + ir->gpio_addr = MO_GP1_IO; + ir->mask_keycode = 0x1f; + ir->mask_keyup = 0x60; + ir->polling = 1; /* ms */ + break; case CX88_BOARD_ADSTECH_DVB_T_PCI: ir_codes = ir_codes_adstech_dvb_t_pci; ir->gpio_addr = MO_GP1_IO; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 342568cf728f..ecfb6e2b3bd3 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -169,7 +169,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_KWORLD_XPERT: case SAA7134_BOARD_AVACSSMARTTV: - ir_codes = ir_codes_avacssmart; + ir_codes = ir_codes_pixelview; mask_keycode = 0x00001F; mask_keyup = 0x000020; polling = 50; // ms @@ -181,7 +181,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_STUDIO_305: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: - ir_codes = ir_codes_md2819; + ir_codes = ir_codes_avermedia; mask_keycode = 0x0007C8; mask_keydown = 0x000010; polling = 50; // ms @@ -190,7 +190,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; case SAA7134_BOARD_KWORLD_TERMINATOR: - ir_codes = ir_codes_avacssmart; + ir_codes = ir_codes_pixelview; mask_keycode = 0x00001f; mask_keyup = 0x000060; polling = 50; // ms diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 50fe522bad33..302d5b3946e7 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -63,7 +63,7 @@ extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE]; @@ -78,8 +78,7 @@ extern IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_avacssmart[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_md2819[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE]; @@ -90,7 +89,6 @@ extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; #endif -- cgit v1.2.3-59-g8ed1b From 53a7240416adabb84e32334a9f118b7f05392ba2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 23 Jan 2006 09:46:02 -0200 Subject: V4L/DVB (3402): Fix handling of VIDIOC_G_TUNER audmode in msp3400 - Fix handling of VIDIOC_G_TUNER audmode in msp3400: audmode is only changed by the user with S_TUNER, never by the driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-driver.c | 21 +++++---------------- drivers/media/video/msp3400-kthreads.c | 25 +++++++++++-------------- 2 files changed, 16 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 69ed369c2f48..994c340f9d02 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -653,7 +653,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) } if (scart) { state->rxsubchans = V4L2_TUNER_SUB_STEREO; - state->audmode = V4L2_TUNER_MODE_STEREO; msp_set_scart(client, scart, 0); msp_write_dsp(client, 0x000d, 0x1900); if (state->opmode != OPMODE_AUTOSELECT) @@ -831,11 +830,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return -EINVAL; } - msp_any_detect_stereo(client); - if (state->audmode == V4L2_TUNER_MODE_STEREO) { - a->capability = V4L2_AUDCAP_STEREO; - } - + a->capability = V4L2_AUDCAP_STEREO; + a->mode = 0; /* TODO: add support for AVL */ break; } @@ -865,15 +861,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) } if (scart) { state->rxsubchans = V4L2_TUNER_SUB_STEREO; - state->audmode = V4L2_TUNER_MODE_STEREO; msp_set_scart(client, scart, 0); msp_write_dsp(client, 0x000d, 0x1900); } - if (sarg->capability == V4L2_AUDCAP_STEREO) { - state->audmode = V4L2_TUNER_MODE_STEREO; - } else { - state->audmode &= ~V4L2_TUNER_MODE_STEREO; - } msp_any_set_audmode(client, state->audmode); msp_wake_thread(client); break; @@ -898,11 +888,10 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; - if (state->radio) + if (state->radio) /* TODO: add mono/stereo support for radio */ break; /* only set audmode */ - if (vt->audmode != -1 && vt->audmode != 0) - msp_any_set_audmode(client, vt->audmode); + msp_any_set_audmode(client, vt->audmode); break; } @@ -927,7 +916,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return -EINVAL; } break; - } case VIDIOC_S_AUDOUT: @@ -1094,6 +1082,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) memset(state, 0, sizeof(*state)); state->v4l2_std = V4L2_STD_NTSC; + state->audmode = V4L2_TUNER_MODE_STEREO; state->volume = 58880; /* 0db gain */ state->balance = 32768; /* 0db gain */ state->bass = 32768; diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 2072c3efebb3..3235a15db59f 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -170,7 +170,6 @@ void msp3400c_setmode(struct i2c_client *client, int type) v4l_dbg(1, msp_debug, client, "setmode: %d\n", type); state->mode = type; - state->audmode = V4L2_TUNER_MODE_MONO; state->rxsubchans = V4L2_TUNER_SUB_MONO; msp_write_dem(client, 0x00bb, msp3400c_init_data[type].ad_cv); @@ -210,7 +209,7 @@ void msp3400c_setmode(struct i2c_client *client, int type) } /* turn on/off nicam + stereo */ -void msp3400c_setstereo(struct i2c_client *client, int mode) +void msp3400c_setstereo(struct i2c_client *client, int audmode) { static char *strmode[] = { "mono", "stereo", "lang2", "lang1" }; struct msp_state *state = i2c_get_clientdata(client); @@ -222,16 +221,16 @@ void msp3400c_setstereo(struct i2c_client *client, int mode) * it's never called */ v4l_dbg(1, msp_debug, client, "setstereo called with mode=%d instead of set_source (ignored)\n", - mode); + audmode); return; } /* switch demodulator */ switch (state->mode) { case MSP_MODE_FM_TERRA: - v4l_dbg(1, msp_debug, client, "FM setstereo: %s\n", strmode[mode]); + v4l_dbg(1, msp_debug, client, "FM setstereo: %s\n", strmode[audmode]); msp3400c_setcarrier(client, state->second, state->main); - switch (mode) { + switch (audmode) { case V4L2_TUNER_MODE_STEREO: msp_write_dsp(client, 0x000e, 0x3001); break; @@ -243,8 +242,8 @@ void msp3400c_setstereo(struct i2c_client *client, int mode) } break; case MSP_MODE_FM_SAT: - v4l_dbg(1, msp_debug, client, "SAT setstereo: %s\n", strmode[mode]); - switch (mode) { + v4l_dbg(1, msp_debug, client, "SAT setstereo: %s\n", strmode[audmode]); + switch (audmode) { case V4L2_TUNER_MODE_MONO: msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); break; @@ -262,21 +261,21 @@ void msp3400c_setstereo(struct i2c_client *client, int mode) case MSP_MODE_FM_NICAM1: case MSP_MODE_FM_NICAM2: case MSP_MODE_AM_NICAM: - v4l_dbg(1, msp_debug, client, "NICAM setstereo: %s\n",strmode[mode]); + v4l_dbg(1, msp_debug, client, "NICAM setstereo: %s\n",strmode[audmode]); msp3400c_setcarrier(client,state->second,state->main); if (state->nicam_on) nicam=0x0100; break; case MSP_MODE_BTSC: - v4l_dbg(1, msp_debug, client, "BTSC setstereo: %s\n",strmode[mode]); + v4l_dbg(1, msp_debug, client, "BTSC setstereo: %s\n",strmode[audmode]); nicam=0x0300; break; case MSP_MODE_EXTERN: - v4l_dbg(1, msp_debug, client, "extern setstereo: %s\n",strmode[mode]); + v4l_dbg(1, msp_debug, client, "extern setstereo: %s\n",strmode[audmode]); nicam = 0x0200; break; case MSP_MODE_FM_RADIO: - v4l_dbg(1, msp_debug, client, "FM-Radio setstereo: %s\n",strmode[mode]); + v4l_dbg(1, msp_debug, client, "FM-Radio setstereo: %s\n",strmode[audmode]); break; default: v4l_dbg(1, msp_debug, client, "mono setstereo\n"); @@ -284,7 +283,7 @@ void msp3400c_setstereo(struct i2c_client *client, int mode) } /* switch audio */ - switch (mode) { + switch (audmode) { case V4L2_TUNER_MODE_STEREO: src = 0x0020 | nicam; break; @@ -759,7 +758,6 @@ int msp3410d_thread(void *data) case 0x0040: /* FM radio */ state->mode = MSP_MODE_FM_RADIO; state->rxsubchans = V4L2_TUNER_SUB_STEREO; - state->audmode = V4L2_TUNER_MODE_STEREO; state->nicam_on = 0; state->watch_stereo = 0; /* not needed in theory if we have radio, but @@ -779,7 +777,6 @@ int msp3410d_thread(void *data) case 0x0005: state->mode = MSP_MODE_FM_TERRA; state->rxsubchans = V4L2_TUNER_SUB_MONO; - state->audmode = V4L2_TUNER_MODE_MONO; state->nicam_on = 0; state->watch_stereo = 1; break; -- cgit v1.2.3-59-g8ed1b From 94f9e56e2b32e9d0efa1321afc3fa164563b2c55 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 23 Jan 2006 09:47:40 -0200 Subject: V4L/DVB (3403): Add probe check for the tda9840. - Add probe check for the tda9840 to prevent misdetection of a Micronas dpl3518a as a tda9840. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 6d03b9b05c6e..c8e5ad0e8185 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -390,6 +390,14 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) chip_write(chip, TDA9840_SW, t); } +static int tda9840_checkit(struct CHIPSTATE *chip) +{ + int rc; + rc = chip_read(chip); + /* lower 5 bits should be 0 */ + return ((rc & 0x1f) == 0) ? 1 : 0; +} + /* ---------------------------------------------------------------------- */ /* audio chip descriptions - defines+functions for tda985x */ @@ -1264,6 +1272,7 @@ static struct CHIPDESC chiplist[] = { .addr_hi = I2C_TDA9840 >> 1, .registers = 5, + .checkit = tda9840_checkit, .getmode = tda9840_getmode, .setmode = tda9840_setmode, .checkmode = generic_checkmode, -- cgit v1.2.3-59-g8ed1b From 337208d007d94749cc965742eede1611a94c06ce Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 23 Jan 2006 09:48:02 -0200 Subject: VIDEO_CX88_ALSA must select SND_PCM - VIDEO_CX88_ALSA must select SND_PCM Signed-off-by: Adrian Bunk Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 53308911ae6e..fdf45f7d05a0 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -32,6 +32,7 @@ config VIDEO_CX88_DVB config VIDEO_CX88_ALSA tristate "ALSA DMA audio support" depends on VIDEO_CX88 && SND && EXPERIMENTAL + select SND_PCM ---help--- This is a video4linux driver for direct (DMA) audio on Conexant 2388x based TV cards. -- cgit v1.2.3-59-g8ed1b From e36eaa71c99eb1edb52eb21ab4e8c9e09b943f21 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 09:48:34 -0200 Subject: V4L/DVB (3405): Fixes tvp5150a/am1 detection. - Tvp5150 type were determined by a secondary register instead of using ROM code. - tvp5150am1 have ROM=4.0, while tvp5150a have ROM=3.33 (decimal). All other ROM versions are reported as unknown tvp5150. - Except for reporting, current code doesn't enable any special feature for tvp5150am1 or tvp5150a. Code should work for both models (but were tested only for tvp5150am1). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp5150.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index fad9ea0ae4f2..a6330a351eaa 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -746,24 +746,27 @@ static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std) static inline void tvp5150_reset(struct i2c_client *c) { - u8 type, ver_656, msb_id, lsb_id, msb_rom, lsb_rom; + u8 msb_id, lsb_id, msb_rom, lsb_rom; struct tvp5150 *decoder = i2c_get_clientdata(c); - type=tvp5150_read(c,TVP5150_AUTOSW_MSK); msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID); lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID); msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER); lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER); - if (type==0xdc) { - ver_656=tvp5150_read(c,TVP5150_REV_SELECT); - tvp5150_info("tvp%02x%02xam1 detected 656 version is %d.\n",msb_id, lsb_id,ver_656); - } else if (type==0xfc) { - tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id); + if ((msb_rom==4)&&(lsb_rom==0)) { /* Is TVP5150AM1 */ + tvp5150_info("tvp%02x%02xam1 detected.\n",msb_id, lsb_id); + + /* ITU-T BT.656.4 timing */ + tvp5150_write(c,TVP5150_REV_SELECT,0); } else { - tvp5150_info("unknown tvp%02x%02x chip detected(%d).\n",msb_id,lsb_id,type); + if ((msb_rom==3)||(lsb_rom==0x21)) { /* Is TVP5150A */ + tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id); + } else { + tvp5150_info("*** unknown tvp%02x%02x chip detected.\n",msb_id,lsb_id); + tvp5150_info("*** Rom ver is %d.%d\n",msb_rom,lsb_rom); + } } - tvp5150_info("Rom ver is %d.%d\n",msb_rom,lsb_rom); /* Initializes TVP5150 to its default values */ tvp5150_write_inittab(c, tvp5150_init_default); -- cgit v1.2.3-59-g8ed1b From 439090d7d82a333a21987dcbccb90961f27fd2e9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:10:54 -0200 Subject: V4L/DVB (3406): Added credits for em28xx-video.c - Added credits for sn9c102 kernel module and his author as some parts of em28xx-video were based. Acked-by: Luca Risolia Acked-by: Markus Rechberger Acked-by: Ludovico Cavedon Acked-by: Sascha Sommer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index eea304f75176..94a14a2bb6d6 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -6,6 +6,9 @@ Mauro Carvalho Chehab Sascha Sommer + Some parts based on SN9C10x PC Camera Controllers GPL driver made + by Luca Risolia + 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 -- cgit v1.2.3-59-g8ed1b From 3ad96835cedec7704b1b5a211b39262bb794adaf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:11:05 -0200 Subject: V4L/DVB (3407): added some code for VBI processing and cleanup debug dump - Renamed some registers and improved register debug message - Some cleanups at register dump - Added code to set VBI processor (VDP) - VBI code still incomplete Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp5150.c | 493 ++++++++++++++++---------------------- drivers/media/video/tvp5150_reg.h | 118 +++------ 2 files changed, 238 insertions(+), 373 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index a6330a351eaa..f7fa93c64d11 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -29,6 +29,9 @@ static int debug = 0; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +#define tvp5150_err(fmt, arg...) do { \ + printk(KERN_ERR "%s %d-%04x: " fmt, c->driver->driver.name, \ + i2c_adapter_id(c->adapter), c->addr , ## arg); } while (0) #define tvp5150_info(fmt, arg...) do { \ printk(KERN_INFO "%s %d-%04x: " fmt, c->driver->driver.name, \ i2c_adapter_id(c->adapter), c->addr , ## arg); } while (0) @@ -84,7 +87,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = { struct tvp5150 { struct i2c_client *client; - int norm; + v4l2_std_id norm; /* Current set standard */ int input; int enable; int bright; @@ -125,310 +128,155 @@ static inline void tvp5150_write(struct i2c_client *c, unsigned char addr, tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 2)\n", rc); } +static void dump_reg_range(struct i2c_client *c, char *s, u8 init, const u8 end,int max_line) +{ + int i=0; + + while (init!=(u8)(end+1)) { + if ((i%max_line) == 0) { + if (i>0) + printk("\n"); + printk("tvp5150: %s reg 0x%02x = ",s,init); + } + printk("%02x ",tvp5150_read(c, init)); + + init++; + i++; + } + printk("\n"); +} + static void dump_reg(struct i2c_client *c) { printk("tvp5150: Video input source selection #1 = 0x%02x\n", - tvp5150_read(c, TVP5150_VD_IN_SRC_SEL_1)); + tvp5150_read(c, TVP5150_VD_IN_SRC_SEL_1)); printk("tvp5150: Analog channel controls = 0x%02x\n", - tvp5150_read(c, TVP5150_ANAL_CHL_CTL)); + tvp5150_read(c, TVP5150_ANAL_CHL_CTL)); printk("tvp5150: Operation mode controls = 0x%02x\n", - tvp5150_read(c, TVP5150_OP_MODE_CTL)); + tvp5150_read(c, TVP5150_OP_MODE_CTL)); printk("tvp5150: Miscellaneous controls = 0x%02x\n", - tvp5150_read(c, TVP5150_MISC_CTL)); - printk("tvp5150: Autoswitch mask: TVP5150A / TVP5150AM = 0x%02x\n", - tvp5150_read(c, TVP5150_AUTOSW_MSK)); + tvp5150_read(c, TVP5150_MISC_CTL)); + printk("tvp5150: Autoswitch mask= 0x%02x\n", + tvp5150_read(c, TVP5150_AUTOSW_MSK)); printk("tvp5150: Color killer threshold control = 0x%02x\n", - tvp5150_read(c, TVP5150_COLOR_KIL_THSH_CTL)); - printk("tvp5150: Luminance processing control #1 = 0x%02x\n", - tvp5150_read(c, TVP5150_LUMA_PROC_CTL_1)); - printk("tvp5150: Luminance processing control #2 = 0x%02x\n", - tvp5150_read(c, TVP5150_LUMA_PROC_CTL_2)); + tvp5150_read(c, TVP5150_COLOR_KIL_THSH_CTL)); + printk("tvp5150: Luminance processing controls #1 #2 and #3 = %02x %02x %02x\n", + tvp5150_read(c, TVP5150_LUMA_PROC_CTL_1), + tvp5150_read(c, TVP5150_LUMA_PROC_CTL_2), + tvp5150_read(c, TVP5150_LUMA_PROC_CTL_3)); printk("tvp5150: Brightness control = 0x%02x\n", - tvp5150_read(c, TVP5150_BRIGHT_CTL)); + tvp5150_read(c, TVP5150_BRIGHT_CTL)); printk("tvp5150: Color saturation control = 0x%02x\n", - tvp5150_read(c, TVP5150_SATURATION_CTL)); + tvp5150_read(c, TVP5150_SATURATION_CTL)); printk("tvp5150: Hue control = 0x%02x\n", - tvp5150_read(c, TVP5150_HUE_CTL)); + tvp5150_read(c, TVP5150_HUE_CTL)); printk("tvp5150: Contrast control = 0x%02x\n", - tvp5150_read(c, TVP5150_CONTRAST_CTL)); + tvp5150_read(c, TVP5150_CONTRAST_CTL)); printk("tvp5150: Outputs and data rates select = 0x%02x\n", - tvp5150_read(c, TVP5150_DATA_RATE_SEL)); - printk("tvp5150: Luminance processing control #3 = 0x%02x\n", - tvp5150_read(c, TVP5150_LUMA_PROC_CTL_3)); + tvp5150_read(c, TVP5150_DATA_RATE_SEL)); printk("tvp5150: Configuration shared pins = 0x%02x\n", - tvp5150_read(c, TVP5150_CONF_SHARED_PIN)); - printk("tvp5150: Active video cropping start MSB = 0x%02x\n", - tvp5150_read(c, TVP5150_ACT_VD_CROP_ST_MSB)); - printk("tvp5150: Active video cropping start LSB = 0x%02x\n", - tvp5150_read(c, TVP5150_ACT_VD_CROP_ST_LSB)); - printk("tvp5150: Active video cropping stop MSB = 0x%02x\n", - tvp5150_read(c, TVP5150_ACT_VD_CROP_STP_MSB)); - printk("tvp5150: Active video cropping stop LSB = 0x%02x\n", - tvp5150_read(c, TVP5150_ACT_VD_CROP_STP_LSB)); + tvp5150_read(c, TVP5150_CONF_SHARED_PIN)); + printk("tvp5150: Active video cropping start = 0x%02x%02x\n", + tvp5150_read(c, TVP5150_ACT_VD_CROP_ST_MSB), + tvp5150_read(c, TVP5150_ACT_VD_CROP_ST_LSB)); + printk("tvp5150: Active video cropping stop = 0x%02x%02x\n", + tvp5150_read(c, TVP5150_ACT_VD_CROP_STP_MSB), + tvp5150_read(c, TVP5150_ACT_VD_CROP_STP_LSB)); printk("tvp5150: Genlock/RTC = 0x%02x\n", - tvp5150_read(c, TVP5150_GENLOCK)); + tvp5150_read(c, TVP5150_GENLOCK)); printk("tvp5150: Horizontal sync start = 0x%02x\n", - tvp5150_read(c, TVP5150_HORIZ_SYNC_START)); + tvp5150_read(c, TVP5150_HORIZ_SYNC_START)); printk("tvp5150: Vertical blanking start = 0x%02x\n", - tvp5150_read(c, TVP5150_VERT_BLANKING_START)); + tvp5150_read(c, TVP5150_VERT_BLANKING_START)); printk("tvp5150: Vertical blanking stop = 0x%02x\n", - tvp5150_read(c, TVP5150_VERT_BLANKING_STOP)); - printk("tvp5150: Chrominance processing control #1 = 0x%02x\n", - tvp5150_read(c, TVP5150_CHROMA_PROC_CTL_1)); - printk("tvp5150: Chrominance processing control #2 = 0x%02x\n", - tvp5150_read(c, TVP5150_CHROMA_PROC_CTL_2)); + tvp5150_read(c, TVP5150_VERT_BLANKING_STOP)); + printk("tvp5150: Chrominance processing control #1 and #2 = %02x %02x\n", + tvp5150_read(c, TVP5150_CHROMA_PROC_CTL_1), + tvp5150_read(c, TVP5150_CHROMA_PROC_CTL_2)); printk("tvp5150: Interrupt reset register B = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_RESET_REG_B)); + tvp5150_read(c, TVP5150_INT_RESET_REG_B)); printk("tvp5150: Interrupt enable register B = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_ENABLE_REG_B)); + tvp5150_read(c, TVP5150_INT_ENABLE_REG_B)); printk("tvp5150: Interrupt configuration register B = 0x%02x\n", - tvp5150_read(c, TVP5150_INTT_CONFIG_REG_B)); + tvp5150_read(c, TVP5150_INTT_CONFIG_REG_B)); printk("tvp5150: Video standard = 0x%02x\n", - tvp5150_read(c, TVP5150_VIDEO_STD)); - printk("tvp5150: Cb gain factor = 0x%02x\n", - tvp5150_read(c, TVP5150_CB_GAIN_FACT)); - printk("tvp5150: Cr gain factor = 0x%02x\n", - tvp5150_read(c, TVP5150_CR_GAIN_FACTOR)); + tvp5150_read(c, TVP5150_VIDEO_STD)); + printk("tvp5150: Chroma gain factor: Cb=0x%02x Cr=0x%02x\n", + tvp5150_read(c, TVP5150_CB_GAIN_FACT), + tvp5150_read(c, TVP5150_CR_GAIN_FACTOR)); printk("tvp5150: Macrovision on counter = 0x%02x\n", - tvp5150_read(c, TVP5150_MACROVISION_ON_CTR)); + tvp5150_read(c, TVP5150_MACROVISION_ON_CTR)); printk("tvp5150: Macrovision off counter = 0x%02x\n", - tvp5150_read(c, TVP5150_MACROVISION_OFF_CTR)); - printk("tvp5150: revision select (TVP5150AM1 only) = 0x%02x\n", - tvp5150_read(c, TVP5150_REV_SELECT)); - printk("tvp5150: MSB of device ID = 0x%02x\n", - tvp5150_read(c, TVP5150_MSB_DEV_ID)); - printk("tvp5150: LSB of device ID = 0x%02x\n", - tvp5150_read(c, TVP5150_LSB_DEV_ID)); - printk("tvp5150: ROM major version = 0x%02x\n", - tvp5150_read(c, TVP5150_ROM_MAJOR_VER)); - printk("tvp5150: ROM minor version = 0x%02x\n", - tvp5150_read(c, TVP5150_ROM_MINOR_VER)); - printk("tvp5150: Vertical line count MSB = 0x%02x\n", - tvp5150_read(c, TVP5150_VERT_LN_COUNT_MSB)); - printk("tvp5150: Vertical line count LSB = 0x%02x\n", - tvp5150_read(c, TVP5150_VERT_LN_COUNT_LSB)); + tvp5150_read(c, TVP5150_MACROVISION_OFF_CTR)); + printk("tvp5150: ITU-R BT.656.%d timing(TVP5150AM1 only)\n", + (tvp5150_read(c, TVP5150_REV_SELECT)&1)?3:4); + printk("tvp5150: Device ID = %02x%02x\n", + tvp5150_read(c, TVP5150_MSB_DEV_ID), + tvp5150_read(c, TVP5150_LSB_DEV_ID)); + printk("tvp5150: ROM version = (hex) %02x.%02x\n", + tvp5150_read(c, TVP5150_ROM_MAJOR_VER), + tvp5150_read(c, TVP5150_ROM_MINOR_VER)); + printk("tvp5150: Vertical line count = 0x%02x%02x\n", + tvp5150_read(c, TVP5150_VERT_LN_COUNT_MSB), + tvp5150_read(c, TVP5150_VERT_LN_COUNT_LSB)); printk("tvp5150: Interrupt status register B = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_STATUS_REG_B)); + tvp5150_read(c, TVP5150_INT_STATUS_REG_B)); printk("tvp5150: Interrupt active register B = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_ACTIVE_REG_B)); - printk("tvp5150: Status register #1 = 0x%02x\n", - tvp5150_read(c, TVP5150_STATUS_REG_1)); - printk("tvp5150: Status register #2 = 0x%02x\n", - tvp5150_read(c, TVP5150_STATUS_REG_2)); - printk("tvp5150: Status register #3 = 0x%02x\n", - tvp5150_read(c, TVP5150_STATUS_REG_3)); - printk("tvp5150: Status register #4 = 0x%02x\n", - tvp5150_read(c, TVP5150_STATUS_REG_4)); - printk("tvp5150: Status register #5 = 0x%02x\n", - tvp5150_read(c, TVP5150_STATUS_REG_5)); - printk("tvp5150: Closed caption data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_CC_DATA_REG1)); - printk("tvp5150: Closed caption data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_CC_DATA_REG2)); - printk("tvp5150: Closed caption data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_CC_DATA_REG3)); - printk("tvp5150: Closed caption data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_CC_DATA_REG4)); - printk("tvp5150: WSS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_WSS_DATA_REG1)); - printk("tvp5150: WSS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_WSS_DATA_REG2)); - printk("tvp5150: WSS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_WSS_DATA_REG3)); - printk("tvp5150: WSS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_WSS_DATA_REG4)); - printk("tvp5150: WSS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_WSS_DATA_REG5)); - printk("tvp5150: WSS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_WSS_DATA_REG6)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG1)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG2)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG3)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG4)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG5)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG6)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG7)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG8)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG9)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG10)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG11)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG12)); - printk("tvp5150: VPS data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VPS_DATA_REG13)); - printk("tvp5150: VITC data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VITC_DATA_REG1)); - printk("tvp5150: VITC data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VITC_DATA_REG2)); - printk("tvp5150: VITC data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VITC_DATA_REG3)); - printk("tvp5150: VITC data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VITC_DATA_REG4)); - printk("tvp5150: VITC data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VITC_DATA_REG5)); - printk("tvp5150: VITC data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VITC_DATA_REG6)); - printk("tvp5150: VITC data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VITC_DATA_REG7)); - printk("tvp5150: VITC data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VITC_DATA_REG8)); - printk("tvp5150: VITC data registers = 0x%02x\n", - tvp5150_read(c, TVP5150_VITC_DATA_REG9)); - printk("tvp5150: VBI FIFO read data = 0x%02x\n", - tvp5150_read(c, TVP5150_VBI_FIFO_READ_DATA)); - printk("tvp5150: Teletext filter 1 = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_1_1)); - printk("tvp5150: Teletext filter 1 = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_1_2)); - printk("tvp5150: Teletext filter 1 = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_1_3)); - printk("tvp5150: Teletext filter 1 = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_1_4)); - printk("tvp5150: Teletext filter 1 = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_1_5)); - printk("tvp5150: Teletext filter 2 = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_2_1)); - printk("tvp5150: Teletext filter 2 = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_2_2)); - printk("tvp5150: Teletext filter 2 = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_2_3)); - printk("tvp5150: Teletext filter 2 = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_2_4)); - printk("tvp5150: Teletext filter 2 = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_2_5)); + tvp5150_read(c, TVP5150_INT_ACTIVE_REG_B)); + printk("tvp5150: Status regs #1 to #5 = %02x %02x %02x %02x %02x\n", + tvp5150_read(c, TVP5150_STATUS_REG_1), + tvp5150_read(c, TVP5150_STATUS_REG_2), + tvp5150_read(c, TVP5150_STATUS_REG_3), + tvp5150_read(c, TVP5150_STATUS_REG_4), + tvp5150_read(c, TVP5150_STATUS_REG_5)); + + dump_reg_range(c,"Teletext filter 1", TVP5150_TELETEXT_FIL1_INI, + TVP5150_TELETEXT_FIL1_END,8); + dump_reg_range(c,"Teletext filter 2", TVP5150_TELETEXT_FIL2_INI, + TVP5150_TELETEXT_FIL2_END,8); + printk("tvp5150: Teletext filter enable = 0x%02x\n", - tvp5150_read(c, TVP5150_TELETEXT_FIL_ENA)); + tvp5150_read(c, TVP5150_TELETEXT_FIL_ENA)); printk("tvp5150: Interrupt status register A = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_STATUS_REG_A)); + tvp5150_read(c, TVP5150_INT_STATUS_REG_A)); printk("tvp5150: Interrupt enable register A = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_ENABLE_REG_A)); + tvp5150_read(c, TVP5150_INT_ENABLE_REG_A)); printk("tvp5150: Interrupt configuration = 0x%02x\n", - tvp5150_read(c, TVP5150_INT_CONF)); - printk("tvp5150: VDP configuration RAM data = 0x%02x\n", - tvp5150_read(c, TVP5150_VDP_CONF_RAM_DATA)); - printk("tvp5150: Configuration RAM address low byte = 0x%02x\n", - tvp5150_read(c, TVP5150_CONF_RAM_ADDR_LOW)); - printk("tvp5150: Configuration RAM address high byte = 0x%02x\n", - tvp5150_read(c, TVP5150_CONF_RAM_ADDR_HIGH)); + tvp5150_read(c, TVP5150_INT_CONF)); printk("tvp5150: VDP status register = 0x%02x\n", - tvp5150_read(c, TVP5150_VDP_STATUS_REG)); + tvp5150_read(c, TVP5150_VDP_STATUS_REG)); printk("tvp5150: FIFO word count = 0x%02x\n", - tvp5150_read(c, TVP5150_FIFO_WORD_COUNT)); + tvp5150_read(c, TVP5150_FIFO_WORD_COUNT)); printk("tvp5150: FIFO interrupt threshold = 0x%02x\n", - tvp5150_read(c, TVP5150_FIFO_INT_THRESHOLD)); + tvp5150_read(c, TVP5150_FIFO_INT_THRESHOLD)); printk("tvp5150: FIFO reset = 0x%02x\n", - tvp5150_read(c, TVP5150_FIFO_RESET)); + tvp5150_read(c, TVP5150_FIFO_RESET)); printk("tvp5150: Line number interrupt = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_NUMBER_INT)); - printk("tvp5150: Pixel alignment register low byte = 0x%02x\n", - tvp5150_read(c, TVP5150_PIX_ALIGN_REG_LOW)); - printk("tvp5150: Pixel alignment register high byte = 0x%02x\n", - tvp5150_read(c, TVP5150_PIX_ALIGN_REG_HIGH)); + tvp5150_read(c, TVP5150_LINE_NUMBER_INT)); + printk("tvp5150: Pixel alignment register = 0x%02x%02x\n", + tvp5150_read(c, TVP5150_PIX_ALIGN_REG_HIGH), + tvp5150_read(c, TVP5150_PIX_ALIGN_REG_LOW)); printk("tvp5150: FIFO output control = 0x%02x\n", - tvp5150_read(c, TVP5150_FIFO_OUT_CTRL)); - printk("tvp5150: Full field enable 1 = 0x%02x\n", - tvp5150_read(c, TVP5150_FULL_FIELD_ENA_1)); - printk("tvp5150: Full field enable 2 = 0x%02x\n", - tvp5150_read(c, TVP5150_FULL_FIELD_ENA_2)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_1)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_2)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_3)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_4)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_5)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_6)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_7)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_8)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_9)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_10)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_11)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_12)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_13)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_14)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_15)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_16)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_17)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_18)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_19)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_20)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_21)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_22)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_23)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_24)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_25)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_27)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_28)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_29)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_30)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_31)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_32)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_33)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_34)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_35)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_36)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_37)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_38)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_39)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_40)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_41)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_42)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_43)); - printk("tvp5150: Line mode registers = 0x%02x\n", - tvp5150_read(c, TVP5150_LINE_MODE_REG_44)); + tvp5150_read(c, TVP5150_FIFO_OUT_CTRL)); + printk("tvp5150: Full field enable = 0x%02x\n", + tvp5150_read(c, TVP5150_FULL_FIELD_ENA)); printk("tvp5150: Full field mode register = 0x%02x\n", - tvp5150_read(c, TVP5150_FULL_FIELD_MODE_REG)); + tvp5150_read(c, TVP5150_FULL_FIELD_MODE_REG)); + + dump_reg_range(c,"CC data", TVP5150_CC_DATA_INI, + TVP5150_CC_DATA_END,8); + + dump_reg_range(c,"WSS data", TVP5150_WSS_DATA_INI, + TVP5150_WSS_DATA_END,8); + + dump_reg_range(c,"VPS data", TVP5150_VPS_DATA_INI, + TVP5150_VPS_DATA_END,8); + + dump_reg_range(c,"VITC data", TVP5150_VITC_DATA_INI, + TVP5150_VITC_DATA_END,10); + + dump_reg_range(c,"Line mode", TVP5150_LINE_MODE_INI, + TVP5150_LINE_MODE_END,8); } /**************************************************************************** @@ -593,10 +441,10 @@ static const struct i2c_reg_value tvp5150_init_default[] = { TVP5150_FIFO_OUT_CTRL,0x01 }, { /* 0xcf */ - TVP5150_FULL_FIELD_ENA_1,0x00 + TVP5150_FULL_FIELD_ENA,0x00 }, { /* 0xd0 */ - TVP5150_FULL_FIELD_ENA_2,0x00 + TVP5150_LINE_MODE_INI,0x00 }, { /* 0xfc */ TVP5150_FULL_FIELD_MODE_REG,0x7f @@ -634,45 +482,73 @@ struct i2c_vbi_ram_value { unsigned char values[26]; }; +/* tvp5150_vbi_types should follow the same order as vbi_ram_default + * value 0 means rom position 0x10, value 1 means rom position 0x30 + * and so on. There are 16 possible locations from 0 to 15. + */ +enum tvp5150_vbi_types { /* Video line number Description */ + VBI_WST_SECAM, /* 6-23 (field 1,2) Teletext, SECAM */ + VBI_WST_PAL_B, /* 6-22 (field 1,2) Teletext, PAL, System B */ + VBI_WST_PAL_C, /* 6-22 (field 1,2) Teletext, PAL, System C */ + VBI_WST_NTSC_B, /* 10-21 (field 1,2) Teletext, NTSC, System B */ + VBI_NABTS_NTSC_C, /* 10-21 (field 1,2) Teletext, NTSC, System C */ + VBI_NABTS_NTSC_D, /* 10-21 (field 1,2) Teletext, NTSC, System D */ + VBI_CC_PAL_SECAM, /* 22 (field 1,2) Closed Caption PAL/SECAM */ + VBI_CC_NTSC, /* 21 (field 1,2) Closed Caption NTSC */ + VBI_WSS_PAL_SECAM, /* 23 (field 1,2) Wide Screen Signal PAL/SECAM */ + VBI_WSS_NTSC, /* 20 (field 1,2) Wide Screen Signal NTSC */ + VBI_VITC_PAL_SECAM, /* 6-22 Vertical Interval Timecode PAL/SECAM */ + VBI_VITC_NTSC, /* 10-20 Vertical Interval Timecode NTSC */ + VBI_VPS_PAL, /* 16 Video Program System PAL */ + VBI_EPG_GEMSTAR, /* EPG/Gemstar Electronic program guide */ + VBI_RESERVED, /* not in use on vbi_ram_default table */ + VBI_FULL_FIELD /* Active video/Full Field */ +}; + static struct i2c_vbi_ram_value vbi_ram_default[] = { - {0x010, /* WST SECAM 6 */ + {0x010, /* WST SECAM */ { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x26, 0xe6, 0xb4, 0x0e, 0x0, 0x0, 0x0, 0x10, 0x0 } }, - {0x030, /* WST PAL B 6 */ + {0x030, /* WST PAL B */ { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x2b, 0xa6, 0x72, 0x10, 0x0, 0x0, 0x0, 0x10, 0x0 } }, - {0x050, /* WST PAL C 6 */ + {0x050, /* WST PAL C */ { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0xa6, 0x98, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } }, - {0x070, /* WST NTSC 6 */ + {0x070, /* WST NTSC B */ { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } }, - {0x090, /* NABTS, NTSC 6 */ + {0x090, /* NABTS, NTSC */ { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x15, 0x0 } }, - {0x0b0, /* NABTS, NTSC-J 6 */ + {0x0b0, /* NABTS, NTSC-J */ { 0xaa, 0xaa, 0xff, 0xff , 0xa7, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } }, - {0x0d0, /* CC, PAL/SECAM 6 */ + {0x0d0, /* CC, PAL/SECAM */ { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0xa6, 0x7b, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 } }, - {0x0f0, /* CC, NTSC 6 */ + {0x0f0, /* CC, NTSC */ { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0x69, 0x8c, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 } }, - {0x110, /* WSS, PAL/SECAM 6 */ + {0x110, /* WSS, PAL/SECAM */ { 0x5b, 0x55, 0xc5, 0xff , 0x0, 0x71, 0x6e, 0x42, 0xa6, 0xcd, 0x0f, 0x0, 0x0, 0x0, 0x3a, 0x0 } }, {0x130, /* WSS, NTSC C */ { 0x38, 0x00, 0x3f, 0x00 , 0x0, 0x71, 0x6e, 0x43, 0x69, 0x7c, 0x08, 0x0, 0x0, 0x0, 0x39, 0x0 } }, - {0x150, /* VITC, PAL/SECAM 6 */ + {0x150, /* VITC, PAL/SECAM */ { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0xa6, 0x85, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 } }, - {0x170, /* VITC, NTSC 6 */ + {0x170, /* VITC, NTSC */ { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0x69, 0x94, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 } }, - { (u16)-1 } + {0x190, /* VPS, PAL */ + { 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d, 0xa6, 0xda, 0x0b, 0x0, 0x0, 0x0, 0x60, 0x0 } + }, + {0x1b0, /* Gemstar Custom 1 */ + { 0xcc, 0xcc, 0xff, 0xff, 0x05, 0x51, 0x6e, 0x05, 0x69, 0x19, 0x13, 0x0, 0x0, 0x0, 0x60, 0x0 } + }, }; static int tvp5150_write_inittab(struct i2c_client *c, @@ -691,10 +567,10 @@ static int tvp5150_vdp_init(struct i2c_client *c, unsigned int i; /* Disable Full Field */ - tvp5150_write(c, TVP5150_FULL_FIELD_ENA_1, 0); + tvp5150_write(c, TVP5150_FULL_FIELD_ENA, 0); /* Before programming, Line mode should be at 0xff */ - for (i=TVP5150_FULL_FIELD_ENA_2; i<=TVP5150_LINE_MODE_REG_44; i++) + for (i=TVP5150_LINE_MODE_INI; i<=TVP5150_LINE_MODE_END; i++) tvp5150_write(c, i, 0xff); /* Load Ram Table */ @@ -710,6 +586,51 @@ static int tvp5150_vdp_init(struct i2c_client *c, return 0; } +/* Set vbi processing + * type - one of tvp5150_vbi_types + * line - line to gather data + * fields: bit 0 field1, bit 1, field2 + * flags (default=0xf0) is a bitmask, were set means: + * bit 7: enable filtering null bytes on CC + * bit 6: send data also to FIFO + * bit 5: don't allow data with errors on FIFO + * bit 4: enable ECC when possible + * pix_align = pix alignment: + * LSB = field1 + * MSB = field2 + */ +static int tvp5150_set_vbi(struct i2c_client *c, enum tvp5150_vbi_types type, + u8 flags, int line, const int fields) +{ + struct tvp5150 *decoder = i2c_get_clientdata(c); + v4l2_std_id std=decoder->norm; + u8 reg; + + if (std == V4L2_STD_ALL) { + tvp5150_err("VBI can't be configured without knowing number of lines\n"); + return -EINVAL; + } else if (std && V4L2_STD_625_50) { + /* Don't follow NTSC Line number convension */ + line += 3; + } + + if (line<6||line>27) + return -EINVAL; + + type=type | (flags & 0xf0); + reg=((line-6)<<1)+TVP5150_LINE_MODE_INI; + + if (fields&1) { + tvp5150_write(c, reg, type); + } + + if (fields&2) { + tvp5150_write(c, reg+1, type); + } + + return 0; +} + static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std) { struct tvp5150 *decoder = i2c_get_clientdata(c); @@ -1086,7 +1007,7 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter, rv = i2c_attach_client(c); - core->norm = V4L2_STD_ALL; + core->norm = V4L2_STD_ALL; /* Default is autodetect */ core->input = 2; core->enable = 1; core->bright = 32768; diff --git a/drivers/media/video/tvp5150_reg.h b/drivers/media/video/tvp5150_reg.h index cd45c1ded786..c81587e06e37 100644 --- a/drivers/media/video/tvp5150_reg.h +++ b/drivers/media/video/tvp5150_reg.h @@ -64,49 +64,32 @@ #define TVP5150_STATUS_REG_4 0x8b /* Status register #4 */ #define TVP5150_STATUS_REG_5 0x8c /* Status register #5 */ /* Reserved 8Dh-8Fh */ -#define TVP5150_CC_DATA_REG1 0x90 /* Closed caption data registers */ -#define TVP5150_CC_DATA_REG2 0x91 /* Closed caption data registers */ -#define TVP5150_CC_DATA_REG3 0x92 /* Closed caption data registers */ -#define TVP5150_CC_DATA_REG4 0x93 /* Closed caption data registers */ -#define TVP5150_WSS_DATA_REG1 0X94 /* WSS data registers */ -#define TVP5150_WSS_DATA_REG2 0X95 /* WSS data registers */ -#define TVP5150_WSS_DATA_REG3 0X96 /* WSS data registers */ -#define TVP5150_WSS_DATA_REG4 0X97 /* WSS data registers */ -#define TVP5150_WSS_DATA_REG5 0X98 /* WSS data registers */ -#define TVP5150_WSS_DATA_REG6 0X99 /* WSS data registers */ -#define TVP5150_VPS_DATA_REG1 0x9a /* VPS data registers */ -#define TVP5150_VPS_DATA_REG2 0x9b /* VPS data registers */ -#define TVP5150_VPS_DATA_REG3 0x9c /* VPS data registers */ -#define TVP5150_VPS_DATA_REG4 0x9d /* VPS data registers */ -#define TVP5150_VPS_DATA_REG5 0x9e /* VPS data registers */ -#define TVP5150_VPS_DATA_REG6 0x9f /* VPS data registers */ -#define TVP5150_VPS_DATA_REG7 0xa0 /* VPS data registers */ -#define TVP5150_VPS_DATA_REG8 0xa1 /* VPS data registers */ -#define TVP5150_VPS_DATA_REG9 0xa2 /* VPS data registers */ -#define TVP5150_VPS_DATA_REG10 0xa3 /* VPS data registers */ -#define TVP5150_VPS_DATA_REG11 0xa4 /* VPS data registers */ -#define TVP5150_VPS_DATA_REG12 0xa5 /* VPS data registers */ -#define TVP5150_VPS_DATA_REG13 0xa6 /* VPS data registers */ -#define TVP5150_VITC_DATA_REG1 0xa7 /* VITC data registers */ -#define TVP5150_VITC_DATA_REG2 0xa8 /* VITC data registers */ -#define TVP5150_VITC_DATA_REG3 0xa9 /* VITC data registers */ -#define TVP5150_VITC_DATA_REG4 0xaa /* VITC data registers */ -#define TVP5150_VITC_DATA_REG5 0xab /* VITC data registers */ -#define TVP5150_VITC_DATA_REG6 0xac /* VITC data registers */ -#define TVP5150_VITC_DATA_REG7 0xad /* VITC data registers */ -#define TVP5150_VITC_DATA_REG8 0xae /* VITC data registers */ -#define TVP5150_VITC_DATA_REG9 0xaf /* VITC data registers */ + /* Closed caption data registers */ +#define TVP5150_CC_DATA_INI 0x90 +#define TVP5150_CC_DATA_END 0x93 + + /* WSS data registers */ +#define TVP5150_WSS_DATA_INI 0x94 +#define TVP5150_WSS_DATA_END 0x99 + +/* VPS data registers */ +#define TVP5150_VPS_DATA_INI 0x9a +#define TVP5150_VPS_DATA_END 0xa6 + +/* VITC data registers */ +#define TVP5150_VITC_DATA_INI 0xa7 +#define TVP5150_VITC_DATA_END 0xaf + #define TVP5150_VBI_FIFO_READ_DATA 0xb0 /* VBI FIFO read data */ -#define TVP5150_TELETEXT_FIL_1_1 0xb1 /* Teletext filter 1 */ -#define TVP5150_TELETEXT_FIL_1_2 0xb2 /* Teletext filter 1 */ -#define TVP5150_TELETEXT_FIL_1_3 0xb3 /* Teletext filter 1 */ -#define TVP5150_TELETEXT_FIL_1_4 0xb4 /* Teletext filter 1 */ -#define TVP5150_TELETEXT_FIL_1_5 0xb5 /* Teletext filter 1 */ -#define TVP5150_TELETEXT_FIL_2_1 0xb6 /* Teletext filter 2 */ -#define TVP5150_TELETEXT_FIL_2_2 0xb7 /* Teletext filter 2 */ -#define TVP5150_TELETEXT_FIL_2_3 0xb8 /* Teletext filter 2 */ -#define TVP5150_TELETEXT_FIL_2_4 0xb9 /* Teletext filter 2 */ -#define TVP5150_TELETEXT_FIL_2_5 0xba /* Teletext filter 2 */ + +/* Teletext filter 1 */ +#define TVP5150_TELETEXT_FIL1_INI 0xb1 +#define TVP5150_TELETEXT_FIL1_END 0xb5 + +/* Teletext filter 2 */ +#define TVP5150_TELETEXT_FIL2_INI 0xb6 +#define TVP5150_TELETEXT_FIL2_END 0xba + #define TVP5150_TELETEXT_FIL_ENA 0xbb /* Teletext filter enable */ /* Reserved BCh-BFh */ #define TVP5150_INT_STATUS_REG_A 0xc0 /* Interrupt status register A */ @@ -124,50 +107,11 @@ #define TVP5150_PIX_ALIGN_REG_HIGH 0xcc /* Pixel alignment register high byte */ #define TVP5150_FIFO_OUT_CTRL 0xcd /* FIFO output control */ /* Reserved CEh */ -#define TVP5150_FULL_FIELD_ENA_1 0xcf /* Full field enable 1 */ -#define TVP5150_FULL_FIELD_ENA_2 0xd0 /* Full field enable 2 */ -#define TVP5150_LINE_MODE_REG_1 0xd1 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_2 0xd2 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_3 0xd3 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_4 0xd4 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_5 0xd5 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_6 0xd6 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_7 0xd7 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_8 0xd8 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_9 0xd9 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_10 0xda /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_11 0xdb /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_12 0xdc /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_13 0xdd /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_14 0xde /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_15 0xdf /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_16 0xe0 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_17 0xe1 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_18 0xe2 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_19 0xe3 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_20 0xe4 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_21 0xe5 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_22 0xe6 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_23 0xe7 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_24 0xe8 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_25 0xe9 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_27 0xea /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_28 0xeb /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_29 0xec /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_30 0xed /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_31 0xee /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_32 0xef /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_33 0xf0 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_34 0xf1 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_35 0xf2 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_36 0xf3 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_37 0xf4 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_38 0xf5 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_39 0xf6 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_40 0xf7 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_41 0xf8 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_42 0xf9 /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_43 0xfa /* Line mode registers */ -#define TVP5150_LINE_MODE_REG_44 0xfb /* Line mode registers */ +#define TVP5150_FULL_FIELD_ENA 0xcf /* Full field enable 1 */ + +/* Line mode registers */ +#define TVP5150_LINE_MODE_INI 0xd0 +#define TVP5150_LINE_MODE_END 0xfb + #define TVP5150_FULL_FIELD_MODE_REG 0xfc /* Full field mode register */ /* Reserved FDh-FFh */ -- cgit v1.2.3-59-g8ed1b From 6ac48b458769059ee6147dd8bf2767e820407292 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:11:05 -0200 Subject: V4L/DVB (3408): Included new sliced VBI types to videodev2.h and tvp5150 - Added other sliced VBI types to videodev2.h - tvp5150 now uses standard V4L2 API codes from videodev2.h - Implemented VIDIOC_G_SLICED_VBI_CAP for tvp5150. This is dynamically filled based on defined VDP C-RAM values filled by the driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-vbi.c | 6 +- drivers/media/video/saa7115.c | 6 +- drivers/media/video/tvp5150.c | 161 +++++++++++++++++++----------- drivers/media/video/tvp5150_reg.h | 7 ++ include/linux/videodev2.h | 51 ++++++++-- 5 files changed, 161 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 04d879da7d63..e96fd1f1d6dc 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c @@ -151,7 +151,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) case VIDIOC_G_FMT: { static u16 lcr2vbi[] = { - 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ + 0, V4L2_SLICED_TELETEXT_PAL_B, 0, /* 1 */ 0, V4L2_SLICED_WSS_625, 0, /* 4 */ V4L2_SLICED_CAPTION_525, /* 6 */ 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ @@ -231,7 +231,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) for (i = 7; i <= 23; i++) { for (x = 0; x <= 1; x++) { switch (svbi->service_lines[1-x][i]) { - case V4L2_SLICED_TELETEXT_B: + case V4L2_SLICED_TELETEXT_PAL_B: lcr[i] |= 1 << (4 * x); break; case V4L2_SLICED_WSS_625: @@ -282,7 +282,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) switch (id2) { case 1: - id2 = V4L2_SLICED_TELETEXT_B; + id2 = V4L2_SLICED_TELETEXT_PAL_B; break; case 4: id2 = V4L2_SLICED_WSS_625; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 048d000941c7..487a42970963 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -791,7 +791,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo case 0: lcr[i] |= 0xf << (4 * x); break; - case V4L2_SLICED_TELETEXT_B: + case V4L2_SLICED_TELETEXT_PAL_B: lcr[i] |= 1 << (4 * x); break; case V4L2_SLICED_CAPTION_525: @@ -820,7 +820,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) { static u16 lcr2vbi[] = { - 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ + 0, V4L2_SLICED_TELETEXT_PAL_B, 0, /* 1 */ 0, V4L2_SLICED_CAPTION_525, /* 4 */ V4L2_SLICED_WSS_625, 0, /* 5 */ V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */ @@ -985,7 +985,7 @@ static void saa7115_decode_vbi_line(struct i2c_client *client, /* decode payloads */ switch (id2) { case 1: - vbi->type = V4L2_SLICED_TELETEXT_B; + vbi->type = V4L2_SLICED_TELETEXT_PAL_B; break; case 4: if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1])) diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index f7fa93c64d11..17a8dd726912 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -1,8 +1,8 @@ /* - * tvp5150 - Texas Instruments TVP5150A(M) video decoder driver + * tvp5150 - Texas Instruments TVP5150A/AM1 video decoder driver * - * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) - * This code is placed under the terms of the GNU General Public License + * Copyright (c) 2005,2006 Mauro Carvalho Chehab (mchehab@infradead.org) + * This code is placed under the terms of the GNU General Public License v2 */ #include @@ -13,10 +13,11 @@ #include "tvp5150_reg.h" -MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); /* standard i2c insmod options */ +MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); +/* standard i2c insmod options */ static unsigned short normal_i2c[] = { 0xb8 >> 1, 0xba >> 1, @@ -477,82 +478,101 @@ static const struct i2c_reg_value tvp5150_init_enable[] = { } }; +struct tvp5150_vbi_type { + unsigned int vbi_type; + unsigned int ini_line; + unsigned int end_line; + unsigned int by_field :1; +}; + struct i2c_vbi_ram_value { u16 reg; - unsigned char values[26]; + struct tvp5150_vbi_type type; + unsigned char values[16]; }; -/* tvp5150_vbi_types should follow the same order as vbi_ram_default +/* This struct have the values for each supported VBI Standard + * by + tvp5150_vbi_types should follow the same order as vbi_ram_default * value 0 means rom position 0x10, value 1 means rom position 0x30 * and so on. There are 16 possible locations from 0 to 15. */ -enum tvp5150_vbi_types { /* Video line number Description */ - VBI_WST_SECAM, /* 6-23 (field 1,2) Teletext, SECAM */ - VBI_WST_PAL_B, /* 6-22 (field 1,2) Teletext, PAL, System B */ - VBI_WST_PAL_C, /* 6-22 (field 1,2) Teletext, PAL, System C */ - VBI_WST_NTSC_B, /* 10-21 (field 1,2) Teletext, NTSC, System B */ - VBI_NABTS_NTSC_C, /* 10-21 (field 1,2) Teletext, NTSC, System C */ - VBI_NABTS_NTSC_D, /* 10-21 (field 1,2) Teletext, NTSC, System D */ - VBI_CC_PAL_SECAM, /* 22 (field 1,2) Closed Caption PAL/SECAM */ - VBI_CC_NTSC, /* 21 (field 1,2) Closed Caption NTSC */ - VBI_WSS_PAL_SECAM, /* 23 (field 1,2) Wide Screen Signal PAL/SECAM */ - VBI_WSS_NTSC, /* 20 (field 1,2) Wide Screen Signal NTSC */ - VBI_VITC_PAL_SECAM, /* 6-22 Vertical Interval Timecode PAL/SECAM */ - VBI_VITC_NTSC, /* 10-20 Vertical Interval Timecode NTSC */ - VBI_VPS_PAL, /* 16 Video Program System PAL */ - VBI_EPG_GEMSTAR, /* EPG/Gemstar Electronic program guide */ - VBI_RESERVED, /* not in use on vbi_ram_default table */ - VBI_FULL_FIELD /* Active video/Full Field */ -}; static struct i2c_vbi_ram_value vbi_ram_default[] = { - {0x010, /* WST SECAM */ - { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x26, 0xe6, 0xb4, 0x0e, 0x0, 0x0, 0x0, 0x10, 0x0 } + {0x010, /* Teletext, SECAM, WST System A */ + {V4L2_SLICED_TELETEXT_SECAM,6,23,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26, + 0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 } }, - {0x030, /* WST PAL B */ - { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x2b, 0xa6, 0x72, 0x10, 0x0, 0x0, 0x0, 0x10, 0x0 } + {0x030, /* Teletext, PAL, WST System B */ + {V4L2_SLICED_TELETEXT_PAL_B,6,22,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b, + 0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 } }, - {0x050, /* WST PAL C */ - { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0xa6, 0x98, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } + {0x050, /* Teletext, PAL, WST System C */ + {V4L2_SLICED_TELETEXT_PAL_C,6,22,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22, + 0xa6, 0x98, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 } }, - {0x070, /* WST NTSC B */ - { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } + {0x070, /* Teletext, NTSC, WST System B */ + {V4L2_SLICED_TELETEXT_NTSC_B,10,21,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x23, + 0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 } }, - {0x090, /* NABTS, NTSC */ - { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x15, 0x0 } + {0x090, /* Tetetext, NTSC NABTS System C */ + {V4L2_SLICED_TELETEXT_NTSC_C,10,21,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22, + 0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x15, 0x00 } }, - {0x0b0, /* NABTS, NTSC-J */ - { 0xaa, 0xaa, 0xff, 0xff , 0xa7, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } + {0x0b0, /* Teletext, NTSC-J, NABTS System D */ + {V4L2_SLICED_TELETEXT_NTSC_D,10,21,1}, + { 0xaa, 0xaa, 0xff, 0xff, 0xa7, 0x2e, 0x20, 0x23, + 0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 } }, - {0x0d0, /* CC, PAL/SECAM */ - { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0xa6, 0x7b, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 } + {0x0d0, /* Closed Caption, PAL/SECAM */ + {V4L2_SLICED_CAPTION_625,22,22,1}, + { 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02, + 0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 } }, - {0x0f0, /* CC, NTSC */ - { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0x69, 0x8c, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 } + {0x0f0, /* Closed Caption, NTSC */ + {V4L2_SLICED_CAPTION_525,21,21,1}, + { 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02, + 0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 } }, - {0x110, /* WSS, PAL/SECAM */ - { 0x5b, 0x55, 0xc5, 0xff , 0x0, 0x71, 0x6e, 0x42, 0xa6, 0xcd, 0x0f, 0x0, 0x0, 0x0, 0x3a, 0x0 } + {0x110, /* Wide Screen Signal, PAL/SECAM */ + {V4L2_SLICED_WSS_625,20,21,1}, + { 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42, + 0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 } }, - {0x130, /* WSS, NTSC C */ - { 0x38, 0x00, 0x3f, 0x00 , 0x0, 0x71, 0x6e, 0x43, 0x69, 0x7c, 0x08, 0x0, 0x0, 0x0, 0x39, 0x0 } + {0x130, /* Wide Screen Signal, NTSC C */ + {V4L2_SLICED_WSS_525,20,20,1}, + { 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43, + 0x69, 0x7c, 0x08, 0x00, 0x00, 0x00, 0x39, 0x00 } }, - {0x150, /* VITC, PAL/SECAM */ - { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0xa6, 0x85, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 } + {0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */ + {V4l2_SLICED_VITC_625,6,22,0}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49, + 0xa6, 0x85, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 } }, - {0x170, /* VITC, NTSC */ - { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0x69, 0x94, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 } + {0x170, /* Vertical Interval Timecode (VITC), NTSC */ + {V4l2_SLICED_VITC_525,10,20,0}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49, + 0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 } }, - {0x190, /* VPS, PAL */ - { 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d, 0xa6, 0xda, 0x0b, 0x0, 0x0, 0x0, 0x60, 0x0 } - }, - {0x1b0, /* Gemstar Custom 1 */ - { 0xcc, 0xcc, 0xff, 0xff, 0x05, 0x51, 0x6e, 0x05, 0x69, 0x19, 0x13, 0x0, 0x0, 0x0, 0x60, 0x0 } + {0x190, /* Video Program System (VPS), PAL */ + {V4L2_SLICED_VPS,16,16,0}, + { 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d, + 0xa6, 0xda, 0x0b, 0x00, 0x00, 0x00, 0x60, 0x00 } }, + /* 0x1d0 User programmable */ + + /* End of struct */ + { (u16)-1 } }; static int tvp5150_write_inittab(struct i2c_client *c, - const struct i2c_reg_value *regs) + const struct i2c_reg_value *regs) { while (regs->reg != 0xff) { tvp5150_write(c, regs->reg, regs->value); @@ -562,7 +582,7 @@ static int tvp5150_write_inittab(struct i2c_client *c, } static int tvp5150_vdp_init(struct i2c_client *c, - const struct i2c_vbi_ram_value *regs) + const struct i2c_vbi_ram_value *regs) { unsigned int i; @@ -586,6 +606,24 @@ static int tvp5150_vdp_init(struct i2c_client *c, return 0; } +/* Fills VBI capabilities based on i2c_vbi_ram_value struct */ +static void tvp5150_vbi_get_cap(const struct i2c_vbi_ram_value *regs, + struct v4l2_sliced_vbi_cap *cap) +{ + int line; + + memset(cap, 0, sizeof *cap); + + while (regs->reg != (u16)-1 ) { + for (line=regs->type.ini_line;line<=regs->type.end_line;line++) { + cap->service_lines[0][line] |= regs->type.vbi_type; + } + cap->service_set |= regs->type.vbi_type; + + regs++; + } +} + /* Set vbi processing * type - one of tvp5150_vbi_types * line - line to gather data @@ -599,7 +637,7 @@ static int tvp5150_vdp_init(struct i2c_client *c, * LSB = field1 * MSB = field2 */ -static int tvp5150_set_vbi(struct i2c_client *c, enum tvp5150_vbi_types type, +static int tvp5150_set_vbi(struct i2c_client *c, unsigned int type, u8 flags, int line, const int fields) { struct tvp5150 *decoder = i2c_get_clientdata(c); @@ -775,6 +813,15 @@ static int tvp5150_command(struct i2c_client *c, *(v4l2_std_id *)arg = decoder->norm; break; + case VIDIOC_G_SLICED_VBI_CAP: + { + struct v4l2_sliced_vbi_cap *cap = arg; + tvp5150_dbg(1, "VIDIOC_G_SLICED_VBI_CAP\n"); + + tvp5150_vbi_get_cap(vbi_ram_default, cap); + break; + } + #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_INT_G_REGISTER: { @@ -1021,7 +1068,7 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter, return rv; } - if (debug > 1) +// if (debug > 1) dump_reg(c); return 0; } diff --git a/drivers/media/video/tvp5150_reg.h b/drivers/media/video/tvp5150_reg.h index c81587e06e37..4240043c0b2a 100644 --- a/drivers/media/video/tvp5150_reg.h +++ b/drivers/media/video/tvp5150_reg.h @@ -1,3 +1,10 @@ +/* + * tvp5150 - Texas Instruments TVP5150A/AM1 video decoder registers + * + * Copyright (c) 2005,2006 Mauro Carvalho Chehab (mchehab@infradead.org) + * This code is placed under the terms of the GNU General Public License v2 + */ + #define TVP5150_VD_IN_SRC_SEL_1 0x00 /* Video input source selection #1 */ #define TVP5150_ANAL_CHL_CTL 0x01 /* Analog channel controls */ #define TVP5150_OP_MODE_CTL 0x02 /* Operation mode controls */ diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index ce40675324bd..27ae3d679cbe 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -949,13 +949,50 @@ struct v4l2_sliced_vbi_format __u32 reserved[2]; /* must be zero */ }; -#define V4L2_SLICED_TELETEXT_B (0x0001) -#define V4L2_SLICED_VPS (0x0400) -#define V4L2_SLICED_CAPTION_525 (0x1000) -#define V4L2_SLICED_WSS_625 (0x4000) - -#define V4L2_SLICED_VBI_525 (V4L2_SLICED_CAPTION_525) -#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625) +/* Teletext WST, defined on ITU-R BT.653-2 */ +#define V4L2_SLICED_TELETEXT_PAL_B (0x000001) +#define V4L2_SLICED_TELETEXT_PAL_C (0x000002) +#define V4L2_SLICED_TELETEXT_NTSC_B (0x000010) +#define V4L2_SLICED_TELETEXT_SECAM (0x000020) + +/* Teletext NABTS, defined on ITU-R BT.653-2 */ +#define V4L2_SLICED_TELETEXT_NTSC_C (0x000040) +#define V4L2_SLICED_TELETEXT_NTSC_D (0x000080) + +/* Video Program System, defined on ETS 300 231*/ +#define V4L2_SLICED_VPS (0x000400) + +/* Closed Caption, defined on EIA-608 */ +#define V4L2_SLICED_CAPTION_525 (0x001000) +#define V4L2_SLICED_CAPTION_625 (0x002000) + +/* Wide Screen System, defined on ITU-R BT1119.1 */ +#define V4L2_SLICED_WSS_625 (0x004000) + +/* Wide Screen System, defined on IEC 61880 */ +#define V4L2_SLICED_WSS_525 (0x008000) + +/* Vertical Interval Timecode (VITC), defined on SMPTE 12M */ +#define V4l2_SLICED_VITC_625 (0x010000) +#define V4l2_SLICED_VITC_525 (0x020000) + +/* Compat macro - Should be removed for 2.6.18 */ +#define V4L2_SLICED_TELETEXT_B V4L2_SLICED_TELETEXT_PAL_B + +#define V4L2_SLICED_VBI_525 (V4L2_SLICED_TELETEXT_NTSC_B |\ + V4L2_SLICED_TELETEXT_NTSC_C |\ + V4L2_SLICED_TELETEXT_NTSC_D |\ + V4L2_SLICED_CAPTION_525 |\ + V4L2_SLICED_WSS_525 |\ + V4l2_SLICED_VITC_525) + +#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_PAL_B |\ + V4L2_SLICED_TELETEXT_PAL_C |\ + V4L2_SLICED_TELETEXT_SECAM |\ + V4L2_SLICED_VPS |\ + V4L2_SLICED_CAPTION_625 |\ + V4L2_SLICED_WSS_625 |\ + V4l2_SLICED_VITC_625) struct v4l2_sliced_vbi_cap { -- cgit v1.2.3-59-g8ed1b From 10b7a903072eb066b17cc9049d6ea55dd044f4c3 Mon Sep 17 00:00:00 2001 From: Peter Missel Date: Mon, 23 Jan 2006 17:11:06 -0200 Subject: V4L/DVB (3409): Mark Typhoon cards as Lifeview OEM's - Mark Typhoon cards as OEM of Lifeview. Signed-off-by: Peter Missel Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 6 ++-- drivers/media/video/saa7134/saa7134-cards.c | 47 ++++++++++++++--------------- drivers/media/video/saa7134/saa7134-dvb.c | 2 +- drivers/media/video/saa7134/saa7134.h | 2 +- 4 files changed, 28 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index cb3a59bbeb17..8a352597830f 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -1,7 +1,7 @@ 0 -> UNKNOWN/GENERIC 1 -> Proteus Pro [philips reference design] [1131:2001,1131:2001] 2 -> LifeView FlyVIDEO3000 [5168:0138,4e42:0138] - 3 -> LifeView FlyVIDEO2000 [5168:0138] + 3 -> LifeView/Typhoon FlyVIDEO2000 [5168:0138,4e42:0138] 4 -> EMPRESS [1131:6752] 5 -> SKNet Monster TV [1131:4e85] 6 -> Tevion MD 9717 @@ -53,12 +53,12 @@ 52 -> AverMedia AverTV/305 [1461:2108] 53 -> ASUS TV-FM 7135 [1043:4845] 54 -> LifeView FlyTV Platinum FM [5168:0214,1489:0214] - 55 -> LifeView FlyDVB-T DUO [5168:0502,5168:0306] + 55 -> LifeView FlyDVB-T DUO [5168:0306] 56 -> Avermedia AVerTV 307 [1461:a70a] 57 -> Avermedia AVerTV GO 007 FM [1461:f31f] 58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0351,1421:0370,1421:1370] 59 -> Kworld/Tevion V-Stream Xpert TV PVR7134 - 60 -> Typhoon DVB-T Duo Digital/Analog Cardbus [4e42:0502] + 60 -> LifeView/Typhoon FlyDVB-T Duo Cardbus [5168:0502,4e42:0502] 61 -> Philips TOUGH DVB-T reference design [1131:2004] 62 -> Compro VideoMate TV Gold+II 63 -> Kworld Xpert TV PVR7134 diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index c64718aec9cb..5a35d3b6550d 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -136,7 +136,7 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_FLYVIDEO2000] = { /* "TC Wan" */ - .name = "LifeView FlyVIDEO2000", + .name = "LifeView/Typhoon FlyVIDEO2000", .audio_clock = 0x00200000, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .radio_type = UNSET, @@ -1884,44 +1884,38 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x000, }, }, - [SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS] = { - .name = "Typhoon DVB-T Duo Digital/Analog Cardbus", + [SAA7134_BOARD_FLYDVBT_DUO_CARDBUS] = { + .name = "LifeView/Typhoon FlyDVB-T Duo Cardbus", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, - /* .gpiomask = 0xe000, */ + .gpiomask = 0x00200000, .inputs = {{ .name = name_tv, .vmux = 1, .amux = TV, - /* .gpio = 0x0000, */ + .gpio = 0x200000, /* GPIO21=High for TV input */ .tv = 1, + },{ + .name = name_svideo, /* S-Video signal on S-Video input */ + .vmux = 8, + .amux = LINE2, },{ .name = name_comp1, /* Composite signal on S-Video input */ .vmux = 0, .amux = LINE2, - /* .gpio = 0x4000, */ },{ .name = name_comp2, /* Composite input */ .vmux = 3, .amux = LINE2, - /* .gpio = 0x4000, */ - },{ - .name = name_svideo, /* S-Video signal on S-Video input */ - .vmux = 8, - .amux = LINE2, - /* .gpio = 0x4000, */ }}, .radio = { .name = name_radio, - .amux = LINE2, - }, - .mute = { - .name = name_mute, - .amux = LINE1, + .amux = TV, + .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, }, [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = { @@ -2699,6 +2693,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x5168, .subdevice = 0x0138, .driver_data = SAA7134_BOARD_FLYVIDEO2000, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x4e42, /* Typhoon */ + .subdevice = 0x0138, /* LifeView FlyTV Prime30 OEM */ + .driver_data = SAA7134_BOARD_FLYVIDEO2000, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -2935,7 +2935,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5168, .subdevice = 0x0502, /* Cardbus version */ - .driver_data = SAA7134_BOARD_FLYDVBTDUO, + .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -2980,12 +2980,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x1370, /* cardbus version */ .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, - },{ /* Typhoon DVB-T Duo Digital/Analog Cardbus */ + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x4e42, - .subdevice = 0x0502, - .driver_data = SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS, + .subvendor = 0x4e42, /* Typhoon */ + .subdevice = 0x0502, /* LifeView LR502 OEM */ + .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -3206,8 +3206,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004); break; - case SAA7134_BOARD_FLYDVBTDUO: - case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS: + case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: /* turn the fan on */ saa_writeb(SAA7134_GPIO_GPMODE3, 0x08); saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 399f9952596c..1a536e865277 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -861,7 +861,7 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, &dev->i2c_adap); break; - case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS: + case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, &dev->i2c_adap); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index e70eae8d29bb..3261d8bebdd1 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -185,7 +185,7 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57 #define SAA7134_BOARD_ADS_INSTANT_TV 58 #define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59 -#define SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS 60 +#define SAA7134_BOARD_FLYDVBT_DUO_CARDBUS 60 #define SAA7134_BOARD_PHILIPS_TOUGH 61 #define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62 #define SAA7134_BOARD_KWORLD_XPERT 63 -- cgit v1.2.3-59-g8ed1b From 2701dacb5ae5e7ecab4131605bdbcedd92bbaf82 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:11:06 -0200 Subject: V4L/DVB (3410): Implemented sliced VBI set on VIDIOC_S_FMT - Implemented sliced VBI set on VIDIOC_S_FMT Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp5150.c | 47 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 17a8dd726912..df7f304416c9 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -637,12 +637,15 @@ static void tvp5150_vbi_get_cap(const struct i2c_vbi_ram_value *regs, * LSB = field1 * MSB = field2 */ -static int tvp5150_set_vbi(struct i2c_client *c, unsigned int type, - u8 flags, int line, const int fields) +static int tvp5150_set_vbi(struct i2c_client *c, + const struct i2c_vbi_ram_value *regs, + unsigned int type,u8 flags, int line, + const int fields) { struct tvp5150 *decoder = i2c_get_clientdata(c); v4l2_std_id std=decoder->norm; u8 reg; + int pos=0; if (std == V4L2_STD_ALL) { tvp5150_err("VBI can't be configured without knowing number of lines\n"); @@ -653,9 +656,23 @@ static int tvp5150_set_vbi(struct i2c_client *c, unsigned int type, } if (line<6||line>27) - return -EINVAL; + return 0; - type=type | (flags & 0xf0); + while (regs->reg != (u16)-1 ) { + if ((type & regs->type.vbi_type) && + (line>=regs->type.ini_line) && + (line<=regs->type.end_line)) { + type=regs->type.vbi_type; + break; + } + + regs++; + pos++; + } + if (regs->reg == (u16)-1) + return 0; + + type=pos | (flags & 0xf0); reg=((line-6)<<1)+TVP5150_LINE_MODE_INI; if (fields&1) { @@ -666,7 +683,7 @@ static int tvp5150_set_vbi(struct i2c_client *c, unsigned int type, tvp5150_write(c, reg+1, type); } - return 0; + return type; } static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std) @@ -821,7 +838,27 @@ static int tvp5150_command(struct i2c_client *c, tvp5150_vbi_get_cap(vbi_ram_default, cap); break; } + case VIDIOC_S_FMT: + { + struct v4l2_format *fmt; + struct v4l2_sliced_vbi_format *svbi; + int i; + fmt = arg; + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + if (svbi->service_set != 0) { + for (i = 0; i <= 23; i++) { + svbi->service_lines[1][i] = 0; + + svbi->service_lines[0][i]=tvp5150_set_vbi(c, + vbi_ram_default, + svbi->service_lines[0][i],0xf0,i,3); + } + } + break; + } #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_INT_G_REGISTER: { -- cgit v1.2.3-59-g8ed1b From 2af3557748c18239b0aa2c77dd9c8392f6c1c7e1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 23 Jan 2006 17:11:06 -0200 Subject: V4L/DVB (3411): group dvb-bt8xx Subsystem ID's together, in order. - group dvb-bt8xx Subsystem ID's together, in order. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bttv-cards.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 9749d6ed6231..21ffe1c8dde4 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -275,7 +275,6 @@ static struct CARD { { 0x03116000, BTTV_BOARD_SENSORAY311, "Sensoray 311" }, { 0x00790e11, BTTV_BOARD_WINDVR, "Canopus WinDVR PCI" }, { 0xa0fca1a0, BTTV_BOARD_ZOLTRIX, "Face to Face Tvmax" }, - { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" }, { 0x146caa0c, BTTV_BOARD_PV951, "ituner spectra8" }, { 0x200a1295, BTTV_BOARD_PXC200, "ImageNation PXC200A" }, @@ -297,13 +296,14 @@ static struct CARD { * { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB, "Hauppauge ImpactVCB" }, */ /* DVB cards (using pci function .1 for mpeg data xfer) */ - { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, - { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" }, + { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, + { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, { 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, { 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" }, { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, + { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, -- cgit v1.2.3-59-g8ed1b From d76a617903fa6dc466907531056cc33100560ea4 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 23 Jan 2006 17:11:06 -0200 Subject: V4L/DVB (3413): Kill nxt2002 in favor of the nxt200x module - Kill nxt2002 module in favor of nxt200x. - Repair broken nxt2002 support in the nxt200x module. - Make the flexcop driver use nxt200x instead of the nxt2002 module for the Air2PC 2nd generation PCI card. - Remove the nxt2002 module from cvs and kernel build. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/Kconfig | 2 +- drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 9 +- drivers/media/dvb/frontends/Kconfig | 12 - drivers/media/dvb/frontends/Makefile | 1 - drivers/media/dvb/frontends/dvb-pll.c | 2 +- drivers/media/dvb/frontends/nxt2002.c | 706 ------------------------------ drivers/media/dvb/frontends/nxt2002.h | 23 - drivers/media/dvb/frontends/nxt200x.c | 58 ++- 8 files changed, 57 insertions(+), 756 deletions(-) delete mode 100644 drivers/media/dvb/frontends/nxt2002.c delete mode 100644 drivers/media/dvb/frontends/nxt2002.h (limited to 'drivers') diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index 2583a865a58e..2963605c0ecc 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig @@ -4,7 +4,7 @@ config DVB_B2C2_FLEXCOP select DVB_STV0299 select DVB_MT352 select DVB_MT312 - select DVB_NXT2002 + select DVB_NXT200X select DVB_STV0297 select DVB_BCM3510 select DVB_LGDT330X diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 0b940e152b79..dbe6f6b7ee26 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -9,7 +9,7 @@ #include "stv0299.h" #include "mt352.h" -#include "nxt2002.h" +#include "nxt200x.h" #include "bcm3510.h" #include "stv0297.h" #include "mt312.h" @@ -343,9 +343,10 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = { .clock_polarity_flip = 1, }; -static struct nxt2002_config samsung_tbmv_config = { +static struct nxt200x_config samsung_tbmv_config = { .demod_address = 0x0a, - .request_firmware = flexcop_fe_request_firmware, + .pll_address = 0xc2, + .pll_desc = &dvb_pll_tbmv30111in, }; static struct bcm3510_config air2pc_atsc_first_gen_config = { @@ -505,7 +506,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); } else /* try the air atsc 2nd generation (nxt2002) */ - if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { + if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC2; info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); } else diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index db3a8b40031e..f09e3da669fe 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -166,18 +166,6 @@ config DVB_STV0297 comment "ATSC (North American/Korean Terresterial DTV) frontends" depends on DVB_CORE -config DVB_NXT2002 - tristate "Nxt2002 based" - depends on DVB_CORE - select FW_LOADER - help - An ATSC 8VSB tuner module. Say Y when you want to support this frontend. - - This driver needs external firmware. Please use the command - "/Documentation/dvb/get_dvb_firmware nxt2002" to - download/extract it, and then copy it to /usr/lib/hotplug/firmware - or /lib/firmware (depending on configuration of firmware hotplug). - config DVB_NXT200X tristate "Nextwave NXT2002/NXT2004 based" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 615ec830e1c9..8f301468568d 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -25,7 +25,6 @@ obj-$(CONFIG_DVB_CX22702) += cx22702.o obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o obj-$(CONFIG_DVB_TDA10021) += tda10021.o obj-$(CONFIG_DVB_STV0297) += stv0297.o -obj-$(CONFIG_DVB_NXT2002) += nxt2002.o obj-$(CONFIG_DVB_NXT200X) += nxt200x.o obj-$(CONFIG_DVB_OR51211) += or51211.o obj-$(CONFIG_DVB_OR51132) += or51132.o diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 1b9934ea5b06..9c9c12af5799 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -326,7 +326,7 @@ struct dvb_pll_desc dvb_pll_tuv1236d = { }; EXPORT_SYMBOL(dvb_pll_tuv1236d); -/* Samsung TBMV30111IN +/* Samsung TBMV30111IN / TBMV30712IN1 * used in Air2PC ATSC - 2nd generation (nxt2002) */ struct dvb_pll_desc dvb_pll_tbmv30111in = { diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c deleted file mode 100644 index 4f263e65ba14..000000000000 --- a/drivers/media/dvb/frontends/nxt2002.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - Support for B2C2/BBTI Technisat Air2PC - ATSC - - Copyright (C) 2004 Taylor Jacob - - 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 needs external firmware. Please use the command - * "/Documentation/dvb/get_dvb_firmware nxt2002" to - * download/extract it, and then copy it to /usr/lib/hotplug/firmware - * or /lib/firmware (depending on configuration of firmware hotplug). - */ -#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw" -#define CRC_CCIT_MASK 0x1021 - -#include -#include -#include -#include -#include -#include -#include - -#include "dvb_frontend.h" -#include "nxt2002.h" - -struct nxt2002_state { - - struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; - const struct nxt2002_config* config; - struct dvb_frontend frontend; - - /* demodulator private data */ - u8 initialised:1; -}; - -static int debug; -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG "nxt2002: " args); \ - } while (0) - -static int i2c_writebytes (struct nxt2002_state* state, u8 reg, u8 *buf, u8 len) -{ - /* probbably a much better way or doing this */ - u8 buf2 [256],x; - int err; - struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 }; - - buf2[0] = reg; - for (x = 0 ; x < len ; x++) - buf2[x+1] = buf[x]; - - if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { - printk ("%s: i2c write error (addr %02x, err == %i)\n", - __FUNCTION__, state->config->demod_address, err); - return -EREMOTEIO; - } - - return 0; -} - -static u8 i2c_readbytes (struct nxt2002_state* state, u8 reg, u8* buf, u8 len) -{ - u8 reg2 [] = { reg }; - - struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 }, - { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } }; - - int err; - - if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) { - printk ("%s: i2c read error (addr %02x, err == %i)\n", - __FUNCTION__, state->config->demod_address, err); - return -EREMOTEIO; - } - - return 0; -} - -static u16 nxt2002_crc(u16 crc, u8 c) -{ - - u8 i; - u16 input = (u16) c & 0xFF; - - input<<=8; - for(i=0 ;i<8 ;i++) { - if((crc ^ input) & 0x8000) - crc=(crc<<1)^CRC_CCIT_MASK; - else - crc<<=1; - input<<=1; - } - return crc; -} - -static int nxt2002_writereg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len) -{ - u8 buf; - dprintk("%s\n", __FUNCTION__); - - /* set multi register length */ - i2c_writebytes(state,0x34,&len,1); - - /* set mutli register register */ - i2c_writebytes(state,0x35,®,1); - - /* send the actual data */ - i2c_writebytes(state,0x36,data,len); - - /* toggle the multireg write bit*/ - buf = 0x02; - i2c_writebytes(state,0x21,&buf,1); - - i2c_readbytes(state,0x21,&buf,1); - - if ((buf & 0x02) == 0) - return 0; - - dprintk("Error writing multireg register %02X\n",reg); - - return 0; -} - -static int nxt2002_readreg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len) -{ - u8 len2; - dprintk("%s\n", __FUNCTION__); - - /* set multi register length */ - len2 = len & 0x80; - i2c_writebytes(state,0x34,&len2,1); - - /* set mutli register register */ - i2c_writebytes(state,0x35,®,1); - - /* send the actual data */ - i2c_readbytes(state,reg,data,len); - - return 0; -} - -static void nxt2002_microcontroller_stop (struct nxt2002_state* state) -{ - u8 buf[2],counter = 0; - dprintk("%s\n", __FUNCTION__); - - buf[0] = 0x80; - i2c_writebytes(state,0x22,buf,1); - - while (counter < 20) { - i2c_readbytes(state,0x31,buf,1); - if (buf[0] & 0x40) - return; - msleep(10); - counter++; - } - - dprintk("Timeout waiting for micro to stop.. This is ok after firmware upload\n"); - return; -} - -static void nxt2002_microcontroller_start (struct nxt2002_state* state) -{ - u8 buf; - dprintk("%s\n", __FUNCTION__); - - buf = 0x00; - i2c_writebytes(state,0x22,&buf,1); -} - -static int nxt2002_writetuner (struct nxt2002_state* state, u8* data) -{ - u8 buf,count = 0; - - dprintk("Tuner Bytes: %02X %02X %02X %02X\n",data[0],data[1],data[2],data[3]); - - dprintk("%s\n", __FUNCTION__); - /* stop the micro first */ - nxt2002_microcontroller_stop(state); - - /* set the i2c transfer speed to the tuner */ - buf = 0x03; - i2c_writebytes(state,0x20,&buf,1); - - /* setup to transfer 4 bytes via i2c */ - buf = 0x04; - i2c_writebytes(state,0x34,&buf,1); - - /* write actual tuner bytes */ - i2c_writebytes(state,0x36,data,4); - - /* set tuner i2c address */ - buf = 0xC2; - i2c_writebytes(state,0x35,&buf,1); - - /* write UC Opmode to begin transfer */ - buf = 0x80; - i2c_writebytes(state,0x21,&buf,1); - - while (count < 20) { - i2c_readbytes(state,0x21,&buf,1); - if ((buf & 0x80)== 0x00) - return 0; - msleep(100); - count++; - } - - printk("nxt2002: timeout error writing tuner\n"); - return 0; -} - -static void nxt2002_agc_reset(struct nxt2002_state* state) -{ - u8 buf; - dprintk("%s\n", __FUNCTION__); - - buf = 0x08; - i2c_writebytes(state,0x08,&buf,1); - - buf = 0x00; - i2c_writebytes(state,0x08,&buf,1); - - return; -} - -static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) -{ - - struct nxt2002_state* state = fe->demodulator_priv; - u8 buf[256],written = 0,chunkpos = 0; - u16 rambase,position,crc = 0; - - dprintk("%s\n", __FUNCTION__); - dprintk("Firmware is %zu bytes\n",fw->size); - - /* Get the RAM base for this nxt2002 */ - i2c_readbytes(state,0x10,buf,1); - - if (buf[0] & 0x10) - rambase = 0x1000; - else - rambase = 0x0000; - - dprintk("rambase on this nxt2002 is %04X\n",rambase); - - /* Hold the micro in reset while loading firmware */ - buf[0] = 0x80; - i2c_writebytes(state,0x2B,buf,1); - - for (position = 0; position < fw->size ; position++) { - if (written == 0) { - crc = 0; - chunkpos = 0x28; - buf[0] = ((rambase + position) >> 8); - buf[1] = (rambase + position) & 0xFF; - buf[2] = 0x81; - /* write starting address */ - i2c_writebytes(state,0x29,buf,3); - } - written++; - chunkpos++; - - if ((written % 4) == 0) - i2c_writebytes(state,chunkpos,&fw->data[position-3],4); - - crc = nxt2002_crc(crc,fw->data[position]); - - if ((written == 255) || (position+1 == fw->size)) { - /* write remaining bytes of firmware */ - i2c_writebytes(state, chunkpos+4-(written %4), - &fw->data[position-(written %4) + 1], - written %4); - buf[0] = crc << 8; - buf[1] = crc & 0xFF; - - /* write crc */ - i2c_writebytes(state,0x2C,buf,2); - - /* do a read to stop things */ - i2c_readbytes(state,0x2A,buf,1); - - /* set transfer mode to complete */ - buf[0] = 0x80; - i2c_writebytes(state,0x2B,buf,1); - - written = 0; - } - } - - printk ("done.\n"); - return 0; -}; - -static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe, - struct dvb_frontend_parameters *p) -{ - struct nxt2002_state* state = fe->demodulator_priv; - u32 freq = 0; - u16 tunerfreq = 0; - u8 buf[4]; - - freq = 44000 + ( p->frequency / 1000 ); - - dprintk("freq = %d p->frequency = %d\n",freq,p->frequency); - - tunerfreq = freq * 24/4000; - - buf[0] = (tunerfreq >> 8) & 0x7F; - buf[1] = (tunerfreq & 0xFF); - - if (p->frequency <= 214000000) { - buf[2] = 0x84 + (0x06 << 3); - buf[3] = (p->frequency <= 172000000) ? 0x01 : 0x02; - } else if (p->frequency <= 721000000) { - buf[2] = 0x84 + (0x07 << 3); - buf[3] = (p->frequency <= 467000000) ? 0x02 : 0x08; - } else if (p->frequency <= 841000000) { - buf[2] = 0x84 + (0x0E << 3); - buf[3] = 0x08; - } else { - buf[2] = 0x84 + (0x0F << 3); - buf[3] = 0x02; - } - - /* write frequency information */ - nxt2002_writetuner(state,buf); - - /* reset the agc now that tuning has been completed */ - nxt2002_agc_reset(state); - - /* set target power level */ - switch (p->u.vsb.modulation) { - case QAM_64: - case QAM_256: - buf[0] = 0x74; - break; - case VSB_8: - buf[0] = 0x70; - break; - default: - return -EINVAL; - break; - } - i2c_writebytes(state,0x42,buf,1); - - /* configure sdm */ - buf[0] = 0x87; - i2c_writebytes(state,0x57,buf,1); - - /* write sdm1 input */ - buf[0] = 0x10; - buf[1] = 0x00; - nxt2002_writereg_multibyte(state,0x58,buf,2); - - /* write sdmx input */ - switch (p->u.vsb.modulation) { - case QAM_64: - buf[0] = 0x68; - break; - case QAM_256: - buf[0] = 0x64; - break; - case VSB_8: - buf[0] = 0x60; - break; - default: - return -EINVAL; - break; - } - buf[1] = 0x00; - nxt2002_writereg_multibyte(state,0x5C,buf,2); - - /* write adc power lpf fc */ - buf[0] = 0x05; - i2c_writebytes(state,0x43,buf,1); - - /* write adc power lpf fc */ - buf[0] = 0x05; - i2c_writebytes(state,0x43,buf,1); - - /* write accumulator2 input */ - buf[0] = 0x80; - buf[1] = 0x00; - nxt2002_writereg_multibyte(state,0x4B,buf,2); - - /* write kg1 */ - buf[0] = 0x00; - i2c_writebytes(state,0x4D,buf,1); - - /* write sdm12 lpf fc */ - buf[0] = 0x44; - i2c_writebytes(state,0x55,buf,1); - - /* write agc control reg */ - buf[0] = 0x04; - i2c_writebytes(state,0x41,buf,1); - - /* write agc ucgp0 */ - switch (p->u.vsb.modulation) { - case QAM_64: - buf[0] = 0x02; - break; - case QAM_256: - buf[0] = 0x03; - break; - case VSB_8: - buf[0] = 0x00; - break; - default: - return -EINVAL; - break; - } - i2c_writebytes(state,0x30,buf,1); - - /* write agc control reg */ - buf[0] = 0x00; - i2c_writebytes(state,0x41,buf,1); - - /* write accumulator2 input */ - buf[0] = 0x80; - buf[1] = 0x00; - nxt2002_writereg_multibyte(state,0x49,buf,2); - nxt2002_writereg_multibyte(state,0x4B,buf,2); - - /* write agc control reg */ - buf[0] = 0x04; - i2c_writebytes(state,0x41,buf,1); - - nxt2002_microcontroller_start(state); - - /* adjacent channel detection should be done here, but I don't - have any stations with this need so I cannot test it */ - - return 0; -} - -static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status) -{ - struct nxt2002_state* state = fe->demodulator_priv; - u8 lock; - i2c_readbytes(state,0x31,&lock,1); - - *status = 0; - if (lock & 0x20) { - *status |= FE_HAS_SIGNAL; - *status |= FE_HAS_CARRIER; - *status |= FE_HAS_VITERBI; - *status |= FE_HAS_SYNC; - *status |= FE_HAS_LOCK; - } - return 0; -} - -static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber) -{ - struct nxt2002_state* state = fe->demodulator_priv; - u8 b[3]; - - nxt2002_readreg_multibyte(state,0xE6,b,3); - - *ber = ((b[0] << 8) + b[1]) * 8; - - return 0; -} - -static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength) -{ - struct nxt2002_state* state = fe->demodulator_priv; - u8 b[2]; - u16 temp = 0; - - /* setup to read cluster variance */ - b[0] = 0x00; - i2c_writebytes(state,0xA1,b,1); - - /* get multreg val */ - nxt2002_readreg_multibyte(state,0xA6,b,2); - - temp = (b[0] << 8) | b[1]; - *strength = ((0x7FFF - temp) & 0x0FFF) * 16; - - return 0; -} - -static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr) -{ - - struct nxt2002_state* state = fe->demodulator_priv; - u8 b[2]; - u16 temp = 0, temp2; - u32 snrdb = 0; - - /* setup to read cluster variance */ - b[0] = 0x00; - i2c_writebytes(state,0xA1,b,1); - - /* get multreg val from 0xA6 */ - nxt2002_readreg_multibyte(state,0xA6,b,2); - - temp = (b[0] << 8) | b[1]; - temp2 = 0x7FFF - temp; - - /* snr will be in db */ - if (temp2 > 0x7F00) - snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) ); - else if (temp2 > 0x7EC0) - snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) ); - else if (temp2 > 0x7C00) - snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) ); - else - snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) ); - - /* the value reported back from the frontend will be FFFF=32db 0000=0db */ - - *snr = snrdb * (0xFFFF/32000); - - return 0; -} - -static int nxt2002_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) -{ - struct nxt2002_state* state = fe->demodulator_priv; - u8 b[3]; - - nxt2002_readreg_multibyte(state,0xE6,b,3); - *ucblocks = b[2]; - - return 0; -} - -static int nxt2002_sleep(struct dvb_frontend* fe) -{ - return 0; -} - -static int nxt2002_init(struct dvb_frontend* fe) -{ - struct nxt2002_state* state = fe->demodulator_priv; - const struct firmware *fw; - int ret; - u8 buf[2]; - - if (!state->initialised) { - /* request the firmware, this will block until someone uploads it */ - printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE); - ret = state->config->request_firmware(fe, &fw, NXT2002_DEFAULT_FIRMWARE); - printk("nxt2002: Waiting for firmware upload(2)...\n"); - if (ret) { - printk("nxt2002: no firmware upload (timeout or file not found?)\n"); - return ret; - } - - ret = nxt2002_load_firmware(fe, fw); - if (ret) { - printk("nxt2002: writing firmware to device failed\n"); - release_firmware(fw); - return ret; - } - printk("nxt2002: firmware upload complete\n"); - - /* Put the micro into reset */ - nxt2002_microcontroller_stop(state); - - /* ensure transfer is complete */ - buf[0]=0; - i2c_writebytes(state,0x2B,buf,1); - - /* Put the micro into reset for real this time */ - nxt2002_microcontroller_stop(state); - - /* soft reset everything (agc,frontend,eq,fec)*/ - buf[0] = 0x0F; - i2c_writebytes(state,0x08,buf,1); - buf[0] = 0x00; - i2c_writebytes(state,0x08,buf,1); - - /* write agc sdm configure */ - buf[0] = 0xF1; - i2c_writebytes(state,0x57,buf,1); - - /* write mod output format */ - buf[0] = 0x20; - i2c_writebytes(state,0x09,buf,1); - - /* write fec mpeg mode */ - buf[0] = 0x7E; - buf[1] = 0x00; - i2c_writebytes(state,0xE9,buf,2); - - /* write mux selection */ - buf[0] = 0x00; - i2c_writebytes(state,0xCC,buf,1); - - state->initialised = 1; - } - - return 0; -} - -static int nxt2002_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) -{ - fesettings->min_delay_ms = 500; - fesettings->step_size = 0; - fesettings->max_drift = 0; - return 0; -} - -static void nxt2002_release(struct dvb_frontend* fe) -{ - struct nxt2002_state* state = fe->demodulator_priv; - kfree(state); -} - -static struct dvb_frontend_ops nxt2002_ops; - -struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config, - struct i2c_adapter* i2c) -{ - struct nxt2002_state* state = NULL; - u8 buf [] = {0,0,0,0,0}; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct nxt2002_state), GFP_KERNEL); - if (state == NULL) goto error; - - /* setup the state */ - state->config = config; - state->i2c = i2c; - memcpy(&state->ops, &nxt2002_ops, sizeof(struct dvb_frontend_ops)); - state->initialised = 0; - - /* Check the first 5 registers to ensure this a revision we can handle */ - - i2c_readbytes(state, 0x00, buf, 5); - if (buf[0] != 0x04) goto error; /* device id */ - if (buf[1] != 0x02) goto error; /* fab id */ - if (buf[2] != 0x11) goto error; /* month */ - if (buf[3] != 0x20) goto error; /* year msb */ - if (buf[4] != 0x00) goto error; /* year lsb */ - - /* create dvb_frontend */ - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; - return &state->frontend; - -error: - kfree(state); - return NULL; -} - -static struct dvb_frontend_ops nxt2002_ops = { - - .info = { - .name = "Nextwave nxt2002 VSB/QAM frontend", - .type = FE_ATSC, - .frequency_min = 54000000, - .frequency_max = 860000000, - /* stepsize is just a guess */ - .frequency_stepsize = 166666, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256 - }, - - .release = nxt2002_release, - - .init = nxt2002_init, - .sleep = nxt2002_sleep, - - .set_frontend = nxt2002_setup_frontend_parameters, - .get_tune_settings = nxt2002_get_tune_settings, - - .read_status = nxt2002_read_status, - .read_ber = nxt2002_read_ber, - .read_signal_strength = nxt2002_read_signal_strength, - .read_snr = nxt2002_read_snr, - .read_ucblocks = nxt2002_read_ucblocks, - -}; - -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); - -MODULE_DESCRIPTION("NXT2002 ATSC (8VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver"); -MODULE_AUTHOR("Taylor Jacob"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(nxt2002_attach); diff --git a/drivers/media/dvb/frontends/nxt2002.h b/drivers/media/dvb/frontends/nxt2002.h deleted file mode 100644 index 462301f577ee..000000000000 --- a/drivers/media/dvb/frontends/nxt2002.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - Driver for the Nxt2002 demodulator -*/ - -#ifndef NXT2002_H -#define NXT2002_H - -#include -#include - -struct nxt2002_config -{ - /* the demodulator's i2c address */ - u8 demod_address; - - /* request firmware for device */ - int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); -}; - -extern struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config, - struct i2c_adapter* i2c); - -#endif // NXT2002_H diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index 78d2b93d35b9..9e3535394509 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -1,9 +1,10 @@ /* * Support for NXT2002 and NXT2004 - VSB/QAM * - * Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com) + * Copyright (C) 2005 Kirk Lapray + * Copyright (C) 2006 Michael Krufky * based on nxt2002 by Taylor Jacob - * and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com) + * and nxt2004 by Jean-Francois Thibert * * 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 @@ -614,7 +615,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, /* write sdm1 input */ buf[0] = 0x10; buf[1] = 0x00; - nxt200x_writebytes(state, 0x58, buf, 2); + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x58, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x58, buf, 2); + break; + default: + return -EINVAL; + break; + } /* write sdmx input */ switch (p->u.vsb.modulation) { @@ -632,7 +643,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, break; } buf[1] = 0x00; - nxt200x_writebytes(state, 0x5C, buf, 2); + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x5C, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x5C, buf, 2); + break; + default: + return -EINVAL; + break; + } /* write adc power lpf fc */ buf[0] = 0x05; @@ -648,7 +669,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, /* write accumulator2 input */ buf[0] = 0x80; buf[1] = 0x00; - nxt200x_writebytes(state, 0x4B, buf, 2); + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x4B, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x4B, buf, 2); + break; + default: + return -EINVAL; + break; + } /* write kg1 */ buf[0] = 0x00; @@ -714,8 +745,19 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, /* write accumulator2 input */ buf[0] = 0x80; buf[1] = 0x00; - nxt200x_writebytes(state, 0x49, buf,2); - nxt200x_writebytes(state, 0x4B, buf,2); + switch (state->demod_chip) { + case NXT2002: + nxt200x_writereg_multibyte(state, 0x49, buf, 2); + nxt200x_writereg_multibyte(state, 0x4B, buf, 2); + break; + case NXT2004: + nxt200x_writebytes(state, 0x49, buf, 2); + nxt200x_writebytes(state, 0x4B, buf, 2); + break; + default: + return -EINVAL; + break; + } /* write agc control reg */ buf[0] = 0x04; @@ -1199,7 +1241,7 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); -MODULE_AUTHOR("Kirk Lapray, Jean-Francois Thibert, and Taylor Jacob"); +MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(nxt200x_attach); -- cgit v1.2.3-59-g8ed1b From 28f3d4b37db26a30b8990e039b6881b43de815f9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 23 Jan 2006 17:11:07 -0200 Subject: V4L/DVB (3414): rename dvb_pll_tbmv30111in to dvb_pll_samsung_tbmv - rename dvb_pll_tbmv30111in to dvb_pll_samsung_tbmv Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 2 +- drivers/media/dvb/frontends/dvb-pll.c | 6 +++--- drivers/media/dvb/frontends/dvb-pll.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index dbe6f6b7ee26..390cc3a99ce6 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -346,7 +346,7 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = { static struct nxt200x_config samsung_tbmv_config = { .demod_address = 0x0a, .pll_address = 0xc2, - .pll_desc = &dvb_pll_tbmv30111in, + .pll_desc = &dvb_pll_samsung_tbmv, }; static struct bcm3510_config air2pc_atsc_first_gen_config = { diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 9c9c12af5799..4dcb6050d4fa 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -329,8 +329,8 @@ EXPORT_SYMBOL(dvb_pll_tuv1236d); /* Samsung TBMV30111IN / TBMV30712IN1 * used in Air2PC ATSC - 2nd generation (nxt2002) */ -struct dvb_pll_desc dvb_pll_tbmv30111in = { - .name = "Samsung TBMV30111IN", +struct dvb_pll_desc dvb_pll_samsung_tbmv = { + .name = "Samsung TBMV30111IN / TBMV30712IN1", .min = 54000000, .max = 860000000, .count = 6, @@ -343,7 +343,7 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = { { 999999999, 44000000, 166666, 0xfc, 0x02 }, } }; -EXPORT_SYMBOL(dvb_pll_tbmv30111in); +EXPORT_SYMBOL(dvb_pll_samsung_tbmv); /* * Philips SD1878 Tuner. diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index f682c09189b3..bb8d4b4eb183 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -38,7 +38,7 @@ extern struct dvb_pll_desc dvb_pll_tded4; extern struct dvb_pll_desc dvb_pll_tuv1236d; extern struct dvb_pll_desc dvb_pll_tdhu2; -extern struct dvb_pll_desc dvb_pll_tbmv30111in; +extern struct dvb_pll_desc dvb_pll_samsung_tbmv; extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261; int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, -- cgit v1.2.3-59-g8ed1b From 42d2b6ef40fcf9094d4d55a1a4c8d1c80318271c Mon Sep 17 00:00:00 2001 From: Ian Pickworth Date: Mon, 23 Jan 2006 17:11:07 -0200 Subject: V4L/DVB (3416): Recognise Hauppauge card #34519 - Recognise Hauppauge card #34519 Signed-off-by: Ian Pickworth Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 517257b4d2d4..1bc999247fdc 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1298,6 +1298,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) switch (tv.model) { case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ + case 34519: /* WinTV-PCI-FM */ case 90002: /* Nova-T-PCI (9002) */ case 92001: /* Nova-S-Plus (Video and IR) */ case 92002: /* Nova-S-Plus (Video and IR) */ -- cgit v1.2.3-59-g8ed1b From bff75d248f27c10d4bf1aaf8d5c81b00623861b9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 23 Jan 2006 17:11:07 -0200 Subject: V4L/DVB (3417): make VP-3054 Secondary I2C Bus Support a Kconfig option. - make VP-3054 Secondary I2C Bus Support a Kconfig option. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/Kconfig | 11 +++++++++++ drivers/media/video/cx88/Makefile | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index fdf45f7d05a0..e99dfbbf3e95 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -49,6 +49,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS default y depends on VIDEO_CX88_DVB select DVB_MT352 + select VIDEO_CX88_VP3054 select DVB_OR51132 select DVB_CX22702 select DVB_LGDT330X @@ -70,6 +71,16 @@ config VIDEO_CX88_DVB_MT352 This adds DVB-T support for cards based on the Connexant 2388x chip and the MT352 demodulator. +config VIDEO_CX88_VP3054 + tristate "VP-3054 Secondary I2C Bus Support" + default m + depends on DVB_MT352 + ---help--- + This adds DVB-T support for cards based on the + Connexant 2388x chip and the MT352 demodulator, + which also require support for the VP-3054 + Secondary I2C bus, such at DNTV Live! DVB-T Pro. + config VIDEO_CX88_DVB_OR51132 bool "OR51132 ATSC Support" default y diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 6e5eaa22619e..e78da88501d8 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -18,6 +18,6 @@ extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1 extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1 extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1 extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1 -extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1 +extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1 EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) -- cgit v1.2.3-59-g8ed1b From c835ac24e2e3d5de7fff0620949b61228048e27b Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Mon, 23 Jan 2006 17:11:07 -0200 Subject: V4L/DVB (3418): Cause tda9887 to use I2C_DRIVERID_TDA9887 - The tda9887 has an I2C id reserved for it, but it hasn't been using it. Probably an oversight. Fixed with this patch. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda9887.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 5815649bdc78..7c71422f5d3f 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -876,7 +876,7 @@ static int tda9887_resume(struct device * dev) /* ----------------------------------------------------------------------- */ static struct i2c_driver driver = { - .id = -1, /* FIXME */ + .id = I2C_DRIVERID_TDA9887, .attach_adapter = tda9887_probe, .detach_client = tda9887_detach, .command = tda9887_command, -- cgit v1.2.3-59-g8ed1b From 4d0dddb10723cee2b3048bd2389673703bc228e4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:11:07 -0200 Subject: V4L/DVB (3419): added some VBI macros and moved minor definitions to header file - Moved some hardcoded minor numbers to videodev2.h - Included more comments for sliced VBI standards - Included some VBI macros to group similar standards Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videodev.c | 16 ++++++++-------- include/linux/videodev2.h | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 078880e4c8c0..908fbec776ac 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -279,23 +279,23 @@ int video_register_device(struct video_device *vfd, int type, int nr) switch(type) { case VFL_TYPE_GRABBER: - base=0; - end=64; + base=MINOR_VFL_TYPE_GRABBER_MIN; + end=MINOR_VFL_TYPE_GRABBER_MAX+1; name_base = "video"; break; case VFL_TYPE_VTX: - base=192; - end=224; + base=MINOR_VFL_TYPE_VTX_MIN; + end=MINOR_VFL_TYPE_VTX_MAX+1; name_base = "vtx"; break; case VFL_TYPE_VBI: - base=224; - end=256; + base=MINOR_VFL_TYPE_VBI_MIN; + end=MINOR_VFL_TYPE_VBI_MAX+1; name_base = "vbi"; break; case VFL_TYPE_RADIO: - base=64; - end=128; + base=MINOR_VFL_TYPE_RADIO_MIN; + end=MINOR_VFL_TYPE_RADIO_MAX+1; name_base = "radio"; break; default: diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 27ae3d679cbe..6e33ce96cab0 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -21,7 +21,7 @@ #include /* need __user */ -#define OBSOLETE_OWNER 1 /* It will be removed for 2.6.15 */ +#define OBSOLETE_OWNER 1 /* It will be removed for 2.6.17 */ #define HAVE_V4L2 1 /* @@ -48,6 +48,16 @@ #ifdef __KERNEL__ +/* Minor device allocation */ +#define MINOR_VFL_TYPE_GRABBER_MIN 0 +#define MINOR_VFL_TYPE_GRABBER_MAX 63 +#define MINOR_VFL_TYPE_RADIO_MIN 64 +#define MINOR_VFL_TYPE_RADIO_MAX 127 +#define MINOR_VFL_TYPE_VTX_MIN 192 +#define MINOR_VFL_TYPE_VTX_MAX 223 +#define MINOR_VFL_TYPE_VBI_MIN 224 +#define MINOR_VFL_TYPE_VBI_MAX 255 + #define VFL_TYPE_GRABBER 0 #define VFL_TYPE_VBI 1 #define VFL_TYPE_RADIO 2 @@ -949,13 +959,15 @@ struct v4l2_sliced_vbi_format __u32 reserved[2]; /* must be zero */ }; -/* Teletext WST, defined on ITU-R BT.653-2 */ +/* Teletext World System Teletext + (WST), defined on ITU-R BT.653-2 */ #define V4L2_SLICED_TELETEXT_PAL_B (0x000001) #define V4L2_SLICED_TELETEXT_PAL_C (0x000002) #define V4L2_SLICED_TELETEXT_NTSC_B (0x000010) #define V4L2_SLICED_TELETEXT_SECAM (0x000020) -/* Teletext NABTS, defined on ITU-R BT.653-2 */ +/* Teletext North American Broadcast Teletext Specification + (NABTS), defined on ITU-R BT.653-2 */ #define V4L2_SLICED_TELETEXT_NTSC_C (0x000040) #define V4L2_SLICED_TELETEXT_NTSC_D (0x000080) @@ -976,8 +988,24 @@ struct v4l2_sliced_vbi_format #define V4l2_SLICED_VITC_625 (0x010000) #define V4l2_SLICED_VITC_525 (0x020000) -/* Compat macro - Should be removed for 2.6.18 */ -#define V4L2_SLICED_TELETEXT_B V4L2_SLICED_TELETEXT_PAL_B +#define V4L2_SLICED_TELETEXT_B (V4L2_SLICED_TELETEXT_PAL_B |\ + V4L2_SLICED_TELETEXT_NTSC_B) + +#define V4L2_SLICED_TELETEXT (V4L2_SLICED_TELETEXT_PAL_B |\ + V4L2_SLICED_TELETEXT_PAL_C |\ + V4L2_SLICED_TELETEXT_SECAM |\ + V4L2_SLICED_TELETEXT_NTSC_B |\ + V4L2_SLICED_TELETEXT_NTSC_C |\ + V4L2_SLICED_TELETEXT_NTSC_D) + +#define V4L2_SLICED_CAPTION (V4L2_SLICED_CAPTION_525 |\ + V4L2_SLICED_CAPTION_625) + +#define V4L2_SLICED_WSS (V4L2_SLICED_WSS_525 |\ + V4L2_SLICED_WSS_625) + +#define V4L2_SLICED_VITC (V4L2_SLICED_VITC_525 |\ + V4L2_SLICED_VITC_625) #define V4L2_SLICED_VBI_525 (V4L2_SLICED_TELETEXT_NTSC_B |\ V4L2_SLICED_TELETEXT_NTSC_C |\ -- cgit v1.2.3-59-g8ed1b From 12db56071b473a59c550d0aa70db6972a49d73af Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:11:08 -0200 Subject: V4L/DVB (3420): Added iocls to configure VBI on tvp5150 - Added iocls to configure VBI on tvp5150 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp5150.c | 70 +++++++++++++++++++++++++++++++++++++++++-- include/media/v4l2-common.h | 3 +- 2 files changed, 70 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index df7f304416c9..20e63593e441 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -541,7 +541,7 @@ static struct i2c_vbi_ram_value vbi_ram_default[] = 0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 } }, {0x110, /* Wide Screen Signal, PAL/SECAM */ - {V4L2_SLICED_WSS_625,20,21,1}, + {V4L2_SLICED_WSS_625,23,23,1}, { 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42, 0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 } }, @@ -649,7 +649,7 @@ static int tvp5150_set_vbi(struct i2c_client *c, if (std == V4L2_STD_ALL) { tvp5150_err("VBI can't be configured without knowing number of lines\n"); - return -EINVAL; + return 0; } else if (std && V4L2_STD_625_50) { /* Don't follow NTSC Line number convension */ line += 3; @@ -686,6 +686,37 @@ static int tvp5150_set_vbi(struct i2c_client *c, return type; } +static int tvp5150_get_vbi(struct i2c_client *c, + const struct i2c_vbi_ram_value *regs, int line) +{ + struct tvp5150 *decoder = i2c_get_clientdata(c); + v4l2_std_id std=decoder->norm; + u8 reg; + int pos, type=0; + + if (std == V4L2_STD_ALL) { + tvp5150_err("VBI can't be configured without knowing number of lines\n"); + return 0; + } else if (std && V4L2_STD_625_50) { + /* Don't follow NTSC Line number convension */ + line += 3; + } + + if (line<6||line>27) + return 0; + + reg=((line-6)<<1)+TVP5150_LINE_MODE_INI; + + pos=tvp5150_read(c, reg)&0x0f; + if (pos<0x0f) + type=regs[pos].type.vbi_type; + + pos=tvp5150_read(c, reg+1)&0x0f; + if (pos<0x0f) + type|=regs[pos].type.vbi_type; + + return type; +} static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std) { struct tvp5150 *decoder = i2c_get_clientdata(c); @@ -856,9 +887,43 @@ static int tvp5150_command(struct i2c_client *c, vbi_ram_default, svbi->service_lines[0][i],0xf0,i,3); } + /* Enables FIFO */ + tvp5150_write(c, TVP5150_FIFO_OUT_CTRL,1); + } else { + /* Disables FIFO*/ + tvp5150_write(c, TVP5150_FIFO_OUT_CTRL,0); + + /* Disable Full Field */ + tvp5150_write(c, TVP5150_FULL_FIELD_ENA, 0); + + /* Disable Line modes */ + for (i=TVP5150_LINE_MODE_INI; i<=TVP5150_LINE_MODE_END; i++) + tvp5150_write(c, i, 0xff); + } + break; + } + case VIDIOC_G_FMT: + { + struct v4l2_format *fmt; + struct v4l2_sliced_vbi_format *svbi; + + int i, mask=0; + + fmt = arg; + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + memset(svbi, 0, sizeof(*svbi)); + + for (i = 0; i <= 23; i++) { + svbi->service_lines[0][i]=tvp5150_get_vbi(c, + vbi_ram_default,i); + mask|=svbi->service_lines[0][i]; } + svbi->service_set=mask; break; } + #ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_INT_G_REGISTER: { @@ -883,6 +948,7 @@ static int tvp5150_command(struct i2c_client *c, } #endif + case VIDIOC_LOG_STATUS: case DECODER_DUMP: dump_reg(c); break; diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index d4030a7e16e0..11728daf0096 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -160,7 +160,8 @@ struct msp_matrix { /* Used to generate VBI signals on a video signal. v4l2_sliced_vbi_data is filled with the data packets that should be output. Note that if you set - the line field to 0, then that VBI signal is disabled. */ + the line field to 0, then that VBI signal is disabled. If no + valid VBI data was found, then the type field is set to 0 on return. */ #define VIDIOC_INT_S_VBI_DATA _IOW ('d', 105, struct v4l2_sliced_vbi_data) /* Used to obtain the sliced VBI packet from a readback register. Not all -- cgit v1.2.3-59-g8ed1b From e5589befc472ca50882f37c4fb32333fc93a65b7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:11:08 -0200 Subject: V4L/DVB (3421): Several fixes to prepare for VBI - Fixed VBI compilation. - Included capacity to specify vbi and video number. - Added a better control for using more than one em28xx device. - VIDIOC_G_FMT now calls a function. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 256 +++++++++++++++++++++--------- drivers/media/video/em28xx/em28xx.h | 1 + 2 files changed, 181 insertions(+), 76 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 94a14a2bb6d6..e4e82ae716bf 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -59,8 +60,14 @@ MODULE_LICENSE("GPL"); static LIST_HEAD(em28xx_devlist); static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; +static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; +static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); +module_param_array(video_nr, int, NULL, 0444); +module_param_array(vbi_nr, int, NULL, 0444); MODULE_PARM_DESC(card,"card type"); +MODULE_PARM_DESC(video_nr,"video device numbers"); +MODULE_PARM_DESC(vbi_nr,"vbi device numbers"); static int tuner = -1; module_param(tuner, int, 0444); @@ -70,6 +77,9 @@ static unsigned int video_debug = 0; module_param(video_debug,int,0644); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); +/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ +static unsigned long em28xx_devused; + /* supported tv norms */ static struct em28xx_tvnorm tvnorms[] = { { @@ -211,6 +221,11 @@ static int em28xx_config(struct em28xx *dev) em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); /* enable vbi capturing */ + + em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); + em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); + em28xx_write_regs_req(dev,0x00,0x11,"\x51",1); + em28xx_audio_usb_mute(dev, 1); dev->mute = 1; /* maybe not the right place... */ dev->volume = 0x1f; @@ -323,13 +338,20 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) h = list_entry(list, struct em28xx, devlist); if (h->vdev->minor == minor) { dev = h; + dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + if (h->vbi_dev->minor == minor) { + dev = h; + dev->type = V4L2_BUF_TYPE_VBI_CAPTURE; } } + if (NULL == dev) + return -ENODEV; filp->private_data=dev; - - em28xx_videodbg("users=%d\n", dev->users); + em28xx_videodbg("open minor=%d type=%s users=%d\n", + minor,v4l2_type_names[dev->type],dev->users); if (!down_read_trylock(&em28xx_disconnect)) return -ERESTARTSYS; @@ -340,13 +362,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) return -EBUSY; } -/* if(dev->vbi_dev->minor == minor){ - dev->type=V4L2_BUF_TYPE_VBI_CAPTURE; - }*/ - if (dev->vdev->minor == minor) { - dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - init_MUTEX(&dev->fileop_lock); /* to 1 == available */ spin_lock_init(&dev->queue_lock); init_waitqueue_head(&dev->wait_frame); @@ -354,23 +369,27 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) down(&dev->lock); - em28xx_set_alternate(dev); + if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + em28xx_set_alternate(dev); - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); - dev->frame_size = dev->width * dev->height * 2; - dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ - dev->bytesperline = dev->width * 2; - dev->hscale = 0; - dev->vscale = 0; + dev->width = norm_maxw(dev); + dev->height = norm_maxh(dev); + dev->frame_size = dev->width * dev->height * 2; + dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ + dev->bytesperline = dev->width * 2; + dev->hscale = 0; + dev->vscale = 0; - em28xx_capture_start(dev, 1); - em28xx_resolution_set(dev); + em28xx_capture_start(dev, 1); + em28xx_resolution_set(dev); - /* start the transfer */ - errCode = em28xx_init_isoc(dev); - if (errCode) - goto err; + /* start the transfer */ + errCode = em28xx_init_isoc(dev); + if (errCode) + goto err; + + video_mux(dev, 0); + } dev->users++; filp->private_data = dev; @@ -383,8 +402,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev->state |= DEV_INITIALIZED; - video_mux(dev, 0); - err: up(&dev->lock); up_read(&em28xx_disconnect); @@ -400,14 +417,21 @@ static void em28xx_release_resources(struct em28xx *dev) { mutex_lock(&em28xx_sysfs_lock); - em28xx_info("V4L2 device /dev/video%d deregistered\n", - dev->vdev->minor); + /*FIXME: I2C IR should be disconnected */ + + em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n", + dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, + dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); list_del(&dev->devlist); video_unregister_device(dev->vdev); -/* video_unregister_device(dev->vbi_dev); */ + video_unregister_device(dev->vbi_dev); em28xx_i2c_unregister(dev); usb_put_dev(dev->udev); mutex_unlock(&em28xx_sysfs_lock); + + + /* Mark device as unused */ + em28xx_devused&=~(1<devno); } /* @@ -463,6 +487,28 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, int ret = 0; struct em28xx *dev = filp->private_data; + if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + em28xx_videodbg("V4l2_Buf_type_videocapture is set\n"); + } + if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n"); + em28xx_videodbg("not supported yet! ...\n"); + if (copy_to_user(buf, "", 1)) { + up(&dev->fileop_lock); + return -EFAULT; + } + return (1); + } + if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { + em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n"); + em28xx_videodbg("not supported yet! ...\n"); + if (copy_to_user(buf, "", 1)) { + up(&dev->fileop_lock); + return -EFAULT; + } + return (1); + } + if (down_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; @@ -799,7 +845,8 @@ static int em28xx_stream_interrupt(struct em28xx *dev) else if (ret) { dev->state |= DEV_MISCONFIGURED; em28xx_videodbg("device is misconfigured; close and " - "open /dev/video%d again\n", dev->vdev->minor); + "open /dev/video%d again\n", + dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN); return ret; } @@ -850,6 +897,36 @@ static int em28xx_set_norm(struct em28xx *dev, int width, int height) return 0; } + +static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format) +{ + em28xx_videodbg("VIDIOC_G_FMT: type=%s\n", + (format->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE) ? + "V4L2_BUF_TYPE_VIDEO_CAPTURE" : + (format->type ==V4L2_BUF_TYPE_VBI_CAPTURE) ? + "V4L2_BUF_TYPE_VBI_CAPTURE" : + (format->type ==V4L2_CAP_SLICED_VBI_CAPTURE) ? + "V4L2_BUF_TYPE_SLICED_VBI_CAPTURE " : + "not supported"); + + if (format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + format->fmt.pix.width = dev->width; + format->fmt.pix.height = dev->height; + format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + format->fmt.pix.bytesperline = dev->bytesperline; + format->fmt.pix.sizeimage = dev->frame_size; + format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ + + em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width, + dev->height); + return 0; + } + + return -EINVAL; +} + + /* * em28xx_v4l2_do_ioctl() * This function is _not_ called directly, but from @@ -1290,6 +1367,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, sizeof(cap->bus_info)); cap->version = EM28XX_VERSION_CODE; cap->capabilities = + V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; @@ -1314,32 +1392,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, } case VIDIOC_G_FMT: - { - struct v4l2_format *format = arg; - - em28xx_videodbg("VIDIOC_G_FMT: type=%s\n", - format->type == - V4L2_BUF_TYPE_VIDEO_CAPTURE ? - "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type == - V4L2_BUF_TYPE_VBI_CAPTURE ? - "V4L2_BUF_TYPE_VBI_CAPTURE " : - "not supported"); - - if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - format->fmt.pix.width = dev->width; - format->fmt.pix.height = dev->height; - format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - format->fmt.pix.bytesperline = dev->bytesperline; - format->fmt.pix.sizeimage = dev->frame_size; - format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ - - em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width, - dev->height); - return 0; - } + return em28xx_get_fmt(dev, (struct v4l2_format *) arg); case VIDIOC_TRY_FMT: case VIDIOC_S_FMT: @@ -1741,6 +1794,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, if (errCode) { em28xx_errdev("error configuring device\n"); kfree(dev); + em28xx_devused&=~(1<devno); return -ENOMEM; } @@ -1767,9 +1821,30 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, if (NULL == dev->vdev) { em28xx_errdev("cannot allocate video_device.\n"); kfree(dev); + em28xx_devused&=~(1<devno); + return -ENOMEM; + } + + dev->vbi_dev = video_device_alloc(); + if (NULL == dev->vbi_dev) { + em28xx_errdev("cannot allocate video_device.\n"); + kfree(dev->vdev); + kfree(dev); + em28xx_devused&=~(1<devno); return -ENOMEM; } + /* Fills VBI device info */ + dev->vbi_dev->type = VFL_TYPE_VBI; + dev->vbi_dev->hardware = 0; + dev->vbi_dev->fops = &em28xx_v4l_fops; + dev->vbi_dev->minor = -1; + dev->vbi_dev->dev = &dev->udev->dev; + dev->vbi_dev->release = video_device_release; + snprintf(dev->vbi_dev->name, sizeof(dev->vbi_dev->name), "%s#%d %s", + "em28xx",dev->devno,"vbi"); + + /* Fills CAPTURE device info */ dev->vdev->type = VID_TYPE_CAPTURE; if (dev->has_tuner) dev->vdev->type |= VID_TYPE_TUNER; @@ -1778,21 +1853,39 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->vdev->minor = -1; dev->vdev->dev = &dev->udev->dev; dev->vdev->release = video_device_release; - snprintf(dev->vdev->name, sizeof(dev->vdev->name), "%s", - "em28xx video"); + snprintf(dev->vdev->name, sizeof(dev->vbi_dev->name), "%s#%d %s", + "em28xx",dev->devno,"video"); + list_add_tail(&dev->devlist,&em28xx_devlist); /* register v4l2 device */ down(&dev->lock); - if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1))) { + if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, + video_nr[dev->devno]))) { em28xx_errdev("unable to register video device (error=%i).\n", retval); up(&dev->lock); list_del(&dev->devlist); video_device_release(dev->vdev); kfree(dev); + em28xx_devused&=~(1<devno); return -ENODEV; } + + if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, + vbi_nr[dev->devno]) < 0) { + printk("unable to register vbi device\n"); + up(&dev->lock); + list_del(&dev->devlist); + video_device_release(dev->vbi_dev); + video_device_release(dev->vdev); + kfree(dev); + em28xx_devused&=~(1<devno); + return -ENODEV; + } else { + printk("registered VBI\n"); + } + if (dev->has_msp34xx) { /* Send a reset to other chips via gpio */ em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); @@ -1805,8 +1898,9 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, up(&dev->lock); - em28xx_info("V4L2 device registered as /dev/video%d\n", - dev->vdev->minor); + em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", + dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, + dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); return 0; } @@ -1828,6 +1922,9 @@ static int em28xx_usb_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); ifnum = interface->altsetting[0].desc.bInterfaceNumber; + /* Check to see next free device and mark as used */ + nr=find_first_zero_bit(&em28xx_devused,EM28XX_MAXBOARDS); + em28xx_devused|=1<altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { @@ -1835,6 +1932,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, udev->descriptor.idVendor,udev->descriptor.idProduct, ifnum, interface->altsetting[0].desc.bInterfaceClass); + + em28xx_devused&=~(1<bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); + em28xx_devused&=~(1<bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); + em28xx_devused&=~(1<driver_info; - nr=interface->minor; - if (nr>EM28XX_MAXBOARDS) { + if (nr > EM28XX_MAXBOARDS) { printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS); + em28xx_devused&=~(1<name, 29, "em28xx #%d", nr); + dev->devno=nr; + /* compute alternate max packet sizes */ uif = udev->actconfig->interface[0]; dev->num_alt=uif->num_altsetting; - printk(DRIVER_NAME ": Alternate settings: %i\n",dev->num_alt); + em28xx_info("Alternate settings: %i\n",dev->num_alt); // dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* dev->alt_max_pkt_size = kmalloc(32* dev->num_alt,GFP_KERNEL); if (dev->alt_max_pkt_size == NULL) { - em28xx_err(DRIVER_NAME ": out of memory!\n"); + em28xx_errdev("out of memory!\n"); + em28xx_devused&=~(1<alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - printk(DRIVER_NAME ": Alternate setting %i, max size= %i\n",i, + em28xx_info("Alternate setting %i, max size= %i\n",i, dev->alt_max_pkt_size[i]); } - snprintf(dev->name, 29, "em28xx #%d", nr); - if ((card[nr]>=0)&&(card[nr] insmod option to\n" "%s: workaround that. Redirect complaints to the vendor of\n" - "%s: the TV card. Best regards,\n" + "%s: the TV card. Generic type will be used." + "%s: Best regards,\n" "%s: -- tux\n", dev->name,dev->name,dev->name,dev->name,dev->name); - printk("%s: Here is a list of valid choices for the card= insmod option:\n", + em28xx_errdev("%s: Here is a list of valid choices for the card= insmod option:\n", dev->name); for (i = 0; i < em28xx_bcount; i++) { - printk("%s: card=%d -> %s\n", - dev->name, i, em28xx_boards[i].name); + em28xx_errdev(" card=%d -> %s\n", i, + em28xx_boards[i].name); } } @@ -1935,12 +2040,9 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) struct em28xx *dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); -/*FIXME: IR should be disconnected */ - if (!dev) return; - down_write(&em28xx_disconnect); down(&dev->lock); @@ -1952,7 +2054,9 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) if (dev->users) { em28xx_warn ("device /dev/video%d is open! Deregistration and memory " - "deallocation are deferred on close.\n", dev->vdev->minor); + "deallocation are deferred on close.\n", + dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN); + dev->state |= DEV_MISCONFIGURED; em28xx_uninit_isoc(dev); dev->state |= DEV_DISCONNECTED; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 33de9d846af5..119fdbedc7bf 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -209,6 +209,7 @@ struct em28xx { /* generic device properties */ char name[30]; /* name (including minor) of the device */ int model; /* index in the device_data struct */ + int devno; /* marks the number of this device */ unsigned int is_em2800; int video_inputs; /* number of video inputs */ struct list_head devlist; -- cgit v1.2.3-59-g8ed1b From 2d50f847c62acbafa25dc690d0fe65b8b908a326 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:11:08 -0200 Subject: V4L/DVB (3422): Implemented VIDIOC_G_FMT/S_FMT for sliced VBI - Implemented VIDIOC_G_FMT/S_FMT for sliced VBI - VIDIOC_S_FMT now calls a function Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 308 +++++++++++++++--------------- 1 file changed, 155 insertions(+), 153 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index e4e82ae716bf..d8d02c44c9d2 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -897,7 +897,6 @@ static int em28xx_set_norm(struct em28xx *dev, int width, int height) return 0; } - static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format) { em28xx_videodbg("VIDIOC_G_FMT: type=%s\n", @@ -909,7 +908,9 @@ static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format) "V4L2_BUF_TYPE_SLICED_VBI_CAPTURE " : "not supported"); - if (format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + switch (format->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + { format->fmt.pix.width = dev->width; format->fmt.pix.height = dev->height; format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; @@ -920,12 +921,161 @@ static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format) em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width, dev->height); - return 0; + break; + } + + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + { + format->fmt.sliced.service_set=0; + + em28xx_i2c_call_clients(dev,VIDIOC_G_FMT,format); + + if (format->fmt.sliced.service_set==0) + return -EINVAL; + + break; } - return -EINVAL; + default: + return -EINVAL; + } + return (0); } +static int em28xx_set_fmt(struct em28xx *dev, unsigned int cmd, struct v4l2_format *format) +{ + u32 i; + int ret = 0; + int width = format->fmt.pix.width; + int height = format->fmt.pix.height; + unsigned int hscale, vscale; + unsigned int maxh, maxw; + + maxw = norm_maxw(dev); + maxh = norm_maxh(dev); + + em28xx_videodbg("%s: type=%s\n", + cmd == VIDIOC_TRY_FMT ? + "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", + format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? + "V4L2_BUF_TYPE_VIDEO_CAPTURE" : + format->type == V4L2_BUF_TYPE_VBI_CAPTURE ? + "V4L2_BUF_TYPE_VBI_CAPTURE " : + "not supported"); + + if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { + em28xx_i2c_call_clients(dev,VIDIOC_G_FMT,format); + + if (format->fmt.sliced.service_set==0) + return -EINVAL; + + return 0; + } + + + if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + em28xx_videodbg("%s: requested %dx%d\n", + cmd == VIDIOC_TRY_FMT ? + "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", + format->fmt.pix.width, format->fmt.pix.height); + + /* FIXME: Move some code away from here */ + /* width must even because of the YUYV format */ + /* height must be even because of interlacing */ + height &= 0xfffe; + width &= 0xfffe; + + if (height < 32) + height = 32; + if (height > maxh) + height = maxh; + if (width < 48) + width = 48; + if (width > maxw) + width = maxw; + + if(dev->is_em2800){ + /* the em2800 can only scale down to 50% */ + if(height % (maxh / 2)) + height=maxh; + if(width % (maxw / 2)) + width=maxw; + /* according to empiatech support */ + /* the MaxPacketSize is to small to support */ + /* framesizes larger than 640x480 @ 30 fps */ + /* or 640x576 @ 25 fps. As this would cut */ + /* of a part of the image we prefer */ + /* 360x576 or 360x480 for now */ + if(width == maxw && height == maxh) + width /= 2; + } + + if ((hscale = + (((unsigned long)maxw) << 12) / width - 4096L) >= + 0x4000) + hscale = 0x3fff; + width = + (((unsigned long)maxw) << 12) / (hscale + 4096L); + + if ((vscale = + (((unsigned long)maxh) << 12) / height - 4096L) >= + 0x4000) + vscale = 0x3fff; + height = + (((unsigned long)maxh) << 12) / (vscale + 4096L); + + format->fmt.pix.width = width; + format->fmt.pix.height = height; + format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + format->fmt.pix.bytesperline = width * 2; + format->fmt.pix.sizeimage = width * 2 * height; + format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + format->fmt.pix.field = V4L2_FIELD_INTERLACED; + + em28xx_videodbg("%s: returned %dx%d (%d, %d)\n", + cmd == + VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : + "VIDIOC_S_FMT", format->fmt.pix.width, + format->fmt.pix.height, hscale, vscale); + + if (cmd == VIDIOC_TRY_FMT) + return 0; + + for (i = 0; i < dev->num_frames; i++) + if (dev->frame[i].vma_use_count) { + em28xx_videodbg("VIDIOC_S_FMT failed. " + "Unmap the buffers first.\n"); + return -EINVAL; + } + + /* stop io in case it is already in progress */ + if (dev->stream == STREAM_ON) { + em28xx_videodbg("VIDIOC_SET_FMT: interupting stream\n"); + if ((ret = em28xx_stream_interrupt(dev))) + return ret; + } + + em28xx_release_buffers(dev); + dev->io = IO_NONE; + + /* set new image size */ + dev->width = width; + dev->height = height; + dev->frame_size = dev->width * dev->height * 2; + dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ + dev->bytesperline = dev->width * 2; + dev->hscale = hscale; + dev->vscale = vscale; + em28xx_uninit_isoc(dev); + em28xx_set_alternate(dev); + em28xx_capture_start(dev, 1); + em28xx_resolution_set(dev); + em28xx_init_isoc(dev); + + return 0; +} /* * em28xx_v4l2_do_ioctl() @@ -983,24 +1133,6 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, em28xx_set_norm(dev, dev->width, dev->height); -/* - dev->width=norm_maxw(dev); - dev->height=norm_maxh(dev); - dev->frame_size=dev->width*dev->height*2; - dev->field_size=dev->frame_size>>1; - dev->bytesperline=dev->width*2; - dev->hscale=0; - dev->vscale=0; - - em28xx_resolution_set(dev); -*/ -/* - em28xx_uninit_isoc(dev); - em28xx_set_alternate(dev); - em28xx_capture_start(dev, 1); - em28xx_resolution_set(dev); - em28xx_init_isoc(dev); -*/ em28xx_i2c_call_clients(dev, DECODER_SET_NORM, &tvnorms[i].mode); em28xx_i2c_call_clients(dev, VIDIOC_S_STD, @@ -1396,138 +1528,8 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, case VIDIOC_TRY_FMT: case VIDIOC_S_FMT: - { - struct v4l2_format *format = arg; - u32 i; - int ret = 0; - int width = format->fmt.pix.width; - int height = format->fmt.pix.height; - unsigned int hscale, vscale; - unsigned int maxh, maxw; - - maxw = norm_maxw(dev); - maxh = norm_maxh(dev); - -/* int both_fields; */ - - em28xx_videodbg("%s: type=%s\n", - cmd == - VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : - "VIDIOC_S_FMT", - format->type == - V4L2_BUF_TYPE_VIDEO_CAPTURE ? - "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type == - V4L2_BUF_TYPE_VBI_CAPTURE ? - "V4L2_BUF_TYPE_VBI_CAPTURE " : - "not supported"); - - if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - em28xx_videodbg("%s: requested %dx%d\n", - cmd == - VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : - "VIDIOC_S_FMT", format->fmt.pix.width, - format->fmt.pix.height); - - /* FIXME: Move some code away from here */ - /* width must even because of the YUYV format */ - /* height must be even because of interlacing */ - height &= 0xfffe; - width &= 0xfffe; - - if (height < 32) - height = 32; - if (height > maxh) - height = maxh; - if (width < 48) - width = 48; - if (width > maxw) - width = maxw; - - if(dev->is_em2800){ - /* the em2800 can only scale down to 50% */ - if(height % (maxh / 2)) - height=maxh; - if(width % (maxw / 2)) - width=maxw; - /* according to empiatech support */ - /* the MaxPacketSize is to small to support */ - /* framesizes larger than 640x480 @ 30 fps */ - /* or 640x576 @ 25 fps. As this would cut */ - /* of a part of the image we prefer */ - /* 360x576 or 360x480 for now */ - if(width == maxw && height == maxh) - width /= 2; - } - - if ((hscale = - (((unsigned long)maxw) << 12) / width - 4096L) >= - 0x4000) - hscale = 0x3fff; - width = - (((unsigned long)maxw) << 12) / (hscale + 4096L); - - if ((vscale = - (((unsigned long)maxh) << 12) / height - 4096L) >= - 0x4000) - vscale = 0x3fff; - height = - (((unsigned long)maxh) << 12) / (vscale + 4096L); - - format->fmt.pix.width = width; - format->fmt.pix.height = height; - format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - format->fmt.pix.bytesperline = width * 2; - format->fmt.pix.sizeimage = width * 2 * height; - format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - format->fmt.pix.field = V4L2_FIELD_INTERLACED; - - em28xx_videodbg("%s: returned %dx%d (%d, %d)\n", - cmd == - VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : - "VIDIOC_S_FMT", format->fmt.pix.width, - format->fmt.pix.height, hscale, vscale); - - if (cmd == VIDIOC_TRY_FMT) - return 0; - - for (i = 0; i < dev->num_frames; i++) - if (dev->frame[i].vma_use_count) { - em28xx_videodbg("VIDIOC_S_FMT failed. " - "Unmap the buffers first.\n"); - return -EINVAL; - } - - /* stop io in case it is already in progress */ - if (dev->stream == STREAM_ON) { - em28xx_videodbg("VIDIOC_SET_FMT: interupting stream\n"); - if ((ret = em28xx_stream_interrupt(dev))) - return ret; - } - - em28xx_release_buffers(dev); - dev->io = IO_NONE; - - /* set new image size */ - dev->width = width; - dev->height = height; - dev->frame_size = dev->width * dev->height * 2; - dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ - dev->bytesperline = dev->width * 2; - dev->hscale = hscale; - dev->vscale = vscale; -/* dev->both_fileds = both_fileds; */ - em28xx_uninit_isoc(dev); - em28xx_set_alternate(dev); - em28xx_capture_start(dev, 1); - em28xx_resolution_set(dev); - em28xx_init_isoc(dev); - - return 0; - } + return em28xx_set_fmt(dev, cmd, (struct v4l2_format *)arg); - /* --- streaming capture ------------------------------------- */ case VIDIOC_REQBUFS: { struct v4l2_requestbuffers *rb = arg; -- cgit v1.2.3-59-g8ed1b From 9aeb4b051b65c0248ea6589096950413c4da9d63 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Jan 2006 17:11:09 -0200 Subject: V4L/DVB (3423): CodingStyle fixes. - CodingStyle fixes. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 869 +++++++++++++++--------------- 1 file changed, 427 insertions(+), 442 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index d8d02c44c9d2..1b0e10d5edd4 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1012,19 +1012,15 @@ static int em28xx_set_fmt(struct em28xx *dev, unsigned int cmd, struct v4l2_form width /= 2; } - if ((hscale = - (((unsigned long)maxw) << 12) / width - 4096L) >= - 0x4000) + if ((hscale = (((unsigned long)maxw) << 12) / width - 4096L) >= 0x4000) hscale = 0x3fff; - width = - (((unsigned long)maxw) << 12) / (hscale + 4096L); - if ((vscale = - (((unsigned long)maxh) << 12) / height - 4096L) >= - 0x4000) + width = (((unsigned long)maxw) << 12) / (hscale + 4096L); + + if ((vscale = (((unsigned long)maxh) << 12) / height - 4096L) >= 0x4000) vscale = 0x3fff; - height = - (((unsigned long)maxh) << 12) / (vscale + 4096L); + + height = (((unsigned long)maxh) << 12) / (vscale + 4096L); format->fmt.pix.width = width; format->fmt.pix.height = height; @@ -1035,10 +1031,9 @@ static int em28xx_set_fmt(struct em28xx *dev, unsigned int cmd, struct v4l2_form format->fmt.pix.field = V4L2_FIELD_INTERLACED; em28xx_videodbg("%s: returned %dx%d (%d, %d)\n", - cmd == - VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : - "VIDIOC_S_FMT", format->fmt.pix.width, - format->fmt.pix.height, hscale, vscale); + cmd == VIDIOC_TRY_FMT ? + "VIDIOC_TRY_FMT" :"VIDIOC_S_FMT", + format->fmt.pix.width, format->fmt.pix.height, hscale, vscale); if (cmd == VIDIOC_TRY_FMT) return 0; @@ -1064,7 +1059,7 @@ static int em28xx_set_fmt(struct em28xx *dev, unsigned int cmd, struct v4l2_form dev->width = width; dev->height = height; dev->frame_size = dev->width * dev->height * 2; - dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ + dev->field_size = dev->frame_size >> 1; dev->bytesperline = dev->width * 2; dev->hscale = hscale; dev->vscale = vscale; @@ -1092,374 +1087,367 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, switch (cmd) { /* ---------- tv norms ---------- */ case VIDIOC_ENUMSTD: - { - struct v4l2_standard *e = arg; - unsigned int i; + { + struct v4l2_standard *e = arg; + unsigned int i; - i = e->index; - if (i >= TVNORMS) - return -EINVAL; - ret = v4l2_video_std_construct(e, tvnorms[e->index].id, - tvnorms[e->index].name); - e->index = i; - if (ret < 0) - return ret; - return 0; - } + i = e->index; + if (i >= TVNORMS) + return -EINVAL; + ret = v4l2_video_std_construct(e, tvnorms[e->index].id, + tvnorms[e->index].name); + e->index = i; + if (ret < 0) + return ret; + return 0; + } case VIDIOC_G_STD: - { - v4l2_std_id *id = arg; + { + v4l2_std_id *id = arg; - *id = dev->tvnorm->id; - return 0; - } + *id = dev->tvnorm->id; + return 0; + } case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; - unsigned int i; + { + v4l2_std_id *id = arg; + unsigned int i; + for (i = 0; i < TVNORMS; i++) + if (*id == tvnorms[i].id) + break; + if (i == TVNORMS) for (i = 0; i < TVNORMS; i++) - if (*id == tvnorms[i].id) + if (*id & tvnorms[i].id) break; - if (i == TVNORMS) - for (i = 0; i < TVNORMS; i++) - if (*id & tvnorms[i].id) - break; - if (i == TVNORMS) - return -EINVAL; + if (i == TVNORMS) + return -EINVAL; - down(&dev->lock); - dev->tvnorm = &tvnorms[i]; + down(&dev->lock); + dev->tvnorm = &tvnorms[i]; - em28xx_set_norm(dev, dev->width, dev->height); + em28xx_set_norm(dev, dev->width, dev->height); - em28xx_i2c_call_clients(dev, DECODER_SET_NORM, - &tvnorms[i].mode); - em28xx_i2c_call_clients(dev, VIDIOC_S_STD, - &dev->tvnorm->id); + em28xx_i2c_call_clients(dev, DECODER_SET_NORM, + &tvnorms[i].mode); + em28xx_i2c_call_clients(dev, VIDIOC_S_STD, + &dev->tvnorm->id); - up(&dev->lock); + up(&dev->lock); - return 0; - } + return 0; + } - /* ------ input switching ---------- */ + /* ------ input switching ---------- */ case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; - unsigned int n; - static const char *iname[] = { - [EM28XX_VMUX_COMPOSITE1] = "Composite1", - [EM28XX_VMUX_COMPOSITE2] = "Composite2", - [EM28XX_VMUX_COMPOSITE3] = "Composite3", - [EM28XX_VMUX_COMPOSITE4] = "Composite4", - [EM28XX_VMUX_SVIDEO] = "S-Video", - [EM28XX_VMUX_TELEVISION] = "Television", - [EM28XX_VMUX_CABLE] = "Cable TV", - [EM28XX_VMUX_DVB] = "DVB", - [EM28XX_VMUX_DEBUG] = "for debug only", - }; - - n = i->index; - if (n >= MAX_EM28XX_INPUT) - return -EINVAL; - if (0 == INPUT(n)->type) - return -EINVAL; - memset(i, 0, sizeof(*i)); - i->index = n; - i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name, iname[INPUT(n)->type]); - if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) || - (EM28XX_VMUX_CABLE == INPUT(n)->type)) - i->type = V4L2_INPUT_TYPE_TUNER; - for (n = 0; n < ARRAY_SIZE(tvnorms); n++) - i->std |= tvnorms[n].id; - return 0; - } - + { + struct v4l2_input *i = arg; + unsigned int n; + static const char *iname[] = { + [EM28XX_VMUX_COMPOSITE1] = "Composite1", + [EM28XX_VMUX_COMPOSITE2] = "Composite2", + [EM28XX_VMUX_COMPOSITE3] = "Composite3", + [EM28XX_VMUX_COMPOSITE4] = "Composite4", + [EM28XX_VMUX_SVIDEO] = "S-Video", + [EM28XX_VMUX_TELEVISION] = "Television", + [EM28XX_VMUX_CABLE] = "Cable TV", + [EM28XX_VMUX_DVB] = "DVB", + [EM28XX_VMUX_DEBUG] = "for debug only", + }; + + n = i->index; + if (n >= MAX_EM28XX_INPUT) + return -EINVAL; + if (0 == INPUT(n)->type) + return -EINVAL; + memset(i, 0, sizeof(*i)); + i->index = n; + i->type = V4L2_INPUT_TYPE_CAMERA; + strcpy(i->name, iname[INPUT(n)->type]); + if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) || + (EM28XX_VMUX_CABLE == INPUT(n)->type)) + i->type = V4L2_INPUT_TYPE_TUNER; + for (n = 0; n < ARRAY_SIZE(tvnorms); n++) + i->std |= tvnorms[n].id; + return 0; + } case VIDIOC_G_INPUT: - { - int *i = arg; - *i = dev->ctl_input; - - return 0; - } + { + int *i = arg; + *i = dev->ctl_input; + return 0; + } case VIDIOC_S_INPUT: - { - int *index = arg; - - if (*index >= MAX_EM28XX_INPUT) - return -EINVAL; - if (0 == INPUT(*index)->type) - return -EINVAL; + { + int *index = arg; - down(&dev->lock); - video_mux(dev, *index); - up(&dev->lock); + if (*index >= MAX_EM28XX_INPUT) + return -EINVAL; + if (0 == INPUT(*index)->type) + return -EINVAL; - return 0; - } + down(&dev->lock); + video_mux(dev, *index); + up(&dev->lock); + return 0; + } case VIDIOC_G_AUDIO: - { - struct v4l2_audio *a = arg; - unsigned int index = a->index; + { + struct v4l2_audio *a = arg; + unsigned int index = a->index; - if (a->index > 1) - return -EINVAL; - memset(a, 0, sizeof(*a)); - index = dev->ctl_ainput; + if (a->index > 1) + return -EINVAL; + memset(a, 0, sizeof(*a)); + index = dev->ctl_ainput; - if (index == 0) { - strcpy(a->name, "Television"); - } else { - strcpy(a->name, "Line In"); - } - a->capability = V4L2_AUDCAP_STEREO; - a->index = index; - return 0; + if (index == 0) { + strcpy(a->name, "Television"); + } else { + strcpy(a->name, "Line In"); } - + a->capability = V4L2_AUDCAP_STEREO; + a->index = index; + return 0; + } case VIDIOC_S_AUDIO: - { - struct v4l2_audio *a = arg; - if (a->index != dev->ctl_ainput) - return -EINVAL; + { + struct v4l2_audio *a = arg; - return 0; - } + if (a->index != dev->ctl_ainput) + return -EINVAL; + + return 0; + } - /* --- controls ---------------------------------------------- */ + /* --- controls ---------------------------------------------- */ case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - int i, id=qc->id; - - memset(qc,0,sizeof(*qc)); - qc->id=id; - - if (!dev->has_msp34xx) { - for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { - if (qc->id && qc->id == em28xx_qctrl[i].id) { - memcpy(qc, &(em28xx_qctrl[i]), - sizeof(*qc)); - return 0; - } - } - } - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,qc); - if (qc->type) - return 0; - else - return -EINVAL; - } - for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { - if (qc->id && qc->id == saa711x_qctrl[i].id) { - memcpy(qc, &(saa711x_qctrl[i]), - sizeof(*qc)); + { + struct v4l2_queryctrl *qc = arg; + int i, id=qc->id; + + memset(qc,0,sizeof(*qc)); + qc->id=id; + + if (!dev->has_msp34xx) { + for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { + if (qc->id && qc->id == em28xx_qctrl[i].id) { + memcpy(qc, &(em28xx_qctrl[i]), + sizeof(*qc)); return 0; } } - - return -EINVAL; + } + if (dev->decoder == EM28XX_TVP5150) { + em28xx_i2c_call_clients(dev,cmd,qc); + if (qc->type) + return 0; + else + return -EINVAL; + } + for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { + if (qc->id && qc->id == saa711x_qctrl[i].id) { + memcpy(qc, &(saa711x_qctrl[i]), + sizeof(*qc)); + return 0; + } } + return -EINVAL; + } case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - int retval=-EINVAL; - - if (!dev->has_msp34xx) - retval=em28xx_get_ctrl(dev, ctrl); - if (retval==-EINVAL) { - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,arg); - return 0; - } + { + struct v4l2_control *ctrl = arg; + int retval=-EINVAL; - return saa711x_get_ctrl(dev, ctrl); - } else return retval; - } + if (!dev->has_msp34xx) + retval=em28xx_get_ctrl(dev, ctrl); + if (retval==-EINVAL) { + if (dev->decoder == EM28XX_TVP5150) { + em28xx_i2c_call_clients(dev,cmd,arg); + return 0; + } + return saa711x_get_ctrl(dev, ctrl); + } else return retval; + } case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - u8 i; - - if (!dev->has_msp34xx){ - for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { - if (ctrl->id == em28xx_qctrl[i].id) { - if (ctrl->value < - em28xx_qctrl[i].minimum - || ctrl->value > - em28xx_qctrl[i].maximum) - return -ERANGE; - return em28xx_set_ctrl(dev, ctrl); - } + { + struct v4l2_control *ctrl = arg; + u8 i; + + if (!dev->has_msp34xx){ + for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { + if (ctrl->id == em28xx_qctrl[i].id) { + if (ctrl->value < + em28xx_qctrl[i].minimum + || ctrl->value > + em28xx_qctrl[i].maximum) + return -ERANGE; + return em28xx_set_ctrl(dev, ctrl); } } + } - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,arg); - return 0; - } else if (!dev->has_msp34xx) { - for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { - if (ctrl->id == em28xx_qctrl[i].id) { - if (ctrl->value < - em28xx_qctrl[i].minimum - || ctrl->value > - em28xx_qctrl[i].maximum) - return -ERANGE; - return em28xx_set_ctrl(dev, ctrl); - } + if (dev->decoder == EM28XX_TVP5150) { + em28xx_i2c_call_clients(dev,cmd,arg); + return 0; + } else if (!dev->has_msp34xx) { + for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { + if (ctrl->id == em28xx_qctrl[i].id) { + if (ctrl->value < + em28xx_qctrl[i].minimum + || ctrl->value > + em28xx_qctrl[i].maximum) + return -ERANGE; + return em28xx_set_ctrl(dev, ctrl); } - for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { - if (ctrl->id == saa711x_qctrl[i].id) { - if (ctrl->value < - saa711x_qctrl[i].minimum - || ctrl->value > - saa711x_qctrl[i].maximum) - return -ERANGE; - return saa711x_set_ctrl(dev, ctrl); - } + } + for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { + if (ctrl->id == saa711x_qctrl[i].id) { + if (ctrl->value < + saa711x_qctrl[i].minimum + || ctrl->value > + saa711x_qctrl[i].maximum) + return -ERANGE; + return saa711x_set_ctrl(dev, ctrl); } } - - return -EINVAL; } - /* --- tuner ioctls ------------------------------------------ */ + return -EINVAL; + } + /* --- tuner ioctls ------------------------------------------ */ case VIDIOC_G_TUNER: - { - struct v4l2_tuner *t = arg; - int status = 0; + { + struct v4l2_tuner *t = arg; + int status = 0; - if (0 != t->index) - return -EINVAL; + if (0 != t->index) + return -EINVAL; - memset(t, 0, sizeof(*t)); - strcpy(t->name, "Tuner"); - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM; - t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */ + memset(t, 0, sizeof(*t)); + strcpy(t->name, "Tuner"); + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM; + t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */ /* t->signal = 0xffff;*/ /* em28xx_i2c_call_clients(dev,VIDIOC_G_TUNER,t);*/ - /* No way to get signal strength? */ - down(&dev->lock); - em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, - &status); - up(&dev->lock); - t->signal = - (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; - - em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal, - t->afc); - return 0; - } + /* No way to get signal strength? */ + down(&dev->lock); + em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, + &status); + up(&dev->lock); + t->signal = + (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; + + em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal, + t->afc); + return 0; + } case VIDIOC_S_TUNER: - { - struct v4l2_tuner *t = arg; - int status = 0; + { + struct v4l2_tuner *t = arg; + int status = 0; - if (0 != t->index) - return -EINVAL; - memset(t, 0, sizeof(*t)); - strcpy(t->name, "Tuner"); - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM; - t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */ + if (0 != t->index) + return -EINVAL; + memset(t, 0, sizeof(*t)); + strcpy(t->name, "Tuner"); + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM; + t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */ /* t->signal = 0xffff; */ - /* No way to get signal strength? */ - down(&dev->lock); - em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, - &status); - up(&dev->lock); - t->signal = - (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; - - em28xx_videodbg("VIDIO_S_TUNER: signal=%x, afc=%x\n", - t->signal, t->afc); - return 0; - } + /* No way to get signal strength? */ + down(&dev->lock); + em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, + &status); + up(&dev->lock); + t->signal = + (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; + + em28xx_videodbg("VIDIO_S_TUNER: signal=%x, afc=%x\n", + t->signal, t->afc); + return 0; + } case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; + { + struct v4l2_frequency *f = arg; - memset(f, 0, sizeof(*f)); - f->type = V4L2_TUNER_ANALOG_TV; - f->frequency = dev->ctl_freq; + memset(f, 0, sizeof(*f)); + f->type = V4L2_TUNER_ANALOG_TV; + f->frequency = dev->ctl_freq; - return 0; - } + return 0; + } case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - if (0 != f->tuner) - return -EINVAL; + { + struct v4l2_frequency *f = arg; - if (V4L2_TUNER_ANALOG_TV != f->type) - return -EINVAL; + if (0 != f->tuner) + return -EINVAL; - down(&dev->lock); - dev->ctl_freq = f->frequency; - em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); - up(&dev->lock); - return 0; - } + if (V4L2_TUNER_ANALOG_TV != f->type) + return -EINVAL; + down(&dev->lock); + dev->ctl_freq = f->frequency; + em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); + up(&dev->lock); + return 0; + } case VIDIOC_CROPCAP: - { - struct v4l2_cropcap *cc = arg; + { + struct v4l2_cropcap *cc = arg; - if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - cc->bounds.left = 0; - cc->bounds.top = 0; - cc->bounds.width = dev->width; - cc->bounds.height = dev->height; - cc->defrect = cc->bounds; - cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */ - cc->pixelaspect.denominator = 59; - return 0; - } + if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + cc->bounds.left = 0; + cc->bounds.top = 0; + cc->bounds.width = dev->width; + cc->bounds.height = dev->height; + cc->defrect = cc->bounds; + cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */ + cc->pixelaspect.denominator = 59; + return 0; + } case VIDIOC_STREAMON: - { - int *type = arg; + { + int *type = arg; - if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE - || dev->io != IO_MMAP) - return -EINVAL; + if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE + || dev->io != IO_MMAP) + return -EINVAL; - if (list_empty(&dev->inqueue)) - return -EINVAL; + if (list_empty(&dev->inqueue)) + return -EINVAL; - dev->stream = STREAM_ON; /* FIXME: Start video capture here? */ + dev->stream = STREAM_ON; /* FIXME: Start video capture here? */ - em28xx_videodbg("VIDIOC_STREAMON: starting stream\n"); + em28xx_videodbg("VIDIOC_STREAMON: starting stream\n"); - return 0; - } + return 0; + } case VIDIOC_STREAMOFF: - { - int *type = arg; - int ret; - - if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE - || dev->io != IO_MMAP) - return -EINVAL; + { + int *type = arg; + int ret; - if (dev->stream == STREAM_ON) { - em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream\n"); - if ((ret = em28xx_stream_interrupt(dev))) - return ret; - } - em28xx_empty_framequeues(dev); + if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE + || dev->io != IO_MMAP) + return -EINVAL; - return 0; + if (dev->stream == STREAM_ON) { + em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream\n"); + if ((ret = em28xx_stream_interrupt(dev))) + return ret; } + em28xx_empty_framequeues(dev); + + return 0; + } default: return v4l_compat_translate_ioctl(inode, filp, cmd, arg, driver_ioctl); @@ -1489,40 +1477,38 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, /* --- capabilities ------------------------------------------ */ case VIDIOC_QUERYCAP: { - struct v4l2_capability *cap = arg; - - memset(cap, 0, sizeof(*cap)); - strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); - strlcpy(cap->card, em28xx_boards[dev->model].name, - sizeof(cap->card)); - strlcpy(cap->bus_info, dev->udev->dev.bus_id, - sizeof(cap->bus_info)); - cap->version = EM28XX_VERSION_CODE; - cap->capabilities = - V4L2_CAP_SLICED_VBI_CAPTURE | - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - if (dev->has_tuner) - cap->capabilities |= V4L2_CAP_TUNER; - return 0; - } - - /* --- capture ioctls ---------------------------------------- */ + struct v4l2_capability *cap = arg; + + memset(cap, 0, sizeof(*cap)); + strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); + strlcpy(cap->card, em28xx_boards[dev->model].name, + sizeof(cap->card)); + strlcpy(cap->bus_info, dev->udev->dev.bus_id, + sizeof(cap->bus_info)); + cap->version = EM28XX_VERSION_CODE; + cap->capabilities = + V4L2_CAP_SLICED_VBI_CAPTURE | + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_AUDIO | + V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + if (dev->has_tuner) + cap->capabilities |= V4L2_CAP_TUNER; + return 0; + } + /* --- capture ioctls ---------------------------------------- */ case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *fmtd = arg; - - if (fmtd->index != 0) - return -EINVAL; - memset(fmtd, 0, sizeof(*fmtd)); - fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(fmtd->description, "Packed YUY2"); - fmtd->pixelformat = V4L2_PIX_FMT_YUYV; - memset(fmtd->reserved, 0, sizeof(fmtd->reserved)); - return 0; - } + { + struct v4l2_fmtdesc *fmtd = arg; + if (fmtd->index != 0) + return -EINVAL; + memset(fmtd, 0, sizeof(*fmtd)); + fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + strcpy(fmtd->description, "Packed YUY2"); + fmtd->pixelformat = V4L2_PIX_FMT_YUYV; + memset(fmtd->reserved, 0, sizeof(fmtd->reserved)); + return 0; + } case VIDIOC_G_FMT: return em28xx_get_fmt(dev, (struct v4l2_format *) arg); @@ -1531,131 +1517,130 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, return em28xx_set_fmt(dev, cmd, (struct v4l2_format *)arg); case VIDIOC_REQBUFS: - { - struct v4l2_requestbuffers *rb = arg; - u32 i; - int ret; - - if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - rb->memory != V4L2_MEMORY_MMAP) - return -EINVAL; + { + struct v4l2_requestbuffers *rb = arg; + u32 i; + int ret; - if (dev->io == IO_READ) { - em28xx_videodbg ("method is set to read;" - " close and open the device again to" - " choose the mmap I/O method\n"); - return -EINVAL; - } + if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + rb->memory != V4L2_MEMORY_MMAP) + return -EINVAL; - for (i = 0; i < dev->num_frames; i++) - if (dev->frame[i].vma_use_count) { - em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped\n"); - return -EINVAL; - } + if (dev->io == IO_READ) { + em28xx_videodbg ("method is set to read;" + " close and open the device again to" + " choose the mmap I/O method\n"); + return -EINVAL; + } - if (dev->stream == STREAM_ON) { - em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n"); - if ((ret = em28xx_stream_interrupt(dev))) - return ret; + for (i = 0; i < dev->num_frames; i++) + if (dev->frame[i].vma_use_count) { + em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped\n"); + return -EINVAL; } - em28xx_empty_framequeues(dev); + if (dev->stream == STREAM_ON) { + em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n"); + if ((ret = em28xx_stream_interrupt(dev))) + return ret; + } - em28xx_release_buffers(dev); - if (rb->count) - rb->count = - em28xx_request_buffers(dev, rb->count); + em28xx_empty_framequeues(dev); - dev->frame_current = NULL; + em28xx_release_buffers(dev); + if (rb->count) + rb->count = + em28xx_request_buffers(dev, rb->count); - em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i\n", - rb->count); - dev->io = rb->count ? IO_MMAP : IO_NONE; - return 0; - } + dev->frame_current = NULL; + em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i\n", + rb->count); + dev->io = rb->count ? IO_MMAP : IO_NONE; + return 0; + } case VIDIOC_QUERYBUF: - { - struct v4l2_buffer *b = arg; + { + struct v4l2_buffer *b = arg; - if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b->index >= dev->num_frames || dev->io != IO_MMAP) - return -EINVAL; + if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b->index >= dev->num_frames || dev->io != IO_MMAP) + return -EINVAL; - memcpy(b, &dev->frame[b->index].buf, sizeof(*b)); + memcpy(b, &dev->frame[b->index].buf, sizeof(*b)); - if (dev->frame[b->index].vma_use_count) { - b->flags |= V4L2_BUF_FLAG_MAPPED; - } - if (dev->frame[b->index].state == F_DONE) - b->flags |= V4L2_BUF_FLAG_DONE; - else if (dev->frame[b->index].state != F_UNUSED) - b->flags |= V4L2_BUF_FLAG_QUEUED; - return 0; + if (dev->frame[b->index].vma_use_count) { + b->flags |= V4L2_BUF_FLAG_MAPPED; } + if (dev->frame[b->index].state == F_DONE) + b->flags |= V4L2_BUF_FLAG_DONE; + else if (dev->frame[b->index].state != F_UNUSED) + b->flags |= V4L2_BUF_FLAG_QUEUED; + return 0; + } case VIDIOC_QBUF: - { - struct v4l2_buffer *b = arg; - unsigned long lock_flags; + { + struct v4l2_buffer *b = arg; + unsigned long lock_flags; - if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b->index >= dev->num_frames || dev->io != IO_MMAP) { - return -EINVAL; - } + if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b->index >= dev->num_frames || dev->io != IO_MMAP) { + return -EINVAL; + } - if (dev->frame[b->index].state != F_UNUSED) { - return -EAGAIN; - } - dev->frame[b->index].state = F_QUEUED; + if (dev->frame[b->index].state != F_UNUSED) { + return -EAGAIN; + } + dev->frame[b->index].state = F_QUEUED; - /* add frame to fifo */ - spin_lock_irqsave(&dev->queue_lock, lock_flags); - list_add_tail(&dev->frame[b->index].frame, - &dev->inqueue); - spin_unlock_irqrestore(&dev->queue_lock, lock_flags); + /* add frame to fifo */ + spin_lock_irqsave(&dev->queue_lock, lock_flags); + list_add_tail(&dev->frame[b->index].frame, + &dev->inqueue); + spin_unlock_irqrestore(&dev->queue_lock, lock_flags); - return 0; - } + return 0; + } case VIDIOC_DQBUF: - { - struct v4l2_buffer *b = arg; - struct em28xx_frame_t *f; - unsigned long lock_flags; - int ret = 0; + { + struct v4l2_buffer *b = arg; + struct em28xx_frame_t *f; + unsigned long lock_flags; + int ret = 0; - if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE - || dev->io != IO_MMAP) - return -EINVAL; + if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE + || dev->io != IO_MMAP) + return -EINVAL; - if (list_empty(&dev->outqueue)) { - if (dev->stream == STREAM_OFF) - return -EINVAL; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - ret = wait_event_interruptible - (dev->wait_frame, - (!list_empty(&dev->outqueue)) || - (dev->state & DEV_DISCONNECTED)); - if (ret) - return ret; - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - } + if (list_empty(&dev->outqueue)) { + if (dev->stream == STREAM_OFF) + return -EINVAL; + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + ret = wait_event_interruptible + (dev->wait_frame, + (!list_empty(&dev->outqueue)) || + (dev->state & DEV_DISCONNECTED)); + if (ret) + return ret; + if (dev->state & DEV_DISCONNECTED) + return -ENODEV; + } - spin_lock_irqsave(&dev->queue_lock, lock_flags); - f = list_entry(dev->outqueue.next, - struct em28xx_frame_t, frame); - list_del(dev->outqueue.next); - spin_unlock_irqrestore(&dev->queue_lock, lock_flags); + spin_lock_irqsave(&dev->queue_lock, lock_flags); + f = list_entry(dev->outqueue.next, + struct em28xx_frame_t, frame); + list_del(dev->outqueue.next); + spin_unlock_irqrestore(&dev->queue_lock, lock_flags); - f->state = F_UNUSED; - memcpy(b, &f->buf, sizeof(*b)); + f->state = F_UNUSED; + memcpy(b, &f->buf, sizeof(*b)); - if (f->vma_use_count) - b->flags |= V4L2_BUF_FLAG_MAPPED; + if (f->vma_use_count) + b->flags |= V4L2_BUF_FLAG_MAPPED; - return 0; - } + return 0; + } default: return em28xx_do_ioctl(inode, filp, dev, cmd, arg, em28xx_video_do_ioctl); -- cgit v1.2.3-59-g8ed1b From 8a4b275f9c192921797f45c2d4b5e4bc3875500a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 23 Jan 2006 17:11:09 -0200 Subject: V4L/DVB (3427): audmode and rxsubchans fixes (VIDIOC_G/S_TUNER) - Audmode and rxsubchans fixes in msp3400, tuner, tvaudio and cx25840. - msp3400 cleanups Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 46 ++-- drivers/media/video/cx25840/cx25840.h | 1 + drivers/media/video/msp3400-driver.c | 59 ++---- drivers/media/video/msp3400-kthreads.c | 330 ++++++++++++++--------------- drivers/media/video/msp3400.h | 11 +- drivers/media/video/tuner-core.c | 68 +++--- drivers/media/video/tvaudio.c | 26 ++- 7 files changed, 255 insertions(+), 286 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index c66c2c1f4809..3acd587b160c 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -753,6 +753,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, memset(input, 0, sizeof(*input)); input->index = state->aud_input; + input->capability = V4L2_AUDCAP_STEREO; break; } @@ -763,7 +764,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, case VIDIOC_G_TUNER: { u8 mode = cx25840_read(client, 0x804); - u8 pref = cx25840_read(client, 0x809) & 0xf; u8 vpres = cx25840_read(client, 0x80a) & 0x10; int val = 0; @@ -783,44 +783,49 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, val |= V4L2_TUNER_SUB_MONO; if (mode == 2 || mode == 4) - val |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; if (mode & 0x10) val |= V4L2_TUNER_SUB_SAP; vt->rxsubchans = val; - - switch (pref) { - case 0: - vt->audmode = V4L2_TUNER_MODE_MONO; - break; - case 1: - case 2: - vt->audmode = V4L2_TUNER_MODE_LANG2; - break; - case 4: - default: - vt->audmode = V4L2_TUNER_MODE_STEREO; - } + vt->audmode = state->audmode; break; } case VIDIOC_S_TUNER: + if (state->radio) + break; + switch (vt->audmode) { case V4L2_TUNER_MODE_MONO: - case V4L2_TUNER_MODE_LANG1: - /* Force PREF_MODE to MONO */ + /* mono -> mono + stereo -> mono + bilingual -> lang1 */ cx25840_and_or(client, 0x809, ~0xf, 0x00); break; - case V4L2_TUNER_MODE_STEREO: - /* Force PREF_MODE to STEREO */ + case V4L2_TUNER_MODE_LANG1: + /* mono -> mono + stereo -> stereo + bilingual -> lang1 */ cx25840_and_or(client, 0x809, ~0xf, 0x04); break; + case V4L2_TUNER_MODE_STEREO: + /* mono -> mono + stereo -> stereo + bilingual -> lang1/lang2 */ + cx25840_and_or(client, 0x809, ~0xf, 0x07); + break; case V4L2_TUNER_MODE_LANG2: - /* Force PREF_MODE to LANG2 */ + /* mono -> mono + stereo ->stereo + bilingual -> lang2 */ cx25840_and_or(client, 0x809, ~0xf, 0x01); break; + default: + return -EINVAL; } + state->audmode = vt->audmode; break; case VIDIOC_G_FMT: @@ -901,6 +906,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, state->aud_input = CX25840_AUDIO8; state->audclk_freq = 48000; state->pvr150_workaround = 0; + state->audmode = V4L2_TUNER_MODE_LANG1; cx25840_initialize(client, 1); diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840.h index fd22f30dcc1b..dd70664d1dd9 100644 --- a/drivers/media/video/cx25840/cx25840.h +++ b/drivers/media/video/cx25840/cx25840.h @@ -78,6 +78,7 @@ struct cx25840_state { enum cx25840_video_input vid_input; enum cx25840_audio_input aud_input; u32 audclk_freq; + int audmode; }; /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 994c340f9d02..11ea9765769c 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -411,9 +411,9 @@ static int msp_mode_v4l2_to_v4l1(int rxsubchans) if (rxsubchans & V4L2_TUNER_SUB_STEREO) mode |= VIDEO_SOUND_STEREO; if (rxsubchans & V4L2_TUNER_SUB_LANG2) - mode |= VIDEO_SOUND_LANG2; + mode |= VIDEO_SOUND_LANG2 | VIDEO_SOUND_STEREO; if (rxsubchans & V4L2_TUNER_SUB_LANG1) - mode |= VIDEO_SOUND_LANG1; + mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_STEREO; if (mode == 0) mode |= VIDEO_SOUND_MONO; return mode; @@ -430,21 +430,6 @@ static int msp_mode_v4l1_to_v4l2(int mode) return V4L2_TUNER_MODE_MONO; } -static void msp_any_detect_stereo(struct i2c_client *client) -{ - struct msp_state *state = i2c_get_clientdata(client); - - switch (state->opmode) { - case OPMODE_MANUAL: - case OPMODE_AUTODETECT: - autodetect_stereo(client); - break; - case OPMODE_AUTOSELECT: - msp34xxg_detect_stereo(client); - break; - } -} - static struct v4l2_queryctrl msp_qctrl_std[] = { { .id = V4L2_CID_AUDIO_VOLUME, @@ -506,22 +491,6 @@ static struct v4l2_queryctrl msp_qctrl_sound_processing[] = { }; -static void msp_any_set_audmode(struct i2c_client *client, int audmode) -{ - struct msp_state *state = i2c_get_clientdata(client); - - switch (state->opmode) { - case OPMODE_MANUAL: - case OPMODE_AUTODETECT: - state->watch_stereo = 0; - msp3400c_setstereo(client, audmode); - break; - case OPMODE_AUTOSELECT: - msp34xxg_set_audmode(client, audmode); - break; - } -} - static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) { struct msp_state *state = i2c_get_clientdata(client); @@ -656,7 +625,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp_set_scart(client, scart, 0); msp_write_dsp(client, 0x000d, 0x1900); if (state->opmode != OPMODE_AUTOSELECT) - msp3400c_setstereo(client, state->audmode); + msp_set_audmode(client); } msp_wake_thread(client); break; @@ -670,8 +639,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) switch (state->opmode) { case OPMODE_MANUAL: /* set msp3400 to FM radio mode */ - msp3400c_setmode(client, MSP_MODE_FM_RADIO); - msp3400c_setcarrier(client, MSP_CARRIER(10.7), + msp3400c_set_mode(client, MSP_MODE_FM_RADIO); + msp3400c_set_carrier(client, MSP_CARRIER(10.7), MSP_CARRIER(10.7)); msp_set_audio(client); break; @@ -705,7 +674,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) if (state->radio) break; if (state->opmode == OPMODE_AUTOSELECT) - msp_any_detect_stereo(client); + msp_detect_stereo(client); va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans); break; } @@ -721,8 +690,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) state->treble = va->treble; msp_set_audio(client); - if (va->mode != 0 && state->radio == 0) - msp_any_set_audmode(client, msp_mode_v4l1_to_v4l2(va->mode)); + if (va->mode != 0 && state->radio == 0) { + state->audmode = msp_mode_v4l1_to_v4l2(va->mode); + } break; } @@ -864,7 +834,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp_set_scart(client, scart, 0); msp_write_dsp(client, 0x000d, 0x1900); } - msp_any_set_audmode(client, state->audmode); + msp_set_audmode(client); msp_wake_thread(client); break; } @@ -876,7 +846,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) if (state->radio) break; if (state->opmode == OPMODE_AUTOSELECT) - msp_any_detect_stereo(client); + msp_detect_stereo(client); vt->audmode = state->audmode; vt->rxsubchans = state->rxsubchans; vt->capability = V4L2_TUNER_CAP_STEREO | @@ -890,8 +860,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) if (state->radio) /* TODO: add mono/stereo support for radio */ break; + state->audmode = vt->audmode; /* only set audmode */ - msp_any_set_audmode(client, vt->audmode); + msp_set_audmode(client); break; } @@ -981,7 +952,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) const char *p; if (state->opmode == OPMODE_AUTOSELECT) - msp_any_detect_stereo(client); + msp_detect_stereo(client); v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", client->name, state->rev1, state->rev2); v4l_info(client, "Audio: volume %d%s\n", @@ -1082,7 +1053,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) memset(state, 0, sizeof(*state)); state->v4l2_std = V4L2_STD_NTSC; - state->audmode = V4L2_TUNER_MODE_STEREO; + state->audmode = V4L2_TUNER_MODE_LANG1; state->volume = 58880; /* 0db gain */ state->balance = 32768; /* 0db gain */ state->bass = 32768; diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 3235a15db59f..c4668f4b6e5c 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -109,7 +109,7 @@ static struct msp3400c_init_data_dem { {-2, -8, -10, 10, 50, 86}, {-4, -12, -9, 23, 79, 126}, MSP_CARRIER(6.5), MSP_CARRIER(6.5), - 0x00c6, 0x0140, 0x0120, 0x7c03 + 0x00c6, 0x0140, 0x0120, 0x7c00 }, }; @@ -154,53 +154,60 @@ const char *msp_standard_std_name(int std) return "unknown"; } -void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2) +void msp_set_source(struct i2c_client *client, u16 src) +{ + struct msp_state *state = i2c_get_clientdata(client); + + if (msp_dolby) { + msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */ + msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */ + } else { + msp_write_dsp(client, 0x0008, src); + msp_write_dsp(client, 0x0009, src); + } + msp_write_dsp(client, 0x000a, src); + msp_write_dsp(client, 0x000b, src); + msp_write_dsp(client, 0x000c, src); + if (state->has_scart23_in_scart2_out) + msp_write_dsp(client, 0x0041, src); +} + +void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2) { msp_write_dem(client, 0x0093, cdo1 & 0xfff); msp_write_dem(client, 0x009b, cdo1 >> 12); msp_write_dem(client, 0x00a3, cdo2 & 0xfff); msp_write_dem(client, 0x00ab, cdo2 >> 12); - msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/ + msp_write_dem(client, 0x0056, 0); /* LOAD_REG_1/2 */ } -void msp3400c_setmode(struct i2c_client *client, int type) +void msp3400c_set_mode(struct i2c_client *client, int mode) { struct msp_state *state = i2c_get_clientdata(client); + struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode]; int i; - v4l_dbg(1, msp_debug, client, "setmode: %d\n", type); - state->mode = type; + v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode); + state->mode = mode; state->rxsubchans = V4L2_TUNER_SUB_MONO; - msp_write_dem(client, 0x00bb, msp3400c_init_data[type].ad_cv); + msp_write_dem(client, 0x00bb, data->ad_cv); for (i = 5; i >= 0; i--) /* fir 1 */ - msp_write_dem(client, 0x0001, msp3400c_init_data[type].fir1[i]); + msp_write_dem(client, 0x0001, data->fir1[i]); msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */ msp_write_dem(client, 0x0005, 0x0040); msp_write_dem(client, 0x0005, 0x0000); for (i = 5; i >= 0; i--) - msp_write_dem(client, 0x0005, msp3400c_init_data[type].fir2[i]); + msp_write_dem(client, 0x0005, data->fir2[i]); - msp_write_dem(client, 0x0083, msp3400c_init_data[type].mode_reg); + msp_write_dem(client, 0x0083, data->mode_reg); - msp3400c_setcarrier(client, msp3400c_init_data[type].cdo1, - msp3400c_init_data[type].cdo2); + msp3400c_set_carrier(client, data->cdo1, data->cdo2); - msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/ - - if (msp_dolby) { - msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */ - msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */ - msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src); - } else { - msp_write_dsp(client, 0x0008, msp3400c_init_data[type].dsp_src); - msp_write_dsp(client, 0x0009, msp3400c_init_data[type].dsp_src); - msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src); - } - msp_write_dsp(client, 0x000a, msp3400c_init_data[type].dsp_src); - msp_write_dsp(client, 0x000e, msp3400c_init_data[type].dsp_matrix); + msp_set_source(client, data->dsp_src); + msp_write_dsp(client, 0x000e, data->dsp_matrix); if (state->has_nicam) { /* nicam prescale */ @@ -208,29 +215,31 @@ void msp3400c_setmode(struct i2c_client *client, int type) } } -/* turn on/off nicam + stereo */ -void msp3400c_setstereo(struct i2c_client *client, int audmode) +/* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP, + nor do they support stereo BTSC. */ +void msp3400c_set_audmode(struct i2c_client *client) { static char *strmode[] = { "mono", "stereo", "lang2", "lang1" }; struct msp_state *state = i2c_get_clientdata(client); - int nicam = 0; /* channel source: FM/AM or nicam */ - int src = 0; + char *modestr = (state->audmode >= 0 && state->audmode < 4) ? + strmode[state->audmode] : "unknown"; + int src = 0; /* channel source: FM/AM, nicam or SCART */ if (state->opmode == OPMODE_AUTOSELECT) { /* this method would break everything, let's make sure * it's never called */ - v4l_dbg(1, msp_debug, client, "setstereo called with mode=%d instead of set_source (ignored)\n", - audmode); + v4l_dbg(1, msp_debug, client, + "set_audmode called with mode=%d instead of set_source (ignored)\n", + state->audmode); return; } /* switch demodulator */ switch (state->mode) { case MSP_MODE_FM_TERRA: - v4l_dbg(1, msp_debug, client, "FM setstereo: %s\n", strmode[audmode]); - msp3400c_setcarrier(client, state->second, state->main); - switch (audmode) { + v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr); + switch (state->audmode) { case V4L2_TUNER_MODE_STEREO: msp_write_dsp(client, 0x000e, 0x3001); break; @@ -242,50 +251,49 @@ void msp3400c_setstereo(struct i2c_client *client, int audmode) } break; case MSP_MODE_FM_SAT: - v4l_dbg(1, msp_debug, client, "SAT setstereo: %s\n", strmode[audmode]); - switch (audmode) { + v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr); + switch (state->audmode) { case V4L2_TUNER_MODE_MONO: - msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); + msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); break; case V4L2_TUNER_MODE_STEREO: - msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); + msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); break; case V4L2_TUNER_MODE_LANG1: - msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); + msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); break; case V4L2_TUNER_MODE_LANG2: - msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); + msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); break; } break; case MSP_MODE_FM_NICAM1: case MSP_MODE_FM_NICAM2: case MSP_MODE_AM_NICAM: - v4l_dbg(1, msp_debug, client, "NICAM setstereo: %s\n",strmode[audmode]); - msp3400c_setcarrier(client,state->second,state->main); + v4l_dbg(1, msp_debug, client, "NICAM set_audmode: %s\n",modestr); + msp3400c_set_carrier(client, state->second, state->main); if (state->nicam_on) - nicam=0x0100; + src = 0x0100; /* NICAM */ break; case MSP_MODE_BTSC: - v4l_dbg(1, msp_debug, client, "BTSC setstereo: %s\n",strmode[audmode]); - nicam=0x0300; + v4l_dbg(1, msp_debug, client, "BTSC set_audmode: %s\n",modestr); break; case MSP_MODE_EXTERN: - v4l_dbg(1, msp_debug, client, "extern setstereo: %s\n",strmode[audmode]); - nicam = 0x0200; + v4l_dbg(1, msp_debug, client, "extern set_audmode: %s\n",modestr); + src = 0x0200; /* SCART */ break; case MSP_MODE_FM_RADIO: - v4l_dbg(1, msp_debug, client, "FM-Radio setstereo: %s\n",strmode[audmode]); + v4l_dbg(1, msp_debug, client, "FM-Radio set_audmode: %s\n",modestr); break; default: - v4l_dbg(1, msp_debug, client, "mono setstereo\n"); + v4l_dbg(1, msp_debug, client, "mono set_audmode\n"); return; } /* switch audio */ - switch (audmode) { + switch (state->audmode) { case V4L2_TUNER_MODE_STEREO: - src = 0x0020 | nicam; + src |= 0x0020; break; case V4L2_TUNER_MODE_MONO: if (state->mode == MSP_MODE_AM_NICAM) { @@ -296,29 +304,22 @@ void msp3400c_setstereo(struct i2c_client *client, int audmode) src = 0x0200; break; } + if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) + src = 0x0030; + break; case V4L2_TUNER_MODE_LANG1: - src = 0x0000 | nicam; + /* switch to stereo for stereo transmission, otherwise + keep first language */ + if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) + src |= 0x0020; break; case V4L2_TUNER_MODE_LANG2: - src = 0x0010 | nicam; + src |= 0x0010; break; } - v4l_dbg(1, msp_debug, client, "setstereo final source/matrix = 0x%x\n", src); + v4l_dbg(1, msp_debug, client, "set_audmode final source/matrix = 0x%x\n", src); - if (msp_dolby) { - msp_write_dsp(client, 0x0008, 0x0520); - msp_write_dsp(client, 0x0009, 0x0620); - msp_write_dsp(client, 0x000a, src); - msp_write_dsp(client, 0x000b, src); - } else { - msp_write_dsp(client, 0x0008, src); - msp_write_dsp(client, 0x0009, src); - msp_write_dsp(client, 0x000a, src); - msp_write_dsp(client, 0x000b, src); - msp_write_dsp(client, 0x000c, src); - if (state->has_scart23_in_scart2_out) - msp_write_dsp(client, 0x0041, src); - } + msp_set_source(client, src); } static void msp3400c_print_mode(struct i2c_client *client) @@ -346,12 +347,12 @@ static void msp3400c_print_mode(struct i2c_client *client) /* ----------------------------------------------------------------------- */ -int autodetect_stereo(struct i2c_client *client) +static int msp3400c_detect_stereo(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); int val; int rxsubchans = state->rxsubchans; - int newnicam = state->nicam_on; + int newnicam = state->nicam_on; int update = 0; switch (state->mode) { @@ -361,7 +362,7 @@ int autodetect_stereo(struct i2c_client *client) val -= 65536; v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val); if (val > 4096) { - rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; + rxsubchans = V4L2_TUNER_SUB_STEREO; } else if (val < -4096) { rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; } else { @@ -385,14 +386,11 @@ int autodetect_stereo(struct i2c_client *client) break; case 1: case 9: - rxsubchans = V4L2_TUNER_SUB_MONO - | V4L2_TUNER_SUB_LANG1; + rxsubchans = V4L2_TUNER_SUB_MONO; break; case 2: case 10: - rxsubchans = V4L2_TUNER_SUB_MONO - | V4L2_TUNER_SUB_LANG1 - | V4L2_TUNER_SUB_LANG2; + rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; break; default: rxsubchans = V4L2_TUNER_SUB_MONO; @@ -404,30 +402,17 @@ int autodetect_stereo(struct i2c_client *client) rxsubchans = V4L2_TUNER_SUB_MONO; } break; - case MSP_MODE_BTSC: - val = msp_read_dem(client, 0x200); - v4l_dbg(2, msp_debug, client, "status=0x%x (pri=%s, sec=%s, %s%s%s)\n", - val, - (val & 0x0002) ? "no" : "yes", - (val & 0x0004) ? "no" : "yes", - (val & 0x0040) ? "stereo" : "mono", - (val & 0x0080) ? ", nicam 2nd mono" : "", - (val & 0x0100) ? ", bilingual/SAP" : ""); - rxsubchans = V4L2_TUNER_SUB_MONO; - if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO; - if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1; - break; } if (rxsubchans != state->rxsubchans) { update = 1; - v4l_dbg(1, msp_debug, client, "watch: rxsubchans %d => %d\n", - state->rxsubchans,rxsubchans); + v4l_dbg(1, msp_debug, client, "watch: rxsubchans %02x => %02x\n", + state->rxsubchans, rxsubchans); state->rxsubchans = rxsubchans; } if (newnicam != state->nicam_on) { update = 1; v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n", - state->nicam_on,newnicam); + state->nicam_on, newnicam); state->nicam_on = newnicam; } return update; @@ -442,13 +427,8 @@ static void watch_stereo(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); - if (autodetect_stereo(client)) { - if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) - msp3400c_setstereo(client, V4L2_TUNER_MODE_STEREO); - else if (state->rxsubchans & V4L2_TUNER_SUB_LANG1) - msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1); - else - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + if (msp3400c_detect_stereo(client)) { + msp3400c_set_audmode(client); } if (msp_once) @@ -460,7 +440,7 @@ int msp3400c_thread(void *data) struct i2c_client *client = data; struct msp_state *state = i2c_get_clientdata(client); struct msp3400c_carrier_detect *cd; - int count, max1,max2,val1,val2, val,this; + int count, max1, max2, val1, val2, val, this; v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); @@ -470,7 +450,7 @@ int msp3400c_thread(void *data) v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n"); restart: - v4l_dbg(1, msp_debug, client, "thread: restart scan\n"); + v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); state->restart = 0; if (kthread_should_stop()) break; @@ -484,13 +464,14 @@ int msp3400c_thread(void *data) /* mute */ msp_set_mute(client); - msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ ); + msp3400c_set_mode(client, MSP_MODE_AM_DETECT /* +1 */ ); val1 = val2 = 0; max1 = max2 = -1; state->watch_stereo = 0; + state->nicam_on = 0; /* some time for the tuner to sync */ - if (msp_sleep(state,200)) + if (msp_sleep(state, 200)) goto restart; /* carrier detect pass #1 -- main carrier */ @@ -505,7 +486,7 @@ int msp3400c_thread(void *data) } for (this = 0; this < count; this++) { - msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); + msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo); if (msp_sleep(state,100)) goto restart; val = msp_read_dsp(client, 0x1b); @@ -541,7 +522,7 @@ int msp3400c_thread(void *data) max2 = 0; } for (this = 0; this < count; this++) { - msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); + msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo); if (msp_sleep(state,100)) goto restart; val = msp_read_dsp(client, 0x1b); @@ -553,22 +534,20 @@ int msp3400c_thread(void *data) } /* program the msp3400 according to the results */ - state->main = msp3400c_carrier_detect_main[max1].cdo; + state->main = msp3400c_carrier_detect_main[max1].cdo; switch (max1) { case 1: /* 5.5 */ if (max2 == 0) { /* B/G FM-stereo */ state->second = msp3400c_carrier_detect_55[max2].cdo; - msp3400c_setmode(client, MSP_MODE_FM_TERRA); - state->nicam_on = 0; - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + msp3400c_set_mode(client, MSP_MODE_FM_TERRA); state->watch_stereo = 1; } else if (max2 == 1 && state->has_nicam) { /* B/G NICAM */ state->second = msp3400c_carrier_detect_55[max2].cdo; - msp3400c_setmode(client, MSP_MODE_FM_NICAM1); + msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); + msp3400c_set_carrier(client, state->second, state->main); state->nicam_on = 1; - msp3400c_setcarrier(client, state->second, state->main); state->watch_stereo = 1; } else { goto no_second; @@ -577,35 +556,31 @@ int msp3400c_thread(void *data) case 2: /* 6.0 */ /* PAL I NICAM */ state->second = MSP_CARRIER(6.552); - msp3400c_setmode(client, MSP_MODE_FM_NICAM2); + msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); + msp3400c_set_carrier(client, state->second, state->main); state->nicam_on = 1; - msp3400c_setcarrier(client, state->second, state->main); state->watch_stereo = 1; break; case 3: /* 6.5 */ if (max2 == 1 || max2 == 2) { /* D/K FM-stereo */ state->second = msp3400c_carrier_detect_65[max2].cdo; - msp3400c_setmode(client, MSP_MODE_FM_TERRA); - state->nicam_on = 0; - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + msp3400c_set_mode(client, MSP_MODE_FM_TERRA); state->watch_stereo = 1; } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) { /* L NICAM or AM-mono */ state->second = msp3400c_carrier_detect_65[max2].cdo; - msp3400c_setmode(client, MSP_MODE_AM_NICAM); - state->nicam_on = 0; - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); - msp3400c_setcarrier(client, state->second, state->main); + msp3400c_set_mode(client, MSP_MODE_AM_NICAM); + msp3400c_set_carrier(client, state->second, state->main); /* volume prescale for SCART (AM mono input) */ msp_write_dsp(client, 0x000d, 0x1900); state->watch_stereo = 1; } else if (max2 == 0 && state->has_nicam) { /* D/K NICAM */ state->second = msp3400c_carrier_detect_65[max2].cdo; - msp3400c_setmode(client, MSP_MODE_FM_NICAM1); + msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); + msp3400c_set_carrier(client, state->second, state->main); state->nicam_on = 1; - msp3400c_setcarrier(client, state->second, state->main); state->watch_stereo = 1; } else { goto no_second; @@ -615,23 +590,25 @@ int msp3400c_thread(void *data) default: no_second: state->second = msp3400c_carrier_detect_main[max1].cdo; - msp3400c_setmode(client, MSP_MODE_FM_TERRA); - state->nicam_on = 0; - msp3400c_setcarrier(client, state->second, state->main); + msp3400c_set_mode(client, MSP_MODE_FM_TERRA); + msp3400c_set_carrier(client, state->second, state->main); state->rxsubchans = V4L2_TUNER_SUB_MONO; - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); break; } /* unmute */ msp_set_audio(client); + msp3400c_set_audmode(client); if (msp_debug) msp3400c_print_mode(client); - /* monitor tv audio mode */ + /* monitor tv audio mode, the first time don't wait + so long to get a quick stereo/bilingual result */ + if (msp_sleep(state, 1000)) + goto restart; while (state->watch_stereo) { - if (msp_sleep(state,5000)) + if (msp_sleep(state, 5000)) goto restart; watch_stereo(client); } @@ -655,7 +632,7 @@ int msp3410d_thread(void *data) v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n"); restart: - v4l_dbg(1, msp_debug, client, "thread: restart scan\n"); + v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); state->restart = 0; if (kthread_should_stop()) break; @@ -680,9 +657,10 @@ int msp3410d_thread(void *data) else std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1; state->watch_stereo = 0; + state->nicam_on = 0; if (msp_debug) - v4l_dbg(1, msp_debug, client, "setting standard: %s (0x%04x)\n", + v4l_dbg(2, msp_debug, client, "setting standard: %s (0x%04x)\n", msp_standard_std_name(std), std); if (std != 1) { @@ -699,7 +677,7 @@ int msp3410d_thread(void *data) val = msp_read_dem(client, 0x7e); if (val < 0x07ff) break; - v4l_dbg(1, msp_debug, client, "detection still in progress\n"); + v4l_dbg(2, msp_debug, client, "detection still in progress\n"); } } for (i = 0; msp_stdlist[i].name != NULL; i++) @@ -738,46 +716,34 @@ int msp3410d_thread(void *data) state->rxsubchans = V4L2_TUNER_SUB_STEREO; state->nicam_on = 1; state->watch_stereo = 1; - msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); break; case 0x0009: state->mode = MSP_MODE_AM_NICAM; state->rxsubchans = V4L2_TUNER_SUB_MONO; state->nicam_on = 1; - msp3400c_setstereo(client,V4L2_TUNER_MODE_MONO); state->watch_stereo = 1; break; case 0x0020: /* BTSC */ - /* just turn on stereo */ + /* The pre-'G' models only have BTSC-mono */ state->mode = MSP_MODE_BTSC; - state->rxsubchans = V4L2_TUNER_SUB_STEREO; - state->nicam_on = 0; - state->watch_stereo = 1; - msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); + state->rxsubchans = V4L2_TUNER_SUB_MONO; break; case 0x0040: /* FM radio */ state->mode = MSP_MODE_FM_RADIO; state->rxsubchans = V4L2_TUNER_SUB_STEREO; - state->nicam_on = 0; - state->watch_stereo = 0; /* not needed in theory if we have radio, but short programming enables carrier mute */ - msp3400c_setmode(client, MSP_MODE_FM_RADIO); - msp3400c_setcarrier(client, MSP_CARRIER(10.7), + msp3400c_set_mode(client, MSP_MODE_FM_RADIO); + msp3400c_set_carrier(client, MSP_CARRIER(10.7), MSP_CARRIER(10.7)); - /* scart routing */ + /* scart routing (this doesn't belong here I think) */ msp_set_scart(client,SCART_IN2,0); - /* msp34xx does radio decoding */ - msp_write_dsp(client, 0x08, 0x0020); - msp_write_dsp(client, 0x09, 0x0020); - msp_write_dsp(client, 0x0b, 0x0020); break; case 0x0003: case 0x0004: case 0x0005: state->mode = MSP_MODE_FM_TERRA; state->rxsubchans = V4L2_TUNER_SUB_MONO; - state->nicam_on = 0; state->watch_stereo = 1; break; } @@ -788,11 +754,16 @@ int msp3410d_thread(void *data) if (state->has_i2s_conf) msp_write_dem(client, 0x40, state->i2s_mode); - /* monitor tv audio mode */ + msp3400c_set_audmode(client); + + /* monitor tv audio mode, the first time don't wait + so long to get a quick stereo/bilingual result */ + if (msp_sleep(state, 1000)) + goto restart; while (state->watch_stereo) { - if (msp_sleep(state,5000)) - goto restart; watch_stereo(client); + if (msp_sleep(state, 5000)) + goto restart; } } v4l_dbg(1, msp_debug, client, "thread: exit\n"); @@ -810,7 +781,7 @@ int msp3410d_thread(void *data) * the value for source is the same as bit 15:8 of DSP registers 0x08, * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B * - * this function replaces msp3400c_setstereo + * this function replaces msp3400c_set_audmode */ static void msp34xxg_set_source(struct i2c_client *client, int source) { @@ -823,12 +794,7 @@ static void msp34xxg_set_source(struct i2c_client *client, int source) int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20); v4l_dbg(1, msp_debug, client, "set source to %d (0x%x)\n", source, value); - /* Loudspeaker Output */ - msp_write_dsp(client, 0x08, value); - /* SCART1 DA Output */ - msp_write_dsp(client, 0x0a, value); - /* Quasi-peak detector */ - msp_write_dsp(client, 0x0c, value); + msp_set_source(client, value); /* * set identification threshold. Personally, I * I set it to a higher value that the default @@ -945,13 +911,14 @@ int msp34xxg_thread(void *data) if (msp_write_dsp(client, 0x13, state->acb)) return -1; - msp_write_dem(client, 0x40, state->i2s_mode); + if (state->has_i2s_conf) + msp_write_dem(client, 0x40, state->i2s_mode); } v4l_dbg(1, msp_debug, client, "thread: exit\n"); return 0; } -void msp34xxg_detect_stereo(struct i2c_client *client) +static void msp34xxg_detect_stereo(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); @@ -961,11 +928,11 @@ void msp34xxg_detect_stereo(struct i2c_client *client) state->rxsubchans = 0; if (is_stereo) - state->rxsubchans |= V4L2_TUNER_SUB_STEREO; + state->rxsubchans = V4L2_TUNER_SUB_STEREO; else - state->rxsubchans |= V4L2_TUNER_SUB_MONO; + state->rxsubchans = V4L2_TUNER_SUB_MONO; if (is_bilingual) { - state->rxsubchans |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; /* I'm supposed to check whether it's SAP or not * and set only LANG2/SAP in this case. Yet, the MSP * does a lot of work to hide this and handle everything @@ -977,12 +944,12 @@ void msp34xxg_detect_stereo(struct i2c_client *client) status, is_stereo, is_bilingual, state->rxsubchans); } -void msp34xxg_set_audmode(struct i2c_client *client, int audmode) +void msp34xxg_set_audmode(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); int source; - switch (audmode) { + switch (state->audmode) { case V4L2_TUNER_MODE_MONO: source = 0; /* mono only */ break; @@ -997,11 +964,40 @@ void msp34xxg_set_audmode(struct i2c_client *client, int audmode) source = 4; /* stereo or B */ break; default: - audmode = 0; source = 1; break; } - state->audmode = audmode; msp34xxg_set_source(client, source); } +void msp_set_audmode(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + + switch (state->opmode) { + case OPMODE_MANUAL: + case OPMODE_AUTODETECT: + state->watch_stereo = 0; + msp3400c_set_audmode(client); + break; + case OPMODE_AUTOSELECT: + msp34xxg_set_audmode(client); + break; + } +} + +void msp_detect_stereo(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + + switch (state->opmode) { + case OPMODE_MANUAL: + case OPMODE_AUTODETECT: + msp3400c_detect_stereo(client); + break; + case OPMODE_AUTOSELECT: + msp34xxg_detect_stereo(client); + break; + } +} + diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index a9ac57d0700b..418283002130 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h @@ -104,14 +104,13 @@ int msp_sleep(struct msp_state *state, int timeout); /* msp3400-kthreads.c */ const char *msp_standard_std_name(int std); -void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2); -void msp3400c_setmode(struct i2c_client *client, int type); -void msp3400c_setstereo(struct i2c_client *client, int mode); -int autodetect_stereo(struct i2c_client *client); +void msp_set_source(struct i2c_client *client, u16 src); +void msp_set_audmode(struct i2c_client *client); +void msp_detect_stereo(struct i2c_client *client); int msp3400c_thread(void *data); int msp3410d_thread(void *data); int msp34xxg_thread(void *data); -void msp34xxg_detect_stereo(struct i2c_client *client); -void msp34xxg_set_audmode(struct i2c_client *client, int audmode); +void msp3400c_set_mode(struct i2c_client *client, int mode); +void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2); #endif /* MSP3400_H */ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 2995b22acb43..af3e7bb13813 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -398,15 +398,16 @@ static void tuner_status(struct i2c_client *client) tuner_info("Tuner mode: %s\n", p); tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction); tuner_info("Standard: 0x%08llx\n", t->std); - if (t->mode == V4L2_TUNER_RADIO) { - if (t->has_signal) { - tuner_info("Signal strength: %d\n", t->has_signal(client)); - } - if (t->is_stereo) { - tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no"); - } + if (t->mode != V4L2_TUNER_RADIO) + return; + if (t->has_signal) { + tuner_info("Signal strength: %d\n", t->has_signal(client)); + } + if (t->is_stereo) { + tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no"); } } + /* ---------------------------------------------------------------------- */ /* static var Used only in tuner_attach and tuner_probe */ @@ -737,33 +738,29 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; switch_v4l2(); - if (V4L2_TUNER_RADIO == t->mode) { - - if (t->has_signal) - tuner->signal = t->has_signal(client); - - if (t->is_stereo) { - if (t->is_stereo(client)) { - tuner->rxsubchans = - V4L2_TUNER_SUB_STEREO | - V4L2_TUNER_SUB_MONO; - } else { - tuner->rxsubchans = - V4L2_TUNER_SUB_MONO; - } - } - - tuner->capability |= - V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; - - tuner->audmode = t->audmode; - - tuner->rangelow = radio_range[0] * 16000; - tuner->rangehigh = radio_range[1] * 16000; - } else { + tuner->type = t->mode; + if (t->mode != V4L2_TUNER_RADIO) { tuner->rangelow = tv_range[0] * 16; tuner->rangehigh = tv_range[1] * 16; + break; + } + + /* radio mode */ + if (t->has_signal) + tuner->signal = t->has_signal(client); + + tuner->rxsubchans = + V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + if (t->is_stereo) { + tuner->rxsubchans = t->is_stereo(client) ? + V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; } + + tuner->capability |= + V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + tuner->audmode = t->audmode; + tuner->rangelow = radio_range[0] * 16000; + tuner->rangehigh = radio_range[1] * 16000; break; } case VIDIOC_S_TUNER: @@ -775,10 +772,11 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) switch_v4l2(); - if (V4L2_TUNER_RADIO == t->mode) { - t->audmode = tuner->audmode; - set_radio_freq(client, t->radio_freq); - } + /* do nothing unless we're a radio tuner */ + if (t->mode != V4L2_TUNER_RADIO) + break; + t->audmode = tuner->audmode; + set_radio_freq(client, t->radio_freq); break; } case VIDIOC_LOG_STATUS: diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index c8e5ad0e8185..4efb01bb44ac 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -130,6 +130,7 @@ struct CHIPSTATE { struct timer_list wt; int done; int watch_stereo; + int audmode; }; /* ---------------------------------------------------------------------- */ @@ -1514,6 +1515,7 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind) chip->type = desc-chiplist; chip->shadow.count = desc->registers+1; chip->prevmode = -1; + chip->audmode = V4L2_TUNER_MODE_LANG1; /* register */ i2c_attach_client(&chip->c); @@ -1671,6 +1673,8 @@ static int chip_command(struct i2c_client *client, struct v4l2_tuner *vt = arg; int mode = 0; + if (chip->radio) + break; switch (vt->audmode) { case V4L2_TUNER_MODE_MONO: mode = VIDEO_SOUND_MONO; @@ -1685,8 +1689,9 @@ static int chip_command(struct i2c_client *client, mode = VIDEO_SOUND_LANG2; break; default: - break; + return -EINVAL; } + chip->audmode = vt->audmode; if (desc->setmode && mode) { chip->watch_stereo = 0; @@ -1704,7 +1709,7 @@ static int chip_command(struct i2c_client *client, if (chip->radio) break; - vt->audmode = 0; + vt->audmode = chip->audmode; vt->rxsubchans = 0; vt->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; @@ -1716,19 +1721,12 @@ static int chip_command(struct i2c_client *client, vt->rxsubchans |= V4L2_TUNER_SUB_MONO; if (mode & VIDEO_SOUND_STEREO) vt->rxsubchans |= V4L2_TUNER_SUB_STEREO; + /* Note: for SAP it should be mono/lang2 or stereo/lang2. + When this module is converted fully to v4l2, then this + should change for those chips that can detect SAP. */ if (mode & VIDEO_SOUND_LANG1) - vt->rxsubchans |= V4L2_TUNER_SUB_LANG1 | - V4L2_TUNER_SUB_LANG2; - - mode = chip->mode; - if (mode & VIDEO_SOUND_MONO) - vt->audmode = V4L2_TUNER_MODE_MONO; - if (mode & VIDEO_SOUND_STEREO) - vt->audmode = V4L2_TUNER_MODE_STEREO; - if (mode & VIDEO_SOUND_LANG1) - vt->audmode = V4L2_TUNER_MODE_LANG1; - if (mode & VIDEO_SOUND_LANG2) - vt->audmode = V4L2_TUNER_MODE_LANG2; + vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | + V4L2_TUNER_SUB_LANG2; break; } -- cgit v1.2.3-59-g8ed1b From 703cb2cbf4250215e67f4a04081e4ea9d9f34bc9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 23 Jan 2006 17:11:09 -0200 Subject: V4L/DVB (3428): drivers/media/dvb/ possible cleanups - Make needlessly global code static - #if 0 the following unused global functions: - b2c2/flexcop-dma.c: flexcop_dma_control_packet_irq() - b2c2/flexcop-dma.c: flexcop_dma_config_packet_count() Signed-off-by: Adrian Bunk Signed-off-by: Patrick Boettcher Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop-common.h | 2 -- drivers/media/dvb/b2c2/flexcop-dma.c | 35 ---------------------------- drivers/media/dvb/b2c2/flexcop-misc.c | 6 ++--- drivers/media/dvb/b2c2/flexcop-reg.h | 4 ---- drivers/media/dvb/dvb-usb/cxusb.c | 8 +++---- drivers/media/dvb/dvb-usb/dvb-usb-firmware.c | 8 ++++--- drivers/media/dvb/dvb-usb/dvb-usb.h | 1 - drivers/media/dvb/dvb-usb/vp702x.c | 6 +++-- drivers/media/dvb/dvb-usb/vp702x.h | 2 -- drivers/media/dvb/ttpci/av7110.h | 2 -- drivers/media/dvb/ttpci/av7110_ir.c | 26 ++++++++++----------- 11 files changed, 29 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h index 344a3c898460..7d7e1613c5a7 100644 --- a/drivers/media/dvb/b2c2/flexcop-common.h +++ b/drivers/media/dvb/b2c2/flexcop-common.h @@ -116,11 +116,9 @@ void flexcop_dma_free(struct flexcop_dma *dma); int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); -int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx); int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff); int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles); -int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets); /* from flexcop-eeprom.c */ /* the PCI part uses this call to get the MAC address, the USB part has its own */ diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c index cf4ed1df6086..6f592bc32d22 100644 --- a/drivers/media/dvb/b2c2/flexcop-dma.c +++ b/drivers/media/dvb/b2c2/flexcop-dma.c @@ -169,38 +169,3 @@ int flexcop_dma_config_timer(struct flexcop_device *fc, } EXPORT_SYMBOL(flexcop_dma_config_timer); -/* packet IRQ does not exist in FCII or FCIIb - according to data book and tests */ -int flexcop_dma_control_packet_irq(struct flexcop_device *fc, - flexcop_dma_index_t no, - int onoff) -{ - flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); - - deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw); - if (no & FC_DMA_1) - v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff; - - if (no & FC_DMA_2) - v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff; - - fc->write_ibi_reg(fc,ctrl_208,v); - deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw); - - return 0; -} -EXPORT_SYMBOL(flexcop_dma_control_packet_irq); - -int flexcop_dma_config_packet_count(struct flexcop_device *fc, - flexcop_dma_index_t dma_idx, - u8 packets) -{ - flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; - flexcop_ibi_value v = fc->read_ibi_reg(fc,r); - - flexcop_dma_remap(fc,dma_idx,1); - - v.dma_0x4_remap.DMA_maxpackets = packets; - fc->write_ibi_reg(fc,r,v); - return 0; -} -EXPORT_SYMBOL(flexcop_dma_config_packet_count); diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c index 62282d8dbfa8..167583bf0621 100644 --- a/drivers/media/dvb/b2c2/flexcop-misc.c +++ b/drivers/media/dvb/b2c2/flexcop-misc.c @@ -36,14 +36,14 @@ void flexcop_determine_revision(struct flexcop_device *fc) /* bus parts have to decide if hw pid filtering is used or not. */ } -const char *flexcop_revision_names[] = { +static const char *flexcop_revision_names[] = { "Unkown chip", "FlexCopII", "FlexCopIIb", "FlexCopIII", }; -const char *flexcop_device_names[] = { +static const char *flexcop_device_names[] = { "Unkown device", "Air2PC/AirStar 2 DVB-T", "Air2PC/AirStar 2 ATSC 1st generation", @@ -54,7 +54,7 @@ const char *flexcop_device_names[] = { "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", }; -const char *flexcop_bus_names[] = { +static const char *flexcop_bus_names[] = { "USB", "PCI", }; diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h index 3153f9513c63..491f9bd6e195 100644 --- a/drivers/media/dvb/b2c2/flexcop-reg.h +++ b/drivers/media/dvb/b2c2/flexcop-reg.h @@ -16,8 +16,6 @@ typedef enum { FLEXCOP_III, } flexcop_revision_t; -extern const char *flexcop_revision_names[]; - typedef enum { FC_UNK = 0, FC_AIR_DVB, @@ -34,8 +32,6 @@ typedef enum { FC_PCI, } flexcop_bus_t; -extern const char *flexcop_device_names[]; - /* FlexCop IBI Registers */ #if defined(__LITTLE_ENDIAN) #include "flexcop_ibi_value_le.h" diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index a7fb06f4cd34..f14003736afe 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -184,7 +184,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) return 0; } -struct dvb_usb_rc_key dvico_mce_rc_keys[] = { +static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { { 0xfe, 0x02, KEY_TV }, { 0xfe, 0x0e, KEY_MP3 }, { 0xfe, 0x1a, KEY_DVD }, @@ -273,7 +273,7 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe) return 0; } -struct cx22702_config cxusb_cx22702_config = { +static struct cx22702_config cxusb_cx22702_config = { .demod_address = 0x63, .output_mode = CX22702_PARALLEL_OUTPUT, @@ -282,13 +282,13 @@ struct cx22702_config cxusb_cx22702_config = { .pll_set = dvb_usb_pll_set_i2c, }; -struct lgdt330x_config cxusb_lgdt330x_config = { +static struct lgdt330x_config cxusb_lgdt330x_config = { .demod_address = 0x0e, .demod_chip = LGDT3303, .pll_set = dvb_usb_pll_set_i2c, }; -struct mt352_config cxusb_dee1601_config = { +static struct mt352_config cxusb_dee1601_config = { .demod_address = 0x0f, .demod_init = cxusb_dee1601_demod_init, .pll_set = dvb_usb_pll_set, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c index 8535895819fb..9222b0a81f74 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c @@ -24,6 +24,9 @@ static struct usb_cypress_controller cypress[] = { { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, }; +static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, + int *pos); + /* * load a firmware packet to the device */ @@ -112,7 +115,8 @@ int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties return ret; } -int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos) +static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, + int *pos) { u8 *b = (u8 *) &fw->data[*pos]; int data_offs = 4; @@ -142,5 +146,3 @@ int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos) return *pos; } -EXPORT_SYMBOL(dvb_usb_get_hexline); - diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index dd568396e594..5e5d21ad93c9 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -341,7 +341,6 @@ struct hexline { u8 data[255]; u8 chk; }; -extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *); extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type); #endif diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index afa00fdb5ec0..4a95eca81c5c 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c @@ -53,7 +53,8 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 return ret; } -int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) +static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, + u16 index, u8 *b, int blen) { deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); debug_dump(b,blen,deb_xfer); @@ -88,7 +89,8 @@ unlock: return ret; } -int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec) +static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, + int olen, u8 *i, int ilen, int msec) { u8 bout[olen+2]; u8 bin[ilen+1]; diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h index a808d48e7bf2..c2f97f96c21f 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.h +++ b/drivers/media/dvb/dvb-usb/vp702x.h @@ -101,8 +101,6 @@ extern int dvb_usb_vp702x_debug; extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d); extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); -extern int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec); extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); -extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); #endif diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index 6ea30df2e823..fafd25fab835 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h @@ -273,8 +273,6 @@ struct av7110 { extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, u16 subpid, u16 pcrpid); -extern int av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config); - extern int av7110_ir_init(struct av7110 *av7110); extern void av7110_ir_exit(struct av7110 *av7110); diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index 9138132ad25f..617e4f6c0ed7 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c @@ -155,6 +155,19 @@ static void input_repeat_key(unsigned long data) } +static int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config) +{ + int ret = 0; + + dprintk(4, "%p\n", av7110); + if (av7110) { + ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config); + av7110->ir_config = ir_config; + } + return ret; +} + + static int av7110_ir_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) { @@ -187,19 +200,6 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer, } -int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config) -{ - int ret = 0; - - dprintk(4, "%p\n", av7110); - if (av7110) { - ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config); - av7110->ir_config = ir_config; - } - return ret; -} - - static void ir_handler(struct av7110 *av7110, u32 ircom) { dprintk(4, "ircommand = %08x\n", ircom); -- cgit v1.2.3-59-g8ed1b From ac272ed7f1ae15084c64bdc4d3b4578ec2a0830b Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Mon, 23 Jan 2006 17:11:09 -0200 Subject: V4L/DVB (3429): Missing break statement on tuner-core - default_tuner_init was called twice due to a missing break statement. Signed-off-by: Markus Rechberger Acked-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index af3e7bb13813..cd2d5a70cdc1 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -216,6 +216,7 @@ static void set_type(struct i2c_client *c, unsigned int type, buffer[3] = 0xa4; i2c_master_send(c,buffer,4); default_tuner_init(c); + break; default: default_tuner_init(c); break; -- cgit v1.2.3-59-g8ed1b From cbcf749382a7bbf70b1bbf6eeb3234d1682c9f17 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 23 Jan 2006 17:11:10 -0200 Subject: V4L/DVB (3431): fixed spelling error, exectuted --> executed. - fixed spelling error, exectuted --> executed. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index dff3893f32fd..82f0c5fb2417 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -253,7 +253,7 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val) if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) return ret; else if (((u8) ret) & 0x01) { - em28xx_warn ("AC97 command still being exectuted: not handled properly!\n"); + em28xx_warn ("AC97 command still being executed: not handled properly!\n"); } return 0; } -- cgit v1.2.3-59-g8ed1b From a94e95b443811c127734ef10f3b7d2220532c1d2 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Mon, 23 Jan 2006 17:11:10 -0200 Subject: V4L/DVB (3432): Hauppauge HVR 900 Composite support - Hauppauge HVR 900 Composite support Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 67 ++++++++++++++++++++++++------- drivers/media/video/em28xx/em28xx-video.c | 1 + drivers/media/video/em28xx/em28xx.h | 2 + 3 files changed, 56 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 58f7b4194a0d..ed428c58b73d 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -136,6 +136,28 @@ struct em28xx_board em28xx_boards[] = { .amux = 1, }}, }, + [EM2880_BOARD_WINTV_HVR_900] = { + .name = "WinTV HVR 900", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .has_tuner = 0, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM28XX_TVP5150, + .input = {{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 2, + .amux = 0, + },{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, [EM2820_BOARD_MSI_VOX_USB_2] = { .name = "MSI VOX USB 2.0", .vchannels = 3, @@ -254,30 +276,47 @@ struct usb_device_id em28xx_id_table [] = { { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, + { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_WINTV_HVR_900 }, { }, }; +void em28xx_pre_card_setup(struct em28xx *dev) +{ + /* request some modules */ + switch(dev->model){ + case EM2880_BOARD_WINTV_HVR_900: + { + em28xx_write_regs_req(dev, 0x00, 0x08, "\x7d", 1); // reset through GPIO? + break; + } + } +} + void em28xx_card_setup(struct em28xx *dev) { /* request some modules */ - if (dev->model == EM2820_BOARD_HAUPPAUGE_WINTV_USB_2) { - struct tveeprom tv; + switch(dev->model){ + case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: + { + struct tveeprom tv; #ifdef CONFIG_MODULES - request_module("tveeprom"); - request_module("ir-kbd-i2c"); - request_module("msp3400"); + request_module("tveeprom"); + request_module("ir-kbd-i2c"); + request_module("msp3400"); #endif - /* Call first TVeeprom */ + /* Call first TVeeprom */ - dev->i2c_client.addr = 0xa0 >> 1; - tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata); + dev->i2c_client.addr = 0xa0 >> 1; + tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata); - dev->tuner_type= tv.tuner_type; - if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { - dev->i2s_speed=2048000; - dev->has_msp34xx=1; - } else - dev->has_msp34xx=0; + dev->tuner_type= tv.tuner_type; + if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { + dev->i2s_speed=2048000; + dev->has_msp34xx=1; + } else + dev->has_msp34xx=0; + break; + } } } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 1b0e10d5edd4..1726b2c26b6c 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1766,6 +1766,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->vpic.depth = 16; dev->vpic.palette = VIDEO_PALETTE_YUV422; + em28xx_pre_card_setup(dev); #ifdef CONFIG_MODULES /* request some modules */ if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114) diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 119fdbedc7bf..8269cca7dcdb 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -41,6 +41,7 @@ #define EM2800_BOARD_LEADTEK_WINFAST_USBII 7 #define EM2800_BOARD_KWORLD_USB2800 8 #define EM2820_BOARD_PINNACLE_DVC_90 9 +#define EM2880_BOARD_WINTV_HVR_900 10 #define UNSET -1 @@ -327,6 +328,7 @@ int em28xx_set_alternate(struct em28xx *dev); /* Provided by em28xx-cards.c */ extern int em2800_variant_detect(struct usb_device* udev,int model); +extern void em28xx_pre_card_setup(struct em28xx *dev); extern void em28xx_card_setup(struct em28xx *dev); extern struct em28xx_board em28xx_boards[]; extern struct usb_device_id em28xx_id_table[]; -- cgit v1.2.3-59-g8ed1b From 9df8e9456d74c7ac749a1ebfb54a3cc36e46a602 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 23 Jan 2006 17:11:10 -0200 Subject: V4L/DVB (3433): Fix printk type warning - Fix printk type warning: drivers/media/dvb/b2c2/flexcop-pci.c:164: warning: format '%08x' expects type 'unsigned int', but argument 4 has type 'dma_addr_t' Signed-off-by: Randy Dunlap Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop-pci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 2f76eb3fea40..9bc40bdcc282 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -161,8 +161,10 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs) fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; - deb_irq("%u irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ", - jiffies_to_usecs(jiffies - fc_pci->last_irq),v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos); + deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ", + jiffies_to_usecs(jiffies - fc_pci->last_irq), + v.raw, (unsigned long long)cur_addr, cur_pos, + fc_pci->last_dma1_cur_pos); fc_pci->last_irq = jiffies; /* buffer end was reached, restarted from the beginning -- cgit v1.2.3-59-g8ed1b From 257c645d3dc90ee8b7c0640da8d9ea1b2cbe95c4 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Mon, 23 Jan 2006 17:11:11 -0200 Subject: V4L/DVB (3434): changed comment in tuner-core.c - changed comment in tuner-core.c Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index cd2d5a70cdc1..788eadaae672 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -450,7 +450,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) printk("%02x ",buffer[i]); printk("\n"); } - /* TEA5767 autodetection code - only for addr = 0xc0 */ + /* autodetection code based on the i2c addr */ if (!no_autodetect) { switch (addr) { case 0x42: -- cgit v1.2.3-59-g8ed1b From ab66b22f0c4e5786d59fa23569ac37a4a21ab4fb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 23 Jan 2006 17:11:11 -0200 Subject: V4L/DVB (3435): rename cb variable names in tuner structures for global consistency - rename cb variable names in tuner structures for global consistency Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 4 ++-- drivers/media/dvb/frontends/dvb-pll.h | 4 ++-- drivers/media/video/tuner-simple.c | 40 +++++++++++++++++------------------ 3 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 4dcb6050d4fa..cd8f28275ed6 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -391,8 +391,8 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, div = (freq + desc->entries[i].offset) / desc->entries[i].stepsize; buf[0] = div >> 8; buf[1] = div & 0xff; - buf[2] = desc->entries[i].cb1; - buf[3] = desc->entries[i].cb2; + buf[2] = desc->entries[i].config; + buf[3] = desc->entries[i].cb; if (desc->setbw) desc->setbw(buf, freq, bandwidth); diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index bb8d4b4eb183..872e3b4c1396 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -15,8 +15,8 @@ struct dvb_pll_desc { u32 limit; u32 offset; u32 stepsize; - u8 cb1; - u8 cb2; + u8 config; + u8 cb; } entries[12]; }; diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 37977ff49780..2c6410cc0fe9 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -133,7 +133,7 @@ static int tuner_stereo(struct i2c_client *c) static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); - u8 config, tuneraddr; + u8 cb, tuneraddr; u16 div; struct tunertype *tun; u8 buffer[4]; @@ -152,7 +152,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) freq, tun->params[j].ranges[i - 1].limit); freq = tun->params[j].ranges[--i].limit; } - config = tun->params[j].ranges[i].cb; + cb = tun->params[j].ranges[i].cb; /* i == 0 -> VHF_LO */ /* i == 1 -> VHF_HI */ /* i == 2 -> UHF */ @@ -164,40 +164,40 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) /* 0x01 -> ??? no change ??? */ /* 0x02 -> PAL BDGHI / SECAM L */ /* 0x04 -> ??? PAL others / SECAM others ??? */ - config &= ~0x02; + cb &= ~0x02; if (t->std & V4L2_STD_SECAM) - config |= 0x02; + cb |= 0x02; break; case TUNER_TEMIC_4046FM5: - config &= ~0x0f; + cb &= ~0x0f; if (t->std & V4L2_STD_PAL_BG) { - config |= TEMIC_SET_PAL_BG; + cb |= TEMIC_SET_PAL_BG; } else if (t->std & V4L2_STD_PAL_I) { - config |= TEMIC_SET_PAL_I; + cb |= TEMIC_SET_PAL_I; } else if (t->std & V4L2_STD_PAL_DK) { - config |= TEMIC_SET_PAL_DK; + cb |= TEMIC_SET_PAL_DK; } else if (t->std & V4L2_STD_SECAM_L) { - config |= TEMIC_SET_PAL_L; + cb |= TEMIC_SET_PAL_L; } break; case TUNER_PHILIPS_FQ1216ME: - config &= ~0x0f; + cb &= ~0x0f; if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { - config |= PHILIPS_SET_PAL_BGDK; + cb |= PHILIPS_SET_PAL_BGDK; } else if (t->std & V4L2_STD_PAL_I) { - config |= PHILIPS_SET_PAL_I; + cb |= PHILIPS_SET_PAL_I; } else if (t->std & V4L2_STD_SECAM_L) { - config |= PHILIPS_SET_PAL_L; + cb |= PHILIPS_SET_PAL_L; } break; @@ -207,9 +207,9 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) /* 0x01 -> ATSC antenna input 2 */ /* 0x02 -> NTSC antenna input 1 */ /* 0x03 -> NTSC antenna input 2 */ - config &= ~0x03; + cb &= ~0x03; if (!(t->std & V4L2_STD_ATSC)) - config |= 2; + cb |= 2; /* FIXME: input */ break; @@ -227,9 +227,9 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) buffer[1] = 0x00; buffer[2] = 0x17; buffer[3] = 0x00; - config &= ~0x40; + cb &= ~0x40; if (t->std & V4L2_STD_ATSC) { - config |= 0x40; + cb |= 0x40; buffer[1] = 0x04; } /* set to the correct mode (analog or digital) */ @@ -277,14 +277,14 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) { buffer[0] = tun->params[j].config; - buffer[1] = config; + buffer[1] = cb; buffer[2] = (div>>8) & 0x7f; buffer[3] = div & 0xff; } else { buffer[0] = (div>>8) & 0x7f; buffer[1] = div & 0xff; buffer[2] = tun->params[j].config; - buffer[3] = config; + buffer[3] = cb; } t->last_div = div; tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", @@ -316,7 +316,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) buffer[0] = (div>>8) & 0x7f; buffer[1] = div & 0xff; buffer[2] = tun->params[j].config; - buffer[3] = config; + buffer[3] = cb; tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); -- cgit v1.2.3-59-g8ed1b From 3fc46d35b30cfae018c4903228a270c9543f4d7a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 23 Jan 2006 17:11:11 -0200 Subject: V4L/DVB (3436): move config byte from tuner_params to tuner_range struct. - Move config byte from tuner_params to tuner_range struct. - dvb tuners must be able to set different config byte for each range. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 15 +- drivers/media/video/tuner-types.c | 395 ++++++++++++++++--------------------- include/media/tuner-types.h | 2 +- 3 files changed, 176 insertions(+), 236 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 2c6410cc0fe9..6f0d376f0d18 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -133,7 +133,7 @@ static int tuner_stereo(struct i2c_client *c) static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); - u8 cb, tuneraddr; + u8 config, cb, tuneraddr; u16 div; struct tunertype *tun; u8 buffer[4]; @@ -152,6 +152,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) freq, tun->params[j].ranges[i - 1].limit); freq = tun->params[j].ranges[--i].limit; } + config = tun->params[j].ranges[i].config; cb = tun->params[j].ranges[i].cb; /* i == 0 -> VHF_LO */ /* i == 1 -> VHF_HI */ @@ -215,7 +216,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) case TUNER_MICROTUNE_4042FI5: /* Set the charge pump for fast tuning */ - tun->params[j].config |= TUNER_CHARGE_PUMP; + config |= TUNER_CHARGE_PUMP; break; case TUNER_PHILIPS_TUV1236D: @@ -276,14 +277,14 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) div); if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) { - buffer[0] = tun->params[j].config; + buffer[0] = config; buffer[1] = cb; buffer[2] = (div>>8) & 0x7f; buffer[3] = div & 0xff; } else { buffer[0] = (div>>8) & 0x7f; buffer[1] = div & 0xff; - buffer[2] = tun->params[j].config; + buffer[2] = config; buffer[3] = cb; } t->last_div = div; @@ -312,10 +313,10 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) } /* Set the charge pump for optimized phase noise figure */ - tun->params[j].config &= ~TUNER_CHARGE_PUMP; + config &= ~TUNER_CHARGE_PUMP; buffer[0] = (div>>8) & 0x7f; buffer[1] = div & 0xff; - buffer[2] = tun->params[j].config; + buffer[2] = config; buffer[3] = cb; tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); @@ -337,7 +338,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) j = TUNER_PARAM_ANALOG; div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */ - buffer[2] = (tun->params[j].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ + buffer[2] = (tun->params[j].ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ switch (t->type) { case TUNER_TENA_9533_DI: diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 6fe781798d89..d37f833997dd 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -36,9 +36,9 @@ /* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_pal_ranges[] = { - { 16 * 140.25 /*MHz*/, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, + { 16 * 140.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x04, }, + { 16 * 999.99 , 0x8e, 0x01, }, }; static struct tuner_params tuner_temic_pal_params[] = { @@ -46,16 +46,15 @@ static struct tuner_params tuner_temic_pal_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_pal_ranges, .count = ARRAY_SIZE(tuner_temic_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */ static struct tuner_range tuner_philips_pal_i_ranges[] = { - { 16 * 140.25 /*MHz*/, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 140.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_pal_i_params[] = { @@ -63,16 +62,15 @@ static struct tuner_params tuner_philips_pal_i_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_pal_i_ranges, .count = ARRAY_SIZE(tuner_philips_pal_i_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */ static struct tuner_range tuner_philips_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0xa0, }, - { 16 * 451.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 451.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_ntsc_params[] = { @@ -80,7 +78,6 @@ static struct tuner_params tuner_philips_ntsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_philips_ntsc_ranges, .count = ARRAY_SIZE(tuner_philips_ntsc_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -88,9 +85,9 @@ static struct tuner_params tuner_philips_ntsc_params[] = { /* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */ static struct tuner_range tuner_philips_secam_ranges[] = { - { 16 * 168.25 /*MHz*/, 0xa7, }, - { 16 * 447.25 /*MHz*/, 0x97, }, - { 16 * 999.99 , 0x37, }, + { 16 * 168.25 /*MHz*/, 0x8e, 0xa7, }, + { 16 * 447.25 /*MHz*/, 0x8e, 0x97, }, + { 16 * 999.99 , 0x8e, 0x37, }, }; static struct tuner_params tuner_philips_secam_params[] = { @@ -98,7 +95,6 @@ static struct tuner_params tuner_philips_secam_params[] = { .type = TUNER_PARAM_TYPE_SECAM, .ranges = tuner_philips_secam_ranges, .count = ARRAY_SIZE(tuner_philips_secam_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -106,9 +102,9 @@ static struct tuner_params tuner_philips_secam_params[] = { /* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */ static struct tuner_range tuner_philips_pal_ranges[] = { - { 16 * 168.25 /*MHz*/, 0xa0, }, - { 16 * 447.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 447.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_pal_params[] = { @@ -116,7 +112,6 @@ static struct tuner_params tuner_philips_pal_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_pal_ranges, .count = ARRAY_SIZE(tuner_philips_pal_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -124,9 +119,9 @@ static struct tuner_params tuner_philips_pal_params[] = { /* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */ static struct tuner_range tuner_temic_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x04, }, + { 16 * 999.99 , 0x8e, 0x01, }, }; static struct tuner_params tuner_temic_ntsc_params[] = { @@ -134,16 +129,15 @@ static struct tuner_params tuner_temic_ntsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_temic_ntsc_ranges, .count = ARRAY_SIZE(tuner_temic_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */ static struct tuner_range tuner_temic_pal_i_ranges[] = { - { 16 * 170.00 /*MHz*/, 0x02, }, - { 16 * 450.00 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, + { 16 * 170.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 450.00 /*MHz*/, 0x8e, 0x04, }, + { 16 * 999.99 , 0x8e, 0x01, }, }; static struct tuner_params tuner_temic_pal_i_params[] = { @@ -151,16 +145,15 @@ static struct tuner_params tuner_temic_pal_i_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_pal_i_ranges, .count = ARRAY_SIZE(tuner_temic_pal_i_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */ static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = { @@ -168,16 +161,15 @@ static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_temic_4036fy5_ntsc_ranges, .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */ static struct tuner_range tuner_alps_tsb_1_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x01, }, - { 16 * 385.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 385.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = { @@ -185,7 +177,6 @@ static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_alps_tsb_1_ranges, .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges), - .config = 0x8e, }, }; @@ -197,16 +188,15 @@ static struct tuner_params tuner_alps_tsb_1_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_alps_tsb_1_ranges, .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */ static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = { - { 16 * 133.25 /*MHz*/, 0x01, }, - { 16 * 351.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 133.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 351.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_alps_tsbb5_params[] = { @@ -214,7 +204,6 @@ static struct tuner_params tuner_alps_tsbb5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_alps_tsb_5_pal_ranges, .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), - .config = 0x8e, }, }; @@ -225,7 +214,6 @@ static struct tuner_params tuner_alps_tsbe5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_alps_tsb_5_pal_ranges, .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), - .config = 0x8e, }, }; @@ -236,16 +224,15 @@ static struct tuner_params tuner_alps_tsbc5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_alps_tsb_5_pal_ranges, .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_4006fh5_pal_ranges[] = { - { 16 * 170.00 /*MHz*/, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 170.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4006fh5_params[] = { @@ -253,16 +240,15 @@ static struct tuner_params tuner_temic_4006fh5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4006fh5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4006fh5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */ static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x14, }, - { 16 * 385.25 /*MHz*/, 0x12, }, - { 16 * 999.99 , 0x11, }, + { 16 * 137.25 /*MHz*/, 0x8e, 0x14, }, + { 16 * 385.25 /*MHz*/, 0x8e, 0x12, }, + { 16 * 999.99 , 0x8e, 0x11, }, }; static struct tuner_params tuner_alps_tshc6_params[] = { @@ -270,16 +256,15 @@ static struct tuner_params tuner_alps_tshc6_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_alps_tshc6_ntsc_ranges, .count = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_pal_dk_ranges[] = { - { 16 * 168.25 /*MHz*/, 0xa0, }, - { 16 * 456.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 456.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_pal_dk_params[] = { @@ -287,16 +272,15 @@ static struct tuner_params tuner_temic_pal_dk_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_pal_dk_ranges, .count = ARRAY_SIZE(tuner_temic_pal_dk_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */ static struct tuner_range tuner_philips_ntsc_m_ranges[] = { - { 16 * 160.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_ntsc_m_params[] = { @@ -304,16 +288,15 @@ static struct tuner_params tuner_philips_ntsc_m_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_philips_ntsc_m_ranges, .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */ static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = { - { 16 * 169.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 169.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = { @@ -321,7 +304,6 @@ static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_40x6f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), - .config = 0x8e, }, }; @@ -332,7 +314,6 @@ static struct tuner_params tuner_temic_4006fn5_multi_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_40x6f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), - .config = 0x8e, }, }; @@ -340,9 +321,9 @@ static struct tuner_params tuner_temic_4006fn5_multi_params[] = { /* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = { - { 16 * 141.00 /*MHz*/, 0xa0, }, - { 16 * 464.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 141.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 464.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4009f_5_params[] = { @@ -350,16 +331,15 @@ static struct tuner_params tuner_temic_4009f_5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4009f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */ static struct tuner_range tuner_temic_4039fr5_ntsc_ranges[] = { - { 16 * 158.00 /*MHz*/, 0xa0, }, - { 16 * 453.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 158.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 453.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4039fr5_params[] = { @@ -367,16 +347,15 @@ static struct tuner_params tuner_temic_4039fr5_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_temic_4039fr5_ntsc_ranges, .count = ARRAY_SIZE(tuner_temic_4039fr5_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_4046fm5_pal_ranges[] = { - { 16 * 169.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 169.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4046fm5_params[] = { @@ -384,16 +363,15 @@ static struct tuner_params tuner_temic_4046fm5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4046fm5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4046fm5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */ static struct tuner_range tuner_lg_pal_ranges[] = { - { 16 * 170.00 /*MHz*/, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 170.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_pal_dk_params[] = { @@ -401,7 +379,6 @@ static struct tuner_params tuner_philips_pal_dk_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; @@ -412,7 +389,6 @@ static struct tuner_params tuner_philips_fq1216me_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; @@ -423,7 +399,6 @@ static struct tuner_params tuner_lg_pal_i_fm_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; @@ -434,16 +409,15 @@ static struct tuner_params tuner_lg_pal_i_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */ static struct tuner_range tuner_lg_ntsc_fm_ranges[] = { - { 16 * 210.00 /*MHz*/, 0xa0, }, - { 16 * 497.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 210.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 497.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_lg_ntsc_fm_params[] = { @@ -451,7 +425,6 @@ static struct tuner_params tuner_lg_ntsc_fm_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_lg_ntsc_fm_ranges, .count = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges), - .config = 0x8e, }, }; @@ -462,7 +435,6 @@ static struct tuner_params tuner_lg_pal_fm_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; @@ -473,7 +445,6 @@ static struct tuner_params tuner_lg_pal_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_pal_ranges, .count = ARRAY_SIZE(tuner_lg_pal_ranges), - .config = 0x8e, }, }; @@ -485,16 +456,15 @@ static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4009f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */ static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x01, }, - { 16 * 317.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 317.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_sharp_2u5jf5540_params[] = { @@ -502,16 +472,15 @@ static struct tuner_params tuner_sharp_2u5jf5540_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_sharp_2u5jf5540_ntsc_ranges, .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */ static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = { - { 16 * 169 /*MHz*/, 0xa0, }, - { 16 * 464 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 169 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 464 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = { @@ -519,7 +488,6 @@ static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_samsung_pal_tcpm9091pd27_ranges, .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges), - .config = 0x8e, }, }; @@ -530,16 +498,15 @@ static struct tuner_params tuner_temic_4106fh5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4009f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */ static struct tuner_range tuner_temic_4012fy5_pal_ranges[] = { - { 16 * 140.25 /*MHz*/, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, + { 16 * 140.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x04, }, + { 16 * 999.99 , 0x8e, 0x01, }, }; static struct tuner_params tuner_temic_4012fy5_params[] = { @@ -547,16 +514,15 @@ static struct tuner_params tuner_temic_4012fy5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4012fy5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4012fy5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */ static struct tuner_range tuner_temic_4136_fy5_ntsc_ranges[] = { - { 16 * 158.00 /*MHz*/, 0xa0, }, - { 16 * 453.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 158.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 453.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_temic_4136_fy5_params[] = { @@ -564,16 +530,15 @@ static struct tuner_params tuner_temic_4136_fy5_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_temic_4136_fy5_ntsc_ranges, .count = ARRAY_SIZE(tuner_temic_4136_fy5_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */ static struct tuner_range tuner_lg_new_tapc_ranges[] = { - { 16 * 170.00 /*MHz*/, 0x01, }, - { 16 * 450.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 170.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 450.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_lg_pal_new_tapc_params[] = { @@ -581,16 +546,15 @@ static struct tuner_params tuner_lg_pal_new_tapc_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_lg_new_tapc_ranges, .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */ static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = { - { 16 * 158.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 158.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_fm1216me_mk3_params[] = { @@ -598,7 +562,6 @@ static struct tuner_params tuner_fm1216me_mk3_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_fm1216me_mk3_pal_ranges, .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -610,7 +573,6 @@ static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_lg_new_tapc_ranges, .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), - .config = 0x8e, }, }; @@ -622,16 +584,15 @@ static struct tuner_params tuner_hitachi_ntsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_lg_new_tapc_ranges, .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */ static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = { - { 16 * 140.25 /*MHz*/, 0x01, }, - { 16 * 463.25 /*MHz*/, 0xc2, }, - { 16 * 999.99 , 0xcf, }, + { 16 * 140.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0xc2, }, + { 16 * 999.99 , 0x8e, 0xcf, }, }; static struct tuner_params tuner_philips_pal_mk_params[] = { @@ -639,16 +600,15 @@ static struct tuner_params tuner_philips_pal_mk_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_pal_mk_pal_ranges, .count = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_ATSC - Philips ATSC ------------ */ static struct tuner_range tuner_philips_atsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_philips_atsc_params[] = { @@ -656,16 +616,15 @@ static struct tuner_params tuner_philips_atsc_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_philips_atsc_ranges, .count = ARRAY_SIZE(tuner_philips_atsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */ static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_fm1236_mk3_params[] = { @@ -673,7 +632,6 @@ static struct tuner_params tuner_fm1236_mk3_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_fm1236_mk3_ntsc_ranges, .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -681,9 +639,9 @@ static struct tuner_params tuner_fm1236_mk3_params[] = { /* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */ static struct tuner_range tuner_philips_4in1_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_philips_4in1_params[] = { @@ -691,7 +649,6 @@ static struct tuner_params tuner_philips_4in1_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_philips_4in1_ntsc_ranges, .count = ARRAY_SIZE(tuner_philips_4in1_ntsc_ranges), - .config = 0x8e, }, }; @@ -702,16 +659,15 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_temic_4009f_5_pal_ranges, .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */ static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 160.00 /*MHz*/, 0xce, 0x01, }, + { 16 * 454.00 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x08, }, }; static struct tuner_params tuner_panasonic_vp27_params[] = { @@ -719,16 +675,15 @@ static struct tuner_params tuner_panasonic_vp27_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_panasonic_vp27_ntsc_ranges, .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges), - .config = 0xce, }, }; /* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */ static struct tuner_range tuner_lg_ntsc_tape_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_lg_ntsc_tape_params[] = { @@ -736,16 +691,15 @@ static struct tuner_params tuner_lg_ntsc_tape_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_lg_ntsc_tape_ranges, .count = ARRAY_SIZE(tuner_lg_ntsc_tape_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { - { 16 * 161.25 /*MHz*/, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 161.25 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_tnf_8831bgff_params[] = { @@ -753,16 +707,15 @@ static struct tuner_params tuner_tnf_8831bgff_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_tnf_8831bgff_pal_ranges, .count = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */ static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = { - { 16 * 162.00 /*MHz*/, 0xa2, }, - { 16 * 457.00 /*MHz*/, 0x94, }, - { 16 * 999.99 , 0x31, }, + { 16 * 162.00 /*MHz*/, 0x8e, 0xa2, }, + { 16 * 457.00 /*MHz*/, 0x8e, 0x94, }, + { 16 * 999.99 , 0x8e, 0x31, }, }; static struct tuner_params tuner_microtune_4042fi5_params[] = { @@ -770,7 +723,6 @@ static struct tuner_params tuner_microtune_4042fi5_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_microtune_4042fi5_ntsc_ranges, .count = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges), - .config = 0x8e, }, }; @@ -778,9 +730,9 @@ static struct tuner_params tuner_microtune_4042fi5_params[] = { /* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */ static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = { - { 16 * 172.00 /*MHz*/, 0x01, }, - { 16 * 448.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 172.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 448.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_tcl_2002n_params[] = { @@ -788,7 +740,6 @@ static struct tuner_params tuner_tcl_2002n_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_tcl_2002n_ntsc_ranges, .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges), - .config = 0x8e, .cb_first_if_lower_freq = 1, }, }; @@ -796,9 +747,9 @@ static struct tuner_params tuner_tcl_2002n_params[] = { /* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */ static struct tuner_range tuner_philips_fm1256_ih3_pal_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_philips_fm1256_ih3_params[] = { @@ -806,16 +757,15 @@ static struct tuner_params tuner_philips_fm1256_ih3_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_fm1256_ih3_pal_ranges, .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */ static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x39, }, - { 16 * 454.00 /*MHz*/, 0x3a, }, - { 16 * 999.99 , 0x3c, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0x39, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x3a, }, + { 16 * 999.99 , 0x8e, 0x3c, }, }; static struct tuner_params tuner_thomson_dtt7610_params[] = { @@ -823,16 +773,15 @@ static struct tuner_params tuner_thomson_dtt7610_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_thomson_dtt7610_ntsc_ranges, .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */ static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x41, }, - { 16 * 454.00 /*MHz*/, 0x42, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x41, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x42, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_philips_fq1286_params[] = { @@ -840,16 +789,15 @@ static struct tuner_params tuner_philips_fq1286_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_philips_fq1286_ntsc_ranges, .count = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */ static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = { - { 16 * 170.00 /*MHz*/, 0x01, }, - { 16 * 450.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 170.00 /*MHz*/, 0xce, 0x01, }, + { 16 * 450.00 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x08, }, }; static struct tuner_params tuner_tcl_2002mb_params[] = { @@ -857,44 +805,47 @@ static struct tuner_params tuner_tcl_2002mb_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_tcl_2002mb_pal_ranges, .count = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges), - .config = 0xce, }, }; /* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */ -static struct tuner_range tuner_philips_fq12_6a___mk4_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, +static struct tuner_range tuner_philips_fq12_6a___mk4_pal_ranges[] = { + { 16 * 160.00 /*MHz*/, 0xce, 0x01, }, + { 16 * 442.00 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x04, }, }; static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_philips_fq12_6a___mk4_ranges, - .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges), - .config = 0xce, + .ranges = tuner_philips_fq12_6a___mk4_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_pal_ranges), }, }; /* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */ +static struct tuner_range tuner_philips_fq12_6a___mk4_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, +}; + static struct tuner_params tuner_philips_fq1236a_mk4_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_philips_fq12_6a___mk4_ranges, - .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges), - .config = 0x8e, + .ranges = tuner_philips_fq12_6a___mk4_ntsc_ranges, + .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ntsc_ranges), }, }; /* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */ static struct tuner_range tuner_ymec_tvf_8531mf_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 999.99 , 0x8e, 0x30, }, }; static struct tuner_params tuner_ymec_tvf_8531mf_params[] = { @@ -902,16 +853,15 @@ static struct tuner_params tuner_ymec_tvf_8531mf_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_ymec_tvf_8531mf_ntsc_ranges, .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */ static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_ymec_tvf_5533mf_params[] = { @@ -919,7 +869,6 @@ static struct tuner_params tuner_ymec_tvf_5533mf_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_ymec_tvf_5533mf_ntsc_ranges, .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges), - .config = 0x8e, }, }; @@ -928,9 +877,9 @@ static struct tuner_params tuner_ymec_tvf_5533mf_params[] = { /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = { - { 16 * 145.25 /*MHz*/, 0x39, }, - { 16 * 415.25 /*MHz*/, 0x3a, }, - { 16 * 999.99 , 0x3c, }, + { 16 * 145.25 /*MHz*/, 0x8e, 0x39, }, + { 16 * 415.25 /*MHz*/, 0x8e, 0x3a, }, + { 16 * 999.99 , 0x8e, 0x3c, }, }; @@ -939,16 +888,15 @@ static struct tuner_params tuner_thomson_dtt761x_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_thomson_dtt761x_ntsc_ranges, .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */ static struct tuner_range tuner_tuner_tena_9533_di_pal_ranges[] = { - { 16 * 160.25 /*MHz*/, 0x01, }, - { 16 * 464.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 160.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 464.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_tena_9533_di_params[] = { @@ -956,16 +904,15 @@ static struct tuner_params tuner_tena_9533_di_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_tuner_tena_9533_di_pal_ranges, .count = ARRAY_SIZE(tuner_tuner_tena_9533_di_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */ static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x51, }, - { 16 * 442.00 /*MHz*/, 0x52, }, - { 16 * 999.99 , 0x54, }, + { 16 * 160.00 /*MHz*/, 0x86, 0x51, }, + { 16 * 442.00 /*MHz*/, 0x86, 0x52, }, + { 16 * 999.99 , 0x86, 0x54, }, }; @@ -974,7 +921,6 @@ static struct tuner_params tuner_tuner_philips_fmd1216me_mk3_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_fmd1216me_mk3_pal_ranges, .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges), - .config = 0x86, }, }; @@ -982,9 +928,9 @@ static struct tuner_params tuner_tuner_philips_fmd1216me_mk3_params[] = { /* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */ static struct tuner_range tuner_tua6034_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x01 }, - { 16 * 455.00 /*MHz*/, 0x02 }, - { 16 * 999.99 , 0x04 }, + { 16 * 160.00 /*MHz*/, 0x8e, 0x01 }, + { 16 * 455.00 /*MHz*/, 0x8e, 0x02 }, + { 16 * 999.99 , 0x8e, 0x04 }, }; @@ -993,16 +939,15 @@ static struct tuner_params tuner_tua6034_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_tua6034_ntsc_ranges, .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */ static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = { - { 16 * 160.25 /*MHz*/, 0x01, }, - { 16 * 464.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 160.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 464.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { @@ -1010,16 +955,15 @@ static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges, .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */ static struct tuner_range tuner_lg_taln_mini_ntsc_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x01, }, - { 16 * 373.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 373.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_lg_taln_mini_params[] = { @@ -1027,16 +971,15 @@ static struct tuner_params tuner_lg_taln_mini_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_lg_taln_mini_ntsc_ranges, .count = ARRAY_SIZE(tuner_lg_taln_mini_ntsc_ranges), - .config = 0x8e, }, }; /* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */ static struct tuner_range tuner_philips_td1316_pal_ranges[] = { - { 16 * 160.00 /*MHz*/, 0xa1, }, - { 16 * 442.00 /*MHz*/, 0xa2, }, - { 16 * 999.99 , 0xa4, }, + { 16 * 160.00 /*MHz*/, 0xc8, 0xa1, }, + { 16 * 442.00 /*MHz*/, 0xc8, 0xa2, }, + { 16 * 999.99 , 0xc8, 0xa4, }, }; static struct tuner_params tuner_philips_td1316_params[] = { @@ -1044,16 +987,15 @@ static struct tuner_params tuner_philips_td1316_params[] = { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_td1316_pal_ranges, .count = ARRAY_SIZE(tuner_philips_td1316_pal_ranges), - .config = 0xc8, }, }; /* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */ static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 157.25 /*MHz*/, 0xce, 0x01, }, + { 16 * 454.00 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x04, }, }; @@ -1062,16 +1004,15 @@ static struct tuner_params tuner_tuner_tuv1236d_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_tuv1236d_ntsc_ranges, .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges), - .config = 0xce, }, }; /* ------------ TUNER_TNF_5335MF - Philips NTSC ------------ */ static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, + { 16 * 157.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x04, }, }; static struct tuner_params tuner_tnf_5335mf_params[] = { @@ -1079,7 +1020,6 @@ static struct tuner_params tuner_tnf_5335mf_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_tnf_5335mf_ntsc_ranges, .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges), - .config = 0x8e, }, }; @@ -1087,9 +1027,9 @@ static struct tuner_params tuner_tnf_5335mf_params[] = { /* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */ static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = { - { 16 * 175.75 /*MHz*/, 0x01, }, - { 16 * 410.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, + { 16 * 175.75 /*MHz*/, 0xce, 0x01, }, + { 16 * 410.25 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x08, }, }; static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { @@ -1097,7 +1037,6 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges, .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges), - .config = 0xce, }, }; diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index 15821ab14a9e..53ac66e0114b 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -14,6 +14,7 @@ enum param_type { struct tuner_range { unsigned short limit; + unsigned char config; unsigned char cb; }; @@ -38,7 +39,6 @@ struct tuner_params { * static unless the control byte was sent first. */ unsigned int cb_first_if_lower_freq:1; - unsigned char config; /* to be moved into struct tuner_range for dvb-pll merge */ unsigned int count; struct tuner_range *ranges; -- cgit v1.2.3-59-g8ed1b From cc925bbed017b12d46436e8ab788e0de8656d08c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 23 Jan 2006 17:11:11 -0200 Subject: V4L/DVB (3439): removed duplicated tuner_ranges - removed duplicated tuner_ranges Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 122 ++++++++++---------------------------- 1 file changed, 31 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index d37f833997dd..f77584dd356e 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -229,7 +229,7 @@ static struct tuner_params tuner_alps_tsbc5_params[] = { /* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */ -static struct tuner_range tuner_temic_4006fh5_pal_ranges[] = { +static struct tuner_range tuner_lg_pal_ranges[] = { { 16 * 170.00 /*MHz*/, 0x8e, 0xa0, }, { 16 * 450.00 /*MHz*/, 0x8e, 0x90, }, { 16 * 999.99 , 0x8e, 0x30, }, @@ -238,8 +238,8 @@ static struct tuner_range tuner_temic_4006fh5_pal_ranges[] = { static struct tuner_params tuner_temic_4006fh5_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_temic_4006fh5_pal_ranges, - .count = ARRAY_SIZE(tuner_temic_4006fh5_pal_ranges), + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), }, }; @@ -336,7 +336,7 @@ static struct tuner_params tuner_temic_4009f_5_params[] = { /* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */ -static struct tuner_range tuner_temic_4039fr5_ntsc_ranges[] = { +static struct tuner_range tuner_temic_4x3x_f_5_ntsc_ranges[] = { { 16 * 158.00 /*MHz*/, 0x8e, 0xa0, }, { 16 * 453.00 /*MHz*/, 0x8e, 0x90, }, { 16 * 999.99 , 0x8e, 0x30, }, @@ -345,35 +345,23 @@ static struct tuner_range tuner_temic_4039fr5_ntsc_ranges[] = { static struct tuner_params tuner_temic_4039fr5_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_temic_4039fr5_ntsc_ranges, - .count = ARRAY_SIZE(tuner_temic_4039fr5_ntsc_ranges), + .ranges = tuner_temic_4x3x_f_5_ntsc_ranges, + .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges), }, }; /* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */ -static struct tuner_range tuner_temic_4046fm5_pal_ranges[] = { - { 16 * 169.00 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 0x30, }, -}; - static struct tuner_params tuner_temic_4046fm5_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_temic_4046fm5_pal_ranges, - .count = ARRAY_SIZE(tuner_temic_4046fm5_pal_ranges), + .ranges = tuner_temic_40x6f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), }, }; /* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */ -static struct tuner_range tuner_lg_pal_ranges[] = { - { 16 * 170.00 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 0x30, }, -}; - static struct tuner_params tuner_philips_pal_dk_params[] = { { .type = TUNER_PARAM_TYPE_PAL, @@ -503,33 +491,21 @@ static struct tuner_params tuner_temic_4106fh5_params[] = { /* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */ -static struct tuner_range tuner_temic_4012fy5_pal_ranges[] = { - { 16 * 140.25 /*MHz*/, 0x8e, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x8e, 0x04, }, - { 16 * 999.99 , 0x8e, 0x01, }, -}; - static struct tuner_params tuner_temic_4012fy5_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_temic_4012fy5_pal_ranges, - .count = ARRAY_SIZE(tuner_temic_4012fy5_pal_ranges), + .ranges = tuner_temic_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_pal_ranges), }, }; /* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */ -static struct tuner_range tuner_temic_4136_fy5_ntsc_ranges[] = { - { 16 * 158.00 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 453.00 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 0x30, }, -}; - static struct tuner_params tuner_temic_4136_fy5_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_temic_4136_fy5_ntsc_ranges, - .count = ARRAY_SIZE(tuner_temic_4136_fy5_ntsc_ranges), + .ranges = tuner_temic_4x3x_f_5_ntsc_ranges, + .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges), }, }; @@ -638,17 +614,11 @@ static struct tuner_params tuner_fm1236_mk3_params[] = { /* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */ -static struct tuner_range tuner_philips_4in1_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 0x04, }, -}; - static struct tuner_params tuner_philips_4in1_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_philips_4in1_ntsc_ranges, - .count = ARRAY_SIZE(tuner_philips_4in1_ntsc_ranges), + .ranges = tuner_fm1236_mk3_ntsc_ranges, + .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), }, }; @@ -680,17 +650,11 @@ static struct tuner_params tuner_panasonic_vp27_params[] = { /* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */ -static struct tuner_range tuner_lg_ntsc_tape_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 0x04, }, -}; - static struct tuner_params tuner_lg_ntsc_tape_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_lg_ntsc_tape_ranges, - .count = ARRAY_SIZE(tuner_lg_ntsc_tape_ranges), + .ranges = tuner_fm1236_mk3_ntsc_ranges, + .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), }, }; @@ -746,17 +710,11 @@ static struct tuner_params tuner_tcl_2002n_params[] = { /* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */ -static struct tuner_range tuner_philips_fm1256_ih3_pal_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 0x04, }, -}; - static struct tuner_params tuner_philips_fm1256_ih3_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_philips_fm1256_ih3_pal_ranges, - .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_pal_ranges), + .ranges = tuner_fm1236_mk3_ntsc_ranges, + .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), }, }; @@ -826,33 +784,21 @@ static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = { /* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */ -static struct tuner_range tuner_philips_fq12_6a___mk4_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 0x04, }, -}; - static struct tuner_params tuner_philips_fq1236a_mk4_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_philips_fq12_6a___mk4_ntsc_ranges, - .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ntsc_ranges), + .ranges = tuner_fm1236_mk3_ntsc_ranges, + .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), }, }; /* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */ -static struct tuner_range tuner_ymec_tvf_8531mf_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 0x30, }, -}; - static struct tuner_params tuner_ymec_tvf_8531mf_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_ymec_tvf_8531mf_ntsc_ranges, - .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_ntsc_ranges), + .ranges = tuner_philips_ntsc_m_ranges, + .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges), }, }; @@ -893,7 +839,7 @@ static struct tuner_params tuner_thomson_dtt761x_params[] = { /* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */ -static struct tuner_range tuner_tuner_tena_9533_di_pal_ranges[] = { +static struct tuner_range tuner_tena_9533_di_pal_ranges[] = { { 16 * 160.25 /*MHz*/, 0x8e, 0x01, }, { 16 * 464.25 /*MHz*/, 0x8e, 0x02, }, { 16 * 999.99 , 0x8e, 0x04, }, @@ -902,8 +848,8 @@ static struct tuner_range tuner_tuner_tena_9533_di_pal_ranges[] = { static struct tuner_params tuner_tena_9533_di_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_tuner_tena_9533_di_pal_ranges, - .count = ARRAY_SIZE(tuner_tuner_tena_9533_di_pal_ranges), + .ranges = tuner_tena_9533_di_pal_ranges, + .count = ARRAY_SIZE(tuner_tena_9533_di_pal_ranges), }, }; @@ -916,7 +862,7 @@ static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = { }; -static struct tuner_params tuner_tuner_philips_fmd1216me_mk3_params[] = { +static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = { { .type = TUNER_PARAM_TYPE_PAL, .ranges = tuner_philips_fmd1216me_mk3_pal_ranges, @@ -944,17 +890,11 @@ static struct tuner_params tuner_tua6034_params[] = { /* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */ -static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = { - { 16 * 160.25 /*MHz*/, 0x8e, 0x01, }, - { 16 * 464.25 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 0x08, }, -}; - static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges, - .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges), + .ranges = tuner_tena_9533_di_pal_ranges, + .count = ARRAY_SIZE(tuner_tena_9533_di_pal_ranges), }, }; @@ -999,7 +939,7 @@ static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = { }; -static struct tuner_params tuner_tuner_tuv1236d_params[] = { +static struct tuner_params tuner_tuv1236d_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_tuv1236d_ntsc_ranges, @@ -1308,7 +1248,7 @@ struct tunertype tuners[] = { }, [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */ .name = "Philips FMD1216ME MK3 Hybrid Tuner", - .params = tuner_tuner_philips_fmd1216me_mk3_params, + .params = tuner_philips_fmd1216me_mk3_params, }, [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */ .name = "LG TDVS-H062F/TUA6034", @@ -1328,7 +1268,7 @@ struct tunertype tuners[] = { }, [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */ .name = "Philips TUV1236D ATSC/NTSC dual in", - .params = tuner_tuner_tuv1236d_params, + .params = tuner_tuv1236d_params, }, [TUNER_TNF_5335MF] = { /* Philips NTSC */ .name = "Tena TNF 5335 MF", -- cgit v1.2.3-59-g8ed1b From c37844f4a8c9524dbe9187397e75caa7a79ae83a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 24 Jan 2006 13:15:06 -0800 Subject: V4L/DVB (3439a): media video stradis memory fix memset clears once set structure, there is actually no need for memset, because configure function do it for us. Next, vfree(NULL) is legal, so avoid useless labels. Thanks Dave Jones for reporting this. Signed-off-by: Jiri Slaby Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/stradis.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 54fc33011ffb..9d769264a329 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -2012,7 +2012,6 @@ static int __devinit init_saa7146(struct pci_dev *pdev) { struct saa7146 *saa = pci_get_drvdata(pdev); - memset(saa, 0, sizeof(*saa)); saa->user = 0; /* reset the saa7146 */ saawrite(0xffff0000, SAA7146_MC1); @@ -2062,16 +2061,16 @@ static int __devinit init_saa7146(struct pci_dev *pdev) } if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) { dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); - goto errvid; + goto errfree; } if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) { dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); - goto erraud; + goto errfree; } /* allocate 81920 byte buffer for clipping */ if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) { dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr); - goto errosd; + goto errfree; } /* setup clipping registers */ saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2); @@ -2085,15 +2084,11 @@ static int __devinit init_saa7146(struct pci_dev *pdev) I2CBusScan(saa); return 0; -errosd: +errfree: vfree(saa->osdbuf); - saa->osdbuf = NULL; -erraud: vfree(saa->audbuf); - saa->audbuf = NULL; -errvid: vfree(saa->vidbuf); - saa->vidbuf = NULL; + saa->audbuf = saa->osdbuf = saa->vidbuf = NULL; err: return -ENOMEM; } -- cgit v1.2.3-59-g8ed1b From 739dbef022e1600cfd3ba989246b3eecf04f2bb5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 26 Jan 2006 04:37:19 -0200 Subject: V4L/DVB (3442): Allow tristate build for cx88-vp3054-i2c - allow tristate build for cx88-vp3054-i2c Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index e78da88501d8..2b902784facc 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -4,8 +4,9 @@ cx8800-objs := cx88-video.o cx88-vbi.o cx8802-objs := cx88-mpeg.o obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o -obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o +obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o +obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o EXTRA_CFLAGS += -I$(src)/.. EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core -- cgit v1.2.3-59-g8ed1b From 6e586f32931d6c98431d54cd0430d4366195b0ba Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 17 Jan 2006 12:24:39 -0500 Subject: [IA64-SGI] sem2mutex ioc4.c Convert to use a single mutex instead of two rwsems as this isn't performance critical. Signed-off-by: Jes Sorensen Signed-off-by: Brent Casavant Signed-off-by: Tony Luck --- drivers/sn/ioc4.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c index ea75b3d0612b..67140a5804f5 100644 --- a/drivers/sn/ioc4.c +++ b/drivers/sn/ioc4.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -54,11 +54,10 @@ * Submodule management * ************************/ -static LIST_HEAD(ioc4_devices); -static DECLARE_RWSEM(ioc4_devices_rwsem); +static DEFINE_MUTEX(ioc4_mutex); +static LIST_HEAD(ioc4_devices); static LIST_HEAD(ioc4_submodules); -static DECLARE_RWSEM(ioc4_submodules_rwsem); /* Register an IOC4 submodule */ int @@ -66,15 +65,13 @@ ioc4_register_submodule(struct ioc4_submodule *is) { struct ioc4_driver_data *idd; - down_write(&ioc4_submodules_rwsem); + mutex_lock(&ioc4_mutex); list_add(&is->is_list, &ioc4_submodules); - up_write(&ioc4_submodules_rwsem); /* Initialize submodule for each IOC4 */ if (!is->is_probe) - return 0; + goto out; - down_read(&ioc4_devices_rwsem); list_for_each_entry(idd, &ioc4_devices, idd_list) { if (is->is_probe(idd)) { printk(KERN_WARNING @@ -84,8 +81,8 @@ ioc4_register_submodule(struct ioc4_submodule *is) pci_name(idd->idd_pdev)); } } - up_read(&ioc4_devices_rwsem); - + out: + mutex_unlock(&ioc4_mutex); return 0; } @@ -95,15 +92,13 @@ ioc4_unregister_submodule(struct ioc4_submodule *is) { struct ioc4_driver_data *idd; - down_write(&ioc4_submodules_rwsem); + mutex_lock(&ioc4_mutex); list_del(&is->is_list); - up_write(&ioc4_submodules_rwsem); /* Remove submodule for each IOC4 */ if (!is->is_remove) - return; + goto out; - down_read(&ioc4_devices_rwsem); list_for_each_entry(idd, &ioc4_devices, idd_list) { if (is->is_remove(idd)) { printk(KERN_WARNING @@ -113,7 +108,8 @@ ioc4_unregister_submodule(struct ioc4_submodule *is) pci_name(idd->idd_pdev)); } } - up_read(&ioc4_devices_rwsem); + out: + mutex_unlock(&ioc4_mutex); } /********************* @@ -312,12 +308,11 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) /* Track PCI-device specific data */ idd->idd_serial_data = NULL; pci_set_drvdata(idd->idd_pdev, idd); - down_write(&ioc4_devices_rwsem); + + mutex_lock(&ioc4_mutex); list_add(&idd->idd_list, &ioc4_devices); - up_write(&ioc4_devices_rwsem); /* Add this IOC4 to all submodules */ - down_read(&ioc4_submodules_rwsem); list_for_each_entry(is, &ioc4_submodules, is_list) { if (is->is_probe && is->is_probe(idd)) { printk(KERN_WARNING @@ -327,7 +322,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) pci_name(idd->idd_pdev)); } } - up_read(&ioc4_submodules_rwsem); + mutex_unlock(&ioc4_mutex); return 0; @@ -351,7 +346,7 @@ ioc4_remove(struct pci_dev *pdev) idd = pci_get_drvdata(pdev); /* Remove this IOC4 from all submodules */ - down_read(&ioc4_submodules_rwsem); + mutex_lock(&ioc4_mutex); list_for_each_entry(is, &ioc4_submodules, is_list) { if (is->is_remove && is->is_remove(idd)) { printk(KERN_WARNING @@ -361,7 +356,7 @@ ioc4_remove(struct pci_dev *pdev) pci_name(idd->idd_pdev)); } } - up_read(&ioc4_submodules_rwsem); + mutex_unlock(&ioc4_mutex); /* Release resources */ iounmap(idd->idd_misc_regs); @@ -377,9 +372,9 @@ ioc4_remove(struct pci_dev *pdev) pci_disable_device(pdev); /* Remove and free driver data */ - down_write(&ioc4_devices_rwsem); + mutex_lock(&ioc4_mutex); list_del(&idd->idd_list); - up_write(&ioc4_devices_rwsem); + mutex_unlock(&ioc4_mutex); kfree(idd); } -- cgit v1.2.3-59-g8ed1b From 28ff6b9b2fc01d2c2746c72ce8af1729344fae27 Mon Sep 17 00:00:00 2001 From: Aaron Young Date: Mon, 23 Jan 2006 09:00:51 -0800 Subject: [IA64-SGI] Handle SC env. powerdown events Handle system controller power down pending events on SN systems. This allows the system to gracefully shutdown before the system controller removes power due to an adverse environmental condition. Signed-off-by: Aaron Young Signed-off-by: Tony Luck --- drivers/char/snsc.h | 5 ++++- drivers/char/snsc_event.c | 32 ++++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h index a9efc13cc858..8a98169b60c1 100644 --- a/drivers/char/snsc.h +++ b/drivers/char/snsc.h @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved. */ /* @@ -70,6 +70,9 @@ struct sysctl_data_s { #define EV_CLASS_TEST_WARNING 0x6000ul #define EV_CLASS_PWRD_NOTIFY 0x8000ul +/* ENV class codes */ +#define ENV_PWRDN_PEND 0x4101ul + #define EV_SEVERITY_POWER_STABLE 0x0000ul #define EV_SEVERITY_POWER_LOW_WARNING 0x0100ul #define EV_SEVERITY_POWER_HIGH_WARNING 0x0200ul diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c index baaa365285fa..a4fa507eed9e 100644 --- a/drivers/char/snsc_event.c +++ b/drivers/char/snsc_event.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved. */ /* @@ -187,7 +187,8 @@ scdrv_event_severity(int code) static void scdrv_dispatch_event(char *event, int len) { - int code, esp_code, src; + static int snsc_shutting_down = 0; + int code, esp_code, src, class; char desc[CHUNKSIZE]; char *severity; @@ -199,9 +200,25 @@ scdrv_dispatch_event(char *event, int len) /* how urgent is the message? */ severity = scdrv_event_severity(code); - if ((code & EV_CLASS_MASK) == EV_CLASS_PWRD_NOTIFY) { + class = (code & EV_CLASS_MASK); + + if (class == EV_CLASS_PWRD_NOTIFY || code == ENV_PWRDN_PEND) { struct task_struct *p; + if (snsc_shutting_down) + return; + + snsc_shutting_down = 1; + + /* give a message for each type of event */ + if (class == EV_CLASS_PWRD_NOTIFY) + printk(KERN_NOTICE "Power off indication received." + " Sending SIGPWR to init...\n"); + else if (code == ENV_PWRDN_PEND) + printk(KERN_CRIT "WARNING: Shutting down the system" + " due to a critical environmental condition." + " Sending SIGPWR to init...\n"); + /* give a SIGPWR signal to init proc */ /* first find init's task */ @@ -210,12 +227,11 @@ scdrv_dispatch_event(char *event, int len) if (p->pid == 1) break; } - if (p) { /* we found init's task */ - printk(KERN_EMERG "Power off indication received. Initiating power fail sequence...\n"); + if (p) { force_sig(SIGPWR, p); - } else { /* failed to find init's task - just give message(s) */ - printk(KERN_WARNING "Failed to find init proc to handle power off!\n"); - printk("%s|$(0x%x)%s\n", severity, esp_code, desc); + } else { + printk(KERN_ERR "Failed to signal init!\n"); + snsc_shutting_down = 0; /* so can try again (?) */ } read_unlock(&tasklist_lock); } else { -- cgit v1.2.3-59-g8ed1b From ff0fc1467f8189c8e2340b91161c97138a75e484 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 18 Dec 2005 17:17:07 +0900 Subject: [PATCH] ata_piix: fix MAP VALUE interpretation for for ICH6/7 Unlike their older siblings, ICH6 and 7 use different scheme for MAP VALUE. This patch makes ata_piix interpret MV properly on ICH6/7. Pre-ICH6/7 The value of these bits indicate the address range the SATA port responds to, and whether or not the SATA and IDE functions are combined. 000 = Non-combined. P0 is primary master. P1 is secondary master. 001 = Non-combined. P0 is secondary master. P1 is primary master. 100 = Combined. P0 is primary master. P1 is primary slave. P-ATA is 2:0 Map Value secondary. 101 = Combined. P0 is primary slave. P1 is primary master. P-ATA is secondary. 110 = Combined. P-ATA is primary. P0 is secondary master. P1 is secondary slave. 111 = Combined. P-ATA is primary. P0 is secondary slave. P1 is secondary master. ICH6/7 Map Value - R/W. Map Value (MV): The value in the bits below indicate the address range the SATA ports responds to, and whether or not the PATA and SATA functions are combined. When in combined mode, the AHCI memory space is not available and AHCI may not be used. 00 = Non-combined. P0 is primary master, P2 is the primary slave. P1 is secondary master, P3 is the 1:0 secondary slave (desktop only). P0 is primary master, P2 is the primary slave (mobile only). 01 = Combined. IDE is primary. P1 is secondary master, P3 is the secondary slave. (desktop only) 10 = Combined. P0 is primary master. P2 is primary slave. IDE is secondary 11 = Reserved Signed-off-by: Tejun Heo -- Jeff, without this patch, ata_piix misdetects my ICH7's combined mode, ending up not applying bridge limits to PX-710SA and configuring IDE drive on 40-c cable to UDMA/66. Thanks. Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 53 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index fc3ca051ceed..19d8d4ba6a1e 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -101,9 +101,11 @@ enum { ICH5_PCS = 0x92, /* port control and status */ PIIX_SCC = 0x0A, /* sub-class code register */ - PIIX_FLAG_AHCI = (1 << 28), /* AHCI possible */ - PIIX_FLAG_CHECKINTR = (1 << 29), /* make sure PCI INTx enabled */ - PIIX_FLAG_COMBINED = (1 << 30), /* combined mode possible */ + PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ + PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ + PIIX_FLAG_COMBINED = (1 << 29), /* combined mode possible */ + /* ICH6/7 use different scheme for map value */ + PIIX_FLAG_COMBINED_ICH6 = PIIX_FLAG_COMBINED | (1 << 30), /* combined mode. if set, PATA is channel 0. * if clear, PATA is channel 1. @@ -297,8 +299,8 @@ static struct ata_port_info piix_port_info[] = { { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | - PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR | - ATA_FLAG_SLAVE_POSS, + PIIX_FLAG_COMBINED_ICH6 | + PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -309,8 +311,9 @@ static struct ata_port_info piix_port_info[] = { { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | - PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR | - ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI, + PIIX_FLAG_COMBINED_ICH6 | + PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | + PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -680,6 +683,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) struct ata_port_info *port_info[2]; unsigned int combined = 0; unsigned int pata_chan = 0, sata_chan = 0; + unsigned long host_flags; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, @@ -692,7 +696,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) port_info[0] = &piix_port_info[ent->driver_data]; port_info[1] = &piix_port_info[ent->driver_data]; - if (port_info[0]->host_flags & PIIX_FLAG_AHCI) { + host_flags = port_info[0]->host_flags; + + if (host_flags & PIIX_FLAG_AHCI) { u8 tmp; pci_read_config_byte(pdev, PIIX_SCC, &tmp); if (tmp == PIIX_AHCI_DEVICE) { @@ -702,16 +708,35 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) } } - if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) { + if (host_flags & PIIX_FLAG_COMBINED) { u8 tmp; pci_read_config_byte(pdev, ICH5_PMR, &tmp); - if (tmp & PIIX_COMB) { - combined = 1; - if (tmp & PIIX_COMB_PATA_P0) + if (host_flags & PIIX_FLAG_COMBINED_ICH6) { + switch (tmp) { + case 0: + break; + case 1: + combined = 1; sata_chan = 1; - else + break; + case 2: + combined = 1; pata_chan = 1; + break; + case 3: + dev_printk(KERN_WARNING, &pdev->dev, + "invalid MAP value %u\n", tmp); + break; + } + } else { + if (tmp & PIIX_COMB) { + combined = 1; + if (tmp & PIIX_COMB_PATA_P0) + sata_chan = 1; + else + pata_chan = 1; + } } } @@ -721,7 +746,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) * MSI is disabled (and it is disabled, as we don't use * message-signalled interrupts currently). */ - if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR) + if (host_flags & PIIX_FLAG_CHECKINTR) pci_intx(pdev, 1); if (combined) { -- cgit v1.2.3-59-g8ed1b From 0d615ec2bb1cb8c38087bb24f6d2876dec3a9751 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 26 Jan 2006 22:01:38 -0500 Subject: sundance: Really read addr 0 Make phy 0 actually be read, as it is not being right now as we have: int mii_status = mdio_read(dev, phy, MII_BMSR); int phyx = phy & 0x1f; When we should have instead: int phyx = phy & 0x1f; int mii_status = mdio_read(dev, phyx, MII_BMSR); so that when phy, in the end of the (phy = 1; phy <= 32...) loop gets to 32 phyx gets to 0, i.e. we were reading at 32, when the intended read was for 0. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Jeff Garzik --- drivers/net/sundance.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 0ab9c38b4a34..8cdeb5cbab5b 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -633,9 +633,13 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, np->phys[0] = 1; /* Default setting */ np->mii_preamble_required++; + /* + * It seems some phys doesn't deal well with address 0 being accessed + * first, so leave address zero to the end of the loop (32 & 31). + */ for (phy = 1; phy <= 32 && phy_idx < MII_CNT; phy++) { - int mii_status = mdio_read(dev, phy, MII_BMSR); int phyx = phy & 0x1f; + int mii_status = mdio_read(dev, phyx, MII_BMSR); if (mii_status != 0xffff && mii_status != 0x0000) { np->phys[phy_idx++] = phyx; np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE); -- cgit v1.2.3-59-g8ed1b From 4ba946e9d8e10fada7bbce527f6ea05842592e06 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:36 +0900 Subject: [PATCH] libata: fold __ata_qc_complete() into ata_qc_free() All ata_qc_free() does is calling __ata_qc_complete() which isn't used anywhere else. Fold __ata_qc_complete() into ata_qc_free(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a07bd35da912..0e4932362949 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -73,7 +73,6 @@ static int fgb(u32 bitmap); static int ata_choose_xfer_mode(const struct ata_port *ap, u8 *xfer_mode_out, unsigned int *xfer_shift_out); -static void __ata_qc_complete(struct ata_queued_cmd *qc); static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; @@ -3593,21 +3592,6 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, return qc; } -static void __ata_qc_complete(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - unsigned int tag; - - 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); - } -} - /** * ata_qc_free - free unused ata_queued_cmd * @qc: Command to complete @@ -3620,9 +3604,19 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc) */ void ata_qc_free(struct ata_queued_cmd *qc) { + struct ata_port *ap = qc->ap; + unsigned int tag; + assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ - __ata_qc_complete(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); + } } /** @@ -3662,7 +3656,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) if (rc != 0) return; - __ata_qc_complete(qc); + ata_qc_free(qc); VPRINTK("EXIT\n"); } -- cgit v1.2.3-59-g8ed1b From 77853bf2b48e34449e826a9ef4df5ea0dbe947f4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:36 +0900 Subject: [PATCH] libata: make the owner of a qc responsible for freeing it qc used to be freed automatically on command completion. However, as a qc can carry information about its completion status, it can be useful to its owner/issuer after command completion. This patch makes freeing qc responsibility of its owner. This simplifies ata_exec_internal() and makes command turn-around for atapi request sensing less hackish. This change was originally suggested by Jeff Garzik. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 47 +++++++++++++--------------------------------- drivers/scsi/libata-scsi.c | 14 +++++++------- include/linux/libata.h | 2 +- 3 files changed, 21 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 0e4932362949..15df633521d0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1072,24 +1072,12 @@ static unsigned int ata_pio_modes(const struct ata_device *adev) timing API will get this right anyway */ } -struct ata_exec_internal_arg { - unsigned int err_mask; - struct ata_taskfile *tf; - struct completion *waiting; -}; - -int ata_qc_complete_internal(struct ata_queued_cmd *qc) +void ata_qc_complete_internal(struct ata_queued_cmd *qc) { - struct ata_exec_internal_arg *arg = qc->private_data; - struct completion *waiting = arg->waiting; + struct completion *waiting = qc->private_data; - if (!(qc->err_mask & ~AC_ERR_DEV)) - qc->ap->ops->tf_read(qc->ap, arg->tf); - arg->err_mask = qc->err_mask; - arg->waiting = NULL; + qc->ap->ops->tf_read(qc->ap, &qc->tf); complete(waiting); - - return 0; } /** @@ -1120,7 +1108,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, struct ata_queued_cmd *qc; DECLARE_COMPLETION(wait); unsigned long flags; - struct ata_exec_internal_arg arg; + unsigned int err_mask; spin_lock_irqsave(&ap->host_set->lock, flags); @@ -1134,9 +1122,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, qc->nsect = buflen / ATA_SECT_SIZE; } - arg.waiting = &wait; - arg.tf = tf; - qc->private_data = &arg; + qc->private_data = &wait; qc->complete_fn = ata_qc_complete_internal; if (ata_qc_issue(qc)) @@ -1153,7 +1139,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, * before the caller cleans up, it will result in a * spurious interrupt. We can live with that. */ - if (arg.waiting) { + if (qc->flags & ATA_QCFLAG_ACTIVE) { qc->err_mask = AC_ERR_OTHER; ata_qc_complete(qc); printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n", @@ -1163,7 +1149,12 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, spin_unlock_irqrestore(&ap->host_set->lock, flags); } - return arg.err_mask; + *tf = qc->tf; + err_mask = qc->err_mask; + + ata_qc_free(qc); + + return err_mask; issue_fail: ata_qc_free(qc); @@ -3633,8 +3624,6 @@ void ata_qc_free(struct ata_queued_cmd *qc) void ata_qc_complete(struct ata_queued_cmd *qc) { - int rc; - assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ assert(qc->flags & ATA_QCFLAG_ACTIVE); @@ -3648,17 +3637,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) qc->flags &= ~ATA_QCFLAG_ACTIVE; /* call completion callback */ - rc = qc->complete_fn(qc); - - /* if callback indicates not to complete command (non-zero), - * return immediately - */ - if (rc != 0) - return; - - ata_qc_free(qc); - - VPRINTK("EXIT\n"); + qc->complete_fn(qc); } static inline int ata_should_dma_map(struct ata_queued_cmd *qc) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 0e65bfe92e6f..ce3fe928a386 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1219,7 +1219,7 @@ nothing_to_do: return 1; } -static int ata_scsi_qc_complete(struct ata_queued_cmd *qc) +static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; u8 *cdb = cmd->cmnd; @@ -1256,7 +1256,7 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc) qc->scsidone(cmd); - return 0; + ata_qc_free(qc); } /** @@ -1982,7 +1982,7 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 done(cmd); } -static int atapi_sense_complete(struct ata_queued_cmd *qc) +static void atapi_sense_complete(struct ata_queued_cmd *qc) { if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) /* FIXME: not quite right; we don't want the @@ -1993,7 +1993,7 @@ static int atapi_sense_complete(struct ata_queued_cmd *qc) ata_gen_ata_desc_sense(qc); qc->scsidone(qc->scsicmd); - return 0; + ata_qc_free(qc); } /* is it pointless to prefer PIO for "safety reasons"? */ @@ -2050,7 +2050,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) DPRINTK("EXIT\n"); } -static int atapi_qc_complete(struct ata_queued_cmd *qc) +static void atapi_qc_complete(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; unsigned int err_mask = qc->err_mask; @@ -2060,7 +2060,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc) if (unlikely(err_mask & AC_ERR_DEV)) { cmd->result = SAM_STAT_CHECK_CONDITION; atapi_request_sense(qc); - return 1; + return; } else if (unlikely(err_mask)) @@ -2100,7 +2100,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc) } qc->scsidone(cmd); - return 0; + ata_qc_free(qc); } /** * atapi_xlat - Initialize PACKET taskfile diff --git a/include/linux/libata.h b/include/linux/libata.h index 46ccea215892..d58b659cf3f5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -235,7 +235,7 @@ struct ata_port; struct ata_queued_cmd; /* typedefs */ -typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc); +typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); struct ata_ioports { unsigned long cmd_addr; -- cgit v1.2.3-59-g8ed1b From 8e436af9326f5cc2e07d76505154ffddfb04b485 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:36 +0900 Subject: [PATCH] libata: fix ata_qc_issue() error handling When ata_qc_issue() fails, the qc might have been dma mapped or not. So, performing only ata_qc_free() results in dma map leak. This patch makes ata_qc_issue() mark dma map flags correctly on failure and calls ata_qc_complete() after ata_qc_issue() fails. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 18 ++++++++---------- drivers/scsi/libata-scsi.c | 6 ++++-- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 15df633521d0..43a23286d6fe 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1125,8 +1125,10 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, qc->private_data = &wait; qc->complete_fn = ata_qc_complete_internal; - if (ata_qc_issue(qc)) - goto issue_fail; + if (ata_qc_issue(qc)) { + qc->err_mask = AC_ERR_OTHER; + ata_qc_complete(qc); + } spin_unlock_irqrestore(&ap->host_set->lock, flags); @@ -1155,11 +1157,6 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, ata_qc_free(qc); return err_mask; - - issue_fail: - ata_qc_free(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); - return AC_ERR_OTHER; } /** @@ -3687,10 +3684,10 @@ int ata_qc_issue(struct ata_queued_cmd *qc) if (ata_should_dma_map(qc)) { if (qc->flags & ATA_QCFLAG_SG) { if (ata_sg_setup(qc)) - goto err_out; + goto sg_err; } else if (qc->flags & ATA_QCFLAG_SINGLE) { if (ata_sg_setup_one(qc)) - goto err_out; + goto sg_err; } } else { qc->flags &= ~ATA_QCFLAG_DMAMAP; @@ -3703,7 +3700,8 @@ int ata_qc_issue(struct ata_queued_cmd *qc) return ap->ops->qc_issue(qc); -err_out: +sg_err: + qc->flags &= ~ATA_QCFLAG_DMAMAP; return -1; } diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ce3fe928a386..c496309f691a 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1322,8 +1322,10 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, goto early_finish; /* select device, send command to hardware */ - if (ata_qc_issue(qc)) - goto err_did; + if (ata_qc_issue(qc)) { + qc->err_mask |= AC_ERR_OTHER; + ata_qc_complete(qc); + } VPRINTK("EXIT\n"); return; -- cgit v1.2.3-59-g8ed1b From 284b6481cc7112ca6a9e60b7a9b650fba3bf0492 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:36 +0900 Subject: [PATCH] ahci: fix err_mask setting in ahci_host_intr In ahci_host_intr err_mask is determined from IRQ status but never used. This patch sets qc->err_mask to the determined err_mask. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 30676b0eb366..a168b525d079 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -721,7 +721,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) ahci_restart_port(ap, status); if (qc) { - qc->err_mask |= AC_ERR_OTHER; + qc->err_mask |= err_mask; ata_qc_complete(qc); } } -- cgit v1.2.3-59-g8ed1b From 11a56d2439259892319df81cf1582687d7e7fde5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:36 +0900 Subject: [PATCH] libata: add detailed AC_ERR_* flags Add detailed AC_ERR_* flags and use them. Long-term goal is to describe all errors with err_mask and tf combination (tf for failed sector information, etc...). After proper error diagnosis is implemented, sense data should also be generated from err_mask instead of directly from hardware tf registers as it is currently. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 2 +- drivers/scsi/libata-core.c | 12 ++++++------ drivers/scsi/sata_mv.c | 2 +- drivers/scsi/sata_sil24.c | 2 +- include/linux/libata.h | 15 ++++++++++----- 5 files changed, 19 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index a168b525d079..bb3686ae1885 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -680,7 +680,7 @@ static void ahci_eng_timeout(struct ata_port *ap) * not being called from the SCSI EH. */ qc->scsidone = scsi_finish_command; - qc->err_mask |= AC_ERR_OTHER; + qc->err_mask |= AC_ERR_TIMEOUT; ata_qc_complete(qc); } diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 43a23286d6fe..f5519f01491c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1142,7 +1142,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, * spurious interrupt. We can live with that. */ if (qc->flags & ATA_QCFLAG_ACTIVE) { - qc->err_mask = AC_ERR_OTHER; + qc->err_mask = AC_ERR_TIMEOUT; ata_qc_complete(qc); printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n", ap->id, command); @@ -2917,7 +2917,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap) status = ata_chk_status(ap); if (status & ATA_BUSY) { if (time_after(jiffies, ap->pio_task_timeout)) { - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_TIMEOUT; ap->hsm_task_state = HSM_ST_TMOUT; return 0; } @@ -3295,7 +3295,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) err_out: printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n", ap->id, dev->devno); - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; } @@ -3353,7 +3353,7 @@ static void ata_pio_block(struct ata_port *ap) } else { /* handle BSY=0, DRQ=0 as error */ if ((status & ATA_DRQ) == 0) { - qc->err_mask |= AC_ERR_ATA_BUS; + qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; return; } @@ -4159,14 +4159,14 @@ 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)) { - qc->err_mask |= AC_ERR_ATA_BUS; + 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_ATA_BUS; + qc->err_mask |= AC_ERR_HSM; goto err_out; } diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index cd54244058b5..89bcd85fa58c 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1866,7 +1866,7 @@ static void mv_eng_timeout(struct ata_port *ap) */ spin_lock_irqsave(&ap->host_set->lock, flags); qc->scsidone = scsi_finish_command; - qc->err_mask |= AC_ERR_OTHER; + qc->err_mask |= AC_ERR_TIMEOUT; ata_qc_complete(qc); spin_unlock_irqrestore(&ap->host_set->lock, flags); } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 923130185a9e..fb59012b9fbe 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -653,7 +653,7 @@ static void sil24_eng_timeout(struct ata_port *ap) */ printk(KERN_ERR "ata%u: command timeout\n", ap->id); qc->scsidone = scsi_finish_command; - qc->err_mask |= AC_ERR_OTHER; + qc->err_mask |= AC_ERR_TIMEOUT; ata_qc_complete(qc); sil24_reset_controller(ap); diff --git a/include/linux/libata.h b/include/linux/libata.h index d58b659cf3f5..8ff3a7f6f63c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -222,10 +222,15 @@ enum hsm_task_states { }; enum ata_completion_errors { - AC_ERR_OTHER = (1 << 0), - AC_ERR_DEV = (1 << 1), - AC_ERR_ATA_BUS = (1 << 2), - AC_ERR_HOST_BUS = (1 << 3), + AC_ERR_DEV = (1 << 0), /* device reported error */ + AC_ERR_HSM = (1 << 1), /* host state machine violation */ + AC_ERR_TIMEOUT = (1 << 2), /* timeout */ + AC_ERR_MEDIA = (1 << 3), /* media error */ + AC_ERR_ATA_BUS = (1 << 4), /* ATA bus error */ + AC_ERR_HOST_BUS = (1 << 5), /* host bus error */ + AC_ERR_SYSTEM = (1 << 6), /* system error */ + AC_ERR_INVALID = (1 << 7), /* invalid argument */ + AC_ERR_OTHER = (1 << 8), /* unknown */ }; /* forward declarations */ @@ -833,7 +838,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) - return AC_ERR_ATA_BUS; + return AC_ERR_HSM; if (status & (ATA_ERR | ATA_DF)) return AC_ERR_DEV; return 0; -- cgit v1.2.3-59-g8ed1b From 9a3d9eb0177eb10500d49cd283b35576082a522d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:36 +0900 Subject: [PATCH] libata: return AC_ERR_* from issue functions Return AC_ERR_* mask from issue fuctions instead of 0/-1. This enables things like failing a qc with AC_ERR_HSM when the device doesn't set DRDY when the qc is about to be issued. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 4 ++-- drivers/scsi/libata-core.c | 17 ++++++++--------- drivers/scsi/libata-scsi.c | 10 ++++------ drivers/scsi/libata.h | 2 +- drivers/scsi/pdc_adma.c | 4 ++-- drivers/scsi/sata_mv.c | 4 ++-- drivers/scsi/sata_promise.c | 4 ++-- drivers/scsi/sata_qstor.c | 4 ++-- drivers/scsi/sata_sil24.c | 4 ++-- drivers/scsi/sata_sx4.c | 4 ++-- include/linux/libata.h | 4 ++-- 11 files changed, 29 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index bb3686ae1885..0f6e4dd22901 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -184,7 +184,7 @@ struct ahci_port_priv { static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg); 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 int ahci_qc_issue(struct ata_queued_cmd *qc); +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 void ahci_phy_reset(struct ata_port *ap); static void ahci_irq_clear(struct ata_port *ap); @@ -800,7 +800,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * return IRQ_RETVAL(handled); } -static int ahci_qc_issue(struct ata_queued_cmd *qc) +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; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f5519f01491c..b29bf0dc948a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1125,10 +1125,9 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, qc->private_data = &wait; qc->complete_fn = ata_qc_complete_internal; - if (ata_qc_issue(qc)) { - qc->err_mask = AC_ERR_OTHER; + qc->err_mask = ata_qc_issue(qc); + if (qc->err_mask) ata_qc_complete(qc); - } spin_unlock_irqrestore(&ap->host_set->lock, flags); @@ -3674,10 +3673,10 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc) * spin_lock_irqsave(host_set lock) * * RETURNS: - * Zero on success, negative on error. + * Zero on success, AC_ERR_* mask on failure */ -int ata_qc_issue(struct ata_queued_cmd *qc) +unsigned int ata_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -3702,7 +3701,7 @@ int ata_qc_issue(struct ata_queued_cmd *qc) sg_err: qc->flags &= ~ATA_QCFLAG_DMAMAP; - return -1; + return AC_ERR_SYSTEM; } @@ -3721,10 +3720,10 @@ sg_err: * spin_lock_irqsave(host_set lock) * * RETURNS: - * Zero on success, negative on error. + * Zero on success, AC_ERR_* mask on failure */ -int ata_qc_issue_prot(struct ata_queued_cmd *qc) +unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -3769,7 +3768,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) default: WARN_ON(1); - return -1; + return AC_ERR_SYSTEM; } return 0; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index c496309f691a..95e3c278dd43 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1322,10 +1322,9 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, goto early_finish; /* select device, send command to hardware */ - if (ata_qc_issue(qc)) { - qc->err_mask |= AC_ERR_OTHER; + qc->err_mask = ata_qc_issue(qc); + if (qc->err_mask) ata_qc_complete(qc); - } VPRINTK("EXIT\n"); return; @@ -2044,10 +2043,9 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) qc->complete_fn = atapi_sense_complete; - if (ata_qc_issue(qc)) { - qc->err_mask |= AC_ERR_OTHER; + qc->err_mask = ata_qc_issue(qc); + if (qc->err_mask) ata_qc_complete(qc); - } DPRINTK("EXIT\n"); } diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index e03ce48b7b4b..9d76923a2253 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -45,7 +45,7 @@ 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_qc_free(struct ata_queued_cmd *qc); -extern int ata_qc_issue(struct ata_queued_cmd *qc); +extern unsigned int ata_qc_issue(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); diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index e8df0c9ec1e6..3a6bf58dc37b 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -131,7 +131,7 @@ static void adma_host_stop(struct ata_host_set *host_set); static void adma_port_stop(struct ata_port *ap); static void adma_phy_reset(struct ata_port *ap); static void adma_qc_prep(struct ata_queued_cmd *qc); -static int adma_qc_issue(struct ata_queued_cmd *qc); +static unsigned int adma_qc_issue(struct ata_queued_cmd *qc); static int adma_check_atapi_dma(struct ata_queued_cmd *qc); static void adma_bmdma_stop(struct ata_queued_cmd *qc); static u8 adma_bmdma_status(struct ata_port *ap); @@ -419,7 +419,7 @@ static inline void adma_packet_start(struct ata_queued_cmd *qc) writew(aPIOMD4 | aGO, chan + ADMA_CONTROL); } -static int adma_qc_issue(struct ata_queued_cmd *qc) +static unsigned int adma_qc_issue(struct ata_queued_cmd *qc) { struct adma_port_priv *pp = qc->ap->private_data; diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 89bcd85fa58c..281223a0e45f 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -328,7 +328,7 @@ static void mv_host_stop(struct ata_host_set *host_set); static int mv_port_start(struct ata_port *ap); static void mv_port_stop(struct ata_port *ap); static void mv_qc_prep(struct ata_queued_cmd *qc); -static int mv_qc_issue(struct ata_queued_cmd *qc); +static unsigned int mv_qc_issue(struct ata_queued_cmd *qc); static irqreturn_t mv_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static void mv_eng_timeout(struct ata_port *ap); @@ -1040,7 +1040,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) * LOCKING: * Inherited from caller. */ -static int mv_qc_issue(struct ata_queued_cmd *qc) +static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) { void __iomem *port_mmio = mv_ap_base(qc->ap); struct mv_port_priv *pp = qc->ap->private_data; diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index b0b0a69b3563..bac36d5b7c3e 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -95,7 +95,7 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); static void pdc_irq_clear(struct ata_port *ap); -static int pdc_qc_issue_prot(struct ata_queued_cmd *qc); +static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); static struct scsi_host_template pdc_ata_sht = { @@ -544,7 +544,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc) readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */ } -static int pdc_qc_issue_prot(struct ata_queued_cmd *qc) +static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) { switch (qc->tf.protocol) { case ATA_PROT_DMA: diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index de05e2883f9c..2afbeb77f6fe 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -120,7 +120,7 @@ static void qs_host_stop(struct ata_host_set *host_set); static void qs_port_stop(struct ata_port *ap); static void qs_phy_reset(struct ata_port *ap); static void qs_qc_prep(struct ata_queued_cmd *qc); -static int qs_qc_issue(struct ata_queued_cmd *qc); +static unsigned int qs_qc_issue(struct ata_queued_cmd *qc); static int qs_check_atapi_dma(struct ata_queued_cmd *qc); static void qs_bmdma_stop(struct ata_queued_cmd *qc); static u8 qs_bmdma_status(struct ata_port *ap); @@ -352,7 +352,7 @@ static inline void qs_packet_start(struct ata_queued_cmd *qc) readl(chan + QS_CCT_CFF); /* flush */ } -static int qs_qc_issue(struct ata_queued_cmd *qc) +static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) { struct qs_port_priv *pp = qc->ap->private_data; diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index fb59012b9fbe..5a7a7b1d4add 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -251,7 +251,7 @@ 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 void sil24_phy_reset(struct ata_port *ap); static void sil24_qc_prep(struct ata_queued_cmd *qc); -static int sil24_qc_issue(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); @@ -557,7 +557,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) sil24_fill_sg(qc, sge); } -static int sil24_qc_issue(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; diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index bc87c16c80d2..3175c6bb4fec 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -174,7 +174,7 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, u32 offset, u32 size); static void pdc20621_irq_clear(struct ata_port *ap); -static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); +static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); static struct scsi_host_template pdc_sata_sht = { @@ -678,7 +678,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc) } } -static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc) +static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc) { switch (qc->tf.protocol) { case ATA_PROT_DMA: diff --git a/include/linux/libata.h b/include/linux/libata.h index 8ff3a7f6f63c..b1ea2f98bfbb 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -427,7 +427,7 @@ struct ata_port_operations { void (*bmdma_start) (struct ata_queued_cmd *qc); void (*qc_prep) (struct ata_queued_cmd *qc); - int (*qc_issue) (struct ata_queued_cmd *qc); + unsigned int (*qc_issue) (struct ata_queued_cmd *qc); void (*eng_timeout) (struct ata_port *ap); @@ -515,7 +515,7 @@ 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_qc_prep(struct ata_queued_cmd *qc); -extern int ata_qc_issue_prot(struct ata_queued_cmd *qc); +extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc); extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen); extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, -- cgit v1.2.3-59-g8ed1b From 041c5fc33cb7ed4fe5322585a611fb6e29a05d3a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:36 +0900 Subject: [PATCH] SCSI: export scsi_eh_finish_cmd() and scsi_eh_flush_done_q() Export two SCSI EH command handling functions. To be used by libata EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/scsi_error.c | 7 ++++--- include/scsi/scsi_eh.h | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index a2333d2c7af0..6bac3d2668fa 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -584,8 +584,7 @@ static int scsi_request_sense(struct scsi_cmnd *scmd) * keep a list of pending commands for final completion, and once we * are ready to leave error handling we handle completion for real. **/ -static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, - struct list_head *done_q) +void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q) { scmd->device->host->host_failed--; scmd->eh_eflags = 0; @@ -597,6 +596,7 @@ static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, scsi_setup_cmd_retry(scmd); list_move_tail(&scmd->eh_entry, done_q); } +EXPORT_SYMBOL(scsi_eh_finish_cmd); /** * scsi_eh_get_sense - Get device sense data. @@ -1425,7 +1425,7 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost, * @done_q: list_head of processed commands. * **/ -static void scsi_eh_flush_done_q(struct list_head *done_q) +void scsi_eh_flush_done_q(struct list_head *done_q) { struct scsi_cmnd *scmd, *next; @@ -1454,6 +1454,7 @@ static void scsi_eh_flush_done_q(struct list_head *done_q) } } } +EXPORT_SYMBOL(scsi_eh_flush_done_q); /** * scsi_unjam_host - Attempt to fix a host which has a cmd that failed. diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index fabd879c2f2e..d160880b2a87 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -35,6 +35,9 @@ static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr) } +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); extern void scsi_report_bus_reset(struct Scsi_Host *, int); extern void scsi_report_device_reset(struct Scsi_Host *, int, int); extern int scsi_block_when_processing_errors(struct scsi_device *); -- cgit v1.2.3-59-g8ed1b From a72ec4ce6d3ae92e76baf5b2c65cc26e5e775e83 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:37 +0900 Subject: [PATCH] libata: implement and apply ata_eh_qc_complete/retry() Implement ata_eh_qc_complete/retry() using scsi_eh_finish_cmd() and scsi_eh_flush_done_q(). This removes all eh scsicmd finish hacks from low level drivers. This change was first suggested by Jeff Garzik. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 12 +++------ drivers/scsi/libata-core.c | 14 ++++------- drivers/scsi/libata-scsi.c | 59 ++++++++++++++++++++++++++++++++++++++++----- drivers/scsi/sata_mv.c | 12 +-------- drivers/scsi/sata_promise.c | 12 ++------- drivers/scsi/sata_sil24.c | 10 +------- drivers/scsi/sata_sx4.c | 12 ++------- include/linux/libata.h | 3 +++ 8 files changed, 70 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 0f6e4dd22901..5a6b23009897 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -672,19 +672,13 @@ static void ahci_eng_timeout(struct ata_port *ap) ap->id); } else { ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT)); - - /* hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ - qc->scsidone = scsi_finish_command; qc->err_mask |= AC_ERR_TIMEOUT; - ata_qc_complete(qc); } spin_unlock_irqrestore(&host_set->lock, flags); + + if (qc) + ata_eh_qc_complete(qc); } static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b29bf0dc948a..93ae2dcc837c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3449,14 +3449,6 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) spin_lock_irqsave(&host_set->lock, flags); - /* hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ - qc->scsidone = scsi_finish_command; - switch (qc->tf.protocol) { case ATA_PROT_DMA: @@ -3480,12 +3472,13 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) /* complete taskfile transaction */ qc->err_mask |= ac_err_mask(drv_stat); - ata_qc_complete(qc); break; } spin_unlock_irqrestore(&host_set->lock, flags); + ata_eh_qc_complete(qc); + DPRINTK("EXIT\n"); } @@ -4422,6 +4415,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, INIT_WORK(&ap->packet_task, atapi_packet_task, ap); INIT_WORK(&ap->pio_task, ata_pio_task, ap); + INIT_LIST_HEAD(&ap->eh_done_q); for (i = 0; i < ATA_MAX_DEVICES; i++) ap->device[i].devno = i; @@ -5165,6 +5159,8 @@ EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_id_string); EXPORT_SYMBOL_GPL(ata_dev_config); 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); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 95e3c278dd43..ab6b53349d6f 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -738,17 +738,64 @@ int ata_scsi_error(struct Scsi_Host *host) ap = (struct ata_port *) &host->hostdata[0]; ap->ops->eng_timeout(ap); - /* TODO: this is per-command; when queueing is supported - * this code will either change or move to a more - * appropriate place - */ - host->host_failed--; - INIT_LIST_HEAD(&host->eh_cmd_q); + assert(host->host_failed == 0 && 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); + assert(!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. + * This function might need to adjust scmd->retries for commands + * which get retried due to unrelated NCQ failures. + */ +void ata_eh_qc_retry(struct ata_queued_cmd *qc) +{ + __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/sata_mv.c b/drivers/scsi/sata_mv.c index 281223a0e45f..d9a554ca45c7 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1839,7 +1839,6 @@ static void mv_phy_reset(struct ata_port *ap) static void mv_eng_timeout(struct ata_port *ap) { struct ata_queued_cmd *qc; - unsigned long flags; printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id); DPRINTK("All regs @ start of eng_timeout\n"); @@ -1858,17 +1857,8 @@ static void mv_eng_timeout(struct ata_port *ap) printk(KERN_ERR "ata%u: BUG: timeout without command\n", ap->id); } else { - /* hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ - spin_lock_irqsave(&ap->host_set->lock, flags); - qc->scsidone = scsi_finish_command; qc->err_mask |= AC_ERR_TIMEOUT; - ata_qc_complete(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + ata_eh_qc_complete(qc); } } diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index bac36d5b7c3e..77ef646b0f92 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -400,21 +400,12 @@ static void pdc_eng_timeout(struct ata_port *ap) goto out; } - /* hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ - qc->scsidone = scsi_finish_command; - switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: printk(KERN_ERR "ata%u: command timeout\n", ap->id); drv_stat = ata_wait_idle(ap); qc->err_mask |= __ac_err_mask(drv_stat); - ata_qc_complete(qc); break; default: @@ -424,12 +415,13 @@ static void pdc_eng_timeout(struct ata_port *ap) ap->id, qc->tf.command, drv_stat); qc->err_mask |= ac_err_mask(drv_stat); - ata_qc_complete(qc); break; } out: spin_unlock_irqrestore(&host_set->lock, flags); + if (qc) + ata_eh_qc_complete(qc); DPRINTK("EXIT\n"); } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 5a7a7b1d4add..7222fc7ff3fc 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -644,17 +644,9 @@ static void sil24_eng_timeout(struct ata_port *ap) return; } - /* - * hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ printk(KERN_ERR "ata%u: command timeout\n", ap->id); - qc->scsidone = scsi_finish_command; qc->err_mask |= AC_ERR_TIMEOUT; - ata_qc_complete(qc); + ata_eh_qc_complete(qc); sil24_reset_controller(ap); } diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 3175c6bb4fec..9f992fbcf2e7 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -872,20 +872,11 @@ static void pdc_eng_timeout(struct ata_port *ap) goto out; } - /* hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ - qc->scsidone = scsi_finish_command; - switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: printk(KERN_ERR "ata%u: command timeout\n", ap->id); qc->err_mask |= __ac_err_mask(ata_wait_idle(ap)); - ata_qc_complete(qc); break; default: @@ -895,12 +886,13 @@ static void pdc_eng_timeout(struct ata_port *ap) ap->id, qc->tf.command, drv_stat); qc->err_mask |= ac_err_mask(drv_stat); - ata_qc_complete(qc); break; } out: spin_unlock_irqrestore(&host_set->lock, flags); + if (qc) + ata_eh_qc_complete(qc); DPRINTK("EXIT\n"); } diff --git a/include/linux/libata.h b/include/linux/libata.h index b1ea2f98bfbb..576788de962a 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -398,6 +398,7 @@ struct ata_port { unsigned long pio_task_timeout; u32 msg_enable; + struct list_head eh_done_q; void *private_data; }; @@ -490,6 +491,8 @@ 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 *); -- cgit v1.2.3-59-g8ed1b From 9506437921504df18c6601f7d09bb23d72d2f6ba Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 13:09:37 +0900 Subject: [PATCH] libata: create pio/atapi task queueing wrappers Wrap pio/atapi task queueing in correspondingly named functions. This change doesn't change anything. It's preparation for follow-up pio-task/eh sync patch. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 93ae2dcc837c..71de697e2327 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1072,6 +1072,24 @@ 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) +{ + queue_work(ata_wq, &ap->pio_task); +} + +static inline void +ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay) +{ + queue_delayed_work(ata_wq, &ap->pio_task, delay); +} + void ata_qc_complete_internal(struct ata_queued_cmd *qc) { struct completion *waiting = qc->private_data; @@ -3414,7 +3432,7 @@ fsm_start: } if (timeout) - queue_delayed_work(ata_wq, &ap->pio_task, timeout); + ata_queue_delayed_pio_task(ap, timeout); else if (!qc_completed) goto fsm_start; } @@ -3737,26 +3755,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; - queue_work(ata_wq, &ap->pio_task); + ata_queue_pio_task(ap); break; case ATA_PROT_ATAPI: ata_qc_set_polling(qc); ata_tf_to_host(ap, &qc->tf); - queue_work(ata_wq, &ap->packet_task); + ata_queue_packet_task(ap); break; case ATA_PROT_ATAPI_NODATA: ap->flags |= ATA_FLAG_NOINTR; ata_tf_to_host(ap, &qc->tf); - queue_work(ata_wq, &ap->packet_task); + ata_queue_packet_task(ap); 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 */ - queue_work(ata_wq, &ap->packet_task); + ata_queue_packet_task(ap); break; default: @@ -4187,7 +4205,7 @@ static void atapi_packet_task(void *_data) /* PIO commands are handled by polling */ ap->hsm_task_state = HSM_ST; - queue_work(ata_wq, &ap->pio_task); + ata_queue_pio_task(ap); } return; -- cgit v1.2.3-59-g8ed1b From e0bfd149973d22a4330dd6665b54d1dcca07174a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 16:31:53 +0900 Subject: [PATCH] ahci: stop engine during hard reset AHCI spec mandates engine to be stopped during hard resets. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 5a6b23009897..2abc0aca5a8d 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -504,7 +504,9 @@ static void ahci_phy_reset(struct ata_port *ap) struct ata_device *dev = &ap->device[0]; u32 new_tmp, tmp; + ahci_stop_engine(ap); __sata_phy_reset(ap); + ahci_start_engine(ap); if (ap->flags & ATA_FLAG_PORT_DISABLED) return; -- cgit v1.2.3-59-g8ed1b From 22b49985f526796471c074c0e56bcebfd633a6ff Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 23 Jan 2006 21:38:44 +0900 Subject: [PATCH] ahci: add constants for SRST Add constants needed to perform SRST. This is preparation for adding softreset method. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 2abc0aca5a8d..5caf6dec1d40 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -66,6 +66,8 @@ enum { AHCI_IRQ_ON_SG = (1 << 31), AHCI_CMD_ATAPI = (1 << 5), AHCI_CMD_WRITE = (1 << 6), + AHCI_CMD_RESET = (1 << 8), + AHCI_CMD_CLR_BUSY = (1 << 10), RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ @@ -85,6 +87,7 @@ enum { /* HOST_CAP bits */ HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ + HOST_CAP_CLO = (1 << 24), /* Command List Override support */ /* registers for each SATA port */ PORT_LST_ADDR = 0x00, /* command list DMA addr */ @@ -138,6 +141,7 @@ enum { PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */ + PORT_CMD_CLO = (1 << 3), /* Command list override */ PORT_CMD_POWER_ON = (1 << 2), /* Power up device */ PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */ PORT_CMD_START = (1 << 0), /* Enable port DMA engine */ -- cgit v1.2.3-59-g8ed1b From 6f8b99589524f3e759e44721376abcdf88ed8915 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 24 Jan 2006 17:05:21 +0900 Subject: [PATCH] libata: export ata_busy_sleep Export ata_busy_sleep(), to be used by low level driver reset functions. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 9 +++------ include/linux/libata.h | 3 +++ 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 71de697e2327..4336fc889acd 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -61,9 +61,6 @@ #include "libata.h" -static unsigned int ata_busy_sleep (struct ata_port *ap, - unsigned long tmout_pat, - unsigned long tmout); static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev); static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); static void ata_set_mode(struct ata_port *ap); @@ -1960,9 +1957,8 @@ err_out: * */ -static unsigned int ata_busy_sleep (struct ata_port *ap, - unsigned long tmout_pat, - unsigned long tmout) +unsigned int ata_busy_sleep (struct ata_port *ap, + unsigned long tmout_pat, unsigned long tmout) { unsigned long timer_start, timeout; u8 status; @@ -5167,6 +5163,7 @@ EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); +EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_error); diff --git a/include/linux/libata.h b/include/linux/libata.h index 576788de962a..45646f6ebbf5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -500,6 +500,9 @@ extern int ata_scsi_device_suspend(struct scsi_device *); extern int ata_device_resume(struct ata_port *, struct ata_device *); extern int ata_device_suspend(struct ata_port *, struct ata_device *); extern int ata_ratelimit(void); +extern unsigned int ata_busy_sleep(struct ata_port *ap, + unsigned long timeout_pat, + unsigned long timeout); /* * Default driver ops implementations -- cgit v1.2.3-59-g8ed1b From b4dc7623c1bb258b66418261dab40f0e4cfc6d42 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 24 Jan 2006 17:05:22 +0900 Subject: [PATCH] libata: modify ata_dev_try_classify Make ata_dev_try_classify take @r_err to store tf error register value on completion and return device class instead of directly manipulating dev->class. This is preparation for new reset mechanism. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4336fc889acd..1f78e246f5e0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -830,6 +830,7 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf) * ata_dev_try_classify - Parse returned ATA device signature * @ap: ATA channel to examine * @device: Device to examine (starting at zero) + * @r_err: Value of error register on completion * * After an event -- SRST, E.D.D., or SATA COMRESET -- occurs, * an ATA/ATAPI-defined set of values is placed in the ATA @@ -842,11 +843,14 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf) * * LOCKING: * caller. + * + * RETURNS: + * Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE. */ -static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device) +static unsigned int +ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err) { - struct ata_device *dev = &ap->device[device]; struct ata_taskfile tf; unsigned int class; u8 err; @@ -857,8 +861,8 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device) ap->ops->tf_read(ap, &tf); err = tf.feature; - - dev->class = ATA_DEV_NONE; + if (r_err) + *r_err = err; /* see if device passed diags */ if (err == 1) @@ -866,18 +870,16 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device) else if ((device == 0) && (err == 0x81)) /* do nothing */ ; else - return err; + return ATA_DEV_NONE; - /* determine if device if ATA or ATAPI */ + /* determine if device is ATA or ATAPI */ class = ata_dev_classify(&tf); + if (class == ATA_DEV_UNKNOWN) - return err; + return ATA_DEV_NONE; if ((class == ATA_DEV_ATA) && (ata_chk_status(ap) == 0)) - return err; - - dev->class = class; - - return err; + return ATA_DEV_NONE; + return class; } /** @@ -2177,9 +2179,9 @@ void ata_bus_reset(struct ata_port *ap) /* * determine by signature whether we have ATA or ATAPI devices */ - err = ata_dev_try_classify(ap, 0); + ap->device[0].class = ata_dev_try_classify(ap, 0, &err); if ((slave_possible) && (err != 0x81)) - ata_dev_try_classify(ap, 1); + ap->device[1].class = ata_dev_try_classify(ap, 1, &err); /* re-enable interrupts */ if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ -- cgit v1.2.3-59-g8ed1b From c19ba8af4f104cca28d548cac55c128b28dd31fb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 24 Jan 2006 17:05:22 +0900 Subject: [PATCH] libata: new ->probe_reset operation Add new ->probe_reset operation to ata_port_operations obsoleting ->phy_reset. The main difference from ->phy_reset is that the new operation is not allowed to manipulate libata internals directly. It's not allowed to configure or disable the port or devices. It can only succeed or fail and classify attached devices into passed @classes. This change gives more control to higher level and eases sharing reset methods with EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 19 ++++++++++++++++++- include/linux/libata.h | 8 +++++--- 2 files changed, 23 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1f78e246f5e0..147e1461062d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1485,7 +1485,24 @@ static int ata_bus_probe(struct ata_port *ap) { unsigned int i, found = 0; - ap->ops->phy_reset(ap); + if (ap->ops->probe_reset) { + unsigned int classes[ATA_MAX_DEVICES]; + int rc; + + ata_port_probe(ap); + + rc = ap->ops->probe_reset(ap, classes); + if (rc == 0) { + for (i = 0; i < ATA_MAX_DEVICES; i++) + ap->device[i].class = classes[i]; + } else { + printk(KERN_ERR "ata%u: probe reset failed, " + "disabling port\n", ap->id); + ata_port_disable(ap); + } + } else + ap->ops->phy_reset(ap); + if (ap->flags & ATA_FLAG_PORT_DISABLED) goto err_out; diff --git a/include/linux/libata.h b/include/linux/libata.h index 45646f6ebbf5..a84d1c3a5429 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -148,9 +148,9 @@ enum { 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), /* use ATA SRST, not E.D.D. */ + 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), /* use COMRESET */ + 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. */ @@ -419,7 +419,9 @@ struct ata_port_operations { u8 (*check_altstatus)(struct ata_port *ap); void (*dev_select)(struct ata_port *ap, unsigned int device); - void (*phy_reset) (struct ata_port *ap); + void (*phy_reset) (struct ata_port *ap); /* obsolete */ + int (*probe_reset) (struct ata_port *ap, unsigned int *classes); + void (*post_set_mode) (struct ata_port *ap); int (*check_atapi_dma) (struct ata_queued_cmd *qc); -- cgit v1.2.3-59-g8ed1b From a707cd6e2d0a8c21dd8aeef8e4a0c0ccf8774fa9 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn / snakebyte Date: Thu, 26 Jan 2006 22:02:51 +0100 Subject: [PATCH] BUG_ON() Conversion in net/tulip/xircom_cb.c hi, this changes if() BUG(); constructs to BUG_ON() which is cleaner and can better optimized away Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik --- drivers/net/tulip/xircom_cb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 60d1e05ab732..c5c738a51ee3 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -598,10 +598,8 @@ static void setup_descriptors(struct xircom_private *card) enter("setup_descriptors"); - if (card->rx_buffer == NULL) - BUG(); - if (card->tx_buffer == NULL) - BUG(); + BUG_ON(card->rx_buffer == NULL); + BUG_ON(card->tx_buffer == NULL); /* Receive descriptors */ memset(card->rx_buffer, 0, 128); /* clear the descriptors */ -- cgit v1.2.3-59-g8ed1b From 7e0b58f32fb5e9c958078a6d722a7d0b230346a7 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn / snakebyte Date: Thu, 26 Jan 2006 22:02:43 +0100 Subject: [PATCH] BUG_ON() Conversion in net/tulip/de2104x.c hi, this changes if() BUG(); constructs to BUG_ON() which is cleaner and can better optimized away One of the if()s contains a call to de_is_running(), which seems to be safe to replace, but someone with more knownledge of the code might want to verify this... Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik --- drivers/net/tulip/de2104x.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index d7fb3ffe06ac..d6c3d52d2e86 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -402,8 +402,7 @@ static void de_rx (struct de_private *de) unsigned copying_skb, buflen; skb = de->rx_skb[rx_tail].skb; - if (!skb) - BUG(); + BUG_ON(!skb); rmb(); status = le32_to_cpu(de->rx_ring[rx_tail].opts1); if (status & DescOwn) @@ -545,8 +544,7 @@ static void de_tx (struct de_private *de) break; skb = de->tx_skb[tx_tail].skb; - if (!skb) - BUG(); + BUG_ON(!skb); if (unlikely(skb == DE_DUMMY_SKB)) goto next; @@ -789,8 +787,7 @@ static void __de_set_rx_mode (struct net_device *dev) de->tx_head = NEXT_TX(entry); - if (TX_BUFFS_AVAIL(de) < 0) - BUG(); + BUG_ON(TX_BUFFS_AVAIL(de) < 0); if (TX_BUFFS_AVAIL(de) == 0) netif_stop_queue(dev); @@ -916,8 +913,7 @@ static void de_set_media (struct de_private *de) unsigned media = de->media_type; u32 macmode = dr32(MacMode); - if (de_is_running(de)) - BUG(); + BUG_ON(de_is_running(de)); if (de->de21040) dw32(CSR11, FULL_DUPLEX_MAGIC); @@ -1153,8 +1149,7 @@ static void de_media_interrupt (struct de_private *de, u32 status) return; } - if (!(status & LinkFail)) - BUG(); + BUG_ON(!(status & LinkFail)); if (netif_carrier_ok(de->dev)) { de_link_down(de); @@ -2092,8 +2087,7 @@ static void __exit de_remove_one (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); struct de_private *de = dev->priv; - if (!dev) - BUG(); + BUG_ON(!dev); unregister_netdev(dev); kfree(de->ee_data); iounmap(de->regs); -- cgit v1.2.3-59-g8ed1b From cca4aa83c79bcd571b06c83c50ea63cb75f1c2bb Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn / snakebyte Date: Thu, 26 Jan 2006 22:02:49 +0100 Subject: [PATCH] BUG_ON() Conversion in net/tulip/winbond-840.c hi, this changes if() BUG(); constructs to BUG_ON() which is cleaner and can better optimized away Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik --- drivers/net/tulip/winbond-840.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 5b1af3986abf..ba05dedf29d3 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -1645,7 +1645,7 @@ static int w840_suspend (struct pci_dev *pdev, pm_message_t state) /* no more hardware accesses behind this line. */ - if (np->csr6) BUG(); + BUG_ON(np->csr6); if (ioread32(ioaddr + IntrEnable)) BUG(); /* pci_power_off(pdev, -1); */ -- cgit v1.2.3-59-g8ed1b From 7d3d0439f574a4857c97b3ad2e63b082b7382d7e Mon Sep 17 00:00:00 2001 From: Ravinandan Arakali Date: Wed, 25 Jan 2006 14:53:07 -0500 Subject: [PATCH] S2io: Large Receive Offload (LRO) feature(v2) for Neterion (s2io) 10GbE Xframe PCI-X and PCI-E NICs Hi, Below is a patch for the Large Receive Offload feature. Please review and let us know your comments. LRO algorithm was described in an OLS 2005 presentation, located at ftp.s2io.com user: linuxdocs password: HALdocs The same ftp site has Programming Manual for Xframe-I ASIC. LRO feature is supported on Neterion Xframe-I, Xframe-II and Xframe-Express 10GbE NICs. Brief description: The Large Receive Offload(LRO) feature is a stateless offload that is complementary to TSO feature but on the receive path. The idea is to combine and collapse(upto 64K maximum) in the driver, in-sequence TCP packets belonging to the same session. It is mainly designed to improve 1500 mtu receive performance, since Jumbo frame performance is already close to 10GbE line rate. Some performance numbers are attached below. Implementation details: 1. Handle packet chains from multiple sessions(current default MAX_LRO_SESSSIONS=32). 2. Examine each packet for eligiblity to aggregate. A packet is considered eligible if it meets all the below criteria. a. It is a TCP/IP packet and L2 type is not LLC or SNAP. b. The packet has no checksum errors(L3 and L4). c. There are no IP options. The only TCP option supported is timestamps. d. Search and locate the LRO object corresponding to this socket and ensure packet is in TCP sequence. e. It's not a special packet(SYN, FIN, RST, URG, PSH etc. flags are not set). f. TCP payload is non-zero(It's not a pure ACK). g. It's not an IP-fragmented packet. 3. If a packet is found eligible, the LRO object is updated with information such as next sequence number expected, current length of aggregated packet and so on. If not eligible or max packets reached, update IP and TCP headers of first packet in the chain and pass it up to stack. 4. The frag_list in skb structure is used to chain packets into one large packet. Kernel changes required: None Performance results: Main focus of the initial testing was on 1500 mtu receiver, since this is a bottleneck not covered by the existing stateless offloads. There are couple disclaimers about the performance results below: 1. Your mileage will vary!!!! We initially concentrated on couple pci-x 2.0 platforms that are powerful enough to push 10 GbE NIC and do not have bottlenecks other than cpu%; testing on other platforms is still in progress. On some lower end systems we are seeing lower gains. 2. Current LRO implementation is still (for the most part) software based, and therefore performance potential of the feature is far from being realized. Full hw implementation of LRO is expected in the next version of Xframe ASIC. Performance delta(with MTU=1500) going from LRO disabled to enabled: IBM 2-way Xeon (x366) : 3.5 to 7.1 Gbps 2-way Opteron : 4.5 to 6.1 Gbps Signed-off-by: Ravinandan Arakali Signed-off-by: Jeff Garzik --- drivers/net/s2io.c | 586 +++++++++++++++++++++++++++++++++++++++++++++++------ drivers/net/s2io.h | 38 ++++ 2 files changed, 562 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 49b597cbc19a..4e392914971e 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -57,6 +57,9 @@ #include #include #include +#include +#include +#include #include #include @@ -66,7 +69,7 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "Version 2.0.9.4" +#define DRV_VERSION "2.0.11.2" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; @@ -168,6 +171,11 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = { {"\n DRIVER STATISTICS"}, {"single_bit_ecc_errs"}, {"double_bit_ecc_errs"}, + ("lro_aggregated_pkts"), + ("lro_flush_both_count"), + ("lro_out_of_sequence_pkts"), + ("lro_flush_due_to_max_pkts"), + ("lro_avg_aggr_pkts"), }; #define S2IO_STAT_LEN sizeof(ethtool_stats_keys)/ ETH_GSTRING_LEN @@ -317,6 +325,12 @@ static unsigned int indicate_max_pkts; static unsigned int rxsync_frequency = 3; /* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */ static unsigned int intr_type = 0; +/* Large receive offload feature */ +static unsigned int lro = 0; +/* Max pkts to be aggregated by LRO at one time. If not specified, + * aggregation happens until we hit max IP pkt size(64K) + */ +static unsigned int lro_max_pkts = 0xFFFF; /* * S2IO device table. @@ -1476,6 +1490,19 @@ static int init_nic(struct s2io_nic *nic) writel((u32) (val64 >> 32), (add + 4)); val64 = readq(&bar0->mac_cfg); + /* Enable FCS stripping by adapter */ + add = &bar0->mac_cfg; + val64 = readq(&bar0->mac_cfg); + val64 |= MAC_CFG_RMAC_STRIP_FCS; + if (nic->device_type == XFRAME_II_DEVICE) + writeq(val64, &bar0->mac_cfg); + else { + writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); + writel((u32) (val64), add); + writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); + writel((u32) (val64 >> 32), (add + 4)); + } + /* * Set the time value to be inserted in the pause frame * generated by xena. @@ -2569,6 +2596,8 @@ static void rx_intr_handler(ring_info_t *ring_data) #ifndef CONFIG_S2IO_NAPI int pkt_cnt = 0; #endif + int i; + spin_lock(&nic->rx_lock); if (atomic_read(&nic->card_state) == CARD_DOWN) { DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n", @@ -2661,6 +2690,18 @@ static void rx_intr_handler(ring_info_t *ring_data) break; #endif } + if (nic->lro) { + /* Clear all LRO sessions before exiting */ + for (i=0; ilro0_n[i]; + if (lro->in_use) { + update_L3L4_header(nic, lro); + queue_rx_frame(lro->parent); + clear_lro_session(lro); + } + } + } + spin_unlock(&nic->rx_lock); } @@ -3668,23 +3709,32 @@ s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs) * else schedule a tasklet to reallocate the buffers. */ for (i = 0; i < config->rx_ring_num; i++) { - int rxb_size = atomic_read(&sp->rx_bufs_left[i]); - int level = rx_buffer_level(sp, rxb_size, i); - - if ((level == PANIC) && (!TASKLET_IN_USE)) { - DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name); - DBG_PRINT(INTR_DBG, "PANIC levels\n"); - if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", - dev->name); - DBG_PRINT(ERR_DBG, " in ISR!!\n"); + if (!sp->lro) { + int rxb_size = atomic_read(&sp->rx_bufs_left[i]); + int level = rx_buffer_level(sp, rxb_size, i); + + if ((level == PANIC) && (!TASKLET_IN_USE)) { + DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", + dev->name); + DBG_PRINT(INTR_DBG, "PANIC levels\n"); + if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", + dev->name); + DBG_PRINT(ERR_DBG, " in ISR!!\n"); + clear_bit(0, (&sp->tasklet_status)); + atomic_dec(&sp->isr_cnt); + return IRQ_HANDLED; + } clear_bit(0, (&sp->tasklet_status)); - atomic_dec(&sp->isr_cnt); - return IRQ_HANDLED; + } else if (level == LOW) { + tasklet_schedule(&sp->task); } - clear_bit(0, (&sp->tasklet_status)); - } else if (level == LOW) { - tasklet_schedule(&sp->task); + } + else if (fill_rx_buffers(sp, i) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", + dev->name); + DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); + break; } } @@ -3697,29 +3747,37 @@ s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs) { ring_info_t *ring = (ring_info_t *)dev_id; nic_t *sp = ring->nic; + struct net_device *dev = (struct net_device *) dev_id; int rxb_size, level, rng_n; atomic_inc(&sp->isr_cnt); rx_intr_handler(ring); rng_n = ring->ring_no; - rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]); - level = rx_buffer_level(sp, rxb_size, rng_n); - - if ((level == PANIC) && (!TASKLET_IN_USE)) { - int ret; - DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__); - DBG_PRINT(INTR_DBG, "PANIC levels\n"); - if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "Out of memory in %s", - __FUNCTION__); + if (!sp->lro) { + rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]); + level = rx_buffer_level(sp, rxb_size, rng_n); + + if ((level == PANIC) && (!TASKLET_IN_USE)) { + int ret; + DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__); + DBG_PRINT(INTR_DBG, "PANIC levels\n"); + if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "Out of memory in %s", + __FUNCTION__); + clear_bit(0, (&sp->tasklet_status)); + return IRQ_HANDLED; + } clear_bit(0, (&sp->tasklet_status)); - return IRQ_HANDLED; + } else if (level == LOW) { + tasklet_schedule(&sp->task); } - clear_bit(0, (&sp->tasklet_status)); - } else if (level == LOW) { - tasklet_schedule(&sp->task); } + else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); + DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); + } + atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; @@ -3875,24 +3933,33 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs) */ #ifndef CONFIG_S2IO_NAPI for (i = 0; i < config->rx_ring_num; i++) { - int ret; - int rxb_size = atomic_read(&sp->rx_bufs_left[i]); - int level = rx_buffer_level(sp, rxb_size, i); - - if ((level == PANIC) && (!TASKLET_IN_USE)) { - DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name); - DBG_PRINT(INTR_DBG, "PANIC levels\n"); - if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", - dev->name); - DBG_PRINT(ERR_DBG, " in ISR!!\n"); + if (!sp->lro) { + int ret; + int rxb_size = atomic_read(&sp->rx_bufs_left[i]); + int level = rx_buffer_level(sp, rxb_size, i); + + if ((level == PANIC) && (!TASKLET_IN_USE)) { + DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", + dev->name); + DBG_PRINT(INTR_DBG, "PANIC levels\n"); + if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", + dev->name); + DBG_PRINT(ERR_DBG, " in ISR!!\n"); + clear_bit(0, (&sp->tasklet_status)); + atomic_dec(&sp->isr_cnt); + return IRQ_HANDLED; + } clear_bit(0, (&sp->tasklet_status)); - atomic_dec(&sp->isr_cnt); - return IRQ_HANDLED; + } else if (level == LOW) { + tasklet_schedule(&sp->task); } - clear_bit(0, (&sp->tasklet_status)); - } else if (level == LOW) { - tasklet_schedule(&sp->task); + } + else if (fill_rx_buffers(sp, i) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", + dev->name); + DBG_PRINT(ERR_DBG, " in Rx intr!!\n"); + break; } } #endif @@ -5134,6 +5201,16 @@ static void s2io_get_ethtool_stats(struct net_device *dev, tmp_stats[i++] = 0; tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs; tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs; + tmp_stats[i++] = stat_info->sw_stat.clubbed_frms_cnt; + tmp_stats[i++] = stat_info->sw_stat.sending_both; + tmp_stats[i++] = stat_info->sw_stat.outof_sequence_pkts; + tmp_stats[i++] = stat_info->sw_stat.flush_max_pkts; + if (stat_info->sw_stat.num_aggregations) + tmp_stats[i++] = stat_info->sw_stat.sum_avg_pkts_aggregated / + stat_info->sw_stat.num_aggregations; + else + tmp_stats[i++] = 0; + } static int s2io_ethtool_get_regs_len(struct net_device *dev) @@ -5515,6 +5592,14 @@ static int s2io_card_up(nic_t * sp) /* Setting its receive mode */ s2io_set_multicast(dev); + if (sp->lro) { + /* Initialize max aggregatable pkts based on MTU */ + sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu; + /* Check if we can use(if specified) user provided value */ + if (lro_max_pkts < sp->lro_max_aggr_per_sess) + sp->lro_max_aggr_per_sess = lro_max_pkts; + } + /* Enable tasklet for the device */ tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev); @@ -5607,6 +5692,7 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp) ((unsigned long) rxdp->Host_Control); int ring_no = ring_data->ring_no; u16 l3_csum, l4_csum; + lro_t *lro; skb->dev = dev; if (rxdp->Control_1 & RXD_T_CODE) { @@ -5655,7 +5741,8 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp) skb_put(skb, buf2_len); } - if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && + if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && ((!sp->lro) || + (sp->lro && (!(rxdp->Control_1 & RXD_FRAME_IP_FRAG)))) && (sp->rx_csum)) { l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1); l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1); @@ -5666,6 +5753,54 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp) * a flag in the RxD. */ skb->ip_summed = CHECKSUM_UNNECESSARY; + if (sp->lro) { + u32 tcp_len; + u8 *tcp; + int ret = 0; + + ret = s2io_club_tcp_session(skb->data, &tcp, + &tcp_len, &lro, rxdp, sp); + switch (ret) { + case 3: /* Begin anew */ + lro->parent = skb; + goto aggregate; + case 1: /* Aggregate */ + { + lro_append_pkt(sp, lro, + skb, tcp_len); + goto aggregate; + } + case 4: /* Flush session */ + { + lro_append_pkt(sp, lro, + skb, tcp_len); + queue_rx_frame(lro->parent); + clear_lro_session(lro); + sp->mac_control.stats_info-> + sw_stat.flush_max_pkts++; + goto aggregate; + } + case 2: /* Flush both */ + lro->parent->data_len = + lro->frags_len; + sp->mac_control.stats_info-> + sw_stat.sending_both++; + queue_rx_frame(lro->parent); + clear_lro_session(lro); + goto send_up; + case 0: /* sessions exceeded */ + case 5: /* + * First pkt in session not + * L3/L4 aggregatable + */ + break; + default: + DBG_PRINT(ERR_DBG, + "%s: Samadhana!!\n", + __FUNCTION__); + BUG(); + } + } } else { /* * Packet with erroneous checksum, let the @@ -5677,25 +5812,31 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp) skb->ip_summed = CHECKSUM_NONE; } - skb->protocol = eth_type_trans(skb, dev); + if (!sp->lro) { + skb->protocol = eth_type_trans(skb, dev); #ifdef CONFIG_S2IO_NAPI - if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { - /* Queueing the vlan frame to the upper layer */ - vlan_hwaccel_receive_skb(skb, sp->vlgrp, - RXD_GET_VLAN_TAG(rxdp->Control_2)); - } else { - netif_receive_skb(skb); - } + if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { + /* Queueing the vlan frame to the upper layer */ + vlan_hwaccel_receive_skb(skb, sp->vlgrp, + RXD_GET_VLAN_TAG(rxdp->Control_2)); + } else { + netif_receive_skb(skb); + } #else - if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { - /* Queueing the vlan frame to the upper layer */ - vlan_hwaccel_rx(skb, sp->vlgrp, - RXD_GET_VLAN_TAG(rxdp->Control_2)); - } else { - netif_rx(skb); - } + if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { + /* Queueing the vlan frame to the upper layer */ + vlan_hwaccel_rx(skb, sp->vlgrp, + RXD_GET_VLAN_TAG(rxdp->Control_2)); + } else { + netif_rx(skb); + } #endif + } else { +send_up: + queue_rx_frame(skb); + } dev->last_rx = jiffies; +aggregate: atomic_dec(&sp->rx_bufs_left[ring_no]); return SUCCESS; } @@ -5807,6 +5948,8 @@ module_param(indicate_max_pkts, int, 0); #endif module_param(rxsync_frequency, int, 0); module_param(intr_type, int, 0); +module_param(lro, int, 0); +module_param(lro_max_pkts, int, 0); /** * s2io_init_nic - Initialization of the adapter . @@ -5938,6 +6081,7 @@ Defaulting to INTA\n"); else sp->device_type = XFRAME_I_DEVICE; + sp->lro = lro; /* Initialize some PCI/PCI-X fields of the NIC. */ s2io_init_pci(sp); @@ -6241,6 +6385,10 @@ Defaulting to INTA\n"); DBG_PRINT(ERR_DBG, "%s: 3-Buffer mode support has been " "enabled\n",dev->name); + if (sp->lro) + DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n", + dev->name); + /* Initialize device name */ strcpy(sp->name, dev->name); if (sp->device_type & XFRAME_II_DEVICE) @@ -6351,3 +6499,317 @@ void s2io_closer(void) module_init(s2io_starter); module_exit(s2io_closer); + +static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, + struct tcphdr **tcp, RxD_t *rxdp) +{ + int ip_off; + u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len; + + if (!(rxdp->Control_1 & RXD_FRAME_PROTO_TCP)) { + DBG_PRINT(INIT_DBG,"%s: Non-TCP frames not supported for LRO\n", + __FUNCTION__); + return -1; + } + + /* TODO: + * By default the VLAN field in the MAC is stripped by the card, if this + * feature is turned off in rx_pa_cfg register, then the ip_off field + * has to be shifted by a further 2 bytes + */ + switch (l2_type) { + case 0: /* DIX type */ + case 4: /* DIX type with VLAN */ + ip_off = HEADER_ETHERNET_II_802_3_SIZE; + break; + /* LLC, SNAP etc are considered non-mergeable */ + default: + return -1; + } + + *ip = (struct iphdr *)((u8 *)buffer + ip_off); + ip_len = (u8)((*ip)->ihl); + ip_len <<= 2; + *tcp = (struct tcphdr *)((unsigned long)*ip + ip_len); + + return 0; +} + +static int check_for_socket_match(lro_t *lro, struct iphdr *ip, + struct tcphdr *tcp) +{ + DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); + if ((lro->iph->saddr != ip->saddr) || (lro->iph->daddr != ip->daddr) || + (lro->tcph->source != tcp->source) || (lro->tcph->dest != tcp->dest)) + return -1; + return 0; +} + +static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp) +{ + return(ntohs(ip->tot_len) - (ip->ihl << 2) - (tcp->doff << 2)); +} + +static void initiate_new_session(lro_t *lro, u8 *l2h, + struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len) +{ + DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); + lro->l2h = l2h; + lro->iph = ip; + lro->tcph = tcp; + lro->tcp_next_seq = tcp_pyld_len + ntohl(tcp->seq); + lro->tcp_ack = ntohl(tcp->ack_seq); + lro->sg_num = 1; + lro->total_len = ntohs(ip->tot_len); + lro->frags_len = 0; + /* + * check if we saw TCP timestamp. Other consistency checks have + * already been done. + */ + if (tcp->doff == 8) { + u32 *ptr; + ptr = (u32 *)(tcp+1); + lro->saw_ts = 1; + lro->cur_tsval = *(ptr+1); + lro->cur_tsecr = *(ptr+2); + } + lro->in_use = 1; +} + +static void update_L3L4_header(nic_t *sp, lro_t *lro) +{ + struct iphdr *ip = lro->iph; + struct tcphdr *tcp = lro->tcph; + u16 nchk; + StatInfo_t *statinfo = sp->mac_control.stats_info; + DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); + + /* Update L3 header */ + ip->tot_len = htons(lro->total_len); + ip->check = 0; + nchk = ip_fast_csum((u8 *)lro->iph, ip->ihl); + ip->check = nchk; + + /* Update L4 header */ + tcp->ack_seq = lro->tcp_ack; + tcp->window = lro->window; + + /* Update tsecr field if this session has timestamps enabled */ + if (lro->saw_ts) { + u32 *ptr = (u32 *)(tcp + 1); + *(ptr+2) = lro->cur_tsecr; + } + + /* Update counters required for calculation of + * average no. of packets aggregated. + */ + statinfo->sw_stat.sum_avg_pkts_aggregated += lro->sg_num; + statinfo->sw_stat.num_aggregations++; +} + +static void aggregate_new_rx(lro_t *lro, struct iphdr *ip, + struct tcphdr *tcp, u32 l4_pyld) +{ + DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); + lro->total_len += l4_pyld; + lro->frags_len += l4_pyld; + lro->tcp_next_seq += l4_pyld; + lro->sg_num++; + + /* Update ack seq no. and window ad(from this pkt) in LRO object */ + lro->tcp_ack = tcp->ack_seq; + lro->window = tcp->window; + + if (lro->saw_ts) { + u32 *ptr; + /* Update tsecr and tsval from this packet */ + ptr = (u32 *) (tcp + 1); + lro->cur_tsval = *(ptr + 1); + lro->cur_tsecr = *(ptr + 2); + } +} + +static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip, + struct tcphdr *tcp, u32 tcp_pyld_len) +{ + DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); + u8 *ptr; + + if (!tcp_pyld_len) { + /* Runt frame or a pure ack */ + return -1; + } + + if (ip->ihl != 5) /* IP has options */ + return -1; + + if (tcp->urg || tcp->psh || tcp->rst || tcp->syn || tcp->fin || + !tcp->ack) { + /* + * Currently recognize only the ack control word and + * any other control field being set would result in + * flushing the LRO session + */ + return -1; + } + + /* + * Allow only one TCP timestamp option. Don't aggregate if + * any other options are detected. + */ + if (tcp->doff != 5 && tcp->doff != 8) + return -1; + + if (tcp->doff == 8) { + ptr = (u8 *)(tcp + 1); + while (*ptr == TCPOPT_NOP) + ptr++; + if (*ptr != TCPOPT_TIMESTAMP || *(ptr+1) != TCPOLEN_TIMESTAMP) + return -1; + + /* Ensure timestamp value increases monotonically */ + if (l_lro) + if (l_lro->cur_tsval > *((u32 *)(ptr+2))) + return -1; + + /* timestamp echo reply should be non-zero */ + if (*((u32 *)(ptr+6)) == 0) + return -1; + } + + return 0; +} + +static int +s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, lro_t **lro, + RxD_t *rxdp, nic_t *sp) +{ + struct iphdr *ip; + struct tcphdr *tcph; + int ret = 0, i; + + if (!(ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp, + rxdp))) { + DBG_PRINT(INFO_DBG,"IP Saddr: %x Daddr: %x\n", + ip->saddr, ip->daddr); + } else { + return ret; + } + + tcph = (struct tcphdr *)*tcp; + *tcp_len = get_l4_pyld_length(ip, tcph); + for (i=0; ilro0_n[i]; + if (l_lro->in_use) { + if (check_for_socket_match(l_lro, ip, tcph)) + continue; + /* Sock pair matched */ + *lro = l_lro; + + if ((*lro)->tcp_next_seq != ntohl(tcph->seq)) { + DBG_PRINT(INFO_DBG, "%s:Out of order. expected " + "0x%x, actual 0x%x\n", __FUNCTION__, + (*lro)->tcp_next_seq, + ntohl(tcph->seq)); + + sp->mac_control.stats_info-> + sw_stat.outof_sequence_pkts++; + ret = 2; + break; + } + + if (!verify_l3_l4_lro_capable(l_lro, ip, tcph,*tcp_len)) + ret = 1; /* Aggregate */ + else + ret = 2; /* Flush both */ + break; + } + } + + if (ret == 0) { + /* Before searching for available LRO objects, + * check if the pkt is L3/L4 aggregatable. If not + * don't create new LRO session. Just send this + * packet up. + */ + if (verify_l3_l4_lro_capable(NULL, ip, tcph, *tcp_len)) { + return 5; + } + + for (i=0; ilro0_n[i]; + if (!(l_lro->in_use)) { + *lro = l_lro; + ret = 3; /* Begin anew */ + break; + } + } + } + + if (ret == 0) { /* sessions exceeded */ + DBG_PRINT(INFO_DBG,"%s:All LRO sessions already in use\n", + __FUNCTION__); + *lro = NULL; + return ret; + } + + switch (ret) { + case 3: + initiate_new_session(*lro, buffer, ip, tcph, *tcp_len); + break; + case 2: + update_L3L4_header(sp, *lro); + break; + case 1: + aggregate_new_rx(*lro, ip, tcph, *tcp_len); + if ((*lro)->sg_num == sp->lro_max_aggr_per_sess) { + update_L3L4_header(sp, *lro); + ret = 4; /* Flush the LRO */ + } + break; + default: + DBG_PRINT(ERR_DBG,"%s:Dont know, can't say!!\n", + __FUNCTION__); + break; + } + + return ret; +} + +static void clear_lro_session(lro_t *lro) +{ + static u16 lro_struct_size = sizeof(lro_t); + + memset(lro, 0, lro_struct_size); +} + +static void queue_rx_frame(struct sk_buff *skb) +{ + struct net_device *dev = skb->dev; + + skb->protocol = eth_type_trans(skb, dev); +#ifdef CONFIG_S2IO_NAPI + netif_receive_skb(skb); +#else + netif_rx(skb); +#endif +} + +static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, + u32 tcp_len) +{ + struct sk_buff *tmp, *first = lro->parent; + + first->len += tcp_len; + first->data_len = lro->frags_len; + skb_pull(skb, (skb->len - tcp_len)); + if ((tmp = skb_shinfo(first)->frag_list)) { + while (tmp->next) + tmp = tmp->next; + tmp->next = skb; + } + else + skb_shinfo(first)->frag_list = skb; + sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++; + return; +} diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 852a6a899d07..65cc59ac71f0 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -78,6 +78,13 @@ int debug_level = ERR_DBG; /* Default level. */ typedef struct { unsigned long long single_ecc_errs; unsigned long long double_ecc_errs; + /* LRO statistics */ + unsigned long long clubbed_frms_cnt; + unsigned long long sending_both; + unsigned long long outof_sequence_pkts; + unsigned long long flush_max_pkts; + unsigned long long sum_avg_pkts_aggregated; + unsigned long long num_aggregations; } swStat_t; /* The statistics block of Xena */ @@ -680,6 +687,24 @@ struct msix_info_st { u64 data; }; +/* Data structure to represent a LRO session */ +typedef struct lro { + struct sk_buff *parent; + u8 *l2h; + struct iphdr *iph; + struct tcphdr *tcph; + u32 tcp_next_seq; + u32 tcp_ack; + int total_len; + int frags_len; + int sg_num; + int in_use; + u16 window; + u32 cur_tsval; + u32 cur_tsecr; + u8 saw_ts; +}lro_t; + /* Structure representing one instance of the NIC */ struct s2io_nic { int rxd_mode; @@ -784,6 +809,13 @@ struct s2io_nic { #define XFRAME_II_DEVICE 2 u8 device_type; +#define MAX_LRO_SESSIONS 32 + lro_t lro0_n[MAX_LRO_SESSIONS]; + unsigned long clubbed_frms_cnt; + unsigned long sending_both; + u8 lro; + u16 lro_max_aggr_per_sess; + #define INTA 0 #define MSI 1 #define MSI_X 2 @@ -940,4 +972,10 @@ static void s2io_card_down(nic_t *nic); static int s2io_card_up(nic_t *nic); int get_xena_rev_id(struct pci_dev *pdev); void restore_xmsi_data(nic_t *nic); + +static int s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, lro_t **lro, RxD_t *rxdp, nic_t *sp); +static void clear_lro_session(lro_t *lro); +static void queue_rx_frame(struct sk_buff *skb); +static void update_L3L4_header(nic_t *sp, lro_t *lro); +static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len); #endif /* _S2IO_H */ -- cgit v1.2.3-59-g8ed1b From ed9b5d457668392182659747a734b38e86820adb Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 27 Jan 2006 01:06:38 -0700 Subject: [PATCH] mv643xx_eth: Remove needless mp->port_mac_addr mp->port_mac_addr is just a redundant copy of dev->dev_addr, so remove it. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 18 +++++++----------- drivers/net/mv643xx_eth.h | 3 +-- 2 files changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 7ef4b0434a3f..af9bbe649fc1 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -243,8 +243,7 @@ static void mv643xx_eth_update_mac_address(struct net_device *dev) unsigned int port_num = mp->port_num; eth_port_init_mac_tables(port_num); - memcpy(mp->port_mac_addr, dev->dev_addr, 6); - eth_port_uc_addr_set(port_num, mp->port_mac_addr); + eth_port_uc_addr_set(port_num, dev->dev_addr); } /* @@ -320,7 +319,7 @@ static void mv643xx_eth_tx_timeout_task(struct net_device *dev) netif_device_detach(dev); eth_port_reset(mp->port_num); - eth_port_start(mp); + eth_port_start(dev); netif_device_attach(dev); } @@ -751,9 +750,6 @@ static int mv643xx_eth_open(struct net_device *dev) /* Stop RX Queues */ mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00); - /* Set the MAC Address */ - memcpy(mp->port_mac_addr, dev->dev_addr, 6); - eth_port_init(mp); INIT_WORK(&mp->rx_task, (void (*)(void *))mv643xx_eth_rx_task, dev); @@ -839,7 +835,7 @@ static int mv643xx_eth_open(struct net_device *dev) mv643xx_eth_rx_task(dev); /* Fill RX ring with skb's */ - eth_port_start(mp); + eth_port_start(dev); /* Interrupt Coalescing */ @@ -1706,7 +1702,6 @@ MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX"); * Prior to calling the initialization routine eth_port_init() the user * must set the following fields under mv643xx_private struct: * port_num User Ethernet port number. - * port_mac_addr[6] User defined port MAC address. * port_config User port configuration value. * port_config_extend User port config extend value. * port_sdma_config User port SDMA config value. @@ -1796,7 +1791,7 @@ static void eth_port_init(struct mv643xx_private *mp) * and ether_init_rx_desc_ring for Rx queues). * * INPUT: - * struct mv643xx_private *mp Ethernet port control struct + * dev - a pointer to the required interface * * OUTPUT: * Ethernet port is ready to receive and transmit. @@ -1804,8 +1799,9 @@ static void eth_port_init(struct mv643xx_private *mp) * RETURN: * None. */ -static void eth_port_start(struct mv643xx_private *mp) +static void eth_port_start(struct net_device *dev) { + struct mv643xx_private *mp = netdev_priv(dev); unsigned int port_num = mp->port_num; int tx_curr_desc, rx_curr_desc; @@ -1820,7 +1816,7 @@ static void eth_port_start(struct mv643xx_private *mp) (u32)((struct eth_rx_desc *)mp->rx_desc_dma + rx_curr_desc)); /* Add the assigned Ethernet address to the port's address table */ - eth_port_uc_addr_set(port_num, mp->port_mac_addr); + eth_port_uc_addr_set(port_num, dev->dev_addr); /* Assign port configuration and command. */ mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), mp->port_config); diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index f769f9b626ea..c83bcbdef4d5 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -324,7 +324,6 @@ struct mv643xx_mib_counters { struct mv643xx_private { int port_num; /* User Ethernet port number */ - u8 port_mac_addr[6]; /* User defined port MAC address.*/ u32 port_config; /* User port configuration value*/ u32 port_config_extend; /* User port config extend value*/ u32 port_sdma_config; /* User port SDMA config value */ @@ -405,7 +404,7 @@ struct mv643xx_private { /* Port operation control routines */ static void eth_port_init(struct mv643xx_private *mp); static void eth_port_reset(unsigned int eth_port_num); -static void eth_port_start(struct mv643xx_private *mp); +static void eth_port_start(struct net_device *dev); /* Port MAC address routines */ static void eth_port_uc_addr_set(unsigned int eth_port_num, -- cgit v1.2.3-59-g8ed1b From cf4086c7725dc251551243c28325d446d9b1bf06 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 27 Jan 2006 01:07:48 -0700 Subject: [PATCH] mv643xx_eth: Merge unicast and multicast address filtering code Remove duplicated code by having unicast and multicast code use a common filter table function: eth_port_set_filter_table_entry(). Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 84 +++++------------------------------------------ drivers/net/mv643xx_eth.h | 4 --- 2 files changed, 9 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index af9bbe649fc1..4d5e3b8e7578 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1730,8 +1730,7 @@ static int ethernet_phy_get(unsigned int eth_port_num); static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr); /* Ethernet Port routines */ -static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble, - int option); +static void eth_port_set_filter_table_entry(int table, unsigned char entry); /* * eth_port_init - Initialize the Ethernet port driver @@ -1860,8 +1859,9 @@ static void eth_port_start(struct net_device *dev) * char * p_addr Address to be set * * OUTPUT: - * Set MAC address low and high registers. also calls eth_port_uc_addr() - * To set the unicast table with the proper information. + * Set MAC address low and high registers. also calls + * eth_port_set_filter_table_entry() to set the unicast + * table with the proper information. * * RETURN: * N/A. @@ -1872,6 +1872,7 @@ static void eth_port_uc_addr_set(unsigned int eth_port_num, { unsigned int mac_h; unsigned int mac_l; + int table; mac_l = (p_addr[4] << 8) | (p_addr[5]); mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) | @@ -1881,9 +1882,8 @@ static void eth_port_uc_addr_set(unsigned int eth_port_num, mv_write(MV643XX_ETH_MAC_ADDR_HIGH(eth_port_num), mac_h); /* Accept frames of this address */ - eth_port_uc_addr(eth_port_num, p_addr[5], ACCEPT_MAC_ADDR); - - return; + table = MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE(eth_port_num); + eth_port_set_filter_table_entry(table, p_addr[5] & 0x0f); } /* @@ -1921,72 +1921,6 @@ static void eth_port_uc_addr_get(struct net_device *dev, unsigned char *p_addr) p_addr[5] = mac_l & 0xff; } -/* - * eth_port_uc_addr - This function Set the port unicast address table - * - * DESCRIPTION: - * This function locates the proper entry in the Unicast table for the - * specified MAC nibble and sets its properties according to function - * parameters. - * - * INPUT: - * unsigned int eth_port_num Port number. - * unsigned char uc_nibble Unicast MAC Address last nibble. - * int option 0 = Add, 1 = remove address. - * - * OUTPUT: - * This function add/removes MAC addresses from the port unicast address - * table. - * - * RETURN: - * true is output succeeded. - * false if option parameter is invalid. - * - */ -static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble, - int option) -{ - unsigned int unicast_reg; - unsigned int tbl_offset; - unsigned int reg_offset; - - /* Locate the Unicast table entry */ - uc_nibble = (0xf & uc_nibble); - tbl_offset = (uc_nibble / 4) * 4; /* Register offset from unicast table base */ - reg_offset = uc_nibble % 4; /* Entry offset within the above register */ - - switch (option) { - case REJECT_MAC_ADDR: - /* Clear accepts frame bit at given unicast DA table entry */ - unicast_reg = mv_read((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE - (eth_port_num) + tbl_offset)); - - unicast_reg &= (0x0E << (8 * reg_offset)); - - mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE - (eth_port_num) + tbl_offset), unicast_reg); - break; - - case ACCEPT_MAC_ADDR: - /* Set accepts frame bit at unicast DA filter table entry */ - unicast_reg = - mv_read((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE - (eth_port_num) + tbl_offset)); - - unicast_reg |= (0x01 << (8 * reg_offset)); - - mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE - (eth_port_num) + tbl_offset), unicast_reg); - - break; - - default: - return 0; - } - - return 1; -} - /* * The entries in each table are indexed by a hash of a packet's MAC * address. One bit in each entry determines whether the packet is @@ -2199,8 +2133,8 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num) /* Clear DA filter unicast table (Ex_dFUT) */ for (table_index = 0; table_index <= 0xC; table_index += 4) - mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE - (eth_port_num) + table_index), 0); + mv_write(MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE + (eth_port_num) + table_index, 0); for (table_index = 0; table_index <= 0xFC; table_index += 4) { /* Clear DA filter special multicast table (Ex_dFSMT) */ diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index c83bcbdef4d5..ef83906f88e4 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -89,10 +89,6 @@ * */ -/* MAC accepet/reject macros */ -#define ACCEPT_MAC_ADDR 0 -#define REJECT_MAC_ADDR 1 - /* Buffer offset from buffer pointer */ #define RX_BUF_OFFSET 0x2 -- cgit v1.2.3-59-g8ed1b From f98e36f1f7903a319f7f87f96490e88f691ea106 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 27 Jan 2006 01:09:18 -0700 Subject: [PATCH] mv643xx_eth: Rename mp->tx_ring_skbs to mp->tx_desc_count tx_ring_skbs is actually a count of tx descriptors currently in use. Since there may be multiple descriptors per skb, it is not the same as the number of skbs in the ring. Also change rx_ring_skbs to rx_desc_count to be consistent. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 51 ++++++++++++++++++++++++----------------------- drivers/net/mv643xx_eth.h | 8 ++++---- 2 files changed, 30 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 4d5e3b8e7578..73c766b3cd11 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -169,11 +169,11 @@ static void mv643xx_eth_rx_task(void *data) if (test_and_set_bit(0, &mp->rx_task_busy)) panic("%s: Error in test_set_bit / clear_bit", dev->name); - while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) { + while (mp->rx_desc_count < (mp->rx_ring_size - 5)) { skb = dev_alloc_skb(RX_SKB_SIZE + DMA_ALIGN); if (!skb) break; - mp->rx_ring_skbs++; + mp->rx_desc_count++; unaligned = (u32)skb->data & (DMA_ALIGN - 1); if (unaligned) skb_reserve(skb, DMA_ALIGN - unaligned); @@ -194,7 +194,7 @@ static void mv643xx_eth_rx_task(void *data) * If RX ring is empty of SKB, set a timer to try allocating * again in a later time . */ - if ((mp->rx_ring_skbs == 0) && (mp->rx_timer_flag == 0)) { + if ((mp->rx_desc_count == 0) && (mp->rx_timer_flag == 0)) { printk(KERN_INFO "%s: Rx ring is empty\n", dev->name); /* After 100mSec */ mp->timeout.expires = jiffies + (HZ / 10); @@ -394,7 +394,7 @@ static int mv643xx_eth_receive_queue(struct net_device *dev) #else while (eth_port_receive(mp, &pkt_info) == ETH_OK) { #endif - mp->rx_ring_skbs--; + mp->rx_desc_count--; received_packets++; /* Update statistics. Note byte count includes 4 byte CRC count */ @@ -494,7 +494,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, /* UDP change : We may need this */ if ((eth_int_cause_ext & 0x0000ffff) && (mv643xx_eth_free_tx_queue(dev, eth_int_cause_ext) == 0) && - (mp->tx_ring_size > mp->tx_ring_skbs + MAX_DESCS_PER_SKB)) + (mp->tx_ring_size > mp->tx_desc_count + MAX_DESCS_PER_SKB)) netif_wake_queue(dev); #ifdef MV643XX_NAPI } else { @@ -778,7 +778,7 @@ static int mv643xx_eth_open(struct net_device *dev) } /* Allocate TX ring */ - mp->tx_ring_skbs = 0; + mp->tx_desc_count = 0; size = mp->tx_ring_size * sizeof(struct eth_tx_desc); mp->tx_desc_area_size = size; @@ -803,7 +803,7 @@ static int mv643xx_eth_open(struct net_device *dev) ether_init_tx_desc_ring(mp); /* Allocate RX ring */ - mp->rx_ring_skbs = 0; + mp->rx_desc_count = 0; size = mp->rx_ring_size * sizeof(struct eth_rx_desc); mp->rx_desc_area_size = size; @@ -880,17 +880,17 @@ static void mv643xx_eth_free_tx_rings(struct net_device *dev) mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00); /* Free outstanding skb's on TX rings */ - for (curr = 0; mp->tx_ring_skbs && curr < mp->tx_ring_size; curr++) { + for (curr = 0; mp->tx_desc_count && curr < mp->tx_ring_size; curr++) { skb = mp->tx_skb[curr]; if (skb) { - mp->tx_ring_skbs -= skb_shinfo(skb)->nr_frags; + mp->tx_desc_count -= skb_shinfo(skb)->nr_frags; dev_kfree_skb(skb); - mp->tx_ring_skbs--; + mp->tx_desc_count--; } } - if (mp->tx_ring_skbs) + if (mp->tx_desc_count) printk("%s: Error on Tx descriptor free - could not free %d" - " descriptors\n", dev->name, mp->tx_ring_skbs); + " descriptors\n", dev->name, mp->tx_desc_count); /* Free TX ring */ if (mp->tx_sram_size) @@ -910,18 +910,18 @@ static void mv643xx_eth_free_rx_rings(struct net_device *dev) mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00); /* Free preallocated skb's on RX rings */ - for (curr = 0; mp->rx_ring_skbs && curr < mp->rx_ring_size; curr++) { + for (curr = 0; mp->rx_desc_count && curr < mp->rx_ring_size; curr++) { if (mp->rx_skb[curr]) { dev_kfree_skb(mp->rx_skb[curr]); - mp->rx_ring_skbs--; + mp->rx_desc_count--; } } - if (mp->rx_ring_skbs) + if (mp->rx_desc_count) printk(KERN_ERR "%s: Error in freeing Rx Ring. %d skb's still" " stuck in RX Ring - ignoring them\n", dev->name, - mp->rx_ring_skbs); + mp->rx_desc_count); /* Free RX ring */ if (mp->rx_sram_size) iounmap(mp->p_rx_desc_area); @@ -991,7 +991,8 @@ static void mv643xx_tx(struct net_device *dev) } if (netif_queue_stopped(dev) && - mp->tx_ring_size > mp->tx_ring_skbs + MAX_DESCS_PER_SKB) + mp->tx_ring_size > + mp->tx_desc_count + MAX_DESCS_PER_SKB) netif_wake_queue(dev); } @@ -1083,7 +1084,7 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) } /* This is a hard error, log it. */ - if ((mp->tx_ring_size - mp->tx_ring_skbs) <= + if ((mp->tx_ring_size - mp->tx_desc_count) <= (skb_shinfo(skb)->nr_frags + 1)) { netif_stop_queue(dev); printk(KERN_ERR @@ -1260,7 +1261,7 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Check if TX queue can handle another skb. If not, then * signal higher layers to stop requesting TX */ - if (mp->tx_ring_size <= (mp->tx_ring_skbs + MAX_DESCS_PER_SKB)) + if (mp->tx_ring_size <= (mp->tx_desc_count + MAX_DESCS_PER_SKB)) /* * Stop getting skb's from upper layers. * Getting skb's from upper layers will be enabled again after @@ -2563,8 +2564,8 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, return ETH_ERROR; } - mp->tx_ring_skbs++; - BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); + mp->tx_desc_count++; + BUG_ON(mp->tx_desc_count > mp->tx_ring_size); /* Get the Tx Desc ring indexes */ tx_desc_curr = mp->tx_curr_desc_q; @@ -2632,8 +2633,8 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, if (mp->tx_resource_err) return ETH_QUEUE_FULL; - mp->tx_ring_skbs++; - BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); + mp->tx_desc_count++; + BUG_ON(mp->tx_desc_count > mp->tx_ring_size); /* Get the Tx Desc ring indexes */ tx_desc_curr = mp->tx_curr_desc_q; @@ -2747,8 +2748,8 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp, /* Any Tx return cancels the Tx resource error status */ mp->tx_resource_err = 0; - BUG_ON(mp->tx_ring_skbs == 0); - mp->tx_ring_skbs--; + BUG_ON(mp->tx_desc_count == 0); + mp->tx_desc_count--; out: spin_unlock_irqrestore(&mp->lock, flags); diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index ef83906f88e4..345f970d122c 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -371,12 +371,12 @@ struct mv643xx_private { spinlock_t lock; /* Size of Tx Ring per queue */ unsigned int tx_ring_size; - /* Ammont of SKBs outstanding on Tx queue */ - unsigned int tx_ring_skbs; + /* Number of tx descriptors in use */ + unsigned int tx_desc_count; /* Size of Rx Ring per queue */ unsigned int rx_ring_size; - /* Ammount of SKBs allocated to Rx Ring per queue */ - unsigned int rx_ring_skbs; + /* Number of rx descriptors in use */ + unsigned int rx_desc_count; /* * rx_task used to fill RX ring out of bottom half context -- cgit v1.2.3-59-g8ed1b From 9f8dd319459bb5ab9efcc1c345bed7895cc41768 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 27 Jan 2006 01:10:47 -0700 Subject: [PATCH] mv643xx_eth: Make port queue enable/disable code consistent Add and use the following functions: mv643xx_eth_port_enable_tx() mv643xx_eth_port_enable_rx() mv643xx_eth_port_disable_tx() mv643xx_eth_port_disable_rx() so that ports are enabled/disabled consistently. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 133 +++++++++++++++++++++++++++------------------- 1 file changed, 79 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 73c766b3cd11..2daa9b97d2c0 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -83,6 +83,12 @@ static int eth_port_link_is_up(unsigned int eth_port_num); static void eth_port_uc_addr_get(struct net_device *dev, unsigned char *MacAddr); static void eth_port_set_multicast_list(struct net_device *); +static void mv643xx_eth_port_enable_tx(unsigned int port_num, + unsigned int channels); +static void mv643xx_eth_port_enable_rx(unsigned int port_num, + unsigned int channels); +static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num); +static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num); static int mv643xx_eth_open(struct net_device *); static int mv643xx_eth_stop(struct net_device *); static int mv643xx_eth_change_mtu(struct net_device *, int); @@ -535,8 +541,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, netif_carrier_on(dev); netif_wake_queue(dev); /* Start TX queue */ - mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG - (port_num), 1); + mv643xx_eth_port_enable_tx(port_num, mp->port_tx_queue_command); } else { netif_carrier_off(dev); netif_stop_queue(dev); @@ -668,8 +673,8 @@ static void ether_init_rx_desc_ring(struct mv643xx_private *mp) mp->rx_desc_area_size = rx_desc_num * sizeof(struct eth_rx_desc); - /* Add the queue to the list of RX queues of this port */ - mp->port_rx_queue_command |= 1; + /* Enable queue 0 for this port */ + mp->port_rx_queue_command = 1; } /* @@ -715,8 +720,8 @@ static void ether_init_tx_desc_ring(struct mv643xx_private *mp) mp->tx_desc_area_size = tx_desc_num * sizeof(struct eth_tx_desc); - /* Add the queue to the list of Tx queues of this port */ - mp->port_tx_queue_command |= 1; + /* Enable queue 0 for this port */ + mp->port_tx_queue_command = 1; } /* @@ -747,9 +752,6 @@ static int mv643xx_eth_open(struct net_device *dev) return -EAGAIN; } - /* Stop RX Queues */ - mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00); - eth_port_init(mp); INIT_WORK(&mp->rx_task, (void (*)(void *))mv643xx_eth_rx_task, dev); @@ -877,7 +879,7 @@ static void mv643xx_eth_free_tx_rings(struct net_device *dev) struct sk_buff *skb; /* Stop Tx Queues */ - mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00); + mv643xx_eth_port_disable_tx(port_num); /* Free outstanding skb's on TX rings */ for (curr = 0; mp->tx_desc_count && curr < mp->tx_ring_size; curr++) { @@ -907,7 +909,7 @@ static void mv643xx_eth_free_rx_rings(struct net_device *dev) int curr; /* Stop RX Queues */ - mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00); + mv643xx_eth_port_disable_rx(port_num); /* Free preallocated skb's on RX rings */ for (curr = 0; mp->rx_desc_count && curr < mp->rx_ring_size; curr++) { @@ -1719,13 +1721,6 @@ MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX"); * return_info Tx/Rx user resource return information. */ -/* defines */ -/* SDMA command macros */ -#define ETH_ENABLE_TX_QUEUE(eth_port) \ - mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), 1) - -/* locals */ - /* PHY routines */ static int ethernet_phy_get(unsigned int eth_port_num); static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr); @@ -1759,9 +1754,6 @@ static void eth_port_set_filter_table_entry(int table, unsigned char entry); */ static void eth_port_init(struct mv643xx_private *mp) { - mp->port_rx_queue_command = 0; - mp->port_tx_queue_command = 0; - mp->rx_resource_err = 0; mp->tx_resource_err = 0; @@ -1842,8 +1834,7 @@ static void eth_port_start(struct net_device *dev) mp->port_sdma_config); /* Enable port Rx. */ - mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), - mp->port_rx_queue_command); + mv643xx_eth_port_enable_rx(port_num, mp->port_rx_queue_command); /* Disable port bandwidth limits by clearing MTU register */ mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0); @@ -2320,6 +2311,67 @@ static void ethernet_phy_reset(unsigned int eth_port_num) eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data); } +static void mv643xx_eth_port_enable_tx(unsigned int port_num, + unsigned int channels) +{ + mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), channels); +} + +static void mv643xx_eth_port_enable_rx(unsigned int port_num, + unsigned int channels) +{ + mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), channels); +} + +static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num) +{ + u32 channels; + + /* Stop Tx port activity. Check port Tx activity. */ + channels = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num)) + & 0xFF; + if (channels) { + /* Issue stop command for active channels only */ + mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), + (channels << 8)); + + /* Wait for all Tx activity to terminate. */ + /* Check port cause register that all Tx queues are stopped */ + while (mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num)) + & 0xFF) + udelay(PHY_WAIT_MICRO_SECONDS); + + /* Wait for Tx FIFO to empty */ + while (mv_read(MV643XX_ETH_PORT_STATUS_REG(port_num)) & + ETH_PORT_TX_FIFO_EMPTY) + udelay(PHY_WAIT_MICRO_SECONDS); + } + + return channels; +} + +static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num) +{ + u32 channels; + + /* Stop Rx port activity. Check port Rx activity. */ + channels = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num) + & 0xFF); + if (channels) { + /* Issue stop command for active channels only */ + mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), + (channels << 8)); + + /* Wait for all Rx activity to terminate. */ + /* Check port cause register that all Rx queues are stopped */ + while (mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num)) + & 0xFF) + udelay(PHY_WAIT_MICRO_SECONDS); + } + + return channels; +} + /* * eth_port_reset - Reset Ethernet port * @@ -2342,35 +2394,8 @@ static void eth_port_reset(unsigned int port_num) { unsigned int reg_data; - /* Stop Tx port activity. Check port Tx activity. */ - reg_data = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num)); - - if (reg_data & 0xFF) { - /* Issue stop command for active channels only */ - mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), - (reg_data << 8)); - - /* Wait for all Tx activity to terminate. */ - /* Check port cause register that all Tx queues are stopped */ - while (mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num)) - & 0xFF) - udelay(10); - } - - /* Stop Rx port activity. Check port Rx activity. */ - reg_data = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num)); - - if (reg_data & 0xFF) { - /* Issue stop command for active channels only */ - mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), - (reg_data << 8)); - - /* Wait for all Rx activity to terminate. */ - /* Check port cause register that all Rx queues are stopped */ - while (mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num)) - & 0xFF) - udelay(10); - } + mv643xx_eth_port_disable_tx(port_num); + mv643xx_eth_port_disable_rx(port_num); /* Clear all MIB counters */ eth_clear_mib_counters(port_num); @@ -2599,7 +2624,7 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, first_descriptor->cmd_sts = mp->tx_first_command; wmb(); - ETH_ENABLE_TX_QUEUE(mp->port_num); + mv643xx_eth_port_enable_tx(mp->port_num, mp->port_tx_queue_command); /* * Finish Tx packet. Update first desc in case of Tx resource @@ -2652,7 +2677,7 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT; wmb(); - ETH_ENABLE_TX_QUEUE(mp->port_num); + mv643xx_eth_port_enable_tx(mp->port_num, mp->port_tx_queue_command); /* Finish Tx packet. Update first desc in case of Tx resource error */ tx_desc_curr = (tx_desc_curr + 1) % mp->tx_ring_size; -- cgit v1.2.3-59-g8ed1b From c28a4f8947f1b08996502967e348dc88363749a7 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Fri, 27 Jan 2006 01:13:15 -0700 Subject: [PATCH] mv643xx_eth: use MII library for PHY management Modify link up/down handling to use the functions from the MII library. Note that I track link state using the MII PHY registers rather than the mv643xx chip's link state registers because I think it's cleaner to use the MII library code rather than writing local driver support code. It is also useful to make the actual MII registers available to the user with maskable kernel printk messages so the MII registers are being read anyway Signed-off-by: James Chapman Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 64 ++++++++++++++++++++++++++++++----------------- drivers/net/mv643xx_eth.h | 2 ++ 2 files changed, 43 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 2daa9b97d2c0..bca7257c707a 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -79,7 +79,6 @@ #define PHY_WAIT_MICRO_SECONDS 10 /* Static function declarations */ -static int eth_port_link_is_up(unsigned int eth_port_num); static void eth_port_uc_addr_get(struct net_device *dev, unsigned char *MacAddr); static void eth_port_set_multicast_list(struct net_device *); @@ -97,8 +96,11 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num); #ifdef MV643XX_NAPI static int mv643xx_poll(struct net_device *dev, int *budget); #endif +static int ethernet_phy_get(unsigned int eth_port_num); static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr); static int ethernet_phy_detect(unsigned int eth_port_num); +static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location); +static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val); static struct ethtool_ops mv643xx_ethtool_ops; static char mv643xx_driver_name[] = "mv643xx_eth"; @@ -537,14 +539,17 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, } /* PHY status changed */ if (eth_int_cause_ext & (BIT16 | BIT20)) { - if (eth_port_link_is_up(port_num)) { - netif_carrier_on(dev); - netif_wake_queue(dev); - /* Start TX queue */ - mv643xx_eth_port_enable_tx(port_num, mp->port_tx_queue_command); - } else { - netif_carrier_off(dev); + if (mii_link_ok(&mp->mii)) { + if (!netif_carrier_ok(dev)) { + netif_carrier_on(dev); + netif_wake_queue(dev); + /* Start TX queue */ + mv643xx_eth_port_enable_tx(port_num, + mp->port_tx_queue_command); + } + } else if (netif_carrier_ok(dev)) { netif_stop_queue(dev); + netif_carrier_off(dev); } } @@ -1434,6 +1439,14 @@ static int mv643xx_eth_probe(struct platform_device *pdev) } } + /* Hook up MII support for ethtool */ + mp->mii.dev = dev; + mp->mii.mdio_read = mv643xx_mdio_read; + mp->mii.mdio_write = mv643xx_mdio_write; + mp->mii.phy_id = ethernet_phy_get(port_num); + mp->mii.phy_id_mask = 0x3f; + mp->mii.reg_num_mask = 0x1f; + err = ethernet_phy_detect(port_num); if (err) { pr_debug("MV643xx ethernet port %d: " @@ -1442,6 +1455,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev) return err; } + mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii); + err = register_netdev(dev); if (err) goto out; @@ -2416,21 +2431,6 @@ static int eth_port_autoneg_supported(unsigned int eth_port_num) return phy_reg_data0 & 0x1000; } -static int eth_port_link_is_up(unsigned int eth_port_num) -{ - unsigned int phy_reg_data1; - - eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data1); - - if (eth_port_autoneg_supported(eth_port_num)) { - if (phy_reg_data1 & 0x20) /* auto-neg complete */ - return 1; - } else if (phy_reg_data1 & 0x4) /* link up */ - return 1; - - return 0; -} - /* * eth_port_read_smi_reg - Read PHY registers * @@ -2535,6 +2535,24 @@ out: spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags); } +/* + * Wrappers for MII support library. + */ +static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location) +{ + int val; + struct mv643xx_private *mp = netdev_priv(dev); + + eth_port_read_smi_reg(mp->port_num, location, &val); + return val; +} + +static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val) +{ + struct mv643xx_private *mp = netdev_priv(dev); + eth_port_write_smi_reg(mp->port_num, location, val); +} + /* * eth_port_send - Send an Ethernet packet * diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index 345f970d122c..f2e5da79dde8 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -393,6 +394,7 @@ struct mv643xx_private { u32 rx_int_coal; u32 tx_int_coal; + struct mii_if_info mii; }; /* ethernet.h API list */ -- cgit v1.2.3-59-g8ed1b From d0412d967032b9e147bcbacc9ff0c0342636cf2d Mon Sep 17 00:00:00 2001 From: James Chapman Date: Fri, 27 Jan 2006 01:15:30 -0700 Subject: [PATCH] mv643xx_eth: use MII library for ethtool functions Use the common ethtool support functions of the MII library. Add generic MII ioctl handler. Add PHY parameter speed/duplex/negotiation initialization and modification. Signed-off-by: James Chapman Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 351 +++++++++++++++++++++++++++------------------- include/linux/mv643xx.h | 3 + 2 files changed, 213 insertions(+), 141 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index bca7257c707a..ff2b613a7436 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -101,6 +101,7 @@ static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr); static int ethernet_phy_detect(unsigned int eth_port_num); static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location); static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val); +static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static struct ethtool_ops mv643xx_ethtool_ops; static char mv643xx_driver_name[] = "mv643xx_eth"; @@ -457,6 +458,56 @@ static int mv643xx_eth_receive_queue(struct net_device *dev) return received_packets; } +/* Set the mv643xx port configuration register for the speed/duplex mode. */ +static void mv643xx_eth_update_pscr(struct net_device *dev, + struct ethtool_cmd *ecmd) +{ + struct mv643xx_private *mp = netdev_priv(dev); + int port_num = mp->port_num; + u32 o_pscr, n_pscr; + unsigned int channels; + + o_pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); + n_pscr = o_pscr; + + /* clear speed, duplex and rx buffer size fields */ + n_pscr &= ~(MV643XX_ETH_SET_MII_SPEED_TO_100 | + MV643XX_ETH_SET_GMII_SPEED_TO_1000 | + MV643XX_ETH_SET_FULL_DUPLEX_MODE | + MV643XX_ETH_MAX_RX_PACKET_MASK); + + if (ecmd->duplex == DUPLEX_FULL) + n_pscr |= MV643XX_ETH_SET_FULL_DUPLEX_MODE; + + if (ecmd->speed == SPEED_1000) + n_pscr |= MV643XX_ETH_SET_GMII_SPEED_TO_1000 | + MV643XX_ETH_MAX_RX_PACKET_9700BYTE; + else { + if (ecmd->speed == SPEED_100) + n_pscr |= MV643XX_ETH_SET_MII_SPEED_TO_100; + n_pscr |= MV643XX_ETH_MAX_RX_PACKET_1522BYTE; + } + + if (n_pscr != o_pscr) { + if ((o_pscr & MV643XX_ETH_SERIAL_PORT_ENABLE) == 0) + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), + n_pscr); + else { + channels = mv643xx_eth_port_disable_tx(port_num); + + o_pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), + o_pscr); + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), + n_pscr); + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), + n_pscr); + if (channels) + mv643xx_eth_port_enable_tx(port_num, channels); + } + } +} + /* * mv643xx_eth_int_handler * @@ -539,13 +590,19 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, } /* PHY status changed */ if (eth_int_cause_ext & (BIT16 | BIT20)) { + struct ethtool_cmd cmd; + if (mii_link_ok(&mp->mii)) { + mii_ethtool_gset(&mp->mii, &cmd); + mv643xx_eth_update_pscr(dev, &cmd); if (!netif_carrier_ok(dev)) { netif_carrier_on(dev); - netif_wake_queue(dev); - /* Start TX queue */ - mv643xx_eth_port_enable_tx(port_num, - mp->port_tx_queue_command); + if (mp->tx_ring_size > mp->tx_desc_count + + MAX_DESCS_PER_SKB) { + netif_wake_queue(dev); + /* Start TX queue */ + mv643xx_eth_port_enable_tx(port_num, mp->port_tx_queue_command); + } } } else if (netif_carrier_ok(dev)) { netif_stop_queue(dev); @@ -729,6 +786,34 @@ static void ether_init_tx_desc_ring(struct mv643xx_private *mp) mp->port_tx_queue_command = 1; } +static int mv643xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct mv643xx_private *mp = netdev_priv(dev); + int err; + + spin_lock_irq(&mp->lock); + err = mii_ethtool_sset(&mp->mii, cmd); + spin_unlock_irq(&mp->lock); + + return err; +} + +static int mv643xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct mv643xx_private *mp = netdev_priv(dev); + int err; + + spin_lock_irq(&mp->lock); + err = mii_ethtool_gset(&mp->mii, cmd); + spin_unlock_irq(&mp->lock); + + /* The PHY may support 1000baseT_Half, but the mv643xx does not */ + cmd->supported &= ~SUPPORTED_1000baseT_Half; + cmd->advertising &= ~ADVERTISED_1000baseT_Half; + + return err; +} + /* * mv643xx_eth_open * @@ -842,6 +927,10 @@ static int mv643xx_eth_open(struct net_device *dev) mv643xx_eth_rx_task(dev); /* Fill RX ring with skb's */ + /* Clear any pending ethernet port interrupts */ + mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0); + mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); + eth_port_start(dev); /* Interrupt Coalescing */ @@ -854,16 +943,13 @@ static int mv643xx_eth_open(struct net_device *dev) mp->tx_int_coal = eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL); - /* Clear any pending ethernet port interrupts */ - mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0); - mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); - /* Unmask phy and link status changes interrupts */ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), INT_UNMASK_ALL_EXT); /* Unmask RX buffer and TX end interrupt */ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL); + return 0; out_free_tx_skb: @@ -1318,6 +1404,35 @@ static void mv643xx_netpoll(struct net_device *netdev) } #endif +static void mv643xx_init_ethtool_cmd(struct net_device *dev, int phy_address, + int speed, int duplex, + struct ethtool_cmd *cmd) +{ + struct mv643xx_private *mp = netdev_priv(dev); + + memset(cmd, 0, sizeof(*cmd)); + + cmd->port = PORT_MII; + cmd->transceiver = XCVR_INTERNAL; + cmd->phy_address = phy_address; + + if (speed == 0) { + cmd->autoneg = AUTONEG_ENABLE; + /* mii lib checks, but doesn't use speed on AUTONEG_ENABLE */ + cmd->speed = SPEED_100; + cmd->advertising = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full; + if (mp->mii.supports_gmii) + cmd->advertising |= ADVERTISED_1000baseT_Full; + } else { + cmd->autoneg = AUTONEG_DISABLE; + cmd->speed = speed; + cmd->duplex = duplex; + } +} + /*/ * mv643xx_eth_probe * @@ -1338,6 +1453,10 @@ static int mv643xx_eth_probe(struct platform_device *pdev) u8 *p; struct resource *res; int err; + struct ethtool_cmd cmd; + u32 pscr; + int duplex; + int speed; dev = alloc_etherdev(sizeof(struct mv643xx_private)); if (!dev) @@ -1375,6 +1494,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) dev->tx_queue_len = mp->tx_ring_size; dev->base_addr = 0; dev->change_mtu = mv643xx_eth_change_mtu; + dev->do_ioctl = mv643xx_eth_do_ioctl; SET_ETHTOOL_OPS(dev, &mv643xx_ethtool_ops); #ifdef MV643XX_CHECKSUM_OFFLOAD_TX @@ -1452,10 +1572,35 @@ static int mv643xx_eth_probe(struct platform_device *pdev) pr_debug("MV643xx ethernet port %d: " "No PHY detected at addr %d\n", port_num, ethernet_phy_get(port_num)); - return err; + goto out; } + pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); + pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); + pscr = mp->port_serial_control; + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); + + if (!(pscr & MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX) && + !(pscr & MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII)) + speed = 0; + else if (pscr & MV643XX_ETH_PORT_STATUS_GMII_1000) + speed = SPEED_1000; + else if (pscr & MV643XX_ETH_PORT_STATUS_MII_100) + speed = SPEED_100; + else + speed = SPEED_10; + + if (pscr & MV643XX_ETH_PORT_STATUS_FULL_DUPLEX) + duplex = DUPLEX_FULL; + else + duplex = DUPLEX_HALF; + + ethernet_phy_reset(mp->port_num); mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii); + mv643xx_init_ethtool_cmd(dev, mp->mii.phy_id, speed, duplex, &cmd); + mv643xx_eth_update_pscr(dev, &cmd); + mv643xx_set_settings(dev, &cmd); err = register_netdev(dev); if (err) @@ -1775,8 +1920,6 @@ static void eth_port_init(struct mv643xx_private *mp) eth_port_reset(mp->port_num); eth_port_init_mac_tables(mp->port_num); - - ethernet_phy_reset(mp->port_num); } /* @@ -1811,6 +1954,8 @@ static void eth_port_start(struct net_device *dev) struct mv643xx_private *mp = netdev_priv(dev); unsigned int port_num = mp->port_num; int tx_curr_desc, rx_curr_desc; + u32 pscr; + struct ethtool_cmd ethtool_cmd; /* Assignment of Tx CTRP of given queue */ tx_curr_desc = mp->tx_curr_desc_q; @@ -1828,31 +1973,35 @@ static void eth_port_start(struct net_device *dev) /* Assign port configuration and command. */ mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), mp->port_config); - mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num), - mp->port_config_extend); + pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); + pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); + pscr &= ~MV643XX_ETH_FORCE_LINK_PASS; + pscr |= MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | + MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII | + MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX | + MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL | + MV643XX_ETH_SERIAL_PORT_CONTROL_RESERVED; - /* Increase the Rx side buffer size if supporting GigE */ - if (mp->port_serial_control & MV643XX_ETH_SET_GMII_SPEED_TO_1000) - mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), - (mp->port_serial_control & 0xfff1ffff) | (0x5 << 17)); - else - mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), - mp->port_serial_control); + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); - mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), - mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)) | - MV643XX_ETH_SERIAL_PORT_ENABLE); + pscr |= MV643XX_ETH_SERIAL_PORT_ENABLE; + mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); /* Assign port SDMA configuration */ - mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num), - mp->port_sdma_config); + mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num), mp->port_sdma_config); /* Enable port Rx. */ mv643xx_eth_port_enable_rx(port_num, mp->port_rx_queue_command); /* Disable port bandwidth limits by clearing MTU register */ mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0); + + /* save phy settings across reset */ + mv643xx_get_settings(dev, ðtool_cmd); + ethernet_phy_reset(mp->port_num); + mv643xx_set_settings(dev, ðtool_cmd); } /* @@ -2324,6 +2473,12 @@ static void ethernet_phy_reset(unsigned int eth_port_num) eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data); phy_reg_data |= 0x8000; /* Set bit 15 to reset the PHY */ eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data); + + /* wait for PHY to come out of reset */ + do { + udelay(1); + eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data); + } while (phy_reg_data & 0x8000); } static void mv643xx_eth_port_enable_tx(unsigned int port_num, @@ -2417,20 +2572,13 @@ static void eth_port_reset(unsigned int port_num) /* Reset the Enable bit in the Configuration Register */ reg_data = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); - reg_data &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; + reg_data &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE | + MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL | + MV643XX_ETH_FORCE_LINK_PASS); mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data); } -static int eth_port_autoneg_supported(unsigned int eth_port_num) -{ - unsigned int phy_reg_data0; - - eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data0); - - return phy_reg_data0 & 0x1000; -} - /* * eth_port_read_smi_reg - Read PHY registers * @@ -2989,111 +3137,6 @@ static const struct mv643xx_stats mv643xx_gstrings_stats[] = { #define MV643XX_STATS_LEN \ sizeof(mv643xx_gstrings_stats) / sizeof(struct mv643xx_stats) -static int -mv643xx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -{ - struct mv643xx_private *mp = netdev->priv; - int port_num = mp->port_num; - int autoneg = eth_port_autoneg_supported(port_num); - int mode_10_bit; - int auto_duplex; - int half_duplex = 0; - int full_duplex = 0; - int auto_speed; - int speed_10 = 0; - int speed_100 = 0; - int speed_1000 = 0; - - u32 pcs = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); - u32 psr = mv_read(MV643XX_ETH_PORT_STATUS_REG(port_num)); - - mode_10_bit = psr & MV643XX_ETH_PORT_STATUS_MODE_10_BIT; - - if (mode_10_bit) { - ecmd->supported = SUPPORTED_10baseT_Half; - } else { - ecmd->supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - (autoneg ? SUPPORTED_Autoneg : 0) | - SUPPORTED_TP); - - auto_duplex = !(pcs & MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX); - auto_speed = !(pcs & MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII); - - ecmd->advertising = ADVERTISED_TP; - - if (autoneg) { - ecmd->advertising |= ADVERTISED_Autoneg; - - if (auto_duplex) { - half_duplex = 1; - full_duplex = 1; - } else { - if (pcs & MV643XX_ETH_SET_FULL_DUPLEX_MODE) - full_duplex = 1; - else - half_duplex = 1; - } - - if (auto_speed) { - speed_10 = 1; - speed_100 = 1; - speed_1000 = 1; - } else { - if (pcs & MV643XX_ETH_SET_GMII_SPEED_TO_1000) - speed_1000 = 1; - else if (pcs & MV643XX_ETH_SET_MII_SPEED_TO_100) - speed_100 = 1; - else - speed_10 = 1; - } - - if (speed_10 & half_duplex) - ecmd->advertising |= ADVERTISED_10baseT_Half; - if (speed_10 & full_duplex) - ecmd->advertising |= ADVERTISED_10baseT_Full; - if (speed_100 & half_duplex) - ecmd->advertising |= ADVERTISED_100baseT_Half; - if (speed_100 & full_duplex) - ecmd->advertising |= ADVERTISED_100baseT_Full; - if (speed_1000) - ecmd->advertising |= ADVERTISED_1000baseT_Full; - } - } - - ecmd->port = PORT_TP; - ecmd->phy_address = ethernet_phy_get(port_num); - - ecmd->transceiver = XCVR_EXTERNAL; - - if (netif_carrier_ok(netdev)) { - if (mode_10_bit) - ecmd->speed = SPEED_10; - else { - if (psr & MV643XX_ETH_PORT_STATUS_GMII_1000) - ecmd->speed = SPEED_1000; - else if (psr & MV643XX_ETH_PORT_STATUS_MII_100) - ecmd->speed = SPEED_100; - else - ecmd->speed = SPEED_10; - } - - if (psr & MV643XX_ETH_PORT_STATUS_FULL_DUPLEX) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; - } else { - ecmd->speed = -1; - ecmd->duplex = -1; - } - - ecmd->autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; - return 0; -} - static void mv643xx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { @@ -3140,15 +3183,41 @@ static void mv643xx_get_strings(struct net_device *netdev, uint32_t stringset, } } +static u32 mv643xx_eth_get_link(struct net_device *dev) +{ + struct mv643xx_private *mp = netdev_priv(dev); + + return mii_link_ok(&mp->mii); +} + +static int mv643xx_eth_nway_restart(struct net_device *dev) +{ + struct mv643xx_private *mp = netdev_priv(dev); + + return mii_nway_restart(&mp->mii); +} + +static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct mv643xx_private *mp = netdev_priv(dev); + + return generic_mii_ioctl(&mp->mii, if_mii(ifr), cmd, NULL); +} + static struct ethtool_ops mv643xx_ethtool_ops = { .get_settings = mv643xx_get_settings, + .set_settings = mv643xx_set_settings, .get_drvinfo = mv643xx_get_drvinfo, - .get_link = ethtool_op_get_link, + .get_link = mv643xx_eth_get_link, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, .get_strings = mv643xx_get_strings, .get_stats_count = mv643xx_get_stats_count, .get_ethtool_stats = mv643xx_get_ethtool_stats, + .get_strings = mv643xx_get_strings, + .get_stats_count = mv643xx_get_stats_count, + .get_ethtool_stats = mv643xx_get_ethtool_stats, + .nway_reset = mv643xx_eth_nway_restart, }; /************* End ethtool support *************************/ diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h index 0b08cd692201..7ffbeac7d2bb 100644 --- a/include/linux/mv643xx.h +++ b/include/linux/mv643xx.h @@ -1214,6 +1214,7 @@ struct mv64xxx_i2c_pdata { #define MV643XX_ETH_FORCE_BP_MODE_NO_JAM 0 #define MV643XX_ETH_FORCE_BP_MODE_JAM_TX (1<<7) #define MV643XX_ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR (1<<8) +#define MV643XX_ETH_SERIAL_PORT_CONTROL_RESERVED (1<<9) #define MV643XX_ETH_FORCE_LINK_FAIL 0 #define MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL (1<<10) #define MV643XX_ETH_RETRANSMIT_16_ATTEMPTS 0 @@ -1243,6 +1244,8 @@ struct mv64xxx_i2c_pdata { #define MV643XX_ETH_SET_MII_SPEED_TO_10 0 #define MV643XX_ETH_SET_MII_SPEED_TO_100 (1<<24) +#define MV643XX_ETH_MAX_RX_PACKET_MASK (0x7<<17) + #define MV643XX_ETH_PORT_SERIAL_CONTROL_DEFAULT_VALUE \ MV643XX_ETH_DO_NOT_FORCE_LINK_PASS | \ MV643XX_ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \ -- cgit v1.2.3-59-g8ed1b From 01999873a455fe9104e91820c72849e608239928 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 27 Jan 2006 01:18:01 -0700 Subject: [PATCH] mv643xx_eth: Clean up platform_data configuration We shouldn't expose the hardware register contents in platform_data. The only things we allow the user to configure are autoneg, speed, and duplex. Add specific platform_data fields for these values and remove the registers configs. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- arch/ppc/platforms/hdpu.c | 5 ++-- drivers/net/mv643xx_eth.c | 71 ++++++++++++++--------------------------------- drivers/net/mv643xx_eth.h | 4 --- include/linux/mv643xx.h | 24 ++++++---------- 4 files changed, 31 insertions(+), 73 deletions(-) (limited to 'drivers') diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c index 50039a204c24..f945416960e9 100644 --- a/arch/ppc/platforms/hdpu.c +++ b/arch/ppc/platforms/hdpu.c @@ -319,11 +319,10 @@ static void __init hdpu_fixup_eth_pdata(struct platform_device *pd) struct mv643xx_eth_platform_data *eth_pd; eth_pd = pd->dev.platform_data; - eth_pd->port_serial_control = - mv64x60_read(&bh, MV643XX_ETH_PORT_SERIAL_CONTROL_REG(pd->id) & ~1); - eth_pd->force_phy_addr = 1; eth_pd->phy_addr = pd->id; + eth_pd->speed = SPEED_100; + eth_pd->duplex = DUPLEX_FULL; eth_pd->tx_queue_size = 400; eth_pd->rx_queue_size = 800; } diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index ff2b613a7436..df572018595e 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -266,13 +266,14 @@ static void mv643xx_eth_update_mac_address(struct net_device *dev) static void mv643xx_eth_set_rx_mode(struct net_device *dev) { struct mv643xx_private *mp = netdev_priv(dev); + u32 config_reg; + config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num)); if (dev->flags & IFF_PROMISC) - mp->port_config |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; + config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; else - mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; - - mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config); + config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; + mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), config_reg); eth_port_set_multicast_list(dev); } @@ -1454,9 +1455,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev) struct resource *res; int err; struct ethtool_cmd cmd; - u32 pscr; - int duplex; - int speed; + int duplex = DUPLEX_HALF; + int speed = 0; /* default to auto-negotiation */ dev = alloc_etherdev(sizeof(struct mv643xx_private)); if (!dev) @@ -1515,33 +1515,17 @@ static int mv643xx_eth_probe(struct platform_device *pdev) /* set default config values */ eth_port_uc_addr_get(dev, dev->dev_addr); - mp->port_config = MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE; - mp->port_config_extend = MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE; - mp->port_sdma_config = MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE; - mp->port_serial_control = MV643XX_ETH_PORT_SERIAL_CONTROL_DEFAULT_VALUE; mp->rx_ring_size = MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE; mp->tx_ring_size = MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE; pd = pdev->dev.platform_data; if (pd) { - if (pd->mac_addr != NULL) + if (pd->mac_addr) memcpy(dev->dev_addr, pd->mac_addr, 6); if (pd->phy_addr || pd->force_phy_addr) ethernet_phy_set(port_num, pd->phy_addr); - if (pd->port_config || pd->force_port_config) - mp->port_config = pd->port_config; - - if (pd->port_config_extend || pd->force_port_config_extend) - mp->port_config_extend = pd->port_config_extend; - - if (pd->port_sdma_config || pd->force_port_sdma_config) - mp->port_sdma_config = pd->port_sdma_config; - - if (pd->port_serial_control || pd->force_port_serial_control) - mp->port_serial_control = pd->port_serial_control; - if (pd->rx_queue_size) mp->rx_ring_size = pd->rx_queue_size; @@ -1557,6 +1541,9 @@ static int mv643xx_eth_probe(struct platform_device *pdev) mp->rx_sram_size = pd->rx_sram_size; mp->rx_sram_addr = pd->rx_sram_addr; } + + duplex = pd->duplex; + speed = pd->speed; } /* Hook up MII support for ethtool */ @@ -1575,28 +1562,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) goto out; } - pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); - pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; - mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); - pscr = mp->port_serial_control; - mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); - - if (!(pscr & MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX) && - !(pscr & MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII)) - speed = 0; - else if (pscr & MV643XX_ETH_PORT_STATUS_GMII_1000) - speed = SPEED_1000; - else if (pscr & MV643XX_ETH_PORT_STATUS_MII_100) - speed = SPEED_100; - else - speed = SPEED_10; - - if (pscr & MV643XX_ETH_PORT_STATUS_FULL_DUPLEX) - duplex = DUPLEX_FULL; - else - duplex = DUPLEX_HALF; - - ethernet_phy_reset(mp->port_num); + ethernet_phy_reset(port_num); mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii); mv643xx_init_ethtool_cmd(dev, mp->mii.phy_id, speed, duplex, &cmd); mv643xx_eth_update_pscr(dev, &cmd); @@ -1971,13 +1937,17 @@ static void eth_port_start(struct net_device *dev) eth_port_uc_addr_set(port_num, dev->dev_addr); /* Assign port configuration and command. */ - mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), mp->port_config); + mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), + MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE); + + mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num), + MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE); pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); - pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; + + pscr &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE | MV643XX_ETH_FORCE_LINK_PASS); mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); - pscr &= ~MV643XX_ETH_FORCE_LINK_PASS; pscr |= MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII | MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX | @@ -1990,7 +1960,8 @@ static void eth_port_start(struct net_device *dev) mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr); /* Assign port SDMA configuration */ - mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num), mp->port_sdma_config); + mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num), + MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE); /* Enable port Rx. */ mv643xx_eth_port_enable_rx(port_num, mp->port_rx_queue_command); diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index f2e5da79dde8..a553054e8da7 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -321,10 +321,6 @@ struct mv643xx_mib_counters { struct mv643xx_private { int port_num; /* User Ethernet port number */ - u32 port_config; /* User port configuration value*/ - u32 port_config_extend; /* User port config extend value*/ - u32 port_sdma_config; /* User port SDMA config value */ - u32 port_serial_control; /* User port serial control value */ u32 port_tx_queue_command; /* Port active Tx queues summary*/ u32 port_rx_queue_command; /* Port active Rx queues summary*/ diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h index 7ffbeac7d2bb..955d3069d727 100644 --- a/include/linux/mv643xx.h +++ b/include/linux/mv643xx.h @@ -1288,23 +1288,15 @@ struct mv64xxx_i2c_pdata { #define MV643XX_ETH_NAME "mv643xx_eth" struct mv643xx_eth_platform_data { - /* - * Non-values for mac_addr, phy_addr, port_config, etc. - * override the default value. Setting the corresponding - * force_* field, causes the default value to be overridden - * even when zero. - */ - unsigned int force_phy_addr:1; - unsigned int force_port_config:1; - unsigned int force_port_config_extend:1; - unsigned int force_port_sdma_config:1; - unsigned int force_port_serial_control:1; - int phy_addr; char *mac_addr; /* pointer to mac address */ - u32 port_config; - u32 port_config_extend; - u32 port_sdma_config; - u32 port_serial_control; + u16 force_phy_addr; /* force override if phy_addr == 0 */ + u16 phy_addr; + + /* If speed is 0, then speed and duplex are autonegotiated. */ + int speed; /* 0, SPEED_10, SPEED_100, SPEED_1000 */ + int duplex; /* DUPLEX_HALF or DUPLEX_FULL */ + + /* non-zero values of the following fields override defaults */ u32 tx_queue_size; u32 rx_queue_size; u32 tx_sram_addr; -- cgit v1.2.3-59-g8ed1b From a62c0fc526c344d8163f7a9e45e68cc63826ffd3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 24 Jan 2006 17:05:22 +0900 Subject: [PATCH] libata: implement ata_drive_probe_reset() Most low level drivers share supported reset/classify actions and sequence. This patch implements ata_drive_probe_reset() which helps constructing ->probe_reset from three component operations - softreset, hardreset and postreset. This minimizes duplicate code and yet allows flexibility if needed. The three component operations can also be shared by EH later. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 5 +++ 2 files changed, 94 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 147e1461062d..cf91fdc08ef6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2233,6 +2233,94 @@ err_out: DPRINTK("EXIT\n"); } +static int do_probe_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, 0, 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; + + if (postreset) + postreset(ap, classes); + + return classes[0] != ATA_DEV_UNKNOWN ? 0 : -ENODEV; +} + +/** + * ata_drive_probe_reset - Perform probe reset with given methods + * @ap: port to reset + * @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. + * - If verbose is non-zero, print error message on failure; + * otherwise, shut up. + * + * 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_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset, unsigned int *classes) +{ + int rc = -EINVAL; + + if (softreset) { + rc = do_probe_reset(ap, softreset, postreset, classes); + if (rc == 0) + return 0; + } + + if (!hardreset) + return rc; + + rc = do_probe_reset(ap, hardreset, postreset, classes); + if (rc == 0 || rc != -ENODEV) + return rc; + + if (softreset) + rc = do_probe_reset(ap, softreset, postreset, classes); + + return rc; +} + static void ata_pr_blacklisted(const struct ata_port *ap, const struct ata_device *dev) { @@ -5180,6 +5268,7 @@ EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); +EXPORT_SYMBOL_GPL(ata_drive_probe_reset); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_busy_sleep); diff --git a/include/linux/libata.h b/include/linux/libata.h index a84d1c3a5429..38e08ce2d1af 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -241,6 +241,8 @@ struct ata_queued_cmd; /* typedefs */ typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); +typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *); +typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *); struct ata_ioports { unsigned long cmd_addr; @@ -478,6 +480,9 @@ 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_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_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI -- cgit v1.2.3-59-g8ed1b From c2bd58047b9b5c91a3b0a851de66a877f2eb7ae3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 24 Jan 2006 17:05:22 +0900 Subject: [PATCH] libata: implement standard reset component operations and ->probe_reset Implement SRST, COMRESET and standard postreset component operations for ata_drive_probe_reset(), and use these three functions to implement ata_std_probe_reset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 206 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 6 ++ 2 files changed, 212 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index cf91fdc08ef6..b369dbd7cb23 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2233,6 +2233,208 @@ err_out: DPRINTK("EXIT\n"); } +/** + * 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 + * as standard callback for ata_drive_*_reset() functions. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) +{ + unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; + unsigned int devmask = 0, err_mask; + u8 err; + + DPRINTK("ENTER\n"); + + /* determine if device 0/1 are present */ + if (ata_devchk(ap, 0)) + devmask |= (1 << 0); + if (slave_possible && ata_devchk(ap, 1)) + devmask |= (1 << 1); + + /* devchk reports device presence without actual device on + * most SATA controllers. Check SStatus and turn devmask off + * if link is offline. Note that we should continue resetting + * even when it seems like there's no device. + */ + if (ap->ops->scr_read && !sata_dev_present(ap)) + devmask = 0; + + /* select device 0 again */ + ap->ops->dev_select(ap, 0); + + /* issue bus reset */ + 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); + return -EIO; + } + + /* determine by signature whether we have ATA or ATAPI devices */ + classes[0] = ata_dev_try_classify(ap, 0, &err); + if (slave_possible && err != 0x81) + classes[1] = ata_dev_try_classify(ap, 1, &err); + + DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]); + return 0; +} + +/** + * 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. + * This function is to be used as standard callback for + * ata_drive_*_reset(). + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) +{ + u32 sstatus, serror; + unsigned long timeout = jiffies + (HZ * 5); + + DPRINTK("ENTER\n"); + + /* Issue phy wake/reset */ + 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. + */ + msleep(1); + + scr_write_flush(ap, SCR_CONTROL, 0x300); + + /* Wait for phy to become ready, if necessary. */ + do { + msleep(200); + sstatus = scr_read(ap, SCR_STATUS); + if ((sstatus & 0xf) != 1) + break; + } while (time_before(jiffies, timeout)); + + /* Clear SError */ + serror = scr_read(ap, SCR_ERROR); + scr_write(ap, SCR_ERROR, serror); + + /* TODO: phy layer with polling, timeouts, etc. */ + if (!sata_dev_present(ap)) { + *class = ATA_DEV_NONE; + DPRINTK("EXIT, link offline\n"); + return 0; + } + + 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"); + return -EIO; + } + + *class = ata_dev_try_classify(ap, 0, NULL); + + DPRINTK("EXIT, class=%u\n", *class); + return 0; +} + +/** + * ata_std_postreset - standard postreset callback + * @ap: the target ata_port + * @classes: classes of attached devices + * + * This function is invoked after a successful reset. Note that + * the device might have been reset more than once using + * different reset methods before postreset is invoked. + * postreset is also reponsible for setting cable type. + * + * This function is to be used as standard callback for + * ata_drive_*_reset(). + * + * LOCKING: + * Kernel thread context (may sleep) + */ +void ata_std_postreset(struct ata_port *ap, unsigned int *classes) +{ + DPRINTK("ENTER\n"); + + /* set cable type */ + 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); + + /* bail out if no device is present */ + if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) { + DPRINTK("EXIT, no device\n"); + return; + } + + /* is double-select really necessary? */ + if (classes[0] != ATA_DEV_NONE) + ap->ops->dev_select(ap, 1); + if (classes[1] != ATA_DEV_NONE) + ap->ops->dev_select(ap, 0); + + /* re-enable interrupts & set up device control */ + if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ + ata_irq_on(ap); + + 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 (ap->cbl == ATA_CBL_SATA && ap->ops->scr_read) + hardreset = sata_std_hardreset; + + return ata_drive_probe_reset(ap, ata_std_softreset, hardreset, + 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) @@ -5268,6 +5470,10 @@ EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); +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_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); diff --git a/include/linux/libata.h b/include/linux/libata.h index 38e08ce2d1af..474cdfa35d1e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -483,6 +483,11 @@ extern void ata_bus_reset(struct ata_port *ap); 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 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 void ata_std_postreset(struct ata_port *ap, unsigned int *classes); extern void ata_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI @@ -523,6 +528,7 @@ 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-59-g8ed1b From b376bc1f6b4258112d714fb4ee8e5d57b53625f2 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 28 Jan 2006 12:26:23 -0500 Subject: [libata ata_piix] Fix ICH6/7 map value interpretation The previous change failed to properly mask out unrelated bits, which resulted in a failure to detect devices. --- drivers/scsi/ata_piix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 19d8d4ba6a1e..2d984b090b23 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -713,7 +713,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) pci_read_config_byte(pdev, ICH5_PMR, &tmp); if (host_flags & PIIX_FLAG_COMBINED_ICH6) { - switch (tmp) { + switch (tmp & 0x3) { case 0: break; case 1: -- cgit v1.2.3-59-g8ed1b From 6340f019695a08e3b2e317e307014801fc86b178 Mon Sep 17 00:00:00 2001 From: Luke Kosewski Date: Sat, 28 Jan 2006 12:39:29 -0500 Subject: [libata sata_promise] add correct read/write of hotplug registers for SATAII devices This patch adds support for correctly masking out and knowing about hotplug events on Promise SATAII150 Tx4/Tx2 Plus controllers. Also, a kmalloc->kzalloc cleanup. Signed-off-by: Luke Kosewski Signed-off-by: Jeff Garzik --- drivers/scsi/sata_promise.c | 104 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 77ef646b0f92..0950a8e45814 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -46,7 +46,7 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "1.03" +#define DRV_VERSION "1.04" enum { @@ -58,6 +58,7 @@ enum { PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */ PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ + PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */ PDC_SLEW_CTL = 0x470, /* slew rate control reg */ PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | @@ -67,8 +68,10 @@ enum { board_20319 = 1, /* FastTrak S150 TX4 */ board_20619 = 2, /* FastTrak TX4000 */ board_20771 = 3, /* FastTrak TX2300 */ + board_2057x = 4, /* SATAII150 Tx2plus */ + board_40518 = 5, /* SATAII150 Tx4 */ - PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */ + PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ PDC_RESET = (1 << 11), /* HDMA reset */ @@ -82,6 +85,10 @@ struct pdc_port_priv { dma_addr_t pkt_dma; }; +struct pdc_host_priv { + int hotplug_offset; +}; + static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); @@ -96,6 +103,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); static void pdc_irq_clear(struct ata_port *ap); static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); +static void pdc_host_stop(struct ata_host_set *host_set); static struct scsi_host_template pdc_ata_sht = { @@ -137,7 +145,7 @@ static const struct ata_port_operations pdc_sata_ops = { .scr_write = pdc_sata_scr_write, .port_start = pdc_port_start, .port_stop = pdc_port_stop, - .host_stop = ata_pci_host_stop, + .host_stop = pdc_host_stop, }; static const struct ata_port_operations pdc_pata_ops = { @@ -158,7 +166,7 @@ static const struct ata_port_operations pdc_pata_ops = { .port_start = pdc_port_start, .port_stop = pdc_port_stop, - .host_stop = ata_pci_host_stop, + .host_stop = pdc_host_stop, }; static const struct ata_port_info pdc_port_info[] = { @@ -201,6 +209,26 @@ static const struct ata_port_info pdc_port_info[] = { .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_sata_ops, }, + + /* board_2057x */ + { + .sht = &pdc_ata_sht, + .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &pdc_sata_ops, + }, + + /* board_40518 */ + { + .sht = &pdc_ata_sht, + .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &pdc_sata_ops, + }, }; static const struct pci_device_id pdc_ata_pci_tbl[] = { @@ -217,9 +245,9 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3574, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - board_2037x }, + board_2057x }, { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - board_2037x }, + board_2057x }, { PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, @@ -232,7 +260,7 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20319 }, { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - board_20319 }, + board_40518 }, { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20619 }, @@ -261,12 +289,11 @@ static int pdc_port_start(struct ata_port *ap) if (rc) return rc; - pp = kmalloc(sizeof(*pp), GFP_KERNEL); + pp = kzalloc(sizeof(*pp), GFP_KERNEL); if (!pp) { rc = -ENOMEM; goto err_out; } - memset(pp, 0, sizeof(*pp)); pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL); if (!pp->pkt) { @@ -298,6 +325,16 @@ static void pdc_port_stop(struct ata_port *ap) } +static void pdc_host_stop(struct ata_host_set *host_set) +{ + struct pdc_host_priv *hp = host_set->private_data; + + ata_pci_host_stop(host_set); + + kfree(hp); +} + + static void pdc_reset_port(struct ata_port *ap) { void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT; @@ -487,14 +524,15 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r VPRINTK("QUICK EXIT 2\n"); return IRQ_NONE; } + + spin_lock(&host_set->lock); + mask &= 0xffff; /* only 16 tags possible */ if (!mask) { VPRINTK("QUICK EXIT 3\n"); - return IRQ_NONE; + goto done_irq; } - spin_lock(&host_set->lock); - writel(mask, mmio_base + PDC_INT_SEQMASK); for (i = 0; i < host_set->n_ports; i++) { @@ -511,10 +549,10 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r } } - spin_unlock(&host_set->lock); - VPRINTK("EXIT\n"); +done_irq: + spin_unlock(&host_set->lock); return IRQ_RETVAL(handled); } @@ -592,6 +630,8 @@ static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base) static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) { void __iomem *mmio = pe->mmio_base; + struct pdc_host_priv *hp = pe->private_data; + int hotplug_offset = hp->hotplug_offset; u32 tmp; /* @@ -606,12 +646,12 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) writel(tmp, mmio + PDC_FLASH_CTL); /* clear plug/unplug flags for all ports */ - tmp = readl(mmio + PDC_SATA_PLUG_CSR); - writel(tmp | 0xff, mmio + PDC_SATA_PLUG_CSR); + tmp = readl(mmio + hotplug_offset); + writel(tmp | 0xff, mmio + hotplug_offset); /* mask plug/unplug ints */ - tmp = readl(mmio + PDC_SATA_PLUG_CSR); - writel(tmp | 0xff0000, mmio + PDC_SATA_PLUG_CSR); + tmp = readl(mmio + hotplug_offset); + writel(tmp | 0xff0000, mmio + hotplug_offset); /* reduce TBG clock to 133 Mhz. */ tmp = readl(mmio + PDC_TBG_MODE); @@ -633,6 +673,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e { static int printed_version; struct ata_probe_ent *probe_ent = NULL; + struct pdc_host_priv *hp; unsigned long base; void __iomem *mmio_base; unsigned int board_idx = (unsigned int) ent->driver_data; @@ -663,13 +704,12 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e if (rc) goto err_out_regions; - probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); if (probe_ent == NULL) { rc = -ENOMEM; goto err_out_regions; } - memset(probe_ent, 0, sizeof(*probe_ent)); probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); @@ -680,6 +720,16 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e } base = (unsigned long) mmio_base; + hp = kzalloc(sizeof(*hp), GFP_KERNEL); + if (hp == NULL) { + rc = -ENOMEM; + goto err_out_free_ent; + } + + /* Set default hotplug offset */ + hp->hotplug_offset = PDC_SATA_PLUG_CSR; + probe_ent->private_data = hp; + probe_ent->sht = pdc_port_info[board_idx].sht; probe_ent->host_flags = pdc_port_info[board_idx].host_flags; probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; @@ -699,6 +749,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e /* notice 4-port boards */ switch (board_idx) { + case board_40518: + /* Override hotplug offset for SATAII150 */ + hp->hotplug_offset = PDC2_SATA_PLUG_CSR; + /* Fall through */ case board_20319: probe_ent->n_ports = 4; @@ -708,6 +762,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e probe_ent->port[2].scr_addr = base + 0x600; probe_ent->port[3].scr_addr = base + 0x700; break; + case board_2057x: + /* Override hotplug offset for SATAII150 */ + hp->hotplug_offset = PDC2_SATA_PLUG_CSR; + /* Fall through */ case board_2037x: probe_ent->n_ports = 2; break; @@ -733,8 +791,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e /* initialize adapter */ pdc_host_init(board_idx, probe_ent); - /* FIXME: check ata_device_add return value */ - ata_device_add(probe_ent); + /* FIXME: Need any other frees than hp? */ + if (!ata_device_add(probe_ent)) + kfree(hp); + kfree(probe_ent); return 0; -- cgit v1.2.3-59-g8ed1b From c893a3ae49279a4ab6aa6cf594a2ec6d286e1187 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 28 Jan 2006 13:15:32 -0500 Subject: Various libata documentation updates. This is a merger of libata docs + cleanups from Martin Waitz and me. From: Randy Dunlap From: Martin Waitz Fix libata kernel-doc comments to match code. Add some function parameters to kernel-doc. Fix some typos/spellos. Put comments in <= 80 columns. Make one DPRINTK string unique. Fix sparse cast warnings. Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 1 + drivers/scsi/libata-core.c | 60 +++++++++++++++++++++++----------------------- drivers/scsi/libata-scsi.c | 9 +++---- 3 files changed, 36 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 2d984b090b23..49cc4209fe16 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -630,6 +630,7 @@ static int piix_disable_ahci(struct pci_dev *pdev) /** * piix_check_450nx_errata - Check for problem 450NX setup + * @ata_dev: the PCI device to check * * Check for the present of 450NX errata #19 and errata #25. If * they are found return an error code so we can turn off DMA diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b369dbd7cb23..249e67fab81f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1442,12 +1442,11 @@ static inline u8 ata_dev_knobble(const struct ata_port *ap) } /** - * ata_dev_config - Run device specific handlers and check for - * SATA->PATA bridges - * @ap: Bus - * @i: Device + * ata_dev_config - Run device specific handlers & check for SATA->PATA bridges + * @ap: Bus + * @i: Device * - * LOCKING: + * LOCKING: */ void ata_dev_config(struct ata_port *ap, unsigned int i) @@ -1794,9 +1793,9 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, ata_timing_quantize(t, t, T, UT); /* - * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T - * and some other commands. We have to ensure that the DMA cycle timing is - * slower/equal than the fastest PIO timing. + * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, + * S.M.A.R.T * and some other commands. We have to ensure that the + * DMA cycle timing is slower/equal than the fastest PIO timing. */ if (speed > XFER_PIO_4) { @@ -1805,7 +1804,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, } /* - * Lenghten active & recovery time so that cycle time is correct. + * Lengthen active & recovery time so that cycle time is correct. */ if (t->act8b + t->rec8b < t->cyc8b) { @@ -1924,7 +1923,6 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, * * LOCKING: * PCI/etc. bus probe sem. - * */ static void ata_set_mode(struct ata_port *ap) { @@ -1973,7 +1971,6 @@ err_out: * or a timeout occurs. * * LOCKING: None. - * */ unsigned int ata_busy_sleep (struct ata_port *ap, @@ -3200,7 +3197,7 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc) } /** - * ata_pio_poll - + * ata_pio_poll - poll using PIO, depending on current state * @ap: the target ata_port * * LOCKING: @@ -3307,7 +3304,7 @@ static int ata_pio_complete (struct ata_port *ap) /** - * swap_buf_le16 - swap halves of 16-words in place + * swap_buf_le16 - swap halves of 16-bit words in place * @buf: Buffer to swap * @buf_words: Number of 16-bit words in buffer. * @@ -4520,19 +4517,6 @@ err_out: } -/** - * 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 @@ -4584,6 +4568,8 @@ static int ata_start_drive(struct ata_port *ap, struct ata_device *dev) /** * 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 * command and making sure its transfer mode matches between drive @@ -4606,10 +4592,11 @@ int ata_device_resume(struct ata_port *ap, struct ata_device *dev) /** * 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) { @@ -4623,6 +4610,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; @@ -4880,9 +4880,9 @@ int ata_device_add(const struct ata_probe_ent *ent) ap = host_set->ports[i]; - DPRINTK("ata%u: probe begin\n", ap->id); + DPRINTK("ata%u: bus probe begin\n", ap->id); rc = ata_bus_probe(ap); - DPRINTK("ata%u: probe end\n", ap->id); + DPRINTK("ata%u: bus probe end\n", ap->id); if (rc) { /* FIXME: do something useful here? @@ -4906,7 +4906,7 @@ int ata_device_add(const struct ata_probe_ent *ent) } /* probes are done, now scan each port's disk(s) */ - DPRINTK("probe begin\n"); + DPRINTK("host probe begin\n"); for (i = 0; i < count; i++) { struct ata_port *ap = host_set->ports[i]; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ab6b53349d6f..6df82934d2d6 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -151,7 +151,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) struct scsi_sense_hdr sshdr; enum dma_data_direction data_dir; - if (NULL == (void *)arg) + if (arg == NULL) return -EINVAL; if (copy_from_user(args, arg, sizeof(args))) @@ -201,7 +201,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) /* Need code to retrieve data from check condition? */ if ((argbuf) - && copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize)) + && copy_to_user(arg + sizeof(args), argbuf, argsize)) rc = -EFAULT; error: if (argbuf) @@ -228,7 +228,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) u8 args[7]; struct scsi_sense_hdr sshdr; - if (NULL == (void *)arg) + if (arg == NULL) return -EINVAL; if (copy_from_user(args, arg, sizeof(args))) @@ -2533,7 +2533,8 @@ out_unlock: /** * ata_scsi_simulate - simulate SCSI command on ATA device - * @id: current IDENTIFY data for target device. + * @ap: port the device is connected to + * @dev: the target device * @cmd: SCSI command being sent to device. * @done: SCSI command completion function. * -- cgit v1.2.3-59-g8ed1b From d0f6ecad39266f87913539c52dc624f75cc4b914 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 2 Dec 2005 03:54:44 -0500 Subject: [PATCH] arcnet probing cleanups and fixes make arcnet probing do request_mem_region() for all iomem it's going to access, clean the code up. Signed-off-by: Al Viro --- drivers/net/arcnet/arc-rimi.c | 68 ++++++++++++++++------ drivers/net/arcnet/com90xx.c | 132 ++++++++++++++++++++++++++++++------------ 2 files changed, 143 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 38c3f033f739..8c8d6c453c45 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -97,25 +97,44 @@ static int __init arcrimi_probe(struct net_device *dev) "must specify the shmem and irq!\n"); return -ENODEV; } + if (dev->dev_addr[0] == 0) { + BUGMSG(D_NORMAL, "You need to specify your card's station " + "ID!\n"); + return -ENODEV; + } /* - * Grab the memory region at mem_start for BUFFER_SIZE bytes. + * Grab the memory region at mem_start for MIRROR_SIZE bytes. * Later in arcrimi_found() the real size will be determined * and this reserve will be released and the correct size * will be taken. */ - if (!request_mem_region(dev->mem_start, BUFFER_SIZE, "arcnet (90xx)")) { + if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) { BUGMSG(D_NORMAL, "Card memory already allocated\n"); return -ENODEV; } - if (dev->dev_addr[0] == 0) { - release_mem_region(dev->mem_start, BUFFER_SIZE); - BUGMSG(D_NORMAL, "You need to specify your card's station " - "ID!\n"); - return -ENODEV; - } return arcrimi_found(dev); } +static int check_mirror(unsigned long addr, size_t size) +{ + void __iomem *p; + int res = -1; + + if (!request_mem_region(addr, size, "arcnet (90xx)")) + return -1; + + p = ioremap(addr, size); + if (p) { + if (readb(p) == TESTvalue) + res = 1; + else + res = 0; + iounmap(p); + } + + release_mem_region(addr, size); + return res; +} /* * Set up the struct net_device associated with this card. Called after @@ -125,19 +144,28 @@ static int __init arcrimi_found(struct net_device *dev) { struct arcnet_local *lp; unsigned long first_mirror, last_mirror, shmem; + void __iomem *p; int mirror_size; int err; + p = ioremap(dev->mem_start, MIRROR_SIZE); + if (!p) { + release_mem_region(dev->mem_start, MIRROR_SIZE); + BUGMSG(D_NORMAL, "Can't ioremap\n"); + return -ENODEV; + } + /* reserve the irq */ if (request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet (RIM I)", dev)) { - release_mem_region(dev->mem_start, BUFFER_SIZE); + iounmap(p); + release_mem_region(dev->mem_start, MIRROR_SIZE); BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); return -ENODEV; } shmem = dev->mem_start; - isa_writeb(TESTvalue, shmem); - isa_writeb(dev->dev_addr[0], shmem + 1); /* actually the node ID */ + writeb(TESTvalue, p); + writeb(dev->dev_addr[0], p + 1); /* actually the node ID */ /* find the real shared memory start/end points, including mirrors */ @@ -146,17 +174,18 @@ static int __init arcrimi_found(struct net_device *dev) * 2k (or there are no mirrors at all) but on some, it's 4k. */ mirror_size = MIRROR_SIZE; - if (isa_readb(shmem) == TESTvalue - && isa_readb(shmem - mirror_size) != TESTvalue - && isa_readb(shmem - 2 * mirror_size) == TESTvalue) - mirror_size *= 2; + if (readb(p) == TESTvalue + && check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 + && check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1) + mirror_size = 2 * MIRROR_SIZE; - first_mirror = last_mirror = shmem; - while (isa_readb(first_mirror) == TESTvalue) + first_mirror = shmem - mirror_size; + while (check_mirror(first_mirror, mirror_size) == 1) first_mirror -= mirror_size; first_mirror += mirror_size; - while (isa_readb(last_mirror) == TESTvalue) + last_mirror = shmem + mirror_size; + while (check_mirror(last_mirror, mirror_size) == 1) last_mirror += mirror_size; last_mirror -= mirror_size; @@ -181,7 +210,8 @@ static int __init arcrimi_found(struct net_device *dev) * with the correct size. There is a VERY slim chance this could * fail. */ - release_mem_region(shmem, BUFFER_SIZE); + iounmap(p); + release_mem_region(shmem, MIRROR_SIZE); if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)")) { diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 6c2c9b9ac6db..43150b2bd13f 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -53,7 +53,7 @@ /* Internal function declarations */ -static int com90xx_found(int ioaddr, int airq, u_long shmem); +static int com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *); static void com90xx_command(struct net_device *dev, int command); static int com90xx_status(struct net_device *dev); static void com90xx_setmask(struct net_device *dev, int mask); @@ -116,14 +116,26 @@ static void __init com90xx_probe(void) unsigned long airqmask; int ports[(0x3f0 - 0x200) / 16 + 1] = {0}; - u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] = - {0}; + unsigned long *shmems; + void __iomem **iomem; int numports, numshmems, *port; u_long *p; + int index; if (!io && !irq && !shmem && !*device && com90xx_skip_probe) return; + shmems = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(unsigned long), + GFP_KERNEL); + if (!shmems) + return; + iomem = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(void __iomem *), + GFP_KERNEL); + if (!iomem) { + kfree(shmems); + return; + } + BUGLVL(D_NORMAL) printk(VERSION); /* set up the arrays where we'll store the possible probe addresses */ @@ -179,6 +191,8 @@ static void __init com90xx_probe(void) if (!numports) { BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n"); + kfree(shmems); + kfree(iomem); return; } /* Stage 2: we have now reset any possible ARCnet cards, so we can't @@ -202,8 +216,8 @@ static void __init com90xx_probe(void) * 0xD1 byte in the right place, or are read-only. */ numprint = -1; - for (p = &shmems[0]; p < shmems + numshmems; p++) { - u_long ptr = *p; + for (index = 0, p = &shmems[0]; index < numshmems; p++, index++) { + void __iomem *base; numprint++; numprint %= 8; @@ -213,38 +227,49 @@ static void __init com90xx_probe(void) } BUGMSG2(D_INIT, "%lXh ", *p); - if (!request_mem_region(*p, BUFFER_SIZE, "arcnet (90xx)")) { + if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)")) { BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n"); BUGMSG2(D_INIT_REASONS, "Stage 3: "); BUGLVL(D_INIT_REASONS) numprint = 0; - *p-- = shmems[--numshmems]; - continue; + goto out; + } + base = ioremap(*p, MIRROR_SIZE); + if (!base) { + BUGMSG2(D_INIT_REASONS, "(ioremap)\n"); + BUGMSG2(D_INIT_REASONS, "Stage 3: "); + BUGLVL(D_INIT_REASONS) numprint = 0; + goto out1; } - if (isa_readb(ptr) != TESTvalue) { + if (readb(base) != TESTvalue) { BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n", - isa_readb(ptr), TESTvalue); + readb(base), TESTvalue); BUGMSG2(D_INIT_REASONS, "S3: "); BUGLVL(D_INIT_REASONS) numprint = 0; - release_mem_region(*p, BUFFER_SIZE); - *p-- = shmems[--numshmems]; - continue; + goto out2; } /* By writing 0x42 to the TESTvalue location, we also make * sure no "mirror" shmem areas show up - if they occur * in another pass through this loop, they will be discarded * because *cptr != TESTvalue. */ - isa_writeb(0x42, ptr); - if (isa_readb(ptr) != 0x42) { + writeb(0x42, base); + if (readb(base) != 0x42) { BUGMSG2(D_INIT_REASONS, "(read only)\n"); BUGMSG2(D_INIT_REASONS, "S3: "); - release_mem_region(*p, BUFFER_SIZE); - *p-- = shmems[--numshmems]; - continue; + goto out2; } BUGMSG2(D_INIT_REASONS, "\n"); BUGMSG2(D_INIT_REASONS, "S3: "); BUGLVL(D_INIT_REASONS) numprint = 0; + iomem[index] = base; + continue; + out2: + iounmap(base); + out1: + release_mem_region(*p, MIRROR_SIZE); + out: + *p-- = shmems[--numshmems]; + index--; } BUGMSG2(D_INIT, "\n"); @@ -252,6 +277,8 @@ static void __init com90xx_probe(void) BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n"); for (port = &ports[0]; port < ports + numports; port++) release_region(*port, ARCNET_TOTAL_SIZE); + kfree(shmems); + kfree(iomem); return; } /* Stage 4: something of a dummy, to report the shmems that are @@ -351,30 +378,32 @@ static void __init com90xx_probe(void) mdelay(RESETtime); } else { /* just one shmem and port, assume they match */ - isa_writeb(TESTvalue, shmems[0]); + writeb(TESTvalue, iomem[0]); } #else inb(_RESET); mdelay(RESETtime); #endif - for (p = &shmems[0]; p < shmems + numshmems; p++) { - u_long ptr = *p; + for (index = 0; index < numshmems; index++) { + u_long ptr = shmems[index]; + void __iomem *base = iomem[index]; - if (isa_readb(ptr) == TESTvalue) { /* found one */ + if (readb(base) == TESTvalue) { /* found one */ BUGMSG2(D_INIT, "%lXh)\n", *p); openparen = 0; /* register the card */ - if (com90xx_found(*port, airq, *p) == 0) + if (com90xx_found(*port, airq, ptr, base) == 0) found = 1; numprint = -1; /* remove shmem from the list */ - *p = shmems[--numshmems]; + shmems[index] = shmems[--numshmems]; + iomem[index] = iomem[numshmems]; break; /* go to the next I/O port */ } else { - BUGMSG2(D_INIT_REASONS, "%Xh-", isa_readb(ptr)); + BUGMSG2(D_INIT_REASONS, "%Xh-", readb(base)); } } @@ -391,17 +420,40 @@ static void __init com90xx_probe(void) BUGLVL(D_INIT_REASONS) printk("\n"); /* Now put back TESTvalue on all leftover shmems. */ - for (p = &shmems[0]; p < shmems + numshmems; p++) { - isa_writeb(TESTvalue, *p); - release_mem_region(*p, BUFFER_SIZE); + for (index = 0; index < numshmems; index++) { + writeb(TESTvalue, iomem[index]); + iounmap(iomem[index]); + release_mem_region(shmems[index], MIRROR_SIZE); } + kfree(shmems); + kfree(iomem); } +static int check_mirror(unsigned long addr, size_t size) +{ + void __iomem *p; + int res = -1; + + if (!request_mem_region(addr, size, "arcnet (90xx)")) + return -1; + + p = ioremap(addr, size); + if (p) { + if (readb(p) == TESTvalue) + res = 1; + else + res = 0; + iounmap(p); + } + + release_mem_region(addr, size); + return res; +} /* Set up the struct net_device associated with this card. Called after * probing succeeds. */ -static int __init com90xx_found(int ioaddr, int airq, u_long shmem) +static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *p) { struct net_device *dev = NULL; struct arcnet_local *lp; @@ -412,7 +464,8 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem) dev = alloc_arcdev(device); if (!dev) { BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n"); - release_mem_region(shmem, BUFFER_SIZE); + iounmap(p); + release_mem_region(shmem, MIRROR_SIZE); return -ENOMEM; } lp = dev->priv; @@ -423,24 +476,27 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem) * 2k (or there are no mirrors at all) but on some, it's 4k. */ mirror_size = MIRROR_SIZE; - if (isa_readb(shmem) == TESTvalue - && isa_readb(shmem - mirror_size) != TESTvalue - && isa_readb(shmem - 2 * mirror_size) == TESTvalue) - mirror_size *= 2; + if (readb(p) == TESTvalue && + check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 && + check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1) + mirror_size = 2 * MIRROR_SIZE; - first_mirror = last_mirror = shmem; - while (isa_readb(first_mirror) == TESTvalue) + first_mirror = shmem - mirror_size; + while (check_mirror(first_mirror, mirror_size) == 1) first_mirror -= mirror_size; first_mirror += mirror_size; - while (isa_readb(last_mirror) == TESTvalue) + last_mirror = shmem + mirror_size; + while (check_mirror(last_mirror, mirror_size) == 1) last_mirror += mirror_size; last_mirror -= mirror_size; dev->mem_start = first_mirror; dev->mem_end = last_mirror + MIRROR_SIZE - 1; - release_mem_region(shmem, BUFFER_SIZE); + iounmap(p); + release_mem_region(shmem, MIRROR_SIZE); + if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)")) goto err_free_dev; -- cgit v1.2.3-59-g8ed1b From b43de2d8db7655d1c520bf6eac7071d8f6d0b864 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 1 Dec 2005 10:15:21 -0500 Subject: [PATCH] ibm_emac sparse annotations Signed-off-by: Al Viro --- drivers/net/ibm_emac/ibm_emac_core.c | 40 +++++++++++++++++------------------ drivers/net/ibm_emac/ibm_emac_core.h | 2 +- drivers/net/ibm_emac/ibm_emac_debug.c | 2 +- drivers/net/ibm_emac/ibm_emac_rgmii.h | 2 +- drivers/net/ibm_emac/ibm_emac_zmii.c | 7 +++--- drivers/net/ibm_emac/ibm_emac_zmii.h | 2 +- 6 files changed, 26 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c index 591c5864ffb1..7e49522b8b3c 100644 --- a/drivers/net/ibm_emac/ibm_emac_core.c +++ b/drivers/net/ibm_emac/ibm_emac_core.c @@ -204,7 +204,7 @@ static inline int emac_phy_gpcs(int phy_mode) static inline void emac_tx_enable(struct ocp_enet_private *dev) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; unsigned long flags; u32 r; @@ -220,7 +220,7 @@ static inline void emac_tx_enable(struct ocp_enet_private *dev) static void emac_tx_disable(struct ocp_enet_private *dev) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; unsigned long flags; u32 r; @@ -244,7 +244,7 @@ static void emac_tx_disable(struct ocp_enet_private *dev) static void emac_rx_enable(struct ocp_enet_private *dev) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; unsigned long flags; u32 r; @@ -275,7 +275,7 @@ static void emac_rx_enable(struct ocp_enet_private *dev) static void emac_rx_disable(struct ocp_enet_private *dev) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; unsigned long flags; u32 r; @@ -299,7 +299,7 @@ static void emac_rx_disable(struct ocp_enet_private *dev) static inline void emac_rx_disable_async(struct ocp_enet_private *dev) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; unsigned long flags; u32 r; @@ -315,7 +315,7 @@ static inline void emac_rx_disable_async(struct ocp_enet_private *dev) static int emac_reset(struct ocp_enet_private *dev) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; unsigned long flags; int n = 20; @@ -348,7 +348,7 @@ static int emac_reset(struct ocp_enet_private *dev) static void emac_hash_mc(struct ocp_enet_private *dev) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; u16 gaht[4] = { 0 }; struct dev_mc_list *dmi; @@ -393,7 +393,7 @@ static inline int emac_opb_mhz(void) /* BHs disabled */ static int emac_configure(struct ocp_enet_private *dev) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; struct net_device *ndev = dev->ndev; int gige; u32 r; @@ -555,7 +555,7 @@ static void emac_full_tx_reset(struct net_device *ndev) static int __emac_mdio_read(struct ocp_enet_private *dev, u8 id, u8 reg) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; u32 r; int n; @@ -604,7 +604,7 @@ static int __emac_mdio_read(struct ocp_enet_private *dev, u8 id, u8 reg) static void __emac_mdio_write(struct ocp_enet_private *dev, u8 id, u8 reg, u16 val) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; int n; DBG2("%d: mdio_write(%02x,%02x,%04x)" NL, dev->def->index, id, reg, @@ -666,7 +666,7 @@ static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val) static void emac_set_multicast_list(struct net_device *ndev) { struct ocp_enet_private *dev = ndev->priv; - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; u32 rmr = emac_iff2rmr(ndev); DBG("%d: multicast %08x" NL, dev->def->index, rmr); @@ -825,7 +825,7 @@ static void emac_clean_rx_ring(struct ocp_enet_private *dev) } static inline int emac_alloc_rx_skb(struct ocp_enet_private *dev, int slot, - int flags) + gfp_t flags) { struct sk_buff *skb = alloc_skb(dev->rx_skb_size, flags); if (unlikely(!skb)) @@ -1047,7 +1047,7 @@ static inline u16 emac_tx_csum(struct ocp_enet_private *dev, static inline int emac_xmit_finish(struct ocp_enet_private *dev, int len) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; struct net_device *ndev = dev->ndev; /* Send the packet out */ @@ -1519,7 +1519,7 @@ static void emac_rxde(void *param) static irqreturn_t emac_irq(int irq, void *dev_instance, struct pt_regs *regs) { struct ocp_enet_private *dev = dev_instance; - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; struct ibm_emac_error_stats *st = &dev->estats; u32 isr = in_be32(&p->isr); @@ -1619,17 +1619,17 @@ static void emac_remove(struct ocp_device *ocpdev) DBG("%d: remove" NL, dev->def->index); - ocp_set_drvdata(ocpdev, 0); + ocp_set_drvdata(ocpdev, NULL); unregister_netdev(dev->ndev); tah_fini(dev->tah_dev); rgmii_fini(dev->rgmii_dev, dev->rgmii_input); zmii_fini(dev->zmii_dev, dev->zmii_input); - emac_dbg_register(dev->def->index, 0); + emac_dbg_register(dev->def->index, NULL); mal_unregister_commac(dev->mal, &dev->commac); - iounmap((void *)dev->emacp); + iounmap(dev->emacp); kfree(dev->ndev); } @@ -2048,9 +2048,7 @@ static int __init emac_probe(struct ocp_device *ocpdev) goto out4; /* Map EMAC regs */ - dev->emacp = - (struct emac_regs *)ioremap(dev->def->paddr, - sizeof(struct emac_regs)); + dev->emacp = ioremap(dev->def->paddr, sizeof(struct emac_regs)); if (!dev->emacp) { printk(KERN_ERR "emac%d: could not ioremap device registers!\n", dev->def->index); @@ -2210,7 +2208,7 @@ static int __init emac_probe(struct ocp_device *ocpdev) return 0; out6: - iounmap((void *)dev->emacp); + iounmap(dev->emacp); out5: tah_fini(dev->tah_dev); out4: diff --git a/drivers/net/ibm_emac/ibm_emac_core.h b/drivers/net/ibm_emac/ibm_emac_core.h index 911abbaf471b..f61273b2e94f 100644 --- a/drivers/net/ibm_emac/ibm_emac_core.h +++ b/drivers/net/ibm_emac/ibm_emac_core.h @@ -155,7 +155,7 @@ struct ibm_emac_error_stats { struct ocp_enet_private { struct net_device *ndev; /* 0 */ - struct emac_regs *emacp; + struct emac_regs __iomem *emacp; struct mal_descriptor *tx_desc; int tx_cnt; diff --git a/drivers/net/ibm_emac/ibm_emac_debug.c b/drivers/net/ibm_emac/ibm_emac_debug.c index 75d3b8639041..c7e1ecfa08fe 100644 --- a/drivers/net/ibm_emac/ibm_emac_debug.c +++ b/drivers/net/ibm_emac/ibm_emac_debug.c @@ -58,7 +58,7 @@ static void emac_desc_dump(int idx, struct ocp_enet_private *p) static void emac_mac_dump(int idx, struct ocp_enet_private *dev) { - struct emac_regs *p = dev->emacp; + struct emac_regs __iomem *p = dev->emacp; printk("** EMAC%d registers **\n" "MR0 = 0x%08x MR1 = 0x%08x TMR0 = 0x%08x TMR1 = 0x%08x\n" diff --git a/drivers/net/ibm_emac/ibm_emac_rgmii.h b/drivers/net/ibm_emac/ibm_emac_rgmii.h index a1ffb8a44fff..7f03d536c9a3 100644 --- a/drivers/net/ibm_emac/ibm_emac_rgmii.h +++ b/drivers/net/ibm_emac/ibm_emac_rgmii.h @@ -31,7 +31,7 @@ struct rgmii_regs { /* RGMII device */ struct ibm_ocp_rgmii { - struct rgmii_regs *base; + struct rgmii_regs __iomem *base; int users; /* number of EMACs using this RGMII bridge */ }; diff --git a/drivers/net/ibm_emac/ibm_emac_zmii.c b/drivers/net/ibm_emac/ibm_emac_zmii.c index 35c1185079ed..e129e0aaa045 100644 --- a/drivers/net/ibm_emac/ibm_emac_zmii.c +++ b/drivers/net/ibm_emac/ibm_emac_zmii.c @@ -80,7 +80,7 @@ static inline u32 zmii_mode_mask(int mode, int input) static int __init zmii_init(struct ocp_device *ocpdev, int input, int *mode) { struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev); - struct zmii_regs *p; + struct zmii_regs __iomem *p; ZMII_DBG("%d: init(%d, %d)" NL, ocpdev->def->index, input, *mode); @@ -94,8 +94,7 @@ static int __init zmii_init(struct ocp_device *ocpdev, int input, int *mode) } dev->mode = PHY_MODE_NA; - p = (struct zmii_regs *)ioremap(ocpdev->def->paddr, - sizeof(struct zmii_regs)); + p = ioremap(ocpdev->def->paddr, sizeof(struct zmii_regs)); if (!p) { printk(KERN_ERR "zmii%d: could not ioremap device registers!\n", @@ -231,7 +230,7 @@ void __exit __zmii_fini(struct ocp_device *ocpdev, int input) if (!--dev->users) { /* Free everything if this is the last user */ ocp_set_drvdata(ocpdev, NULL); - iounmap((void *)dev->base); + iounmap(dev->base); kfree(dev); } } diff --git a/drivers/net/ibm_emac/ibm_emac_zmii.h b/drivers/net/ibm_emac/ibm_emac_zmii.h index 0bb26062c0ad..92c854410753 100644 --- a/drivers/net/ibm_emac/ibm_emac_zmii.h +++ b/drivers/net/ibm_emac/ibm_emac_zmii.h @@ -32,7 +32,7 @@ struct zmii_regs { /* ZMII device */ struct ibm_ocp_zmii { - struct zmii_regs *base; + struct zmii_regs __iomem *base; int mode; /* subset of PHY_MODE_XXXX */ int users; /* number of EMACs using this ZMII bridge */ u32 fer_save; /* FER value left by firmware */ -- cgit v1.2.3-59-g8ed1b From 976345cc0fb34d677233b5b22d4819dc7ac92ef1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 6 Dec 2005 06:02:45 -0500 Subject: [PATCH] appletalk/cops.h: missing const in struct ltfirmware Signed-off-by: Al Viro --- drivers/net/appletalk/cops.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/appletalk/cops.h b/drivers/net/appletalk/cops.h index c68ba9c2ef46..aca47f3a7b98 100644 --- a/drivers/net/appletalk/cops.h +++ b/drivers/net/appletalk/cops.h @@ -51,7 +51,7 @@ struct ltfirmware { unsigned int length; - unsigned char * data; + const unsigned char * data; }; #define DAYNA 1 -- cgit v1.2.3-59-g8ed1b From ded5ca1f3b9ffa464fe5d4744fd09bba753ff4b7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 4 Dec 2005 02:28:40 -0500 Subject: [PATCH] macsonic.c: missed s/driver_unregister/platform_driver_unregister/ Signed-off-by: Al Viro --- drivers/net/macsonic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index 02d5c6822733..f6f3dafe83ee 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c @@ -622,7 +622,7 @@ static int __init mac_sonic_init_module(void) return 0; out_unregister: - driver_unregister(&mac_sonic_driver); + platform_driver_unregister(&mac_sonic_driver); return -ENOMEM; } -- cgit v1.2.3-59-g8ed1b From 82729971e0f8ccf1f15567cc4f2c5389e0659eb2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 6 Dec 2005 05:53:04 -0500 Subject: [PATCH] missing include of asm/irq.h in drivers/net Signed-off-by: Al Viro --- drivers/net/tulip/xircom_cb.c | 3 +++ drivers/net/wan/hostess_sv11.c | 1 + drivers/net/wan/sealevel.c | 1 + 3 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 60d1e05ab732..42e9ffb07af4 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -32,6 +32,9 @@ #include #include +#ifdef CONFIG_NET_POLL_CONTROLLER +#include +#endif #ifdef DEBUG #define enter(x) printk("Enter: %s, %s line %i\n",x,__FILE__,__LINE__) diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c index 7db1d1d0bb34..cf5c805452a3 100644 --- a/drivers/net/wan/hostess_sv11.c +++ b/drivers/net/wan/hostess_sv11.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c index 5380ddfcd7d5..050e854e7774 100644 --- a/drivers/net/wan/sealevel.c +++ b/drivers/net/wan/sealevel.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3-59-g8ed1b From 3c13958620f08c8082a2694e51dec32592438388 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 1 Dec 2005 06:44:55 -0500 Subject: [PATCH] bogus include of linux/irq.h in 7990.c Signed-off-by: Al Viro --- drivers/net/7990.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 18b027e73f28..86633c5f1a4b 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include /* Used for the temporal inet entries and routing */ #include #include -- cgit v1.2.3-59-g8ed1b From 0018dfa48e171315ce7f0ea689e34b67af926e19 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 1 Dec 2005 06:53:59 -0500 Subject: [PATCH] wrong ifdefs in 82596.c ifdefs around variable declaration would better match those around its uses... Signed-off-by: Al Viro --- drivers/net/82596.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/82596.c b/drivers/net/82596.c index 13b745b39667..da0c878dcba8 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -614,7 +614,7 @@ static void rebuild_rx_bufs(struct net_device *dev) static int init_i596_mem(struct net_device *dev) { struct i596_private *lp = dev->priv; -#if !defined(ENABLE_MVME16x_NET) && !defined(ENABLE_BVME6000_NET) +#if !defined(ENABLE_MVME16x_NET) && !defined(ENABLE_BVME6000_NET) || defined(ENABLE_APRICOT) short ioaddr = dev->base_addr; #endif unsigned long flags; -- cgit v1.2.3-59-g8ed1b From 450d86dff3fc4780fd5c2d1654402ab7ffec9c38 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 22 Dec 2005 14:52:52 -0500 Subject: [PATCH] dead code removed in hp100 for mode 2 (memory-mapped) we always set ->mem_ptr_virt; dead code removed. Signed-off-by: Al Viro --- drivers/net/hp100.c | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 55c7ed608391..7ba87b7ee612 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -1718,17 +1718,10 @@ static int hp100_start_xmit(struct sk_buff *skb, struct net_device *dev) hp100_outw(i, FRAGMENT_LEN); /* and first/only fragment length */ if (lp->mode == 2) { /* memory mapped */ - if (lp->mem_ptr_virt) { /* high pci memory was remapped */ - /* Note: The J2585B needs alignment to 32bits here! */ - memcpy_toio(lp->mem_ptr_virt, skb->data, (skb->len + 3) & ~3); - if (!ok_flag) - memset_io(lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len); - } else { - /* Note: The J2585B needs alignment to 32bits here! */ - isa_memcpy_toio(lp->mem_ptr_phys, skb->data, (skb->len + 3) & ~3); - if (!ok_flag) - isa_memset_io(lp->mem_ptr_phys, 0, HP100_MIN_PACKET_SIZE - skb->len); - } + /* Note: The J2585B needs alignment to 32bits here! */ + memcpy_toio(lp->mem_ptr_virt, skb->data, (skb->len + 3) & ~3); + if (!ok_flag) + memset_io(lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len); } else { /* programmed i/o */ outsl(ioaddr + HP100_REG_DATA32, skb->data, (skb->len + 3) >> 2); @@ -1798,10 +1791,7 @@ static void hp100_rx(struct net_device *dev) /* First we get the header, which contains information about the */ /* actual length of the received packet. */ if (lp->mode == 2) { /* memory mapped mode */ - if (lp->mem_ptr_virt) /* if memory was remapped */ - header = readl(lp->mem_ptr_virt); - else - header = isa_readl(lp->mem_ptr_phys); + header = readl(lp->mem_ptr_virt); } else /* programmed i/o */ header = hp100_inl(DATA32); @@ -1833,13 +1823,9 @@ static void hp100_rx(struct net_device *dev) ptr = skb->data; /* Now transfer the data from the card into that area */ - if (lp->mode == 2) { - if (lp->mem_ptr_virt) - memcpy_fromio(ptr, lp->mem_ptr_virt,pkt_len); - /* Note alignment to 32bit transfers */ - else - isa_memcpy_fromio(ptr, lp->mem_ptr_phys, pkt_len); - } else /* io mapped */ + if (lp->mode == 2) + memcpy_fromio(ptr, lp->mem_ptr_virt,pkt_len); + else /* io mapped */ insl(ioaddr + HP100_REG_DATA32, ptr, pkt_len >> 2); skb->protocol = eth_type_trans(skb, dev); -- cgit v1.2.3-59-g8ed1b From d86b5e0e6bf5980d3136ab4a855522143f2dcb5d Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 21 Jan 2006 00:46:55 +0100 Subject: [PATCH] net/: fix the WIRELESS_EXT abuse This patch contains the following changes: - add a CONFIG_WIRELESS_EXT select'ed by NET_RADIO for conditional code - remove the now no longer required #ifdef CONFIG_NET_RADIO from some #include's Based on a patch by Jean Tourrilhes . Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 3 ++- drivers/net/wireless/netwave_cs.c | 2 -- drivers/net/wireless/wavelan.p.h | 6 +----- drivers/net/wireless/wavelan_cs.p.h | 9 +-------- net/Kconfig | 3 +++ net/core/Makefile | 2 +- net/core/dev.c | 10 ++++------ net/ieee80211/ieee80211_rx.c | 4 ++-- net/socket.c | 9 +++------ 9 files changed, 17 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 233a4f608084..9ccfec50f733 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -6,7 +6,8 @@ menu "Wireless LAN (non-hamradio)" depends on NETDEVICES config NET_RADIO - bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions" + bool "Wireless LAN drivers (non-hamradio)" + select WIRELESS_EXT ---help--- Support for wireless LANs and everything having to do with radio, but not with amateur radio or FM broadcasting. diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index bf6271ee387a..75ce6ddb0cf5 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -55,10 +55,8 @@ #include #include #include -#ifdef CONFIG_NET_RADIO #include #include -#endif #include #include diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h index 166e28b9a4f7..5cb0bc8bb128 100644 --- a/drivers/net/wireless/wavelan.p.h +++ b/drivers/net/wireless/wavelan.p.h @@ -98,11 +98,7 @@ * characteristics of the hardware. Applications such as mobile IP may * take advantage of it. * - * You will need to enable the CONFIG_NET_RADIO define in the kernel - * configuration to enable the wireless extensions (this is the one - * giving access to the radio network device choice). - * - * It might also be a good idea as well to fetch the wireless tools to + * It might be a good idea as well to fetch the wireless tools to * configure the device and play a bit. */ diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h index f2d597568151..451f6271dcbc 100644 --- a/drivers/net/wireless/wavelan_cs.p.h +++ b/drivers/net/wireless/wavelan_cs.p.h @@ -99,11 +99,7 @@ * caracteristics of the hardware in a standard way and support for * applications for taking advantage of it (like Mobile IP). * - * You will need to enable the CONFIG_NET_RADIO define in the kernel - * configuration to enable the wireless extensions (this is the one - * giving access to the radio network device choice). - * - * It might also be a good idea as well to fetch the wireless tools to + * It might be a good idea as well to fetch the wireless tools to * configure the device and play a bit. */ @@ -440,11 +436,8 @@ #include #include #include - -#ifdef CONFIG_NET_RADIO #include /* Wireless extensions */ #include /* New driver API */ -#endif /* Pcmcia headers that we need */ #include diff --git a/net/Kconfig b/net/Kconfig index bc603d9aea56..d6216888c3ae 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -217,6 +217,9 @@ source "net/irda/Kconfig" source "net/bluetooth/Kconfig" source "net/ieee80211/Kconfig" +config WIRELESS_EXT + bool + endif # if NET endmenu # Networking diff --git a/net/core/Makefile b/net/core/Makefile index 630da0f0579e..79fe12cced27 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -14,5 +14,5 @@ obj-$(CONFIG_XFRM) += flow.o obj-$(CONFIG_SYSFS) += net-sysfs.o obj-$(CONFIG_NET_DIVERT) += dv.o obj-$(CONFIG_NET_PKTGEN) += pktgen.o -obj-$(CONFIG_NET_RADIO) += wireless.o +obj-$(CONFIG_WIRELESS_EXT) += wireless.o obj-$(CONFIG_NETPOLL) += netpoll.o diff --git a/net/core/dev.c b/net/core/dev.c index fd070a098f20..41ac7a8ddb0a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -110,10 +110,8 @@ #include #include #include -#ifdef CONFIG_NET_RADIO -#include /* Note : will define WIRELESS_EXT */ +#include #include -#endif /* CONFIG_NET_RADIO */ #include /* @@ -2028,7 +2026,7 @@ static struct file_operations softnet_seq_fops = { .release = seq_release, }; -#ifdef WIRELESS_EXT +#ifdef CONFIG_WIRELESS_EXT extern int wireless_proc_init(void); #else #define wireless_proc_init() 0 @@ -2581,7 +2579,7 @@ int dev_ioctl(unsigned int cmd, void __user *arg) ret = -EFAULT; return ret; } -#ifdef WIRELESS_EXT +#ifdef CONFIG_WIRELESS_EXT /* Take care of Wireless Extensions */ if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { /* If command is `set a parameter', or @@ -2602,7 +2600,7 @@ int dev_ioctl(unsigned int cmd, void __user *arg) ret = -EFAULT; return ret; } -#endif /* WIRELESS_EXT */ +#endif /* CONFIG_WIRELESS_EXT */ return -EINVAL; } } diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 6c070bc155e7..e2f1553ecb7c 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -369,8 +369,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* Put this code here so that we avoid duplicating it in all * Rx paths. - Jean II */ +#ifdef CONFIG_WIRELESS_EXT #ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ -#ifdef CONFIG_NET_RADIO /* If spy monitoring on */ if (ieee->spy_data.spy_number > 0) { struct iw_quality wstats; @@ -397,8 +397,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* Update spy records */ wireless_spy_update(ieee->dev, hdr->addr2, &wstats); } -#endif /* CONFIG_NET_RADIO */ #endif /* IW_WIRELESS_SPY */ +#endif /* CONFIG_WIRELESS_EXT */ #ifdef NOT_YET hostap_update_rx_stats(local->ap, hdr, rx_stats); diff --git a/net/socket.c b/net/socket.c index b38a263853c3..8aa5f1188e9b 100644 --- a/net/socket.c +++ b/net/socket.c @@ -84,10 +84,7 @@ #include #include #include - -#ifdef CONFIG_NET_RADIO -#include /* Note : will define WIRELESS_EXT */ -#endif /* CONFIG_NET_RADIO */ +#include #include #include @@ -840,11 +837,11 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { err = dev_ioctl(cmd, argp); } else -#ifdef WIRELESS_EXT +#ifdef CONFIG_WIRELESS_EXT if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { err = dev_ioctl(cmd, argp); } else -#endif /* WIRELESS_EXT */ +#endif /* CONFIG_WIRELESS_EXT */ switch (cmd) { case FIOSETOWN: case SIOCSPGRP: -- cgit v1.2.3-59-g8ed1b From a39d3e796cd2df8576c0418faa2c3833153bb3a9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 21 Jan 2006 01:35:15 +0100 Subject: [PATCH] AIRO{,_CS} <-> CRYPTO fixes CRYPTO is a helper variable, and to make it easier for users, it should therefore select'ed and not be listed in the dependencies. drivers/net/wireless/airo.c requires CONFIG_CRYPTO for compilations. Therefore, AIRO_CS also has to CRYPTO. Additionally, this patch removes the #ifdef's for the non-compiling CRYPTO=n case from drivers/net/wireless/airo.c. Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 4 +++- drivers/net/wireless/airo.c | 55 ++------------------------------------------ 2 files changed, 5 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 9ccfec50f733..3de5f1d0fbac 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -240,7 +240,8 @@ config IPW2200_DEBUG config AIRO tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards" - depends on NET_RADIO && ISA_DMA_API && CRYPTO && (PCI || BROKEN) + depends on NET_RADIO && ISA_DMA_API && (PCI || BROKEN) + select CRYPTO ---help--- This is the standard Linux driver to support Cisco/Aironet ISA and PCI 802.11 wireless cards. @@ -388,6 +389,7 @@ config PCMCIA_SPECTRUM config AIRO_CS tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards" depends on NET_RADIO && PCMCIA && (BROKEN || !M32R) + select CRYPTO ---help--- This is the standard Linux driver to support Cisco/Aironet PCMCIA 802.11 wireless cards. This driver is the same as the Aironet diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index a4c7ae94614d..9c577f7b6e58 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -87,14 +88,6 @@ static struct pci_driver airo_driver = { #include #endif -/* Support Cisco MIC feature */ -#define MICSUPPORT - -#if defined(MICSUPPORT) && !defined(CONFIG_CRYPTO) -#warning MIC support requires Crypto API -#undef MICSUPPORT -#endif - /* Hack to do some power saving */ #define POWER_ON_DOWN @@ -1118,7 +1111,6 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp); static int writerids(struct net_device *dev, aironet_ioctl *comp); static int flashcard(struct net_device *dev, aironet_ioctl *comp); #endif /* CISCO_EXT */ -#ifdef MICSUPPORT static void micinit(struct airo_info *ai); static int micsetup(struct airo_info *ai); static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len); @@ -1127,9 +1119,6 @@ static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi); static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm); -#include -#endif - struct airo_info { struct net_device_stats stats; struct net_device *dev; @@ -1190,12 +1179,10 @@ struct airo_info { unsigned long scan_timestamp; /* Time started to scan */ struct iw_spy_data spy_data; struct iw_public_data wireless_data; -#ifdef MICSUPPORT /* MIC stuff */ struct crypto_tfm *tfm; mic_module mod[2]; mic_statistics micstats; -#endif HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors HostTxDesc txfids[MPI_MAX_FIDS]; HostRidDesc config_desc; @@ -1229,7 +1216,6 @@ static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime); static int flashputbuf(struct airo_info *ai); static int flashrestart(struct airo_info *ai,struct net_device *dev); -#ifdef MICSUPPORT /*********************************************************************** * MIC ROUTINES * *********************************************************************** @@ -1686,7 +1672,6 @@ static void emmh32_final(emmh32_context *context, u8 digest[4]) digest[2] = (val>>8) & 0xFF; digest[3] = val & 0xFF; } -#endif static int readBSSListRid(struct airo_info *ai, int first, BSSListRid *list) { @@ -2005,7 +1990,6 @@ static int mpi_send_packet (struct net_device *dev) * Firmware automaticly puts 802 header on so * we don't need to account for it in the length */ -#ifdef MICSUPPORT if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && (ntohs(((u16 *)buffer)[6]) != 0x888E)) { MICBuffer pMic; @@ -2022,9 +2006,7 @@ static int mpi_send_packet (struct net_device *dev) memcpy (sendbuf, &pMic, sizeof(pMic)); sendbuf += sizeof(pMic); memcpy (sendbuf, buffer, len - sizeof(etherHead)); - } else -#endif - { + } else { *payloadLen = cpu_to_le16(len - sizeof(etherHead)); dev->trans_start = jiffies; @@ -2400,9 +2382,7 @@ void stop_airo_card( struct net_device *dev, int freeres ) ai->shared, ai->shared_dma); } } -#ifdef MICSUPPORT crypto_free_tfm(ai->tfm); -#endif del_airo_dev( dev ); free_netdev( dev ); } @@ -2726,9 +2706,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, ai->thr_pid = kernel_thread(airo_thread, dev, CLONE_FS | CLONE_FILES); if (ai->thr_pid < 0) goto err_out_free; -#ifdef MICSUPPORT ai->tfm = NULL; -#endif rc = add_airo_dev( dev ); if (rc) goto err_out_thr; @@ -2969,10 +2947,8 @@ static int airo_thread(void *data) { airo_read_wireless_stats(ai); else if (test_bit(JOB_PROMISC, &ai->flags)) airo_set_promisc(ai); -#ifdef MICSUPPORT else if (test_bit(JOB_MIC, &ai->flags)) micinit(ai); -#endif else if (test_bit(JOB_EVENT, &ai->flags)) airo_send_event(dev); else if (test_bit(JOB_AUTOWEP, &ai->flags)) @@ -3010,12 +2986,10 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) if ( status & EV_MIC ) { OUT4500( apriv, EVACK, EV_MIC ); -#ifdef MICSUPPORT if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) { set_bit(JOB_MIC, &apriv->flags); wake_up_interruptible(&apriv->thr_wait); } -#endif } if ( status & EV_LINK ) { union iwreq_data wrqu; @@ -3194,11 +3168,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) } bap_read (apriv, buffer + hdrlen/2, len, BAP0); } else { -#ifdef MICSUPPORT MICBuffer micbuf; -#endif bap_read (apriv, buffer, ETH_ALEN*2, BAP0); -#ifdef MICSUPPORT if (apriv->micstats.enabled) { bap_read (apriv,(u16*)&micbuf,sizeof(micbuf),BAP0); if (ntohs(micbuf.typelen) > 0x05DC) @@ -3211,15 +3182,10 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) skb_trim (skb, len + hdrlen); } } -#endif bap_read(apriv,buffer+ETH_ALEN,len,BAP0); -#ifdef MICSUPPORT if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) { badmic: dev_kfree_skb_irq (skb); -#else - if (0) { -#endif badrx: OUT4500( apriv, EVACK, EV_RX); goto exitrx; @@ -3430,10 +3396,8 @@ static void mpi_receive_802_3(struct airo_info *ai) int len = 0; struct sk_buff *skb; char *buffer; -#ifdef MICSUPPORT int off = 0; MICBuffer micbuf; -#endif memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd)); /* Make sure we got something */ @@ -3448,7 +3412,6 @@ static void mpi_receive_802_3(struct airo_info *ai) goto badrx; } buffer = skb_put(skb,len); -#ifdef MICSUPPORT memcpy(buffer, ai->rxfids[0].virtual_host_addr, ETH_ALEN * 2); if (ai->micstats.enabled) { memcpy(&micbuf, @@ -3470,9 +3433,6 @@ badmic: dev_kfree_skb_irq (skb); goto badrx; } -#else - memcpy(buffer, ai->rxfids[0].virtual_host_addr, len); -#endif #ifdef WIRELESS_SPY if (ai->spy_data.spy_number > 0) { char *sa; @@ -3689,13 +3649,11 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) ai->config.authType = AUTH_OPEN; ai->config.modulation = MOD_CCK; -#ifdef MICSUPPORT if ((cap_rid.len>=sizeof(cap_rid)) && (cap_rid.extSoftCap&1) && (micsetup(ai) == SUCCESS)) { ai->config.opmode |= MODE_MIC; set_bit(FLAG_MIC_CAPABLE, &ai->flags); } -#endif /* Save off the MAC */ for( i = 0; i < ETH_ALEN; i++ ) { @@ -4170,15 +4128,12 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket) } len -= ETH_ALEN * 2; -#ifdef MICSUPPORT if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && (ntohs(((u16 *)pPacket)[6]) != 0x888E)) { if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS) return ERROR; miclen = sizeof(pMic); } -#endif - // packet is destination[6], source[6], payload[len-12] // write the payload length and dst/src/payload if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR; @@ -7270,13 +7225,11 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { case AIROGSTAT: ridcode = RID_STATUS; break; case AIROGSTATSD32: ridcode = RID_STATSDELTA; break; case AIROGSTATSC32: ridcode = RID_STATS; break; -#ifdef MICSUPPORT case AIROGMICSTATS: if (copy_to_user(comp->data, &ai->micstats, min((int)comp->len,(int)sizeof(ai->micstats)))) return -EFAULT; return 0; -#endif case AIRORRID: ridcode = comp->ridnum; break; default: return -EINVAL; @@ -7308,9 +7261,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { static int writerids(struct net_device *dev, aironet_ioctl *comp) { struct airo_info *ai = dev->priv; int ridcode; -#ifdef MICSUPPORT int enabled; -#endif Resp rsp; static int (* writer)(struct airo_info *, u16 rid, const void *, int, int); unsigned char *iobuf; @@ -7367,11 +7318,9 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) { PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,RIDSIZE, 1); -#ifdef MICSUPPORT enabled = ai->micstats.enabled; memset(&ai->micstats,0,sizeof(ai->micstats)); ai->micstats.enabled = enabled; -#endif if (copy_to_user(comp->data, iobuf, min((int)comp->len, (int)RIDSIZE))) { -- cgit v1.2.3-59-g8ed1b From 3c398b8612b210a159ec7ba5e5c3c341fb0d5eab Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 21 Jan 2006 01:36:36 +0100 Subject: [PATCH] drivers/net/wireless/ipw2100.c: make ipw2100_wpa_assoc_frame() static This patch makes the needlessly global ipw2100_wpa_assoc_frame() static. Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 6290c9f7e939..31c262c314ca 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -5771,8 +5771,8 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value) return ret; } -void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv, - char *wpa_ie, int wpa_ie_len) +static void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv, + char *wpa_ie, int wpa_ie_len) { struct ipw2100_wpa_assoc_frame frame; -- cgit v1.2.3-59-g8ed1b From a73e22b286bd162d10526521b34f2d6f37aac635 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 21 Jan 2006 01:39:42 +0100 Subject: [PATCH] drivers/net/wireless/ipw2200: possible cleanups This patch contains the following possible cleanups: - make needlessly global functions static - "extern inline" -> "static inline" - #if 0 the unused global function ipw_led_activity_on() Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 33 ++++++++++++++++++--------------- drivers/net/wireless/ipw2200.h | 4 ++-- 2 files changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 916b24c544e2..2a834deb60e8 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -701,7 +701,7 @@ static void ipw_init_ordinals(struct ipw_priv *priv) } -u32 ipw_register_toggle(u32 reg) +static u32 ipw_register_toggle(u32 reg) { reg &= ~IPW_START_STANDBY; if (reg & IPW_GATE_ODMA) @@ -726,7 +726,7 @@ u32 ipw_register_toggle(u32 reg) #define LD_TIME_LINK_OFF 2700 #define LD_TIME_ACT_ON 250 -void ipw_led_link_on(struct ipw_priv *priv) +static void ipw_led_link_on(struct ipw_priv *priv) { unsigned long flags; u32 led; @@ -769,7 +769,7 @@ static void ipw_bg_led_link_on(void *data) up(&priv->sem); } -void ipw_led_link_off(struct ipw_priv *priv) +static void ipw_led_link_off(struct ipw_priv *priv) { unsigned long flags; u32 led; @@ -847,6 +847,7 @@ static void __ipw_led_activity_on(struct ipw_priv *priv) } } +#if 0 void ipw_led_activity_on(struct ipw_priv *priv) { unsigned long flags; @@ -854,8 +855,9 @@ void ipw_led_activity_on(struct ipw_priv *priv) __ipw_led_activity_on(priv); spin_unlock_irqrestore(&priv->lock, flags); } +#endif /* 0 */ -void ipw_led_activity_off(struct ipw_priv *priv) +static void ipw_led_activity_off(struct ipw_priv *priv) { unsigned long flags; u32 led; @@ -890,7 +892,7 @@ static void ipw_bg_led_activity_off(void *data) up(&priv->sem); } -void ipw_led_band_on(struct ipw_priv *priv) +static void ipw_led_band_on(struct ipw_priv *priv) { unsigned long flags; u32 led; @@ -925,7 +927,7 @@ void ipw_led_band_on(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -void ipw_led_band_off(struct ipw_priv *priv) +static void ipw_led_band_off(struct ipw_priv *priv) { unsigned long flags; u32 led; @@ -948,24 +950,24 @@ void ipw_led_band_off(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -void ipw_led_radio_on(struct ipw_priv *priv) +static void ipw_led_radio_on(struct ipw_priv *priv) { ipw_led_link_on(priv); } -void ipw_led_radio_off(struct ipw_priv *priv) +static void ipw_led_radio_off(struct ipw_priv *priv) { ipw_led_activity_off(priv); ipw_led_link_off(priv); } -void ipw_led_link_up(struct ipw_priv *priv) +static void ipw_led_link_up(struct ipw_priv *priv) { /* Set the Link Led on for all nic types */ ipw_led_link_on(priv); } -void ipw_led_link_down(struct ipw_priv *priv) +static void ipw_led_link_down(struct ipw_priv *priv) { ipw_led_activity_off(priv); ipw_led_link_off(priv); @@ -974,7 +976,7 @@ void ipw_led_link_down(struct ipw_priv *priv) ipw_led_radio_off(priv); } -void ipw_led_init(struct ipw_priv *priv) +static void ipw_led_init(struct ipw_priv *priv) { priv->nic_type = priv->eeprom[EEPROM_NIC_TYPE]; @@ -1025,7 +1027,7 @@ void ipw_led_init(struct ipw_priv *priv) } } -void ipw_led_shutdown(struct ipw_priv *priv) +static void ipw_led_shutdown(struct ipw_priv *priv) { ipw_led_activity_off(priv); ipw_led_link_off(priv); @@ -6204,7 +6206,8 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value) return ret; } -void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len) +static void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, + int wpa_ie_len) { /* make sure WPA is enabled */ ipw_wpa_enable(priv, 1); @@ -10059,7 +10062,7 @@ static void ipw_bg_rf_kill(void *data) up(&priv->sem); } -void ipw_link_up(struct ipw_priv *priv) +static void ipw_link_up(struct ipw_priv *priv) { priv->last_seq_num = -1; priv->last_frag_num = -1; @@ -10094,7 +10097,7 @@ static void ipw_bg_link_up(void *data) up(&priv->sem); } -void ipw_link_down(struct ipw_priv *priv) +static void ipw_link_down(struct ipw_priv *priv) { ipw_led_link_down(priv); netif_carrier_off(priv->net_dev); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index e65620a4d79e..e2afa76ad3cd 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -852,7 +852,7 @@ struct ipw_scan_request_ext { u16 dwell_time[IPW_SCAN_TYPES]; } __attribute__ ((packed)); -extern inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index) +static inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index) { if (index % 2) return scan->scan_type[index / 2] & 0x0F; @@ -860,7 +860,7 @@ extern inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index) return (scan->scan_type[index / 2] & 0xF0) >> 4; } -extern inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan, +static inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan, u8 index, u8 scan_type) { if (index % 2) -- cgit v1.2.3-59-g8ed1b From cbbdd03fadeddd02efec05ccfd4e6870ed913762 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 13:48:53 +0800 Subject: [PATCH] ipw2100: Add LEAP authentication algorithm support Signed-off-by: Hong Liu Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2100.c | 12 +++++++++--- drivers/net/wireless/ipw2100.h | 6 ++++-- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 31c262c314ca..b73af7789588 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -5365,9 +5365,12 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode) SEC_LEVEL_0, 0, 1); } else { auth_mode = IPW_AUTH_OPEN; - if ((priv->ieee->sec.flags & SEC_AUTH_MODE) && - (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY)) - auth_mode = IPW_AUTH_SHARED; + if (priv->ieee->sec.flags & SEC_AUTH_MODE) { + if (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY) + auth_mode = IPW_AUTH_SHARED; + else if (priv->ieee->sec.auth_mode == WLAN_AUTH_LEAP) + auth_mode = IPW_AUTH_LEAP_CISCO_ID; + } sec_level = SEC_LEVEL_0; if (priv->ieee->sec.flags & SEC_LEVEL) @@ -5760,6 +5763,9 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value) } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) { sec.auth_mode = WLAN_AUTH_OPEN; ieee->open_wep = 1; + } else if (value & IW_AUTH_ALG_LEAP) { + sec.auth_mode = WLAN_AUTH_LEAP; + ieee->open_wep = 1; } else return -EINVAL; diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index f6c51441fa87..51360910d222 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -392,8 +392,10 @@ struct ipw2100_notification { #define IPW_WEP104_CIPHER (1<<5) #define IPW_CKIP_CIPHER (1<<6) -#define IPW_AUTH_OPEN 0 -#define IPW_AUTH_SHARED 1 +#define IPW_AUTH_OPEN 0 +#define IPW_AUTH_SHARED 1 +#define IPW_AUTH_LEAP 2 +#define IPW_AUTH_LEAP_CISCO_ID 0x80 struct statistic { int value; -- cgit v1.2.3-59-g8ed1b From 3173ca0b76879be1fb7af826ae4ce7ee733159ce Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 13:49:01 +0800 Subject: [PATCH] ipw2100: Make iwconfig txpower setting consistent with user input Signed-off-by: Hong Liu Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2100.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index b73af7789588..80bfc1cf142f 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -5107,12 +5107,13 @@ static int ipw2100_set_tx_power(struct ipw2100_priv *priv, u32 tx_power) .host_command_length = 4 }; int err = 0; + u32 tmp = tx_power; if (tx_power != IPW_TX_POWER_DEFAULT) - tx_power = (tx_power - IPW_TX_POWER_MIN_DBM) * 16 / - (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM); + tmp = (tx_power - IPW_TX_POWER_MIN_DBM) * 16 / + (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM); - cmd.host_command_parameters[0] = tx_power; + cmd.host_command_parameters[0] = tmp; if (priv->ieee->iw_mode == IW_MODE_ADHOC) err = ipw2100_hw_send_command(priv, &cmd); -- cgit v1.2.3-59-g8ed1b From be6b3b15b511aededd89d1ebbc7b25d0edd1ccd3 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 13:49:08 +0800 Subject: [PATCH] ipw2100: Add generic geo information This patch fixes a BUG_ON for the latest ieee80211 change. Signed-off-by: Hong Liu Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2100.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 80bfc1cf142f..b560f5c763e0 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -1672,6 +1672,18 @@ static int ipw2100_start_scan(struct ipw2100_priv *priv) return err; } +static const struct ieee80211_geo ipw_geos[] = { + { /* Restricted */ + "---", + .bg_channels = 14, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}, {2467, 12}, + {2472, 13}, {2484, 14}}, + }, +}; + static int ipw2100_up(struct ipw2100_priv *priv, int deferred) { unsigned long flags; @@ -1727,6 +1739,13 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) goto exit; } + /* Initialize the geo */ + if (ieee80211_set_geo(priv->ieee, &ipw_geos[0])) { + printk(KERN_WARNING DRV_NAME "Could not set geo\n"); + return 0; + } + priv->ieee->freq_band = IEEE80211_24GHZ_BAND; + lock = LOCK_NONE; if (ipw2100_set_ordinal(priv, IPW_ORD_PERS_DB_LOCK, &lock, &ord_len)) { printk(KERN_ERR DRV_NAME -- cgit v1.2.3-59-g8ed1b From 8ed55a482e2f044bfb044295ee86ecd5744c9911 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 13:49:20 +0800 Subject: [PATCH] ipw2100: remove white space and better format the code Signed-off-by: James Ketrenos Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index b560f5c763e0..8393512da3a2 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -3769,7 +3769,7 @@ static ssize_t store_memory(struct device *d, struct device_attribute *attr, struct net_device *dev = priv->net_dev; const char *p = buf; - (void) dev; /* kill unused-var warning for debug-only code */ + (void)dev; /* kill unused-var warning for debug-only code */ if (count < 1) return count; @@ -4089,7 +4089,7 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, unsigned long val; char *p = buffer; - (void) dev; /* kill unused-var warning for debug-only code */ + (void)dev; /* kill unused-var warning for debug-only code */ IPW_DEBUG_INFO("enter\n"); -- cgit v1.2.3-59-g8ed1b From 71aa122d8a510b79338e28e2d56326574642d000 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:08:55 +0800 Subject: [PATCH] increase ipw2100 driver version to git-1.1.4 Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 8393512da3a2..eb79198ac450 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -167,7 +167,7 @@ that only one external action is invoked at a time. #include "ipw2100.h" -#define IPW2100_VERSION "1.1.3" +#define IPW2100_VERSION "git-1.1.4" #define DRV_NAME "ipw2100" #define DRV_VERSION IPW2100_VERSION -- cgit v1.2.3-59-g8ed1b From c8fe6679086a983c4c95a441f3246c7aaecab80a Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:36:36 +0800 Subject: [PATCH] ipw2200: Fix indirect SRAM/register 8/16-bit write routines The indirect SRAM/register 8/16-bit write routines are broken for non-dword-aligned destination addresses. Fortunately, these routines are, so far, not used for non-dword-aligned destinations, but here's a patch that fixes them, anyway. The attached patch also adds comments for all direct/indirect I/O routine variations. Signed-off-by: Ben M Cahill Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 86 ++++++++++++++++++++++++++++++++++-------- drivers/net/wireless/ipw2200.h | 13 +++---- 2 files changed, 76 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 2a834deb60e8..d7d24b6facfe 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -227,12 +227,15 @@ static int snprintk_buf(u8 * output, size_t size, const u8 * data, size_t len) return total; } +/* alias for 32-bit indirect read (for SRAM/reg above 4K), with debug wrapper */ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg); #define ipw_read_reg32(a, b) _ipw_read_reg32(a, b) +/* alias for 8-bit indirect read (for SRAM/reg above 4K), with debug wrapper */ static u8 _ipw_read_reg8(struct ipw_priv *ipw, u32 reg); #define ipw_read_reg8(a, b) _ipw_read_reg8(a, b) +/* 8-bit indirect write (for SRAM/reg above 4K), with debug wrapper */ static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value); static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c) { @@ -241,6 +244,7 @@ static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c) _ipw_write_reg8(a, b, c); } +/* 16-bit indirect write (for SRAM/reg above 4K), with debug wrapper */ static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value); static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c) { @@ -249,6 +253,7 @@ static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c) _ipw_write_reg16(a, b, c); } +/* 32-bit indirect write (for SRAM/reg above 4K), with debug wrapper */ static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value); static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c) { @@ -257,48 +262,76 @@ static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c) _ipw_write_reg32(a, b, c); } +/* 8-bit direct write (low 4K) */ #define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs)) + +/* 8-bit direct write (for low 4K of SRAM/regs), with debug wrapper */ #define ipw_write8(ipw, ofs, val) \ IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ _ipw_write8(ipw, ofs, val) + +/* 16-bit direct write (low 4K) */ #define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs)) + +/* 16-bit direct write (for low 4K of SRAM/regs), with debug wrapper */ #define ipw_write16(ipw, ofs, val) \ IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ _ipw_write16(ipw, ofs, val) + +/* 32-bit direct write (low 4K) */ #define _ipw_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs)) + +/* 32-bit direct write (for low 4K of SRAM/regs), with debug wrapper */ #define ipw_write32(ipw, ofs, val) \ IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ _ipw_write32(ipw, ofs, val) + +/* 8-bit direct read (low 4K) */ #define _ipw_read8(ipw, ofs) readb((ipw)->hw_base + (ofs)) + +/* 8-bit direct read (low 4K), with debug wrapper */ static inline u8 __ipw_read8(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) { IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", f, l, (u32) (ofs)); return _ipw_read8(ipw, ofs); } +/* alias to 8-bit direct read (low 4K of SRAM/regs), with debug wrapper */ #define ipw_read8(ipw, ofs) __ipw_read8(__FILE__, __LINE__, ipw, ofs) + +/* 16-bit direct read (low 4K) */ #define _ipw_read16(ipw, ofs) readw((ipw)->hw_base + (ofs)) + +/* 16-bit direct read (low 4K), with debug wrapper */ static inline u16 __ipw_read16(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) { IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", f, l, (u32) (ofs)); return _ipw_read16(ipw, ofs); } +/* alias to 16-bit direct read (low 4K of SRAM/regs), with debug wrapper */ #define ipw_read16(ipw, ofs) __ipw_read16(__FILE__, __LINE__, ipw, ofs) + +/* 32-bit direct read (low 4K) */ #define _ipw_read32(ipw, ofs) readl((ipw)->hw_base + (ofs)) + +/* 32-bit direct read (low 4K), with debug wrapper */ static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) { IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", f, l, (u32) (ofs)); return _ipw_read32(ipw, ofs); } +/* alias to 32-bit direct read (low 4K of SRAM/regs), with debug wrapper */ #define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs) + +/* multi-byte read (above 4K), with debug wrapper */ static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int); static inline void __ipw_read_indirect(const char *f, int l, struct ipw_priv *a, u32 b, u8 * c, int d) @@ -308,15 +341,17 @@ static inline void __ipw_read_indirect(const char *f, int l, _ipw_read_indirect(a, b, c, d); } +/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */ #define ipw_read_indirect(a, b, c, d) __ipw_read_indirect(__FILE__, __LINE__, a, b, c, d) +/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data, int num); #define ipw_write_indirect(a, b, c, d) \ IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \ _ipw_write_indirect(a, b, c, d) -/* indirect write s */ +/* 32-bit indirect write (above 4K) */ static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value) { IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value); @@ -324,22 +359,30 @@ static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value) _ipw_write32(priv, IPW_INDIRECT_DATA, value); } +/* 8-bit indirect write (above 4K) */ static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value) { + u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */ + u32 dif_len = reg - aligned_addr; + IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); - _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); - _ipw_write8(priv, IPW_INDIRECT_DATA, value); + _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); + _ipw_write8(priv, IPW_INDIRECT_DATA + dif_len, value); } +/* 16-bit indirect write (above 4K) */ static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) { + u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */ + u32 dif_len = (reg - aligned_addr) & (~0x1ul); + IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); - _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); - _ipw_write16(priv, IPW_INDIRECT_DATA, value); + _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); + _ipw_write16(priv, IPW_INDIRECT_DATA + dif_len, value); } -/* indirect read s */ +/* 8-bit indirect read (above 4K) */ static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) { u32 word; @@ -349,6 +392,7 @@ static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) return (word >> ((reg & 0x3) * 8)) & 0xff; } +/* 32-bit indirect read (above 4K) */ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) { u32 value; @@ -361,11 +405,12 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) return value; } -/* iterative/auto-increment 32 bit reads and writes */ +/* General purpose, no alignment requirement, iterative (multi-byte) read, */ +/* for area above 1st 4K of SRAM/reg space */ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, int num) { - u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; + u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */ u32 dif_len = addr - aligned_addr; u32 i; @@ -375,7 +420,7 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, return; } - /* Read the first nibble byte by byte */ + /* Read the first dword (or portion) byte by byte */ if (unlikely(dif_len)) { _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); /* Start reading at aligned_addr + dif_len */ @@ -384,11 +429,12 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, aligned_addr += 4; } + /* Read all of the middle dwords as dwords, with auto-increment */ _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) *(u32 *) buf = _ipw_read32(priv, IPW_AUTOINC_DATA); - /* Copy the last nibble */ + /* Read the last dword (or portion) byte by byte */ if (unlikely(num)) { _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); for (i = 0; num > 0; i++, num--) @@ -396,10 +442,12 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, } } +/* General purpose, no alignment requirement, iterative (multi-byte) write, */ +/* for area above 1st 4K of SRAM/reg space */ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, int num) { - u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; + u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */ u32 dif_len = addr - aligned_addr; u32 i; @@ -409,20 +457,21 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, return; } - /* Write the first nibble byte by byte */ + /* Write the first dword (or portion) byte by byte */ if (unlikely(dif_len)) { _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); - /* Start reading at aligned_addr + dif_len */ + /* Start writing at aligned_addr + dif_len */ for (i = dif_len; ((i < 4) && (num > 0)); i++, num--, buf++) _ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf); aligned_addr += 4; } + /* Write all of the middle dwords as dwords, with auto-increment */ _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) _ipw_write32(priv, IPW_AUTOINC_DATA, *(u32 *) buf); - /* Copy the last nibble */ + /* Write the last dword (or portion) byte by byte */ if (unlikely(num)) { _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); for (i = 0; num > 0; i++, num--, buf++) @@ -430,17 +479,21 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, } } +/* General purpose, no alignment requirement, iterative (multi-byte) write, */ +/* for 1st 4K of SRAM/regs space */ static void ipw_write_direct(struct ipw_priv *priv, u32 addr, void *buf, int num) { memcpy_toio((priv->hw_base + addr), buf, num); } +/* Set bit(s) in low 4K of SRAM/regs */ static inline void ipw_set_bit(struct ipw_priv *priv, u32 reg, u32 mask) { ipw_write32(priv, reg, ipw_read32(priv, reg) | mask); } +/* Clear bit(s) in low 4K of SRAM/regs */ static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask) { ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask); @@ -1076,6 +1129,7 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, static inline u32 ipw_get_event_log_len(struct ipw_priv *priv) { + /* length = 1st dword in log */ return ipw_read_reg32(priv, ipw_read32(priv, IPW_EVENT_LOG)); } @@ -2892,8 +2946,8 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) mdelay(1); /* enable ucode store */ - ipw_write_reg8(priv, DINO_CONTROL_REG, 0x0); - ipw_write_reg8(priv, DINO_CONTROL_REG, DINO_ENABLE_CS); + ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0x0); + ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, DINO_ENABLE_CS); mdelay(1); /* write ucode */ diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index e2afa76ad3cd..44ff76386a8e 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1406,13 +1406,6 @@ do { if (ipw_debug_level & (level)) \ * Register bit definitions */ -/* Dino control registers bits */ - -#define DINO_ENABLE_SYSTEM 0x80 -#define DINO_ENABLE_CS 0x40 -#define DINO_RXFIFO_DATA 0x01 -#define DINO_CONTROL_REG 0x00200000 - #define IPW_INTA_RW 0x00000008 #define IPW_INTA_MASK_R 0x0000000C #define IPW_INDIRECT_ADDR 0x00000010 @@ -1459,6 +1452,12 @@ do { if (ipw_debug_level & (level)) \ #define IPW_DOMAIN_0_END 0x1000 #define CLX_MEM_BAR_SIZE 0x1000 + +/* Dino/baseband control registers bits */ + +#define DINO_ENABLE_SYSTEM 0x80 /* 1 = baseband processor on, 0 = reset */ +#define DINO_ENABLE_CS 0x40 /* 1 = enable ucode load */ +#define DINO_RXFIFO_DATA 0x01 /* 1 = data available */ #define IPW_BASEBAND_CONTROL_STATUS 0X00200000 #define IPW_BASEBAND_TX_FIFO_WRITE 0X00200004 #define IPW_BASEBAND_RX_FIFO_READ 0X00200004 -- cgit v1.2.3-59-g8ed1b From f516dbcd7df76d468be98c343bc22e86ab7207fc Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:36:44 +0800 Subject: [PATCH] ipw2200: Mask out the WEP_KEY command dump from debug log for security reason Signed-off-by: Nick Kralevich Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index d7d24b6facfe..b40bfa063725 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1953,7 +1953,14 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) IPW_DEBUG_HC("%s command (#%d) %d bytes: 0x%08X\n", get_cmd_string(cmd->cmd), cmd->cmd, cmd->len, priv->status); - printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len); + +#ifndef DEBUG_CMD_WEP_KEY + if (cmd->cmd == IPW_CMD_WEP_KEY) + IPW_DEBUG_HC("WEP_KEY command masked out for secure.\n"); + else +#endif + printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len); + rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0); if (rc) { -- cgit v1.2.3-59-g8ed1b From 3e234b4e5768b4f783fc45f20be8c6515b875f17 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:36:52 +0800 Subject: [PATCH] ipw2200: Add LEAP authentication algorithm support Signed-off-by: Hong Liu Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 18 ++++++++++++------ drivers/net/wireless/ipw2200.h | 7 ++++--- 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index b40bfa063725..671631831226 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -6256,6 +6256,9 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value) } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) { sec.auth_mode = WLAN_AUTH_OPEN; ieee->open_wep = 1; + } else if (value & IW_AUTH_ALG_LEAP) { + sec.auth_mode = WLAN_AUTH_LEAP; + ieee->open_wep = 1; } else return -EINVAL; @@ -7116,19 +7119,22 @@ static int ipw_associate_network(struct ipw_priv *priv, memset(&priv->assoc_request, 0, sizeof(priv->assoc_request)); priv->assoc_request.channel = network->channel; + priv->assoc_request.auth_key = 0; + if ((priv->capability & CAP_PRIVACY_ON) && - (priv->capability & CAP_SHARED_KEY)) { + (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY)) { priv->assoc_request.auth_type = AUTH_SHARED_KEY; priv->assoc_request.auth_key = priv->ieee->sec.active_key; - if ((priv->capability & CAP_PRIVACY_ON) && - (priv->ieee->sec.level == SEC_LEVEL_1) && + if ((priv->ieee->sec.level == SEC_LEVEL_1) && !(priv->ieee->host_encrypt || priv->ieee->host_decrypt)) ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); - } else { + + } else if ((priv->capability & CAP_PRIVACY_ON) && + (priv->ieee->sec.auth_mode == WLAN_AUTH_LEAP)) + priv->assoc_request.auth_type = AUTH_LEAP; + else priv->assoc_request.auth_type = AUTH_OPEN; - priv->assoc_request.auth_key = 0; - } if (priv->ieee->wpa_ie_len) { priv->assoc_request.policy_support = 0x02; /* RSN active */ diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 44ff76386a8e..5f32834745b5 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1657,9 +1657,10 @@ enum { IPW_FW_ERROR_FATAL_ERROR }; -#define AUTH_OPEN 0 -#define AUTH_SHARED_KEY 1 -#define AUTH_IGNORE 3 +#define AUTH_OPEN 0 +#define AUTH_SHARED_KEY 1 +#define AUTH_LEAP 2 +#define AUTH_IGNORE 3 #define HC_ASSOCIATE 0 #define HC_REASSOCIATE 1 -- cgit v1.2.3-59-g8ed1b From 810dabd466fe70869b66ab64dd326b6153cef645 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:36:59 +0800 Subject: [PATCH] ipw2200: Bluetooth coexistence support I've added a new module param "bt_coexist" which defaults to OFF. This does not seem to fix the firmware restarts, but it does do "the right thing" and disables something that we were enabling by default: signaling the Bluetooth h/w which channel we're on (whether or not the BT h/w was out there). Signed-off-by: Ben M Cahill Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 20 +++++++++++++++++++- drivers/net/wireless/ipw2200.h | 35 +++++++++++++++++++++-------------- 2 files changed, 40 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 671631831226..e6a23c2be1af 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -55,6 +55,7 @@ static int associate = 1; static int auto_create = 1; static int led = 0; static int disable = 0; +static int bt_coexist = 0; static int hwcrypto = 1; static const char ipw_modes[] = { 'a', 'b', 'g', '?' @@ -9656,7 +9657,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) static void init_sys_config(struct ipw_sys_config *sys_config) { memset(sys_config, 0, sizeof(struct ipw_sys_config)); - sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */ + sys_config->bt_coexistence = 0; sys_config->answer_broadcast_ssid_probe = 0; sys_config->accept_all_data_frames = 0; sys_config->accept_non_directed_frames = 1; @@ -10362,6 +10363,20 @@ static int ipw_config(struct ipw_priv *priv) /* set basic system config settings */ init_sys_config(&priv->sys_config); + + /* Support Bluetooth if we have BT h/w on board, and user wants to. + * Does not support BT priority yet (don't abort or defer our Tx) */ + if (bt_coexist) { + unsigned char bt_caps = priv->eeprom[EEPROM_SKU_CAPABILITY]; + + if (bt_caps & EEPROM_SKU_CAP_BT_CHANNEL_SIG) + priv->sys_config.bt_coexistence + |= CFG_BT_COEXISTENCE_SIGNAL_CHNL; + if (bt_caps & EEPROM_SKU_CAP_BT_OOB) + priv->sys_config.bt_coexistence + |= CFG_BT_COEXISTENCE_OOB; + } + if (priv->ieee->iw_mode == IW_MODE_ADHOC) priv->sys_config.answer_broadcast_ssid_probe = 1; else @@ -11351,6 +11366,9 @@ module_param(mode, int, 0444); MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); #endif +module_param(bt_coexist, int, 0444); +MODULE_PARM_DESC(bt_coexist, "enable bluetooth coexistence (default off)"); + module_param(hwcrypto, int, 0444); MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default on)"); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 5f32834745b5..d6d7d9db0462 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1566,13 +1566,18 @@ do { if (ipw_debug_level & (level)) \ #define EEPROM_BSS_CHANNELS_BG (GET_EEPROM_ADDR(0x2c,LSB)) /* 2 bytes */ #define EEPROM_HW_VERSION (GET_EEPROM_ADDR(0x72,LSB)) /* 2 bytes */ -/* NIC type as found in the one byte EEPROM_NIC_TYPE offset*/ +/* NIC type as found in the one byte EEPROM_NIC_TYPE offset */ #define EEPROM_NIC_TYPE_0 0 #define EEPROM_NIC_TYPE_1 1 #define EEPROM_NIC_TYPE_2 2 #define EEPROM_NIC_TYPE_3 3 #define EEPROM_NIC_TYPE_4 4 +/* Bluetooth Coexistence capabilities as found in EEPROM_SKU_CAPABILITY */ +#define EEPROM_SKU_CAP_BT_CHANNEL_SIG 0x01 /* we can tell BT our channel # */ +#define EEPROM_SKU_CAP_BT_PRIORITY 0x02 /* BT can take priority over us */ +#define EEPROM_SKU_CAP_BT_OOB 0x04 /* we can signal BT out-of-band */ + #define FW_MEM_REG_LOWER_BOUND 0x00300000 #define FW_MEM_REG_EEPROM_ACCESS (FW_MEM_REG_LOWER_BOUND + 0x40) #define IPW_EVENT_REG (FW_MEM_REG_LOWER_BOUND + 0x04) @@ -1869,21 +1874,23 @@ struct ipw_cmd_log { struct host_cmd cmd; }; -#define CFG_BT_COEXISTENCE_MIN 0x00 -#define CFG_BT_COEXISTENCE_DEFER 0x02 -#define CFG_BT_COEXISTENCE_KILL 0x04 -#define CFG_BT_COEXISTENCE_WME_OVER_BT 0x08 -#define CFG_BT_COEXISTENCE_OOB 0x10 -#define CFG_BT_COEXISTENCE_MAX 0xFF -#define CFG_BT_COEXISTENCE_DEF 0x80 /* read Bt from EEPROM */ - -#define CFG_CTS_TO_ITSELF_ENABLED_MIN 0x0 -#define CFG_CTS_TO_ITSELF_ENABLED_MAX 0x1 +/* SysConfig command parameters ... */ +/* bt_coexistence param */ +#define CFG_BT_COEXISTENCE_SIGNAL_CHNL 0x01 /* tell BT our chnl # */ +#define CFG_BT_COEXISTENCE_DEFER 0x02 /* defer our Tx if BT traffic */ +#define CFG_BT_COEXISTENCE_KILL 0x04 /* kill our Tx if BT traffic */ +#define CFG_BT_COEXISTENCE_WME_OVER_BT 0x08 /* multimedia extensions */ +#define CFG_BT_COEXISTENCE_OOB 0x10 /* signal BT via out-of-band */ + +/* clear-to-send to self param */ +#define CFG_CTS_TO_ITSELF_ENABLED_MIN 0x00 +#define CFG_CTS_TO_ITSELF_ENABLED_MAX 0x01 #define CFG_CTS_TO_ITSELF_ENABLED_DEF CFG_CTS_TO_ITSELF_ENABLED_MIN -#define CFG_SYS_ANTENNA_BOTH 0x000 -#define CFG_SYS_ANTENNA_A 0x001 -#define CFG_SYS_ANTENNA_B 0x003 +/* Antenna diversity param (h/w can select best antenna, based on signal) */ +#define CFG_SYS_ANTENNA_BOTH 0x00 /* NIC selects best antenna */ +#define CFG_SYS_ANTENNA_A 0x01 /* force antenna A */ +#define CFG_SYS_ANTENNA_B 0x03 /* force antenna B */ /* * The definitions below were lifted off the ipw2100 driver, which only -- cgit v1.2.3-59-g8ed1b From c7b6a6744c3eb878e08ef992d57cd01eed457810 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:37:05 +0800 Subject: [PATCH] ipw2200: use jiffies_to_msec() wherever possible This substitutes Linux jiffies_to_msec() wherever there is a computation for determining milliseconds from jiffies, following lead from ieee80211 code. And it does a little cleanup. "it's" == "it is" ... "its" == possessive "it". Indulge me. ;-) Signed-off-by: Cahill, Ben M Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 30 ++++++++++++++++-------------- drivers/net/wireless/ipw2200.h | 1 + 2 files changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index e6a23c2be1af..d3aa59d0461c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -2112,8 +2112,8 @@ static void ipw_scan_check(void *data) struct ipw_priv *priv = data; if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) { IPW_DEBUG_SCAN("Scan completion watchdog resetting " - "adapter (%dms).\n", - IPW_SCAN_CHECK_WATCHDOG / 100); + "adapter after (%dms).\n", + jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG)); queue_work(priv->workqueue, &priv->adapter_restart); } } @@ -2518,7 +2518,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv) /* If the data looks correct, then copy it to our private copy. Otherwise let the firmware know to perform the operation - on it's own + on its own. */ if ((priv->eeprom + EEPROM_VERSION) != 0) { IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n"); @@ -2836,6 +2836,7 @@ static inline int ipw_alive(struct ipw_priv *priv) return ipw_read32(priv, 0x90) == 0xd55555d5; } +/* timeout in msec, attempted in 10-msec quanta */ static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, int timeout) { @@ -2864,10 +2865,11 @@ static int ipw_stop_master(struct ipw_priv *priv) /* stop master. typical delay - 0 */ ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); + /* timeout is in msec, polled in 10-msec quanta */ rc = ipw_poll_bit(priv, IPW_RESET_REG, IPW_RESET_REG_MASTER_DISABLED, 100); if (rc < 0) { - IPW_ERROR("stop master failed in 10ms\n"); + IPW_ERROR("wait for stop master failed after 100ms\n"); return -1; } @@ -3100,7 +3102,7 @@ static int ipw_stop_nic(struct ipw_priv *priv) rc = ipw_poll_bit(priv, IPW_RESET_REG, IPW_RESET_REG_MASTER_DISABLED, 500); if (rc < 0) { - IPW_ERROR("wait for reg master disabled failed\n"); + IPW_ERROR("wait for reg master disabled failed after 500ms\n"); return rc; } @@ -3362,7 +3364,7 @@ static int ipw_load(struct ipw_priv *priv) /* kick start the device */ ipw_start_nic(priv); - /* wait for the device to finish it's initial startup sequence */ + /* wait for the device to finish its initial startup sequence */ rc = ipw_poll_bit(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); if (rc < 0) { @@ -3426,7 +3428,7 @@ static int ipw_load(struct ipw_priv *priv) rc = ipw_poll_bit(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); if (rc < 0) { - IPW_ERROR("device failed to start after 500ms\n"); + IPW_ERROR("device failed to start within 500ms\n"); goto error; } IPW_DEBUG_INFO("device response after %dms\n", rc); @@ -4981,7 +4983,7 @@ static void ipw_bg_rx_queue_replenish(void *data) } /* Assumes that the skb field of the buffers in 'pool' is kept accurate. - * If an SKB has been detached, the POOL needs to have it's SKB set to NULL + * If an SKB has been detached, the POOL needs to have its SKB set to NULL * This free routine walks the list of POOL entries and if SKB is set to * non NULL it is unmapped and freed */ @@ -5321,10 +5323,10 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, if (priv->ieee->scan_age != 0 && time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " - "because of age: %lums.\n", + "because of age: %ums.\n", escape_essid(network->ssid, network->ssid_len), MAC_ARG(network->bssid), - 1000 * (jiffies - network->last_scanned) / HZ); + jiffies_to_msecs(jiffies - network->last_scanned)); return 0; } @@ -5531,11 +5533,11 @@ static int ipw_best_network(struct ipw_priv *priv, if (network->last_associate && time_after(network->last_associate + (HZ * 3UL), jiffies)) { IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " - "because of storming (%lus since last " + "because of storming (%ums since last " "assoc attempt).\n", escape_essid(network->ssid, network->ssid_len), MAC_ARG(network->bssid), - (jiffies - network->last_associate) / HZ); + jiffies_to_msecs(jiffies - network->last_associate)); return 0; } @@ -5543,10 +5545,10 @@ static int ipw_best_network(struct ipw_priv *priv, if (priv->ieee->scan_age != 0 && time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " - "because of age: %lums.\n", + "because of age: %ums.\n", escape_essid(network->ssid, network->ssid_len), MAC_ARG(network->bssid), - 1000 * (jiffies - network->last_scanned) / HZ); + jiffies_to_msecs(jiffies - network->last_scanned)); return 0; } diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index d6d7d9db0462..04a0c26cab84 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -46,6 +46,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3-59-g8ed1b From ede6111cae6a83fbb0b6b621b4333d1a3983c089 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:37:10 +0800 Subject: [PATCH] ipw2200: Make LED blinking frequency independent of HZ Signed-off-by: Clemens Buchacher . Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index d3aa59d0461c..37cd71cd1144 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -776,9 +776,9 @@ static u32 ipw_register_toggle(u32 reg) * - On radio OFF, turn off any LEDs started during radio on * */ -#define LD_TIME_LINK_ON 300 -#define LD_TIME_LINK_OFF 2700 -#define LD_TIME_ACT_ON 250 +#define LD_TIME_LINK_ON msecs_to_jiffies(300) +#define LD_TIME_LINK_OFF msecs_to_jiffies(2700) +#define LD_TIME_ACT_ON msecs_to_jiffies(250) static void ipw_led_link_on(struct ipw_priv *priv) { -- cgit v1.2.3-59-g8ed1b From 4bfdb91dcff0dd4b70922de263ccffffb8fb1d16 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:37:16 +0800 Subject: [PATCH] ipw2200: add module parameter to enable/disable roaming Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 37cd71cd1144..624f29500490 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -57,6 +57,7 @@ static int led = 0; static int disable = 0; static int bt_coexist = 0; static int hwcrypto = 1; +static int roaming = 1; static const char ipw_modes[] = { 'a', 'b', 'g', '?' }; @@ -4187,8 +4188,9 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, return; } - if (missed_count > priv->roaming_threshold && - missed_count <= priv->disassociate_threshold) { + if (roaming && + (missed_count > priv->roaming_threshold && + missed_count <= priv->disassociate_threshold)) { /* If we are not already roaming, set the ROAM * bit in the status and kick off a scan. * This can happen several times before we reach @@ -4216,7 +4218,6 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, } IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count); - } /** @@ -11378,5 +11379,8 @@ module_param(cmdlog, int, 0444); MODULE_PARM_DESC(cmdlog, "allocate a ring buffer for logging firmware commands"); +module_param(roaming, int, 0444); +MODULE_PARM_DESC(roaming, "enable roaming support (default on)"); + module_exit(ipw_exit); module_init(ipw_init); -- cgit v1.2.3-59-g8ed1b From 397ae121ee0116d3b4125d621f0ef528d1d52580 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:37:22 +0800 Subject: [PATCH] ipw2200: Scale firmware loading watchdog with the firmware size I can't really help with why restarts happen, but the following patch greatly increases the likelihood that a firmware reload will succeed afterward on my thinkpad. It addresses two issues. First, sysfs module loading and hotplug are asynchronous, and as such file operations on the "loading" and "data" files are racy when you load 2 firmwares in quick succession. Second, the timeout for DMAing the firmware needs to scale with the size of the firmware being loaded. That is, the watchdog needs to be on throughput, not on time alone. I no longer get the firmware load errors, though this is at best a hacky workaround for a racy interface. (Obviously, this does nothing to address the fatal errors in firmware which cause reloads; it just causes the initial loading and the reloads to work more often.) Signed-off-by: Peter Jones Signed-off-by: Ben M Cahill Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 114 +++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 624f29500490..c42eb54f379a 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -2772,22 +2772,25 @@ static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, static int ipw_fw_dma_wait(struct ipw_priv *priv) { - u32 current_index = 0; + u32 current_index = 0, previous_index; u32 watchdog = 0; IPW_DEBUG_FW(">> : \n"); current_index = ipw_fw_dma_command_block_index(priv); - IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%8X\n", + IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n", (int)priv->sram_desc.last_cb_index); while (current_index < priv->sram_desc.last_cb_index) { udelay(50); + previous_index = current_index; current_index = ipw_fw_dma_command_block_index(priv); - watchdog++; - - if (watchdog > 400) { + if (previous_index < current_index) { + watchdog = 0; + continue; + } + if (++watchdog > 400) { IPW_DEBUG_FW_INFO("Timeout\n"); ipw_fw_dma_dump_command_block(priv); ipw_fw_dma_abort(priv); @@ -3276,55 +3279,31 @@ static int ipw_load(struct ipw_priv *priv) const struct firmware *firmware = NULL; const struct firmware *ucode = NULL; #endif + char *ucode_name; + char *fw_name; int rc = 0, retries = 3; -#ifdef CONFIG_PM - if (!fw_loaded) { -#endif - rc = ipw_get_fw(priv, &bootfw, IPW_FW_NAME("boot")); - if (rc) - goto error; - - switch (priv->ieee->iw_mode) { - case IW_MODE_ADHOC: - rc = ipw_get_fw(priv, &ucode, - IPW_FW_NAME("ibss_ucode")); - if (rc) - goto error; - - rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("ibss")); - break; - + switch (priv->ieee->iw_mode) { + case IW_MODE_ADHOC: + ucode_name = IPW_FW_NAME("ibss_ucode"); + fw_name = IPW_FW_NAME("ibss"); + break; #ifdef CONFIG_IPW2200_MONITOR - case IW_MODE_MONITOR: - rc = ipw_get_fw(priv, &ucode, - IPW_FW_NAME("sniffer_ucode")); - if (rc) - goto error; - - rc = ipw_get_fw(priv, &firmware, - IPW_FW_NAME("sniffer")); - break; + case IW_MODE_MONITOR: + ucode_name = IPW_FW_NAME("sniffer_ucode"); + fw_name = IPW_FW_NAME("sniffer"); + break; #endif - case IW_MODE_INFRA: - rc = ipw_get_fw(priv, &ucode, IPW_FW_NAME("bss_ucode")); - if (rc) - goto error; - - rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("bss")); - break; - - default: - rc = -EINVAL; - } - - if (rc) - goto error; - -#ifdef CONFIG_PM - fw_loaded = 1; + case IW_MODE_INFRA: + ucode_name = IPW_FW_NAME("bss_ucode"); + fw_name = IPW_FW_NAME("bss"); + break; + default: + rc = -EINVAL; } -#endif + + if (rc < 0) + goto error; if (!priv->rxq) priv->rxq = ipw_rx_queue_alloc(priv); @@ -3346,7 +3325,7 @@ static int ipw_load(struct ipw_priv *priv) ipw_stop_nic(priv); rc = ipw_reset_nic(priv); - if (rc) { + if (rc < 0) { IPW_ERROR("Unable to reset NIC\n"); goto error; } @@ -3354,6 +3333,15 @@ static int ipw_load(struct ipw_priv *priv) ipw_zero_memory(priv, IPW_NIC_SRAM_LOWER_BOUND, IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); +#ifdef CONFIG_PM + if (!fw_loaded) { +#endif + rc = ipw_get_fw(priv, &bootfw, IPW_FW_NAME("boot")); + if (rc < 0) + goto error; +#ifdef CONFIG_PM + } +#endif /* DMA the initial boot firmware into the device */ rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header), bootfw->size - sizeof(struct fw_header)); @@ -3377,6 +3365,16 @@ static int ipw_load(struct ipw_priv *priv) /* ack fw init done interrupt */ ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); +#ifdef CONFIG_PM + if (!fw_loaded) { +#endif + rc = ipw_get_fw(priv, &ucode, ucode_name); + if (rc < 0) + goto error; +#ifdef CONFIG_PM + } +#endif + /* DMA the ucode into the device */ rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header), ucode->size - sizeof(struct fw_header)); @@ -3388,6 +3386,16 @@ static int ipw_load(struct ipw_priv *priv) /* stop nic */ ipw_stop_nic(priv); +#ifdef CONFIG_PM + if (!fw_loaded) { +#endif + rc = ipw_get_fw(priv, &firmware, fw_name); + if (rc < 0) + goto error; +#ifdef CONFIG_PM + } +#endif + /* DMA bss firmware into the device */ rc = ipw_load_firmware(priv, firmware->data + sizeof(struct fw_header), @@ -3397,10 +3405,14 @@ static int ipw_load(struct ipw_priv *priv) goto error; } +#ifdef CONFIG_PM + fw_loaded = 1; +#endif + ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0); rc = ipw_queue_reset(priv); - if (rc) { + if (rc < 0) { IPW_ERROR("Unable to initialize queues\n"); goto error; } -- cgit v1.2.3-59-g8ed1b From 0a7bcf261ea584c87a9cee4523023fa74168de4a Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:37:28 +0800 Subject: [PATCH] ipw2200: stack reduction Checking the stack usage of my kernel, showed that ipw2200 had a few bad offenders. This is on i386 32-bit: 0x00002876 ipw_send_associate: 544 0x000028ee ipw_send_associate: 544 0x000027dc ipw_send_scan_request_ext: 520 0x00002864 ipw_set_sensitivity: 520 0x00005eac ipw_set_rsn_capa: 520 The reason is the host_cmd structure is large (500 bytes). All other functions currently using ipw_send_cmd() suffer from the same problem. This patch introduces ipw_send_cmd_simple() for commands with no data transfer, and ipw_send_cmd_pdu() for commands with a data payload and makes the payload a pointer to the buffer passed in from the caller. As an added bonus, the diffstat looks like this: ipw2200.c | 260 +++++++++++++++++++++----------------------------------------- ipw2200.h | 2 2 files changed, 92 insertions(+), 170 deletions(-) and it shrinks the module a lot as well: Before: text data bss dec hex filename 75177 2472 44 77693 12f7d drivers/net/wireless/ipw2200.ko After: text data bss dec hex filename 61363 2488 44 63895 f997 drivers/net/wireless/ipw2200.ko So about a ~18% reduction in module size. Signed-off-by: Jens Axboe Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 253 +++++++++++++++-------------------------- drivers/net/wireless/ipw2200.h | 2 +- 2 files changed, 91 insertions(+), 164 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index c42eb54f379a..2fe1e048328e 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1928,7 +1928,8 @@ static char *get_cmd_string(u8 cmd) } #define HOST_COMPLETE_TIMEOUT HZ -static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) + +static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) { int rc = 0; unsigned long flags; @@ -1964,7 +1965,7 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len); - rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0); + rc = ipw_queue_tx_hcmd(priv, cmd->cmd, cmd->param, cmd->len, 0); if (rc) { priv->status &= ~STATUS_HCMD_ACTIVE; IPW_ERROR("Failed to send %s: Reason %d\n", @@ -1999,7 +2000,7 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) goto exit; } - exit: +exit: if (priv->cmdlog) { priv->cmdlog[priv->cmdlog_pos++].retcode = rc; priv->cmdlog_pos %= priv->cmdlog_len; @@ -2007,61 +2008,62 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) return rc; } -static int ipw_send_host_complete(struct ipw_priv *priv) +static int ipw_send_cmd_simple(struct ipw_priv *priv, u8 command) +{ + struct host_cmd cmd = { + .cmd = command, + }; + + return __ipw_send_cmd(priv, &cmd); +} + +static int ipw_send_cmd_pdu(struct ipw_priv *priv, u8 command, u8 len, + void *data) { struct host_cmd cmd = { - .cmd = IPW_CMD_HOST_COMPLETE, - .len = 0 + .cmd = command, + .len = len, + .param = data, }; + return __ipw_send_cmd(priv, &cmd); +} + +static int ipw_send_host_complete(struct ipw_priv *priv) +{ if (!priv) { IPW_ERROR("Invalid args\n"); return -1; } - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE); } static int ipw_send_system_config(struct ipw_priv *priv, struct ipw_sys_config *config) { - struct host_cmd cmd = { - .cmd = IPW_CMD_SYSTEM_CONFIG, - .len = sizeof(*config) - }; - if (!priv || !config) { IPW_ERROR("Invalid args\n"); return -1; } - memcpy(cmd.param, config, sizeof(*config)); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, sizeof(*config), + config); } static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) { - struct host_cmd cmd = { - .cmd = IPW_CMD_SSID, - .len = min(len, IW_ESSID_MAX_SIZE) - }; - if (!priv || !ssid) { IPW_ERROR("Invalid args\n"); return -1; } - memcpy(cmd.param, ssid, cmd.len); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_SSID, min(len, IW_ESSID_MAX_SIZE), + ssid); } static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) { - struct host_cmd cmd = { - .cmd = IPW_CMD_ADAPTER_ADDRESS, - .len = ETH_ALEN - }; - if (!priv || !mac) { IPW_ERROR("Invalid args\n"); return -1; @@ -2070,8 +2072,8 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) IPW_DEBUG_INFO("%s: Setting MAC to " MAC_FMT "\n", priv->net_dev->name, MAC_ARG(mac)); - memcpy(cmd.param, mac, ETH_ALEN); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, + mac); } /* @@ -2130,51 +2132,40 @@ static void ipw_bg_scan_check(void *data) static int ipw_send_scan_request_ext(struct ipw_priv *priv, struct ipw_scan_request_ext *request) { - struct host_cmd cmd = { - .cmd = IPW_CMD_SCAN_REQUEST_EXT, - .len = sizeof(*request) - }; - - memcpy(cmd.param, request, sizeof(*request)); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_SCAN_REQUEST_EXT, + sizeof(*request), request); } static int ipw_send_scan_abort(struct ipw_priv *priv) { - struct host_cmd cmd = { - .cmd = IPW_CMD_SCAN_ABORT, - .len = 0 - }; - if (!priv) { IPW_ERROR("Invalid args\n"); return -1; } - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_simple(priv, IPW_CMD_SCAN_ABORT); } static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens) { - struct host_cmd cmd = { - .cmd = IPW_CMD_SENSITIVITY_CALIB, - .len = sizeof(struct ipw_sensitivity_calib) + struct ipw_sensitivity_calib calib = { + .beacon_rssi_raw = sens, }; - struct ipw_sensitivity_calib *calib = (struct ipw_sensitivity_calib *) - &cmd.param; - calib->beacon_rssi_raw = sens; - return ipw_send_cmd(priv, &cmd); + + return ipw_send_cmd_pdu(priv, IPW_CMD_SENSITIVITY_CALIB, sizeof(calib), + &calib); } static int ipw_send_associate(struct ipw_priv *priv, struct ipw_associate *associate) { - struct host_cmd cmd = { - .cmd = IPW_CMD_ASSOCIATE, - .len = sizeof(*associate) - }; - struct ipw_associate tmp_associate; + + if (!priv || !associate) { + IPW_ERROR("Invalid args\n"); + return -1; + } + memcpy(&tmp_associate, associate, sizeof(*associate)); tmp_associate.policy_support = cpu_to_le16(tmp_associate.policy_support); @@ -2187,80 +2178,56 @@ static int ipw_send_associate(struct ipw_priv *priv, cpu_to_le16(tmp_associate.beacon_interval); tmp_associate.atim_window = cpu_to_le16(tmp_associate.atim_window); - if (!priv || !associate) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - memcpy(cmd.param, &tmp_associate, sizeof(*associate)); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_ASSOCIATE, sizeof(tmp_associate), + &tmp_associate); } static int ipw_send_supported_rates(struct ipw_priv *priv, struct ipw_supported_rates *rates) { - struct host_cmd cmd = { - .cmd = IPW_CMD_SUPPORTED_RATES, - .len = sizeof(*rates) - }; - if (!priv || !rates) { IPW_ERROR("Invalid args\n"); return -1; } - memcpy(cmd.param, rates, sizeof(*rates)); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_SUPPORTED_RATES, sizeof(*rates), + rates); } static int ipw_set_random_seed(struct ipw_priv *priv) { - struct host_cmd cmd = { - .cmd = IPW_CMD_SEED_NUMBER, - .len = sizeof(u32) - }; + u32 val; if (!priv) { IPW_ERROR("Invalid args\n"); return -1; } - get_random_bytes(&cmd.param, sizeof(u32)); + get_random_bytes(&val, sizeof(val)); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_SEED_NUMBER, sizeof(val), &val); } static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) { - struct host_cmd cmd = { - .cmd = IPW_CMD_CARD_DISABLE, - .len = sizeof(u32) - }; - if (!priv) { IPW_ERROR("Invalid args\n"); return -1; } - *((u32 *) & cmd.param) = phy_off; - - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(phy_off), + &phy_off); } static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) { - struct host_cmd cmd = { - .cmd = IPW_CMD_TX_POWER, - .len = sizeof(*power) - }; - if (!priv || !power) { IPW_ERROR("Invalid args\n"); return -1; } - memcpy(cmd.param, power, sizeof(*power)); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_TX_POWER, sizeof(*power), + power); } static int ipw_set_tx_power(struct ipw_priv *priv) @@ -2312,18 +2279,14 @@ static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts) struct ipw_rts_threshold rts_threshold = { .rts_threshold = rts, }; - struct host_cmd cmd = { - .cmd = IPW_CMD_RTS_THRESHOLD, - .len = sizeof(rts_threshold) - }; if (!priv) { IPW_ERROR("Invalid args\n"); return -1; } - memcpy(cmd.param, &rts_threshold, sizeof(rts_threshold)); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_RTS_THRESHOLD, + sizeof(rts_threshold), &rts_threshold); } static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) @@ -2331,27 +2294,19 @@ static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) struct ipw_frag_threshold frag_threshold = { .frag_threshold = frag, }; - struct host_cmd cmd = { - .cmd = IPW_CMD_FRAG_THRESHOLD, - .len = sizeof(frag_threshold) - }; if (!priv) { IPW_ERROR("Invalid args\n"); return -1; } - memcpy(cmd.param, &frag_threshold, sizeof(frag_threshold)); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_FRAG_THRESHOLD, + sizeof(frag_threshold), &frag_threshold); } static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) { - struct host_cmd cmd = { - .cmd = IPW_CMD_POWER_MODE, - .len = sizeof(u32) - }; - u32 *param = (u32 *) (&cmd.param); + u32 param; if (!priv) { IPW_ERROR("Invalid args\n"); @@ -2362,17 +2317,18 @@ static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) * level */ switch (mode) { case IPW_POWER_BATTERY: - *param = IPW_POWER_INDEX_3; + param = IPW_POWER_INDEX_3; break; case IPW_POWER_AC: - *param = IPW_POWER_MODE_CAM; + param = IPW_POWER_MODE_CAM; break; default: - *param = mode; + param = mode; break; } - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param), + ¶m); } static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) @@ -2381,18 +2337,14 @@ static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) .short_retry_limit = slimit, .long_retry_limit = llimit }; - struct host_cmd cmd = { - .cmd = IPW_CMD_RETRY_LIMIT, - .len = sizeof(retry_limit) - }; if (!priv) { IPW_ERROR("Invalid args\n"); return -1; } - memcpy(cmd.param, &retry_limit, sizeof(retry_limit)); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_RETRY_LIMIT, sizeof(retry_limit), + &retry_limit); } /* @@ -5750,54 +5702,44 @@ static void ipw_adhoc_create(struct ipw_priv *priv, static void ipw_send_tgi_tx_key(struct ipw_priv *priv, int type, int index) { - struct ipw_tgi_tx_key *key; - struct host_cmd cmd = { - .cmd = IPW_CMD_TGI_TX_KEY, - .len = sizeof(*key) - }; + struct ipw_tgi_tx_key key; if (!(priv->ieee->sec.flags & (1 << index))) return; - key = (struct ipw_tgi_tx_key *)&cmd.param; - key->key_id = index; - memcpy(key->key, priv->ieee->sec.keys[index], SCM_TEMPORAL_KEY_LENGTH); - key->security_type = type; - key->station_index = 0; /* always 0 for BSS */ - key->flags = 0; + key.key_id = index; + memcpy(key.key, priv->ieee->sec.keys[index], SCM_TEMPORAL_KEY_LENGTH); + key.security_type = type; + key.station_index = 0; /* always 0 for BSS */ + key.flags = 0; /* 0 for new key; previous value of counter (after fatal error) */ - key->tx_counter[0] = 0; - key->tx_counter[1] = 0; + key.tx_counter[0] = 0; + key.tx_counter[1] = 0; - ipw_send_cmd(priv, &cmd); + ipw_send_cmd_pdu(priv, IPW_CMD_TGI_TX_KEY, sizeof(key), &key); } static void ipw_send_wep_keys(struct ipw_priv *priv, int type) { - struct ipw_wep_key *key; + struct ipw_wep_key key; int i; - struct host_cmd cmd = { - .cmd = IPW_CMD_WEP_KEY, - .len = sizeof(*key) - }; - key = (struct ipw_wep_key *)&cmd.param; - key->cmd_id = DINO_CMD_WEP_KEY; - key->seq_num = 0; + key.cmd_id = DINO_CMD_WEP_KEY; + key.seq_num = 0; /* Note: AES keys cannot be set for multiple times. * Only set it at the first time. */ for (i = 0; i < 4; i++) { - key->key_index = i | type; + key.key_index = i | type; if (!(priv->ieee->sec.flags & (1 << i))) { - key->key_size = 0; + key.key_size = 0; continue; } - key->key_size = priv->ieee->sec.key_sizes[i]; - memcpy(key->key, priv->ieee->sec.keys[i], key->key_size); + key.key_size = priv->ieee->sec.key_sizes[i]; + memcpy(key.key, priv->ieee->sec.keys[i], key.key_size); - ipw_send_cmd(priv, &cmd); + ipw_send_cmd_pdu(priv, IPW_CMD_WEP_KEY, sizeof(key), &key); } } @@ -6298,15 +6240,10 @@ static void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, static int ipw_set_rsn_capa(struct ipw_priv *priv, char *capabilities, int length) { - struct host_cmd cmd = { - .cmd = IPW_CMD_RSN_CAPABILITIES, - .len = length, - }; - IPW_DEBUG_HC("HOST_CMD_RSN_CAPABILITIES\n"); - memcpy(cmd.param, capabilities, length); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_RSN_CAPABILITIES, length, + capabilities); } /* @@ -7093,25 +7030,15 @@ static int ipw_handle_assoc_response(struct net_device *dev, static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters *qos_param) { - struct host_cmd cmd = { - .cmd = IPW_CMD_QOS_PARAMETERS, - .len = (sizeof(struct ieee80211_qos_parameters) * 3) - }; - - memcpy(cmd.param, qos_param, sizeof(*qos_param) * 3); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_QOS_PARAMETERS, qos_param, + sizeof(*qos_param) * 3); } static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element *qos_param) { - struct host_cmd cmd = { - .cmd = IPW_CMD_WME_INFO, - .len = sizeof(*qos_param) - }; - - memcpy(cmd.param, qos_param, sizeof(*qos_param)); - return ipw_send_cmd(priv, &cmd); + return ipw_send_cmd_pdu(priv, IPW_CMD_WME_INFO, qos_param, + sizeof(*qos_param)); } #endif /* CONFIG_IPW_QOS */ diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 04a0c26cab84..c09888b1f1f8 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1866,7 +1866,7 @@ struct host_cmd { u8 cmd; u8 len; u16 reserved; - u32 param[TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH]; + u32 *param; } __attribute__ ((packed)); struct ipw_cmd_log { -- cgit v1.2.3-59-g8ed1b From 4e22699fa264b88084210ceaa63747b8352bd517 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:37:36 +0800 Subject: [PATCH] ipw2200: Fix qos_cmd param switch bug The patch fixes a couple of errors regarding QoS, which results in compile warnings and malfunction of the driver. Signed-off-by: Henrik Brix Andersen Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 2fe1e048328e..072746c07a9c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7030,15 +7030,15 @@ static int ipw_handle_assoc_response(struct net_device *dev, static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters *qos_param) { - return ipw_send_cmd_pdu(priv, IPW_CMD_QOS_PARAMETERS, qos_param, - sizeof(*qos_param) * 3); + return ipw_send_cmd_pdu(priv, IPW_CMD_QOS_PARAMETERS, + sizeof(*qos_param) * 3, qos_param); } static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element *qos_param) { - return ipw_send_cmd_pdu(priv, IPW_CMD_WME_INFO, qos_param, - sizeof(*qos_param)); + return ipw_send_cmd_pdu(priv, IPW_CMD_WME_INFO, sizeof(*qos_param), + qos_param); } #endif /* CONFIG_IPW_QOS */ -- cgit v1.2.3-59-g8ed1b From 7c97eb3f1dd09548fe7167e684da4fc94580aceb Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:37:47 +0800 Subject: [PATCH] ipw2200: increase ipw2200 driver version increase ipw2200 driver version to git-1.0.10 Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 072746c07a9c..7d61257249aa 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -33,7 +33,7 @@ #include "ipw2200.h" #include -#define IPW2200_VERSION "git-1.0.8" +#define IPW2200_VERSION "git-1.0.10" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation" #define DRV_VERSION IPW2200_VERSION -- cgit v1.2.3-59-g8ed1b From 2638bc394195f27801d1c184c4358ce25599146b Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:37:52 +0800 Subject: [PATCH] ipw2200: remove white space and better format the code Signed-off-by: James Ketrenos Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 62 ++++++++++++++++++------------------------ drivers/net/wireless/ipw2200.h | 29 ++++++++++---------- 2 files changed, 41 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 7d61257249aa..f793cd8f8d71 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -272,7 +272,6 @@ static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c) IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ _ipw_write8(ipw, ofs, val) - /* 16-bit direct write (low 4K) */ #define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs)) @@ -281,7 +280,6 @@ static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c) IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ _ipw_write16(ipw, ofs, val) - /* 32-bit direct write (low 4K) */ #define _ipw_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs)) @@ -290,7 +288,6 @@ static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c) IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ _ipw_write32(ipw, ofs, val) - /* 8-bit direct read (low 4K) */ #define _ipw_read8(ipw, ofs) readb((ipw)->hw_base + (ofs)) @@ -304,7 +301,6 @@ static inline u8 __ipw_read8(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) /* alias to 8-bit direct read (low 4K of SRAM/regs), with debug wrapper */ #define ipw_read8(ipw, ofs) __ipw_read8(__FILE__, __LINE__, ipw, ofs) - /* 16-bit direct read (low 4K) */ #define _ipw_read16(ipw, ofs) readw((ipw)->hw_base + (ofs)) @@ -318,7 +314,6 @@ static inline u16 __ipw_read16(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) /* alias to 16-bit direct read (low 4K of SRAM/regs), with debug wrapper */ #define ipw_read16(ipw, ofs) __ipw_read16(__FILE__, __LINE__, ipw, ofs) - /* 32-bit direct read (low 4K) */ #define _ipw_read32(ipw, ofs) readl((ipw)->hw_base + (ofs)) @@ -332,7 +327,6 @@ static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) /* alias to 32-bit direct read (low 4K of SRAM/regs), with debug wrapper */ #define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs) - /* multi-byte read (above 4K), with debug wrapper */ static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int); static inline void __ipw_read_indirect(const char *f, int l, @@ -364,7 +358,7 @@ static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value) /* 8-bit indirect write (above 4K) */ static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value) { - u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */ + u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */ u32 dif_len = reg - aligned_addr; IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); @@ -375,7 +369,7 @@ static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value) /* 16-bit indirect write (above 4K) */ static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) { - u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */ + u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */ u32 dif_len = (reg - aligned_addr) & (~0x1ul); IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); @@ -383,7 +377,6 @@ static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) _ipw_write16(priv, IPW_INDIRECT_DATA + dif_len, value); } - /* 8-bit indirect read (above 4K) */ static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) { @@ -412,7 +405,7 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, int num) { - u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */ + u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */ u32 dif_len = addr - aligned_addr; u32 i; @@ -449,7 +442,7 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, int num) { - u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */ + u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */ u32 dif_len = addr - aligned_addr; u32 i; @@ -1964,7 +1957,6 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) #endif printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len); - rc = ipw_queue_tx_hcmd(priv, cmd->cmd, cmd->param, cmd->len, 0); if (rc) { priv->status &= ~STATUS_HCMD_ACTIVE; @@ -2000,7 +1992,7 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) goto exit; } -exit: + exit: if (priv->cmdlog) { priv->cmdlog[priv->cmdlog_pos++].retcode = rc; priv->cmdlog_pos %= priv->cmdlog_len; @@ -2048,7 +2040,7 @@ static int ipw_send_system_config(struct ipw_priv *priv, } return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, sizeof(*config), - config); + config); } static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) @@ -2059,7 +2051,7 @@ static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) } return ipw_send_cmd_pdu(priv, IPW_CMD_SSID, min(len, IW_ESSID_MAX_SIZE), - ssid); + ssid); } static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) @@ -2072,8 +2064,7 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) IPW_DEBUG_INFO("%s: Setting MAC to " MAC_FMT "\n", priv->net_dev->name, MAC_ARG(mac)); - return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, - mac); + return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, mac); } /* @@ -2133,7 +2124,7 @@ static int ipw_send_scan_request_ext(struct ipw_priv *priv, struct ipw_scan_request_ext *request) { return ipw_send_cmd_pdu(priv, IPW_CMD_SCAN_REQUEST_EXT, - sizeof(*request), request); + sizeof(*request), request); } static int ipw_send_scan_abort(struct ipw_priv *priv) @@ -2153,7 +2144,7 @@ static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens) }; return ipw_send_cmd_pdu(priv, IPW_CMD_SENSITIVITY_CALIB, sizeof(calib), - &calib); + &calib); } static int ipw_send_associate(struct ipw_priv *priv, @@ -2179,7 +2170,7 @@ static int ipw_send_associate(struct ipw_priv *priv, tmp_associate.atim_window = cpu_to_le16(tmp_associate.atim_window); return ipw_send_cmd_pdu(priv, IPW_CMD_ASSOCIATE, sizeof(tmp_associate), - &tmp_associate); + &tmp_associate); } static int ipw_send_supported_rates(struct ipw_priv *priv, @@ -2191,7 +2182,7 @@ static int ipw_send_supported_rates(struct ipw_priv *priv, } return ipw_send_cmd_pdu(priv, IPW_CMD_SUPPORTED_RATES, sizeof(*rates), - rates); + rates); } static int ipw_set_random_seed(struct ipw_priv *priv) @@ -2216,7 +2207,7 @@ static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) } return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(phy_off), - &phy_off); + &phy_off); } static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) @@ -2226,8 +2217,7 @@ static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) return -1; } - return ipw_send_cmd_pdu(priv, IPW_CMD_TX_POWER, sizeof(*power), - power); + return ipw_send_cmd_pdu(priv, IPW_CMD_TX_POWER, sizeof(*power), power); } static int ipw_set_tx_power(struct ipw_priv *priv) @@ -2328,7 +2318,7 @@ static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) } return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param), - ¶m); + ¶m); } static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) @@ -2344,7 +2334,7 @@ static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) } return ipw_send_cmd_pdu(priv, IPW_CMD_RETRY_LIMIT, sizeof(retry_limit), - &retry_limit); + &retry_limit); } /* @@ -3326,7 +3316,7 @@ static int ipw_load(struct ipw_priv *priv) #ifdef CONFIG_PM } #endif - + /* DMA the ucode into the device */ rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header), ucode->size - sizeof(struct fw_header)); @@ -3356,7 +3346,6 @@ static int ipw_load(struct ipw_priv *priv) IPW_ERROR("Unable to load firmware: %d\n", rc); goto error; } - #ifdef CONFIG_PM fw_loaded = 1; #endif @@ -5291,7 +5280,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, "because of age: %ums.\n", escape_essid(network->ssid, network->ssid_len), MAC_ARG(network->bssid), - jiffies_to_msecs(jiffies - network->last_scanned)); + jiffies_to_msecs(jiffies - + network->last_scanned)); return 0; } @@ -5502,7 +5492,8 @@ static int ipw_best_network(struct ipw_priv *priv, "assoc attempt).\n", escape_essid(network->ssid, network->ssid_len), MAC_ARG(network->bssid), - jiffies_to_msecs(jiffies - network->last_associate)); + jiffies_to_msecs(jiffies - + network->last_associate)); return 0; } @@ -5513,7 +5504,8 @@ static int ipw_best_network(struct ipw_priv *priv, "because of age: %ums.\n", escape_essid(network->ssid, network->ssid_len), MAC_ARG(network->bssid), - jiffies_to_msecs(jiffies - network->last_scanned)); + jiffies_to_msecs(jiffies - + network->last_scanned)); return 0; } @@ -6243,7 +6235,7 @@ static int ipw_set_rsn_capa(struct ipw_priv *priv, IPW_DEBUG_HC("HOST_CMD_RSN_CAPABILITIES\n"); return ipw_send_cmd_pdu(priv, IPW_CMD_RSN_CAPABILITIES, length, - capabilities); + capabilities); } /* @@ -10309,14 +10301,14 @@ static int ipw_config(struct ipw_priv *priv) /* Support Bluetooth if we have BT h/w on board, and user wants to. * Does not support BT priority yet (don't abort or defer our Tx) */ if (bt_coexist) { - unsigned char bt_caps = priv->eeprom[EEPROM_SKU_CAPABILITY]; + unsigned char bt_caps = priv->eeprom[EEPROM_SKU_CAPABILITY]; if (bt_caps & EEPROM_SKU_CAP_BT_CHANNEL_SIG) priv->sys_config.bt_coexistence - |= CFG_BT_COEXISTENCE_SIGNAL_CHNL; + |= CFG_BT_COEXISTENCE_SIGNAL_CHNL; if (bt_caps & EEPROM_SKU_CAP_BT_OOB) priv->sys_config.bt_coexistence - |= CFG_BT_COEXISTENCE_OOB; + |= CFG_BT_COEXISTENCE_OOB; } if (priv->ieee->iw_mode == IW_MODE_ADHOC) diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index c09888b1f1f8..eedd347b892e 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1453,12 +1453,11 @@ do { if (ipw_debug_level & (level)) \ #define IPW_DOMAIN_0_END 0x1000 #define CLX_MEM_BAR_SIZE 0x1000 - /* Dino/baseband control registers bits */ -#define DINO_ENABLE_SYSTEM 0x80 /* 1 = baseband processor on, 0 = reset */ -#define DINO_ENABLE_CS 0x40 /* 1 = enable ucode load */ -#define DINO_RXFIFO_DATA 0x01 /* 1 = data available */ +#define DINO_ENABLE_SYSTEM 0x80 /* 1 = baseband processor on, 0 = reset */ +#define DINO_ENABLE_CS 0x40 /* 1 = enable ucode load */ +#define DINO_RXFIFO_DATA 0x01 /* 1 = data available */ #define IPW_BASEBAND_CONTROL_STATUS 0X00200000 #define IPW_BASEBAND_TX_FIFO_WRITE 0X00200004 #define IPW_BASEBAND_RX_FIFO_READ 0X00200004 @@ -1575,9 +1574,9 @@ do { if (ipw_debug_level & (level)) \ #define EEPROM_NIC_TYPE_4 4 /* Bluetooth Coexistence capabilities as found in EEPROM_SKU_CAPABILITY */ -#define EEPROM_SKU_CAP_BT_CHANNEL_SIG 0x01 /* we can tell BT our channel # */ -#define EEPROM_SKU_CAP_BT_PRIORITY 0x02 /* BT can take priority over us */ -#define EEPROM_SKU_CAP_BT_OOB 0x04 /* we can signal BT out-of-band */ +#define EEPROM_SKU_CAP_BT_CHANNEL_SIG 0x01 /* we can tell BT our channel # */ +#define EEPROM_SKU_CAP_BT_PRIORITY 0x02 /* BT can take priority over us */ +#define EEPROM_SKU_CAP_BT_OOB 0x04 /* we can signal BT out-of-band */ #define FW_MEM_REG_LOWER_BOUND 0x00300000 #define FW_MEM_REG_EEPROM_ACCESS (FW_MEM_REG_LOWER_BOUND + 0x40) @@ -1877,11 +1876,11 @@ struct ipw_cmd_log { /* SysConfig command parameters ... */ /* bt_coexistence param */ -#define CFG_BT_COEXISTENCE_SIGNAL_CHNL 0x01 /* tell BT our chnl # */ -#define CFG_BT_COEXISTENCE_DEFER 0x02 /* defer our Tx if BT traffic */ -#define CFG_BT_COEXISTENCE_KILL 0x04 /* kill our Tx if BT traffic */ -#define CFG_BT_COEXISTENCE_WME_OVER_BT 0x08 /* multimedia extensions */ -#define CFG_BT_COEXISTENCE_OOB 0x10 /* signal BT via out-of-band */ +#define CFG_BT_COEXISTENCE_SIGNAL_CHNL 0x01 /* tell BT our chnl # */ +#define CFG_BT_COEXISTENCE_DEFER 0x02 /* defer our Tx if BT traffic */ +#define CFG_BT_COEXISTENCE_KILL 0x04 /* kill our Tx if BT traffic */ +#define CFG_BT_COEXISTENCE_WME_OVER_BT 0x08 /* multimedia extensions */ +#define CFG_BT_COEXISTENCE_OOB 0x10 /* signal BT via out-of-band */ /* clear-to-send to self param */ #define CFG_CTS_TO_ITSELF_ENABLED_MIN 0x00 @@ -1889,9 +1888,9 @@ struct ipw_cmd_log { #define CFG_CTS_TO_ITSELF_ENABLED_DEF CFG_CTS_TO_ITSELF_ENABLED_MIN /* Antenna diversity param (h/w can select best antenna, based on signal) */ -#define CFG_SYS_ANTENNA_BOTH 0x00 /* NIC selects best antenna */ -#define CFG_SYS_ANTENNA_A 0x01 /* force antenna A */ -#define CFG_SYS_ANTENNA_B 0x03 /* force antenna B */ +#define CFG_SYS_ANTENNA_BOTH 0x00 /* NIC selects best antenna */ +#define CFG_SYS_ANTENNA_A 0x01 /* force antenna A */ +#define CFG_SYS_ANTENNA_B 0x03 /* force antenna B */ /* * The definitions below were lifted off the ipw2100 driver, which only -- cgit v1.2.3-59-g8ed1b From 4644151b7208bec9522cad928a7105e0fc04a2b2 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:37:59 +0800 Subject: [PATCH] ipw2200: Semaphore to mutexes conversion The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Cc: Ronald Bultje Cc: "David S. Miller" Cc: Jeff Garzik Cc: Yi Zhu Cc: James Ketrenos Signed-off-by: Andrew Morton Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 294 ++++++++++++++++++++--------------------- drivers/net/wireless/ipw2200.h | 3 +- 2 files changed, 149 insertions(+), 148 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index f793cd8f8d71..fdb8065a8088 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -812,9 +812,9 @@ static void ipw_led_link_on(struct ipw_priv *priv) static void ipw_bg_led_link_on(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_led_link_on(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static void ipw_led_link_off(struct ipw_priv *priv) @@ -856,9 +856,9 @@ static void ipw_led_link_off(struct ipw_priv *priv) static void ipw_bg_led_link_off(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_led_link_off(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static void __ipw_led_activity_on(struct ipw_priv *priv) @@ -935,9 +935,9 @@ static void ipw_led_activity_off(struct ipw_priv *priv) static void ipw_bg_led_activity_off(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_led_activity_off(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static void ipw_led_band_on(struct ipw_priv *priv) @@ -2094,9 +2094,9 @@ static void ipw_adapter_restart(void *adapter) static void ipw_bg_adapter_restart(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_adapter_restart(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } #define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) @@ -2115,9 +2115,9 @@ static void ipw_scan_check(void *data) static void ipw_bg_scan_check(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_scan_check(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static int ipw_send_scan_request_ext(struct ipw_priv *priv, @@ -3735,9 +3735,9 @@ static int ipw_disassociate(void *data) static void ipw_bg_disassociate(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_disassociate(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static void ipw_system_config(void *data) @@ -4097,9 +4097,9 @@ static void ipw_gather_stats(struct ipw_priv *priv) static void ipw_bg_gather_stats(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_gather_stats(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } /* Missed beacon behavior: @@ -4931,9 +4931,9 @@ static void ipw_rx_queue_replenish(void *data) static void ipw_bg_rx_queue_replenish(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_rx_queue_replenish(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } /* Assumes that the skb field of the buffers in 'pool' is kept accurate. @@ -5390,7 +5390,7 @@ static void ipw_merge_adhoc_network(void *data) return; } - down(&priv->sem); + mutex_lock(&priv->mutex); if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) { IPW_DEBUG_MERGE("remove network %s\n", escape_essid(priv->essid, @@ -5400,7 +5400,7 @@ static void ipw_merge_adhoc_network(void *data) ipw_disassociate(priv); priv->assoc_network = match.network; - up(&priv->sem); + mutex_unlock(&priv->mutex); return; } } @@ -5835,9 +5835,9 @@ static void ipw_adhoc_check(void *data) static void ipw_bg_adhoc_check(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_adhoc_check(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } #ifdef CONFIG_IPW2200_DEBUG @@ -6064,7 +6064,7 @@ static int ipw_request_scan(struct ipw_priv *priv) (priv->status & STATUS_EXIT_PENDING)) return 0; - down(&priv->sem); + mutex_lock(&priv->mutex); if (priv->status & STATUS_SCANNING) { IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n"); @@ -6172,16 +6172,16 @@ static int ipw_request_scan(struct ipw_priv *priv) queue_delayed_work(priv->workqueue, &priv->scan_check, IPW_SCAN_CHECK_WATCHDOG); done: - up(&priv->sem); + mutex_unlock(&priv->mutex); return err; } static void ipw_bg_abort_scan(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_abort_scan(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static int ipw_wpa_enable(struct ipw_priv *priv, int value) @@ -6256,7 +6256,7 @@ static int ipw_wx_set_genie(struct net_device *dev, (wrqu->data.length && extra == NULL)) return -EINVAL; - //down(&priv->sem); + //mutex_lock(&priv->mutex); //if (!ieee->wpa_enabled) { // err = -EOPNOTSUPP; @@ -6282,7 +6282,7 @@ static int ipw_wx_set_genie(struct net_device *dev, ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); out: - //up(&priv->sem); + //mutex_unlock(&priv->mutex); return err; } @@ -6295,7 +6295,7 @@ static int ipw_wx_get_genie(struct net_device *dev, struct ieee80211_device *ieee = priv->ieee; int err = 0; - //down(&priv->sem); + //mutex_lock(&priv->mutex); //if (!ieee->wpa_enabled) { // err = -EOPNOTSUPP; @@ -6316,7 +6316,7 @@ static int ipw_wx_get_genie(struct net_device *dev, memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); out: - //up(&priv->sem); + //mutex_unlock(&priv->mutex); return err; } @@ -6976,12 +6976,12 @@ static void ipw_bg_qos_activate(void *data) if (priv == NULL) return; - down(&priv->sem); + mutex_lock(&priv->mutex); if (priv->status & STATUS_ASSOCIATED) ipw_qos_activate(priv, &(priv->assoc_network->qos_data)); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static int ipw_handle_probe_response(struct net_device *dev, @@ -7283,9 +7283,9 @@ static void ipw_roam(void *data) static void ipw_bg_roam(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_roam(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static int ipw_associate(void *data) @@ -7380,9 +7380,9 @@ static int ipw_associate(void *data) static void ipw_bg_associate(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_associate(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv, @@ -8131,7 +8131,7 @@ static int ipw_wx_get_name(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); if (priv->status & STATUS_RF_KILL_MASK) strcpy(wrqu->name, "radio off"); else if (!(priv->status & STATUS_ASSOCIATED)) @@ -8140,7 +8140,7 @@ static int ipw_wx_get_name(struct net_device *dev, snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c", ipw_modes[priv->assoc_request.ieee_mode]); IPW_DEBUG_WX("Name: %s\n", wrqu->name); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8209,9 +8209,9 @@ static int ipw_wx_set_freq(struct net_device *dev, if (fwrq->m == 0) { IPW_DEBUG_WX("SET Freq/Channel -> any\n"); - down(&priv->sem); + mutex_lock(&priv->mutex); ret = ipw_set_channel(priv, 0); - up(&priv->sem); + mutex_unlock(&priv->mutex); return ret; } /* if setting by freq convert to channel */ @@ -8239,9 +8239,9 @@ static int ipw_wx_set_freq(struct net_device *dev, } IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); - down(&priv->sem); + mutex_lock(&priv->mutex); ret = ipw_set_channel(priv, channel); - up(&priv->sem); + mutex_unlock(&priv->mutex); return ret; } @@ -8255,14 +8255,14 @@ static int ipw_wx_get_freq(struct net_device *dev, /* If we are associated, trying to associate, or have a statically * configured CHANNEL then return that; otherwise return ANY */ - down(&priv->sem); + mutex_lock(&priv->mutex); if (priv->config & CFG_STATIC_CHANNEL || priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) wrqu->freq.m = priv->channel; else wrqu->freq.m = 0; - up(&priv->sem); + mutex_unlock(&priv->mutex); IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); return 0; } @@ -8292,7 +8292,7 @@ static int ipw_wx_set_mode(struct net_device *dev, if (wrqu->mode == priv->ieee->iw_mode) return 0; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_sw_reset(priv, 0); @@ -8315,7 +8315,7 @@ static int ipw_wx_set_mode(struct net_device *dev, priv->ieee->iw_mode = wrqu->mode; queue_work(priv->workqueue, &priv->adapter_restart); - up(&priv->sem); + mutex_unlock(&priv->mutex); return err; } @@ -8324,10 +8324,10 @@ static int ipw_wx_get_mode(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); wrqu->mode = priv->ieee->iw_mode; IPW_DEBUG_WX("Get MODE -> %d\n", wrqu->mode); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8374,7 +8374,7 @@ static int ipw_wx_get_range(struct net_device *dev, range->avg_qual.level = 0; /* FIXME to real average level */ range->avg_qual.noise = 0; range->avg_qual.updated = 7; /* Updated all three */ - down(&priv->sem); + mutex_lock(&priv->mutex); range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES); for (i = 0; i < range->num_bitrates; i++) @@ -8416,7 +8416,7 @@ static int ipw_wx_get_range(struct net_device *dev, range->num_channels = i; range->num_frequency = i; - up(&priv->sem); + mutex_unlock(&priv->mutex); /* Event capability (kernel + driver) */ range->event_capa[0] = (IW_EVENT_CAPA_K_0 | @@ -8443,7 +8443,7 @@ static int ipw_wx_set_wap(struct net_device *dev, if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) return -EINVAL; - down(&priv->sem); + mutex_lock(&priv->mutex); if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) || !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) { /* we disable mandatory BSSID association */ @@ -8452,14 +8452,14 @@ static int ipw_wx_set_wap(struct net_device *dev, IPW_DEBUG_ASSOC("Attempting to associate with new " "parameters.\n"); ipw_associate(priv); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } priv->config |= CFG_STATIC_BSSID; if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) { IPW_DEBUG_WX("BSSID set to current BSSID.\n"); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8473,7 +8473,7 @@ static int ipw_wx_set_wap(struct net_device *dev, if (!ipw_disassociate(priv)) ipw_associate(priv); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8484,7 +8484,7 @@ static int ipw_wx_get_wap(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); /* If we are associated, trying to associate, or have a statically * configured BSSID then return that; otherwise return ANY */ - down(&priv->sem); + mutex_lock(&priv->mutex); if (priv->config & CFG_STATIC_BSSID || priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { wrqu->ap_addr.sa_family = ARPHRD_ETHER; @@ -8494,7 +8494,7 @@ static int ipw_wx_get_wap(struct net_device *dev, IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n", MAC_ARG(wrqu->ap_addr.sa_data)); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8505,7 +8505,7 @@ static int ipw_wx_set_essid(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); char *essid = ""; /* ANY */ int length = 0; - down(&priv->sem); + mutex_lock(&priv->mutex); if (wrqu->essid.flags && wrqu->essid.length) { length = wrqu->essid.length - 1; essid = extra; @@ -8520,7 +8520,7 @@ static int ipw_wx_set_essid(struct net_device *dev, priv->config &= ~CFG_STATIC_ESSID; ipw_associate(priv); } - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8530,7 +8530,7 @@ static int ipw_wx_set_essid(struct net_device *dev, if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) { IPW_DEBUG_WX("ESSID set to current ESSID.\n"); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8545,7 +8545,7 @@ static int ipw_wx_set_essid(struct net_device *dev, if (!ipw_disassociate(priv)) ipw_associate(priv); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8557,7 +8557,7 @@ static int ipw_wx_get_essid(struct net_device *dev, /* If we are associated, trying to associate, or have a statically * configured ESSID then return that; otherwise return ANY */ - down(&priv->sem); + mutex_lock(&priv->mutex); if (priv->config & CFG_STATIC_ESSID || priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { IPW_DEBUG_WX("Getting essid: '%s'\n", @@ -8570,7 +8570,7 @@ static int ipw_wx_get_essid(struct net_device *dev, wrqu->essid.length = 0; wrqu->essid.flags = 0; /* active */ } - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8583,12 +8583,12 @@ static int ipw_wx_set_nick(struct net_device *dev, IPW_DEBUG_WX("Setting nick to '%s'\n", extra); if (wrqu->data.length > IW_ESSID_MAX_SIZE) return -E2BIG; - down(&priv->sem); + mutex_lock(&priv->mutex); wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick)); memset(priv->nick, 0, sizeof(priv->nick)); memcpy(priv->nick, extra, wrqu->data.length); IPW_DEBUG_TRACE("<<\n"); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8599,11 +8599,11 @@ static int ipw_wx_get_nick(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); IPW_DEBUG_WX("Getting nick\n"); - down(&priv->sem); + mutex_lock(&priv->mutex); wrqu->data.length = strlen(priv->nick) + 1; memcpy(extra, priv->nick, wrqu->data.length); wrqu->data.flags = 1; /* active */ - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8696,7 +8696,7 @@ static int ipw_wx_set_rate(struct net_device *dev, apply: IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n", mask, fixed ? "fixed" : "sub-rates"); - down(&priv->sem); + mutex_lock(&priv->mutex); if (mask == IEEE80211_DEFAULT_RATES_MASK) { priv->config &= ~CFG_FIXED_RATE; ipw_set_fixed_rate(priv, priv->ieee->mode); @@ -8705,7 +8705,7 @@ static int ipw_wx_set_rate(struct net_device *dev, if (priv->rates_mask == mask) { IPW_DEBUG_WX("Mask set to current mask.\n"); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8716,7 +8716,7 @@ static int ipw_wx_set_rate(struct net_device *dev, if (!ipw_disassociate(priv)) ipw_associate(priv); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -8725,9 +8725,9 @@ static int ipw_wx_get_rate(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); wrqu->bitrate.value = priv->last_rate; - up(&priv->sem); + mutex_unlock(&priv->mutex); IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); return 0; } @@ -8737,20 +8737,20 @@ static int ipw_wx_set_rts(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); if (wrqu->rts.disabled) priv->rts_threshold = DEFAULT_RTS_THRESHOLD; else { if (wrqu->rts.value < MIN_RTS_THRESHOLD || wrqu->rts.value > MAX_RTS_THRESHOLD) { - up(&priv->sem); + mutex_unlock(&priv->mutex); return -EINVAL; } priv->rts_threshold = wrqu->rts.value; } ipw_send_rts_threshold(priv, priv->rts_threshold); - up(&priv->sem); + mutex_unlock(&priv->mutex); IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold); return 0; } @@ -8760,11 +8760,11 @@ static int ipw_wx_get_rts(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); wrqu->rts.value = priv->rts_threshold; wrqu->rts.fixed = 0; /* no auto select */ wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); - up(&priv->sem); + mutex_unlock(&priv->mutex); IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value); return 0; } @@ -8776,7 +8776,7 @@ static int ipw_wx_set_txpow(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); int err = 0; - down(&priv->sem); + mutex_lock(&priv->mutex); if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) { err = -EINPROGRESS; goto out; @@ -8799,7 +8799,7 @@ static int ipw_wx_set_txpow(struct net_device *dev, priv->tx_power = wrqu->power.value; err = ipw_set_tx_power(priv); out: - up(&priv->sem); + mutex_unlock(&priv->mutex); return err; } @@ -8808,12 +8808,12 @@ static int ipw_wx_get_txpow(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); wrqu->power.value = priv->tx_power; wrqu->power.fixed = 1; wrqu->power.flags = IW_TXPOW_DBM; wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; - up(&priv->sem); + mutex_unlock(&priv->mutex); IPW_DEBUG_WX("GET TX Power -> %s %d \n", wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); @@ -8826,13 +8826,13 @@ static int ipw_wx_set_frag(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); if (wrqu->frag.disabled) priv->ieee->fts = DEFAULT_FTS; else { if (wrqu->frag.value < MIN_FRAG_THRESHOLD || wrqu->frag.value > MAX_FRAG_THRESHOLD) { - up(&priv->sem); + mutex_unlock(&priv->mutex); return -EINVAL; } @@ -8840,7 +8840,7 @@ static int ipw_wx_set_frag(struct net_device *dev, } ipw_send_frag_threshold(priv, wrqu->frag.value); - up(&priv->sem); + mutex_unlock(&priv->mutex); IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value); return 0; } @@ -8850,11 +8850,11 @@ static int ipw_wx_get_frag(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); wrqu->frag.value = priv->ieee->fts; wrqu->frag.fixed = 0; /* no auto select */ wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS); - up(&priv->sem); + mutex_unlock(&priv->mutex); IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); return 0; @@ -8875,7 +8875,7 @@ static int ipw_wx_set_retry(struct net_device *dev, if (wrqu->retry.value < 0 || wrqu->retry.value > 255) return -EINVAL; - down(&priv->sem); + mutex_lock(&priv->mutex); if (wrqu->retry.flags & IW_RETRY_MIN) priv->short_retry_limit = (u8) wrqu->retry.value; else if (wrqu->retry.flags & IW_RETRY_MAX) @@ -8887,7 +8887,7 @@ static int ipw_wx_set_retry(struct net_device *dev, ipw_send_retry_limit(priv, priv->short_retry_limit, priv->long_retry_limit); - up(&priv->sem); + mutex_unlock(&priv->mutex); IPW_DEBUG_WX("SET retry limit -> short:%d long:%d\n", priv->short_retry_limit, priv->long_retry_limit); return 0; @@ -8899,11 +8899,11 @@ static int ipw_wx_get_retry(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); wrqu->retry.disabled = 0; if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - up(&priv->sem); + mutex_unlock(&priv->mutex); return -EINVAL; } @@ -8917,7 +8917,7 @@ static int ipw_wx_get_retry(struct net_device *dev, wrqu->retry.flags = IW_RETRY_LIMIT; wrqu->retry.value = priv->short_retry_limit; } - up(&priv->sem); + mutex_unlock(&priv->mutex); IPW_DEBUG_WX("GET retry -> %d \n", wrqu->retry.value); @@ -8934,7 +8934,7 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, (priv->status & STATUS_EXIT_PENDING)) return 0; - down(&priv->sem); + mutex_lock(&priv->mutex); if (priv->status & STATUS_RF_KILL_MASK) { IPW_DEBUG_HC("Aborting scan due to RF kill activation\n"); @@ -8986,7 +8986,7 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, priv->status |= STATUS_SCANNING; done: - up(&priv->sem); + mutex_unlock(&priv->mutex); return err; } @@ -9029,7 +9029,7 @@ static int ipw_wx_set_encode(struct net_device *dev, int ret; u32 cap = priv->capability; - down(&priv->sem); + mutex_lock(&priv->mutex); ret = ieee80211_wx_set_encode(priv->ieee, info, wrqu, key); /* In IBSS mode, we need to notify the firmware to update @@ -9039,7 +9039,7 @@ static int ipw_wx_set_encode(struct net_device *dev, priv->status & STATUS_ASSOCIATED) ipw_disassociate(priv); - up(&priv->sem); + mutex_unlock(&priv->mutex); return ret; } @@ -9057,17 +9057,17 @@ static int ipw_wx_set_power(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); int err; - down(&priv->sem); + mutex_lock(&priv->mutex); if (wrqu->power.disabled) { priv->power_mode = IPW_POWER_LEVEL(priv->power_mode); err = ipw_send_power_mode(priv, IPW_POWER_MODE_CAM); if (err) { IPW_DEBUG_WX("failed setting power mode.\n"); - up(&priv->sem); + mutex_unlock(&priv->mutex); return err; } IPW_DEBUG_WX("SET Power Management Mode -> off\n"); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -9079,7 +9079,7 @@ static int ipw_wx_set_power(struct net_device *dev, default: /* Otherwise we don't support it */ IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", wrqu->power.flags); - up(&priv->sem); + mutex_unlock(&priv->mutex); return -EOPNOTSUPP; } @@ -9092,12 +9092,12 @@ static int ipw_wx_set_power(struct net_device *dev, err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode)); if (err) { IPW_DEBUG_WX("failed setting power mode.\n"); - up(&priv->sem); + mutex_unlock(&priv->mutex); return err; } IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -9106,13 +9106,13 @@ static int ipw_wx_get_power(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); if (!(priv->power_mode & IPW_POWER_ENABLED)) wrqu->power.disabled = 1; else wrqu->power.disabled = 0; - up(&priv->sem); + mutex_unlock(&priv->mutex); IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode); return 0; @@ -9125,7 +9125,7 @@ static int ipw_wx_set_powermode(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); int mode = *(int *)extra; int err; - down(&priv->sem); + mutex_lock(&priv->mutex); if ((mode < 1) || (mode > IPW_POWER_LIMIT)) { mode = IPW_POWER_AC; priv->power_mode = mode; @@ -9138,11 +9138,11 @@ static int ipw_wx_set_powermode(struct net_device *dev, if (err) { IPW_DEBUG_WX("failed setting power mode.\n"); - up(&priv->sem); + mutex_unlock(&priv->mutex); return err; } } - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -9191,7 +9191,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev, IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode); return -EINVAL; } - down(&priv->sem); + mutex_lock(&priv->mutex); if (priv->adapter == IPW_2915ABG) { priv->ieee->abg_true = 1; if (mode & IEEE_A) { @@ -9203,7 +9203,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev, if (mode & IEEE_A) { IPW_WARNING("Attempt to set 2200BG into " "802.11a mode\n"); - up(&priv->sem); + mutex_unlock(&priv->mutex); return -EINVAL; } @@ -9240,7 +9240,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev, IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n", mode & IEEE_A ? 'a' : '.', mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.'); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -9249,7 +9249,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); switch (priv->ieee->mode) { case IEEE_A: strncpy(extra, "802.11a (1)", MAX_WX_STRING); @@ -9280,7 +9280,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev, IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra); wrqu->data.length = strlen(extra) + 1; - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -9291,7 +9291,7 @@ static int ipw_wx_set_preamble(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); int mode = *(int *)extra; - down(&priv->sem); + mutex_lock(&priv->mutex); /* Switching from SHORT -> LONG requires a disassociation */ if (mode == 1) { if (!(priv->config & CFG_PREAMBLE_LONG)) { @@ -9310,11 +9310,11 @@ static int ipw_wx_set_preamble(struct net_device *dev, priv->config &= ~CFG_PREAMBLE_LONG; goto done; } - up(&priv->sem); + mutex_unlock(&priv->mutex); return -EINVAL; done: - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -9323,12 +9323,12 @@ static int ipw_wx_get_preamble(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); if (priv->config & CFG_PREAMBLE_LONG) snprintf(wrqu->name, IFNAMSIZ, "long (1)"); else snprintf(wrqu->name, IFNAMSIZ, "auto (0)"); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -9340,7 +9340,7 @@ static int ipw_wx_set_monitor(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); int *parms = (int *)extra; int enable = (parms[0] > 0); - down(&priv->sem); + mutex_lock(&priv->mutex); IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); if (enable) { if (priv->ieee->iw_mode != IW_MODE_MONITOR) { @@ -9355,13 +9355,13 @@ static int ipw_wx_set_monitor(struct net_device *dev, ipw_set_channel(priv, parms[1]); } else { if (priv->ieee->iw_mode != IW_MODE_MONITOR) { - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } priv->net_dev->type = ARPHRD_ETHER; queue_work(priv->workqueue, &priv->adapter_restart); } - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -9391,7 +9391,7 @@ static int ipw_wx_sw_reset(struct net_device *dev, IPW_DEBUG_WX("SW_RESET\n"); - down(&priv->sem); + mutex_lock(&priv->mutex); ret = ipw_sw_reset(priv, 0); if (!ret) { @@ -9403,9 +9403,9 @@ static int ipw_wx_sw_reset(struct net_device *dev, * module parameter, so take appropriate action */ ipw_radio_kill_sw(priv, priv->status & STATUS_RF_KILL_SW); - up(&priv->sem); + mutex_unlock(&priv->mutex); ieee80211_wx_set_encode(priv->ieee, info, &wrqu_sec, NULL); - down(&priv->sem); + mutex_lock(&priv->mutex); if (!(priv->status & STATUS_RF_KILL_MASK)) { /* Configuration likely changed -- force [re]association */ @@ -9415,7 +9415,7 @@ static int ipw_wx_sw_reset(struct net_device *dev, ipw_associate(priv); } - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -9612,11 +9612,11 @@ static int ipw_net_open(struct net_device *dev) struct ipw_priv *priv = ieee80211_priv(dev); IPW_DEBUG_INFO("dev->open\n"); /* we should be verifying the device is ready to be opened */ - down(&priv->sem); + mutex_lock(&priv->mutex); if (!(priv->status & STATUS_RF_KILL_MASK) && (priv->status & STATUS_ASSOCIATED)) netif_start_queue(dev); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -9895,13 +9895,13 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p) struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - down(&priv->sem); + mutex_lock(&priv->mutex); priv->config |= CFG_CUSTOM_MAC; memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN); printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n", priv->net_dev->name, MAC_ARG(priv->mac_addr)); queue_work(priv->workqueue, &priv->adapter_restart); - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -9945,9 +9945,9 @@ static int ipw_ethtool_get_eeprom(struct net_device *dev, if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) return -EINVAL; - down(&p->sem); + mutex_lock(&p->mutex); memcpy(bytes, &p->eeprom[eeprom->offset], eeprom->len); - up(&p->sem); + mutex_unlock(&p->mutex); return 0; } @@ -9959,12 +9959,12 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev, if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) return -EINVAL; - down(&p->sem); + mutex_lock(&p->mutex); memcpy(&p->eeprom[eeprom->offset], bytes, eeprom->len); for (i = IPW_EEPROM_DATA; i < IPW_EEPROM_DATA + IPW_EEPROM_IMAGE_SIZE; i++) ipw_write8(p, i, p->eeprom[i]); - up(&p->sem); + mutex_unlock(&p->mutex); return 0; } @@ -10059,9 +10059,9 @@ static void ipw_rf_kill(void *adapter) static void ipw_bg_rf_kill(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_rf_kill(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static void ipw_link_up(struct ipw_priv *priv) @@ -10094,9 +10094,9 @@ static void ipw_link_up(struct ipw_priv *priv) static void ipw_bg_link_up(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_link_up(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static void ipw_link_down(struct ipw_priv *priv) @@ -10122,9 +10122,9 @@ static void ipw_link_down(struct ipw_priv *priv) static void ipw_bg_link_down(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_link_down(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static int ipw_setup_deferred_work(struct ipw_priv *priv) @@ -10801,9 +10801,9 @@ static int ipw_up(struct ipw_priv *priv) static void ipw_bg_up(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_up(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } static void ipw_deinit(struct ipw_priv *priv) @@ -10872,23 +10872,23 @@ static void ipw_down(struct ipw_priv *priv) static void ipw_bg_down(void *data) { struct ipw_priv *priv = data; - down(&priv->sem); + mutex_lock(&priv->mutex); ipw_down(data); - up(&priv->sem); + mutex_unlock(&priv->mutex); } /* Called by register_netdev() */ static int ipw_net_init(struct net_device *dev) { struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); + mutex_lock(&priv->mutex); if (ipw_up(priv)) { - up(&priv->sem); + mutex_unlock(&priv->mutex); return -EIO; } - up(&priv->sem); + mutex_unlock(&priv->mutex); return 0; } @@ -10978,7 +10978,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); - init_MUTEX(&priv->sem); + mutex_init(&priv->mutex); if (pci_enable_device(pdev)) { err = -ENODEV; goto out_free_ieee80211; @@ -11036,7 +11036,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SET_MODULE_OWNER(net_dev); SET_NETDEV_DEV(net_dev, &pdev->dev); - down(&priv->sem); + mutex_lock(&priv->mutex); priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; priv->ieee->set_security = shim__set_security; @@ -11069,11 +11069,11 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group); if (err) { IPW_ERROR("failed to create sysfs device attributes\n"); - up(&priv->sem); + mutex_unlock(&priv->mutex); goto out_release_irq; } - up(&priv->sem); + mutex_unlock(&priv->mutex); err = register_netdev(net_dev); if (err) { IPW_ERROR("failed to register network device\n"); @@ -11110,13 +11110,13 @@ static void ipw_pci_remove(struct pci_dev *pdev) if (!priv) return; - down(&priv->sem); + mutex_lock(&priv->mutex); priv->status |= STATUS_EXIT_PENDING; ipw_down(priv); sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); - up(&priv->sem); + mutex_unlock(&priv->mutex); unregister_netdev(priv->net_dev); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index eedd347b892e..5405ba105abf 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -1121,7 +1122,7 @@ struct ipw_priv { struct ieee80211_device *ieee; spinlock_t lock; - struct semaphore sem; + struct mutex mutex; /* basic pci-network driver stuff */ struct pci_dev *pci_dev; -- cgit v1.2.3-59-g8ed1b From bde37d037715bef4a67d58d00fecbe4c71836cab Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 24 Jan 2006 16:38:08 +0800 Subject: [PATCH] ipw2200: Disable hwcrypto by default After looking at the mailing list (and experiencing permanent driver lockups while using hwcrypto=1) I think that disabling this option by default would be better than otherwise. Signed-off-by: Andreas Happe Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index fdb8065a8088..18e00fe8a218 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -56,7 +56,7 @@ static int auto_create = 1; static int led = 0; static int disable = 0; static int bt_coexist = 0; -static int hwcrypto = 1; +static int hwcrypto = 0; static int roaming = 1; static const char ipw_modes[] = { 'a', 'b', 'g', '?' @@ -11304,7 +11304,7 @@ module_param(bt_coexist, int, 0444); MODULE_PARM_DESC(bt_coexist, "enable bluetooth coexistence (default off)"); module_param(hwcrypto, int, 0444); -MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default on)"); +MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default off)"); module_param(cmdlog, int, 0444); MODULE_PARM_DESC(cmdlog, -- cgit v1.2.3-59-g8ed1b From 4be757dd4c00ddabff2d6faf639466bb5d76bc79 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 30 Jan 2006 11:58:00 -0500 Subject: [PATCH] wireless/airo: add IWENCODEEXT and IWAUTH support This patch adds IWENCODEEXT and IWAUTH support to the airo driver for WEP and unencrypted operation. No WPA though. It allows the driver to operate more willingly with wpa_supplicant and NetworkManager. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 276 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 274 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 9c577f7b6e58..ef6495b07890 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -5756,11 +5756,13 @@ static int airo_set_wap(struct net_device *dev, Cmd cmd; Resp rsp; APListRid APList_rid; - static const unsigned char bcast[ETH_ALEN] = { 255, 255, 255, 255, 255, 255 }; + static const u8 any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + static const u8 off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; if (awrq->sa_family != ARPHRD_ETHER) return -EINVAL; - else if (!memcmp(bcast, awrq->sa_data, ETH_ALEN)) { + else if (!memcmp(any, awrq->sa_data, ETH_ALEN) || + !memcmp(off, awrq->sa_data, ETH_ALEN)) { memset(&cmd, 0, sizeof(cmd)); cmd.cmd=CMD_LOSE_SYNC; if (down_interruptible(&local->sem)) @@ -6249,6 +6251,267 @@ static int airo_get_encode(struct net_device *dev, return 0; } +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set extended Encryption parameters + */ +static int airo_set_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct airo_info *local = dev->priv; + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + CapabilityRid cap_rid; /* Card capability info */ + int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 ); + u16 currentAuthType = local->config.authType; + int idx, key_len, alg = ext->alg; /* Check encryption mode */ + wep_key_t key; + + /* Is WEP supported ? */ + readCapabilityRid(local, &cap_rid, 1); + /* Older firmware doesn't support this... + if(!(cap_rid.softCap & 2)) { + return -EOPNOTSUPP; + } */ + readConfigRid(local, 1); + + /* Determine and validate the key index */ + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) { + if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1)) + return -EINVAL; + idx--; + } else + idx = get_wep_key(local, 0xffff); + + if (encoding->flags & IW_ENCODE_DISABLED) + alg = IW_ENCODE_ALG_NONE; + + /* Just setting the transmit key? */ + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + set_wep_key(local, idx, NULL, 0, perm, 1); + } else { + /* Set the requested key first */ + memset(key.key, 0, MAX_KEY_SIZE); + switch (alg) { + case IW_ENCODE_ALG_NONE: + key.len = 0; + break; + case IW_ENCODE_ALG_WEP: + if (ext->key_len > MIN_KEY_SIZE) { + key.len = MAX_KEY_SIZE; + } else if (ext->key_len > 0) { + key.len = MIN_KEY_SIZE; + } else { + return -EINVAL; + } + key_len = min (ext->key_len, key.len); + memcpy(key.key, ext->key, key_len); + break; + default: + return -EINVAL; + } + /* Send the key to the card */ + set_wep_key(local, idx, key.key, key.len, perm, 1); + } + + /* Read the flags */ + if(encoding->flags & IW_ENCODE_DISABLED) + local->config.authType = AUTH_OPEN; // disable encryption + if(encoding->flags & IW_ENCODE_RESTRICTED) + local->config.authType = AUTH_SHAREDKEY; // Only Both + if(encoding->flags & IW_ENCODE_OPEN) + local->config.authType = AUTH_ENCRYPT; // Only Wep + /* Commit the changes to flags if needed */ + if (local->config.authType != currentAuthType) + set_bit (FLAG_COMMIT, &local->flags); + + return -EINPROGRESS; +} + + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get extended Encryption parameters + */ +static int airo_get_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct airo_info *local = dev->priv; + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + CapabilityRid cap_rid; /* Card capability info */ + int idx, max_key_len; + + /* Is it supported ? */ + readCapabilityRid(local, &cap_rid, 1); + if(!(cap_rid.softCap & 2)) { + return -EOPNOTSUPP; + } + readConfigRid(local, 1); + + max_key_len = encoding->length - sizeof(*ext); + if (max_key_len < 0) + return -EINVAL; + + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) { + if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1)) + return -EINVAL; + idx--; + } else + idx = get_wep_key(local, 0xffff); + + encoding->flags = idx + 1; + memset(ext, 0, sizeof(*ext)); + + /* Check encryption mode */ + switch(local->config.authType) { + case AUTH_ENCRYPT: + encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED; + break; + case AUTH_SHAREDKEY: + encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED; + break; + default: + case AUTH_OPEN: + encoding->flags = IW_ENCODE_ALG_NONE | IW_ENCODE_DISABLED; + break; + } + /* We can't return the key, so set the proper flag and return zero */ + encoding->flags |= IW_ENCODE_NOKEY; + memset(extra, 0, 16); + + /* Copy the key to the user buffer */ + ext->key_len = get_wep_key(local, idx); + if (ext->key_len > 16) { + ext->key_len=0; + } + + return 0; +} + + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : set extended authentication parameters + */ +static int airo_set_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct airo_info *local = dev->priv; + struct iw_param *param = &wrqu->param; + u16 currentAuthType = local->config.authType; + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_PRIVACY_INVOKED: + /* + * airo does not use these parameters + */ + break; + + case IW_AUTH_DROP_UNENCRYPTED: + if (param->value) { + /* Only change auth type if unencrypted */ + if (currentAuthType == AUTH_OPEN) + local->config.authType = AUTH_ENCRYPT; + } else { + local->config.authType = AUTH_OPEN; + } + + /* Commit the changes to flags if needed */ + if (local->config.authType != currentAuthType) + set_bit (FLAG_COMMIT, &local->flags); + break; + + case IW_AUTH_80211_AUTH_ALG: { + /* FIXME: What about AUTH_OPEN? This API seems to + * disallow setting our auth to AUTH_OPEN. + */ + if (param->value & IW_AUTH_ALG_SHARED_KEY) { + local->config.authType = AUTH_SHAREDKEY; + } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { + local->config.authType = AUTH_ENCRYPT; + } else + return -EINVAL; + break; + + /* Commit the changes to flags if needed */ + if (local->config.authType != currentAuthType) + set_bit (FLAG_COMMIT, &local->flags); + } + + case IW_AUTH_WPA_ENABLED: + /* Silently accept disable of WPA */ + if (param->value > 0) + return -EOPNOTSUPP; + break; + + default: + return -EOPNOTSUPP; + } + return -EINPROGRESS; +} + + +/*------------------------------------------------------------------*/ +/* + * Wireless Handler : get extended authentication parameters + */ +static int airo_get_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct airo_info *local = dev->priv; + struct iw_param *param = &wrqu->param; + u16 currentAuthType = local->config.authType; + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + switch (currentAuthType) { + case AUTH_SHAREDKEY: + case AUTH_ENCRYPT: + param->value = 1; + break; + default: + param->value = 0; + break; + } + break; + + case IW_AUTH_80211_AUTH_ALG: + switch (currentAuthType) { + case AUTH_SHAREDKEY: + param->value = IW_AUTH_ALG_SHARED_KEY; + break; + case AUTH_ENCRYPT: + default: + param->value = IW_AUTH_ALG_OPEN_SYSTEM; + break; + } + break; + + case IW_AUTH_WPA_ENABLED: + param->value = 0; + break; + + default: + return -EOPNOTSUPP; + } + return 0; +} + + /*------------------------------------------------------------------*/ /* * Wireless Handler : set Tx-Power @@ -7005,6 +7268,15 @@ static const iw_handler airo_handler[] = (iw_handler) airo_get_encode, /* SIOCGIWENCODE */ (iw_handler) airo_set_power, /* SIOCSIWPOWER */ (iw_handler) airo_get_power, /* SIOCGIWPOWER */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWGENIE */ + (iw_handler) NULL, /* SIOCGIWGENIE */ + (iw_handler) airo_set_auth, /* SIOCSIWAUTH */ + (iw_handler) airo_get_auth, /* SIOCGIWAUTH */ + (iw_handler) airo_set_encodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) airo_get_encodeext, /* SIOCGIWENCODEEXT */ + (iw_handler) NULL, /* SIOCSIWPMKSA */ }; /* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here. -- cgit v1.2.3-59-g8ed1b From f1b50863aa6a96c61a57e3b3a5e76e67b38c5c3e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 30 Jan 2006 13:58:56 -0500 Subject: [PATCH] wireless/ipw2200: support WE-18 WPA enc_capa This patch allows ipw2100 driver to advertise the WPA-related encryption options that it does really support. It's necessary to work correctly with NetworkManager and other programs that actually check driver & card capabilities. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 18e00fe8a218..734d2cb1de06 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -8392,7 +8392,7 @@ static int ipw_wx_get_range(struct net_device *dev, /* Set the Wireless Extension versions */ range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 16; + range->we_version_source = 18; i = 0; if (priv->ieee->mode & (IEEE_B | IEEE_G)) { @@ -8424,6 +8424,9 @@ static int ipw_wx_get_range(struct net_device *dev, IW_EVENT_CAPA_MASK(SIOCGIWAP)); range->event_capa[1] = IW_EVENT_CAPA_K_1; + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; + IPW_DEBUG_WX("GET Range\n"); return 0; } -- cgit v1.2.3-59-g8ed1b From e4e7b89280d1d666e2c09e5ad36cf071796c4c7e Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 31 Jan 2006 12:18:41 -0500 Subject: [libata sata_mv] add 6042 support, fix 60xx/50xx EDMA configuration --- drivers/scsi/sata_mv.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 200 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index d9a554ca45c7..b55dd839ddbd 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -37,7 +37,7 @@ #include #define DRV_NAME "sata_mv" -#define DRV_VERSION "0.5" +#define DRV_VERSION "0.6" enum { /* BAR's are enumerated in terms of pci_resource_start() terms */ @@ -228,7 +228,9 @@ enum { MV_HP_ERRATA_50XXB2 = (1 << 2), MV_HP_ERRATA_60X1B2 = (1 << 3), MV_HP_ERRATA_60X1C0 = (1 << 4), - MV_HP_50XX = (1 << 5), + MV_HP_ERRATA_XX42A0 = (1 << 5), + MV_HP_50XX = (1 << 6), + MV_HP_GEN_IIE = (1 << 7), /* Port private flags (pp_flags) */ MV_PP_FLAG_EDMA_EN = (1 << 0), @@ -237,6 +239,9 @@ enum { #define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX) #define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0) +#define IS_GEN_I(hpriv) IS_50XX(hpriv) +#define IS_GEN_II(hpriv) IS_60XX(hpriv) +#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE) enum { /* Our DMA boundary is determined by an ePRD being unable to handle @@ -255,6 +260,8 @@ enum chip_type { chip_5080, chip_604x, chip_608x, + chip_6042, + chip_7042, }; /* Command ReQuest Block: 32B */ @@ -265,6 +272,14 @@ struct mv_crqb { u16 ata_cmd[11]; }; +struct mv_crqb_iie { + u32 addr; + u32 addr_hi; + u32 flags; + u32 len; + u32 ata_cmd[4]; +}; + /* Command ResPonse Block: 8B */ struct mv_crpb { u16 id; @@ -328,6 +343,7 @@ static void mv_host_stop(struct ata_host_set *host_set); static int mv_port_start(struct ata_port *ap); static void mv_port_stop(struct ata_port *ap); static void mv_qc_prep(struct ata_queued_cmd *qc); +static void mv_qc_prep_iie(struct ata_queued_cmd *qc); static unsigned int mv_qc_issue(struct ata_queued_cmd *qc); static irqreturn_t mv_interrupt(int irq, void *dev_instance, struct pt_regs *regs); @@ -430,6 +446,33 @@ static const struct ata_port_operations mv6_ops = { .host_stop = mv_host_stop, }; +static const struct ata_port_operations mv_iie_ops = { + .port_disable = ata_port_disable, + + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .phy_reset = mv_phy_reset, + + .qc_prep = mv_qc_prep_iie, + .qc_issue = mv_qc_issue, + + .eng_timeout = mv_eng_timeout, + + .irq_handler = mv_interrupt, + .irq_clear = mv_irq_clear, + + .scr_read = mv_scr_read, + .scr_write = mv_scr_write, + + .port_start = mv_port_start, + .port_stop = mv_port_stop, + .host_stop = mv_host_stop, +}; + static const struct ata_port_info mv_port_info[] = { { /* chip_504x */ .sht = &mv_sht, @@ -467,6 +510,21 @@ static const struct ata_port_info mv_port_info[] = { .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &mv6_ops, }, + { /* chip_6042 */ + .sht = &mv_sht, + .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), + .pio_mask = 0x1f, /* pio0-4 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &mv_iie_ops, + }, + { /* chip_7042 */ + .sht = &mv_sht, + .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS | + MV_FLAG_DUAL_HC), + .pio_mask = 0x1f, /* pio0-4 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &mv_iie_ops, + }, }; static const struct pci_device_id mv_pci_tbl[] = { @@ -477,6 +535,7 @@ static const struct pci_device_id mv_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x}, {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x}, + {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6042), 0, 0, chip_6042}, {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6080), 0, 0, chip_608x}, {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6081), 0, 0, chip_608x}, @@ -767,6 +826,33 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev) dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma); } +static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio) +{ + u32 cfg = readl(port_mmio + EDMA_CFG_OFS); + + /* set up non-NCQ EDMA configuration */ + cfg &= ~0x1f; /* clear queue depth */ + cfg &= ~EDMA_CFG_NCQ; /* clear NCQ mode */ + cfg &= ~(1 << 9); /* disable equeue */ + + if (IS_GEN_I(hpriv)) + cfg |= (1 << 8); /* enab config burst size mask */ + + else if (IS_GEN_II(hpriv)) + cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN; + + else if (IS_GEN_IIE(hpriv)) { + cfg |= (1 << 23); /* dis RX PM port mask */ + cfg &= ~(1 << 16); /* dis FIS-based switching (for now) */ + cfg &= ~(1 << 19); /* dis 128-entry queue (for now?) */ + cfg |= (1 << 18); /* enab early completion */ + cfg |= (1 << 17); /* enab host q cache */ + cfg |= (1 << 22); /* enab cutthrough */ + } + + writelfl(cfg, port_mmio + EDMA_CFG_OFS); +} + /** * mv_port_start - Port specific init/start routine. * @ap: ATA channel to manipulate @@ -780,6 +866,7 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev) static int mv_port_start(struct ata_port *ap) { struct device *dev = ap->host_set->dev; + struct mv_host_priv *hpriv = ap->host_set->private_data; struct mv_port_priv *pp; void __iomem *port_mmio = mv_ap_base(ap); void *mem; @@ -823,17 +910,26 @@ static int mv_port_start(struct ata_port *ap) pp->sg_tbl = mem; pp->sg_tbl_dma = mem_dma; - writelfl(EDMA_CFG_Q_DEPTH | EDMA_CFG_RD_BRST_EXT | - EDMA_CFG_WR_BUFF_LEN, port_mmio + EDMA_CFG_OFS); + mv_edma_cfg(hpriv, port_mmio); writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS); writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK, port_mmio + EDMA_REQ_Q_IN_PTR_OFS); - writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); - writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); + if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) + writelfl(pp->crqb_dma & 0xffffffff, + port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); + else + writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS); + + if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) + writelfl(pp->crpb_dma & 0xffffffff, + port_mmio + EDMA_RSP_Q_IN_PTR_OFS); + else + writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); + writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); @@ -954,9 +1050,8 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) struct ata_taskfile *tf; u16 flags = 0; - if (ATA_PROT_DMA != qc->tf.protocol) { + if (ATA_PROT_DMA != qc->tf.protocol) return; - } /* the req producer index should be the same as we remember it */ assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> @@ -965,9 +1060,8 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) /* Fill in command request block */ - if (!(qc->tf.flags & ATA_TFLAG_WRITE)) { + if (!(qc->tf.flags & ATA_TFLAG_WRITE)) flags |= CRQB_FLAG_READ; - } assert(MV_MAX_Q_DEPTH > qc->tag); flags |= qc->tag << CRQB_TAG_SHIFT; @@ -1022,9 +1116,76 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0); mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */ - if (!(qc->flags & ATA_QCFLAG_DMAMAP)) { + if (!(qc->flags & ATA_QCFLAG_DMAMAP)) + return; + mv_fill_sg(qc); +} + +/** + * mv_qc_prep_iie - Host specific command preparation. + * @qc: queued command to prepare + * + * This routine simply redirects to the general purpose routine + * if command is not DMA. Else, it handles prep of the CRQB + * (command request block), does some sanity checking, and calls + * the SG load routine. + * + * LOCKING: + * Inherited from caller. + */ +static void mv_qc_prep_iie(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct mv_port_priv *pp = ap->private_data; + struct mv_crqb_iie *crqb; + struct ata_taskfile *tf; + u32 flags = 0; + + if (ATA_PROT_DMA != qc->tf.protocol) + return; + + /* the req producer index should be the same as we remember it */ + assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> + EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == + pp->req_producer); + + /* Fill in Gen IIE command request block + */ + if (!(qc->tf.flags & ATA_TFLAG_WRITE)) + flags |= CRQB_FLAG_READ; + + assert(MV_MAX_Q_DEPTH > qc->tag); + flags |= qc->tag << CRQB_TAG_SHIFT; + + crqb = (struct mv_crqb_iie *) &pp->crqb[pp->req_producer]; + crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); + crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); + crqb->flags = cpu_to_le32(flags); + + tf = &qc->tf; + crqb->ata_cmd[0] = cpu_to_le32( + (tf->command << 16) | + (tf->feature << 24) + ); + crqb->ata_cmd[1] = cpu_to_le32( + (tf->lbal << 0) | + (tf->lbam << 8) | + (tf->lbah << 16) | + (tf->device << 24) + ); + crqb->ata_cmd[2] = cpu_to_le32( + (tf->hob_lbal << 0) | + (tf->hob_lbam << 8) | + (tf->hob_lbah << 16) | + (tf->hob_feature << 24) + ); + crqb->ata_cmd[3] = cpu_to_le32( + (tf->nsect << 0) | + (tf->hob_nsect << 8) + ); + + if (!(qc->flags & ATA_QCFLAG_DMAMAP)) return; - } mv_fill_sg(qc); } @@ -1674,6 +1835,12 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, m2 |= hpriv->signal[port].pre; m2 &= ~(1 << 16); + /* according to mvSata 3.6.1, some IIE values are fixed */ + if (IS_GEN_IIE(hpriv)) { + m2 &= ~0xC30FF01F; + m2 |= 0x0000900F; + } + writel(m2, port_mmio + PHY_MODE2); } @@ -1978,6 +2145,27 @@ static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv, } break; + case chip_7042: + case chip_6042: + hpriv->ops = &mv6xxx_ops; + + hp_flags |= MV_HP_GEN_IIE; + + switch (rev_id) { + case 0x0: + hp_flags |= MV_HP_ERRATA_XX42A0; + break; + case 0x1: + hp_flags |= MV_HP_ERRATA_60X1C0; + break; + default: + dev_printk(KERN_WARNING, &pdev->dev, + "Applying 60X1C0 workarounds to unknown rev\n"); + hp_flags |= MV_HP_ERRATA_60X1C0; + break; + } + break; + default: printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx); return 1; -- cgit v1.2.3-59-g8ed1b From bbab6fd81f26b210f0815d79064a3387c3a1ade3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 6 Feb 2006 09:15:11 -0200 Subject: V4L/DVB (3265): Add count to tunertype struct The tuner_params element is an array of undefined length, with each array member being a set of parameters for each video standard type. The number of members in the tuner_params array will be stored in tuners[]->count Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 67 +++++++++++++++++++++++++++++++++++++++ include/media/tuner-types.h | 1 + 2 files changed, 68 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index f77584dd356e..27fc4d06b1d2 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -987,18 +987,22 @@ struct tunertype tuners[] = { [TUNER_TEMIC_PAL] = { /* TEMIC PAL */ .name = "Temic PAL (4002 FH5)", .params = tuner_temic_pal_params, + .count = ARRAY_SIZE(tuner_temic_pal_params), }, [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */ .name = "Philips PAL_I (FI1246 and compatibles)", .params = tuner_philips_pal_i_params, + .count = ARRAY_SIZE(tuner_philips_pal_i_params), }, [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */ .name = "Philips NTSC (FI1236,FM1236 and compatibles)", .params = tuner_philips_ntsc_params, + .count = ARRAY_SIZE(tuner_philips_ntsc_params), }, [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */ .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", .params = tuner_philips_secam_params, + .count = ARRAY_SIZE(tuner_philips_secam_params), }, [TUNER_ABSENT] = { /* Tuner Absent */ .name = "NoTuner", @@ -1006,120 +1010,148 @@ struct tunertype tuners[] = { [TUNER_PHILIPS_PAL] = { /* Philips PAL */ .name = "Philips PAL_BG (FI1216 and compatibles)", .params = tuner_philips_pal_params, + .count = ARRAY_SIZE(tuner_philips_pal_params), }, [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */ .name = "Temic NTSC (4032 FY5)", .params = tuner_temic_ntsc_params, + .count = ARRAY_SIZE(tuner_temic_ntsc_params), }, [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */ .name = "Temic PAL_I (4062 FY5)", .params = tuner_temic_pal_i_params, + .count = ARRAY_SIZE(tuner_temic_pal_i_params), }, [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */ .name = "Temic NTSC (4036 FY5)", .params = tuner_temic_4036fy5_ntsc_params, + .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_params), }, [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */ .name = "Alps HSBH1", .params = tuner_alps_tsbh1_ntsc_params, + .count = ARRAY_SIZE(tuner_alps_tsbh1_ntsc_params), }, /* 10-19 */ [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */ .name = "Alps TSBE1", .params = tuner_alps_tsb_1_params, + .count = ARRAY_SIZE(tuner_alps_tsb_1_params), }, [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */ .name = "Alps TSBB5", .params = tuner_alps_tsbb5_params, + .count = ARRAY_SIZE(tuner_alps_tsbb5_params), }, [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */ .name = "Alps TSBE5", .params = tuner_alps_tsbe5_params, + .count = ARRAY_SIZE(tuner_alps_tsbe5_params), }, [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */ .name = "Alps TSBC5", .params = tuner_alps_tsbc5_params, + .count = ARRAY_SIZE(tuner_alps_tsbc5_params), }, [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */ .name = "Temic PAL_BG (4006FH5)", .params = tuner_temic_4006fh5_params, + .count = ARRAY_SIZE(tuner_temic_4006fh5_params), }, [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */ .name = "Alps TSCH6", .params = tuner_alps_tshc6_params, + .count = ARRAY_SIZE(tuner_alps_tshc6_params), }, [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */ .name = "Temic PAL_DK (4016 FY5)", .params = tuner_temic_pal_dk_params, + .count = ARRAY_SIZE(tuner_temic_pal_dk_params), }, [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */ .name = "Philips NTSC_M (MK2)", .params = tuner_philips_ntsc_m_params, + .count = ARRAY_SIZE(tuner_philips_ntsc_m_params), }, [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */ .name = "Temic PAL_I (4066 FY5)", .params = tuner_temic_4066fy5_pal_i_params, + .count = ARRAY_SIZE(tuner_temic_4066fy5_pal_i_params), }, [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */ .name = "Temic PAL* auto (4006 FN5)", .params = tuner_temic_4006fn5_multi_params, + .count = ARRAY_SIZE(tuner_temic_4006fn5_multi_params), }, /* 20-29 */ [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */ .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", .params = tuner_temic_4009f_5_params, + .count = ARRAY_SIZE(tuner_temic_4009f_5_params), }, [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */ .name = "Temic NTSC (4039 FR5)", .params = tuner_temic_4039fr5_params, + .count = ARRAY_SIZE(tuner_temic_4039fr5_params), }, [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */ .name = "Temic PAL/SECAM multi (4046 FM5)", .params = tuner_temic_4046fm5_params, + .count = ARRAY_SIZE(tuner_temic_4046fm5_params), }, [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */ .name = "Philips PAL_DK (FI1256 and compatibles)", .params = tuner_philips_pal_dk_params, + .count = ARRAY_SIZE(tuner_philips_pal_dk_params), }, [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */ .name = "Philips PAL/SECAM multi (FQ1216ME)", .params = tuner_philips_fq1216me_params, + .count = ARRAY_SIZE(tuner_philips_fq1216me_params), }, [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */ .name = "LG PAL_I+FM (TAPC-I001D)", .params = tuner_lg_pal_i_fm_params, + .count = ARRAY_SIZE(tuner_lg_pal_i_fm_params), }, [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */ .name = "LG PAL_I (TAPC-I701D)", .params = tuner_lg_pal_i_params, + .count = ARRAY_SIZE(tuner_lg_pal_i_params), }, [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */ .name = "LG NTSC+FM (TPI8NSR01F)", .params = tuner_lg_ntsc_fm_params, + .count = ARRAY_SIZE(tuner_lg_ntsc_fm_params), }, [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */ .name = "LG PAL_BG+FM (TPI8PSB01D)", .params = tuner_lg_pal_fm_params, + .count = ARRAY_SIZE(tuner_lg_pal_fm_params), }, [TUNER_LG_PAL] = { /* LGINNOTEK PAL */ .name = "LG PAL_BG (TPI8PSB11D)", .params = tuner_lg_pal_params, + .count = ARRAY_SIZE(tuner_lg_pal_params), }, /* 30-39 */ [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */ .name = "Temic PAL* auto + FM (4009 FN5)", .params = tuner_temic_4009_fn5_multi_pal_fm_params, + .count = ARRAY_SIZE(tuner_temic_4009_fn5_multi_pal_fm_params), }, [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */ .name = "SHARP NTSC_JP (2U5JF5540)", .params = tuner_sharp_2u5jf5540_params, + .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_params), }, [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */ .name = "Samsung PAL TCPM9091PD27", .params = tuner_samsung_pal_tcpm9091pd27_params, + .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_params), }, [TUNER_MT2032] = { /* Microtune PAL|NTSC */ .name = "MT20xx universal", @@ -1127,86 +1159,106 @@ struct tunertype tuners[] = { [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */ .name = "Temic PAL_BG (4106 FH5)", .params = tuner_temic_4106fh5_params, + .count = ARRAY_SIZE(tuner_temic_4106fh5_params), }, [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */ .name = "Temic PAL_DK/SECAM_L (4012 FY5)", .params = tuner_temic_4012fy5_params, + .count = ARRAY_SIZE(tuner_temic_4012fy5_params), }, [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */ .name = "Temic NTSC (4136 FY5)", .params = tuner_temic_4136_fy5_params, + .count = ARRAY_SIZE(tuner_temic_4136_fy5_params), }, [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */ .name = "LG PAL (newer TAPC series)", .params = tuner_lg_pal_new_tapc_params, + .count = ARRAY_SIZE(tuner_lg_pal_new_tapc_params), }, [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */ .name = "Philips PAL/SECAM multi (FM1216ME MK3)", .params = tuner_fm1216me_mk3_params, + .count = ARRAY_SIZE(tuner_fm1216me_mk3_params), }, [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */ .name = "LG NTSC (newer TAPC series)", .params = tuner_lg_ntsc_new_tapc_params, + .count = ARRAY_SIZE(tuner_lg_ntsc_new_tapc_params), }, /* 40-49 */ [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */ .name = "HITACHI V7-J180AT", .params = tuner_hitachi_ntsc_params, + .count = ARRAY_SIZE(tuner_hitachi_ntsc_params), }, [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */ .name = "Philips PAL_MK (FI1216 MK)", .params = tuner_philips_pal_mk_params, + .count = ARRAY_SIZE(tuner_philips_pal_mk_params), }, [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */ .name = "Philips 1236D ATSC/NTSC dual in", .params = tuner_philips_atsc_params, + .count = ARRAY_SIZE(tuner_philips_atsc_params), }, [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */ .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", .params = tuner_fm1236_mk3_params, + .count = ARRAY_SIZE(tuner_fm1236_mk3_params), }, [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */ .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", .params = tuner_philips_4in1_params, + .count = ARRAY_SIZE(tuner_philips_4in1_params), }, [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */ .name = "Microtune 4049 FM5", .params = tuner_microtune_4049_fm5_params, + .count = ARRAY_SIZE(tuner_microtune_4049_fm5_params), }, [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */ .name = "Panasonic VP27s/ENGE4324D", .params = tuner_panasonic_vp27_params, + .count = ARRAY_SIZE(tuner_panasonic_vp27_params), }, [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ .name = "LG NTSC (TAPE series)", .params = tuner_lg_ntsc_tape_params, + .count = ARRAY_SIZE(tuner_lg_ntsc_tape_params), }, [TUNER_TNF_8831BGFF] = { /* Philips PAL */ .name = "Tenna TNF 8831 BGFF)", .params = tuner_tnf_8831bgff_params, + .count = ARRAY_SIZE(tuner_tnf_8831bgff_params), }, [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */ .name = "Microtune 4042 FI5 ATSC/NTSC dual in", .params = tuner_microtune_4042fi5_params, + .count = ARRAY_SIZE(tuner_microtune_4042fi5_params), }, /* 50-59 */ [TUNER_TCL_2002N] = { /* TCL NTSC */ .name = "TCL 2002N", .params = tuner_tcl_2002n_params, + .count = ARRAY_SIZE(tuner_tcl_2002n_params), }, [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */ .name = "Philips PAL/SECAM_D (FM 1256 I-H3)", .params = tuner_philips_fm1256_ih3_params, + .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_params), }, [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */ .name = "Thomson DTT 7610 (ATSC/NTSC)", .params = tuner_thomson_dtt7610_params, + .count = ARRAY_SIZE(tuner_thomson_dtt7610_params), }, [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */ .name = "Philips FQ1286", .params = tuner_philips_fq1286_params, + .count = ARRAY_SIZE(tuner_philips_fq1286_params), }, [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */ .name = "tda8290+75", @@ -1214,22 +1266,27 @@ struct tunertype tuners[] = { [TUNER_TCL_2002MB] = { /* TCL PAL */ .name = "TCL 2002MB", .params = tuner_tcl_2002mb_params, + .count = ARRAY_SIZE(tuner_tcl_2002mb_params), }, [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */ .name = "Philips PAL/SECAM multi (FQ1216AME MK4)", .params = tuner_philips_fq1216ame_mk4_params, + .count = ARRAY_SIZE(tuner_philips_fq1216ame_mk4_params), }, [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */ .name = "Philips FQ1236A MK4", .params = tuner_philips_fq1236a_mk4_params, + .count = ARRAY_SIZE(tuner_philips_fq1236a_mk4_params), }, [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */ .name = "Ymec TVision TVF-8531MF/8831MF/8731MF", .params = tuner_ymec_tvf_8531mf_params, + .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_params), }, [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */ .name = "Ymec TVision TVF-5533MF", .params = tuner_ymec_tvf_5533mf_params, + .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_params), }, /* 60-69 */ @@ -1237,10 +1294,12 @@ struct tunertype tuners[] = { /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ .name = "Thomson DTT 761X (ATSC/NTSC)", .params = tuner_thomson_dtt761x_params, + .count = ARRAY_SIZE(tuner_thomson_dtt761x_params), }, [TUNER_TENA_9533_DI] = { /* Philips PAL */ .name = "Tena TNF9533-D/IF/TNF9533-B/DF", .params = tuner_tena_9533_di_params, + .count = ARRAY_SIZE(tuner_tena_9533_di_params), }, [TUNER_TEA5767] = { /* Philips RADIO */ .name = "Philips TEA5767HN FM Radio", @@ -1249,36 +1308,44 @@ struct tunertype tuners[] = { [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */ .name = "Philips FMD1216ME MK3 Hybrid Tuner", .params = tuner_philips_fmd1216me_mk3_params, + .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params), }, [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */ .name = "LG TDVS-H062F/TUA6034", .params = tuner_tua6034_params, + .count = ARRAY_SIZE(tuner_tua6034_params), }, [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ .name = "Ymec TVF66T5-B/DFF", .params = tuner_ymec_tvf66t5_b_dff_params, + .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_params), }, [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */ .name = "LG NTSC (TALN mini series)", .params = tuner_lg_taln_mini_params, + .count = ARRAY_SIZE(tuner_lg_taln_mini_params), }, [TUNER_PHILIPS_TD1316] = { /* Philips PAL */ .name = "Philips TD1316 Hybrid Tuner", .params = tuner_philips_td1316_params, + .count = ARRAY_SIZE(tuner_philips_td1316_params), }, [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */ .name = "Philips TUV1236D ATSC/NTSC dual in", .params = tuner_tuv1236d_params, + .count = ARRAY_SIZE(tuner_tuv1236d_params), }, [TUNER_TNF_5335MF] = { /* Philips NTSC */ .name = "Tena TNF 5335 MF", .params = tuner_tnf_5335mf_params, + .count = ARRAY_SIZE(tuner_tnf_5335mf_params), }, /* 70-79 */ [TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */ .name = "Samsung TCPN 2121P30A", .params = tuner_samsung_tcpn_2121p30a_params, + .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_params), }, }; diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index 53ac66e0114b..ad9c171bfa07 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -46,6 +46,7 @@ struct tuner_params { struct tunertype { char *name; + unsigned int count; struct tuner_params *params; }; -- cgit v1.2.3-59-g8ed1b From 17801f5fa2e31b60f26aadd7ba41395dd1b1093e Mon Sep 17 00:00:00 2001 From: Marcin Rudowski Date: Mon, 6 Feb 2006 09:15:14 -0200 Subject: V4L/DVB (3266): Fix NICAM buzz on analog sound Apparently, having the number of lines fixed at 4 reduces (or even kills) the buzz found in NICAM stereo with analog sound. Signed-off-by: Marcin Rudowski Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 8d6d6a6cf785..3720f24a25cf 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -787,12 +787,14 @@ static int set_pll(struct cx88_core *core, int prescale, u32 ofreq) int cx88_start_audio_dma(struct cx88_core *core) { + /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */ + int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4; /* setup fifo + format */ - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0); - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0); - cx_write(MO_AUDD_LNGTH, 128); /* fifo bpl size */ - cx_write(MO_AUDR_LNGTH, 128); /* fifo bpl size */ + cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */ + cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */ /* start dma */ cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */ -- cgit v1.2.3-59-g8ed1b From fe9313956d67367cc91c5a6989bafc4315801402 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 3 Feb 2006 01:45:12 -0800 Subject: [PATCH] git-netdev-all: s2io fixes Fix this: drivers/built-in.o(.text+0x89469): In function `s2io_get_ethtool_stats': drivers/net/s2io.c:5209: undefined reference to `__udivdi3' Cc: Ravinandan Arakali Cc: Ananda Raju Cc: Adrian Bunk Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/s2io.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 4e392914971e..e7a9b0d32a18 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -64,6 +64,7 @@ #include #include #include +#include /* local include */ #include "s2io.h" @@ -5110,6 +5111,7 @@ static void s2io_get_ethtool_stats(struct net_device *dev, int i = 0; nic_t *sp = dev->priv; StatInfo_t *stat_info = sp->mac_control.stats_info; + u64 tmp; s2io_updt_stats(sp); tmp_stats[i++] = @@ -5205,12 +5207,12 @@ static void s2io_get_ethtool_stats(struct net_device *dev, tmp_stats[i++] = stat_info->sw_stat.sending_both; tmp_stats[i++] = stat_info->sw_stat.outof_sequence_pkts; tmp_stats[i++] = stat_info->sw_stat.flush_max_pkts; - if (stat_info->sw_stat.num_aggregations) - tmp_stats[i++] = stat_info->sw_stat.sum_avg_pkts_aggregated / - stat_info->sw_stat.num_aggregations; - else - tmp_stats[i++] = 0; - + tmp = 0; + if (stat_info->sw_stat.num_aggregations) { + tmp = stat_info->sw_stat.sum_avg_pkts_aggregated; + do_div(tmp, stat_info->sw_stat.num_aggregations); + } + tmp_stats[i++] = tmp; } static int s2io_ethtool_get_regs_len(struct net_device *dev) -- cgit v1.2.3-59-g8ed1b From 79dc190147f8a87718fe72928d5ceb58e09acdb9 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 3 Feb 2006 01:45:13 -0800 Subject: [PATCH] s2io c99 warning fix drivers/net/s2io.c: In function `verify_l3_l4_lro_capable': drivers/net/s2io.c:6638: warning: ISO C90 forbids mixed declarations and code Cc: Ravinandan Arakali Cc: Ananda Raju Cc: Adrian Bunk Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/s2io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index e7a9b0d32a18..fcce43c9fed5 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -6634,9 +6634,10 @@ static void aggregate_new_rx(lro_t *lro, struct iphdr *ip, static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len) { - DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); u8 *ptr; + DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); + if (!tcp_pyld_len) { /* Runt frame or a pure ack */ return -1; -- cgit v1.2.3-59-g8ed1b From a78d0bfabda67dd40a5a97ba4c24265e1820e7ea Mon Sep 17 00:00:00 2001 From: Jose Alberto Reguero Date: Tue, 7 Feb 2006 06:25:14 -0200 Subject: V4L/DVB (3267): Add support for the Avermedia 777 DVB-T card Signed-off-by: Jose Alberto Reguero Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/dvb/frontends/dvb-pll.c | 42 +++++++++++++++++++++++++++++ drivers/media/dvb/frontends/dvb-pll.h | 1 + drivers/media/video/saa7134/saa7134-cards.c | 24 +++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 41 +++++++++++++++++++++++++++- drivers/media/video/saa7134/saa7134.h | 1 + 6 files changed, 109 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 8a352597830f..636792e2e154 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -83,3 +83,4 @@ 82 -> MSI TV@Anywhere plus [1462:6231] 83 -> Terratec Cinergy 250 PCI TV [153b:1160] 84 -> LifeView FlyDVB Trio [5168:0319] + 85 -> AverTV DVB-T 777 [1461:2c05] diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index cd8f28275ed6..4f682534df42 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -362,6 +362,48 @@ struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = { }; EXPORT_SYMBOL(dvb_pll_philips_sd1878_tda8261); +/* + * Philips TD1316 Tuner. + */ +static void td1316_bw(u8 *buf, u32 freq, int bandwidth) +{ + u8 band; + + /* determine band */ + if (freq < 161000000) + band = 1; + else if (freq < 444000000) + band = 2; + else + band = 4; + + buf[3] |= band; + + /* setup PLL filter */ + if (bandwidth == BANDWIDTH_8_MHZ) + buf[3] |= 1 << 3; +} + +struct dvb_pll_desc dvb_pll_philips_td1316 = { + .name = "Philips TD1316", + .min = 87000000, + .max = 895000000, + .setbw = td1316_bw, + .count = 9, + .entries = { + { 93834000, 36166000, 166666, 0xca, 0x60}, + { 123834000, 36166000, 166666, 0xca, 0xa0}, + { 163834000, 36166000, 166666, 0xca, 0xc0}, + { 253834000, 36166000, 166666, 0xca, 0x60}, + { 383834000, 36166000, 166666, 0xca, 0xa0}, + { 443834000, 36166000, 166666, 0xca, 0xc0}, + { 583834000, 36166000, 166666, 0xca, 0x60}, + { 793834000, 36166000, 166666, 0xca, 0xa0}, + { 858834000, 36166000, 166666, 0xca, 0xe0}, + }, +}; +EXPORT_SYMBOL(dvb_pll_philips_td1316); + /* ----------------------------------------------------------- */ /* code */ diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 872e3b4c1396..56c3cd76a7fa 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -40,6 +40,7 @@ extern struct dvb_pll_desc dvb_pll_tuv1236d; extern struct dvb_pll_desc dvb_pll_tdhu2; extern struct dvb_pll_desc dvb_pll_samsung_tbmv; extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261; +extern struct dvb_pll_desc dvb_pll_philips_td1316; int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, u32 freq, int bandwidth); diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 5a35d3b6550d..3f964ed7eb56 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2619,6 +2619,24 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, }, + [SAA7134_BOARD_AVERMEDIA_777] = { + .name = "AverTV DVB-T 777", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_comp1, + .vmux = 0, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3089,6 +3107,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x5168, .subdevice = 0x0319, .driver_data = SAA7134_BOARD_FLYDVB_TRIO, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, /* SAA 7131E */ + .subvendor = 0x1461, + .subdevice = 0x2c05, + .driver_data = SAA7134_BOARD_AVERMEDIA_777, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 1a536e865277..45b52575e16b 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -32,6 +32,7 @@ #include "saa7134-reg.h" #include "saa7134.h" #include +#include "dvb-pll.h" #ifdef HAVE_MT352 # include "mt352.h" @@ -42,7 +43,6 @@ #endif #ifdef HAVE_NXT200X # include "nxt200x.h" -# include "dvb-pll.h" #endif MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); @@ -113,6 +113,24 @@ static int mt352_pinnacle_init(struct dvb_frontend* fe) return 0; } +static int mt352_aver777_init(struct dvb_frontend* fe) +{ + static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x2d }; + static u8 reset [] = { RESET, 0x80 }; + static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; + static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0xa0 }; + static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 }; + + mt352_write(fe, clock_config, sizeof(clock_config)); + udelay(200); + mt352_write(fe, reset, sizeof(reset)); + mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); + mt352_write(fe, agc_cfg, sizeof(agc_cfg)); + mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); + + return 0; +} + static int mt352_pinnacle_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) @@ -142,6 +160,15 @@ static int mt352_pinnacle_pll_set(struct dvb_frontend* fe, return 0; } +static int mt352_aver777_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf) +{ + pllbuf[0] = 0xc2; + dvb_pll_configure(&dvb_pll_philips_td1316, pllbuf+1, + params->frequency, + params->u.ofdm.bandwidth); + return 0; +} + static struct mt352_config pinnacle_300i = { .demod_address = 0x3c >> 1, .adc_clock = 20333, @@ -150,6 +177,12 @@ static struct mt352_config pinnacle_300i = { .demod_init = mt352_pinnacle_init, .pll_set = mt352_pinnacle_pll_set, }; + +static struct mt352_config avermedia_777 = { + .demod_address = 0xf, + .demod_init = mt352_aver777_init, + .pll_set = mt352_aver777_pll_set, +}; #endif /* ------------------------------------------------------------------ */ @@ -847,6 +880,12 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = mt352_attach(&pinnacle_300i, &dev->i2c_adap); break; + + case SAA7134_BOARD_AVERMEDIA_777: + printk("%s: avertv 777 dvb setup\n",dev->name); + dev->dvb.frontend = mt352_attach(&avermedia_777, + &dev->i2c_adap); + break; #endif #ifdef HAVE_TDA1004X case SAA7134_BOARD_MD7134: diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 3261d8bebdd1..3b8f466c7e17 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -210,6 +210,7 @@ struct saa7134_format { #define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS 82 #define SAA7134_BOARD_CINERGY250PCI 83 #define SAA7134_BOARD_FLYDVB_TRIO 84 +#define SAA7134_BOARD_AVERMEDIA_777 85 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3-59-g8ed1b From 5f5941872c0035cb4624efe8c5a1dfbb89d199e7 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 7 Feb 2006 06:25:33 -0200 Subject: V4L/DVB (3268): Move video std detection to top of set_tv_freq function - move video std detection to top of set_tv_freq function - we must detect video std first, so that we can choose the correct tuner_params Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 68 +++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 6f0d376f0d18..907ea8c5d9b3 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -142,6 +142,29 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) tun = &tuners[t->type]; j = TUNER_PARAM_ANALOG; + /* IFPCoff = Video Intermediate Frequency - Vif: + 940 =16*58.75 NTSC/J (Japan) + 732 =16*45.75 M/N STD + 704 =16*44 ATSC (at DVB code) + 632 =16*39.50 I U.K. + 622.4=16*38.90 B/G D/K I, L STD + 592 =16*37.00 D China + 590 =16.36.875 B Australia + 543.2=16*33.95 L' STD + 171.2=16*10.70 FM Radio (at set_radio_freq) + */ + + if (t->std == V4L2_STD_NTSC_M_JP) { + IFPCoff = 940; + } else if ((t->std & V4L2_STD_MN) && + !(t->std & ~V4L2_STD_MN)) { + IFPCoff = 732; + } else if (t->std == V4L2_STD_SECAM_LC) { + IFPCoff = 543; + } else { + IFPCoff = 623; + } + for (i = 0; i < tun->params[j].count; i++) { if (freq > tun->params[j].ranges[i].limit) continue; @@ -154,11 +177,19 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) } config = tun->params[j].ranges[i].config; cb = tun->params[j].ranges[i].cb; - /* i == 0 -> VHF_LO */ - /* i == 1 -> VHF_HI */ - /* i == 2 -> UHF */ + /* i == 0 -> VHF_LO + * i == 1 -> VHF_HI + * i == 2 -> UHF */ tuner_dbg("tv: range %d\n",i); + div=freq + IFPCoff + offset; + + tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n", + freq / 16, freq % 16 * 100 / 16, + IFPCoff / 16, IFPCoff % 16 * 100 / 16, + offset / 16, offset % 16 * 100 / 16, + div); + /* tv norm specific stuff for multi-norm tuners */ switch (t->type) { case TUNER_PHILIPS_SECAM: // FI1216MF @@ -245,37 +276,6 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) break; } - /* IFPCoff = Video Intermediate Frequency - Vif: - 940 =16*58.75 NTSC/J (Japan) - 732 =16*45.75 M/N STD - 704 =16*44 ATSC (at DVB code) - 632 =16*39.50 I U.K. - 622.4=16*38.90 B/G D/K I, L STD - 592 =16*37.00 D China - 590 =16.36.875 B Australia - 543.2=16*33.95 L' STD - 171.2=16*10.70 FM Radio (at set_radio_freq) - */ - - if (t->std == V4L2_STD_NTSC_M_JP) { - IFPCoff = 940; - } else if ((t->std & V4L2_STD_MN) && - !(t->std & ~V4L2_STD_MN)) { - IFPCoff = 732; - } else if (t->std == V4L2_STD_SECAM_LC) { - IFPCoff = 543; - } else { - IFPCoff = 623; - } - - div=freq + IFPCoff + offset; - - tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n", - freq / 16, freq % 16 * 100 / 16, - IFPCoff / 16, IFPCoff % 16 * 100 / 16, - offset / 16, offset % 16 * 100 / 16, - div); - if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) { buffer[0] = config; buffer[1] = cb; -- cgit v1.2.3-59-g8ed1b From 476d63d061a082bcb833009e15a3632459a3caad Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 7 Feb 2006 06:25:34 -0200 Subject: V4L/DVB (3269): Allow multiple tuner params in each tuner definition - allow multiple tuner params in each tuner definition. - the correct tuner_params element will be chosen based on current video standard. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 907ea8c5d9b3..58fa0d29962b 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -79,14 +79,13 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); #define TUNER_PLL_LOCKED 0x40 #define TUNER_STEREO_MK3 0x04 -#define TUNER_PARAM_ANALOG 0 /* to be removed */ /* FIXME: * Right now, all tuners are using the first tuner_params[] array element * for analog mode. In the future, we will be merging similar tuner * definitions together, such that each tuner definition will have a * tuner_params struct for each available video standard. At that point, - * TUNER_PARAM_ANALOG will be removed, and the tuner_params[] array - * element will be chosen based on the video standard in use. + * the tuner_params[] array element will be chosen based on the video + * standard in use. * */ @@ -138,9 +137,9 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) struct tunertype *tun; u8 buffer[4]; int rc, IFPCoff, i, j; + enum param_type desired_type; tun = &tuners[t->type]; - j = TUNER_PARAM_ANALOG; /* IFPCoff = Video Intermediate Frequency - Vif: 940 =16*58.75 NTSC/J (Japan) @@ -155,16 +154,25 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) */ if (t->std == V4L2_STD_NTSC_M_JP) { - IFPCoff = 940; + IFPCoff = 940; + desired_type = TUNER_PARAM_TYPE_NTSC; } else if ((t->std & V4L2_STD_MN) && !(t->std & ~V4L2_STD_MN)) { - IFPCoff = 732; + IFPCoff = 732; + desired_type = TUNER_PARAM_TYPE_NTSC; } else if (t->std == V4L2_STD_SECAM_LC) { - IFPCoff = 543; + IFPCoff = 543; + desired_type = TUNER_PARAM_TYPE_SECAM; } else { - IFPCoff = 623; + IFPCoff = 623; + desired_type = TUNER_PARAM_TYPE_PAL; } + for (j = 0; j < tun->count-1; j++) { + if (desired_type != tun->params[j].type) + continue; + break; + } for (i = 0; i < tun->params[j].count; i++) { if (freq > tun->params[j].ranges[i].limit) continue; @@ -333,9 +341,15 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) u8 buffer[4]; u16 div; int rc, j; + enum param_type desired_type = TUNER_PARAM_TYPE_RADIO; tun = &tuners[t->type]; - j = TUNER_PARAM_ANALOG; + + for (j = 0; j < tun->count-1; j++) { + if (desired_type != tun->params[j].type) + continue; + break; + } div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */ buffer[2] = (tun->params[j].ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ -- cgit v1.2.3-59-g8ed1b From bd0d0f59ca56c7ef063d714e9b602fcaa5c11072 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 7 Feb 2006 06:25:35 -0200 Subject: V4L/DVB (3270): Tuner_dbg will show tuner param and range selected - tuner_dbg will show tuner param and range selected Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 58fa0d29962b..17e29cc60c90 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -188,7 +188,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) /* i == 0 -> VHF_LO * i == 1 -> VHF_HI * i == 2 -> UHF */ - tuner_dbg("tv: range %d\n",i); + tuner_dbg("tv: param %d, range %d\n",j,i); div=freq + IFPCoff + offset; -- cgit v1.2.3-59-g8ed1b From 99d33d5012c31c6c2b7ad5658654d7c5f0d606d1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 7 Feb 2006 06:25:36 -0200 Subject: V4L/DVB (3271): Update tuner comments Right now, all tuners are using the first tuner_params[] array element for analog mode. We are now ready to begin merging similar tuner definitions together, such that each tuner definition will have a tuner_params struct for each available video standard. The tuner_params[] array element will be chosen based on the video standard in use. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 10 ---------- drivers/media/video/tuner-types.c | 15 +++++++++------ 2 files changed, 9 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 17e29cc60c90..2e680cf515a2 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -79,16 +79,6 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); #define TUNER_PLL_LOCKED 0x40 #define TUNER_STEREO_MK3 0x04 -/* FIXME: - * Right now, all tuners are using the first tuner_params[] array element - * for analog mode. In the future, we will be merging similar tuner - * definitions together, such that each tuner definition will have a - * tuner_params struct for each available video standard. At that point, - * the tuner_params[] array element will be chosen based on the video - * standard in use. - * - */ - /* ---------------------------------------------------------------------- */ static int tuner_getstatus(struct i2c_client *c) diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 27fc4d06b1d2..9786e590624a 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -23,13 +23,16 @@ * Each tuner_params array may contain one or more elements, one * for each video standard. * - * FIXME: Some tuner_range definitions are duplicated, and - * should be eliminated. + * FIXME: tuner_params struct contains an element, tda988x. We must + * set this for all tuners that contain a tda988x chip, and then we + * can remove this setting from the various card structs. * - * FIXME: tunertype struct contains an element, has_tda988x. - * We must set this for all tunertypes that contain a tda988x - * chip, and then we can remove this setting from the various - * card structs. + * FIXME: Right now, all tuners are using the first tuner_params[] + * array element for analog mode. In the future, we will be merging + * similar tuner definitions together, such that each tuner definition + * will have a tuner_params struct for each available video standard. + * At that point, the tuner_params[] array element will be chosen + * based on the video standard in use. */ /* 0-9 */ -- cgit v1.2.3-59-g8ed1b From f7d66e82c6df37043ddd41ec9ec893844d3a18be Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 7 Feb 2006 06:25:37 -0200 Subject: V4L/DVB (3275): Allow SAA7134 to fall back to AM sound when there is NICAM-L This patch allows to select AM sound even if NICAM is detected. Proposed by Alain Frappin Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-tvaudio.c | 14 ++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 2 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index afa4dcb3f96d..3043233a8b6e 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -139,6 +139,12 @@ static struct saa7134_tvaudio tvaudio[] = { .carr1 = 6500, .carr2 = 5850, .mode = TVAUDIO_NICAM_AM, + },{ + .name = "SECAM-L MONO", + .std = V4L2_STD_SECAM, + .carr1 = 6500, + .carr2 = -1, + .mode = TVAUDIO_AM_MONO, },{ .name = "SECAM-D/K", .std = V4L2_STD_SECAM, @@ -334,6 +340,12 @@ static void tvaudio_setmode(struct saa7134_dev *dev, saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0xa1); saa_writeb(SAA7134_NICAM_CONFIG, 0x00); break; + case TVAUDIO_AM_MONO: + saa_writeb(SAA7134_DEMODULATOR, 0x12); + saa_writeb(SAA7134_DCXO_IDENT_CTRL, 0x00); + saa_writeb(SAA7134_FM_DEEMPHASIS, 0x44); + saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0xa0); + break; case TVAUDIO_FM_SAT_STEREO: /* not implemented (yet) */ break; @@ -414,6 +426,7 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au switch (audio->mode) { case TVAUDIO_FM_MONO: + case TVAUDIO_AM_MONO: return V4L2_TUNER_SUB_MONO; case TVAUDIO_FM_K_STEREO: case TVAUDIO_FM_BG_STEREO: @@ -480,6 +493,7 @@ static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au switch (audio->mode) { case TVAUDIO_FM_MONO: + case TVAUDIO_AM_MONO: /* nothing to do ... */ break; case TVAUDIO_FM_K_STEREO: diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 3b8f466c7e17..b638df941ff9 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -60,6 +60,7 @@ enum saa7134_tvaudio_mode { TVAUDIO_FM_K_STEREO = 4, TVAUDIO_NICAM_AM = 5, TVAUDIO_NICAM_FM = 6, + TVAUDIO_AM_MONO = 7 }; enum saa7134_audio_in { -- cgit v1.2.3-59-g8ed1b From 4d17d0834a2e6a5cba096ea09592a4a096183300 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 7 Feb 2006 06:25:39 -0200 Subject: V4L/DVB (3276): Added terratec hybrid xs and kworld 2800rf support - Added terratec hybrid xs product/vendorid - Added gpio audio initialization for kworld pvr 2800rf Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 1 + drivers/media/video/em28xx/em28xx-cards.c | 56 ++++++++++++++++++++++++++++--- drivers/media/video/em28xx/em28xx.h | 4 ++- 3 files changed, 56 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index a0c7cad20971..7a903f7080c3 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -8,3 +8,4 @@ 7 -> Leadtek Winfast USB II (em2800) 8 -> Kworld USB2800 (em2800) 9 -> Pinnacle Dazzle DVC 90 (em2820/em2840) [2304:0207] + 12 -> Unknown EM2820/2840 video grabber (em2820/em2840) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ed428c58b73d..573d24d2a18d 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -72,6 +72,24 @@ struct em28xx_board em28xx_boards[] = { .amux = 1, }}, }, + [EM2820_BOARD_KWORLD_PVRTV2800RF] = { + .name = "Unknown EM2820/2840 video grabber", + .is_em2800 = 0, + .vchannels = 2, + .norm = VIDEO_MODE_PAL, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM28XX_SAA7113, + .input = {{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, [EM2820_BOARD_TERRATEC_CINERGY_250] = { .name = "Terratec Cinergy 250 USB", .vchannels = 3, @@ -136,8 +154,30 @@ struct em28xx_board em28xx_boards[] = { .amux = 1, }}, }, - [EM2880_BOARD_WINTV_HVR_900] = { - .name = "WinTV HVR 900", + [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { + .name = "Hauppauge WinTV HVR 900", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .has_tuner = 0, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM28XX_TVP5150, + .input = {{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 2, + .amux = 0, + },{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2880_BOARD_TERRATEC_HYBRID_XS] = { + .name = "Terratec Hybrid XS", .vchannels = 3, .norm = VIDEO_MODE_PAL, .has_tuner = 0, @@ -276,7 +316,8 @@ struct usb_device_id em28xx_id_table [] = { { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, - { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_WINTV_HVR_900 }, + { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, + { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, { }, }; @@ -284,7 +325,8 @@ void em28xx_pre_card_setup(struct em28xx *dev) { /* request some modules */ switch(dev->model){ - case EM2880_BOARD_WINTV_HVR_900: + case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: + case EM2880_BOARD_TERRATEC_HYBRID_XS: { em28xx_write_regs_req(dev, 0x00, 0x08, "\x7d", 1); // reset through GPIO? break; @@ -317,6 +359,12 @@ void em28xx_card_setup(struct em28xx *dev) dev->has_msp34xx=0; break; } + case EM2820_BOARD_KWORLD_PVRTV2800RF: + { + em28xx_write_regs_req(dev,0x00,0x08, "\xf9", 1); // GPIO enables sound on KWORLD PVR TV 2800RF + break; + } + } } diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 8269cca7dcdb..ddf06c520e99 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -41,7 +41,9 @@ #define EM2800_BOARD_LEADTEK_WINFAST_USBII 7 #define EM2800_BOARD_KWORLD_USB2800 8 #define EM2820_BOARD_PINNACLE_DVC_90 9 -#define EM2880_BOARD_WINTV_HVR_900 10 +#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10 +#define EM2880_BOARD_TERRATEC_HYBRID_XS 11 +#define EM2820_BOARD_KWORLD_PVRTV2800RF 12 #define UNSET -1 -- cgit v1.2.3-59-g8ed1b From 8f1a58d0fccacb5d61aed8a63c3920c8acc155e7 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 7 Feb 2006 06:25:39 -0200 Subject: V4L/DVB (3277): Use default tuner_params if desired_type not available If a given tuner definition contains more than one tuner_params array members, it will try to select the appropriate tuner_params based on the video standard in use. If there is no tuner_params defined for the current video standard, it will select the default, tuner_params[0] Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 2e680cf515a2..61dd26a43976 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -163,6 +163,10 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) continue; break; } + /* use default tuner_params if desired_type not available */ + if (desired_type != tun->params[j].type) + j = 0; + for (i = 0; i < tun->params[j].count; i++) { if (freq > tun->params[j].ranges[i].limit) continue; @@ -340,6 +344,9 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) continue; break; } + /* use default tuner_params if desired_type not available */ + if (desired_type != tun->params[j].type) + j = 0; div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */ buffer[2] = (tun->params[j].ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ -- cgit v1.2.3-59-g8ed1b From 15207b2e73afb3aa6cd96a1b8c0b5016bcf90128 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 7 Feb 2006 06:25:40 -0200 Subject: V4L/DVB (3278): Show debug for tuners trying to use unsupported video standards With tuner_debug enabled, if a tuner tries to use a video standard that doesn't have a matching tuner_params defined, the IFPCoff value and tuner number will be displayed, and the default tuner_params entry will be used. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 61dd26a43976..aba0688d7c1c 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -164,8 +164,11 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) break; } /* use default tuner_params if desired_type not available */ - if (desired_type != tun->params[j].type) + if (desired_type != tun->params[j].type) { + tuner_dbg("IFPCoff = %d: tuner_params undefined for tuner %d\n", + IFPCoff,t->type); j = 0; + } for (i = 0; i < tun->params[j].count; i++) { if (freq > tun->params[j].ranges[i].limit) -- cgit v1.2.3-59-g8ed1b From 33ccaa3feb2a6e09942b6f0af6fbb0451a2e1537 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 7 Feb 2006 06:25:41 -0200 Subject: V4L/DVB (3280): Changed description of KWorld PVR TV 2800RF Changed description of KWorld PVR TV 2800RF Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 2 +- drivers/media/video/em28xx/em28xx-cards.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 7a903f7080c3..a3026689bbe6 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -8,4 +8,4 @@ 7 -> Leadtek Winfast USB II (em2800) 8 -> Kworld USB2800 (em2800) 9 -> Pinnacle Dazzle DVC 90 (em2820/em2840) [2304:0207] - 12 -> Unknown EM2820/2840 video grabber (em2820/em2840) + 12 -> Kworld PVR TV 2800 RF (em2820/em2840) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 573d24d2a18d..a9e7cec17a6b 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -73,7 +73,7 @@ struct em28xx_board em28xx_boards[] = { }}, }, [EM2820_BOARD_KWORLD_PVRTV2800RF] = { - .name = "Unknown EM2820/2840 video grabber", + .name = "Kworld PVR TV 2800 RF", .is_em2800 = 0, .vchannels = 2, .norm = VIDEO_MODE_PAL, -- cgit v1.2.3-59-g8ed1b From 19d7509c0531b0e08f52ab93070569e0aba54cdf Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 7 Feb 2006 06:38:24 -0200 Subject: V4L/DVB (3281): Added signal detection support to tvp5150 - added signal detection support to tvp5150 Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp5150.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 20e63593e441..3ae8a9ff5b13 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -967,6 +967,17 @@ static int tvp5150_command(struct i2c_client *c, } case DECODER_GET_STATUS: { + int *iarg = arg; + int status; + int res=0; + status = tvp5150_read(c, 0x88); + if(status&0x08){ + res |= DECODER_STATUS_COLOR; + } + if(status&0x04 && status&0x02){ + res |= DECODER_STATUS_GOOD; + } + *iarg=res; break; } -- cgit v1.2.3-59-g8ed1b From 6a5b28f9b7688638eed23b891d6bf5d9aaca94d3 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 7 Feb 2006 06:45:30 -0200 Subject: V4L/DVB (3294): Fix [Bug 5895] to correct snd_87x autodetect With DVB drivers enabled snd_87x (ALSA) don't detect. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/bt878.c | 44 ++++++++++++++++++++++++++++++++++++++++- drivers/media/dvb/bt8xx/bt878.h | 17 ++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index a04bb61f21f4..34c3189a1a33 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -381,6 +381,23 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet * EXPORT_SYMBOL(bt878_device_control); + +struct cards card_list[] __devinitdata = { + + { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, + { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, + { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" }, + { 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, + { 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" }, + { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, + { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, + { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, + { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, + { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, + { 0, -1, NULL } +}; + + /***********************/ /* PCI device handling */ /***********************/ @@ -388,18 +405,41 @@ EXPORT_SYMBOL(bt878_device_control); static int __devinit bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { - int result; + int result = 0, has_dvb = 0, i; unsigned char lat; struct bt878 *bt; #if defined(__powerpc__) unsigned int cmd; #endif + unsigned int cardid; + unsigned short id; + struct cards *dvb_cards; printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n", bt878_num); if (pci_enable_device(dev)) return -EIO; + pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &id); + cardid = id << 16; + pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &id); + cardid |= id; + + for (i = 0, dvb_cards = card_list; i < ARRAY_SIZE(card_list); i++, dvb_cards++) { + if (cardid == dvb_cards->pci_id) { + printk("%s: card id=[0x%x],[ %s ] has DVB functions.\n", + __func__, cardid, dvb_cards->name); + has_dvb = 1; + } + } + + if (!has_dvb) { + printk("%s: card id=[0x%x], Unknown card.\nExiting..\n", __func__, cardid); + result = -EINVAL; + + goto fail0; + } + bt = &bt878[bt878_num]; bt->dev = dev; bt->nr = bt878_num; @@ -416,6 +456,8 @@ static int __devinit bt878_probe(struct pci_dev *dev, pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision); pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + + printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ", bt878_num, bt->id, bt->revision, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h index a73baf00ca39..9faf93770d08 100644 --- a/drivers/media/dvb/bt8xx/bt878.h +++ b/drivers/media/dvb/bt8xx/bt878.h @@ -88,6 +88,23 @@ #define BT878_RISC_SYNC_MASK (1 << 15) + +#define BTTV_BOARD_UNKNOWN 0x00 +#define BTTV_BOARD_PINNACLESAT 0x5e +#define BTTV_BOARD_NEBULA_DIGITV 0x68 +#define BTTV_BOARD_PC_HDTV 0x70 +#define BTTV_BOARD_TWINHAN_DST 0x71 +#define BTTV_BOARD_AVDVBT_771 0x7b +#define BTTV_BOARD_AVDVBT_761 0x7c +#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 +#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 + +struct cards { + __u32 pci_id; + __u16 card_id; + char *name; +}; + extern int bt878_num; struct bt878 { -- cgit v1.2.3-59-g8ed1b From 28ecc4490100488663f1a978846632800ab198d5 Mon Sep 17 00:00:00 2001 From: Marco Manenti Date: Tue, 7 Feb 2006 06:45:33 -0200 Subject: V4L/DVB (3297): Add IR support to KWorld DVB-T (cx22702-based) add IR support to KWorld DVB-T (cx22702-based) Signed-off-by: Marco Manenti Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-input.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 800e2b31ac7b..f2fba57f955b 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -151,6 +151,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) switch (core->board) { case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_KWORLD_DVB_T: + case CX88_BOARD_KWORLD_DVB_T_CX22702: ir_codes = ir_codes_dntv_live_dvb_t; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; -- cgit v1.2.3-59-g8ed1b From 8a8832a8eb5a824261a63c22befb4a8c193d4d02 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 7 Feb 2006 06:45:33 -0200 Subject: V4L/DVB (3299): Kconfig: DVB_USB_CXUSB depends on DVB_LGDT330X and DVB_MT352 - rename DVB_USB_CXUSB one-liner description to: Conexant USB2.0 hybrid reference design support. - with the addition of bluebird support to dvb-usb-cxusb, it now depends on lgdt330x and mt352 modules. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 90a69d343b79..d3df12039b06 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -83,12 +83,18 @@ config DVB_USB_UMT_010 Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. config DVB_USB_CXUSB - tristate "Medion MD95700 hybrid USB2.0 (Conexant) support" + tristate "Conexant USB2.0 hybrid reference design support" depends on DVB_USB select DVB_CX22702 + select DVB_LGDT330X + select DVB_MT352 help - Say Y here to support the Medion MD95700 hybrid USB2.0 device. Currently - only the DVB-T part is supported. + Say Y here to support the Conexant USB2.0 hybrid reference design. + Currently, only DVB and ATSC modes are supported, analog mode + shall be added in the future. Devices that require this module: + + Medion MD95700 hybrid USB2.0 device. + DViCO FusionHDTV (Bluebird) USB2.0 devices config DVB_USB_DIGITV tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" -- cgit v1.2.3-59-g8ed1b From d97a11e091a0bf40f1cfb0bbf443ddd7b455b133 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 7 Feb 2006 06:48:40 -0200 Subject: V4L/DVB (3300): Add standard for South Korean NTSC-M using A2 audio. South Korea uses NTSC-M but with A2 audio instead of BTSC. Several audio chips need this information in order to set the correct audio processing registers. Acked-by: Mauro Carvalho Chehab Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bttv-driver.c | 2 +- drivers/media/video/cx25840/cx25840-core.c | 50 ++++++++++++------------------ drivers/media/video/tda9887.c | 7 ++++- drivers/media/video/tuner-core.c | 5 +++ include/linux/videodev2.h | 4 ++- 5 files changed, 35 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index aa4c4c521880..578b20085082 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -214,7 +214,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { we can capture, of the first and second field. */ .vbistart = { 7,320 }, },{ - .v4l2_id = V4L2_STD_NTSC_M, + .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, .name = "NTSC", .Fsc = 28636363, .swidth = 768, diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 3acd587b160c..8d8aa8ec8304 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -220,33 +220,23 @@ static void input_change(struct i2c_client *client) cx25840_write(client, 0x808, 0xff); cx25840_write(client, 0x80b, 0x10); } else if (std & V4L2_STD_NTSC) { - /* NTSC */ - if (state->pvr150_workaround) { - /* Certain Hauppauge PVR150 models have a hardware bug - that causes audio to drop out. For these models the - audio standard must be set explicitly. - To be precise: it affects cards with tuner models - 85, 99 and 112 (model numbers from tveeprom). */ - if (std == V4L2_STD_NTSC_M_JP) { - /* Japan uses EIAJ audio standard */ - cx25840_write(client, 0x808, 0x2f); - } else { - /* Others use the BTSC audio standard */ - cx25840_write(client, 0x808, 0x1f); - } - /* South Korea uses the A2-M (aka Zweiton M) audio - standard, and should set 0x808 to 0x3f, but I don't - know how to detect this. */ - } else if (std == V4L2_STD_NTSC_M_JP) { + /* Certain Hauppauge PVR150 models have a hardware bug + that causes audio to drop out. For these models the + audio standard must be set explicitly. + To be precise: it affects cards with tuner models + 85, 99 and 112 (model numbers from tveeprom). */ + int hw_fix = state->pvr150_workaround; + + if (std == V4L2_STD_NTSC_M_JP) { /* Japan uses EIAJ audio standard */ - cx25840_write(client, 0x808, 0xf7); + cx25840_write(client, 0x808, hw_fix ? 0x2f : 0xf7); + } else if (std == V4L2_STD_NTSC_M_KR) { + /* South Korea uses A2 audio standard */ + cx25840_write(client, 0x808, hw_fix ? 0x3f : 0xf8); } else { /* Others use the BTSC audio standard */ - cx25840_write(client, 0x808, 0xf6); + cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6); } - /* South Korea uses the A2-M (aka Zweiton M) audio standard, - and should set 0x808 to 0xf8, but I don't know how to - detect this. */ cx25840_write(client, 0x80b, 0x00); } @@ -330,17 +320,17 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) u8 fmt=0; /* zero is autodetect */ /* First tests should be against specific std */ - if (std & V4L2_STD_NTSC_M_JP) { + if (std == V4L2_STD_NTSC_M_JP) { fmt=0x2; - } else if (std & V4L2_STD_NTSC_443) { + } else if (std == V4L2_STD_NTSC_443) { fmt=0x3; - } else if (std & V4L2_STD_PAL_M) { + } else if (std == V4L2_STD_PAL_M) { fmt=0x5; - } else if (std & V4L2_STD_PAL_N) { + } else if (std == V4L2_STD_PAL_N) { fmt=0x6; - } else if (std & V4L2_STD_PAL_Nc) { + } else if (std == V4L2_STD_PAL_Nc) { fmt=0x7; - } else if (std & V4L2_STD_PAL_60) { + } else if (std == V4L2_STD_PAL_60) { fmt=0x8; } else { /* Then, test against generic ones */ @@ -369,7 +359,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) } switch (fmt) { - case 0x1: return V4L2_STD_NTSC_M; + case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR; case 0x2: return V4L2_STD_NTSC_M_JP; case 0x3: return V4L2_STD_NTSC_443; case 0x4: return V4L2_STD_PAL; diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 7c71422f5d3f..0d54f6c1982b 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -231,7 +231,7 @@ static struct tvnorm tvnorms[] = { cAudioIF_6_5 | cVideoIF_38_90 ), },{ - .std = V4L2_STD_NTSC_M, + .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, .name = "NTSC-M", .b = ( cNegativeFmTV | cQSS ), @@ -619,6 +619,11 @@ static int tda9887_fixup_std(struct tda9887 *t) tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); t->std = V4L2_STD_NTSC_M_JP; break; + case 'k': + case 'K': + tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); + t->std = V4L2_STD_NTSC_M_KR; + break; case '-': /* default parameter, do nothing */ break; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 788eadaae672..e34f801c9a10 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -366,6 +366,11 @@ static int tuner_fixup_std(struct tuner *t) tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); t->std = V4L2_STD_NTSC_M_JP; break; + case 'k': + case 'K': + tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); + t->std = V4L2_STD_NTSC_M_KR; + break; case '-': /* default parameter, do nothing */ break; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 6e33ce96cab0..965c8902fe60 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -638,6 +638,7 @@ typedef __u64 v4l2_std_id; #define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) #define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) #define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) +#define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000) #define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) #define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) @@ -670,7 +671,8 @@ typedef __u64 v4l2_std_id; V4L2_STD_PAL_H |\ V4L2_STD_PAL_I) #define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ - V4L2_STD_NTSC_M_JP) + V4L2_STD_NTSC_M_JP |\ + V4L2_STD_NTSC_M_KR) #define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ V4L2_STD_SECAM_K |\ V4L2_STD_SECAM_K1) -- cgit v1.2.3-59-g8ed1b From 3d8466ece44c70555a101da73845955c443f4d18 Mon Sep 17 00:00:00 2001 From: Giampiero Giancipoli Date: Tue, 7 Feb 2006 06:49:09 -0200 Subject: V4L/DVB (3302): Added support for the LifeView FlyDVB-T LR301 card Additionally to the card support, this changeset adds the option tda10046lifeview to get_dvb_firmware to download tda10046 firmware from LifeView's site. Signed-off-by: Giampiero Giancipoli Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- Documentation/dvb/get_dvb_firmware | 23 +++++++++++++++++++++-- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 28 ++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 4 ++++ drivers/media/video/saa7134/saa7134-input.c | 5 +++++ drivers/media/video/saa7134/saa7134.h | 1 + 6 files changed, 60 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index 75c28a174092..bb55f49f2745 100644 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -21,8 +21,9 @@ use File::Temp qw/ tempdir /; use IO::Handle; -@components = ( "sp8870", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t", - "dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004", +@components = ( "sp8870", "sp887x", "tda10045", "tda10046", + "tda10046lifeview", "av7110", "dec2000t", "dec2540t", + "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004", "or51211", "or51132_qam", "or51132_vsb", "bluebird"); # Check args @@ -126,6 +127,24 @@ sub tda10046 { $outfile; } +sub tda10046lifeview { + my $sourcefile = "Drv_2.11.02.zip"; + my $url = "http://www.lifeview.com.tw/drivers/pci_card/FlyDVB-T/$sourcefile"; + my $hash = "1ea24dee4eea8fe971686981f34fd2e0"; + my $outfile = "dvb-fe-tda10046.fw"; + my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); + + checkstandard(); + + wgetfile($sourcefile, $url); + unzip($sourcefile, $tmpdir); + extract("$tmpdir/LVHybrid.sys", 0x8b088, 24602, "$tmpdir/fwtmp"); + verify("$tmpdir/fwtmp", $hash); + copy("$tmpdir/fwtmp", $outfile); + + $outfile; +} + sub av7110 { my $sourcefile = "dvb-ttpci-01.fw-261d"; my $url = "http://www.linuxtv.org/downloads/firmware/$sourcefile"; diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 636792e2e154..1823e4ced087 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -84,3 +84,4 @@ 83 -> Terratec Cinergy 250 PCI TV [153b:1160] 84 -> LifeView FlyDVB Trio [5168:0319] 85 -> AverTV DVB-T 777 [1461:2c05] + 86 -> LifeView FlyDVB-T [5168:0301] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 3f964ed7eb56..f469f17a25cf 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2637,6 +2637,27 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }}, }, + [SAA7134_BOARD_FLYDVBT_LR301] = { + /* LifeView FlyDVB-T */ + /* Giampiero Giancipoli */ + .name = "LifeView FlyDVB-T", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_comp1, /* Composite input */ + .vmux = 3, + .amux = LINE2, + },{ + .name = name_svideo, /* S-Video signal on S-Video input */ + .vmux = 8, + .amux = LINE2, + }}, + }, + }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3113,6 +3134,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1461, .subdevice = 0x2c05, .driver_data = SAA7134_BOARD_AVERMEDIA_777, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x5168, + .subdevice = 0x0301, + .driver_data = SAA7134_BOARD_FLYDVBT_LR301, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3213,6 +3240,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_GOTVIEW_7135: case SAA7134_BOARD_KWORLD_TERMINATOR: case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: + case SAA7134_BOARD_FLYDVBT_LR301: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_MD5044: diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 45b52575e16b..be110b85f097 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -924,6 +924,10 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&philips_tiger_config, &dev->i2c_adap); break; + case SAA7134_BOARD_FLYDVBT_LR301: + dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, + &dev->i2c_adap); + break; #endif #ifdef HAVE_NXT200X case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ecfb6e2b3bd3..6970334d5ee8 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -230,6 +230,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keycode = 0x003F00; mask_keyup = 0x040000; break; + case SAA7134_BOARD_FLYDVBT_LR301: + ir_codes = ir_codes_flydvb; + mask_keycode = 0x0001F00; + mask_keydown = 0x0040000; + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index b638df941ff9..ed556e6e61a7 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -212,6 +212,7 @@ struct saa7134_format { #define SAA7134_BOARD_CINERGY250PCI 83 #define SAA7134_BOARD_FLYDVB_TRIO 84 #define SAA7134_BOARD_AVERMEDIA_777 85 +#define SAA7134_BOARD_FLYDVBT_LR301 86 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3-59-g8ed1b From 0157a9cc727dec90a7d60ad254eb899a775685a9 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 7 Feb 2006 06:49:09 -0200 Subject: V4L/DVB (3303): TDA8290 update This patch - works around a bug in the I2C bridge that makes the initialization of the TDA10046 fail on recent LifeView cards - puts the AGC output to tristate in sleep mode. This is necessary for recent hybrid cards that switch the AGC via tristateing. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 7b4fb282ac82..2b954b3d2ba6 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -281,7 +281,7 @@ static void tda827xa_agcf(struct i2c_client *c) static void tda8290_i2c_bridge(struct i2c_client *c, int close) { unsigned char enable[2] = { 0x21, 0xC0 }; - unsigned char disable[2] = { 0x21, 0x80 }; + unsigned char disable[2] = { 0x21, 0x00 }; unsigned char *msg; if(close) { msg = enable; @@ -302,6 +302,7 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) unsigned char soft_reset[] = { 0x00, 0x00 }; unsigned char easy_mode[] = { 0x01, t->tda8290_easy_mode }; unsigned char expert_mode[] = { 0x01, 0x80 }; + unsigned char agc_out_on[] = { 0x02, 0x00 }; unsigned char gainset_off[] = { 0x28, 0x14 }; unsigned char if_agc_spd[] = { 0x0f, 0x88 }; unsigned char adc_head_6[] = { 0x05, 0x04 }; @@ -320,6 +321,7 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) pll_stat; i2c_master_send(c, easy_mode, 2); + i2c_master_send(c, agc_out_on, 2); i2c_master_send(c, soft_reset, 2); msleep(1); @@ -470,6 +472,7 @@ static void standby(struct i2c_client *c) struct tuner *t = i2c_get_clientdata(c); unsigned char cb1[] = { 0x30, 0xD0 }; unsigned char tda8290_standby[] = { 0x00, 0x02 }; + unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; struct i2c_msg msg = {.addr = t->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; tda8290_i2c_bridge(c, 1); @@ -477,6 +480,7 @@ static void standby(struct i2c_client *c) cb1[1] = 0x90; i2c_transfer(c->adapter, &msg, 1); tda8290_i2c_bridge(c, 0); + i2c_master_send(c, tda8290_agc_tri, 2); i2c_master_send(c, tda8290_standby, 2); } @@ -565,7 +569,7 @@ int tda8290_init(struct i2c_client *c) strlcpy(c->name, "tda8290+75a", sizeof(c->name)); t->tda827x_ver = 2; } - tuner_info("tuner: type set to %s\n", c->name); + tuner_info("type set to %s\n", c->name); t->set_tv_freq = set_tv_freq; t->set_radio_freq = set_radio_freq; -- cgit v1.2.3-59-g8ed1b From 0eb3de20a1cec67547951cebc4fcddc701e7428b Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 7 Feb 2006 06:49:10 -0200 Subject: V4L/DVB (3304): TDA10046 Driver update - Set outputs to tristate in sleep mode - Reduce dangerously high firmware download speed with 16MHz xtal - added tda827x configuration with GPIOs low - added comments to stupid looking IIC reads that work around bugs in the tda10046. - some minor updates Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda1004x.c | 25 +++++++++++++++++++++---- drivers/media/dvb/frontends/tda1004x.h | 3 ++- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index c63e9a5084eb..8e8df7b4ca0e 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -229,7 +229,7 @@ static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state) dprintk("%s\n", __FUNCTION__); result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2); - msleep(1); + msleep(20); return result; } @@ -502,7 +502,12 @@ static int tda10046_fwupload(struct dvb_frontend* fe) const struct firmware *fw; /* reset + wake up chip */ - tda1004x_write_byteI(state, TDA1004X_CONFC4, 0); + if (state->config->xtal_freq == TDA10046_XTAL_4M) { + tda1004x_write_byteI(state, TDA1004X_CONFC4, 0); + } else { + dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __FUNCTION__); + tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80); + } tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); /* let the clocks recover from sleep */ msleep(5); @@ -651,7 +656,7 @@ static int tda10046_init(struct dvb_frontend* fe) // tda setup tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream - tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer + tda1004x_write_byteI(state, TDA1004X_CONFC1, 0x88); // enable pulse killer switch (state->config->agc_config) { case TDA10046_AGC_DEFAULT: @@ -672,6 +677,12 @@ static int tda10046_init(struct dvb_frontend* fe) tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities break; + case TDA10046_AGC_TDA827X_GPL: + tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup + tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold + tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize + tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities + break; } tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on @@ -683,6 +694,7 @@ static int tda10046_init(struct dvb_frontend* fe) tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config + // tda1004x_write_mask(state, 0x50, 0x80, 0x80); // handle out of guard echoes tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); state->initialised = 1; @@ -1027,6 +1039,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status if (status == -1) return -EIO; cber |= (status << 8); + // The address 0x20 should be read to cope with a TDA10046 bug tda1004x_read_byte(state, TDA1004X_CBER_RESET); if (cber != 65535) @@ -1047,7 +1060,8 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status status = tda1004x_read_byte(state, TDA1004X_VBER_MSB); if (status == -1) return -EIO; - vber |= ((status << 16) & 0x0f); + vber |= (status & 0x0f) << 16; + // The CVBER_LUT should be read to cope with TDA10046 hardware bug tda1004x_read_byte(state, TDA1004X_CVBER_LUT); // if RS has passed some valid TS packets, then we must be @@ -1161,6 +1175,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber) if (tmp < 0) return -EIO; *ber |= (tmp << 9); + // The address 0x20 should be read to cope with a TDA10046 bug tda1004x_read_byte(state, TDA1004X_CBER_RESET); dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber); @@ -1187,6 +1202,8 @@ static int tda1004x_sleep(struct dvb_frontend* fe) tda1004x_disable_tuner_i2c(state); } } + /* set outputs to tristate */ + tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff); tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); break; } diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index 8659c52647ad..cc0c4af64067 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h @@ -35,7 +35,8 @@ enum tda10046_agc { TDA10046_AGC_DEFAULT, /* original configuration */ TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */ TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */ - TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */ + TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */ + TDA10046_AGC_TDA827X_GPL, /* same as above, but GPIOs 0 */ }; enum tda10046_if { -- cgit v1.2.3-59-g8ed1b From df42eaf2b2f2c43969d879dbcafa698c666fe8a9 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 7 Feb 2006 06:49:10 -0200 Subject: V4L/DVB (3305): Added support for the ADS Instant TV DUO Cardbus PTV331 Analog and DVB-T are working, Remote not yet. This card is based on the new LifeView design, there should be many variants. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 36 +++++++++++++++++++++++- drivers/media/video/saa7134/saa7134-dvb.c | 43 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 80 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 1823e4ced087..ee1618deadf2 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -85,3 +85,4 @@ 84 -> LifeView FlyDVB Trio [5168:0319] 85 -> AverTV DVB-T 777 [1461:2c05] 86 -> LifeView FlyDVB-T [5168:0301] + 87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index f469f17a25cf..d65b9dd90342 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2657,7 +2657,23 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }}, }, - + [SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331] = { + .name = "ADS Instant TV Duo Cardbus PTV331", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */ + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x00200000, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3140,6 +3156,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x5168, .subdevice = 0x0301, .driver_data = SAA7134_BOARD_FLYDVBT_LR301, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0331, + .subdevice = 0x1421, + .driver_data = SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3263,6 +3285,10 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_writeb(SAA7134_GPIO_GPMODE3, 0x08); saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06); break; + case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: + saa_writeb(SAA7134_GPIO_GPMODE3, 0x08); + saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x00); + break; case SAA7134_BOARD_AVERMEDIA_CARDBUS: /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0xffffffff); @@ -3413,6 +3439,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) i2c_transfer(&dev->i2c_adap, &msg, 1); } break; + case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: + /* make the tda10046 find its eeprom */ + { + u8 data[] = { 0x3c, 0x33, 0x62}; + struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; + i2c_transfer(&dev->i2c_adap, &msg, 1); + } + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index be110b85f097..a0c8fa393501 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -846,6 +846,45 @@ static struct tda1004x_config philips_tiger_config = { .request_firmware = NULL, }; +/* ------------------------------------------------------------------ */ + +static int ads_duo_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + int ret; + + ret = philips_tda827xa_pll_set(0x61, fe, params); + return ret; +}; + +static int ads_duo_dvb_mode(struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + /* route TDA8275a AGC input to the channel decoder */ + saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x60); + return 0; +} + +static void ads_duo_analog_mode(struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + /* route TDA8275a AGC input to the analog IF chip*/ + saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x20); + philips_tda827xa_pll_sleep( 0x61, fe); +} + +static struct tda1004x_config ads_tech_duo_config = { + .demod_address = 0x08, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_16M, + .agc_config = TDA10046_AGC_TDA827X_GPL, + .if_freq = TDA10046_FREQ_045, + .pll_init = ads_duo_dvb_mode, + .pll_set = ads_duo_pll_set, + .pll_sleep = ads_duo_analog_mode, + .request_firmware = NULL, +}; + #endif /* ------------------------------------------------------------------ */ @@ -928,6 +967,10 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, &dev->i2c_adap); break; + case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: + dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config, + &dev->i2c_adap); + break; #endif #ifdef HAVE_NXT200X case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index ed556e6e61a7..4b49ee03fc21 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -213,6 +213,7 @@ struct saa7134_format { #define SAA7134_BOARD_FLYDVB_TRIO 84 #define SAA7134_BOARD_AVERMEDIA_777 85 #define SAA7134_BOARD_FLYDVBT_LR301 86 +#define SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331 87 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3-59-g8ed1b From e8e41da46dca6b33e990b48ee379503d25b4da65 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 7 Feb 2006 06:49:11 -0200 Subject: V4L/DVB (3306): Fixed i2c return value, conversion mdelay to msleep fixed i2c return value, conversion mdelay to msleep Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 15 +++++++++++++-- drivers/media/video/em28xx/em28xx-i2c.c | 8 ++++---- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 82f0c5fb2417..e5ee8bceb210 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -139,6 +139,9 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, { int ret, byte; + if (dev->state & DEV_DISCONNECTED) + return(-ENODEV); + em28xx_regdbg("req=%02x, reg=%02x ", req, reg); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, @@ -165,6 +168,9 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) u8 val; int ret; + if (dev->state & DEV_DISCONNECTED) + return(-ENODEV); + em28xx_regdbg("req=%02x, reg=%02x:", req, reg); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, @@ -195,7 +201,12 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int ret; /*usb_control_msg seems to expect a kmalloced buffer */ - unsigned char *bufs = kmalloc(len, GFP_KERNEL); + unsigned char *bufs; + + if (dev->state & DEV_DISCONNECTED) + return(-ENODEV); + + bufs = kmalloc(len, GFP_KERNEL); em28xx_regdbg("req=%02x reg=%02x:", req, reg); @@ -212,7 +223,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0000, reg, bufs, len, HZ); - mdelay(5); /* FIXME: magic number */ + msleep(5); /* FIXME: magic number */ kfree(bufs); return ret; } diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 0591a705b7a1..6ca8631bc36d 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -78,7 +78,7 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, ret = dev->em28xx_read_reg(dev, 0x05); if (ret == 0x80 + len - 1) return len; - mdelay(5); + msleep(5); } em28xx_warn("i2c write timed out\n"); return -EIO; @@ -138,7 +138,7 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) return -ENODEV; else if (msg == 0x84) return 0; - mdelay(5); + msleep(5); } return -ENODEV; } @@ -278,9 +278,9 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, msgs[i].buf, msgs[i].len, i == num - 1); - if (rc < 0) - goto err; } + if (rc < 0) + goto err; if (i2c_debug>=2) printk("\n"); } -- cgit v1.2.3-59-g8ed1b From 8bd6301c2a33271b629ac1ef2088e110624d5665 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Tue, 7 Feb 2006 06:49:11 -0200 Subject: V4L/DVB (3307): Support for Galaxis DVB-S rev1.3 support for Galaxis DVB-S rev1.3 (subsystem 13c2:0004) Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 27494901975f..d36369e9e88f 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -2329,6 +2329,17 @@ static int frontend_init(struct av7110 *av7110) av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); break; + case 0x0004: // Galaxis DVB-S rev1.3 + /* ALPS BSRV2 */ + av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops->set_tone = av7110_set_tone; + av7110->recover = dvb_s_recover; + } + break; + case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */ /* Grundig 29504-451 */ av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); @@ -2930,6 +2941,7 @@ MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE"); MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T"); MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C"); MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6"); +MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3"); static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000), @@ -2937,13 +2949,13 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001), MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002), MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003), + MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004), MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006), MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008), MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a), MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e), MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002), -/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1 /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v???? -- cgit v1.2.3-59-g8ed1b From d9ed881c66525ac0d95fbf76a46187a5de43be2d Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Tue, 7 Feb 2006 06:49:11 -0200 Subject: V4L/DVB (3308): Use parallel transport for FusionHDTV Dual Digital USB Use the parallel transport function of the MT352 in USB demodulator of the Dual Digital board. Signed-off-by: Chris Pascoe Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index f14003736afe..650536a4169c 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -234,7 +234,7 @@ static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) { - static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; + static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; static u8 reset [] = { RESET, 0x80 }; static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; -- cgit v1.2.3-59-g8ed1b From fb51fd2d345021d0cc34848319f4efa75c9e1daa Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 7 Feb 2006 06:49:12 -0200 Subject: V4L/DVB (3310): Use MT352 parallel transport function for all Bluebird FusionHDTV DVB-T boxes. Use the parallel transport function of the MT352 demodulator in TH7579 and LGZ201 -based FusionHDTV Bluebird usb boxes. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 650536a4169c..f327fac1688e 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -255,7 +255,7 @@ static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) static int cxusb_mt352_demod_init(struct dvb_frontend* fe) { /* used in both lgz201 and th7579 */ - static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; + static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x29 }; static u8 reset [] = { RESET, 0x80 }; static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; -- cgit v1.2.3-59-g8ed1b From 123aab28608ac81938865b31db188c985aeb4424 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Tue, 7 Feb 2006 06:49:12 -0200 Subject: V4L/DVB (3312): FIX: Multiple usage of VP7045-based devices Reassigning function pointers in a static led to infinite loops when using multiple VP7045-based device at the same time on one system. Using kmalloc'd copies for reassignments is better. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/vp7045-fe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c index 5242cca5db4a..9999336aeeb6 100644 --- a/drivers/media/dvb/dvb-usb/vp7045-fe.c +++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c @@ -23,10 +23,11 @@ struct vp7045_fe_state { struct dvb_frontend fe; + struct dvb_frontend_ops ops; + struct dvb_usb_device *d; }; - static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) { struct vp7045_fe_state *state = fe->demodulator_priv; @@ -150,7 +151,8 @@ struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d) goto error; s->d = d; - s->fe.ops = &vp7045_fe_ops; + memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops)); + s->fe.ops = &s->ops; s->fe.demodulator_priv = s; goto success; -- cgit v1.2.3-59-g8ed1b From 21d06544a745a09cc1e9ce5376a61b074bfce379 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Tue, 7 Feb 2006 06:49:12 -0200 Subject: V4L/DVB (3313): FIX: Check if FW was downloaded or not + new firmware file - When a firmware was downloaded dvb_usb_device_init returns NULL for the dvb_usb_device, then nothing should be done with that pointer and device, because it will re-enumerate. - A new firmware should be used with digitv devices. - It should make "slave"-devices work and others, too. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/digitv.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index e6c55c9c9417..caa1346e3063 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -175,11 +175,13 @@ static int digitv_probe(struct usb_interface *intf, if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) { u8 b[4] = { 0 }; - b[0] = 1; - digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0); + if (d != NULL) { /* do that only when the firmware is loaded */ + b[0] = 1; + digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0); - b[0] = 0; - digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0); + b[0] = 0; + digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0); + } } return ret; } @@ -194,7 +196,7 @@ static struct dvb_usb_properties digitv_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = CYPRESS_FX2, - .firmware = "dvb-usb-digitv-01.fw", + .firmware = "dvb-usb-digitv-02.fw", .size_of_priv = 0, @@ -229,6 +231,7 @@ static struct dvb_usb_properties digitv_properties = { { &digitv_table[0], NULL }, { NULL }, }, + { NULL }, } }; -- cgit v1.2.3-59-g8ed1b From e5d4a56d5d824e4dfe7d065d0fedb02e63952710 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 7 Feb 2006 06:49:13 -0200 Subject: V4L/DVB (3314): Fixed em28xx based system lockup Fixed em28xx based system lockup, device needs to be initialized before starting the isoc transfer otherwise the system will completly lock up. Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 1726b2c26b6c..1c1557d9bace 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -383,12 +383,14 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) em28xx_capture_start(dev, 1); em28xx_resolution_set(dev); + /* device needs to be initialized before isoc transfer */ + video_mux(dev, 0); + /* start the transfer */ errCode = em28xx_init_isoc(dev); if (errCode) goto err; - video_mux(dev, 0); } dev->users++; -- cgit v1.2.3-59-g8ed1b From 3dfb729f4513184d06a0c618179489ac7bb277e0 Mon Sep 17 00:00:00 2001 From: Peter Hartshorn Date: Tue, 7 Feb 2006 06:49:13 -0200 Subject: V4L/DVB (3315): Added support for the Tevion DVB-T 220RF card This is an analog / digital hybrid card. Signed-off-by: Peter Hartshorn Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 38 ++++++++++++++++++++++++++++- drivers/media/video/saa7134/saa7134-dvb.c | 36 +++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 75 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index ee1618deadf2..c10cfd26d529 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -86,3 +86,4 @@ 85 -> AverTV DVB-T 777 [1461:2c05] 86 -> LifeView FlyDVB-T [5168:0301] 87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421] + 88 -> Tevion DVB-T 220RF [17de:7201] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index d65b9dd90342..3f418620bacf 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2674,6 +2674,33 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x00200000, }}, }, + [SAA7134_BOARD_TEVION_DVBT_220RF] = { + .name = "Tevion DVB-T 220RF", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 0, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE1, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3162,6 +3189,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x0331, .subdevice = 0x1421, .driver_data = SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x17de, + .subdevice = 0x7201, + .driver_data = SAA7134_BOARD_TEVION_DVBT_220RF, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3431,8 +3464,11 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_PHILIPS_TIGER: + case SAA7134_BOARD_TEVION_DVBT_220RF: case SAA7134_BOARD_ASUSTeK_P7131_DUAL: - /* this is a hybrid board, initialize to analog mode */ + /* this is a hybrid board, initialize to analog mode + * and configure firmware eeprom address + */ { u8 data[] = { 0x3c, 0x33, 0x68}; struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index a0c8fa393501..56ca3fad55c4 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -885,6 +885,38 @@ static struct tda1004x_config ads_tech_duo_config = { .request_firmware = NULL, }; +/* ------------------------------------------------------------------ */ + +static int tevion_dvb220rf_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + int ret; + ret = philips_tda827xa_pll_set(0x60, fe, params); + return ret; +} + +static int tevion_dvb220rf_pll_init(struct dvb_frontend *fe) +{ + return 0; +} + +static void tevion_dvb220rf_pll_sleep(struct dvb_frontend *fe) +{ + philips_tda827xa_pll_sleep( 0x61, fe); +} + +static struct tda1004x_config tevion_dvbt220rf_config = { + .demod_address = 0x08, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_16M, + .agc_config = TDA10046_AGC_TDA827X, + .if_freq = TDA10046_FREQ_045, + .pll_init = tevion_dvb220rf_pll_init, + .pll_set = tevion_dvb220rf_pll_set, + .pll_sleep = tevion_dvb220rf_pll_sleep, + .request_firmware = NULL, +}; + #endif /* ------------------------------------------------------------------ */ @@ -971,6 +1003,10 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config, &dev->i2c_adap); break; + case SAA7134_BOARD_TEVION_DVBT_220RF: + dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config, + &dev->i2c_adap); + break; #endif #ifdef HAVE_NXT200X case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 4b49ee03fc21..ff39a63c7372 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -214,6 +214,7 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_777 85 #define SAA7134_BOARD_FLYDVBT_LR301 86 #define SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331 87 +#define SAA7134_BOARD_TEVION_DVBT_220RF 88 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3-59-g8ed1b From 44256de13ecc72291b616fda5f2c7ca8b110feec Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 7 Feb 2006 06:49:14 -0200 Subject: V4L/DVB (3316): Add initial support for KWorld HardwareMpegTV XPert - Add initial support for KWorld HardwareMpegTV XPert. - uses silicon tuner: tda8290 + tda8275 - standard video using cx88 broadcast decoder is working. - blackbird mpeg encoder support (cx23416) not yet working. - FM radio untested. - audio is only working correctly in television mode, all other modes disabled. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 23 +++++++++++++++++++++++ drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 25 insertions(+) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 8bea3fbd0548..d852ad4f93a2 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -43,3 +43,4 @@ 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025] 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1] 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54] + 45 -> KWorld HardwareMpegTV XPert [17de:0840] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 1bc999247fdc..f2ae0478c33a 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1048,6 +1048,25 @@ struct cx88_board cx88_boards[] = { }}, .dvb = 1, }, + [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { + /* FIXME: This card is shipped without a windows tv app, + * so I haven't been able to use regspy to figure out the GPIO + * settings. Standard video using the cx88 broadcast decoder is + * working, but blackbird isn't working yet, audio is only + * working correctly for television mode. S-Video and Composite + * are working for video-only, so I have them disabled for now. + */ + .name = "KWorld HardwareMpegTV XPert", + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x07fa, + }}, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -1254,6 +1273,10 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0xdb11, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, /* Re-branded DViCO: UltraView DVB-T Plus */ + },{ + .subvendor = 0x17de, + .subdevice = 0x0840, + .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index e9fd55b57fa6..31a688a3fb77 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -187,6 +187,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_DNTV_LIVE_DVB_T_PRO 42 #define CX88_BOARD_KWORLD_DVB_T_CX22702 43 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44 +#define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3-59-g8ed1b From 538f9630afbbe429ecbcdcf92536200293a8e4b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 7 Feb 2006 06:49:14 -0200 Subject: V4L/DVB (3318a): Makes Some symbols static. Some symbols at cx88-alsa were global. Making those static. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-alsa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index a2e36a1e5f59..2acccd6d49bc 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -128,7 +128,7 @@ MODULE_PARM_DESC(debug,"enable debug messages"); * BOARD Specific: Sets audio DMA */ -int _cx88_start_audio_dma(snd_cx88_card_t *chip) +static int _cx88_start_audio_dma(snd_cx88_card_t *chip) { struct cx88_buffer *buf = chip->buf; struct cx88_core *core=chip->core; @@ -173,7 +173,7 @@ int _cx88_start_audio_dma(snd_cx88_card_t *chip) /* * BOARD Specific: Resets audio DMA */ -int _cx88_stop_audio_dma(snd_cx88_card_t *chip) +static int _cx88_stop_audio_dma(snd_cx88_card_t *chip) { struct cx88_core *core=chip->core; dprintk(1, "Stopping audio DMA\n"); @@ -613,7 +613,7 @@ static snd_kcontrol_new_t snd_cx88_capture_volume = { * Only boards with eeprom and byte 1 at eeprom=1 have it */ -struct pci_device_id cx88_audio_pci_tbl[] = { +static struct pci_device_id cx88_audio_pci_tbl[] = { {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0, } -- cgit v1.2.3-59-g8ed1b From 3593cab5d62c4c7abced1076710f9bc2d8847433 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 7 Feb 2006 06:49:14 -0200 Subject: V4L/DVB (3318b): sem2mutex: drivers/media/, #2 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: Mauro Carvalho Chehab --- drivers/media/common/saa7146_core.c | 6 +- drivers/media/common/saa7146_fops.c | 18 ++-- drivers/media/common/saa7146_i2c.c | 4 +- drivers/media/common/saa7146_vbi.c | 2 +- drivers/media/common/saa7146_video.c | 30 +++--- drivers/media/dvb/b2c2/flexcop-common.h | 4 +- drivers/media/dvb/b2c2/flexcop-i2c.c | 6 +- drivers/media/dvb/bt8xx/bt878.c | 4 +- drivers/media/dvb/bt8xx/bt878.h | 4 +- drivers/media/dvb/bt8xx/dst.c | 14 +-- drivers/media/dvb/bt8xx/dst_ca.c | 6 +- drivers/media/dvb/bt8xx/dst_common.h | 3 +- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 12 +-- drivers/media/dvb/bt8xx/dvb-bt8xx.h | 3 +- drivers/media/dvb/cinergyT2/cinergyT2.c | 47 ++++----- drivers/media/dvb/dvb-core/dmxdev.c | 86 ++++++++--------- drivers/media/dvb/dvb-core/dmxdev.h | 6 +- drivers/media/dvb/dvb-core/dvb_demux.c | 104 ++++++++++---------- drivers/media/dvb/dvb-core/dvb_demux.h | 4 +- drivers/media/dvb/dvb-core/dvb_frontend.c | 13 ++- drivers/media/dvb/dvb-core/dvb_net.c | 14 +-- drivers/media/dvb/dvb-usb/cxusb.c | 4 +- drivers/media/dvb/dvb-usb/dibusb-common.c | 4 +- drivers/media/dvb/dvb-usb/digitv.c | 4 +- drivers/media/dvb/dvb-usb/dvb-usb-init.c | 4 +- drivers/media/dvb/dvb-usb/dvb-usb-urb.c | 4 +- drivers/media/dvb/dvb-usb/dvb-usb.h | 9 +- drivers/media/dvb/dvb-usb/vp702x.c | 4 +- drivers/media/dvb/dvb-usb/vp7045.c | 4 +- drivers/media/dvb/frontends/bcm3510.c | 9 +- drivers/media/dvb/ttpci/av7110.c | 23 +++-- drivers/media/dvb/ttpci/av7110.h | 7 +- drivers/media/dvb/ttpci/av7110_hw.c | 40 ++++---- drivers/media/dvb/ttpci/budget.h | 4 +- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 32 ++++--- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 31 +++--- drivers/media/radio/miropcm20-rds-core.c | 11 ++- drivers/media/radio/radio-aimslab.c | 20 ++-- drivers/media/radio/radio-aztech.c | 12 +-- drivers/media/radio/radio-maestro.c | 11 ++- drivers/media/radio/radio-maxiradio.c | 11 ++- drivers/media/radio/radio-sf16fmi.c | 22 ++--- drivers/media/radio/radio-sf16fmr2.c | 22 ++--- drivers/media/radio/radio-typhoon.c | 12 +-- drivers/media/radio/radio-zoltrix.c | 26 ++--- drivers/media/video/arv.c | 16 ++-- drivers/media/video/bttv-driver.c | 48 +++++----- drivers/media/video/bw-qcam.c | 16 ++-- drivers/media/video/bw-qcam.h | 2 +- drivers/media/video/c-qcam.c | 19 ++-- drivers/media/video/cpia.c | 102 ++++++++++---------- drivers/media/video/cpia.h | 5 +- drivers/media/video/cx88/cx88-core.c | 2 +- drivers/media/video/cx88/cx88-video.c | 26 ++--- drivers/media/video/cx88/cx88.h | 4 +- drivers/media/video/em28xx/em28xx-video.c | 106 ++++++++++---------- drivers/media/video/em28xx/em28xx.h | 3 +- drivers/media/video/meye.c | 112 +++++++++++----------- drivers/media/video/meye.h | 4 +- drivers/media/video/mxb.c | 4 +- drivers/media/video/planb.c | 8 +- drivers/media/video/planb.h | 2 +- drivers/media/video/pms.c | 28 +++--- drivers/media/video/saa5246a.c | 10 +- drivers/media/video/saa5249.c | 10 +- drivers/media/video/saa7134/saa7134-alsa.c | 6 +- drivers/media/video/saa7134/saa7134-core.c | 2 +- drivers/media/video/saa7134/saa7134-empress.c | 8 +- drivers/media/video/saa7134/saa7134-oss.c | 40 ++++---- drivers/media/video/saa7134/saa7134-video.c | 40 ++++---- drivers/media/video/saa7134/saa7134.h | 5 +- drivers/media/video/video-buf-dvb.c | 10 +- drivers/media/video/video-buf.c | 42 ++++---- drivers/media/video/videodev.c | 6 +- drivers/media/video/vino.c | 33 +++---- include/linux/videodev2.h | 3 +- include/media/saa7146.h | 21 ++-- include/media/video-buf-dvb.h | 2 +- include/media/video-buf.h | 2 +- 79 files changed, 749 insertions(+), 718 deletions(-) (limited to 'drivers') diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 04c1938b9c91..ee16c042ef6e 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -21,7 +21,7 @@ #include LIST_HEAD(saa7146_devices); -DECLARE_MUTEX(saa7146_devices_lock); +DEFINE_MUTEX(saa7146_devices_lock); static int saa7146_num; @@ -402,11 +402,11 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent pci_set_drvdata(pci, dev); - init_MUTEX(&dev->lock); + mutex_init(&dev->lock); spin_lock_init(&dev->int_slock); spin_lock_init(&dev->slock); - init_MUTEX(&dev->i2c_lock); + mutex_init(&dev->i2c_lock); dev->module = THIS_MODULE; init_waitqueue_head(&dev->i2c_wq); diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index f8cf73ed49ad..dc7fb20f47b5 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -17,18 +17,18 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit) } /* is it free? */ - down(&dev->lock); + mutex_lock(&dev->lock); if (vv->resources & bit) { DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit)); /* no, someone else uses it */ - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } /* it's free, grab it */ fh->resources |= bit; vv->resources |= bit; DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources)); - up(&dev->lock); + mutex_unlock(&dev->lock); return 1; } @@ -40,11 +40,11 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) if ((fh->resources & bits) != bits) BUG(); - down(&dev->lock); + mutex_lock(&dev->lock); fh->resources &= ~bits; vv->resources &= ~bits; DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources)); - up(&dev->lock); + mutex_unlock(&dev->lock); } @@ -204,7 +204,7 @@ static int fops_open(struct inode *inode, struct file *file) DEB_EE(("inode:%p, file:%p, minor:%d\n",inode,file,minor)); - if (down_interruptible(&saa7146_devices_lock)) + if (mutex_lock_interruptible(&saa7146_devices_lock)) return -ERESTARTSYS; list_for_each(list,&saa7146_devices) { @@ -276,7 +276,7 @@ out: kfree(fh); file->private_data = NULL; } - up(&saa7146_devices_lock); + mutex_unlock(&saa7146_devices_lock); return result; } @@ -287,7 +287,7 @@ static int fops_release(struct inode *inode, struct file *file) DEB_EE(("inode:%p, file:%p\n",inode,file)); - if (down_interruptible(&saa7146_devices_lock)) + if (mutex_lock_interruptible(&saa7146_devices_lock)) return -ERESTARTSYS; if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { @@ -303,7 +303,7 @@ static int fops_release(struct inode *inode, struct file *file) file->private_data = NULL; kfree(fh); - up(&saa7146_devices_lock); + mutex_unlock(&saa7146_devices_lock); return 0; } diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index 8aabdd8fb3c5..d9953f7a8b6b 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c @@ -279,7 +279,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, in int address_err = 0; int short_delay = 0; - if (down_interruptible (&dev->i2c_lock)) + if (mutex_lock_interruptible(&dev->i2c_lock)) return -ERESTARTSYS; for(i=0;ii2c_lock); + mutex_unlock(&dev->i2c_lock); return err; } diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index 468d3c959075..500bd3f05e16 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c @@ -410,7 +410,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) V4L2_FIELD_SEQ_TB, // FIXME: does this really work? sizeof(struct saa7146_buf), file); - init_MUTEX(&fh->vbi_q.lock); + mutex_init(&fh->vbi_q.lock); init_timer(&fh->vbi_read_timeout); fh->vbi_read_timeout.function = vbi_read_timeout; diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 7ebac7949df3..6b42713d97f4 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -378,20 +378,20 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) err = try_win(dev,&f->fmt.win); if (0 != err) return err; - down(&dev->lock); + mutex_lock(&dev->lock); fh->ov.win = f->fmt.win; fh->ov.nclips = f->fmt.win.clipcount; if (fh->ov.nclips > 16) fh->ov.nclips = 16; if (copy_from_user(fh->ov.clips,f->fmt.win.clips,sizeof(struct v4l2_clip)*fh->ov.nclips)) { - up(&dev->lock); + mutex_unlock(&dev->lock); return -EFAULT; } /* fh->ov.fh is used to indicate that we have valid overlay informations, too */ fh->ov.fh = fh; - up(&dev->lock); + mutex_unlock(&dev->lock); /* check if our current overlay is active */ if (IS_OVERLAY_ACTIVE(fh) != 0) { @@ -516,7 +516,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) return -EINVAL; } - down(&dev->lock); + mutex_lock(&dev->lock); switch (ctrl->type) { case V4L2_CTRL_TYPE_BOOLEAN: @@ -560,7 +560,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) /* fixme: we can support changing VFLIP and HFLIP here... */ if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D(("V4L2_CID_HFLIP while active capture.\n")); - up(&dev->lock); + mutex_unlock(&dev->lock); return -EINVAL; } vv->hflip = c->value; @@ -568,7 +568,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) case V4L2_CID_VFLIP: if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D(("V4L2_CID_VFLIP while active capture.\n")); - up(&dev->lock); + mutex_unlock(&dev->lock); return -EINVAL; } vv->vflip = c->value; @@ -577,7 +577,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) return -EINVAL; } } - up(&dev->lock); + mutex_unlock(&dev->lock); if (IS_OVERLAY_ACTIVE(fh) != 0) { saa7146_stop_preview(fh); @@ -939,7 +939,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int } } - down(&dev->lock); + mutex_lock(&dev->lock); /* ok, accept it */ vv->ov_fb = *fb; @@ -948,7 +948,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width*fmt->depth/8; - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -1086,7 +1086,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int } } - down(&dev->lock); + mutex_lock(&dev->lock); for(i = 0; i < dev->ext_vv_data->num_stds; i++) if (*id & dev->ext_vv_data->stds[i].id) @@ -1098,7 +1098,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int found = 1; } - up(&dev->lock); + mutex_unlock(&dev->lock); if (vv->ov_suspend != NULL) { saa7146_start_preview(vv->ov_suspend); @@ -1201,11 +1201,11 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int DEB_D(("VIDIOCGMBUF \n")); q = &fh->video_q; - down(&q->lock); + mutex_lock(&q->lock); err = videobuf_mmap_setup(q,gbuffers,gbufsize, V4L2_MEMORY_MMAP); if (err < 0) { - up(&q->lock); + mutex_unlock(&q->lock); return err; } memset(mbuf,0,sizeof(*mbuf)); @@ -1213,7 +1213,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int mbuf->size = gbuffers * gbufsize; for (i = 0; i < gbuffers; i++) mbuf->offsets[i] = i * gbufsize; - up(&q->lock); + mutex_unlock(&q->lock); return 0; } default: @@ -1414,7 +1414,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file) sizeof(struct saa7146_buf), file); - init_MUTEX(&fh->video_q.lock); + mutex_init(&fh->video_q.lock); return 0; } diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h index 7d7e1613c5a7..b3dd0603cd92 100644 --- a/drivers/media/dvb/b2c2/flexcop-common.h +++ b/drivers/media/dvb/b2c2/flexcop-common.h @@ -10,6 +10,7 @@ #include #include +#include #include "flexcop-reg.h" @@ -73,8 +74,7 @@ struct flexcop_device { int (*fe_sleep) (struct dvb_frontend *); struct i2c_adapter i2c_adap; - struct semaphore i2c_sem; - + struct mutex i2c_mutex; struct module *owner; /* options and status */ diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c index 56495cb6cd02..e0bd2d8f0f0c 100644 --- a/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/drivers/media/dvb/b2c2/flexcop-i2c.c @@ -135,7 +135,7 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs struct flexcop_device *fc = i2c_get_adapdata(i2c_adap); int i, ret = 0; - if (down_interruptible(&fc->i2c_sem)) + if (mutex_lock_interruptible(&fc->i2c_mutex)) return -ERESTARTSYS; /* reading */ @@ -161,7 +161,7 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs else ret = num; - up(&fc->i2c_sem); + mutex_unlock(&fc->i2c_mutex); return ret; } @@ -180,7 +180,7 @@ int flexcop_i2c_init(struct flexcop_device *fc) { int ret; - sema_init(&fc->i2c_sem,1); + mutex_init(&fc->i2c_mutex); memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter)); strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",I2C_NAME_SIZE); diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index 34c3189a1a33..d276ce6b3661 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -344,7 +344,7 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet * int retval; retval = 0; - if (down_interruptible (&bt->gpio_lock)) + if (mutex_lock_interruptible(&bt->gpio_lock)) return -ERESTARTSYS; /* special gpio signal */ switch (cmd) { @@ -375,7 +375,7 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet * retval = -EINVAL; break; } - up(&bt->gpio_lock); + mutex_unlock(&bt->gpio_lock); return retval; } diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h index 9faf93770d08..f685bc129609 100644 --- a/drivers/media/dvb/bt8xx/bt878.h +++ b/drivers/media/dvb/bt8xx/bt878.h @@ -25,6 +25,8 @@ #include #include #include +#include + #include "bt848.h" #include "bttv.h" @@ -108,7 +110,7 @@ struct cards { extern int bt878_num; struct bt878 { - struct semaphore gpio_lock; + struct mutex gpio_lock; unsigned int nr; unsigned int bttv_nr; struct i2c_adapter *adapter; diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 3a2ff1cc24b7..d800df1212c5 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -910,7 +910,7 @@ static int dst_get_device_id(struct dst_state *state) static int dst_probe(struct dst_state *state) { - sema_init(&state->dst_mutex, 1); + mutex_init(&state->dst_mutex); if ((rdc_8820_reset(state)) < 0) { dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed."); return -1; @@ -962,7 +962,7 @@ int dst_command(struct dst_state *state, u8 *data, u8 len) { u8 reply; - down(&state->dst_mutex); + mutex_lock(&state->dst_mutex); if ((dst_comm_init(state)) < 0) { dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed."); goto error; @@ -1013,11 +1013,11 @@ int dst_command(struct dst_state *state, u8 *data, u8 len) dprintk(verbose, DST_INFO, 1, "checksum failure"); goto error; } - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return 0; error: - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return -EIO; } @@ -1128,7 +1128,7 @@ static int dst_write_tuna(struct dvb_frontend *fe) dst_set_voltage(fe, SEC_VOLTAGE_13); } state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE); - down(&state->dst_mutex); + mutex_lock(&state->dst_mutex); if ((dst_comm_init(state)) < 0) { dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed."); goto error; @@ -1160,11 +1160,11 @@ static int dst_write_tuna(struct dvb_frontend *fe) state->diseq_flags |= ATTEMPT_TUNE; retval = dst_get_tuna(state); werr: - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return retval; error: - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return -EIO; } diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index c650b4bf7f5f..f6b49a801eba 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -81,7 +81,7 @@ static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 { u8 reply; - down(&state->dst_mutex); + mutex_lock(&state->dst_mutex); dst_comm_init(state); msleep(65); @@ -110,11 +110,11 @@ static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 goto error; } } - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return 0; error: - up(&state->dst_mutex); + mutex_unlock(&state->dst_mutex); return -EIO; } diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h index 81557f38fe38..51d4e043716c 100644 --- a/drivers/media/dvb/bt8xx/dst_common.h +++ b/drivers/media/dvb/bt8xx/dst_common.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "bt878.h" #include "dst_ca.h" @@ -121,7 +122,7 @@ struct dst_state { u8 vendor[8]; u8 board_info[8]; - struct semaphore dst_mutex; + struct mutex dst_mutex; }; struct dst_types { diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index ea27b15007e9..1649846f9ceb 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -76,13 +76,13 @@ static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed) if (!dvbdmx->dmx.frontend) return -EINVAL; - down(&card->lock); + mutex_lock(&card->lock); card->nfeeds++; rc = card->nfeeds; if (card->nfeeds == 1) bt878_start(card->bt, card->gpio_mode, card->op_sync_orin, card->irq_err_ignore); - up(&card->lock); + mutex_unlock(&card->lock); return rc; } @@ -96,11 +96,11 @@ static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) if (!dvbdmx->dmx.frontend) return -EINVAL; - down(&card->lock); + mutex_lock(&card->lock); card->nfeeds--; if (card->nfeeds == 0) bt878_stop(card->bt); - up(&card->lock); + mutex_unlock(&card->lock); return 0; } @@ -788,7 +788,7 @@ static int dvb_bt8xx_probe(struct bttv_sub_device *sub) if (!(card = kzalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL))) return -ENOMEM; - init_MUTEX(&card->lock); + mutex_init(&card->lock); card->bttv_nr = sub->core->nr; strncpy(card->card_name, sub->core->name, sizeof(sub->core->name)); card->i2c_adapter = &sub->core->i2c_adap; @@ -881,7 +881,7 @@ static int dvb_bt8xx_probe(struct bttv_sub_device *sub) return -EFAULT; } - init_MUTEX(&card->bt->gpio_lock); + mutex_init(&card->bt->gpio_lock); card->bt->bttv_nr = sub->core->nr; if ( (ret = dvb_bt8xx_load_card(card, sub->core->type)) ) { diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index cf035a80361c..00dd9fa54c82 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -26,6 +26,7 @@ #define DVB_BT8XX_H #include +#include #include "dvbdev.h" #include "dvb_net.h" #include "bttv.h" @@ -38,7 +39,7 @@ #include "lgdt330x.h" struct dvb_bt8xx_card { - struct semaphore lock; + struct mutex lock; int nfeeds; char card_name[32]; struct dvb_adapter dvb_adapter; diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index c4b4c5b6b7c8..29b7be5271d4 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "dmxdev.h" #include "dvb_demux.h" @@ -116,7 +117,7 @@ static struct dvb_frontend_info cinergyt2_fe_info = { struct cinergyt2 { struct dvb_demux demux; struct usb_device *udev; - struct semaphore sem; + struct mutex sem; struct dvb_adapter adapter; struct dvb_device *fedev; struct dmxdev dmxdev; @@ -345,14 +346,14 @@ static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *demux = dvbdmxfeed->demux; struct cinergyt2 *cinergyt2 = demux->priv; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (cinergyt2->streaming == 0) cinergyt2_start_stream_xfer(cinergyt2); cinergyt2->streaming++; - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return 0; } @@ -361,13 +362,13 @@ static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *demux = dvbdmxfeed->demux; struct cinergyt2 *cinergyt2 = demux->priv; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (--cinergyt2->streaming == 0) cinergyt2_stop_stream_xfer(cinergyt2); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return 0; } @@ -483,11 +484,11 @@ static int cinergyt2_open (struct inode *inode, struct file *file) struct cinergyt2 *cinergyt2 = dvbdev->priv; int err = -ERESTARTSYS; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if ((err = dvb_generic_open(inode, file))) { - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return err; } @@ -499,7 +500,7 @@ static int cinergyt2_open (struct inode *inode, struct file *file) atomic_inc(&cinergyt2->inuse); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return 0; } @@ -517,7 +518,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file) struct dvb_device *dvbdev = file->private_data; struct cinergyt2 *cinergyt2 = dvbdev->priv; - if (down_interruptible(&cinergyt2->sem)) + if (mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) { @@ -526,7 +527,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file) cinergyt2_sleep(cinergyt2, 1); } - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) { warn("delayed unregister in release"); @@ -541,12 +542,12 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct struct dvb_device *dvbdev = file->private_data; struct cinergyt2 *cinergyt2 = dvbdev->priv; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; poll_wait(file, &cinergyt2->poll_wq, wait); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return (POLLIN | POLLRDNORM | POLLPRI); } @@ -613,7 +614,7 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file, if (copy_from_user(&p, (void __user*) arg, sizeof(p))) return -EFAULT; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; @@ -629,7 +630,7 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file, (char *) param, sizeof(*param), NULL, 0); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return (err < 0) ? err : 0; } @@ -724,7 +725,7 @@ static void cinergyt2_query_rc (void *data) struct cinergyt2_rc_event rc_events[12]; int n, len, i; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return; len = cinergyt2_command(cinergyt2, buf, sizeof(buf), @@ -784,7 +785,7 @@ out: schedule_delayed_work(&cinergyt2->rc_query_work, msecs_to_jiffies(RC_QUERY_INTERVAL)); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); } static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) @@ -849,7 +850,7 @@ static void cinergyt2_query (void *data) uint8_t lock_bits; uint32_t unc; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return; unc = s->uncorrected_block_count; @@ -868,7 +869,7 @@ static void cinergyt2_query (void *data) schedule_delayed_work(&cinergyt2->query_work, msecs_to_jiffies(QUERY_INTERVAL)); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); } static int cinergyt2_probe (struct usb_interface *intf, @@ -885,7 +886,7 @@ static int cinergyt2_probe (struct usb_interface *intf, memset (cinergyt2, 0, sizeof (struct cinergyt2)); usb_set_intfdata (intf, (void *) cinergyt2); - init_MUTEX(&cinergyt2->sem); + mutex_init(&cinergyt2->sem); init_waitqueue_head (&cinergyt2->poll_wq); INIT_WORK(&cinergyt2->query_work, cinergyt2_query, cinergyt2); @@ -967,7 +968,7 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) { struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (state.event > PM_EVENT_ON) { @@ -981,7 +982,7 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) cinergyt2_sleep(cinergyt2, 1); } - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return 0; } @@ -990,7 +991,7 @@ static int cinergyt2_resume (struct usb_interface *intf) struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); struct dvbt_set_parameters_msg *param = &cinergyt2->param; - if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (!cinergyt2->sleeping) { @@ -1003,7 +1004,7 @@ static int cinergyt2_resume (struct usb_interface *intf) cinergyt2_resume_rc(cinergyt2); - up(&cinergyt2->sem); + mutex_unlock(&cinergyt2->sem); return 0; } diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 7b8373ad121b..ead5343d7706 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -175,12 +175,12 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) dprintk ("function : %s\n", __FUNCTION__); - if (down_interruptible (&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; if ((file->f_flags&O_ACCMODE)==O_RDWR) { if (!(dmxdev->capabilities&DMXDEV_CAP_DUPLEX)) { - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return -EOPNOTSUPP; } } @@ -190,7 +190,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) dmxdev->dvr_buffer.size=DVR_BUFFER_SIZE; dmxdev->dvr_buffer.data=vmalloc(DVR_BUFFER_SIZE); if (!dmxdev->dvr_buffer.data) { - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return -ENOMEM; } } @@ -199,20 +199,20 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) dmxdev->dvr_orig_fe=dmxdev->demux->frontend; if (!dmxdev->demux->write) { - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return -EOPNOTSUPP; } front=get_fe(dmxdev->demux, DMX_MEMORY_FE); if (!front) { - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return -EINVAL; } dmxdev->demux->disconnect_frontend(dmxdev->demux); dmxdev->demux->connect_frontend(dmxdev->demux, front); } - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return 0; } @@ -221,7 +221,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) struct dvb_device *dvbdev = file->private_data; struct dmxdev *dmxdev = dvbdev->priv; - if (down_interruptible (&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; if ((file->f_flags&O_ACCMODE)==O_WRONLY) { @@ -239,7 +239,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) vfree(mem); } } - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return 0; } @@ -254,10 +254,10 @@ static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, return -EOPNOTSUPP; if ((file->f_flags&O_ACCMODE)!=O_WRONLY) return -EINVAL; - if (down_interruptible (&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; ret=dmxdev->demux->write(dmxdev->demux, buf, count); - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return ret; } @@ -268,11 +268,11 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, struct dmxdev *dmxdev = dvbdev->priv; int ret; - //down(&dmxdev->mutex); + //mutex_lock(&dmxdev->mutex); ret= dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, file->f_flags&O_NONBLOCK, buf, count, ppos); - //up(&dmxdev->mutex); + //mutex_unlock(&dmxdev->mutex); return ret; } @@ -688,7 +688,7 @@ static int dvb_demux_open(struct inode *inode, struct file *file) if (!dmxdev->filter) return -EINVAL; - if (down_interruptible(&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; for (i=0; ifilternum; i++) @@ -696,12 +696,12 @@ static int dvb_demux_open(struct inode *inode, struct file *file) break; if (i==dmxdev->filternum) { - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return -EMFILE; } dmxdevfilter=&dmxdev->filter[i]; - sema_init(&dmxdevfilter->mutex, 1); + mutex_init(&dmxdevfilter->mutex); dmxdevfilter->dvbdev=dmxdev->dvbdev; file->private_data=dmxdevfilter; @@ -711,18 +711,18 @@ static int dvb_demux_open(struct inode *inode, struct file *file) dmxdevfilter->feed.ts=NULL; init_timer(&dmxdevfilter->timer); - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return 0; } static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, struct dmxdev_filter *dmxdevfilter) { - if (down_interruptible(&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } @@ -740,8 +740,8 @@ static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, struct dmxdev_filter *d dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE); wake_up(&dmxdevfilter->buffer.queue); - up(&dmxdevfilter->mutex); - up(&dmxdev->mutex); + mutex_unlock(&dmxdevfilter->mutex); + mutex_unlock(&dmxdev->mutex); return 0; } @@ -841,7 +841,7 @@ dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) struct dmxdev_filter *dmxdevfilter= file->private_data; int ret=0; - if (down_interruptible(&dmxdevfilter->mutex)) + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) return -ERESTARTSYS; if (dmxdevfilter->type==DMXDEV_TYPE_SEC) @@ -851,7 +851,7 @@ dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) file->f_flags&O_NONBLOCK, buf, count, ppos); - up(&dmxdevfilter->mutex); + mutex_unlock(&dmxdevfilter->mutex); return ret; } @@ -864,58 +864,58 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, unsigned long arg=(unsigned long) parg; int ret=0; - if (down_interruptible (&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; switch (cmd) { case DMX_START: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } if (dmxdevfilter->statemutex); + mutex_unlock(&dmxdevfilter->mutex); break; case DMX_STOP: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } ret=dvb_dmxdev_filter_stop(dmxdevfilter); - up(&dmxdevfilter->mutex); + mutex_unlock(&dmxdevfilter->mutex); break; case DMX_SET_FILTER: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, (struct dmx_sct_filter_params *)parg); - up(&dmxdevfilter->mutex); + mutex_unlock(&dmxdevfilter->mutex); break; case DMX_SET_PES_FILTER: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } ret=dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, (struct dmx_pes_filter_params *)parg); - up(&dmxdevfilter->mutex); + mutex_unlock(&dmxdevfilter->mutex); break; case DMX_SET_BUFFER_SIZE: - if (down_interruptible(&dmxdevfilter->mutex)) { - up(&dmxdev->mutex); + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } ret=dvb_dmxdev_set_buffer_size(dmxdevfilter, arg); - up(&dmxdevfilter->mutex); + mutex_unlock(&dmxdevfilter->mutex); break; case DMX_GET_EVENT: @@ -959,7 +959,7 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, default: ret=-EINVAL; } - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return ret; } @@ -1030,7 +1030,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file, int ret=0; - if (down_interruptible (&dmxdev->mutex)) + if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; switch (cmd) { @@ -1042,7 +1042,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file, default: ret=-EINVAL; } - up(&dmxdev->mutex); + mutex_unlock(&dmxdev->mutex); return ret; } @@ -1113,7 +1113,7 @@ dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) return -ENOMEM; } - sema_init(&dmxdev->mutex, 1); + mutex_init(&dmxdev->mutex); spin_lock_init(&dmxdev->lock); for (i=0; ifilternum; i++) { dmxdev->filter[i].dev=dmxdev; diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h index fd72920c2199..ec2a7a4da5e4 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.h +++ b/drivers/media/dvb/dvb-core/dmxdev.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include @@ -83,7 +83,7 @@ struct dmxdev_filter { struct dmxdev *dev; struct dmxdev_buffer buffer; - struct semaphore mutex; + struct mutex mutex; /* only for sections */ struct timer_list timer; @@ -117,7 +117,7 @@ struct dmxdev { struct dmxdev_buffer dvr_buffer; #define DVR_BUFFER_SIZE (10*188*1024) - struct semaphore mutex; + struct mutex mutex; spinlock_t lock; }; diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index b4c899b15959..83ec5e06c482 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -589,18 +589,18 @@ static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type, if (pid > DMX_MAX_PID) return -EINVAL; - if (down_interruptible(&demux->mutex)) + if (mutex_lock_interruptible(&demux->mutex)) return -ERESTARTSYS; if (ts_type & TS_DECODER) { if (pes_type >= DMX_TS_PES_OTHER) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EINVAL; } if (demux->pesfilter[pes_type] && demux->pesfilter[pes_type] != feed) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EINVAL; } @@ -622,14 +622,14 @@ static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type, #else feed->buffer = vmalloc(feed->buffer_size); if (!feed->buffer) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -ENOMEM; } #endif } feed->state = DMX_STATE_READY; - up(&demux->mutex); + mutex_unlock(&demux->mutex); return 0; } @@ -640,21 +640,21 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed) struct dvb_demux *demux = feed->demux; int ret; - if (down_interruptible(&demux->mutex)) + if (mutex_lock_interruptible(&demux->mutex)) return -ERESTARTSYS; if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EINVAL; } if (!demux->start_feed) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -ENODEV; } if ((ret = demux->start_feed(feed)) < 0) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return ret; } @@ -662,7 +662,7 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed) ts_feed->is_filtering = 1; feed->state = DMX_STATE_GO; spin_unlock_irq(&demux->lock); - up(&demux->mutex); + mutex_unlock(&demux->mutex); return 0; } @@ -673,16 +673,16 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) struct dvb_demux *demux = feed->demux; int ret; - if (down_interruptible(&demux->mutex)) + if (mutex_lock_interruptible(&demux->mutex)) return -ERESTARTSYS; if (feed->state < DMX_STATE_GO) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EINVAL; } if (!demux->stop_feed) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -ENODEV; } @@ -692,7 +692,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) ts_feed->is_filtering = 0; feed->state = DMX_STATE_ALLOCATED; spin_unlock_irq(&demux->lock); - up(&demux->mutex); + mutex_unlock(&demux->mutex); return ret; } @@ -704,11 +704,11 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, struct dvb_demux *demux = (struct dvb_demux *)dmx; struct dvb_demux_feed *feed; - if (down_interruptible(&demux->mutex)) + if (mutex_lock_interruptible(&demux->mutex)) return -ERESTARTSYS; if (!(feed = dvb_dmx_feed_alloc(demux))) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EBUSY; } @@ -729,7 +729,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, if (!(feed->filter = dvb_dmx_filter_alloc(demux))) { feed->state = DMX_STATE_FREE; - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EBUSY; } @@ -737,7 +737,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, feed->filter->feed = feed; feed->filter->state = DMX_STATE_READY; - up(&demux->mutex); + mutex_unlock(&demux->mutex); return 0; } @@ -748,11 +748,11 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dvb_demux *demux = (struct dvb_demux *)dmx; struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; - if (down_interruptible(&demux->mutex)) + if (mutex_lock_interruptible(&demux->mutex)) return -ERESTARTSYS; if (feed->state == DMX_STATE_FREE) { - up(&demux->mutex); + mutex_unlock(&demux->mutex); return -EINVAL; } #ifndef NOBUFS @@ -770,7 +770,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER) demux->pesfilter[feed->pes_type] = NULL; - up(&demux->mutex); + mutex_unlock(&demux->mutex); return 0; } @@ -785,12 +785,12 @@ static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed, struct dvb_demux *dvbdemux = dvbdmxfeed->demux; struct dvb_demux_filter *dvbdmxfilter; - if (down_interruptible(&dvbdemux->mutex)) + if (mutex_lock_interruptible(&dvbdemux->mutex)) return -ERESTARTSYS; dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux); if (!dvbdmxfilter) { - up(&dvbdemux->mutex); + mutex_unlock(&dvbdemux->mutex); return -EBUSY; } @@ -805,7 +805,7 @@ static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed, dvbdmxfeed->filter = dvbdmxfilter; spin_unlock_irq(&dvbdemux->lock); - up(&dvbdemux->mutex); + mutex_unlock(&dvbdemux->mutex); return 0; } @@ -819,7 +819,7 @@ static int dmx_section_feed_set(struct dmx_section_feed *feed, if (pid > 0x1fff) return -EINVAL; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; dvb_demux_feed_add(dvbdmxfeed); @@ -833,13 +833,13 @@ static int dmx_section_feed_set(struct dmx_section_feed *feed, #else dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size); if (!dvbdmxfeed->buffer) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -ENOMEM; } #endif dvbdmxfeed->state = DMX_STATE_READY; - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return 0; } @@ -871,16 +871,16 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) struct dvb_demux *dvbdmx = dvbdmxfeed->demux; int ret; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; if (feed->is_filtering) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -EBUSY; } if (!dvbdmxfeed->filter) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -EINVAL; } @@ -890,14 +890,14 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) dvbdmxfeed->feed.sec.seclen = 0; if (!dvbdmx->start_feed) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -ENODEV; } prepare_secfilters(dvbdmxfeed); if ((ret = dvbdmx->start_feed(dvbdmxfeed)) < 0) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return ret; } @@ -906,7 +906,7 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) dvbdmxfeed->state = DMX_STATE_GO; spin_unlock_irq(&dvbdmx->lock); - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return 0; } @@ -916,11 +916,11 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed) struct dvb_demux *dvbdmx = dvbdmxfeed->demux; int ret; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; if (!dvbdmx->stop_feed) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -ENODEV; } @@ -931,7 +931,7 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed) feed->is_filtering = 0; spin_unlock_irq(&dvbdmx->lock); - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return ret; } @@ -942,11 +942,11 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; if (dvbdmxfilter->feed != dvbdmxfeed) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -EINVAL; } @@ -966,7 +966,7 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, dvbdmxfilter->state = DMX_STATE_FREE; spin_unlock_irq(&dvbdmx->lock); - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return 0; } @@ -977,11 +977,11 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; struct dvb_demux_feed *dvbdmxfeed; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -EBUSY; } @@ -1006,7 +1006,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, (*feed)->stop_filtering = dmx_section_feed_stop_filtering; (*feed)->release_filter = dmx_section_feed_release_filter; - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return 0; } @@ -1016,11 +1016,11 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux, struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; - if (down_interruptible(&dvbdmx->mutex)) + if (mutex_lock_interruptible(&dvbdmx->mutex)) return -ERESTARTSYS; if (dvbdmxfeed->state == DMX_STATE_FREE) { - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return -EINVAL; } #ifndef NOBUFS @@ -1033,7 +1033,7 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux, dvbdmxfeed->pid = 0xffff; - up(&dvbdmx->mutex); + mutex_unlock(&dvbdmx->mutex); return 0; } @@ -1071,10 +1071,10 @@ static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count) if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE)) return -EINVAL; - if (down_interruptible(&dvbdemux->mutex)) + if (mutex_lock_interruptible(&dvbdemux->mutex)) return -ERESTARTSYS; dvb_dmx_swfilter(dvbdemux, buf, count); - up(&dvbdemux->mutex); + mutex_unlock(&dvbdemux->mutex); if (signal_pending(current)) return -EINTR; @@ -1126,11 +1126,11 @@ static int dvbdmx_connect_frontend(struct dmx_demux *demux, if (demux->frontend) return -EINVAL; - if (down_interruptible(&dvbdemux->mutex)) + if (mutex_lock_interruptible(&dvbdemux->mutex)) return -ERESTARTSYS; demux->frontend = frontend; - up(&dvbdemux->mutex); + mutex_unlock(&dvbdemux->mutex); return 0; } @@ -1138,11 +1138,11 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux) { struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; - if (down_interruptible(&dvbdemux->mutex)) + if (mutex_lock_interruptible(&dvbdemux->mutex)) return -ERESTARTSYS; demux->frontend = NULL; - up(&dvbdemux->mutex); + mutex_unlock(&dvbdemux->mutex); return 0; } @@ -1215,7 +1215,7 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) dmx->disconnect_frontend = dvbdmx_disconnect_frontend; dmx->get_pes_pids = dvbdmx_get_pes_pids; - sema_init(&dvbdemux->mutex, 1); + mutex_init(&dvbdemux->mutex); spin_lock_init(&dvbdemux->lock); return 0; diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h index 0cc888339d52..2c5f915329ca 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.h +++ b/drivers/media/dvb/dvb-core/dvb_demux.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include "demux.h" @@ -125,7 +125,7 @@ struct dvb_demux { u8 tsbuf[204]; int tsbufp; - struct semaphore mutex; + struct mutex mutex; spinlock_t lock; }; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 771f32d889e6..22e96cf8497a 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "dvb_frontend.h" #include "dvbdev.h" @@ -88,7 +87,7 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB vola * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. */ -static DECLARE_MUTEX(frontend_mutex); +static DEFINE_MUTEX(frontend_mutex); struct dvb_frontend_private { @@ -1021,12 +1020,12 @@ int dvb_register_frontend(struct dvb_adapter* dvb, dprintk ("%s\n", __FUNCTION__); - if (down_interruptible (&frontend_mutex)) + if (mutex_lock_interruptible(&frontend_mutex)) return -ERESTARTSYS; fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL); if (fe->frontend_priv == NULL) { - up(&frontend_mutex); + mutex_unlock(&frontend_mutex); return -ENOMEM; } fepriv = fe->frontend_priv; @@ -1045,7 +1044,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb, dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, fe, DVB_DEVICE_FRONTEND); - up (&frontend_mutex); + mutex_unlock(&frontend_mutex); return 0; } EXPORT_SYMBOL(dvb_register_frontend); @@ -1055,7 +1054,7 @@ int dvb_unregister_frontend(struct dvb_frontend* fe) struct dvb_frontend_private *fepriv = fe->frontend_priv; dprintk ("%s\n", __FUNCTION__); - down (&frontend_mutex); + mutex_lock(&frontend_mutex); dvb_unregister_device (fepriv->dvbdev); dvb_frontend_stop (fe); if (fe->ops->release) @@ -1064,7 +1063,7 @@ int dvb_unregister_frontend(struct dvb_frontend* fe) printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name); /* fe is invalid now */ kfree(fepriv); - up (&frontend_mutex); + mutex_unlock(&frontend_mutex); return 0; } EXPORT_SYMBOL(dvb_unregister_frontend); diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 6711eb6a058c..2f0f35811bf7 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -62,6 +62,7 @@ #include #include #include +#include #include "dvb_demux.h" #include "dvb_net.h" @@ -151,8 +152,7 @@ struct dvb_net_priv { unsigned char ule_bridged; /* Whether the ULE_BRIDGED extension header was found. */ int ule_sndu_remain; /* Nr. of bytes still required for current ULE SNDU. */ unsigned long ts_count; /* Current ts cell counter. */ - - struct semaphore mutex; + struct mutex mutex; }; @@ -889,7 +889,7 @@ static int dvb_net_feed_start(struct net_device *dev) unsigned char *mac = (unsigned char *) dev->dev_addr; dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode); - down(&priv->mutex); + mutex_lock(&priv->mutex); if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) printk("%s: BUG %d\n", __FUNCTION__, __LINE__); @@ -974,7 +974,7 @@ static int dvb_net_feed_start(struct net_device *dev) ret = -EINVAL; error: - up(&priv->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -984,7 +984,7 @@ static int dvb_net_feed_stop(struct net_device *dev) int i, ret = 0; dprintk("%s\n", __FUNCTION__); - down(&priv->mutex); + mutex_lock(&priv->mutex); if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) { if (priv->secfeed) { if (priv->secfeed->is_filtering) { @@ -1026,7 +1026,7 @@ static int dvb_net_feed_stop(struct net_device *dev) printk("%s: no ts feed to stop\n", dev->name); } else ret = -EINVAL; - up(&priv->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -1208,7 +1208,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net); INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net); - init_MUTEX(&priv->mutex); + mutex_init(&priv->mutex); net->base_addr = pid; diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index f327fac1688e..e62a293c7e5a 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -77,7 +77,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) struct dvb_usb_device *d = i2c_get_adapdata(adap); int i; - if (down_interruptible(&d->i2c_sem) < 0) + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; if (num > 2) @@ -126,7 +126,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) } } - up(&d->i2c_sem); + mutex_unlock(&d->i2c_mutex); return i; } diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c index 269d899da488..2d52b76671d3 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -128,7 +128,7 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num struct dvb_usb_device *d = i2c_get_adapdata(adap); int i; - if (down_interruptible(&d->i2c_sem) < 0) + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; if (num > 2) @@ -146,7 +146,7 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num break; } - up(&d->i2c_sem); + mutex_unlock(&d->i2c_mutex); return i; } diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index caa1346e3063..91136c00ce9d 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -48,7 +48,7 @@ static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num struct dvb_usb_device *d = i2c_get_adapdata(adap); int i; - if (down_interruptible(&d->i2c_sem) < 0) + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; if (num > 2) @@ -67,7 +67,7 @@ static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num break; } - up(&d->i2c_sem); + mutex_unlock(&d->i2c_mutex); return i; } diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c index 716f8bf528cd..4258a995dce1 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c @@ -42,8 +42,8 @@ static int dvb_usb_init(struct dvb_usb_device *d) { int ret = 0; - sema_init(&d->usb_sem, 1); - sema_init(&d->i2c_sem, 1); + mutex_init(&d->usb_mutex); + mutex_init(&d->i2c_mutex); d->state = DVB_USB_STATE_INIT; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c index ee821974dc60..9002f35aa952 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c @@ -21,7 +21,7 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, if (wbuf == NULL || wlen == 0) return -EINVAL; - if ((ret = down_interruptible(&d->usb_sem))) + if ((ret = mutex_lock_interruptible(&d->usb_mutex))) return ret; deb_xfer(">>> "); @@ -53,7 +53,7 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, } } - up(&d->usb_sem); + mutex_unlock(&d->usb_mutex); return ret; } EXPORT_SYMBOL(dvb_usb_generic_rw); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 5e5d21ad93c9..d2be37cc43b7 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -12,6 +12,7 @@ #include #include #include +#include #include "dvb_frontend.h" #include "dvb_demux.h" @@ -227,8 +228,8 @@ struct dvb_usb_properties { * @feedcount: number of reqested feeds (used for streaming-activation) * @pid_filtering: is hardware pid_filtering used or not. * - * @usb_sem: semaphore of USB control messages (reading needs two messages) - * @i2c_sem: semaphore for i2c-transfers + * @usb_mutex: semaphore of USB control messages (reading needs two messages) + * @i2c_mutex: semaphore for i2c-transfers * * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB * @pll_addr: I2C address of the tuner for programming @@ -283,10 +284,10 @@ struct dvb_usb_device { int pid_filtering; /* locking */ - struct semaphore usb_sem; + struct mutex usb_mutex; /* i2c */ - struct semaphore i2c_sem; + struct mutex i2c_mutex; struct i2c_adapter i2c_adap; /* tuner programming information */ diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index 4a95eca81c5c..b2f098a2d5f7 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c @@ -75,7 +75,7 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il { int ret; - if ((ret = down_interruptible(&d->usb_sem))) + if ((ret = mutex_lock_interruptible(&d->usb_mutex))) return ret; if ((ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen)) < 0) @@ -84,7 +84,7 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen); unlock: - up(&d->usb_sem); + mutex_unlock(&d->usb_mutex); return ret; } diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index 028204956bb0..7fa656b108cc 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c @@ -38,7 +38,7 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, deb_xfer("out buffer: "); debug_dump(outbuf,outlen+1,deb_xfer); - if ((ret = down_interruptible(&d->usb_sem))) + if ((ret = mutex_lock_interruptible(&d->usb_mutex))) return ret; if (usb_control_msg(d->udev, @@ -68,7 +68,7 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, memcpy(in,&inbuf[1],inlen); unlock: - up(&d->usb_sem); + mutex_unlock(&d->usb_mutex); return ret; } diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c index caaee893ca76..1708a1d4893e 100644 --- a/drivers/media/dvb/frontends/bcm3510.c +++ b/drivers/media/dvb/frontends/bcm3510.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "dvb_frontend.h" #include "bcm3510.h" @@ -52,7 +53,7 @@ struct bcm3510_state { struct dvb_frontend frontend; /* demodulator private data */ - struct semaphore hab_sem; + struct mutex hab_mutex; u8 firmware_loaded:1; unsigned long next_status_check; @@ -213,7 +214,7 @@ static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *ob dbufout(ob,olen+2,deb_hab); deb_hab("\n"); - if (down_interruptible(&st->hab_sem) < 0) + if (mutex_lock_interruptible(&st->hab_mutex) < 0) return -EAGAIN; if ((ret = bcm3510_hab_send_request(st, ob, olen+2)) < 0 || @@ -226,7 +227,7 @@ static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *ob memcpy(ibuf,&ib[2],ilen); error: - up(&st->hab_sem); + mutex_unlock(&st->hab_mutex); return ret; } @@ -796,7 +797,7 @@ struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config, state->frontend.ops = &state->ops; state->frontend.demodulator_priv = state; - sema_init(&state->hab_sem, 1); + mutex_init(&state->hab_mutex); if ((ret = bcm3510_readB(state,0xe0,&v)) < 0) goto error; diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index d36369e9e88f..1aa61bf29ad6 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -54,7 +54,6 @@ #include #include -#include #include @@ -242,10 +241,10 @@ static int arm_thread(void *data) if (!av7110->arm_ready) continue; - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) break; newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); if (newloops == av7110->arm_loops || av7110->arm_errors > 3) { printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n", @@ -253,10 +252,10 @@ static int arm_thread(void *data) recover_arm(av7110); - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) break; newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1; - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); } av7110->arm_loops = newloops; av7110->arm_errors = 0; @@ -741,7 +740,7 @@ int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, int ret = 0; dprintk(4, "%p\n", av7110); - if (down_interruptible(&av7110->pid_mutex)) + if (mutex_lock_interruptible(&av7110->pid_mutex)) return -ERESTARTSYS; if (!(vpid & 0x8000)) @@ -760,7 +759,7 @@ int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid); } - up(&av7110->pid_mutex); + mutex_unlock(&av7110->pid_mutex); return ret; } @@ -2096,7 +2095,7 @@ static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status) if (av7110->playing) return 0; - if (down_interruptible(&av7110->pid_mutex)) + if (mutex_lock_interruptible(&av7110->pid_mutex)) return -ERESTARTSYS; if (synced) { @@ -2118,7 +2117,7 @@ static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status) if (!ret) av7110->fe_synced = synced; - up(&av7110->pid_mutex); + mutex_unlock(&av7110->pid_mutex); return ret; } @@ -2713,16 +2712,16 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110); tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110); - sema_init(&av7110->pid_mutex, 1); + mutex_init(&av7110->pid_mutex); /* locks for data transfers from/to AV7110 */ spin_lock_init(&av7110->debilock); - sema_init(&av7110->dcomlock, 1); + mutex_init(&av7110->dcomlock); av7110->debitype = -1; /* default OSD window */ av7110->osdwin = 1; - sema_init(&av7110->osd_sema, 1); + mutex_init(&av7110->osd_mutex); /* ARM "watchdog" */ init_waitqueue_head(&av7110->arm_wait); diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index fafd25fab835..3e2e12124bae 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "dvbdev.h" #include "demux.h" @@ -127,7 +128,7 @@ struct av7110 { /* DEBI and polled command interface */ spinlock_t debilock; - struct semaphore dcomlock; + struct mutex dcomlock; volatile int debitype; volatile int debilen; @@ -146,7 +147,7 @@ struct av7110 { int osdwin; /* currently active window */ u16 osdbpp[8]; - struct semaphore osd_sema; + struct mutex osd_mutex; /* CA */ @@ -172,7 +173,7 @@ struct av7110 { struct tasklet_struct vpe_tasklet; int fe_synced; - struct semaphore pid_mutex; + struct mutex pid_mutex; int video_blank; struct video_status videostate; diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index b2e63e9fc053..3c5366d15a8a 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c @@ -324,10 +324,10 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags) start = jiffies; for (;;) { err = time_after(jiffies, start + ARM_WAIT_FREE); - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); if ((stat & flags) == 0) break; if (err) { @@ -484,11 +484,11 @@ static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) dprintk(1, "arm not ready.\n"); return -1; } - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; ret = __av7110_send_fw_cmd(av7110, buf, length); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); if (ret && ret!=-ERESTARTSYS) printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n", __FUNCTION__, ret); @@ -560,11 +560,11 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, return -1; } - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) { - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err); return err; } @@ -576,7 +576,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, break; if (err) { printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } #ifdef _NOHANDSHAKE @@ -592,7 +592,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, break; if (err) { printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } msleep(1); @@ -603,12 +603,12 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); if (stat & GPMQOver) { printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -1; } else if (stat & OSDQOver) { printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -1; } #endif @@ -616,7 +616,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, for (i = 0; i < reply_buf_len; i++) reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return 0; } @@ -732,7 +732,7 @@ static int FlushText(struct av7110 *av7110) unsigned long start; int err; - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; start = jiffies; while (1) { @@ -742,12 +742,12 @@ static int FlushText(struct av7110 *av7110) if (err) { printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } msleep(1); } - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return 0; } @@ -758,7 +758,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) int length = strlen(buf) + 1; u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y }; - if (down_interruptible(&av7110->dcomlock)) + if (mutex_lock_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; start = jiffies; @@ -769,7 +769,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) if (ret) { printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } msleep(1); @@ -783,7 +783,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) if (ret) { printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); return -ETIMEDOUT; } msleep(1); @@ -795,7 +795,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) if (length & 1) wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2); ret = __av7110_send_fw_cmd(av7110, cbuf, 5); - up(&av7110->dcomlock); + mutex_unlock(&av7110->dcomlock); if (ret && ret!=-ERESTARTSYS) printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret); return ret; @@ -1059,7 +1059,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) { int ret; - if (down_interruptible(&av7110->osd_sema)) + if (mutex_lock_interruptible(&av7110->osd_mutex)) return -ERESTARTSYS; switch (dc->cmd) { @@ -1195,7 +1195,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) break; } - up(&av7110->osd_sema); + mutex_unlock(&av7110->osd_mutex); if (ret==-ERESTARTSYS) dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd); else if (ret) diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h index c7bb63c4d98d..4ac0f4d08025 100644 --- a/drivers/media/dvb/ttpci/budget.h +++ b/drivers/media/dvb/ttpci/budget.h @@ -10,6 +10,8 @@ #include "dvb_net.h" #include +#include + #include extern int budget_debug; @@ -51,7 +53,7 @@ struct budget { struct dmx_frontend mem_frontend; int fe_synced; - struct semaphore pid_mutex; + struct mutex pid_mutex; int ci_present; int video_port; diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 5a13c4744f61..ecb15d4ecf81 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include "dvb_frontend.h" #include "dmxdev.h" @@ -35,7 +35,6 @@ #include #include - /* TTUSB_HWSECTIONS: the DSP supports filtering in hardware, however, since the "muxstream" @@ -83,8 +82,8 @@ struct ttusb { struct dvb_net dvbnet; /* and one for USB access. */ - struct semaphore semi2c; - struct semaphore semusb; + struct mutex semi2c; + struct mutex semusb; struct dvb_adapter adapter; struct usb_device *dev; @@ -150,7 +149,7 @@ static int ttusb_cmd(struct ttusb *ttusb, printk("\n"); #endif - if (down_interruptible(&ttusb->semusb) < 0) + if (mutex_lock_interruptible(&ttusb->semusb) < 0) return -EAGAIN; err = usb_bulk_msg(ttusb->dev, ttusb->bulk_out_pipe, @@ -158,13 +157,13 @@ static int ttusb_cmd(struct ttusb *ttusb, if (err != 0) { dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n", __FUNCTION__, err); - up(&ttusb->semusb); + mutex_unlock(&ttusb->semusb); return err; } if (actual_len != len) { dprintk("%s: only wrote %d of %d bytes\n", __FUNCTION__, actual_len, len); - up(&ttusb->semusb); + mutex_unlock(&ttusb->semusb); return -1; } @@ -174,7 +173,7 @@ static int ttusb_cmd(struct ttusb *ttusb, if (err != 0) { printk("%s: failed, receive error %d\n", __FUNCTION__, err); - up(&ttusb->semusb); + mutex_unlock(&ttusb->semusb); return err; } #if DEBUG >= 3 @@ -185,14 +184,14 @@ static int ttusb_cmd(struct ttusb *ttusb, printk("\n"); #endif if (!needresult) - up(&ttusb->semusb); + mutex_unlock(&ttusb->semusb); return 0; } static int ttusb_result(struct ttusb *ttusb, u8 * data, int len) { memcpy(data, ttusb->last_result, len); - up(&ttusb->semusb); + mutex_unlock(&ttusb->semusb); return 0; } @@ -250,7 +249,7 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num int i = 0; int inc; - if (down_interruptible(&ttusb->semi2c) < 0) + if (mutex_lock_interruptible(&ttusb->semi2c) < 0) return -EAGAIN; while (i < num) { @@ -284,7 +283,7 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num i += inc; } - up(&ttusb->semi2c); + mutex_unlock(&ttusb->semi2c); return i; } @@ -1495,8 +1494,11 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i ttusb->dev = udev; ttusb->c = 0; ttusb->mux_state = 0; - sema_init(&ttusb->semi2c, 0); - sema_init(&ttusb->semusb, 1); + mutex_init(&ttusb->semi2c); + + mutex_lock(&ttusb->semi2c); + + mutex_init(&ttusb->semusb); ttusb_setup_interfaces(ttusb); @@ -1504,7 +1506,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i if (ttusb_init_controller(ttusb)) printk("ttusb_init_controller: error\n"); - up(&ttusb->semi2c); + mutex_unlock(&ttusb->semi2c); dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE); ttusb->adapter.priv = ttusb; diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index df831171e03c..44dea3211848 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -20,7 +20,8 @@ * */ -#include +#include + #include #include #include @@ -115,7 +116,7 @@ struct ttusb_dec { unsigned int out_pipe; unsigned int irq_pipe; enum ttusb_dec_interface interface; - struct semaphore usb_sem; + struct mutex usb_mutex; void *irq_buffer; struct urb *irq_urb; @@ -124,7 +125,7 @@ struct ttusb_dec { dma_addr_t iso_dma_handle; struct urb *iso_urb[ISO_BUF_COUNT]; int iso_stream_count; - struct semaphore iso_sem; + struct mutex iso_mutex; u8 packet[MAX_PVA_LENGTH + 4]; enum ttusb_dec_packet_type packet_type; @@ -273,9 +274,9 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, if (!b) return -ENOMEM; - if ((result = down_interruptible(&dec->usb_sem))) { + if ((result = mutex_lock_interruptible(&dec->usb_mutex))) { kfree(b); - printk("%s: Failed to down usb semaphore.\n", __FUNCTION__); + printk("%s: Failed to lock usb mutex.\n", __FUNCTION__); return result; } @@ -300,7 +301,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, if (result) { printk("%s: command bulk message failed: error %d\n", __FUNCTION__, result); - up(&dec->usb_sem); + mutex_unlock(&dec->usb_mutex); kfree(b); return result; } @@ -311,7 +312,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, if (result) { printk("%s: result bulk message failed: error %d\n", __FUNCTION__, result); - up(&dec->usb_sem); + mutex_unlock(&dec->usb_mutex); kfree(b); return result; } else { @@ -327,7 +328,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, if (cmd_result && b[3] > 0) memcpy(cmd_result, &b[4], b[3]); - up(&dec->usb_sem); + mutex_unlock(&dec->usb_mutex); kfree(b); return 0; @@ -835,7 +836,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec) dprintk("%s\n", __FUNCTION__); - if (down_interruptible(&dec->iso_sem)) + if (mutex_lock_interruptible(&dec->iso_mutex)) return; dec->iso_stream_count--; @@ -845,7 +846,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec) usb_kill_urb(dec->iso_urb[i]); } - up(&dec->iso_sem); + mutex_unlock(&dec->iso_mutex); } /* Setting the interface of the DEC tends to take down the USB communications @@ -890,7 +891,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) dprintk("%s\n", __FUNCTION__); - if (down_interruptible(&dec->iso_sem)) + if (mutex_lock_interruptible(&dec->iso_mutex)) return -EAGAIN; if (!dec->iso_stream_count) { @@ -911,7 +912,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) i--; } - up(&dec->iso_sem); + mutex_unlock(&dec->iso_mutex); return result; } } @@ -919,7 +920,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) dec->iso_stream_count++; - up(&dec->iso_sem); + mutex_unlock(&dec->iso_mutex); return 0; } @@ -1229,8 +1230,8 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec) { dprintk("%s\n", __FUNCTION__); - sema_init(&dec->usb_sem, 1); - sema_init(&dec->iso_sem, 1); + mutex_init(&dec->usb_mutex); + mutex_init(&dec->iso_mutex); dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE); dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE); diff --git a/drivers/media/radio/miropcm20-rds-core.c b/drivers/media/radio/miropcm20-rds-core.c index a917a90cb5dc..b602c73e2309 100644 --- a/drivers/media/radio/miropcm20-rds-core.c +++ b/drivers/media/radio/miropcm20-rds-core.c @@ -18,14 +18,15 @@ #include #include #include -#include +#include + #include #include "../../../sound/oss/aci.h" #include "miropcm20-rds-core.h" #define DEBUG 0 -static struct semaphore aci_rds_sem; +static struct mutex aci_rds_mutex; #define RDS_DATASHIFT 2 /* Bit 2 */ #define RDS_DATAMASK (1 << RDS_DATASHIFT) @@ -181,7 +182,7 @@ int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize) { int ret; - if (down_interruptible(&aci_rds_sem)) + if (mutex_lock_interruptible(&aci_rds_mutex)) return -EINTR; rds_write(cmd); @@ -192,7 +193,7 @@ int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize) else ret = 0; - up(&aci_rds_sem); + mutex_unlock(&aci_rds_mutex); return ret; } @@ -200,7 +201,7 @@ EXPORT_SYMBOL(aci_rds_cmd); int __init attach_aci_rds(void) { - init_MUTEX(&aci_rds_sem); + mutex_init(&aci_rds_mutex); return 0; } diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 914deab4e044..557fb5c4af38 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -43,7 +43,7 @@ static int io = CONFIG_RADIO_RTRACK_PORT; static int radio_nr = -1; -static struct semaphore lock; +static struct mutex lock; struct rt_device { @@ -83,23 +83,23 @@ static void rt_incvol(void) static void rt_mute(struct rt_device *dev) { dev->muted = 1; - down(&lock); + mutex_lock(&lock); outb(0xd0, io); /* volume steady, off */ - up(&lock); + mutex_unlock(&lock); } static int rt_setvol(struct rt_device *dev, int vol) { int i; - down(&lock); + mutex_lock(&lock); if(vol == dev->curvol) { /* requested volume = current */ if (dev->muted) { /* user is unmuting the card */ dev->muted = 0; outb (0xd8, io); /* enable card */ } - up(&lock); + mutex_unlock(&lock); return 0; } @@ -108,7 +108,7 @@ static int rt_setvol(struct rt_device *dev, int vol) sleep_delay(2000000); /* make sure it's totally down */ outb(0xd0, io); /* volume steady, off */ dev->curvol = 0; /* track the volume state! */ - up(&lock); + mutex_unlock(&lock); return 0; } @@ -121,7 +121,7 @@ static int rt_setvol(struct rt_device *dev, int vol) rt_decvol(); dev->curvol = vol; - up(&lock); + mutex_unlock(&lock); return 0; } @@ -168,7 +168,7 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq) freq += 171200; /* Add 10.7 MHz IF */ freq /= 800; /* Convert to 50 kHz units */ - down(&lock); /* Stop other ops interfering */ + mutex_lock(&lock); /* Stop other ops interfering */ send_0_byte (io, dev); /* 0: LSB of frequency */ @@ -196,7 +196,7 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq) else outb (0xd8, io); /* volume steady + sigstr + on */ - up(&lock); + mutex_unlock(&lock); return 0; } @@ -337,7 +337,7 @@ static int __init rtrack_init(void) /* Set up the I/O locking */ - init_MUTEX(&lock); + mutex_init(&lock); /* mute card - prevents noisy bootups */ diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 523be820f9c6..83bdae23417d 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -42,7 +42,7 @@ static int io = CONFIG_RADIO_AZTECH_PORT; static int radio_nr = -1; static int radio_wait_time = 1000; -static struct semaphore lock; +static struct mutex lock; struct az_device { @@ -87,9 +87,9 @@ static void send_1_byte (struct az_device *dev) static int az_setvol(struct az_device *dev, int vol) { - down(&lock); + mutex_lock(&lock); outb (volconvert(vol), io); - up(&lock); + mutex_unlock(&lock); return 0; } @@ -122,7 +122,7 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency) frequency += 171200; /* Add 10.7 MHz IF */ frequency /= 800; /* Convert to 50 kHz units */ - down(&lock); + mutex_lock(&lock); send_0_byte (dev); /* 0: LSB of frequency */ @@ -152,7 +152,7 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency) udelay (radio_wait_time); outb_p(128+64+volconvert(dev->curvol), io); - up(&lock); + mutex_unlock(&lock); return 0; } @@ -283,7 +283,7 @@ static int __init aztech_init(void) return -EBUSY; } - init_MUTEX(&lock); + mutex_init(&lock); aztech_radio.priv=&aztech_unit; if(video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr)==-1) diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 36c9f5bf8cdd..39c1d9118636 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -23,10 +23,11 @@ #include #include #include -#include +#include #include #include + #define DRIVER_VERSION "0.05" #define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */ @@ -104,7 +105,7 @@ struct radio_device { muted, /* VIDEO_AUDIO_MUTE */ stereo, /* VIDEO_TUNER_STEREO_ON */ tuned; /* signal strength (0 or 0xffff) */ - struct semaphore lock; + struct mutex lock; }; static u32 radio_bits_get(struct radio_device *dev) @@ -258,9 +259,9 @@ static int radio_ioctl(struct inode *inode, struct file *file, struct radio_device *card = video_get_drvdata(dev); int ret; - down(&card->lock); + mutex_lock(&card->lock); ret = video_usercopy(inode, file, cmd, arg, radio_function); - up(&card->lock); + mutex_unlock(&card->lock); return ret; } @@ -311,7 +312,7 @@ static int __devinit maestro_probe(struct pci_dev *pdev, } radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA; - init_MUTEX(&radio_unit->lock); + mutex_init(&radio_unit->lock); maestro_radio_inst = video_device_alloc(); if (maestro_radio_inst == NULL) { diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index c975ddd86cd5..f0bf47bcb64c 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -37,7 +37,8 @@ #include #include #include -#include +#include + #include #include @@ -101,7 +102,7 @@ static struct radio_device unsigned long freq; - struct semaphore lock; + struct mutex lock; } radio_unit = {0, 0, 0, 0, }; @@ -267,9 +268,9 @@ static int radio_ioctl(struct inode *inode, struct file *file, struct radio_device *card=dev->priv; int ret; - down(&card->lock); + mutex_lock(&card->lock); ret = video_usercopy(inode, file, cmd, arg, radio_function); - up(&card->lock); + mutex_unlock(&card->lock); return ret; } @@ -290,7 +291,7 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d goto err_out_free_region; radio_unit.io = pci_resource_start(pdev, 0); - init_MUTEX(&radio_unit.lock); + mutex_init(&radio_unit.lock); maxiradio_radio.priv = &radio_unit; if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) { diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 0229f792a059..53073b424107 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -24,7 +24,7 @@ #include #include /* outb, outb_p */ #include /* copy to/from user */ -#include +#include struct fmi_device { @@ -37,7 +37,7 @@ struct fmi_device static int io = -1; static int radio_nr = -1; static struct pnp_dev *dev = NULL; -static struct semaphore lock; +static struct mutex lock; /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ /* It is only useful to give freq in intervall of 800 (=0.05Mhz), @@ -68,16 +68,16 @@ static void outbits(int bits, unsigned int data, int port) static inline void fmi_mute(int port) { - down(&lock); + mutex_lock(&lock); outb(0x00, port); - up(&lock); + mutex_unlock(&lock); } static inline void fmi_unmute(int port) { - down(&lock); + mutex_lock(&lock); outb(0x08, port); - up(&lock); + mutex_unlock(&lock); } static inline int fmi_setfreq(struct fmi_device *dev) @@ -85,12 +85,12 @@ static inline int fmi_setfreq(struct fmi_device *dev) int myport = dev->port; unsigned long freq = dev->curfreq; - down(&lock); + mutex_lock(&lock); outbits(16, RSF16_ENCODE(freq), myport); outbits(8, 0xC0, myport); msleep(143); /* was schedule_timeout(HZ/7) */ - up(&lock); + mutex_unlock(&lock); if (dev->curvol) fmi_unmute(myport); return 0; } @@ -102,7 +102,7 @@ static inline int fmi_getsigstr(struct fmi_device *dev) int myport = dev->port; - down(&lock); + mutex_lock(&lock); val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */ outb(val, myport); outb(val | 0x10, myport); @@ -110,7 +110,7 @@ static inline int fmi_getsigstr(struct fmi_device *dev) res = (int)inb(myport+1); outb(val, myport); - up(&lock); + mutex_unlock(&lock); return (res & 2) ? 0 : 0xFFFF; } @@ -296,7 +296,7 @@ static int __init fmi_init(void) fmi_unit.flags = VIDEO_TUNER_LOW; fmi_radio.priv = &fmi_unit; - init_MUTEX(&lock); + mutex_init(&lock); if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) == -1) { release_region(io, 2); diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 099ffb3b9c71..bcebd8cb19ad 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -19,9 +19,9 @@ #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ -#include +#include -static struct semaphore lock; +static struct mutex lock; #undef DEBUG //#define DEBUG 1 @@ -238,9 +238,9 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file, if (fmr2->mute) v->flags |= VIDEO_AUDIO_MUTE; v->mode=VIDEO_MODE_AUTO; - down(&lock); + mutex_lock(&lock); v->signal = fmr2_getsigstr(fmr2); - up(&lock); + mutex_unlock(&lock); return 0; } case VIDIOCSTUNER: @@ -274,9 +274,9 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file, /* set card freq (if not muted) */ if (fmr2->curvol && !fmr2->mute) { - down(&lock); + mutex_lock(&lock); fmr2_setfreq(fmr2); - up(&lock); + mutex_unlock(&lock); } return 0; } @@ -318,14 +318,14 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file, else printk(KERN_DEBUG "mute\n"); #endif - down(&lock); + mutex_lock(&lock); if (fmr2->curvol && !fmr2->mute) { fmr2_setvolume(fmr2); fmr2_setfreq(fmr2); } else fmr2_mute(fmr2->port); - up(&lock); + mutex_unlock(&lock); return 0; } case VIDIOCGUNIT: @@ -380,7 +380,7 @@ static int __init fmr2_init(void) fmr2_unit.card_type = 0; fmr2_radio.priv = &fmr2_unit; - init_MUTEX(&lock); + mutex_init(&lock); if (request_region(io, 2, "sf16fmr2")) { @@ -397,10 +397,10 @@ static int __init fmr2_init(void) printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io); debug_print((KERN_DEBUG "Mute %d Low %d\n",VIDEO_AUDIO_MUTE,VIDEO_TUNER_LOW)); /* mute card - prevents noisy bootups */ - down(&lock); + mutex_lock(&lock); fmr2_mute(io); fmr2_product_info(&fmr2_unit); - up(&lock); + mutex_unlock(&lock); debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type)); return 0; } diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index 8ac9a8ef9094..e50955836d6b 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -59,7 +59,7 @@ struct typhoon_device { int muted; unsigned long curfreq; unsigned long mutefreq; - struct semaphore lock; + struct mutex lock; }; static void typhoon_setvol_generic(struct typhoon_device *dev, int vol); @@ -77,12 +77,12 @@ static int typhoon_get_info(char *buf, char **start, off_t offset, int len); static void typhoon_setvol_generic(struct typhoon_device *dev, int vol) { - down(&dev->lock); + mutex_lock(&dev->lock); vol >>= 14; /* Map 16 bit to 2 bit */ vol &= 3; outb_p(vol / 2, dev->iobase); /* Set the volume, high bit. */ outb_p(vol % 2, dev->iobase + 2); /* Set the volume, low bit. */ - up(&dev->lock); + mutex_unlock(&dev->lock); } static int typhoon_setfreq_generic(struct typhoon_device *dev, @@ -102,7 +102,7 @@ static int typhoon_setfreq_generic(struct typhoon_device *dev, * */ - down(&dev->lock); + mutex_lock(&dev->lock); x = frequency / 160; outval = (x * x + 2500) / 5000; outval = (outval * x + 5000) / 10000; @@ -112,7 +112,7 @@ static int typhoon_setfreq_generic(struct typhoon_device *dev, outb_p((outval >> 8) & 0x01, dev->iobase + 4); outb_p(outval >> 9, dev->iobase + 6); outb_p(outval & 0xff, dev->iobase + 8); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -337,7 +337,7 @@ static int __init typhoon_init(void) #endif /* MODULE */ printk(KERN_INFO BANNER); - init_MUTEX(&typhoon_unit.lock); + mutex_init(&typhoon_unit.lock); io = typhoon_unit.iobase; if (!request_region(io, 8, "typhoon")) { printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n", diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index d590e80c922e..7bf1a4264891 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -48,7 +48,7 @@ struct zol_device { unsigned long curfreq; int muted; unsigned int stereo; - struct semaphore lock; + struct mutex lock; }; static int zol_setvol(struct zol_device *dev, int vol) @@ -57,30 +57,30 @@ static int zol_setvol(struct zol_device *dev, int vol) if (dev->muted) return 0; - down(&dev->lock); + mutex_lock(&dev->lock); if (vol == 0) { outb(0, io); outb(0, io); inb(io + 3); /* Zoltrix needs to be read to confirm */ - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } outb(dev->curvol-1, io); msleep(10); inb(io + 2); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } static void zol_mute(struct zol_device *dev) { dev->muted = 1; - down(&dev->lock); + mutex_lock(&dev->lock); outb(0, io); outb(0, io); inb(io + 3); /* Zoltrix needs to be read to confirm */ - up(&dev->lock); + mutex_unlock(&dev->lock); } static void zol_unmute(struct zol_device *dev) @@ -104,7 +104,7 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) bitmask = 0xc480402c10080000ull; i = 45; - down(&dev->lock); + mutex_lock(&dev->lock); outb(0, io); outb(0, io); @@ -149,7 +149,7 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) udelay(1000); } - up(&dev->lock); + mutex_unlock(&dev->lock); if(!dev->muted) { @@ -164,7 +164,7 @@ static int zol_getsigstr(struct zol_device *dev) { int a, b; - down(&dev->lock); + mutex_lock(&dev->lock); outb(0x00, io); /* This stuff I found to do nothing */ outb(dev->curvol, io); msleep(20); @@ -173,7 +173,7 @@ static int zol_getsigstr(struct zol_device *dev) msleep(10); b = inb(io); - up(&dev->lock); + mutex_unlock(&dev->lock); if (a != b) return (0); @@ -188,7 +188,7 @@ static int zol_is_stereo (struct zol_device *dev) { int x1, x2; - down(&dev->lock); + mutex_lock(&dev->lock); outb(0x00, io); outb(dev->curvol, io); @@ -198,7 +198,7 @@ static int zol_is_stereo (struct zol_device *dev) msleep(10); x2 = inb(io); - up(&dev->lock); + mutex_unlock(&dev->lock); if ((x1 == x2) && (x1 == 0xcf)) return 1; @@ -350,7 +350,7 @@ static int __init zoltrix_init(void) } printk(KERN_INFO "Zoltrix Radio Plus card driver.\n"); - init_MUTEX(&zoltrix_unit.lock); + mutex_init(&zoltrix_unit.lock); /* mute card - prevents noisy bootups */ diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 994b75fe165a..c586f64b6b7f 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -31,8 +31,8 @@ #include #include #include +#include -#include #include #include #include @@ -117,7 +117,7 @@ struct ar_device { int width, height; int frame_bytes, line_bytes; wait_queue_head_t wait; - struct semaphore lock; + struct mutex lock; }; static int video_nr = -1; /* video device number (first free) */ @@ -288,7 +288,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) if (ar->mode == AR_MODE_NORMAL) arvcr1 |= ARVCR1_NORMAL; - down(&ar->lock); + mutex_lock(&ar->lock); #if USE_INT local_irq_save(flags); @@ -392,7 +392,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) } DEBUG(1, "ret = %d\n", ret); out_up: - up(&ar->lock); + mutex_unlock(&ar->lock); return ret; } @@ -456,7 +456,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file, (w->width != AR_WIDTH_QVGA || w->height != AR_HEIGHT_QVGA)) return -EINVAL; - down(&ar->lock); + mutex_lock(&ar->lock); ar->width = w->width; ar->height = w->height; if (ar->width == AR_WIDTH_VGA) { @@ -473,7 +473,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file, ar->line_bytes = AR_LINE_BYTES_QVGA; ar->mode = AR_MODE_INTERLACE; } - up(&ar->lock); + mutex_unlock(&ar->lock); return 0; } case VIDIOCGFBUF: @@ -734,7 +734,7 @@ static int ar_initialize(struct video_device *dev) void ar_release(struct video_device *vfd) { struct ar_device *ar = vfd->priv; - down(&ar->lock); + mutex_lock(&ar->lock); video_device_release(vfd); } @@ -824,7 +824,7 @@ static int __init ar_init(void) ar->line_bytes = AR_LINE_BYTES_QVGA; ar->mode = AR_MODE_INTERLACE; } - init_MUTEX(&ar->lock); + mutex_init(&ar->lock); init_waitqueue_head(&ar->wait); #if USE_INT diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 578b20085082..c0415d6e7fee 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1965,7 +1965,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, BUG(); } - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); kfree(fh->ov.clips); fh->ov.clips = clips; fh->ov.nclips = n; @@ -1986,7 +1986,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv,fh,new); } - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return retval; } @@ -2166,7 +2166,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, fmt = format_by_fourcc(f->fmt.pix.pixelformat); /* update our state informations */ - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); fh->fmt = fmt; fh->cap.field = f->fmt.pix.field; fh->cap.last = V4L2_FIELD_NONE; @@ -2175,7 +2175,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, btv->init.fmt = fmt; btv->init.width = f->fmt.pix.width; btv->init.height = f->fmt.pix.height; - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return 0; } @@ -2282,7 +2282,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, fmt = format_by_palette(pic->palette); if (NULL == fmt) return -EINVAL; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); if (fmt->depth != pic->depth) { retval = -EINVAL; goto fh_unlock_and_return; @@ -2313,7 +2313,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, bt848_contrast(btv,pic->contrast); bt848_hue(btv,pic->hue); bt848_sat(btv,pic->colour); - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return 0; } @@ -2379,7 +2379,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return -EPERM; end = (unsigned long)fbuf->base + fbuf->height * fbuf->bytesperline; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); retval = -EINVAL; switch (fbuf->depth) { @@ -2417,7 +2417,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, btv->fbuf.fmt.bytesperline = fbuf->bytesperline; else btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fbuf->depth/8; - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return 0; } @@ -2440,7 +2440,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY)) return -EBUSY; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); if (*on) { fh->ov.tvnorm = btv->tvnorm; new = videobuf_alloc(sizeof(*new)); @@ -2451,7 +2451,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, /* switch over */ retval = bttv_switch_overlay(btv,fh,new); - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return retval; } @@ -2460,7 +2460,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, struct video_mbuf *mbuf = arg; unsigned int i; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize, V4L2_MEMORY_MMAP); if (retval < 0) @@ -2470,7 +2470,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, mbuf->size = gbuffers * gbufsize; for (i = 0; i < gbuffers; i++) mbuf->offsets[i] = i * gbufsize; - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return 0; } case VIDIOCMCAPTURE: @@ -2482,7 +2482,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (vm->frame >= VIDEO_MAX_FRAME) return -EINVAL; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); retval = -EINVAL; buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame]; if (NULL == buf) @@ -2504,7 +2504,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, spin_lock_irqsave(&btv->s_lock,flags); buffer_queue(&fh->cap,&buf->vb); spin_unlock_irqrestore(&btv->s_lock,flags); - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return 0; } case VIDIOCSYNC: @@ -2515,7 +2515,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (*frame >= VIDEO_MAX_FRAME) return -EINVAL; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); retval = -EINVAL; buf = (struct bttv_buffer *)fh->cap.bufs[*frame]; if (NULL == buf) @@ -2535,7 +2535,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, retval = -EINVAL; break; } - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return retval; } @@ -2719,7 +2719,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (0 == (fmt->flags & FORMAT_FLAGS_PACKED)) return -EINVAL; - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); retval = -EINVAL; if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { if (fb->fmt.width > bttv_tvnorms[btv->tvnorm].swidth) @@ -2759,7 +2759,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, retval = bttv_switch_overlay(btv,fh,new); } } - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return retval; } @@ -2890,7 +2890,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return 0; fh_unlock_and_return: - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return retval; } @@ -2957,16 +2957,16 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream); } else { /* read() capture */ - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); if (NULL == fh->cap.read_buf) { /* need to capture a new frame */ if (locked_btres(fh->btv,RESOURCE_VIDEO)) { - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return POLLERR; } fh->cap.read_buf = videobuf_alloc(fh->cap.msize); if (NULL == fh->cap.read_buf) { - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return POLLERR; } fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR; @@ -2974,13 +2974,13 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) { kfree (fh->cap.read_buf); fh->cap.read_buf = NULL; - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return POLLERR; } fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; } - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); buf = (struct bttv_buffer*)fh->cap.read_buf; } diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 6bad93ef969f..d97b7d8ac33d 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -73,7 +73,7 @@ OTHER DEALINGS IN THE SOFTWARE. #include #include #include -#include +#include #include #include "bw-qcam.h" @@ -168,7 +168,7 @@ static struct qcam_device *qcam_init(struct parport *port) memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); - init_MUTEX(&q->lock); + mutex_init(&q->lock); q->port_mode = (QC_ANY | QC_NOTSET); q->width = 320; @@ -772,9 +772,9 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, qcam->whitebal = p->whiteness>>8; qcam->bpp = p->depth; - down(&qcam->lock); + mutex_lock(&qcam->lock); qc_setscanmode(qcam); - up(&qcam->lock); + mutex_unlock(&qcam->lock); qcam->status |= QC_PARAM_CHANGE; return 0; @@ -805,9 +805,9 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, qcam->height = 240; qcam->transfer_scale = 1; } - down(&qcam->lock); + mutex_lock(&qcam->lock); qc_setscanmode(qcam); - up(&qcam->lock); + mutex_unlock(&qcam->lock); /* We must update the camera before we grab. We could just have changed the grab size */ @@ -854,7 +854,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf, int len; parport_claim_or_block(qcam->pdev); - down(&qcam->lock); + mutex_lock(&qcam->lock); qc_reset(qcam); @@ -864,7 +864,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf, len=qc_capture(qcam, buf,count); - up(&qcam->lock); + mutex_unlock(&qcam->lock); parport_release(qcam->pdev); return len; diff --git a/drivers/media/video/bw-qcam.h b/drivers/media/video/bw-qcam.h index 723e8ad9e56a..6701dafbc0da 100644 --- a/drivers/media/video/bw-qcam.h +++ b/drivers/media/video/bw-qcam.h @@ -55,7 +55,7 @@ struct qcam_device { struct video_device vdev; struct pardevice *pdev; struct parport *pport; - struct semaphore lock; + struct mutex lock; int width, height; int bpp; int mode; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 9976db4f6da8..8211fd8d7cbf 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -34,7 +34,8 @@ #include #include #include -#include +#include + #include struct qcam_device { @@ -47,7 +48,7 @@ struct qcam_device { int contrast, brightness, whitebal; int top, left; unsigned int bidirectional; - struct semaphore lock; + struct mutex lock; }; /* cameras maximum */ @@ -581,11 +582,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, qcam->contrast = p->contrast>>8; qcam->whitebal = p->whiteness>>8; - down(&qcam->lock); + mutex_lock(&qcam->lock); parport_claim_or_block(qcam->pdev); qc_setup(qcam); parport_release(qcam->pdev); - up(&qcam->lock); + mutex_unlock(&qcam->lock); return 0; } case VIDIOCSWIN: @@ -628,11 +629,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, #endif /* Ok we figured out what to use from our wide choice */ - down(&qcam->lock); + mutex_lock(&qcam->lock); parport_claim_or_block(qcam->pdev); qc_setup(qcam); parport_release(qcam->pdev); - up(&qcam->lock); + mutex_unlock(&qcam->lock); return 0; } case VIDIOCGWIN: @@ -672,12 +673,12 @@ static ssize_t qcam_read(struct file *file, char __user *buf, struct qcam_device *qcam=(struct qcam_device *)v; int len; - down(&qcam->lock); + mutex_lock(&qcam->lock); parport_claim_or_block(qcam->pdev); /* Probably should have a semaphore against multiple users */ len = qc_capture(qcam, buf,count); parport_release(qcam->pdev); - up(&qcam->lock); + mutex_unlock(&qcam->lock); return len; } @@ -727,7 +728,7 @@ static struct qcam_device *qcam_init(struct parport *port) memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); - init_MUTEX(&q->lock); + mutex_init(&q->lock); q->width = q->ccd_width = 320; q->height = q->ccd_height = 240; q->mode = QC_MILLIONS | QC_DECIMATION_1; diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 9f59541155d9..c2405029a720 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #ifdef CONFIG_KMOD #include @@ -622,7 +622,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, buffer = page; - if (down_interruptible(&cam->param_lock)) + if (mutex_lock_interruptible(&cam->param_lock)) return -ERESTARTSYS; /* @@ -1350,7 +1350,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, } else DBG("error: %d\n", retval); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); out: free_page((unsigned long)page); @@ -1664,7 +1664,7 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) case CPIA_COMMAND_GetColourParams: case CPIA_COMMAND_GetColourBalance: case CPIA_COMMAND_GetExposure: - down(&cam->param_lock); + mutex_lock(&cam->param_lock); datasize=8; break; case CPIA_COMMAND_ReadMCPorts: @@ -1691,7 +1691,7 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) if (command == CPIA_COMMAND_GetColourParams || command == CPIA_COMMAND_GetColourBalance || command == CPIA_COMMAND_GetExposure) - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); } else { switch(command) { case CPIA_COMMAND_GetCPIAVersion: @@ -1726,13 +1726,13 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) cam->params.colourParams.brightness = data[0]; cam->params.colourParams.contrast = data[1]; cam->params.colourParams.saturation = data[2]; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); break; case CPIA_COMMAND_GetColourBalance: cam->params.colourBalance.redGain = data[0]; cam->params.colourBalance.greenGain = data[1]; cam->params.colourBalance.blueGain = data[2]; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); break; case CPIA_COMMAND_GetExposure: cam->params.exposure.gain = data[0]; @@ -1743,7 +1743,7 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) cam->params.exposure.green1Comp = data[5]; cam->params.exposure.green2Comp = data[6]; cam->params.exposure.blueComp = data[7]; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); break; case CPIA_COMMAND_ReadMCPorts: @@ -2059,7 +2059,7 @@ static int parse_picture(struct cam_data *cam, int size) int rows, cols, linesize, subsample_422; /* make sure params don't change while we are decoding */ - down(&cam->param_lock); + mutex_lock(&cam->param_lock); obuf = cam->decompressed_frame.data; end_obuf = obuf+CPIA_MAX_FRAME_SIZE; @@ -2069,26 +2069,26 @@ static int parse_picture(struct cam_data *cam, int size) if ((ibuf[0] != MAGIC_0) || (ibuf[1] != MAGIC_1)) { LOG("header not found\n"); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } if ((ibuf[16] != VIDEOSIZE_QCIF) && (ibuf[16] != VIDEOSIZE_CIF)) { LOG("wrong video size\n"); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } if (ibuf[17] != SUBSAMPLE_420 && ibuf[17] != SUBSAMPLE_422) { LOG("illegal subtype %d\n",ibuf[17]); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } subsample_422 = ibuf[17] == SUBSAMPLE_422; if (ibuf[18] != YUVORDER_YUYV && ibuf[18] != YUVORDER_UYVY) { LOG("illegal yuvorder %d\n",ibuf[18]); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } in_uyvy = ibuf[18] == YUVORDER_UYVY; @@ -2098,7 +2098,7 @@ static int parse_picture(struct cam_data *cam, int size) (ibuf[26] != cam->params.roi.rowStart) || (ibuf[27] != cam->params.roi.rowEnd)) { LOG("ROI mismatch\n"); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } cols = 8*(ibuf[25] - ibuf[24]); @@ -2107,14 +2107,14 @@ static int parse_picture(struct cam_data *cam, int size) if ((ibuf[28] != NOT_COMPRESSED) && (ibuf[28] != COMPRESSED)) { LOG("illegal compression %d\n",ibuf[28]); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } compressed = (ibuf[28] == COMPRESSED); if (ibuf[29] != NO_DECIMATION && ibuf[29] != DECIMATION_ENAB) { LOG("illegal decimation %d\n",ibuf[29]); - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return -1; } decimation = (ibuf[29] == DECIMATION_ENAB); @@ -2130,7 +2130,7 @@ static int parse_picture(struct cam_data *cam, int size) cam->params.status.vpStatus = ibuf[38]; cam->params.status.errorCode = ibuf[39]; cam->fps = ibuf[41]; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); linesize = skipcount(cols, out_fmt); ibuf += FRAME_HEADER_SIZE; @@ -2271,9 +2271,9 @@ static int find_over_exposure(int brightness) /* update various camera modes and settings */ static void dispatch_commands(struct cam_data *cam) { - down(&cam->param_lock); + mutex_lock(&cam->param_lock); if (cam->cmd_queue==COMMAND_NONE) { - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return; } DEB_BYTE(cam->cmd_queue); @@ -2415,7 +2415,7 @@ static void dispatch_commands(struct cam_data *cam) } cam->cmd_queue = COMMAND_NONE; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return; } @@ -2562,7 +2562,7 @@ static void monitor_exposure(struct cam_data *cam) gain = data[2]; coarseL = data[3]; - down(&cam->param_lock); + mutex_lock(&cam->param_lock); light_exp = cam->params.colourParams.brightness + TC - 50 + EXP_ACC_LIGHT; if(light_exp > 255) @@ -2762,7 +2762,7 @@ static void monitor_exposure(struct cam_data *cam) LOG("Automatically increasing sensor_fps\n"); } } - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); } /*-----------------------------------------------------------------*/ @@ -2778,10 +2778,10 @@ static void restart_flicker(struct cam_data *cam) int cam_exposure, old_exp; if(!FIRMWARE_VERSION(1,2)) return; - down(&cam->param_lock); + mutex_lock(&cam->param_lock); if(cam->params.flickerControl.flickerMode == 0 || cam->raw_image[39] == 0) { - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); return; } cam_exposure = cam->raw_image[39]*2; @@ -2810,7 +2810,7 @@ static void restart_flicker(struct cam_data *cam) cam->exposure_status = EXPOSURE_NORMAL; } - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); } #undef FIRMWARE_VERSION @@ -3186,7 +3186,7 @@ static int cpia_open(struct inode *inode, struct file *file) if (!try_module_get(cam->ops->owner)) return -ENODEV; - down(&cam->busy_lock); + mutex_lock(&cam->busy_lock); err = -ENOMEM; if (!cam->raw_image) { cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE); @@ -3227,7 +3227,7 @@ static int cpia_open(struct inode *inode, struct file *file) ++cam->open_count; file->private_data = dev; - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return 0; oops: @@ -3239,7 +3239,7 @@ static int cpia_open(struct inode *inode, struct file *file) rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); cam->raw_image = NULL; } - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); put_cam(cam->ops); return err; } @@ -3303,24 +3303,24 @@ static ssize_t cpia_read(struct file *file, char __user *buf, int err; /* make this _really_ smp and multithread-safe */ - if (down_interruptible(&cam->busy_lock)) + if (mutex_lock_interruptible(&cam->busy_lock)) return -EINTR; if (!buf) { DBG("buf NULL\n"); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EINVAL; } if (!count) { DBG("count 0\n"); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return 0; } if (!cam->ops) { DBG("ops NULL\n"); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -ENODEV; } @@ -3329,7 +3329,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf, cam->mmap_kludge=0; if((err = fetch_frame(cam)) != 0) { DBG("ERROR from fetch_frame: %d\n", err); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return err; } cam->decompressed_frame.state = FRAME_UNUSED; @@ -3338,17 +3338,17 @@ static ssize_t cpia_read(struct file *file, char __user *buf, if (cam->decompressed_frame.count > count) { DBG("count wrong: %d, %lu\n", cam->decompressed_frame.count, (unsigned long) count); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EFAULT; } if (copy_to_user(buf, cam->decompressed_frame.data, cam->decompressed_frame.count)) { DBG("copy_to_user failed\n"); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EFAULT; } - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return cam->decompressed_frame.count; } @@ -3363,7 +3363,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, return -ENODEV; /* make this _really_ smp-safe */ - if (down_interruptible(&cam->busy_lock)) + if (mutex_lock_interruptible(&cam->busy_lock)) return -EINTR; //DBG("cpia_ioctl: %u\n", ioctlnr); @@ -3439,7 +3439,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, break; } - down(&cam->param_lock); + mutex_lock(&cam->param_lock); /* brightness, colour, contrast need no check 0-65535 */ cam->vp = *vp; /* update cam->params.colourParams */ @@ -3466,7 +3466,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, /* queue command to update camera */ cam->cmd_queue |= COMMAND_SETCOLOURPARAMS; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); DBG("VIDIOCSPICT: %d / %d // %d / %d / %d / %d\n", vp->depth, vp->palette, vp->brightness, vp->hue, vp->colour, vp->contrast); @@ -3501,13 +3501,13 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, /* we set the video window to something smaller or equal to what * is requested by the user??? */ - down(&cam->param_lock); + mutex_lock(&cam->param_lock); if (vw->width != cam->vw.width || vw->height != cam->vw.height) { int video_size = match_videosize(vw->width, vw->height); if (video_size < 0) { retval = -EINVAL; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); break; } cam->video_size = video_size; @@ -3520,7 +3520,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, cam->cmd_queue |= COMMAND_SETFORMAT; } - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); /* setformat ignored by camera during streaming, * so stop/dispatch/start */ @@ -3682,7 +3682,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, DBG("%d,%d/%dx%d\n", vc->x,vc->y,vc->width, vc->height); - down(&cam->param_lock); + mutex_lock(&cam->param_lock); cam->vc.x = vc->x; cam->vc.y = vc->y; @@ -3692,7 +3692,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, set_vw_size(cam); cam->cmd_queue |= COMMAND_SETFORMAT; - up(&cam->param_lock); + mutex_unlock(&cam->param_lock); /* setformat ignored by camera during streaming, * so stop/dispatch/start */ @@ -3736,7 +3736,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, break; } - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return retval; } @@ -3769,12 +3769,12 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) return -ENODEV; /* make this _really_ smp-safe */ - if (down_interruptible(&cam->busy_lock)) + if (mutex_lock_interruptible(&cam->busy_lock)) return -EINTR; if (!cam->frame_buf) { /* we do lazy allocation */ if ((retval = allocate_frame_buf(cam))) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return retval; } } @@ -3783,7 +3783,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) while (size > 0) { page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EAGAIN; } start += PAGE_SIZE; @@ -3795,7 +3795,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) } DBG("cpia_mmap: %ld\n", size); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return 0; } @@ -3936,8 +3936,8 @@ static void init_camera_struct(struct cam_data *cam, memset(cam, 0, sizeof(struct cam_data)); cam->ops = ops; - init_MUTEX(&cam->param_lock); - init_MUTEX(&cam->busy_lock); + mutex_init(&cam->param_lock); + mutex_init(&cam->busy_lock); reset_camera_struct(cam); diff --git a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h index f629b693ee65..de6678200a57 100644 --- a/drivers/media/video/cpia.h +++ b/drivers/media/video/cpia.h @@ -47,6 +47,7 @@ #include #include #include +#include struct cpia_camera_ops { @@ -246,7 +247,7 @@ enum v4l_camstates { struct cam_data { struct list_head cam_data_list; - struct semaphore busy_lock; /* guard against SMP multithreading */ + struct mutex busy_lock; /* guard against SMP multithreading */ struct cpia_camera_ops *ops; /* lowlevel driver operations */ void *lowlevel_data; /* private data for lowlevel driver */ u8 *raw_image; /* buffer for raw image data */ @@ -261,7 +262,7 @@ struct cam_data { u8 mainsFreq; /* for flicker control */ /* proc interface */ - struct semaphore param_lock; /* params lock for this camera */ + struct mutex param_lock; /* params lock for this camera */ struct cam_params params; /* camera settings */ struct proc_dir_entry *proc_entry; /* /proc/cpia/videoX */ diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 3720f24a25cf..eda7cd8b2d4a 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -1061,7 +1061,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci) core->pci_bus = pci->bus->number; core->pci_slot = PCI_SLOT(pci->devfn); core->pci_irqmask = 0x00fc00; - init_MUTEX(&core->lock); + mutex_init(&core->lock); core->nr = cx88_devcount++; sprintf(core->name,"cx88[%d]",core->nr); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 073494ceab0f..d15ef158ac8f 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -336,17 +336,17 @@ static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bi return 1; /* is it free? */ - down(&core->lock); + mutex_lock(&core->lock); if (dev->resources & bit) { /* no, someone else uses it */ - up(&core->lock); + mutex_unlock(&core->lock); return 0; } /* it's free, grab it */ fh->resources |= bit; dev->resources |= bit; dprintk(1,"res: get %d\n",bit); - up(&core->lock); + mutex_unlock(&core->lock); return 1; } @@ -369,11 +369,11 @@ void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits) if ((fh->resources & bits) != bits) BUG(); - down(&core->lock); + mutex_lock(&core->lock); fh->resources &= ~bits; dev->resources &= ~bits; dprintk(1,"res: put %d\n",bits); - up(&core->lock); + mutex_unlock(&core->lock); } /* ------------------------------------------------------------------ */ @@ -1291,9 +1291,9 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, if (i == ARRAY_SIZE(tvnorms)) return -EINVAL; - down(&core->lock); + mutex_lock(&core->lock); cx88_set_tvnorm(core,&tvnorms[i]); - up(&core->lock); + mutex_unlock(&core->lock); return 0; } @@ -1343,10 +1343,10 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, if (*i >= 4) return -EINVAL; - down(&core->lock); + mutex_lock(&core->lock); cx88_newstation(core); video_mux(core,*i); - up(&core->lock); + mutex_unlock(&core->lock); return 0; } @@ -1438,7 +1438,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, return -EINVAL; if (1 == radio && f->type != V4L2_TUNER_RADIO) return -EINVAL; - down(&core->lock); + mutex_lock(&core->lock); core->freq = f->frequency; cx88_newstation(core); cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f); @@ -1447,7 +1447,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, msleep (10); cx88_set_tvaudio(core); - up(&core->lock); + mutex_unlock(&core->lock); return 0; } @@ -1921,11 +1921,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, pci_set_drvdata(pci_dev,dev); /* initial device configuration */ - down(&core->lock); + mutex_lock(&core->lock); cx88_set_tvnorm(core,tvnorms); init_controls(core); video_mux(core,0); - up(&core->lock); + mutex_unlock(&core->lock); /* start tvaudio thread */ if (core->tuner_type != TUNER_ABSENT) diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 31a688a3fb77..a4cf2473eacf 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -35,6 +35,7 @@ #include "cx88-reg.h" #include +#include #define CX88_VERSION_CODE KERNEL_VERSION(0,0,5) #ifndef TRUE @@ -309,8 +310,7 @@ struct cx88_core { /* IR remote control state */ struct cx88_IR *ir; - struct semaphore lock; - + struct mutex lock; /* various v4l controls */ u32 freq; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 1c1557d9bace..671fc52b6a88 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -362,12 +362,12 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) return -EBUSY; } - init_MUTEX(&dev->fileop_lock); /* to 1 == available */ + mutex_init(&dev->fileop_lock); /* to 1 == available */ spin_lock_init(&dev->queue_lock); init_waitqueue_head(&dev->wait_frame); init_waitqueue_head(&dev->wait_stream); - down(&dev->lock); + mutex_lock(&dev->lock); if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { em28xx_set_alternate(dev); @@ -404,8 +404,8 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev->state |= DEV_INITIALIZED; - err: - up(&dev->lock); +err: + mutex_unlock(&dev->lock); up_read(&em28xx_disconnect); return errCode; } @@ -447,7 +447,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) em28xx_videodbg("users=%d\n", dev->users); - down(&dev->lock); + mutex_lock(&dev->lock); em28xx_uninit_isoc(dev); @@ -456,7 +456,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) /* the device is already disconnect, free the remaining resources */ if (dev->state & DEV_DISCONNECTED) { em28xx_release_resources(dev); - up(&dev->lock); + mutex_unlock(&dev->lock); kfree(dev); return 0; } @@ -472,7 +472,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) dev->users--; wake_up_interruptible_nr(&dev->open, 1); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -496,7 +496,7 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n"); em28xx_videodbg("not supported yet! ...\n"); if (copy_to_user(buf, "", 1)) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EFAULT; } return (1); @@ -505,38 +505,38 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n"); em28xx_videodbg("not supported yet! ...\n"); if (copy_to_user(buf, "", 1)) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EFAULT; } return (1); } - if (down_interruptible(&dev->fileop_lock)) + if (mutex_lock_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { em28xx_videodbg("device not present\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { em28xx_videodbg("device misconfigured; close and open it again\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EIO; } if (dev->io == IO_MMAP) { em28xx_videodbg ("IO method is set to mmap; close and open" " the device again to choose the read method\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EINVAL; } if (dev->io == IO_NONE) { if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) { em28xx_errdev("read failed, not enough memory\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -ENOMEM; } dev->io = IO_READ; @@ -545,13 +545,13 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, } if (!count) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return 0; } if (list_empty(&dev->outqueue)) { if (filp->f_flags & O_NONBLOCK) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EAGAIN; } ret = wait_event_interruptible @@ -559,11 +559,11 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, (!list_empty(&dev->outqueue)) || (dev->state & DEV_DISCONNECTED)); if (ret) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return ret; } if (dev->state & DEV_DISCONNECTED) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -ENODEV; } } @@ -582,12 +582,12 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, count = f->buf.length; if (copy_to_user(buf, f->bufmem, count)) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EFAULT; } *f_pos += count; - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return count; } @@ -601,7 +601,7 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) unsigned int mask = 0; struct em28xx *dev = filp->private_data; - if (down_interruptible(&dev->fileop_lock)) + if (mutex_lock_interruptible(&dev->fileop_lock)) return POLLERR; if (dev->state & DEV_DISCONNECTED) { @@ -627,13 +627,13 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) if (!list_empty(&dev->outqueue)) mask |= POLLIN | POLLRDNORM; - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return mask; } } - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return POLLERR; } @@ -673,25 +673,25 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) struct em28xx *dev = filp->private_data; - if (down_interruptible(&dev->fileop_lock)) + if (mutex_lock_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { em28xx_videodbg("mmap: device not present\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { em28xx_videodbg ("mmap: Device is misconfigured; close and " "open it again\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EIO; } if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || size != PAGE_ALIGN(dev->frame[0].buf.length)) { - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EINVAL; } @@ -701,7 +701,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) } if (i == dev->num_frames) { em28xx_videodbg("mmap: user supplied mapping address is out of range\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EINVAL; } @@ -713,7 +713,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) while (size > 0) { /* size is page-aligned */ if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { em28xx_videodbg("mmap: vm_insert_page failed\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EAGAIN; } start += PAGE_SIZE; @@ -725,7 +725,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_private_data = &dev->frame[i]; em28xx_vm_open(vma); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return 0; } @@ -1125,7 +1125,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, if (i == TVNORMS) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); dev->tvnorm = &tvnorms[i]; em28xx_set_norm(dev, dev->width, dev->height); @@ -1135,7 +1135,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -1189,9 +1189,9 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, if (0 == INPUT(*index)->type) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); video_mux(dev, *index); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -1338,10 +1338,10 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, /* t->signal = 0xffff;*/ /* em28xx_i2c_call_clients(dev,VIDIOC_G_TUNER,t);*/ /* No way to get signal strength? */ - down(&dev->lock); + mutex_lock(&dev->lock); em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, &status); - up(&dev->lock); + mutex_unlock(&dev->lock); t->signal = (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; @@ -1363,10 +1363,10 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */ /* t->signal = 0xffff; */ /* No way to get signal strength? */ - down(&dev->lock); + mutex_lock(&dev->lock); em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, &status); - up(&dev->lock); + mutex_unlock(&dev->lock); t->signal = (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; @@ -1394,10 +1394,10 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, if (V4L2_TUNER_ANALOG_TV != f->type) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); dev->ctl_freq = f->frequency; em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } case VIDIOC_CROPCAP: @@ -1660,25 +1660,25 @@ static int em28xx_v4l2_ioctl(struct inode *inode, struct file *filp, int ret = 0; struct em28xx *dev = filp->private_data; - if (down_interruptible(&dev->fileop_lock)) + if (mutex_lock_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { em28xx_errdev("v4l2 ioctl: device not present\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { em28xx_errdev ("v4l2 ioctl: device is misconfigured; close and open it again\n"); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return -EIO; } ret = video_usercopy(inode, filp, cmd, arg, em28xx_video_do_ioctl); - up(&dev->fileop_lock); + mutex_unlock(&dev->fileop_lock); return ret; } @@ -1712,7 +1712,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->udev = udev; dev->model = model; - init_MUTEX(&dev->lock); + mutex_init(&dev->lock); init_waitqueue_head(&dev->open); dev->em28xx_write_regs = em28xx_write_regs; @@ -1788,7 +1788,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return -ENOMEM; } - down(&dev->lock); + mutex_lock(&dev->lock); /* register i2c bus */ em28xx_i2c_register(dev); @@ -1798,7 +1798,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, /* configure the device */ em28xx_config_i2c(dev); - up(&dev->lock); + mutex_unlock(&dev->lock); errCode = em28xx_config(dev); @@ -1849,12 +1849,12 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, list_add_tail(&dev->devlist,&em28xx_devlist); /* register v4l2 device */ - down(&dev->lock); + mutex_lock(&dev->lock); if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, video_nr[dev->devno]))) { em28xx_errdev("unable to register video device (error=%i).\n", retval); - up(&dev->lock); + mutex_unlock(&dev->lock); list_del(&dev->devlist); video_device_release(dev->vdev); kfree(dev); @@ -1865,7 +1865,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, vbi_nr[dev->devno]) < 0) { printk("unable to register vbi device\n"); - up(&dev->lock); + mutex_unlock(&dev->lock); list_del(&dev->devlist); video_device_release(dev->vbi_dev); video_device_release(dev->vdev); @@ -1886,7 +1886,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, } video_mux(dev, 0); - up(&dev->lock); + mutex_unlock(&dev->lock); em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, @@ -2035,7 +2035,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) down_write(&em28xx_disconnect); - down(&dev->lock); + mutex_lock(&dev->lock); em28xx_info("disconnecting %s\n", dev->vdev->name); @@ -2057,7 +2057,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) em28xx_release_resources(dev); } - up(&dev->lock); + mutex_unlock(&dev->lock); if (!dev->users) { kfree(dev->alt_max_pkt_size); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index ddf06c520e99..4e2fe62b7350 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -27,6 +27,7 @@ #include #include +#include #include /* Boards supported by driver */ @@ -260,7 +261,7 @@ struct em28xx { enum em28xx_stream_state stream; enum em28xx_io_method io; /* locks */ - struct semaphore lock, fileop_lock; + struct mutex lock, fileop_lock; spinlock_t queue_lock; struct list_head inqueue, outqueue; wait_queue_head_t open, wait_frame, wait_stream; diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 2869464aee0d..850bee97090c 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -925,7 +925,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (p->palette != VIDEO_PALETTE_YUV422) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, p->brightness >> 10); sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, @@ -935,7 +935,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST, p->contrast >> 10); meye.picture = *p; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -946,21 +946,21 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (*i < 0 || *i >= gbuffers) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); switch (meye.grab_buffer[*i].state) { case MEYE_BUF_UNUSED: - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; case MEYE_BUF_USING: if (file->f_flags & O_NONBLOCK) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EAGAIN; } if (wait_event_interruptible(meye.proc_list, (meye.grab_buffer[*i].state != MEYE_BUF_USING))) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINTR; } /* fall through */ @@ -968,7 +968,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); } - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -987,7 +987,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (meye.grab_buffer[vm->frame].state != MEYE_BUF_UNUSED) return -EBUSY; - down(&meye.lock); + mutex_lock(&meye.lock); if (vm->width == 640 && vm->height == 480) { if (meye.params.subsample) { meye.params.subsample = 0; @@ -999,7 +999,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, restart = 1; } } else { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } @@ -1007,7 +1007,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, mchip_continuous_start(); meye.grab_buffer[vm->frame].state = MEYE_BUF_USING; kfifo_put(meye.grabq, (unsigned char *)&vm->frame, sizeof(int)); - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1039,7 +1039,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (jp->framerate > 31) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); if (meye.params.subsample != jp->subsample || meye.params.quality != jp->quality) mchip_hic_stop(); /* need restart */ @@ -1050,7 +1050,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.params.agc); sonypi_camera_command(SONYPI_COMMAND_SETCAMERAPICTURE, meye.params.picture); - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1068,12 +1068,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, } if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED) return -EBUSY; - down(&meye.lock); + mutex_lock(&meye.lock); if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP) mchip_cont_compression_start(); meye.grab_buffer[*nb].state = MEYE_BUF_USING; kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int)); - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1084,20 +1084,20 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (*i < 0 || *i >= gbuffers) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); switch (meye.grab_buffer[*i].state) { case MEYE_BUF_UNUSED: - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; case MEYE_BUF_USING: if (file->f_flags & O_NONBLOCK) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EAGAIN; } if (wait_event_interruptible(meye.proc_list, (meye.grab_buffer[*i].state != MEYE_BUF_USING))) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINTR; } /* fall through */ @@ -1106,7 +1106,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); } *i = meye.grab_buffer[*i].size; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1116,14 +1116,14 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) return -EBUSY; - down(&meye.lock); + mutex_lock(&meye.lock); meye.grab_buffer[0].state = MEYE_BUF_USING; mchip_take_picture(); mchip_get_picture( meye.grab_fbuffer, mchip_hsize() * mchip_vsize() * 2); meye.grab_buffer[0].state = MEYE_BUF_DONE; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1134,7 +1134,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) return -EBUSY; - down(&meye.lock); + mutex_lock(&meye.lock); meye.grab_buffer[0].state = MEYE_BUF_USING; *len = -1; while (*len == -1) { @@ -1142,7 +1142,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize); } meye.grab_buffer[0].state = MEYE_BUF_DONE; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1285,7 +1285,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_S_CTRL: { struct v4l2_control *c = arg; - down(&meye.lock); + mutex_lock(&meye.lock); switch (c->id) { case V4L2_CID_BRIGHTNESS: sonypi_camera_command( @@ -1329,17 +1329,17 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.params.framerate = c->value; break; default: - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } - up(&meye.lock); + mutex_unlock(&meye.lock); break; } case VIDIOC_G_CTRL: { struct v4l2_control *c = arg; - down(&meye.lock); + mutex_lock(&meye.lock); switch (c->id) { case V4L2_CID_BRIGHTNESS: c->value = meye.picture.brightness >> 10; @@ -1369,10 +1369,10 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, c->value = meye.params.framerate; break; default: - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1469,7 +1469,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, f->fmt.pix.field != V4L2_FIELD_NONE) return -EINVAL; f->fmt.pix.field = V4L2_FIELD_NONE; - down(&meye.lock); + mutex_lock(&meye.lock); if (f->fmt.pix.width <= 320) { f->fmt.pix.width = 320; f->fmt.pix.height = 240; @@ -1487,7 +1487,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP; break; } - up(&meye.lock); + mutex_unlock(&meye.lock); f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; @@ -1509,11 +1509,11 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, /* already allocated, no modifications */ break; } - down(&meye.lock); + mutex_lock(&meye.lock); if (meye.grab_fbuffer) { for (i = 0; i < gbuffers; i++) if (meye.vma_use_count[i]) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } rvfree(meye.grab_fbuffer, gbuffers * gbufsize); @@ -1525,12 +1525,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (!meye.grab_fbuffer) { printk(KERN_ERR "meye: v4l framebuffer allocation" " failed\n"); - up(&meye.lock); + mutex_unlock(&meye.lock); return -ENOMEM; } for (i = 0; i < gbuffers; i++) meye.vma_use_count[i] = 0; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1569,12 +1569,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); buf->flags |= V4L2_BUF_FLAG_QUEUED; buf->flags &= ~V4L2_BUF_FLAG_DONE; meye.grab_buffer[buf->index].state = MEYE_BUF_USING; kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int)); - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1587,23 +1587,23 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; - down(&meye.lock); + mutex_lock(&meye.lock); if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EAGAIN; } if (wait_event_interruptible(meye.proc_list, kfifo_len(meye.doneq) != 0) < 0) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINTR; } if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr, sizeof(int))) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EBUSY; } if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } buf->index = reqnr; @@ -1616,12 +1616,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, buf->m.offset = reqnr * gbufsize; buf->length = gbufsize; meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } case VIDIOC_STREAMON: { - down(&meye.lock); + mutex_lock(&meye.lock); switch (meye.mchip_mode) { case MCHIP_HIC_MODE_CONT_OUT: mchip_continuous_start(); @@ -1630,23 +1630,23 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, mchip_cont_compression_start(); break; default: - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } - up(&meye.lock); + mutex_unlock(&meye.lock); break; } case VIDIOC_STREAMOFF: { int i; - down(&meye.lock); + mutex_lock(&meye.lock); mchip_hic_stop(); kfifo_reset(meye.grabq); kfifo_reset(meye.doneq); for (i = 0; i < MEYE_MAX_BUFNBRS; i++) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; - up(&meye.lock); + mutex_unlock(&meye.lock); break; } @@ -1672,11 +1672,11 @@ static unsigned int meye_poll(struct file *file, poll_table *wait) { unsigned int res = 0; - down(&meye.lock); + mutex_lock(&meye.lock); poll_wait(file, &meye.proc_list, wait); if (kfifo_len(meye.doneq)) res = POLLIN | POLLRDNORM; - up(&meye.lock); + mutex_unlock(&meye.lock); return res; } @@ -1704,9 +1704,9 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; unsigned long page, pos; - down(&meye.lock); + mutex_lock(&meye.lock); if (size > gbuffers * gbufsize) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EINVAL; } if (!meye.grab_fbuffer) { @@ -1716,7 +1716,7 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) meye.grab_fbuffer = rvmalloc(gbuffers*gbufsize); if (!meye.grab_fbuffer) { printk(KERN_ERR "meye: v4l framebuffer allocation failed\n"); - up(&meye.lock); + mutex_unlock(&meye.lock); return -ENOMEM; } for (i = 0; i < gbuffers; i++) @@ -1727,7 +1727,7 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) while (size > 0) { page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - up(&meye.lock); + mutex_unlock(&meye.lock); return -EAGAIN; } start += PAGE_SIZE; @@ -1744,7 +1744,7 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_private_data = (void *) (offset / gbufsize); meye_vm_open(vma); - up(&meye.lock); + mutex_unlock(&meye.lock); return 0; } @@ -1913,7 +1913,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev, goto outvideoreg; } - init_MUTEX(&meye.lock); + mutex_init(&meye.lock); init_waitqueue_head(&meye.proc_list); meye.picture.depth = 16; meye.picture.palette = VIDEO_PALETTE_YUV422; diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index e8cd897b0d20..0d09a0e3803c 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h @@ -260,6 +260,8 @@ /* private API definitions */ #include +#include + /* Enable jpg software correction */ #define MEYE_JPEG_CORRECTION 1 @@ -301,7 +303,7 @@ struct meye { /* list of buffers */ struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS]; int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */ - struct semaphore lock; /* semaphore for open/mmap... */ + struct mutex lock; /* mutex for open/mmap... */ struct kfifo *grabq; /* queue for buffers to be grabbed */ spinlock_t grabq_lock; /* lock protecting the queue */ struct kfifo *doneq; /* queue for grabbed buffers */ diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 8416ceff524b..69a7eddf3a24 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -625,9 +625,9 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) } /* fixme: locke das setzen des inputs mit hilfe des mutexes - down(&dev->lock); + mutex_lock(&dev->lock); video_mux(dev,*i); - up(&dev->lock); + mutex_unlock(&dev->lock); */ /* fixme: check if streaming capture diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index f3fc361bec97..15fd85acabda 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include "planb.h" #include "saa7196.h" @@ -329,12 +329,12 @@ static volatile struct dbdma_cmd *cmd_geo_setup( static inline void planb_lock(struct planb *pb) { - down(&pb->lock); + mutex_lock(&pb->lock); } static inline void planb_unlock(struct planb *pb) { - up(&pb->lock); + mutex_unlock(&pb->lock); } /***************/ @@ -2067,7 +2067,7 @@ static int init_planb(struct planb *pb) #endif pb->tab_size = PLANB_MAXLINES + 40; pb->suspend = 0; - init_MUTEX(&pb->lock); + mutex_init(&pb->lock); pb->ch1_cmd = 0; pb->ch2_cmd = 0; pb->mask = 0; diff --git a/drivers/media/video/planb.h b/drivers/media/video/planb.h index 8a0faad16118..79b6b561426e 100644 --- a/drivers/media/video/planb.h +++ b/drivers/media/video/planb.h @@ -174,7 +174,7 @@ struct planb { int user; unsigned int tab_size; int maxlines; - struct semaphore lock; + struct mutex lock; unsigned int irq; /* interrupt number */ volatile unsigned int intr_mask; diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 9e6448639480..05ca55939e77 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -30,6 +30,8 @@ #include #include #include +#include + #include @@ -44,7 +46,7 @@ struct pms_device struct video_picture picture; int height; int width; - struct semaphore lock; + struct mutex lock; }; struct i2c_info @@ -724,10 +726,10 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, struct video_channel *v = arg; if(v->channel<0 || v->channel>3) return -EINVAL; - down(&pd->lock); + mutex_lock(&pd->lock); pms_videosource(v->channel&1); pms_vcrinput(v->channel>>1); - up(&pd->lock); + mutex_unlock(&pd->lock); return 0; } case VIDIOCGTUNER: @@ -761,7 +763,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, struct video_tuner *v = arg; if(v->tuner) return -EINVAL; - down(&pd->lock); + mutex_lock(&pd->lock); switch(v->mode) { case VIDEO_MODE_AUTO: @@ -785,10 +787,10 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, pms_format(2); break; default: - up(&pd->lock); + mutex_unlock(&pd->lock); return -EINVAL; } - up(&pd->lock); + mutex_unlock(&pd->lock); return 0; } case VIDIOCGPICT: @@ -809,12 +811,12 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, * Now load the card. */ - down(&pd->lock); + mutex_lock(&pd->lock); pms_brightness(p->brightness>>8); pms_hue(p->hue>>8); pms_colour(p->colour>>8); pms_contrast(p->contrast>>8); - up(&pd->lock); + mutex_unlock(&pd->lock); return 0; } case VIDIOCSWIN: @@ -830,9 +832,9 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; pd->width=vw->width; pd->height=vw->height; - down(&pd->lock); + mutex_lock(&pd->lock); pms_resolution(pd->width, pd->height); - up(&pd->lock); /* Ok we figured out what to use from our wide choice */ + mutex_unlock(&pd->lock); /* Ok we figured out what to use from our wide choice */ return 0; } case VIDIOCGWIN: @@ -872,9 +874,9 @@ static ssize_t pms_read(struct file *file, char __user *buf, struct pms_device *pd=(struct pms_device *)v; int len; - down(&pd->lock); + mutex_lock(&pd->lock); len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count); - up(&pd->lock); + mutex_unlock(&pd->lock); return len; } @@ -1029,7 +1031,7 @@ static int __init init_pms_cards(void) return -ENODEV; } memcpy(&pms_device, &pms_template, sizeof(pms_template)); - init_MUTEX(&pms_device.lock); + mutex_init(&pms_device.lock); pms_device.height=240; pms_device.width=320; pms_swsense(75); diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 2ce010201308..dd830e0e5e96 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -46,6 +46,8 @@ #include #include #include +#include + #include "saa5246a.h" MODULE_AUTHOR("Michael Geng "); @@ -57,7 +59,7 @@ struct saa5246a_device u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; int is_searching[NUM_DAUS]; struct i2c_client *client; - struct semaphore lock; + struct mutex lock; }; static struct video_device saa_template; /* Declared near bottom */ @@ -90,7 +92,7 @@ static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind) return -ENOMEM; } strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); - init_MUTEX(&t->lock); + mutex_init(&t->lock); /* * Now create a video4linux device @@ -719,9 +721,9 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file, int err; cmd = vtx_fix_command(cmd); - down(&t->lock); + mutex_lock(&t->lock); err = video_usercopy(inode, file, cmd, arg, do_saa5246a_ioctl); - up(&t->lock); + mutex_unlock(&t->lock); return err; } diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 5694eb58c3a1..a9f3cf0b1e3c 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -56,6 +56,8 @@ #include #include #include +#include + #include #include @@ -105,7 +107,7 @@ struct saa5249_device int disp_mode; int virtual_mode; struct i2c_client *client; - struct semaphore lock; + struct mutex lock; }; @@ -158,7 +160,7 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) return -ENOMEM; } strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); - init_MUTEX(&t->lock); + mutex_init(&t->lock); /* * Now create a video4linux device @@ -619,9 +621,9 @@ static int saa5249_ioctl(struct inode *inode, struct file *file, int err; cmd = vtx_fix_command(cmd); - down(&t->lock); + mutex_lock(&t->lock); err = video_usercopy(inode,file,cmd,arg,do_saa5249_ioctl); - up(&t->lock); + mutex_unlock(&t->lock); return err; } diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index a7a6ab9298a9..d3c7345a5d22 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -609,12 +609,12 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) struct saa7134_dev *dev = saa7134->dev; int err; - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); dev->dmasound.read_count = 0; dev->dmasound.read_offset = 0; - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); if (pcm == NULL) @@ -932,7 +932,7 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) chip->irq = dev->pci->irq; - init_MUTEX(&dev->dmasound.lock); + mutex_init(&dev->dmasound.lock); if ((err = snd_card_saa7134_new_mixer(chip)) < 0) goto __nodev; diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 028904bd94a2..e7c30665739e 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -613,7 +613,7 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, 0); - init_MUTEX(&dev->lock); + mutex_init(&dev->lock); spin_lock_init(&dev->slock); saa7134_track_gpio(dev,"pre-init"); diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index bd4c389d4c37..1d972edb3be6 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -89,7 +89,7 @@ static int ts_open(struct inode *inode, struct file *file) dprintk("open minor=%d\n",minor); err = -EBUSY; - if (down_trylock(&dev->empress_tsq.lock)) + if (!mutex_trylock(&dev->empress_tsq.lock)) goto done; if (dev->empress_users) goto done_up; @@ -99,7 +99,7 @@ static int ts_open(struct inode *inode, struct file *file) err = 0; done_up: - up(&dev->empress_tsq.lock); + mutex_unlock(&dev->empress_tsq.lock); done: return err; } @@ -110,7 +110,7 @@ static int ts_release(struct inode *inode, struct file *file) if (dev->empress_tsq.streaming) videobuf_streamoff(&dev->empress_tsq); - down(&dev->empress_tsq.lock); + mutex_lock(&dev->empress_tsq.lock); if (dev->empress_tsq.reading) videobuf_read_stop(&dev->empress_tsq); videobuf_mmap_free(&dev->empress_tsq); @@ -119,7 +119,7 @@ static int ts_release(struct inode *inode, struct file *file) /* stop the encoder */ ts_reset_encoder(dev); - up(&dev->empress_tsq.lock); + mutex_unlock(&dev->empress_tsq.lock); return 0; } diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index 7448e386a804..80e34a5fdcc5 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -254,7 +254,7 @@ static int dsp_open(struct inode *inode, struct file *file) if (NULL == dev) return -ENODEV; - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); err = -EBUSY; if (dev->dmasound.users_dsp) goto fail1; @@ -270,13 +270,13 @@ static int dsp_open(struct inode *inode, struct file *file) if (0 != err) goto fail2; - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return 0; fail2: dev->dmasound.users_dsp--; fail1: - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return err; } @@ -284,13 +284,13 @@ static int dsp_release(struct inode *inode, struct file *file) { struct saa7134_dev *dev = file->private_data; - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); if (dev->dmasound.recording_on) dsp_rec_stop(dev); dsp_buffer_free(dev); dev->dmasound.users_dsp--; file->private_data = NULL; - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return 0; } @@ -304,7 +304,7 @@ static ssize_t dsp_read(struct file *file, char __user *buffer, int err,ret = 0; add_wait_queue(&dev->dmasound.wq, &wait); - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); while (count > 0) { /* wait for data if needed */ if (0 == dev->dmasound.read_count) { @@ -328,12 +328,12 @@ static ssize_t dsp_read(struct file *file, char __user *buffer, ret = -EAGAIN; break; } - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); set_current_state(TASK_INTERRUPTIBLE); if (0 == dev->dmasound.read_count) schedule(); set_current_state(TASK_RUNNING); - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); if (signal_pending(current)) { if (0 == ret) ret = -EINTR; @@ -362,7 +362,7 @@ static ssize_t dsp_read(struct file *file, char __user *buffer, if (dev->dmasound.read_offset == dev->dmasound.bufsize) dev->dmasound.read_offset = 0; } - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); remove_wait_queue(&dev->dmasound.wq, &wait); return ret; } @@ -435,13 +435,13 @@ static int dsp_ioctl(struct inode *inode, struct file *file, case SNDCTL_DSP_STEREO: if (get_user(val, p)) return -EFAULT; - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); dev->dmasound.channels = val ? 2 : 1; if (dev->dmasound.recording_on) { dsp_rec_stop(dev); dsp_rec_start(dev); } - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return put_user(dev->dmasound.channels-1, p); case SNDCTL_DSP_CHANNELS: @@ -449,13 +449,13 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return -EFAULT; if (val != 1 && val != 2) return -EINVAL; - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); dev->dmasound.channels = val; if (dev->dmasound.recording_on) { dsp_rec_stop(dev); dsp_rec_start(dev); } - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); /* fall through */ case SOUND_PCM_READ_CHANNELS: return put_user(dev->dmasound.channels, p); @@ -478,13 +478,13 @@ static int dsp_ioctl(struct inode *inode, struct file *file, case AFMT_U16_BE: case AFMT_S16_LE: case AFMT_S16_BE: - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); dev->dmasound.afmt = val; if (dev->dmasound.recording_on) { dsp_rec_stop(dev); dsp_rec_start(dev); } - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return put_user(dev->dmasound.afmt, p); default: return -EINVAL; @@ -509,10 +509,10 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return 0; case SNDCTL_DSP_RESET: - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); if (dev->dmasound.recording_on) dsp_rec_stop(dev); - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); return 0; case SNDCTL_DSP_GETBLKSIZE: return put_user(dev->dmasound.blksize, p); @@ -556,10 +556,10 @@ static unsigned int dsp_poll(struct file *file, struct poll_table_struct *wait) poll_wait(file, &dev->dmasound.wq, wait); if (0 == dev->dmasound.read_count) { - down(&dev->dmasound.lock); + mutex_lock(&dev->dmasound.lock); if (!dev->dmasound.recording_on) dsp_rec_start(dev); - up(&dev->dmasound.lock); + mutex_unlock(&dev->dmasound.lock); } else mask |= (POLLIN | POLLRDNORM); return mask; @@ -852,7 +852,7 @@ int saa7134_oss_init1(struct saa7134_dev *dev) return -1; /* general */ - init_MUTEX(&dev->dmasound.lock); + mutex_init(&dev->dmasound.lock); init_waitqueue_head(&dev->dmasound.wq); switch (dev->pci->device) { diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index e97426bc85df..72f389a51a13 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -460,17 +460,17 @@ static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int return 1; /* is it free? */ - down(&dev->lock); + mutex_lock(&dev->lock); if (dev->resources & bit) { /* no, someone else uses it */ - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } /* it's free, grab it */ fh->resources |= bit; dev->resources |= bit; dprintk("res: get %d\n",bit); - up(&dev->lock); + mutex_unlock(&dev->lock); return 1; } @@ -492,11 +492,11 @@ void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits) if ((fh->resources & bits) != bits) BUG(); - down(&dev->lock); + mutex_lock(&dev->lock); fh->resources &= ~bits; dev->resources &= ~bits; dprintk("res: put %d\n",bits); - up(&dev->lock); + mutex_unlock(&dev->lock); } /* ------------------------------------------------------------------ */ @@ -1340,21 +1340,21 @@ video_poll(struct file *file, struct poll_table_struct *wait) if (!list_empty(&fh->cap.stream)) buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream); } else { - down(&fh->cap.lock); + mutex_lock(&fh->cap.lock); if (UNSET == fh->cap.read_off) { /* need to capture a new frame */ if (res_locked(fh->dev,RESOURCE_VIDEO)) { - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return POLLERR; } if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); return POLLERR; } fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; } - up(&fh->cap.lock); + mutex_unlock(&fh->cap.lock); buf = fh->cap.read_buf; } @@ -1561,14 +1561,14 @@ static int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, if (0 != err) return err; - down(&dev->lock); + mutex_lock(&dev->lock); fh->win = f->fmt.win; fh->nclips = f->fmt.win.clipcount; if (fh->nclips > 8) fh->nclips = 8; if (copy_from_user(fh->clips,f->fmt.win.clips, sizeof(struct v4l2_clip)*fh->nclips)) { - up(&dev->lock); + mutex_unlock(&dev->lock); return -EFAULT; } @@ -1578,7 +1578,7 @@ static int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, start_preview(dev,fh); spin_unlock_irqrestore(&dev->slock,flags); } - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; case V4L2_BUF_TYPE_VBI_CAPTURE: saa7134_vbi_fmt(dev,f); @@ -1612,9 +1612,9 @@ int saa7134_common_ioctl(struct saa7134_dev *dev, return get_control(dev,arg); case VIDIOC_S_CTRL: { - down(&dev->lock); + mutex_lock(&dev->lock); err = set_control(dev,NULL,arg); - up(&dev->lock); + mutex_unlock(&dev->lock); return err; } /* --- input switching --------------------------------------- */ @@ -1664,9 +1664,9 @@ int saa7134_common_ioctl(struct saa7134_dev *dev, return -EINVAL; if (NULL == card_in(dev,*i).name) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); video_mux(dev,*i); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -1766,7 +1766,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, if (i == TVNORMS) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); if (res_check(fh, RESOURCE_OVERLAY)) { spin_lock_irqsave(&dev->slock,flags); stop_preview(dev,fh); @@ -1776,7 +1776,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } else set_tvnorm(dev,&tvnorms[i]); saa7134_tvaudio_do_scan(dev); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -1909,13 +1909,13 @@ static int video_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (1 == fh->radio && V4L2_TUNER_RADIO != f->type) return -EINVAL; - down(&dev->lock); + mutex_lock(&dev->lock); dev->ctl_freq = f->frequency; saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f); saa7134_tvaudio_do_scan(dev); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index ff39a63c7372..691c10be459d 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -364,7 +365,7 @@ struct saa7134_fh { /* dmasound dsp status */ struct saa7134_dmasound { - struct semaphore lock; + struct mutex lock; int minor_mixer; int minor_dsp; unsigned int users_dsp; @@ -428,7 +429,7 @@ struct saa7134_mpeg_ops { /* global device status */ struct saa7134_dev { struct list_head devlist; - struct semaphore lock; + struct mutex lock; spinlock_t slock; #ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c index 0a4004a4393c..caf3e7e2f219 100644 --- a/drivers/media/video/video-buf-dvb.c +++ b/drivers/media/video/video-buf-dvb.c @@ -96,7 +96,7 @@ static int videobuf_dvb_start_feed(struct dvb_demux_feed *feed) if (!demux->dmx.frontend) return -EINVAL; - down(&dvb->lock); + mutex_lock(&dvb->lock); dvb->nfeeds++; rc = dvb->nfeeds; @@ -110,7 +110,7 @@ static int videobuf_dvb_start_feed(struct dvb_demux_feed *feed) } out: - up(&dvb->lock); + mutex_unlock(&dvb->lock); return rc; } @@ -120,14 +120,14 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed) struct videobuf_dvb *dvb = demux->priv; int err = 0; - down(&dvb->lock); + mutex_lock(&dvb->lock); dvb->nfeeds--; if (0 == dvb->nfeeds && NULL != dvb->thread) { // FIXME: cx8802_cancel_buffers(dev); err = kthread_stop(dvb->thread); dvb->thread = NULL; } - up(&dvb->lock); + mutex_unlock(&dvb->lock); return err; } @@ -139,7 +139,7 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb, { int result; - init_MUTEX(&dvb->lock); + mutex_init(&dvb->lock); /* register adapter */ result = dvb_register_adapter(&dvb->adapter, dvb->name, module); diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 9ef477523d27..cb1c228e29f8 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -385,7 +385,7 @@ void videobuf_queue_init(struct videobuf_queue* q, q->ops = ops; q->priv_data = priv; - init_MUTEX(&q->lock); + mutex_init(&q->lock); INIT_LIST_HEAD(&q->stream); } @@ -549,7 +549,7 @@ videobuf_reqbufs(struct videobuf_queue *q, if (!list_empty(&q->stream)) return -EBUSY; - down(&q->lock); + mutex_lock(&q->lock); count = req->count; if (count > VIDEO_MAX_FRAME) count = VIDEO_MAX_FRAME; @@ -566,7 +566,7 @@ videobuf_reqbufs(struct videobuf_queue *q, req->count = count; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -592,7 +592,7 @@ videobuf_qbuf(struct videobuf_queue *q, unsigned long flags; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; if (q->reading) goto done; @@ -652,7 +652,7 @@ videobuf_qbuf(struct videobuf_queue *q, retval = 0; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -663,7 +663,7 @@ videobuf_dqbuf(struct videobuf_queue *q, struct videobuf_buffer *buf; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; if (q->reading) goto done; @@ -693,7 +693,7 @@ videobuf_dqbuf(struct videobuf_queue *q, videobuf_status(b,buf,q->type); done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -704,7 +704,7 @@ int videobuf_streamon(struct videobuf_queue *q) unsigned long flags; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; if (q->reading) goto done; @@ -721,7 +721,7 @@ int videobuf_streamon(struct videobuf_queue *q) spin_unlock_irqrestore(q->irqlock,flags); done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -729,7 +729,7 @@ int videobuf_streamoff(struct videobuf_queue *q) { int retval = -EINVAL; - down(&q->lock); + mutex_lock(&q->lock); if (!q->streaming) goto done; videobuf_queue_cancel(q); @@ -737,7 +737,7 @@ int videobuf_streamoff(struct videobuf_queue *q) retval = 0; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -792,7 +792,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, unsigned size, nbufs, bytes; int retval; - down(&q->lock); + mutex_lock(&q->lock); nbufs = 1; size = 0; q->ops->buf_setup(q,&nbufs,&size); @@ -860,7 +860,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -922,7 +922,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, unsigned long flags; dprintk(2,"%s\n",__FUNCTION__); - down(&q->lock); + mutex_lock(&q->lock); retval = -EBUSY; if (q->streaming) goto done; @@ -996,7 +996,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, } done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } @@ -1007,7 +1007,7 @@ unsigned int videobuf_poll_stream(struct file *file, struct videobuf_buffer *buf = NULL; unsigned int rc = 0; - down(&q->lock); + mutex_lock(&q->lock); if (q->streaming) { if (!list_empty(&q->stream)) buf = list_entry(q->stream.next, @@ -1035,7 +1035,7 @@ unsigned int videobuf_poll_stream(struct file *file, buf->state == STATE_ERROR) rc = POLLIN|POLLRDNORM; } - up(&q->lock); + mutex_unlock(&q->lock); return rc; } @@ -1064,7 +1064,7 @@ videobuf_vm_close(struct vm_area_struct *vma) map->count--; if (0 == map->count) { dprintk(1,"munmap %p q=%p\n",map,q); - down(&q->lock); + mutex_lock(&q->lock); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -1076,7 +1076,7 @@ videobuf_vm_close(struct vm_area_struct *vma) q->bufs[i]->baddr = 0; q->ops->buf_release(q,q->bufs[i]); } - up(&q->lock); + mutex_unlock(&q->lock); kfree(map); } return; @@ -1170,7 +1170,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, unsigned int first,last,size,i; int retval; - down(&q->lock); + mutex_lock(&q->lock); retval = -EINVAL; if (!(vma->vm_flags & VM_WRITE)) { dprintk(1,"mmap app bug: PROT_WRITE please\n"); @@ -1238,7 +1238,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, retval = 0; done: - up(&q->lock); + mutex_unlock(&q->lock); return retval; } diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 908fbec776ac..75e3d41382f2 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -224,13 +224,13 @@ int video_exclusive_open(struct inode *inode, struct file *file) struct video_device *vfl = video_devdata(file); int retval = 0; - down(&vfl->lock); + mutex_lock(&vfl->lock); if (vfl->users) { retval = -EBUSY; } else { vfl->users++; } - up(&vfl->lock); + mutex_unlock(&vfl->lock); return retval; } @@ -328,7 +328,7 @@ int video_register_device(struct video_device *vfd, int type, int nr) sprintf(vfd->devfs_name, "v4l/%s%d", name_base, i - base); devfs_mk_cdev(MKDEV(VIDEO_MAJOR, vfd->minor), S_IFCHR | S_IRUSR | S_IWUSR, vfd->devfs_name); - init_MUTEX(&vfd->lock); + mutex_init(&vfd->lock); /* sysfs class */ memset(&vfd->class_dev, 0x00, sizeof(vfd->class_dev)); diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index c8fd8238904d..0229819d0aac 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -245,7 +246,7 @@ struct vino_framebuffer_queue { struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX]; spinlock_t queue_lock; - struct semaphore queue_sem; + struct mutex queue_mutex; wait_queue_head_t frame_wait_queue; }; @@ -283,7 +284,7 @@ struct vino_channel_settings { /* the driver is currently processing the queue */ int capturing; - struct semaphore sem; + struct mutex mutex; spinlock_t capture_lock; unsigned int users; @@ -1131,11 +1132,11 @@ static void vino_queue_free(struct vino_framebuffer_queue *q) if (q->type != VINO_MEMORY_MMAP) return; - down(&q->queue_sem); + mutex_lock(&q->queue_mutex); vino_queue_free_with_count(q, q->length); - up(&q->queue_sem); + mutex_unlock(&q->queue_mutex); } static int vino_queue_init(struct vino_framebuffer_queue *q, @@ -1159,7 +1160,7 @@ static int vino_queue_init(struct vino_framebuffer_queue *q, if (*length < 1) return -EINVAL; - down(&q->queue_sem); + mutex_lock(&q->queue_mutex); if (*length > VINO_FRAMEBUFFER_COUNT_MAX) *length = VINO_FRAMEBUFFER_COUNT_MAX; @@ -1211,7 +1212,7 @@ static int vino_queue_init(struct vino_framebuffer_queue *q, q->magic = VINO_QUEUE_MAGIC; } - up(&q->queue_sem); + mutex_unlock(&q->queue_mutex); return ret; } @@ -4045,7 +4046,7 @@ static int vino_open(struct inode *inode, struct file *file) dprintk("open(): channel = %c\n", (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B'); - down(&vcs->sem); + mutex_lock(&vcs->mutex); if (vcs->users) { dprintk("open(): driver busy\n"); @@ -4062,7 +4063,7 @@ static int vino_open(struct inode *inode, struct file *file) vcs->users++; out: - up(&vcs->sem); + mutex_unlock(&vcs->mutex); dprintk("open(): %s!\n", ret ? "failed" : "complete"); @@ -4075,7 +4076,7 @@ static int vino_close(struct inode *inode, struct file *file) struct vino_channel_settings *vcs = video_get_drvdata(dev); dprintk("close():\n"); - down(&vcs->sem); + mutex_lock(&vcs->mutex); vcs->users--; @@ -4087,7 +4088,7 @@ static int vino_close(struct inode *inode, struct file *file) vino_queue_free(&vcs->fb_queue); } - up(&vcs->sem); + mutex_unlock(&vcs->mutex); return 0; } @@ -4130,7 +4131,7 @@ static int vino_mmap(struct file *file, struct vm_area_struct *vma) // TODO: reject mmap if already mapped - if (down_interruptible(&vcs->sem)) + if (mutex_lock_interruptible(&vcs->mutex)) return -EINTR; if (vcs->reading) { @@ -4214,7 +4215,7 @@ found: vma->vm_ops = &vino_vm_ops; out: - up(&vcs->sem); + mutex_unlock(&vcs->mutex); return ret; } @@ -4374,12 +4375,12 @@ static int vino_ioctl(struct inode *inode, struct file *file, struct vino_channel_settings *vcs = video_get_drvdata(dev); int ret; - if (down_interruptible(&vcs->sem)) + if (mutex_lock_interruptible(&vcs->mutex)) return -EINTR; ret = video_usercopy(inode, file, cmd, arg, vino_do_ioctl); - up(&vcs->sem); + mutex_unlock(&vcs->mutex); return ret; } @@ -4564,10 +4565,10 @@ static int vino_init_channel_settings(struct vino_channel_settings *vcs, vcs->capturing = 0; - init_MUTEX(&vcs->sem); + mutex_init(&vcs->mutex); spin_lock_init(&vcs->capture_lock); - init_MUTEX(&vcs->fb_queue.queue_sem); + mutex_init(&vcs->fb_queue.queue_mutex); spin_lock_init(&vcs->fb_queue.queue_lock); init_waitqueue_head(&vcs->fb_queue.frame_wait_queue); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 965c8902fe60..1dd8efeff35a 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -17,6 +17,7 @@ #include /* need struct timeval */ #include #include +#include #endif #include /* need __user */ @@ -90,7 +91,7 @@ struct video_device /* for videodev.c intenal usage -- please don't touch */ int users; /* video_exclusive_{open|close} ... */ - struct semaphore lock; /* ... helper function uses these */ + struct mutex lock; /* ... helper function uses these */ char devfs_name[64]; /* devfs */ struct class_device class_dev; /* sysfs */ }; diff --git a/include/media/saa7146.h b/include/media/saa7146.h index 2bc634fcb7bb..fee579f10b32 100644 --- a/include/media/saa7146.h +++ b/include/media/saa7146.h @@ -11,6 +11,8 @@ #include /* for i2c subsystem */ #include /* for accessing devices */ #include +#include + #include /* for vmalloc() */ #include /* for vmalloc_to_page() */ @@ -112,7 +114,7 @@ struct saa7146_dev /* different device locks */ spinlock_t slock; - struct semaphore lock; + struct mutex lock; unsigned char __iomem *mem; /* pointer to mapped IO memory */ int revision; /* chip revision; needed for bug-workarounds*/ @@ -133,15 +135,16 @@ struct saa7146_dev void (*vv_callback)(struct saa7146_dev *dev, unsigned long status); /* i2c-stuff */ - struct semaphore i2c_lock; - u32 i2c_bitrate; - struct saa7146_dma d_i2c; /* pointer to i2c memory */ - wait_queue_head_t i2c_wq; - int i2c_op; + struct mutex i2c_lock; + + u32 i2c_bitrate; + struct saa7146_dma d_i2c; /* pointer to i2c memory */ + wait_queue_head_t i2c_wq; + int i2c_op; /* memories */ - struct saa7146_dma d_rps0; - struct saa7146_dma d_rps1; + struct saa7146_dma d_rps0; + struct saa7146_dma d_rps1; }; /* from saa7146_i2c.c */ @@ -150,7 +153,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg *msgs, in /* from saa7146_core.c */ extern struct list_head saa7146_devices; -extern struct semaphore saa7146_devices_lock; +extern struct mutex saa7146_devices_lock; int saa7146_register_extension(struct saa7146_extension*); int saa7146_unregister_extension(struct saa7146_extension*); struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc); diff --git a/include/media/video-buf-dvb.h b/include/media/video-buf-dvb.h index ad0a07a3a895..b78d90fe629f 100644 --- a/include/media/video-buf-dvb.h +++ b/include/media/video-buf-dvb.h @@ -11,7 +11,7 @@ struct videobuf_dvb { struct videobuf_queue dvbq; /* video-buf-dvb state info */ - struct semaphore lock; + struct mutex lock; struct task_struct *thread; int nfeeds; diff --git a/include/media/video-buf.h b/include/media/video-buf.h index 8ecfd78e0027..d90dec5484ee 100644 --- a/include/media/video-buf.h +++ b/include/media/video-buf.h @@ -177,7 +177,7 @@ struct videobuf_queue_ops { }; struct videobuf_queue { - struct semaphore lock; + struct mutex lock; spinlock_t *irqlock; struct pci_dev *pci; -- cgit v1.2.3-59-g8ed1b From 922f77de3e26af512ae12d2a0ddb1e1efdf8d81c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 7 Feb 2006 06:49:15 -0200 Subject: V4L/DVB (3318c): fix saa7146 kobject register failure Whoops. kobject_register failed for hexium HV-PCI6/Orion (-13) [] kobject_register+0x31/0x47 [] bus_add_driver+0x4a/0xfd [] __pci_register_driver+0x82/0xa4 [] hexium_init_module+0xa/0x47 [hexium_orion] [] sys_init_module+0x167b/0x1822 [] do_sync_read+0xb8/0xf3 [] autoremove_wake_function+0x0/0x2d [] audit_syscall_entry+0x118/0x13f [] do_syscall_trace+0x104/0x14a [] syscall_call+0x7/0xb slashes in kobject names aren't allowed. Signed-off-by: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hexium_orion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index 0b6c2096ec66..aad4a18aafd6 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -484,7 +484,7 @@ static struct saa7146_ext_vv vv_data = { }; static struct saa7146_extension extension = { - .name = "hexium HV-PCI6/Orion", + .name = "hexium HV-PCI6 Orion", .flags = 0, // SAA7146_USE_I2C_IRQ, .pci_tbl = &pci_tbl[0], -- cgit v1.2.3-59-g8ed1b From 2d77645a0e8228d3473008ec736e89b7105eafff Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 7 Feb 2006 06:49:15 -0200 Subject: V4L/DVB (3318e): DVB: remove the at76c651/tda80xx frontends The at76c651 and tda80xx frontends are currently completely unused, IOW their only effect is making the kernel larger for people accitentially enabling them. The current in-kernel drivers differ from the drivers at cvs.tuxbox.org, and re-adding them when parts of the dbox2 project get merged should be trivial. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 12 - drivers/media/dvb/frontends/Makefile | 2 - drivers/media/dvb/frontends/at76c651.c | 450 -------------------- drivers/media/dvb/frontends/at76c651.h | 47 --- drivers/media/dvb/frontends/tda80xx.c | 734 --------------------------------- drivers/media/dvb/frontends/tda80xx.h | 51 --- 6 files changed, 1296 deletions(-) delete mode 100644 drivers/media/dvb/frontends/at76c651.c delete mode 100644 drivers/media/dvb/frontends/at76c651.h delete mode 100644 drivers/media/dvb/frontends/tda80xx.c delete mode 100644 drivers/media/dvb/frontends/tda80xx.h (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index f09e3da669fe..76b6a2aef32f 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -28,12 +28,6 @@ config DVB_TDA8083 help A DVB-S tuner module. Say Y when you want to support this frontend. -config DVB_TDA80XX - tristate "Philips TDA8044 or TDA8083 based" - depends on DVB_CORE - help - A DVB-S tuner module. Say Y when you want to support this frontend. - config DVB_MT312 tristate "Zarlink MT312 based" depends on DVB_CORE @@ -139,12 +133,6 @@ config DVB_DIB3000MC comment "DVB-C (cable) frontends" depends on DVB_CORE -config DVB_ATMEL_AT76C651 - tristate "Atmel AT76C651 based" - depends on DVB_CORE - help - A DVB-C tuner module. Say Y when you want to support this frontend. - config DVB_VES1820 tristate "VLSI VES1820 based" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 8f301468568d..1af769cd90c0 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_DVB_CORE) += dvb-pll.o obj-$(CONFIG_DVB_STV0299) += stv0299.o obj-$(CONFIG_DVB_SP8870) += sp8870.o obj-$(CONFIG_DVB_CX22700) += cx22700.o -obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o obj-$(CONFIG_DVB_CX24110) += cx24110.o obj-$(CONFIG_DVB_TDA8083) += tda8083.o obj-$(CONFIG_DVB_L64781) += l64781.o @@ -22,7 +21,6 @@ obj-$(CONFIG_DVB_SP887X) += sp887x.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_MT352) += mt352.o obj-$(CONFIG_DVB_CX22702) += cx22702.o -obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o obj-$(CONFIG_DVB_TDA10021) += tda10021.o obj-$(CONFIG_DVB_STV0297) += stv0297.o obj-$(CONFIG_DVB_NXT200X) += nxt200x.o diff --git a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c deleted file mode 100644 index 8e0f4b3a1417..000000000000 --- a/drivers/media/dvb/frontends/at76c651.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * at76c651.c - * - * Atmel DVB-C Frontend Driver (at76c651/tua6010xs) - * - * Copyright (C) 2001 fnbrd - * & 2002-2004 Andreas Oberritter - * & 2003 Wolfram Joost - * - * 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. - * - * AT76C651 - * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf - * http://www.atmel.com/atmel/acrobat/doc1320.pdf - */ - -#include -#include -#include -#include -#include -#include -#include -#include "dvb_frontend.h" -#include "at76c651.h" - - -struct at76c651_state { - - struct i2c_adapter* i2c; - - struct dvb_frontend_ops ops; - - const struct at76c651_config* config; - - struct dvb_frontend frontend; - - /* revision of the chip */ - u8 revision; - - /* last QAM value set */ - u8 qam; -}; - -static int debug; -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG "at76c651: " args); \ - } while (0) - - -#if ! defined(__powerpc__) -static __inline__ int __ilog2(unsigned long x) -{ - int i; - - if (x == 0) - return -1; - - for (i = 0; x != 0; i++) - x >>= 1; - - return i - 1; -} -#endif - -static int at76c651_writereg(struct at76c651_state* state, u8 reg, u8 data) -{ - int ret; - u8 buf[] = { reg, data }; - struct i2c_msg msg = - { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; - - ret = i2c_transfer(state->i2c, &msg, 1); - - if (ret != 1) - dprintk("%s: writereg error " - "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", - __FUNCTION__, reg, data, ret); - - msleep(10); - - return (ret != 1) ? -EREMOTEIO : 0; -} - -static u8 at76c651_readreg(struct at76c651_state* state, u8 reg) -{ - int ret; - u8 val; - struct i2c_msg msg[] = { - { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 }, - { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = &val, .len = 1 } - }; - - ret = i2c_transfer(state->i2c, msg, 2); - - if (ret != 2) - dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); - - return val; -} - -static int at76c651_reset(struct at76c651_state* state) -{ - return at76c651_writereg(state, 0x07, 0x01); -} - -static void at76c651_disable_interrupts(struct at76c651_state* state) -{ - at76c651_writereg(state, 0x0b, 0x00); -} - -static int at76c651_set_auto_config(struct at76c651_state *state) -{ - /* - * Autoconfig - */ - - at76c651_writereg(state, 0x06, 0x01); - - /* - * Performance optimizations, should be done after autoconfig - */ - - at76c651_writereg(state, 0x10, 0x06); - at76c651_writereg(state, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10); - at76c651_writereg(state, 0x15, 0x28); - at76c651_writereg(state, 0x20, 0x09); - at76c651_writereg(state, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90); - at76c651_writereg(state, 0x30, 0x90); - if (state->qam == 5) - at76c651_writereg(state, 0x35, 0x2A); - - /* - * Initialize A/D-converter - */ - - if (state->revision == 0x11) { - at76c651_writereg(state, 0x2E, 0x38); - at76c651_writereg(state, 0x2F, 0x13); - } - - at76c651_disable_interrupts(state); - - /* - * Restart operation - */ - - at76c651_reset(state); - - return 0; -} - -static void at76c651_set_bbfreq(struct at76c651_state* state) -{ - at76c651_writereg(state, 0x04, 0x3f); - at76c651_writereg(state, 0x05, 0xee); -} - -static int at76c651_set_symbol_rate(struct at76c651_state* state, u32 symbol_rate) -{ - u8 exponent; - u32 mantissa; - - if (symbol_rate > 9360000) - return -EINVAL; - - /* - * FREF = 57800 kHz - * exponent = 10 + floor (log2(symbol_rate / FREF)) - * mantissa = (symbol_rate / FREF) * (1 << (30 - exponent)) - */ - - exponent = __ilog2((symbol_rate << 4) / 903125); - mantissa = ((symbol_rate / 3125) * (1 << (24 - exponent))) / 289; - - at76c651_writereg(state, 0x00, mantissa >> 13); - at76c651_writereg(state, 0x01, mantissa >> 5); - at76c651_writereg(state, 0x02, (mantissa << 3) | exponent); - - return 0; -} - -static int at76c651_set_qam(struct at76c651_state *state, fe_modulation_t qam) -{ - switch (qam) { - case QPSK: - state->qam = 0x02; - break; - case QAM_16: - state->qam = 0x04; - break; - case QAM_32: - state->qam = 0x05; - break; - case QAM_64: - state->qam = 0x06; - break; - case QAM_128: - state->qam = 0x07; - break; - case QAM_256: - state->qam = 0x08; - break; -#if 0 - case QAM_512: - state->qam = 0x09; - break; - case QAM_1024: - state->qam = 0x0A; - break; -#endif - default: - return -EINVAL; - - } - - return at76c651_writereg(state, 0x03, state->qam); -} - -static int at76c651_set_inversion(struct at76c651_state* state, fe_spectral_inversion_t inversion) -{ - u8 feciqinv = at76c651_readreg(state, 0x60); - - switch (inversion) { - case INVERSION_OFF: - feciqinv |= 0x02; - feciqinv &= 0xFE; - break; - - case INVERSION_ON: - feciqinv |= 0x03; - break; - - case INVERSION_AUTO: - feciqinv &= 0xFC; - break; - - default: - return -EINVAL; - } - - return at76c651_writereg(state, 0x60, feciqinv); -} - -static int at76c651_set_parameters(struct dvb_frontend* fe, - struct dvb_frontend_parameters *p) -{ - int ret; - struct at76c651_state* state = fe->demodulator_priv; - - at76c651_writereg(state, 0x0c, 0xc3); - state->config->pll_set(fe, p); - at76c651_writereg(state, 0x0c, 0xc2); - - if ((ret = at76c651_set_symbol_rate(state, p->u.qam.symbol_rate))) - return ret; - - if ((ret = at76c651_set_inversion(state, p->inversion))) - return ret; - - return at76c651_set_auto_config(state); -} - -static int at76c651_set_defaults(struct dvb_frontend* fe) -{ - struct at76c651_state* state = fe->demodulator_priv; - - at76c651_set_symbol_rate(state, 6900000); - at76c651_set_qam(state, QAM_64); - at76c651_set_bbfreq(state); - at76c651_set_auto_config(state); - - if (state->config->pll_init) { - at76c651_writereg(state, 0x0c, 0xc3); - state->config->pll_init(fe); - at76c651_writereg(state, 0x0c, 0xc2); - } - - return 0; -} - -static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status) -{ - struct at76c651_state* state = fe->demodulator_priv; - u8 sync; - - /* - * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0) - */ - sync = at76c651_readreg(state, 0x80); - *status = 0; - - if (sync & (0x04 | 0x10)) /* AGC1 || TIM */ - *status |= FE_HAS_SIGNAL; - if (sync & 0x10) /* TIM */ - *status |= FE_HAS_CARRIER; - if (sync & 0x80) /* FEC */ - *status |= FE_HAS_VITERBI; - if (sync & 0x40) /* CAR */ - *status |= FE_HAS_SYNC; - if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */ - *status |= FE_HAS_LOCK; - - return 0; -} - -static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber) -{ - struct at76c651_state* state = fe->demodulator_priv; - - *ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16; - *ber |= at76c651_readreg(state, 0x82) << 8; - *ber |= at76c651_readreg(state, 0x83); - *ber *= 10; - - return 0; -} - -static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength) -{ - struct at76c651_state* state = fe->demodulator_priv; - - u8 gain = ~at76c651_readreg(state, 0x91); - *strength = (gain << 8) | gain; - - return 0; -} - -static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr) -{ - struct at76c651_state* state = fe->demodulator_priv; - - *snr = 0xFFFF - - ((at76c651_readreg(state, 0x8F) << 8) | - at76c651_readreg(state, 0x90)); - - return 0; -} - -static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) -{ - struct at76c651_state* state = fe->demodulator_priv; - - *ucblocks = at76c651_readreg(state, 0x82); - - return 0; -} - -static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *fesettings) -{ - fesettings->min_delay_ms = 50; - fesettings->step_size = 0; - fesettings->max_drift = 0; - return 0; -} - -static void at76c651_release(struct dvb_frontend* fe) -{ - struct at76c651_state* state = fe->demodulator_priv; - kfree(state); -} - -static struct dvb_frontend_ops at76c651_ops; - -struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, - struct i2c_adapter* i2c) -{ - struct at76c651_state* state = NULL; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL); - if (state == NULL) goto error; - - /* setup the state */ - state->config = config; - state->qam = 0; - - /* check if the demod is there */ - if (at76c651_readreg(state, 0x0e) != 0x65) goto error; - - /* finalise state setup */ - state->i2c = i2c; - state->revision = at76c651_readreg(state, 0x0f) & 0xfe; - memcpy(&state->ops, &at76c651_ops, sizeof(struct dvb_frontend_ops)); - - /* create dvb_frontend */ - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; - return &state->frontend; - -error: - kfree(state); - return NULL; -} - -static struct dvb_frontend_ops at76c651_ops = { - - .info = { - .name = "Atmel AT76C651B DVB-C", - .type = FE_QAM, - .frequency_min = 48250000, - .frequency_max = 863250000, - .frequency_stepsize = 62500, - /*.frequency_tolerance = */ /* FIXME: 12% of SR */ - .symbol_rate_min = 0, /* FIXME */ - .symbol_rate_max = 9360000, /* FIXME */ - .symbol_rate_tolerance = 4000, - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | - FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER - }, - - .release = at76c651_release, - - .init = at76c651_set_defaults, - - .set_frontend = at76c651_set_parameters, - .get_tune_settings = at76c651_get_tune_settings, - - .read_status = at76c651_read_status, - .read_ber = at76c651_read_ber, - .read_signal_strength = at76c651_read_signal_strength, - .read_snr = at76c651_read_snr, - .read_ucblocks = at76c651_read_ucblocks, -}; - -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); - -MODULE_DESCRIPTION("Atmel AT76C651 DVB-C Demodulator Driver"); -MODULE_AUTHOR("Andreas Oberritter "); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(at76c651_attach); diff --git a/drivers/media/dvb/frontends/at76c651.h b/drivers/media/dvb/frontends/at76c651.h deleted file mode 100644 index 34054df93608..000000000000 --- a/drivers/media/dvb/frontends/at76c651.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * at76c651.c - * - * Atmel DVB-C Frontend Driver (at76c651) - * - * Copyright (C) 2001 fnbrd - * & 2002-2004 Andreas Oberritter - * & 2003 Wolfram Joost - * - * 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. - * - * AT76C651 - * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf - * http://www.atmel.com/atmel/acrobat/doc1320.pdf - */ - -#ifndef AT76C651_H -#define AT76C651_H - -#include - -struct at76c651_config -{ - /* the demodulator's i2c address */ - u8 demod_address; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); -}; - -extern struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, - struct i2c_adapter* i2c); - -#endif // AT76C651_H diff --git a/drivers/media/dvb/frontends/tda80xx.c b/drivers/media/dvb/frontends/tda80xx.c deleted file mode 100644 index d1cabb6a0a13..000000000000 --- a/drivers/media/dvb/frontends/tda80xx.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - * tda80xx.c - * - * Philips TDA8044 / TDA8083 QPSK demodulator driver - * - * Copyright (C) 2001 Felix Domke - * Copyright (C) 2002-2004 Andreas Oberritter - * - * 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 -#include -#include - -#include "dvb_frontend.h" -#include "tda80xx.h" - -enum { - ID_TDA8044 = 0x04, - ID_TDA8083 = 0x05, -}; - - -struct tda80xx_state { - - struct i2c_adapter* i2c; - - struct dvb_frontend_ops ops; - - /* configuration settings */ - const struct tda80xx_config* config; - - struct dvb_frontend frontend; - - u32 clk; - int afc_loop; - struct work_struct worklet; - fe_code_rate_t code_rate; - fe_spectral_inversion_t spectral_inversion; - fe_status_t status; - u8 id; -}; - -static int debug = 1; -#define dprintk if (debug) printk - -static u8 tda8044_inittab_pre[] = { - 0x02, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea, - 0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x58, - 0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68, - 0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x00, - 0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - -static u8 tda8044_inittab_post[] = { - 0x04, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea, - 0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x50, - 0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68, - 0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x6c, - 0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - -static u8 tda8083_inittab[] = { - 0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea, - 0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10, - 0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8, - 0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00, - 0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 -}; - -static __inline__ u32 tda80xx_div(u32 a, u32 b) -{ - return (a + (b / 2)) / b; -} - -static __inline__ u32 tda80xx_gcd(u32 a, u32 b) -{ - u32 r; - - while ((r = a % b)) { - a = b; - b = r; - } - - return b; -} - -static int tda80xx_read(struct tda80xx_state* state, u8 reg, u8 *buf, u8 len) -{ - int ret; - struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 }, - { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } }; - - ret = i2c_transfer(state->i2c, msg, 2); - - if (ret != 2) - dprintk("%s: readreg error (reg %02x, ret == %i)\n", - __FUNCTION__, reg, ret); - - mdelay(10); - - return (ret == 2) ? 0 : -EREMOTEIO; -} - -static int tda80xx_write(struct tda80xx_state* state, u8 reg, const u8 *buf, u8 len) -{ - int ret; - u8 wbuf[len + 1]; - struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = wbuf, .len = len + 1 }; - - wbuf[0] = reg; - memcpy(&wbuf[1], buf, len); - - ret = i2c_transfer(state->i2c, &msg, 1); - - if (ret != 1) - dprintk("%s: i2c xfer error (ret == %i)\n", __FUNCTION__, ret); - - mdelay(10); - - return (ret == 1) ? 0 : -EREMOTEIO; -} - -static __inline__ u8 tda80xx_readreg(struct tda80xx_state* state, u8 reg) -{ - u8 val; - - tda80xx_read(state, reg, &val, 1); - - return val; -} - -static __inline__ int tda80xx_writereg(struct tda80xx_state* state, u8 reg, u8 data) -{ - return tda80xx_write(state, reg, &data, 1); -} - -static int tda80xx_set_parameters(struct tda80xx_state* state, - fe_spectral_inversion_t inversion, - u32 symbol_rate, - fe_code_rate_t fec_inner) -{ - u8 buf[15]; - u64 ratio; - u32 clk; - u32 k; - u32 sr = symbol_rate; - u32 gcd; - u8 scd; - - if (symbol_rate > (state->clk * 3) / 16) - scd = 0; - else if (symbol_rate > (state->clk * 3) / 32) - scd = 1; - else if (symbol_rate > (state->clk * 3) / 64) - scd = 2; - else - scd = 3; - - clk = scd ? (state->clk / (scd * 2)) : state->clk; - - /* - * Viterbi decoder: - * Differential decoding off - * Spectral inversion unknown - * QPSK modulation - */ - if (inversion == INVERSION_ON) - buf[0] = 0x60; - else if (inversion == INVERSION_OFF) - buf[0] = 0x20; - else - buf[0] = 0x00; - - /* - * CLK ratio: - * system clock frequency is up to 64 or 96 MHz - * - * formula: - * r = k * clk / symbol_rate - * - * k: 2^21 for caa 0..3, - * 2^20 for caa 4..5, - * 2^19 for caa 6..7 - */ - if (symbol_rate <= (clk * 3) / 32) - k = (1 << 19); - else if (symbol_rate <= (clk * 3) / 16) - k = (1 << 20); - else - k = (1 << 21); - - gcd = tda80xx_gcd(clk, sr); - clk /= gcd; - sr /= gcd; - - gcd = tda80xx_gcd(k, sr); - k /= gcd; - sr /= gcd; - - ratio = (u64)k * (u64)clk; - do_div(ratio, sr); - - buf[1] = ratio >> 16; - buf[2] = ratio >> 8; - buf[3] = ratio; - - /* nyquist filter roll-off factor 35% */ - buf[4] = 0x20; - - clk = scd ? (state->clk / (scd * 2)) : state->clk; - - /* Anti Alias Filter */ - if (symbol_rate < (clk * 3) / 64) - printk("tda80xx: unsupported symbol rate: %u\n", symbol_rate); - else if (symbol_rate <= clk / 16) - buf[4] |= 0x07; - else if (symbol_rate <= (clk * 3) / 32) - buf[4] |= 0x06; - else if (symbol_rate <= clk / 8) - buf[4] |= 0x05; - else if (symbol_rate <= (clk * 3) / 16) - buf[4] |= 0x04; - else if (symbol_rate <= clk / 4) - buf[4] |= 0x03; - else if (symbol_rate <= (clk * 3) / 8) - buf[4] |= 0x02; - else if (symbol_rate <= clk / 2) - buf[4] |= 0x01; - else - buf[4] |= 0x00; - - /* Sigma Delta converter */ - buf[5] = 0x00; - - /* FEC: Possible puncturing rates */ - if (fec_inner == FEC_NONE) - buf[6] = 0x00; - else if ((fec_inner >= FEC_1_2) && (fec_inner <= FEC_8_9)) - buf[6] = (1 << (8 - fec_inner)); - else if (fec_inner == FEC_AUTO) - buf[6] = 0xff; - else - return -EINVAL; - - /* carrier lock detector threshold value */ - buf[7] = 0x30; - /* AFC1: proportional part settings */ - buf[8] = 0x42; - /* AFC1: integral part settings */ - buf[9] = 0x98; - /* PD: Leaky integrator SCPC mode */ - buf[10] = 0x28; - /* AFC2, AFC1 controls */ - buf[11] = 0x30; - /* PD: proportional part settings */ - buf[12] = 0x42; - /* PD: integral part settings */ - buf[13] = 0x99; - /* AGC */ - buf[14] = 0x50 | scd; - - printk("symbol_rate=%u clk=%u\n", symbol_rate, clk); - - return tda80xx_write(state, 0x01, buf, sizeof(buf)); -} - -static int tda80xx_set_clk(struct tda80xx_state* state) -{ - u8 buf[2]; - - /* CLK proportional part */ - buf[0] = (0x06 << 5) | 0x08; /* CMP[2:0], CSP[4:0] */ - /* CLK integral part */ - buf[1] = (0x04 << 5) | 0x1a; /* CMI[2:0], CSI[4:0] */ - - return tda80xx_write(state, 0x17, buf, sizeof(buf)); -} - -#if 0 -static int tda80xx_set_scpc_freq_offset(struct tda80xx_state* state) -{ - /* a constant value is nonsense here imho */ - return tda80xx_writereg(state, 0x22, 0xf9); -} -#endif - -static int tda80xx_close_loop(struct tda80xx_state* state) -{ - u8 buf[2]; - - /* PD: Loop closed, LD: lock detect enable, SCPC: Sweep mode - AFC1 loop closed */ - buf[0] = 0x68; - /* AFC1: Loop closed, CAR Feedback: 8192 */ - buf[1] = 0x70; - - return tda80xx_write(state, 0x0b, buf, sizeof(buf)); -} - -static irqreturn_t tda80xx_irq(int irq, void *priv, struct pt_regs *pt) -{ - schedule_work(priv); - - return IRQ_HANDLED; -} - -static void tda80xx_read_status_int(struct tda80xx_state* state) -{ - u8 val; - - static const fe_spectral_inversion_t inv_tab[] = { - INVERSION_OFF, INVERSION_ON - }; - - static const fe_code_rate_t fec_tab[] = { - FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4, - FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8, - }; - - val = tda80xx_readreg(state, 0x02); - - state->status = 0; - - if (val & 0x01) /* demodulator lock */ - state->status |= FE_HAS_SIGNAL; - if (val & 0x02) /* clock recovery lock */ - state->status |= FE_HAS_CARRIER; - if (val & 0x04) /* viterbi lock */ - state->status |= FE_HAS_VITERBI; - if (val & 0x08) /* deinterleaver lock (packet sync) */ - state->status |= FE_HAS_SYNC; - if (val & 0x10) /* derandomizer lock (frame sync) */ - state->status |= FE_HAS_LOCK; - if (val & 0x20) /* frontend can not lock */ - state->status |= FE_TIMEDOUT; - - if ((state->status & (FE_HAS_CARRIER)) && (state->afc_loop)) { - printk("tda80xx: closing loop\n"); - tda80xx_close_loop(state); - state->afc_loop = 0; - } - - if (state->status & (FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK)) { - val = tda80xx_readreg(state, 0x0e); - state->code_rate = fec_tab[val & 0x07]; - if (state->status & (FE_HAS_SYNC | FE_HAS_LOCK)) - state->spectral_inversion = inv_tab[(val >> 7) & 0x01]; - else - state->spectral_inversion = INVERSION_AUTO; - } - else { - state->code_rate = FEC_AUTO; - } -} - -static void tda80xx_worklet(void *priv) -{ - struct tda80xx_state *state = priv; - - tda80xx_writereg(state, 0x00, 0x04); - enable_irq(state->config->irq); - - tda80xx_read_status_int(state); -} - -static void tda80xx_wait_diseqc_fifo(struct tda80xx_state* state) -{ - size_t i; - - for (i = 0; i < 100; i++) { - if (tda80xx_readreg(state, 0x02) & 0x80) - break; - msleep(10); - } -} - -static int tda8044_init(struct dvb_frontend* fe) -{ - struct tda80xx_state* state = fe->demodulator_priv; - int ret; - - /* - * this function is a mess... - */ - - if ((ret = tda80xx_write(state, 0x00, tda8044_inittab_pre, sizeof(tda8044_inittab_pre)))) - return ret; - - tda80xx_writereg(state, 0x0f, 0x50); -#if 1 - tda80xx_writereg(state, 0x20, 0x8F); /* FIXME */ - tda80xx_writereg(state, 0x20, state->config->volt18setting); /* FIXME */ - //tda80xx_writereg(state, 0x00, 0x04); - tda80xx_writereg(state, 0x00, 0x0C); -#endif - //tda80xx_writereg(state, 0x00, 0x08); /* Reset AFC1 loop filter */ - - tda80xx_write(state, 0x00, tda8044_inittab_post, sizeof(tda8044_inittab_post)); - - if (state->config->pll_init) { - tda80xx_writereg(state, 0x1c, 0x80); - state->config->pll_init(fe); - tda80xx_writereg(state, 0x1c, 0x00); - } - - return 0; -} - -static int tda8083_init(struct dvb_frontend* fe) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - tda80xx_write(state, 0x00, tda8083_inittab, sizeof(tda8083_inittab)); - - if (state->config->pll_init) { - tda80xx_writereg(state, 0x1c, 0x80); - state->config->pll_init(fe); - tda80xx_writereg(state, 0x1c, 0x00); - } - - return 0; -} - -static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - switch (voltage) { - case SEC_VOLTAGE_13: - return tda80xx_writereg(state, 0x20, state->config->volt13setting); - case SEC_VOLTAGE_18: - return tda80xx_writereg(state, 0x20, state->config->volt18setting); - case SEC_VOLTAGE_OFF: - return tda80xx_writereg(state, 0x20, 0); - default: - return -EINVAL; - } -} - -static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - switch (tone) { - case SEC_TONE_OFF: - return tda80xx_writereg(state, 0x29, 0x00); - case SEC_TONE_ON: - return tda80xx_writereg(state, 0x29, 0x80); - default: - return -EINVAL; - } -} - -static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - if (cmd->msg_len > 6) - return -EINVAL; - - tda80xx_writereg(state, 0x29, 0x08 | (cmd->msg_len - 3)); - tda80xx_write(state, 0x23, cmd->msg, cmd->msg_len); - tda80xx_writereg(state, 0x29, 0x0c | (cmd->msg_len - 3)); - tda80xx_wait_diseqc_fifo(state); - - return 0; -} - -static int tda80xx_send_diseqc_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t cmd) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - switch (cmd) { - case SEC_MINI_A: - tda80xx_writereg(state, 0x29, 0x14); - break; - case SEC_MINI_B: - tda80xx_writereg(state, 0x29, 0x1c); - break; - default: - return -EINVAL; - } - - tda80xx_wait_diseqc_fifo(state); - - return 0; -} - -static int tda80xx_sleep(struct dvb_frontend* fe) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - tda80xx_writereg(state, 0x00, 0x02); /* enter standby */ - - return 0; -} - -static int tda80xx_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - tda80xx_writereg(state, 0x1c, 0x80); - state->config->pll_set(fe, p); - tda80xx_writereg(state, 0x1c, 0x00); - - tda80xx_set_parameters(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner); - tda80xx_set_clk(state); - //tda80xx_set_scpc_freq_offset(state); - state->afc_loop = 1; - - return 0; -} - -static int tda80xx_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - if (!state->config->irq) - tda80xx_read_status_int(state); - - p->inversion = state->spectral_inversion; - p->u.qpsk.fec_inner = state->code_rate; - - return 0; -} - -static int tda80xx_read_status(struct dvb_frontend* fe, fe_status_t* status) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - if (!state->config->irq) - tda80xx_read_status_int(state); - *status = state->status; - - return 0; -} - -static int tda80xx_read_ber(struct dvb_frontend* fe, u32* ber) -{ - struct tda80xx_state* state = fe->demodulator_priv; - int ret; - u8 buf[3]; - - if ((ret = tda80xx_read(state, 0x0b, buf, sizeof(buf)))) - return ret; - - *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2]; - - return 0; -} - -static int tda80xx_read_signal_strength(struct dvb_frontend* fe, u16* strength) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - u8 gain = ~tda80xx_readreg(state, 0x01); - *strength = (gain << 8) | gain; - - return 0; -} - -static int tda80xx_read_snr(struct dvb_frontend* fe, u16* snr) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - u8 quality = tda80xx_readreg(state, 0x08); - *snr = (quality << 8) | quality; - - return 0; -} - -static int tda80xx_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - *ucblocks = tda80xx_readreg(state, 0x0f); - if (*ucblocks == 0xff) - *ucblocks = 0xffffffff; - - return 0; -} - -static int tda80xx_init(struct dvb_frontend* fe) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - switch(state->id) { - case ID_TDA8044: - return tda8044_init(fe); - - case ID_TDA8083: - return tda8083_init(fe); - } - return 0; -} - -static void tda80xx_release(struct dvb_frontend* fe) -{ - struct tda80xx_state* state = fe->demodulator_priv; - - if (state->config->irq) - free_irq(state->config->irq, &state->worklet); - - kfree(state); -} - -static struct dvb_frontend_ops tda80xx_ops; - -struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config, - struct i2c_adapter* i2c) -{ - struct tda80xx_state* state = NULL; - int ret; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL); - if (state == NULL) goto error; - - /* setup the state */ - state->config = config; - state->i2c = i2c; - memcpy(&state->ops, &tda80xx_ops, sizeof(struct dvb_frontend_ops)); - state->spectral_inversion = INVERSION_AUTO; - state->code_rate = FEC_AUTO; - state->status = 0; - state->afc_loop = 0; - - /* check if the demod is there */ - if (tda80xx_writereg(state, 0x89, 0x00) < 0) goto error; - state->id = tda80xx_readreg(state, 0x00); - - switch (state->id) { - case ID_TDA8044: - state->clk = 96000000; - printk("tda80xx: Detected tda8044\n"); - break; - - case ID_TDA8083: - state->clk = 64000000; - printk("tda80xx: Detected tda8083\n"); - break; - - default: - goto error; - } - - /* setup IRQ */ - if (state->config->irq) { - INIT_WORK(&state->worklet, tda80xx_worklet, state); - if ((ret = request_irq(state->config->irq, tda80xx_irq, SA_ONESHOT, "tda80xx", &state->worklet)) < 0) { - printk(KERN_ERR "tda80xx: request_irq failed (%d)\n", ret); - goto error; - } - } - - /* create dvb_frontend */ - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; - return &state->frontend; - -error: - kfree(state); - return NULL; -} - -static struct dvb_frontend_ops tda80xx_ops = { - - .info = { - .name = "Philips TDA80xx DVB-S", - .type = FE_QPSK, - .frequency_min = 500000, - .frequency_max = 2700000, - .frequency_stepsize = 125, - .symbol_rate_min = 4500000, - .symbol_rate_max = 45000000, - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | - FE_CAN_MUTE_TS - }, - - .release = tda80xx_release, - - .init = tda80xx_init, - .sleep = tda80xx_sleep, - - .set_frontend = tda80xx_set_frontend, - .get_frontend = tda80xx_get_frontend, - - .read_status = tda80xx_read_status, - .read_ber = tda80xx_read_ber, - .read_signal_strength = tda80xx_read_signal_strength, - .read_snr = tda80xx_read_snr, - .read_ucblocks = tda80xx_read_ucblocks, - - .diseqc_send_master_cmd = tda80xx_send_diseqc_msg, - .diseqc_send_burst = tda80xx_send_diseqc_burst, - .set_tone = tda80xx_set_tone, - .set_voltage = tda80xx_set_voltage, -}; - -module_param(debug, int, 0644); - -MODULE_DESCRIPTION("Philips TDA8044 / TDA8083 DVB-S Demodulator driver"); -MODULE_AUTHOR("Felix Domke, Andreas Oberritter"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(tda80xx_attach); diff --git a/drivers/media/dvb/frontends/tda80xx.h b/drivers/media/dvb/frontends/tda80xx.h deleted file mode 100644 index cd639a0aad55..000000000000 --- a/drivers/media/dvb/frontends/tda80xx.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * tda80xx.c - * - * Philips TDA8044 / TDA8083 QPSK demodulator driver - * - * Copyright (C) 2001 Felix Domke - * Copyright (C) 2002-2004 Andreas Oberritter - * - * 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. - */ - -#ifndef TDA80XX_H -#define TDA80XX_H - -#include - -struct tda80xx_config -{ - /* the demodulator's i2c address */ - u8 demod_address; - - /* IRQ to use (0=>no IRQ used) */ - u32 irq; - - /* Register setting to use for 13v */ - u8 volt13setting; - - /* Register setting to use for 18v */ - u8 volt18setting; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); -}; - -extern struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config, - struct i2c_adapter* i2c); - -#endif // TDA80XX_H -- cgit v1.2.3-59-g8ed1b From df821f758c37dce41fbef0d20932909332619f04 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 6 Feb 2006 23:52:24 +0200 Subject: V4L/DVB (3324): Fix Samsung tuner frequency ranges Forgot to take the NTSC frequency offset into account. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 9786e590624a..a90bc04cf807 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -970,8 +970,8 @@ static struct tuner_params tuner_tnf_5335mf_params[] = { /* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */ static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = { - { 16 * 175.75 /*MHz*/, 0xce, 0x01, }, - { 16 * 410.25 /*MHz*/, 0xce, 0x02, }, + { 16 * 130.00 /*MHz*/, 0xce, 0x01, }, + { 16 * 364.50 /*MHz*/, 0xce, 0x02, }, { 16 * 999.99 , 0xce, 0x08, }, }; -- cgit v1.2.3-59-g8ed1b From f1e5ee45b4a0216ac4f0a9c41e488032391e8575 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 7 Feb 2006 04:01:19 +0100 Subject: V4L/DVB (3325): Disabled debug on by default in tvp5150 disabled debug on by default in tvp5150 Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp5150.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 3ae8a9ff5b13..69d0fe159f4d 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -1182,7 +1182,7 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter, return rv; } -// if (debug > 1) + if (debug > 1) dump_reg(c); return 0; } -- cgit v1.2.3-59-g8ed1b From 282b7cb3e03d9ada4067083e61919d74197a1e5a Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 7 Feb 2006 06:14:16 +0100 Subject: V4L/DVB (3326): Adding support for Terratec Prodigy XS Adding support for Terratec Prodigy XS Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 26 ++++++++++++++++++++++++++ drivers/media/video/em28xx/em28xx.h | 1 + 2 files changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index a9e7cec17a6b..703927e8da13 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -198,6 +198,30 @@ struct em28xx_board em28xx_boards[] = { .amux = 1, }}, }, + /* maybe there's a reason behind it why Terratec sells the Hybrid XS as Prodigy XS with a + * different PID, let's keep it separated for now maybe we'll need it lateron */ + [EM2880_BOARD_TERRATEC_PRODIGY_XS] = { + .name = "Terratec Prodigy XS", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .tuner_type = TUNER_XCEIVE_XC3028, + .decoder = EM28XX_TVP5150, + .input = {{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 0, + .amux = 0, + },{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 2, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, [EM2820_BOARD_MSI_VOX_USB_2] = { .name = "MSI VOX USB 2.0", .vchannels = 3, @@ -318,6 +342,7 @@ struct usb_device_id em28xx_id_table [] = { { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, + { USB_DEVICE(0x0ccd, 0x0047), .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, { }, }; @@ -325,6 +350,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) { /* request some modules */ switch(dev->model){ + case EM2880_BOARD_TERRATEC_PRODIGY_XS: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2880_BOARD_TERRATEC_HYBRID_XS: { diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 4e2fe62b7350..e1ddc2f27a21 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -45,6 +45,7 @@ #define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10 #define EM2880_BOARD_TERRATEC_HYBRID_XS 11 #define EM2820_BOARD_KWORLD_PVRTV2800RF 12 +#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13 #define UNSET -1 -- cgit v1.2.3-59-g8ed1b From dde44589bf9fac0168c6ce6d097c99c33b18074f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Feb 2006 00:56:10 +0900 Subject: [PATCH] libata: implement ATA_FLAG_IN_EH port flag ATA_FLAG_IN_EH flag is set on entry to EH and cleared on completion. This patch just sets and clears the flag. Following patches will build normal qc execution / EH synchronization aroung this flag. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 9 +++++++++ include/linux/libata.h | 2 ++ 2 files changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 2d328b3af067..3a4f40b251fb 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -735,6 +735,11 @@ int ata_scsi_error(struct Scsi_Host *host) DPRINTK("ENTER\n"); + spin_lock_irqsave(&ap->host_set->lock, flags); + assert(!(ap->flags & ATA_FLAG_IN_EH)); + ap->flags |= ATA_FLAG_IN_EH; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + ap = (struct ata_port *) &host->hostdata[0]; ap->ops->eng_timeout(ap); @@ -742,6 +747,10 @@ 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 474cdfa35d1e..55176df403a5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -162,6 +162,8 @@ enum { 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_IN_EH = (1 << 15), /* 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? */ ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ -- cgit v1.2.3-59-g8ed1b From c18d06f89fd09ee0059c4899e615c471d59af66a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Feb 2006 00:56:10 +0900 Subject: [PATCH] libata: EH / pio tasks synchronization This patch makes sure that pio tasks are flushed before proceeding with EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 56 +++++++++++++++++++++++++++++++++++++++++++--- include/linux/libata.h | 3 ++- 2 files changed, 55 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 249e67fab81f..9a785cf0c5b1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1074,19 +1074,66 @@ static unsigned int ata_pio_modes(const struct ata_device *adev) static inline void ata_queue_packet_task(struct ata_port *ap) { - queue_work(ata_wq, &ap->packet_task); + if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) + queue_work(ata_wq, &ap->packet_task); } static inline void ata_queue_pio_task(struct ata_port *ap) { - queue_work(ata_wq, &ap->pio_task); + if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) + queue_work(ata_wq, &ap->pio_task); } static inline void ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay) { - queue_delayed_work(ata_wq, &ap->pio_task, delay); + if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) + queue_delayed_work(ata_wq, &ap->pio_task, delay); +} + +/** + * ata_flush_pio_tasks - Flush pio_task and packet_task + * @ap: the target ata_port + * + * After this function completes, pio_task and packet_task are + * guranteed not to be running or scheduled. + * + * LOCKING: + * Kernel thread context (may sleep) + */ + +static void ata_flush_pio_tasks(struct ata_port *ap) +{ + int tmp = 0; + unsigned long flags; + + DPRINTK("ENTER\n"); + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags |= ATA_FLAG_FLUSH_PIO_TASK; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("flush #1\n"); + flush_workqueue(ata_wq); + + /* + * At this point, if a task is running, it's guaranteed to see + * the FLUSH flag; thus, it will never queue pio tasks again. + * 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); + } + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("EXIT\n"); } void ata_qc_complete_internal(struct ata_queued_cmd *qc) @@ -3767,6 +3814,9 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) DPRINTK("ENTER\n"); + ata_flush_pio_tasks(ap); + ap->hsm_task_state = HSM_ST_IDLE; + spin_lock_irqsave(&host_set->lock, flags); switch (qc->tf.protocol) { diff --git a/include/linux/libata.h b/include/linux/libata.h index 55176df403a5..f4cd1eb734a0 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -162,7 +162,8 @@ enum { 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_IN_EH = (1 << 15), /* EH in progress */ + ATA_FLAG_FLUSH_PIO_TASK = (1 << 15), /* Flush PIO 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-59-g8ed1b From b911fc3ae0121ff0b72a52e58823c3f8ac3094d0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Feb 2006 18:20:00 +0900 Subject: [PATCH] libata: fix ata_std_probe_reset() SATA detection ap->cbl is initialized during postreset and thus unknown on entry to ata_std_probe_reset(). This patch makes ata_std_probe_reset() use ATA_FLAG_SATA flag instead of ap->cbl to detect SATA port. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9a785cf0c5b1..d4fb0f754c91 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2472,7 +2472,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 (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) hardreset = sata_std_hardreset; return ata_drive_probe_reset(ap, ata_std_softreset, hardreset, -- cgit v1.2.3-59-g8ed1b From 7a7921e8661a6b9fb99400983ee67df7e125853b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Feb 2006 18:20:00 +0900 Subject: [PATCH] libata: separate out sata_phy_resume() from sata_std_hardreset() This patch separates out sata_phy_resume() from sata_std_hardreset(). The function will later be used by probeinit callback. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d4fb0f754c91..99f4bf6022ee 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2277,6 +2277,24 @@ err_out: DPRINTK("EXIT\n"); } +static int sata_phy_resume(struct ata_port *ap) +{ + unsigned long timeout = jiffies + (HZ * 5); + u32 sstatus; + + scr_write_flush(ap, SCR_CONTROL, 0x300); + + /* Wait for phy to become ready, if necessary. */ + do { + msleep(200); + sstatus = scr_read(ap, SCR_STATUS); + if ((sstatus & 0xf) != 1) + return 0; + } while (time_before(jiffies, timeout)); + + return -1; +} + /** * ata_std_softreset - reset host port via ATA SRST * @ap: port to reset @@ -2357,8 +2375,7 @@ 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 sstatus, serror; - unsigned long timeout = jiffies + (HZ * 5); + u32 serror; DPRINTK("ENTER\n"); @@ -2371,15 +2388,8 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) */ msleep(1); - scr_write_flush(ap, SCR_CONTROL, 0x300); - - /* Wait for phy to become ready, if necessary. */ - do { - msleep(200); - sstatus = scr_read(ap, SCR_STATUS); - if ((sstatus & 0xf) != 1) - break; - } while (time_before(jiffies, timeout)); + /* Bring phy back */ + sata_phy_resume(ap); /* Clear SError */ serror = scr_read(ap, SCR_ERROR); -- cgit v1.2.3-59-g8ed1b From 5140788f77d71b4f05fde217adbfb0c92f28f20c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 9 Feb 2006 01:56:05 -0500 Subject: [libata scsi] build fix for ATA_FLAG_IN_EH change --- drivers/scsi/libata-scsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 3a4f40b251fb..b007bb409382 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -732,15 +732,17 @@ int ata_scsi_slave_config(struct scsi_device *sdev) int ata_scsi_error(struct Scsi_Host *host) { struct ata_port *ap; + unsigned long flags; DPRINTK("ENTER\n"); + ap = (struct ata_port *) &host->hostdata[0]; + spin_lock_irqsave(&ap->host_set->lock, flags); assert(!(ap->flags & ATA_FLAG_IN_EH)); ap->flags |= ATA_FLAG_IN_EH; spin_unlock_irqrestore(&ap->host_set->lock, flags); - ap = (struct ata_port *) &host->hostdata[0]; ap->ops->eng_timeout(ap); assert(host->host_failed == 0 && list_empty(&host->eh_cmd_q)); -- cgit v1.2.3-59-g8ed1b From 7944ea9522ce0ea32d57894b3dc2540b0bdca66e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Feb 2006 18:20:00 +0900 Subject: [PATCH] libata: add probeinit component operation to ata_drive_probe_reset() This patch adds probeinit component operation to ata_drive_probe_reset(). If present, this new operation is called before performing any reset. The operations's roll is to prepare @ap for following probe-reset operations. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 9 +++++++-- include/linux/libata.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 99f4bf6022ee..c36c5a9a4617 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2485,7 +2485,8 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) hardreset = sata_std_hardreset; - return ata_drive_probe_reset(ap, ata_std_softreset, hardreset, + return ata_drive_probe_reset(ap, NULL, + ata_std_softreset, hardreset, ata_std_postreset, classes); } @@ -2524,6 +2525,7 @@ static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset, /** * 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) @@ -2552,12 +2554,15 @@ static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset, * if classification fails, and any error code from reset * methods. */ -int ata_drive_probe_reset(struct ata_port *ap, +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; + if (probeinit) + probeinit(ap); + if (softreset) { rc = do_probe_reset(ap, softreset, postreset, classes); if (rc == 0) diff --git a/include/linux/libata.h b/include/linux/libata.h index f4cd1eb734a0..e8f29cefc351 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -244,6 +244,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 void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *); @@ -484,6 +485,7 @@ 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_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 int ata_std_softreset(struct ata_port *ap, int verbose, -- cgit v1.2.3-59-g8ed1b From 8a19ac89edbe9b702c10fd2039b8cb2db4644a5f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Feb 2006 18:20:00 +0900 Subject: [PATCH] libata: implement ata_std_probeinit() This patch implements the off-the-shelf probeinit component operation. Currently, all it does is waking up the PHY if it's a SATA port. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 16 +++++++++++++++- include/linux/libata.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c36c5a9a4617..14cdbb336dd5 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2295,6 +2295,19 @@ static int sata_phy_resume(struct ata_port *ap) return -1; } +/** + * 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(). + */ +extern void ata_std_probeinit(struct ata_port *ap) +{ + if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) + sata_phy_resume(ap); +} + /** * ata_std_softreset - reset host port via ATA SRST * @ap: port to reset @@ -2485,7 +2498,7 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) hardreset = sata_std_hardreset; - return ata_drive_probe_reset(ap, NULL, + return ata_drive_probe_reset(ap, ata_std_probeinit, ata_std_softreset, hardreset, ata_std_postreset, classes); } @@ -5535,6 +5548,7 @@ EXPORT_SYMBOL_GPL(ata_port_probe); 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_softreset); EXPORT_SYMBOL_GPL(sata_std_hardreset); EXPORT_SYMBOL_GPL(ata_std_postreset); diff --git a/include/linux/libata.h b/include/linux/libata.h index e8f29cefc351..68b3fe6f9a4d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -488,6 +488,7 @@ 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_softreset(struct ata_port *ap, int verbose, unsigned int *classes); extern int sata_std_hardreset(struct ata_port *ap, int verbose, -- cgit v1.2.3-59-g8ed1b From 1fdffbce0332b3e00993d741e76935e7f4f0d40f Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 9 Feb 2006 05:15:27 -0500 Subject: [libata] Move PCI IDE BMDMA-related code to new file libata-bmdma.c. --- drivers/scsi/Makefile | 2 +- drivers/scsi/libata-bmdma.c | 703 ++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata-core.c | 693 ++----------------------------------------- 3 files changed, 724 insertions(+), 674 deletions(-) create mode 100644 drivers/scsi/libata-bmdma.c (limited to 'drivers') diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 320e765fa0cd..15dc2e00e1b2 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -163,7 +163,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-objs := libata-core.o libata-scsi.o libata-bmdma.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-bmdma.c b/drivers/scsi/libata-bmdma.c new file mode 100644 index 000000000000..a93336adcd23 --- /dev/null +++ b/drivers/scsi/libata-bmdma.c @@ -0,0 +1,703 @@ +/* + * libata-bmdma.c - helper library for PCI IDE BMDMA + * + * Maintained by: Jeff Garzik + * Please ALWAYS copy linux-ide@vger.kernel.org + * on emails. + * + * Copyright 2003-2006 Red Hat, Inc. All rights reserved. + * Copyright 2003-2006 Jeff Garzik + * + * + * 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 "libata.h" + +/** + * ata_tf_load_pio - send taskfile registers to host controller + * @ap: Port to which output is sent + * @tf: ATA taskfile register set + * + * Outputs ATA taskfile to standard ATA host controller. + * + * LOCKING: + * Inherited from caller. + */ + +static void ata_tf_load_pio(struct ata_port *ap, const struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; + + if (tf->ctl != ap->last_ctl) { + outb(tf->ctl, ioaddr->ctl_addr); + ap->last_ctl = tf->ctl; + ata_wait_idle(ap); + } + + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { + outb(tf->hob_feature, ioaddr->feature_addr); + outb(tf->hob_nsect, ioaddr->nsect_addr); + outb(tf->hob_lbal, ioaddr->lbal_addr); + outb(tf->hob_lbam, ioaddr->lbam_addr); + outb(tf->hob_lbah, ioaddr->lbah_addr); + VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", + tf->hob_feature, + tf->hob_nsect, + tf->hob_lbal, + tf->hob_lbam, + tf->hob_lbah); + } + + if (is_addr) { + outb(tf->feature, ioaddr->feature_addr); + outb(tf->nsect, ioaddr->nsect_addr); + outb(tf->lbal, ioaddr->lbal_addr); + outb(tf->lbam, ioaddr->lbam_addr); + outb(tf->lbah, ioaddr->lbah_addr); + VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", + tf->feature, + tf->nsect, + tf->lbal, + tf->lbam, + tf->lbah); + } + + if (tf->flags & ATA_TFLAG_DEVICE) { + outb(tf->device, ioaddr->device_addr); + VPRINTK("device 0x%X\n", tf->device); + } + + ata_wait_idle(ap); +} + +/** + * ata_tf_load_mmio - send taskfile registers to host controller + * @ap: Port to which output is sent + * @tf: ATA taskfile register set + * + * Outputs ATA taskfile to standard ATA host controller using MMIO. + * + * LOCKING: + * Inherited from caller. + */ + +static void ata_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; + + if (tf->ctl != ap->last_ctl) { + writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr); + ap->last_ctl = tf->ctl; + ata_wait_idle(ap); + } + + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { + writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr); + writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr); + writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr); + writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr); + writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr); + VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", + tf->hob_feature, + tf->hob_nsect, + tf->hob_lbal, + tf->hob_lbam, + tf->hob_lbah); + } + + if (is_addr) { + writeb(tf->feature, (void __iomem *) ioaddr->feature_addr); + writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr); + writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr); + writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr); + writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr); + VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", + tf->feature, + tf->nsect, + tf->lbal, + tf->lbam, + tf->lbah); + } + + if (tf->flags & ATA_TFLAG_DEVICE) { + writeb(tf->device, (void __iomem *) ioaddr->device_addr); + VPRINTK("device 0x%X\n", tf->device); + } + + ata_wait_idle(ap); +} + + +/** + * ata_tf_load - send taskfile registers to host controller + * @ap: Port to which output is sent + * @tf: ATA taskfile register set + * + * Outputs ATA taskfile to standard ATA host controller using MMIO + * or PIO as indicated by the ATA_FLAG_MMIO flag. + * Writes the control, feature, nsect, lbal, lbam, and lbah registers. + * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect, + * hob_lbal, hob_lbam, and hob_lbah. + * + * This function waits for idle (!BUSY and !DRQ) after writing + * registers. If the control register has a new value, this + * function also waits for idle after writing control and before + * writing the remaining registers. + * + * May be used as the tf_load() entry in ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ +void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) +{ + if (ap->flags & ATA_FLAG_MMIO) + ata_tf_load_mmio(ap, tf); + else + ata_tf_load_pio(ap, tf); +} + +/** + * ata_exec_command_pio - issue ATA command to host controller + * @ap: port to which command is being issued + * @tf: ATA taskfile register set + * + * Issues PIO write to ATA command register, with proper + * synchronization with interrupt handler / other threads. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf) +{ + DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); + + outb(tf->command, ap->ioaddr.command_addr); + ata_pause(ap); +} + + +/** + * ata_exec_command_mmio - issue ATA command to host controller + * @ap: port to which command is being issued + * @tf: ATA taskfile register set + * + * Issues MMIO write to ATA command register, with proper + * synchronization with interrupt handler / other threads. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf) +{ + DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); + + writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr); + ata_pause(ap); +} + + +/** + * ata_exec_command - issue ATA command to host controller + * @ap: port to which command is being issued + * @tf: ATA taskfile register set + * + * Issues PIO/MMIO write to ATA command register, with proper + * synchronization with interrupt handler / other threads. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) +{ + if (ap->flags & ATA_FLAG_MMIO) + ata_exec_command_mmio(ap, tf); + else + ata_exec_command_pio(ap, tf); +} + +/** + * ata_tf_read_pio - input device's ATA taskfile shadow registers + * @ap: Port from which input is read + * @tf: ATA taskfile register set for storing input + * + * Reads ATA taskfile registers for currently-selected device + * into @tf. + * + * LOCKING: + * Inherited from caller. + */ + +static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + + tf->command = ata_check_status(ap); + tf->feature = inb(ioaddr->error_addr); + tf->nsect = inb(ioaddr->nsect_addr); + tf->lbal = inb(ioaddr->lbal_addr); + tf->lbam = inb(ioaddr->lbam_addr); + tf->lbah = inb(ioaddr->lbah_addr); + tf->device = inb(ioaddr->device_addr); + + if (tf->flags & ATA_TFLAG_LBA48) { + outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr); + tf->hob_feature = inb(ioaddr->error_addr); + tf->hob_nsect = inb(ioaddr->nsect_addr); + tf->hob_lbal = inb(ioaddr->lbal_addr); + tf->hob_lbam = inb(ioaddr->lbam_addr); + tf->hob_lbah = inb(ioaddr->lbah_addr); + } +} + +/** + * ata_tf_read_mmio - input device's ATA taskfile shadow registers + * @ap: Port from which input is read + * @tf: ATA taskfile register set for storing input + * + * Reads ATA taskfile registers for currently-selected device + * into @tf via MMIO. + * + * LOCKING: + * Inherited from caller. + */ + +static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + + tf->command = ata_check_status(ap); + tf->feature = readb((void __iomem *)ioaddr->error_addr); + tf->nsect = readb((void __iomem *)ioaddr->nsect_addr); + tf->lbal = readb((void __iomem *)ioaddr->lbal_addr); + tf->lbam = readb((void __iomem *)ioaddr->lbam_addr); + tf->lbah = readb((void __iomem *)ioaddr->lbah_addr); + tf->device = readb((void __iomem *)ioaddr->device_addr); + + if (tf->flags & ATA_TFLAG_LBA48) { + writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr); + tf->hob_feature = readb((void __iomem *)ioaddr->error_addr); + tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr); + tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr); + tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr); + tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr); + } +} + + +/** + * ata_tf_read - input device's ATA taskfile shadow registers + * @ap: Port from which input is read + * @tf: ATA taskfile register set for storing input + * + * Reads ATA taskfile registers for currently-selected device + * into @tf. + * + * Reads nsect, lbal, lbam, lbah, and device. If ATA_TFLAG_LBA48 + * is set, also reads the hob registers. + * + * May be used as the tf_read() entry in ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ +void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) +{ + if (ap->flags & ATA_FLAG_MMIO) + ata_tf_read_mmio(ap, tf); + else + ata_tf_read_pio(ap, tf); +} + +/** + * ata_check_status_pio - Read device status reg & clear interrupt + * @ap: port where the device is + * + * Reads ATA taskfile status register for currently-selected device + * and return its value. This also clears pending interrupts + * from this device + * + * LOCKING: + * Inherited from caller. + */ +static u8 ata_check_status_pio(struct ata_port *ap) +{ + return inb(ap->ioaddr.status_addr); +} + +/** + * ata_check_status_mmio - Read device status reg & clear interrupt + * @ap: port where the device is + * + * Reads ATA taskfile status register for currently-selected device + * via MMIO and return its value. This also clears pending interrupts + * from this device + * + * LOCKING: + * Inherited from caller. + */ +static u8 ata_check_status_mmio(struct ata_port *ap) +{ + return readb((void __iomem *) ap->ioaddr.status_addr); +} + + +/** + * ata_check_status - Read device status reg & clear interrupt + * @ap: port where the device is + * + * Reads ATA taskfile status register for currently-selected device + * and return its value. This also clears pending interrupts + * from this device + * + * May be used as the check_status() entry in ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ +u8 ata_check_status(struct ata_port *ap) +{ + if (ap->flags & ATA_FLAG_MMIO) + return ata_check_status_mmio(ap); + return ata_check_status_pio(ap); +} + + +/** + * ata_altstatus - Read device alternate status reg + * @ap: port where the device is + * + * Reads ATA taskfile alternate status register for + * currently-selected device and return its value. + * + * Note: may NOT be used as the check_altstatus() entry in + * ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ +u8 ata_altstatus(struct ata_port *ap) +{ + if (ap->ops->check_altstatus) + return ap->ops->check_altstatus(ap); + + if (ap->flags & ATA_FLAG_MMIO) + return readb((void __iomem *)ap->ioaddr.altstatus_addr); + return inb(ap->ioaddr.altstatus_addr); +} + +#ifdef CONFIG_PCI +static struct ata_probe_ent * +ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) +{ + struct ata_probe_ent *probe_ent; + + probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); + if (!probe_ent) { + printk(KERN_ERR DRV_NAME "(%s): out of memory\n", + kobject_name(&(dev->kobj))); + return NULL; + } + + INIT_LIST_HEAD(&probe_ent->node); + probe_ent->dev = dev; + + probe_ent->sht = port->sht; + probe_ent->host_flags = port->host_flags; + probe_ent->pio_mask = port->pio_mask; + probe_ent->mwdma_mask = port->mwdma_mask; + probe_ent->udma_mask = port->udma_mask; + probe_ent->port_ops = port->port_ops; + + return probe_ent; +} + + +/** + * ata_pci_init_native_mode - Initialize native-mode driver + * @pdev: pci device to be initialized + * @port: array[2] of pointers to port info structures. + * @ports: bitmap of ports present + * + * Utility function which allocates and initializes an + * ata_probe_ent structure for a standard dual-port + * PIO-based IDE controller. The returned ata_probe_ent + * structure can be passed to ata_device_add(). The returned + * ata_probe_ent structure should then be freed with kfree(). + * + * The caller need only pass the address of the primary port, the + * secondary will be deduced automatically. If the device has non + * standard secondary port mappings this function can be called twice, + * once for each interface. + */ + +struct ata_probe_ent * +ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports) +{ + struct ata_probe_ent *probe_ent = + ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); + int p = 0; + + if (!probe_ent) + return NULL; + + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + probe_ent->private_data = port[0]->private_data; + + if (ports & ATA_PORT_PRIMARY) { + probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0); + probe_ent->port[p].altstatus_addr = + probe_ent->port[p].ctl_addr = + pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; + probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4); + ata_std_ports(&probe_ent->port[p]); + p++; + } + + if (ports & ATA_PORT_SECONDARY) { + probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2); + probe_ent->port[p].altstatus_addr = + probe_ent->port[p].ctl_addr = + pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; + probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8; + ata_std_ports(&probe_ent->port[p]); + p++; + } + + probe_ent->n_ports = p; + return probe_ent; +} + + +static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, + struct ata_port_info *port, int port_num) +{ + struct ata_probe_ent *probe_ent; + + probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port); + if (!probe_ent) + return NULL; + + probe_ent->legacy_mode = 1; + probe_ent->n_ports = 1; + probe_ent->hard_port_no = port_num; + probe_ent->private_data = port->private_data; + + switch(port_num) + { + case 0: + probe_ent->irq = 14; + probe_ent->port[0].cmd_addr = 0x1f0; + probe_ent->port[0].altstatus_addr = + probe_ent->port[0].ctl_addr = 0x3f6; + break; + case 1: + probe_ent->irq = 15; + probe_ent->port[0].cmd_addr = 0x170; + probe_ent->port[0].altstatus_addr = + probe_ent->port[0].ctl_addr = 0x376; + break; + } + + probe_ent->port[0].bmdma_addr = + pci_resource_start(pdev, 4) + 8 * port_num; + ata_std_ports(&probe_ent->port[0]); + + return probe_ent; +} + + +/** + * ata_pci_init_one - Initialize/register PCI IDE host controller + * @pdev: Controller to be initialized + * @port_info: Information from low-level host driver + * @n_ports: Number of ports attached to host controller + * + * This is a helper function which can be called from a driver's + * xxx_init_one() probe function if the hardware uses traditional + * IDE taskfile registers. + * + * This function calls pci_enable_device(), reserves its register + * regions, sets the dma mask, enables bus master mode, and calls + * ata_device_add() + * + * LOCKING: + * Inherited from PCI layer (may sleep). + * + * RETURNS: + * Zero on success, negative on errno-based value on error. + */ + +int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, + unsigned int n_ports) +{ + struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL; + struct ata_port_info *port[2]; + u8 tmp8, mask; + unsigned int legacy_mode = 0; + int disable_dev_on_err = 1; + int rc; + + DPRINTK("ENTER\n"); + + port[0] = port_info[0]; + if (n_ports > 1) + port[1] = port_info[1]; + else + port[1] = port[0]; + + if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0 + && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { + /* TODO: What if one channel is in native mode ... */ + pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); + mask = (1 << 2) | (1 << 0); + if ((tmp8 & mask) != mask) + legacy_mode = (1 << 3); + } + + /* FIXME... */ + if ((!legacy_mode) && (n_ports > 2)) { + printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n"); + n_ports = 2; + /* For now */ + } + + /* FIXME: Really for ATA it isn't safe because the device may be + multi-purpose and we want to leave it alone if it was already + enabled. Secondly for shared use as Arjan says we want refcounting + + Checking dev->is_enabled is insufficient as this is not set at + boot for the primary video which is BIOS enabled + */ + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) { + disable_dev_on_err = 0; + goto err_out; + } + + /* FIXME: Should use platform specific mappers for legacy port ranges */ + if (legacy_mode) { + if (!request_region(0x1f0, 8, "libata")) { + struct resource *conflict, res; + res.start = 0x1f0; + res.end = 0x1f0 + 8 - 1; + conflict = ____request_resource(&ioport_resource, &res); + if (!strcmp(conflict->name, "libata")) + legacy_mode |= (1 << 0); + else { + disable_dev_on_err = 0; + printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n"); + } + } else + legacy_mode |= (1 << 0); + + if (!request_region(0x170, 8, "libata")) { + struct resource *conflict, res; + res.start = 0x170; + res.end = 0x170 + 8 - 1; + conflict = ____request_resource(&ioport_resource, &res); + if (!strcmp(conflict->name, "libata")) + legacy_mode |= (1 << 1); + else { + disable_dev_on_err = 0; + printk(KERN_WARNING "ata: 0x170 IDE port busy\n"); + } + } else + legacy_mode |= (1 << 1); + } + + /* we have legacy mode, but all ports are unavailable */ + if (legacy_mode == (1 << 3)) { + rc = -EBUSY; + goto err_out_regions; + } + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + if (legacy_mode) { + if (legacy_mode & (1 << 0)) + probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0); + if (legacy_mode & (1 << 1)) + probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1); + } else { + if (n_ports == 2) + probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); + else + probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY); + } + if (!probe_ent && !probe_ent2) { + rc = -ENOMEM; + goto err_out_regions; + } + + pci_set_master(pdev); + + /* FIXME: check ata_device_add return */ + if (legacy_mode) { + if (legacy_mode & (1 << 0)) + ata_device_add(probe_ent); + if (legacy_mode & (1 << 1)) + ata_device_add(probe_ent2); + } else + ata_device_add(probe_ent); + + kfree(probe_ent); + kfree(probe_ent2); + + return 0; + +err_out_regions: + if (legacy_mode & (1 << 0)) + release_region(0x1f0, 8); + if (legacy_mode & (1 << 1)) + release_region(0x170, 8); + pci_release_regions(pdev); +err_out: + if (disable_dev_on_err) + pci_disable_device(pdev); + return rc; +} + +#endif /* CONFIG_PCI */ + diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 14cdbb336dd5..22db73932253 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -83,403 +83,6 @@ MODULE_DESCRIPTION("Library module for ATA devices"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -/** - * ata_tf_load_pio - send taskfile registers to host controller - * @ap: Port to which output is sent - * @tf: ATA taskfile register set - * - * Outputs ATA taskfile to standard ATA host controller. - * - * LOCKING: - * Inherited from caller. - */ - -static void ata_tf_load_pio(struct ata_port *ap, const struct ata_taskfile *tf) -{ - struct ata_ioports *ioaddr = &ap->ioaddr; - unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; - - if (tf->ctl != ap->last_ctl) { - outb(tf->ctl, ioaddr->ctl_addr); - ap->last_ctl = tf->ctl; - ata_wait_idle(ap); - } - - if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { - outb(tf->hob_feature, ioaddr->feature_addr); - outb(tf->hob_nsect, ioaddr->nsect_addr); - outb(tf->hob_lbal, ioaddr->lbal_addr); - outb(tf->hob_lbam, ioaddr->lbam_addr); - outb(tf->hob_lbah, ioaddr->lbah_addr); - VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", - tf->hob_feature, - tf->hob_nsect, - tf->hob_lbal, - tf->hob_lbam, - tf->hob_lbah); - } - - if (is_addr) { - outb(tf->feature, ioaddr->feature_addr); - outb(tf->nsect, ioaddr->nsect_addr); - outb(tf->lbal, ioaddr->lbal_addr); - outb(tf->lbam, ioaddr->lbam_addr); - outb(tf->lbah, ioaddr->lbah_addr); - VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", - tf->feature, - tf->nsect, - tf->lbal, - tf->lbam, - tf->lbah); - } - - if (tf->flags & ATA_TFLAG_DEVICE) { - outb(tf->device, ioaddr->device_addr); - VPRINTK("device 0x%X\n", tf->device); - } - - ata_wait_idle(ap); -} - -/** - * ata_tf_load_mmio - send taskfile registers to host controller - * @ap: Port to which output is sent - * @tf: ATA taskfile register set - * - * Outputs ATA taskfile to standard ATA host controller using MMIO. - * - * LOCKING: - * Inherited from caller. - */ - -static void ata_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) -{ - struct ata_ioports *ioaddr = &ap->ioaddr; - unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; - - if (tf->ctl != ap->last_ctl) { - writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr); - ap->last_ctl = tf->ctl; - ata_wait_idle(ap); - } - - if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { - writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr); - writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr); - writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr); - writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr); - writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr); - VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", - tf->hob_feature, - tf->hob_nsect, - tf->hob_lbal, - tf->hob_lbam, - tf->hob_lbah); - } - - if (is_addr) { - writeb(tf->feature, (void __iomem *) ioaddr->feature_addr); - writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr); - writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr); - writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr); - writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr); - VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", - tf->feature, - tf->nsect, - tf->lbal, - tf->lbam, - tf->lbah); - } - - if (tf->flags & ATA_TFLAG_DEVICE) { - writeb(tf->device, (void __iomem *) ioaddr->device_addr); - VPRINTK("device 0x%X\n", tf->device); - } - - ata_wait_idle(ap); -} - - -/** - * ata_tf_load - send taskfile registers to host controller - * @ap: Port to which output is sent - * @tf: ATA taskfile register set - * - * Outputs ATA taskfile to standard ATA host controller using MMIO - * or PIO as indicated by the ATA_FLAG_MMIO flag. - * Writes the control, feature, nsect, lbal, lbam, and lbah registers. - * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect, - * hob_lbal, hob_lbam, and hob_lbah. - * - * This function waits for idle (!BUSY and !DRQ) after writing - * registers. If the control register has a new value, this - * function also waits for idle after writing control and before - * writing the remaining registers. - * - * May be used as the tf_load() entry in ata_port_operations. - * - * LOCKING: - * Inherited from caller. - */ -void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) -{ - if (ap->flags & ATA_FLAG_MMIO) - ata_tf_load_mmio(ap, tf); - else - ata_tf_load_pio(ap, tf); -} - -/** - * ata_exec_command_pio - issue ATA command to host controller - * @ap: port to which command is being issued - * @tf: ATA taskfile register set - * - * Issues PIO write to ATA command register, with proper - * synchronization with interrupt handler / other threads. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf) -{ - DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); - - outb(tf->command, ap->ioaddr.command_addr); - ata_pause(ap); -} - - -/** - * ata_exec_command_mmio - issue ATA command to host controller - * @ap: port to which command is being issued - * @tf: ATA taskfile register set - * - * Issues MMIO write to ATA command register, with proper - * synchronization with interrupt handler / other threads. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf) -{ - DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); - - writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr); - ata_pause(ap); -} - - -/** - * ata_exec_command - issue ATA command to host controller - * @ap: port to which command is being issued - * @tf: ATA taskfile register set - * - * Issues PIO/MMIO write to ATA command register, with proper - * synchronization with interrupt handler / other threads. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ -void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) -{ - if (ap->flags & ATA_FLAG_MMIO) - ata_exec_command_mmio(ap, tf); - else - ata_exec_command_pio(ap, tf); -} - -/** - * ata_tf_to_host - issue ATA taskfile to host controller - * @ap: port to which command is being issued - * @tf: ATA taskfile register set - * - * Issues ATA taskfile register set to ATA host controller, - * with proper synchronization with interrupt handler and - * other threads. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -static inline void ata_tf_to_host(struct ata_port *ap, - const struct ata_taskfile *tf) -{ - ap->ops->tf_load(ap, tf); - ap->ops->exec_command(ap, tf); -} - -/** - * ata_tf_read_pio - input device's ATA taskfile shadow registers - * @ap: Port from which input is read - * @tf: ATA taskfile register set for storing input - * - * Reads ATA taskfile registers for currently-selected device - * into @tf. - * - * LOCKING: - * Inherited from caller. - */ - -static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf) -{ - struct ata_ioports *ioaddr = &ap->ioaddr; - - tf->command = ata_check_status(ap); - tf->feature = inb(ioaddr->error_addr); - tf->nsect = inb(ioaddr->nsect_addr); - tf->lbal = inb(ioaddr->lbal_addr); - tf->lbam = inb(ioaddr->lbam_addr); - tf->lbah = inb(ioaddr->lbah_addr); - tf->device = inb(ioaddr->device_addr); - - if (tf->flags & ATA_TFLAG_LBA48) { - outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr); - tf->hob_feature = inb(ioaddr->error_addr); - tf->hob_nsect = inb(ioaddr->nsect_addr); - tf->hob_lbal = inb(ioaddr->lbal_addr); - tf->hob_lbam = inb(ioaddr->lbam_addr); - tf->hob_lbah = inb(ioaddr->lbah_addr); - } -} - -/** - * ata_tf_read_mmio - input device's ATA taskfile shadow registers - * @ap: Port from which input is read - * @tf: ATA taskfile register set for storing input - * - * Reads ATA taskfile registers for currently-selected device - * into @tf via MMIO. - * - * LOCKING: - * Inherited from caller. - */ - -static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf) -{ - struct ata_ioports *ioaddr = &ap->ioaddr; - - tf->command = ata_check_status(ap); - tf->feature = readb((void __iomem *)ioaddr->error_addr); - tf->nsect = readb((void __iomem *)ioaddr->nsect_addr); - tf->lbal = readb((void __iomem *)ioaddr->lbal_addr); - tf->lbam = readb((void __iomem *)ioaddr->lbam_addr); - tf->lbah = readb((void __iomem *)ioaddr->lbah_addr); - tf->device = readb((void __iomem *)ioaddr->device_addr); - - if (tf->flags & ATA_TFLAG_LBA48) { - writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr); - tf->hob_feature = readb((void __iomem *)ioaddr->error_addr); - tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr); - tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr); - tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr); - tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr); - } -} - - -/** - * ata_tf_read - input device's ATA taskfile shadow registers - * @ap: Port from which input is read - * @tf: ATA taskfile register set for storing input - * - * Reads ATA taskfile registers for currently-selected device - * into @tf. - * - * Reads nsect, lbal, lbam, lbah, and device. If ATA_TFLAG_LBA48 - * is set, also reads the hob registers. - * - * May be used as the tf_read() entry in ata_port_operations. - * - * LOCKING: - * Inherited from caller. - */ -void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) -{ - if (ap->flags & ATA_FLAG_MMIO) - ata_tf_read_mmio(ap, tf); - else - ata_tf_read_pio(ap, tf); -} - -/** - * ata_check_status_pio - Read device status reg & clear interrupt - * @ap: port where the device is - * - * Reads ATA taskfile status register for currently-selected device - * and return its value. This also clears pending interrupts - * from this device - * - * LOCKING: - * Inherited from caller. - */ -static u8 ata_check_status_pio(struct ata_port *ap) -{ - return inb(ap->ioaddr.status_addr); -} - -/** - * ata_check_status_mmio - Read device status reg & clear interrupt - * @ap: port where the device is - * - * Reads ATA taskfile status register for currently-selected device - * via MMIO and return its value. This also clears pending interrupts - * from this device - * - * LOCKING: - * Inherited from caller. - */ -static u8 ata_check_status_mmio(struct ata_port *ap) -{ - return readb((void __iomem *) ap->ioaddr.status_addr); -} - - -/** - * ata_check_status - Read device status reg & clear interrupt - * @ap: port where the device is - * - * Reads ATA taskfile status register for currently-selected device - * and return its value. This also clears pending interrupts - * from this device - * - * May be used as the check_status() entry in ata_port_operations. - * - * LOCKING: - * Inherited from caller. - */ -u8 ata_check_status(struct ata_port *ap) -{ - if (ap->flags & ATA_FLAG_MMIO) - return ata_check_status_mmio(ap); - return ata_check_status_pio(ap); -} - - -/** - * ata_altstatus - Read device alternate status reg - * @ap: port where the device is - * - * Reads ATA taskfile alternate status register for - * currently-selected device and return its value. - * - * Note: may NOT be used as the check_altstatus() entry in - * ata_port_operations. - * - * LOCKING: - * Inherited from caller. - */ -u8 ata_altstatus(struct ata_port *ap) -{ - if (ap->ops->check_altstatus) - return ap->ops->check_altstatus(ap); - - if (ap->flags & ATA_FLAG_MMIO) - return readb((void __iomem *)ap->ioaddr.altstatus_addr); - return inb(ap->ioaddr.altstatus_addr); -} - /** * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure @@ -2008,6 +1611,26 @@ err_out: ata_port_disable(ap); } +/** + * ata_tf_to_host - issue ATA taskfile to host controller + * @ap: port to which command is being issued + * @tf: ATA taskfile register set + * + * Issues ATA taskfile register set to ATA host controller, + * with proper synchronization with interrupt handler and + * other threads. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +static inline void ata_tf_to_host(struct ata_port *ap, + const struct ata_taskfile *tf) +{ + ap->ops->tf_load(ap, tf); + ap->ops->exec_command(ap, tf); +} + /** * ata_busy_sleep - sleep until BSY clears, or timeout * @ap: port containing status register to be polled @@ -5106,32 +4729,6 @@ void ata_std_ports(struct ata_ioports *ioaddr) ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD; } -static struct ata_probe_ent * -ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) -{ - struct ata_probe_ent *probe_ent; - - probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); - if (!probe_ent) { - printk(KERN_ERR DRV_NAME "(%s): out of memory\n", - kobject_name(&(dev->kobj))); - return NULL; - } - - INIT_LIST_HEAD(&probe_ent->node); - probe_ent->dev = dev; - - probe_ent->sht = port->sht; - probe_ent->host_flags = port->host_flags; - probe_ent->pio_mask = port->pio_mask; - probe_ent->mwdma_mask = port->mwdma_mask; - probe_ent->udma_mask = port->udma_mask; - probe_ent->port_ops = port->port_ops; - - return probe_ent; -} - - #ifdef CONFIG_PCI @@ -5142,256 +4739,6 @@ void ata_pci_host_stop (struct ata_host_set *host_set) pci_iounmap(pdev, host_set->mmio_base); } -/** - * ata_pci_init_native_mode - Initialize native-mode driver - * @pdev: pci device to be initialized - * @port: array[2] of pointers to port info structures. - * @ports: bitmap of ports present - * - * Utility function which allocates and initializes an - * ata_probe_ent structure for a standard dual-port - * PIO-based IDE controller. The returned ata_probe_ent - * structure can be passed to ata_device_add(). The returned - * ata_probe_ent structure should then be freed with kfree(). - * - * The caller need only pass the address of the primary port, the - * secondary will be deduced automatically. If the device has non - * standard secondary port mappings this function can be called twice, - * once for each interface. - */ - -struct ata_probe_ent * -ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports) -{ - struct ata_probe_ent *probe_ent = - ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); - int p = 0; - - if (!probe_ent) - return NULL; - - probe_ent->irq = pdev->irq; - probe_ent->irq_flags = SA_SHIRQ; - probe_ent->private_data = port[0]->private_data; - - if (ports & ATA_PORT_PRIMARY) { - probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0); - probe_ent->port[p].altstatus_addr = - probe_ent->port[p].ctl_addr = - pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; - probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4); - ata_std_ports(&probe_ent->port[p]); - p++; - } - - if (ports & ATA_PORT_SECONDARY) { - probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2); - probe_ent->port[p].altstatus_addr = - probe_ent->port[p].ctl_addr = - pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; - probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8; - ata_std_ports(&probe_ent->port[p]); - p++; - } - - probe_ent->n_ports = p; - return probe_ent; -} - -static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info *port, int port_num) -{ - struct ata_probe_ent *probe_ent; - - probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port); - if (!probe_ent) - return NULL; - - probe_ent->legacy_mode = 1; - probe_ent->n_ports = 1; - probe_ent->hard_port_no = port_num; - probe_ent->private_data = port->private_data; - - switch(port_num) - { - case 0: - probe_ent->irq = 14; - probe_ent->port[0].cmd_addr = 0x1f0; - probe_ent->port[0].altstatus_addr = - probe_ent->port[0].ctl_addr = 0x3f6; - break; - case 1: - probe_ent->irq = 15; - probe_ent->port[0].cmd_addr = 0x170; - probe_ent->port[0].altstatus_addr = - probe_ent->port[0].ctl_addr = 0x376; - break; - } - probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4) + 8 * port_num; - ata_std_ports(&probe_ent->port[0]); - return probe_ent; -} - -/** - * ata_pci_init_one - Initialize/register PCI IDE host controller - * @pdev: Controller to be initialized - * @port_info: Information from low-level host driver - * @n_ports: Number of ports attached to host controller - * - * This is a helper function which can be called from a driver's - * xxx_init_one() probe function if the hardware uses traditional - * IDE taskfile registers. - * - * This function calls pci_enable_device(), reserves its register - * regions, sets the dma mask, enables bus master mode, and calls - * ata_device_add() - * - * LOCKING: - * Inherited from PCI layer (may sleep). - * - * RETURNS: - * Zero on success, negative on errno-based value on error. - */ - -int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, - unsigned int n_ports) -{ - struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL; - struct ata_port_info *port[2]; - u8 tmp8, mask; - unsigned int legacy_mode = 0; - int disable_dev_on_err = 1; - int rc; - - DPRINTK("ENTER\n"); - - port[0] = port_info[0]; - if (n_ports > 1) - port[1] = port_info[1]; - else - port[1] = port[0]; - - if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0 - && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { - /* TODO: What if one channel is in native mode ... */ - pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); - mask = (1 << 2) | (1 << 0); - if ((tmp8 & mask) != mask) - legacy_mode = (1 << 3); - } - - /* FIXME... */ - if ((!legacy_mode) && (n_ports > 2)) { - printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n"); - n_ports = 2; - /* For now */ - } - - /* FIXME: Really for ATA it isn't safe because the device may be - multi-purpose and we want to leave it alone if it was already - enabled. Secondly for shared use as Arjan says we want refcounting - - Checking dev->is_enabled is insufficient as this is not set at - boot for the primary video which is BIOS enabled - */ - - rc = pci_enable_device(pdev); - if (rc) - return rc; - - rc = pci_request_regions(pdev, DRV_NAME); - if (rc) { - disable_dev_on_err = 0; - goto err_out; - } - - /* FIXME: Should use platform specific mappers for legacy port ranges */ - if (legacy_mode) { - if (!request_region(0x1f0, 8, "libata")) { - struct resource *conflict, res; - res.start = 0x1f0; - res.end = 0x1f0 + 8 - 1; - conflict = ____request_resource(&ioport_resource, &res); - if (!strcmp(conflict->name, "libata")) - legacy_mode |= (1 << 0); - else { - disable_dev_on_err = 0; - printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n"); - } - } else - legacy_mode |= (1 << 0); - - if (!request_region(0x170, 8, "libata")) { - struct resource *conflict, res; - res.start = 0x170; - res.end = 0x170 + 8 - 1; - conflict = ____request_resource(&ioport_resource, &res); - if (!strcmp(conflict->name, "libata")) - legacy_mode |= (1 << 1); - else { - disable_dev_on_err = 0; - printk(KERN_WARNING "ata: 0x170 IDE port busy\n"); - } - } else - legacy_mode |= (1 << 1); - } - - /* we have legacy mode, but all ports are unavailable */ - if (legacy_mode == (1 << 3)) { - rc = -EBUSY; - goto err_out_regions; - } - - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - goto err_out_regions; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - goto err_out_regions; - - if (legacy_mode) { - if (legacy_mode & (1 << 0)) - probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0); - if (legacy_mode & (1 << 1)) - probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1); - } else { - if (n_ports == 2) - probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); - else - probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY); - } - if (!probe_ent && !probe_ent2) { - rc = -ENOMEM; - goto err_out_regions; - } - - pci_set_master(pdev); - - /* FIXME: check ata_device_add return */ - if (legacy_mode) { - if (legacy_mode & (1 << 0)) - ata_device_add(probe_ent); - if (legacy_mode & (1 << 1)) - ata_device_add(probe_ent2); - } else - ata_device_add(probe_ent); - - kfree(probe_ent); - kfree(probe_ent2); - - return 0; - -err_out_regions: - if (legacy_mode & (1 << 0)) - release_region(0x1f0, 8); - if (legacy_mode & (1 << 1)) - release_region(0x170, 8); - pci_release_regions(pdev); -err_out: - if (disable_dev_on_err) - pci_disable_device(pdev); - return rc; -} - /** * ata_pci_remove_one - PCI layer callback for device removal * @pdev: PCI device that was removed -- cgit v1.2.3-59-g8ed1b From 2ef9481e666b4654159ac9f847e6963809e3c470 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Mon, 23 Jan 2006 10:58:20 -0600 Subject: [PATCH] powerpc: trivial: modify comments to refer to new location of files This patch removes all self references and fixes references to files in the now defunct arch/ppc64 tree. I think this accomplises everything wanted, though there might be a few references I missed. Signed-off-by: Jon Mason Signed-off-by: Paul Mackerras --- Documentation/powerpc/eeh-pci-error-recovery.txt | 15 ++++++++------- arch/powerpc/boot/install.sh | 2 -- arch/powerpc/kernel/entry_64.S | 4 +--- arch/powerpc/kernel/head_44x.S | 2 -- arch/powerpc/kernel/head_64.S | 2 -- arch/powerpc/kernel/head_8xx.S | 2 -- arch/powerpc/kernel/head_fsl_booke.S | 2 -- arch/powerpc/kernel/iomap.c | 2 -- arch/powerpc/kernel/iommu.c | 1 - arch/powerpc/kernel/irq.c | 2 -- arch/powerpc/kernel/kprobes.c | 1 - arch/powerpc/kernel/pci_iommu.c | 1 - arch/powerpc/kernel/process.c | 2 -- arch/powerpc/kernel/ptrace-common.h | 2 -- arch/powerpc/kernel/rtas-proc.c | 1 - arch/powerpc/kernel/rtas_pci.c | 2 -- arch/powerpc/kernel/signal_64.c | 2 -- arch/powerpc/kernel/vdso.c | 2 -- arch/powerpc/lib/copypage_64.S | 2 -- arch/powerpc/lib/copyuser_64.S | 2 -- arch/powerpc/lib/e2a.c | 4 +--- arch/powerpc/lib/memcpy_64.S | 2 -- arch/powerpc/lib/rheap.c | 2 -- arch/powerpc/mm/fault.c | 2 -- arch/powerpc/mm/hash_low_32.S | 2 -- arch/powerpc/mm/mmap.c | 2 -- arch/powerpc/mm/slb_low.S | 2 -- arch/powerpc/mm/tlb_64.c | 2 +- arch/powerpc/platforms/chrp/pegasos_eth.c | 2 -- arch/powerpc/platforms/chrp/setup.c | 2 -- arch/powerpc/platforms/chrp/time.c | 2 -- arch/powerpc/platforms/maple/time.c | 2 -- arch/powerpc/platforms/powermac/cpufreq_32.c | 2 -- arch/powerpc/platforms/powermac/feature.c | 2 -- arch/powerpc/platforms/powermac/nvram.c | 2 -- arch/powerpc/platforms/pseries/hvCall.S | 2 -- arch/powerpc/platforms/pseries/iommu.c | 2 -- arch/powerpc/platforms/pseries/pci.c | 2 -- arch/powerpc/sysdev/dcr.S | 2 -- arch/powerpc/sysdev/ipic.h | 2 -- arch/ppc/4xx_io/serial_sicc.c | 2 -- arch/ppc/amiga/amiints.c | 2 +- arch/ppc/amiga/bootinfo.c | 2 -- arch/ppc/amiga/cia.c | 2 -- arch/ppc/amiga/config.c | 2 -- arch/ppc/amiga/ints.c | 2 -- arch/ppc/boot/Makefile | 3 --- arch/ppc/boot/common/Makefile | 3 --- arch/ppc/boot/common/bootinfo.c | 2 -- arch/ppc/boot/common/misc-common.c | 2 -- arch/ppc/boot/common/serial_stub.c | 2 -- arch/ppc/boot/common/util.S | 2 -- arch/ppc/boot/include/mpc10x.h | 2 -- arch/ppc/boot/simple/cpc700_memory.c | 2 -- arch/ppc/boot/simple/head.S | 2 -- arch/ppc/boot/simple/misc-chestnut.c | 2 -- arch/ppc/boot/simple/misc-cpci690.c | 2 -- arch/ppc/boot/simple/misc-ev64260.c | 2 -- arch/ppc/boot/simple/misc-ev64360.c | 1 - arch/ppc/boot/simple/misc-katana.c | 2 -- arch/ppc/boot/simple/misc-mv64x60.c | 2 -- arch/ppc/boot/simple/misc-prep.c | 2 -- arch/ppc/boot/simple/misc-radstone_ppc7d.c | 2 -- arch/ppc/boot/simple/misc-spruce.c | 2 -- arch/ppc/boot/simple/misc.c | 2 -- arch/ppc/boot/simple/mpc10x_memory.c | 2 -- arch/ppc/boot/simple/mpc52xx_tty.c | 2 -- arch/ppc/boot/simple/mv64x60_tty.c | 2 -- arch/ppc/boot/simple/openbios.c | 2 -- arch/ppc/boot/simple/relocate.S | 2 -- arch/ppc/boot/utils/mkbugboot.c | 2 -- arch/ppc/kernel/head_44x.S | 2 -- arch/ppc/kernel/head_8xx.S | 2 -- arch/ppc/kernel/head_fsl_booke.S | 2 -- arch/ppc/kernel/traps.c | 2 -- arch/ppc/lib/rheap.c | 2 -- arch/ppc/math-emu/math.c | 2 -- arch/ppc/mm/fault.c | 2 -- arch/ppc/mm/hashtable.S | 2 -- arch/ppc/platforms/4xx/bamboo.c | 2 -- arch/ppc/platforms/4xx/bamboo.h | 2 -- arch/ppc/platforms/4xx/bubinga.h | 2 -- arch/ppc/platforms/4xx/cpci405.c | 2 -- arch/ppc/platforms/4xx/ebony.c | 2 -- arch/ppc/platforms/4xx/ebony.h | 2 -- arch/ppc/platforms/4xx/ep405.c | 2 -- arch/ppc/platforms/4xx/ep405.h | 2 -- arch/ppc/platforms/4xx/ibm405ep.c | 2 -- arch/ppc/platforms/4xx/ibm405ep.h | 2 -- arch/ppc/platforms/4xx/ibm405gp.h | 2 -- arch/ppc/platforms/4xx/ibm405gpr.c | 2 -- arch/ppc/platforms/4xx/ibm405gpr.h | 2 -- arch/ppc/platforms/4xx/ibm440ep.c | 2 -- arch/ppc/platforms/4xx/ibm440ep.h | 2 -- arch/ppc/platforms/4xx/ibm440gp.c | 2 -- arch/ppc/platforms/4xx/ibm440gp.h | 2 -- arch/ppc/platforms/4xx/ibm440gx.c | 2 -- arch/ppc/platforms/4xx/ibm440gx.h | 2 -- arch/ppc/platforms/4xx/ibm440sp.c | 2 -- arch/ppc/platforms/4xx/ibm440sp.h | 2 -- arch/ppc/platforms/4xx/ibmnp405h.c | 2 -- arch/ppc/platforms/4xx/ibmnp405h.h | 2 -- arch/ppc/platforms/4xx/ibmstb4.c | 2 -- arch/ppc/platforms/4xx/ibmstb4.h | 2 -- arch/ppc/platforms/4xx/ibmstbx25.c | 2 -- arch/ppc/platforms/4xx/ibmstbx25.h | 2 -- arch/ppc/platforms/4xx/luan.c | 2 -- arch/ppc/platforms/4xx/luan.h | 2 -- arch/ppc/platforms/4xx/ocotea.c | 2 -- arch/ppc/platforms/4xx/ocotea.h | 2 -- arch/ppc/platforms/4xx/ppc440spe.c | 2 -- arch/ppc/platforms/4xx/ppc440spe.h | 2 -- arch/ppc/platforms/4xx/redwood5.c | 2 -- arch/ppc/platforms/4xx/redwood5.h | 2 -- arch/ppc/platforms/4xx/redwood6.c | 2 -- arch/ppc/platforms/4xx/redwood6.h | 2 -- arch/ppc/platforms/4xx/sycamore.c | 2 -- arch/ppc/platforms/4xx/sycamore.h | 2 -- arch/ppc/platforms/4xx/walnut.c | 2 -- arch/ppc/platforms/4xx/walnut.h | 2 -- arch/ppc/platforms/4xx/xilinx_ml300.c | 2 -- arch/ppc/platforms/4xx/xilinx_ml300.h | 2 -- arch/ppc/platforms/4xx/yucca.c | 2 -- arch/ppc/platforms/4xx/yucca.h | 2 -- arch/ppc/platforms/83xx/mpc834x_sys.c | 2 -- arch/ppc/platforms/83xx/mpc834x_sys.h | 2 -- arch/ppc/platforms/85xx/mpc8540_ads.c | 2 -- arch/ppc/platforms/85xx/mpc8540_ads.h | 2 -- arch/ppc/platforms/85xx/mpc8555_cds.h | 2 -- arch/ppc/platforms/85xx/mpc8560_ads.c | 2 -- arch/ppc/platforms/85xx/mpc8560_ads.h | 2 -- arch/ppc/platforms/85xx/mpc85xx_ads_common.c | 2 -- arch/ppc/platforms/85xx/mpc85xx_ads_common.h | 2 -- arch/ppc/platforms/85xx/mpc85xx_cds_common.c | 2 -- arch/ppc/platforms/85xx/mpc85xx_cds_common.h | 2 -- arch/ppc/platforms/85xx/sbc8560.c | 2 -- arch/ppc/platforms/85xx/sbc8560.h | 2 -- arch/ppc/platforms/85xx/sbc85xx.c | 2 -- arch/ppc/platforms/85xx/sbc85xx.h | 2 -- arch/ppc/platforms/85xx/stx_gp3.c | 2 -- arch/ppc/platforms/85xx/stx_gp3.h | 2 -- arch/ppc/platforms/85xx/tqm85xx.c | 2 -- arch/ppc/platforms/85xx/tqm85xx.h | 2 -- arch/ppc/platforms/apus_setup.c | 2 -- arch/ppc/platforms/chestnut.c | 2 -- arch/ppc/platforms/chestnut.h | 2 -- arch/ppc/platforms/chrp_pegasos_eth.c | 2 -- arch/ppc/platforms/chrp_setup.c | 2 -- arch/ppc/platforms/chrp_time.c | 2 -- arch/ppc/platforms/cpci690.c | 2 -- arch/ppc/platforms/cpci690.h | 2 -- arch/ppc/platforms/ev64260.c | 2 -- arch/ppc/platforms/ev64260.h | 2 -- arch/ppc/platforms/ev64360.c | 2 -- arch/ppc/platforms/ev64360.h | 2 -- arch/ppc/platforms/gemini.h | 3 --- arch/ppc/platforms/gemini_prom.S | 2 -- arch/ppc/platforms/gemini_setup.c | 2 -- arch/ppc/platforms/hdpu.c | 3 --- arch/ppc/platforms/hdpu.h | 2 -- arch/ppc/platforms/katana.c | 2 -- arch/ppc/platforms/katana.h | 2 -- arch/ppc/platforms/lite5200.c | 2 -- arch/ppc/platforms/lite5200.h | 2 -- arch/ppc/platforms/lopec.c | 2 -- arch/ppc/platforms/mvme5100.c | 2 -- arch/ppc/platforms/pal4.h | 2 -- arch/ppc/platforms/pal4_pci.c | 2 -- arch/ppc/platforms/pal4_serial.h | 2 -- arch/ppc/platforms/pal4_setup.c | 2 -- arch/ppc/platforms/powerpmc250.c | 2 -- arch/ppc/platforms/pplus.c | 2 -- arch/ppc/platforms/pplus.h | 2 -- arch/ppc/platforms/pq2ads.c | 2 -- arch/ppc/platforms/prep_setup.c | 2 -- arch/ppc/platforms/prpmc750.c | 2 -- arch/ppc/platforms/prpmc800.c | 2 -- arch/ppc/platforms/radstone_ppc7d.c | 2 -- arch/ppc/platforms/radstone_ppc7d.h | 2 -- arch/ppc/platforms/sandpoint.c | 2 -- arch/ppc/platforms/sandpoint.h | 2 -- arch/ppc/platforms/sbc82xx.c | 2 -- arch/ppc/platforms/spruce.c | 2 -- arch/ppc/platforms/tqm8260_setup.c | 2 -- arch/ppc/syslib/cpc700.h | 2 -- arch/ppc/syslib/cpc700_pic.c | 2 -- arch/ppc/syslib/cpc710.h | 2 -- arch/ppc/syslib/gen550.h | 2 -- arch/ppc/syslib/gen550_dbg.c | 2 -- arch/ppc/syslib/gen550_kgdb.c | 2 -- arch/ppc/syslib/gt64260_pic.c | 2 -- arch/ppc/syslib/harrier.c | 2 -- arch/ppc/syslib/hawk_common.c | 2 -- arch/ppc/syslib/ibm440gp_common.c | 2 -- arch/ppc/syslib/ibm440gp_common.h | 2 -- arch/ppc/syslib/ibm440gx_common.c | 2 -- arch/ppc/syslib/ibm440gx_common.h | 2 -- arch/ppc/syslib/ibm440sp_common.c | 2 -- arch/ppc/syslib/ibm440sp_common.h | 2 -- arch/ppc/syslib/ibm44x_common.c | 2 -- arch/ppc/syslib/ibm44x_common.h | 2 -- arch/ppc/syslib/m8260_pci_erratum9.c | 2 -- arch/ppc/syslib/m8260_setup.c | 2 -- arch/ppc/syslib/m8xx_setup.c | 2 -- arch/ppc/syslib/mpc10x_common.c | 2 -- arch/ppc/syslib/mpc52xx_devices.c | 2 -- arch/ppc/syslib/mpc52xx_pci.c | 2 -- arch/ppc/syslib/mpc52xx_pci.h | 2 -- arch/ppc/syslib/mpc52xx_pic.c | 2 -- arch/ppc/syslib/mpc52xx_setup.c | 2 -- arch/ppc/syslib/mpc52xx_sys.c | 2 -- arch/ppc/syslib/mpc83xx_devices.c | 2 -- arch/ppc/syslib/mpc83xx_sys.c | 2 -- arch/ppc/syslib/mpc85xx_devices.c | 2 -- arch/ppc/syslib/mpc85xx_sys.c | 2 -- arch/ppc/syslib/mpc8xx_devices.c | 2 -- arch/ppc/syslib/mpc8xx_sys.c | 2 -- arch/ppc/syslib/mv64360_pic.c | 2 -- arch/ppc/syslib/mv64x60.c | 2 -- arch/ppc/syslib/mv64x60_dbg.c | 2 -- arch/ppc/syslib/mv64x60_win.c | 2 -- arch/ppc/syslib/open_pic.c | 2 -- arch/ppc/syslib/open_pic2.c | 2 -- arch/ppc/syslib/open_pic_defs.h | 2 -- arch/ppc/syslib/pci_auto.c | 2 -- arch/ppc/syslib/ppc4xx_dma.c | 2 -- arch/ppc/syslib/ppc4xx_pic.c | 2 -- arch/ppc/syslib/ppc4xx_sgdma.c | 2 -- arch/ppc/syslib/ppc83xx_setup.c | 2 -- arch/ppc/syslib/ppc83xx_setup.h | 2 -- arch/ppc/syslib/ppc85xx_common.c | 2 -- arch/ppc/syslib/ppc85xx_common.h | 2 -- arch/ppc/syslib/ppc85xx_setup.c | 2 -- arch/ppc/syslib/ppc85xx_setup.h | 2 -- arch/ppc/syslib/ppc_sys.c | 2 -- arch/ppc/syslib/pq2_devices.c | 2 -- arch/ppc/syslib/pq2_sys.c | 2 -- arch/ppc/syslib/prep_nvram.c | 2 -- arch/ppc/syslib/todc_time.c | 2 -- arch/ppc/syslib/xilinx_pic.c | 2 -- drivers/char/hvcs.c | 9 +++++---- include/asm-powerpc/paca.h | 2 +- include/asm-powerpc/rwsem.h | 2 +- include/asm-ppc/harrier.h | 2 -- include/asm-ppc/mpc10x.h | 2 -- include/asm-ppc/todc.h | 2 -- kernel/auditsc.c | 2 +- lib/extable.c | 1 - 248 files changed, 20 insertions(+), 498 deletions(-) (limited to 'drivers') diff --git a/Documentation/powerpc/eeh-pci-error-recovery.txt b/Documentation/powerpc/eeh-pci-error-recovery.txt index 67a11a36270c..3764dd4b12cb 100644 --- a/Documentation/powerpc/eeh-pci-error-recovery.txt +++ b/Documentation/powerpc/eeh-pci-error-recovery.txt @@ -121,7 +121,7 @@ accomplished. EEH must be enabled in the PHB's very early during the boot process, and if a PCI slot is hot-plugged. The former is performed by -eeh_init() in arch/ppc64/kernel/eeh.c, and the later by +eeh_init() in arch/powerpc/platforms/pseries/eeh.c, and the later by drivers/pci/hotplug/pSeries_pci.c calling in to the eeh.c code. EEH must be enabled before a PCI scan of the device can proceed. Current Power5 hardware will not work unless EEH is enabled; @@ -133,7 +133,7 @@ error. Given an arbitrary address, the routine pci_get_device_by_addr() will find the pci device associated with that address (if any). -The default include/asm-ppc64/io.h macros readb(), inb(), insb(), +The default include/asm-powerpc/io.h macros readb(), inb(), insb(), etc. include a check to see if the i/o read returned all-0xff's. If so, these make a call to eeh_dn_check_failure(), which in turn asks the firmware if the all-ff's value is the sign of a true EEH @@ -143,11 +143,12 @@ seen in /proc/ppc64/eeh (subject to change). Normally, almost all of these occur during boot, when the PCI bus is scanned, where a large number of 0xff reads are part of the bus scan procedure. -If a frozen slot is detected, code in arch/ppc64/kernel/eeh.c will -print a stack trace to syslog (/var/log/messages). This stack trace -has proven to be very useful to device-driver authors for finding -out at what point the EEH error was detected, as the error itself -usually occurs slightly beforehand. +If a frozen slot is detected, code in +arch/powerpc/platforms/pseries/eeh.c will print a stack trace to +syslog (/var/log/messages). This stack trace has proven to be very +useful to device-driver authors for finding out at what point the EEH +error was detected, as the error itself usually occurs slightly +beforehand. Next, it uses the Linux kernel notifier chain/work queue mechanism to allow any interested parties to find out about the failure. Device diff --git a/arch/powerpc/boot/install.sh b/arch/powerpc/boot/install.sh index eacce9590816..b002bfd56786 100644 --- a/arch/powerpc/boot/install.sh +++ b/arch/powerpc/boot/install.sh @@ -1,7 +1,5 @@ #!/bin/sh # -# arch/ppc64/boot/install.sh -# # 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. diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 388f861b8ed1..79a0c910f0d8 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/entry.S - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP @@ -374,7 +372,7 @@ _GLOBAL(ret_from_fork) * the fork code also. * * The code which creates the new task context is in 'copy_thread' - * in arch/ppc64/kernel/process.c + * in arch/powerpc/kernel/process.c */ .align 7 _GLOBAL(_switch) diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 8b49679fad54..47c7fa148c9a 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/head_44x.S - * * Kernel execution entry point code. * * Copyright (c) 1995-1996 Gary Thomas diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 415659629394..7ebb73665e9d 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/head.S - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index bc6d1ac55235..28941f5ce673 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/except_8xx.S - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 0abd05f14f87..dd86bbed7627 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/head_fsl_booke.S - * * Kernel execution entry point code. * * Copyright (c) 1995-1996 Gary Thomas diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index 6160c8dbb7c5..fd8214caedee 100644 --- a/arch/powerpc/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/iomap.c - * * ppc64 "iomap" interface implementation. * * (C) Copyright 2004 Linus Torvalds diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 946f3219fd29..d9a7fdef59b9 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -1,5 +1,4 @@ /* - * arch/ppc64/kernel/iommu.c * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * * Rewrite, cleanup, new allocation schemes, virtual merging: diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index d1fffce86df9..edb2b00edbd2 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/irq.c - * * Derived from arch/i386/kernel/irq.c * Copyright (C) 1992 Linus Torvalds * Adapted from arch/i386 by Gary Thomas diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index cfab48566db1..258039fb3016 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -1,6 +1,5 @@ /* * Kernel Probes (KProbes) - * arch/ppc64/kernel/kprobes.c * * 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/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index bdf15dbbf4f0..c336f3e31cff 100644 --- a/arch/powerpc/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c @@ -1,5 +1,4 @@ /* - * arch/ppc64/kernel/pci_iommu.c * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * * Rewrite, cleanup, new allocation schemes: diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 57703994a063..1201880cab40 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/process.c - * * Derived from "arch/i386/kernel/process.c" * Copyright (C) 1995 Linus Torvalds * diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h index 5ccbdbe0d5c9..c42a860c8d25 100644 --- a/arch/powerpc/kernel/ptrace-common.h +++ b/arch/powerpc/kernel/ptrace-common.h @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/kernel/ptrace-common.h - * * Copyright (c) 2002 Stephen Rothwell, IBM Coproration * Extracted from ptrace.c and ptrace32.c * diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 7a95b8a28354..1f03fb28cc0a 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c @@ -1,5 +1,4 @@ /* - * arch/ppc64/kernel/rtas-proc.c * Copyright (C) 2000 Tilmann Bitterberg * (tilmann@bitterberg.de) * diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 5579f6559912..03afb79e27e5 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/rtas_pci.c - * * Copyright (C) 2001 Dave Engebretsen, IBM Corporation * Copyright (C) 2003 Anton Blanchard , IBM * diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 497a5d3df359..59b9c9cdd6a9 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/kernel/signal.c - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index f0c47dab0903..b316fda58b89 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/kernel/vdso.c - * * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. * * diff --git a/arch/powerpc/lib/copypage_64.S b/arch/powerpc/lib/copypage_64.S index 40523b140109..f9837f44ac0b 100644 --- a/arch/powerpc/lib/copypage_64.S +++ b/arch/powerpc/lib/copypage_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/lib/copypage.S - * * Copyright (C) 2002 Paul Mackerras, IBM Corp. * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index 6d69ef39b7df..a6b54cb97c49 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/lib/copyuser.S - * * Copyright (C) 2002 Paul Mackerras, IBM Corp. * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/lib/e2a.c b/arch/powerpc/lib/e2a.c index d2b834887920..4f88f4cc21e8 100644 --- a/arch/powerpc/lib/e2a.c +++ b/arch/powerpc/lib/e2a.c @@ -1,9 +1,7 @@ /* - * arch/ppc64/lib/e2a.c - * * EBCDIC to ASCII conversion * - * This function moved here from arch/ppc64/kernel/viopath.c + * This function moved here from arch/powerpc/platforms/iseries/viopath.c * * (C) Copyright 2000-2004 IBM Corporation * diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S index 9ccacdf5bcb9..fd66acfd3e3e 100644 --- a/arch/powerpc/lib/memcpy_64.S +++ b/arch/powerpc/lib/memcpy_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/lib/memcpy.S - * * Copyright (C) 2002 Paul Mackerras, IBM Corp. * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c index 42c5de2c898f..31e511856dc5 100644 --- a/arch/powerpc/lib/rheap.c +++ b/arch/powerpc/lib/rheap.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/rheap.c - * * A Remote Heap. Remote means that we don't touch the memory that the * heap points to. Normal heap implementations use the memory they manage * to place their list. We cannot do that because the memory we manage may diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index a4815d316722..ec4adcb4bc28 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -1,6 +1,4 @@ /* - * arch/ppc/mm/fault.c - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S index 12ccd7155bac..ea469eefa146 100644 --- a/arch/powerpc/mm/hash_low_32.S +++ b/arch/powerpc/mm/hash_low_32.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/hashtable.S - * * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $ * * PowerPC version diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c index fe65f522aff3..972a8e884b9a 100644 --- a/arch/powerpc/mm/mmap.c +++ b/arch/powerpc/mm/mmap.c @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/mm/mmap.c - * * flexible mmap layout support * * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index d1acee38f163..abfaabf667bf 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/mm/slb_low.S - * * Low-level SLB routines * * Copyright (C) 2004 David Gibson , IBM diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index bb3afb6e6317..f734b11566c2 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c @@ -36,7 +36,7 @@ DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); /* This is declared as we are using the more or less generic - * include/asm-ppc64/tlb.h file -- tgall + * include/asm-powerpc/tlb.h file -- tgall */ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c index 29c86781c493..6ad4b1a72c96 100644 --- a/arch/powerpc/platforms/chrp/pegasos_eth.c +++ b/arch/powerpc/platforms/chrp/pegasos_eth.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chrp_pegasos_eth.c - * * Copyright (C) 2005 Sven Luther * Thanks to : * Dale Farnsworth diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index e1fadbf49150..8bf4307e323d 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 78df2e7ca88a..12c6f689b1aa 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chrp_time.c - * * Copyright (C) 1991, 1992, 1995 Linus Torvalds * * Adapted for PowerPC (PReP) by Gary Thomas diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 50bc4eb85353..5e6981d17379 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/maple_time.c - * * (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org), * IBM Corp. * diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index 56fd4e05fede..cfd6527a0d7e 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pmac_cpufreq.c - * * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt * Copyright (C) 2004 John Steele Scott * diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 558dd0692092..50ed8890dd33 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pmac_feature.c - * * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) * Ben. Herrenschmidt (benh@kernel.crashing.org) * diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index 3ebd045a3350..5fd28995c74c 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pmac_nvram.c - * * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 176e8da76466..db7c19fe9297 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/pSeries_hvCall.S - * * This file contains the generic code to perform a call to the * pSeries LPAR hypervisor. * NOTE: this file will go away when we move to inline this work. diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 48cfbfc43f99..57930e23cc74 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/pSeries_iommu.c - * * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * * Rewrite, cleanup: diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 999a9620b5ce..946ad59e3352 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/pSeries_pci.c - * * Copyright (C) 2001 Dave Engebretsen, IBM Corporation * Copyright (C) 2003 Anton Blanchard , IBM * diff --git a/arch/powerpc/sysdev/dcr.S b/arch/powerpc/sysdev/dcr.S index 895f10243a43..2078f39e2f17 100644 --- a/arch/powerpc/sysdev/dcr.S +++ b/arch/powerpc/sysdev/dcr.S @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/dcr.S - * * "Indirect" DCR access * * Copyright (c) 2004 Eugene Surovegin diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h index a7ce7da8785c..a60c9d18bb7f 100644 --- a/arch/powerpc/sysdev/ipic.h +++ b/arch/powerpc/sysdev/ipic.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ipic.h - * * IPIC private definitions and structure. * * Maintainer: Kumar Gala diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c index 8ace2a1f3b48..4dc6aa2abfc1 100644 --- a/arch/ppc/4xx_io/serial_sicc.c +++ b/arch/ppc/4xx_io/serial_sicc.c @@ -1,6 +1,4 @@ /* - * arch/ppc/4xx_io/serial_sicc.c - * * Driver for IBM STB3xxx SICC serial port * * Based on drivers/char/serial_amba.c, by ARM Ltd. diff --git a/arch/ppc/amiga/amiints.c b/arch/ppc/amiga/amiints.c index 5f35cf3986f7..b2bba052ab93 100644 --- a/arch/ppc/amiga/amiints.c +++ b/arch/ppc/amiga/amiints.c @@ -1,5 +1,5 @@ /* - * arch/ppc/amiga/amiints.c -- Amiga Linux interrupt handling code + * Amiga Linux interrupt handling code * * 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 diff --git a/arch/ppc/amiga/bootinfo.c b/arch/ppc/amiga/bootinfo.c index e2e965661d03..efd869a3ed9b 100644 --- a/arch/ppc/amiga/bootinfo.c +++ b/arch/ppc/amiga/bootinfo.c @@ -1,6 +1,4 @@ /* - * arch/ppc/amiga/bootinfo.c - * * Extracted from arch/m68k/kernel/setup.c. * Should be properly generalized and put somewhere else. * Jesper diff --git a/arch/ppc/amiga/cia.c b/arch/ppc/amiga/cia.c index 4431c58f611a..9558f2f40e64 100644 --- a/arch/ppc/amiga/cia.c +++ b/arch/ppc/amiga/cia.c @@ -1,6 +1,4 @@ /* - * arch/ppc/amiga/cia.c - CIA support - * * Copyright (C) 1996 Roman Zippel * * The concept of some functions bases on the original Amiga OS function diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c index 60e2da1c92c0..bbe47c9bd707 100644 --- a/arch/ppc/amiga/config.c +++ b/arch/ppc/amiga/config.c @@ -1,8 +1,6 @@ #define m68k_debug_device debug_device /* - * arch/ppc/amiga/config.c - * * Copyright (C) 1993 Hamish Macdonald * * This file is subject to the terms and conditions of the GNU General Public diff --git a/arch/ppc/amiga/ints.c b/arch/ppc/amiga/ints.c index 5d318e498f06..083a17462190 100644 --- a/arch/ppc/amiga/ints.c +++ b/arch/ppc/amiga/ints.c @@ -1,6 +1,4 @@ /* - * arch/ppc/amiga/ints.c - * * Linux/m68k general interrupt handling code from arch/m68k/kernel/ints.c * Needed to drive the m68k emulating IRQ hardware on the PowerUp boards. */ diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile index efd8ce515d5f..f565699a9fe0 100644 --- a/arch/ppc/boot/Makefile +++ b/arch/ppc/boot/Makefile @@ -1,6 +1,3 @@ -# -# arch/ppc/boot/Makefile -# # 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. diff --git a/arch/ppc/boot/common/Makefile b/arch/ppc/boot/common/Makefile index f88d647d5dd4..a2e85e3beb88 100644 --- a/arch/ppc/boot/common/Makefile +++ b/arch/ppc/boot/common/Makefile @@ -1,6 +1,3 @@ -# -# arch/ppc/boot/common/Makefile -# # 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. diff --git a/arch/ppc/boot/common/bootinfo.c b/arch/ppc/boot/common/bootinfo.c index 9c6e528940e9..f4dc9b9fab9c 100644 --- a/arch/ppc/boot/common/bootinfo.c +++ b/arch/ppc/boot/common/bootinfo.c @@ -1,6 +1,4 @@ /* - * arch/ppc/common/bootinfo.c - * * General bootinfo record utilities * Author: Randy Vinson * diff --git a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c index e79e6b3f276e..073830a8559a 100644 --- a/arch/ppc/boot/common/misc-common.c +++ b/arch/ppc/boot/common/misc-common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/common/misc-common.c - * * Misc. bootloader code (almost) all platforms can use * * Author: Johnnie Peters diff --git a/arch/ppc/boot/common/serial_stub.c b/arch/ppc/boot/common/serial_stub.c index 03dfaa01fa63..5cc9ae66a8ba 100644 --- a/arch/ppc/boot/common/serial_stub.c +++ b/arch/ppc/boot/common/serial_stub.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/common/serial_stub.c - * * This is a few stub routines to make the boot code cleaner looking when * there is no serial port support doesn't need to be closed, for example. * diff --git a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S index 368ec035e6cd..0c5e43c4ae06 100644 --- a/arch/ppc/boot/common/util.S +++ b/arch/ppc/boot/common/util.S @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/common/util.S - * * Useful bootup functions, which are more easily done in asm than C. * * NOTE: Be very very careful about the registers you use here. diff --git a/arch/ppc/boot/include/mpc10x.h b/arch/ppc/boot/include/mpc10x.h index 6cd40ecabc74..6e5d540d8d3e 100644 --- a/arch/ppc/boot/include/mpc10x.h +++ b/arch/ppc/boot/include/mpc10x.h @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/include/mpc10.h - * * Common defines for the Motorola SPS MPC106/8240/107 Host bridge/Mem * ctrl/EPIC/etc. * diff --git a/arch/ppc/boot/simple/cpc700_memory.c b/arch/ppc/boot/simple/cpc700_memory.c index 8c75cf6c2383..d75420a45a59 100644 --- a/arch/ppc/boot/simple/cpc700_memory.c +++ b/arch/ppc/boot/simple/cpc700_memory.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/common/cpc700_memory.c - * * Find memory based upon settings in the CPC700 bridge * * Author: Dan Cox diff --git a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S index 119b9dc89587..160da1006ff8 100644 --- a/arch/ppc/boot/simple/head.S +++ b/arch/ppc/boot/simple/head.S @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/head.S - * * Initial board bringup code for many different boards. * * Author: Tom Rini diff --git a/arch/ppc/boot/simple/misc-chestnut.c b/arch/ppc/boot/simple/misc-chestnut.c index 0dce7f3557e4..b94e142ad892 100644 --- a/arch/ppc/boot/simple/misc-chestnut.c +++ b/arch/ppc/boot/simple/misc-chestnut.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-chestnut.c - * * Setup for the IBM Chestnut (ibm-750fxgx_eval) * * Author: Mark A. Greer diff --git a/arch/ppc/boot/simple/misc-cpci690.c b/arch/ppc/boot/simple/misc-cpci690.c index 26860300fa09..8a8614d11a32 100644 --- a/arch/ppc/boot/simple/misc-cpci690.c +++ b/arch/ppc/boot/simple/misc-cpci690.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-cpci690.c - * * Add birec data for Force CPCI690 board. * * Author: Mark A. Greer diff --git a/arch/ppc/boot/simple/misc-ev64260.c b/arch/ppc/boot/simple/misc-ev64260.c index 52ece6937a7a..2678c224af22 100644 --- a/arch/ppc/boot/simple/misc-ev64260.c +++ b/arch/ppc/boot/simple/misc-ev64260.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-ev64260.c - * * Host bridge init code for the Marvell/Galileo EV-64260-BP evaluation board * with a GT64260 onboard. * diff --git a/arch/ppc/boot/simple/misc-ev64360.c b/arch/ppc/boot/simple/misc-ev64360.c index cd1ccf2a1582..a212b5b988cb 100644 --- a/arch/ppc/boot/simple/misc-ev64360.c +++ b/arch/ppc/boot/simple/misc-ev64360.c @@ -1,5 +1,4 @@ /* - * arch/ppc/boot/simple/misc-ev64360.c * Copyright (C) 2005 Lee Nicks * * Based on arch/ppc/boot/simple/misc-katana.c from: diff --git a/arch/ppc/boot/simple/misc-katana.c b/arch/ppc/boot/simple/misc-katana.c index ec94a11bacac..d97f2ee6f04e 100644 --- a/arch/ppc/boot/simple/misc-katana.c +++ b/arch/ppc/boot/simple/misc-katana.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-katana.c - * * Set up MPSC values to bootwrapper can prompt user. * * Author: Mark A. Greer diff --git a/arch/ppc/boot/simple/misc-mv64x60.c b/arch/ppc/boot/simple/misc-mv64x60.c index 258d4599fadc..71ff20fd494a 100644 --- a/arch/ppc/boot/simple/misc-mv64x60.c +++ b/arch/ppc/boot/simple/misc-mv64x60.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-mv64x60.c - * * Relocate bridge's register base and call board specific routine. * * Author: Mark A. Greer diff --git a/arch/ppc/boot/simple/misc-prep.c b/arch/ppc/boot/simple/misc-prep.c index 75380ac41669..63def9d13d70 100644 --- a/arch/ppc/boot/simple/misc-prep.c +++ b/arch/ppc/boot/simple/misc-prep.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-prep.c - * * Maintainer: Tom Rini * * In the past: Gary Thomas, Cort Dougan diff --git a/arch/ppc/boot/simple/misc-radstone_ppc7d.c b/arch/ppc/boot/simple/misc-radstone_ppc7d.c index 569e0d4feeaf..0f302ea9c3d1 100644 --- a/arch/ppc/boot/simple/misc-radstone_ppc7d.c +++ b/arch/ppc/boot/simple/misc-radstone_ppc7d.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/misc-radstone_ppc7d.c - * * Misc data for Radstone PPC7D board. * * Author: James Chapman diff --git a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c index d012c39278fd..0cad2f557a1e 100644 --- a/arch/ppc/boot/simple/misc-spruce.c +++ b/arch/ppc/boot/simple/misc-spruce.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/spruce/misc.c - * * Misc. bootloader code for IBM Spruce reference platform * * Authors: Johnnie Peters diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c index f415d6c62362..3d78571ad945 100644 --- a/arch/ppc/boot/simple/misc.c +++ b/arch/ppc/boot/simple/misc.c @@ -1,6 +1,4 @@ /* - * arch/ppc/simple/misc.c - * * Misc. bootloader code for many machines. This assumes you have are using * a 6xx/7xx/74xx CPU in your machine. This assumes the chunk of memory * below 8MB is free. Finally, it assumes you have a NS16550-style uart for diff --git a/arch/ppc/boot/simple/mpc10x_memory.c b/arch/ppc/boot/simple/mpc10x_memory.c index 20d92a34ceb8..c24290823f7f 100644 --- a/arch/ppc/boot/simple/mpc10x_memory.c +++ b/arch/ppc/boot/simple/mpc10x_memory.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/common/mpc10x_common.c - * * A routine to find out how much memory the machine has. * * Based on: diff --git a/arch/ppc/boot/simple/mpc52xx_tty.c b/arch/ppc/boot/simple/mpc52xx_tty.c index 3acc6b7c0727..1964493cf3bd 100644 --- a/arch/ppc/boot/simple/mpc52xx_tty.c +++ b/arch/ppc/boot/simple/mpc52xx_tty.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/mpc52xx_tty.c - * * Minimal serial functions needed to send messages out a MPC52xx * Programmable Serial Controller (PSC). * diff --git a/arch/ppc/boot/simple/mv64x60_tty.c b/arch/ppc/boot/simple/mv64x60_tty.c index b9c24d4c738b..0c52f5c784a2 100644 --- a/arch/ppc/boot/simple/mv64x60_tty.c +++ b/arch/ppc/boot/simple/mv64x60_tty.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/mv64x60_tty.c - * * Bootloader version of the embedded MPSC/UART driver for the Marvell 64x60. * Note: Due to a GT64260A erratum, DMA will be used for UART input (via SDMA). * diff --git a/arch/ppc/boot/simple/openbios.c b/arch/ppc/boot/simple/openbios.c index 81f11d8b30a7..3f2ed53f793a 100644 --- a/arch/ppc/boot/simple/openbios.c +++ b/arch/ppc/boot/simple/openbios.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/openbios.c - * * Copyright (c) 2005 DENX Software Engineering * Stefan Roese * diff --git a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S index 555a216ccc49..7efddc507564 100644 --- a/arch/ppc/boot/simple/relocate.S +++ b/arch/ppc/boot/simple/relocate.S @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/simple/relocate.S - * * This is the common part of the loader relocation and initialization * process. All of the board/processor specific initialization is * done before we get here. diff --git a/arch/ppc/boot/utils/mkbugboot.c b/arch/ppc/boot/utils/mkbugboot.c index 886122283f39..29115e01f60a 100644 --- a/arch/ppc/boot/utils/mkbugboot.c +++ b/arch/ppc/boot/utils/mkbugboot.c @@ -1,6 +1,4 @@ /* - * arch/ppc/boot/utils/mkbugboot.c - * * Makes a Motorola PPCBUG ROM bootable image which can be flashed * into one of the FLASH banks on a Motorola PowerPlus board. * diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 677c571aa276..0d8b88219d38 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/head_44x.S - * * Kernel execution entry point code. * * Copyright (c) 1995-1996 Gary Thomas diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index c1e89ad0684d..ec53c7d65f2b 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/except_8xx.S - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index 0abd05f14f87..dd86bbed7627 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/head_fsl_booke.S - * * Kernel execution entry point code. * * Copyright (c) 1995-1996 Gary Thomas diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 6d0a1838d94c..1c0d68026abd 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/traps.c - * * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * * This program is free software; you can redistribute it and/or diff --git a/arch/ppc/lib/rheap.c b/arch/ppc/lib/rheap.c index 42c5de2c898f..31e511856dc5 100644 --- a/arch/ppc/lib/rheap.c +++ b/arch/ppc/lib/rheap.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/rheap.c - * * A Remote Heap. Remote means that we don't touch the memory that the * heap points to. Normal heap implementations use the memory they manage * to place their list. We cannot do that because the memory we manage may diff --git a/arch/ppc/math-emu/math.c b/arch/ppc/math-emu/math.c index b7dff53a7103..589153472761 100644 --- a/arch/ppc/math-emu/math.c +++ b/arch/ppc/math-emu/math.c @@ -1,6 +1,4 @@ /* - * arch/ppc/math-emu/math.c - * * Copyright (C) 1999 Eddie C. Dost (ecd@atecom.com) */ diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index ee5e9f25baf9..0217188ef465 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c @@ -1,6 +1,4 @@ /* - * arch/ppc/mm/fault.c - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S index 3ec87c91343e..f09fa88db35a 100644 --- a/arch/ppc/mm/hashtable.S +++ b/arch/ppc/mm/hashtable.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/hashtable.S - * * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $ * * PowerPC version diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c index 0ec53f049338..b940cfd646c2 100644 --- a/arch/ppc/platforms/4xx/bamboo.c +++ b/arch/ppc/platforms/4xx/bamboo.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/bamboo.c - * * Bamboo board specific routines * * Wade Farnsworth diff --git a/arch/ppc/platforms/4xx/bamboo.h b/arch/ppc/platforms/4xx/bamboo.h index 5c0192826494..31c0dd6a26cb 100644 --- a/arch/ppc/platforms/4xx/bamboo.h +++ b/arch/ppc/platforms/4xx/bamboo.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/bamboo.h - * * Bamboo board definitions * * Wade Farnsworth diff --git a/arch/ppc/platforms/4xx/bubinga.h b/arch/ppc/platforms/4xx/bubinga.h index b5380cfaf5c0..606aa9fa5caa 100644 --- a/arch/ppc/platforms/4xx/bubinga.h +++ b/arch/ppc/platforms/4xx/bubinga.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/bubinga.h - * * Bubinga board definitions * * Copyright (c) 2005 DENX Software Engineering diff --git a/arch/ppc/platforms/4xx/cpci405.c b/arch/ppc/platforms/4xx/cpci405.c index ff966773a0bf..6571e39fbe48 100644 --- a/arch/ppc/platforms/4xx/cpci405.c +++ b/arch/ppc/platforms/4xx/cpci405.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/cpci405.c - * * Board setup routines for the esd CPCI-405 cPCI Board. * * Author: Stefan Roese diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c index 9a828b623417..b4ecb9c79854 100644 --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ebony.c - * * Ebony board specific routines * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h index b91ad4272dfe..27b2e77c7c83 100644 --- a/arch/ppc/platforms/4xx/ebony.h +++ b/arch/ppc/platforms/4xx/ebony.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ebony.h - * * Ebony board definitions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ep405.c b/arch/ppc/platforms/4xx/ep405.c index 26a07cdb30ec..6efa91ff9c07 100644 --- a/arch/ppc/platforms/4xx/ep405.c +++ b/arch/ppc/platforms/4xx/ep405.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ep405.c - * * Embedded Planet 405GP board * http://www.embeddedplanet.com * diff --git a/arch/ppc/platforms/4xx/ep405.h b/arch/ppc/platforms/4xx/ep405.h index ea3eb21338fb..9814fc431725 100644 --- a/arch/ppc/platforms/4xx/ep405.h +++ b/arch/ppc/platforms/4xx/ep405.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ep405.h - * * Embedded Planet 405GP board * http://www.embeddedplanet.com * diff --git a/arch/ppc/platforms/4xx/ibm405ep.c b/arch/ppc/platforms/4xx/ibm405ep.c index 093b28d27a41..55af769a6e70 100644 --- a/arch/ppc/platforms/4xx/ibm405ep.c +++ b/arch/ppc/platforms/4xx/ibm405ep.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ibm405ep.c - * * Support for IBM PPC 405EP processors. * * Author: SAW (IBM), derived from ibmnp405l.c. diff --git a/arch/ppc/platforms/4xx/ibm405ep.h b/arch/ppc/platforms/4xx/ibm405ep.h index e051e3fe8c63..fe46640de152 100644 --- a/arch/ppc/platforms/4xx/ibm405ep.h +++ b/arch/ppc/platforms/4xx/ibm405ep.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm405ep.h - * * IBM PPC 405EP processor defines. * * Author: SAW (IBM), derived from ibm405gp.h. diff --git a/arch/ppc/platforms/4xx/ibm405gp.h b/arch/ppc/platforms/4xx/ibm405gp.h index b2b642e81af7..eaf0ef57028d 100644 --- a/arch/ppc/platforms/4xx/ibm405gp.h +++ b/arch/ppc/platforms/4xx/ibm405gp.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm405gp.h - * * Author: Armin Kuster akuster@mvista.com * * 2001 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibm405gpr.c b/arch/ppc/platforms/4xx/ibm405gpr.c index cd0d00d8e8ee..49da61f6854a 100644 --- a/arch/ppc/platforms/4xx/ibm405gpr.c +++ b/arch/ppc/platforms/4xx/ibm405gpr.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm405gpr.c - * * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibm405gpr.h b/arch/ppc/platforms/4xx/ibm405gpr.h index 45412fb4368f..e90c5dde01d3 100644 --- a/arch/ppc/platforms/4xx/ibm405gpr.h +++ b/arch/ppc/platforms/4xx/ibm405gpr.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm405gpr.h - * * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibm440ep.c b/arch/ppc/platforms/4xx/ibm440ep.c index 65ac0b9c2d05..1fed6638c81f 100644 --- a/arch/ppc/platforms/4xx/ibm440ep.c +++ b/arch/ppc/platforms/4xx/ibm440ep.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440ep.c - * * PPC440EP I/O descriptions * * Wade Farnsworth diff --git a/arch/ppc/platforms/4xx/ibm440ep.h b/arch/ppc/platforms/4xx/ibm440ep.h index 97c80b8e3e10..61717e8a799e 100644 --- a/arch/ppc/platforms/4xx/ibm440ep.h +++ b/arch/ppc/platforms/4xx/ibm440ep.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440ep.h - * * PPC440EP definitions * * Wade Farnsworth diff --git a/arch/ppc/platforms/4xx/ibm440gp.c b/arch/ppc/platforms/4xx/ibm440gp.c index d926245e8b3e..b67a72e5c6fe 100644 --- a/arch/ppc/platforms/4xx/ibm440gp.c +++ b/arch/ppc/platforms/4xx/ibm440gp.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440gp.c - * * PPC440GP I/O descriptions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ibm440gp.h b/arch/ppc/platforms/4xx/ibm440gp.h index ae1efc03b295..7b2763b6024f 100644 --- a/arch/ppc/platforms/4xx/ibm440gp.h +++ b/arch/ppc/platforms/4xx/ibm440gp.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440gp.h - * * PPC440GP definitions * * Roland Dreier diff --git a/arch/ppc/platforms/4xx/ibm440gx.c b/arch/ppc/platforms/4xx/ibm440gx.c index d24c09ee7b18..685abffcb6ce 100644 --- a/arch/ppc/platforms/4xx/ibm440gx.c +++ b/arch/ppc/platforms/4xx/ibm440gx.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440gx.c - * * PPC440GX I/O descriptions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ibm440gx.h b/arch/ppc/platforms/4xx/ibm440gx.h index 0b59d8dcd03c..070a34efe1c7 100644 --- a/arch/ppc/platforms/4xx/ibm440gx.h +++ b/arch/ppc/platforms/4xx/ibm440gx.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ibm440gx.h - * * PPC440GX definitions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ibm440sp.c b/arch/ppc/platforms/4xx/ibm440sp.c index 71a0117d3597..de8f7ac5623c 100644 --- a/arch/ppc/platforms/4xx/ibm440sp.c +++ b/arch/ppc/platforms/4xx/ibm440sp.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440sp.c - * * PPC440SP I/O descriptions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ibm440sp.h b/arch/ppc/platforms/4xx/ibm440sp.h index c71e46a18b9e..77e8bb22c527 100644 --- a/arch/ppc/platforms/4xx/ibm440sp.h +++ b/arch/ppc/platforms/4xx/ibm440sp.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440sp.h - * * PPC440SP definitions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ibmnp405h.c b/arch/ppc/platforms/4xx/ibmnp405h.c index a477a78f4902..f1dcb0ac15b7 100644 --- a/arch/ppc/platforms/4xx/ibmnp405h.c +++ b/arch/ppc/platforms/4xx/ibmnp405h.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmnp405h.c - * * Author: Armin Kuster * * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibmnp405h.h b/arch/ppc/platforms/4xx/ibmnp405h.h index e2c2b06128c8..2c683f6aaa66 100644 --- a/arch/ppc/platforms/4xx/ibmnp405h.h +++ b/arch/ppc/platforms/4xx/ibmnp405h.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmnp405h.h - * * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibmstb4.c b/arch/ppc/platforms/4xx/ibmstb4.c index 7e33bb635443..799a2eccccc3 100644 --- a/arch/ppc/platforms/4xx/ibmstb4.c +++ b/arch/ppc/platforms/4xx/ibmstb4.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmstb4.c - * * Author: Armin Kuster * * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibmstb4.h b/arch/ppc/platforms/4xx/ibmstb4.h index 9f21d4c88a3d..9de426597351 100644 --- a/arch/ppc/platforms/4xx/ibmstb4.h +++ b/arch/ppc/platforms/4xx/ibmstb4.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmstb4.h - * * Author: Armin Kuster * * 2001 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibmstbx25.c b/arch/ppc/platforms/4xx/ibmstbx25.c index b895b9cca57d..090ddcbecc5e 100644 --- a/arch/ppc/platforms/4xx/ibmstbx25.c +++ b/arch/ppc/platforms/4xx/ibmstbx25.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmstbx25.c - * * Author: Armin Kuster * * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/ibmstbx25.h b/arch/ppc/platforms/4xx/ibmstbx25.h index 9a2efc366e9c..6884a49d3482 100644 --- a/arch/ppc/platforms/4xx/ibmstbx25.h +++ b/arch/ppc/platforms/4xx/ibmstbx25.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibmstbx25.h - * * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c index 21d29132aebd..5c37de28e135 100644 --- a/arch/ppc/platforms/4xx/luan.c +++ b/arch/ppc/platforms/4xx/luan.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/luan.c - * * Luan board specific routines * * Matt Porter diff --git a/arch/ppc/platforms/4xx/luan.h b/arch/ppc/platforms/4xx/luan.h index bbe7d0766db8..e0db6a810feb 100644 --- a/arch/ppc/platforms/4xx/luan.h +++ b/arch/ppc/platforms/4xx/luan.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/luan.h - * * Luan board definitions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index 4f355b6acab2..f841972f1fa9 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ocotea.c - * * Ocotea board specific routines * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h index 33251153ac5f..7c799a9ff82b 100644 --- a/arch/ppc/platforms/4xx/ocotea.h +++ b/arch/ppc/platforms/4xx/ocotea.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ocotea.h - * * Ocotea board definitions * * Matt Porter diff --git a/arch/ppc/platforms/4xx/ppc440spe.c b/arch/ppc/platforms/4xx/ppc440spe.c index 6139a0b3393e..1be5d1c8e266 100644 --- a/arch/ppc/platforms/4xx/ppc440spe.c +++ b/arch/ppc/platforms/4xx/ppc440spe.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ppc440spe.c - * * PPC440SPe I/O descriptions * * Roland Dreier diff --git a/arch/ppc/platforms/4xx/ppc440spe.h b/arch/ppc/platforms/4xx/ppc440spe.h index 2216846973b8..d3a620ddcdee 100644 --- a/arch/ppc/platforms/4xx/ppc440spe.h +++ b/arch/ppc/platforms/4xx/ppc440spe.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/ibm440spe.h - * * PPC440SPe definitions * * Roland Dreier diff --git a/arch/ppc/platforms/4xx/redwood5.c b/arch/ppc/platforms/4xx/redwood5.c index 611ac861804d..53da2b4f7c24 100644 --- a/arch/ppc/platforms/4xx/redwood5.c +++ b/arch/ppc/platforms/4xx/redwood5.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/redwood5.c - * * Support for the IBM redwood5 eval board file * * Author: Armin Kuster diff --git a/arch/ppc/platforms/4xx/redwood5.h b/arch/ppc/platforms/4xx/redwood5.h index 264e34fb3fbd..49edd4818970 100644 --- a/arch/ppc/platforms/4xx/redwood5.h +++ b/arch/ppc/platforms/4xx/redwood5.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/redwood5.h - * * Macros, definitions, and data structures specific to the IBM PowerPC * STB03xxx "Redwood" evaluation board. * diff --git a/arch/ppc/platforms/4xx/redwood6.c b/arch/ppc/platforms/4xx/redwood6.c index b13116691289..41b27d106fa3 100644 --- a/arch/ppc/platforms/4xx/redwood6.c +++ b/arch/ppc/platforms/4xx/redwood6.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/redwood6.c - * * Author: Armin Kuster * * 2002 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/4xx/redwood6.h b/arch/ppc/platforms/4xx/redwood6.h index 1814b9f5fc3a..1edcbe5c51c7 100644 --- a/arch/ppc/platforms/4xx/redwood6.h +++ b/arch/ppc/platforms/4xx/redwood6.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/redwood6.h - * * Macros, definitions, and data structures specific to the IBM PowerPC * STBx25xx "Redwood6" evaluation board. * diff --git a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c index 281b4a2ffb96..bab31eb30687 100644 --- a/arch/ppc/platforms/4xx/sycamore.c +++ b/arch/ppc/platforms/4xx/sycamore.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/sycamore.c - * * Architecture- / platform-specific boot-time initialization code for * IBM PowerPC 4xx based boards. * diff --git a/arch/ppc/platforms/4xx/sycamore.h b/arch/ppc/platforms/4xx/sycamore.h index 1cd6c824fd62..dae01620227d 100644 --- a/arch/ppc/platforms/4xx/sycamore.h +++ b/arch/ppc/platforms/4xx/sycamore.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/sycamore.h - * * Sycamore board definitions * * Copyright (c) 2005 DENX Software Engineering diff --git a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c index 74cb33182d9f..6bd77902b9a4 100644 --- a/arch/ppc/platforms/4xx/walnut.c +++ b/arch/ppc/platforms/4xx/walnut.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/walnut.c - * * Architecture- / platform-specific boot-time initialization code for * IBM PowerPC 4xx based boards. Adapted from original * code by Gary Thomas, Cort Dougan , and Dan Malek diff --git a/arch/ppc/platforms/4xx/walnut.h b/arch/ppc/platforms/4xx/walnut.h index dcf2691698c0..f13a577f0a41 100644 --- a/arch/ppc/platforms/4xx/walnut.h +++ b/arch/ppc/platforms/4xx/walnut.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/walnut.h - * * Walnut board definitions * * Copyright (c) 2005 DENX Software Engineering diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c index 267afb50607e..d97a7f269f97 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml300.c +++ b/arch/ppc/platforms/4xx/xilinx_ml300.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/xilinx_ml300.c - * * Xilinx ML300 evaluation board initialization * * Author: MontaVista Software, Inc. diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.h b/arch/ppc/platforms/4xx/xilinx_ml300.h index ae8bf1353b01..3d57332ba820 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml300.h +++ b/arch/ppc/platforms/4xx/xilinx_ml300.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/xilinx_ml300.h - * * Include file that defines the Xilinx ML300 evaluation board * * Author: MontaVista Software, Inc. diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c index b065b8babcd3..f287dcdbffce 100644 --- a/arch/ppc/platforms/4xx/yucca.c +++ b/arch/ppc/platforms/4xx/yucca.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/yucca.c - * * Yucca board specific routines * * Roland Dreier (based on luan.c by Matt Porter) diff --git a/arch/ppc/platforms/4xx/yucca.h b/arch/ppc/platforms/4xx/yucca.h index 01a4afea1514..7ae23012237a 100644 --- a/arch/ppc/platforms/4xx/yucca.h +++ b/arch/ppc/platforms/4xx/yucca.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/4xx/yucca.h - * * Yucca board definitions * * Roland Dreier (based on luan.h by Matt Porter) diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 1a659bbc1860..11626dd9090f 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/83xx/mpc834x_sys.c - * * MPC834x SYS board specific routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h index 2e514d316fb8..aa86c22cdd25 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.h +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/83xx/mpc834x_sys.h - * * MPC834X SYS common board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index 408d64f18e1a..9b014df516b9 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc8540_ads.c - * * MPC8540ADS board specific routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.h b/arch/ppc/platforms/85xx/mpc8540_ads.h index e48ca3a97397..0b5e7ff856f5 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.h +++ b/arch/ppc/platforms/85xx/mpc8540_ads.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc8540_ads.h - * * MPC8540ADS board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc8555_cds.h b/arch/ppc/platforms/85xx/mpc8555_cds.h index 1a8e6c67355d..9754dbd5d18c 100644 --- a/arch/ppc/platforms/85xx/mpc8555_cds.h +++ b/arch/ppc/platforms/85xx/mpc8555_cds.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/mpc8555_cds.h - * * MPC8555CDS board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 442c7ff195d3..0cb2e86470e2 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc8560_ads.c - * * MPC8560ADS board specific routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.h b/arch/ppc/platforms/85xx/mpc8560_ads.h index 143ae7eefa7c..c2247c21fc53 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.h +++ b/arch/ppc/platforms/85xx/mpc8560_ads.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/mpc8560_ads.h - * * MPC8540ADS board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c index 17ce48fe3503..8fd9d763f58d 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc85xx_ads_common.c - * * MPC85xx ADS board common routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h index 198a6a02cde8..de8d41aafe11 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc85xx_ads_common.h - * * MPC85XX ADS common board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 1801ab392e22..c9e0aeeca3d8 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platform/85xx/mpc85xx_cds_common.c - * * MPC85xx CDS board specific routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h index 5b588cfd0e41..62df54f61ae3 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc85xx_cds_common.h - * * MPC85xx CDS board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index 8a72221f816c..b73778ecf827 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/sbc8560.c - * * Wind River SBC8560 board specific routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/platforms/85xx/sbc8560.h b/arch/ppc/platforms/85xx/sbc8560.h index 5e1b00c77da5..44ffaa2d2c87 100644 --- a/arch/ppc/platforms/85xx/sbc8560.h +++ b/arch/ppc/platforms/85xx/sbc8560.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/sbc8560.h - * * Wind River SBC8560 board definitions * * Copyright 2003 Motorola Inc. diff --git a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c index c02f110219f5..d3ff280510ff 100644 --- a/arch/ppc/platforms/85xx/sbc85xx.c +++ b/arch/ppc/platforms/85xx/sbc85xx.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platform/85xx/sbc85xx.c - * * WindRiver PowerQUICC III SBC85xx board common routines * * Copyright 2002, 2003 Motorola Inc. diff --git a/arch/ppc/platforms/85xx/sbc85xx.h b/arch/ppc/platforms/85xx/sbc85xx.h index 7af93c691a6b..5dd8b6a98c9b 100644 --- a/arch/ppc/platforms/85xx/sbc85xx.h +++ b/arch/ppc/platforms/85xx/sbc85xx.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/sbc85xx.h - * * WindRiver PowerQUICC III SBC85xx common board definitions * * Copyright 2003 Motorola Inc. diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index 061bb7cf2d9a..8d7baa9a397a 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/stx_gp3.c - * * STx GP3 board specific routines * * Dan Malek diff --git a/arch/ppc/platforms/85xx/stx_gp3.h b/arch/ppc/platforms/85xx/stx_gp3.h index 2f25b5195152..3f71f8f59370 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.h +++ b/arch/ppc/platforms/85xx/stx_gp3.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/stx8560_gp3.h - * * STx GP3 board definitions * * Dan Malek (dan@embeddededge.com) diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c index a5e38ba62732..00af132262b3 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.c +++ b/arch/ppc/platforms/85xx/tqm85xx.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/tqm85xx.c - * * TQM85xx (40/41/55/60) board specific routines * * Copyright (c) 2005 DENX Software Engineering diff --git a/arch/ppc/platforms/85xx/tqm85xx.h b/arch/ppc/platforms/85xx/tqm85xx.h index 3775eb363fde..612d80504f9b 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.h +++ b/arch/ppc/platforms/85xx/tqm85xx.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/tqm85xx.h - * * TQM85xx (40/41/55/60) board definitions * * Copyright (c) 2005 DENX Software Engineering diff --git a/arch/ppc/platforms/apus_setup.c b/arch/ppc/platforms/apus_setup.c index c42c50073da5..fe0cdc04d436 100644 --- a/arch/ppc/platforms/apus_setup.c +++ b/arch/ppc/platforms/apus_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/apus_setup.c - * * Copyright (C) 1998, 1999 Jesper Skov * * Basically what is needed to replace functionality found in diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c index aefcc0e7be57..f324f757cae1 100644 --- a/arch/ppc/platforms/chestnut.c +++ b/arch/ppc/platforms/chestnut.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chestnut.c - * * Board setup routines for IBM Chestnut * * Author: diff --git a/arch/ppc/platforms/chestnut.h b/arch/ppc/platforms/chestnut.h index 0400b2be40ab..e00fd9f8bbd0 100644 --- a/arch/ppc/platforms/chestnut.h +++ b/arch/ppc/platforms/chestnut.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chestnut.h - * * Definitions for IBM 750FXGX Eval (Chestnut) * * Author: diff --git a/arch/ppc/platforms/chrp_pegasos_eth.c b/arch/ppc/platforms/chrp_pegasos_eth.c index 108a6e265185..9305c8aa1373 100644 --- a/arch/ppc/platforms/chrp_pegasos_eth.c +++ b/arch/ppc/platforms/chrp_pegasos_eth.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chrp_pegasos_eth.c - * * Copyright (C) 2005 Sven Luther * Thanks to : * Dale Farnsworth diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c index 48996b787378..f9fd3f4f8e2e 100644 --- a/arch/ppc/platforms/chrp_setup.c +++ b/arch/ppc/platforms/chrp_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c index 57753a55b580..c8627770af13 100644 --- a/arch/ppc/platforms/chrp_time.c +++ b/arch/ppc/platforms/chrp_time.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chrp_time.c - * * Copyright (C) 1991, 1992, 1995 Linus Torvalds * * Adapted for PowerPC (PReP) by Gary Thomas diff --git a/arch/ppc/platforms/cpci690.c b/arch/ppc/platforms/cpci690.c index 6ca7bcac9474..55be550a0811 100644 --- a/arch/ppc/platforms/cpci690.c +++ b/arch/ppc/platforms/cpci690.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/cpci690.c - * * Board setup routines for the Force CPCI690 board. * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/cpci690.h b/arch/ppc/platforms/cpci690.h index 49584c9cedf3..0fa5a4c31b67 100644 --- a/arch/ppc/platforms/cpci690.h +++ b/arch/ppc/platforms/cpci690.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/cpci690.h - * * Definitions for Force CPCI690 * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c index ffde8f6f6302..6444760caa3a 100644 --- a/arch/ppc/platforms/ev64260.c +++ b/arch/ppc/platforms/ev64260.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ev64260.c - * * Board setup routines for the Marvell/Galileo EV-64260-BP Evaluation Board. * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/ev64260.h b/arch/ppc/platforms/ev64260.h index bedffced3a02..44d90d56745a 100644 --- a/arch/ppc/platforms/ev64260.h +++ b/arch/ppc/platforms/ev64260.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ev64260.h - * * Definitions for Marvell/Galileo EV-64260-BP Evaluation Board. * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c index b9d844f88c2b..b5f52eba4fc1 100644 --- a/arch/ppc/platforms/ev64360.c +++ b/arch/ppc/platforms/ev64360.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ev64360.c - * * Board setup routines for the Marvell EV-64360-BP Evaluation Board. * * Author: Lee Nicks diff --git a/arch/ppc/platforms/ev64360.h b/arch/ppc/platforms/ev64360.h index 68eabe490397..b30f4722690a 100644 --- a/arch/ppc/platforms/ev64360.h +++ b/arch/ppc/platforms/ev64360.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/ev64360.h - * * Definitions for Marvell EV-64360-BP Evaluation Board. * * Author: Lee Nicks diff --git a/arch/ppc/platforms/gemini.h b/arch/ppc/platforms/gemini.h index 06de59248918..5528fd0a1216 100644 --- a/arch/ppc/platforms/gemini.h +++ b/arch/ppc/platforms/gemini.h @@ -1,7 +1,4 @@ /* - * arch/ppc/platforms/gemini.h - * - * * Onboard registers and descriptions for Synergy Microsystems' * "Gemini" boards. * diff --git a/arch/ppc/platforms/gemini_prom.S b/arch/ppc/platforms/gemini_prom.S index 8c5065d56505..b181f2108001 100644 --- a/arch/ppc/platforms/gemini_prom.S +++ b/arch/ppc/platforms/gemini_prom.S @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/gemini_prom.S - * * Not really prom support code (yet), but sort of anti-prom code. The current * bootloader does a number of things it shouldn't and doesn't do things that it * should. The stuff in here is mainly a hodge-podge collection of setup code diff --git a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c index 729897c59033..0090ff154608 100644 --- a/arch/ppc/platforms/gemini_setup.c +++ b/arch/ppc/platforms/gemini_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/gemini_setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c index 50039a204c24..220674d883df 100644 --- a/arch/ppc/platforms/hdpu.c +++ b/arch/ppc/platforms/hdpu.c @@ -1,7 +1,4 @@ - /* - * arch/ppc/platforms/hdpu_setup.c - * * Board setup routines for the Sky Computers HDPU Compute Blade. * * Written by Brian Waite diff --git a/arch/ppc/platforms/hdpu.h b/arch/ppc/platforms/hdpu.h index 07c3cffb5c7b..f9e020b6970c 100644 --- a/arch/ppc/platforms/hdpu.h +++ b/arch/ppc/platforms/hdpu.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/hdpu.h - * * Definitions for Sky Computers HDPU board. * * Brian Waite diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c index 6e58e30ceed1..d2766617c3cb 100644 --- a/arch/ppc/platforms/katana.c +++ b/arch/ppc/platforms/katana.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/katana.c - * * Board setup routines for the Artesyn Katana cPCI boards. * * Author: Tim Montgomery diff --git a/arch/ppc/platforms/katana.h b/arch/ppc/platforms/katana.h index 597257eff2ec..0a9b036526b1 100644 --- a/arch/ppc/platforms/katana.h +++ b/arch/ppc/platforms/katana.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/katana.h - * * Definitions for Artesyn Katana750i/3750 board. * * Author: Tim Montgomery diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c index 7ed52dc340c9..5171b53bccb5 100644 --- a/arch/ppc/platforms/lite5200.c +++ b/arch/ppc/platforms/lite5200.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/lite5200.c - * * Platform support file for the Freescale LITE5200 based on MPC52xx. * A maximum of this file should be moved to syslib/mpc52xx_????? * so that new platform based on MPC52xx need a minimal platform file diff --git a/arch/ppc/platforms/lite5200.h b/arch/ppc/platforms/lite5200.h index c1de2aa47175..852a18e24d0b 100644 --- a/arch/ppc/platforms/lite5200.h +++ b/arch/ppc/platforms/lite5200.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/lite5200.h - * * Definitions for Freescale LITE5200 : MPC52xx Standard Development * Platform board support * diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c index 06d247c23b82..c6445a727ca3 100644 --- a/arch/ppc/platforms/lopec.c +++ b/arch/ppc/platforms/lopec.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/lopec.c - * * Setup routines for the Motorola LoPEC. * * Author: Dan Cox diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c index 108eb182dddc..c717cd92c028 100644 --- a/arch/ppc/platforms/mvme5100.c +++ b/arch/ppc/platforms/mvme5100.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/mvme5100.c - * * Board setup routines for the Motorola MVME5100. * * Author: Matt Porter diff --git a/arch/ppc/platforms/pal4.h b/arch/ppc/platforms/pal4.h index 641a11a31657..8569c423d887 100644 --- a/arch/ppc/platforms/pal4.h +++ b/arch/ppc/platforms/pal4.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pal4.h - * * Definitions for SBS Palomar IV board * * Author: Dan Cox diff --git a/arch/ppc/platforms/pal4_pci.c b/arch/ppc/platforms/pal4_pci.c index c3b1b757a48b..d81ae1c7e1cf 100644 --- a/arch/ppc/platforms/pal4_pci.c +++ b/arch/ppc/platforms/pal4_pci.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pal4_pci.c - * * PCI support for SBS Palomar IV * * Author: Dan Cox diff --git a/arch/ppc/platforms/pal4_serial.h b/arch/ppc/platforms/pal4_serial.h index a715c66e1adf..a75343224cfd 100644 --- a/arch/ppc/platforms/pal4_serial.h +++ b/arch/ppc/platforms/pal4_serial.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pal4_serial.h - * * Definitions for SBS PalomarIV serial support * * Author: Dan Cox diff --git a/arch/ppc/platforms/pal4_setup.c b/arch/ppc/platforms/pal4_setup.c index f93a3f871932..3c3d881df00d 100644 --- a/arch/ppc/platforms/pal4_setup.c +++ b/arch/ppc/platforms/pal4_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pal4_setup.c - * * Board setup routines for the SBS PalomarIV. * * Author: Dan Cox diff --git a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c index e6b520e6e13f..c3a86be11fb7 100644 --- a/arch/ppc/platforms/powerpmc250.c +++ b/arch/ppc/platforms/powerpmc250.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/powerpmc250.c - * * Board setup routines for Force PowerPMC-250 Processor PMC * * Author: Troy Benjegerdes diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c index 22bd40cfb092..de2761ebe0d9 100644 --- a/arch/ppc/platforms/pplus.c +++ b/arch/ppc/platforms/pplus.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pplus.c - * * Board and PCI setup routines for MCG PowerPlus * * Author: Randy Vinson diff --git a/arch/ppc/platforms/pplus.h b/arch/ppc/platforms/pplus.h index 90f0cb2d409f..a07cbbdd72c6 100644 --- a/arch/ppc/platforms/pplus.h +++ b/arch/ppc/platforms/pplus.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pplus.h - * * Definitions for Motorola MCG Falcon/Raven & HAWK North Bridge & Memory ctlr. * * Author: Mark A. Greerinclude/asm-ppc/hawk.h diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c index 71c9fca1fe9b..3365fd788a7a 100644 --- a/arch/ppc/platforms/pq2ads.c +++ b/arch/ppc/platforms/pq2ads.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pq2ads.c - * * PQ2ADS platform support * * Author: Kumar Gala diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index d06535802003..a0fc628ffb1e 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c index 0bb14a5e824c..cdd9cfb13ee9 100644 --- a/arch/ppc/platforms/prpmc750.c +++ b/arch/ppc/platforms/prpmc750.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/prpmc750_setup.c - * * Board setup routines for Motorola PrPMC750 * * Author: Matt Porter diff --git a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c index de7baefacd3a..e459a199fb1d 100644 --- a/arch/ppc/platforms/prpmc800.c +++ b/arch/ppc/platforms/prpmc800.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/prpmc800.c - * * Author: Dale Farnsworth * * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c index 872c0a3ba3c7..1b1e7c5ef152 100644 --- a/arch/ppc/platforms/radstone_ppc7d.c +++ b/arch/ppc/platforms/radstone_ppc7d.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/radstone_ppc7d.c - * * Board setup routines for the Radstone PPC7D boards. * * Author: James Chapman diff --git a/arch/ppc/platforms/radstone_ppc7d.h b/arch/ppc/platforms/radstone_ppc7d.h index 938375510be4..2bb093a0c03e 100644 --- a/arch/ppc/platforms/radstone_ppc7d.h +++ b/arch/ppc/platforms/radstone_ppc7d.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/radstone_ppc7d.h - * * Board definitions for the Radstone PPC7D boards. * * Author: James Chapman diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c index 9eeed3572309..6dc459decb2d 100644 --- a/arch/ppc/platforms/sandpoint.c +++ b/arch/ppc/platforms/sandpoint.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/sandpoint_setup.c - * * Board setup routines for the Motorola SPS Sandpoint Test Platform. * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/sandpoint.h b/arch/ppc/platforms/sandpoint.h index f4e982cb69df..3b64e6418489 100644 --- a/arch/ppc/platforms/sandpoint.h +++ b/arch/ppc/platforms/sandpoint.h @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/sandpoint.h - * * Definitions for Motorola SPS Sandpoint Test Platform * * Author: Mark A. Greer diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c index 74c9ff72c3dd..866807b4ad0b 100644 --- a/arch/ppc/platforms/sbc82xx.c +++ b/arch/ppc/platforms/sbc82xx.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/sbc82xx.c - * * SBC82XX platform support * * Author: Guy Streeter diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c index 69e1de7971f2..3783deccd9b2 100644 --- a/arch/ppc/platforms/spruce.c +++ b/arch/ppc/platforms/spruce.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/spruce.c - * * Board and PCI setup routines for IBM Spruce * * Author: MontaVista Software diff --git a/arch/ppc/platforms/tqm8260_setup.c b/arch/ppc/platforms/tqm8260_setup.c index 3409139330b1..b766339f44ac 100644 --- a/arch/ppc/platforms/tqm8260_setup.c +++ b/arch/ppc/platforms/tqm8260_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/tqm8260_setup.c - * * TQM8260 platform support * * Author: Allen Curtis diff --git a/arch/ppc/syslib/cpc700.h b/arch/ppc/syslib/cpc700.h index f2c002531019..0a8a5d84390f 100644 --- a/arch/ppc/syslib/cpc700.h +++ b/arch/ppc/syslib/cpc700.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/cpc700.h - * * Header file for IBM CPC700 Host Bridge, et. al. * * Author: Mark A. Greer diff --git a/arch/ppc/syslib/cpc700_pic.c b/arch/ppc/syslib/cpc700_pic.c index 75fe8eb10693..5add0a919ef6 100644 --- a/arch/ppc/syslib/cpc700_pic.c +++ b/arch/ppc/syslib/cpc700_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/cpc700_pic.c - * * Interrupt controller support for IBM Spruce * * Authors: Mark Greer, Matt Porter, and Johnnie Peters diff --git a/arch/ppc/syslib/cpc710.h b/arch/ppc/syslib/cpc710.h index cc0afd804029..5299bf8b5d01 100644 --- a/arch/ppc/syslib/cpc710.h +++ b/arch/ppc/syslib/cpc710.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/cpc710.h - * * Definitions for the IBM CPC710 PCI Host Bridge * * Author: Matt Porter diff --git a/arch/ppc/syslib/gen550.h b/arch/ppc/syslib/gen550.h index 039d249e19a8..5254d3cdbca6 100644 --- a/arch/ppc/syslib/gen550.h +++ b/arch/ppc/syslib/gen550.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/gen550.h - * * gen550 prototypes * * Matt Porter diff --git a/arch/ppc/syslib/gen550_dbg.c b/arch/ppc/syslib/gen550_dbg.c index 9ef0113c83d1..9fcff74bfdd0 100644 --- a/arch/ppc/syslib/gen550_dbg.c +++ b/arch/ppc/syslib/gen550_dbg.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/gen550_dbg.c - * * A library of polled 16550 serial routines. These are intended to * be used to support progress messages, xmon, kgdb, etc. on a * variety of platforms. diff --git a/arch/ppc/syslib/gen550_kgdb.c b/arch/ppc/syslib/gen550_kgdb.c index 7239d5d7ddcd..874078a7664d 100644 --- a/arch/ppc/syslib/gen550_kgdb.c +++ b/arch/ppc/syslib/gen550_kgdb.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/gen550_kgdb.c - * * Generic 16550 kgdb support intended to be useful on a variety * of platforms. To enable this support, it is necessary to set * the CONFIG_GEN550 option. Any virtual mapping of the serial diff --git a/arch/ppc/syslib/gt64260_pic.c b/arch/ppc/syslib/gt64260_pic.c index f97b3a9abd1e..dc3bd9ecbbf6 100644 --- a/arch/ppc/syslib/gt64260_pic.c +++ b/arch/ppc/syslib/gt64260_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/gt64260_pic.c - * * Interrupt controller support for Galileo's GT64260. * * Author: Chris Zankel diff --git a/arch/ppc/syslib/harrier.c b/arch/ppc/syslib/harrier.c index a6b3f8645793..c1583f488325 100644 --- a/arch/ppc/syslib/harrier.c +++ b/arch/ppc/syslib/harrier.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/harrier.c - * * Motorola MCG Harrier northbridge/memory controller support * * Author: Dale Farnsworth diff --git a/arch/ppc/syslib/hawk_common.c b/arch/ppc/syslib/hawk_common.c index a9911dc3a82f..c5bf16b0d6a1 100644 --- a/arch/ppc/syslib/hawk_common.c +++ b/arch/ppc/syslib/hawk_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/hawk_common.c - * * Common Motorola PowerPlus Platform--really Falcon/Raven or HAWK. * * Author: Mark A. Greer diff --git a/arch/ppc/syslib/ibm440gp_common.c b/arch/ppc/syslib/ibm440gp_common.c index 0d6be2d6dd67..fbaae5f6d834 100644 --- a/arch/ppc/syslib/ibm440gp_common.c +++ b/arch/ppc/syslib/ibm440gp_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ibm440gp_common.c - * * PPC440GP system library * * Matt Porter diff --git a/arch/ppc/syslib/ibm440gp_common.h b/arch/ppc/syslib/ibm440gp_common.h index a054d83cb1ac..f48529f3c23d 100644 --- a/arch/ppc/syslib/ibm440gp_common.h +++ b/arch/ppc/syslib/ibm440gp_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ibm440gp_common.h - * * PPC440GP system library * * Eugene Surovegin or diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c index c36db279b43d..a7dd55f1c63e 100644 --- a/arch/ppc/syslib/ibm440gx_common.c +++ b/arch/ppc/syslib/ibm440gx_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ibm440gx_common.c - * * PPC440GX system library * * Eugene Surovegin or diff --git a/arch/ppc/syslib/ibm440gx_common.h b/arch/ppc/syslib/ibm440gx_common.h index e73aa0411d35..a2ab9fab8e34 100644 --- a/arch/ppc/syslib/ibm440gx_common.h +++ b/arch/ppc/syslib/ibm440gx_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ibm440gx_common.h - * * PPC440GX system library * * Eugene Surovegin or diff --git a/arch/ppc/syslib/ibm440sp_common.c b/arch/ppc/syslib/ibm440sp_common.c index cdafda127d81..293e4138d172 100644 --- a/arch/ppc/syslib/ibm440sp_common.c +++ b/arch/ppc/syslib/ibm440sp_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ibm440sp_common.c - * * PPC440SP/PPC440SPe system library * * Matt Porter diff --git a/arch/ppc/syslib/ibm440sp_common.h b/arch/ppc/syslib/ibm440sp_common.h index a21a9906dcc9..8077bf8ed118 100644 --- a/arch/ppc/syslib/ibm440sp_common.h +++ b/arch/ppc/syslib/ibm440sp_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ibm440sp_common.h - * * PPC440SP system library * * Matt Porter diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c index 71db11d22158..14a981a5cea7 100644 --- a/arch/ppc/syslib/ibm44x_common.c +++ b/arch/ppc/syslib/ibm44x_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ibm44x_common.c - * * PPC44x system library * * Matt Porter diff --git a/arch/ppc/syslib/ibm44x_common.h b/arch/ppc/syslib/ibm44x_common.h index b25a8995e4e9..f179db8634e0 100644 --- a/arch/ppc/syslib/ibm44x_common.h +++ b/arch/ppc/syslib/ibm44x_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ibm44x_common.h - * * PPC44x system library * * Eugene Surovegin or diff --git a/arch/ppc/syslib/m8260_pci_erratum9.c b/arch/ppc/syslib/m8260_pci_erratum9.c index 1dc7e4e1d491..99e4bc0e42af 100644 --- a/arch/ppc/syslib/m8260_pci_erratum9.c +++ b/arch/ppc/syslib/m8260_pci_erratum9.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/mpc8260_pci9.c - * * Workaround for device erratum PCI 9. * See Motorola's "XPC826xA Family Device Errata Reference." * The erratum applies to all 8260 family Hip4 processors. It is scheduled diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c index 76a2aa4ce65e..b7a6cb2d8d52 100644 --- a/arch/ppc/syslib/m8260_setup.c +++ b/arch/ppc/syslib/m8260_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/m8260_setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c index cdb73a23a538..dae9af78bde1 100644 --- a/arch/ppc/syslib/m8xx_setup.c +++ b/arch/ppc/syslib/m8xx_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c index 3e039706bdbc..2fc7c4150a18 100644 --- a/arch/ppc/syslib/mpc10x_common.c +++ b/arch/ppc/syslib/mpc10x_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc10x_common.c - * * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge, * Mem ctlr, EPIC, etc. * diff --git a/arch/ppc/syslib/mpc52xx_devices.c b/arch/ppc/syslib/mpc52xx_devices.c index da3c74bfdc92..7487539a4e92 100644 --- a/arch/ppc/syslib/mpc52xx_devices.c +++ b/arch/ppc/syslib/mpc52xx_devices.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_devices.c - * * Freescale MPC52xx device descriptions * * diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c index 313c96ec7eb1..9ec525f9fe98 100644 --- a/arch/ppc/syslib/mpc52xx_pci.c +++ b/arch/ppc/syslib/mpc52xx_pci.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_pci.c - * * PCI code for the Freescale MPC52xx embedded CPU. * * diff --git a/arch/ppc/syslib/mpc52xx_pci.h b/arch/ppc/syslib/mpc52xx_pci.h index 04b509a02530..77d47dbba85e 100644 --- a/arch/ppc/syslib/mpc52xx_pci.h +++ b/arch/ppc/syslib/mpc52xx_pci.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_pci.h - * * PCI Include file the Freescale MPC52xx embedded cpu chips * * diff --git a/arch/ppc/syslib/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c index 4c4497e62517..c4406f9dc6a3 100644 --- a/arch/ppc/syslib/mpc52xx_pic.c +++ b/arch/ppc/syslib/mpc52xx_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_pic.c - * * Programmable Interrupt Controller functions for the Freescale MPC52xx * embedded CPU. * diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c index a4a4b02227df..2ee48ce0a517 100644 --- a/arch/ppc/syslib/mpc52xx_setup.c +++ b/arch/ppc/syslib/mpc52xx_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_setup.c - * * Common code for the boards based on Freescale MPC52xx embedded CPU. * * diff --git a/arch/ppc/syslib/mpc52xx_sys.c b/arch/ppc/syslib/mpc52xx_sys.c index 9a0f90aa8aac..b4e6f978f057 100644 --- a/arch/ppc/syslib/mpc52xx_sys.c +++ b/arch/ppc/syslib/mpc52xx_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc52xx_sys.c - * * Freescale MPC52xx system descriptions * * diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index f9b95de70e23..1af2c000fcfa 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/83xx/mpc83xx_devices.c - * * MPC83xx Device descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mpc83xx_sys.c b/arch/ppc/syslib/mpc83xx_sys.c index 82cf3ab77f4a..0498ae7e01e3 100644 --- a/arch/ppc/syslib/mpc83xx_sys.c +++ b/arch/ppc/syslib/mpc83xx_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/83xx/mpc83xx_sys.c - * * MPC83xx System descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c index 00e9b6ff2f6e..7735336f5b8f 100644 --- a/arch/ppc/syslib/mpc85xx_devices.c +++ b/arch/ppc/syslib/mpc85xx_devices.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc85xx_devices.c - * * MPC85xx Device descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c index 397cfbcce5ea..d96a93dbcb5a 100644 --- a/arch/ppc/syslib/mpc85xx_sys.c +++ b/arch/ppc/syslib/mpc85xx_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/85xx/mpc85xx_sys.c - * * MPC85xx System descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c index 92dc98b36bde..bd41ed83beb3 100644 --- a/arch/ppc/syslib/mpc8xx_devices.c +++ b/arch/ppc/syslib/mpc8xx_devices.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mpc8xx_devices.c - * * MPC8xx Device descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c index d3c617521603..eee213284855 100644 --- a/arch/ppc/syslib/mpc8xx_sys.c +++ b/arch/ppc/syslib/mpc8xx_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/mpc8xx_sys.c - * * MPC8xx System descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/mv64360_pic.c b/arch/ppc/syslib/mv64360_pic.c index 58b0aa813e85..5a19697060f0 100644 --- a/arch/ppc/syslib/mv64360_pic.c +++ b/arch/ppc/syslib/mv64360_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/mv64360_pic.c - * * Interrupt controller support for Marvell's MV64360. * * Author: Rabeeh Khoury diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 1f01b7e2376b..3b039c30a439 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mv64x60.c - * * Common routines for the Marvell/Galileo Discovery line of host bridges * (gt64260, mv64360, mv64460, ...). * diff --git a/arch/ppc/syslib/mv64x60_dbg.c b/arch/ppc/syslib/mv64x60_dbg.c index fa5b2e45e0ca..9cf18764a1a1 100644 --- a/arch/ppc/syslib/mv64x60_dbg.c +++ b/arch/ppc/syslib/mv64x60_dbg.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mv64x60_dbg.c - * * KGDB and progress routines for the Marvell/Galileo MV64x60 (Discovery). * * Author: Mark A. Greer diff --git a/arch/ppc/syslib/mv64x60_win.c b/arch/ppc/syslib/mv64x60_win.c index 5b827e2bbe22..4bf1ad17bf1a 100644 --- a/arch/ppc/syslib/mv64x60_win.c +++ b/arch/ppc/syslib/mv64x60_win.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/mv64x60_win.c - * * Tables with info on how to manipulate the 32 & 64 bit windows on the * various types of Marvell bridge chips. * diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c index 894779712b46..38e5b93fbe41 100644 --- a/arch/ppc/syslib/open_pic.c +++ b/arch/ppc/syslib/open_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling - * * Copyright (C) 1997 Geert Uytterhoeven * * This file is subject to the terms and conditions of the GNU General Public diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c index 1c40049b9a45..bcbe40de26fe 100644 --- a/arch/ppc/syslib/open_pic2.c +++ b/arch/ppc/syslib/open_pic2.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling - * * Copyright (C) 1997 Geert Uytterhoeven * * This file is subject to the terms and conditions of the GNU General Public diff --git a/arch/ppc/syslib/open_pic_defs.h b/arch/ppc/syslib/open_pic_defs.h index 6c94e7131463..3a25de7cb572 100644 --- a/arch/ppc/syslib/open_pic_defs.h +++ b/arch/ppc/syslib/open_pic_defs.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/open_pic_defs.h -- OpenPIC definitions - * * Copyright (C) 1997 Geert Uytterhoeven * * This file is based on the following documentation: diff --git a/arch/ppc/syslib/pci_auto.c b/arch/ppc/syslib/pci_auto.c index d64207c2a972..ee20a86fcc4b 100644 --- a/arch/ppc/syslib/pci_auto.c +++ b/arch/ppc/syslib/pci_auto.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/pci_auto.c - * * PCI autoconfiguration library * * Author: Matt Porter diff --git a/arch/ppc/syslib/ppc4xx_dma.c b/arch/ppc/syslib/ppc4xx_dma.c index 05ccd598dd4e..b40b96a8c609 100644 --- a/arch/ppc/syslib/ppc4xx_dma.c +++ b/arch/ppc/syslib/ppc4xx_dma.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ppc4xx_dma.c - * * IBM PPC4xx DMA engine core library * * Copyright 2000-2004 MontaVista Software Inc. diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c index aa4165144ec2..fd9af0fc0e9f 100644 --- a/arch/ppc/syslib/ppc4xx_pic.c +++ b/arch/ppc/syslib/ppc4xx_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc4xx_pic.c - * * Interrupt controller driver for PowerPC 4xx-based processors. * * Eugene Surovegin or diff --git a/arch/ppc/syslib/ppc4xx_sgdma.c b/arch/ppc/syslib/ppc4xx_sgdma.c index 9f76e8ee39ed..280ea010a9c8 100644 --- a/arch/ppc/syslib/ppc4xx_sgdma.c +++ b/arch/ppc/syslib/ppc4xx_sgdma.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ppc4xx_sgdma.c - * * IBM PPC4xx DMA engine scatter/gather library * * Copyright 2002-2003 MontaVista Software Inc. diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c index 7bada82527a8..26afd637dc81 100644 --- a/arch/ppc/syslib/ppc83xx_setup.c +++ b/arch/ppc/syslib/ppc83xx_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc83xx_setup.c - * * MPC83XX common board code * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc83xx_setup.h b/arch/ppc/syslib/ppc83xx_setup.h index a122a7322e5e..478b011cd963 100644 --- a/arch/ppc/syslib/ppc83xx_setup.h +++ b/arch/ppc/syslib/ppc83xx_setup.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc83xx_setup.h - * * MPC83XX common board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc85xx_common.c b/arch/ppc/syslib/ppc85xx_common.c index 19ad537225e4..0145c968f9ad 100644 --- a/arch/ppc/syslib/ppc85xx_common.c +++ b/arch/ppc/syslib/ppc85xx_common.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc85xx_common.c - * * MPC85xx support routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc85xx_common.h b/arch/ppc/syslib/ppc85xx_common.h index 94edf32151dd..182744a1321c 100644 --- a/arch/ppc/syslib/ppc85xx_common.h +++ b/arch/ppc/syslib/ppc85xx_common.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc85xx_common.h - * * MPC85xx support routines * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c index e4dda43fdaa7..e70b34ee6275 100644 --- a/arch/ppc/syslib/ppc85xx_setup.c +++ b/arch/ppc/syslib/ppc85xx_setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc85xx_setup.c - * * MPC85XX common board code * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc85xx_setup.h b/arch/ppc/syslib/ppc85xx_setup.h index e340b0545fb5..f55b8032d3d9 100644 --- a/arch/ppc/syslib/ppc85xx_setup.h +++ b/arch/ppc/syslib/ppc85xx_setup.h @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc85xx_setup.h - * * MPC85XX common board definitions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c index 879783a41cfd..60c724e11584 100644 --- a/arch/ppc/syslib/ppc_sys.c +++ b/arch/ppc/syslib/ppc_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/ppc_sys.c - * * PPC System library functions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/pq2_devices.c b/arch/ppc/syslib/pq2_devices.c index 6ff3aab82fc3..0636aed7b827 100644 --- a/arch/ppc/syslib/pq2_devices.c +++ b/arch/ppc/syslib/pq2_devices.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/pq2_devices.c - * * PQ2 Device descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c index 36d6e2179940..75e64f1c144d 100644 --- a/arch/ppc/syslib/pq2_sys.c +++ b/arch/ppc/syslib/pq2_sys.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/pq2_devices.c - * * PQ2 System descriptions * * Maintainer: Kumar Gala diff --git a/arch/ppc/syslib/prep_nvram.c b/arch/ppc/syslib/prep_nvram.c index 2c6364d9641f..474dccbc4a8a 100644 --- a/arch/ppc/syslib/prep_nvram.c +++ b/arch/ppc/syslib/prep_nvram.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/prep_nvram.c - * * Copyright (C) 1998 Corey Minyard * * This reads the NvRAM on PReP compliant machines (generally from IBM or diff --git a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c index 1323c641c19d..a8168b8e5683 100644 --- a/arch/ppc/syslib/todc_time.c +++ b/arch/ppc/syslib/todc_time.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/todc_time.c - * * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818 * Real Time Clocks/Timekeepers. * diff --git a/arch/ppc/syslib/xilinx_pic.c b/arch/ppc/syslib/xilinx_pic.c index 848fb512f3f8..e672b600f315 100644 --- a/arch/ppc/syslib/xilinx_pic.c +++ b/arch/ppc/syslib/xilinx_pic.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/xilinx_pic.c - * * Interrupt controller driver for Xilinx Virtex-II Pro. * * Author: MontaVista Software, Inc. diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 831eb4e8d9d3..f7ac31856572 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -118,7 +118,7 @@ * the hvcs_final_close() function in order to get it out of the spinlock. * Rearranged hvcs_close(). Cleaned up some printks and did some housekeeping * on the changelog. Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from - * arch/ppc64/hvcserver.h. + * include/asm-powerpc/hvcserver.h * * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to * prevent possible lockup with realtime scheduling as similarily pointed out by @@ -168,9 +168,10 @@ MODULE_VERSION(HVCS_DRIVER_VERSION); /* * The hcall interface involves putting 8 chars into each of two registers. - * We load up those 2 registers (in arch/ppc64/hvconsole.c) by casting char[16] - * to long[2]. It would work without __ALIGNED__, but a little (tiny) bit - * slower because an unaligned load is slower than aligned load. + * We load up those 2 registers (in arch/powerpc/platforms/pseries/hvconsole.c) + * by casting char[16] to long[2]. It would work without __ALIGNED__, but a + * little (tiny) bit slower because an unaligned load is slower than aligned + * load. */ #define __ALIGNED__ __attribute__((__aligned__(8))) diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index c9add8f1ad94..ec94b51074fc 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -54,7 +54,7 @@ struct paca_struct { #endif /* CONFIG_PPC_ISERIES */ /* - * MAGIC: the spinlock functions in arch/ppc64/lib/locks.c + * MAGIC: the spinlock functions in arch/powerpc/lib/locks.c * load lock_token and paca_index with a single lwz * instruction. They must travel together and be properly * aligned. diff --git a/include/asm-powerpc/rwsem.h b/include/asm-powerpc/rwsem.h index 79bae4933b73..2c2fe9647595 100644 --- a/include/asm-powerpc/rwsem.h +++ b/include/asm-powerpc/rwsem.h @@ -4,7 +4,7 @@ #ifdef __KERNEL__ /* - * include/asm-ppc64/rwsem.h: R/W semaphores for PPC using the stuff + * include/asm-powerpc/rwsem.h: R/W semaphores for PPC using the stuff * in lib/rwsem.c. Adapted largely from include/asm-i386/rwsem.h * by Paul Mackerras . */ diff --git a/include/asm-ppc/harrier.h b/include/asm-ppc/harrier.h index 36c73ab7e43e..7acd7fc126ec 100644 --- a/include/asm-ppc/harrier.h +++ b/include/asm-ppc/harrier.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/harrier.h - * * Definitions for Motorola MCG Harrier North Bridge & Memory controller * * Author: Dale Farnsworth diff --git a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h index 976ad3d94f27..b30a6a3b5bd2 100644 --- a/include/asm-ppc/mpc10x.h +++ b/include/asm-ppc/mpc10x.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/mpc10x.h - * * Common routines for the Motorola SPS MPC106/8240/107 Host bridge/Mem * ctlr/EPIC/etc. * diff --git a/include/asm-ppc/todc.h b/include/asm-ppc/todc.h index 84bae7d76814..937c7dbe6e5c 100644 --- a/include/asm-ppc/todc.h +++ b/include/asm-ppc/todc.h @@ -1,6 +1,4 @@ /* - * include/asm-ppc/todc.h - * * Definitions for the M48Txx and mc146818 series of Time of day/Real Time * Clock chips. * diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 685c25175d96..3e376202dd48 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -958,7 +958,7 @@ void audit_syscall_entry(struct task_struct *tsk, int arch, int major, * * i386 no * x86_64 no - * ppc64 yes (see arch/ppc64/kernel/misc.S) + * ppc64 yes (see arch/powerpc/platforms/iseries/misc.S) * * This also happens with vm86 emulation in a non-nested manner * (entries without exits), so this case must be caught. diff --git a/lib/extable.c b/lib/extable.c index 18df57c029df..01c08b5836f5 100644 --- a/lib/extable.c +++ b/lib/extable.c @@ -1,5 +1,4 @@ /* - * lib/extable.c * Derived from arch/ppc/mm/extable.c and arch/i386/mm/extable.c. * * Copyright (C) 2004 Paul Mackerras, IBM Corp. -- cgit v1.2.3-59-g8ed1b From 341963b909a01d2f38d86f5db8dd1f8c80bd6dbf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 15:10:48 +0900 Subject: [PATCH] libata: add ATA_QCFLAG_EH_SCHEDULED Add ATA_QCFLAG_EH_SCHEDULED. If this flag is set, the qc is owned by EH and normal completion path is not allowed to finish it. This patch doesn't actually use this flag. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 33 ++++++++++++++++++++------------- drivers/scsi/libata-scsi.c | 2 +- drivers/scsi/libata.h | 1 + include/linux/libata.h | 1 + 4 files changed, 23 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 22db73932253..977a53dd1677 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3620,19 +3620,7 @@ void ata_qc_free(struct ata_queued_cmd *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) +inline void __ata_qc_complete(struct ata_queued_cmd *qc) { assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ assert(qc->flags & ATA_QCFLAG_ACTIVE); @@ -3650,6 +3638,25 @@ 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) +{ + if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED)) + return; + + __ata_qc_complete(qc); +} + static inline int ata_should_dma_map(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index b007bb409382..1df468eb2bf3 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -770,7 +770,7 @@ static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) spin_lock_irqsave(&ap->host_set->lock, flags); qc->scsidone = ata_eh_scsidone; - ata_qc_complete(qc); + __ata_qc_complete(qc); assert(!ata_tag_valid(qc->tag)); spin_unlock_irqrestore(&ap->host_set->lock, flags); diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 9d76923a2253..1cd071a32e93 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -46,6 +46,7 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc); extern unsigned int 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); diff --git a/include/linux/libata.h b/include/linux/libata.h index 68b3fe6f9a4d..5c70a57f93ee 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -169,6 +169,7 @@ enum { ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, + ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */ /* various lengths of time */ ATA_TMOUT_EDD = 5 * HZ, /* heuristic */ -- cgit v1.2.3-59-g8ed1b From f29841e08fa20a7f2c8bc1b70306975299c66ee7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 15:10:48 +0900 Subject: [PATCH] libata: implement ata_scsi_timed_out() Implement ata_scsi_timed_out(), to be used as scsi_host_template->eh_timed_out callback for all libata drivers. Without this function, the following race exists. If a qc completes after SCSI timer expires but before libata EH kicks in, the qc gets completed but the scsicmd still gets passed to libata EH resulting in ->eng_timeout invocation with NULL qc, which none is handling properly. This patch makes sure that scmd and qc share the same lifetime. Original idea from Jeff Garzik . Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 1 + drivers/scsi/libata-scsi.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 1 + 3 files changed, 43 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 977a53dd1677..d53e0bce2bec 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4913,6 +4913,7 @@ EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); +EXPORT_SYMBOL_GPL(ata_scsi_timed_out); EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 1df468eb2bf3..d67cc2fb5694 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -716,6 +716,47 @@ 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) { + assert(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 diff --git a/include/linux/libata.h b/include/linux/libata.h index 5c70a57f93ee..c1e198655bb1 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -509,6 +509,7 @@ 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 enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); 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); -- cgit v1.2.3-59-g8ed1b From 35daeb8f9b41fd13180e8a6f8bec9fc5268938f9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 15:10:48 +0900 Subject: [PATCH] libata: use ata_scsi_timed_out() Make all libata low level drivers use ata_scsi_timed_out(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 1 + drivers/scsi/ata_piix.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 + 15 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index c840d5ec12a7..c67189a4e0b1 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -206,6 +206,7 @@ static struct scsi_host_template ahci_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 49cc4209fe16..4933ba284885 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -180,6 +180,7 @@ static struct scsi_host_template piix_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 3a6bf58dc37b..d0ad3ebe9685 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -143,6 +143,7 @@ static struct scsi_host_template adma_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 3e916327ae37..1db05f23f12f 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -378,6 +378,7 @@ static struct scsi_host_template mv_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = MV_USE_Q_DEPTH, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index bbbb55eeb73a..cdfeb9aa600b 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -229,6 +229,7 @@ static struct scsi_host_template nv_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 0950a8e45814..5d4ed54d9452 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -111,6 +111,7 @@ static struct scsi_host_template pdc_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 2afbeb77f6fe..82c3df7048ea 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -132,6 +132,7 @@ static struct scsi_host_template qs_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 17f74d3c10e7..f40f25edbb11 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -135,6 +135,7 @@ static struct scsi_host_template sil_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 7222fc7ff3fc..f4742ad3c962 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -280,6 +280,7 @@ static struct scsi_host_template sil24_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 2df8c5632ac3..2f1815715705 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -87,6 +87,7 @@ static struct scsi_host_template sis_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index d8472563fde8..f369c3003adf 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -288,6 +288,7 @@ static struct scsi_host_template k2_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 9f992fbcf2e7..3319f03b61a0 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -182,6 +182,7 @@ static struct scsi_host_template pdc_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 9635ca700977..c500f2490902 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -75,6 +75,7 @@ static struct scsi_host_template uli_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 6d5b0a794cfd..2e20887dc88f 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -94,6 +94,7 @@ static struct scsi_host_template svia_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 2e2c3b7acb0c..cf1f8a61bda0 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -223,6 +223,7 @@ static struct scsi_host_template vsc_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, -- cgit v1.2.3-59-g8ed1b From f63790201521ccadb63673ff121dac46ab300cf0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 15:10:48 +0900 Subject: [PATCH] libata: kill NULL qc handling from ->eng_timeout callbacks ->eng_timeout cannot be invoked with NULL qc anymore. Add an assertion in ata_scsi_error() and kill NULL qc handling from all ->eng_timeout callbacks. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 12 +++--------- drivers/scsi/libata-core.c | 12 +----------- drivers/scsi/libata-scsi.c | 1 + drivers/scsi/sata_mv.c | 9 ++------- drivers/scsi/sata_promise.c | 9 +-------- drivers/scsi/sata_sil24.c | 5 ----- drivers/scsi/sata_sx4.c | 9 +-------- 7 files changed, 9 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index c67189a4e0b1..fa01894fc41b 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -677,19 +677,13 @@ static void ahci_eng_timeout(struct ata_port *ap) spin_lock_irqsave(&host_set->lock, flags); + ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT)); qc = ata_qc_from_tag(ap, ap->active_tag); - if (!qc) { - printk(KERN_ERR "ata%u: BUG: timeout without command\n", - ap->id); - } else { - ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT)); - qc->err_mask |= AC_ERR_TIMEOUT; - } + qc->err_mask |= AC_ERR_TIMEOUT; spin_unlock_irqrestore(&host_set->lock, flags); - if (qc) - ata_eh_qc_complete(qc); + ata_eh_qc_complete(qc); } static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d53e0bce2bec..b938c7a37664 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3524,20 +3524,10 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) void ata_eng_timeout(struct ata_port *ap) { - struct ata_queued_cmd *qc; - DPRINTK("ENTER\n"); - qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc) - ata_qc_timeout(qc); - else { - printk(KERN_ERR "ata%u: BUG: timeout without command\n", - ap->id); - goto out; - } + ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag)); -out: DPRINTK("EXIT\n"); } diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index d67cc2fb5694..9d67c6768335 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -782,6 +782,7 @@ int ata_scsi_error(struct Scsi_Host *host) spin_lock_irqsave(&ap->host_set->lock, flags); assert(!(ap->flags & ATA_FLAG_IN_EH)); ap->flags |= ATA_FLAG_IN_EH; + assert(ata_qc_from_tag(ap, ap->active_tag) != NULL); spin_unlock_irqrestore(&ap->host_set->lock, flags); ap->ops->eng_timeout(ap); diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 1db05f23f12f..6c80527ddd21 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -2027,13 +2027,8 @@ static void mv_eng_timeout(struct ata_port *ap) mv_err_intr(ap); mv_stop_and_reset(ap); - if (!qc) { - printk(KERN_ERR "ata%u: BUG: timeout without command\n", - ap->id); - } else { - qc->err_mask |= AC_ERR_TIMEOUT; - ata_eh_qc_complete(qc); - } + qc->err_mask |= AC_ERR_TIMEOUT; + ata_eh_qc_complete(qc); } /** diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 5d4ed54d9452..c9dfd9370919 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -432,11 +432,6 @@ static void pdc_eng_timeout(struct ata_port *ap) spin_lock_irqsave(&host_set->lock, flags); qc = ata_qc_from_tag(ap, ap->active_tag); - if (!qc) { - printk(KERN_ERR "ata%u: BUG: timeout without command\n", - ap->id); - goto out; - } switch (qc->tf.protocol) { case ATA_PROT_DMA: @@ -456,10 +451,8 @@ static void pdc_eng_timeout(struct ata_port *ap) break; } -out: spin_unlock_irqrestore(&host_set->lock, flags); - if (qc) - ata_eh_qc_complete(qc); + ata_eh_qc_complete(qc); DPRINTK("EXIT\n"); } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index f4742ad3c962..962396b36f61 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -639,11 +639,6 @@ static void sil24_eng_timeout(struct ata_port *ap) struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (!qc) { - printk(KERN_ERR "ata%u: BUG: timeout without command\n", - ap->id); - return; - } printk(KERN_ERR "ata%u: command timeout\n", ap->id); qc->err_mask |= AC_ERR_TIMEOUT; diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 3319f03b61a0..212cff4fe5f5 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -867,11 +867,6 @@ static void pdc_eng_timeout(struct ata_port *ap) spin_lock_irqsave(&host_set->lock, flags); qc = ata_qc_from_tag(ap, ap->active_tag); - if (!qc) { - printk(KERN_ERR "ata%u: BUG: timeout without command\n", - ap->id); - goto out; - } switch (qc->tf.protocol) { case ATA_PROT_DMA: @@ -890,10 +885,8 @@ static void pdc_eng_timeout(struct ata_port *ap) break; } -out: spin_unlock_irqrestore(&host_set->lock, flags); - if (qc) - ata_eh_qc_complete(qc); + ata_eh_qc_complete(qc); DPRINTK("EXIT\n"); } -- cgit v1.2.3-59-g8ed1b From cc9278ed5e992122a654a3f762561ee5e013810f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 17:25:47 +0900 Subject: [PATCH] ahci: separate out ahci_fill_cmd_slot() Separate out ahci_fill_cmd_slot() from ahci_qc_prep(). ahci_fill_cmd_slot() can later be used to issue non-standard commands. (e.g. softreset) Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index fa01894fc41b..98ce6bb62ff8 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -507,6 +507,15 @@ static unsigned int ahci_dev_classify(struct ata_port *ap) return ata_dev_classify(&tf); } +static void ahci_fill_cmd_slot(struct ata_port *ap, u32 opts) +{ + struct ahci_port_priv *pp = ap->private_data; + 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); +} + static void ahci_phy_reset(struct ata_port *ap) { void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; @@ -585,42 +594,35 @@ 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); u32 opts; const u32 cmd_fis_len = 5; /* five dwords */ unsigned int n_elem; - /* - * Fill in command slot information (currently only one slot, - * slot 0, is currently since we don't do queueing) - */ - - opts = cmd_fis_len; - if (qc->tf.flags & ATA_TFLAG_WRITE) - opts |= AHCI_CMD_WRITE; - if (is_atapi_taskfile(&qc->tf)) - opts |= AHCI_CMD_ATAPI; - - 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); - /* * 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); - if (opts & AHCI_CMD_ATAPI) { + if (is_atapi) { memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len); } - if (!(qc->flags & ATA_QCFLAG_DMAMAP)) - return; + n_elem = 0; + if (qc->flags & ATA_QCFLAG_DMAMAP) + n_elem = ahci_fill_sg(qc); - n_elem = ahci_fill_sg(qc); + /* + * Fill in command slot information. + */ + opts = cmd_fis_len | n_elem << 16; + if (qc->tf.flags & ATA_TFLAG_WRITE) + opts |= AHCI_CMD_WRITE; + if (is_atapi) + opts |= AHCI_CMD_ATAPI; - pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16); + ahci_fill_cmd_slot(ap, opts); } static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) -- cgit v1.2.3-59-g8ed1b From 3a39746a5290445ea4238f21ac260e42106c1454 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 23:58:48 +0900 Subject: [PATCH] libata: make new reset act identical to ->phy_reset register-wise This patch makes std component operations act identical to ->phy_reset register-wise except for SError clearing on sata_std_hardreset. Note that if a driver only implements/uses hardreset, it should not use ata_std_probeinit() to avoid extra sata_phy_resume() and ata_busy_sleep() compared to ->phy_reset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 51 ++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b938c7a37664..8424bd9ee26d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1924,11 +1924,20 @@ static int sata_phy_resume(struct ata_port *ap) * * @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 */ extern void ata_std_probeinit(struct ata_port *ap) { - if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) + if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) { sata_phy_resume(ap); + if (sata_dev_present(ap)) + ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + } } /** @@ -1954,20 +1963,17 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) DPRINTK("ENTER\n"); + if (ap->ops->scr_read && !sata_dev_present(ap)) { + classes[0] = ATA_DEV_NONE; + goto out; + } + /* determine if device 0/1 are present */ if (ata_devchk(ap, 0)) devmask |= (1 << 0); if (slave_possible && ata_devchk(ap, 1)) devmask |= (1 << 1); - /* devchk reports device presence without actual device on - * most SATA controllers. Check SStatus and turn devmask off - * if link is offline. Note that we should continue resetting - * even when it seems like there's no device. - */ - if (ap->ops->scr_read && !sata_dev_present(ap)) - devmask = 0; - /* select device 0 again */ ap->ops->dev_select(ap, 0); @@ -1989,6 +1995,7 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) if (slave_possible && err != 0x81) classes[1] = ata_dev_try_classify(ap, 1, &err); + out: DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]); return 0; } @@ -2047,6 +2054,8 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) return -EIO; } + ap->ops->dev_select(ap, 0); /* probably unnecessary */ + *class = ata_dev_try_classify(ap, 0, NULL); DPRINTK("EXIT, class=%u\n", *class); @@ -2081,11 +2090,9 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) if (ap->cbl == ATA_CBL_SATA) sata_print_link_status(ap); - /* bail out if no device is present */ - if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) { - DPRINTK("EXIT, no device\n"); - return; - } + /* re-enable interrupts */ + if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ + ata_irq_on(ap); /* is double-select really necessary? */ if (classes[0] != ATA_DEV_NONE) @@ -2093,9 +2100,19 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) if (classes[1] != ATA_DEV_NONE) ap->ops->dev_select(ap, 0); - /* re-enable interrupts & set up device control */ - if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ - ata_irq_on(ap); + /* bail out if no device is present */ + if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) { + DPRINTK("EXIT, no device\n"); + return; + } + + /* set up device control */ + if (ap->ioaddr.ctl_addr) { + if (ap->flags & ATA_FLAG_MMIO) + writeb(ap->ctl, (void __iomem *) ap->ioaddr.ctl_addr); + else + outb(ap->ctl, ap->ioaddr.ctl_addr); + } DPRINTK("EXIT\n"); } -- cgit v1.2.3-59-g8ed1b From ac7c6d596e2177857ffc35b8d453ee313a874d8d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 23:58:48 +0900 Subject: [PATCH] libata: kill SError clearing in sata_std_hardreset(). Don't clear SError in sata_std_hardreset(). This makes hardreset act identically to ->phy_reset register-wise. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 8424bd9ee26d..38e72c1dd689 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2018,8 +2018,6 @@ 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 serror; - DPRINTK("ENTER\n"); /* Issue phy wake/reset */ @@ -2034,10 +2032,6 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) /* Bring phy back */ sata_phy_resume(ap); - /* Clear SError */ - serror = scr_read(ap, SCR_ERROR); - scr_write(ap, SCR_ERROR, serror); - /* TODO: phy layer with polling, timeouts, etc. */ if (!sata_dev_present(ap)) { *class = ATA_DEV_NONE; -- cgit v1.2.3-59-g8ed1b From 531db7aa0db09f188b71108c35f334af35968291 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 23:58:48 +0900 Subject: [PATCH] sata_sil: convert to new reset mechanism Convert sata_sil to use new reset mechanism. sata_sil is fairly generic and can directly use std routine. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index f40f25edbb11..bd2887741d78 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -158,7 +158,7 @@ static const struct ata_port_operations sil_ops = { .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, + .probe_reset = ata_std_probe_reset, .post_set_mode = sil_post_set_mode, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, @@ -181,7 +181,7 @@ static const struct ata_port_info sil_port_info[] = { { .sht = &sil_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO, + ATA_FLAG_MMIO, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -190,8 +190,7 @@ static const struct ata_port_info sil_port_info[] = { { .sht = &sil_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO | - SIL_FLAG_MOD15WRITE, + ATA_FLAG_MMIO | SIL_FLAG_MOD15WRITE, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -200,7 +199,7 @@ static const struct ata_port_info sil_port_info[] = { { .sht = &sil_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO, + ATA_FLAG_MMIO, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ -- cgit v1.2.3-59-g8ed1b From 07b734702a96efbc260bf50c2ce57e34167f431b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 23:58:48 +0900 Subject: [PATCH] sata_sil24: convert to new reset mechanism Convert sata_sil24 ->phy_reset to new reset mechanism. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 56 +++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 962396b36f61..ccac05a5eb6d 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -249,7 +249,7 @@ 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 void sil24_phy_reset(struct ata_port *ap); +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); @@ -306,7 +306,7 @@ static const struct ata_port_operations sil24_ops = { .tf_read = sil24_tf_read, - .phy_reset = sil24_phy_reset, + .probe_reset = sil24_probe_reset, .qc_prep = sil24_qc_prep, .qc_issue = sil24_qc_issue, @@ -336,8 +336,8 @@ static struct ata_port_info sil24_port_info[] = { { .sht = &sil24_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO | - ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4), + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + SIL24_NPORTS2FLAG(4), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -347,8 +347,8 @@ static struct ata_port_info sil24_port_info[] = { { .sht = &sil24_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO | - ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2), + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + SIL24_NPORTS2FLAG(2), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -358,8 +358,8 @@ static struct ata_port_info sil24_port_info[] = { { .sht = &sil24_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO | - ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1), + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + SIL24_NPORTS2FLAG(1), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -428,7 +428,8 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) *tf = pp->tf; } -static int sil24_issue_SRST(struct ata_port *ap) +static int sil24_softreset(struct ata_port *ap, int verbose, + unsigned int *class) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; struct sil24_port_priv *pp = ap->private_data; @@ -437,6 +438,8 @@ static int sil24_issue_SRST(struct ata_port *ap) u32 irq_enable, irq_stat; int cnt; + DPRINTK("ENTER\n"); + /* temporarily turn off IRQs during SRST */ irq_enable = readl(port + PORT_IRQ_ENABLE_SET); writel(irq_enable, port + PORT_IRQ_ENABLE_CLR); @@ -466,30 +469,27 @@ static int sil24_issue_SRST(struct ata_port *ap) /* restore IRQs */ writel(irq_enable, port + PORT_IRQ_ENABLE_SET); - if (!(irq_stat & PORT_IRQ_COMPLETE)) - return -1; + if (sata_dev_present(ap)) { + if (!(irq_stat & PORT_IRQ_COMPLETE)) { + DPRINTK("EXIT, srst failed\n"); + return -EIO; + } - /* update TF */ - sil24_update_tf(ap); + sil24_update_tf(ap); + *class = ata_dev_classify(&pp->tf); + } + if (*class == ATA_DEV_UNKNOWN) + *class = ATA_DEV_NONE; + + DPRINTK("EXIT, class=%u\n", *class); return 0; } -static void sil24_phy_reset(struct ata_port *ap) +static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes) { - struct sil24_port_priv *pp = ap->private_data; - - __sata_phy_reset(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) - return; - - if (sil24_issue_SRST(ap) < 0) { - printk(KERN_ERR DRV_NAME - " ata%u: SRST failed, disabling port\n", ap->id); - ap->ops->port_disable(ap); - return; - } - - ap->device->class = ata_dev_classify(&pp->tf); + return ata_drive_probe_reset(ap, ata_std_probeinit, + sil24_softreset, NULL, + ata_std_postreset, classes); } static inline void sil24_fill_sg(struct ata_queued_cmd *qc, -- cgit v1.2.3-59-g8ed1b From 489ff4c7d167be954f715128790bd80d3c888322 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Feb 2006 23:58:48 +0900 Subject: [PATCH] sata_sil24: add hardreset Now that libata is smart enough to handle both soft and hard resets, add hardreset method. Note that sil24 hardreset doesn't supply signature; still, the new reset mechanism can make good use of it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index ccac05a5eb6d..228a7fabffff 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -485,10 +485,19 @@ 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) +{ + unsigned int dummy_class; + + /* sil24 doesn't report device signature after hard reset */ + return sata_std_hardreset(ap, verbose, &dummy_class); +} + static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes) { return ata_drive_probe_reset(ap, ata_std_probeinit, - sil24_softreset, NULL, + sil24_softreset, sil24_hardreset, ata_std_postreset, classes); } -- cgit v1.2.3-59-g8ed1b From 76014427e60f7ecfdc689dfbcb48e9760e1da4fb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 11 Feb 2006 15:13:49 +0900 Subject: [PATCH] libata: inline ata_qc_complete() This patch inlines ata_qc_complete() and uninlines __ata_qc_complete() as suggested by Jeff Garzik. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 23 ++--------------------- drivers/scsi/libata.h | 1 - include/linux/libata.h | 20 +++++++++++++++++++- 3 files changed, 21 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 38e72c1dd689..fffbaa9dae76 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3621,7 +3621,7 @@ void ata_qc_free(struct ata_queued_cmd *qc) } } -inline void __ata_qc_complete(struct ata_queued_cmd *qc) +void __ata_qc_complete(struct ata_queued_cmd *qc) { assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ assert(qc->flags & ATA_QCFLAG_ACTIVE); @@ -3639,25 +3639,6 @@ inline 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) -{ - if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED)) - return; - - __ata_qc_complete(qc); -} - static inline int ata_should_dma_map(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -4877,7 +4858,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_eng_timeout); EXPORT_SYMBOL_GPL(ata_tf_load); diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 1cd071a32e93..9d76923a2253 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -46,7 +46,6 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc); extern unsigned int 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); diff --git a/include/linux/libata.h b/include/linux/libata.h index c1e198655bb1..695d9ae6ec03 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -556,7 +556,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_eng_timeout(struct ata_port *ap); extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, struct scsi_cmnd *cmd, @@ -756,6 +756,24 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) ata_tf_init(qc->ap, &qc->tf, qc->dev->devno); } +/** + * 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) +{ + if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED)) + return; + + __ata_qc_complete(qc); +} /** * ata_irq_on - Enable interrupts on a port. -- cgit v1.2.3-59-g8ed1b From a42fc659ba4e4026b2397344180458bebb79e1d2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 11 Feb 2006 16:26:02 +0900 Subject: [PATCH] ahci: make ahci_fill_cmd_slot() take *pp instead of *ap Make ahci_fill_cmd_slot() take struct ahci_port_priv *pp instead of struct ata_port *ap as suggested by Jeff Garzik. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 98ce6bb62ff8..72bdd434159e 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -507,9 +507,8 @@ static unsigned int ahci_dev_classify(struct ata_port *ap) return ata_dev_classify(&tf); } -static void ahci_fill_cmd_slot(struct ata_port *ap, u32 opts) +static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) { - struct ahci_port_priv *pp = ap->private_data; 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); @@ -622,7 +621,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) if (is_atapi) opts |= AHCI_CMD_ATAPI; - ahci_fill_cmd_slot(ap, opts); + ahci_fill_cmd_slot(pp, opts); } static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) -- cgit v1.2.3-59-g8ed1b From 4bd00f6a201897af4cd50250a761e6bc4b2221ec Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 11 Feb 2006 16:26:02 +0900 Subject: [PATCH] ahci: convert to new reset mechanism Convert ahci ->phy_reset to new reset mechanism. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 72bdd434159e..86bccb7128f9 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -190,7 +190,7 @@ 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 void ahci_phy_reset(struct ata_port *ap); +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); @@ -230,7 +230,7 @@ static const struct ata_port_operations ahci_ops = { .tf_read = ahci_tf_read, - .phy_reset = ahci_phy_reset, + .probe_reset = ahci_probe_reset, .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, @@ -252,8 +252,7 @@ static const struct ata_port_info ahci_port_info[] = { { .sht = &ahci_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | - ATA_FLAG_PIO_DMA, + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, @@ -515,28 +514,35 @@ 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 void ahci_phy_reset(struct ata_port *ap) +static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) { - void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; - struct ata_device *dev = &ap->device[0]; - u32 new_tmp, tmp; + int rc; + + DPRINTK("ENTER\n"); ahci_stop_engine(ap); - __sata_phy_reset(ap); + rc = sata_std_hardreset(ap, verbose, class); ahci_start_engine(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) - return; + if (rc == 0) + *class = ahci_dev_classify(ap); + if (*class == ATA_DEV_UNKNOWN) + *class = ATA_DEV_NONE; - dev->class = ahci_dev_classify(ap); - if (!ata_dev_present(dev)) { - ata_port_disable(ap); - return; - } + DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); + return rc; +} + +static void ahci_postreset(struct ata_port *ap, unsigned int *class) +{ + void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; + u32 new_tmp, tmp; + + ata_std_postreset(ap, class); /* Make sure port's ATAPI bit is set appropriately */ new_tmp = tmp = readl(port_mmio + PORT_CMD); - if (dev->class == ATA_DEV_ATAPI) + if (*class == ATA_DEV_ATAPI) new_tmp |= PORT_CMD_ATAPI; else new_tmp &= ~PORT_CMD_ATAPI; @@ -546,6 +552,12 @@ static void ahci_phy_reset(struct ata_port *ap) } } +static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes) +{ + return ata_drive_probe_reset(ap, NULL, NULL, ahci_hardreset, + ahci_postreset, classes); +} + static u8 ahci_check_status(struct ata_port *ap) { void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; -- cgit v1.2.3-59-g8ed1b From a46314744d8fadb91451bf2e5d2fd949c4a752d8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 11 Feb 2006 19:11:13 +0900 Subject: [PATCH] libata: convert assert(X)'s in libata core layer to WARN_ON(!X)'s In an effort to kill libata-specific assert() and use generic WARN_ON(), this patch converts all assert(X)'s in libata core layer to WARN_ON(!X)'s. Most conversions are straight-forward logical negation exception for the followings. * In libata-core.c:ata_fill_sg(), assert(qc->n_elem > 0) is converted to WARN_ON(qc->n_elem == 0) because qc->n_elem is unsigned and unsigned <= 0 is weird. * In libata-scsi.c:ata_gen_ata_desc/fixed_sense(), assert(NULL != qc->ap->ops->tf_read) is converted to WARN_ON(qc->ap->ops->tf_read == NULL), as there are no other users of 'constant cond var' style in libata. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 46 +++++++++++++++++++++++----------------------- drivers/scsi/libata-scsi.c | 14 +++++++------- 2 files changed, 30 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index fffbaa9dae76..cef85e515c4c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -904,8 +904,8 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) DPRINTK("ENTER, host %u, dev %u\n", ap->id, device); - assert (dev->class == ATA_DEV_ATA || dev->class == ATA_DEV_ATAPI || - dev->class == ATA_DEV_NONE); + WARN_ON(dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ATAPI && + dev->class != ATA_DEV_NONE); ata_dev_select(ap, device, 1, 1); /* select device 0/1 */ @@ -2301,7 +2301,7 @@ static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift) master = &ap->device[0]; slave = &ap->device[1]; - assert (ata_dev_present(master) || ata_dev_present(slave)); + WARN_ON(!ata_dev_present(master) && !ata_dev_present(slave)); if (shift == ATA_SHIFT_UDMA) { mask = ap->udma_mask; @@ -2547,11 +2547,11 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) int dir = qc->dma_dir; void *pad_buf = NULL; - assert(qc->flags & ATA_QCFLAG_DMAMAP); - assert(sg != NULL); + WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP)); + WARN_ON(sg == NULL); if (qc->flags & ATA_QCFLAG_SINGLE) - assert(qc->n_elem == 1); + WARN_ON(qc->n_elem != 1); VPRINTK("unmapping %u sg elements\n", qc->n_elem); @@ -2606,8 +2606,8 @@ static void ata_fill_sg(struct ata_queued_cmd *qc) struct scatterlist *sg; unsigned int idx; - assert(qc->__sg != NULL); - assert(qc->n_elem > 0); + WARN_ON(qc->__sg == NULL); + WARN_ON(qc->n_elem == 0); idx = 0; ata_for_each_sg(sg, qc) { @@ -2759,7 +2759,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); struct scatterlist *psg = &qc->pad_sgent; - assert(qc->dev->class == ATA_DEV_ATAPI); + WARN_ON(qc->dev->class != ATA_DEV_ATAPI); memset(pad_buf, 0, ATA_DMA_PAD_SZ); @@ -2821,7 +2821,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) int n_elem, pre_n_elem, dir, trim_sg = 0; VPRINTK("ENTER, ata%u\n", ap->id); - assert(qc->flags & ATA_QCFLAG_SG); + WARN_ON(!(qc->flags & ATA_QCFLAG_SG)); /* we must lengthen transfers to end on a 32-bit boundary */ qc->pad_len = lsg->length & 3; @@ -2830,7 +2830,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) struct scatterlist *psg = &qc->pad_sgent; unsigned int offset; - assert(qc->dev->class == ATA_DEV_ATAPI); + WARN_ON(qc->dev->class != ATA_DEV_ATAPI); memset(pad_buf, 0, ATA_DMA_PAD_SZ); @@ -2924,7 +2924,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap) unsigned int reg_state = HSM_ST_UNKNOWN; qc = ata_qc_from_tag(ap, ap->active_tag); - assert(qc != NULL); + WARN_ON(qc == NULL); switch (ap->hsm_task_state) { case HSM_ST: @@ -2992,7 +2992,7 @@ static int ata_pio_complete (struct ata_port *ap) } qc = ata_qc_from_tag(ap, ap->active_tag); - assert(qc != NULL); + WARN_ON(qc == NULL); drv_stat = ata_wait_idle(ap); if (!ata_ok(drv_stat)) { @@ -3003,7 +3003,7 @@ static int ata_pio_complete (struct ata_port *ap) ap->hsm_task_state = HSM_ST_IDLE; - assert(qc->err_mask == 0); + WARN_ON(qc->err_mask); ata_poll_qc_complete(qc); /* another command may start at this point */ @@ -3360,7 +3360,7 @@ static void ata_pio_block(struct ata_port *ap) } qc = ata_qc_from_tag(ap, ap->active_tag); - assert(qc != NULL); + WARN_ON(qc == NULL); /* check error */ if (status & (ATA_ERR | ATA_DF)) { @@ -3397,12 +3397,12 @@ static void ata_pio_error(struct ata_port *ap) printk(KERN_WARNING "ata%u: PIO error\n", ap->id); qc = ata_qc_from_tag(ap, ap->active_tag); - assert(qc != NULL); + WARN_ON(qc == NULL); /* 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; @@ -3609,7 +3609,7 @@ void ata_qc_free(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; unsigned int tag; - assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ + WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ qc->flags = 0; tag = qc->tag; @@ -3623,8 +3623,8 @@ void ata_qc_free(struct ata_queued_cmd *qc) void __ata_qc_complete(struct ata_queued_cmd *qc) { - assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ - assert(qc->flags & ATA_QCFLAG_ACTIVE); + WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ + WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); if (likely(qc->flags & ATA_QCFLAG_DMAMAP)) ata_sg_clean(qc); @@ -4155,8 +4155,8 @@ static void atapi_packet_task(void *_data) u8 status; 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)); /* sleep-wait for BSY to clear */ DPRINTK("busy wait\n"); @@ -4174,7 +4174,7 @@ static void atapi_packet_task(void *_data) /* send SCSI cdb */ DPRINTK("send cdb\n"); - assert(ap->cdb_len >= 12); + WARN_ON(ap->cdb_len < 12); if (qc->tf.protocol == ATA_PROT_ATAPI_DMA || qc->tf.protocol == ATA_PROT_ATAPI_NODATA) { diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 9d67c6768335..26f07a2617f9 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -553,7 +553,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) /* * Read the controller registers. */ - assert(NULL != qc->ap->ops->tf_read); + WARN_ON(qc->ap->ops->tf_read == NULL); qc->ap->ops->tf_read(qc->ap, tf); /* @@ -628,7 +628,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) /* * Read the controller registers. */ - assert(NULL != qc->ap->ops->tf_read); + WARN_ON(qc->ap->ops->tf_read == NULL); qc->ap->ops->tf_read(qc->ap, tf); /* @@ -746,7 +746,7 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) spin_lock_irqsave(&ap->host_set->lock, flags); qc = ata_qc_from_tag(ap, ap->active_tag); if (qc) { - assert(qc->scsicmd == cmd); + WARN_ON(qc->scsicmd != cmd); qc->flags |= ATA_QCFLAG_EH_SCHEDULED; qc->err_mask |= AC_ERR_TIMEOUT; ret = EH_NOT_HANDLED; @@ -780,14 +780,14 @@ int ata_scsi_error(struct Scsi_Host *host) ap = (struct ata_port *) &host->hostdata[0]; spin_lock_irqsave(&ap->host_set->lock, flags); - assert(!(ap->flags & ATA_FLAG_IN_EH)); + WARN_ON(ap->flags & ATA_FLAG_IN_EH); ap->flags |= ATA_FLAG_IN_EH; - assert(ata_qc_from_tag(ap, ap->active_tag) != NULL); + WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); spin_unlock_irqrestore(&ap->host_set->lock, flags); ap->ops->eng_timeout(ap); - assert(host->host_failed == 0 && list_empty(&host->eh_cmd_q)); + WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); scsi_eh_flush_done_q(&ap->eh_done_q); @@ -813,7 +813,7 @@ static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) spin_lock_irqsave(&ap->host_set->lock, flags); qc->scsidone = ata_eh_scsidone; __ata_qc_complete(qc); - assert(!ata_tag_valid(qc->tag)); + WARN_ON(ata_tag_valid(qc->tag)); spin_unlock_irqrestore(&ap->host_set->lock, flags); scsi_eh_finish_cmd(scmd, &ap->eh_done_q); -- cgit v1.2.3-59-g8ed1b From beec7dbc6ff003bbc94de62b3323519c878fb2ac Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 11 Feb 2006 19:11:13 +0900 Subject: [PATCH] libata: convert assert(xxx)'s in low-level drivers to WARN_ON(!xxx)'s This patch converts all assert(xxx)'s in low-level drivers to WARN_ON(!xxx)'s. After this patch, there is no in-kernel user of the libata assert() macro. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 2 +- drivers/scsi/sata_mv.c | 50 +++++++++++++++++++++++------------------------ drivers/scsi/sata_qstor.c | 4 ++-- drivers/scsi/sata_sx4.c | 2 +- 4 files changed, 29 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 86bccb7128f9..24a54a5a91b8 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -714,7 +714,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) ci = readl(port_mmio + PORT_CMD_ISSUE); if (likely((ci & 0x1) == 0)) { if (qc) { - assert(qc->err_mask == 0); + WARN_ON(qc->err_mask); ata_qc_complete(qc); qc = NULL; } diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 6c80527ddd21..732cb64a4d1b 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -632,8 +632,8 @@ static void mv_irq_clear(struct ata_port *ap) * @base: port base address * @pp: port private data * - * Verify the local cache of the eDMA state is accurate with an - * assert. + * Verify the local cache of the eDMA state is accurate with a + * WARN_ON. * * LOCKING: * Inherited from caller. @@ -644,15 +644,15 @@ static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp) writelfl(EDMA_EN, base + EDMA_CMD_OFS); pp->pp_flags |= MV_PP_FLAG_EDMA_EN; } - assert(EDMA_EN & readl(base + EDMA_CMD_OFS)); + WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS))); } /** * mv_stop_dma - Disable eDMA engine * @ap: ATA channel to manipulate * - * Verify the local cache of the eDMA state is accurate with an - * assert. + * Verify the local cache of the eDMA state is accurate with a + * WARN_ON. * * LOCKING: * Inherited from caller. @@ -670,7 +670,7 @@ static void mv_stop_dma(struct ata_port *ap) writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; } else { - assert(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS))); + WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)); } /* now properly wait for the eDMA to stop */ @@ -1061,15 +1061,15 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) return; /* the req producer index should be the same as we remember it */ - assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> - EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == - pp->req_producer); + WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> + EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != + pp->req_producer); /* Fill in command request block */ if (!(qc->tf.flags & ATA_TFLAG_WRITE)) flags |= CRQB_FLAG_READ; - assert(MV_MAX_Q_DEPTH > qc->tag); + WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); flags |= qc->tag << CRQB_TAG_SHIFT; pp->crqb[pp->req_producer].sg_addr = @@ -1152,16 +1152,16 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc) return; /* the req producer index should be the same as we remember it */ - assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> - EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == - pp->req_producer); + WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> + EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != + pp->req_producer); /* Fill in Gen IIE command request block */ if (!(qc->tf.flags & ATA_TFLAG_WRITE)) flags |= CRQB_FLAG_READ; - assert(MV_MAX_Q_DEPTH > qc->tag); + WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); flags |= qc->tag << CRQB_TAG_SHIFT; crqb = (struct mv_crqb_iie *) &pp->crqb[pp->req_producer]; @@ -1226,12 +1226,12 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS); /* the req producer index should be the same as we remember it */ - assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == - pp->req_producer); + WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != + pp->req_producer); /* until we do queuing, the queue should be empty at this point */ - assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == - ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >> - EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); + WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != + ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >> + EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); mv_inc_q_index(&pp->req_producer); /* now incr producer index */ @@ -1251,7 +1251,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) * * This routine is for use when the port is in DMA mode, when it * will be using the CRPB (command response block) method of - * returning command completion information. We assert indices + * returning command completion information. We check indices * are good, grab status, and bump the response consumer index to * prove that we're up to date. * @@ -1267,16 +1267,16 @@ static u8 mv_get_crpb_status(struct ata_port *ap) out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); /* the response consumer index should be the same as we remember it */ - assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == - pp->rsp_consumer); + WARN_ON(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != + pp->rsp_consumer); /* increment our consumer index... */ pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer); /* and, until we do NCQ, there should only be 1 CRPB waiting */ - assert(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >> - EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == - pp->rsp_consumer); + WARN_ON(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >> + EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != + pp->rsp_consumer); /* write out our inc'd consumer index so EDMA knows we're caught up */ out_ptr &= EDMA_RSP_Q_BASE_LO_MASK; diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 82c3df7048ea..955131b43206 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -277,8 +277,8 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc) unsigned int nelem; u8 *prd = pp->pkt + QS_CPB_BYTES; - assert(qc->__sg != NULL); - assert(qc->n_elem > 0); + WARN_ON(qc->__sg == NULL); + WARN_ON(qc->n_elem == 0); nelem = 0; ata_for_each_sg(sg, qc) { diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 212cff4fe5f5..e158f7a34d62 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -461,7 +461,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc) unsigned int i, idx, total_len = 0, sgt_len; u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; - assert(qc->flags & ATA_QCFLAG_DMAMAP); + WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP)); VPRINTK("ata%u: ENTER\n", ap->id); -- cgit v1.2.3-59-g8ed1b From 06ab78222bd119a0a3d8a1f89997ce902a219703 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 15:01:49 +0900 Subject: [PATCH] libata: allow ->probe_reset to return ATA_DEV_UNKNOWN This patch makes ata_bus_probe() normalize classes[] returned by ->probe_reset such that ->probe_reset can return ATA_DEV_UNKNOWN. This eases implementation of ->probe_reset's which don't directly use ata_drive_probe_reset(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index cef85e515c4c..9ddb568267e1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1142,8 +1142,11 @@ static int ata_bus_probe(struct ata_port *ap) rc = ap->ops->probe_reset(ap, classes); if (rc == 0) { - for (i = 0; i < ATA_MAX_DEVICES; i++) + for (i = 0; i < ATA_MAX_DEVICES; i++) { + if (classes[i] == ATA_DEV_UNKNOWN) + classes[i] = ATA_DEV_NONE; ap->device[i].class = classes[i]; + } } else { printk(KERN_ERR "ata%u: probe reset failed, " "disabling port\n", ap->id); -- cgit v1.2.3-59-g8ed1b From 48f80e12abbc1e9034e54614c30e7c304209ce99 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 19:05:07 +0900 Subject: [PATCH] ata_piix: kill spurious assignment in piix_sata_probe() In piix_sata_probe(), mask gets assigned unnecessarily at the beginning of the function. Kill the assignment. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 4933ba284885..8e0529601730 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -415,9 +415,6 @@ static int piix_sata_probe (struct ata_port *ap) int orig_mask, mask, i; u8 pcs; - mask = (PIIX_PORT_PRESENT << ap->hard_port_no) | - (PIIX_PORT_ENABLED << ap->hard_port_no); - pci_read_config_byte(pdev, ICH5_PCS, &pcs); orig_mask = (int) pcs & 0xff; -- cgit v1.2.3-59-g8ed1b From 0e949ff304a7ca07db38c17fbbf3ead1085d7bbf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 22:47:04 +0900 Subject: [PATCH] libata: implement ata_dev_id_c_string() ata_dev_id_c_string() reads ATA string from the specified offset of the given IDENTIFY PAGE and puts it in the specified buffer in trimmed and NULL-terminated form. The caller must supply a buffer which is one byte larger than the maximum size of the target ID string. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 29 +++++++++++++++++++++++++++++ include/linux/libata.h | 2 ++ 2 files changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9ddb568267e1..7e410299d67a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -519,6 +519,34 @@ void ata_dev_id_string(const u16 *id, unsigned char *s, } } +/** + * ata_dev_id_c_string - Convert IDENTIFY DEVICE page into C string + * @id: IDENTIFY DEVICE results we will examine + * @s: string into which data is output + * @ofs: offset into identify device page + * @len: length of string to return. must be an odd number. + * + * This function is identical to ata_dev_id_string except that it + * trims trailing spaces and terminates the resulting string with + * null. @len must be actual maximum length (even number) + 1. + * + * LOCKING: + * caller. + */ +void ata_dev_id_c_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len) +{ + unsigned char *p; + + WARN_ON(!(len & 1)); + + ata_dev_id_string(id, s, ofs, len - 1); + + p = s + strnlen(s, len - 1); + while (p > s && p[-1] == ' ') + p--; + *p = '\0'; +} /** * ata_noop_dev_select - Select device 0/1 on ATA bus @@ -4905,6 +4933,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_id_string); +EXPORT_SYMBOL_GPL(ata_dev_id_c_string); EXPORT_SYMBOL_GPL(ata_dev_config); EXPORT_SYMBOL_GPL(ata_scsi_simulate); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); diff --git a/include/linux/libata.h b/include/linux/libata.h index 83a1f2ead861..0853032673b7 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -540,6 +540,8 @@ extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, extern unsigned int ata_dev_classify(const struct ata_taskfile *tf); extern void ata_dev_id_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); +extern void ata_dev_id_c_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len); extern void ata_dev_config(struct ata_port *ap, unsigned int i); extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc); -- cgit v1.2.3-59-g8ed1b From 2e02671daa2cd69d93c828c40579bbe953f17210 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 22:47:04 +0900 Subject: [PATCH] libata: use ata_dev_id_c_string() Use ata_dev_id_c_string() Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 18 ++++-------------- drivers/scsi/libata-scsi.c | 11 ++++------- drivers/scsi/sata_sil.c | 19 +++++-------------- 3 files changed, 13 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 7e410299d67a..1d65f703348e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2301,24 +2301,14 @@ static const char * const ata_dma_blacklist [] = { static int ata_dma_blacklisted(const struct ata_device *dev) { - unsigned char model_num[40]; - char *s; - unsigned int len; + unsigned char model_num[41]; int i; - ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); - s = &model_num[0]; - len = strnlen(s, sizeof(model_num)); - - /* ATAPI specifies that empty space is blank-filled; remove blanks */ - while ((len > 0) && (s[len - 1] == ' ')) { - len--; - s[len] = 0; - } + ata_dev_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, + sizeof(model_num)); for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++) - if (!strncmp(ata_dma_blacklist[i], s, len)) + if (!strcmp(ata_dma_blacklist[i], model_num)) return 1; return 0; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 26f07a2617f9..ebd7cf42550b 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1806,15 +1806,12 @@ static int ata_dev_supports_fua(u16 *id) if (!ata_id_has_fua(id)) return 0; - model[40] = '\0'; - fw[8] = '\0'; + ata_dev_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model)); + ata_dev_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw)); - ata_dev_id_string(id, model, ATA_ID_PROD_OFS, sizeof(model) - 1); - ata_dev_id_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw) - 1); - - if (strncmp(model, "Maxtor", 6)) + if (strcmp(model, "Maxtor")) return 1; - if (strncmp(fw, "BANC1G10", 8)) + if (strcmp(fw, "BANC1G10")) return 1; return 0; /* blacklisted */ diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index bd2887741d78..61c4ac7ff9db 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -337,22 +337,13 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) { unsigned int n, quirks = 0; - unsigned char model_num[40]; - const char *s; - unsigned int len; + unsigned char model_num[41]; - ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); - s = &model_num[0]; - len = strnlen(s, sizeof(model_num)); - - /* ATAPI specifies that empty space is blank-filled; remove blanks */ - while ((len > 0) && (s[len - 1] == ' ')) - len--; + ata_dev_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, + sizeof(model_num)); for (n = 0; sil_blacklist[n].product; n++) - if (!memcmp(sil_blacklist[n].product, s, - strlen(sil_blacklist[n].product))) { + if (!strcmp(sil_blacklist[n].product, model_num)) { quirks = sil_blacklist[n].quirk; break; } @@ -372,7 +363,7 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) /* limit to udma5 */ if (quirks & SIL_QUIRK_UDMA5MAX) { printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n", - ap->id, dev->devno, s); + ap->id, dev->devno, model_num); ap->udma_mask &= ATA_UDMA5; return; } -- cgit v1.2.3-59-g8ed1b From 2940740bcaa5948967d261dfceec04f40b2d2fa1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 22:47:04 +0900 Subject: [PATCH] libata: separate out ata_id_n_sectors() Separate out n_sectors calculation into ata_id_n_sectors() from ata_dev_identify(). This will be used by revalidation. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1d65f703348e..4df5024c3888 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -548,6 +548,21 @@ void ata_dev_id_c_string(const u16 *id, unsigned char *s, *p = '\0'; } +static u64 ata_id_n_sectors(const u16 *id) +{ + if (ata_id_has_lba(id)) { + if (ata_id_has_lba48(id)) + return ata_id_u64(id, 100); + else + return ata_id_u32(id, 60); + } else { + if (ata_id_current_chs_valid(id)) + return ata_id_u32(id, 57); + else + return id[1] * id[3] * id[6]; + } +} + /** * ata_noop_dev_select - Select device 0/1 on ATA bus * @ap: ATA channel to manipulate @@ -1009,6 +1024,8 @@ retry: /* ATA-specific feature tests */ if (dev->class == ATA_DEV_ATA) { + dev->n_sectors = ata_id_n_sectors(dev->id); + if (!ata_id_is_ata(dev->id)) /* sanity check */ goto err_out_nosup; @@ -1038,12 +1055,8 @@ retry: if (ata_id_has_lba(dev->id)) { dev->flags |= ATA_DFLAG_LBA; - if (ata_id_has_lba48(dev->id)) { + if (ata_id_has_lba48(dev->id)) dev->flags |= ATA_DFLAG_LBA48; - dev->n_sectors = ata_id_u64(dev->id, 100); - } else { - dev->n_sectors = ata_id_u32(dev->id, 60); - } /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n", @@ -1059,15 +1072,12 @@ retry: dev->cylinders = dev->id[1]; dev->heads = dev->id[3]; dev->sectors = dev->id[6]; - dev->n_sectors = dev->cylinders * dev->heads * dev->sectors; if (ata_id_current_chs_valid(dev->id)) { /* Current CHS translation is valid. */ dev->cylinders = dev->id[54]; dev->heads = dev->id[55]; dev->sectors = dev->id[56]; - - dev->n_sectors = ata_id_u32(dev->id, 57); } /* print device info to dmesg */ -- cgit v1.2.3-59-g8ed1b From 3d2ca91095f8ab6dc0cb925374eec62fa5336764 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 22:47:04 +0900 Subject: [PATCH] libata: separate out ata_id_major_version() Separate out ATA major version calculation from ata_dev_identify() into ata_id_major_version(). It's preparation for splitting ata_dev_identify(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 +----- include/linux/ata.h | 10 ++++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4df5024c3888..d87854e199f6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -927,7 +927,6 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) { struct ata_device *dev = &ap->device[device]; unsigned int major_version; - u16 tmp; unsigned long xfer_modes; unsigned int using_edd; struct ata_taskfile tf; @@ -1030,10 +1029,7 @@ retry: goto err_out_nosup; /* get major version */ - tmp = dev->id[ATA_ID_MAJOR_VER]; - for (major_version = 14; major_version >= 1; major_version--) - if (tmp & (1 << major_version)) - break; + major_version = ata_id_major_version(dev->id); /* * The exact sequence expected by certain pre-ATA4 drives is: diff --git a/include/linux/ata.h b/include/linux/ata.h index a8155ca4947f..b02a16c435e7 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -267,6 +267,16 @@ struct ata_taskfile { ((u64) (id)[(n) + 1] << 16) | \ ((u64) (id)[(n) + 0]) ) +static inline unsigned int ata_id_major_version(const u16 *id) +{ + unsigned int mver; + + for (mver = 14; mver >= 1; mver--) + if (id[ATA_ID_MAJOR_VER] & (1 << mver)) + break; + return mver; +} + static inline int ata_id_current_chs_valid(const u16 *id) { /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command -- cgit v1.2.3-59-g8ed1b From 0bd3300ac9158b6ceef38fab6fb473765a40e77e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 22:47:05 +0900 Subject: [PATCH] libata: make ata_dump_id() take @id instead of @dev Make ata_dump_id() take @id instead of @dev. This is preparation for splitting ata_dev_identify(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d87854e199f6..a0b6ca3d1a0c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -651,41 +651,41 @@ void ata_dev_select(struct ata_port *ap, unsigned int device, /** * ata_dump_id - IDENTIFY DEVICE info debugging output - * @dev: Device whose IDENTIFY DEVICE page we will dump + * @id: IDENTIFY DEVICE page to dump * - * Dump selected 16-bit words from a detected device's - * IDENTIFY PAGE page. + * Dump selected 16-bit words from the given IDENTIFY DEVICE + * page. * * LOCKING: * caller. */ -static inline void ata_dump_id(const struct ata_device *dev) +static inline void ata_dump_id(const u16 *id) { DPRINTK("49==0x%04x " "53==0x%04x " "63==0x%04x " "64==0x%04x " "75==0x%04x \n", - dev->id[49], - dev->id[53], - dev->id[63], - dev->id[64], - dev->id[75]); + id[49], + id[53], + id[63], + id[64], + id[75]); DPRINTK("80==0x%04x " "81==0x%04x " "82==0x%04x " "83==0x%04x " "84==0x%04x \n", - dev->id[80], - dev->id[81], - dev->id[82], - dev->id[83], - dev->id[84]); + id[80], + id[81], + id[82], + id[83], + id[84]); DPRINTK("88==0x%04x " "93==0x%04x\n", - dev->id[88], - dev->id[93]); + id[88], + id[93]); } /* @@ -1019,7 +1019,7 @@ retry: if (!xfer_modes) xfer_modes = ata_pio_modes(dev); - ata_dump_id(dev); + ata_dump_id(dev->id); /* ATA-specific feature tests */ if (dev->class == ATA_DEV_ATA) { @@ -2510,7 +2510,7 @@ static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev) swap_buf_le16(dev->id, ATA_ID_WORDS); - ata_dump_id(dev); + ata_dump_id(dev->id); DPRINTK("EXIT\n"); -- cgit v1.2.3-59-g8ed1b From 61eb066affc02e16c548aef8b876c49c84113f40 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 23:22:37 +0900 Subject: [PATCH] libata: don't do EDD handling if ->probe_reset is used EDD is never used with ->probe_reset. Don't handle EDD special case in ata_dev_identify if ->probe_reset is in use. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a0b6ca3d1a0c..21ae752cd95c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -939,7 +939,8 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) return; } - if (ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET)) + if (ap->ops->probe_reset || + ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET)) using_edd = 0; else using_edd = 1; -- cgit v1.2.3-59-g8ed1b From 8eabd02c246b808e0e27c3ee9ea17d0349efb06d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 23:32:58 +0900 Subject: [PATCH] libata: make ata_dev_knobble() per-device ata_dev_knobble() unconditionally used the first device of the port to determine whether a device is bridged or not. This causes bridge limit to be incorrectly applied or unapplied for hosts with slave devices (e.g. ata_piix). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 21ae752cd95c..5e8a32052a1e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1121,9 +1121,10 @@ err_out: } -static inline u8 ata_dev_knobble(const struct ata_port *ap) +static inline u8 ata_dev_knobble(const struct ata_port *ap, + struct ata_device *dev) { - return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id))); + return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); } /** @@ -1137,9 +1138,9 @@ static inline u8 ata_dev_knobble(const struct ata_port *ap) void ata_dev_config(struct ata_port *ap, unsigned int i) { /* limit bridge transfers to udma5, 200 sectors */ - if (ata_dev_knobble(ap)) { + if (ata_dev_knobble(ap, &ap->device[i])) { printk(KERN_INFO "ata%u(%u): applying bridge limits\n", - ap->id, ap->device->devno); + ap->id, i); ap->udma_mask &= ATA_UDMA5; ap->host->max_sectors = ATA_MAX_SECTORS; ap->host->hostt->max_sectors = ATA_MAX_SECTORS; -- cgit v1.2.3-59-g8ed1b From 6e7846e9c548443c86cfbad9e4defb4bdcfc538b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 23:32:58 +0900 Subject: [PATCH] libata: move cdb_len for host to device cdb_len is per-device property. Sharing cdb_len on ap results in inaccurate configuration on revalidation and hotplugging. This patch makes cdb_len per-device. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 3 ++- drivers/scsi/libata-core.c | 19 ++++++++++++------- drivers/scsi/libata-scsi.c | 4 ++-- drivers/scsi/sata_sil24.c | 4 ++-- include/linux/libata.h | 2 +- 5 files changed, 19 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 24a54a5a91b8..23caa0c4019b 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -617,7 +617,8 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) ata_tf_to_fis(&qc->tf, pp->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, ap->cdb_len); + memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, + qc->dev->cdb_len); } n_elem = 0; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5e8a32052a1e..1a373b4d0e22 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -931,7 +931,7 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) unsigned int using_edd; struct ata_taskfile tf; unsigned int err_mask; - int rc; + int i, rc; if (!ata_dev_present(dev)) { DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", @@ -1087,7 +1087,7 @@ retry: } - ap->host->max_cmd_len = 16; + dev->cdb_len = 16; } /* ATAPI-specific feature tests */ @@ -1100,8 +1100,7 @@ retry: printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); goto err_out_nosup; } - ap->cdb_len = (unsigned int) rc; - ap->host->max_cmd_len = (unsigned char) ap->cdb_len; + dev->cdb_len = (unsigned int) rc; /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", @@ -1109,6 +1108,12 @@ retry: ata_mode_string(xfer_modes)); } + ap->host->max_cmd_len = 0; + for (i = 0; i < ATA_MAX_DEVICES; i++) + ap->host->max_cmd_len = max_t(unsigned int, + ap->host->max_cmd_len, + ap->device[i].cdb_len); + DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); return; @@ -4203,7 +4208,7 @@ static void atapi_packet_task(void *_data) /* send SCSI cdb */ DPRINTK("send cdb\n"); - WARN_ON(ap->cdb_len < 12); + WARN_ON(qc->dev->cdb_len < 12); if (qc->tf.protocol == ATA_PROT_ATAPI_DMA || qc->tf.protocol == ATA_PROT_ATAPI_NODATA) { @@ -4217,12 +4222,12 @@ static void atapi_packet_task(void *_data) */ spin_lock_irqsave(&ap->host_set->lock, flags); ap->flags &= ~ATA_FLAG_NOINTR; - ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); + 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, ap->cdb_len, 1); + ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); /* PIO commands are handled by polling */ ap->hsm_task_state = HSM_ST; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ebd7cf42550b..3628fedc9865 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2146,7 +2146,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer)); qc->dma_dir = DMA_FROM_DEVICE; - memset(&qc->cdb, 0, ap->cdb_len); + memset(&qc->cdb, 0, qc->dev->cdb_len); qc->cdb[0] = REQUEST_SENSE; qc->cdb[4] = SCSI_SENSE_BUFFERSIZE; @@ -2248,7 +2248,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) if (ata_check_atapi_dma(qc)) using_pio = 1; - memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len); + memcpy(&qc->cdb, scsicmd, dev->cdb_len); qc->complete_fn = atapi_qc_complete; diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 228a7fabffff..24020c68903a 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -371,7 +371,7 @@ static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; - if (ap->cdb_len == 16) + if (dev->cdb_len == 16) writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); else writel(PORT_CS_CDB16, port + PORT_CTRL_CLR); @@ -543,7 +543,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) prb = &cb->atapi.prb; sge = cb->atapi.sge; memset(cb->atapi.cdb, 0, 32); - memcpy(cb->atapi.cdb, qc->cdb, ap->cdb_len); + memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len); if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { if (qc->tf.flags & ATA_TFLAG_WRITE) diff --git a/include/linux/libata.h b/include/linux/libata.h index 0853032673b7..853c98859a9f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -348,6 +348,7 @@ struct ata_device { unsigned int multi_count; /* sectors count for READ/WRITE MULTIPLE */ + unsigned int cdb_len; /* for CHS addressing */ u16 cylinders; /* Number of cylinders */ @@ -377,7 +378,6 @@ struct ata_port { unsigned int mwdma_mask; unsigned int udma_mask; unsigned int cbl; /* cable type; ATA_CBL_xxx */ - unsigned int cdb_len; struct ata_device device[ATA_MAX_DEVICES]; -- cgit v1.2.3-59-g8ed1b From b00eec1d58ee71131375bfeb86e64bceec3f5618 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 23:32:59 +0900 Subject: [PATCH] libata: add per-device max_sectors If a low level driver wants to control max_sectors, it had to adjust ap->host->max_sectors and set ATA_DFLAG_LOCK_SECTORS to tell ata_scsi_slave_config not to override the limit. This is not only cumbersome but also incorrect for hosts which support more than one devices per port. This patch adds per-device ->max_sectors. If the field is unset (zero), libata core layer will adjust ->max_sectors according to default rules. If the field is set, libata honors the setting. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 4 +--- drivers/scsi/libata-scsi.c | 18 +++++++++--------- drivers/scsi/sata_sil.c | 4 +--- include/linux/libata.h | 4 ++-- 4 files changed, 13 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1a373b4d0e22..61cba39a6834 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1147,9 +1147,7 @@ void ata_dev_config(struct ata_port *ap, unsigned int i) printk(KERN_INFO "ata%u(%u): applying bridge limits\n", ap->id, i); ap->udma_mask &= ATA_UDMA5; - ap->host->max_sectors = ATA_MAX_SECTORS; - ap->host->hostt->max_sectors = ATA_MAX_SECTORS; - ap->device[i].flags |= ATA_DFLAG_LOCK_SECTORS; + ap->device[i].max_sectors = ATA_MAX_SECTORS; } if (ap->ops->dev_config) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 3628fedc9865..86da46502b3e 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -684,23 +684,23 @@ int ata_scsi_slave_config(struct scsi_device *sdev) if (sdev->id < ATA_MAX_DEVICES) { struct ata_port *ap; struct ata_device *dev; + unsigned int max_sectors; ap = (struct ata_port *) &sdev->host->hostdata[0]; dev = &ap->device[sdev->id]; - /* TODO: 1024 is an arbitrary number, not the + /* TODO: 2048 is an arbitrary number, not the * hardware maximum. This should be increased to * 65534 when Jens Axboe's patch for dynamically * determining max_sectors is merged. */ - if ((dev->flags & ATA_DFLAG_LBA48) && - ((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) { - /* - * do not overwrite sdev->host->max_sectors, since - * other drives on this host may not support LBA48 - */ - blk_queue_max_sectors(sdev->request_queue, 2048); - } + max_sectors = ATA_MAX_SECTORS; + if (dev->flags & ATA_DFLAG_LBA48) + max_sectors = 2048; + if (dev->max_sectors) + max_sectors = dev->max_sectors; + + blk_queue_max_sectors(sdev->request_queue, max_sectors); /* * SATA DMA transfers must be multiples of 4 byte, so diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 61c4ac7ff9db..6c482c8be254 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -354,9 +354,7 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) (quirks & SIL_QUIRK_MOD15WRITE))) { printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n", ap->id, dev->devno); - ap->host->max_sectors = 15; - ap->host->hostt->max_sectors = 15; - dev->flags |= ATA_DFLAG_LOCK_SECTORS; + dev->max_sectors = 15; return; } diff --git a/include/linux/libata.h b/include/linux/libata.h index 853c98859a9f..afe46457124e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -122,8 +122,7 @@ enum { /* struct ata_device stuff */ 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_LBA = (1 << 3), /* device supports LBA */ + ATA_DFLAG_LBA = (1 << 2), /* device supports LBA */ ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ @@ -348,6 +347,7 @@ struct ata_device { unsigned int multi_count; /* sectors count for READ/WRITE MULTIPLE */ + unsigned int max_sectors; /* per-device max sectors */ unsigned int cdb_len; /* for CHS addressing */ -- cgit v1.2.3-59-g8ed1b From 49430f97dd952eda60848bf6bf161b4917ba103d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Feb 2006 23:32:59 +0900 Subject: [PATCH] libata: kill sht->max_sectors The previous dev->max_sectors patch made sht->max_sectors meaningless. Kill all initializations of sht->max_sectors. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 1 - drivers/scsi/ata_piix.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 - 15 files changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 23caa0c4019b..1c2ab3dede71 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -211,7 +211,6 @@ static struct scsi_host_template ahci_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = AHCI_MAX_SG, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = AHCI_USE_CLUSTERING, diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 8e0529601730..4cc1108f721a 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -185,7 +185,6 @@ static struct scsi_host_template piix_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index d0ad3ebe9685..5f33cc932e70 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -148,7 +148,6 @@ static struct scsi_host_template adma_ata_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ENABLE_CLUSTERING, diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 732cb64a4d1b..c158de2e757d 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -383,7 +383,6 @@ static struct scsi_host_template mv_sht = { .can_queue = MV_USE_Q_DEPTH, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = MV_MAX_SG_CT / 2, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index cdfeb9aa600b..caffadc2e0ae 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -234,7 +234,6 @@ static struct scsi_host_template nv_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index c9dfd9370919..ba2b7a0983db 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -116,7 +116,6 @@ static struct scsi_host_template pdc_ata_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 955131b43206..286482630be3 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -137,7 +137,6 @@ static struct scsi_host_template qs_ata_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = QS_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, //FIXME .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 6c482c8be254..15346888faf2 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -140,7 +140,6 @@ static struct scsi_host_template sil_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 24020c68903a..a0e35a262156 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -285,7 +285,6 @@ static struct scsi_host_template sil24_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 2f1815715705..7fd45f86de99 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -92,7 +92,6 @@ static struct scsi_host_template sis_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = ATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index f369c3003adf..4aaccd53e736 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -293,7 +293,6 @@ static struct scsi_host_template k2_sata_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index e158f7a34d62..9f8a76815402 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -187,7 +187,6 @@ static struct scsi_host_template pdc_sata_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index c500f2490902..37a487b7d655 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -80,7 +80,6 @@ static struct scsi_host_template uli_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 2e20887dc88f..ff65a0b0457f 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -99,7 +99,6 @@ static struct scsi_host_template svia_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index cf1f8a61bda0..e124db8e8284 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -228,7 +228,6 @@ static struct scsi_host_template vsc_sata_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, -- cgit v1.2.3-59-g8ed1b From 4ddc1651cee0143eeddbe043ccd66bb87072e279 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Sun, 5 Feb 2006 16:13:22 +0100 Subject: [PATCH] let IPW2{1,2}00 select IEEE80211 This patch makes the IPW2100 and IPW2200 options available in the configuration menu even if IEEE80211 has not been selected before. This behaviour is more intuitive for people which are not familiar with the driver internals. The suggestion for this change was made by Alejandro Bonilla Beeche. Signed-off-by: Jan Niehusmann Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index a1ede41d9071..7587df760ecb 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -136,8 +136,9 @@ comment "Wireless 802.11b ISA/PCI cards support" config IPW2100 tristate "Intel PRO/Wireless 2100 Network Connection" - depends on NET_RADIO && PCI && IEEE80211 + depends on NET_RADIO && PCI select FW_LOADER + select IEEE80211 ---help--- A driver for the Intel PRO/Wireless 2100 Network Connection 802.11b wireless network adapter. @@ -189,8 +190,9 @@ config IPW2100_DEBUG config IPW2200 tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection" - depends on NET_RADIO && IEEE80211 && PCI + depends on NET_RADIO && PCI select FW_LOADER + select IEEE80211 ---help--- A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network Connection adapters. -- cgit v1.2.3-59-g8ed1b From 4861dd79c1724f37e36d66cc4b3454803aec3f93 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 5 Feb 2006 17:57:36 -0500 Subject: [PATCH] wireless/atmel: convert constants to ieee80211 layer equivalents This patch converts the Atmel driver-only IEEE 802.11 constants to their equivalents from the kernel's ieee80211 layer headers. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 110 ++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index dfc24016ba81..87afa6878f26 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -137,44 +137,6 @@ static struct { #define MAC_BOOT_COMPLETE 0x0010 // MAC boot has been completed #define MAC_INIT_OK 0x0002 // MAC boot has been completed -#define C80211_SUBTYPE_MGMT_ASS_REQUEST 0x00 -#define C80211_SUBTYPE_MGMT_ASS_RESPONSE 0x10 -#define C80211_SUBTYPE_MGMT_REASS_REQUEST 0x20 -#define C80211_SUBTYPE_MGMT_REASS_RESPONSE 0x30 -#define C80211_SUBTYPE_MGMT_ProbeRequest 0x40 -#define C80211_SUBTYPE_MGMT_ProbeResponse 0x50 -#define C80211_SUBTYPE_MGMT_BEACON 0x80 -#define C80211_SUBTYPE_MGMT_ATIM 0x90 -#define C80211_SUBTYPE_MGMT_DISASSOSIATION 0xA0 -#define C80211_SUBTYPE_MGMT_Authentication 0xB0 -#define C80211_SUBTYPE_MGMT_Deauthentication 0xC0 - -#define C80211_MGMT_AAN_OPENSYSTEM 0x0000 -#define C80211_MGMT_AAN_SHAREDKEY 0x0001 - -#define C80211_MGMT_CAPABILITY_ESS 0x0001 // see 802.11 p.58 -#define C80211_MGMT_CAPABILITY_IBSS 0x0002 // - " - -#define C80211_MGMT_CAPABILITY_CFPollable 0x0004 // - " - -#define C80211_MGMT_CAPABILITY_CFPollRequest 0x0008 // - " - -#define C80211_MGMT_CAPABILITY_Privacy 0x0010 // - " - - -#define C80211_MGMT_SC_Success 0 -#define C80211_MGMT_SC_Unspecified 1 -#define C80211_MGMT_SC_SupportCapabilities 10 -#define C80211_MGMT_SC_ReassDenied 11 -#define C80211_MGMT_SC_AssDenied 12 -#define C80211_MGMT_SC_AuthAlgNotSupported 13 -#define C80211_MGMT_SC_AuthTransSeqNumError 14 -#define C80211_MGMT_SC_AuthRejectChallenge 15 -#define C80211_MGMT_SC_AuthRejectTimeout 16 -#define C80211_MGMT_SC_AssDeniedHandleAP 17 -#define C80211_MGMT_SC_AssDeniedBSSRate 18 - -#define C80211_MGMT_ElementID_SSID 0 -#define C80211_MGMT_ElementID_SupportedRates 1 -#define C80211_MGMT_ElementID_ChallengeText 16 -#define C80211_MGMT_CAPABILITY_ShortPreamble 0x0020 - #define MIB_MAX_DATA_BYTES 212 #define MIB_HEADER_SIZE 4 /* first four fields */ @@ -2835,7 +2797,7 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 channel) { int rejoin = 0; - int new = capability & C80211_MGMT_CAPABILITY_ShortPreamble ? + int new = capability & MFIE_TYPE_POWER_CONSTRAINT ? SHORT_PREAMBLE : LONG_PREAMBLE; if (priv->preamble != new) { @@ -2921,11 +2883,11 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc) memcpy(header.addr2, priv->dev->dev_addr, 6); memcpy(header.addr3, priv->CurrentBSSID, 6); - body.capability = cpu_to_le16(C80211_MGMT_CAPABILITY_ESS); + body.capability = cpu_to_le16(WLAN_CAPABILITY_ESS); if (priv->wep_is_on) - body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_Privacy); + body.capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); if (priv->preamble == SHORT_PREAMBLE) - body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_ShortPreamble); + body.capability |= cpu_to_le16(MFIE_TYPE_POWER_CONSTRAINT); body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period); @@ -2939,10 +2901,10 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc) bodysize = 12 + priv->SSID_size; } - ssid_el_p[0] = C80211_MGMT_ElementID_SSID; + ssid_el_p[0] = MFIE_TYPE_SSID; ssid_el_p[1] = priv->SSID_size; memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size); - ssid_el_p[2 + priv->SSID_size] = C80211_MGMT_ElementID_SupportedRates; + ssid_el_p[2 + priv->SSID_size] = MFIE_TYPE_RATES; ssid_el_p[3 + priv->SSID_size] = 4; /* len of suported rates */ memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4); @@ -3004,7 +2966,7 @@ static void store_bss_info(struct atmel_private *priv, u16 beacon_period, u8 channel, u8 rssi, u8 ssid_len, u8 *ssid, int is_beacon) { - u8 *bss = capability & C80211_MGMT_CAPABILITY_ESS ? header->addr2 : header->addr3; + u8 *bss = capability & WLAN_CAPABILITY_ESS ? header->addr2 : header->addr3; int i, index; for (index = -1, i = 0; i < priv->BSS_list_entries; i++) @@ -3030,16 +2992,16 @@ static void store_bss_info(struct atmel_private *priv, priv->BSSinfo[index].channel = channel; priv->BSSinfo[index].beacon_period = beacon_period; - priv->BSSinfo[index].UsingWEP = capability & C80211_MGMT_CAPABILITY_Privacy; + priv->BSSinfo[index].UsingWEP = capability & WLAN_CAPABILITY_PRIVACY; memcpy(priv->BSSinfo[index].SSID, ssid, ssid_len); priv->BSSinfo[index].SSIDsize = ssid_len; - if (capability & C80211_MGMT_CAPABILITY_IBSS) + if (capability & WLAN_CAPABILITY_IBSS) priv->BSSinfo[index].BSStype = IW_MODE_ADHOC; - else if (capability & C80211_MGMT_CAPABILITY_ESS) + else if (capability & WLAN_CAPABILITY_ESS) priv->BSSinfo[index].BSStype =IW_MODE_INFRA; - priv->BSSinfo[index].preamble = capability & C80211_MGMT_CAPABILITY_ShortPreamble ? + priv->BSSinfo[index].preamble = capability & MFIE_TYPE_POWER_CONSTRAINT ? SHORT_PREAMBLE : LONG_PREAMBLE; } @@ -3050,7 +3012,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) u16 trans_seq_no = le16_to_cpu(auth->trans_seq); u16 system = le16_to_cpu(auth->alg); - if (status == C80211_MGMT_SC_Success && !priv->wep_is_on) { + if (status == WLAN_STATUS_SUCCESS && !priv->wep_is_on) { /* no WEP */ if (priv->station_was_associated) { atmel_enter_state(priv, STATION_STATE_REASSOCIATING); @@ -3063,19 +3025,19 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) } } - if (status == C80211_MGMT_SC_Success && priv->wep_is_on) { + if (status == WLAN_STATUS_SUCCESS && priv->wep_is_on) { int should_associate = 0; /* WEP */ if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum) return; - if (system == C80211_MGMT_AAN_OPENSYSTEM) { + if (system == WLAN_AUTH_OPEN) { if (trans_seq_no == 0x0002) { should_associate = 1; } - } else if (system == C80211_MGMT_AAN_SHAREDKEY) { + } else if (system == WLAN_AUTH_SHARED_KEY) { if (trans_seq_no == 0x0002 && - auth->el_id == C80211_MGMT_ElementID_ChallengeText) { + auth->el_id == MFIE_TYPE_CHALLENGE) { send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len); return; } else if (trans_seq_no == 0x0004) { @@ -3140,8 +3102,8 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype) if (frame_len < 8 + rates_len) return; - if (status == C80211_MGMT_SC_Success) { - if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE) + if (status == WLAN_STATUS_SUCCESS) { + if (subtype == IEEE80211_STYPE_ASSOC_RESP) priv->AssociationRequestRetryCnt = 0; else priv->ReAssociationRequestRetryCnt = 0; @@ -3178,9 +3140,9 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype) return; } - if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE && - status != C80211_MGMT_SC_AssDeniedBSSRate && - status != C80211_MGMT_SC_SupportCapabilities && + if (subtype == IEEE80211_STYPE_ASSOC_RESP && + status != WLAN_STATUS_ASSOC_DENIED_RATES && + status != WLAN_STATUS_CAPS_UNSUPPORTED && priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) { mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); priv->AssociationRequestRetryCnt++; @@ -3188,9 +3150,9 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype) return; } - if (subtype == C80211_SUBTYPE_MGMT_REASS_RESPONSE && - status != C80211_MGMT_SC_AssDeniedBSSRate && - status != C80211_MGMT_SC_SupportCapabilities && + if (subtype == IEEE80211_STYPE_REASSOC_RESP && + status != WLAN_STATUS_ASSOC_DENIED_RATES && + status != WLAN_STATUS_CAPS_UNSUPPORTED && priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) { mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); priv->ReAssociationRequestRetryCnt++; @@ -3325,8 +3287,8 @@ static void atmel_management_frame(struct atmel_private *priv, subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE; switch (subtype) { - case C80211_SUBTYPE_MGMT_BEACON: - case C80211_SUBTYPE_MGMT_ProbeResponse: + case IEEE80211_STYPE_BEACON: + case IEEE80211_STYPE_PROBE_RESP: /* beacon frame has multiple variable-length fields - never let an engineer loose with a data structure design. */ @@ -3384,19 +3346,19 @@ static void atmel_management_frame(struct atmel_private *priv, beacon_interval, channel, rssi, ssid_length, &beacon->rates_el_id, - subtype == C80211_SUBTYPE_MGMT_BEACON); + subtype == IEEE80211_STYPE_BEACON); } break; - case C80211_SUBTYPE_MGMT_Authentication: + case IEEE80211_STYPE_AUTH: if (priv->station_state == STATION_STATE_AUTHENTICATING) authenticate(priv, frame_len); break; - case C80211_SUBTYPE_MGMT_ASS_RESPONSE: - case C80211_SUBTYPE_MGMT_REASS_RESPONSE: + case IEEE80211_STYPE_ASSOC_RESP: + case IEEE80211_STYPE_REASSOC_RESP: if (priv->station_state == STATION_STATE_ASSOCIATING || priv->station_state == STATION_STATE_REASSOCIATING) @@ -3404,7 +3366,7 @@ static void atmel_management_frame(struct atmel_private *priv, break; - case C80211_SUBTYPE_MGMT_DISASSOSIATION: + case IEEE80211_STYPE_DISASSOC: if (priv->station_is_associated && priv->operating_mode == IW_MODE_INFRA && is_frame_from_current_bss(priv, header)) { @@ -3417,7 +3379,7 @@ static void atmel_management_frame(struct atmel_private *priv, break; - case C80211_SUBTYPE_MGMT_Deauthentication: + case IEEE80211_STYPE_DEAUTH: if (priv->operating_mode == IW_MODE_INFRA && is_frame_from_current_bss(priv, header)) { priv->station_was_associated = 0; @@ -3453,12 +3415,12 @@ static void atmel_management_timer(u_long a) priv->AuthenticationRequestRetryCnt = 0; restart_search(priv); } else { - int auth = C80211_MGMT_AAN_OPENSYSTEM; + int auth = WLAN_AUTH_OPEN; priv->AuthenticationRequestRetryCnt++; priv->CurrentAuthentTransactionSeqNum = 0x0001; mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); if (priv->wep_is_on && priv->exclude_unencrypted) - auth = C80211_MGMT_AAN_SHAREDKEY; + auth = WLAN_AUTH_SHARED_KEY; send_authentication_request(priv, auth, NULL, 0); } break; @@ -3558,14 +3520,14 @@ static void atmel_command_irq(struct atmel_private *priv) priv->station_was_associated = priv->station_is_associated; atmel_enter_state(priv, STATION_STATE_READY); } else { - int auth = C80211_MGMT_AAN_OPENSYSTEM; + int auth = WLAN_AUTH_OPEN; priv->AuthenticationRequestRetryCnt = 0; atmel_enter_state(priv, STATION_STATE_AUTHENTICATING); mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); priv->CurrentAuthentTransactionSeqNum = 0x0001; if (priv->wep_is_on && priv->exclude_unencrypted) - auth = C80211_MGMT_AAN_SHAREDKEY; + auth = WLAN_AUTH_SHARED_KEY; send_authentication_request(priv, auth, NULL, 0); } return; -- cgit v1.2.3-59-g8ed1b From 2c0f63166a5998102ddc7697706af83cbff49317 Mon Sep 17 00:00:00 2001 From: Andreas Happe Date: Thu, 5 Jan 2006 19:40:07 +0100 Subject: [PATCH] ipw2200: add monitor and qos entries to Kconfig I have made a stupid copy&paste error: QoS option is named IPW_QOS not IPW2200_MONITOR. Spotted by Daniel Paschka, thanks. Add the following config entries for the ipw2200 driver to drivers/net/wireless/Kconfig * IPW2200_MONITOR enables Monitor mode * IPW_QOS enables QoS feature - this is under development right now, so it depends upon EXPERIMENTAL Signed-off-by: Andreas Happe Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 7587df760ecb..f389467f835e 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -216,6 +216,19 @@ config IPW2200 say M here and read . The module will be called ipw2200.ko. +config IPW2200_MONITOR + bool "Enable promiscuous mode" + depends on IPW2200 + ---help--- + Enables promiscuous/monitor mode support for the ipw2200 driver. + With this feature compiled into the driver, you can switch to + promiscuous mode via the Wireless Tool's Monitor mode. While in this + mode, no packets can be sent. + +config IPW_QOS + bool "Enable QoS support" + depends on IPW2200 && EXPERIMENTAL + config IPW2200_DEBUG bool "Enable full debugging output in IPW2200 module." depends on IPW2200 -- cgit v1.2.3-59-g8ed1b From 23afaec4441baf0579fa115b626242d4d23704dd Mon Sep 17 00:00:00 2001 From: Stefan Rompf Date: Tue, 7 Feb 2006 03:42:23 +0800 Subject: [PATCH] ipw2200: Fix WPA network selection problem Do not avoid APs with wpa_ie or rsn_ie if !ieee->wpa_enabled There are broken APs out there that fill these elements even though encryption is disnabled. Also, this breaks legit WEP to WPA migration scenarious. We add a checking to prohibite WPA configured STA trying to associate with non-WPA supported APs. Signed-off-by: Stefan Rompf Signed-off-by: James Ketrenos Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 0702f0eeb784..02d2dae85c4c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -5533,8 +5533,8 @@ static int ipw_best_network(struct ipw_priv *priv, return 0; } - if (!priv->ieee->wpa_enabled && (network->wpa_ie_len > 0 || - network->rsn_ie_len > 0)) { + if (priv->ieee->wpa_enabled && + network->wpa_ie_len == 0 && network->rsn_ie_len == 0) { IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " "because of WPA capability mismatch.\n", escape_essid(network->ssid, network->ssid_len), -- cgit v1.2.3-59-g8ed1b From 47c51431fcc5fce3108e8e549cc9d243acd462ed Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Sun, 12 Feb 2006 11:53:04 -0600 Subject: [PATCH] trivial: fix spelling errors in Kconfigs This patch corrects a few spelling and grammar errors found in drivers/net Signed-off-by: Jon Mason Signed-off-by: John W. Linville --- drivers/net/Kconfig | 18 +++++++++--------- drivers/net/arcnet/Kconfig | 4 ++-- drivers/net/irda/Kconfig | 4 ++-- drivers/net/wan/Kconfig | 2 +- drivers/net/wireless/Kconfig | 6 +++--- 5 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 47c72a63dfe1..2610cedd55c7 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -66,7 +66,7 @@ config BONDING 'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux. The driver supports multiple bonding modes to allow for both high - perfomance and high availability operation. + performance and high availability operation. Refer to for more information. @@ -698,8 +698,8 @@ config VORTEX depends on NET_VENDOR_3COM && (PCI || EISA) select MII ---help--- - This option enables driver support for a large number of 10mbps and - 10/100mbps EISA, PCI and PCMCIA 3Com network cards: + This option enables driver support for a large number of 10Mbps and + 10/100Mbps EISA, PCI and PCMCIA 3Com network cards: "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI "Boomerang" (EtherLink XL 3c900 or 3c905) PCI @@ -1021,7 +1021,7 @@ config EEXPRESS_PRO depends on NET_ISA ---help--- If you have a network (Ethernet) card of this type, say Y. This - driver supports intel i82595{FX,TX} based boards. Note however + driver supports Intel i82595{FX,TX} based boards. Note however that the EtherExpress PRO/100 Ethernet card has its own separate driver. Please read the Ethernet-HOWTO, available from . @@ -1207,7 +1207,7 @@ config IBM_EMAC_RX_SKB_HEADROOM help Additional receive skb headroom. Note, that driver will always reserve at least 2 bytes to make IP header - aligned, so usualy there is no need to add any additional + aligned, so usually there is no need to add any additional headroom. If unsure, set to 0. @@ -1933,7 +1933,7 @@ config MYRI_SBUS will be called myri_sbus. This is recommended. config NS83820 - tristate "National Semiconduct DP83820 support" + tristate "National Semiconductor DP83820 support" depends on PCI help This is a driver for the National Semiconductor DP83820 series @@ -2514,7 +2514,7 @@ config PPP_FILTER Say Y here if you want to be able to filter the packets passing over PPP interfaces. This allows you to control which packets count as activity (i.e. which packets will reset the idle timer or bring up - a demand-dialled link) and which packets are to be dropped entirely. + a demand-dialed link) and which packets are to be dropped entirely. You need to say Y here if you wish to use the pass-filter and active-filter options to pppd. @@ -2702,8 +2702,8 @@ config SHAPER for more information. An alternative to this traffic shaper is the experimental - Class-Based Queueing (CBQ) scheduling support which you get if you - say Y to "QoS and/or fair queueing" above. + Class-Based Queuing (CBQ) scheduling support which you get if you + say Y to "QoS and/or fair queuing" above. To compile this driver as a module, choose M here: the module will be called shaper. If unsure, say N. diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig index 948de2532a1e..7284ccad0b91 100644 --- a/drivers/net/arcnet/Kconfig +++ b/drivers/net/arcnet/Kconfig @@ -68,10 +68,10 @@ config ARCNET_CAP packet is stuffed with an extra 4 byte "cookie" which doesn't actually appear on the network. After transmit the driver will send back a packet with protocol byte 0 containing the status of the - transmition: + transmission: 0=no hardware acknowledge 1=excessive nak - 2=transmition accepted by the reciever hardware + 2=transmission accepted by the receiver hardware Received packets are also stuffed with the extra 4 bytes but it will be random data. diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index 7a081346f079..c81fe1c382d5 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -283,7 +283,7 @@ config USB_IRDA Say Y here if you want to build support for the USB IrDA FIR Dongle device driver. To compile it as a module, choose M here: the module will be called irda-usb. IrDA-USB support the various IrDA USB - dongles available and most of their pecularities. Those dongles + dongles available and most of their peculiarities. Those dongles plug in the USB port of your computer, are plug and play, and support SIR and FIR (4Mbps) speeds. On the other hand, those dongles tend to be less efficient than a FIR chipset. @@ -360,7 +360,7 @@ config ALI_FIR help Say Y here if you want to build support for the ALi M5123 FIR Controller. The ALi M5123 FIR Controller is embedded in ALi M1543C, - M1535, M1535D, M1535+, M1535D Sourth Bridge. This driver supports + M1535, M1535D, M1535+, M1535D South Bridge. This driver supports SIR, MIR and FIR (4Mbps) speeds. To compile it as a module, choose M here: the module will be called diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 18c27e1e7884..883cf7da10fc 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -459,7 +459,7 @@ config WANPIPE_FR bool "WANPIPE Frame Relay support" depends on VENDOR_SANGOMA help - Connect a WANPIPE card to a Frame Relay network, or use Frame Felay + Connect a WANPIPE card to a Frame Relay network, or use Frame Relay API to develop custom applications. Contains the Ethernet Bridging over Frame Relay feature, where diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index f389467f835e..5b0a19a5058d 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -204,7 +204,7 @@ config IPW2200 In order to use this driver, you will need a firmware image for it. You can obtain the firmware from . See the above referenced README.ipw2200 - for information on where to install the firmare images. + for information on where to install the firmware images. You will also very likely need the Wireless Tools in order to configure your card: @@ -262,7 +262,7 @@ config AIRO PCI 802.11 wireless cards. It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X - with or without encryption) as well as card before the Cisco - aquisition (Aironet 4500, Aironet 4800, Aironet 4800B). + acquisition (Aironet 4500, Aironet 4800, Aironet 4800B). This driver support both the standard Linux Wireless Extensions and Cisco proprietary API, so both the Linux Wireless Tools and the @@ -411,7 +411,7 @@ config AIRO_CS driver part of the Linux Pcmcia package. It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X - with or without encryption) as well as card before the Cisco - aquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also + acquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also supports OEM of Cisco such as the DELL TrueMobile 4800 and Xircom 802.11b cards. -- cgit v1.2.3-59-g8ed1b From 1ba61e05e254a587b7a6be9484a8bcd973551be1 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Wed, 15 Feb 2006 13:00:55 +0800 Subject: [PATCH] ipw2200: Fix software crypto shared WEP authentication problem We didn't set the WEP key to hardware when we are using software based crypto. Hardware needs the key to do WEP authentication even for software based encryption. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 02d2dae85c4c..30b13a6e6fd9 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7061,8 +7061,7 @@ static int ipw_associate_network(struct ipw_priv *priv, priv->assoc_request.auth_type = AUTH_SHARED_KEY; priv->assoc_request.auth_key = priv->ieee->sec.active_key; - if ((priv->ieee->sec.level == SEC_LEVEL_1) && - !(priv->ieee->host_encrypt || priv->ieee->host_decrypt)) + if (priv->ieee->sec.level == SEC_LEVEL_1) ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); } else if ((priv->capability & CAP_PRIVACY_ON) && -- cgit v1.2.3-59-g8ed1b From 22d8846e5ce329436628da71a4239ccc2745869f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 5 Feb 2006 18:00:30 -0500 Subject: [PATCH] wireless/airo: fix setting TX key index plus key in ENCODEEXT The previous patch that added ENCODEEXT and AUTH support to the airo driver contained a slight error which would cause setting the TX key index ignore a valid key-set request at the same time. This patch allows any combination of setting the TX key index and setting an encryption key. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index ef6495b07890..b96b6dbe01f9 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -6266,7 +6266,7 @@ static int airo_set_encodeext(struct net_device *dev, CapabilityRid cap_rid; /* Card capability info */ int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 ); u16 currentAuthType = local->config.authType; - int idx, key_len, alg = ext->alg; /* Check encryption mode */ + int idx, key_len, alg = ext->alg, set_key = 1; wep_key_t key; /* Is WEP supported ? */ @@ -6289,10 +6289,15 @@ static int airo_set_encodeext(struct net_device *dev, if (encoding->flags & IW_ENCODE_DISABLED) alg = IW_ENCODE_ALG_NONE; - /* Just setting the transmit key? */ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + /* Only set transmit key index here, actual + * key is set below if needed. + */ set_wep_key(local, idx, NULL, 0, perm, 1); - } else { + set_key = ext->key_len > 0 ? 1 : 0; + } + + if (set_key) { /* Set the requested key first */ memset(key.key, 0, MAX_KEY_SIZE); switch (alg) { -- cgit v1.2.3-59-g8ed1b From 18a43ba26dcbe2a7a51011c9daae37adc7fc5c93 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Wed, 15 Feb 2006 01:01:58 -0500 Subject: kbuild: remove checkconfig.pl checkconfig.pl is no longer needed now that autoconf.h is automatically included. Remove it and all references to it. Signed-off-by: Brian Gerst Signed-off-by: Sam Ravnborg --- Documentation/smart-config.txt | 4 -- drivers/video/matrox/matroxfb_DAC1064.c | 1 - drivers/video/matrox/matroxfb_DAC1064.h | 1 - drivers/video/matrox/matroxfb_Ti3026.c | 1 - drivers/video/matrox/matroxfb_Ti3026.h | 1 - drivers/video/matrox/matroxfb_base.c | 1 - drivers/video/matrox/matroxfb_misc.c | 1 - scripts/checkconfig.pl | 65 --------------------------------- 8 files changed, 75 deletions(-) delete mode 100755 scripts/checkconfig.pl (limited to 'drivers') diff --git a/Documentation/smart-config.txt b/Documentation/smart-config.txt index c9bed4cf8773..8467447b5a87 100644 --- a/Documentation/smart-config.txt +++ b/Documentation/smart-config.txt @@ -56,10 +56,6 @@ Here is the solution: writing one file per option. It updates only the files for options that have changed. - mkdep.c no longer generates warning messages for missing or unneeded - lines. The new top-level target 'make checkconfig' - checks for these problems. - Flag Dependencies Martin Von Loewis contributed another feature to this patch: diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 0fbd9b5149f1..a456e67a5b00 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -12,7 +12,6 @@ * */ -/* make checkconfig does not walk through include tree :-( */ #include #include "matroxfb_DAC1064.h" diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h index a6a470127289..2e7238aa2432 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.h +++ b/drivers/video/matrox/matroxfb_DAC1064.h @@ -1,7 +1,6 @@ #ifndef __MATROXFB_DAC1064_H__ #define __MATROXFB_DAC1064_H__ -/* make checkconfig does not walk through include tree */ #include #include "matroxfb_base.h" diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c index 537ade5d8b21..23ebad0a12d8 100644 --- a/drivers/video/matrox/matroxfb_Ti3026.c +++ b/drivers/video/matrox/matroxfb_Ti3026.c @@ -78,7 +78,6 @@ * */ -/* make checkconfig does not verify included files... */ #include #include "matroxfb_Ti3026.h" diff --git a/drivers/video/matrox/matroxfb_Ti3026.h b/drivers/video/matrox/matroxfb_Ti3026.h index 541933d7e4ea..536e5f69de9f 100644 --- a/drivers/video/matrox/matroxfb_Ti3026.h +++ b/drivers/video/matrox/matroxfb_Ti3026.h @@ -1,7 +1,6 @@ #ifndef __MATROXFB_TI3026_H__ #define __MATROXFB_TI3026_H__ -/* make checkconfig does not walk through whole include tree */ #include #include "matroxfb_base.h" diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 4055ff6f5a81..951c9974a1d3 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -99,7 +99,6 @@ * */ -/* make checkconfig does not check included files... */ #include #include diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c index 455a46ce840c..263d801ef78f 100644 --- a/drivers/video/matrox/matroxfb_misc.c +++ b/drivers/video/matrox/matroxfb_misc.c @@ -84,7 +84,6 @@ * */ -/* make checkconfig does not check includes for this... */ #include #include "matroxfb_misc.h" diff --git a/scripts/checkconfig.pl b/scripts/checkconfig.pl deleted file mode 100755 index ca1f231b15a6..000000000000 --- a/scripts/checkconfig.pl +++ /dev/null @@ -1,65 +0,0 @@ -#! /usr/bin/perl -# -# checkconfig: find uses of CONFIG_* names without matching definitions. -# Copyright abandoned, 1998, Michael Elizabeth Chastain . - -use integer; - -$| = 1; - -foreach $file (@ARGV) -{ - # Open this file. - open(FILE, $file) || die "Can't open $file: $!\n"; - - # Initialize variables. - my $fInComment = 0; - my $fInString = 0; - my $fUseConfig = 0; - my $iLinuxConfig = 0; - my %configList = (); - - LINE: while ( ) - { - # Strip comments. - $fInComment && (s+^.*?\*/+ +o ? ($fInComment = 0) : next); - m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1))); - - # Pick up definitions. - if ( m/^\s*#/o ) - { - $iLinuxConfig = $. if m/^\s*#\s*include\s*"linux\/config\.h"/o; - $configList{uc $1} = 1 if m/^\s*#\s*include\s*"config\/(\S*)\.h"/o; - } - - # Strip strings. - $fInString && (s+^.*?"+ +o ? ($fInString = 0) : next); - m+"+o && (s+".*?"+ +go, (s+".*$+ +o && ($fInString = 1))); - - # Pick up definitions. - if ( m/^\s*#/o ) - { - $iLinuxConfig = $. if m/^\s*#\s*include\s*/o; - $configList{uc $1} = 1 if m/^\s*#\s*include\s*/o; - $configList{$1} = 1 if m/^\s*#\s*define\s+CONFIG_(\w*)/o; - $configList{$1} = 1 if m/^\s*#\s*undef\s+CONFIG_(\w*)/o; - } - - # Look for usages. - next unless m/CONFIG_/o; - WORD: while ( m/\bCONFIG_(\w+)/og ) - { - $fUseConfig = 1; - last LINE if $iLinuxConfig; - next WORD if exists $configList{$1}; - print "$file: $.: need CONFIG_$1.\n"; - $configList{$1} = 0; - } - } - - # Report superfluous includes. - if ( $iLinuxConfig && ! $fUseConfig ) - { print "$file: $iLinuxConfig: linux/config.h not needed.\n"; } - - close(FILE); -} -- cgit v1.2.3-59-g8ed1b From 6a62a04d4705df4f9f9bee39e889b9e920eeca47 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 13 Feb 2006 10:02:46 +0900 Subject: [PATCH] libata: rename ata_dev_id_[c_]string() This patch renames ata_dev_id_[c_]string() to ata_id_[c_]string(). All other functions which read data from ATA ID data start with ata_id and those two function names were getting too long. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 23 +++++++++++------------ drivers/scsi/libata-scsi.c | 12 ++++++------ drivers/scsi/sata_sil.c | 3 +-- include/linux/libata.h | 8 ++++---- 4 files changed, 22 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index adc5b440c9bc..d694b20e81bf 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -486,7 +486,7 @@ ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err) } /** - * ata_dev_id_string - Convert IDENTIFY DEVICE page into string + * ata_id_string - Convert IDENTIFY DEVICE page into string * @id: IDENTIFY DEVICE results we will examine * @s: string into which data is output * @ofs: offset into identify device page @@ -500,8 +500,8 @@ ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err) * caller. */ -void ata_dev_id_string(const u16 *id, unsigned char *s, - unsigned int ofs, unsigned int len) +void ata_id_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len) { unsigned int c; @@ -520,27 +520,27 @@ void ata_dev_id_string(const u16 *id, unsigned char *s, } /** - * ata_dev_id_c_string - Convert IDENTIFY DEVICE page into C string + * ata_id_c_string - Convert IDENTIFY DEVICE page into C string * @id: IDENTIFY DEVICE results we will examine * @s: string into which data is output * @ofs: offset into identify device page * @len: length of string to return. must be an odd number. * - * This function is identical to ata_dev_id_string except that it + * This function is identical to ata_id_string except that it * trims trailing spaces and terminates the resulting string with * null. @len must be actual maximum length (even number) + 1. * * LOCKING: * caller. */ -void ata_dev_id_c_string(const u16 *id, unsigned char *s, - unsigned int ofs, unsigned int len) +void ata_id_c_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len) { unsigned char *p; WARN_ON(!(len & 1)); - ata_dev_id_string(id, s, ofs, len - 1); + ata_id_string(id, s, ofs, len - 1); p = s + strnlen(s, len - 1); while (p > s && p[-1] == ' ') @@ -2315,8 +2315,7 @@ static int ata_dma_blacklisted(const struct ata_device *dev) unsigned char model_num[41]; int i; - ata_dev_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); + ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++) if (!strcmp(ata_dma_blacklist[i], model_num)) @@ -4934,8 +4933,8 @@ EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_dev_classify); -EXPORT_SYMBOL_GPL(ata_dev_id_string); -EXPORT_SYMBOL_GPL(ata_dev_id_c_string); +EXPORT_SYMBOL_GPL(ata_id_string); +EXPORT_SYMBOL_GPL(ata_id_c_string); EXPORT_SYMBOL_GPL(ata_dev_config); EXPORT_SYMBOL_GPL(ata_scsi_simulate); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 86da46502b3e..538784e65cdc 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1567,8 +1567,8 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, if (buflen > 35) { memcpy(&rbuf[8], "ATA ", 8); - ata_dev_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16); - ata_dev_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4); + ata_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16); + ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4); if (rbuf[32] == 0 || rbuf[32] == ' ') memcpy(&rbuf[32], "n/a ", 4); } @@ -1642,8 +1642,8 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf, memcpy(rbuf, hdr, sizeof(hdr)); if (buflen > (ATA_SERNO_LEN + 4 - 1)) - ata_dev_id_string(args->id, (unsigned char *) &rbuf[4], - ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + ata_id_string(args->id, (unsigned char *) &rbuf[4], + ATA_ID_SERNO_OFS, ATA_SERNO_LEN); return 0; } @@ -1806,8 +1806,8 @@ static int ata_dev_supports_fua(u16 *id) if (!ata_id_has_fua(id)) return 0; - ata_dev_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model)); - ata_dev_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw)); + ata_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model)); + ata_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw)); if (strcmp(model, "Maxtor")) return 1; diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 15346888faf2..e14ed4ebbeed 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -338,8 +338,7 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) unsigned int n, quirks = 0; unsigned char model_num[41]; - ata_dev_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); + ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); for (n = 0; sil_blacklist[n].product; n++) if (!strcmp(sil_blacklist[n].product, model_num)) { diff --git a/include/linux/libata.h b/include/linux/libata.h index afe46457124e..0d6bf50ad029 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -538,10 +538,10 @@ extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, unsigned int n_elem); extern unsigned int ata_dev_classify(const struct ata_taskfile *tf); -extern void ata_dev_id_string(const u16 *id, unsigned char *s, - unsigned int ofs, unsigned int len); -extern void ata_dev_id_c_string(const u16 *id, unsigned char *s, - unsigned int ofs, unsigned int len); +extern void ata_id_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len); +extern void ata_id_c_string(const u16 *id, unsigned char *s, + unsigned int ofs, unsigned int len); extern void ata_dev_config(struct ata_port *ap, unsigned int i); extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc); -- cgit v1.2.3-59-g8ed1b From 6aff8f1f07a7fff48121d1ad4a550f3af24ccc81 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 15 Feb 2006 18:24:09 +0900 Subject: [PATCH] libata: update ata_dev_init_params() Update ata_dev_init_params() such that it doesn't disable port directly but return with appropriate error mask on failure. This is preparation for splitting ata_dev_identify(). Note that this patch changes behavior of dev_init_params failure such that only failing devices are taken offline not the whole port. This change is intended. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d694b20e81bf..76621463b499 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -62,7 +62,8 @@ #include "libata.h" static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev); -static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); +static unsigned int ata_dev_init_params(struct ata_port *ap, + struct ata_device *dev); static void ata_set_mode(struct ata_port *ap); static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift); @@ -1041,7 +1042,12 @@ retry: * Some drives were very specific about that exact sequence. */ if (major_version < 4 || (!ata_id_has_lba(dev->id))) { - ata_dev_init_params(ap, dev); + err_mask = ata_dev_init_params(ap, dev); + if (err_mask) { + printk(KERN_ERR "ata%u: failed to init " + "parameters, disabled\n", ap->id); + goto err_out; + } /* current CHS translation info (id[53-58]) might be * changed. reread the identify device info. @@ -2530,17 +2536,23 @@ err_out: * @dev: Device to which command will be sent * * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, AC_ERR_* mask otherwise. */ -static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev) +static unsigned int ata_dev_init_params(struct ata_port *ap, + struct ata_device *dev) { struct ata_taskfile tf; + unsigned int err_mask; u16 sectors = dev->id[6]; u16 heads = dev->id[3]; /* Number of sectors per track 1-255. Number of heads 1-16 */ if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16) - return; + return 0; /* set up init dev params taskfile */ DPRINTK("init dev params \n"); @@ -2552,13 +2564,10 @@ static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev) tf.nsect = sectors; tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */ - if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) { - printk(KERN_ERR "ata%u: failed to init parameters, disabled\n", - ap->id); - ata_port_disable(ap); - } + err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); - DPRINTK("EXIT\n"); + DPRINTK("EXIT, err_mask=%x\n", err_mask); + return err_mask; } /** -- cgit v1.2.3-59-g8ed1b From ee407b02f3f1992bc746876c26f8175c8783562b Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Sat, 4 Feb 2006 13:13:17 -0500 Subject: [PATCH] forcedeth: Add vlan support This forcedeth patch adds support for vlan stripping/inserting in hardware. Signed-off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 76 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 3682ec61e8a8..0fbe342c2ac9 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -102,6 +102,7 @@ * 0.47: 26 Oct 2005: Add phyaddr 0 in phy scan. * 0.48: 24 Dec 2005: Disable TSO, bugfix for pci_map_single * 0.49: 10 Dec 2005: Fix tso for large buffers. + * 0.50: 20 Jan 2006: Add 8021pq tagging support. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -113,7 +114,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.49" +#define FORCEDETH_VERSION "0.50" #define DRV_NAME "forcedeth" #include @@ -153,6 +154,7 @@ #define DEV_HAS_LARGEDESC 0x0004 /* device supports jumbo frames and needs packet format 2 */ #define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */ #define DEV_HAS_CHECKSUM 0x0010 /* device supports tx and rx checksum offloads */ +#define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */ enum { NvRegIrqStatus = 0x000, @@ -254,6 +256,8 @@ enum { #define NVREG_TXRXCTL_DESC_1 0 #define NVREG_TXRXCTL_DESC_2 0x02100 #define NVREG_TXRXCTL_DESC_3 0x02200 +#define NVREG_TXRXCTL_VLANSTRIP 0x00040 +#define NVREG_TXRXCTL_VLANINS 0x00080 NvRegMIIStatus = 0x180, #define NVREG_MIISTAT_ERROR 0x0001 #define NVREG_MIISTAT_LINKCHANGE 0x0008 @@ -303,6 +307,8 @@ enum { #define NVREG_POWERSTATE_D1 0x0001 #define NVREG_POWERSTATE_D2 0x0002 #define NVREG_POWERSTATE_D3 0x0003 + NvRegVlanControl = 0x300, +#define NVREG_VLANCONTROL_ENABLE 0x2000 }; /* Big endian: should work, but is untested */ @@ -314,7 +320,7 @@ struct ring_desc { struct ring_desc_ex { u32 PacketBufferHigh; u32 PacketBufferLow; - u32 Reserved; + u32 TxVlan; u32 FlagLen; }; @@ -355,6 +361,8 @@ typedef union _ring_type { #define NV_TX2_CHECKSUM_L3 (1<<27) #define NV_TX2_CHECKSUM_L4 (1<<26) +#define NV_TX3_VLAN_TAG_PRESENT (1<<18) + #define NV_RX_DESCRIPTORVALID (1<<16) #define NV_RX_MISSEDFRAME (1<<17) #define NV_RX_SUBSTRACT1 (1<<18) @@ -385,6 +393,9 @@ typedef union _ring_type { #define NV_RX2_ERROR (1<<30) #define NV_RX2_AVAIL (1<<31) +#define NV_RX3_VLAN_TAG_PRESENT (1<<16) +#define NV_RX3_VLAN_TAG_MASK (0x0000FFFF) + /* Miscelaneous hardware related defines: */ #define NV_PCI_REGSZ 0x270 @@ -511,6 +522,7 @@ struct fe_priv { u32 irqmask; u32 desc_ver; u32 txrxctl_bits; + u32 vlanctl_bits; void __iomem *base; @@ -540,6 +552,9 @@ struct fe_priv { dma_addr_t tx_dma[TX_RING]; unsigned int tx_dma_len[TX_RING]; u32 tx_flags; + + /* vlan fields */ + struct vlan_group *vlangrp; }; /* @@ -1031,6 +1046,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) u32 bcnt; u32 size = skb->len-skb->data_len; u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); + u32 tx_flags_vlan = 0; /* add fragments to entries count */ for (i = 0; i < fragments; i++) { @@ -1111,10 +1127,16 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) #endif tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); + /* vlan tag */ + if (np->vlangrp && vlan_tx_tag_present(skb)) { + tx_flags_vlan = NV_TX3_VLAN_TAG_PRESENT | vlan_tx_tag_get(skb); + } + /* set tx flags */ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { np->tx_ring.orig[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra); } else { + np->tx_ring.ex[start_nr].TxVlan = cpu_to_le32(tx_flags_vlan); np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra); } @@ -1342,6 +1364,8 @@ static void nv_rx_process(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); u32 Flags; + u32 vlanflags = 0; + for (;;) { struct sk_buff *skb; @@ -1357,6 +1381,7 @@ static void nv_rx_process(struct net_device *dev) } else { Flags = le32_to_cpu(np->rx_ring.ex[i].FlagLen); len = nv_descr_getlength_ex(&np->rx_ring.ex[i], np->desc_ver); + vlanflags = le32_to_cpu(np->rx_ring.ex[i].PacketBufferLow); } dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, Flags 0x%x.\n", @@ -1474,7 +1499,11 @@ static void nv_rx_process(struct net_device *dev) skb->protocol = eth_type_trans(skb, dev); dprintk(KERN_DEBUG "%s: nv_rx_process: packet %d with %d bytes, proto %d accepted.\n", dev->name, np->cur_rx, len, skb->protocol); - netif_rx(skb); + if (np->vlangrp && (vlanflags & NV_RX3_VLAN_TAG_PRESENT)) { + vlan_hwaccel_rx(skb, np->vlangrp, vlanflags & NV_RX3_VLAN_TAG_MASK); + } else { + netif_rx(skb); + } dev->last_rx = jiffies; np->stats.rx_packets++; np->stats.rx_bytes += len; @@ -2217,6 +2246,34 @@ static struct ethtool_ops ops = { .get_perm_addr = ethtool_op_get_perm_addr, }; +static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) +{ + struct fe_priv *np = get_nvpriv(dev); + + spin_lock_irq(&np->lock); + + /* save vlan group */ + np->vlangrp = grp; + + if (grp) { + /* enable vlan on MAC */ + np->txrxctl_bits |= NVREG_TXRXCTL_VLANSTRIP | NVREG_TXRXCTL_VLANINS; + } else { + /* disable vlan on MAC */ + np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANSTRIP; + np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANINS; + } + + writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); + + spin_unlock_irq(&np->lock); +}; + +static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +{ + /* nothing to do */ +}; + static int nv_open(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); @@ -2265,6 +2322,7 @@ static int nv_open(struct net_device *dev) writel(np->linkspeed, base + NvRegLinkSpeed); writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3); writel(np->txrxctl_bits, base + NvRegTxRxControl); + writel(np->vlanctl_bits, base + NvRegVlanControl); pci_push(base); writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl); reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, @@ -2496,6 +2554,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i #endif } + np->vlanctl_bits = 0; + if (id->driver_data & DEV_HAS_VLAN) { + np->vlanctl_bits = NVREG_VLANCONTROL_ENABLE; + dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX; + dev->vlan_rx_register = nv_vlan_rx_register; + dev->vlan_rx_kill_vid = nv_vlan_rx_kill_vid; + } + err = -ENOMEM; np->base = ioremap(addr, NV_PCI_REGSZ); if (!np->base) @@ -2737,11 +2803,11 @@ static struct pci_device_id pci_tbl[] = { }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN, }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN, }, {0,}, }; -- cgit v1.2.3-59-g8ed1b From 0832b25a75d128e4f9724156380ba071c4f3f20d Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Sat, 4 Feb 2006 13:13:26 -0500 Subject: [PATCH] forcedeth: Add support for 64bit rings This forcedeth patch adds high dma support for tx/rx rings. Signed-off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 58 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 0fbe342c2ac9..870613bf3fd6 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -103,6 +103,7 @@ * 0.48: 24 Dec 2005: Disable TSO, bugfix for pci_map_single * 0.49: 10 Dec 2005: Fix tso for large buffers. * 0.50: 20 Jan 2006: Add 8021pq tagging support. + * 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -114,7 +115,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.50" +#define FORCEDETH_VERSION "0.51" #define DRV_NAME "forcedeth" #include @@ -258,6 +259,8 @@ enum { #define NVREG_TXRXCTL_DESC_3 0x02200 #define NVREG_TXRXCTL_VLANSTRIP 0x00040 #define NVREG_TXRXCTL_VLANINS 0x00080 + NvRegTxRingPhysAddrHigh = 0x148, + NvRegRxRingPhysAddrHigh = 0x14C, NvRegMIIStatus = 0x180, #define NVREG_MIISTAT_ERROR 0x0001 #define NVREG_MIISTAT_LINKCHANGE 0x0008 @@ -627,6 +630,33 @@ static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target, return 0; } +#define NV_SETUP_RX_RING 0x01 +#define NV_SETUP_TX_RING 0x02 + +static void setup_hw_rings(struct net_device *dev, int rxtx_flags) +{ + struct fe_priv *np = get_nvpriv(dev); + u8 __iomem *base = get_hwbase(dev); + + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + if (rxtx_flags & NV_SETUP_RX_RING) { + writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr); + } + if (rxtx_flags & NV_SETUP_TX_RING) { + writel((u32) cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr); + } + } else { + if (rxtx_flags & NV_SETUP_RX_RING) { + writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr); + writel((u32) (cpu_to_le64(np->ring_addr) >> 32), base + NvRegRxRingPhysAddrHigh); + } + if (rxtx_flags & NV_SETUP_TX_RING) { + writel((u32) cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr); + writel((u32) (cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)) >> 32), base + NvRegTxRingPhysAddrHigh); + } + } +} + #define MII_READ (-1) /* mii_rw: read/write a register on the PHY. * @@ -1295,10 +1325,7 @@ static void nv_tx_timeout(struct net_device *dev) printk(KERN_DEBUG "%s: tx_timeout: dead entries!\n", dev->name); nv_drain_tx(dev); np->next_tx = np->nic_tx = 0; - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr); - else - writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr); + setup_hw_rings(dev, NV_SETUP_TX_RING); netif_wake_queue(dev); } @@ -1573,11 +1600,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) } /* reinit nic view of the rx queue */ writel(np->rx_buf_sz, base + NvRegOffloadConfig); - writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr); - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr); - else - writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr); + setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes); pci_push(base); @@ -2310,11 +2333,7 @@ static int nv_open(struct net_device *dev) nv_copy_mac_to_hw(dev); /* 4) give hw rings */ - writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr); - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr); - else - writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr); + setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes); @@ -2529,7 +2548,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", pci_name(pci_dev)); } else { - dev->features |= NETIF_F_HIGHDMA; + if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) { + printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n", + pci_name(pci_dev)); + goto out_relreg; + } else { + dev->features |= NETIF_F_HIGHDMA; + printk(KERN_INFO "forcedeth: using HIGHDMA\n"); + } } np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; } else if (id->driver_data & DEV_HAS_LARGEDESC) { -- cgit v1.2.3-59-g8ed1b From d33a73c81241e3d9ab8da2d0558429bdd5b4ef9a Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Sat, 4 Feb 2006 13:13:31 -0500 Subject: [PATCH] forcedeth: Add support for MSI/MSIX This forcedeth patch adds support for MSI/MSIX interrupts. Signed-off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 467 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 436 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 870613bf3fd6..e7fc28b07e5a 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -104,6 +104,7 @@ * 0.49: 10 Dec 2005: Fix tso for large buffers. * 0.50: 20 Jan 2006: Add 8021pq tagging support. * 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings. + * 0.52: 20 Jan 2006: Add MSI/MSIX support. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -115,7 +116,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.51" +#define FORCEDETH_VERSION "0.52" #define DRV_NAME "forcedeth" #include @@ -156,6 +157,8 @@ #define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */ #define DEV_HAS_CHECKSUM 0x0010 /* device supports tx and rx checksum offloads */ #define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */ +#define DEV_HAS_MSI 0x0040 /* device supports MSI */ +#define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ enum { NvRegIrqStatus = 0x000, @@ -169,14 +172,17 @@ enum { #define NVREG_IRQ_TX_OK 0x0010 #define NVREG_IRQ_TIMER 0x0020 #define NVREG_IRQ_LINK 0x0040 -#define NVREG_IRQ_TX_ERROR 0x0080 -#define NVREG_IRQ_TX1 0x0100 +#define NVREG_IRQ_RX_FORCED 0x0080 +#define NVREG_IRQ_TX_FORCED 0x0100 #define NVREG_IRQMASK_THROUGHPUT 0x00df #define NVREG_IRQMASK_CPU 0x0040 +#define NVREG_IRQ_TX_ALL (NVREG_IRQ_TX_ERR|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_FORCED) +#define NVREG_IRQ_RX_ALL (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_RX_FORCED) +#define NVREG_IRQ_OTHER (NVREG_IRQ_TIMER|NVREG_IRQ_LINK) #define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \ - NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX_ERROR| \ - NVREG_IRQ_TX1)) + NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RX_FORCED| \ + NVREG_IRQ_TX_FORCED)) NvRegUnknownSetupReg6 = 0x008, #define NVREG_UNKSETUP6_VAL 3 @@ -188,6 +194,10 @@ enum { NvRegPollingInterval = 0x00c, #define NVREG_POLL_DEFAULT_THROUGHPUT 970 #define NVREG_POLL_DEFAULT_CPU 13 + NvRegMSIMap0 = 0x020, + NvRegMSIMap1 = 0x024, + NvRegMSIIrqMask = 0x030, +#define NVREG_MSI_VECTOR_0_ENABLED 0x01 NvRegMisc1 = 0x080, #define NVREG_MISC1_HD 0x02 #define NVREG_MISC1_FORCE 0x3b0f3c @@ -312,6 +322,9 @@ enum { #define NVREG_POWERSTATE_D3 0x0003 NvRegVlanControl = 0x300, #define NVREG_VLANCONTROL_ENABLE 0x2000 + NvRegMSIXMap0 = 0x3e0, + NvRegMSIXMap1 = 0x3e4, + NvRegMSIXIrqStatus = 0x3f0, }; /* Big endian: should work, but is untested */ @@ -489,6 +502,18 @@ typedef union _ring_type { #define LPA_1000FULL 0x0800 #define LPA_1000HALF 0x0400 +/* MSI/MSI-X defines */ +#define NV_MSI_X_MAX_VECTORS 8 +#define NV_MSI_X_VECTORS_MASK 0x000f +#define NV_MSI_CAPABLE 0x0010 +#define NV_MSI_X_CAPABLE 0x0020 +#define NV_MSI_ENABLED 0x0040 +#define NV_MSI_X_ENABLED 0x0080 + +#define NV_MSI_X_VECTOR_ALL 0x0 +#define NV_MSI_X_VECTOR_RX 0x0 +#define NV_MSI_X_VECTOR_TX 0x1 +#define NV_MSI_X_VECTOR_OTHER 0x2 /* * SMP locking: @@ -540,6 +565,7 @@ struct fe_priv { unsigned int pkt_limit; struct timer_list oom_kick; struct timer_list nic_poll; + u32 nic_poll_irq; /* media detection workaround. * Locking: Within irq hander or disable_irq+spin_lock(&np->lock); @@ -558,6 +584,10 @@ struct fe_priv { /* vlan fields */ struct vlan_group *vlangrp; + + /* msi/msi-x fields */ + u32 msi_flags; + struct msix_entry msi_x_entry[NV_MSI_X_MAX_VECTORS]; }; /* @@ -585,6 +615,16 @@ static int optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT; */ static int poll_interval = -1; +/* + * Disable MSI interrupts + */ +static int disable_msi = 0; + +/* + * Disable MSIX interrupts + */ +static int disable_msix = 0; + static inline struct fe_priv *get_nvpriv(struct net_device *dev) { return netdev_priv(dev); @@ -948,14 +988,27 @@ static void nv_do_rx_refill(unsigned long data) struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); - disable_irq(dev->irq); + + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + disable_irq(dev->irq); + } else { + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); + } if (nv_alloc_rx(dev)) { spin_lock(&np->lock); if (!np->in_shutdown) mod_timer(&np->oom_kick, jiffies + OOM_REFILL); spin_unlock(&np->lock); } - enable_irq(dev->irq); + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + enable_irq(dev->irq); + } else { + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); + } } static void nv_init_rx(struct net_device *dev) @@ -1010,7 +1063,7 @@ static int nv_release_txskb(struct net_device *dev, unsigned int skbnr) } if (np->tx_skbuff[skbnr]) { - dev_kfree_skb_irq(np->tx_skbuff[skbnr]); + dev_kfree_skb_any(np->tx_skbuff[skbnr]); np->tx_skbuff[skbnr] = NULL; return 1; } else { @@ -1261,9 +1314,14 @@ static void nv_tx_timeout(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); + u32 status; + + if (np->msi_flags & NV_MSI_X_ENABLED) + status = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; + else + status = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; - printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name, - readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK); + printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name, status); { int i; @@ -1579,7 +1637,15 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) * guessed, there is probably a simpler approach. * Changing the MTU is a rare event, it shouldn't matter. */ - disable_irq(dev->irq); + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + disable_irq(dev->irq); + } else { + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); + } spin_lock_bh(&dev->xmit_lock); spin_lock(&np->lock); /* stop engines */ @@ -1612,7 +1678,15 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) nv_start_tx(dev); spin_unlock(&np->lock); spin_unlock_bh(&dev->xmit_lock); - enable_irq(dev->irq); + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + enable_irq(dev->irq); + } else { + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); + } } return 0; } @@ -1918,8 +1992,13 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs) dprintk(KERN_DEBUG "%s: nv_nic_irq\n", dev->name); for (i=0; ; i++) { - events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; - writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); + if (!(np->msi_flags & NV_MSI_X_ENABLED)) { + events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; + writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); + } else { + events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; + writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); + } pci_push(base); dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); if (!(events & np->irqmask)) @@ -1959,11 +2038,16 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs) if (i > max_interrupt_work) { spin_lock(&np->lock); /* disable interrupts on the nic */ - writel(0, base + NvRegIrqMask); + if (!(np->msi_flags & NV_MSI_X_ENABLED)) + writel(0, base + NvRegIrqMask); + else + writel(np->irqmask, base + NvRegIrqMask); pci_push(base); - if (!np->in_shutdown) + if (!np->in_shutdown) { + np->nic_poll_irq = np->irqmask; mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + } printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); spin_unlock(&np->lock); break; @@ -1975,22 +2059,212 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs) return IRQ_RETVAL(i); } +static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) data; + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + u32 events; + int i; + + dprintk(KERN_DEBUG "%s: nv_nic_irq_tx\n", dev->name); + + for (i=0; ; i++) { + events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL; + writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus); + pci_push(base); + dprintk(KERN_DEBUG "%s: tx irq: %08x\n", dev->name, events); + if (!(events & np->irqmask)) + break; + + spin_lock(&np->lock); + nv_tx_done(dev); + spin_unlock(&np->lock); + + if (events & (NVREG_IRQ_TX_ERR)) { + dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", + dev->name, events); + } + if (i > max_interrupt_work) { + spin_lock(&np->lock); + /* disable interrupts on the nic */ + writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); + pci_push(base); + + if (!np->in_shutdown) { + np->nic_poll_irq |= NVREG_IRQ_TX_ALL; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + } + printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); + spin_unlock(&np->lock); + break; + } + + } + dprintk(KERN_DEBUG "%s: nv_nic_irq_tx completed\n", dev->name); + + return IRQ_RETVAL(i); +} + +static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) data; + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + u32 events; + int i; + + dprintk(KERN_DEBUG "%s: nv_nic_irq_rx\n", dev->name); + + for (i=0; ; i++) { + events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL; + writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus); + pci_push(base); + dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events); + if (!(events & np->irqmask)) + break; + + nv_rx_process(dev); + if (nv_alloc_rx(dev)) { + spin_lock(&np->lock); + if (!np->in_shutdown) + mod_timer(&np->oom_kick, jiffies + OOM_REFILL); + spin_unlock(&np->lock); + } + + if (i > max_interrupt_work) { + spin_lock(&np->lock); + /* disable interrupts on the nic */ + writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); + pci_push(base); + + if (!np->in_shutdown) { + np->nic_poll_irq |= NVREG_IRQ_RX_ALL; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + } + printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); + spin_unlock(&np->lock); + break; + } + + } + dprintk(KERN_DEBUG "%s: nv_nic_irq_rx completed\n", dev->name); + + return IRQ_RETVAL(i); +} + +static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) data; + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + u32 events; + int i; + + dprintk(KERN_DEBUG "%s: nv_nic_irq_other\n", dev->name); + + for (i=0; ; i++) { + events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_OTHER; + writel(NVREG_IRQ_OTHER, base + NvRegMSIXIrqStatus); + pci_push(base); + dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); + if (!(events & np->irqmask)) + break; + + if (events & NVREG_IRQ_LINK) { + spin_lock(&np->lock); + nv_link_irq(dev); + spin_unlock(&np->lock); + } + if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { + spin_lock(&np->lock); + nv_linkchange(dev); + spin_unlock(&np->lock); + np->link_timeout = jiffies + LINK_TIMEOUT; + } + if (events & (NVREG_IRQ_UNKNOWN)) { + printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", + dev->name, events); + } + if (i > max_interrupt_work) { + spin_lock(&np->lock); + /* disable interrupts on the nic */ + writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); + pci_push(base); + + if (!np->in_shutdown) { + np->nic_poll_irq |= NVREG_IRQ_OTHER; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + } + printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); + spin_unlock(&np->lock); + break; + } + + } + dprintk(KERN_DEBUG "%s: nv_nic_irq_other completed\n", dev->name); + + return IRQ_RETVAL(i); +} + static void nv_do_nic_poll(unsigned long data) { struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); + u32 mask = 0; - disable_irq(dev->irq); - /* FIXME: Do we need synchronize_irq(dev->irq) here? */ /* + * First disable irq(s) and then * reenable interrupts on the nic, we have to do this before calling * nv_nic_irq because that may decide to do otherwise */ - writel(np->irqmask, base + NvRegIrqMask); + + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + disable_irq(dev->irq); + mask = np->irqmask; + } else { + if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); + mask |= NVREG_IRQ_RX_ALL; + } + if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) { + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); + mask |= NVREG_IRQ_TX_ALL; + } + if (np->nic_poll_irq & NVREG_IRQ_OTHER) { + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); + mask |= NVREG_IRQ_OTHER; + } + } + np->nic_poll_irq = 0; + + /* FIXME: Do we need synchronize_irq(dev->irq) here? */ + + writel(mask, base + NvRegIrqMask); pci_push(base); - nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL); - enable_irq(dev->irq); + + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL); + enable_irq(dev->irq); + } else { + if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { + nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL); + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); + } + if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) { + nv_nic_irq_tx((int) 0, (void *) data, (struct pt_regs *) NULL); + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); + } + if (np->nic_poll_irq & NVREG_IRQ_OTHER) { + nv_nic_irq_other((int) 0, (void *) data, (struct pt_regs *) NULL); + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); + } + } } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2297,11 +2571,38 @@ static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) /* nothing to do */ }; +static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask) +{ + u8 __iomem *base = get_hwbase(dev); + int i; + u32 msixmap = 0; + + /* Each interrupt bit can be mapped to a MSIX vector (4 bits). + * MSIXMap0 represents the first 8 interrupts and MSIXMap1 represents + * the remaining 8 interrupts. + */ + for (i = 0; i < 8; i++) { + if ((irqmask >> i) & 0x1) { + msixmap |= vector << (i << 2); + } + } + writel(readl(base + NvRegMSIXMap0) | msixmap, base + NvRegMSIXMap0); + + msixmap = 0; + for (i = 0; i < 8; i++) { + if ((irqmask >> (i + 8)) & 0x1) { + msixmap |= vector << (i << 2); + } + } + writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1); +} + static int nv_open(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - int ret, oom, i; + int ret = 1; + int oom, i; dprintk(KERN_DEBUG "nv_open: begin\n"); @@ -2392,9 +2693,77 @@ static int nv_open(struct net_device *dev) writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); pci_push(base); - ret = request_irq(dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev); - if (ret) - goto out_drain; + if (np->msi_flags & NV_MSI_X_CAPABLE) { + for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { + np->msi_x_entry[i].entry = i; + } + if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) { + np->msi_flags |= NV_MSI_X_ENABLED; + if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) { + /* Request irq for rx handling */ + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_drain; + } + /* Request irq for tx handling */ + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_drain; + } + /* Request irq for link and timer handling */ + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_drain; + } + + /* map interrupts to their respective vector */ + writel(0, base + NvRegMSIXMap0); + writel(0, base + NvRegMSIXMap1); + set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL); + set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL); + set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER); + } else { + /* Request irq for all interrupts */ + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_drain; + } + + /* map interrupts to vector 0 */ + writel(0, base + NvRegMSIXMap0); + writel(0, base + NvRegMSIXMap1); + } + } + } + if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { + if ((ret = pci_enable_msi(np->pci_dev)) == 0) { + np->msi_flags |= NV_MSI_ENABLED; + if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); + pci_disable_msi(np->pci_dev); + np->msi_flags &= ~NV_MSI_ENABLED; + goto out_drain; + } + + /* map interrupts to vector 0 */ + writel(0, base + NvRegMSIMap0); + writel(0, base + NvRegMSIMap1); + /* enable msi vector 0 */ + writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); + } + } + if (ret != 0) { + if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) + goto out_drain; + } /* ask for interrupts */ writel(np->irqmask, base + NvRegIrqMask); @@ -2441,6 +2810,7 @@ static int nv_close(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); u8 __iomem *base; + int i; spin_lock_irq(&np->lock); np->in_shutdown = 1; @@ -2458,13 +2828,31 @@ static int nv_close(struct net_device *dev) /* disable interrupts on the nic or we will lock up */ base = get_hwbase(dev); - writel(0, base + NvRegIrqMask); + if (np->msi_flags & NV_MSI_X_ENABLED) { + writel(np->irqmask, base + NvRegIrqMask); + } else { + if (np->msi_flags & NV_MSI_ENABLED) + writel(0, base + NvRegMSIIrqMask); + writel(0, base + NvRegIrqMask); + } pci_push(base); dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name); spin_unlock_irq(&np->lock); - free_irq(dev->irq, dev); + if (np->msi_flags & NV_MSI_X_ENABLED) { + for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { + free_irq(np->msi_x_entry[i].vector, dev); + } + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + } else { + free_irq(np->pci_dev->irq, dev); + if (np->msi_flags & NV_MSI_ENABLED) { + pci_disable_msi(np->pci_dev); + np->msi_flags &= ~NV_MSI_ENABLED; + } + } drain_ring(dev); @@ -2588,6 +2976,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev->vlan_rx_kill_vid = nv_vlan_rx_kill_vid; } + np->msi_flags = 0; + if ((id->driver_data & DEV_HAS_MSI) && !disable_msi) { + np->msi_flags |= NV_MSI_CAPABLE; + } + if ((id->driver_data & DEV_HAS_MSI_X) && !disable_msix) { + np->msi_flags |= NV_MSI_X_CAPABLE; + } + err = -ENOMEM; np->base = ioremap(addr, NV_PCI_REGSZ); if (!np->base) @@ -2670,10 +3066,15 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i } else { np->tx_flags = NV_TX2_VALID; } - if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) + if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) { np->irqmask = NVREG_IRQMASK_THROUGHPUT; - else + if (np->msi_flags & NV_MSI_X_CAPABLE) /* set number of vectors */ + np->msi_flags |= 0x0003; + } else { np->irqmask = NVREG_IRQMASK_CPU; + if (np->msi_flags & NV_MSI_X_CAPABLE) /* set number of vectors */ + np->msi_flags |= 0x0001; + } if (id->driver_data & DEV_NEED_TIMERIRQ) np->irqmask |= NVREG_IRQ_TIMER; @@ -2829,11 +3230,11 @@ static struct pci_device_id pci_tbl[] = { }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X, }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X, }, {0,}, }; @@ -2863,6 +3264,10 @@ module_param(optimization_mode, int, 0); MODULE_PARM_DESC(optimization_mode, "In throughput mode (0), every tx & rx packet will generate an interrupt. In CPU mode (1), interrupts are controlled by a timer."); module_param(poll_interval, int, 0); MODULE_PARM_DESC(poll_interval, "Interval determines how frequent timer interrupt is generated by [(time_in_micro_secs * 100) / (2^10)]. Min is 0 and Max is 65535."); +module_param(disable_msi, int, 0); +MODULE_PARM_DESC(disable_msi, "Disable MSI interrupts by setting to 1."); +module_param(disable_msix, int, 0); +MODULE_PARM_DESC(disable_msix, "Disable MSIX interrupts by setting to 1."); MODULE_AUTHOR("Manfred Spraul "); MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver"); -- cgit v1.2.3-59-g8ed1b From 56497bd5f1340cb97d94cab953b050be6f729790 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 15 Feb 2006 15:01:42 +0900 Subject: [PATCH] libata: fix comment regarding setting cable type The comment above ata_std_postreset() specified that setting cable type is the responsibility of postreset(), which isn't possible / optimal depending on controller / driver. This patch kills the comment. Setting cable type is responsibility of ->probe_reset. libata doesn't care whether it's done in probeinit, reset or postreset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 76621463b499..62340f4ef004 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2112,7 +2112,6 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) * This function is invoked after a successful reset. Note that * the device might have been reset more than once using * different reset methods before postreset is invoked. - * postreset is also reponsible for setting cable type. * * This function is to be used as standard callback for * ata_drive_*_reset(). @@ -2124,7 +2123,7 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) { DPRINTK("ENTER\n"); - /* set cable type */ + /* 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; -- cgit v1.2.3-59-g8ed1b From 573db6b8f93b5e359abd9a05e620fd9a589b0209 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 15 Feb 2006 15:01:42 +0900 Subject: [PATCH] ata_piix: convert pata to new reset mechanism Convert ata_piix pata ->phy_reset to new reset mechanism. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 4cc1108f721a..d79c252a3f60 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -131,7 +131,7 @@ enum { static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static void piix_pata_phy_reset(struct ata_port *ap); +static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes); static void piix_sata_phy_reset(struct ata_port *ap); 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); @@ -207,7 +207,7 @@ static const struct ata_port_operations piix_pata_ops = { .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = piix_pata_phy_reset, + .probe_reset = piix_pata_probe_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, @@ -258,8 +258,7 @@ static struct ata_port_info piix_port_info[] = { /* ich5_pata */ { .sht = &piix_sht, - .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | - PIIX_FLAG_CHECKINTR, + .host_flags = ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR, .pio_mask = 0x1f, /* pio0-4 */ #if 0 .mwdma_mask = 0x06, /* mwdma1-2 */ @@ -284,7 +283,7 @@ static struct ata_port_info piix_port_info[] = { /* piix4_pata */ { .sht = &piix_sht, - .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .host_flags = ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, /* pio0-4 */ #if 0 .mwdma_mask = 0x06, /* mwdma1-2 */ @@ -366,30 +365,42 @@ cbl40: } /** - * piix_pata_phy_reset - Probe specified port on PATA host controller - * @ap: Port to probe + * piix_pata_probeinit - probeinit for PATA host controller + * @ap: Target port * - * Probe PATA phy. + * 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); +} -static void piix_pata_phy_reset(struct ata_port *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. + * + * LOCKING: + * None (inherited from caller). + */ +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])) { - ata_port_disable(ap); printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return; + return 0; } - piix_pata_cbl_detect(ap); - - ata_port_probe(ap); - - ata_bus_reset(ap); + return ata_drive_probe_reset(ap, piix_pata_probeinit, + ata_std_softreset, NULL, + ata_std_postreset, classes); } /** -- cgit v1.2.3-59-g8ed1b From ccbe6d5ee0eb3182675ef1c84322810fd884586d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 15 Feb 2006 15:01:42 +0900 Subject: [PATCH] ata_piix: convert sata to new reset mechanism Convert ata_piix sata ->phy_reset to new reset mechanism. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index d79c252a3f60..c662bf531514 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -132,7 +132,7 @@ 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 void piix_sata_phy_reset(struct ata_port *ap); +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); @@ -235,7 +235,7 @@ static const struct ata_port_operations piix_sata_ops = { .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = piix_sata_phy_reset, + .probe_reset = piix_sata_probe_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, @@ -272,8 +272,8 @@ static struct ata_port_info piix_port_info[] = { /* ich5_sata */ { .sht = &piix_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | - PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR, + .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED | + PIIX_FLAG_CHECKINTR, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -297,8 +297,7 @@ static struct ata_port_info piix_port_info[] = { /* ich6_sata */ { .sht = &piix_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | - PIIX_FLAG_COMBINED_ICH6 | + .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ @@ -309,8 +308,7 @@ static struct ata_port_info piix_port_info[] = { /* ich6_sata_ahci */ { .sht = &piix_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | - PIIX_FLAG_COMBINED_ICH6 | + .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ @@ -448,28 +446,25 @@ static int piix_sata_probe (struct ata_port *ap) } /** - * piix_sata_phy_reset - Probe specified port on SATA host controller - * @ap: Port to probe + * piix_sata_probe_reset - Perform reset on SATA port and classify + * @ap: Port to reset + * @classes: Resulting classes of attached devices * - * Probe SATA phy. + * Reset SATA phy and classify attached devices. * * LOCKING: * None (inherited from caller). */ - -static void piix_sata_phy_reset(struct ata_port *ap) +static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes) { if (!piix_sata_probe(ap)) { - ata_port_disable(ap); printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id); - return; + return 0; } - ap->cbl = ATA_CBL_SATA; - - ata_port_probe(ap); - - ata_bus_reset(ap); + return ata_drive_probe_reset(ap, ata_std_probeinit, + ata_std_softreset, NULL, + ata_std_postreset, classes); } /** -- cgit v1.2.3-59-g8ed1b From 49016aca2e54c64f08c31d5512dfd8d35f934c58 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 21 Feb 2006 02:12:11 +0900 Subject: [PATCH] libata: separate out ata_dev_read_id() Separate out ata_dev_read_id() from ata_dev_identify(). This is the first half of splitting ata_dev_identify(). ata_dev_read_id() will also be used for revalidation. This patch does not make any behavior change. ata_dev_read_id() doesn't modify any of libata-internal data structures. It simply reads IDENTIFY page and returns error code on failure. INIT_DEV_PARAMS and EDD wrong class code are also handled by this function. Re-reading IDENTIFY after INIT_DEV_PARAMS is performed by jumping to retry: instead of calling ata_dev_reread_id(). This is done because 1. there's retry label anyway 2. ata_dev_reread_id() cannot be used anywhere else so there's no reason to keep it. This function is probably the place to set transfer mode to PIO0 before IDENTIFY. However, reset -> identify -> init_dev_params order should be kept for pre-ATA4 devices so we cannot set transfer mode before IDENTIFY for them. How do we know if a device is post-ATA4 before IDENTIFY? Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 210 +++++++++++++++++++++++++++------------------ 1 file changed, 128 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 70efde99f652..d0a26e9553a1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -903,42 +903,36 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) } /** - * ata_dev_identify - obtain IDENTIFY x DEVICE page - * @ap: port on which device we wish to probe resides - * @device: device bus address, starting at zero - * - * Following bus reset, we issue the IDENTIFY [PACKET] DEVICE - * command, and read back the 512-byte device information page. - * The device information page is fed to us via the standard - * PIO-IN protocol, but we hand-code it here. (TODO: investigate - * using standard PIO-IN paths) - * - * After reading the device information page, we use several - * bits of information from it to initialize data structures - * that will be used during the lifetime of the ata_device. - * Other data from the info page is used to disqualify certain - * older ATA devices we do not wish to support. + * 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? + * @id: buffer to fill IDENTIFY page into + * + * Read ID data from the specified device. ATA_CMD_ID_ATA is + * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI + * devices. This function also takes care of EDD signature + * misreporting (to be removed once EDD support is gone) and + * issues ATA_CMD_INIT_DEV_PARAMS for pre-ATA4 drives. * * LOCKING: - * Inherited from caller. Some functions called by this function - * obtain the host_set lock. + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise. */ - -static void ata_dev_identify(struct ata_port *ap, unsigned int device) +static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, + unsigned int *p_class, int post_reset, u16 *id) { - struct ata_device *dev = &ap->device[device]; - unsigned int major_version; - unsigned long xfer_modes; + unsigned int class = *p_class; unsigned int using_edd; struct ata_taskfile tf; - unsigned int err_mask; - int i, rc; + unsigned int err_mask = 0; + const char *reason; + int rc; - if (!ata_dev_present(dev)) { - DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", - ap->id, device); - return; - } + DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); if (ap->ops->probe_reset || ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET)) @@ -946,30 +940,33 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) else using_edd = 1; - DPRINTK("ENTER, host %u, dev %u\n", ap->id, device); - - WARN_ON(dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ATAPI && - dev->class != ATA_DEV_NONE); - - ata_dev_select(ap, device, 1, 1); /* select device 0/1 */ + ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ -retry: - ata_tf_init(ap, &tf, device); + retry: + ata_tf_init(ap, &tf, dev->devno); - if (dev->class == ATA_DEV_ATA) { + switch (class) { + case ATA_DEV_ATA: tf.command = ATA_CMD_ID_ATA; - DPRINTK("do ATA identify\n"); - } else { + break; + case ATA_DEV_ATAPI: tf.command = ATA_CMD_ID_ATAPI; - DPRINTK("do ATAPI identify\n"); + break; + default: + rc = -ENODEV; + reason = "unsupported class"; + goto err_out; } tf.protocol = ATA_PROT_PIO; err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE, - dev->id, sizeof(dev->id)); + id, sizeof(id[0]) * ATA_ID_WORDS); if (err_mask) { + rc = -EIO; + reason = "I/O error"; + if (err_mask & ~AC_ERR_DEV) goto err_out; @@ -984,25 +981,105 @@ retry: * ATA software reset (SRST, the default) does not appear * to have this problem. */ - if ((using_edd) && (dev->class == ATA_DEV_ATA)) { + if ((using_edd) && (class == ATA_DEV_ATA)) { u8 err = tf.feature; if (err & ATA_ABORTED) { - dev->class = ATA_DEV_ATAPI; + class = ATA_DEV_ATAPI; goto retry; } } goto err_out; } - swap_buf_le16(dev->id, ATA_ID_WORDS); + swap_buf_le16(id, ATA_ID_WORDS); /* print device capabilities */ 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, device, dev->id[49], - dev->id[82], dev->id[83], dev->id[84], - dev->id[85], dev->id[86], dev->id[87], - dev->id[88]); + ap->id, dev->devno, + id[49], id[82], id[83], id[84], id[85], id[86], id[87], id[88]); + + /* sanity check */ + if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) { + rc = -EINVAL; + reason = "device reports illegal type"; + goto err_out; + } + + if (post_reset && class == ATA_DEV_ATA) { + /* + * The exact sequence expected by certain pre-ATA4 drives is: + * SRST RESET + * IDENTIFY + * INITIALIZE DEVICE PARAMETERS + * anything else.. + * 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); + if (err_mask) { + rc = -EIO; + reason = "INIT_DEV_PARAMS failed"; + goto err_out; + } + + /* current CHS translation info (id[53-58]) might be + * changed. reread the identify device info. + */ + post_reset = 0; + goto retry; + } + } + + *p_class = class; + 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; +} + +/** + * ata_dev_identify - obtain IDENTIFY x DEVICE page + * @ap: port on which device we wish to probe resides + * @device: device bus address, starting at zero + * + * Following bus reset, we issue the IDENTIFY [PACKET] DEVICE + * command, and read back the 512-byte device information page. + * The device information page is fed to us via the standard + * PIO-IN protocol, but we hand-code it here. (TODO: investigate + * using standard PIO-IN paths) + * + * After reading the device information page, we use several + * bits of information from it to initialize data structures + * that will be used during the lifetime of the ata_device. + * Other data from the info page is used to disqualify certain + * older ATA devices we do not wish to support. + * + * LOCKING: + * Inherited from caller. Some functions called by this function + * obtain the host_set lock. + */ + +static void ata_dev_identify(struct ata_port *ap, unsigned int device) +{ + struct ata_device *dev = &ap->device[device]; + unsigned long xfer_modes; + int i, rc; + + if (!ata_dev_present(dev)) { + DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", + ap->id, device); + return; + } + + DPRINTK("ENTER, host %u, dev %u\n", ap->id, device); + + rc = ata_dev_read_id(ap, dev, &dev->class, 1, dev->id); + if (rc) + goto err_out; /* * common ATA, ATAPI feature tests @@ -1027,34 +1104,6 @@ retry: if (dev->class == ATA_DEV_ATA) { dev->n_sectors = ata_id_n_sectors(dev->id); - if (!ata_id_is_ata(dev->id)) /* sanity check */ - goto err_out_nosup; - - /* get major version */ - major_version = ata_id_major_version(dev->id); - - /* - * The exact sequence expected by certain pre-ATA4 drives is: - * SRST RESET - * IDENTIFY - * INITIALIZE DEVICE PARAMETERS - * anything else.. - * Some drives were very specific about that exact sequence. - */ - if (major_version < 4 || (!ata_id_has_lba(dev->id))) { - err_mask = ata_dev_init_params(ap, dev); - if (err_mask) { - printk(KERN_ERR "ata%u: failed to init " - "parameters, disabled\n", ap->id); - goto err_out; - } - - /* current CHS translation info (id[53-58]) might be - * changed. reread the identify device info. - */ - ata_dev_reread_id(ap, dev); - } - if (ata_id_has_lba(dev->id)) { dev->flags |= ATA_DFLAG_LBA; @@ -1064,7 +1113,7 @@ retry: /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n", ap->id, device, - major_version, + ata_id_major_version(dev->id), ata_mode_string(xfer_modes), (unsigned long long)dev->n_sectors, dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA"); @@ -1086,7 +1135,7 @@ retry: /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n", ap->id, device, - major_version, + ata_id_major_version(dev->id), ata_mode_string(xfer_modes), (unsigned long long)dev->n_sectors, (int)dev->cylinders, (int)dev->heads, (int)dev->sectors); @@ -1098,9 +1147,6 @@ retry: /* ATAPI-specific feature tests */ else if (dev->class == ATA_DEV_ATAPI) { - if (ata_id_is_ata(dev->id)) /* sanity check */ - goto err_out_nosup; - rc = atapi_cdb_len(dev->id); if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); -- cgit v1.2.3-59-g8ed1b From ba70d0614728892b86b2be2f7eae0c696b436461 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 21 Feb 2006 02:12:11 +0900 Subject: [PATCH] libata: kill ata_dev_reread_id() Kill now-unused ata_dev_reread_id(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d0a26e9553a1..ab3257a6b860 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -61,7 +61,6 @@ #include "libata.h" -static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev); static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); static void ata_set_mode(struct ata_port *ap); @@ -2534,47 +2533,6 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) DPRINTK("EXIT\n"); } -/** - * ata_dev_reread_id - Reread the device identify device info - * @ap: port where the device is - * @dev: device to reread the identify device info - * - * LOCKING: - */ - -static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev) -{ - struct ata_taskfile tf; - - ata_tf_init(ap, &tf, dev->devno); - - if (dev->class == ATA_DEV_ATA) { - tf.command = ATA_CMD_ID_ATA; - DPRINTK("do ATA identify\n"); - } else { - tf.command = ATA_CMD_ID_ATAPI; - DPRINTK("do ATAPI identify\n"); - } - - tf.flags |= ATA_TFLAG_DEVICE; - tf.protocol = ATA_PROT_PIO; - - if (ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE, - dev->id, sizeof(dev->id))) - goto err_out; - - swap_buf_le16(dev->id, ATA_ID_WORDS); - - ata_dump_id(dev->id); - - DPRINTK("EXIT\n"); - - return; -err_out: - printk(KERN_ERR "ata%u: failed to reread ID, disabled\n", ap->id); - ata_port_disable(ap); -} - /** * ata_dev_init_params - Issue INIT DEV PARAMS command * @ap: Port associated with device @dev -- cgit v1.2.3-59-g8ed1b From cc006288fb538005a14ca4297250abbf0beeb0b9 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Feb 2006 20:15:58 +0100 Subject: kbuild: ignore all generated files for make allmodconfig (x86_64) With following patch we now ignore all generated files for make allmodconfig for x86_64. Signed-off-by: Sam Ravnborg --- drivers/atm/.gitignore | 5 +++++ sound/oss/.gitignore | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 drivers/atm/.gitignore create mode 100644 sound/oss/.gitignore (limited to 'drivers') diff --git a/drivers/atm/.gitignore b/drivers/atm/.gitignore new file mode 100644 index 000000000000..a165b7167714 --- /dev/null +++ b/drivers/atm/.gitignore @@ -0,0 +1,5 @@ +# Ignore generated files +fore200e_mkfirm +fore200e_pca_fw.c +pca200e.bin + diff --git a/sound/oss/.gitignore b/sound/oss/.gitignore new file mode 100644 index 000000000000..7efb12b45502 --- /dev/null +++ b/sound/oss/.gitignore @@ -0,0 +1,4 @@ +#Ignore generated files +maui_boot.h +pss_boot.h +trix_boot.h -- cgit v1.2.3-59-g8ed1b From 0004fd59d57a5875db8897966c414a88b5dad481 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Mon, 27 Feb 2006 00:07:27 -0300 Subject: V4L/DVB (3291): Added support for xc3028 analogue tuner (Hauppauge HVR900, Terratec Hybrid XS) Added support for xc3028 to v4l which adds support for: * Terratec Hybrid XS (analogue) * Hauppauge HVR 900 (analogue) Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.tuner | 1 + drivers/media/video/Makefile | 2 +- drivers/media/video/em28xx/em28xx-cards.c | 4 ++-- drivers/media/video/tuner-core.c | 3 +++ drivers/media/video/tuner-types.c | 21 +++++++++++++++++++++ include/media/tuner.h | 3 +++ 6 files changed, 31 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index f6d0cf7b7922..de48438d5115 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -69,3 +69,4 @@ tuner=67 - Philips TD1316 Hybrid Tuner tuner=68 - Philips TUV1236D ATSC/NTSC dual in tuner=69 - Tena TNF 5335 MF tuner=70 - Samsung TCPN 2121P30A +tuner=71 - Xceive xc3028 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index faf728366c4e..60e9c6e3f2b7 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -9,7 +9,7 @@ zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ - mt20xx.o tda8290.o tea5767.o + mt20xx.o tda8290.o tea5767.o xc3028.o msp3400-objs := msp3400-driver.o msp3400-kthreads.o diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 703927e8da13..e9834c159aec 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -158,8 +158,8 @@ struct em28xx_board em28xx_boards[] = { .name = "Hauppauge WinTV HVR 900", .vchannels = 3, .norm = VIDEO_MODE_PAL, - .has_tuner = 0, .tda9887_conf = TDA9887_PRESENT, + .tuner_type = TUNER_XCEIVE_XC3028, .has_tuner = 1, .decoder = EM28XX_TVP5150, .input = {{ @@ -180,8 +180,8 @@ struct em28xx_board em28xx_boards[] = { .name = "Terratec Hybrid XS", .vchannels = 3, .norm = VIDEO_MODE_PAL, - .has_tuner = 0, .tda9887_conf = TDA9887_PRESENT, + .tuner_type = TUNER_XCEIVE_XC3028, .has_tuner = 1, .decoder = EM28XX_TVP5150, .input = {{ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index e34f801c9a10..520f274c89e5 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -217,6 +217,9 @@ static void set_type(struct i2c_client *c, unsigned int type, i2c_master_send(c,buffer,4); default_tuner_init(c); break; + case TUNER_XCEIVE_XC3028: + xc3028_init(c); + break; default: default_tuner_init(c); break; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index a90bc04cf807..a4384e6e5318 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -983,6 +983,23 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { }, }; +/* ------------ TUNER_XCEIVE_XC3028 - Xceive xc3028 ------------ */ + +static struct tuner_range tuner_xceive_xc3028_ranges[] = { + { 16 * 140.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, +}; + +static struct tuner_params tuner_xceive_xc3028_params[] = { + { + .type = TUNER_XCEIVE_XC3028, + .ranges = tuner_xceive_xc3028_ranges, + .count = ARRAY_SIZE(tuner_xceive_xc3028_ranges), + }, +}; + + /* --------------------------------------------------------------------- */ struct tunertype tuners[] = { @@ -1350,6 +1367,10 @@ struct tunertype tuners[] = { .params = tuner_samsung_tcpn_2121p30a_params, .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_params), }, + [TUNER_XCEIVE_XC3028] = { /* Xceive 3028 */ + .name = "Xceive xc3028", + .params = tuner_xceive_xc3028_params, + }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/include/media/tuner.h b/include/media/tuner.h index a5beeac495c7..f51759c0d180 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -117,6 +117,8 @@ #define TUNER_TNF_5335MF 69 /* Sabrent Bt848 */ #define TUNER_SAMSUNG_TCPN_2121P30A 70 /* Hauppauge PVR-500MCE NTSC */ +#define TUNER_XCEIVE_XC3028 71 + /* tv card specific */ #define TDA9887_PRESENT (1<<0) #define TDA9887_PORT1_INACTIVE (1<<1) @@ -209,6 +211,7 @@ struct tuner { extern unsigned const int tuner_count; extern int microtune_init(struct i2c_client *c); +extern int xc3028_init(struct i2c_client *c); extern int tda8290_init(struct i2c_client *c); extern int tda8290_probe(struct i2c_client *c); extern int tea5767_tuner_init(struct i2c_client *c); -- cgit v1.2.3-59-g8ed1b From cce91e36d74be635abb99aa1dc74951e11be8aea Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Mon, 27 Feb 2006 00:07:31 -0300 Subject: V4L/DVB (3292): Fixed xc3028 firmware extractor, added terratec fw support Fixed xc3028 firmware extractor for terratec's emBDA.sys firmware Fixed delay in firmwareupload, now terratec's firmware also works Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 2 +- drivers/media/video/em28xx/em28xx-i2c.c | 1 - drivers/media/video/tuner-core.c | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index e9834c159aec..fc589070ef69 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -181,8 +181,8 @@ struct em28xx_board em28xx_boards[] = { .vchannels = 3, .norm = VIDEO_MODE_PAL, .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_XCEIVE_XC3028, .has_tuner = 1, + .tuner_type = TUNER_XCEIVE_XC3028, .decoder = EM28XX_TVP5150, .input = {{ .type = EM28XX_VMUX_COMPOSITE1, diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 6ca8631bc36d..5b6cece37aee 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -420,7 +420,6 @@ static int em28xx_set_tuner(int check_eeprom, struct i2c_client *client) tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; tun_setup.type = dev->tuner_type; tun_setup.addr = dev->tuner_addr; - em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); } diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 520f274c89e5..4a660a4228b9 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -173,7 +173,6 @@ static void set_type(struct i2c_client *c, unsigned int type, } t->type = type; - switch (t->type) { case TUNER_MT2032: microtune_init(c); -- cgit v1.2.3-59-g8ed1b From 9475fb1c717ee5ce3df767b8e3b9439d341f043d Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Mon, 27 Feb 2006 00:07:34 -0300 Subject: V4L/DVB (3293): Fixed amux hauppauge hvr900/terratec hybrid xs Fixed amux hauppauge hvr900/terratec hybrid xs Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 14 +++++++------- drivers/media/video/em28xx/em28xx-video.c | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index fc589070ef69..00665d6ffc17 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -101,7 +101,7 @@ struct em28xx_board em28xx_boards[] = { .input = {{ .type = EM28XX_VMUX_TELEVISION, .vmux = 2, - .amux = 0, + .amux = 1, },{ .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -165,11 +165,11 @@ struct em28xx_board em28xx_boards[] = { .input = {{ .type = EM28XX_VMUX_COMPOSITE1, .vmux = 2, - .amux = 0, + .amux = 1, },{ .type = EM28XX_VMUX_TELEVISION, .vmux = 0, - .amux = 1, + .amux = 0, },{ .type = EM28XX_VMUX_SVIDEO, .vmux = 9, @@ -185,12 +185,12 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XCEIVE_XC3028, .decoder = EM28XX_TVP5150, .input = {{ - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 2, - .amux = 0, - },{ .type = EM28XX_VMUX_TELEVISION, .vmux = 0, + .amux = 0, + },{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 2, .amux = 1, },{ .type = EM28XX_VMUX_SVIDEO, diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 671fc52b6a88..f56ae4852165 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -222,8 +222,8 @@ static int em28xx_config(struct em28xx *dev) /* enable vbi capturing */ - em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); - em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); +/* em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); audio register */ +/* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */ em28xx_write_regs_req(dev,0x00,0x11,"\x51",1); em28xx_audio_usb_mute(dev, 1); @@ -313,11 +313,11 @@ static void video_mux(struct em28xx *dev, int index) em28xx_audio_source(dev, ainput); } else { switch (dev->ctl_ainput) { - case 0: - ainput = EM28XX_AUDIO_SRC_TUNER; - break; - default: - ainput = EM28XX_AUDIO_SRC_LINE; + case 0: + ainput = EM28XX_AUDIO_SRC_TUNER; + break; + default: + ainput = EM28XX_AUDIO_SRC_LINE; } em28xx_audio_source(dev, ainput); } -- cgit v1.2.3-59-g8ed1b From cfcd718d492d401a7d8a7ee3a85e48164b56e2e2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Feb 2006 00:07:37 -0300 Subject: V4L/DVB (3332): XC3028 code marked with an special define option - Current xc3028 support is still experimental, requiring more work to be sent to mainstream. So, it was marked inside some defines, in order to be removed by gentree.pl stript. Script also updated to remove it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 4 ++++ drivers/media/video/tuner-core.c | 2 ++ drivers/media/video/tuner-types.c | 19 +------------------ 3 files changed, 7 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 00665d6ffc17..666630572f35 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -154,6 +154,7 @@ struct em28xx_board em28xx_boards[] = { .amux = 1, }}, }, +#ifdef CONFIG_XC3028 [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { .name = "Hauppauge WinTV HVR 900", .vchannels = 3, @@ -222,6 +223,7 @@ struct em28xx_board em28xx_boards[] = { .amux = 1, }}, }, +#endif [EM2820_BOARD_MSI_VOX_USB_2] = { .name = "MSI VOX USB 2.0", .vchannels = 3, @@ -340,9 +342,11 @@ struct usb_device_id em28xx_id_table [] = { { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, +#ifdef CONFIG_XC3028 { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0047), .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, +#endif { }, }; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 4a660a4228b9..3a96cc4ae81d 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -216,9 +216,11 @@ static void set_type(struct i2c_client *c, unsigned int type, i2c_master_send(c,buffer,4); default_tuner_init(c); break; +#ifdef CONFIG_XC3028 case TUNER_XCEIVE_XC3028: xc3028_init(c); break; +#endif default: default_tuner_init(c); break; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index a4384e6e5318..15761dd8607d 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -983,23 +983,6 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { }, }; -/* ------------ TUNER_XCEIVE_XC3028 - Xceive xc3028 ------------ */ - -static struct tuner_range tuner_xceive_xc3028_ranges[] = { - { 16 * 140.25 /*MHz*/, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, -}; - -static struct tuner_params tuner_xceive_xc3028_params[] = { - { - .type = TUNER_XCEIVE_XC3028, - .ranges = tuner_xceive_xc3028_ranges, - .count = ARRAY_SIZE(tuner_xceive_xc3028_ranges), - }, -}; - - /* --------------------------------------------------------------------- */ struct tunertype tuners[] = { @@ -1369,7 +1352,7 @@ struct tunertype tuners[] = { }, [TUNER_XCEIVE_XC3028] = { /* Xceive 3028 */ .name = "Xceive xc3028", - .params = tuner_xceive_xc3028_params, + /* see xc3028.c for details */ }, }; -- cgit v1.2.3-59-g8ed1b From 176790f0681ad151c55068589092a813c689654c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 27 Feb 2006 00:07:43 -0300 Subject: V4L/DVB (3335): Fix in-kernel build - remove tuner.ko build dependency on xc3028.o , which will be added again later. - fix the following build error when using the "make kernel-links" build method to symlink the latest code from the v4l-dvb repository into the kernel source: drivers/media/video/xc3028.c:31:20: em28xx.h: No such file or directory drivers/media/video/xc3028.c: In function `xc3028_init': drivers/media/video/xc3028.c:120: error: dereferencing pointer to incomplete type drivers/media/video/xc3028.c:121: error: dereferencing pointer to incomplete type drivers/media/video/xc3028.c:139: error: dereferencing pointer to incomplete type drivers/media/video/xc3028.c:140: error: dereferencing pointer to incomplete type make[3]: *** [drivers/media/video/xc3028.o] Error 1 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 60e9c6e3f2b7..faf728366c4e 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -9,7 +9,7 @@ zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ - mt20xx.o tda8290.o tea5767.o xc3028.o + mt20xx.o tda8290.o tea5767.o msp3400-objs := msp3400-driver.o msp3400-kthreads.o -- cgit v1.2.3-59-g8ed1b From 4592b3a08454bb018e482de230fd5f15757bba92 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 27 Feb 2006 00:07:49 -0300 Subject: V4L/DVB (3337): Drivers/media/dvb/frontends/mt312.c: cleanups This patch contains the following possible cleanups: - update the Kconfig help to mention the VP310 - merge vp310_attach and mt312_attach into a new vp310_mt312_attach to remove some code duplication Signed-off-by: Adrian Bunk Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 2 +- drivers/media/dvb/frontends/Kconfig | 2 +- drivers/media/dvb/frontends/mt312.c | 116 ++++++++++++------------------ drivers/media/dvb/frontends/mt312.h | 6 +- 4 files changed, 48 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 390cc3a99ce6..9c7f122826e0 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -526,7 +526,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address); } else /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ - if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) { + if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) { ops = fc->fe->ops; ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 76b6a2aef32f..c676b1e23ab0 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -29,7 +29,7 @@ config DVB_TDA8083 A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_MT312 - tristate "Zarlink MT312 based" + tristate "Zarlink VP310/MT312 based" depends on DVB_CORE help A DVB-S tuner module. Say Y when you want to support this frontend. diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index ec4e641acc64..d3aea83cf218 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -612,76 +612,6 @@ static void mt312_release(struct dvb_frontend* fe) kfree(state); } -static struct dvb_frontend_ops vp310_mt312_ops; - -struct dvb_frontend* vp310_attach(const struct mt312_config* config, - struct i2c_adapter* i2c) -{ - struct mt312_state* state = NULL; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL); - if (state == NULL) - goto error; - - /* setup the state */ - state->config = config; - state->i2c = i2c; - memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); - strcpy(state->ops.info.name, "Zarlink VP310 DVB-S"); - - /* check if the demod is there */ - if (mt312_readreg(state, ID, &state->id) < 0) - goto error; - if (state->id != ID_VP310) { - goto error; - } - - /* create dvb_frontend */ - state->frequency = 90; - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; - return &state->frontend; - -error: - kfree(state); - return NULL; -} - -struct dvb_frontend* mt312_attach(const struct mt312_config* config, - struct i2c_adapter* i2c) -{ - struct mt312_state* state = NULL; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL); - if (state == NULL) - goto error; - - /* setup the state */ - state->config = config; - state->i2c = i2c; - memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); - strcpy(state->ops.info.name, "Zarlink MT312 DVB-S"); - - /* check if the demod is there */ - if (mt312_readreg(state, ID, &state->id) < 0) - goto error; - if (state->id != ID_MT312) { - goto error; - } - - /* create dvb_frontend */ - state->frequency = 60; - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; - return &state->frontend; - -error: - kfree(state); - return NULL; -} - static struct dvb_frontend_ops vp310_mt312_ops = { .info = { @@ -720,6 +650,49 @@ static struct dvb_frontend_ops vp310_mt312_ops = { .set_voltage = mt312_set_voltage, }; +struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config, + struct i2c_adapter* i2c) +{ + struct mt312_state* state = NULL; + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); + + /* check if the demod is there */ + if (mt312_readreg(state, ID, &state->id) < 0) + goto error; + + switch (state->id) { + case ID_VP310: + strcpy(state->ops.info.name, "Zarlink VP310 DVB-S"); + state->frequency = 90; + break; + case ID_MT312: + strcpy(state->ops.info.name, "Zarlink MT312 DVB-S"); + state->frequency = 60; + break; + default: + printk (KERN_WARNING "Only Zarlink VP310/MT312 are supported chips.\n"); + goto error; + } + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + kfree(state); + return NULL; +} + module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); @@ -727,5 +700,4 @@ MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver"); MODULE_AUTHOR("Andreas Oberritter "); MODULE_LICENSE("GPL"); -EXPORT_SYMBOL(mt312_attach); -EXPORT_SYMBOL(vp310_attach); +EXPORT_SYMBOL(vp310_mt312_attach); diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h index b3a53a73a117..074d844f0139 100644 --- a/drivers/media/dvb/frontends/mt312.h +++ b/drivers/media/dvb/frontends/mt312.h @@ -38,10 +38,8 @@ struct mt312_config int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; -extern struct dvb_frontend* mt312_attach(const struct mt312_config* config, - struct i2c_adapter* i2c); +struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config, + struct i2c_adapter* i2c); -extern struct dvb_frontend* vp310_attach(const struct mt312_config* config, - struct i2c_adapter* i2c); #endif // MT312_H -- cgit v1.2.3-59-g8ed1b From 36b36562c4159cca890f29a603e829030fea5788 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Mon, 27 Feb 2006 00:07:52 -0300 Subject: V4L/DVB (3340): Make a struct static Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/bt878.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index d276ce6b3661..5500f8a0ffe2 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -382,7 +382,7 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet * EXPORT_SYMBOL(bt878_device_control); -struct cards card_list[] __devinitdata = { +static struct cards card_list[] __devinitdata = { { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, -- cgit v1.2.3-59-g8ed1b From 47a9e50eb7719dc1bf01ac8b60f4d8758146d00e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 27 Feb 2006 00:07:55 -0300 Subject: V4L/DVB (3341): Upstream sync - make 2 structs static Signed-off-by: Adrian Bunk Acked-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index d800df1212c5..1cfa5e5035d8 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -602,7 +602,7 @@ static int dst_type_print(u8 type) */ -struct dst_types dst_tlist[] = { +static struct dst_types dst_tlist[] = { { .device_id = "200103A", .offset = 0, -- cgit v1.2.3-59-g8ed1b From e2798212e3ce0057336bc0807beb3213de1dc5be Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 27 Feb 2006 00:07:58 -0300 Subject: V4L/DVB (3343): KWorld HardwareMpegTV XPert: Add radio support - add radio support for KWorld HardwareMpegTV XPert - fix GPIO settings for tv and radio Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index f2ae0478c33a..8617b087659a 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1064,8 +1064,12 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0x07fa, + .gpio0 = 0x3de2, }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x3de6, + }, }, }; -- cgit v1.2.3-59-g8ed1b From 24da4e4b8dbd443c205c4ec3b2a563421e6ca319 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 27 Feb 2006 00:08:01 -0300 Subject: V4L/DVB (3344): KWorld HardwareMpegTV XPert must set gpio2 - KWorld HardwareMpegTV XPert must set gpio2 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 8617b087659a..09f5739b518d 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1065,10 +1065,12 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x3de2, + .gpio2 = 0x00ff, }}, .radio = { .type = CX88_RADIO, .gpio0 = 0x3de6, + .gpio2 = 0x00ff, }, }, -- cgit v1.2.3-59-g8ed1b From d0456d1d67044ff2987190d0d8148a88f1a775af Mon Sep 17 00:00:00 2001 From: Tamuki Shoichi Date: Mon, 27 Feb 2006 00:08:04 -0300 Subject: V4L/DVB (3346): Add saa713x card: ELSA EX-VISION 700TV (saa7130) Add support for ELSA EX-VISION 700TV, which is the ELSA Japan's flagship model of the software encoding TV capture card. All inputs (Television, Composite1 and S-Video) have been tested. Signed-off-by: Tamuki Shoichi Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 32 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 34 insertions(+) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index c10cfd26d529..617c7572c001 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -87,3 +87,4 @@ 86 -> LifeView FlyDVB-T [5168:0301] 87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421] 88 -> Tevion DVB-T 220RF [17de:7201] + 89 -> ELSA EX-VISION 700TV [1131:7130] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 3f418620bacf..f5c79898fcfb 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -640,6 +640,32 @@ struct saa7134_board saa7134_boards[] = { .tv = 1, }}, }, + [SAA7134_BOARD_ELSA_700TV] = { + .name = "ELSA EX-VISION 700TV", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_HITACHI_NTSC, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_tv, + .vmux = 4, + .amux = LINE2, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 6, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 7, + .amux = LINE1, + }}, + .mute = { + .name = name_mute, + .amux = TV, + }, + }, [SAA7134_BOARD_ASUSTeK_TVFM7134] = { .name = "ASUS TV-FM 7134", .audio_clock = 0x00187de7, @@ -2829,6 +2855,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1048, .subdevice = 0x226b, .driver_data = SAA7134_BOARD_ELSA_500TV, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x1131, + .subdevice = 0x7130, + .driver_data = SAA7134_BOARD_ELSA_700TV, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 691c10be459d..55a6733c363a 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -216,6 +216,7 @@ struct saa7134_format { #define SAA7134_BOARD_FLYDVBT_LR301 86 #define SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331 87 #define SAA7134_BOARD_TEVION_DVBT_220RF 88 +#define SAA7134_BOARD_ELSA_700TV 89 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3-59-g8ed1b From cb46e3c28ef8055e82dfbc64ba64dda123833036 Mon Sep 17 00:00:00 2001 From: Karsten Suehring Date: Mon, 27 Feb 2006 00:08:08 -0300 Subject: V4L/DVB (3347): Pinnacle PCTV 40i: add filtered Composite2 input This patch adds another composite input to the Pinnacle PCTV 100i definition which filters the chrominace signal from the luma input. This improves video quality for Composite signals on the S-Video connector of the card. In addition the name string of the card is changed to include PCTV 40i and 50i since these cards are identical. Signed-off-by: Karsten Suehring Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 617c7572c001..7d163763d4b0 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -75,7 +75,7 @@ 74 -> LifeView FlyTV Platinum Mini2 [14c0:1212] 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] 76 -> SKNet MonsterTV Mobile [1131:4ee9] - 77 -> Pinnacle PCTV 110i (saa7133) [11bd:002e] + 77 -> Pinnacle PCTV 40i/50i/110i (saa7133) [11bd:002e] 78 -> ASUSTeK P7131 Dual [1043:4862] 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) 80 -> ASUS Digimatrix TV [1043:0210] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index f5c79898fcfb..602c614d74c5 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2418,7 +2418,7 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_PINNACLE_PCTV_110i] = { - .name = "Pinnacle PCTV 110i (saa7133)", + .name = "Pinnacle PCTV 40i/50i/110i (saa7133)", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, @@ -2433,6 +2433,10 @@ struct saa7134_board saa7134_boards[] = { },{ .name = name_comp1, .vmux = 1, + .amux = LINE2, + },{ + .name = name_comp2, + .vmux = 0, .amux = LINE2, },{ .name = name_svideo, -- cgit v1.2.3-59-g8ed1b From 8a9a5fbd33258b8e3e3b629a9f33254b6f1d883b Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Mon, 27 Feb 2006 00:08:11 -0300 Subject: V4L/DVB (3348): Fixed saa7134 ALSA initialization with multiple cards When multiple cards were installed, only the first card would have audio initialized, because only the first position in the array parameter defaulted to "1" To make things worse, the "enable" parameter wasn't enabled, so there was no workaround. Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-alsa.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index d3c7345a5d22..614f7b923403 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -54,10 +54,12 @@ MODULE_PARM_DESC(debug,"enable debug messages [alsa]"); 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] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; module_param_array(index, int, NULL, 0444); +module_param_array(enable, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s)."); +MODULE_PARM_DESC(enable, "Enable (or not) the SAA7134 capture interface(s)."); #define dprintk(fmt, arg...) if (debug) \ printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ##arg) -- cgit v1.2.3-59-g8ed1b From 4ab2b99b9f41a0a409030f1edb79a14ec2287e4b Mon Sep 17 00:00:00 2001 From: BoyZonder Date: Mon, 27 Feb 2006 00:08:15 -0300 Subject: V4L/DVB (3349): Remote control codes for BTTV_BOARD_CONTVFMI The remote control interface for this board is the same as the one for BTTV_BOARD_CONCEPTRONIC_CTVFMI2 Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bttv-input.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/bttv-input.c b/drivers/media/video/bttv-input.c index c637677acefd..69efa0e5174d 100644 --- a/drivers/media/video/bttv-input.c +++ b/drivers/media/video/bttv-input.c @@ -328,6 +328,7 @@ int bttv_input_init(struct bttv *btv) ir->polling = 50; // ms break; case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: + case BTTV_BOARD_CONTVFMI: ir_codes = ir_codes_pixelview; ir->mask_keycode = 0x001F00; ir->mask_keyup = 0x006000; -- cgit v1.2.3-59-g8ed1b From fddd632a8f3850b3981e21a477fcb83d227353ca Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 27 Feb 2006 00:08:17 -0300 Subject: V4L/DVB (3352): Cxusb: fix lgdt3303 naming The following are specific to lgdt3303, and are being renamed to reflect this. - cxusb_lgdt330x_config renamed to cxusb_lgdt3303_config. - cxusb_lgdt330x_frontend_attach renamed to cxusb_lgdt3303_frontend_attach. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index e62a293c7e5a..e14bf43941e3 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -282,7 +282,7 @@ static struct cx22702_config cxusb_cx22702_config = { .pll_set = dvb_usb_pll_set_i2c, }; -static struct lgdt330x_config cxusb_lgdt330x_config = { +static struct lgdt330x_config cxusb_lgdt3303_config = { .demod_address = 0x0e, .demod_chip = LGDT3303, .pll_set = dvb_usb_pll_set_i2c, @@ -357,14 +357,14 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d) return -EIO; } -static int cxusb_lgdt330x_frontend_attach(struct dvb_usb_device *d) +static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_device *d) { if (usb_set_interface(d->udev,0,7) < 0) err("set interface failed"); cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0); - if ((d->fe = lgdt330x_attach(&cxusb_lgdt330x_config, &d->i2c_adap)) != NULL) + if ((d->fe = lgdt330x_attach(&cxusb_lgdt3303_config, &d->i2c_adap)) != NULL) return 0; return -EIO; @@ -506,7 +506,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = { .streaming_ctrl = cxusb_streaming_ctrl, .power_ctrl = cxusb_power_ctrl, - .frontend_attach = cxusb_lgdt330x_frontend_attach, + .frontend_attach = cxusb_lgdt3303_frontend_attach, .tuner_attach = cxusb_lgh064f_tuner_attach, .i2c_algo = &cxusb_i2c_algo, -- cgit v1.2.3-59-g8ed1b From ecc0b94742014f21fd1ba331bb6815322800b6c8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 27 Feb 2006 00:08:20 -0300 Subject: V4L/DVB (3354): Fix maximum for the saturation and contrast controls. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 4 ++-- drivers/media/video/saa7115.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 8d8aa8ec8304..8a257978056f 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -567,7 +567,7 @@ static struct v4l2_queryctrl cx25840_qctrl[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Contrast", .minimum = 0, - .maximum = 255, + .maximum = 127, .step = 1, .default_value = 64, .flags = 0, @@ -576,7 +576,7 @@ static struct v4l2_queryctrl cx25840_qctrl[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Saturation", .minimum = 0, - .maximum = 255, + .maximum = 127, .step = 1, .default_value = 64, .flags = 0, diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 487a42970963..f0eb9851bf53 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1027,7 +1027,7 @@ static struct v4l2_queryctrl saa7115_qctrl[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Contrast", .minimum = 0, - .maximum = 255, + .maximum = 127, .step = 1, .default_value = 64, .flags = 0, @@ -1036,7 +1036,7 @@ static struct v4l2_queryctrl saa7115_qctrl[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Saturation", .minimum = 0, - .maximum = 255, + .maximum = 127, .step = 1, .default_value = 64, .flags = 0, -- cgit v1.2.3-59-g8ed1b From 3e1410adc7cc9e8511327179b5b86864be17b7f9 Mon Sep 17 00:00:00 2001 From: Andrew Burri Date: Mon, 27 Feb 2006 00:08:23 -0300 Subject: V4L/DVB (3361): Add support for Kworld ATSC110 Signed-off-by: Andrew Burri Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 22 ++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 9 +++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 33 insertions(+) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 7d163763d4b0..f74d2f9b47f5 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -88,3 +88,4 @@ 87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421] 88 -> Tevion DVB-T 220RF [17de:7201] 89 -> ELSA EX-VISION 700TV [1131:7130] + 90 -> KWORLD ATSC110 [17de:7350] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 602c614d74c5..6ce9c083de2d 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2731,6 +2731,22 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_KWORLD_ATSC110] = { + .name = "KWORLD ATSC110", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TUV1236D, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3231,6 +3247,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x17de, .subdevice = 0x7201, .driver_data = SAA7134_BOARD_TEVION_DVBT_220RF, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ + .subvendor = 0x17de, + .subdevice = 0x7350, + .driver_data = SAA7134_BOARD_KWORLD_ATSC110, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 56ca3fad55c4..354bbf7a1858 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -927,6 +927,12 @@ static struct nxt200x_config avertvhda180 = { .pll_address = 0x61, .pll_desc = &dvb_pll_tdhu2, }; + +static struct nxt200x_config kworldatsc110 = { + .demod_address = 0x0a, + .pll_address = 0x61, + .pll_desc = &dvb_pll_tuv1236d, +}; #endif /* ------------------------------------------------------------------ */ @@ -1012,6 +1018,9 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: dev->dvb.frontend = nxt200x_attach(&avertvhda180, &dev->i2c_adap); break; + case SAA7134_BOARD_KWORLD_ATSC110: + dev->dvb.frontend = nxt200x_attach(&kworldatsc110, &dev->i2c_adap); + break; #endif default: printk("%s: Huh? unknown DVB card?\n",dev->name); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 55a6733c363a..f8c9b6760732 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -217,6 +217,7 @@ struct saa7134_format { #define SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331 87 #define SAA7134_BOARD_TEVION_DVBT_220RF 88 #define SAA7134_BOARD_ELSA_700TV 89 +#define SAA7134_BOARD_KWORLD_ATSC110 90 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3-59-g8ed1b From fbc81c072d832a0529bdb710404e7c9dc14f3043 Mon Sep 17 00:00:00 2001 From: Curt Meyers Date: Mon, 27 Feb 2006 00:08:27 -0300 Subject: V4L/DVB (3362): KWorld ATSC110: implement set_pll_input - When tuning VSB, use ANT input - When tuning QAM, use CABLE input Signed-off-by: Curt Meyers Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-dvb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 354bbf7a1858..757796259cf9 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -928,10 +928,20 @@ static struct nxt200x_config avertvhda180 = { .pll_desc = &dvb_pll_tdhu2, }; +static int nxt200x_set_pll_input(u8 *buf, int input) +{ + if (input) + buf[3] |= 0x08; + else + buf[3] &= ~0x08; + return 0; +} + static struct nxt200x_config kworldatsc110 = { .demod_address = 0x0a, .pll_address = 0x61, .pll_desc = &dvb_pll_tuv1236d, + .set_pll_input = nxt200x_set_pll_input, }; #endif -- cgit v1.2.3-59-g8ed1b From 6ba509d7c73f6cea795a71ceed6cdb7e302fc4b7 Mon Sep 17 00:00:00 2001 From: Curt Meyers Date: Mon, 27 Feb 2006 00:08:32 -0300 Subject: V4L/DVB (3363): Kworld ATSC110: enable composite and svideo inputs - corrected composite input. - verified s-video input. Signed-off-by: Curt Meyers Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 6ce9c083de2d..0cc171ea2058 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2745,6 +2745,14 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, }}, }, }; -- cgit v1.2.3-59-g8ed1b From ccb1ef199162754e80c27e5b7d20817eb73a0eab Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 27 Feb 2006 00:08:36 -0300 Subject: V4L/DVB (3365): Kworld ATSC110: cleanups - There is no radio with this tuner card... Thanks-to: Dwaine Garden - fixed capitalization in card name. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index f74d2f9b47f5..e1484dfef103 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -88,4 +88,4 @@ 87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421] 88 -> Tevion DVB-T 220RF [17de:7201] 89 -> ELSA EX-VISION 700TV [1131:7130] - 90 -> KWORLD ATSC110 [17de:7350] + 90 -> Kworld ATSC110 [17de:7350] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 0cc171ea2058..99cefdd077ab 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2732,7 +2732,7 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_KWORLD_ATSC110] = { - .name = "KWORLD ATSC110", + .name = "Kworld ATSC110", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TUV1236D, .radio_type = UNSET, -- cgit v1.2.3-59-g8ed1b From 20b5ee5d491238b8de7ba0c06945d8e3935d42e6 Mon Sep 17 00:00:00 2001 From: Curt Meyers Date: Mon, 27 Feb 2006 00:08:39 -0300 Subject: V4L/DVB (3366): Kworld ATSC110: initialize the tuner for analog mode on module load - Enable the tuv1236 tuner on the Kworld-ATSC110 card so that the tuner can be identified when tuners.ko loads. - With this change it is no longer necessary to remove and reload the tuner module in order to get the tuv1236 identified. - This code was copied from the ATI HDTV Wonder init routine (in cx88-cards.c) which also uses the TUV1236D. Signed-off-by: Curt Meyers Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 99cefdd077ab..e1145a84b03e 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3549,6 +3549,18 @@ int saa7134_board_init2(struct saa7134_dev *dev) i2c_transfer(&dev->i2c_adap, &msg, 1); } break; + case SAA7134_BOARD_KWORLD_ATSC110: + { + /* enable tuner */ + int i; + u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 }; + dev->i2c_client.addr = 0x0a; + for (i = 0; i < 5; i++) + if (2 != i2c_master_send(&dev->i2c_client,&buffer[i*2],2)) + printk(KERN_WARNING "%s: Unable to enable tuner(%i).\n", + dev->name, i); + } + break; } return 0; } -- cgit v1.2.3-59-g8ed1b From f29edc22109840be0dd8e2d7d532cabac97d9c19 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 27 Feb 2006 00:08:43 -0300 Subject: V4L/DVB (3368): KWorld HardwareMpegTV XPert: update comments Standard video using the cx88 broadcast decoder is working, but blackbird isn't working yet, audio is only working correctly for television mode. S-Video and Composite are working for video-only, so I have them disabled for now. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 09f5739b518d..cc9d6601eafa 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1049,9 +1049,7 @@ struct cx88_board cx88_boards[] = { .dvb = 1, }, [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { - /* FIXME: This card is shipped without a windows tv app, - * so I haven't been able to use regspy to figure out the GPIO - * settings. Standard video using the cx88 broadcast decoder is + /* FIXME: Standard video using the cx88 broadcast decoder is * working, but blackbird isn't working yet, audio is only * working correctly for television mode. S-Video and Composite * are working for video-only, so I have them disabled for now. -- cgit v1.2.3-59-g8ed1b From a8029170b907e7bfac5f6ea3fcd5d076e90beaf3 Mon Sep 17 00:00:00 2001 From: Rudo Thomas Date: Mon, 27 Feb 2006 00:08:46 -0300 Subject: V4L/DVB (3369): LifeView FlyDVB-T Duo: add support for remote control The remote controller on the LifeView FlyDVB-T Duo card work flawlessly with the same settings as the LifeView FlyDVB-T LR301 card. Signed-off-by: Rudo Thomas Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 1 + drivers/media/video/saa7134/saa7134-input.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index e1145a84b03e..ca90a73f71d4 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3362,6 +3362,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_KWORLD_TERMINATOR: case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: case SAA7134_BOARD_FLYDVBT_LR301: + case SAA7134_BOARD_FLYDVBTDUO: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_MD5044: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 6970334d5ee8..1426e4c8602f 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -231,6 +231,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x040000; break; case SAA7134_BOARD_FLYDVBT_LR301: + case SAA7134_BOARD_FLYDVBTDUO: ir_codes = ir_codes_flydvb; mask_keycode = 0x0001F00; mask_keydown = 0x0040000; -- cgit v1.2.3-59-g8ed1b From 41f38b43e0bfbb2ba1ef3c778f376dad8820b214 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Feb 2006 00:08:49 -0300 Subject: V4L/DVB (3371): Add debug to ioctl arguments. Added a new function that allows printing ioctl arguments. This makes easier to include debug code under v4l ioctl handling. Also fixed some declarations on internal ioctl. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 524 ++++++++++++++++++++++++++++++++++++++ include/media/v4l2-common.h | 11 +- 2 files changed, 531 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index cd2c4475525e..a241bf7e92ca 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -362,6 +362,529 @@ void v4l_printk_ioctl(unsigned int cmd) } } +/* Common ioctl debug function. This function can be used by + external ioctl messages as well as internal V4L ioctl and its + arguments */ +void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) +{ + printk(s); + printk(": "); + v4l_printk_ioctl(cmd); + switch (cmd) { + case VIDIOC_INT_G_CHIP_IDENT: + { + enum v4l2_chip_ident *p=arg; + printk ("%s: chip ident=%d\n", s, *p); + break; + } + case VIDIOC_G_PRIORITY: + case VIDIOC_S_PRIORITY: + { + enum v4l2_priority *p=arg; + printk ("%s: priority=%d\n", s, *p); + break; + } + case VIDIOC_INT_S_TUNER_MODE: + { + enum v4l2_tuner_type *p=arg; + printk ("%s: tuner type=%d\n", s, *p); + break; + } + case DECODER_SET_VBI_BYPASS: + case DECODER_ENABLE_OUTPUT: + case DECODER_GET_STATUS: + case DECODER_SET_OUTPUT: + case DECODER_SET_INPUT: + case DECODER_SET_GPIO: + case DECODER_SET_NORM: + case VIDIOCCAPTURE: + case VIDIOCSYNC: + case VIDIOCSWRITEMODE: + case TUNER_SET_TYPE_ADDR: + case TUNER_SET_STANDBY: + case TDA9887_SET_CONFIG: + case AUDC_SET_INPUT: + case VIDIOC_OVERLAY_OLD: + case VIDIOC_STREAMOFF: + case VIDIOC_G_OUTPUT: + case VIDIOC_S_OUTPUT: + case VIDIOC_STREAMON: + case VIDIOC_G_INPUT: + case VIDIOC_OVERLAY: + case VIDIOC_S_INPUT: + { + int *p=arg; + printk ("%s: value=%d\n", s, *p); + break; + } + case MSP_SET_MATRIX: + { + struct msp_matrix *p=arg; + printk ("%s: input=%d, output=%d\n", s, p->input, p->output); + break; + } + case VIDIOC_G_AUDIO: + case VIDIOC_S_AUDIO: + case VIDIOC_ENUMAUDIO: + case VIDIOC_G_AUDIO_OLD: + { + struct v4l2_audio *p=arg; + + printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", + s,p->index, p->name,p->capability, p->mode); + break; + } + case VIDIOC_G_AUDOUT: + case VIDIOC_S_AUDOUT: + case VIDIOC_ENUMAUDOUT: + case VIDIOC_G_AUDOUT_OLD: + { + struct v4l2_audioout *p=arg; + printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", s, + p->index, p->name, p->capability,p->mode); + break; + } + case VIDIOC_QBUF: + case VIDIOC_DQBUF: + case VIDIOC_QUERYBUF: + { + struct v4l2_buffer *p=arg; + struct v4l2_timecode *tc=&p->timecode; + printk ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%d, " + "bytesused=%d, flags=0x%08d, " + "field=%0d, sequence=%d, memory=%d, offset/userptr=0x%08lx,", + s, + (p->timestamp.tv_sec/3600), + (int)(p->timestamp.tv_sec/60)%60, + (int)(p->timestamp.tv_sec%60), + p->timestamp.tv_usec, + p->index,p->type,p->bytesused,p->flags, + p->field,p->sequence,p->memory,p->m.userptr); + printk ("%s: timecode= %02d:%02d:%02d type=%d, " + "flags=0x%08d, frames=%d, userbits=0x%08x", + s,tc->hours,tc->minutes,tc->seconds, + tc->type, tc->flags, tc->frames, (__u32) tc->userbits); + break; + } + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *p=arg; + printk ("%s: driver=%s, card=%s, bus=%s, version=%d, " + "capabilities=%d\n", s, + p->driver,p->card,p->bus_info, + p->version, + p->capabilities); + break; + } + case VIDIOC_G_CTRL: + case VIDIOC_S_CTRL: + case VIDIOC_S_CTRL_OLD: + { + struct v4l2_control *p=arg; + printk ("%s: id=%d, value=%d\n", s, p->id, p->value); + break; + } + case VIDIOC_G_CROP: + case VIDIOC_S_CROP: + { + struct v4l2_crop *p=arg; + /*FIXME: Should also show rect structs */ + printk ("%s: type=%d\n", s, p->type); + break; + } + case VIDIOC_CROPCAP: + case VIDIOC_CROPCAP_OLD: + { + struct v4l2_cropcap *p=arg; + /*FIXME: Should also show rect structs */ + printk ("%s: type=%d\n", s, p->type); + break; + } + case VIDIOC_INT_DECODE_VBI_LINE: + { + struct v4l2_decode_vbi_line *p=arg; + printk ("%s: is_second_field=%d, ptr=0x%08lx, line=%d, " + "type=%d\n", s, + p->is_second_field,(unsigned long)p->p,p->line,p->type); + break; + } + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *p=arg; + printk ("%s: index=%d, type=%d, flags=%d, description=%s," + " pixelformat=%d\n", s, + p->index, p->type, p->flags,p->description, + p->pixelformat); + + break; + } + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_TRY_FMT: + { + struct v4l2_format *p=arg; + /* FIXME: Should be one dump per type*/ + printk ("%s: type=%d\n", s,p->type); + break; + } + case VIDIOC_G_FBUF: + case VIDIOC_S_FBUF: + { + struct v4l2_framebuffer *p=arg; + /*FIXME: should show also struct v4l2_pix_format p->fmt field */ + printk ("%s: capability=%d, flags=%d, base=0x%08lx\n", s, + p->capability,p->flags, (unsigned long)p->base); + break; + } + case VIDIOC_G_FREQUENCY: + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *p=arg; + printk ("%s: tuner=%d, type=%d, frequency=%d\n", s, + p->tuner,p->type,p->frequency); + break; + } + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *p=arg; + printk ("%s: index=%d, name=%s, type=%d, audioset=%d, " + "tuner=%d, std=%lld, status=%d\n", s, + p->index,p->name,p->type,p->audioset, + p->tuner,p->std, + p->status); + break; + } + case VIDIOC_G_JPEGCOMP: + case VIDIOC_S_JPEGCOMP: + { + struct v4l2_jpegcompression *p=arg; + printk ("%s: quality=%d, APPn=%d, APP_len=%d, COM_len=%d," + " jpeg_markers=%d\n", s, + p->quality,p->APPn,p->APP_len, + p->COM_len,p->jpeg_markers); + break; + } + case VIDIOC_G_MODULATOR: + case VIDIOC_S_MODULATOR: + { + struct v4l2_modulator *p=arg; + printk ("%s: index=%d, name=%s, capability=%d, rangelow=%d," + " rangehigh=%d, txsubchans=%d\n", s, + p->index, p->name,p->capability,p->rangelow, + p->rangehigh,p->txsubchans); + break; + } + case VIDIOC_G_MPEGCOMP: + case VIDIOC_S_MPEGCOMP: + { + struct v4l2_mpeg_compression *p=arg; + /*FIXME: Several fields not shown */ + printk ("%s: ts_pid_pmt=%d, ts_pid_audio=%d, ts_pid_video=%d, " + "ts_pid_pcr=%d, ps_size=%d, au_sample_rate=%d, " + "au_pesid=%c, vi_frame_rate=%d, vi_frames_per_gop=%d, " + "vi_bframes_count=%d, vi_pesid=%c\n", s, + p->ts_pid_pmt,p->ts_pid_audio, p->ts_pid_video, + p->ts_pid_pcr, p->ps_size, p->au_sample_rate, + p->au_pesid, p->vi_frame_rate, + p->vi_frames_per_gop, p->vi_bframes_count, + p->vi_pesid); + break; + } + case VIDIOC_ENUMOUTPUT: + { + struct v4l2_output *p=arg; + printk ("%s: index=%d, name=%s,type=%d, audioset=%d, " + "modulator=%d, std=%lld\n", + s,p->index,p->name,p->type,p->audioset, + p->modulator,p->std); + break; + } + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *p=arg; + printk ("%s: id=%d, type=%d, name=%s, min/max=%d/%d," + " step=%d, default=%d, flags=0x%08x\n", s, + p->id,p->type,p->name,p->minimum,p->maximum, + p->step,p->default_value,p->flags); + break; + } + case VIDIOC_QUERYMENU: + { + struct v4l2_querymenu *p=arg; + printk ("%s: id=%d, index=%d, name=%s\n", s, + p->id,p->index,p->name); + break; + } + case VIDIOC_INT_G_REGISTER: + case VIDIOC_INT_S_REGISTER: + { + struct v4l2_register *p=arg; + printk ("%s: i2c_id=%d, reg=%lu, val=%d\n", s, + p->i2c_id,p->reg,p->val); + + break; + } + case VIDIOC_REQBUFS: + { + struct v4l2_requestbuffers *p=arg; + printk ("%s: count=%d, type=%d, memory=%d\n", s, + p->count,p->type,p->memory); + break; + } + case VIDIOC_INT_S_AUDIO_ROUTING: + case VIDIOC_INT_S_VIDEO_ROUTING: + case VIDIOC_INT_G_AUDIO_ROUTING: + case VIDIOC_INT_G_VIDEO_ROUTING: + { + struct v4l2_routing *p=arg; + printk ("%s: input=%d, output=%d\n", s, p->input, p->output); + break; + } + case VIDIOC_G_SLICED_VBI_CAP: + { + struct v4l2_sliced_vbi_cap *p=arg; + printk ("%s: service_set=%d\n", s, + p->service_set); + break; + } + case VIDIOC_INT_S_VBI_DATA: + case VIDIOC_INT_G_VBI_DATA: + { + struct v4l2_sliced_vbi_data *p=arg; + printk ("%s: id=%d, field=%d, line=%d\n", s, + p->id, p->field, p->line); + break; + } + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *p=arg; + printk ("%s: index=%d, id=%lld, name=%s, fps=%d/%d, framelines=%d\n", s, + p->index, p->id, p->name, + p->frameperiod.numerator, + p->frameperiod.denominator, + p->framelines); + + break; + } + case VIDIOC_G_PARM: + case VIDIOC_S_PARM: + case VIDIOC_S_PARM_OLD: + { + struct v4l2_streamparm *p=arg; + printk ("%s: type=%d\n", s, p->type); + + break; + } + case VIDIOC_G_TUNER: + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *p=arg; + printk ("%s: index=%d, name=%s, type=%d, capability=%d, " + "rangelow=%d, rangehigh=%d, signal=%d, afc=%d, " + "rxsubchans=%d, audmode=%d\n", s, + p->index, p->name, p->type, + p->capability, p->rangelow,p->rangehigh, + p->rxsubchans, p->audmode, p->signal, + p->afc); + break; + } + case VIDIOCGVBIFMT: + case VIDIOCSVBIFMT: + { + struct vbi_format *p=arg; + printk ("%s: sampling_rate=%d, samples_per_line=%d, " + "sample_format=%d, start=%d/%d, count=%d/%d, flags=%d\n", s, + p->sampling_rate,p->samples_per_line, + p->sample_format,p->start[0],p->start[1], + p->count[0],p->count[1],p->flags); + break; + } + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + { + struct video_audio *p=arg; + printk ("%s: audio=%d, volume=%d, bass=%d, treble=%d, " + "flags=%d, name=%s, mode=%d, balance=%d, step=%d\n", + s,p->audio,p->volume,p->bass, p->treble, + p->flags,p->name,p->mode,p->balance,p->step); + break; + } + case VIDIOCGFBUF: + case VIDIOCSFBUF: + { + struct video_buffer *p=arg; + printk ("%s: base=%08lx, height=%d, width=%d, depth=%d, " + "bytesperline=%d\n", s, + (unsigned long) p->base, p->height, p->width, + p->depth,p->bytesperline); + break; + } + case VIDIOCGCAP: + { + struct video_capability *p=arg; + printk ("%s: name=%s, type=%d, channels=%d, audios=%d, " + "maxwidth=%d, maxheight=%d, minwidth=%d, minheight=%d\n", + s,p->name,p->type,p->channels,p->audios, + p->maxwidth,p->maxheight,p->minwidth, + p->minheight); + + break; + } + case VIDIOCGCAPTURE: + case VIDIOCSCAPTURE: + { + struct video_capture *p=arg; + printk ("%s: x=%d, y=%d, width=%d, height=%d, decimation=%d," + " flags=%d\n", s, + p->x, p->y,p->width, p->height, + p->decimation,p->flags); + break; + } + case VIDIOCGCHAN: + case VIDIOCSCHAN: + { + struct video_channel *p=arg; + printk ("%s: channel=%d, name=%s, tuners=%d, flags=%d, " + "type=%d, norm=%d\n", s, + p->channel,p->name,p->tuners, + p->flags,p->type,p->norm); + + break; + } + case VIDIOCSMICROCODE: + { + struct video_code *p=arg; + printk ("%s: loadwhat=%s, datasize=%d\n", s, + p->loadwhat,p->datasize); + break; + } + case DECODER_GET_CAPABILITIES: + { + struct video_decoder_capability *p=arg; + printk ("%s: flags=%d, inputs=%d, outputs=%d\n", s, + p->flags,p->inputs,p->outputs); + break; + } + case DECODER_INIT: + { + struct video_decoder_init *p=arg; + printk ("%s: len=%c\n", s, p->len); + break; + } + case VIDIOCGPLAYINFO: + { + struct video_info *p=arg; + printk ("%s: frame_count=%d, h_size=%d, v_size=%d, " + "smpte_timecode=%d, picture_type=%d, " + "temporal_reference=%d, user_data=%s\n", s, + p->frame_count, p->h_size, + p->v_size, p->smpte_timecode, + p->picture_type, p->temporal_reference, + p->user_data); + break; + } + case VIDIOCKEY: + { + struct video_key *p=arg; + printk ("%s: key=%s, flags=%d\n", s, + p->key, p->flags); + break; + } + case VIDIOCGMBUF: + { + struct video_mbuf *p=arg; + printk ("%s: size=%d, frames=%d, offsets=0x%08lx\n", s, + p->size, + p->frames, + (unsigned long)p->offsets); + break; + } + case VIDIOCMCAPTURE: + { + struct video_mmap *p=arg; + printk ("%s: frame=%d, height=%d, width=%d, format=%d\n", s, + p->frame, + p->height, p->width, + p->format); + break; + } + case VIDIOCGPICT: + case VIDIOCSPICT: + case DECODER_SET_PICTURE: + { + struct video_picture *p=arg; + + printk ("%s: brightness=%d, hue=%d, colour=%d, contrast=%d," + " whiteness=%d, depth=%d, palette=%d\n", s, + p->brightness, p->hue, p->colour, + p->contrast, p->whiteness, p->depth, + p->palette); + break; + } + case VIDIOCSPLAYMODE: + { + struct video_play_mode *p=arg; + printk ("%s: mode=%d, p1=%d, p2=%d\n", s, + p->mode,p->p1,p->p2); + break; + } + case VIDIOCGTUNER: + case VIDIOCSTUNER: + { + struct video_tuner *p=arg; + printk ("%s: tuner=%d, name=%s, rangelow=%ld, rangehigh=%ld, " + "flags=%d, mode=%d, signal=%d\n", s, + p->tuner, p->name,p->rangelow, p->rangehigh, + p->flags,p->mode, p->signal); + break; + } + case VIDIOCGUNIT: + { + struct video_unit *p=arg; + printk ("%s: video=%d, vbi=%d, radio=%d, audio=%d, " + "teletext=%d\n", s, + p->video,p->vbi,p->radio,p->audio,p->teletext); + break; + } + case VIDIOCGWIN: + case VIDIOCSWIN: + { + struct video_window *p=arg; + printk ("%s: x=%d, y=%d, width=%d, height=%d, chromakey=%d," + " flags=%d, clipcount=%d\n", s, + p->x, p->y,p->width, p->height, + p->chromakey,p->flags, + p->clipcount); + break; + } + case VIDIOC_INT_AUDIO_CLOCK_FREQ: + case VIDIOC_INT_I2S_CLOCK_FREQ: + case VIDIOC_INT_S_STANDBY: + { + u32 *p=arg; + + printk ("%s: value=%d\n", s, *p); + break; + } + case VIDIOCGFREQ: + case VIDIOCSFREQ: + { + unsigned long *p=arg; + printk ("%s: value=%lu\n", s, *p); + break; + } + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case VIDIOC_QUERYSTD: + { + v4l2_std_id *p=arg; + + printk ("%s: value=%llu\n", s, *p); + break; + } + } +} + /* ----------------------------------------------------------------- */ EXPORT_SYMBOL(v4l2_video_std_construct); @@ -376,6 +899,7 @@ EXPORT_SYMBOL(v4l2_prio_check); EXPORT_SYMBOL(v4l2_field_names); EXPORT_SYMBOL(v4l2_type_names); EXPORT_SYMBOL(v4l_printk_ioctl); +EXPORT_SYMBOL(v4l_printk_ioctl_arg); /* * Local variables: diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 234e9cf7e844..c44741e78f20 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -58,6 +58,9 @@ /* Prints the ioctl in a human-readable format */ extern void v4l_printk_ioctl(unsigned int cmd); +/* Prints the ioctl and arg in a human-readable format */ +extern void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg); + /* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */ #define v4l_print_ioctl(name, cmd) \ do { \ @@ -185,11 +188,11 @@ struct msp_matrix { register contains invalid or erroneous data -EIO is returned. Note that you must fill in the 'id' member and the 'field' member (to determine whether CC data from the first or second field should be obtained). */ -#define VIDIOC_INT_G_VBI_DATA _IOWR('d', 106, struct v4l2_sliced_vbi_data *) +#define VIDIOC_INT_G_VBI_DATA _IOWR('d', 106, struct v4l2_sliced_vbi_data) /* Returns the chip identifier or V4L2_IDENT_UNKNOWN if no identification can be made. */ -#define VIDIOC_INT_G_CHIP_IDENT _IOR ('d', 107, enum v4l2_chip_ident *) +#define VIDIOC_INT_G_CHIP_IDENT _IOR ('d', 107, enum v4l2_chip_ident) /* Sets I2S speed in bps. This is used to provide a standard way to select I2S clock used by driving digital audio streams at some board designs. @@ -214,8 +217,8 @@ struct v4l2_routing { These four commands should only be sent directly to an i2c device, they should not be broadcast as the routing is very device specific. */ #define VIDIOC_INT_S_AUDIO_ROUTING _IOW ('d', 109, struct v4l2_routing) -#define VIDIOC_INT_G_AUDIO_ROUTING _IOR ('d', 110, struct v4l2_routing *) +#define VIDIOC_INT_G_AUDIO_ROUTING _IOR ('d', 110, struct v4l2_routing) #define VIDIOC_INT_S_VIDEO_ROUTING _IOW ('d', 111, struct v4l2_routing) -#define VIDIOC_INT_G_VIDEO_ROUTING _IOR ('d', 112, struct v4l2_routing *) +#define VIDIOC_INT_G_VIDEO_ROUTING _IOR ('d', 112, struct v4l2_routing) #endif /* V4L2_COMMON_H_ */ -- cgit v1.2.3-59-g8ed1b From 3ed33c31a7253f2b29a3813b66bf87985d3396ac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Feb 2006 00:08:52 -0300 Subject: V4L/DVB (3372): Fix a small bug when constructing fps and line numbers Previously, only NTSC and PAL/M were associated to 30fps and 525 lines, so, PAL/60 were not handled properly. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index a241bf7e92ca..4908dab2df18 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -97,7 +97,7 @@ int v4l2_video_std_construct(struct v4l2_standard *vs, memset(vs, 0, sizeof(struct v4l2_standard)); vs->index = index; vs->id = id; - if (id & (V4L2_STD_NTSC | V4L2_STD_PAL_M)) { + if (id & V4L2_STD_525_60) { vs->frameperiod.numerator = 1001; vs->frameperiod.denominator = 30000; vs->framelines = 525; @@ -110,7 +110,6 @@ int v4l2_video_std_construct(struct v4l2_standard *vs, return 0; } - /* ----------------------------------------------------------------- */ /* priority handling */ -- cgit v1.2.3-59-g8ed1b From 0bbb9c175211c2e114216978c9630d894c7760b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Feb 2006 00:08:55 -0300 Subject: V4L/DVB (3373): Debug messages for ioctl improved Adds field and type name to debug message. Also prints now format for type=capture. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 4908dab2df18..9e41ab7d5677 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -323,6 +323,16 @@ static const char *v4l2_int_ioctls[] = { }; #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls) +static void v4l_print_pix_fmt (char *s, struct v4l2_pix_format *fmt) +{ + printk ("%s: width=%d, height=%d, format=%d, field=%s, " + "bytesperline=%d sizeimage=%d, colorspace=%d\n", s, + fmt->width,fmt->height,fmt->pixelformat, + ((fmt->field>=0)&&(fmt->fieldfield]:"unknown", + fmt->bytesperline,fmt->sizeimage,fmt->colorspace); +}; + /* Common ioctl debug function. This function can be used by external ioctl messages as well as internal V4L ioctl */ void v4l_printk_ioctl(unsigned int cmd) @@ -449,15 +459,18 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) { struct v4l2_buffer *p=arg; struct v4l2_timecode *tc=&p->timecode; - printk ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%d, " + printk ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%s, " "bytesused=%d, flags=0x%08d, " - "field=%0d, sequence=%d, memory=%d, offset/userptr=0x%08lx,", + "field=%0d, sequence=%d, memory=%d, offset/userptr=0x%08lx\n", s, (p->timestamp.tv_sec/3600), (int)(p->timestamp.tv_sec/60)%60, (int)(p->timestamp.tv_sec%60), p->timestamp.tv_usec, - p->index,p->type,p->bytesused,p->flags, + p->index, + ((p->type>=0)&&(p->typetype]:"unknown", + p->bytesused,p->flags, p->field,p->sequence,p->memory,p->m.userptr); printk ("%s: timecode= %02d:%02d:%02d type=%d, " "flags=0x%08d, frames=%d, userbits=0x%08x", @@ -522,17 +535,24 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) case VIDIOC_TRY_FMT: { struct v4l2_format *p=arg; - /* FIXME: Should be one dump per type*/ - printk ("%s: type=%d\n", s,p->type); - break; + printk ("%s: type=%s\n", s, + ((p->type>=0)&&(p->typetype]:"unknown"); + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + v4l_print_pix_fmt (s, &p->fmt.pix); + break; + default: + break; + } } case VIDIOC_G_FBUF: case VIDIOC_S_FBUF: { struct v4l2_framebuffer *p=arg; - /*FIXME: should show also struct v4l2_pix_format p->fmt field */ printk ("%s: capability=%d, flags=%d, base=0x%08lx\n", s, p->capability,p->flags, (unsigned long)p->base); + v4l_print_pix_fmt (s, &p->fmt); break; } case VIDIOC_G_FREQUENCY: -- cgit v1.2.3-59-g8ed1b From 2e0d447005d2ac05b15aa21b3846815f90bafbdb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Feb 2006 00:08:58 -0300 Subject: V4L/DVB (3374): Adds debuging v4l2_memory enum Some cleanup on printing enum names. v4l2_memory now translated also to name. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 9e41ab7d5677..95a6e47c99f1 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -170,7 +170,7 @@ int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local) /* ----------------------------------------------------------------- */ -/* some arrays for pretty-printing debug messages */ +/* some arrays for pretty-printing debug messages of enum types */ char *v4l2_field_names[] = { [V4L2_FIELD_ANY] = "any", @@ -191,6 +191,14 @@ char *v4l2_type_names[] = { [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", }; +static char *v4l2_memory_names[] = { + [V4L2_MEMORY_MMAP] = "mmap", + [V4L2_MEMORY_USERPTR] = "userptr", + [V4L2_MEMORY_OVERLAY] = "overlay", +}; + +#define prt_names(a,arr) (((a)>=0)&&((a)width,fmt->height,fmt->pixelformat, - ((fmt->field>=0)&&(fmt->fieldfield]:"unknown", + prt_names(fmt->field,v4l2_field_names), fmt->bytesperline,fmt->sizeimage,fmt->colorspace); }; @@ -461,17 +468,18 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) struct v4l2_timecode *tc=&p->timecode; printk ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%s, " "bytesused=%d, flags=0x%08d, " - "field=%0d, sequence=%d, memory=%d, offset/userptr=0x%08lx\n", + "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n", s, (p->timestamp.tv_sec/3600), (int)(p->timestamp.tv_sec/60)%60, (int)(p->timestamp.tv_sec%60), p->timestamp.tv_usec, p->index, - ((p->type>=0)&&(p->typetype]:"unknown", + prt_names(p->type,v4l2_type_names), p->bytesused,p->flags, - p->field,p->sequence,p->memory,p->m.userptr); + p->field,p->sequence, + prt_names(p->memory,v4l2_memory_names), + p->m.userptr); printk ("%s: timecode= %02d:%02d:%02d type=%d, " "flags=0x%08d, frames=%d, userbits=0x%08x", s,tc->hours,tc->minutes,tc->seconds, @@ -536,8 +544,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) { struct v4l2_format *p=arg; printk ("%s: type=%s\n", s, - ((p->type>=0)&&(p->typetype]:"unknown"); + prt_names(p->type,v4l2_type_names)); switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: v4l_print_pix_fmt (s, &p->fmt.pix); @@ -646,8 +653,10 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) case VIDIOC_REQBUFS: { struct v4l2_requestbuffers *p=arg; - printk ("%s: count=%d, type=%d, memory=%d\n", s, - p->count,p->type,p->memory); + printk ("%s: count=%d, type=%s, memory=%s\n", s, + p->count, + prt_names(p->type,v4l2_type_names), + prt_names(p->memory,v4l2_memory_names)); break; } case VIDIOC_INT_S_AUDIO_ROUTING: -- cgit v1.2.3-59-g8ed1b From ab33d5071de7a33616842882c11b5eb52a6c26a1 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Feb 2006 00:09:05 -0300 Subject: V4L/DVB (3376): Add cpia2 camera support There has been a CPIA2 driver out of kernel for a long time and it has been pretty clean for some time too. This is an import of the sourceforge driver which has been stripped of - 2.4 back compatibility - 2.4 old style MJPEG ioctls A couple of functions have been made static and the docs have been repackaged into Documentation/video4linux. The rvmalloc/free functions now match the cpia driver again. Other than that this is the code as is. Tested on x86-64 with a QX5 microscope. Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/README.cpia2 | 130 ++ Documentation/video4linux/cpia2_overview.txt | 38 + drivers/media/video/Kconfig | 10 + drivers/media/video/Makefile | 1 + drivers/media/video/cpia2/Makefile | 3 + drivers/media/video/cpia2/cpia2.h | 497 +++++ drivers/media/video/cpia2/cpia2_core.c | 2525 ++++++++++++++++++++++++++ drivers/media/video/cpia2/cpia2_registers.h | 476 +++++ drivers/media/video/cpia2/cpia2_usb.c | 907 +++++++++ drivers/media/video/cpia2/cpia2_v4l.c | 2104 +++++++++++++++++++++ drivers/media/video/cpia2/cpia2dev.h | 50 + drivers/media/video/cpia2/cpia2patch.h | 233 +++ 12 files changed, 6974 insertions(+) create mode 100644 Documentation/video4linux/README.cpia2 create mode 100644 Documentation/video4linux/cpia2_overview.txt create mode 100644 drivers/media/video/cpia2/Makefile create mode 100644 drivers/media/video/cpia2/cpia2.h create mode 100644 drivers/media/video/cpia2/cpia2_core.c create mode 100644 drivers/media/video/cpia2/cpia2_registers.h create mode 100644 drivers/media/video/cpia2/cpia2_usb.c create mode 100644 drivers/media/video/cpia2/cpia2_v4l.c create mode 100644 drivers/media/video/cpia2/cpia2dev.h create mode 100644 drivers/media/video/cpia2/cpia2patch.h (limited to 'drivers') diff --git a/Documentation/video4linux/README.cpia2 b/Documentation/video4linux/README.cpia2 new file mode 100644 index 000000000000..f3bd3439ad91 --- /dev/null +++ b/Documentation/video4linux/README.cpia2 @@ -0,0 +1,130 @@ +$Id: README,v 1.7 2005/08/29 23:39:57 sbertin Exp $ + +1. Introduction + + This is a driver for STMicroelectronics's CPiA2 (second generation +Colour Processor Interface ASIC) based cameras. This camera outputs an MJPEG +stream at up to vga size. It implements the Video4Linux interface as much as +possible. Since the V4L interface does not support compressed formats, only +an mjpeg enabled application can be used with the camera. We have modified the +gqcam application to view this stream. + + The driver is implemented as two kernel modules. The cpia2 module +contains the camera functions and the V4L interface. The cpia2_usb module +contains usb specific functions. The main reason for this was the size of the +module was getting out of hand, so I separted them. It is not likely that +there will be a parallel port version. + +FEATURES: + - Supports cameras with the Vision stv6410 (CIF) and stv6500 (VGA) cmos + sensors. I only have the vga sensor, so can't test the other. + - Image formats: VGA, QVGA, CIF, QCIF, and a number of sizes in between. + VGA and QVGA are the native image sizes for the VGA camera. CIF is done + in the coprocessor by scaling QVGA. All other sizes are done by clipping. + - Palette: YCrCb, compressed with MJPEG. + - Some compression parameters are settable. + - Sensor framerate is adjustable (up to 30 fps CIF, 15 fps VGA). + - Adjust brightness, color, contrast while streaming. + - Flicker control settable for 50 or 60 Hz mains frequency. + +2. Making and installing the stv672 driver modules: + + Requirements: + ------------- + This should work with 2.4 (2.4.23 and later) and 2.6 kernels, but has +only been tested on 2.6. Video4Linux must be either compiled into the kernel or +available as a module. Video4Linux2 is automatically detected and made +available at compile time. + + Compiling: + ---------- + As root, do a make install. This will compile and install the modules +into the media/video directory in the module tree. For 2.4 kernels, use +Makefile_2.4 (aka do make -f Makefile_2.4 install). + + Setup: + ------ + Use 'modprobe cpia2' to load and 'modprobe -r cpia2' to unload. This +may be done automatically by your distribution. + +3. Driver options + + Option Description + ------ ----------- + video_nr video device to register (0=/dev/video0, etc) + range -1 to 64. default is -1 (first available) + If you have more than 1 camera, this MUST be -1. + buffer_size Size for each frame buffer in bytes (default 68k) + num_buffers Number of frame buffers (1-32, default 3) + alternate USB Alternate (2-7, default 7) + flicker_freq Frequency for flicker reduction(50 or 60, default 60) + flicker_mode 0 to disable, or 1 to enable flicker reduction. + (default 0). This is only effective if the camera + uses a stv0672 coprocessor. + + Setting the options: + -------------------- + If you are using modules, edit /etc/modules.conf and add an options +line like this: + options cpia2 num_buffers=3 buffer_size=65535 + + If the driver is compiled into the kernel, at boot time specify them +like this: + cpia2=num_buffers:3,buffer_size:65535 + + What buffer size should I use? + ------------------------------ + The maximum image size depends on the alternate you choose, and the +frame rate achieved by the camera. If the compression engine is able to +keep up with the frame rate, the maximum image size is given by the table +below. + The compression engine starts out at maximum compression, and will +increase image quality until it is close to the size in the table. As long +as the compression engine can keep up with the frame rate, after a short time +the images will all be about the size in the table, regardless of resolution. + At low alternate settings, the compression engine may not be able to +compress the image enough and will reduce the frame rate by producing larger +images. + The default of 68k should be good for most users. This will handle +any alternate at frame rates down to 15fps. For lower frame rates, it may +be necessary to increase the buffer size to avoid having frames dropped due +to insufficient space. + + Image size(bytes) + Alternate bytes/ms 15fps 30fps + 2 128 8533 4267 + 3 384 25600 12800 + 4 640 42667 21333 + 5 768 51200 25600 + 6 896 59733 29867 + 7 1023 68200 34100 + + How many buffers should I use? + ------------------------------ + For normal streaming, 3 should give the best results. With only 2, +it is possible for the camera to finish sending one image just after a +program has started reading the other. If this happens, the driver must drop +a frame. The exception to this is if you have a heavily loaded machine. In +this case use 2 buffers. You are probably not reading at the full frame rate. +If the camera can send multiple images before a read finishes, it could +overwrite the third buffer before the read finishes, leading to a corrupt +image. Single and double buffering have extra checks to avoid overwriting. + +4. Using the camera + + We are providing a modified gqcam application to view the output. In +order to avoid confusion, here it is called mview. There is also the qx5view +program which can also control the lights on the qx5 microscope. MJPEG Tools +(http://mjpeg.sourceforge.net) can also be used to record from the camera. + +5. Notes to developers: + + - This is a driver version stripped of the 2.4 back compatibility + and old MJPEG ioctl API. See cpia2.sf.net for 2.4 support. + +6. Thanks: + + - Peter Pregler , + Scott J. Bertin , and + Jarl Totland for the original cpia driver, which + this one was modelled from. diff --git a/Documentation/video4linux/cpia2_overview.txt b/Documentation/video4linux/cpia2_overview.txt new file mode 100644 index 000000000000..a6e53665216b --- /dev/null +++ b/Documentation/video4linux/cpia2_overview.txt @@ -0,0 +1,38 @@ + Programmer's View of Cpia2 + +Cpia2 is the second generation video coprocessor from VLSI Vision Ltd (now a +division of ST Microelectronics). There are two versions. The first is the +STV0672, which is capable of up to 30 frames per second (fps) in frame sizes +up to CIF, and 15 fps for VGA frames. The STV0676 is an improved version, +which can handle up to 30 fps VGA. Both coprocessors can be attached to two +CMOS sensors - the vvl6410 CIF sensor and the vvl6500 VGA sensor. These will +be referred to as the 410 and the 500 sensors, or the CIF and VGA sensors. + +The two chipsets operate almost identically. The core is an 8051 processor, +running two different versions of firmware. The 672 runs the VP4 video +processor code, the 676 runs VP5. There are a few differences in register +mappings for the two chips. In these cases, the symbols defined in the +header files are marked with VP4 or VP5 as part of the symbol name. + +The cameras appear externally as three sets of registers. Setting register +values is the only way to control the camera. Some settings are +interdependant, such as the sequence required to power up the camera. I will +try to make note of all of these cases. + +The register sets are called blocks. Block 0 is the system block. This +section is always powered on when the camera is plugged in. It contains +registers that control housekeeping functions such as powering up the video +processor. The video processor is the VP block. These registers control +how the video from the sensor is processed. Examples are timing registers, +user mode (vga, qvga), scaling, cropping, framerates, and so on. The last +block is the video compressor (VC). The video stream sent from the camera is +compressed as Motion JPEG (JPEGA). The VC controls all of the compression +parameters. Looking at the file cpia2_registers.h, you can get a full view +of these registers and the possible values for most of them. + +One or more registers can be set or read by sending a usb control message to +the camera. There are three modes for this. Block mode requests a number +of contiguous registers. Random mode reads or writes random registers with +a tuple structure containing address/value pairs. The repeat mode is only +used by VP4 to load a firmware patch. It contains a starting address and +a sequence of bytes to be written into a gpio port. \ No newline at end of file diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index d82c8a30ba44..f6889f771053 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -142,6 +142,16 @@ config VIDEO_CPIA_USB otherwise say N. This will not work with the Creative Webcam III. It is also available as a module (cpia_usb). +config VIDEO_CPIA2 + tristate "CPiA2 Video For Linux" + depends on VIDEO_DEV + ---help--- + This is the video4linux driver for cameras based on Vision's CPiA2 + (Colour Processor Interface ASIC), such as the Digital Blue QX5 + Microscope. If you have one of these cameras, say Y here + + This driver is also available as a module (cpia2). + config VIDEO_SAA5246A tristate "SAA5246A, SAA5281 Teletext processor" depends on VIDEO_DEV && I2C diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index faf728366c4e..87b1ce6e2050 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ +obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o diff --git a/drivers/media/video/cpia2/Makefile b/drivers/media/video/cpia2/Makefile new file mode 100644 index 000000000000..828cf1b1df86 --- /dev/null +++ b/drivers/media/video/cpia2/Makefile @@ -0,0 +1,3 @@ +cpia2-objs := cpia2_v4l.o cpia2_usb.o cpia2_core.o + +obj-$(CONFIG_VIDEO_CPIA2) += cpia2.o diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h new file mode 100644 index 000000000000..95d3afa94a3d --- /dev/null +++ b/drivers/media/video/cpia2/cpia2.h @@ -0,0 +1,497 @@ +/**************************************************************************** + * + * Filename: cpia2.h + * + * Copyright 2001, STMicrolectronics, Inc. + * + * Contact: steve.miller@st.com + * + * Description: + * This is a USB driver for CPiA2 based video cameras. + * + * This driver is modelled on the cpia usb driver by + * Jochen Scharrlach and Johannes Erdfeldt. + * + * 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. + * + ****************************************************************************/ + +#ifndef __CPIA2_H__ +#define __CPIA2_H__ + +#include +#include +#include +#include + +#include "cpia2dev.h" +#include "cpia2_registers.h" + +/* define for verbose debug output */ +//#define _CPIA2_DEBUG_ + +#define CPIA2_MAJ_VER 2 +#define CPIA2_MIN_VER 0 +#define CPIA2_PATCH_VER 0 + +/*** + * Image defines + ***/ +#ifndef true +#define true 1 +#define false 0 +#endif + +/* Misc constants */ +#define ALLOW_CORRUPT 0 /* Causes collater to discard checksum */ + +/* USB Transfer mode */ +#define XFER_ISOC 0 +#define XFER_BULK 1 + +/* USB Alternates */ +#define USBIF_CMDONLY 0 +#define USBIF_BULK 1 +#define USBIF_ISO_1 2 /* 128 bytes/ms */ +#define USBIF_ISO_2 3 /* 384 bytes/ms */ +#define USBIF_ISO_3 4 /* 640 bytes/ms */ +#define USBIF_ISO_4 5 /* 768 bytes/ms */ +#define USBIF_ISO_5 6 /* 896 bytes/ms */ +#define USBIF_ISO_6 7 /* 1023 bytes/ms */ + +/* Flicker Modes */ +#define NEVER_FLICKER 0 +#define ANTI_FLICKER_ON 1 +#define FLICKER_60 60 +#define FLICKER_50 50 + +/* Debug flags */ +#define DEBUG_NONE 0 +#define DEBUG_REG 0x00000001 +#define DEBUG_DUMP_PATCH 0x00000002 +#define DEBUG_DUMP_REGS 0x00000004 + +/*** + * Video frame sizes + ***/ +enum { + VIDEOSIZE_VGA = 0, /* 640x480 */ + VIDEOSIZE_CIF, /* 352x288 */ + VIDEOSIZE_QVGA, /* 320x240 */ + VIDEOSIZE_QCIF, /* 176x144 */ + VIDEOSIZE_288_216, + VIDEOSIZE_256_192, + VIDEOSIZE_224_168, + VIDEOSIZE_192_144, +}; + +#define STV_IMAGE_CIF_ROWS 288 +#define STV_IMAGE_CIF_COLS 352 + +#define STV_IMAGE_QCIF_ROWS 144 +#define STV_IMAGE_QCIF_COLS 176 + +#define STV_IMAGE_VGA_ROWS 480 +#define STV_IMAGE_VGA_COLS 640 + +#define STV_IMAGE_QVGA_ROWS 240 +#define STV_IMAGE_QVGA_COLS 320 + +#define JPEG_MARKER_COM (1<<6) /* Comment segment */ + +/*** + * Enums + ***/ +/* Sensor types available with cpia2 asics */ +enum sensors { + CPIA2_SENSOR_410, + CPIA2_SENSOR_500 +}; + +/* Asic types available in the CPiA2 architecture */ +#define CPIA2_ASIC_672 0x67 + +/* Device types (stv672, stv676, etc) */ +#define DEVICE_STV_672 0x0001 +#define DEVICE_STV_676 0x0002 + +enum frame_status { + FRAME_EMPTY, + FRAME_READING, /* In the process of being grabbed into */ + FRAME_READY, /* Ready to be read */ + FRAME_ERROR, +}; + +/*** + * Register access (for USB request byte) + ***/ +enum { + CAMERAACCESS_SYSTEM = 0, + CAMERAACCESS_VC, + CAMERAACCESS_VP, + CAMERAACCESS_IDATA +}; + +#define CAMERAACCESS_TYPE_BLOCK 0x00 +#define CAMERAACCESS_TYPE_RANDOM 0x04 +#define CAMERAACCESS_TYPE_MASK 0x08 +#define CAMERAACCESS_TYPE_REPEAT 0x0C + +#define TRANSFER_READ 0 +#define TRANSFER_WRITE 1 + +#define DEFAULT_ALT USBIF_ISO_6 +#define DEFAULT_BRIGHTNESS 0x46 +#define DEFAULT_CONTRAST 0x93 +#define DEFAULT_SATURATION 0x7f +#define DEFAULT_TARGET_KB 0x30 + +/* Power state */ +#define HI_POWER_MODE CPIA2_SYSTEM_CONTROL_HIGH_POWER +#define LO_POWER_MODE CPIA2_SYSTEM_CONTROL_LOW_POWER + + +/******** + * Commands + *******/ +enum { + CPIA2_CMD_NONE = 0, + CPIA2_CMD_GET_VERSION, + CPIA2_CMD_GET_PNP_ID, + CPIA2_CMD_GET_ASIC_TYPE, + CPIA2_CMD_GET_SENSOR, + CPIA2_CMD_GET_VP_DEVICE, + CPIA2_CMD_GET_VP_BRIGHTNESS, + CPIA2_CMD_SET_VP_BRIGHTNESS, + CPIA2_CMD_GET_CONTRAST, + CPIA2_CMD_SET_CONTRAST, + CPIA2_CMD_GET_VP_SATURATION, + CPIA2_CMD_SET_VP_SATURATION, + CPIA2_CMD_GET_VP_GPIO_DIRECTION, + CPIA2_CMD_SET_VP_GPIO_DIRECTION, + CPIA2_CMD_GET_VP_GPIO_DATA, + CPIA2_CMD_SET_VP_GPIO_DATA, + CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION, + CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION, + CPIA2_CMD_GET_VC_MP_GPIO_DATA, + CPIA2_CMD_SET_VC_MP_GPIO_DATA, + CPIA2_CMD_ENABLE_PACKET_CTRL, + CPIA2_CMD_GET_FLICKER_MODES, + CPIA2_CMD_SET_FLICKER_MODES, + CPIA2_CMD_RESET_FIFO, /* clear fifo and enable stream block */ + CPIA2_CMD_SET_HI_POWER, + CPIA2_CMD_SET_LOW_POWER, + CPIA2_CMD_CLEAR_V2W_ERR, + CPIA2_CMD_SET_USER_MODE, + CPIA2_CMD_GET_USER_MODE, + CPIA2_CMD_FRAMERATE_REQ, + CPIA2_CMD_SET_COMPRESSION_STATE, + CPIA2_CMD_GET_WAKEUP, + CPIA2_CMD_SET_WAKEUP, + CPIA2_CMD_GET_PW_CONTROL, + CPIA2_CMD_SET_PW_CONTROL, + CPIA2_CMD_GET_SYSTEM_CTRL, + CPIA2_CMD_SET_SYSTEM_CTRL, + CPIA2_CMD_GET_VP_SYSTEM_STATE, + CPIA2_CMD_GET_VP_SYSTEM_CTRL, + CPIA2_CMD_SET_VP_SYSTEM_CTRL, + CPIA2_CMD_GET_VP_EXP_MODES, + CPIA2_CMD_SET_VP_EXP_MODES, + CPIA2_CMD_GET_DEVICE_CONFIG, + CPIA2_CMD_SET_DEVICE_CONFIG, + CPIA2_CMD_SET_SERIAL_ADDR, + CPIA2_CMD_SET_SENSOR_CR1, + CPIA2_CMD_GET_VC_CONTROL, + CPIA2_CMD_SET_VC_CONTROL, + CPIA2_CMD_SET_TARGET_KB, + CPIA2_CMD_SET_DEF_JPEG_OPT, + CPIA2_CMD_REHASH_VP4, + CPIA2_CMD_GET_USER_EFFECTS, + CPIA2_CMD_SET_USER_EFFECTS +}; + +enum user_cmd { + COMMAND_NONE = 0x00000001, + COMMAND_SET_FPS = 0x00000002, + COMMAND_SET_COLOR_PARAMS = 0x00000004, + COMMAND_GET_COLOR_PARAMS = 0x00000008, + COMMAND_SET_FORMAT = 0x00000010, /* size, etc */ + COMMAND_SET_FLICKER = 0x00000020 +}; + +/*** + * Some defines specific to the 676 chip + ***/ +#define CAMACC_CIF 0x01 +#define CAMACC_VGA 0x02 +#define CAMACC_QCIF 0x04 +#define CAMACC_QVGA 0x08 + + +struct cpia2_register { + u8 index; + u8 value; +}; + +struct cpia2_reg_mask { + u8 index; + u8 and_mask; + u8 or_mask; + u8 fill; +}; + +struct cpia2_command { + u32 command; + u8 req_mode; /* (Block or random) | registerBank */ + u8 reg_count; + u8 direction; + u8 start; + union reg_types { + struct cpia2_register registers[32]; + struct cpia2_reg_mask masks[16]; + u8 block_data[64]; + u8 *patch_data; /* points to function defined block */ + } buffer; +}; + +struct camera_params { + struct { + u8 firmware_revision_hi; /* For system register set (bank 0) */ + u8 firmware_revision_lo; + u8 asic_id; /* Video Compressor set (bank 1) */ + u8 asic_rev; + u8 vp_device_hi; /* Video Processor set (bank 2) */ + u8 vp_device_lo; + u8 sensor_flags; + u8 sensor_rev; + } version; + + struct { + u32 device_type; /* enumerated from vendor/product ids. + * Currently, either STV_672 or STV_676 */ + u16 vendor; + u16 product; + u16 device_revision; + } pnp_id; + + struct { + u8 brightness; /* CPIA2_VP_EXPOSURE_TARGET */ + u8 contrast; /* Note: this is CPIA2_VP_YRANGE */ + u8 saturation; /* CPIA2_VP_SATURATION */ + } color_params; + + struct { + u8 cam_register; + u8 flicker_mode_req; /* 1 if flicker on, else never flicker */ + int mains_frequency; + } flicker_control; + + struct { + u8 jpeg_options; + u8 creep_period; + u8 user_squeeze; + u8 inhibit_htables; + } compression; + + struct { + u8 ohsize; /* output image size */ + u8 ovsize; + u8 hcrop; /* cropping start_pos/4 */ + u8 vcrop; + u8 hphase; /* scaling registers */ + u8 vphase; + u8 hispan; + u8 vispan; + u8 hicrop; + u8 vicrop; + u8 hifraction; + u8 vifraction; + } image_size; + + struct { + int width; /* actual window width */ + int height; /* actual window height */ + } roi; + + struct { + u8 video_mode; + u8 frame_rate; + u8 video_size; /* Not a register, just a convenience for cropped sizes */ + u8 gpio_direction; + u8 gpio_data; + u8 system_ctrl; + u8 system_state; + u8 lowlight_boost; /* Bool: 0 = off, 1 = on */ + u8 device_config; + u8 exposure_modes; + u8 user_effects; + } vp_params; + + struct { + u8 pw_control; + u8 wakeup; + u8 vc_control; + u8 vc_mp_direction; + u8 vc_mp_data; + u8 target_kb; + } vc_params; + + struct { + u8 power_mode; + u8 system_ctrl; + u8 stream_mode; /* This is the current alternate for usb drivers */ + u8 allow_corrupt; + } camera_state; +}; + +#define NUM_SBUF 2 + +struct cpia2_sbuf { + char *data; + struct urb *urb; +}; + +struct framebuf { + struct timeval timestamp; + unsigned long seq; + int num; + int length; + int max_length; + volatile enum frame_status status; + u8 *data; + struct framebuf *next; +}; + +struct cpia2_fh { + enum v4l2_priority prio; + u8 mmapped; +}; + +struct camera_data { + /* locks */ + struct semaphore busy_lock; /* guard against SMP multithreading */ + struct v4l2_prio_state prio; + + /* camera status */ + volatile int present; /* Is the camera still present? */ + int open_count; /* # of process that have camera open */ + int first_image_seen; + u8 mains_freq; /* for flicker control */ + enum sensors sensor_type; + u8 flush; + u8 mmapped; + int streaming; /* 0 = no, 1 = yes */ + int xfer_mode; /* XFER_BULK or XFER_ISOC */ + struct camera_params params; /* camera settings */ + + /* v4l */ + int video_size; /* VIDEO_SIZE_ */ + struct video_device *vdev; /* v4l videodev */ + struct video_picture vp; /* v4l camera settings */ + struct video_window vw; /* v4l capture area */ + __u32 pixelformat; /* Format fourcc */ + + /* USB */ + struct usb_device *dev; + unsigned char iface; + unsigned int cur_alt; + unsigned int old_alt; + struct cpia2_sbuf sbuf[NUM_SBUF]; /* Double buffering */ + + wait_queue_head_t wq_stream; + + /* Buffering */ + u32 frame_size; + int num_frames; + unsigned long frame_count; + u8 *frame_buffer; /* frame buffer data */ + struct framebuf *buffers; + struct framebuf * volatile curbuff; + struct framebuf *workbuff; + + /* MJPEG Extension */ + int APPn; /* Number of APP segment to be written, must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ + + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ +}; + +/* v4l */ +int cpia2_register_camera(struct camera_data *cam); +void cpia2_unregister_camera(struct camera_data *cam); + +/* core */ +int cpia2_reset_camera(struct camera_data *cam); +int cpia2_set_low_power(struct camera_data *cam); +void cpia2_dbg_dump_registers(struct camera_data *cam); +int cpia2_match_video_size(int width, int height); +void cpia2_set_camera_state(struct camera_data *cam); +void cpia2_save_camera_state(struct camera_data *cam); +void cpia2_set_color_params(struct camera_data *cam); +void cpia2_set_brightness(struct camera_data *cam, unsigned char value); +void cpia2_set_contrast(struct camera_data *cam, unsigned char value); +void cpia2_set_saturation(struct camera_data *cam, unsigned char value); +int cpia2_set_flicker_mode(struct camera_data *cam, int mode); +void cpia2_set_format(struct camera_data *cam); +int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd); +int cpia2_do_command(struct camera_data *cam, + unsigned int command, + unsigned char direction, unsigned char param); +struct camera_data *cpia2_init_camera_struct(void); +int cpia2_init_camera(struct camera_data *cam); +int cpia2_allocate_buffers(struct camera_data *cam); +void cpia2_free_buffers(struct camera_data *cam); +long cpia2_read(struct camera_data *cam, + char *buf, unsigned long count, int noblock); +unsigned int cpia2_poll(struct camera_data *cam, + struct file *filp, poll_table *wait); +int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma); +void cpia2_set_property_flip(struct camera_data *cam, int prop_val); +void cpia2_set_property_mirror(struct camera_data *cam, int prop_val); +int cpia2_set_target_kb(struct camera_data *cam, unsigned char value); +int cpia2_set_gpio(struct camera_data *cam, unsigned char setting); +int cpia2_set_fps(struct camera_data *cam, int framerate); + +/* usb */ +int cpia2_usb_init(void); +void cpia2_usb_cleanup(void); +int cpia2_usb_transfer_cmd(struct camera_data *cam, void *registers, + u8 request, u8 start, u8 count, u8 direction); +int cpia2_usb_stream_start(struct camera_data *cam, unsigned int alternate); +int cpia2_usb_stream_stop(struct camera_data *cam); +int cpia2_usb_stream_pause(struct camera_data *cam); +int cpia2_usb_stream_resume(struct camera_data *cam); +int cpia2_usb_change_streaming_alternate(struct camera_data *cam, + unsigned int alt); + + +/* ----------------------- debug functions ---------------------- */ +#ifdef _CPIA2_DEBUG_ +#define ALOG(lev, fmt, args...) printk(lev "%s:%d %s(): " fmt, __FILE__, __LINE__, __func__, ## args) +#define LOG(fmt, args...) ALOG(KERN_INFO, fmt, ## args) +#define ERR(fmt, args...) ALOG(KERN_ERR, fmt, ## args) +#define DBG(fmt, args...) ALOG(KERN_DEBUG, fmt, ## args) +#else +#define ALOG(fmt,args...) printk(fmt,##args) +#define LOG(fmt,args...) ALOG(KERN_INFO "cpia2: "fmt,##args) +#define ERR(fmt,args...) ALOG(KERN_ERR "cpia2: "fmt,##args) +#define DBG(fmn,args...) do {} while(0) +#endif +/* No function or lineno, for shorter lines */ +#define KINFO(fmt, args...) printk(KERN_INFO fmt,##args) + +#endif diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c new file mode 100644 index 000000000000..5dfb242d5b8c --- /dev/null +++ b/drivers/media/video/cpia2/cpia2_core.c @@ -0,0 +1,2525 @@ +/**************************************************************************** + * + * Filename: cpia2_core.c + * + * Copyright 2001, STMicrolectronics, Inc. + * Contact: steve.miller@st.com + * + * Description: + * This is a USB driver for CPia2 based video cameras. + * The infrastructure of this driver is based on the cpia usb driver by + * Jochen Scharrlach and Johannes Erdfeldt. + * + * 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. + * + * Stripped of 2.4 stuff ready for main kernel submit by + * Alan Cox + * + ****************************************************************************/ + +#include "cpia2.h" + +#include +#include + +//#define _CPIA2_DEBUG_ + +#include "cpia2patch.h" + +#ifdef _CPIA2_DEBUG_ + +static const char *block_name[] = { + "System", + "VC", + "VP", + "IDATA" +}; +#endif + +static unsigned int debugs_on = 0;//DEBUG_REG; + + +/****************************************************************************** + * + * Forward Declarations + * + *****************************************************************************/ +static int apply_vp_patch(struct camera_data *cam); +static int set_default_user_mode(struct camera_data *cam); +static int set_vw_size(struct camera_data *cam, int size); +static int configure_sensor(struct camera_data *cam, + int reqwidth, int reqheight); +static int config_sensor_410(struct camera_data *cam, + int reqwidth, int reqheight); +static int config_sensor_500(struct camera_data *cam, + int reqwidth, int reqheight); +static int set_all_properties(struct camera_data *cam); +static void get_color_params(struct camera_data *cam); +static void wake_system(struct camera_data *cam); +static void set_lowlight_boost(struct camera_data *cam); +static void reset_camera_struct(struct camera_data *cam); +static int cpia2_set_high_power(struct camera_data *cam); + +/* Here we want the physical address of the memory. + * This is used when initializing the contents of the + * area and marking the pages as reserved. + */ +static inline unsigned long kvirt_to_pa(unsigned long adr) +{ + unsigned long kva, ret; + + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ + ret = __pa(kva); + return ret; +} + +static void *rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr; + + /* Round it off to PAGE_SIZE */ + size = PAGE_ALIGN(size); + + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + + while ((long)size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + return mem; +} + +static void rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + size = PAGE_ALIGN(size); + + adr = (unsigned long) mem; + while ((long)size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + +/****************************************************************************** + * + * cpia2_do_command + * + * Send an arbitrary command to the camera. For commands that read from + * the camera, copy the buffers into the proper param structures. + *****************************************************************************/ +int cpia2_do_command(struct camera_data *cam, + u32 command, u8 direction, u8 param) +{ + int retval = 0; + struct cpia2_command cmd; + unsigned int device = cam->params.pnp_id.device_type; + + cmd.command = command; + cmd.reg_count = 2; /* default */ + cmd.direction = direction; + + /*** + * Set up the command. + ***/ + switch (command) { + case CPIA2_CMD_GET_VERSION: + cmd.req_mode = + CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; + cmd.start = CPIA2_SYSTEM_DEVICE_HI; + break; + case CPIA2_CMD_GET_PNP_ID: + cmd.req_mode = + CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; + cmd.reg_count = 8; + cmd.start = CPIA2_SYSTEM_DESCRIP_VID_HI; + break; + case CPIA2_CMD_GET_ASIC_TYPE: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; + cmd.start = CPIA2_VC_ASIC_ID; + break; + case CPIA2_CMD_GET_SENSOR: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.start = CPIA2_VP_SENSOR_FLAGS; + break; + case CPIA2_CMD_GET_VP_DEVICE: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.start = CPIA2_VP_DEVICEH; + break; + case CPIA2_CMD_SET_VP_BRIGHTNESS: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_VP_BRIGHTNESS: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + if (device == DEVICE_STV_672) + cmd.start = CPIA2_VP4_EXPOSURE_TARGET; + else + cmd.start = CPIA2_VP5_EXPOSURE_TARGET; + break; + case CPIA2_CMD_SET_CONTRAST: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_CONTRAST: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + cmd.start = CPIA2_VP_YRANGE; + break; + case CPIA2_CMD_SET_VP_SATURATION: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_VP_SATURATION: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + if (device == DEVICE_STV_672) + cmd.start = CPIA2_VP_SATURATION; + else + cmd.start = CPIA2_VP5_MCUVSATURATION; + break; + case CPIA2_CMD_SET_VP_GPIO_DATA: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_VP_GPIO_DATA: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + cmd.start = CPIA2_VP_GPIO_DATA; + break; + case CPIA2_CMD_SET_VP_GPIO_DIRECTION: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_VP_GPIO_DIRECTION: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + cmd.start = CPIA2_VP_GPIO_DIRECTION; + break; + case CPIA2_CMD_SET_VC_MP_GPIO_DATA: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_VC_MP_GPIO_DATA: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; + cmd.reg_count = 1; + cmd.start = CPIA2_VC_MP_DATA; + break; + case CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; + cmd.reg_count = 1; + cmd.start = CPIA2_VC_MP_DIR; + break; + case CPIA2_CMD_ENABLE_PACKET_CTRL: + cmd.req_mode = + CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; + cmd.start = CPIA2_SYSTEM_INT_PACKET_CTRL; + cmd.reg_count = 1; + cmd.buffer.block_data[0] = param; + break; + case CPIA2_CMD_SET_FLICKER_MODES: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_FLICKER_MODES: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + cmd.start = CPIA2_VP_FLICKER_MODES; + break; + case CPIA2_CMD_RESET_FIFO: /* clear fifo and enable stream block */ + cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; + cmd.reg_count = 2; + cmd.start = 0; + cmd.buffer.registers[0].index = CPIA2_VC_ST_CTRL; + cmd.buffer.registers[0].value = CPIA2_VC_ST_CTRL_SRC_VC | + CPIA2_VC_ST_CTRL_DST_USB | CPIA2_VC_ST_CTRL_EOF_DETECT; + cmd.buffer.registers[1].index = CPIA2_VC_ST_CTRL; + cmd.buffer.registers[1].value = CPIA2_VC_ST_CTRL_SRC_VC | + CPIA2_VC_ST_CTRL_DST_USB | + CPIA2_VC_ST_CTRL_EOF_DETECT | + CPIA2_VC_ST_CTRL_FIFO_ENABLE; + break; + case CPIA2_CMD_SET_HI_POWER: + cmd.req_mode = + CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_SYSTEM; + cmd.reg_count = 2; + cmd.buffer.registers[0].index = + CPIA2_SYSTEM_SYSTEM_CONTROL; + cmd.buffer.registers[1].index = + CPIA2_SYSTEM_SYSTEM_CONTROL; + cmd.buffer.registers[0].value = CPIA2_SYSTEM_CONTROL_CLEAR_ERR; + cmd.buffer.registers[1].value = + CPIA2_SYSTEM_CONTROL_HIGH_POWER; + break; + case CPIA2_CMD_SET_LOW_POWER: + cmd.req_mode = + CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; + cmd.reg_count = 1; + cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL; + cmd.buffer.block_data[0] = 0; + break; + case CPIA2_CMD_CLEAR_V2W_ERR: + cmd.req_mode = + CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; + cmd.reg_count = 1; + cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL; + cmd.buffer.block_data[0] = CPIA2_SYSTEM_CONTROL_CLEAR_ERR; + break; + case CPIA2_CMD_SET_USER_MODE: /* Then fall through */ + cmd.buffer.block_data[0] = param; + case CPIA2_CMD_GET_USER_MODE: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + if (device == DEVICE_STV_672) + cmd.start = CPIA2_VP4_USER_MODE; + else + cmd.start = CPIA2_VP5_USER_MODE; + break; + case CPIA2_CMD_FRAMERATE_REQ: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + if (device == DEVICE_STV_672) + cmd.start = CPIA2_VP4_FRAMERATE_REQUEST; + else + cmd.start = CPIA2_VP5_FRAMERATE_REQUEST; + cmd.buffer.block_data[0] = param; + break; + case CPIA2_CMD_SET_WAKEUP: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_WAKEUP: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; + cmd.reg_count = 1; + cmd.start = CPIA2_VC_WAKEUP; + break; + case CPIA2_CMD_SET_PW_CONTROL: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_PW_CONTROL: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; + cmd.reg_count = 1; + cmd.start = CPIA2_VC_PW_CTRL; + break; + case CPIA2_CMD_GET_VP_SYSTEM_STATE: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + cmd.start = CPIA2_VP_SYSTEMSTATE; + break; + case CPIA2_CMD_SET_SYSTEM_CTRL: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_SYSTEM_CTRL: + cmd.req_mode = + CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; + cmd.reg_count = 1; + cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL; + break; + case CPIA2_CMD_SET_VP_SYSTEM_CTRL: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_VP_SYSTEM_CTRL: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + cmd.start = CPIA2_VP_SYSTEMCTRL; + break; + case CPIA2_CMD_SET_VP_EXP_MODES: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_VP_EXP_MODES: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + cmd.start = CPIA2_VP_EXPOSURE_MODES; + break; + case CPIA2_CMD_SET_DEVICE_CONFIG: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_DEVICE_CONFIG: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + cmd.start = CPIA2_VP_DEVICE_CONFIG; + break; + case CPIA2_CMD_SET_SERIAL_ADDR: + cmd.buffer.block_data[0] = param; + cmd.req_mode = + CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; + cmd.reg_count = 1; + cmd.start = CPIA2_SYSTEM_VP_SERIAL_ADDR; + break; + case CPIA2_CMD_SET_SENSOR_CR1: + cmd.buffer.block_data[0] = param; + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + cmd.start = CPIA2_SENSOR_CR1; + break; + case CPIA2_CMD_SET_VC_CONTROL: + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_VC_CONTROL: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; + cmd.reg_count = 1; + cmd.start = CPIA2_VC_VC_CTRL; + break; + case CPIA2_CMD_SET_TARGET_KB: + cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; + cmd.reg_count = 1; + cmd.buffer.registers[0].index = CPIA2_VC_VC_TARGET_KB; + cmd.buffer.registers[0].value = param; + break; + case CPIA2_CMD_SET_DEF_JPEG_OPT: + cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; + cmd.reg_count = 4; + cmd.buffer.registers[0].index = CPIA2_VC_VC_JPEG_OPT; + cmd.buffer.registers[0].value = + CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE; + cmd.buffer.registers[1].index = CPIA2_VC_VC_USER_SQUEEZE; + cmd.buffer.registers[1].value = 20; + cmd.buffer.registers[2].index = CPIA2_VC_VC_CREEP_PERIOD; + cmd.buffer.registers[2].value = 2; + cmd.buffer.registers[3].index = CPIA2_VC_VC_JPEG_OPT; + cmd.buffer.registers[3].value = CPIA2_VC_VC_JPEG_OPT_DEFAULT; + break; + case CPIA2_CMD_REHASH_VP4: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + cmd.start = CPIA2_VP_REHASH_VALUES; + cmd.buffer.block_data[0] = param; + break; + case CPIA2_CMD_SET_USER_EFFECTS: /* Note: Be careful with this as + this register can also affect + flicker modes */ + cmd.buffer.block_data[0] = param; /* Then fall through */ + case CPIA2_CMD_GET_USER_EFFECTS: + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 1; + if (device == DEVICE_STV_672) + cmd.start = CPIA2_VP4_USER_EFFECTS; + else + cmd.start = CPIA2_VP5_USER_EFFECTS; + break; + default: + LOG("DoCommand received invalid command\n"); + return -EINVAL; + } + + retval = cpia2_send_command(cam, &cmd); + if (retval) { + return retval; + } + + /*** + * Now copy any results from a read into the appropriate param struct. + ***/ + switch (command) { + case CPIA2_CMD_GET_VERSION: + cam->params.version.firmware_revision_hi = + cmd.buffer.block_data[0]; + cam->params.version.firmware_revision_lo = + cmd.buffer.block_data[1]; + break; + case CPIA2_CMD_GET_PNP_ID: + cam->params.pnp_id.vendor = (cmd.buffer.block_data[0] << 8) | + cmd.buffer.block_data[1]; + cam->params.pnp_id.product = (cmd.buffer.block_data[2] << 8) | + cmd.buffer.block_data[3]; + cam->params.pnp_id.device_revision = + (cmd.buffer.block_data[4] << 8) | + cmd.buffer.block_data[5]; + if (cam->params.pnp_id.vendor == 0x553) { + if (cam->params.pnp_id.product == 0x100) { + cam->params.pnp_id.device_type = DEVICE_STV_672; + } else if (cam->params.pnp_id.product == 0x140 || + cam->params.pnp_id.product == 0x151) { + cam->params.pnp_id.device_type = DEVICE_STV_676; + } + } + break; + case CPIA2_CMD_GET_ASIC_TYPE: + cam->params.version.asic_id = cmd.buffer.block_data[0]; + cam->params.version.asic_rev = cmd.buffer.block_data[1]; + break; + case CPIA2_CMD_GET_SENSOR: + cam->params.version.sensor_flags = cmd.buffer.block_data[0]; + cam->params.version.sensor_rev = cmd.buffer.block_data[1]; + break; + case CPIA2_CMD_GET_VP_DEVICE: + cam->params.version.vp_device_hi = cmd.buffer.block_data[0]; + cam->params.version.vp_device_lo = cmd.buffer.block_data[1]; + break; + case CPIA2_CMD_GET_VP_BRIGHTNESS: + cam->params.color_params.brightness = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_CONTRAST: + cam->params.color_params.contrast = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_VP_SATURATION: + cam->params.color_params.saturation = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_VP_GPIO_DATA: + cam->params.vp_params.gpio_data = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_VP_GPIO_DIRECTION: + cam->params.vp_params.gpio_direction = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION: + cam->params.vc_params.vc_mp_direction =cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_VC_MP_GPIO_DATA: + cam->params.vc_params.vc_mp_data = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_FLICKER_MODES: + cam->params.flicker_control.cam_register = + cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_WAKEUP: + cam->params.vc_params.wakeup = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_PW_CONTROL: + cam->params.vc_params.pw_control = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_SYSTEM_CTRL: + cam->params.camera_state.system_ctrl = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_VP_SYSTEM_STATE: + cam->params.vp_params.system_state = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_VP_SYSTEM_CTRL: + cam->params.vp_params.system_ctrl = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_VP_EXP_MODES: + cam->params.vp_params.exposure_modes = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_DEVICE_CONFIG: + cam->params.vp_params.device_config = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_VC_CONTROL: + cam->params.vc_params.vc_control = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_USER_MODE: + cam->params.vp_params.video_mode = cmd.buffer.block_data[0]; + break; + case CPIA2_CMD_GET_USER_EFFECTS: + cam->params.vp_params.user_effects = cmd.buffer.block_data[0]; + break; + default: + break; + } + return retval; +} + +/****************************************************************************** + * + * cpia2_send_command + * + *****************************************************************************/ +int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd) +{ + u8 count; + u8 start; + u8 block_index; + u8 *buffer; + int retval; + const char* dir; + + if (cmd->direction == TRANSFER_WRITE) { + dir = "Write"; + } else { + dir = "Read"; + } + + block_index = cmd->req_mode & 0x03; + + switch (cmd->req_mode & 0x0c) { + case CAMERAACCESS_TYPE_RANDOM: + count = cmd->reg_count * sizeof(struct cpia2_register); + start = 0; + buffer = (u8 *) & cmd->buffer; + if (debugs_on & DEBUG_REG) + DBG("%s Random: Register block %s\n", dir, + block_name[block_index]); + break; + case CAMERAACCESS_TYPE_BLOCK: + count = cmd->reg_count; + start = cmd->start; + buffer = cmd->buffer.block_data; + if (debugs_on & DEBUG_REG) + DBG("%s Block: Register block %s\n", dir, + block_name[block_index]); + break; + case CAMERAACCESS_TYPE_MASK: + count = cmd->reg_count * sizeof(struct cpia2_reg_mask); + start = 0; + buffer = (u8 *) & cmd->buffer; + if (debugs_on & DEBUG_REG) + DBG("%s Mask: Register block %s\n", dir, + block_name[block_index]); + break; + case CAMERAACCESS_TYPE_REPEAT: /* For patch blocks only */ + count = cmd->reg_count; + start = cmd->start; + buffer = cmd->buffer.block_data; + if (debugs_on & DEBUG_REG) + DBG("%s Repeat: Register block %s\n", dir, + block_name[block_index]); + break; + default: + LOG("%s: invalid request mode\n",__FUNCTION__); + return -EINVAL; + } + + retval = cpia2_usb_transfer_cmd(cam, + buffer, + cmd->req_mode, + start, count, cmd->direction); +#ifdef _CPIA2_DEBUG_ + if (debugs_on & DEBUG_REG) { + int i; + for (i = 0; i < cmd->reg_count; i++) { + if((cmd->req_mode & 0x0c) == CAMERAACCESS_TYPE_BLOCK) + KINFO("%s Block: [0x%02X] = 0x%02X\n", + dir, start + i, buffer[i]); + if((cmd->req_mode & 0x0c) == CAMERAACCESS_TYPE_RANDOM) + KINFO("%s Random: [0x%02X] = 0x%02X\n", + dir, cmd->buffer.registers[i].index, + cmd->buffer.registers[i].value); + } + } +#endif + + return retval; +}; + +/************* + * Functions to implement camera functionality + *************/ +/****************************************************************************** + * + * cpia2_get_version_info + * + *****************************************************************************/ +static void cpia2_get_version_info(struct camera_data *cam) +{ + cpia2_do_command(cam, CPIA2_CMD_GET_VERSION, TRANSFER_READ, 0); + cpia2_do_command(cam, CPIA2_CMD_GET_PNP_ID, TRANSFER_READ, 0); + cpia2_do_command(cam, CPIA2_CMD_GET_ASIC_TYPE, TRANSFER_READ, 0); + cpia2_do_command(cam, CPIA2_CMD_GET_SENSOR, TRANSFER_READ, 0); + cpia2_do_command(cam, CPIA2_CMD_GET_VP_DEVICE, TRANSFER_READ, 0); +} + +/****************************************************************************** + * + * cpia2_reset_camera + * + * Called at least during the open process, sets up initial params. + *****************************************************************************/ +int cpia2_reset_camera(struct camera_data *cam) +{ + u8 tmp_reg; + int retval = 0; + int i; + struct cpia2_command cmd; + + /*** + * VC setup + ***/ + retval = configure_sensor(cam, + cam->params.roi.width, + cam->params.roi.height); + if (retval < 0) { + ERR("Couldn't configure sensor, error=%d\n", retval); + return retval; + } + + /* Clear FIFO and route/enable stream block */ + cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; + cmd.direction = TRANSFER_WRITE; + cmd.reg_count = 2; + cmd.buffer.registers[0].index = CPIA2_VC_ST_CTRL; + cmd.buffer.registers[0].value = CPIA2_VC_ST_CTRL_SRC_VC | + CPIA2_VC_ST_CTRL_DST_USB | CPIA2_VC_ST_CTRL_EOF_DETECT; + cmd.buffer.registers[1].index = CPIA2_VC_ST_CTRL; + cmd.buffer.registers[1].value = CPIA2_VC_ST_CTRL_SRC_VC | + CPIA2_VC_ST_CTRL_DST_USB | + CPIA2_VC_ST_CTRL_EOF_DETECT | CPIA2_VC_ST_CTRL_FIFO_ENABLE; + + cpia2_send_command(cam, &cmd); + + cpia2_set_high_power(cam); + + if (cam->params.pnp_id.device_type == DEVICE_STV_672) { + /* Enable button notification */ + cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_SYSTEM; + cmd.buffer.registers[0].index = CPIA2_SYSTEM_INT_PACKET_CTRL; + cmd.buffer.registers[0].value = + CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_SW_XX; + cmd.reg_count = 1; + cpia2_send_command(cam, &cmd); + } + + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(100 * HZ / 1000); /* wait for 100 msecs */ + + if (cam->params.pnp_id.device_type == DEVICE_STV_672) + retval = apply_vp_patch(cam); + + /* wait for vp to go to sleep */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(100 * HZ / 1000); /* wait for 100 msecs */ + + /*** + * If this is a 676, apply VP5 fixes before we start streaming + ***/ + if (cam->params.pnp_id.device_type == DEVICE_STV_676) { + cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP; + + /* The following writes improve the picture */ + cmd.buffer.registers[0].index = CPIA2_VP5_MYBLACK_LEVEL; + cmd.buffer.registers[0].value = 0; /* reduce from the default + * rec 601 pedestal of 16 */ + cmd.buffer.registers[1].index = CPIA2_VP5_MCYRANGE; + cmd.buffer.registers[1].value = 0x92; /* increase from 100% to + * (256/256 - 31) to fill + * available range */ + cmd.buffer.registers[2].index = CPIA2_VP5_MYCEILING; + cmd.buffer.registers[2].value = 0xFF; /* Increase from the + * default rec 601 ceiling + * of 240 */ + cmd.buffer.registers[3].index = CPIA2_VP5_MCUVSATURATION; + cmd.buffer.registers[3].value = 0xFF; /* Increase from the rec + * 601 100% level (128) + * to 145-192 */ + cmd.buffer.registers[4].index = CPIA2_VP5_ANTIFLKRSETUP; + cmd.buffer.registers[4].value = 0x80; /* Inhibit the + * anti-flicker */ + + /* The following 4 writes are a fix to allow QVGA to work at 30 fps */ + cmd.buffer.registers[5].index = CPIA2_VP_RAM_ADDR_H; + cmd.buffer.registers[5].value = 0x01; + cmd.buffer.registers[6].index = CPIA2_VP_RAM_ADDR_L; + cmd.buffer.registers[6].value = 0xE3; + cmd.buffer.registers[7].index = CPIA2_VP_RAM_DATA; + cmd.buffer.registers[7].value = 0x02; + cmd.buffer.registers[8].index = CPIA2_VP_RAM_DATA; + cmd.buffer.registers[8].value = 0xFC; + + cmd.direction = TRANSFER_WRITE; + cmd.reg_count = 9; + + cpia2_send_command(cam, &cmd); + } + + /* Activate all settings and start the data stream */ + /* Set user mode */ + set_default_user_mode(cam); + + /* Give VP time to wake up */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(100 * HZ / 1000); /* wait for 100 msecs */ + + set_all_properties(cam); + + cpia2_do_command(cam, CPIA2_CMD_GET_USER_MODE, TRANSFER_READ, 0); + DBG("After SetAllProperties(cam), user mode is 0x%0X\n", + cam->params.vp_params.video_mode); + + /*** + * Set audio regulator off. This and the code to set the compresison + * state are too complex to form a CPIA2_CMD_, and seem to be somewhat + * intertwined. This stuff came straight from the windows driver. + ***/ + /* Turn AutoExposure off in VP and enable the serial bridge to the sensor */ + cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_CTRL, TRANSFER_READ, 0); + tmp_reg = cam->params.vp_params.system_ctrl; + cmd.buffer.registers[0].value = tmp_reg & + (tmp_reg & (CPIA2_VP_SYSTEMCTRL_HK_CONTROL ^ 0xFF)); + + cpia2_do_command(cam, CPIA2_CMD_GET_DEVICE_CONFIG, TRANSFER_READ, 0); + cmd.buffer.registers[1].value = cam->params.vp_params.device_config | + CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE; + cmd.buffer.registers[0].index = CPIA2_VP_SYSTEMCTRL; + cmd.buffer.registers[1].index = CPIA2_VP_DEVICE_CONFIG; + cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP; + cmd.reg_count = 2; + cmd.direction = TRANSFER_WRITE; + cmd.start = 0; + cpia2_send_command(cam, &cmd); + + /* Set the correct I2C address in the CPiA-2 system register */ + cpia2_do_command(cam, + CPIA2_CMD_SET_SERIAL_ADDR, + TRANSFER_WRITE, + CPIA2_SYSTEM_VP_SERIAL_ADDR_SENSOR); + + /* Now have sensor access - set bit to turn the audio regulator off */ + cpia2_do_command(cam, + CPIA2_CMD_SET_SENSOR_CR1, + TRANSFER_WRITE, CPIA2_SENSOR_CR1_DOWN_AUDIO_REGULATOR); + + /* Set the correct I2C address in the CPiA-2 system register */ + if (cam->params.pnp_id.device_type == DEVICE_STV_672) + cpia2_do_command(cam, + CPIA2_CMD_SET_SERIAL_ADDR, + TRANSFER_WRITE, + CPIA2_SYSTEM_VP_SERIAL_ADDR_VP); // 0x88 + else + cpia2_do_command(cam, + CPIA2_CMD_SET_SERIAL_ADDR, + TRANSFER_WRITE, + CPIA2_SYSTEM_VP_SERIAL_ADDR_676_VP); // 0x8a + + /* increase signal drive strength */ + if (cam->params.pnp_id.device_type == DEVICE_STV_676) + cpia2_do_command(cam, + CPIA2_CMD_SET_VP_EXP_MODES, + TRANSFER_WRITE, + CPIA2_VP_EXPOSURE_MODES_COMPILE_EXP); + + /* Start autoexposure */ + cpia2_do_command(cam, CPIA2_CMD_GET_DEVICE_CONFIG, TRANSFER_READ, 0); + cmd.buffer.registers[0].value = cam->params.vp_params.device_config & + (CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE ^ 0xFF); + + cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_CTRL, TRANSFER_READ, 0); + cmd.buffer.registers[1].value = + cam->params.vp_params.system_ctrl | CPIA2_VP_SYSTEMCTRL_HK_CONTROL; + + cmd.buffer.registers[0].index = CPIA2_VP_DEVICE_CONFIG; + cmd.buffer.registers[1].index = CPIA2_VP_SYSTEMCTRL; + cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP; + cmd.reg_count = 2; + cmd.direction = TRANSFER_WRITE; + + cpia2_send_command(cam, &cmd); + + /* Set compression state */ + cpia2_do_command(cam, CPIA2_CMD_GET_VC_CONTROL, TRANSFER_READ, 0); + if (cam->params.compression.inhibit_htables) { + tmp_reg = cam->params.vc_params.vc_control | + CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES; + } else { + tmp_reg = cam->params.vc_params.vc_control & + ~CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES; + } + cpia2_do_command(cam, CPIA2_CMD_SET_VC_CONTROL, TRANSFER_WRITE,tmp_reg); + + /* Set target size (kb) on vc */ + cpia2_do_command(cam, CPIA2_CMD_SET_TARGET_KB, + TRANSFER_WRITE, cam->params.vc_params.target_kb); + + /* Wiggle VC Reset */ + /*** + * First read and wait a bit. + ***/ + for (i = 0; i < 50; i++) { + cpia2_do_command(cam, CPIA2_CMD_GET_PW_CONTROL, + TRANSFER_READ, 0); + } + + tmp_reg = cam->params.vc_params.pw_control; + tmp_reg &= ~CPIA2_VC_PW_CTRL_VC_RESET_N; + + cpia2_do_command(cam, CPIA2_CMD_SET_PW_CONTROL, TRANSFER_WRITE,tmp_reg); + + tmp_reg |= CPIA2_VC_PW_CTRL_VC_RESET_N; + cpia2_do_command(cam, CPIA2_CMD_SET_PW_CONTROL, TRANSFER_WRITE,tmp_reg); + + cpia2_do_command(cam, CPIA2_CMD_SET_DEF_JPEG_OPT, TRANSFER_WRITE, 0); + + cpia2_do_command(cam, CPIA2_CMD_GET_USER_MODE, TRANSFER_READ, 0); + DBG("After VC RESET, user mode is 0x%0X\n", + cam->params.vp_params.video_mode); + + return retval; +} + +/****************************************************************************** + * + * cpia2_set_high_power + * + *****************************************************************************/ +static int cpia2_set_high_power(struct camera_data *cam) +{ + int i; + for (i = 0; i <= 50; i++) { + /* Read system status */ + cpia2_do_command(cam,CPIA2_CMD_GET_SYSTEM_CTRL,TRANSFER_READ,0); + + /* If there is an error, clear it */ + if(cam->params.camera_state.system_ctrl & + CPIA2_SYSTEM_CONTROL_V2W_ERR) + cpia2_do_command(cam, CPIA2_CMD_CLEAR_V2W_ERR, + TRANSFER_WRITE, 0); + + /* Try to set high power mode */ + cpia2_do_command(cam, CPIA2_CMD_SET_SYSTEM_CTRL, + TRANSFER_WRITE, 1); + + /* Try to read something in VP to check if everything is awake */ + cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_STATE, + TRANSFER_READ, 0); + if (cam->params.vp_params.system_state & + CPIA2_VP_SYSTEMSTATE_HK_ALIVE) { + break; + } else if (i == 50) { + cam->params.camera_state.power_mode = LO_POWER_MODE; + ERR("Camera did not wake up\n"); + return -EIO; + } + } + + DBG("System now in high power state\n"); + cam->params.camera_state.power_mode = HI_POWER_MODE; + return 0; +} + +/****************************************************************************** + * + * cpia2_set_low_power + * + *****************************************************************************/ +int cpia2_set_low_power(struct camera_data *cam) +{ + cam->params.camera_state.power_mode = LO_POWER_MODE; + cpia2_do_command(cam, CPIA2_CMD_SET_SYSTEM_CTRL, TRANSFER_WRITE, 0); + return 0; +} + +/****************************************************************************** + * + * apply_vp_patch + * + *****************************************************************************/ +static int apply_vp_patch(struct camera_data *cam) +{ + int i, j; + struct cpia2_command cmd; + + cmd.req_mode = CAMERAACCESS_TYPE_REPEAT | CAMERAACCESS_VP; + cmd.direction = TRANSFER_WRITE; + + for (i = 0; i < PATCH_DATA_SIZE; i++) { + for (j = 0; j < patch_data[i].count; j++) { + cmd.buffer.block_data[j] = patch_data[i].data[j]; + } + + cmd.start = patch_data[i].reg; + cmd.reg_count = patch_data[i].count; + cpia2_send_command(cam, &cmd); + } + + return 0; +} + +/****************************************************************************** + * + * set_default_user_mode + * + *****************************************************************************/ +static int set_default_user_mode(struct camera_data *cam) +{ + unsigned char user_mode; + unsigned char frame_rate; + int width = cam->params.roi.width; + int height = cam->params.roi.height; + + switch (cam->params.version.sensor_flags) { + case CPIA2_VP_SENSOR_FLAGS_404: + case CPIA2_VP_SENSOR_FLAGS_407: + case CPIA2_VP_SENSOR_FLAGS_409: + case CPIA2_VP_SENSOR_FLAGS_410: + if ((width > STV_IMAGE_QCIF_COLS) + || (height > STV_IMAGE_QCIF_ROWS)) { + user_mode = CPIA2_VP_USER_MODE_CIF; + } else { + user_mode = CPIA2_VP_USER_MODE_QCIFDS; + } + frame_rate = CPIA2_VP_FRAMERATE_30; + break; + case CPIA2_VP_SENSOR_FLAGS_500: + if ((width > STV_IMAGE_CIF_COLS) + || (height > STV_IMAGE_CIF_ROWS)) { + user_mode = CPIA2_VP_USER_MODE_VGA; + } else { + user_mode = CPIA2_VP_USER_MODE_QVGADS; + } + if (cam->params.pnp_id.device_type == DEVICE_STV_672) + frame_rate = CPIA2_VP_FRAMERATE_15; + else + frame_rate = CPIA2_VP_FRAMERATE_30; + break; + default: + LOG("%s: Invalid sensor flag value 0x%0X\n",__FUNCTION__, + cam->params.version.sensor_flags); + return -EINVAL; + } + + DBG("Sensor flag = 0x%0x, user mode = 0x%0x, frame rate = 0x%X\n", + cam->params.version.sensor_flags, user_mode, frame_rate); + cpia2_do_command(cam, CPIA2_CMD_SET_USER_MODE, TRANSFER_WRITE, + user_mode); + if(cam->params.vp_params.frame_rate > 0 && + frame_rate > cam->params.vp_params.frame_rate) + frame_rate = cam->params.vp_params.frame_rate; + + cpia2_set_fps(cam, frame_rate); + +// if (cam->params.pnp_id.device_type == DEVICE_STV_676) +// cpia2_do_command(cam, +// CPIA2_CMD_SET_VP_SYSTEM_CTRL, +// TRANSFER_WRITE, +// CPIA2_VP_SYSTEMCTRL_HK_CONTROL | +// CPIA2_VP_SYSTEMCTRL_POWER_CONTROL); + + return 0; +} + +/****************************************************************************** + * + * cpia2_match_video_size + * + * return the best match, where 'best' is as always + * the largest that is not bigger than what is requested. + *****************************************************************************/ +int cpia2_match_video_size(int width, int height) +{ + if (width >= STV_IMAGE_VGA_COLS && height >= STV_IMAGE_VGA_ROWS) + return VIDEOSIZE_VGA; + + if (width >= STV_IMAGE_CIF_COLS && height >= STV_IMAGE_CIF_ROWS) + return VIDEOSIZE_CIF; + + if (width >= STV_IMAGE_QVGA_COLS && height >= STV_IMAGE_QVGA_ROWS) + return VIDEOSIZE_QVGA; + + if (width >= 288 && height >= 216) + return VIDEOSIZE_288_216; + + if (width >= 256 && height >= 192) + return VIDEOSIZE_256_192; + + if (width >= 224 && height >= 168) + return VIDEOSIZE_224_168; + + if (width >= 192 && height >= 144) + return VIDEOSIZE_192_144; + + if (width >= STV_IMAGE_QCIF_COLS && height >= STV_IMAGE_QCIF_ROWS) + return VIDEOSIZE_QCIF; + + return -1; +} + +/****************************************************************************** + * + * SetVideoSize + * + *****************************************************************************/ +static int set_vw_size(struct camera_data *cam, int size) +{ + int retval = 0; + + cam->params.vp_params.video_size = size; + + switch (size) { + case VIDEOSIZE_VGA: + DBG("Setting size to VGA\n"); + cam->params.roi.width = STV_IMAGE_VGA_COLS; + cam->params.roi.height = STV_IMAGE_VGA_ROWS; + cam->vw.width = STV_IMAGE_VGA_COLS; + cam->vw.height = STV_IMAGE_VGA_ROWS; + break; + case VIDEOSIZE_CIF: + DBG("Setting size to CIF\n"); + cam->params.roi.width = STV_IMAGE_CIF_COLS; + cam->params.roi.height = STV_IMAGE_CIF_ROWS; + cam->vw.width = STV_IMAGE_CIF_COLS; + cam->vw.height = STV_IMAGE_CIF_ROWS; + break; + case VIDEOSIZE_QVGA: + DBG("Setting size to QVGA\n"); + cam->params.roi.width = STV_IMAGE_QVGA_COLS; + cam->params.roi.height = STV_IMAGE_QVGA_ROWS; + cam->vw.width = STV_IMAGE_QVGA_COLS; + cam->vw.height = STV_IMAGE_QVGA_ROWS; + break; + case VIDEOSIZE_288_216: + cam->params.roi.width = 288; + cam->params.roi.height = 216; + cam->vw.width = 288; + cam->vw.height = 216; + break; + case VIDEOSIZE_256_192: + cam->vw.width = 256; + cam->vw.height = 192; + cam->params.roi.width = 256; + cam->params.roi.height = 192; + break; + case VIDEOSIZE_224_168: + cam->vw.width = 224; + cam->vw.height = 168; + cam->params.roi.width = 224; + cam->params.roi.height = 168; + break; + case VIDEOSIZE_192_144: + cam->vw.width = 192; + cam->vw.height = 144; + cam->params.roi.width = 192; + cam->params.roi.height = 144; + break; + case VIDEOSIZE_QCIF: + DBG("Setting size to QCIF\n"); + cam->params.roi.width = STV_IMAGE_QCIF_COLS; + cam->params.roi.height = STV_IMAGE_QCIF_ROWS; + cam->vw.width = STV_IMAGE_QCIF_COLS; + cam->vw.height = STV_IMAGE_QCIF_ROWS; + break; + default: + retval = -EINVAL; + } + return retval; +} + +/****************************************************************************** + * + * configure_sensor + * + *****************************************************************************/ +static int configure_sensor(struct camera_data *cam, + int req_width, int req_height) +{ + int retval; + + switch (cam->params.version.sensor_flags) { + case CPIA2_VP_SENSOR_FLAGS_404: + case CPIA2_VP_SENSOR_FLAGS_407: + case CPIA2_VP_SENSOR_FLAGS_409: + case CPIA2_VP_SENSOR_FLAGS_410: + retval = config_sensor_410(cam, req_width, req_height); + break; + case CPIA2_VP_SENSOR_FLAGS_500: + retval = config_sensor_500(cam, req_width, req_height); + break; + default: + return -EINVAL; + } + + return retval; +} + +/****************************************************************************** + * + * config_sensor_410 + * + *****************************************************************************/ +static int config_sensor_410(struct camera_data *cam, + int req_width, int req_height) +{ + struct cpia2_command cmd; + int i = 0; + int image_size; + int image_type; + int width = req_width; + int height = req_height; + + /*** + * Make sure size doesn't exceed CIF. + ***/ + if (width > STV_IMAGE_CIF_COLS) + width = STV_IMAGE_CIF_COLS; + if (height > STV_IMAGE_CIF_ROWS) + height = STV_IMAGE_CIF_ROWS; + + image_size = cpia2_match_video_size(width, height); + + DBG("Config 410: width = %d, height = %d\n", width, height); + DBG("Image size returned is %d\n", image_size); + if (image_size >= 0) { + set_vw_size(cam, image_size); + width = cam->params.roi.width; + height = cam->params.roi.height; + + DBG("After set_vw_size(), width = %d, height = %d\n", + width, height); + if (width <= 176 && height <= 144) { + DBG("image type = VIDEOSIZE_QCIF\n"); + image_type = VIDEOSIZE_QCIF; + } + else if (width <= 320 && height <= 240) { + DBG("image type = VIDEOSIZE_QVGA\n"); + image_type = VIDEOSIZE_QVGA; + } + else { + DBG("image type = VIDEOSIZE_CIF\n"); + image_type = VIDEOSIZE_CIF; + } + } else { + ERR("ConfigSensor410 failed\n"); + return -EINVAL; + } + + cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; + cmd.direction = TRANSFER_WRITE; + + /* VC Format */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_FORMAT; + if (image_type == VIDEOSIZE_CIF) { + cmd.buffer.registers[i++].value = + (u8) (CPIA2_VC_VC_FORMAT_UFIRST | + CPIA2_VC_VC_FORMAT_SHORTLINE); + } else { + cmd.buffer.registers[i++].value = + (u8) CPIA2_VC_VC_FORMAT_UFIRST; + } + + /* VC Clocks */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_CLOCKS; + if (image_type == VIDEOSIZE_QCIF) { + if (cam->params.pnp_id.device_type == DEVICE_STV_672) { + cmd.buffer.registers[i++].value= + (u8)(CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 | + CPIA2_VC_VC_672_CLOCKS_SCALING | + CPIA2_VC_VC_CLOCKS_LOGDIV2); + DBG("VC_Clocks (0xc4) should be B\n"); + } + else { + cmd.buffer.registers[i++].value= + (u8)(CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 | + CPIA2_VC_VC_CLOCKS_LOGDIV2); + } + } else { + if (cam->params.pnp_id.device_type == DEVICE_STV_672) { + cmd.buffer.registers[i++].value = + (u8) (CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 | + CPIA2_VC_VC_CLOCKS_LOGDIV0); + } + else { + cmd.buffer.registers[i++].value = + (u8) (CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 | + CPIA2_VC_VC_676_CLOCKS_SCALING | + CPIA2_VC_VC_CLOCKS_LOGDIV0); + } + } + DBG("VC_Clocks (0xc4) = 0x%0X\n", cmd.buffer.registers[i-1].value); + + /* Input reqWidth from VC */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_IHSIZE_LO; + if (image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = + (u8) (STV_IMAGE_QCIF_COLS / 4); + else + cmd.buffer.registers[i++].value = + (u8) (STV_IMAGE_CIF_COLS / 4); + + /* Timings */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_HI; + if (image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = (u8) 0; + else + cmd.buffer.registers[i++].value = (u8) 1; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_LO; + if (image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = (u8) 208; + else + cmd.buffer.registers[i++].value = (u8) 160; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_HI; + if (image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = (u8) 0; + else + cmd.buffer.registers[i++].value = (u8) 1; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_LO; + if (image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = (u8) 160; + else + cmd.buffer.registers[i++].value = (u8) 64; + + /* Output Image Size */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_OHSIZE; + cmd.buffer.registers[i++].value = cam->params.roi.width / 4; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_OVSIZE; + cmd.buffer.registers[i++].value = cam->params.roi.height / 4; + + /* Cropping */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_HCROP; + if (image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_QCIF_COLS / 4) - (width / 4)) / 2); + else + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_CIF_COLS / 4) - (width / 4)) / 2); + + cmd.buffer.registers[i].index = CPIA2_VC_VC_VCROP; + if (image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_QCIF_ROWS / 4) - (height / 4)) / 2); + else + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_CIF_ROWS / 4) - (height / 4)) / 2); + + /* Scaling registers (defaults) */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_HPHASE; + cmd.buffer.registers[i++].value = (u8) 0; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_VPHASE; + cmd.buffer.registers[i++].value = (u8) 0; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_HISPAN; + cmd.buffer.registers[i++].value = (u8) 31; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_VISPAN; + cmd.buffer.registers[i++].value = (u8) 31; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_HICROP; + cmd.buffer.registers[i++].value = (u8) 0; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_VICROP; + cmd.buffer.registers[i++].value = (u8) 0; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_HFRACT; + cmd.buffer.registers[i++].value = (u8) 0x81; /* = 8/1 = 8 (HIBYTE/LOBYTE) */ + + cmd.buffer.registers[i].index = CPIA2_VC_VC_VFRACT; + cmd.buffer.registers[i++].value = (u8) 0x81; /* = 8/1 = 8 (HIBYTE/LOBYTE) */ + + cmd.reg_count = i; + + cpia2_send_command(cam, &cmd); + + return i; +} + + +/****************************************************************************** + * + * config_sensor_500(cam) + * + *****************************************************************************/ +static int config_sensor_500(struct camera_data *cam, + int req_width, int req_height) +{ + struct cpia2_command cmd; + int i = 0; + int image_size = VIDEOSIZE_CIF; + int image_type = VIDEOSIZE_VGA; + int width = req_width; + int height = req_height; + unsigned int device = cam->params.pnp_id.device_type; + + image_size = cpia2_match_video_size(width, height); + + if (width > STV_IMAGE_CIF_COLS || height > STV_IMAGE_CIF_ROWS) + image_type = VIDEOSIZE_VGA; + else if (width > STV_IMAGE_QVGA_COLS || height > STV_IMAGE_QVGA_ROWS) + image_type = VIDEOSIZE_CIF; + else if (width > STV_IMAGE_QCIF_COLS || height > STV_IMAGE_QCIF_ROWS) + image_type = VIDEOSIZE_QVGA; + else + image_type = VIDEOSIZE_QCIF; + + if (image_size >= 0) { + set_vw_size(cam, image_size); + width = cam->params.roi.width; + height = cam->params.roi.height; + } else { + ERR("ConfigSensor500 failed\n"); + return -EINVAL; + } + + DBG("image_size = %d, width = %d, height = %d, type = %d\n", + image_size, width, height, image_type); + + cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; + cmd.direction = TRANSFER_WRITE; + i = 0; + + /* VC Format */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_FORMAT; + cmd.buffer.registers[i].value = (u8) CPIA2_VC_VC_FORMAT_UFIRST; + if (image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i].value |= (u8) CPIA2_VC_VC_FORMAT_DECIMATING; + i++; + + /* VC Clocks */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_CLOCKS; + if (device == DEVICE_STV_672) { + if (image_type == VIDEOSIZE_VGA) + cmd.buffer.registers[i].value = + (u8)CPIA2_VC_VC_CLOCKS_LOGDIV1; + else + cmd.buffer.registers[i].value = + (u8)(CPIA2_VC_VC_672_CLOCKS_SCALING | + CPIA2_VC_VC_CLOCKS_LOGDIV3); + } else { + if (image_type == VIDEOSIZE_VGA) + cmd.buffer.registers[i].value = + (u8)CPIA2_VC_VC_CLOCKS_LOGDIV0; + else + cmd.buffer.registers[i].value = + (u8)(CPIA2_VC_VC_676_CLOCKS_SCALING | + CPIA2_VC_VC_CLOCKS_LOGDIV2); + } + i++; + + DBG("VC_CLOCKS = 0x%X\n", cmd.buffer.registers[i-1].value); + + /* Input width from VP */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_IHSIZE_LO; + if (image_type == VIDEOSIZE_VGA) + cmd.buffer.registers[i].value = + (u8) (STV_IMAGE_VGA_COLS / 4); + else + cmd.buffer.registers[i].value = + (u8) (STV_IMAGE_QVGA_COLS / 4); + i++; + DBG("Input width = %d\n", cmd.buffer.registers[i-1].value); + + /* Timings */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_HI; + if (image_type == VIDEOSIZE_VGA) + cmd.buffer.registers[i++].value = (u8) 2; + else + cmd.buffer.registers[i++].value = (u8) 1; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_LO; + if (image_type == VIDEOSIZE_VGA) + cmd.buffer.registers[i++].value = (u8) 250; + else if (image_type == VIDEOSIZE_QVGA) + cmd.buffer.registers[i++].value = (u8) 125; + else + cmd.buffer.registers[i++].value = (u8) 160; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_HI; + if (image_type == VIDEOSIZE_VGA) + cmd.buffer.registers[i++].value = (u8) 2; + else + cmd.buffer.registers[i++].value = (u8) 1; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_LO; + if (image_type == VIDEOSIZE_VGA) + cmd.buffer.registers[i++].value = (u8) 12; + else if (image_type == VIDEOSIZE_QVGA) + cmd.buffer.registers[i++].value = (u8) 64; + else + cmd.buffer.registers[i++].value = (u8) 6; + + /* Output Image Size */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_OHSIZE; + if (image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = STV_IMAGE_CIF_COLS / 4; + else + cmd.buffer.registers[i++].value = width / 4; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_OVSIZE; + if (image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = STV_IMAGE_CIF_ROWS / 4; + else + cmd.buffer.registers[i++].value = height / 4; + + /* Cropping */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_HCROP; + if (image_type == VIDEOSIZE_VGA) + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_VGA_COLS / 4) - (width / 4)) / 2); + else if (image_type == VIDEOSIZE_QVGA) + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_QVGA_COLS / 4) - (width / 4)) / 2); + else if (image_type == VIDEOSIZE_CIF) + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_CIF_COLS / 4) - (width / 4)) / 2); + else /*if (image_type == VIDEOSIZE_QCIF)*/ + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_QCIF_COLS / 4) - (width / 4)) / 2); + + cmd.buffer.registers[i].index = CPIA2_VC_VC_VCROP; + if (image_type == VIDEOSIZE_VGA) + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_VGA_ROWS / 4) - (height / 4)) / 2); + else if (image_type == VIDEOSIZE_QVGA) + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_QVGA_ROWS / 4) - (height / 4)) / 2); + else if (image_type == VIDEOSIZE_CIF) + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_CIF_ROWS / 4) - (height / 4)) / 2); + else /*if (image_type == VIDEOSIZE_QCIF)*/ + cmd.buffer.registers[i++].value = + (u8) (((STV_IMAGE_QCIF_ROWS / 4) - (height / 4)) / 2); + + /* Scaling registers (defaults) */ + cmd.buffer.registers[i].index = CPIA2_VC_VC_HPHASE; + if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = (u8) 36; + else + cmd.buffer.registers[i++].value = (u8) 0; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_VPHASE; + if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = (u8) 32; + else + cmd.buffer.registers[i++].value = (u8) 0; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_HISPAN; + if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = (u8) 26; + else + cmd.buffer.registers[i++].value = (u8) 31; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_VISPAN; + if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = (u8) 21; + else + cmd.buffer.registers[i++].value = (u8) 31; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_HICROP; + cmd.buffer.registers[i++].value = (u8) 0; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_VICROP; + cmd.buffer.registers[i++].value = (u8) 0; + + cmd.buffer.registers[i].index = CPIA2_VC_VC_HFRACT; + if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = (u8) 0x2B; /* 2/11 */ + else + cmd.buffer.registers[i++].value = (u8) 0x81; /* 8/1 */ + + cmd.buffer.registers[i].index = CPIA2_VC_VC_VFRACT; + if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) + cmd.buffer.registers[i++].value = (u8) 0x13; /* 1/3 */ + else + cmd.buffer.registers[i++].value = (u8) 0x81; /* 8/1 */ + + cmd.reg_count = i; + + cpia2_send_command(cam, &cmd); + + return i; +} + + +/****************************************************************************** + * + * setallproperties + * + * This sets all user changeable properties to the values in cam->params. + *****************************************************************************/ +int set_all_properties(struct camera_data *cam) +{ + /** + * Don't set target_kb here, it will be set later. + * framerate and user_mode were already set (set_default_user_mode). + **/ + + cpia2_set_color_params(cam); + + cpia2_usb_change_streaming_alternate(cam, + cam->params.camera_state.stream_mode); + + cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE, + cam->params.vp_params.user_effects); + + cpia2_set_flicker_mode(cam, + cam->params.flicker_control.flicker_mode_req); + + cpia2_do_command(cam, + CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION, + TRANSFER_WRITE, cam->params.vp_params.gpio_direction); + cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DATA, TRANSFER_WRITE, + cam->params.vp_params.gpio_data); + + wake_system(cam); + + set_lowlight_boost(cam); + + return 0; +} + +/****************************************************************************** + * + * cpia2_save_camera_state + * + *****************************************************************************/ +void cpia2_save_camera_state(struct camera_data *cam) +{ + get_color_params(cam); + cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0); + cpia2_do_command(cam, CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION, TRANSFER_READ, + 0); + cpia2_do_command(cam, CPIA2_CMD_GET_VC_MP_GPIO_DATA, TRANSFER_READ, 0); + /* Don't get framerate or target_kb. Trust the values we already have */ +} + +/****************************************************************************** + * + * get_color_params + * + *****************************************************************************/ +void get_color_params(struct camera_data *cam) +{ + cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS, TRANSFER_READ, 0); + cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION, TRANSFER_READ, 0); + cpia2_do_command(cam, CPIA2_CMD_GET_CONTRAST, TRANSFER_READ, 0); +} + +/****************************************************************************** + * + * cpia2_set_color_params + * + *****************************************************************************/ +void cpia2_set_color_params(struct camera_data *cam) +{ + DBG("Setting color params\n"); + cpia2_set_brightness(cam, cam->params.color_params.brightness); + cpia2_set_contrast(cam, cam->params.color_params.contrast); + cpia2_set_saturation(cam, cam->params.color_params.saturation); +} + +/****************************************************************************** + * + * cpia2_set_flicker_mode + * + *****************************************************************************/ +int cpia2_set_flicker_mode(struct camera_data *cam, int mode) +{ + unsigned char cam_reg; + int err = 0; + + if(cam->params.pnp_id.device_type != DEVICE_STV_672) + return -EINVAL; + + /* Set the appropriate bits in FLICKER_MODES, preserving the rest */ + if((err = cpia2_do_command(cam, CPIA2_CMD_GET_FLICKER_MODES, + TRANSFER_READ, 0))) + return err; + cam_reg = cam->params.flicker_control.cam_register; + + switch(mode) { + case NEVER_FLICKER: + cam_reg |= CPIA2_VP_FLICKER_MODES_NEVER_FLICKER; + cam_reg &= ~CPIA2_VP_FLICKER_MODES_50HZ; + break; + case FLICKER_60: + cam_reg &= ~CPIA2_VP_FLICKER_MODES_NEVER_FLICKER; + cam_reg &= ~CPIA2_VP_FLICKER_MODES_50HZ; + break; + case FLICKER_50: + cam_reg &= ~CPIA2_VP_FLICKER_MODES_NEVER_FLICKER; + cam_reg |= CPIA2_VP_FLICKER_MODES_50HZ; + break; + default: + return -EINVAL; + } + + if((err = cpia2_do_command(cam, CPIA2_CMD_SET_FLICKER_MODES, + TRANSFER_WRITE, cam_reg))) + return err; + + /* Set the appropriate bits in EXP_MODES, preserving the rest */ + if((err = cpia2_do_command(cam, CPIA2_CMD_GET_VP_EXP_MODES, + TRANSFER_READ, 0))) + return err; + cam_reg = cam->params.vp_params.exposure_modes; + + if (mode == NEVER_FLICKER) { + cam_reg |= CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER; + } else { + cam_reg &= ~CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER; + } + + if((err = cpia2_do_command(cam, CPIA2_CMD_SET_VP_EXP_MODES, + TRANSFER_WRITE, cam_reg))) + return err; + + if((err = cpia2_do_command(cam, CPIA2_CMD_REHASH_VP4, + TRANSFER_WRITE, 1))) + return err; + + switch(mode) { + case NEVER_FLICKER: + cam->params.flicker_control.flicker_mode_req = mode; + break; + case FLICKER_60: + cam->params.flicker_control.flicker_mode_req = mode; + cam->params.flicker_control.mains_frequency = 60; + break; + case FLICKER_50: + cam->params.flicker_control.flicker_mode_req = mode; + cam->params.flicker_control.mains_frequency = 50; + break; + default: + err = -EINVAL; + } + + return err; +} + +/****************************************************************************** + * + * cpia2_set_property_flip + * + *****************************************************************************/ +void cpia2_set_property_flip(struct camera_data *cam, int prop_val) +{ + unsigned char cam_reg; + + cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0); + cam_reg = cam->params.vp_params.user_effects; + + if (prop_val) + { + cam_reg |= CPIA2_VP_USER_EFFECTS_FLIP; + } + else + { + cam_reg &= ~CPIA2_VP_USER_EFFECTS_FLIP; + } + cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE, + cam_reg); +} + +/****************************************************************************** + * + * cpia2_set_property_mirror + * + *****************************************************************************/ +void cpia2_set_property_mirror(struct camera_data *cam, int prop_val) +{ + unsigned char cam_reg; + + cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0); + cam_reg = cam->params.vp_params.user_effects; + + if (prop_val) + { + cam_reg |= CPIA2_VP_USER_EFFECTS_MIRROR; + } + else + { + cam_reg &= ~CPIA2_VP_USER_EFFECTS_MIRROR; + } + cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE, + cam_reg); +} + +/****************************************************************************** + * + * set_target_kb + * + * The new Target KB is set in cam->params.vc_params.target_kb and + * activates on reset. + *****************************************************************************/ + +int cpia2_set_target_kb(struct camera_data *cam, unsigned char value) +{ + DBG("Requested target_kb = %d\n", value); + if (value != cam->params.vc_params.target_kb) { + + cpia2_usb_stream_pause(cam); + + /* reset camera for new target_kb */ + cam->params.vc_params.target_kb = value; + cpia2_reset_camera(cam); + + cpia2_usb_stream_resume(cam); + } + + return 0; +} + +/****************************************************************************** + * + * cpia2_set_gpio + * + *****************************************************************************/ +int cpia2_set_gpio(struct camera_data *cam, unsigned char setting) +{ + int ret; + + /* Set the microport direction (register 0x90, should be defined + * already) to 1 (user output), and set the microport data (0x91) to + * the value in the ioctl argument. + */ + + ret = cpia2_do_command(cam, + CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION, + CPIA2_VC_MP_DIR_OUTPUT, + 255); + if (ret < 0) + return ret; + cam->params.vp_params.gpio_direction = 255; + + ret = cpia2_do_command(cam, + CPIA2_CMD_SET_VC_MP_GPIO_DATA, + CPIA2_VC_MP_DIR_OUTPUT, + setting); + if (ret < 0) + return ret; + cam->params.vp_params.gpio_data = setting; + + return 0; +} + +/****************************************************************************** + * + * cpia2_set_fps + * + *****************************************************************************/ +int cpia2_set_fps(struct camera_data *cam, int framerate) +{ + int retval; + + switch(framerate) { + case CPIA2_VP_FRAMERATE_30: + case CPIA2_VP_FRAMERATE_25: + if(cam->params.pnp_id.device_type == DEVICE_STV_672 && + cam->params.version.sensor_flags == + CPIA2_VP_SENSOR_FLAGS_500) { + return -EINVAL; + } + /* Fall through */ + case CPIA2_VP_FRAMERATE_15: + case CPIA2_VP_FRAMERATE_12_5: + case CPIA2_VP_FRAMERATE_7_5: + case CPIA2_VP_FRAMERATE_6_25: + break; + default: + return -EINVAL; + } + + if (cam->params.pnp_id.device_type == DEVICE_STV_672 && + framerate == CPIA2_VP_FRAMERATE_15) + framerate = 0; /* Work around bug in VP4 */ + + retval = cpia2_do_command(cam, + CPIA2_CMD_FRAMERATE_REQ, + TRANSFER_WRITE, + framerate); + + if(retval == 0) + cam->params.vp_params.frame_rate = framerate; + + return retval; +} + +/****************************************************************************** + * + * cpia2_set_brightness + * + *****************************************************************************/ +void cpia2_set_brightness(struct camera_data *cam, unsigned char value) +{ + /*** + * Don't let the register be set to zero - bug in VP4 - flash of full + * brightness + ***/ + if (cam->params.pnp_id.device_type == DEVICE_STV_672 && value == 0) + value++; + DBG("Setting brightness to %d (0x%0x)\n", value, value); + cpia2_do_command(cam,CPIA2_CMD_SET_VP_BRIGHTNESS, TRANSFER_WRITE,value); +} + +/****************************************************************************** + * + * cpia2_set_contrast + * + *****************************************************************************/ +void cpia2_set_contrast(struct camera_data *cam, unsigned char value) +{ + DBG("Setting contrast to %d (0x%0x)\n", value, value); + cam->params.color_params.contrast = value; + cpia2_do_command(cam, CPIA2_CMD_SET_CONTRAST, TRANSFER_WRITE, value); +} + +/****************************************************************************** + * + * cpia2_set_saturation + * + *****************************************************************************/ +void cpia2_set_saturation(struct camera_data *cam, unsigned char value) +{ + DBG("Setting saturation to %d (0x%0x)\n", value, value); + cam->params.color_params.saturation = value; + cpia2_do_command(cam,CPIA2_CMD_SET_VP_SATURATION, TRANSFER_WRITE,value); +} + +/****************************************************************************** + * + * wake_system + * + *****************************************************************************/ +void wake_system(struct camera_data *cam) +{ + cpia2_do_command(cam, CPIA2_CMD_SET_WAKEUP, TRANSFER_WRITE, 0); +} + +/****************************************************************************** + * + * set_lowlight_boost + * + * Valid for STV500 sensor only + *****************************************************************************/ +void set_lowlight_boost(struct camera_data *cam) +{ + struct cpia2_command cmd; + + if (cam->params.pnp_id.device_type != DEVICE_STV_672 || + cam->params.version.sensor_flags != CPIA2_VP_SENSOR_FLAGS_500) + return; + + cmd.direction = TRANSFER_WRITE; + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 3; + cmd.start = CPIA2_VP_RAM_ADDR_H; + + cmd.buffer.block_data[0] = 0; /* High byte of address to write to */ + cmd.buffer.block_data[1] = 0x59; /* Low byte of address to write to */ + cmd.buffer.block_data[2] = 0; /* High byte of data to write */ + + cpia2_send_command(cam, &cmd); + + if (cam->params.vp_params.lowlight_boost) { + cmd.buffer.block_data[0] = 0x02; /* Low byte data to write */ + } else { + cmd.buffer.block_data[0] = 0x06; + } + cmd.start = CPIA2_VP_RAM_DATA; + cmd.reg_count = 1; + cpia2_send_command(cam, &cmd); + + /* Rehash the VP4 values */ + cpia2_do_command(cam, CPIA2_CMD_REHASH_VP4, TRANSFER_WRITE, 1); +} + +/****************************************************************************** + * + * cpia2_set_format + * + * Assumes that new size is already set in param struct. + *****************************************************************************/ +void cpia2_set_format(struct camera_data *cam) +{ + cam->flush = true; + + cpia2_usb_stream_pause(cam); + + /* reset camera to new size */ + cpia2_set_low_power(cam); + cpia2_reset_camera(cam); + cam->flush = false; + + cpia2_dbg_dump_registers(cam); + + cpia2_usb_stream_resume(cam); +} + +/****************************************************************************** + * + * cpia2_dbg_dump_registers + * + *****************************************************************************/ +void cpia2_dbg_dump_registers(struct camera_data *cam) +{ +#ifdef _CPIA2_DEBUG_ + struct cpia2_command cmd; + + if (!(debugs_on & DEBUG_DUMP_REGS)) + return; + + cmd.direction = TRANSFER_READ; + + /* Start with bank 0 (SYSTEM) */ + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; + cmd.reg_count = 3; + cmd.start = 0; + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "System Device Hi = 0x%X\n", + cmd.buffer.block_data[0]); + printk(KERN_DEBUG "System Device Lo = 0x%X\n", + cmd.buffer.block_data[1]); + printk(KERN_DEBUG "System_system control = 0x%X\n", + cmd.buffer.block_data[2]); + + /* Bank 1 (VC) */ + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; + cmd.reg_count = 4; + cmd.start = 0x80; + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "ASIC_ID = 0x%X\n", + cmd.buffer.block_data[0]); + printk(KERN_DEBUG "ASIC_REV = 0x%X\n", + cmd.buffer.block_data[1]); + printk(KERN_DEBUG "PW_CONTRL = 0x%X\n", + cmd.buffer.block_data[2]); + printk(KERN_DEBUG "WAKEUP = 0x%X\n", + cmd.buffer.block_data[3]); + + cmd.start = 0xA0; /* ST_CTRL */ + cmd.reg_count = 1; + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "Stream ctrl = 0x%X\n", + cmd.buffer.block_data[0]); + + cmd.start = 0xA4; /* Stream status */ + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "Stream status = 0x%X\n", + cmd.buffer.block_data[0]); + + cmd.start = 0xA8; /* USB status */ + cmd.reg_count = 3; + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "USB_CTRL = 0x%X\n", + cmd.buffer.block_data[0]); + printk(KERN_DEBUG "USB_STRM = 0x%X\n", + cmd.buffer.block_data[1]); + printk(KERN_DEBUG "USB_STATUS = 0x%X\n", + cmd.buffer.block_data[2]); + + cmd.start = 0xAF; /* USB settings */ + cmd.reg_count = 1; + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "USB settings = 0x%X\n", + cmd.buffer.block_data[0]); + + cmd.start = 0xC0; /* VC stuff */ + cmd.reg_count = 26; + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "VC Control = 0x%0X\n", + cmd.buffer.block_data[0]); + printk(KERN_DEBUG "VC Format = 0x%0X\n", + cmd.buffer.block_data[3]); + printk(KERN_DEBUG "VC Clocks = 0x%0X\n", + cmd.buffer.block_data[4]); + printk(KERN_DEBUG "VC IHSize = 0x%0X\n", + cmd.buffer.block_data[5]); + printk(KERN_DEBUG "VC Xlim Hi = 0x%0X\n", + cmd.buffer.block_data[6]); + printk(KERN_DEBUG "VC XLim Lo = 0x%0X\n", + cmd.buffer.block_data[7]); + printk(KERN_DEBUG "VC YLim Hi = 0x%0X\n", + cmd.buffer.block_data[8]); + printk(KERN_DEBUG "VC YLim Lo = 0x%0X\n", + cmd.buffer.block_data[9]); + printk(KERN_DEBUG "VC OHSize = 0x%0X\n", + cmd.buffer.block_data[10]); + printk(KERN_DEBUG "VC OVSize = 0x%0X\n", + cmd.buffer.block_data[11]); + printk(KERN_DEBUG "VC HCrop = 0x%0X\n", + cmd.buffer.block_data[12]); + printk(KERN_DEBUG "VC VCrop = 0x%0X\n", + cmd.buffer.block_data[13]); + printk(KERN_DEBUG "VC HPhase = 0x%0X\n", + cmd.buffer.block_data[14]); + printk(KERN_DEBUG "VC VPhase = 0x%0X\n", + cmd.buffer.block_data[15]); + printk(KERN_DEBUG "VC HIspan = 0x%0X\n", + cmd.buffer.block_data[16]); + printk(KERN_DEBUG "VC VIspan = 0x%0X\n", + cmd.buffer.block_data[17]); + printk(KERN_DEBUG "VC HiCrop = 0x%0X\n", + cmd.buffer.block_data[18]); + printk(KERN_DEBUG "VC ViCrop = 0x%0X\n", + cmd.buffer.block_data[19]); + printk(KERN_DEBUG "VC HiFract = 0x%0X\n", + cmd.buffer.block_data[20]); + printk(KERN_DEBUG "VC ViFract = 0x%0X\n", + cmd.buffer.block_data[21]); + printk(KERN_DEBUG "VC JPeg Opt = 0x%0X\n", + cmd.buffer.block_data[22]); + printk(KERN_DEBUG "VC Creep Per = 0x%0X\n", + cmd.buffer.block_data[23]); + printk(KERN_DEBUG "VC User Sq. = 0x%0X\n", + cmd.buffer.block_data[24]); + printk(KERN_DEBUG "VC Target KB = 0x%0X\n", + cmd.buffer.block_data[25]); + + /*** VP ***/ + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; + cmd.reg_count = 14; + cmd.start = 0; + cpia2_send_command(cam, &cmd); + + printk(KERN_DEBUG "VP Dev Hi = 0x%0X\n", + cmd.buffer.block_data[0]); + printk(KERN_DEBUG "VP Dev Lo = 0x%0X\n", + cmd.buffer.block_data[1]); + printk(KERN_DEBUG "VP Sys State = 0x%0X\n", + cmd.buffer.block_data[2]); + printk(KERN_DEBUG "VP Sys Ctrl = 0x%0X\n", + cmd.buffer.block_data[3]); + printk(KERN_DEBUG "VP Sensor flg = 0x%0X\n", + cmd.buffer.block_data[5]); + printk(KERN_DEBUG "VP Sensor Rev = 0x%0X\n", + cmd.buffer.block_data[6]); + printk(KERN_DEBUG "VP Dev Config = 0x%0X\n", + cmd.buffer.block_data[7]); + printk(KERN_DEBUG "VP GPIO_DIR = 0x%0X\n", + cmd.buffer.block_data[8]); + printk(KERN_DEBUG "VP GPIO_DATA = 0x%0X\n", + cmd.buffer.block_data[9]); + printk(KERN_DEBUG "VP Ram ADDR H = 0x%0X\n", + cmd.buffer.block_data[10]); + printk(KERN_DEBUG "VP Ram ADDR L = 0x%0X\n", + cmd.buffer.block_data[11]); + printk(KERN_DEBUG "VP RAM Data = 0x%0X\n", + cmd.buffer.block_data[12]); + printk(KERN_DEBUG "Do Call = 0x%0X\n", + cmd.buffer.block_data[13]); + + if (cam->params.pnp_id.device_type == DEVICE_STV_672) { + cmd.reg_count = 9; + cmd.start = 0x0E; + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "VP Clock Ctrl = 0x%0X\n", + cmd.buffer.block_data[0]); + printk(KERN_DEBUG "VP Patch Rev = 0x%0X\n", + cmd.buffer.block_data[1]); + printk(KERN_DEBUG "VP Vid Mode = 0x%0X\n", + cmd.buffer.block_data[2]); + printk(KERN_DEBUG "VP Framerate = 0x%0X\n", + cmd.buffer.block_data[3]); + printk(KERN_DEBUG "VP UserEffect = 0x%0X\n", + cmd.buffer.block_data[4]); + printk(KERN_DEBUG "VP White Bal = 0x%0X\n", + cmd.buffer.block_data[5]); + printk(KERN_DEBUG "VP WB thresh = 0x%0X\n", + cmd.buffer.block_data[6]); + printk(KERN_DEBUG "VP Exp Modes = 0x%0X\n", + cmd.buffer.block_data[7]); + printk(KERN_DEBUG "VP Exp Target = 0x%0X\n", + cmd.buffer.block_data[8]); + + cmd.reg_count = 1; + cmd.start = 0x1B; + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "VP FlickerMds = 0x%0X\n", + cmd.buffer.block_data[0]); + } else { + cmd.reg_count = 8 ; + cmd.start = 0x0E; + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "VP Clock Ctrl = 0x%0X\n", + cmd.buffer.block_data[0]); + printk(KERN_DEBUG "VP Patch Rev = 0x%0X\n", + cmd.buffer.block_data[1]); + printk(KERN_DEBUG "VP Vid Mode = 0x%0X\n", + cmd.buffer.block_data[5]); + printk(KERN_DEBUG "VP Framerate = 0x%0X\n", + cmd.buffer.block_data[6]); + printk(KERN_DEBUG "VP UserEffect = 0x%0X\n", + cmd.buffer.block_data[7]); + + cmd.reg_count = 1; + cmd.start = CPIA2_VP5_EXPOSURE_TARGET; + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "VP5 Exp Target= 0x%0X\n", + cmd.buffer.block_data[0]); + + cmd.reg_count = 4; + cmd.start = 0x3A; + cpia2_send_command(cam, &cmd); + printk(KERN_DEBUG "VP5 MY Black = 0x%0X\n", + cmd.buffer.block_data[0]); + printk(KERN_DEBUG "VP5 MCY Range = 0x%0X\n", + cmd.buffer.block_data[1]); + printk(KERN_DEBUG "VP5 MYCEILING = 0x%0X\n", + cmd.buffer.block_data[2]); + printk(KERN_DEBUG "VP5 MCUV Sat = 0x%0X\n", + cmd.buffer.block_data[3]); + } +#endif +} + +/****************************************************************************** + * + * reset_camera_struct + * + * Sets all values to the defaults + *****************************************************************************/ +void reset_camera_struct(struct camera_data *cam) +{ + /*** + * The following parameter values are the defaults from the register map. + ***/ + cam->params.color_params.brightness = DEFAULT_BRIGHTNESS; + cam->params.color_params.contrast = DEFAULT_CONTRAST; + cam->params.color_params.saturation = DEFAULT_SATURATION; + cam->params.vp_params.lowlight_boost = 0; + + /* FlickerModes */ + cam->params.flicker_control.flicker_mode_req = NEVER_FLICKER; + cam->params.flicker_control.mains_frequency = 60; + + /* jpeg params */ + cam->params.compression.jpeg_options = CPIA2_VC_VC_JPEG_OPT_DEFAULT; + cam->params.compression.creep_period = 2; + cam->params.compression.user_squeeze = 20; + cam->params.compression.inhibit_htables = false; + + /* gpio params */ + cam->params.vp_params.gpio_direction = 0; /* write, the default safe mode */ + cam->params.vp_params.gpio_data = 0; + + /* Target kb params */ + cam->params.vc_params.target_kb = DEFAULT_TARGET_KB; + + /*** + * Set Sensor FPS as fast as possible. + ***/ + if(cam->params.pnp_id.device_type == DEVICE_STV_672) { + if(cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500) + cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_15; + else + cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_30; + } else { + cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_30; + } + + /*** + * Set default video mode as large as possible : + * for vga sensor set to vga, for cif sensor set to CIF. + ***/ + if (cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500) { + cam->sensor_type = CPIA2_SENSOR_500; + cam->video_size = VIDEOSIZE_VGA; + cam->params.roi.width = STV_IMAGE_VGA_COLS; + cam->params.roi.height = STV_IMAGE_VGA_ROWS; + } else { + cam->sensor_type = CPIA2_SENSOR_410; + cam->video_size = VIDEOSIZE_CIF; + cam->params.roi.width = STV_IMAGE_CIF_COLS; + cam->params.roi.height = STV_IMAGE_CIF_ROWS; + } + + /*** + * Fill in the v4l structures. video_cap is filled in inside the VIDIOCCAP + * Ioctl. Here, just do the window and picture stucts. + ***/ + cam->vp.palette = (u16) VIDEO_PALETTE_RGB24; /* Is this right? */ + cam->vp.brightness = (u16) cam->params.color_params.brightness * 256; + cam->vp.colour = (u16) cam->params.color_params.saturation * 256; + cam->vp.contrast = (u16) cam->params.color_params.contrast * 256; + + cam->vw.x = 0; + cam->vw.y = 0; + cam->vw.width = cam->params.roi.width; + cam->vw.height = cam->params.roi.height; + cam->vw.flags = 0; + cam->vw.clipcount = 0; + + return; +} + +/****************************************************************************** + * + * cpia2_init_camera_struct + * + * Initializes camera struct, does not call reset to fill in defaults. + *****************************************************************************/ +struct camera_data *cpia2_init_camera_struct(void) +{ + struct camera_data *cam; + + cam = kmalloc(sizeof(*cam), GFP_KERNEL); + + if (!cam) { + ERR("couldn't kmalloc cpia2 struct\n"); + return NULL; + } + + /* Default everything to 0 */ + memset(cam, 0, sizeof(struct camera_data)); + + cam->present = 1; + init_MUTEX(&cam->busy_lock); + init_waitqueue_head(&cam->wq_stream); + + return cam; +} + +/****************************************************************************** + * + * cpia2_init_camera + * + * Initializes camera. + *****************************************************************************/ +int cpia2_init_camera(struct camera_data *cam) +{ + DBG("Start\n"); + + cam->mmapped = false; + + /* Get sensor and asic types before reset. */ + cpia2_set_high_power(cam); + cpia2_get_version_info(cam); + if (cam->params.version.asic_id != CPIA2_ASIC_672) { + ERR("Device IO error (asicID has incorrect value of 0x%X\n", + cam->params.version.asic_id); + return -ENODEV; + } + + /* Set GPIO direction and data to a safe state. */ + cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION, + TRANSFER_WRITE, 0); + cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DATA, + TRANSFER_WRITE, 0); + + /* resetting struct requires version info for sensor and asic types */ + reset_camera_struct(cam); + + cpia2_set_low_power(cam); + + DBG("End\n"); + + return 0; +} + +/****************************************************************************** + * + * cpia2_allocate_buffers + * + *****************************************************************************/ +int cpia2_allocate_buffers(struct camera_data *cam) +{ + int i; + + if(!cam->buffers) { + u32 size = cam->num_frames*sizeof(struct framebuf); + cam->buffers = kmalloc(size, GFP_KERNEL); + if(!cam->buffers) { + ERR("couldn't kmalloc frame buffer structures\n"); + return -ENOMEM; + } + } + + if(!cam->frame_buffer) { + cam->frame_buffer = rvmalloc(cam->frame_size*cam->num_frames); + if (!cam->frame_buffer) { + ERR("couldn't vmalloc frame buffer data area\n"); + kfree(cam->buffers); + cam->buffers = NULL; + return -ENOMEM; + } + } + + for(i=0; inum_frames-1; ++i) { + cam->buffers[i].next = &cam->buffers[i+1]; + cam->buffers[i].data = cam->frame_buffer +i*cam->frame_size; + cam->buffers[i].status = FRAME_EMPTY; + cam->buffers[i].length = 0; + cam->buffers[i].max_length = 0; + cam->buffers[i].num = i; + } + cam->buffers[i].next = cam->buffers; + cam->buffers[i].data = cam->frame_buffer +i*cam->frame_size; + cam->buffers[i].status = FRAME_EMPTY; + cam->buffers[i].length = 0; + cam->buffers[i].max_length = 0; + cam->buffers[i].num = i; + cam->curbuff = cam->buffers; + cam->workbuff = cam->curbuff->next; + DBG("buffers=%p, curbuff=%p, workbuff=%p\n", cam->buffers, cam->curbuff, + cam->workbuff); + return 0; +} + +/****************************************************************************** + * + * cpia2_free_buffers + * + *****************************************************************************/ +void cpia2_free_buffers(struct camera_data *cam) +{ + if(cam->buffers) { + kfree(cam->buffers); + cam->buffers = NULL; + } + if(cam->frame_buffer) { + rvfree(cam->frame_buffer, cam->frame_size*cam->num_frames); + cam->frame_buffer = NULL; + } +} + +/****************************************************************************** + * + * cpia2_read + * + *****************************************************************************/ +long cpia2_read(struct camera_data *cam, + char __user *buf, unsigned long count, int noblock) +{ + struct framebuf *frame; + if (!count) { + return 0; + } + + if (!buf) { + ERR("%s: buffer NULL\n",__FUNCTION__); + return -EINVAL; + } + + if (!cam) { + ERR("%s: Internal error, camera_data NULL!\n",__FUNCTION__); + return -EINVAL; + } + + /* make this _really_ smp and multithread-safe */ + if (down_interruptible(&cam->busy_lock)) + return -ERESTARTSYS; + + if (!cam->present) { + LOG("%s: camera removed\n",__FUNCTION__); + up(&cam->busy_lock); + return 0; /* EOF */ + } + + if(!cam->streaming) { + /* Start streaming */ + cpia2_usb_stream_start(cam, + cam->params.camera_state.stream_mode); + } + + /* Copy cam->curbuff in case it changes while we're processing */ + frame = cam->curbuff; + if (noblock && frame->status != FRAME_READY) { + up(&cam->busy_lock); + return -EAGAIN; + } + + if(frame->status != FRAME_READY) { + up(&cam->busy_lock); + wait_event_interruptible(cam->wq_stream, + !cam->present || + (frame = cam->curbuff)->status == FRAME_READY); + if (signal_pending(current)) + return -ERESTARTSYS; + /* make this _really_ smp and multithread-safe */ + if (down_interruptible(&cam->busy_lock)) { + return -ERESTARTSYS; + } + if(!cam->present) { + up(&cam->busy_lock); + return 0; + } + } + + /* copy data to user space */ + if (frame->length > count) { + up(&cam->busy_lock); + return -EFAULT; + } + if (copy_to_user(buf, frame->data, frame->length)) { + up(&cam->busy_lock); + return -EFAULT; + } + + count = frame->length; + + frame->status = FRAME_EMPTY; + + up(&cam->busy_lock); + return count; +} + +/****************************************************************************** + * + * cpia2_poll + * + *****************************************************************************/ +unsigned int cpia2_poll(struct camera_data *cam, struct file *filp, + poll_table *wait) +{ + unsigned int status=0; + + if(!cam) { + ERR("%s: Internal error, camera_data not found!\n",__FUNCTION__); + return POLLERR; + } + + down(&cam->busy_lock); + + if(!cam->present) { + up(&cam->busy_lock); + return POLLHUP; + } + + if(!cam->streaming) { + /* Start streaming */ + cpia2_usb_stream_start(cam, + cam->params.camera_state.stream_mode); + } + + up(&cam->busy_lock); + poll_wait(filp, &cam->wq_stream, wait); + down(&cam->busy_lock); + + if(!cam->present) + status = POLLHUP; + else if(cam->curbuff->status == FRAME_READY) + status = POLLIN | POLLRDNORM; + + up(&cam->busy_lock); + return status; +} + +/****************************************************************************** + * + * cpia2_remap_buffer + * + *****************************************************************************/ +int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma) +{ + const char *adr = (const char *)vma->vm_start; + unsigned long size = vma->vm_end-vma->vm_start; + unsigned long start_offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long start = (unsigned long) adr; + unsigned long page, pos; + + if (!cam) + return -ENODEV; + + DBG("mmap offset:%ld size:%ld\n", start_offset, size); + + /* make this _really_ smp-safe */ + if (down_interruptible(&cam->busy_lock)) + return -ERESTARTSYS; + + if (!cam->present) { + up(&cam->busy_lock); + return -ENODEV; + } + + if (size > cam->frame_size*cam->num_frames || + (start_offset % cam->frame_size) != 0 || + (start_offset+size > cam->frame_size*cam->num_frames)) { + up(&cam->busy_lock); + return -EINVAL; + } + + pos = ((unsigned long) (cam->frame_buffer)) + start_offset; + while (size > 0) { + page = kvirt_to_pa(pos); + if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) { + up(&cam->busy_lock); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + cam->mmapped = true; + up(&cam->busy_lock); + return 0; +} + diff --git a/drivers/media/video/cpia2/cpia2_registers.h b/drivers/media/video/cpia2/cpia2_registers.h new file mode 100644 index 000000000000..3bbec514a967 --- /dev/null +++ b/drivers/media/video/cpia2/cpia2_registers.h @@ -0,0 +1,476 @@ +/**************************************************************************** + * + * Filename: cpia2registers.h + * + * Copyright 2001, STMicrolectronics, Inc. + * + * Description: + * Definitions for the CPia2 register set + * + * 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. + * + ****************************************************************************/ + +#ifndef CPIA2_REGISTER_HEADER +#define CPIA2_REGISTER_HEADER + +/*** + * System register set (Bank 0) + ***/ +#define CPIA2_SYSTEM_DEVICE_HI 0x00 +#define CPIA2_SYSTEM_DEVICE_LO 0x01 + +#define CPIA2_SYSTEM_SYSTEM_CONTROL 0x02 +#define CPIA2_SYSTEM_CONTROL_LOW_POWER 0x00 +#define CPIA2_SYSTEM_CONTROL_HIGH_POWER 0x01 +#define CPIA2_SYSTEM_CONTROL_SUSPEND 0x02 +#define CPIA2_SYSTEM_CONTROL_V2W_ERR 0x10 +#define CPIA2_SYSTEM_CONTROL_RB_ERR 0x10 +#define CPIA2_SYSTEM_CONTROL_CLEAR_ERR 0x80 + +#define CPIA2_SYSTEM_INT_PACKET_CTRL 0x04 +#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_SW_XX 0x01 +#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_EOF 0x02 +#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_INT1 0x04 + +#define CPIA2_SYSTEM_CACHE_CTRL 0x05 +#define CPIA2_SYSTEM_CACHE_CTRL_CACHE_RESET 0x01 +#define CPIA2_SYSTEM_CACHE_CTRL_CACHE_FLUSH 0x02 + +#define CPIA2_SYSTEM_SERIAL_CTRL 0x06 +#define CPIA2_SYSTEM_SERIAL_CTRL_NULL_CMD 0x00 +#define CPIA2_SYSTEM_SERIAL_CTRL_START_CMD 0x01 +#define CPIA2_SYSTEM_SERIAL_CTRL_STOP_CMD 0x02 +#define CPIA2_SYSTEM_SERIAL_CTRL_WRITE_CMD 0x03 +#define CPIA2_SYSTEM_SERIAL_CTRL_READ_ACK_CMD 0x04 +#define CPIA2_SYSTEM_SERIAL_CTRL_READ_NACK_CMD 0x05 + +#define CPIA2_SYSTEM_SERIAL_DATA 0x07 + +#define CPIA2_SYSTEM_VP_SERIAL_ADDR 0x08 + +/*** + * I2C addresses for various devices in CPiA2 + ***/ +#define CPIA2_SYSTEM_VP_SERIAL_ADDR_SENSOR 0x20 +#define CPIA2_SYSTEM_VP_SERIAL_ADDR_VP 0x88 +#define CPIA2_SYSTEM_VP_SERIAL_ADDR_676_VP 0x8A + +#define CPIA2_SYSTEM_SPARE_REG1 0x09 +#define CPIA2_SYSTEM_SPARE_REG2 0x0A +#define CPIA2_SYSTEM_SPARE_REG3 0x0B + +#define CPIA2_SYSTEM_MC_PORT_0 0x0C +#define CPIA2_SYSTEM_MC_PORT_1 0x0D +#define CPIA2_SYSTEM_MC_PORT_2 0x0E +#define CPIA2_SYSTEM_MC_PORT_3 0x0F + +#define CPIA2_SYSTEM_STATUS_PKT 0x20 +#define CPIA2_SYSTEM_STATUS_PKT_END 0x27 + +#define CPIA2_SYSTEM_DESCRIP_VID_HI 0x30 +#define CPIA2_SYSTEM_DESCRIP_VID_LO 0x31 +#define CPIA2_SYSTEM_DESCRIP_PID_HI 0x32 +#define CPIA2_SYSTEM_DESCRIP_PID_LO 0x33 + +#define CPIA2_SYSTEM_FW_VERSION_HI 0x34 +#define CPIA2_SYSTEM_FW_VERSION_LO 0x35 + +#define CPIA2_SYSTEM_CACHE_START_INDEX 0x80 +#define CPIA2_SYSTEM_CACHE_MAX_WRITES 0x10 + +/*** + * VC register set (Bank 1) + ***/ +#define CPIA2_VC_ASIC_ID 0x80 + +#define CPIA2_VC_ASIC_REV 0x81 + +#define CPIA2_VC_PW_CTRL 0x82 +#define CPIA2_VC_PW_CTRL_COLDSTART 0x01 +#define CPIA2_VC_PW_CTRL_CP_CLK_EN 0x02 +#define CPIA2_VC_PW_CTRL_VP_RESET_N 0x04 +#define CPIA2_VC_PW_CTRL_VC_CLK_EN 0x08 +#define CPIA2_VC_PW_CTRL_VC_RESET_N 0x10 +#define CPIA2_VC_PW_CTRL_GOTO_SUSPEND 0x20 +#define CPIA2_VC_PW_CTRL_UDC_SUSPEND 0x40 +#define CPIA2_VC_PW_CTRL_PWR_DOWN 0x80 + +#define CPIA2_VC_WAKEUP 0x83 +#define CPIA2_VC_WAKEUP_SW_ENABLE 0x01 +#define CPIA2_VC_WAKEUP_XX_ENABLE 0x02 +#define CPIA2_VC_WAKEUP_SW_ATWAKEUP 0x04 +#define CPIA2_VC_WAKEUP_XX_ATWAKEUP 0x08 + +#define CPIA2_VC_CLOCK_CTRL 0x84 +#define CPIA2_VC_CLOCK_CTRL_TESTUP72 0x01 + +#define CPIA2_VC_INT_ENABLE 0x88 +#define CPIA2_VC_INT_ENABLE_XX_IE 0x01 +#define CPIA2_VC_INT_ENABLE_SW_IE 0x02 +#define CPIA2_VC_INT_ENABLE_VC_IE 0x04 +#define CPIA2_VC_INT_ENABLE_USBDATA_IE 0x08 +#define CPIA2_VC_INT_ENABLE_USBSETUP_IE 0x10 +#define CPIA2_VC_INT_ENABLE_USBCFG_IE 0x20 + +#define CPIA2_VC_INT_FLAG 0x89 +#define CPIA2_VC_INT_ENABLE_XX_FLAG 0x01 +#define CPIA2_VC_INT_ENABLE_SW_FLAG 0x02 +#define CPIA2_VC_INT_ENABLE_VC_FLAG 0x04 +#define CPIA2_VC_INT_ENABLE_USBDATA_FLAG 0x08 +#define CPIA2_VC_INT_ENABLE_USBSETUP_FLAG 0x10 +#define CPIA2_VC_INT_ENABLE_USBCFG_FLAG 0x20 +#define CPIA2_VC_INT_ENABLE_SET_RESET_BIT 0x80 + +#define CPIA2_VC_INT_STATE 0x8A +#define CPIA2_VC_INT_STATE_XX_STATE 0x01 +#define CPIA2_VC_INT_STATE_SW_STATE 0x02 + +#define CPIA2_VC_MP_DIR 0x90 +#define CPIA2_VC_MP_DIR_INPUT 0x00 +#define CPIA2_VC_MP_DIR_OUTPUT 0x01 + +#define CPIA2_VC_MP_DATA 0x91 + +#define CPIA2_VC_DP_CTRL 0x98 +#define CPIA2_VC_DP_CTRL_MODE_0 0x00 +#define CPIA2_VC_DP_CTRL_MODE_A 0x01 +#define CPIA2_VC_DP_CTRL_MODE_B 0x02 +#define CPIA2_VC_DP_CTRL_MODE_C 0x03 +#define CPIA2_VC_DP_CTRL_FAKE_FST 0x04 + +#define CPIA2_VC_AD_CTRL 0x99 +#define CPIA2_VC_AD_CTRL_SRC_0 0x00 +#define CPIA2_VC_AD_CTRL_SRC_DIGI_A 0x01 +#define CPIA2_VC_AD_CTRL_SRC_REG 0x02 +#define CPIA2_VC_AD_CTRL_DST_USB 0x00 +#define CPIA2_VC_AD_CTRL_DST_REG 0x04 + +#define CPIA2_VC_AD_TEST_IN 0x9B + +#define CPIA2_VC_AD_TEST_OUT 0x9C + +#define CPIA2_VC_AD_STATUS 0x9D +#define CPIA2_VC_AD_STATUS_EMPTY 0x01 +#define CPIA2_VC_AD_STATUS_FULL 0x02 + +#define CPIA2_VC_DP_DATA 0x9E + +#define CPIA2_VC_ST_CTRL 0xA0 +#define CPIA2_VC_ST_CTRL_SRC_VC 0x00 +#define CPIA2_VC_ST_CTRL_SRC_DP 0x01 +#define CPIA2_VC_ST_CTRL_SRC_REG 0x02 + +#define CPIA2_VC_ST_CTRL_RAW_SELECT 0x04 + +#define CPIA2_VC_ST_CTRL_DST_USB 0x00 +#define CPIA2_VC_ST_CTRL_DST_DP 0x08 +#define CPIA2_VC_ST_CTRL_DST_REG 0x10 + +#define CPIA2_VC_ST_CTRL_FIFO_ENABLE 0x20 +#define CPIA2_VC_ST_CTRL_EOF_DETECT 0x40 + +#define CPIA2_VC_ST_TEST 0xA1 +#define CPIA2_VC_ST_TEST_MODE_MANUAL 0x00 +#define CPIA2_VC_ST_TEST_MODE_INCREMENT 0x02 + +#define CPIA2_VC_ST_TEST_AUTO_FILL 0x08 + +#define CPIA2_VC_ST_TEST_REPEAT_FIFO 0x10 + +#define CPIA2_VC_ST_TEST_IN 0xA2 + +#define CPIA2_VC_ST_TEST_OUT 0xA3 + +#define CPIA2_VC_ST_STATUS 0xA4 +#define CPIA2_VC_ST_STATUS_EMPTY 0x01 +#define CPIA2_VC_ST_STATUS_FULL 0x02 + +#define CPIA2_VC_ST_FRAME_DETECT_1 0xA5 + +#define CPIA2_VC_ST_FRAME_DETECT_2 0xA6 + +#define CPIA2_VC_USB_CTRL 0xA8 +#define CPIA2_VC_USB_CTRL_CMD_STALLED 0x01 +#define CPIA2_VC_USB_CTRL_CMD_READY 0x02 +#define CPIA2_VC_USB_CTRL_CMD_STATUS 0x04 +#define CPIA2_VC_USB_CTRL_CMD_STATUS_DIR 0x08 +#define CPIA2_VC_USB_CTRL_CMD_NO_CLASH 0x10 +#define CPIA2_VC_USB_CTRL_CMD_MICRO_ACCESS 0x80 + +#define CPIA2_VC_USB_STRM 0xA9 +#define CPIA2_VC_USB_STRM_ISO_ENABLE 0x01 +#define CPIA2_VC_USB_STRM_BLK_ENABLE 0x02 +#define CPIA2_VC_USB_STRM_INT_ENABLE 0x04 +#define CPIA2_VC_USB_STRM_AUD_ENABLE 0x08 + +#define CPIA2_VC_USB_STATUS 0xAA +#define CPIA2_VC_USB_STATUS_CMD_IN_PROGRESS 0x01 +#define CPIA2_VC_USB_STATUS_CMD_STATUS_STALL 0x02 +#define CPIA2_VC_USB_STATUS_CMD_HANDSHAKE 0x04 +#define CPIA2_VC_USB_STATUS_CMD_OVERRIDE 0x08 +#define CPIA2_VC_USB_STATUS_CMD_FIFO_BUSY 0x10 +#define CPIA2_VC_USB_STATUS_BULK_REPEAT_TXN 0x20 +#define CPIA2_VC_USB_STATUS_CONFIG_DONE 0x40 +#define CPIA2_VC_USB_STATUS_USB_SUSPEND 0x80 + +#define CPIA2_VC_USB_CMDW 0xAB + +#define CPIA2_VC_USB_DATARW 0xAC + +#define CPIA2_VC_USB_INFO 0xAD + +#define CPIA2_VC_USB_CONFIG 0xAE + +#define CPIA2_VC_USB_SETTINGS 0xAF +#define CPIA2_VC_USB_SETTINGS_CONFIG_MASK 0x03 +#define CPIA2_VC_USB_SETTINGS_INTERFACE_MASK 0x0C +#define CPIA2_VC_USB_SETTINGS_ALTERNATE_MASK 0x70 + +#define CPIA2_VC_USB_ISOLIM 0xB0 + +#define CPIA2_VC_USB_ISOFAILS 0xB1 + +#define CPIA2_VC_USB_ISOMAXPKTHI 0xB2 + +#define CPIA2_VC_USB_ISOMAXPKTLO 0xB3 + +#define CPIA2_VC_V2W_CTRL 0xB8 +#define CPIA2_VC_V2W_SELECT 0x01 + +#define CPIA2_VC_V2W_SCL 0xB9 + +#define CPIA2_VC_V2W_SDA 0xBA + +#define CPIA2_VC_VC_CTRL 0xC0 +#define CPIA2_VC_VC_CTRL_RUN 0x01 +#define CPIA2_VC_VC_CTRL_SINGLESHOT 0x02 +#define CPIA2_VC_VC_CTRL_IDLING 0x04 +#define CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES 0x10 +#define CPIA2_VC_VC_CTRL_INHIBIT_Q_TABLES 0x20 +#define CPIA2_VC_VC_CTRL_INHIBIT_PRIVATE 0x40 + +#define CPIA2_VC_VC_RESTART_IVAL_HI 0xC1 + +#define CPIA2_VC_VC_RESTART_IVAL_LO 0xC2 + +#define CPIA2_VC_VC_FORMAT 0xC3 +#define CPIA2_VC_VC_FORMAT_UFIRST 0x01 +#define CPIA2_VC_VC_FORMAT_MONO 0x02 +#define CPIA2_VC_VC_FORMAT_DECIMATING 0x04 +#define CPIA2_VC_VC_FORMAT_SHORTLINE 0x08 +#define CPIA2_VC_VC_FORMAT_SELFTEST 0x10 + +#define CPIA2_VC_VC_CLOCKS 0xC4 +#define CPIA2_VC_VC_CLOCKS_CLKDIV_MASK 0x03 +#define CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 0x04 +#define CPIA2_VC_VC_672_CLOCKS_SCALING 0x08 +#define CPIA2_VC_VC_CLOCKS_LOGDIV0 0x00 +#define CPIA2_VC_VC_CLOCKS_LOGDIV1 0x01 +#define CPIA2_VC_VC_CLOCKS_LOGDIV2 0x02 +#define CPIA2_VC_VC_CLOCKS_LOGDIV3 0x03 +#define CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 0x08 +#define CPIA2_VC_VC_676_CLOCKS_SCALING 0x10 + +#define CPIA2_VC_VC_IHSIZE_LO 0xC5 + +#define CPIA2_VC_VC_XLIM_HI 0xC6 + +#define CPIA2_VC_VC_XLIM_LO 0xC7 + +#define CPIA2_VC_VC_YLIM_HI 0xC8 + +#define CPIA2_VC_VC_YLIM_LO 0xC9 + +#define CPIA2_VC_VC_OHSIZE 0xCA + +#define CPIA2_VC_VC_OVSIZE 0xCB + +#define CPIA2_VC_VC_HCROP 0xCC + +#define CPIA2_VC_VC_VCROP 0xCD + +#define CPIA2_VC_VC_HPHASE 0xCE + +#define CPIA2_VC_VC_VPHASE 0xCF + +#define CPIA2_VC_VC_HISPAN 0xD0 + +#define CPIA2_VC_VC_VISPAN 0xD1 + +#define CPIA2_VC_VC_HICROP 0xD2 + +#define CPIA2_VC_VC_VICROP 0xD3 + +#define CPIA2_VC_VC_HFRACT 0xD4 +#define CPIA2_VC_VC_HFRACT_DEN_MASK 0x0F +#define CPIA2_VC_VC_HFRACT_NUM_MASK 0xF0 + +#define CPIA2_VC_VC_VFRACT 0xD5 +#define CPIA2_VC_VC_VFRACT_DEN_MASK 0x0F +#define CPIA2_VC_VC_VFRACT_NUM_MASK 0xF0 + +#define CPIA2_VC_VC_JPEG_OPT 0xD6 +#define CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE 0x01 +#define CPIA2_VC_VC_JPEG_OPT_NO_DC_AUTO_SQUEEZE 0x02 +#define CPIA2_VC_VC_JPEG_OPT_AUTO_SQUEEZE 0x04 +#define CPIA2_VC_VC_JPEG_OPT_DEFAULT (CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE|\ + CPIA2_VC_VC_JPEG_OPT_AUTO_SQUEEZE) + + +#define CPIA2_VC_VC_CREEP_PERIOD 0xD7 +#define CPIA2_VC_VC_USER_SQUEEZE 0xD8 +#define CPIA2_VC_VC_TARGET_KB 0xD9 + +#define CPIA2_VC_VC_AUTO_SQUEEZE 0xE6 + + +/*** + * VP register set (Bank 2) + ***/ +#define CPIA2_VP_DEVICEH 0 +#define CPIA2_VP_DEVICEL 1 + +#define CPIA2_VP_SYSTEMSTATE 0x02 +#define CPIA2_VP_SYSTEMSTATE_HK_ALIVE 0x01 + +#define CPIA2_VP_SYSTEMCTRL 0x03 +#define CPIA2_VP_SYSTEMCTRL_REQ_CLEAR_ERROR 0x80 +#define CPIA2_VP_SYSTEMCTRL_POWER_DOWN_PLL 0x20 +#define CPIA2_VP_SYSTEMCTRL_REQ_SUSPEND_STATE 0x10 +#define CPIA2_VP_SYSTEMCTRL_REQ_SERIAL_WAKEUP 0x08 +#define CPIA2_VP_SYSTEMCTRL_REQ_AUTOLOAD 0x04 +#define CPIA2_VP_SYSTEMCTRL_HK_CONTROL 0x02 +#define CPIA2_VP_SYSTEMCTRL_POWER_CONTROL 0x01 + +#define CPIA2_VP_SENSOR_FLAGS 0x05 +#define CPIA2_VP_SENSOR_FLAGS_404 0x01 +#define CPIA2_VP_SENSOR_FLAGS_407 0x02 +#define CPIA2_VP_SENSOR_FLAGS_409 0x04 +#define CPIA2_VP_SENSOR_FLAGS_410 0x08 +#define CPIA2_VP_SENSOR_FLAGS_500 0x10 + +#define CPIA2_VP_SENSOR_REV 0x06 + +#define CPIA2_VP_DEVICE_CONFIG 0x07 +#define CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE 0x01 + +#define CPIA2_VP_GPIO_DIRECTION 0x08 +#define CPIA2_VP_GPIO_READ 0xFF +#define CPIA2_VP_GPIO_WRITE 0x00 + +#define CPIA2_VP_GPIO_DATA 0x09 + +#define CPIA2_VP_RAM_ADDR_H 0x0A +#define CPIA2_VP_RAM_ADDR_L 0x0B +#define CPIA2_VP_RAM_DATA 0x0C + +#define CPIA2_VP_PATCH_REV 0x0F + +#define CPIA2_VP4_USER_MODE 0x10 +#define CPIA2_VP5_USER_MODE 0x13 +#define CPIA2_VP_USER_MODE_CIF 0x01 +#define CPIA2_VP_USER_MODE_QCIFDS 0x02 +#define CPIA2_VP_USER_MODE_QCIFPTC 0x04 +#define CPIA2_VP_USER_MODE_QVGADS 0x08 +#define CPIA2_VP_USER_MODE_QVGAPTC 0x10 +#define CPIA2_VP_USER_MODE_VGA 0x20 + +#define CPIA2_VP4_FRAMERATE_REQUEST 0x11 +#define CPIA2_VP5_FRAMERATE_REQUEST 0x14 +#define CPIA2_VP_FRAMERATE_60 0x80 +#define CPIA2_VP_FRAMERATE_50 0x40 +#define CPIA2_VP_FRAMERATE_30 0x20 +#define CPIA2_VP_FRAMERATE_25 0x10 +#define CPIA2_VP_FRAMERATE_15 0x08 +#define CPIA2_VP_FRAMERATE_12_5 0x04 +#define CPIA2_VP_FRAMERATE_7_5 0x02 +#define CPIA2_VP_FRAMERATE_6_25 0x01 + +#define CPIA2_VP4_USER_EFFECTS 0x12 +#define CPIA2_VP5_USER_EFFECTS 0x15 +#define CPIA2_VP_USER_EFFECTS_COLBARS 0x01 +#define CPIA2_VP_USER_EFFECTS_COLBARS_GRAD 0x02 +#define CPIA2_VP_USER_EFFECTS_MIRROR 0x04 +#define CPIA2_VP_USER_EFFECTS_FLIP 0x40 // VP5 only + +/* NOTE: CPIA2_VP_EXPOSURE_MODES shares the same register as VP5 User + * Effects */ +#define CPIA2_VP_EXPOSURE_MODES 0x15 +#define CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER 0x20 +#define CPIA2_VP_EXPOSURE_MODES_COMPILE_EXP 0x10 + +#define CPIA2_VP4_EXPOSURE_TARGET 0x16 // VP4 +#define CPIA2_VP5_EXPOSURE_TARGET 0x20 // VP5 + +#define CPIA2_VP_FLICKER_MODES 0x1B +#define CPIA2_VP_FLICKER_MODES_50HZ 0x80 +#define CPIA2_VP_FLICKER_MODES_CUSTOM_FLT_FFREQ 0x40 +#define CPIA2_VP_FLICKER_MODES_NEVER_FLICKER 0x20 +#define CPIA2_VP_FLICKER_MODES_INHIBIT_RUB 0x10 +#define CPIA2_VP_FLICKER_MODES_ADJUST_LINE_FREQ 0x08 +#define CPIA2_VP_FLICKER_MODES_CUSTOM_INT_FFREQ 0x04 + +#define CPIA2_VP_UMISC 0x1D +#define CPIA2_VP_UMISC_FORCE_MONO 0x80 +#define CPIA2_VP_UMISC_FORCE_ID_MASK 0x40 +#define CPIA2_VP_UMISC_INHIBIT_AUTO_FGS 0x20 +#define CPIA2_VP_UMISC_INHIBIT_AUTO_DIMS 0x08 +#define CPIA2_VP_UMISC_OPT_FOR_SENSOR_DS 0x04 +#define CPIA2_VP_UMISC_INHIBIT_AUTO_MODE_INT 0x02 + +#define CPIA2_VP5_ANTIFLKRSETUP 0x22 //34 + +#define CPIA2_VP_INTERPOLATION 0x24 +#define CPIA2_VP_INTERPOLATION_EVEN_FIRST 0x40 +#define CPIA2_VP_INTERPOLATION_HJOG 0x20 +#define CPIA2_VP_INTERPOLATION_VJOG 0x10 + +#define CPIA2_VP_GAMMA 0x25 +#define CPIA2_VP_DEFAULT_GAMMA 0x10 + +#define CPIA2_VP_YRANGE 0x26 + +#define CPIA2_VP_SATURATION 0x27 + +#define CPIA2_VP5_MYBLACK_LEVEL 0x3A //58 +#define CPIA2_VP5_MCYRANGE 0x3B //59 +#define CPIA2_VP5_MYCEILING 0x3C //60 +#define CPIA2_VP5_MCUVSATURATION 0x3D //61 + + +#define CPIA2_VP_REHASH_VALUES 0x60 + + +/*** + * Common sensor registers + ***/ +#define CPIA2_SENSOR_DEVICE_H 0x00 +#define CPIA2_SENSOR_DEVICE_L 0x01 + +#define CPIA2_SENSOR_DATA_FORMAT 0x16 +#define CPIA2_SENSOR_DATA_FORMAT_HMIRROR 0x08 +#define CPIA2_SENSOR_DATA_FORMAT_VMIRROR 0x10 + +#define CPIA2_SENSOR_CR1 0x76 +#define CPIA2_SENSOR_CR1_STAND_BY 0x01 +#define CPIA2_SENSOR_CR1_DOWN_RAMP_GEN 0x02 +#define CPIA2_SENSOR_CR1_DOWN_COLUMN_ADC 0x04 +#define CPIA2_SENSOR_CR1_DOWN_CAB_REGULATOR 0x08 +#define CPIA2_SENSOR_CR1_DOWN_AUDIO_REGULATOR 0x10 +#define CPIA2_SENSOR_CR1_DOWN_VRT_AMP 0x20 +#define CPIA2_SENSOR_CR1_DOWN_BAND_GAP 0x40 + +#endif diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c new file mode 100644 index 000000000000..f4da02941493 --- /dev/null +++ b/drivers/media/video/cpia2/cpia2_usb.c @@ -0,0 +1,907 @@ +/**************************************************************************** + * + * Filename: cpia2_usb.c + * + * Copyright 2001, STMicrolectronics, Inc. + * Contact: steve.miller@st.com + * + * Description: + * This is a USB driver for CPia2 based video cameras. + * The infrastructure of this driver is based on the cpia usb driver by + * Jochen Scharrlach and Johannes Erdfeldt. + * + * 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. + * + * Stripped of 2.4 stuff ready for main kernel submit by + * Alan Cox + ****************************************************************************/ + +#include +#include +#include + +#include "cpia2.h" + +static int frame_sizes[] = { + 0, // USBIF_CMDONLY + 0, // USBIF_BULK + 128, // USBIF_ISO_1 + 384, // USBIF_ISO_2 + 640, // USBIF_ISO_3 + 768, // USBIF_ISO_4 + 896, // USBIF_ISO_5 + 1023, // USBIF_ISO_6 +}; + +#define FRAMES_PER_DESC 10 +#define FRAME_SIZE_PER_DESC frame_sizes[cam->cur_alt] + +static void process_frame(struct camera_data *cam); +static void cpia2_usb_complete(struct urb *urb, struct pt_regs *); +static int cpia2_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id); +static void cpia2_usb_disconnect(struct usb_interface *intf); + +static void free_sbufs(struct camera_data *cam); +static void add_APPn(struct camera_data *cam); +static void add_COM(struct camera_data *cam); +static int submit_urbs(struct camera_data *cam); +static int set_alternate(struct camera_data *cam, unsigned int alt); +static int configure_transfer_mode(struct camera_data *cam, unsigned int alt); + +static struct usb_device_id cpia2_id_table[] = { + {USB_DEVICE(0x0553, 0x0100)}, + {USB_DEVICE(0x0553, 0x0140)}, + {USB_DEVICE(0x0553, 0x0151)}, /* STV0676 */ + {} /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, cpia2_id_table); + +static struct usb_driver cpia2_driver = { + .name = "cpia2", + .probe = cpia2_usb_probe, + .disconnect = cpia2_usb_disconnect, + .id_table = cpia2_id_table +}; + + +/****************************************************************************** + * + * process_frame + * + *****************************************************************************/ +static void process_frame(struct camera_data *cam) +{ + static int frame_count = 0; + + unsigned char *inbuff = cam->workbuff->data; + + DBG("Processing frame #%d, current:%d\n", + cam->workbuff->num, cam->curbuff->num); + + if(cam->workbuff->length > cam->workbuff->max_length) + cam->workbuff->max_length = cam->workbuff->length; + + if ((inbuff[0] == 0xFF) && (inbuff[1] == 0xD8)) { + frame_count++; + } else { + cam->workbuff->status = FRAME_ERROR; + DBG("Start of frame not found\n"); + return; + } + + /*** + * Now the output buffer should have a JPEG image in it. + ***/ + if(!cam->first_image_seen) { + /* Always skip the first image after streaming + * starts. It is almost certainly corrupt. */ + cam->first_image_seen = 1; + cam->workbuff->status = FRAME_EMPTY; + return; + } + if (cam->workbuff->length > 3) { + if(cam->mmapped && + cam->workbuff->length < cam->workbuff->max_length) { + /* No junk in the buffers */ + memset(cam->workbuff->data+cam->workbuff->length, + 0, cam->workbuff->max_length- + cam->workbuff->length); + } + cam->workbuff->max_length = cam->workbuff->length; + cam->workbuff->status = FRAME_READY; + + if(!cam->mmapped && cam->num_frames > 2) { + /* During normal reading, the most recent + * frame will be read. If the current frame + * hasn't started reading yet, it will never + * be read, so mark it empty. If the buffer is + * mmapped, or we have few buffers, we need to + * wait for the user to free the buffer. + * + * NOTE: This is not entirely foolproof with 3 + * buffers, but it would take an EXTREMELY + * overloaded system to cause problems (possible + * image data corruption). Basically, it would + * need to take more time to execute cpia2_read + * than it would for the camera to send + * cam->num_frames-2 frames before problems + * could occur. + */ + cam->curbuff->status = FRAME_EMPTY; + } + cam->curbuff = cam->workbuff; + cam->workbuff = cam->workbuff->next; + DBG("Changed buffers, work:%d, current:%d\n", + cam->workbuff->num, cam->curbuff->num); + return; + } else { + DBG("Not enough data for an image.\n"); + } + + cam->workbuff->status = FRAME_ERROR; + return; +} + +/****************************************************************************** + * + * add_APPn + * + * Adds a user specified APPn record + *****************************************************************************/ +static void add_APPn(struct camera_data *cam) +{ + if(cam->APP_len > 0) { + cam->workbuff->data[cam->workbuff->length++] = 0xFF; + cam->workbuff->data[cam->workbuff->length++] = 0xE0+cam->APPn; + cam->workbuff->data[cam->workbuff->length++] = 0; + cam->workbuff->data[cam->workbuff->length++] = cam->APP_len+2; + memcpy(cam->workbuff->data+cam->workbuff->length, + cam->APP_data, cam->APP_len); + cam->workbuff->length += cam->APP_len; + } +} + +/****************************************************************************** + * + * add_COM + * + * Adds a user specified COM record + *****************************************************************************/ +static void add_COM(struct camera_data *cam) +{ + if(cam->COM_len > 0) { + cam->workbuff->data[cam->workbuff->length++] = 0xFF; + cam->workbuff->data[cam->workbuff->length++] = 0xFE; + cam->workbuff->data[cam->workbuff->length++] = 0; + cam->workbuff->data[cam->workbuff->length++] = cam->COM_len+2; + memcpy(cam->workbuff->data+cam->workbuff->length, + cam->COM_data, cam->COM_len); + cam->workbuff->length += cam->COM_len; + } +} + +/****************************************************************************** + * + * cpia2_usb_complete + * + * callback when incoming packet is received + *****************************************************************************/ +static void cpia2_usb_complete(struct urb *urb, struct pt_regs *regs) +{ + int i; + unsigned char *cdata; + static int frame_ready = false; + struct camera_data *cam = (struct camera_data *) urb->context; + + if (urb->status!=0) { + if (!(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN)) + { + DBG("urb->status = %d!\n", urb->status); + } + DBG("Stopping streaming\n"); + return; + } + + if (!cam->streaming || !cam->present || cam->open_count == 0) { + LOG("Will now stop the streaming: streaming = %d, " + "present=%d, open_count=%d\n", + cam->streaming, cam->present, cam->open_count); + return; + } + + /*** + * Packet collater + ***/ + //DBG("Collating %d packets\n", urb->number_of_packets); + for (i = 0; i < urb->number_of_packets; i++) { + u16 checksum, iso_checksum; + int j; + int n = urb->iso_frame_desc[i].actual_length; + int st = urb->iso_frame_desc[i].status; + + if(cam->workbuff->status == FRAME_READY) { + struct framebuf *ptr; + /* Try to find an available buffer */ + DBG("workbuff full, searching\n"); + for (ptr = cam->workbuff->next; + ptr != cam->workbuff; + ptr = ptr->next) + { + if (ptr->status == FRAME_EMPTY) { + ptr->status = FRAME_READING; + ptr->length = 0; + break; + } + } + if (ptr == cam->workbuff) + break; /* No READING or EMPTY buffers left */ + + cam->workbuff = ptr; + } + + if (cam->workbuff->status == FRAME_EMPTY || + cam->workbuff->status == FRAME_ERROR) { + cam->workbuff->status = FRAME_READING; + cam->workbuff->length = 0; + } + + //DBG(" Packet %d length = %d, status = %d\n", i, n, st); + cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + + if (st) { + LOG("cpia2 data error: [%d] len=%d, status = %d\n", + i, n, st); + if(!ALLOW_CORRUPT) + cam->workbuff->status = FRAME_ERROR; + continue; + } + + if(n<=2) + continue; + + checksum = 0; + for(j=0; jworkbuff->status = FRAME_ERROR; + continue; + } + } + n -= 2; + + if(cam->workbuff->status != FRAME_READING) { + if((0xFF == cdata[0] && 0xD8 == cdata[1]) || + (0xD8 == cdata[0] && 0xFF == cdata[1] && + 0 != cdata[2])) { + /* frame is skipped, but increment total + * frame count anyway */ + cam->frame_count++; + } + DBG("workbuff not reading, status=%d\n", + cam->workbuff->status); + continue; + } + + if (cam->frame_size < cam->workbuff->length + n) { + ERR("buffer overflow! length: %d, n: %d\n", + cam->workbuff->length, n); + cam->workbuff->status = FRAME_ERROR; + if(cam->workbuff->length > cam->workbuff->max_length) + cam->workbuff->max_length = + cam->workbuff->length; + continue; + } + + if (cam->workbuff->length == 0) { + int data_offset; + if ((0xD8 == cdata[0]) && (0xFF == cdata[1])) { + data_offset = 1; + } else if((0xFF == cdata[0]) && (0xD8 == cdata[1]) + && (0xFF == cdata[2])) { + data_offset = 2; + } else { + DBG("Ignoring packet, not beginning!\n"); + continue; + } + DBG("Start of frame pattern found\n"); + do_gettimeofday(&cam->workbuff->timestamp); + cam->workbuff->seq = cam->frame_count++; + cam->workbuff->data[0] = 0xFF; + cam->workbuff->data[1] = 0xD8; + cam->workbuff->length = 2; + add_APPn(cam); + add_COM(cam); + memcpy(cam->workbuff->data+cam->workbuff->length, + cdata+data_offset, n-data_offset); + cam->workbuff->length += n-data_offset; + } else if (cam->workbuff->length > 0) { + memcpy(cam->workbuff->data + cam->workbuff->length, + cdata, n); + cam->workbuff->length += n; + } + + if ((cam->workbuff->length >= 3) && + (cam->workbuff->data[cam->workbuff->length - 3] == 0xFF) && + (cam->workbuff->data[cam->workbuff->length - 2] == 0xD9) && + (cam->workbuff->data[cam->workbuff->length - 1] == 0xFF)) { + frame_ready = true; + cam->workbuff->data[cam->workbuff->length - 1] = 0; + cam->workbuff->length -= 1; + } else if ((cam->workbuff->length >= 2) && + (cam->workbuff->data[cam->workbuff->length - 2] == 0xFF) && + (cam->workbuff->data[cam->workbuff->length - 1] == 0xD9)) { + frame_ready = true; + } + + if (frame_ready) { + DBG("Workbuff image size = %d\n",cam->workbuff->length); + process_frame(cam); + + frame_ready = false; + + if (waitqueue_active(&cam->wq_stream)) + wake_up_interruptible(&cam->wq_stream); + } + } + + if(cam->streaming) { + /* resubmit */ + urb->dev = cam->dev; + if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0) + ERR("%s: usb_submit_urb ret %d!\n", __func__, i); + } +} + +/****************************************************************************** + * + * configure_transfer_mode + * + *****************************************************************************/ +static int configure_transfer_mode(struct camera_data *cam, unsigned int alt) +{ + static unsigned char iso_regs[8][4] = { + {0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00}, + {0xB9, 0x00, 0x00, 0x7E}, + {0xB9, 0x00, 0x01, 0x7E}, + {0xB9, 0x00, 0x02, 0x7E}, + {0xB9, 0x00, 0x02, 0xFE}, + {0xB9, 0x00, 0x03, 0x7E}, + {0xB9, 0x00, 0x03, 0xFD} + }; + struct cpia2_command cmd; + unsigned char reg; + + if(!cam->present) + return -ENODEV; + + /*** + * Write the isoc registers according to the alternate selected + ***/ + cmd.direction = TRANSFER_WRITE; + cmd.buffer.block_data[0] = iso_regs[alt][0]; + cmd.buffer.block_data[1] = iso_regs[alt][1]; + cmd.buffer.block_data[2] = iso_regs[alt][2]; + cmd.buffer.block_data[3] = iso_regs[alt][3]; + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; + cmd.start = CPIA2_VC_USB_ISOLIM; + cmd.reg_count = 4; + cpia2_send_command(cam, &cmd); + + /*** + * Enable relevant streams before starting polling. + * First read USB Stream Config Register. + ***/ + cmd.direction = TRANSFER_READ; + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; + cmd.start = CPIA2_VC_USB_STRM; + cmd.reg_count = 1; + cpia2_send_command(cam, &cmd); + reg = cmd.buffer.block_data[0]; + + /* Clear iso, bulk, and int */ + reg &= ~(CPIA2_VC_USB_STRM_BLK_ENABLE | + CPIA2_VC_USB_STRM_ISO_ENABLE | + CPIA2_VC_USB_STRM_INT_ENABLE); + + if (alt == USBIF_BULK) { + DBG("Enabling bulk xfer\n"); + reg |= CPIA2_VC_USB_STRM_BLK_ENABLE; /* Enable Bulk */ + cam->xfer_mode = XFER_BULK; + } else if (alt >= USBIF_ISO_1) { + DBG("Enabling ISOC xfer\n"); + reg |= CPIA2_VC_USB_STRM_ISO_ENABLE; + cam->xfer_mode = XFER_ISOC; + } + + cmd.buffer.block_data[0] = reg; + cmd.direction = TRANSFER_WRITE; + cmd.start = CPIA2_VC_USB_STRM; + cmd.reg_count = 1; + cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; + cpia2_send_command(cam, &cmd); + + return 0; +} + +/****************************************************************************** + * + * cpia2_usb_change_streaming_alternate + * + *****************************************************************************/ +int cpia2_usb_change_streaming_alternate(struct camera_data *cam, + unsigned int alt) +{ + int ret = 0; + + if(alt < USBIF_ISO_1 || alt > USBIF_ISO_6) + return -EINVAL; + + if(alt == cam->params.camera_state.stream_mode) + return 0; + + cpia2_usb_stream_pause(cam); + + configure_transfer_mode(cam, alt); + + cam->params.camera_state.stream_mode = alt; + + /* Reset the camera to prevent image quality degradation */ + cpia2_reset_camera(cam); + + cpia2_usb_stream_resume(cam); + + return ret; +} + +/****************************************************************************** + * + * set_alternate + * + *****************************************************************************/ +int set_alternate(struct camera_data *cam, unsigned int alt) +{ + int ret = 0; + + if(alt == cam->cur_alt) + return 0; + + if (cam->cur_alt != USBIF_CMDONLY) { + DBG("Changing from alt %d to %d\n", cam->cur_alt, USBIF_CMDONLY); + ret = usb_set_interface(cam->dev, cam->iface, USBIF_CMDONLY); + if (ret != 0) + return ret; + } + if (alt != USBIF_CMDONLY) { + DBG("Changing from alt %d to %d\n", USBIF_CMDONLY, alt); + ret = usb_set_interface(cam->dev, cam->iface, alt); + if (ret != 0) + return ret; + } + + cam->old_alt = cam->cur_alt; + cam->cur_alt = alt; + + return ret; +} + +/****************************************************************************** + * + * free_sbufs + * + * Free all cam->sbuf[]. All non-NULL .data and .urb members that are non-NULL + * are assumed to be allocated. Non-NULL .urb members are also assumed to be + * submitted (and must therefore be killed before they are freed). + *****************************************************************************/ +static void free_sbufs(struct camera_data *cam) +{ + int i; + + for (i = 0; i < NUM_SBUF; i++) { + if(cam->sbuf[i].urb) { + usb_kill_urb(cam->sbuf[i].urb); + usb_free_urb(cam->sbuf[i].urb); + cam->sbuf[i].urb = NULL; + } + if(cam->sbuf[i].data) { + kfree(cam->sbuf[i].data); + cam->sbuf[i].data = NULL; + } + } +} + +/******* +* Convenience functions +*******/ +/**************************************************************************** + * + * write_packet + * + ***************************************************************************/ +static int write_packet(struct usb_device *udev, + u8 request, u8 * registers, u16 start, size_t size) +{ + if (!registers || size <= 0) + return -EINVAL; + + return usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + request, + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + start, /* value */ + 0, /* index */ + registers, /* buffer */ + size, + HZ); +} + +/**************************************************************************** + * + * read_packet + * + ***************************************************************************/ +static int read_packet(struct usb_device *udev, + u8 request, u8 * registers, u16 start, size_t size) +{ + if (!registers || size <= 0) + return -EINVAL; + + return usb_control_msg(udev, + usb_rcvctrlpipe(udev, 0), + request, + USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE, + start, /* value */ + 0, /* index */ + registers, /* buffer */ + size, + HZ); +} + +/****************************************************************************** + * + * cpia2_usb_transfer_cmd + * + *****************************************************************************/ +int cpia2_usb_transfer_cmd(struct camera_data *cam, + void *registers, + u8 request, u8 start, u8 count, u8 direction) +{ + int err = 0; + struct usb_device *udev = cam->dev; + + if (!udev) { + ERR("%s: Internal driver error: udev is NULL\n", __func__); + return -EINVAL; + } + + if (!registers) { + ERR("%s: Internal driver error: register array is NULL\n", __func__); + return -EINVAL; + } + + if (direction == TRANSFER_READ) { + err = read_packet(udev, request, (u8 *)registers, start, count); + if (err > 0) + err = 0; + } else if (direction == TRANSFER_WRITE) { + err =write_packet(udev, request, (u8 *)registers, start, count); + if (err < 0) { + LOG("Control message failed, err val = %d\n", err); + LOG("Message: request = 0x%0X, start = 0x%0X\n", + request, start); + LOG("Message: count = %d, register[0] = 0x%0X\n", + count, ((unsigned char *) registers)[0]); + } else + err=0; + } else { + LOG("Unexpected first byte of direction: %d\n", + direction); + return -EINVAL; + } + + if(err != 0) + LOG("Unexpected error: %d\n", err); + return err; +} + + +/****************************************************************************** + * + * submit_urbs + * + *****************************************************************************/ +static int submit_urbs(struct camera_data *cam) +{ + struct urb *urb; + int fx, err, i; + + for(i=0; isbuf[i].data) + continue; + cam->sbuf[i].data = + kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); + if (!cam->sbuf[i].data) { + return -ENOMEM; + } + } + + /* We double buffer the Isoc lists, and also know the polling + * interval is every frame (1 == (1 << (bInterval -1))). + */ + for(i=0; isbuf[i].urb) { + continue; + } + urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); + if (!urb) { + return -ENOMEM; + } + + cam->sbuf[i].urb = urb; + urb->dev = cam->dev; + urb->context = cam; + urb->pipe = usb_rcvisocpipe(cam->dev, 1 /*ISOC endpoint*/); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = cam->sbuf[i].data; + urb->complete = cpia2_usb_complete; + urb->number_of_packets = FRAMES_PER_DESC; + urb->interval = 1; + urb->transfer_buffer_length = + FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; + + for (fx = 0; fx < FRAMES_PER_DESC; fx++) { + urb->iso_frame_desc[fx].offset = + FRAME_SIZE_PER_DESC * fx; + urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; + } + } + + + /* Queue the ISO urbs, and resubmit in the completion handler */ + for(i=0; isbuf[i].urb, GFP_KERNEL); + if (err) { + ERR("usb_submit_urb[%d]() = %d\n", i, err); + return err; + } + } + + return 0; +} + +/****************************************************************************** + * + * cpia2_usb_stream_start + * + *****************************************************************************/ +int cpia2_usb_stream_start(struct camera_data *cam, unsigned int alternate) +{ + int ret; + int old_alt; + + if(cam->streaming) + return 0; + + if (cam->flush) { + int i; + DBG("Flushing buffers\n"); + for(i=0; inum_frames; ++i) { + cam->buffers[i].status = FRAME_EMPTY; + cam->buffers[i].length = 0; + } + cam->curbuff = &cam->buffers[0]; + cam->workbuff = cam->curbuff->next; + cam->flush = false; + } + + old_alt = cam->params.camera_state.stream_mode; + cam->params.camera_state.stream_mode = 0; + ret = cpia2_usb_change_streaming_alternate(cam, alternate); + if (ret < 0) { + int ret2; + ERR("cpia2_usb_change_streaming_alternate() = %d!\n", ret); + cam->params.camera_state.stream_mode = old_alt; + ret2 = set_alternate(cam, USBIF_CMDONLY); + if (ret2 < 0) { + ERR("cpia2_usb_change_streaming_alternate(%d) =%d has already " + "failed. Then tried to call " + "set_alternate(USBIF_CMDONLY) = %d.\n", + alternate, ret, ret2); + } + } else { + cam->frame_count = 0; + cam->streaming = 1; + ret = cpia2_usb_stream_resume(cam); + } + return ret; +} + +/****************************************************************************** + * + * cpia2_usb_stream_pause + * + *****************************************************************************/ +int cpia2_usb_stream_pause(struct camera_data *cam) +{ + int ret = 0; + if(cam->streaming) { + ret = set_alternate(cam, USBIF_CMDONLY); + free_sbufs(cam); + } + return ret; +} + +/****************************************************************************** + * + * cpia2_usb_stream_resume + * + *****************************************************************************/ +int cpia2_usb_stream_resume(struct camera_data *cam) +{ + int ret = 0; + if(cam->streaming) { + cam->first_image_seen = 0; + ret = set_alternate(cam, cam->params.camera_state.stream_mode); + if(ret == 0) { + ret = submit_urbs(cam); + } + } + return ret; +} + +/****************************************************************************** + * + * cpia2_usb_stream_stop + * + *****************************************************************************/ +int cpia2_usb_stream_stop(struct camera_data *cam) +{ + int ret; + ret = cpia2_usb_stream_pause(cam); + cam->streaming = 0; + configure_transfer_mode(cam, 0); + return ret; +} + +/****************************************************************************** + * + * cpia2_usb_probe + * + * Probe and initialize. + *****************************************************************************/ +static int cpia2_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_interface_descriptor *interface; + struct camera_data *cam; + int ret; + + /* A multi-config CPiA2 camera? */ + if (udev->descriptor.bNumConfigurations != 1) + return -ENODEV; + interface = &intf->cur_altsetting->desc; + + /* If we get to this point, we found a CPiA2 camera */ + LOG("CPiA2 USB camera found\n"); + + if((cam = cpia2_init_camera_struct()) == NULL) + return -ENOMEM; + + cam->dev = udev; + cam->iface = interface->bInterfaceNumber; + + ret = set_alternate(cam, USBIF_CMDONLY); + if (ret < 0) { + ERR("%s: usb_set_interface error (ret = %d)\n", __func__, ret); + kfree(cam); + return ret; + } + + if ((ret = cpia2_register_camera(cam)) < 0) { + ERR("%s: Failed to register cpia2 camera (ret = %d)\n", __func__, ret); + kfree(cam); + return ret; + } + + + if((ret = cpia2_init_camera(cam)) < 0) { + ERR("%s: failed to initialize cpia2 camera (ret = %d)\n", __func__, ret); + cpia2_unregister_camera(cam); + kfree(cam); + return ret; + } + LOG(" CPiA Version: %d.%02d (%d.%d)\n", + cam->params.version.firmware_revision_hi, + cam->params.version.firmware_revision_lo, + cam->params.version.asic_id, + cam->params.version.asic_rev); + LOG(" CPiA PnP-ID: %04x:%04x:%04x\n", + cam->params.pnp_id.vendor, + cam->params.pnp_id.product, + cam->params.pnp_id.device_revision); + LOG(" SensorID: %d.(version %d)\n", + cam->params.version.sensor_flags, + cam->params.version.sensor_rev); + + usb_set_intfdata(intf, cam); + + return 0; +} + +/****************************************************************************** + * + * cpia2_disconnect + * + *****************************************************************************/ +static void cpia2_usb_disconnect(struct usb_interface *intf) +{ + struct camera_data *cam = usb_get_intfdata(intf); + usb_set_intfdata(intf, NULL); + cam->present = 0; + + DBG("Stopping stream\n"); + cpia2_usb_stream_stop(cam); + + DBG("Unregistering camera\n"); + cpia2_unregister_camera(cam); + + if(cam->buffers) { + DBG("Wakeup waiting processes\n"); + cam->curbuff->status = FRAME_READY; + cam->curbuff->length = 0; + if (waitqueue_active(&cam->wq_stream)) + wake_up_interruptible(&cam->wq_stream); + } + + DBG("Releasing interface\n"); + usb_driver_release_interface(&cpia2_driver, intf); + + if (cam->open_count == 0) { + DBG("Freeing camera structure\n"); + kfree(cam); + } + + LOG("CPiA2 camera disconnected.\n"); +} + + +/****************************************************************************** + * + * usb_cpia2_init + * + *****************************************************************************/ +int cpia2_usb_init(void) +{ + return usb_register(&cpia2_driver); +} + +/****************************************************************************** + * + * usb_cpia_cleanup + * + *****************************************************************************/ +void cpia2_usb_cleanup(void) +{ + schedule_timeout(2 * HZ); + usb_deregister(&cpia2_driver); +} diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c new file mode 100644 index 000000000000..3480a2ca7cdc --- /dev/null +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -0,0 +1,2104 @@ +/**************************************************************************** + * + * Filename: cpia2_v4l.c + * + * Copyright 2001, STMicrolectronics, Inc. + * Contact: steve.miller@st.com + * Copyright 2001,2005, Scott J. Bertin + * + * Description: + * This is a USB driver for CPia2 based video cameras. + * The infrastructure of this driver is based on the cpia usb driver by + * Jochen Scharrlach and Johannes Erdfeldt. + * + * 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. + * + * Stripped of 2.4 stuff ready for main kernel submit by + * Alan Cox + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "cpia2.h" +#include "cpia2dev.h" + + +//#define _CPIA2_DEBUG_ + +#define MAKE_STRING_1(x) #x +#define MAKE_STRING(x) MAKE_STRING_1(x) + +static int video_nr = -1; +module_param(video_nr, int, 0); +MODULE_PARM_DESC(video_nr,"video device to register (0=/dev/video0, etc)"); + +static int buffer_size = 68*1024; +module_param(buffer_size, int, 0); +MODULE_PARM_DESC(buffer_size, "Size for each frame buffer in bytes (default 68k)"); + +static int num_buffers = 3; +module_param(num_buffers, int, 0); +MODULE_PARM_DESC(num_buffers, "Number of frame buffers (1-" + MAKE_STRING(VIDEO_MAX_FRAME) ", default 3)"); + +static int alternate = DEFAULT_ALT; +module_param(alternate, int, 0); +MODULE_PARM_DESC(alternate, "USB Alternate (" MAKE_STRING(USBIF_ISO_1) "-" + MAKE_STRING(USBIF_ISO_6) ", default " + MAKE_STRING(DEFAULT_ALT) ")"); + +static int flicker_freq = 60; +module_param(flicker_freq, int, 0); +MODULE_PARM_DESC(flicker_freq, "Flicker frequency (" MAKE_STRING(50) "or" + MAKE_STRING(60) ", default " + MAKE_STRING(60) ")"); + +static int flicker_mode = NEVER_FLICKER; +module_param(flicker_mode, int, 0); +MODULE_PARM_DESC(flicker_mode, + "Flicker supression (" MAKE_STRING(NEVER_FLICKER) "or" + MAKE_STRING(ANTI_FLICKER_ON) ", default " + MAKE_STRING(NEVER_FLICKER) ")"); + +MODULE_AUTHOR("Steve Miller (STMicroelectronics) "); +MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras"); +MODULE_SUPPORTED_DEVICE("video"); +MODULE_LICENSE("GPL"); + +#define ABOUT "V4L-Driver for Vision CPiA2 based cameras" + +#ifndef VID_HARDWARE_CPIA2 +#error "VID_HARDWARE_CPIA2 should have been defined in linux/videodev.h" +#endif + +struct control_menu_info { + int value; + char name[32]; +}; + +static struct control_menu_info framerate_controls[] = +{ + { CPIA2_VP_FRAMERATE_6_25, "6.25 fps" }, + { CPIA2_VP_FRAMERATE_7_5, "7.5 fps" }, + { CPIA2_VP_FRAMERATE_12_5, "12.5 fps" }, + { CPIA2_VP_FRAMERATE_15, "15 fps" }, + { CPIA2_VP_FRAMERATE_25, "25 fps" }, + { CPIA2_VP_FRAMERATE_30, "30 fps" }, +}; +#define NUM_FRAMERATE_CONTROLS (sizeof(framerate_controls)/sizeof(framerate_controls[0])) + +static struct control_menu_info flicker_controls[] = +{ + { NEVER_FLICKER, "Off" }, + { FLICKER_50, "50 Hz" }, + { FLICKER_60, "60 Hz" }, +}; +#define NUM_FLICKER_CONTROLS (sizeof(flicker_controls)/sizeof(flicker_controls[0])) + +static struct control_menu_info lights_controls[] = +{ + { 0, "Off" }, + { 64, "Top" }, + { 128, "Bottom" }, + { 192, "Both" }, +}; +#define NUM_LIGHTS_CONTROLS (sizeof(lights_controls)/sizeof(lights_controls[0])) +#define GPIO_LIGHTS_MASK 192 + +static struct v4l2_queryctrl controls[] = { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = DEFAULT_BRIGHTNESS, + }, + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = DEFAULT_CONTRAST, + }, + { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = DEFAULT_SATURATION, + }, + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Mirror Horizontally", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = CPIA2_CID_TARGET_KB, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Target KB", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = DEFAULT_TARGET_KB, + }, + { + .id = CPIA2_CID_GPIO, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "GPIO", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 0, + }, + { + .id = CPIA2_CID_FLICKER_MODE, + .type = V4L2_CTRL_TYPE_MENU, + .name = "Flicker Reduction", + .minimum = 0, + .maximum = NUM_FLICKER_CONTROLS-1, + .step = 1, + .default_value = 0, + }, + { + .id = CPIA2_CID_FRAMERATE, + .type = V4L2_CTRL_TYPE_MENU, + .name = "Framerate", + .minimum = 0, + .maximum = NUM_FRAMERATE_CONTROLS-1, + .step = 1, + .default_value = NUM_FRAMERATE_CONTROLS-1, + }, + { + .id = CPIA2_CID_USB_ALT, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "USB Alternate", + .minimum = USBIF_ISO_1, + .maximum = USBIF_ISO_6, + .step = 1, + .default_value = DEFAULT_ALT, + }, + { + .id = CPIA2_CID_LIGHTS, + .type = V4L2_CTRL_TYPE_MENU, + .name = "Lights", + .minimum = 0, + .maximum = NUM_LIGHTS_CONTROLS-1, + .step = 1, + .default_value = 0, + }, + { + .id = CPIA2_CID_RESET_CAMERA, + .type = V4L2_CTRL_TYPE_BUTTON, + .name = "Reset Camera", + .minimum = 0, + .maximum = 0, + .step = 0, + .default_value = 0, + }, +}; +#define NUM_CONTROLS (sizeof(controls)/sizeof(controls[0])) + + +/****************************************************************************** + * + * cpia2_open + * + *****************************************************************************/ +static int cpia2_open(struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct camera_data *cam = video_get_drvdata(dev); + int retval = 0; + + if (!cam) { + ERR("Internal error, camera_data not found!\n"); + return -ENODEV; + } + + if(down_interruptible(&cam->busy_lock)) + return -ERESTARTSYS; + + if(!cam->present) { + retval = -ENODEV; + goto err_return; + } + + if (cam->open_count > 0) { + goto skip_init; + } + + if (cpia2_allocate_buffers(cam)) { + retval = -ENOMEM; + goto err_return; + } + + /* reset the camera */ + if (cpia2_reset_camera(cam) < 0) { + retval = -EIO; + goto err_return; + } + + cam->APP_len = 0; + cam->COM_len = 0; + +skip_init: + { + struct cpia2_fh *fh = kmalloc(sizeof(*fh),GFP_KERNEL); + if(!fh) { + retval = -ENOMEM; + goto err_return; + } + file->private_data = fh; + fh->prio = V4L2_PRIORITY_UNSET; + v4l2_prio_open(&cam->prio, &fh->prio); + fh->mmapped = 0; + } + + ++cam->open_count; + + cpia2_dbg_dump_registers(cam); + +err_return: + up(&cam->busy_lock); + return retval; +} + +/****************************************************************************** + * + * cpia2_close + * + *****************************************************************************/ +static int cpia2_close(struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct camera_data *cam = video_get_drvdata(dev); + struct cpia2_fh *fh = file->private_data; + + down(&cam->busy_lock); + + if (cam->present && + (cam->open_count == 1 + || fh->prio == V4L2_PRIORITY_RECORD + )) { + cpia2_usb_stream_stop(cam); + + if(cam->open_count == 1) { + /* save camera state for later open */ + cpia2_save_camera_state(cam); + + cpia2_set_low_power(cam); + cpia2_free_buffers(cam); + } + } + + { + if(fh->mmapped) + cam->mmapped = 0; + v4l2_prio_close(&cam->prio,&fh->prio); + file->private_data = NULL; + kfree(fh); + } + + if (--cam->open_count == 0) { + cpia2_free_buffers(cam); + if (!cam->present) { + video_unregister_device(dev); + kfree(cam); + } + } + + up(&cam->busy_lock); + + return 0; +} + +/****************************************************************************** + * + * cpia2_v4l_read + * + *****************************************************************************/ +static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, + loff_t *off) +{ + struct video_device *dev = video_devdata(file); + struct camera_data *cam = video_get_drvdata(dev); + int noblock = file->f_flags&O_NONBLOCK; + + struct cpia2_fh *fh = file->private_data; + + if(!cam) + return -EINVAL; + + /* Priority check */ + if(fh->prio != V4L2_PRIORITY_RECORD) { + return -EBUSY; + } + + return cpia2_read(cam, buf, count, noblock); +} + + +/****************************************************************************** + * + * cpia2_v4l_poll + * + *****************************************************************************/ +static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait) +{ + struct video_device *dev = video_devdata(filp); + struct camera_data *cam = video_get_drvdata(dev); + + struct cpia2_fh *fh = filp->private_data; + + if(!cam) + return POLLERR; + + /* Priority check */ + if(fh->prio != V4L2_PRIORITY_RECORD) { + return POLLERR; + } + + return cpia2_poll(cam, filp, wait); +} + + +/****************************************************************************** + * + * ioctl_cap_query + * + *****************************************************************************/ +static int ioctl_cap_query(void *arg, struct camera_data *cam) +{ + struct video_capability *vc; + int retval = 0; + vc = arg; + + if (cam->params.pnp_id.product == 0x151) + strcpy(vc->name, "QX5 Microscope"); + else + strcpy(vc->name, "CPiA2 Camera"); + + vc->type = VID_TYPE_CAPTURE | VID_TYPE_MJPEG_ENCODER; + vc->channels = 1; + vc->audios = 0; + vc->minwidth = 176; /* VIDEOSIZE_QCIF */ + vc->minheight = 144; + switch (cam->params.version.sensor_flags) { + case CPIA2_VP_SENSOR_FLAGS_500: + vc->maxwidth = STV_IMAGE_VGA_COLS; + vc->maxheight = STV_IMAGE_VGA_ROWS; + break; + case CPIA2_VP_SENSOR_FLAGS_410: + vc->maxwidth = STV_IMAGE_CIF_COLS; + vc->maxheight = STV_IMAGE_CIF_ROWS; + break; + default: + return -EINVAL; + } + + return retval; +} + +/****************************************************************************** + * + * ioctl_get_channel + * + *****************************************************************************/ +static int ioctl_get_channel(void *arg) +{ + int retval = 0; + struct video_channel *v; + v = arg; + + if (v->channel != 0) + return -EINVAL; + + v->channel = 0; + strcpy(v->name, "Camera"); + v->tuners = 0; + v->flags = 0; + v->type = VIDEO_TYPE_CAMERA; + v->norm = 0; + + return retval; +} + +/****************************************************************************** + * + * ioctl_set_channel + * + *****************************************************************************/ +static int ioctl_set_channel(void *arg) +{ + struct video_channel *v; + int retval = 0; + v = arg; + + if (retval == 0 && v->channel != 0) + retval = -EINVAL; + + return retval; +} + +/****************************************************************************** + * + * ioctl_set_image_prop + * + *****************************************************************************/ +static int ioctl_set_image_prop(void *arg, struct camera_data *cam) +{ + struct video_picture *vp; + int retval = 0; + vp = arg; + + /* brightness, color, contrast need no check 0-65535 */ + memcpy(&cam->vp, vp, sizeof(*vp)); + + /* update cam->params.colorParams */ + cam->params.color_params.brightness = vp->brightness / 256; + cam->params.color_params.saturation = vp->colour / 256; + cam->params.color_params.contrast = vp->contrast / 256; + + DBG("Requested params: bright 0x%X, sat 0x%X, contrast 0x%X\n", + cam->params.color_params.brightness, + cam->params.color_params.saturation, + cam->params.color_params.contrast); + + cpia2_set_color_params(cam); + + return retval; +} + +static int sync(struct camera_data *cam, int frame_nr) +{ + struct framebuf *frame = &cam->buffers[frame_nr]; + + while (1) { + if (frame->status == FRAME_READY) + return 0; + + if (!cam->streaming) { + frame->status = FRAME_READY; + frame->length = 0; + return 0; + } + + up(&cam->busy_lock); + wait_event_interruptible(cam->wq_stream, + !cam->streaming || + frame->status == FRAME_READY); + down(&cam->busy_lock); + if (signal_pending(current)) + return -ERESTARTSYS; + if(!cam->present) + return -ENOTTY; + } +} + +/****************************************************************************** + * + * ioctl_set_window_size + * + *****************************************************************************/ +static int ioctl_set_window_size(void *arg, struct camera_data *cam, + struct cpia2_fh *fh) +{ + /* copy_from_user, check validity, copy to internal structure */ + struct video_window *vw; + int frame, err; + vw = arg; + + if (vw->clipcount != 0) /* clipping not supported */ + return -EINVAL; + + if (vw->clips != NULL) /* clipping not supported */ + return -EINVAL; + + /* Ensure that only this process can change the format. */ + err = v4l2_prio_change(&cam->prio, &fh->prio, V4L2_PRIORITY_RECORD); + if(err != 0) + return err; + + cam->pixelformat = V4L2_PIX_FMT_JPEG; + + /* Be sure to supply the Huffman tables, this isn't MJPEG */ + cam->params.compression.inhibit_htables = 0; + + /* we set the video window to something smaller or equal to what + * is requested by the user??? + */ + DBG("Requested width = %d, height = %d\n", vw->width, vw->height); + if (vw->width != cam->vw.width || vw->height != cam->vw.height) { + cam->vw.width = vw->width; + cam->vw.height = vw->height; + cam->params.roi.width = vw->width; + cam->params.roi.height = vw->height; + cpia2_set_format(cam); + } + + for (frame = 0; frame < cam->num_frames; ++frame) { + if (cam->buffers[frame].status == FRAME_READING) + if ((err = sync(cam, frame)) < 0) + return err; + + cam->buffers[frame].status = FRAME_EMPTY; + } + + return 0; +} + +/****************************************************************************** + * + * ioctl_get_mbuf + * + *****************************************************************************/ +static int ioctl_get_mbuf(void *arg, struct camera_data *cam) +{ + struct video_mbuf *vm; + int i; + vm = arg; + + memset(vm, 0, sizeof(*vm)); + vm->size = cam->frame_size*cam->num_frames; + vm->frames = cam->num_frames; + for (i = 0; i < cam->num_frames; i++) + vm->offsets[i] = cam->frame_size * i; + + return 0; +} + +/****************************************************************************** + * + * ioctl_mcapture + * + *****************************************************************************/ +static int ioctl_mcapture(void *arg, struct camera_data *cam, + struct cpia2_fh *fh) +{ + struct video_mmap *vm; + int video_size, err; + vm = arg; + + if (vm->frame < 0 || vm->frame >= cam->num_frames) + return -EINVAL; + + /* set video size */ + video_size = cpia2_match_video_size(vm->width, vm->height); + if (cam->video_size < 0) { + return -EINVAL; + } + + /* Ensure that only this process can change the format. */ + err = v4l2_prio_change(&cam->prio, &fh->prio, V4L2_PRIORITY_RECORD); + if(err != 0) + return err; + + if (video_size != cam->video_size) { + cam->video_size = video_size; + cam->params.roi.width = vm->width; + cam->params.roi.height = vm->height; + cpia2_set_format(cam); + } + + if (cam->buffers[vm->frame].status == FRAME_READING) + if ((err=sync(cam, vm->frame)) < 0) + return err; + + cam->buffers[vm->frame].status = FRAME_EMPTY; + + return cpia2_usb_stream_start(cam,cam->params.camera_state.stream_mode); +} + +/****************************************************************************** + * + * ioctl_sync + * + *****************************************************************************/ +static int ioctl_sync(void *arg, struct camera_data *cam) +{ + int frame; + + frame = *(int*)arg; + + if (frame < 0 || frame >= cam->num_frames) + return -EINVAL; + + return sync(cam, frame); +} + + +/****************************************************************************** + * + * ioctl_set_gpio + * + *****************************************************************************/ + +static int ioctl_set_gpio(void *arg, struct camera_data *cam) +{ + __u32 gpio_val; + + gpio_val = *(__u32*) arg; + + if (gpio_val &~ 0xFFU) + return -EINVAL; + + return cpia2_set_gpio(cam, (unsigned char)gpio_val); +} + +/****************************************************************************** + * + * ioctl_querycap + * + * V4L2 device capabilities + * + *****************************************************************************/ + +static int ioctl_querycap(void *arg, struct camera_data *cam) +{ + struct v4l2_capability *vc = arg; + + memset(vc, 0, sizeof(*vc)); + strcpy(vc->driver, "cpia2"); + + if (cam->params.pnp_id.product == 0x151) + strcpy(vc->card, "QX5 Microscope"); + else + strcpy(vc->card, "CPiA2 Camera"); + switch (cam->params.pnp_id.device_type) { + case DEVICE_STV_672: + strcat(vc->card, " (672/"); + break; + case DEVICE_STV_676: + strcat(vc->card, " (676/"); + break; + default: + strcat(vc->card, " (???/"); + break; + } + switch (cam->params.version.sensor_flags) { + case CPIA2_VP_SENSOR_FLAGS_404: + strcat(vc->card, "404)"); + break; + case CPIA2_VP_SENSOR_FLAGS_407: + strcat(vc->card, "407)"); + break; + case CPIA2_VP_SENSOR_FLAGS_409: + strcat(vc->card, "409)"); + break; + case CPIA2_VP_SENSOR_FLAGS_410: + strcat(vc->card, "410)"); + break; + case CPIA2_VP_SENSOR_FLAGS_500: + strcat(vc->card, "500)"); + break; + default: + strcat(vc->card, "???)"); + break; + } + + if (usb_make_path(cam->dev, vc->bus_info, sizeof(vc->bus_info)) <0) + memset(vc->bus_info,0, sizeof(vc->bus_info)); + + vc->version = KERNEL_VERSION(CPIA2_MAJ_VER, CPIA2_MIN_VER, + CPIA2_PATCH_VER); + + vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; + + return 0; +} + +/****************************************************************************** + * + * ioctl_input + * + * V4L2 input get/set/enumerate + * + *****************************************************************************/ + +static int ioctl_input(unsigned int ioclt_nr,void *arg,struct camera_data *cam) +{ + struct v4l2_input *i = arg; + + if(ioclt_nr != VIDIOC_G_INPUT) { + if (i->index != 0) + return -EINVAL; + } + + memset(i, 0, sizeof(*i)); + strcpy(i->name, "Camera"); + i->type = V4L2_INPUT_TYPE_CAMERA; + + return 0; +} + +/****************************************************************************** + * + * ioctl_enum_fmt + * + * V4L2 format enumerate + * + *****************************************************************************/ + +static int ioctl_enum_fmt(void *arg,struct camera_data *cam) +{ + struct v4l2_fmtdesc *f = arg; + int index = f->index; + + if (index < 0 || index > 1) + return -EINVAL; + + memset(f, 0, sizeof(*f)); + f->index = index; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->flags = V4L2_FMT_FLAG_COMPRESSED; + switch(index) { + case 0: + strcpy(f->description, "MJPEG"); + f->pixelformat = V4L2_PIX_FMT_MJPEG; + break; + case 1: + strcpy(f->description, "JPEG"); + f->pixelformat = V4L2_PIX_FMT_JPEG; + break; + default: + return -EINVAL; + } + + return 0; +} + +/****************************************************************************** + * + * ioctl_try_fmt + * + * V4L2 format try + * + *****************************************************************************/ + +static int ioctl_try_fmt(void *arg,struct camera_data *cam) +{ + struct v4l2_format *f = arg; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG && + f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) + return -EINVAL; + + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.sizeimage = cam->frame_size; + f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; + f->fmt.pix.priv = 0; + + switch (cpia2_match_video_size(f->fmt.pix.width, f->fmt.pix.height)) { + case VIDEOSIZE_VGA: + f->fmt.pix.width = 640; + f->fmt.pix.height = 480; + break; + case VIDEOSIZE_CIF: + f->fmt.pix.width = 352; + f->fmt.pix.height = 288; + break; + case VIDEOSIZE_QVGA: + f->fmt.pix.width = 320; + f->fmt.pix.height = 240; + break; + case VIDEOSIZE_288_216: + f->fmt.pix.width = 288; + f->fmt.pix.height = 216; + break; + case VIDEOSIZE_256_192: + f->fmt.pix.width = 256; + f->fmt.pix.height = 192; + break; + case VIDEOSIZE_224_168: + f->fmt.pix.width = 224; + f->fmt.pix.height = 168; + break; + case VIDEOSIZE_192_144: + f->fmt.pix.width = 192; + f->fmt.pix.height = 144; + break; + case VIDEOSIZE_QCIF: + default: + f->fmt.pix.width = 176; + f->fmt.pix.height = 144; + break; + } + + return 0; +} + +/****************************************************************************** + * + * ioctl_set_fmt + * + * V4L2 format set + * + *****************************************************************************/ + +static int ioctl_set_fmt(void *arg,struct camera_data *cam, struct cpia2_fh *fh) +{ + struct v4l2_format *f = arg; + int err, frame; + + err = ioctl_try_fmt(arg, cam); + if(err != 0) + return err; + + /* Ensure that only this process can change the format. */ + err = v4l2_prio_change(&cam->prio, &fh->prio, V4L2_PRIORITY_RECORD); + if(err != 0) { + return err; + } + + cam->pixelformat = f->fmt.pix.pixelformat; + + /* NOTE: This should be set to 1 for MJPEG, but some apps don't handle + * the missing Huffman table properly. */ + cam->params.compression.inhibit_htables = 0; + /*f->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG;*/ + + /* we set the video window to something smaller or equal to what + * is requested by the user??? + */ + DBG("Requested width = %d, height = %d\n", + f->fmt.pix.width, f->fmt.pix.height); + if (f->fmt.pix.width != cam->vw.width || + f->fmt.pix.height != cam->vw.height) { + cam->vw.width = f->fmt.pix.width; + cam->vw.height = f->fmt.pix.height; + cam->params.roi.width = f->fmt.pix.width; + cam->params.roi.height = f->fmt.pix.height; + cpia2_set_format(cam); + } + + for (frame = 0; frame < cam->num_frames; ++frame) { + if (cam->buffers[frame].status == FRAME_READING) + if ((err = sync(cam, frame)) < 0) + return err; + + cam->buffers[frame].status = FRAME_EMPTY; + } + + return 0; +} + +/****************************************************************************** + * + * ioctl_get_fmt + * + * V4L2 format get + * + *****************************************************************************/ + +static int ioctl_get_fmt(void *arg,struct camera_data *cam) +{ + struct v4l2_format *f = arg; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + f->fmt.pix.width = cam->vw.width; + f->fmt.pix.height = cam->vw.height; + f->fmt.pix.pixelformat = cam->pixelformat; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.sizeimage = cam->frame_size; + f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; + f->fmt.pix.priv = 0; + + return 0; +} + +/****************************************************************************** + * + * ioctl_cropcap + * + * V4L2 query cropping capabilities + * NOTE: cropping is currently disabled + * + *****************************************************************************/ + +static int ioctl_cropcap(void *arg,struct camera_data *cam) +{ + struct v4l2_cropcap *c = arg; + + if (c->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + c->bounds.left = 0; + c->bounds.top = 0; + c->bounds.width = cam->vw.width; + c->bounds.height = cam->vw.height; + c->defrect.left = 0; + c->defrect.top = 0; + c->defrect.width = cam->vw.width; + c->defrect.height = cam->vw.height; + c->pixelaspect.numerator = 1; + c->pixelaspect.denominator = 1; + + return 0; +} + +/****************************************************************************** + * + * ioctl_queryctrl + * + * V4L2 query possible control variables + * + *****************************************************************************/ + +static int ioctl_queryctrl(void *arg,struct camera_data *cam) +{ + struct v4l2_queryctrl *c = arg; + int i; + + for(i=0; iid == controls[i].id) { + memcpy(c, controls+i, sizeof(*c)); + break; + } + } + + if(i == NUM_CONTROLS) + return -EINVAL; + + /* Some devices have additional limitations */ + switch(c->id) { + case V4L2_CID_BRIGHTNESS: + /*** + * Don't let the register be set to zero - bug in VP4 + * flash of full brightness + ***/ + if (cam->params.pnp_id.device_type == DEVICE_STV_672) + c->minimum = 1; + break; + case V4L2_CID_VFLIP: + // VP5 Only + if(cam->params.pnp_id.device_type == DEVICE_STV_672) + c->flags |= V4L2_CTRL_FLAG_DISABLED; + break; + case CPIA2_CID_FRAMERATE: + if(cam->params.pnp_id.device_type == DEVICE_STV_672 && + cam->params.version.sensor_flags==CPIA2_VP_SENSOR_FLAGS_500){ + // Maximum 15fps + int i; + for(i=0; imaximum; ++i) { + if(framerate_controls[i].value == + CPIA2_VP_FRAMERATE_15) { + c->maximum = i; + c->default_value = i; + } + } + } + break; + case CPIA2_CID_FLICKER_MODE: + // Flicker control only valid for 672. + if(cam->params.pnp_id.device_type != DEVICE_STV_672) + c->flags |= V4L2_CTRL_FLAG_DISABLED; + break; + case CPIA2_CID_LIGHTS: + // Light control only valid for the QX5 Microscope. + if(cam->params.pnp_id.product != 0x151) + c->flags |= V4L2_CTRL_FLAG_DISABLED; + break; + default: + break; + } + + return 0; +} + +/****************************************************************************** + * + * ioctl_querymenu + * + * V4L2 query possible control variables + * + *****************************************************************************/ + +static int ioctl_querymenu(void *arg,struct camera_data *cam) +{ + struct v4l2_querymenu *m = arg; + + memset(m->name, 0, sizeof(m->name)); + m->reserved = 0; + + switch(m->id) { + case CPIA2_CID_FLICKER_MODE: + if(m->index < 0 || m->index >= NUM_FLICKER_CONTROLS) + return -EINVAL; + + strcpy(m->name, flicker_controls[m->index].name); + break; + case CPIA2_CID_FRAMERATE: + { + int maximum = NUM_FRAMERATE_CONTROLS - 1; + if(cam->params.pnp_id.device_type == DEVICE_STV_672 && + cam->params.version.sensor_flags==CPIA2_VP_SENSOR_FLAGS_500){ + // Maximum 15fps + int i; + for(i=0; iindex < 0 || m->index > maximum) + return -EINVAL; + + strcpy(m->name, framerate_controls[m->index].name); + break; + } + case CPIA2_CID_LIGHTS: + if(m->index < 0 || m->index >= NUM_LIGHTS_CONTROLS) + return -EINVAL; + + strcpy(m->name, lights_controls[m->index].name); + break; + default: + return -EINVAL; + } + + return 0; +} + +/****************************************************************************** + * + * ioctl_g_ctrl + * + * V4L2 get the value of a control variable + * + *****************************************************************************/ + +static int ioctl_g_ctrl(void *arg,struct camera_data *cam) +{ + struct v4l2_control *c = arg; + + switch(c->id) { + case V4L2_CID_BRIGHTNESS: + cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS, + TRANSFER_READ, 0); + c->value = cam->params.color_params.brightness; + break; + case V4L2_CID_CONTRAST: + cpia2_do_command(cam, CPIA2_CMD_GET_CONTRAST, + TRANSFER_READ, 0); + c->value = cam->params.color_params.contrast; + break; + case V4L2_CID_SATURATION: + cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION, + TRANSFER_READ, 0); + c->value = cam->params.color_params.saturation; + break; + case V4L2_CID_HFLIP: + cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, + TRANSFER_READ, 0); + c->value = (cam->params.vp_params.user_effects & + CPIA2_VP_USER_EFFECTS_MIRROR) != 0; + break; + case V4L2_CID_VFLIP: + cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, + TRANSFER_READ, 0); + c->value = (cam->params.vp_params.user_effects & + CPIA2_VP_USER_EFFECTS_FLIP) != 0; + break; + case CPIA2_CID_TARGET_KB: + c->value = cam->params.vc_params.target_kb; + break; + case CPIA2_CID_GPIO: + cpia2_do_command(cam, CPIA2_CMD_GET_VP_GPIO_DATA, + TRANSFER_READ, 0); + c->value = cam->params.vp_params.gpio_data; + break; + case CPIA2_CID_FLICKER_MODE: + { + int i, mode; + cpia2_do_command(cam, CPIA2_CMD_GET_FLICKER_MODES, + TRANSFER_READ, 0); + if(cam->params.flicker_control.cam_register & + CPIA2_VP_FLICKER_MODES_NEVER_FLICKER) { + mode = NEVER_FLICKER; + } else { + if(cam->params.flicker_control.cam_register & + CPIA2_VP_FLICKER_MODES_50HZ) { + mode = FLICKER_50; + } else { + mode = FLICKER_60; + } + } + for(i=0; ivalue = i; + break; + } + } + if(i == NUM_FLICKER_CONTROLS) + return -EINVAL; + break; + } + case CPIA2_CID_FRAMERATE: + { + int maximum = NUM_FRAMERATE_CONTROLS - 1; + int i; + for(i=0; i<= maximum; i++) { + if(cam->params.vp_params.frame_rate == + framerate_controls[i].value) + break; + } + if(i > maximum) + return -EINVAL; + c->value = i; + break; + } + case CPIA2_CID_USB_ALT: + c->value = cam->params.camera_state.stream_mode; + break; + case CPIA2_CID_LIGHTS: + { + int i; + cpia2_do_command(cam, CPIA2_CMD_GET_VP_GPIO_DATA, + TRANSFER_READ, 0); + for(i=0; iparams.vp_params.gpio_data&GPIO_LIGHTS_MASK) == + lights_controls[i].value) { + break; + } + } + if(i == NUM_LIGHTS_CONTROLS) + return -EINVAL; + c->value = i; + break; + } + case CPIA2_CID_RESET_CAMERA: + return -EINVAL; + default: + return -EINVAL; + } + + DBG("Get control id:%d, value:%d\n", c->id, c->value); + + return 0; +} + +/****************************************************************************** + * + * ioctl_s_ctrl + * + * V4L2 set the value of a control variable + * + *****************************************************************************/ + +static int ioctl_s_ctrl(void *arg,struct camera_data *cam) +{ + struct v4l2_control *c = arg; + int i; + int retval = 0; + + DBG("Set control id:%d, value:%d\n", c->id, c->value); + + /* Check that the value is in range */ + for(i=0; iid == controls[i].id) { + if(c->value < controls[i].minimum || + c->value > controls[i].maximum) { + return -EINVAL; + } + break; + } + } + if(i == NUM_CONTROLS) + return -EINVAL; + + switch(c->id) { + case V4L2_CID_BRIGHTNESS: + cpia2_set_brightness(cam, c->value); + break; + case V4L2_CID_CONTRAST: + cpia2_set_contrast(cam, c->value); + break; + case V4L2_CID_SATURATION: + cpia2_set_saturation(cam, c->value); + break; + case V4L2_CID_HFLIP: + cpia2_set_property_mirror(cam, c->value); + break; + case V4L2_CID_VFLIP: + cpia2_set_property_flip(cam, c->value); + break; + case CPIA2_CID_TARGET_KB: + retval = cpia2_set_target_kb(cam, c->value); + break; + case CPIA2_CID_GPIO: + retval = cpia2_set_gpio(cam, c->value); + break; + case CPIA2_CID_FLICKER_MODE: + retval = cpia2_set_flicker_mode(cam, + flicker_controls[c->value].value); + break; + case CPIA2_CID_FRAMERATE: + retval = cpia2_set_fps(cam, framerate_controls[c->value].value); + break; + case CPIA2_CID_USB_ALT: + retval = cpia2_usb_change_streaming_alternate(cam, c->value); + break; + case CPIA2_CID_LIGHTS: + retval = cpia2_set_gpio(cam, lights_controls[c->value].value); + break; + case CPIA2_CID_RESET_CAMERA: + cpia2_usb_stream_pause(cam); + cpia2_reset_camera(cam); + cpia2_usb_stream_resume(cam); + break; + default: + retval = -EINVAL; + } + + return retval; +} + +/****************************************************************************** + * + * ioctl_g_jpegcomp + * + * V4L2 get the JPEG compression parameters + * + *****************************************************************************/ + +static int ioctl_g_jpegcomp(void *arg,struct camera_data *cam) +{ + struct v4l2_jpegcompression *parms = arg; + + memset(parms, 0, sizeof(*parms)); + + parms->quality = 80; // TODO: Can this be made meaningful? + + parms->jpeg_markers = V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI; + if(!cam->params.compression.inhibit_htables) { + parms->jpeg_markers |= V4L2_JPEG_MARKER_DHT; + } + + parms->APPn = cam->APPn; + parms->APP_len = cam->APP_len; + if(cam->APP_len > 0) { + memcpy(parms->APP_data, cam->APP_data, cam->APP_len); + parms->jpeg_markers |= V4L2_JPEG_MARKER_APP; + } + + parms->COM_len = cam->COM_len; + if(cam->COM_len > 0) { + memcpy(parms->COM_data, cam->COM_data, cam->COM_len); + parms->jpeg_markers |= JPEG_MARKER_COM; + } + + DBG("G_JPEGCOMP APP_len:%d COM_len:%d\n", + parms->APP_len, parms->COM_len); + + return 0; +} + +/****************************************************************************** + * + * ioctl_s_jpegcomp + * + * V4L2 set the JPEG compression parameters + * NOTE: quality and some jpeg_markers are ignored. + * + *****************************************************************************/ + +static int ioctl_s_jpegcomp(void *arg,struct camera_data *cam) +{ + struct v4l2_jpegcompression *parms = arg; + + DBG("S_JPEGCOMP APP_len:%d COM_len:%d\n", + parms->APP_len, parms->COM_len); + + cam->params.compression.inhibit_htables = + !(parms->jpeg_markers & V4L2_JPEG_MARKER_DHT); + + if(parms->APP_len != 0) { + if(parms->APP_len > 0 && + parms->APP_len <= sizeof(cam->APP_data) && + parms->APPn >= 0 && parms->APPn <= 15) { + cam->APPn = parms->APPn; + cam->APP_len = parms->APP_len; + memcpy(cam->APP_data, parms->APP_data, parms->APP_len); + } else { + LOG("Bad APPn Params n=%d len=%d\n", + parms->APPn, parms->APP_len); + return -EINVAL; + } + } else { + cam->APP_len = 0; + } + + if(parms->COM_len != 0) { + if(parms->COM_len > 0 && + parms->COM_len <= sizeof(cam->COM_data)) { + cam->COM_len = parms->COM_len; + memcpy(cam->COM_data, parms->COM_data, parms->COM_len); + } else { + LOG("Bad COM_len=%d\n", parms->COM_len); + return -EINVAL; + } + } + + return 0; +} + +/****************************************************************************** + * + * ioctl_reqbufs + * + * V4L2 Initiate memory mapping. + * NOTE: The user's request is ignored. For now the buffers are fixed. + * + *****************************************************************************/ + +static int ioctl_reqbufs(void *arg,struct camera_data *cam) +{ + struct v4l2_requestbuffers *req = arg; + + if(req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + req->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + DBG("REQBUFS requested:%d returning:%d\n", req->count, cam->num_frames); + req->count = cam->num_frames; + memset(&req->reserved, 0, sizeof(req->reserved)); + + return 0; +} + +/****************************************************************************** + * + * ioctl_querybuf + * + * V4L2 Query memory buffer status. + * + *****************************************************************************/ + +static int ioctl_querybuf(void *arg,struct camera_data *cam) +{ + struct v4l2_buffer *buf = arg; + + if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + buf->index > cam->num_frames) + return -EINVAL; + + buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; + buf->length = cam->frame_size; + + buf->memory = V4L2_MEMORY_MMAP; + + if(cam->mmapped) + buf->flags = V4L2_BUF_FLAG_MAPPED; + else + buf->flags = 0; + + switch (cam->buffers[buf->index].status) { + case FRAME_EMPTY: + case FRAME_ERROR: + case FRAME_READING: + buf->bytesused = 0; + buf->flags = V4L2_BUF_FLAG_QUEUED; + break; + case FRAME_READY: + buf->bytesused = cam->buffers[buf->index].length; + buf->timestamp = cam->buffers[buf->index].timestamp; + buf->sequence = cam->buffers[buf->index].seq; + buf->flags = V4L2_BUF_FLAG_DONE; + break; + } + + DBG("QUERYBUF index:%d offset:%d flags:%d seq:%d bytesused:%d\n", + buf->index, buf->m.offset, buf->flags, buf->sequence, + buf->bytesused); + + return 0; +} + +/****************************************************************************** + * + * ioctl_qbuf + * + * V4L2 User is freeing buffer + * + *****************************************************************************/ + +static int ioctl_qbuf(void *arg,struct camera_data *cam) +{ + struct v4l2_buffer *buf = arg; + + if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + buf->memory != V4L2_MEMORY_MMAP || + buf->index > cam->num_frames) + return -EINVAL; + + DBG("QBUF #%d\n", buf->index); + + if(cam->buffers[buf->index].status == FRAME_READY) + cam->buffers[buf->index].status = FRAME_EMPTY; + + return 0; +} + +/****************************************************************************** + * + * find_earliest_filled_buffer + * + * Helper for ioctl_dqbuf. Find the next ready buffer. + * + *****************************************************************************/ + +static int find_earliest_filled_buffer(struct camera_data *cam) +{ + int i; + int found = -1; + for (i=0; inum_frames; i++) { + if(cam->buffers[i].status == FRAME_READY) { + if(found < 0) { + found = i; + } else { + /* find which buffer is earlier */ + struct timeval *tv1, *tv2; + tv1 = &cam->buffers[i].timestamp; + tv2 = &cam->buffers[found].timestamp; + if(tv1->tv_sec < tv2->tv_sec || + (tv1->tv_sec == tv2->tv_sec && + tv1->tv_usec < tv2->tv_usec)) + found = i; + } + } + } + return found; +} + +/****************************************************************************** + * + * ioctl_dqbuf + * + * V4L2 User is asking for a filled buffer. + * + *****************************************************************************/ + +static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file) +{ + struct v4l2_buffer *buf = arg; + int frame; + + if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + buf->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + frame = find_earliest_filled_buffer(cam); + + if(frame < 0 && file->f_flags&O_NONBLOCK) + return -EAGAIN; + + if(frame < 0) { + /* Wait for a frame to become available */ + struct framebuf *cb=cam->curbuff; + up(&cam->busy_lock); + wait_event_interruptible(cam->wq_stream, + !cam->present || + (cb=cam->curbuff)->status == FRAME_READY); + down(&cam->busy_lock); + if (signal_pending(current)) + return -ERESTARTSYS; + if(!cam->present) + return -ENOTTY; + frame = cb->num; + } + + + buf->index = frame; + buf->bytesused = cam->buffers[buf->index].length; + buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE; + buf->field = V4L2_FIELD_NONE; + buf->timestamp = cam->buffers[buf->index].timestamp; + buf->sequence = cam->buffers[buf->index].seq; + buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; + buf->length = cam->frame_size; + buf->input = 0; + buf->reserved = 0; + memset(&buf->timecode, 0, sizeof(buf->timecode)); + + DBG("DQBUF #%d status:%d seq:%d length:%d\n", buf->index, + cam->buffers[buf->index].status, buf->sequence, buf->bytesused); + + return 0; +} + +/****************************************************************************** + * + * cpia2_ioctl + * + *****************************************************************************/ +static int cpia2_do_ioctl(struct inode *inode, struct file *file, + unsigned int ioctl_nr, void *arg) +{ + struct video_device *dev = video_devdata(file); + struct camera_data *cam = video_get_drvdata(dev); + int retval = 0; + + if (!cam) + return -ENOTTY; + + /* make this _really_ smp-safe */ + if (down_interruptible(&cam->busy_lock)) + return -ERESTARTSYS; + + if (!cam->present) { + up(&cam->busy_lock); + return -ENODEV; + } + + /* Priority check */ + switch (ioctl_nr) { + case VIDIOCSWIN: + case VIDIOCMCAPTURE: + case VIDIOC_S_FMT: + { + struct cpia2_fh *fh = file->private_data; + retval = v4l2_prio_check(&cam->prio, &fh->prio); + if(retval) { + up(&cam->busy_lock); + return retval; + } + break; + } + case VIDIOCGMBUF: + case VIDIOCSYNC: + { + struct cpia2_fh *fh = file->private_data; + if(fh->prio != V4L2_PRIORITY_RECORD) { + up(&cam->busy_lock); + return -EBUSY; + } + break; + } + default: + break; + } + + switch (ioctl_nr) { + case VIDIOCGCAP: /* query capabilites */ + retval = ioctl_cap_query(arg, cam); + break; + + case VIDIOCGCHAN: /* get video source - we are a camera, nothing else */ + retval = ioctl_get_channel(arg); + break; + case VIDIOCSCHAN: /* set video source - we are a camera, nothing else */ + retval = ioctl_set_channel(arg); + break; + case VIDIOCGPICT: /* image properties */ + memcpy(arg, &cam->vp, sizeof(struct video_picture)); + break; + case VIDIOCSPICT: + retval = ioctl_set_image_prop(arg, cam); + break; + case VIDIOCGWIN: /* get/set capture window */ + memcpy(arg, &cam->vw, sizeof(struct video_window)); + break; + case VIDIOCSWIN: + retval = ioctl_set_window_size(arg, cam, file->private_data); + break; + case VIDIOCGMBUF: /* mmap interface */ + retval = ioctl_get_mbuf(arg, cam); + break; + case VIDIOCMCAPTURE: + retval = ioctl_mcapture(arg, cam, file->private_data); + break; + case VIDIOCSYNC: + retval = ioctl_sync(arg, cam); + break; + /* pointless to implement overlay with this camera */ + case VIDIOCCAPTURE: + case VIDIOCGFBUF: + case VIDIOCSFBUF: + case VIDIOCKEY: + retval = -EINVAL; + break; + + /* tuner interface - we have none */ + case VIDIOCGTUNER: + case VIDIOCSTUNER: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + retval = -EINVAL; + break; + + /* audio interface - we have none */ + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + retval = -EINVAL; + break; + + /* CPIA2 extension to Video4Linux API */ + case CPIA2_IOC_SET_GPIO: + retval = ioctl_set_gpio(arg, cam); + break; + case VIDIOC_QUERYCAP: + retval = ioctl_querycap(arg,cam); + break; + + case VIDIOC_ENUMINPUT: + case VIDIOC_G_INPUT: + case VIDIOC_S_INPUT: + retval = ioctl_input(ioctl_nr, arg,cam); + break; + + case VIDIOC_ENUM_FMT: + retval = ioctl_enum_fmt(arg,cam); + break; + case VIDIOC_TRY_FMT: + retval = ioctl_try_fmt(arg,cam); + break; + case VIDIOC_G_FMT: + retval = ioctl_get_fmt(arg,cam); + break; + case VIDIOC_S_FMT: + retval = ioctl_set_fmt(arg,cam,file->private_data); + break; + + case VIDIOC_CROPCAP: + retval = ioctl_cropcap(arg,cam); + break; + case VIDIOC_G_CROP: + case VIDIOC_S_CROP: + // TODO: I think cropping can be implemented - SJB + retval = -EINVAL; + break; + + case VIDIOC_QUERYCTRL: + retval = ioctl_queryctrl(arg,cam); + break; + case VIDIOC_QUERYMENU: + retval = ioctl_querymenu(arg,cam); + break; + case VIDIOC_G_CTRL: + retval = ioctl_g_ctrl(arg,cam); + break; + case VIDIOC_S_CTRL: + retval = ioctl_s_ctrl(arg,cam); + break; + + case VIDIOC_G_JPEGCOMP: + retval = ioctl_g_jpegcomp(arg,cam); + break; + case VIDIOC_S_JPEGCOMP: + retval = ioctl_s_jpegcomp(arg,cam); + break; + + case VIDIOC_G_PRIORITY: + { + struct cpia2_fh *fh = file->private_data; + *(enum v4l2_priority*)arg = fh->prio; + break; + } + case VIDIOC_S_PRIORITY: + { + struct cpia2_fh *fh = file->private_data; + enum v4l2_priority prio; + prio = *(enum v4l2_priority*)arg; + if(cam->streaming && + prio != fh->prio && + fh->prio == V4L2_PRIORITY_RECORD) { + /* Can't drop record priority while streaming */ + retval = -EBUSY; + } else if(prio == V4L2_PRIORITY_RECORD && + prio != fh->prio && + v4l2_prio_max(&cam->prio) == V4L2_PRIORITY_RECORD) { + /* Only one program can record at a time */ + retval = -EBUSY; + } else { + retval = v4l2_prio_change(&cam->prio, &fh->prio, prio); + } + break; + } + + case VIDIOC_REQBUFS: + retval = ioctl_reqbufs(arg,cam); + break; + case VIDIOC_QUERYBUF: + retval = ioctl_querybuf(arg,cam); + break; + case VIDIOC_QBUF: + retval = ioctl_qbuf(arg,cam); + break; + case VIDIOC_DQBUF: + retval = ioctl_dqbuf(arg,cam,file); + break; + case VIDIOC_STREAMON: + { + int type; + DBG("VIDIOC_STREAMON, streaming=%d\n", cam->streaming); + type = *(int*)arg; + if(!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + retval = -EINVAL; + + if(!cam->streaming) { + retval = cpia2_usb_stream_start(cam, + cam->params.camera_state.stream_mode); + } else { + retval = -EINVAL; + } + + break; + } + case VIDIOC_STREAMOFF: + { + int type; + DBG("VIDIOC_STREAMOFF, streaming=%d\n", cam->streaming); + type = *(int*)arg; + if(!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + retval = -EINVAL; + + if(cam->streaming) { + retval = cpia2_usb_stream_stop(cam); + } else { + retval = -EINVAL; + } + + break; + } + + case VIDIOC_ENUMOUTPUT: + case VIDIOC_G_OUTPUT: + case VIDIOC_S_OUTPUT: + case VIDIOC_G_MODULATOR: + case VIDIOC_S_MODULATOR: + + case VIDIOC_ENUMAUDIO: + case VIDIOC_G_AUDIO: + case VIDIOC_S_AUDIO: + + case VIDIOC_ENUMAUDOUT: + case VIDIOC_G_AUDOUT: + case VIDIOC_S_AUDOUT: + + case VIDIOC_ENUMSTD: + case VIDIOC_QUERYSTD: + case VIDIOC_G_STD: + case VIDIOC_S_STD: + + case VIDIOC_G_TUNER: + case VIDIOC_S_TUNER: + case VIDIOC_G_FREQUENCY: + case VIDIOC_S_FREQUENCY: + + case VIDIOC_OVERLAY: + case VIDIOC_G_FBUF: + case VIDIOC_S_FBUF: + + case VIDIOC_G_PARM: + case VIDIOC_S_PARM: + retval = -EINVAL; + break; + default: + retval = -ENOIOCTLCMD; + break; + } + + up(&cam->busy_lock); + return retval; +} + +static int cpia2_ioctl(struct inode *inode, struct file *file, + unsigned int ioctl_nr, unsigned long iarg) +{ + return video_usercopy(inode, file, ioctl_nr, iarg, cpia2_do_ioctl); +} + +/****************************************************************************** + * + * cpia2_mmap + * + *****************************************************************************/ +static int cpia2_mmap(struct file *file, struct vm_area_struct *area) +{ + int retval; + struct video_device *dev = video_devdata(file); + struct camera_data *cam = video_get_drvdata(dev); + + /* Priority check */ + struct cpia2_fh *fh = file->private_data; + if(fh->prio != V4L2_PRIORITY_RECORD) { + return -EBUSY; + } + + retval = cpia2_remap_buffer(cam, area); + + if(!retval) + fh->mmapped = 1; + return retval; +} + +/****************************************************************************** + * + * reset_camera_struct_v4l + * + * Sets all values to the defaults + *****************************************************************************/ +static void reset_camera_struct_v4l(struct camera_data *cam) +{ + /*** + * Fill in the v4l structures. video_cap is filled in inside the VIDIOCCAP + * Ioctl. Here, just do the window and picture stucts. + ***/ + cam->vp.palette = (u16) VIDEO_PALETTE_RGB24; /* Is this right? */ + cam->vp.brightness = (u16) cam->params.color_params.brightness * 256; + cam->vp.colour = (u16) cam->params.color_params.saturation * 256; + cam->vp.contrast = (u16) cam->params.color_params.contrast * 256; + + cam->vw.x = 0; + cam->vw.y = 0; + cam->vw.width = cam->params.roi.width; + cam->vw.height = cam->params.roi.height; + cam->vw.flags = 0; + cam->vw.clipcount = 0; + + cam->frame_size = buffer_size; + cam->num_frames = num_buffers; + + /* FlickerModes */ + cam->params.flicker_control.flicker_mode_req = flicker_mode; + cam->params.flicker_control.mains_frequency = flicker_freq; + + /* streamMode */ + cam->params.camera_state.stream_mode = alternate; + + cam->pixelformat = V4L2_PIX_FMT_JPEG; + v4l2_prio_init(&cam->prio); + return; +} + +/*** + * The v4l video device structure initialized for this device + ***/ +static struct file_operations fops_template = { + .owner= THIS_MODULE, + .open= cpia2_open, + .release= cpia2_close, + .read= cpia2_v4l_read, + .poll= cpia2_v4l_poll, + .ioctl= cpia2_ioctl, + .llseek= no_llseek, + .mmap= cpia2_mmap, +}; + +static struct video_device cpia2_template = { + /* I could not find any place for the old .initialize initializer?? */ + .owner= THIS_MODULE, + .name= "CPiA2 Camera", + .type= VID_TYPE_CAPTURE, + .type2 = V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING, + .hardware= VID_HARDWARE_CPIA2, + .minor= -1, + .fops= &fops_template, + .release= video_device_release, +}; + +/****************************************************************************** + * + * cpia2_register_camera + * + *****************************************************************************/ +int cpia2_register_camera(struct camera_data *cam) +{ + cam->vdev = video_device_alloc(); + if(!cam->vdev) + return -ENOMEM; + + memcpy(cam->vdev, &cpia2_template, sizeof(cpia2_template)); + video_set_drvdata(cam->vdev, cam); + + reset_camera_struct_v4l(cam); + + /* register v4l device */ + if (video_register_device + (cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + ERR("video_register_device failed\n"); + video_device_release(cam->vdev); + return -ENODEV; + } + + return 0; +} + +/****************************************************************************** + * + * cpia2_unregister_camera + * + *****************************************************************************/ +void cpia2_unregister_camera(struct camera_data *cam) +{ + if (!cam->open_count) { + video_unregister_device(cam->vdev); + } else { + LOG("/dev/video%d removed while open, " + "deferring video_unregister_device\n", + cam->vdev->minor); + } +} + +/****************************************************************************** + * + * check_parameters + * + * Make sure that all user-supplied parameters are sensible + *****************************************************************************/ +static void __init check_parameters(void) +{ + if(buffer_size < PAGE_SIZE) { + buffer_size = PAGE_SIZE; + LOG("buffer_size too small, setting to %d\n", buffer_size); + } else if(buffer_size > 1024*1024) { + /* arbitrary upper limiit */ + buffer_size = 1024*1024; + LOG("buffer_size ridiculously large, setting to %d\n", + buffer_size); + } else { + buffer_size += PAGE_SIZE-1; + buffer_size &= ~(PAGE_SIZE-1); + } + + if(num_buffers < 1) { + num_buffers = 1; + LOG("num_buffers too small, setting to %d\n", num_buffers); + } else if(num_buffers > VIDEO_MAX_FRAME) { + num_buffers = VIDEO_MAX_FRAME; + LOG("num_buffers too large, setting to %d\n", num_buffers); + } + + if(alternate < USBIF_ISO_1 || alternate > USBIF_ISO_6) { + alternate = DEFAULT_ALT; + LOG("alternate specified is invalid, using %d\n", alternate); + } + + if (flicker_mode != NEVER_FLICKER && flicker_mode != ANTI_FLICKER_ON) { + flicker_mode = NEVER_FLICKER; + LOG("Flicker mode specified is invalid, using %d\n", + flicker_mode); + } + + if (flicker_freq != FLICKER_50 && flicker_freq != FLICKER_60) { + flicker_freq = FLICKER_60; + LOG("Flicker mode specified is invalid, using %d\n", + flicker_freq); + } + + if(video_nr < -1 || video_nr > 64) { + video_nr = -1; + LOG("invalid video_nr specified, must be -1 to 64\n"); + } + + DBG("Using %d buffers, each %d bytes, alternate=%d\n", + num_buffers, buffer_size, alternate); +} + +/************ Module Stuff ***************/ + + +/****************************************************************************** + * + * cpia2_init/module_init + * + *****************************************************************************/ +int __init cpia2_init(void) +{ + LOG("%s v%d.%d.%d\n", + ABOUT, CPIA2_MAJ_VER, CPIA2_MIN_VER, CPIA2_PATCH_VER); + check_parameters(); + cpia2_usb_init(); + return 0; +} + + +/****************************************************************************** + * + * cpia2_exit/module_exit + * + *****************************************************************************/ +void __exit cpia2_exit(void) +{ + cpia2_usb_cleanup(); + schedule_timeout(2 * HZ); +} + + +int __init cpia2_setup(char *str) +{ + while(str) { + if(!strncmp(str, "buffer_size:", 12)) { + buffer_size = simple_strtoul(str + 13, &str, 10); + } else if(!strncmp(str, "num_buffers:", 12)) { + num_buffers = simple_strtoul(str + 13, &str, 10); + } else if(!strncmp(str, "alternate:", 10)) { + alternate = simple_strtoul(str + 11, &str, 10); + } else if(!strncmp(str, "video_nr:", 9)) { + video_nr = simple_strtoul(str + 10, &str, 10); + } else if(!strncmp(str, "flicker_freq:",13)) { + flicker_freq = simple_strtoul(str + 14, &str, 10); + } else if(!strncmp(str, "flicker_mode:",13)) { + flicker_mode = simple_strtoul(str + 14, &str, 10); + } else { + ++str; + } + } + return 1; +} + +__setup("cpia2=", cpia2_setup); + +module_init(cpia2_init); +module_exit(cpia2_exit); + diff --git a/drivers/media/video/cpia2/cpia2dev.h b/drivers/media/video/cpia2/cpia2dev.h new file mode 100644 index 000000000000..d58097ce0d5e --- /dev/null +++ b/drivers/media/video/cpia2/cpia2dev.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * + * Filename: cpia2dev.h + * + * Copyright 2001, STMicrolectronics, Inc. + * + * Contact: steve.miller@st.com + * + * Description: + * This file provides definitions for applications wanting to use the + * cpia2 driver beyond the generic v4l capabilities. + * + * 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. + * + ****************************************************************************/ + +#ifndef CPIA2_DEV_HEADER +#define CPIA2_DEV_HEADER + +#include + +/*** + * The following defines are ioctl numbers based on video4linux private ioctls, + * which can range from 192 (BASE_VIDIOCPRIVATE) to 255. All of these take int + * args + */ +#define CPIA2_IOC_SET_GPIO _IOW('v', BASE_VIDIOCPRIVATE + 17, __u32) + +/* V4L2 driver specific controls */ +#define CPIA2_CID_TARGET_KB (V4L2_CID_PRIVATE_BASE+0) +#define CPIA2_CID_GPIO (V4L2_CID_PRIVATE_BASE+1) +#define CPIA2_CID_FLICKER_MODE (V4L2_CID_PRIVATE_BASE+2) +#define CPIA2_CID_FRAMERATE (V4L2_CID_PRIVATE_BASE+3) +#define CPIA2_CID_USB_ALT (V4L2_CID_PRIVATE_BASE+4) +#define CPIA2_CID_LIGHTS (V4L2_CID_PRIVATE_BASE+5) +#define CPIA2_CID_RESET_CAMERA (V4L2_CID_PRIVATE_BASE+6) + +#endif diff --git a/drivers/media/video/cpia2/cpia2patch.h b/drivers/media/video/cpia2/cpia2patch.h new file mode 100644 index 000000000000..7f085fbe76fb --- /dev/null +++ b/drivers/media/video/cpia2/cpia2patch.h @@ -0,0 +1,233 @@ +/**************************************************************************** + * + * Filename: cpia2patch.h + * + * Copyright 2001, STMicrolectronics, Inc. + * + * Contact: steve.miller@st.com + * + * Description: + * This file contains patch data for the CPiA2 (stv0672) VP4. + * + * 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. + * + ****************************************************************************/ + +#ifndef CPIA2_PATCH_HEADER +#define CPIA2_PATCH_HEADER + +typedef struct { + unsigned char reg; + unsigned char count; + const unsigned char *data; +} cpia2_patch; + +static const unsigned char start_address_hi[1] = { + 0x01 +}; + +static const unsigned char start_address_lo[1] = { + 0xBC +}; + +static const unsigned char patch_block0[64] = { + 0xE3, 0x02, 0xE3, 0x03, 0xE3, 0x04, 0xE3, 0x05, + 0xE3, 0x06, 0xE3, 0x07, 0x93, 0x44, 0x56, 0xD4, + 0x93, 0x4E, 0x56, 0x51, 0x93, 0x4E, 0x51, 0xD6, + 0x93, 0x4E, 0x4F, 0x54, 0x93, 0x4E, 0x92, 0x4F, + 0x92, 0xA4, 0x93, 0x05, 0x92, 0xF4, 0x93, 0x1B, + 0x92, 0x92, 0x91, 0xE6, 0x92, 0x36, 0x92, 0x74, + 0x92, 0x4A, 0x92, 0x8C, 0x92, 0x8E, 0xC8, 0xD0, + 0x0B, 0x42, 0x02, 0xA0, 0xCA, 0x92, 0x09, 0x02 +}; + +static const unsigned char patch_block1[64] = { + 0xC9, 0x10, 0x0A, 0x0A, 0x0A, 0x81, 0xE3, 0xB8, + 0xE3, 0xB0, 0xE3, 0xA8, 0xE3, 0xA0, 0xE3, 0x98, + 0xE3, 0x90, 0xE1, 0x00, 0xCF, 0xD7, 0x0A, 0x12, + 0xCC, 0x95, 0x08, 0xB2, 0x0A, 0x18, 0xE1, 0x00, + 0x01, 0xEE, 0x0C, 0x08, 0x4A, 0x12, 0xC8, 0x18, + 0xF0, 0x9A, 0xC0, 0x22, 0xF3, 0x1C, 0x4A, 0x13, + 0xF3, 0x14, 0xC8, 0xA0, 0xF2, 0x14, 0xF2, 0x1C, + 0xEB, 0x13, 0xD3, 0xA2, 0x63, 0x16, 0x48, 0x9E +}; + +static const unsigned char patch_block2[64] = { + 0xF0, 0x18, 0xA4, 0x03, 0xF3, 0x93, 0xC0, 0x58, + 0xF7, 0x13, 0x51, 0x9C, 0xE9, 0x20, 0xCF, 0xEF, + 0x63, 0xF9, 0x92, 0x2E, 0xD3, 0x5F, 0x63, 0xFA, + 0x92, 0x2E, 0xD3, 0x67, 0x63, 0xFB, 0x92, 0x2E, + 0xD3, 0x6F, 0xE9, 0x1A, 0x63, 0x16, 0x48, 0xA7, + 0xF0, 0x20, 0xA4, 0x06, 0xF3, 0x94, 0xC0, 0x27, + 0xF7, 0x14, 0xF5, 0x13, 0x51, 0x9D, 0xF6, 0x13, + 0x63, 0x18, 0xC4, 0x20, 0xCB, 0xEF, 0x63, 0xFC +}; + +static const unsigned char patch_block3[64] = { + 0x92, 0x2E, 0xD3, 0x77, 0x63, 0xFD, 0x92, 0x2E, + 0xD3, 0x7F, 0x63, 0xFE, 0x92, 0x2E, 0xD3, 0x87, + 0x63, 0xFF, 0x92, 0x2E, 0xD3, 0x8F, 0x64, 0x38, + 0x92, 0x2E, 0xD3, 0x97, 0x64, 0x39, 0x92, 0x2E, + 0xD3, 0x9F, 0xE1, 0x00, 0xF5, 0x3A, 0xF4, 0x3B, + 0xF7, 0xBF, 0xF2, 0xBC, 0xF2, 0x3D, 0xE1, 0x00, + 0x80, 0x87, 0x90, 0x80, 0x51, 0xD5, 0x02, 0x22, + 0x02, 0x32, 0x4B, 0xD3, 0xF7, 0x11, 0x0B, 0xDA +}; + +static const unsigned char patch_block4[64] = { + 0xE1, 0x00, 0x0E, 0x02, 0x02, 0x40, 0x0D, 0xB5, + 0xE3, 0x02, 0x48, 0x55, 0xE5, 0x12, 0xA4, 0x01, + 0xE8, 0x1B, 0xE3, 0x90, 0xF0, 0x18, 0xA4, 0x01, + 0xE8, 0xBF, 0x8D, 0xB8, 0x4B, 0xD1, 0x4B, 0xD8, + 0x0B, 0xCB, 0x0B, 0xC2, 0xE1, 0x00, 0xE3, 0x02, + 0xE3, 0x03, 0x52, 0xD3, 0x60, 0x59, 0xE6, 0x93, + 0x0D, 0x22, 0x52, 0xD4, 0xE6, 0x93, 0x0D, 0x2A, + 0xE3, 0x98, 0xE3, 0x90, 0xE1, 0x00, 0x02, 0x5D +}; + +static const unsigned char patch_block5[64] = { + 0x02, 0x63, 0xE3, 0x02, 0xC8, 0x12, 0x02, 0xCA, + 0xC8, 0x52, 0x02, 0xC2, 0x82, 0x68, 0xE3, 0x02, + 0xC8, 0x14, 0x02, 0xCA, 0xC8, 0x90, 0x02, 0xC2, + 0x0A, 0xD0, 0xC9, 0x93, 0x0A, 0xDA, 0xCC, 0xD2, + 0x0A, 0xE2, 0x63, 0x12, 0x02, 0xDA, 0x0A, 0x98, + 0x0A, 0xA0, 0x0A, 0xA8, 0xE3, 0x90, 0xE1, 0x00, + 0xE3, 0x02, 0x0A, 0xD0, 0xC9, 0x93, 0x0A, 0xDA, + 0xCC, 0xD2, 0x0A, 0xE2, 0x63, 0x12, 0x02, 0xDA +}; + +static const unsigned char patch_block6[64] = { + 0x0A, 0x98, 0x0A, 0xA0, 0x0A, 0xA8, 0x49, 0x91, + 0xE5, 0x6A, 0xA4, 0x04, 0xC8, 0x12, 0x02, 0xCA, + 0xC8, 0x52, 0x82, 0x89, 0xC8, 0x14, 0x02, 0xCA, + 0xC8, 0x90, 0x02, 0xC2, 0xE3, 0x90, 0xE1, 0x00, + 0x08, 0x60, 0xE1, 0x00, 0x48, 0x53, 0xE8, 0x97, + 0x08, 0x5A, 0xE1, 0x00, 0xE3, 0x02, 0xE3, 0x03, + 0x54, 0xD3, 0x60, 0x59, 0xE6, 0x93, 0x0D, 0x52, + 0xE3, 0x98, 0xE3, 0x90, 0xE1, 0x00, 0x02, 0x9C +}; + +static const unsigned char patch_block7[64] = { + 0xE3, 0x02, 0x55, 0x13, 0x93, 0x17, 0x55, 0x13, + 0x93, 0x17, 0xE3, 0x90, 0xE1, 0x00, 0x75, 0x30, + 0xE3, 0x02, 0xE3, 0x03, 0x55, 0x55, 0x60, 0x59, + 0xE6, 0x93, 0x0D, 0xB2, 0xE3, 0x98, 0xE3, 0x90, + 0xE1, 0x00, 0x02, 0xAE, 0xE7, 0x92, 0xE9, 0x18, + 0xEA, 0x9A, 0xE8, 0x98, 0xE8, 0x10, 0xE8, 0x11, + 0xE8, 0x51, 0xD2, 0xDA, 0xD2, 0xF3, 0xE8, 0x13, + 0xD2, 0xFA, 0xE8, 0x50, 0xD2, 0xEA, 0xE8, 0xD0 +}; + +static const unsigned char patch_block8[64] = { + 0xE8, 0xD1, 0xD3, 0x0A, 0x03, 0x09, 0x48, 0x23, + 0xE5, 0x2C, 0xA0, 0x03, 0x48, 0x24, 0xEA, 0x1C, + 0x03, 0x08, 0xD2, 0xE3, 0xD3, 0x03, 0xD3, 0x13, + 0xE1, 0x00, 0x02, 0xCB, 0x05, 0x93, 0x57, 0x93, + 0xF0, 0x9A, 0xAC, 0x0B, 0xE3, 0x07, 0x92, 0xEA, + 0xE2, 0x9F, 0xE5, 0x06, 0xE3, 0xB0, 0xA0, 0x02, + 0xEB, 0x1E, 0x82, 0xD7, 0xEA, 0x1E, 0xE2, 0x3B, + 0x85, 0x9B, 0xE9, 0x1E, 0xC8, 0x90, 0x85, 0x94 +}; + +static const unsigned char patch_block9[64] = { + 0x02, 0xDE, 0x05, 0x80, 0x57, 0x93, 0xF0, 0xBA, + 0xAC, 0x06, 0x92, 0xEA, 0xE2, 0xBF, 0xE5, 0x06, + 0xA0, 0x01, 0xEB, 0xBF, 0x85, 0x88, 0xE9, 0x3E, + 0xC8, 0x90, 0x85, 0x81, 0xE9, 0x3E, 0xF0, 0xBA, + 0xF3, 0x39, 0xF0, 0x3A, 0x60, 0x17, 0xF0, 0x3A, + 0xC0, 0x90, 0xF0, 0xBA, 0xE1, 0x00, 0x00, 0x3F, + 0xE3, 0x02, 0xE3, 0x03, 0x58, 0x10, 0x60, 0x59, + 0xE6, 0x93, 0x0D, 0xA2, 0x58, 0x12, 0xE6, 0x93 +}; + +static const unsigned char patch_block10[64] = { + 0x0D, 0xAA, 0xE3, 0x98, 0xE3, 0x90, 0xE1, 0x00, + 0x03, 0x01, 0xE1, 0x00, 0x03, 0x03, 0x9B, 0x7D, + 0x8B, 0x8B, 0xE3, 0x02, 0xE3, 0x03, 0x58, 0x56, + 0x60, 0x59, 0xE6, 0x93, 0x0D, 0xBA, 0xE3, 0x98, + 0xE3, 0x90, 0xE1, 0x00, 0x03, 0x0F, 0x93, 0x11, + 0xE1, 0x00, 0xE3, 0x02, 0x4A, 0x11, 0x0B, 0x42, + 0x91, 0xAF, 0xE3, 0x90, 0xE1, 0x00, 0xF2, 0x91, + 0xF0, 0x91, 0xA3, 0xFE, 0xE1, 0x00, 0x60, 0x92 +}; + +static const unsigned char patch_block11[64] = { + 0xC0, 0x5F, 0xF0, 0x13, 0xF0, 0x13, 0x59, 0x5B, + 0xE2, 0x13, 0xF0, 0x11, 0x5A, 0x19, 0xE2, 0x13, + 0xE1, 0x00, 0x00, 0x00, 0x03, 0x27, 0x68, 0x61, + 0x76, 0x61, 0x6E, 0x61, 0x00, 0x06, 0x03, 0x2C, + 0xE3, 0x02, 0xE3, 0x03, 0xE9, 0x38, 0x59, 0x15, + 0x59, 0x5A, 0xF2, 0x9A, 0xBC, 0x0B, 0xA4, 0x0A, + 0x59, 0x1E, 0xF3, 0x11, 0xF0, 0x1A, 0xE2, 0xBB, + 0x59, 0x15, 0xF0, 0x11, 0x19, 0x2A, 0xE5, 0x02 +}; + +static const unsigned char patch_block12[54] = { + 0xA4, 0x01, 0xEB, 0xBF, 0xE3, 0x98, 0xE3, 0x90, + 0xE1, 0x00, 0x03, 0x42, 0x19, 0x28, 0xE1, 0x00, + 0xE9, 0x30, 0x60, 0x79, 0xE1, 0x00, 0xE3, 0x03, + 0xE3, 0x07, 0x60, 0x79, 0x93, 0x4E, 0xE3, 0xB8, + 0xE3, 0x98, 0xE1, 0x00, 0xE9, 0x1A, 0xF0, 0x1F, + 0xE2, 0x33, 0xF0, 0x91, 0xE2, 0x92, 0xE0, 0x32, + 0xF0, 0x31, 0xE1, 0x00, 0x00, 0x00 +}; + +static const unsigned char do_call[1] = { + 0x01 +}; + + +#define PATCH_DATA_SIZE 18 + +static const cpia2_patch patch_data[PATCH_DATA_SIZE] = { + {0x0A, sizeof(start_address_hi), start_address_hi} + , // 0 + {0x0B, sizeof(start_address_lo), start_address_lo} + , // 1 + {0x0C, sizeof(patch_block0), patch_block0} + , // 2 + {0x0C, sizeof(patch_block1), patch_block1} + , // 3 + {0x0C, sizeof(patch_block2), patch_block2} + , // 4 + {0x0C, sizeof(patch_block3), patch_block3} + , // 5 + {0x0C, sizeof(patch_block4), patch_block4} + , // 6 + {0x0C, sizeof(patch_block5), patch_block5} + , // 7 + {0x0C, sizeof(patch_block6), patch_block6} + , // 8 + {0x0C, sizeof(patch_block7), patch_block7} + , // 9 + {0x0C, sizeof(patch_block8), patch_block8} + , // 10 + {0x0C, sizeof(patch_block9), patch_block9} + , //11 + {0x0C, sizeof(patch_block10), patch_block10} + , // 12 + {0x0C, sizeof(patch_block11), patch_block11} + , // 13 + {0x0C, sizeof(patch_block12), patch_block12} + , // 14 + {0x0A, sizeof(start_address_hi), start_address_hi} + , // 15 + {0x0B, sizeof(start_address_lo), start_address_lo} + , // 16 + {0x0D, sizeof(do_call), do_call} //17 +}; + + +#endif -- cgit v1.2.3-59-g8ed1b From 36f4f334a169e5d42721d74b5d92fda89f792b06 Mon Sep 17 00:00:00 2001 From: Thilo Berger Date: Mon, 27 Feb 2006 00:09:08 -0300 Subject: V4L/DVB (3377): Support for Satelco EasyWatch DVB-S light Support for Satelco EasyWatch DVB-S light. Signed-off-by: Thilo Berger Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-av.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 1465c04e49aa..9dd4745f5312 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -1000,6 +1000,7 @@ static u8 read_pwm(struct budget_av *budget_av) #define SUBID_DVBS_TV_STAR 0x0014 #define SUBID_DVBS_TV_STAR_CI 0x0016 +#define SUBID_DVBS_EASYWATCH 0x001e #define SUBID_DVBC_KNC1 0x0020 #define SUBID_DVBC_KNC1_PLUS 0x0021 #define SUBID_DVBC_CINERGY1200 0x1156 @@ -1038,6 +1039,7 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBS_TV_STAR: case SUBID_DVBS_TV_STAR_CI: case SUBID_DVBS_CYNERGY1200N: + case SUBID_DVBS_EASYWATCH: fe = stv0299_attach(&philips_sd1878_config, &budget_av->budget.i2c_adap); break; @@ -1285,6 +1287,7 @@ MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S); MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C); MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T); MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR); +MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR); MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP); MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP); MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP); @@ -1300,6 +1303,7 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011), MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014), MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016), + MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), -- cgit v1.2.3-59-g8ed1b From 44fd06fa9002c42b367c152594cc95b7632c081d Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Mon, 27 Feb 2006 00:09:11 -0300 Subject: V4L/DVB (3378): Restore power on defaults of tda9887 after tda8290 probe The probing code for tda8290 changes the state of the tda9887 GP ports. The patch assumes that if probing for tda8290 failed, this must be a tda9887 and restores its power on defaults. This should solve the module load order issue with some pinnacle cards. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 4 ++-- drivers/media/video/tda8290.c | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index ca90a73f71d4..eaf32b81ccf8 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2213,7 +2213,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = 0x61, .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, + .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, @@ -2237,7 +2237,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = 0x61, .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, + .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 2b954b3d2ba6..027c8a074dfe 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -584,9 +584,10 @@ int tda8290_init(struct i2c_client *c) int tda8290_probe(struct i2c_client *c) { - unsigned char soft_reset[] = { 0x00, 0x00 }; - unsigned char easy_mode_b[] = { 0x01, 0x02 }; - unsigned char easy_mode_g[] = { 0x01, 0x04 }; + unsigned char soft_reset[] = { 0x00, 0x00 }; + unsigned char easy_mode_b[] = { 0x01, 0x02 }; + unsigned char easy_mode_g[] = { 0x01, 0x04 }; + unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 }; unsigned char addr_dto_lsb = 0x07; unsigned char data; @@ -603,6 +604,7 @@ int tda8290_probe(struct i2c_client *c) return 0; } } + i2c_master_send(c, restore_9886, 3); return -1; } -- cgit v1.2.3-59-g8ed1b From b9ee9ad7cb91301aae0fc12e11f79ba119c133d9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 27 Feb 2006 00:09:14 -0300 Subject: V4L/DVB (3380): TUV1236d: declare buffer as static const Make buffer a static const Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index cc9d6601eafa..44e27dc646ae 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1487,7 +1487,7 @@ void cx88_card_setup(struct cx88_core *core) if (0 == core->i2c_rc) { /* enable tuner */ int i; - u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 }; + static const u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 }; core->i2c_client.addr = 0x0a; for (i = 0; i < 5; i++) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index eaf32b81ccf8..ccf7231cde3e 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3554,7 +3554,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) { /* enable tuner */ int i; - u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 }; + static const u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 }; dev->i2c_client.addr = 0x0a; for (i = 0; i < 5; i++) if (2 != i2c_master_send(&dev->i2c_client,&buffer[i*2],2)) -- cgit v1.2.3-59-g8ed1b From 981a16f185bdf105f0d411d87f5c276d3da60e64 Mon Sep 17 00:00:00 2001 From: Mattias Nordstrom Date: Mon, 27 Feb 2006 00:09:17 -0300 Subject: V4L/DVB (3382): Fix stv0297 for qam128 on tt c1500 (saa7146) I have a TT C1500 card (saa7146, STV0297) which had problems tuning channels at QAM128 (like the ones in the Finnish HTV / Welho network). A fix which seems to work perfectly so far is to change the delay for QAM128 to the same values as for QAM256 in stv0297_set_frontend(), Signed-off-by: Mattias Nordstrom Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0297.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c index 6122ba754bc5..eb15676d374f 100644 --- a/drivers/media/dvb/frontends/stv0297.c +++ b/drivers/media/dvb/frontends/stv0297.c @@ -393,10 +393,6 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par break; case QAM_128: - delay = 150; - sweeprate = 1000; - break; - case QAM_256: delay = 200; sweeprate = 500; -- cgit v1.2.3-59-g8ed1b From 1be11e367f25d3874276d56d1c4ffed5b3cc3bb9 Mon Sep 17 00:00:00 2001 From: Johannes Stezenbach Date: Mon, 27 Feb 2006 00:09:20 -0300 Subject: V4L/DVB (3385): Dvb: fix __init/__exit section references in av7110 driver use __devinit/__devexit/__devexit_p() where appropriate Signed-off-by: Johannes Stezenbach Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110.c | 7 ++++--- drivers/media/dvb/ttpci/av7110_ir.c | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 1aa61bf29ad6..d982a50cdd7f 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -2476,7 +2476,8 @@ static int frontend_init(struct av7110 *av7110) * The same behaviour of missing VSYNC can be duplicated on budget * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble. */ -static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext) +static int __devinit av7110_attach(struct saa7146_dev* dev, + struct saa7146_pci_extension_data *pci_ext) { const int length = TS_WIDTH * TS_HEIGHT; struct pci_dev *pdev = dev->pci; @@ -2826,7 +2827,7 @@ err_kfree_0: goto out; } -static int av7110_detach(struct saa7146_dev* saa) +static int __devexit av7110_detach(struct saa7146_dev* saa) { struct av7110 *av7110 = saa->ext_priv; dprintk(4, "%p\n", av7110); @@ -2973,7 +2974,7 @@ static struct saa7146_extension av7110_extension = { .module = THIS_MODULE, .pci_tbl = &pci_tbl[0], .attach = av7110_attach, - .detach = av7110_detach, + .detach = __devexit_p(av7110_detach), .irq_mask = MASK_19 | MASK_03 | MASK_10, .irq_func = av7110_irq, diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index 617e4f6c0ed7..d54bbcdde2cc 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c @@ -208,7 +208,7 @@ static void ir_handler(struct av7110 *av7110, u32 ircom) } -int __init av7110_ir_init(struct av7110 *av7110) +int __devinit av7110_ir_init(struct av7110 *av7110) { static struct proc_dir_entry *e; @@ -248,7 +248,7 @@ int __init av7110_ir_init(struct av7110 *av7110) } -void __exit av7110_ir_exit(struct av7110 *av7110) +void __devexit av7110_ir_exit(struct av7110 *av7110) { int i; -- cgit v1.2.3-59-g8ed1b From 3b81fec4328799e94789e8404e6e8b7218c096f6 Mon Sep 17 00:00:00 2001 From: Peter Beutner Date: Mon, 27 Feb 2006 00:09:23 -0300 Subject: V4L/DVB (3386): Dvb-core: remove dead code The field "dvr" in struct dmxdev is competely unused. Remove it and code which allocates, initializes and frees it. Signed-off-by: Peter Beutner Signed-off-by: Johannes Stezenbach Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dmxdev.c | 19 ------------------- drivers/media/dvb/dvb-core/dmxdev.h | 8 -------- 2 files changed, 27 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index ead5343d7706..4c52c8521bd8 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -160,13 +160,6 @@ static struct dmx_frontend * get_fe(struct dmx_demux *demux, int type) return NULL; } -static inline void dvb_dmxdev_dvr_state_set(struct dmxdev_dvr *dmxdevdvr, int state) -{ - spin_lock_irq(&dmxdevdvr->dev->lock); - dmxdevdvr->state=state; - spin_unlock_irq(&dmxdevdvr->dev->lock); -} - static int dvb_dvr_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; @@ -1106,22 +1099,12 @@ dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) if (!dmxdev->filter) return -ENOMEM; - dmxdev->dvr = vmalloc(dmxdev->filternum*sizeof(struct dmxdev_dvr)); - if (!dmxdev->dvr) { - vfree(dmxdev->filter); - dmxdev->filter = NULL; - return -ENOMEM; - } - mutex_init(&dmxdev->mutex); spin_lock_init(&dmxdev->lock); for (i=0; ifilternum; i++) { dmxdev->filter[i].dev=dmxdev; dmxdev->filter[i].buffer.data=NULL; dvb_dmxdev_filter_state_set(&dmxdev->filter[i], DMXDEV_STATE_FREE); - dmxdev->dvr[i].dev=dmxdev; - dmxdev->dvr[i].buffer.data=NULL; - dvb_dmxdev_dvr_state_set(&dmxdev->dvr[i], DMXDEV_STATE_FREE); } dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, DVB_DEVICE_DEMUX); @@ -1141,8 +1124,6 @@ dvb_dmxdev_release(struct dmxdev *dmxdev) vfree(dmxdev->filter); dmxdev->filter=NULL; - vfree(dmxdev->dvr); - dmxdev->dvr=NULL; dmxdev->demux->close(dmxdev->demux); } EXPORT_SYMBOL(dvb_dmxdev_release); diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h index ec2a7a4da5e4..fafdf476b23a 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.h +++ b/drivers/media/dvb/dvb-core/dmxdev.h @@ -94,19 +94,11 @@ struct dmxdev_filter { }; -struct dmxdev_dvr { - int state; - struct dmxdev *dev; - struct dmxdev_buffer buffer; -}; - - struct dmxdev { struct dvb_device *dvbdev; struct dvb_device *dvr_dvbdev; struct dmxdev_filter *filter; - struct dmxdev_dvr *dvr; struct dmx_demux *demux; int filternum; -- cgit v1.2.3-59-g8ed1b From 1e7eb89ba936fc1db54e247a336f3f55bdbc644d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Mon, 27 Feb 2006 00:09:25 -0300 Subject: V4L/DVB (3388): Ignore DiSEqC messages > 6 and < 3 Ignore invalid messages on cx24110 frontend. Thanks to Edgar Toernig Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx24110.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index d15d32c51dc5..cc68b7e83b5e 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c @@ -418,6 +418,9 @@ static int cx24110_send_diseqc_msg(struct dvb_frontend* fe, struct cx24110_state *state = fe->demodulator_priv; unsigned long timeout; + if (cmd->msg_len < 3 || cmd->msg_len > 6) + return -EINVAL; /* not implemented */ + for (i = 0; i < cmd->msg_len; i++) cx24110_writereg(state, 0x79 + i, cmd->msg[i]); -- cgit v1.2.3-59-g8ed1b From e7ac46469c247a931f760354deaed9cf10b75fde Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Mon, 27 Feb 2006 00:09:29 -0300 Subject: V4L/DVB (3389): Fix broken IF-OUT Relay handling Fixed broken IF-OUT on pinnacle sat board. Thanks to Edgar Toernig Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 15 +++++++++++++++ drivers/media/dvb/frontends/cx24110.c | 10 ++++++++++ drivers/media/dvb/frontends/cx24110.h | 1 + 3 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 1649846f9ceb..f5bfcd2b3803 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -239,6 +239,20 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete static int pinnsat_pll_init(struct dvb_frontend* fe) { + struct dvb_bt8xx_card *card = fe->dvb->priv; + + bttv_gpio_enable(card->bttv_nr, 1, 1); /* output */ + bttv_write_gpio(card->bttv_nr, 1, 1); /* relay on */ + + return 0; +} + +static int pinnsat_pll_sleep(struct dvb_frontend* fe) +{ + struct dvb_bt8xx_card *card = fe->dvb->priv; + + bttv_write_gpio(card->bttv_nr, 1, 0); /* relay off */ + return 0; } @@ -246,6 +260,7 @@ static struct cx24110_config pctvsat_config = { .demod_address = 0x55, .pll_init = pinnsat_pll_init, .pll_set = cx24108_pll_set, + .pll_sleep = pinnsat_pll_sleep, }; static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index cc68b7e83b5e..f3edf8b517dd 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c @@ -371,6 +371,15 @@ static int cx24110_initfe(struct dvb_frontend* fe) return 0; } +static int cx24110_sleep(struct dvb_frontend *fe) +{ + struct cx24110_state *state = fe->demodulator_priv; + + if (state->config->pll_sleep) + return state->config->pll_sleep(fe); + return 0; +} + static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) { struct cx24110_state *state = fe->demodulator_priv; @@ -642,6 +651,7 @@ static struct dvb_frontend_ops cx24110_ops = { .release = cx24110_release, .init = cx24110_initfe, + .sleep = cx24110_sleep, .set_frontend = cx24110_set_frontend, .get_frontend = cx24110_get_frontend, .read_status = cx24110_read_status, diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h index b63ecf26421a..609ac642b406 100644 --- a/drivers/media/dvb/frontends/cx24110.h +++ b/drivers/media/dvb/frontends/cx24110.h @@ -35,6 +35,7 @@ struct cx24110_config /* PLL maintenance */ int (*pll_init)(struct dvb_frontend* fe); int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); + int (*pll_sleep)(struct dvb_frontend* fe); }; extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, -- cgit v1.2.3-59-g8ed1b From 6baad3f041eec7c31ad88b52eb44205987148eba Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Mon, 27 Feb 2006 00:09:32 -0300 Subject: V4L/DVB (3390): Fix module parameters Now, root may change parameters while module is running. Thanks to Edgar Toerning Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 22e96cf8497a..2c3ea8f95dcd 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -49,13 +49,13 @@ static int dvb_powerdown_on_sleep = 1; module_param_named(frontend_debug, dvb_frontend_debug, int, 0644); MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off)."); -module_param(dvb_shutdown_timeout, int, 0444); +module_param(dvb_shutdown_timeout, int, 0644); MODULE_PARM_DESC(dvb_shutdown_timeout, "wait seconds after close() before suspending hardware"); -module_param(dvb_force_auto_inversion, int, 0444); +module_param(dvb_force_auto_inversion, int, 0644); MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always"); -module_param(dvb_override_tune_delay, int, 0444); +module_param(dvb_override_tune_delay, int, 0644); MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); -module_param(dvb_powerdown_on_sleep, int, 0444); +module_param(dvb_powerdown_on_sleep, int, 0644); MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volatage off on sleep (default)"); #define dprintk if (dvb_frontend_debug) printk -- cgit v1.2.3-59-g8ed1b From df5a4f4fd378367db1f48e92f46ce312814cf745 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Mon, 27 Feb 2006 00:09:37 -0300 Subject: V4L/DVB (3392): Do a RESYNC for all cards After a FIFO corruptions occurrs (generally due to buffer overflow), FIFO contents needs to be discarted. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index f5bfcd2b3803..b8eab69d2c56 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -813,14 +813,14 @@ static int dvb_bt8xx_probe(struct bttv_sub_device *sub) card->gpio_mode = 0x0400c060; /* should be: BT878_A_GAIN=0,BT878_A_PWRDN,BT878_DA_DPM,BT878_DA_SBR, BT878_DA_IOM=1,BT878_DA_APP to enable serial highspeed mode. */ - card->op_sync_orin = 0; - card->irq_err_ignore = 0; + card->op_sync_orin = BT878_RISC_SYNC_MASK; + card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR; break; case BTTV_BOARD_DVICO_DVBT_LITE: card->gpio_mode = 0x0400C060; - card->op_sync_orin = 0; - card->irq_err_ignore = 0; + card->op_sync_orin = BT878_RISC_SYNC_MASK; + card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR; /* 26, 15, 14, 6, 5 * A_PWRDN DA_DPM DA_SBR DA_IOM_DA * DA_APP(parallel) */ @@ -835,15 +835,15 @@ static int dvb_bt8xx_probe(struct bttv_sub_device *sub) case BTTV_BOARD_NEBULA_DIGITV: case BTTV_BOARD_AVDVBT_761: card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5); - card->op_sync_orin = 0; - card->irq_err_ignore = 0; + card->op_sync_orin = BT878_RISC_SYNC_MASK; + card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR; /* A_PWRDN DA_SBR DA_APP (high speed serial) */ break; case BTTV_BOARD_AVDVBT_771: //case 0x07711461: card->gpio_mode = 0x0400402B; card->op_sync_orin = BT878_RISC_SYNC_MASK; - card->irq_err_ignore = 0; + card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR; /* A_PWRDN DA_SBR DA_APP[0] PKTP=10 RISC_ENABLE FIFO_ENABLE*/ break; @@ -867,8 +867,8 @@ static int dvb_bt8xx_probe(struct bttv_sub_device *sub) case BTTV_BOARD_PC_HDTV: card->gpio_mode = 0x0100EC7B; - card->op_sync_orin = 0; - card->irq_err_ignore = 0; + card->op_sync_orin = BT878_RISC_SYNC_MASK; + card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR; break; default: -- cgit v1.2.3-59-g8ed1b From dadaff2db46aae917ccdbceb2cd2ecac75767435 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Feb 2006 00:09:41 -0300 Subject: V4L/DVB (3392a): XC3028 code removed from -git versions - Current xc3028 support is still experimental, requiring more work to be sent to mainstream. It will be kept only at mercurial tree on http://linuxtv.org/hg until fixed. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 75 ------------------------------- drivers/media/video/tuner-core.c | 5 --- 2 files changed, 80 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 666630572f35..4e22fc4889e1 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -154,76 +154,6 @@ struct em28xx_board em28xx_boards[] = { .amux = 1, }}, }, -#ifdef CONFIG_XC3028 - [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { - .name = "Hauppauge WinTV HVR 900", - .vchannels = 3, - .norm = VIDEO_MODE_PAL, - .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_XCEIVE_XC3028, - .has_tuner = 1, - .decoder = EM28XX_TVP5150, - .input = {{ - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 2, - .amux = 1, - },{ - .type = EM28XX_VMUX_TELEVISION, - .vmux = 0, - .amux = 0, - },{ - .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, - .amux = 1, - }}, - }, - [EM2880_BOARD_TERRATEC_HYBRID_XS] = { - .name = "Terratec Hybrid XS", - .vchannels = 3, - .norm = VIDEO_MODE_PAL, - .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, - .tuner_type = TUNER_XCEIVE_XC3028, - .decoder = EM28XX_TVP5150, - .input = {{ - .type = EM28XX_VMUX_TELEVISION, - .vmux = 0, - .amux = 0, - },{ - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 2, - .amux = 1, - },{ - .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, - .amux = 1, - }}, - }, - /* maybe there's a reason behind it why Terratec sells the Hybrid XS as Prodigy XS with a - * different PID, let's keep it separated for now maybe we'll need it lateron */ - [EM2880_BOARD_TERRATEC_PRODIGY_XS] = { - .name = "Terratec Prodigy XS", - .vchannels = 3, - .norm = VIDEO_MODE_PAL, - .tda9887_conf = TDA9887_PRESENT, - .has_tuner = 1, - .tuner_type = TUNER_XCEIVE_XC3028, - .decoder = EM28XX_TVP5150, - .input = {{ - .type = EM28XX_VMUX_TELEVISION, - .vmux = 0, - .amux = 0, - },{ - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 2, - .amux = 1, - },{ - .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, - .amux = 1, - }}, - }, -#endif [EM2820_BOARD_MSI_VOX_USB_2] = { .name = "MSI VOX USB 2.0", .vchannels = 3, @@ -342,11 +272,6 @@ struct usb_device_id em28xx_id_table [] = { { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, -#ifdef CONFIG_XC3028 - { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, - { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, - { USB_DEVICE(0x0ccd, 0x0047), .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, -#endif { }, }; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 3a96cc4ae81d..3964244d6ff5 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -216,11 +216,6 @@ static void set_type(struct i2c_client *c, unsigned int type, i2c_master_send(c,buffer,4); default_tuner_init(c); break; -#ifdef CONFIG_XC3028 - case TUNER_XCEIVE_XC3028: - xc3028_init(c); - break; -#endif default: default_tuner_init(c); break; -- cgit v1.2.3-59-g8ed1b From 6457af5f7eac49ff8e072fdc98c986d4ac874b04 Mon Sep 17 00:00:00 2001 From: Ian Pickworth Date: Mon, 27 Feb 2006 00:09:45 -0300 Subject: V4L/DVB (3393): Cx88: reduce excessive logging - fix temporary debug code by changing printk to dprintk at level 1. - move CORE_IOCTL messages from level 1 to level 2. - this should help with selective debugging, while not filling people's logs up during normal use. Signed-off-by: Ian Pickworth Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 2 +- drivers/media/video/cx88/cx88-video.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index b8eab69d2c56..baa8227ef87c 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -243,7 +243,7 @@ static int pinnsat_pll_init(struct dvb_frontend* fe) bttv_gpio_enable(card->bttv_nr, 1, 1); /* output */ bttv_write_gpio(card->bttv_nr, 1, 1); /* relay on */ - + return 0; } diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index d15ef158ac8f..7bbc81fb43b5 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -918,9 +918,9 @@ static int get_control(struct cx88_core *core, struct v4l2_control *ctl) ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift; break; } - printk("get_control id=0x%X reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", - ctl->id, c->reg, ctl->value, - c->mask, c->sreg ? " [shadowed]" : ""); + dprintk(1,"get_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", + ctl->id, c->v.name, ctl->value, c->reg, + value,c->mask, c->sreg ? " [shadowed]" : ""); return 0; } @@ -969,9 +969,9 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) value = ((ctl->value - c->off) << c->shift) & c->mask; break; } - printk("set_control id=0x%X reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", - ctl->id, c->reg, value, - mask, c->sreg ? " [shadowed]" : ""); + dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", + ctl->id, c->v.name, ctl->value, c->reg, value, + mask, c->sreg ? " [shadowed]" : ""); if (c->sreg) { cx_sandor(c->sreg, c->reg, mask, value); } else { @@ -1252,7 +1252,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, { int err; - dprintk( 1, "CORE IOCTL: 0x%x\n", cmd ); + dprintk(2, "CORE IOCTL: 0x%x\n", cmd ); if (video_debug > 1) v4l_print_ioctl(core->name,cmd); -- cgit v1.2.3-59-g8ed1b From 4a287cfeea7056dc71d2bc352ae490a2a5bcceb0 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Mon, 27 Feb 2006 00:09:48 -0300 Subject: V4L/DVB (3394): Bttv: correct bttv_risc_packed buffer size This patch fixes the strange crashes I was seeing after using bttv card, caused by a buffer overflow in bttv_risc_packed. The instruction buffer size calculation contains two errors: (a) a non-zero padding value can push the start of the next bpl section to just before a page border, leading to more scanline splits and thus additional instructions. (b) the first DMA region can be smaller than one page, so there can be a scanline split even if bpl*lines is smaller than PAGE_SIZE. For example, consider the case where offset is 0, bpl is 2, padding is 4094, lines is smaller than 2048, the first DMA region has size 1 and all others have size PAGE_SIZE, assumed to equal 4096. Then all bpl regions cross page borders and the number of instructions written is 2*lines+2, rather than lines+2 (the current estimate). With this patch the number of instructions for this example is estimated to be 2*lines+3. Also, the BUG_ON that was supposed to catch buffer overflows contained a thinko causing it fire only if the buffer was overrun by a factor of 16 or more, so it fixes the the BUG_ON's (using sizeof rather than "4"). Signed-off-by: Duncan Sands Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bttv-risc.c | 12 +++++++----- drivers/media/video/cx88/cx88-core.c | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index b40e9734bf08..a60c211c9e31 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -51,8 +51,10 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, int rc; /* estimate risc mem: worst case is one write per page border + - one write per scan line + sync + jump (all 2 dwords) */ - instructions = (bpl * lines) / PAGE_SIZE + lines; + one write per scan line + sync + jump (all 2 dwords). padding + can cause next bpl to start close to a page border. First DMA + region may be smaller than PAGE_SIZE */ + instructions = 1 + ((bpl + padding) * lines) / PAGE_SIZE + lines; instructions += 2; if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) return rc; @@ -104,7 +106,7 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, /* save pointer to jmp instruction address */ risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size); + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); return 0; } @@ -222,7 +224,7 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, /* save pointer to jmp instruction address */ risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size); + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); return 0; } @@ -307,7 +309,7 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, /* save pointer to jmp instruction address */ risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size); + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); kfree(skips); return 0; } diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index eda7cd8b2d4a..25be3a976d09 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -163,7 +163,7 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, /* save pointer to jmp instruction address */ risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size); + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); return 0; } @@ -188,7 +188,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, /* save pointer to jmp instruction address */ risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size); + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); return 0; } -- cgit v1.2.3-59-g8ed1b From a23f460dd0c7c9c58b03494c7819e126b2c72383 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 27 Feb 2006 16:28:36 -0500 Subject: [PATCH] wireless/airo: Remove 'Setting transmit key' info messages These messages end up polluting logs when things like NetworkManager or wpa_supplicant are controlling the driver. They aren't really that useful, and no other drivers output messages like this when the user fiddles with encryption keys. Users can use iwconfig and other wireless-tools methods to determine and change the current transmit key if they wish to do so manually. Therefore, remove the messages. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index b96b6dbe01f9..864937a409e5 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -5036,7 +5036,6 @@ static int set_wep_key(struct airo_info *ai, u16 index, wkr.len = sizeof(wkr); wkr.kindex = 0xffff; wkr.mac[0] = (char)index; - if (perm) printk(KERN_INFO "Setting transmit key to %d\n", index); if (perm) ai->defindex = (char)index; } else { // We are actually setting the key @@ -5045,7 +5044,6 @@ static int set_wep_key(struct airo_info *ai, u16 index, wkr.klen = keylen; memcpy( wkr.key, key, keylen ); memcpy( wkr.mac, macaddr, ETH_ALEN ); - printk(KERN_INFO "Setting key %d\n", index); } if (perm) disable_MAC(ai, lock); -- cgit v1.2.3-59-g8ed1b From 24669f75a3231fa37444977c92d1f4838bec1233 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 16 Jan 2006 10:31:18 -0500 Subject: [SCSI] SCSI core kmalloc2kzalloc Change the core SCSI code to use kzalloc rather than kmalloc+memset where possible. Signed-off-by: Jes Sorensen Signed-off-by: James Bottomley --- drivers/scsi/hosts.c | 3 +-- drivers/scsi/scsi.c | 3 +-- drivers/scsi/scsi_debug.c | 9 +++------ drivers/scsi/scsi_ioctl.c | 3 +-- drivers/scsi/scsi_lib.c | 5 ++--- drivers/scsi/scsi_scan.c | 6 ++---- drivers/scsi/scsi_transport_fc.c | 9 +++------ drivers/scsi/scsi_transport_iscsi.c | 3 +-- drivers/scsi/scsi_transport_sas.c | 9 +++------ drivers/scsi/scsi_transport_spi.c | 12 ++++-------- drivers/scsi/sd.c | 3 +-- drivers/scsi/sg.c | 6 ++---- drivers/scsi/sr.c | 3 +-- drivers/scsi/sr_ioctl.c | 6 ++---- drivers/scsi/st.c | 9 +++------ 15 files changed, 30 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 588107923499..ef57f253031c 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -306,10 +306,9 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) dump_stack(); } - shost = kmalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask); + shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask); if (!shost) return NULL; - memset(shost, 0, sizeof(struct Scsi_Host) + privsize); spin_lock_init(&shost->default_lock); scsi_assign_lock(shost, &shost->default_lock); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index c551bb84dbfb..11b27ba0cd41 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -136,9 +136,8 @@ struct scsi_request *scsi_allocate_request(struct scsi_device *sdev, const int size = offset + sizeof(struct request); struct scsi_request *sreq; - sreq = kmalloc(size, gfp_mask); + sreq = kzalloc(size, gfp_mask); if (likely(sreq != NULL)) { - memset(sreq, 0, size); sreq->sr_request = (struct request *)(((char *)sreq) + offset); sreq->sr_device = sdev; sreq->sr_host = sdev->host; diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 0e529f8171c4..5a5d2af8ee43 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1061,13 +1061,12 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) } } if (NULL == open_devip) { /* try and make a new one */ - open_devip = kmalloc(sizeof(*open_devip),GFP_KERNEL); + open_devip = kzalloc(sizeof(*open_devip),GFP_KERNEL); if (NULL == open_devip) { printk(KERN_ERR "%s: out of memory at line %d\n", __FUNCTION__, __LINE__); return NULL; } - memset(open_devip, 0, sizeof(*open_devip)); open_devip->sdbg_host = sdbg_host; list_add_tail(&open_devip->dev_list, &sdbg_host->dev_info_list); @@ -1814,7 +1813,7 @@ static int sdebug_add_adapter(void) struct sdebug_dev_info *sdbg_devinfo; struct list_head *lh, *lh_sf; - sdbg_host = kmalloc(sizeof(*sdbg_host),GFP_KERNEL); + sdbg_host = kzalloc(sizeof(*sdbg_host), GFP_KERNEL); if (NULL == sdbg_host) { printk(KERN_ERR "%s: out of memory at line %d\n", @@ -1822,19 +1821,17 @@ static int sdebug_add_adapter(void) return -ENOMEM; } - memset(sdbg_host, 0, sizeof(*sdbg_host)); INIT_LIST_HEAD(&sdbg_host->dev_info_list); devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns; for (k = 0; k < devs_per_host; k++) { - sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL); + sdbg_devinfo = kzalloc(sizeof(*sdbg_devinfo), GFP_KERNEL); if (NULL == sdbg_devinfo) { printk(KERN_ERR "%s: out of memory at line %d\n", __FUNCTION__, __LINE__); error = -ENOMEM; goto clean; } - memset(sdbg_devinfo, 0, sizeof(*sdbg_devinfo)); sdbg_devinfo->sdbg_host = sdbg_host; list_add_tail(&sdbg_devinfo->dev_list, &sdbg_host->dev_info_list); diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 0bba7d8eebb0..36e930066649 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -241,10 +241,9 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, buf_needed = (buf_needed + 511) & ~511; if (buf_needed > MAX_BUF) buf_needed = MAX_BUF; - buf = kmalloc(buf_needed, gfp_mask); + buf = kzalloc(buf_needed, gfp_mask); if (!buf) return -ENOMEM; - memset(buf, 0, buf_needed); if (inlen == 0) { data_direction = DMA_FROM_DEVICE; } else if (outlen == 0 ) { diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 4362dcde74af..1fe4fd83e305 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -286,13 +286,12 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, int result; if (sshdr) { - sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); + sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); if (!sense) return DRIVER_ERROR << 24; - memset(sense, 0, SCSI_SENSE_BUFFERSIZE); } result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, - sense, timeout, retries, 0); + sense, timeout, retries, 0); if (sshdr) scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 5acb83ca5ae5..74863da1d630 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -205,12 +205,11 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, int display_failure_msg = 1, ret; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - sdev = kmalloc(sizeof(*sdev) + shost->transportt->device_size, + sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size, GFP_ATOMIC); if (!sdev) goto out; - memset(sdev, 0, sizeof(*sdev)); sdev->vendor = scsi_null_device_strs; sdev->model = scsi_null_device_strs; sdev->rev = scsi_null_device_strs; @@ -334,12 +333,11 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, struct scsi_target *starget; struct scsi_target *found_target; - starget = kmalloc(size, GFP_KERNEL); + starget = kzalloc(size, GFP_KERNEL); if (!starget) { printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); return NULL; } - memset(starget, 0, size); dev = &starget->dev; device_initialize(dev); starget->reap_ref = 1; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index f2c9acf11bd0..56012b2694d2 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -1115,15 +1115,13 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel, struct scsi_transport_template * fc_attach_transport(struct fc_function_template *ft) { - struct fc_internal *i = kmalloc(sizeof(struct fc_internal), - GFP_KERNEL); int count; + struct fc_internal *i = kzalloc(sizeof(struct fc_internal), + GFP_KERNEL); if (unlikely(!i)) return NULL; - memset(i, 0, sizeof(struct fc_internal)); - i->t.target_attrs.ac.attrs = &i->starget_attrs[0]; i->t.target_attrs.ac.class = &fc_transport_class.class; i->t.target_attrs.ac.match = fc_target_match; @@ -1305,12 +1303,11 @@ fc_rport_create(struct Scsi_Host *shost, int channel, size_t size; size = (sizeof(struct fc_rport) + fci->f->dd_fcrport_size); - rport = kmalloc(size, GFP_KERNEL); + rport = kzalloc(size, GFP_KERNEL); if (unlikely(!rport)) { printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); return NULL; } - memset(rport, 0, size); rport->maxframe_size = -1; rport->supported_classes = FC_COS_UNSPECIFIED; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 71e54a64adca..2730d507e585 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1117,10 +1117,9 @@ iscsi_register_transport(struct iscsi_transport *tt) if (priv) return NULL; - priv = kmalloc(sizeof(*priv), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return NULL; - memset(priv, 0, sizeof(*priv)); INIT_LIST_HEAD(&priv->list); priv->iscsi_transport = tt; diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 210dab5879fa..205542988e29 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -391,10 +391,9 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number) struct Scsi_Host *shost = dev_to_shost(parent); struct sas_phy *phy; - phy = kmalloc(sizeof(*phy), GFP_KERNEL); + phy = kzalloc(sizeof(*phy), GFP_KERNEL); if (!phy) return NULL; - memset(phy, 0, sizeof(*phy)); get_device(parent); @@ -585,12 +584,11 @@ struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent) struct Scsi_Host *shost = dev_to_shost(&parent->dev); struct sas_rphy *rphy; - rphy = kmalloc(sizeof(*rphy), GFP_KERNEL); + rphy = kzalloc(sizeof(*rphy), GFP_KERNEL); if (!rphy) { put_device(&parent->dev); return NULL; } - memset(rphy, 0, sizeof(*rphy)); device_initialize(&rphy->dev); rphy->dev.parent = get_device(&parent->dev); @@ -793,10 +791,9 @@ sas_attach_transport(struct sas_function_template *ft) struct sas_internal *i; int count; - i = kmalloc(sizeof(struct sas_internal), GFP_KERNEL); + i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL); if (!i) return NULL; - memset(i, 0, sizeof(struct sas_internal)); i->t.user_scan = sas_user_scan; diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 7ee95eb83dda..a1e521b58b67 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -900,13 +900,11 @@ spi_dv_device(struct scsi_device *sdev) if (unlikely(scsi_device_get(sdev))) return; - buffer = kmalloc(len, GFP_KERNEL); + buffer = kzalloc(len, GFP_KERNEL); if (unlikely(!buffer)) goto out_put; - memset(buffer, 0, len); - /* We need to verify that the actual device will quiesce; the * later target quiesce is just a nice to have */ if (unlikely(scsi_device_quiesce(sdev))) @@ -1265,15 +1263,13 @@ static DECLARE_ANON_TRANSPORT_CLASS(spi_device_class, struct scsi_transport_template * spi_attach_transport(struct spi_function_template *ft) { - struct spi_internal *i = kmalloc(sizeof(struct spi_internal), - GFP_KERNEL); int count = 0; + struct spi_internal *i = kzalloc(sizeof(struct spi_internal), + GFP_KERNEL); + if (unlikely(!i)) return NULL; - memset(i, 0, sizeof(struct spi_internal)); - - i->t.target_attrs.ac.class = &spi_transport_class.class; i->t.target_attrs.ac.attrs = &i->attrs[0]; i->t.target_attrs.ac.match = spi_target_match; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 9d9872347f56..8ba2d988d051 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1517,11 +1517,10 @@ static int sd_probe(struct device *dev) "sd_attach\n")); error = -ENOMEM; - sdkp = kmalloc(sizeof(*sdkp), GFP_KERNEL); + sdkp = kzalloc(sizeof(*sdkp), GFP_KERNEL); if (!sdkp) goto out; - memset (sdkp, 0, sizeof(*sdkp)); kref_init(&sdkp->kref); gd = alloc_disk(16); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 2a547538d444..ecf2f6010e76 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1361,7 +1361,7 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) void *old_sg_dev_arr = NULL; int k, error; - sdp = kmalloc(sizeof(Sg_device), GFP_KERNEL); + sdp = kzalloc(sizeof(Sg_device), GFP_KERNEL); if (!sdp) { printk(KERN_WARNING "kmalloc Sg_device failure\n"); return -ENOMEM; @@ -1373,12 +1373,11 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) int tmp_dev_max = sg_nr_dev + SG_DEV_ARR_LUMP; write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - tmp_da = kmalloc(tmp_dev_max * sizeof(Sg_device *), GFP_KERNEL); + tmp_da = kzalloc(tmp_dev_max * sizeof(Sg_device *), GFP_KERNEL); if (unlikely(!tmp_da)) goto expand_failed; write_lock_irqsave(&sg_dev_arr_lock, iflags); - memset(tmp_da, 0, tmp_dev_max * sizeof(Sg_device *)); memcpy(tmp_da, sg_dev_arr, sg_dev_max * sizeof(Sg_device *)); old_sg_dev_arr = sg_dev_arr; sg_dev_arr = tmp_da; @@ -1391,7 +1390,6 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) if (unlikely(k >= SG_MAX_DEVS)) goto overflow; - memset(sdp, 0, sizeof(*sdp)); SCSI_LOG_TIMEOUT(3, printk("sg_alloc: dev=%d \n", k)); sprintf(disk->disk_name, "sg%d", k); disk->first_minor = k; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 997f8e30509b..d8d12a1718bf 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -525,10 +525,9 @@ static int sr_probe(struct device *dev) goto fail; error = -ENOMEM; - cd = kmalloc(sizeof(*cd), GFP_KERNEL); + cd = kzalloc(sizeof(*cd), GFP_KERNEL); if (!cd) goto fail; - memset(cd, 0, sizeof(*cd)); kref_init(&cd->kref); diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 5d02ff4db6cc..03fbc4b44473 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -44,11 +44,10 @@ static int sr_read_tochdr(struct cdrom_device_info *cdi, int result; unsigned char *buffer; - buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); + buffer = kzalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); if (!buffer) return -ENOMEM; - memset(&cgc, 0, sizeof(struct packet_command)); cgc.timeout = IOCTL_TIMEOUT; cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; cgc.cmd[8] = 12; /* LSB of length */ @@ -74,11 +73,10 @@ static int sr_read_tocentry(struct cdrom_device_info *cdi, int result; unsigned char *buffer; - buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); + buffer = kzalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); if (!buffer) return -ENOMEM; - memset(&cgc, 0, sizeof(struct packet_command)); cgc.timeout = IOCTL_TIMEOUT; cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 7f96f33c1bb1..f0606da19d02 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3590,12 +3590,11 @@ static struct st_buffer * i = sizeof(struct st_buffer) + (max_sg - 1) * sizeof(struct scatterlist) + max_sg * sizeof(struct st_buf_fragment); - tb = kmalloc(i, priority); + tb = kzalloc(i, priority); if (!tb) { printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n"); return NULL; } - memset(tb, 0, i); tb->frp_segs = tb->orig_frp_segs = 0; tb->use_sg = max_sg; tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg); @@ -3924,14 +3923,13 @@ static int st_probe(struct device *dev) goto out_put_disk; } - tmp_da = kmalloc(tmp_dev_max * sizeof(struct scsi_tape *), GFP_ATOMIC); + tmp_da = kzalloc(tmp_dev_max * sizeof(struct scsi_tape *), GFP_ATOMIC); if (tmp_da == NULL) { write_unlock(&st_dev_arr_lock); printk(KERN_ERR "st: Can't extend device array.\n"); goto out_put_disk; } - memset(tmp_da, 0, tmp_dev_max * sizeof(struct scsi_tape *)); if (scsi_tapes != NULL) { memcpy(tmp_da, scsi_tapes, st_dev_max * sizeof(struct scsi_tape *)); @@ -3948,13 +3946,12 @@ static int st_probe(struct device *dev) if (i >= st_dev_max) panic("scsi_devices corrupt (st)"); - tpnt = kmalloc(sizeof(struct scsi_tape), GFP_ATOMIC); + tpnt = kzalloc(sizeof(struct scsi_tape), GFP_ATOMIC); if (tpnt == NULL) { write_unlock(&st_dev_arr_lock); printk(KERN_ERR "st: Can't allocate device descriptor.\n"); goto out_put_disk; } - memset(tpnt, 0, sizeof(struct scsi_tape)); kref_init(&tpnt->kref); tpnt->disk = disk; sprintf(disk->disk_name, "st%d", i); -- cgit v1.2.3-59-g8ed1b From 5e3c34c1e988a0dfe177c38cf324e8e321c55ef5 Mon Sep 17 00:00:00 2001 From: Greg KH Date: Wed, 18 Jan 2006 16:17:46 -0800 Subject: [SCSI] Remove devfs support from the SCSI subsystem As devfs has been disabled from the kernel tree for a number of months now (5 to be exact), here's a patch against 2.6.16-rc1-git1 that removes support for it from the SCSI subsystem. The patch also removes the scsi_disk devfs_name field as it's no longer needed. Signed-off-by: Greg Kroah-Hartman Signed-off-by: James Bottomley --- drivers/scsi/osst.c | 24 ++---------------------- drivers/scsi/scsi.c | 3 --- drivers/scsi/scsi_scan.c | 6 +----- drivers/scsi/sd.c | 2 -- drivers/scsi/sg.c | 10 ++-------- drivers/scsi/sr.c | 2 -- drivers/scsi/st.c | 20 -------------------- include/scsi/scsi_device.h | 1 - 8 files changed, 5 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index d9946bd95492..b9f6084fdd9e 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -48,7 +48,6 @@ static const char * osst_version = "0.99.3"; #include #include #include -#include #include #include #include @@ -107,8 +106,6 @@ static struct osst_dev_parm { }; #endif -static char *osst_formats[ST_NBR_MODES] ={"", "l", "m", "a"}; - /* Some default definitions have been moved to osst_options.h */ #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE) #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE) @@ -5667,7 +5664,7 @@ static int osst_probe(struct device *dev) struct st_partstat * STps; struct osst_buffer * buffer; struct gendisk * drive; - int i, mode, dev_num; + int i, dev_num; if (SDp->type != TYPE_TAPE || !osst_supports(SDp)) return -ENODEV; @@ -5803,18 +5800,6 @@ static int osst_probe(struct device *dev) snprintf(name, 8, "%s%s", "n", tape_name(tpnt)); osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name); } - for (mode = 0; mode < ST_NBR_MODES; ++mode) { - /* Rewind entry */ - devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)), - S_IFCHR | S_IRUGO | S_IWUGO, - "%s/ot%s", SDp->devfs_name, osst_formats[mode]); - - /* No-rewind entry */ - devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128), - S_IFCHR | S_IRUGO | S_IWUGO, - "%s/ot%sn", SDp->devfs_name, osst_formats[mode]); - } - drive->number = devfs_register_tape(SDp->devfs_name); sdev_printk(KERN_INFO, SDp, "osst :I: Attached OnStream %.5s tape as %s\n", @@ -5831,7 +5816,7 @@ static int osst_remove(struct device *dev) { struct scsi_device * SDp = to_scsi_device(dev); struct osst_tape * tpnt; - int i, mode; + int i; if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0)) return 0; @@ -5842,11 +5827,6 @@ static int osst_remove(struct device *dev) osst_sysfs_destroy(MKDEV(OSST_MAJOR, i)); osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128)); tpnt->device = NULL; - for (mode = 0; mode < ST_NBR_MODES; ++mode) { - devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]); - devfs_remove("%s/ot%sn", SDp->devfs_name, osst_formats[mode]); - } - devfs_unregister_tape(tpnt->drive->number); put_disk(tpnt->drive); os_scsi_tapes[i] = NULL; osst_nr_dev--; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 11b27ba0cd41..6913b0623167 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -1247,7 +1246,6 @@ static int __init init_scsi(void) for_each_cpu(i) INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); - devfs_mk_dir("scsi"); printk(KERN_NOTICE "SCSI subsystem initialized\n"); return 0; @@ -1272,7 +1270,6 @@ static void __exit exit_scsi(void) scsi_exit_sysctl(); scsi_exit_hosts(); scsi_exit_devinfo(); - devfs_remove("scsi"); scsi_exit_procfs(); scsi_exit_queue(); } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 74863da1d630..dfdbbd008630 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -687,12 +687,8 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) if (inq_result[7] & 0x10) sdev->sdtr = 1; - sprintf(sdev->devfs_name, "scsi/host%d/bus%d/target%d/lun%d", - sdev->host->host_no, sdev->channel, - sdev->id, sdev->lun); - /* - * End driverfs/devfs code. + * End sysfs code. */ if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) && diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8ba2d988d051..76b4d14c0b3f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1571,8 +1571,6 @@ static int sd_probe(struct device *dev) 'a' + m1, 'a' + m2, 'a' + m3); } - strcpy(gd->devfs_name, sdp->devfs_name); - gd->private_data = &sdkp->driver; gd->queue = sdkp->device->request_queue; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index ecf2f6010e76..06fc8ed720fc 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -44,7 +44,6 @@ static int sg_version_num = 30533; /* 2 digits for each component */ #include #include #include -#include #include #include #include @@ -1456,14 +1455,10 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) k = error; sdp = sg_dev_arr[k]; - devfs_mk_cdev(MKDEV(SCSI_GENERIC_MAJOR, k), - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, - "%s/generic", scsidp->devfs_name); error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, k), 1); - if (error) { - devfs_remove("%s/generic", scsidp->devfs_name); + if (error) goto out; - } + sdp->cdev = cdev; if (sg_sysfs_valid) { struct class_device * sg_class_member; @@ -1553,7 +1548,6 @@ sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf) class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, k)); cdev_del(sdp->cdev); sdp->cdev = NULL; - devfs_remove("%s/generic", scsidp->devfs_name); put_disk(sdp->disk); sdp->disk = NULL; if (NULL == sdp->headfp) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index d8d12a1718bf..328837b7ccb9 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -573,8 +573,6 @@ static int sr_probe(struct device *dev) get_capabilities(cd); sr_vendor_init(cd); - snprintf(disk->devfs_name, sizeof(disk->devfs_name), - "%s/cd", sdev->devfs_name); disk->driverfs_dev = &sdev->sdev_gendev; set_capacity(disk, cd->capacity); disk->private_data = &cd->driver; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index f0606da19d02..31c6eefba9d6 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -35,7 +35,6 @@ static const char *verstr = "20050830"; #include #include #include -#include #include #include #include @@ -4053,21 +4052,6 @@ static int st_probe(struct device *dev) do_create_class_files(tpnt, dev_num, mode); } - for (mode = 0; mode < ST_NBR_MODES; ++mode) { - /* Make sure that the minor numbers corresponding to the four - first modes always get the same names */ - i = mode << (4 - ST_NBR_MODE_BITS); - /* Rewind entry */ - devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, 0)), - S_IFCHR | S_IRUGO | S_IWUGO, - "%s/mt%s", SDp->devfs_name, st_formats[i]); - /* No-rewind entry */ - devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, 1)), - S_IFCHR | S_IRUGO | S_IWUGO, - "%s/mt%sn", SDp->devfs_name, st_formats[i]); - } - disk->number = devfs_register_tape(SDp->devfs_name); - sdev_printk(KERN_WARNING, SDp, "Attached scsi tape %s", tape_name(tpnt)); printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n", @@ -4121,13 +4105,9 @@ static int st_remove(struct device *dev) scsi_tapes[i] = NULL; st_nr_dev--; write_unlock(&st_dev_arr_lock); - devfs_unregister_tape(tpnt->disk->number); sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, "tape"); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - j = mode << (4 - ST_NBR_MODE_BITS); - devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[j]); - devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[j]); for (j=0; j < 2; j++) { class_device_destroy(st_sysfs_class, MKDEV(SCSI_TAPE_MAJOR, diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 290e3b4d2aec..cde84b39bb65 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -73,7 +73,6 @@ struct scsi_device { unsigned sector_size; /* size in bytes */ void *hostdata; /* available to low-level driver */ - char devfs_name[256]; /* devfs junk */ char type; char scsi_level; char inq_periph_qual; /* PQ from INQUIRY data */ -- cgit v1.2.3-59-g8ed1b From 4f8d98abaf957691f9543b9b1b610d49aa0f662b Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Thu, 2 Feb 2006 17:20:05 -0700 Subject: [SCSI] fusion - mptlan - remove wierd humor print Removes wierd humor, and bad language printk in mptlan. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptlan.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 73f59528212a..314c3a27585d 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -1152,10 +1152,7 @@ mpt_lan_receive_post_reply(struct net_device *dev, priv->mpt_rxfidx_tail, MPT_LAN_MAX_BUCKETS_OUT); - panic("Damn it Jim! I'm a doctor, not a programmer! " - "Oh, wait a sec, I am a programmer. " - "And, who's Jim?!?!\n" - "Arrgghh! We've done it again!\n"); + return -1; } if (remaining == 0) -- cgit v1.2.3-59-g8ed1b From f8a88b19b9d4f59bd625b4852c1b1138a5cf89f3 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 3 Feb 2006 16:52:42 -0600 Subject: [SCSI] PCI Error Recovery: IPR SCSI device driver Various PCI bus errors can be signaled by newer PCI controllers. This patch adds the PCI error recovery callbacks to the IPR SCSI device driver. The patch has been tested, and appears to work well. Signed-off-by: Linas Vepstas Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 2bba5e55d7bc..5890e5f92d82 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -5830,6 +5830,109 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg, shutdown_type); } +/** + * ipr_reset_freeze - Hold off all I/O activity + * @ipr_cmd: ipr command struct + * + * Description: If the PCI slot is frozen, hold off all I/O + * activity; then, as soon as the slot is available again, + * initiate an adapter reset. + */ +static int ipr_reset_freeze(struct ipr_cmnd *ipr_cmd) +{ + /* Disallow new interrupts, avoid loop */ + ipr_cmd->ioa_cfg->allow_interrupts = 0; + list_add_tail(&ipr_cmd->queue, &ipr_cmd->ioa_cfg->pending_q); + ipr_cmd->done = ipr_reset_ioa_job; + return IPR_RC_JOB_RETURN; +} + +/** + * ipr_pci_frozen - Called when slot has experienced a PCI bus error. + * @pdev: PCI device struct + * + * Description: This routine is called to tell us that the PCI bus + * is down. Can't do anything here, except put the device driver + * into a holding pattern, waiting for the PCI bus to come back. + */ +static void ipr_pci_frozen(struct pci_dev *pdev) +{ + unsigned long flags = 0; + struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); + + spin_lock_irqsave(ioa_cfg->host->host_lock, flags); + _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_freeze, IPR_SHUTDOWN_NONE); + spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); +} + +/** + * ipr_pci_slot_reset - Called when PCI slot has been reset. + * @pdev: PCI device struct + * + * Description: This routine is called by the pci error recovery + * code after the PCI slot has been reset, just before we + * should resume normal operations. + */ +static pci_ers_result_t ipr_pci_slot_reset(struct pci_dev *pdev) +{ + unsigned long flags = 0; + struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); + + spin_lock_irqsave(ioa_cfg->host->host_lock, flags); + _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space, + IPR_SHUTDOWN_NONE); + spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); + return PCI_ERS_RESULT_RECOVERED; +} + +/** + * ipr_pci_perm_failure - Called when PCI slot is dead for good. + * @pdev: PCI device struct + * + * Description: This routine is called when the PCI bus has + * permanently failed. + */ +static void ipr_pci_perm_failure(struct pci_dev *pdev) +{ + unsigned long flags = 0; + struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); + + spin_lock_irqsave(ioa_cfg->host->host_lock, flags); + if (ioa_cfg->sdt_state == WAIT_FOR_DUMP) + ioa_cfg->sdt_state = ABORT_DUMP; + ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES; + ioa_cfg->in_ioa_bringdown = 1; + ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); + spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); +} + +/** + * ipr_pci_error_detected - Called when a PCI error is detected. + * @pdev: PCI device struct + * @state: PCI channel state + * + * Description: Called when a PCI error is detected. + * + * Return value: + * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT + */ +static pci_ers_result_t ipr_pci_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + switch (state) { + case pci_channel_io_frozen: + ipr_pci_frozen(pdev); + return PCI_ERS_RESULT_NEED_RESET; + case pci_channel_io_perm_failure: + ipr_pci_perm_failure(pdev); + return PCI_ERS_RESULT_DISCONNECT; + break; + default: + break; + } + return PCI_ERS_RESULT_NEED_RESET; +} + /** * ipr_probe_ioa_part2 - Initializes IOAs found in ipr_probe_ioa(..) * @ioa_cfg: ioa cfg struct @@ -6601,12 +6704,18 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { }; MODULE_DEVICE_TABLE(pci, ipr_pci_table); +static struct pci_error_handlers ipr_err_handler = { + .error_detected = ipr_pci_error_detected, + .slot_reset = ipr_pci_slot_reset, +}; + static struct pci_driver ipr_driver = { .name = IPR_NAME, .id_table = ipr_pci_table, .probe = ipr_probe, .remove = ipr_remove, .shutdown = ipr_shutdown, + .err_handler = &ipr_err_handler, }; /** -- cgit v1.2.3-59-g8ed1b From 03fbcbcd57e9d1bc5a4fe6a81c1845e7365ddabc Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 25 Jan 2006 02:00:52 +0100 Subject: [SCSI] drivers/message/fusion/mptfc.c: make 2 functions static This patch makes two needlessly global functions static. Signed-off-by: Adrian Bunk Signed-off-by: James Bottomley --- drivers/message/fusion/mptfc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index c3a3499bce2a..8ea12ea652ad 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(pci, mptfc_pci_table); static struct scsi_transport_template *mptfc_transport_template = NULL; -struct fc_function_template mptfc_transport_functions = { +static struct fc_function_template mptfc_transport_functions = { .dd_fcrport_size = 8, .show_host_node_name = 1, .show_host_port_name = 1, @@ -514,7 +514,7 @@ mptfc_target_alloc(struct scsi_target *starget) * Return non-zero if allocation fails. * Init memory once per LUN. */ -int +static int mptfc_slave_alloc(struct scsi_device *sdev) { MPT_SCSI_HOST *hd; -- cgit v1.2.3-59-g8ed1b From 1acc0b0ba409dcf4909890fb33e0829f7fd400be Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 4 Jan 2006 18:30:03 -0800 Subject: [SCSI] cciss: kfree(NULL) is legal Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/block/cciss.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 0d65394707db..b9c786ee6fad 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3251,8 +3251,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, clean4: #ifdef CONFIG_CISS_SCSI_TAPE - if(hba[i]->scsi_rejects.complete) - kfree(hba[i]->scsi_rejects.complete); + kfree(hba[i]->scsi_rejects.complete); #endif kfree(hba[i]->cmd_pool_bits); if(hba[i]->cmd_pool) -- cgit v1.2.3-59-g8ed1b From a97a83a06b44d4d1cb01191423caf9813a150b95 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 5 Feb 2006 08:01:33 -0700 Subject: [SCSI] fix uninitialized variable error in __scsi_add_device, sdev may be uninitialised if scsi_host_scan_allowed() returns false. Fix by initialising at the top of the routine. Also rely on the fact that scsi_probe_and_add_lun() only actually fills in the sdev pointer if the SCSI_SCAN_LUN_PRESENT case (so no need to check the return value). Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index dfdbbd008630..803c7b9690c5 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1243,9 +1243,8 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, uint id, uint lun, void *hostdata) { - struct scsi_device *sdev; + struct scsi_device *sdev = ERR_PTR(-ENODEV); struct device *parent = &shost->shost_gendev; - int res; struct scsi_target *starget; starget = scsi_alloc_target(parent, channel, id); @@ -1254,12 +1253,8 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, get_device(&starget->dev); mutex_lock(&shost->scan_mutex); - if (scsi_host_scan_allowed(shost)) { - res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, - hostdata); - if (res != SCSI_SCAN_LUN_PRESENT) - sdev = ERR_PTR(-ENODEV); - } + if (scsi_host_scan_allowed(shost)) + scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); mutex_unlock(&shost->scan_mutex); scsi_target_reap(starget); put_device(&starget->dev); -- cgit v1.2.3-59-g8ed1b From ea697e456a278fb74a925a6c6befe04054520994 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 7 Feb 2006 08:01:02 -0700 Subject: [SCSI] unused show_spi_transport_period_helper parameter show_spi_transport_period_helper() doesn't need the class_device parameter Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index a1e521b58b67..97f4be62f748 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -401,8 +401,7 @@ static int period_to_str(char *buf, int period) } static ssize_t -show_spi_transport_period_helper(struct class_device *cdev, char *buf, - int period) +show_spi_transport_period_helper(char *buf, int period) { int len = period_to_str(buf, period); buf[len++] = '\n'; @@ -459,7 +458,7 @@ show_spi_transport_period(struct class_device *cdev, char *buf) if (i->f->get_period) i->f->get_period(starget); - return show_spi_transport_period_helper(cdev, buf, tp->period); + return show_spi_transport_period_helper(buf, tp->period); } static ssize_t @@ -494,7 +493,7 @@ show_spi_transport_min_period(struct class_device *cdev, char *buf) struct spi_transport_attrs *tp = (struct spi_transport_attrs *)&starget->starget_data; - return show_spi_transport_period_helper(cdev, buf, tp->min_period); + return show_spi_transport_period_helper(buf, tp->min_period); } static ssize_t -- cgit v1.2.3-59-g8ed1b From b0dc1db15225d5801bf3105966c9ce12c5142013 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 17 Feb 2006 13:18:41 -0700 Subject: [SCSI] ncr53c8xx update Delete unused NAME53C definition Remove use of the M_* constants; use the common SCSI constants instead Translate some remaining German Add a missing changelog entry Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/ncr53c8xx.c | 118 +++++++++++++++++++++++------------------------ drivers/scsi/ncr53c8xx.h | 37 ++------------- 2 files changed, 61 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 32350707b940..abb1859bff09 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -69,6 +69,10 @@ ** Low PCI traffic for command handling when on-chip RAM is present. ** Aggressive SCSI SCRIPTS optimizations. ** +** 2005 by Matthew Wilcox and James Bottomley +** PCI-ectomy. This driver now supports only the 720 chip (see the +** NCR_Q720 and zalon drivers for the bus probe logic). +** ******************************************************************************* */ @@ -90,13 +94,6 @@ #define SCSI_NCR_DEBUG_FLAGS (0) -/*========================================================== -** -** Include files -** -**========================================================== -*/ - #include #include #include @@ -121,6 +118,7 @@ #include #include +#include #include #include #include @@ -128,10 +126,8 @@ #include "ncr53c8xx.h" -#define NAME53C "ncr53c" #define NAME53C8XX "ncr53c8xx" - /*========================================================== ** ** Debugging tags @@ -2111,7 +2107,7 @@ static struct script script0 __initdata = { */ /* - ** The M_REJECT problem seems to be due to a selection + ** The MESSAGE_REJECT problem seems to be due to a selection ** timing problem. ** Wait immediately for the selection to complete. ** (2.5x behaves so) @@ -2162,7 +2158,7 @@ static struct script script0 __initdata = { /* ** Selection complete. ** Send the IDENTIFY and SIMPLE_TAG messages - ** (and the M_X_SYNC_REQ message) + ** (and the EXTENDED_SDTR message) */ SCR_MOVE_TBL ^ SCR_MSG_OUT, offsetof (struct dsb, smsg), @@ -2191,7 +2187,7 @@ static struct script script0 __initdata = { /* ** Initialize the msgout buffer with a NOOP message. */ - SCR_LOAD_REG (scratcha, M_NOOP), + SCR_LOAD_REG (scratcha, NOP), 0, SCR_COPY (1), RADDR (scratcha), @@ -2343,21 +2339,21 @@ static struct script script0 __initdata = { /* ** Handle this message. */ - SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)), + SCR_JUMP ^ IFTRUE (DATA (COMMAND_COMPLETE)), PADDR (complete), - SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), + SCR_JUMP ^ IFTRUE (DATA (DISCONNECT)), PADDR (disconnect), - SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)), + SCR_JUMP ^ IFTRUE (DATA (SAVE_POINTERS)), PADDR (save_dp), - SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)), + SCR_JUMP ^ IFTRUE (DATA (RESTORE_POINTERS)), PADDR (restore_dp), - SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), + SCR_JUMP ^ IFTRUE (DATA (EXTENDED_MESSAGE)), PADDRH (msg_extended), - SCR_JUMP ^ IFTRUE (DATA (M_NOOP)), + SCR_JUMP ^ IFTRUE (DATA (NOP)), PADDR (clrack), - SCR_JUMP ^ IFTRUE (DATA (M_REJECT)), + SCR_JUMP ^ IFTRUE (DATA (MESSAGE_REJECT)), PADDRH (msg_reject), - SCR_JUMP ^ IFTRUE (DATA (M_IGN_RESIDUE)), + SCR_JUMP ^ IFTRUE (DATA (IGNORE_WIDE_RESIDUE)), PADDRH (msg_ign_residue), /* ** Rest of the messages left as @@ -2372,7 +2368,7 @@ static struct script script0 __initdata = { */ SCR_INT, SIR_REJECT_SENT, - SCR_LOAD_REG (scratcha, M_REJECT), + SCR_LOAD_REG (scratcha, MESSAGE_REJECT), 0, }/*-------------------------< SETMSG >----------------------*/,{ SCR_COPY (1), @@ -2564,7 +2560,7 @@ static struct script script0 __initdata = { /* ** If it was no ABORT message ... */ - SCR_JUMP ^ IFTRUE (DATA (M_ABORT)), + SCR_JUMP ^ IFTRUE (DATA (ABORT_TASK_SET)), PADDRH (msg_out_abort), /* ** ... wait for the next phase @@ -2576,7 +2572,7 @@ static struct script script0 __initdata = { /* ** ... else clear the message ... */ - SCR_LOAD_REG (scratcha, M_NOOP), + SCR_LOAD_REG (scratcha, NOP), 0, SCR_COPY (4), RADDR (scratcha), @@ -3035,7 +3031,7 @@ static struct scripth scripth0 __initdata = { */ SCR_MOVE_ABS (1) ^ SCR_MSG_IN, NADDR (msgin[2]), - SCR_JUMP ^ IFTRUE (DATA (M_X_WIDE_REQ)), + SCR_JUMP ^ IFTRUE (DATA (EXTENDED_WDTR)), PADDRH (msg_wdtr), /* ** unknown extended message @@ -3069,7 +3065,7 @@ static struct scripth scripth0 __initdata = { }/*-------------------------< SEND_WDTR >----------------*/,{ /* - ** Send the M_X_WIDE_REQ + ** Send the EXTENDED_WDTR */ SCR_MOVE_ABS (4) ^ SCR_MSG_OUT, NADDR (msgout), @@ -3089,7 +3085,7 @@ static struct scripth scripth0 __initdata = { */ SCR_MOVE_ABS (1) ^ SCR_MSG_IN, NADDR (msgin[2]), - SCR_JUMP ^ IFTRUE (DATA (M_X_SYNC_REQ)), + SCR_JUMP ^ IFTRUE (DATA (EXTENDED_SDTR)), PADDRH (msg_sdtr), /* ** unknown extended message @@ -3124,7 +3120,7 @@ static struct scripth scripth0 __initdata = { }/*-------------------------< SEND_SDTR >-------------*/,{ /* - ** Send the M_X_SYNC_REQ + ** Send the EXTENDED_SDTR */ SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, NADDR (msgout), @@ -3202,10 +3198,10 @@ static struct scripth scripth0 __initdata = { }/*-------------------------< RESET >----------------------*/,{ /* - ** Send a M_RESET message if bad IDENTIFY + ** Send a TARGET_RESET message if bad IDENTIFY ** received on reselection. */ - SCR_LOAD_REG (scratcha, M_ABORT_TAG), + SCR_LOAD_REG (scratcha, ABORT_TASK), 0, SCR_JUMP, PADDRH (abort_resel), @@ -3213,7 +3209,7 @@ static struct scripth scripth0 __initdata = { /* ** Abort a wrong tag received on reselection. */ - SCR_LOAD_REG (scratcha, M_ABORT_TAG), + SCR_LOAD_REG (scratcha, ABORT_TASK), 0, SCR_JUMP, PADDRH (abort_resel), @@ -3221,7 +3217,7 @@ static struct scripth scripth0 __initdata = { /* ** Abort a reselection when no active CCB. */ - SCR_LOAD_REG (scratcha, M_ABORT), + SCR_LOAD_REG (scratcha, ABORT_TASK_SET), 0, }/*-------------------------< ABORT_RESEL >----------------*/,{ SCR_COPY (1), @@ -3333,7 +3329,7 @@ static struct scripth scripth0 __initdata = { ** Read the message, since we got it directly ** from the SCSI BUS data lines. ** Signal problem to C code for logging the event. - ** Send a M_ABORT to clear all pending tasks. + ** Send an ABORT_TASK_SET to clear all pending tasks. */ SCR_INT, SIR_RESEL_BAD_LUN, @@ -3345,7 +3341,7 @@ static struct scripth scripth0 __initdata = { /* ** We donnot have a task for that I_T_L. ** Signal problem to C code for logging the event. - ** Send a M_ABORT message. + ** Send an ABORT_TASK_SET message. */ SCR_INT, SIR_RESEL_BAD_I_T_L, @@ -3355,7 +3351,7 @@ static struct scripth scripth0 __initdata = { /* ** We donnot have a task that matches the tag. ** Signal problem to C code for logging the event. - ** Send a M_ABORTTAG message. + ** Send an ABORT_TASK message. */ SCR_INT, SIR_RESEL_BAD_I_T_L_Q, @@ -3366,7 +3362,7 @@ static struct scripth scripth0 __initdata = { ** We donnot know the target that reselected us. ** Grab the first message if any (IDENTIFY). ** Signal problem to C code for logging the event. - ** M_RESET message. + ** TARGET_RESET message. */ SCR_INT, SIR_RESEL_BAD_TARGET, @@ -4109,16 +4105,16 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr) switch (nego) { case NS_SYNC: - msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = EXTENDED_MESSAGE; msgptr[msglen++] = 3; - msgptr[msglen++] = M_X_SYNC_REQ; + msgptr[msglen++] = EXTENDED_SDTR; msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0; msgptr[msglen++] = tp->maxoffs; break; case NS_WIDE: - msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = EXTENDED_MESSAGE; msgptr[msglen++] = 2; - msgptr[msglen++] = M_X_WIDE_REQ; + msgptr[msglen++] = EXTENDED_WDTR; msgptr[msglen++] = tp->usrwide; break; } @@ -4220,7 +4216,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) **---------------------------------------------------- */ - idmsg = M_IDENTIFY | sdev->lun; + idmsg = IDENTIFY(0, sdev->lun); if (cp ->tag != NO_TAG || (cp != np->ccb && np->disc && !(tp->usrflag & UF_NODISC))) @@ -4239,7 +4235,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) */ if (lp && time_after(jiffies, lp->tags_stime)) { if (lp->tags_smap) { - order = M_ORDERED_TAG; + order = ORDERED_QUEUE_TAG; if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){ PRINT_ADDR(cmd, "ordered tag forced.\n"); @@ -4257,10 +4253,10 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) case 0x08: /* READ_SMALL (6) */ case 0x28: /* READ_BIG (10) */ case 0xa8: /* READ_HUGE (12) */ - order = M_SIMPLE_TAG; + order = SIMPLE_QUEUE_TAG; break; default: - order = M_ORDERED_TAG; + order = ORDERED_QUEUE_TAG; } } msgptr[msglen++] = order; @@ -6229,9 +6225,9 @@ static int ncr_int_par (struct ncb *np) if (!(dbc & 0xc0000000)) phase = (dbc >> 24) & 7; if (phase == 7) - msg = M_PARITY; + msg = MSG_PARITY_ERROR; else - msg = M_ID_ERROR; + msg = INITIATOR_ERROR; /* @@ -6795,6 +6791,8 @@ void ncr_int_sir (struct ncb *np) /*----------------------------------------------------------------------------- ** ** Was Sie schon immer ueber transfermode negotiation wissen wollten ... +** ("Everything you've always wanted to know about transfer mode +** negotiation") ** ** We try to negotiate sync and wide transfer only after ** a successful inquire command. We look at byte 7 of the @@ -6896,8 +6894,8 @@ void ncr_int_sir (struct ncb *np) break; } - np->msgin [0] = M_NOOP; - np->msgout[0] = M_NOOP; + np->msgin [0] = NOP; + np->msgout[0] = NOP; cp->nego_status = 0; break; @@ -6991,9 +6989,9 @@ void ncr_int_sir (struct ncb *np) spi_offset(starget) = ofs; ncr_setsync(np, cp, scntl3, (fak<<5)|ofs); - np->msgout[0] = M_EXTENDED; + np->msgout[0] = EXTENDED_MESSAGE; np->msgout[1] = 3; - np->msgout[2] = M_X_SYNC_REQ; + np->msgout[2] = EXTENDED_SDTR; np->msgout[3] = per; np->msgout[4] = ofs; @@ -7007,7 +7005,7 @@ void ncr_int_sir (struct ncb *np) OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad)); return; } - np->msgin [0] = M_NOOP; + np->msgin [0] = NOP; break; @@ -7083,12 +7081,12 @@ void ncr_int_sir (struct ncb *np) spi_width(starget) = wide; ncr_setwide(np, cp, wide, 1); - np->msgout[0] = M_EXTENDED; + np->msgout[0] = EXTENDED_MESSAGE; np->msgout[1] = 2; - np->msgout[2] = M_X_WIDE_REQ; + np->msgout[2] = EXTENDED_WDTR; np->msgout[3] = wide; - np->msgin [0] = M_NOOP; + np->msgin [0] = NOP; cp->nego_status = NS_WIDE; @@ -7107,12 +7105,12 @@ void ncr_int_sir (struct ncb *np) case SIR_REJECT_RECEIVED: /*----------------------------------------------- ** - ** We received a M_REJECT message. + ** We received a MESSAGE_REJECT. ** **----------------------------------------------- */ - PRINT_ADDR(cp->cmd, "M_REJECT received (%x:%x).\n", + PRINT_ADDR(cp->cmd, "MESSAGE_REJECT received (%x:%x).\n", (unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]); break; @@ -7124,7 +7122,7 @@ void ncr_int_sir (struct ncb *np) **----------------------------------------------- */ - ncr_print_msg(cp, "M_REJECT sent for", np->msgin); + ncr_print_msg(cp, "MESSAGE_REJECT sent for", np->msgin); break; /*-------------------------------------------------------------------- @@ -7143,7 +7141,7 @@ void ncr_int_sir (struct ncb *np) **----------------------------------------------- */ - PRINT_ADDR(cp->cmd, "M_IGN_RESIDUE received, but not yet " + PRINT_ADDR(cp->cmd, "IGNORE_WIDE_RESIDUE received, but not yet " "implemented.\n"); break; #if 0 @@ -7156,7 +7154,7 @@ void ncr_int_sir (struct ncb *np) **----------------------------------------------- */ - PRINT_ADDR(cp->cmd, "M_DISCONNECT received, but datapointer " + PRINT_ADDR(cp->cmd, "DISCONNECT received, but datapointer " "not saved: data=%x save=%x goal=%x.\n", (unsigned) INL (nc_temp), (unsigned) scr_to_cpu(np->header.savep), @@ -7862,7 +7860,7 @@ static int __init ncr_snooptest (struct ncb* np) **========================================================== ** ** Note: we have to return the correct value. -** THERE IS NO SAVE DEFAULT VALUE. +** THERE IS NO SAFE DEFAULT VALUE. ** ** Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock. ** 53C860 and 53C875 rev. 1 support fast20 transfers but @@ -8562,7 +8560,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, /* use SIMPLE TAG messages by default */ #ifdef SCSI_NCR_ALWAYS_SIMPLE_TAG - np->order = M_SIMPLE_TAG; + np->order = SIMPLE_QUEUE_TAG; #endif spin_unlock_irqrestore(&np->smp_lock, flags); diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h index 6a7bef2e6118..0e4e46a01336 100644 --- a/drivers/scsi/ncr53c8xx.h +++ b/drivers/scsi/ncr53c8xx.h @@ -56,8 +56,10 @@ #include #include +#include + /* -** If you want a driver as small as possible, do not define the +** If you want a driver as small as possible, donnot define the ** following options. */ #define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT @@ -1254,39 +1256,6 @@ struct scr_tblsel { **----------------------------------------------------------- */ -/* -** Messages -*/ - -#define M_COMPLETE COMMAND_COMPLETE -#define M_EXTENDED EXTENDED_MESSAGE -#define M_SAVE_DP SAVE_POINTERS -#define M_RESTORE_DP RESTORE_POINTERS -#define M_DISCONNECT DISCONNECT -#define M_ID_ERROR INITIATOR_ERROR -#define M_ABORT ABORT_TASK_SET -#define M_REJECT MESSAGE_REJECT -#define M_NOOP NOP -#define M_PARITY MSG_PARITY_ERROR -#define M_LCOMPLETE LINKED_CMD_COMPLETE -#define M_FCOMPLETE LINKED_FLG_CMD_COMPLETE -#define M_RESET TARGET_RESET -#define M_ABORT_TAG ABORT_TASK -#define M_CLEAR_QUEUE CLEAR_TASK_SET -#define M_INIT_REC INITIATE_RECOVERY -#define M_REL_REC RELEASE_RECOVERY -#define M_TERMINATE (0x11) -#define M_SIMPLE_TAG SIMPLE_QUEUE_TAG -#define M_HEAD_TAG HEAD_OF_QUEUE_TAG -#define M_ORDERED_TAG ORDERED_QUEUE_TAG -#define M_IGN_RESIDUE IGNORE_WIDE_RESIDUE -#define M_IDENTIFY (0x80) - -#define M_X_MODIFY_DP EXTENDED_MODIFY_DATA_POINTER -#define M_X_SYNC_REQ EXTENDED_SDTR -#define M_X_WIDE_REQ EXTENDED_WDTR -#define M_X_PPR_REQ EXTENDED_PPR - /* ** Status */ -- cgit v1.2.3-59-g8ed1b From 6ea3c0b2dac0d6a857d6bc010e544f4c901fff78 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 7 Feb 2006 07:54:46 -0700 Subject: [SCSI] Add spi_populate_*_msg functions Introduce new helpers: - spi_populate_width_msg() - spi_populate_sync_msg() - spi_populate_ppr_msg() and use them in drivers which already enable the SPI transport. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/53c700.c | 18 +++---------- drivers/scsi/aha152x.c | 7 +---- drivers/scsi/aic7xxx/aic79xx_core.c | 24 +++++------------ drivers/scsi/aic7xxx/aic7xxx_core.c | 24 +++++------------ drivers/scsi/ncr53c8xx.c | 25 ++++------------- drivers/scsi/scsi_transport_spi.c | 33 +++++++++++++++++++++++ drivers/scsi/sym53c8xx_2/sym_hipd.c | 53 +++++++++---------------------------- include/scsi/scsi_transport_spi.h | 4 +++ 8 files changed, 73 insertions(+), 115 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 4ce7438608ec..6a0f9506ea00 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -238,14 +238,6 @@ static char *NCR_700_SBCL_to_phase[] = { "MSG IN", }; -static __u8 NCR_700_SDTR_msg[] = { - 0x01, /* Extended message */ - 0x03, /* Extended message Length */ - 0x01, /* SDTR Extended message */ - NCR_700_MIN_PERIOD, - NCR_700_MAX_OFFSET -}; - /* This translates the SDTR message offset and period to a value * which can be loaded into the SXFER_REG. * @@ -266,7 +258,7 @@ NCR_700_offset_period_to_sxfer(struct NCR_700_Host_Parameters *hostdata, return 0; if(period < hostdata->min_period) { - printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_SDTR_msg[3]*4); + printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_MIN_PERIOD*4); period = hostdata->min_period; } XFERP = (period*4 * hostdata->sync_clock)/1000 - 4; @@ -1434,11 +1426,9 @@ NCR_700_start_command(struct scsi_cmnd *SCp) if(hostdata->fast && NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) { - memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg, - sizeof(NCR_700_SDTR_msg)); - hostdata->msgout[count+3] = spi_period(SCp->device->sdev_target); - hostdata->msgout[count+4] = spi_offset(SCp->device->sdev_target); - count += sizeof(NCR_700_SDTR_msg); + count += spi_populate_sync_msg(&hostdata->msgout[count], + spi_period(SCp->device->sdev_target), + spi_offset(SCp->device->sdev_target)); NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index cb2ee25f213f..67d78ed7119a 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -1708,12 +1708,7 @@ static void seldo_run(struct Scsi_Host *shpnt) ADDMSGO(BUS_DEVICE_RESET); } else if (SYNCNEG==0 && SYNCHRONOUS) { CURRENT_SC->SCp.phase |= syncneg; - ADDMSGO(EXTENDED_MESSAGE); - ADDMSGO(3); - ADDMSGO(EXTENDED_SDTR); - ADDMSGO(50); /* 200ns */ - ADDMSGO(8); /* 8 byte req/ack offset */ - + MSGOLEN += spi_populate_sync_msg(&MSGO(MSGOLEN), 50, 8); SYNCNEG=1; /* negotiation in progress */ } diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 342f77966a5b..b6266fd31688 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -3762,11 +3762,8 @@ ahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, { if (offset == 0) period = AHD_ASYNC_XFER_PERIOD; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR; - ahd->msgout_buf[ahd->msgout_index++] = period; - ahd->msgout_buf[ahd->msgout_index++] = offset; + ahd->msgout_index += spi_populate_sync_msg( + ahd->msgout_buf + ahd->msgout_index, period, offset); ahd->msgout_len += 5; if (bootverbose) { printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", @@ -3783,10 +3780,8 @@ static void ahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, u_int bus_width) { - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR; - ahd->msgout_buf[ahd->msgout_index++] = bus_width; + ahd->msgout_index += spi_populate_width_msg( + ahd->msgout_buf + ahd->msgout_index, bus_width); ahd->msgout_len += 4; if (bootverbose) { printf("(%s:%c:%d:%d): Sending WDTR %x\n", @@ -3813,14 +3808,9 @@ ahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ppr_options |= MSG_EXT_PPR_PCOMP_EN; if (offset == 0) period = AHD_ASYNC_XFER_PERIOD; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR; - ahd->msgout_buf[ahd->msgout_index++] = period; - ahd->msgout_buf[ahd->msgout_index++] = 0; - ahd->msgout_buf[ahd->msgout_index++] = offset; - ahd->msgout_buf[ahd->msgout_index++] = bus_width; - ahd->msgout_buf[ahd->msgout_index++] = ppr_options; + ahd->msgout_index += spi_populate_ppr_msg( + ahd->msgout_buf + ahd->msgout_index, period, offset, + bus_width, ppr_options); ahd->msgout_len += 8; if (bootverbose) { printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 58ac46103eb6..d37566978fba 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -2461,11 +2461,8 @@ ahc_construct_sdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, { if (offset == 0) period = AHC_ASYNC_XFER_PERIOD; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR_LEN; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR; - ahc->msgout_buf[ahc->msgout_index++] = period; - ahc->msgout_buf[ahc->msgout_index++] = offset; + ahc->msgout_index += spi_populate_sync_msg( + ahc->msgout_buf + ahc->msgout_index, period, offset); ahc->msgout_len += 5; if (bootverbose) { printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", @@ -2482,10 +2479,8 @@ static void ahc_construct_wdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, u_int bus_width) { - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR_LEN; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR; - ahc->msgout_buf[ahc->msgout_index++] = bus_width; + ahc->msgout_index += spi_populate_width_msg( + ahc->msgout_buf + ahc->msgout_index, bus_width); ahc->msgout_len += 4; if (bootverbose) { printf("(%s:%c:%d:%d): Sending WDTR %x\n", @@ -2505,14 +2500,9 @@ ahc_construct_ppr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, { if (offset == 0) period = AHC_ASYNC_XFER_PERIOD; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR_LEN; - ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR; - ahc->msgout_buf[ahc->msgout_index++] = period; - ahc->msgout_buf[ahc->msgout_index++] = 0; - ahc->msgout_buf[ahc->msgout_index++] = offset; - ahc->msgout_buf[ahc->msgout_index++] = bus_width; - ahc->msgout_buf[ahc->msgout_index++] = ppr_options; + ahc->msgout_index += spi_populate_ppr_msg( + ahc->msgout_buf + ahc->msgout_index, period, offset, + bus_width, ppr_options); ahc->msgout_len += 8; if (bootverbose) { printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index abb1859bff09..22f913127f08 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -4105,17 +4105,11 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr) switch (nego) { case NS_SYNC: - msgptr[msglen++] = EXTENDED_MESSAGE; - msgptr[msglen++] = 3; - msgptr[msglen++] = EXTENDED_SDTR; - msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0; - msgptr[msglen++] = tp->maxoffs; + msglen += spi_populate_sync_msg(msgptr + msglen, + tp->maxoffs ? tp->minsync : 0, tp->maxoffs); break; case NS_WIDE: - msgptr[msglen++] = EXTENDED_MESSAGE; - msgptr[msglen++] = 2; - msgptr[msglen++] = EXTENDED_WDTR; - msgptr[msglen++] = tp->usrwide; + msglen += spi_populate_width_msg(msgptr + msglen, tp->usrwide); break; } @@ -6989,12 +6983,7 @@ void ncr_int_sir (struct ncb *np) spi_offset(starget) = ofs; ncr_setsync(np, cp, scntl3, (fak<<5)|ofs); - np->msgout[0] = EXTENDED_MESSAGE; - np->msgout[1] = 3; - np->msgout[2] = EXTENDED_SDTR; - np->msgout[3] = per; - np->msgout[4] = ofs; - + spi_populate_sync_msg(np->msgout, per, ofs); cp->nego_status = NS_SYNC; if (DEBUG_FLAGS & DEBUG_NEGO) { @@ -7080,11 +7069,7 @@ void ncr_int_sir (struct ncb *np) spi_width(starget) = wide; ncr_setwide(np, cp, wide, 1); - - np->msgout[0] = EXTENDED_MESSAGE; - np->msgout[1] = 2; - np->msgout[2] = EXTENDED_WDTR; - np->msgout[3] = wide; + spi_populate_width_msg(np->msgout, wide); np->msgin [0] = NOP; diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 97f4be62f748..c0051a432a97 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -1051,6 +1051,39 @@ void spi_display_xfer_agreement(struct scsi_target *starget) } EXPORT_SYMBOL(spi_display_xfer_agreement); +int spi_populate_width_msg(unsigned char *msg, int width) +{ + msg[0] = EXTENDED_MESSAGE; + msg[1] = 2; + msg[2] = EXTENDED_WDTR; + msg[3] = width; + return 4; +} + +int spi_populate_sync_msg(unsigned char *msg, int period, int offset) +{ + msg[0] = EXTENDED_MESSAGE; + msg[1] = 3; + msg[2] = EXTENDED_SDTR; + msg[3] = period; + msg[4] = offset; + return 5; +} + +int spi_populate_ppr_msg(unsigned char *msg, int period, int offset, + int width, int options) +{ + msg[0] = EXTENDED_MESSAGE; + msg[1] = 6; + msg[2] = EXTENDED_PPR; + msg[3] = period; + msg[4] = 0; + msg[5] = offset; + msg[6] = width; + msg[7] = options; + return 8; +} + #ifdef CONFIG_SCSI_CONSTANTS static const char * const one_byte_msgs[] = { /* 0x00 */ "Command Complete", NULL, "Save Pointers", diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index f4854c33f48d..620b4726fbd9 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -40,7 +40,6 @@ #include #include /* for timeouts in units of HZ */ -#include #include "sym_glue.h" #include "sym_nvram.h" @@ -1430,29 +1429,18 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp switch (nego) { case NS_SYNC: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 3; - msgptr[msglen++] = M_X_SYNC_REQ; - msgptr[msglen++] = goal->period; - msgptr[msglen++] = goal->offset; + msglen += spi_populate_sync_msg(msgptr + msglen, goal->period, + goal->offset); break; case NS_WIDE: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 2; - msgptr[msglen++] = M_X_WIDE_REQ; - msgptr[msglen++] = goal->width; + msglen += spi_populate_width_msg(msgptr + msglen, goal->width); break; case NS_PPR: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 6; - msgptr[msglen++] = M_X_PPR_REQ; - msgptr[msglen++] = goal->period; - msgptr[msglen++] = 0; - msgptr[msglen++] = goal->offset; - msgptr[msglen++] = goal->width; - msgptr[msglen++] = (goal->iu ? PPR_OPT_IU : 0) | + msglen += spi_populate_ppr_msg(msgptr + msglen, goal->period, + goal->offset, goal->width, + (goal->iu ? PPR_OPT_IU : 0) | (goal->dt ? PPR_OPT_DT : 0) | - (goal->qas ? PPR_OPT_QAS : 0); + (goal->qas ? PPR_OPT_QAS : 0)); break; } @@ -3948,11 +3936,7 @@ sym_sync_nego_check(struct sym_hcb *np, int req, struct sym_ccb *cp) /* * It was a request. Prepare an answer message. */ - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 3; - np->msgout[2] = M_X_SYNC_REQ; - np->msgout[3] = per; - np->msgout[4] = ofs; + spi_populate_sync_msg(np->msgout, per, ofs); if (DEBUG_FLAGS & DEBUG_NEGO) { sym_print_nego_msg(np, target, "sync msgout", np->msgout); @@ -4078,14 +4062,7 @@ sym_ppr_nego_check(struct sym_hcb *np, int req, int target) /* * It was a request. Prepare an answer message. */ - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 6; - np->msgout[2] = M_X_PPR_REQ; - np->msgout[3] = per; - np->msgout[4] = 0; - np->msgout[5] = ofs; - np->msgout[6] = wide; - np->msgout[7] = opts; + spi_populate_ppr_msg(np->msgout, per, ofs, wide, opts); if (DEBUG_FLAGS & DEBUG_NEGO) { sym_print_nego_msg(np, target, "ppr msgout", np->msgout); @@ -4197,10 +4174,7 @@ sym_wide_nego_check(struct sym_hcb *np, int req, struct sym_ccb *cp) /* * It was a request. Prepare an answer message. */ - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 2; - np->msgout[2] = M_X_WIDE_REQ; - np->msgout[3] = wide; + spi_populate_width_msg(np->msgout, wide); np->msgin [0] = M_NOOP; @@ -4245,11 +4219,8 @@ static void sym_wide_nego(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb * a single SCSI command (Suggested by Justin Gibbs). */ if (tp->tgoal.offset) { - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 3; - np->msgout[2] = M_X_SYNC_REQ; - np->msgout[3] = tp->tgoal.period; - np->msgout[4] = tp->tgoal.offset; + spi_populate_sync_msg(np->msgout, tp->tgoal.period, + tp->tgoal.offset); if (DEBUG_FLAGS & DEBUG_NEGO) { sym_print_nego_msg(np, cp->target, diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h index fb5a2ffae939..5e1d61913d4e 100644 --- a/include/scsi/scsi_transport_spi.h +++ b/include/scsi/scsi_transport_spi.h @@ -148,5 +148,9 @@ void spi_schedule_dv_device(struct scsi_device *); void spi_dv_device(struct scsi_device *); void spi_display_xfer_agreement(struct scsi_target *); int spi_print_msg(const unsigned char *); +int spi_populate_width_msg(unsigned char *msg, int width); +int spi_populate_sync_msg(unsigned char *msg, int period, int offset); +int spi_populate_ppr_msg(unsigned char *msg, int period, int offset, int width, + int options); #endif /* SCSI_TRANSPORT_SPI_H */ -- cgit v1.2.3-59-g8ed1b From e24d873d250f9999ad3703f220e3759c1fb70998 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 7 Feb 2006 08:05:26 -0700 Subject: [SCSI] Make spi_print_msg more consistent Almost all the output from spi_print_msg() has a trailing space. This patch fixes up the three cases that don't. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index c0051a432a97..653f165d65ff 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -1131,7 +1131,7 @@ int spi_print_msg(const unsigned char *msg) (int) msg[2]); switch (msg[2]) { case EXTENDED_MODIFY_DATA_POINTER: - printk("pointer = %d", (int) (msg[3] << 24) | + printk("pointer = %d ", (msg[3] << 24) | (msg[4] << 16) | (msg[5] << 8) | msg[6]); break; case EXTENDED_SDTR: @@ -1157,7 +1157,7 @@ int spi_print_msg(const unsigned char *msg) /* Normal One byte */ } else if (msg[0] < 0x1f) { if (msg[0] < ARRAY_SIZE(one_byte_msgs)) - printk(one_byte_msgs[msg[0]]); + printk("%s ", one_byte_msgs[msg[0]]); else printk("reserved (%02x) ", msg[0]); len = 1; @@ -1171,7 +1171,7 @@ int spi_print_msg(const unsigned char *msg) msg[0], msg[1]); len = 2; } else - printk("reserved"); + printk("reserved "); return len; } EXPORT_SYMBOL(spi_print_msg); -- cgit v1.2.3-59-g8ed1b From 0320503dce208c03f296a09d9a18a992ab88cbd5 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 9 Feb 2006 11:15:49 -0500 Subject: [SCSI] jazz_esp: Delete useless prototype Signed-off-by: James Bottomley --- drivers/scsi/jazz_esp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c index 23728d1c980c..ee8735153dc3 100644 --- a/drivers/scsi/jazz_esp.c +++ b/drivers/scsi/jazz_esp.c @@ -52,7 +52,6 @@ static volatile unsigned char cmd_buffer[16]; * via PIO. */ -int jazz_esp_detect(struct scsi_host_template *tpnt); static int jazz_esp_release(struct Scsi_Host *shost) { if (shost->irq) -- cgit v1.2.3-59-g8ed1b From ae198df37775e4471fae0b023061667275b2f71b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 9 Feb 2006 11:16:27 -0500 Subject: [SCSI] jazz_esp: Fix sparse warnings. Using plain integer as NULL pointer. Signed-off-by: Ralf Baechle Signed-off-by: James Bottomley --- drivers/scsi/jazz_esp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c index ee8735153dc3..a07e930a9c04 100644 --- a/drivers/scsi/jazz_esp.c +++ b/drivers/scsi/jazz_esp.c @@ -95,7 +95,7 @@ static int jazz_esp_detect(struct scsi_host_template *tpnt) * first assumption it is there:-) */ if (1) { - esp_dev = 0; + esp_dev = NULL; esp = esp_allocate(tpnt, (void *) esp_dev); /* Do command transfer with programmed I/O */ @@ -114,13 +114,13 @@ static int jazz_esp_detect(struct scsi_host_template *tpnt) esp->dma_setup = &dma_setup; /* Optional functions */ - esp->dma_barrier = 0; - esp->dma_drain = 0; - esp->dma_invalidate = 0; - esp->dma_irq_entry = 0; - esp->dma_irq_exit = 0; - esp->dma_poll = 0; - esp->dma_reset = 0; + esp->dma_barrier = NULL; + esp->dma_drain = NULL; + esp->dma_invalidate = NULL; + esp->dma_irq_entry = NULL; + esp->dma_irq_exit = NULL; + esp->dma_poll = NULL; + esp->dma_reset = NULL; esp->dma_led_off = &dma_led_off; esp->dma_led_on = &dma_led_on; @@ -140,7 +140,7 @@ static int jazz_esp_detect(struct scsi_host_template *tpnt) * of DMA channel, so we can use the jazz DMA functions * */ - esp->dregs = JAZZ_SCSI_DMA; + esp->dregs = (void *) JAZZ_SCSI_DMA; /* ESP register base */ esp->eregs = (struct ESP_regs *)(JAZZ_SCSI_BASE); -- cgit v1.2.3-59-g8ed1b From e3094447e013a59ccedcf60f6055f18225bd8465 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 16 Feb 2006 13:25:36 +0100 Subject: [SCSI] mptsas: add support for enclosure and bay identifier attributes Adds support to retrieve the enclosure and bay identifiers. This patch is from Eric with minor modifications from me, rewritten from a buggy patch of mine, based on the earlier CSMI implementation from Eric.. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 196 +++++++++++++++++++++++++++++++++------- 1 file changed, 161 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 2512d0e6155e..74f4368c79ab 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -117,6 +117,8 @@ struct mptsas_hotplug_event { struct mptsas_devinfo { u16 handle; /* unique id to address this device */ u16 handle_parent; /* unique id to address parent device */ + u16 handle_enclosure; /* enclosure identifier of the enclosure */ + u16 slot; /* physical slot in enclosure */ u8 phy_id; /* phy number of parent device */ u8 port_id; /* sas physical port this device is assoc'd with */ @@ -146,6 +148,18 @@ struct mptsas_portinfo { struct mptsas_phyinfo *phy_info; }; +struct mptsas_enclosure { + u64 enclosure_logical_id; /* The WWN for the enclosure */ + u16 enclosure_handle; /* unique id to address this */ + u16 flags; /* details enclosure management */ + u16 num_slot; /* num slots */ + u16 start_slot; /* first slot */ + u8 start_id; /* starting logical target id */ + u8 start_channel; /* starting logical channel id */ + u8 sep_id; /* SEP device logical target id */ + u8 sep_channel; /* SEP channel logical channel id */ +}; + #ifdef SASDEBUG static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) @@ -205,6 +219,7 @@ static void mptsas_print_device_pg0(SasDevicePage0_t *pg0) printk("---- SAS DEVICE PAGE 0 ---------\n"); printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle)); + printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle)); printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle)); printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot)); printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address)); @@ -243,6 +258,82 @@ static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1) #define mptsas_print_expander_pg1(pg1) do { } while (0) #endif +static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) +{ + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; +} + +static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy) +{ + struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); + return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; +} + +static int +mptsas_sas_exclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, + u32 form, u32 form_specific) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasEnclosurePage0_t *buffer; + dma_addr_t dma_handle; + int error; + __le64 le_identifier; + + memset(&hdr, 0, sizeof(hdr)); + hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION; + hdr.PageNumber = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE; + + cfg.cfghdr.ehdr = &hdr; + cfg.physAddr = -1; + cfg.pageAddr = form + form_specific; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + /* save config data */ + memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64)); + enclosure->enclosure_logical_id = le64_to_cpu(le_identifier); + enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle); + enclosure->flags = le16_to_cpu(buffer->Flags); + enclosure->num_slot = le16_to_cpu(buffer->NumSlots); + enclosure->start_slot = le16_to_cpu(buffer->StartSlot); + enclosure->start_id = buffer->StartTargetID; + enclosure->start_channel = buffer->StartBus; + enclosure->sep_id = buffer->SEPTargetID; + enclosure->sep_channel = buffer->SEPBus; + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} /* * This is pretty ugly. We will be able to seriously clean it up @@ -399,12 +490,6 @@ static struct scsi_host_template mptsas_driver_template = { .use_clustering = ENABLE_CLUSTERING, }; -static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) -{ - struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); - return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; -} - static int mptsas_get_linkerrors(struct sas_phy *phy) { MPT_ADAPTER *ioc = phy_to_ioc(phy); @@ -546,8 +631,67 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) return error; } +static int +mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) +{ + MPT_ADAPTER *ioc = rphy_to_ioc(rphy); + int i, error; + struct mptsas_portinfo *p; + struct mptsas_enclosure enclosure_info; + u64 enclosure_handle; + + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry(p, &ioc->sas_topology, list) { + for (i = 0; i < p->num_phys; i++) { + if (p->phy_info[i].attached.sas_address == + rphy->identify.sas_address) { + enclosure_handle = p->phy_info[i]. + attached.handle_enclosure; + goto found_info; + } + } + } + mutex_unlock(&ioc->sas_topology_mutex); + return -ENXIO; + + found_info: + mutex_unlock(&ioc->sas_topology_mutex); + memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure)); + error = mptsas_sas_exclosure_pg0(ioc, &enclosure_info, + (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << + MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle); + if (!error) + *identifier = enclosure_info.enclosure_logical_id; + return error; +} + +static int +mptsas_get_bay_identifier(struct sas_rphy *rphy) +{ + MPT_ADAPTER *ioc = rphy_to_ioc(rphy); + struct mptsas_portinfo *p; + int i, rc; + + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry(p, &ioc->sas_topology, list) { + for (i = 0; i < p->num_phys; i++) { + if (p->phy_info[i].attached.sas_address == + rphy->identify.sas_address) { + rc = p->phy_info[i].attached.slot; + goto out; + } + } + } + rc = -ENXIO; + out: + mutex_unlock(&ioc->sas_topology_mutex); + return rc; +} + static struct sas_function_template mptsas_transport_functions = { .get_linkerrors = mptsas_get_linkerrors, + .get_enclosure_identifier = mptsas_get_enclosure_identifier, + .get_bay_identifier = mptsas_get_bay_identifier, .phy_reset = mptsas_phy_reset, }; @@ -739,6 +883,9 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, device_info->handle = le16_to_cpu(buffer->DevHandle); device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle); + device_info->handle_enclosure = + le16_to_cpu(buffer->EnclosureHandle); + device_info->slot = le16_to_cpu(buffer->Slot); device_info->phy_id = buffer->PhyNum; device_info->port_id = buffer->PhysicalPort; device_info->id = buffer->TargetID; @@ -1335,29 +1482,15 @@ mptsas_hotplug_work(void *arg) case MPTSAS_ADD_DEVICE: /* - * When there is no sas address, - * RAID volumes are being deleted, - * and hidden phy disk are being added. - * We don't know the SAS data yet, - * so lookup sas device page to get - * pertaining info + * Refresh sas device pg0 data */ - if (!ev->sas_address) { - if (mptsas_sas_device_pg0(ioc, - &sas_device, ev->id, - (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << - MPI_SAS_DEVICE_PGAD_FORM_SHIFT))) - break; - ev->handle = sas_device.handle; - ev->parent_handle = sas_device.handle_parent; - ev->channel = sas_device.channel; - ev->phy_id = sas_device.phy_id; - ev->sas_address = sas_device.sas_address; - ev->device_info = sas_device.device_info; - } + if (mptsas_sas_device_pg0(ioc, &sas_device, + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) + break; phy_info = mptsas_find_phyinfo_by_parent(ioc, - ev->parent_handle, ev->phy_id); + sas_device.handle_parent, sas_device.phy_id); if (!phy_info) { printk("mptsas: add event for non-existant PHY.\n"); break; @@ -1368,14 +1501,8 @@ mptsas_hotplug_work(void *arg) break; } - /* fill attached info */ - phy_info->attached.handle = ev->handle; - phy_info->attached.phy_id = ev->phy_id; - phy_info->attached.port_id = phy_info->identify.port_id; - phy_info->attached.id = ev->id; - phy_info->attached.channel = ev->channel; - phy_info->attached.sas_address = ev->sas_address; - phy_info->attached.device_info = ev->device_info; + memcpy(&phy_info->attached, &sas_device, + sizeof(struct mptsas_devinfo)); if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) ds = "ssp"; @@ -1393,7 +1520,6 @@ mptsas_hotplug_work(void *arg) if (!rphy) break; /* non-fatal: an rphy can be added later */ - rphy->scsi_target_id = phy_info->attached.id; mptsas_parse_device_info(&rphy->identify, &phy_info->attached); if (sas_rphy_add(rphy)) { sas_rphy_free(rphy); -- cgit v1.2.3-59-g8ed1b From a012564136a665f8d63443c057ba368572b483df Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 16 Feb 2006 13:31:47 +0100 Subject: [SCSI] sas: add support for enclosure and bad ID rphy attributes Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 53 +++++++++++++++++++++++++++++++++++++-- include/scsi/scsi_transport_sas.h | 2 ++ 2 files changed, 53 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 205542988e29..eab5c7c6f3c7 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Dell Inc. + * Copyright (C) 2005-2006 Dell Inc. * Released under GPL v2. * * Serial Attached SCSI (SAS) transport class. @@ -38,7 +38,7 @@ #define SAS_HOST_ATTRS 0 #define SAS_PORT_ATTRS 17 -#define SAS_RPORT_ATTRS 5 +#define SAS_RPORT_ATTRS 7 struct sas_internal { struct scsi_transport_template t; @@ -533,6 +533,53 @@ show_sas_rphy_device_type(struct class_device *cdev, char *buf) static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO, show_sas_rphy_device_type, NULL); +static ssize_t +show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf) +{ + struct sas_rphy *rphy = transport_class_to_rphy(cdev); + struct sas_phy *phy = dev_to_phy(rphy->dev.parent); + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + struct sas_internal *i = to_sas_internal(shost->transportt); + u64 identifier; + int error; + + /* + * Only devices behind an expander are supported, because the + * enclosure identifier is a SMP feature. + */ + if (phy->local_attached) + return -EINVAL; + + error = i->f->get_enclosure_identifier(rphy, &identifier); + if (error) + return error; + return sprintf(buf, "0x%llx\n", (unsigned long long)identifier); +} + +static SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, + show_sas_rphy_enclosure_identifier, NULL); + +static ssize_t +show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf) +{ + struct sas_rphy *rphy = transport_class_to_rphy(cdev); + struct sas_phy *phy = dev_to_phy(rphy->dev.parent); + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + struct sas_internal *i = to_sas_internal(shost->transportt); + int val; + + if (phy->local_attached) + return -EINVAL; + + val = i->f->get_bay_identifier(rphy); + if (val < 0) + return val; + return sprintf(buf, "%d\n", val); +} + +static SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, + show_sas_rphy_bay_identifier, NULL); + sas_rphy_protocol_attr(identify.initiator_port_protocols, initiator_port_protocols); sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); @@ -845,6 +892,8 @@ sas_attach_transport(struct sas_function_template *ft) SETUP_RPORT_ATTRIBUTE(rphy_device_type); SETUP_RPORT_ATTRIBUTE(rphy_sas_address); SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); + SETUP_RPORT_ATTRIBUTE(rphy_enclosure_identifier); + SETUP_RPORT_ATTRIBUTE(rphy_bay_identifier); i->rphy_attrs[count] = NULL; return &i->t; diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index b91400bfb02a..ccef5d2cf478 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -94,6 +94,8 @@ struct sas_rphy { /* The functions by which the transport class and the driver communicate */ struct sas_function_template { int (*get_linkerrors)(struct sas_phy *); + int (*get_enclosure_identifier)(struct sas_rphy *, u64 *); + int (*get_bay_identifier)(struct sas_rphy *); int (*phy_reset)(struct sas_phy *, int); }; -- cgit v1.2.3-59-g8ed1b From 38e14f895b212943995379dea824cc52b0c25991 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 17 Feb 2006 14:58:47 -0800 Subject: [SCSI] Add EXPORT_SYMBOL for spi msg functions Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 653f165d65ff..c63adff15afa 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -1059,6 +1059,7 @@ int spi_populate_width_msg(unsigned char *msg, int width) msg[3] = width; return 4; } +EXPORT_SYMBOL_GPL(spi_populate_width_msg); int spi_populate_sync_msg(unsigned char *msg, int period, int offset) { @@ -1069,6 +1070,7 @@ int spi_populate_sync_msg(unsigned char *msg, int period, int offset) msg[4] = offset; return 5; } +EXPORT_SYMBOL_GPL(spi_populate_sync_msg); int spi_populate_ppr_msg(unsigned char *msg, int period, int offset, int width, int options) @@ -1083,6 +1085,7 @@ int spi_populate_ppr_msg(unsigned char *msg, int period, int offset, msg[7] = options; return 8; } +EXPORT_SYMBOL_GPL(spi_populate_ppr_msg); #ifdef CONFIG_SCSI_CONSTANTS static const char * const one_byte_msgs[] = { -- cgit v1.2.3-59-g8ed1b From fe27381d16c6683c55e618360d0d11bd43647e43 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 14 Feb 2006 18:45:06 +0100 Subject: [SCSI] aacraid: use kthread_ API Use the kthread_ API instead of opencoding lots of hairy code for kernel thread creation and teardown. Signed-off-by: Christoph Hellwig Acked-by: Salyzyn, Mark Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aacraid.h | 5 ++--- drivers/scsi/aacraid/comminit.c | 1 - drivers/scsi/aacraid/commsup.c | 14 +++++--------- drivers/scsi/aacraid/linit.c | 14 ++++++-------- 4 files changed, 13 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 2d430b7e8cf4..9ce7002bd070 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -997,7 +997,7 @@ struct aac_dev int maximum_num_physicals; int maximum_num_channels; struct fsa_dev_info *fsa_dev; - pid_t thread_pid; + struct task_struct *thread; int cardtype; /* @@ -1017,7 +1017,6 @@ struct aac_dev * AIF thread states */ u32 aif_thread; - struct completion aif_completion; struct aac_adapter_info adapter_info; struct aac_supplement_adapter_info supplement_adapter_info; /* These are in adapter info but they are in the io flow so @@ -1797,7 +1796,7 @@ int aac_sa_init(struct aac_dev *dev); unsigned int aac_response_normal(struct aac_queue * q); unsigned int aac_command_normal(struct aac_queue * q); unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); -int aac_command_thread(struct aac_dev * dev); +int aac_command_thread(void *data); int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size); struct aac_driver_ident* aac_get_driver_ident(int devtype); diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 1628d094943d..19397453bae7 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -433,7 +433,6 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) } INIT_LIST_HEAD(&dev->fib_list); - init_completion(&dev->aif_completion); return dev; } diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 609fd19b1844..c7f80ec7abde 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -1045,8 +1046,9 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) * more FIBs. */ -int aac_command_thread(struct aac_dev * dev) +int aac_command_thread(void *data) { + struct aac_dev *dev = data; struct hw_fib *hw_fib, *hw_newfib; struct fib *fib, *newfib; struct aac_fib_context *fibctx; @@ -1058,12 +1060,7 @@ int aac_command_thread(struct aac_dev * dev) */ if (dev->aif_thread) return -EINVAL; - /* - * Set up the name that will appear in 'ps' - * stored in task_struct.comm[16]. - */ - daemonize("aacraid"); - allow_signal(SIGKILL); + /* * Let the DPC know it has a place to send the AIF's to. */ @@ -1266,13 +1263,12 @@ int aac_command_thread(struct aac_dev * dev) spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); schedule(); - if(signal_pending(current)) + if (kthread_should_stop()) break; set_current_state(TASK_INTERRUPTIBLE); } if (dev->queues) remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait); dev->aif_thread = 0; - complete_and_exit(&dev->aif_completion, 0); return 0; } diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 271617890562..c2596335549d 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -850,10 +851,10 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, /* * Start any kernel threads needed */ - aac->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, - aac, 0); - if (aac->thread_pid < 0) { + aac->thread = kthread_run(aac_command_thread, aac, AAC_DRIVERNAME); + if (IS_ERR(aac->thread)) { printk(KERN_ERR "aacraid: Unable to create command thread.\n"); + error = PTR_ERR(aac->thread); goto out_deinit; } @@ -934,9 +935,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, return 0; out_deinit: - kill_proc(aac->thread_pid, SIGKILL, 0); - wait_for_completion(&aac->aif_completion); - + kthread_stop(aac->thread); aac_send_shutdown(aac); aac_adapter_disable_int(aac); free_irq(pdev->irq, aac); @@ -970,8 +969,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev) scsi_remove_host(shost); - kill_proc(aac->thread_pid, SIGKILL, 0); - wait_for_completion(&aac->aif_completion); + kthread_stop(aac->thread); aac_send_shutdown(aac); aac_adapter_disable_int(aac); -- cgit v1.2.3-59-g8ed1b From 8cac814501677e9f6a824cf4d423122ac8d67fcb Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 6 Feb 2006 15:40:45 +0100 Subject: [SCSI] aic7xxx: semaphore to completion conversion On Tue, Jan 31, 2006 at 06:20:18PM +0100, Christoph Hellwig wrote: > switch eh_sem to a completion. due to wait_for_completion_timeout this > also nicely simplifies the code. Unfortunately it's untested, so if > someone with the hardware could give it a try that would be nice. Once > it works the same thing can be applied to aic79xx. New version that switches to the common onstack completion and just a pointer in the platform_data struct idiom. This gets rid of all the flags fiddling. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 45 ++++++++++---------------------------- drivers/scsi/aic7xxx/aic7xxx_osm.h | 5 +---- 2 files changed, 12 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 051970efba68..2c801672d8bb 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -373,7 +373,6 @@ static void ahc_linux_handle_scsi_status(struct ahc_softc *, struct scb *); static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd); -static void ahc_linux_sem_timeout(u_long arg); static void ahc_linux_freeze_simq(struct ahc_softc *ahc); static void ahc_linux_release_simq(struct ahc_softc *ahc); static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); @@ -1193,7 +1192,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); ahc->platform_data->irq = AHC_LINUX_NOIRQ; ahc_lockinit(ahc); - init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); ahc->seltime = (aic7xxx_seltime & 0x3) << 4; ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; if (aic7xxx_pci_parity == 0) @@ -1830,10 +1828,9 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) if (ahc_get_transaction_status(scb) == CAM_BDR_SENT || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); - if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) { - ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE; - up(&ahc->platform_data->eh_sem); - } + + if (ahc->platform_data->eh_done) + complete(ahc->platform_data->eh_done); } ahc_free_scb(ahc, scb); @@ -2039,22 +2036,6 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) cmd->scsi_done(cmd); } -static void -ahc_linux_sem_timeout(u_long arg) -{ - struct ahc_softc *ahc; - u_long s; - - ahc = (struct ahc_softc *)arg; - - ahc_lock(ahc, &s); - if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) { - ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE; - up(&ahc->platform_data->eh_sem); - } - ahc_unlock(ahc, &s); -} - static void ahc_linux_freeze_simq(struct ahc_softc *ahc) { @@ -2355,25 +2336,21 @@ done: if (paused) ahc_unpause(ahc); if (wait) { - struct timer_list timer; - int ret; + DECLARE_COMPLETION(done); - ahc->platform_data->flags |= AHC_UP_EH_SEMAPHORE; + ahc->platform_data->eh_done = &done; ahc_unlock(ahc, &flags); - init_timer(&timer); - timer.data = (u_long)ahc; - timer.expires = jiffies + (5 * HZ); - timer.function = ahc_linux_sem_timeout; - add_timer(&timer); printf("Recovery code sleeping\n"); - down(&ahc->platform_data->eh_sem); - printf("Recovery code awake\n"); - ret = del_timer_sync(&timer); - if (ret == 0) { + if (!wait_for_completion_timeout(&done, 5 * HZ)) { + ahc_lock(ahc, &flags); + ahc->platform_data->eh_done = NULL; + ahc_unlock(ahc, &flags); + printf("Timer Expired\n"); retval = FAILED; } + printf("Recovery code awake\n"); } else ahc_unlock(ahc, &flags); return (retval); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index e0edacae895f..a20b08c9ff15 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -369,15 +369,12 @@ struct ahc_platform_data { spinlock_t spin_lock; u_int qfrozen; - struct semaphore eh_sem; + struct completion *eh_done; struct Scsi_Host *host; /* pointer to scsi host */ #define AHC_LINUX_NOIRQ ((uint32_t)~0) uint32_t irq; /* IRQ for this adapter */ uint32_t bios_address; uint32_t mem_busaddr; /* Mem Base Addr */ - -#define AHC_UP_EH_SEMAPHORE 0x1 - uint32_t flags; }; /************************** OS Utility Wrappers *******************************/ -- cgit v1.2.3-59-g8ed1b From 1bfc5d9d5eb8e1a2efacc306bc55c248ed259a8e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 9 Feb 2006 15:26:18 -0500 Subject: [SCSI] Recognize missing LUNs for non-standard devices Some non-standard SCSI targets or protocols, such as USB UFI, report "no LUN present" by setting the Peripheral Device Type to 0x1f and the Peripheral Qualifier to 0 (not 3 as the standard requires) in the INQUIRY response. This patch (as650b) adds a new target flag and code to accomodate such targets. Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 13 +++++++++++++ include/scsi/scsi_device.h | 5 ++++- 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 803c7b9690c5..94b86d5b1469 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -853,6 +853,19 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, goto out_free_result; } + /* + * Non-standard SCSI targets may set the PDT to 0x1f (unknown or + * no device type) instead of using the Peripheral Qualifier to + * indicate that no LUN is present. For example, USB UFI does this. + */ + if (starget->pdt_1f_for_no_lun && (result[0] & 0x1f) == 0x1f) { + SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO + "scsi scan: peripheral device type" + " of 31, no device added\n")); + res = SCSI_SCAN_TARGET_PRESENT; + goto out_free_result; + } + res = scsi_add_lun(sdev, result, &bflags); if (res == SCSI_SCAN_LUN_PRESENT) { if (bflags & BLIST_KEY) { diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index cde84b39bb65..8d77da932d2c 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -167,7 +167,10 @@ struct scsi_target { unsigned int channel; unsigned int id; /* target id ... replace * scsi_device.id eventually */ - unsigned long create:1; /* signal that it needs to be added */ + unsigned int create:1; /* signal that it needs to be added */ + unsigned int pdt_1f_for_no_lun; /* PDT = 0x1f */ + /* means no lun present */ + char scsi_level; void *hostdata; /* available to low-level driver */ unsigned long starget_data[0]; /* for the transport */ -- cgit v1.2.3-59-g8ed1b From fc25307d06f524d6c04b371b236dc9e62186058c Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sat, 18 Feb 2006 20:52:31 -0700 Subject: [SCSI] Improve message printing code Fix a bug where we would consume one byte too many in the message printing code. Add support for 256-byte long messages. Add support for the Modify Bidirectional Data Pointer message. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index c63adff15afa..0b29ee9989a4 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -1105,7 +1105,7 @@ static const char * const two_byte_msgs[] = { static const char * const extended_msgs[] = { /* 0x00 */ "Modify Data Pointer", "Synchronous Data Transfer Request", /* 0x02 */ "SCSI-I Extended Identify", "Wide Data Transfer Request", -/* 0x04 */ "Parallel Protocol Request" +/* 0x04 */ "Parallel Protocol Request", "Modify Bidirectional Data Pointer" }; static void print_nego(const unsigned char *msg, int per, int off, int width) @@ -1122,11 +1122,20 @@ static void print_nego(const unsigned char *msg, int per, int off, int width) printk("width = %d ", 8 << msg[width]); } +static void print_ptr(const unsigned char *msg, int msb, const char *desc) +{ + int ptr = (msg[msb] << 24) | (msg[msb+1] << 16) | (msg[msb+2] << 8) | + msg[msb+3]; + printk("%s = %d ", desc, ptr); +} + int spi_print_msg(const unsigned char *msg) { int len = 0, i; if (msg[0] == EXTENDED_MESSAGE) { - len = 3 + msg[1]; + len = 2 + msg[1]; + if (len == 2) + len += 256; if (msg[2] < ARRAY_SIZE(extended_msgs)) printk ("%s ", extended_msgs[msg[2]]); else @@ -1134,8 +1143,7 @@ int spi_print_msg(const unsigned char *msg) (int) msg[2]); switch (msg[2]) { case EXTENDED_MODIFY_DATA_POINTER: - printk("pointer = %d ", (msg[3] << 24) | - (msg[4] << 16) | (msg[5] << 8) | msg[6]); + print_ptr(msg, 3, "pointer"); break; case EXTENDED_SDTR: print_nego(msg, 3, 4, 0); @@ -1146,6 +1154,10 @@ int spi_print_msg(const unsigned char *msg) case EXTENDED_PPR: print_nego(msg, 3, 5, 6); break; + case EXTENDED_MODIFY_BIDI_DATA_PTR: + print_ptr(msg, 3, "out"); + print_ptr(msg, 7, "in"); + break; default: for (i = 2; i < len; ++i) printk("%02x ", msg[i]); @@ -1186,7 +1198,9 @@ int spi_print_msg(const unsigned char *msg) int len = 0, i; if (msg[0] == EXTENDED_MESSAGE) { - len = 3 + msg[1]; + len = 2 + msg[1]; + if (len == 2) + len += 256; for (i = 0; i < len; ++i) printk("%02x ", msg[i]); /* Identify */ -- cgit v1.2.3-59-g8ed1b From 6d73c8514da241c6b1b8d710a6294786604d7142 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 23 Feb 2006 02:03:16 +0100 Subject: [SCSI] scsi_lib: fix recognition of cache type of Initio SBP-2 bridges Regardless what mode page was asked for, Initio INIC-14x0 and INIC-2430 always return page 6 without mode page headers. Try to recognise this as a special case in scsi_mode_sense and setting the mode sense headers accordingly. Signed-off-by: Al Viro Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 13 +++++++++++-- drivers/scsi/sd.c | 6 ++++++ 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 1fe4fd83e305..eab303d148d8 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1892,8 +1892,16 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, } if(scsi_status_is_good(result)) { - data->header_length = header_length; - if(use_10_for_ms) { + if (unlikely(buffer[0] == 0x86 && buffer[1] == 0x0b && + (modepage == 6 || modepage == 8))) { + /* Initio breakage? */ + header_length = 0; + data->length = 13; + data->medium_type = 0; + data->device_specific = 0; + data->longlba = 0; + data->block_descriptor_length = 0; + } else if(use_10_for_ms) { data->length = buffer[0]*256 + buffer[1] + 2; data->medium_type = buffer[2]; data->device_specific = buffer[3]; @@ -1906,6 +1914,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, data->device_specific = buffer[2]; data->block_descriptor_length = buffer[3]; } + data->header_length = header_length; } return result; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 76b4d14c0b3f..31c9685ebc5a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1333,6 +1333,12 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, if (!scsi_status_is_good(res)) goto bad_sense; + if (!data.header_length) { + modepage = 6; + printk(KERN_ERR "%s: missing header in MODE_SENSE response\n", + diskname); + } + /* that went OK, now ask for the proper length */ len = data.length; -- cgit v1.2.3-59-g8ed1b From ba3af0aff042caa1f41b5f7164cab37c717b8811 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 22 Feb 2006 02:11:59 -0600 Subject: [SCSI] don't call ips_eh_reset in ips_queue to avoid deadlock When the locking was changed in the eh code ips_eh_reset was changed so that it was a wraper around __ips_eh_reset and all ips_eh_reset does is grab the host lock and then calls __ips_eh_reset. In the queuecommand, ips_queue is called with the host_lock held so if it calls ips_eh_reset we will have a problem. This patch just has ips_queue call __ips_eh_reset. Patch is only compile tested. I do not have the HW. Signed-off-by: Mike Christie Acked-by: Hammer, Jack Signed-off-by: James Bottomley --- drivers/scsi/ips.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 86c546164da9..481708d527ae 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -1146,7 +1146,7 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *)) return (0); } ha->ioctl_reset = 1; /* This reset request is from an IOCTL */ - ips_eh_reset(SC); + __ips_eh_reset(SC); SC->result = DID_OK << 16; SC->scsi_done(SC); return (0); -- cgit v1.2.3-59-g8ed1b From ffedb4522571ac170f941678d138a31bc0884ab4 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 23 Feb 2006 14:27:18 -0600 Subject: [SCSI] fix scsi process problems and clean up the target reap issues In order to use the new execute_in_process_context() API, you have to provide it with the work storage, which I do in SCSI in scsi_device and scsi_target, but which also means that we can no longer queue up the target reaps, so instead I moved the target to a state model which allows target_alloc to detect if we've received a dying target and wait for it to be gone. Hopefully, this should also solve the target namespace race. Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 58 ---------------------------------------------- drivers/scsi/scsi_scan.c | 49 ++++++++++++++++++++++++++------------- drivers/scsi/scsi_sysfs.c | 4 +++- include/scsi/scsi.h | 2 -- include/scsi/scsi_device.h | 10 ++++++++ 5 files changed, 46 insertions(+), 77 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index eab303d148d8..3042520c413c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2257,61 +2257,3 @@ scsi_target_unblock(struct device *dev) device_for_each_child(dev, NULL, target_unblock); } EXPORT_SYMBOL_GPL(scsi_target_unblock); - - -struct work_queue_work { - struct work_struct work; - void (*fn)(void *); - void *data; -}; - -static void execute_in_process_context_work(void *data) -{ - void (*fn)(void *data); - struct work_queue_work *wqw = data; - - fn = wqw->fn; - data = wqw->data; - - kfree(wqw); - - fn(data); -} - -/** - * scsi_execute_in_process_context - reliably execute the routine with user context - * @fn: the function to execute - * @data: data to pass to the function - * - * Executes the function immediately if process context is available, - * otherwise schedules the function for delayed execution. - * - * Returns: 0 - function was executed - * 1 - function was scheduled for execution - * <0 - error - */ -int scsi_execute_in_process_context(void (*fn)(void *data), void *data) -{ - struct work_queue_work *wqw; - - if (!in_interrupt()) { - fn(data); - return 0; - } - - wqw = kmalloc(sizeof(struct work_queue_work), GFP_ATOMIC); - - if (unlikely(!wqw)) { - printk(KERN_ERR "Failed to allocate memory\n"); - WARN_ON(1); - return -ENOMEM; - } - - INIT_WORK(&wqw->work, execute_in_process_context_work, wqw); - wqw->fn = fn; - wqw->data = data; - schedule_work(&wqw->work); - - return 1; -} -EXPORT_SYMBOL_GPL(scsi_execute_in_process_context); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 94b86d5b1469..84f01fd0c8fd 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -349,6 +349,8 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, starget->channel = channel; INIT_LIST_HEAD(&starget->siblings); INIT_LIST_HEAD(&starget->devices); + starget->state = STARGET_RUNNING; + retry: spin_lock_irqsave(shost->host_lock, flags); found_target = __scsi_find_target(parent, channel, id); @@ -381,8 +383,15 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, found_target->reap_ref++; spin_unlock_irqrestore(shost->host_lock, flags); put_device(parent); - kfree(starget); - return found_target; + if (found_target->state != STARGET_DEL) { + kfree(starget); + return found_target; + } + /* Unfortunately, we found a dying target; need to + * wait until it's dead before we can get a new one */ + put_device(&found_target->dev); + flush_scheduled_work(); + goto retry; } static void scsi_target_reap_usercontext(void *data) @@ -391,21 +400,13 @@ static void scsi_target_reap_usercontext(void *data) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); unsigned long flags; + transport_remove_device(&starget->dev); + device_del(&starget->dev); + transport_destroy_device(&starget->dev); spin_lock_irqsave(shost->host_lock, flags); - - if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { - list_del_init(&starget->siblings); - spin_unlock_irqrestore(shost->host_lock, flags); - transport_remove_device(&starget->dev); - device_del(&starget->dev); - transport_destroy_device(&starget->dev); - put_device(&starget->dev); - return; - - } + list_del_init(&starget->siblings); spin_unlock_irqrestore(shost->host_lock, flags); - - return; + put_device(&starget->dev); } /** @@ -419,7 +420,23 @@ static void scsi_target_reap_usercontext(void *data) */ void scsi_target_reap(struct scsi_target *starget) { - scsi_execute_in_process_context(scsi_target_reap_usercontext, starget); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + + if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { + BUG_ON(starget->state == STARGET_DEL); + starget->state = STARGET_DEL; + spin_unlock_irqrestore(shost->host_lock, flags); + execute_in_process_context(scsi_target_reap_usercontext, + starget, &starget->ew); + return; + + } + spin_unlock_irqrestore(shost->host_lock, flags); + + return; } /** diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 902a5def8e62..89055494dfee 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -256,7 +256,9 @@ static void scsi_device_dev_release_usercontext(void *data) static void scsi_device_dev_release(struct device *dev) { - scsi_execute_in_process_context(scsi_device_dev_release_usercontext, dev); + struct scsi_device *sdp = to_scsi_device(dev); + execute_in_process_context(scsi_device_dev_release_usercontext, dev, + &sdp->ew); } static struct class sdev_class = { diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 9c331258bc27..c60b8ff2f5e4 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -433,6 +433,4 @@ struct scsi_lun { /* Used to obtain the PCI location of a device */ #define SCSI_IOCTL_GET_PCI 0x5387 -int scsi_execute_in_process_context(void (*fn)(void *data), void *data); - #endif /* _SCSI_SCSI_H */ diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 8d77da932d2c..1ec17ee12815 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -4,6 +4,7 @@ #include #include #include +#include #include struct request_queue; @@ -137,6 +138,8 @@ struct scsi_device { struct device sdev_gendev; struct class_device sdev_classdev; + struct execute_work ew; /* used to get process context on put */ + enum scsi_device_state sdev_state; unsigned long sdev_data[0]; } __attribute__((aligned(sizeof(unsigned long)))); @@ -153,6 +156,11 @@ struct scsi_device { #define scmd_printk(prefix, scmd, fmt, a...) \ dev_printk(prefix, &(scmd)->device->sdev_gendev, fmt, ##a) +enum scsi_target_state { + STARGET_RUNNING = 1, + STARGET_DEL, +}; + /* * scsi_target: representation of a scsi target, for now, this is only * used for single_lun devices. If no one has active IO to the target, @@ -172,6 +180,8 @@ struct scsi_target { /* means no lun present */ char scsi_level; + struct execute_work ew; + enum scsi_target_state state; void *hostdata; /* available to low-level driver */ unsigned long starget_data[0]; /* for the transport */ /* starget_data must be the last element!!!! */ -- cgit v1.2.3-59-g8ed1b From 32f95792500794a0a7cce266b7dafb2bee323bf8 Mon Sep 17 00:00:00 2001 From: Brian King Date: Wed, 22 Feb 2006 14:28:24 -0600 Subject: [SCSI] scsi: Handle device_add failure in scsi_alloc_target Fixes scsi to handle device_add failure in scsi_alloc_target. Without this patch, if this call were to fail, we can oops when we free the target. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 84f01fd0c8fd..be14f9d82fde 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -332,6 +332,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, + shost->transportt->target_size; struct scsi_target *starget; struct scsi_target *found_target; + int error; starget = kzalloc(size, GFP_KERNEL); if (!starget) { @@ -361,10 +362,20 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, spin_unlock_irqrestore(shost->host_lock, flags); /* allocate and add */ transport_setup_device(dev); - device_add(dev); + error = device_add(dev); + if (error) { + dev_err(dev, "target device_add failed, error %d\n", error); + spin_lock_irqsave(shost->host_lock, flags); + list_del_init(&starget->siblings); + spin_unlock_irqrestore(shost->host_lock, flags); + transport_destroy_device(dev); + put_device(parent); + kfree(starget); + return NULL; + } transport_add_device(dev); if (shost->hostt->target_alloc) { - int error = shost->hostt->target_alloc(starget); + error = shost->hostt->target_alloc(starget); if(error) { dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error); -- cgit v1.2.3-59-g8ed1b From 32ee8c3e470d86588b51dc42ed01e85c5fa0f180 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 28 Feb 2006 00:43:23 -0500 Subject: [CPUFREQ] Lots of whitespace & CodingStyle cleanup. Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/Kconfig | 1 - arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c | 64 ++++----- arch/i386/kernel/cpu/cpufreq/elanfreq.c | 109 ++++++++------- arch/i386/kernel/cpu/cpufreq/gx-suspmod.c | 180 ++++++++++++------------- arch/i386/kernel/cpu/cpufreq/longhaul.h | 4 +- arch/i386/kernel/cpu/cpufreq/p4-clockmod.c | 24 ++-- arch/i386/kernel/cpu/cpufreq/powernow-k6.c | 16 +-- arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 10 +- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 15 +-- arch/i386/kernel/cpu/cpufreq/powernow-k8.h | 6 +- arch/i386/kernel/cpu/cpufreq/speedstep-lib.c | 42 +++--- arch/i386/kernel/cpu/cpufreq/speedstep-lib.h | 20 +-- arch/i386/kernel/cpu/cpufreq/speedstep-smi.c | 49 ++++--- drivers/cpufreq/cpufreq.c | 54 ++++---- drivers/cpufreq/cpufreq_ondemand.c | 86 ++++++------ drivers/cpufreq/cpufreq_performance.c | 2 +- drivers/cpufreq/cpufreq_powersave.c | 2 +- drivers/cpufreq/cpufreq_stats.c | 6 +- drivers/cpufreq/cpufreq_userspace.c | 12 +- drivers/cpufreq/freq_table.c | 12 +- 20 files changed, 343 insertions(+), 371 deletions(-) (limited to 'drivers') diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig index 26892d2099b0..0f1eb507233b 100644 --- a/arch/i386/kernel/cpu/cpufreq/Kconfig +++ b/arch/i386/kernel/cpu/cpufreq/Kconfig @@ -96,7 +96,6 @@ config X86_POWERNOW_K8_ACPI config X86_GX_SUSPMOD tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation" - depends on PCI help This add the CPUFreq driver for NatSemi Geode processors which support suspend modulation. diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c index 2b62dee35c6c..f275e0d4aee5 100644 --- a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c +++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c @@ -39,7 +39,7 @@ static struct pci_dev *nforce2_chipset_dev; static int fid = 0; /* min_fsb, max_fsb: - * minimum and maximum FSB (= FSB at boot time) + * minimum and maximum FSB (= FSB at boot time) */ static int min_fsb = 0; static int max_fsb = 0; @@ -57,10 +57,10 @@ MODULE_PARM_DESC(min_fsb, #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "cpufreq-nforce2", msg) -/* +/** * nforce2_calc_fsb - calculate FSB * @pll: PLL value - * + * * Calculates FSB from PLL value */ static int nforce2_calc_fsb(int pll) @@ -76,10 +76,10 @@ static int nforce2_calc_fsb(int pll) return 0; } -/* +/** * nforce2_calc_pll - calculate PLL value * @fsb: FSB - * + * * Calculate PLL value for given FSB */ static int nforce2_calc_pll(unsigned int fsb) @@ -106,10 +106,10 @@ static int nforce2_calc_pll(unsigned int fsb) return NFORCE2_PLL(mul, div); } -/* +/** * nforce2_write_pll - write PLL value to chipset * @pll: PLL value - * + * * Writes new FSB PLL value to chipset */ static void nforce2_write_pll(int pll) @@ -121,15 +121,13 @@ static void nforce2_write_pll(int pll) pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLADR, temp); /* Now write the value in all 64 registers */ - for (temp = 0; temp <= 0x3f; temp++) { - pci_write_config_dword(nforce2_chipset_dev, - NFORCE2_PLLREG, pll); - } + for (temp = 0; temp <= 0x3f; temp++) + pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLREG, pll); return; } -/* +/** * nforce2_fsb_read - Read FSB * * Read FSB from chipset @@ -140,39 +138,32 @@ static unsigned int nforce2_fsb_read(int bootfsb) struct pci_dev *nforce2_sub5; u32 fsb, temp = 0; - /* Get chipset boot FSB from subdevice 5 (FSB at boot-time) */ nforce2_sub5 = pci_get_subsys(PCI_VENDOR_ID_NVIDIA, - 0x01EF, - PCI_ANY_ID, - PCI_ANY_ID, - NULL); - + 0x01EF,PCI_ANY_ID,PCI_ANY_ID,NULL); if (!nforce2_sub5) return 0; pci_read_config_dword(nforce2_sub5, NFORCE2_BOOTFSB, &fsb); fsb /= 1000000; - + /* Check if PLL register is already set */ - pci_read_config_byte(nforce2_chipset_dev, - NFORCE2_PLLENABLE, (u8 *)&temp); - + pci_read_config_byte(nforce2_chipset_dev,NFORCE2_PLLENABLE, (u8 *)&temp); + if(bootfsb || !temp) return fsb; /* Use PLL register FSB value */ - pci_read_config_dword(nforce2_chipset_dev, - NFORCE2_PLLREG, &temp); + pci_read_config_dword(nforce2_chipset_dev,NFORCE2_PLLREG, &temp); fsb = nforce2_calc_fsb(temp); return fsb; } -/* +/** * nforce2_set_fsb - set new FSB * @fsb: New FSB - * + * * Sets new FSB */ static int nforce2_set_fsb(unsigned int fsb) @@ -186,7 +177,7 @@ static int nforce2_set_fsb(unsigned int fsb) printk(KERN_ERR "cpufreq: FSB %d is out of range!\n", fsb); return -EINVAL; } - + tfsb = nforce2_fsb_read(0); if (!tfsb) { printk(KERN_ERR "cpufreq: Error while reading the FSB\n"); @@ -194,8 +185,7 @@ static int nforce2_set_fsb(unsigned int fsb) } /* First write? Then set actual value */ - pci_read_config_byte(nforce2_chipset_dev, - NFORCE2_PLLENABLE, (u8 *)&temp); + pci_read_config_byte(nforce2_chipset_dev,NFORCE2_PLLENABLE, (u8 *)&temp); if (!temp) { pll = nforce2_calc_pll(tfsb); @@ -223,7 +213,7 @@ static int nforce2_set_fsb(unsigned int fsb) /* Calculate the PLL reg. value */ if ((pll = nforce2_calc_pll(tfsb)) == -1) return -EINVAL; - + nforce2_write_pll(pll); #ifdef NFORCE2_DELAY mdelay(NFORCE2_DELAY); @@ -239,7 +229,7 @@ static int nforce2_set_fsb(unsigned int fsb) /** * nforce2_get - get the CPU frequency * @cpu: CPU number - * + * * Returns the CPU frequency */ static unsigned int nforce2_get(unsigned int cpu) @@ -354,10 +344,10 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy) printk(KERN_INFO "cpufreq: FSB currently at %i MHz, FID %d.%d\n", fsb, fid / 10, fid % 10); - + /* Set maximum FSB to FSB at boot time */ max_fsb = nforce2_fsb_read(1); - + if(!max_fsb) return -EIO; @@ -398,17 +388,15 @@ static struct cpufreq_driver nforce2_driver = { * nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic * * Detects nForce2 A2 and C1 stepping - * + * */ static unsigned int nforce2_detect_chipset(void) { u8 revision; nforce2_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA, - PCI_DEVICE_ID_NVIDIA_NFORCE2, - PCI_ANY_ID, - PCI_ANY_ID, - NULL); + PCI_DEVICE_ID_NVIDIA_NFORCE2, + PCI_ANY_ID, PCI_ANY_ID, NULL); if (nforce2_chipset_dev == NULL) return -ENODEV; diff --git a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c index 3f7caa4ae6d6..f317276afa7a 100644 --- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c +++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c @@ -1,16 +1,16 @@ /* - * elanfreq: cpufreq driver for the AMD ELAN family + * elanfreq: cpufreq driver for the AMD ELAN family * * (c) Copyright 2002 Robert Schwebel * - * Parts of this code are (c) Sven Geggus + * Parts of this code are (c) Sven Geggus * - * All Rights Reserved. + * 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; either version - * 2 of the License, or (at your option) any later version. + * 2 of the License, or (at your option) any later version. * * 2002-02-13: - initial revision for 2.4.18-pre9 by Robert Schwebel * @@ -28,7 +28,7 @@ #include #include -#define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */ +#define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */ #define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */ /* Module parameter */ @@ -41,7 +41,7 @@ struct s_elan_multiplier { }; /* - * It is important that the frequencies + * It is important that the frequencies * are listed in ascending order here! */ struct s_elan_multiplier elan_multiplier[] = { @@ -72,78 +72,79 @@ static struct cpufreq_frequency_table elanfreq_table[] = { * elanfreq_get_cpu_frequency: determine current cpu speed * * Finds out at which frequency the CPU of the Elan SOC runs - * at the moment. Frequencies from 1 to 33 MHz are generated + * at the moment. Frequencies from 1 to 33 MHz are generated * the normal way, 66 and 99 MHz are called "Hyperspeed Mode" - * and have the rest of the chip running with 33 MHz. + * and have the rest of the chip running with 33 MHz. */ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu) { - u8 clockspeed_reg; /* Clock Speed Register */ - + u8 clockspeed_reg; /* Clock Speed Register */ + local_irq_disable(); - outb_p(0x80,REG_CSCIR); - clockspeed_reg = inb_p(REG_CSCDR); + outb_p(0x80,REG_CSCIR); + clockspeed_reg = inb_p(REG_CSCDR); local_irq_enable(); - if ((clockspeed_reg & 0xE0) == 0xE0) { return 0; } + if ((clockspeed_reg & 0xE0) == 0xE0) + return 0; - /* Are we in CPU clock multiplied mode (66/99 MHz)? */ - if ((clockspeed_reg & 0xE0) == 0xC0) { - if ((clockspeed_reg & 0x01) == 0) { + /* Are we in CPU clock multiplied mode (66/99 MHz)? */ + if ((clockspeed_reg & 0xE0) == 0xC0) { + if ((clockspeed_reg & 0x01) == 0) return 66000; - } else { - return 99000; - } - } + else + return 99000; + } /* 33 MHz is not 32 MHz... */ if ((clockspeed_reg & 0xE0)==0xA0) return 33000; - return ((1<<((clockspeed_reg & 0xE0) >> 5)) * 1000); + return ((1<<((clockspeed_reg & 0xE0) >> 5)) * 1000); } /** - * elanfreq_set_cpu_frequency: Change the CPU core frequency - * @cpu: cpu number + * elanfreq_set_cpu_frequency: Change the CPU core frequency + * @cpu: cpu number * @freq: frequency in kHz * - * This function takes a frequency value and changes the CPU frequency + * This function takes a frequency value and changes the CPU frequency * according to this. Note that the frequency has to be checked by * elanfreq_validatespeed() for correctness! - * - * There is no return value. + * + * There is no return value. */ -static void elanfreq_set_cpu_state (unsigned int state) { - +static void elanfreq_set_cpu_state (unsigned int state) +{ struct cpufreq_freqs freqs; freqs.old = elanfreq_get_cpu_frequency(0); freqs.new = elan_multiplier[state].clock; freqs.cpu = 0; /* elanfreq.c is UP only driver */ - + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - printk(KERN_INFO "elanfreq: attempting to set frequency to %i kHz\n",elan_multiplier[state].clock); + printk(KERN_INFO "elanfreq: attempting to set frequency to %i kHz\n", + elan_multiplier[state].clock); - /* - * Access to the Elan's internal registers is indexed via - * 0x22: Chip Setup & Control Register Index Register (CSCI) - * 0x23: Chip Setup & Control Register Data Register (CSCD) + /* + * Access to the Elan's internal registers is indexed via + * 0x22: Chip Setup & Control Register Index Register (CSCI) + * 0x23: Chip Setup & Control Register Data Register (CSCD) * */ - /* - * 0x40 is the Power Management Unit's Force Mode Register. + /* + * 0x40 is the Power Management Unit's Force Mode Register. * Bit 6 enables Hyperspeed Mode (66/100 MHz core frequency) */ local_irq_disable(); - outb_p(0x40,REG_CSCIR); /* Disable hyperspeed mode */ + outb_p(0x40,REG_CSCIR); /* Disable hyperspeed mode */ outb_p(0x00,REG_CSCDR); local_irq_enable(); /* wait till internal pipelines and */ udelay(1000); /* buffers have cleaned up */ @@ -166,10 +167,10 @@ static void elanfreq_set_cpu_state (unsigned int state) { /** * elanfreq_validatespeed: test if frequency range is valid - * @policy: the policy to validate + * @policy: the policy to validate * - * This function checks if a given frequency range in kHz is valid - * for the hardware supported by the driver. + * This function checks if a given frequency range in kHz is valid + * for the hardware supported by the driver. */ static int elanfreq_verify (struct cpufreq_policy *policy) @@ -177,11 +178,11 @@ static int elanfreq_verify (struct cpufreq_policy *policy) return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]); } -static int elanfreq_target (struct cpufreq_policy *policy, - unsigned int target_freq, +static int elanfreq_target (struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) { - unsigned int newstate = 0; + unsigned int newstate = 0; if (cpufreq_frequency_table_target(policy, &elanfreq_table[0], target_freq, relation, &newstate)) return -EINVAL; @@ -212,7 +213,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) max_freq = elanfreq_get_cpu_frequency(0); /* table init */ - for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) { + for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) { if (elanfreq_table[i].frequency > max_freq) elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID; } @@ -226,8 +227,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) if (result) return (result); - cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu); - + cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu); return 0; } @@ -268,9 +268,9 @@ static struct freq_attr* elanfreq_attr[] = { static struct cpufreq_driver elanfreq_driver = { - .get = elanfreq_get_cpu_frequency, - .verify = elanfreq_verify, - .target = elanfreq_target, + .get = elanfreq_get_cpu_frequency, + .verify = elanfreq_verify, + .target = elanfreq_target, .init = elanfreq_cpu_init, .exit = elanfreq_cpu_exit, .name = "elanfreq", @@ -279,23 +279,21 @@ static struct cpufreq_driver elanfreq_driver = { }; -static int __init elanfreq_init(void) -{ +static int __init elanfreq_init(void) +{ struct cpuinfo_x86 *c = cpu_data; /* Test if we have the right hardware */ if ((c->x86_vendor != X86_VENDOR_AMD) || - (c->x86 != 4) || (c->x86_model!=10)) - { + (c->x86 != 4) || (c->x86_model!=10)) { printk(KERN_INFO "elanfreq: error: no Elan processor found!\n"); return -ENODEV; } - return cpufreq_register_driver(&elanfreq_driver); } -static void __exit elanfreq_exit(void) +static void __exit elanfreq_exit(void) { cpufreq_unregister_driver(&elanfreq_driver); } @@ -309,4 +307,3 @@ MODULE_DESCRIPTION("cpufreq driver for AMD's Elan CPUs"); module_init(elanfreq_init); module_exit(elanfreq_exit); - diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c index e86ea486c311..65b8fa2b0ee4 100644 --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c @@ -6,12 +6,12 @@ * * 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 * * The author(s) of this software shall not be held liable for damages * of any nature resulting due to the use of this software. This * software is provided AS-IS with no warranties. - * + * * Theoritical note: * * (see Geode(tm) CS5530 manual (rev.4.1) page.56) @@ -21,18 +21,18 @@ * * Suspend Modulation works by asserting and de-asserting the SUSP# pin * to CPU(GX1/GXLV) for configurable durations. When asserting SUSP# - * the CPU enters an idle state. GX1 stops its core clock when SUSP# is + * the CPU enters an idle state. GX1 stops its core clock when SUSP# is * asserted then power consumption is reduced. * - * Suspend Modulation's OFF/ON duration are configurable + * Suspend Modulation's OFF/ON duration are configurable * with 'Suspend Modulation OFF Count Register' * and 'Suspend Modulation ON Count Register'. - * These registers are 8bit counters that represent the number of + * These registers are 8bit counters that represent the number of * 32us intervals which the SUSP# pin is asserted(ON)/de-asserted(OFF) * to the processor. * - * These counters define a ratio which is the effective frequency - * of operation of the system. + * These counters define a ratio which is the effective frequency + * of operation of the system. * * OFF Count * F_eff = Fgx * ---------------------- @@ -40,24 +40,24 @@ * * 0 <= On Count, Off Count <= 255 * - * From these limits, we can get register values + * From these limits, we can get register values * * off_duration + on_duration <= MAX_DURATION * on_duration = off_duration * (stock_freq - freq) / freq * - * off_duration = (freq * DURATION) / stock_freq - * on_duration = DURATION - off_duration + * off_duration = (freq * DURATION) / stock_freq + * on_duration = DURATION - off_duration * * *--------------------------------------------------------------------------- * * ChangeLog: - * Dec. 12, 2003 Hiroshi Miura - * - fix on/off register mistake - * - fix cpu_khz calc when it stops cpu modulation. + * Dec. 12, 2003 Hiroshi Miura + * - fix on/off register mistake + * - fix cpu_khz calc when it stops cpu modulation. * - * Dec. 11, 2002 Hiroshi Miura - * - rewrite for Cyrix MediaGX Cx5510/5520 and + * Dec. 11, 2002 Hiroshi Miura + * - rewrite for Cyrix MediaGX Cx5510/5520 and * NatSemi Geode Cs5530(A). * * Jul. ??, 2002 Zwane Mwaikambo @@ -74,40 +74,40 @@ ************************************************************************/ #include -#include +#include #include #include #include #include -#include +#include #include /* PCI config registers, all at F0 */ -#define PCI_PMER1 0x80 /* power management enable register 1 */ -#define PCI_PMER2 0x81 /* power management enable register 2 */ -#define PCI_PMER3 0x82 /* power management enable register 3 */ -#define PCI_IRQTC 0x8c /* irq speedup timer counter register:typical 2 to 4ms */ -#define PCI_VIDTC 0x8d /* video speedup timer counter register: typical 50 to 100ms */ -#define PCI_MODOFF 0x94 /* suspend modulation OFF counter register, 1 = 32us */ -#define PCI_MODON 0x95 /* suspend modulation ON counter register */ -#define PCI_SUSCFG 0x96 /* suspend configuration register */ +#define PCI_PMER1 0x80 /* power management enable register 1 */ +#define PCI_PMER2 0x81 /* power management enable register 2 */ +#define PCI_PMER3 0x82 /* power management enable register 3 */ +#define PCI_IRQTC 0x8c /* irq speedup timer counter register:typical 2 to 4ms */ +#define PCI_VIDTC 0x8d /* video speedup timer counter register: typical 50 to 100ms */ +#define PCI_MODOFF 0x94 /* suspend modulation OFF counter register, 1 = 32us */ +#define PCI_MODON 0x95 /* suspend modulation ON counter register */ +#define PCI_SUSCFG 0x96 /* suspend configuration register */ /* PMER1 bits */ -#define GPM (1<<0) /* global power management */ -#define GIT (1<<1) /* globally enable PM device idle timers */ -#define GTR (1<<2) /* globally enable IO traps */ -#define IRQ_SPDUP (1<<3) /* disable clock throttle during interrupt handling */ -#define VID_SPDUP (1<<4) /* disable clock throttle during vga video handling */ +#define GPM (1<<0) /* global power management */ +#define GIT (1<<1) /* globally enable PM device idle timers */ +#define GTR (1<<2) /* globally enable IO traps */ +#define IRQ_SPDUP (1<<3) /* disable clock throttle during interrupt handling */ +#define VID_SPDUP (1<<4) /* disable clock throttle during vga video handling */ /* SUSCFG bits */ -#define SUSMOD (1<<0) /* enable/disable suspend modulation */ -/* the belows support only with cs5530 (after rev.1.2)/cs5530A */ -#define SMISPDUP (1<<1) /* select how SMI re-enable suspend modulation: */ - /* IRQTC timer or read SMI speedup disable reg.(F1BAR[08-09h]) */ -#define SUSCFG (1<<2) /* enable powering down a GXLV processor. "Special 3Volt Suspend" mode */ -/* the belows support only with cs5530A */ -#define PWRSVE_ISA (1<<3) /* stop ISA clock */ -#define PWRSVE (1<<4) /* active idle */ +#define SUSMOD (1<<0) /* enable/disable suspend modulation */ +/* the belows support only with cs5530 (after rev.1.2)/cs5530A */ +#define SMISPDUP (1<<1) /* select how SMI re-enable suspend modulation: */ + /* IRQTC timer or read SMI speedup disable reg.(F1BAR[08-09h]) */ +#define SUSCFG (1<<2) /* enable powering down a GXLV processor. "Special 3Volt Suspend" mode */ +/* the belows support only with cs5530A */ +#define PWRSVE_ISA (1<<3) /* stop ISA clock */ +#define PWRSVE (1<<4) /* active idle */ struct gxfreq_params { u8 on_duration; @@ -128,7 +128,7 @@ module_param (pci_busclk, int, 0444); /* maximum duration for which the cpu may be suspended * (32us * MAX_DURATION). If no parameter is given, this defaults - * to 255. + * to 255. * Note that this leads to a maximum of 8 ms(!) where the CPU clock * is suspended -- processing power is just 0.39% of what it used to be, * though. 781.25 kHz(!) for a 200 MHz processor -- wow. */ @@ -144,17 +144,17 @@ module_param (max_duration, int, 0444); #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "gx-suspmod", msg) /** - * we can detect a core multipiler from dir0_lsb - * from GX1 datasheet p.56, - * MULT[3:0]: - * 0000 = SYSCLK multiplied by 4 (test only) - * 0001 = SYSCLK multiplied by 10 - * 0010 = SYSCLK multiplied by 4 - * 0011 = SYSCLK multiplied by 6 - * 0100 = SYSCLK multiplied by 9 - * 0101 = SYSCLK multiplied by 5 - * 0110 = SYSCLK multiplied by 7 - * 0111 = SYSCLK multiplied by 8 + * we can detect a core multipiler from dir0_lsb + * from GX1 datasheet p.56, + * MULT[3:0]: + * 0000 = SYSCLK multiplied by 4 (test only) + * 0001 = SYSCLK multiplied by 10 + * 0010 = SYSCLK multiplied by 4 + * 0011 = SYSCLK multiplied by 6 + * 0100 = SYSCLK multiplied by 9 + * 0101 = SYSCLK multiplied by 5 + * 0110 = SYSCLK multiplied by 7 + * 0111 = SYSCLK multiplied by 8 * of 33.3MHz **/ static int gx_freq_mult[16] = { @@ -164,17 +164,17 @@ static int gx_freq_mult[16] = { /**************************************************************** - * Low Level chipset interface * + * Low Level chipset interface * ****************************************************************/ static struct pci_device_id gx_chipset_tbl[] __initdata = { - { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, PCI_ANY_ID, PCI_ANY_ID }, - { 0, }, + { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, PCI_ANY_ID, PCI_ANY_ID }, + { 0, }, }; /** - * gx_detect_chipset: + * gx_detect_chipset: * **/ static __init struct pci_dev *gx_detect_chipset(void) @@ -182,17 +182,16 @@ static __init struct pci_dev *gx_detect_chipset(void) struct pci_dev *gx_pci = NULL; /* check if CPU is a MediaGX or a Geode. */ - if ((current_cpu_data.x86_vendor != X86_VENDOR_NSC) && + if ((current_cpu_data.x86_vendor != X86_VENDOR_NSC) && (current_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) { dprintk("error: no MediaGX/Geode processor found!\n"); - return NULL; + return NULL; } /* detect which companion chip is used */ while ((gx_pci = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, gx_pci)) != NULL) { - if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL) { + if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL) return gx_pci; - } } dprintk("error: no supported chipset found!\n"); @@ -200,24 +199,24 @@ static __init struct pci_dev *gx_detect_chipset(void) } /** - * gx_get_cpuspeed: + * gx_get_cpuspeed: * * Finds out at which efficient frequency the Cyrix MediaGX/NatSemi Geode CPU runs. */ static unsigned int gx_get_cpuspeed(unsigned int cpu) { - if ((gx_params->pci_suscfg & SUSMOD) == 0) + if ((gx_params->pci_suscfg & SUSMOD) == 0) return stock_freq; - return (stock_freq * gx_params->off_duration) + return (stock_freq * gx_params->off_duration) / (gx_params->on_duration + gx_params->off_duration); } /** * gx_validate_speed: * determine current cpu speed - * -**/ + * + **/ static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration, u8 *off_duration) { @@ -230,7 +229,7 @@ static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration, u8 *off *on_duration=0; for (i=max_duration; i>0; i--) { - tmp_off = ((khz * i) / stock_freq) & 0xff; + tmp_off = ((khz * i) / stock_freq) & 0xff; tmp_on = i - tmp_off; tmp_freq = (stock_freq * tmp_off) / i; /* if this relation is closer to khz, use this. If it's equal, @@ -247,18 +246,17 @@ static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration, u8 *off /** - * gx_set_cpuspeed: - * set cpu speed in khz. + * gx_set_cpuspeed: + * set cpu speed in khz. **/ static void gx_set_cpuspeed(unsigned int khz) { - u8 suscfg, pmer1; + u8 suscfg, pmer1; unsigned int new_khz; unsigned long flags; struct cpufreq_freqs freqs; - freqs.cpu = 0; freqs.old = gx_get_cpuspeed(0); @@ -303,18 +301,18 @@ static void gx_set_cpuspeed(unsigned int khz) pci_write_config_byte(gx_params->cs55x0, PCI_MODOFF, gx_params->off_duration); pci_write_config_byte(gx_params->cs55x0, PCI_MODON, gx_params->on_duration); - pci_write_config_byte(gx_params->cs55x0, PCI_SUSCFG, suscfg); - pci_read_config_byte(gx_params->cs55x0, PCI_SUSCFG, &suscfg); + pci_write_config_byte(gx_params->cs55x0, PCI_SUSCFG, suscfg); + pci_read_config_byte(gx_params->cs55x0, PCI_SUSCFG, &suscfg); - local_irq_restore(flags); + local_irq_restore(flags); gx_params->pci_suscfg = suscfg; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - dprintk("suspend modulation w/ duration of ON:%d us, OFF:%d us\n", - gx_params->on_duration * 32, gx_params->off_duration * 32); - dprintk("suspend modulation w/ clock speed: %d kHz.\n", freqs.new); + dprintk("suspend modulation w/ duration of ON:%d us, OFF:%d us\n", + gx_params->on_duration * 32, gx_params->off_duration * 32); + dprintk("suspend modulation w/ clock speed: %d kHz.\n", freqs.new); } /**************************************************************** @@ -322,10 +320,10 @@ static void gx_set_cpuspeed(unsigned int khz) ****************************************************************/ /* - * cpufreq_gx_verify: test if frequency range is valid + * cpufreq_gx_verify: test if frequency range is valid * - * This function checks if a given frequency range in kHz is valid - * for the hardware supported by the driver. + * This function checks if a given frequency range in kHz is valid + * for the hardware supported by the driver. */ static int cpufreq_gx_verify(struct cpufreq_policy *policy) @@ -333,8 +331,8 @@ static int cpufreq_gx_verify(struct cpufreq_policy *policy) unsigned int tmp_freq = 0; u8 tmp1, tmp2; - if (!stock_freq || !policy) - return -EINVAL; + if (!stock_freq || !policy) + return -EINVAL; policy->cpu = 0; cpufreq_verify_within_limits(policy, (stock_freq / max_duration), stock_freq); @@ -342,14 +340,14 @@ static int cpufreq_gx_verify(struct cpufreq_policy *policy) /* it needs to be assured that at least one supported frequency is * within policy->min and policy->max. If it is not, policy->max * needs to be increased until one freuqency is supported. - * policy->min may not be decreased, though. This way we guarantee a + * policy->min may not be decreased, though. This way we guarantee a * specific processing capacity. */ tmp_freq = gx_validate_speed(policy->min, &tmp1, &tmp2); - if (tmp_freq < policy->min) + if (tmp_freq < policy->min) tmp_freq += stock_freq / max_duration; policy->min = tmp_freq; - if (policy->min > policy->max) + if (policy->min > policy->max) policy->max = tmp_freq; tmp_freq = gx_validate_speed(policy->max, &tmp1, &tmp2); if (tmp_freq > policy->max) @@ -358,12 +356,12 @@ static int cpufreq_gx_verify(struct cpufreq_policy *policy) if (policy->max < policy->min) policy->max = policy->min; cpufreq_verify_within_limits(policy, (stock_freq / max_duration), stock_freq); - + return 0; } /* - * cpufreq_gx_target: + * cpufreq_gx_target: * */ static int cpufreq_gx_target(struct cpufreq_policy *policy, @@ -373,8 +371,8 @@ static int cpufreq_gx_target(struct cpufreq_policy *policy, u8 tmp1, tmp2; unsigned int tmp_freq; - if (!stock_freq || !policy) - return -EINVAL; + if (!stock_freq || !policy) + return -EINVAL; policy->cpu = 0; @@ -431,7 +429,7 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy) return 0; } -/* +/* * cpufreq_gx_init: * MediaGX/Geode GX initialize cpufreq driver */ @@ -452,7 +450,7 @@ static int __init cpufreq_gx_init(void) u32 class_rev; /* Test if we have the right hardware */ - if ((gx_pci = gx_detect_chipset()) == NULL) + if ((gx_pci = gx_detect_chipset()) == NULL) return -ENODEV; /* check whether module parameters are sane */ @@ -478,7 +476,7 @@ static int __init cpufreq_gx_init(void) pci_read_config_dword(params->cs55x0, PCI_CLASS_REVISION, &class_rev); params->pci_rev = class_rev && 0xff; - if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) { + if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) { kfree(params); return ret; /* register error! */ } diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h index 2a495c162ec7..d3a95d77ee85 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.h +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h @@ -234,7 +234,7 @@ static int __initdata ezrat_eblcr[32] = { /* * VIA C3 Nehemiah */ - + static int __initdata nehemiah_a_clock_ratio[32] = { 100, /* 0000 -> 10.0x */ 160, /* 0001 -> 16.0x */ @@ -446,7 +446,7 @@ static int __initdata nehemiah_c_eblcr[32] = { /* end of table */ }; -/* +/* * Voltage scales. Div/Mod by 1000 to get actual voltage. * Which scale to use depends on the VRM type in use. */ diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c index cc73a7ae34bc..0e1fc5c45242 100644 --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c @@ -14,7 +14,7 @@ * The author(s) of this software shall not be held liable for damages * of any nature resulting due to the use of this software. This * software is provided AS-IS with no warranties. - * + * * Date Errata Description * 20020525 N44, O17 12.5% or 25% DC causes lockup * @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include @@ -30,7 +30,7 @@ #include #include /* current / set_cpus_allowed() */ -#include +#include #include #include @@ -79,7 +79,7 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate) } else { dprintk("CPU#%d setting duty cycle to %d%%\n", cpu, ((125 * newstate) / 10)); - /* bits 63 - 5 : reserved + /* bits 63 - 5 : reserved * bit 4 : enable/disable * bits 3-1 : duty cycle * bit 0 : reserved @@ -132,7 +132,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, } /* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software - * Developer's Manual, Volume 3 + * Developer's Manual, Volume 3 */ cpus_allowed = current->cpus_allowed; @@ -206,7 +206,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_P4D); } - + static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) { @@ -234,7 +234,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) dprintk("has errata -- disabling frequencies lower than 2ghz\n"); break; } - + /* get max frequency */ stock_freq = cpufreq_p4_get_frequency(c); if (!stock_freq) @@ -250,7 +250,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) p4clockmod_table[i].frequency = (stock_freq * i)/8; } cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu); - + /* cpuinfo and default policy values */ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 1000000; /* assumed */ @@ -262,7 +262,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy) { - cpufreq_frequency_table_put_attr(policy->cpu); + cpufreq_frequency_table_put_attr(policy->cpu); return 0; } @@ -298,7 +298,7 @@ static struct freq_attr* p4clockmod_attr[] = { }; static struct cpufreq_driver p4clockmod_driver = { - .verify = cpufreq_p4_verify, + .verify = cpufreq_p4_verify, .target = cpufreq_p4_target, .init = cpufreq_p4_cpu_init, .exit = cpufreq_p4_cpu_exit, @@ -310,12 +310,12 @@ static struct cpufreq_driver p4clockmod_driver = { static int __init cpufreq_p4_init(void) -{ +{ struct cpuinfo_x86 *c = cpu_data; int ret; /* - * THERM_CONTROL is architectural for IA32 now, so + * THERM_CONTROL is architectural for IA32 now, so * we can rely on the capability checks */ if (c->x86_vendor != X86_VENDOR_INTEL) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c index 222f8cfe3c57..f89524051e4a 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c @@ -8,7 +8,7 @@ */ #include -#include +#include #include #include #include @@ -50,7 +50,7 @@ static int powernow_k6_get_cpu_multiplier(void) { u64 invalue = 0; u32 msrval; - + msrval = POWERNOW_IOPORT + 0x1; wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ invalue=inl(POWERNOW_IOPORT + 0x8); @@ -81,7 +81,7 @@ static void powernow_k6_set_state (unsigned int best_i) freqs.old = busfreq * powernow_k6_get_cpu_multiplier(); freqs.new = busfreq * clock_ratio[best_i].index; freqs.cpu = 0; /* powernow-k6.c is UP only driver */ - + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); /* we now need to transform best_i to the BVC format, see AMD#23446 */ @@ -152,7 +152,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) busfreq = cpu_khz / max_multiplier; /* table init */ - for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { + for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { if (clock_ratio[i].index > max_multiplier) clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID; else @@ -182,7 +182,7 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy) powernow_k6_set_state(i); } cpufreq_frequency_table_put_attr(policy->cpu); - return 0; + return 0; } static unsigned int powernow_k6_get(unsigned int cpu) @@ -196,8 +196,8 @@ static struct freq_attr* powernow_k6_attr[] = { }; static struct cpufreq_driver powernow_k6_driver = { - .verify = powernow_k6_verify, - .target = powernow_k6_target, + .verify = powernow_k6_verify, + .target = powernow_k6_target, .init = powernow_k6_cpu_init, .exit = powernow_k6_cpu_exit, .get = powernow_k6_get, @@ -215,7 +215,7 @@ static struct cpufreq_driver powernow_k6_driver = { * on success. */ static int __init powernow_k6_init(void) -{ +{ struct cpuinfo_x86 *c = cpu_data; if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) || diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index edcd626001da..2bf4237cb94e 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -199,8 +199,8 @@ static int get_ranges (unsigned char *pst) powernow_table[j].index |= (vid << 8); /* upper 8 bits */ dprintk (" FID: 0x%x (%d.%dx [%dMHz]) " - "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10, - fid_codes[fid] % 10, speed/1000, vid, + "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10, + fid_codes[fid] % 10, speed/1000, vid, mobile_vid_table[vid]/1000, mobile_vid_table[vid]%1000); } @@ -368,8 +368,8 @@ static int powernow_acpi_init(void) } dprintk (" FID: 0x%x (%d.%dx [%dMHz]) " - "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10, - fid_codes[fid] % 10, speed/1000, vid, + "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10, + fid_codes[fid] % 10, speed/1000, vid, mobile_vid_table[vid]/1000, mobile_vid_table[vid]%1000); @@ -460,7 +460,7 @@ static int powernow_decode_bios (int maxfid, int startvid) (maxfid==pst->maxfid) && (startvid==pst->startvid)) { dprintk ("PST:%d (@%p)\n", i, pst); - dprintk (" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n", + dprintk (" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n", pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid); ret = get_ranges ((char *) pst + sizeof (struct pst_s)); diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 3b3a94987d10..e85e90524df7 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -83,11 +83,10 @@ static u32 find_millivolts_from_vid(struct powernow_k8_data *data, u32 vid) */ static u32 convert_fid_to_vco_fid(u32 fid) { - if (fid < HI_FID_TABLE_BOTTOM) { + if (fid < HI_FID_TABLE_BOTTOM) return 8 + (2 * fid); - } else { + else return fid; - } } /* @@ -177,7 +176,7 @@ static int write_new_fid(struct powernow_k8_data *data, u32 fid) if (i++ > 100) { printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n"); return 1; - } + } } while (query_current_values_with_pending_wait(data)); count_off_irt(data); @@ -782,9 +781,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) /* verify only 1 entry from the lo frequency table */ if (fid < HI_FID_TABLE_BOTTOM) { if (cntlofreq) { - /* if both entries are the same, ignore this - * one... - */ + /* if both entries are the same, ignore this one ... */ if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) || (powernow_table[i].index != powernow_table[cntlofreq].index)) { printk(KERN_ERR PFX "Too many lo freq table entries\n"); @@ -856,7 +853,7 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); /* fid are the lower 8 bits of the index we stored into - * the cpufreq frequency table in find_psb_table, vid are + * the cpufreq frequency table in find_psb_table, vid are * the upper 8 bits. */ @@ -1050,7 +1047,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) pol->governor = CPUFREQ_DEFAULT_GOVERNOR; pol->cpus = cpu_core_map[pol->cpu]; - /* Take a crude guess here. + /* Take a crude guess here. * That guess was in microseconds, so multiply with 1000 */ pol->cpuinfo.transition_latency = (((data->rvo + 8) * data->vstable * VST_UNITS_20US) + (3 * (1 << data->irt) * 10)) * 1000; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index d0de37d58e9a..00ea899c17e1 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h @@ -63,7 +63,7 @@ struct powernow_k8_data { #define MSR_C_LO_VID_SHIFT 8 /* Field definitions within the FID VID High Control MSR : */ -#define MSR_C_HI_STP_GNT_TO 0x000fffff +#define MSR_C_HI_STP_GNT_TO 0x000fffff /* Field definitions within the FID VID Low Status MSR : */ #define MSR_S_LO_CHANGE_PENDING 0x80000000 /* cleared when completed */ @@ -123,7 +123,7 @@ struct powernow_k8_data { * Most values of interest are enocoded in a single field of the _PSS * entries: the "control" value. */ - + #define IRT_SHIFT 30 #define RVO_SHIFT 28 #define EXT_TYPE_SHIFT 27 @@ -185,7 +185,7 @@ static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned #ifndef for_each_cpu_mask #define for_each_cpu_mask(i,mask) for (i=0;i<1;i++) #endif - + #ifdef CONFIG_SMP static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[]) { diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c index 7c47005a1805..4f46cac155c4 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c @@ -9,7 +9,7 @@ */ #include -#include +#include #include #include #include @@ -36,8 +36,8 @@ static unsigned int pentium3_get_frequency (unsigned int processor) /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */ struct { unsigned int ratio; /* Frequency Multiplier (x10) */ - u8 bitmap; /* power on configuration bits - [27, 25:22] (in MSR 0x2a) */ + u8 bitmap; /* power on configuration bits + [27, 25:22] (in MSR 0x2a) */ } msr_decode_mult [] = { { 30, 0x01 }, { 35, 0x05 }, @@ -58,9 +58,9 @@ static unsigned int pentium3_get_frequency (unsigned int processor) /* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */ struct { - unsigned int value; /* Front Side Bus speed in MHz */ - u8 bitmap; /* power on configuration bits [18: 19] - (in MSR 0x2a) */ + unsigned int value; /* Front Side Bus speed in MHz */ + u8 bitmap; /* power on configuration bits [18: 19] + (in MSR 0x2a) */ } msr_decode_fsb [] = { { 66, 0x0 }, { 100, 0x2 }, @@ -68,8 +68,8 @@ static unsigned int pentium3_get_frequency (unsigned int processor) { 0, 0xff} }; - u32 msr_lo, msr_tmp; - int i = 0, j = 0; + u32 msr_lo, msr_tmp; + int i = 0, j = 0; /* read MSR 0x2a - we only need the low 32 bits */ rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); @@ -106,7 +106,7 @@ static unsigned int pentium3_get_frequency (unsigned int processor) static unsigned int pentiumM_get_frequency(void) { - u32 msr_lo, msr_tmp; + u32 msr_lo, msr_tmp; rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); dprintk("PM - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); @@ -134,7 +134,7 @@ static unsigned int pentium4_get_frequency(void) dprintk("P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); - /* decode the FSB: see IA-32 Intel (C) Architecture Software + /* decode the FSB: see IA-32 Intel (C) Architecture Software * Developer's Manual, Volume 3: System Prgramming Guide, * revision #12 in Table B-1: MSRs in the Pentium 4 and * Intel Xeon Processors, on page B-4 and B-5. @@ -170,7 +170,7 @@ static unsigned int pentium4_get_frequency(void) return (fsb * mult); } - + unsigned int speedstep_get_processor_frequency(unsigned int processor) { switch (processor) { @@ -198,11 +198,11 @@ EXPORT_SYMBOL_GPL(speedstep_get_processor_frequency); unsigned int speedstep_detect_processor (void) { struct cpuinfo_x86 *c = cpu_data; - u32 ebx, msr_lo, msr_hi; + u32 ebx, msr_lo, msr_hi; dprintk("x86: %x, model: %x\n", c->x86, c->x86_model); - if ((c->x86_vendor != X86_VENDOR_INTEL) || + if ((c->x86_vendor != X86_VENDOR_INTEL) || ((c->x86 != 6) && (c->x86 != 0xF))) return 0; @@ -218,15 +218,15 @@ unsigned int speedstep_detect_processor (void) dprintk("ebx value is %x, x86_mask is %x\n", ebx, c->x86_mask); switch (c->x86_mask) { - case 4: + case 4: /* - * B-stepping [M-P4-M] + * B-stepping [M-P4-M] * sample has ebx = 0x0f, production has 0x0e. */ if ((ebx == 0x0e) || (ebx == 0x0f)) return SPEEDSTEP_PROCESSOR_P4M; break; - case 7: + case 7: /* * C-stepping [M-P4-M] * needs to have ebx=0x0e, else it's a celeron: @@ -253,7 +253,7 @@ unsigned int speedstep_detect_processor (void) * also, M-P4M HTs have ebx=0x8, too * For now, they are distinguished by the model_id string */ - if ((ebx == 0x0e) || (strstr(c->x86_model_id,"Mobile Intel(R) Pentium(R) 4") != NULL)) + if ((ebx == 0x0e) || (strstr(c->x86_model_id,"Mobile Intel(R) Pentium(R) 4") != NULL)) return SPEEDSTEP_PROCESSOR_P4M; break; default: @@ -264,8 +264,7 @@ unsigned int speedstep_detect_processor (void) switch (c->x86_model) { case 0x0B: /* Intel PIII [Tualatin] */ - /* cpuid_ebx(1) is 0x04 for desktop PIII, - 0x06 for mobile PIII-M */ + /* cpuid_ebx(1) is 0x04 for desktop PIII, 0x06 for mobile PIII-M */ ebx = cpuid_ebx(0x00000001); dprintk("ebx is %x\n", ebx); @@ -275,9 +274,8 @@ unsigned int speedstep_detect_processor (void) return 0; /* So far all PIII-M processors support SpeedStep. See - * Intel's 24540640.pdf of June 2003 + * Intel's 24540640.pdf of June 2003 */ - return SPEEDSTEP_PROCESSOR_PIII_T; case 0x08: /* Intel PIII [Coppermine] */ @@ -399,7 +397,7 @@ unsigned int speedstep_get_freqs(unsigned int processor, } } - out: +out: local_irq_restore(flags); return (ret); } diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h index 6a727fd3a77e..b735429c50b4 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h @@ -14,7 +14,7 @@ #define SPEEDSTEP_PROCESSOR_PIII_C_EARLY 0x00000001 /* Coppermine core */ #define SPEEDSTEP_PROCESSOR_PIII_C 0x00000002 /* Coppermine core */ -#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000003 /* Tualatin core */ +#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000003 /* Tualatin core */ #define SPEEDSTEP_PROCESSOR_P4M 0x00000004 /* P4-M */ /* the following processors are not speedstep-capable and are not auto-detected @@ -25,8 +25,8 @@ /* speedstep states -- only two of them */ -#define SPEEDSTEP_HIGH 0x00000000 -#define SPEEDSTEP_LOW 0x00000001 +#define SPEEDSTEP_HIGH 0x00000000 +#define SPEEDSTEP_LOW 0x00000001 /* detect a speedstep-capable processor */ @@ -36,13 +36,13 @@ extern unsigned int speedstep_detect_processor (void); extern unsigned int speedstep_get_processor_frequency(unsigned int processor); -/* detect the low and high speeds of the processor. The callback - * set_state"'s first argument is either SPEEDSTEP_HIGH or - * SPEEDSTEP_LOW; the second argument is zero so that no +/* detect the low and high speeds of the processor. The callback + * set_state"'s first argument is either SPEEDSTEP_HIGH or + * SPEEDSTEP_LOW; the second argument is zero so that no * cpufreq_notify_transition calls are initiated. */ extern unsigned int speedstep_get_freqs(unsigned int processor, - unsigned int *low_speed, - unsigned int *high_speed, - unsigned int *transition_latency, - void (*set_state) (unsigned int state)); + unsigned int *low_speed, + unsigned int *high_speed, + unsigned int *transition_latency, + void (*set_state) (unsigned int state)); diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c index 28cc5d524afc..336ba49e526d 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c @@ -13,8 +13,8 @@ *********************************************************************/ #include -#include -#include +#include +#include #include #include #include @@ -28,21 +28,21 @@ * * These parameters are got from IST-SMI BIOS call. * If user gives it, these are used. - * + * */ -static int smi_port = 0; -static int smi_cmd = 0; -static unsigned int smi_sig = 0; +static int smi_port = 0; +static int smi_cmd = 0; +static unsigned int smi_sig = 0; /* info about the processor */ -static unsigned int speedstep_processor = 0; +static unsigned int speedstep_processor = 0; -/* - * There are only two frequency states for each processor. Values +/* + * There are only two frequency states for each processor. Values * are in kHz for the time being. */ static struct cpufreq_frequency_table speedstep_freqs[] = { - {SPEEDSTEP_HIGH, 0}, + {SPEEDSTEP_HIGH, 0}, {SPEEDSTEP_LOW, 0}, {0, CPUFREQ_TABLE_END}, }; @@ -123,7 +123,7 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) *low = low_mhz * 1000; return result; -} +} /** * speedstep_get_state - set the SpeedStep state @@ -204,7 +204,7 @@ static void speedstep_set_state (unsigned int state) * speedstep_target - set a new CPUFreq policy * @policy: new policy * @target_freq: new freq - * @relation: + * @relation: * * Sets a new CPUFreq policy/freq. */ @@ -283,7 +283,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) state = speedstep_get_state(); speed = speedstep_freqs[state].frequency; - dprintk("currently at %s speed setting - %i MHz\n", + dprintk("currently at %s speed setting - %i MHz\n", (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high", (speed / 1000)); @@ -296,7 +296,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) if (result) return (result); - cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu); + cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu); return 0; } @@ -332,8 +332,8 @@ static struct freq_attr* speedstep_attr[] = { static struct cpufreq_driver speedstep_driver = { .name = "speedstep-smi", - .verify = speedstep_verify, - .target = speedstep_target, + .verify = speedstep_verify, + .target = speedstep_target, .init = speedstep_cpu_init, .exit = speedstep_cpu_exit, .get = speedstep_get, @@ -370,13 +370,12 @@ static int __init speedstep_init(void) return -ENODEV; } - dprintk("signature:0x%.8lx, command:0x%.8lx, event:0x%.8lx, perf_level:0x%.8lx.\n", + dprintk("signature:0x%.8lx, command:0x%.8lx, event:0x%.8lx, perf_level:0x%.8lx.\n", ist_info.signature, ist_info.command, ist_info.event, ist_info.perf_level); - - /* Error if no IST-SMI BIOS or no PARM + /* Error if no IST-SMI BIOS or no PARM sig= 'ISGE' aka 'Intel Speedstep Gate E' */ - if ((ist_info.signature != 0x47534943) && ( + if ((ist_info.signature != 0x47534943) && ( (smi_port == 0) || (smi_cmd == 0))) return -ENODEV; @@ -386,17 +385,15 @@ static int __init speedstep_init(void) smi_sig = ist_info.signature; /* setup smi_port from MODLULE_PARM or BIOS */ - if ((smi_port > 0xff) || (smi_port < 0)) { + if ((smi_port > 0xff) || (smi_port < 0)) return -EINVAL; - } else if (smi_port == 0) { + else if (smi_port == 0) smi_port = ist_info.command & 0xff; - } - if ((smi_cmd > 0xff) || (smi_cmd < 0)) { + if ((smi_cmd > 0xff) || (smi_cmd < 0)) return -EINVAL; - } else if (smi_cmd == 0) { + else if (smi_cmd == 0) smi_cmd = (ist_info.command >> 16) & 0xff; - } return cpufreq_register_driver(&speedstep_driver); } diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 9582de1c9cad..cb7d6e0db759 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -5,7 +5,7 @@ * (C) 2002 - 2003 Dominik Brodowski * * Oct 2005 - Ashok Raj - * Added handling for CPU hotplug + * Added handling for CPU hotplug * * 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 @@ -44,8 +44,8 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) static void handle_update(void *data); /** - * Two notifier lists: the "policy" list is involved in the - * validation process for a new CPU frequency policy; the + * Two notifier lists: the "policy" list is involved in the + * validation process for a new CPU frequency policy; the * "transition" list for kernel code that needs to handle * changes to devices when the CPU clock speed changes. * The mutex locks both lists. @@ -151,7 +151,7 @@ void cpufreq_debug_printk(unsigned int type, const char *prefix, const char *fmt va_list args; unsigned int len; unsigned long flags; - + WARN_ON(!prefix); if (type & debug) { spin_lock_irqsave(&disable_ratelimit_lock, flags); @@ -198,7 +198,7 @@ static inline void cpufreq_debug_disable_ratelimit(void) { return; } * * This function alters the system "loops_per_jiffy" for the clock * speed change. Note that loops_per_jiffy cannot be updated on SMP - * systems as each CPU might be scaled differently. So, use the arch + * systems as each CPU might be scaled differently. So, use the arch * per-CPU loops_per_jiffy value wherever possible. */ #ifndef CONFIG_SMP @@ -233,7 +233,7 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { * * This function calls the transition notifiers and the "adjust_jiffies" * function. It is called twice on all CPU frequency changes that have - * external effects. + * external effects. */ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) { @@ -251,7 +251,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) switch (state) { case CPUFREQ_PRECHANGE: - /* detect if the driver reported a value as "old frequency" + /* detect if the driver reported a value as "old frequency" * which is not equal to what the cpufreq core thinks is * "old frequency". */ @@ -335,11 +335,11 @@ extern struct sysdev_class cpu_sysdev_class; * "unsigned int". */ -#define show_one(file_name, object) \ -static ssize_t show_##file_name \ -(struct cpufreq_policy * policy, char *buf) \ -{ \ - return sprintf (buf, "%u\n", policy->object); \ +#define show_one(file_name, object) \ +static ssize_t show_##file_name \ +(struct cpufreq_policy * policy, char *buf) \ +{ \ + return sprintf (buf, "%u\n", policy->object); \ } show_one(cpuinfo_min_freq, cpuinfo.min_freq); @@ -404,8 +404,8 @@ static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf) /** * store_scaling_governor - store policy for the specified CPU */ -static ssize_t store_scaling_governor (struct cpufreq_policy * policy, - const char *buf, size_t count) +static ssize_t store_scaling_governor (struct cpufreq_policy * policy, + const char *buf, size_t count) { unsigned int ret = -EINVAL; char str_governor[16]; @@ -528,7 +528,7 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf) return ret; } -static ssize_t store(struct kobject * kobj, struct attribute * attr, +static ssize_t store(struct kobject * kobj, struct attribute * attr, const char * buf, size_t count) { struct cpufreq_policy * policy = to_policy(kobj); @@ -564,7 +564,7 @@ static struct kobj_type ktype_cpufreq = { /** * cpufreq_add_dev - add a CPU device * - * Adds the cpufreq interface for a CPU device. + * Adds the cpufreq interface for a CPU device. */ static int cpufreq_add_dev (struct sys_device * sys_dev) { @@ -724,7 +724,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) #ifdef CONFIG_SMP /* if this isn't the CPU which is the parent of the kobj, we - * only need to unlink, put and exit + * only need to unlink, put and exit */ if (unlikely(cpu != data->cpu)) { dprintk("removing link\n"); @@ -740,7 +740,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) if (!kobject_get(&data->kobj)) { spin_unlock_irqrestore(&cpufreq_driver_lock, flags); cpufreq_debug_enable_ratelimit(); - return -EFAULT; + return -EFAULT; } #ifdef CONFIG_SMP @@ -783,7 +783,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) kobject_put(&data->kobj); /* we need to make sure that the underlying kobj is actually - * not referenced anymore by anybody before we proceed with + * not referenced anymore by anybody before we proceed with * unloading. */ dprintk("waiting for dropping of refcount\n"); @@ -831,7 +831,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne } -/** +/** * cpufreq_quick_get - get the CPU frequency (in kHz) frpm policy->cur * @cpu: CPU number * @@ -855,7 +855,7 @@ unsigned int cpufreq_quick_get(unsigned int cpu) EXPORT_SYMBOL(cpufreq_quick_get); -/** +/** * cpufreq_get - get the current CPU frequency (in kHz) * @cpu: CPU number * @@ -1072,7 +1072,7 @@ static struct sysdev_driver cpufreq_sysdev_driver = { * @nb: notifier function to register * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER * - * Add a driver to one of two lists: either a list of drivers that + * Add a driver to one of two lists: either a list of drivers that * are notified about clock rate changes (once before and once after * the transition), or a list of drivers that are notified about * changes in cpufreq policy. @@ -1225,7 +1225,7 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) return -EINVAL; mutex_lock(&cpufreq_governor_mutex); - + list_for_each_entry(t, &cpufreq_governor_list, governor_list) { if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { mutex_unlock(&cpufreq_governor_mutex); @@ -1234,7 +1234,7 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) } list_add(&governor->governor_list, &cpufreq_governor_list); - mutex_unlock(&cpufreq_governor_mutex); + mutex_unlock(&cpufreq_governor_mutex); return 0; } EXPORT_SYMBOL_GPL(cpufreq_register_governor); @@ -1497,9 +1497,9 @@ static struct notifier_block cpufreq_cpu_notifier = * @driver_data: A struct cpufreq_driver containing the values# * submitted by the CPU Frequency driver. * - * Registers a CPU Frequency driver to this core code. This code + * Registers a CPU Frequency driver to this core code. This code * returns zero on success, -EBUSY when another driver got here first - * (and isn't unregistered in the meantime). + * (and isn't unregistered in the meantime). * */ int cpufreq_register_driver(struct cpufreq_driver *driver_data) @@ -1560,7 +1560,7 @@ EXPORT_SYMBOL_GPL(cpufreq_register_driver); /** * cpufreq_unregister_driver - unregister the current CPUFreq driver * - * Unregister the current CPUFreq driver. Only call this if you have + * Unregister the current CPUFreq driver. Only call this if you have * the right to do so, i.e. if you have succeeded in initialising before! * Returns zero if successful, and -EINVAL if the cpufreq_driver is * currently not initialised. diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 9ee9411f186f..69aa1db8336c 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -38,17 +38,17 @@ #define MIN_FREQUENCY_UP_THRESHOLD (11) #define MAX_FREQUENCY_UP_THRESHOLD (100) -/* - * The polling frequency of this governor depends on the capability of +/* + * The polling frequency of this governor depends on the capability of * the processor. Default polling frequency is 1000 times the transition - * latency of the processor. The governor will work on any processor with - * transition latency <= 10mS, using appropriate sampling + * latency of the processor. The governor will work on any processor with + * transition latency <= 10mS, using appropriate sampling * rate. * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) * this governor will not work. * All times here are in uS. */ -static unsigned int def_sampling_rate; +static unsigned int def_sampling_rate; #define MIN_SAMPLING_RATE_RATIO (2) /* for correct statistics, we need at least 10 ticks between each measure */ #define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) @@ -62,28 +62,28 @@ static unsigned int def_sampling_rate; static void do_dbs_timer(void *data); struct cpu_dbs_info_s { - struct cpufreq_policy *cur_policy; - unsigned int prev_cpu_idle_up; - unsigned int prev_cpu_idle_down; - unsigned int enable; + struct cpufreq_policy *cur_policy; + unsigned int prev_cpu_idle_up; + unsigned int prev_cpu_idle_down; + unsigned int enable; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); static unsigned int dbs_enable; /* number of CPUs using this policy */ -static DEFINE_MUTEX (dbs_mutex); +static DEFINE_MUTEX (dbs_mutex); static DECLARE_WORK (dbs_work, do_dbs_timer, NULL); struct dbs_tuners { - unsigned int sampling_rate; - unsigned int sampling_down_factor; - unsigned int up_threshold; - unsigned int ignore_nice; + unsigned int sampling_rate; + unsigned int sampling_down_factor; + unsigned int up_threshold; + unsigned int ignore_nice; }; static struct dbs_tuners dbs_tuners_ins = { - .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, - .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, + .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, + .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, }; static inline unsigned int get_cpu_idle_time(unsigned int cpu) @@ -106,8 +106,8 @@ static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) return sprintf (buf, "%u\n", MIN_SAMPLING_RATE); } -#define define_one_ro(_name) \ -static struct freq_attr _name = \ +#define define_one_ro(_name) \ +static struct freq_attr _name = \ __ATTR(_name, 0444, show_##_name, NULL) define_one_ro(sampling_rate_max); @@ -125,7 +125,7 @@ show_one(sampling_down_factor, sampling_down_factor); show_one(up_threshold, up_threshold); show_one(ignore_nice_load, ignore_nice); -static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, +static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, const char *buf, size_t count) { unsigned int input; @@ -144,7 +144,7 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, return count; } -static ssize_t store_sampling_rate(struct cpufreq_policy *unused, +static ssize_t store_sampling_rate(struct cpufreq_policy *unused, const char *buf, size_t count) { unsigned int input; @@ -163,7 +163,7 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, return count; } -static ssize_t store_up_threshold(struct cpufreq_policy *unused, +static ssize_t store_up_threshold(struct cpufreq_policy *unused, const char *buf, size_t count) { unsigned int input; @@ -171,7 +171,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, ret = sscanf (buf, "%u", &input); mutex_lock(&dbs_mutex); - if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || + if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || input < MIN_FREQUENCY_UP_THRESHOLD) { mutex_unlock(&dbs_mutex); return -EINVAL; @@ -190,14 +190,14 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, int ret; unsigned int j; - + ret = sscanf (buf, "%u", &input); if ( ret != 1 ) return -EINVAL; if ( input > 1 ) input = 1; - + mutex_lock(&dbs_mutex); if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */ mutex_unlock(&dbs_mutex); @@ -259,16 +259,16 @@ static void dbs_check_cpu(int cpu) return; policy = this_dbs_info->cur_policy; - /* + /* * Every sampling_rate, we check, if current idle time is less * than 20% (default), then we try to increase frequency * Every sampling_rate*sampling_down_factor, we look for a the lowest * frequency which can sustain the load while keeping idle time over * 30%. If such a frequency exist, we try to decrease to this frequency. * - * Any frequency increase takes it to the maximum frequency. - * Frequency reduction happens at minimum steps of - * 5% (default) of current frequency + * Any frequency increase takes it to the maximum frequency. + * Frequency reduction happens at minimum steps of + * 5% (default) of current frequency */ /* Check for frequency increase */ @@ -298,14 +298,14 @@ static void dbs_check_cpu(int cpu) struct cpu_dbs_info_s *j_dbs_info; j_dbs_info = &per_cpu(cpu_dbs_info, j); - j_dbs_info->prev_cpu_idle_down = + j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; } /* if we are already at full speed then break out early */ if (policy->cur == policy->max) return; - - __cpufreq_driver_target(policy, policy->max, + + __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); return; } @@ -347,7 +347,7 @@ static void dbs_check_cpu(int cpu) * policy. To be safe, we focus 10 points under the threshold. */ freq_next = ((total_ticks - idle_ticks) * 100) / total_ticks; - freq_next = (freq_next * policy->cur) / + freq_next = (freq_next * policy->cur) / (dbs_tuners_ins.up_threshold - 10); if (freq_next <= ((policy->cur * 95) / 100)) @@ -355,15 +355,15 @@ static void dbs_check_cpu(int cpu) } static void do_dbs_timer(void *data) -{ +{ int i; mutex_lock(&dbs_mutex); for_each_online_cpu(i) dbs_check_cpu(i); - schedule_delayed_work(&dbs_work, + schedule_delayed_work(&dbs_work, usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); mutex_unlock(&dbs_mutex); -} +} static inline void dbs_timer_init(void) { @@ -390,7 +390,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, switch (event) { case CPUFREQ_GOV_START: - if ((!cpu_online(cpu)) || + if ((!cpu_online(cpu)) || (!policy->cur)) return -EINVAL; @@ -399,13 +399,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, return -EINVAL; if (this_dbs_info->enable) /* Already enabled */ break; - + mutex_lock(&dbs_mutex); for_each_cpu_mask(j, policy->cpus) { struct cpu_dbs_info_s *j_dbs_info; j_dbs_info = &per_cpu(cpu_dbs_info, j); j_dbs_info->cur_policy = policy; - + j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j); j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; @@ -435,7 +435,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, dbs_timer_init(); } - + mutex_unlock(&dbs_mutex); break; @@ -448,9 +448,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, * Stop the timerschedule work, when this governor * is used for first time */ - if (dbs_enable == 0) + if (dbs_enable == 0) dbs_timer_exit(); - + mutex_unlock(&dbs_mutex); break; @@ -460,11 +460,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target( this_dbs_info->cur_policy, - policy->max, CPUFREQ_RELATION_H); + policy->max, CPUFREQ_RELATION_H); else if (policy->min > this_dbs_info->cur_policy->cur) __cpufreq_driver_target( this_dbs_info->cur_policy, - policy->min, CPUFREQ_RELATION_L); + policy->min, CPUFREQ_RELATION_L); mutex_unlock(&dbs_mutex); break; } diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c index 8d536b40deb8..de91e3371ef8 100644 --- a/drivers/cpufreq/cpufreq_performance.c +++ b/drivers/cpufreq/cpufreq_performance.c @@ -32,7 +32,7 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy, } return 0; } - + struct cpufreq_governor cpufreq_gov_performance = { .name = "performance", .governor = cpufreq_governor_performance, diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c index c85edda7feb0..0a2596044e65 100644 --- a/drivers/cpufreq/cpufreq_powersave.c +++ b/drivers/cpufreq/cpufreq_powersave.c @@ -31,7 +31,7 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy, } return 0; } - + static struct cpufreq_governor cpufreq_gov_powersave = { .name = "powersave", .governor = cpufreq_governor_powersave, diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 0bddb8e694d9..c25bdb7aec51 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -2,7 +2,7 @@ * drivers/cpufreq/cpufreq_stats.c * * Copyright (C) 2003-2004 Venkatesh Pallipadi . - * (C) 2004 Zou Nan hai . + * (C) 2004 Zou Nan hai . * * 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 @@ -90,7 +90,7 @@ show_time_in_state(struct cpufreq_policy *policy, char *buf) return 0; cpufreq_stats_update(stat->cpu); for (i = 0; i < stat->state_num; i++) { - len += sprintf(buf + len, "%u %llu\n", stat->freq_table[i], + len += sprintf(buf + len, "%u %llu\n", stat->freq_table[i], (unsigned long long)cputime64_to_clock_t(stat->time_in_state[i])); } return len; @@ -171,7 +171,7 @@ cpufreq_stats_free_table (unsigned int cpu) { struct cpufreq_stats *stat = cpufreq_stats_table[cpu]; struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); - if (policy && policy->cpu == cpu) + if (policy && policy->cpu == cpu) sysfs_remove_group(&policy->kobj, &stats_attr_group); if (stat) { kfree(stat->time_in_state); diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 92a0be22a2a9..071ee4f1bbf2 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -41,7 +41,7 @@ static DEFINE_MUTEX (userspace_mutex); #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg) /* keep track of frequency transitions */ -static int +static int userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) { @@ -58,7 +58,7 @@ static struct notifier_block userspace_cpufreq_notifier_block = { }; -/** +/** * cpufreq_set - set the CPU frequency * @freq: target frequency in kHz * @cpu: CPU for which the frequency is to be set @@ -103,8 +103,8 @@ static ssize_t show_speed (struct cpufreq_policy *policy, char *buf) return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]); } -static ssize_t -store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) +static ssize_t +store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) { unsigned int freq = 0; unsigned int ret; @@ -118,7 +118,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) return count; } -static struct freq_attr freq_attr_scaling_setspeed = +static struct freq_attr freq_attr_scaling_setspeed = { .attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE }, .show = show_speed, @@ -135,7 +135,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, return -EINVAL; BUG_ON(!policy->cur); mutex_lock(&userspace_mutex); - cpu_is_managed[cpu] = 1; + cpu_is_managed[cpu] = 1; cpu_min_freq[cpu] = policy->min; cpu_max_freq[cpu] = policy->max; cpu_cur_freq[cpu] = policy->cur; diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index ba460bdea60f..a4818ce88919 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -59,9 +59,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, if (!cpu_online(policy->cpu)) return -EINVAL; - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { unsigned int freq = table[i].frequency; @@ -76,9 +75,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, if (!count) policy->max = next_larger; - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); dprintk("verification lead to (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu); @@ -199,7 +197,7 @@ EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs); * if you use these, you must assure that the frequency table is valid * all the time between get_attr and put_attr! */ -void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, +void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, unsigned int cpu) { dprintk("setting show_table for cpu %u to %p\n", cpu, table); -- cgit v1.2.3-59-g8ed1b From 6a92a4e0d201aea6d7c83f100d77310676b2e049 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 28 Feb 2006 00:54:25 -0500 Subject: [AGPGART] Lots of CodingStyle/whitespace cleanups. Eliminate trailing whitespace. s/if(/if (/ s/for(/for (/ Signed-off-by: Dave Jones --- drivers/char/agp/Kconfig | 2 +- drivers/char/agp/agp.h | 11 +++++----- drivers/char/agp/ali-agp.c | 2 +- drivers/char/agp/alpha-agp.c | 14 +++++++------ drivers/char/agp/amd64-agp.c | 2 +- drivers/char/agp/ati-agp.c | 6 +++--- drivers/char/agp/backend.c | 2 +- drivers/char/agp/efficeon-agp.c | 16 +++++++-------- drivers/char/agp/frontend.c | 2 +- drivers/char/agp/generic.c | 2 +- drivers/char/agp/hp-agp.c | 6 +++--- drivers/char/agp/i460-agp.c | 16 +++++++-------- drivers/char/agp/intel-agp.c | 45 +++++++++++++++++------------------------ drivers/char/agp/isoch.c | 20 +++++++++--------- drivers/char/agp/nvidia-agp.c | 20 +++++++++--------- drivers/char/agp/sgi-agp.c | 2 +- drivers/char/agp/sis-agp.c | 8 ++++---- drivers/char/agp/sworks-agp.c | 15 +++++++------- drivers/char/agp/uninorth-agp.c | 12 +++++------ 19 files changed, 98 insertions(+), 105 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index a4d425d2dce2..80d86a9d2e63 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -98,7 +98,7 @@ config AGP_SWORKS tristate "Serverworks LE/HE chipset support" depends on AGP && X86_32 help - Say Y here to support the Serverworks AGP card. See + Say Y here to support the Serverworks AGP card. See for product descriptions and images. config AGP_VIA diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index b4af87c6f9c8..3c623b67ea1c 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -19,9 +19,9 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ @@ -53,7 +53,7 @@ enum aper_size_type { struct gatt_mask { unsigned long mask; u32 type; - /* totally device specific, for integrated chipsets that + /* totally device specific, for integrated chipsets that * might have different types of memory masks. For other * devices this will probably be ignored */ }; @@ -104,8 +104,7 @@ struct agp_bridge_driver { void (*agp_enable)(struct agp_bridge_data *, u32); void (*cleanup)(void); void (*tlb_flush)(struct agp_memory *); - unsigned long (*mask_memory)(struct agp_bridge_data *, - unsigned long, int); + unsigned long (*mask_memory)(struct agp_bridge_data *, unsigned long, int); void (*cache_flush)(void); int (*create_gatt_table)(struct agp_bridge_data *); int (*free_gatt_table)(struct agp_bridge_data *); diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index b02fc2267159..5a31ec7c62fc 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -147,7 +147,7 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge) if (!addr) return NULL; - + pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c index a072d32005a4..2b5838e64751 100644 --- a/drivers/char/agp/alpha-agp.c +++ b/drivers/char/agp/alpha-agp.c @@ -23,8 +23,9 @@ static struct page *alpha_core_agp_vm_nopage(struct vm_area_struct *vma, dma_addr = address - vma->vm_start + agp->aperture.bus_base; pa = agp->ops->translate(agp, dma_addr); - if (pa == (unsigned long)-EINVAL) return NULL; /* no translation */ - + if (pa == (unsigned long)-EINVAL) + return NULL; /* no translation */ + /* * Get the page, inc the use count, and return it */ @@ -89,7 +90,7 @@ static void alpha_core_agp_enable(struct agp_bridge_data *bridge, u32 mode) agp_device_command(agp->mode.lw, 0); } -static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start, +static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start, int type) { alpha_agp_info *agp = agp_bridge->dev_private_data; @@ -98,7 +99,8 @@ static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start, temp = agp_bridge->current_size; num_entries = A_SIZE_FIX(temp)->num_entries; - if ((pg_start + mem->page_count) > num_entries) return -EINVAL; + if ((pg_start + mem->page_count) > num_entries) + return -EINVAL; status = agp->ops->bind(agp, pg_start, mem); mb(); @@ -107,7 +109,7 @@ static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start, return status; } -static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start, +static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { alpha_agp_info *agp = agp_bridge->dev_private_data; @@ -125,7 +127,7 @@ struct agp_bridge_driver alpha_core_agp_driver = { .size_type = FIXED_APER_SIZE, .cant_use_aperture = 1, .masks = NULL, - + .fetch_size = alpha_core_agp_fetch_size, .configure = alpha_core_agp_configure, .agp_enable = alpha_core_agp_enable, diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 1251b2515bbe..cccf05fdc6cb 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -216,7 +216,7 @@ static struct aper_size_info_32 amd_8151_sizes[7] = {256, 65536, 6, 0x00000700 }, /* 1 1 1 0 0 0 */ {128, 32768, 5, 0x00000720 }, /* 1 1 1 1 0 0 */ {64, 16384, 4, 0x00000730 }, /* 1 1 1 1 1 0 */ - {32, 8192, 3, 0x00000738 } /* 1 1 1 1 1 1 */ + {32, 8192, 3, 0x00000738 } /* 1 1 1 1 1 1 */ }; static int amd_8151_configure(void) diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 5b74c36c116c..4a26a2a01c2f 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -74,7 +74,7 @@ static int ati_create_page_map(ati_page_map *page_map) /*CACHE_FLUSH();*/ global_cache_flush(); - for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { + for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { writel(agp_bridge->scratch_page, page_map->remapped+i); readl(page_map->remapped+i); /* PCI Posting. */ } @@ -99,7 +99,7 @@ static void ati_free_gatt_pages(void) ati_page_map *entry; tables = ati_generic_private.gatt_pages; - for(i = 0; i < ati_generic_private.num_tables; i++) { + for (i = 0; i < ati_generic_private.num_tables; i++) { entry = tables[i]; if (entry != NULL) { if (entry->real != NULL) @@ -387,7 +387,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge) agp_bridge->gart_bus_addr = addr; /* Calculate the agp offset */ - for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { + for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1, page_dir.remapped+GET_PAGE_DIR_OFF(addr)); readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 80ee17a8fc23..509adc403250 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -228,7 +228,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) struct agp_bridge_data *agp_alloc_bridge(void) { struct agp_bridge_data *bridge; - + bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); if (!bridge) return NULL; diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index e7aea77a60f9..fed0a87448d8 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c @@ -1,6 +1,6 @@ /* * Transmeta's Efficeon AGPGART driver. - * + * * Based upon a diff by Linus around November '02. * * Ported to the 2.6 kernel by Carlos Puchol @@ -9,7 +9,7 @@ /* * NOTE-cpg-040217: - * + * * - when compiled as a module, after loading the module, * it will refuse to unload, indicating it is in use, * when it is not. @@ -45,7 +45,7 @@ * 8: Present * 7:6: reserved, write as zero * 5:0: GATT directory index: which 1st-level entry - * + * * The Efficeon AGP spec requires pages to be WB-cacheable * but to be explicitly CLFLUSH'd after any changes. */ @@ -125,7 +125,7 @@ static int efficeon_configure(void) struct aper_size_info_lvl2 *current_size; printk(KERN_DEBUG PFX "efficeon_configure()\n"); - + current_size = A_SIZE_LVL2(agp_bridge->current_size); /* aperture size */ @@ -190,7 +190,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge) const int present = EFFICEON_PRESENT; const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3; int num_entries, l1_pages; - + num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; printk(KERN_DEBUG PFX "efficeon_create_gatt_table(%d)\n", num_entries); @@ -257,12 +257,12 @@ static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int t if (!page) continue; - + page += (index & 0x3ff); *page = insert; /* clflush is slow, so don't clflush until we have to */ - if ( last_page && + if ( last_page && ((unsigned long)page^(unsigned long)last_page) & clflush_mask ) asm volatile("clflush %0" : : "m" (*last_page)); @@ -373,7 +373,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev, */ r = &pdev->resource[0]; if (!r->start && r->end) { - if(pci_assign_resource(pdev, 0)) { + if (pci_assign_resource(pdev, 0)) { printk(KERN_ERR PFX "could not assign resource 0\n"); return -ENODEV; } diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index 97eeb2345b18..ffcf15c30e90 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -781,7 +781,7 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv) if (agp_fe.current_controller != NULL) return -EBUSY; - if(!agp_bridge) + if (!agp_bridge) return -ENODEV; if (atomic_read(&agp_bridge->agp_in_use)) diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 5567ce8d72b0..4e1891e2c035 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -299,7 +299,7 @@ EXPORT_SYMBOL_GPL(agp_num_entries); /** * agp_copy_info - copy bridge state information * - * @info: agp_kern_info pointer. The caller should insure that this pointer is valid. + * @info: agp_kern_info pointer. The caller should insure that this pointer is valid. * * This function copies information about the agp bridge device and the state of * the agp backend into an agp_kern_info pointer. diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index de5d6d212674..8c4c6ef748ec 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -85,8 +85,8 @@ static int __init hp_zx1_ioc_shared(void) /* * IOC already configured by sba_iommu module; just use * its setup. We assume: - * - IOVA space is 1Gb in size - * - first 512Mb is IOMMU, second 512Mb is GART + * - IOVA space is 1Gb in size + * - first 512Mb is IOMMU, second 512Mb is GART */ hp->io_tlb_ps = readq(hp->ioc_regs+HP_ZX1_TCNFG); switch (hp->io_tlb_ps) { @@ -115,7 +115,7 @@ static int __init hp_zx1_ioc_shared(void) if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { /* Normal case when no AGP device in system */ - hp->gatt = NULL; + hp->gatt = NULL; hp->gatt_entries = 0; printk(KERN_ERR PFX "No reserved IO PDIR entry found; " "GART disabled\n"); diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 8ee19a4a6bce..91769443d8fe 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -400,10 +400,10 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem, num_entries = A_SIZE_8(temp)->num_entries; /* Figure out what pg_start means in terms of our large GART pages */ - start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE]; - end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE]; - start_offset = pg_start % I460_KPAGES_PER_IOPAGE; - end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE; + start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE]; + end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE]; + start_offset = pg_start % I460_KPAGES_PER_IOPAGE; + end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE; if (end > i460.lp_desc + num_entries) { printk(KERN_ERR PFX "Looks like we're out of AGP memory\n"); @@ -458,10 +458,10 @@ static int i460_remove_memory_large_io_page (struct agp_memory *mem, num_entries = A_SIZE_8(temp)->num_entries; /* Figure out what pg_start means in terms of our large GART pages */ - start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE]; - end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE]; - start_offset = pg_start % I460_KPAGES_PER_IOPAGE; - end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE; + start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE]; + end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE]; + start_offset = pg_start % I460_KPAGES_PER_IOPAGE; + end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE; for (i = 0, lp = start; lp <= end; ++lp) { for (idx = ((lp == start) ? start_offset : 0); diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 631531fd97a5..bddcae54b16d 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -201,9 +201,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, temp = agp_bridge->current_size; num_entries = A_SIZE_FIX(temp)->num_entries; - if ((pg_start + mem->page_count) > num_entries) { + if ((pg_start + mem->page_count) > num_entries) return -EINVAL; - } + for (j = pg_start; j < (pg_start + mem->page_count); j++) { if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) return -EBUSY; @@ -221,7 +221,7 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, agp_bridge->driver->tlb_flush(mem); return 0; } - if((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY)) + if ((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY)) goto insert; return -EINVAL; } @@ -328,7 +328,7 @@ static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) static void intel_i810_free_by_type(struct agp_memory *curr) { agp_free_key(curr->key); - if(curr->type == AGP_PHYS_MEMORY) { + if (curr->type == AGP_PHYS_MEMORY) { if (curr->page_count == 4) i8xx_destroy_pages(gart_to_virt(curr->memory[0])); else { @@ -1603,11 +1603,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, name = "i820"; break; case PCI_DEVICE_ID_INTEL_82830_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC)) { + if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC)) bridge->driver = &intel_830_driver; - } else { + else bridge->driver = &intel_830mp_driver; - } name = "830M"; break; case PCI_DEVICE_ID_INTEL_82840_HB: @@ -1619,11 +1618,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, name = "i845"; break; case PCI_DEVICE_ID_INTEL_82845G_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG)) { + if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG)) bridge->driver = &intel_830_driver; - } else { + else bridge->driver = &intel_845_driver; - } name = "845G"; break; case PCI_DEVICE_ID_INTEL_82850_HB: @@ -1648,11 +1646,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, name = "i860"; break; case PCI_DEVICE_ID_INTEL_82865_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) { + if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) bridge->driver = &intel_830_driver; - } else { + else bridge->driver = &intel_845_driver; - } name = "865"; break; case PCI_DEVICE_ID_INTEL_82875_HB: @@ -1660,35 +1657,31 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, name = "i875"; break; case PCI_DEVICE_ID_INTEL_82915G_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG)) { + if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG)) bridge->driver = &intel_915_driver; - } else { + else bridge->driver = &intel_845_driver; - } name = "915G"; break; case PCI_DEVICE_ID_INTEL_82915GM_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG)) { + if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG)) bridge->driver = &intel_915_driver; - } else { + else bridge->driver = &intel_845_driver; - } name = "915GM"; break; case PCI_DEVICE_ID_INTEL_82945G_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) { + if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) bridge->driver = &intel_915_driver; - } else { + else bridge->driver = &intel_845_driver; - } name = "945G"; break; case PCI_DEVICE_ID_INTEL_82945GM_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG)) { + if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG)) bridge->driver = &intel_915_driver; - } else { + else bridge->driver = &intel_845_driver; - } name = "945GM"; break; case PCI_DEVICE_ID_INTEL_7505_0: @@ -1724,7 +1717,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, */ r = &pdev->resource[0]; if (!r->start && r->end) { - if(pci_assign_resource(pdev, 0)) { + if (pci_assign_resource(pdev, 0)) { printk(KERN_ERR PFX "could not assign resource 0\n"); agp_put_bridge(bridge); return -ENODEV; diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c index 7c14a096b85e..3f9ccde62377 100644 --- a/drivers/char/agp/isoch.c +++ b/drivers/char/agp/isoch.c @@ -26,7 +26,7 @@ static void agp_3_5_dev_list_insert(struct list_head *head, struct list_head *ne list_for_each(pos, head) { cur = list_entry(pos, struct agp_3_5_dev, list); - if(cur->maxbw > n->maxbw) + if (cur->maxbw > n->maxbw) break; } list_add_tail(new, pos); @@ -54,9 +54,9 @@ static void agp_3_5_dev_list_sort(struct agp_3_5_dev *list, unsigned int ndevs) } } -/* - * Initialize all isochronous transfer parameters for an AGP 3.0 - * node (i.e. a host bridge in combination with the adapters +/* + * Initialize all isochronous transfer parameters for an AGP 3.0 + * node (i.e. a host bridge in combination with the adapters * lying behind it...) */ @@ -200,7 +200,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, * this to the hungriest device (as per the spec) */ rem = target.n - tot_n; - /* + /* * Calculate the minimum isochronous RQ depth needed by each master. * Along the way, distribute the extra ISOCH_N capability calculated * above. @@ -214,7 +214,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, * many writes on the AGP bus). */ master[cdev].rq = master[cdev].n; - if(master[cdev].y > 0x1) + if (master[cdev].y > 0x1) master[cdev].rq *= (1 << (master[cdev].y - 1)); tot_rq += master[cdev].rq; @@ -334,9 +334,9 @@ int agp_3_5_enable(struct agp_bridge_data *bridge) arqsz = (tstatus >> 13) & 0x7; - /* + /* * Allocate a head for our AGP 3.5 device list - * (multiple AGP v3 devices are allowed behind a single bridge). + * (multiple AGP v3 devices are allowed behind a single bridge). */ if ((dev_list = kmalloc(sizeof(*dev_list), GFP_KERNEL)) == NULL) { ret = -ENOMEM; @@ -366,7 +366,7 @@ int agp_3_5_enable(struct agp_bridge_data *bridge) case 0x0300: /* Display controller */ case 0x0400: /* Multimedia controller */ - if((cur = kmalloc(sizeof(*cur), GFP_KERNEL)) == NULL) { + if ((cur = kmalloc(sizeof(*cur), GFP_KERNEL)) == NULL) { ret = -ENOMEM; goto free_and_exit; } @@ -391,7 +391,7 @@ int agp_3_5_enable(struct agp_bridge_data *bridge) list_for_each(pos, head) { cur = list_entry(pos, struct agp_3_5_dev, list); dev = cur->dev; - + pci_read_config_word(dev, PCI_STATUS, &mpstat); if ((mpstat & PCI_STATUS_CAP_LIST) == 0) continue; diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 80dafa3030bd..70b8ed9cd172 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c @@ -72,7 +72,7 @@ static int nvidia_init_iorr(u32 base, u32 size) /* Find the iorr that is already used for the base */ /* If not found, determine the uppermost available iorr */ free_iorr_addr = AMD_K7_NUM_IORR; - for(iorr_addr = 0; iorr_addr < AMD_K7_NUM_IORR; iorr_addr++) { + for (iorr_addr = 0; iorr_addr < AMD_K7_NUM_IORR; iorr_addr++) { rdmsr(IORR_BASE0 + 2 * iorr_addr, base_lo, base_hi); rdmsr(IORR_MASK0 + 2 * iorr_addr, mask_lo, mask_hi); @@ -82,7 +82,7 @@ static int nvidia_init_iorr(u32 base, u32 size) if ((mask_lo & 0x00000800) == 0) free_iorr_addr = iorr_addr; } - + if (iorr_addr >= AMD_K7_NUM_IORR) { iorr_addr = free_iorr_addr; if (iorr_addr >= AMD_K7_NUM_IORR) @@ -139,7 +139,7 @@ static int nvidia_configure(void) } /* attbase */ - for(i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_ATTBASE(i), (agp_bridge->gatt_bus_addr + (i % num_dirs) * 64 * 1024) | 1); } @@ -197,15 +197,15 @@ extern int agp_memory_reserved; static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type) { int i, j; - + if ((type != 0) || (mem->type != 0)) return -EINVAL; - + if ((pg_start + mem->page_count) > (nvidia_private.num_active_entries - agp_memory_reserved/PAGE_SIZE)) return -EINVAL; - - for(j = pg_start; j < (pg_start + mem->page_count); j++) { + + for (j = pg_start; j < (pg_start + mem->page_count); j++) { if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j))) return -EBUSY; } @@ -264,9 +264,9 @@ static void nvidia_tlbflush(struct agp_memory *mem) } /* flush TLB entries */ - for(i = 0; i < 32 + 1; i++) + for (i = 0; i < 32 + 1; i++) temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32))); - for(i = 0; i < 32 + 1; i++) + for (i = 0; i < 32 + 1; i++) temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32))); } @@ -323,7 +323,7 @@ static int __devinit agp_nvidia_probe(struct pci_dev *pdev, pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2)); nvidia_private.dev_3 = pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0)); - + if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) { printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 " "chipset, but could not find the secondary devices.\n"); diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index 4df7734b51c2..cfa7922cb431 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c @@ -329,7 +329,7 @@ static int __devinit agp_sgi_init(void) static void __devexit agp_sgi_cleanup(void) { - if(sgi_tioca_agp_bridges) + if (sgi_tioca_agp_bridges) kfree(sgi_tioca_agp_bridges); sgi_tioca_agp_bridges=NULL; } diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index ebc05554045c..a00fd48a6f05 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c @@ -121,7 +121,7 @@ static struct aper_size_info_8 sis_generic_sizes[7] = static struct agp_bridge_driver sis_driver = { .owner = THIS_MODULE, - .aperture_sizes = sis_generic_sizes, + .aperture_sizes = sis_generic_sizes, .size_type = U8_APER_SIZE, .num_aperture_sizes = 7, .configure = sis_configure, @@ -243,11 +243,11 @@ static void __devinit sis_get_driver(struct agp_bridge_data *bridge) { int i; - for(i=0; sis_broken_chipsets[i]!=0; ++i) - if(bridge->dev->device==sis_broken_chipsets[i]) + for (i=0; sis_broken_chipsets[i]!=0; ++i) + if (bridge->dev->device==sis_broken_chipsets[i]) break; - if(sis_broken_chipsets[i] || agp_sis_force_delay) + if (sis_broken_chipsets[i] || agp_sis_force_delay) sis_driver.agp_enable=sis_delayed_enable; // sis chipsets that indicate less than agp3.5 diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index efef9999f1cf..4f2d7d99902f 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -64,7 +64,7 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map) } global_cache_flush(); - for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) + for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) writel(agp_bridge->scratch_page, page_map->remapped+i); return 0; @@ -84,7 +84,7 @@ static void serverworks_free_gatt_pages(void) struct serverworks_page_map *entry; tables = serverworks_private.gatt_pages; - for(i = 0; i < serverworks_private.num_tables; i++) { + for (i = 0; i < serverworks_private.num_tables; i++) { entry = tables[i]; if (entry != NULL) { if (entry->real != NULL) { @@ -103,7 +103,7 @@ static int serverworks_create_gatt_pages(int nr_tables) int retval = 0; int i; - tables = kzalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *), + tables = kzalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *), GFP_KERNEL); if (tables == NULL) return -ENOMEM; @@ -161,7 +161,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) return retval; } /* Create a fake scratch directory */ - for(i = 0; i < 1024; i++) { + for (i = 0; i < 1024; i++) { writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i); writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i); } @@ -185,9 +185,8 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) pci_read_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs,&temp); agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - /* Calculate the agp offset */ - - for(i = 0; i < value->num_entries / 1024; i++) + /* Calculate the agp offset */ + for (i = 0; i < value->num_entries / 1024; i++) writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i); return 0; @@ -196,7 +195,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) static int serverworks_free_gatt_table(struct agp_bridge_data *bridge) { struct serverworks_page_map page_dir; - + page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table; diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 50947e38501a..9846defbddb4 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -95,12 +95,12 @@ static void uninorth_cleanup(void) static int uninorth_configure(void) { struct aper_size_info_32 *current_size; - + current_size = A_SIZE_32(agp_bridge->current_size); printk(KERN_INFO PFX "configuring for size idx: %d\n", current_size->size_value); - + /* aperture size and gatt addr */ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_BASE, @@ -127,7 +127,7 @@ static int uninorth_configure(void) UNI_N_CFG_GART_DUMMY_PAGE, agp_bridge->scratch_page_real >> 12); } - + return 0; } @@ -162,7 +162,7 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, } (void)in_le32((volatile u32*)&agp_bridge->gatt_table[pg_start]); mb(); - flush_dcache_range((unsigned long)&agp_bridge->gatt_table[pg_start], + flush_dcache_range((unsigned long)&agp_bridge->gatt_table[pg_start], (unsigned long)&agp_bridge->gatt_table[pg_start + mem->page_count]); uninorth_tlbflush(mem); @@ -235,7 +235,7 @@ static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode) command = agp_collect_device_status(bridge, mode, status); command |= PCI_AGP_COMMAND_AGP; - + if (uninorth_rev == 0x21) { /* * Darwin disable AGP 4x on this revision, thus we @@ -456,7 +456,7 @@ static struct aper_size_info_32 uninorth_sizes[7] = {256, 65536, 6, 64}, {128, 32768, 5, 32}, {64, 16384, 4, 16}, -#endif +#endif {32, 8192, 3, 8}, {16, 4096, 2, 4}, {8, 2048, 1, 2}, -- cgit v1.2.3-59-g8ed1b From 3bbae37ab42d9d7d6c707e275ea944104a1f38ca Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:11 -0500 Subject: [SCSI] lpfc 8.1.2: Remove unused prototypes from lpfc_crtn.h Remove unused prototypes from lpfc_crtn.h Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_crtn.h | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index f1e708946e66..eda353b918ab 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -42,9 +42,6 @@ void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); -int lpfc_nlp_plogi(struct lpfc_hba *, struct lpfc_nodelist *); -int lpfc_nlp_adisc(struct lpfc_hba *, struct lpfc_nodelist *); -int lpfc_nlp_unmapped(struct lpfc_hba *, struct lpfc_nodelist *); int lpfc_nlp_list(struct lpfc_hba *, struct lpfc_nodelist *, int); void lpfc_set_disctmo(struct lpfc_hba *); int lpfc_can_disctmo(struct lpfc_hba *); @@ -54,12 +51,10 @@ int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *, int lpfc_nlp_remove(struct lpfc_hba *, struct lpfc_nodelist *); void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t); struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t); -struct lpfc_nodelist *lpfc_setup_rscn_node(struct lpfc_hba *, uint32_t); void lpfc_disc_list_loopmap(struct lpfc_hba *); void lpfc_disc_start(struct lpfc_hba *); void lpfc_disc_flush_list(struct lpfc_hba *); void lpfc_disc_timeout(unsigned long); -void lpfc_scan_timeout(unsigned long); struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi); @@ -68,12 +63,6 @@ int lpfc_do_work(void *); int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *, uint32_t); -uint32_t lpfc_cmpl_prli_reglogin_issue(struct lpfc_hba *, - struct lpfc_nodelist *, void *, - uint32_t); -uint32_t lpfc_cmpl_plogi_prli_issue(struct lpfc_hba *, struct lpfc_nodelist *, - void *, uint32_t); - int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *, struct serv_parm *, uint32_t); int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp, @@ -120,15 +109,11 @@ int lpfc_hba_down_prep(struct lpfc_hba *); void lpfc_hba_init(struct lpfc_hba *, uint32_t *); int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int); void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int); -uint8_t *lpfc_get_lpfchba_info(struct lpfc_hba *, uint8_t *); -int lpfc_fcp_abort(struct lpfc_hba *, int, int, int); int lpfc_online(struct lpfc_hba *); int lpfc_offline(struct lpfc_hba *); - int lpfc_sli_setup(struct lpfc_hba *); int lpfc_sli_queue_setup(struct lpfc_hba *); -void lpfc_slim_access(struct lpfc_hba *); void lpfc_handle_eratt(struct lpfc_hba *); void lpfc_handle_latt(struct lpfc_hba *); @@ -174,9 +159,6 @@ int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, void lpfc_mbox_timeout(unsigned long); void lpfc_mbox_timeout_handler(struct lpfc_hba *); -void lpfc_map_fcp_cmnd_to_bpl(struct lpfc_hba *, struct lpfc_scsi_buf *); -void lpfc_free_scsi_cmd(struct lpfc_scsi_buf *); -uint32_t lpfc_os_timeout_transform(struct lpfc_hba *, uint32_t); struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did); -- cgit v1.2.3-59-g8ed1b From 0c71fd9e433c032c08e85a955471bc03138afa80 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:12 -0500 Subject: [SCSI] lpfc 8.1.2: Remove unreferenced cfg_fcp_bind_method from struct lpfc_hba Remove unreferenced cfg_fcp_bind_method from struct lpfc_hba Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 38ffa8d6e629..7a0da125aa7d 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -290,7 +290,6 @@ struct lpfc_hba { uint32_t cfg_cr_delay; uint32_t cfg_cr_count; uint32_t cfg_fdmi_on; - uint32_t cfg_fcp_bind_method; uint32_t cfg_discovery_threads; uint32_t cfg_max_luns; uint32_t cfg_poll; -- cgit v1.2.3-59-g8ed1b From 0228aadd0fb1d8ca90efbe74291f3b5b753c2da2 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:13 -0500 Subject: [SCSI] lpfc 8.1.2: Remove unused SLI_IOCB_HIGH_PRIORITY Remove unused SLI_IOCB_HIGH_PRIORITY Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_sli.c | 10 ---------- drivers/scsi/lpfc/lpfc_sli.h | 1 - 2 files changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 7b785ade8b07..ab710243687a 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2237,16 +2237,6 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, !(phba->sli.sli_flag & LPFC_PROCESS_LA))) goto iocb_busy; - /* - * Check to see if this is a high priority command. - * If so bypass tx queue processing. - */ - if (unlikely((flag & SLI_IOCB_HIGH_PRIORITY) && - (iocb = lpfc_sli_next_iocb_slot(phba, pring)))) { - lpfc_sli_submit_iocb(phba, pring, iocb, piocb); - piocb = NULL; - } - while ((iocb = lpfc_sli_next_iocb_slot(phba, pring)) && (nextiocb = lpfc_sli_next_iocb(phba, pring, &piocb))) lpfc_sli_submit_iocb(phba, pring, iocb, nextiocb); diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index b7a9f970f565..6d357d9e48f7 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -61,7 +61,6 @@ struct lpfc_iocbq { }; #define SLI_IOCB_RET_IOCB 1 /* Return IOCB if cmd ring full */ -#define SLI_IOCB_HIGH_PRIORITY 2 /* High priority command */ #define IOCB_SUCCESS 0 #define IOCB_BUSY 1 -- cgit v1.2.3-59-g8ed1b From 7bb3b137abf2b7073e683c14cfe062d811d35247 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:15 -0500 Subject: [SCSI] lpfc 8.1.2: Handling of ELS commands RRQ, RPS, RPL and LIRR correctly Handling of ELS commands RRQ, RPS, RPL and LIRR correctly Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 4 +- drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_els.c | 274 ++++++++++++++++++++++++++++++++++++++---- drivers/scsi/lpfc/lpfc_hw.h | 47 ++++++-- drivers/scsi/lpfc/lpfc_mbox.c | 17 +++ 5 files changed, 309 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 7a0da125aa7d..14151de23fd7 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -121,7 +121,9 @@ struct lpfc_stats { uint32_t elsRcvLOGO; uint32_t elsRcvPRLO; uint32_t elsRcvPRLI; - uint32_t elsRcvRRQ; + uint32_t elsRcvLIRR; + uint32_t elsRcvRPS; + uint32_t elsRcvRPL; uint32_t elsXmitFLOGI; uint32_t elsXmitPLOGI; uint32_t elsXmitPRLI; diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index eda353b918ab..0ae49811b916 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -26,6 +26,7 @@ void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *); +void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_set_slim(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *, uint32_t); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 20f1a0713db2..9c9e7661de59 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -2654,41 +2654,243 @@ lpfc_els_rcv_rnid(struct lpfc_hba * phba, } static int -lpfc_els_rcv_rrq(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, +lpfc_els_rcv_lirr(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, + struct lpfc_nodelist * ndlp) +{ + struct ls_rjt stat; + + /* For now, unconditionally reject this command */ + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; + stat.un.b.vendorUnique = 0; + lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); + return 0; +} + +void +lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) +{ + struct lpfc_sli *psli; + struct lpfc_sli_ring *pring; + MAILBOX_t *mb; + IOCB_t *icmd; + RPS_RSP *rps_rsp; + uint8_t *pcmd; + struct lpfc_iocbq *elsiocb; + struct lpfc_nodelist *ndlp; + uint16_t xri, status; + uint32_t cmdsize; + + psli = &phba->sli; + pring = &psli->ring[LPFC_ELS_RING]; + mb = &pmb->mb; + + ndlp = (struct lpfc_nodelist *) pmb->context2; + xri = (uint16_t) ((unsigned long)(pmb->context1)); + pmb->context1 = 0; + pmb->context2 = 0; + + if (mb->mbxStatus) { + mempool_free( pmb, phba->mbox_mem_pool); + return; + } + + cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); + mempool_free( pmb, phba->mbox_mem_pool); + if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, 3, + ndlp, ELS_CMD_ACC)) == 0) { + return; + } + + icmd = &elsiocb->iocb; + icmd->ulpContext = xri; + + pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); + *((uint32_t *) (pcmd)) = ELS_CMD_ACC; + pcmd += sizeof (uint32_t); /* Skip past command */ + rps_rsp = (RPS_RSP *)pcmd; + + if (phba->fc_topology != TOPOLOGY_LOOP) + status = 0x10; + else + status = 0x8; + if (phba->fc_flag & FC_FABRIC) + status |= 0x4; + + rps_rsp->rsvd1 = 0; + rps_rsp->portStatus = be16_to_cpu(status); + rps_rsp->linkFailureCnt = be32_to_cpu(mb->un.varRdLnk.linkFailureCnt); + rps_rsp->lossSyncCnt = be32_to_cpu(mb->un.varRdLnk.lossSyncCnt); + rps_rsp->lossSignalCnt = be32_to_cpu(mb->un.varRdLnk.lossSignalCnt); + rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt); + rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord); + rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt); + + /* Xmit ELS RPS ACC response tag */ + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, + "%d:0128 Xmit ELS RPS ACC response tag x%x " + "Data: x%x x%x x%x x%x x%x\n", + phba->brd_no, + elsiocb->iocb.ulpIoTag, + elsiocb->iocb.ulpContext, ndlp->nlp_DID, + ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); + + elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; + phba->fc_stat.elsXmitACC++; + if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { + lpfc_els_free_iocb(phba, elsiocb); + } + return; +} + +static int +lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp) { - struct lpfc_dmabuf *pcmd; uint32_t *lp; + uint8_t flag; + LPFC_MBOXQ_t *mbox; + struct lpfc_dmabuf *pcmd; + RPS *rps; + struct ls_rjt stat; + + if((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && + (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; + stat.un.b.vendorUnique = 0; + lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); + } + + pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; + lp = (uint32_t *) pcmd->virt; + flag = (be32_to_cpu(*lp++) & 0xf); + rps = (RPS *) lp; + + if ((flag == 0) || + ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) || + ((flag == 2) && (memcmp(&rps->un.portName, &phba->fc_portname, + sizeof (struct lpfc_name)) == 0))) { + if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC))) { + lpfc_read_lnk_stat(phba, mbox); + mbox->context1 = + (void *)((unsigned long)cmdiocb->iocb.ulpContext); + mbox->context2 = ndlp; + mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; + if (lpfc_sli_issue_mbox (phba, mbox, + (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) { + /* Mbox completion will send ELS Response */ + return 0; + } + mempool_free(mbox, phba->mbox_mem_pool); + } + } + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; + stat.un.b.vendorUnique = 0; + lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); + return 0; +} + +int +lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize, + struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp) +{ IOCB_t *icmd; + IOCB_t *oldcmd; + RPL_RSP rpl_rsp; + struct lpfc_iocbq *elsiocb; struct lpfc_sli_ring *pring; struct lpfc_sli *psli; - RRQ *rrq; - uint32_t cmd, did; + uint8_t *pcmd; psli = &phba->sli; - pring = &psli->ring[LPFC_FCP_RING]; - icmd = &cmdiocb->iocb; - did = icmd->un.elsreq64.remoteID; + pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ + + if ((elsiocb = + lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, + ndlp, ELS_CMD_ACC)) == 0) { + return 1; + } + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri */ + + pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); + *((uint32_t *) (pcmd)) = ELS_CMD_ACC; + pcmd += sizeof (uint16_t); + *((uint16_t *)(pcmd)) = be16_to_cpu(cmdsize); + pcmd += sizeof(uint16_t); + + /* Setup the RPL ACC payload */ + rpl_rsp.listLen = be32_to_cpu(1); + rpl_rsp.index = 0; + rpl_rsp.port_num_blk.portNum = 0; + rpl_rsp.port_num_blk.portID = be32_to_cpu(phba->fc_myDID); + memcpy(&rpl_rsp.port_num_blk.portName, &phba->fc_portname, + sizeof(struct lpfc_name)); + + memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t)); + + + /* Xmit ELS RPL ACC response tag */ + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, + "%d:0128 Xmit ELS RPL ACC response tag x%x " + "Data: x%x x%x x%x x%x x%x\n", + phba->brd_no, + elsiocb->iocb.ulpIoTag, + elsiocb->iocb.ulpContext, ndlp->nlp_DID, + ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); + + elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; + + phba->fc_stat.elsXmitACC++; + if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { + lpfc_els_free_iocb(phba, elsiocb); + return 1; + } + return 0; +} + +static int +lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, + struct lpfc_nodelist * ndlp) +{ + struct lpfc_dmabuf *pcmd; + uint32_t *lp; + uint32_t maxsize; + uint16_t cmdsize; + RPL *rpl; + struct ls_rjt stat; + + if((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && + (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { + stat.un.b.lsRjtRsvd0 = 0; + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; + stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; + stat.un.b.vendorUnique = 0; + lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); + } + pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; lp = (uint32_t *) pcmd->virt; + rpl = (RPL *) (lp + 1); - cmd = *lp++; - rrq = (RRQ *) lp; + maxsize = be32_to_cpu(rpl->maxsize); - /* RRQ received */ - /* Get oxid / rxid from payload and abort it */ - spin_lock_irq(phba->host->host_lock); - if ((rrq->SID == be32_to_cpu(phba->fc_myDID))) { - lpfc_sli_abort_iocb(phba, pring, 0, 0, rrq->Oxid, - LPFC_CTX_CTX); - } else { - lpfc_sli_abort_iocb(phba, pring, 0, 0, rrq->Rxid, - LPFC_CTX_CTX); + /* We support only one port */ + if ((rpl->index == 0) && + ((maxsize == 0) || + ((maxsize * sizeof(uint32_t)) >= sizeof(RPL_RSP)))) { + cmdsize = sizeof(uint32_t) + sizeof(RPL_RSP); } - - spin_unlock_irq(phba->host->host_lock); - /* ACCEPT the rrq request */ - lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); + else { + cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t); + } + lpfc_els_rsp_rpl_acc(phba, cmdsize, cmdiocb, ndlp); return 0; } @@ -3201,10 +3403,6 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, phba->fc_stat.elsRcvFAN++; lpfc_els_rcv_fan(phba, elsiocb, ndlp); break; - case ELS_CMD_RRQ: - phba->fc_stat.elsRcvRRQ++; - lpfc_els_rcv_rrq(phba, elsiocb, ndlp); - break; case ELS_CMD_PRLI: phba->fc_stat.elsRcvPRLI++; if (phba->hba_state < LPFC_DISC_AUTH) { @@ -3213,9 +3411,33 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, } lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI); break; + case ELS_CMD_LIRR: + phba->fc_stat.elsRcvLIRR++; + lpfc_els_rcv_lirr(phba, elsiocb, ndlp); + if (newnode) { + mempool_free( ndlp, phba->nlp_mem_pool); + } + break; + case ELS_CMD_RPS: + phba->fc_stat.elsRcvRPS++; + lpfc_els_rcv_rps(phba, elsiocb, ndlp); + if (newnode) { + mempool_free( ndlp, phba->nlp_mem_pool); + } + break; + case ELS_CMD_RPL: + phba->fc_stat.elsRcvRPL++; + lpfc_els_rcv_rpl(phba, elsiocb, ndlp); + if (newnode) { + mempool_free( ndlp, phba->nlp_mem_pool); + } + break; case ELS_CMD_RNID: phba->fc_stat.elsRcvRNID++; lpfc_els_rcv_rnid(phba, elsiocb, ndlp); + if (newnode) { + mempool_free( ndlp, phba->nlp_mem_pool); + } break; default: /* Unsupported ELS command, reject */ diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 1ea565e0561f..e613dd07d2ad 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -454,10 +454,13 @@ struct serv_parm { /* Structure is in Big Endian format */ #define ELS_CMD_ADISC 0x52000000 #define ELS_CMD_FARP 0x54000000 #define ELS_CMD_FARPR 0x55000000 +#define ELS_CMD_RPS 0x56000000 +#define ELS_CMD_RPL 0x57000000 #define ELS_CMD_FAN 0x60000000 #define ELS_CMD_RSCN 0x61040000 #define ELS_CMD_SCR 0x62000000 #define ELS_CMD_RNID 0x78000000 +#define ELS_CMD_LIRR 0x7A000000 #else /* __LITTLE_ENDIAN_BITFIELD */ #define ELS_CMD_MASK 0xffff #define ELS_RSP_MASK 0xff @@ -486,10 +489,13 @@ struct serv_parm { /* Structure is in Big Endian format */ #define ELS_CMD_ADISC 0x52 #define ELS_CMD_FARP 0x54 #define ELS_CMD_FARPR 0x55 +#define ELS_CMD_RPS 0x56 +#define ELS_CMD_RPL 0x57 #define ELS_CMD_FAN 0x60 #define ELS_CMD_RSCN 0x0461 #define ELS_CMD_SCR 0x62 #define ELS_CMD_RNID 0x78 +#define ELS_CMD_LIRR 0x7A #endif /* @@ -758,12 +764,40 @@ typedef struct _RNID { /* Structure is in Big Endian format */ } un; } RNID; -typedef struct _RRQ { /* Structure is in Big Endian format */ - uint32_t SID; - uint16_t Oxid; - uint16_t Rxid; - uint8_t resv[32]; /* optional association hdr */ -} RRQ; +typedef struct _RPS { /* Structure is in Big Endian format */ + union { + uint32_t portNum; + struct lpfc_name portName; + } un; +} RPS; + +typedef struct _RPS_RSP { /* Structure is in Big Endian format */ + uint16_t rsvd1; + uint16_t portStatus; + uint32_t linkFailureCnt; + uint32_t lossSyncCnt; + uint32_t lossSignalCnt; + uint32_t primSeqErrCnt; + uint32_t invalidXmitWord; + uint32_t crcCnt; +} RPS_RSP; + +typedef struct _RPL { /* Structure is in Big Endian format */ + uint32_t maxsize; + uint32_t index; +} RPL; + +typedef struct _PORT_NUM_BLK { + uint32_t portNum; + uint32_t portID; + struct lpfc_name portName; +} PORT_NUM_BLK; + +typedef struct _RPL_RSP { /* Structure is in Big Endian format */ + uint32_t listLen; + uint32_t index; + PORT_NUM_BLK port_num_blk; +} RPL_RSP; /* This is used for RSCN command */ typedef struct _D_ID { /* Structure is in Big Endian format */ @@ -804,7 +838,6 @@ typedef struct _ELS_PKT { /* Structure is in Big Endian format */ FARP farp; /* Payload for FARP/ACC */ FAN fan; /* Payload for FAN */ SCR scr; /* Payload for SCR/ACC */ - RRQ rrq; /* Payload for RRQ */ RNID rnid; /* Payload for RNID */ uint8_t pad[128 - 4]; /* Pad out to payload of 128 bytes */ } un; diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index e3bc8d3f7302..6c4b21a32c7f 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -336,6 +336,23 @@ lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) return; } +/*************************************************/ +/* lpfc_read_lnk_stat Issue a READ LINK STATUS */ +/* mailbox command */ +/*************************************************/ +void +lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) +{ + MAILBOX_t *mb; + + mb = &pmb->mb; + memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); + + mb->mbxCommand = MBX_READ_LNK_STAT; + mb->mbxOwner = OWN_HOST; + return; +} + /********************************************/ /* lpfc_reg_login Issue a REG_LOGIN */ /* mailbox command */ -- cgit v1.2.3-59-g8ed1b From 6ad425356bba9664393b579d81df8135ca1510e6 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:16 -0500 Subject: [SCSI] lpfc 8.1.2: Fixed a race condition in the PLOGI retry logic. Fixed a race condition in the PLOGI retry logic. Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 28 ++++++++++++++++------------ drivers/scsi/lpfc/lpfc_nportdisc.c | 8 ++++++++ 2 files changed, 24 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 9c9e7661de59..056f9157d2c8 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1467,24 +1467,28 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) lpfc_issue_els_flogi(phba, ndlp, retry); break; case ELS_CMD_PLOGI: - ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; - lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); - lpfc_issue_els_plogi(phba, ndlp, retry); + if (!lpfc_issue_els_plogi(phba, ndlp, retry)) { + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); + } break; case ELS_CMD_ADISC: - ndlp->nlp_state = NLP_STE_ADISC_ISSUE; - lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); - lpfc_issue_els_adisc(phba, ndlp, retry); + if (!lpfc_issue_els_adisc(phba, ndlp, retry)) { + ndlp->nlp_state = NLP_STE_ADISC_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); + } break; case ELS_CMD_PRLI: - ndlp->nlp_state = NLP_STE_PRLI_ISSUE; - lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); - lpfc_issue_els_prli(phba, ndlp, retry); + if (!lpfc_issue_els_prli(phba, ndlp, retry)) { + ndlp->nlp_state = NLP_STE_PRLI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); + } break; case ELS_CMD_LOGO: - ndlp->nlp_state = NLP_STE_NPR_NODE; - lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); - lpfc_issue_els_logo(phba, ndlp, retry); + if (!lpfc_issue_els_logo(phba, ndlp, retry)) { + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); + } break; } return; diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index fbead786031f..1c04ea353ffa 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1627,6 +1627,14 @@ lpfc_device_recov_npr_node(struct lpfc_hba * phba, { spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; + if (ndlp->nlp_flag & NLP_DELAY_TMO) { + ndlp->nlp_flag &= ~NLP_DELAY_TMO; + if (!list_empty(&ndlp->els_retry_evt.evt_listp)) + list_del_init(&ndlp->els_retry_evt.evt_listp); + spin_unlock_irq(phba->host->host_lock); + del_timer_sync(&ndlp->nlp_delayfunc); + return (ndlp->nlp_state); + } spin_unlock_irq(phba->host->host_lock); return (ndlp->nlp_state); } -- cgit v1.2.3-59-g8ed1b From 7062c5281c68dfdb685ec9ba25cfc7b6a15bc0fe Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:17 -0500 Subject: [SCSI] lpfc 8.1.2: Explicitly initialize the skip_post argument to lpfc_sli_send_reset Explicitly initialize the skip_post argument to lpfc_sli_send_reset on a ERATT interrupt. Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_sli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index ab710243687a..cb4ccbba0652 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2983,7 +2983,7 @@ lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs) * to shutdown interrupt when there is a * ERROR. */ - lpfc_sli_send_reset(phba, phba->hba_state); + lpfc_sli_send_reset(phba, 1); } spin_lock(phba->host->host_lock); -- cgit v1.2.3-59-g8ed1b From 901a920f0759c6ea94255f3c2cd6ec324f7e4752 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:19 -0500 Subject: [SCSI] lpfc 8.1.2: Fixed system panic in lpfc_sli_brdreset during dynamic add of LP11K Fixed system panic in lpfc_sli_brdreset during dynamic add of LP11K Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_init.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index b7a603a45328..369487e8f450 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1462,9 +1462,23 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) phba->pci_bar2_map = pci_resource_start(phba->pcidev, 2); bar2map_len = pci_resource_len(phba->pcidev, 2); - /* Map HBA SLIM and Control Registers to a kernel virtual address. */ + /* Map HBA SLIM to a kernel virtual address. */ phba->slim_memmap_p = ioremap(phba->pci_bar0_map, bar0map_len); + if (!phba->slim_memmap_p) { + error = -ENODEV; + dev_printk(KERN_ERR, &pdev->dev, + "ioremap failed for SLIM memory.\n"); + goto out_idr_remove; + } + + /* Map HBA Control Registers to a kernel virtual address. */ phba->ctrl_regs_memmap_p = ioremap(phba->pci_bar2_map, bar2map_len); + if (!phba->ctrl_regs_memmap_p) { + error = -ENODEV; + dev_printk(KERN_ERR, &pdev->dev, + "ioremap failed for HBA control registers.\n"); + goto out_iounmap_slim; + } /* Allocate memory for SLI-2 structures */ phba->slim2p = dma_alloc_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE, @@ -1643,6 +1657,7 @@ out_free_slim: phba->slim2p_mapping); out_iounmap: iounmap(phba->ctrl_regs_memmap_p); +out_iounmap_slim: iounmap(phba->slim_memmap_p); out_idr_remove: idr_remove(&lpfc_hba_index, phba->brd_no); -- cgit v1.2.3-59-g8ed1b From 406d6041ace581b63a7898f3c1ef036c58c74989 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:20 -0500 Subject: [SCSI] lpfc 8.1.2: Fixed a double insertion of mail box object to the SLI mailbox list. Fixed a double insertion of mail box object to the SLI mailbox list. Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_sli.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index cb4ccbba0652..1f876328b44b 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2867,11 +2867,10 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq, pmboxq->context1 = NULL; /* if schedule_timeout returns 0, we timed out and were not woken up */ - if (timeleft == 0) { + if ((timeleft == 0) || signal_pending(current)) retval = MBX_TIMEOUT; - } else { + else retval = MBX_SUCCESS; - } } -- cgit v1.2.3-59-g8ed1b From b28485acb930f67c014024bc3b9c01129124e566 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:21 -0500 Subject: [SCSI] lpfc 8.1.2: Add module parameter to limit number of outstanding commands per lpfc HBA Add module parameter to limit number of outstanding commands per lpfc HBA Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_attr.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 5625a8c2a8fd..b897e522a966 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -519,6 +519,16 @@ LPFC_ATTR_HEX_RW(log_verbose, 0x0, 0x0, 0xffff, "Verbose logging bit-mask"); LPFC_ATTR_R(lun_queue_depth, 30, 1, 128, "Max number of FCP commands we can queue to a specific LUN"); +/* +# hba_queue_depth: This parameter is used to limit the number of outstanding +# commands per lpfc HBA. Value range is [32,8192]. If this parameter +# value is greater than the maximum number of exchanges supported by the HBA, +# then maximum number of exchanges supported by the HBA is used to determine +# the hba_queue_depth. +*/ +LPFC_ATTR_R(hba_queue_depth, 8192, 32, 8192, + "Max number of FCP commands we can queue to a lpfc HBA"); + /* # Some disk devices have a "select ID" or "select Target" capability. # From a protocol standpoint "select ID" usually means select the @@ -649,6 +659,7 @@ struct class_device_attribute *lpfc_host_attrs[] = { &class_device_attr_lpfc_drvr_version, &class_device_attr_lpfc_log_verbose, &class_device_attr_lpfc_lun_queue_depth, + &class_device_attr_lpfc_hba_queue_depth, &class_device_attr_lpfc_nodev_tmo, &class_device_attr_lpfc_fcp_class, &class_device_attr_lpfc_use_adisc, @@ -1411,5 +1422,9 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) default: phba->cfg_hba_queue_depth = LPFC_DFT_HBA_Q_DEPTH; } + + if (phba->cfg_hba_queue_depth > lpfc_hba_queue_depth) + lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); + return; } -- cgit v1.2.3-59-g8ed1b From c9f8735beadfba403045c4423c91bbcf594b6ef2 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:23 -0500 Subject: [SCSI] lpfc 8.1.2: Misc FC Discovery changes : Misc FC Discovery changes : - Added FC_BYPASSED_MODE statistic - Corrected some log message data - Fix up Discovery infrastructure to support FAN: Allow Fabric entities to flow thru DSM Fix up linkup/linkdown unregister login processing for Fabric entities Clean up Discovery code Utilize nodev_tmo for Fabric entities - Use of 3 * ratov for CT handling timeouts - Fix up DSM to make more appropriate decisions and clean up code. Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_ct.c | 11 +- drivers/scsi/lpfc/lpfc_els.c | 330 ++++++++++++++++--------------------- drivers/scsi/lpfc/lpfc_hbadisc.c | 220 +++++++++++++++---------- drivers/scsi/lpfc/lpfc_nportdisc.c | 283 ++++++++++++++++++------------- 5 files changed, 452 insertions(+), 393 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 14151de23fd7..d07ab0214af1 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -247,6 +247,7 @@ struct lpfc_hba { #define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */ #define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */ #define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */ +#define FC_BYPASSED_MODE 0x20000 /* NPort is in bypassed mode */ uint32_t fc_topology; /* link topology, from LINK INIT */ diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 7f427f9c4688..98b94c0eb597 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -260,8 +260,10 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp, icmd->un.genreq64.w5.hcsw.Rctl = FC_UNSOL_CTL; icmd->un.genreq64.w5.hcsw.Type = FC_COMMON_TRANSPORT_ULP; - if (!tmo) - tmo = (2 * phba->fc_ratov) + 1; + if (!tmo) { + /* FC spec states we need 3 * ratov for CT requests */ + tmo = (3 * phba->fc_ratov); + } icmd->ulpTimeout = tmo; icmd->ulpBdeCount = 1; icmd->ulpLe = 1; @@ -449,6 +451,11 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, CTrsp = (struct lpfc_sli_ct_request *) outp->virt; if (CTrsp->CommandResponse.bits.CmdRsp == be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, + "%d:0239 NameServer Rsp " + "Data: x%x\n", + phba->brd_no, + phba->fc_flag); lpfc_ns_rsp(phba, outp, (uint32_t) (irsp->un.genreq64.bdl.bdeSize)); } else if (CTrsp->CommandResponse.bits.CmdRsp == diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 056f9157d2c8..70581b9eafaf 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -92,7 +92,7 @@ lpfc_els_chk_latt(struct lpfc_hba * phba) } } - return (1); + return 1; } @@ -235,7 +235,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, ndlp->nlp_DID, icmd->ulpIoTag, cmdSize); } - return (elsiocb); + return elsiocb; } @@ -446,9 +446,10 @@ lpfc_cmpl_els_flogi(struct lpfc_hba * phba, lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d:0100 FLOGI failure Data: x%x x%x\n", + "%d:0100 FLOGI failure Data: x%x x%x x%x\n", phba->brd_no, - irsp->ulpStatus, irsp->un.ulpWord[4]); + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout); goto flogifail; } @@ -517,7 +518,7 @@ lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, ELS_CMD_FLOGI)) == 0) { - return (1); + return 1; } icmd = &elsiocb->iocb; @@ -552,9 +553,9 @@ lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, spin_unlock_irq(phba->host->host_lock); if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } - return (0); + return 0; } int @@ -611,29 +612,21 @@ lpfc_initial_flogi(struct lpfc_hba * phba) { struct lpfc_nodelist *ndlp; - /* First look for Fabric ndlp on the unmapped list */ - - if ((ndlp = - lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, - Fabric_DID)) == 0) { + /* First look for the Fabric ndlp */ + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, Fabric_DID); + if (!ndlp) { /* Cannot find existing Fabric ndlp, so allocate a new one */ - if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) - == 0) { - return (0); - } + ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); + if (!ndlp) + return 0; lpfc_nlp_init(phba, ndlp, Fabric_DID); - } - else { - phba->fc_unmap_cnt--; - list_del(&ndlp->nlp_listp); - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~NLP_LIST_MASK; - spin_unlock_irq(phba->host->host_lock); + } else { + lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ); } if (lpfc_issue_els_flogi(phba, ndlp, 0)) { mempool_free( ndlp, phba->nlp_mem_pool); } - return (1); + return 1; } static void @@ -675,22 +668,23 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, irsp = &rspiocb->iocb; ndlp = (struct lpfc_nodelist *) cmdiocb->context1; - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~NLP_PLOGI_SND; - spin_unlock_irq(phba->host->host_lock); /* Since ndlp can be freed in the disc state machine, note if this node * is being used during discovery. */ disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag &= ~(NLP_PLOGI_SND | NLP_NPR_2B_DISC); + spin_unlock_irq(phba->host->host_lock); rc = 0; /* PLOGI completes to NPort */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0102 PLOGI completes to NPort x%x " - "Data: x%x x%x x%x x%x\n", + "Data: x%x x%x x%x x%x x%x\n", phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, - irsp->un.ulpWord[4], disc, phba->num_disc_nodes); + irsp->un.ulpWord[4], irsp->ulpTimeout, disc, + phba->num_disc_nodes); /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(phba)) { @@ -722,7 +716,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { - disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); + rc = NLP_STE_FREED_NODE; } else { rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb, @@ -747,18 +741,11 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, lpfc_more_plogi(phba); } - if (rc != NLP_STE_FREED_NODE) { + if (phba->num_disc_nodes == 0) { spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; + phba->fc_flag &= ~FC_NDISC_ACTIVE; spin_unlock_irq(phba->host->host_lock); - } - if (phba->num_disc_nodes == 0) { - if(disc) { - spin_lock_irq(phba->host->host_lock); - phba->fc_flag &= ~FC_NDISC_ACTIVE; - spin_unlock_irq(phba->host->host_lock); - } lpfc_can_disctmo(phba); if (phba->fc_flag & FC_RSCN_MODE) { /* Check to see if more RSCNs came in while we were @@ -796,10 +783,10 @@ lpfc_issue_els_plogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); - if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, - ndlp, ELS_CMD_PLOGI)) == 0) { - return (1); - } + elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, + ELS_CMD_PLOGI); + if (!elsiocb) + return 1; icmd = &elsiocb->iocb; pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); @@ -824,10 +811,10 @@ lpfc_issue_els_plogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, ndlp->nlp_flag &= ~NLP_PLOGI_SND; spin_unlock_irq(phba->host->host_lock); lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } spin_unlock_irq(phba->host->host_lock); - return (0); + return 0; } static void @@ -851,9 +838,10 @@ lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, /* PRLI completes to NPort */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0103 PRLI completes to NPort x%x " - "Data: x%x x%x x%x\n", + "Data: x%x x%x x%x x%x\n", phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, - irsp->un.ulpWord[4], phba->num_disc_nodes); + irsp->un.ulpWord[4], irsp->ulpTimeout, + phba->num_disc_nodes); phba->fc_prli_sent--; /* Check to see if link went down during discovery */ @@ -906,7 +894,7 @@ lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, cmdsize = (sizeof (uint32_t) + sizeof (PRLI)); if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, ELS_CMD_PRLI)) == 0) { - return (1); + return 1; } icmd = &elsiocb->iocb; @@ -943,11 +931,11 @@ lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, ndlp->nlp_flag &= ~NLP_PRLI_SND; spin_unlock_irq(phba->host->host_lock); lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } spin_unlock_irq(phba->host->host_lock); phba->fc_prli_sent++; - return (0); + return 0; } static void @@ -1016,21 +1004,22 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, irsp = &(rspiocb->iocb); ndlp = (struct lpfc_nodelist *) cmdiocb->context1; - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~NLP_ADISC_SND; - spin_unlock_irq(phba->host->host_lock); /* Since ndlp can be freed in the disc state machine, note if this node * is being used during discovery. */ disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC); + spin_unlock_irq(phba->host->host_lock); /* ADISC completes to NPort */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0104 ADISC completes to NPort x%x " - "Data: x%x x%x x%x x%x\n", + "Data: x%x x%x x%x x%x x%x\n", phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, - irsp->un.ulpWord[4], disc, phba->num_disc_nodes); + irsp->un.ulpWord[4], irsp->ulpTimeout, disc, + phba->num_disc_nodes); /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(phba)) { @@ -1054,13 +1043,10 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, } /* ADISC failed */ /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ - if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && - ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || - (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || - (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { - disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); - } - else { + if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) || + ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) && + (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) && + (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) { lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_ADISC); } @@ -1112,9 +1098,6 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, } } } - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; - spin_unlock_irq(phba->host->host_lock); out: lpfc_els_free_iocb(phba, cmdiocb); return; @@ -1138,7 +1121,7 @@ lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, cmdsize = (sizeof (uint32_t) + sizeof (ADISC)); if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, ELS_CMD_ADISC)) == 0) { - return (1); + return 1; } icmd = &elsiocb->iocb; @@ -1163,10 +1146,10 @@ lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, ndlp->nlp_flag &= ~NLP_ADISC_SND; spin_unlock_irq(phba->host->host_lock); lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } spin_unlock_irq(phba->host->host_lock); - return (0); + return 0; } static void @@ -1190,9 +1173,10 @@ lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, /* LOGO completes to NPort */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0105 LOGO completes to NPort x%x " - "Data: x%x x%x x%x\n", + "Data: x%x x%x x%x x%x\n", phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, - irsp->un.ulpWord[4], phba->num_disc_nodes); + irsp->un.ulpWord[4], irsp->ulpTimeout, + phba->num_disc_nodes); /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(phba)) @@ -1247,7 +1231,7 @@ lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, cmdsize = 2 * (sizeof (uint32_t) + sizeof (struct lpfc_name)); if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, ELS_CMD_LOGO)) == 0) { - return (1); + return 1; } icmd = &elsiocb->iocb; @@ -1268,10 +1252,10 @@ lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, ndlp->nlp_flag &= ~NLP_LOGO_SND; spin_unlock_irq(phba->host->host_lock); lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } spin_unlock_irq(phba->host->host_lock); - return (0); + return 0; } static void @@ -1286,9 +1270,10 @@ lpfc_cmpl_els_cmd(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d:0106 ELS cmd tag x%x completes Data: x%x x%x\n", + "%d:0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n", phba->brd_no, - irsp->ulpIoTag, irsp->ulpStatus, irsp->un.ulpWord[4]); + irsp->ulpIoTag, irsp->ulpStatus, + irsp->un.ulpWord[4], irsp->ulpTimeout); /* Check to see if link went down during discovery */ lpfc_els_chk_latt(phba); @@ -1310,16 +1295,16 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) psli = &phba->sli; pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ cmdsize = (sizeof (uint32_t) + sizeof (SCR)); - if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) == 0) { - return (1); - } + ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); + if (!ndlp) + return 1; lpfc_nlp_init(phba, ndlp, nportid); if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, ELS_CMD_SCR)) == 0) { mempool_free( ndlp, phba->nlp_mem_pool); - return (1); + return 1; } icmd = &elsiocb->iocb; @@ -1339,11 +1324,11 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) spin_unlock_irq(phba->host->host_lock); mempool_free( ndlp, phba->nlp_mem_pool); lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } spin_unlock_irq(phba->host->host_lock); mempool_free( ndlp, phba->nlp_mem_pool); - return (0); + return 0; } static int @@ -1363,15 +1348,15 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) psli = &phba->sli; pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ cmdsize = (sizeof (uint32_t) + sizeof (FARP)); - if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) == 0) { - return (1); - } + ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); + if (!ndlp) + return 1; lpfc_nlp_init(phba, ndlp, nportid); if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, ELS_CMD_RNID)) == 0) { mempool_free( ndlp, phba->nlp_mem_pool); - return (1); + return 1; } icmd = &elsiocb->iocb; @@ -1405,11 +1390,11 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) spin_unlock_irq(phba->host->host_lock); mempool_free( ndlp, phba->nlp_mem_pool); lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } spin_unlock_irq(phba->host->host_lock); mempool_free( ndlp, phba->nlp_mem_pool); - return (0); + return 0; } void @@ -1541,11 +1526,6 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, case IOERR_SEQUENCE_TIMEOUT: retry = 1; - if ((cmd == ELS_CMD_FLOGI) - && (phba->fc_topology != TOPOLOGY_LOOP)) { - delay = 1; - maxretry = 48; - } break; case IOERR_NO_RESOURCES: @@ -1654,32 +1634,32 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_last_elscmd = cmd; - return (1); + return 1; } switch (cmd) { case ELS_CMD_FLOGI: lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry); - return (1); + return 1; case ELS_CMD_PLOGI: ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, cmdiocb->retry); - return (1); + return 1; case ELS_CMD_ADISC: ndlp->nlp_state = NLP_STE_ADISC_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry); - return (1); + return 1; case ELS_CMD_PRLI: ndlp->nlp_state = NLP_STE_PRLI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry); - return (1); + return 1; case ELS_CMD_LOGO: ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry); - return (1); + return 1; } } @@ -1690,7 +1670,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, phba->brd_no, cmd, ndlp->nlp_DID, cmdiocb->retry, ndlp->nlp_flag); - return (0); + return 0; } int @@ -1780,11 +1760,12 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, /* ELS response tag completes */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0110 ELS response tag x%x completes " - "Data: x%x x%x x%x x%x x%x x%x\n", + "Data: x%x x%x x%x x%x x%x x%x x%x\n", phba->brd_no, cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus, - rspiocb->iocb.un.ulpWord[4], ndlp->nlp_DID, - ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); + rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); if (mbox) { if ((rspiocb->iocb.ulpStatus == 0) @@ -1846,7 +1827,7 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, ELS_CMD_ACC)) == 0) { - return (1); + return 1; } icmd = &elsiocb->iocb; icmd->ulpContext = oldcmd->ulpContext; /* Xri */ @@ -1859,7 +1840,7 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, ELS_CMD_ACC)) == 0) { - return (1); + return 1; } icmd = &elsiocb->iocb; icmd->ulpContext = oldcmd->ulpContext; /* Xri */ @@ -1873,7 +1854,7 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm)); break; default: - return (1); + return 1; } if (newnode) @@ -1889,6 +1870,9 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); if (ndlp->nlp_flag & NLP_LOGO_ACC) { + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag &= ~NLP_LOGO_ACC; + spin_unlock_irq(phba->host->host_lock); elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; } else { elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; @@ -1900,9 +1884,9 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, spin_unlock_irq(phba->host->host_lock); if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } - return (0); + return 0; } int @@ -1924,7 +1908,7 @@ lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError, cmdsize = 2 * sizeof (uint32_t); if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, ELS_CMD_LS_RJT)) == 0) { - return (1); + return 1; } icmd = &elsiocb->iocb; @@ -1952,9 +1936,9 @@ lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError, spin_unlock_irq(phba->host->host_lock); if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } - return (0); + return 0; } int @@ -1977,7 +1961,7 @@ lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba, cmdsize = sizeof (uint32_t) + sizeof (ADISC); if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, ELS_CMD_ACC)) == 0) { - return (1); + return 1; } /* Xmit ADISC ACC response tag */ @@ -2010,9 +1994,9 @@ lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba, spin_unlock_irq(phba->host->host_lock); if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } - return (0); + return 0; } int @@ -2034,13 +2018,10 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba * phba, pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ cmdsize = sizeof (uint32_t) + sizeof (PRLI); - if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, - ndlp, - (ELS_CMD_ACC | - (ELS_CMD_PRLI & ~ELS_RSP_MASK)))) == - 0) { - return (1); - } + elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, + (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK))); + if (!elsiocb) + return 1; /* Xmit PRLI ACC response tag */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, @@ -2090,9 +2071,9 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba * phba, spin_unlock_irq(phba->host->host_lock); if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } - return (0); + return 0; } static int @@ -2120,7 +2101,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba, if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, ELS_CMD_ACC)) == 0) { - return (1); + return 1; } /* Xmit RNID ACC response tag */ @@ -2173,9 +2154,9 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba, spin_unlock_irq(phba->host->host_lock); if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); - return (1); + return 1; } - return (0); + return 0; } int @@ -2268,7 +2249,7 @@ lpfc_els_flush_rscn(struct lpfc_hba * phba) phba->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY); spin_unlock_irq(phba->host->host_lock); lpfc_can_disctmo(phba); - return (0); + return 0; } int @@ -2289,7 +2270,7 @@ lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did) /* If we are doing a FULL RSCN rediscovery, match everything */ if (phba->fc_flag & FC_RSCN_DISCOVERY) { - return (did); + return did; } for (i = 0; i < phba->fc_rscn_id_cnt; i++) { @@ -2337,7 +2318,7 @@ lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did) } } } - return (match); + return match; } static int @@ -2379,7 +2360,7 @@ lpfc_rscn_recovery_check(struct lpfc_hba * phba) } } } - return (0); + return 0; } static int @@ -2415,7 +2396,7 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba, if (phba->hba_state < LPFC_NS_QRY) { lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode); - return (0); + return 0; } /* If we are already processing an RSCN, save the received @@ -2457,7 +2438,7 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba, /* send RECOVERY event for ALL nodes that match RSCN payload */ lpfc_rscn_recovery_check(phba); - return (0); + return 0; } phba->fc_flag |= FC_RSCN_MODE; @@ -2476,7 +2457,7 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba, /* send RECOVERY event for ALL nodes that match RSCN payload */ lpfc_rscn_recovery_check(phba); - return (lpfc_els_handle_rscn(phba)); + return lpfc_els_handle_rscn(phba); } int @@ -2498,27 +2479,27 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) /* To process RSCN, first compare RSCN data with NameServer */ phba->fc_ns_retry = 0; - if ((ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, - NameServer_DID))) { + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, NameServer_DID); + if (ndlp) { /* Good ndlp, issue CT Request to NameServer */ if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) { /* Wait for NameServer query cmpl before we can continue */ - return (1); + return 1; } } else { /* If login to NameServer does not exist, issue one */ /* Good status, issue PLOGI to NameServer */ - if ((ndlp = - lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID))) { + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); + if (ndlp) { /* Wait for NameServer login cmpl before we can continue */ - return (1); + return 1; } - if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) - == 0) { + ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); + if (!ndlp) { lpfc_els_flush_rscn(phba); - return (0); + return 0; } else { lpfc_nlp_init(phba, ndlp, NameServer_DID); ndlp->nlp_type |= NLP_FABRIC; @@ -2526,12 +2507,12 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) lpfc_issue_els_plogi(phba, ndlp, 0); /* Wait for NameServer login cmpl before we can continue */ - return (1); + return 1; } } lpfc_els_flush_rscn(phba); - return (0); + return 0; } static int @@ -2565,7 +2546,7 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, "%d:0113 An FLOGI ELS command x%x was received " "from DID x%x in Loop Mode\n", phba->brd_no, cmd, did); - return (1); + return 1; } did = Fabric_DID; @@ -2581,7 +2562,7 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, if (!rc) { if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) == 0) { - return (1); + return 1; } lpfc_linkdown(phba); lpfc_init_link(phba, mbox, @@ -2594,7 +2575,7 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, if (rc == MBX_NOT_FINISHED) { mempool_free( mbox, phba->mbox_mem_pool); } - return (1); + return 1; } else if (rc > 0) { /* greater than */ spin_lock_irq(phba->host->host_lock); @@ -2610,13 +2591,13 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; stat.un.b.vendorUnique = 0; lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); - return (1); + return 1; } /* Send back ACC */ lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode); - return (0); + return 0; } static int @@ -2654,7 +2635,7 @@ lpfc_els_rcv_rnid(struct lpfc_hba * phba, stat.un.b.vendorUnique = 0; lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); } - return (0); + return 0; } static int @@ -2702,10 +2683,10 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); mempool_free( pmb, phba->mbox_mem_pool); - if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, 3, - ndlp, ELS_CMD_ACC)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, + ndlp, ELS_CMD_ACC); + if (!elsiocb) return; - } icmd = &elsiocb->iocb; icmd->ulpContext = xri; @@ -2926,7 +2907,7 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, /* We will only support match on WWPN or WWNN */ if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) { - return (0); + return 0; } cnt = 0; @@ -2960,7 +2941,7 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, } } } - return (0); + return 0; } static int @@ -3026,14 +3007,14 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, /* This node has switched fabrics. An FLOGI is required * after the timeout */ - return (0); + return 0; } /* Start discovery */ lpfc_disc_start(phba); } - return (0); + return 0; } void @@ -3156,7 +3137,6 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) struct lpfc_dmabuf *pcmd; uint32_t *elscmd; uint32_t els_command; - uint32_t remote_ID; pring = &phba->sli.ring[LPFC_ELS_RING]; spin_lock_irq(phba->host->host_lock); @@ -3179,18 +3159,6 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) elscmd = (uint32_t *) (pcmd->virt); els_command = *elscmd; - if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { - struct lpfc_nodelist *ndlp; - - ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext); - remote_ID = ndlp->nlp_DID; - if (phba->hba_state == LPFC_HBA_READY) { - continue; - } - } else { - remote_ID = cmd->un.elsreq64.remoteID; - } - list_del(&piocb->list); pring->txcmplq_cnt--; @@ -3216,18 +3184,6 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) elscmd = (uint32_t *) (pcmd->virt); els_command = *elscmd; - if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { - struct lpfc_nodelist *ndlp; - - ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext); - remote_ID = ndlp->nlp_DID; - if (phba->hba_state == LPFC_HBA_READY) { - continue; - } - } else { - remote_ID = cmd->un.elsreq64.remoteID; - } - list_del(&piocb->list); pring->txcmplq_cnt--; @@ -3311,10 +3267,11 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, } did = icmd->un.rcvels.remoteID; - if ((ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did)) == 0) { + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); + if (!ndlp) { /* Cannot find existing Fabric ndlp, so allocate a new one */ - if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) - == 0) { + ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); + if (!ndlp) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); drop_cmd = 1; @@ -3475,8 +3432,9 @@ dropit: if (drop_cmd == 1) { lpfc_printf_log(phba, KERN_ERR, LOG_ELS, "%d:0111 Dropping received ELS cmd " - "Data: x%x x%x\n", phba->brd_no, - icmd->ulpStatus, icmd->un.ulpWord[4]); + "Data: x%x x%x x%x\n", phba->brd_no, + icmd->ulpStatus, icmd->un.ulpWord[4], + icmd->ulpTimeout); phba->fc_stat.elsRcvDrop++; } return; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index a1f751e79405..5c396171ebe8 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -283,16 +283,18 @@ lpfc_linkdown(struct lpfc_hba * phba) { struct lpfc_sli *psli; struct lpfc_nodelist *ndlp, *next_ndlp; - struct list_head *listp; - struct list_head *node_list[7]; + struct list_head *listp, *node_list[7]; LPFC_MBOXQ_t *mb; int rc, i; psli = &phba->sli; - spin_lock_irq(phba->host->host_lock); - phba->hba_state = LPFC_LINK_DOWN; - spin_unlock_irq(phba->host->host_lock); + /* sysfs or selective reset may call this routine to clean up */ + if (phba->hba_state > LPFC_LINK_DOWN) { + spin_lock_irq(phba->host->host_lock); + phba->hba_state = LPFC_LINK_DOWN; + spin_unlock_irq(phba->host->host_lock); + } /* Clean up any firmware default rpi's */ if ((mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) { @@ -324,32 +326,20 @@ lpfc_linkdown(struct lpfc_hba * phba) continue; list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { - /* Fabric nodes are not handled thru state machine for - link down */ - if (ndlp->nlp_type & NLP_FABRIC) { - /* Remove ALL Fabric nodes except Fabric_DID */ - if (ndlp->nlp_DID != Fabric_DID) { - /* Take it off current list and free */ - lpfc_nlp_list(phba, ndlp, - NLP_NO_LIST); - } - } - else { - - rc = lpfc_disc_state_machine(phba, ndlp, NULL, - NLP_EVT_DEVICE_RECOVERY); - - /* Check config parameter use-adisc or FCP-2 */ - if ((rc != NLP_STE_FREED_NODE) && - (phba->cfg_use_adisc == 0) && - !(ndlp->nlp_fcp_info & - NLP_FCP_2_DEVICE)) { - /* We know we will have to relogin, so - * unreglogin the rpi right now to fail - * any outstanding I/Os quickly. - */ - lpfc_unreg_rpi(phba, ndlp); - } + + rc = lpfc_disc_state_machine(phba, ndlp, NULL, + NLP_EVT_DEVICE_RECOVERY); + + /* Check config parameter use-adisc or FCP-2 */ + if ((rc != NLP_STE_FREED_NODE) && + (phba->cfg_use_adisc == 0) && + !(ndlp->nlp_fcp_info & + NLP_FCP_2_DEVICE)) { + /* We know we will have to relogin, so + * unreglogin the rpi right now to fail + * any outstanding I/Os quickly. + */ + lpfc_unreg_rpi(phba, ndlp); } } } @@ -391,6 +381,8 @@ static int lpfc_linkup(struct lpfc_hba * phba) { struct lpfc_nodelist *ndlp, *next_ndlp; + struct list_head *listp, *node_list[7]; + int i; spin_lock_irq(phba->host->host_lock); phba->hba_state = LPFC_LINK_UP; @@ -401,14 +393,33 @@ lpfc_linkup(struct lpfc_hba * phba) spin_unlock_irq(phba->host->host_lock); - /* - * Clean up old Fabric NLP_FABRIC logins. - */ - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list, - nlp_listp) { - if (ndlp->nlp_DID == Fabric_DID) { - /* Take it off current list and free */ - lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + node_list[0] = &phba->fc_plogi_list; + node_list[1] = &phba->fc_adisc_list; + node_list[2] = &phba->fc_reglogin_list; + node_list[3] = &phba->fc_prli_list; + node_list[4] = &phba->fc_nlpunmap_list; + node_list[5] = &phba->fc_nlpmap_list; + node_list[6] = &phba->fc_npr_list; + for (i = 0; i < 7; i++) { + listp = node_list[i]; + if (list_empty(listp)) + continue; + + list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { + if (phba->fc_flag & FC_LBIT) { + if (ndlp->nlp_type & NLP_FABRIC) { + /* On Linkup its safe to clean up the + * ndlp from Fabric connections. + */ + lpfc_nlp_list(phba, ndlp, + NLP_UNUSED_LIST); + } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { + /* Fail outstanding IO now since device + * is marked for PLOGI. + */ + lpfc_unreg_rpi(phba, ndlp); + } + } } } @@ -784,6 +795,13 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) memcpy(&phba->alpa_map[0], mp->virt, 128); + spin_lock_irq(phba->host->host_lock); + if (la->pb) + phba->fc_flag |= FC_BYPASSED_MODE; + else + phba->fc_flag &= ~FC_BYPASSED_MODE; + spin_unlock_irq(phba->host->host_lock); + if (((phba->fc_eventTag + 1) < la->eventTag) || (phba->fc_eventTag == la->eventTag)) { phba->fc_stat.LinkMultiEvent++; @@ -904,32 +922,36 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) */ lpfc_issue_els_scr(phba, SCR_DID, 0); - /* Allocate a new node instance. If the pool is empty, just - * start the discovery process and skip the Nameserver login - * process. This is attempted again later on. Otherwise, issue - * a Port Login (PLOGI) to the NameServer - */ - if ((ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL)) - == 0) { - lpfc_disc_start(phba); - } else { - lpfc_nlp_init(phba, ndlp, NameServer_DID); - ndlp->nlp_type |= NLP_FABRIC; - ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; - lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); - lpfc_issue_els_plogi(phba, ndlp, 0); - if (phba->cfg_fdmi_on) { - if ((ndlp_fdmi = mempool_alloc( - phba->nlp_mem_pool, - GFP_KERNEL))) { - lpfc_nlp_init(phba, ndlp_fdmi, - FDMI_DID); - ndlp_fdmi->nlp_type |= NLP_FABRIC; - ndlp_fdmi->nlp_state = - NLP_STE_PLOGI_ISSUE; - lpfc_issue_els_plogi(phba, ndlp_fdmi, - 0); - } + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); + if (!ndlp) { + /* Allocate a new node instance. If the pool is empty, + * start the discovery process and skip the Nameserver + * login process. This is attempted again later on. + * Otherwise, issue a Port Login (PLOGI) to NameServer. + */ + ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); + if (!ndlp) { + lpfc_disc_start(phba); + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + mempool_free( pmb, phba->mbox_mem_pool); + return; + } else { + lpfc_nlp_init(phba, ndlp, NameServer_DID); + ndlp->nlp_type |= NLP_FABRIC; + } + } + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); + lpfc_issue_els_plogi(phba, ndlp, 0); + if (phba->cfg_fdmi_on) { + ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool, + GFP_KERNEL); + if (ndlp_fdmi) { + lpfc_nlp_init(phba, ndlp_fdmi, FDMI_DID); + ndlp_fdmi->nlp_type |= NLP_FABRIC; + ndlp_fdmi->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_issue_els_plogi(phba, ndlp_fdmi, 0); } } } @@ -937,7 +959,6 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); - return; } @@ -1241,16 +1262,9 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list); phba->fc_npr_cnt++; - /* - * Sanity check for Fabric entity. - * Set nodev_tmo for NPR state, for Fabric use 1 sec. - */ - if (nlp->nlp_type & NLP_FABRIC) { - mod_timer(&nlp->nlp_tmofunc, jiffies + HZ); - } - else { + if (!(nlp->nlp_flag & NLP_NODEV_TMO)) { mod_timer(&nlp->nlp_tmofunc, - jiffies + HZ * phba->cfg_nodev_tmo); + jiffies + HZ * phba->cfg_nodev_tmo); } spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= NLP_NODEV_TMO; @@ -1314,7 +1328,15 @@ lpfc_set_disctmo(struct lpfc_hba * phba) { uint32_t tmo; - tmo = ((phba->fc_ratov * 2) + 1); + if (phba->hba_state == LPFC_LOCAL_CFG_LINK) { + /* For FAN, timeout should be greater then edtov */ + tmo = (((phba->fc_edtov + 999) / 1000) + 1); + } else { + /* Normal discovery timeout should be > then ELS/CT timeout + * FC spec states we need 3 * ratov for CT requests + */ + tmo = ((phba->fc_ratov * 3) + 3); + } mod_timer(&phba->fc_disctmo, jiffies + HZ * tmo); spin_lock_irq(phba->host->host_lock); @@ -1846,8 +1868,9 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) struct lpfc_nodelist *ndlp; uint32_t flg; - if ((ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did)) == 0) { - if ((phba->hba_state == LPFC_HBA_READY) && + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); + if (!ndlp) { + if ((phba->fc_flag & FC_RSCN_MODE) && ((lpfc_rscn_payload_check(phba, did) == 0))) return NULL; ndlp = (struct lpfc_nodelist *) @@ -1860,10 +1883,23 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) ndlp->nlp_flag |= NLP_NPR_2B_DISC; return ndlp; } - if ((phba->hba_state == LPFC_HBA_READY) && - (phba->fc_flag & FC_RSCN_MODE)) { + if (phba->fc_flag & FC_RSCN_MODE) { if (lpfc_rscn_payload_check(phba, did)) { ndlp->nlp_flag |= NLP_NPR_2B_DISC; + + /* Since this node is marked for discovery, + * delay timeout is not needed. + */ + if (ndlp->nlp_flag & NLP_DELAY_TMO) { + ndlp->nlp_flag &= ~NLP_DELAY_TMO; + spin_unlock_irq(phba->host->host_lock); + del_timer_sync(&ndlp->nlp_delayfunc); + spin_lock_irq(phba->host->host_lock); + if (!list_empty(&ndlp->els_retry_evt. + evt_listp)) + list_del_init(&ndlp->els_retry_evt. + evt_listp); + } } else { ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; @@ -1872,10 +1908,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) } else { flg = ndlp->nlp_flag & NLP_LIST_MASK; - if ((flg == NLP_ADISC_LIST) || - (flg == NLP_PLOGI_LIST)) { + if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST)) return NULL; - } ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_flag |= NLP_NPR_2B_DISC; @@ -2174,7 +2208,7 @@ static void lpfc_disc_timeout_handler(struct lpfc_hba *phba) { struct lpfc_sli *psli; - struct lpfc_nodelist *ndlp; + struct lpfc_nodelist *ndlp, *next_ndlp; LPFC_MBOXQ_t *clearlambox, *initlinkmbox; int rc, clrlaerr = 0; @@ -2201,10 +2235,20 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) "%d:0221 FAN timeout\n", phba->brd_no); - /* Forget about FAN, Start discovery by sending a FLOGI - * hba_state is identically LPFC_FLOGI while waiting for FLOGI - * cmpl - */ + /* Start discovery by sending FLOGI, clean up old rpis */ + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, + nlp_listp) { + if (ndlp->nlp_type & NLP_FABRIC) { + /* Clean up the ndlp on Fabric connections */ + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + } + else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { + /* Fail outstanding IO now since device + * is marked for PLOGI. + */ + lpfc_unreg_rpi(phba, ndlp); + } + } phba->hba_state = LPFC_FLOGI; lpfc_set_disctmo(phba); lpfc_initial_flogi(phba); diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 1c04ea353ffa..a580e1e50672 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -46,13 +46,13 @@ lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, * table entry for that node. */ if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)) != 0) - return (0); + return 0; if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)) != 0) - return (0); + return 0; /* we match, return success */ - return (1); + return 1; } int @@ -159,7 +159,7 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba * phba, } ptr = NULL; } - return (ptr); + return ptr; } @@ -266,7 +266,7 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, if (!list_empty(&ndlp->els_retry_evt.evt_listp)) list_del_init(&ndlp->els_retry_evt.evt_listp); } - return (0); + return 0; } static int @@ -321,7 +321,7 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); - return (0); + return 0; } icmd = &cmdiocb->iocb; @@ -362,7 +362,7 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, case NLP_STE_UNMAPPED_NODE: case NLP_STE_MAPPED_NODE: lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0); - return (1); + return 1; } if ((phba->fc_flag & FC_PT2PT) @@ -409,13 +409,13 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, } ndlp->nlp_flag |= NLP_RCV_PLOGI; lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); - return (1); + return 1; out: stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE; lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); - return (0); + return 0; } static int @@ -456,7 +456,7 @@ lpfc_rcv_padisc(struct lpfc_hba * phba, lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0); } - return (1); + return 1; } /* Reject this request because invalid parameters */ stat.un.b.lsRjtRsvd0 = 0; @@ -474,7 +474,7 @@ lpfc_rcv_padisc(struct lpfc_hba * phba, spin_unlock_irq(phba->host->host_lock); ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); - return (0); + return 0; } static int @@ -489,25 +489,31 @@ lpfc_rcv_logo(struct lpfc_hba * phba, ndlp->nlp_flag |= NLP_LOGO_ACC; lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); - if (!(ndlp->nlp_type & NLP_FABRIC)) { + if (!(ndlp->nlp_type & NLP_FABRIC) || + (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { /* Only try to re-login if this is NOT a Fabric Node */ ndlp->nlp_last_elscmd = (unsigned long)ELS_CMD_PLOGI; mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag |= NLP_DELAY_TMO; spin_unlock_irq(phba->host->host_lock); - } - ndlp->nlp_state = NLP_STE_NPR_NODE; - lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); + } else { + ndlp->nlp_state = NLP_STE_UNUSED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); + } + spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; + spin_unlock_irq(phba->host->host_lock); /* The driver has to wait until the ACC completes before it continues * processing the LOGO. The action will resume in * lpfc_cmpl_els_logo_acc routine. Since part of processing includes an * unreg_login, the driver waits so the ACC does not get aborted. */ - return (0); + return 0; } static void @@ -555,20 +561,12 @@ lpfc_disc_set_adisc(struct lpfc_hba * phba, if ((phba->cfg_use_adisc == 0) && !(phba->fc_flag & FC_RSCN_MODE)) { if (!(ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE)) - return (0); + return 0; } spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag |= NLP_NPR_ADISC; spin_unlock_irq(phba->host->host_lock); - return (1); -} - -static uint32_t -lpfc_disc_noop(struct lpfc_hba * phba, - struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) -{ - /* This routine does nothing, just return the current state */ - return (ndlp->nlp_state); + return 1; } static uint32_t @@ -583,7 +581,7 @@ lpfc_disc_illegal(struct lpfc_hba * phba, phba->brd_no, ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi, ndlp->nlp_flag); - return (ndlp->nlp_state); + return ndlp->nlp_state; } /* Start of Discovery State Machine routines */ @@ -599,10 +597,10 @@ lpfc_rcv_plogi_unused_node(struct lpfc_hba * phba, if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) { ndlp->nlp_state = NLP_STE_UNUSED_NODE; lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); - return (ndlp->nlp_state); + return ndlp->nlp_state; } lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - return (NLP_STE_FREED_NODE); + return NLP_STE_FREED_NODE; } static uint32_t @@ -611,7 +609,7 @@ lpfc_rcv_els_unused_node(struct lpfc_hba * phba, { lpfc_issue_els_logo(phba, ndlp, 0); lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -628,7 +626,7 @@ lpfc_rcv_logo_unused_node(struct lpfc_hba * phba, lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -636,7 +634,7 @@ lpfc_cmpl_logo_unused_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) { lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - return (NLP_STE_FREED_NODE); + return NLP_STE_FREED_NODE; } static uint32_t @@ -644,7 +642,7 @@ lpfc_device_rm_unused_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) { lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - return (NLP_STE_FREED_NODE); + return NLP_STE_FREED_NODE; } static uint32_t @@ -682,7 +680,22 @@ lpfc_rcv_plogi_plogi_issue(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, lpfc_rcv_plogi(phba, ndlp, cmdiocb); } /* if our portname was less */ - return (ndlp->nlp_state); + return ndlp->nlp_state; +} + +static uint32_t +lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba, + struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) +{ + struct lpfc_iocbq *cmdiocb; + + cmdiocb = (struct lpfc_iocbq *) arg; + + /* software abort outstanding PLOGI */ + lpfc_els_abort(phba, ndlp, 1); + + lpfc_rcv_logo(phba, ndlp, cmdiocb); + return ndlp->nlp_state; } static uint32_t @@ -712,7 +725,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba, ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -731,7 +744,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, rspiocb = cmdiocb->context_un.rsp_iocb; if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { - return (ndlp->nlp_state); + return ndlp->nlp_state; } irsp = &rspiocb->iocb; @@ -812,7 +825,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, NLP_STE_REG_LOGIN_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_REGLOGIN_LIST); - return (ndlp->nlp_state); + return ndlp->nlp_state; } mempool_free(mbox, phba->mbox_mem_pool); } else { @@ -824,7 +837,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, /* Free this node since the driver cannot login or has the wrong sparm */ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - return (NLP_STE_FREED_NODE); + return NLP_STE_FREED_NODE; } static uint32_t @@ -835,7 +848,7 @@ lpfc_device_rm_plogi_issue(struct lpfc_hba * phba, lpfc_els_abort(phba, ndlp, 1); lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - return (NLP_STE_FREED_NODE); + return NLP_STE_FREED_NODE; } static uint32_t @@ -852,7 +865,7 @@ lpfc_device_recov_plogi_issue(struct lpfc_hba * phba, ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; spin_unlock_irq(phba->host->host_lock); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -868,13 +881,13 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) { - return (ndlp->nlp_state); + return ndlp->nlp_state; } ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, 0); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -887,7 +900,7 @@ lpfc_rcv_prli_adisc_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -903,7 +916,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba, lpfc_els_abort(phba, ndlp, 0); lpfc_rcv_logo(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -916,7 +929,7 @@ lpfc_rcv_padisc_adisc_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_padisc(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -930,7 +943,7 @@ lpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba, /* Treat like rcv logo */ lpfc_rcv_logo(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -963,7 +976,7 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba, ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); lpfc_unreg_rpi(phba, ndlp); - return (ndlp->nlp_state); + return ndlp->nlp_state; } if (ndlp->nlp_type & NLP_FCP_TARGET) { ndlp->nlp_state = NLP_STE_MAPPED_NODE; @@ -972,7 +985,7 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba, ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); } - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -984,7 +997,7 @@ lpfc_device_rm_adisc_issue(struct lpfc_hba * phba, lpfc_els_abort(phba, ndlp, 1); lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - return (NLP_STE_FREED_NODE); + return NLP_STE_FREED_NODE; } static uint32_t @@ -999,10 +1012,10 @@ lpfc_device_recov_adisc_issue(struct lpfc_hba * phba, lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; + ndlp->nlp_flag |= NLP_NPR_ADISC; spin_unlock_irq(phba->host->host_lock); - lpfc_disc_set_adisc(phba, ndlp); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1015,7 +1028,7 @@ lpfc_rcv_plogi_reglogin_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_plogi(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1028,7 +1041,7 @@ lpfc_rcv_prli_reglogin_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1041,7 +1054,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_logo(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1054,7 +1067,7 @@ lpfc_rcv_padisc_reglogin_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_padisc(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1066,7 +1079,7 @@ lpfc_rcv_prlo_reglogin_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1100,7 +1113,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba, ndlp->nlp_last_elscmd = (unsigned long)ELS_CMD_PLOGI; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); - return (ndlp->nlp_state); + return ndlp->nlp_state; } ndlp->nlp_rpi = mb->un.varWords[0]; @@ -1114,7 +1127,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba, ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); } - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1123,7 +1136,7 @@ lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba, uint32_t evt) { lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - return (NLP_STE_FREED_NODE); + return NLP_STE_FREED_NODE; } static uint32_t @@ -1136,7 +1149,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba, spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; spin_unlock_irq(phba->host->host_lock); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1148,7 +1161,7 @@ lpfc_rcv_plogi_prli_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_plogi(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1160,7 +1173,7 @@ lpfc_rcv_prli_prli_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1175,7 +1188,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba, lpfc_els_abort(phba, ndlp, 1); lpfc_rcv_logo(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1187,7 +1200,7 @@ lpfc_rcv_padisc_prli_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_padisc(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } /* This routine is envoked when we rcv a PRLO request from a nport @@ -1203,7 +1216,7 @@ lpfc_rcv_prlo_prli_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1222,7 +1235,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba, if (irsp->ulpStatus) { ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); - return (ndlp->nlp_state); + return ndlp->nlp_state; } /* Check out PRLI rsp */ @@ -1240,7 +1253,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba, ndlp->nlp_state = NLP_STE_MAPPED_NODE; lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST); - return (ndlp->nlp_state); + return ndlp->nlp_state; } /*! lpfc_device_rm_prli_issue @@ -1268,7 +1281,7 @@ lpfc_device_rm_prli_issue(struct lpfc_hba * phba, lpfc_els_abort(phba, ndlp, 1); lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - return (NLP_STE_FREED_NODE); + return NLP_STE_FREED_NODE; } @@ -1300,7 +1313,7 @@ lpfc_device_recov_prli_issue(struct lpfc_hba * phba, spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; spin_unlock_irq(phba->host->host_lock); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1312,7 +1325,7 @@ lpfc_rcv_plogi_unmap_node(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_plogi(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1325,7 +1338,7 @@ lpfc_rcv_prli_unmap_node(struct lpfc_hba * phba, lpfc_rcv_prli(phba, ndlp, cmdiocb); lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1337,7 +1350,7 @@ lpfc_rcv_logo_unmap_node(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_logo(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1349,7 +1362,7 @@ lpfc_rcv_padisc_unmap_node(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_padisc(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1360,9 +1373,8 @@ lpfc_rcv_prlo_unmap_node(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; - /* Treat like rcv logo */ - lpfc_rcv_logo(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); + return ndlp->nlp_state; } static uint32_t @@ -1374,7 +1386,7 @@ lpfc_device_recov_unmap_node(struct lpfc_hba * phba, ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; lpfc_disc_set_adisc(phba, ndlp); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1386,7 +1398,7 @@ lpfc_rcv_plogi_mapped_node(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_plogi(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1398,7 +1410,7 @@ lpfc_rcv_prli_mapped_node(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1410,7 +1422,7 @@ lpfc_rcv_logo_mapped_node(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_logo(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1423,7 +1435,7 @@ lpfc_rcv_padisc_mapped_node(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_padisc(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1442,7 +1454,7 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_hba * phba, /* Treat like rcv logo */ lpfc_rcv_logo(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1456,7 +1468,7 @@ lpfc_device_recov_mapped_node(struct lpfc_hba * phba, ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; spin_unlock_irq(phba->host->host_lock); lpfc_disc_set_adisc(phba, ndlp); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1470,14 +1482,14 @@ lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba, /* Ignore PLOGI if we have an outstanding LOGO */ if (ndlp->nlp_flag & NLP_LOGO_SND) { - return (ndlp->nlp_state); + return ndlp->nlp_state; } if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) { spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~(NLP_NPR_ADISC | NLP_NPR_2B_DISC); spin_unlock_irq(phba->host->host_lock); - return (ndlp->nlp_state); + return ndlp->nlp_state; } /* send PLOGI immediately, move to PLOGI issue state */ @@ -1486,7 +1498,7 @@ lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba, lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, 0); } - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1506,6 +1518,9 @@ lpfc_rcv_prli_npr_node(struct lpfc_hba * phba, if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { if (ndlp->nlp_flag & NLP_NPR_ADISC) { + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag &= ~NLP_NPR_ADISC; + spin_unlock_irq(phba->host->host_lock); ndlp->nlp_state = NLP_STE_ADISC_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); lpfc_issue_els_adisc(phba, ndlp, 0); @@ -1515,7 +1530,7 @@ lpfc_rcv_prli_npr_node(struct lpfc_hba * phba, lpfc_issue_els_plogi(phba, ndlp, 0); } } - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1528,7 +1543,7 @@ lpfc_rcv_logo_npr_node(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; lpfc_rcv_logo(phba, ndlp, cmdiocb); - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1553,7 +1568,7 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba, lpfc_issue_els_plogi(phba, ndlp, 0); } } - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1565,25 +1580,46 @@ lpfc_rcv_prlo_npr_node(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag |= NLP_LOGO_ACC; + spin_unlock_irq(phba->host->host_lock); + lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); - if (ndlp->nlp_flag & NLP_DELAY_TMO) { - if (ndlp->nlp_last_elscmd == (unsigned long)ELS_CMD_PLOGI) { - return (ndlp->nlp_state); - } else { - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~NLP_DELAY_TMO; - spin_unlock_irq(phba->host->host_lock); - del_timer_sync(&ndlp->nlp_delayfunc); - if (!list_empty(&ndlp->els_retry_evt.evt_listp)) - list_del_init(&ndlp->els_retry_evt.evt_listp); - } + if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { + mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag |= NLP_DELAY_TMO; + ndlp->nlp_flag &= ~NLP_NPR_ADISC; + spin_unlock_irq(phba->host->host_lock); + } else { + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag &= ~NLP_NPR_ADISC; + spin_unlock_irq(phba->host->host_lock); } + return ndlp->nlp_state; +} - ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; - lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); - lpfc_issue_els_plogi(phba, ndlp, 0); - return (ndlp->nlp_state); +static uint32_t +lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba, + struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) +{ + struct lpfc_iocbq *cmdiocb, *rspiocb; + + cmdiocb = (struct lpfc_iocbq *) arg; + rspiocb = cmdiocb->context_un.rsp_iocb; + return ndlp->nlp_state; +} + +static uint32_t +lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba, + struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) +{ + struct lpfc_iocbq *cmdiocb, *rspiocb; + + cmdiocb = (struct lpfc_iocbq *) arg; + rspiocb = cmdiocb->context_un.rsp_iocb; + return ndlp->nlp_state; } static uint32_t @@ -1592,7 +1628,19 @@ lpfc_cmpl_logo_npr_node(struct lpfc_hba * phba, { lpfc_unreg_rpi(phba, ndlp); /* This routine does nothing, just return the current state */ - return (ndlp->nlp_state); + return ndlp->nlp_state; +} + +static uint32_t +lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba, + struct lpfc_nodelist * ndlp, void *arg, + uint32_t evt) +{ + struct lpfc_iocbq *cmdiocb, *rspiocb; + + cmdiocb = (struct lpfc_iocbq *) arg; + rspiocb = cmdiocb->context_un.rsp_iocb; + return ndlp->nlp_state; } static uint32_t @@ -1606,9 +1654,10 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba, pmb = (LPFC_MBOXQ_t *) arg; mb = &pmb->mb; - ndlp->nlp_rpi = mb->un.varWords[0]; + if (!mb->mbxStatus) + ndlp->nlp_rpi = mb->un.varWords[0]; - return (ndlp->nlp_state); + return ndlp->nlp_state; } static uint32_t @@ -1617,7 +1666,7 @@ lpfc_device_rm_npr_node(struct lpfc_hba * phba, uint32_t evt) { lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - return (NLP_STE_FREED_NODE); + return NLP_STE_FREED_NODE; } static uint32_t @@ -1633,10 +1682,10 @@ lpfc_device_recov_npr_node(struct lpfc_hba * phba, list_del_init(&ndlp->els_retry_evt.evt_listp); spin_unlock_irq(phba->host->host_lock); del_timer_sync(&ndlp->nlp_delayfunc); - return (ndlp->nlp_state); + return ndlp->nlp_state; } spin_unlock_irq(phba->host->host_lock); - return (ndlp->nlp_state); + return ndlp->nlp_state; } @@ -1715,7 +1764,7 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) lpfc_rcv_plogi_plogi_issue, /* RCV_PLOGI PLOGI_ISSUE */ lpfc_rcv_els_plogi_issue, /* RCV_PRLI */ - lpfc_rcv_els_plogi_issue, /* RCV_LOGO */ + lpfc_rcv_logo_plogi_issue, /* RCV_LOGO */ lpfc_rcv_els_plogi_issue, /* RCV_ADISC */ lpfc_rcv_els_plogi_issue, /* RCV_PDISC */ lpfc_rcv_els_plogi_issue, /* RCV_PRLO */ @@ -1803,10 +1852,10 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) lpfc_rcv_padisc_npr_node, /* RCV_ADISC */ lpfc_rcv_padisc_npr_node, /* RCV_PDISC */ lpfc_rcv_prlo_npr_node, /* RCV_PRLO */ - lpfc_disc_noop, /* CMPL_PLOGI */ - lpfc_disc_noop, /* CMPL_PRLI */ + lpfc_cmpl_plogi_npr_node, /* CMPL_PLOGI */ + lpfc_cmpl_prli_npr_node, /* CMPL_PRLI */ lpfc_cmpl_logo_npr_node, /* CMPL_LOGO */ - lpfc_disc_noop, /* CMPL_ADISC */ + lpfc_cmpl_adisc_npr_node, /* CMPL_ADISC */ lpfc_cmpl_reglogin_npr_node, /* CMPL_REG_LOGIN */ lpfc_device_rm_npr_node, /* DEVICE_RM */ lpfc_device_recov_npr_node, /* DEVICE_RECOVERY */ @@ -1852,10 +1901,10 @@ lpfc_disc_state_machine(struct lpfc_hba * phba, ndlp->nlp_flag &= ~NLP_DELAY_REMOVE; spin_unlock_irq(phba->host->host_lock); lpfc_nlp_remove(phba, ndlp); - return (NLP_STE_FREED_NODE); + return NLP_STE_FREED_NODE; } if (rc == NLP_STE_FREED_NODE) - return (NLP_STE_FREED_NODE); + return NLP_STE_FREED_NODE; ndlp->nlp_state = rc; - return (rc); + return rc; } -- cgit v1.2.3-59-g8ed1b From 7f0b5b1913ba20ae035adbaeca176e78a53fa7a8 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:24 -0500 Subject: [SCSI] lpfc 8.1.2: Correct use of the hostdata field in scsi_host Correct use of the hostdata field in scsi_host Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_attr.c | 64 +++++++++++++++++++++---------------------- drivers/scsi/lpfc/lpfc_init.c | 3 +- drivers/scsi/lpfc/lpfc_scsi.c | 14 +++++----- 3 files changed, 40 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index b897e522a966..c8fb43d60882 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -79,7 +79,7 @@ static ssize_t lpfc_serialnum_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber); } @@ -87,7 +87,7 @@ static ssize_t lpfc_modeldesc_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc); } @@ -95,7 +95,7 @@ static ssize_t lpfc_modelname_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName); } @@ -103,7 +103,7 @@ static ssize_t lpfc_programtype_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType); } @@ -111,7 +111,7 @@ static ssize_t lpfc_portnum_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port); } @@ -119,7 +119,7 @@ static ssize_t lpfc_fwrev_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; char fwrev[32]; lpfc_decode_firmware_rev(phba, fwrev, 1); return snprintf(buf, PAGE_SIZE, "%s\n",fwrev); @@ -130,7 +130,7 @@ lpfc_hdw_show(struct class_device *cdev, char *buf) { char hdw[9]; struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; lpfc_vpd_t *vp = &phba->vpd; lpfc_jedec_to_ascii(vp->rev.biuRev, hdw); return snprintf(buf, PAGE_SIZE, "%s\n", hdw); @@ -139,14 +139,14 @@ static ssize_t lpfc_option_rom_version_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion); } static ssize_t lpfc_state_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; int len = 0; switch (phba->hba_state) { case LPFC_INIT_START: @@ -194,7 +194,7 @@ static ssize_t lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; return snprintf(buf, PAGE_SIZE, "%d\n", phba->fc_map_cnt + phba->fc_unmap_cnt); } @@ -203,7 +203,7 @@ lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf) static int lpfc_issue_lip(struct Scsi_Host *host) { - struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata; LPFC_MBOXQ_t *pmboxq; int mbxstatus = MBXERR_ERROR; @@ -235,7 +235,7 @@ static ssize_t lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt); } @@ -243,7 +243,7 @@ static ssize_t lpfc_board_online_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; if (phba->fc_flag & FC_OFFLINE_MODE) return snprintf(buf, PAGE_SIZE, "0\n"); @@ -256,7 +256,7 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf, size_t count) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; struct completion online_compl; int val=0, status=0; @@ -282,7 +282,7 @@ static ssize_t lpfc_poll_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll); } @@ -292,7 +292,7 @@ lpfc_poll_store(struct class_device *cdev, const char *buf, size_t count) { struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; uint32_t creg_val; uint32_t old_val; int val=0; @@ -349,7 +349,7 @@ static ssize_t \ lpfc_##attr##_show(struct class_device *cdev, char *buf) \ { \ struct Scsi_Host *host = class_to_shost(cdev);\ - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];\ + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\ int val = 0;\ val = phba->cfg_##attr;\ return snprintf(buf, PAGE_SIZE, "%d\n",\ @@ -361,7 +361,7 @@ static ssize_t \ lpfc_##attr##_show(struct class_device *cdev, char *buf) \ { \ struct Scsi_Host *host = class_to_shost(cdev);\ - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];\ + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\ int val = 0;\ val = phba->cfg_##attr;\ return snprintf(buf, PAGE_SIZE, "%#x\n",\ @@ -404,7 +404,7 @@ static ssize_t \ lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \ { \ struct Scsi_Host *host = class_to_shost(cdev);\ - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];\ + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\ int val=0;\ if (!isdigit(buf[0]))\ return -EINVAL;\ @@ -685,7 +685,7 @@ sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count) size_t buf_off; struct Scsi_Host *host = class_to_shost(container_of(kobj, struct class_device, kobj)); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; if ((off + count) > FF_REG_AREA_SIZE) return -ERANGE; @@ -718,7 +718,7 @@ sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count) uint32_t * tmp_ptr; struct Scsi_Host *host = class_to_shost(container_of(kobj, struct class_device, kobj)); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; if (off > FF_REG_AREA_SIZE) return -ERANGE; @@ -773,7 +773,7 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count) { struct Scsi_Host * host = class_to_shost(container_of(kobj, struct class_device, kobj)); - struct lpfc_hba * phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba * phba = (struct lpfc_hba*)host->hostdata; struct lpfcMboxq * mbox = NULL; if ((count + off) > MAILBOX_CMD_SIZE) @@ -826,7 +826,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) struct Scsi_Host *host = class_to_shost(container_of(kobj, struct class_device, kobj)); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; int rc; if (off > sizeof(MAILBOX_t)) @@ -1001,7 +1001,7 @@ lpfc_free_sysfs_attr(struct lpfc_hba *phba) static void lpfc_get_host_port_id(struct Scsi_Host *shost) { - struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata; /* note: fc_myDID already in cpu endianness */ fc_host_port_id(shost) = phba->fc_myDID; } @@ -1009,7 +1009,7 @@ lpfc_get_host_port_id(struct Scsi_Host *shost) static void lpfc_get_host_port_type(struct Scsi_Host *shost) { - struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata; spin_lock_irq(shost->host_lock); @@ -1034,7 +1034,7 @@ lpfc_get_host_port_type(struct Scsi_Host *shost) static void lpfc_get_host_port_state(struct Scsi_Host *shost) { - struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata; spin_lock_irq(shost->host_lock); @@ -1075,7 +1075,7 @@ lpfc_get_host_port_state(struct Scsi_Host *shost) static void lpfc_get_host_speed(struct Scsi_Host *shost) { - struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata; spin_lock_irq(shost->host_lock); @@ -1102,7 +1102,7 @@ lpfc_get_host_speed(struct Scsi_Host *shost) static void lpfc_get_host_fabric_name (struct Scsi_Host *shost) { - struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata; u64 node_name; spin_lock_irq(shost->host_lock); @@ -1124,7 +1124,7 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost) static struct fc_host_statistics * lpfc_get_stats(struct Scsi_Host *shost) { - struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; struct lpfc_sli *psli = &phba->sli; struct fc_host_statistics *hs = &phba->link_stats; LPFC_MBOXQ_t *pmboxq; @@ -1214,7 +1214,7 @@ static void lpfc_get_starget_port_id(struct scsi_target *starget) { struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata; uint32_t did = -1; struct lpfc_nodelist *ndlp = NULL; @@ -1235,7 +1235,7 @@ static void lpfc_get_starget_node_name(struct scsi_target *starget) { struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata; u64 node_name = 0; struct lpfc_nodelist *ndlp = NULL; @@ -1256,7 +1256,7 @@ static void lpfc_get_starget_port_name(struct scsi_target *starget) { struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata; u64 port_name = 0; struct lpfc_nodelist *ndlp = NULL; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 369487e8f450..5e92c451f96e 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1553,7 +1553,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list); host->transportt = lpfc_transport_template; - host->hostdata[0] = (unsigned long)phba; pci_set_drvdata(pdev, host); error = scsi_add_host(host, &pdev->dev); if (error) @@ -1675,7 +1674,7 @@ static void __devexit lpfc_pci_remove_one(struct pci_dev *pdev) { struct Scsi_Host *host = pci_get_drvdata(pdev); - struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; unsigned long iflag; lpfc_free_sysfs_attr(phba); diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index dafabeefc5b3..fd7540ea4e19 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -743,7 +743,7 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba) const char * lpfc_info(struct Scsi_Host *host) { - struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata; int len; static char lpfcinfobuf[384]; @@ -803,7 +803,7 @@ static int lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) { struct lpfc_hba *phba = - (struct lpfc_hba *) cmnd->device->host->hostdata[0]; + (struct lpfc_hba *) cmnd->device->host->hostdata; struct lpfc_sli *psli = &phba->sli; struct lpfc_rport_data *rdata = cmnd->device->hostdata; struct lpfc_nodelist *ndlp = rdata->pnode; @@ -877,7 +877,7 @@ static int lpfc_abort_handler(struct scsi_cmnd *cmnd) { struct Scsi_Host *shost = cmnd->device->host; - struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring]; struct lpfc_iocbq *iocb; struct lpfc_iocbq *abtsiocb; @@ -981,7 +981,7 @@ static int lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) { struct Scsi_Host *shost = cmnd->device->host; - struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; struct lpfc_scsi_buf *lpfc_cmd; struct lpfc_iocbq *iocbq, *iocbqrsp; struct lpfc_rport_data *rdata = cmnd->device->hostdata; @@ -1094,7 +1094,7 @@ static int lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) { struct Scsi_Host *shost = cmnd->device->host; - struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; struct lpfc_nodelist *ndlp = NULL; int match; int ret = FAILED, i, err_count = 0; @@ -1195,7 +1195,7 @@ out: static int lpfc_slave_alloc(struct scsi_device *sdev) { - struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata; struct lpfc_scsi_buf *scsi_buf = NULL; struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); uint32_t total = 0, i; @@ -1251,7 +1251,7 @@ lpfc_slave_alloc(struct scsi_device *sdev) static int lpfc_slave_configure(struct scsi_device *sdev) { - struct lpfc_hba *phba = (struct lpfc_hba *) sdev->host->hostdata[0]; + struct lpfc_hba *phba = (struct lpfc_hba *) sdev->host->hostdata; struct fc_rport *rport = starget_to_rport(sdev->sdev_target); if (sdev->tagged_supported) -- cgit v1.2.3-59-g8ed1b From d9d959c41f013439508e0fa1d31f5644d8d626ef Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:26 -0500 Subject: [SCSI] lpfc 8.1.2: Remove hba_list from struct lpfc_hba Remove hba_list from struct lpfc_hba Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index d07ab0214af1..214ab436e035 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -169,7 +169,6 @@ struct lpfc_sysfs_mbox { }; struct lpfc_hba { - struct list_head hba_list; /* List of hbas/ports */ struct lpfc_sli sli; struct lpfc_sli2_slim *slim2p; dma_addr_t slim2p_mapping; -- cgit v1.2.3-59-g8ed1b From 41415862a23f422b80eccc92cf885935139e2415 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:27 -0500 Subject: [SCSI] lpfc 8.1.2: Add ERROR and WARM_START modes for diagnostic purposes. Add ERROR and WARM_START modes for diagnostic purposes. Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 34 +++-- drivers/scsi/lpfc/lpfc_attr.c | 64 +++++++- drivers/scsi/lpfc/lpfc_crtn.h | 9 +- drivers/scsi/lpfc/lpfc_disc.h | 18 ++- drivers/scsi/lpfc/lpfc_hbadisc.c | 32 +++- drivers/scsi/lpfc/lpfc_hw.h | 4 +- drivers/scsi/lpfc/lpfc_init.c | 57 +++++-- drivers/scsi/lpfc/lpfc_mbox.c | 13 +- drivers/scsi/lpfc/lpfc_sli.c | 311 +++++++++++++++++++++++++-------------- 9 files changed, 390 insertions(+), 152 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 214ab436e035..c4cca9124f45 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -175,25 +175,27 @@ struct lpfc_hba { uint16_t pci_cfg_value; struct semaphore hba_can_block; - uint32_t hba_state; - -#define LPFC_INIT_START 1 /* Initial state after board reset */ -#define LPFC_INIT_MBX_CMDS 2 /* Initialize HBA with mbox commands */ -#define LPFC_LINK_DOWN 3 /* HBA initialized, link is down */ -#define LPFC_LINK_UP 4 /* Link is up - issue READ_LA */ -#define LPFC_LOCAL_CFG_LINK 5 /* local NPORT Id configured */ -#define LPFC_FLOGI 6 /* FLOGI sent to Fabric */ -#define LPFC_FABRIC_CFG_LINK 7 /* Fabric assigned NPORT Id + int32_t hba_state; + +#define LPFC_STATE_UNKNOWN 0 /* HBA state is unknown */ +#define LPFC_WARM_START 1 /* HBA state after selective reset */ +#define LPFC_INIT_START 2 /* Initial state after board reset */ +#define LPFC_INIT_MBX_CMDS 3 /* Initialize HBA with mbox commands */ +#define LPFC_LINK_DOWN 4 /* HBA initialized, link is down */ +#define LPFC_LINK_UP 5 /* Link is up - issue READ_LA */ +#define LPFC_LOCAL_CFG_LINK 6 /* local NPORT Id configured */ +#define LPFC_FLOGI 7 /* FLOGI sent to Fabric */ +#define LPFC_FABRIC_CFG_LINK 8 /* Fabric assigned NPORT Id configured */ -#define LPFC_NS_REG 8 /* Register with NameServer */ -#define LPFC_NS_QRY 9 /* Query NameServer for NPort ID list */ -#define LPFC_BUILD_DISC_LIST 10 /* Build ADISC and PLOGI lists for +#define LPFC_NS_REG 9 /* Register with NameServer */ +#define LPFC_NS_QRY 10 /* Query NameServer for NPort ID list */ +#define LPFC_BUILD_DISC_LIST 11 /* Build ADISC and PLOGI lists for * device authentication / discovery */ -#define LPFC_DISC_AUTH 11 /* Processing ADISC list */ -#define LPFC_CLEAR_LA 12 /* authentication cmplt - issue +#define LPFC_DISC_AUTH 12 /* Processing ADISC list */ +#define LPFC_CLEAR_LA 13 /* authentication cmplt - issue CLEAR_LA */ #define LPFC_HBA_READY 32 -#define LPFC_HBA_ERROR 0xff +#define LPFC_HBA_ERROR -1 uint8_t fc_linkspeed; /* Link speed after last READ_LA */ diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index c8fb43d60882..e7aca3c4b26e 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -149,6 +149,8 @@ lpfc_state_show(struct class_device *cdev, char *buf) struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; int len = 0; switch (phba->hba_state) { + case LPFC_STATE_UNKNOWN: + case LPFC_WARM_START: case LPFC_INIT_START: case LPFC_INIT_MBX_CMDS: case LPFC_LINK_DOWN: @@ -278,6 +280,58 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf, return -EIO; } +static ssize_t +lpfc_board_mode_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; + char * state; + + if (phba->hba_state == LPFC_HBA_ERROR) + state = "error"; + else if (phba->hba_state == LPFC_WARM_START) + state = "warm start"; + else if (phba->hba_state == LPFC_INIT_START) + state = "offline"; + else + state = "online"; + + return snprintf(buf, PAGE_SIZE, "%s\n", state); +} + +static ssize_t +lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count) +{ + struct Scsi_Host *host = class_to_shost(cdev); + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; + struct completion online_compl; + int status=0; + + init_completion(&online_compl); + + if(strncmp(buf, "online", sizeof("online") - 1) == 0) + lpfc_workq_post_event(phba, &status, &online_compl, + LPFC_EVT_ONLINE); + else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) + lpfc_workq_post_event(phba, &status, &online_compl, + LPFC_EVT_OFFLINE); + else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0) + lpfc_workq_post_event(phba, &status, &online_compl, + LPFC_EVT_WARM_START); + else if (strncmp(buf, "error", sizeof("error") - 1) == 0) + lpfc_workq_post_event(phba, &status, &online_compl, + LPFC_EVT_KILL); + else + return -EINVAL; + + wait_for_completion(&online_compl); + + if (!status) + return strlen(buf); + else + return -EIO; +} + static ssize_t lpfc_poll_show(struct class_device *cdev, char *buf) { @@ -480,6 +534,8 @@ static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show, NULL); static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR, lpfc_board_online_show, lpfc_board_online_store); +static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR, + lpfc_board_mode_show, lpfc_board_mode_store); static int lpfc_poll = 0; module_param(lpfc_poll, int, 0); @@ -674,6 +730,7 @@ struct class_device_attribute *lpfc_host_attrs[] = { &class_device_attr_nport_evt_cnt, &class_device_attr_management_version, &class_device_attr_board_online, + &class_device_attr_board_mode, &class_device_attr_lpfc_poll, &class_device_attr_lpfc_poll_tmo, NULL, @@ -883,8 +940,11 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) case MBX_DUMP_MEMORY: case MBX_DOWN_LOAD: case MBX_UPDATE_CFG: + case MBX_KILL_BOARD: case MBX_LOAD_AREA: case MBX_LOAD_EXP_ROM: + case MBX_BEACON: + case MBX_DEL_LD_ENTRY: break; case MBX_READ_SPARM64: case MBX_READ_LA: @@ -1042,6 +1102,8 @@ lpfc_get_host_port_state(struct Scsi_Host *shost) fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; else { switch (phba->hba_state) { + case LPFC_STATE_UNKNOWN: + case LPFC_WARM_START: case LPFC_INIT_START: case LPFC_INIT_MBX_CMDS: case LPFC_LINK_DOWN: diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 0ae49811b916..cafddf2f1af8 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -107,6 +107,7 @@ void lpfc_fdmi_tmo_handler(struct lpfc_hba *); int lpfc_config_port_prep(struct lpfc_hba *); int lpfc_config_port_post(struct lpfc_hba *); int lpfc_hba_down_prep(struct lpfc_hba *); +int lpfc_hba_down_post(struct lpfc_hba *); void lpfc_hba_init(struct lpfc_hba *, uint32_t *); int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int); void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int); @@ -123,6 +124,7 @@ irqreturn_t lpfc_intr_handler(int, void *, struct pt_regs *); void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *); void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *); +void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *); LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *); @@ -135,6 +137,11 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba); struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *); void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); + +int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); +int lpfc_sli_brdkill(struct lpfc_hba *); +int lpfc_sli_brdreset(struct lpfc_hba *); +int lpfc_sli_brdrestart(struct lpfc_hba *); int lpfc_sli_hba_setup(struct lpfc_hba *); int lpfc_sli_hba_down(struct lpfc_hba *); int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index ed6c81660e03..4dfcd4eda2fc 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -28,18 +28,24 @@ * This is used by Fibre Channel protocol to support FCP. */ +/* worker thread events */ +enum lpfc_work_type { + LPFC_EVT_NODEV_TMO, + LPFC_EVT_ONLINE, + LPFC_EVT_OFFLINE, + LPFC_EVT_WARM_START, + LPFC_EVT_KILL, + LPFC_EVT_ELS_RETRY, +}; + /* structure used to queue event to the discovery tasklet */ struct lpfc_work_evt { struct list_head evt_listp; void * evt_arg1; void * evt_arg2; - uint32_t evt; + enum lpfc_work_type evt; }; -#define LPFC_EVT_NODEV_TMO 0x1 -#define LPFC_EVT_ONLINE 0x2 -#define LPFC_EVT_OFFLINE 0x3 -#define LPFC_EVT_ELS_RETRY 0x4 struct lpfc_nodelist { struct list_head nlp_listp; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 5c396171ebe8..55454923029d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -120,11 +120,33 @@ lpfc_work_list_done(struct lpfc_hba * phba) free_evt = 0; break; case LPFC_EVT_ONLINE: - *(int *)(evtp->evt_arg1) = lpfc_online(phba); + if (phba->hba_state < LPFC_LINK_DOWN) + *(int *)(evtp->evt_arg1) = lpfc_online(phba); + else + *(int *)(evtp->evt_arg1) = 0; complete((struct completion *)(evtp->evt_arg2)); break; case LPFC_EVT_OFFLINE: - *(int *)(evtp->evt_arg1) = lpfc_offline(phba); + if (phba->hba_state >= LPFC_LINK_DOWN) + lpfc_offline(phba); + lpfc_sli_brdrestart(phba); + *(int *)(evtp->evt_arg1) = + lpfc_sli_brdready(phba,HS_FFRDY | HS_MBRDY); + complete((struct completion *)(evtp->evt_arg2)); + break; + case LPFC_EVT_WARM_START: + if (phba->hba_state >= LPFC_LINK_DOWN) + lpfc_offline(phba); + lpfc_sli_brdreset(phba); + lpfc_hba_down_post(phba); + *(int *)(evtp->evt_arg1) = + lpfc_sli_brdready(phba, HS_MBRDY); + complete((struct completion *)(evtp->evt_arg2)); + break; + case LPFC_EVT_KILL: + if (phba->hba_state >= LPFC_LINK_DOWN) + lpfc_offline(phba); + *(int *)(evtp->evt_arg1) = lpfc_sli_brdkill(phba); complete((struct completion *)(evtp->evt_arg2)); break; } @@ -287,6 +309,10 @@ lpfc_linkdown(struct lpfc_hba * phba) LPFC_MBOXQ_t *mb; int rc, i; + if (phba->hba_state == LPFC_LINK_DOWN) { + return 0; + } + psli = &phba->sli; /* sysfs or selective reset may call this routine to clean up */ diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index e613dd07d2ad..98d39cea7954 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -1233,7 +1233,9 @@ typedef struct { /* FireFly BIU registers */ #define MBX_SET_MASK 0x20 #define MBX_SET_SLIM 0x21 #define MBX_UNREG_D_ID 0x23 +#define MBX_KILL_BOARD 0x24 #define MBX_CONFIG_FARP 0x25 +#define MBX_BEACON 0x2A #define MBX_LOAD_AREA 0x81 #define MBX_RUN_BIU_DIAG64 0x84 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 5e92c451f96e..391ca50293f2 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -459,9 +459,45 @@ lpfc_hba_down_prep(struct lpfc_hba * phba) lpfc_els_flush_cmd(phba); lpfc_disc_flush_list(phba); + /* Disable SLI2 since we disabled interrupts */ + phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE; return (0); } +/************************************************************************/ +/* */ +/* lpfc_hba_down_post */ +/* This routine will do uninitialization after the HBA is reset */ +/* when bringing down the SLI Layer. */ +/* This routine returns 0 on success. Any other return value */ +/* indicates an error. */ +/* */ +/************************************************************************/ +int +lpfc_hba_down_post(struct lpfc_hba * phba) +{ + struct lpfc_sli *psli = &phba->sli; + struct lpfc_sli_ring *pring; + struct lpfc_dmabuf *mp, *next_mp; + int i; + + /* Cleanup preposted buffers on the ELS ring */ + pring = &psli->ring[LPFC_ELS_RING]; + list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) { + list_del(&mp->list); + pring->postbufq_cnt--; + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + } + + for (i = 0; i < psli->num_rings; i++) { + pring = &psli->ring[i]; + lpfc_sli_abort_iocb_ring(phba, pring); + } + + return 0; +} + /************************************************************************/ /* */ /* lpfc_handle_eratt */ @@ -476,20 +512,6 @@ lpfc_handle_eratt(struct lpfc_hba * phba) struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; - /* - * If a reset is sent to the HBA restore PCI configuration registers. - */ - if ( phba->hba_state == LPFC_INIT_START ) { - mdelay(1); - readl(phba->HCregaddr); /* flush */ - writel(0, phba->HCregaddr); - readl(phba->HCregaddr); /* flush */ - - /* Restore PCI cmd register */ - pci_write_config_word(phba->pcidev, - PCI_COMMAND, phba->pci_cfg_value); - } - if (phba->work_hs & HS_FFER6) { /* Re-establishing Link */ lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, @@ -516,6 +538,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba) * attempt to restart it. */ lpfc_offline(phba); + lpfc_sli_brdrestart(phba); if (lpfc_online(phba) == 0) { /* Initialize the HBA */ mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); return; @@ -532,7 +555,8 @@ lpfc_handle_eratt(struct lpfc_hba * phba) phba->work_status[0], phba->work_status[1]); lpfc_offline(phba); - + phba->hba_state = LPFC_HBA_ERROR; + lpfc_hba_down_post(phba); } } @@ -1695,6 +1719,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev) * the HBA. */ lpfc_sli_hba_down(phba); + lpfc_sli_brdrestart(phba); /* Release the irq reservation */ free_irq(phba->pcidev->irq, phba); diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 6c4b21a32c7f..df88b78707de 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -636,6 +636,17 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) phba->brd_no); } +void +lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) +{ + MAILBOX_t *mb = &pmb->mb; + + memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); + mb->mbxCommand = MBX_KILL_BOARD; + mb->mbxOwner = OWN_HOST; + return; +} + void lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) { diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 1f876328b44b..d6ffe26ae123 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -513,7 +513,9 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) case MBX_SET_MASK: case MBX_SET_SLIM: case MBX_UNREG_D_ID: + case MBX_KILL_BOARD: case MBX_CONFIG_FARP: + case MBX_BEACON: case MBX_LOAD_AREA: case MBX_RUN_BIU_DIAG64: case MBX_CONFIG_PORT: @@ -1512,98 +1514,162 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) return errcnt; } -/****************************************************************************** -* lpfc_sli_send_reset -* -* Note: After returning from this function, the HBA cannot be accessed for -* 1 ms. Since we do not wish to delay in interrupt context, it is the -* responsibility of the caller to perform the mdelay(1) and flush via readl(). -******************************************************************************/ -static int -lpfc_sli_send_reset(struct lpfc_hba * phba, uint16_t skip_post) +int +lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask) { - MAILBOX_t *swpmb; - volatile uint32_t word0; - void __iomem *to_slim; - unsigned long flags = 0; + uint32_t status; + int i = 0; + int retval = 0; - spin_lock_irqsave(phba->host->host_lock, flags); + /* Read the HBA Host Status Register */ + status = readl(phba->HSregaddr); - /* A board reset must use REAL SLIM. */ - phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE; + /* + * Check status register every 100ms for 5 retries, then every + * 500ms for 5, then every 2.5 sec for 5, then reset board and + * every 2.5 sec for 4. + * Break our of the loop if errors occurred during init. + */ + while (((status & mask) != mask) && + !(status & HS_FFERM) && + i++ < 20) { - word0 = 0; - swpmb = (MAILBOX_t *) & word0; - swpmb->mbxCommand = MBX_RESTART; - swpmb->mbxHc = 1; + if (i <= 5) + msleep(10); + else if (i <= 10) + msleep(500); + else + msleep(2500); - to_slim = phba->MBslimaddr; - writel(*(uint32_t *) swpmb, to_slim); - readl(to_slim); /* flush */ + if (i == 15) { + phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */ + lpfc_sli_brdrestart(phba); + } + /* Read the HBA Host Status Register */ + status = readl(phba->HSregaddr); + } - /* Only skip post after fc_ffinit is completed */ - if (skip_post) { - word0 = 1; /* This is really setting up word1 */ - } else { - word0 = 0; /* This is really setting up word1 */ + /* Check to see if any errors occurred during init */ + if ((status & HS_FFERM) || (i >= 20)) { + phba->hba_state = LPFC_HBA_ERROR; + retval = 1; } - to_slim = phba->MBslimaddr + sizeof (uint32_t); - writel(*(uint32_t *) swpmb, to_slim); - readl(to_slim); /* flush */ - /* Turn off parity checking and serr during the physical reset */ - pci_read_config_word(phba->pcidev, PCI_COMMAND, &phba->pci_cfg_value); - pci_write_config_word(phba->pcidev, PCI_COMMAND, - (phba->pci_cfg_value & - ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR))); + return retval; +} - writel(HC_INITFF, phba->HCregaddr); +int +lpfc_sli_brdkill(struct lpfc_hba * phba) +{ + struct lpfc_sli *psli; + LPFC_MBOXQ_t *pmb; + uint32_t status; + uint32_t ha_copy; + int retval; + int i = 0; - phba->hba_state = LPFC_INIT_START; - spin_unlock_irqrestore(phba->host->host_lock, flags); + psli = &phba->sli; - return 0; + /* Kill HBA */ + lpfc_printf_log(phba, + KERN_INFO, + LOG_SLI, + "%d:0329 Kill HBA Data: x%x x%x\n", + phba->brd_no, + phba->hba_state, + psli->sli_flag); + + if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, + GFP_ATOMIC)) == 0) { + return 1; + } + + /* Disable the error attention */ + spin_lock_irq(phba->host->host_lock); + status = readl(phba->HCregaddr); + status &= ~HC_ERINT_ENA; + writel(status, phba->HCregaddr); + readl(phba->HCregaddr); /* flush */ + spin_unlock_irq(phba->host->host_lock); + + lpfc_kill_board(phba, pmb); + pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; + retval = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); + + if (retval != MBX_SUCCESS) { + if (retval != MBX_BUSY) + mempool_free(pmb, phba->mbox_mem_pool); + return 1; + } + + mempool_free(pmb, phba->mbox_mem_pool); + + /* There is no completion for a KILL_BOARD mbox cmd. Check for an error + * attention every 100ms for 3 seconds. If we don't get ERATT after + * 3 seconds we still set HBA_ERROR state because the status of the + * board is now undefined. + */ + ha_copy = readl(phba->HAregaddr); + + while ((i++ < 30) && !(ha_copy & HA_ERATT)) { + mdelay(100); + ha_copy = readl(phba->HAregaddr); + } + + del_timer_sync(&psli->mbox_tmo); + + spin_lock_irq(phba->host->host_lock); + psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; + spin_unlock_irq(phba->host->host_lock); + + psli->mbox_active = NULL; + lpfc_hba_down_post(phba); + phba->hba_state = LPFC_HBA_ERROR; + + return (ha_copy & HA_ERATT ? 0 : 1); } -static int -lpfc_sli_brdreset(struct lpfc_hba * phba, uint16_t skip_post) +int +lpfc_sli_brdreset(struct lpfc_hba * phba) { + struct lpfc_sli *psli; struct lpfc_sli_ring *pring; + uint16_t cfg_value; int i; - struct lpfc_dmabuf *mp, *next_mp; - unsigned long flags = 0; - - lpfc_sli_send_reset(phba, skip_post); - mdelay(1); - spin_lock_irqsave(phba->host->host_lock, flags); - /* Risk the write on flush case ie no delay after the readl */ - readl(phba->HCregaddr); /* flush */ - /* Now toggle INITFF bit set by lpfc_sli_send_reset */ - writel(0, phba->HCregaddr); - readl(phba->HCregaddr); /* flush */ + psli = &phba->sli; - /* Restore PCI cmd register */ - pci_write_config_word(phba->pcidev, PCI_COMMAND, phba->pci_cfg_value); + /* Reset HBA */ + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "%d:0325 Reset HBA Data: x%x x%x\n", phba->brd_no, + phba->hba_state, psli->sli_flag); /* perform board reset */ phba->fc_eventTag = 0; phba->fc_myDID = 0; - phba->fc_prevDID = Mask_DID; + phba->fc_prevDID = 0; - /* Reset HBA */ - lpfc_printf_log(phba, - KERN_INFO, - LOG_SLI, - "%d:0325 Reset HBA Data: x%x x%x x%x\n", - phba->brd_no, - phba->hba_state, - phba->sli.sli_flag, - skip_post); + psli->sli_flag = 0; + + /* Turn off parity checking and serr during the physical reset */ + pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value); + pci_write_config_word(phba->pcidev, PCI_COMMAND, + (cfg_value & + ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR))); + + /* Now toggle INITFF bit in the Host Control Register */ + writel(HC_INITFF, phba->HCregaddr); + mdelay(1); + readl(phba->HCregaddr); /* flush */ + writel(0, phba->HCregaddr); + readl(phba->HCregaddr); /* flush */ + + /* Restore PCI cmd register */ + pci_write_config_word(phba->pcidev, PCI_COMMAND, cfg_value); /* Initialize relevant SLI info */ - for (i = 0; i < phba->sli.num_rings; i++) { - pring = &phba->sli.ring[i]; + for (i = 0; i < psli->num_rings; i++) { + pring = &psli->ring[i]; pring->flag = 0; pring->rspidx = 0; pring->next_cmdidx = 0; @@ -1611,27 +1677,62 @@ lpfc_sli_brdreset(struct lpfc_hba * phba, uint16_t skip_post) pring->cmdidx = 0; pring->missbufcnt = 0; } - spin_unlock_irqrestore(phba->host->host_lock, flags); - if (skip_post) { - mdelay(100); + phba->hba_state = LPFC_WARM_START; + return 0; +} + +int +lpfc_sli_brdrestart(struct lpfc_hba * phba) +{ + MAILBOX_t *mb; + struct lpfc_sli *psli; + uint16_t skip_post; + volatile uint32_t word0; + void __iomem *to_slim; + + spin_lock_irq(phba->host->host_lock); + + psli = &phba->sli; + + /* Restart HBA */ + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "%d:0328 Restart HBA Data: x%x x%x\n", phba->brd_no, + phba->hba_state, psli->sli_flag); + + word0 = 0; + mb = (MAILBOX_t *) &word0; + mb->mbxCommand = MBX_RESTART; + mb->mbxHc = 1; + + to_slim = phba->MBslimaddr; + writel(*(uint32_t *) mb, to_slim); + readl(to_slim); /* flush */ + + /* Only skip post after fc_ffinit is completed */ + if (phba->hba_state) { + skip_post = 1; + word0 = 1; /* This is really setting up word1 */ } else { - mdelay(2000); + skip_post = 0; + word0 = 0; /* This is really setting up word1 */ } + to_slim = (uint8_t *) phba->MBslimaddr + sizeof (uint32_t); + writel(*(uint32_t *) mb, to_slim); + readl(to_slim); /* flush */ - spin_lock_irqsave(phba->host->host_lock, flags); - /* Cleanup preposted buffers on the ELS ring */ - pring = &phba->sli.ring[LPFC_ELS_RING]; - list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) { - list_del(&mp->list); - pring->postbufq_cnt--; - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - } - spin_unlock_irqrestore(phba->host->host_lock, flags); + lpfc_sli_brdreset(phba); - for (i = 0; i < phba->sli.num_rings; i++) - lpfc_sli_abort_iocb_ring(phba, &phba->sli.ring[i]); + phba->hba_state = LPFC_INIT_START; + + spin_unlock_irq(phba->host->host_lock); + + if (skip_post) + mdelay(100); + else + mdelay(2000); + + lpfc_hba_down_post(phba); return 0; } @@ -1691,7 +1792,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) } if (i == 15) { - lpfc_sli_brdreset(phba, 0); + phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */ + lpfc_sli_brdrestart(phba); } /* Read the HBA Host Status Register */ status = readl(phba->HSregaddr); @@ -1735,8 +1837,8 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba) } while (resetcount < 2 && !done) { - phba->hba_state = 0; - lpfc_sli_brdreset(phba, 0); + phba->hba_state = LPFC_STATE_UNKNOWN; + lpfc_sli_brdrestart(phba); msleep(2500); rc = lpfc_sli_chipset_init(phba); if (rc) @@ -1920,6 +2022,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) mb = &pmbox->mb; status = MBX_SUCCESS; + if (phba->hba_state == LPFC_HBA_ERROR) { + spin_unlock_irqrestore(phba->host->host_lock, drvr_flag); + + /* Mbox command cannot issue */ + LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag) + return (MBX_NOT_FINISHED); + } + if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) { /* Polling for a mbox command when another one is already active * is not allowed in SLI. Also, the driver must have established @@ -2002,7 +2112,8 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) /* If we are not polling, we MUST be in SLI2 mode */ if (flag != MBX_POLL) { - if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) { + if (!(psli->sli_flag & LPFC_SLI2_ACTIVE) && + (mb->mbxCommand != MBX_KILL_BOARD)) { psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; spin_unlock_irqrestore(phba->host->host_lock, drvr_flag); @@ -2035,7 +2146,8 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) /* First copy command data to host SLIM area */ lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, MAILBOX_CMD_SIZE); } else { - if (mb->mbxCommand == MBX_CONFIG_PORT) { + if (mb->mbxCommand == MBX_CONFIG_PORT || + mb->mbxCommand == MBX_KILL_BOARD) { /* copy command data into host mbox for cmpl */ lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, MAILBOX_CMD_SIZE); @@ -2086,8 +2198,9 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) ha_copy = readl(phba->HAregaddr); /* Wait for command to complete */ - while (((word0 & OWN_CHIP) == OWN_CHIP) - || !(ha_copy & HA_MBATT)) { + while (((word0 & OWN_CHIP) == OWN_CHIP) || + (!(ha_copy & HA_MBATT) && + (phba->hba_state > LPFC_WARM_START))) { if (i++ >= 100) { psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; spin_unlock_irqrestore(phba->host->host_lock, @@ -2455,15 +2568,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba) spin_unlock_irqrestore(phba->host->host_lock, flags); - /* - * Provided the hba is not in an error state, reset it. It is not - * capable of IO anymore. - */ - if (phba->hba_state != LPFC_HBA_ERROR) { - phba->hba_state = LPFC_INIT_START; - lpfc_sli_brdreset(phba, 1); - } - return 1; } @@ -2976,13 +3080,6 @@ lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs) /* Clear Chip error bit */ writel(HA_ERATT, phba->HAregaddr); readl(phba->HAregaddr); /* flush */ - - /* - * Reseting the HBA is the only reliable way - * to shutdown interrupt when there is a - * ERROR. - */ - lpfc_sli_send_reset(phba, 1); } spin_lock(phba->host->host_lock); -- cgit v1.2.3-59-g8ed1b From 5024ab179c13d763f95c8391f45f22309609f479 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:28 -0500 Subject: [SCSI] lpfc 8.1.2: Added support for FAN Added support for FAN Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_disc.h | 1 + drivers/scsi/lpfc/lpfc_els.c | 123 +++++++++++++++++++++++++++---------- drivers/scsi/lpfc/lpfc_hbadisc.c | 13 ++-- drivers/scsi/lpfc/lpfc_nportdisc.c | 61 ++++++++++++------ 4 files changed, 140 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 4dfcd4eda2fc..8932b1be2b60 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -62,6 +62,7 @@ struct lpfc_nodelist { uint16_t nlp_rpi; uint16_t nlp_state; /* state transition indicator */ + uint16_t nlp_prev_state; /* state transition indicator */ uint16_t nlp_xri; /* output exchange id for RPI */ uint16_t nlp_sid; /* scsi id */ #define NLP_NO_SID 0xffff diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 70581b9eafaf..a88a1477b552 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1201,12 +1201,10 @@ lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, NLP_EVT_CMPL_LOGO); } } else { - /* Good status, call state machine */ + /* Good status, call state machine. + * This will unregister the rpi if needed. + */ lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO); - - if (ndlp->nlp_flag & NLP_DELAY_TMO) { - lpfc_unreg_rpi(phba, ndlp); - } } out: @@ -1435,8 +1433,9 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) phba = ndlp->nlp_phba; spin_lock_irq(phba->host->host_lock); - did = (uint32_t) (ndlp->nlp_DID); - cmd = (uint32_t) (ndlp->nlp_last_elscmd); + did = ndlp->nlp_DID; + cmd = ndlp->nlp_last_elscmd; + ndlp->nlp_last_elscmd = 0; if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { spin_unlock_irq(phba->host->host_lock); @@ -1453,24 +1452,28 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) break; case ELS_CMD_PLOGI: if (!lpfc_issue_els_plogi(phba, ndlp, retry)) { + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); } break; case ELS_CMD_ADISC: if (!lpfc_issue_els_adisc(phba, ndlp, retry)) { + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_ADISC_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); } break; case ELS_CMD_PRLI: if (!lpfc_issue_els_prli(phba, ndlp, retry)) { + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PRLI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); } break; case ELS_CMD_LOGO: if (!lpfc_issue_els_logo(phba, ndlp, retry)) { + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); } @@ -1630,6 +1633,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); ndlp->nlp_flag |= NLP_DELAY_TMO; + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_last_elscmd = cmd; @@ -1641,21 +1645,25 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry); return 1; case ELS_CMD_PLOGI: + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, cmdiocb->retry); return 1; case ELS_CMD_ADISC: + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_ADISC_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry); return 1; case ELS_CMD_PRLI: + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PRLI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry); return 1; case ELS_CMD_LOGO: + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry); @@ -1719,10 +1727,6 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~NLP_LOGO_ACC; - spin_unlock_irq(phba->host->host_lock); - switch (ndlp->nlp_state) { case NLP_STE_UNUSED_NODE: /* node is just allocated */ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); @@ -1776,6 +1780,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, lpfc_unreg_rpi(phba, ndlp); mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; mbox->context2 = ndlp; + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_REG_LOGIN_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_REGLOGIN_LIST); if (lpfc_sli_issue_mbox(phba, mbox, @@ -1790,6 +1795,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, mempool_free( mbox, phba->mbox_mem_pool); if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + ndlp = NULL; } } } @@ -1827,6 +1833,7 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, ELS_CMD_ACC)) == 0) { + ndlp->nlp_flag &= ~NLP_LOGO_ACC; return 1; } icmd = &elsiocb->iocb; @@ -2172,6 +2179,7 @@ lpfc_els_disc_adisc(struct lpfc_hba * phba) if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { if (ndlp->nlp_flag & NLP_NPR_ADISC) { ndlp->nlp_flag &= ~NLP_NPR_ADISC; + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_ADISC_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); @@ -2209,6 +2217,7 @@ lpfc_els_disc_plogi(struct lpfc_hba * phba) if ((ndlp->nlp_flag & NLP_NPR_2B_DISC) && (!(ndlp->nlp_flag & NLP_DELAY_TMO))) { if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, 0); @@ -2350,8 +2359,13 @@ lpfc_rscn_recovery_check(struct lpfc_hba * phba) lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RECOVERY); + + /* Make sure NLP_DELAY_TMO is NOT running + * after a device recovery event. + */ if (ndlp->nlp_flag & NLP_DELAY_TMO) { ndlp->nlp_flag &= ~NLP_DELAY_TMO; + ndlp->nlp_last_elscmd = 0; del_timer_sync(&ndlp->nlp_delayfunc); if (!list_empty(&ndlp-> els_retry_evt.evt_listp)) @@ -2503,6 +2517,7 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) } else { lpfc_nlp_init(phba, ndlp, NameServer_DID); ndlp->nlp_type |= NLP_FABRIC; + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_issue_els_plogi(phba, ndlp, 0); /* Wait for NameServer login cmpl before we can @@ -2930,6 +2945,7 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, (ndlp->nlp_state == NLP_STE_MAPPED_NODE)) { /* Log back into the node before sending the FARP. */ if (fp->Rflags & FARP_REQUEST_PLOGI) { + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, 0); @@ -2974,46 +2990,89 @@ lpfc_els_rcv_farpr(struct lpfc_hba * phba, static int lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, - struct lpfc_nodelist * ndlp) + struct lpfc_nodelist * fan_ndlp) { struct lpfc_dmabuf *pcmd; uint32_t *lp; IOCB_t *icmd; - FAN *fp; uint32_t cmd, did; + FAN *fp; + struct lpfc_nodelist *ndlp, *next_ndlp; + + /* FAN received */ + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:265 FAN received\n", + phba->brd_no); icmd = &cmdiocb->iocb; did = icmd->un.elsreq64.remoteID; - pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; - lp = (uint32_t *) pcmd->virt; + pcmd = (struct lpfc_dmabuf *)cmdiocb->context2; + lp = (uint32_t *)pcmd->virt; cmd = *lp++; - fp = (FAN *) lp; + fp = (FAN *)lp; - /* FAN received */ - - /* ACCEPT the FAN request */ - lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); + /* FAN received; Fan does not have a reply sequence */ if (phba->hba_state == LPFC_LOCAL_CFG_LINK) { - /* The discovery state machine needs to take a different - * action if this node has switched fabrics - */ - if ((memcmp(&fp->FportName, &phba->fc_fabparam.portName, - sizeof (struct lpfc_name)) != 0) - || - (memcmp(&fp->FnodeName, &phba->fc_fabparam.nodeName, - sizeof (struct lpfc_name)) != 0)) { - /* This node has switched fabrics. An FLOGI is required - * after the timeout + if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName, + sizeof(struct lpfc_name)) != 0) || + (memcmp(&phba->fc_fabparam.portName, &fp->FportName, + sizeof(struct lpfc_name)) != 0)) { + /* + * This node has switched fabrics. FLOGI is required + * Clean up the old rpi's */ + + list_for_each_entry_safe(ndlp, next_ndlp, + &phba->fc_npr_list, nlp_listp) { + + if (ndlp->nlp_type & NLP_FABRIC) { + /* + * Clean up old Fabric, Nameserver and + * other NLP_FABRIC logins + */ + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + } + else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { + /* Fail outstanding I/O now since this + * device is marked for PLOGI + */ + lpfc_unreg_rpi(phba, ndlp); + } + } + + phba->hba_state = LPFC_FLOGI; + lpfc_set_disctmo(phba); + lpfc_initial_flogi(phba); return 0; } + /* Discovery not needed, + * move the nodes to their original state. + */ + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, + nlp_listp) { - /* Start discovery */ + switch (ndlp->nlp_prev_state) { + case NLP_STE_UNMAPPED_NODE: + ndlp->nlp_prev_state = NLP_STE_NPR_NODE; + ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); + break; + + case NLP_STE_MAPPED_NODE: + ndlp->nlp_prev_state = NLP_STE_NPR_NODE; + ndlp->nlp_state = NLP_STE_MAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST); + break; + + default: + break; + } + } + + /* Start discovery - this should just do CLEAR_LA */ lpfc_disc_start(phba); } - return 0; } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 55454923029d..710efec1221f 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -309,14 +309,12 @@ lpfc_linkdown(struct lpfc_hba * phba) LPFC_MBOXQ_t *mb; int rc, i; - if (phba->hba_state == LPFC_LINK_DOWN) { - return 0; - } - psli = &phba->sli; - /* sysfs or selective reset may call this routine to clean up */ - if (phba->hba_state > LPFC_LINK_DOWN) { + if (phba->hba_state >= LPFC_LINK_DOWN) { + if (phba->hba_state == LPFC_LINK_DOWN) + return 0; + spin_lock_irq(phba->host->host_lock); phba->hba_state = LPFC_LINK_DOWN; spin_unlock_irq(phba->host->host_lock); @@ -1172,6 +1170,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) spin_lock_irq(phba->host->host_lock); nlp->nlp_flag &= ~NLP_DELAY_TMO; spin_unlock_irq(phba->host->host_lock); + nlp->nlp_last_elscmd = 0; del_timer_sync(&nlp->nlp_delayfunc); if (!list_empty(&nlp->els_retry_evt.evt_listp)) list_del_init(&nlp->els_retry_evt.evt_listp); @@ -1595,6 +1594,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) spin_unlock_irq(phba->host->host_lock); del_timer_sync(&ndlp->nlp_tmofunc); + ndlp->nlp_last_elscmd = 0; del_timer_sync(&ndlp->nlp_delayfunc); if (!list_empty(&ndlp->nodev_timeout_evt.evt_listp)) @@ -1630,6 +1630,7 @@ lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_DELAY_TMO; spin_unlock_irq(phba->host->host_lock); + ndlp->nlp_last_elscmd = 0; del_timer_sync(&ndlp->nlp_delayfunc); if (!list_empty(&ndlp->els_retry_evt.evt_listp)) list_del_init(&ndlp->els_retry_evt.evt_listp); diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index a580e1e50672..4bf232a9adc9 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -262,6 +262,7 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, /* If we are delaying issuing an ELS command, cancel it */ if (ndlp->nlp_flag & NLP_DELAY_TMO) { ndlp->nlp_flag &= ~NLP_DELAY_TMO; + ndlp->nlp_last_elscmd = 0; del_timer_sync(&ndlp->nlp_delayfunc); if (!list_empty(&ndlp->els_retry_evt.evt_listp)) list_del_init(&ndlp->els_retry_evt.evt_listp); @@ -398,16 +399,8 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, */ mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; mbox->context2 = ndlp; - ndlp->nlp_flag |= NLP_ACC_REGLOGIN; + ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI); - /* If there is an outstanding PLOGI issued, abort it before - * sending ACC rsp to PLOGI recieved. - */ - if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) { - /* software abort outstanding PLOGI */ - lpfc_els_abort(phba, ndlp, 1); - } - ndlp->nlp_flag |= NLP_RCV_PLOGI; lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); return 1; @@ -465,13 +458,14 @@ lpfc_rcv_padisc(struct lpfc_hba * phba, stat.un.b.vendorUnique = 0; lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); - ndlp->nlp_last_elscmd = (unsigned long)ELS_CMD_PLOGI; /* 1 sec timeout */ mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag |= NLP_DELAY_TMO; spin_unlock_irq(phba->host->host_lock); + ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); return 0; @@ -492,15 +486,17 @@ lpfc_rcv_logo(struct lpfc_hba * phba, if (!(ndlp->nlp_type & NLP_FABRIC) || (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { /* Only try to re-login if this is NOT a Fabric Node */ - ndlp->nlp_last_elscmd = (unsigned long)ELS_CMD_PLOGI; mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag |= NLP_DELAY_TMO; spin_unlock_irq(phba->host->host_lock); + ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); } else { + ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_UNUSED_NODE; lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); } @@ -595,6 +591,7 @@ lpfc_rcv_plogi_unused_node(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) { + ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; ndlp->nlp_state = NLP_STE_UNUSED_NODE; lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); return ndlp->nlp_state; @@ -708,10 +705,6 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba, /* software abort outstanding PLOGI */ lpfc_els_abort(phba, ndlp, 1); - mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag |= NLP_DELAY_TMO; - spin_unlock_irq(phba->host->host_lock); if (evt == NLP_EVT_RCV_LOGO) { lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); @@ -721,7 +714,12 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba, } /* Put ndlp in npr list set plogi timer for 1 sec */ - ndlp->nlp_last_elscmd = (unsigned long)ELS_CMD_PLOGI; + mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag |= NLP_DELAY_TMO; + spin_unlock_irq(phba->host->host_lock); + ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; + ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); @@ -744,6 +742,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, rspiocb = cmdiocb->context_un.rsp_iocb; if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { + /* Recovery from PLOGI collision logic */ return ndlp->nlp_state; } @@ -859,6 +858,7 @@ lpfc_device_recov_plogi_issue(struct lpfc_hba * phba, /* software abort outstanding PLOGI */ lpfc_els_abort(phba, ndlp, 1); + ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); spin_lock_irq(phba->host->host_lock); @@ -883,6 +883,7 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba, if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) { return ndlp->nlp_state; } + ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, 0); @@ -963,25 +964,29 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba, if ((irsp->ulpStatus) || (!lpfc_check_adisc(phba, ndlp, &ap->nodeName, &ap->portName))) { - ndlp->nlp_last_elscmd = (unsigned long)ELS_CMD_PLOGI; /* 1 sec timeout */ mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag |= NLP_DELAY_TMO; spin_unlock_irq(phba->host->host_lock); + ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; memset(&ndlp->nlp_nodename, 0, sizeof (struct lpfc_name)); memset(&ndlp->nlp_portname, 0, sizeof (struct lpfc_name)); + ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); lpfc_unreg_rpi(phba, ndlp); return ndlp->nlp_state; } + if (ndlp->nlp_type & NLP_FCP_TARGET) { + ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; ndlp->nlp_state = NLP_STE_MAPPED_NODE; lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST); } else { + ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); } @@ -1008,6 +1013,7 @@ lpfc_device_recov_adisc_issue(struct lpfc_hba * phba, /* software abort outstanding ADISC */ lpfc_els_abort(phba, ndlp, 1); + ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); spin_lock_irq(phba->host->host_lock); @@ -1103,14 +1109,15 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba, phba->brd_no, did, mb->mbxStatus, phba->hba_state); + /* Put ndlp in npr list set plogi timer for 1 sec */ mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag |= NLP_DELAY_TMO; spin_unlock_irq(phba->host->host_lock); + ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; lpfc_issue_els_logo(phba, ndlp, 0); - /* Put ndlp in npr list set plogi timer for 1 sec */ - ndlp->nlp_last_elscmd = (unsigned long)ELS_CMD_PLOGI; + ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); return ndlp->nlp_state; @@ -1120,10 +1127,12 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba, /* Only if we are not a fabric nport do we issue PRLI */ if (!(ndlp->nlp_type & NLP_FABRIC)) { + ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; ndlp->nlp_state = NLP_STE_PRLI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); lpfc_issue_els_prli(phba, ndlp, 0); } else { + ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); } @@ -1144,6 +1153,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) { + ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); spin_lock_irq(phba->host->host_lock); @@ -1233,6 +1243,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba, irsp = &rspiocb->iocb; if (irsp->ulpStatus) { + ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); return ndlp->nlp_state; @@ -1251,6 +1262,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba, ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; } + ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; ndlp->nlp_state = NLP_STE_MAPPED_NODE; lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST); return ndlp->nlp_state; @@ -1308,6 +1320,7 @@ lpfc_device_recov_prli_issue(struct lpfc_hba * phba, /* software abort outstanding PRLI */ lpfc_els_abort(phba, ndlp, 1); + ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); spin_lock_irq(phba->host->host_lock); @@ -1381,6 +1394,7 @@ static uint32_t lpfc_device_recov_unmap_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) { + ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; @@ -1462,6 +1476,7 @@ lpfc_device_recov_mapped_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) { + ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE; ndlp->nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); spin_lock_irq(phba->host->host_lock); @@ -1494,6 +1509,7 @@ lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba, /* send PLOGI immediately, move to PLOGI issue state */ if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { + ndlp->nlp_prev_state = NLP_STE_NPR_NODE; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, 0); @@ -1521,10 +1537,12 @@ lpfc_rcv_prli_npr_node(struct lpfc_hba * phba, spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; spin_unlock_irq(phba->host->host_lock); + ndlp->nlp_prev_state = NLP_STE_NPR_NODE; ndlp->nlp_state = NLP_STE_ADISC_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); lpfc_issue_els_adisc(phba, ndlp, 0); } else { + ndlp->nlp_prev_state = NLP_STE_NPR_NODE; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, 0); @@ -1559,10 +1577,12 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba, if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { if (ndlp->nlp_flag & NLP_NPR_ADISC) { + ndlp->nlp_prev_state = NLP_STE_NPR_NODE; ndlp->nlp_state = NLP_STE_ADISC_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); lpfc_issue_els_adisc(phba, ndlp, 0); } else { + ndlp->nlp_prev_state = NLP_STE_NPR_NODE; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp, 0); @@ -1592,6 +1612,7 @@ lpfc_rcv_prlo_npr_node(struct lpfc_hba * phba, ndlp->nlp_flag |= NLP_DELAY_TMO; ndlp->nlp_flag &= ~NLP_NPR_ADISC; spin_unlock_irq(phba->host->host_lock); + ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; } else { spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; @@ -1681,6 +1702,7 @@ lpfc_device_recov_npr_node(struct lpfc_hba * phba, if (!list_empty(&ndlp->els_retry_evt.evt_listp)) list_del_init(&ndlp->els_retry_evt.evt_listp); spin_unlock_irq(phba->host->host_lock); + ndlp->nlp_last_elscmd = 0; del_timer_sync(&ndlp->nlp_delayfunc); return ndlp->nlp_state; } @@ -1905,6 +1927,5 @@ lpfc_disc_state_machine(struct lpfc_hba * phba, } if (rc == NLP_STE_FREED_NODE) return NLP_STE_FREED_NODE; - ndlp->nlp_state = rc; return rc; } -- cgit v1.2.3-59-g8ed1b From 082c02667d98d3060f63382e7a695d58d4c8c5e4 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:30 -0500 Subject: [SCSI] lpfc 8.1.2: Make lpfc_els_rsp_rps_acc and lpfc_els_rsp_rpl_acc static Make lpfc_els_rsp_rps_acc and lpfc_els_rsp_rpl_acc static Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index a88a1477b552..74ad15d0a2ba 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -2668,7 +2668,7 @@ lpfc_els_rcv_lirr(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, return 0; } -void +static void lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) { struct lpfc_sli *psli; @@ -2795,7 +2795,7 @@ lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, return 0; } -int +static int lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize, struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp) { -- cgit v1.2.3-59-g8ed1b From 2fe165b65089925292122e9772321738627f325c Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:31 -0500 Subject: [SCSI] lpfc 8.1.2: Code style changes for Discovery code Code style changes for Discovery code Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_ct.c | 2 +- drivers/scsi/lpfc/lpfc_els.c | 40 ++++++-------- drivers/scsi/lpfc/lpfc_hbadisc.c | 103 +++++++++++++++++-------------------- drivers/scsi/lpfc/lpfc_nportdisc.c | 24 ++++----- 4 files changed, 74 insertions(+), 95 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 98b94c0eb597..eab087bf826e 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 74ad15d0a2ba..6e1a5162851c 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -717,8 +717,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { rc = NLP_STE_FREED_NODE; - } - else { + } else { rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_PLOGI); } @@ -784,7 +783,7 @@ lpfc_issue_els_plogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, - ELS_CMD_PLOGI); + ELS_CMD_PLOGI); if (!elsiocb) return 1; @@ -861,8 +860,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { goto out; - } - else { + } else { lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI); } @@ -1195,8 +1193,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { goto out; - } - else { + } else { lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO); } @@ -2201,7 +2198,7 @@ lpfc_els_disc_adisc(struct lpfc_hba * phba) phba->fc_flag &= ~FC_NLP_MORE; spin_unlock_irq(phba->host->host_lock); } - return(sentadisc); + return sentadisc; } int @@ -2238,7 +2235,7 @@ lpfc_els_disc_plogi(struct lpfc_hba * phba) phba->fc_flag &= ~FC_NLP_MORE; spin_unlock_irq(phba->host->host_lock); } - return(sentplogi); + return sentplogi; } int @@ -2591,8 +2588,7 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, mempool_free( mbox, phba->mbox_mem_pool); } return 1; - } - else if (rc > 0) { /* greater than */ + } else if (rc > 0) { /* greater than */ spin_lock_irq(phba->host->host_lock); phba->fc_flag |= FC_PT2PT_PLOGI; spin_unlock_irq(phba->host->host_lock); @@ -2755,8 +2751,8 @@ lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, RPS *rps; struct ls_rjt stat; - if((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && - (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { + if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && + (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { stat.un.b.lsRjtRsvd0 = 0; stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; @@ -2866,8 +2862,8 @@ lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, RPL *rpl; struct ls_rjt stat; - if((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && - (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { + if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && + (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { stat.un.b.lsRjtRsvd0 = 0; stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; @@ -2886,8 +2882,7 @@ lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, ((maxsize == 0) || ((maxsize * sizeof(uint32_t)) >= sizeof(RPL_RSP)))) { cmdsize = sizeof(uint32_t) + sizeof(RPL_RSP); - } - else { + } else { cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t); } lpfc_els_rsp_rpl_acc(phba, cmdsize, cmdiocb, ndlp); @@ -3032,8 +3027,7 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, * other NLP_FABRIC logins */ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - } - else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { + } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { /* Fail outstanding I/O now since this * device is marked for PLOGI */ @@ -3228,8 +3222,7 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) spin_unlock_irq(phba->host->host_lock); (piocb->iocb_cmpl) (phba, piocb, piocb); spin_lock_irq(phba->host->host_lock); - } - else + } else lpfc_sli_release_iocbq(phba, piocb); } @@ -3253,8 +3246,7 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) spin_unlock_irq(phba->host->host_lock); (piocb->iocb_cmpl) (phba, piocb, piocb); spin_lock_irq(phba->host->host_lock); - } - else + } else lpfc_sli_release_iocbq(phba, piocb); } spin_unlock_irq(phba->host->host_lock); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 710efec1221f..b2aec79eed80 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -108,7 +108,7 @@ lpfc_work_list_done(struct lpfc_hba * phba) evt_listp); spin_unlock_irq(phba->host->host_lock); free_evt = 1; - switch(evtp->evt) { + switch (evtp->evt) { case LPFC_EVT_NODEV_TMO: ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); lpfc_process_nodev_timeout(phba, ndlp); @@ -173,13 +173,13 @@ lpfc_work_done(struct lpfc_hba * phba) work_hba_events=phba->work_hba_events; spin_unlock_irq(phba->host->host_lock); - if(ha_copy & HA_ERATT) + if (ha_copy & HA_ERATT) lpfc_handle_eratt(phba); - if(ha_copy & HA_MBATT) + if (ha_copy & HA_MBATT) lpfc_sli_handle_mb_event(phba); - if(ha_copy & HA_LATT) + if (ha_copy & HA_LATT) lpfc_handle_latt(phba); if (work_hba_events & WORKER_DISC_TMO) @@ -357,8 +357,7 @@ lpfc_linkdown(struct lpfc_hba * phba) /* Check config parameter use-adisc or FCP-2 */ if ((rc != NLP_STE_FREED_NODE) && (phba->cfg_use_adisc == 0) && - !(ndlp->nlp_fcp_info & - NLP_FCP_2_DEVICE)) { + !(ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE)) { /* We know we will have to relogin, so * unreglogin the rpi right now to fail * any outstanding I/Os quickly. @@ -398,7 +397,7 @@ lpfc_linkdown(struct lpfc_hba * phba) lpfc_can_disctmo(phba); /* Must process IOCBs on all rings to handle ABORTed I/Os */ - return (0); + return 0; } static int @@ -497,7 +496,7 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_els_disc_plogi(phba); } - if(!phba->num_disc_nodes) { + if (!phba->num_disc_nodes) { spin_lock_irq(phba->host->host_lock); phba->fc_flag &= ~FC_NDISC_ACTIVE; spin_unlock_irq(phba->host->host_lock); @@ -685,7 +684,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); spin_lock_irq(phba->host->host_lock); - switch(la->UlnkSpeed) { + switch (la->UlnkSpeed) { case LA_1GHZ_LINK: phba->fc_linkspeed = LA_1GHZ_LINK; break; @@ -1115,12 +1114,11 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) psli = &phba->sli; /* Sanity check to ensure we are not moving to / from the same list */ - if ((nlp->nlp_flag & NLP_LIST_MASK) == list) { + if ((nlp->nlp_flag & NLP_LIST_MASK) == list) if (list != NLP_NO_LIST) - return(0); - } + return 0; - switch(nlp->nlp_flag & NLP_LIST_MASK) { + switch (nlp->nlp_flag & NLP_LIST_MASK) { case NLP_NO_LIST: /* Not on any list */ break; case NLP_UNUSED_LIST: @@ -1190,7 +1188,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) phba->brd_no, nlp->nlp_DID, list, nlp->nlp_flag); - switch(list) { + switch (list) { case NLP_NO_LIST: /* No list, just remove it */ lpfc_nlp_remove(phba, nlp); /* as node removed - stop further transport calls */ @@ -1287,10 +1285,10 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list); phba->fc_npr_cnt++; - if (!(nlp->nlp_flag & NLP_NODEV_TMO)) { + if (!(nlp->nlp_flag & NLP_NODEV_TMO)) mod_timer(&nlp->nlp_tmofunc, jiffies + HZ * phba->cfg_nodev_tmo); - } + spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= NLP_NODEV_TMO; nlp->nlp_flag &= ~NLP_RCV_PLOGI; @@ -1342,7 +1340,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) } } } - return (0); + return 0; } /* @@ -1401,7 +1399,7 @@ lpfc_can_disctmo(struct lpfc_hba * phba) phba->brd_no, phba->hba_state, phba->fc_flag, phba->fc_plogi_cnt, phba->fc_adisc_cnt); - return (0); + return 0; } /* @@ -1422,11 +1420,11 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba, switch (icmd->ulpCommand) { case CMD_GEN_REQUEST64_CR: if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi) - return (1); + return 1; case CMD_ELS_REQUEST64_CR: case CMD_XMIT_ELS_RSP64_CX: if (iocb->context1 == (uint8_t *) ndlp) - return (1); + return 1; } } else if (pring->ringno == psli->ip_ring) { @@ -1434,15 +1432,15 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba, /* Skip match check if waiting to relogin to FCP target */ if ((ndlp->nlp_type & NLP_FCP_TARGET) && (ndlp->nlp_flag & NLP_DELAY_TMO)) { - return (0); + return 0; } if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi) { - return (1); + return 1; } } else if (pring->ringno == psli->next_ring) { } - return (0); + return 0; } /* @@ -1503,7 +1501,7 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) } } - return (0); + return 0; } /* @@ -1604,7 +1602,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) lpfc_unreg_rpi(phba, ndlp); - return (0); + return 0; } /* @@ -1640,12 +1638,11 @@ lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag |= NLP_DELAY_REMOVE; spin_unlock_irq(phba->host->host_lock); - } - else { + } else { lpfc_freenode(phba, ndlp); mempool_free( ndlp, phba->nlp_mem_pool); } - return(0); + return 0; } static int @@ -1656,20 +1653,20 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) D_ID matchdid; if (did == Bcast_DID) - return (0); + return 0; if (ndlp->nlp_DID == 0) { - return (0); + return 0; } /* First check for Direct match */ if (ndlp->nlp_DID == did) - return (1); + return 1; /* Next check for area/domain identically equals 0 match */ mydid.un.word = phba->fc_myDID; if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) { - return (0); + return 0; } matchdid.un.word = did; @@ -1680,9 +1677,9 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) if ((ndlpdid.un.b.domain == 0) && (ndlpdid.un.b.area == 0)) { if (ndlpdid.un.b.id) - return (1); + return 1; } - return (0); + return 0; } matchdid.un.word = ndlp->nlp_DID; @@ -1691,11 +1688,11 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) if ((matchdid.un.b.domain == 0) && (matchdid.un.b.area == 0)) { if (matchdid.un.b.id) - return (1); + return 1; } } } - return (0); + return 0; } /* Search for a nodelist entry on a specific list */ @@ -1720,7 +1717,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - return (ndlp); + return ndlp; } } } @@ -1741,7 +1738,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - return (ndlp); + return ndlp; } } } @@ -1763,7 +1760,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - return (ndlp); + return ndlp; } } } @@ -1785,7 +1782,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - return (ndlp); + return ndlp; } } } @@ -1807,7 +1804,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - return (ndlp); + return ndlp; } } } @@ -1829,7 +1826,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - return (ndlp); + return ndlp; } } } @@ -1851,7 +1848,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - return (ndlp); + return ndlp; } } } @@ -1873,7 +1870,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); - return (ndlp); + return ndlp; } } } @@ -1923,17 +1920,15 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) del_timer_sync(&ndlp->nlp_delayfunc); spin_lock_irq(phba->host->host_lock); if (!list_empty(&ndlp->els_retry_evt. - evt_listp)) + evt_listp)) list_del_init(&ndlp->els_retry_evt. - evt_listp); + evt_listp); } - } - else { + } else { ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; ndlp = NULL; } - } - else { + } else { flg = ndlp->nlp_flag & NLP_LIST_MASK; if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST)) return NULL; @@ -2084,8 +2079,7 @@ lpfc_disc_start(struct lpfc_hba * phba) spin_lock_irq(phba->host->host_lock); phba->fc_flag &= ~FC_RSCN_MODE; spin_unlock_irq(phba->host->host_lock); - } - else + } else lpfc_els_handle_rscn(phba); } } @@ -2268,8 +2262,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) if (ndlp->nlp_type & NLP_FABRIC) { /* Clean up the ndlp on Fabric connections */ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - } - else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { + } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { /* Fail outstanding IO now since device * is marked for PLOGI. */ @@ -2544,7 +2537,7 @@ lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) for (i = 0; i < ARRAY_SIZE(lists); i++ ) list_for_each_entry(ndlp, lists[i], nlp_listp) if (ndlp->nlp_rpi == rpi) - return (ndlp); + return ndlp; return NULL; } diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 4bf232a9adc9..dba11d94d27d 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -150,8 +150,7 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba * phba, lp = (uint32_t *) prsp->virt; ptr = (void *)((uint8_t *)lp + sizeof(uint32_t)); } - } - else { + } else { /* Force ulpStatus error since we are returning NULL ptr */ if (!(irsp->ulpStatus)) { irsp->ulpStatus = IOSTAT_LOCAL_REJECT; @@ -301,12 +300,10 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, /* Start discovery - this should just do CLEAR_LA */ lpfc_disc_start(phba); - } - else { + } else { lpfc_initial_flogi(phba); } - } - else { + } else { stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, @@ -354,7 +351,7 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; /* no need to reg_login if we are already in one of these states */ - switch(ndlp->nlp_state) { + switch (ndlp->nlp_state) { case NLP_STE_NPR_NODE: if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) break; @@ -444,8 +441,7 @@ lpfc_rcv_padisc(struct lpfc_hba * phba, (lpfc_check_adisc(phba, ndlp, pnn, ppn))) { if (cmd == ELS_CMD_ADISC) { lpfc_els_rsp_adisc_acc(phba, cmdiocb, ndlp); - } - else { + } else { lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0); } @@ -672,8 +668,7 @@ lpfc_rcv_plogi_plogi_issue(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS; lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); - } - else { + } else { lpfc_rcv_plogi(phba, ndlp, cmdiocb); } /* if our portname was less */ @@ -708,8 +703,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba, if (evt == NLP_EVT_RCV_LOGO) { lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); - } - else { + } else { lpfc_issue_els_logo(phba, ndlp, 0); } @@ -803,7 +797,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, * execute first, queue this command to * be processed later. */ - switch(ndlp->nlp_DID) { + switch (ndlp->nlp_DID) { case NameServer_DID: mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login; -- cgit v1.2.3-59-g8ed1b From 367c27134a94dce351080ae66ab87a1b296d1e64 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:32 -0500 Subject: [SCSI] lpfc 8.1.2: Allow turning on internal loop-back mode Allow turning on internal loop-back mode Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_attr.c | 3 ++- drivers/scsi/lpfc/lpfc_mbox.c | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index e7aca3c4b26e..998c863fdc7e 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -616,6 +616,7 @@ LPFC_ATTR_RW(nodev_tmo, 30, 0, 255, /* # lpfc_topology: link topology for init link # 0x0 = attempt loop mode then point-to-point +# 0x01 = internal loopback mode # 0x02 = attempt point-to-point mode only # 0x04 = attempt loop mode only # 0x06 = attempt point-to-point mode then loop @@ -623,7 +624,7 @@ LPFC_ATTR_RW(nodev_tmo, 30, 0, 255, # Set loop mode if you want to run as an NL_Port. Value range is [0,0x6]. # Default value is 0. */ -LPFC_ATTR_R(topology, 0, 0, 6, "Select Fibre Channel topology"); +LPFC_ATTR_RW(topology, 0, 0, 6, "Select Fibre Channel topology"); /* # lpfc_link_speed: Link speed selection for initializing the Fibre Channel diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index df88b78707de..c585e2b2e589 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -195,6 +195,9 @@ lpfc_init_link(struct lpfc_hba * phba, mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT; mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER; break; + case FLAGS_LOCAL_LB: + mb->un.varInitLnk.link_flags = FLAGS_LOCAL_LB; + break; } /* NEW_FEATURE -- cgit v1.2.3-59-g8ed1b From 25594c6b84ff96e156d8cf8168d68f50e07e8318 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:34 -0500 Subject: [SCSI] lpfc 8.1.2: Code cleanup of lpfc_mbx_cmpl_config_link Code cleanup of lpfc_mbx_cmpl_config_link Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hbadisc.c | 107 ++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index b2aec79eed80..aa58ff0e3218 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -538,80 +538,59 @@ out: } static void -lpfc_mbx_cmpl_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) +lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { - struct lpfc_sli *psli; - MAILBOX_t *mb; - - psli = &phba->sli; - mb = &pmb->mb; - /* Check for error */ - if (mb->mbxStatus) { - /* CONFIG_LINK mbox error state */ - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "%d:0306 CONFIG_LINK mbxStatus error x%x " - "HBA state x%x\n", - phba->brd_no, mb->mbxStatus, phba->hba_state); + struct lpfc_sli *psli = &phba->sli; + int rc; - lpfc_linkdown(phba); - phba->hba_state = LPFC_HBA_ERROR; + if (pmb->mb.mbxStatus) goto out; - } - if (phba->hba_state == LPFC_LOCAL_CFG_LINK) { - if (phba->fc_topology == TOPOLOGY_LOOP) { - /* If we are public loop and L bit was set */ - if ((phba->fc_flag & FC_PUBLIC_LOOP) && - !(phba->fc_flag & FC_LBIT)) { - /* Need to wait for FAN - use discovery timer - * for timeout. hba_state is identically - * LPFC_LOCAL_CFG_LINK while waiting for FAN - */ - lpfc_set_disctmo(phba); - mempool_free( pmb, phba->mbox_mem_pool); - return; - } + mempool_free(pmb, phba->mbox_mem_pool); + + if (phba->fc_topology == TOPOLOGY_LOOP && + phba->fc_flag & FC_PUBLIC_LOOP && + !(phba->fc_flag & FC_LBIT)) { + /* Need to wait for FAN - use discovery timer + * for timeout. hba_state is identically + * LPFC_LOCAL_CFG_LINK while waiting for FAN + */ + lpfc_set_disctmo(phba); + return; } - /* Start discovery by sending a FLOGI hba_state is identically - * LPFC_FLOGI while waiting for FLOGI cmpl - */ - phba->hba_state = LPFC_FLOGI; - lpfc_set_disctmo(phba); - lpfc_initial_flogi(phba); - mempool_free( pmb, phba->mbox_mem_pool); - return; - } - if (phba->hba_state == LPFC_FABRIC_CFG_LINK) { - mempool_free( pmb, phba->mbox_mem_pool); - return; - } + /* Start discovery by sending a FLOGI. hba_state is identically + * LPFC_FLOGI while waiting for FLOGI cmpl + */ + phba->hba_state = LPFC_FLOGI; + lpfc_set_disctmo(phba); + lpfc_initial_flogi(phba); + return; out: - /* CONFIG_LINK bad hba state */ - lpfc_printf_log(phba, - KERN_ERR, - LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, + "%d:0306 CONFIG_LINK mbxStatus error x%x " + "HBA state x%x\n", + phba->brd_no, pmb->mb.mbxStatus, phba->hba_state); + + lpfc_linkdown(phba); + + phba->hba_state = LPFC_HBA_ERROR; + + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "%d:0200 CONFIG_LINK bad hba state x%x\n", phba->brd_no, phba->hba_state); - if (phba->hba_state != LPFC_CLEAR_LA) { - lpfc_clear_la(phba, pmb); - pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la; - if (lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)) - == MBX_NOT_FINISHED) { - mempool_free( pmb, phba->mbox_mem_pool); - lpfc_disc_flush_list(phba); - psli->ring[(psli->ip_ring)].flag &= - ~LPFC_STOP_IOCB_EVENT; - psli->ring[(psli->fcp_ring)].flag &= - ~LPFC_STOP_IOCB_EVENT; - psli->ring[(psli->next_ring)].flag &= - ~LPFC_STOP_IOCB_EVENT; - phba->hba_state = LPFC_HBA_READY; - } - } else { - mempool_free( pmb, phba->mbox_mem_pool); + lpfc_clear_la(phba, pmb); + pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la; + rc = lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)); + if (rc == MBX_NOT_FINISHED) { + mempool_free(pmb, phba->mbox_mem_pool); + lpfc_disc_flush_list(phba); + psli->ring[(psli->ip_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; + psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; + psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; + phba->hba_state = LPFC_HBA_READY; } return; } @@ -765,7 +744,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) if (cfglink_mbox) { phba->hba_state = LPFC_LOCAL_CFG_LINK; lpfc_config_link(phba, cfglink_mbox); - cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_config_link; + cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; lpfc_sli_issue_mbox(phba, cfglink_mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); } -- cgit v1.2.3-59-g8ed1b From 8189fd19ac5ee517f276982c5947ef7f565841ad Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:35 -0500 Subject: [SCSI] lpfc 8.1.2: Fixed module parameter descriptions. Fixed module parameter descriptions. Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_attr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 998c863fdc7e..ab49379b6abe 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -664,10 +664,10 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support"); # is 0. Default value of cr_count is 1. The cr_count feature is disabled if # cr_delay is set to 0. */ -LPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an" +LPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an " "interrupt response is generated"); -LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an" +LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an " "interrupt response is generated"); /* @@ -683,7 +683,7 @@ LPFC_ATTR_RW(fdmi_on, 0, 0, 2, "Enable FDMI support"); # Specifies the maximum number of ELS cmds we can have outstanding (for # discovery). Value range is [1,64]. Default value = 32. */ -LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands" +LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands " "during discovery"); /* -- cgit v1.2.3-59-g8ed1b From 0c6ac8efa83a465b950fe4dca096cd7ff1937f67 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:36 -0500 Subject: [SCSI] lpfc 8.1.2: Fix panic caused by HBA resets and target side cable pulls Fix panic caused by HBA resets and target side cable pulls Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_scsi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index fd7540ea4e19..094f18f1fa05 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -467,7 +467,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, sdev = cmd->device; cmd->scsi_done(cmd); - if (!result && + if (!result && pnode != NULL && ((jiffies - pnode->last_ramp_up_time) > LPFC_Q_RAMP_UP_INTERVAL * HZ) && ((jiffies - pnode->last_q_full_time) > @@ -495,7 +495,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, * Check for queue full. If the lun is reporting queue full, then * back off the lun queue depth to prevent target overloads. */ - if (result == SAM_STAT_TASK_SET_FULL) { + if (result == SAM_STAT_TASK_SET_FULL && pnode != NULL) { pnode->last_q_full_time = jiffies; shost_for_each_device(tmp_sdev, sdev->host) { -- cgit v1.2.3-59-g8ed1b From 50eba24f2e0576910a3e23dced769b7be7f3683e Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:38 -0500 Subject: [SCSI] lpfc 8.1.2: Modify RSCN handling to unregister rpis on lost FCP_TARGETs immediately Modify RSCN handling to unregister rpis on lost FCP_TARGETs immediately Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_ct.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index eab087bf826e..0c982bbc4c77 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -323,6 +323,7 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size) struct lpfc_sli_ct_request *Response = (struct lpfc_sli_ct_request *) mp->virt; struct lpfc_nodelist *ndlp = NULL; + struct lpfc_nodelist *next_ndlp; struct lpfc_dmabuf *mlast, *next_mp; uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType; uint32_t Did; @@ -391,8 +392,36 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size) nsout1: list_del(&head); - /* Here we are finished in the case RSCN */ + /* + * The driver has cycled through all Nports in the RSCN payload. + * Complete the handling by cleaning up and marking the + * current driver state. + */ if (phba->hba_state == LPFC_HBA_READY) { + + /* + * Switch ports that connect a loop of multiple targets need + * special consideration. The driver wants to unregister the + * rpi only on the target that was pulled from the loop. On + * RSCN, the driver wants to rediscover an NPort only if the + * driver flagged it as NLP_NPR_2B_DISC. Provided adisc is + * not enabled and the NPort is not capable of retransmissions + * (FC Tape) prevent timing races with the scsi error handler by + * unregistering the Nport's RPI. This action causes all + * outstanding IO to flush back to the midlayer. + */ + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, + nlp_listp) { + if (!(ndlp->nlp_flag & NLP_NPR_2B_DISC) && + (lpfc_rscn_payload_check(phba, ndlp->nlp_DID))) { + if ((phba->cfg_use_adisc == 0) && + !(ndlp->nlp_fcp_info & + NLP_FCP_2_DEVICE)) { + lpfc_unreg_rpi(phba, ndlp); + ndlp->nlp_flag &= ~NLP_NPR_ADISC; + } + } + } lpfc_els_flush_rscn(phba); spin_lock_irq(phba->host->host_lock); phba->fc_flag |= FC_RSCN_MODE; /* we are still in RSCN mode */ -- cgit v1.2.3-59-g8ed1b From 3ef0b47ee498ea183bffd9b3b4a1eef757fef4ba Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 19:25:39 -0500 Subject: [SCSI] lpfc 8.1.2: Change version number to 8.1.2 Change version number to 8.1.2 Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index fa681a934ffe..dad013c771a1 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -18,12 +18,12 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.1.1" +#define LPFC_DRIVER_VERSION "8.1.2" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ LPFC_DRIVER_VERSION -#define LPFC_COPYRIGHT "Copyright(c) 2004-2005 Emulex. All rights reserved." +#define LPFC_COPYRIGHT "Copyright(c) 2004-2006 Emulex. All rights reserved." #define DFC_API_VERSION "0.0.0" -- cgit v1.2.3-59-g8ed1b From c92f222e1f14588171e63b550ca8c85fa9130061 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 1 Mar 2006 09:02:49 -0600 Subject: [SCSI] mptspi: Add transport class Domain Validation This is the first half of a patch to add the generic domain validation to mptspi. It also creates a secondary "virtual" channel for raid component devices since these are now exported with no_uld_attach. What Eric and I would have really liked is to export all physical components on channel 0 and all raid components on channel 1. Unfortunately, this would result in device renumbering on platforms with mixed RAID/Physical devices which was considered unacceptable for userland stability reasons. Still to be done is to plug back the extra parameter setting and DV pieces on reset and hotplug. Signed-off-by: James Bottomley --- drivers/message/fusion/Kconfig | 1 + drivers/message/fusion/mptbase.c | 72 +- drivers/message/fusion/mptbase.h | 14 +- drivers/message/fusion/mptscsih.c | 2402 ++----------------------------------- drivers/message/fusion/mptscsih.h | 11 +- drivers/message/fusion/mptspi.c | 733 ++++++++++- 6 files changed, 774 insertions(+), 2459 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index e67cf15e9c39..bbc229852881 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -9,6 +9,7 @@ config FUSION_SPI tristate "Fusion MPT ScsiHost drivers for SPI" depends on PCI && SCSI select FUSION + select SCSI_SPI_ATTRS ---help--- SCSI HOST support for a parallel SCSI host adapters. diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 642a61b6d0a4..f2721ea30aa7 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1120,65 +1120,6 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) return -1; } -int -mpt_alt_ioc_wait(MPT_ADAPTER *ioc) -{ - int loop_count = 30 * 4; /* Wait 30 seconds */ - int status = -1; /* -1 means failed to get board READY */ - - do { - spin_lock(&ioc->initializing_hba_lock); - if (ioc->initializing_hba_lock_flag == 0) { - ioc->initializing_hba_lock_flag=1; - spin_unlock(&ioc->initializing_hba_lock); - status = 0; - break; - } - spin_unlock(&ioc->initializing_hba_lock); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - } while (--loop_count); - - return status; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery - * @ioc: Pointer to MPT adapter structure - * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. - * - * This routine performs all the steps necessary to bring the IOC - * to a OPERATIONAL state. - * - * Special Note: This function was added with spin lock's so as to allow - * the dv(domain validation) work thread to succeed on the other channel - * that maybe occuring at the same time when this function is called. - * Without this lock, the dv would fail when message frames were - * requested during hba bringup on the alternate ioc. - */ -static int -mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag) -{ - int r; - - if(ioc->alt_ioc) { - if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0)) - return r; - } - - r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, - CAN_SLEEP); - - if(ioc->alt_ioc) { - spin_lock(&ioc->alt_ioc->initializing_hba_lock); - ioc->alt_ioc->initializing_hba_lock_flag=0; - spin_unlock(&ioc->alt_ioc->initializing_hba_lock); - } - -return r; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_attach - Install a PCI intelligent MPT adapter. @@ -1482,7 +1423,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) */ mpt_detect_bound_ports(ioc, pdev); - if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){ + if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, + CAN_SLEEP)) != 0){ printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n", ioc->name, r); @@ -1629,7 +1571,6 @@ mpt_resume(struct pci_dev *pdev) MPT_ADAPTER *ioc = pci_get_drvdata(pdev); u32 device_state = pdev->current_state; int recovery_state; - int ii; printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", @@ -1643,14 +1584,6 @@ mpt_resume(struct pci_dev *pdev) CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); ioc->active = 1; - /* F/W not running */ - if(!CHIPREG_READ32(&ioc->chip->Doorbell)) { - /* enable domain validation flags */ - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV; - } - } - printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", ioc->name, @@ -6435,7 +6368,6 @@ EXPORT_SYMBOL(mpt_read_ioc_pg_3); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mptbase_sas_persist_operation); -EXPORT_SYMBOL(mpt_alt_ioc_wait); EXPORT_SYMBOL(mptbase_GetFcPortPage0); diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 723d54300953..f4197a9962a3 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -331,6 +331,7 @@ typedef struct _SYSIF_REGS * VirtDevice - FC LUN device or SCSI target device */ typedef struct _VirtTarget { + struct scsi_target *starget; u8 tflags; u8 ioc_id; u8 target_id; @@ -343,7 +344,6 @@ typedef struct _VirtTarget { u8 type; /* byte 0 of Inquiry data */ u32 num_luns; u32 luns[8]; /* Max LUNs is 256 */ - u8 inq_data[8]; } VirtTarget; typedef struct _VirtDevice { @@ -364,6 +364,7 @@ typedef struct _VirtDevice { #define MPT_TARGET_FLAGS_Q_YES 0x08 #define MPT_TARGET_FLAGS_VALID_56 0x10 #define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20 +#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x40 /* * /proc/mpt interface @@ -447,13 +448,6 @@ typedef struct _mpt_ioctl_events { * Substructure to store SCSI specific configuration page data */ /* dvStatus defines: */ -#define MPT_SCSICFG_NEGOTIATE 0x01 /* Negotiate on next IO */ -#define MPT_SCSICFG_NEED_DV 0x02 /* Schedule DV */ -#define MPT_SCSICFG_DV_PENDING 0x04 /* DV on this physical id pending */ -#define MPT_SCSICFG_DV_NOT_DONE 0x08 /* DV has not been performed */ -#define MPT_SCSICFG_BLK_NEGO 0x10 /* WriteSDP1 with WDTR and SDTR disabled */ -#define MPT_SCSICFG_RELOAD_IOC_PG3 0x20 /* IOC Pg 3 data is obsolete */ - /* Args passed to writeSDP1: */ #define MPT_SCSICFG_USE_NVRAM 0x01 /* WriteSDP1 using NVRAM */ #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ /* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ @@ -464,7 +458,6 @@ typedef struct _SpiCfgData { IOCPage4_t *pIocPg4; /* SEP devices addressing */ dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */ int IocPg4Sz; /* IOCPage4 size */ - u8 dvStatus[MPT_MAX_SCSI_DEVICES]; u8 minSyncFactor; /* 0xFF if async */ u8 maxSyncOffset; /* 0 if async */ u8 maxBusWidth; /* 0 if narrow, 1 if wide */ @@ -474,13 +467,11 @@ typedef struct _SpiCfgData { u8 sdp0version; /* SDP0 version */ u8 sdp0length; /* SDP0 length */ u8 dvScheduled; /* 1 if scheduled */ - u8 forceDv; /* 1 to force DV scheduling */ u8 noQas; /* Disable QAS for this adapter */ u8 Saf_Te; /* 1 to force all Processors as * SAF-TE if Inquiry data length * is too short to check for SAF-TE */ - u8 mpt_dv; /* command line option: enhanced=1, basic=0 */ u8 bus_reset; /* 1 to allow bus reset */ u8 rsvd[1]; }SpiCfgData; @@ -1033,7 +1024,6 @@ extern int mpt_findImVolumes(MPT_ADAPTER *ioc); extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); -extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc); /* * Public data decl's... diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 4fee6befc93d..ff83e21e1000 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -114,21 +114,6 @@ typedef struct _internal_cmd { u8 rsvd; } INTERNAL_CMD; -typedef struct _negoparms { - u8 width; - u8 offset; - u8 factor; - u8 flags; -} NEGOPARMS; - -typedef struct _dv_parameters { - NEGOPARMS max; - NEGOPARMS now; - u8 cmd; - u8 id; - u16 pad1; -} DVPARAMETERS; - /* * Other private/forward protos... */ @@ -149,28 +134,12 @@ static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 tar int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); -static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen); -static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, char byte56); -static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags); -static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc); -static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags); +static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); +static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); -static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice); -static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); - -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION -static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); -static void mptscsih_domainValidation(void *hd); -static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id); -static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target); -static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); -static void mptscsih_fillbuf(char *buffer, int size, int index, int width); -static void mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id); -static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc); -#endif void mptscsih_remove(struct pci_dev *); void mptscsih_shutdown(struct pci_dev *); @@ -181,16 +150,6 @@ int mptscsih_resume(struct pci_dev *pdev); #define SNS_LEN(scp) sizeof((scp)->sense_buffer) -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION -/* - * Domain Validation task structure - */ -static DEFINE_SPINLOCK(dvtaskQ_lock); -static int dvtaskQ_active = 0; -static int dvtaskQ_release = 0; -static struct work_struct dvTaskQ_task; -#endif - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_add_sge - Place a simple SGE at address pAddr. @@ -687,9 +646,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) */ sc->result = DID_RESET << 16; - /* GEM Workaround. */ - if (ioc->bus_type == SPI) - mptscsih_no_negotiate(hd, sc); break; case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ @@ -1005,10 +961,6 @@ mptscsih_remove(struct pci_dev *pdev) MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct Scsi_Host *host = ioc->sh; MPT_SCSI_HOST *hd; -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - int count; - unsigned long flags; -#endif int sz1; if(!host) { @@ -1021,25 +973,6 @@ mptscsih_remove(struct pci_dev *pdev) if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL) return; -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - /* Check DV thread active */ - count = 10 * HZ; - spin_lock_irqsave(&dvtaskQ_lock, flags); - if (dvtaskQ_active) { - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - while(dvtaskQ_active && --count) - schedule_timeout_interruptible(1); - } else { - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - } - if (!count) - printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n"); -#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) - else - printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count); -#endif -#endif - mptscsih_shutdown(pdev); sz1=0; @@ -1127,21 +1060,6 @@ mptscsih_resume(struct pci_dev *pdev) if(!hd) return 0; -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - { - unsigned long lflags; - spin_lock_irqsave(&dvtaskQ_lock, lflags); - if (!dvtaskQ_active) { - dvtaskQ_active = 1; - spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - INIT_WORK(&dvTaskQ_task, - mptscsih_domainValidation, (void *) hd); - schedule_work(&dvTaskQ_task); - } else { - spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - } - } -#endif return 0; } @@ -1317,6 +1235,13 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return SCSI_MLQUEUE_HOST_BUSY; } + if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && + mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) { + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + return 0; + } + /* * Put together a MPT SCSI request... */ @@ -1363,7 +1288,10 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) pScsiReq->TargetID = (u8) vdev->target_id; pScsiReq->Bus = vdev->bus_id; pScsiReq->ChainOffset = 0; - pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; + if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) + pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; + else + pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; pScsiReq->CDBLength = SCpnt->cmd_len; pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; pScsiReq->Reserved = 0; @@ -1411,49 +1339,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) hd->ScsiLookup[my_idx] = SCpnt; SCpnt->host_scribble = NULL; -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - if (hd->ioc->bus_type == SPI) { - int dvStatus = hd->ioc->spi_data.dvStatus[vdev->target_id]; - int issueCmd = 1; - - if (dvStatus || hd->ioc->spi_data.forceDv) { - - if ((dvStatus & MPT_SCSICFG_NEED_DV) || - (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) { - unsigned long lflags; - /* Schedule DV if necessary */ - spin_lock_irqsave(&dvtaskQ_lock, lflags); - if (!dvtaskQ_active) { - dvtaskQ_active = 1; - spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd); - - schedule_work(&dvTaskQ_task); - } else { - spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - } - hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV; - } - - /* Trying to do DV to this target, extend timeout. - * Wait to issue until flag is clear - */ - if (dvStatus & MPT_SCSICFG_DV_PENDING) { - mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ); - issueCmd = 0; - } - - /* Set the DV flags. - */ - if (dvStatus & MPT_SCSICFG_DV_NOT_DONE) - mptscsih_set_dvflags(hd, SCpnt); - - if (!issueCmd) - goto fail; - } - } -#endif - mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", hd->ioc->name, SCpnt, mf, my_idx)); @@ -2218,6 +2103,24 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, return 0; } +int +mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) +{ + int i; + + if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3) + return -ENXIO; + + for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) { + if (physdiskid == + hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) + return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; + } + + return -ENXIO; +} +EXPORT_SYMBOL(mptscsih_raid_id_to_num); + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * OS entry point to allow host driver to alloc memory @@ -2233,6 +2136,7 @@ mptscsih_target_alloc(struct scsi_target *starget) if (!vtarget) return -ENOMEM; starget->hostdata = vtarget; + vtarget->starget = starget; return 0; } @@ -2266,6 +2170,7 @@ mptscsih_slave_alloc(struct scsi_device *sdev) starget = scsi_target(sdev); vtarget = starget->hostdata; + vdev->vtarget = vtarget; if (vtarget->num_luns == 0) { @@ -2274,14 +2179,11 @@ mptscsih_slave_alloc(struct scsi_device *sdev) vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; vtarget->target_id = sdev->id; vtarget->bus_id = sdev->channel; - if (hd->ioc->bus_type == SPI) { - if (hd->ioc->raid_data.isRaid & (1 << sdev->id)) { - vtarget->raidVolume = 1; - ddvtprintk((KERN_INFO + if (hd->ioc->bus_type == SPI && sdev->channel == 0 && + hd->ioc->raid_data.isRaid & (1 << sdev->id)) { + vtarget->raidVolume = 1; + ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", sdev->id)); - } - } else { - vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; } } vtarget->num_luns++; @@ -2321,19 +2223,6 @@ mptscsih_slave_destroy(struct scsi_device *sdev) vtarget->luns[0] &= ~(1 << vdevice->lun); vtarget->num_luns--; if (vtarget->num_luns == 0) { - mptscsih_negotiate_to_asyn_narrow(hd, vdevice); - if (hd->ioc->bus_type == SPI) { - if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) { - hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; - } else { - hd->ioc->spi_data.dvStatus[vtarget->target_id] = - MPT_SCSICFG_NEGOTIATE; - if (!hd->negoNvram) { - hd->ioc->spi_data.dvStatus[vtarget->target_id] |= - MPT_SCSICFG_DV_NOT_DONE; - } - } - } hd->Targets[sdev->id] = NULL; } mptscsih_synchronize_cache(hd, vdevice); @@ -2362,18 +2251,13 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) vtarget = starget->hostdata; if (hd->ioc->bus_type == SPI) { - if (vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { - if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) - max_depth = 1; - else if (((vtarget->inq_data[0] & 0x1f) == 0x00) && - (vtarget->minSyncFactor <= MPT_ULTRA160 )) - max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; - else - max_depth = MPT_SCSI_CMD_PER_DEV_LOW; - } else { - /* error case - No Inq. Data */ + if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) max_depth = 1; - } + else if (sdev->type == TYPE_DISK && + vtarget->minSyncFactor <= MPT_ULTRA160) + max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; + else + max_depth = MPT_SCSI_CMD_PER_DEV_LOW; } else max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; @@ -2427,8 +2311,7 @@ mptscsih_slave_configure(struct scsi_device *sdev) lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */ indexed_lun = (vdevice->lun % 32); vtarget->luns[lun_index] |= (1 << indexed_lun); - mptscsih_initTarget(hd, vtarget, sdev->lun, sdev->inquiry, - sdev->inquiry_len ); + mptscsih_initTarget(hd, vtarget, sdev); mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); dsprintk((MYIOC_s_INFO_FMT @@ -2597,10 +2480,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) /* 4. Renegotiate to all devices, if SPI */ - if (ioc->bus_type == SPI) { - dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n")); - mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM); - } /* 5. Enable new commands to be posted */ @@ -2624,13 +2503,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) hd->cmdPtr = NULL; } - /* 7. SPI: Set flag to force DV and re-read IOC Page 3 - */ - if (ioc->bus_type == SPI) { - ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; - ddvtprintk(("Set reload IOC Pg3 Flag\n")); - } - /* 7. FC: Rescan for blocked rports which might have returned. */ else if (ioc->bus_type == FC) { @@ -2699,18 +2571,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) break; case MPI_EVENT_INTEGRATED_RAID: /* 0B */ - { -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - pMpiEventDataRaid_t pRaidEventData = - (pMpiEventDataRaid_t) pEvReply->Data; - /* Domain Validation Needed */ - if (ioc->bus_type == SPI && - pRaidEventData->ReasonCode == - MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) - mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum); -#endif break; - } case MPI_EVENT_NONE: /* 00 */ case MPI_EVENT_LOG_DATA: /* 01 */ @@ -2729,9 +2590,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) * mptscsih_initTarget - Target, LUN alloc/free functionality. * @hd: Pointer to MPT_SCSI_HOST structure * @vtarget: per target private data - * @lun: SCSI LUN id - * @data: Pointer to data - * @dlen: Number of INQUIRY bytes + * @sdev: SCSI device * * NOTE: It's only SAFE to call this routine if data points to * sane & valid STANDARD INQUIRY data! @@ -2741,98 +2600,46 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) * */ static void -mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen) +mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, + struct scsi_device *sdev) { - SpiCfgData *pSpi; - char data_56; - int inq_len; - dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd)); - /* - * If the peripheral qualifier filter is enabled then if the target reports a 0x1 - * (i.e. The targer is capable of supporting the specified peripheral device type - * on this logical unit; however, the physical device is not currently connected - * to this logical unit) it will be converted to a 0x3 (i.e. The target is not - * capable of supporting a physical device on this logical unit). This is to work - * around a bug in th emid-layer in some distributions in which the mid-layer will - * continue to try to communicate to the LUN and evntually create a dummy LUN. - */ - if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0)) - data[0] |= 0x40; - /* Is LUN supported? If so, upper 2 bits will be 0 * in first byte of inquiry data. */ - if (data[0] & 0xe0) + if (sdev->inq_periph_qual != 0) return; if (vtarget == NULL) return; - if (data) - vtarget->type = data[0]; + vtarget->type = sdev->type; if (hd->ioc->bus_type != SPI) return; - if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { + if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { /* Treat all Processors as SAF-TE if * command line option is set */ vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); - }else if ((data[0] == TYPE_PROCESSOR) && + }else if ((sdev->type == TYPE_PROCESSOR) && !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { - if ( dlen > 49 ) { - vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; - if ( data[44] == 'S' && - data[45] == 'A' && - data[46] == 'F' && - data[47] == '-' && - data[48] == 'T' && - data[49] == 'E' ) { + if (sdev->inquiry_len > 49 ) { + if (sdev->inquiry[44] == 'S' && + sdev->inquiry[45] == 'A' && + sdev->inquiry[46] == 'F' && + sdev->inquiry[47] == '-' && + sdev->inquiry[48] == 'T' && + sdev->inquiry[49] == 'E' ) { vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); } } } - if (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { - inq_len = dlen < 8 ? dlen : 8; - memcpy (vtarget->inq_data, data, inq_len); - /* If have not done DV, set the DV flag. - */ - pSpi = &hd->ioc->spi_data; - if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) { - if (pSpi->dvStatus[vtarget->target_id] & MPT_SCSICFG_DV_NOT_DONE) - pSpi->dvStatus[vtarget->target_id] |= MPT_SCSICFG_NEED_DV; - } - vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; - - data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */ - if (dlen > 56) { - if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) { - /* Update the target capabilities - */ - data_56 = data[56]; - vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56; - } - } - mptscsih_setTargetNegoParms(hd, vtarget, data_56); - } else { - /* Initial Inquiry may not request enough data bytes to - * obtain byte 57. DV will; if target doesn't return - * at least 57 bytes, data[56] will be zero. */ - if (dlen > 56) { - if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) { - /* Update the target capabilities - */ - data_56 = data[56]; - vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56; - mptscsih_setTargetNegoParms(hd, vtarget, data_56); - } - } - } + mptscsih_setTargetNegoParms(hd, vtarget, sdev); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2842,66 +2649,51 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, * */ static void -mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) +mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, + struct scsi_device *sdev) { SpiCfgData *pspi_data = &hd->ioc->spi_data; int id = (int) target->target_id; int nvram; - VirtTarget *vtarget; - int ii; u8 width = MPT_NARROW; u8 factor = MPT_ASYNC; u8 offset = 0; - u8 version, nfactor; + u8 nfactor; u8 noQas = 1; target->negoFlags = pspi_data->noQas; - /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine - * support. If available, default QAS to off and allow enabling. - * If not available, default QAS to on, turn off for non-disks. - */ + /* noQas == 0 => device supports QAS. */ - /* Set flags based on Inquiry data - */ - version = target->inq_data[2] & 0x07; - if (version < 2) { + if (sdev->scsi_level < SCSI_2) { width = 0; factor = MPT_ULTRA2; offset = pspi_data->maxSyncOffset; target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; } else { - if (target->inq_data[7] & 0x20) { + if (scsi_device_wide(sdev)) { width = 1; } - if (target->inq_data[7] & 0x10) { + if (scsi_device_sync(sdev)) { factor = pspi_data->minSyncFactor; - if (target->tflags & MPT_TARGET_FLAGS_VALID_56) { - /* bits 2 & 3 show Clocking support */ - if ((byte56 & 0x0C) == 0) + if (!scsi_device_dt(sdev)) factor = MPT_ULTRA2; + else { + if (!scsi_device_ius(sdev) && + !scsi_device_qas(sdev)) + factor = MPT_ULTRA160; else { - if ((byte56 & 0x03) == 0) - factor = MPT_ULTRA160; - else { - factor = MPT_ULTRA320; - if (byte56 & 0x02) - { - ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id)); - noQas = 0; - } - if (target->inq_data[0] == TYPE_TAPE) { - if (byte56 & 0x01) - target->negoFlags |= MPT_TAPE_NEGO_IDP; - } + factor = MPT_ULTRA320; + if (scsi_device_qas(sdev)) { + ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id)); + noQas = 0; } + if (sdev->type == TYPE_TAPE && + scsi_device_ius(sdev)) + target->negoFlags |= MPT_TAPE_NEGO_IDP; } - } else { - ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id)); - noQas = 0; } - offset = pspi_data->maxSyncOffset; /* If RAID, never disable QAS @@ -2919,7 +2711,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) } } - if ( (target->inq_data[7] & 0x02) == 0) { + if (!sdev->tagged_supported) { target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; } @@ -2977,55 +2769,18 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) if ( factor > MPT_ULTRA320 ) noQas = 0; - /* GEM, processor WORKAROUND - */ - if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) { - target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); - pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; - } else { - if (noQas && (pspi_data->noQas == 0)) { - pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; - target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - - /* Disable QAS in a mixed configuration case - */ - - ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); - for (ii = 0; ii < id; ii++) { - if ( (vtarget = hd->Targets[ii]) ) { - vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - mptscsih_writeSDP1(hd, 0, ii, vtarget->negoFlags); - } - } - } - } + if (noQas && (pspi_data->noQas == 0)) { + pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; + target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - /* Write SDP1 on this I/O to this target */ - if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) { - ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id)); - mptscsih_writeSDP1(hd, 0, id, hd->negoNvram); - pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE; - } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) { - ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id)); - mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO); - pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO; + /* Disable QAS in a mixed configuration case + */ + + ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); } } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * If no Target, bus reset on 1st I/O. Set the flag to - * prevent any future negotiations to this device. - */ -static void -mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc) -{ - VirtDevice *vdev; - - if ((vdev = sc->device->hostdata) != NULL) - hd->ioc->spi_data.dvStatus[vdev->target_id] |= MPT_SCSICFG_BLK_NEGO; - return; -} /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -3076,207 +2831,6 @@ mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, return; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_writeSDP1 - write SCSI Device Page 1 - * @hd: Pointer to a SCSI Host Strucutre - * @portnum: IOC port number - * @target_id: writeSDP1 for single ID - * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO - * - * Return: -EFAULT if read of config page header fails - * or 0 if success. - * - * Remark: If a target has been found, the settings from the - * target structure are used, else the device is set - * to async/narrow. - * - * Remark: Called during init and after a FW reload. - * Remark: We do not wait for a return, write pages sequentially. - */ -static int -mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) -{ - MPT_ADAPTER *ioc = hd->ioc; - Config_t *pReq; - SCSIDevicePage1_t *pData; - VirtTarget *vtarget=NULL; - MPT_FRAME_HDR *mf; - dma_addr_t dataDma; - u16 req_idx; - u32 frameOffset; - u32 requested, configuration, flagsLength; - int ii, nvram; - int id = 0, maxid = 0; - u8 width; - u8 factor; - u8 offset; - u8 bus = 0; - u8 negoFlags; - u8 maxwidth, maxoffset, maxfactor; - - if (ioc->spi_data.sdp1length == 0) - return 0; - - if (flags & MPT_SCSICFG_ALL_IDS) { - id = 0; - maxid = ioc->sh->max_id - 1; - } else if (ioc->sh) { - id = target_id; - maxid = min_t(int, id, ioc->sh->max_id - 1); - } - - for (; id <= maxid; id++) { - - if (id == ioc->pfacts[portnum].PortSCSIID) - continue; - - /* Use NVRAM to get adapter and target maximums - * Data over-riden by target structure information, if present - */ - maxwidth = ioc->spi_data.maxBusWidth; - maxoffset = ioc->spi_data.maxSyncOffset; - maxfactor = ioc->spi_data.minSyncFactor; - if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { - nvram = ioc->spi_data.nvram[id]; - - if (maxwidth) - maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; - - if (maxoffset > 0) { - maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; - if (maxfactor == 0) { - /* Key for async */ - maxfactor = MPT_ASYNC; - maxoffset = 0; - } else if (maxfactor < ioc->spi_data.minSyncFactor) { - maxfactor = ioc->spi_data.minSyncFactor; - } - } else - maxfactor = MPT_ASYNC; - } - - /* Set the negotiation flags. - */ - negoFlags = ioc->spi_data.noQas; - if (!maxwidth) - negoFlags |= MPT_TARGET_NO_NEGO_WIDE; - - if (!maxoffset) - negoFlags |= MPT_TARGET_NO_NEGO_SYNC; - - if (flags & MPT_SCSICFG_USE_NVRAM) { - width = maxwidth; - factor = maxfactor; - offset = maxoffset; - } else { - width = 0; - factor = MPT_ASYNC; - offset = 0; - //negoFlags = 0; - //negoFlags = MPT_TARGET_NO_NEGO_SYNC; - } - - /* If id is not a raid volume, get the updated - * transmission settings from the target structure. - */ - if (hd->Targets && (vtarget = hd->Targets[id]) && !vtarget->raidVolume) { - width = vtarget->maxWidth; - factor = vtarget->minSyncFactor; - offset = vtarget->maxOffset; - negoFlags = vtarget->negoFlags; - } - -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - /* Force to async and narrow if DV has not been executed - * for this ID - */ - if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) { - width = 0; - factor = MPT_ASYNC; - offset = 0; - } -#endif - - if (flags & MPT_SCSICFG_BLK_NEGO) - negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; - - mptscsih_setDevicePage1Flags(width, factor, offset, - &requested, &configuration, negoFlags); - dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", - target_id, width, factor, offset, negoFlags, requested, configuration)); - - /* Get a MF for this command. - */ - if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { - dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n", - ioc->name)); - return -EAGAIN; - } - - ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n", - hd->ioc->name, mf, id, requested, configuration)); - - - /* Set the request and the data pointers. - * Request takes: 36 bytes (32 bit SGE) - * SCSI Device Page 1 requires 16 bytes - * 40 + 16 <= size of SCSI IO Request = 56 bytes - * and MF size >= 64 bytes. - * Place data at end of MF. - */ - pReq = (Config_t *)mf; - - req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t); - - pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset); - dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset; - - /* Complete the request frame (same for all requests). - */ - pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - pReq->Reserved = 0; - pReq->ChainOffset = 0; - pReq->Function = MPI_FUNCTION_CONFIG; - pReq->ExtPageLength = 0; - pReq->ExtPageType = 0; - pReq->MsgFlags = 0; - for (ii=0; ii < 8; ii++) { - pReq->Reserved2[ii] = 0; - } - pReq->Header.PageVersion = ioc->spi_data.sdp1version; - pReq->Header.PageLength = ioc->spi_data.sdp1length; - pReq->Header.PageNumber = 1; - pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - pReq->PageAddress = cpu_to_le32(id | (bus << 8 )); - - /* Add a SGE to the config request. - */ - flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4; - - mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); - - /* Set up the common data portion - */ - pData->Header.PageVersion = pReq->Header.PageVersion; - pData->Header.PageLength = pReq->Header.PageLength; - pData->Header.PageNumber = pReq->Header.PageNumber; - pData->Header.PageType = pReq->Header.PageType; - pData->RequestedParameters = cpu_to_le32(requested); - pData->Reserved = 0; - pData->Configuration = cpu_to_le32(configuration); - - dprintk((MYIOC_s_INFO_FMT - "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n", - ioc->name, id, (id | (bus<<8)), - requested, configuration)); - - mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); - } - - return 0; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* mptscsih_writeIOCPage4 - write IOC Page 4 * @hd: Pointer to a SCSI Host Structure @@ -3465,6 +3019,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) completionCode = MPT_SCANDV_GOOD; else completionCode = MPT_SCANDV_SOME_ERROR; + memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense)); } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { u8 *sense_data; @@ -3578,78 +3133,6 @@ mptscsih_timer_expired(unsigned long data) return; } -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_do_raid - Format and Issue a RAID volume request message. - * @hd: Pointer to scsi host structure - * @action: What do be done. - * @id: Logical target id. - * @bus: Target locations bus. - * - * Returns: < 0 on a fatal error - * 0 on success - * - * Remark: Wait to return until reply processed by the ISR. - */ -static int -mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io) -{ - MpiRaidActionRequest_t *pReq; - MPT_FRAME_HDR *mf; - int in_isr; - - in_isr = in_interrupt(); - if (in_isr) { - dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n", - hd->ioc->name)); - return -EPERM; - } - - /* Get and Populate a free Frame - */ - if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { - ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", - hd->ioc->name)); - return -EAGAIN; - } - pReq = (MpiRaidActionRequest_t *)mf; - pReq->Action = action; - pReq->Reserved1 = 0; - pReq->ChainOffset = 0; - pReq->Function = MPI_FUNCTION_RAID_ACTION; - pReq->VolumeID = io->id; - pReq->VolumeBus = io->bus; - pReq->PhysDiskNum = io->physDiskNum; - pReq->MsgFlags = 0; - pReq->Reserved2 = 0; - pReq->ActionDataWord = 0; /* Reserved for this action */ - //pReq->ActionDataSGE = 0; - - mpt_add_sge((char *)&pReq->ActionDataSGE, - MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); - - ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", - hd->ioc->name, action, io->id)); - - hd->pLocal = NULL; - hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ - hd->scandv_wait_done = 0; - - /* Save cmd pointer, for resource free if timeout or - * FW reload occurs - */ - hd->cmdPtr = mf; - - add_timer(&hd->timer); - mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); - wait_event(hd->scandv_waitq, hd->scandv_wait_done); - - if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD)) - return -1; - - return 0; -} -#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** @@ -3901,93 +3384,6 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) return rc; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_negotiate_to_asyn_narrow - Restore devices to default state - * @hd: Pointer to a SCSI HOST structure - * @vtarget: per device private data - * - * Uses the ISR, but with special processing. - * MUST be single-threaded. - * - */ -static void -mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice) -{ - VirtTarget *vtarget = vdevice->vtarget; - MPT_ADAPTER *ioc= hd->ioc; - SCSIDevicePage1_t *pcfg1Data; - CONFIGPARMS cfg; - dma_addr_t cfg1_dma_addr; - ConfigPageHeader_t header; - int id; - int requested, configuration, data,i; - u8 flags, factor; - - if ((ioc->bus_type != SPI) || - (!vdevice->configured_lun)) - return; - - if (!ioc->spi_data.sdp1length) - return; - - pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev, - ioc->spi_data.sdp1length * 4, &cfg1_dma_addr); - - if (pcfg1Data == NULL) - return; - - header.PageVersion = ioc->spi_data.sdp1version; - header.PageLength = ioc->spi_data.sdp1length; - header.PageNumber = 1; - header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - cfg.cfghdr.hdr = &header; - cfg.physAddr = cfg1_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfg.dir = 1; - cfg.timeout = 0; - - if (vtarget->raidVolume && ioc->raid_data.pIocPg3) { - for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { - id = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID; - flags = hd->ioc->spi_data.noQas; - if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { - data = hd->ioc->spi_data.nvram[id]; - if (data & MPT_NVRAM_WIDE_DISABLE) - flags |= MPT_TARGET_NO_NEGO_WIDE; - factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; - if ((factor == 0) || (factor == MPT_ASYNC)) - flags |= MPT_TARGET_NO_NEGO_SYNC; - } - mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, - &configuration, flags); - dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC " - "offset=0 negoFlags=%x request=%x config=%x\n", - id, flags, requested, configuration)); - pcfg1Data->RequestedParameters = cpu_to_le32(requested); - pcfg1Data->Reserved = 0; - pcfg1Data->Configuration = cpu_to_le32(configuration); - cfg.pageAddr = (vtarget->bus_id<<8) | id; - mpt_config(hd->ioc, &cfg); - } - } else { - flags = vtarget->negoFlags; - mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, - &configuration, flags); - dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC " - "offset=0 negoFlags=%x request=%x config=%x\n", - vtarget->target_id, flags, requested, configuration)); - pcfg1Data->RequestedParameters = cpu_to_le32(requested); - pcfg1Data->Reserved = 0; - pcfg1Data->Configuration = cpu_to_le32(configuration); - cfg.pageAddr = (vtarget->bus_id<<8) | vtarget->target_id; - mpt_config(hd->ioc, &cfg); - } - - if (pcfg1Data) - pci_free_consistent(ioc->pcidev, header.PageLength * 4, pcfg1Data, cfg1_dma_addr); -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks. @@ -4018,1633 +3414,11 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) iocmd.id = vdevice->target_id; iocmd.lun = (u8)vdevice->lun; - if ((vdevice->vtarget->type & TYPE_DISK) && + if ((vdevice->vtarget->type == TYPE_DISK) && (vdevice->configured_lun)) mptscsih_do_cmd(hd, &iocmd); } -/* Search IOC page 3 to determine if this is hidden physical disk - */ -static int -mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) -{ - int i; - - if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) - return 0; - - for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { - if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) - return 1; - } - - return 0; -} - -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_domainValidation - Top level handler for domain validation. - * @hd: Pointer to MPT_SCSI_HOST structure. - * - * Uses the ISR, but with special processing. - * Called from schedule, should not be in interrupt mode. - * While thread alive, do dv for all devices needing dv - * - * Return: None. - */ -static void -mptscsih_domainValidation(void *arg) -{ - MPT_SCSI_HOST *hd; - MPT_ADAPTER *ioc; - unsigned long flags; - int id, maxid, dvStatus, did; - int ii, isPhysDisk; - - spin_lock_irqsave(&dvtaskQ_lock, flags); - dvtaskQ_active = 1; - if (dvtaskQ_release) { - dvtaskQ_active = 0; - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - return; - } - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - - /* For this ioc, loop through all devices and do dv to each device. - * When complete with this ioc, search through the ioc list, and - * for each scsi ioc found, do dv for all devices. Exit when no - * device needs dv. - */ - did = 1; - while (did) { - did = 0; - list_for_each_entry(ioc, &ioc_list, list) { - spin_lock_irqsave(&dvtaskQ_lock, flags); - if (dvtaskQ_release) { - dvtaskQ_active = 0; - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - return; - } - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - - msleep(250); - - /* DV only to SPI adapters */ - if (ioc->bus_type != SPI) - continue; - - /* Make sure everything looks ok */ - if (ioc->sh == NULL) - continue; - - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd == NULL) - continue; - - if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) { - mpt_read_ioc_pg_3(ioc); - if (ioc->raid_data.pIocPg3) { - Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; - int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; - - while (numPDisk) { - if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE) - ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; - - pPDisk++; - numPDisk--; - } - } - ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3; - } - - maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES); - - for (id = 0; id < maxid; id++) { - spin_lock_irqsave(&dvtaskQ_lock, flags); - if (dvtaskQ_release) { - dvtaskQ_active = 0; - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - return; - } - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - dvStatus = hd->ioc->spi_data.dvStatus[id]; - - if (dvStatus & MPT_SCSICFG_NEED_DV) { - did++; - hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING; - hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV; - - msleep(250); - - /* If hidden phys disk, block IO's to all - * raid volumes - * else, process normally - */ - isPhysDisk = mptscsih_is_phys_disk(ioc, id); - if (isPhysDisk) { - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - if (hd->ioc->raid_data.isRaid & (1 << ii)) { - hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING; - } - } - } - - if(mpt_alt_ioc_wait(hd->ioc)!=0) { - ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n", - hd->ioc->name)); - continue; - } - - if (mptscsih_doDv(hd, 0, id) == 1) { - /* Untagged device was busy, try again - */ - hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV; - hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING; - } else { - /* DV is complete. Clear flags. - */ - hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING); - } - - spin_lock(&hd->ioc->initializing_hba_lock); - hd->ioc->initializing_hba_lock_flag=0; - spin_unlock(&hd->ioc->initializing_hba_lock); - - if (isPhysDisk) { - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - if (hd->ioc->raid_data.isRaid & (1 << ii)) { - hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING; - } - } - } - - if (hd->ioc->spi_data.noQas) - mptscsih_qas_check(hd, id); - } - } - } - } - - spin_lock_irqsave(&dvtaskQ_lock, flags); - dvtaskQ_active = 0; - spin_unlock_irqrestore(&dvtaskQ_lock, flags); - - return; -} - -/* Write SDP1 if no QAS has been enabled - */ -static void -mptscsih_qas_check(MPT_SCSI_HOST *hd, int id) -{ - VirtTarget *vtarget; - int ii; - - if (hd->Targets == NULL) - return; - - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - if (ii == id) - continue; - - if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0) - continue; - - vtarget = hd->Targets[ii]; - - if ((vtarget != NULL) && (!vtarget->raidVolume)) { - if ((vtarget->negoFlags & hd->ioc->spi_data.noQas) == 0) { - vtarget->negoFlags |= hd->ioc->spi_data.noQas; - dnegoprintk(("writeSDP1: id=%d flags=0\n", id)); - mptscsih_writeSDP1(hd, 0, ii, 0); - } - } else { - if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) { - dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id)); - mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM); - } - } - } - return; -} - - - -#define MPT_GET_NVRAM_VALS 0x01 -#define MPT_UPDATE_MAX 0x02 -#define MPT_SET_MAX 0x04 -#define MPT_SET_MIN 0x08 -#define MPT_FALLBACK 0x10 -#define MPT_SAVE 0x20 - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_doDv - Perform domain validation to a target. - * @hd: Pointer to MPT_SCSI_HOST structure. - * @portnum: IOC port number. - * @target: Physical ID of this target - * - * Uses the ISR, but with special processing. - * MUST be single-threaded. - * Test will exit if target is at async & narrow. - * - * Return: None. - */ -static int -mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) -{ - MPT_ADAPTER *ioc = hd->ioc; - VirtTarget *vtarget; - SCSIDevicePage1_t *pcfg1Data; - SCSIDevicePage0_t *pcfg0Data; - u8 *pbuf1; - u8 *pbuf2; - u8 *pDvBuf; - dma_addr_t dvbuf_dma = -1; - dma_addr_t buf1_dma = -1; - dma_addr_t buf2_dma = -1; - dma_addr_t cfg1_dma_addr = -1; - dma_addr_t cfg0_dma_addr = -1; - ConfigPageHeader_t header1; - ConfigPageHeader_t header0; - DVPARAMETERS dv; - INTERNAL_CMD iocmd; - CONFIGPARMS cfg; - int dv_alloc = 0; - int rc, sz = 0; - int bufsize = 0; - int dataBufSize = 0; - int echoBufSize = 0; - int notDone; - int patt; - int repeat; - int retcode = 0; - int nfactor = MPT_ULTRA320; - char firstPass = 1; - char doFallback = 0; - char readPage0; - char bus, lun; - char inq0 = 0; - - if (ioc->spi_data.sdp1length == 0) - return 0; - - if (ioc->spi_data.sdp0length == 0) - return 0; - - /* If multiple buses are used, require that the initiator - * id be the same on all buses. - */ - if (id == ioc->pfacts[0].PortSCSIID) - return 0; - - lun = 0; - bus = (u8) bus_number; - ddvtprintk((MYIOC_s_NOTE_FMT - "DV started: bus=%d, id=%d dv @ %p\n", - ioc->name, bus, id, &dv)); - - /* Prep DV structure - */ - memset (&dv, 0, sizeof(DVPARAMETERS)); - dv.id = id; - - /* Populate tmax with the current maximum - * transfer parameters for this target. - * Exit if narrow and async. - */ - dv.cmd = MPT_GET_NVRAM_VALS; - mptscsih_dv_parms(hd, &dv, NULL); - - /* Prep SCSI IO structure - */ - iocmd.id = id; - iocmd.bus = bus; - iocmd.lun = lun; - iocmd.flags = 0; - iocmd.physDiskNum = -1; - iocmd.rsvd = iocmd.rsvd2 = 0; - - vtarget = hd->Targets[id]; - - /* Use tagged commands if possible. - */ - if (vtarget) { - if (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) - iocmd.flags |= MPT_ICFLAG_TAGGED_CMD; - else { - if (hd->ioc->facts.FWVersion.Word < 0x01000600) - return 0; - - if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) && - (hd->ioc->facts.FWVersion.Word < 0x01010B00)) - return 0; - } - } - - /* Prep cfg structure - */ - cfg.pageAddr = (bus<<8) | id; - cfg.cfghdr.hdr = NULL; - - /* Prep SDP0 header - */ - header0.PageVersion = ioc->spi_data.sdp0version; - header0.PageLength = ioc->spi_data.sdp0length; - header0.PageNumber = 0; - header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - - /* Prep SDP1 header - */ - header1.PageVersion = ioc->spi_data.sdp1version; - header1.PageLength = ioc->spi_data.sdp1length; - header1.PageNumber = 1; - header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - - if (header0.PageLength & 1) - dv_alloc = (header0.PageLength * 4) + 4; - - dv_alloc += (2048 + (header1.PageLength * 4)); - - pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma); - if (pDvBuf == NULL) - return 0; - - sz = 0; - pbuf1 = (u8 *)pDvBuf; - buf1_dma = dvbuf_dma; - sz +=1024; - - pbuf2 = (u8 *) (pDvBuf + sz); - buf2_dma = dvbuf_dma + sz; - sz +=1024; - - pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz); - cfg0_dma_addr = dvbuf_dma + sz; - sz += header0.PageLength * 4; - - /* 8-byte alignment - */ - if (header0.PageLength & 1) - sz += 4; - - pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz); - cfg1_dma_addr = dvbuf_dma + sz; - - /* Skip this ID? Set cfg.cfghdr.hdr to force config page write - */ - { - SpiCfgData *pspi_data = &hd->ioc->spi_data; - if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { - /* Set the factor from nvram */ - nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8; - if (nfactor < pspi_data->minSyncFactor ) - nfactor = pspi_data->minSyncFactor; - - if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) || - (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) { - - ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n", - ioc->name, bus, id, lun)); - - dv.cmd = MPT_SET_MAX; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - cfg.cfghdr.hdr = &header1; - - /* Save the final negotiated settings to - * SCSI device page 1. - */ - cfg.physAddr = cfg1_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfg.dir = 1; - mpt_config(hd->ioc, &cfg); - goto target_done; - } - } - } - - /* Finish iocmd inititialization - hidden or visible disk? */ - if (ioc->raid_data.pIocPg3) { - /* Search IOC page 3 for matching id - */ - Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; - int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; - - while (numPDisk) { - if (pPDisk->PhysDiskID == id) { - /* match */ - iocmd.flags |= MPT_ICFLAG_PHYS_DISK; - iocmd.physDiskNum = pPDisk->PhysDiskNum; - - /* Quiesce the IM - */ - if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) { - ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name)); - goto target_done; - } - break; - } - pPDisk++; - numPDisk--; - } - } - - /* RAID Volume ID's may double for a physical device. If RAID but - * not a physical ID as well, skip DV. - */ - if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) - goto target_done; - - - /* Basic Test. - * Async & Narrow - Inquiry - * Async & Narrow - Inquiry - * Maximum transfer rate - Inquiry - * Compare buffers: - * If compare, test complete. - * If miscompare and first pass, repeat - * If miscompare and not first pass, fall back and repeat - */ - hd->pLocal = NULL; - readPage0 = 0; - sz = SCSI_MAX_INQUIRY_BYTES; - rc = MPT_SCANDV_GOOD; - while (1) { - ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id)); - retcode = 0; - dv.cmd = MPT_SET_MIN; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - - cfg.cfghdr.hdr = &header1; - cfg.physAddr = cfg1_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfg.dir = 1; - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - /* Wide - narrow - wide workaround case - */ - if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) { - /* Send an untagged command to reset disk Qs corrupted - * when a parity error occurs on a Request Sense. - */ - if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) || - ((hd->ioc->facts.FWVersion.Word >= 0x01010000) && - (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) { - - iocmd.cmd = REQUEST_SENSE; - iocmd.data_dma = buf1_dma; - iocmd.data = pbuf1; - iocmd.size = 0x12; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else { - if (hd->pLocal == NULL) - goto target_done; - rc = hd->pLocal->completion; - if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) { - dv.max.width = 0; - doFallback = 0; - } else - goto target_done; - } - } else - goto target_done; - } - - iocmd.cmd = INQUIRY; - iocmd.data_dma = buf1_dma; - iocmd.data = pbuf1; - iocmd.size = sz; - memset(pbuf1, 0x00, sz); - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else { - if (hd->pLocal == NULL) - goto target_done; - rc = hd->pLocal->completion; - if (rc == MPT_SCANDV_GOOD) { - if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) { - if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0) - retcode = 1; - else - retcode = 0; - - goto target_done; - } - } else if (rc == MPT_SCANDV_SENSE) { - ; - } else { - /* If first command doesn't complete - * with a good status or with a check condition, - * exit. - */ - goto target_done; - } - } - - /* Reset the size for disks - */ - inq0 = (*pbuf1) & 0x1F; - if ((inq0 == 0) && vtarget && !vtarget->raidVolume) { - sz = 0x40; - iocmd.size = sz; - } - - /* Another GEM workaround. Check peripheral device type, - * if PROCESSOR, quit DV. - */ - if (inq0 == TYPE_PROCESSOR) { - mptscsih_initTarget(hd, - vtarget, - lun, - pbuf1, - sz); - goto target_done; - } - - if (inq0 > 0x08) - goto target_done; - - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - - if (sz == 0x40) { - if ((vtarget->maxWidth == 1) && (vtarget->maxOffset) && (nfactor < 0x0A) - && (vtarget->minSyncFactor > 0x09)) { - if ((pbuf1[56] & 0x04) == 0) - ; - else if ((pbuf1[56] & 0x01) == 1) { - vtarget->minSyncFactor = - nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320; - } else { - vtarget->minSyncFactor = - nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160; - } - - dv.max.factor = vtarget->minSyncFactor; - - if ((pbuf1[56] & 0x02) == 0) { - vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; - ddvprintk((MYIOC_s_NOTE_FMT - "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", - ioc->name, id, pbuf1[56])); - } - } - } - - if (doFallback) - dv.cmd = MPT_FALLBACK; - else - dv.cmd = MPT_SET_MAX; - - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - if ((!dv.now.width) && (!dv.now.offset)) - goto target_done; - - iocmd.cmd = INQUIRY; - iocmd.data_dma = buf2_dma; - iocmd.data = pbuf2; - iocmd.size = sz; - memset(pbuf2, 0x00, sz); - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - /* Save the return code. - * If this is the first pass, - * read SCSI Device Page 0 - * and update the target max parameters. - */ - rc = hd->pLocal->completion; - doFallback = 0; - if (rc == MPT_SCANDV_GOOD) { - if (!readPage0) { - u32 sdp0_info; - u32 sdp0_nego; - - cfg.cfghdr.hdr = &header0; - cfg.physAddr = cfg0_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - cfg.dir = 0; - - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E; - sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8; - - /* Quantum and Fujitsu workarounds. - * Quantum: PPR U320 -> PPR reply with Ultra2 and wide - * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide - * Resetart with a request for U160. - */ - if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) { - doFallback = 1; - } else { - dv.cmd = MPT_UPDATE_MAX; - mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data); - /* Update the SCSI device page 1 area - */ - pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters; - readPage0 = 1; - } - } - - /* Quantum workaround. Restart this test will the fallback - * flag set. - */ - if (doFallback == 0) { - if (memcmp(pbuf1, pbuf2, sz) != 0) { - if (!firstPass) - doFallback = 1; - } else { - ddvprintk((MYIOC_s_NOTE_FMT - "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id)); - hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE; - mptscsih_initTarget(hd, - vtarget, - lun, - pbuf1, - sz); - break; /* test complete */ - } - } - - - } else if (rc == MPT_SCANDV_ISSUE_SENSE) - doFallback = 1; /* set fallback flag */ - else if ((rc == MPT_SCANDV_DID_RESET) || - (rc == MPT_SCANDV_SENSE) || - (rc == MPT_SCANDV_FALLBACK)) - doFallback = 1; /* set fallback flag */ - else - goto target_done; - - firstPass = 0; - } - } - ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id)); - - if (ioc->spi_data.mpt_dv == 0) - goto target_done; - - inq0 = (*pbuf1) & 0x1F; - - /* Continue only for disks - */ - if (inq0 != 0) - goto target_done; - - if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY ) - goto target_done; - - /* Start the Enhanced Test. - * 0) issue TUR to clear out check conditions - * 1) read capacity of echo (regular) buffer - * 2) reserve device - * 3) do write-read-compare data pattern test - * 4) release - * 5) update nego parms to target struct - */ - cfg.cfghdr.hdr = &header1; - cfg.physAddr = cfg1_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfg.dir = 1; - - iocmd.cmd = TEST_UNIT_READY; - iocmd.data_dma = -1; - iocmd.data = NULL; - iocmd.size = 0; - notDone = 1; - while (notDone) { - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - - if (hd->pLocal == NULL) - goto target_done; - - rc = hd->pLocal->completion; - if (rc == MPT_SCANDV_GOOD) - notDone = 0; - else if (rc == MPT_SCANDV_SENSE) { - u8 skey = hd->pLocal->sense[2] & 0x0F; - u8 asc = hd->pLocal->sense[12]; - u8 ascq = hd->pLocal->sense[13]; - ddvprintk((MYIOC_s_INFO_FMT - "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", - ioc->name, skey, asc, ascq)); - - if (skey == UNIT_ATTENTION) - notDone++; /* repeat */ - else if ((skey == NOT_READY) && - (asc == 0x04)&&(ascq == 0x01)) { - /* wait then repeat */ - mdelay (2000); - notDone++; - } else if ((skey == NOT_READY) && (asc == 0x3A)) { - /* no medium, try read test anyway */ - notDone = 0; - } else { - /* All other errors are fatal. - */ - ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.", - ioc->name)); - goto target_done; - } - } else - goto target_done; - } - - iocmd.cmd = READ_BUFFER; - iocmd.data_dma = buf1_dma; - iocmd.data = pbuf1; - iocmd.size = 4; - iocmd.flags |= MPT_ICFLAG_BUF_CAP; - - dataBufSize = 0; - echoBufSize = 0; - for (patt = 0; patt < 2; patt++) { - if (patt == 0) - iocmd.flags |= MPT_ICFLAG_ECHO; - else - iocmd.flags &= ~MPT_ICFLAG_ECHO; - - notDone = 1; - while (notDone) { - bufsize = 0; - - /* If not ready after 8 trials, - * give up on this device. - */ - if (notDone > 8) - goto target_done; - - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - rc = hd->pLocal->completion; - ddvprintk(("ReadBuffer Comp Code %d", rc)); - ddvprintk((" buff: %0x %0x %0x %0x\n", - pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3])); - - if (rc == MPT_SCANDV_GOOD) { - notDone = 0; - if (iocmd.flags & MPT_ICFLAG_ECHO) { - bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3]; - if (pbuf1[0] & 0x01) - iocmd.flags |= MPT_ICFLAG_EBOS; - } else { - bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3]; - } - } else if (rc == MPT_SCANDV_SENSE) { - u8 skey = hd->pLocal->sense[2] & 0x0F; - u8 asc = hd->pLocal->sense[12]; - u8 ascq = hd->pLocal->sense[13]; - ddvprintk((MYIOC_s_INFO_FMT - "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", - ioc->name, skey, asc, ascq)); - if (skey == ILLEGAL_REQUEST) { - notDone = 0; - } else if (skey == UNIT_ATTENTION) { - notDone++; /* repeat */ - } else if ((skey == NOT_READY) && - (asc == 0x04)&&(ascq == 0x01)) { - /* wait then repeat */ - mdelay (2000); - notDone++; - } else { - /* All other errors are fatal. - */ - ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.", - ioc->name)); - goto target_done; - } - } else { - /* All other errors are fatal - */ - goto target_done; - } - } - } - - if (iocmd.flags & MPT_ICFLAG_ECHO) - echoBufSize = bufsize; - else - dataBufSize = bufsize; - } - sz = 0; - iocmd.flags &= ~MPT_ICFLAG_BUF_CAP; - - /* Use echo buffers if possible, - * Exit if both buffers are 0. - */ - if (echoBufSize > 0) { - iocmd.flags |= MPT_ICFLAG_ECHO; - if (dataBufSize > 0) - bufsize = min(echoBufSize, dataBufSize); - else - bufsize = echoBufSize; - } else if (dataBufSize == 0) - goto target_done; - - ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name, - (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize)); - - /* Data buffers for write-read-compare test max 1K. - */ - sz = min(bufsize, 1024); - - /* --- loop ---- - * On first pass, always issue a reserve. - * On additional loops, only if a reset has occurred. - * iocmd.flags indicates if echo or regular buffer - */ - for (patt = 0; patt < 4; patt++) { - ddvprintk(("Pattern %d\n", patt)); - if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) { - iocmd.cmd = TEST_UNIT_READY; - iocmd.data_dma = -1; - iocmd.data = NULL; - iocmd.size = 0; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - - iocmd.cmd = RELEASE; - iocmd.data_dma = -1; - iocmd.data = NULL; - iocmd.size = 0; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - rc = hd->pLocal->completion; - ddvprintk(("Release rc %d\n", rc)); - if (rc == MPT_SCANDV_GOOD) - iocmd.flags &= ~MPT_ICFLAG_RESERVED; - else - goto target_done; - } - iocmd.flags &= ~MPT_ICFLAG_RESERVED; - } - iocmd.flags &= ~MPT_ICFLAG_DID_RESET; - - if (iocmd.flags & MPT_ICFLAG_EBOS) - goto skip_Reserve; - - repeat = 5; - while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) { - iocmd.cmd = RESERVE; - iocmd.data_dma = -1; - iocmd.data = NULL; - iocmd.size = 0; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - rc = hd->pLocal->completion; - if (rc == MPT_SCANDV_GOOD) { - iocmd.flags |= MPT_ICFLAG_RESERVED; - } else if (rc == MPT_SCANDV_SENSE) { - /* Wait if coming ready - */ - u8 skey = hd->pLocal->sense[2] & 0x0F; - u8 asc = hd->pLocal->sense[12]; - u8 ascq = hd->pLocal->sense[13]; - ddvprintk((MYIOC_s_INFO_FMT - "DV: Reserve Failed: ", ioc->name)); - ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", - skey, asc, ascq)); - - if ((skey == NOT_READY) && (asc == 0x04)&& - (ascq == 0x01)) { - /* wait then repeat */ - mdelay (2000); - notDone++; - } else { - ddvprintk((MYIOC_s_INFO_FMT - "DV: Reserved Failed.", ioc->name)); - goto target_done; - } - } else { - ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.", - ioc->name)); - goto target_done; - } - } - } - -skip_Reserve: - mptscsih_fillbuf(pbuf1, sz, patt, 1); - iocmd.cmd = WRITE_BUFFER; - iocmd.data_dma = buf1_dma; - iocmd.data = pbuf1; - iocmd.size = sz; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - rc = hd->pLocal->completion; - if (rc == MPT_SCANDV_GOOD) - ; /* Issue read buffer */ - else if (rc == MPT_SCANDV_DID_RESET) { - /* If using echo buffers, reset to data buffers. - * Else do Fallback and restart - * this test (re-issue reserve - * because of bus reset). - */ - if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) { - iocmd.flags &= ~MPT_ICFLAG_ECHO; - } else { - dv.cmd = MPT_FALLBACK; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - if ((!dv.now.width) && (!dv.now.offset)) - goto target_done; - } - - iocmd.flags |= MPT_ICFLAG_DID_RESET; - patt = -1; - continue; - } else if (rc == MPT_SCANDV_SENSE) { - /* Restart data test if UA, else quit. - */ - u8 skey = hd->pLocal->sense[2] & 0x0F; - ddvprintk((MYIOC_s_INFO_FMT - "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, - hd->pLocal->sense[12], hd->pLocal->sense[13])); - if (skey == UNIT_ATTENTION) { - patt = -1; - continue; - } else if (skey == ILLEGAL_REQUEST) { - if (iocmd.flags & MPT_ICFLAG_ECHO) { - if (dataBufSize >= bufsize) { - iocmd.flags &= ~MPT_ICFLAG_ECHO; - patt = -1; - continue; - } - } - goto target_done; - } - else - goto target_done; - } else { - /* fatal error */ - goto target_done; - } - } - - iocmd.cmd = READ_BUFFER; - iocmd.data_dma = buf2_dma; - iocmd.data = pbuf2; - iocmd.size = sz; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - goto target_done; - else if (hd->pLocal == NULL) - goto target_done; - else { - rc = hd->pLocal->completion; - if (rc == MPT_SCANDV_GOOD) { - /* If buffers compare, - * go to next pattern, - * else, do a fallback and restart - * data transfer test. - */ - if (memcmp (pbuf1, pbuf2, sz) == 0) { - ; /* goto next pattern */ - } else { - /* Miscompare with Echo buffer, go to data buffer, - * if that buffer exists. - * Miscompare with Data buffer, check first 4 bytes, - * some devices return capacity. Exit in this case. - */ - if (iocmd.flags & MPT_ICFLAG_ECHO) { - if (dataBufSize >= bufsize) - iocmd.flags &= ~MPT_ICFLAG_ECHO; - else - goto target_done; - } else { - if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) { - /* Argh. Device returning wrong data. - * Quit DV for this device. - */ - goto target_done; - } - - /* Had an actual miscompare. Slow down.*/ - dv.cmd = MPT_FALLBACK; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - if ((!dv.now.width) && (!dv.now.offset)) - goto target_done; - } - - patt = -1; - continue; - } - } else if (rc == MPT_SCANDV_DID_RESET) { - /* Do Fallback and restart - * this test (re-issue reserve - * because of bus reset). - */ - dv.cmd = MPT_FALLBACK; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - - if (mpt_config(hd->ioc, &cfg) != 0) - goto target_done; - - if ((!dv.now.width) && (!dv.now.offset)) - goto target_done; - - iocmd.flags |= MPT_ICFLAG_DID_RESET; - patt = -1; - continue; - } else if (rc == MPT_SCANDV_SENSE) { - /* Restart data test if UA, else quit. - */ - u8 skey = hd->pLocal->sense[2] & 0x0F; - ddvprintk((MYIOC_s_INFO_FMT - "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, - hd->pLocal->sense[12], hd->pLocal->sense[13])); - if (skey == UNIT_ATTENTION) { - patt = -1; - continue; - } - else - goto target_done; - } else { - /* fatal error */ - goto target_done; - } - } - - } /* --- end of patt loop ---- */ - -target_done: - if (iocmd.flags & MPT_ICFLAG_RESERVED) { - iocmd.cmd = RELEASE; - iocmd.data_dma = -1; - iocmd.data = NULL; - iocmd.size = 0; - if (mptscsih_do_cmd(hd, &iocmd) < 0) - printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d", - ioc->name, id); - else if (hd->pLocal) { - if (hd->pLocal->completion == MPT_SCANDV_GOOD) - iocmd.flags &= ~MPT_ICFLAG_RESERVED; - } else { - printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d", - ioc->name, id); - } - } - - - /* Set if cfg1_dma_addr contents is valid - */ - if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){ - /* If disk, not U320, disable QAS - */ - if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) { - hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; - ddvprintk((MYIOC_s_NOTE_FMT - "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor)); - } - - dv.cmd = MPT_SAVE; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - - /* Double writes to SDP1 can cause problems, - * skip save of the final negotiated settings to - * SCSI device page 1. - * - cfg.cfghdr.hdr = &header1; - cfg.physAddr = cfg1_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfg.dir = 1; - mpt_config(hd->ioc, &cfg); - */ - } - - /* If this is a RAID Passthrough, enable internal IOs - */ - if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) { - if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0) - ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name)); - } - - /* Done with the DV scan of the current target - */ - if (pDvBuf) - pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma); - - ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n", - ioc->name, id)); - - return retcode; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_dv_parms - perform a variety of operations on the - * parameters used for negotiation. - * @hd: Pointer to a SCSI host. - * @dv: Pointer to a structure that contains the maximum and current - * negotiated parameters. - */ -static void -mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) -{ - VirtTarget *vtarget; - SCSIDevicePage0_t *pPage0; - SCSIDevicePage1_t *pPage1; - int val = 0, data, configuration; - u8 width = 0; - u8 offset = 0; - u8 factor = 0; - u8 negoFlags = 0; - u8 cmd = dv->cmd; - u8 id = dv->id; - - switch (cmd) { - case MPT_GET_NVRAM_VALS: - ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ", - hd->ioc->name)); - /* Get the NVRAM values and save in tmax - * If not an LVD bus, the adapter minSyncFactor has been - * already throttled back. - */ - negoFlags = hd->ioc->spi_data.noQas; - if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume) { - width = vtarget->maxWidth; - offset = vtarget->maxOffset; - factor = vtarget->minSyncFactor; - negoFlags |= vtarget->negoFlags; - } else { - if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { - data = hd->ioc->spi_data.nvram[id]; - width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; - if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0) - factor = MPT_ASYNC; - else { - factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; - if ((factor == 0) || (factor == MPT_ASYNC)){ - factor = MPT_ASYNC; - offset = 0; - } - } - } else { - width = MPT_NARROW; - offset = 0; - factor = MPT_ASYNC; - } - - /* Set the negotiation flags */ - if (!width) - negoFlags |= MPT_TARGET_NO_NEGO_WIDE; - - if (!offset) - negoFlags |= MPT_TARGET_NO_NEGO_SYNC; - } - - /* limit by adapter capabilities */ - width = min(width, hd->ioc->spi_data.maxBusWidth); - offset = min(offset, hd->ioc->spi_data.maxSyncOffset); - factor = max(factor, hd->ioc->spi_data.minSyncFactor); - - /* Check Consistency */ - if (offset && (factor < MPT_ULTRA2) && !width) - factor = MPT_ULTRA2; - - dv->max.width = width; - dv->max.offset = offset; - dv->max.factor = factor; - dv->max.flags = negoFlags; - ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n", - id, width, factor, offset, negoFlags)); - break; - - case MPT_UPDATE_MAX: - ddvprintk((MYIOC_s_NOTE_FMT - "Updating with SDP0 Data: ", hd->ioc->name)); - /* Update tmax values with those from Device Page 0.*/ - pPage0 = (SCSIDevicePage0_t *) pPage; - if (pPage0) { - val = le32_to_cpu(pPage0->NegotiatedParameters); - dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0; - dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16; - dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8; - } - - dv->now.width = dv->max.width; - dv->now.offset = dv->max.offset; - dv->now.factor = dv->max.factor; - ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n", - id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); - break; - - case MPT_SET_MAX: - ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ", - hd->ioc->name)); - /* Set current to the max values. Update the config page.*/ - dv->now.width = dv->max.width; - dv->now.offset = dv->max.offset; - dv->now.factor = dv->max.factor; - dv->now.flags = dv->max.flags; - - pPage1 = (SCSIDevicePage1_t *)pPage; - if (pPage1) { - mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor, - dv->now.offset, &val, &configuration, dv->now.flags); - dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", - id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); - pPage1->RequestedParameters = cpu_to_le32(val); - pPage1->Reserved = 0; - pPage1->Configuration = cpu_to_le32(configuration); - } - - ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n", - id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); - break; - - case MPT_SET_MIN: - ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ", - hd->ioc->name)); - /* Set page to asynchronous and narrow - * Do not update now, breaks fallback routine. */ - width = MPT_NARROW; - offset = 0; - factor = MPT_ASYNC; - negoFlags = dv->max.flags; - - pPage1 = (SCSIDevicePage1_t *)pPage; - if (pPage1) { - mptscsih_setDevicePage1Flags (width, factor, - offset, &val, &configuration, negoFlags); - dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", - id, width, factor, offset, negoFlags, val, configuration)); - pPage1->RequestedParameters = cpu_to_le32(val); - pPage1->Reserved = 0; - pPage1->Configuration = cpu_to_le32(configuration); - } - ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n", - id, width, factor, offset, val, configuration, negoFlags)); - break; - - case MPT_FALLBACK: - ddvprintk((MYIOC_s_NOTE_FMT - "Fallback: Start: offset %d, factor %x, width %d \n", - hd->ioc->name, dv->now.offset, - dv->now.factor, dv->now.width)); - width = dv->now.width; - offset = dv->now.offset; - factor = dv->now.factor; - if ((offset) && (dv->max.width)) { - if (factor < MPT_ULTRA160) - factor = MPT_ULTRA160; - else if (factor < MPT_ULTRA2) { - factor = MPT_ULTRA2; - width = MPT_WIDE; - } else if ((factor == MPT_ULTRA2) && width) { - factor = MPT_ULTRA2; - width = MPT_NARROW; - } else if (factor < MPT_ULTRA) { - factor = MPT_ULTRA; - width = MPT_WIDE; - } else if ((factor == MPT_ULTRA) && width) { - width = MPT_NARROW; - } else if (factor < MPT_FAST) { - factor = MPT_FAST; - width = MPT_WIDE; - } else if ((factor == MPT_FAST) && width) { - factor = MPT_FAST; - width = MPT_NARROW; - } else if (factor < MPT_SCSI) { - factor = MPT_SCSI; - width = MPT_WIDE; - } else if ((factor == MPT_SCSI) && width) { - factor = MPT_SCSI; - width = MPT_NARROW; - } else { - factor = MPT_ASYNC; - offset = 0; - } - - } else if (offset) { - width = MPT_NARROW; - if (factor < MPT_ULTRA) - factor = MPT_ULTRA; - else if (factor < MPT_FAST) - factor = MPT_FAST; - else if (factor < MPT_SCSI) - factor = MPT_SCSI; - else { - factor = MPT_ASYNC; - offset = 0; - } - - } else { - width = MPT_NARROW; - factor = MPT_ASYNC; - } - dv->max.flags |= MPT_TARGET_NO_NEGO_QAS; - dv->max.flags &= ~MPT_TAPE_NEGO_IDP; - - dv->now.width = width; - dv->now.offset = offset; - dv->now.factor = factor; - dv->now.flags = dv->max.flags; - - pPage1 = (SCSIDevicePage1_t *)pPage; - if (pPage1) { - mptscsih_setDevicePage1Flags (width, factor, offset, &val, - &configuration, dv->now.flags); - dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n", - id, width, offset, factor, dv->now.flags, val, configuration)); - - pPage1->RequestedParameters = cpu_to_le32(val); - pPage1->Reserved = 0; - pPage1->Configuration = cpu_to_le32(configuration); - } - - ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n", - id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration)); - break; - - case MPT_SAVE: - ddvprintk((MYIOC_s_NOTE_FMT - "Saving to Target structure: ", hd->ioc->name)); - ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n", - id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); - - /* Save these values to target structures - * or overwrite nvram (phys disks only). - */ - - if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume ) { - vtarget->maxWidth = dv->now.width; - vtarget->maxOffset = dv->now.offset; - vtarget->minSyncFactor = dv->now.factor; - vtarget->negoFlags = dv->now.flags; - } else { - /* Preserv all flags, use - * read-modify-write algorithm - */ - if (hd->ioc->spi_data.nvram) { - data = hd->ioc->spi_data.nvram[id]; - - if (dv->now.width) - data &= ~MPT_NVRAM_WIDE_DISABLE; - else - data |= MPT_NVRAM_WIDE_DISABLE; - - if (!dv->now.offset) - factor = MPT_ASYNC; - - data &= ~MPT_NVRAM_SYNC_MASK; - data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK; - - hd->ioc->spi_data.nvram[id] = data; - } - } - break; - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_fillbuf - fill a buffer with a special data pattern - * cleanup. For bus scan only. - * - * @buffer: Pointer to data buffer to be filled. - * @size: Number of bytes to fill - * @index: Pattern index - * @width: bus width, 0 (8 bits) or 1 (16 bits) - */ -static void -mptscsih_fillbuf(char *buffer, int size, int index, int width) -{ - char *ptr = buffer; - int ii; - char byte; - short val; - - switch (index) { - case 0: - - if (width) { - /* Pattern: 0000 FFFF 0000 FFFF - */ - for (ii=0; ii < size; ii++, ptr++) { - if (ii & 0x02) - *ptr = 0xFF; - else - *ptr = 0x00; - } - } else { - /* Pattern: 00 FF 00 FF - */ - for (ii=0; ii < size; ii++, ptr++) { - if (ii & 0x01) - *ptr = 0xFF; - else - *ptr = 0x00; - } - } - break; - - case 1: - if (width) { - /* Pattern: 5555 AAAA 5555 AAAA 5555 - */ - for (ii=0; ii < size; ii++, ptr++) { - if (ii & 0x02) - *ptr = 0xAA; - else - *ptr = 0x55; - } - } else { - /* Pattern: 55 AA 55 AA 55 - */ - for (ii=0; ii < size; ii++, ptr++) { - if (ii & 0x01) - *ptr = 0xAA; - else - *ptr = 0x55; - } - } - break; - - case 2: - /* Pattern: 00 01 02 03 04 05 - * ... FE FF 00 01.. - */ - for (ii=0; ii < size; ii++, ptr++) - *ptr = (char) ii; - break; - - case 3: - if (width) { - /* Wide Pattern: FFFE 0001 FFFD 0002 - * ... 4000 DFFF 8000 EFFF - */ - byte = 0; - for (ii=0; ii < size/2; ii++) { - /* Create the base pattern - */ - val = (1 << byte); - /* every 64 (0x40) bytes flip the pattern - * since we fill 2 bytes / iteration, - * test for ii = 0x20 - */ - if (ii & 0x20) - val = ~(val); - - if (ii & 0x01) { - *ptr = (char)( (val & 0xFF00) >> 8); - ptr++; - *ptr = (char)(val & 0xFF); - byte++; - byte &= 0x0F; - } else { - val = ~val; - *ptr = (char)( (val & 0xFF00) >> 8); - ptr++; - *ptr = (char)(val & 0xFF); - } - - ptr++; - } - } else { - /* Narrow Pattern: FE 01 FD 02 FB 04 - * .. 7F 80 01 FE 02 FD ... 80 7F - */ - byte = 0; - for (ii=0; ii < size; ii++, ptr++) { - /* Base pattern - first 32 bytes - */ - if (ii & 0x01) { - *ptr = (1 << byte); - byte++; - byte &= 0x07; - } else { - *ptr = (char) (~(1 << byte)); - } - - /* Flip the pattern every 32 bytes - */ - if (ii & 0x20) - *ptr = ~(*ptr); - } - } - break; - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return. - * Else set the NEED_DV flag after Read Capacity Issued (disks) - * or Mode Sense (cdroms). - * - * Tapes, initTarget will set this flag on completion of Inquiry command. - * Called only if DV_NOT_DONE flag is set - */ -static void -mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc) -{ - MPT_ADAPTER *ioc = hd->ioc; - u8 cmd; - SpiCfgData *pSpi; - - ddvtprintk((MYIOC_s_NOTE_FMT - " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", - hd->ioc->name, sc->device->id, sc->device->lun , hd->negoNvram, sc->cmnd[0])); - - if ((sc->device->lun != 0) || (hd->negoNvram != 0)) - return; - - cmd = sc->cmnd[0]; - - if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) { - pSpi = &ioc->spi_data; - if ((ioc->raid_data.isRaid & (1 << sc->device->id)) && ioc->raid_data.pIocPg3) { - /* Set NEED_DV for all hidden disks - */ - Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; - int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; - - while (numPDisk) { - pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; - ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID)); - pPDisk++; - numPDisk--; - } - } - pSpi->dvStatus[sc->device->id] |= MPT_SCSICFG_NEED_DV; - ddvtprintk(("NEED_DV set for visible disk id %d\n", sc->device->id)); - } -} - -/* mptscsih_raid_set_dv_flags() - * - * New or replaced disk. Set DV flag and schedule DV. - */ -static void -mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id) -{ - MPT_ADAPTER *ioc = hd->ioc; - SpiCfgData *pSpi = &ioc->spi_data; - Ioc3PhysDisk_t *pPDisk; - int numPDisk; - - if (hd->negoNvram != 0) - return; - - ddvtprintk(("DV requested for phys disk id %d\n", id)); - if (ioc->raid_data.pIocPg3) { - pPDisk = ioc->raid_data.pIocPg3->PhysDisk; - numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; - while (numPDisk) { - if (id == pPDisk->PhysDiskNum) { - pSpi->dvStatus[pPDisk->PhysDiskID] = - (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE); - pSpi->forceDv = MPT_SCSICFG_NEED_DV; - ddvtprintk(("NEED_DV set for phys disk id %d\n", - pPDisk->PhysDiskID)); - break; - } - pPDisk++; - numPDisk--; - } - - if (numPDisk == 0) { - /* The physical disk that needs DV was not found - * in the stored IOC Page 3. The driver must reload - * this page. DV routine will set the NEED_DV flag for - * all phys disks that have DV_NOT_DONE set. - */ - pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; - ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id)); - } - } -} -#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */ - EXPORT_SYMBOL(mptscsih_remove); EXPORT_SYMBOL(mptscsih_shutdown); #ifdef CONFIG_PM diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 44b248d51ea3..2447a203513f 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -60,16 +60,6 @@ #define MPT_SCSI_MAX_SECTORS 8192 -/* To disable domain validation, uncomment the - * following line. No effect for FC devices. - * For SCSI devices, driver will negotiate to - * NVRAM settings (if available) or to maximum adapter - * capabilities. - */ - -#define MPTSCSIH_ENABLE_DOMAIN_VALIDATION - - /* SCSI driver setup structure. Settings can be overridden * by command line options. */ @@ -109,3 +99,4 @@ extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern void mptscsih_timer_expired(unsigned long data); extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); +extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid); diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index f148dfa39117..437189f871b0 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -56,12 +56,15 @@ #include /* notifier code */ #include #include +#include #include #include #include #include #include +#include +#include #include "mptbase.h" #include "mptscsih.h" @@ -76,20 +79,6 @@ MODULE_DESCRIPTION(my_NAME); MODULE_LICENSE("GPL"); /* Command line args */ -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION -static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION; -module_param(mpt_dv, int, 0); -MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)"); - -static int mpt_width = MPTSCSIH_MAX_WIDTH; -module_param(mpt_width, int, 0); -MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)"); - -static ushort mpt_factor = MPTSCSIH_MIN_SYNC; -module_param(mpt_factor, ushort, 0); -MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)"); -#endif - static int mpt_saf_te = MPTSCSIH_SAF_TE; module_param(mpt_saf_te, int, 0); MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); @@ -98,10 +87,308 @@ static int mpt_pq_filter = 0; module_param(mpt_pq_filter, int, 0); MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); +static void mptspi_write_offset(struct scsi_target *, int); +static void mptspi_write_width(struct scsi_target *, int); +static int mptspi_write_spi_device_pg1(struct scsi_target *, + struct _CONFIG_PAGE_SCSI_DEVICE_1 *); + +static struct scsi_transport_template *mptspi_transport_template = NULL; + static int mptspiDoneCtx = -1; static int mptspiTaskCtx = -1; static int mptspiInternalCtx = -1; /* Used only for internal commands */ +static int mptspi_target_alloc(struct scsi_target *starget) +{ + struct Scsi_Host *shost = dev_to_shost(&starget->dev); + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; + int ret; + + if (hd == NULL) + return -ENODEV; + + ret = mptscsih_target_alloc(starget); + if (ret) + return ret; + + /* if we're a device on virtual channel 1 and we're not part + * of an array, just return here (otherwise the setup below + * may actually affect a real physical device on channel 0 */ + if (starget->channel == 1 && + mptscsih_raid_id_to_num(hd, starget->id) < 0) + return 0; + + if (hd->ioc->spi_data.nvram && + hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) { + u32 nvram = hd->ioc->spi_data.nvram[starget->id]; + spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; + spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; + } else { + spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor; + spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth; + } + spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset; + + spi_offset(starget) = 0; + mptspi_write_width(starget, 0); + + return 0; +} + +static int mptspi_read_spi_device_pg0(struct scsi_target *starget, + struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0) +{ + struct Scsi_Host *shost = dev_to_shost(&starget->dev); + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; + struct _MPT_ADAPTER *ioc = hd->ioc; + struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0; + dma_addr_t pg0_dma; + int size; + struct _x_config_parms cfg; + struct _CONFIG_PAGE_HEADER hdr; + int err = -EBUSY; + + /* No SPI parameters for RAID devices */ + if (starget->channel == 0 && + (hd->ioc->raid_data.isRaid & (1 << starget->id))) + return -1; + + size = ioc->spi_data.sdp0length * 4; + /* + if (ioc->spi_data.sdp0length & 1) + size += size + 4; + size += 2048; + */ + + pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL); + if (pg0 == NULL) { + starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n"); + return -EINVAL; + } + + memset(&hdr, 0, sizeof(hdr)); + + hdr.PageVersion = ioc->spi_data.sdp0version; + hdr.PageLength = ioc->spi_data.sdp0length; + hdr.PageNumber = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; + + memset(&cfg, 0, sizeof(cfg)); + + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = pg0_dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + cfg.dir = 0; + cfg.pageAddr = starget->id; + + if (mpt_config(ioc, &cfg)) { + starget_printk(KERN_ERR, starget, "mpt_config failed\n"); + goto out_free; + } + err = 0; + memcpy(pass_pg0, pg0, size); + + out_free: + dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma); + return err; +} + +static u32 mptspi_getRP(struct scsi_target *starget) +{ + u32 nego = 0; + + nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0; + nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0; + nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0; + nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0; + nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0; + nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0; + nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0; + nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0; + + nego |= (spi_period(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK; + nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK; + nego |= spi_width(starget) ? MPI_SCSIDEVPAGE1_RP_WIDE : 0; + + return nego; +} + +static void mptspi_read_parameters(struct scsi_target *starget) +{ + int nego; + struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0; + + mptspi_read_spi_device_pg0(starget, &pg0); + + nego = le32_to_cpu(pg0.NegotiatedParameters); + + spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0; + spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0; + spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0; + spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0; + spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0; + spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0; + spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0; + spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0; + spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD; + spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET; + spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0; +} + +static int +mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) +{ + MpiRaidActionRequest_t *pReq; + MPT_FRAME_HDR *mf; + + /* Get and Populate a free Frame + */ + if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { + ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", + hd->ioc->name)); + return -EAGAIN; + } + pReq = (MpiRaidActionRequest_t *)mf; + if (quiesce) + pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO; + else + pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO; + pReq->Reserved1 = 0; + pReq->ChainOffset = 0; + pReq->Function = MPI_FUNCTION_RAID_ACTION; + pReq->VolumeID = disk; + pReq->VolumeBus = 0; + pReq->PhysDiskNum = 0; + pReq->MsgFlags = 0; + pReq->Reserved2 = 0; + pReq->ActionDataWord = 0; /* Reserved for this action */ + + mpt_add_sge((char *)&pReq->ActionDataSGE, + MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); + + ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", + hd->ioc->name, action, io->id)); + + hd->pLocal = NULL; + hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ + hd->scandv_wait_done = 0; + + /* Save cmd pointer, for resource free if timeout or + * FW reload occurs + */ + hd->cmdPtr = mf; + + add_timer(&hd->timer); + mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); + wait_event(hd->scandv_waitq, hd->scandv_wait_done); + + if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0)) + return -1; + + return 0; +} + +static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, + struct scsi_device *sdev) +{ + VirtTarget *vtarget = scsi_target(sdev)->hostdata; + + /* no DV on RAID devices */ + if (sdev->channel == 0 && + (hd->ioc->raid_data.isRaid & (1 << sdev->id))) + return; + + /* If this is a piece of a RAID, then quiesce first */ + if (sdev->channel == 1 && + mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) { + starget_printk(KERN_ERR, scsi_target(sdev), + "Integrated RAID quiesce failed\n"); + return; + } + + spi_dv_device(sdev); + + if (sdev->channel == 1 && + mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0) + starget_printk(KERN_ERR, scsi_target(sdev), + "Integrated RAID resume failed\n"); + + mptspi_read_parameters(sdev->sdev_target); + spi_display_xfer_agreement(sdev->sdev_target); + mptspi_read_parameters(sdev->sdev_target); +} + +static int mptspi_slave_alloc(struct scsi_device *sdev) +{ + int ret; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; + /* gcc doesn't see that all uses of this variable occur within + * the if() statements, so stop it from whining */ + int physdisknum = 0; + + if (sdev->channel == 1) { + physdisknum = mptscsih_raid_id_to_num(hd, sdev->id); + + if (physdisknum < 0) + return physdisknum; + } + + ret = mptscsih_slave_alloc(sdev); + + if (ret) + return ret; + + if (sdev->channel == 1) { + VirtDevice *vdev = sdev->hostdata; + sdev->no_uld_attach = 1; + vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; + /* The real channel for this device is zero */ + vdev->bus_id = 0; + /* The actual physdisknum (for RAID passthrough) */ + vdev->target_id = physdisknum; + } + + return 0; +} + +static int mptspi_slave_configure(struct scsi_device *sdev) +{ + int ret = mptscsih_slave_configure(sdev); + struct _MPT_SCSI_HOST *hd = + (struct _MPT_SCSI_HOST *)sdev->host->hostdata; + + if (ret) + return ret; + + if ((sdev->channel == 1 || + !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) && + !spi_initial_dv(sdev->sdev_target)) + mptspi_dv_device(hd, sdev); + + return 0; +} + +static void mptspi_slave_destroy(struct scsi_device *sdev) +{ + struct scsi_target *starget = scsi_target(sdev); + VirtTarget *vtarget = starget->hostdata; + VirtDevice *vdevice = sdev->hostdata; + + /* Will this be the last lun on a non-raid device? */ + if (vtarget->num_luns == 1 && vdevice->configured_lun) { + struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; + + /* Async Narrow */ + pg1.RequestedParameters = 0; + pg1.Reserved = 0; + pg1.Configuration = 0; + + mptspi_write_spi_device_pg1(starget, &pg1); + } + + mptscsih_slave_destroy(sdev); +} + static struct scsi_host_template mptspi_driver_template = { .module = THIS_MODULE, .proc_name = "mptspi", @@ -109,11 +396,11 @@ static struct scsi_host_template mptspi_driver_template = { .name = "MPT SPI Host", .info = mptscsih_info, .queuecommand = mptscsih_qcmd, - .target_alloc = mptscsih_target_alloc, - .slave_alloc = mptscsih_slave_alloc, - .slave_configure = mptscsih_slave_configure, + .target_alloc = mptspi_target_alloc, + .slave_alloc = mptspi_slave_alloc, + .slave_configure = mptspi_slave_configure, .target_destroy = mptscsih_target_destroy, - .slave_destroy = mptscsih_slave_destroy, + .slave_destroy = mptspi_slave_destroy, .change_queue_depth = mptscsih_change_queue_depth, .eh_abort_handler = mptscsih_abort, .eh_device_reset_handler = mptscsih_dev_reset, @@ -128,6 +415,360 @@ static struct scsi_host_template mptspi_driver_template = { .use_clustering = ENABLE_CLUSTERING, }; +static int mptspi_write_spi_device_pg1(struct scsi_target *starget, + struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1) +{ + struct Scsi_Host *shost = dev_to_shost(&starget->dev); + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; + struct _MPT_ADAPTER *ioc = hd->ioc; + struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1; + dma_addr_t pg1_dma; + int size; + struct _x_config_parms cfg; + struct _CONFIG_PAGE_HEADER hdr; + int err = -EBUSY; + + /* don't allow updating nego parameters on RAID devices */ + if (starget->channel == 0 && + (hd->ioc->raid_data.isRaid & (1 << starget->id))) + return -1; + + size = ioc->spi_data.sdp1length * 4; + + pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL); + if (pg1 == NULL) { + starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n"); + return -EINVAL; + } + + memset(&hdr, 0, sizeof(hdr)); + + hdr.PageVersion = ioc->spi_data.sdp1version; + hdr.PageLength = ioc->spi_data.sdp1length; + hdr.PageNumber = 1; + hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; + + memset(&cfg, 0, sizeof(cfg)); + + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = pg1_dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + cfg.dir = 1; + cfg.pageAddr = starget->id; + + memcpy(pg1, pass_pg1, size); + + pg1->Header.PageVersion = hdr.PageVersion; + pg1->Header.PageLength = hdr.PageLength; + pg1->Header.PageNumber = hdr.PageNumber; + pg1->Header.PageType = hdr.PageType; + + if (mpt_config(ioc, &cfg)) { + starget_printk(KERN_ERR, starget, "mpt_config failed\n"); + goto out_free; + } + err = 0; + + out_free: + dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma); + return err; +} + +static void mptspi_write_offset(struct scsi_target *starget, int offset) +{ + struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; + u32 nego; + + if (offset < 0) + offset = 0; + + if (offset > 255) + offset = 255; + + if (spi_offset(starget) == -1) + mptspi_read_parameters(starget); + + spi_offset(starget) = offset; + + nego = mptspi_getRP(starget); + + pg1.RequestedParameters = cpu_to_le32(nego); + pg1.Reserved = 0; + pg1.Configuration = 0; + + mptspi_write_spi_device_pg1(starget, &pg1); +} + +static void mptspi_write_period(struct scsi_target *starget, int period) +{ + struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; + u32 nego; + + if (period < 8) + period = 8; + + if (period > 255) + period = 255; + + if (spi_period(starget) == -1) + mptspi_read_parameters(starget); + + if (period == 8) { + spi_iu(starget) = 1; + spi_dt(starget) = 1; + } else if (period == 9) { + spi_dt(starget) = 1; + } + + spi_period(starget) = period; + + nego = mptspi_getRP(starget); + + pg1.RequestedParameters = cpu_to_le32(nego); + pg1.Reserved = 0; + pg1.Configuration = 0; + + mptspi_write_spi_device_pg1(starget, &pg1); +} + +static void mptspi_write_dt(struct scsi_target *starget, int dt) +{ + struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; + u32 nego; + + if (spi_period(starget) == -1) + mptspi_read_parameters(starget); + + if (!dt && spi_period(starget) < 10) + spi_period(starget) = 10; + + spi_dt(starget) = dt; + + nego = mptspi_getRP(starget); + + + pg1.RequestedParameters = cpu_to_le32(nego); + pg1.Reserved = 0; + pg1.Configuration = 0; + + mptspi_write_spi_device_pg1(starget, &pg1); +} + +static void mptspi_write_iu(struct scsi_target *starget, int iu) +{ + struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; + u32 nego; + + if (spi_period(starget) == -1) + mptspi_read_parameters(starget); + + if (!iu && spi_period(starget) < 9) + spi_period(starget) = 9; + + spi_iu(starget) = iu; + + nego = mptspi_getRP(starget); + + pg1.RequestedParameters = cpu_to_le32(nego); + pg1.Reserved = 0; + pg1.Configuration = 0; + + mptspi_write_spi_device_pg1(starget, &pg1); +} + +#define MPTSPI_SIMPLE_TRANSPORT_PARM(parm) \ +static void mptspi_write_##parm(struct scsi_target *starget, int parm)\ +{ \ + struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; \ + u32 nego; \ + \ + spi_##parm(starget) = parm; \ + \ + nego = mptspi_getRP(starget); \ + \ + pg1.RequestedParameters = cpu_to_le32(nego); \ + pg1.Reserved = 0; \ + pg1.Configuration = 0; \ + \ + mptspi_write_spi_device_pg1(starget, &pg1); \ +} + +MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm) +MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow) +MPTSPI_SIMPLE_TRANSPORT_PARM(rti) +MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs) +MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en) + +static void mptspi_write_qas(struct scsi_target *starget, int qas) +{ + struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; + struct Scsi_Host *shost = dev_to_shost(&starget->dev); + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; + VirtTarget *vtarget = starget->hostdata; + u32 nego; + + if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) || + hd->ioc->spi_data.noQas) + spi_qas(starget) = 0; + else + spi_qas(starget) = qas; + + nego = mptspi_getRP(starget); + + pg1.RequestedParameters = cpu_to_le32(nego); + pg1.Reserved = 0; + pg1.Configuration = 0; + + mptspi_write_spi_device_pg1(starget, &pg1); +} + +static void mptspi_write_width(struct scsi_target *starget, int width) +{ + struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; + u32 nego; + + if (!width) { + spi_dt(starget) = 0; + if (spi_period(starget) < 10) + spi_period(starget) = 10; + } + + spi_width(starget) = width; + + nego = mptspi_getRP(starget); + + pg1.RequestedParameters = cpu_to_le32(nego); + pg1.Reserved = 0; + pg1.Configuration = 0; + + mptspi_write_spi_device_pg1(starget, &pg1); +} + +struct work_queue_wrapper { + struct work_struct work; + struct _MPT_SCSI_HOST *hd; + int disk; +}; + +static void mpt_work_wrapper(void *data) +{ + struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; + struct _MPT_SCSI_HOST *hd = wqw->hd; + struct Scsi_Host *shost = hd->ioc->sh; + struct scsi_device *sdev; + int disk = wqw->disk; + struct _CONFIG_PAGE_IOC_3 *pg3; + + kfree(wqw); + + mpt_findImVolumes(hd->ioc); + pg3 = hd->ioc->raid_data.pIocPg3; + if (!pg3) + return; + + shost_for_each_device(sdev,shost) { + struct scsi_target *starget = scsi_target(sdev); + VirtTarget *vtarget = starget->hostdata; + + /* only want to search RAID components */ + if (sdev->channel != 1) + continue; + + /* The target_id is the raid PhysDiskNum, even if + * starget->id is the actual target address */ + if(vtarget->target_id != disk) + continue; + + starget_printk(KERN_INFO, vtarget->starget, + "Integrated RAID requests DV of new device\n"); + mptspi_dv_device(hd, sdev); + } + shost_printk(KERN_INFO, shost, + "Integrated RAID detects new device %d\n", disk); + scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1); +} + + +static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk) +{ + struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC); + + if (!wqw) { + shost_printk(KERN_ERR, hd->ioc->sh, + "Failed to act on RAID event for physical disk %d\n", + disk); + return; + } + INIT_WORK(&wqw->work, mpt_work_wrapper, wqw); + wqw->hd = hd; + wqw->disk = disk; + + schedule_work(&wqw->work); +} + +static int +mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) +{ + u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata; + + if (hd && event == MPI_EVENT_INTEGRATED_RAID) { + int reason + = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16; + + if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { + int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24; + mpt_dv_raid(hd, disk); + } + } + return mptscsih_event_process(ioc, pEvReply); +} + +static int +mptspi_deny_binding(struct scsi_target *starget) +{ + struct _MPT_SCSI_HOST *hd = + (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata; + return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) && + starget->channel == 0) ? 1 : 0; +} + +static struct spi_function_template mptspi_transport_functions = { + .get_offset = mptspi_read_parameters, + .set_offset = mptspi_write_offset, + .show_offset = 1, + .get_period = mptspi_read_parameters, + .set_period = mptspi_write_period, + .show_period = 1, + .get_width = mptspi_read_parameters, + .set_width = mptspi_write_width, + .show_width = 1, + .get_iu = mptspi_read_parameters, + .set_iu = mptspi_write_iu, + .show_iu = 1, + .get_dt = mptspi_read_parameters, + .set_dt = mptspi_write_dt, + .show_dt = 1, + .get_qas = mptspi_read_parameters, + .set_qas = mptspi_write_qas, + .show_qas = 1, + .get_wr_flow = mptspi_read_parameters, + .set_wr_flow = mptspi_write_wr_flow, + .show_wr_flow = 1, + .get_rd_strm = mptspi_read_parameters, + .set_rd_strm = mptspi_write_rd_strm, + .show_rd_strm = 1, + .get_rti = mptspi_read_parameters, + .set_rti = mptspi_write_rti, + .show_rti = 1, + .get_pcomp_en = mptspi_read_parameters, + .set_pcomp_en = mptspi_write_pcomp_en, + .show_pcomp_en = 1, + .get_hold_mcs = mptspi_read_parameters, + .set_hold_mcs = mptspi_write_hold_mcs, + .show_hold_mcs = 1, + .deny_binding = mptspi_deny_binding, +}; /**************************************************************************** * Supported hardware @@ -242,7 +883,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) sh->max_id = MPT_MAX_SCSI_DEVICES; sh->max_lun = MPT_LAST_LUN + 1; - sh->max_channel = 0; + /* + * If RAID Firmware Detected, setup virtual channel + */ + if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) + > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) + sh->max_channel = 1; + else + sh->max_channel = 0; sh->this_id = ioc->pfacts[0].PortSCSIID; /* Required entry. @@ -301,7 +949,8 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) * indicates a device exists. * max_id = 1 + maximum id (hosts.h) */ - hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); + hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1), + sizeof(void *), GFP_ATOMIC); if (!hd->Targets) { error = -ENOMEM; goto out_mptspi_probe; @@ -334,49 +983,23 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->spi_data.Saf_Te = mpt_saf_te; hd->mpt_pq_filter = mpt_pq_filter; -#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - if (ioc->spi_data.maxBusWidth > mpt_width) - ioc->spi_data.maxBusWidth = mpt_width; - if (ioc->spi_data.minSyncFactor < mpt_factor) - ioc->spi_data.minSyncFactor = mpt_factor; - if (ioc->spi_data.minSyncFactor == MPT_ASYNC) { - ioc->spi_data.maxSyncOffset = 0; - } - ioc->spi_data.mpt_dv = mpt_dv; - hd->negoNvram = 0; - - ddvprintk((MYIOC_s_INFO_FMT - "dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n", - ioc->name, - mpt_dv, - mpt_width, - mpt_factor, - mpt_saf_te, - mpt_pq_filter)); -#else hd->negoNvram = MPT_SCSICFG_USE_NVRAM; ddvprintk((MYIOC_s_INFO_FMT "saf_te %x mpt_pq_filter %x\n", ioc->name, mpt_saf_te, mpt_pq_filter)); -#endif - - ioc->spi_data.forceDv = 0; ioc->spi_data.noQas = 0; - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) - ioc->spi_data.dvStatus[ii] = - MPT_SCSICFG_NEGOTIATE; - - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) - ioc->spi_data.dvStatus[ii] |= - MPT_SCSICFG_DV_NOT_DONE; - init_waitqueue_head(&hd->scandv_waitq); hd->scandv_wait_done = 0; hd->last_queue_full = 0; + /* Some versions of the firmware don't support page 0; without + * that we can't get the parameters */ + if (hd->ioc->spi_data.sdp0length != 0) + sh->transportt = mptspi_transport_template; + error = scsi_add_host (sh, &ioc->pcidev->dev); if(error) { dprintk((KERN_ERR MYNAM @@ -423,14 +1046,17 @@ static struct pci_driver mptspi_driver = { static int __init mptspi_init(void) { - show_mptmod_ver(my_NAME, my_VERSION); + mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions); + if (!mptspi_transport_template) + return -ENODEV; + mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); - if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) { + if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) { devtprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } @@ -465,6 +1091,7 @@ mptspi_exit(void) mpt_deregister(mptspiInternalCtx); mpt_deregister(mptspiTaskCtx); mpt_deregister(mptspiDoneCtx); + spi_release_transport(mptspi_transport_template); } module_init(mptspi_init); -- cgit v1.2.3-59-g8ed1b From 9d1ef8a64e21e57109be45a7345b09cf913e4b0e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 1 Mar 2006 14:23:14 -0500 Subject: [AGPGART] ATI RS350 support. From: Julien Tous Signed-off-by: Dave Jones --- drivers/char/agp/ati-agp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 4a26a2a01c2f..06fd10ba0c5e 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -466,6 +466,10 @@ static struct agp_device_ids ati_agp_device_ids[] __devinitdata = .device_id = PCI_DEVICE_ID_ATI_RS300_200, .chipset_name = "IGP9100/M", }, + { + .device_id = PCI_DEVICE_ID_ATI_RS350_200, + .chipset_name = "IGP9100/M", + }, { }, /* dummy final entry, always present */ }; -- cgit v1.2.3-59-g8ed1b From 4b9d7e04a8daaf3e5afe775ec9cbbfda5e32dd5b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 23 Feb 2006 10:46:47 +0900 Subject: [PATCH] sata_sil24: add a new PCI ID for SiI 3124 Add a new PCI ID for SiI 3124. Reported by Silicon Image. Signed-off-by: Tejun Heo Cc: Carlos Pardo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index a0e35a262156..5c5822e33a49 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -262,6 +262,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) static const struct pci_device_id sil24_pci_tbl[] = { { 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 }, + { 0x8086, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 }, { 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 }, { 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 }, { 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 }, -- cgit v1.2.3-59-g8ed1b From a9d01d2b49f528ffcf3093a77c66f254d297d5c8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 28 Feb 2006 17:38:10 +0900 Subject: [PATCH] libata: kill illegal kfree(id) Kill kfree(id) in failure path of ata_dev_read_id(). id is not dynamically allocated yet. Signed-off-by: Tejun Heo Cc: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 17c1df435cc8..e34b421eb2a3 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1040,7 +1040,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, err_out: printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n", ap->id, dev->devno, reason); - kfree(id); return rc; } -- cgit v1.2.3-59-g8ed1b From 348edc59a8f9b9a66700781d972c24a46a79ae86 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 19:07:27 +0900 Subject: [PATCH] sata_sil: remove unneeded ATA_FLAG_SRST from 3512 port info Now unneeded ATA_FLAG_SRST sneaked into sil_3512 port info while merging upstream-fixes. Kill it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 91ecf527bb8a..cdf800e3ec13 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -202,7 +202,7 @@ static const struct ata_port_info sil_port_info[] = { { .sht = &sil_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO | + ATA_FLAG_MMIO | SIL_FLAG_RERR_ON_DMA_ACT, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ -- cgit v1.2.3-59-g8ed1b From c1605eb37aa658b810a5a7080412d656ddce2f76 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:16:38 -0800 Subject: e1000: Remove Multiqueue code until we have support for MSI-X in our hardware Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000.h | 26 ----- drivers/net/e1000/e1000_ethtool.c | 43 -------- drivers/net/e1000/e1000_main.c | 227 +------------------------------------- 3 files changed, 4 insertions(+), 292 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 99baf0e099fc..658f36ad8b4f 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -83,10 +83,6 @@ struct e1000_adapter; #include "e1000_hw.h" -#ifdef CONFIG_E1000_MQ -#include -#include -#endif #ifdef DBG #define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args) @@ -169,12 +165,6 @@ struct e1000_buffer { uint16_t next_to_watch; }; -#ifdef CONFIG_E1000_MQ -struct e1000_queue_stats { - uint64_t packets; - uint64_t bytes; -}; -#endif struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; }; struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; }; @@ -198,12 +188,7 @@ struct e1000_tx_ring { spinlock_t tx_lock; uint16_t tdh; uint16_t tdt; - boolean_t last_tx_tso; - -#ifdef CONFIG_E1000_MQ - struct e1000_queue_stats tx_stats; -#endif }; struct e1000_rx_ring { @@ -230,9 +215,6 @@ struct e1000_rx_ring { uint16_t rdh; uint16_t rdt; -#ifdef CONFIG_E1000_MQ - struct e1000_queue_stats rx_stats; -#endif }; #define E1000_DESC_UNUSED(R) \ @@ -278,9 +260,6 @@ struct e1000_adapter { /* TX */ struct e1000_tx_ring *tx_ring; /* One per active queue */ -#ifdef CONFIG_E1000_MQ - struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */ -#endif unsigned long tx_queue_len; uint32_t txd_cmd; uint32_t tx_int_delay; @@ -313,11 +292,6 @@ struct e1000_adapter { struct e1000_rx_ring *rx_ring; /* One per active queue */ #ifdef CONFIG_E1000_NAPI struct net_device *polling_netdev; /* One per active queue */ -#endif -#ifdef CONFIG_E1000_MQ - struct net_device **cpu_netdev; /* per-cpu */ - struct call_async_data_struct rx_sched_call_data; - cpumask_t cpumask; #endif int num_tx_queues; int num_rx_queues; diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 5cedc81786e3..c7b47911f003 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -97,14 +97,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = { { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) }, }; -#ifdef CONFIG_E1000_MQ -#define E1000_QUEUE_STATS_LEN \ - (((struct e1000_adapter *)netdev->priv)->num_tx_queues + \ - ((struct e1000_adapter *)netdev->priv)->num_rx_queues) \ - * (sizeof(struct e1000_queue_stats) / sizeof(uint64_t)) -#else #define E1000_QUEUE_STATS_LEN 0 -#endif #define E1000_GLOBAL_STATS_LEN \ sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats) #define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN) @@ -1799,11 +1792,6 @@ e1000_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, uint64_t *data) { struct e1000_adapter *adapter = netdev_priv(netdev); -#ifdef CONFIG_E1000_MQ - uint64_t *queue_stat; - int stat_count = sizeof(struct e1000_queue_stats) / sizeof(uint64_t); - int j, k; -#endif int i; e1000_update_stats(adapter); @@ -1812,29 +1800,12 @@ e1000_get_ethtool_stats(struct net_device *netdev, data[i] = (e1000_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p; } -#ifdef CONFIG_E1000_MQ - for (j = 0; j < adapter->num_tx_queues; j++) { - queue_stat = (uint64_t *)&adapter->tx_ring[j].tx_stats; - for (k = 0; k < stat_count; k++) - data[i + k] = queue_stat[k]; - i += k; - } - for (j = 0; j < adapter->num_rx_queues; j++) { - queue_stat = (uint64_t *)&adapter->rx_ring[j].rx_stats; - for (k = 0; k < stat_count; k++) - data[i + k] = queue_stat[k]; - i += k; - } -#endif /* BUG_ON(i != E1000_STATS_LEN); */ } static void e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) { -#ifdef CONFIG_E1000_MQ - struct e1000_adapter *adapter = netdev_priv(netdev); -#endif uint8_t *p = data; int i; @@ -1849,20 +1820,6 @@ e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } -#ifdef CONFIG_E1000_MQ - for (i = 0; i < adapter->num_tx_queues; i++) { - sprintf(p, "tx_queue_%u_packets", i); - p += ETH_GSTRING_LEN; - sprintf(p, "tx_queue_%u_bytes", i); - p += ETH_GSTRING_LEN; - } - for (i = 0; i < adapter->num_rx_queues; i++) { - sprintf(p, "rx_queue_%u_packets", i); - p += ETH_GSTRING_LEN; - sprintf(p, "rx_queue_%u_bytes", i); - p += ETH_GSTRING_LEN; - } -#endif /* BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */ break; } diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5b7d0f425af2..af87eb04d832 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -103,7 +103,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #else #define DRIVERNAPI "-NAPI" #endif -#define DRV_VERSION "6.3.9-k4"DRIVERNAPI +#define DRV_VERSION "7.0.33-k2"DRIVERNAPI char e1000_driver_version[] = DRV_VERSION; static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; @@ -191,9 +191,6 @@ static void e1000_exit_module(void); static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static void __devexit e1000_remove(struct pci_dev *pdev); static int e1000_alloc_queues(struct e1000_adapter *adapter); -#ifdef CONFIG_E1000_MQ -static void e1000_setup_queue_mapping(struct e1000_adapter *adapter); -#endif static int e1000_sw_init(struct e1000_adapter *adapter); static int e1000_open(struct net_device *netdev); static int e1000_close(struct net_device *netdev); @@ -265,10 +262,6 @@ static int e1000_resume(struct pci_dev *pdev); static void e1000_netpoll (struct net_device *netdev); #endif -#ifdef CONFIG_E1000_MQ -/* for multiple Rx queues */ -void e1000_rx_schedule(void *data); -#endif /* Exported from other modules */ @@ -502,10 +495,6 @@ e1000_up(struct e1000_adapter *adapter) return err; } -#ifdef CONFIG_E1000_MQ - e1000_setup_queue_mapping(adapter); -#endif - adapter->tx_queue_len = netdev->tx_queue_len; mod_timer(&adapter->watchdog_timer, jiffies); @@ -526,9 +515,7 @@ e1000_down(struct e1000_adapter *adapter) e1000_check_mng_mode(&adapter->hw); e1000_irq_disable(adapter); -#ifdef CONFIG_E1000_MQ - while (atomic_read(&adapter->rx_sched_call_data.count) != 0); -#endif + free_irq(adapter->pdev->irq, netdev); #ifdef CONFIG_PCI_MSI if (adapter->hw.mac_type > e1000_82547_rev_2 && @@ -972,10 +959,6 @@ e1000_remove(struct pci_dev *pdev) iounmap(adapter->hw.hw_addr); pci_release_regions(pdev); -#ifdef CONFIG_E1000_MQ - free_percpu(adapter->cpu_netdev); - free_percpu(adapter->cpu_tx_ring); -#endif free_netdev(netdev); pci_disable_device(pdev); @@ -1056,40 +1039,8 @@ e1000_sw_init(struct e1000_adapter *adapter) hw->master_slave = E1000_MASTER_SLAVE; } -#ifdef CONFIG_E1000_MQ - /* Number of supported queues */ - switch (hw->mac_type) { - case e1000_82571: - case e1000_82572: - /* These controllers support 2 tx queues, but with a single - * qdisc implementation, multiple tx queues aren't quite as - * interesting. If we can find a logical way of mapping - * flows to a queue, then perhaps we can up the num_tx_queue - * count back to its default. Until then, we run the risk of - * terrible performance due to SACK overload. */ - adapter->num_tx_queues = 1; - adapter->num_rx_queues = 2; - break; - default: - adapter->num_tx_queues = 1; - adapter->num_rx_queues = 1; - break; - } - adapter->num_rx_queues = min(adapter->num_rx_queues, num_online_cpus()); - adapter->num_tx_queues = min(adapter->num_tx_queues, num_online_cpus()); - DPRINTK(DRV, INFO, "Multiqueue Enabled: Rx Queue count = %u %s\n", - adapter->num_rx_queues, - ((adapter->num_rx_queues == 1) - ? ((num_online_cpus() > 1) - ? "(due to unsupported feature in current adapter)" - : "(due to unsupported system configuration)") - : "")); - DPRINTK(DRV, INFO, "Multiqueue Enabled: Tx Queue count = %u\n", - adapter->num_tx_queues); -#else adapter->num_tx_queues = 1; adapter->num_rx_queues = 1; -#endif if (e1000_alloc_queues(adapter)) { DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); @@ -1152,51 +1103,9 @@ e1000_alloc_queues(struct e1000_adapter *adapter) memset(adapter->polling_netdev, 0, size); #endif -#ifdef CONFIG_E1000_MQ - adapter->rx_sched_call_data.func = e1000_rx_schedule; - adapter->rx_sched_call_data.info = adapter->netdev; - - adapter->cpu_netdev = alloc_percpu(struct net_device *); - adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *); -#endif - return E1000_SUCCESS; } -#ifdef CONFIG_E1000_MQ -static void __devinit -e1000_setup_queue_mapping(struct e1000_adapter *adapter) -{ - int i, cpu; - - adapter->rx_sched_call_data.func = e1000_rx_schedule; - adapter->rx_sched_call_data.info = adapter->netdev; - cpus_clear(adapter->rx_sched_call_data.cpumask); - - adapter->cpu_netdev = alloc_percpu(struct net_device *); - adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *); - - lock_cpu_hotplug(); - i = 0; - for_each_online_cpu(cpu) { - *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_tx_queues]; - /* This is incomplete because we'd like to assign separate - * physical cpus to these netdev polling structures and - * avoid saturating a subset of cpus. - */ - if (i < adapter->num_rx_queues) { - *per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i]; - adapter->rx_ring[i].cpu = cpu; - cpu_set(cpu, adapter->cpumask); - } else - *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL; - - i++; - } - unlock_cpu_hotplug(); -} -#endif - /** * e1000_open - Called when a network interface is made active * @netdev: network interface device structure @@ -1435,18 +1344,6 @@ e1000_configure_tx(struct e1000_adapter *adapter) /* Setup the HW Tx Head and Tail descriptor pointers */ switch (adapter->num_tx_queues) { - case 2: - tdba = adapter->tx_ring[1].dma; - tdlen = adapter->tx_ring[1].count * - sizeof(struct e1000_tx_desc); - E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL)); - E1000_WRITE_REG(hw, TDBAH1, (tdba >> 32)); - E1000_WRITE_REG(hw, TDLEN1, tdlen); - E1000_WRITE_REG(hw, TDH1, 0); - E1000_WRITE_REG(hw, TDT1, 0); - adapter->tx_ring[1].tdh = E1000_TDH1; - adapter->tx_ring[1].tdt = E1000_TDT1; - /* Fall Through */ case 1: default: tdba = adapter->tx_ring[0].dma; @@ -1790,10 +1687,6 @@ e1000_configure_rx(struct e1000_adapter *adapter) uint64_t rdba; struct e1000_hw *hw = &adapter->hw; uint32_t rdlen, rctl, rxcsum, ctrl_ext; -#ifdef CONFIG_E1000_MQ - uint32_t reta, mrqc; - int i; -#endif if (adapter->rx_ps_pages) { rdlen = adapter->rx_ring[0].count * @@ -1837,18 +1730,6 @@ e1000_configure_rx(struct e1000_adapter *adapter) /* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ switch (adapter->num_rx_queues) { -#ifdef CONFIG_E1000_MQ - case 2: - rdba = adapter->rx_ring[1].dma; - E1000_WRITE_REG(hw, RDBAL1, (rdba & 0x00000000ffffffffULL)); - E1000_WRITE_REG(hw, RDBAH1, (rdba >> 32)); - E1000_WRITE_REG(hw, RDLEN1, rdlen); - E1000_WRITE_REG(hw, RDH1, 0); - E1000_WRITE_REG(hw, RDT1, 0); - adapter->rx_ring[1].rdh = E1000_RDH1; - adapter->rx_ring[1].rdt = E1000_RDT1; - /* Fall Through */ -#endif case 1: default: rdba = adapter->rx_ring[0].dma; @@ -1862,46 +1743,6 @@ e1000_configure_rx(struct e1000_adapter *adapter) break; } -#ifdef CONFIG_E1000_MQ - if (adapter->num_rx_queues > 1) { - uint32_t random[10]; - - get_random_bytes(&random[0], 40); - - if (hw->mac_type <= e1000_82572) { - E1000_WRITE_REG(hw, RSSIR, 0); - E1000_WRITE_REG(hw, RSSIM, 0); - } - - switch (adapter->num_rx_queues) { - case 2: - default: - reta = 0x00800080; - mrqc = E1000_MRQC_ENABLE_RSS_2Q; - break; - } - - /* Fill out redirection table */ - for (i = 0; i < 32; i++) - E1000_WRITE_REG_ARRAY(hw, RETA, i, reta); - /* Fill out hash function seeds */ - for (i = 0; i < 10; i++) - E1000_WRITE_REG_ARRAY(hw, RSSRK, i, random[i]); - - mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 | - E1000_MRQC_RSS_FIELD_IPV4_TCP); - E1000_WRITE_REG(hw, MRQC, mrqc); - } - - /* Multiqueue and packet checksumming are mutually exclusive. */ - if (hw->mac_type >= e1000_82571) { - rxcsum = E1000_READ_REG(hw, RXCSUM); - rxcsum |= E1000_RXCSUM_PCSD; - E1000_WRITE_REG(hw, RXCSUM, rxcsum); - } - -#else - /* Enable 82543 Receive Checksum Offload for TCP and UDP */ if (hw->mac_type >= e1000_82543) { rxcsum = E1000_READ_REG(hw, RXCSUM); @@ -1920,7 +1761,6 @@ e1000_configure_rx(struct e1000_adapter *adapter) } E1000_WRITE_REG(hw, RXCSUM, rxcsum); } -#endif /* CONFIG_E1000_MQ */ if (hw->mac_type == e1000_82573) E1000_WRITE_REG(hw, ERT, 0x0100); @@ -2465,9 +2305,6 @@ e1000_watchdog_task(struct e1000_adapter *adapter) e1000_update_adaptive(&adapter->hw); -#ifdef CONFIG_E1000_MQ - txdr = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id()); -#endif if (!netif_carrier_ok(netdev)) { if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) { /* We've lost link, so the controller stops DMA, @@ -2881,11 +2718,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) unsigned int f; len -= skb->data_len; -#ifdef CONFIG_E1000_MQ - tx_ring = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id()); -#else tx_ring = adapter->tx_ring; -#endif if (unlikely(skb->len <= 0)) { dev_kfree_skb_any(skb); @@ -3288,29 +3121,6 @@ e1000_update_stats(struct e1000_adapter *adapter) spin_unlock_irqrestore(&adapter->stats_lock, flags); } -#ifdef CONFIG_E1000_MQ -void -e1000_rx_schedule(void *data) -{ - struct net_device *poll_dev, *netdev = data; - struct e1000_adapter *adapter = netdev->priv; - int this_cpu = get_cpu(); - - poll_dev = *per_cpu_ptr(adapter->cpu_netdev, this_cpu); - if (poll_dev == NULL) { - put_cpu(); - return; - } - - if (likely(netif_rx_schedule_prep(poll_dev))) - __netif_rx_schedule(poll_dev); - else - e1000_irq_enable(adapter); - - put_cpu(); -} -#endif - /** * e1000_intr - Interrupt Handler * @irq: interrupt number @@ -3355,26 +3165,11 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) E1000_WRITE_REG(hw, IMC, ~0); E1000_WRITE_FLUSH(hw); } -#ifdef CONFIG_E1000_MQ - if (atomic_read(&adapter->rx_sched_call_data.count) == 0) { - /* We must setup the cpumask once count == 0 since - * each cpu bit is cleared when the work is done. */ - adapter->rx_sched_call_data.cpumask = adapter->cpumask; - atomic_add(adapter->num_rx_queues - 1, &adapter->irq_sem); - atomic_set(&adapter->rx_sched_call_data.count, - adapter->num_rx_queues); - smp_call_async_mask(&adapter->rx_sched_call_data); - } else { - printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count)); - } -#else /* if !CONFIG_E1000_MQ */ if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0]))) __netif_rx_schedule(&adapter->polling_netdev[0]); else e1000_irq_enable(adapter); -#endif /* CONFIG_E1000_MQ */ - -#else /* if !CONFIG_E1000_NAPI */ +#else /* Writing IMC and IMS is needed for 82547. * Due to Hub Link bus being occupied, an interrupt * de-assertion message is not able to be sent. @@ -3398,7 +3193,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) e1000_irq_enable(adapter); -#endif /* CONFIG_E1000_NAPI */ +#endif return IRQ_HANDLED; } @@ -3486,18 +3281,12 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, buffer_info = &tx_ring->buffer_info[i]; cleaned = (i == eop); -#ifdef CONFIG_E1000_MQ - tx_ring->tx_stats.bytes += buffer_info->length; -#endif e1000_unmap_and_free_tx_resource(adapter, buffer_info); memset(tx_desc, 0, sizeof(struct e1000_tx_desc)); if (unlikely(++i == tx_ring->count)) i = 0; } -#ifdef CONFIG_E1000_MQ - tx_ring->tx_stats.packets++; -#endif eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); @@ -3733,10 +3522,6 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, } #endif /* CONFIG_E1000_NAPI */ netdev->last_rx = jiffies; -#ifdef CONFIG_E1000_MQ - rx_ring->rx_stats.packets++; - rx_ring->rx_stats.bytes += length; -#endif next_desc: rx_desc->status = 0; @@ -3878,10 +3663,6 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, } #endif /* CONFIG_E1000_NAPI */ netdev->last_rx = jiffies; -#ifdef CONFIG_E1000_MQ - rx_ring->rx_stats.packets++; - rx_ring->rx_stats.bytes += length; -#endif next_desc: rx_desc->wb.middle.status_error &= ~0xFF; -- cgit v1.2.3-59-g8ed1b From 9f644d518f35903ecaff062d6e9e4f7080d80cfb Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:16:59 -0800 Subject: e1000: Fix dead counters Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_ethtool.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index c7b47911f003..9c77413faf0c 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -60,7 +60,6 @@ static const struct e1000_stats e1000_gstrings_stats[] = { { "tx_bytes", E1000_STAT(net_stats.tx_bytes) }, { "rx_errors", E1000_STAT(net_stats.rx_errors) }, { "tx_errors", E1000_STAT(net_stats.tx_errors) }, - { "rx_dropped", E1000_STAT(net_stats.rx_dropped) }, { "tx_dropped", E1000_STAT(net_stats.tx_dropped) }, { "multicast", E1000_STAT(net_stats.multicast) }, { "collisions", E1000_STAT(net_stats.collisions) }, -- cgit v1.2.3-59-g8ed1b From 0989aa431636ffb347314f0e2f367fdd16d7a57f Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:17:16 -0800 Subject: e1000: Fix lock up while setting ring parameters Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_ethtool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 9c77413faf0c..f7e81e96a191 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -634,6 +634,9 @@ e1000_set_ringparam(struct net_device *netdev, struct e1000_rx_ring *rxdr, *rx_old, *rx_new; int i, err, tx_ring_size, rx_ring_size; + if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + return -EINVAL; + tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues; rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues; @@ -661,9 +664,6 @@ e1000_set_ringparam(struct net_device *netdev, txdr = adapter->tx_ring; rxdr = adapter->rx_ring; - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD); rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ? E1000_MAX_RXD : E1000_MAX_82544_RXD)); -- cgit v1.2.3-59-g8ed1b From 5b66ba0db8d04d99926445bc7d9f920bb5d744ed Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:17:30 -0800 Subject: e1000: Fix unecessary delay for 82573 controllers Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_hw.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index beeec0fbbeac..0af68bab974b 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -6746,12 +6746,6 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw) break; } - /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high. - * Need to wait for PHY configuration completion before accessing NVM - * and PHY. */ - if (hw->mac_type == e1000_82573) - msec_delay(25); - return E1000_SUCCESS; } -- cgit v1.2.3-59-g8ed1b From c5f226fe97e8025440aa330aa2c8e1c66bfdc96b Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:17:55 -0800 Subject: e1000: Fix AMT losing connectivity when switching VLAN in passive mode Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index af87eb04d832..0109cc72746c 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -373,7 +373,8 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter) (vid != old_vid) && !adapter->vlgrp->vlan_devices[old_vid]) e1000_vlan_rx_kill_vid(netdev, old_vid); - } + } else + adapter->mng_vlan_id = vid; } } -- cgit v1.2.3-59-g8ed1b From 20a44028f06030a71a1250ad8efb0a7fb556c3ea Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:18:08 -0800 Subject: e1000: Fix dhcp issue when the skb structure fields are not filled properly Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 0109cc72746c..a525c95266f1 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2678,7 +2678,7 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb) E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) ) return 0; } - if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) { + if (skb->len > MINIMUM_DHCP_PACKET_SIZE) { struct ethhdr *eth = (struct ethhdr *) skb->data; if ((htons(ETH_P_IP) == eth->h_proto)) { const struct iphdr *ip = -- cgit v1.2.3-59-g8ed1b From 497fce5e72a21f45929a786bf416ac03cbe09e2f Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:18:20 -0800 Subject: e1000: Fix 82543 issue when reading eeprom Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_hw.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 0af68bab974b..1b8869e39533 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -906,7 +906,13 @@ e1000_setup_link(struct e1000_hw *hw) * signal detection. So this should be done before e1000_setup_pcs_link() * or e1000_phy_setup() is called. */ - if(hw->mac_type == e1000_82543) { + if (hw->mac_type == e1000_82543) { + ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, + 1, &eeprom_data); + if (ret_val) { + DEBUGOUT("EEPROM Read Error\n"); + return -E1000_ERR_EEPROM; + } ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << SWDPIO__EXT_SHIFT); E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); -- cgit v1.2.3-59-g8ed1b From 8df06e504e999ff729f1b2a2e573d96bf3690dbc Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:18:32 -0800 Subject: e1000: Fix RSS if enabled in mid-connection Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_hw.c | 30 +++++++++++++++++++++++++++++- drivers/net/e1000/e1000_hw.h | 1 + 2 files changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 1b8869e39533..5ee42c75adb1 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -4755,8 +4755,36 @@ e1000_rar_set(struct e1000_hw *hw, rar_low = ((uint32_t) addr[0] | ((uint32_t) addr[1] << 8) | ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24)); + rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8)); - rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8) | E1000_RAH_AV); + /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx + * unit hang. + * + * Description: + * If there are any Rx frames queued up or otherwise present in the HW + * before RSS is enabled, and then we enable RSS, the HW Rx unit will + * hang. To work around this issue, we have to disable receives and + * flush out all Rx frames before we enable RSS. To do so, we modify we + * redirect all Rx traffic to manageability and then reset the HW. + * This flushes away Rx frames, and (since the redirections to + * manageability persists across resets) keeps new ones from coming in + * while we work. Then, we clear the Address Valid AV bit for all MAC + * addresses and undo the re-direction to manageability. + * Now, frames are coming in again, but the MAC won't accept them, so + * far so good. We now proceed to initialize RSS (if necessary) and + * configure the Rx unit. Last, we re-enable the AV bits and continue + * on our merry way. + */ + switch (hw->mac_type) { + case e1000_82571: + case e1000_82572: + if (hw->leave_av_bit_off == TRUE) + break; + default: + /* Indicate to hardware the Address is Valid. */ + rar_high |= E1000_RAH_AV; + break; + } E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low); E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high); diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index f1219dd9dbac..0848e556b1a9 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -1361,6 +1361,7 @@ struct e1000_hw { boolean_t ifs_params_forced; boolean_t in_ifs_mode; boolean_t mng_reg_access_disabled; + boolean_t leave_av_bit_off; }; -- cgit v1.2.3-59-g8ed1b From 8491682986e04fe7b258e5ba1d22f9a0ea2d803e Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:18:48 -0800 Subject: e1000: Fix Quadport Wake on LAN Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000.h | 1 + drivers/net/e1000/e1000_ethtool.c | 31 ++++++++++++++++++++++++++++++- drivers/net/e1000/e1000_main.c | 10 ++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 658f36ad8b4f..a18782748d5a 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -242,6 +242,7 @@ struct e1000_adapter { uint32_t rx_buffer_len; uint32_t part_num; uint32_t wol; + uint32_t ksp3_port_a; uint32_t smartspeed; uint32_t en_mng_pt; uint16_t link_speed; diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index f7e81e96a191..f1b9cf4643c9 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -1632,10 +1632,26 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) case E1000_DEV_ID_82546EB_QUAD_COPPER: case E1000_DEV_ID_82545EM_FIBER: case E1000_DEV_ID_82545EM_COPPER: + case E1000_DEV_ID_82546GB_QUAD_COPPER: wol->supported = 0; wol->wolopts = 0; return; + case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: + /* device id 10B5 port-A supports wol */ + if (!adapter->ksp3_port_a) { + wol->supported = 0; + return; + } + /* KSP3 does not suppport UCAST wake-ups for any interface */ + wol->supported = WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; + + if (adapter->wol & E1000_WUFC_EX) + DPRINTK(DRV, ERR, "Interface does not support " + "directed (unicast) frame wake-up packets\n"); + wol->wolopts = 0; + goto do_defaults; + case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546GB_FIBER: case E1000_DEV_ID_82571EB_FIBER: @@ -1650,8 +1666,9 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) default: wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; - wol->wolopts = 0; + +do_defaults: if (adapter->wol & E1000_WUFC_EX) wol->wolopts |= WAKE_UCAST; if (adapter->wol & E1000_WUFC_MC) @@ -1676,10 +1693,22 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) case E1000_DEV_ID_82543GC_COPPER: case E1000_DEV_ID_82544EI_FIBER: case E1000_DEV_ID_82546EB_QUAD_COPPER: + case E1000_DEV_ID_82546GB_QUAD_COPPER: case E1000_DEV_ID_82545EM_FIBER: case E1000_DEV_ID_82545EM_COPPER: return wol->wolopts ? -EOPNOTSUPP : 0; + case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: + /* device id 10B5 port-A supports wol */ + if (!adapter->ksp3_port_a) + return wol->wolopts ? -EOPNOTSUPP : 0; + + if (wol->wolopts & WAKE_UCAST) { + DPRINTK(DRV, ERR, "Interface does not support " + "directed (unicast) frame wake-up packets\n"); + return -EOPNOTSUPP; + } + case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546GB_FIBER: case E1000_DEV_ID_82571EB_FIBER: diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index a525c95266f1..aad5373a8aeb 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -651,6 +651,7 @@ e1000_probe(struct pci_dev *pdev, unsigned long mmio_start, mmio_len; static int cards_found = 0; + static int e1000_ksp3_port_a = 0; /* global ksp3 port a indication */ int i, err, pci_using_dac; uint16_t eeprom_data; uint16_t eeprom_apme_mask = E1000_EEPROM_APME; @@ -743,6 +744,15 @@ e1000_probe(struct pci_dev *pdev, if ((err = e1000_check_phy_reset_block(&adapter->hw))) DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); + /* if ksp3, indicate if it's port a being setup */ + if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 && + e1000_ksp3_port_a == 0) + adapter->ksp3_port_a = 1; + e1000_ksp3_port_a++; + /* Reset for multiple KP3 adapters */ + if (e1000_ksp3_port_a == 4) + e1000_ksp3_port_a = 0; + if (adapter->hw.mac_type >= e1000_82543) { netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | -- cgit v1.2.3-59-g8ed1b From 7e6c9861bbc2fcd2438da910c006781784968a7c Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:19:30 -0800 Subject: e1000: Fix network problems when forced at 100Mb/s and to fix TSO when forced at 100Mb/s Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000.h | 5 +++ drivers/net/e1000/e1000_ethtool.c | 3 ++ drivers/net/e1000/e1000_main.c | 67 +++++++++++++++++++++++++++++++++------ drivers/net/e1000/e1000_param.c | 2 +- 4 files changed, 66 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index a18782748d5a..3319c19cbee6 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -332,6 +332,11 @@ struct e1000_adapter { int msg_enable; #ifdef CONFIG_PCI_MSI boolean_t have_msi; +#endif + /* to not mess up cache alignment, always add to the bottom */ + boolean_t txb2b; +#ifdef NETIF_F_TSO + boolean_t tso_force; #endif }; #endif /* _E1000_H_ */ diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index f1b9cf4643c9..70238e089f16 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -338,6 +338,9 @@ e1000_set_tso(struct net_device *netdev, uint32_t data) netdev->features |= NETIF_F_TSO; else netdev->features &= ~NETIF_F_TSO; + + DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled"); + adapter->tso_force = TRUE; return 0; } #endif /* NETIF_F_TSO */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index aad5373a8aeb..6ee8ed5606f1 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1405,10 +1405,13 @@ e1000_configure_tx(struct e1000_adapter *adapter) tctl = E1000_READ_REG(hw, TCTL); tctl &= ~E1000_TCTL_CT; - tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC | + tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); - E1000_WRITE_REG(hw, TCTL, tctl); +#ifdef DISABLE_MULR + /* disable Multiple Reads for debugging */ + tctl &= ~E1000_TCTL_MULR; +#endif if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) { tarc = E1000_READ_REG(hw, TARC0); @@ -1439,6 +1442,9 @@ e1000_configure_tx(struct e1000_adapter *adapter) if (hw->mac_type == e1000_82544 && hw->bus_type == e1000_bus_type_pcix) adapter->pcix_82544 = 1; + + E1000_WRITE_REG(hw, TCTL, tctl); + } /** @@ -2243,7 +2249,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct e1000_tx_ring *txdr = adapter->tx_ring; - uint32_t link; + uint32_t link, tctl; e1000_check_for_link(&adapter->hw); if (adapter->hw.mac_type == e1000_82573) { @@ -2269,20 +2275,61 @@ e1000_watchdog_task(struct e1000_adapter *adapter) adapter->link_duplex == FULL_DUPLEX ? "Full Duplex" : "Half Duplex"); - /* tweak tx_queue_len according to speed/duplex */ + /* tweak tx_queue_len according to speed/duplex + * and adjust the timeout factor */ netdev->tx_queue_len = adapter->tx_queue_len; adapter->tx_timeout_factor = 1; - if (adapter->link_duplex == HALF_DUPLEX) { + adapter->txb2b = 1; + switch (adapter->link_speed) { + case SPEED_10: + adapter->txb2b = 0; + netdev->tx_queue_len = 10; + adapter->tx_timeout_factor = 8; + break; + case SPEED_100: + adapter->txb2b = 0; + netdev->tx_queue_len = 100; + /* maybe add some timeout factor ? */ + break; + } + + if ((adapter->hw.mac_type == e1000_82571 || + adapter->hw.mac_type == e1000_82572) && + adapter->txb2b == 0) { +#define SPEED_MODE_BIT (1 << 21) + uint32_t tarc0; + tarc0 = E1000_READ_REG(&adapter->hw, TARC0); + tarc0 &= ~SPEED_MODE_BIT; + E1000_WRITE_REG(&adapter->hw, TARC0, tarc0); + } + +#ifdef NETIF_F_TSO + /* disable TSO for pcie and 10/100 speeds, to avoid + * some hardware issues */ + if (!adapter->tso_force && + adapter->hw.bus_type == e1000_bus_type_pci_express){ switch (adapter->link_speed) { case SPEED_10: - netdev->tx_queue_len = 10; - adapter->tx_timeout_factor = 8; - break; case SPEED_100: - netdev->tx_queue_len = 100; + DPRINTK(PROBE,INFO, + "10/100 speed: disabling TSO\n"); + netdev->features &= ~NETIF_F_TSO; + break; + case SPEED_1000: + netdev->features |= NETIF_F_TSO; + break; + default: + /* oops */ break; } } +#endif + + /* enable transmits in the hardware, need to do this + * after setting TARC0 */ + tctl = E1000_READ_REG(&adapter->hw, TCTL); + tctl |= E1000_TCTL_EN; + E1000_WRITE_REG(&adapter->hw, TCTL, tctl); netif_carrier_on(netdev); netif_wake_queue(netdev); @@ -3319,7 +3366,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, adapter->detect_tx_hung = FALSE; if (tx_ring->buffer_info[eop].dma && time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + - adapter->tx_timeout_factor * HZ) + (adapter->tx_timeout_factor * HZ)) && !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) { diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index 3768d83cd577..e0a4d37d1b85 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -268,7 +268,7 @@ e1000_validate_option(int *value, struct e1000_option *opt, BUG(); } - DPRINTK(PROBE, INFO, "Invalid %s specified (%i) %s\n", + DPRINTK(PROBE, INFO, "Invalid %s value specified (%i) %s\n", opt->name, *value, opt->err); *value = opt->def; return -1; -- cgit v1.2.3-59-g8ed1b From 329bfd0b6d5ffec00b787f1d0e68eef63d8b1d56 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:20:02 -0800 Subject: e1000: Fix filling skb descriptors while using packet split - Simplified by calling skb_fill_page_desc(), which is more efficient. Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 6ee8ed5606f1..9e58419c8729 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3686,12 +3686,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j], PAGE_SIZE, PCI_DMA_FROMDEVICE); ps_page_dma->ps_page_dma[j] = 0; - skb_shinfo(skb)->frags[j].page = - ps_page->ps_page[j]; + skb_fill_page_desc(skb, j, ps_page->ps_page[j], 0, + length); ps_page->ps_page[j] = NULL; - skb_shinfo(skb)->frags[j].page_offset = 0; - skb_shinfo(skb)->frags[j].size = length; - skb_shinfo(skb)->nr_frags++; skb->len += length; skb->data_len += length; } -- cgit v1.2.3-59-g8ed1b From 9f68788856b134f93d9d10b19aa902924c61fc02 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:20:17 -0800 Subject: e1000: Add 82573 controller support to TSO fix Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_main.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 9e58419c8729..6603bd139064 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2796,21 +2796,29 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) max_per_txd = min(mss << 2, max_per_txd); max_txd_pwr = fls(max_per_txd) - 1; - /* TSO Workaround for 82571/2 Controllers -- if skb->data + /* TSO Workaround for 82571/2/3 Controllers -- if skb->data * points to just header, pull a few bytes of payload from * frags into skb->data */ hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); - if (skb->data_len && (hdr_len == (skb->len - skb->data_len)) && - (adapter->hw.mac_type == e1000_82571 || - adapter->hw.mac_type == e1000_82572)) { - unsigned int pull_size; - pull_size = min((unsigned int)4, skb->data_len); - if (!__pskb_pull_tail(skb, pull_size)) { - printk(KERN_ERR "__pskb_pull_tail failed.\n"); - dev_kfree_skb_any(skb); - return -EFAULT; + if (skb->data_len && (hdr_len == (skb->len - skb->data_len))) { + switch (adapter->hw.mac_type) { + unsigned int pull_size; + case e1000_82571: + case e1000_82572: + case e1000_82573: + pull_size = min((unsigned int)4, skb->data_len); + if (!__pskb_pull_tail(skb, pull_size)) { + printk(KERN_ERR + "__pskb_pull_tail failed.\n"); + dev_kfree_skb_any(skb); + return -EFAULT; + } + len = skb->len - skb->data_len; + break; + default: + /* do nothing */ + break; } - len = skb->len - skb->data_len; } } -- cgit v1.2.3-59-g8ed1b From 85b22eb632dc75887ba99edad49307a02c2ae7ec Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:20:29 -0800 Subject: e1000: Add enabled Jumbo frame support for 82573L Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_hw.h | 5 +++++ drivers/net/e1000/e1000_main.c | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 0848e556b1a9..f565b201c49e 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -1875,6 +1875,7 @@ struct e1000_hw { #define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ #define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ #define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */ +#define E1000_MANC_RCV_ALL 0x00080000 /* Receive All Enabled */ #define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ #define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address * filtering */ @@ -2036,6 +2037,7 @@ struct e1000_host_command_info { #define EEPROM_INIT_CONTROL1_REG 0x000A #define EEPROM_INIT_CONTROL2_REG 0x000F #define EEPROM_INIT_CONTROL3_PORT_B 0x0014 +#define EEPROM_INIT_3GIO_3 0x001A #define EEPROM_INIT_CONTROL3_PORT_A 0x0024 #define EEPROM_CFG 0x0012 #define EEPROM_FLASH_VERSION 0x0032 @@ -2085,6 +2087,9 @@ struct e1000_host_command_info { #define EEPROM_WORD0F_ANE 0x0800 #define EEPROM_WORD0F_SWPDIO_EXT 0x00F0 +/* Mask bits for fields in Word 0x1a of the EEPROM */ +#define EEPROM_WORD1A_ASPM_MASK 0x000C + /* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */ #define EEPROM_SUM 0xBABA diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 6603bd139064..58561a4955e3 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2978,6 +2978,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) { struct e1000_adapter *adapter = netdev_priv(netdev); int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; + uint16_t eeprom_data = 0; if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { @@ -2989,12 +2990,25 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) switch (adapter->hw.mac_type) { case e1000_82542_rev2_0: case e1000_82542_rev2_1: - case e1000_82573: if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) { DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n"); return -EINVAL; } break; + case e1000_82573: + /* only enable jumbo frames if ASPM is disabled completely + * this means both bits must be zero in 0x1A bits 3:2 */ + e1000_read_eeprom(&adapter->hw, EEPROM_INIT_3GIO_3, 1, + &eeprom_data); + if (eeprom_data & EEPROM_WORD1A_ASPM_MASK) { + if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) { + DPRINTK(PROBE, ERR, + "Jumbo Frames not supported.\n"); + return -EINVAL; + } + break; + } + /* fall through to get support */ case e1000_82571: case e1000_82572: #define MAX_STD_JUMBO_FRAME_SIZE 9234 -- cgit v1.2.3-59-g8ed1b From 2a1af5d7dfd809b16fb69f3f0fc073d9b6b7c6ac Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:20:43 -0800 Subject: e1000: Add performance enahancement by balancing TX and RX Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_main.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 58561a4955e3..e80378a220d4 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3349,6 +3349,9 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, struct e1000_tx_desc *tx_desc, *eop_desc; struct e1000_buffer *buffer_info; unsigned int i, eop; +#ifdef CONFIG_E1000_NAPI + unsigned int count = 0; +#endif boolean_t cleaned = FALSE; i = tx_ring->next_to_clean; @@ -3370,6 +3373,11 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); +#ifdef CONFIG_E1000_NAPI +#define E1000_TX_WEIGHT 64 + /* weight of a sort for tx, to avoid endless transmit cleanup */ + if (count++ == E1000_TX_WEIGHT) break; +#endif } tx_ring->next_to_clean = i; -- cgit v1.2.3-59-g8ed1b From 6418ecc68e1d9416451b6f78ebb2c0b077e0abf2 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:21:10 -0800 Subject: e1000: Add support for new hardware (ESB2) Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_ethtool.c | 3 + drivers/net/e1000/e1000_hw.c | 685 +++++++++++++++++++++++++++++++++++++- drivers/net/e1000/e1000_hw.h | 287 ++++++++++++++++ drivers/net/e1000/e1000_main.c | 5 + 4 files changed, 964 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 70238e089f16..0d6a16c5f8cd 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -589,6 +589,7 @@ e1000_get_drvinfo(struct net_device *netdev, case e1000_82571: case e1000_82572: case e1000_82573: + case e1000_80003es2lan: sprintf(firmware_version, "%d.%d-%d", (eeprom_data & 0xF000) >> 12, (eeprom_data & 0x0FF0) >> 4, @@ -762,6 +763,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) /* there are several bits on newer hardware that are r/w */ case e1000_82571: case e1000_82572: + case e1000_80003es2lan: toggle = 0x7FFFF3FF; break; case e1000_82573: @@ -1320,6 +1322,7 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter) case e1000_82571: case e1000_82572: case e1000_82573: + case e1000_80003es2lan: return e1000_integrated_phy_loopback(adapter); break; diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 5ee42c75adb1..63e237084a51 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -100,6 +100,8 @@ static void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, #define E1000_WRITE_REG_IO(a, reg, val) \ e1000_write_reg_io((a), E1000_##reg, val) +static int32_t e1000_configure_kmrn_for_10_100(struct e1000_hw *hw); +static int32_t e1000_configure_kmrn_for_1000(struct e1000_hw *hw); /* IGP cable length table */ static const @@ -153,6 +155,11 @@ e1000_set_phy_type(struct e1000_hw *hw) hw->phy_type = e1000_phy_igp; break; } + case GG82563_E_PHY_ID: + if (hw->mac_type == e1000_80003es2lan) { + hw->phy_type = e1000_phy_gg82563; + break; + } /* Fall Through */ default: /* Should never have loaded on this device */ @@ -353,12 +360,19 @@ e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_82573L: hw->mac_type = e1000_82573; break; + case E1000_DEV_ID_80003ES2LAN_COPPER_DPT: + case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: + hw->mac_type = e1000_80003es2lan; + break; default: /* Should never have loaded on this device */ return -E1000_ERR_MAC_TYPE; } switch(hw->mac_type) { + case e1000_80003es2lan: + hw->swfw_sync_present = TRUE; + /* fall through */ case e1000_82571: case e1000_82572: case e1000_82573: @@ -399,6 +413,7 @@ e1000_set_media_type(struct e1000_hw *hw) case E1000_DEV_ID_82546GB_SERDES: case E1000_DEV_ID_82571EB_SERDES: case E1000_DEV_ID_82572EI_SERDES: + case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: hw->media_type = e1000_media_type_internal_serdes; break; default: @@ -575,6 +590,7 @@ e1000_reset_hw(struct e1000_hw *hw) /* fall through */ case e1000_82571: case e1000_82572: + case e1000_80003es2lan: ret_val = e1000_get_auto_rd_done(hw); if(ret_val) /* We don't want to continue accessing MAC registers. */ @@ -641,6 +657,7 @@ e1000_init_hw(struct e1000_hw *hw) uint16_t cmd_mmrbc; uint16_t stat_mmrbc; uint32_t mta_size; + uint32_t reg_data; uint32_t ctrl_ext; DEBUGFUNC("e1000_init_hw"); @@ -739,6 +756,7 @@ e1000_init_hw(struct e1000_hw *hw) case e1000_82571: case e1000_82572: case e1000_82573: + case e1000_80003es2lan: ctrl |= E1000_TXDCTL_COUNT_DESC; break; } @@ -752,12 +770,34 @@ e1000_init_hw(struct e1000_hw *hw) switch (hw->mac_type) { default: break; + case e1000_80003es2lan: + /* Enable retransmit on late collisions */ + reg_data = E1000_READ_REG(hw, TCTL); + reg_data |= E1000_TCTL_RTLC; + E1000_WRITE_REG(hw, TCTL, reg_data); + + /* Configure Gigabit Carry Extend Padding */ + reg_data = E1000_READ_REG(hw, TCTL_EXT); + reg_data &= ~E1000_TCTL_EXT_GCEX_MASK; + reg_data |= DEFAULT_80003ES2LAN_TCTL_EXT_GCEX; + E1000_WRITE_REG(hw, TCTL_EXT, reg_data); + + /* Configure Transmit Inter-Packet Gap */ + reg_data = E1000_READ_REG(hw, TIPG); + reg_data &= ~E1000_TIPG_IPGT_MASK; + reg_data |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000; + E1000_WRITE_REG(hw, TIPG, reg_data); + + reg_data = E1000_READ_REG_ARRAY(hw, FFLT, 0x0001); + reg_data &= ~0x00100000; + E1000_WRITE_REG_ARRAY(hw, FFLT, 0x0001, reg_data); + /* Fall through */ case e1000_82571: case e1000_82572: ctrl = E1000_READ_REG(hw, TXDCTL1); - ctrl &= ~E1000_TXDCTL_WTHRESH; - ctrl |= E1000_TXDCTL_COUNT_DESC | E1000_TXDCTL_FULL_TX_DESC_WB; - ctrl |= (1 << 22); + ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; + if(hw->mac_type >= e1000_82571) + ctrl |= E1000_TXDCTL_COUNT_DESC; E1000_WRITE_REG(hw, TXDCTL1, ctrl); break; } @@ -1314,6 +1354,154 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw) return E1000_SUCCESS; } +/******************************************************************** +* Copper link setup for e1000_phy_gg82563 series. +* +* hw - Struct containing variables accessed by shared code +*********************************************************************/ +static int32_t +e1000_copper_link_ggp_setup(struct e1000_hw *hw) +{ + int32_t ret_val; + uint16_t phy_data; + uint32_t reg_data; + + DEBUGFUNC("e1000_copper_link_ggp_setup"); + + if(!hw->phy_reset_disable) { + + /* Enable CRS on TX for half-duplex operation. */ + ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, + &phy_data); + if(ret_val) + return ret_val; + + phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; + /* Use 25MHz for both link down and 1000BASE-T for Tx clock */ + phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ; + + ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, + phy_data); + if(ret_val) + return ret_val; + + /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ + ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL, &phy_data); + if(ret_val) + return ret_val; + + phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK; + + switch (hw->mdix) { + case 1: + phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDI; + break; + case 2: + phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDIX; + break; + case 0: + default: + phy_data |= GG82563_PSCR_CROSSOVER_MODE_AUTO; + break; + } + + /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE; + if(hw->disable_polarity_correction == 1) + phy_data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE; + ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data); + + if(ret_val) + return ret_val; + + /* SW Reset the PHY so all changes take effect */ + ret_val = e1000_phy_reset(hw); + if (ret_val) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } + } /* phy_reset_disable */ + + if (hw->mac_type == e1000_80003es2lan) { + /* Bypass RX and TX FIFO's */ + ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL, + E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS | + E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS); + if (ret_val) + return ret_val; + + ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, &phy_data); + if (ret_val) + return ret_val; + + phy_data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG; + ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, phy_data); + + if (ret_val) + return ret_val; + + reg_data = E1000_READ_REG(hw, CTRL_EXT); + reg_data &= ~(E1000_CTRL_EXT_LINK_MODE_MASK); + E1000_WRITE_REG(hw, CTRL_EXT, reg_data); + + ret_val = e1000_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, + &phy_data); + if (ret_val) + return ret_val; + + /* Do not init these registers when the HW is in IAMT mode, since the + * firmware will have already initialized them. We only initialize + * them if the HW is not in IAMT mode. + */ + if (e1000_check_mng_mode(hw) == FALSE) { + /* Enable Electrical Idle on the PHY */ + phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; + ret_val = e1000_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, + phy_data); + if (ret_val) + return ret_val; + + ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + &phy_data); + if (ret_val) + return ret_val; + + /* Enable Pass False Carrier on the PHY */ + phy_data |= GG82563_KMCR_PASS_FALSE_CARRIER; + + ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, + phy_data); + if (ret_val) + return ret_val; + } + + /* Workaround: Disable padding in Kumeran interface in the MAC + * and in the PHY to avoid CRC errors. + */ + ret_val = e1000_read_phy_reg(hw, GG82563_PHY_INBAND_CTRL, + &phy_data); + if (ret_val) + return ret_val; + phy_data |= GG82563_ICR_DIS_PADDING; + ret_val = e1000_write_phy_reg(hw, GG82563_PHY_INBAND_CTRL, + phy_data); + if (ret_val) + return ret_val; + } + + return E1000_SUCCESS; +} /******************************************************************** * Copper link setup for e1000_phy_m88 series. @@ -1524,6 +1712,7 @@ e1000_setup_copper_link(struct e1000_hw *hw) int32_t ret_val; uint16_t i; uint16_t phy_data; + uint16_t reg_data; DEBUGFUNC("e1000_setup_copper_link"); @@ -1532,6 +1721,22 @@ e1000_setup_copper_link(struct e1000_hw *hw) if(ret_val) return ret_val; + switch (hw->mac_type) { + case e1000_80003es2lan: + ret_val = e1000_read_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL, + ®_data); + if (ret_val) + return ret_val; + reg_data |= E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING; + ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL, + reg_data); + if (ret_val) + return ret_val; + break; + default: + break; + } + if (hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2) { ret_val = e1000_copper_link_igp_setup(hw); @@ -1541,6 +1746,10 @@ e1000_setup_copper_link(struct e1000_hw *hw) ret_val = e1000_copper_link_mgp_setup(hw); if(ret_val) return ret_val; + } else if (hw->phy_type == e1000_phy_gg82563) { + ret_val = e1000_copper_link_ggp_setup(hw); + if(ret_val) + return ret_val; } if(hw->autoneg) { @@ -1587,6 +1796,59 @@ e1000_setup_copper_link(struct e1000_hw *hw) return E1000_SUCCESS; } +/****************************************************************************** +* Configure the MAC-to-PHY interface for 10/100Mbps +* +* hw - Struct containing variables accessed by shared code +******************************************************************************/ +static int32_t +e1000_configure_kmrn_for_10_100(struct e1000_hw *hw) +{ + int32_t ret_val = E1000_SUCCESS; + uint32_t tipg; + uint16_t reg_data; + + DEBUGFUNC("e1000_configure_kmrn_for_10_100"); + + reg_data = E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT; + ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL, + reg_data); + if (ret_val) + return ret_val; + + /* Configure Transmit Inter-Packet Gap */ + tipg = E1000_READ_REG(hw, TIPG); + tipg &= ~E1000_TIPG_IPGT_MASK; + tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_10_100; + E1000_WRITE_REG(hw, TIPG, tipg); + + return ret_val; +} + +static int32_t +e1000_configure_kmrn_for_1000(struct e1000_hw *hw) +{ + int32_t ret_val = E1000_SUCCESS; + uint16_t reg_data; + uint32_t tipg; + + DEBUGFUNC("e1000_configure_kmrn_for_1000"); + + reg_data = E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT; + ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL, + reg_data); + if (ret_val) + return ret_val; + + /* Configure Transmit Inter-Packet Gap */ + tipg = E1000_READ_REG(hw, TIPG); + tipg &= ~E1000_TIPG_IPGT_MASK; + tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000; + E1000_WRITE_REG(hw, TIPG, tipg); + + return ret_val; +} + /****************************************************************************** * Configures PHY autoneg and flow control advertisement settings * @@ -1808,7 +2070,8 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); - if (hw->phy_type == e1000_phy_m88) { + if ((hw->phy_type == e1000_phy_m88) || + (hw->phy_type == e1000_phy_gg82563)) { ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if(ret_val) return ret_val; @@ -1877,7 +2140,8 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) msec_delay(100); } if((i == 0) && - (hw->phy_type == e1000_phy_m88)) { + ((hw->phy_type == e1000_phy_m88) || + (hw->phy_type == e1000_phy_gg82563))) { /* We didn't get link. Reset the DSP and wait again for link. */ ret_val = e1000_phy_reset_dsp(hw); if(ret_val) { @@ -1936,6 +2200,27 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) if(ret_val) return ret_val; } + } else if (hw->phy_type == e1000_phy_gg82563) { + /* The TX_CLK of the Extended PHY Specific Control Register defaults + * to 2.5MHz on a reset. We need to re-force it back to 25MHz, if + * we're not in a forced 10/duplex configuration. */ + ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); + if (ret_val) + return ret_val; + + phy_data &= ~GG82563_MSCR_TX_CLK_MASK; + if ((hw->forced_speed_duplex == e1000_10_full) || + (hw->forced_speed_duplex == e1000_10_half)) + phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ; + else + phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25MHZ; + + /* Also due to the reset, we need to enable CRS on Tx. */ + phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; + + ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data); + if (ret_val) + return ret_val; } return E1000_SUCCESS; } @@ -2598,6 +2883,16 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw, } } + if ((hw->mac_type == e1000_80003es2lan) && + (hw->media_type == e1000_media_type_copper)) { + if (*speed == SPEED_1000) + ret_val = e1000_configure_kmrn_for_1000(hw); + else + ret_val = e1000_configure_kmrn_for_10_100(hw); + if (ret_val) + return ret_val; + } + return E1000_SUCCESS; } @@ -2773,6 +3068,72 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw) return data; } +int32_t +e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask) +{ + uint32_t swfw_sync = 0; + uint32_t swmask = mask; + uint32_t fwmask = mask << 16; + int32_t timeout = 200; + + DEBUGFUNC("e1000_swfw_sync_acquire"); + + if (!hw->swfw_sync_present) + return e1000_get_hw_eeprom_semaphore(hw); + + while(timeout) { + if (e1000_get_hw_eeprom_semaphore(hw)) + return -E1000_ERR_SWFW_SYNC; + + swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC); + if (!(swfw_sync & (fwmask | swmask))) { + break; + } + + /* firmware currently using resource (fwmask) */ + /* or other software thread currently using resource (swmask) */ + e1000_put_hw_eeprom_semaphore(hw); + msec_delay_irq(5); + timeout--; + } + + if (!timeout) { + DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); + return -E1000_ERR_SWFW_SYNC; + } + + swfw_sync |= swmask; + E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync); + + e1000_put_hw_eeprom_semaphore(hw); + return E1000_SUCCESS; +} + +void +e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask) +{ + uint32_t swfw_sync; + uint32_t swmask = mask; + + DEBUGFUNC("e1000_swfw_sync_release"); + + if (!hw->swfw_sync_present) { + e1000_put_hw_eeprom_semaphore(hw); + return; + } + + /* if (e1000_get_hw_eeprom_semaphore(hw)) + * return -E1000_ERR_SWFW_SYNC; */ + while (e1000_get_hw_eeprom_semaphore(hw) != E1000_SUCCESS); + /* empty */ + + swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC); + swfw_sync &= ~swmask; + E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync); + + e1000_put_hw_eeprom_semaphore(hw); +} + /***************************************************************************** * Reads the value from a PHY register, if the value is on a specific non zero * page, sets the page first. @@ -2785,22 +3146,55 @@ e1000_read_phy_reg(struct e1000_hw *hw, uint16_t *phy_data) { uint32_t ret_val; + uint16_t swfw; DEBUGFUNC("e1000_read_phy_reg"); + if ((hw->mac_type == e1000_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (e1000_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + if((hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, (uint16_t)reg_addr); if(ret_val) { + e1000_swfw_sync_release(hw, swfw); return ret_val; } + } else if (hw->phy_type == e1000_phy_gg82563) { + if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) || + (hw->mac_type == e1000_80003es2lan)) { + /* Select Configuration Page */ + if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { + ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } else { + /* Use Alternative Page Select register to access + * registers 30 and 31 + */ + ret_val = e1000_write_phy_reg_ex(hw, + GG82563_PHY_PAGE_SELECT_ALT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } + + if (ret_val) { + e1000_swfw_sync_release(hw, swfw); + return ret_val; + } + } } ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, phy_data); + e1000_swfw_sync_release(hw, swfw); return ret_val; } @@ -2891,22 +3285,55 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint16_t phy_data) { uint32_t ret_val; + uint16_t swfw; DEBUGFUNC("e1000_write_phy_reg"); + if ((hw->mac_type == e1000_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (e1000_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + if((hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, (uint16_t)reg_addr); if(ret_val) { + e1000_swfw_sync_release(hw, swfw); return ret_val; } + } else if (hw->phy_type == e1000_phy_gg82563) { + if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) || + (hw->mac_type == e1000_80003es2lan)) { + /* Select Configuration Page */ + if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { + ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } else { + /* Use Alternative Page Select register to access + * registers 30 and 31 + */ + ret_val = e1000_write_phy_reg_ex(hw, + GG82563_PHY_PAGE_SELECT_ALT, + (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT)); + } + + if (ret_val) { + e1000_swfw_sync_release(hw, swfw); + return ret_val; + } + } } ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, phy_data); + e1000_swfw_sync_release(hw, swfw); return ret_val; } @@ -2973,6 +3400,65 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, return E1000_SUCCESS; } +int32_t +e1000_read_kmrn_reg(struct e1000_hw *hw, + uint32_t reg_addr, + uint16_t *data) +{ + uint32_t reg_val; + uint16_t swfw; + DEBUGFUNC("e1000_read_kmrn_reg"); + + if ((hw->mac_type == e1000_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (e1000_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + + /* Write register address */ + reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) & + E1000_KUMCTRLSTA_OFFSET) | + E1000_KUMCTRLSTA_REN; + E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val); + udelay(2); + + /* Read the data returned */ + reg_val = E1000_READ_REG(hw, KUMCTRLSTA); + *data = (uint16_t)reg_val; + + e1000_swfw_sync_release(hw, swfw); + return E1000_SUCCESS; +} + +int32_t +e1000_write_kmrn_reg(struct e1000_hw *hw, + uint32_t reg_addr, + uint16_t data) +{ + uint32_t reg_val; + uint16_t swfw; + DEBUGFUNC("e1000_write_kmrn_reg"); + + if ((hw->mac_type == e1000_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (e1000_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + + reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) & + E1000_KUMCTRLSTA_OFFSET) | data; + E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val); + udelay(2); + + e1000_swfw_sync_release(hw, swfw); + return E1000_SUCCESS; +} /****************************************************************************** * Returns the PHY to the power-on reset state @@ -2985,6 +3471,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw) uint32_t ctrl, ctrl_ext; uint32_t led_ctrl; int32_t ret_val; + uint16_t swfw; DEBUGFUNC("e1000_phy_hw_reset"); @@ -2997,6 +3484,16 @@ e1000_phy_hw_reset(struct e1000_hw *hw) DEBUGOUT("Resetting Phy...\n"); if(hw->mac_type > e1000_82543) { + if ((hw->mac_type == e1000_80003es2lan) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + swfw = E1000_SWFW_PHY1_SM; + } else { + swfw = E1000_SWFW_PHY0_SM; + } + if (e1000_swfw_sync_acquire(hw, swfw)) { + e1000_release_software_semaphore(hw); + return -E1000_ERR_SWFW_SYNC; + } /* Read the device control register and assert the E1000_CTRL_PHY_RST * bit. Then, take it out of reset. * For pre-e1000_82571 hardware, we delay for 10ms between the assert @@ -3017,6 +3514,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw) if (hw->mac_type >= e1000_82571) msec_delay(10); + e1000_swfw_sync_release(hw, swfw); } else { /* Read the Extended Device Control Register, assert the PHY_RESET_DIR * bit to put the PHY into reset. Then, take it out of reset. @@ -3043,6 +3541,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw) /* Wait for FW to finish PHY configuration. */ ret_val = e1000_get_phy_cfg_done(hw); + e1000_release_software_semaphore(hw); return ret_val; } @@ -3120,6 +3619,15 @@ e1000_detect_gig_phy(struct e1000_hw *hw) return E1000_SUCCESS; } + /* ESB-2 PHY reads require e1000_phy_gg82563 to be set because of a work- + * around that forces PHY page 0 to be set or the reads fail. The rest of + * the code in this routine uses e1000_read_phy_reg to read the PHY ID. + * So for ESB-2 we need to have this set so our reads won't fail. If the + * attached PHY is not a e1000_phy_gg82563, the routines below will figure + * this out as well. */ + if (hw->mac_type == e1000_80003es2lan) + hw->phy_type = e1000_phy_gg82563; + /* Read the PHY ID Registers to identify which PHY is onboard. */ ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high); if(ret_val) @@ -3157,6 +3665,9 @@ e1000_detect_gig_phy(struct e1000_hw *hw) case e1000_82573: if(hw->phy_id == M88E1111_I_PHY_ID) match = TRUE; break; + case e1000_80003es2lan: + if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE; + break; default: DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type); return -E1000_ERR_CONFIG; @@ -3183,8 +3694,10 @@ e1000_phy_reset_dsp(struct e1000_hw *hw) DEBUGFUNC("e1000_phy_reset_dsp"); do { - ret_val = e1000_write_phy_reg(hw, 29, 0x001d); - if(ret_val) break; + if (hw->phy_type != e1000_phy_gg82563) { + ret_val = e1000_write_phy_reg(hw, 29, 0x001d); + if(ret_val) break; + } ret_val = e1000_write_phy_reg(hw, 30, 0x00c1); if(ret_val) break; ret_val = e1000_write_phy_reg(hw, 30, 0x0000); @@ -3316,8 +3829,17 @@ e1000_phy_m88_get_info(struct e1000_hw *hw, /* Cable Length Estimation and Local/Remote Receiver Information * are only valid at 1000 Mbps. */ - phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT); + if (hw->phy_type != e1000_phy_gg82563) { + phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> + M88E1000_PSSR_CABLE_LENGTH_SHIFT); + } else { + ret_val = e1000_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE, + &phy_data); + if (ret_val) + return ret_val; + + phy_info->cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH; + } ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); if(ret_val) @@ -3511,6 +4033,20 @@ e1000_init_eeprom_params(struct e1000_hw *hw) E1000_WRITE_REG(hw, EECD, eecd); } break; + case e1000_80003es2lan: + eeprom->type = e1000_eeprom_spi; + eeprom->opcode_bits = 8; + eeprom->delay_usec = 1; + if (eecd & E1000_EECD_ADDR_BITS) { + eeprom->page_size = 32; + eeprom->address_bits = 16; + } else { + eeprom->page_size = 8; + eeprom->address_bits = 8; + } + eeprom->use_eerd = TRUE; + eeprom->use_eewr = FALSE; + break; default: break; } @@ -3691,9 +4227,8 @@ e1000_acquire_eeprom(struct e1000_hw *hw) DEBUGFUNC("e1000_acquire_eeprom"); - if(e1000_get_hw_eeprom_semaphore(hw)) - return -E1000_ERR_EEPROM; - + if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM)) + return -E1000_ERR_SWFW_SYNC; eecd = E1000_READ_REG(hw, EECD); if (hw->mac_type != e1000_82573) { @@ -3712,7 +4247,7 @@ e1000_acquire_eeprom(struct e1000_hw *hw) eecd &= ~E1000_EECD_REQ; E1000_WRITE_REG(hw, EECD, eecd); DEBUGOUT("Could not acquire EEPROM grant\n"); - e1000_put_hw_eeprom_semaphore(hw); + e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM); return -E1000_ERR_EEPROM; } } @@ -3835,7 +4370,7 @@ e1000_release_eeprom(struct e1000_hw *hw) E1000_WRITE_REG(hw, EECD, eecd); } - e1000_put_hw_eeprom_semaphore(hw); + e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM); } /****************************************************************************** @@ -3914,6 +4449,8 @@ e1000_read_eeprom(struct e1000_hw *hw, if (e1000_is_onboard_nvm_eeprom(hw) == TRUE && hw->eeprom.use_eerd == FALSE) { switch (hw->mac_type) { + case e1000_80003es2lan: + break; default: /* Prepare the EEPROM for reading */ if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) @@ -4031,6 +4568,9 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw, uint32_t i = 0; int32_t error = 0; + if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM)) + return -E1000_ERR_SWFW_SYNC; + for (i = 0; i < words; i++) { register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | @@ -4050,6 +4590,7 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw, } } + e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM); return error; } @@ -4091,6 +4632,8 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw) { uint32_t eecd = 0; + DEBUGFUNC("e1000_is_onboard_nvm_eeprom"); + if(hw->mac_type == e1000_82573) { eecd = E1000_READ_REG(hw, EECD); @@ -4517,6 +5060,7 @@ e1000_read_mac_addr(struct e1000_hw * hw) case e1000_82546: case e1000_82546_rev_3: case e1000_82571: + case e1000_80003es2lan: if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) hw->perm_mac_addr[5] ^= 0x01; break; @@ -4778,6 +5322,7 @@ e1000_rar_set(struct e1000_hw *hw, switch (hw->mac_type) { case e1000_82571: case e1000_82572: + case e1000_80003es2lan: if (hw->leave_av_bit_off == TRUE) break; default: @@ -5364,6 +5909,7 @@ e1000_get_bus_info(struct e1000_hw *hw) hw->bus_width = e1000_bus_width_pciex_1; break; case e1000_82571: + case e1000_80003es2lan: hw->bus_type = e1000_bus_type_pci_express; hw->bus_speed = e1000_bus_speed_2500; hw->bus_width = e1000_bus_width_pciex_4; @@ -5509,6 +6055,34 @@ e1000_get_cable_length(struct e1000_hw *hw, return -E1000_ERR_PHY; break; } + } else if (hw->phy_type == e1000_phy_gg82563) { + ret_val = e1000_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE, + &phy_data); + if (ret_val) + return ret_val; + cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH; + + switch (cable_length) { + case e1000_gg_cable_length_60: + *min_length = 0; + *max_length = e1000_igp_cable_length_60; + break; + case e1000_gg_cable_length_60_115: + *min_length = e1000_igp_cable_length_60; + *max_length = e1000_igp_cable_length_115; + break; + case e1000_gg_cable_length_115_150: + *min_length = e1000_igp_cable_length_115; + *max_length = e1000_igp_cable_length_150; + break; + case e1000_gg_cable_length_150: + *min_length = e1000_igp_cable_length_150; + *max_length = e1000_igp_cable_length_180; + break; + default: + return -E1000_ERR_PHY; + break; + } } else if(hw->phy_type == e1000_phy_igp) { /* For IGP PHY */ uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {IGP01E1000_PHY_AGC_A, @@ -5618,7 +6192,8 @@ e1000_check_polarity(struct e1000_hw *hw, DEBUGFUNC("e1000_check_polarity"); - if(hw->phy_type == e1000_phy_m88) { + if ((hw->phy_type == e1000_phy_m88) || + (hw->phy_type == e1000_phy_gg82563)) { /* return the Polarity bit in the Status register. */ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); @@ -5687,7 +6262,8 @@ e1000_check_downshift(struct e1000_hw *hw) return ret_val; hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; - } else if(hw->phy_type == e1000_phy_m88) { + } else if ((hw->phy_type == e1000_phy_m88) || + (hw->phy_type == e1000_phy_gg82563)) { ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if(ret_val) @@ -6720,6 +7296,7 @@ e1000_get_auto_rd_done(struct e1000_hw *hw) case e1000_82571: case e1000_82572: case e1000_82573: + case e1000_80003es2lan: while(timeout) { if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break; else msec_delay(1); @@ -6763,6 +7340,11 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw) default: msec_delay(10); break; + case e1000_80003es2lan: + /* Separate *_CFG_DONE_* bit for each port */ + if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) + cfg_mask = E1000_EEPROM_CFG_DONE_PORT_1; + /* Fall Through */ case e1000_82571: case e1000_82572: while (timeout) { @@ -6805,6 +7387,11 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw) if(!hw->eeprom_semaphore_present) return E1000_SUCCESS; + if (hw->mac_type == e1000_80003es2lan) { + /* Get the SW semaphore. */ + if (e1000_get_software_semaphore(hw) != E1000_SUCCESS) + return -E1000_ERR_EEPROM; + } /* Get the FW semaphore. */ timeout = hw->eeprom.word_size + 1; @@ -6850,10 +7437,75 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw) return; swsm = E1000_READ_REG(hw, SWSM); + if (hw->mac_type == e1000_80003es2lan) { + /* Release both semaphores. */ + swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); + } else swsm &= ~(E1000_SWSM_SWESMBI); E1000_WRITE_REG(hw, SWSM, swsm); } +/*************************************************************************** + * + * Obtaining software semaphore bit (SMBI) before resetting PHY. + * + * hw: Struct containing variables accessed by shared code + * + * returns: - E1000_ERR_RESET if fail to obtain semaphore. + * E1000_SUCCESS at any other case. + * + ***************************************************************************/ +int32_t +e1000_get_software_semaphore(struct e1000_hw *hw) +{ + int32_t timeout = hw->eeprom.word_size + 1; + uint32_t swsm; + + DEBUGFUNC("e1000_get_software_semaphore"); + + if (hw->mac_type != e1000_80003es2lan) + return E1000_SUCCESS; + + while(timeout) { + swsm = E1000_READ_REG(hw, SWSM); + /* If SMBI bit cleared, it is now set and we hold the semaphore */ + if(!(swsm & E1000_SWSM_SMBI)) + break; + msec_delay_irq(1); + timeout--; + } + + if(!timeout) { + DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); + return -E1000_ERR_RESET; + } + + return E1000_SUCCESS; +} + +/*************************************************************************** + * + * Release semaphore bit (SMBI). + * + * hw: Struct containing variables accessed by shared code + * + ***************************************************************************/ +void +e1000_release_software_semaphore(struct e1000_hw *hw) +{ + uint32_t swsm; + + DEBUGFUNC("e1000_release_software_semaphore"); + + if (hw->mac_type != e1000_80003es2lan) + return; + + swsm = E1000_READ_REG(hw, SWSM); + /* Release the SW semaphores.*/ + swsm &= ~E1000_SWSM_SMBI; + E1000_WRITE_REG(hw, SWSM, swsm); +} + /****************************************************************************** * Checks if PHY reset is blocked due to SOL/IDER session, for example. * Returning E1000_BLK_PHY_RESET isn't necessarily an error. But it's up to @@ -6890,6 +7542,7 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw) case e1000_82571: case e1000_82572: case e1000_82573: + case e1000_80003es2lan: fwsm = E1000_READ_REG(hw, FWSM); if((fwsm & E1000_FWSM_MODE_MASK) != 0) return TRUE; diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index f565b201c49e..947a156bd702 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -60,6 +60,7 @@ typedef enum { e1000_82571, e1000_82572, e1000_82573, + e1000_80003es2lan, e1000_num_macs } e1000_mac_type; @@ -138,6 +139,13 @@ typedef enum { e1000_cable_length_undefined = 0xFF } e1000_cable_length; +typedef enum { + e1000_gg_cable_length_60 = 0, + e1000_gg_cable_length_60_115 = 1, + e1000_gg_cable_length_115_150 = 2, + e1000_gg_cable_length_150 = 4 +} e1000_gg_cable_length; + typedef enum { e1000_igp_cable_length_10 = 10, e1000_igp_cable_length_20 = 20, @@ -208,6 +216,7 @@ typedef enum { e1000_phy_m88 = 0, e1000_phy_igp, e1000_phy_igp_2, + e1000_phy_gg82563, e1000_phy_undefined = 0xFF } e1000_phy_type; @@ -281,6 +290,7 @@ typedef enum { #define E1000_ERR_MASTER_REQUESTS_PENDING 10 #define E1000_ERR_HOST_INTERFACE_COMMAND 11 #define E1000_BLK_PHY_RESET 12 +#define E1000_ERR_SWFW_SYNC 13 /* Function prototypes */ /* Initialization */ @@ -304,6 +314,8 @@ int32_t e1000_phy_hw_reset(struct e1000_hw *hw); int32_t e1000_phy_reset(struct e1000_hw *hw); int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); int32_t e1000_validate_mdi_setting(struct e1000_hw *hw); +int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data); +int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data); /* EEPROM Functions */ int32_t e1000_init_eeprom_params(struct e1000_hw *hw); @@ -454,6 +466,8 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); #define E1000_DEV_ID_82573E_IAMT 0x108C #define E1000_DEV_ID_82573L 0x109A #define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5 +#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 +#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 #define NODE_ADDRESS_SIZE 6 @@ -850,6 +864,7 @@ struct e1000_ffvt_entry { #define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ #define E1000_RXCW 0x00180 /* RX Configuration Word - RO */ #define E1000_TCTL 0x00400 /* TX Control - RW */ +#define E1000_TCTL_EXT 0x00404 /* Extended TX Control - RW */ #define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */ #define E1000_TBT 0x00448 /* TX Burst Timer - RW */ #define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ @@ -996,6 +1011,11 @@ struct e1000_ffvt_entry { #define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ #define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ +#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */ +#define E1000_MDPHYA 0x0003C /* PHY address - RW */ +#define E1000_MANC2H 0x05860 /* Managment Control To Host - RW */ +#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ + #define E1000_GCR 0x05B00 /* PCI-Ex Control */ #define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */ #define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */ @@ -1065,6 +1085,7 @@ struct e1000_ffvt_entry { #define E1000_82542_RXCW E1000_RXCW #define E1000_82542_MTA 0x00200 #define E1000_82542_TCTL E1000_TCTL +#define E1000_82542_TCTL_EXT E1000_TCTL_EXT #define E1000_82542_TIPG E1000_TIPG #define E1000_82542_TDBAL 0x00420 #define E1000_82542_TDBAH 0x00424 @@ -1212,6 +1233,8 @@ struct e1000_ffvt_entry { #define E1000_82542_RSSRK E1000_RSSRK #define E1000_82542_RSSIM E1000_RSSIM #define E1000_82542_RSSIR E1000_RSSIR +#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA +#define E1000_82542_SW_FW_SYNC E1000_SW_FW_SYNC /* Statistics counters collected by the MAC */ struct e1000_hw_stats { @@ -1303,6 +1326,7 @@ struct e1000_hw { e1000_ffe_config ffe_config_state; uint32_t asf_firmware_present; uint32_t eeprom_semaphore_present; + uint32_t swfw_sync_present; unsigned long io_base; uint32_t phy_id; uint32_t phy_revision; @@ -1394,6 +1418,8 @@ struct e1000_hw { #define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ #define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */ #define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */ +#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */ +#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */ #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ #define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ @@ -1430,6 +1456,16 @@ struct e1000_hw { #define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ #define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ #define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ +#define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disabled */ +#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */ +#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */ +#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */ +#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution disabled */ +#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */ +#define E1000_STATUS_FUSE_8 0x04000000 +#define E1000_STATUS_FUSE_9 0x08000000 +#define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disabled on port 0 */ +#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */ /* Constants used to intrepret the masked PCI-X bus speed. */ #define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ @@ -1507,6 +1543,8 @@ struct e1000_hw { #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 #define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 +#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000 +#define E1000_CTRL_EXT_LINK_MODE_SERDES 0x00C00000 #define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000 #define E1000_CTRL_EXT_WR_WMARK_256 0x00000000 #define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 @@ -1516,6 +1554,9 @@ struct e1000_hw { #define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ #define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ #define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ +#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error detection enabled */ +#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */ +#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 /* MDI Control */ #define E1000_MDIC_DATA_MASK 0x0000FFFF @@ -1529,6 +1570,32 @@ struct e1000_hw { #define E1000_MDIC_INT_EN 0x20000000 #define E1000_MDIC_ERROR 0x40000000 +#define E1000_KUMCTRLSTA_MASK 0x0000FFFF +#define E1000_KUMCTRLSTA_OFFSET 0x001F0000 +#define E1000_KUMCTRLSTA_OFFSET_SHIFT 16 +#define E1000_KUMCTRLSTA_REN 0x00200000 + +#define E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL 0x00000000 +#define E1000_KUMCTRLSTA_OFFSET_CTRL 0x00000001 +#define E1000_KUMCTRLSTA_OFFSET_INB_CTRL 0x00000002 +#define E1000_KUMCTRLSTA_OFFSET_DIAG 0x00000003 +#define E1000_KUMCTRLSTA_OFFSET_TIMEOUTS 0x00000004 +#define E1000_KUMCTRLSTA_OFFSET_INB_PARAM 0x00000009 +#define E1000_KUMCTRLSTA_OFFSET_HD_CTRL 0x00000010 +#define E1000_KUMCTRLSTA_OFFSET_M2P_SERDES 0x0000001E +#define E1000_KUMCTRLSTA_OFFSET_M2P_MODES 0x0000001F + +/* FIFO Control */ +#define E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS 0x00000008 +#define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS 0x00000800 + +/* In-Band Control */ +#define E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING 0x00000010 + +/* Half-Duplex Control */ +#define E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004 +#define E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT 0x00000000 + /* LED Control */ #define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F #define E1000_LEDCTL_LED0_MODE_SHIFT 0 @@ -1591,6 +1658,13 @@ struct e1000_hw { #define E1000_ICR_MNG 0x00040000 /* Manageability event */ #define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ #define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ +#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity error */ +#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */ +#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */ +#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */ +#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */ /* Interrupt Cause Set */ #define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1611,6 +1685,12 @@ struct e1000_hw { #define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ +#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ +#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ +#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1631,6 +1711,12 @@ struct e1000_hw { #define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ +#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ +#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ +#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ /* Interrupt Mask Clear */ #define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1651,6 +1737,12 @@ struct e1000_hw { #define E1000_IMC_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_IMC_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_IMC_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_IMC_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ +#define E1000_IMC_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ +#define E1000_IMC_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ +#define E1000_IMC_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ +#define E1000_IMC_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ +#define E1000_IMC_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ /* Receive Control */ #define E1000_RCTL_RST 0x00000001 /* Software reset */ @@ -1720,6 +1812,12 @@ struct e1000_hw { #define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */ #define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ +/* SW_W_SYNC definitions */ +#define E1000_SWFW_EEP_SM 0x0001 +#define E1000_SWFW_PHY0_SM 0x0002 +#define E1000_SWFW_PHY1_SM 0x0004 +#define E1000_SWFW_MAC_CSR_SM 0x0008 + /* Receive Descriptor */ #define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ #define E1000_RDT_FPDB 0x80000000 /* Flush descriptor block */ @@ -1798,6 +1896,11 @@ struct e1000_hw { #define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ #define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ #define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ +/* Extended Transmit Control */ +#define E1000_TCTL_EXT_BST_MASK 0x000003FF /* Backoff Slot Time */ +#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */ + +#define DEFAULT_80003ES2LAN_TCTL_EXT_GCEX 0x00010000 /* Receive Checksum Control */ #define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */ @@ -2044,6 +2147,7 @@ struct e1000_host_command_info { #define EEPROM_CHECKSUM_REG 0x003F #define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */ +#define E1000_EEPROM_CFG_DONE_PORT_1 0x00080000 /* ...for second port */ /* Word definitions for ID LED Settings */ #define ID_LED_RESERVED_0000 0x0000 @@ -2132,8 +2236,11 @@ struct e1000_host_command_info { #define DEFAULT_82542_TIPG_IPGR2 10 #define DEFAULT_82543_TIPG_IPGR2 6 +#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7 #define E1000_TIPG_IPGR2_SHIFT 20 +#define DEFAULT_80003ES2LAN_TIPG_IPGT_10_100 0x00000009 +#define DEFAULT_80003ES2LAN_TIPG_IPGT_1000 0x00000008 #define E1000_TXDMAC_DPP 0x00000001 /* Adaptive IFS defines */ @@ -2374,6 +2481,78 @@ struct e1000_host_command_info { #define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 +/* Bits... + * 15-5: page + * 4-0: register offset + */ +#define GG82563_PAGE_SHIFT 5 +#define GG82563_REG(page, reg) \ + (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS)) +#define GG82563_MIN_ALT_REG 30 + +/* GG82563 Specific Registers */ +#define GG82563_PHY_SPEC_CTRL \ + GG82563_REG(0, 16) /* PHY Specific Control */ +#define GG82563_PHY_SPEC_STATUS \ + GG82563_REG(0, 17) /* PHY Specific Status */ +#define GG82563_PHY_INT_ENABLE \ + GG82563_REG(0, 18) /* Interrupt Enable */ +#define GG82563_PHY_SPEC_STATUS_2 \ + GG82563_REG(0, 19) /* PHY Specific Status 2 */ +#define GG82563_PHY_RX_ERR_CNTR \ + GG82563_REG(0, 21) /* Receive Error Counter */ +#define GG82563_PHY_PAGE_SELECT \ + GG82563_REG(0, 22) /* Page Select */ +#define GG82563_PHY_SPEC_CTRL_2 \ + GG82563_REG(0, 26) /* PHY Specific Control 2 */ +#define GG82563_PHY_PAGE_SELECT_ALT \ + GG82563_REG(0, 29) /* Alternate Page Select */ +#define GG82563_PHY_TEST_CLK_CTRL \ + GG82563_REG(0, 30) /* Test Clock Control (use reg. 29 to select) */ + +#define GG82563_PHY_MAC_SPEC_CTRL \ + GG82563_REG(2, 21) /* MAC Specific Control Register */ +#define GG82563_PHY_MAC_SPEC_CTRL_2 \ + GG82563_REG(2, 26) /* MAC Specific Control 2 */ + +#define GG82563_PHY_DSP_DISTANCE \ + GG82563_REG(5, 26) /* DSP Distance */ + +/* Page 193 - Port Control Registers */ +#define GG82563_PHY_KMRN_MODE_CTRL \ + GG82563_REG(193, 16) /* Kumeran Mode Control */ +#define GG82563_PHY_PORT_RESET \ + GG82563_REG(193, 17) /* Port Reset */ +#define GG82563_PHY_REVISION_ID \ + GG82563_REG(193, 18) /* Revision ID */ +#define GG82563_PHY_DEVICE_ID \ + GG82563_REG(193, 19) /* Device ID */ +#define GG82563_PHY_PWR_MGMT_CTRL \ + GG82563_REG(193, 20) /* Power Management Control */ +#define GG82563_PHY_RATE_ADAPT_CTRL \ + GG82563_REG(193, 25) /* Rate Adaptation Control */ + +/* Page 194 - KMRN Registers */ +#define GG82563_PHY_KMRN_FIFO_CTRL_STAT \ + GG82563_REG(194, 16) /* FIFO's Control/Status */ +#define GG82563_PHY_KMRN_CTRL \ + GG82563_REG(194, 17) /* Control */ +#define GG82563_PHY_INBAND_CTRL \ + GG82563_REG(194, 18) /* Inband Control */ +#define GG82563_PHY_KMRN_DIAGNOSTIC \ + GG82563_REG(194, 19) /* Diagnostic */ +#define GG82563_PHY_ACK_TIMEOUTS \ + GG82563_REG(194, 20) /* Acknowledge Timeouts */ +#define GG82563_PHY_ADV_ABILITY \ + GG82563_REG(194, 21) /* Advertised Ability */ +#define GG82563_PHY_LINK_PARTNER_ADV_ABILITY \ + GG82563_REG(194, 23) /* Link Partner Advertised Ability */ +#define GG82563_PHY_ADV_NEXT_PAGE \ + GG82563_REG(194, 24) /* Advertised Next Page */ +#define GG82563_PHY_LINK_PARTNER_ADV_NEXT_PAGE \ + GG82563_REG(194, 25) /* Link Partner Advertised Next page */ +#define GG82563_PHY_KMRN_MISC \ + GG82563_REG(194, 26) /* Misc. */ /* PHY Control Register */ #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ @@ -2687,6 +2866,113 @@ struct e1000_host_command_info { #define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080 #define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500 +/* GG82563 PHY Specific Status Register (Page 0, Register 16 */ +#define GG82563_PSCR_DISABLE_JABBER 0x0001 /* 1=Disable Jabber */ +#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Polarity Reversal Disabled */ +#define GG82563_PSCR_POWER_DOWN 0x0004 /* 1=Power Down */ +#define GG82563_PSCR_COPPER_TRANSMITER_DISABLE 0x0008 /* 1=Transmitter Disabled */ +#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060 +#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI configuration */ +#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX configuration */ +#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Automatic crossover */ +#define GG82563_PSCR_ENALBE_EXTENDED_DISTANCE 0x0080 /* 1=Enable Extended Distance */ +#define GG82563_PSCR_ENERGY_DETECT_MASK 0x0300 +#define GG82563_PSCR_ENERGY_DETECT_OFF 0x0000 /* 00,01=Off */ +#define GG82563_PSCR_ENERGY_DETECT_RX 0x0200 /* 10=Sense on Rx only (Energy Detect) */ +#define GG82563_PSCR_ENERGY_DETECT_RX_TM 0x0300 /* 11=Sense and Tx NLP */ +#define GG82563_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force Link Good */ +#define GG82563_PSCR_DOWNSHIFT_ENABLE 0x0800 /* 1=Enable Downshift */ +#define GG82563_PSCR_DOWNSHIFT_COUNTER_MASK 0x7000 +#define GG82563_PSCR_DOWNSHIFT_COUNTER_SHIFT 12 + +/* PHY Specific Status Register (Page 0, Register 17) */ +#define GG82563_PSSR_JABBER 0x0001 /* 1=Jabber */ +#define GG82563_PSSR_POLARITY 0x0002 /* 1=Polarity Reversed */ +#define GG82563_PSSR_LINK 0x0008 /* 1=Link is Up */ +#define GG82563_PSSR_ENERGY_DETECT 0x0010 /* 1=Sleep, 0=Active */ +#define GG82563_PSSR_DOWNSHIFT 0x0020 /* 1=Downshift */ +#define GG82563_PSSR_CROSSOVER_STATUS 0x0040 /* 1=MDIX, 0=MDI */ +#define GG82563_PSSR_RX_PAUSE_ENABLED 0x0100 /* 1=Receive Pause Enabled */ +#define GG82563_PSSR_TX_PAUSE_ENABLED 0x0200 /* 1=Transmit Pause Enabled */ +#define GG82563_PSSR_LINK_UP 0x0400 /* 1=Link Up */ +#define GG82563_PSSR_SPEED_DUPLEX_RESOLVED 0x0800 /* 1=Resolved */ +#define GG82563_PSSR_PAGE_RECEIVED 0x1000 /* 1=Page Received */ +#define GG82563_PSSR_DUPLEX 0x2000 /* 1-Full-Duplex */ +#define GG82563_PSSR_SPEED_MASK 0xC000 +#define GG82563_PSSR_SPEED_10MBPS 0x0000 /* 00=10Mbps */ +#define GG82563_PSSR_SPEED_100MBPS 0x4000 /* 01=100Mbps */ +#define GG82563_PSSR_SPEED_1000MBPS 0x8000 /* 10=1000Mbps */ + +/* PHY Specific Status Register 2 (Page 0, Register 19) */ +#define GG82563_PSSR2_JABBER 0x0001 /* 1=Jabber */ +#define GG82563_PSSR2_POLARITY_CHANGED 0x0002 /* 1=Polarity Changed */ +#define GG82563_PSSR2_ENERGY_DETECT_CHANGED 0x0010 /* 1=Energy Detect Changed */ +#define GG82563_PSSR2_DOWNSHIFT_INTERRUPT 0x0020 /* 1=Downshift Detected */ +#define GG82563_PSSR2_MDI_CROSSOVER_CHANGE 0x0040 /* 1=Crossover Changed */ +#define GG82563_PSSR2_FALSE_CARRIER 0x0100 /* 1=False Carrier */ +#define GG82563_PSSR2_SYMBOL_ERROR 0x0200 /* 1=Symbol Error */ +#define GG82563_PSSR2_LINK_STATUS_CHANGED 0x0400 /* 1=Link Status Changed */ +#define GG82563_PSSR2_AUTO_NEG_COMPLETED 0x0800 /* 1=Auto-Neg Completed */ +#define GG82563_PSSR2_PAGE_RECEIVED 0x1000 /* 1=Page Received */ +#define GG82563_PSSR2_DUPLEX_CHANGED 0x2000 /* 1=Duplex Changed */ +#define GG82563_PSSR2_SPEED_CHANGED 0x4000 /* 1=Speed Changed */ +#define GG82563_PSSR2_AUTO_NEG_ERROR 0x8000 /* 1=Auto-Neg Error */ + +/* PHY Specific Control Register 2 (Page 0, Register 26) */ +#define GG82563_PSCR2_10BT_POLARITY_FORCE 0x0002 /* 1=Force Negative Polarity */ +#define GG82563_PSCR2_1000MB_TEST_SELECT_MASK 0x000C +#define GG82563_PSCR2_1000MB_TEST_SELECT_NORMAL 0x0000 /* 00,01=Normal Operation */ +#define GG82563_PSCR2_1000MB_TEST_SELECT_112NS 0x0008 /* 10=Select 112ns Sequence */ +#define GG82563_PSCR2_1000MB_TEST_SELECT_16NS 0x000C /* 11=Select 16ns Sequence */ +#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 /* 1=Reverse Auto-Negotiation */ +#define GG82563_PSCR2_1000BT_DISABLE 0x4000 /* 1=Disable 1000BASE-T */ +#define GG82563_PSCR2_TRANSMITER_TYPE_MASK 0x8000 +#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_B 0x0000 /* 0=Class B */ +#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_A 0x8000 /* 1=Class A */ + +/* MAC Specific Control Register (Page 2, Register 21) */ +/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */ +#define GG82563_MSCR_TX_CLK_MASK 0x0007 +#define GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ 0x0004 +#define GG82563_MSCR_TX_CLK_100MBPS_25MHZ 0x0005 +#define GG82563_MSCR_TX_CLK_1000MBPS_2_5MHZ 0x0006 +#define GG82563_MSCR_TX_CLK_1000MBPS_25MHZ 0x0007 + +#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */ + +/* DSP Distance Register (Page 5, Register 26) */ +#define GG82563_DSPD_CABLE_LENGTH 0x0007 /* 0 = <50M; + 1 = 50-80M; + 2 = 80-110M; + 3 = 110-140M; + 4 = >140M */ + +/* Kumeran Mode Control Register (Page 193, Register 16) */ +#define GG82563_KMCR_PHY_LEDS_EN 0x0020 /* 1=PHY LEDs, 0=Kumeran Inband LEDs */ +#define GG82563_KMCR_FORCE_LINK_UP 0x0040 /* 1=Force Link Up */ +#define GG82563_KMCR_SUPPRESS_SGMII_EPD_EXT 0x0080 +#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT_MASK 0x0400 +#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT 0x0400 /* 1=6.25MHz, 0=0.8MHz */ +#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 + +/* Power Management Control Register (Page 193, Register 20) */ +#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 /* 1=Enalbe SERDES Electrical Idle */ +#define GG82563_PMCR_DISABLE_PORT 0x0002 /* 1=Disable Port */ +#define GG82563_PMCR_DISABLE_SERDES 0x0004 /* 1=Disable SERDES */ +#define GG82563_PMCR_REVERSE_AUTO_NEG 0x0008 /* 1=Enable Reverse Auto-Negotiation */ +#define GG82563_PMCR_DISABLE_1000_NON_D0 0x0010 /* 1=Disable 1000Mbps Auto-Neg in non D0 */ +#define GG82563_PMCR_DISABLE_1000 0x0020 /* 1=Disable 1000Mbps Auto-Neg Always */ +#define GG82563_PMCR_REVERSE_AUTO_NEG_D0A 0x0040 /* 1=Enable D0a Reverse Auto-Negotiation */ +#define GG82563_PMCR_FORCE_POWER_STATE 0x0080 /* 1=Force Power State */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_MASK 0x0300 +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_DR 0x0000 /* 00=Dr */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0U 0x0100 /* 01=D0u */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0A 0x0200 /* 10=D0a */ +#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D3 0x0300 /* 11=D3 */ + +/* In-Band Control Register (Page 194, Register 18) */ +#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding Use */ + /* Bit definitions for valid PHY IDs. */ /* I = Integrated @@ -2701,6 +2987,7 @@ struct e1000_host_command_info { #define M88E1011_I_REV_4 0x04 #define M88E1111_I_PHY_ID 0x01410CC0 #define L1LXT971A_PHY_ID 0x001378E0 +#define GG82563_E_PHY_ID 0x01410CA0 /* Miscellaneous PHY bit definitions. */ #define PHY_PREAMBLE 0xFFFFFFFF diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index e80378a220d4..3acbffd5bde3 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -157,9 +157,12 @@ static struct pci_device_id e1000_pci_tbl[] = { INTEL_E1000_ETHERNET_DEVICE(0x108A), INTEL_E1000_ETHERNET_DEVICE(0x108B), INTEL_E1000_ETHERNET_DEVICE(0x108C), + INTEL_E1000_ETHERNET_DEVICE(0x1096), + INTEL_E1000_ETHERNET_DEVICE(0x1098), INTEL_E1000_ETHERNET_DEVICE(0x1099), INTEL_E1000_ETHERNET_DEVICE(0x109A), INTEL_E1000_ETHERNET_DEVICE(0x10B5), + INTEL_E1000_ETHERNET_DEVICE(0x10B9), /* required last entry */ {0,} }; @@ -575,6 +578,7 @@ e1000_reset(struct e1000_adapter *adapter) break; case e1000_82571: case e1000_82572: + case e1000_80003es2lan: pba = E1000_PBA_38K; break; case e1000_82573: @@ -852,6 +856,7 @@ e1000_probe(struct pci_dev *pdev, case e1000_82546: case e1000_82546_rev_3: case e1000_82571: + case e1000_80003es2lan: if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){ e1000_read_eeprom(&adapter->hw, EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); -- cgit v1.2.3-59-g8ed1b From 8704163987882f8b989e8143ad1f87c6b7229a13 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:21:24 -0800 Subject: e1000: Fixed the following issues with ESB2 (requires ESB2 support): - Add restriction for ESB2 to MTU size <=9216 - Removed FIFO errors which were not being used - Fixed issues with loopback - Power management change for saving state and config space - WA to disable recieves and reset device on link loss. Reset needed to be done outside the interrupt context - modified existing tx_timeout_task Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000.h | 4 +-- drivers/net/e1000/e1000_ethtool.c | 10 +++++- drivers/net/e1000/e1000_main.c | 65 ++++++++++++++++++++++++++++++++------- 3 files changed, 65 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 3319c19cbee6..d4266f18bbd9 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -252,8 +252,8 @@ struct e1000_adapter { spinlock_t tx_queue_lock; #endif atomic_t irq_sem; - struct work_struct tx_timeout_task; struct work_struct watchdog_task; + struct work_struct reset_task; uint8_t fc_autoneg; struct timer_list blink_timer; @@ -328,7 +328,7 @@ struct e1000_adapter { struct e1000_rx_ring test_rx_ring; - u32 *config_space; + uint32_t *config_space; int msg_enable; #ifdef CONFIG_PCI_MSI boolean_t have_msi; diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 0d6a16c5f8cd..44d39f1d8298 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -67,7 +67,6 @@ static const struct e1000_stats e1000_gstrings_stats[] = { { "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) }, { "rx_crc_errors", E1000_STAT(net_stats.rx_crc_errors) }, { "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) }, - { "rx_fifo_errors", E1000_STAT(net_stats.rx_fifo_errors) }, { "rx_no_buffer_count", E1000_STAT(stats.rnbc) }, { "rx_missed_errors", E1000_STAT(net_stats.rx_missed_errors) }, { "tx_aborted_errors", E1000_STAT(net_stats.tx_aborted_errors) }, @@ -1253,6 +1252,10 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter) e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140); /* autoneg off */ e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140); + } else if (adapter->hw.phy_type == e1000_phy_gg82563) { + e1000_write_phy_reg(&adapter->hw, + GG82563_PHY_KMRN_MODE_CTRL, + 0x1CE); } /* force 1000, set loopback */ e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140); @@ -1403,6 +1406,11 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter) case e1000_82546_rev_3: default: hw->autoneg = TRUE; + if (hw->phy_type == e1000_phy_gg82563) { + e1000_write_phy_reg(hw, + GG82563_PHY_KMRN_MODE_CTRL, + 0x180); + } e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg); if (phy_reg & MII_CR_LOOPBACK) { phy_reg &= ~MII_CR_LOOPBACK; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 3acbffd5bde3..431b03ee077e 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -245,7 +245,7 @@ void e1000_set_ethtool_ops(struct net_device *netdev); static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static void e1000_tx_timeout(struct net_device *dev); -static void e1000_tx_timeout_task(struct net_device *dev); +static void e1000_reset_task(struct net_device *dev); static void e1000_smartspeed(struct e1000_adapter *adapter); static inline int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb); @@ -611,7 +611,10 @@ e1000_reset(struct e1000_adapter *adapter) adapter->hw.fc_high_water = fc_high_water_mark; adapter->hw.fc_low_water = fc_high_water_mark - 8; - adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME; + if (adapter->hw.mac_type == e1000_80003es2lan) + adapter->hw.fc_pause_time = 0xFFFF; + else + adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME; adapter->hw.fc_send_xon = 1; adapter->hw.fc = adapter->hw.original_fc; @@ -828,8 +831,8 @@ e1000_probe(struct pci_dev *pdev, adapter->phy_info_timer.function = &e1000_update_phy_info; adapter->phy_info_timer.data = (unsigned long) adapter; - INIT_WORK(&adapter->tx_timeout_task, - (void (*)(void *))e1000_tx_timeout_task, netdev); + INIT_WORK(&adapter->reset_task, + (void (*)(void *))e1000_reset_task, netdev); /* we're going to reset, so assume we have no link for now */ @@ -1390,6 +1393,10 @@ e1000_configure_tx(struct e1000_adapter *adapter) ipgr1 = DEFAULT_82542_TIPG_IPGR1; ipgr2 = DEFAULT_82542_TIPG_IPGR2; break; + case e1000_80003es2lan: + ipgr1 = DEFAULT_82543_TIPG_IPGR1; + ipgr2 = DEFAULT_80003ES2LAN_TIPG_IPGR2; + break; default: ipgr1 = DEFAULT_82543_TIPG_IPGR1; ipgr2 = DEFAULT_82543_TIPG_IPGR2; @@ -1429,6 +1436,15 @@ e1000_configure_tx(struct e1000_adapter *adapter) else tarc |= (1 << 28); E1000_WRITE_REG(hw, TARC1, tarc); + } else if (hw->mac_type == e1000_80003es2lan) { + tarc = E1000_READ_REG(hw, TARC0); + tarc |= 1; + if (hw->media_type == e1000_media_type_internal_serdes) + tarc |= (1 << 20); + E1000_WRITE_REG(hw, TARC0, tarc); + tarc = E1000_READ_REG(hw, TARC1); + tarc |= 1; + E1000_WRITE_REG(hw, TARC1, tarc); } e1000_config_collision_dist(hw); @@ -2349,6 +2365,16 @@ e1000_watchdog_task(struct e1000_adapter *adapter) netif_carrier_off(netdev); netif_stop_queue(netdev); mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ); + + /* 80003ES2LAN workaround-- + * For packet buffer work-around on link down event; + * disable receives in the ISR and + * reset device here in the watchdog + */ + if (adapter->hw.mac_type == e1000_80003es2lan) { + /* reset device */ + schedule_work(&adapter->reset_task); + } } e1000_smartspeed(adapter); @@ -2374,7 +2400,8 @@ e1000_watchdog_task(struct e1000_adapter *adapter) * but we've got queued Tx work that's never going * to get done, so reset controller to flush Tx. * (Do the reset outside of interrupt context). */ - schedule_work(&adapter->tx_timeout_task); + adapter->tx_timeout_count++; + schedule_work(&adapter->reset_task); } } @@ -2940,15 +2967,15 @@ e1000_tx_timeout(struct net_device *netdev) struct e1000_adapter *adapter = netdev_priv(netdev); /* Do the reset outside of interrupt context */ - schedule_work(&adapter->tx_timeout_task); + adapter->tx_timeout_count++; + schedule_work(&adapter->reset_task); } static void -e1000_tx_timeout_task(struct net_device *netdev) +e1000_reset_task(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); - adapter->tx_timeout_count++; e1000_down(adapter); e1000_up(adapter); } @@ -3016,6 +3043,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) /* fall through to get support */ case e1000_82571: case e1000_82572: + case e1000_80003es2lan: #define MAX_STD_JUMBO_FRAME_SIZE 9234 if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { DPRINTK(PROBE, ERR, "MTU > 9216 not supported.\n"); @@ -3169,11 +3197,15 @@ e1000_update_stats(struct e1000_adapter *adapter) /* Rx Errors */ + /* RLEC on some newer hardware can be incorrect so build + * our own version based on RUC and ROC */ adapter->net_stats.rx_errors = adapter->stats.rxerrc + adapter->stats.crcerrs + adapter->stats.algnerrc + - adapter->stats.rlec + adapter->stats.cexterr; + adapter->stats.ruc + adapter->stats.roc + + adapter->stats.cexterr; adapter->net_stats.rx_dropped = 0; - adapter->net_stats.rx_length_errors = adapter->stats.rlec; + adapter->net_stats.rx_length_errors = adapter->stats.ruc + + adapter->stats.roc; adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; adapter->net_stats.rx_missed_errors = adapter->stats.mpc; @@ -3219,7 +3251,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) struct net_device *netdev = data; struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - uint32_t icr = E1000_READ_REG(hw, ICR); + uint32_t rctl, icr = E1000_READ_REG(hw, ICR); #ifndef CONFIG_E1000_NAPI int i; #else @@ -3241,6 +3273,17 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { hw->get_link_status = 1; + /* 80003ES2LAN workaround-- + * For packet buffer work-around on link down event; + * disable receives here in the ISR and + * reset adapter in watchdog + */ + if (netif_carrier_ok(netdev) && + (adapter->hw.mac_type == e1000_80003es2lan)) { + /* disable receives */ + rctl = E1000_READ_REG(hw, RCTL); + E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); + } mod_timer(&adapter->watchdog_timer, jiffies); } -- cgit v1.2.3-59-g8ed1b From dc7c6add3493cdc71475a006b7afc3732e55abd8 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:21:40 -0800 Subject: e1000: Add copybreak when using packet split Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_main.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 431b03ee077e..d641fbc7a6e1 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3757,6 +3757,35 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, /* Good Receive */ skb_put(skb, length); + { + /* this looks ugly, but it seems compiler issues make it + more efficient than reusing j */ + int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); + + /* page alloc/put takes too long and effects small packet + * throughput, so unsplit small packets and save the alloc/put*/ + if (l1 && ((length + l1) < E1000_CB_LENGTH)) { + u8 *vaddr; + /* there is no documentation about how to call + * kmap_atomic, so we can't hold the mapping + * very long */ + pci_dma_sync_single_for_cpu(pdev, + ps_page_dma->ps_page_dma[0], + PAGE_SIZE, + PCI_DMA_FROMDEVICE); + vaddr = kmap_atomic(ps_page->ps_page[0], + KM_SKB_DATA_SOFTIRQ); + memcpy(skb->tail, vaddr, l1); + kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); + pci_dma_sync_single_for_device(pdev, + ps_page_dma->ps_page_dma[0], + PAGE_SIZE, PCI_DMA_FROMDEVICE); + skb_put(skb, l1); + length += l1; + goto copydone; + } /* if */ + } + for (j = 0; j < adapter->rx_ps_pages; j++) { if (!(length = le16_to_cpu(rx_desc->wb.upper.length[j]))) break; @@ -3771,6 +3800,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, skb->data_len += length; } +copydone: e1000_rx_checksum(adapter, staterr, rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); skb->protocol = eth_type_trans(skb, netdev); -- cgit v1.2.3-59-g8ed1b From 30320be88fb9cae888eacf1f1eaae95a03720128 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:21:57 -0800 Subject: e1000: Added a performance enhancement - prefetch - this implementation of prefetch was tested on new and old hardware Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000_main.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index d641fbc7a6e1..b572a1218c81 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3569,10 +3569,15 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, skb = buffer_info->skb; buffer_info->skb = NULL; + prefetch(skb->data - NET_IP_ALIGN); + if (++i == rx_ring->count) i = 0; next_rxd = E1000_RX_DESC(*rx_ring, i); + prefetch(next_rxd); + next_buffer = &rx_ring->buffer_info[i]; next_skb = next_buffer->skb; + prefetch(next_skb->data - NET_IP_ALIGN); cleaned = TRUE; cleaned_count++; @@ -3668,6 +3673,7 @@ next_desc: cleaned_count = 0; } + /* use prefetched values */ rx_desc = next_rxd; buffer_info = next_buffer; } @@ -3710,9 +3716,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC_PS(*rx_ring, i); staterr = le32_to_cpu(rx_desc->wb.middle.status_error); - buffer_info = &rx_ring->buffer_info[i]; while (staterr & E1000_RXD_STAT_DD) { + buffer_info = &rx_ring->buffer_info[i]; ps_page = &rx_ring->ps_page[i]; ps_page_dma = &rx_ring->ps_page_dma[i]; #ifdef CONFIG_E1000_NAPI @@ -3722,10 +3728,16 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, #endif skb = buffer_info->skb; + /* in the packet split case this is header only */ + prefetch(skb->data - NET_IP_ALIGN); + if (++i == rx_ring->count) i = 0; next_rxd = E1000_RX_DESC_PS(*rx_ring, i); + prefetch(next_rxd); + next_buffer = &rx_ring->buffer_info[i]; next_skb = next_buffer->skb; + prefetch(next_skb->data - NET_IP_ALIGN); cleaned = TRUE; cleaned_count++; @@ -3787,9 +3799,8 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, } for (j = 0; j < adapter->rx_ps_pages; j++) { - if (!(length = le16_to_cpu(rx_desc->wb.upper.length[j]))) + if (!(length= le16_to_cpu(rx_desc->wb.upper.length[j]))) break; - pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j], PAGE_SIZE, PCI_DMA_FROMDEVICE); ps_page_dma->ps_page_dma[j] = 0; @@ -3837,6 +3848,7 @@ next_desc: cleaned_count = 0; } + /* use prefetched values */ rx_desc = next_rxd; buffer_info = next_buffer; -- cgit v1.2.3-59-g8ed1b From 0f15a8fae8b8558f5a9b0fec770846c487c779f6 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 2 Mar 2006 18:46:29 -0800 Subject: e1000: Added driver comments and whitespace changes. Modified long lines of code to ensure they would not wrap beyond 80 characters. Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: John Ronciak --- drivers/net/e1000/e1000.h | 10 ++-- drivers/net/e1000/e1000_hw.c | 5 +- drivers/net/e1000/e1000_hw.h | 26 +++++------ drivers/net/e1000/e1000_main.c | 101 ++++++++++++++++------------------------- 4 files changed, 60 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index d4266f18bbd9..214468c35b4b 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -281,15 +281,15 @@ struct e1000_adapter { /* RX */ #ifdef CONFIG_E1000_NAPI boolean_t (*clean_rx) (struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do); + struct e1000_rx_ring *rx_ring, + int *work_done, int work_to_do); #else boolean_t (*clean_rx) (struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring); + struct e1000_rx_ring *rx_ring); #endif void (*alloc_rx_buf) (struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count); + struct e1000_rx_ring *rx_ring, + int cleaned_count); struct e1000_rx_ring *rx_ring; /* One per active queue */ #ifdef CONFIG_E1000_NAPI struct net_device *polling_netdev; /* One per active queue */ diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 63e237084a51..523c2c9fc0ac 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -3498,7 +3498,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw) * bit. Then, take it out of reset. * For pre-e1000_82571 hardware, we delay for 10ms between the assert * and deassert. For e1000_82571 hardware and later, we instead delay - * for 10ms after the deassertion. + * for 50us between and 10ms after the deassertion. */ ctrl = E1000_READ_REG(hw, CTRL); E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST); @@ -3920,7 +3920,8 @@ e1000_validate_mdi_setting(struct e1000_hw *hw) /****************************************************************************** * Sets up eeprom variables in the hw struct. Must be called after mac_type - * is configured. + * is configured. Additionally, if this is ICH8, the flash controller GbE + * registers must be mapped, or this will crash. * * hw - Struct containing variables accessed by shared code *****************************************************************************/ diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 947a156bd702..150e45e30f87 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -2067,19 +2067,19 @@ struct e1000_host_command_info { /* PCI-Ex registers */ /* PCI-Ex Control Register */ -#define E1000_GCR_RXD_NO_SNOOP 0x00000001 -#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 -#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 -#define E1000_GCR_TXD_NO_SNOOP 0x00000008 -#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 -#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 - -#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ - E1000_GCR_RXDSCW_NO_SNOOP | \ - E1000_GCR_RXDSCR_NO_SNOOP | \ - E1000_GCR TXD_NO_SNOOP | \ - E1000_GCR_TXDSCW_NO_SNOOP | \ - E1000_GCR_TXDSCR_NO_SNOOP) +#define E1000_GCR_RXD_NO_SNOOP 0x00000001 +#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 +#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 +#define E1000_GCR_TXD_NO_SNOOP 0x00000008 +#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 +#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 + +#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ + E1000_GCR_RXDSCW_NO_SNOOP | \ + E1000_GCR_RXDSCR_NO_SNOOP | \ + E1000_GCR_TXD_NO_SNOOP | \ + E1000_GCR_TXDSCW_NO_SNOOP | \ + E1000_GCR_TXDSCR_NO_SNOOP) #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 /* Function Active and Power State to MNG */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index b572a1218c81..9adaf5fa9d48 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -29,6 +29,23 @@ #include "e1000.h" /* Change Log + * 7.0.33 3-Feb-2006 + * o Added another fix for the pass false carrier bit + * 7.0.32 24-Jan-2006 + * o Need to rebuild with noew version number for the pass false carrier + * fix in e1000_hw.c + * 7.0.30 18-Jan-2006 + * o fixup for tso workaround to disable it for pci-x + * o fix mem leak on 82542 + * o fixes for 10 Mb/s connections and incorrect stats + * 7.0.28 01/06/2006 + * o hardware workaround to only set "speed mode" bit for 1G link. + * 7.0.26 12/23/2005 + * o wake on lan support modified for device ID 10B5 + * o fix dhcp + vlan issue not making it to the iAMT firmware + * 7.0.24 12/9/2005 + * o New hardware support for the Gigabit NIC embedded in the south bridge + * o Fixes to the recycling logic (skb->tail) from IBM LTC * 6.3.9 12/16/2005 * o incorporate fix for recycled skbs from IBM LTC * 6.3.7 11/18/2005 @@ -46,54 +63,8 @@ * rx_buffer_len * 6.3.1 9/19/05 * o Use adapter->tx_timeout_factor in Tx Hung Detect logic - (e1000_clean_tx_irq) + * (e1000_clean_tx_irq) * o Support for 8086:10B5 device (Quad Port) - * 6.2.14 9/15/05 - * o In AMT enabled configurations, set/reset DRV_LOAD bit on interface - * open/close - * 6.2.13 9/14/05 - * o Invoke e1000_check_mng_mode only for 8257x controllers since it - * accesses the FWSM that is not supported in other controllers - * 6.2.12 9/9/05 - * o Add support for device id E1000_DEV_ID_82546GB_QUAD_COPPER - * o set RCTL:SECRC only for controllers newer than 82543. - * o When the n/w interface comes down reset DRV_LOAD bit to notify f/w. - * This code was moved from e1000_remove to e1000_close - * 6.2.10 9/6/05 - * o Fix error in updating RDT in el1000_alloc_rx_buffers[_ps] -- one off. - * o Enable fc by default on 82573 controllers (do not read eeprom) - * o Fix rx_errors statistic not to include missed_packet_count - * o Fix rx_dropped statistic not to include missed_packet_count - (Padraig Brady) - * 6.2.9 8/30/05 - * o Remove call to update statistics from the controller ib e1000_get_stats - * 6.2.8 8/30/05 - * o Improved algorithm for rx buffer allocation/rdt update - * o Flow control watermarks relative to rx PBA size - * o Simplified 'Tx Hung' detect logic - * 6.2.7 8/17/05 - * o Report rx buffer allocation failures and tx timeout counts in stats - * 6.2.6 8/16/05 - * o Implement workaround for controller erratum -- linear non-tso packet - * following a TSO gets written back prematurely - * 6.2.5 8/15/05 - * o Set netdev->tx_queue_len based on link speed/duplex settings. - * o Fix net_stats.rx_fifo_errors - * o Do not power off PHY if SoL/IDER session is active - * 6.2.4 8/10/05 - * o Fix loopback test setup/cleanup for 82571/3 controllers - * o Fix parsing of outgoing packets (e1000_transfer_dhcp_info) to treat - * all packets as raw - * o Prevent operations that will cause the PHY to be reset if SoL/IDER - * sessions are active and log a message - * 6.2.2 7/21/05 - * o used fixed size descriptors for all MTU sizes, reduces memory load - * 6.1.2 4/13/05 - * o Fixed ethtool diagnostics - * o Enabled flow control to take default eeprom settings - * o Added stats_lock around e1000_read_phy_reg commands to avoid concurrent - * calls, one from mii_ioctl and other from within update_stats while - * processing MIIREG ioctl. */ char e1000_driver_name[] = "e1000"; @@ -178,13 +149,13 @@ int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); void e1000_free_all_tx_resources(struct e1000_adapter *adapter); void e1000_free_all_rx_resources(struct e1000_adapter *adapter); static int e1000_setup_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *txdr); + struct e1000_tx_ring *txdr); static int e1000_setup_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rxdr); + struct e1000_rx_ring *rxdr); static void e1000_free_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring); + struct e1000_tx_ring *tx_ring); static void e1000_free_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring); + struct e1000_rx_ring *rx_ring); void e1000_update_stats(struct e1000_adapter *adapter); /* Local Function Prototypes */ @@ -1727,6 +1698,7 @@ e1000_configure_rx(struct e1000_adapter *adapter) uint32_t rdlen, rctl, rxcsum, ctrl_ext; if (adapter->rx_ps_pages) { + /* this is a 32 byte descriptor */ rdlen = adapter->rx_ring[0].count * sizeof(union e1000_rx_desc_packet_split); adapter->clean_rx = e1000_clean_rx_irq_ps; @@ -2576,9 +2548,9 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, /* Workaround for Controller erratum -- * descriptor for non-tso packet in a linear SKB that follows a * tso gets written back prematurely before the data is fully - * DMAd to the controller */ + * DMA'd to the controller */ if (!skb->data_len && tx_ring->last_tx_tso && - !skb_shinfo(skb)->tso_size) { + !skb_shinfo(skb)->tso_size) { tx_ring->last_tx_tso = 0; size -= 4; } @@ -2866,7 +2838,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)->tso_size) count++; #endif @@ -2889,7 +2861,9 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (adapter->pcix_82544) count += nr_frags; - if (adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) ) + + if (adapter->hw.tx_pkt_filtering && + (adapter->hw.mac_type == e1000_82573)) e1000_transfer_dhcp_info(adapter, skb); local_irq_save(flags); @@ -3892,7 +3866,6 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter, goto map_skb; } - if (unlikely(!skb)) { /* Better luck next round */ adapter->alloc_rx_buff_failed++; @@ -4445,8 +4418,8 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) } #ifdef CONFIG_PM -/* these functions save and restore 16 or 64 dwords (64-256 bytes) of config - * space versus the 64 bytes that pci_[save|restore]_state handle +/* Save/restore 16 or 64 dwords of PCI config space depending on which + * bus we're on (PCI(X) vs. PCI-E) */ #define PCIE_CONFIG_SPACE_LEN 256 #define PCI_CONFIG_SPACE_LEN 64 @@ -4456,6 +4429,7 @@ e1000_pci_save_state(struct e1000_adapter *adapter) struct pci_dev *dev = adapter->pdev; int size; int i; + if (adapter->hw.mac_type >= e1000_82571) size = PCIE_CONFIG_SPACE_LEN; else @@ -4479,8 +4453,10 @@ e1000_pci_restore_state(struct e1000_adapter *adapter) struct pci_dev *dev = adapter->pdev; int size; int i; + if (adapter->config_space == NULL) return; + if (adapter->hw.mac_type >= e1000_82571) size = PCIE_CONFIG_SPACE_LEN; else @@ -4508,8 +4484,8 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) e1000_down(adapter); #ifdef CONFIG_PM - /* implement our own version of pci_save_state(pdev) because pci - * express adapters have larger 256 byte config spaces */ + /* Implement our own version of pci_save_state(pdev) because pci- + * express adapters have 256-byte config spaces. */ retval = e1000_pci_save_state(adapter); if (retval) return retval; @@ -4566,7 +4542,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) retval = pci_enable_wake(pdev, PCI_D3hot, 0); if (retval) DPRINTK(PROBE, ERR, "Error enabling D3 wake\n"); - retval = pci_enable_wake(pdev, PCI_D3cold, 0); /* 4 == D3 cold */ + retval = pci_enable_wake(pdev, PCI_D3cold, 0); if (retval) DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n"); } @@ -4582,7 +4558,8 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) DPRINTK(PROBE, ERR, "Error enabling D3 wake\n"); retval = pci_enable_wake(pdev, PCI_D3cold, 1); if (retval) - DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n"); + DPRINTK(PROBE, ERR, + "Error enabling D3 cold wake\n"); } } -- cgit v1.2.3-59-g8ed1b From 7e6dff62dad539cbd608bb3b8b833193d13f00ac Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 2 Mar 2006 14:12:56 -0600 Subject: [SCSI] add 6.0 Gbit phy definitions to the sas transport class I don't think these exist in silicon yet, but the aic94xx driver has a register setting for them. Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 1 + include/scsi/scsi_transport_sas.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index eab5c7c6f3c7..fed39abeff86 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -151,6 +151,7 @@ static struct { { SAS_SATA_SPINUP_HOLD, "Spin-up hold" }, { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, + { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, }; sas_bitfield_name_search(linkspeed, sas_linkspeed_names) diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index ccef5d2cf478..95e2132d485e 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -30,6 +30,7 @@ enum sas_linkrate { SAS_SATA_PORT_SELECTOR, SAS_LINK_RATE_1_5_GBPS, SAS_LINK_RATE_3_0_GBPS, + SAS_LINK_RATE_6_0_GBPS, SAS_LINK_VIRTUAL, }; -- cgit v1.2.3-59-g8ed1b From 98acfc7e8e2606fadae6d2bf99fa040be917ce8c Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 1 Mar 2006 12:04:46 -0700 Subject: [SCSI] Add Brownie to blacklist This device spews total rubbish to a REPORT LUNS command, so avoid sending it one. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/scsi_devinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index f01ec0a7c506..84c3937ae8fb 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -126,6 +126,7 @@ static struct { {"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN}, {"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN}, {"BELKIN", "USB 2 HS-CF", "1.95", BLIST_FORCELUN | BLIST_INQUIRY_36}, + {"BROWNIE", "1600U3P", NULL, BLIST_NOREPORTLUN}, {"CANON", "IPUBJD", NULL, BLIST_SPARSELUN}, {"CBOX3", "USB Storage-SMC", "300A", BLIST_FORCELUN | BLIST_INQUIRY_36}, {"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */ -- cgit v1.2.3-59-g8ed1b From 35dc2585fa32a2b300307ffa9f17122b13ccef97 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Thu, 2 Mar 2006 21:28:54 +0100 Subject: [SCSI] zfcp: correctly set this_id for hosts It fixes a bug in zfcp which provokes a race in scsi_scan.c. Finally this can lead to an Oops like: kernel BUG at fs/sysfs/symlink.c:87! Correctly set this_id for the host. Otherwise we provoke a race between scsi_target_reap_work and concurrent scsi_add_device. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 9f6b4d7a46f3..a2de3c9afe49 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -68,7 +68,7 @@ struct zfcp_data zfcp_data = { eh_host_reset_handler: zfcp_scsi_eh_host_reset_handler, /* FIXME(openfcp): Tune */ can_queue: 4096, - this_id: 0, + this_id: -1, /* * FIXME: * one less? can zfcp_create_sbale cope with it? -- cgit v1.2.3-59-g8ed1b From 39a112403fd4c6cd2215b5a59ff079e42eb824a4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 14 Feb 2006 18:46:22 +0100 Subject: [SCSI] qla2xxx: use kthread_ API Use the kthread_ API instead of opencoding lots of hairy code for kernel thread creation and teardown. Also switch from semaphore-based thread wakeup to wake_up_process. Signed-off-by: Christoph Hellwig Acked-By: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 6 +-- drivers/scsi/qla2xxx/qla_gbl.h | 2 + drivers/scsi/qla2xxx/qla_isr.c | 7 +--- drivers/scsi/qla2xxx/qla_mbx.c | 4 +- drivers/scsi/qla2xxx/qla_os.c | 89 ++++++++++++++---------------------------- drivers/scsi/qla2xxx/qla_sup.c | 4 +- 6 files changed, 38 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index b31a03bbd14f..2e16f3285d5f 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2414,11 +2414,7 @@ typedef struct scsi_qla_host { struct sns_cmd_pkt *sns_cmd; dma_addr_t sns_cmd_dma; - pid_t dpc_pid; - int dpc_should_die; - struct completion dpc_inited; - struct completion dpc_exited; - struct semaphore *dpc_wait; + struct task_struct *dpc_thread; uint8_t dpc_active; /* DPC routine is active */ /* Timeout timers. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index ffdc2680f049..e897eadf0362 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -81,6 +81,8 @@ extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *); extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *); +extern void qla2xxx_wake_dpc(scsi_qla_host_t *); + /* * Global Function Prototypes in qla_iocb.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 42aa7a7c1a73..c15458c2bf32 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -838,9 +838,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) qla_printk(KERN_WARNING, ha, "Status Entry invalid handle.\n"); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - if (ha->dpc_wait && !ha->dpc_active) - up(ha->dpc_wait); - + qla2xxx_wake_dpc(ha); return; } cp = sp->cmd; @@ -1271,8 +1269,7 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) "Error entry - invalid handle\n"); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - if (ha->dpc_wait && !ha->dpc_active) - up(ha->dpc_wait); + qla2xxx_wake_dpc(ha); } } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 363dfdd042b0..584cc2f6dd35 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -284,9 +284,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) "Mailbox command timeout occured. Scheduling ISP " "abort.\n"); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - if (ha->dpc_wait && !ha->dpc_active) - up(ha->dpc_wait); - + qla2xxx_wake_dpc(ha); } else if (!abort_active) { /* call abort directly since we are in the DPC thread */ DEBUG(printk("%s(%ld): timeout calling abort_isp\n", diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 9f91f1a20542..43ca0d8ca384 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -8,8 +8,8 @@ #include #include -#include #include +#include #include #include @@ -1307,8 +1307,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->brd_info = brd_info; sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no); - ha->dpc_pid = -1; - /* Configure PCI I/O space */ ret = qla2x00_iospace_config(ha); if (ret) @@ -1449,9 +1447,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) */ spin_lock_init(&ha->mbx_reg_lock); - init_completion(&ha->dpc_inited); - init_completion(&ha->dpc_exited); - qla2x00_config_dma_addressing(ha); if (qla2x00_mem_alloc(ha)) { qla_printk(KERN_WARNING, ha, @@ -1478,16 +1473,14 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) /* * Startup the kernel thread for this host adapter */ - ha->dpc_should_die = 0; - ha->dpc_pid = kernel_thread(qla2x00_do_dpc, ha, 0); - if (ha->dpc_pid < 0) { + ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha, + "%s_dpc", ha->host_str); + if (IS_ERR(ha->dpc_thread)) { qla_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n"); - - ret = -ENODEV; + ret = PTR_ERR(ha->dpc_thread); goto probe_failed; } - wait_for_completion(&ha->dpc_inited); host->this_id = 255; host->cmd_per_lun = 3; @@ -1621,8 +1614,6 @@ EXPORT_SYMBOL_GPL(qla2x00_remove_one); static void qla2x00_free_device(scsi_qla_host_t *ha) { - int ret; - /* Abort any outstanding IO descriptors. */ if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) qla2x00_cancel_io_descriptors(ha); @@ -1632,18 +1623,15 @@ qla2x00_free_device(scsi_qla_host_t *ha) qla2x00_stop_timer(ha); /* Kill the kernel thread for this host */ - if (ha->dpc_pid >= 0) { - ha->dpc_should_die = 1; - wmb(); - ret = kill_proc(ha->dpc_pid, SIGHUP, 1); - if (ret) { - qla_printk(KERN_ERR, ha, - "Unable to signal DPC thread -- (%d)\n", ret); + if (ha->dpc_thread) { + struct task_struct *t = ha->dpc_thread; - /* TODO: SOMETHING MORE??? */ - } else { - wait_for_completion(&ha->dpc_exited); - } + /* + * qla2xxx_wake_dpc checks for ->dpc_thread + * so we need to zero it out. + */ + ha->dpc_thread = NULL; + kthread_stop(t); } /* Stop currently executing firmware. */ @@ -1775,8 +1763,8 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) atomic_set(&fcport->state, FCS_DEVICE_LOST); } - if (defer && ha->dpc_wait && !ha->dpc_active) - up(ha->dpc_wait); + if (defer) + qla2xxx_wake_dpc(ha); } /* @@ -1993,7 +1981,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) { struct list_head *fcpl, *fcptemp; fc_port_t *fcport; - unsigned int wtime;/* max wait time if mbx cmd is busy. */ if (ha == NULL) { /* error */ @@ -2001,11 +1988,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) return; } - /* Make sure all other threads are stopped. */ - wtime = 60 * 1000; - while (ha->dpc_wait && wtime) - wtime = msleep_interruptible(wtime); - /* free ioctl memory */ qla2x00_free_ioctl_mem(ha); @@ -2156,7 +2138,6 @@ qla2x00_free_sp_pool( scsi_qla_host_t *ha) static int qla2x00_do_dpc(void *data) { - DECLARE_MUTEX_LOCKED(sem); scsi_qla_host_t *ha; fc_port_t *fcport; uint8_t status; @@ -2164,32 +2145,19 @@ qla2x00_do_dpc(void *data) ha = (scsi_qla_host_t *)data; - lock_kernel(); - - daemonize("%s_dpc", ha->host_str); - allow_signal(SIGHUP); - - ha->dpc_wait = &sem; - set_user_nice(current, -20); - unlock_kernel(); - - complete(&ha->dpc_inited); - - while (1) { + while (!kthread_should_stop()) { DEBUG3(printk("qla2x00: DPC handler sleeping\n")); - if (down_interruptible(&sem)) - break; - - if (ha->dpc_should_die) - break; + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + __set_current_state(TASK_RUNNING); DEBUG3(printk("qla2x00: DPC handler waking up\n")); /* Initialization not yet finished. Don't do anything yet. */ - if (!ha->flags.init_done || ha->dpc_active) + if (!ha->flags.init_done) continue; DEBUG3(printk("scsi(%ld): DPC handler\n", ha->host_no)); @@ -2356,10 +2324,16 @@ qla2x00_do_dpc(void *data) /* * Make sure that nobody tries to wake us up again. */ - ha->dpc_wait = NULL; ha->dpc_active = 0; - complete_and_exit(&ha->dpc_exited, 0); + return 0; +} + +void +qla2xxx_wake_dpc(scsi_qla_host_t *ha) +{ + if (ha->dpc_thread) + wake_up_process(ha->dpc_thread); } /* @@ -2540,11 +2514,8 @@ qla2x00_timer(scsi_qla_host_t *ha) test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) || - test_bit(RELOGIN_NEEDED, &ha->dpc_flags)) && - ha->dpc_wait && !ha->dpc_active) { - - up(ha->dpc_wait); - } + test_bit(RELOGIN_NEEDED, &ha->dpc_flags))) + qla2xxx_wake_dpc(ha); qla2x00_restart_timer(ha, WATCH_INTERVAL); } diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 3866a5760f15..8d68c463cd5b 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -1354,7 +1354,7 @@ qla2x00_resume_hba(struct scsi_qla_host *ha) /* Resume HBA. */ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - up(ha->dpc_wait); + qla2xxx_wake_dpc(ha); qla2x00_wait_for_hba_online(ha); scsi_unblock_requests(ha->host); } @@ -1652,7 +1652,7 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, /* Resume HBA -- RISC reset needed. */ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - up(ha->dpc_wait); + qla2xxx_wake_dpc(ha); qla2x00_wait_for_hba_online(ha); scsi_unblock_requests(ha->host); -- cgit v1.2.3-59-g8ed1b From dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 2 Mar 2006 16:01:31 -0600 Subject: [SCSI] make some sas class properties optional aic94xx doesn't have a use for the bay or enclosure identifiers. Also, I think it's not going to need a get_linkerrors(), so wire up all of these exported properties as conditional on the underlying function support. Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index fed39abeff86..434f3954aa87 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -273,7 +273,7 @@ show_sas_phy_##field(struct class_device *cdev, char *buf) \ if (!phy->local_attached) \ return -EINVAL; \ \ - error = i->f->get_linkerrors(phy); \ + error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0; \ if (error) \ return error; \ return snprintf(buf, 20, "%u\n", phy->field); \ @@ -814,6 +814,14 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, i->rphy_attrs[count] = &i->private_rphy_attrs[count]; \ count++ +#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func) \ + i->private_rphy_attrs[count] = class_device_attr_##field; \ + i->private_rphy_attrs[count].attr.mode = S_IRUGO; \ + i->private_rphy_attrs[count].store = NULL; \ + i->rphy_attrs[count] = &i->private_rphy_attrs[count]; \ + if (i->f->func) \ + count++ + #define SETUP_PORT_ATTRIBUTE(field) \ i->private_phy_attrs[count] = class_device_attr_##field; \ i->private_phy_attrs[count].attr.mode = S_IRUGO; \ @@ -821,6 +829,14 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, i->phy_attrs[count] = &i->private_phy_attrs[count]; \ count++ +#define SETUP_OPTIONAL_PORT_ATTRIBUTE(field, func) \ + i->private_phy_attrs[count] = class_device_attr_##field; \ + i->private_phy_attrs[count].attr.mode = S_IRUGO; \ + i->private_phy_attrs[count].store = NULL; \ + i->phy_attrs[count] = &i->private_phy_attrs[count]; \ + if (i->f->func) \ + count++ + #define SETUP_PORT_ATTRIBUTE_WRONLY(field) \ i->private_phy_attrs[count] = class_device_attr_##field; \ i->private_phy_attrs[count].attr.mode = S_IWUGO; \ @@ -828,6 +844,14 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, i->phy_attrs[count] = &i->private_phy_attrs[count]; \ count++ +#define SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(field, func) \ + i->private_phy_attrs[count] = class_device_attr_##field; \ + i->private_phy_attrs[count].attr.mode = S_IWUGO; \ + i->private_phy_attrs[count].show = NULL; \ + i->phy_attrs[count] = &i->private_phy_attrs[count]; \ + if (i->f->func) \ + count++ + /** * sas_attach_transport -- instantiate SAS transport template @@ -883,8 +907,8 @@ sas_attach_transport(struct sas_function_template *ft) SETUP_PORT_ATTRIBUTE(running_disparity_error_count); SETUP_PORT_ATTRIBUTE(loss_of_dword_sync_count); SETUP_PORT_ATTRIBUTE(phy_reset_problem_count); - SETUP_PORT_ATTRIBUTE_WRONLY(link_reset); - SETUP_PORT_ATTRIBUTE_WRONLY(hard_reset); + SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(link_reset, phy_reset); + SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(hard_reset, phy_reset); i->phy_attrs[count] = NULL; count = 0; @@ -893,8 +917,10 @@ sas_attach_transport(struct sas_function_template *ft) SETUP_RPORT_ATTRIBUTE(rphy_device_type); SETUP_RPORT_ATTRIBUTE(rphy_sas_address); SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); - SETUP_RPORT_ATTRIBUTE(rphy_enclosure_identifier); - SETUP_RPORT_ATTRIBUTE(rphy_bay_identifier); + SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier, + get_enclosure_identifier); + SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier, + get_bay_identifier); i->rphy_attrs[count] = NULL; return &i->t; -- cgit v1.2.3-59-g8ed1b From df8cf70683ba3109756e20c50e0fefe24736564f Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Fri, 3 Mar 2006 12:09:26 -0300 Subject: V4L/DVB (3395): Fixed Pinnacle 300i DVB-T support - fixed tda9886 port 2 setting - turned remote control receiver off via saa7134 GPIO to avoid i2c hangs - modified tda9886 client calls to direct i2c access to allow proper return to analog mode - allow mode change to V4L2_TUNER_DIGITAL_TV in tuner VIDIOC_S_FREQUENCY client call Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 9 +++++++-- drivers/media/video/saa7134/saa7134-dvb.c | 12 ++++++++---- drivers/media/video/tuner-core.c | 5 +++-- 3 files changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index ccf7231cde3e..722ebff0f889 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -1003,7 +1003,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_ACTIVE, + .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE, .inputs = {{ .name = name_tv, .vmux = 3, @@ -1692,7 +1692,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_ACTIVE, + .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, @@ -3375,6 +3375,11 @@ int saa7134_board_init1(struct saa7134_dev *dev) /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000); + case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL: + /* this turns the remote control chip off to work around a bug in it */ + saa_writeb(SAA7134_GPIO_GPMODE1, 0x80); + saa_writeb(SAA7134_GPIO_GPSTATUS1, 0x80); + break; case SAA7134_BOARD_MONSTERTV_MOBILE: /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 757796259cf9..5969481ed4fb 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -110,6 +110,7 @@ static int mt352_pinnacle_init(struct dvb_frontend* fe) mt352_write(fe, fsm_ctl_cfg, sizeof(fsm_ctl_cfg)); mt352_write(fe, scan_ctl_cfg, sizeof(scan_ctl_cfg)); mt352_write(fe, irq_cfg, sizeof(irq_cfg)); + return 0; } @@ -135,8 +136,10 @@ static int mt352_pinnacle_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) { - static int on = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE; - static int off = TDA9887_PRESENT | TDA9887_PORT2_ACTIVE; + u8 off[] = { 0x00, 0xf1}; + u8 on[] = { 0x00, 0x71}; + struct i2c_msg msg = {.addr=0x43, .flags=0, .buf=off, .len = sizeof(off)}; + struct saa7134_dev *dev = fe->dvb->priv; struct v4l2_frequency f; @@ -144,9 +147,10 @@ static int mt352_pinnacle_pll_set(struct dvb_frontend* fe, f.tuner = 0; f.type = V4L2_TUNER_DIGITAL_TV; f.frequency = params->frequency / 1000 * 16 / 1000; - saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&on); + i2c_transfer(&dev->i2c_adap, &msg, 1); saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f); - saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&off); + msg.buf = on; + i2c_transfer(&dev->i2c_adap, &msg, 1); pinnacle_antenna_pwr(dev, antenna_pwr); diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 3964244d6ff5..32e1849441fb 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -713,8 +713,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) struct v4l2_frequency *f = arg; switch_v4l2(); - if (V4L2_TUNER_RADIO == f->type && - V4L2_TUNER_RADIO != t->mode) { + if ((V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode) + || (V4L2_TUNER_DIGITAL_TV == f->type + && V4L2_TUNER_DIGITAL_TV != t->mode)) { if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") == EINVAL) return 0; -- cgit v1.2.3-59-g8ed1b From 420f32fe4e3eed466a6563e15a89f4688134cc98 Mon Sep 17 00:00:00 2001 From: Nico Sabbi Date: Fri, 3 Mar 2006 12:11:28 -0300 Subject: V4L/DVB (3396): Add DVB-T support for the LifeView DVB Trio PCI card This patch adds DVB-T support, no DVB-S yet Signed-off-by: Nico Sabbi Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 2 ++ drivers/media/video/saa7134/saa7134-dvb.c | 37 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 722ebff0f889..288d1f8841be 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2624,6 +2624,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .gpiomask = 0x00200000, + .mpeg = SAA7134_MPEG_DVB, /* FIXME: DVB not implemented yet */ .inputs = {{ .name = name_tv, /* Analog broadcast/cable TV */ .vmux = 1, @@ -3547,6 +3548,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) i2c_transfer(&dev->i2c_adap, &msg, 1); } break; + case SAA7134_BOARD_FLYDVB_TRIO: case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: /* make the tda10046 find its eeprom */ { diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 5969481ed4fb..ad34eb5b17cb 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -852,6 +852,39 @@ static struct tda1004x_config philips_tiger_config = { /* ------------------------------------------------------------------ */ +static int lifeview_trio_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + int ret; + + ret = philips_tda827xa_pll_set(0x60, fe, params); + return ret; +} + +static int lifeview_trio_dvb_mode(struct dvb_frontend *fe) +{ + return 0; +} + +static void lifeview_trio_analog_mode(struct dvb_frontend *fe) +{ + philips_tda827xa_pll_sleep(0x60, fe); +} + +static struct tda1004x_config lifeview_trio_config = { + .demod_address = 0x09, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_16M, + .agc_config = TDA10046_AGC_TDA827X_GPL, + .if_freq = TDA10046_FREQ_045, + .pll_init = lifeview_trio_dvb_mode, + .pll_set = lifeview_trio_pll_set, + .pll_sleep = lifeview_trio_analog_mode, + .request_firmware = NULL, +}; + +/* ------------------------------------------------------------------ */ + static int ads_duo_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { int ret; @@ -1019,6 +1052,10 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, &dev->i2c_adap); break; + case SAA7134_BOARD_FLYDVB_TRIO: + dev->dvb.frontend = tda10046_attach(&lifeview_trio_config, + &dev->i2c_adap); + break; case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config, &dev->i2c_adap); -- cgit v1.2.3-59-g8ed1b From ba52429cb4e9ccd2e6417205a3f7d1f78356e236 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 27 Feb 2006 14:38:17 -0300 Subject: V4L/DVB (3398): ELSA EX-VISION 700TV: fix incorrect PCI subsystem ID - Corrected autodetection for saa7130 card: subsystem: 1048:226c, board: ELSA EX-VISION 700TV Signed-off-by: TAMUKI Shoichi Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index e1484dfef103..8435a21856aa 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -87,5 +87,5 @@ 86 -> LifeView FlyDVB-T [5168:0301] 87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421] 88 -> Tevion DVB-T 220RF [17de:7201] - 89 -> ELSA EX-VISION 700TV [1131:7130] + 89 -> ELSA EX-VISION 700TV [1048:226c] 90 -> Kworld ATSC110 [17de:7350] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 288d1f8841be..384f6f221e18 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2887,8 +2887,8 @@ struct pci_device_id saa7134_pci_tbl[] = { },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1131, - .subdevice = 0x7130, + .subvendor = 0x1048, + .subdevice = 0x226c, .driver_data = SAA7134_BOARD_ELSA_700TV, },{ .vendor = PCI_VENDOR_ID_PHILIPS, -- cgit v1.2.3-59-g8ed1b From 9a7871ba111862b1515719994df66eeda9debbd1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 27 Feb 2006 15:22:49 -0300 Subject: V4L/DVB (3399): ELSA EX-VISION 500TV: fix incorrect PCI subsystem ID - ELSA EX-VISION 500TV was incorrectly programmed to have the same subsystem ID as ELSA EX-VISION 300TV, (1048:226b) - This changeset replaces the incorrect subsystem ID (1048:226b) with the correct one (1048:226a) for the ELSA EX-VISION 500TV. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 8435a21856aa..17ea5a031b30 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -13,7 +13,7 @@ 12 -> Medion 7134 [16be:0003] 13 -> Typhoon TV+Radio 90031 14 -> ELSA EX-VISION 300TV [1048:226b] - 15 -> ELSA EX-VISION 500TV [1048:226b] + 15 -> ELSA EX-VISION 500TV [1048:226a] 16 -> ASUS TV-FM 7134 [1043:4842,1043:4830,1043:4840] 17 -> AOPEN VA1000 POWER [1131:7133] 18 -> BMK MPEX No Tuner diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 384f6f221e18..f156650960c2 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2882,7 +2882,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x1048, - .subdevice = 0x226b, + .subdevice = 0x226a, .driver_data = SAA7134_BOARD_ELSA_500TV, },{ .vendor = PCI_VENDOR_ID_PHILIPS, -- cgit v1.2.3-59-g8ed1b From d15549acfedd70b2bd97a5876ecd59527fa97671 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Fri, 3 Mar 2006 12:13:42 -0300 Subject: V4L/DVB (3197a): IR keymaps are exported by the ir-common module now Moved keymaps to the ir-common module, and export them from there, instead of #including them in each module Included missing files from V4L/DVB(3197). Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-functions.c | 272 ++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 drivers/media/common/ir-functions.c (limited to 'drivers') diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c new file mode 100644 index 000000000000..397cff8b345b --- /dev/null +++ b/drivers/media/common/ir-functions.c @@ -0,0 +1,272 @@ +/* + * + * some common structs and functions to handle infrared remotes via + * input layer ... + * + * (c) 2003 Gerd Knorr [SuSE Labs] + * + * 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 + +/* -------------------------------------------------------------------------- */ + +MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); +MODULE_LICENSE("GPL"); + +static int repeat = 1; +module_param(repeat, int, 0444); +MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); + +static int debug = 0; /* debug level (0,1,2) */ +module_param(debug, int, 0644); + +#define dprintk(level, fmt, arg...) if (debug >= level) \ + printk(KERN_DEBUG fmt , ## arg) + +/* -------------------------------------------------------------------------- */ + +static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) +{ + if (KEY_RESERVED == ir->keycode) { + printk(KERN_INFO "%s: unknown key: key=0x%02x raw=0x%02x down=%d\n", + dev->name,ir->ir_key,ir->ir_raw,ir->keypressed); + return; + } + dprintk(1,"%s: key event code=%d down=%d\n", + dev->name,ir->keycode,ir->keypressed); + input_report_key(dev,ir->keycode,ir->keypressed); + input_sync(dev); +} + +/* -------------------------------------------------------------------------- */ + +void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, + int ir_type, IR_KEYTAB_TYPE *ir_codes) +{ + int i; + + ir->ir_type = ir_type; + if (ir_codes) + memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes)); + + + dev->keycode = ir->ir_codes; + dev->keycodesize = sizeof(IR_KEYTAB_TYPE); + dev->keycodemax = IR_KEYTAB_SIZE; + for (i = 0; i < IR_KEYTAB_SIZE; i++) + set_bit(ir->ir_codes[i], dev->keybit); + clear_bit(0, dev->keybit); + + set_bit(EV_KEY, dev->evbit); + if (repeat) + set_bit(EV_REP, dev->evbit); +} + +void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir) +{ + if (ir->keypressed) { + ir->keypressed = 0; + ir_input_key_event(dev,ir); + } +} + +void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, + u32 ir_key, u32 ir_raw) +{ + u32 keycode = IR_KEYCODE(ir->ir_codes, ir_key); + + if (ir->keypressed && ir->keycode != keycode) { + ir->keypressed = 0; + ir_input_key_event(dev,ir); + } + if (!ir->keypressed) { + ir->ir_key = ir_key; + ir->ir_raw = ir_raw; + ir->keycode = keycode; + ir->keypressed = 1; + ir_input_key_event(dev,ir); + } +} + +/* -------------------------------------------------------------------------- */ + +u32 ir_extract_bits(u32 data, u32 mask) +{ + int mbit, vbit; + u32 value; + + value = 0; + vbit = 0; + for (mbit = 0; mbit < 32; mbit++) { + if (!(mask & ((u32)1 << mbit))) + continue; + if (data & ((u32)1 << mbit)) + value |= (1 << vbit); + vbit++; + } + return value; +} + +static int inline getbit(u32 *samples, int bit) +{ + return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0; +} + +/* sump raw samples for visual debugging ;) */ +int ir_dump_samples(u32 *samples, int count) +{ + int i, bit, start; + + printk(KERN_DEBUG "ir samples: "); + start = 0; + for (i = 0; i < count * 32; i++) { + bit = getbit(samples,i); + if (bit) + start = 1; + if (0 == start) + continue; + printk("%s", bit ? "#" : "_"); + } + printk("\n"); + return 0; +} + +/* decode raw samples, pulse distance coding used by NEC remotes */ +int ir_decode_pulsedistance(u32 *samples, int count, int low, int high) +{ + int i,last,bit,len; + u32 curBit; + u32 value; + + /* find start burst */ + for (i = len = 0; i < count * 32; i++) { + bit = getbit(samples,i); + if (bit) { + len++; + } else { + if (len >= 29) + break; + len = 0; + } + } + + /* start burst to short */ + if (len < 29) + return 0xffffffff; + + /* find start silence */ + for (len = 0; i < count * 32; i++) { + bit = getbit(samples,i); + if (bit) { + break; + } else { + len++; + } + } + + /* silence to short */ + if (len < 7) + return 0xffffffff; + + /* go decoding */ + len = 0; + last = 1; + value = 0; curBit = 1; + for (; i < count * 32; i++) { + bit = getbit(samples,i); + if (last) { + if(bit) { + continue; + } else { + len = 1; + } + } else { + if (bit) { + if (len > (low + high) /2) + value |= curBit; + curBit <<= 1; + if (curBit == 1) + break; + } else { + len++; + } + } + last = bit; + } + + return value; +} + +/* decode raw samples, biphase coding, used by rc5 for example */ +int ir_decode_biphase(u32 *samples, int count, int low, int high) +{ + int i,last,bit,len,flips; + u32 value; + + /* find start bit (1) */ + for (i = 0; i < 32; i++) { + bit = getbit(samples,i); + if (bit) + break; + } + + /* go decoding */ + len = 0; + flips = 0; + value = 1; + for (; i < count * 32; i++) { + if (len > high) + break; + if (flips > 1) + break; + last = bit; + bit = getbit(samples,i); + if (last == bit) { + len++; + continue; + } + if (len < low) { + len++; + flips++; + continue; + } + value <<= 1; + value |= bit; + flips = 0; + len = 1; + } + return value; +} + +EXPORT_SYMBOL_GPL(ir_input_init); +EXPORT_SYMBOL_GPL(ir_input_nokey); +EXPORT_SYMBOL_GPL(ir_input_keydown); + +EXPORT_SYMBOL_GPL(ir_extract_bits); +EXPORT_SYMBOL_GPL(ir_dump_samples); +EXPORT_SYMBOL_GPL(ir_decode_biphase); +EXPORT_SYMBOL_GPL(ir_decode_pulsedistance); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ + -- cgit v1.2.3-59-g8ed1b From 8cbe84f33a8d420d8c8228599bc042cb31c569fa Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 28 Feb 2006 04:40:51 -0300 Subject: V4L/DVB (3399a): cpia2/cpia2_v4l.c cleanups - make 2 needlessly global functions static - remove cpia2_setup(): the driver already allows setting parameters through module_param(), and there's no reason for having two different ways for setting the same parameters Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/README.cpia2 | 2 +- drivers/media/video/cpia2/cpia2_v4l.c | 29 ++--------------------------- 2 files changed, 3 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/README.cpia2 b/Documentation/video4linux/README.cpia2 index f3bd3439ad91..ce8213d28b67 100644 --- a/Documentation/video4linux/README.cpia2 +++ b/Documentation/video4linux/README.cpia2 @@ -70,7 +70,7 @@ line like this: If the driver is compiled into the kernel, at boot time specify them like this: - cpia2=num_buffers:3,buffer_size:65535 + cpia2.num_buffers=3 cpia2.buffer_size=65535 What buffer size should I use? ------------------------------ diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 3480a2ca7cdc..589283d5ddd1 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -2053,7 +2053,7 @@ static void __init check_parameters(void) * cpia2_init/module_init * *****************************************************************************/ -int __init cpia2_init(void) +static int __init cpia2_init(void) { LOG("%s v%d.%d.%d\n", ABOUT, CPIA2_MAJ_VER, CPIA2_MIN_VER, CPIA2_PATCH_VER); @@ -2068,37 +2068,12 @@ int __init cpia2_init(void) * cpia2_exit/module_exit * *****************************************************************************/ -void __exit cpia2_exit(void) +static void __exit cpia2_exit(void) { cpia2_usb_cleanup(); schedule_timeout(2 * HZ); } - -int __init cpia2_setup(char *str) -{ - while(str) { - if(!strncmp(str, "buffer_size:", 12)) { - buffer_size = simple_strtoul(str + 13, &str, 10); - } else if(!strncmp(str, "num_buffers:", 12)) { - num_buffers = simple_strtoul(str + 13, &str, 10); - } else if(!strncmp(str, "alternate:", 10)) { - alternate = simple_strtoul(str + 11, &str, 10); - } else if(!strncmp(str, "video_nr:", 9)) { - video_nr = simple_strtoul(str + 10, &str, 10); - } else if(!strncmp(str, "flicker_freq:",13)) { - flicker_freq = simple_strtoul(str + 14, &str, 10); - } else if(!strncmp(str, "flicker_mode:",13)) { - flicker_mode = simple_strtoul(str + 14, &str, 10); - } else { - ++str; - } - } - return 1; -} - -__setup("cpia2=", cpia2_setup); - module_init(cpia2_init); module_exit(cpia2_exit); -- cgit v1.2.3-59-g8ed1b From d5f9558a7778d3f7dc3c9e0d5cbe7318710532f8 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 3 Mar 2006 09:58:29 -0700 Subject: [PATCH] mv643xx_eth: Remove duplicate includes of linux/in.h and linux/ip.h Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 6b4fff80ae5f..4f36489e7cdb 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -37,8 +37,6 @@ #include #include #include -#include -#include #include #include -- cgit v1.2.3-59-g8ed1b From e38fd1a055cf4038c423bd841859b01aeb07d1b0 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 3 Mar 2006 09:59:28 -0700 Subject: [PATCH] mv643xx_eth: Fix misplaced parenthesis in mv643xx_eth_port_disable_rx This bug could result in a system hang. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 4f36489e7cdb..4cbf84052b0f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2496,8 +2496,8 @@ static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num) u32 channels; /* Stop Rx port activity. Check port Rx activity. */ - channels = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num) - & 0xFF); + channels = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num)) + & 0xFF; if (channels) { /* Issue stop command for active channels only */ mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), -- cgit v1.2.3-59-g8ed1b From 12a87c644ab1862232d0916656ff2ee42f3fb873 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 3 Mar 2006 10:00:22 -0700 Subject: [PATCH] mv643xx_eth: Rename "channels" to "queues" Use better terminology for HW queues. No functional changes. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 4cbf84052b0f..098f3a28837c 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -83,9 +83,9 @@ static void eth_port_uc_addr_get(struct net_device *dev, unsigned char *MacAddr); static void eth_port_set_multicast_list(struct net_device *); static void mv643xx_eth_port_enable_tx(unsigned int port_num, - unsigned int channels); + unsigned int queues); static void mv643xx_eth_port_enable_rx(unsigned int port_num, - unsigned int channels); + unsigned int queues); static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num); static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num); static int mv643xx_eth_open(struct net_device *); @@ -466,7 +466,7 @@ static void mv643xx_eth_update_pscr(struct net_device *dev, struct mv643xx_private *mp = netdev_priv(dev); int port_num = mp->port_num; u32 o_pscr, n_pscr; - unsigned int channels; + unsigned int queues; o_pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)); n_pscr = o_pscr; @@ -494,7 +494,7 @@ static void mv643xx_eth_update_pscr(struct net_device *dev, mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), n_pscr); else { - channels = mv643xx_eth_port_disable_tx(port_num); + queues = mv643xx_eth_port_disable_tx(port_num); o_pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE; mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), @@ -503,8 +503,8 @@ static void mv643xx_eth_update_pscr(struct net_device *dev, n_pscr); mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), n_pscr); - if (channels) - mv643xx_eth_port_enable_tx(port_num, channels); + if (queues) + mv643xx_eth_port_enable_tx(port_num, queues); } } } @@ -2453,28 +2453,28 @@ static void ethernet_phy_reset(unsigned int eth_port_num) } static void mv643xx_eth_port_enable_tx(unsigned int port_num, - unsigned int channels) + unsigned int queues) { - mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), channels); + mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), queues); } static void mv643xx_eth_port_enable_rx(unsigned int port_num, - unsigned int channels) + unsigned int queues) { - mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), channels); + mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), queues); } static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num) { - u32 channels; + u32 queues; /* Stop Tx port activity. Check port Tx activity. */ - channels = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num)) + queues = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF; - if (channels) { - /* Issue stop command for active channels only */ + if (queues) { + /* Issue stop command for active queues only */ mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), - (channels << 8)); + (queues << 8)); /* Wait for all Tx activity to terminate. */ /* Check port cause register that all Tx queues are stopped */ @@ -2488,20 +2488,20 @@ static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num) udelay(PHY_WAIT_MICRO_SECONDS); } - return channels; + return queues; } static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num) { - u32 channels; + u32 queues; /* Stop Rx port activity. Check port Rx activity. */ - channels = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num)) + queues = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF; - if (channels) { - /* Issue stop command for active channels only */ + if (queues) { + /* Issue stop command for active queues only */ mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), - (channels << 8)); + (queues << 8)); /* Wait for all Rx activity to terminate. */ /* Check port cause register that all Rx queues are stopped */ @@ -2510,7 +2510,7 @@ static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num) udelay(PHY_WAIT_MICRO_SECONDS); } - return channels; + return queues; } /* -- cgit v1.2.3-59-g8ed1b From cd6478c8aed9b2001dfff067fa66b7492a0a2ffa Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 3 Mar 2006 10:01:08 -0700 Subject: [PATCH] mv643xx_eth: Select CONFIG_MII on CONFIG_MV643XX_ETH >From : Dale Farnsworth Recent patches for the mv643xx_eth driver now use the MII interface library. Select MII so it gets built when that driver is selected. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 840bfed312f6..11ca9f03b43e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2194,6 +2194,7 @@ config GFAR_NAPI config MV643XX_ETH tristate "MV-643XX Ethernet support" depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3 || PPC_MULTIPLATFORM + select MII help This driver supports the gigabit Ethernet on the Marvell MV643XX chipset which is used in the Momenco Ocelot C and Jaguar ATX and -- cgit v1.2.3-59-g8ed1b From c8aaea25e0b069e9572caa74f984e109899c1765 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 3 Mar 2006 10:02:05 -0700 Subject: [PATCH] mv643xx_eth: Refactor tx command queuing code Simplify and remove redundant code for filling transmit descriptors. No changes in features; it's just a code reorganization/cleanup. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 549 +++++++++++++--------------------------------- drivers/net/mv643xx_eth.h | 19 +- 2 files changed, 158 insertions(+), 410 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 098f3a28837c..260be8048d3c 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -10,7 +10,7 @@ * * Copyright (C) 2003 Ralf Baechle * - * Copyright (C) 2004-2005 MontaVista Software, Inc. + * Copyright (C) 2004-2006 MontaVista Software, Inc. * Dale Farnsworth * * Copyright (C) 2004 Steven J. Hill @@ -554,7 +554,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, /* UDP change : We may need this */ if ((eth_int_cause_ext & 0x0000ffff) && (mv643xx_eth_free_tx_queue(dev, eth_int_cause_ext) == 0) && - (mp->tx_ring_size > mp->tx_desc_count + MAX_DESCS_PER_SKB)) + (mp->tx_ring_size - mp->tx_desc_count > MAX_DESCS_PER_SKB)) netif_wake_queue(dev); #ifdef MV643XX_NAPI } else { @@ -598,7 +598,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, mv643xx_eth_update_pscr(dev, &cmd); if (!netif_carrier_ok(dev)) { netif_carrier_on(dev); - if (mp->tx_ring_size > mp->tx_desc_count + + if (mp->tx_ring_size - mp->tx_desc_count > MAX_DESCS_PER_SKB) { netif_wake_queue(dev); /* Start TX queue */ @@ -777,9 +777,6 @@ static void ether_init_tx_desc_ring(struct mv643xx_private *mp) mp->tx_curr_desc_q = 0; mp->tx_used_desc_q = 0; -#ifdef MV643XX_CHECKSUM_OFFLOAD_TX - mp->tx_first_desc_q = 0; -#endif mp->tx_desc_area_size = tx_desc_num * sizeof(struct eth_tx_desc); @@ -1085,8 +1082,7 @@ static void mv643xx_tx(struct net_device *dev) } if (netif_queue_stopped(dev) && - mp->tx_ring_size > - mp->tx_desc_count + MAX_DESCS_PER_SKB) + mp->tx_ring_size - mp->tx_desc_count > MAX_DESCS_PER_SKB) netif_wake_queue(dev); } @@ -1133,7 +1129,10 @@ static int mv643xx_poll(struct net_device *dev, int *budget) } #endif -/* Hardware can't handle unaligned fragments smaller than 9 bytes. +/** + * has_tiny_unaligned_frags - check if skb has any small, unaligned fragments + * + * Hardware can't handle unaligned fragments smaller than 9 bytes. * This helper function detects that case. */ @@ -1150,223 +1149,170 @@ static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb) return 0; } +/** + * eth_alloc_tx_desc_index - return the index of the next available tx desc + */ +static int eth_alloc_tx_desc_index(struct mv643xx_private *mp) +{ + int tx_desc_curr; + + tx_desc_curr = mp->tx_curr_desc_q; -/* - * mv643xx_eth_start_xmit - * - * This function is queues a packet in the Tx descriptor for - * required port. - * - * Input : skb - a pointer to socket buffer - * dev - a pointer to the required port + BUG_ON(mp->tx_desc_count >= mp->tx_ring_size); + mp->tx_desc_count++; + + mp->tx_curr_desc_q = (tx_desc_curr + 1) % mp->tx_ring_size; + + BUG_ON(mp->tx_curr_desc_q == mp->tx_used_desc_q); + + return tx_desc_curr; +} + +/** + * eth_tx_fill_frag_descs - fill tx hw descriptors for an skb's fragments. * - * Output : zero upon success + * Ensure the data for each fragment to be transmitted is mapped properly, + * then fill in descriptors in the tx hw queue. */ -static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) +static void eth_tx_fill_frag_descs(struct mv643xx_private *mp, + struct sk_buff *skb) { - struct mv643xx_private *mp = netdev_priv(dev); + int frag; + int tx_index; + struct eth_tx_desc *desc; struct net_device_stats *stats = &mp->stats; - ETH_FUNC_RET_STATUS status; - unsigned long flags; - struct pkt_info pkt_info; - if (netif_queue_stopped(dev)) { - printk(KERN_ERR - "%s: Tried sending packet when interface is stopped\n", - dev->name); - return 1; + for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { + skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag]; + + tx_index = eth_alloc_tx_desc_index(mp); + desc = &mp->p_tx_desc_area[tx_index]; + + desc->cmd_sts = ETH_BUFFER_OWNED_BY_DMA; + /* Last Frag enables interrupt and frees the skb */ + if (frag == (skb_shinfo(skb)->nr_frags - 1)) { + desc->cmd_sts |= ETH_ZERO_PADDING | + ETH_TX_LAST_DESC | + ETH_TX_ENABLE_INTERRUPT; + mp->tx_skb[tx_index] = skb; + } else + mp->tx_skb[tx_index] = 0; + + desc = &mp->p_tx_desc_area[tx_index]; + desc->l4i_chk = 0; + desc->byte_cnt = this_frag->size; + desc->buf_ptr = dma_map_page(NULL, this_frag->page, + this_frag->page_offset, + this_frag->size, + DMA_TO_DEVICE); + stats->tx_bytes += this_frag->size; } +} - /* This is a hard error, log it. */ - if ((mp->tx_ring_size - mp->tx_desc_count) <= - (skb_shinfo(skb)->nr_frags + 1)) { - netif_stop_queue(dev); - printk(KERN_ERR - "%s: Bug in mv643xx_eth - Trying to transmit when" - " queue full !\n", dev->name); - return 1; - } +/** + * eth_tx_submit_descs_for_skb - submit data from an skb to the tx hw + * + * Ensure the data for an skb to be transmitted is mapped properly, + * then fill in descriptors in the tx hw queue and start the hardware. + */ +static int eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, + struct sk_buff *skb) +{ + int tx_index; + struct eth_tx_desc *desc; + u32 cmd_sts; + int length; + int tx_bytes = 0; - /* Paranoid check - this shouldn't happen */ - if (skb == NULL) { - stats->tx_dropped++; - printk(KERN_ERR "mv64320_eth paranoid check failed\n"); - return 1; - } + cmd_sts = ETH_TX_FIRST_DESC | ETH_GEN_CRC | ETH_BUFFER_OWNED_BY_DMA; -#ifdef MV643XX_CHECKSUM_OFFLOAD_TX - if (has_tiny_unaligned_frags(skb)) { - if ((skb_linearize(skb, GFP_ATOMIC) != 0)) { - stats->tx_dropped++; - printk(KERN_DEBUG "%s: failed to linearize tiny " - "unaligned fragment\n", dev->name); - return 1; - } + tx_index = eth_alloc_tx_desc_index(mp); + desc = &mp->p_tx_desc_area[tx_index]; + + if (skb_shinfo(skb)->nr_frags) { + eth_tx_fill_frag_descs(mp, skb); + + length = skb_headlen(skb); + mp->tx_skb[tx_index] = 0; + } else { + cmd_sts |= ETH_ZERO_PADDING | + ETH_TX_LAST_DESC | + ETH_TX_ENABLE_INTERRUPT; + length = skb->len; + mp->tx_skb[tx_index] = skb; } - spin_lock_irqsave(&mp->lock, flags); + desc->byte_cnt = length; + desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); + tx_bytes += length; - if (!skb_shinfo(skb)->nr_frags) { - if (skb->ip_summed != CHECKSUM_HW) { - /* Errata BTS #50, IHL must be 5 if no HW checksum */ - pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | - ETH_TX_FIRST_DESC | - ETH_TX_LAST_DESC | - 5 << ETH_TX_IHL_SHIFT; - pkt_info.l4i_chk = 0; - } else { - pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | - ETH_TX_FIRST_DESC | - ETH_TX_LAST_DESC | - ETH_GEN_TCP_UDP_CHECKSUM | - ETH_GEN_IP_V_4_CHECKSUM | - skb->nh.iph->ihl << ETH_TX_IHL_SHIFT; - /* CPU already calculated pseudo header checksum. */ - if ((skb->protocol == ETH_P_IP) && - (skb->nh.iph->protocol == IPPROTO_UDP) ) { - pkt_info.cmd_sts |= ETH_UDP_FRAME; - pkt_info.l4i_chk = skb->h.uh->check; - } else if ((skb->protocol == ETH_P_IP) && - (skb->nh.iph->protocol == IPPROTO_TCP)) - pkt_info.l4i_chk = skb->h.th->check; - else { - printk(KERN_ERR - "%s: chksum proto != IPv4 TCP or UDP\n", - dev->name); - spin_unlock_irqrestore(&mp->lock, flags); - return 1; - } + if (skb->ip_summed == CHECKSUM_HW) { + BUG_ON(skb->protocol != ETH_P_IP); + + cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM | + ETH_GEN_IP_V_4_CHECKSUM | + skb->nh.iph->ihl << ETH_TX_IHL_SHIFT; + + switch (skb->nh.iph->protocol) { + case IPPROTO_UDP: + cmd_sts |= ETH_UDP_FRAME; + desc->l4i_chk = skb->h.uh->check; + break; + case IPPROTO_TCP: + desc->l4i_chk = skb->h.th->check; + break; + default: + BUG(); } - pkt_info.byte_cnt = skb->len; - pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len, - DMA_TO_DEVICE); - pkt_info.return_info = skb; - status = eth_port_send(mp, &pkt_info); - if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) - printk(KERN_ERR "%s: Error on transmitting packet\n", - dev->name); - stats->tx_bytes += pkt_info.byte_cnt; } else { - unsigned int frag; - - /* first frag which is skb header */ - pkt_info.byte_cnt = skb_headlen(skb); - pkt_info.buf_ptr = dma_map_single(NULL, skb->data, - skb_headlen(skb), - DMA_TO_DEVICE); - pkt_info.l4i_chk = 0; - pkt_info.return_info = 0; - - if (skb->ip_summed != CHECKSUM_HW) - /* Errata BTS #50, IHL must be 5 if no HW checksum */ - pkt_info.cmd_sts = ETH_TX_FIRST_DESC | - 5 << ETH_TX_IHL_SHIFT; - else { - pkt_info.cmd_sts = ETH_TX_FIRST_DESC | - ETH_GEN_TCP_UDP_CHECKSUM | - ETH_GEN_IP_V_4_CHECKSUM | - skb->nh.iph->ihl << ETH_TX_IHL_SHIFT; - /* CPU already calculated pseudo header checksum. */ - if ((skb->protocol == ETH_P_IP) && - (skb->nh.iph->protocol == IPPROTO_UDP)) { - pkt_info.cmd_sts |= ETH_UDP_FRAME; - pkt_info.l4i_chk = skb->h.uh->check; - } else if ((skb->protocol == ETH_P_IP) && - (skb->nh.iph->protocol == IPPROTO_TCP)) - pkt_info.l4i_chk = skb->h.th->check; - else { - printk(KERN_ERR - "%s: chksum proto != IPv4 TCP or UDP\n", - dev->name); - spin_unlock_irqrestore(&mp->lock, flags); - return 1; - } - } + /* Errata BTS #50, IHL must be 5 if no HW checksum */ + cmd_sts |= 5 << ETH_TX_IHL_SHIFT; + desc->l4i_chk = 0; + } - status = eth_port_send(mp, &pkt_info); - if (status != ETH_OK) { - if ((status == ETH_ERROR)) - printk(KERN_ERR - "%s: Error on transmitting packet\n", - dev->name); - if (status == ETH_QUEUE_FULL) - printk("Error on Queue Full \n"); - if (status == ETH_QUEUE_LAST_RESOURCE) - printk("Tx resource error \n"); - } - stats->tx_bytes += pkt_info.byte_cnt; - - /* Check for the remaining frags */ - for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { - skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag]; - pkt_info.l4i_chk = 0x0000; - pkt_info.cmd_sts = 0x00000000; - - /* Last Frag enables interrupt and frees the skb */ - if (frag == (skb_shinfo(skb)->nr_frags - 1)) { - pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT | - ETH_TX_LAST_DESC; - pkt_info.return_info = skb; - } else { - pkt_info.return_info = 0; - } - pkt_info.l4i_chk = 0; - pkt_info.byte_cnt = this_frag->size; + /* ensure all other descriptors are written before first cmd_sts */ + wmb(); + desc->cmd_sts = cmd_sts; - pkt_info.buf_ptr = dma_map_page(NULL, this_frag->page, - this_frag->page_offset, - this_frag->size, - DMA_TO_DEVICE); + /* ensure all descriptors are written before poking hardware */ + wmb(); + mv643xx_eth_port_enable_tx(mp->port_num, mp->port_tx_queue_command); - status = eth_port_send(mp, &pkt_info); + return tx_bytes; +} - if (status != ETH_OK) { - if ((status == ETH_ERROR)) - printk(KERN_ERR "%s: Error on " - "transmitting packet\n", - dev->name); +/** + * mv643xx_eth_start_xmit - queue an skb to the hardware for transmission + * + */ +static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct mv643xx_private *mp = netdev_priv(dev); + struct net_device_stats *stats = &mp->stats; + unsigned long flags; - if (status == ETH_QUEUE_LAST_RESOURCE) - printk("Tx resource error \n"); + BUG_ON(netif_queue_stopped(dev)); + BUG_ON(skb == NULL); + BUG_ON(mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB); - if (status == ETH_QUEUE_FULL) - printk("Queue is full \n"); - } - stats->tx_bytes += pkt_info.byte_cnt; + if (has_tiny_unaligned_frags(skb)) { + if ((skb_linearize(skb, GFP_ATOMIC) != 0)) { + stats->tx_dropped++; + printk(KERN_DEBUG "%s: failed to linearize tiny " + "unaligned fragment\n", dev->name); + return 1; } } -#else - spin_lock_irqsave(&mp->lock, flags); - - pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | ETH_TX_FIRST_DESC | - ETH_TX_LAST_DESC; - pkt_info.l4i_chk = 0; - pkt_info.byte_cnt = skb->len; - pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len, - DMA_TO_DEVICE); - pkt_info.return_info = skb; - status = eth_port_send(mp, &pkt_info); - if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) - printk(KERN_ERR "%s: Error on transmitting packet\n", - dev->name); - stats->tx_bytes += pkt_info.byte_cnt; -#endif - /* Check if TX queue can handle another skb. If not, then - * signal higher layers to stop requesting TX - */ - if (mp->tx_ring_size <= (mp->tx_desc_count + MAX_DESCS_PER_SKB)) - /* - * Stop getting skb's from upper layers. - * Getting skb's from upper layers will be enabled again after - * packets are released. - */ - netif_stop_queue(dev); + spin_lock_irqsave(&mp->lock, flags); - /* Update statistics and start of transmittion time */ + stats->tx_bytes = eth_tx_submit_descs_for_skb(mp, skb); stats->tx_packets++; dev->trans_start = jiffies; + if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) + netif_stop_queue(dev); + spin_unlock_irqrestore(&mp->lock, flags); return 0; /* success */ @@ -1812,22 +1758,6 @@ MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX"); * to the Rx descriptor ring to enable the reuse of this source. * Return Rx resource is done using the eth_rx_return_buff API. * - * Transmit operation: - * The eth_port_send API supports Scatter-Gather which enables to - * send a packet spanned over multiple buffers. This means that - * for each packet info structure given by the user and put into - * the Tx descriptors ring, will be transmitted only if the 'LAST' - * bit will be set in the packet info command status field. This - * API also consider restriction regarding buffer alignments and - * sizes. - * The user must return a Tx resource after ensuring the buffer - * has been transmitted to enable the Tx ring indexes to update. - * - * BOARD LAYOUT - * This device is on-board. No jumper diagram is necessary. - * - * EXTERNAL INTERFACE - * * Prior to calling the initialization routine eth_port_init() the user * must set the following fields under mv643xx_private struct: * port_num User Ethernet port number. @@ -1881,7 +1811,6 @@ static void eth_port_set_filter_table_entry(int table, unsigned char entry); static void eth_port_init(struct mv643xx_private *mp) { mp->rx_resource_err = 0; - mp->tx_resource_err = 0; eth_port_reset(mp->port_num); @@ -2672,166 +2601,6 @@ static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, eth_port_write_smi_reg(mp->port_num, location, val); } -/* - * eth_port_send - Send an Ethernet packet - * - * DESCRIPTION: - * This routine send a given packet described by p_pktinfo parameter. It - * supports transmitting of a packet spaned over multiple buffers. The - * routine updates 'curr' and 'first' indexes according to the packet - * segment passed to the routine. In case the packet segment is first, - * the 'first' index is update. In any case, the 'curr' index is updated. - * If the routine get into Tx resource error it assigns 'curr' index as - * 'first'. This way the function can abort Tx process of multiple - * descriptors per packet. - * - * INPUT: - * struct mv643xx_private *mp Ethernet Port Control srtuct. - * struct pkt_info *p_pkt_info User packet buffer. - * - * OUTPUT: - * Tx ring 'curr' and 'first' indexes are updated. - * - * RETURN: - * ETH_QUEUE_FULL in case of Tx resource error. - * ETH_ERROR in case the routine can not access Tx desc ring. - * ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource. - * ETH_OK otherwise. - * - */ -#ifdef MV643XX_CHECKSUM_OFFLOAD_TX -/* - * Modified to include the first descriptor pointer in case of SG - */ -static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, - struct pkt_info *p_pkt_info) -{ - int tx_desc_curr, tx_desc_used, tx_first_desc, tx_next_desc; - struct eth_tx_desc *current_descriptor; - struct eth_tx_desc *first_descriptor; - u32 command; - - /* Do not process Tx ring in case of Tx ring resource error */ - if (mp->tx_resource_err) - return ETH_QUEUE_FULL; - - /* - * The hardware requires that each buffer that is <= 8 bytes - * in length must be aligned on an 8 byte boundary. - */ - if (p_pkt_info->byte_cnt <= 8 && p_pkt_info->buf_ptr & 0x7) { - printk(KERN_ERR - "mv643xx_eth port %d: packet size <= 8 problem\n", - mp->port_num); - return ETH_ERROR; - } - - mp->tx_desc_count++; - BUG_ON(mp->tx_desc_count > mp->tx_ring_size); - - /* Get the Tx Desc ring indexes */ - tx_desc_curr = mp->tx_curr_desc_q; - tx_desc_used = mp->tx_used_desc_q; - - current_descriptor = &mp->p_tx_desc_area[tx_desc_curr]; - - tx_next_desc = (tx_desc_curr + 1) % mp->tx_ring_size; - - current_descriptor->buf_ptr = p_pkt_info->buf_ptr; - current_descriptor->byte_cnt = p_pkt_info->byte_cnt; - current_descriptor->l4i_chk = p_pkt_info->l4i_chk; - mp->tx_skb[tx_desc_curr] = p_pkt_info->return_info; - - command = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC | - ETH_BUFFER_OWNED_BY_DMA; - if (command & ETH_TX_FIRST_DESC) { - tx_first_desc = tx_desc_curr; - mp->tx_first_desc_q = tx_first_desc; - first_descriptor = current_descriptor; - mp->tx_first_command = command; - } else { - tx_first_desc = mp->tx_first_desc_q; - first_descriptor = &mp->p_tx_desc_area[tx_first_desc]; - BUG_ON(first_descriptor == NULL); - current_descriptor->cmd_sts = command; - } - - if (command & ETH_TX_LAST_DESC) { - wmb(); - first_descriptor->cmd_sts = mp->tx_first_command; - - wmb(); - mv643xx_eth_port_enable_tx(mp->port_num, mp->port_tx_queue_command); - - /* - * Finish Tx packet. Update first desc in case of Tx resource - * error */ - tx_first_desc = tx_next_desc; - mp->tx_first_desc_q = tx_first_desc; - } - - /* Check for ring index overlap in the Tx desc ring */ - if (tx_next_desc == tx_desc_used) { - mp->tx_resource_err = 1; - mp->tx_curr_desc_q = tx_first_desc; - - return ETH_QUEUE_LAST_RESOURCE; - } - - mp->tx_curr_desc_q = tx_next_desc; - - return ETH_OK; -} -#else -static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, - struct pkt_info *p_pkt_info) -{ - int tx_desc_curr; - int tx_desc_used; - struct eth_tx_desc *current_descriptor; - unsigned int command_status; - - /* Do not process Tx ring in case of Tx ring resource error */ - if (mp->tx_resource_err) - return ETH_QUEUE_FULL; - - mp->tx_desc_count++; - BUG_ON(mp->tx_desc_count > mp->tx_ring_size); - - /* Get the Tx Desc ring indexes */ - tx_desc_curr = mp->tx_curr_desc_q; - tx_desc_used = mp->tx_used_desc_q; - current_descriptor = &mp->p_tx_desc_area[tx_desc_curr]; - - command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC; - current_descriptor->buf_ptr = p_pkt_info->buf_ptr; - current_descriptor->byte_cnt = p_pkt_info->byte_cnt; - mp->tx_skb[tx_desc_curr] = p_pkt_info->return_info; - - /* Set last desc with DMA ownership and interrupt enable. */ - wmb(); - current_descriptor->cmd_sts = command_status | - ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT; - - wmb(); - mv643xx_eth_port_enable_tx(mp->port_num, mp->port_tx_queue_command); - - /* Finish Tx packet. Update first desc in case of Tx resource error */ - tx_desc_curr = (tx_desc_curr + 1) % mp->tx_ring_size; - - /* Update the current descriptor */ - mp->tx_curr_desc_q = tx_desc_curr; - - /* Check for ring index overlap in the Tx desc ring */ - if (tx_desc_curr == tx_desc_used) { - mp->tx_resource_err = 1; - return ETH_QUEUE_LAST_RESOURCE; - } - - return ETH_OK; -} -#endif - /* * eth_tx_return_desc - Free all used Tx descriptors * @@ -2858,7 +2627,6 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp, struct pkt_info *p_pkt_info) { int tx_desc_used; - int tx_busy_desc; struct eth_tx_desc *p_tx_desc_used; unsigned int command_status; unsigned long flags; @@ -2866,33 +2634,23 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp, spin_lock_irqsave(&mp->lock, flags); -#ifdef MV643XX_CHECKSUM_OFFLOAD_TX - tx_busy_desc = mp->tx_first_desc_q; -#else - tx_busy_desc = mp->tx_curr_desc_q; -#endif + BUG_ON(mp->tx_desc_count < 0); + if (mp->tx_desc_count == 0) { + /* no more tx descs in use */ + err = ETH_ERROR; + goto out; + } /* Get the Tx Desc ring indexes */ tx_desc_used = mp->tx_used_desc_q; p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used]; - /* Sanity check */ - if (p_tx_desc_used == NULL) { - err = ETH_ERROR; - goto out; - } - - /* Stop release. About to overlap the current available Tx descriptor */ - if (tx_desc_used == tx_busy_desc && !mp->tx_resource_err) { - err = ETH_ERROR; - goto out; - } + BUG_ON(p_tx_desc_used == NULL); command_status = p_tx_desc_used->cmd_sts; - - /* Still transmitting... */ if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) { + /* Still transmitting... */ err = ETH_ERROR; goto out; } @@ -2907,9 +2665,6 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp, /* Update the next descriptor to release. */ mp->tx_used_desc_q = (tx_desc_used + 1) % mp->tx_ring_size; - /* Any Tx return cancels the Tx resource error status */ - mp->tx_resource_err = 0; - BUG_ON(mp->tx_desc_count == 0); mp->tx_desc_count--; diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index a553054e8da7..8768e1ba45df 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -330,7 +330,6 @@ struct mv643xx_private { u32 tx_sram_size; /* Size of tx sram area */ int rx_resource_err; /* Rx ring resource error flag */ - int tx_resource_err; /* Tx ring resource error flag */ /* Tx/Rx rings managment indexes fields. For driver use */ @@ -339,10 +338,6 @@ struct mv643xx_private { /* Next available and first returning Tx resource */ int tx_curr_desc_q, tx_used_desc_q; -#ifdef MV643XX_CHECKSUM_OFFLOAD_TX - int tx_first_desc_q; - u32 tx_first_command; -#endif #ifdef MV643XX_TX_FAST_REFILL u32 tx_clean_threshold; @@ -350,12 +345,12 @@ struct mv643xx_private { struct eth_rx_desc *p_rx_desc_area; dma_addr_t rx_desc_dma; - unsigned int rx_desc_area_size; + int rx_desc_area_size; struct sk_buff **rx_skb; struct eth_tx_desc *p_tx_desc_area; dma_addr_t tx_desc_dma; - unsigned int tx_desc_area_size; + int tx_desc_area_size; struct sk_buff **tx_skb; struct work_struct tx_timeout_task; @@ -367,13 +362,13 @@ struct mv643xx_private { struct mv643xx_mib_counters mib_counters; spinlock_t lock; /* Size of Tx Ring per queue */ - unsigned int tx_ring_size; + int tx_ring_size; /* Number of tx descriptors in use */ - unsigned int tx_desc_count; + int tx_desc_count; /* Size of Rx Ring per queue */ - unsigned int rx_ring_size; + int rx_ring_size; /* Number of rx descriptors in use */ - unsigned int rx_desc_count; + int rx_desc_count; /* * rx_task used to fill RX ring out of bottom half context @@ -416,8 +411,6 @@ static void eth_port_read_smi_reg(unsigned int eth_port_num, static void eth_clear_mib_counters(unsigned int eth_port_num); /* Port data flow control routines */ -static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, - struct pkt_info *p_pkt_info); static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp, struct pkt_info *p_pkt_info); static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp, -- cgit v1.2.3-59-g8ed1b From ff561eef9fb37c7180085e08418acfc009a9ada7 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 3 Mar 2006 10:02:51 -0700 Subject: [PATCH] mv643xx_eth: Refactor/clean up tx queue handling Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 257 +++++++++++++++------------------------------- drivers/net/mv643xx_eth.h | 4 - 2 files changed, 84 insertions(+), 177 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 260be8048d3c..8a24b39f3ccb 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -62,6 +62,9 @@ #define WRAP HW_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN #define RX_SKB_SIZE ((dev->mtu + WRAP + 7) & ~0x7) +#define ETH_RX_QUEUES_ENABLED (1 << 0) /* use only Q0 for receive */ +#define ETH_TX_QUEUES_ENABLED (1 << 0) /* use only Q0 for transmit */ + #define INT_UNMASK_ALL 0x0007ffff #define INT_UNMASK_ALL_EXT 0x0011ffff #define INT_MASK_ALL 0x00000000 @@ -333,49 +336,78 @@ static void mv643xx_eth_tx_timeout_task(struct net_device *dev) netif_device_attach(dev); } -/* - * mv643xx_eth_free_tx_queue - * - * Input : dev - a pointer to the required interface +/** + * mv643xx_eth_free_tx_descs - Free the tx desc data for completed descriptors * - * Output : 0 if was able to release skb , nonzero otherwise + * If force is non-zero, frees uncompleted descriptors as well */ -static int mv643xx_eth_free_tx_queue(struct net_device *dev, - unsigned int eth_int_cause_ext) +int mv643xx_eth_free_tx_descs(struct net_device *dev, int force) { struct mv643xx_private *mp = netdev_priv(dev); - struct net_device_stats *stats = &mp->stats; - struct pkt_info pkt_info; - int released = 1; + struct eth_tx_desc *desc; + u32 cmd_sts; + struct sk_buff *skb; + unsigned long flags; + int tx_index; + dma_addr_t addr; + int count; + int released = 0; - if (!(eth_int_cause_ext & (BIT0 | BIT8))) - return released; + while (mp->tx_desc_count > 0) { + spin_lock_irqsave(&mp->lock, flags); + tx_index = mp->tx_used_desc_q; + desc = &mp->p_tx_desc_area[tx_index]; + cmd_sts = desc->cmd_sts; + + if (!force && (cmd_sts & ETH_BUFFER_OWNED_BY_DMA)) { + spin_unlock_irqrestore(&mp->lock, flags); + return released; + } + + mp->tx_used_desc_q = (tx_index + 1) % mp->tx_ring_size; + mp->tx_desc_count--; + + addr = desc->buf_ptr; + count = desc->byte_cnt; + skb = mp->tx_skb[tx_index]; + if (skb) + mp->tx_skb[tx_index] = NULL; + + spin_unlock_irqrestore(&mp->lock, flags); - /* Check only queue 0 */ - while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) { - if (pkt_info.cmd_sts & BIT0) { + if (cmd_sts & BIT0) { printk("%s: Error in TX\n", dev->name); - stats->tx_errors++; + mp->stats.tx_errors++; } - if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC) - dma_unmap_single(NULL, pkt_info.buf_ptr, - pkt_info.byte_cnt, - DMA_TO_DEVICE); + if (cmd_sts & ETH_TX_FIRST_DESC) + dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); else - dma_unmap_page(NULL, pkt_info.buf_ptr, - pkt_info.byte_cnt, - DMA_TO_DEVICE); + dma_unmap_page(NULL, addr, count, DMA_TO_DEVICE); - if (pkt_info.return_info) { - dev_kfree_skb_irq(pkt_info.return_info); - released = 0; - } + if (skb) + dev_kfree_skb_irq(skb); + + released = 1; } return released; } +static void mv643xx_eth_free_completed_tx_descs(struct net_device *dev) +{ + struct mv643xx_private *mp = netdev_priv(dev); + + if (mv643xx_eth_free_tx_descs(dev, 0) && + mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB) + netif_wake_queue(dev); +} + +static void mv643xx_eth_free_all_tx_descs(struct net_device *dev) +{ + mv643xx_eth_free_tx_descs(dev, 1); +} + /* * mv643xx_eth_receive * @@ -547,15 +579,13 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, */ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), ~eth_int_cause); - if (eth_int_cause_ext != 0x0) + if (eth_int_cause_ext != 0x0) { mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG (port_num), ~eth_int_cause_ext); - - /* UDP change : We may need this */ - if ((eth_int_cause_ext & 0x0000ffff) && - (mv643xx_eth_free_tx_queue(dev, eth_int_cause_ext) == 0) && - (mp->tx_ring_size - mp->tx_desc_count > MAX_DESCS_PER_SKB)) - netif_wake_queue(dev); + /* UDP change : We may need this */ + if (eth_int_cause_ext & (BIT0 | BIT8)) + mv643xx_eth_free_completed_tx_descs(dev); + } #ifdef MV643XX_NAPI } else { if (netif_rx_schedule_prep(dev)) { @@ -596,14 +626,13 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, if (mii_link_ok(&mp->mii)) { mii_ethtool_gset(&mp->mii, &cmd); mv643xx_eth_update_pscr(dev, &cmd); + mv643xx_eth_port_enable_tx(port_num, + ETH_TX_QUEUES_ENABLED); if (!netif_carrier_ok(dev)) { netif_carrier_on(dev); - if (mp->tx_ring_size - mp->tx_desc_count > - MAX_DESCS_PER_SKB) { + if (mp->tx_ring_size - mp->tx_desc_count >= + MAX_DESCS_PER_SKB) netif_wake_queue(dev); - /* Start TX queue */ - mv643xx_eth_port_enable_tx(port_num, mp->port_tx_queue_command); - } } } else if (netif_carrier_ok(dev)) { netif_stop_queue(dev); @@ -735,9 +764,6 @@ static void ether_init_rx_desc_ring(struct mv643xx_private *mp) mp->rx_used_desc_q = 0; mp->rx_desc_area_size = rx_desc_num * sizeof(struct eth_rx_desc); - - /* Enable queue 0 for this port */ - mp->port_rx_queue_command = 1; } /* @@ -779,9 +805,6 @@ static void ether_init_tx_desc_ring(struct mv643xx_private *mp) mp->tx_used_desc_q = 0; mp->tx_desc_area_size = tx_desc_num * sizeof(struct eth_tx_desc); - - /* Enable queue 0 for this port */ - mp->port_tx_queue_command = 1; } static int mv643xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) @@ -963,25 +986,14 @@ out_free_irq: static void mv643xx_eth_free_tx_rings(struct net_device *dev) { struct mv643xx_private *mp = netdev_priv(dev); - unsigned int port_num = mp->port_num; - unsigned int curr; - struct sk_buff *skb; /* Stop Tx Queues */ - mv643xx_eth_port_disable_tx(port_num); + mv643xx_eth_port_disable_tx(mp->port_num); - /* Free outstanding skb's on TX rings */ - for (curr = 0; mp->tx_desc_count && curr < mp->tx_ring_size; curr++) { - skb = mp->tx_skb[curr]; - if (skb) { - mp->tx_desc_count -= skb_shinfo(skb)->nr_frags; - dev_kfree_skb(skb); - mp->tx_desc_count--; - } - } - if (mp->tx_desc_count) - printk("%s: Error on Tx descriptor free - could not free %d" - " descriptors\n", dev->name, mp->tx_desc_count); + /* Free outstanding skb's on TX ring */ + mv643xx_eth_free_all_tx_descs(dev); + + BUG_ON(mp->tx_used_desc_q != mp->tx_curr_desc_q); /* Free TX ring */ if (mp->tx_sram_size) @@ -1062,30 +1074,6 @@ static int mv643xx_eth_stop(struct net_device *dev) } #ifdef MV643XX_NAPI -static void mv643xx_tx(struct net_device *dev) -{ - struct mv643xx_private *mp = netdev_priv(dev); - struct pkt_info pkt_info; - - while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) { - if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC) - dma_unmap_single(NULL, pkt_info.buf_ptr, - pkt_info.byte_cnt, - DMA_TO_DEVICE); - else - dma_unmap_page(NULL, pkt_info.buf_ptr, - pkt_info.byte_cnt, - DMA_TO_DEVICE); - - if (pkt_info.return_info) - dev_kfree_skb_irq(pkt_info.return_info); - } - - if (netif_queue_stopped(dev) && - mp->tx_ring_size - mp->tx_desc_count > MAX_DESCS_PER_SKB) - netif_wake_queue(dev); -} - /* * mv643xx_poll * @@ -1099,7 +1087,7 @@ static int mv643xx_poll(struct net_device *dev, int *budget) #ifdef MV643XX_TX_FAST_REFILL if (++mp->tx_clean_threshold > 5) { - mv643xx_tx(dev); + mv643xx_eth_free_completed_tx_descs(dev); mp->tx_clean_threshold = 0; } #endif @@ -1156,11 +1144,9 @@ static int eth_alloc_tx_desc_index(struct mv643xx_private *mp) { int tx_desc_curr; - tx_desc_curr = mp->tx_curr_desc_q; - BUG_ON(mp->tx_desc_count >= mp->tx_ring_size); - mp->tx_desc_count++; + tx_desc_curr = mp->tx_curr_desc_q; mp->tx_curr_desc_q = (tx_desc_curr + 1) % mp->tx_ring_size; BUG_ON(mp->tx_curr_desc_q == mp->tx_used_desc_q); @@ -1180,7 +1166,6 @@ static void eth_tx_fill_frag_descs(struct mv643xx_private *mp, int frag; int tx_index; struct eth_tx_desc *desc; - struct net_device_stats *stats = &mp->stats; for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag]; @@ -1205,7 +1190,6 @@ static void eth_tx_fill_frag_descs(struct mv643xx_private *mp, this_frag->page_offset, this_frag->size, DMA_TO_DEVICE); - stats->tx_bytes += this_frag->size; } } @@ -1215,21 +1199,21 @@ static void eth_tx_fill_frag_descs(struct mv643xx_private *mp, * Ensure the data for an skb to be transmitted is mapped properly, * then fill in descriptors in the tx hw queue and start the hardware. */ -static int eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, - struct sk_buff *skb) +static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, + struct sk_buff *skb) { int tx_index; struct eth_tx_desc *desc; u32 cmd_sts; int length; - int tx_bytes = 0; + int nr_frags = skb_shinfo(skb)->nr_frags; cmd_sts = ETH_TX_FIRST_DESC | ETH_GEN_CRC | ETH_BUFFER_OWNED_BY_DMA; tx_index = eth_alloc_tx_desc_index(mp); desc = &mp->p_tx_desc_area[tx_index]; - if (skb_shinfo(skb)->nr_frags) { + if (nr_frags) { eth_tx_fill_frag_descs(mp, skb); length = skb_headlen(skb); @@ -1244,7 +1228,6 @@ static int eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, desc->byte_cnt = length; desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); - tx_bytes += length; if (skb->ip_summed == CHECKSUM_HW) { BUG_ON(skb->protocol != ETH_P_IP); @@ -1276,9 +1259,9 @@ static int eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, /* ensure all descriptors are written before poking hardware */ wmb(); - mv643xx_eth_port_enable_tx(mp->port_num, mp->port_tx_queue_command); + mv643xx_eth_port_enable_tx(mp->port_num, ETH_TX_QUEUES_ENABLED); - return tx_bytes; + mp->tx_desc_count += nr_frags + 1; } /** @@ -1306,7 +1289,8 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&mp->lock, flags); - stats->tx_bytes = eth_tx_submit_descs_for_skb(mp, skb); + eth_tx_submit_descs_for_skb(mp, skb); + stats->tx_bytes = skb->len; stats->tx_packets++; dev->trans_start = jiffies; @@ -1893,7 +1877,7 @@ static void eth_port_start(struct net_device *dev) MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE); /* Enable port Rx. */ - mv643xx_eth_port_enable_rx(port_num, mp->port_rx_queue_command); + mv643xx_eth_port_enable_rx(port_num, ETH_RX_QUEUES_ENABLED); /* Disable port bandwidth limits by clearing MTU register */ mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0); @@ -2601,79 +2585,6 @@ static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, eth_port_write_smi_reg(mp->port_num, location, val); } -/* - * eth_tx_return_desc - Free all used Tx descriptors - * - * DESCRIPTION: - * This routine returns the transmitted packet information to the caller. - * It uses the 'first' index to support Tx desc return in case a transmit - * of a packet spanned over multiple buffer still in process. - * In case the Tx queue was in "resource error" condition, where there are - * no available Tx resources, the function resets the resource error flag. - * - * INPUT: - * struct mv643xx_private *mp Ethernet Port Control srtuct. - * struct pkt_info *p_pkt_info User packet buffer. - * - * OUTPUT: - * Tx ring 'first' and 'used' indexes are updated. - * - * RETURN: - * ETH_OK on success - * ETH_ERROR otherwise. - * - */ -static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp, - struct pkt_info *p_pkt_info) -{ - int tx_desc_used; - struct eth_tx_desc *p_tx_desc_used; - unsigned int command_status; - unsigned long flags; - int err = ETH_OK; - - spin_lock_irqsave(&mp->lock, flags); - - BUG_ON(mp->tx_desc_count < 0); - if (mp->tx_desc_count == 0) { - /* no more tx descs in use */ - err = ETH_ERROR; - goto out; - } - - /* Get the Tx Desc ring indexes */ - tx_desc_used = mp->tx_used_desc_q; - - p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used]; - - BUG_ON(p_tx_desc_used == NULL); - - command_status = p_tx_desc_used->cmd_sts; - if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) { - /* Still transmitting... */ - err = ETH_ERROR; - goto out; - } - - /* Pass the packet information to the caller */ - p_pkt_info->cmd_sts = command_status; - p_pkt_info->return_info = mp->tx_skb[tx_desc_used]; - p_pkt_info->buf_ptr = p_tx_desc_used->buf_ptr; - p_pkt_info->byte_cnt = p_tx_desc_used->byte_cnt; - mp->tx_skb[tx_desc_used] = NULL; - - /* Update the next descriptor to release. */ - mp->tx_used_desc_q = (tx_desc_used + 1) % mp->tx_ring_size; - - BUG_ON(mp->tx_desc_count == 0); - mp->tx_desc_count--; - -out: - spin_unlock_irqrestore(&mp->lock, flags); - - return err; -} - /* * eth_port_receive - Get received information from Rx ring. * diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index 8768e1ba45df..cade2705423c 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -321,8 +321,6 @@ struct mv643xx_mib_counters { struct mv643xx_private { int port_num; /* User Ethernet port number */ - u32 port_tx_queue_command; /* Port active Tx queues summary*/ - u32 port_rx_queue_command; /* Port active Rx queues summary*/ u32 rx_sram_addr; /* Base address of rx sram area */ u32 rx_sram_size; /* Size of rx sram area */ @@ -411,8 +409,6 @@ static void eth_port_read_smi_reg(unsigned int eth_port_num, static void eth_clear_mib_counters(unsigned int eth_port_num); /* Port data flow control routines */ -static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp, - struct pkt_info *p_pkt_info); static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp, struct pkt_info *p_pkt_info); static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp, -- cgit v1.2.3-59-g8ed1b From 7303fde88a149c4cee54dae7e46d1895fa7214b4 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 3 Mar 2006 10:03:36 -0700 Subject: [PATCH] mv643xx_eth: Move #defines of constants to mv643xx_eth.h Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 66 +++++++++++++---------------------------------- drivers/net/mv643xx_eth.h | 47 +++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 8a24b39f3ccb..50ee08518c6b 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -50,37 +50,6 @@ #include #include "mv643xx_eth.h" -/* - * The first part is the high level driver of the gigE ethernet ports. - */ - -/* Constants */ -#define VLAN_HLEN 4 -#define FCS_LEN 4 -#define DMA_ALIGN 8 /* hw requires 8-byte alignment */ -#define HW_IP_ALIGN 2 /* hw aligns IP header */ -#define WRAP HW_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN -#define RX_SKB_SIZE ((dev->mtu + WRAP + 7) & ~0x7) - -#define ETH_RX_QUEUES_ENABLED (1 << 0) /* use only Q0 for receive */ -#define ETH_TX_QUEUES_ENABLED (1 << 0) /* use only Q0 for transmit */ - -#define INT_UNMASK_ALL 0x0007ffff -#define INT_UNMASK_ALL_EXT 0x0011ffff -#define INT_MASK_ALL 0x00000000 -#define INT_MASK_ALL_EXT 0x00000000 -#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL -#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT - -#ifdef MV643XX_CHECKSUM_OFFLOAD_TX -#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1) -#else -#define MAX_DESCS_PER_SKB 1 -#endif - -#define PHY_WAIT_ITERATIONS 1000 /* 1000 iterations * 10uS = 10mS max */ -#define PHY_WAIT_MICRO_SECONDS 10 - /* Static function declarations */ static void eth_port_uc_addr_get(struct net_device *dev, unsigned char *MacAddr); @@ -182,24 +151,24 @@ static void mv643xx_eth_rx_task(void *data) panic("%s: Error in test_set_bit / clear_bit", dev->name); while (mp->rx_desc_count < (mp->rx_ring_size - 5)) { - skb = dev_alloc_skb(RX_SKB_SIZE + DMA_ALIGN); + skb = dev_alloc_skb(ETH_RX_SKB_SIZE + ETH_DMA_ALIGN); if (!skb) break; mp->rx_desc_count++; - unaligned = (u32)skb->data & (DMA_ALIGN - 1); + unaligned = (u32)skb->data & (ETH_DMA_ALIGN - 1); if (unaligned) - skb_reserve(skb, DMA_ALIGN - unaligned); + skb_reserve(skb, ETH_DMA_ALIGN - unaligned); pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT; - pkt_info.byte_cnt = RX_SKB_SIZE; - pkt_info.buf_ptr = dma_map_single(NULL, skb->data, RX_SKB_SIZE, - DMA_FROM_DEVICE); + pkt_info.byte_cnt = ETH_RX_SKB_SIZE; + pkt_info.buf_ptr = dma_map_single(NULL, skb->data, + ETH_RX_SKB_SIZE, DMA_FROM_DEVICE); pkt_info.return_info = skb; if (eth_rx_return_buff(mp, &pkt_info) != ETH_OK) { printk(KERN_ERR "%s: Error allocating RX Ring\n", dev->name); break; } - skb_reserve(skb, HW_IP_ALIGN); + skb_reserve(skb, ETH_HW_IP_ALIGN); } clear_bit(0, &mp->rx_task_busy); /* @@ -375,7 +344,7 @@ int mv643xx_eth_free_tx_descs(struct net_device *dev, int force) spin_unlock_irqrestore(&mp->lock, flags); - if (cmd_sts & BIT0) { + if (cmd_sts & ETH_ERROR_SUMMARY) { printk("%s: Error in TX\n", dev->name); mp->stats.tx_errors++; } @@ -562,12 +531,12 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, /* Read interrupt cause registers */ eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) & - INT_UNMASK_ALL; + ETH_INT_UNMASK_ALL; if (eth_int_cause & BIT1) eth_int_cause_ext = mv_read( MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) & - INT_UNMASK_ALL_EXT; + ETH_INT_UNMASK_ALL_EXT; #ifdef MV643XX_NAPI if (!(eth_int_cause & 0x0007fffd)) { @@ -591,7 +560,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, if (netif_rx_schedule_prep(dev)) { /* Mask all the interrupts */ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), - INT_MASK_ALL); + ETH_INT_MASK_ALL); /* wait for previous write to complete */ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num)); __netif_rx_schedule(dev); @@ -619,6 +588,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, #endif #endif } + /* PHY status changed */ if (eth_int_cause_ext & (BIT16 | BIT20)) { struct ethtool_cmd cmd; @@ -966,10 +936,10 @@ static int mv643xx_eth_open(struct net_device *dev) /* Unmask phy and link status changes interrupts */ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), - INT_UNMASK_ALL_EXT); + ETH_INT_UNMASK_ALL_EXT); /* Unmask RX buffer and TX end interrupt */ - mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL); + mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL); return 0; @@ -1049,7 +1019,7 @@ static int mv643xx_eth_stop(struct net_device *dev) unsigned int port_num = mp->port_num; /* Mask all interrupts on ethernet port */ - mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL); + mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL); /* wait for previous write to complete */ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num)); @@ -1110,7 +1080,7 @@ static int mv643xx_poll(struct net_device *dev, int *budget) mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0); mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0); mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), - INT_UNMASK_ALL); + ETH_INT_UNMASK_ALL); } return done ? 0 : 1; @@ -1325,13 +1295,13 @@ static void mv643xx_netpoll(struct net_device *netdev) struct mv643xx_private *mp = netdev_priv(netdev); int port_num = mp->port_num; - mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL); + mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL); /* wait for previous write to complete */ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num)); mv643xx_eth_int_handler(netdev->irq, netdev, NULL); - mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL); + mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL); } #endif diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index cade2705423c..2e59f193e267 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -74,21 +74,40 @@ #define MV643XX_RX_COAL 100 #endif -/* - * The second part is the low level driver of the gigE ethernet ports. - */ +#ifdef MV643XX_CHECKSUM_OFFLOAD_TX +#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1) +#else +#define MAX_DESCS_PER_SKB 1 +#endif -/* - * Header File for : MV-643xx network interface header - * - * DESCRIPTION: - * This header file contains macros typedefs and function declaration for - * the Marvell Gig Bit Ethernet Controller. - * - * DEPENDENCIES: - * None. - * - */ +#define ETH_VLAN_HLEN 4 +#define ETH_FCS_LEN 4 +#define ETH_DMA_ALIGN 8 /* hw requires 8-byte alignment */ +#define ETH_HW_IP_ALIGN 2 /* hw aligns IP header */ +#define ETH_WRAPPER_LEN (ETH_HW_IP_ALIGN + ETH_HLEN + \ + ETH_VLAN_HLEN + ETH_FCS_LEN) +#define ETH_RX_SKB_SIZE ((dev->mtu + ETH_WRAPPER_LEN + 7) & ~0x7) + +#define ETH_RX_QUEUES_ENABLED (1 << 0) /* use only Q0 for receive */ +#define ETH_TX_QUEUES_ENABLED (1 << 0) /* use only Q0 for transmit */ + +#define ETH_INT_CAUSE_RX_DONE (ETH_RX_QUEUES_ENABLED << 2) +#define ETH_INT_CAUSE_RX_ERROR (ETH_RX_QUEUES_ENABLED << 9) +#define ETH_INT_CAUSE_RX (ETH_INT_CAUSE_RX_DONE | ETH_INT_CAUSE_RX_ERROR) +#define ETH_INT_CAUSE_EXT 0x00000002 +#define ETH_INT_UNMASK_ALL (ETH_INT_CAUSE_RX | ETH_INT_CAUSE_EXT) + +#define ETH_INT_CAUSE_TX_DONE (ETH_TX_QUEUES_ENABLED << 0) +#define ETH_INT_CAUSE_TX_ERROR (ETH_TX_QUEUES_ENABLED << 8) +#define ETH_INT_CAUSE_TX (ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR) +#define ETH_INT_CAUSE_PHY 0x00010000 +#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY) + +#define ETH_INT_MASK_ALL 0x00000000 +#define ETH_INT_MASK_ALL_EXT 0x00000000 + +#define PHY_WAIT_ITERATIONS 1000 /* 1000 iterations * 10uS = 10mS max */ +#define PHY_WAIT_MICRO_SECONDS 10 /* Buffer offset from buffer pointer */ #define RX_BUF_OFFSET 0x2 -- cgit v1.2.3-59-g8ed1b From 468d09f8946d40228c56de26fe4874b2f98067ed Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 3 Mar 2006 10:04:39 -0700 Subject: [PATCH] mv643xx_eth: Clean up interrupt handling Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 75 ++++++++++++++++------------------------------- drivers/net/mv643xx_eth.h | 5 ---- 2 files changed, 25 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 50ee08518c6b..30b0d5b1b155 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -388,11 +388,7 @@ static void mv643xx_eth_free_all_tx_descs(struct net_device *dev) * * Output : number of served packets */ -#ifdef MV643XX_NAPI static int mv643xx_eth_receive_queue(struct net_device *dev, int budget) -#else -static int mv643xx_eth_receive_queue(struct net_device *dev) -#endif { struct mv643xx_private *mp = netdev_priv(dev); struct net_device_stats *stats = &mp->stats; @@ -400,15 +396,14 @@ static int mv643xx_eth_receive_queue(struct net_device *dev) struct sk_buff *skb; struct pkt_info pkt_info; -#ifdef MV643XX_NAPI while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) { -#else - while (eth_port_receive(mp, &pkt_info) == ETH_OK) { -#endif mp->rx_desc_count--; received_packets++; - /* Update statistics. Note byte count includes 4 byte CRC count */ + /* + * Update statistics. + * Note byte count includes 4 byte CRC count + */ stats->rx_packets++; stats->rx_bytes += pkt_info.byte_cnt; skb = pkt_info.return_info; @@ -532,48 +527,10 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, /* Read interrupt cause registers */ eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) & ETH_INT_UNMASK_ALL; - - if (eth_int_cause & BIT1) + if (eth_int_cause & ETH_INT_CAUSE_EXT) { eth_int_cause_ext = mv_read( MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) & ETH_INT_UNMASK_ALL_EXT; - -#ifdef MV643XX_NAPI - if (!(eth_int_cause & 0x0007fffd)) { - /* Dont ack the Rx interrupt */ -#endif - /* - * Clear specific ethernet port intrerrupt registers by - * acknowleding relevant bits. - */ - mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), - ~eth_int_cause); - if (eth_int_cause_ext != 0x0) { - mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG - (port_num), ~eth_int_cause_ext); - /* UDP change : We may need this */ - if (eth_int_cause_ext & (BIT0 | BIT8)) - mv643xx_eth_free_completed_tx_descs(dev); - } -#ifdef MV643XX_NAPI - } else { - if (netif_rx_schedule_prep(dev)) { - /* Mask all the interrupts */ - mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), - ETH_INT_MASK_ALL); - /* wait for previous write to complete */ - mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num)); - __netif_rx_schedule(dev); - } -#else - if (eth_int_cause & (BIT2 | BIT11)) - mv643xx_eth_receive_queue(dev, 0); - - /* - * After forwarded received packets to upper layer, add a task - * in an interrupts enabled context that refills the RX ring - * with skb's. - */ #ifdef MV643XX_RX_QUEUE_FILL_ON_TASK /* Mask all interrupts on ethernet port */ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), @@ -586,11 +543,12 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, #else mp->rx_task.func(dev); #endif -#endif + mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), + ~eth_int_cause_ext); } /* PHY status changed */ - if (eth_int_cause_ext & (BIT16 | BIT20)) { + if (eth_int_cause_ext & ETH_INT_CAUSE_PHY) { struct ethtool_cmd cmd; if (mii_link_ok(&mp->mii)) { @@ -610,6 +568,23 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, } } +#ifdef MV643XX_NAPI + if (eth_int_cause & ETH_INT_CAUSE_RX) { + /* schedule the NAPI poll routine to maintain port */ + mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), + ETH_INT_MASK_ALL); + /* wait for previous write to complete */ + mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num)); + + netif_rx_schedule(dev); + } +#else + if (eth_int_cause & ETH_INT_CAUSE_RX) + mv643xx_eth_receive_queue(dev, INT_MAX); + if (eth_int_cause_ext & ETH_INT_CAUSE_TX) + mv643xx_eth_free_completed_tx_descs(dev); +#endif + /* * If no real interrupt occured, exit. * This can happen when using gigE interrupt coalescing mechanism. diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index 2e59f193e267..df2c76154205 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -372,9 +372,6 @@ struct mv643xx_private { struct work_struct tx_timeout_task; - /* - * Former struct mv643xx_eth_priv members start here - */ struct net_device_stats stats; struct mv643xx_mib_counters mib_counters; spinlock_t lock; @@ -405,8 +402,6 @@ struct mv643xx_private { struct mii_if_info mii; }; -/* ethernet.h API list */ - /* Port operation control routines */ static void eth_port_init(struct mv643xx_private *mp); static void eth_port_reset(unsigned int eth_port_num); -- cgit v1.2.3-59-g8ed1b From f78fb4743dc06719084239c29dc178ad38ad2e2f Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 3 Mar 2006 10:05:26 -0700 Subject: [PATCH] mv643xx_eth: Remove non-working feature: task level rx queue refill The task level rx queue refill feature hasn't ever worked (at least in 2.6) and is of dubious value. Remove it. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 59 ++++++++++------------------------------------- drivers/net/mv643xx_eth.h | 8 ------- 2 files changed, 12 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 30b0d5b1b155..9f2661355a4a 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -132,25 +132,21 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu) } /* - * mv643xx_eth_rx_task + * mv643xx_eth_rx_refill_descs * * Fills / refills RX queue on a certain gigabit ethernet port * * Input : pointer to ethernet interface network device structure * Output : N/A */ -static void mv643xx_eth_rx_task(void *data) +static void mv643xx_eth_rx_refill_descs(struct net_device *dev) { - struct net_device *dev = (struct net_device *)data; struct mv643xx_private *mp = netdev_priv(dev); struct pkt_info pkt_info; struct sk_buff *skb; int unaligned; - if (test_and_set_bit(0, &mp->rx_task_busy)) - panic("%s: Error in test_set_bit / clear_bit", dev->name); - - while (mp->rx_desc_count < (mp->rx_ring_size - 5)) { + while (mp->rx_desc_count < mp->rx_ring_size) { skb = dev_alloc_skb(ETH_RX_SKB_SIZE + ETH_DMA_ALIGN); if (!skb) break; @@ -170,29 +166,19 @@ static void mv643xx_eth_rx_task(void *data) } skb_reserve(skb, ETH_HW_IP_ALIGN); } - clear_bit(0, &mp->rx_task_busy); /* * If RX ring is empty of SKB, set a timer to try allocating - * again in a later time . + * again at a later time. */ - if ((mp->rx_desc_count == 0) && (mp->rx_timer_flag == 0)) { + if (mp->rx_desc_count == 0) { printk(KERN_INFO "%s: Rx ring is empty\n", dev->name); - /* After 100mSec */ - mp->timeout.expires = jiffies + (HZ / 10); + mp->timeout.expires = jiffies + (HZ / 10); /* 100 mSec */ add_timer(&mp->timeout); - mp->rx_timer_flag = 1; - } -#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK - else { - /* Return interrupts */ - mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(mp->port_num), - INT_UNMASK_ALL); } -#endif } /* - * mv643xx_eth_rx_task_timer_wrapper + * mv643xx_eth_rx_refill_descs_timer_wrapper * * Timer routine to wake up RX queue filling task. This function is * used only in case the RX queue is empty, and all alloc_skb has @@ -201,13 +187,9 @@ static void mv643xx_eth_rx_task(void *data) * Input : pointer to ethernet interface network device structure * Output : N/A */ -static void mv643xx_eth_rx_task_timer_wrapper(unsigned long data) +static inline void mv643xx_eth_rx_refill_descs_timer_wrapper(unsigned long data) { - struct net_device *dev = (struct net_device *)data; - struct mv643xx_private *mp = netdev_priv(dev); - - mp->rx_timer_flag = 0; - mv643xx_eth_rx_task((void *)data); + mv643xx_eth_rx_refill_descs((struct net_device *)data); } /* @@ -451,6 +433,7 @@ static int mv643xx_eth_receive_queue(struct net_device *dev, int budget) } dev->last_rx = jiffies; } + mv643xx_eth_rx_refill_descs(dev); /* Fill RX ring with skb's */ return received_packets; } @@ -531,18 +514,6 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, eth_int_cause_ext = mv_read( MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) & ETH_INT_UNMASK_ALL_EXT; -#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK - /* Mask all interrupts on ethernet port */ - mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), - INT_MASK_ALL); - /* wait for previous write to take effect */ - mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num)); - - queue_task(&mp->rx_task, &tq_immediate); - mark_bh(IMMEDIATE_BH); -#else - mp->rx_task.func(dev); -#endif mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), ~eth_int_cause_ext); } @@ -810,15 +781,10 @@ static int mv643xx_eth_open(struct net_device *dev) eth_port_init(mp); - INIT_WORK(&mp->rx_task, (void (*)(void *))mv643xx_eth_rx_task, dev); - memset(&mp->timeout, 0, sizeof(struct timer_list)); - mp->timeout.function = mv643xx_eth_rx_task_timer_wrapper; + mp->timeout.function = mv643xx_eth_rx_refill_descs_timer_wrapper; mp->timeout.data = (unsigned long)dev; - mp->rx_task_busy = 0; - mp->rx_timer_flag = 0; - /* Allocate RX and TX skb rings */ mp->rx_skb = kmalloc(sizeof(*mp->rx_skb) * mp->rx_ring_size, GFP_KERNEL); @@ -891,7 +857,7 @@ static int mv643xx_eth_open(struct net_device *dev) ether_init_rx_desc_ring(mp); - mv643xx_eth_rx_task(dev); /* Fill RX ring with skb's */ + mv643xx_eth_rx_refill_descs(dev); /* Fill RX ring with skb's */ /* Clear any pending ethernet port interrupts */ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0); @@ -1043,7 +1009,6 @@ static int mv643xx_poll(struct net_device *dev, int *budget) if (orig_budget > dev->quota) orig_budget = dev->quota; work_done = mv643xx_eth_receive_queue(dev, orig_budget); - mp->rx_task.func(dev); *budget -= work_done; dev->quota -= work_done; if (work_done >= orig_budget) diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index df2c76154205..f8742e1edea2 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -52,7 +52,6 @@ #define MV643XX_CHECKSUM_OFFLOAD_TX #define MV643XX_NAPI #define MV643XX_TX_FAST_REFILL -#undef MV643XX_RX_QUEUE_FILL_ON_TASK /* Does not work, yet */ #undef MV643XX_COAL /* @@ -384,18 +383,11 @@ struct mv643xx_private { /* Number of rx descriptors in use */ int rx_desc_count; - /* - * rx_task used to fill RX ring out of bottom half context - */ - struct work_struct rx_task; - /* * Used in case RX Ring is empty, which can be caused when * system does not have resources (skb's) */ struct timer_list timeout; - long rx_task_busy __attribute__ ((aligned(SMP_CACHE_BYTES))); - unsigned rx_timer_flag; u32 rx_int_coal; u32 tx_int_coal; -- cgit v1.2.3-59-g8ed1b From ebe19a4ed78d4a11a7e01cdeda25f91b7f2fcb5a Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Fri, 3 Mar 2006 10:06:20 -0700 Subject: [PATCH] mv643xx_eth: Remove BIT0-BIT31 #defines Now that the BIT0-BIT31 defines are no longer used by mv643xx_eth.c, remove them from mv643xx_eth.h. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.h | 152 +++++++++++++++------------------------------- 1 file changed, 49 insertions(+), 103 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index f8742e1edea2..7754d1974b9e 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -9,43 +9,6 @@ #include -#define BIT0 0x00000001 -#define BIT1 0x00000002 -#define BIT2 0x00000004 -#define BIT3 0x00000008 -#define BIT4 0x00000010 -#define BIT5 0x00000020 -#define BIT6 0x00000040 -#define BIT7 0x00000080 -#define BIT8 0x00000100 -#define BIT9 0x00000200 -#define BIT10 0x00000400 -#define BIT11 0x00000800 -#define BIT12 0x00001000 -#define BIT13 0x00002000 -#define BIT14 0x00004000 -#define BIT15 0x00008000 -#define BIT16 0x00010000 -#define BIT17 0x00020000 -#define BIT18 0x00040000 -#define BIT19 0x00080000 -#define BIT20 0x00100000 -#define BIT21 0x00200000 -#define BIT22 0x00400000 -#define BIT23 0x00800000 -#define BIT24 0x01000000 -#define BIT25 0x02000000 -#define BIT26 0x04000000 -#define BIT27 0x08000000 -#define BIT28 0x10000000 -#define BIT29 0x20000000 -#define BIT30 0x40000000 -#define BIT31 0x80000000 - -/* - * The first part is the high level driver of the gigE ethernet ports. - */ - /* Checksum offload for Tx works for most packets, but * fails if previous packet sent did not use hw csum */ @@ -148,88 +111,71 @@ #define ETH_MIB_LATE_COLLISION 0x7c /* Port serial status reg (PSR) */ -#define ETH_INTERFACE_GMII_MII 0 -#define ETH_INTERFACE_PCM BIT0 -#define ETH_LINK_IS_DOWN 0 -#define ETH_LINK_IS_UP BIT1 -#define ETH_PORT_AT_HALF_DUPLEX 0 -#define ETH_PORT_AT_FULL_DUPLEX BIT2 -#define ETH_RX_FLOW_CTRL_DISABLED 0 -#define ETH_RX_FLOW_CTRL_ENBALED BIT3 -#define ETH_GMII_SPEED_100_10 0 -#define ETH_GMII_SPEED_1000 BIT4 -#define ETH_MII_SPEED_10 0 -#define ETH_MII_SPEED_100 BIT5 -#define ETH_NO_TX 0 -#define ETH_TX_IN_PROGRESS BIT7 -#define ETH_BYPASS_NO_ACTIVE 0 -#define ETH_BYPASS_ACTIVE BIT8 -#define ETH_PORT_NOT_AT_PARTITION_STATE 0 -#define ETH_PORT_AT_PARTITION_STATE BIT9 -#define ETH_PORT_TX_FIFO_NOT_EMPTY 0 -#define ETH_PORT_TX_FIFO_EMPTY BIT10 - -#define ETH_DEFAULT_RX_BPDU_QUEUE_3 (BIT23 | BIT22) -#define ETH_DEFAULT_RX_BPDU_QUEUE_4 BIT24 -#define ETH_DEFAULT_RX_BPDU_QUEUE_5 (BIT24 | BIT22) -#define ETH_DEFAULT_RX_BPDU_QUEUE_6 (BIT24 | BIT23) -#define ETH_DEFAULT_RX_BPDU_QUEUE_7 (BIT24 | BIT23 | BIT22) +#define ETH_INTERFACE_PCM 0x00000001 +#define ETH_LINK_IS_UP 0x00000002 +#define ETH_PORT_AT_FULL_DUPLEX 0x00000004 +#define ETH_RX_FLOW_CTRL_ENABLED 0x00000008 +#define ETH_GMII_SPEED_1000 0x00000010 +#define ETH_MII_SPEED_100 0x00000020 +#define ETH_TX_IN_PROGRESS 0x00000080 +#define ETH_BYPASS_ACTIVE 0x00000100 +#define ETH_PORT_AT_PARTITION_STATE 0x00000200 +#define ETH_PORT_TX_FIFO_EMPTY 0x00000400 /* SMI reg */ -#define ETH_SMI_BUSY BIT28 /* 0 - Write, 1 - Read */ -#define ETH_SMI_READ_VALID BIT27 /* 0 - Write, 1 - Read */ -#define ETH_SMI_OPCODE_WRITE 0 /* Completion of Read operation */ -#define ETH_SMI_OPCODE_READ BIT26 /* Operation is in progress */ +#define ETH_SMI_BUSY 0x10000000 /* 0 - Write, 1 - Read */ +#define ETH_SMI_READ_VALID 0x08000000 /* 0 - Write, 1 - Read */ +#define ETH_SMI_OPCODE_WRITE 0 /* Completion of Read */ +#define ETH_SMI_OPCODE_READ 0x04000000 /* Operation is in progress */ + +/* Interrupt Cause Register Bit Definitions */ /* SDMA command status fields macros */ /* Tx & Rx descriptors status */ -#define ETH_ERROR_SUMMARY (BIT0) +#define ETH_ERROR_SUMMARY 0x00000001 /* Tx & Rx descriptors command */ -#define ETH_BUFFER_OWNED_BY_DMA (BIT31) +#define ETH_BUFFER_OWNED_BY_DMA 0x80000000 /* Tx descriptors status */ -#define ETH_LC_ERROR (0 ) -#define ETH_UR_ERROR (BIT1 ) -#define ETH_RL_ERROR (BIT2 ) -#define ETH_LLC_SNAP_FORMAT (BIT9 ) +#define ETH_LC_ERROR 0 +#define ETH_UR_ERROR 0x00000002 +#define ETH_RL_ERROR 0x00000004 +#define ETH_LLC_SNAP_FORMAT 0x00000200 /* Rx descriptors status */ -#define ETH_CRC_ERROR (0 ) -#define ETH_OVERRUN_ERROR (BIT1 ) -#define ETH_MAX_FRAME_LENGTH_ERROR (BIT2 ) -#define ETH_RESOURCE_ERROR ((BIT2 | BIT1)) -#define ETH_VLAN_TAGGED (BIT19) -#define ETH_BPDU_FRAME (BIT20) -#define ETH_TCP_FRAME_OVER_IP_V_4 (0 ) -#define ETH_UDP_FRAME_OVER_IP_V_4 (BIT21) -#define ETH_OTHER_FRAME_TYPE (BIT22) -#define ETH_LAYER_2_IS_ETH_V_2 (BIT23) -#define ETH_FRAME_TYPE_IP_V_4 (BIT24) -#define ETH_FRAME_HEADER_OK (BIT25) -#define ETH_RX_LAST_DESC (BIT26) -#define ETH_RX_FIRST_DESC (BIT27) -#define ETH_UNKNOWN_DESTINATION_ADDR (BIT28) -#define ETH_RX_ENABLE_INTERRUPT (BIT29) -#define ETH_LAYER_4_CHECKSUM_OK (BIT30) +#define ETH_OVERRUN_ERROR 0x00000002 +#define ETH_MAX_FRAME_LENGTH_ERROR 0x00000004 +#define ETH_RESOURCE_ERROR 0x00000006 +#define ETH_VLAN_TAGGED 0x00080000 +#define ETH_BPDU_FRAME 0x00100000 +#define ETH_UDP_FRAME_OVER_IP_V_4 0x00200000 +#define ETH_OTHER_FRAME_TYPE 0x00400000 +#define ETH_LAYER_2_IS_ETH_V_2 0x00800000 +#define ETH_FRAME_TYPE_IP_V_4 0x01000000 +#define ETH_FRAME_HEADER_OK 0x02000000 +#define ETH_RX_LAST_DESC 0x04000000 +#define ETH_RX_FIRST_DESC 0x08000000 +#define ETH_UNKNOWN_DESTINATION_ADDR 0x10000000 +#define ETH_RX_ENABLE_INTERRUPT 0x20000000 +#define ETH_LAYER_4_CHECKSUM_OK 0x40000000 /* Rx descriptors byte count */ -#define ETH_FRAME_FRAGMENTED (BIT2) +#define ETH_FRAME_FRAGMENTED 0x00000004 /* Tx descriptors command */ -#define ETH_LAYER_4_CHECKSUM_FIRST_DESC (BIT10) -#define ETH_FRAME_SET_TO_VLAN (BIT15) -#define ETH_TCP_FRAME (0 ) -#define ETH_UDP_FRAME (BIT16) -#define ETH_GEN_TCP_UDP_CHECKSUM (BIT17) -#define ETH_GEN_IP_V_4_CHECKSUM (BIT18) -#define ETH_ZERO_PADDING (BIT19) -#define ETH_TX_LAST_DESC (BIT20) -#define ETH_TX_FIRST_DESC (BIT21) -#define ETH_GEN_CRC (BIT22) -#define ETH_TX_ENABLE_INTERRUPT (BIT23) -#define ETH_AUTO_MODE (BIT30) +#define ETH_LAYER_4_CHECKSUM_FIRST_DESC 0x00000400 +#define ETH_FRAME_SET_TO_VLAN 0x00008000 +#define ETH_UDP_FRAME 0x00010000 +#define ETH_GEN_TCP_UDP_CHECKSUM 0x00020000 +#define ETH_GEN_IP_V_4_CHECKSUM 0x00040000 +#define ETH_ZERO_PADDING 0x00080000 +#define ETH_TX_LAST_DESC 0x00100000 +#define ETH_TX_FIRST_DESC 0x00200000 +#define ETH_GEN_CRC 0x00400000 +#define ETH_TX_ENABLE_INTERRUPT 0x00800000 +#define ETH_AUTO_MODE 0x40000000 #define ETH_TX_IHL_SHIFT 11 -- cgit v1.2.3-59-g8ed1b From 1d076e5b8d91babc018ffaefafd4f85a53c9a1b1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 01:25:39 +0900 Subject: [PATCH] ata_piix: finer-grained port_info Make port_info finer-grained. This patch doesn't cause any functional change. Later init reimplementation will make use of it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 77 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index c662bf531514..5988d5fe1e18 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -119,11 +119,14 @@ enum { PIIX_80C_PRI = (1 << 5) | (1 << 4), PIIX_80C_SEC = (1 << 7) | (1 << 6), - ich5_pata = 0, - ich5_sata = 1, - piix4_pata = 2, - ich6_sata = 3, - ich6_sata_ahci = 4, + /* controller IDs */ + piix4_pata = 0, + ich5_pata = 1, + ich5_sata = 2, + esb_sata = 3, + ich6_sata = 4, + ich6_sata_ahci = 5, + ich6m_sata_ahci = 6, PIIX_AHCI_DEVICE = 6, }; @@ -149,19 +152,32 @@ static const struct pci_device_id piix_pci_tbl[] = { * list in drivers/pci/quirks.c. */ + /* 82801EB (ICH5) */ { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + /* 82801EB (ICH5) */ { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, - { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, - { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + /* 6300ESB (ICH5 variant with broken PCS present bits) */ + { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata }, + /* 6300ESB pretending RAID */ + { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata }, + /* 82801FB/FW (ICH6/ICH6W) */ { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, + /* 82801FR/FRW (ICH6R/ICH6RW) */ { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, - { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, + /* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented) */ + { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci }, + /* 82801GB/GR/GH (ICH7, identical to ICH6) */ { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, - { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, + /* 2801GBM/GHM (ICH7M, identical to ICH6M) */ + { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci }, + /* Enterprise Southbridge 2 (where's the datasheet?) */ { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, + /* SATA Controller 1 IDE (ICH8, no datasheet yet) */ { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, + /* SATA Controller 2 IDE (ICH8, ditto) */ { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, - { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, + /* Mobile SATA Controller IDE (ICH8M, ditto) */ + { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci }, { } /* terminate list */ }; @@ -255,6 +271,20 @@ static const struct ata_port_operations piix_sata_ops = { }; static struct ata_port_info piix_port_info[] = { + /* piix4_pata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = 0x1f, /* pio0-4 */ +#if 0 + .mwdma_mask = 0x06, /* mwdma1-2 */ +#else + .mwdma_mask = 0x00, /* mwdma broken */ +#endif + .udma_mask = ATA_UDMA_MASK_40C, + .port_ops = &piix_pata_ops, + }, + /* ich5_pata */ { .sht = &piix_sht, @@ -280,18 +310,15 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* piix4_pata */ + /* i6300esb_sata */ { .sht = &piix_sht, - .host_flags = ATA_FLAG_SLAVE_POSS, + .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED | + PIIX_FLAG_CHECKINTR, .pio_mask = 0x1f, /* pio0-4 */ -#if 0 - .mwdma_mask = 0x06, /* mwdma1-2 */ -#else - .mwdma_mask = 0x00, /* mwdma broken */ -#endif - .udma_mask = ATA_UDMA_MASK_40C, - .port_ops = &piix_pata_ops, + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &piix_sata_ops, }, /* ich6_sata */ @@ -316,6 +343,18 @@ static struct ata_port_info piix_port_info[] = { .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, + + /* ich6m_sata_ahci */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | + PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | + PIIX_FLAG_AHCI, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &piix_sata_ops, + }, }; static struct pci_bits piix_enable_bits[] = { -- cgit v1.2.3-59-g8ed1b From d435804803befedbda9fdc1be088e7930b60982b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 01:25:39 +0900 Subject: [PATCH] ata_piix: add a couple of flags Add PIIX_FLAG_IGN_PRESENT and SCR flags. Thi patch doesn't cause any functional change. To be used by later init/scr updates. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 5988d5fe1e18..987a7ccac917 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -101,6 +101,8 @@ enum { ICH5_PCS = 0x92, /* port control and status */ PIIX_SCC = 0x0A, /* sub-class code register */ + PIIX_FLAG_IGN_PRESENT = (1 << 25), /* ignore PCS present bits */ + PIIX_FLAG_SCR = (1 << 26), /* SCR available */ PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ PIIX_FLAG_COMBINED = (1 << 29), /* combined mode possible */ @@ -314,7 +316,7 @@ static struct ata_port_info piix_port_info[] = { { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED | - PIIX_FLAG_CHECKINTR, + PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGN_PRESENT, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -325,7 +327,8 @@ static struct ata_port_info piix_port_info[] = { { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | - PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS, + PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | + PIIX_FLAG_SCR, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -337,7 +340,7 @@ static struct ata_port_info piix_port_info[] = { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | - PIIX_FLAG_AHCI, + PIIX_FLAG_SCR | PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -349,7 +352,7 @@ static struct ata_port_info piix_port_info[] = { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | - PIIX_FLAG_AHCI, + PIIX_FLAG_SCR | PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ -- cgit v1.2.3-59-g8ed1b From d33f58b883a3f624b9362227bf73fc52a6cbd4b4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 01:25:39 +0900 Subject: [PATCH] ata_piix: implement proper port map Replace combined mode handling via PIIX_COMB/COMB_PATA_P0 with proper port map. PIIX now prints port configuration during initialization. ATA_FLAG_SLAVE_POSS is now turned on for SATA ports only when the slave device is actually avaliable. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 182 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 122 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 987a7ccac917..4080b8be847b 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -112,9 +112,6 @@ enum { /* combined mode. if set, PATA is channel 0. * if clear, PATA is channel 1. */ - PIIX_COMB_PATA_P0 = (1 << 1), - PIIX_COMB = (1 << 2), /* combined mode enabled? */ - PIIX_PORT_ENABLED = (1 << 0), PIIX_PORT_PRESENT = (1 << 4), @@ -130,9 +127,23 @@ enum { ich6_sata_ahci = 5, ich6m_sata_ahci = 6, + /* constants for mapping table */ + P0 = 0, /* port 0 */ + P1 = 1, /* port 1 */ + P2 = 2, /* port 2 */ + P3 = 3, /* port 3 */ + IDE = -1, /* IDE */ + NA = -2, /* not avaliable */ + RV = -3, /* reserved */ + PIIX_AHCI_DEVICE = 6, }; +struct piix_map_db { + const u32 mask; + const int map[][4]; +}; + static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); @@ -272,6 +283,43 @@ static const struct ata_port_operations piix_sata_ops = { .host_stop = ata_host_stop, }; +static struct piix_map_db ich5_map_db = { + .mask = 0x7, + .map = { + /* PM PS SM SS MAP */ + { P0, NA, P1, NA }, /* 000b */ + { P1, NA, P0, NA }, /* 001b */ + { RV, RV, RV, RV }, + { RV, RV, RV, RV }, + { P0, P1, IDE, IDE }, /* 100b */ + { P1, P0, IDE, IDE }, /* 101b */ + { IDE, IDE, P0, P1 }, /* 110b */ + { IDE, IDE, P1, P0 }, /* 111b */ + }, +}; + +static struct piix_map_db ich6_map_db = { + .mask = 0x3, + .map = { + /* PM PS SM SS MAP */ + { P0, P1, P2, P3 }, /* 00b */ + { IDE, IDE, P1, P3 }, /* 01b */ + { P0, P2, IDE, IDE }, /* 10b */ + { RV, RV, RV, RV }, + }, +}; + +static struct piix_map_db ich6m_map_db = { + .mask = 0x3, + .map = { + /* PM PS SM SS MAP */ + { P0, P1, P2, P3 }, /* 00b */ + { RV, RV, RV, RV }, + { P0, P2, IDE, IDE }, /* 10b */ + { RV, RV, RV, RV }, + }, +}; + static struct ata_port_info piix_port_info[] = { /* piix4_pata */ { @@ -310,6 +358,7 @@ static struct ata_port_info piix_port_info[] = { .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, + .private_data = &ich5_map_db, }, /* i6300esb_sata */ @@ -321,42 +370,45 @@ static struct ata_port_info piix_port_info[] = { .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, + .private_data = &ich5_map_db, }, /* ich6_sata */ { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | - PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | - PIIX_FLAG_SCR, + PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, + .private_data = &ich6_map_db, }, /* ich6_sata_ahci */ { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | - PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | - PIIX_FLAG_SCR | PIIX_FLAG_AHCI, + PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | + PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, + .private_data = &ich6_map_db, }, /* ich6m_sata_ahci */ { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | - PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | - PIIX_FLAG_SCR | PIIX_FLAG_AHCI, + PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | + PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, + .private_data = &ich6m_map_db, }, }; @@ -708,6 +760,54 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) return no_piix_dma; } +static void __devinit piix_init_sata_map(struct pci_dev *pdev, + struct ata_port_info *pinfo) +{ + struct piix_map_db *map_db = pinfo[0].private_data; + const unsigned int *map; + int i, invalid_map = 0; + u8 map_value; + + pci_read_config_byte(pdev, ICH5_PMR, &map_value); + + map = map_db->map[map_value & map_db->mask]; + + dev_printk(KERN_INFO, &pdev->dev, "MAP ["); + for (i = 0; i < 4; i++) { + switch (map[i]) { + case RV: + invalid_map = 1; + printk(" XX"); + break; + + case NA: + printk(" --"); + break; + + case IDE: + WARN_ON((i & 1) || map[i + 1] != IDE); + pinfo[i / 2] = piix_port_info[ich5_pata]; + i++; + printk(" IDE IDE"); + break; + + default: + printk(" P%d", map[i]); + if (i & 1) + pinfo[i / 2].host_flags |= ATA_FLAG_SLAVE_POSS; + break; + } + } + printk(" ]\n"); + + if (invalid_map) + dev_printk(KERN_ERR, &pdev->dev, + "invalid MAP value %u\n", map_value); + + pinfo[0].private_data = (void *)map; + pinfo[1].private_data = (void *)map; +} + /** * piix_init_one - Register PIIX ATA PCI device with kernel services * @pdev: PCI device to register @@ -726,9 +826,8 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - struct ata_port_info *port_info[2]; - unsigned int combined = 0; - unsigned int pata_chan = 0, sata_chan = 0; + struct ata_port_info port_info[2]; + struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] }; unsigned long host_flags; if (!printed_version++) @@ -739,10 +838,10 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (!in_module_init) return -ENODEV; - port_info[0] = &piix_port_info[ent->driver_data]; - port_info[1] = &piix_port_info[ent->driver_data]; + port_info[0] = piix_port_info[ent->driver_data]; + port_info[1] = piix_port_info[ent->driver_data]; - host_flags = port_info[0]->host_flags; + host_flags = port_info[0].host_flags; if (host_flags & PIIX_FLAG_AHCI) { u8 tmp; @@ -754,37 +853,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) } } - if (host_flags & PIIX_FLAG_COMBINED) { - u8 tmp; - pci_read_config_byte(pdev, ICH5_PMR, &tmp); - - if (host_flags & PIIX_FLAG_COMBINED_ICH6) { - switch (tmp & 0x3) { - case 0: - break; - case 1: - combined = 1; - sata_chan = 1; - break; - case 2: - combined = 1; - pata_chan = 1; - break; - case 3: - dev_printk(KERN_WARNING, &pdev->dev, - "invalid MAP value %u\n", tmp); - break; - } - } else { - if (tmp & PIIX_COMB) { - combined = 1; - if (tmp & PIIX_COMB_PATA_P0) - sata_chan = 1; - else - pata_chan = 1; - } - } - } + /* Initialize SATA map */ + if (host_flags & ATA_FLAG_SATA) + piix_init_sata_map(pdev, port_info); /* On ICH5, some BIOSen disable the interrupt using the * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. @@ -795,25 +866,16 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (host_flags & PIIX_FLAG_CHECKINTR) pci_intx(pdev, 1); - if (combined) { - port_info[sata_chan] = &piix_port_info[ent->driver_data]; - port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS; - port_info[pata_chan] = &piix_port_info[ich5_pata]; - - dev_printk(KERN_WARNING, &pdev->dev, - "combined mode detected (p=%u, s=%u)\n", - pata_chan, sata_chan); - } if (piix_check_450nx_errata(pdev)) { /* This writes into the master table but it does not really matter for this errata as we will apply it to all the PIIX devices on the board */ - port_info[0]->mwdma_mask = 0; - port_info[0]->udma_mask = 0; - port_info[1]->mwdma_mask = 0; - port_info[1]->udma_mask = 0; + port_info[0].mwdma_mask = 0; + port_info[0].udma_mask = 0; + port_info[1].mwdma_mask = 0; + port_info[1].udma_mask = 0; } - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppinfo, 2); } static int __init piix_init(void) -- cgit v1.2.3-59-g8ed1b From d133ecab8ff1233c2eb3ecb94f7956aa10002300 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 01:25:39 +0900 Subject: [PATCH] ata_piix: reimplement piix_sata_probe() Reimplement piix_sata_probe() such that it turns on PCS enable bits on all avaliable ports and check present bits after a while to determine device presence. This should help broken BIOSes. After device presence detection is complete, PCS enable bits of unoccupied bits are turned off unless the controller supports AHCI (ICH6/7 docs mandate all enables bits are always set on AHCI capable controllers). Note that PCS present bits are ignored on 6300ESB as described in the datasheet. This should fix device detection problems reported with the controller. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 61 ++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 4080b8be847b..72e38e6ea756 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -499,44 +499,59 @@ static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes) * piix_sata_probe - Probe PCI device for present SATA devices * @ap: Port associated with the PCI device we wish to probe * - * Reads SATA PCI device's PCI config register Port Configuration - * and Status (PCS) to determine port and device availability. + * Reads and configures SATA PCI device's PCI config register + * Port Configuration and Status (PCS) to determine port and + * device availability. * * LOCKING: * None (inherited from caller). * * RETURNS: - * Non-zero if port is enabled, it may or may not have a device - * attached in that case (PRESENT bit would only be set if BIOS probe - * was done). Zero is returned if port is disabled. + * Mask of avaliable devices on the port. */ -static int piix_sata_probe (struct ata_port *ap) +static unsigned int piix_sata_probe (struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); - int combined = (ap->flags & ATA_FLAG_SLAVE_POSS); - int orig_mask, mask, i; + const unsigned int *map = ap->host_set->private_data; + int base = 2 * ap->hard_port_no; + unsigned int present_mask = 0; + int port, i; u8 pcs; pci_read_config_byte(pdev, ICH5_PCS, &pcs); - orig_mask = (int) pcs & 0xff; - - /* TODO: this is vaguely wrong for ICH6 combined mode, - * where only two of the four SATA ports are mapped - * onto a single ATA channel. It is also vaguely inaccurate - * for ICH5, which has only two ports. However, this is ok, - * as further device presence detection code will handle - * any false positives produced here. - */ + DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base); - for (i = 0; i < 4; i++) { - mask = (PIIX_PORT_ENABLED << i); + /* enable all ports on this ap and wait for them to settle */ + for (i = 0; i < 2; i++) { + port = map[base + i]; + if (port >= 0) + pcs |= 1 << port; + } - if ((orig_mask & mask) == mask) - if (combined || (i == ap->hard_port_no)) - return 1; + pci_write_config_byte(pdev, ICH5_PCS, pcs); + msleep(100); + + /* let's see which devices are present */ + pci_read_config_byte(pdev, ICH5_PCS, &pcs); + + for (i = 0; i < 2; i++) { + port = map[base + i]; + if (port < 0) + continue; + if (ap->flags & PIIX_FLAG_IGN_PRESENT || pcs & 1 << (4 + port)) + present_mask |= 1 << i; + else + pcs &= ~(1 << port); } - return 0; + /* disable offline ports on non-AHCI controllers */ + if (!(ap->flags & PIIX_FLAG_AHCI)) + pci_write_config_byte(pdev, ICH5_PCS, pcs); + + DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", + ap->id, pcs, present_mask); + + return present_mask; } /** -- cgit v1.2.3-59-g8ed1b From d9572b1d5e60b63e27e17f1f7771c5a26dd5d81e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 16:09:35 +0900 Subject: [PATCH] libata: convert dev->id to pointer Convert dev->id from array to pointer. This is to accomodate revalidation. During revalidation, both old and new IDENTIFY pages should be accessible and single ->id array doesn't cut it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 20 +++++++++++++++++--- include/linux/libata.h | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index e34b421eb2a3..fecda706d85f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -911,7 +911,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? - * @id: buffer to fill IDENTIFY page into + * @p_id: read IDENTIFY page (newly allocated) * * Read ID data from the specified device. ATA_CMD_ID_ATA is * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI @@ -926,12 +926,13 @@ 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 *id) + unsigned int *p_class, int post_reset, u16 **p_id) { unsigned int class = *p_class; unsigned int using_edd; struct ata_taskfile tf; unsigned int err_mask = 0; + u16 *id; const char *reason; int rc; @@ -945,6 +946,13 @@ 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); @@ -1035,11 +1043,13 @@ 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; } @@ -1079,7 +1089,8 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) DPRINTK("ENTER, host %u, dev %u\n", ap->id, device); - rc = ata_dev_read_id(ap, dev, &dev->class, 1, dev->id); + WARN_ON(dev->id != NULL); + rc = ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id); if (rc) goto err_out; @@ -4732,11 +4743,14 @@ 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]; + 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 22e86cb2d166..9f273dd1958c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -339,7 +339,7 @@ struct ata_device { unsigned long flags; /* ATA_DFLAG_xxx */ unsigned int class; /* ATA_DEV_xxx */ unsigned int devno; /* 0 or 1 */ - u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ + u16 *id; /* IDENTIFY xxx DEVICE data */ u8 pio_mode; u8 dma_mode; u8 xfer_mode; -- cgit v1.2.3-59-g8ed1b From ffeae418c12a304f6a9b6468043954d4e67a2b1e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 16:09:35 +0900 Subject: [PATCH] libata: separate out ata_dev_configure() Separate out ata_dev_configure() from ata_dev_identify() such that ata_dev_configure() only configures @dev according to passed in @id. The function now does not disable device on failure, it just returns appropirate error code. As this change leaves ata_dev_identify() with only reading ID, calling configure and disabling devices according to the results, this patch also kills ata_dev_identify() and inlines the logic into ata_bus_probe(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 80 +++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index fecda706d85f..ba26c66cc11b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1054,45 +1054,31 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, } /** - * ata_dev_identify - obtain IDENTIFY x DEVICE page - * @ap: port on which device we wish to probe resides - * @device: device bus address, starting at zero - * - * Following bus reset, we issue the IDENTIFY [PACKET] DEVICE - * command, and read back the 512-byte device information page. - * The device information page is fed to us via the standard - * PIO-IN protocol, but we hand-code it here. (TODO: investigate - * using standard PIO-IN paths) - * - * After reading the device information page, we use several - * bits of information from it to initialize data structures - * that will be used during the lifetime of the ata_device. - * Other data from the info page is used to disqualify certain - * older ATA devices we do not wish to support. + * ata_dev_configure - Configure the specified ATA/ATAPI device + * @ap: Port on which target device resides + * @dev: Target device to configure + * + * Configure @dev according to @dev->id. Generic and low-level + * driver specific fixups are also applied. * * LOCKING: - * Inherited from caller. Some functions called by this function - * obtain the host_set lock. + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise */ - -static void ata_dev_identify(struct ata_port *ap, unsigned int device) +static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev) { - struct ata_device *dev = &ap->device[device]; unsigned long xfer_modes; int i, rc; if (!ata_dev_present(dev)) { DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", - ap->id, device); - return; + ap->id, dev->devno); + return 0; } - DPRINTK("ENTER, host %u, dev %u\n", ap->id, device); - - WARN_ON(dev->id != NULL); - rc = ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id); - if (rc) - goto err_out; + DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); /* * common ATA, ATAPI feature tests @@ -1101,6 +1087,7 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) /* we require DMA support (bits 8 of word 49) */ if (!ata_id_has_dma(dev->id)) { printk(KERN_DEBUG "ata%u: no dma\n", ap->id); + rc = -EINVAL; goto err_out_nosup; } @@ -1125,12 +1112,12 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n", - ap->id, device, + ap->id, dev->devno, ata_id_major_version(dev->id), ata_mode_string(xfer_modes), (unsigned long long)dev->n_sectors, dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA"); - } else { + } else { /* CHS */ /* Default translation */ @@ -1147,7 +1134,7 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n", - ap->id, device, + ap->id, dev->devno, ata_id_major_version(dev->id), ata_mode_string(xfer_modes), (unsigned long long)dev->n_sectors, @@ -1163,13 +1150,14 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) rc = atapi_cdb_len(dev->id); if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); + rc = -EINVAL; goto err_out_nosup; } dev->cdb_len = (unsigned int) rc; /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", - ap->id, device, + ap->id, dev->devno, ata_mode_string(xfer_modes)); } @@ -1180,14 +1168,13 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) ap->device[i].cdb_len); DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); - return; + return 0; err_out_nosup: printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n", - ap->id, device); -err_out: - dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */ + ap->id, dev->devno); DPRINTK("EXIT, err\n"); + return rc; } @@ -1263,11 +1250,24 @@ static int ata_bus_probe(struct ata_port *ap) goto err_out; for (i = 0; i < ATA_MAX_DEVICES; i++) { - ata_dev_identify(ap, i); - if (ata_dev_present(&ap->device[i])) { - found = 1; - ata_dev_config(ap,i); + struct ata_device *dev = &ap->device[i]; + + if (!ata_dev_present(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 (ata_dev_configure(ap, dev)) { + dev->class++; /* disable device */ + continue; + } + + ata_dev_config(ap, i); + found = 1; } if ((!found) || (ap->flags & ATA_FLAG_PORT_DISABLED)) -- cgit v1.2.3-59-g8ed1b From 4b2f3ededc035525038a7a9247074243dac6b351 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 16:09:36 +0900 Subject: [PATCH] libata: fold ata_dev_config() into ata_dev_configure() ata_dev_config() needs to be done everytime a device is configured. Fold it into ata_dev_configure(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 48 ++++++++++++++++------------------------------ include/linux/libata.h | 1 - 2 files changed, 17 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ba26c66cc11b..10803f72c57d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1053,6 +1053,12 @@ 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) +{ + return ((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 @@ -1167,6 +1173,17 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev) ap->host->max_cmd_len, ap->device[i].cdb_len); + /* limit bridge transfers to udma5, 200 sectors */ + if (ata_dev_knobble(ap, dev)) { + printk(KERN_INFO "ata%u(%u): applying bridge limits\n", + ap->id, dev->devno); + ap->udma_mask &= ATA_UDMA5; + dev->max_sectors = ATA_MAX_SECTORS; + } + + if (ap->ops->dev_config) + ap->ops->dev_config(ap, dev); + DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); return 0; @@ -1177,35 +1194,6 @@ err_out_nosup: return rc; } - -static inline u8 ata_dev_knobble(const struct ata_port *ap, - struct ata_device *dev) -{ - return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); -} - -/** - * ata_dev_config - Run device specific handlers & check for SATA->PATA bridges - * @ap: Bus - * @i: Device - * - * LOCKING: - */ - -void ata_dev_config(struct ata_port *ap, unsigned int i) -{ - /* limit bridge transfers to udma5, 200 sectors */ - if (ata_dev_knobble(ap, &ap->device[i])) { - printk(KERN_INFO "ata%u(%u): applying bridge limits\n", - ap->id, i); - ap->udma_mask &= ATA_UDMA5; - ap->device[i].max_sectors = ATA_MAX_SECTORS; - } - - if (ap->ops->dev_config) - ap->ops->dev_config(ap, &ap->device[i]); -} - /** * ata_bus_probe - Reset and probe ATA bus * @ap: Bus to probe @@ -1266,7 +1254,6 @@ static int ata_bus_probe(struct ata_port *ap) continue; } - ata_dev_config(ap, i); found = 1; } @@ -4967,7 +4954,6 @@ EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_c_string); -EXPORT_SYMBOL_GPL(ata_dev_config); EXPORT_SYMBOL_GPL(ata_scsi_simulate); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); EXPORT_SYMBOL_GPL(ata_eh_qc_retry); diff --git a/include/linux/libata.h b/include/linux/libata.h index 9f273dd1958c..86a504f0ef06 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -542,7 +542,6 @@ extern void ata_id_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); extern void ata_id_c_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); -extern void ata_dev_config(struct ata_port *ap, unsigned int i); extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc); -- cgit v1.2.3-59-g8ed1b From 28ca5c57dc9f235f7cba609f2b541328de47beb2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Mar 2006 16:09:36 +0900 Subject: [PATCH] libata: reorganize ata_bus_probe() Now that reset and configure are converted such that they don't modify or disable libata core data structures, reorganize ata_bus_probe() to reflect this change. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 10803f72c57d..b710fc480740 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1211,35 +1211,40 @@ err_out_nosup: static int ata_bus_probe(struct ata_port *ap) { - unsigned int i, found = 0; + unsigned int classes[ATA_MAX_DEVICES]; + unsigned int i, rc, found = 0; - if (ap->ops->probe_reset) { - unsigned int classes[ATA_MAX_DEVICES]; - int rc; - - ata_port_probe(ap); + ata_port_probe(ap); + /* reset */ + if (ap->ops->probe_reset) { rc = ap->ops->probe_reset(ap, classes); - if (rc == 0) { - for (i = 0; i < ATA_MAX_DEVICES; i++) { - if (classes[i] == ATA_DEV_UNKNOWN) - classes[i] = ATA_DEV_NONE; - ap->device[i].class = classes[i]; - } - } else { - printk(KERN_ERR "ata%u: probe reset failed, " - "disabling port\n", ap->id); - ata_port_disable(ap); + if (rc) { + printk("ata%u: reset failed (errno=%d)\n", ap->id, rc); + return rc; } - } else + + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (classes[i] == ATA_DEV_UNKNOWN) + classes[i] = ATA_DEV_NONE; + } else { ap->ops->phy_reset(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) - goto err_out; + for (i = 0; i < ATA_MAX_DEVICES; i++) { + if (!(ap->flags & ATA_FLAG_PORT_DISABLED)) + classes[i] = ap->device[i].class; + else + ap->device[i].class = ATA_DEV_UNKNOWN; + } + ata_port_probe(ap); + } + /* read IDENTIFY page and configure devices */ for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; + dev->class = classes[i]; + if (!ata_dev_present(dev)) continue; @@ -1257,7 +1262,7 @@ static int ata_bus_probe(struct ata_port *ap) found = 1; } - if ((!found) || (ap->flags & ATA_FLAG_PORT_DISABLED)) + if (!found) goto err_out_disable; ata_set_mode(ap); @@ -1268,7 +1273,6 @@ static int ata_bus_probe(struct ata_port *ap) err_out_disable: ap->ops->port_disable(ap); -err_out: return -1; } -- cgit v1.2.3-59-g8ed1b From 8f903c708fcc2b579ebf16542bf6109bad593a1d Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Tue, 21 Feb 2006 16:36:44 -0800 Subject: [PATCH] bonding: suppress duplicate packets Originally submitted by Kenzo Iwami; his original description is: The current bonding driver receives duplicate packets when broadcast/ multicast packets are sent by other devices or packets are flooded by the switch. In this patch, new flags are added in priv_flags of net_device structure to let the bonding driver discard duplicate packets in dev.c:skb_bond(). Modified by Jay Vosburgh to change a define name, update some comments, rearrange the new skb_bond() for clarity, clear all bonding priv_flags on slave release, and update the driver version. Signed-off-by: Kenzo Iwami Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_main.c | 43 ++++++++++++++++++++-------------------- drivers/net/bonding/bond_sysfs.c | 6 ++++++ drivers/net/bonding/bonding.h | 33 +++++++++++++++++++++++++----- include/linux/if.h | 3 +++ include/linux/if_ether.h | 1 + net/core/dev.c | 26 +++++++++++++++++++++++- 6 files changed, 85 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bcf9f17daf0d..623c87a83615 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1040,6 +1040,10 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) if ((bond->params.mode == BOND_MODE_TLB) || (bond->params.mode == BOND_MODE_ALB)) { bond_alb_handle_active_change(bond, new_active); + if (old_active) + bond_set_slave_inactive_flags(old_active); + if (new_active) + bond_set_slave_active_flags(new_active); } else { bond->curr_active_slave = new_active; } @@ -1443,15 +1447,16 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) switch (bond->params.mode) { case BOND_MODE_ACTIVEBACKUP: - /* if we're in active-backup mode, we need one and only one active - * interface. The backup interfaces will have their NOARP flag set - * because we need them to be completely deaf and not to respond to - * any ARP request on the network to avoid fooling a switch. Thus, - * since we guarantee that curr_active_slave always point to the last - * usable interface, we just have to verify this interface's flag. + /* if we're in active-backup mode, we need one and + * only one active interface. The backup interfaces + * will have their SLAVE_INACTIVE flag set because we + * need them to be drop all packets. Thus, since we + * guarantee that curr_active_slave always point to + * the last usable interface, we just have to verify + * this interface's flag. */ if (((!bond->curr_active_slave) || - (bond->curr_active_slave->dev->flags & IFF_NOARP)) && + (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) && (new_slave->link != BOND_LINK_DOWN)) { dprintk("This is the first active slave\n"); /* first slave or no active slave yet, and this link @@ -1492,6 +1497,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) * is OK, so make this interface the active one */ bond_change_active_slave(bond, new_slave); + } else { + bond_set_slave_inactive_flags(new_slave); } break; default: @@ -1724,13 +1731,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) addr.sa_family = slave_dev->type; dev_set_mac_address(slave_dev, &addr); - /* restore the original state of the - * IFF_NOARP flag that might have been - * set by bond_set_slave_inactive_flags() - */ - if ((slave->original_flags & IFF_NOARP) == 0) { - slave_dev->flags &= ~IFF_NOARP; - } + slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | + IFF_SLAVE_INACTIVE); kfree(slave); @@ -1816,12 +1818,8 @@ static int bond_release_all(struct net_device *bond_dev) addr.sa_family = slave_dev->type; dev_set_mac_address(slave_dev, &addr); - /* restore the original state of the IFF_NOARP flag that might have - * been set by bond_set_slave_inactive_flags() - */ - if ((slave->original_flags & IFF_NOARP) == 0) { - slave_dev->flags &= ~IFF_NOARP; - } + slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | + IFF_SLAVE_INACTIVE); kfree(slave); @@ -4061,14 +4059,17 @@ void bond_set_mode_ops(struct bonding *bond, int mode) bond_dev->hard_start_xmit = bond_xmit_broadcast; break; case BOND_MODE_8023AD: + bond_set_master_3ad_flags(bond); bond_dev->hard_start_xmit = bond_3ad_xmit_xor; if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) bond->xmit_hash_policy = bond_xmit_hash_policy_l34; else bond->xmit_hash_policy = bond_xmit_hash_policy_l2; break; - case BOND_MODE_TLB: case BOND_MODE_ALB: + bond_set_master_alb_flags(bond); + /* FALLTHRU */ + case BOND_MODE_TLB: bond_dev->hard_start_xmit = bond_alb_xmit; bond_dev->set_mac_address = bond_alb_set_mac_address; break; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 041bcc583557..5a9bd95884be 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -424,6 +424,12 @@ static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size ret = -EINVAL; goto out; } else { + if (bond->params.mode == BOND_MODE_8023AD) + bond_unset_master_3ad_flags(bond); + + if (bond->params.mode == BOND_MODE_ALB) + bond_unset_master_alb_flags(bond); + bond->params.mode = new_value; bond_set_mode_ops(bond, bond->params.mode); printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n", diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 3dd78d048c3e..ce9dc9b4e2dc 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -22,8 +22,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.0.1" -#define DRV_RELDATE "January 9, 2006" +#define DRV_VERSION "3.0.2" +#define DRV_RELDATE "February 21, 2006" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" @@ -230,14 +230,37 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) static inline void bond_set_slave_inactive_flags(struct slave *slave) { - slave->state = BOND_STATE_BACKUP; - slave->dev->flags |= IFF_NOARP; + struct bonding *bond = slave->dev->master->priv; + if (bond->params.mode != BOND_MODE_TLB && + bond->params.mode != BOND_MODE_ALB) + slave->state = BOND_STATE_BACKUP; + slave->dev->priv_flags |= IFF_SLAVE_INACTIVE; } static inline void bond_set_slave_active_flags(struct slave *slave) { slave->state = BOND_STATE_ACTIVE; - slave->dev->flags &= ~IFF_NOARP; + slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE; +} + +static inline void bond_set_master_3ad_flags(struct bonding *bond) +{ + bond->dev->priv_flags |= IFF_MASTER_8023AD; +} + +static inline void bond_unset_master_3ad_flags(struct bonding *bond) +{ + bond->dev->priv_flags &= ~IFF_MASTER_8023AD; +} + +static inline void bond_set_master_alb_flags(struct bonding *bond) +{ + bond->dev->priv_flags |= IFF_MASTER_ALB; +} + +static inline void bond_unset_master_alb_flags(struct bonding *bond) +{ + bond->dev->priv_flags &= ~IFF_MASTER_ALB; } struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); diff --git a/include/linux/if.h b/include/linux/if.h index ce627d9092ef..12c6f6d157c3 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -52,6 +52,9 @@ /* Private (from user) interface flags (netdevice->priv_flags). */ #define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */ #define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */ +#define IFF_SLAVE_INACTIVE 0x4 /* bonding slave not the curr. active */ +#define IFF_MASTER_8023AD 0x8 /* bonding master, 802.3ad. */ +#define IFF_MASTER_ALB 0x10 /* bonding master, balance-alb. */ #define IF_GET_IFACE 0x0001 /* for querying only */ #define IF_GET_PROTO 0x0002 diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 7a92c1ce1457..ab08f35cbc35 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -61,6 +61,7 @@ #define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ #define ETH_P_IPX 0x8137 /* IPX over DIX */ #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ +#define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ #define ETH_P_WCCP 0x883E /* Web-cache coordination protocol * defined in draft-wilson-wrec-wccp-v2-00.txt */ #define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ diff --git a/net/core/dev.c b/net/core/dev.c index 225e38ff57c4..ef56c035d44e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1446,8 +1446,29 @@ static inline struct net_device *skb_bond(struct sk_buff *skb) { struct net_device *dev = skb->dev; - if (dev->master) + if (dev->master) { + /* + * On bonding slaves other than the currently active + * slave, suppress duplicates except for 802.3ad + * ETH_P_SLOW and alb non-mcast/bcast. + */ + if (dev->priv_flags & IFF_SLAVE_INACTIVE) { + if (dev->master->priv_flags & IFF_MASTER_ALB) { + if (skb->pkt_type != PACKET_BROADCAST && + skb->pkt_type != PACKET_MULTICAST) + goto keep; + } + + if (dev->master->priv_flags & IFF_MASTER_8023AD && + skb->protocol == __constant_htons(ETH_P_SLOW)) + goto keep; + + kfree_skb(skb); + return NULL; + } +keep: skb->dev = dev->master; + } return dev; } @@ -1591,6 +1612,9 @@ int netif_receive_skb(struct sk_buff *skb) orig_dev = skb_bond(skb); + if (!orig_dev) + return NET_RX_DROP; + __get_cpu_var(netdev_rx_stat).total++; skb->h.raw = skb->nh.raw = skb->data; -- cgit v1.2.3-59-g8ed1b From c96a34ec3bad5ba37ee4da4a188ad534b2fa4321 Mon Sep 17 00:00:00 2001 From: Komuro Date: Fri, 3 Mar 2006 21:21:13 -0500 Subject: pcnet_cs: add new id (Logitec LPM-LN100TE) --- drivers/net/pcmcia/pcnet_cs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index d85b758f3efa..736dff5fa93c 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9), PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline + 10/100 Network PC Card (PCM100H1)", 0x733cc81, 0x7a3e5c3a), PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737), + PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TE", 0x88fcdeda, 0x0e714bee), PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922), PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0), PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578), -- cgit v1.2.3-59-g8ed1b From f90fdc3cce3d8c8ed09615dc68cb789655078803 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 8 Feb 2006 23:23:26 +0000 Subject: [PATCH] sb1250-mac: Add support for the BCM1480 This adds support for the 4th port and other new features of the BCM1480 SOC. Signed-Off-By: Andy Isaacson Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik --- drivers/net/sb1250-mac.c | 109 ++++++++++++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index aa4ca1821759..f2be9f83f091 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001,2002,2003 Broadcom Corporation + * Copyright (C) 2001,2002,2003,2004 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -43,6 +43,7 @@ #define SBMAC_ETH0_HWADDR "40:00:00:00:01:00" #define SBMAC_ETH1_HWADDR "40:00:00:00:01:01" #define SBMAC_ETH2_HWADDR "40:00:00:00:01:02" +#define SBMAC_ETH3_HWADDR "40:00:00:00:01:03" #endif @@ -57,7 +58,7 @@ static char version1[] __devinitdata = #define CONFIG_SBMAC_COALESCE -#define MAX_UNITS 3 /* More are supported, limit only on options */ +#define MAX_UNITS 4 /* More are supported, limit only on options */ /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (2*HZ) @@ -85,11 +86,11 @@ MODULE_PARM_DESC(noisy_mii, "MII status messages"); The media type is usually passed in 'options[]'. */ #ifdef MODULE -static int options[MAX_UNITS] = {-1, -1, -1}; +static int options[MAX_UNITS] = {-1, -1, -1, -1}; module_param_array(options, int, NULL, S_IRUGO); MODULE_PARM_DESC(options, "1-" __MODULE_STRING(MAX_UNITS)); -static int full_duplex[MAX_UNITS] = {-1, -1, -1}; +static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1}; module_param_array(full_duplex, int, NULL, S_IRUGO); MODULE_PARM_DESC(full_duplex, "1-" __MODULE_STRING(MAX_UNITS)); #endif @@ -105,13 +106,26 @@ MODULE_PARM_DESC(int_timeout, "Timeout value"); #endif #include -#include +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) +#include +#include +#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) #include -#include -#include #include +#else +#error invalid SiByte MAC configuation +#endif #include +#include +#include +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) +#define UNIT_INT(n) (K_BCM1480_INT_MAC_0 + ((n) * 2)) +#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) +#define UNIT_INT(n) (K_INT_MAC_0 + (n)) +#else +#error invalid SiByte MAC configuation +#endif /********************************************************************** * Simple types @@ -1476,10 +1490,10 @@ static void sbmac_channel_start(struct sbmac_softc *s) * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above * Use a larger RD_THRSH for gigabit */ - if (periph_rev >= 2) - th_value = 64; - else + if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) th_value = 28; + else + th_value = 64; fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */ ((s->sbm_speed == sbmac_speed_1000) @@ -1589,13 +1603,17 @@ static void sbmac_channel_start(struct sbmac_softc *s) * Turn on the rest of the bits in the enable register */ +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) + __raw_writeq(M_MAC_RXDMA_EN0 | + M_MAC_TXDMA_EN0, s->sbm_macenable); +#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) __raw_writeq(M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0 | M_MAC_RX_ENABLE | M_MAC_TX_ENABLE, s->sbm_macenable); - - - +#else +#error invalid SiByte MAC configuation +#endif #ifdef CONFIG_SBMAC_COALESCE /* @@ -1786,11 +1804,12 @@ static void sbmac_set_iphdr_offset(struct sbmac_softc *sc) reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15); __raw_writeq(reg, sc->sbm_rxfilter); - /* read system identification to determine revision */ - if (periph_rev >= 2) { - sc->rx_hw_checksum = ENABLE; - } else { + /* BCM1250 pass1 didn't have hardware checksum. Everything + later does. */ + if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) { sc->rx_hw_checksum = DISABLE; + } else { + sc->rx_hw_checksum = ENABLE; } } @@ -2220,7 +2239,7 @@ static void sbmac_setmulti(struct sbmac_softc *sc) -#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) +#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) || defined(SBMAC_ETH3_HWADDR) /********************************************************************** * SBMAC_PARSE_XDIGIT(str) * @@ -2792,7 +2811,7 @@ static int sbmac_close(struct net_device *dev) -#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) +#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) || defined(SBMAC_ETH3_HWADDR) static void sbmac_setup_hwaddr(int chan,char *addr) { @@ -2818,25 +2837,7 @@ sbmac_init_module(void) unsigned long port; int chip_max_units; - /* - * For bringup when not using the firmware, we can pre-fill - * the MAC addresses using the environment variables - * specified in this file (or maybe from the config file?) - */ -#ifdef SBMAC_ETH0_HWADDR - sbmac_setup_hwaddr(0,SBMAC_ETH0_HWADDR); -#endif -#ifdef SBMAC_ETH1_HWADDR - sbmac_setup_hwaddr(1,SBMAC_ETH1_HWADDR); -#endif -#ifdef SBMAC_ETH2_HWADDR - sbmac_setup_hwaddr(2,SBMAC_ETH2_HWADDR); -#endif - - /* - * Walk through the Ethernet controllers and find - * those who have their MAC addresses set. - */ + /* Set the number of available units based on the SOC type. */ switch (soc_type) { case K_SYS_SOC_TYPE_BCM1250: case K_SYS_SOC_TYPE_BCM1250_ALT: @@ -2848,6 +2849,10 @@ sbmac_init_module(void) case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */ chip_max_units = 2; break; + case K_SYS_SOC_TYPE_BCM1x55: + case K_SYS_SOC_TYPE_BCM1x80: + chip_max_units = 4; + break; default: chip_max_units = 0; break; @@ -2855,6 +2860,32 @@ sbmac_init_module(void) if (chip_max_units > MAX_UNITS) chip_max_units = MAX_UNITS; + /* + * For bringup when not using the firmware, we can pre-fill + * the MAC addresses using the environment variables + * specified in this file (or maybe from the config file?) + */ +#ifdef SBMAC_ETH0_HWADDR + if (chip_max_units > 0) + sbmac_setup_hwaddr(0,SBMAC_ETH0_HWADDR); +#endif +#ifdef SBMAC_ETH1_HWADDR + if (chip_max_units > 1) + sbmac_setup_hwaddr(1,SBMAC_ETH1_HWADDR); +#endif +#ifdef SBMAC_ETH2_HWADDR + if (chip_max_units > 2) + sbmac_setup_hwaddr(2,SBMAC_ETH2_HWADDR); +#endif +#ifdef SBMAC_ETH3_HWADDR + if (chip_max_units > 3) + sbmac_setup_hwaddr(3,SBMAC_ETH3_HWADDR); +#endif + + /* + * Walk through the Ethernet controllers and find + * those who have their MAC addresses set. + */ for (idx = 0; idx < chip_max_units; idx++) { /* @@ -2886,7 +2917,7 @@ sbmac_init_module(void) printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port); - dev->irq = K_INT_MAC_0 + idx; + dev->irq = UNIT_INT(idx); dev->base_addr = port; dev->mem_end = 0; if (sbmac_init(dev, idx)) { -- cgit v1.2.3-59-g8ed1b From f71e130966ba429dbd24be08ddbcdf263df9a5ad Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 3 Mar 2006 21:33:57 -0500 Subject: Massive net driver const-ification. --- drivers/net/3c59x.c | 4 +- drivers/net/8139cp.c | 2 +- drivers/net/8139too.c | 4 +- drivers/net/bnx2.c | 10 ++--- drivers/net/bnx2_fw.h | 84 ++++++++++++++++++++-------------------- drivers/net/bonding/bond_alb.c | 2 +- drivers/net/bonding/bond_main.c | 2 +- drivers/net/chelsio/subr.c | 2 +- drivers/net/dgrs.c | 2 +- drivers/net/dgrs_firmware.c | 4 +- drivers/net/dl2k.c | 4 +- drivers/net/eepro100.c | 4 +- drivers/net/epic100.c | 4 +- drivers/net/fealnx.c | 2 +- drivers/net/hamachi.c | 2 +- drivers/net/natsemi.c | 4 +- drivers/net/ne2k-pci.c | 2 +- drivers/net/ns83820.c | 2 +- drivers/net/pcmcia/3c574_cs.c | 2 +- drivers/net/pcmcia/3c589_cs.c | 2 +- drivers/net/pcmcia/fmvj18x_cs.c | 2 +- drivers/net/pcmcia/nmclan_cs.c | 2 +- drivers/net/pcmcia/pcnet_cs.c | 2 +- drivers/net/pcmcia/smc91c92_cs.c | 4 +- drivers/net/pcmcia/xirc2ps_cs.c | 2 +- drivers/net/pcnet32.c | 6 +-- drivers/net/phy/phy.c | 2 +- drivers/net/plip.c | 4 +- drivers/net/ppp_synctty.c | 2 +- drivers/net/r8169.c | 4 +- drivers/net/s2io.c | 8 ++-- drivers/net/sb1000.c | 2 +- drivers/net/sis190.c | 2 +- drivers/net/sis900.c | 8 ++-- drivers/net/skfp/fplustm.c | 14 +++---- drivers/net/skfp/pcmplc.c | 4 +- drivers/net/skfp/skfddi.c | 2 +- drivers/net/starfire.c | 4 +- drivers/net/sundance.c | 4 +- drivers/net/sungem_phy.c | 2 +- drivers/net/tg3.c | 4 +- drivers/net/typhoon.c | 2 +- drivers/net/yellowfin.c | 6 +-- 43 files changed, 118 insertions(+), 118 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 7f47124f118d..26212a965cad 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -841,7 +841,7 @@ enum xcvr_types { XCVR_100baseFx, XCVR_MII=6, XCVR_NWAY=8, XCVR_ExtMII=9, XCVR_Default=10, }; -static struct media_table { +static const struct media_table { char *name; unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */ mask:8, /* The transceiver-present bit in Wn3_Config.*/ @@ -1445,7 +1445,7 @@ static int __devinit vortex_probe1(struct device *gendev, } { - static const char * ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; + static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; unsigned int config; EL3WINDOW(3); vp->available_media = ioread16(ioaddr + Wn3_Options); diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index dd410496aadb..ce99845d8266 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -1276,7 +1276,7 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu) } #endif /* BROKEN */ -static char mii_2_8139_map[8] = { +static const char mii_2_8139_map[8] = { BasicModeCtrl, BasicModeStatus, 0, diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 2beac55b57d6..e58d4c50c2e1 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -229,7 +229,7 @@ typedef enum { /* indexed by board_t, above */ -static struct { +static const struct { const char *name; u32 hw_flags; } board_info[] __devinitdata = { @@ -1192,7 +1192,7 @@ static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_l #define mdio_delay() RTL_R8(Config4) -static char mii_2_8139_map[8] = { +static const char mii_2_8139_map[8] = { BasicModeCtrl, BasicModeStatus, 0, diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index a24200d0a616..b787b6582e50 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -46,7 +46,7 @@ typedef enum { } board_t; /* indexed by board_t, above */ -static struct { +static const struct { char *name; } board_info[] __devinitdata = { { "Broadcom NetXtreme II BCM5706 1000Base-T" }, @@ -3476,7 +3476,7 @@ bnx2_test_registers(struct bnx2 *bp) { int ret; int i; - static struct { + static const struct { u16 offset; u16 flags; u32 rw_mask; @@ -3891,7 +3891,7 @@ reg_test_err: static int bnx2_do_mem_test(struct bnx2 *bp, u32 start, u32 size) { - static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555, + static const u32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555, 0xaaaaaaaa , 0xaa55aa55, 0x55aa55aa }; int i; @@ -3916,7 +3916,7 @@ bnx2_test_memory(struct bnx2 *bp) { int ret = 0; int i; - static struct { + static const struct { u32 offset; u32 len; } mem_tbl[] = { @@ -5122,7 +5122,7 @@ static struct { #define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4) -static unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = { +static const unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = { STATS_OFFSET32(stat_IfHCInOctets_hi), STATS_OFFSET32(stat_IfHCInBadOctets_hi), STATS_OFFSET32(stat_IfHCOutOctets_hi), diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h index 0c21bd849814..8158974c35a8 100644 --- a/drivers/net/bnx2_fw.h +++ b/drivers/net/bnx2_fw.h @@ -14,20 +14,20 @@ * accompanying it. */ -static int bnx2_COM_b06FwReleaseMajor = 0x1; -static int bnx2_COM_b06FwReleaseMinor = 0x0; -static int bnx2_COM_b06FwReleaseFix = 0x0; -static u32 bnx2_COM_b06FwStartAddr = 0x080008b4; -static u32 bnx2_COM_b06FwTextAddr = 0x08000000; -static int bnx2_COM_b06FwTextLen = 0x57bc; -static u32 bnx2_COM_b06FwDataAddr = 0x08005840; -static int bnx2_COM_b06FwDataLen = 0x0; -static u32 bnx2_COM_b06FwRodataAddr = 0x080057c0; -static int bnx2_COM_b06FwRodataLen = 0x58; -static u32 bnx2_COM_b06FwBssAddr = 0x08005860; -static int bnx2_COM_b06FwBssLen = 0x88; -static u32 bnx2_COM_b06FwSbssAddr = 0x08005840; -static int bnx2_COM_b06FwSbssLen = 0x1c; +static const int bnx2_COM_b06FwReleaseMajor = 0x1; +static const int bnx2_COM_b06FwReleaseMinor = 0x0; +static const int bnx2_COM_b06FwReleaseFix = 0x0; +static const u32 bnx2_COM_b06FwStartAddr = 0x080008b4; +static const u32 bnx2_COM_b06FwTextAddr = 0x08000000; +static const int bnx2_COM_b06FwTextLen = 0x57bc; +static const u32 bnx2_COM_b06FwDataAddr = 0x08005840; +static const int bnx2_COM_b06FwDataLen = 0x0; +static const u32 bnx2_COM_b06FwRodataAddr = 0x080057c0; +static const int bnx2_COM_b06FwRodataLen = 0x58; +static const u32 bnx2_COM_b06FwBssAddr = 0x08005860; +static const int bnx2_COM_b06FwBssLen = 0x88; +static const u32 bnx2_COM_b06FwSbssAddr = 0x08005840; +static const int bnx2_COM_b06FwSbssLen = 0x1c; static u32 bnx2_COM_b06FwText[(0x57bc/4) + 1] = { 0x0a00022d, 0x00000000, 0x00000000, 0x0000000d, 0x636f6d20, 0x322e352e, 0x38000000, 0x02050802, 0x00000000, 0x00000003, 0x00000014, 0x00000032, @@ -2325,20 +2325,20 @@ static u32 bnx2_rv2p_proc2[] = { 0x0000000c, 0x29520000, 0x00000018, 0x80000002, 0x0000000c, 0x29800000, 0x00000018, 0x00570000 }; -static int bnx2_TPAT_b06FwReleaseMajor = 0x1; -static int bnx2_TPAT_b06FwReleaseMinor = 0x0; -static int bnx2_TPAT_b06FwReleaseFix = 0x0; -static u32 bnx2_TPAT_b06FwStartAddr = 0x08000860; -static u32 bnx2_TPAT_b06FwTextAddr = 0x08000800; -static int bnx2_TPAT_b06FwTextLen = 0x122c; -static u32 bnx2_TPAT_b06FwDataAddr = 0x08001a60; -static int bnx2_TPAT_b06FwDataLen = 0x0; -static u32 bnx2_TPAT_b06FwRodataAddr = 0x00000000; -static int bnx2_TPAT_b06FwRodataLen = 0x0; -static u32 bnx2_TPAT_b06FwBssAddr = 0x08001aa0; -static int bnx2_TPAT_b06FwBssLen = 0x250; -static u32 bnx2_TPAT_b06FwSbssAddr = 0x08001a60; -static int bnx2_TPAT_b06FwSbssLen = 0x34; +static const int bnx2_TPAT_b06FwReleaseMajor = 0x1; +static const int bnx2_TPAT_b06FwReleaseMinor = 0x0; +static const int bnx2_TPAT_b06FwReleaseFix = 0x0; +static const u32 bnx2_TPAT_b06FwStartAddr = 0x08000860; +static const u32 bnx2_TPAT_b06FwTextAddr = 0x08000800; +static const int bnx2_TPAT_b06FwTextLen = 0x122c; +static const u32 bnx2_TPAT_b06FwDataAddr = 0x08001a60; +static const int bnx2_TPAT_b06FwDataLen = 0x0; +static const u32 bnx2_TPAT_b06FwRodataAddr = 0x00000000; +static const int bnx2_TPAT_b06FwRodataLen = 0x0; +static const u32 bnx2_TPAT_b06FwBssAddr = 0x08001aa0; +static const int bnx2_TPAT_b06FwBssLen = 0x250; +static const u32 bnx2_TPAT_b06FwSbssAddr = 0x08001a60; +static const int bnx2_TPAT_b06FwSbssLen = 0x34; static u32 bnx2_TPAT_b06FwText[(0x122c/4) + 1] = { 0x0a000218, 0x00000000, 0x00000000, 0x0000000d, 0x74706174, 0x20322e35, 0x2e313100, 0x02050b01, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -2540,20 +2540,20 @@ static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 }; static u32 bnx2_TPAT_b06FwBss[(0x250/4) + 1] = { 0x0 }; static u32 bnx2_TPAT_b06FwSbss[(0x34/4) + 1] = { 0x0 }; -static int bnx2_TXP_b06FwReleaseMajor = 0x1; -static int bnx2_TXP_b06FwReleaseMinor = 0x0; -static int bnx2_TXP_b06FwReleaseFix = 0x0; -static u32 bnx2_TXP_b06FwStartAddr = 0x080034b0; -static u32 bnx2_TXP_b06FwTextAddr = 0x08000000; -static int bnx2_TXP_b06FwTextLen = 0x5748; -static u32 bnx2_TXP_b06FwDataAddr = 0x08005760; -static int bnx2_TXP_b06FwDataLen = 0x0; -static u32 bnx2_TXP_b06FwRodataAddr = 0x00000000; -static int bnx2_TXP_b06FwRodataLen = 0x0; -static u32 bnx2_TXP_b06FwBssAddr = 0x080057a0; -static int bnx2_TXP_b06FwBssLen = 0x1c4; -static u32 bnx2_TXP_b06FwSbssAddr = 0x08005760; -static int bnx2_TXP_b06FwSbssLen = 0x38; +static const int bnx2_TXP_b06FwReleaseMajor = 0x1; +static const int bnx2_TXP_b06FwReleaseMinor = 0x0; +static const int bnx2_TXP_b06FwReleaseFix = 0x0; +static const u32 bnx2_TXP_b06FwStartAddr = 0x080034b0; +static const u32 bnx2_TXP_b06FwTextAddr = 0x08000000; +static const int bnx2_TXP_b06FwTextLen = 0x5748; +static const u32 bnx2_TXP_b06FwDataAddr = 0x08005760; +static const int bnx2_TXP_b06FwDataLen = 0x0; +static const u32 bnx2_TXP_b06FwRodataAddr = 0x00000000; +static const int bnx2_TXP_b06FwRodataLen = 0x0; +static const u32 bnx2_TXP_b06FwBssAddr = 0x080057a0; +static const int bnx2_TXP_b06FwBssLen = 0x1c4; +static const u32 bnx2_TXP_b06FwSbssAddr = 0x08005760; +static const int bnx2_TXP_b06FwSbssLen = 0x38; static u32 bnx2_TXP_b06FwText[(0x5748/4) + 1] = { 0x0a000d2c, 0x00000000, 0x00000000, 0x0000000d, 0x74787020, 0x322e352e, 0x38000000, 0x02050800, 0x0000000a, 0x000003e8, 0x0000ea60, 0x00000000, diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index f2a63186ae05..e83bc825f6af 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -1261,7 +1261,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) struct ethhdr *eth_data; struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); struct slave *tx_slave = NULL; - static u32 ip_bcast = 0xffffffff; + static const u32 ip_bcast = 0xffffffff; int hash_size = 0; int do_tx_balance = 1; u32 hash_index = 0; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bcf9f17daf0d..d0c54ea55fb0 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -131,7 +131,7 @@ MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); /*----------------------------- Global variables ----------------------------*/ -static const char *version = +static const char * const version = DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"; LIST_HEAD(bond_dev_list); diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index 1ebb5d149aef..12e4e96dba2d 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c @@ -686,7 +686,7 @@ int t1_init_hw_modules(adapter_t *adapter) */ static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p) { - static unsigned short speed_map[] = { 33, 66, 100, 133 }; + static const unsigned short speed_map[] = { 33, 66, 100, 133 }; u32 pci_mode; pci_read_config_dword(adapter->pdev, A_PCICFG_MODE, &pci_mode); diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 70b47e4c4e9c..32d13166c6e8 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -993,7 +993,7 @@ dgrs_download(struct net_device *dev0) int is; unsigned long i; - static int iv2is[16] = { + static const int iv2is[16] = { 0, 0, 0, ES4H_IS_INT3, 0, ES4H_IS_INT5, 0, ES4H_IS_INT7, 0, 0, ES4H_IS_INT10, ES4H_IS_INT11, diff --git a/drivers/net/dgrs_firmware.c b/drivers/net/dgrs_firmware.c index 1e49e1e1f201..8c20d4c99937 100644 --- a/drivers/net/dgrs_firmware.c +++ b/drivers/net/dgrs_firmware.c @@ -1,4 +1,4 @@ -static int dgrs_firmnum = 550; +static const int dgrs_firmnum = 550; static char dgrs_firmver[] = "$Version$"; static char dgrs_firmdate[] = "11/16/96 03:45:15"; static unsigned char dgrs_code[] __initdata = { @@ -9963,4 +9963,4 @@ static unsigned char dgrs_code[] __initdata = { 109,46,99,0,114,99,0,0,48,120,0,0, 0,0,0,0,0,0,0,0,0,0,0,0 } ; -static int dgrs_ncode = 119520 ; +static const int dgrs_ncode = 119520 ; diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index 430c628279b3..6376b63d9b17 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -90,8 +90,8 @@ module_param(tx_coalesce, int, 0); /* HW xmit count each TxDMAComplete */ #define EnableInt() \ writew(DEFAULT_INTR, ioaddr + IntEnable) -static int max_intrloop = 50; -static int multicast_filter_limit = 0x40; +static const int max_intrloop = 50; +static const int multicast_filter_limit = 0x40; static int rio_open (struct net_device *dev); static void rio_timer (unsigned long data); diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 8c62ced2c9b2..467fc861360d 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -27,7 +27,7 @@ rx_align support: enables rx DMA without causing unaligned accesses. */ -static const char *version = +static const char * const version = "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://www.scyld.com/network/eepro100.html\n" "eepro100.c: $Revision: 1.36 $ 2000/11/17 Modified by Andrey V. Savochkin and others\n"; @@ -469,7 +469,7 @@ static const char i82558_config_cmd[CONFIG_DATA_SIZE] = { 0x31, 0x05, }; /* PHY media interface chips. */ -static const char *phys[] = { +static const char * const phys[] = { "None", "i82553-A/B", "i82553-C", "i82503", "DP83840", "80c240", "80c24", "i82555", "unknown-8", "unknown-9", "DP83840A", "unknown-11", diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index f119ec4e89ea..2f7b86837fe8 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -225,7 +225,7 @@ struct epic_chip_info { /* indexed by chip_t */ -static struct epic_chip_info pci_id_tbl[] = { +static const struct epic_chip_info pci_id_tbl[] = { { "SMSC EPIC/100 83c170", EPIC_IOTYPE, EPIC_TOTAL_SIZE, TYPE2_INTR | NO_MII | MII_PWRDWN }, { "SMSC EPIC/100 83c170", @@ -291,7 +291,7 @@ enum CommandBits { RxDone | RxStarted | RxEarlyWarn | RxOverflow | RxFull) #define EpicNormalEvent (0x0000ffff & ~EpicNapiEvent) -static u16 media2miictl[16] = { +static const u16 media2miictl[16] = { 0, 0x0C00, 0x0C00, 0x2000, 0x0100, 0x2100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index 55dbe9a3fd56..a8449265e5fd 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -160,7 +160,7 @@ struct chip_info { int flags; }; -static struct chip_info skel_netdrv_tbl[] = { +static const struct chip_info skel_netdrv_tbl[] = { {"100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR}, {"100/10M Ethernet PCI Adapter", 136, HAS_CHIP_XCVR}, {"1000/100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR}, diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index bc9a3bf8d560..0ea4cb4a0d80 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -427,7 +427,7 @@ that case. static void hamachi_timer(unsigned long data); enum capability_flags {CanHaveMII=1, }; -static struct chip_info { +static const struct chip_info { u16 vendor_id, device_id, device_id_mask, pad; const char *name; void (*media_timer)(unsigned long data); diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 9d6d2548c2d3..01920648fc38 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -189,7 +189,7 @@ static int mtu; /* Maximum number of multicast addresses to filter (vs. rx-all-multicast). This chip uses a 512 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 100; +static const int multicast_filter_limit = 100; /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1518 effectively disables this feature. */ @@ -374,7 +374,7 @@ enum pcistuff { /* array of board data directly indexed by pci_tbl[x].driver_data */ -static struct { +static const struct { const char *name; unsigned long flags; } natsemi_pci_info[] __devinitdata = { diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index d11821dd86ed..e3ebb5803b02 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -117,7 +117,7 @@ enum ne2k_pci_chipsets { }; -static struct { +static const struct { char *name; int flags; } pci_clone_list[] __devinitdata = { diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index b0c3b6ab6263..f3924fb615b2 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -651,7 +651,7 @@ static void FASTCALL(phy_intr(struct net_device *ndev)); static void fastcall phy_intr(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); - static char *speeds[] = { "10", "100", "1000", "1000(?)", "1000F" }; + static const char *speeds[] = { "10", "100", "1000", "1000(?)", "1000F" }; u32 cfg, new_cfg; u32 tbisr, tanar, tanlpar; int speed, fullduplex, newlinkstate; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 48774efeec71..ce90becb8bdf 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -341,7 +341,7 @@ static void tc574_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; +static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; static void tc574_config(dev_link_t *link) { diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 1c3c9c666f74..576b2bf46925 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -115,7 +115,7 @@ struct el3_private { spinlock_t lock; }; -static char *if_names[] = { "auto", "10baseT", "10base2", "AUI" }; +static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" }; /*====================================================================*/ diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 28fe2fb4d6c0..b7ac14ba8877 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -309,7 +309,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) static int mfc_try_io_port(dev_link_t *link) { int i, ret; - static kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; + static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; for (i = 0; i < 5; i++) { link->io.BasePort2 = serial_base[i]; diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 4a232254a497..787176c57fd9 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -388,7 +388,7 @@ static char *version = DRV_NAME " " DRV_VERSION " (Roger C. Pao)"; #endif -static char *if_names[]={ +static const char *if_names[]={ "Auto", "10baseT", "BNC", }; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index d85b758f3efa..a280cf650488 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -66,7 +66,7 @@ #define PCNET_RDC_TIMEOUT (2*HZ/100) /* Max wait in jiffies for Tx RDC */ -static char *if_names[] = { "auto", "10baseT", "10base2"}; +static const char *if_names[] = { "auto", "10baseT", "10base2"}; #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 0122415dfeef..8839c4faafd6 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -59,7 +59,7 @@ /*====================================================================*/ -static char *if_names[] = { "auto", "10baseT", "10base2"}; +static const char *if_names[] = { "auto", "10baseT", "10base2"}; /* Module parameters */ @@ -777,7 +777,7 @@ free_cfg_mem: static int osi_config(dev_link_t *link) { struct net_device *dev = link->priv; - static kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; + static const kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; int i, j; link->conf.Attributes |= CONF_ENABLE_SPKR; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 593d8adee891..eed496803fe4 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -208,7 +208,7 @@ enum xirc_cmd { /* Commands */ #define XIRCREG45_REV 15 /* Revision Register (rd) */ #define XIRCREG50_IA 8 /* Individual Address (8-13) */ -static char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; +static const char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; /**************** * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 8f6cf8c896a4..7e900572eaf8 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -26,7 +26,7 @@ #define DRV_RELDATE "01.Nov.2005" #define PFX DRV_NAME ": " -static const char *version = +static const char * const version = DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n"; #include @@ -109,7 +109,7 @@ static int rx_copybreak = 200; * table to translate option values from tulip * to internal options */ -static unsigned char options_mapping[] = { +static const unsigned char options_mapping[] = { PCNET32_PORT_ASEL, /* 0 Auto-select */ PCNET32_PORT_AUI, /* 1 BNC/AUI */ PCNET32_PORT_AUI, /* 2 AUI/BNC */ @@ -733,7 +733,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1) int rc; /* return code */ int size; /* size of packets */ unsigned char *packet; /* source packet data */ - static int data_len = 60; /* length of source packets */ + static const int data_len = 60; /* length of source packets */ unsigned long flags; unsigned long ticks; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 1474b7c5ac0b..33cec2dab942 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -132,7 +132,7 @@ struct phy_setting { }; /* A mapping of all SUPPORTED settings to speed/duplex */ -static struct phy_setting settings[] = { +static const struct phy_setting settings[] = { { .speed = 10000, .duplex = DUPLEX_FULL, diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 87ee3271b17d..d4449d6d1fe4 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -123,7 +123,7 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n" #ifndef NET_DEBUG #define NET_DEBUG 1 #endif -static unsigned int net_debug = NET_DEBUG; +static const unsigned int net_debug = NET_DEBUG; #define ENABLE(irq) if (irq != -1) enable_irq(irq) #define DISABLE(irq) if (irq != -1) disable_irq(irq) @@ -351,7 +351,7 @@ static int plip_bh_timeout_error(struct net_device *dev, struct net_local *nl, typedef int (*plip_func)(struct net_device *dev, struct net_local *nl, struct plip_local *snd, struct plip_local *rcv); -static plip_func connection_state_table[] = +static const plip_func connection_state_table[] = { plip_none, plip_receive_packet, diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 33cb8254e79d..33255fe8031e 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -108,7 +108,7 @@ static void ppp_print_hex (register __u8 * out, const __u8 * in, int count) { register __u8 next_ch; - static char hex[] = "0123456789ABCDEF"; + static const char hex[] = "0123456789ABCDEF"; while (count-- > 0) { next_ch = *in++; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 8cc0d0bbdf50..0ad3310290f1 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -113,11 +113,11 @@ static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; static int num_media = 0; /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 20; +static const int max_interrupt_work = 20; /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; +static const int multicast_filter_limit = 32; /* MAC address length */ #define MAC_ADDR_LEN 6 diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 49b597cbc19a..a49ff17e1b83 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -214,7 +214,7 @@ static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid) #define SWITCH_SIGN 0xA5A5A5A5A5A5A5A5ULL #define END_SIGN 0x0 -static u64 herc_act_dtx_cfg[] = { +static const u64 herc_act_dtx_cfg[] = { /* Set address */ 0x8000051536750000ULL, 0x80000515367500E0ULL, /* Write data */ @@ -235,7 +235,7 @@ static u64 herc_act_dtx_cfg[] = { END_SIGN }; -static u64 xena_mdio_cfg[] = { +static const u64 xena_mdio_cfg[] = { /* Reset PMA PLL */ 0xC001010000000000ULL, 0xC0010100000000E0ULL, 0xC0010100008000E4ULL, @@ -245,7 +245,7 @@ static u64 xena_mdio_cfg[] = { END_SIGN }; -static u64 xena_dtx_cfg[] = { +static const u64 xena_dtx_cfg[] = { 0x8000051500000000ULL, 0x80000515000000E0ULL, 0x80000515D93500E4ULL, 0x8001051500000000ULL, 0x80010515000000E0ULL, 0x80010515001E00E4ULL, @@ -273,7 +273,7 @@ static u64 xena_dtx_cfg[] = { * Constants for Fixing the MacAddress problem seen mostly on * Alpha machines. */ -static u64 fix_mac[] = { +static const u64 fix_mac[] = { 0x0060000000000000ULL, 0x0060600000000000ULL, 0x0040600000000000ULL, 0x0000600000000000ULL, 0x0020600000000000ULL, 0x0060600000000000ULL, diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index 76139478c3df..66cf226c4ee3 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -59,7 +59,7 @@ static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n"; #ifdef SB1000_DEBUG static int sb1000_debug = SB1000_DEBUG; #else -static int sb1000_debug = 1; +static const int sb1000_debug = 1; #endif static const int SB1000_IO_EXTENT = 8; diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index ed4bc91638d2..31dd3f036fa8 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -366,7 +366,7 @@ static const u32 sis190_intr_mask = * Maximum number of multicast addresses to filter (vs. Rx-all-multicast). * The chips use a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; +static const int multicast_filter_limit = 32; static void __mdio_cmd(void __iomem *ioaddr, u32 ctl) { diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 7a952fe60be2..a1cb07cdb60f 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -100,7 +100,7 @@ enum { SIS_900 = 0, SIS_7016 }; -static char * card_names[] = { +static const char * card_names[] = { "SiS 900 PCI Fast Ethernet", "SiS 7016 PCI Fast Ethernet" }; @@ -115,7 +115,7 @@ MODULE_DEVICE_TABLE (pci, sis900_pci_tbl); static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex); -static struct mii_chip_info { +static const struct mii_chip_info { const char * name; u16 phy_id0; u16 phy_id1; @@ -400,7 +400,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev, void *ring_space; long ioaddr; int i, ret; - char *card_name = card_names[pci_id->driver_data]; + const char *card_name = card_names[pci_id->driver_data]; const char *dev_name = pci_name(pci_dev); /* when built into the kernel, we only print version if device is found */ @@ -1275,7 +1275,7 @@ static void sis900_timer(unsigned long data) struct net_device *net_dev = (struct net_device *)data; struct sis900_private *sis_priv = net_dev->priv; struct mii_phy *mii_phy = sis_priv->mii; - static int next_tick = 5*HZ; + static const int next_tick = 5*HZ; u16 status; if (!sis_priv->autong_complete){ diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c index a2ed47f1cc70..a4b2b6975d6c 100644 --- a/drivers/net/skfp/fplustm.c +++ b/drivers/net/skfp/fplustm.c @@ -89,21 +89,21 @@ static const u_short my_sagp = 0xffff ; /* short group address (n.u.) */ /* * useful interrupt bits */ -static int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ; -static int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0| +static const int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ; +static const int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0| FM_STBURS | FM_STBURA0 ; /* delete FM_SRBFL after tests */ -static int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL | +static const int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL | FM_SMYCLM ; -static int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR | +static const int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR | FM_SERRCTR | FM_SLSTCTR | FM_STRTEXP | FM_SMULTDA | FM_SRNGOP ; -static int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ; -static int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ; +static const int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ; +static const int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ; -static int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC | +static const int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC | FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ; diff --git a/drivers/net/skfp/pcmplc.c b/drivers/net/skfp/pcmplc.c index cd0aa4c151b0..74e129f3ce92 100644 --- a/drivers/net/skfp/pcmplc.c +++ b/drivers/net/skfp/pcmplc.c @@ -186,7 +186,7 @@ static const struct plt { * Do we need the EBUF error during signaling, too, to detect SUPERNET_3 * PLL bug? */ -static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK | +static const int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK | PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR; #else /* SUPERNET_3 */ /* @@ -195,7 +195,7 @@ static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK | static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK | PL_PCM_ENABLED | PL_SELF_TEST ; #endif /* SUPERNET_3 */ -static int plc_imsk_act = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK | +static const int plc_imsk_act = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK | PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR; /* external functions */ diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 4b5ed2c63177..c7fb6133047e 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -67,7 +67,7 @@ /* each new release!!! */ #define VERSION "2.07" -static const char *boot_msg = +static const char * const boot_msg = "SysKonnect FDDI PCI Adapter driver v" VERSION " for\n" " SK-55xx/SK-58xx adapters (SK-NET FDDI-FP/UP/LP)"; diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index d167deda9a53..a6bf5728fed1 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -201,7 +201,7 @@ static int max_interrupt_work = 20; static int mtu; /* Maximum number of multicast addresses to filter (vs. rx-all-multicast). The Starfire has a 512 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 512; +static const int multicast_filter_limit = 512; /* Whether to do TCP/UDP checksums in hardware */ static int enable_hw_cksum = 1; @@ -463,7 +463,7 @@ static struct pci_device_id starfire_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, starfire_pci_tbl); /* A chip capabilities table, matching the CH_xxx entries in xxx_pci_tbl[] above. */ -static struct chip_info { +static const struct chip_info { const char *name; int drv_flags; } netdrv_tbl[] __devinitdata = { diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 0ab9c38b4a34..059141814fec 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -106,7 +106,7 @@ static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ /* Maximum number of multicast addresses to filter (vs. rx-all-multicast). Typical is a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; +static const int multicast_filter_limit = 32; /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1518 effectively disables this feature. @@ -298,7 +298,7 @@ enum { struct pci_id_info { const char *name; }; -static struct pci_id_info pci_id_tbl[] = { +static const struct pci_id_info pci_id_tbl[] = { {"D-Link DFE-550TX FAST Ethernet Adapter"}, {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"}, {"D-Link DFE-580TX 4 port Server Adapter"}, diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c index d3ddb41d6e5c..cb0aba95d4e3 100644 --- a/drivers/net/sungem_phy.c +++ b/drivers/net/sungem_phy.c @@ -39,7 +39,7 @@ #include "sungem_phy.h" /* Link modes of the BCM5400 PHY */ -static int phy_BCM5400_link_table[8][3] = { +static const int phy_BCM5400_link_table[8][3] = { { 0, 0, 0 }, /* No link */ { 0, 0, 0 }, /* 10BT Half Duplex */ { 1, 0, 0 }, /* 10BT Full Duplex */ diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e8e92c853e89..83ff5994a8d5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7785,7 +7785,7 @@ static int tg3_test_link(struct tg3 *tp) } /* Only test the commonly used registers */ -static int tg3_test_registers(struct tg3 *tp) +static const int tg3_test_registers(struct tg3 *tp) { int i, is_5705; u32 offset, read_mask, write_mask, val, save_val, read_val; @@ -7999,7 +7999,7 @@ out: static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len) { - static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0xaa55a55a }; + static const u32 test_pattern[] = { 0x00000000, 0xffffffff, 0xaa55a55a }; int i; u32 j; diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 4c76cb794bfb..cde35dd87906 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -178,7 +178,7 @@ enum typhoon_cards { }; /* directly indexed by enum typhoon_cards, above */ -static struct typhoon_card_info typhoon_card_info[] __devinitdata = { +static const struct typhoon_card_info typhoon_card_info[] __devinitdata = { { "3Com Typhoon (3C990-TX)", TYPHOON_CRYPTO_NONE}, { "3Com Typhoon (3CR990-TX-95)", diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 1c2506535f7e..75d56bfef0ee 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -69,8 +69,8 @@ static int fifo_cfg = 0x0020; /* Bypass external Tx FIFO. */ static int dma_ctrl = 0x00CAC277; /* Override when loading module! */ static int fifo_cfg = 0x0028; #else -static int dma_ctrl = 0x004A0263; /* Constrained by errata */ -static int fifo_cfg = 0x0020; /* Bypass external Tx FIFO. */ +static const int dma_ctrl = 0x004A0263; /* Constrained by errata */ +static const int fifo_cfg = 0x0020; /* Bypass external Tx FIFO. */ #endif /* Set the copy breakpoint for the copy-only-tiny-frames scheme. @@ -266,7 +266,7 @@ struct pci_id_info { int drv_flags; /* Driver use, intended as capability flags. */ }; -static struct pci_id_info pci_id_tbl[] = { +static const struct pci_id_info pci_id_tbl[] = { {"Yellowfin G-NIC Gigabit Ethernet", { 0x07021000, 0xffffffff}, PCI_IOTYPE, YELLOWFIN_SIZE, FullTxStatus | IsGigabit | HasMulticastBug | HasMACAddrBug | DontUseEeprom}, -- cgit v1.2.3-59-g8ed1b From c3cf560e35509634d72cf809074834d5ea23ab66 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 4 Mar 2006 17:07:57 +0100 Subject: [PATCH] remove obsolete sis900 documentation This documentation is mostly obsolete, and should therefore either be updated or removed (this patch does the latter). Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik --- Documentation/DocBook/Makefile | 2 +- Documentation/DocBook/sis900.tmpl | 585 ------------------------------------ Documentation/networking/00-INDEX | 2 - Documentation/networking/sis900.txt | 257 ---------------- drivers/net/Kconfig | 6 +- 5 files changed, 2 insertions(+), 850 deletions(-) delete mode 100644 Documentation/DocBook/sis900.tmpl delete mode 100644 Documentation/networking/sis900.txt (limited to 'drivers') diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 1c955883cf58..2975291e296a 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -9,7 +9,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ procfs-guide.xml writing_usb_driver.xml \ - sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \ + kernel-api.xml journal-api.xml lsm.xml usb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml ### diff --git a/Documentation/DocBook/sis900.tmpl b/Documentation/DocBook/sis900.tmpl deleted file mode 100644 index 6c2cbac93c3f..000000000000 --- a/Documentation/DocBook/sis900.tmpl +++ /dev/null @@ -1,585 +0,0 @@ - - - - - - - -SiS 900/7016 Fast Ethernet Device Driver - - - -Ollie -Lho - - - -Lei Chun -Chang - - - -Document Revision: 0.3 for SiS900 driver v1.06 & v1.07 -November 16, 2000 - - - 1999 - Silicon Integrated System 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. - - - - 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 - - - - - -This document gives some information on installation and usage of SiS 900/7016 -device driver under Linux. - - - - - - - - - Introduction - - -This document describes the revision 1.06 and 1.07 of SiS 900/7016 Fast Ethernet -device driver under Linux. The driver is developed by Silicon Integrated -System Corp. and distributed freely under the GNU General Public License (GPL). -The driver can be compiled as a loadable module and used under Linux kernel -version 2.2.x. (rev. 1.06) -With minimal changes, the driver can also be used under 2.3.x and 2.4.x kernel -(rev. 1.07), please see -. If you are intended to -use the driver for earlier kernels, you are on your own. - - - -The driver is tested with usual TCP/IP applications including -FTP, Telnet, Netscape etc. and is used constantly by the developers. - - - -Please send all comments/fixes/questions to -Lei-Chun Chang. - - - - - Changes - - -Changes made in Revision 1.07 - - - - -Separation of sis900.c and sis900.h in order to move most -constant definition to sis900.h (many of those constants were -corrected) - - - - - -Clean up PCI detection, the pci-scan from Donald Becker were not used, -just simple pci_find_*. - - - - - -MII detection is modified to support multiple mii transceiver. - - - - - -Bugs in read_eeprom, mdio_* were removed. - - - - - -Lot of sis900 irrelevant comments were removed/changed and -more comments were added to reflect the real situation. - - - - - -Clean up of physical/virtual address space mess in buffer -descriptors. - - - - - -Better transmit/receive error handling. - - - - - -The driver now uses zero-copy single buffer management -scheme to improve performance. - - - - - -Names of variables were changed to be more consistent. - - - - - -Clean up of auo-negotiation and timer code. - - - - - -Automatic detection and change of PHY on the fly. - - - - - -Bug in mac probing fixed. - - - - - -Fix 630E equalier problem by modifying the equalizer workaround rule. - - - - - -Support for ICS1893 10/100 Interated PHYceiver. - - - - - -Support for media select by ifconfig. - - - - - -Added kernel-doc extratable documentation. - - - - - - - - - Tested Environment - - -This driver is developed on the following hardware - - - - - -Intel Celeron 500 with SiS 630 (rev 02) chipset - - - - - -SiS 900 (rev 01) and SiS 7016/7014 Fast Ethernet Card - - - - - -and tested with these software environments - - - - - -Red Hat Linux version 6.2 - - - - - -Linux kernel version 2.4.0 - - - - - -Netscape version 4.6 - - - - - -NcFTP 3.0.0 beta 18 - - - - - -Samba version 2.0.3 - - - - - - - - - - -Files in This Package - - -In the package you can find these files: - - - - - - -sis900.c - - -Driver source file in C - - - - - -sis900.h - - -Header file for sis900.c - - - - - -sis900.sgml - - -DocBook SGML source of the document - - - - - -sis900.txt - - -Driver document in plain text - - - - - - - - - - Installation - - -Silicon Integrated System Corp. is cooperating closely with core Linux Kernel -developers. The revisions of SiS 900 driver are distributed by the usuall channels -for kernel tar files and patches. Those kernel tar files for official kernel and -patches for kernel pre-release can be download at -official kernel ftp site -and its mirrors. -The 1.06 revision can be found in kernel version later than 2.3.15 and pre-2.2.14, -and 1.07 revision can be found in kernel version 2.4.0. -If you have no prior experience in networking under Linux, please read -Ethernet HOWTO and -Networking HOWTO available from -Linux Documentation Project (LDP). - - - -The driver is bundled in release later than 2.2.11 and 2.3.15 so this -is the most easy case. -Be sure you have the appropriate packages for compiling kernel source. -Those packages are listed in Document/Changes in kernel source -distribution. If you have to install the driver other than those bundled -in kernel release, you should have your driver file -sis900.c and sis900.h -copied into /usr/src/linux/drivers/net/ first. -There are two alternative ways to install the driver - - - -Building the driver as loadable module - - -To build the driver as a loadable kernel module you have to reconfigure -the kernel to activate network support by - - - -make menuconfig - - - -Choose Loadable module support --->, -then select Enable loadable module support. - - - -Choose Network Device Support --->, select -Ethernet (10 or 100Mbit). -Then select EISA, VLB, PCI and on board controllers, -and choose SiS 900/7016 PCI Fast Ethernet Adapter support -to M. - - - -After reconfiguring the kernel, you can make the driver module by - - - -make modules - - - -The driver should be compiled with no errors. After compiling the driver, -the driver can be installed to proper place by - - - -make modules_install - - - -Load the driver into kernel by - - - -insmod sis900 - - - -When loading the driver into memory, some information message can be view by - - - - -dmesg - - -or - - -cat /var/log/message - - - - -If the driver is loaded properly you will have messages similar to this: - - - -sis900.c: v1.07.06 11/07/2000 -eth0: SiS 900 PCI Fast Ethernet at 0xd000, IRQ 10, 00:00:e8:83:7f:a4. -eth0: SiS 900 Internal MII PHY transceiver found at address 1. -eth0: Using SiS 900 Internal MII PHY as default - - - -showing the version of the driver and the results of probing routine. - - - -Once the driver is loaded, network can be brought up by - - - -/sbin/ifconfig eth0 IPADDR broadcast BROADCAST netmask NETMASK media TYPE - - - -where IPADDR, BROADCAST, NETMASK are your IP address, broadcast address and -netmask respectively. TYPE is used to set medium type used by the device. -Typical values are "10baseT"(twisted-pair 10Mbps Ethernet) or "100baseT" -(twisted-pair 100Mbps Ethernet). For more information on how to configure -network interface, please refer to -Networking HOWTO. - - - -The link status is also shown by kernel messages. For example, after the -network interface is activated, you may have the message: - - - -eth0: Media Link On 100mbps full-duplex - - - -If you try to unplug the twist pair (TP) cable you will get - - - -eth0: Media Link Off - - - -indicating that the link is failed. - - - - -Building the driver into kernel - - -If you want to make the driver into kernel, choose Y -rather than M on -SiS 900/7016 PCI Fast Ethernet Adapter support -when configuring the kernel. Build the kernel image in the usual way - - - -make clean - -make bzlilo - - - -Next time the system reboot, you have the driver in memory. - - - - - - - Known Problems and Bugs - - -There are some known problems and bugs. If you find any other bugs please -mail to lcchang@sis.com.tw - - - - - -AM79C901 HomePNA PHY is not thoroughly tested, there may be some -bugs in the on the fly change of transceiver. - - - - - -A bug is hidden somewhere in the receive buffer management code, -the bug causes NULL pointer reference in the kernel. This fault is -caught before bad things happen and reported with the message: - - -eth0: NULL pointer encountered in Rx ring, skipping - - -which can be viewed with dmesg or -cat /var/log/message. - - - - - -The media type change from 10Mbps to 100Mbps twisted-pair ethernet -by ifconfig causes the media link down. - - - - - - - - - Revision History - - - - - - -November 13, 2000, Revision 1.07, seventh release, 630E problem fixed -and further clean up. - - - - - -November 4, 1999, Revision 1.06, Second release, lots of clean up -and optimization. - - - - - -August 8, 1999, Revision 1.05, Initial Public Release - - - - - - - - - Acknowledgements - - -This driver was originally derived form -Donald Becker's -pci-skeleton and -rtl8139 drivers. Donald also provided various suggestion -regarded with improvements made in revision 1.06. - - - -The 1.05 revision was created by -Jim Huang, AMD 79c901 -support was added by Chin-Shan Li. - - - - -List of Functions -!Idrivers/net/sis900.c - - - diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX index 5b01d5cc4e95..b1181ce232d9 100644 --- a/Documentation/networking/00-INDEX +++ b/Documentation/networking/00-INDEX @@ -92,8 +92,6 @@ routing.txt - the new routing mechanism shaper.txt - info on the module that can shape/limit transmitted traffic. -sis900.txt - - SiS 900/7016 Fast Ethernet device driver info. sk98lin.txt - Marvell Yukon Chipset / SysKonnect SK-98xx compliant Gigabit Ethernet Adapter family driver info diff --git a/Documentation/networking/sis900.txt b/Documentation/networking/sis900.txt deleted file mode 100644 index bddffd7385ae..000000000000 --- a/Documentation/networking/sis900.txt +++ /dev/null @@ -1,257 +0,0 @@ - -SiS 900/7016 Fast Ethernet Device Driver - -Ollie Lho - -Lei Chun Chang - - Copyright © 1999 by Silicon Integrated System Corp. - - This document gives some information on installation and usage of SiS - 900/7016 device driver under Linux. - - 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 - _________________________________________________________________ - - Table of Contents - 1. Introduction - 2. Changes - 3. Tested Environment - 4. Files in This Package - 5. Installation - - Building the driver as loadable module - Building the driver into kernel - - 6. Known Problems and Bugs - 7. Revision History - 8. Acknowledgements - _________________________________________________________________ - -Chapter 1. Introduction - - This document describes the revision 1.06 and 1.07 of SiS 900/7016 - Fast Ethernet device driver under Linux. The driver is developed by - Silicon Integrated System Corp. and distributed freely under the GNU - General Public License (GPL). The driver can be compiled as a loadable - module and used under Linux kernel version 2.2.x. (rev. 1.06) With - minimal changes, the driver can also be used under 2.3.x and 2.4.x - kernel (rev. 1.07), please see Chapter 5. If you are intended to use - the driver for earlier kernels, you are on your own. - - The driver is tested with usual TCP/IP applications including FTP, - Telnet, Netscape etc. and is used constantly by the developers. - - Please send all comments/fixes/questions to Lei-Chun Chang. - _________________________________________________________________ - -Chapter 2. Changes - - Changes made in Revision 1.07 - - 1. Separation of sis900.c and sis900.h in order to move most constant - definition to sis900.h (many of those constants were corrected) - 2. Clean up PCI detection, the pci-scan from Donald Becker were not - used, just simple pci_find_*. - 3. MII detection is modified to support multiple mii transceiver. - 4. Bugs in read_eeprom, mdio_* were removed. - 5. Lot of sis900 irrelevant comments were removed/changed and more - comments were added to reflect the real situation. - 6. Clean up of physical/virtual address space mess in buffer - descriptors. - 7. Better transmit/receive error handling. - 8. The driver now uses zero-copy single buffer management scheme to - improve performance. - 9. Names of variables were changed to be more consistent. - 10. Clean up of auo-negotiation and timer code. - 11. Automatic detection and change of PHY on the fly. - 12. Bug in mac probing fixed. - 13. Fix 630E equalier problem by modifying the equalizer workaround - rule. - 14. Support for ICS1893 10/100 Interated PHYceiver. - 15. Support for media select by ifconfig. - 16. Added kernel-doc extratable documentation. - _________________________________________________________________ - -Chapter 3. Tested Environment - - This driver is developed on the following hardware - - * Intel Celeron 500 with SiS 630 (rev 02) chipset - * SiS 900 (rev 01) and SiS 7016/7014 Fast Ethernet Card - - and tested with these software environments - - * Red Hat Linux version 6.2 - * Linux kernel version 2.4.0 - * Netscape version 4.6 - * NcFTP 3.0.0 beta 18 - * Samba version 2.0.3 - _________________________________________________________________ - -Chapter 4. Files in This Package - - In the package you can find these files: - - sis900.c - Driver source file in C - - sis900.h - Header file for sis900.c - - sis900.sgml - DocBook SGML source of the document - - sis900.txt - Driver document in plain text - _________________________________________________________________ - -Chapter 5. Installation - - Silicon Integrated System Corp. is cooperating closely with core Linux - Kernel developers. The revisions of SiS 900 driver are distributed by - the usuall channels for kernel tar files and patches. Those kernel tar - files for official kernel and patches for kernel pre-release can be - download at official kernel ftp site and its mirrors. The 1.06 - revision can be found in kernel version later than 2.3.15 and - pre-2.2.14, and 1.07 revision can be found in kernel version 2.4.0. If - you have no prior experience in networking under Linux, please read - Ethernet HOWTO and Networking HOWTO available from Linux Documentation - Project (LDP). - - The driver is bundled in release later than 2.2.11 and 2.3.15 so this - is the most easy case. Be sure you have the appropriate packages for - compiling kernel source. Those packages are listed in Document/Changes - in kernel source distribution. If you have to install the driver other - than those bundled in kernel release, you should have your driver file - sis900.c and sis900.h copied into /usr/src/linux/drivers/net/ first. - There are two alternative ways to install the driver - _________________________________________________________________ - -Building the driver as loadable module - - To build the driver as a loadable kernel module you have to - reconfigure the kernel to activate network support by - -make menuconfig - - Choose "Loadable module support --->", then select "Enable loadable - module support". - - Choose "Network Device Support --->", select "Ethernet (10 or - 100Mbit)". Then select "EISA, VLB, PCI and on board controllers", and - choose "SiS 900/7016 PCI Fast Ethernet Adapter support" to "M". - - After reconfiguring the kernel, you can make the driver module by - -make modules - - The driver should be compiled with no errors. After compiling the - driver, the driver can be installed to proper place by - -make modules_install - - Load the driver into kernel by - -insmod sis900 - - When loading the driver into memory, some information message can be - view by - -dmesg - - or -cat /var/log/message - - If the driver is loaded properly you will have messages similar to - this: - -sis900.c: v1.07.06 11/07/2000 -eth0: SiS 900 PCI Fast Ethernet at 0xd000, IRQ 10, 00:00:e8:83:7f:a4. -eth0: SiS 900 Internal MII PHY transceiver found at address 1. -eth0: Using SiS 900 Internal MII PHY as default - - showing the version of the driver and the results of probing routine. - - Once the driver is loaded, network can be brought up by - -/sbin/ifconfig eth0 IPADDR broadcast BROADCAST netmask NETMASK media TYPE - - where IPADDR, BROADCAST, NETMASK are your IP address, broadcast - address and netmask respectively. TYPE is used to set medium type used - by the device. Typical values are "10baseT"(twisted-pair 10Mbps - Ethernet) or "100baseT" (twisted-pair 100Mbps Ethernet). For more - information on how to configure network interface, please refer to - Networking HOWTO. - - The link status is also shown by kernel messages. For example, after - the network interface is activated, you may have the message: - -eth0: Media Link On 100mbps full-duplex - - If you try to unplug the twist pair (TP) cable you will get - -eth0: Media Link Off - - indicating that the link is failed. - _________________________________________________________________ - -Building the driver into kernel - - If you want to make the driver into kernel, choose "Y" rather than "M" - on "SiS 900/7016 PCI Fast Ethernet Adapter support" when configuring - the kernel. Build the kernel image in the usual way - -make clean - -make bzlilo - - Next time the system reboot, you have the driver in memory. - _________________________________________________________________ - -Chapter 6. Known Problems and Bugs - - There are some known problems and bugs. If you find any other bugs - please mail to lcchang@sis.com.tw - - 1. AM79C901 HomePNA PHY is not thoroughly tested, there may be some - bugs in the "on the fly" change of transceiver. - 2. A bug is hidden somewhere in the receive buffer management code, - the bug causes NULL pointer reference in the kernel. This fault is - caught before bad things happen and reported with the message: - eth0: NULL pointer encountered in Rx ring, skipping which can be - viewed with dmesg or cat /var/log/message. - 3. The media type change from 10Mbps to 100Mbps twisted-pair ethernet - by ifconfig causes the media link down. - _________________________________________________________________ - -Chapter 7. Revision History - - * November 13, 2000, Revision 1.07, seventh release, 630E problem - fixed and further clean up. - * November 4, 1999, Revision 1.06, Second release, lots of clean up - and optimization. - * August 8, 1999, Revision 1.05, Initial Public Release - _________________________________________________________________ - -Chapter 8. Acknowledgements - - This driver was originally derived form Donald Becker's pci-skeleton - and rtl8139 drivers. Donald also provided various suggestion regarded - with improvements made in revision 1.06. - - The 1.05 revision was created by Jim Huang, AMD 79c901 support was - added by Chin-Shan Li. diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 11ca9f03b43e..bdf294d2df26 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1613,11 +1613,7 @@ config SIS900 ---help--- This is a driver for the Fast Ethernet PCI network cards based on the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in - SiS 630 and SiS 540 chipsets. If you have one of those, say Y and - read the Ethernet-HOWTO, available at - . Please read - and comments at the - beginning of for more information. + SiS 630 and SiS 540 chipsets. This driver also supports AMD 79C901 HomePNA so that you can use your phone line as a network cable. -- cgit v1.2.3-59-g8ed1b From b27a16b7c4738ea16f6f0730caf382a3f57317bb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Feb 2006 00:00:01 +0000 Subject: [PATCH] natsemi: NAPI and a bugfix This patch converts the natsemi driver to use NAPI. It was originally based on one written by Harald Welte, though it has since been modified quite a bit, most extensively in order to remove the ability to disable NAPI since none of the other drivers seem to provide that functionality any more. Signed-off-by: Mark Brown Signed-off-by: Jeff Garzik --- drivers/net/natsemi.c | 146 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 97 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 01920648fc38..e363f9bb35ea 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -3,6 +3,7 @@ Written/copyright 1999-2001 by Donald Becker. Portions copyright (c) 2001,2002 Sun Microsystems (thockin@sun.com) Portions copyright 2001,2002 Manfred Spraul (manfred@colorfullife.com) + Portions copyright 2004 Harald Welte This software may be used and distributed according to the terms of the GNU General Public License (GPL), incorporated herein by reference. @@ -135,8 +136,6 @@ TODO: * big endian support with CFG:BEM instead of cpu_to_le32 - * support for an external PHY - * NAPI */ #include @@ -160,6 +159,7 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include @@ -183,8 +183,6 @@ NETIF_MSG_TX_ERR) static int debug = -1; -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 20; static int mtu; /* Maximum number of multicast addresses to filter (vs. rx-all-multicast). @@ -251,14 +249,11 @@ MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver"); MODULE_LICENSE("GPL"); -module_param(max_interrupt_work, int, 0); module_param(mtu, int, 0); module_param(debug, int, 0); module_param(rx_copybreak, int, 0); module_param_array(options, int, NULL, 0); module_param_array(full_duplex, int, NULL, 0); -MODULE_PARM_DESC(max_interrupt_work, - "DP8381x maximum events handled per interrupt"); MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)"); MODULE_PARM_DESC(debug, "DP8381x default debug level"); MODULE_PARM_DESC(rx_copybreak, @@ -691,6 +686,8 @@ struct netdev_private { /* Based on MTU+slack. */ unsigned int rx_buf_sz; int oom; + /* Interrupt status */ + u32 intr_status; /* Do not touch the nic registers */ int hands_off; /* external phy that is used: only valid if dev->if_port != PORT_TP */ @@ -748,7 +745,8 @@ static void init_registers(struct net_device *dev); static int start_tx(struct sk_buff *skb, struct net_device *dev); static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs); static void netdev_error(struct net_device *dev, int intr_status); -static void netdev_rx(struct net_device *dev); +static int natsemi_poll(struct net_device *dev, int *budget); +static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do); static void netdev_tx_done(struct net_device *dev); static int natsemi_change_mtu(struct net_device *dev, int new_mtu); #ifdef CONFIG_NET_POLL_CONTROLLER @@ -776,6 +774,18 @@ static inline void __iomem *ns_ioaddr(struct net_device *dev) return (void __iomem *) dev->base_addr; } +static inline void natsemi_irq_enable(struct net_device *dev) +{ + writel(1, ns_ioaddr(dev) + IntrEnable); + readl(ns_ioaddr(dev) + IntrEnable); +} + +static inline void natsemi_irq_disable(struct net_device *dev) +{ + writel(0, ns_ioaddr(dev) + IntrEnable); + readl(ns_ioaddr(dev) + IntrEnable); +} + static void move_int_phy(struct net_device *dev, int addr) { struct netdev_private *np = netdev_priv(dev); @@ -879,6 +889,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, spin_lock_init(&np->lock); np->msg_enable = (debug >= 0) ? (1<hands_off = 0; + np->intr_status = 0; /* Initial port: * - If the nic was configured to use an external phy and if find_mii @@ -932,6 +943,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, dev->do_ioctl = &netdev_ioctl; dev->tx_timeout = &tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + dev->poll = natsemi_poll; + dev->weight = 64; + #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = &natsemi_poll_controller; #endif @@ -2158,68 +2172,92 @@ static void netdev_tx_done(struct net_device *dev) } } -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ +/* The interrupt handler doesn't actually handle interrupts itself, it + * schedules a NAPI poll if there is anything to do. */ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) { struct net_device *dev = dev_instance; struct netdev_private *np = netdev_priv(dev); void __iomem * ioaddr = ns_ioaddr(dev); - int boguscnt = max_interrupt_work; - unsigned int handled = 0; if (np->hands_off) return IRQ_NONE; - do { - /* Reading automatically acknowledges all int sources. */ - u32 intr_status = readl(ioaddr + IntrStatus); + + /* Reading automatically acknowledges. */ + np->intr_status = readl(ioaddr + IntrStatus); - if (netif_msg_intr(np)) - printk(KERN_DEBUG - "%s: Interrupt, status %#08x, mask %#08x.\n", - dev->name, intr_status, - readl(ioaddr + IntrMask)); + if (netif_msg_intr(np)) + printk(KERN_DEBUG + "%s: Interrupt, status %#08x, mask %#08x.\n", + dev->name, np->intr_status, + readl(ioaddr + IntrMask)); - if (intr_status == 0) - break; - handled = 1; + if (!np->intr_status) + return IRQ_NONE; - if (intr_status & - (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | - IntrRxErr | IntrRxOverrun)) { - netdev_rx(dev); - } + prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]); + + if (netif_rx_schedule_prep(dev)) { + /* Disable interrupts and register for poll */ + natsemi_irq_disable(dev); + __netif_rx_schedule(dev); + } + return IRQ_HANDLED; +} + +/* This is the NAPI poll routine. As well as the standard RX handling + * it also handles all other interrupts that the chip might raise. + */ +static int natsemi_poll(struct net_device *dev, int *budget) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem * ioaddr = ns_ioaddr(dev); - if (intr_status & - (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr)) { + int work_to_do = min(*budget, dev->quota); + int work_done = 0; + + do { + if (np->intr_status & + (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr)) { spin_lock(&np->lock); netdev_tx_done(dev); spin_unlock(&np->lock); } /* Abnormal error summary/uncommon events handlers. */ - if (intr_status & IntrAbnormalSummary) - netdev_error(dev, intr_status); - - if (--boguscnt < 0) { - if (netif_msg_intr(np)) - printk(KERN_WARNING - "%s: Too much work at interrupt, " - "status=%#08x.\n", - dev->name, intr_status); - break; + if (np->intr_status & IntrAbnormalSummary) + netdev_error(dev, np->intr_status); + + if (np->intr_status & + (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | + IntrRxErr | IntrRxOverrun)) { + netdev_rx(dev, &work_done, work_to_do); } - } while (1); + + *budget -= work_done; + dev->quota -= work_done; - if (netif_msg_intr(np)) - printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name); + if (work_done >= work_to_do) + return 1; + + np->intr_status = readl(ioaddr + IntrStatus); + } while (np->intr_status); - return IRQ_RETVAL(handled); + netif_rx_complete(dev); + + /* Reenable interrupts providing nothing is trying to shut + * the chip down. */ + spin_lock(&np->lock); + if (!np->hands_off && netif_running(dev)) + natsemi_irq_enable(dev); + spin_unlock(&np->lock); + + return 0; } /* This routine is logically part of the interrupt handler, but separated for clarity and better register allocation. */ -static void netdev_rx(struct net_device *dev) +static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do) { struct netdev_private *np = netdev_priv(dev); int entry = np->cur_rx % RX_RING_SIZE; @@ -2237,6 +2275,12 @@ static void netdev_rx(struct net_device *dev) entry, desc_status); if (--boguscnt < 0) break; + + if (*work_done >= work_to_do) + break; + + (*work_done)++; + pkt_len = (desc_status & DescSizeMask) - 4; if ((desc_status&(DescMore|DescPktOK|DescRxLong)) != DescPktOK){ if (desc_status & DescMore) { @@ -2293,7 +2337,7 @@ static void netdev_rx(struct net_device *dev) np->rx_skbuff[entry] = NULL; } skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); + netif_receive_skb(skb); dev->last_rx = jiffies; np->stats.rx_packets++; np->stats.rx_bytes += pkt_len; @@ -3074,9 +3118,7 @@ static int netdev_close(struct net_device *dev) del_timer_sync(&np->timer); disable_irq(dev->irq); spin_lock_irq(&np->lock); - /* Disable interrupts, and flush posted writes */ - writel(0, ioaddr + IntrEnable); - readl(ioaddr + IntrEnable); + natsemi_irq_disable(dev); np->hands_off = 1; spin_unlock_irq(&np->lock); enable_irq(dev->irq); @@ -3158,6 +3200,9 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev) * * netdev_timer: timer stopped by natsemi_suspend. * * intr_handler: doesn't acquire the spinlock. suspend calls * disable_irq() to enforce synchronization. + * * natsemi_poll: checks before reenabling interrupts. suspend + * sets hands_off, disables interrupts and then waits with + * netif_poll_disable(). * * Interrupts must be disabled, otherwise hands_off can cause irq storms. */ @@ -3183,6 +3228,8 @@ static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state) spin_unlock_irq(&np->lock); enable_irq(dev->irq); + netif_poll_disable(dev); + /* Update the error counts. */ __get_stats(dev); @@ -3235,6 +3282,7 @@ static int natsemi_resume (struct pci_dev *pdev) mod_timer(&np->timer, jiffies + 1*HZ); } netif_device_attach(dev); + netif_poll_enable(dev); out: rtnl_unlock(); return 0; -- cgit v1.2.3-59-g8ed1b From e72fd96e8ee3ff4dd80757172a4fe49bd92fea9c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Feb 2006 00:00:02 +0000 Subject: [PATCH] natsemi: NAPI and a bugfix As documented in National application note 1287 the RX state machine on the natsemi chip can lock up under some conditions (mostly related to heavy load). When this happens a series of bogus packets are reported by the chip including some oversized frames prior to the final lockup. This patch implements the fix from the application note: when an oversized packet is reported it resets the RX state machine, dropping any currently pending packets. Signed-off-by: Mark Brown Signed-off-by: Jeff Garzik --- drivers/net/natsemi.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'drivers') diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index e363f9bb35ea..8d4999837b65 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -1498,6 +1498,31 @@ static void natsemi_reset(struct net_device *dev) writel(rfcr, ioaddr + RxFilterAddr); } +static void reset_rx(struct net_device *dev) +{ + int i; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = ns_ioaddr(dev); + + np->intr_status &= ~RxResetDone; + + writel(RxReset, ioaddr + ChipCmd); + + for (i=0;iintr_status |= readl(ioaddr + IntrStatus); + if (np->intr_status & RxResetDone) + break; + udelay(15); + } + if (i==NATSEMI_HW_TIMEOUT) { + printk(KERN_WARNING "%s: RX reset did not complete in %d usec.\n", + dev->name, i*15); + } else if (netif_msg_hw(np)) { + printk(KERN_WARNING "%s: RX reset took %d usec.\n", + dev->name, i*15); + } +} + static void natsemi_reload_eeprom(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); @@ -2292,6 +2317,23 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do) "status %#08x.\n", dev->name, np->cur_rx, desc_status); np->stats.rx_length_errors++; + + /* The RX state machine has probably + * locked up beneath us. Follow the + * reset procedure documented in + * AN-1287. */ + + spin_lock_irq(&np->lock); + reset_rx(dev); + reinit_rx(dev); + writel(np->ring_dma, ioaddr + RxRingPtr); + check_link(dev); + spin_unlock_irq(&np->lock); + + /* We'll enable RX on exit from this + * function. */ + break; + } else { /* There was an error. */ np->stats.rx_errors++; -- cgit v1.2.3-59-g8ed1b From ad8c48ad3bbef078616ed4d2652d362dfd962f09 Mon Sep 17 00:00:00 2001 From: "Catalin(ux aka Dino) BOIE" Date: Sat, 4 Mar 2006 12:18:59 -0500 Subject: Fix io ordering problems in e100 Checking e100.c code against Documentation/io_ordering.txt I found the following problem: spin_lock_irq... write spin-unlock e100_write_flush The attached patch fix the code like this: spin_lock_irq... write e100_write_flush spin-unlock Signed-off-by: Catalin BOIE Signed-off-by: Jeff Garzik --- drivers/net/e100.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 24253c807e55..ed13f72ef8ef 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -598,8 +598,8 @@ static void e100_enable_irq(struct nic *nic) spin_lock_irqsave(&nic->cmd_lock, flags); writeb(irq_mask_none, &nic->csr->scb.cmd_hi); - spin_unlock_irqrestore(&nic->cmd_lock, flags); e100_write_flush(nic); + spin_unlock_irqrestore(&nic->cmd_lock, flags); } static void e100_disable_irq(struct nic *nic) @@ -608,8 +608,8 @@ static void e100_disable_irq(struct nic *nic) spin_lock_irqsave(&nic->cmd_lock, flags); writeb(irq_mask_all, &nic->csr->scb.cmd_hi); - spin_unlock_irqrestore(&nic->cmd_lock, flags); e100_write_flush(nic); + spin_unlock_irqrestore(&nic->cmd_lock, flags); } static void e100_hw_reset(struct nic *nic) @@ -1582,8 +1582,8 @@ static void e100_watchdog(unsigned long data) * interrupt mask bit and the SW Interrupt generation bit */ spin_lock_irq(&nic->cmd_lock); writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); - spin_unlock_irq(&nic->cmd_lock); e100_write_flush(nic); + spin_unlock_irq(&nic->cmd_lock); e100_update_stats(nic); e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); -- cgit v1.2.3-59-g8ed1b From e1fd263c772e89706dee28aa794399ac4bd6b9c1 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Sat, 4 Mar 2006 15:36:21 +0000 Subject: [PATCH] sata_promise: Support FastTrak TX4300/TX4310 This patch adds support for the Promise FastTrak TX4300/TX4310 4-port PCI SATA controllers based on the PDC40719 chip. Signed-off-by: Daniel Drake Signed-off-by: Jeff Garzik --- drivers/scsi/sata_promise.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index ba2b7a0983db..84cb3940ad88 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -255,6 +255,8 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { board_20319 }, { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20319 }, + { PCI_VENDOR_ID_PROMISE, 0x3515, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_20319 }, { PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20319 }, { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- cgit v1.2.3-59-g8ed1b From 219e621443a1d0bba2a6d15cbc9a1181892c6d79 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 14:28:51 +0900 Subject: [PATCH] ata_piix: rename PIIX_FLAG_IGN_PRESENT to PIIX_FLAG_IGNORE_PCS Rename PIIX_FLAG_IGN_PRESENT to PIIX_FLAG_IGNORE_PCS as Jeff requested. Signed-off-by: Tejun Heo Cc: Jeff Garzik Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 72e38e6ea756..9327b62f97de 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -101,7 +101,7 @@ enum { ICH5_PCS = 0x92, /* port control and status */ PIIX_SCC = 0x0A, /* sub-class code register */ - PIIX_FLAG_IGN_PRESENT = (1 << 25), /* ignore PCS present bits */ + PIIX_FLAG_IGNORE_PCS = (1 << 25), /* ignore PCS present bits */ PIIX_FLAG_SCR = (1 << 26), /* SCR available */ PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ @@ -365,7 +365,7 @@ static struct ata_port_info piix_port_info[] = { { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGN_PRESENT, + PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -538,7 +538,7 @@ static unsigned int piix_sata_probe (struct ata_port *ap) port = map[base + i]; if (port < 0) continue; - if (ap->flags & PIIX_FLAG_IGN_PRESENT || pcs & 1 << (4 + port)) + if (ap->flags & PIIX_FLAG_IGNORE_PCS || pcs & 1 << (4 + port)) present_mask |= 1 << i; else pcs &= ~(1 << port); -- cgit v1.2.3-59-g8ed1b From 81c2af3561db54a4d3b439c84c58d8c2a469ec9b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 16:03:52 +0900 Subject: [PATCH] sata_sil: replace sil_3112_m15w board id with sil_3112 All 3112's have m15w. Replace sil_3112_m15w with sil_3112 and flag sil_3112 with SIL_FLAG_MOD15WRITE. Signed-off-by: Tejun Heo Cc: Carlos Pardo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index cdf800e3ec13..8cb662d537a3 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -53,9 +53,8 @@ enum { SIL_FLAG_MOD15WRITE = (1 << 30), sil_3112 = 0, - sil_3112_m15w = 1, - sil_3512 = 2, - sil_3114 = 3, + sil_3512 = 1, + sil_3114 = 2, SIL_FIFO_R0 = 0x40, SIL_FIFO_W0 = 0x41, @@ -90,13 +89,13 @@ static void sil_post_set_mode (struct ata_port *ap); static const struct pci_device_id sil_pci_tbl[] = { - { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, - { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, + { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 }, { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 }, - { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, - { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, - { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, + { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, { } /* terminate list */ }; @@ -179,16 +178,6 @@ static const struct ata_port_operations sil_ops = { static const struct ata_port_info sil_port_info[] = { /* sil_3112 */ - { - .sht = &sil_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = 0x3f, /* udma0-5 */ - .port_ops = &sil_ops, - }, - /* sil_3112_15w - keep it sync'd w/ sil_3112 */ { .sht = &sil_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -- cgit v1.2.3-59-g8ed1b From 9a5314432a07251c2a8d71bfc793adcf00f4122e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 16:03:52 +0900 Subject: [PATCH] sata_sil: use kzalloc Use kzalloc instead of kmalloc/memset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 8cb662d537a3..5cdcb9db3e71 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -407,13 +407,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_regions; - probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); if (probe_ent == NULL) { rc = -ENOMEM; goto err_out_regions; } - memset(probe_ent, 0, sizeof(*probe_ent)); INIT_LIST_HEAD(&probe_ent->node); probe_ent->dev = pci_dev_to_dev(pdev); probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops; -- cgit v1.2.3-59-g8ed1b From 48d4ef2a1df9867c67b515d66732ba028a73735d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 16:03:52 +0900 Subject: [PATCH] sata_sil: replace register address constants with sil_port[] entry Kill SIL_FIFO_* and SIL_IDE2_BMDMA and replace them with proper sil_port[] entry. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 5cdcb9db3e71..81bdc10a6e95 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -56,15 +56,6 @@ enum { sil_3512 = 1, sil_3114 = 2, - SIL_FIFO_R0 = 0x40, - SIL_FIFO_W0 = 0x41, - SIL_FIFO_R1 = 0x44, - SIL_FIFO_W1 = 0x45, - SIL_FIFO_R2 = 0x240, - SIL_FIFO_W2 = 0x241, - SIL_FIFO_R3 = 0x244, - SIL_FIFO_W3 = 0x245, - SIL_SYSCFG = 0x48, SIL_MASK_IDE0_INT = (1 << 22), SIL_MASK_IDE1_INT = (1 << 23), @@ -74,8 +65,6 @@ enum { SIL_MASK_4PORT = SIL_MASK_2PORT | SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT, - SIL_IDE2_BMDMA = 0x200, - SIL_INTR_STEERING = (1 << 1), SIL_QUIRK_MOD15WRITE = (1 << 0), SIL_QUIRK_UDMA5MAX = (1 << 1), @@ -217,16 +206,17 @@ 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 fifo_cfg; /* FIFO Valid Byte Count and Control */ unsigned long scr; /* SATA control register block */ unsigned long sien; /* SATA Interrupt Enable register */ unsigned long xfer_mode;/* data transfer mode register */ unsigned long sfis_cfg; /* SATA FIS reception config register */ } sil_port[] = { /* port 0 ... */ - { 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4, 0x14c }, - { 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4, 0x1cc }, - { 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4, 0x34c }, - { 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4, 0x3cc }, + { 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 }, /* ... port 3 */ }; @@ -449,19 +439,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (cls) { cls >>= 3; cls++; /* cls = (line_size/8)+1 */ - writeb(cls, mmio_base + SIL_FIFO_R0); - writeb(cls, mmio_base + SIL_FIFO_W0); - writeb(cls, mmio_base + SIL_FIFO_R1); - writeb(cls, mmio_base + SIL_FIFO_W1); - if (ent->driver_data == sil_3114) { - writeb(cls, mmio_base + SIL_FIFO_R2); - writeb(cls, mmio_base + SIL_FIFO_W2); - writeb(cls, mmio_base + SIL_FIFO_R3); - writeb(cls, mmio_base + SIL_FIFO_W3); - } + for (i = 0; i < probe_ent->n_ports; i++) + writew(cls << 8 | cls, + mmio_base + sil_port[i].fifo_cfg); } else dev_printk(KERN_WARNING, &pdev->dev, - "cache line size not set. Driver may not function\n"); + "cache line size not set. Driver may not function\n"); /* Apply R_ERR on DMA activate FIS errata workaround */ if (probe_ent->host_flags & SIL_FLAG_RERR_ON_DMA_ACT) { @@ -484,10 +467,10 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) irq_mask = SIL_MASK_4PORT; /* flip the magic "make 4 ports work" bit */ - tmp = readl(mmio_base + SIL_IDE2_BMDMA); + tmp = readl(mmio_base + sil_port[2].bmdma); if ((tmp & SIL_INTR_STEERING) == 0) writel(tmp | SIL_INTR_STEERING, - mmio_base + SIL_IDE2_BMDMA); + mmio_base + sil_port[2].bmdma); } else { irq_mask = SIL_MASK_2PORT; -- cgit v1.2.3-59-g8ed1b From e653a1e6131d0a819288a2e2de654627233604e0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 16:03:52 +0900 Subject: [PATCH] sata_sil: cosmetic flag/constant changes Collect common host flags into SIL_DFL_HOST_FLAGS and add comments to constants. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 81bdc10a6e95..4f2a67ed39d8 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -49,14 +49,30 @@ #define DRV_VERSION "0.9" enum { + /* + * host flags + */ 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, + /* + * Controller IDs + */ sil_3112 = 0, sil_3512 = 1, sil_3114 = 2, + /* + * Register offsets + */ SIL_SYSCFG = 0x48, + + /* + * Register bits + */ + /* SYSCFG */ SIL_MASK_IDE0_INT = (1 << 22), SIL_MASK_IDE1_INT = (1 << 23), SIL_MASK_IDE2_INT = (1 << 24), @@ -65,7 +81,12 @@ enum { SIL_MASK_4PORT = SIL_MASK_2PORT | SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT, + /* BMDMA/BMDMA2 */ SIL_INTR_STEERING = (1 << 1), + + /* + * Others + */ SIL_QUIRK_MOD15WRITE = (1 << 0), SIL_QUIRK_UDMA5MAX = (1 << 1), }; @@ -169,8 +190,7 @@ static const struct ata_port_info sil_port_info[] = { /* sil_3112 */ { .sht = &sil_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | SIL_FLAG_MOD15WRITE, + .host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -179,9 +199,7 @@ static const struct ata_port_info sil_port_info[] = { /* sil_3512 */ { .sht = &sil_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | - SIL_FLAG_RERR_ON_DMA_ACT, + .host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -190,9 +208,7 @@ static const struct ata_port_info sil_port_info[] = { /* sil_3114 */ { .sht = &sil_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | - SIL_FLAG_RERR_ON_DMA_ACT, + .host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ -- cgit v1.2.3-59-g8ed1b From 8ff69732d484ea9ccbf242cc49b4fe9538e64c71 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 5 Mar 2006 03:37:23 -0500 Subject: [CPUFREQ] Fix handling for CPU hotplug This patch adds proper logic to cpufreq driver in order to handle CPU Hotplug. When CPUs go on/offline, the affected CPUs data, cpufreq_policy->cpus, is not updated properly. This causes sysfs directories and symlinks to be in an incorrect state after few CPU on/offlines. Signed-off-by: Jacob Shin Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 51 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index cb7d6e0db759..aed80e6aec6d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -6,6 +6,8 @@ * * Oct 2005 - Ashok Raj * Added handling for CPU hotplug + * Feb 2006 - Jacob Shin + * Fix handling for CPU hotplug -- affected CPUs * * 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 @@ -573,8 +575,12 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) struct cpufreq_policy new_policy; struct cpufreq_policy *policy; struct freq_attr **drv_attr; + struct sys_device *cpu_sys_dev; unsigned long flags; unsigned int j; +#ifdef CONFIG_SMP + struct cpufreq_policy *managed_policy; +#endif if (cpu_is_offline(cpu)) return 0; @@ -587,8 +593,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) * CPU because it is in the same boat. */ policy = cpufreq_cpu_get(cpu); if (unlikely(policy)) { - dprintk("CPU already managed, adding link\n"); - sysfs_create_link(&sys_dev->kobj, &policy->kobj, "cpufreq"); + cpufreq_cpu_put(policy); cpufreq_debug_enable_ratelimit(); return 0; } @@ -623,6 +628,32 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) goto err_out; } +#ifdef CONFIG_SMP + for_each_cpu_mask(j, policy->cpus) { + if (cpu == j) + continue; + + /* check for existing affected CPUs. They may not be aware + * of it due to CPU Hotplug. + */ + managed_policy = cpufreq_cpu_get(j); + if (unlikely(managed_policy)) { + spin_lock_irqsave(&cpufreq_driver_lock, flags); + managed_policy->cpus = policy->cpus; + cpufreq_cpu_data[cpu] = managed_policy; + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + dprintk("CPU already managed, adding link\n"); + sysfs_create_link(&sys_dev->kobj, + &managed_policy->kobj, "cpufreq"); + + cpufreq_debug_enable_ratelimit(); + mutex_unlock(&policy->lock); + ret = 0; + goto err_out_driver_exit; /* call driver->exit() */ + } + } +#endif memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); /* prepare interface data */ @@ -650,6 +681,21 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) for_each_cpu_mask(j, policy->cpus) cpufreq_cpu_data[j] = policy; spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + + /* symlink affected CPUs */ + for_each_cpu_mask(j, policy->cpus) { + if (j == cpu) + continue; + if (!cpu_online(j)) + continue; + + dprintk("CPU already managed, adding link\n"); + cpufreq_cpu_get(cpu); + cpu_sys_dev = get_cpu_sysdev(j); + sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj, + "cpufreq"); + } + policy->governor = NULL; /* to assure that the starting sequence is * run in cpufreq_set_policy */ mutex_unlock(&policy->lock); @@ -728,6 +774,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) */ if (unlikely(cpu != data->cpu)) { dprintk("removing link\n"); + cpu_clear(cpu, data->cpus); spin_unlock_irqrestore(&cpufreq_driver_lock, flags); sysfs_remove_link(&sys_dev->kobj, "cpufreq"); cpufreq_cpu_put(data); -- cgit v1.2.3-59-g8ed1b From cdaeedae9844ec3deaafa00b7dd8c21e01368633 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 5 Mar 2006 11:42:06 +0100 Subject: [SCSI] scsi: aha152x pcmcia driver needs spi transport AHA152X PCMCIA module needs spi_print_msg. Signed-off-by: Dominik Brodowski Signed-off-by: James Bottomley --- drivers/scsi/pcmcia/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig index df52190f4d94..eac8e179cfff 100644 --- a/drivers/scsi/pcmcia/Kconfig +++ b/drivers/scsi/pcmcia/Kconfig @@ -8,6 +8,7 @@ menu "PCMCIA SCSI adapter support" config PCMCIA_AHA152X tristate "Adaptec AHA152X PCMCIA support" depends on m && !64BIT + select SCSI_SPI_ATTRS help Say Y here if you intend to attach this type of PCMCIA SCSI host adapter to your computer. -- cgit v1.2.3-59-g8ed1b From 208a9933bc7d71e7ad194a9ffbfbcd7878c48dfe Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 17:55:58 +0900 Subject: [PATCH] libata: re-initialize parameters before configuring In ata_dev_configure(), reinitialize parameters before configuring. This change is for revalidation and hotplug. As ata_dev_configure() can be entered multiple times, parameters need to be reinitialized. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b710fc480740..59828490a750 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1086,6 +1086,15 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev) DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); + /* initialize to-be-configured parameters */ + dev->flags = 0; + dev->max_sectors = 0; + dev->cdb_len = 0; + dev->n_sectors = 0; + dev->cylinders = 0; + dev->heads = 0; + dev->sectors = 0; + /* * common ATA, ATAPI feature tests */ -- cgit v1.2.3-59-g8ed1b From 4c2d721ab6413ee4ff33617ed1413458261f36ea Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 17:55:58 +0900 Subject: [PATCH] libata: add @print_info argument to ata_dev_configure() Add @print_info argument to ata_dev_configure(). Details of configured device is printed only when @pinfo_info is non-zero. This patch also reorganizes device info printing for LBA case to simplify code (necessary as @print_info adds extra nesting around it). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 54 +++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 59828490a750..d65aa86ddbb2 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1063,6 +1063,7 @@ static inline u8 ata_dev_knobble(const struct ata_port *ap, * 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 * * Configure @dev according to @dev->id. Generic and low-level * driver specific fixups are also applied. @@ -1073,7 +1074,8 @@ 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) +static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, + int print_info) { unsigned long xfer_modes; int i, rc; @@ -1120,18 +1122,24 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev) dev->n_sectors = ata_id_n_sectors(dev->id); if (ata_id_has_lba(dev->id)) { - dev->flags |= ATA_DFLAG_LBA; + const char *lba_desc; - if (ata_id_has_lba48(dev->id)) + lba_desc = "LBA"; + dev->flags |= ATA_DFLAG_LBA; + if (ata_id_has_lba48(dev->id)) { dev->flags |= ATA_DFLAG_LBA48; + lba_desc = "LBA48"; + } /* print device info to dmesg */ - printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n", - ap->id, dev->devno, - ata_id_major_version(dev->id), - ata_mode_string(xfer_modes), - (unsigned long long)dev->n_sectors, - dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA"); + 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(dev->id), + ata_mode_string(xfer_modes), + (unsigned long long)dev->n_sectors, + lba_desc); } else { /* CHS */ @@ -1148,13 +1156,14 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev) } /* print device info to dmesg */ - printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n", - ap->id, dev->devno, - ata_id_major_version(dev->id), - ata_mode_string(xfer_modes), - (unsigned long long)dev->n_sectors, - (int)dev->cylinders, (int)dev->heads, (int)dev->sectors); - + 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(dev->id), + ata_mode_string(xfer_modes), + (unsigned long long)dev->n_sectors, + dev->cylinders, dev->heads, dev->sectors); } dev->cdb_len = 16; @@ -1171,9 +1180,9 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev) dev->cdb_len = (unsigned int) rc; /* print device info to dmesg */ - printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", - ap->id, dev->devno, - ata_mode_string(xfer_modes)); + if (print_info) + printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", + ap->id, dev->devno, ata_mode_string(xfer_modes)); } ap->host->max_cmd_len = 0; @@ -1184,8 +1193,9 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev) /* limit bridge transfers to udma5, 200 sectors */ if (ata_dev_knobble(ap, dev)) { - printk(KERN_INFO "ata%u(%u): applying bridge limits\n", - ap->id, dev->devno); + if (print_info) + printk(KERN_INFO "ata%u(%u): applying bridge limits\n", + ap->id, dev->devno); ap->udma_mask &= ATA_UDMA5; dev->max_sectors = ATA_MAX_SECTORS; } @@ -1263,7 +1273,7 @@ static int ata_bus_probe(struct ata_port *ap) continue; } - if (ata_dev_configure(ap, dev)) { + if (ata_dev_configure(ap, dev, 1)) { dev->class++; /* disable device */ continue; } -- cgit v1.2.3-59-g8ed1b From 623a3128aa2b86caa8e06e762e9e444177e4fa47 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 17:55:58 +0900 Subject: [PATCH] libata: implement ata_dev_revalidate() ata_dev_revalidate() re-reads IDENTIFY PAGE of the given device and makes sure it's the same device as the configured one. Once it's verified that it's the same device, @dev is configured according to newly read IDENTIFY PAGE. Note that revalidation currently doesn't invoke transfer mode reconfiguration. Criteria for 'same device' * same class (of course) * same model string * same serial string * if ATA, same n_sectors (to catch geometry parameter changes) Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 115 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 2 + 2 files changed, 117 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d65aa86ddbb2..5d0adfa4610a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2345,6 +2345,120 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, return rc; } +/** + * 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 + * + * Compare @new_class and @new_id against @dev and determine + * whether @dev is the device indicated by @new_class and + * @new_id. + * + * LOCKING: + * None. + * + * 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) +{ + 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); + return 0; + } + + ata_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0])); + ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1])); + ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0])); + ata_id_c_string(new_id, serial[1], ATA_ID_SERNO_OFS, sizeof(serial[1])); + 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]); + 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]); + 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); + return 0; + } + + return 1; +} + +/** + * 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? + * + * Re-read IDENTIFY page and make sure @dev is still attached to + * the port. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, negative errno otherwise + */ +int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, + int post_reset) +{ + unsigned int class; + u16 *id; + int rc; + + if (!ata_dev_present(dev)) + return -ENODEV; + + class = dev->class; + id = NULL; + + /* allocate & read ID data */ + rc = ata_dev_read_id(ap, dev, &class, post_reset, &id); + if (rc) + goto fail; + + /* is the device still there? */ + if (!ata_dev_same_device(ap, dev, class, id)) { + rc = -ENODEV; + goto fail; + } + + kfree(dev->id); + dev->id = id; + + /* configure device according to the new ID */ + return ata_dev_configure(ap, dev, 0); + + fail: + printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", + ap->id, dev->devno, rc); + kfree(id); + return rc; +} + static void ata_pr_blacklisted(const struct ata_port *ap, const struct ata_device *dev) { @@ -4964,6 +5078,7 @@ 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_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_busy_sleep); diff --git a/include/linux/libata.h b/include/linux/libata.h index 86a504f0ef06..66dce58f1941 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -485,6 +485,8 @@ extern int ata_std_softreset(struct ata_port *ap, int verbose, extern int sata_std_hardreset(struct ata_port *ap, int verbose, 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 void ata_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI -- cgit v1.2.3-59-g8ed1b From 48a8a14ff1f13aa4dba3f6b4381b886727609db4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 17:55:58 +0900 Subject: [PATCH] libata: revalidate after transfer mode configuration Revalidate device after transfer mode configuration. This also makes dev->id up-to-date. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5d0adfa4610a..5dbcf0cf4a10 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1625,6 +1625,12 @@ static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) idx = ofs + dev->xfer_shift; WARN_ON(idx >= ARRAY_SIZE(xfer_mode_str)); + if (ata_dev_revalidate(ap, dev, 0)) { + printk(KERN_ERR "ata%u: failed to revalidate after set " + "xfermode, disabled\n", ap->id); + ata_port_disable(ap); + } + DPRINTK("idx=%d xfer_shift=%u, xfer_mode=0x%x, base=0x%x, offset=%d\n", idx, dev->xfer_shift, (int)dev->xfer_mode, (int)base, ofs); -- cgit v1.2.3-59-g8ed1b From fbfda6e71bbdd3b4d41a56c3f20f31762c455a5e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 23:03:42 +0900 Subject: [PATCH] sata_sil24: fix mwdma_mask setting mwdma_mask was not copied from port_info to probe_ent. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 5c5822e33a49..8fb62427be84 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -892,6 +892,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->sht = pinfo->sht; probe_ent->host_flags = pinfo->host_flags; probe_ent->pio_mask = pinfo->pio_mask; + probe_ent->mwdma_mask = pinfo->mwdma_mask; probe_ent->udma_mask = pinfo->udma_mask; probe_ent->port_ops = pinfo->port_ops; probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->host_flags); -- cgit v1.2.3-59-g8ed1b From 42ab03609cca4ef5079e248296f015650c626899 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 4 Mar 2006 09:10:18 -0600 Subject: [PATCH] convert aic94xx over to using the sas transport end device Begin introducing the concept of sas remote devices that have an rphy embedded. The first one (this) is a simple end device. All that an end device really does is have port mode page parameters contained. The next and more complex piece will be expander remote devices. Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 199 +++++++++++++++++++++++++++++++------- include/scsi/scsi_transport_sas.h | 19 ++++ 2 files changed, 184 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 434f3954aa87..5de29b941c6b 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -39,6 +39,7 @@ #define SAS_HOST_ATTRS 0 #define SAS_PORT_ATTRS 17 #define SAS_RPORT_ATTRS 7 +#define SAS_END_DEV_ATTRS 3 struct sas_internal { struct scsi_transport_template t; @@ -47,9 +48,11 @@ struct sas_internal { struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS]; struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS]; struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS]; + struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS]; struct transport_container phy_attr_cont; struct transport_container rphy_attr_cont; + struct transport_container end_dev_attr_cont; /* * The array of null terminated pointers to attributes @@ -58,6 +61,7 @@ struct sas_internal { struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1]; struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1]; struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1]; + struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1]; }; #define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t) @@ -588,6 +592,73 @@ sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", unsigned long long); sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); +/* only need 8 bytes of data plus header (4 or 8) */ +#define BUF_SIZE 64 + +int sas_read_port_mode_page(struct scsi_device *sdev) +{ + char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; + struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target); + struct sas_end_device *rdev; + struct scsi_mode_data mode_data; + int res, error; + + BUG_ON(rphy->identify.device_type != SAS_END_DEVICE); + + rdev = rphy_to_end_device(rphy); + + if (!buffer) + return -ENOMEM; + + res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, + &mode_data, NULL); + + error = -EINVAL; + if (!scsi_status_is_good(res)) + goto out; + + msdata = buffer + mode_data.header_length + + mode_data.block_descriptor_length; + + if (msdata - buffer > BUF_SIZE - 8) + goto out; + + error = 0; + + rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0; + rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5]; + rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7]; + + out: + kfree(buffer); + return error; +} +EXPORT_SYMBOL(sas_read_port_mode_page); + +#define sas_end_dev_show_simple(field, name, format_string, cast) \ +static ssize_t \ +show_sas_end_dev_##name(struct class_device *cdev, char *buf) \ +{ \ + struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ + struct sas_end_device *rdev = rphy_to_end_device(rphy); \ + \ + return snprintf(buf, 20, format_string, cast rdev->field); \ +} + +#define sas_end_dev_simple_attr(field, name, format_string, type) \ + sas_end_dev_show_simple(field, name, format_string, (type)) \ +static SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ + show_sas_end_dev_##name, NULL) + +sas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int); +sas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, + "%d\n", int); +sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, + "%d\n", int); + +static DECLARE_TRANSPORT_CLASS(sas_end_dev_class, + "sas_end_device", NULL, NULL, NULL); + static DECLARE_TRANSPORT_CLASS(sas_rphy_class, "sas_rphy", NULL, NULL, NULL); @@ -610,6 +681,31 @@ static int sas_rphy_match(struct attribute_container *cont, struct device *dev) return &i->rphy_attr_cont.ac == cont; } +static int sas_end_dev_match(struct attribute_container *cont, + struct device *dev) +{ + struct Scsi_Host *shost; + struct sas_internal *i; + struct sas_rphy *rphy; + + if (!scsi_is_sas_rphy(dev)) + return 0; + shost = dev_to_shost(dev->parent->parent); + rphy = dev_to_rphy(dev); + + if (!shost->transportt) + return 0; + if (shost->transportt->host_attrs.ac.class != + &sas_host_class.class) + return 0; + + i = to_sas_internal(shost->transportt); + return &i->end_dev_attr_cont.ac == cont && + rphy->identify.device_type == SAS_END_DEVICE && + /* FIXME: remove contained eventually */ + rphy->contained; +} + static void sas_rphy_release(struct device *dev) { struct sas_rphy *rphy = dev_to_rphy(dev); @@ -649,6 +745,40 @@ struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent) } EXPORT_SYMBOL(sas_rphy_alloc); +/** + * sas_end_device_alloc - allocate an rphy for an end device + * + * Allocates an SAS remote PHY structure, connected to @parent. + * + * Returns: + * SAS PHY allocated or %NULL if the allocation failed. + */ +struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent) +{ + struct Scsi_Host *shost = dev_to_shost(&parent->dev); + struct sas_end_device *rdev; + + rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); + if (!rdev) { + put_device(&parent->dev); + return NULL; + } + + device_initialize(&rdev->rphy.dev); + rdev->rphy.dev.parent = get_device(&parent->dev); + rdev->rphy.dev.release = sas_rphy_release; + sprintf(rdev->rphy.dev.bus_id, "rphy-%d:%d-%d", + shost->host_no, parent->port_identifier, parent->number); + rdev->rphy.identify.device_type = SAS_END_DEVICE; + /* FIXME: mark the rphy as being contained in a larger structure */ + rdev->rphy.contained = 1; + transport_setup_device(&rdev->rphy.dev); + + return &rdev->rphy; +} +EXPORT_SYMBOL(sas_end_device_alloc); + + /** * sas_rphy_add -- add a SAS remote PHY to the device hierachy * @rphy: The remote PHY to be added @@ -807,51 +937,35 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, * Setup / Teardown code */ -#define SETUP_RPORT_ATTRIBUTE(field) \ - i->private_rphy_attrs[count] = class_device_attr_##field; \ - i->private_rphy_attrs[count].attr.mode = S_IRUGO; \ - i->private_rphy_attrs[count].store = NULL; \ - i->rphy_attrs[count] = &i->private_rphy_attrs[count]; \ - count++ +#define SETUP_TEMPLATE(attrb, field, perm, test) \ + i->private_##attrb[count] = class_device_attr_##field; \ + i->private_##attrb[count].attr.mode = perm; \ + i->private_##attrb[count].store = NULL; \ + i->attrb[count] = &i->private_##attrb[count]; \ + if (test) \ + count++ + + +#define SETUP_RPORT_ATTRIBUTE(field) \ + SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) #define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func) \ - i->private_rphy_attrs[count] = class_device_attr_##field; \ - i->private_rphy_attrs[count].attr.mode = S_IRUGO; \ - i->private_rphy_attrs[count].store = NULL; \ - i->rphy_attrs[count] = &i->private_rphy_attrs[count]; \ - if (i->f->func) \ - count++ + SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func) #define SETUP_PORT_ATTRIBUTE(field) \ - i->private_phy_attrs[count] = class_device_attr_##field; \ - i->private_phy_attrs[count].attr.mode = S_IRUGO; \ - i->private_phy_attrs[count].store = NULL; \ - i->phy_attrs[count] = &i->private_phy_attrs[count]; \ - count++ + SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) #define SETUP_OPTIONAL_PORT_ATTRIBUTE(field, func) \ - i->private_phy_attrs[count] = class_device_attr_##field; \ - i->private_phy_attrs[count].attr.mode = S_IRUGO; \ - i->private_phy_attrs[count].store = NULL; \ - i->phy_attrs[count] = &i->private_phy_attrs[count]; \ - if (i->f->func) \ - count++ + SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) #define SETUP_PORT_ATTRIBUTE_WRONLY(field) \ - i->private_phy_attrs[count] = class_device_attr_##field; \ - i->private_phy_attrs[count].attr.mode = S_IWUGO; \ - i->private_phy_attrs[count].show = NULL; \ - i->phy_attrs[count] = &i->private_phy_attrs[count]; \ - count++ + SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1) #define SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(field, func) \ - i->private_phy_attrs[count] = class_device_attr_##field; \ - i->private_phy_attrs[count].attr.mode = S_IWUGO; \ - i->private_phy_attrs[count].show = NULL; \ - i->phy_attrs[count] = &i->private_phy_attrs[count]; \ - if (i->f->func) \ - count++ + SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func) +#define SETUP_END_DEV_ATTRIBUTE(field) \ + SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) /** * sas_attach_transport -- instantiate SAS transport template @@ -885,6 +999,11 @@ sas_attach_transport(struct sas_function_template *ft) i->rphy_attr_cont.ac.match = sas_rphy_match; transport_container_register(&i->rphy_attr_cont); + i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class; + i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0]; + i->end_dev_attr_cont.ac.match = sas_end_dev_match; + transport_container_register(&i->end_dev_attr_cont); + i->f = ft; count = 0; @@ -923,6 +1042,12 @@ sas_attach_transport(struct sas_function_template *ft) get_bay_identifier); i->rphy_attrs[count] = NULL; + count = 0; + SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning); + SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout); + SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); + i->end_dev_attrs[count] = NULL; + return &i->t; } EXPORT_SYMBOL(sas_attach_transport); @@ -956,9 +1081,14 @@ static __init int sas_transport_init(void) error = transport_class_register(&sas_rphy_class); if (error) goto out_unregister_phy; + error = transport_class_register(&sas_end_dev_class); + if (error) + goto out_unregister_rphy; return 0; + out_unregister_rphy: + transport_class_unregister(&sas_rphy_class); out_unregister_phy: transport_class_unregister(&sas_phy_class); out_unregister_transport: @@ -973,6 +1103,7 @@ static void __exit sas_transport_exit(void) transport_class_unregister(&sas_host_class); transport_class_unregister(&sas_phy_class); transport_class_unregister(&sas_rphy_class); + transport_class_unregister(&sas_end_dev_class); } MODULE_AUTHOR("Christoph Hellwig"); diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 95e2132d485e..8fded431cf46 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -82,6 +82,10 @@ struct sas_rphy { struct sas_identify identify; struct list_head list; u32 scsi_target_id; + /* temporary expedient: mark the rphy as being contained + * within a type specific rphy + * FIXME: pull this out when everything uses the containers */ + unsigned contained:1; }; #define dev_to_rphy(d) \ @@ -90,6 +94,19 @@ struct sas_rphy { dev_to_rphy((cdev)->dev) #define rphy_to_shost(rphy) \ dev_to_shost((rphy)->dev.parent) +#define target_to_rphy(targ) \ + dev_to_rphy((targ)->dev.parent) + +struct sas_end_device { + struct sas_rphy rphy; + /* flags */ + unsigned ready_led_meaning:1; + /* parameters */ + u16 I_T_nexus_loss_timeout; + u16 initiator_response_timeout; +}; +#define rphy_to_end_device(r) \ + container_of((r), struct sas_end_device, rphy) /* The functions by which the transport class and the driver communicate */ @@ -110,6 +127,7 @@ extern void sas_phy_delete(struct sas_phy *); extern int scsi_is_sas_phy(const struct device *); extern struct sas_rphy *sas_rphy_alloc(struct sas_phy *); +extern struct sas_rphy *sas_end_device_alloc(struct sas_phy *); void sas_rphy_free(struct sas_rphy *); extern int sas_rphy_add(struct sas_rphy *); extern void sas_rphy_delete(struct sas_rphy *); @@ -118,5 +136,6 @@ extern int scsi_is_sas_rphy(const struct device *); extern struct scsi_transport_template * sas_attach_transport(struct sas_function_template *); extern void sas_release_transport(struct scsi_transport_template *); +int sas_read_port_mode_page(struct scsi_device *); #endif /* SCSI_TRANSPORT_SAS_H */ -- cgit v1.2.3-59-g8ed1b From 74b72a59b8d42d31aa6ffac8f10ca7a784be392c Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 22:33:04 -0500 Subject: [PATCH] lpfc 8.1.3: Derive supported speeds from LMT field in the READ_CONFIG Derive supported speeds from LMT field in the READ_CONFIG Driver was keying off internal cores. Use what the firmware reports instead. Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_ct.c | 24 +++--- drivers/scsi/lpfc/lpfc_hw.h | 14 ++-- drivers/scsi/lpfc/lpfc_init.c | 182 +++++++++++++++++++++++++----------------- 3 files changed, 126 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 0c982bbc4c77..f3b280313a74 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1014,19 +1014,19 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode) ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size); ae->ad.bits.AttrType = be16_to_cpu(SUPPORTED_SPEED); ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4); - if (FC_JEDEC_ID(vp->rev.biuRev) == VIPER_JEDEC_ID) + + ae->un.SupportSpeed = 0; + if (phba->lmt & LMT_10Gb) ae->un.SupportSpeed = HBA_PORTSPEED_10GBIT; - else if (FC_JEDEC_ID(vp->rev.biuRev) == HELIOS_JEDEC_ID) - ae->un.SupportSpeed = HBA_PORTSPEED_4GBIT; - else if ((FC_JEDEC_ID(vp->rev.biuRev) == - CENTAUR_2G_JEDEC_ID) - || (FC_JEDEC_ID(vp->rev.biuRev) == - PEGASUS_JEDEC_ID) - || (FC_JEDEC_ID(vp->rev.biuRev) == - THOR_JEDEC_ID)) - ae->un.SupportSpeed = HBA_PORTSPEED_2GBIT; - else - ae->un.SupportSpeed = HBA_PORTSPEED_1GBIT; + if (phba->lmt & LMT_8Gb) + ae->un.SupportSpeed |= HBA_PORTSPEED_8GBIT; + if (phba->lmt & LMT_4Gb) + ae->un.SupportSpeed |= HBA_PORTSPEED_4GBIT; + if (phba->lmt & LMT_2Gb) + ae->un.SupportSpeed |= HBA_PORTSPEED_2GBIT; + if (phba->lmt & LMT_1Gb) + ae->un.SupportSpeed |= HBA_PORTSPEED_1GBIT; + pab->ab.EntryCnt++; size += FOURBYTES + 4; diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 98d39cea7954..54d04188f7cc 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1711,13 +1711,13 @@ typedef struct { uint32_t rttov; uint32_t altov; uint32_t lmt; -#define LMT_RESERVED 0x0 /* Not used */ -#define LMT_266_10bit 0x1 /* 265.625 Mbaud 10 bit iface */ -#define LMT_532_10bit 0x2 /* 531.25 Mbaud 10 bit iface */ -#define LMT_1063_20bit 0x3 /* 1062.5 Mbaud 20 bit iface */ -#define LMT_1063_10bit 0x4 /* 1062.5 Mbaud 10 bit iface */ -#define LMT_2125_10bit 0x8 /* 2125 Mbaud 10 bit iface */ -#define LMT_4250_10bit 0x40 /* 4250 Mbaud 10 bit iface */ +#define LMT_RESERVED 0x000 /* Not used */ +#define LMT_1Gb 0x004 +#define LMT_2Gb 0x008 +#define LMT_4Gb 0x040 +#define LMT_8Gb 0x080 +#define LMT_10Gb 0x100 + uint32_t rsvd2; uint32_t rsvd3; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 391ca50293f2..5fd98a345347 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -42,7 +42,7 @@ #include "lpfc_crtn.h" #include "lpfc_version.h" -static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *); +static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int); static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *); static int lpfc_post_rcv_buf(struct lpfc_hba *); @@ -161,9 +161,6 @@ lpfc_config_port_prep(struct lpfc_hba * phba) memcpy(phba->RandomData, (char *)&mb->un.varWords[24], sizeof (phba->RandomData)); - /* Get the default values for Model Name and Description */ - lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc); - /* Get adapter VPD information */ pmb->context2 = kmalloc(DMP_RSP_SIZE, GFP_KERNEL); if (!pmb->context2) @@ -182,16 +179,15 @@ lpfc_config_port_prep(struct lpfc_hba * phba) "mbxCmd x%x DUMP VPD, mbxStatus x%x\n", phba->brd_no, mb->mbxCommand, mb->mbxStatus); - kfree(lpfc_vpd_data); - lpfc_vpd_data = NULL; - break; + mb->un.varDmp.word_cnt = 0; } - + if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset) + mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset; lpfc_sli_pcimem_bcopy(pmb->context2, lpfc_vpd_data + offset, mb->un.varDmp.word_cnt); offset += mb->un.varDmp.word_cnt; - } while (mb->un.varDmp.word_cnt); - lpfc_parse_vpd(phba, lpfc_vpd_data); + } while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE); + lpfc_parse_vpd(phba, lpfc_vpd_data, offset); kfree(lpfc_vpd_data); out_free_context2: @@ -327,13 +323,22 @@ lpfc_config_port_post(struct lpfc_hba * phba) mb->un.varRdConfig.max_xri + 1; phba->lmt = mb->un.varRdConfig.lmt; - /* HBA is not 4GB capable, or HBA is not 2GB capable, - don't let link speed ask for it */ - if ((((phba->lmt & LMT_4250_10bit) != LMT_4250_10bit) && - (phba->cfg_link_speed > LINK_SPEED_2G)) || - (((phba->lmt & LMT_2125_10bit) != LMT_2125_10bit) && - (phba->cfg_link_speed > LINK_SPEED_1G))) { - /* Reset link speed to auto. 1G/2GB HBA cfg'd for 4G */ + + /* Get the default values for Model Name and Description */ + lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc); + + if ((phba->cfg_link_speed > LINK_SPEED_10G) + || ((phba->cfg_link_speed == LINK_SPEED_1G) + && !(phba->lmt & LMT_1Gb)) + || ((phba->cfg_link_speed == LINK_SPEED_2G) + && !(phba->lmt & LMT_2Gb)) + || ((phba->cfg_link_speed == LINK_SPEED_4G) + && !(phba->lmt & LMT_4Gb)) + || ((phba->cfg_link_speed == LINK_SPEED_8G) + && !(phba->lmt & LMT_8Gb)) + || ((phba->cfg_link_speed == LINK_SPEED_10G) + && !(phba->lmt & LMT_10Gb))) { + /* Reset link speed to auto */ lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT, @@ -647,7 +652,7 @@ lpfc_handle_latt_err_exit: /* */ /************************************************************************/ static int -lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd) +lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len) { uint8_t lenlo, lenhi; uint32_t Length; @@ -666,9 +671,10 @@ lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd) phba->brd_no, (uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2], (uint32_t) vpd[3]); - do { + while (!finished && (index < (len - 4))) { switch (vpd[index]) { case 0x82: + case 0x91: index += 1; lenlo = vpd[index]; index += 1; @@ -684,7 +690,8 @@ lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd) lenhi = vpd[index]; index += 1; Length = ((((unsigned short)lenhi) << 8) + lenlo); - + if (Length > len - index) + Length = len - index; while (Length > 0) { /* Look for Serial Number */ if ((vpd[index] == 'S') && (vpd[index+1] == 'N')) { @@ -778,7 +785,7 @@ lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd) index ++; break; } - } while (!finished && (index < 108)); + } return(1); } @@ -790,124 +797,153 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) uint16_t dev_id = phba->pcidev->device; uint16_t dev_subid = phba->pcidev->subsystem_device; uint8_t hdrtype = phba->pcidev->hdr_type; - char *model_str = ""; + int max_speed; + char * ports = (hdrtype == 0x80) ? "2-port " : ""; + struct { + char * name; + int max_speed; + char * ports; + char * bus; + } m; + + if (mdp && mdp[0] != '\0' + && descp && descp[0] != '\0') + return; + + if (phba->lmt & LMT_10Gb) + max_speed = 10; + else if (phba->lmt & LMT_8Gb) + max_speed = 8; + else if (phba->lmt & LMT_4Gb) + max_speed = 4; + else if (phba->lmt & LMT_2Gb) + max_speed = 2; + else + max_speed = 1; vp = &phba->vpd; switch (dev_id) { case PCI_DEVICE_ID_FIREFLY: - model_str = "LP6000 1Gb PCI"; + m = (typeof(m)){"LP6000", max_speed, "", "PCI"}; break; case PCI_DEVICE_ID_SUPERFLY: if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3) - model_str = "LP7000 1Gb PCI"; + m = (typeof(m)){"LP7000", max_speed, "", "PCI"}; else - model_str = "LP7000E 1Gb PCI"; + m = (typeof(m)){"LP7000E", max_speed, "", "PCI"}; break; case PCI_DEVICE_ID_DRAGONFLY: - model_str = "LP8000 1Gb PCI"; + m = (typeof(m)){"LP8000", max_speed, "", "PCI"}; break; case PCI_DEVICE_ID_CENTAUR: if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) - model_str = "LP9002 2Gb PCI"; + m = (typeof(m)){"LP9002", max_speed, "", "PCI"}; else - model_str = "LP9000 1Gb PCI"; + m = (typeof(m)){"LP9000", max_speed, "", "PCI"}; break; case PCI_DEVICE_ID_RFLY: - model_str = "LP952 2Gb PCI"; + m = (typeof(m)){"LP952", max_speed, "", "PCI"}; break; case PCI_DEVICE_ID_PEGASUS: - model_str = "LP9802 2Gb PCI-X"; + m = (typeof(m)){"LP9802", max_speed, "", "PCI-X"}; break; case PCI_DEVICE_ID_THOR: if (hdrtype == 0x80) - model_str = "LP10000DC 2Gb 2-port PCI-X"; + m = (typeof(m)){"LP10000DC", + max_speed, ports, "PCI-X"}; else - model_str = "LP10000 2Gb PCI-X"; + m = (typeof(m)){"LP10000", + max_speed, ports, "PCI-X"}; break; case PCI_DEVICE_ID_VIPER: - model_str = "LPX1000 10Gb PCI-X"; + m = (typeof(m)){"LPX1000", max_speed, "", "PCI-X"}; break; case PCI_DEVICE_ID_PFLY: - model_str = "LP982 2Gb PCI-X"; + m = (typeof(m)){"LP982", max_speed, "", "PCI-X"}; break; case PCI_DEVICE_ID_TFLY: if (hdrtype == 0x80) - model_str = "LP1050DC 2Gb 2-port PCI-X"; + m = (typeof(m)){"LP1050DC", max_speed, ports, "PCI-X"}; else - model_str = "LP1050 2Gb PCI-X"; + m = (typeof(m)){"LP1050", max_speed, ports, "PCI-X"}; break; case PCI_DEVICE_ID_HELIOS: if (hdrtype == 0x80) - model_str = "LP11002 4Gb 2-port PCI-X2"; + m = (typeof(m)){"LP11002", max_speed, ports, "PCI-X2"}; else - model_str = "LP11000 4Gb PCI-X2"; + m = (typeof(m)){"LP11000", max_speed, ports, "PCI-X2"}; break; case PCI_DEVICE_ID_HELIOS_SCSP: - model_str = "LP11000-SP 4Gb PCI-X2"; + m = (typeof(m)){"LP11000-SP", max_speed, ports, "PCI-X2"}; break; case PCI_DEVICE_ID_HELIOS_DCSP: - model_str = "LP11002-SP 4Gb 2-port PCI-X2"; + m = (typeof(m)){"LP11002-SP", max_speed, ports, "PCI-X2"}; break; case PCI_DEVICE_ID_NEPTUNE: if (hdrtype == 0x80) - model_str = "LPe1002 4Gb 2-port"; + m = (typeof(m)){"LPe1002", max_speed, ports, "PCIe"}; else - model_str = "LPe1000 4Gb PCIe"; + m = (typeof(m)){"LPe1000", max_speed, ports, "PCIe"}; break; case PCI_DEVICE_ID_NEPTUNE_SCSP: - model_str = "LPe1000-SP 4Gb PCIe"; + m = (typeof(m)){"LPe1000-SP", max_speed, ports, "PCIe"}; break; case PCI_DEVICE_ID_NEPTUNE_DCSP: - model_str = "LPe1002-SP 4Gb 2-port PCIe"; + m = (typeof(m)){"LPe1002-SP", max_speed, ports, "PCIe"}; break; case PCI_DEVICE_ID_BMID: - model_str = "LP1150 4Gb PCI-X2"; + m = (typeof(m)){"LP1150", max_speed, ports, "PCI-X2"}; break; case PCI_DEVICE_ID_BSMB: - model_str = "LP111 4Gb PCI-X2"; + m = (typeof(m)){"LP111", max_speed, ports, "PCI-X2"}; break; case PCI_DEVICE_ID_ZEPHYR: if (hdrtype == 0x80) - model_str = "LPe11002 4Gb 2-port PCIe"; + m = (typeof(m)){"LPe11002", max_speed, ports, "PCIe"}; else - model_str = "LPe11000 4Gb PCIe"; + m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"}; break; case PCI_DEVICE_ID_ZEPHYR_SCSP: - model_str = "LPe11000-SP 4Gb PCIe"; + m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"}; break; case PCI_DEVICE_ID_ZEPHYR_DCSP: - model_str = "LPe11002-SP 4Gb 2-port PCIe"; + m = (typeof(m)){"LPe11002-SP", max_speed, ports, "PCIe"}; break; case PCI_DEVICE_ID_ZMID: - model_str = "LPe1150 4Gb PCIe"; + m = (typeof(m)){"LPe1150", max_speed, ports, "PCIe"}; break; case PCI_DEVICE_ID_ZSMB: - model_str = "LPe111 4Gb PCIe"; + m = (typeof(m)){"LPe111", max_speed, ports, "PCIe"}; break; case PCI_DEVICE_ID_LP101: - model_str = "LP101 2Gb PCI-X"; + m = (typeof(m)){"LP101", max_speed, ports, "PCI-X"}; break; case PCI_DEVICE_ID_LP10000S: - model_str = "LP10000-S 2Gb PCI"; + m = (typeof(m)){"LP10000-S", max_speed, ports, "PCI"}; break; case PCI_DEVICE_ID_LP11000S: case PCI_DEVICE_ID_LPE11000S: switch (dev_subid) { case PCI_SUBSYSTEM_ID_LP11000S: - model_str = "LP11002-S 4Gb PCI-X2"; + m = (typeof(m)){"LP11000-S", max_speed, + ports, "PCI-X2"}; break; case PCI_SUBSYSTEM_ID_LP11002S: - model_str = "LP11000-S 4Gb 2-port PCI-X2"; + m = (typeof(m)){"LP11002-S", max_speed, + ports, "PCI-X2"}; break; case PCI_SUBSYSTEM_ID_LPE11000S: - model_str = "LPe11002-S 4Gb PCIe"; + m = (typeof(m)){"LPe11000-S", max_speed, + ports, "PCIe"}; break; case PCI_SUBSYSTEM_ID_LPE11002S: - model_str = "LPe11002-S 4Gb 2-port PCIe"; + m = (typeof(m)){"LPe11002-S", max_speed, + ports, "PCIe"}; break; case PCI_SUBSYSTEM_ID_LPE11010S: - model_str = "LPe11010-S 4Gb 10-port PCIe"; + m = (typeof(m)){"LPe11010-S", max_speed, + "10-port ", "PCIe"}; break; default: break; @@ -916,10 +952,13 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) default: break; } - if (mdp) - sscanf(model_str, "%s", mdp); - if (descp) - sprintf(descp, "Emulex %s Fibre Channel Adapter", model_str); + + if (mdp && mdp[0] == '\0') + snprintf(mdp, 79,"%s", m.name); + if (descp && descp[0] == '\0') + snprintf(descp, 255, + "Emulex %s %dGb %s%s Fibre Channel Adapter", + m.name, m.max_speed, m.ports, m.bus); } /**************************************************/ @@ -1627,21 +1666,14 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(host)); fc_host_supported_speeds(host) = 0; - switch (FC_JEDEC_ID(phba->vpd.rev.biuRev)) { - case VIPER_JEDEC_ID: + if (phba->lmt & LMT_10Gb) fc_host_supported_speeds(host) |= FC_PORTSPEED_10GBIT; - break; - case HELIOS_JEDEC_ID: + if (phba->lmt & LMT_4Gb) fc_host_supported_speeds(host) |= FC_PORTSPEED_4GBIT; - /* Fall through */ - case CENTAUR_2G_JEDEC_ID: - case PEGASUS_JEDEC_ID: - case THOR_JEDEC_ID: + if (phba->lmt & LMT_2Gb) fc_host_supported_speeds(host) |= FC_PORTSPEED_2GBIT; - /* Fall through */ - default: - fc_host_supported_speeds(host) = FC_PORTSPEED_1GBIT; - } + if (phba->lmt & LMT_1Gb) + fc_host_supported_speeds(host) |= FC_PORTSPEED_1GBIT; fc_host_maxframe_size(host) = ((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) | -- cgit v1.2.3-59-g8ed1b From 719396b48ce6310ab43d7432b6d7f2a330a831b3 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 22:33:05 -0500 Subject: [PATCH] lpfc 8.1.3: PCI hrd_type should be obtained with pci_read_config_byte() macro PCI hrd_type should be obtained with pci_read_config_byte() macro Driver keys off of this field to report the proper adapter type. The pci subsystem explicitly clears the multiport bit in the copy of the field given the driver. Thus, to properly name the card, obtain it from config space. Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_init.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 5fd98a345347..71d2c8d3b001 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -796,9 +796,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) lpfc_vpd_t *vp; uint16_t dev_id = phba->pcidev->device; uint16_t dev_subid = phba->pcidev->subsystem_device; - uint8_t hdrtype = phba->pcidev->hdr_type; + uint8_t hdrtype; int max_speed; - char * ports = (hdrtype == 0x80) ? "2-port " : ""; + char * ports; struct { char * name; int max_speed; @@ -806,6 +806,8 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) char * bus; } m; + pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype); + ports = (hdrtype == 0x80) ? "2-port " : ""; if (mdp && mdp[0] != '\0' && descp && descp[0] != '\0') return; -- cgit v1.2.3-59-g8ed1b From 56178645c2686a7ef630e1b23b81d40dcfb553e6 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 22:33:06 -0500 Subject: [PATCH] lpfc 8.1.3: Remove unused MBhostaddr from lpfc_sli structure Remove unused MBhostaddr from lpfc_sli structure Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_sli.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 6d357d9e48f7..a52d6c6cf083 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -199,8 +199,6 @@ struct lpfc_sli { struct timer_list mbox_tmo; /* Hold clk to timeout active mbox cmd */ - uint32_t *MBhostaddr; /* virtual address for mbox cmds */ - #define LPFC_IOCBQ_LOOKUP_INCREMENT 1024 struct lpfc_iocbq ** iocbq_lookup; /* array to lookup IOCB by IOTAG */ size_t iocbq_lookup_len; /* current lengs of the array */ -- cgit v1.2.3-59-g8ed1b From cf5bf97e1d28651fd689be9c974b2318ac262f2d Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 22:33:08 -0500 Subject: [PATCH] lpfc 8.1.3: Fix performance when using multiple SLI rings Fix performance when using multiple SLI rings Currently the driver allocates all of its SLI command and response ring entries to one primary ring. Other rings get little, or no, resources. Allow more resources to be given to ring 1 Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_attr.c | 10 ++++++++++ drivers/scsi/lpfc/lpfc_sli.c | 42 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 50 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index c4cca9124f45..2f67a8a92599 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -293,6 +293,7 @@ struct lpfc_hba { uint32_t cfg_link_speed; uint32_t cfg_cr_delay; uint32_t cfg_cr_count; + uint32_t cfg_multi_ring_support; uint32_t cfg_fdmi_on; uint32_t cfg_discovery_threads; uint32_t cfg_max_luns; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index ab49379b6abe..2558156f064d 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -670,6 +670,14 @@ LPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an " LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an " "interrupt response is generated"); +/* +# lpfc_multi_ring_support: Determines how many rings to spread available +# cmd/rsp IOCB entries across. +# Value range is [1,2]. Default value is 1. +*/ +LPFC_ATTR_R(multi_ring_support, 1, 1, 2, "Determines number of primary " + "SLI rings to spread IOCB entries across"); + /* # lpfc_fdmi_on: controls FDMI support. # 0 = no FDMI support @@ -726,6 +734,7 @@ struct class_device_attribute *lpfc_host_attrs[] = { &class_device_attr_lpfc_link_speed, &class_device_attr_lpfc_cr_delay, &class_device_attr_lpfc_cr_count, + &class_device_attr_lpfc_multi_ring_support, &class_device_attr_lpfc_fdmi_on, &class_device_attr_lpfc_max_luns, &class_device_attr_nport_evt_cnt, @@ -1440,6 +1449,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_log_verbose_init(phba, lpfc_log_verbose); lpfc_cr_delay_init(phba, lpfc_cr_delay); lpfc_cr_count_init(phba, lpfc_cr_count); + lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support); lpfc_lun_queue_depth_init(phba, lpfc_lun_queue_depth); lpfc_fcp_class_init(phba, lpfc_fcp_class); lpfc_use_adisc_init(phba, lpfc_use_adisc); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index d6ffe26ae123..d08fd89dd44f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -766,7 +766,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /* unSolicited Responses */ if (pring->prt[0].profile) { - (pring->prt[0].lpfc_sli_rcv_unsol_event) (phba, pring, saveq); + if (pring->prt[0].lpfc_sli_rcv_unsol_event) + (pring->prt[0].lpfc_sli_rcv_unsol_event) (phba, pring, + saveq); match = 1; } else { /* We must search, based on rctl / type @@ -777,8 +779,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, Rctl) && (pring->prt[i]. type == Type)) { - (pring->prt[i].lpfc_sli_rcv_unsol_event) - (phba, pring, saveq); + if (pring->prt[i].lpfc_sli_rcv_unsol_event) + (pring->prt[i].lpfc_sli_rcv_unsol_event) + (phba, pring, saveq); match = 1; break; } @@ -2377,6 +2380,37 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, return IOCB_BUSY; } +static int +lpfc_extra_ring_setup( struct lpfc_hba *phba) +{ + struct lpfc_sli *psli; + struct lpfc_sli_ring *pring; + + psli = &phba->sli; + + /* Adjust cmd/rsp ring iocb entries more evenly */ + pring = &psli->ring[psli->fcp_ring]; + pring->numCiocb -= SLI2_IOCB_CMD_R1XTRA_ENTRIES; + pring->numRiocb -= SLI2_IOCB_RSP_R1XTRA_ENTRIES; + pring->numCiocb -= SLI2_IOCB_CMD_R3XTRA_ENTRIES; + pring->numRiocb -= SLI2_IOCB_RSP_R3XTRA_ENTRIES; + + pring = &psli->ring[1]; + pring->numCiocb += SLI2_IOCB_CMD_R1XTRA_ENTRIES; + pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES; + pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES; + pring->numRiocb += SLI2_IOCB_RSP_R3XTRA_ENTRIES; + + /* Setup default profile for this ring */ + pring->iotag_max = 4096; + pring->num_mask = 1; + pring->prt[0].profile = 0; /* Mask 0 */ + pring->prt[0].rctl = FC_UNSOL_DATA; + pring->prt[0].type = 5; + pring->prt[0].lpfc_sli_rcv_unsol_event = NULL; + return 0; +} + int lpfc_sli_setup(struct lpfc_hba *phba) { @@ -2460,6 +2494,8 @@ lpfc_sli_setup(struct lpfc_hba *phba) "SLI2 SLIM Data: x%x x%x\n", phba->brd_no, totiocb, MAX_SLI2_IOCB); } + if (phba->cfg_multi_ring_support == 2) + lpfc_extra_ring_setup(phba); return 0; } -- cgit v1.2.3-59-g8ed1b From 5fe9f5119378e75986ad90c783a7e085bf67703a Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 22:33:09 -0500 Subject: [PATCH] lpfc 8.1.3: Fix deadlock in lpfc_fdmi_tmo_handler Fix deadlock in lpfc_fdmi_tmo_handler lpfc_fdmi_tmo_handler was calling lpfc_fdmi_cmd with the host_lock held. lpfc_fdmi_cmd assumes the host_lock is released as it calls functions that acquire the host_lock. lpfc_fdmi_tmo_handler acquired the host_lock to protect access to work_hba_events. This was already checked in the worker thread so we can remove that code completely and remove access to the host_lock. Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_ct.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index f3b280313a74..b65ee57af53e 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1166,11 +1166,6 @@ lpfc_fdmi_tmo_handler(struct lpfc_hba *phba) { struct lpfc_nodelist *ndlp; - spin_lock_irq(phba->host->host_lock); - if (!(phba->work_hba_events & WORKER_FDMI_TMO)) { - spin_unlock_irq(phba->host->host_lock); - return; - } ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, FDMI_DID); if (ndlp) { if (system_utsname.nodename[0] != '\0') { @@ -1179,7 +1174,6 @@ lpfc_fdmi_tmo_handler(struct lpfc_hba *phba) mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60); } } - spin_unlock_irq(phba->host->host_lock); return; } -- cgit v1.2.3-59-g8ed1b From 66a9ed66000d186933892ca5121e68a071d624ac Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 22:33:10 -0500 Subject: [PATCH] lpfc 8.1.3: Protect NPL lists with host lock Protect NPL lists with host lock Symptoms: lpfc_findnode_rpi and lpfc_findnode_did can be called outside of the discovery thread context. We have to iterate through the NPL lists under the host lock and all add/del operations on those lists have to be done under host lock. Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 3 ++- drivers/scsi/lpfc/lpfc_hbadisc.c | 53 ++++++++++++++++++---------------------- 2 files changed, 26 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 6e1a5162851c..090f4609d2af 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -3144,8 +3144,9 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { struct lpfc_nodelist *ndlp; - + spin_unlock_irq(phba->host->host_lock); ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext); + spin_lock_irq(phba->host->host_lock); remote_ID = ndlp->nlp_DID; if (cmd->un.elsreq64.bdl.ulpIoTag32) { lpfc_sli_issue_abort_iotag32(phba, diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index aa58ff0e3218..e7664a6bd251 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1097,6 +1097,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) if (list != NLP_NO_LIST) return 0; + spin_lock_irq(phba->host->host_lock); switch (nlp->nlp_flag & NLP_LIST_MASK) { case NLP_NO_LIST: /* Not on any list */ break; @@ -1123,10 +1124,8 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) case NLP_UNMAPPED_LIST: phba->fc_unmap_cnt--; list_del(&nlp->nlp_listp); - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag &= ~NLP_TGT_NO_SCSIID; nlp->nlp_type &= ~NLP_FC_NODE; - spin_unlock_irq(phba->host->host_lock); phba->nport_event_cnt++; if (nlp->rport) rport_del = unmapped; @@ -1144,20 +1143,18 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) /* Stop delay tmo if taking node off NPR list */ if ((nlp->nlp_flag & NLP_DELAY_TMO) && (list != NLP_NPR_LIST)) { - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag &= ~NLP_DELAY_TMO; - spin_unlock_irq(phba->host->host_lock); nlp->nlp_last_elscmd = 0; + spin_unlock_irq(phba->host->host_lock); del_timer_sync(&nlp->nlp_delayfunc); + spin_lock_irq(phba->host->host_lock); if (!list_empty(&nlp->els_retry_evt.evt_listp)) list_del_init(&nlp->els_retry_evt.evt_listp); } break; } - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag &= ~NLP_LIST_MASK; - spin_unlock_irq(phba->host->host_lock); /* Add NPort to list */ lpfc_printf_log(phba, @@ -1169,46 +1166,38 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) switch (list) { case NLP_NO_LIST: /* No list, just remove it */ + spin_unlock_irq(phba->host->host_lock); lpfc_nlp_remove(phba, nlp); + spin_lock_irq(phba->host->host_lock); /* as node removed - stop further transport calls */ rport_del = none; break; case NLP_UNUSED_LIST: - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; - spin_unlock_irq(phba->host->host_lock); /* Put it at the end of the unused list */ list_add_tail(&nlp->nlp_listp, &phba->fc_unused_list); phba->fc_unused_cnt++; break; case NLP_PLOGI_LIST: - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; - spin_unlock_irq(phba->host->host_lock); /* Put it at the end of the plogi list */ list_add_tail(&nlp->nlp_listp, &phba->fc_plogi_list); phba->fc_plogi_cnt++; break; case NLP_ADISC_LIST: - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; - spin_unlock_irq(phba->host->host_lock); /* Put it at the end of the adisc list */ list_add_tail(&nlp->nlp_listp, &phba->fc_adisc_list); phba->fc_adisc_cnt++; break; case NLP_REGLOGIN_LIST: - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; - spin_unlock_irq(phba->host->host_lock); /* Put it at the end of the reglogin list */ list_add_tail(&nlp->nlp_listp, &phba->fc_reglogin_list); phba->fc_reglogin_cnt++; break; case NLP_PRLI_LIST: - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; - spin_unlock_irq(phba->host->host_lock); /* Put it at the end of the prli list */ list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list); phba->fc_prli_cnt++; @@ -1217,19 +1206,17 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) rport_add = unmapped; /* ensure all vestiges of "mapped" significance are gone */ nlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; - spin_unlock_irq(phba->host->host_lock); /* Put it at the end of the unmap list */ list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list); phba->fc_unmap_cnt++; phba->nport_event_cnt++; /* stop nodev tmo if running */ if (nlp->nlp_flag & NLP_NODEV_TMO) { - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag &= ~NLP_NODEV_TMO; spin_unlock_irq(phba->host->host_lock); del_timer_sync(&nlp->nlp_tmofunc); + spin_lock_irq(phba->host->host_lock); if (!list_empty(&nlp->nodev_timeout_evt.evt_listp)) list_del_init(&nlp->nodev_timeout_evt. evt_listp); @@ -1239,9 +1226,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) break; case NLP_MAPPED_LIST: rport_add = mapped; - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; - spin_unlock_irq(phba->host->host_lock); /* Put it at the end of the map list */ list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list); phba->fc_map_cnt++; @@ -1249,7 +1234,9 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) /* stop nodev tmo if running */ if (nlp->nlp_flag & NLP_NODEV_TMO) { nlp->nlp_flag &= ~NLP_NODEV_TMO; + spin_unlock_irq(phba->host->host_lock); del_timer_sync(&nlp->nlp_tmofunc); + spin_lock_irq(phba->host->host_lock); if (!list_empty(&nlp->nodev_timeout_evt.evt_listp)) list_del_init(&nlp->nodev_timeout_evt. evt_listp); @@ -1257,9 +1244,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) } break; case NLP_NPR_LIST: - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= list; - spin_unlock_irq(phba->host->host_lock); /* Put it at the end of the npr list */ list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list); phba->fc_npr_cnt++; @@ -1268,15 +1253,15 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) mod_timer(&nlp->nlp_tmofunc, jiffies + HZ * phba->cfg_nodev_tmo); - spin_lock_irq(phba->host->host_lock); nlp->nlp_flag |= NLP_NODEV_TMO; nlp->nlp_flag &= ~NLP_RCV_PLOGI; - spin_unlock_irq(phba->host->host_lock); break; case NLP_JUST_DQ: break; } + spin_unlock_irq(phba->host->host_lock); + /* * We make all the calls into the transport after we have * moved the node between lists. This so that we don't @@ -1681,6 +1666,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) struct lpfc_nodelist *ndlp, *next_ndlp; uint32_t data1; + spin_lock_irq(phba->host->host_lock); if (order & NLP_SEARCH_UNMAPPED) { list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list, nlp_listp) { @@ -1696,6 +1682,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); + spin_unlock_irq(phba->host->host_lock); return ndlp; } } @@ -1717,6 +1704,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); + spin_unlock_irq(phba->host->host_lock); return ndlp; } } @@ -1739,6 +1727,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); + spin_unlock_irq(phba->host->host_lock); return ndlp; } } @@ -1783,6 +1772,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); + spin_unlock_irq(phba->host->host_lock); return ndlp; } } @@ -1827,6 +1817,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); + spin_unlock_irq(phba->host->host_lock); return ndlp; } } @@ -1849,11 +1840,14 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); + spin_unlock_irq(phba->host->host_lock); return ndlp; } } } + spin_unlock_irq(phba->host->host_lock); + /* FIND node did NOT FOUND */ lpfc_printf_log(phba, KERN_INFO, @@ -1895,9 +1889,7 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) */ if (ndlp->nlp_flag & NLP_DELAY_TMO) { ndlp->nlp_flag &= ~NLP_DELAY_TMO; - spin_unlock_irq(phba->host->host_lock); del_timer_sync(&ndlp->nlp_delayfunc); - spin_lock_irq(phba->host->host_lock); if (!list_empty(&ndlp->els_retry_evt. evt_listp)) list_del_init(&ndlp->els_retry_evt. @@ -2513,11 +2505,14 @@ lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) &phba->fc_reglogin_list}; int i; + spin_lock_irq(phba->host->host_lock); for (i = 0; i < ARRAY_SIZE(lists); i++ ) list_for_each_entry(ndlp, lists[i], nlp_listp) - if (ndlp->nlp_rpi == rpi) + if (ndlp->nlp_rpi == rpi) { + spin_unlock_irq(phba->host->host_lock); return ndlp; - + } + spin_unlock_irq(phba->host->host_lock); return NULL; } -- cgit v1.2.3-59-g8ed1b From b808608bd7afdf1b0a2eb096ff2b5b93781fdbb6 Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 22:33:12 -0500 Subject: [PATCH] lpfc 8.1.3: Fix polling mode panic Fix polling mode panic Cause: Race between interrupt driven and polling path in harvesting iocbs from the response ring. Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_scsi.c | 5 +++++ drivers/scsi/lpfc/lpfc_sli.c | 17 +++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 094f18f1fa05..f93799873721 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -467,6 +467,11 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, sdev = cmd->device; cmd->scsi_done(cmd); + if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { + lpfc_release_scsi_buf(phba, lpfc_cmd); + return; + } + if (!result && pnode != NULL && ((jiffies - pnode->last_ramp_up_time) > LPFC_Q_RAMP_UP_INTERVAL * HZ) && diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index d08fd89dd44f..764aadbec71b 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1154,12 +1154,17 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring, &rspiocbq); if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) { - spin_unlock_irqrestore( - phba->host->host_lock, iflag); - (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, - &rspiocbq); - spin_lock_irqsave(phba->host->host_lock, - iflag); + if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { + (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, + &rspiocbq); + } else { + spin_unlock_irqrestore( + phba->host->host_lock, iflag); + (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, + &rspiocbq); + spin_lock_irqsave(phba->host->host_lock, + iflag); + } } break; default: -- cgit v1.2.3-59-g8ed1b From b2e977ca364764dabb091c360f329868b7e3f29b Mon Sep 17 00:00:00 2001 From: Jamie Wellnitz Date: Tue, 28 Feb 2006 22:33:15 -0500 Subject: [PATCH] lpfc 8.1.3: Change version number to 8.1.3 Change version number to 8.1.3 Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index dad013c771a1..9d9d91cbefb1 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.1.2" +#define LPFC_DRIVER_VERSION "8.1.3" #define LPFC_DRIVER_NAME "lpfc" -- cgit v1.2.3-59-g8ed1b From 286fc8f8ea7ef58b54f150fc900ce019af483e89 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 6 Mar 2006 10:20:56 -0600 Subject: [SCSI] lpfc: minor syntax fixes Stop gcc complaining about undefined variables Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_init.c | 2 ++ drivers/scsi/lpfc/lpfc_scsi.h | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 71d2c8d3b001..a2e15436730e 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -948,10 +948,12 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) "10-port ", "PCIe"}; break; default: + m = (typeof(m)){ 0 }; break; } break; default: + m = (typeof(m)){ 0 }; break; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h index acd64c49e849..cdcd2535803f 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.h +++ b/drivers/scsi/lpfc/lpfc_scsi.h @@ -23,10 +23,13 @@ struct lpfc_hba; #define list_remove_head(list, entry, type, member) \ + do { \ + entry = NULL; \ if (!list_empty(list)) { \ entry = list_entry((list)->next, type, member); \ list_del_init(&entry->member); \ - } + } \ + } while(0) #define list_get_first(list, type, member) \ (list_empty(list)) ? NULL : \ -- cgit v1.2.3-59-g8ed1b From 5e6575c051f3313feb9fe1aad61263b3560df5cc Mon Sep 17 00:00:00 2001 From: Willem Riede Date: Sat, 11 Feb 2006 14:46:56 -0500 Subject: [SCSI] osst: changes required to move forward to block request On 02/07/2006 04:12:55 AM, Christoph Hellwig wrote: > On Mon, Feb 06, 2006 at 08:02:21PM -0500, Willem Riede wrote: > > > But I will certainly help retire scsi_request. And anything else that is > > needed to keep up with proper kernel style. Let me know what those are, if > > you would? I'll start looking at how st has changed, and will be back with > > any questions I may have. > > right now the above is the most urgent bit. What would be nice but not > required is a conversion to the sense handling helpers, similar to what > st got (aka using the *normalize_sense functions and then dealing with the > parsed sense buffer instead of the raw sense data) Ok, so here is my first take at satisfying this request. Be warned, that beyond compiling, and checking that the new module doesn't immediately blow up, there hasn't yet been a lot of testing. But this should allow you to comment on the changes, and move forward with dropping scsi_request from the kernel code. Signed-off-by: Willem Riede Signed-off-by: James Bottomley --- drivers/scsi/osst.c | 503 +++++++++++++++++++++++++++++----------------------- drivers/scsi/osst.h | 12 +- 2 files changed, 290 insertions(+), 225 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index b9f6084fdd9e..00f3edc2417f 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -13,7 +13,7 @@ order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale. - Copyright 1992 - 2002 Kai Makisara / 2000 - 2004 Willem Riede + Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede email osst@riede.org $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $ @@ -24,7 +24,7 @@ */ static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $"; -static const char * osst_version = "0.99.3"; +static const char * osst_version = "0.99.4"; /* The "failure to reconnect" firmware bug */ #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/ @@ -69,7 +69,6 @@ static const char * osst_version = "0.99.3"; #include #include #include -#include #define ST_KILOBYTE 1024 @@ -176,16 +175,16 @@ static struct scsi_driver osst_template = { } }; -static int osst_int_ioctl(struct osst_tape *STp, struct scsi_request ** aSRpnt, +static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt, unsigned int cmd_in, unsigned long arg); -static int osst_set_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt, int frame, int skip); +static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip); -static int osst_get_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt); +static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt); -static int osst_flush_write_buffer(struct osst_tape *STp, struct scsi_request ** aSRpnt); +static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt); -static int osst_write_error_recovery(struct osst_tape * STp, struct scsi_request ** aSRpnt, int pending); +static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending); static inline char *tape_name(struct osst_tape *tape) { @@ -194,52 +193,84 @@ static inline char *tape_name(struct osst_tape *tape) /* Routines that handle the interaction with mid-layer SCSI routines */ + +/* Normalize Sense */ +static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s) +{ + const u8 *ucp; + const u8 *sense = SRpnt->sense; + + s->have_sense = scsi_normalize_sense(SRpnt->sense, + SCSI_SENSE_BUFFERSIZE, &s->sense_hdr); + s->flags = 0; + + if (s->have_sense) { + s->deferred = 0; + s->remainder_valid = + scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64); + switch (sense[0] & 0x7f) { + case 0x71: + s->deferred = 1; + case 0x70: + s->fixed_format = 1; + s->flags = sense[2] & 0xe0; + break; + case 0x73: + s->deferred = 1; + case 0x72: + s->fixed_format = 0; + ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4); + s->flags = ucp ? (ucp[3] & 0xe0) : 0; + break; + } + } +} + /* Convert the result to success code */ -static int osst_chk_result(struct osst_tape * STp, struct scsi_request * SRpnt) +static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt) { char *name = tape_name(STp); - int result = SRpnt->sr_result; - unsigned char * sense = SRpnt->sr_sense_buffer, scode; + int result = SRpnt->result; + u8 * sense = SRpnt->sense, scode; #if DEBUG const char *stp; #endif + struct st_cmdstatus *cmdstatp; - if (!result) { - sense[0] = 0; /* We don't have sense data if this byte is zero */ + if (!result) return 0; - } - if ((driver_byte(result) & DRIVER_MASK) == DRIVER_SENSE) - scode = sense[2] & 0x0f; - else { - sense[0] = 0; /* We don't have sense data if this byte is zero */ + + cmdstatp = &STp->buffer->cmdstat; + osst_analyze_sense(SRpnt, cmdstatp); + + if (cmdstatp->have_sense) + scode = STp->buffer->cmdstat.sense_hdr.sense_key; + else scode = 0; - } #if DEBUG if (debugging) { - printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n", + printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n", name, result, - SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2], - SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5], - SRpnt->sr_bufflen); + SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2], + SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]); if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n", name, scode, sense[12], sense[13]); - if (driver_byte(result) & DRIVER_SENSE) - scsi_print_req_sense("osst ", SRpnt); + if (cmdstatp->have_sense) + __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE); } else #endif - if (!(driver_byte(result) & DRIVER_SENSE) || - ((sense[0] & 0x70) == 0x70 && + if (cmdstatp->have_sense && ( scode != NO_SENSE && scode != RECOVERED_ERROR && /* scode != UNIT_ATTENTION && */ scode != BLANK_CHECK && scode != VOLUME_OVERFLOW && - SRpnt->sr_cmnd[0] != MODE_SENSE && - SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */ - if (driver_byte(result) & DRIVER_SENSE) { + SRpnt->cmd[0] != MODE_SENSE && + SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */ + if (cmdstatp->have_sense) { printk(KERN_WARNING "%s:W: Command with sense data:\n", name); - scsi_print_req_sense("osst:", SRpnt); + __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE); } else { static int notyetprinted = 1; @@ -259,15 +290,14 @@ static int osst_chk_result(struct osst_tape * STp, struct scsi_request * SRpnt) } STp->pos_unknown |= STp->device->was_reset; - if ((sense[0] & 0x70) == 0x70 && - scode == RECOVERED_ERROR) { + if (cmdstatp->have_sense && scode == RECOVERED_ERROR) { STp->recover_count++; STp->recover_erreg++; #if DEBUG if (debugging) { - if (SRpnt->sr_cmnd[0] == READ_6) + if (SRpnt->cmd[0] == READ_6) stp = "read"; - else if (SRpnt->sr_cmnd[0] == WRITE_6) + else if (SRpnt->cmd[0] == WRITE_6) stp = "write"; else stp = "ioctl"; @@ -283,74 +313,99 @@ static int osst_chk_result(struct osst_tape * STp, struct scsi_request * SRpnt) /* Wakeup from interrupt */ -static void osst_sleep_done (struct scsi_cmnd * SCpnt) +static void osst_sleep_done(void *data, char *sense, int result, int resid) { - struct osst_tape * STp = container_of(SCpnt->request->rq_disk->private_data, struct osst_tape, driver); - - if ((STp->buffer)->writing && - (SCpnt->sense_buffer[0] & 0x70) == 0x70 && - (SCpnt->sense_buffer[2] & 0x40)) { - /* EOM at write-behind, has all been written? */ - if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW) - STp->buffer->midlevel_result = SCpnt->result; /* Error */ - else - STp->buffer->midlevel_result = INT_MAX; /* OK */ - } - else - STp->buffer->midlevel_result = SCpnt->result; - SCpnt->request->rq_status = RQ_SCSI_DONE; - STp->buffer->last_SRpnt = SCpnt->sc_request; + struct osst_request *SRpnt = data; + struct osst_tape *STp = SRpnt->stp; + memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE); + STp->buffer->cmdstat.midlevel_result = SRpnt->result = result; #if DEBUG STp->write_pending = 0; #endif - complete(SCpnt->request->waiting); + if (SRpnt->waiting) + complete(SRpnt->waiting); +} + +/* osst_request memory management */ +static struct osst_request *osst_allocate_request(void) +{ + return kzalloc(sizeof(struct osst_request), GFP_KERNEL); } +static void osst_release_request(struct osst_request *streq) +{ + kfree(streq); +} /* Do the scsi command. Waits until command performed if do_wait is true. Otherwise osst_write_behind_check() is used to check that the command has finished. */ -static struct scsi_request * osst_do_scsi(struct scsi_request *SRpnt, struct osst_tape *STp, +static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp, unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait) { unsigned char *bp; + unsigned short use_sg; #ifdef OSST_INJECT_ERRORS static int inject = 0; static int repeat = 0; #endif + struct completion *waiting; + + /* if async, make sure there's no command outstanding */ + if (!do_wait && ((STp->buffer)->last_SRpnt)) { + printk(KERN_ERR "%s: Async command already active.\n", + tape_name(STp)); + if (signal_pending(current)) + (STp->buffer)->syscall_result = (-EINTR); + else + (STp->buffer)->syscall_result = (-EBUSY); + return NULL; + } + if (SRpnt == NULL) { - if ((SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC)) == NULL) { - printk(KERN_ERR "%s:E: Can't get SCSI request.\n", tape_name(STp)); + SRpnt = osst_allocate_request(); + if (SRpnt == NULL) { + printk(KERN_ERR "%s: Can't allocate SCSI request.\n", + tape_name(STp)); if (signal_pending(current)) (STp->buffer)->syscall_result = (-EINTR); else (STp->buffer)->syscall_result = (-EBUSY); return NULL; } + SRpnt->stp = STp; } - init_completion(&STp->wait); - SRpnt->sr_use_sg = (bytes > (STp->buffer)->sg[0].length) ? - (STp->buffer)->use_sg : 0; - if (SRpnt->sr_use_sg) { + /* If async IO, set last_SRpnt. This ptr tells write_behind_check + which IO is outstanding. It's nulled out when the IO completes. */ + if (!do_wait) + (STp->buffer)->last_SRpnt = SRpnt; + + waiting = &STp->wait; + init_completion(waiting); + SRpnt->waiting = waiting; + + use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0; + if (use_sg) { bp = (char *)&(STp->buffer->sg[0]); - if (STp->buffer->sg_segs < SRpnt->sr_use_sg) - SRpnt->sr_use_sg = STp->buffer->sg_segs; + if (STp->buffer->sg_segs < use_sg) + use_sg = STp->buffer->sg_segs; } else bp = (STp->buffer)->b_data; - SRpnt->sr_data_direction = direction; - SRpnt->sr_cmd_len = 0; - SRpnt->sr_request->waiting = &(STp->wait); - SRpnt->sr_request->rq_status = RQ_SCSI_BUSY; - SRpnt->sr_request->rq_disk = STp->drive; - scsi_do_req(SRpnt, (void *)cmd, bp, bytes, osst_sleep_done, timeout, retries); + memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd)); + STp->buffer->cmdstat.have_sense = 0; + STp->buffer->syscall_result = 0; - if (do_wait) { - wait_for_completion(SRpnt->sr_request->waiting); - SRpnt->sr_request->waiting = NULL; + if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes, + use_sg, timeout, retries, SRpnt, osst_sleep_done, GFP_KERNEL)) + /* could not allocate the buffer or request was too large */ + (STp->buffer)->syscall_result = (-EBUSY); + else if (do_wait) { + wait_for_completion(waiting); + SRpnt->waiting = NULL; STp->buffer->syscall_result = osst_chk_result(STp, SRpnt); #ifdef OSST_INJECT_ERRORS if (STp->buffer->syscall_result == 0 && @@ -383,21 +438,22 @@ static void osst_write_behind_check(struct osst_tape *STp) STp->nbr_finished++; #endif wait_for_completion(&(STp->wait)); - (STp->buffer)->last_SRpnt->sr_request->waiting = NULL; + STp->buffer->last_SRpnt->waiting = NULL; STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt); - if ((STp->buffer)->syscall_result) - (STp->buffer)->syscall_result = - osst_write_error_recovery(STp, &((STp->buffer)->last_SRpnt), 1); + if (STp->buffer->syscall_result) + STp->buffer->syscall_result = + osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1); else STp->first_frame_position++; - scsi_release_request((STp->buffer)->last_SRpnt); + osst_release_request(STp->buffer->last_SRpnt); if (STbuffer->writing < STbuffer->buffer_bytes) printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n"); + STbuffer->last_SRpnt = NULL; STbuffer->buffer_bytes -= STbuffer->writing; STbuffer->writing = 0; @@ -606,11 +662,11 @@ err_out: /* * Wait for the unit to become Ready */ -static int osst_wait_ready(struct osst_tape * STp, struct scsi_request ** aSRpnt, +static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout, int initial_delay) { unsigned char cmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt; + struct osst_request * SRpnt; unsigned long startwait = jiffies; #if DEBUG int dbg = debugging; @@ -630,10 +686,10 @@ static int osst_wait_ready(struct osst_tape * STp, struct scsi_request ** aSRpnt if (!SRpnt) return (-EBUSY); while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) && - (( SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 && - (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8) ) || - ( SRpnt->sr_sense_buffer[2] == 6 && SRpnt->sr_sense_buffer[12] == 0x28 && - SRpnt->sr_sense_buffer[13] == 0 ) )) { + (( SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 && + (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8) ) || + ( SRpnt->sense[2] == 6 && SRpnt->sense[12] == 0x28 && + SRpnt->sense[13] == 0 ) )) { #if DEBUG if (debugging) { printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name); @@ -657,8 +713,8 @@ static int osst_wait_ready(struct osst_tape * STp, struct scsi_request ** aSRpnt #if DEBUG printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name); printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name, - STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2], - SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]); + STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2], + SRpnt->sense[12], SRpnt->sense[13]); #endif return (-EIO); } @@ -671,10 +727,10 @@ static int osst_wait_ready(struct osst_tape * STp, struct scsi_request ** aSRpnt /* * Wait for a tape to be inserted in the unit */ -static int osst_wait_for_medium(struct osst_tape * STp, struct scsi_request ** aSRpnt, unsigned timeout) +static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout) { unsigned char cmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt; + struct osst_request * SRpnt; unsigned long startwait = jiffies; #if DEBUG int dbg = debugging; @@ -691,8 +747,7 @@ static int osst_wait_for_medium(struct osst_tape * STp, struct scsi_request ** a if (!SRpnt) return (-EBUSY); while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) && - SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 0x3a && - SRpnt->sr_sense_buffer[13] == 0 ) { + SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0 ) { #if DEBUG if (debugging) { printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name); @@ -711,13 +766,13 @@ static int osst_wait_for_medium(struct osst_tape * STp, struct scsi_request ** a #if DEBUG debugging = dbg; #endif - if ( STp->buffer->syscall_result && SRpnt->sr_sense_buffer[2] != 2 && - SRpnt->sr_sense_buffer[12] != 4 && SRpnt->sr_sense_buffer[13] == 1) { + if ( STp->buffer->syscall_result && SRpnt->sense[2] != 2 && + SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) { #if DEBUG printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name); printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name, - STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2], - SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]); + STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2], + SRpnt->sense[12], SRpnt->sense[13]); #endif return 0; } @@ -727,7 +782,7 @@ static int osst_wait_for_medium(struct osst_tape * STp, struct scsi_request ** a return 1; } -static int osst_position_tape_and_confirm(struct osst_tape * STp, struct scsi_request ** aSRpnt, int frame) +static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame) { int retval; @@ -741,10 +796,10 @@ static int osst_position_tape_and_confirm(struct osst_tape * STp, struct scsi_re /* * Wait for write(s) to complete */ -static int osst_flush_drive_buffer(struct osst_tape * STp, struct scsi_request ** aSRpnt) +static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt) { unsigned char cmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt; + struct osst_request * SRpnt; int result = 0; int delay = OSST_WAIT_WRITE_COMPLETE; #if DEBUG @@ -761,8 +816,8 @@ static int osst_flush_drive_buffer(struct osst_tape * STp, struct scsi_request * *aSRpnt = SRpnt; if (!SRpnt) return (-EBUSY); if (STp->buffer->syscall_result) { - if ((SRpnt->sr_sense_buffer[2] & 0x0f) == 2 && SRpnt->sr_sense_buffer[12] == 4) { - if (SRpnt->sr_sense_buffer[13] == 8) { + if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) { + if (SRpnt->sense[13] == 8) { delay = OSST_WAIT_LONG_WRITE_COMPLETE; } } else @@ -775,7 +830,7 @@ static int osst_flush_drive_buffer(struct osst_tape * STp, struct scsi_request * } #define OSST_POLL_PER_SEC 10 -static int osst_wait_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int curr, int minlast, int to) +static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to) { unsigned long startwait = jiffies; char * name = tape_name(STp); @@ -830,9 +885,9 @@ static int osst_wait_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt return -EBUSY; } -static int osst_recover_wait_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int writing) +static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing) { - struct scsi_request * SRpnt; + struct osst_request * SRpnt; unsigned char cmd[MAX_COMMAND_SIZE]; unsigned long startwait = jiffies; int retval = 1; @@ -853,7 +908,7 @@ static int osst_recover_wait_frame(struct osst_tape * STp, struct scsi_request * while (retval && time_before (jiffies, startwait + 5*60*HZ)) { - if (STp->buffer->syscall_result && (SRpnt->sr_sense_buffer[2] & 0x0f) != 2) { + if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) { /* some failure - not just not-ready */ retval = osst_write_error_recovery(STp, aSRpnt, 0); @@ -878,9 +933,9 @@ static int osst_recover_wait_frame(struct osst_tape * STp, struct scsi_request * if (STp->buffer->syscall_result) printk(KERN_WARNING "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name, - (*aSRpnt)->sr_sense_buffer[ 2] & 0x0f, - (*aSRpnt)->sr_sense_buffer[12], - (*aSRpnt)->sr_sense_buffer[13]); + (*aSRpnt)->sense[ 2] & 0x0f, + (*aSRpnt)->sense[12], + (*aSRpnt)->sense[13]); return retval; } @@ -888,10 +943,10 @@ static int osst_recover_wait_frame(struct osst_tape * STp, struct scsi_request * /* * Read the next OnStream tape frame at the current location */ -static int osst_read_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int timeout) +static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout) { unsigned char cmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt; + struct osst_request * SRpnt; int retval = 0; #if DEBUG os_aux_t * aux = STp->buffer->aux; @@ -929,10 +984,10 @@ static int osst_read_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt if (debugging) printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", name, - SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1], - SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3], - SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5], - SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]); + SRpnt->sense[0], SRpnt->sense[1], + SRpnt->sense[2], SRpnt->sense[3], + SRpnt->sense[4], SRpnt->sense[5], + SRpnt->sense[6], SRpnt->sense[7]); #endif } else @@ -959,10 +1014,10 @@ static int osst_read_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt return (retval); } -static int osst_initiate_read(struct osst_tape * STp, struct scsi_request ** aSRpnt) +static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt) { struct st_partstat * STps = &(STp->ps[STp->partition]); - struct scsi_request * SRpnt ; + struct osst_request * SRpnt ; unsigned char cmd[MAX_COMMAND_SIZE]; int retval = 0; char * name = tape_name(STp); @@ -996,7 +1051,7 @@ static int osst_initiate_read(struct osst_tape * STp, struct scsi_request ** aSR return retval; } -static int osst_get_logical_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, +static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame_seq_number, int quiet) { struct st_partstat * STps = &(STp->ps[STp->partition]); @@ -1125,7 +1180,7 @@ static int osst_get_logical_frame(struct osst_tape * STp, struct scsi_request ** return (STps->eof); } -static int osst_seek_logical_blk(struct osst_tape * STp, struct scsi_request ** aSRpnt, int logical_blk_num) +static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num) { struct st_partstat * STps = &(STp->ps[STp->partition]); char * name = tape_name(STp); @@ -1234,7 +1289,7 @@ error: #define OSST_SECTOR_SHIFT 9 #define OSST_SECTOR_MASK 0x03F -static int osst_get_sector(struct osst_tape * STp, struct scsi_request ** aSRpnt) +static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt) { int sector; #if DEBUG @@ -1264,7 +1319,7 @@ static int osst_get_sector(struct osst_tape * STp, struct scsi_request ** aSRpnt return sector; } -static int osst_seek_sector(struct osst_tape * STp, struct scsi_request ** aSRpnt, int sector) +static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector) { struct st_partstat * STps = &(STp->ps[STp->partition]); int frame = sector >> OSST_FRAME_SHIFT, @@ -1327,10 +1382,10 @@ static int osst_seek_sector(struct osst_tape * STp, struct scsi_request ** aSRpn * Precondition for this function to work: all frames in the * drive's buffer must be of one type (DATA, MARK or EOD)! */ -static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi_request ** aSRpnt, +static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned int frame, unsigned int skip, int pending) { - struct scsi_request * SRpnt = * aSRpnt; + struct osst_request * SRpnt = * aSRpnt; unsigned char * buffer, * p; unsigned char cmd[MAX_COMMAND_SIZE]; int flag, new_frame, i; @@ -1474,8 +1529,8 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1); - if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 && - (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) { + if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 && + (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) { /* in the process of becoming ready */ msleep(100); continue; @@ -1492,17 +1547,17 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi } *aSRpnt = SRpnt; if (flag) { - if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 && - SRpnt->sr_sense_buffer[12] == 0 && - SRpnt->sr_sense_buffer[13] == 2) { + if ((SRpnt->sense[ 2] & 0x0f) == 13 && + SRpnt->sense[12] == 0 && + SRpnt->sense[13] == 2) { printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name); vfree(buffer); return (-EIO); /* hit end of tape = fail */ } - i = ((SRpnt->sr_sense_buffer[3] << 24) | - (SRpnt->sr_sense_buffer[4] << 16) | - (SRpnt->sr_sense_buffer[5] << 8) | - SRpnt->sr_sense_buffer[6] ) - new_frame; + i = ((SRpnt->sense[3] << 24) | + (SRpnt->sense[4] << 16) | + (SRpnt->sense[5] << 8) | + SRpnt->sense[6] ) - new_frame; p = &buffer[i * OS_DATA_SIZE]; #if DEBUG printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i); @@ -1525,11 +1580,11 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi return 0; } -static int osst_reposition_and_retry(struct osst_tape * STp, struct scsi_request ** aSRpnt, +static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned int frame, unsigned int skip, int pending) { unsigned char cmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt; + struct osst_request * SRpnt; char * name = tape_name(STp); int expected = 0; int attempts = 1000 / skip; @@ -1581,9 +1636,9 @@ static int osst_reposition_and_retry(struct osst_tape * STp, struct scsi_request *aSRpnt = SRpnt; if (STp->buffer->syscall_result) { /* additional write error */ - if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 && - SRpnt->sr_sense_buffer[12] == 0 && - SRpnt->sr_sense_buffer[13] == 2) { + if ((SRpnt->sense[ 2] & 0x0f) == 13 && + SRpnt->sense[12] == 0 && + SRpnt->sense[13] == 2) { printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name); @@ -1628,9 +1683,9 @@ static int osst_reposition_and_retry(struct osst_tape * STp, struct scsi_request * Error recovery algorithm for the OnStream tape. */ -static int osst_write_error_recovery(struct osst_tape * STp, struct scsi_request ** aSRpnt, int pending) +static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending) { - struct scsi_request * SRpnt = * aSRpnt; + struct osst_request * SRpnt = * aSRpnt; struct st_partstat * STps = & STp->ps[STp->partition]; char * name = tape_name(STp); int retval = 0; @@ -1639,20 +1694,20 @@ static int osst_write_error_recovery(struct osst_tape * STp, struct scsi_request rw_state = STps->rw; - if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) != 3 - || SRpnt->sr_sense_buffer[12] != 12 - || SRpnt->sr_sense_buffer[13] != 0) { + if ((SRpnt->sense[ 2] & 0x0f) != 3 + || SRpnt->sense[12] != 12 + || SRpnt->sense[13] != 0) { #if DEBUG printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name, - SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]); + SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]); #endif return (-EIO); } - frame = (SRpnt->sr_sense_buffer[3] << 24) | - (SRpnt->sr_sense_buffer[4] << 16) | - (SRpnt->sr_sense_buffer[5] << 8) | - SRpnt->sr_sense_buffer[6]; - skip = SRpnt->sr_sense_buffer[9]; + frame = (SRpnt->sense[3] << 24) | + (SRpnt->sense[4] << 16) | + (SRpnt->sense[5] << 8) | + SRpnt->sense[6]; + skip = SRpnt->sense[9]; #if DEBUG printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip); @@ -1707,7 +1762,7 @@ static int osst_write_error_recovery(struct osst_tape * STp, struct scsi_request return retval; } -static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct scsi_request ** aSRpnt, +static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt, int mt_op, int mt_count) { char * name = tape_name(STp); @@ -1806,7 +1861,7 @@ found: * * Just scans for the filemark sequentially. */ -static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct scsi_request ** aSRpnt, +static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt, int mt_op, int mt_count) { int cnt = 0; @@ -1860,7 +1915,7 @@ static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct /* * Fast linux specific version of OnStream FSF */ -static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct scsi_request ** aSRpnt, +static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt, int mt_op, int mt_count) { char * name = tape_name(STp); @@ -2011,10 +2066,10 @@ static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct * to test the error recovery mechanism. */ #if DEBUG -static void osst_set_retries(struct osst_tape * STp, struct scsi_request ** aSRpnt, int retries) +static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries) { unsigned char cmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt = * aSRpnt; + struct osst_request * SRpnt = * aSRpnt; char * name = tape_name(STp); memset(cmd, 0, MAX_COMMAND_SIZE); @@ -2043,7 +2098,7 @@ static void osst_set_retries(struct osst_tape * STp, struct scsi_request ** aSRp #endif -static int osst_write_filemark(struct osst_tape * STp, struct scsi_request ** aSRpnt) +static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt) { int result; int this_mark_ppos = STp->first_frame_position; @@ -2071,7 +2126,7 @@ static int osst_write_filemark(struct osst_tape * STp, struct scsi_request ** aS return result; } -static int osst_write_eod(struct osst_tape * STp, struct scsi_request ** aSRpnt) +static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt) { int result; #if DEBUG @@ -2094,7 +2149,7 @@ static int osst_write_eod(struct osst_tape * STp, struct scsi_request ** aSRpnt) return result; } -static int osst_write_filler(struct osst_tape * STp, struct scsi_request ** aSRpnt, int where, int count) +static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count) { char * name = tape_name(STp); @@ -2119,7 +2174,7 @@ static int osst_write_filler(struct osst_tape * STp, struct scsi_request ** aSRp return osst_flush_drive_buffer(STp, aSRpnt); } -static int __osst_write_header(struct osst_tape * STp, struct scsi_request ** aSRpnt, int where, int count) +static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count) { char * name = tape_name(STp); int result; @@ -2146,7 +2201,7 @@ static int __osst_write_header(struct osst_tape * STp, struct scsi_request ** aS return result; } -static int osst_write_header(struct osst_tape * STp, struct scsi_request ** aSRpnt, int locate_eod) +static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod) { os_header_t * header; int result; @@ -2220,7 +2275,7 @@ static int osst_write_header(struct osst_tape * STp, struct scsi_request ** aSRp return result; } -static int osst_reset_header(struct osst_tape * STp, struct scsi_request ** aSRpnt) +static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt) { if (STp->header_cache != NULL) memset(STp->header_cache, 0, sizeof(os_header_t)); @@ -2233,7 +2288,7 @@ static int osst_reset_header(struct osst_tape * STp, struct scsi_request ** aSRp return osst_write_header(STp, aSRpnt, 1); } -static int __osst_analyze_headers(struct osst_tape * STp, struct scsi_request ** aSRpnt, int ppos) +static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos) { char * name = tape_name(STp); os_header_t * header; @@ -2410,7 +2465,7 @@ static int __osst_analyze_headers(struct osst_tape * STp, struct scsi_request ** return 1; } -static int osst_analyze_headers(struct osst_tape * STp, struct scsi_request ** aSRpnt) +static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt) { int position, ppos; int first, last; @@ -2465,7 +2520,7 @@ static int osst_analyze_headers(struct osst_tape * STp, struct scsi_request ** a return 1; } -static int osst_verify_position(struct osst_tape * STp, struct scsi_request ** aSRpnt) +static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt) { int frame_position = STp->first_frame_position; int frame_seq_numbr = STp->frame_seq_number; @@ -2541,11 +2596,11 @@ static unsigned int osst_parse_firmware_rev (const char * str) /* * Configure the OnStream SCII tape drive for default operation */ -static int osst_configure_onstream(struct osst_tape *STp, struct scsi_request ** aSRpnt) +static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt) { unsigned char cmd[MAX_COMMAND_SIZE]; char * name = tape_name(STp); - struct scsi_request * SRpnt = * aSRpnt; + struct osst_request * SRpnt = * aSRpnt; osst_mode_parameter_header_t * header; osst_block_size_page_t * bs; osst_capabilities_page_t * cp; @@ -2712,7 +2767,7 @@ static int osst_configure_onstream(struct osst_tape *STp, struct scsi_request ** /* Step over EOF if it has been inadvertently crossed (ioctl not used because it messes up the block number). */ -static int cross_eof(struct osst_tape *STp, struct scsi_request ** aSRpnt, int forward) +static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward) { int result; char * name = tape_name(STp); @@ -2741,10 +2796,10 @@ static int cross_eof(struct osst_tape *STp, struct scsi_request ** aSRpnt, int f /* Get the tape position. */ -static int osst_get_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt) +static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt) { unsigned char scmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt; + struct osst_request * SRpnt; int result = 0; char * name = tape_name(STp); @@ -2769,14 +2824,14 @@ static int osst_get_frame_position(struct osst_tape *STp, struct scsi_request ** *aSRpnt = SRpnt; if (STp->buffer->syscall_result) - result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL; /* 3: Write Error */ + result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL; /* 3: Write Error */ if (result == -EINVAL) printk(KERN_ERR "%s:E: Can't read tape position.\n", name); else { if (result == -EIO) { /* re-read position - this needs to preserve media errors */ unsigned char mysense[16]; - memcpy (mysense, SRpnt->sr_sense_buffer, 16); + memcpy (mysense, SRpnt->sense, 16); memset (scmd, 0, MAX_COMMAND_SIZE); scmd[0] = READ_POSITION; STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24; @@ -2785,10 +2840,10 @@ static int osst_get_frame_position(struct osst_tape *STp, struct scsi_request ** #if DEBUG printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n", name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:", - SRpnt->sr_sense_buffer[2],SRpnt->sr_sense_buffer[12],SRpnt->sr_sense_buffer[13]); + SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]); #endif if (!STp->buffer->syscall_result) - memcpy (SRpnt->sr_sense_buffer, mysense, 16); + memcpy (SRpnt->sense, mysense, 16); else printk(KERN_WARNING "%s:W: Double error in get position\n", name); } @@ -2825,10 +2880,10 @@ static int osst_get_frame_position(struct osst_tape *STp, struct scsi_request ** /* Set the tape block */ -static int osst_set_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt, int ppos, int skip) +static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip) { unsigned char scmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt; + struct osst_request * SRpnt; struct st_partstat * STps; int result = 0; int pp = (ppos == 3000 && !skip)? 0 : ppos; @@ -2883,7 +2938,7 @@ static int osst_set_frame_position(struct osst_tape *STp, struct scsi_request ** return result; } -static int osst_write_trailer(struct osst_tape *STp, struct scsi_request ** aSRpnt, int leave_at_EOT) +static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT) { struct st_partstat * STps = &(STp->ps[STp->partition]); int result = 0; @@ -2910,12 +2965,12 @@ out: /* osst versions of st functions - augmented and stripped to suit OnStream only */ /* Flush the write buffer (never need to write if variable blocksize). */ -static int osst_flush_write_buffer(struct osst_tape *STp, struct scsi_request ** aSRpnt) +static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt) { int offset, transfer, blks = 0; int result = 0; unsigned char cmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt = *aSRpnt; + struct osst_request * SRpnt = *aSRpnt; struct st_partstat * STps; char * name = tape_name(STp); @@ -2923,13 +2978,13 @@ static int osst_flush_write_buffer(struct osst_tape *STp, struct scsi_request ** if (SRpnt == (STp->buffer)->last_SRpnt) #if DEBUG { printk(OSST_DEB_MSG - "%s:D: aSRpnt points to scsi_request that write_behind_check will release -- cleared\n", name); + "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name); #endif *aSRpnt = SRpnt = NULL; #if DEBUG } else if (SRpnt) printk(OSST_DEB_MSG - "%s:D: aSRpnt does not point to scsi_request that write_behind_check will release -- strange\n", name); + "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name); #endif osst_write_behind_check(STp); if ((STp->buffer)->syscall_result) { @@ -3007,12 +3062,12 @@ static int osst_flush_write_buffer(struct osst_tape *STp, struct scsi_request ** #if DEBUG printk(OSST_DEB_MSG "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n", - name, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2], - SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]); + name, SRpnt->sense[0], SRpnt->sense[2], + SRpnt->sense[12], SRpnt->sense[13]); #endif - if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && - (SRpnt->sr_sense_buffer[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */ - (SRpnt->sr_sense_buffer[2] & 0x0f) == NO_SENSE) { + if ((SRpnt->sense[0] & 0x70) == 0x70 && + (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */ + (SRpnt->sense[2] & 0x0f) == NO_SENSE) { STp->dirty = 0; (STp->buffer)->buffer_bytes = 0; result = (-ENOSPC); @@ -3040,7 +3095,7 @@ static int osst_flush_write_buffer(struct osst_tape *STp, struct scsi_request ** /* Flush the tape buffer. The tape will be positioned correctly unless seek_next is true. */ -static int osst_flush_buffer(struct osst_tape * STp, struct scsi_request ** aSRpnt, int seek_next) +static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next) { struct st_partstat * STps; int backspace = 0, result = 0; @@ -3102,10 +3157,10 @@ static int osst_flush_buffer(struct osst_tape * STp, struct scsi_request ** aSRp return result; } -static int osst_write_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int synchronous) +static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous) { unsigned char cmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt; + struct osst_request * SRpnt; int blks; #if DEBUG char * name = tape_name(STp); @@ -3166,9 +3221,9 @@ static int osst_write_frame(struct osst_tape * STp, struct scsi_request ** aSRpn if (debugging) printk(OSST_DEB_MSG "%s:D: Error on write:\n", name); #endif - if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && - (SRpnt->sr_sense_buffer[2] & 0x40)) { - if ((SRpnt->sr_sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW) + if ((SRpnt->sense[0] & 0x70) == 0x70 && + (SRpnt->sense[2] & 0x40)) { + if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW) return (-ENOSPC); } else { @@ -3185,7 +3240,7 @@ static int osst_write_frame(struct osst_tape * STp, struct scsi_request ** aSRpn return 0; } -/* Lock or unlock the drive door. Don't use when struct scsi_request allocated. */ +/* Lock or unlock the drive door. Don't use when struct osst_request allocated. */ static int do_door_lock(struct osst_tape * STp, int do_lock) { int retval, cmd; @@ -3233,7 +3288,7 @@ static ssize_t osst_write(struct file * filp, const char __user * buf, size_t co int write_threshold; int doing_write = 0; const char __user * b_point; - struct scsi_request * SRpnt = NULL; + struct osst_request * SRpnt = NULL; struct st_modedef * STm; struct st_partstat * STps; struct osst_tape * STp = filp->private_data; @@ -3424,7 +3479,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name #if DEBUG if (debugging) printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n", - name, count, STps->drv_file, STps->drv_block, + name, (int) count, STps->drv_file, STps->drv_block, STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position); #endif b_point = buf; @@ -3460,7 +3515,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name #if DEBUG if (debugging) printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n", - name, transfer); + name, (int) transfer); #endif } else { @@ -3478,7 +3533,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name if (retval < 0) { if (SRpnt != NULL) { - scsi_release_request(SRpnt); + osst_release_request(SRpnt); SRpnt = NULL; } STp->buffer->buffer_bytes = 0; @@ -3540,7 +3595,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name retval = total; out: - if (SRpnt != NULL) scsi_release_request(SRpnt); + if (SRpnt != NULL) osst_release_request(SRpnt); up(&STp->lock); @@ -3556,7 +3611,7 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo int special; struct st_modedef * STm; struct st_partstat * STps; - struct scsi_request * SRpnt = NULL; + struct osst_request * SRpnt = NULL; struct osst_tape * STp = filp->private_data; char * name = tape_name(STp); @@ -3664,7 +3719,7 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo #if DEBUG if (debugging && STps->eof != ST_NOEOF) printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name, - STps->eof, (STp->buffer)->buffer_bytes, count - total); + STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total)); #endif /* force multiple of block size, note block_size may have been adjusted */ transfer = (((STp->buffer)->buffer_bytes < count - total ? @@ -3725,7 +3780,7 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo retval = total; out: - if (SRpnt != NULL) scsi_release_request(SRpnt); + if (SRpnt != NULL) osst_release_request(SRpnt); up(&STp->lock); @@ -3913,7 +3968,7 @@ static int osst_set_options(struct osst_tape *STp, long options) /* Internal ioctl function */ -static int osst_int_ioctl(struct osst_tape * STp, struct scsi_request ** aSRpnt, +static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned int cmd_in, unsigned long arg) { int timeout; @@ -3921,7 +3976,7 @@ static int osst_int_ioctl(struct osst_tape * STp, struct scsi_request ** aSRpnt, int i, ioctl_result; int chg_eof = 1; unsigned char cmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt = * aSRpnt; + struct osst_request * SRpnt = * aSRpnt; struct st_partstat * STps; int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num; int datalen = 0, direction = DMA_NONE; @@ -4279,14 +4334,14 @@ os_bypass: } else if (cmd_in == MTERASE) { STp->header_ok = 0; } else if (SRpnt) { /* SCSI command was not completely successful. */ - if (SRpnt->sr_sense_buffer[2] & 0x40) { + if (SRpnt->sense[2] & 0x40) { STps->eof = ST_EOM_OK; STps->drv_block = 0; } if (chg_eof) STps->eof = ST_NOEOF; - if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK) + if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK) STps->eof = ST_EOD; if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60)) @@ -4304,7 +4359,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) unsigned short flags; int i, b_size, new_session = 0, retval = 0; unsigned char cmd[MAX_COMMAND_SIZE]; - struct scsi_request * SRpnt = NULL; + struct osst_request * SRpnt = NULL; struct osst_tape * STp; struct st_modedef * STm; struct st_partstat * STps; @@ -4412,17 +4467,17 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) retval = (STp->buffer)->syscall_result; /* FIXME - valid? */ goto err_out; } - if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && - (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY && - SRpnt->sr_sense_buffer[12] == 4 ) { + if ((SRpnt->sense[0] & 0x70) == 0x70 && + (SRpnt->sense[2] & 0x0f) == NOT_READY && + SRpnt->sense[12] == 4 ) { #if DEBUG - printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sr_sense_buffer[13]); + printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]); #endif if (filp->f_flags & O_NONBLOCK) { retval = -EAGAIN; goto err_out; } - if (SRpnt->sr_sense_buffer[13] == 2) { /* initialize command required (LOAD) */ + if (SRpnt->sense[13] == 2) { /* initialize command required (LOAD) */ memset (cmd, 0, MAX_COMMAND_SIZE); cmd[0] = START_STOP; cmd[1] = 1; @@ -4430,10 +4485,10 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1); } - osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60, 0); + osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0); } - if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && - (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */ + if ((SRpnt->sense[0] & 0x70) == 0x70 && + (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */ #if DEBUG printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name); #endif @@ -4446,8 +4501,8 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1); - if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 || - (SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION) + if ((SRpnt->sense[0] & 0x70) != 0x70 || + (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION) break; } @@ -4473,7 +4528,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) * open without reconfiguring and re-reading the headers */ if (!STp->buffer->syscall_result && STp->header_ok && - !SRpnt->sr_result && SRpnt->sr_sense_buffer[0] == 0) { + !SRpnt->result && SRpnt->sense[0] == 0) { memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = MODE_SENSE; @@ -4512,7 +4567,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) } STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size; STp->fast_open = 1; - scsi_release_request(SRpnt); + osst_release_request(SRpnt); return 0; } #if DEBUG @@ -4525,7 +4580,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) STp->fast_open = 0; if ((STp->buffer)->syscall_result != 0 && /* in all error conditions except no medium */ - (SRpnt->sr_sense_buffer[2] != 2 || SRpnt->sr_sense_buffer[12] != 0x3A) ) { + (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) { memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = MODE_SELECT; @@ -4555,11 +4610,11 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1); - if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 || - (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY) + if ((SRpnt->sense[0] & 0x70) != 0x70 || + (SRpnt->sense[2] & 0x0f) == NOT_READY) break; - if ((SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { + if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { STp->pos_unknown = 0; STp->partition = STp->new_partition = 0; if (STp->can_partitions) @@ -4583,13 +4638,13 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) if ((STp->buffer)->syscall_result != 0) { if ((STp->device)->scsi_level >= SCSI_2 && - (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && - (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY && - SRpnt->sr_sense_buffer[12] == 0x3a) { /* Check ASC */ + (SRpnt->sense[0] & 0x70) == 0x70 && + (SRpnt->sense[2] & 0x0f) == NOT_READY && + SRpnt->sense[12] == 0x3a) { /* Check ASC */ STp->ready = ST_NO_TAPE; } else STp->ready = ST_NOT_READY; - scsi_release_request(SRpnt); + osst_release_request(SRpnt); SRpnt = NULL; STp->density = 0; /* Clear the erroneous "residue" */ STp->write_prot = 0; @@ -4649,14 +4704,14 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) osst_analyze_headers(STp, &SRpnt); - scsi_release_request(SRpnt); + osst_release_request(SRpnt); SRpnt = NULL; return 0; err_out: if (SRpnt != NULL) - scsi_release_request(SRpnt); + osst_release_request(SRpnt); normalize_buffer(STp->buffer); STp->header_ok = 0; STp->in_use = 0; @@ -4673,7 +4728,7 @@ static int os_scsi_tape_flush(struct file * filp) struct osst_tape * STp = filp->private_data; struct st_modedef * STm = &(STp->modes[STp->current_mode]); struct st_partstat * STps = &(STp->ps[STp->partition]); - struct scsi_request * SRpnt = NULL; + struct osst_request * SRpnt = NULL; char * name = tape_name(STp); if (file_count(filp) > 1) @@ -4736,7 +4791,7 @@ out: if (result == 0 && result2 < 0) result = result2; } - if (SRpnt) scsi_release_request(SRpnt); + if (SRpnt) osst_release_request(SRpnt); if (STp->abort_count || STp->recover_count) { printk(KERN_INFO "%s:I:", name); @@ -4790,7 +4845,7 @@ static int osst_ioctl(struct inode * inode,struct file * file, unsigned int blk; struct st_modedef * STm; struct st_partstat * STps; - struct scsi_request * SRpnt = NULL; + struct osst_request * SRpnt = NULL; struct osst_tape * STp = file->private_data; char * name = tape_name(STp); void __user * p = (void __user *)arg; @@ -5104,14 +5159,14 @@ static int osst_ioctl(struct inode * inode,struct file * file, retval = -EFAULT; goto out; } - if (SRpnt) scsi_release_request(SRpnt); + if (SRpnt) osst_release_request(SRpnt); up(&STp->lock); return scsi_ioctl(STp->device, cmd_in, p); out: - if (SRpnt) scsi_release_request(SRpnt); + if (SRpnt) osst_release_request(SRpnt); up(&STp->lock); diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h index b72e1c76f52c..011d4d6ca9f9 100644 --- a/drivers/scsi/osst.h +++ b/drivers/scsi/osst.h @@ -518,7 +518,8 @@ struct osst_buffer { int writing; int midlevel_result; int syscall_result; - struct scsi_request *last_SRpnt; + struct osst_request *last_SRpnt; + struct st_cmdstatus cmdstat; unsigned char *b_data; os_aux_t *aux; /* onstream AUX structure at end of each block */ unsigned short use_sg; /* zero or number of s/g segments for this adapter */ @@ -626,6 +627,15 @@ struct osst_tape { struct gendisk *drive; } ; +/* scsi tape command */ +struct osst_request { + unsigned char cmd[MAX_COMMAND_SIZE]; + unsigned char sense[SCSI_SENSE_BUFFERSIZE]; + int result; + struct osst_tape *stp; + struct completion *waiting; +}; + /* Values of write_type */ #define OS_WRITE_DATA 0 #define OS_WRITE_EOD 1 -- cgit v1.2.3-59-g8ed1b From e12f0a3dec17de3d847f533ba81ad6956c9da5fd Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 7 Mar 2006 14:53:40 -0600 Subject: [SCSI] sr: partial revert of 24669f75a3231fa37444977c92d1f4838bec1233 The patch [SCSI] SCSI core kmalloc2kzalloc Has an incorrect piece in sr_ioctl.c; it changes buffer from kmalloc to kzalloc, but then removes the clearing of the stack variable struct packet_command. This, in turn leaves rubbish in the sense pointer which the sr_do_ioctl() command then happily writes to ... oops. Thanks to Mike Christie for spotting this. Signed-off-by: James Bottomley --- drivers/scsi/sr_ioctl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 03fbc4b44473..5d02ff4db6cc 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -44,10 +44,11 @@ static int sr_read_tochdr(struct cdrom_device_info *cdi, int result; unsigned char *buffer; - buffer = kzalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); + buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); if (!buffer) return -ENOMEM; + memset(&cgc, 0, sizeof(struct packet_command)); cgc.timeout = IOCTL_TIMEOUT; cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; cgc.cmd[8] = 12; /* LSB of length */ @@ -73,10 +74,11 @@ static int sr_read_tocentry(struct cdrom_device_info *cdi, int result; unsigned char *buffer; - buffer = kzalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); + buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); if (!buffer) return -ENOMEM; + memset(&cgc, 0, sizeof(struct packet_command)); cgc.timeout = IOCTL_TIMEOUT; cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0; -- cgit v1.2.3-59-g8ed1b From 293cdaba3f6663f630bcb85077206e55b581ed67 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Mon, 27 Feb 2006 21:08:07 -0300 Subject: V4L/DVB (3400): Fixes for Lifeview Trio non fatal bugs - Init message was sent to wrong slave address - Deleted outdated comment Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index f156650960c2..ea2fa0d18927 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2624,7 +2624,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .gpiomask = 0x00200000, - .mpeg = SAA7134_MPEG_DVB, /* FIXME: DVB not implemented yet */ + .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, /* Analog broadcast/cable TV */ .vmux = 1, @@ -3549,6 +3549,12 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_FLYDVB_TRIO: + { + u8 data[] = { 0x3c, 0x33, 0x62}; + struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)}; + i2c_transfer(&dev->i2c_adap, &msg, 1); + } + break; case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: /* make the tda10046 find its eeprom */ { -- cgit v1.2.3-59-g8ed1b From 2d6b5f6257a11d66d2f1e335180e8aca16704294 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Mon, 27 Feb 2006 21:14:36 -0300 Subject: V4L/DVB (3401): Coding style fixes in saa7134-dvb.c deleted 2 semicolons at end of functions Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-dvb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index ad34eb5b17cb..86cfdb8514cb 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -814,7 +814,7 @@ static int philips_tiger_pll_set(struct dvb_frontend *fe, struct dvb_frontend_pa tda8290_msg.buf = tda8290_open; i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); return ret; -}; +} static int philips_tiger_dvb_mode(struct dvb_frontend *fe) { @@ -891,7 +891,7 @@ static int ads_duo_pll_set(struct dvb_frontend *fe, struct dvb_frontend_paramete ret = philips_tda827xa_pll_set(0x61, fe, params); return ret; -}; +} static int ads_duo_dvb_mode(struct dvb_frontend *fe) { -- cgit v1.2.3-59-g8ed1b From 9f3319b49cc793b9da06ca57cc8740e3a8e88d1d Mon Sep 17 00:00:00 2001 From: Marco Schluessler Date: Fri, 24 Feb 2006 18:53:00 -0300 Subject: V4L/DVB (3403): Workaround to fix initialization for Nexus CA Workaround for Nexus CA: Debi test fails unless first debi write is repeated. Signed-off-by: Marco Schluessler Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110_hw.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index 3c5366d15a8a..75736f2fe838 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c @@ -245,6 +245,9 @@ int av7110_bootarm(struct av7110 *av7110) /* test DEBI */ iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4); + /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */ + iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4); + if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) { printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: " "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n", -- cgit v1.2.3-59-g8ed1b From 2f27bdce972ceb97a2fd109a77546c37aa499fc9 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Tue, 28 Feb 2006 09:31:16 -0300 Subject: V4L/DVB (3404): Refactored LNBP21 and BSBE1 support Moved duplicated code to separate files. LNBP21 stuff rewritten from scratch, BSBE1 copied from av7110.c. Modified budget driver to use the new routines. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.h | 1 + drivers/media/dvb/frontends/bsbe1.h | 123 ++++++++++++++++++++++++++ drivers/media/dvb/frontends/lnbp21.h | 139 +++++++++++++++++++++++++++++ drivers/media/dvb/ttpci/budget.c | 141 +----------------------------- 4 files changed, 267 insertions(+), 137 deletions(-) create mode 100644 drivers/media/dvb/frontends/bsbe1.h create mode 100644 drivers/media/dvb/frontends/lnbp21.h (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 70a6d14efda7..d5aee5ad67a0 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -104,6 +104,7 @@ struct dvb_frontend { struct dvb_adapter *dvb; void* demodulator_priv; void* frontend_priv; + void* misc_priv; }; extern int dvb_register_frontend(struct dvb_adapter* dvb, diff --git a/drivers/media/dvb/frontends/bsbe1.h b/drivers/media/dvb/frontends/bsbe1.h new file mode 100644 index 000000000000..78573b22ada9 --- /dev/null +++ b/drivers/media/dvb/frontends/bsbe1.h @@ -0,0 +1,123 @@ +/* + * bsbe1.h - ALPS BSBE1 tuner support (moved from av7110.c) + * + * 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. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ + +#ifndef BSBE1_H +#define BSBE1_H + +static u8 alps_bsbe1_inittab[] = { + 0x01, 0x15, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb9, + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x92, + 0xff, 0xff +}; + + +static int alps_bsbe1_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } + else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } + else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } + else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } + else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } + else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } + + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, (ratio ) & 0xf0); + + return 0; +} + +static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) +{ + int ret; + u8 data[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4; + + ret = i2c_transfer(i2c, &msg, 1); + return (ret != 1) ? -EIO : 0; +} + +static struct stv0299_config alps_bsbe1_config = { + .demod_address = 0x68, + .inittab = alps_bsbe1_inittab, + .mclk = 88000000UL, + .invert = 1, + .skip_reinit = 0, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsbe1_set_symbol_rate, + .pll_set = alps_bsbe1_pll_set, +}; + +#endif diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb/frontends/lnbp21.h new file mode 100644 index 000000000000..0dcbe61b61b1 --- /dev/null +++ b/drivers/media/dvb/frontends/lnbp21.h @@ -0,0 +1,139 @@ +/* + * lnbp21.h - driver for lnb supply and control ic lnbp21 + * + * Copyright (C) 2006 Oliver Endriss + * + * 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. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ + +#ifndef _LNBP21_H +#define _LNBP21_H + +/* system register */ +#define LNBP21_OLF 0x01 +#define LNBP21_OTF 0x02 +#define LNBP21_EN 0x04 +#define LNBP21_VSEL 0x08 +#define LNBP21_LLC 0x10 +#define LNBP21_TEN 0x20 +#define LNBP21_ISEL 0x40 +#define LNBP21_PCL 0x80 + +struct lnbp21 { + u8 config; + u8 override_or; + u8 override_and; + struct i2c_adapter *i2c; + void (*release_chain)(struct dvb_frontend* fe); +}; + +static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + struct i2c_msg msg = { .addr = 0x08, .flags = 0, + .buf = &lnbp21->config, + .len = sizeof(lnbp21->config) }; + + lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN); + + switch(voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + lnbp21->config |= LNBP21_EN; + break; + case SEC_VOLTAGE_18: + lnbp21->config |= (LNBP21_EN | LNBP21_VSEL); + break; + default: + return -EINVAL; + }; + + lnbp21->config |= lnbp21->override_or; + lnbp21->config &= lnbp21->override_and; + + return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + struct i2c_msg msg = { .addr = 0x08, .flags = 0, + .buf = &lnbp21->config, + .len = sizeof(lnbp21->config) }; + + if (arg) + lnbp21->config |= LNBP21_LLC; + else + lnbp21->config &= ~LNBP21_LLC; + + lnbp21->config |= lnbp21->override_or; + lnbp21->config &= lnbp21->override_and; + + return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static void lnbp21_exit(struct dvb_frontend *fe) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + + /* LNBP power off */ + lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF); + + /* free data & call next release routine */ + fe->ops->release = lnbp21->release_chain; + kfree(fe->misc_priv); + fe->misc_priv = NULL; + if (fe->ops->release) + fe->ops->release(fe); +} + +static int lnbp21_init(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) +{ + struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL); + + if (!lnbp21) + return -ENOMEM; + + /* default configuration */ + lnbp21->config = LNBP21_ISEL; + + /* bits which should be forced to '1' */ + lnbp21->override_or = override_set; + + /* bits which should be forced to '0' */ + lnbp21->override_and = ~override_clear; + + /* install release callback */ + lnbp21->release_chain = fe->ops->release; + fe->ops->release = lnbp21_exit; + + /* override frontend ops */ + fe->ops->set_voltage = lnbp21_set_voltage; + fe->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; + + lnbp21->i2c = i2c; + fe->misc_priv = lnbp21; + + return lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF); +} + +#endif diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 238c77b52f89..2a0e3efd81c7 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -41,6 +41,8 @@ #include "l64781.h" #include "tda8083.h" #include "s5h1420.h" +#include "lnbp21.h" +#include "bsbe1.h" static void Set22K (struct budget *budget, int state) { @@ -184,64 +186,6 @@ static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t m return 0; } -static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) -{ - struct budget* budget = (struct budget*) fe->dvb->priv; - u8 buf; - struct i2c_msg msg = { .addr = 0x08, .flags = I2C_M_RD, .buf = &buf, .len = sizeof(buf) }; - - if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; - - switch(voltage) { - case SEC_VOLTAGE_13: - buf = (buf & 0xf7) | 0x04; - break; - - case SEC_VOLTAGE_18: - buf = (buf & 0xf7) | 0x0c; - break; - - case SEC_VOLTAGE_OFF: - buf = buf & 0xf0; - break; - } - - msg.flags = 0; - if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; - - return 0; -} - -static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, long arg) -{ - struct budget* budget = (struct budget*) fe->dvb->priv; - u8 buf; - struct i2c_msg msg = { .addr = 0x08, .flags = I2C_M_RD, .buf = &buf, .len = sizeof(buf) }; - - if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; - - if (arg) { - buf = buf | 0x10; - } else { - buf = buf & 0xef; - } - - msg.flags = 0; - if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; - - return 0; -} - -static int lnbp21_init(struct budget* budget) -{ - u8 buf = 0x00; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = &buf, .len = sizeof(buf) }; - - if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) - return -EIO; - return 0; -} - static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; @@ -374,79 +318,6 @@ static struct stv0299_config alps_bsru6_config = { .pll_set = alps_bsru6_pll_set, }; -static u8 alps_bsbe1_inittab[] = { - 0x01, 0x15, - 0x02, 0x30, - 0x03, 0x00, - 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ - 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ - 0x06, 0x40, /* DAC not used, set to high impendance mode */ - 0x07, 0x00, /* DAC LSB */ - 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ - 0x09, 0x00, /* FIFO */ - 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ - 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ - 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ - 0x10, 0x3f, // AGC2 0x3d - 0x11, 0x84, - 0x12, 0xb9, - 0x15, 0xc9, // lock detector threshold - 0x16, 0x00, - 0x17, 0x00, - 0x18, 0x00, - 0x19, 0x00, - 0x1a, 0x00, - 0x1f, 0x50, - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 - 0x29, 0x1e, // 1/2 threshold - 0x2a, 0x14, // 2/3 threshold - 0x2b, 0x0f, // 3/4 threshold - 0x2c, 0x09, // 5/6 threshold - 0x2d, 0x05, // 7/8 threshold - 0x2e, 0x01, - 0x31, 0x1f, // test all FECs - 0x32, 0x19, // viterbi and synchro search - 0x33, 0xfc, // rs control - 0x34, 0x93, // error control - 0x0f, 0x92, // 0x80 = inverse AGC - 0xff, 0xff -}; - -static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) -{ - int ret; - u8 data[4]; - u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) - return -EINVAL; - - div = (params->frequency + (125 - 1)) / 125; // round correctly - data[0] = (div >> 8) & 0x7f; - data[1] = div & 0xff; - data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; - data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4; - - ret = i2c_transfer(i2c, &msg, 1); - return (ret != 1) ? -EIO : 0; -} - -static struct stv0299_config alps_bsbe1_config = { - .demod_address = 0x68, - .inittab = alps_bsbe1_inittab, - .mclk = 88000000UL, - .invert = 1, - .skip_reinit = 0, - .min_delay_ms = 100, - .set_symbol_rate = alps_bsru6_set_symbol_rate, - .pll_set = alps_bsbe1_pll_set, -}; - static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; @@ -584,10 +455,8 @@ static void frontend_init(struct budget *budget) // try the ALPS BSBE1 now budget->dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget->i2c_adap); if (budget->dvb_frontend) { - budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage; - budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; - if (lnbp21_init(budget)) { + if (lnbp21_init(budget->dvb_frontend, &budget->i2c_adap, LNBP21_LLC, 0)) { printk("%s: No LNBP21 found!\n", __FUNCTION__); goto error_out; } @@ -646,9 +515,7 @@ static void frontend_init(struct budget *budget) case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260)) budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap); if (budget->dvb_frontend) { - budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage; - budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; - if (lnbp21_init(budget)) { + if (lnbp21_init(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) { printk("%s: No LNBP21 found!\n", __FUNCTION__); goto error_out; } -- cgit v1.2.3-59-g8ed1b From 8cc2e377a0f20f58606d8a68a423ed2ea348869d Mon Sep 17 00:00:00 2001 From: Perceval Anichini Date: Tue, 28 Feb 2006 09:52:44 -0300 Subject: V4L/DVB (3405): TechnoTrend S-1500 card handling moved from budget.c to budget-ci.c TechnoTrend S-1500 card handling moved from budget.c to budget-ci.c. Signed-off-by: Perceval Anichini Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 18 ++++++++++++++++++ drivers/media/dvb/ttpci/budget.c | 15 --------------- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index b9b3cd9c0369..09b972b9ffe3 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -42,6 +42,8 @@ #include "stv0299.h" #include "stv0297.h" #include "tda1004x.h" +#include "lnbp21.h" +#include "bsbe1.h" #define DEBIADDR_IR 0x1234 #define DEBIADDR_CICONTROL 0x0000 @@ -1069,6 +1071,20 @@ static void frontend_init(struct budget_ci *budget_ci) break; } break; + + case 0x1017: // TT S-1500 PCI + budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget_ci->budget.i2c_adap); + if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; + if (lnbp21_init(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) { + printk("%s: No LNBP21 found!\n", __FUNCTION__); + if (budget_ci->budget.dvb_frontend->ops->release) + budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend); + budget_ci->budget.dvb_frontend = NULL; + } + } + + break; } if (budget_ci->budget.dvb_frontend == NULL) { @@ -1146,6 +1162,7 @@ static int budget_ci_detach(struct saa7146_dev *dev) static struct saa7146_extension budget_extension; +MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC); MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT); @@ -1157,6 +1174,7 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010), MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011), MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012), + MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017), { .vendor = 0, } diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 2a0e3efd81c7..bfb80925019a 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -42,7 +42,6 @@ #include "tda8083.h" #include "s5h1420.h" #include "lnbp21.h" -#include "bsbe1.h" static void Set22K (struct budget *budget, int state) { @@ -451,18 +450,6 @@ static u8 read_pwm(struct budget* budget) static void frontend_init(struct budget *budget) { switch(budget->dev->pci->subsystem_device) { - case 0x1017: - // try the ALPS BSBE1 now - budget->dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget->i2c_adap); - if (budget->dvb_frontend) { - budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; - if (lnbp21_init(budget->dvb_frontend, &budget->i2c_adap, LNBP21_LLC, 0)) { - printk("%s: No LNBP21 found!\n", __FUNCTION__); - goto error_out; - } - } - - break; case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659)) case 0x1013: // try the ALPS BSRV2 first of all @@ -586,7 +573,6 @@ static int budget_detach (struct saa7146_dev* dev) static struct saa7146_extension budget_extension; -MAKE_BUDGET_INFO(ttbs2, "TT-Budget/WinTV-NOVA-S PCI (rev AL/alps bsbe1 lnbp21 frontend)", BUDGET_TT); MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); @@ -599,7 +585,6 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004), MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005), MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), - MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017), MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016), MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60), MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), -- cgit v1.2.3-59-g8ed1b From db5d91eb36e1cc9d46016d1d44874376cfabf274 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Tue, 28 Feb 2006 10:32:25 -0300 Subject: V4L/DVB (3406): Use refactored LNBP21 and BSBE1 code Use refactored LNBP21/BSBE1 code for Technotrend/Hauppauge DVB-S rev 2.3. As a side effect, FE_ENABLE_HIGH_LNB_VOLTAGE ioctl is supported now. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110.c | 114 +++++---------------------------------- 1 file changed, 12 insertions(+), 102 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index d982a50cdd7f..914f2e34d8d3 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -66,6 +66,9 @@ #include "av7110_ca.h" #include "av7110_ipack.h" +#include "bsbe1.h" +#include "lnbp21.h" + #define TS_WIDTH 376 #define TS_HEIGHT 512 #define TS_BUFLEN (TS_WIDTH*TS_HEIGHT) @@ -1672,105 +1675,6 @@ static struct stv0299_config alps_bsru6_config = { }; -static u8 alps_bsbe1_inittab[] = { - 0x01, 0x15, - 0x02, 0x30, - 0x03, 0x00, - 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ - 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ - 0x06, 0x40, /* DAC not used, set to high impendance mode */ - 0x07, 0x00, /* DAC LSB */ - 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ - 0x09, 0x00, /* FIFO */ - 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ - 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ - 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ - 0x10, 0x3f, // AGC2 0x3d - 0x11, 0x84, - 0x12, 0xb9, - 0x15, 0xc9, // lock detector threshold - 0x16, 0x00, - 0x17, 0x00, - 0x18, 0x00, - 0x19, 0x00, - 0x1a, 0x00, - 0x1f, 0x50, - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 - 0x29, 0x1e, // 1/2 threshold - 0x2a, 0x14, // 2/3 threshold - 0x2b, 0x0f, // 3/4 threshold - 0x2c, 0x09, // 5/6 threshold - 0x2d, 0x05, // 7/8 threshold - 0x2e, 0x01, - 0x31, 0x1f, // test all FECs - 0x32, 0x19, // viterbi and synchro search - 0x33, 0xfc, // rs control - 0x34, 0x93, // error control - 0x0f, 0x92, - 0xff, 0xff -}; - -static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) -{ - int ret; - u8 data[4]; - u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) - return -EINVAL; - - div = (params->frequency + (125 - 1)) / 125; // round correctly - data[0] = (div >> 8) & 0x7f; - data[1] = div & 0xff; - data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; - data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4; - - ret = i2c_transfer(i2c, &msg, 1); - return (ret != 1) ? -EIO : 0; -} - -static struct stv0299_config alps_bsbe1_config = { - .demod_address = 0x68, - .inittab = alps_bsbe1_inittab, - .mclk = 88000000UL, - .invert = 1, - .skip_reinit = 0, - .min_delay_ms = 100, - .set_symbol_rate = alps_bsru6_set_symbol_rate, - .pll_set = alps_bsbe1_pll_set, -}; - -static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) -{ - struct av7110* av7110 = (struct av7110*) fe->dvb->priv; - int ret; - u8 data[1]; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = data, .len = sizeof(data) }; - - switch(voltage) { - case SEC_VOLTAGE_OFF: - data[0] = 0x00; - break; - case SEC_VOLTAGE_13: - data[0] = 0x44; - break; - case SEC_VOLTAGE_18: - data[0] = 0x4c; - break; - default: - return -EINVAL; - }; - - ret = i2c_transfer(&av7110->i2c_adap, &msg, 1); - return (ret != 1) ? -EIO : 0; -} - - static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct av7110* av7110 = fe->dvb->priv; @@ -2373,9 +2277,15 @@ static int frontend_init(struct av7110 *av7110) /* ALPS BSBE1 */ av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap); if (av7110->fe) { - av7110->fe->ops->set_voltage = lnbp21_set_voltage; - av7110->fe->ops->dishnetwork_send_legacy_command = NULL; - av7110->recover = dvb_s_recover; + if (lnbp21_init(av7110->fe, &av7110->i2c_adap, 0, 0)) { + printk("dvb-ttpci: LNBP21 not found!\n"); + if (av7110->fe->ops->release) + av7110->fe->ops->release(av7110->fe); + av7110->fe = NULL; + } else { + av7110->fe->ops->dishnetwork_send_legacy_command = NULL; + av7110->recover = dvb_s_recover; + } } break; } -- cgit v1.2.3-59-g8ed1b From 780dfef37e2c941985b708f67aa0074edc922bea Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Tue, 28 Feb 2006 08:34:59 -0300 Subject: V4L/DVB (3408): DViCO FusionHDTV DVB-T Hybrid and ZL10353-based FusionHDTV DVB-T Plus support Add support for the FE6600 tuner used on the DVB-T Hybrid board. Add support for the Zarlink ZL10353 DVB-T demodulator, which supersedes the MT352, used on the DViCO FusionHDTV DVB-T Hybrid and later model Plus boards. Signed-off-by: Chris Pascoe Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + Documentation/video4linux/CARDLIST.tuner | 1 + drivers/media/dvb/frontends/Kconfig | 6 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/dvb-pll.c | 15 ++ drivers/media/dvb/frontends/dvb-pll.h | 2 + drivers/media/dvb/frontends/zl10353.c | 311 +++++++++++++++++++++++++++++ drivers/media/dvb/frontends/zl10353.h | 43 ++++ drivers/media/dvb/frontends/zl10353_priv.h | 42 ++++ drivers/media/video/cx88/Makefile | 1 + drivers/media/video/cx88/cx88-cards.c | 67 +++++++ drivers/media/video/cx88/cx88-dvb.c | 108 ++++++++-- drivers/media/video/cx88/cx88.h | 1 + drivers/media/video/tuner-types.c | 20 ++ include/media/tuner.h | 3 +- 15 files changed, 599 insertions(+), 23 deletions(-) create mode 100644 drivers/media/dvb/frontends/zl10353.c create mode 100644 drivers/media/dvb/frontends/zl10353.h create mode 100644 drivers/media/dvb/frontends/zl10353_priv.h (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index d852ad4f93a2..3b39a91b24bd 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -44,3 +44,4 @@ 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1] 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54] 45 -> KWorld HardwareMpegTV XPert [17de:0840] + 46 -> DViCO FusionHDTV DVB-T Hybrid [18ac:db40,18ac:db44] diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index de48438d5115..ab344c94c0a2 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -70,3 +70,4 @@ tuner=68 - Philips TUV1236D ATSC/NTSC dual in tuner=69 - Tena TNF 5335 MF tuner=70 - Samsung TCPN 2121P30A tuner=71 - Xceive xc3028 +tuner=72 - FE6600 diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index c676b1e23ab0..a1a894d81040 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -116,6 +116,12 @@ config DVB_MT352 help A DVB-T tuner module. Say Y when you want to support this frontend. +config DVB_ZL10353 + tristate "Zarlink ZL10353 based" + depends on DVB_CORE + help + A DVB-T tuner module. Say Y when you want to support this frontend. + config DVB_DIB3000MB tristate "DiBcom 3000M-B" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 1af769cd90c0..d09b6071fbaf 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o obj-$(CONFIG_DVB_SP887X) += sp887x.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_MT352) += mt352.o +obj-$(CONFIG_DVB_ZL10353) += zl10353.o obj-$(CONFIG_DVB_CX22702) += cx22702.o obj-$(CONFIG_DVB_TDA10021) += tda10021.o obj-$(CONFIG_DVB_STV0297) += stv0297.o diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 4f682534df42..8a4c904d3a27 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -404,6 +404,21 @@ struct dvb_pll_desc dvb_pll_philips_td1316 = { }; EXPORT_SYMBOL(dvb_pll_philips_td1316); +/* FE6600 used on DViCO Hybrid */ +struct dvb_pll_desc dvb_pll_unknown_fe6600 = { + .name = "FE6600", + .min = 44250000, + .max = 858000000, + .count = 4, + .entries = { + { 250000000, 36213333, 166667, 0xb4, 0x12 }, + { 455000000, 36213333, 166667, 0xfe, 0x11 }, + { 775500000, 36213333, 166667, 0xbc, 0x18 }, + { 999999999, 36213333, 166667, 0xf4, 0x18 }, + } +}; +EXPORT_SYMBOL(dvb_pll_unknown_fe6600); + /* ----------------------------------------------------------- */ /* code */ diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 56c3cd76a7fa..8a7f0b941c38 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -42,6 +42,8 @@ extern struct dvb_pll_desc dvb_pll_samsung_tbmv; extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261; extern struct dvb_pll_desc dvb_pll_philips_td1316; +extern struct dvb_pll_desc dvb_pll_unknown_fe6600; + int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, u32 freq, int bandwidth); diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c new file mode 100644 index 000000000000..23846c4452ad --- /dev/null +++ b/drivers/media/dvb/frontends/zl10353.c @@ -0,0 +1,311 @@ +/* + * Driver for Zarlink DVB-T ZL10353 demodulator + * + * Copyright (C) 2006 Christopher Pascoe + * + * 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 "dvb_frontend.h" +#include "zl10353_priv.h" +#include "zl10353.h" + +struct zl10353_state { + struct i2c_adapter *i2c; + struct dvb_frontend frontend; + struct dvb_frontend_ops ops; + + struct zl10353_config config; +}; + +static int debug_regs = 0; + +static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val) +{ + struct zl10353_state *state = fe->demodulator_priv; + u8 buf[2] = { reg, val }; + struct i2c_msg msg = { .addr = state->config.demod_address, .flags = 0, + .buf = buf, .len = 2 }; + int err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) { + printk("zl10353: write to reg %x failed (err = %d)!\n", reg, err); + return err; + } + return 0; +} + +int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen) +{ + int err, i; + for (i = 0; i < ilen - 1; i++) + if ((err = zl10353_single_write(fe, ibuf[0] + i, ibuf[i + 1]))) + return err; + + return 0; +} + +static int zl10353_read_register(struct zl10353_state *state, u8 reg) +{ + int ret; + u8 b0[1] = { reg }; + u8 b1[1] = { 0 }; + struct i2c_msg msg[2] = { { .addr = state->config.demod_address, + .flags = 0, + .buf = b0, .len = 1 }, + { .addr = state->config.demod_address, + .flags = I2C_M_RD, + .buf = b1, .len = 1 } }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) { + printk("%s: readreg error (reg=%d, ret==%i)\n", + __FUNCTION__, reg, ret); + return ret; + } + + return b1[0]; +} + +void zl10353_dump_regs(struct dvb_frontend *fe) +{ + struct zl10353_state *state = fe->demodulator_priv; + char buf[52], buf2[4]; + int ret; + u8 reg; + + /* Dump all registers. */ + for (reg = 0; ; reg++) { + if (reg % 16 == 0) { + if (reg) + printk(KERN_DEBUG "%s\n", buf); + sprintf(buf, "%02x: ", reg); + } + ret = zl10353_read_register(state, reg); + if (ret >= 0) + sprintf(buf2, "%02x ", (u8)ret); + else + strcpy(buf2, "-- "); + strcat(buf, buf2); + if (reg == 0xff) + break; + } + printk(KERN_DEBUG "%s\n", buf); +} + +static int zl10353_sleep(struct dvb_frontend *fe) +{ + static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 }; + + zl10353_write(fe, zl10353_softdown, sizeof(zl10353_softdown)); + return 0; +} + +static int zl10353_set_parameters(struct dvb_frontend *fe, + struct dvb_frontend_parameters *param) +{ + struct zl10353_state *state = fe->demodulator_priv; + u8 pllbuf[6] = { 0x67 }; + + /* These settings set "auto-everything" and start the FSM. */ + zl10353_single_write(fe, 0x55, 0x80); + udelay(200); + zl10353_single_write(fe, 0xEA, 0x01); + udelay(200); + zl10353_single_write(fe, 0xEA, 0x00); + + zl10353_single_write(fe, 0x56, 0x28); + zl10353_single_write(fe, 0x89, 0x20); + zl10353_single_write(fe, 0x5E, 0x00); + zl10353_single_write(fe, 0x65, 0x5A); + zl10353_single_write(fe, 0x66, 0xE9); + zl10353_single_write(fe, 0x62, 0x0A); + + state->config.pll_set(fe, param, pllbuf + 1); + zl10353_write(fe, pllbuf, sizeof(pllbuf)); + + zl10353_single_write(fe, 0x70, 0x01); + udelay(250); + zl10353_single_write(fe, 0xE4, 0x00); + zl10353_single_write(fe, 0xE5, 0x2A); + zl10353_single_write(fe, 0xE9, 0x02); + zl10353_single_write(fe, 0xE7, 0x40); + zl10353_single_write(fe, 0xE8, 0x10); + + return 0; +} + +static int zl10353_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct zl10353_state *state = fe->demodulator_priv; + int s6, s7, s8; + + if ((s6 = zl10353_read_register(state, STATUS_6)) < 0) + return -EREMOTEIO; + if ((s7 = zl10353_read_register(state, STATUS_7)) < 0) + return -EREMOTEIO; + if ((s8 = zl10353_read_register(state, STATUS_8)) < 0) + return -EREMOTEIO; + + *status = 0; + if (s6 & (1 << 2)) + *status |= FE_HAS_CARRIER; + if (s6 & (1 << 1)) + *status |= FE_HAS_VITERBI; + if (s6 & (1 << 5)) + *status |= FE_HAS_LOCK; + if (s7 & (1 << 4)) + *status |= FE_HAS_SYNC; + if (s8 & (1 << 6)) + *status |= FE_HAS_SIGNAL; + + if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != + (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) + *status &= ~FE_HAS_LOCK; + + return 0; +} + +static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct zl10353_state *state = fe->demodulator_priv; + u8 _snr; + + if (debug_regs) + zl10353_dump_regs(fe); + + _snr = zl10353_read_register(state, SNR); + *snr = (_snr << 8) | _snr; + + return 0; +} + +static int zl10353_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings + *fe_tune_settings) +{ + fe_tune_settings->min_delay_ms = 1000; + fe_tune_settings->step_size = 0; + fe_tune_settings->max_drift = 0; + + return 0; +} + +static int zl10353_init(struct dvb_frontend *fe) +{ + struct zl10353_state *state = fe->demodulator_priv; + u8 zl10353_reset_attach[6] = { 0x50, 0x03, 0x64, 0x46, 0x15, 0x0F }; + int rc = 0; + + if (debug_regs) + zl10353_dump_regs(fe); + + /* Do a "hard" reset if not already done */ + if (zl10353_read_register(state, 0x50) != 0x03) { + rc = zl10353_write(fe, zl10353_reset_attach, + sizeof(zl10353_reset_attach)); + if (debug_regs) + zl10353_dump_regs(fe); + } + + return 0; +} + +static void zl10353_release(struct dvb_frontend *fe) +{ + struct zl10353_state *state = fe->demodulator_priv; + + kfree(state); +} + +static struct dvb_frontend_ops zl10353_ops; + +struct dvb_frontend *zl10353_attach(const struct zl10353_config *config, + struct i2c_adapter *i2c) +{ + struct zl10353_state *state = NULL; + + /* allocate memory for the internal state */ + state = kzalloc(sizeof(struct zl10353_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->i2c = i2c; + memcpy(&state->config, config, sizeof(struct zl10353_config)); + memcpy(&state->ops, &zl10353_ops, sizeof(struct dvb_frontend_ops)); + + /* check if the demod is there */ + if (zl10353_read_register(state, CHIP_ID) != ID_ZL10353) + goto error; + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + + return &state->frontend; +error: + kfree(state); + return NULL; +} + +static struct dvb_frontend_ops zl10353_ops = { + + .info = { + .name = "Zarlink ZL10353 DVB-T", + .type = FE_OFDM, + .frequency_min = 174000000, + .frequency_max = 862000000, + .frequency_stepsize = 166667, + .frequency_tolerance = 0, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | + FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | + FE_CAN_MUTE_TS + }, + + .release = zl10353_release, + + .init = zl10353_init, + .sleep = zl10353_sleep, + + .set_frontend = zl10353_set_parameters, + .get_tune_settings = zl10353_get_tune_settings, + + .read_status = zl10353_read_status, + .read_snr = zl10353_read_snr, +}; + +module_param(debug_regs, int, 0644); +MODULE_PARM_DESC(debug_regs, "Turn on/off frontend register dumps (default:off)."); + +MODULE_DESCRIPTION("Zarlink ZL10353 DVB-T demodulator driver"); +MODULE_AUTHOR("Chris Pascoe"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(zl10353_attach); +EXPORT_SYMBOL(zl10353_write); diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h new file mode 100644 index 000000000000..5cc4ae718d8c --- /dev/null +++ b/drivers/media/dvb/frontends/zl10353.h @@ -0,0 +1,43 @@ +/* + * Driver for Zarlink DVB-T ZL10353 demodulator + * + * Copyright (C) 2006 Christopher Pascoe + * + * 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.= + */ + +#ifndef ZL10353_H +#define ZL10353_H + +#include + +struct zl10353_config +{ + /* demodulator's I2C address */ + u8 demod_address; + + /* function which configures the PLL buffer (for secondary I2C + * connected tuner) or tunes the PLL (for direct connected tuner) */ + int (*pll_set)(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, u8 *pllbuf); +}; + +extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config, + struct i2c_adapter *i2c); + +extern int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen); + +#endif /* ZL10353_H */ diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb/frontends/zl10353_priv.h new file mode 100644 index 000000000000..b72224bd7dde --- /dev/null +++ b/drivers/media/dvb/frontends/zl10353_priv.h @@ -0,0 +1,42 @@ +/* + * Driver for Zarlink DVB-T ZL10353 demodulator + * + * Copyright (C) 2006 Christopher Pascoe + * + * 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.= + */ + +#ifndef _ZL10353_PRIV_ +#define _ZL10353_PRIV_ + +#define ID_ZL10353 0x14 + +enum zl10353_reg_addr { + INTERRUPT_0 = 0x00, + INTERRUPT_1 = 0x01, + INTERRUPT_2 = 0x02, + INTERRUPT_3 = 0x03, + INTERRUPT_4 = 0x04, + INTERRUPT_5 = 0x05, + STATUS_6 = 0x06, + STATUS_7 = 0x07, + STATUS_8 = 0x08, + STATUS_9 = 0x09, + SNR = 0x10, + CHIP_ID = 0x7F, +}; + +#endif /* _ZL10353_PRIV_ */ diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 2b902784facc..6482b9aa6a1f 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -17,6 +17,7 @@ extra-cflags-$(CONFIG_DVB_CX22702) += -DHAVE_CX22702=1 extra-cflags-$(CONFIG_DVB_OR51132) += -DHAVE_OR51132=1 extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1 extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1 +extra-cflags-$(CONFIG_DVB_ZL10353) += -DHAVE_ZL10353=1 extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1 extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1 extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1 diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 44e27dc646ae..d91e5b3a64ef 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1071,6 +1071,27 @@ struct cx88_board cx88_boards[] = { .gpio2 = 0x00ff, }, }, + [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = { + .name = "DViCO FusionHDTV DVB-T Hybrid", + .tuner_type = TUNER_FE6600, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0000a75f, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0000a75b, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x0000a75b, + }}, + .dvb = 1, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -1281,6 +1302,14 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x17de, .subdevice = 0x0840, .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, + },{ + .subvendor = 0x18ac, + .subdevice = 0xdb40, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID, + },{ + .subvendor = 0x18ac, + .subdevice = 0xdb44, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); @@ -1399,6 +1428,40 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) core->has_radio = gdi_tuner[eeprom_data[0x0d]].fm; } +/* ----------------------------------------------------------------------- */ +/* some DViCO specific stuff */ + +static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core) +{ + struct i2c_msg msg = { .addr = 0x45, .flags = 0 }; + int i, err; + u8 init_bufs[13][5] = { + { 0x10, 0x00, 0x20, 0x01, 0x03 }, + { 0x10, 0x10, 0x01, 0x00, 0x21 }, + { 0x10, 0x10, 0x10, 0x00, 0xCA }, + { 0x10, 0x10, 0x12, 0x00, 0x08 }, + { 0x10, 0x10, 0x13, 0x00, 0x0A }, + { 0x10, 0x10, 0x16, 0x01, 0xC0 }, + { 0x10, 0x10, 0x22, 0x01, 0x3D }, + { 0x10, 0x10, 0x73, 0x01, 0x2E }, + { 0x10, 0x10, 0x72, 0x00, 0xC5 }, + { 0x10, 0x10, 0x71, 0x01, 0x97 }, + { 0x10, 0x10, 0x70, 0x00, 0x0F }, + { 0x10, 0x10, 0xB0, 0x00, 0x01 }, + { 0x03, 0x0C }, + }; + + for (i = 0; i < 13; i++) { + msg.buf = init_bufs[i]; + msg.len = (i != 12 ? 5 : 2); + err = i2c_transfer(&core->i2c_adap, &msg, 1); + if (err != 1) { + printk("dvico_fusionhdtv_hybrid_init buf %d failed (err = %d)!\n", i, err); + return; + } + } +} + /* ----------------------------------------------------------------------- */ void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) @@ -1465,11 +1528,15 @@ void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: /* GPIO0:0 is hooked to mt352 reset pin */ cx_set(MO_GP0_IO, 0x00000101); cx_clear(MO_GP0_IO, 0x00000001); msleep(1); cx_set(MO_GP0_IO, 0x00000101); + if (0 == core->i2c_rc && + core->board == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID) + dvico_fusionhdtv_hybrid_init(core); break; case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T: diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index e48aa3f6e500..2c97d3f7101a 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -40,6 +40,9 @@ # include "cx88-vp3054-i2c.h" # endif #endif +#ifdef HAVE_ZL10353 +# include "zl10353.h" +#endif #ifdef HAVE_CX22702 # include "cx22702.h" #endif @@ -111,6 +114,21 @@ static struct videobuf_queue_ops dvb_qops = { /* ------------------------------------------------------------------ */ +#if defined(HAVE_MT352) || defined(HAVE_ZL10353) +static int zarlink_pll_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, + u8 *pllbuf) +{ + struct cx8802_dev *dev = fe->dvb->priv; + + pllbuf[0] = dev->core->pll_addr << 1; + dvb_pll_configure(dev->core->pll_desc, pllbuf + 1, + params->frequency, + params->u.ofdm.bandwidth); + return 0; +} +#endif + #ifdef HAVE_MT352 static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) { @@ -176,35 +194,22 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) return 0; } -static int mt352_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params, - u8* pllbuf) -{ - struct cx8802_dev *dev= fe->dvb->priv; - - pllbuf[0] = dev->core->pll_addr << 1; - dvb_pll_configure(dev->core->pll_desc, pllbuf+1, - params->frequency, - params->u.ofdm.bandwidth); - return 0; -} - static struct mt352_config dvico_fusionhdtv = { .demod_address = 0x0F, .demod_init = dvico_fusionhdtv_demod_init, - .pll_set = mt352_pll_set, + .pll_set = zarlink_pll_set, }; static struct mt352_config dntv_live_dvbt_config = { .demod_address = 0x0f, .demod_init = dntv_live_dvbt_demod_init, - .pll_set = mt352_pll_set, + .pll_set = zarlink_pll_set, }; static struct mt352_config dvico_fusionhdtv_dual = { .demod_address = 0x0F, .demod_init = dvico_dual_demod_init, - .pll_set = mt352_pll_set, + .pll_set = zarlink_pll_set, }; #ifdef HAVE_VP3054_I2C @@ -294,6 +299,46 @@ static struct mt352_config dntv_live_dvbt_pro_config = { #endif #endif +#ifdef HAVE_ZL10353 +static int dvico_hybrid_tune_pll(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, + u8 *pllbuf) +{ + struct cx8802_dev *dev= fe->dvb->priv; + struct i2c_msg msg = + { .addr = dev->core->pll_addr, .flags = 0, + .buf = pllbuf + 1, .len = 4 }; + int err; + + pllbuf[0] = dev->core->pll_addr << 1; + dvb_pll_configure(dev->core->pll_desc, pllbuf + 1, + params->frequency, + params->u.ofdm.bandwidth); + + if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "cx88-dvb: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, pllbuf[0], pllbuf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + return 0; +} + +static struct zl10353_config dvico_fusionhdtv_hybrid = { + .demod_address = 0x0F, + .pll_set = dvico_hybrid_tune_pll, +}; + +static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { + .demod_address = 0x0F, + .pll_set = zarlink_pll_set, +}; +#endif + #ifdef HAVE_CX22702 static struct cx22702_config connexant_refboard_config = { .demod_address = 0x43, @@ -500,16 +545,27 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); break; #endif +#if defined(HAVE_MT352) || defined(HAVE_ZL10353) + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: + dev->core->pll_addr = 0x60; + dev->core->pll_desc = &dvb_pll_thomson_dtt7579; #ifdef HAVE_MT352 - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: - dev->core->pll_addr = 0x61; - dev->core->pll_desc = &dvb_pll_lg_z201; dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) + break; +#endif +#ifdef HAVE_ZL10353 + /* ZL10353 replaces MT352 on later cards */ + dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1, + &dev->core->i2c_adap); +#endif break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: - dev->core->pll_addr = 0x60; - dev->core->pll_desc = &dvb_pll_thomson_dtt7579; +#endif /* HAVE_MT352 || HAVE_ZL10353 */ +#ifdef HAVE_MT352 + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: + dev->core->pll_addr = 0x61; + dev->core->pll_desc = &dvb_pll_lg_z201; dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, &dev->core->i2c_adap); break; @@ -540,6 +596,14 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); break; #endif +#ifdef HAVE_ZL10353 + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: + dev->core->pll_addr = 0x61; + dev->core->pll_desc = &dvb_pll_unknown_fe6600; + dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid, + &dev->core->i2c_adap); + break; +#endif #ifdef HAVE_OR51132 case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = or51132_attach(&pchdtv_hd3000, diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index a4cf2473eacf..21738b664bc9 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -189,6 +189,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_KWORLD_DVB_T_CX22702 43 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44 #define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45 +#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 15761dd8607d..d10cfd400f2b 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -983,6 +983,22 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { }, }; +/* ------------ TUNER_FE6600 - DViCO Hybrid PAL ------------ */ + +static struct tuner_range tuner_fe6600_ranges[] = { + { 16 * 160.00 /*MHz*/, 0xfe, 0x11, }, + { 16 * 442.00 /*MHz*/, 0xf6, 0x12, }, + { 16 * 999.99 , 0xf6, 0x18, }, +}; + +static struct tuner_params tuner_fe6600_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_fe6600_ranges, + .count = ARRAY_SIZE(tuner_fe6600_ranges), + }, +}; + /* --------------------------------------------------------------------- */ struct tunertype tuners[] = { @@ -1354,6 +1370,10 @@ struct tunertype tuners[] = { .name = "Xceive xc3028", /* see xc3028.c for details */ }, + [TUNER_FE6600] = { /* */ + .name = "FE6600", + .params = tuner_fe6600_params, + }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/include/media/tuner.h b/include/media/tuner.h index f51759c0d180..039c77e02d34 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -116,9 +116,10 @@ #define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ #define TUNER_TNF_5335MF 69 /* Sabrent Bt848 */ #define TUNER_SAMSUNG_TCPN_2121P30A 70 /* Hauppauge PVR-500MCE NTSC */ - #define TUNER_XCEIVE_XC3028 71 +#define TUNER_FE6600 72 /* DViCO FusionHDTV DVB-T Hybrid */ + /* tv card specific */ #define TDA9887_PRESENT (1<<0) #define TDA9887_PORT1_INACTIVE (1<<1) -- cgit v1.2.3-59-g8ed1b From 0785c87af1d1b6106b14c85f1267be8543f11d00 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 28 Feb 2006 14:02:15 -0300 Subject: V4L/DVB (3409): Kconfig: fix in-kernel build for cx88-dvb: zl10353 frontend - VIDEO_CX88_DVB_ALL_FRONTENDS should select DVB_ZL10353 - created VIDEO_CX88_DVB_ZL10353, for selective zl10353 support in cx88-dvb. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index e99dfbbf3e95..b52a243c357e 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -50,6 +50,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS depends on VIDEO_CX88_DVB select DVB_MT352 select VIDEO_CX88_VP3054 + select DVB_ZL10353 select DVB_OR51132 select DVB_CX22702 select DVB_LGDT330X @@ -81,6 +82,16 @@ config VIDEO_CX88_VP3054 which also require support for the VP-3054 Secondary I2C bus, such at DNTV Live! DVB-T Pro. +config VIDEO_CX88_DVB_ZL10353 + bool "Zarlink ZL10353 DVB-T Support" + default y + depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS + select DVB_ZL10353 + ---help--- + This adds DVB-T support for cards based on the + Connexant 2388x chip and the ZL10353 demodulator, + successor to the Zarlink MT352. + config VIDEO_CX88_DVB_OR51132 bool "OR51132 ATSC Support" default y -- cgit v1.2.3-59-g8ed1b From 69b27e3dfebff8f59e979d57263e1cd83c4d8370 Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Tue, 28 Feb 2006 20:23:11 -0300 Subject: V4L/DVB (3410): Move DViCO hybrid initialisation data from stack. The init_data array is never changed and need not be on the stack. Turn it into a static variable. Signed-off-by: Michael Krufky Signed-off-by: Chris Pascoe Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index d91e5b3a64ef..f655567a8ecd 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1435,7 +1435,7 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core) { struct i2c_msg msg = { .addr = 0x45, .flags = 0 }; int i, err; - u8 init_bufs[13][5] = { + static u8 init_bufs[13][5] = { { 0x10, 0x00, 0x20, 0x01, 0x03 }, { 0x10, 0x10, 0x01, 0x00, 0x21 }, { 0x10, 0x10, 0x10, 0x00, 0xCA }, -- cgit v1.2.3-59-g8ed1b From 91ae3299d7d3493a25e5f26cbaceeb18e7760ef3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 1 Mar 2006 00:04:42 -0300 Subject: V4L/DVB (3411): FE6600 is a Thomson tuner - The tuner used in DViCO FusionHDTV DVB-T hybrid is made by Thomson - renamed tuner and dvb_pll structs accordingly Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.tuner | 2 +- drivers/media/dvb/frontends/dvb-pll.c | 6 +++--- drivers/media/dvb/frontends/dvb-pll.h | 2 +- drivers/media/video/cx88/cx88-cards.c | 2 +- drivers/media/video/cx88/cx88-dvb.c | 2 +- drivers/media/video/tuner-types.c | 16 ++++++++-------- include/media/tuner.h | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index ab344c94c0a2..603f165376fe 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -70,4 +70,4 @@ tuner=68 - Philips TUV1236D ATSC/NTSC dual in tuner=69 - Tena TNF 5335 MF tuner=70 - Samsung TCPN 2121P30A tuner=71 - Xceive xc3028 -tuner=72 - FE6600 +tuner=72 - Thomson FE6600 diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 8a4c904d3a27..b6e2c387a04c 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -405,8 +405,8 @@ struct dvb_pll_desc dvb_pll_philips_td1316 = { EXPORT_SYMBOL(dvb_pll_philips_td1316); /* FE6600 used on DViCO Hybrid */ -struct dvb_pll_desc dvb_pll_unknown_fe6600 = { - .name = "FE6600", +struct dvb_pll_desc dvb_pll_thomson_fe6600 = { + .name = "Thomson FE6600", .min = 44250000, .max = 858000000, .count = 4, @@ -417,7 +417,7 @@ struct dvb_pll_desc dvb_pll_unknown_fe6600 = { { 999999999, 36213333, 166667, 0xf4, 0x18 }, } }; -EXPORT_SYMBOL(dvb_pll_unknown_fe6600); +EXPORT_SYMBOL(dvb_pll_thomson_fe6600); /* ----------------------------------------------------------- */ /* code */ diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 8a7f0b941c38..2b8461784989 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -42,7 +42,7 @@ extern struct dvb_pll_desc dvb_pll_samsung_tbmv; extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261; extern struct dvb_pll_desc dvb_pll_philips_td1316; -extern struct dvb_pll_desc dvb_pll_unknown_fe6600; +extern struct dvb_pll_desc dvb_pll_thomson_fe6600; int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, u32 freq, int bandwidth); diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index f655567a8ecd..c0d1f0b12829 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1073,7 +1073,7 @@ struct cx88_board cx88_boards[] = { }, [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = { .name = "DViCO FusionHDTV DVB-T Hybrid", - .tuner_type = TUNER_FE6600, + .tuner_type = TUNER_THOMSON_FE6600, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 2c97d3f7101a..a9fc2695b157 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -599,7 +599,7 @@ static int dvb_register(struct cx8802_dev *dev) #ifdef HAVE_ZL10353 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: dev->core->pll_addr = 0x61; - dev->core->pll_desc = &dvb_pll_unknown_fe6600; + dev->core->pll_desc = &dvb_pll_thomson_fe6600; dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid, &dev->core->i2c_adap); break; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index d10cfd400f2b..db8b9873029b 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -983,19 +983,19 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { }, }; -/* ------------ TUNER_FE6600 - DViCO Hybrid PAL ------------ */ +/* ------------ TUNER_THOMSON_FE6600 - DViCO Hybrid PAL ------------ */ -static struct tuner_range tuner_fe6600_ranges[] = { +static struct tuner_range tuner_thomson_fe6600_ranges[] = { { 16 * 160.00 /*MHz*/, 0xfe, 0x11, }, { 16 * 442.00 /*MHz*/, 0xf6, 0x12, }, { 16 * 999.99 , 0xf6, 0x18, }, }; -static struct tuner_params tuner_fe6600_params[] = { +static struct tuner_params tuner_thomson_fe6600_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_fe6600_ranges, - .count = ARRAY_SIZE(tuner_fe6600_ranges), + .ranges = tuner_thomson_fe6600_ranges, + .count = ARRAY_SIZE(tuner_thomson_fe6600_ranges), }, }; @@ -1370,9 +1370,9 @@ struct tunertype tuners[] = { .name = "Xceive xc3028", /* see xc3028.c for details */ }, - [TUNER_FE6600] = { /* */ - .name = "FE6600", - .params = tuner_fe6600_params, + [TUNER_THOMSON_FE6600] = { /* Thomson PAL / DVB-T */ + .name = "Thomson FE6600", + .params = tuner_thomson_fe6600_params, }, }; diff --git a/include/media/tuner.h b/include/media/tuner.h index 039c77e02d34..02d7d9a76fa2 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -118,7 +118,7 @@ #define TUNER_SAMSUNG_TCPN_2121P30A 70 /* Hauppauge PVR-500MCE NTSC */ #define TUNER_XCEIVE_XC3028 71 -#define TUNER_FE6600 72 /* DViCO FusionHDTV DVB-T Hybrid */ +#define TUNER_THOMSON_FE6600 72 /* DViCO FusionHDTV DVB-T Hybrid */ /* tv card specific */ #define TDA9887_PRESENT (1<<0) -- cgit v1.2.3-59-g8ed1b From be787ace0139bc7ef0229606819bad64bb5d84f4 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 7 Mar 2006 22:20:23 -0300 Subject: V4L/DVB (3413): Typos grab bag of the month Typos grab bag of the month. Eyeballed by jmc@ in OpenBSD. Signed-off-by: Alexey Dobriyan Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/demux.h | 2 +- drivers/media/dvb/dvb-usb/dvb-usb-init.c | 2 +- drivers/media/dvb/dvb-usb/dvb-usb.h | 2 +- drivers/media/dvb/ttpci/av7110.c | 2 +- drivers/media/video/cpia.c | 2 +- drivers/media/video/cpia2/cpia2_v4l.c | 2 +- drivers/media/video/videocodec.h | 2 +- drivers/media/video/zr36050.c | 2 +- drivers/media/video/zr36060.c | 2 +- drivers/media/video/zr36120_i2c.c | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h index 9f025825b2d2..0c1d87c5227a 100644 --- a/drivers/media/dvb/dvb-core/demux.h +++ b/drivers/media/dvb/dvb-core/demux.h @@ -216,7 +216,7 @@ struct dmx_frontend { /*--------------------------------------------------------------------------*/ /* - * Flags OR'ed in the capabilites field of struct dmx_demux. + * Flags OR'ed in the capabilities field of struct dmx_demux. */ #define DMX_TS_FILTERING 1 diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c index 4258a995dce1..a1705ecb9a54 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c @@ -47,7 +47,7 @@ static int dvb_usb_init(struct dvb_usb_device *d) d->state = DVB_USB_STATE_INIT; -/* check the capabilites and set appropriate variables */ +/* check the capabilities and set appropriate variables */ /* speed - when running at FULL speed we need a HW PID filter */ if (d->udev->speed == USB_SPEED_FULL && !(d->props.caps & DVB_USB_HAS_PID_FILTER)) { diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index d2be37cc43b7..fead958a57e3 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -88,7 +88,7 @@ struct dvb_usb_device; /** * struct dvb_usb_properties - properties of a dvb-usb-device - * @caps: capabilites of the DVB USB device. + * @caps: capabilities of the DVB USB device. * @pid_filter_count: number of PID filter position in the optional hardware * PID-filter. * diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 914f2e34d8d3..aef4f58d712d 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -1441,7 +1441,7 @@ static int check_firmware(struct av7110* av7110) len = ntohl(*(u32*) ptr); ptr += 4; if (len >= 512) { - printk("dvb-ttpci: dpram file is way to big.\n"); + printk("dvb-ttpci: dpram file is way too big.\n"); return -EINVAL; } if (crc != crc32_le(0, ptr, len)) { diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index c2405029a720..d93a561e6b80 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -3369,7 +3369,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, //DBG("cpia_ioctl: %u\n", ioctlnr); switch (ioctlnr) { - /* query capabilites */ + /* query capabilities */ case VIDIOCGCAP: { struct video_capability *b = arg; diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 589283d5ddd1..08f8be345fa8 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -1628,7 +1628,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file, } switch (ioctl_nr) { - case VIDIOCGCAP: /* query capabilites */ + case VIDIOCGCAP: /* query capabilities */ retval = ioctl_cap_query(arg, cam); break; diff --git a/drivers/media/video/videocodec.h b/drivers/media/video/videocodec.h index 156ae57096fe..b1239ac7f371 100644 --- a/drivers/media/video/videocodec.h +++ b/drivers/media/video/videocodec.h @@ -56,7 +56,7 @@ the slave is bound to it). Otherwise it doesn't need this functions and therfor they may not be initialized. - The other fuctions are just for convenience, as they are for shure used by + The other fuctions are just for convenience, as they are for sure used by most/all of the codecs. The last ones may be ommited, too. See the structure declaration below for more information and which data has diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c index bd0cd28543ca..6699725be605 100644 --- a/drivers/media/video/zr36050.c +++ b/drivers/media/video/zr36050.c @@ -159,7 +159,7 @@ zr36050_wait_end (struct zr36050 *ptr) while (!(zr36050_read_status1(ptr) & 0x4)) { udelay(1); - if (i++ > 200000) { // 200ms, there is for shure something wrong!!! + if (i++ > 200000) { // 200ms, there is for sure something wrong!!! dprintk(1, "%s: timout at wait_end (last status: 0x%02x)\n", ptr->name, ptr->status1); diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c index 28fa31a5f150..d8dd003a7aad 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zr36060.c @@ -161,7 +161,7 @@ zr36060_wait_end (struct zr36060 *ptr) while (zr36060_read_status(ptr) & ZR060_CFSR_Busy) { udelay(1); - if (i++ > 200000) { // 200ms, there is for shure something wrong!!! + if (i++ > 200000) { // 200ms, there is for sure something wrong!!! dprintk(1, "%s: timout at wait_end (last status: 0x%02x)\n", ptr->name, ptr->status); diff --git a/drivers/media/video/zr36120_i2c.c b/drivers/media/video/zr36120_i2c.c index 6bfe84d657f1..21fde43a6aed 100644 --- a/drivers/media/video/zr36120_i2c.c +++ b/drivers/media/video/zr36120_i2c.c @@ -65,7 +65,7 @@ void attach_inform(struct i2c_bus *bus, int id) case I2C_DRIVERID_VIDEODECODER: DEBUG(printk(CARD_INFO "decoder attached\n",CARD)); - /* fetch the capabilites of the decoder */ + /* fetch the capabilities of the decoder */ rv = i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &dc); if (rv) { DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD)); -- cgit v1.2.3-59-g8ed1b From 793f225b0d77dd6a53614f5e312a28b754144d86 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 8 Mar 2006 10:50:06 -0300 Subject: V4L/DVB (3414): Saa7134: document that there's also a 220RF from KWorld I have the same card with the same PCI id, but from KWorld. The patch documents that this is the same card. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 17ea5a031b30..874ffc4b5cca 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -86,6 +86,6 @@ 85 -> AverTV DVB-T 777 [1461:2c05] 86 -> LifeView FlyDVB-T [5168:0301] 87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421] - 88 -> Tevion DVB-T 220RF [17de:7201] + 88 -> Tevion/KWorld DVB-T 220RF [17de:7201] 89 -> ELSA EX-VISION 700TV [1048:226c] 90 -> Kworld ATSC110 [17de:7350] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index ea2fa0d18927..4071313cc45f 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2706,7 +2706,7 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_TEVION_DVBT_220RF] = { - .name = "Tevion DVB-T 220RF", + .name = "Tevion/KWorld DVB-T 220RF", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, -- cgit v1.2.3-59-g8ed1b From 044f324f6ea5d55391db62fca6a295b2651cb946 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 8 Mar 2006 10:50:07 -0300 Subject: V4L/DVB (3415): Msp3400-kthreads.c: make 3 functions static This patch makes three needlessly global functions static. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-kthreads.c | 6 +++--- drivers/media/video/msp3400.h | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index c4668f4b6e5c..852ab6a115fa 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -154,7 +154,7 @@ const char *msp_standard_std_name(int std) return "unknown"; } -void msp_set_source(struct i2c_client *client, u16 src) +static void msp_set_source(struct i2c_client *client, u16 src) { struct msp_state *state = i2c_get_clientdata(client); @@ -217,7 +217,7 @@ void msp3400c_set_mode(struct i2c_client *client, int mode) /* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP, nor do they support stereo BTSC. */ -void msp3400c_set_audmode(struct i2c_client *client) +static void msp3400c_set_audmode(struct i2c_client *client) { static char *strmode[] = { "mono", "stereo", "lang2", "lang1" }; struct msp_state *state = i2c_get_clientdata(client); @@ -944,7 +944,7 @@ static void msp34xxg_detect_stereo(struct i2c_client *client) status, is_stereo, is_bilingual, state->rxsubchans); } -void msp34xxg_set_audmode(struct i2c_client *client) +static void msp34xxg_set_audmode(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); int source; diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index 418283002130..6fb5c8c994e7 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h @@ -104,7 +104,6 @@ int msp_sleep(struct msp_state *state, int timeout); /* msp3400-kthreads.c */ const char *msp_standard_std_name(int std); -void msp_set_source(struct i2c_client *client, u16 src); void msp_set_audmode(struct i2c_client *client); void msp_detect_stereo(struct i2c_client *client); int msp3400c_thread(void *data); -- cgit v1.2.3-59-g8ed1b From cb764326dff0ee51aca0d450e1a292de65661055 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Wed, 8 Mar 2006 17:24:12 -0800 Subject: e1000: Fix mii-tool access to setting speed and duplex Paul Rolland reported that e1000 was having a hard time using mii-tool to set speed and duplex. This patch fixes the issue on both newer hardware as well as fixing the code issue that originally caused the problem. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher --- drivers/net/e1000/e1000_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 9adaf5fa9d48..5f7e5c808201 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -4171,7 +4171,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) spin_unlock_irqrestore(&adapter->stats_lock, flags); return -EIO; } - if (adapter->hw.phy_type == e1000_phy_m88) { + if (adapter->hw.phy_type == e1000_media_type_copper) { switch (data->reg_num) { case PHY_CTRL: if (mii_reg & MII_CR_POWER_DOWN) @@ -4187,8 +4187,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) else spddplx = SPEED_10; spddplx += (mii_reg & 0x100) - ? FULL_DUPLEX : - HALF_DUPLEX; + ? DUPLEX_FULL : + DUPLEX_HALF; retval = e1000_set_spd_dplx(adapter, spddplx); if (retval) { -- cgit v1.2.3-59-g8ed1b From ad139a2f56e5789aa8a9f74e3600a7f854a38de9 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Thu, 9 Mar 2006 16:37:49 +0100 Subject: [SCSI] scsi_transport_fc: fix FC_HOST_NUM_ATTRS In the past I added an host attribute but unfortunately I forgot to increase FC_HOST_NUM_ATTRS. This is fixed with the patch. Otherwise an fibre channel lld might run into BUG_ON(count > FC_HOST_NUM_ATTRS); in fc_attach_transport(). Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 929032e370db..13ea64119b73 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -223,7 +223,7 @@ static void fc_rport_terminate(struct fc_rport *rport); */ #define FC_STARGET_NUM_ATTRS 3 #define FC_RPORT_NUM_ATTRS 9 -#define FC_HOST_NUM_ATTRS 16 +#define FC_HOST_NUM_ATTRS 17 struct fc_internal { struct scsi_transport_template t; -- cgit v1.2.3-59-g8ed1b From ad58f7dbeb6f5ea82679962f18985f16b660a2d9 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 10 Mar 2006 00:56:16 +0100 Subject: [SCSI] zfcp: fix device registration issues The patch fixes following issues: (1) Replace scsi_add_device with scsi_scan_target. (Thus the rport instead of the scsi_host becomes parent of a scsi_target again.) (2) Avoid scsi_device allocation during registration of an remote port. (Would be done during fc_scsi_scan_rport.) (3) Fix queuecommand behaviour when an zfcp unit is blocked. (Call scsi_done with DID_NO_CONNECT instead of returning SCSI_MLQUEUE_DEVICE_BUSY otherwise we might end up waiting for completion in blk_execute_rq for ever.) Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_erp.c | 11 +++++++---- drivers/s390/scsi/zfcp_scsi.c | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 7f551d66f47f..6eba56cd89ba 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -664,6 +664,7 @@ do { \ #define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002 #define ZFCP_STATUS_UNIT_SHARED 0x00000004 #define ZFCP_STATUS_UNIT_READONLY 0x00000008 +#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010 /* FSF request status (this does not have a common part) */ #define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000 diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index e3c4bdd29a60..57cb628a05aa 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -3391,10 +3391,13 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY, &unit->status)) && !unit->device - && port->rport) - scsi_add_device(port->adapter->scsi_host, 0, - port->rport->scsi_target_id, - unit->scsi_lun); + && port->rport) { + atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED, + &unit->status); + scsi_scan_target(&port->rport->dev, 0, + port->rport->scsi_target_id, + unit->scsi_lun, 0); + } zfcp_unit_put(unit); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index a2de3c9afe49..9e6d07d7b3c8 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -183,7 +183,8 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) read_lock_irqsave(&zfcp_data.config_lock, flags); unit = zfcp_unit_lookup(adapter, sdp->channel, sdp->id, sdp->lun); - if (unit) { + if (unit && atomic_test_mask(ZFCP_STATUS_UNIT_REGISTERED, + &unit->status)) { sdp->hostdata = unit; unit->device = sdp; zfcp_unit_get(unit); @@ -208,6 +209,7 @@ zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; if (unit) { + atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); sdpnt->hostdata = NULL; unit->device = NULL; zfcp_unit_put(unit); @@ -291,7 +293,7 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, "on port 0x%016Lx in recovery\n", zfcp_get_busid_by_unit(unit), unit->fcp_lun, unit->port->wwpn); - retval = SCSI_MLQUEUE_DEVICE_BUSY; + zfcp_scsi_command_fail(scpnt, DID_NO_CONNECT); goto out; } -- cgit v1.2.3-59-g8ed1b From db82f8410ed7546792358964aa5f8dafff1c70a2 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 9 Mar 2006 22:06:36 -0500 Subject: [SCSI] add missing transport_container_unregister in sas class Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 5de29b941c6b..3eb11a175904 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1063,6 +1063,7 @@ void sas_release_transport(struct scsi_transport_template *t) transport_container_unregister(&i->t.host_attrs); transport_container_unregister(&i->phy_attr_cont); transport_container_unregister(&i->rphy_attr_cont); + transport_container_unregister(&i->end_dev_attr_cont); kfree(i); } -- cgit v1.2.3-59-g8ed1b From bb1a813d3c49e57814958d2d52b5bb299204032e Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 11 Mar 2006 19:22:53 +0100 Subject: [PATCH] cpufreq: fix section mismatch warnings cpufreq are the only remaining bit to be solved for me to have a modpost clean build for sparc64 - so I took one more look at it. changelog entry: Fix section mismatch warnings in cpufreq: WARNING: drivers/cpufreq/cpufreq_stats.o - Section mismatch: reference to .init.text: from .data between 'cpufreq_stat_cpu_notifier' (at offset 0xa8) and 'notifier_policy_block' WARNING: drivers/cpufreq/cpufreq_stats.o - Section mismatch: reference to .init.text: from .exit.text after 'cleanup_module' (at offset 0x30) The culprint is the function: cpufreq_stat_cpu_callback It is marked __cpuinit which get's redefined to __init in case HOTPLUG_CPU is not enabled as per. init.h: #ifdef CONFIG_HOTPLUG_CPU #define __cpuinit #else #define __cpuinit __init #endif $> grep HOTPLUG .config CONFIG_HOTPLUG=y But cpufreq_stat_cpu_callback() is used in: __exit cpufreq_stats_exit() static struct notifier_block cpufreq_stat_cpu_notifier cpufreq_stat_cpu_notifier is again used in: __init cpufreq_stats_init() __exit cpufreq_stats_exit() So in both cases used from both __init and __exit context. Only solution seems to drop __cpuinit tag. Signed-off-by: Sam Ravnborg Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index c25bdb7aec51..9694b6ed3268 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -303,7 +303,7 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val, return 0; } -static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, +static int cpufreq_stat_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; -- cgit v1.2.3-59-g8ed1b From 86e45b6bd6900c4a0b3666fb18b46e215f775c4f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 15:29:09 +0900 Subject: [PATCH] libata: implement port_task Implement port_task. LLDD's can schedule a function to be executed with context after specified delay. libata core takes care of synchronization against EH. This is generalized form of pio_task and packet_task which are tied to PIO hsm implementation. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata-scsi.c | 2 ++ drivers/scsi/libata.h | 1 + include/linux/libata.h | 4 +++ 4 files changed, 84 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5dbcf0cf4a10..d59d462130c1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -721,6 +721,81 @@ static unsigned int ata_pio_modes(const struct ata_device *adev) timing API will get this right anyway */ } +/** + * ata_port_queue_task - Queue port_task + * @ap: The ata_port to queue port_task for + * + * Schedule @fn(@data) for execution after @delay jiffies using + * port_task. There is one port_task per port and it's the + * user(low level driver)'s responsibility to make sure that only + * one task is active at any given time. + * + * libata core layer takes care of synchronization between + * port_task and EH. ata_port_queue_task() may be ignored for EH + * synchronization. + * + * LOCKING: + * Inherited from caller. + */ +void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, + unsigned long delay) +{ + int rc; + + if (ap->flags & ATA_FLAG_FLUSH_PIO_TASK) + return; + + PREPARE_WORK(&ap->port_task, fn, data); + + if (!delay) + rc = queue_work(ata_wq, &ap->port_task); + else + rc = queue_delayed_work(ata_wq, &ap->port_task, delay); + + /* rc == 0 means that another user is using port task */ + WARN_ON(rc == 0); +} + +/** + * ata_port_flush_task - Flush port_task + * @ap: The ata_port to flush port_task for + * + * After this function completes, port_task is guranteed not to + * be running or scheduled. + * + * LOCKING: + * Kernel thread context (may sleep) + */ +void ata_port_flush_task(struct ata_port *ap) +{ + unsigned long flags; + + DPRINTK("ENTER\n"); + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags |= ATA_FLAG_FLUSH_PIO_TASK; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("flush #1\n"); + flush_workqueue(ata_wq); + + /* + * At this point, if a task is running, it's guaranteed to see + * the FLUSH flag; thus, it will never queue pio tasks again. + * Cancel and flush. + */ + if (!cancel_delayed_work(&ap->port_task)) { + DPRINTK("flush #2\n"); + flush_workqueue(ata_wq); + } + + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK; + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + DPRINTK("EXIT\n"); +} + static inline void ata_queue_packet_task(struct ata_port *ap) { @@ -4617,6 +4692,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->port_task, NULL, NULL); INIT_WORK(&ap->packet_task, atapi_packet_task, ap); INIT_WORK(&ap->pio_task, ata_pio_task, ap); INIT_LIST_HEAD(&ap->eh_done_q); @@ -5088,6 +5164,7 @@ EXPORT_SYMBOL_GPL(ata_dev_revalidate); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); 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_timed_out); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index d0bd94abb413..ccedb4536977 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -785,6 +785,8 @@ int ata_scsi_error(struct Scsi_Host *host) 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); WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index d822eba05f3c..f4c48c91b63d 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -45,6 +45,7 @@ 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_port_flush_task(struct ata_port *ap); extern void ata_qc_free(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); diff --git a/include/linux/libata.h b/include/linux/libata.h index 66dce58f1941..3ad2570f663b 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -388,6 +388,8 @@ struct ata_port { struct ata_host_stats stats; struct ata_host_set *host_set; + struct work_struct port_task; + struct work_struct packet_task; struct work_struct pio_task; @@ -515,6 +517,8 @@ extern int ata_ratelimit(void); extern unsigned int ata_busy_sleep(struct ata_port *ap, unsigned long timeout_pat, unsigned long timeout); +extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), + void *data, unsigned long delay); /* * Default driver ops implementations -- cgit v1.2.3-59-g8ed1b From 8061f5f0a04cfd2bc7aa273596ad3fcd426f8eea Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 15:29:09 +0900 Subject: [PATCH] libata: convert pio_task and packet_task to port_task Make pio_task and atapi_packet_task use port_task. atapi_packet_task() is moved upward such that it's right after ata_pio_task(). This position is more natural and makes adding prototype for ata_qc_issue_prot() unnecessary. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 154 ++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 77 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d59d462130c1..16a108d2f9a9 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3709,11 +3709,83 @@ fsm_start: } if (timeout) - ata_queue_delayed_pio_task(ap, timeout); + ata_port_queue_task(ap, ata_pio_task, ap, timeout); else if (!qc_completed) 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); + 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 @@ -4013,26 +4085,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_queue_pio_task(ap); + ata_port_queue_task(ap, ata_pio_task, ap, 0); break; case ATA_PROT_ATAPI: ata_qc_set_polling(qc); ata_tf_to_host(ap, &qc->tf); - ata_queue_packet_task(ap); + ata_port_queue_task(ap, atapi_packet_task, ap, 0); break; case ATA_PROT_ATAPI_NODATA: ap->flags |= ATA_FLAG_NOINTR; ata_tf_to_host(ap, &qc->tf); - ata_queue_packet_task(ap); + ata_port_queue_task(ap, atapi_packet_task, ap, 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_queue_packet_task(ap); + ata_port_queue_task(ap, atapi_packet_task, ap, 0); break; default: @@ -4400,78 +4472,6 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) return IRQ_RETVAL(handled); } -/** - * 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); - 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_queue_pio_task(ap); - } - - return; - -err_out: - ata_poll_qc_complete(qc); -} - /* * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, -- cgit v1.2.3-59-g8ed1b From 507ceda00302c071029277652d9faa5a0a55419a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 15:29:09 +0900 Subject: [PATCH] libata: kill unused pio_task and packet_task Kill unused pio_task and packet_task. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 68 ---------------------------------------------- include/linux/libata.h | 3 -- 2 files changed, 71 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 16a108d2f9a9..2974438d3bb7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -796,71 +796,6 @@ void ata_port_flush_task(struct ata_port *ap) DPRINTK("EXIT\n"); } -static inline void -ata_queue_packet_task(struct ata_port *ap) -{ - if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) - queue_work(ata_wq, &ap->packet_task); -} - -static inline void -ata_queue_pio_task(struct ata_port *ap) -{ - if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) - queue_work(ata_wq, &ap->pio_task); -} - -static inline void -ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay) -{ - if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) - queue_delayed_work(ata_wq, &ap->pio_task, delay); -} - -/** - * ata_flush_pio_tasks - Flush pio_task and packet_task - * @ap: the target ata_port - * - * After this function completes, pio_task and packet_task are - * guranteed not to be running or scheduled. - * - * LOCKING: - * Kernel thread context (may sleep) - */ - -static void ata_flush_pio_tasks(struct ata_port *ap) -{ - int tmp = 0; - unsigned long flags; - - DPRINTK("ENTER\n"); - - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags |= ATA_FLAG_FLUSH_PIO_TASK; - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - DPRINTK("flush #1\n"); - flush_workqueue(ata_wq); - - /* - * At this point, if a task is running, it's guaranteed to see - * the FLUSH flag; thus, it will never queue pio tasks again. - * 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); - } - - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK; - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - DPRINTK("EXIT\n"); -} - void ata_qc_complete_internal(struct ata_queued_cmd *qc) { struct completion *waiting = qc->private_data; @@ -3814,7 +3749,6 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) DPRINTK("ENTER\n"); - ata_flush_pio_tasks(ap); ap->hsm_task_state = HSM_ST_IDLE; spin_lock_irqsave(&host_set->lock, flags); @@ -4693,8 +4627,6 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->last_ctl = 0xFF; INIT_WORK(&ap->port_task, NULL, NULL); - INIT_WORK(&ap->packet_task, atapi_packet_task, ap); - INIT_WORK(&ap->pio_task, ata_pio_task, ap); INIT_LIST_HEAD(&ap->eh_done_q); for (i = 0; i < ATA_MAX_DEVICES; i++) diff --git a/include/linux/libata.h b/include/linux/libata.h index 3ad2570f663b..9ad020ac8591 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -390,9 +390,6 @@ struct ata_port { struct work_struct port_task; - struct work_struct packet_task; - - struct work_struct pio_task; unsigned int hsm_task_state; unsigned long pio_task_timeout; -- cgit v1.2.3-59-g8ed1b From 2e755f68ee23b03484fde18d978f910cc5479cb8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 5 Mar 2006 15:29:09 +0900 Subject: [PATCH] libata: rename ATA_FLAG_FLUSH_PIO_TASK to ATA_FLAG_FLUSH_PORT_TASK Rename ATA_FLAG_FLUSH_PIO_TASK to ATA_FLAG_FLUSH_PORT_TASK. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 +++--- include/linux/libata.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 2974438d3bb7..6d8aa86f2f6b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -742,7 +742,7 @@ void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, { int rc; - if (ap->flags & ATA_FLAG_FLUSH_PIO_TASK) + if (ap->flags & ATA_FLAG_FLUSH_PORT_TASK) return; PREPARE_WORK(&ap->port_task, fn, data); @@ -773,7 +773,7 @@ void ata_port_flush_task(struct ata_port *ap) DPRINTK("ENTER\n"); spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags |= ATA_FLAG_FLUSH_PIO_TASK; + ap->flags |= ATA_FLAG_FLUSH_PORT_TASK; spin_unlock_irqrestore(&ap->host_set->lock, flags); DPRINTK("flush #1\n"); @@ -790,7 +790,7 @@ void ata_port_flush_task(struct ata_port *ap) } spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK; + ap->flags &= ~ATA_FLAG_FLUSH_PORT_TASK; spin_unlock_irqrestore(&ap->host_set->lock, flags); DPRINTK("EXIT\n"); diff --git a/include/linux/libata.h b/include/linux/libata.h index 9ad020ac8591..15674923cc84 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -151,7 +151,7 @@ enum { 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_PIO_TASK = (1 << 15), /* Flush PIO task */ + 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 */ -- cgit v1.2.3-59-g8ed1b From 1da7b0d01b20bf21f3263d8d2f17fa49a214d773 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 6 Mar 2006 04:31:56 +0900 Subject: [PATCH] libata: improve xfer mask constants and update ata_mode_string() Add ATA_BITS_*, ATA_MASK_* macros and reorder xfer_mask fields such that higher transfer mode is placed at higher order bit. As thie reordering breaks ata_mode_string(), this patch also rewrites ata_mode_string(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 44 +++++++++++++++++--------------------------- include/linux/libata.h | 16 ++++++++++++---- 2 files changed, 29 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 6d8aa86f2f6b..18418c82d6f6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -232,6 +232,14 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc) } static const char * const xfer_mode_str[] = { + "PIO0", + "PIO1", + "PIO2", + "PIO3", + "PIO4", + "MWDMA0", + "MWDMA1", + "MWDMA2", "UDMA/16", "UDMA/25", "UDMA/33", @@ -240,49 +248,31 @@ static const char * const xfer_mode_str[] = { "UDMA/100", "UDMA/133", "UDMA7", - "MWDMA0", - "MWDMA1", - "MWDMA2", - "PIO0", - "PIO1", - "PIO2", - "PIO3", - "PIO4", }; /** - * ata_udma_string - convert UDMA bit offset to string - * @mask: mask of bits supported; only highest bit counts. + * ata_mode_string - convert xfer_mask to string + * @xfer_mask: mask of bits supported; only highest bit counts. * * Determine string which represents the highest speed - * (highest bit in @udma_mask). + * (highest bit in @modemask). * * LOCKING: * None. * * RETURNS: * Constant C string representing highest speed listed in - * @udma_mask, or the constant C string "". + * @mode_mask, or the constant C string "". */ -static const char *ata_mode_string(unsigned int mask) +static const char *ata_mode_string(unsigned int xfer_mask) { - int i; - - for (i = 7; i >= 0; i--) - if (mask & (1 << i)) - goto out; - for (i = ATA_SHIFT_MWDMA + 2; i >= ATA_SHIFT_MWDMA; i--) - if (mask & (1 << i)) - goto out; - for (i = ATA_SHIFT_PIO + 4; i >= ATA_SHIFT_PIO; i--) - if (mask & (1 << i)) - goto out; + int highbit; + highbit = fls(xfer_mask) - 1; + if (highbit >= 0 && highbit < ARRAY_SIZE(xfer_mode_str)) + return xfer_mode_str[highbit]; return ""; - -out: - return xfer_mode_str[i]; } /** diff --git a/include/linux/libata.h b/include/linux/libata.h index 15674923cc84..239408ecfddf 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -188,11 +188,19 @@ enum { PORT_DISABLED = 2, /* encoding various smaller bitmaps into a single - * unsigned long bitmap + * unsigned int bitmap */ - ATA_SHIFT_UDMA = 0, - ATA_SHIFT_MWDMA = 8, - ATA_SHIFT_PIO = 11, + ATA_BITS_PIO = 5, + ATA_BITS_MWDMA = 3, + ATA_BITS_UDMA = 8, + + ATA_SHIFT_PIO = 0, + ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_BITS_PIO, + ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_BITS_MWDMA, + + ATA_MASK_PIO = ((1 << ATA_BITS_PIO) - 1) << ATA_SHIFT_PIO, + ATA_MASK_MWDMA = ((1 << ATA_BITS_MWDMA) - 1) << ATA_SHIFT_MWDMA, + ATA_MASK_UDMA = ((1 << ATA_BITS_UDMA) - 1) << ATA_SHIFT_UDMA, /* size of buffer to pad xfers ending on unaligned boundaries */ ATA_DMA_PAD_SZ = 4, -- cgit v1.2.3-59-g8ed1b From cb95d562e40140572efbca809f372e608aff7326 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 6 Mar 2006 04:31:56 +0900 Subject: [PATCH] libata: add xfer_mask handling functions Add ata_pack_xfermask(), ata_xfer_mask2mode(), ata_xfer_mode2mask(), ata_xfer_mode2shift() and ata_id_xfermask(). These functions will be used by following patches to simplify xfer_mask handling. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 147 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 18418c82d6f6..9946618f1a35 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -231,6 +231,108 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc) return -1; } +/** + * ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask + * @pio_mask: pio_mask + * @mwdma_mask: mwdma_mask + * @udma_mask: udma_mask + * + * Pack @pio_mask, @mwdma_mask and @udma_mask into a single + * unsigned int xfer_mask. + * + * LOCKING: + * None. + * + * RETURNS: + * Packed xfer_mask. + */ +static unsigned int ata_pack_xfermask(unsigned int pio_mask, + unsigned int mwdma_mask, + unsigned int udma_mask) +{ + return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) | + ((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) | + ((udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA); +} + +static const struct ata_xfer_ent { + unsigned int shift, bits; + u8 base; +} ata_xfer_tbl[] = { + { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 }, + { ATA_SHIFT_MWDMA, ATA_BITS_MWDMA, XFER_MW_DMA_0 }, + { ATA_SHIFT_UDMA, ATA_BITS_UDMA, XFER_UDMA_0 }, + { -1, }, +}; + +/** + * ata_xfer_mask2mode - Find matching XFER_* for the given xfer_mask + * @xfer_mask: xfer_mask of interest + * + * Return matching XFER_* value for @xfer_mask. Only the highest + * bit of @xfer_mask is considered. + * + * LOCKING: + * None. + * + * RETURNS: + * Matching XFER_* value, 0 if no match found. + */ +static u8 ata_xfer_mask2mode(unsigned int xfer_mask) +{ + int highbit = fls(xfer_mask) - 1; + const struct ata_xfer_ent *ent; + + for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) + if (highbit >= ent->shift && highbit < ent->shift + ent->bits) + return ent->base + highbit - ent->shift; + return 0; +} + +/** + * ata_xfer_mode2mask - Find matching xfer_mask for XFER_* + * @xfer_mode: XFER_* of interest + * + * Return matching xfer_mask for @xfer_mode. + * + * LOCKING: + * None. + * + * RETURNS: + * Matching xfer_mask, 0 if no match found. + */ +static unsigned int ata_xfer_mode2mask(u8 xfer_mode) +{ + const struct ata_xfer_ent *ent; + + for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) + if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits) + return 1 << (ent->shift + xfer_mode - ent->base); + return 0; +} + +/** + * ata_xfer_mode2shift - Find matching xfer_shift for XFER_* + * @xfer_mode: XFER_* of interest + * + * Return matching xfer_shift for @xfer_mode. + * + * LOCKING: + * None. + * + * RETURNS: + * Matching xfer_shift, -1 if no match found. + */ +static int ata_xfer_mode2shift(unsigned int xfer_mode) +{ + const struct ata_xfer_ent *ent; + + for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) + if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits) + return ent->shift; + return -1; +} + static const char * const xfer_mode_str[] = { "PIO0", "PIO1", @@ -682,6 +784,51 @@ static inline void ata_dump_id(const u16 *id) id[93]); } +/** + * ata_id_xfermask - Compute xfermask from the given IDENTIFY data + * @id: IDENTIFY data to compute xfer mask from + * + * Compute the xfermask for this device. This is not as trivial + * as it seems if we must consider early devices correctly. + * + * FIXME: pre IDE drive timing (do we care ?). + * + * LOCKING: + * None. + * + * RETURNS: + * Computed xfermask + */ +static unsigned int ata_id_xfermask(const u16 *id) +{ + unsigned int pio_mask, mwdma_mask, udma_mask; + + /* Usual case. Word 53 indicates word 64 is valid */ + if (id[ATA_ID_FIELD_VALID] & (1 << 1)) { + pio_mask = id[ATA_ID_PIO_MODES] & 0x03; + pio_mask <<= 3; + pio_mask |= 0x7; + } else { + /* If word 64 isn't valid then Word 51 high byte holds + * the PIO timing number for the maximum. Turn it into + * a mask. + */ + pio_mask = (2 << (id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ; + + /* But wait.. there's more. Design your standards by + * committee and you too can get a free iordy field to + * process. However its the speeds not the modes that + * are supported... Note drivers using the timing API + * will get this right anyway + */ + } + + mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07; + udma_mask = id[ATA_ID_UDMA_MODES] & 0xff; + + return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask); +} + /* * Compute the PIO modes available for this device. This is not as * trivial as it seems if we must consider early devices correctly. -- cgit v1.2.3-59-g8ed1b From ff8854b2719b9d26f5d3e84db4f66eb7e35e4ed9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 6 Mar 2006 04:31:56 +0900 Subject: [PATCH] libata: use ata_id_xfermask() in ata_dev_configure() Replace quick & dirty max transfer mode determination in ata_dev_configure() with ata_id_xfermask(). While at it, rename xfer_modes variable to xfer_mask and make it unsigned int for consistency. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9946618f1a35..84a8550c56a4 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1224,7 +1224,7 @@ static inline u8 ata_dev_knobble(const struct ata_port *ap, static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, int print_info) { - unsigned long xfer_modes; + unsigned int xfer_mask; int i, rc; if (!ata_dev_present(dev)) { @@ -1255,12 +1255,8 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, goto err_out_nosup; } - /* quick-n-dirty find max transfer mode; for printk only */ - xfer_modes = dev->id[ATA_ID_UDMA_MODES]; - if (!xfer_modes) - xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA; - if (!xfer_modes) - xfer_modes = ata_pio_modes(dev); + /* find max transfer mode; for printk only */ + xfer_mask = ata_id_xfermask(dev->id); ata_dump_id(dev->id); @@ -1284,7 +1280,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, "max %s, %Lu sectors: %s\n", ap->id, dev->devno, ata_id_major_version(dev->id), - ata_mode_string(xfer_modes), + ata_mode_string(xfer_mask), (unsigned long long)dev->n_sectors, lba_desc); } else { @@ -1308,7 +1304,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, "max %s, %Lu sectors: CHS %u/%u/%u\n", ap->id, dev->devno, ata_id_major_version(dev->id), - ata_mode_string(xfer_modes), + ata_mode_string(xfer_mask), (unsigned long long)dev->n_sectors, dev->cylinders, dev->heads, dev->sectors); } @@ -1329,7 +1325,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, /* 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_modes)); + ap->id, dev->devno, ata_mode_string(xfer_mask)); } ap->host->max_cmd_len = 0; -- cgit v1.2.3-59-g8ed1b From 23e71c3d3e88b9f554ecd47d6f9aec76e89e2e6d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 6 Mar 2006 04:31:57 +0900 Subject: [PATCH] libata: use xfer_mask helpers in ata_dev_set_mode() Rewrite hardcoded xfer_mode string determination in ata_dev_set_mode() using xfer_mask helpers. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 84a8550c56a4..88495127efb2 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1752,9 +1752,6 @@ static u8 base_from_shift(unsigned int shift) static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) { - int ofs, idx; - u8 base; - if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) return; @@ -1763,22 +1760,18 @@ static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) ata_dev_set_xfermode(ap, dev); - base = base_from_shift(dev->xfer_shift); - ofs = dev->xfer_mode - base; - idx = ofs + dev->xfer_shift; - WARN_ON(idx >= ARRAY_SIZE(xfer_mode_str)); - if (ata_dev_revalidate(ap, dev, 0)) { printk(KERN_ERR "ata%u: failed to revalidate after set " "xfermode, disabled\n", ap->id); ata_port_disable(ap); } - DPRINTK("idx=%d xfer_shift=%u, xfer_mode=0x%x, base=0x%x, offset=%d\n", - idx, dev->xfer_shift, (int)dev->xfer_mode, (int)base, ofs); + 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, xfer_mode_str[idx]); + ap->id, dev->devno, + ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode))); } static int ata_host_set_pio(struct ata_port *ap) -- cgit v1.2.3-59-g8ed1b From a6d5a51cf1bf5d83ddd2e06fd372a79b395fb393 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 6 Mar 2006 04:31:57 +0900 Subject: [PATCH] libata: reimplement ata_set_mode() using xfer_mask helpers Use xfer_mask helpers to determine transfer mode. This rewrite also makes transfer mode determination done before any actual configuration. This patch doesn't result in any functional changes. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 233 +++++++++++++++------------------------------ 1 file changed, 79 insertions(+), 154 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 88495127efb2..d211f0b1d721 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -65,11 +65,9 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); static void ata_set_mode(struct ata_port *ap); static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); -static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift); +static unsigned int ata_dev_xfermask(struct ata_port *ap, + struct ata_device *dev); static int fgb(u32 bitmap); -static int ata_choose_xfer_mode(const struct ata_port *ap, - u8 *xfer_mode_out, - unsigned int *xfer_shift_out); static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; @@ -1776,51 +1774,42 @@ static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) static int ata_host_set_pio(struct ata_port *ap) { - unsigned int mask; - int x, i; - u8 base, xfer_mode; - - mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO); - x = fgb(mask); - if (x < 0) { - printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); - return -1; - } - - base = base_from_shift(ATA_SHIFT_PIO); - xfer_mode = base + x; - - DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n", - (int)base, (int)xfer_mode, mask, x); + int i; for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; - if (ata_dev_present(dev)) { - dev->pio_mode = xfer_mode; - dev->xfer_mode = xfer_mode; - dev->xfer_shift = ATA_SHIFT_PIO; - if (ap->ops->set_piomode) - ap->ops->set_piomode(ap, dev); + + if (!ata_dev_present(dev)) + continue; + + if (!dev->pio_mode) { + printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); + 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, u8 xfer_mode, - unsigned int xfer_shift) +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_present(dev)) { - dev->dma_mode = xfer_mode; - dev->xfer_mode = xfer_mode; - dev->xfer_shift = xfer_shift; - if (ap->ops->set_dmamode) - ap->ops->set_dmamode(ap, dev); - } + + if (!ata_dev_present(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); } } @@ -1835,28 +1824,34 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, */ static void ata_set_mode(struct ata_port *ap) { - unsigned int xfer_shift; - u8 xfer_mode; - int rc; + int i, rc; - /* step 1: always set host PIO timings */ - rc = ata_host_set_pio(ap); - if (rc) - goto err_out; + /* step 1: calculate xfer_mask */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + unsigned int xfer_mask; + + if (!ata_dev_present(dev)) + continue; - /* step 2: choose the best data xfer mode */ - xfer_mode = xfer_shift = 0; - rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift); + xfer_mask = ata_dev_xfermask(ap, dev); + + dev->pio_mode = ata_xfer_mask2mode(xfer_mask & ATA_MASK_PIO); + dev->dma_mode = ata_xfer_mask2mode(xfer_mask & (ATA_MASK_MWDMA | + ATA_MASK_UDMA)); + } + + /* step 2: always set host PIO timings */ + rc = ata_host_set_pio(ap); if (rc) goto err_out; - /* step 3: if that xfer mode isn't PIO, set host DMA timings */ - if (xfer_shift != ATA_SHIFT_PIO) - ata_host_set_dma(ap, xfer_mode, xfer_shift); + /* step 3: set host DMA timings */ + ata_host_set_dma(ap); /* step 4: update devices' xfer mode */ - ata_dev_set_mode(ap, &ap->device[0]); - ata_dev_set_mode(ap, &ap->device[1]); + for (i = 0; i < ATA_MAX_DEVICES; i++) + ata_dev_set_mode(ap, &ap->device[i]); if (ap->flags & ATA_FLAG_PORT_DISABLED) return; @@ -2654,77 +2649,45 @@ static int ata_dma_blacklisted(const struct ata_device *dev) return 0; } -static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift) +/** + * 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. This function is + * responsible for applying all known limits including host + * controller limits, device blacklist, etc... + * + * LOCKING: + * None. + * + * RETURNS: + * Computed xfermask. + */ +static unsigned int ata_dev_xfermask(struct ata_port *ap, + struct ata_device *dev) { - const struct ata_device *master, *slave; - unsigned int mask; - - master = &ap->device[0]; - slave = &ap->device[1]; + unsigned long xfer_mask; + int i; - WARN_ON(!ata_dev_present(master) && !ata_dev_present(slave)); + xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, + ap->udma_mask); - if (shift == ATA_SHIFT_UDMA) { - mask = ap->udma_mask; - if (ata_dev_present(master)) { - mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff); - if (ata_dma_blacklisted(master)) { - mask = 0; - ata_pr_blacklisted(ap, master); - } - } - if (ata_dev_present(slave)) { - mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff); - if (ata_dma_blacklisted(slave)) { - mask = 0; - ata_pr_blacklisted(ap, slave); - } - } - } - else if (shift == ATA_SHIFT_MWDMA) { - mask = ap->mwdma_mask; - if (ata_dev_present(master)) { - mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07); - if (ata_dma_blacklisted(master)) { - mask = 0; - ata_pr_blacklisted(ap, master); - } - } - if (ata_dev_present(slave)) { - mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07); - if (ata_dma_blacklisted(slave)) { - mask = 0; - ata_pr_blacklisted(ap, slave); - } - } - } - else if (shift == ATA_SHIFT_PIO) { - mask = ap->pio_mask; - if (ata_dev_present(master)) { - /* spec doesn't return explicit support for - * PIO0-2, so we fake it - */ - u16 tmp_mode = master->id[ATA_ID_PIO_MODES] & 0x03; - tmp_mode <<= 3; - tmp_mode |= 0x7; - mask &= tmp_mode; - } - if (ata_dev_present(slave)) { - /* spec doesn't return explicit support for - * PIO0-2, so we fake it - */ - u16 tmp_mode = slave->id[ATA_ID_PIO_MODES] & 0x03; - tmp_mode <<= 3; - tmp_mode |= 0x7; - mask &= tmp_mode; - } - } - else { - mask = 0xffffffff; /* shut up compiler warning */ - BUG(); + /* 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)) + continue; + xfer_mask &= ata_id_xfermask(d->id); + if (ata_dma_blacklisted(d)) + xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); } - return mask; + if (ata_dma_blacklisted(dev)) + printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " + "disabling DMA\n", ap->id, dev->devno); + + return xfer_mask; } /* find greatest bit */ @@ -2740,44 +2703,6 @@ static int fgb(u32 bitmap) return x; } -/** - * ata_choose_xfer_mode - attempt to find best transfer mode - * @ap: Port for which an xfer mode will be selected - * @xfer_mode_out: (output) SET FEATURES - XFER MODE code - * @xfer_shift_out: (output) bit shift that selects this mode - * - * Based on host and device capabilities, determine the - * maximum transfer mode that is amenable to all. - * - * LOCKING: - * PCI/etc. bus probe sem. - * - * RETURNS: - * Zero on success, negative on error. - */ - -static int ata_choose_xfer_mode(const struct ata_port *ap, - u8 *xfer_mode_out, - unsigned int *xfer_shift_out) -{ - unsigned int mask, shift; - int x, i; - - for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) { - shift = xfer_mode_classes[i].shift; - mask = ata_get_mode_mask(ap, shift); - - x = fgb(mask); - if (x >= 0) { - *xfer_mode_out = xfer_mode_classes[i].base + x; - *xfer_shift_out = shift; - return 0; - } - } - - return -1; -} - /** * ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command * @ap: Port associated with device @dev -- cgit v1.2.3-59-g8ed1b From 75f554bc139461a5a926fad6a6fa90433a00a117 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 6 Mar 2006 04:31:57 +0900 Subject: [PATCH] libata: kill unused xfer_mode functions Preceding xfer_mask changes make the following functions unused. ata_pio_modes(), base_from_shift(), ata_pr_blacklisted(), fgb() Kill them. Also, as xfer_mode_str[] is now only used by ata_mode_string(), move it into the function. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 108 ++++++++------------------------------------- 1 file changed, 18 insertions(+), 90 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d211f0b1d721..5acb0798534c 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 void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); static unsigned int ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev); -static int fgb(u32 bitmap); static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; @@ -331,25 +330,6 @@ static int ata_xfer_mode2shift(unsigned int xfer_mode) return -1; } -static const char * const xfer_mode_str[] = { - "PIO0", - "PIO1", - "PIO2", - "PIO3", - "PIO4", - "MWDMA0", - "MWDMA1", - "MWDMA2", - "UDMA/16", - "UDMA/25", - "UDMA/33", - "UDMA/44", - "UDMA/66", - "UDMA/100", - "UDMA/133", - "UDMA7", -}; - /** * ata_mode_string - convert xfer_mask to string * @xfer_mask: mask of bits supported; only highest bit counts. @@ -364,9 +344,26 @@ static const char * const xfer_mode_str[] = { * Constant C string representing highest speed listed in * @mode_mask, or the constant C string "". */ - static const char *ata_mode_string(unsigned int xfer_mask) { + static const char * const xfer_mode_str[] = { + "PIO0", + "PIO1", + "PIO2", + "PIO3", + "PIO4", + "MWDMA0", + "MWDMA1", + "MWDMA2", + "UDMA/16", + "UDMA/25", + "UDMA/33", + "UDMA/44", + "UDMA/66", + "UDMA/100", + "UDMA/133", + "UDMA7", + }; int highbit; highbit = fls(xfer_mask) - 1; @@ -827,35 +824,6 @@ static unsigned int ata_id_xfermask(const u16 *id) return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask); } -/* - * Compute the PIO modes available for this device. This is not as - * trivial as it seems if we must consider early devices correctly. - * - * FIXME: pre IDE drive timing (do we care ?). - */ - -static unsigned int ata_pio_modes(const struct ata_device *adev) -{ - u16 modes; - - /* Usual case. Word 53 indicates word 64 is valid */ - if (adev->id[ATA_ID_FIELD_VALID] & (1 << 1)) { - modes = adev->id[ATA_ID_PIO_MODES] & 0x03; - modes <<= 3; - modes |= 0x7; - return modes; - } - - /* If word 64 isn't valid then Word 51 high byte holds the PIO timing - number for the maximum. Turn it into a mask and return it */ - modes = (2 << ((adev->id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF)) - 1 ; - return modes; - /* But wait.. there's more. Design your standards by committee and - you too can get a free iordy field to process. However its the - speeds not the modes that are supported... Note drivers using the - timing API will get this right anyway */ -} - /** * ata_port_queue_task - Queue port_task * @ap: The ata_port to queue port_task for @@ -1728,26 +1696,6 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, return 0; } -static const struct { - unsigned int shift; - u8 base; -} xfer_mode_classes[] = { - { ATA_SHIFT_UDMA, XFER_UDMA_0 }, - { ATA_SHIFT_MWDMA, XFER_MW_DMA_0 }, - { ATA_SHIFT_PIO, XFER_PIO_0 }, -}; - -static u8 base_from_shift(unsigned int shift) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) - if (xfer_mode_classes[i].shift == shift) - return xfer_mode_classes[i].base; - - return 0xff; -} - static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) { if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) @@ -2596,13 +2544,6 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, return rc; } -static void ata_pr_blacklisted(const struct ata_port *ap, - const struct ata_device *dev) -{ - printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, disabling DMA\n", - ap->id, dev->devno); -} - static const char * const ata_dma_blacklist [] = { "WDC AC11000H", "WDC AC22100H", @@ -2690,19 +2631,6 @@ static unsigned int ata_dev_xfermask(struct ata_port *ap, return xfer_mask; } -/* find greatest bit */ -static int fgb(u32 bitmap) -{ - unsigned int i; - int x = -1; - - for (i = 0; i < 32; i++) - if (bitmap & (1 << i)) - x = i; - - return x; -} - /** * ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command * @ap: Port associated with device @dev -- cgit v1.2.3-59-g8ed1b From 2061a47a9b9530a9523e51167c996307db951c31 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Mar 2006 00:57:39 +0900 Subject: [PATCH] libata: fix missing classes[] initialization in ata_bus_probe() ata_bus_probe() didn't initialize classes[] properly with ATA_DEV_UNKNOWN. As ->probe_reset() is allowed to leave @classes alone when no device is present, this results in garbage class values. ATM, the only affected driver is ata_piix. Signed-off-by: Tejun Heo Cc: Jiri Slaby Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5acb0798534c..5a0b67a602df 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1346,6 +1346,9 @@ static int ata_bus_probe(struct ata_port *ap) /* reset */ if (ap->ops->probe_reset) { + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_UNKNOWN; + rc = ap->ops->probe_reset(ap, classes); if (rc) { printk("ata%u: reset failed (errno=%d)\n", ap->id, rc); -- cgit v1.2.3-59-g8ed1b From 10d996ad1990ec2338c463042db6d5ef4f347187 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 11 Mar 2006 11:42:34 +0900 Subject: [PATCH] sata_sil24: exit early from softreset if SStatus reports no device sata_sil24 softreset routine used to check sata_dev_present() after SRST is complete in the hope that SRST may do some good even when SStatus reports no device. This is okay as long as SRST timeout is short (> 100ms in the current code) but it seems that not all SATA devices are happy with short SRST timeout. This patch makes softreset exit early without performing actual SRST if SStatus reports no device in preparation for lengthening SRST timeout. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 8fb62427be84..fa1a5ac60639 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -440,6 +440,12 @@ static int sil24_softreset(struct ata_port *ap, int verbose, DPRINTK("ENTER\n"); + if (!sata_dev_present(ap)) { + DPRINTK("PHY reports no device\n"); + *class = ATA_DEV_NONE; + goto out; + } + /* temporarily turn off IRQs during SRST */ irq_enable = readl(port + PORT_IRQ_ENABLE_SET); writel(irq_enable, port + PORT_IRQ_ENABLE_CLR); @@ -469,18 +475,18 @@ static int sil24_softreset(struct ata_port *ap, int verbose, /* restore IRQs */ writel(irq_enable, port + PORT_IRQ_ENABLE_SET); - if (sata_dev_present(ap)) { - if (!(irq_stat & PORT_IRQ_COMPLETE)) { - DPRINTK("EXIT, srst failed\n"); - return -EIO; - } - - sil24_update_tf(ap); - *class = ata_dev_classify(&pp->tf); + if (!(irq_stat & PORT_IRQ_COMPLETE)) { + DPRINTK("EXIT, srst failed\n"); + return -EIO; } + + sil24_update_tf(ap); + *class = ata_dev_classify(&pp->tf); + if (*class == ATA_DEV_UNKNOWN) *class = ATA_DEV_NONE; + out: DPRINTK("EXIT, class=%u\n", *class); return 0; } -- cgit v1.2.3-59-g8ed1b From 8645984c357a0262a29b8a28353a576645e2c707 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 11 Mar 2006 11:44:08 +0900 Subject: [PATCH] sata_sil24: lengthen softreset timeout sil24 softreset timeout was > 100ms (100 loops with msleep(1)), which turned out to be too short for some devices (ASI ARAID99 2000). This patch converts sil24 softreset waiting loop to use proper timeout condition and lengthen the timeout to ATA_TMOUT_BOOT secs and check interval to 100ms. Chisato Yamauchi discovered the problem and supplied initial patch. Signed-off-by: Tejun Heo Cc: Chisato Yamauchi Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sil24.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index fa1a5ac60639..9a53a5ed38c5 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -435,8 +435,8 @@ static int sil24_softreset(struct ata_port *ap, int verbose, 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; u32 irq_enable, irq_stat; - int cnt; DPRINTK("ENTER\n"); @@ -461,7 +461,7 @@ static int sil24_softreset(struct ata_port *ap, int verbose, writel((u32)paddr, port + PORT_CMD_ACTIVATE); - for (cnt = 0; cnt < 100; cnt++) { + do { irq_stat = readl(port + PORT_IRQ_STAT); writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ @@ -469,8 +469,8 @@ static int sil24_softreset(struct ata_port *ap, int verbose, if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR)) break; - msleep(1); - } + msleep(100); + } while (time_before(jiffies, timeout)); /* restore IRQs */ writel(irq_enable, port + PORT_IRQ_ENABLE_SET); -- cgit v1.2.3-59-g8ed1b From 827700866ad0996e8c0f5ce75d1c01ae9b034cd6 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 8 Mar 2006 00:06:30 -0800 Subject: [PATCH] CONFIG_FORCEDETH updates This patch contains the following possible updates: - let FORCEDETH no longer depend on EXPERIMENTAL - remove the "Reverse Engineered" from the option text: for the user it's important which hardware the driver supports, not how it was developed Signed-off-by: Adrian Bunk Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d4d8e5f9ebf1..e0b11095b9da 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1372,8 +1372,8 @@ config B44 called b44. config FORCEDETH - tristate "Reverse Engineered nForce Ethernet support (EXPERIMENTAL)" - depends on NET_PCI && PCI && EXPERIMENTAL + tristate "nForce Ethernet support" + depends on NET_PCI && PCI help If you have a network (Ethernet) controller of this type, say Y and read the Ethernet-HOWTO, available from -- cgit v1.2.3-59-g8ed1b From 60a89ff6d2681029b3d46b5d23dccf2903a254b4 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Wed, 8 Mar 2006 00:06:28 -0800 Subject: [PATCH] 3c509: use proper suspend/resume API Convert 3c509 driver to use proper suspend/resume API instead of the deprecated pm_register/pm_unregister. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/3c509.c | 70 ++++++++++++++++++----------------------------------- 1 file changed, 23 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 830528dce0ca..dc845f36fe49 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -100,6 +100,10 @@ static int max_interrupt_work = 10; static char versionA[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n"; +#if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA)) +#define EL3_SUSPEND +#endif + #ifdef EL3_DEBUG static int el3_debug = EL3_DEBUG; #else @@ -174,9 +178,6 @@ struct el3_private { /* skb send-queue */ int head, size; struct sk_buff *queue[SKB_QUEUE_SIZE]; -#ifdef CONFIG_PM_LEGACY - struct pm_dev *pmdev; -#endif enum { EL3_MCA, EL3_PNP, @@ -201,11 +202,15 @@ static void el3_tx_timeout (struct net_device *dev); static void el3_down(struct net_device *dev); static void el3_up(struct net_device *dev); static struct ethtool_ops ethtool_ops; -#ifdef CONFIG_PM_LEGACY -static int el3_suspend(struct pm_dev *pdev); -static int el3_resume(struct pm_dev *pdev); -static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data); +#ifdef EL3_SUSPEND +static int el3_suspend(struct device *, pm_message_t); +static int el3_resume(struct device *); +#else +#define el3_suspend NULL +#define el3_resume NULL #endif + + /* generic device remove for all device types */ #if defined(CONFIG_EISA) || defined(CONFIG_MCA) static int el3_device_remove (struct device *device); @@ -229,7 +234,9 @@ static struct eisa_driver el3_eisa_driver = { .driver = { .name = "3c509", .probe = el3_eisa_probe, - .remove = __devexit_p (el3_device_remove) + .remove = __devexit_p (el3_device_remove), + .suspend = el3_suspend, + .resume = el3_resume, } }; #endif @@ -262,6 +269,8 @@ static struct mca_driver el3_mca_driver = { .bus = &mca_bus_type, .probe = el3_mca_probe, .remove = __devexit_p(el3_device_remove), + .suspend = el3_suspend, + .resume = el3_resume, }, }; #endif /* CONFIG_MCA */ @@ -362,10 +371,6 @@ static void el3_common_remove (struct net_device *dev) struct el3_private *lp = netdev_priv(dev); (void) lp; /* Keep gcc quiet... */ -#ifdef CONFIG_PM_LEGACY - if (lp->pmdev) - pm_unregister(lp->pmdev); -#endif #if defined(__ISAPNP__) if (lp->type == EL3_PNP) pnp_device_detach(to_pnp_dev(lp->dev)); @@ -572,16 +577,6 @@ no_pnp: if (err) goto out1; -#ifdef CONFIG_PM_LEGACY - /* register power management */ - lp->pmdev = pm_register(PM_ISA_DEV, card_idx, el3_pm_callback); - if (lp->pmdev) { - struct pm_dev *p; - p = lp->pmdev; - p->data = (struct net_device *)dev; - } -#endif - el3_cards++; lp->next_dev = el3_root_dev; el3_root_dev = dev; @@ -1480,20 +1475,17 @@ el3_up(struct net_device *dev) } /* Power Management support functions */ -#ifdef CONFIG_PM_LEGACY +#ifdef EL3_SUSPEND static int -el3_suspend(struct pm_dev *pdev) +el3_suspend(struct device *pdev, pm_message_t state) { unsigned long flags; struct net_device *dev; struct el3_private *lp; int ioaddr; - if (!pdev && !pdev->data) - return -EINVAL; - - dev = (struct net_device *)pdev->data; + dev = pdev->driver_data; lp = netdev_priv(dev); ioaddr = dev->base_addr; @@ -1510,17 +1502,14 @@ el3_suspend(struct pm_dev *pdev) } static int -el3_resume(struct pm_dev *pdev) +el3_resume(struct device *pdev) { unsigned long flags; struct net_device *dev; struct el3_private *lp; int ioaddr; - if (!pdev && !pdev->data) - return -EINVAL; - - dev = (struct net_device *)pdev->data; + dev = pdev->driver_data; lp = netdev_priv(dev); ioaddr = dev->base_addr; @@ -1536,20 +1525,7 @@ el3_resume(struct pm_dev *pdev) return 0; } -static int -el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data) -{ - switch (rqst) { - case PM_SUSPEND: - return el3_suspend(pdev); - - case PM_RESUME: - return el3_resume(pdev); - } - return 0; -} - -#endif /* CONFIG_PM_LEGACY */ +#endif /* EL3_SUSPEND */ /* Parameters that may be passed into the module. */ static int debug = -1; -- cgit v1.2.3-59-g8ed1b From a4d4d5181d043ea835c15da6c85a5bbecbaded6e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 8 Mar 2006 11:49:31 +0000 Subject: [PATCH] Sparse: Cleanup sgiseeq sparse warnings. o Make sgiseeq_dump_rings static. o Delete unused sgiseeq_my_reset. o Move DEBUG define to beginning where it's easier to spot and will be seen by as well. o Use NULL for pointer initialization. Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik --- drivers/net/sgiseeq.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index a4614df38a90..f95a5b0223fb 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -3,6 +3,9 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) */ + +#undef DEBUG + #include #include #include @@ -59,8 +62,6 @@ static char *sgiseeqstr = "SGI Seeq8003"; sp->tx_old + (SEEQ_TX_BUFFERS - 1) - sp->tx_new : \ sp->tx_old - sp->tx_new - 1) -#define DEBUG - struct sgiseeq_rx_desc { volatile struct hpc_dma_desc rdma; volatile signed int buf_vaddr; @@ -209,7 +210,7 @@ static int seeq_init_ring(struct net_device *dev) static struct sgiseeq_private *gpriv; static struct net_device *gdev; -void sgiseeq_dump_rings(void) +static void sgiseeq_dump_rings(void) { static int once; struct sgiseeq_rx_desc *r = gpriv->rx_desc; @@ -311,9 +312,9 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp struct sgiseeq_regs *sregs) { struct sgiseeq_rx_desc *rd; - struct sk_buff *skb = 0; + struct sk_buff *skb = NULL; unsigned char pkt_status; - unsigned char *pkt_pointer = 0; + unsigned char *pkt_pointer = NULL; int len = 0; unsigned int orig_end = PREV_RX(sp->rx_new); @@ -515,12 +516,6 @@ static inline int sgiseeq_reset(struct net_device *dev) return 0; } -void sgiseeq_my_reset(void) -{ - printk("RESET!\n"); - sgiseeq_reset(gdev); -} - static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct sgiseeq_private *sp = netdev_priv(dev); -- cgit v1.2.3-59-g8ed1b From ded78e5e2cab0ec470cca7d34d7af742371bd476 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 10 Mar 2006 00:06:53 +0100 Subject: [PATCH] chelsio/espi.c:tricn_init(): remove dead code The Coverity checker spotted these two unused variables. Please check whether this patch is correct or whether they should be used. Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik --- drivers/net/chelsio/espi.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/espi.c b/drivers/net/chelsio/espi.c index e824acaf188a..542e5e065c6f 100644 --- a/drivers/net/chelsio/espi.c +++ b/drivers/net/chelsio/espi.c @@ -87,15 +87,9 @@ static int tricn_write(adapter_t *adapter, int bundle_addr, int module_addr, static int tricn_init(adapter_t *adapter) { int i = 0; - int sme = 1; int stat = 0; int timeout = 0; int is_ready = 0; - int dynamic_deskew = 0; - - if (dynamic_deskew) - sme = 0; - /* 1 */ timeout=1000; @@ -113,11 +107,9 @@ static int tricn_init(adapter_t *adapter) } /* 2 */ - if (sme) { - tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81); - tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81); - tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81); - } + tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81); + tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81); + tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81); for (i=1; i<= 8; i++) tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1); for (i=1; i<= 2; i++) tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1); for (i=1; i<= 3; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1); -- cgit v1.2.3-59-g8ed1b From 418dc1f5a805822fcf1118804ddc689a4156db4a Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 11 Mar 2006 20:50:08 -0500 Subject: libata: turn on ATAPI by default --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5a0b67a602df..42d43b55fb8f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -71,7 +71,7 @@ static unsigned int ata_dev_xfermask(struct ata_port *ap, static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; -int atapi_enabled = 0; +int atapi_enabled = 1; module_param(atapi_enabled, int, 0444); MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)"); -- cgit v1.2.3-59-g8ed1b From 4b10e559277de490bf5c257a1e3264a2bf51404b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Mar 2006 11:25:27 +0900 Subject: [PATCH] ahci: enable prefetching for PACKET commands Turn on AHCI_CMD_PREFETCH for PACKET commands. This hints the controller that it can prefetch the CDB and the PRD entries. This patch is originally from Jeff Garzik. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 00dfdefe2967..e97ab3e6de4d 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -66,6 +66,7 @@ enum { AHCI_IRQ_ON_SG = (1 << 31), AHCI_CMD_ATAPI = (1 << 5), AHCI_CMD_WRITE = (1 << 6), + AHCI_CMD_PREFETCH = (1 << 7), AHCI_CMD_RESET = (1 << 8), AHCI_CMD_CLR_BUSY = (1 << 10), @@ -631,7 +632,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) if (qc->tf.flags & ATA_TFLAG_WRITE) opts |= AHCI_CMD_WRITE; if (is_atapi) - opts |= AHCI_CMD_ATAPI; + opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH; ahci_fill_cmd_slot(pp, opts); } -- cgit v1.2.3-59-g8ed1b From 30dcbf29cc6d92d70fa262e79e84011fe6913bed Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 11 Mar 2006 17:51:39 -0800 Subject: [PATCH] drivers/net/e1000/: proper prototypes This patch moves prototypes of global variables and functions to a header file. Signed-off-by: Adrian Bunk Acked-by: John Ronciak Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/e1000/e1000.h | 22 ++++++++++++++++++++++ drivers/net/e1000/e1000_ethtool.c | 13 ------------- drivers/net/e1000/e1000_main.c | 14 -------------- 3 files changed, 22 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 214468c35b4b..281de41d030a 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -339,4 +339,26 @@ struct e1000_adapter { boolean_t tso_force; #endif }; + + +/* e1000_main.c */ +extern char e1000_driver_name[]; +extern char e1000_driver_version[]; +int e1000_up(struct e1000_adapter *adapter); +void e1000_down(struct e1000_adapter *adapter); +void e1000_reset(struct e1000_adapter *adapter); +int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); +void e1000_free_all_tx_resources(struct e1000_adapter *adapter); +int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); +void e1000_free_all_rx_resources(struct e1000_adapter *adapter); +void e1000_update_stats(struct e1000_adapter *adapter); +int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx); + +/* e1000_ethtool.c */ +void e1000_set_ethtool_ops(struct net_device *netdev); + +/* e1000_param.c */ +void e1000_check_options(struct e1000_adapter *adapter); + + #endif /* _E1000_H_ */ diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 44d39f1d8298..ecccca35c6f4 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -32,19 +32,6 @@ #include -extern char e1000_driver_name[]; -extern char e1000_driver_version[]; - -extern int e1000_up(struct e1000_adapter *adapter); -extern void e1000_down(struct e1000_adapter *adapter); -extern void e1000_reset(struct e1000_adapter *adapter); -extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx); -extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); -extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); -extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter); -extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter); -extern void e1000_update_stats(struct e1000_adapter *adapter); - struct e1000_stats { char stat_string[ETH_GSTRING_LEN]; int sizeof_stat; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 34d77ed6acaa..4400117eb6c7 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -140,14 +140,6 @@ static struct pci_device_id e1000_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); -int e1000_up(struct e1000_adapter *adapter); -void e1000_down(struct e1000_adapter *adapter); -void e1000_reset(struct e1000_adapter *adapter); -int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx); -int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); -int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); -void e1000_free_all_tx_resources(struct e1000_adapter *adapter); -void e1000_free_all_rx_resources(struct e1000_adapter *adapter); static int e1000_setup_tx_resources(struct e1000_adapter *adapter, struct e1000_tx_ring *txdr); static int e1000_setup_rx_resources(struct e1000_adapter *adapter, @@ -156,7 +148,6 @@ static void e1000_free_tx_resources(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring); static void e1000_free_rx_resources(struct e1000_adapter *adapter, struct e1000_rx_ring *rx_ring); -void e1000_update_stats(struct e1000_adapter *adapter); /* Local Function Prototypes */ @@ -212,7 +203,6 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -void e1000_set_ethtool_ops(struct net_device *netdev); static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static void e1000_tx_timeout(struct net_device *dev); @@ -237,10 +227,6 @@ static void e1000_netpoll (struct net_device *netdev); #endif -/* Exported from other modules */ - -extern void e1000_check_options(struct e1000_adapter *adapter); - static struct pci_driver e1000_driver = { .name = e1000_driver_name, .id_table = e1000_pci_tbl, -- cgit v1.2.3-59-g8ed1b From cf7f5b45fe0180a0f0e3491183c0ec95e4b96d44 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 3 Mar 2006 16:34:08 +0000 Subject: [SCSI] wd33c93: Fix missing prototypes by including . Signed-off-by: Ralf Baechle Signed-off-by: James Bottomley --- drivers/scsi/wd33c93.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index fb53eeaee617..d8a72609a31d 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -78,8 +78,8 @@ #include #include #include +#include #include -#include #include #include -- cgit v1.2.3-59-g8ed1b From 071a651e28bfc1a66a885dc285792e335427a097 Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Sun, 5 Mar 2006 23:18:14 +0100 Subject: [SCSI] i2o: fix memory leak in i2o_exec_lct_modified i2o_exec_lct_modified() does not release memory allocated for work_struct. Signed-off-by: Vasily Averin Although your patch is the same, i've rewritten it a little bit for naming consistency in the I2O driver. Acked-by: Markus Lidel Signed-off-by: James Bottomley --- drivers/message/i2o/exec-osm.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 9bb9859f6dfe..5ea133c59afb 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -57,6 +57,13 @@ struct i2o_exec_wait { struct list_head list; /* node in global wait list */ }; +/* Work struct needed to handle LCT NOTIFY replies */ +struct i2o_exec_lct_notify_work { + struct work_struct work; /* work struct */ + struct i2o_controller *c; /* controller on which the LCT NOTIFY + was received */ +}; + /* Exec OSM class handling definition */ static struct i2o_class_id i2o_exec_class_id[] = { {I2O_CLASS_EXECUTIVE}, @@ -355,9 +362,12 @@ static int i2o_exec_remove(struct device *dev) * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY * again, otherwise send LCT NOTIFY to get informed on next LCT change. */ -static void i2o_exec_lct_modified(struct i2o_controller *c) +static void i2o_exec_lct_modified(struct i2o_exec_lct_notify_work *work) { u32 change_ind = 0; + struct i2o_controller *c = work->c; + + kfree(work); if (i2o_device_parse_lct(c) != -EAGAIN) change_ind = c->lct->change_ind + 1; @@ -410,7 +420,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, return i2o_msg_post_wait_complete(c, m, msg, context); if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { - struct work_struct *work; + struct i2o_exec_lct_notify_work *work; pr_debug("%s: LCT notify received\n", c->name); @@ -418,8 +428,11 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, if (!work) return -ENOMEM; - INIT_WORK(work, (void (*)(void *))i2o_exec_lct_modified, c); - queue_work(i2o_exec_driver.event_queue, work); + work->c = c; + + INIT_WORK(&work->work, (void (*)(void *))i2o_exec_lct_modified, + work); + queue_work(i2o_exec_driver.event_queue, &work->work); return 1; } -- cgit v1.2.3-59-g8ed1b From 488d1469b318e6bf2b907743d626008340bc4f6e Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 7 Mar 2006 15:02:37 -0500 Subject: [SCSI] lpfc 8.1.4 : Fix Discovery processing for NPorts that change their NPortId on the fly Fix Discovery processing for NPorts that change their NPortId on the fly due to a cable swap. Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_crtn.h | 7 +- drivers/scsi/lpfc/lpfc_els.c | 207 +++++++++++++++++++++++-------------- drivers/scsi/lpfc/lpfc_hbadisc.c | 68 ++++++++++-- drivers/scsi/lpfc/lpfc_nportdisc.c | 16 +-- 4 files changed, 204 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index cafddf2f1af8..7b6534a1c315 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -70,7 +70,7 @@ int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp, int); int lpfc_els_abort_flogi(struct lpfc_hba *); int lpfc_initial_flogi(struct lpfc_hba *); -int lpfc_issue_els_plogi(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t); +int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t); int lpfc_issue_els_prli(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_adisc(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_logo(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t); @@ -168,8 +168,9 @@ int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, void lpfc_mbox_timeout(unsigned long); void lpfc_mbox_timeout_handler(struct lpfc_hba *); -struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, - uint32_t did); +struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t, uint32_t); +struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, uint32_t, + struct lpfc_name *); int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq, uint32_t timeout); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 090f4609d2af..efba875e53e4 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -97,10 +97,9 @@ lpfc_els_chk_latt(struct lpfc_hba * phba) } static struct lpfc_iocbq * -lpfc_prep_els_iocb(struct lpfc_hba * phba, - uint8_t expectRsp, - uint16_t cmdSize, - uint8_t retry, struct lpfc_nodelist * ndlp, uint32_t elscmd) +lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, + uint16_t cmdSize, uint8_t retry, struct lpfc_nodelist * ndlp, + uint32_t did, uint32_t elscmd) { struct lpfc_sli_ring *pring; struct lpfc_iocbq *elsiocb; @@ -181,7 +180,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL; if (expectRsp) { icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64)); - icmd->un.elsreq64.remoteID = ndlp->nlp_DID; /* DID */ + icmd->un.elsreq64.remoteID = did; /* DID */ icmd->ulpCommand = CMD_ELS_REQUEST64_CR; } else { icmd->un.elsreq64.bdl.bdeSize = sizeof (struct ulp_bde64); @@ -225,7 +224,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, "%d:0116 Xmit ELS command x%x to remote " "NPORT x%x Data: x%x x%x\n", phba->brd_no, elscmd, - ndlp->nlp_DID, icmd->ulpIoTag, phba->hba_state); + did, icmd->ulpIoTag, phba->hba_state); } else { /* Xmit ELS response to remote NPORT */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, @@ -516,10 +515,10 @@ lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, pring = &phba->sli.ring[LPFC_ELS_RING]; cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); - if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, - ndlp, ELS_CMD_FLOGI)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, + ndlp->nlp_DID, ELS_CMD_FLOGI); + if (!elsiocb) return 1; - } icmd = &elsiocb->iocb; pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); @@ -652,29 +651,80 @@ lpfc_more_plogi(struct lpfc_hba * phba) return; } +static struct lpfc_nodelist * +lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, + struct lpfc_nodelist *ndlp) +{ + struct lpfc_nodelist *new_ndlp; + struct lpfc_dmabuf *pcmd, *prsp; + uint32_t *lp; + struct serv_parm *sp; + uint8_t name[sizeof (struct lpfc_name)]; + uint32_t rc; + + pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; + prsp = (struct lpfc_dmabuf *) pcmd->list.next; + lp = (uint32_t *) prsp->virt; + sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); + + /* Now we to find out if the NPort we are logging into, matches the WWPN + * we have for that ndlp. If not, we have some work to do. + */ + new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName); + + memset(name, 0, sizeof (struct lpfc_name)); + rc = memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)); + if (!rc || (new_ndlp == ndlp)) { + return ndlp; + } + + if (!new_ndlp) { + new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); + if (!new_ndlp) + return ndlp; + + lpfc_nlp_init(phba, new_ndlp, ndlp->nlp_DID); + } + + lpfc_unreg_rpi(phba, new_ndlp); + new_ndlp->nlp_prev_state = ndlp->nlp_state; + new_ndlp->nlp_DID = ndlp->nlp_DID; + new_ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, new_ndlp, NLP_PLOGI_LIST); + + /* Move this back to NPR list */ + lpfc_unreg_rpi(phba, ndlp); + ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */ + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); + + return new_ndlp; +} + static void lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb) { IOCB_t *irsp; - struct lpfc_sli *psli; struct lpfc_nodelist *ndlp; int disc, rc, did, type; - psli = &phba->sli; /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; irsp = &rspiocb->iocb; - ndlp = (struct lpfc_nodelist *) cmdiocb->context1; + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, + irsp->un.elsreq64.remoteID); + if (!ndlp) + goto out; /* Since ndlp can be freed in the disc state machine, note if this node * is being used during discovery. */ disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~(NLP_PLOGI_SND | NLP_NPR_2B_DISC); + ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; spin_unlock_irq(phba->host->host_lock); rc = 0; @@ -723,18 +773,11 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, } } else { /* Good status, call state machine */ + ndlp = lpfc_plogi_confirm_nport(phba, cmdiocb, ndlp); rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_PLOGI); } - if (type & NLP_FABRIC) { - /* If we cannot login to Nameserver, kick off discovery now */ - if ((did == NameServer_DID) && (rc == NLP_STE_FREED_NODE)) { - lpfc_disc_start(phba); - } - goto out; - } - if (disc && phba->num_disc_nodes) { /* Check to see if there are more PLOGIs to be sent */ lpfc_more_plogi(phba); @@ -767,8 +810,7 @@ out: } int -lpfc_issue_els_plogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, - uint8_t retry) +lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry) { struct serv_parm *sp; IOCB_t *icmd; @@ -782,7 +824,7 @@ lpfc_issue_els_plogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); - elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, + elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, 0, did, ELS_CMD_PLOGI); if (!elsiocb) return 1; @@ -805,9 +847,7 @@ lpfc_issue_els_plogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, phba->fc_stat.elsXmitPLOGI++; elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi; spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag |= NLP_PLOGI_SND; if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { - ndlp->nlp_flag &= ~NLP_PLOGI_SND; spin_unlock_irq(phba->host->host_lock); lpfc_els_free_iocb(phba, elsiocb); return 1; @@ -890,10 +930,10 @@ lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ cmdsize = (sizeof (uint32_t) + sizeof (PRLI)); - if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, - ndlp, ELS_CMD_PRLI)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, + ndlp->nlp_DID, ELS_CMD_PRLI); + if (!elsiocb) return 1; - } icmd = &elsiocb->iocb; pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); @@ -1117,10 +1157,10 @@ lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ cmdsize = (sizeof (uint32_t) + sizeof (ADISC)); - if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, - ndlp, ELS_CMD_ADISC)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, + ndlp->nlp_DID, ELS_CMD_ADISC); + if (!elsiocb) return 1; - } icmd = &elsiocb->iocb; pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); @@ -1224,10 +1264,10 @@ lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, pring = &psli->ring[LPFC_ELS_RING]; cmdsize = 2 * (sizeof (uint32_t) + sizeof (struct lpfc_name)); - if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, - ndlp, ELS_CMD_LOGO)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, + ndlp->nlp_DID, ELS_CMD_LOGO); + if (!elsiocb) return 1; - } icmd = &elsiocb->iocb; pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); @@ -1296,8 +1336,9 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) lpfc_nlp_init(phba, ndlp, nportid); - if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, - ndlp, ELS_CMD_SCR)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, + ndlp->nlp_DID, ELS_CMD_SCR); + if (!elsiocb) { mempool_free( ndlp, phba->nlp_mem_pool); return 1; } @@ -1348,8 +1389,9 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) return 1; lpfc_nlp_init(phba, ndlp, nportid); - if ((elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, - ndlp, ELS_CMD_RNID)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, + ndlp->nlp_DID, ELS_CMD_RNID); + if (!elsiocb) { mempool_free( ndlp, phba->nlp_mem_pool); return 1; } @@ -1448,7 +1490,7 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) lpfc_issue_els_flogi(phba, ndlp, retry); break; case ELS_CMD_PLOGI: - if (!lpfc_issue_els_plogi(phba, ndlp, retry)) { + if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) { ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); @@ -1491,6 +1533,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, int retry, maxretry; int delay; uint32_t cmd; + uint32_t did; retry = 0; delay = 0; @@ -1499,6 +1542,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, ndlp = (struct lpfc_nodelist *) cmdiocb->context1; pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; cmd = 0; + /* Note: context2 may be 0 for internal driver abort * of delays ELS command. */ @@ -1508,6 +1552,16 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, cmd = *elscmd++; } + if(ndlp) + did = ndlp->nlp_DID; + else { + /* We should only hit this case for retrying PLOGI */ + did = irsp->un.elsreq64.remoteID; + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); + if (!ndlp && (cmd != ELS_CMD_PLOGI)) + return 1; + } + switch (irsp->ulpStatus) { case IOSTAT_FCP_RSP_ERROR: case IOSTAT_REMOTE_STOP: @@ -1596,9 +1650,8 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, break; } - if (ndlp->nlp_DID == FDMI_DID) { + if (did == FDMI_DID) retry = 1; - } if ((++cmdiocb->retry) >= maxretry) { phba->fc_stat.elsRetryExceeded++; @@ -1612,7 +1665,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, "%d:0107 Retry ELS command x%x to remote " "NPORT x%x Data: x%x x%x\n", phba->brd_no, - cmd, ndlp->nlp_DID, cmdiocb->retry, delay); + cmd, did, cmdiocb->retry, delay); if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) { /* If discovery / RSCN timer is running, reset it */ @@ -1623,7 +1676,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, } phba->fc_stat.elsXmitRetry++; - if (delay) { + if (ndlp && delay) { phba->fc_stat.elsDelayRetry++; ndlp->nlp_retry = cmdiocb->retry; @@ -1642,10 +1695,12 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry); return 1; case ELS_CMD_PLOGI: - ndlp->nlp_prev_state = ndlp->nlp_state; - ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; - lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); - lpfc_issue_els_plogi(phba, ndlp, cmdiocb->retry); + if (ndlp) { + ndlp->nlp_prev_state = ndlp->nlp_state; + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); + } + lpfc_issue_els_plogi(phba, did, cmdiocb->retry); return 1; case ELS_CMD_ADISC: ndlp->nlp_prev_state = ndlp->nlp_state; @@ -1671,9 +1726,9 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, /* No retry ELS command to remote NPORT */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0108 No retry ELS command x%x to remote NPORT x%x " - "Data: x%x x%x\n", + "Data: x%x\n", phba->brd_no, - cmd, ndlp->nlp_DID, cmdiocb->retry, ndlp->nlp_flag); + cmd, did, cmdiocb->retry); return 0; } @@ -1827,9 +1882,9 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, switch (flag) { case ELS_CMD_ACC: cmdsize = sizeof (uint32_t); - if ((elsiocb = - lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, - ndlp, ELS_CMD_ACC)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, + ndlp, ndlp->nlp_DID, ELS_CMD_ACC); + if (!elsiocb) { ndlp->nlp_flag &= ~NLP_LOGO_ACC; return 1; } @@ -1841,11 +1896,11 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, break; case ELS_CMD_PLOGI: cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t)); - if ((elsiocb = - lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, - ndlp, ELS_CMD_ACC)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, + ndlp, ndlp->nlp_DID, ELS_CMD_ACC); + if (!elsiocb) return 1; - } + icmd = &elsiocb->iocb; icmd->ulpContext = oldcmd->ulpContext; /* Xri */ pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); @@ -1910,10 +1965,10 @@ lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError, pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ cmdsize = 2 * sizeof (uint32_t); - if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, - ndlp, ELS_CMD_LS_RJT)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, + ndlp, ndlp->nlp_DID, ELS_CMD_LS_RJT); + if (!elsiocb) return 1; - } icmd = &elsiocb->iocb; oldcmd = &oldiocb->iocb; @@ -1963,10 +2018,10 @@ lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba, pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ cmdsize = sizeof (uint32_t) + sizeof (ADISC); - if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, - ndlp, ELS_CMD_ACC)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, + ndlp, ndlp->nlp_DID, ELS_CMD_ACC); + if (!elsiocb) return 1; - } /* Xmit ADISC ACC response tag */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, @@ -2023,7 +2078,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba * phba, cmdsize = sizeof (uint32_t) + sizeof (PRLI); elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, - (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK))); + ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK))); if (!elsiocb) return 1; @@ -2103,10 +2158,10 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba, if (format) cmdsize += sizeof (RNID_TOP_DISC); - if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, - ndlp, ELS_CMD_ACC)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, + ndlp, ndlp->nlp_DID, ELS_CMD_ACC); + if (!elsiocb) return 1; - } /* Xmit RNID ACC response tag */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, @@ -2217,7 +2272,7 @@ lpfc_els_disc_plogi(struct lpfc_hba * phba) ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); - lpfc_issue_els_plogi(phba, ndlp, 0); + lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); sentplogi++; phba->num_disc_nodes++; if (phba->num_disc_nodes >= @@ -2516,7 +2571,7 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) ndlp->nlp_type |= NLP_FABRIC; ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; - lpfc_issue_els_plogi(phba, ndlp, 0); + lpfc_issue_els_plogi(phba, NameServer_DID, 0); /* Wait for NameServer login cmpl before we can continue */ return 1; @@ -2694,8 +2749,8 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); mempool_free( pmb, phba->mbox_mem_pool); - elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, - ndlp, ELS_CMD_ACC); + elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp, + ndlp->nlp_DID, ELS_CMD_ACC); if (!elsiocb) return; @@ -2806,11 +2861,11 @@ lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize, psli = &phba->sli; pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ - if ((elsiocb = - lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, - ndlp, ELS_CMD_ACC)) == 0) { + elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, + ndlp, ndlp->nlp_DID, ELS_CMD_ACC); + if (!elsiocb) return 1; - } + icmd = &elsiocb->iocb; oldcmd = &oldiocb->iocb; icmd->ulpContext = oldcmd->ulpContext; /* Xri */ @@ -2943,7 +2998,7 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); - lpfc_issue_els_plogi(phba, ndlp, 0); + lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); } /* Send a FARP response to that node */ diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index e7664a6bd251..2b227b363ae3 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -59,6 +59,7 @@ static void lpfc_disc_timeout_handler(struct lpfc_hba *); static void lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) { + uint8_t *name = (uint8_t *)&ndlp->nlp_portname; int warn_on = 0; spin_lock_irq(phba->host->host_lock); @@ -79,15 +80,23 @@ lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) if (warn_on) { lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d:0203 Nodev timeout on NPort x%x " - "Data: x%x x%x x%x\n", - phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, + "%d:0203 Nodev timeout on " + "WWPN %x:%x:%x:%x:%x:%x:%x:%x " + "NPort x%x Data: x%x x%x x%x\n", + phba->brd_no, + *name, *(name+1), *(name+2), *(name+3), + *(name+4), *(name+5), *(name+6), *(name+7), + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); } else { lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d:0204 Nodev timeout on NPort x%x " - "Data: x%x x%x x%x\n", - phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, + "%d:0204 Nodev timeout on " + "WWPN %x:%x:%x:%x:%x:%x:%x:%x " + "NPort x%x Data: x%x x%x x%x\n", + phba->brd_no, + *name, *(name+1), *(name+2), *(name+3), + *(name+4), *(name+5), *(name+6), *(name+7), + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); } @@ -945,7 +954,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); - lpfc_issue_els_plogi(phba, ndlp, 0); + lpfc_issue_els_plogi(phba, NameServer_DID, 0); if (phba->cfg_fdmi_on) { ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); @@ -953,7 +962,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_nlp_init(phba, ndlp_fdmi, FDMI_DID); ndlp_fdmi->nlp_type |= NLP_FABRIC; ndlp_fdmi->nlp_state = NLP_STE_PLOGI_ISSUE; - lpfc_issue_els_plogi(phba, ndlp_fdmi, 0); + lpfc_issue_els_plogi(phba, FDMI_DID, 0); } } } @@ -2516,6 +2525,49 @@ lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) return NULL; } +/* + * This routine looks up the ndlp lists + * for the given WWPN. If WWPN found + * it return the node list pointer + * else return NULL. + */ +struct lpfc_nodelist * +lpfc_findnode_wwpn(struct lpfc_hba * phba, uint32_t order, + struct lpfc_name * wwpn) +{ + struct lpfc_nodelist *ndlp; + struct list_head * lists[]={&phba->fc_nlpunmap_list, + &phba->fc_nlpmap_list, + &phba->fc_npr_list, + &phba->fc_plogi_list, + &phba->fc_adisc_list, + &phba->fc_reglogin_list, + &phba->fc_prli_list}; + uint32_t search[]={NLP_SEARCH_UNMAPPED, + NLP_SEARCH_MAPPED, + NLP_SEARCH_NPR, + NLP_SEARCH_PLOGI, + NLP_SEARCH_ADISC, + NLP_SEARCH_REGLOGIN, + NLP_SEARCH_PRLI}; + int i; + + spin_lock_irq(phba->host->host_lock); + for (i = 0; i < ARRAY_SIZE(lists); i++ ) { + if (!(order & search[i])) + continue; + list_for_each_entry(ndlp, lists[i], nlp_listp) { + if (memcmp(&ndlp->nlp_portname, wwpn, + sizeof(struct lpfc_name)) == 0) { + spin_unlock_irq(phba->host->host_lock); + return ndlp; + } + } + } + spin_unlock_irq(phba->host->host_lock); + return NULL; +} + void lpfc_nlp_init(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index dba11d94d27d..8affc1543c6e 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -880,7 +880,7 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba, ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); - lpfc_issue_els_plogi(phba, ndlp, 0); + lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); return ndlp->nlp_state; } @@ -1503,11 +1503,12 @@ lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba, /* send PLOGI immediately, move to PLOGI issue state */ if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { - ndlp->nlp_prev_state = NLP_STE_NPR_NODE; - ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; - lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); - lpfc_issue_els_plogi(phba, ndlp, 0); + ndlp->nlp_prev_state = NLP_STE_NPR_NODE; + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); + lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); } + return ndlp->nlp_state; } @@ -1539,8 +1540,9 @@ lpfc_rcv_prli_npr_node(struct lpfc_hba * phba, ndlp->nlp_prev_state = NLP_STE_NPR_NODE; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); - lpfc_issue_els_plogi(phba, ndlp, 0); + lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); } + } return ndlp->nlp_state; } @@ -1579,7 +1581,7 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba, ndlp->nlp_prev_state = NLP_STE_NPR_NODE; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); - lpfc_issue_els_plogi(phba, ndlp, 0); + lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); } } return ndlp->nlp_state; -- cgit v1.2.3-59-g8ed1b From fdcebe282fd8654381852260efec267eff8002fb Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 7 Mar 2006 15:04:01 -0500 Subject: [SCSI] lpfc 8.1.4 : Fixed RSCN handling when a PLOGI is in retry Fixed RSCN handling when a PLOGI is in retry. Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_els.c | 51 +++++++++++++++++++++++++++++++------- drivers/scsi/lpfc/lpfc_hbadisc.c | 24 +++--------------- drivers/scsi/lpfc/lpfc_nportdisc.c | 21 ++++------------ 4 files changed, 52 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 7b6534a1c315..f716c1d85f41 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -84,6 +84,7 @@ int lpfc_els_rsp_adisc_acc(struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_nodelist *); int lpfc_els_rsp_prli_acc(struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_nodelist *); +void lpfc_cancel_retry_delay_tmo(struct lpfc_hba *, struct lpfc_nodelist *); void lpfc_els_retry_delay(unsigned long); void lpfc_els_retry_delay_handler(struct lpfc_nodelist *); void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index efba875e53e4..6d12cd0c49ff 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1434,6 +1434,46 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) return 0; } +void +lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp) +{ + nlp->nlp_flag &= ~NLP_DELAY_TMO; + del_timer_sync(&nlp->nlp_delayfunc); + nlp->nlp_last_elscmd = 0; + + if (!list_empty(&nlp->els_retry_evt.evt_listp)) + list_del_init(&nlp->els_retry_evt.evt_listp); + + if (nlp->nlp_flag & NLP_NPR_2B_DISC) { + nlp->nlp_flag &= ~NLP_NPR_2B_DISC; + if (phba->num_disc_nodes) { + /* Check to see if there are more + * PLOGIs to be sent + */ + lpfc_more_plogi(phba); + } + + if (phba->num_disc_nodes == 0) { + phba->fc_flag &= ~FC_NDISC_ACTIVE; + lpfc_can_disctmo(phba); + if (phba->fc_flag & FC_RSCN_MODE) { + /* Check to see if more RSCNs + * came in while we were + * processing this one. + */ + if((phba->fc_rscn_id_cnt==0) && + (!(phba->fc_flag & FC_RSCN_DISCOVERY))) { + phba->fc_flag &= ~FC_RSCN_MODE; + } + else { + lpfc_els_handle_rscn(phba); + } + } + } + } + return; +} + void lpfc_els_retry_delay(unsigned long ptr) { @@ -2415,15 +2455,8 @@ lpfc_rscn_recovery_check(struct lpfc_hba * phba) /* Make sure NLP_DELAY_TMO is NOT running * after a device recovery event. */ - if (ndlp->nlp_flag & NLP_DELAY_TMO) { - ndlp->nlp_flag &= ~NLP_DELAY_TMO; - ndlp->nlp_last_elscmd = 0; - del_timer_sync(&ndlp->nlp_delayfunc); - if (!list_empty(&ndlp-> - els_retry_evt.evt_listp)) - list_del_init(&ndlp-> - els_retry_evt.evt_listp); - } + if (ndlp->nlp_flag & NLP_DELAY_TMO) + lpfc_cancel_retry_delay_tmo(phba, ndlp); } } return 0; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 2b227b363ae3..e15120d21aaa 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1152,13 +1152,9 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) /* Stop delay tmo if taking node off NPR list */ if ((nlp->nlp_flag & NLP_DELAY_TMO) && (list != NLP_NPR_LIST)) { - nlp->nlp_flag &= ~NLP_DELAY_TMO; - nlp->nlp_last_elscmd = 0; spin_unlock_irq(phba->host->host_lock); - del_timer_sync(&nlp->nlp_delayfunc); + lpfc_cancel_retry_delay_tmo(phba, nlp); spin_lock_irq(phba->host->host_lock); - if (!list_empty(&nlp->els_retry_evt.evt_listp)) - list_del_init(&nlp->els_retry_evt.evt_listp); } break; } @@ -1598,13 +1594,7 @@ lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) if (ndlp->nlp_flag & NLP_DELAY_TMO) { - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~NLP_DELAY_TMO; - spin_unlock_irq(phba->host->host_lock); - ndlp->nlp_last_elscmd = 0; - del_timer_sync(&ndlp->nlp_delayfunc); - if (!list_empty(&ndlp->els_retry_evt.evt_listp)) - list_del_init(&ndlp->els_retry_evt.evt_listp); + lpfc_cancel_retry_delay_tmo(phba, ndlp); } if (ndlp->nlp_disc_refcnt) { @@ -1896,14 +1886,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) /* Since this node is marked for discovery, * delay timeout is not needed. */ - if (ndlp->nlp_flag & NLP_DELAY_TMO) { - ndlp->nlp_flag &= ~NLP_DELAY_TMO; - del_timer_sync(&ndlp->nlp_delayfunc); - if (!list_empty(&ndlp->els_retry_evt. - evt_listp)) - list_del_init(&ndlp->els_retry_evt. - evt_listp); - } + if (ndlp->nlp_flag & NLP_DELAY_TMO) + lpfc_cancel_retry_delay_tmo(phba, ndlp); } else { ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; ndlp = NULL; diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 8affc1543c6e..3d77bd999b70 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -259,13 +259,8 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, } while(found); /* If we are delaying issuing an ELS command, cancel it */ - if (ndlp->nlp_flag & NLP_DELAY_TMO) { - ndlp->nlp_flag &= ~NLP_DELAY_TMO; - ndlp->nlp_last_elscmd = 0; - del_timer_sync(&ndlp->nlp_delayfunc); - if (!list_empty(&ndlp->els_retry_evt.evt_listp)) - list_del_init(&ndlp->els_retry_evt.evt_listp); - } + if (ndlp->nlp_flag & NLP_DELAY_TMO) + lpfc_cancel_retry_delay_tmo(phba, ndlp); return 0; } @@ -1496,7 +1491,7 @@ lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba, if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) { spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~(NLP_NPR_ADISC | NLP_NPR_2B_DISC); + ndlp->nlp_flag &= ~NLP_NPR_ADISC; spin_unlock_irq(phba->host->host_lock); return ndlp->nlp_state; } @@ -1693,16 +1688,10 @@ lpfc_device_recov_npr_node(struct lpfc_hba * phba, { spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; + spin_unlock_irq(phba->host->host_lock); if (ndlp->nlp_flag & NLP_DELAY_TMO) { - ndlp->nlp_flag &= ~NLP_DELAY_TMO; - if (!list_empty(&ndlp->els_retry_evt.evt_listp)) - list_del_init(&ndlp->els_retry_evt.evt_listp); - spin_unlock_irq(phba->host->host_lock); - ndlp->nlp_last_elscmd = 0; - del_timer_sync(&ndlp->nlp_delayfunc); - return ndlp->nlp_state; + lpfc_cancel_retry_delay_tmo(phba, ndlp); } - spin_unlock_irq(phba->host->host_lock); return ndlp->nlp_state; } -- cgit v1.2.3-59-g8ed1b From 1a169689c2152ea599c94d622204f7bf5b7dc09f Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 7 Mar 2006 15:04:06 -0500 Subject: [SCSI] lpfc 8.1.4 : Fixed a timer panic due to timer firing after freeing ndlp Fixed a timer panic due to timer firing after freeing ndlp Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 6 ++++++ drivers/scsi/lpfc/lpfc_hbadisc.c | 9 +++++++++ 2 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 6d12cd0c49ff..4813beaaca8f 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1523,6 +1523,12 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_flag &= ~NLP_DELAY_TMO; spin_unlock_irq(phba->host->host_lock); + /* + * If a discovery event readded nlp_delayfunc after timer + * firing and before processing the timer, cancel the + * nlp_delayfunc. + */ + del_timer_sync(&ndlp->nlp_delayfunc); retry = ndlp->nlp_retry; switch (cmd) { diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index e15120d21aaa..82704148d5d4 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -68,6 +68,15 @@ lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) return; } + /* + * If a discovery event readded nodev_timer after timer + * firing and before processing the timer, cancel the + * nlp_tmofunc. + */ + spin_unlock_irq(phba->host->host_lock); + del_timer_sync(&ndlp->nlp_tmofunc); + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag &= ~NLP_NODEV_TMO; if (ndlp->nlp_sid != NLP_NO_SID) { -- cgit v1.2.3-59-g8ed1b From 9290831f00879d4a66d3bffb609949d5ea5576fb Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 7 Mar 2006 15:04:13 -0500 Subject: [SCSI] lpfc 8.1.4 : Introduce lpfc_reset_barrier() function for resets on dual channel adapters Introduce lpfc_reset_barrier() function for resets on dual channel adapters Workaround for a hardware errata on dual channel asics. There is a potential for the chip to lock up on a reset if a shared dma engine is in use. The (ugly) work around requires a reset process which uses a mailbox command to synchronize the independent channels prior to the reset to avoid the issue. Unfortunately, the timing windows required to ensure this workaround succeeds are very specific, meaning we can't release the cpu during the barrier. Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_hbadisc.c | 4 +- drivers/scsi/lpfc/lpfc_init.c | 4 +- drivers/scsi/lpfc/lpfc_sli.c | 99 +++++++++++++++++++++++++++++++++++++--- 5 files changed, 100 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 2f67a8a92599..087c44539a16 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -197,6 +197,7 @@ struct lpfc_hba { #define LPFC_HBA_READY 32 #define LPFC_HBA_ERROR -1 + int32_t stopped; /* HBA has not been restarted since last ERATT */ uint8_t fc_linkspeed; /* Link speed after last READ_LA */ uint32_t fc_eventTag; /* event tag for link attention */ diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index f716c1d85f41..fad607b2e6f4 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -139,6 +139,7 @@ struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *); void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); +void lpfc_reset_barrier(struct lpfc_hba * phba); int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); int lpfc_sli_brdkill(struct lpfc_hba *); int lpfc_sli_brdreset(struct lpfc_hba *); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 82704148d5d4..f54089fe4732 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -155,6 +155,7 @@ lpfc_work_list_done(struct lpfc_hba * phba) case LPFC_EVT_WARM_START: if (phba->hba_state >= LPFC_LINK_DOWN) lpfc_offline(phba); + lpfc_reset_barrier(phba); lpfc_sli_brdreset(phba); lpfc_hba_down_post(phba); *(int *)(evtp->evt_arg1) = @@ -164,7 +165,8 @@ lpfc_work_list_done(struct lpfc_hba * phba) case LPFC_EVT_KILL: if (phba->hba_state >= LPFC_LINK_DOWN) lpfc_offline(phba); - *(int *)(evtp->evt_arg1) = lpfc_sli_brdkill(phba); + *(int *)(evtp->evt_arg1) + = (phba->stopped) ? 0 : lpfc_sli_brdkill(phba); complete((struct completion *)(evtp->evt_arg2)); break; } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index a2e15436730e..66d5d003555d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -464,8 +464,6 @@ lpfc_hba_down_prep(struct lpfc_hba * phba) lpfc_els_flush_cmd(phba); lpfc_disc_flush_list(phba); - /* Disable SLI2 since we disabled interrupts */ - phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE; return (0); } @@ -526,6 +524,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba) phba->work_status[0], phba->work_status[1]); spin_lock_irq(phba->host->host_lock); phba->fc_flag |= FC_ESTABLISH_LINK; + psli->sli_flag &= ~LPFC_SLI2_ACTIVE; spin_unlock_irq(phba->host->host_lock); /* @@ -559,6 +558,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba) phba->brd_no, phba->work_hs, phba->work_status[0], phba->work_status[1]); + psli->sli_flag &= ~LPFC_SLI2_ACTIVE; lpfc_offline(phba); phba->hba_state = LPFC_HBA_ERROR; lpfc_hba_down_post(phba); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 764aadbec71b..bb69a7a1ec59 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1566,6 +1566,79 @@ lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask) return retval; } +#define BARRIER_TEST_PATTERN (0xdeadbeef) + +void lpfc_reset_barrier(struct lpfc_hba * phba) +{ + uint32_t * resp_buf; + uint32_t * mbox_buf; + volatile uint32_t mbox; + uint32_t hc_copy; + int i; + uint8_t hdrtype; + + pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype); + if (hdrtype != 0x80 || + (FC_JEDEC_ID(phba->vpd.rev.biuRev) != HELIOS_JEDEC_ID && + FC_JEDEC_ID(phba->vpd.rev.biuRev) != THOR_JEDEC_ID)) + return; + + /* + * Tell the other part of the chip to suspend temporarily all + * its DMA activity. + */ + resp_buf = (uint32_t *)phba->MBslimaddr; + + /* Disable the error attention */ + hc_copy = readl(phba->HCregaddr); + writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr); + readl(phba->HCregaddr); /* flush */ + + if (readl(phba->HAregaddr) & HA_ERATT) { + /* Clear Chip error bit */ + writel(HA_ERATT, phba->HAregaddr); + phba->stopped = 1; + } + + mbox = 0; + ((MAILBOX_t *)&mbox)->mbxCommand = MBX_KILL_BOARD; + ((MAILBOX_t *)&mbox)->mbxOwner = OWN_CHIP; + + writel(BARRIER_TEST_PATTERN, (resp_buf + 1)); + mbox_buf = (uint32_t *)phba->MBslimaddr; + writel(mbox, mbox_buf); + + for (i = 0; + readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN) && i < 50; i++) + mdelay(1); + + if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) { + if (phba->sli.sli_flag & LPFC_SLI2_ACTIVE || + phba->stopped) + goto restore_hc; + else + goto clear_errat; + } + + ((MAILBOX_t *)&mbox)->mbxOwner = OWN_HOST; + for (i = 0; readl(resp_buf) != mbox && i < 500; i++) + mdelay(1); + +clear_errat: + + while (!(readl(phba->HAregaddr) & HA_ERATT) && ++i < 500) + mdelay(1); + + if (readl(phba->HAregaddr) & HA_ERATT) { + writel(HA_ERATT, phba->HAregaddr); + phba->stopped = 1; + } + +restore_hc: + writel(hc_copy, phba->HCregaddr); + readl(phba->HCregaddr); /* flush */ +} + int lpfc_sli_brdkill(struct lpfc_hba * phba) { @@ -1588,9 +1661,8 @@ lpfc_sli_brdkill(struct lpfc_hba * phba) psli->sli_flag); if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, - GFP_ATOMIC)) == 0) { + GFP_KERNEL)) == 0) return 1; - } /* Disable the error attention */ spin_lock_irq(phba->host->host_lock); @@ -1610,6 +1682,8 @@ lpfc_sli_brdkill(struct lpfc_hba * phba) return 1; } + psli->sli_flag &= ~LPFC_SLI2_ACTIVE; + mempool_free(pmb, phba->mbox_mem_pool); /* There is no completion for a KILL_BOARD mbox cmd. Check for an error @@ -1625,7 +1699,10 @@ lpfc_sli_brdkill(struct lpfc_hba * phba) } del_timer_sync(&psli->mbox_tmo); - + if (ha_copy & HA_ERATT) { + writel(HA_ERATT, phba->HAregaddr); + phba->stopped = 1; + } spin_lock_irq(phba->host->host_lock); psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; spin_unlock_irq(phba->host->host_lock); @@ -1665,6 +1742,7 @@ lpfc_sli_brdreset(struct lpfc_hba * phba) (cfg_value & ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR))); + psli->sli_flag &= ~LPFC_SLI2_ACTIVE; /* Now toggle INITFF bit in the Host Control Register */ writel(HC_INITFF, phba->HCregaddr); mdelay(1); @@ -1713,6 +1791,8 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba) mb->mbxCommand = MBX_RESTART; mb->mbxHc = 1; + lpfc_reset_barrier(phba); + to_slim = phba->MBslimaddr; writel(*(uint32_t *) mb, to_slim); readl(to_slim); /* flush */ @@ -1730,7 +1810,7 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba) readl(to_slim); /* flush */ lpfc_sli_brdreset(phba); - + phba->stopped = 0; phba->hba_state = LPFC_INIT_START; spin_unlock_irq(phba->host->host_lock); @@ -2038,6 +2118,13 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) return (MBX_NOT_FINISHED); } + if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT && + !(readl(phba->HCregaddr) & HC_MBINT_ENA)) { + spin_unlock_irqrestore(phba->host->host_lock, drvr_flag); + LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag) + return (MBX_NOT_FINISHED); + } + if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) { /* Polling for a mbox command when another one is already active * is not allowed in SLI. Also, the driver must have established @@ -2154,8 +2241,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) /* First copy command data to host SLIM area */ lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, MAILBOX_CMD_SIZE); } else { - if (mb->mbxCommand == MBX_CONFIG_PORT || - mb->mbxCommand == MBX_KILL_BOARD) { + if (mb->mbxCommand == MBX_CONFIG_PORT) { /* copy command data into host mbox for cmpl */ lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, MAILBOX_CMD_SIZE); @@ -3121,6 +3207,7 @@ lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs) /* Clear Chip error bit */ writel(HA_ERATT, phba->HAregaddr); readl(phba->HAregaddr); /* flush */ + phba->stopped = 1; } spin_lock(phba->host->host_lock); -- cgit v1.2.3-59-g8ed1b From fc6c12bcc19bdff6b4bcb02f5bd6d9fa59a7e1af Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 7 Mar 2006 15:04:19 -0500 Subject: [SCSI] lpfc 8.1.4 : Two misc fixes Two misc fixes: - Fix deadlock caused by return with host_lock held in lpfc_findnode_did - Initialize all fields of the allocated mail box structure to zero. Was causing some sysfs mailbox commands to fail immediately after load. Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_attr.c | 2 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 2558156f064d..b62a72dfab29 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -856,7 +856,7 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count) mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) return -ENOMEM; - + memset(mbox, 0, sizeof (LPFC_MBOXQ_t)); } spin_lock_irq(host->host_lock); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index f54089fe4732..6721e679df62 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1760,6 +1760,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); + spin_unlock_irq(phba->host->host_lock); return ndlp; } } @@ -1805,6 +1806,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) phba->brd_no, ndlp, ndlp->nlp_DID, ndlp->nlp_flag, data1); + spin_unlock_irq(phba->host->host_lock); return ndlp; } } -- cgit v1.2.3-59-g8ed1b From a382dd7c13377c8ff98f6ec59f64355653fb507e Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 7 Mar 2006 15:04:25 -0500 Subject: [SCSI] lpfc 8.1.4 : Change version number to 8.1.4 Change version number to 8.1.4 Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 9d9d91cbefb1..4cf1366108b7 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.1.3" +#define LPFC_DRIVER_VERSION "8.1.4" #define LPFC_DRIVER_NAME "lpfc" -- cgit v1.2.3-59-g8ed1b From 7b22da38b64a32df20fdb7272deb7546045fccec Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 8 Mar 2006 12:56:14 +0100 Subject: [SCSI] aic79xx: remove qfrozen This patch removes the need for platform_data->qfrozen. We're now using complete() instead of semaphores thus simplifying ahd_freeze_simq() quite a lot. This also fixes some deadlocks in the recovery code (again). Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_osm.c | 104 ++++++++++--------------------------- drivers/scsi/aic7xxx/aic79xx_osm.h | 5 +- 2 files changed, 27 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 7254ea535a16..fc393bd95f4a 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -373,7 +373,6 @@ static void ahd_linux_handle_scsi_status(struct ahd_softc *, struct scb *); static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd); -static void ahd_linux_sem_timeout(u_long arg); static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, @@ -453,18 +452,13 @@ ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *)) struct ahd_softc *ahd; struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device); int rtn = SCSI_MLQUEUE_HOST_BUSY; - unsigned long flags; ahd = *(struct ahd_softc **)cmd->device->host->hostdata; - ahd_lock(ahd, &flags); - if (ahd->platform_data->qfrozen == 0) { - cmd->scsi_done = scsi_done; - cmd->result = CAM_REQ_INPROG << 16; - rtn = ahd_linux_run_command(ahd, dev, cmd); + cmd->scsi_done = scsi_done; + cmd->result = CAM_REQ_INPROG << 16; + rtn = ahd_linux_run_command(ahd, dev, cmd); - } - ahd_unlock(ahd, &flags); return rtn; } @@ -682,7 +676,6 @@ static int ahd_linux_bus_reset(struct scsi_cmnd *cmd) { struct ahd_softc *ahd; - u_long s; int found; ahd = *(struct ahd_softc **)cmd->device->host->hostdata; @@ -691,10 +684,8 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd) printf("%s: Bus reset called for cmd %p\n", ahd_name(ahd), cmd); #endif - ahd_lock(ahd, &s); found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A', /*initiate reset*/TRUE); - ahd_unlock(ahd, &s); if (bootverbose) printf("%s: SCSI bus reset delivered. " @@ -1194,7 +1185,6 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); ahd->platform_data->irq = AHD_LINUX_NOIRQ; ahd_lockinit(ahd); - init_MUTEX_LOCKED(&ahd->platform_data->eh_sem); ahd->seltime = (aic79xx_seltime & 0x3) << 4; return (0); } @@ -1443,6 +1433,9 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, struct ahd_tmode_tstate *tstate; u_int col_idx; uint16_t mask; + unsigned long flags; + + ahd_lock(ahd, &flags); /* * Get an scb to use. @@ -1458,6 +1451,7 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, } if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) { ahd->flags |= AHD_RESOURCE_SHORTAGE; + ahd_unlock(ahd, &flags); return SCSI_MLQUEUE_HOST_BUSY; } @@ -1583,6 +1577,8 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, scb->flags |= SCB_ACTIVE; ahd_queue_scb(ahd, scb); + ahd_unlock(ahd, &flags); + return 0; } @@ -1618,7 +1614,6 @@ ahd_send_async(struct ahd_softc *ahd, char channel, { char buf[80]; struct scsi_target *starget; - struct ahd_linux_target *targ; struct info_str info; struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; @@ -1651,7 +1646,6 @@ ahd_send_async(struct ahd_softc *ahd, char channel, starget = ahd->platform_data->starget[target]; if (starget == NULL) break; - targ = scsi_transport_target_data(starget); target_ppr_options = (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) @@ -1803,10 +1797,9 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) if (ahd_get_transaction_status(scb) == CAM_BDR_SENT || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); - if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { - ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; - up(&ahd->platform_data->eh_sem); - } + + if (ahd->platform_data->eh_done) + complete(ahd->platform_data->eh_done); } ahd_free_scb(ahd, scb); @@ -2030,60 +2023,16 @@ ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) cmd->scsi_done(cmd); } -static void -ahd_linux_sem_timeout(u_long arg) -{ - struct ahd_softc *ahd; - u_long s; - - ahd = (struct ahd_softc *)arg; - - ahd_lock(ahd, &s); - if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { - ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; - up(&ahd->platform_data->eh_sem); - } - ahd_unlock(ahd, &s); -} - void ahd_freeze_simq(struct ahd_softc *ahd) { - unsigned long s; - - ahd_lock(ahd, &s); - ahd->platform_data->qfrozen++; - if (ahd->platform_data->qfrozen == 1) { - scsi_block_requests(ahd->platform_data->host); - ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS, - CAM_LUN_WILDCARD, SCB_LIST_NULL, - ROLE_INITIATOR, CAM_REQUEUE_REQ); - } - ahd_unlock(ahd, &s); + scsi_block_requests(ahd->platform_data->host); } void ahd_release_simq(struct ahd_softc *ahd) { - u_long s; - int unblock_reqs; - - unblock_reqs = 0; - ahd_lock(ahd, &s); - if (ahd->platform_data->qfrozen > 0) - ahd->platform_data->qfrozen--; - if (ahd->platform_data->qfrozen == 0) { - unblock_reqs = 1; - } - ahd_unlock(ahd, &s); - /* - * There is still a race here. The mid-layer - * should keep its own freeze count and use - * a bottom half handler to run the queues - * so we can unblock with our own lock held. - */ - if (unblock_reqs) - scsi_unblock_requests(ahd->platform_data->host); + scsi_unblock_requests(ahd->platform_data->host); } static int @@ -2344,30 +2293,29 @@ done: if (paused) ahd_unpause(ahd); if (wait) { - struct timer_list timer; - int ret; + DECLARE_COMPLETION(done); - ahd->platform_data->flags |= AHD_SCB_UP_EH_SEM; + ahd->platform_data->eh_done = &done; ahd_unlock(ahd, &flags); - init_timer(&timer); - timer.data = (u_long)ahd; - timer.expires = jiffies + (5 * HZ); - timer.function = ahd_linux_sem_timeout; - add_timer(&timer); printf("%s: Recovery code sleeping\n", ahd_name(ahd)); - down(&ahd->platform_data->eh_sem); - printf("%s: Recovery code awake\n", ahd_name(ahd)); - ret = del_timer_sync(&timer); - if (ret == 0) { + if (!wait_for_completion_timeout(&done, 5 * HZ)) { + ahd_lock(ahd, &flags); + ahd->platform_data->eh_done = NULL; + ahd_unlock(ahd, &flags); printf("%s: Timer Expired (active %d)\n", ahd_name(ahd), dev->active); retval = FAILED; } + printf("Recovery code awake\n"); } else ahd_unlock(ahd, &flags); - return (retval); + if (retval != SUCCESS) + printf("%s: Command abort returning 0x%x\n", + ahd_name(ahd), retval); + + return retval; } static void ahd_linux_set_width(struct scsi_target *starget, int width) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 9cb101345107..599e3940db16 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -381,15 +381,12 @@ struct ahd_platform_data { struct scsi_target *starget[AHD_NUM_TARGETS]; spinlock_t spin_lock; - u_int qfrozen; - struct semaphore eh_sem; + struct completion *eh_done; struct Scsi_Host *host; /* pointer to scsi host */ #define AHD_LINUX_NOIRQ ((uint32_t)~0) uint32_t irq; /* IRQ for this adapter */ uint32_t bios_address; uint32_t mem_busaddr; /* Mem Base Addr */ -#define AHD_SCB_UP_EH_SEM 0x1 - uint32_t flags; }; /************************** OS Utility Wrappers *******************************/ -- cgit v1.2.3-59-g8ed1b From 0aa800db8f1927aefe6f0ba6ce9d70f044374aef Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 8 Mar 2006 12:56:56 +0100 Subject: [SCSI] aic79xx: use tcq functions This patch converts aic79xx to use the midlayer-supplied tcq functions. We also set the queuedepth to '1' if tcq is disabled; the aic79xx driver gets confused otherwise. Will set it back to '2' once I figure out how to queue requests in the driver. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_osm.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index fc393bd95f4a..4eb7bba24a68 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -1336,14 +1336,12 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) { case AHD_DEV_Q_BASIC: - scsi_adjust_queue_depth(sdev, - MSG_SIMPLE_TASK, - dev->openings + dev->active); + scsi_set_tag_type(sdev, MSG_SIMPLE_TASK); + scsi_activate_tcq(sdev, dev->openings + dev->active); break; case AHD_DEV_Q_TAGGED: - scsi_adjust_queue_depth(sdev, - MSG_ORDERED_TASK, - dev->openings + dev->active); + scsi_set_tag_type(sdev, MSG_ORDERED_TASK); + scsi_activate_tcq(sdev, dev->openings + dev->active); break; default: /* @@ -1352,9 +1350,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, * serially on the controller/device. This should * remove some latency. */ - scsi_adjust_queue_depth(sdev, - /*NON-TAGGED*/0, - /*queue depth*/2); + scsi_deactivate_tcq(sdev, 1); break; } } -- cgit v1.2.3-59-g8ed1b From 1ede5f9fe59ea245ad0ba859cfb08ac5814f6269 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 8 Mar 2006 12:57:28 +0100 Subject: [SCSI] aic79xx: Remove dead code Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_core.c | 1 - drivers/scsi/aic7xxx/aic79xx_osm.c | 59 ------------------------------------- drivers/scsi/aic7xxx/aic79xx_osm.h | 2 -- 3 files changed, 62 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index b6266fd31688..b2bcdd4ca1ab 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -7084,7 +7084,6 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) ahd_flush_qoutfifo(ahd); - ahd_platform_flushwork(ahd); ahd->flags &= ~AHD_ALL_INTERRUPTS; } diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 4eb7bba24a68..cb5f7af606ed 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -802,59 +802,6 @@ ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) } /********************* Platform Dependent Functions ***************************/ -/* - * Compare "left hand" softc with "right hand" softc, returning: - * < 0 - lahd has a lower priority than rahd - * 0 - Softcs are equal - * > 0 - lahd has a higher priority than rahd - */ -int -ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd) -{ - int value; - - /* - * Under Linux, cards are ordered as follows: - * 1) PCI devices that are marked as the boot controller. - * 2) PCI devices with BIOS enabled sorted by bus/slot/func. - * 3) All remaining PCI devices sorted by bus/slot/func. - */ -#if 0 - value = (lahd->flags & AHD_BOOT_CHANNEL) - - (rahd->flags & AHD_BOOT_CHANNEL); - if (value != 0) - /* Controllers set for boot have a *higher* priority */ - return (value); -#endif - - value = (lahd->flags & AHD_BIOS_ENABLED) - - (rahd->flags & AHD_BIOS_ENABLED); - if (value != 0) - /* Controllers with BIOS enabled have a *higher* priority */ - return (value); - - /* Still equal. Sort by bus/slot/func. */ - if (aic79xx_reverse_scan != 0) - value = ahd_get_pci_bus(lahd->dev_softc) - - ahd_get_pci_bus(rahd->dev_softc); - else - value = ahd_get_pci_bus(rahd->dev_softc) - - ahd_get_pci_bus(lahd->dev_softc); - if (value != 0) - return (value); - if (aic79xx_reverse_scan != 0) - value = ahd_get_pci_slot(lahd->dev_softc) - - ahd_get_pci_slot(rahd->dev_softc); - else - value = ahd_get_pci_slot(rahd->dev_softc) - - ahd_get_pci_slot(lahd->dev_softc); - if (value != 0) - return (value); - - value = rahd->channel - lahd->channel; - return (value); -} - static void ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value) { @@ -1595,12 +1542,6 @@ ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs) return IRQ_RETVAL(ours); } -void -ahd_platform_flushwork(struct ahd_softc *ahd) -{ - -} - void ahd_send_async(struct ahd_softc *ahd, char channel, u_int target, u_int lun, ac_code code, void *arg) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 599e3940db16..2b8331649eeb 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -872,8 +872,6 @@ int ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, role_t role, uint32_t status); irqreturn_t ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs); -void ahd_platform_flushwork(struct ahd_softc *ahd); -int ahd_softc_comp(struct ahd_softc *, struct ahd_softc *); void ahd_done(struct ahd_softc*, struct scb*); void ahd_send_async(struct ahd_softc *, char channel, u_int target, u_int lun, ac_code, void *); -- cgit v1.2.3-59-g8ed1b From 6902f41610d631f74cfca7c61eac7b0950dd8990 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 8 Mar 2006 12:58:16 +0100 Subject: [SCSI] aic79xx: Update error recovery This patch updates the error recovery. Routines for TARGET RESET and ABORT COMMAND are split up as the logic is quite dissimilar. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_osm.c | 325 +++++++++++++++++++++++-------------- 1 file changed, 201 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index cb5f7af606ed..00d48a0fb7e1 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -373,7 +373,7 @@ static void ahd_linux_handle_scsi_status(struct ahd_softc *, struct scb *); static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd); -static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); +static int ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd); static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); @@ -648,10 +648,9 @@ static int ahd_linux_abort(struct scsi_cmnd *cmd) { int error; + + error = ahd_linux_queue_abort_cmd(cmd); - error = ahd_linux_queue_recovery_cmd(cmd, SCB_ABORT); - if (error != 0) - printf("aic79xx_abort returns 0x%x\n", error); return error; } @@ -661,12 +660,97 @@ ahd_linux_abort(struct scsi_cmnd *cmd) static int ahd_linux_dev_reset(struct scsi_cmnd *cmd) { - int error; + struct ahd_softc *ahd; + struct ahd_linux_device *dev; + struct scb *reset_scb; + u_int cdb_byte; + int retval = SUCCESS; + int paused; + int wait; + struct ahd_initiator_tinfo *tinfo; + struct ahd_tmode_tstate *tstate; + unsigned long flags; + DECLARE_COMPLETION(done); - error = ahd_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET); - if (error != 0) - printf("aic79xx_dev_reset returns 0x%x\n", error); - return error; + reset_scb = NULL; + paused = FALSE; + wait = FALSE; + ahd = *(struct ahd_softc **)cmd->device->host->hostdata; + + scmd_printk(KERN_INFO, cmd, + "Attempting to queue a TARGET RESET message:"); + + printf("CDB:"); + for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) + printf(" 0x%x", cmd->cmnd[cdb_byte]); + printf("\n"); + + /* + * Determine if we currently own this command. + */ + dev = scsi_transport_device_data(cmd->device); + + if (dev == NULL) { + /* + * No target device for this command exists, + * so we must not still own the command. + */ + scmd_printk(KERN_INFO, cmd, "Is not an active device\n"); + return SUCCESS; + } + + /* + * Generate us a new SCB + */ + reset_scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX); + if (!reset_scb) { + scmd_printk(KERN_INFO, cmd, "No SCB available\n"); + return FAILED; + } + + tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, + cmd->device->id, &tstate); + reset_scb->io_ctx = cmd; + reset_scb->platform_data->dev = dev; + reset_scb->sg_count = 0; + ahd_set_residual(reset_scb, 0); + ahd_set_sense_residual(reset_scb, 0); + reset_scb->platform_data->xfer_len = 0; + reset_scb->hscb->control = 0; + reset_scb->hscb->scsiid = BUILD_SCSIID(ahd,cmd); + reset_scb->hscb->lun = cmd->device->lun; + reset_scb->hscb->cdb_len = 0; + reset_scb->hscb->task_management = SIU_TASKMGMT_LUN_RESET; + reset_scb->flags |= SCB_DEVICE_RESET|SCB_RECOVERY_SCB|SCB_ACTIVE; + if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { + reset_scb->flags |= SCB_PACKETIZED; + } else { + reset_scb->hscb->control |= MK_MESSAGE; + } + dev->openings--; + dev->active++; + dev->commands_issued++; + + ahd_lock(ahd, &flags); + + LIST_INSERT_HEAD(&ahd->pending_scbs, reset_scb, pending_links); + ahd_queue_scb(ahd, reset_scb); + + ahd->platform_data->eh_done = &done; + ahd_unlock(ahd, &flags); + + printf("%s: Device reset code sleeping\n", ahd_name(ahd)); + if (!wait_for_completion_timeout(&done, 5 * HZ)) { + ahd_lock(ahd, &flags); + ahd->platform_data->eh_done = NULL; + ahd_unlock(ahd, &flags); + printf("%s: Device reset timer expired (active %d)\n", + ahd_name(ahd), dev->active); + retval = FAILED; + } + printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval); + + return (retval); } /* @@ -1891,72 +1975,108 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) { + int status; + int new_status = DID_OK; + int do_fallback = 0; + int scsi_status; + /* * Map CAM error codes into Linux Error codes. We * avoid the conversion so that the DV code has the * full error information available when making * state change decisions. */ - { - uint32_t status; - u_int new_status; - - status = ahd_cmd_get_transaction_status(cmd); - switch (status) { - case CAM_REQ_INPROG: - case CAM_REQ_CMP: - case CAM_SCSI_STATUS_ERROR: - new_status = DID_OK; - break; - case CAM_REQ_ABORTED: - new_status = DID_ABORT; - break; - case CAM_BUSY: - new_status = DID_BUS_BUSY; - break; - case CAM_REQ_INVALID: - case CAM_PATH_INVALID: - new_status = DID_BAD_TARGET; - break; - case CAM_SEL_TIMEOUT: - new_status = DID_NO_CONNECT; - break; - case CAM_SCSI_BUS_RESET: - case CAM_BDR_SENT: - new_status = DID_RESET; - break; - case CAM_UNCOR_PARITY: - new_status = DID_PARITY; - break; - case CAM_CMD_TIMEOUT: - new_status = DID_TIME_OUT; - break; - case CAM_UA_ABORT: - case CAM_REQ_CMP_ERR: - case CAM_AUTOSENSE_FAIL: - case CAM_NO_HBA: - case CAM_DATA_RUN_ERR: - case CAM_UNEXP_BUSFREE: - case CAM_SEQUENCE_FAIL: - case CAM_CCB_LEN_ERR: - case CAM_PROVIDE_FAIL: - case CAM_REQ_TERMIO: - case CAM_UNREC_HBA_ERROR: - case CAM_REQ_TOO_BIG: - new_status = DID_ERROR; - break; - case CAM_REQUEUE_REQ: - new_status = DID_REQUEUE; + + status = ahd_cmd_get_transaction_status(cmd); + switch (status) { + case CAM_REQ_INPROG: + case CAM_REQ_CMP: + new_status = DID_OK; + break; + case CAM_AUTOSENSE_FAIL: + new_status = DID_ERROR; + /* Fallthrough */ + case CAM_SCSI_STATUS_ERROR: + scsi_status = ahd_cmd_get_scsi_status(cmd); + + switch(scsi_status) { + case SCSI_STATUS_CMD_TERMINATED: + case SCSI_STATUS_CHECK_COND: + if ((cmd->result >> 24) != DRIVER_SENSE) { + do_fallback = 1; + } else { + struct scsi_sense_data *sense; + + sense = (struct scsi_sense_data *) + &cmd->sense_buffer; + if (sense->extra_len >= 5 && + (sense->add_sense_code == 0x47 + || sense->add_sense_code == 0x48)) + do_fallback = 1; + } break; default: - /* We should never get here */ - new_status = DID_ERROR; break; } + break; + case CAM_REQ_ABORTED: + new_status = DID_ABORT; + break; + case CAM_BUSY: + new_status = DID_BUS_BUSY; + break; + case CAM_REQ_INVALID: + case CAM_PATH_INVALID: + new_status = DID_BAD_TARGET; + break; + case CAM_SEL_TIMEOUT: + new_status = DID_NO_CONNECT; + break; + case CAM_SCSI_BUS_RESET: + case CAM_BDR_SENT: + new_status = DID_RESET; + break; + case CAM_UNCOR_PARITY: + new_status = DID_PARITY; + do_fallback = 1; + break; + case CAM_CMD_TIMEOUT: + new_status = DID_TIME_OUT; + do_fallback = 1; + break; + case CAM_REQ_CMP_ERR: + case CAM_UNEXP_BUSFREE: + case CAM_DATA_RUN_ERR: + new_status = DID_ERROR; + do_fallback = 1; + break; + case CAM_UA_ABORT: + case CAM_NO_HBA: + case CAM_SEQUENCE_FAIL: + case CAM_CCB_LEN_ERR: + case CAM_PROVIDE_FAIL: + case CAM_REQ_TERMIO: + case CAM_UNREC_HBA_ERROR: + case CAM_REQ_TOO_BIG: + new_status = DID_ERROR; + break; + case CAM_REQUEUE_REQ: + new_status = DID_REQUEUE; + break; + default: + /* We should never get here */ + new_status = DID_ERROR; + break; + } - ahd_cmd_set_transaction_status(cmd, new_status); + if (do_fallback) { + printf("%s: device overrun (status %x) on %d:%d:%d\n", + ahd_name(ahd), status, cmd->device->channel, + cmd->device->id, cmd->device->lun); } + ahd_cmd_set_transaction_status(cmd, new_status); + cmd->scsi_done(cmd); } @@ -1973,7 +2093,7 @@ ahd_release_simq(struct ahd_softc *ahd) } static int -ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) +ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) { struct ahd_softc *ahd; struct ahd_linux_device *dev; @@ -1988,7 +2108,6 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) int paused; int wait; int disconnected; - int found; ahd_mode_state saved_modes; unsigned long flags; @@ -1998,8 +2117,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) ahd = *(struct ahd_softc **)cmd->device->host->hostdata; scmd_printk(KERN_INFO, cmd, - "Attempting to queue a%s message:", - flag == SCB_ABORT ? "n ABORT" : " TARGET RESET"); + "Attempting to queue an ABORT message:"); printf("CDB:"); for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) @@ -2035,19 +2153,6 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) break; } - if (pending_scb == NULL && flag == SCB_DEVICE_RESET) { - - /* Any SCB for this device will do for a target reset */ - LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { - if (ahd_match_scb(ahd, pending_scb, - scmd_id(cmd), - scmd_channel(cmd) + 'A', - CAM_LUN_WILDCARD, - SCB_LIST_NULL, ROLE_INITIATOR)) - break; - } - } - if (pending_scb == NULL) { scmd_printk(KERN_INFO, cmd, "Command not found\n"); goto no_cmd; @@ -2081,25 +2186,17 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) ahd_dump_card_state(ahd); disconnected = TRUE; - if (flag == SCB_ABORT) { - if (ahd_search_qinfifo(ahd, cmd->device->id, - cmd->device->channel + 'A', - cmd->device->lun, - pending_scb->hscb->tag, - ROLE_INITIATOR, CAM_REQ_ABORTED, - SEARCH_COMPLETE) > 0) { - printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", - ahd_name(ahd), cmd->device->channel, - cmd->device->id, cmd->device->lun); - retval = SUCCESS; - goto done; - } - } else if (ahd_search_qinfifo(ahd, cmd->device->id, - cmd->device->channel + 'A', - cmd->device->lun, pending_scb->hscb->tag, - ROLE_INITIATOR, /*status*/0, - SEARCH_COUNT) > 0) { - disconnected = FALSE; + if (ahd_search_qinfifo(ahd, cmd->device->id, + cmd->device->channel + 'A', + cmd->device->lun, + pending_scb->hscb->tag, + ROLE_INITIATOR, CAM_REQ_ABORTED, + SEARCH_COMPLETE) > 0) { + printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", + ahd_name(ahd), cmd->device->channel, + cmd->device->id, cmd->device->lun); + retval = SUCCESS; + goto done; } saved_modes = ahd_save_modes(ahd); @@ -2107,17 +2204,12 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) last_phase = ahd_inb(ahd, LASTPHASE); saved_scbptr = ahd_get_scbptr(ahd); active_scbptr = saved_scbptr; - if (disconnected && ((last_phase != P_BUSFREE) || - (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) { + if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) { struct scb *bus_scb; bus_scb = ahd_lookup_scb(ahd, active_scbptr); if (bus_scb == pending_scb) disconnected = FALSE; - else if (flag != SCB_ABORT - && ahd_inb(ahd, SAVED_SCSIID) == pending_scb->hscb->scsiid - && ahd_inb(ahd, SAVED_LUN) == SCB_GET_LUN(pending_scb)) - disconnected = FALSE; } /* @@ -2126,41 +2218,26 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) * bus or is in the disconnected state. */ saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); - if (SCB_GET_TAG(pending_scb) == active_scbptr - || (flag == SCB_DEVICE_RESET - && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) { + if (last_phase != P_BUSFREE + && SCB_GET_TAG(pending_scb) == active_scbptr) { /* * We're active on the bus, so assert ATN * and hope that the target responds. */ pending_scb = ahd_lookup_scb(ahd, active_scbptr); - pending_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET; + pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; ahd_outb(ahd, MSG_OUT, HOST_MSG); ahd_outb(ahd, SCSISIGO, last_phase|ATNO); - scmd_printk(KERN_INFO, cmd, "BDR message in message buffer\n"); + scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n"); wait = TRUE; - } else if (last_phase != P_BUSFREE - && ahd_inb(ahd, SCSIPHASE) == 0) { - /* - * SCB is not identified, there - * is no pending REQ, and the sequencer - * has not seen a busfree. Looks like - * a stuck connection waiting to - * go busfree. Reset the bus. - */ - found = ahd_reset_channel(ahd, cmd->device->channel + 'A', - /*Initiate Reset*/TRUE); - printf("%s: Issued Channel %c Bus Reset. " - "%d SCBs aborted\n", ahd_name(ahd), - cmd->device->channel + 'A', found); } else if (disconnected) { /* * Actually re-queue this SCB in an attempt * to select the device before it reconnects. */ - pending_scb->flags |= SCB_RECOVERY_SCB|flag; + pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); pending_scb->hscb->cdb_len = 0; pending_scb->hscb->task_attribute = 0; -- cgit v1.2.3-59-g8ed1b From 9e691dfba56f7d7a38b09edc5252264bc1bab659 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 8 Mar 2006 12:59:03 +0100 Subject: [SCSI] aic79xx: Invalid Sequencer interrupt occured On certain systems the driver seems to hit upon some "scsi0: Invalid Sequencer interrupt occurred." problem and dumps card state. According to Adaptec engineers this message is harmless. So as not to confuse user we can as well disable the internal card state dump and just print out the message itself. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index b2bcdd4ca1ab..326a62226235 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -978,9 +978,13 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) break; } case INVALID_SEQINT: - printf("%s: Invalid Sequencer interrupt occurred.\n", + printf("%s: Invalid Sequencer interrupt occurred, " + "resetting channel.\n", ahd_name(ahd)); - ahd_dump_card_state(ahd); +#ifdef AHD_DEBUG + if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) + ahd_dump_card_state(ahd); +#endif ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); break; case STATUS_OVERRUN: -- cgit v1.2.3-59-g8ed1b From 986a25f96accc8272059ae8b3eb63055f58cadb0 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 8 Mar 2006 12:59:35 +0100 Subject: [SCSI] aic79xx: use BIOS settings This patch fixes the aic79xx driver to properly respond to BIOS settings. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_osm.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 00d48a0fb7e1..0fbd1ec58340 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -481,6 +481,7 @@ ahd_linux_target_alloc(struct scsi_target *starget) { struct ahd_softc *ahd = *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata); + struct seeprom_config *sc = ahd->seep_config; unsigned long flags; struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget); struct ahd_linux_target *targ = scsi_transport_target_data(starget); @@ -496,18 +497,38 @@ ahd_linux_target_alloc(struct scsi_target *starget) *ahd_targp = starget; memset(targ, 0, sizeof(*targ)); + if (sc) { + int flags = sc->device_flags[starget->id]; + + tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, + starget->id, &tstate); + + if ((flags & CFPACKETIZED) == 0) { + /* Do not negotiate packetized transfers */ + spi_rd_strm(starget) = 0; + spi_pcomp_en(starget) = 0; + spi_rti(starget) = 0; + spi_wr_flow(starget) = 0; + spi_hold_mcs(starget) = 0; + } else { + if ((ahd->features & AHD_RTI) == 0) + spi_rti(starget) = 0; + } + + if ((flags & CFQAS) == 0) + spi_qas(starget) = 0; + + /* Transinfo values have been set to BIOS settings */ + spi_max_width(starget) = (flags & CFWIDEB) ? 1 : 0; + spi_min_period(starget) = tinfo->user.period; + spi_max_offset(starget) = tinfo->user.offset; + } + tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id, starget->id, &tstate); ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id, CAM_LUN_WILDCARD, channel, ROLE_INITIATOR); - spi_min_period(starget) = AHD_SYNCRATE_MAX; /* We can do U320 */ - if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) - spi_max_offset(starget) = MAX_OFFSET_PACED_BUG; - else - spi_max_offset(starget) = MAX_OFFSET_PACED; - spi_max_width(starget) = ahd->features & AHD_WIDE; - ahd_set_syncrate(ahd, &devinfo, 0, 0, 0, AHD_TRANS_GOAL, /*paused*/FALSE); ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, -- cgit v1.2.3-59-g8ed1b From 76744f429a178ad2df06b722e5e7bbbf1b5245ee Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 8 Mar 2006 13:00:07 +0100 Subject: [SCSI] aic79xx: Avoid renegotiation on inquiry Because of some quirk in the SCSI spec the aic79xx driver chose to force a renegotiation when sending an inquiry. This should better be handled by the upper layers if required at all. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_osm.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 0fbd1ec58340..bcced0a417e6 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -1526,30 +1526,6 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, if ((tstate->auto_negotiate & mask) != 0) { scb->flags |= SCB_AUTO_NEGOTIATE; scb->hscb->control |= MK_MESSAGE; - } else if (cmd->cmnd[0] == INQUIRY - && (tinfo->curr.offset != 0 - || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT - || tinfo->curr.ppr_options != 0) - && (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) { - /* - * The SCSI spec requires inquiry - * commands to complete without - * reporting unit attention conditions. - * Because of this, an inquiry command - * that occurs just after a device is - * reset will result in a data phase - * with mismatched negotiated rates. - * The core already forces a renegotiation - * for reset events that are visible to - * our controller or that we initiate, - * but a third party device reset or a - * hot-plug insertion can still cause this - * issue. Therefore, we force a re-negotiation - * for every inquiry command unless we - * are async. - */ - scb->flags |= SCB_NEGOTIATE; - scb->hscb->control |= MK_MESSAGE; } if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { -- cgit v1.2.3-59-g8ed1b From f018fa552c52642a6b9db2bda90477762e42163f Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Wed, 8 Mar 2006 00:14:20 -0800 Subject: [SCSI] MODULE_ALIAS_{BLOCK,CHAR}DEV_MAJOR for drivers/scsi Add device-major aliases in drivers/scsi, allowing kmod autoload: MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR) MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR) MODULE_ALIAS_CHARDEV_MAJOR(SCSI_TAPE_MAJOR) MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR) MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISKN_MAJOR) Signed-off-by: Andrew Morton Acked-by: Kai Makisara Signed-off-by: James Bottomley --- drivers/scsi/ch.c | 1 + drivers/scsi/osst.c | 1 + drivers/scsi/sd.c | 25 +++++++++++++++++++++---- drivers/scsi/sg.c | 2 +- drivers/scsi/sr.c | 4 ++++ drivers/scsi/st.c | 3 ++- 6 files changed, 30 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index c3f27285db1b..d9abd1645d15 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -39,6 +39,7 @@ MODULE_DESCRIPTION("device driver for scsi media changer devices"); MODULE_AUTHOR("Gerd Knorr "); MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR); static int init = 1; module_param(init, int, 0444); diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 00f3edc2417f..66ea47a9c53c 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -85,6 +85,7 @@ static int max_sg_segs = 0; MODULE_AUTHOR("Willem Riede"); MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR); module_param(max_dev, int, 0444); MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)"); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 31c9685ebc5a..3b01e5d6221c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -71,6 +71,27 @@ */ #define SD_MAJORS 16 +MODULE_AUTHOR("Eric Youngdale"); +MODULE_DESCRIPTION("SCSI disk (sd) driver"); +MODULE_LICENSE("GPL"); + +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK0_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK1_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK2_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK3_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK4_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK5_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK6_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK7_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK8_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK9_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK10_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK11_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK12_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK13_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK14_MAJOR); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR); + /* * This is limited by the naming scheme enforced in sd_probe, * add another character to it if you really need more disks. @@ -1713,9 +1734,5 @@ static void __exit exit_sd(void) unregister_blkdev(sd_major(i), "sd"); } -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Eric Youngdale"); -MODULE_DESCRIPTION("SCSI disk (sd) driver"); - module_init(init_sd); module_exit(exit_sd); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 06fc8ed720fc..af3fea59a456 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1569,6 +1569,7 @@ MODULE_AUTHOR("Douglas Gilbert"); MODULE_DESCRIPTION("SCSI generic (sg) driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(SG_VERSION_STR); +MODULE_ALIAS_CHARDEV_MAJOR(SCSI_GENERIC_MAJOR); MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd"); MODULE_PARM_DESC(allow_dio, "allow direct I/O (default: 0 (disallow))"); @@ -2966,4 +2967,3 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v) module_init(init_sg); module_exit(exit_sg); -MODULE_ALIAS_CHARDEV_MAJOR(SCSI_GENERIC_MAJOR); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 328837b7ccb9..f9c1192dc15e 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -60,6 +60,10 @@ #include "sr.h" +MODULE_DESCRIPTION("SCSI cdrom (sr) driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR); + #define SR_DISKS 256 #define MAX_RETRIES 3 diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 31c6eefba9d6..d40e7c871c36 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -86,8 +86,9 @@ static int st_nr_dev; static struct class *st_sysfs_class; MODULE_AUTHOR("Kai Makisara"); -MODULE_DESCRIPTION("SCSI Tape Driver"); +MODULE_DESCRIPTION("SCSI tape (st) driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(SCSI_TAPE_MAJOR); /* Set 'perm' (4th argument) to 0 to disable module_param's definition * of sysfs parameters (which module_param doesn't yet support). -- cgit v1.2.3-59-g8ed1b From 85ae97d816da3f8af9dcfbc4197a2950b55c3b0d Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:22 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: remove unused things * Remove unused #define's * Remove unused typedefs. * Remove prototypes for non-existing functions. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 345 +--------------------------------------------- 1 file changed, 1 insertion(+), 344 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 8d64f0bed628..38e6b71484b7 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -47,15 +47,10 @@ #define SccbMgr_isr FlashPoint_HandleInterrupt -#define MAX_CDBLEN 12 -#define SCAM_LEV_2 1 #define CRCMASK 0xA001 -#define BL_VENDOR_ID 0x104B -#define FP_DEVICE_ID 0x8130 -#define MM_DEVICE_ID 0x1040 #define FAILURE 0xFFFFFFFFL @@ -65,15 +60,9 @@ typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned int UINT; typedef unsigned long ULONG; -typedef unsigned char * PUCHAR; -typedef unsigned short* PUSHORT; -typedef unsigned long * PULONG; -typedef void * PVOID; -typedef unsigned char * uchar_ptr; typedef unsigned short * ushort_ptr; -typedef unsigned long * ulong_ptr; #define s08bits char @@ -84,9 +73,6 @@ typedef unsigned long * ulong_ptr; #define u16bits unsigned s16bits #define u32bits unsigned s32bits -typedef u08bits * pu08bits; -typedef u16bits * pu16bits; -typedef u32bits * pu32bits; #define BIT(x) ((UCHAR)(1<<(x))) /* single-bit mask in bit position x */ @@ -144,10 +130,6 @@ typedef SCCBMGR_INFO * PSCCBMGR_INFO; #define HARPOON_FAMILY 0x02 -#define ISA_BUS_CARD 0x01 -#define EISA_BUS_CARD 0x02 -#define PCI_BUS_CARD 0x03 -#define VESA_BUS_CARD 0x04 /* SCCB struct used for both SCCB and UCB manager compiles! * The UCB Manager treats the SCCB as it's 'native hardware structure' @@ -200,14 +182,11 @@ typedef struct _SCCB { ULONG Sccb_SGoffset; } SCCB; -#define SCCB_SIZE sizeof(SCCB) #pragma pack() -#define SCSI_INITIATOR_COMMAND 0x00 -#define TARGET_MODE_COMMAND 0x01 #define SCATTER_GATHER_COMMAND 0x02 #define RESIDUAL_COMMAND 0x03 #define RESIDUAL_SG_COMMAND 0x04 @@ -216,12 +195,10 @@ typedef struct _SCCB { #define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */ #define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */ -#define TAG_Q_MASK 0xE0 #define SCCB_DATA_XFER_OUT 0x10 /* Write */ #define SCCB_DATA_XFER_IN 0x08 /* Read */ -#define FOURTEEN_BYTES 0x00 /* Request Sense Buffer size */ #define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ @@ -235,9 +212,7 @@ typedef struct _SCCB { #define DATA_OUT_ST 7 #define DATA_IN_ST 8 #define DISCONNECT_ST 9 -#define STATUS_ST 10 #define ABORT_ST 11 -#define MESSAGE_ST 12 #define F_HOST_XFER_DIR 0x01 @@ -249,7 +224,6 @@ typedef struct _SCCB { #define F_STATUSLOADED 0x01 -#define F_MSGLOADED 0x02 #define F_DEV_SELECTED 0x04 @@ -257,56 +231,39 @@ typedef struct _SCCB { #define SCCB_DATA_UNDER_RUN 0x0C #define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ #define SCCB_DATA_OVER_RUN 0x12 -#define SCCB_UNEXPECTED_BUS_FREE 0x13 /* Target dropped SCSI BSY */ #define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */ -#define SCCB_INVALID_OP_CODE 0x16 /* SCCB invalid operation code */ -#define SCCB_INVALID_SCCB 0x1A /* Invalid SCCB - bad parameter */ #define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */ #define SCCB_BM_ERR 0x30 /* BusMaster error. */ #define SCCB_PARITY_ERR 0x34 /* SCSI parity error */ -#define SCCB_INVALID_DIRECTION 0x18 /* Invalid target direction */ -#define SCCB_DUPLICATE_SCCB 0x19 /* Duplicate SCCB */ -#define SCCB_SCSI_RST 0x35 /* SCSI RESET detected. */ #define SCCB_IN_PROCESS 0x00 #define SCCB_SUCCESS 0x01 #define SCCB_ABORT 0x02 -#define SCCB_NOT_FOUND 0x03 #define SCCB_ERROR 0x04 -#define SCCB_INVALID 0x05 -#define SCCB_SIZE sizeof(SCCB) #define ORION_FW_REV 3110 -#define HARP_REVD 1 #define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */ #define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */ -#define WIDE_SCSI 1 #define MAX_SCSI_TAR 16 #define MAX_LUN 32 #define LUN_MASK 0x1f -#if defined(HARP_REVA) -#define SG_BUF_CNT 15 /*Number of prefetched elements. */ -#else #define SG_BUF_CNT 16 /*Number of prefetched elements. */ -#endif #define SG_ELEMENT_SIZE 8 /*Eight byte per element. */ -#define SG_LOCAL_MASK 0x00000000L -#define SG_ELEMENT_MASK 0xFFFFFFFFL #define RD_HARPOON(ioport) OS_InPortByte((u32bits)ioport) @@ -318,31 +275,25 @@ typedef struct _SCCB { #define TAR_SYNC_MASK (BIT(7)+BIT(6)) -#define SYNC_UNKNOWN 0x00 #define SYNC_TRYING BIT(6) #define SYNC_SUPPORTED (BIT(7)+BIT(6)) #define TAR_WIDE_MASK (BIT(5)+BIT(4)) -#define WIDE_DISABLED 0x00 #define WIDE_ENABLED BIT(4) #define WIDE_NEGOCIATED BIT(5) #define TAR_TAG_Q_MASK (BIT(3)+BIT(2)) -#define TAG_Q_UNKNOWN 0x00 #define TAG_Q_TRYING BIT(2) #define TAG_Q_REJECT BIT(3) -#define TAG_Q_SUPPORTED (BIT(3)+BIT(2)) #define TAR_ALLOW_DISC BIT(0) #define EE_SYNC_MASK (BIT(0)+BIT(1)) -#define EE_SYNC_ASYNC 0x00 #define EE_SYNC_5MB BIT(0) #define EE_SYNC_10MB BIT(1) #define EE_SYNC_20MB (BIT(0)+BIT(1)) -#define EE_ALLOW_DISC BIT(6) #define EE_WIDE_SCSI BIT(7) @@ -418,7 +369,6 @@ typedef struct SCCBcard *PSCCBcard; #define ID_STRING_LENGTH 32 #define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */ -#define TYPE_CODE1 00 /*No ID yet */ #define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */ @@ -430,16 +380,9 @@ typedef struct SCCBcard *PSCCBcard; #define ID_0_7 0x18 #define ID_8_F 0x11 -#define ID_10_17 0x12 -#define ID_18_1F 0x0B #define MISC_CODE 0x14 #define CLR_P_FLAG 0x18 -#define LOCATE_ON 0x12 -#define LOCATE_OFF 0x0B -#define LVL_1_MST 0x00 -#define LVL_2_MST 0x40 -#define DOM_LVL_2 0xC0 #define INIT_SELTD 0x01 @@ -455,64 +398,24 @@ typedef struct SCCBscam_info { UCHAR id_string[ID_STRING_LENGTH]; enum scam_id_st state; -} SCCBSCAM_INFO, *PSCCBSCAM_INFO; +} SCCBSCAM_INFO; -#define SCSI_TEST_UNIT_READY 0x00 -#define SCSI_REZERO_UNIT 0x01 #define SCSI_REQUEST_SENSE 0x03 -#define SCSI_FORMAT_UNIT 0x04 -#define SCSI_REASSIGN 0x07 #define SCSI_READ 0x08 #define SCSI_WRITE 0x0A -#define SCSI_SEEK 0x0B -#define SCSI_INQUIRY 0x12 -#define SCSI_MODE_SELECT 0x15 -#define SCSI_RESERVE_UNIT 0x16 -#define SCSI_RELEASE_UNIT 0x17 -#define SCSI_MODE_SENSE 0x1A #define SCSI_START_STOP_UNIT 0x1B -#define SCSI_SEND_DIAGNOSTIC 0x1D -#define SCSI_READ_CAPACITY 0x25 #define SCSI_READ_EXTENDED 0x28 #define SCSI_WRITE_EXTENDED 0x2A -#define SCSI_SEEK_EXTENDED 0x2B #define SCSI_WRITE_AND_VERIFY 0x2E -#define SCSI_VERIFY 0x2F -#define SCSI_READ_DEFECT_DATA 0x37 -#define SCSI_WRITE_BUFFER 0x3B -#define SCSI_READ_BUFFER 0x3C -#define SCSI_RECV_DIAGNOSTIC 0x1C -#define SCSI_READ_LONG 0x3E -#define SCSI_WRITE_LONG 0x3F -#define SCSI_LAST_SCSI_CMND SCSI_WRITE_LONG -#define SCSI_INVALID_CMND 0xFF #define SSGOOD 0x00 #define SSCHECK 0x02 -#define SSCOND_MET 0x04 -#define SSBUSY 0x08 -#define SSRESERVATION_CONFLICT 0x18 -#define SSCMD_TERM 0x22 #define SSQ_FULL 0x28 -#define SKNO_SEN 0x00 -#define SKRECOV_ERR 0x01 -#define SKNOT_RDY 0x02 -#define SKMED_ERR 0x03 -#define SKHW_ERR 0x04 -#define SKILL_REQ 0x05 -#define SKUNIT_ATTN 0x06 -#define SKDATA_PROTECT 0x07 -#define SKBLNK_CHK 0x08 -#define SKCPY_ABORT 0x0A -#define SKABORT_CMD 0x0B -#define SKEQUAL 0x0C -#define SKVOL_OVF 0x0D -#define SKMIS_CMP 0x0E #define SMCMD_COMP 0x00 @@ -520,7 +423,6 @@ typedef struct SCCBscam_info { #define SMSAVE_DATA_PTR 0x02 #define SMREST_DATA_PTR 0x03 #define SMDISC 0x04 -#define SMINIT_DETEC_ERR 0x05 #define SMABORT 0x06 #define SMREJECT 0x07 #define SMNO_OP 0x08 @@ -535,35 +437,22 @@ typedef struct SCCBscam_info { #define SMSYNC 0x01 -#define SM10MBS 0x19 /* 100ns */ -#define SM5MBS 0x32 /* 200ns */ -#define SMOFFSET 0x0F /* Maxoffset value */ #define SMWDTR 0x03 #define SM8BIT 0x00 #define SM16BIT 0x01 -#define SM32BIT 0x02 #define SMIGNORWR 0x23 /* Ignore Wide Residue */ -#define ARBITRATION_DELAY 0x01 /* 2.4us using a 40Mhz clock */ -#define BUS_SETTLE_DELAY 0x01 /* 400ns */ -#define BUS_CLEAR_DELAY 0x01 /* 800ns */ -#define SPHASE_TO 0x0A /* 10 second timeout waiting for */ -#define SCMD_TO 0x0F /* Overall command timeout */ #define SIX_BYTE_CMD 0x06 -#define TEN_BYTE_CMD 0x0A #define TWELVE_BYTE_CMD 0x0C #define ASYNC 0x00 -#define PERI25NS 0x06 /* 25/4ns to next clock for xbow. */ -#define SYNC10MBS 0x19 -#define SYNC5MBS 0x32 #define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */ @@ -572,19 +461,11 @@ typedef struct SCCBscam_info { #define EEPROM_CHECK_SUM 0 #define FW_SIGNATURE 2 #define MODEL_NUMB_0 4 -#define MODEL_NUMB_1 5 #define MODEL_NUMB_2 6 -#define MODEL_NUMB_3 7 #define MODEL_NUMB_4 8 -#define MODEL_NUMB_5 9 -#define IO_BASE_ADDR 10 -#define IRQ_NUMBER 12 -#define PCI_INT_PIN 13 -#define BUS_DELAY 14 /*On time in byte 14 off delay in 15 */ #define SYSTEM_CONFIG 16 #define SCSI_CONFIG 17 #define BIOS_CONFIG 18 -#define SPIN_UP_DELAY 19 #define SCAM_CONFIG 20 #define ADAPTER_SCSI_ID 24 @@ -609,7 +490,6 @@ typedef struct SCCBscam_info { - #define DOM_MASTER (BIT(0) + BIT(1)) #define SCAM_ENABLED BIT(2) #define SCAM_LEVEL2 BIT(3) @@ -644,16 +524,9 @@ typedef struct SCCBscam_info { /* Sub Vendor ID and Sub Device ID only available in Harpoon Version 2 and higher */ - #define hp_sub_vendor_id_0 0x04 /* LSB */ - #define hp_sub_vendor_id_1 0x05 /* MSB */ #define hp_sub_device_id_0 0x06 /* LSB */ - #define hp_sub_device_id_1 0x07 /* MSB */ - #define hp_dual_addr_lo 0x08 - #define hp_dual_addr_lmi 0x09 - #define hp_dual_addr_hmi 0x0A - #define hp_dual_addr_hi 0x0B #define hp_semaphore 0x0C #define SCCB_MGR_ACTIVE BIT(0) @@ -661,9 +534,7 @@ typedef struct SCCBscam_info { #define SCCB_MGR_PRESENT BIT(3) #define BIOS_IN_USE BIT(4) - #define hp_user_defined_D 0x0D - #define hp_reserved_E 0x0E #define hp_sys_ctrl 0x0F @@ -671,95 +542,49 @@ typedef struct SCCBscam_info { #define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */ #define HALT_MACH BIT(3) /*Halt State Machine */ #define HARD_ABORT BIT(4) /*Hard Abort */ - #define DIAG_MODE BIT(5) /*Diagnostic Mode */ - #define BM_ABORT_TMOUT 0x50 /*Halt State machine time out */ - #define hp_sys_cfg 0x10 - #define DONT_RST_FIFO BIT(7) /*Don't reset FIFO */ - #define hp_host_ctrl0 0x11 - #define DUAL_ADDR_MODE BIT(0) /*Enable 64-bit addresses */ - #define IO_MEM_SPACE BIT(1) /*I/O Memory Space */ - #define RESOURCE_LOCK BIT(2) /*Enable Resource Lock */ - #define IGNOR_ACCESS_ERR BIT(3) /*Ignore Access Error */ - #define HOST_INT_EDGE BIT(4) /*Host interrupt level/edge mode sel */ - #define SIX_CLOCKS BIT(5) /*6 Clocks between Strobe */ - #define DMA_EVEN_PARITY BIT(6) /*Enable DMA Enen Parity */ -/* - #define BURST_MODE BIT(0) -*/ - #define hp_reserved_12 0x12 #define hp_host_blk_cnt 0x13 - #define XFER_BLK1 0x00 /* 0 0 0 1 byte per block*/ - #define XFER_BLK2 0x01 /* 0 0 1 2 byte per block*/ - #define XFER_BLK4 0x02 /* 0 1 0 4 byte per block*/ - #define XFER_BLK8 0x03 /* 0 1 1 8 byte per block*/ - #define XFER_BLK16 0x04 /* 1 0 0 16 byte per block*/ - #define XFER_BLK32 0x05 /* 1 0 1 32 byte per block*/ #define XFER_BLK64 0x06 /* 1 1 0 64 byte per block*/ #define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes*/ - #define hp_reserved_14 0x14 - #define hp_reserved_15 0x15 - #define hp_reserved_16 0x16 #define hp_int_mask 0x17 #define INT_CMD_COMPL BIT(0) /* DMA command complete */ #define INT_EXT_STATUS BIT(1) /* Extended Status Set */ - #define INT_SCSI BIT(2) /* Scsi block interrupt */ - #define INT_FIFO_RDY BIT(4) /* FIFO data ready */ #define hp_xfer_cnt_lo 0x18 - #define hp_xfer_cnt_mi 0x19 #define hp_xfer_cnt_hi 0x1A #define hp_xfer_cmd 0x1B #define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */ #define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */ - #define XFER_HOST_MPU 0x02 /* 0 1 0 Transfer Host -> MPU */ - #define XFER_MPU_HOST 0x03 /* 0 1 1 Transfer MPU -> Host */ - #define XFER_DMA_MPU 0x04 /* 1 0 0 Transfer DMA -> MPU */ - #define XFER_MPU_DMA 0x05 /* 1 0 1 Transfer MPU -> DMA */ - #define SET_SEMAPHORE 0x06 /* 1 1 0 Set Semaphore */ - #define XFER_NOP 0x07 /* 1 1 1 Transfer NOP */ - #define XFER_MB_MPU 0x06 /* 1 1 0 Transfer MB -> MPU */ - #define XFER_MB_DMA 0x07 /* 1 1 1 Transfer MB -> DMA */ #define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */ - #define XFER_HOST_8BIT 0x08 /* 0 1 8 BIT Transfer Size */ - #define XFER_HOST_16BIT 0x10 /* 1 0 16 BIT Transfer Size */ - #define XFER_HOST_32BIT 0x18 /* 1 1 32 BIT Transfer Size */ #define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */ - #define XFER_DMA_16BIT 0x40 /* 1 0 16 BIT Transfer Size */ #define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */ #define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT)) #define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT)) - #define WIDE_HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_16BIT)) - #define WIDE_HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_16BIT)) #define hp_host_addr_lo 0x1C - #define hp_host_addr_lmi 0x1D #define hp_host_addr_hmi 0x1E - #define hp_host_addr_hi 0x1F - #define hp_pio_data 0x20 - #define hp_reserved_21 0x21 #define hp_ee_ctrl 0x22 #define EXT_ARB_ACK BIT(7) @@ -777,17 +602,8 @@ typedef struct SCCBscam_info { #define EWDS 0x04 #define EWDS_ADDR 0x0000 - #define hp_brdctl 0x23 - #define DAT_7 BIT(7) - #define DAT_6 BIT(6) - #define DAT_5 BIT(5) - #define BRD_STB BIT(4) - #define BRD_CS BIT(3) - #define BRD_WR BIT(2) - #define hp_reserved_24 0x24 - #define hp_reserved_25 0x25 @@ -796,70 +612,36 @@ typedef struct SCCBscam_info { #define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */ #define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */ - #define BM_XFER_MIN_8 BIT(2) /*Enable bus master transfer of 9 */ - #define BIOS_ENA BIT(3) /*Enable BIOS/FLASH Enable */ #define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */ #define FAST_SINGLE BIT(6) /*?? */ #define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L) - #define hp_reserved_27 0x27 #define hp_sg_addr 0x28 #define hp_page_ctrl 0x29 #define SCATTER_EN BIT(0) #define SGRAM_ARAM BIT(1) - #define BIOS_SHADOW BIT(2) #define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */ #define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */ - #define hp_reserved_2A 0x2A - #define hp_pci_cmd_cfg 0x2B - #define IO_SPACE_ENA BIT(0) /*enable I/O space */ - #define MEM_SPACE_ENA BIT(1) /*enable memory space */ - #define BUS_MSTR_ENA BIT(2) /*enable bus master operation */ - #define MEM_WI_ENA BIT(4) /*enable Write and Invalidate */ - #define PAR_ERR_RESP BIT(6) /*enable parity error responce. */ - #define hp_reserved_2C 0x2C #define hp_pci_stat_cfg 0x2D - #define DATA_PARITY_ERR BIT(0) - #define REC_TARGET_ABORT BIT(4) /*received Target abort */ #define REC_MASTER_ABORT BIT(5) /*received Master abort */ - #define SIG_SYSTEM_ERR BIT(6) - #define DETECTED_PAR_ERR BIT(7) - #define hp_reserved_2E 0x2E - #define hp_sys_status 0x2F - #define SLV_DATA_RDY BIT(0) /*Slave data ready */ - #define XFER_CNT_ZERO BIT(1) /*Transfer counter = 0 */ - #define BM_FIFO_EMPTY BIT(2) /*FIFO empty */ - #define BM_FIFO_FULL BIT(3) /*FIFO full */ - #define HOST_OP_DONE BIT(4) /*host operation done */ - #define DMA_OP_DONE BIT(5) /*DMA operation done */ - #define SLV_OP_DONE BIT(6) /*Slave operation done */ - #define PWR_ON_FLAG BIT(7) /*Power on flag */ - #define hp_reserved_30 0x30 - #define hp_host_status0 0x31 - #define HOST_TERM BIT(5) /*Host Terminal Count */ - #define HOST_TRSHLD BIT(6) /*Host Threshold */ - #define CONNECTED_2_HOST BIT(7) /*Connected to Host */ - #define hp_reserved_32 0x32 #define hp_rev_num 0x33 - #define REV_A_CONST 0x0E - #define REV_B_CONST 0x0E #define hp_stack_data 0x34 #define hp_stack_addr 0x35 @@ -869,8 +651,6 @@ typedef struct SCCBscam_info { #define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */ #define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */ #define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */ - #define FIFO_TC_NOT_ZERO BIT(2) /*FIFO or transfer counter not zero */ - #define CHIP_RST_OCCUR BIT(3) /*Chip reset occurs */ #define CMD_ABORTED BIT(4) /*Command aborted */ #define BM_PARITY_ERR BIT(5) /*parity error on data received */ #define PIO_OVERRUN BIT(6) /*Slave data overrun */ @@ -880,24 +660,13 @@ typedef struct SCCBscam_info { #define hp_int_status 0x37 - #define BM_CMD_CMPL BIT(0) /*Bus Master command complete */ #define EXT_STATUS_ON BIT(1) /*Extended status is valid */ #define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */ - #define BM_FIFO_RDY BIT(4) #define INT_ASSERTED BIT(5) /* */ - #define SRAM_BUSY BIT(6) /*Scatter/Gather RAM busy */ - #define CMD_REG_BUSY BIT(7) #define hp_fifo_cnt 0x38 - #define hp_curr_host_cnt 0x39 - #define hp_reserved_3A 0x3A - #define hp_fifo_in_addr 0x3B - #define hp_fifo_out_addr 0x3C - #define hp_reserved_3D 0x3D - #define hp_reserved_3E 0x3E - #define hp_reserved_3F 0x3F @@ -937,9 +706,7 @@ typedef struct SCCBscam_info { #define SCSI_IOBIT BIT(0) #define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0)) - #define S_CMD_PH (BIT(2) ) #define S_MSGO_PH (BIT(2)+BIT(1) ) - #define S_STAT_PH (BIT(2) +BIT(0)) #define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0)) #define S_DATAI_PH ( BIT(0)) #define S_DATAO_PH 0x00 @@ -947,7 +714,6 @@ typedef struct SCCBscam_info { #define hp_scsictrl_0 0x45 - #define NO_ARB BIT(7) #define SEL_TAR BIT(6) #define ENA_ATN BIT(4) #define ENA_RESEL BIT(2) @@ -969,44 +735,33 @@ typedef struct SCCBscam_info { #define hp_scsireset 0x47 - #define SCSI_TAR BIT(7) #define SCSI_INI BIT(6) #define SCAM_EN BIT(5) - #define ACK_HOLD BIT(4) #define DMA_RESET BIT(3) #define HPSCSI_RESET BIT(2) #define PROG_RESET BIT(1) #define FIFO_CLR BIT(0) #define hp_xfercnt_0 0x48 - #define hp_xfercnt_1 0x49 #define hp_xfercnt_2 0x4A - #define hp_xfercnt_3 0x4B #define hp_fifodata_0 0x4C - #define hp_fifodata_1 0x4D #define hp_addstat 0x4E #define SCAM_TIMER BIT(7) - #define AUTO_RUNNING BIT(6) - #define FAST_SYNC BIT(5) #define SCSI_MODE8 BIT(3) #define SCSI_PAR_ERR BIT(0) #define hp_prgmcnt_0 0x4F - #define AUTO_PC_MASK 0x3F #define hp_selfid_0 0x50 #define hp_selfid_1 0x51 #define hp_arb_id 0x52 - #define ARB_ID (BIT(3) + BIT(2) + BIT(1) + BIT(0)) #define hp_select_id 0x53 - #define RESEL_ID (BIT(7) + BIT(6) + BIT(5) + BIT(4)) - #define SELECT_ID (BIT(3) + BIT(2) + BIT(1) + BIT(0)) #define hp_synctarg_base 0x54 #define hp_synctarg_12 0x54 @@ -1029,63 +784,38 @@ typedef struct SCCBscam_info { #define hp_synctarg_2 0x62 #define hp_synctarg_3 0x63 - #define RATE_20MB 0x00 - #define RATE_10MB ( BIT(5)) - #define RATE_6_6MB ( BIT(6) ) - #define RATE_5MB ( BIT(6)+BIT(5)) - #define RATE_4MB (BIT(7) ) - #define RATE_3_33MB (BIT(7) +BIT(5)) - #define RATE_2_85MB (BIT(7)+BIT(6) ) - #define RATE_2_5MB (BIT(7)+BIT(5)+BIT(6)) - #define NEXT_CLK BIT(5) - #define SLOWEST_SYNC (BIT(7)+BIT(6)+BIT(5)) #define NARROW_SCSI BIT(4) - #define SYNC_OFFSET (BIT(3) + BIT(2) + BIT(1) + BIT(0)) - #define DEFAULT_ASYNC 0x00 #define DEFAULT_OFFSET 0x0F #define hp_autostart_0 0x64 #define hp_autostart_1 0x65 - #define hp_autostart_2 0x66 #define hp_autostart_3 0x67 - #define DISABLE 0x00 #define AUTO_IMMED BIT(5) #define SELECT BIT(6) - #define RESELECT (BIT(6)+BIT(5)) - #define BUSFREE BIT(7) - #define XFER_0 (BIT(7)+BIT(5)) #define END_DATA (BIT(7)+BIT(6)) - #define MSG_PHZ (BIT(7)+BIT(6)+BIT(5)) #define hp_gp_reg_0 0x68 #define hp_gp_reg_1 0x69 - #define hp_gp_reg_2 0x6A #define hp_gp_reg_3 0x6B #define hp_seltimeout 0x6C - #define TO_2ms 0x54 /* 2.0503ms */ #define TO_4ms 0x67 /* 3.9959ms */ #define TO_5ms 0x03 /* 4.9152ms */ #define TO_10ms 0x07 /* 11.xxxms */ #define TO_250ms 0x99 /* 250.68ms */ #define TO_290ms 0xB1 /* 289.99ms */ - #define TO_350ms 0xD6 /* 350.62ms */ - #define TO_417ms 0xFF /* 417.79ms */ #define hp_clkctrl_0 0x6D #define PWR_DWN BIT(6) #define ACTdeassert BIT(4) - #define ATNonErr BIT(3) - #define CLK_30MHZ BIT(1) #define CLK_40MHZ (BIT(1) + BIT(0)) - #define CLK_50MHZ BIT(2) #define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ) @@ -1095,38 +825,21 @@ typedef struct SCCBscam_info { #define hp_offsetctr 0x70 #define hp_xferstat 0x71 - #define FIFO_FULL BIT(7) #define FIFO_EMPTY BIT(6) - #define FIFO_MASK 0x3F /* Mask for the FIFO count value. */ - #define FIFO_LEN 0x20 #define hp_portctrl_1 0x72 - #define EVEN_HOST_P BIT(5) - #define INVT_SCSI BIT(4) #define CHK_SCSI_P BIT(3) #define HOST_MODE8 BIT(0) - #define HOST_MODE16 0x00 #define hp_xfer_pad 0x73 #define ID_UNLOCK BIT(3) - #define XFER_PAD BIT(2) #define hp_scsidata_0 0x74 #define hp_scsidata_1 0x75 - #define hp_timer_0 0x76 - #define hp_timer_1 0x77 - #define hp_reserved_78 0x78 - #define hp_reserved_79 0x79 - #define hp_reserved_7A 0x7A - #define hp_reserved_7B 0x7B - #define hp_reserved_7C 0x7C - #define hp_reserved_7D 0x7D - #define hp_reserved_7E 0x7E - #define hp_reserved_7F 0x7F #define hp_aramBase 0x80 #define BIOS_DATA_OFFSET 0x60 @@ -1135,22 +848,15 @@ typedef struct SCCBscam_info { - #define AUTO_LEN 0x80 - #define AR0 0x00 - #define AR1 BITW(8) - #define AR2 BITW(9) #define AR3 (BITW(9) + BITW(8)) #define SDATA BITW(10) - #define NOP_OP 0x00 /* Nop command */ #define CRD_OP BITW(11) /* Cmp Reg. w/ Data */ #define CRR_OP BITW(12) /* Cmp Reg. w. Reg. */ - #define CBE_OP (BITW(14)+BITW(12)+BITW(11)) /* Cmp SCSI cmd class & Branch EQ */ - #define CBN_OP (BITW(14)+BITW(13)) /* Cmp SCSI cmd class & Branch NOT EQ */ #define CPE_OP (BITW(14)+BITW(11)) /* Cmp SCSI phs & Branch EQ */ @@ -1163,7 +869,6 @@ typedef struct SCCBscam_info { #define ASTATUS (BITW(10)+BITW(8)) #define AMSG_OUT (BITW(10)+BITW(9)) #define AMSG_IN (BITW(10)+BITW(9)+BITW(8)) - #define AILLEGAL (BITW(9)+BITW(8)) #define BRH_OP BITW(13) /* Branch */ @@ -1176,17 +881,11 @@ typedef struct SCCBscam_info { #define TCB_OP (BITW(13)+BITW(11)) /* Test condition & branch */ - #define ATN_SET BITW(8) - #define ATN_RESET BITW(9) - #define XFER_CNT (BITW(9)+BITW(8)) #define FIFO_0 BITW(10) - #define FIFO_NOT0 (BITW(10)+BITW(8)) - #define T_USE_SYNC0 (BITW(10)+BITW(9)) #define MPM_OP BITW(15) /* Match phase and move data */ - #define MDR_OP (BITW(12)+BITW(11)) /* Move data to Reg. */ #define MRR_OP BITW(14) /* Move DReg. to Reg. */ @@ -1196,34 +895,14 @@ typedef struct SCCBscam_info { #define D_AR0 0x00 #define D_AR1 BIT(0) - #define D_AR2 BIT(1) - #define D_AR3 (BIT(1) + BIT(0)) - #define D_SDATA BIT(2) #define D_BUCKET (BIT(2) + BIT(1) + BIT(0)) - #define ADR_OP (BITW(13)+BITW(12)) /* Logical AND Reg. w. Data */ - #define ADS_OP (BITW(14)+BITW(13)+BITW(12)) - #define ODR_OP (BITW(13)+BITW(12)+BITW(11)) - #define ODS_OP (BITW(14)+BITW(13)+BITW(12)+BITW(11)) - #define STR_OP (BITW(15)+BITW(14)) /* Store to A_Reg. */ - #define AINT_ENA1 0x00 - #define AINT_STAT1 BITW(8) - #define ASCSI_SIG BITW(9) - #define ASCSI_CNTL (BITW(9)+BITW(8)) - #define APORT_CNTL BITW(10) - #define ARST_CNTL (BITW(10)+BITW(8)) - #define AXFERCNT0 (BITW(10)+BITW(9)) - #define AXFERCNT1 (BITW(10)+BITW(9)+BITW(8)) - #define AXFERCNT2 BITW(11) - #define AFIFO_DATA (BITW(11)+BITW(8)) - #define ASCSISELID (BITW(11)+BITW(9)) - #define ASCSISYNC0 (BITW(11)+BITW(9)+BITW(8)) #define RAT_OP (BITW(14)+BITW(13)+BITW(11)) @@ -1233,7 +912,6 @@ typedef struct SCCBscam_info { #define SSI_ITAR_DISC (ITAR_DISC >> 8) #define SSI_IDO_STRT (IDO_STRT >> 8) - #define SSI_IDI_STRT (IDO_STRT >> 8) #define SSI_ICMD_COMP (ICMD_COMP >> 8) #define SSI_ITICKLE (ITICKLE >> 8) @@ -1248,13 +926,11 @@ typedef struct SCCBscam_info { #define CMDPZ 0x04 /*Command phase */ #define DINT 0x12 /*Data Out/In interrupt */ #define DI 0x13 /*Data Out */ - #define MI 0x14 /*Message In */ #define DC 0x19 /*Disconnect Message */ #define ST 0x1D /*Status Phase */ #define UNKNWN 0x24 /*Unknown bus action */ #define CC 0x25 /*Command Completion failure */ #define TICK 0x26 /*New target reselected us. */ - #define RFAIL 0x27 /*Reselection failed */ #define SELCHK 0x28 /*Select & Check SCSI ID latch reg */ @@ -1268,25 +944,18 @@ typedef struct SCCBscam_info { #define TAG_STRT 0x00 - #define SELECTION_START 0x00 #define DISCONNECT_START 0x10/2 #define END_DATA_START 0x14/2 - #define NONTAG_STRT 0x02/2 #define CMD_ONLY_STRT CMDPZ/2 - #define TICKLE_STRT TICK/2 #define SELCHK_STRT SELCHK/2 -#define mEEPROM_CLK_DELAY(port) (RD_HARPOON(port+hp_intstat_1)) -#define mWAIT_10MS(port) (RD_HARPOON(port+hp_intstat_1)) -#define CLR_XFER_CNT(port) (WR_HARPOON(port+hp_xfercnt_0, 0x00)) -#define SET_XFER_CNT(port, data) (WR_HARP32(port,hp_xfercnt_0,data)) #define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;} /* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \ @@ -1308,11 +977,7 @@ typedef struct SCCBscam_info { #define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));} -#define ACCEPT_STAT(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ - WR_HARPOON(port+hp_scsisig, S_ILL_PH);} -#define ACCEPT_STAT_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ - WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));} #define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\ WR_HARPOON(port+hp_scsireset, 0x00)) @@ -1332,7 +997,6 @@ typedef struct SCCBscam_info { -void scsiStartAuto(ULONG port); static UCHAR FPT_sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag); static void FPT_ssel(ULONG port, UCHAR p_card); static void FPT_sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard); @@ -1405,7 +1069,6 @@ static void FPT_DiagEEPROM(ULONG p_port); -void busMstrAbort(ULONG port); static void FPT_dataXferProcessor(ULONG port, PSCCBcard pCurrCard); static void FPT_busMstrSGDataXferStart(ULONG port, PSCCB pCurrSCCB); static void FPT_busMstrDataXferStart(ULONG port, PSCCB pCurrSCCB); @@ -1446,12 +1109,6 @@ static void FPT_autoLoadDefaultMap(ULONG p_port); -void OS_start_timer(unsigned long ioport, unsigned long timeout); -void OS_stop_timer(unsigned long ioport, unsigned long timeout); -void OS_disable_int(unsigned char intvec); -void OS_enable_int(unsigned char intvec); -void OS_delay(unsigned long count); -int OS_VirtToPhys(u32bits CardHandle, u32bits *physaddr, u32bits *virtaddr); static SCCBMGR_TAR_INFO FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } }; static SCCBCARD FPT_BL_Card[MAX_CARDS] = { { 0 } }; -- cgit v1.2.3-59-g8ed1b From d8b6b8bd8a99ee91843381d51e8e619463721aed Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:23 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: remove trivial wrappers Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 54 +++++++++++++++++------------------------------ 1 file changed, 19 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 38e6b71484b7..1d1e4413c8d1 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -26,25 +26,9 @@ #undef BUSTYPE_PCI -#define OS_InPortByte(port) inb(port) -#define OS_InPortWord(port) inw(port) -#define OS_InPortLong(port) inl(port) -#define OS_OutPortByte(port, value) outb(value, port) -#define OS_OutPortWord(port, value) outw(value, port) -#define OS_OutPortLong(port, value) outl(value, port) -/* - Define name replacements for compatibility with the Linux BusLogic Driver. -*/ -#define SccbMgr_sense_adapter FlashPoint_ProbeHostAdapter -#define SccbMgr_config_adapter FlashPoint_HardwareResetHostAdapter -#define SccbMgr_unload_card FlashPoint_ReleaseHostAdapter -#define SccbMgr_start_sccb FlashPoint_StartCCB -#define SccbMgr_abort_sccb FlashPoint_AbortCCB -#define SccbMgr_my_int FlashPoint_InterruptPending -#define SccbMgr_isr FlashPoint_HandleInterrupt @@ -266,12 +250,12 @@ typedef struct _SCCB { #define SG_ELEMENT_SIZE 8 /*Eight byte per element. */ -#define RD_HARPOON(ioport) OS_InPortByte((u32bits)ioport) -#define RDW_HARPOON(ioport) OS_InPortWord((u32bits)ioport) -#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((u32bits)(ioport + offset))) -#define WR_HARPOON(ioport,val) OS_OutPortByte((u32bits)ioport,(u08bits) val) -#define WRW_HARPOON(ioport,val) OS_OutPortWord((u32bits)ioport,(u16bits)val) -#define WR_HARP32(ioport,offset,data) OS_OutPortLong((u32bits)(ioport + offset), data) +#define RD_HARPOON(ioport) inb((u32bits)ioport) +#define RDW_HARPOON(ioport) inw((u32bits)ioport) +#define RD_HARP32(ioport,offset,data) (data = inl((u32bits)(ioport + offset))) +#define WR_HARPOON(ioport,val) outb((u08bits) val, (u32bits)ioport) +#define WRW_HARPOON(ioport,val) outw((u16bits)val, (u32bits)ioport) +#define WR_HARP32(ioport,offset,data) outl(data, (u32bits)(ioport + offset)) #define TAR_SYNC_MASK (BIT(7)+BIT(6)) @@ -1130,13 +1114,13 @@ static void (*FPT_s_PhaseTbl[8]) (ULONG, UCHAR)= { 0 }; /*--------------------------------------------------------------------- * - * Function: SccbMgr_sense_adapter + * Function: FlashPoint_ProbeHostAdapter * * Description: Setup and/or Search for cards and return info to caller. * *---------------------------------------------------------------------*/ -static int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo) +static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) { static UCHAR first_time = 1; @@ -1408,13 +1392,13 @@ static int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo) /*--------------------------------------------------------------------- * - * Function: SccbMgr_config_adapter + * Function: FlashPoint_HardwareResetHostAdapter * * Description: Setup adapter for normal operation (hard reset). * *---------------------------------------------------------------------*/ -static ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo) +static ULONG FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) { PSCCBcard CurrCard = NULL; PNVRamInfo pCurrNvRam; @@ -1595,7 +1579,7 @@ static ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo) return((ULONG)CurrCard); } -static void SccbMgr_unload_card(ULONG pCurrCard) +static void FlashPoint_ReleaseHostAdapter(ULONG pCurrCard) { UCHAR i; ULONG portBase; @@ -1687,14 +1671,14 @@ static UCHAR FPT_ChkIfChipInitialized(ULONG ioPort) } /*--------------------------------------------------------------------- * - * Function: SccbMgr_start_sccb + * Function: FlashPoint_StartCCB * * Description: Start a command pointed to by p_Sccb. When the * command is completed it will be returned via the * callback function. * *---------------------------------------------------------------------*/ -static void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb) +static void FlashPoint_StartCCB(ULONG pCurrCard, PSCCB p_Sccb) { ULONG ioport; UCHAR thisCard, lun; @@ -1807,14 +1791,14 @@ static void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb) /*--------------------------------------------------------------------- * - * Function: SccbMgr_abort_sccb + * Function: FlashPoint_AbortCCB * * Description: Abort the command pointed to by p_Sccb. When the * command is completed it will be returned via the * callback function. * *---------------------------------------------------------------------*/ -static int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb) +static int FlashPoint_AbortCCB(ULONG pCurrCard, PSCCB p_Sccb) { ULONG ioport; @@ -1908,13 +1892,13 @@ static int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb) /*--------------------------------------------------------------------- * - * Function: SccbMgr_my_int + * Function: FlashPoint_InterruptPending * * Description: Do a quick check to determine if there is a pending * interrupt for this card and disable the IRQ Pin if so. * *---------------------------------------------------------------------*/ -static UCHAR SccbMgr_my_int(ULONG pCurrCard) +static UCHAR FlashPoint_InterruptPending(ULONG pCurrCard) { ULONG ioport; @@ -1934,14 +1918,14 @@ static UCHAR SccbMgr_my_int(ULONG pCurrCard) /*--------------------------------------------------------------------- * - * Function: SccbMgr_isr + * Function: FlashPoint_HandleInterrupt * * Description: This is our entry point when an interrupt is generated * by the card and the upper level driver passes it on to * us. * *---------------------------------------------------------------------*/ -static int SccbMgr_isr(ULONG pCurrCard) +static int FlashPoint_HandleInterrupt(ULONG pCurrCard) { PSCCB currSCCB; UCHAR thisCard,result,bm_status, bm_int_st; -- cgit v1.2.3-59-g8ed1b From db038cf86fc63d336fc9d8e57712dee1d726e2e9 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:24 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: remove UCHAR Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 677 +++++++++++++++++++++++----------------------- 1 file changed, 338 insertions(+), 339 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 1d1e4413c8d1..e98bbef485b8 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -40,7 +40,6 @@ #define FAILURE 0xFFFFFFFFL -typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned int UINT; typedef unsigned long ULONG; @@ -59,7 +58,7 @@ typedef unsigned short * ushort_ptr; -#define BIT(x) ((UCHAR)(1<<(x))) /* single-bit mask in bit position x */ +#define BIT(x) ((unsigned char)(1<<(x))) /* single-bit mask in bit position x */ #define BITW(x) ((USHORT)(1<<(x))) /* single-bit mask in bit position x */ @@ -71,10 +70,10 @@ typedef void (*CALL_BK_FN)(PSCCB); typedef struct SCCBMgr_info { ULONG si_baseaddr; - UCHAR si_present; - UCHAR si_intvect; - UCHAR si_id; - UCHAR si_lun; + unsigned char si_present; + unsigned char si_intvect; + unsigned char si_id; + unsigned char si_lun; USHORT si_fw_revision; USHORT si_per_targ_init_sync; USHORT si_per_targ_fast_nego; @@ -82,13 +81,13 @@ typedef struct SCCBMgr_info { USHORT si_per_targ_no_disc; USHORT si_per_targ_wide_nego; USHORT si_flags; - UCHAR si_card_family; - UCHAR si_bustype; - UCHAR si_card_model[3]; - UCHAR si_relative_cardnum; - UCHAR si_reserved[4]; + unsigned char si_card_family; + unsigned char si_bustype; + unsigned char si_card_model[3]; + unsigned char si_relative_cardnum; + unsigned char si_reserved[4]; ULONG si_OS_reserved; - UCHAR si_XlatInfo[4]; + unsigned char si_XlatInfo[4]; ULONG si_reserved2[5]; ULONG si_secondary_range; } SCCBMGR_INFO; @@ -122,28 +121,28 @@ typedef SCCBMGR_INFO * PSCCBMGR_INFO; #pragma pack(1) typedef struct _SCCB { - UCHAR OperationCode; - UCHAR ControlByte; - UCHAR CdbLength; - UCHAR RequestSenseLength; + unsigned char OperationCode; + unsigned char ControlByte; + unsigned char CdbLength; + unsigned char RequestSenseLength; ULONG DataLength; ULONG DataPointer; - UCHAR CcbRes[2]; - UCHAR HostStatus; - UCHAR TargetStatus; - UCHAR TargID; - UCHAR Lun; - UCHAR Cdb[12]; - UCHAR CcbRes1; - UCHAR Reserved1; + unsigned char CcbRes[2]; + unsigned char HostStatus; + unsigned char TargetStatus; + unsigned char TargID; + unsigned char Lun; + unsigned char Cdb[12]; + unsigned char CcbRes1; + unsigned char Reserved1; ULONG Reserved2; ULONG SensePointer; CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */ ULONG SccbIOPort; /* Identifies board base port */ - UCHAR SccbStatus; - UCHAR SCCBRes2; + unsigned char SccbStatus; + unsigned char SCCBRes2; USHORT SccbOSFlags; @@ -153,16 +152,16 @@ typedef struct _SCCB { ULONG Sccb_res1; USHORT Sccb_MGRFlags; USHORT Sccb_sgseg; - UCHAR Sccb_scsimsg; /* identify msg for selection */ - UCHAR Sccb_tag; - UCHAR Sccb_scsistat; - UCHAR Sccb_idmsg; /* image of last msg in */ + unsigned char Sccb_scsimsg; /* identify msg for selection */ + unsigned char Sccb_tag; + unsigned char Sccb_scsistat; + unsigned char Sccb_idmsg; /* image of last msg in */ PSCCB Sccb_forwardlink; PSCCB Sccb_backlink; ULONG Sccb_savedATC; - UCHAR Save_Cdb[6]; - UCHAR Save_CdbLen; - UCHAR Sccb_XferState; + unsigned char Save_Cdb[6]; + unsigned char Save_CdbLen; + unsigned char Sccb_XferState; ULONG Sccb_SGoffset; } SCCB; @@ -288,27 +287,27 @@ typedef struct SCCBMgr_tar_info { PSCCB TarSelQ_Head; PSCCB TarSelQ_Tail; - UCHAR TarLUN_CA; /*Contingent Allgiance */ - UCHAR TarTagQ_Cnt; - UCHAR TarSelQ_Cnt; - UCHAR TarStatus; - UCHAR TarEEValue; - UCHAR TarSyncCtrl; - UCHAR TarReserved[2]; /* for alignment */ - UCHAR LunDiscQ_Idx[MAX_LUN]; - UCHAR TarLUNBusy[MAX_LUN]; + unsigned char TarLUN_CA; /*Contingent Allgiance */ + unsigned char TarTagQ_Cnt; + unsigned char TarSelQ_Cnt; + unsigned char TarStatus; + unsigned char TarEEValue; + unsigned char TarSyncCtrl; + unsigned char TarReserved[2]; /* for alignment */ + unsigned char LunDiscQ_Idx[MAX_LUN]; + unsigned char TarLUNBusy[MAX_LUN]; } SCCBMGR_TAR_INFO; typedef struct NVRAMInfo { - UCHAR niModel; /* Model No. of card */ - UCHAR niCardNo; /* Card no. */ + unsigned char niModel; /* Model No. of card */ + unsigned char niCardNo; /* Card no. */ ULONG niBaseAddr; /* Port Address of card */ - UCHAR niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */ - UCHAR niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */ - UCHAR niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */ - UCHAR niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */ - UCHAR niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */ - UCHAR niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */ + unsigned char niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */ + unsigned char niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */ + unsigned char niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */ + unsigned char niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */ + unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */ + unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */ }NVRAMINFO; typedef NVRAMINFO *PNVRamInfo; @@ -326,12 +325,12 @@ typedef struct SCCBcard { ULONG ioPort; USHORT cmdCounter; - UCHAR discQCount; - UCHAR tagQ_Lst; - UCHAR cardIndex; - UCHAR scanIndex; - UCHAR globalFlags; - UCHAR ourId; + unsigned char discQCount; + unsigned char tagQ_Lst; + unsigned char cardIndex; + unsigned char scanIndex; + unsigned char globalFlags; + unsigned char ourId; PNVRamInfo pNvRamInfo; PSCCB discQ_Tbl[QUEUE_DEPTH]; @@ -379,7 +378,7 @@ enum scam_id_st { ID0,ID1,ID2,ID3,ID4,ID5,ID6,ID7,ID8,ID9,ID10,ID11,ID12, typedef struct SCCBscam_info { - UCHAR id_string[ID_STRING_LENGTH]; + unsigned char id_string[ID_STRING_LENGTH]; enum scam_id_st state; } SCCBSCAM_INFO; @@ -981,72 +980,72 @@ typedef struct SCCBscam_info { -static UCHAR FPT_sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag); -static void FPT_ssel(ULONG port, UCHAR p_card); -static void FPT_sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard); -static void FPT_shandem(ULONG port, UCHAR p_card,PSCCB pCurrSCCB); -static void FPT_stsyncn(ULONG port, UCHAR p_card); -static void FPT_sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset); -static void FPT_sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value, +static unsigned char FPT_sisyncn(ULONG port, unsigned char p_card, unsigned char syncFlag); +static void FPT_ssel(ULONG port, unsigned char p_card); +static void FPT_sres(ULONG port, unsigned char p_card, PSCCBcard pCurrCard); +static void FPT_shandem(ULONG port, unsigned char p_card,PSCCB pCurrSCCB); +static void FPT_stsyncn(ULONG port, unsigned char p_card); +static void FPT_sisyncr(ULONG port,unsigned char sync_pulse, unsigned char offset); +static void FPT_sssyncv(ULONG p_port, unsigned char p_id, unsigned char p_sync_value, PSCCBMgr_tar_info currTar_Info); -static void FPT_sresb(ULONG port, UCHAR p_card); -static void FPT_sxfrp(ULONG p_port, UCHAR p_card); -static void FPT_schkdd(ULONG port, UCHAR p_card); -static UCHAR FPT_RdStack(ULONG port, UCHAR index); -static void FPT_WrStack(ULONG portBase, UCHAR index, UCHAR data); -static UCHAR FPT_ChkIfChipInitialized(ULONG ioPort); - -static void FPT_SendMsg(ULONG port, UCHAR message); -static void FPT_queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, - UCHAR error_code); - -static void FPT_sinits(PSCCB p_sccb, UCHAR p_card); +static void FPT_sresb(ULONG port, unsigned char p_card); +static void FPT_sxfrp(ULONG p_port, unsigned char p_card); +static void FPT_schkdd(ULONG port, unsigned char p_card); +static unsigned char FPT_RdStack(ULONG port, unsigned char index); +static void FPT_WrStack(ULONG portBase, unsigned char index, unsigned char data); +static unsigned char FPT_ChkIfChipInitialized(ULONG ioPort); + +static void FPT_SendMsg(ULONG port, unsigned char message); +static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg, + unsigned char error_code); + +static void FPT_sinits(PSCCB p_sccb, unsigned char p_card); static void FPT_RNVRamData(PNVRamInfo pNvRamInfo); -static UCHAR FPT_siwidn(ULONG port, UCHAR p_card); -static void FPT_stwidn(ULONG port, UCHAR p_card); -static void FPT_siwidr(ULONG port, UCHAR width); +static unsigned char FPT_siwidn(ULONG port, unsigned char p_card); +static void FPT_stwidn(ULONG port, unsigned char p_card); +static void FPT_siwidr(ULONG port, unsigned char width); -static void FPT_queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card); -static void FPT_queueDisconnect(PSCCB p_SCCB, UCHAR p_card); +static void FPT_queueSelectFail(PSCCBcard pCurrCard, unsigned char p_card); +static void FPT_queueDisconnect(PSCCB p_SCCB, unsigned char p_card); static void FPT_queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_SCCB, - UCHAR p_card); -static void FPT_queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card); -static void FPT_queueFlushSccb(UCHAR p_card, UCHAR error_code); -static void FPT_queueAddSccb(PSCCB p_SCCB, UCHAR card); -static UCHAR FPT_queueFindSccb(PSCCB p_SCCB, UCHAR p_card); + unsigned char p_card); +static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card); +static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code); +static void FPT_queueAddSccb(PSCCB p_SCCB, unsigned char card); +static unsigned char FPT_queueFindSccb(PSCCB p_SCCB, unsigned char p_card); static void FPT_utilUpdateResidual(PSCCB p_SCCB); -static USHORT FPT_CalcCrc16(UCHAR buffer[]); -static UCHAR FPT_CalcLrc(UCHAR buffer[]); +static USHORT FPT_CalcCrc16(unsigned char buffer[]); +static unsigned char FPT_CalcLrc(unsigned char buffer[]); static void FPT_Wait1Second(ULONG p_port); -static void FPT_Wait(ULONG p_port, UCHAR p_delay); -static void FPT_utilEEWriteOnOff(ULONG p_port,UCHAR p_mode); +static void FPT_Wait(ULONG p_port, unsigned char p_delay); +static void FPT_utilEEWriteOnOff(ULONG p_port,unsigned char p_mode); static void FPT_utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr); static USHORT FPT_utilEERead(ULONG p_port, USHORT ee_addr); static USHORT FPT_utilEEReadOrg(ULONG p_port, USHORT ee_addr); -static void FPT_utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr); +static void FPT_utilEESendCmdAddr(ULONG p_port, unsigned char ee_cmd, USHORT ee_addr); -static void FPT_phaseDataOut(ULONG port, UCHAR p_card); -static void FPT_phaseDataIn(ULONG port, UCHAR p_card); -static void FPT_phaseCommand(ULONG port, UCHAR p_card); -static void FPT_phaseStatus(ULONG port, UCHAR p_card); -static void FPT_phaseMsgOut(ULONG port, UCHAR p_card); -static void FPT_phaseMsgIn(ULONG port, UCHAR p_card); -static void FPT_phaseIllegal(ULONG port, UCHAR p_card); +static void FPT_phaseDataOut(ULONG port, unsigned char p_card); +static void FPT_phaseDataIn(ULONG port, unsigned char p_card); +static void FPT_phaseCommand(ULONG port, unsigned char p_card); +static void FPT_phaseStatus(ULONG port, unsigned char p_card); +static void FPT_phaseMsgOut(ULONG port, unsigned char p_card); +static void FPT_phaseMsgIn(ULONG port, unsigned char p_card); +static void FPT_phaseIllegal(ULONG port, unsigned char p_card); -static void FPT_phaseDecode(ULONG port, UCHAR p_card); -static void FPT_phaseChkFifo(ULONG port, UCHAR p_card); -static void FPT_phaseBusFree(ULONG p_port, UCHAR p_card); +static void FPT_phaseDecode(ULONG port, unsigned char p_card); +static void FPT_phaseChkFifo(ULONG port, unsigned char p_card); +static void FPT_phaseBusFree(ULONG p_port, unsigned char p_card); -static void FPT_XbowInit(ULONG port, UCHAR scamFlg); +static void FPT_XbowInit(ULONG port, unsigned char scamFlg); static void FPT_BusMasterInit(ULONG p_port); static void FPT_DiagEEPROM(ULONG p_port); @@ -1056,39 +1055,39 @@ static void FPT_DiagEEPROM(ULONG p_port); static void FPT_dataXferProcessor(ULONG port, PSCCBcard pCurrCard); static void FPT_busMstrSGDataXferStart(ULONG port, PSCCB pCurrSCCB); static void FPT_busMstrDataXferStart(ULONG port, PSCCB pCurrSCCB); -static void FPT_hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB); +static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrSCCB); static void FPT_hostDataXferRestart(PSCCB currSCCB); -static UCHAR FPT_SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, +static unsigned char FPT_SccbMgr_bad_isr(ULONG p_port, unsigned char p_card, PSCCBcard pCurrCard, USHORT p_int); static void FPT_SccbMgrTableInitAll(void); -static void FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card); -static void FPT_SccbMgrTableInitTarget(UCHAR p_card, UCHAR target); +static void FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, unsigned char p_card); +static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char target); -static void FPT_scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up); +static void FPT_scini(unsigned char p_card, unsigned char p_our_id, unsigned char p_power_up); -static int FPT_scarb(ULONG p_port, UCHAR p_sel_type); +static int FPT_scarb(ULONG p_port, unsigned char p_sel_type); static void FPT_scbusf(ULONG p_port); static void FPT_scsel(ULONG p_port); -static void FPT_scasid(UCHAR p_card, ULONG p_port); -static UCHAR FPT_scxferc(ULONG p_port, UCHAR p_data); -static UCHAR FPT_scsendi(ULONG p_port, UCHAR p_id_string[]); -static UCHAR FPT_sciso(ULONG p_port, UCHAR p_id_string[]); -static void FPT_scwirod(ULONG p_port, UCHAR p_data_bit); -static void FPT_scwiros(ULONG p_port, UCHAR p_data_bit); -static UCHAR FPT_scvalq(UCHAR p_quintet); -static UCHAR FPT_scsell(ULONG p_port, UCHAR targ_id); +static void FPT_scasid(unsigned char p_card, ULONG p_port); +static unsigned char FPT_scxferc(ULONG p_port, unsigned char p_data); +static unsigned char FPT_scsendi(ULONG p_port, unsigned char p_id_string[]); +static unsigned char FPT_sciso(ULONG p_port, unsigned char p_id_string[]); +static void FPT_scwirod(ULONG p_port, unsigned char p_data_bit); +static void FPT_scwiros(ULONG p_port, unsigned char p_data_bit); +static unsigned char FPT_scvalq(unsigned char p_quintet); +static unsigned char FPT_scsell(ULONG p_port, unsigned char targ_id); static void FPT_scwtsel(ULONG p_port); -static void FPT_inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id); -static void FPT_scsavdi(UCHAR p_card, ULONG p_port); -static UCHAR FPT_scmachid(UCHAR p_card, UCHAR p_id_string[]); +static void FPT_inisci(unsigned char p_card, ULONG p_port, unsigned char p_our_id); +static void FPT_scsavdi(unsigned char p_card, ULONG p_port); +static unsigned char FPT_scmachid(unsigned char p_card, unsigned char p_id_string[]); -static void FPT_autoCmdCmplt(ULONG p_port, UCHAR p_card); +static void FPT_autoCmdCmplt(ULONG p_port, unsigned char p_card); static void FPT_autoLoadDefaultMap(ULONG p_port); @@ -1100,8 +1099,8 @@ static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { { { 0 } } }; static NVRAMINFO FPT_nvRamInfo[MAX_MB_CARDS] = { { 0 } }; -static UCHAR FPT_mbCards = 0; -static UCHAR FPT_scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', \ +static unsigned char FPT_mbCards = 0; +static unsigned char FPT_scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', \ ' ', 'B', 'T', '-', '9', '3', '0', \ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; @@ -1109,7 +1108,7 @@ static UCHAR FPT_scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I' static USHORT FPT_default_intena = 0; -static void (*FPT_s_PhaseTbl[8]) (ULONG, UCHAR)= { 0 }; +static void (*FPT_s_PhaseTbl[8]) (ULONG, unsigned char)= { 0 }; /*--------------------------------------------------------------------- @@ -1122,9 +1121,9 @@ static void (*FPT_s_PhaseTbl[8]) (ULONG, UCHAR)= { 0 }; static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) { - static UCHAR first_time = 1; + static unsigned char first_time = 1; - UCHAR i,j,id,ScamFlg; + unsigned char i,j,id,ScamFlg; USHORT temp,temp2,temp3,temp4,temp5,temp6; ULONG ioport; PNVRamInfo pCurrNvRam; @@ -1190,8 +1189,8 @@ static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) if(pCurrNvRam) pCardInfo->si_id = pCurrNvRam->niAdapId; else - pCardInfo->si_id = (UCHAR)(FPT_utilEERead(ioport, (ADAPTER_SCSI_ID/2)) & - (UCHAR)0x0FF); + pCardInfo->si_id = (unsigned char)(FPT_utilEERead(ioport, (ADAPTER_SCSI_ID/2)) & + (unsigned char)0x0FF); pCardInfo->si_lun = 0x00; pCardInfo->si_fw_revision = ORION_FW_REV; @@ -1247,12 +1246,12 @@ static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) if(pCurrNvRam) i = pCurrNvRam->niSysConf; else - i = (UCHAR)(FPT_utilEERead(ioport, (SYSTEM_CONFIG/2))); + i = (unsigned char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG/2))); if(pCurrNvRam) ScamFlg = pCurrNvRam->niScamConf; else - ScamFlg = (UCHAR) FPT_utilEERead(ioport, SCAM_CONFIG/2); + ScamFlg = (unsigned char) FPT_utilEERead(ioport, SCAM_CONFIG/2); pCardInfo->si_flags = 0x0000; @@ -1312,11 +1311,11 @@ static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) } }else{ temp = FPT_utilEERead(ioport, (MODEL_NUMB_0/2)); - pCardInfo->si_card_model[0] = (UCHAR)(temp >> 8); + pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8); temp = FPT_utilEERead(ioport, (MODEL_NUMB_2/2)); - pCardInfo->si_card_model[1] = (UCHAR)(temp & 0x00FF); - pCardInfo->si_card_model[2] = (UCHAR)(temp >> 8); + pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF); + pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8); } if (pCardInfo->si_card_model[1] == '3') @@ -1371,7 +1370,7 @@ static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) logical card number sorted by BIOS (zero-based) */ pCardInfo->si_relative_cardnum = - (UCHAR)(RD_HARPOON(ioport+hp_aramBase+BIOS_RELATIVE_CARD)-1); + (unsigned char)(RD_HARPOON(ioport+hp_aramBase+BIOS_RELATIVE_CARD)-1); SGRAM_ACCESS(ioport); @@ -1402,7 +1401,7 @@ static ULONG FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) { PSCCBcard CurrCard = NULL; PNVRamInfo pCurrNvRam; - UCHAR i,j,thisCard, ScamFlg; + unsigned char i,j,thisCard, ScamFlg; USHORT temp,sync_bit_map,id; ULONG ioport; @@ -1446,7 +1445,7 @@ static ULONG FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) ScamFlg = pCurrNvRam->niScamConf; } else{ - ScamFlg = (UCHAR) FPT_utilEERead(ioport, SCAM_CONFIG/2); + ScamFlg = (unsigned char) FPT_utilEERead(ioport, SCAM_CONFIG/2); } @@ -1463,7 +1462,7 @@ static ULONG FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) WR_HARPOON(ioport+hp_arb_id, pCardInfo->si_id); CurrCard->ourId = pCardInfo->si_id; - i = (UCHAR) pCardInfo->si_flags; + i = (unsigned char) pCardInfo->si_flags; if (i & SCSI_PARITY_ENA) WR_HARPOON(ioport+hp_portctrl_1,(HOST_MODE8 | CHK_SCSI_P)); @@ -1543,13 +1542,13 @@ static ULONG FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) if (pCardInfo->si_per_targ_init_sync & sync_bit_map) { - FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue = (UCHAR)temp; + FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue = (unsigned char)temp; } else { FPT_sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED; FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue = - (UCHAR)(temp & ~EE_SYNC_MASK); + (unsigned char)(temp & ~EE_SYNC_MASK); } /* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) || @@ -1574,14 +1573,14 @@ static ULONG FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) } WR_HARPOON((ioport+hp_semaphore), - (UCHAR)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT)); + (unsigned char)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT)); return((ULONG)CurrCard); } static void FlashPoint_ReleaseHostAdapter(ULONG pCurrCard) { - UCHAR i; + unsigned char i; ULONG portBase; ULONG regOffset; ULONG scamData; @@ -1598,7 +1597,7 @@ static void FlashPoint_ReleaseHostAdapter(ULONG pCurrCard) FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId); for(i = 0; i < MAX_SCSI_TAR / 2; i++) - FPT_WrStack(pCurrNvRam->niBaseAddr, (UCHAR)(i+5), pCurrNvRam->niSyncTbl[i]); + FPT_WrStack(pCurrNvRam->niBaseAddr, (unsigned char)(i+5), pCurrNvRam->niSyncTbl[i]); portBase = pCurrNvRam->niBaseAddr; @@ -1617,7 +1616,7 @@ static void FlashPoint_ReleaseHostAdapter(ULONG pCurrCard) static void FPT_RNVRamData(PNVRamInfo pNvRamInfo) { - UCHAR i; + unsigned char i; ULONG portBase; ULONG regOffset; ULONG scamData; @@ -1630,7 +1629,7 @@ static void FPT_RNVRamData(PNVRamInfo pNvRamInfo) pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4); for(i = 0; i < MAX_SCSI_TAR / 2; i++) - pNvRamInfo->niSyncTbl[i] = FPT_RdStack(pNvRamInfo->niBaseAddr, (UCHAR)(i+5)); + pNvRamInfo->niSyncTbl[i] = FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i+5)); portBase = pNvRamInfo->niBaseAddr; @@ -1643,20 +1642,20 @@ static void FPT_RNVRamData(PNVRamInfo pNvRamInfo) } -static UCHAR FPT_RdStack(ULONG portBase, UCHAR index) +static unsigned char FPT_RdStack(ULONG portBase, unsigned char index) { WR_HARPOON(portBase + hp_stack_addr, index); return(RD_HARPOON(portBase + hp_stack_data)); } -static void FPT_WrStack(ULONG portBase, UCHAR index, UCHAR data) +static void FPT_WrStack(ULONG portBase, unsigned char index, unsigned char data) { WR_HARPOON(portBase + hp_stack_addr, index); WR_HARPOON(portBase + hp_stack_data, data); } -static UCHAR FPT_ChkIfChipInitialized(ULONG ioPort) +static unsigned char FPT_ChkIfChipInitialized(ULONG ioPort) { if((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4)) return(0); @@ -1681,7 +1680,7 @@ static UCHAR FPT_ChkIfChipInitialized(ULONG ioPort) static void FlashPoint_StartCCB(ULONG pCurrCard, PSCCB p_Sccb) { ULONG ioport; - UCHAR thisCard, lun; + unsigned char thisCard, lun; PSCCB pSaveSccb; CALL_BK_FN callback; @@ -1802,9 +1801,9 @@ static int FlashPoint_AbortCCB(ULONG pCurrCard, PSCCB p_Sccb) { ULONG ioport; - UCHAR thisCard; + unsigned char thisCard; CALL_BK_FN callback; - UCHAR TID; + unsigned char TID; PSCCB pSaveSCCB; PSCCBMgr_tar_info currTar_Info; @@ -1823,7 +1822,7 @@ static int FlashPoint_AbortCCB(ULONG pCurrCard, PSCCB p_Sccb) if (!((PSCCBcard)pCurrCard)->cmdCounter) WR_HARPOON(ioport+hp_semaphore,(RD_HARPOON(ioport+hp_semaphore) - & (UCHAR)(~(SCCB_MGR_ACTIVE | TICKLE_ME)) )); + & (unsigned char)(~(SCCB_MGR_ACTIVE | TICKLE_ME)) )); p_Sccb->SccbStatus = SCCB_ABORT; callback = p_Sccb->SccbCallback; @@ -1898,7 +1897,7 @@ static int FlashPoint_AbortCCB(ULONG pCurrCard, PSCCB p_Sccb) * interrupt for this card and disable the IRQ Pin if so. * *---------------------------------------------------------------------*/ -static UCHAR FlashPoint_InterruptPending(ULONG pCurrCard) +static unsigned char FlashPoint_InterruptPending(ULONG pCurrCard) { ULONG ioport; @@ -1928,9 +1927,9 @@ static UCHAR FlashPoint_InterruptPending(ULONG pCurrCard) static int FlashPoint_HandleInterrupt(ULONG pCurrCard) { PSCCB currSCCB; - UCHAR thisCard,result,bm_status, bm_int_st; + unsigned char thisCard,result,bm_status, bm_int_st; USHORT hp_int; - UCHAR i, target; + unsigned char i, target; ULONG ioport; thisCard = ((PSCCBcard)pCurrCard)->cardIndex; @@ -1939,7 +1938,7 @@ static int FlashPoint_HandleInterrupt(ULONG pCurrCard) MDISABLE_INT(ioport); if ((bm_int_st=RD_HARPOON(ioport+hp_int_status)) & EXT_STATUS_ON) - bm_status = RD_HARPOON(ioport+hp_ext_status) & (UCHAR)BAD_EXT_STATUS; + bm_status = RD_HARPOON(ioport+hp_ext_status) & (unsigned char)BAD_EXT_STATUS; else bm_status = 0; @@ -2080,7 +2079,7 @@ static int FlashPoint_HandleInterrupt(ULONG pCurrCard) else if ( (hp_int & IUNKWN) || (hp_int & PROG_HLT) ) { WRW_HARPOON((ioport+hp_intstat), (PHASE | IUNKWN | PROG_HLT)); - if ((RD_HARPOON(ioport+hp_prgmcnt_0) & (UCHAR)0x3f)< (UCHAR)SELCHK) + if ((RD_HARPOON(ioport+hp_prgmcnt_0) & (unsigned char)0x3f)< (unsigned char)SELCHK) { FPT_phaseDecode(ioport,thisCard); } @@ -2093,11 +2092,11 @@ static int FlashPoint_HandleInterrupt(ULONG pCurrCard) reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we need to read this reg first then restore it later. After update to 0x53 */ - i = (UCHAR)(RD_HARPOON(ioport+hp_fifowrite)); - target = (UCHAR)(RD_HARPOON(ioport+hp_gp_reg_3)); - WR_HARPOON(ioport+hp_xfer_pad, (UCHAR) ID_UNLOCK); - WR_HARPOON(ioport+hp_select_id, (UCHAR)(target | target<<4)); - WR_HARPOON(ioport+hp_xfer_pad, (UCHAR) 0x00); + i = (unsigned char)(RD_HARPOON(ioport+hp_fifowrite)); + target = (unsigned char)(RD_HARPOON(ioport+hp_gp_reg_3)); + WR_HARPOON(ioport+hp_xfer_pad, (unsigned char) ID_UNLOCK); + WR_HARPOON(ioport+hp_select_id, (unsigned char)(target | target<<4)); + WR_HARPOON(ioport+hp_xfer_pad, (unsigned char) 0x00); WR_HARPOON(ioport+hp_fifowrite, i); WR_HARPOON(ioport+hp_autostart_3, (AUTO_IMMED+TAG_STRT)); } @@ -2170,10 +2169,10 @@ static int FlashPoint_HandleInterrupt(ULONG pCurrCard) * processing time. * *---------------------------------------------------------------------*/ -static UCHAR FPT_SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, +static unsigned char FPT_SccbMgr_bad_isr(ULONG p_port, unsigned char p_card, PSCCBcard pCurrCard, USHORT p_int) { - UCHAR temp, ScamFlg; + unsigned char temp, ScamFlg; PSCCBMgr_tar_info currTar_Info; PNVRamInfo pCurrNvRam; @@ -2206,9 +2205,9 @@ static UCHAR FPT_SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, FPT_sxfrp(p_port,p_card); - temp = (UCHAR)(RD_HARPOON(p_port+hp_ee_ctrl) & + temp = (unsigned char)(RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H)); - WR_HARPOON(p_port+hp_ee_ctrl, ((UCHAR)temp | SEE_MS | SEE_CS)); + WR_HARPOON(p_port+hp_ee_ctrl, ((unsigned char)temp | SEE_MS | SEE_CS)); WR_HARPOON(p_port+hp_ee_ctrl, temp); if (!(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET))) @@ -2243,7 +2242,7 @@ static UCHAR FPT_SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, ScamFlg = pCurrNvRam->niScamConf; } else{ - ScamFlg = (UCHAR) FPT_utilEERead(p_port, SCAM_CONFIG/2); + ScamFlg = (unsigned char) FPT_utilEERead(p_port, SCAM_CONFIG/2); } FPT_XbowInit(p_port, ScamFlg); @@ -2324,7 +2323,7 @@ static UCHAR FPT_SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, static void FPT_SccbMgrTableInitAll() { - UCHAR thisCard; + unsigned char thisCard; for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) { @@ -2347,9 +2346,9 @@ static void FPT_SccbMgrTableInitAll() * *---------------------------------------------------------------------*/ -static void FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card) +static void FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, unsigned char p_card) { - UCHAR scsiID, qtag; + unsigned char scsiID, qtag; for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) { @@ -2382,10 +2381,10 @@ static void FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_SccbMgrTableInitTarget(UCHAR p_card, UCHAR target) +static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char target) { - UCHAR lun, qtag; + unsigned char lun, qtag; PSCCBMgr_tar_info currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][target]; @@ -2428,9 +2427,9 @@ static void FPT_SccbMgrTableInitTarget(UCHAR p_card, UCHAR target) * *---------------------------------------------------------------------*/ -static UCHAR FPT_sfm(ULONG port, PSCCB pCurrSCCB) +static unsigned char FPT_sfm(ULONG port, PSCCB pCurrSCCB) { - UCHAR message; + unsigned char message; USHORT TimeOutLoop; TimeOutLoop = 0; @@ -2501,16 +2500,16 @@ static UCHAR FPT_sfm(ULONG port, PSCCB pCurrSCCB) * *---------------------------------------------------------------------*/ -static void FPT_ssel(ULONG port, UCHAR p_card) +static void FPT_ssel(ULONG port, unsigned char p_card) { - UCHAR auto_loaded, i, target, *theCCB; + unsigned char auto_loaded, i, target, *theCCB; ULONG cdb_reg; PSCCBcard CurrCard; PSCCB currSCCB; PSCCBMgr_tar_info currTar_Info; - UCHAR lastTag, lun; + unsigned char lastTag, lun; CurrCard = &FPT_BL_Card[p_card]; currSCCB = CurrCard->currentSCCB; @@ -2656,8 +2655,8 @@ static void FPT_ssel(ULONG port, UCHAR p_card) WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+ - (((UCHAR)(currSCCB->ControlByte & TAG_TYPE_MASK) - >> 6) | (UCHAR)0x20))); + (((unsigned char)(currSCCB->ControlByte & TAG_TYPE_MASK) + >> 6) | (unsigned char)0x20))); WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+currSCCB->Sccb_tag)); WRW_HARPOON((port+SYNC_MSGS+4), (BRH_OP+ALWAYS+NP )); @@ -2713,8 +2712,8 @@ static void FPT_ssel(ULONG port, UCHAR p_card) WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg)); WRW_HARPOON((port+ID_MSG_STRT+2), (MPM_OP+AMSG_OUT+ - (((UCHAR)(currSCCB->ControlByte & TAG_TYPE_MASK) - >> 6) | (UCHAR)0x20))); + (((unsigned char)(currSCCB->ControlByte & TAG_TYPE_MASK) + >> 6) | (unsigned char)0x20))); for (i = 1; i < QUEUE_DEPTH; i++) { @@ -2760,7 +2759,7 @@ static void FPT_ssel(ULONG port, UCHAR p_card) } - theCCB = (UCHAR *)&currSCCB->Cdb[0]; + theCCB = (unsigned char *)&currSCCB->Cdb[0]; cdb_reg = port + CMD_STRT; @@ -2791,7 +2790,7 @@ static void FPT_ssel(ULONG port, UCHAR p_card) else { -/* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (UCHAR)0x1F); +/* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F); auto_loaded |= AUTO_IMMED; */ auto_loaded = AUTO_IMMED; @@ -2812,10 +2811,10 @@ static void FPT_ssel(ULONG port, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard) +static void FPT_sres(ULONG port, unsigned char p_card, PSCCBcard pCurrCard) { - UCHAR our_target, message, lun = 0, tag, msgRetryCount; + unsigned char our_target, message, lun = 0, tag, msgRetryCount; PSCCBMgr_tar_info currTar_Info; @@ -2881,7 +2880,7 @@ static void FPT_sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard) WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00); - our_target = (UCHAR)(RD_HARPOON(port+hp_select_id) >> 4); + our_target = (unsigned char)(RD_HARPOON(port+hp_select_id) >> 4); currTar_Info = &FPT_sccbMgrTbl[p_card][our_target]; @@ -2913,7 +2912,7 @@ static void FPT_sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard) if (message <= (0x80 | LUN_MASK)) { - lun = message & (UCHAR)LUN_MASK; + lun = message & (unsigned char)LUN_MASK; if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING) { @@ -3073,7 +3072,7 @@ static void FPT_sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard) (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ; } -static void FPT_SendMsg(ULONG port, UCHAR message) +static void FPT_SendMsg(ULONG port, unsigned char message) { while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) { @@ -3122,7 +3121,7 @@ static void FPT_SendMsg(ULONG port, UCHAR message) * target device. * *---------------------------------------------------------------------*/ -static void FPT_sdecm(UCHAR message, ULONG port, UCHAR p_card) +static void FPT_sdecm(unsigned char message, ULONG port, unsigned char p_card) { PSCCB currSCCB; PSCCBcard CurrCard; @@ -3152,8 +3151,8 @@ static void FPT_sdecm(UCHAR message, ULONG port, UCHAR p_card) if (currSCCB->Sccb_scsistat == SELECT_Q_ST) { - currTar_Info->TarStatus &= ~(UCHAR)TAR_TAG_Q_MASK; - currTar_Info->TarStatus |= (UCHAR)TAG_Q_REJECT; + currTar_Info->TarStatus &= ~(unsigned char)TAR_TAG_Q_MASK; + currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT; } ACCEPT_MSG(port); @@ -3190,7 +3189,7 @@ static void FPT_sdecm(UCHAR message, ULONG port, UCHAR p_card) if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) { - currTar_Info->TarStatus |= (UCHAR)SYNC_SUPPORTED; + currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED; currTar_Info->TarEEValue &= ~EE_SYNC_MASK; } @@ -3209,7 +3208,7 @@ static void FPT_sdecm(UCHAR message, ULONG port, UCHAR p_card) else if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING ) { currTar_Info->TarStatus = (currTar_Info->TarStatus & - ~(UCHAR)TAR_TAG_Q_MASK) | TAG_Q_REJECT; + ~(unsigned char)TAR_TAG_Q_MASK) | TAG_Q_REJECT; currSCCB->ControlByte &= ~F_USE_CMD_Q; @@ -3241,7 +3240,7 @@ static void FPT_sdecm(UCHAR message, ULONG port, UCHAR p_card) currTar_Info->TarLUNBusy[0] = 1; - currSCCB->ControlByte &= ~(UCHAR)F_USE_CMD_Q; + currSCCB->ControlByte &= ~(unsigned char)F_USE_CMD_Q; WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); @@ -3301,9 +3300,9 @@ static void FPT_sdecm(UCHAR message, ULONG port, UCHAR p_card) * Description: Decide what to do with the extended message. * *---------------------------------------------------------------------*/ -static void FPT_shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB) +static void FPT_shandem(ULONG port, unsigned char p_card, PSCCB pCurrSCCB) { - UCHAR length,message; + unsigned char length,message; length = FPT_sfm(port,pCurrSCCB); if (length) @@ -3380,7 +3379,7 @@ static void FPT_shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB) * *---------------------------------------------------------------------*/ -static UCHAR FPT_sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag) +static unsigned char FPT_sisyncn(ULONG port, unsigned char p_card, unsigned char syncFlag) { PSCCB currSCCB; PSCCBMgr_tar_info currTar_Info; @@ -3392,7 +3391,7 @@ static UCHAR FPT_sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag) WRW_HARPOON((port+ID_MSG_STRT), - (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV))); + (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV))); WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); @@ -3426,7 +3425,7 @@ static UCHAR FPT_sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag) { WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_TRYING); + ~(unsigned char)TAR_SYNC_MASK) | (unsigned char)SYNC_TRYING); } else { @@ -3439,7 +3438,7 @@ static UCHAR FPT_sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag) else { - currTar_Info->TarStatus |= (UCHAR)SYNC_SUPPORTED; + currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED; currTar_Info->TarEEValue &= ~EE_SYNC_MASK; return(0); } @@ -3455,9 +3454,9 @@ static UCHAR FPT_sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag) * necessary. * *---------------------------------------------------------------------*/ -static void FPT_stsyncn(ULONG port, UCHAR p_card) +static void FPT_stsyncn(ULONG port, unsigned char p_card) { - UCHAR sync_msg,offset,sync_reg,our_sync_msg; + unsigned char sync_msg,offset,sync_reg,our_sync_msg; PSCCB currSCCB; PSCCBMgr_tar_info currTar_Info; @@ -3562,7 +3561,7 @@ static void FPT_stsyncn(ULONG port, UCHAR p_card) ACCEPT_MSG(port); currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_SUPPORTED); + ~(unsigned char)TAR_SYNC_MASK) | (unsigned char)SYNC_SUPPORTED); WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); } @@ -3575,7 +3574,7 @@ static void FPT_stsyncn(ULONG port, UCHAR p_card) FPT_sisyncr(port,sync_msg,offset); currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_SUPPORTED); + ~(unsigned char)TAR_SYNC_MASK) | (unsigned char)SYNC_SUPPORTED); } } @@ -3587,7 +3586,7 @@ static void FPT_stsyncn(ULONG port, UCHAR p_card) * Description: Answer the targets sync message. * *---------------------------------------------------------------------*/ -static void FPT_sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset) +static void FPT_sisyncr(ULONG port,unsigned char sync_pulse, unsigned char offset) { ARAM_ACCESS(port); WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); @@ -3618,7 +3617,7 @@ static void FPT_sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset) * *---------------------------------------------------------------------*/ -static UCHAR FPT_siwidn(ULONG port, UCHAR p_card) +static unsigned char FPT_siwidn(ULONG port, unsigned char p_card) { PSCCB currSCCB; PSCCBMgr_tar_info currTar_Info; @@ -3630,7 +3629,7 @@ static UCHAR FPT_siwidn(ULONG port, UCHAR p_card) WRW_HARPOON((port+ID_MSG_STRT), - (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV))); + (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV))); WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); @@ -3645,7 +3644,7 @@ static UCHAR FPT_siwidn(ULONG port, UCHAR p_card) currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(UCHAR)TAR_WIDE_MASK) | (UCHAR)WIDE_ENABLED); + ~(unsigned char)TAR_WIDE_MASK) | (unsigned char)WIDE_ENABLED); return(1); } @@ -3653,7 +3652,7 @@ static UCHAR FPT_siwidn(ULONG port, UCHAR p_card) else { currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(UCHAR)TAR_WIDE_MASK) | WIDE_NEGOCIATED); + ~(unsigned char)TAR_WIDE_MASK) | WIDE_NEGOCIATED); currTar_Info->TarEEValue &= ~EE_WIDE_SCSI; return(0); @@ -3670,9 +3669,9 @@ static UCHAR FPT_siwidn(ULONG port, UCHAR p_card) * necessary. * *---------------------------------------------------------------------*/ -static void FPT_stwidn(ULONG port, UCHAR p_card) +static void FPT_stwidn(ULONG port, unsigned char p_card) { - UCHAR width; + unsigned char width; PSCCB currSCCB; PSCCBMgr_tar_info currTar_Info; @@ -3750,7 +3749,7 @@ static void FPT_stwidn(ULONG port, UCHAR p_card) * Description: Answer the targets Wide nego message. * *---------------------------------------------------------------------*/ -static void FPT_siwidr(ULONG port, UCHAR width) +static void FPT_siwidr(ULONG port, unsigned char width) { ARAM_ACCESS(port); WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); @@ -3779,10 +3778,10 @@ static void FPT_siwidr(ULONG port, UCHAR width) * ID specified. * *---------------------------------------------------------------------*/ -static void FPT_sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value, +static void FPT_sssyncv(ULONG p_port, unsigned char p_id, unsigned char p_sync_value, PSCCBMgr_tar_info currTar_Info) { - UCHAR index; + unsigned char index; index = p_id; @@ -3851,9 +3850,9 @@ static void FPT_sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value, * Description: Reset the desired card's SCSI bus. * *---------------------------------------------------------------------*/ -static void FPT_sresb(ULONG port, UCHAR p_card) +static void FPT_sresb(ULONG port, unsigned char p_card) { - UCHAR scsiID, i; + unsigned char scsiID, i; PSCCBMgr_tar_info currTar_Info; @@ -3926,7 +3925,7 @@ static void FPT_sresb(ULONG port, UCHAR p_card) *---------------------------------------------------------------------*/ static void FPT_ssenss(PSCCBcard pCurrCard) { - UCHAR i; + unsigned char i; PSCCB currSCCB; currSCCB = pCurrCard->currentSCCB; @@ -3941,7 +3940,7 @@ static void FPT_ssenss(PSCCBcard pCurrCard) currSCCB->CdbLength = SIX_BYTE_CMD; currSCCB->Cdb[0] = SCSI_REQUEST_SENSE; - currSCCB->Cdb[1] = currSCCB->Cdb[1] & (UCHAR)0xE0; /*Keep LUN. */ + currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */ currSCCB->Cdb[2] = 0x00; currSCCB->Cdb[3] = 0x00; currSCCB->Cdb[4] = currSCCB->RequestSenseLength; @@ -3955,7 +3954,7 @@ static void FPT_ssenss(PSCCBcard pCurrCard) currSCCB->Sccb_XferState &= ~F_SG_XFER; - currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV; + currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV; currSCCB->ControlByte = 0x00; @@ -3973,9 +3972,9 @@ static void FPT_ssenss(PSCCBcard pCurrCard) * *---------------------------------------------------------------------*/ -static void FPT_sxfrp(ULONG p_port, UCHAR p_card) +static void FPT_sxfrp(ULONG p_port, unsigned char p_card) { - UCHAR curr_phz; + unsigned char curr_phz; DISABLE_AUTO(p_port); @@ -3994,7 +3993,7 @@ static void FPT_sxfrp(ULONG p_port, UCHAR p_card) WR_HARPOON(p_port+hp_xfercnt_0, 0x00); - curr_phz = RD_HARPOON(p_port+hp_scsisig) & (UCHAR)S_SCSI_PHZ; + curr_phz = RD_HARPOON(p_port+hp_scsisig) & (unsigned char)S_SCSI_PHZ; WRW_HARPOON((p_port+hp_intstat), XFER_CNT_0); @@ -4002,9 +4001,9 @@ static void FPT_sxfrp(ULONG p_port, UCHAR p_card) WR_HARPOON(p_port+hp_scsisig, curr_phz); while ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET)) && - (curr_phz == (RD_HARPOON(p_port+hp_scsisig) & (UCHAR)S_SCSI_PHZ)) ) + (curr_phz == (RD_HARPOON(p_port+hp_scsisig) & (unsigned char)S_SCSI_PHZ)) ) { - if (curr_phz & (UCHAR)SCSI_IOBIT) + if (curr_phz & (unsigned char)SCSI_IOBIT) { WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | SCSI_INBIT)); @@ -4055,10 +4054,10 @@ static void FPT_sxfrp(ULONG p_port, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_schkdd(ULONG port, UCHAR p_card) +static void FPT_schkdd(ULONG port, unsigned char p_card) { USHORT TimeOutLoop; - UCHAR sPhase; + unsigned char sPhase; PSCCB currSCCB; @@ -4112,7 +4111,7 @@ static void FPT_schkdd(ULONG port, UCHAR p_card) if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) { return; } - if (RD_HARPOON(port+hp_offsetctr) & (UCHAR)0x1F) { + if (RD_HARPOON(port+hp_offsetctr) & (unsigned char)0x1F) { break; } if (RDW_HARPOON((port+hp_intstat)) & RESET) { @@ -4124,7 +4123,7 @@ static void FPT_schkdd(ULONG port, UCHAR p_card) sPhase = RD_HARPOON(port+hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ); if ((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) || - (RD_HARPOON(port+hp_offsetctr) & (UCHAR)0x1F) || + (RD_HARPOON(port+hp_offsetctr) & (unsigned char)0x1F) || (sPhase == (SCSI_BSY | S_DATAO_PH)) || (sPhase == (SCSI_BSY | S_DATAI_PH))) { @@ -4168,7 +4167,7 @@ static void FPT_schkdd(ULONG port, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_sinits(PSCCB p_sccb, UCHAR p_card) +static void FPT_sinits(PSCCB p_sccb, unsigned char p_card) { PSCCBMgr_tar_info currTar_Info; @@ -4213,12 +4212,12 @@ static void FPT_sinits(PSCCB p_sccb, UCHAR p_card) */ if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) || (currTar_Info->TarStatus & TAG_Q_TRYING)) { - p_sccb->Sccb_idmsg = (UCHAR)(SMIDENT | DISC_PRIV) | p_sccb->Lun; + p_sccb->Sccb_idmsg = (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun; } else { - p_sccb->Sccb_idmsg = (UCHAR)SMIDENT | p_sccb->Lun; + p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun; } p_sccb->HostStatus = 0x00; @@ -4248,15 +4247,15 @@ static void FPT_sinits(PSCCB p_sccb, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseDecode(ULONG p_port, UCHAR p_card) +static void FPT_phaseDecode(ULONG p_port, unsigned char p_card) { unsigned char phase_ref; - void (*phase) (ULONG, UCHAR); + void (*phase) (ULONG, unsigned char); DISABLE_AUTO(p_port); - phase_ref = (UCHAR) (RD_HARPOON(p_port+hp_scsisig) & S_SCSI_PHZ); + phase_ref = (unsigned char) (RD_HARPOON(p_port+hp_scsisig) & S_SCSI_PHZ); phase = FPT_s_PhaseTbl[phase_ref]; @@ -4273,7 +4272,7 @@ static void FPT_phaseDecode(ULONG p_port, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseDataOut(ULONG port, UCHAR p_card) +static void FPT_phaseDataOut(ULONG port, unsigned char p_card) { PSCCB currSCCB; @@ -4317,7 +4316,7 @@ static void FPT_phaseDataOut(ULONG port, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseDataIn(ULONG port, UCHAR p_card) +static void FPT_phaseDataIn(ULONG port, unsigned char p_card) { PSCCB currSCCB; @@ -4364,11 +4363,11 @@ static void FPT_phaseDataIn(ULONG port, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseCommand(ULONG p_port, UCHAR p_card) +static void FPT_phaseCommand(ULONG p_port, unsigned char p_card) { PSCCB currSCCB; ULONG cdb_reg; - UCHAR i; + unsigned char i; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4416,7 +4415,7 @@ static void FPT_phaseCommand(ULONG p_port, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseStatus(ULONG port, UCHAR p_card) +static void FPT_phaseStatus(ULONG port, unsigned char p_card) { /* Start-up the automation to finish off this command and let the isr handle the interrupt for command complete when it comes in. @@ -4438,9 +4437,9 @@ static void FPT_phaseStatus(ULONG port, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseMsgOut(ULONG port, UCHAR p_card) +static void FPT_phaseMsgOut(ULONG port, unsigned char p_card) { - UCHAR message,scsiID; + unsigned char message,scsiID; PSCCB currSCCB; PSCCBMgr_tar_info currTar_Info; @@ -4586,9 +4585,9 @@ static void FPT_phaseMsgOut(ULONG port, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseMsgIn(ULONG port, UCHAR p_card) +static void FPT_phaseMsgIn(ULONG port, unsigned char p_card) { - UCHAR message; + unsigned char message; PSCCB currSCCB; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4639,7 +4638,7 @@ static void FPT_phaseMsgIn(ULONG port, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseIllegal(ULONG port, UCHAR p_card) +static void FPT_phaseIllegal(ULONG port, unsigned char p_card) { PSCCB currSCCB; @@ -4667,7 +4666,7 @@ static void FPT_phaseIllegal(ULONG port, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseChkFifo(ULONG port, UCHAR p_card) +static void FPT_phaseChkFifo(ULONG port, unsigned char p_card) { ULONG xfercnt; PSCCB currSCCB; @@ -4745,7 +4744,7 @@ static void FPT_phaseChkFifo(ULONG port, UCHAR p_card) * because of command complete or from a disconnect. * *---------------------------------------------------------------------*/ -static void FPT_phaseBusFree(ULONG port, UCHAR p_card) +static void FPT_phaseBusFree(ULONG port, unsigned char p_card) { PSCCB currSCCB; @@ -4775,7 +4774,7 @@ static void FPT_phaseBusFree(ULONG port, UCHAR p_card) else if(currSCCB->Sccb_scsistat == SELECT_SN_ST) { FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= - (UCHAR)SYNC_SUPPORTED; + (unsigned char)SYNC_SUPPORTED; FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK; } @@ -4951,10 +4950,10 @@ static void FPT_autoLoadDefaultMap(ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_autoCmdCmplt(ULONG p_port, UCHAR p_card) +static void FPT_autoCmdCmplt(ULONG p_port, unsigned char p_card) { PSCCB currSCCB; - UCHAR status_byte; + unsigned char status_byte; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -5001,7 +5000,7 @@ static void FPT_autoCmdCmplt(ULONG p_port, UCHAR p_card) if(currSCCB->Sccb_scsistat == SELECT_SN_ST) { FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= - (UCHAR)SYNC_SUPPORTED; + (unsigned char)SYNC_SUPPORTED; FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK; FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; @@ -5177,7 +5176,7 @@ static void FPT_dataXferProcessor(ULONG port, PSCCBcard pCurrCard) if (pCurrCard->globalFlags & F_HOST_XFER_ACT) { - currSCCB->Sccb_sgseg += (UCHAR)SG_BUF_CNT; + currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT; currSCCB->Sccb_SGoffset = 0x00; } pCurrCard->globalFlags |= F_HOST_XFER_ACT; @@ -5208,7 +5207,7 @@ static void FPT_busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB) { ULONG count,addr,tmpSGCnt; UINT sg_index; - UCHAR sg_count, i; + unsigned char sg_count, i; ULONG reg_offset; @@ -5227,12 +5226,12 @@ static void FPT_busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB) reg_offset = hp_aramBase; - i = (UCHAR) (RD_HARPOON(p_port+hp_page_ctrl) & ~(SGRAM_ARAM|SCATTER_EN)); + i = (unsigned char) (RD_HARPOON(p_port+hp_page_ctrl) & ~(SGRAM_ARAM|SCATTER_EN)); WR_HARPOON(p_port+hp_page_ctrl, i); - while ((sg_count < (UCHAR)SG_BUF_CNT) && + while ((sg_count < (unsigned char)SG_BUF_CNT) && ((ULONG)(sg_index * (UINT)SG_ELEMENT_SIZE) < pcurrSCCB->DataLength) ) { tmpSGCnt += *(((ULONG *)pcurrSCCB->DataPointer)+ @@ -5297,7 +5296,7 @@ static void FPT_busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB) } - WR_HARPOON(p_port+hp_page_ctrl, (UCHAR) (i | SCATTER_EN)); + WR_HARPOON(p_port+hp_page_ctrl, (unsigned char) (i | SCATTER_EN)); } @@ -5362,7 +5361,7 @@ static void FPT_busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB) * command busy is also time out, it'll just give up. * *---------------------------------------------------------------------*/ -static UCHAR FPT_busMstrTimeOut(ULONG p_port) +static unsigned char FPT_busMstrTimeOut(ULONG p_port) { ULONG timeout; @@ -5400,7 +5399,7 @@ static UCHAR FPT_busMstrTimeOut(ULONG p_port) * Description: Abort any in progress transfer. * *---------------------------------------------------------------------*/ -static void FPT_hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB) +static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrSCCB) { ULONG timeout; @@ -5707,13 +5706,13 @@ static void FPT_hostDataXferRestart(PSCCB currSCCB) * *---------------------------------------------------------------------*/ -static void FPT_scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up) +static void FPT_scini(unsigned char p_card, unsigned char p_our_id, unsigned char p_power_up) { - UCHAR loser,assigned_id; + unsigned char loser,assigned_id; ULONG p_port; - UCHAR i,k,ScamFlg ; + unsigned char i,k,ScamFlg ; PSCCBcard currCard; PNVRamInfo pCurrNvRam; @@ -5727,8 +5726,8 @@ static void FPT_scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up) i = pCurrNvRam->niSysConf; } else{ - ScamFlg = (UCHAR) FPT_utilEERead(p_port, SCAM_CONFIG/2); - i = (UCHAR)(FPT_utilEERead(p_port, (SYSTEM_CONFIG/2))); + ScamFlg = (unsigned char) FPT_utilEERead(p_port, SCAM_CONFIG/2); + i = (unsigned char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG/2))); } if(!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */ return; @@ -5846,7 +5845,7 @@ static void FPT_scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up) if (FPT_scvalq(k)) { currCard->ourId = - ((UCHAR)(i<<3)+(k & (UCHAR)7)) & (UCHAR) 0x3F; + ((unsigned char)(i<<3)+(k & (unsigned char)7)) & (unsigned char) 0x3F; FPT_inisci(p_card, p_port, p_our_id); FPT_scamInfo[currCard->ourId].state = ID_ASSIGNED; FPT_scamInfo[currCard->ourId].id_string[0] @@ -5903,7 +5902,7 @@ static void FPT_scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up) * *---------------------------------------------------------------------*/ -static int FPT_scarb(ULONG p_port, UCHAR p_sel_type) +static int FPT_scarb(ULONG p_port, unsigned char p_sel_type) { if (p_sel_type == INIT_SELTD) { @@ -6000,12 +5999,12 @@ static void FPT_scbusf(ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_scasid(UCHAR p_card, ULONG p_port) +static void FPT_scasid(unsigned char p_card, ULONG p_port) { - UCHAR temp_id_string[ID_STRING_LENGTH]; + unsigned char temp_id_string[ID_STRING_LENGTH]; - UCHAR i,k,scam_id; - UCHAR crcBytes[3]; + unsigned char i,k,scam_id; + unsigned char crcBytes[3]; PNVRamInfo pCurrNvRam; ushort_ptr pCrcBytes; @@ -6018,7 +6017,7 @@ static void FPT_scasid(UCHAR p_card, ULONG p_port) for (k=0; k < ID_STRING_LENGTH; k++) { - temp_id_string[k] = (UCHAR) 0x00; + temp_id_string[k] = (unsigned char) 0x00; } FPT_scxferc(p_port,SYNC_PTRN); @@ -6034,7 +6033,7 @@ static void FPT_scasid(UCHAR p_card, ULONG p_port) temp_id_string[2] = crcBytes[0]; temp_id_string[3] = crcBytes[1]; for(k = 4; k < ID_STRING_LENGTH; k++) - temp_id_string[k] = (UCHAR) 0x00; + temp_id_string[k] = (unsigned char) 0x00; } i = FPT_scmachid(p_card,temp_id_string); @@ -6052,7 +6051,7 @@ static void FPT_scasid(UCHAR p_card, ULONG p_port) else FPT_scxferc(p_port,ID_8_F); - scam_id = (i & (UCHAR) 0x07); + scam_id = (i & (unsigned char) 0x07); for (k=1; k < 0x08; k <<= 1) @@ -6098,15 +6097,15 @@ static void FPT_scsel(ULONG p_port) WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); - WR_HARPOON(p_port+hp_scsidata_0, (UCHAR)(RD_HARPOON(p_port+hp_scsidata_0) | - (UCHAR)(BIT(7)+BIT(6)))); + WR_HARPOON(p_port+hp_scsidata_0, (unsigned char)(RD_HARPOON(p_port+hp_scsidata_0) | + (unsigned char)(BIT(7)+BIT(6)))); WR_HARPOON(p_port+hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD)); FPT_scwiros(p_port, SCSI_SEL); - WR_HARPOON(p_port+hp_scsidata_0, (UCHAR)(RD_HARPOON(p_port+hp_scsidata_0) & - ~(UCHAR)BIT(6))); + WR_HARPOON(p_port+hp_scsidata_0, (unsigned char)(RD_HARPOON(p_port+hp_scsidata_0) & + ~(unsigned char)BIT(6))); FPT_scwirod(p_port, BIT(6)); WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); @@ -6122,9 +6121,9 @@ static void FPT_scsel(ULONG p_port) * *---------------------------------------------------------------------*/ -static UCHAR FPT_scxferc(ULONG p_port, UCHAR p_data) +static unsigned char FPT_scxferc(ULONG p_port, unsigned char p_data) { - UCHAR curr_data, ret_data; + unsigned char curr_data, ret_data; curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */ @@ -6137,7 +6136,7 @@ static UCHAR FPT_scxferc(ULONG p_port, UCHAR p_data) FPT_scwirod(p_port,BIT(7)); /*Wait for DB7 to be released. */ while (!(RD_HARPOON(p_port+hp_scsidata_0) & BIT(5))); - ret_data = (RD_HARPOON(p_port+hp_scsidata_0) & (UCHAR) 0x1F); + ret_data = (RD_HARPOON(p_port+hp_scsidata_0) & (unsigned char) 0x1F); curr_data |= BIT(6); @@ -6173,9 +6172,9 @@ static UCHAR FPT_scxferc(ULONG p_port, UCHAR p_data) * *---------------------------------------------------------------------*/ -static UCHAR FPT_scsendi(ULONG p_port, UCHAR p_id_string[]) +static unsigned char FPT_scsendi(ULONG p_port, unsigned char p_id_string[]) { - UCHAR ret_data,byte_cnt,bit_cnt,defer; + unsigned char ret_data,byte_cnt,bit_cnt,defer; defer = 0; @@ -6226,9 +6225,9 @@ static UCHAR FPT_scsendi(ULONG p_port, UCHAR p_id_string[]) * *---------------------------------------------------------------------*/ -static UCHAR FPT_sciso(ULONG p_port, UCHAR p_id_string[]) +static unsigned char FPT_sciso(ULONG p_port, unsigned char p_id_string[]) { - UCHAR ret_data,the_data,byte_cnt,bit_cnt; + unsigned char ret_data,the_data,byte_cnt,bit_cnt; the_data = 0; @@ -6287,9 +6286,9 @@ static UCHAR FPT_sciso(ULONG p_port, UCHAR p_id_string[]) * *---------------------------------------------------------------------*/ -static void FPT_scwirod(ULONG p_port, UCHAR p_data_bit) +static void FPT_scwirod(ULONG p_port, unsigned char p_data_bit) { - UCHAR i; + unsigned char i; i = 0; while ( i < MAX_SCSI_TAR ) { @@ -6316,9 +6315,9 @@ static void FPT_scwirod(ULONG p_port, UCHAR p_data_bit) * *---------------------------------------------------------------------*/ -static void FPT_scwiros(ULONG p_port, UCHAR p_data_bit) +static void FPT_scwiros(ULONG p_port, unsigned char p_data_bit) { - UCHAR i; + unsigned char i; i = 0; while ( i < MAX_SCSI_TAR ) { @@ -6343,9 +6342,9 @@ static void FPT_scwiros(ULONG p_port, UCHAR p_data_bit) * *---------------------------------------------------------------------*/ -static UCHAR FPT_scvalq(UCHAR p_quintet) +static unsigned char FPT_scvalq(unsigned char p_quintet) { - UCHAR count; + unsigned char count; for (count=1; count < 0x08; count<<=1) { if (!(p_quintet & count)) @@ -6370,7 +6369,7 @@ static UCHAR FPT_scvalq(UCHAR p_quintet) * *---------------------------------------------------------------------*/ -static UCHAR FPT_scsell(ULONG p_port, UCHAR targ_id) +static unsigned char FPT_scsell(ULONG p_port, unsigned char targ_id) { ULONG i; @@ -6463,9 +6462,9 @@ static void FPT_scwtsel(ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id) +static void FPT_inisci(unsigned char p_card, ULONG p_port, unsigned char p_our_id) { - UCHAR i,k,max_id; + unsigned char i,k,max_id; USHORT ee_data; PNVRamInfo pCurrNvRam; @@ -6483,7 +6482,7 @@ static void FPT_inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id) for(k = 0; k < 4; k++) FPT_scamInfo[i].id_string[k] = pCurrNvRam->niScamTbl[i][k]; for(k = 4; k < ID_STRING_LENGTH; k++) - FPT_scamInfo[i].id_string[k] = (UCHAR) 0x00; + FPT_scamInfo[i].id_string[k] = (unsigned char) 0x00; if(FPT_scamInfo[i].id_string[0] == 0x00) FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */ @@ -6498,9 +6497,9 @@ static void FPT_inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id) { ee_data = FPT_utilEERead(p_port, (USHORT)((EE_SCAMBASE/2) + (USHORT) (i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2))); - FPT_scamInfo[i].id_string[k] = (UCHAR) ee_data; + FPT_scamInfo[i].id_string[k] = (unsigned char) ee_data; ee_data >>= 8; - FPT_scamInfo[i].id_string[k+1] = (UCHAR) ee_data; + FPT_scamInfo[i].id_string[k+1] = (unsigned char) ee_data; } if ((FPT_scamInfo[i].id_string[0] == 0x00) || @@ -6527,10 +6526,10 @@ static void FPT_inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id) * *---------------------------------------------------------------------*/ -static UCHAR FPT_scmachid(UCHAR p_card, UCHAR p_id_string[]) +static unsigned char FPT_scmachid(unsigned char p_card, unsigned char p_id_string[]) { - UCHAR i,k,match; + unsigned char i,k,match; for (i=0; i < MAX_SCSI_TAR; i++) { @@ -6559,7 +6558,7 @@ static UCHAR FPT_scmachid(UCHAR p_card, UCHAR p_id_string[]) i = MAX_SCSI_TAR; if (((p_id_string[0] & 0x06) == 0x02) || ((p_id_string[0] & 0x06) == 0x04)) - match = p_id_string[1] & (UCHAR) 0x1F; + match = p_id_string[1] & (unsigned char) 0x1F; else match = 7; @@ -6608,7 +6607,7 @@ static UCHAR FPT_scmachid(UCHAR p_card, UCHAR p_id_string[]) i = MAX_SCSI_TAR; if (((p_id_string[0] & 0x06) == 0x02) || ((p_id_string[0] & 0x06) == 0x04)) - match = p_id_string[1] & (UCHAR) 0x1F; + match = p_id_string[1] & (unsigned char) 0x1F; else match = 7; @@ -6656,9 +6655,9 @@ static UCHAR FPT_scmachid(UCHAR p_card, UCHAR p_id_string[]) * *---------------------------------------------------------------------*/ -static void FPT_scsavdi(UCHAR p_card, ULONG p_port) +static void FPT_scsavdi(unsigned char p_card, ULONG p_port) { - UCHAR i,k,max_id; + unsigned char i,k,max_id; USHORT ee_data,sum_data; @@ -6705,12 +6704,12 @@ static void FPT_scsavdi(UCHAR p_card, ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_XbowInit(ULONG port, UCHAR ScamFlg) +static void FPT_XbowInit(ULONG port, unsigned char ScamFlg) { -UCHAR i; +unsigned char i; i = RD_HARPOON(port+hp_page_ctrl); - WR_HARPOON(port+hp_page_ctrl, (UCHAR) (i | G_INT_DISABLE)); + WR_HARPOON(port+hp_page_ctrl, (unsigned char) (i | G_INT_DISABLE)); WR_HARPOON(port+hp_scsireset,0x00); WR_HARPOON(port+hp_portctrl_1,HOST_MODE8); @@ -6812,7 +6811,7 @@ static void FPT_DiagEEPROM(ULONG p_port) } - FPT_utilEEWriteOnOff(p_port,(UCHAR)1); + FPT_utilEEWriteOnOff(p_port,(unsigned char)1); for (index = 0; index < max_wd_cnt; index++) { @@ -6933,7 +6932,7 @@ static void FPT_DiagEEPROM(ULONG p_port) FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM/2); - FPT_utilEEWriteOnOff(p_port,(UCHAR)0); + FPT_utilEEWriteOnOff(p_port,(unsigned char)0); } @@ -6946,9 +6945,9 @@ static void FPT_DiagEEPROM(ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card) +static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card) { - UCHAR scan_ptr, lun; + unsigned char scan_ptr, lun; PSCCBMgr_tar_info currTar_Info; PSCCB pOldSccb; @@ -7077,14 +7076,14 @@ static void FPT_queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card) +static void FPT_queueSelectFail(PSCCBcard pCurrCard, unsigned char p_card) { - UCHAR thisTarg; + unsigned char thisTarg; PSCCBMgr_tar_info currTar_Info; if (pCurrCard->currentSCCB != NULL) { - thisTarg = (UCHAR)(((PSCCB)(pCurrCard->currentSCCB))->TargID); + thisTarg = (unsigned char)(((PSCCB)(pCurrCard->currentSCCB))->TargID); currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; pCurrCard->currentSCCB->Sccb_backlink = (PSCCB)NULL; @@ -7117,10 +7116,10 @@ static void FPT_queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card) *---------------------------------------------------------------------*/ static void FPT_queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, - UCHAR p_card) + unsigned char p_card) { - UCHAR i, SCSIcmd; + unsigned char i, SCSIcmd; CALL_BK_FN callback; PSCCBMgr_tar_info currTar_Info; @@ -7218,7 +7217,7 @@ static void FPT_queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, * Description: Add SCCB to our disconnect array. * *---------------------------------------------------------------------*/ -static void FPT_queueDisconnect(PSCCB p_sccb, UCHAR p_card) +static void FPT_queueDisconnect(PSCCB p_sccb, unsigned char p_card) { PSCCBMgr_tar_info currTar_Info; @@ -7253,16 +7252,16 @@ static void FPT_queueDisconnect(PSCCB p_sccb, UCHAR p_card) * *---------------------------------------------------------------------*/ -static void FPT_queueFlushSccb(UCHAR p_card, UCHAR error_code) +static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code) { - UCHAR qtag,thisTarg; + unsigned char qtag,thisTarg; PSCCB currSCCB; PSCCBMgr_tar_info currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; if(currSCCB != NULL) { - thisTarg = (UCHAR)currSCCB->TargID; + thisTarg = (unsigned char)currSCCB->TargID; currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; for (qtag=0; qtagTargID == thisTarg)) { - FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code; + FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (unsigned char)error_code; FPT_queueCmdComplete(&FPT_BL_Card[p_card],FPT_BL_Card[p_card].discQ_Tbl[qtag], p_card); @@ -7292,10 +7291,10 @@ static void FPT_queueFlushSccb(UCHAR p_card, UCHAR error_code) * *---------------------------------------------------------------------*/ -static void FPT_queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, - UCHAR error_code) +static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg, + unsigned char error_code) { - UCHAR qtag; + unsigned char qtag; PSCCBMgr_tar_info currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; @@ -7306,7 +7305,7 @@ static void FPT_queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) { - FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code; + FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (unsigned char)error_code; FPT_queueCmdComplete(&FPT_BL_Card[p_card],FPT_BL_Card[p_card].discQ_Tbl[qtag], p_card); @@ -7322,7 +7321,7 @@ static void FPT_queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, -static void FPT_queueAddSccb(PSCCB p_SCCB, UCHAR p_card) +static void FPT_queueAddSccb(PSCCB p_SCCB, unsigned char p_card) { PSCCBMgr_tar_info currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID]; @@ -7356,7 +7355,7 @@ static void FPT_queueAddSccb(PSCCB p_SCCB, UCHAR p_card) * *---------------------------------------------------------------------*/ -static UCHAR FPT_queueFindSccb(PSCCB p_SCCB, UCHAR p_card) +static unsigned char FPT_queueFindSccb(PSCCB p_SCCB, unsigned char p_card) { PSCCB q_ptr; PSCCBMgr_tar_info currTar_Info; @@ -7469,7 +7468,7 @@ static void FPT_utilUpdateResidual(PSCCB p_SCCB) static void FPT_Wait1Second(ULONG p_port) { - UCHAR i; + unsigned char i; for(i=0; i < 4; i++) { @@ -7492,10 +7491,10 @@ static void FPT_Wait1Second(ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_Wait(ULONG p_port, UCHAR p_delay) +static void FPT_Wait(ULONG p_port, unsigned char p_delay) { - UCHAR old_timer; - UCHAR green_flag; + unsigned char old_timer; + unsigned char green_flag; old_timer = RD_HARPOON(p_port+hp_seltimeout); @@ -7540,11 +7539,11 @@ static void FPT_Wait(ULONG p_port, UCHAR p_delay) * *---------------------------------------------------------------------*/ -static void FPT_utilEEWriteOnOff(ULONG p_port,UCHAR p_mode) +static void FPT_utilEEWriteOnOff(ULONG p_port,unsigned char p_mode) { - UCHAR ee_value; + unsigned char ee_value; - ee_value = (UCHAR)(RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H)); + ee_value = (unsigned char)(RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H)); if (p_mode) @@ -7572,10 +7571,10 @@ static void FPT_utilEEWriteOnOff(ULONG p_port,UCHAR p_mode) static void FPT_utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr) { - UCHAR ee_value; + unsigned char ee_value; USHORT i; - ee_value = (UCHAR)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| + ee_value = (unsigned char)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| (SEE_MS | SEE_CS)); @@ -7653,10 +7652,10 @@ static USHORT FPT_utilEERead(ULONG p_port, USHORT ee_addr) static USHORT FPT_utilEEReadOrg(ULONG p_port, USHORT ee_addr) { - UCHAR ee_value; + unsigned char ee_value; USHORT i, ee_data; - ee_value = (UCHAR)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| + ee_value = (unsigned char)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| (SEE_MS | SEE_CS)); @@ -7698,15 +7697,15 @@ static USHORT FPT_utilEEReadOrg(ULONG p_port, USHORT ee_addr) * *---------------------------------------------------------------------*/ -static void FPT_utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr) +static void FPT_utilEESendCmdAddr(ULONG p_port, unsigned char ee_cmd, USHORT ee_addr) { - UCHAR ee_value; - UCHAR narrow_flg; + unsigned char ee_value; + unsigned char narrow_flg; USHORT i; - narrow_flg= (UCHAR)(RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD); + narrow_flg= (unsigned char)(RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD); ee_value = SEE_MS; @@ -7761,7 +7760,7 @@ static void FPT_utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr) } } -static USHORT FPT_CalcCrc16(UCHAR buffer[]) +static USHORT FPT_CalcCrc16(unsigned char buffer[]) { USHORT crc=0; int i,j; @@ -7781,10 +7780,10 @@ static USHORT FPT_CalcCrc16(UCHAR buffer[]) return(crc); } -static UCHAR FPT_CalcLrc(UCHAR buffer[]) +static unsigned char FPT_CalcLrc(unsigned char buffer[]) { int i; - UCHAR lrc; + unsigned char lrc; lrc = 0; for(i = 0; i < ID_STRING_LENGTH; i++) lrc ^= buffer[i]; -- cgit v1.2.3-59-g8ed1b From c823feeb33161c09e83ee4e68c822d6b9ececbc4 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:25 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: remove USHORT Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 117 +++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index e98bbef485b8..02af5fb73147 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -40,7 +40,6 @@ #define FAILURE 0xFFFFFFFFL -typedef unsigned short USHORT; typedef unsigned int UINT; typedef unsigned long ULONG; @@ -59,7 +58,7 @@ typedef unsigned short * ushort_ptr; #define BIT(x) ((unsigned char)(1<<(x))) /* single-bit mask in bit position x */ -#define BITW(x) ((USHORT)(1<<(x))) /* single-bit mask in bit position x */ +#define BITW(x) ((unsigned short)(1<<(x))) /* single-bit mask in bit position x */ @@ -74,13 +73,13 @@ typedef struct SCCBMgr_info { unsigned char si_intvect; unsigned char si_id; unsigned char si_lun; - USHORT si_fw_revision; - USHORT si_per_targ_init_sync; - USHORT si_per_targ_fast_nego; - USHORT si_per_targ_ultra_nego; - USHORT si_per_targ_no_disc; - USHORT si_per_targ_wide_nego; - USHORT si_flags; + unsigned short si_fw_revision; + unsigned short si_per_targ_init_sync; + unsigned short si_per_targ_fast_nego; + unsigned short si_per_targ_ultra_nego; + unsigned short si_per_targ_no_disc; + unsigned short si_per_targ_wide_nego; + unsigned short si_flags; unsigned char si_card_family; unsigned char si_bustype; unsigned char si_card_model[3]; @@ -143,15 +142,15 @@ typedef struct _SCCB { ULONG SccbIOPort; /* Identifies board base port */ unsigned char SccbStatus; unsigned char SCCBRes2; - USHORT SccbOSFlags; + unsigned short SccbOSFlags; ULONG Sccb_XferCnt; /* actual transfer count */ ULONG Sccb_ATC; ULONG SccbVirtDataPtr; /* virtual addr for OS/2 */ ULONG Sccb_res1; - USHORT Sccb_MGRFlags; - USHORT Sccb_sgseg; + unsigned short Sccb_MGRFlags; + unsigned short Sccb_sgseg; unsigned char Sccb_scsimsg; /* identify msg for selection */ unsigned char Sccb_tag; unsigned char Sccb_scsistat; @@ -324,7 +323,7 @@ typedef struct SCCBcard { ULONG ioPort; - USHORT cmdCounter; + unsigned short cmdCounter; unsigned char discQCount; unsigned char tagQ_Lst; unsigned char cardIndex; @@ -943,13 +942,13 @@ typedef struct SCCBscam_info { #define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;} /* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \ xfercnt <<= 16,\ - xfercnt |= RDW_HARPOON((USHORT)(port+hp_xfercnt_0))) + xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0))) */ -#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (USHORT)(addr & 0x0000FFFFL)),\ +#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (unsigned short)(addr & 0x0000FFFFL)),\ addr >>= 16,\ - WRW_HARPOON((port+hp_host_addr_hmi), (USHORT)(addr & 0x0000FFFFL)),\ + WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\ WR_HARP32(port,hp_xfercnt_0,count),\ - WRW_HARPOON((port+hp_xfer_cnt_lo), (USHORT)(count & 0x0000FFFFL)),\ + WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\ count >>= 16,\ WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF))) @@ -1016,17 +1015,17 @@ static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code); static void FPT_queueAddSccb(PSCCB p_SCCB, unsigned char card); static unsigned char FPT_queueFindSccb(PSCCB p_SCCB, unsigned char p_card); static void FPT_utilUpdateResidual(PSCCB p_SCCB); -static USHORT FPT_CalcCrc16(unsigned char buffer[]); +static unsigned short FPT_CalcCrc16(unsigned char buffer[]); static unsigned char FPT_CalcLrc(unsigned char buffer[]); static void FPT_Wait1Second(ULONG p_port); static void FPT_Wait(ULONG p_port, unsigned char p_delay); static void FPT_utilEEWriteOnOff(ULONG p_port,unsigned char p_mode); -static void FPT_utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr); -static USHORT FPT_utilEERead(ULONG p_port, USHORT ee_addr); -static USHORT FPT_utilEEReadOrg(ULONG p_port, USHORT ee_addr); -static void FPT_utilEESendCmdAddr(ULONG p_port, unsigned char ee_cmd, USHORT ee_addr); +static void FPT_utilEEWrite(ULONG p_port, unsigned short ee_data, unsigned short ee_addr); +static unsigned short FPT_utilEERead(ULONG p_port, unsigned short ee_addr); +static unsigned short FPT_utilEEReadOrg(ULONG p_port, unsigned short ee_addr); +static void FPT_utilEESendCmdAddr(ULONG p_port, unsigned char ee_cmd, unsigned short ee_addr); @@ -1060,7 +1059,7 @@ static void FPT_hostDataXferRestart(PSCCB currSCCB); static unsigned char FPT_SccbMgr_bad_isr(ULONG p_port, unsigned char p_card, - PSCCBcard pCurrCard, USHORT p_int); + PSCCBcard pCurrCard, unsigned short p_int); static void FPT_SccbMgrTableInitAll(void); static void FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, unsigned char p_card); @@ -1105,7 +1104,7 @@ static unsigned char FPT_scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; -static USHORT FPT_default_intena = 0; +static unsigned short FPT_default_intena = 0; static void (*FPT_s_PhaseTbl[8]) (ULONG, unsigned char)= { 0 }; @@ -1124,7 +1123,7 @@ static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) static unsigned char first_time = 1; unsigned char i,j,id,ScamFlg; - USHORT temp,temp2,temp3,temp4,temp5,temp6; + unsigned short temp,temp2,temp3,temp4,temp5,temp6; ULONG ioport; PNVRamInfo pCurrNvRam; @@ -1203,11 +1202,11 @@ static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) for (id = 0; id < (16/2); id++) { if(pCurrNvRam){ - temp = (USHORT) pCurrNvRam->niSyncTbl[id]; + temp = (unsigned short) pCurrNvRam->niSyncTbl[id]; temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); }else - temp = FPT_utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id)); + temp = FPT_utilEERead(ioport, (unsigned short)((SYNC_RATE_TBL/2)+id)); for (i = 0; i < 2; temp >>=8,i++) { @@ -1402,7 +1401,7 @@ static ULONG FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) PSCCBcard CurrCard = NULL; PNVRamInfo pCurrNvRam; unsigned char i,j,thisCard, ScamFlg; - USHORT temp,sync_bit_map,id; + unsigned short temp,sync_bit_map,id; ULONG ioport; ioport = pCardInfo->si_baseaddr; @@ -1532,11 +1531,11 @@ static ULONG FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) for (id = 0; id < (MAX_SCSI_TAR/2); id++) { if(pCurrNvRam){ - temp = (USHORT) pCurrNvRam->niSyncTbl[id]; + temp = (unsigned short) pCurrNvRam->niSyncTbl[id]; temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); }else - temp = FPT_utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id)); + temp = FPT_utilEERead(ioport, (unsigned short)((SYNC_RATE_TBL/2)+id)); for (i = 0; i < 2; temp >>=8,i++) { @@ -1928,7 +1927,7 @@ static int FlashPoint_HandleInterrupt(ULONG pCurrCard) { PSCCB currSCCB; unsigned char thisCard,result,bm_status, bm_int_st; - USHORT hp_int; + unsigned short hp_int; unsigned char i, target; ULONG ioport; @@ -2170,7 +2169,7 @@ static int FlashPoint_HandleInterrupt(ULONG pCurrCard) * *---------------------------------------------------------------------*/ static unsigned char FPT_SccbMgr_bad_isr(ULONG p_port, unsigned char p_card, - PSCCBcard pCurrCard, USHORT p_int) + PSCCBcard pCurrCard, unsigned short p_int) { unsigned char temp, ScamFlg; PSCCBMgr_tar_info currTar_Info; @@ -2430,7 +2429,7 @@ static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char targe static unsigned char FPT_sfm(ULONG port, PSCCB pCurrSCCB) { unsigned char message; - USHORT TimeOutLoop; + unsigned short TimeOutLoop; TimeOutLoop = 0; while( (!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && @@ -2775,7 +2774,7 @@ static void FPT_ssel(ULONG port, unsigned char p_card) } /* auto_loaded */ - WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00); + WRW_HARPOON((port+hp_fiforead), (unsigned short) 0x00); WR_HARPOON(port+hp_xferstat, 0x00); WRW_HARPOON((port+hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE)); @@ -2877,7 +2876,7 @@ static void FPT_sres(ULONG port, unsigned char p_card, PSCCBcard pCurrCard) FPT_queueSelectFail(&FPT_BL_Card[p_card],p_card); } - WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00); + WRW_HARPOON((port+hp_fiforead), (unsigned short) 0x00); our_target = (unsigned char)(RD_HARPOON(port+hp_select_id) >> 4); @@ -4056,7 +4055,7 @@ static void FPT_sxfrp(ULONG p_port, unsigned char p_card) static void FPT_schkdd(ULONG port, unsigned char p_card) { - USHORT TimeOutLoop; + unsigned short TimeOutLoop; unsigned char sPhase; PSCCB currSCCB; @@ -4079,7 +4078,7 @@ static void FPT_schkdd(ULONG port, unsigned char p_card) currSCCB->Sccb_XferCnt = 1; currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT; - WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00); + WRW_HARPOON((port+hp_fiforead), (unsigned short) 0x00); WR_HARPOON(port+hp_xferstat, 0x00); } @@ -5486,7 +5485,7 @@ static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrS pCurrSCCB->Sccb_SGoffset = remain_cnt; - pCurrSCCB->Sccb_sgseg = (USHORT)sg_ptr; + pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr; if ((ULONG)(sg_ptr * SG_ELEMENT_SIZE) == pCurrSCCB->DataLength @@ -5631,7 +5630,7 @@ static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrS pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; - pCurrSCCB->Sccb_sgseg = (USHORT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE); + pCurrSCCB->Sccb_sgseg = (unsigned short)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE); } } @@ -5688,7 +5687,7 @@ static void FPT_hostDataXferRestart(PSCCB currSCCB) currSCCB->Sccb_SGoffset = data_count - currSCCB->Sccb_ATC; } - currSCCB->Sccb_sgseg = (USHORT)sg_index; + currSCCB->Sccb_sgseg = (unsigned short)sg_index; } else { @@ -6465,7 +6464,7 @@ static void FPT_scwtsel(ULONG p_port) static void FPT_inisci(unsigned char p_card, ULONG p_port, unsigned char p_our_id) { unsigned char i,k,max_id; - USHORT ee_data; + unsigned short ee_data; PNVRamInfo pCurrNvRam; pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo; @@ -6495,8 +6494,8 @@ static void FPT_inisci(unsigned char p_card, ULONG p_port, unsigned char p_our_i { for (k=0; k < ID_STRING_LENGTH; k+=2) { - ee_data = FPT_utilEERead(p_port, (USHORT)((EE_SCAMBASE/2) + - (USHORT) (i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2))); + ee_data = FPT_utilEERead(p_port, (unsigned short)((EE_SCAMBASE/2) + + (unsigned short) (i*((unsigned short)ID_STRING_LENGTH/2)) + (unsigned short)(k/2))); FPT_scamInfo[i].id_string[k] = (unsigned char) ee_data; ee_data >>= 8; FPT_scamInfo[i].id_string[k+1] = (unsigned char) ee_data; @@ -6658,7 +6657,7 @@ static unsigned char FPT_scmachid(unsigned char p_card, unsigned char p_id_strin static void FPT_scsavdi(unsigned char p_card, ULONG p_port) { unsigned char i,k,max_id; - USHORT ee_data,sum_data; + unsigned short ee_data,sum_data; sum_data = 0x0000; @@ -6686,8 +6685,8 @@ static void FPT_scsavdi(unsigned char p_card, ULONG p_port) ee_data <<= 8; ee_data |= FPT_scamInfo[i].id_string[k]; sum_data += ee_data; - FPT_utilEEWrite(p_port, ee_data, (USHORT)((EE_SCAMBASE/2) + - (USHORT)(i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2))); + FPT_utilEEWrite(p_port, ee_data, (unsigned short)((EE_SCAMBASE/2) + + (unsigned short)(i*((unsigned short)ID_STRING_LENGTH/2)) + (unsigned short)(k/2))); } } @@ -6787,7 +6786,7 @@ static void FPT_BusMasterInit(ULONG p_port) static void FPT_DiagEEPROM(ULONG p_port) { - USHORT index,temp,max_wd_cnt; + unsigned short index,temp,max_wd_cnt; if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD) max_wd_cnt = EEPROM_WD_CNT; @@ -7568,11 +7567,11 @@ static void FPT_utilEEWriteOnOff(ULONG p_port,unsigned char p_mode) * *---------------------------------------------------------------------*/ -static void FPT_utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr) +static void FPT_utilEEWrite(ULONG p_port, unsigned short ee_data, unsigned short ee_addr) { unsigned char ee_value; - USHORT i; + unsigned short i; ee_value = (unsigned char)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| (SEE_MS | SEE_CS)); @@ -7619,9 +7618,9 @@ static void FPT_utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr) * *---------------------------------------------------------------------*/ -static USHORT FPT_utilEERead(ULONG p_port, USHORT ee_addr) +static unsigned short FPT_utilEERead(ULONG p_port, unsigned short ee_addr) { - USHORT i, ee_data1, ee_data2; + unsigned short i, ee_data1, ee_data2; i = 0; ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr); @@ -7649,11 +7648,11 @@ static USHORT FPT_utilEERead(ULONG p_port, USHORT ee_addr) * *---------------------------------------------------------------------*/ -static USHORT FPT_utilEEReadOrg(ULONG p_port, USHORT ee_addr) +static unsigned short FPT_utilEEReadOrg(ULONG p_port, unsigned short ee_addr) { unsigned char ee_value; - USHORT i, ee_data; + unsigned short i, ee_data; ee_value = (unsigned char)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| (SEE_MS | SEE_CS)); @@ -7697,12 +7696,12 @@ static USHORT FPT_utilEEReadOrg(ULONG p_port, USHORT ee_addr) * *---------------------------------------------------------------------*/ -static void FPT_utilEESendCmdAddr(ULONG p_port, unsigned char ee_cmd, USHORT ee_addr) +static void FPT_utilEESendCmdAddr(ULONG p_port, unsigned char ee_cmd, unsigned short ee_addr) { unsigned char ee_value; unsigned char narrow_flg; - USHORT i; + unsigned short i; narrow_flg= (unsigned char)(RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD); @@ -7760,14 +7759,14 @@ static void FPT_utilEESendCmdAddr(ULONG p_port, unsigned char ee_cmd, USHORT ee_ } } -static USHORT FPT_CalcCrc16(unsigned char buffer[]) +static unsigned short FPT_CalcCrc16(unsigned char buffer[]) { - USHORT crc=0; + unsigned short crc=0; int i,j; - USHORT ch; + unsigned short ch; for (i=0; i < ID_STRING_LENGTH; i++) { - ch = (USHORT) buffer[i]; + ch = (unsigned short) buffer[i]; for(j=0; j < 8; j++) { if ((crc ^ ch) & 1) -- cgit v1.2.3-59-g8ed1b From ce793215b428ae7650b39d87702efa3d5b26ba28 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:26 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: remove UINT Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 02af5fb73147..a981dea3bbfb 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -40,7 +40,6 @@ #define FAILURE 0xFFFFFFFFL -typedef unsigned int UINT; typedef unsigned long ULONG; @@ -5205,7 +5204,7 @@ static void FPT_dataXferProcessor(ULONG port, PSCCBcard pCurrCard) static void FPT_busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB) { ULONG count,addr,tmpSGCnt; - UINT sg_index; + unsigned int sg_index; unsigned char sg_count, i; ULONG reg_offset; @@ -5231,7 +5230,7 @@ static void FPT_busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB) WR_HARPOON(p_port+hp_page_ctrl, i); while ((sg_count < (unsigned char)SG_BUF_CNT) && - ((ULONG)(sg_index * (UINT)SG_ELEMENT_SIZE) < pcurrSCCB->DataLength) ) { + ((ULONG)(sg_index * (unsigned int)SG_ELEMENT_SIZE) < pcurrSCCB->DataLength) ) { tmpSGCnt += *(((ULONG *)pcurrSCCB->DataPointer)+ (sg_index * 2)); @@ -5403,7 +5402,7 @@ static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrS ULONG timeout; ULONG remain_cnt; - UINT sg_ptr; + unsigned int sg_ptr; FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT; @@ -5454,9 +5453,9 @@ static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrS sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT; - if (sg_ptr > (UINT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE)) { + if (sg_ptr > (unsigned int)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE)) { - sg_ptr = (UINT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE); + sg_ptr = (unsigned int)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE); } remain_cnt = pCurrSCCB->Sccb_XferCnt; @@ -5659,7 +5658,7 @@ static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrS static void FPT_hostDataXferRestart(PSCCB currSCCB) { ULONG data_count; - UINT sg_index; + unsigned int sg_index; ULONG *sg_ptr; if (currSCCB->Sccb_XferState & F_SG_XFER) { @@ -7418,7 +7417,7 @@ static unsigned char FPT_queueFindSccb(PSCCB p_SCCB, unsigned char p_card) static void FPT_utilUpdateResidual(PSCCB p_SCCB) { ULONG partial_cnt; - UINT sg_index; + unsigned int sg_index; ULONG *sg_ptr; if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) { -- cgit v1.2.3-59-g8ed1b From d63a4cccf387a8e6210cfd818c1ea717beefc531 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:26 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: remove ULONG Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 381 +++++++++++++++++++++++----------------------- 1 file changed, 190 insertions(+), 191 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index a981dea3bbfb..d877a6a12aca 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -40,7 +40,6 @@ #define FAILURE 0xFFFFFFFFL -typedef unsigned long ULONG; typedef unsigned short * ushort_ptr; @@ -67,7 +66,7 @@ typedef void (*CALL_BK_FN)(PSCCB); typedef struct SCCBMgr_info { - ULONG si_baseaddr; + unsigned long si_baseaddr; unsigned char si_present; unsigned char si_intvect; unsigned char si_id; @@ -84,10 +83,10 @@ typedef struct SCCBMgr_info { unsigned char si_card_model[3]; unsigned char si_relative_cardnum; unsigned char si_reserved[4]; - ULONG si_OS_reserved; + unsigned long si_OS_reserved; unsigned char si_XlatInfo[4]; - ULONG si_reserved2[5]; - ULONG si_secondary_range; + unsigned long si_reserved2[5]; + unsigned long si_secondary_range; } SCCBMGR_INFO; typedef SCCBMGR_INFO * PSCCBMGR_INFO; @@ -123,8 +122,8 @@ typedef struct _SCCB { unsigned char ControlByte; unsigned char CdbLength; unsigned char RequestSenseLength; - ULONG DataLength; - ULONG DataPointer; + unsigned long DataLength; + unsigned long DataPointer; unsigned char CcbRes[2]; unsigned char HostStatus; unsigned char TargetStatus; @@ -133,21 +132,21 @@ typedef struct _SCCB { unsigned char Cdb[12]; unsigned char CcbRes1; unsigned char Reserved1; - ULONG Reserved2; - ULONG SensePointer; + unsigned long Reserved2; + unsigned long SensePointer; CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */ - ULONG SccbIOPort; /* Identifies board base port */ + unsigned long SccbIOPort; /* Identifies board base port */ unsigned char SccbStatus; unsigned char SCCBRes2; unsigned short SccbOSFlags; - ULONG Sccb_XferCnt; /* actual transfer count */ - ULONG Sccb_ATC; - ULONG SccbVirtDataPtr; /* virtual addr for OS/2 */ - ULONG Sccb_res1; + unsigned long Sccb_XferCnt; /* actual transfer count */ + unsigned long Sccb_ATC; + unsigned long SccbVirtDataPtr; /* virtual addr for OS/2 */ + unsigned long Sccb_res1; unsigned short Sccb_MGRFlags; unsigned short Sccb_sgseg; unsigned char Sccb_scsimsg; /* identify msg for selection */ @@ -156,11 +155,11 @@ typedef struct _SCCB { unsigned char Sccb_idmsg; /* image of last msg in */ PSCCB Sccb_forwardlink; PSCCB Sccb_backlink; - ULONG Sccb_savedATC; + unsigned long Sccb_savedATC; unsigned char Save_Cdb[6]; unsigned char Save_CdbLen; unsigned char Sccb_XferState; - ULONG Sccb_SGoffset; + unsigned long Sccb_SGoffset; } SCCB; @@ -299,7 +298,7 @@ typedef struct SCCBMgr_tar_info { typedef struct NVRAMInfo { unsigned char niModel; /* Model No. of card */ unsigned char niCardNo; /* Card no. */ - ULONG niBaseAddr; /* Port Address of card */ + unsigned long niBaseAddr; /* Port Address of card */ unsigned char niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */ unsigned char niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */ unsigned char niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */ @@ -320,7 +319,7 @@ typedef struct SCCBcard { PSCCB currentSCCB; PSCCBMGR_INFO cardInfo; - ULONG ioPort; + unsigned long ioPort; unsigned short cmdCounter; unsigned char discQCount; @@ -978,31 +977,31 @@ typedef struct SCCBscam_info { -static unsigned char FPT_sisyncn(ULONG port, unsigned char p_card, unsigned char syncFlag); -static void FPT_ssel(ULONG port, unsigned char p_card); -static void FPT_sres(ULONG port, unsigned char p_card, PSCCBcard pCurrCard); -static void FPT_shandem(ULONG port, unsigned char p_card,PSCCB pCurrSCCB); -static void FPT_stsyncn(ULONG port, unsigned char p_card); -static void FPT_sisyncr(ULONG port,unsigned char sync_pulse, unsigned char offset); -static void FPT_sssyncv(ULONG p_port, unsigned char p_id, unsigned char p_sync_value, +static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, unsigned char syncFlag); +static void FPT_ssel(unsigned long port, unsigned char p_card); +static void FPT_sres(unsigned long port, unsigned char p_card, PSCCBcard pCurrCard); +static void FPT_shandem(unsigned long port, unsigned char p_card,PSCCB pCurrSCCB); +static void FPT_stsyncn(unsigned long port, unsigned char p_card); +static void FPT_sisyncr(unsigned long port,unsigned char sync_pulse, unsigned char offset); +static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, unsigned char p_sync_value, PSCCBMgr_tar_info currTar_Info); -static void FPT_sresb(ULONG port, unsigned char p_card); -static void FPT_sxfrp(ULONG p_port, unsigned char p_card); -static void FPT_schkdd(ULONG port, unsigned char p_card); -static unsigned char FPT_RdStack(ULONG port, unsigned char index); -static void FPT_WrStack(ULONG portBase, unsigned char index, unsigned char data); -static unsigned char FPT_ChkIfChipInitialized(ULONG ioPort); - -static void FPT_SendMsg(ULONG port, unsigned char message); +static void FPT_sresb(unsigned long port, unsigned char p_card); +static void FPT_sxfrp(unsigned long p_port, unsigned char p_card); +static void FPT_schkdd(unsigned long port, unsigned char p_card); +static unsigned char FPT_RdStack(unsigned long port, unsigned char index); +static void FPT_WrStack(unsigned long portBase, unsigned char index, unsigned char data); +static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort); + +static void FPT_SendMsg(unsigned long port, unsigned char message); static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg, unsigned char error_code); static void FPT_sinits(PSCCB p_sccb, unsigned char p_card); static void FPT_RNVRamData(PNVRamInfo pNvRamInfo); -static unsigned char FPT_siwidn(ULONG port, unsigned char p_card); -static void FPT_stwidn(ULONG port, unsigned char p_card); -static void FPT_siwidr(ULONG port, unsigned char width); +static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card); +static void FPT_stwidn(unsigned long port, unsigned char p_card); +static void FPT_siwidr(unsigned long port, unsigned char width); static void FPT_queueSelectFail(PSCCBcard pCurrCard, unsigned char p_card); @@ -1018,46 +1017,46 @@ static unsigned short FPT_CalcCrc16(unsigned char buffer[]); static unsigned char FPT_CalcLrc(unsigned char buffer[]); -static void FPT_Wait1Second(ULONG p_port); -static void FPT_Wait(ULONG p_port, unsigned char p_delay); -static void FPT_utilEEWriteOnOff(ULONG p_port,unsigned char p_mode); -static void FPT_utilEEWrite(ULONG p_port, unsigned short ee_data, unsigned short ee_addr); -static unsigned short FPT_utilEERead(ULONG p_port, unsigned short ee_addr); -static unsigned short FPT_utilEEReadOrg(ULONG p_port, unsigned short ee_addr); -static void FPT_utilEESendCmdAddr(ULONG p_port, unsigned char ee_cmd, unsigned short ee_addr); +static void FPT_Wait1Second(unsigned long p_port); +static void FPT_Wait(unsigned long p_port, unsigned char p_delay); +static void FPT_utilEEWriteOnOff(unsigned long p_port,unsigned char p_mode); +static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data, unsigned short ee_addr); +static unsigned short FPT_utilEERead(unsigned long p_port, unsigned short ee_addr); +static unsigned short FPT_utilEEReadOrg(unsigned long p_port, unsigned short ee_addr); +static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd, unsigned short ee_addr); -static void FPT_phaseDataOut(ULONG port, unsigned char p_card); -static void FPT_phaseDataIn(ULONG port, unsigned char p_card); -static void FPT_phaseCommand(ULONG port, unsigned char p_card); -static void FPT_phaseStatus(ULONG port, unsigned char p_card); -static void FPT_phaseMsgOut(ULONG port, unsigned char p_card); -static void FPT_phaseMsgIn(ULONG port, unsigned char p_card); -static void FPT_phaseIllegal(ULONG port, unsigned char p_card); +static void FPT_phaseDataOut(unsigned long port, unsigned char p_card); +static void FPT_phaseDataIn(unsigned long port, unsigned char p_card); +static void FPT_phaseCommand(unsigned long port, unsigned char p_card); +static void FPT_phaseStatus(unsigned long port, unsigned char p_card); +static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card); +static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card); +static void FPT_phaseIllegal(unsigned long port, unsigned char p_card); -static void FPT_phaseDecode(ULONG port, unsigned char p_card); -static void FPT_phaseChkFifo(ULONG port, unsigned char p_card); -static void FPT_phaseBusFree(ULONG p_port, unsigned char p_card); +static void FPT_phaseDecode(unsigned long port, unsigned char p_card); +static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card); +static void FPT_phaseBusFree(unsigned long p_port, unsigned char p_card); -static void FPT_XbowInit(ULONG port, unsigned char scamFlg); -static void FPT_BusMasterInit(ULONG p_port); -static void FPT_DiagEEPROM(ULONG p_port); +static void FPT_XbowInit(unsigned long port, unsigned char scamFlg); +static void FPT_BusMasterInit(unsigned long p_port); +static void FPT_DiagEEPROM(unsigned long p_port); -static void FPT_dataXferProcessor(ULONG port, PSCCBcard pCurrCard); -static void FPT_busMstrSGDataXferStart(ULONG port, PSCCB pCurrSCCB); -static void FPT_busMstrDataXferStart(ULONG port, PSCCB pCurrSCCB); -static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrSCCB); +static void FPT_dataXferProcessor(unsigned long port, PSCCBcard pCurrCard); +static void FPT_busMstrSGDataXferStart(unsigned long port, PSCCB pCurrSCCB); +static void FPT_busMstrDataXferStart(unsigned long port, PSCCB pCurrSCCB); +static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, PSCCB pCurrSCCB); static void FPT_hostDataXferRestart(PSCCB currSCCB); -static unsigned char FPT_SccbMgr_bad_isr(ULONG p_port, unsigned char p_card, +static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, unsigned char p_card, PSCCBcard pCurrCard, unsigned short p_int); static void FPT_SccbMgrTableInitAll(void); @@ -1068,25 +1067,25 @@ static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char targ static void FPT_scini(unsigned char p_card, unsigned char p_our_id, unsigned char p_power_up); -static int FPT_scarb(ULONG p_port, unsigned char p_sel_type); -static void FPT_scbusf(ULONG p_port); -static void FPT_scsel(ULONG p_port); -static void FPT_scasid(unsigned char p_card, ULONG p_port); -static unsigned char FPT_scxferc(ULONG p_port, unsigned char p_data); -static unsigned char FPT_scsendi(ULONG p_port, unsigned char p_id_string[]); -static unsigned char FPT_sciso(ULONG p_port, unsigned char p_id_string[]); -static void FPT_scwirod(ULONG p_port, unsigned char p_data_bit); -static void FPT_scwiros(ULONG p_port, unsigned char p_data_bit); +static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type); +static void FPT_scbusf(unsigned long p_port); +static void FPT_scsel(unsigned long p_port); +static void FPT_scasid(unsigned char p_card, unsigned long p_port); +static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data); +static unsigned char FPT_scsendi(unsigned long p_port, unsigned char p_id_string[]); +static unsigned char FPT_sciso(unsigned long p_port, unsigned char p_id_string[]); +static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit); +static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit); static unsigned char FPT_scvalq(unsigned char p_quintet); -static unsigned char FPT_scsell(ULONG p_port, unsigned char targ_id); -static void FPT_scwtsel(ULONG p_port); -static void FPT_inisci(unsigned char p_card, ULONG p_port, unsigned char p_our_id); -static void FPT_scsavdi(unsigned char p_card, ULONG p_port); +static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id); +static void FPT_scwtsel(unsigned long p_port); +static void FPT_inisci(unsigned char p_card, unsigned long p_port, unsigned char p_our_id); +static void FPT_scsavdi(unsigned char p_card, unsigned long p_port); static unsigned char FPT_scmachid(unsigned char p_card, unsigned char p_id_string[]); -static void FPT_autoCmdCmplt(ULONG p_port, unsigned char p_card); -static void FPT_autoLoadDefaultMap(ULONG p_port); +static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card); +static void FPT_autoLoadDefaultMap(unsigned long p_port); @@ -1106,7 +1105,7 @@ static unsigned char FPT_scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', static unsigned short FPT_default_intena = 0; -static void (*FPT_s_PhaseTbl[8]) (ULONG, unsigned char)= { 0 }; +static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char)= { 0 }; /*--------------------------------------------------------------------- @@ -1123,7 +1122,7 @@ static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) unsigned char i,j,id,ScamFlg; unsigned short temp,temp2,temp3,temp4,temp5,temp6; - ULONG ioport; + unsigned long ioport; PNVRamInfo pCurrNvRam; ioport = pCardInfo->si_baseaddr; @@ -1395,13 +1394,13 @@ static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) * *---------------------------------------------------------------------*/ -static ULONG FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) +static unsigned long FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) { PSCCBcard CurrCard = NULL; PNVRamInfo pCurrNvRam; unsigned char i,j,thisCard, ScamFlg; unsigned short temp,sync_bit_map,id; - ULONG ioport; + unsigned long ioport; ioport = pCardInfo->si_baseaddr; @@ -1573,16 +1572,16 @@ static ULONG FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) WR_HARPOON((ioport+hp_semaphore), (unsigned char)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT)); - return((ULONG)CurrCard); + return((unsigned long)CurrCard); } -static void FlashPoint_ReleaseHostAdapter(ULONG pCurrCard) +static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard) { unsigned char i; - ULONG portBase; - ULONG regOffset; - ULONG scamData; - ULONG *pScamTbl; + unsigned long portBase; + unsigned long regOffset; + unsigned long scamData; + unsigned long *pScamTbl; PNVRamInfo pCurrNvRam; pCurrNvRam = ((PSCCBcard)pCurrCard)->pNvRamInfo; @@ -1601,7 +1600,7 @@ static void FlashPoint_ReleaseHostAdapter(ULONG pCurrCard) for(i = 0; i < MAX_SCSI_TAR; i++){ regOffset = hp_aramBase + 64 + i*4; - pScamTbl = (ULONG *) &pCurrNvRam->niScamTbl[i]; + pScamTbl = (unsigned long *) &pCurrNvRam->niScamTbl[i]; scamData = *pScamTbl; WR_HARP32(portBase, regOffset, scamData); } @@ -1615,10 +1614,10 @@ static void FlashPoint_ReleaseHostAdapter(ULONG pCurrCard) static void FPT_RNVRamData(PNVRamInfo pNvRamInfo) { unsigned char i; - ULONG portBase; - ULONG regOffset; - ULONG scamData; - ULONG *pScamTbl; + unsigned long portBase; + unsigned long regOffset; + unsigned long scamData; + unsigned long *pScamTbl; pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0); pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1); @@ -1634,26 +1633,26 @@ static void FPT_RNVRamData(PNVRamInfo pNvRamInfo) for(i = 0; i < MAX_SCSI_TAR; i++){ regOffset = hp_aramBase + 64 + i*4; RD_HARP32(portBase, regOffset, scamData); - pScamTbl = (ULONG *) &pNvRamInfo->niScamTbl[i]; + pScamTbl = (unsigned long *) &pNvRamInfo->niScamTbl[i]; *pScamTbl = scamData; } } -static unsigned char FPT_RdStack(ULONG portBase, unsigned char index) +static unsigned char FPT_RdStack(unsigned long portBase, unsigned char index) { WR_HARPOON(portBase + hp_stack_addr, index); return(RD_HARPOON(portBase + hp_stack_data)); } -static void FPT_WrStack(ULONG portBase, unsigned char index, unsigned char data) +static void FPT_WrStack(unsigned long portBase, unsigned char index, unsigned char data) { WR_HARPOON(portBase + hp_stack_addr, index); WR_HARPOON(portBase + hp_stack_data, data); } -static unsigned char FPT_ChkIfChipInitialized(ULONG ioPort) +static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort) { if((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4)) return(0); @@ -1675,9 +1674,9 @@ static unsigned char FPT_ChkIfChipInitialized(ULONG ioPort) * callback function. * *---------------------------------------------------------------------*/ -static void FlashPoint_StartCCB(ULONG pCurrCard, PSCCB p_Sccb) +static void FlashPoint_StartCCB(unsigned long pCurrCard, PSCCB p_Sccb) { - ULONG ioport; + unsigned long ioport; unsigned char thisCard, lun; PSCCB pSaveSccb; CALL_BK_FN callback; @@ -1795,9 +1794,9 @@ static void FlashPoint_StartCCB(ULONG pCurrCard, PSCCB p_Sccb) * callback function. * *---------------------------------------------------------------------*/ -static int FlashPoint_AbortCCB(ULONG pCurrCard, PSCCB p_Sccb) +static int FlashPoint_AbortCCB(unsigned long pCurrCard, PSCCB p_Sccb) { - ULONG ioport; + unsigned long ioport; unsigned char thisCard; CALL_BK_FN callback; @@ -1895,9 +1894,9 @@ static int FlashPoint_AbortCCB(ULONG pCurrCard, PSCCB p_Sccb) * interrupt for this card and disable the IRQ Pin if so. * *---------------------------------------------------------------------*/ -static unsigned char FlashPoint_InterruptPending(ULONG pCurrCard) +static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard) { - ULONG ioport; + unsigned long ioport; ioport = ((PSCCBcard)pCurrCard)->ioPort; @@ -1922,13 +1921,13 @@ static unsigned char FlashPoint_InterruptPending(ULONG pCurrCard) * us. * *---------------------------------------------------------------------*/ -static int FlashPoint_HandleInterrupt(ULONG pCurrCard) +static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) { PSCCB currSCCB; unsigned char thisCard,result,bm_status, bm_int_st; unsigned short hp_int; unsigned char i, target; - ULONG ioport; + unsigned long ioport; thisCard = ((PSCCBcard)pCurrCard)->cardIndex; ioport = ((PSCCBcard)pCurrCard)->ioPort; @@ -2167,7 +2166,7 @@ static int FlashPoint_HandleInterrupt(ULONG pCurrCard) * processing time. * *---------------------------------------------------------------------*/ -static unsigned char FPT_SccbMgr_bad_isr(ULONG p_port, unsigned char p_card, +static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, unsigned char p_card, PSCCBcard pCurrCard, unsigned short p_int) { unsigned char temp, ScamFlg; @@ -2425,7 +2424,7 @@ static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char targe * *---------------------------------------------------------------------*/ -static unsigned char FPT_sfm(ULONG port, PSCCB pCurrSCCB) +static unsigned char FPT_sfm(unsigned long port, PSCCB pCurrSCCB) { unsigned char message; unsigned short TimeOutLoop; @@ -2498,12 +2497,12 @@ static unsigned char FPT_sfm(ULONG port, PSCCB pCurrSCCB) * *---------------------------------------------------------------------*/ -static void FPT_ssel(ULONG port, unsigned char p_card) +static void FPT_ssel(unsigned long port, unsigned char p_card) { unsigned char auto_loaded, i, target, *theCCB; - ULONG cdb_reg; + unsigned long cdb_reg; PSCCBcard CurrCard; PSCCB currSCCB; PSCCBMgr_tar_info currTar_Info; @@ -2809,7 +2808,7 @@ static void FPT_ssel(ULONG port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_sres(ULONG port, unsigned char p_card, PSCCBcard pCurrCard) +static void FPT_sres(unsigned long port, unsigned char p_card, PSCCBcard pCurrCard) { unsigned char our_target, message, lun = 0, tag, msgRetryCount; @@ -3070,7 +3069,7 @@ static void FPT_sres(ULONG port, unsigned char p_card, PSCCBcard pCurrCard) (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ; } -static void FPT_SendMsg(ULONG port, unsigned char message) +static void FPT_SendMsg(unsigned long port, unsigned char message) { while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) { @@ -3119,7 +3118,7 @@ static void FPT_SendMsg(ULONG port, unsigned char message) * target device. * *---------------------------------------------------------------------*/ -static void FPT_sdecm(unsigned char message, ULONG port, unsigned char p_card) +static void FPT_sdecm(unsigned char message, unsigned long port, unsigned char p_card) { PSCCB currSCCB; PSCCBcard CurrCard; @@ -3298,7 +3297,7 @@ static void FPT_sdecm(unsigned char message, ULONG port, unsigned char p_card) * Description: Decide what to do with the extended message. * *---------------------------------------------------------------------*/ -static void FPT_shandem(ULONG port, unsigned char p_card, PSCCB pCurrSCCB) +static void FPT_shandem(unsigned long port, unsigned char p_card, PSCCB pCurrSCCB) { unsigned char length,message; @@ -3377,7 +3376,7 @@ static void FPT_shandem(ULONG port, unsigned char p_card, PSCCB pCurrSCCB) * *---------------------------------------------------------------------*/ -static unsigned char FPT_sisyncn(ULONG port, unsigned char p_card, unsigned char syncFlag) +static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, unsigned char syncFlag) { PSCCB currSCCB; PSCCBMgr_tar_info currTar_Info; @@ -3452,7 +3451,7 @@ static unsigned char FPT_sisyncn(ULONG port, unsigned char p_card, unsigned char * necessary. * *---------------------------------------------------------------------*/ -static void FPT_stsyncn(ULONG port, unsigned char p_card) +static void FPT_stsyncn(unsigned long port, unsigned char p_card) { unsigned char sync_msg,offset,sync_reg,our_sync_msg; PSCCB currSCCB; @@ -3584,7 +3583,7 @@ static void FPT_stsyncn(ULONG port, unsigned char p_card) * Description: Answer the targets sync message. * *---------------------------------------------------------------------*/ -static void FPT_sisyncr(ULONG port,unsigned char sync_pulse, unsigned char offset) +static void FPT_sisyncr(unsigned long port,unsigned char sync_pulse, unsigned char offset) { ARAM_ACCESS(port); WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); @@ -3615,7 +3614,7 @@ static void FPT_sisyncr(ULONG port,unsigned char sync_pulse, unsigned char offse * *---------------------------------------------------------------------*/ -static unsigned char FPT_siwidn(ULONG port, unsigned char p_card) +static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card) { PSCCB currSCCB; PSCCBMgr_tar_info currTar_Info; @@ -3667,7 +3666,7 @@ static unsigned char FPT_siwidn(ULONG port, unsigned char p_card) * necessary. * *---------------------------------------------------------------------*/ -static void FPT_stwidn(ULONG port, unsigned char p_card) +static void FPT_stwidn(unsigned long port, unsigned char p_card) { unsigned char width; PSCCB currSCCB; @@ -3747,7 +3746,7 @@ static void FPT_stwidn(ULONG port, unsigned char p_card) * Description: Answer the targets Wide nego message. * *---------------------------------------------------------------------*/ -static void FPT_siwidr(ULONG port, unsigned char width) +static void FPT_siwidr(unsigned long port, unsigned char width) { ARAM_ACCESS(port); WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); @@ -3776,7 +3775,7 @@ static void FPT_siwidr(ULONG port, unsigned char width) * ID specified. * *---------------------------------------------------------------------*/ -static void FPT_sssyncv(ULONG p_port, unsigned char p_id, unsigned char p_sync_value, +static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, unsigned char p_sync_value, PSCCBMgr_tar_info currTar_Info) { unsigned char index; @@ -3848,7 +3847,7 @@ static void FPT_sssyncv(ULONG p_port, unsigned char p_id, unsigned char p_sync_v * Description: Reset the desired card's SCSI bus. * *---------------------------------------------------------------------*/ -static void FPT_sresb(ULONG port, unsigned char p_card) +static void FPT_sresb(unsigned long port, unsigned char p_card) { unsigned char scsiID, i; @@ -3970,7 +3969,7 @@ static void FPT_ssenss(PSCCBcard pCurrCard) * *---------------------------------------------------------------------*/ -static void FPT_sxfrp(ULONG p_port, unsigned char p_card) +static void FPT_sxfrp(unsigned long p_port, unsigned char p_card) { unsigned char curr_phz; @@ -4052,7 +4051,7 @@ static void FPT_sxfrp(ULONG p_port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_schkdd(ULONG port, unsigned char p_card) +static void FPT_schkdd(unsigned long port, unsigned char p_card) { unsigned short TimeOutLoop; unsigned char sPhase; @@ -4245,10 +4244,10 @@ static void FPT_sinits(PSCCB p_sccb, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseDecode(ULONG p_port, unsigned char p_card) +static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card) { unsigned char phase_ref; - void (*phase) (ULONG, unsigned char); + void (*phase) (unsigned long, unsigned char); DISABLE_AUTO(p_port); @@ -4270,7 +4269,7 @@ static void FPT_phaseDecode(ULONG p_port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseDataOut(ULONG port, unsigned char p_card) +static void FPT_phaseDataOut(unsigned long port, unsigned char p_card) { PSCCB currSCCB; @@ -4314,7 +4313,7 @@ static void FPT_phaseDataOut(ULONG port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseDataIn(ULONG port, unsigned char p_card) +static void FPT_phaseDataIn(unsigned long port, unsigned char p_card) { PSCCB currSCCB; @@ -4361,10 +4360,10 @@ static void FPT_phaseDataIn(ULONG port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseCommand(ULONG p_port, unsigned char p_card) +static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card) { PSCCB currSCCB; - ULONG cdb_reg; + unsigned long cdb_reg; unsigned char i; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4413,7 +4412,7 @@ static void FPT_phaseCommand(ULONG p_port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseStatus(ULONG port, unsigned char p_card) +static void FPT_phaseStatus(unsigned long port, unsigned char p_card) { /* Start-up the automation to finish off this command and let the isr handle the interrupt for command complete when it comes in. @@ -4435,7 +4434,7 @@ static void FPT_phaseStatus(ULONG port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseMsgOut(ULONG port, unsigned char p_card) +static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card) { unsigned char message,scsiID; PSCCB currSCCB; @@ -4583,7 +4582,7 @@ static void FPT_phaseMsgOut(ULONG port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseMsgIn(ULONG port, unsigned char p_card) +static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card) { unsigned char message; PSCCB currSCCB; @@ -4636,7 +4635,7 @@ static void FPT_phaseMsgIn(ULONG port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseIllegal(ULONG port, unsigned char p_card) +static void FPT_phaseIllegal(unsigned long port, unsigned char p_card) { PSCCB currSCCB; @@ -4664,9 +4663,9 @@ static void FPT_phaseIllegal(ULONG port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_phaseChkFifo(ULONG port, unsigned char p_card) +static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card) { - ULONG xfercnt; + unsigned long xfercnt; PSCCB currSCCB; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4742,7 +4741,7 @@ static void FPT_phaseChkFifo(ULONG port, unsigned char p_card) * because of command complete or from a disconnect. * *---------------------------------------------------------------------*/ -static void FPT_phaseBusFree(ULONG port, unsigned char p_card) +static void FPT_phaseBusFree(unsigned long port, unsigned char p_card) { PSCCB currSCCB; @@ -4840,9 +4839,9 @@ static void FPT_phaseBusFree(ULONG port, unsigned char p_card) * Description: Load the Automation RAM with the defualt map values. * *---------------------------------------------------------------------*/ -static void FPT_autoLoadDefaultMap(ULONG p_port) +static void FPT_autoLoadDefaultMap(unsigned long p_port) { - ULONG map_addr; + unsigned long map_addr; ARAM_ACCESS(p_port); map_addr = p_port + hp_aramBase; @@ -4948,7 +4947,7 @@ static void FPT_autoLoadDefaultMap(ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_autoCmdCmplt(ULONG p_port, unsigned char p_card) +static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card) { PSCCB currSCCB; unsigned char status_byte; @@ -5163,7 +5162,7 @@ static void FPT_autoCmdCmplt(ULONG p_port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_dataXferProcessor(ULONG port, PSCCBcard pCurrCard) +static void FPT_dataXferProcessor(unsigned long port, PSCCBcard pCurrCard) { PSCCB currSCCB; @@ -5201,21 +5200,21 @@ static void FPT_dataXferProcessor(ULONG port, PSCCBcard pCurrCard) * Description: * *---------------------------------------------------------------------*/ -static void FPT_busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB) +static void FPT_busMstrSGDataXferStart(unsigned long p_port, PSCCB pcurrSCCB) { - ULONG count,addr,tmpSGCnt; + unsigned long count,addr,tmpSGCnt; unsigned int sg_index; unsigned char sg_count, i; - ULONG reg_offset; + unsigned long reg_offset; if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { - count = ((ULONG) HOST_RD_CMD)<<24; + count = ((unsigned long) HOST_RD_CMD)<<24; } else { - count = ((ULONG) HOST_WRT_CMD)<<24; + count = ((unsigned long) HOST_WRT_CMD)<<24; } sg_count = 0; @@ -5230,15 +5229,15 @@ static void FPT_busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB) WR_HARPOON(p_port+hp_page_ctrl, i); while ((sg_count < (unsigned char)SG_BUF_CNT) && - ((ULONG)(sg_index * (unsigned int)SG_ELEMENT_SIZE) < pcurrSCCB->DataLength) ) { + ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) < pcurrSCCB->DataLength) ) { - tmpSGCnt += *(((ULONG *)pcurrSCCB->DataPointer)+ + tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer)+ (sg_index * 2)); - count |= *(((ULONG *)pcurrSCCB->DataPointer)+ + count |= *(((unsigned long *)pcurrSCCB->DataPointer)+ (sg_index * 2)); - addr = *(((ULONG *)pcurrSCCB->DataPointer)+ + addr = *(((unsigned long *)pcurrSCCB->DataPointer)+ ((sg_index * 2) + 1)); @@ -5306,15 +5305,15 @@ static void FPT_busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB) * Description: * *---------------------------------------------------------------------*/ -static void FPT_busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB) +static void FPT_busMstrDataXferStart(unsigned long p_port, PSCCB pcurrSCCB) { - ULONG addr,count; + unsigned long addr,count; if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) { count = pcurrSCCB->Sccb_XferCnt; - addr = (ULONG) pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC; + addr = (unsigned long) pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC; } else { @@ -5359,9 +5358,9 @@ static void FPT_busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB) * command busy is also time out, it'll just give up. * *---------------------------------------------------------------------*/ -static unsigned char FPT_busMstrTimeOut(ULONG p_port) +static unsigned char FPT_busMstrTimeOut(unsigned long p_port) { - ULONG timeout; + unsigned long timeout; timeout = LONG_WAIT; @@ -5397,11 +5396,11 @@ static unsigned char FPT_busMstrTimeOut(ULONG p_port) * Description: Abort any in progress transfer. * *---------------------------------------------------------------------*/ -static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrSCCB) +static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, PSCCB pCurrSCCB) { - ULONG timeout; - ULONG remain_cnt; + unsigned long timeout; + unsigned long remain_cnt; unsigned int sg_ptr; FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT; @@ -5464,10 +5463,10 @@ static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrS sg_ptr--; - if (remain_cnt > (ULONG)(*(((ULONG *)pCurrSCCB-> + if (remain_cnt > (unsigned long)(*(((unsigned long *)pCurrSCCB-> DataPointer) + (sg_ptr * 2)))) { - remain_cnt -= (ULONG)(*(((ULONG *)pCurrSCCB-> + remain_cnt -= (unsigned long)(*(((unsigned long *)pCurrSCCB-> DataPointer) + (sg_ptr * 2))); } @@ -5487,7 +5486,7 @@ static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrS pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr; - if ((ULONG)(sg_ptr * SG_ELEMENT_SIZE) == pCurrSCCB->DataLength + if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) == pCurrSCCB->DataLength && (remain_cnt == 0)) pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; @@ -5624,7 +5623,7 @@ static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrS pCurrSCCB->Sccb_SGoffset = 0x00; - if ((ULONG)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >= + if ((unsigned long)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >= pCurrSCCB->DataLength) { pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; @@ -5657,9 +5656,9 @@ static void FPT_hostDataXferAbort(ULONG port, unsigned char p_card, PSCCB pCurrS *---------------------------------------------------------------------*/ static void FPT_hostDataXferRestart(PSCCB currSCCB) { - ULONG data_count; + unsigned long data_count; unsigned int sg_index; - ULONG *sg_ptr; + unsigned long *sg_ptr; if (currSCCB->Sccb_XferState & F_SG_XFER) { @@ -5668,7 +5667,7 @@ static void FPT_hostDataXferRestart(PSCCB currSCCB) sg_index = 0xffff; /*Index by long words into sg list. */ data_count = 0; /*Running count of SG xfer counts. */ - sg_ptr = (ULONG *)currSCCB->DataPointer; + sg_ptr = (unsigned long *)currSCCB->DataPointer; while (data_count < currSCCB->Sccb_ATC) { @@ -5708,7 +5707,7 @@ static void FPT_scini(unsigned char p_card, unsigned char p_our_id, unsigned cha { unsigned char loser,assigned_id; - ULONG p_port; + unsigned long p_port; unsigned char i,k,ScamFlg ; PSCCBcard currCard; @@ -5900,7 +5899,7 @@ static void FPT_scini(unsigned char p_card, unsigned char p_our_id, unsigned cha * *---------------------------------------------------------------------*/ -static int FPT_scarb(ULONG p_port, unsigned char p_sel_type) +static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type) { if (p_sel_type == INIT_SELTD) { @@ -5961,7 +5960,7 @@ static int FPT_scarb(ULONG p_port, unsigned char p_sel_type) * *---------------------------------------------------------------------*/ -static void FPT_scbusf(ULONG p_port) +static void FPT_scbusf(unsigned long p_port) { WR_HARPOON(p_port+hp_page_ctrl, (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)); @@ -5997,7 +5996,7 @@ static void FPT_scbusf(ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_scasid(unsigned char p_card, ULONG p_port) +static void FPT_scasid(unsigned char p_card, unsigned long p_port) { unsigned char temp_id_string[ID_STRING_LENGTH]; @@ -6085,7 +6084,7 @@ static void FPT_scasid(unsigned char p_card, ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_scsel(ULONG p_port) +static void FPT_scsel(unsigned long p_port) { WR_HARPOON(p_port+hp_scsisig, SCSI_SEL); @@ -6119,7 +6118,7 @@ static void FPT_scsel(ULONG p_port) * *---------------------------------------------------------------------*/ -static unsigned char FPT_scxferc(ULONG p_port, unsigned char p_data) +static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data) { unsigned char curr_data, ret_data; @@ -6170,7 +6169,7 @@ static unsigned char FPT_scxferc(ULONG p_port, unsigned char p_data) * *---------------------------------------------------------------------*/ -static unsigned char FPT_scsendi(ULONG p_port, unsigned char p_id_string[]) +static unsigned char FPT_scsendi(unsigned long p_port, unsigned char p_id_string[]) { unsigned char ret_data,byte_cnt,bit_cnt,defer; @@ -6223,7 +6222,7 @@ static unsigned char FPT_scsendi(ULONG p_port, unsigned char p_id_string[]) * *---------------------------------------------------------------------*/ -static unsigned char FPT_sciso(ULONG p_port, unsigned char p_id_string[]) +static unsigned char FPT_sciso(unsigned long p_port, unsigned char p_id_string[]) { unsigned char ret_data,the_data,byte_cnt,bit_cnt; @@ -6284,7 +6283,7 @@ static unsigned char FPT_sciso(ULONG p_port, unsigned char p_id_string[]) * *---------------------------------------------------------------------*/ -static void FPT_scwirod(ULONG p_port, unsigned char p_data_bit) +static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit) { unsigned char i; @@ -6313,7 +6312,7 @@ static void FPT_scwirod(ULONG p_port, unsigned char p_data_bit) * *---------------------------------------------------------------------*/ -static void FPT_scwiros(ULONG p_port, unsigned char p_data_bit) +static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit) { unsigned char i; @@ -6367,9 +6366,9 @@ static unsigned char FPT_scvalq(unsigned char p_quintet) * *---------------------------------------------------------------------*/ -static unsigned char FPT_scsell(ULONG p_port, unsigned char targ_id) +static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id) { - ULONG i; + unsigned long i; WR_HARPOON(p_port+hp_page_ctrl, (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)); @@ -6446,7 +6445,7 @@ static unsigned char FPT_scsell(ULONG p_port, unsigned char targ_id) * *---------------------------------------------------------------------*/ -static void FPT_scwtsel(ULONG p_port) +static void FPT_scwtsel(unsigned long p_port) { while(!(RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) {} } @@ -6460,7 +6459,7 @@ static void FPT_scwtsel(ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_inisci(unsigned char p_card, ULONG p_port, unsigned char p_our_id) +static void FPT_inisci(unsigned char p_card, unsigned long p_port, unsigned char p_our_id) { unsigned char i,k,max_id; unsigned short ee_data; @@ -6653,7 +6652,7 @@ static unsigned char FPT_scmachid(unsigned char p_card, unsigned char p_id_strin * *---------------------------------------------------------------------*/ -static void FPT_scsavdi(unsigned char p_card, ULONG p_port) +static void FPT_scsavdi(unsigned char p_card, unsigned long p_port) { unsigned char i,k,max_id; unsigned short ee_data,sum_data; @@ -6702,7 +6701,7 @@ static void FPT_scsavdi(unsigned char p_card, ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_XbowInit(ULONG port, unsigned char ScamFlg) +static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg) { unsigned char i; @@ -6752,7 +6751,7 @@ unsigned char i; * *---------------------------------------------------------------------*/ -static void FPT_BusMasterInit(ULONG p_port) +static void FPT_BusMasterInit(unsigned long p_port) { @@ -6783,7 +6782,7 @@ static void FPT_BusMasterInit(ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_DiagEEPROM(ULONG p_port) +static void FPT_DiagEEPROM(unsigned long p_port) { unsigned short index,temp,max_wd_cnt; @@ -7416,9 +7415,9 @@ static unsigned char FPT_queueFindSccb(PSCCB p_SCCB, unsigned char p_card) static void FPT_utilUpdateResidual(PSCCB p_SCCB) { - ULONG partial_cnt; + unsigned long partial_cnt; unsigned int sg_index; - ULONG *sg_ptr; + unsigned long *sg_ptr; if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) { @@ -7431,7 +7430,7 @@ static void FPT_utilUpdateResidual(PSCCB p_SCCB) sg_index = p_SCCB->Sccb_sgseg; - sg_ptr = (ULONG *)p_SCCB->DataPointer; + sg_ptr = (unsigned long *)p_SCCB->DataPointer; if (p_SCCB->Sccb_SGoffset) { @@ -7439,7 +7438,7 @@ static void FPT_utilUpdateResidual(PSCCB p_SCCB) sg_index++; } - while ( ((ULONG)sg_index * (ULONG)SG_ELEMENT_SIZE) < + while ( ((unsigned long)sg_index * (unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength ) { partial_cnt += *(sg_ptr+(sg_index * 2)); @@ -7464,7 +7463,7 @@ static void FPT_utilUpdateResidual(PSCCB p_SCCB) * *---------------------------------------------------------------------*/ -static void FPT_Wait1Second(ULONG p_port) +static void FPT_Wait1Second(unsigned long p_port) { unsigned char i; @@ -7489,7 +7488,7 @@ static void FPT_Wait1Second(ULONG p_port) * *---------------------------------------------------------------------*/ -static void FPT_Wait(ULONG p_port, unsigned char p_delay) +static void FPT_Wait(unsigned long p_port, unsigned char p_delay) { unsigned char old_timer; unsigned char green_flag; @@ -7537,7 +7536,7 @@ static void FPT_Wait(ULONG p_port, unsigned char p_delay) * *---------------------------------------------------------------------*/ -static void FPT_utilEEWriteOnOff(ULONG p_port,unsigned char p_mode) +static void FPT_utilEEWriteOnOff(unsigned long p_port,unsigned char p_mode) { unsigned char ee_value; @@ -7566,7 +7565,7 @@ static void FPT_utilEEWriteOnOff(ULONG p_port,unsigned char p_mode) * *---------------------------------------------------------------------*/ -static void FPT_utilEEWrite(ULONG p_port, unsigned short ee_data, unsigned short ee_addr) +static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data, unsigned short ee_addr) { unsigned char ee_value; @@ -7617,7 +7616,7 @@ static void FPT_utilEEWrite(ULONG p_port, unsigned short ee_data, unsigned short * *---------------------------------------------------------------------*/ -static unsigned short FPT_utilEERead(ULONG p_port, unsigned short ee_addr) +static unsigned short FPT_utilEERead(unsigned long p_port, unsigned short ee_addr) { unsigned short i, ee_data1, ee_data2; @@ -7647,7 +7646,7 @@ static unsigned short FPT_utilEERead(ULONG p_port, unsigned short ee_addr) * *---------------------------------------------------------------------*/ -static unsigned short FPT_utilEEReadOrg(ULONG p_port, unsigned short ee_addr) +static unsigned short FPT_utilEEReadOrg(unsigned long p_port, unsigned short ee_addr) { unsigned char ee_value; @@ -7695,7 +7694,7 @@ static unsigned short FPT_utilEEReadOrg(ULONG p_port, unsigned short ee_addr) * *---------------------------------------------------------------------*/ -static void FPT_utilEESendCmdAddr(ULONG p_port, unsigned char ee_cmd, unsigned short ee_addr) +static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd, unsigned short ee_addr) { unsigned char ee_value; unsigned char narrow_flg; -- cgit v1.2.3-59-g8ed1b From fd1e29ed62cc307281d1a62f73ebac059ac6b6a1 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:27 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: remove ushort_ptr Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index d877a6a12aca..6089af003130 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -42,7 +42,6 @@ -typedef unsigned short * ushort_ptr; #define s08bits char @@ -6003,7 +6002,7 @@ static void FPT_scasid(unsigned char p_card, unsigned long p_port) unsigned char i,k,scam_id; unsigned char crcBytes[3]; PNVRamInfo pCurrNvRam; - ushort_ptr pCrcBytes; + unsigned short * pCrcBytes; pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo; @@ -6023,7 +6022,7 @@ static void FPT_scasid(unsigned char p_card, unsigned long p_port) if (!(FPT_sciso(p_port,&temp_id_string[0]))) { if(pCurrNvRam){ - pCrcBytes = (ushort_ptr)&crcBytes[0]; + pCrcBytes = (unsigned short *)&crcBytes[0]; *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]); crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]); temp_id_string[1] = crcBytes[2]; -- cgit v1.2.3-59-g8ed1b From ad0e1d9f0155073cffb74755fb21c0fb82b1b094 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:28 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: use standard fixed size types Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 6089af003130..022a4c0da7e1 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -44,13 +44,7 @@ -#define s08bits char -#define s16bits short -#define s32bits long -#define u08bits unsigned s08bits -#define u16bits unsigned s16bits -#define u32bits unsigned s32bits @@ -245,12 +239,12 @@ typedef struct _SCCB { #define SG_ELEMENT_SIZE 8 /*Eight byte per element. */ -#define RD_HARPOON(ioport) inb((u32bits)ioport) -#define RDW_HARPOON(ioport) inw((u32bits)ioport) -#define RD_HARP32(ioport,offset,data) (data = inl((u32bits)(ioport + offset))) -#define WR_HARPOON(ioport,val) outb((u08bits) val, (u32bits)ioport) -#define WRW_HARPOON(ioport,val) outw((u16bits)val, (u32bits)ioport) -#define WR_HARP32(ioport,offset,data) outl(data, (u32bits)(ioport + offset)) +#define RD_HARPOON(ioport) inb((u32)ioport) +#define RDW_HARPOON(ioport) inw((u32)ioport) +#define RD_HARP32(ioport,offset,data) (data = inl((u32)(ioport + offset))) +#define WR_HARPOON(ioport,val) outb((u8) val, (u32)ioport) +#define WRW_HARPOON(ioport,val) outw((u16)val, (u32)ioport) +#define WR_HARP32(ioport,offset,data) outl(data, (u32)(ioport + offset)) #define TAR_SYNC_MASK (BIT(7)+BIT(6)) -- cgit v1.2.3-59-g8ed1b From 69eb2ea47793366f59bfbc6e3c655b9c5047badd Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:29 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: untypedef struct _SCCB * struct _SCCB => struct sccb * PSCCB => struct sccb * * SCCB => struct sccb Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 143 +++++++++++++++++++++++----------------------- 1 file changed, 71 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 022a4c0da7e1..88b7da371399 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -53,9 +53,8 @@ - -typedef struct _SCCB *PSCCB; -typedef void (*CALL_BK_FN)(PSCCB); +struct sccb; +typedef void (*CALL_BK_FN)(struct sccb *); typedef struct SCCBMgr_info { @@ -110,7 +109,7 @@ typedef SCCBMGR_INFO * PSCCBMGR_INFO; #pragma pack(1) -typedef struct _SCCB { +struct sccb { unsigned char OperationCode; unsigned char ControlByte; unsigned char CdbLength; @@ -146,14 +145,14 @@ typedef struct _SCCB { unsigned char Sccb_tag; unsigned char Sccb_scsistat; unsigned char Sccb_idmsg; /* image of last msg in */ - PSCCB Sccb_forwardlink; - PSCCB Sccb_backlink; + struct sccb * Sccb_forwardlink; + struct sccb * Sccb_backlink; unsigned long Sccb_savedATC; unsigned char Save_Cdb[6]; unsigned char Save_CdbLen; unsigned char Sccb_XferState; unsigned long Sccb_SGoffset; - } SCCB; + }; #pragma pack() @@ -275,8 +274,8 @@ typedef struct SCCBMgr_tar_info *PSCCBMgr_tar_info; typedef struct SCCBMgr_tar_info { - PSCCB TarSelQ_Head; - PSCCB TarSelQ_Tail; + struct sccb * TarSelQ_Head; + struct sccb * TarSelQ_Tail; unsigned char TarLUN_CA; /*Contingent Allgiance */ unsigned char TarTagQ_Cnt; unsigned char TarSelQ_Cnt; @@ -309,7 +308,7 @@ typedef NVRAMINFO *PNVRamInfo; typedef struct SCCBcard { - PSCCB currentSCCB; + struct sccb * currentSCCB; PSCCBMGR_INFO cardInfo; unsigned long ioPort; @@ -322,7 +321,7 @@ typedef struct SCCBcard { unsigned char globalFlags; unsigned char ourId; PNVRamInfo pNvRamInfo; - PSCCB discQ_Tbl[QUEUE_DEPTH]; + struct sccb * discQ_Tbl[QUEUE_DEPTH]; }SCCBCARD; @@ -973,7 +972,7 @@ typedef struct SCCBscam_info { static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, unsigned char syncFlag); static void FPT_ssel(unsigned long port, unsigned char p_card); static void FPT_sres(unsigned long port, unsigned char p_card, PSCCBcard pCurrCard); -static void FPT_shandem(unsigned long port, unsigned char p_card,PSCCB pCurrSCCB); +static void FPT_shandem(unsigned long port, unsigned char p_card,struct sccb * pCurrSCCB); static void FPT_stsyncn(unsigned long port, unsigned char p_card); static void FPT_sisyncr(unsigned long port,unsigned char sync_pulse, unsigned char offset); static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, unsigned char p_sync_value, @@ -989,7 +988,7 @@ static void FPT_SendMsg(unsigned long port, unsigned char message); static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg, unsigned char error_code); -static void FPT_sinits(PSCCB p_sccb, unsigned char p_card); +static void FPT_sinits(struct sccb * p_sccb, unsigned char p_card); static void FPT_RNVRamData(PNVRamInfo pNvRamInfo); static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card); @@ -998,14 +997,14 @@ static void FPT_siwidr(unsigned long port, unsigned char width); static void FPT_queueSelectFail(PSCCBcard pCurrCard, unsigned char p_card); -static void FPT_queueDisconnect(PSCCB p_SCCB, unsigned char p_card); -static void FPT_queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_SCCB, +static void FPT_queueDisconnect(struct sccb * p_SCCB, unsigned char p_card); +static void FPT_queueCmdComplete(PSCCBcard pCurrCard, struct sccb * p_SCCB, unsigned char p_card); static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card); static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code); -static void FPT_queueAddSccb(PSCCB p_SCCB, unsigned char card); -static unsigned char FPT_queueFindSccb(PSCCB p_SCCB, unsigned char p_card); -static void FPT_utilUpdateResidual(PSCCB p_SCCB); +static void FPT_queueAddSccb(struct sccb * p_SCCB, unsigned char card); +static unsigned char FPT_queueFindSccb(struct sccb * p_SCCB, unsigned char p_card); +static void FPT_utilUpdateResidual(struct sccb * p_SCCB); static unsigned short FPT_CalcCrc16(unsigned char buffer[]); static unsigned char FPT_CalcLrc(unsigned char buffer[]); @@ -1043,10 +1042,10 @@ static void FPT_DiagEEPROM(unsigned long p_port); static void FPT_dataXferProcessor(unsigned long port, PSCCBcard pCurrCard); -static void FPT_busMstrSGDataXferStart(unsigned long port, PSCCB pCurrSCCB); -static void FPT_busMstrDataXferStart(unsigned long port, PSCCB pCurrSCCB); -static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, PSCCB pCurrSCCB); -static void FPT_hostDataXferRestart(PSCCB currSCCB); +static void FPT_busMstrSGDataXferStart(unsigned long port, struct sccb * pCurrSCCB); +static void FPT_busMstrDataXferStart(unsigned long port, struct sccb * pCurrSCCB); +static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, struct sccb * pCurrSCCB); +static void FPT_hostDataXferRestart(struct sccb * currSCCB); static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, unsigned char p_card, @@ -1667,11 +1666,11 @@ static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort) * callback function. * *---------------------------------------------------------------------*/ -static void FlashPoint_StartCCB(unsigned long pCurrCard, PSCCB p_Sccb) +static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb * p_Sccb) { unsigned long ioport; unsigned char thisCard, lun; - PSCCB pSaveSccb; + struct sccb * pSaveSccb; CALL_BK_FN callback; thisCard = ((PSCCBcard) pCurrCard)->cardIndex; @@ -1787,14 +1786,14 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, PSCCB p_Sccb) * callback function. * *---------------------------------------------------------------------*/ -static int FlashPoint_AbortCCB(unsigned long pCurrCard, PSCCB p_Sccb) +static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb * p_Sccb) { unsigned long ioport; unsigned char thisCard; CALL_BK_FN callback; unsigned char TID; - PSCCB pSaveSCCB; + struct sccb * pSaveSCCB; PSCCBMgr_tar_info currTar_Info; @@ -1916,7 +1915,7 @@ static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard) *---------------------------------------------------------------------*/ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) { - PSCCB currSCCB; + struct sccb * currSCCB; unsigned char thisCard,result,bm_status, bm_int_st; unsigned short hp_int; unsigned char i, target; @@ -2417,7 +2416,7 @@ static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char targe * *---------------------------------------------------------------------*/ -static unsigned char FPT_sfm(unsigned long port, PSCCB pCurrSCCB) +static unsigned char FPT_sfm(unsigned long port, struct sccb * pCurrSCCB) { unsigned char message; unsigned short TimeOutLoop; @@ -2497,7 +2496,7 @@ static void FPT_ssel(unsigned long port, unsigned char p_card) unsigned long cdb_reg; PSCCBcard CurrCard; - PSCCB currSCCB; + struct sccb * currSCCB; PSCCBMgr_tar_info currTar_Info; unsigned char lastTag, lun; @@ -2808,7 +2807,7 @@ static void FPT_sres(unsigned long port, unsigned char p_card, PSCCBcard pCurrCa PSCCBMgr_tar_info currTar_Info; - PSCCB currSCCB; + struct sccb * currSCCB; @@ -3113,7 +3112,7 @@ static void FPT_SendMsg(unsigned long port, unsigned char message) *---------------------------------------------------------------------*/ static void FPT_sdecm(unsigned char message, unsigned long port, unsigned char p_card) { - PSCCB currSCCB; + struct sccb * currSCCB; PSCCBcard CurrCard; PSCCBMgr_tar_info currTar_Info; @@ -3290,7 +3289,7 @@ static void FPT_sdecm(unsigned char message, unsigned long port, unsigned char p * Description: Decide what to do with the extended message. * *---------------------------------------------------------------------*/ -static void FPT_shandem(unsigned long port, unsigned char p_card, PSCCB pCurrSCCB) +static void FPT_shandem(unsigned long port, unsigned char p_card, struct sccb * pCurrSCCB) { unsigned char length,message; @@ -3371,7 +3370,7 @@ static void FPT_shandem(unsigned long port, unsigned char p_card, PSCCB pCurrSCC static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, unsigned char syncFlag) { - PSCCB currSCCB; + struct sccb * currSCCB; PSCCBMgr_tar_info currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -3447,7 +3446,7 @@ static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, unsig static void FPT_stsyncn(unsigned long port, unsigned char p_card) { unsigned char sync_msg,offset,sync_reg,our_sync_msg; - PSCCB currSCCB; + struct sccb * currSCCB; PSCCBMgr_tar_info currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -3609,7 +3608,7 @@ static void FPT_sisyncr(unsigned long port,unsigned char sync_pulse, unsigned ch static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card) { - PSCCB currSCCB; + struct sccb * currSCCB; PSCCBMgr_tar_info currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -3662,7 +3661,7 @@ static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card) static void FPT_stwidn(unsigned long port, unsigned char p_card) { unsigned char width; - PSCCB currSCCB; + struct sccb * currSCCB; PSCCBMgr_tar_info currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -3916,7 +3915,7 @@ static void FPT_sresb(unsigned long port, unsigned char p_card) static void FPT_ssenss(PSCCBcard pCurrCard) { unsigned char i; - PSCCB currSCCB; + struct sccb * currSCCB; currSCCB = pCurrCard->currentSCCB; @@ -4049,7 +4048,7 @@ static void FPT_schkdd(unsigned long port, unsigned char p_card) unsigned short TimeOutLoop; unsigned char sPhase; - PSCCB currSCCB; + struct sccb * currSCCB; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4157,7 +4156,7 @@ static void FPT_schkdd(unsigned long port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_sinits(PSCCB p_sccb, unsigned char p_card) +static void FPT_sinits(struct sccb * p_sccb, unsigned char p_card) { PSCCBMgr_tar_info currTar_Info; @@ -4265,7 +4264,7 @@ static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card) static void FPT_phaseDataOut(unsigned long port, unsigned char p_card) { - PSCCB currSCCB; + struct sccb * currSCCB; currSCCB = FPT_BL_Card[p_card].currentSCCB; if (currSCCB == NULL) @@ -4309,7 +4308,7 @@ static void FPT_phaseDataOut(unsigned long port, unsigned char p_card) static void FPT_phaseDataIn(unsigned long port, unsigned char p_card) { - PSCCB currSCCB; + struct sccb * currSCCB; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4355,7 +4354,7 @@ static void FPT_phaseDataIn(unsigned long port, unsigned char p_card) static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card) { - PSCCB currSCCB; + struct sccb * currSCCB; unsigned long cdb_reg; unsigned char i; @@ -4430,7 +4429,7 @@ static void FPT_phaseStatus(unsigned long port, unsigned char p_card) static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card) { unsigned char message,scsiID; - PSCCB currSCCB; + struct sccb * currSCCB; PSCCBMgr_tar_info currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4578,7 +4577,7 @@ static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card) static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card) { unsigned char message; - PSCCB currSCCB; + struct sccb * currSCCB; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4630,7 +4629,7 @@ static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card) static void FPT_phaseIllegal(unsigned long port, unsigned char p_card) { - PSCCB currSCCB; + struct sccb * currSCCB; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4659,7 +4658,7 @@ static void FPT_phaseIllegal(unsigned long port, unsigned char p_card) static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card) { unsigned long xfercnt; - PSCCB currSCCB; + struct sccb * currSCCB; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4736,7 +4735,7 @@ static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card) *---------------------------------------------------------------------*/ static void FPT_phaseBusFree(unsigned long port, unsigned char p_card) { - PSCCB currSCCB; + struct sccb * currSCCB; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4942,7 +4941,7 @@ static void FPT_autoLoadDefaultMap(unsigned long p_port) static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card) { - PSCCB currSCCB; + struct sccb * currSCCB; unsigned char status_byte; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -5157,7 +5156,7 @@ static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card) static void FPT_dataXferProcessor(unsigned long port, PSCCBcard pCurrCard) { - PSCCB currSCCB; + struct sccb * currSCCB; currSCCB = pCurrCard->currentSCCB; @@ -5193,7 +5192,7 @@ static void FPT_dataXferProcessor(unsigned long port, PSCCBcard pCurrCard) * Description: * *---------------------------------------------------------------------*/ -static void FPT_busMstrSGDataXferStart(unsigned long p_port, PSCCB pcurrSCCB) +static void FPT_busMstrSGDataXferStart(unsigned long p_port, struct sccb * pcurrSCCB) { unsigned long count,addr,tmpSGCnt; unsigned int sg_index; @@ -5298,7 +5297,7 @@ static void FPT_busMstrSGDataXferStart(unsigned long p_port, PSCCB pcurrSCCB) * Description: * *---------------------------------------------------------------------*/ -static void FPT_busMstrDataXferStart(unsigned long p_port, PSCCB pcurrSCCB) +static void FPT_busMstrDataXferStart(unsigned long p_port, struct sccb * pcurrSCCB) { unsigned long addr,count; @@ -5389,7 +5388,7 @@ static unsigned char FPT_busMstrTimeOut(unsigned long p_port) * Description: Abort any in progress transfer. * *---------------------------------------------------------------------*/ -static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, PSCCB pCurrSCCB) +static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, struct sccb * pCurrSCCB) { unsigned long timeout; @@ -5647,7 +5646,7 @@ static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, PSCC * pointers message. * *---------------------------------------------------------------------*/ -static void FPT_hostDataXferRestart(PSCCB currSCCB) +static void FPT_hostDataXferRestart(struct sccb * currSCCB) { unsigned long data_count; unsigned int sg_index; @@ -6939,7 +6938,7 @@ static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card) { unsigned char scan_ptr, lun; PSCCBMgr_tar_info currTar_Info; - PSCCB pOldSccb; + struct sccb * pOldSccb; scan_ptr = pCurrCard->scanIndex; do @@ -6967,22 +6966,22 @@ static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card) (lun != pCurrCard->currentSCCB->Lun)) { pOldSccb = pCurrCard->currentSCCB; - pCurrCard->currentSCCB = (PSCCB)(pCurrCard->currentSCCB)-> + pCurrCard->currentSCCB = (struct sccb *)(pCurrCard->currentSCCB)-> Sccb_forwardlink; } if(pCurrCard->currentSCCB == NULL) continue; if(pOldSccb != NULL) { - pOldSccb->Sccb_forwardlink = (PSCCB)(pCurrCard->currentSCCB)-> + pOldSccb->Sccb_forwardlink = (struct sccb *)(pCurrCard->currentSCCB)-> Sccb_forwardlink; - pOldSccb->Sccb_backlink = (PSCCB)(pCurrCard->currentSCCB)-> + pOldSccb->Sccb_backlink = (struct sccb *)(pCurrCard->currentSCCB)-> Sccb_backlink; currTar_Info->TarSelQ_Cnt--; } else { - currTar_Info->TarSelQ_Head = (PSCCB)(pCurrCard->currentSCCB)->Sccb_forwardlink; + currTar_Info->TarSelQ_Head = (struct sccb *)(pCurrCard->currentSCCB)->Sccb_forwardlink; if (currTar_Info->TarSelQ_Head == NULL) { @@ -6992,7 +6991,7 @@ static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card) else { currTar_Info->TarSelQ_Cnt--; - currTar_Info->TarSelQ_Head->Sccb_backlink = (PSCCB)NULL; + currTar_Info->TarSelQ_Head->Sccb_backlink = (struct sccb *)NULL; } } pCurrCard->scanIndex = scan_ptr; @@ -7021,7 +7020,7 @@ static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card) pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head; - currTar_Info->TarSelQ_Head = (PSCCB)(pCurrCard->currentSCCB)->Sccb_forwardlink; + currTar_Info->TarSelQ_Head = (struct sccb *)(pCurrCard->currentSCCB)->Sccb_forwardlink; if (currTar_Info->TarSelQ_Head == NULL) { @@ -7031,7 +7030,7 @@ static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card) else { currTar_Info->TarSelQ_Cnt--; - currTar_Info->TarSelQ_Head->Sccb_backlink = (PSCCB)NULL; + currTar_Info->TarSelQ_Head->Sccb_backlink = (struct sccb *)NULL; } scan_ptr++; @@ -7073,10 +7072,10 @@ static void FPT_queueSelectFail(PSCCBcard pCurrCard, unsigned char p_card) if (pCurrCard->currentSCCB != NULL) { - thisTarg = (unsigned char)(((PSCCB)(pCurrCard->currentSCCB))->TargID); + thisTarg = (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->TargID); currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; - pCurrCard->currentSCCB->Sccb_backlink = (PSCCB)NULL; + pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL; pCurrCard->currentSCCB->Sccb_forwardlink = currTar_Info->TarSelQ_Head; @@ -7105,7 +7104,7 @@ static void FPT_queueSelectFail(PSCCBcard pCurrCard, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, +static void FPT_queueCmdComplete(PSCCBcard pCurrCard, struct sccb * p_sccb, unsigned char p_card) { @@ -7207,7 +7206,7 @@ static void FPT_queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, * Description: Add SCCB to our disconnect array. * *---------------------------------------------------------------------*/ -static void FPT_queueDisconnect(PSCCB p_sccb, unsigned char p_card) +static void FPT_queueDisconnect(struct sccb * p_sccb, unsigned char p_card) { PSCCBMgr_tar_info currTar_Info; @@ -7245,7 +7244,7 @@ static void FPT_queueDisconnect(PSCCB p_sccb, unsigned char p_card) static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code) { unsigned char qtag,thisTarg; - PSCCB currSCCB; + struct sccb * currSCCB; PSCCBMgr_tar_info currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -7311,7 +7310,7 @@ static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg -static void FPT_queueAddSccb(PSCCB p_SCCB, unsigned char p_card) +static void FPT_queueAddSccb(struct sccb * p_SCCB, unsigned char p_card) { PSCCBMgr_tar_info currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID]; @@ -7345,9 +7344,9 @@ static void FPT_queueAddSccb(PSCCB p_SCCB, unsigned char p_card) * *---------------------------------------------------------------------*/ -static unsigned char FPT_queueFindSccb(PSCCB p_SCCB, unsigned char p_card) +static unsigned char FPT_queueFindSccb(struct sccb * p_SCCB, unsigned char p_card) { - PSCCB q_ptr; + struct sccb * q_ptr; PSCCBMgr_tar_info currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID]; @@ -7406,7 +7405,7 @@ static unsigned char FPT_queueFindSccb(PSCCB p_SCCB, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_utilUpdateResidual(PSCCB p_SCCB) +static void FPT_utilUpdateResidual(struct sccb * p_SCCB) { unsigned long partial_cnt; unsigned int sg_index; @@ -7809,14 +7808,14 @@ FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle) static inline void FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle, struct BusLogic_CCB *CCB) { - FlashPoint_StartCCB(CardHandle, (PSCCB) CCB); + FlashPoint_StartCCB(CardHandle, (struct sccb *) CCB); } static inline void FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle, struct BusLogic_CCB *CCB) { - FlashPoint_AbortCCB(CardHandle, (PSCCB) CCB); + FlashPoint_AbortCCB(CardHandle, (struct sccb *) CCB); } -- cgit v1.2.3-59-g8ed1b From 7f101662dd55aa16852ff6228ac496f56a259f5e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:30 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: untypedef struct SCCBMgr_info * struct SCCBMgr_info => struct sccb_mgr_info * PSCCBMGR_INFO => struct sccb_mgr_info * * SCCBMGR_INFO => struct sccb_mgr_info Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 88b7da371399..9969fef8fd52 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -57,7 +57,7 @@ struct sccb; typedef void (*CALL_BK_FN)(struct sccb *); -typedef struct SCCBMgr_info { +struct sccb_mgr_info { unsigned long si_baseaddr; unsigned char si_present; unsigned char si_intvect; @@ -79,9 +79,8 @@ typedef struct SCCBMgr_info { unsigned char si_XlatInfo[4]; unsigned long si_reserved2[5]; unsigned long si_secondary_range; -} SCCBMGR_INFO; +}; -typedef SCCBMGR_INFO * PSCCBMGR_INFO; #define SCSI_PARITY_ENA 0x0001 @@ -309,7 +308,7 @@ typedef NVRAMINFO *PNVRamInfo; typedef struct SCCBcard { struct sccb * currentSCCB; - PSCCBMGR_INFO cardInfo; + struct sccb_mgr_info * cardInfo; unsigned long ioPort; @@ -1108,7 +1107,7 @@ static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char)= { 0 }; * *---------------------------------------------------------------------*/ -static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) +static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info * pCardInfo) { static unsigned char first_time = 1; @@ -1386,7 +1385,7 @@ static int FlashPoint_ProbeHostAdapter(PSCCBMGR_INFO pCardInfo) * *---------------------------------------------------------------------*/ -static unsigned long FlashPoint_HardwareResetHostAdapter(PSCCBMGR_INFO pCardInfo) +static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info * pCardInfo) { PSCCBcard CurrCard = NULL; PNVRamInfo pCurrNvRam; @@ -7788,14 +7787,14 @@ static unsigned char FPT_CalcLrc(unsigned char buffer[]) static inline unsigned char FlashPoint__ProbeHostAdapter(struct FlashPoint_Info *FlashPointInfo) { - return FlashPoint_ProbeHostAdapter((PSCCBMGR_INFO) FlashPointInfo); + return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *) FlashPointInfo); } static inline FlashPoint_CardHandle_T FlashPoint__HardwareResetHostAdapter(struct FlashPoint_Info *FlashPointInfo) { - return FlashPoint_HardwareResetHostAdapter((PSCCBMGR_INFO) FlashPointInfo); + return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *) FlashPointInfo); } static inline void -- cgit v1.2.3-59-g8ed1b From f31dc0cde69761dca05687addfd233accd393d1c Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:31 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: untypedef struct SCCBMgr_tar_info * struct SCCBMgr_tar_info => struct sccb_mgr_tar_info * PSCCBMgr_tar_info => struct sccb_mgr_tar_info * * SCCBMGR_TAR_INFO => struct sccb_mgr_tar_info Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 53 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 9969fef8fd52..895e4ff7be1d 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -268,10 +268,9 @@ struct sccb { #define EE_WIDE_SCSI BIT(7) -typedef struct SCCBMgr_tar_info *PSCCBMgr_tar_info; -typedef struct SCCBMgr_tar_info { +struct sccb_mgr_tar_info { struct sccb * TarSelQ_Head; struct sccb * TarSelQ_Tail; @@ -284,7 +283,7 @@ typedef struct SCCBMgr_tar_info { unsigned char TarReserved[2]; /* for alignment */ unsigned char LunDiscQ_Idx[MAX_LUN]; unsigned char TarLUNBusy[MAX_LUN]; -} SCCBMGR_TAR_INFO; +}; typedef struct NVRAMInfo { unsigned char niModel; /* Model No. of card */ @@ -975,7 +974,7 @@ static void FPT_shandem(unsigned long port, unsigned char p_card,struct sccb * static void FPT_stsyncn(unsigned long port, unsigned char p_card); static void FPT_sisyncr(unsigned long port,unsigned char sync_pulse, unsigned char offset); static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, unsigned char p_sync_value, - PSCCBMgr_tar_info currTar_Info); + struct sccb_mgr_tar_info * currTar_Info); static void FPT_sresb(unsigned long port, unsigned char p_card); static void FPT_sxfrp(unsigned long p_port, unsigned char p_card); static void FPT_schkdd(unsigned long port, unsigned char p_card); @@ -1081,7 +1080,7 @@ static void FPT_autoLoadDefaultMap(unsigned long p_port); -static SCCBMGR_TAR_INFO FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } }; +static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } }; static SCCBCARD FPT_BL_Card[MAX_CARDS] = { { 0 } }; static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { { { 0 } } }; static NVRAMINFO FPT_nvRamInfo[MAX_MB_CARDS] = { { 0 } }; @@ -1793,7 +1792,7 @@ static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb * p_Sccb) CALL_BK_FN callback; unsigned char TID; struct sccb * pSaveSCCB; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; ioport = ((PSCCBcard) pCurrCard)->ioPort; @@ -2161,7 +2160,7 @@ static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, unsigned char p_c PSCCBcard pCurrCard, unsigned short p_int) { unsigned char temp, ScamFlg; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; PNVRamInfo pCurrNvRam; @@ -2373,7 +2372,7 @@ static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char targe { unsigned char lun, qtag; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][target]; @@ -2496,7 +2495,7 @@ static void FPT_ssel(unsigned long port, unsigned char p_card) unsigned long cdb_reg; PSCCBcard CurrCard; struct sccb * currSCCB; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; unsigned char lastTag, lun; CurrCard = &FPT_BL_Card[p_card]; @@ -2805,7 +2804,7 @@ static void FPT_sres(unsigned long port, unsigned char p_card, PSCCBcard pCurrCa unsigned char our_target, message, lun = 0, tag, msgRetryCount; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; struct sccb * currSCCB; @@ -3113,7 +3112,7 @@ static void FPT_sdecm(unsigned char message, unsigned long port, unsigned char p { struct sccb * currSCCB; PSCCBcard CurrCard; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; CurrCard = &FPT_BL_Card[p_card]; currSCCB = CurrCard->currentSCCB; @@ -3370,7 +3369,7 @@ static void FPT_shandem(unsigned long port, unsigned char p_card, struct sccb * static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, unsigned char syncFlag) { struct sccb * currSCCB; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; @@ -3446,7 +3445,7 @@ static void FPT_stsyncn(unsigned long port, unsigned char p_card) { unsigned char sync_msg,offset,sync_reg,our_sync_msg; struct sccb * currSCCB; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; @@ -3608,7 +3607,7 @@ static void FPT_sisyncr(unsigned long port,unsigned char sync_pulse, unsigned ch static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card) { struct sccb * currSCCB; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; @@ -3661,7 +3660,7 @@ static void FPT_stwidn(unsigned long port, unsigned char p_card) { unsigned char width; struct sccb * currSCCB; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; @@ -3767,7 +3766,7 @@ static void FPT_siwidr(unsigned long port, unsigned char width) * *---------------------------------------------------------------------*/ static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, unsigned char p_sync_value, - PSCCBMgr_tar_info currTar_Info) + struct sccb_mgr_tar_info * currTar_Info) { unsigned char index; @@ -3842,7 +3841,7 @@ static void FPT_sresb(unsigned long port, unsigned char p_card) { unsigned char scsiID, i; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; WR_HARPOON(port+hp_page_ctrl, (RD_HARPOON(port+hp_page_ctrl) | G_INT_DISABLE)); @@ -4157,7 +4156,7 @@ static void FPT_schkdd(unsigned long port, unsigned char p_card) static void FPT_sinits(struct sccb * p_sccb, unsigned char p_card) { - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; if((p_sccb->TargID > MAX_SCSI_TAR) || (p_sccb->Lun > MAX_LUN)) { @@ -4429,7 +4428,7 @@ static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card) { unsigned char message,scsiID; struct sccb * currSCCB; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -6936,7 +6935,7 @@ static void FPT_DiagEEPROM(unsigned long p_port) static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card) { unsigned char scan_ptr, lun; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; struct sccb * pOldSccb; scan_ptr = pCurrCard->scanIndex; @@ -7067,7 +7066,7 @@ static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card) static void FPT_queueSelectFail(PSCCBcard pCurrCard, unsigned char p_card) { unsigned char thisTarg; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; if (pCurrCard->currentSCCB != NULL) { @@ -7109,7 +7108,7 @@ static void FPT_queueCmdComplete(PSCCBcard pCurrCard, struct sccb * p_sccb, unsigned char i, SCSIcmd; CALL_BK_FN callback; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; SCSIcmd = p_sccb->Cdb[0]; @@ -7207,7 +7206,7 @@ static void FPT_queueCmdComplete(PSCCBcard pCurrCard, struct sccb * p_sccb, *---------------------------------------------------------------------*/ static void FPT_queueDisconnect(struct sccb * p_sccb, unsigned char p_card) { - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID]; @@ -7244,7 +7243,7 @@ static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code) { unsigned char qtag,thisTarg; struct sccb * currSCCB; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; if(currSCCB != NULL) @@ -7283,7 +7282,7 @@ static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg unsigned char error_code) { unsigned char qtag; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; @@ -7311,7 +7310,7 @@ static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg static void FPT_queueAddSccb(struct sccb * p_SCCB, unsigned char p_card) { - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID]; p_SCCB->Sccb_forwardlink = NULL; @@ -7346,7 +7345,7 @@ static void FPT_queueAddSccb(struct sccb * p_SCCB, unsigned char p_card) static unsigned char FPT_queueFindSccb(struct sccb * p_SCCB, unsigned char p_card) { struct sccb * q_ptr; - PSCCBMgr_tar_info currTar_Info; + struct sccb_mgr_tar_info * currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID]; -- cgit v1.2.3-59-g8ed1b From 68d0c1ae66413ef553b1132269129003cea668ed Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:33 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: untypedef struct NVRAMInfo * struct NVRAMInfo => struct nvram_info * PNVRamInfo => struct nvram_info * * NVRAMINFO => struct nvram_info Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 895e4ff7be1d..696f31c5df76 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -285,7 +285,7 @@ struct sccb_mgr_tar_info { unsigned char TarLUNBusy[MAX_LUN]; }; -typedef struct NVRAMInfo { +struct nvram_info { unsigned char niModel; /* Model No. of card */ unsigned char niCardNo; /* Card no. */ unsigned long niBaseAddr; /* Port Address of card */ @@ -295,9 +295,8 @@ typedef struct NVRAMInfo { unsigned char niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */ unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */ unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */ -}NVRAMINFO; +}; -typedef NVRAMINFO *PNVRamInfo; #define MODEL_LT 1 #define MODEL_DL 2 @@ -318,7 +317,7 @@ typedef struct SCCBcard { unsigned char scanIndex; unsigned char globalFlags; unsigned char ourId; - PNVRamInfo pNvRamInfo; + struct nvram_info * pNvRamInfo; struct sccb * discQ_Tbl[QUEUE_DEPTH]; }SCCBCARD; @@ -987,7 +986,7 @@ static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg unsigned char error_code); static void FPT_sinits(struct sccb * p_sccb, unsigned char p_card); -static void FPT_RNVRamData(PNVRamInfo pNvRamInfo); +static void FPT_RNVRamData(struct nvram_info * pNvRamInfo); static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card); static void FPT_stwidn(unsigned long port, unsigned char p_card); @@ -1083,7 +1082,7 @@ static void FPT_autoLoadDefaultMap(unsigned long p_port); static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } }; static SCCBCARD FPT_BL_Card[MAX_CARDS] = { { 0 } }; static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { { { 0 } } }; -static NVRAMINFO FPT_nvRamInfo[MAX_MB_CARDS] = { { 0 } }; +static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { { 0 } }; static unsigned char FPT_mbCards = 0; @@ -1113,7 +1112,7 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info * pCardInfo) unsigned char i,j,id,ScamFlg; unsigned short temp,temp2,temp3,temp4,temp5,temp6; unsigned long ioport; - PNVRamInfo pCurrNvRam; + struct nvram_info * pCurrNvRam; ioport = pCardInfo->si_baseaddr; @@ -1387,7 +1386,7 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info * pCardInfo) static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info * pCardInfo) { PSCCBcard CurrCard = NULL; - PNVRamInfo pCurrNvRam; + struct nvram_info * pCurrNvRam; unsigned char i,j,thisCard, ScamFlg; unsigned short temp,sync_bit_map,id; unsigned long ioport; @@ -1572,7 +1571,7 @@ static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard) unsigned long regOffset; unsigned long scamData; unsigned long *pScamTbl; - PNVRamInfo pCurrNvRam; + struct nvram_info * pCurrNvRam; pCurrNvRam = ((PSCCBcard)pCurrCard)->pNvRamInfo; @@ -1601,7 +1600,7 @@ static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard) } -static void FPT_RNVRamData(PNVRamInfo pNvRamInfo) +static void FPT_RNVRamData(struct nvram_info * pNvRamInfo) { unsigned char i; unsigned long portBase; @@ -2161,7 +2160,7 @@ static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, unsigned char p_c { unsigned char temp, ScamFlg; struct sccb_mgr_tar_info * currTar_Info; - PNVRamInfo pCurrNvRam; + struct nvram_info * pCurrNvRam; if (RD_HARPOON(p_port+hp_ext_status) & @@ -5701,7 +5700,7 @@ static void FPT_scini(unsigned char p_card, unsigned char p_our_id, unsigned cha unsigned char i,k,ScamFlg ; PSCCBcard currCard; - PNVRamInfo pCurrNvRam; + struct nvram_info * pCurrNvRam; currCard = &FPT_BL_Card[p_card]; p_port = currCard->ioPort; @@ -5992,7 +5991,7 @@ static void FPT_scasid(unsigned char p_card, unsigned long p_port) unsigned char i,k,scam_id; unsigned char crcBytes[3]; - PNVRamInfo pCurrNvRam; + struct nvram_info * pCurrNvRam; unsigned short * pCrcBytes; pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo; @@ -6453,7 +6452,7 @@ static void FPT_inisci(unsigned char p_card, unsigned long p_port, unsigned char { unsigned char i,k,max_id; unsigned short ee_data; - PNVRamInfo pCurrNvRam; + struct nvram_info * pCurrNvRam; pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo; -- cgit v1.2.3-59-g8ed1b From 13e6851aa1e8f7db0e9f0cc8567394a9fe451357 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:34 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: untypedef struct SCCBcard * struct SCCBcard => struct sccb_card * PSCCBcard => struct sccb_card * * SCCBCARD => struct sccb_card Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 143 +++++++++++++++++++++++----------------------- 1 file changed, 71 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 696f31c5df76..37ee2cb60d20 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -304,7 +304,7 @@ struct nvram_info { #define MODEL_DW 4 -typedef struct SCCBcard { +struct sccb_card { struct sccb * currentSCCB; struct sccb_mgr_info * cardInfo; @@ -320,9 +320,8 @@ typedef struct SCCBcard { struct nvram_info * pNvRamInfo; struct sccb * discQ_Tbl[QUEUE_DEPTH]; -}SCCBCARD; +}; -typedef struct SCCBcard *PSCCBcard; #define F_TAG_STARTED 0x01 @@ -968,7 +967,7 @@ typedef struct SCCBscam_info { static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, unsigned char syncFlag); static void FPT_ssel(unsigned long port, unsigned char p_card); -static void FPT_sres(unsigned long port, unsigned char p_card, PSCCBcard pCurrCard); +static void FPT_sres(unsigned long port, unsigned char p_card, struct sccb_card * pCurrCard); static void FPT_shandem(unsigned long port, unsigned char p_card,struct sccb * pCurrSCCB); static void FPT_stsyncn(unsigned long port, unsigned char p_card); static void FPT_sisyncr(unsigned long port,unsigned char sync_pulse, unsigned char offset); @@ -993,11 +992,11 @@ static void FPT_stwidn(unsigned long port, unsigned char p_card); static void FPT_siwidr(unsigned long port, unsigned char width); -static void FPT_queueSelectFail(PSCCBcard pCurrCard, unsigned char p_card); +static void FPT_queueSelectFail(struct sccb_card * pCurrCard, unsigned char p_card); static void FPT_queueDisconnect(struct sccb * p_SCCB, unsigned char p_card); -static void FPT_queueCmdComplete(PSCCBcard pCurrCard, struct sccb * p_SCCB, +static void FPT_queueCmdComplete(struct sccb_card * pCurrCard, struct sccb * p_SCCB, unsigned char p_card); -static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card); +static void FPT_queueSearchSelect(struct sccb_card * pCurrCard, unsigned char p_card); static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code); static void FPT_queueAddSccb(struct sccb * p_SCCB, unsigned char card); static unsigned char FPT_queueFindSccb(struct sccb * p_SCCB, unsigned char p_card); @@ -1038,7 +1037,7 @@ static void FPT_DiagEEPROM(unsigned long p_port); -static void FPT_dataXferProcessor(unsigned long port, PSCCBcard pCurrCard); +static void FPT_dataXferProcessor(unsigned long port, struct sccb_card * pCurrCard); static void FPT_busMstrSGDataXferStart(unsigned long port, struct sccb * pCurrSCCB); static void FPT_busMstrDataXferStart(unsigned long port, struct sccb * pCurrSCCB); static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, struct sccb * pCurrSCCB); @@ -1046,10 +1045,10 @@ static void FPT_hostDataXferRestart(struct sccb * currSCCB); static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, unsigned char p_card, - PSCCBcard pCurrCard, unsigned short p_int); + struct sccb_card * pCurrCard, unsigned short p_int); static void FPT_SccbMgrTableInitAll(void); -static void FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, unsigned char p_card); +static void FPT_SccbMgrTableInitCard(struct sccb_card * pCurrCard, unsigned char p_card); static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char target); @@ -1080,7 +1079,7 @@ static void FPT_autoLoadDefaultMap(unsigned long p_port); static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } }; -static SCCBCARD FPT_BL_Card[MAX_CARDS] = { { 0 } }; +static struct sccb_card FPT_BL_Card[MAX_CARDS] = { { 0 } }; static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { { { 0 } } }; static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { { 0 } }; @@ -1385,7 +1384,7 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info * pCardInfo) static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info * pCardInfo) { - PSCCBcard CurrCard = NULL; + struct sccb_card * CurrCard = NULL; struct nvram_info * pCurrNvRam; unsigned char i,j,thisCard, ScamFlg; unsigned short temp,sync_bit_map,id; @@ -1573,7 +1572,7 @@ static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard) unsigned long *pScamTbl; struct nvram_info * pCurrNvRam; - pCurrNvRam = ((PSCCBcard)pCurrCard)->pNvRamInfo; + pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo; if(pCurrNvRam){ FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel); @@ -1595,7 +1594,7 @@ static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard) } }else{ - FPT_WrStack(((PSCCBcard)pCurrCard)->ioPort, 0, 0); + FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0); } } @@ -1670,8 +1669,8 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb * p_Sccb) struct sccb * pSaveSccb; CALL_BK_FN callback; - thisCard = ((PSCCBcard) pCurrCard)->cardIndex; - ioport = ((PSCCBcard) pCurrCard)->ioPort; + thisCard = ((struct sccb_card *) pCurrCard)->cardIndex; + ioport = ((struct sccb_card *) pCurrCard)->ioPort; if((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) { @@ -1688,19 +1687,19 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb * p_Sccb) FPT_sinits(p_Sccb,thisCard); - if (!((PSCCBcard) pCurrCard)->cmdCounter) + if (!((struct sccb_card *) pCurrCard)->cmdCounter) { WR_HARPOON(ioport+hp_semaphore, (RD_HARPOON(ioport+hp_semaphore) | SCCB_MGR_ACTIVE)); - if (((PSCCBcard) pCurrCard)->globalFlags & F_GREEN_PC) + if (((struct sccb_card *) pCurrCard)->globalFlags & F_GREEN_PC) { WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT); WR_HARPOON(ioport+hp_sys_ctrl, 0x00); } } - ((PSCCBcard)pCurrCard)->cmdCounter++; + ((struct sccb_card *)pCurrCard)->cmdCounter++; if (RD_HARPOON(ioport+hp_semaphore) & BIOS_IN_USE) { @@ -1708,10 +1707,10 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb * p_Sccb) | TICKLE_ME)); if(p_Sccb->OperationCode == RESET_COMMAND) { - pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB; - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; + pSaveSccb = ((struct sccb_card *) pCurrCard)->currentSCCB; + ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard); - ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb; + ((struct sccb_card *) pCurrCard)->currentSCCB = pSaveSccb; } else { @@ -1723,10 +1722,10 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb * p_Sccb) if(p_Sccb->OperationCode == RESET_COMMAND) { - pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB; - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; + pSaveSccb = ((struct sccb_card *) pCurrCard)->currentSCCB; + ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard); - ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb; + ((struct sccb_card *) pCurrCard)->currentSCCB = pSaveSccb; } else { @@ -1738,17 +1737,17 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb * p_Sccb) MDISABLE_INT(ioport); - if((((PSCCBcard) pCurrCard)->globalFlags & F_CONLUN_IO) && + if((((struct sccb_card *) pCurrCard)->globalFlags & F_CONLUN_IO) && ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) lun = p_Sccb->Lun; else lun = 0; - if ((((PSCCBcard) pCurrCard)->currentSCCB == NULL) && + if ((((struct sccb_card *) pCurrCard)->currentSCCB == NULL) && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0) && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun] == 0)) { - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; + ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; FPT_ssel(p_Sccb->SccbIOPort,thisCard); } @@ -1756,10 +1755,10 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb * p_Sccb) if(p_Sccb->OperationCode == RESET_COMMAND) { - pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB; - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; + pSaveSccb = ((struct sccb_card *) pCurrCard)->currentSCCB; + ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard); - ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb; + ((struct sccb_card *) pCurrCard)->currentSCCB = pSaveSccb; } else { @@ -1794,9 +1793,9 @@ static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb * p_Sccb) struct sccb_mgr_tar_info * currTar_Info; - ioport = ((PSCCBcard) pCurrCard)->ioPort; + ioport = ((struct sccb_card *) pCurrCard)->ioPort; - thisCard = ((PSCCBcard)pCurrCard)->cardIndex; + thisCard = ((struct sccb_card *)pCurrCard)->cardIndex; if (!(RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE)) { @@ -1804,9 +1803,9 @@ static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb * p_Sccb) if (FPT_queueFindSccb(p_Sccb,thisCard)) { - ((PSCCBcard)pCurrCard)->cmdCounter--; + ((struct sccb_card *)pCurrCard)->cmdCounter--; - if (!((PSCCBcard)pCurrCard)->cmdCounter) + if (!((struct sccb_card *)pCurrCard)->cmdCounter) WR_HARPOON(ioport+hp_semaphore,(RD_HARPOON(ioport+hp_semaphore) & (unsigned char)(~(SCCB_MGR_ACTIVE | TICKLE_ME)) )); @@ -1819,7 +1818,7 @@ static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb * p_Sccb) else { - if (((PSCCBcard)pCurrCard)->currentSCCB == p_Sccb) + if (((struct sccb_card *)pCurrCard)->currentSCCB == p_Sccb) { p_Sccb->SccbStatus = SCCB_ABORT; return(0); @@ -1835,23 +1834,23 @@ static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb * p_Sccb) if(p_Sccb->Sccb_tag) { MDISABLE_INT(ioport); - if (((PSCCBcard) pCurrCard)->discQ_Tbl[p_Sccb->Sccb_tag]==p_Sccb) + if (((struct sccb_card *) pCurrCard)->discQ_Tbl[p_Sccb->Sccb_tag]==p_Sccb) { p_Sccb->SccbStatus = SCCB_ABORT; p_Sccb->Sccb_scsistat = ABORT_ST; p_Sccb->Sccb_scsimsg = SMABORT_TAG; - if(((PSCCBcard) pCurrCard)->currentSCCB == NULL) + if(((struct sccb_card *) pCurrCard)->currentSCCB == NULL) { - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; + ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; FPT_ssel(ioport, thisCard); } else { - pSaveSCCB = ((PSCCBcard) pCurrCard)->currentSCCB; - ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; - FPT_queueSelectFail((PSCCBcard) pCurrCard, thisCard); - ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSCCB; + pSaveSCCB = ((struct sccb_card *) pCurrCard)->currentSCCB; + ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; + FPT_queueSelectFail((struct sccb_card *) pCurrCard, thisCard); + ((struct sccb_card *) pCurrCard)->currentSCCB = pSaveSCCB; } } MENABLE_INT(ioport); @@ -1887,7 +1886,7 @@ static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard) { unsigned long ioport; - ioport = ((PSCCBcard)pCurrCard)->ioPort; + ioport = ((struct sccb_card *)pCurrCard)->ioPort; if (RD_HARPOON(ioport+hp_int_status) & INT_ASSERTED) { @@ -1918,8 +1917,8 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) unsigned char i, target; unsigned long ioport; - thisCard = ((PSCCBcard)pCurrCard)->cardIndex; - ioport = ((PSCCBcard)pCurrCard)->ioPort; + thisCard = ((struct sccb_card *)pCurrCard)->cardIndex; + ioport = ((struct sccb_card *)pCurrCard)->ioPort; MDISABLE_INT(ioport); @@ -1934,10 +1933,10 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) bm_status) { - currSCCB = ((PSCCBcard)pCurrCard)->currentSCCB; + currSCCB = ((struct sccb_card *)pCurrCard)->currentSCCB; if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) { - result = FPT_SccbMgr_bad_isr(ioport,thisCard,((PSCCBcard)pCurrCard),hp_int); + result = FPT_SccbMgr_bad_isr(ioport,thisCard,((struct sccb_card *)pCurrCard),hp_int); WRW_HARPOON((ioport+hp_intstat), (FIFO | TIMEOUT | RESET | SCAM_SEL)); bm_status = 0; @@ -1960,7 +1959,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) while (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL))) ; } - if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) + if (((struct sccb_card *)pCurrCard)->globalFlags & F_HOST_XFER_ACT) FPT_phaseChkFifo(ioport, thisCard); @@ -1978,7 +1977,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) else if (hp_int & ITAR_DISC) { - if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) { + if (((struct sccb_card *)pCurrCard)->globalFlags & F_HOST_XFER_ACT) { FPT_phaseChkFifo(ioport, thisCard); @@ -2019,7 +2018,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ITAR_DISC)); - ((PSCCBcard)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD; + ((struct sccb_card *)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD; } @@ -2030,7 +2029,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) if (RDW_HARPOON((ioport+hp_intstat)) & ITAR_DISC) { - if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) + if (((struct sccb_card *)pCurrCard)->globalFlags & F_HOST_XFER_ACT) { FPT_phaseChkFifo(ioport, thisCard); } @@ -2047,7 +2046,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) FPT_queueDisconnect(currSCCB,thisCard); } - FPT_sres(ioport,thisCard,((PSCCBcard)pCurrCard)); + FPT_sres(ioport,thisCard,((struct sccb_card *)pCurrCard)); FPT_phaseDecode(ioport,thisCard); } @@ -2101,7 +2100,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) WRW_HARPOON((ioport+hp_intstat), BUS_FREE); - if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) { + if (((struct sccb_card *)pCurrCard)->globalFlags & F_HOST_XFER_ACT) { FPT_hostDataXferAbort(ioport,thisCard,currSCCB); } @@ -2113,24 +2112,24 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) else if (hp_int & ITICKLE) { WRW_HARPOON((ioport+hp_intstat), ITICKLE); - ((PSCCBcard)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD; + ((struct sccb_card *)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD; } - if (((PSCCBcard)pCurrCard)->globalFlags & F_NEW_SCCB_CMD) { + if (((struct sccb_card *)pCurrCard)->globalFlags & F_NEW_SCCB_CMD) { - ((PSCCBcard)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD; + ((struct sccb_card *)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD; - if (((PSCCBcard)pCurrCard)->currentSCCB == NULL) { + if (((struct sccb_card *)pCurrCard)->currentSCCB == NULL) { - FPT_queueSearchSelect(((PSCCBcard)pCurrCard),thisCard); + FPT_queueSearchSelect(((struct sccb_card *)pCurrCard),thisCard); } - if (((PSCCBcard)pCurrCard)->currentSCCB != NULL) { - ((PSCCBcard)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD; + if (((struct sccb_card *)pCurrCard)->currentSCCB != NULL) { + ((struct sccb_card *)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD; FPT_ssel(ioport,thisCard); } @@ -2156,7 +2155,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) * *---------------------------------------------------------------------*/ static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, unsigned char p_card, - PSCCBcard pCurrCard, unsigned short p_int) + struct sccb_card * pCurrCard, unsigned short p_int) { unsigned char temp, ScamFlg; struct sccb_mgr_tar_info * currTar_Info; @@ -2332,7 +2331,7 @@ static void FPT_SccbMgrTableInitAll() * *---------------------------------------------------------------------*/ -static void FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, unsigned char p_card) +static void FPT_SccbMgrTableInitCard(struct sccb_card * pCurrCard, unsigned char p_card) { unsigned char scsiID, qtag; @@ -2492,7 +2491,7 @@ static void FPT_ssel(unsigned long port, unsigned char p_card) unsigned char auto_loaded, i, target, *theCCB; unsigned long cdb_reg; - PSCCBcard CurrCard; + struct sccb_card * CurrCard; struct sccb * currSCCB; struct sccb_mgr_tar_info * currTar_Info; unsigned char lastTag, lun; @@ -2797,7 +2796,7 @@ static void FPT_ssel(unsigned long port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_sres(unsigned long port, unsigned char p_card, PSCCBcard pCurrCard) +static void FPT_sres(unsigned long port, unsigned char p_card, struct sccb_card * pCurrCard) { unsigned char our_target, message, lun = 0, tag, msgRetryCount; @@ -3110,7 +3109,7 @@ static void FPT_SendMsg(unsigned long port, unsigned char message) static void FPT_sdecm(unsigned char message, unsigned long port, unsigned char p_card) { struct sccb * currSCCB; - PSCCBcard CurrCard; + struct sccb_card * CurrCard; struct sccb_mgr_tar_info * currTar_Info; CurrCard = &FPT_BL_Card[p_card]; @@ -3909,7 +3908,7 @@ static void FPT_sresb(unsigned long port, unsigned char p_card) * Description: Setup for the Auto Sense command. * *---------------------------------------------------------------------*/ -static void FPT_ssenss(PSCCBcard pCurrCard) +static void FPT_ssenss(struct sccb_card * pCurrCard) { unsigned char i; struct sccb * currSCCB; @@ -5151,7 +5150,7 @@ static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_dataXferProcessor(unsigned long port, PSCCBcard pCurrCard) +static void FPT_dataXferProcessor(unsigned long port, struct sccb_card * pCurrCard) { struct sccb * currSCCB; @@ -5699,7 +5698,7 @@ static void FPT_scini(unsigned char p_card, unsigned char p_our_id, unsigned cha unsigned long p_port; unsigned char i,k,ScamFlg ; - PSCCBcard currCard; + struct sccb_card * currCard; struct nvram_info * pCurrNvRam; currCard = &FPT_BL_Card[p_card]; @@ -6931,7 +6930,7 @@ static void FPT_DiagEEPROM(unsigned long p_port) * *---------------------------------------------------------------------*/ -static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card) +static void FPT_queueSearchSelect(struct sccb_card * pCurrCard, unsigned char p_card) { unsigned char scan_ptr, lun; struct sccb_mgr_tar_info * currTar_Info; @@ -7062,7 +7061,7 @@ static void FPT_queueSearchSelect(PSCCBcard pCurrCard, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_queueSelectFail(PSCCBcard pCurrCard, unsigned char p_card) +static void FPT_queueSelectFail(struct sccb_card * pCurrCard, unsigned char p_card) { unsigned char thisTarg; struct sccb_mgr_tar_info * currTar_Info; @@ -7101,7 +7100,7 @@ static void FPT_queueSelectFail(PSCCBcard pCurrCard, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_queueCmdComplete(PSCCBcard pCurrCard, struct sccb * p_sccb, +static void FPT_queueCmdComplete(struct sccb_card * pCurrCard, struct sccb * p_sccb, unsigned char p_card) { -- cgit v1.2.3-59-g8ed1b From 5c04a7b8981f2855869bf04c881553135445d701 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:35 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: Lindent It's much, much more readable now. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 9190 ++++++++++++++++++++++----------------------- 1 file changed, 4490 insertions(+), 4700 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 37ee2cb60d20..ce49fbcafbb6 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -15,74 +15,47 @@ */ - #include - #ifndef CONFIG_SCSI_OMIT_FLASHPOINT - #define MAX_CARDS 8 #undef BUSTYPE_PCI - - - - - - - - #define CRCMASK 0xA001 - - #define FAILURE 0xFFFFFFFFL - - - - - - - - - -#define BIT(x) ((unsigned char)(1<<(x))) /* single-bit mask in bit position x */ -#define BITW(x) ((unsigned short)(1<<(x))) /* single-bit mask in bit position x */ - - +#define BIT(x) ((unsigned char)(1<<(x))) /* single-bit mask in bit position x */ +#define BITW(x) ((unsigned short)(1<<(x))) /* single-bit mask in bit position x */ struct sccb; -typedef void (*CALL_BK_FN)(struct sccb *); - +typedef void (*CALL_BK_FN) (struct sccb *); struct sccb_mgr_info { - unsigned long si_baseaddr; - unsigned char si_present; - unsigned char si_intvect; - unsigned char si_id; - unsigned char si_lun; - unsigned short si_fw_revision; - unsigned short si_per_targ_init_sync; - unsigned short si_per_targ_fast_nego; - unsigned short si_per_targ_ultra_nego; - unsigned short si_per_targ_no_disc; - unsigned short si_per_targ_wide_nego; - unsigned short si_flags; - unsigned char si_card_family; - unsigned char si_bustype; - unsigned char si_card_model[3]; - unsigned char si_relative_cardnum; - unsigned char si_reserved[4]; - unsigned long si_OS_reserved; - unsigned char si_XlatInfo[4]; - unsigned long si_reserved2[5]; - unsigned long si_secondary_range; + unsigned long si_baseaddr; + unsigned char si_present; + unsigned char si_intvect; + unsigned char si_id; + unsigned char si_lun; + unsigned short si_fw_revision; + unsigned short si_per_targ_init_sync; + unsigned short si_per_targ_fast_nego; + unsigned short si_per_targ_ultra_nego; + unsigned short si_per_targ_no_disc; + unsigned short si_per_targ_wide_nego; + unsigned short si_flags; + unsigned char si_card_family; + unsigned char si_bustype; + unsigned char si_card_model[3]; + unsigned char si_relative_cardnum; + unsigned char si_reserved[4]; + unsigned long si_OS_reserved; + unsigned char si_XlatInfo[4]; + unsigned long si_reserved2[5]; + unsigned long si_secondary_range; }; - - #define SCSI_PARITY_ENA 0x0001 #define LOW_BYTE_TERM 0x0010 #define HIGH_BYTE_TERM 0x0020 @@ -95,97 +68,82 @@ struct sccb_mgr_info { #define FLAG_SCAM_ENABLED 0x0080 #define FLAG_SCAM_LEVEL2 0x0100 - - - #define HARPOON_FAMILY 0x02 - - /* SCCB struct used for both SCCB and UCB manager compiles! * The UCB Manager treats the SCCB as it's 'native hardware structure' */ - #pragma pack(1) struct sccb { - unsigned char OperationCode; - unsigned char ControlByte; - unsigned char CdbLength; - unsigned char RequestSenseLength; - unsigned long DataLength; - unsigned long DataPointer; - unsigned char CcbRes[2]; - unsigned char HostStatus; - unsigned char TargetStatus; - unsigned char TargID; - unsigned char Lun; - unsigned char Cdb[12]; - unsigned char CcbRes1; - unsigned char Reserved1; - unsigned long Reserved2; - unsigned long SensePointer; - - - CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */ - unsigned long SccbIOPort; /* Identifies board base port */ - unsigned char SccbStatus; - unsigned char SCCBRes2; - unsigned short SccbOSFlags; - - - unsigned long Sccb_XferCnt; /* actual transfer count */ - unsigned long Sccb_ATC; - unsigned long SccbVirtDataPtr; /* virtual addr for OS/2 */ - unsigned long Sccb_res1; - unsigned short Sccb_MGRFlags; - unsigned short Sccb_sgseg; - unsigned char Sccb_scsimsg; /* identify msg for selection */ - unsigned char Sccb_tag; - unsigned char Sccb_scsistat; - unsigned char Sccb_idmsg; /* image of last msg in */ - struct sccb * Sccb_forwardlink; - struct sccb * Sccb_backlink; - unsigned long Sccb_savedATC; - unsigned char Save_Cdb[6]; - unsigned char Save_CdbLen; - unsigned char Sccb_XferState; - unsigned long Sccb_SGoffset; - }; - + unsigned char OperationCode; + unsigned char ControlByte; + unsigned char CdbLength; + unsigned char RequestSenseLength; + unsigned long DataLength; + unsigned long DataPointer; + unsigned char CcbRes[2]; + unsigned char HostStatus; + unsigned char TargetStatus; + unsigned char TargID; + unsigned char Lun; + unsigned char Cdb[12]; + unsigned char CcbRes1; + unsigned char Reserved1; + unsigned long Reserved2; + unsigned long SensePointer; + + CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */ + unsigned long SccbIOPort; /* Identifies board base port */ + unsigned char SccbStatus; + unsigned char SCCBRes2; + unsigned short SccbOSFlags; + + unsigned long Sccb_XferCnt; /* actual transfer count */ + unsigned long Sccb_ATC; + unsigned long SccbVirtDataPtr; /* virtual addr for OS/2 */ + unsigned long Sccb_res1; + unsigned short Sccb_MGRFlags; + unsigned short Sccb_sgseg; + unsigned char Sccb_scsimsg; /* identify msg for selection */ + unsigned char Sccb_tag; + unsigned char Sccb_scsistat; + unsigned char Sccb_idmsg; /* image of last msg in */ + struct sccb *Sccb_forwardlink; + struct sccb *Sccb_backlink; + unsigned long Sccb_savedATC; + unsigned char Save_Cdb[6]; + unsigned char Save_CdbLen; + unsigned char Sccb_XferState; + unsigned long Sccb_SGoffset; +}; #pragma pack() - - #define SCATTER_GATHER_COMMAND 0x02 #define RESIDUAL_COMMAND 0x03 #define RESIDUAL_SG_COMMAND 0x04 #define RESET_COMMAND 0x81 +#define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */ +#define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */ +#define SCCB_DATA_XFER_OUT 0x10 /* Write */ +#define SCCB_DATA_XFER_IN 0x08 /* Read */ -#define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */ -#define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */ -#define SCCB_DATA_XFER_OUT 0x10 /* Write */ -#define SCCB_DATA_XFER_IN 0x08 /* Read */ - - -#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ +#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ - -#define BUS_FREE_ST 0 +#define BUS_FREE_ST 0 #define SELECT_ST 1 -#define SELECT_BDR_ST 2 /* Select w\ Bus Device Reset */ -#define SELECT_SN_ST 3 /* Select w\ Sync Nego */ -#define SELECT_WN_ST 4 /* Select w\ Wide Data Nego */ -#define SELECT_Q_ST 5 /* Select w\ Tagged Q'ing */ +#define SELECT_BDR_ST 2 /* Select w\ Bus Device Reset */ +#define SELECT_SN_ST 3 /* Select w\ Sync Nego */ +#define SELECT_WN_ST 4 /* Select w\ Wide Data Nego */ +#define SELECT_Q_ST 5 /* Select w\ Tagged Q'ing */ #define COMMAND_ST 6 #define DATA_OUT_ST 7 #define DATA_IN_ST 8 #define DISCONNECT_ST 9 #define ABORT_ST 11 - #define F_HOST_XFER_DIR 0x01 #define F_ALL_XFERRED 0x02 #define F_SG_XFER 0x04 @@ -193,49 +151,37 @@ struct sccb { #define F_ODD_BALL_CNT 0x10 #define F_NO_DATA_YET 0x80 - #define F_STATUSLOADED 0x01 #define F_DEV_SELECTED 0x04 - -#define SCCB_COMPLETE 0x00 /* SCCB completed without error */ +#define SCCB_COMPLETE 0x00 /* SCCB completed without error */ #define SCCB_DATA_UNDER_RUN 0x0C -#define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ +#define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ #define SCCB_DATA_OVER_RUN 0x12 -#define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */ - -#define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */ -#define SCCB_BM_ERR 0x30 /* BusMaster error. */ -#define SCCB_PARITY_ERR 0x34 /* SCSI parity error */ - - - +#define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */ +#define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */ +#define SCCB_BM_ERR 0x30 /* BusMaster error. */ +#define SCCB_PARITY_ERR 0x34 /* SCSI parity error */ #define SCCB_IN_PROCESS 0x00 #define SCCB_SUCCESS 0x01 #define SCCB_ABORT 0x02 #define SCCB_ERROR 0x04 - - #define ORION_FW_REV 3110 +#define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */ - -#define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */ - -#define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */ - +#define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */ #define MAX_SCSI_TAR 16 #define MAX_LUN 32 #define LUN_MASK 0x1f -#define SG_BUF_CNT 16 /*Number of prefetched elements. */ - -#define SG_ELEMENT_SIZE 8 /*Eight byte per element. */ +#define SG_BUF_CNT 16 /*Number of prefetched elements. */ +#define SG_ELEMENT_SIZE 8 /*Eight byte per element. */ #define RD_HARPOON(ioport) inb((u32)ioport) #define RDW_HARPOON(ioport) inw((u32)ioport) @@ -244,7 +190,6 @@ struct sccb { #define WRW_HARPOON(ioport,val) outw((u16)val, (u32)ioport) #define WR_HARP32(ioport,offset,data) outl(data, (u32)(ioport + offset)) - #define TAR_SYNC_MASK (BIT(7)+BIT(6)) #define SYNC_TRYING BIT(6) #define SYNC_SUPPORTED (BIT(7)+BIT(6)) @@ -259,7 +204,6 @@ struct sccb { #define TAR_ALLOW_DISC BIT(0) - #define EE_SYNC_MASK (BIT(0)+BIT(1)) #define EE_SYNC_5MB BIT(0) #define EE_SYNC_10MB BIT(1) @@ -267,62 +211,55 @@ struct sccb { #define EE_WIDE_SCSI BIT(7) - - - struct sccb_mgr_tar_info { - struct sccb * TarSelQ_Head; - struct sccb * TarSelQ_Tail; - unsigned char TarLUN_CA; /*Contingent Allgiance */ - unsigned char TarTagQ_Cnt; - unsigned char TarSelQ_Cnt; - unsigned char TarStatus; - unsigned char TarEEValue; - unsigned char TarSyncCtrl; - unsigned char TarReserved[2]; /* for alignment */ - unsigned char LunDiscQ_Idx[MAX_LUN]; - unsigned char TarLUNBusy[MAX_LUN]; + struct sccb *TarSelQ_Head; + struct sccb *TarSelQ_Tail; + unsigned char TarLUN_CA; /*Contingent Allgiance */ + unsigned char TarTagQ_Cnt; + unsigned char TarSelQ_Cnt; + unsigned char TarStatus; + unsigned char TarEEValue; + unsigned char TarSyncCtrl; + unsigned char TarReserved[2]; /* for alignment */ + unsigned char LunDiscQ_Idx[MAX_LUN]; + unsigned char TarLUNBusy[MAX_LUN]; }; struct nvram_info { - unsigned char niModel; /* Model No. of card */ - unsigned char niCardNo; /* Card no. */ - unsigned long niBaseAddr; /* Port Address of card */ - unsigned char niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */ - unsigned char niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */ - unsigned char niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */ - unsigned char niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */ - unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */ - unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */ + unsigned char niModel; /* Model No. of card */ + unsigned char niCardNo; /* Card no. */ + unsigned long niBaseAddr; /* Port Address of card */ + unsigned char niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */ + unsigned char niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */ + unsigned char niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */ + unsigned char niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */ + unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */ + unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */ }; - #define MODEL_LT 1 #define MODEL_DL 2 #define MODEL_LW 3 #define MODEL_DW 4 - struct sccb_card { - struct sccb * currentSCCB; - struct sccb_mgr_info * cardInfo; - - unsigned long ioPort; - - unsigned short cmdCounter; - unsigned char discQCount; - unsigned char tagQ_Lst; - unsigned char cardIndex; - unsigned char scanIndex; - unsigned char globalFlags; - unsigned char ourId; - struct nvram_info * pNvRamInfo; - struct sccb * discQ_Tbl[QUEUE_DEPTH]; - -}; + struct sccb *currentSCCB; + struct sccb_mgr_info *cardInfo; + + unsigned long ioPort; + unsigned short cmdCounter; + unsigned char discQCount; + unsigned char tagQ_Lst; + unsigned char cardIndex; + unsigned char scanIndex; + unsigned char globalFlags; + unsigned char ourId; + struct nvram_info *pNvRamInfo; + struct sccb *discQ_Tbl[QUEUE_DEPTH]; +}; #define F_TAG_STARTED 0x01 #define F_CONLUN_IO 0x02 @@ -333,12 +270,10 @@ struct sccb_card { #define F_NEW_SCCB_CMD 0x40 #define F_UPDATE_EEPROM 0x80 - #define ID_STRING_LENGTH 32 -#define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */ - +#define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */ -#define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */ +#define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */ #define ASSIGN_ID 0x00 #define SET_P_FLAG 0x01 @@ -351,23 +286,21 @@ struct sccb_card { #define MISC_CODE 0x14 #define CLR_P_FLAG 0x18 - - #define INIT_SELTD 0x01 #define LEVEL2_TAR 0x02 - -enum scam_id_st { ID0,ID1,ID2,ID3,ID4,ID5,ID6,ID7,ID8,ID9,ID10,ID11,ID12, - ID13,ID14,ID15,ID_UNUSED,ID_UNASSIGNED,ID_ASSIGNED,LEGACY, - CLR_PRIORITY,NO_ID_AVAIL }; +enum scam_id_st { ID0, ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10, ID11, + ID12, + ID13, ID14, ID15, ID_UNUSED, ID_UNASSIGNED, ID_ASSIGNED, LEGACY, + CLR_PRIORITY, NO_ID_AVAIL +}; typedef struct SCCBscam_info { - unsigned char id_string[ID_STRING_LENGTH]; - enum scam_id_st state; - -} SCCBSCAM_INFO; + unsigned char id_string[ID_STRING_LENGTH]; + enum scam_id_st state; +} SCCBSCAM_INFO; #define SCSI_REQUEST_SENSE 0x03 #define SCSI_READ 0x08 @@ -377,15 +310,10 @@ typedef struct SCCBscam_info { #define SCSI_WRITE_EXTENDED 0x2A #define SCSI_WRITE_AND_VERIFY 0x2E - - #define SSGOOD 0x00 #define SSCHECK 0x02 #define SSQ_FULL 0x28 - - - #define SMCMD_COMP 0x00 #define SMEXT 0x01 #define SMSAVE_DATA_PTR 0x02 @@ -403,26 +331,17 @@ typedef struct SCCBscam_info { #define SMIDENT 0x80 #define DISC_PRIV 0x40 - #define SMSYNC 0x01 #define SMWDTR 0x03 #define SM8BIT 0x00 #define SM16BIT 0x01 -#define SMIGNORWR 0x23 /* Ignore Wide Residue */ - - - - - - - +#define SMIGNORWR 0x23 /* Ignore Wide Residue */ #define SIX_BYTE_CMD 0x06 #define TWELVE_BYTE_CMD 0x0C #define ASYNC 0x00 -#define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */ - +#define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */ #define EEPROM_WD_CNT 256 @@ -437,7 +356,6 @@ typedef struct SCCBscam_info { #define SCAM_CONFIG 20 #define ADAPTER_SCSI_ID 24 - #define IGNORE_B_SCAN 32 #define SEND_START_ENA 34 #define DEVICE_ENABLE 36 @@ -452,478 +370,385 @@ typedef struct SCCBscam_info { #define SYNC_RATE_TBLcd 50 #define SYNC_RATE_TBLef 52 +#define EE_SCAMBASE 256 +#define SCAM_ENABLED BIT(2) +#define SCAM_LEVEL2 BIT(3) -#define EE_SCAMBASE 256 - - - - #define SCAM_ENABLED BIT(2) - #define SCAM_LEVEL2 BIT(3) - - - #define RENEGO_ENA BITW(10) - #define CONNIO_ENA BITW(11) - #define GREEN_PC_ENA BITW(12) +#define RENEGO_ENA BITW(10) +#define CONNIO_ENA BITW(11) +#define GREEN_PC_ENA BITW(12) +#define AUTO_RATE_00 00 +#define AUTO_RATE_05 01 +#define AUTO_RATE_10 02 +#define AUTO_RATE_20 03 - #define AUTO_RATE_00 00 - #define AUTO_RATE_05 01 - #define AUTO_RATE_10 02 - #define AUTO_RATE_20 03 +#define WIDE_NEGO_BIT BIT(7) +#define DISC_ENABLE_BIT BIT(6) - #define WIDE_NEGO_BIT BIT(7) - #define DISC_ENABLE_BIT BIT(6) +#define hp_vendor_id_0 0x00 /* LSB */ +#define ORION_VEND_0 0x4B +#define hp_vendor_id_1 0x01 /* MSB */ +#define ORION_VEND_1 0x10 +#define hp_device_id_0 0x02 /* LSB */ +#define ORION_DEV_0 0x30 - #define hp_vendor_id_0 0x00 /* LSB */ - #define ORION_VEND_0 0x4B - - #define hp_vendor_id_1 0x01 /* MSB */ - #define ORION_VEND_1 0x10 - - #define hp_device_id_0 0x02 /* LSB */ - #define ORION_DEV_0 0x30 - - #define hp_device_id_1 0x03 /* MSB */ - #define ORION_DEV_1 0x81 +#define hp_device_id_1 0x03 /* MSB */ +#define ORION_DEV_1 0x81 /* Sub Vendor ID and Sub Device ID only available in - Harpoon Version 2 and higher */ - - #define hp_sub_device_id_0 0x06 /* LSB */ - - - - #define hp_semaphore 0x0C - #define SCCB_MGR_ACTIVE BIT(0) - #define TICKLE_ME BIT(1) - #define SCCB_MGR_PRESENT BIT(3) - #define BIOS_IN_USE BIT(4) - - - - #define hp_sys_ctrl 0x0F - - #define STOP_CLK BIT(0) /*Turn off BusMaster Clock */ - #define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */ - #define HALT_MACH BIT(3) /*Halt State Machine */ - #define HARD_ABORT BIT(4) /*Hard Abort */ - - - - - - - - - - #define hp_host_blk_cnt 0x13 - - #define XFER_BLK64 0x06 /* 1 1 0 64 byte per block*/ - - #define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes*/ - + Harpoon Version 2 and higher */ +#define hp_sub_device_id_0 0x06 /* LSB */ - #define hp_int_mask 0x17 +#define hp_semaphore 0x0C +#define SCCB_MGR_ACTIVE BIT(0) +#define TICKLE_ME BIT(1) +#define SCCB_MGR_PRESENT BIT(3) +#define BIOS_IN_USE BIT(4) - #define INT_CMD_COMPL BIT(0) /* DMA command complete */ - #define INT_EXT_STATUS BIT(1) /* Extended Status Set */ +#define hp_sys_ctrl 0x0F +#define STOP_CLK BIT(0) /*Turn off BusMaster Clock */ +#define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */ +#define HALT_MACH BIT(3) /*Halt State Machine */ +#define HARD_ABORT BIT(4) /*Hard Abort */ - #define hp_xfer_cnt_lo 0x18 - #define hp_xfer_cnt_hi 0x1A - #define hp_xfer_cmd 0x1B +#define hp_host_blk_cnt 0x13 - #define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */ - #define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */ +#define XFER_BLK64 0x06 /* 1 1 0 64 byte per block */ +#define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes */ - #define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */ +#define hp_int_mask 0x17 - #define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */ +#define INT_CMD_COMPL BIT(0) /* DMA command complete */ +#define INT_EXT_STATUS BIT(1) /* Extended Status Set */ - #define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */ +#define hp_xfer_cnt_lo 0x18 +#define hp_xfer_cnt_hi 0x1A +#define hp_xfer_cmd 0x1B - #define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT)) - #define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT)) +#define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */ +#define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */ - #define hp_host_addr_lo 0x1C - #define hp_host_addr_hmi 0x1E +#define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */ - #define hp_ee_ctrl 0x22 +#define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */ - #define EXT_ARB_ACK BIT(7) - #define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */ - #define SEE_MS BIT(5) - #define SEE_CS BIT(3) - #define SEE_CLK BIT(2) - #define SEE_DO BIT(1) - #define SEE_DI BIT(0) +#define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */ - #define EE_READ 0x06 - #define EE_WRITE 0x05 - #define EWEN 0x04 - #define EWEN_ADDR 0x03C0 - #define EWDS 0x04 - #define EWDS_ADDR 0x0000 +#define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT)) +#define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT)) +#define hp_host_addr_lo 0x1C +#define hp_host_addr_hmi 0x1E +#define hp_ee_ctrl 0x22 +#define EXT_ARB_ACK BIT(7) +#define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */ +#define SEE_MS BIT(5) +#define SEE_CS BIT(3) +#define SEE_CLK BIT(2) +#define SEE_DO BIT(1) +#define SEE_DI BIT(0) +#define EE_READ 0x06 +#define EE_WRITE 0x05 +#define EWEN 0x04 +#define EWEN_ADDR 0x03C0 +#define EWDS 0x04 +#define EWDS_ADDR 0x0000 +#define hp_bm_ctrl 0x26 +#define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */ +#define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */ +#define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */ +#define FAST_SINGLE BIT(6) /*?? */ - #define hp_bm_ctrl 0x26 +#define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L) - #define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */ - #define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */ - #define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */ - #define FAST_SINGLE BIT(6) /*?? */ +#define hp_sg_addr 0x28 +#define hp_page_ctrl 0x29 - #define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L) +#define SCATTER_EN BIT(0) +#define SGRAM_ARAM BIT(1) +#define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */ +#define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */ +#define hp_pci_stat_cfg 0x2D - #define hp_sg_addr 0x28 - #define hp_page_ctrl 0x29 +#define REC_MASTER_ABORT BIT(5) /*received Master abort */ - #define SCATTER_EN BIT(0) - #define SGRAM_ARAM BIT(1) - #define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */ - #define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */ +#define hp_rev_num 0x33 +#define hp_stack_data 0x34 +#define hp_stack_addr 0x35 +#define hp_ext_status 0x36 - - #define hp_pci_stat_cfg 0x2D - - #define REC_MASTER_ABORT BIT(5) /*received Master abort */ - - - - - - - - - #define hp_rev_num 0x33 - - - #define hp_stack_data 0x34 - #define hp_stack_addr 0x35 - - #define hp_ext_status 0x36 - - #define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */ - #define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */ - #define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */ - #define CMD_ABORTED BIT(4) /*Command aborted */ - #define BM_PARITY_ERR BIT(5) /*parity error on data received */ - #define PIO_OVERRUN BIT(6) /*Slave data overrun */ - #define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */ - #define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \ +#define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */ +#define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */ +#define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */ +#define CMD_ABORTED BIT(4) /*Command aborted */ +#define BM_PARITY_ERR BIT(5) /*parity error on data received */ +#define PIO_OVERRUN BIT(6) /*Slave data overrun */ +#define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */ +#define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \ BM_PARITY_ERR | PIO_OVERRUN) - #define hp_int_status 0x37 - - #define EXT_STATUS_ON BIT(1) /*Extended status is valid */ - #define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */ - #define INT_ASSERTED BIT(5) /* */ - - - #define hp_fifo_cnt 0x38 - - - - - #define hp_intena 0x40 - - #define RESET BITW(7) - #define PROG_HLT BITW(6) - #define PARITY BITW(5) - #define FIFO BITW(4) - #define SEL BITW(3) - #define SCAM_SEL BITW(2) - #define RSEL BITW(1) - #define TIMEOUT BITW(0) - #define BUS_FREE BITW(15) - #define XFER_CNT_0 BITW(14) - #define PHASE BITW(13) - #define IUNKWN BITW(12) - #define ICMD_COMP BITW(11) - #define ITICKLE BITW(10) - #define IDO_STRT BITW(9) - #define ITAR_DISC BITW(8) - #define AUTO_INT (BITW(12)+BITW(11)+BITW(10)+BITW(9)+BITW(8)) - #define CLR_ALL_INT 0xFFFF - #define CLR_ALL_INT_1 0xFF00 - - #define hp_intstat 0x42 - - #define hp_scsisig 0x44 - - #define SCSI_SEL BIT(7) - #define SCSI_BSY BIT(6) - #define SCSI_REQ BIT(5) - #define SCSI_ACK BIT(4) - #define SCSI_ATN BIT(3) - #define SCSI_CD BIT(2) - #define SCSI_MSG BIT(1) - #define SCSI_IOBIT BIT(0) - - #define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0)) - #define S_MSGO_PH (BIT(2)+BIT(1) ) - #define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0)) - #define S_DATAI_PH ( BIT(0)) - #define S_DATAO_PH 0x00 - #define S_ILL_PH ( BIT(1) ) - - #define hp_scsictrl_0 0x45 - - #define SEL_TAR BIT(6) - #define ENA_ATN BIT(4) - #define ENA_RESEL BIT(2) - #define SCSI_RST BIT(1) - #define ENA_SCAM_SEL BIT(0) - - - - #define hp_portctrl_0 0x46 - - #define SCSI_PORT BIT(7) - #define SCSI_INBIT BIT(6) - #define DMA_PORT BIT(5) - #define DMA_RD BIT(4) - #define HOST_PORT BIT(3) - #define HOST_WRT BIT(2) - #define SCSI_BUS_EN BIT(1) - #define START_TO BIT(0) - - #define hp_scsireset 0x47 - - #define SCSI_INI BIT(6) - #define SCAM_EN BIT(5) - #define DMA_RESET BIT(3) - #define HPSCSI_RESET BIT(2) - #define PROG_RESET BIT(1) - #define FIFO_CLR BIT(0) - - #define hp_xfercnt_0 0x48 - #define hp_xfercnt_2 0x4A - - #define hp_fifodata_0 0x4C - #define hp_addstat 0x4E - - #define SCAM_TIMER BIT(7) - #define SCSI_MODE8 BIT(3) - #define SCSI_PAR_ERR BIT(0) - - #define hp_prgmcnt_0 0x4F - - - #define hp_selfid_0 0x50 - #define hp_selfid_1 0x51 - #define hp_arb_id 0x52 - - - #define hp_select_id 0x53 - - - #define hp_synctarg_base 0x54 - #define hp_synctarg_12 0x54 - #define hp_synctarg_13 0x55 - #define hp_synctarg_14 0x56 - #define hp_synctarg_15 0x57 - - #define hp_synctarg_8 0x58 - #define hp_synctarg_9 0x59 - #define hp_synctarg_10 0x5A - #define hp_synctarg_11 0x5B - - #define hp_synctarg_4 0x5C - #define hp_synctarg_5 0x5D - #define hp_synctarg_6 0x5E - #define hp_synctarg_7 0x5F - - #define hp_synctarg_0 0x60 - #define hp_synctarg_1 0x61 - #define hp_synctarg_2 0x62 - #define hp_synctarg_3 0x63 - - #define NARROW_SCSI BIT(4) - #define DEFAULT_OFFSET 0x0F - - #define hp_autostart_0 0x64 - #define hp_autostart_1 0x65 - #define hp_autostart_3 0x67 - - - - #define AUTO_IMMED BIT(5) - #define SELECT BIT(6) - #define END_DATA (BIT(7)+BIT(6)) - - #define hp_gp_reg_0 0x68 - #define hp_gp_reg_1 0x69 - #define hp_gp_reg_3 0x6B - - #define hp_seltimeout 0x6C - - - #define TO_4ms 0x67 /* 3.9959ms */ - - #define TO_5ms 0x03 /* 4.9152ms */ - #define TO_10ms 0x07 /* 11.xxxms */ - #define TO_250ms 0x99 /* 250.68ms */ - #define TO_290ms 0xB1 /* 289.99ms */ +#define hp_int_status 0x37 + +#define EXT_STATUS_ON BIT(1) /*Extended status is valid */ +#define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */ +#define INT_ASSERTED BIT(5) /* */ + +#define hp_fifo_cnt 0x38 + +#define hp_intena 0x40 + +#define RESET BITW(7) +#define PROG_HLT BITW(6) +#define PARITY BITW(5) +#define FIFO BITW(4) +#define SEL BITW(3) +#define SCAM_SEL BITW(2) +#define RSEL BITW(1) +#define TIMEOUT BITW(0) +#define BUS_FREE BITW(15) +#define XFER_CNT_0 BITW(14) +#define PHASE BITW(13) +#define IUNKWN BITW(12) +#define ICMD_COMP BITW(11) +#define ITICKLE BITW(10) +#define IDO_STRT BITW(9) +#define ITAR_DISC BITW(8) +#define AUTO_INT (BITW(12)+BITW(11)+BITW(10)+BITW(9)+BITW(8)) +#define CLR_ALL_INT 0xFFFF +#define CLR_ALL_INT_1 0xFF00 + +#define hp_intstat 0x42 + +#define hp_scsisig 0x44 + +#define SCSI_SEL BIT(7) +#define SCSI_BSY BIT(6) +#define SCSI_REQ BIT(5) +#define SCSI_ACK BIT(4) +#define SCSI_ATN BIT(3) +#define SCSI_CD BIT(2) +#define SCSI_MSG BIT(1) +#define SCSI_IOBIT BIT(0) + +#define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0)) +#define S_MSGO_PH (BIT(2)+BIT(1) ) +#define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0)) +#define S_DATAI_PH ( BIT(0)) +#define S_DATAO_PH 0x00 +#define S_ILL_PH ( BIT(1) ) + +#define hp_scsictrl_0 0x45 + +#define SEL_TAR BIT(6) +#define ENA_ATN BIT(4) +#define ENA_RESEL BIT(2) +#define SCSI_RST BIT(1) +#define ENA_SCAM_SEL BIT(0) - #define hp_clkctrl_0 0x6D +#define hp_portctrl_0 0x46 - #define PWR_DWN BIT(6) - #define ACTdeassert BIT(4) - #define CLK_40MHZ (BIT(1) + BIT(0)) +#define SCSI_PORT BIT(7) +#define SCSI_INBIT BIT(6) +#define DMA_PORT BIT(5) +#define DMA_RD BIT(4) +#define HOST_PORT BIT(3) +#define HOST_WRT BIT(2) +#define SCSI_BUS_EN BIT(1) +#define START_TO BIT(0) - #define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ) +#define hp_scsireset 0x47 - #define hp_fiforead 0x6E - #define hp_fifowrite 0x6F +#define SCSI_INI BIT(6) +#define SCAM_EN BIT(5) +#define DMA_RESET BIT(3) +#define HPSCSI_RESET BIT(2) +#define PROG_RESET BIT(1) +#define FIFO_CLR BIT(0) - #define hp_offsetctr 0x70 - #define hp_xferstat 0x71 +#define hp_xfercnt_0 0x48 +#define hp_xfercnt_2 0x4A - #define FIFO_EMPTY BIT(6) +#define hp_fifodata_0 0x4C +#define hp_addstat 0x4E - #define hp_portctrl_1 0x72 +#define SCAM_TIMER BIT(7) +#define SCSI_MODE8 BIT(3) +#define SCSI_PAR_ERR BIT(0) - #define CHK_SCSI_P BIT(3) - #define HOST_MODE8 BIT(0) +#define hp_prgmcnt_0 0x4F - #define hp_xfer_pad 0x73 +#define hp_selfid_0 0x50 +#define hp_selfid_1 0x51 +#define hp_arb_id 0x52 - #define ID_UNLOCK BIT(3) +#define hp_select_id 0x53 - #define hp_scsidata_0 0x74 - #define hp_scsidata_1 0x75 +#define hp_synctarg_base 0x54 +#define hp_synctarg_12 0x54 +#define hp_synctarg_13 0x55 +#define hp_synctarg_14 0x56 +#define hp_synctarg_15 0x57 +#define hp_synctarg_8 0x58 +#define hp_synctarg_9 0x59 +#define hp_synctarg_10 0x5A +#define hp_synctarg_11 0x5B +#define hp_synctarg_4 0x5C +#define hp_synctarg_5 0x5D +#define hp_synctarg_6 0x5E +#define hp_synctarg_7 0x5F - #define hp_aramBase 0x80 - #define BIOS_DATA_OFFSET 0x60 - #define BIOS_RELATIVE_CARD 0x64 +#define hp_synctarg_0 0x60 +#define hp_synctarg_1 0x61 +#define hp_synctarg_2 0x62 +#define hp_synctarg_3 0x63 +#define NARROW_SCSI BIT(4) +#define DEFAULT_OFFSET 0x0F +#define hp_autostart_0 0x64 +#define hp_autostart_1 0x65 +#define hp_autostart_3 0x67 +#define AUTO_IMMED BIT(5) +#define SELECT BIT(6) +#define END_DATA (BIT(7)+BIT(6)) - #define AR3 (BITW(9) + BITW(8)) - #define SDATA BITW(10) +#define hp_gp_reg_0 0x68 +#define hp_gp_reg_1 0x69 +#define hp_gp_reg_3 0x6B +#define hp_seltimeout 0x6C - #define CRD_OP BITW(11) /* Cmp Reg. w/ Data */ +#define TO_4ms 0x67 /* 3.9959ms */ - #define CRR_OP BITW(12) /* Cmp Reg. w. Reg. */ +#define TO_5ms 0x03 /* 4.9152ms */ +#define TO_10ms 0x07 /* 11.xxxms */ +#define TO_250ms 0x99 /* 250.68ms */ +#define TO_290ms 0xB1 /* 289.99ms */ - - - #define CPE_OP (BITW(14)+BITW(11)) /* Cmp SCSI phs & Branch EQ */ +#define hp_clkctrl_0 0x6D - #define CPN_OP (BITW(14)+BITW(12)) /* Cmp SCSI phs & Branch NOT EQ */ +#define PWR_DWN BIT(6) +#define ACTdeassert BIT(4) +#define CLK_40MHZ (BIT(1) + BIT(0)) +#define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ) - #define ADATA_OUT 0x00 - #define ADATA_IN BITW(8) - #define ACOMMAND BITW(10) - #define ASTATUS (BITW(10)+BITW(8)) - #define AMSG_OUT (BITW(10)+BITW(9)) - #define AMSG_IN (BITW(10)+BITW(9)+BITW(8)) +#define hp_fiforead 0x6E +#define hp_fifowrite 0x6F +#define hp_offsetctr 0x70 +#define hp_xferstat 0x71 - #define BRH_OP BITW(13) /* Branch */ +#define FIFO_EMPTY BIT(6) - - #define ALWAYS 0x00 - #define EQUAL BITW(8) - #define NOT_EQ BITW(9) +#define hp_portctrl_1 0x72 - #define TCB_OP (BITW(13)+BITW(11)) /* Test condition & branch */ +#define CHK_SCSI_P BIT(3) +#define HOST_MODE8 BIT(0) - - #define FIFO_0 BITW(10) +#define hp_xfer_pad 0x73 +#define ID_UNLOCK BIT(3) - #define MPM_OP BITW(15) /* Match phase and move data */ +#define hp_scsidata_0 0x74 +#define hp_scsidata_1 0x75 +#define hp_aramBase 0x80 +#define BIOS_DATA_OFFSET 0x60 +#define BIOS_RELATIVE_CARD 0x64 - #define MRR_OP BITW(14) /* Move DReg. to Reg. */ +#define AR3 (BITW(9) + BITW(8)) +#define SDATA BITW(10) +#define CRD_OP BITW(11) /* Cmp Reg. w/ Data */ - #define S_IDREG (BIT(2)+BIT(1)+BIT(0)) +#define CRR_OP BITW(12) /* Cmp Reg. w. Reg. */ +#define CPE_OP (BITW(14)+BITW(11)) /* Cmp SCSI phs & Branch EQ */ - #define D_AR0 0x00 - #define D_AR1 BIT(0) - #define D_BUCKET (BIT(2) + BIT(1) + BIT(0)) +#define CPN_OP (BITW(14)+BITW(12)) /* Cmp SCSI phs & Branch NOT EQ */ +#define ADATA_OUT 0x00 +#define ADATA_IN BITW(8) +#define ACOMMAND BITW(10) +#define ASTATUS (BITW(10)+BITW(8)) +#define AMSG_OUT (BITW(10)+BITW(9)) +#define AMSG_IN (BITW(10)+BITW(9)+BITW(8)) +#define BRH_OP BITW(13) /* Branch */ +#define ALWAYS 0x00 +#define EQUAL BITW(8) +#define NOT_EQ BITW(9) +#define TCB_OP (BITW(13)+BITW(11)) /* Test condition & branch */ +#define FIFO_0 BITW(10) +#define MPM_OP BITW(15) /* Match phase and move data */ +#define MRR_OP BITW(14) /* Move DReg. to Reg. */ +#define S_IDREG (BIT(2)+BIT(1)+BIT(0)) - #define RAT_OP (BITW(14)+BITW(13)+BITW(11)) - - #define SSI_OP (BITW(15)+BITW(11)) - - - #define SSI_ITAR_DISC (ITAR_DISC >> 8) - #define SSI_IDO_STRT (IDO_STRT >> 8) - - #define SSI_ICMD_COMP (ICMD_COMP >> 8) - #define SSI_ITICKLE (ITICKLE >> 8) - - #define SSI_IUNKWN (IUNKWN >> 8) - #define SSI_INO_CC (IUNKWN >> 8) - #define SSI_IRFAIL (IUNKWN >> 8) - - - #define NP 0x10 /*Next Phase */ - #define NTCMD 0x02 /*Non- Tagged Command start */ - #define CMDPZ 0x04 /*Command phase */ - #define DINT 0x12 /*Data Out/In interrupt */ - #define DI 0x13 /*Data Out */ - #define DC 0x19 /*Disconnect Message */ - #define ST 0x1D /*Status Phase */ - #define UNKNWN 0x24 /*Unknown bus action */ - #define CC 0x25 /*Command Completion failure */ - #define TICK 0x26 /*New target reselected us. */ - #define SELCHK 0x28 /*Select & Check SCSI ID latch reg */ - - - #define ID_MSG_STRT hp_aramBase + 0x00 - #define NON_TAG_ID_MSG hp_aramBase + 0x06 - #define CMD_STRT hp_aramBase + 0x08 - #define SYNC_MSGS hp_aramBase + 0x08 - - - - - - #define TAG_STRT 0x00 - #define DISCONNECT_START 0x10/2 - #define END_DATA_START 0x14/2 - #define CMD_ONLY_STRT CMDPZ/2 - #define SELCHK_STRT SELCHK/2 +#define D_AR0 0x00 +#define D_AR1 BIT(0) +#define D_BUCKET (BIT(2) + BIT(1) + BIT(0)) +#define RAT_OP (BITW(14)+BITW(13)+BITW(11)) +#define SSI_OP (BITW(15)+BITW(11)) +#define SSI_ITAR_DISC (ITAR_DISC >> 8) +#define SSI_IDO_STRT (IDO_STRT >> 8) +#define SSI_ICMD_COMP (ICMD_COMP >> 8) +#define SSI_ITICKLE (ITICKLE >> 8) +#define SSI_IUNKWN (IUNKWN >> 8) +#define SSI_INO_CC (IUNKWN >> 8) +#define SSI_IRFAIL (IUNKWN >> 8) +#define NP 0x10 /*Next Phase */ +#define NTCMD 0x02 /*Non- Tagged Command start */ +#define CMDPZ 0x04 /*Command phase */ +#define DINT 0x12 /*Data Out/In interrupt */ +#define DI 0x13 /*Data Out */ +#define DC 0x19 /*Disconnect Message */ +#define ST 0x1D /*Status Phase */ +#define UNKNWN 0x24 /*Unknown bus action */ +#define CC 0x25 /*Command Completion failure */ +#define TICK 0x26 /*New target reselected us. */ +#define SELCHK 0x28 /*Select & Check SCSI ID latch reg */ +#define ID_MSG_STRT hp_aramBase + 0x00 +#define NON_TAG_ID_MSG hp_aramBase + 0x06 +#define CMD_STRT hp_aramBase + 0x08 +#define SYNC_MSGS hp_aramBase + 0x08 +#define TAG_STRT 0x00 +#define DISCONNECT_START 0x10/2 +#define END_DATA_START 0x14/2 +#define CMD_ONLY_STRT CMDPZ/2 +#define SELCHK_STRT SELCHK/2 #define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;} /* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \ @@ -941,12 +766,9 @@ typedef struct SCCBscam_info { #define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ WR_HARPOON(port+hp_scsisig, S_ILL_PH);} - #define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));} - - #define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\ WR_HARPOON(port+hp_scsireset, 0x00)) @@ -962,139 +784,146 @@ typedef struct SCCBscam_info { #define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE))) - - - -static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, unsigned char syncFlag); -static void FPT_ssel(unsigned long port, unsigned char p_card); -static void FPT_sres(unsigned long port, unsigned char p_card, struct sccb_card * pCurrCard); -static void FPT_shandem(unsigned long port, unsigned char p_card,struct sccb * pCurrSCCB); -static void FPT_stsyncn(unsigned long port, unsigned char p_card); -static void FPT_sisyncr(unsigned long port,unsigned char sync_pulse, unsigned char offset); -static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, unsigned char p_sync_value, - struct sccb_mgr_tar_info * currTar_Info); -static void FPT_sresb(unsigned long port, unsigned char p_card); -static void FPT_sxfrp(unsigned long p_port, unsigned char p_card); -static void FPT_schkdd(unsigned long port, unsigned char p_card); +static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, + unsigned char syncFlag); +static void FPT_ssel(unsigned long port, unsigned char p_card); +static void FPT_sres(unsigned long port, unsigned char p_card, + struct sccb_card *pCurrCard); +static void FPT_shandem(unsigned long port, unsigned char p_card, + struct sccb *pCurrSCCB); +static void FPT_stsyncn(unsigned long port, unsigned char p_card); +static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse, + unsigned char offset); +static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, + unsigned char p_sync_value, + struct sccb_mgr_tar_info *currTar_Info); +static void FPT_sresb(unsigned long port, unsigned char p_card); +static void FPT_sxfrp(unsigned long p_port, unsigned char p_card); +static void FPT_schkdd(unsigned long port, unsigned char p_card); static unsigned char FPT_RdStack(unsigned long port, unsigned char index); -static void FPT_WrStack(unsigned long portBase, unsigned char index, unsigned char data); +static void FPT_WrStack(unsigned long portBase, unsigned char index, + unsigned char data); static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort); static void FPT_SendMsg(unsigned long port, unsigned char message); -static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg, - unsigned char error_code); +static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg, + unsigned char error_code); -static void FPT_sinits(struct sccb * p_sccb, unsigned char p_card); -static void FPT_RNVRamData(struct nvram_info * pNvRamInfo); +static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card); +static void FPT_RNVRamData(struct nvram_info *pNvRamInfo); static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card); -static void FPT_stwidn(unsigned long port, unsigned char p_card); -static void FPT_siwidr(unsigned long port, unsigned char width); - - -static void FPT_queueSelectFail(struct sccb_card * pCurrCard, unsigned char p_card); -static void FPT_queueDisconnect(struct sccb * p_SCCB, unsigned char p_card); -static void FPT_queueCmdComplete(struct sccb_card * pCurrCard, struct sccb * p_SCCB, +static void FPT_stwidn(unsigned long port, unsigned char p_card); +static void FPT_siwidr(unsigned long port, unsigned char width); + +static void FPT_queueSelectFail(struct sccb_card *pCurrCard, + unsigned char p_card); +static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card); +static void FPT_queueCmdComplete(struct sccb_card *pCurrCard, + struct sccb *p_SCCB, unsigned char p_card); +static void FPT_queueSearchSelect(struct sccb_card *pCurrCard, unsigned char p_card); -static void FPT_queueSearchSelect(struct sccb_card * pCurrCard, unsigned char p_card); -static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code); -static void FPT_queueAddSccb(struct sccb * p_SCCB, unsigned char card); -static unsigned char FPT_queueFindSccb(struct sccb * p_SCCB, unsigned char p_card); -static void FPT_utilUpdateResidual(struct sccb * p_SCCB); +static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code); +static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card); +static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB, + unsigned char p_card); +static void FPT_utilUpdateResidual(struct sccb *p_SCCB); static unsigned short FPT_CalcCrc16(unsigned char buffer[]); -static unsigned char FPT_CalcLrc(unsigned char buffer[]); - - -static void FPT_Wait1Second(unsigned long p_port); -static void FPT_Wait(unsigned long p_port, unsigned char p_delay); -static void FPT_utilEEWriteOnOff(unsigned long p_port,unsigned char p_mode); -static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data, unsigned short ee_addr); -static unsigned short FPT_utilEERead(unsigned long p_port, unsigned short ee_addr); -static unsigned short FPT_utilEEReadOrg(unsigned long p_port, unsigned short ee_addr); -static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd, unsigned short ee_addr); - - - -static void FPT_phaseDataOut(unsigned long port, unsigned char p_card); -static void FPT_phaseDataIn(unsigned long port, unsigned char p_card); -static void FPT_phaseCommand(unsigned long port, unsigned char p_card); -static void FPT_phaseStatus(unsigned long port, unsigned char p_card); -static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card); -static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card); -static void FPT_phaseIllegal(unsigned long port, unsigned char p_card); - -static void FPT_phaseDecode(unsigned long port, unsigned char p_card); -static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card); -static void FPT_phaseBusFree(unsigned long p_port, unsigned char p_card); - - - - -static void FPT_XbowInit(unsigned long port, unsigned char scamFlg); -static void FPT_BusMasterInit(unsigned long p_port); -static void FPT_DiagEEPROM(unsigned long p_port); - - - - -static void FPT_dataXferProcessor(unsigned long port, struct sccb_card * pCurrCard); -static void FPT_busMstrSGDataXferStart(unsigned long port, struct sccb * pCurrSCCB); -static void FPT_busMstrDataXferStart(unsigned long port, struct sccb * pCurrSCCB); -static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, struct sccb * pCurrSCCB); -static void FPT_hostDataXferRestart(struct sccb * currSCCB); - - -static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, unsigned char p_card, - struct sccb_card * pCurrCard, unsigned short p_int); - -static void FPT_SccbMgrTableInitAll(void); -static void FPT_SccbMgrTableInitCard(struct sccb_card * pCurrCard, unsigned char p_card); -static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char target); - - - -static void FPT_scini(unsigned char p_card, unsigned char p_our_id, unsigned char p_power_up); - -static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type); -static void FPT_scbusf(unsigned long p_port); -static void FPT_scsel(unsigned long p_port); -static void FPT_scasid(unsigned char p_card, unsigned long p_port); +static unsigned char FPT_CalcLrc(unsigned char buffer[]); + +static void FPT_Wait1Second(unsigned long p_port); +static void FPT_Wait(unsigned long p_port, unsigned char p_delay); +static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode); +static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data, + unsigned short ee_addr); +static unsigned short FPT_utilEERead(unsigned long p_port, + unsigned short ee_addr); +static unsigned short FPT_utilEEReadOrg(unsigned long p_port, + unsigned short ee_addr); +static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd, + unsigned short ee_addr); + +static void FPT_phaseDataOut(unsigned long port, unsigned char p_card); +static void FPT_phaseDataIn(unsigned long port, unsigned char p_card); +static void FPT_phaseCommand(unsigned long port, unsigned char p_card); +static void FPT_phaseStatus(unsigned long port, unsigned char p_card); +static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card); +static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card); +static void FPT_phaseIllegal(unsigned long port, unsigned char p_card); + +static void FPT_phaseDecode(unsigned long port, unsigned char p_card); +static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card); +static void FPT_phaseBusFree(unsigned long p_port, unsigned char p_card); + +static void FPT_XbowInit(unsigned long port, unsigned char scamFlg); +static void FPT_BusMasterInit(unsigned long p_port); +static void FPT_DiagEEPROM(unsigned long p_port); + +static void FPT_dataXferProcessor(unsigned long port, + struct sccb_card *pCurrCard); +static void FPT_busMstrSGDataXferStart(unsigned long port, + struct sccb *pCurrSCCB); +static void FPT_busMstrDataXferStart(unsigned long port, + struct sccb *pCurrSCCB); +static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, + struct sccb *pCurrSCCB); +static void FPT_hostDataXferRestart(struct sccb *currSCCB); + +static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, + unsigned char p_card, + struct sccb_card *pCurrCard, + unsigned short p_int); + +static void FPT_SccbMgrTableInitAll(void); +static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard, + unsigned char p_card); +static void FPT_SccbMgrTableInitTarget(unsigned char p_card, + unsigned char target); + +static void FPT_scini(unsigned char p_card, unsigned char p_our_id, + unsigned char p_power_up); + +static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type); +static void FPT_scbusf(unsigned long p_port); +static void FPT_scsel(unsigned long p_port); +static void FPT_scasid(unsigned char p_card, unsigned long p_port); static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data); -static unsigned char FPT_scsendi(unsigned long p_port, unsigned char p_id_string[]); -static unsigned char FPT_sciso(unsigned long p_port, unsigned char p_id_string[]); -static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit); -static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit); +static unsigned char FPT_scsendi(unsigned long p_port, + unsigned char p_id_string[]); +static unsigned char FPT_sciso(unsigned long p_port, + unsigned char p_id_string[]); +static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit); +static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit); static unsigned char FPT_scvalq(unsigned char p_quintet); static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id); -static void FPT_scwtsel(unsigned long p_port); -static void FPT_inisci(unsigned char p_card, unsigned long p_port, unsigned char p_our_id); -static void FPT_scsavdi(unsigned char p_card, unsigned long p_port); -static unsigned char FPT_scmachid(unsigned char p_card, unsigned char p_id_string[]); - - -static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card); -static void FPT_autoLoadDefaultMap(unsigned long p_port); - - - - -static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } }; -static struct sccb_card FPT_BL_Card[MAX_CARDS] = { { 0 } }; -static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { { { 0 } } }; -static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { { 0 } }; - +static void FPT_scwtsel(unsigned long p_port); +static void FPT_inisci(unsigned char p_card, unsigned long p_port, + unsigned char p_our_id); +static void FPT_scsavdi(unsigned char p_card, unsigned long p_port); +static unsigned char FPT_scmachid(unsigned char p_card, + unsigned char p_id_string[]); + +static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card); +static void FPT_autoLoadDefaultMap(unsigned long p_port); + +static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = + { {{0}} }; +static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} }; +static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} }; +static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} }; static unsigned char FPT_mbCards = 0; -static unsigned char FPT_scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', \ - ' ', 'B', 'T', '-', '9', '3', '0', \ - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \ - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; +static unsigned char FPT_scamHAString[] = + { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', + ' ', 'B', 'T', '-', '9', '3', '0', + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 +}; static unsigned short FPT_default_intena = 0; - -static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char)= { 0 }; - +static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char) = { +0}; /*--------------------------------------------------------------------- * @@ -1104,276 +933,270 @@ static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char)= { 0 }; * *---------------------------------------------------------------------*/ -static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info * pCardInfo) +static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo) { - static unsigned char first_time = 1; - - unsigned char i,j,id,ScamFlg; - unsigned short temp,temp2,temp3,temp4,temp5,temp6; - unsigned long ioport; - struct nvram_info * pCurrNvRam; - - ioport = pCardInfo->si_baseaddr; + static unsigned char first_time = 1; + unsigned char i, j, id, ScamFlg; + unsigned short temp, temp2, temp3, temp4, temp5, temp6; + unsigned long ioport; + struct nvram_info *pCurrNvRam; - if (RD_HARPOON(ioport+hp_vendor_id_0) != ORION_VEND_0) - return((int)FAILURE); + ioport = pCardInfo->si_baseaddr; - if ((RD_HARPOON(ioport+hp_vendor_id_1) != ORION_VEND_1)) - return((int)FAILURE); + if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0) + return ((int)FAILURE); - if ((RD_HARPOON(ioport+hp_device_id_0) != ORION_DEV_0)) - return((int)FAILURE); + if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1)) + return ((int)FAILURE); - if ((RD_HARPOON(ioport+hp_device_id_1) != ORION_DEV_1)) - return((int)FAILURE); + if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0)) + return ((int)FAILURE); + if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1)) + return ((int)FAILURE); - if (RD_HARPOON(ioport+hp_rev_num) != 0x0f){ + if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) { /* For new Harpoon then check for sub_device ID LSB the bits(0-3) must be all ZERO for compatible with current version of SCCBMgr, else skip this Harpoon device. */ - if (RD_HARPOON(ioport+hp_sub_device_id_0) & 0x0f) - return((int)FAILURE); + if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f) + return ((int)FAILURE); } - if (first_time) - { - FPT_SccbMgrTableInitAll(); - first_time = 0; + if (first_time) { + FPT_SccbMgrTableInitAll(); + first_time = 0; FPT_mbCards = 0; - } + } - if(FPT_RdStack(ioport, 0) != 0x00) { - if(FPT_ChkIfChipInitialized(ioport) == 0) - { + if (FPT_RdStack(ioport, 0) != 0x00) { + if (FPT_ChkIfChipInitialized(ioport) == 0) { pCurrNvRam = NULL; - WR_HARPOON(ioport+hp_semaphore, 0x00); - FPT_XbowInit(ioport, 0); /*Must Init the SCSI before attempting */ + WR_HARPOON(ioport + hp_semaphore, 0x00); + FPT_XbowInit(ioport, 0); /*Must Init the SCSI before attempting */ FPT_DiagEEPROM(ioport); - } - else - { - if(FPT_mbCards < MAX_MB_CARDS) { + } else { + if (FPT_mbCards < MAX_MB_CARDS) { pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards]; FPT_mbCards++; pCurrNvRam->niBaseAddr = ioport; FPT_RNVRamData(pCurrNvRam); - }else - return((int) FAILURE); + } else + return ((int)FAILURE); } - }else + } else pCurrNvRam = NULL; - WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT); - WR_HARPOON(ioport+hp_sys_ctrl, 0x00); + WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT); + WR_HARPOON(ioport + hp_sys_ctrl, 0x00); - if(pCurrNvRam) + if (pCurrNvRam) pCardInfo->si_id = pCurrNvRam->niAdapId; else - pCardInfo->si_id = (unsigned char)(FPT_utilEERead(ioport, (ADAPTER_SCSI_ID/2)) & - (unsigned char)0x0FF); + pCardInfo->si_id = + (unsigned + char)(FPT_utilEERead(ioport, + (ADAPTER_SCSI_ID / + 2)) & (unsigned char)0x0FF); + + pCardInfo->si_lun = 0x00; + pCardInfo->si_fw_revision = ORION_FW_REV; + temp2 = 0x0000; + temp3 = 0x0000; + temp4 = 0x0000; + temp5 = 0x0000; + temp6 = 0x0000; + + for (id = 0; id < (16 / 2); id++) { + + if (pCurrNvRam) { + temp = (unsigned short)pCurrNvRam->niSyncTbl[id]; + temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + + (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); + } else + temp = + FPT_utilEERead(ioport, + (unsigned short)((SYNC_RATE_TBL / 2) + + id)); + + for (i = 0; i < 2; temp >>= 8, i++) { + + temp2 >>= 1; + temp3 >>= 1; + temp4 >>= 1; + temp5 >>= 1; + temp6 >>= 1; + switch (temp & 0x3) { + case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */ + temp6 |= 0x8000; /* Fall through */ + case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */ + temp5 |= 0x8000; /* Fall through */ + case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */ + temp2 |= 0x8000; /* Fall through */ + case AUTO_RATE_00: /* Asynchronous */ + break; + } - pCardInfo->si_lun = 0x00; - pCardInfo->si_fw_revision = ORION_FW_REV; - temp2 = 0x0000; - temp3 = 0x0000; - temp4 = 0x0000; - temp5 = 0x0000; - temp6 = 0x0000; + if (temp & DISC_ENABLE_BIT) + temp3 |= 0x8000; - for (id = 0; id < (16/2); id++) { + if (temp & WIDE_NEGO_BIT) + temp4 |= 0x8000; - if(pCurrNvRam){ - temp = (unsigned short) pCurrNvRam->niSyncTbl[id]; - temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + - (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); - }else - temp = FPT_utilEERead(ioport, (unsigned short)((SYNC_RATE_TBL/2)+id)); - - for (i = 0; i < 2; temp >>=8,i++) { - - temp2 >>= 1; - temp3 >>= 1; - temp4 >>= 1; - temp5 >>= 1; - temp6 >>= 1; - switch (temp & 0x3) - { - case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */ - temp6 |= 0x8000; /* Fall through */ - case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */ - temp5 |= 0x8000; /* Fall through */ - case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */ - temp2 |= 0x8000; /* Fall through */ - case AUTO_RATE_00: /* Asynchronous */ - break; - } - - if (temp & DISC_ENABLE_BIT) - temp3 |= 0x8000; - - if (temp & WIDE_NEGO_BIT) - temp4 |= 0x8000; - - } - } + } + } - pCardInfo->si_per_targ_init_sync = temp2; - pCardInfo->si_per_targ_no_disc = temp3; - pCardInfo->si_per_targ_wide_nego = temp4; - pCardInfo->si_per_targ_fast_nego = temp5; - pCardInfo->si_per_targ_ultra_nego = temp6; + pCardInfo->si_per_targ_init_sync = temp2; + pCardInfo->si_per_targ_no_disc = temp3; + pCardInfo->si_per_targ_wide_nego = temp4; + pCardInfo->si_per_targ_fast_nego = temp5; + pCardInfo->si_per_targ_ultra_nego = temp6; - if(pCurrNvRam) + if (pCurrNvRam) i = pCurrNvRam->niSysConf; else - i = (unsigned char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG/2))); + i = (unsigned + char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2))); - if(pCurrNvRam) + if (pCurrNvRam) ScamFlg = pCurrNvRam->niScamConf; else - ScamFlg = (unsigned char) FPT_utilEERead(ioport, SCAM_CONFIG/2); + ScamFlg = + (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2); - pCardInfo->si_flags = 0x0000; + pCardInfo->si_flags = 0x0000; - if (i & 0x01) - pCardInfo->si_flags |= SCSI_PARITY_ENA; + if (i & 0x01) + pCardInfo->si_flags |= SCSI_PARITY_ENA; - if (!(i & 0x02)) - pCardInfo->si_flags |= SOFT_RESET; + if (!(i & 0x02)) + pCardInfo->si_flags |= SOFT_RESET; - if (i & 0x10) - pCardInfo->si_flags |= EXTENDED_TRANSLATION; + if (i & 0x10) + pCardInfo->si_flags |= EXTENDED_TRANSLATION; - if (ScamFlg & SCAM_ENABLED) - pCardInfo->si_flags |= FLAG_SCAM_ENABLED; + if (ScamFlg & SCAM_ENABLED) + pCardInfo->si_flags |= FLAG_SCAM_ENABLED; - if (ScamFlg & SCAM_LEVEL2) - pCardInfo->si_flags |= FLAG_SCAM_LEVEL2; + if (ScamFlg & SCAM_LEVEL2) + pCardInfo->si_flags |= FLAG_SCAM_LEVEL2; - j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L); - if (i & 0x04) { - j |= SCSI_TERM_ENA_L; - } - WR_HARPOON(ioport+hp_bm_ctrl, j ); + j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L); + if (i & 0x04) { + j |= SCSI_TERM_ENA_L; + } + WR_HARPOON(ioport + hp_bm_ctrl, j); - j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H); - if (i & 0x08) { - j |= SCSI_TERM_ENA_H; - } - WR_HARPOON(ioport+hp_ee_ctrl, j ); + j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H); + if (i & 0x08) { + j |= SCSI_TERM_ENA_H; + } + WR_HARPOON(ioport + hp_ee_ctrl, j); + + if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD)) + + pCardInfo->si_flags |= SUPPORT_16TAR_32LUN; + + pCardInfo->si_card_family = HARPOON_FAMILY; + pCardInfo->si_bustype = BUSTYPE_PCI; + + if (pCurrNvRam) { + pCardInfo->si_card_model[0] = '9'; + switch (pCurrNvRam->niModel & 0x0f) { + case MODEL_LT: + pCardInfo->si_card_model[1] = '3'; + pCardInfo->si_card_model[2] = '0'; + break; + case MODEL_LW: + pCardInfo->si_card_model[1] = '5'; + pCardInfo->si_card_model[2] = '0'; + break; + case MODEL_DL: + pCardInfo->si_card_model[1] = '3'; + pCardInfo->si_card_model[2] = '2'; + break; + case MODEL_DW: + pCardInfo->si_card_model[1] = '5'; + pCardInfo->si_card_model[2] = '2'; + break; + } + } else { + temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2)); + pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8); + temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2)); - if (!(RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD)) + pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF); + pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8); + } - pCardInfo->si_flags |= SUPPORT_16TAR_32LUN; + if (pCardInfo->si_card_model[1] == '3') { + if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)) + pCardInfo->si_flags |= LOW_BYTE_TERM; + } else if (pCardInfo->si_card_model[2] == '0') { + temp = RD_HARPOON(ioport + hp_xfer_pad); + WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4))); + if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)) + pCardInfo->si_flags |= LOW_BYTE_TERM; + WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4))); + if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)) + pCardInfo->si_flags |= HIGH_BYTE_TERM; + WR_HARPOON(ioport + hp_xfer_pad, temp); + } else { + temp = RD_HARPOON(ioport + hp_ee_ctrl); + temp2 = RD_HARPOON(ioport + hp_xfer_pad); + WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS)); + WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4))); + temp3 = 0; + for (i = 0; i < 8; i++) { + temp3 <<= 1; + if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))) + temp3 |= 1; + WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4))); + WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4))); + } + WR_HARPOON(ioport + hp_ee_ctrl, temp); + WR_HARPOON(ioport + hp_xfer_pad, temp2); + if (!(temp3 & BIT(7))) + pCardInfo->si_flags |= LOW_BYTE_TERM; + if (!(temp3 & BIT(6))) + pCardInfo->si_flags |= HIGH_BYTE_TERM; + } - pCardInfo->si_card_family = HARPOON_FAMILY; - pCardInfo->si_bustype = BUSTYPE_PCI; + ARAM_ACCESS(ioport); - if(pCurrNvRam){ - pCardInfo->si_card_model[0] = '9'; - switch(pCurrNvRam->niModel & 0x0f){ - case MODEL_LT: - pCardInfo->si_card_model[1] = '3'; - pCardInfo->si_card_model[2] = '0'; - break; - case MODEL_LW: - pCardInfo->si_card_model[1] = '5'; - pCardInfo->si_card_model[2] = '0'; - break; - case MODEL_DL: - pCardInfo->si_card_model[1] = '3'; - pCardInfo->si_card_model[2] = '2'; - break; - case MODEL_DW: - pCardInfo->si_card_model[1] = '5'; - pCardInfo->si_card_model[2] = '2'; - break; - } - }else{ - temp = FPT_utilEERead(ioport, (MODEL_NUMB_0/2)); - pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8); - temp = FPT_utilEERead(ioport, (MODEL_NUMB_2/2)); - - pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF); - pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8); - } - - if (pCardInfo->si_card_model[1] == '3') - { - if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7)) - pCardInfo->si_flags |= LOW_BYTE_TERM; - } - else if (pCardInfo->si_card_model[2] == '0') - { - temp = RD_HARPOON(ioport+hp_xfer_pad); - WR_HARPOON(ioport+hp_xfer_pad, (temp & ~BIT(4))); - if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7)) - pCardInfo->si_flags |= LOW_BYTE_TERM; - WR_HARPOON(ioport+hp_xfer_pad, (temp | BIT(4))); - if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7)) - pCardInfo->si_flags |= HIGH_BYTE_TERM; - WR_HARPOON(ioport+hp_xfer_pad, temp); - } - else - { - temp = RD_HARPOON(ioport+hp_ee_ctrl); - temp2 = RD_HARPOON(ioport+hp_xfer_pad); - WR_HARPOON(ioport+hp_ee_ctrl, (temp | SEE_CS)); - WR_HARPOON(ioport+hp_xfer_pad, (temp2 | BIT(4))); - temp3 = 0; - for (i = 0; i < 8; i++) - { - temp3 <<= 1; - if (!(RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7))) - temp3 |= 1; - WR_HARPOON(ioport+hp_xfer_pad, (temp2 & ~BIT(4))); - WR_HARPOON(ioport+hp_xfer_pad, (temp2 | BIT(4))); - } - WR_HARPOON(ioport+hp_ee_ctrl, temp); - WR_HARPOON(ioport+hp_xfer_pad, temp2); - if (!(temp3 & BIT(7))) - pCardInfo->si_flags |= LOW_BYTE_TERM; - if (!(temp3 & BIT(6))) - pCardInfo->si_flags |= HIGH_BYTE_TERM; - } - - - ARAM_ACCESS(ioport); - - for ( i = 0; i < 4; i++ ) { - - pCardInfo->si_XlatInfo[i] = - RD_HARPOON(ioport+hp_aramBase+BIOS_DATA_OFFSET+i); - } + for (i = 0; i < 4; i++) { + + pCardInfo->si_XlatInfo[i] = + RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i); + } /* return with -1 if no sort, else return with logical card number sorted by BIOS (zero-based) */ pCardInfo->si_relative_cardnum = - (unsigned char)(RD_HARPOON(ioport+hp_aramBase+BIOS_RELATIVE_CARD)-1); + (unsigned + char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1); - SGRAM_ACCESS(ioport); + SGRAM_ACCESS(ioport); - FPT_s_PhaseTbl[0] = FPT_phaseDataOut; - FPT_s_PhaseTbl[1] = FPT_phaseDataIn; - FPT_s_PhaseTbl[2] = FPT_phaseIllegal; - FPT_s_PhaseTbl[3] = FPT_phaseIllegal; - FPT_s_PhaseTbl[4] = FPT_phaseCommand; - FPT_s_PhaseTbl[5] = FPT_phaseStatus; - FPT_s_PhaseTbl[6] = FPT_phaseMsgOut; - FPT_s_PhaseTbl[7] = FPT_phaseMsgIn; + FPT_s_PhaseTbl[0] = FPT_phaseDataOut; + FPT_s_PhaseTbl[1] = FPT_phaseDataIn; + FPT_s_PhaseTbl[2] = FPT_phaseIllegal; + FPT_s_PhaseTbl[3] = FPT_phaseIllegal; + FPT_s_PhaseTbl[4] = FPT_phaseCommand; + FPT_s_PhaseTbl[5] = FPT_phaseStatus; + FPT_s_PhaseTbl[6] = FPT_phaseMsgOut; + FPT_s_PhaseTbl[7] = FPT_phaseMsgIn; - pCardInfo->si_present = 0x01; + pCardInfo->si_present = 0x01; - return(0); + return (0); } - /*--------------------------------------------------------------------- * * Function: FlashPoint_HardwareResetHostAdapter @@ -1382,185 +1205,190 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info * pCardInfo) * *---------------------------------------------------------------------*/ -static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info * pCardInfo) +static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info + *pCardInfo) { - struct sccb_card * CurrCard = NULL; - struct nvram_info * pCurrNvRam; - unsigned char i,j,thisCard, ScamFlg; - unsigned short temp,sync_bit_map,id; - unsigned long ioport; + struct sccb_card *CurrCard = NULL; + struct nvram_info *pCurrNvRam; + unsigned char i, j, thisCard, ScamFlg; + unsigned short temp, sync_bit_map, id; + unsigned long ioport; - ioport = pCardInfo->si_baseaddr; + ioport = pCardInfo->si_baseaddr; - for(thisCard =0; thisCard <= MAX_CARDS; thisCard++) { + for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) { - if (thisCard == MAX_CARDS) { + if (thisCard == MAX_CARDS) { - return(FAILURE); - } + return (FAILURE); + } - if (FPT_BL_Card[thisCard].ioPort == ioport) { + if (FPT_BL_Card[thisCard].ioPort == ioport) { - CurrCard = &FPT_BL_Card[thisCard]; - FPT_SccbMgrTableInitCard(CurrCard,thisCard); - break; - } + CurrCard = &FPT_BL_Card[thisCard]; + FPT_SccbMgrTableInitCard(CurrCard, thisCard); + break; + } - else if (FPT_BL_Card[thisCard].ioPort == 0x00) { + else if (FPT_BL_Card[thisCard].ioPort == 0x00) { - FPT_BL_Card[thisCard].ioPort = ioport; - CurrCard = &FPT_BL_Card[thisCard]; + FPT_BL_Card[thisCard].ioPort = ioport; + CurrCard = &FPT_BL_Card[thisCard]; - if(FPT_mbCards) - for(i = 0; i < FPT_mbCards; i++){ - if(CurrCard->ioPort == FPT_nvRamInfo[i].niBaseAddr) - CurrCard->pNvRamInfo = &FPT_nvRamInfo[i]; + if (FPT_mbCards) + for (i = 0; i < FPT_mbCards; i++) { + if (CurrCard->ioPort == + FPT_nvRamInfo[i].niBaseAddr) + CurrCard->pNvRamInfo = + &FPT_nvRamInfo[i]; } - FPT_SccbMgrTableInitCard(CurrCard,thisCard); - CurrCard->cardIndex = thisCard; - CurrCard->cardInfo = pCardInfo; + FPT_SccbMgrTableInitCard(CurrCard, thisCard); + CurrCard->cardIndex = thisCard; + CurrCard->cardInfo = pCardInfo; - break; - } - } + break; + } + } pCurrNvRam = CurrCard->pNvRamInfo; - if(pCurrNvRam){ + if (pCurrNvRam) { ScamFlg = pCurrNvRam->niScamConf; + } else { + ScamFlg = + (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2); } - else{ - ScamFlg = (unsigned char) FPT_utilEERead(ioport, SCAM_CONFIG/2); - } - - - FPT_BusMasterInit(ioport); - FPT_XbowInit(ioport, ScamFlg); - FPT_autoLoadDefaultMap(ioport); + FPT_BusMasterInit(ioport); + FPT_XbowInit(ioport, ScamFlg); + FPT_autoLoadDefaultMap(ioport); - for (i = 0,id = 0x01; i != pCardInfo->si_id; i++,id <<= 1){} - - WR_HARPOON(ioport+hp_selfid_0, id); - WR_HARPOON(ioport+hp_selfid_1, 0x00); - WR_HARPOON(ioport+hp_arb_id, pCardInfo->si_id); - CurrCard->ourId = pCardInfo->si_id; - - i = (unsigned char) pCardInfo->si_flags; - if (i & SCSI_PARITY_ENA) - WR_HARPOON(ioport+hp_portctrl_1,(HOST_MODE8 | CHK_SCSI_P)); + for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) { + } - j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L); - if (i & LOW_BYTE_TERM) - j |= SCSI_TERM_ENA_L; - WR_HARPOON(ioport+hp_bm_ctrl, j); + WR_HARPOON(ioport + hp_selfid_0, id); + WR_HARPOON(ioport + hp_selfid_1, 0x00); + WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id); + CurrCard->ourId = pCardInfo->si_id; - j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H); - if (i & HIGH_BYTE_TERM) - j |= SCSI_TERM_ENA_H; - WR_HARPOON(ioport+hp_ee_ctrl, j ); + i = (unsigned char)pCardInfo->si_flags; + if (i & SCSI_PARITY_ENA) + WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P)); + j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L); + if (i & LOW_BYTE_TERM) + j |= SCSI_TERM_ENA_L; + WR_HARPOON(ioport + hp_bm_ctrl, j); - if (!(pCardInfo->si_flags & SOFT_RESET)) { + j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H); + if (i & HIGH_BYTE_TERM) + j |= SCSI_TERM_ENA_H; + WR_HARPOON(ioport + hp_ee_ctrl, j); - FPT_sresb(ioport,thisCard); - - FPT_scini(thisCard, pCardInfo->si_id, 0); - } + if (!(pCardInfo->si_flags & SOFT_RESET)) { + FPT_sresb(ioport, thisCard); + FPT_scini(thisCard, pCardInfo->si_id, 0); + } - if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS) - CurrCard->globalFlags |= F_NO_FILTER; + if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS) + CurrCard->globalFlags |= F_NO_FILTER; - if(pCurrNvRam){ - if(pCurrNvRam->niSysConf & 0x10) + if (pCurrNvRam) { + if (pCurrNvRam->niSysConf & 0x10) + CurrCard->globalFlags |= F_GREEN_PC; + } else { + if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA) CurrCard->globalFlags |= F_GREEN_PC; - } - else{ - if (FPT_utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA) - CurrCard->globalFlags |= F_GREEN_PC; } /* Set global flag to indicate Re-Negotiation to be done on all - ckeck condition */ - if(pCurrNvRam){ - if(pCurrNvRam->niScsiConf & 0x04) + ckeck condition */ + if (pCurrNvRam) { + if (pCurrNvRam->niScsiConf & 0x04) + CurrCard->globalFlags |= F_DO_RENEGO; + } else { + if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA) CurrCard->globalFlags |= F_DO_RENEGO; - } - else{ - if (FPT_utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA) - CurrCard->globalFlags |= F_DO_RENEGO; } - if(pCurrNvRam){ - if(pCurrNvRam->niScsiConf & 0x08) + if (pCurrNvRam) { + if (pCurrNvRam->niScsiConf & 0x08) + CurrCard->globalFlags |= F_CONLUN_IO; + } else { + if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA) CurrCard->globalFlags |= F_CONLUN_IO; } - else{ - if (FPT_utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA) - CurrCard->globalFlags |= F_CONLUN_IO; - } - - temp = pCardInfo->si_per_targ_no_disc; + temp = pCardInfo->si_per_targ_no_disc; - for (i = 0,id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) { + for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) { - if (temp & id) - FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC; - } + if (temp & id) + FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC; + } - sync_bit_map = 0x0001; + sync_bit_map = 0x0001; - for (id = 0; id < (MAX_SCSI_TAR/2); id++) { + for (id = 0; id < (MAX_SCSI_TAR / 2); id++) { - if(pCurrNvRam){ - temp = (unsigned short) pCurrNvRam->niSyncTbl[id]; + if (pCurrNvRam) { + temp = (unsigned short)pCurrNvRam->niSyncTbl[id]; temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + - (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); - }else - temp = FPT_utilEERead(ioport, (unsigned short)((SYNC_RATE_TBL/2)+id)); + (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); + } else + temp = + FPT_utilEERead(ioport, + (unsigned short)((SYNC_RATE_TBL / 2) + + id)); - for (i = 0; i < 2; temp >>=8,i++) { + for (i = 0; i < 2; temp >>= 8, i++) { - if (pCardInfo->si_per_targ_init_sync & sync_bit_map) { + if (pCardInfo->si_per_targ_init_sync & sync_bit_map) { - FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue = (unsigned char)temp; - } + FPT_sccbMgrTbl[thisCard][id * 2 + + i].TarEEValue = + (unsigned char)temp; + } - else { - FPT_sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED; - FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue = - (unsigned char)(temp & ~EE_SYNC_MASK); - } + else { + FPT_sccbMgrTbl[thisCard][id * 2 + + i].TarStatus |= + SYNC_SUPPORTED; + FPT_sccbMgrTbl[thisCard][id * 2 + + i].TarEEValue = + (unsigned char)(temp & ~EE_SYNC_MASK); + } /* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) || (id*2+i >= 8)){ */ - if (pCardInfo->si_per_targ_wide_nego & sync_bit_map){ - - FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI; + if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) { - } + FPT_sccbMgrTbl[thisCard][id * 2 + + i].TarEEValue |= + EE_WIDE_SCSI; - else { /* NARROW SCSI */ - FPT_sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED; - } - - - sync_bit_map <<= 1; + } + else { /* NARROW SCSI */ + FPT_sccbMgrTbl[thisCard][id * 2 + + i].TarStatus |= + WIDE_NEGOCIATED; + } + sync_bit_map <<= 1; - } - } + } + } - WR_HARPOON((ioport+hp_semaphore), - (unsigned char)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT)); + WR_HARPOON((ioport + hp_semaphore), + (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) | + SCCB_MGR_PRESENT)); - return((unsigned long)CurrCard); + return ((unsigned long)CurrCard); } static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard) @@ -1570,36 +1398,37 @@ static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard) unsigned long regOffset; unsigned long scamData; unsigned long *pScamTbl; - struct nvram_info * pCurrNvRam; + struct nvram_info *pCurrNvRam; pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo; - if(pCurrNvRam){ + if (pCurrNvRam) { FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel); FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf); FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf); FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf); FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId); - for(i = 0; i < MAX_SCSI_TAR / 2; i++) - FPT_WrStack(pCurrNvRam->niBaseAddr, (unsigned char)(i+5), pCurrNvRam->niSyncTbl[i]); + for (i = 0; i < MAX_SCSI_TAR / 2; i++) + FPT_WrStack(pCurrNvRam->niBaseAddr, + (unsigned char)(i + 5), + pCurrNvRam->niSyncTbl[i]); portBase = pCurrNvRam->niBaseAddr; - for(i = 0; i < MAX_SCSI_TAR; i++){ - regOffset = hp_aramBase + 64 + i*4; - pScamTbl = (unsigned long *) &pCurrNvRam->niScamTbl[i]; + for (i = 0; i < MAX_SCSI_TAR; i++) { + regOffset = hp_aramBase + 64 + i * 4; + pScamTbl = (unsigned long *)&pCurrNvRam->niScamTbl[i]; scamData = *pScamTbl; WR_HARP32(portBase, regOffset, scamData); } - }else{ + } else { FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0); } } - -static void FPT_RNVRamData(struct nvram_info * pNvRamInfo) +static void FPT_RNVRamData(struct nvram_info *pNvRamInfo) { unsigned char i; unsigned long portBase; @@ -1607,21 +1436,22 @@ static void FPT_RNVRamData(struct nvram_info * pNvRamInfo) unsigned long scamData; unsigned long *pScamTbl; - pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0); - pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1); + pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0); + pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1); pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2); pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3); - pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4); + pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4); - for(i = 0; i < MAX_SCSI_TAR / 2; i++) - pNvRamInfo->niSyncTbl[i] = FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i+5)); + for (i = 0; i < MAX_SCSI_TAR / 2; i++) + pNvRamInfo->niSyncTbl[i] = + FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5)); portBase = pNvRamInfo->niBaseAddr; - for(i = 0; i < MAX_SCSI_TAR; i++){ - regOffset = hp_aramBase + 64 + i*4; + for (i = 0; i < MAX_SCSI_TAR; i++) { + regOffset = hp_aramBase + 64 + i * 4; RD_HARP32(portBase, regOffset, scamData); - pScamTbl = (unsigned long *) &pNvRamInfo->niScamTbl[i]; + pScamTbl = (unsigned long *)&pNvRamInfo->niScamTbl[i]; *pScamTbl = scamData; } @@ -1630,29 +1460,30 @@ static void FPT_RNVRamData(struct nvram_info * pNvRamInfo) static unsigned char FPT_RdStack(unsigned long portBase, unsigned char index) { WR_HARPOON(portBase + hp_stack_addr, index); - return(RD_HARPOON(portBase + hp_stack_data)); + return (RD_HARPOON(portBase + hp_stack_data)); } -static void FPT_WrStack(unsigned long portBase, unsigned char index, unsigned char data) +static void FPT_WrStack(unsigned long portBase, unsigned char index, + unsigned char data) { WR_HARPOON(portBase + hp_stack_addr, index); WR_HARPOON(portBase + hp_stack_data, data); } - static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort) { - if((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4)) - return(0); - if((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT) - != CLKCTRL_DEFAULT) - return(0); - if((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) || - (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms)) - return(1); - return(0); + if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4)) + return (0); + if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT) + != CLKCTRL_DEFAULT) + return (0); + if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) || + (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms)) + return (1); + return (0); } + /*--------------------------------------------------------------------- * * Function: FlashPoint_StartCCB @@ -1662,117 +1493,115 @@ static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort) * callback function. * *---------------------------------------------------------------------*/ -static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb * p_Sccb) +static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb) { - unsigned long ioport; - unsigned char thisCard, lun; - struct sccb * pSaveSccb; - CALL_BK_FN callback; + unsigned long ioport; + unsigned char thisCard, lun; + struct sccb *pSaveSccb; + CALL_BK_FN callback; - thisCard = ((struct sccb_card *) pCurrCard)->cardIndex; - ioport = ((struct sccb_card *) pCurrCard)->ioPort; + thisCard = ((struct sccb_card *)pCurrCard)->cardIndex; + ioport = ((struct sccb_card *)pCurrCard)->ioPort; - if((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) - { + if ((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) { p_Sccb->HostStatus = SCCB_COMPLETE; p_Sccb->SccbStatus = SCCB_ERROR; - callback = (CALL_BK_FN)p_Sccb->SccbCallback; + callback = (CALL_BK_FN) p_Sccb->SccbCallback; if (callback) callback(p_Sccb); return; } - FPT_sinits(p_Sccb,thisCard); - - - if (!((struct sccb_card *) pCurrCard)->cmdCounter) - { - WR_HARPOON(ioport+hp_semaphore, (RD_HARPOON(ioport+hp_semaphore) - | SCCB_MGR_ACTIVE)); - - if (((struct sccb_card *) pCurrCard)->globalFlags & F_GREEN_PC) - { - WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT); - WR_HARPOON(ioport+hp_sys_ctrl, 0x00); - } - } - - ((struct sccb_card *)pCurrCard)->cmdCounter++; + FPT_sinits(p_Sccb, thisCard); - if (RD_HARPOON(ioport+hp_semaphore) & BIOS_IN_USE) { + if (!((struct sccb_card *)pCurrCard)->cmdCounter) { + WR_HARPOON(ioport + hp_semaphore, + (RD_HARPOON(ioport + hp_semaphore) + | SCCB_MGR_ACTIVE)); - WR_HARPOON(ioport+hp_semaphore, (RD_HARPOON(ioport+hp_semaphore) - | TICKLE_ME)); - if(p_Sccb->OperationCode == RESET_COMMAND) - { - pSaveSccb = ((struct sccb_card *) pCurrCard)->currentSCCB; - ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; - FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard); - ((struct sccb_card *) pCurrCard)->currentSCCB = pSaveSccb; - } - else - { - FPT_queueAddSccb(p_Sccb,thisCard); - } - } + if (((struct sccb_card *)pCurrCard)->globalFlags & F_GREEN_PC) { + WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT); + WR_HARPOON(ioport + hp_sys_ctrl, 0x00); + } + } - else if ((RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE)) { + ((struct sccb_card *)pCurrCard)->cmdCounter++; + + if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) { + + WR_HARPOON(ioport + hp_semaphore, + (RD_HARPOON(ioport + hp_semaphore) + | TICKLE_ME)); + if (p_Sccb->OperationCode == RESET_COMMAND) { + pSaveSccb = + ((struct sccb_card *)pCurrCard)->currentSCCB; + ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb; + FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard); + ((struct sccb_card *)pCurrCard)->currentSCCB = + pSaveSccb; + } else { + FPT_queueAddSccb(p_Sccb, thisCard); + } + } - if(p_Sccb->OperationCode == RESET_COMMAND) - { - pSaveSccb = ((struct sccb_card *) pCurrCard)->currentSCCB; - ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; - FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard); - ((struct sccb_card *) pCurrCard)->currentSCCB = pSaveSccb; - } - else - { - FPT_queueAddSccb(p_Sccb,thisCard); - } - } + else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) { + + if (p_Sccb->OperationCode == RESET_COMMAND) { + pSaveSccb = + ((struct sccb_card *)pCurrCard)->currentSCCB; + ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb; + FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard); + ((struct sccb_card *)pCurrCard)->currentSCCB = + pSaveSccb; + } else { + FPT_queueAddSccb(p_Sccb, thisCard); + } + } - else { + else { - MDISABLE_INT(ioport); + MDISABLE_INT(ioport); - if((((struct sccb_card *) pCurrCard)->globalFlags & F_CONLUN_IO) && - ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + if ((((struct sccb_card *)pCurrCard)->globalFlags & F_CONLUN_IO) + && + ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID]. + TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) lun = p_Sccb->Lun; else lun = 0; - if ((((struct sccb_card *) pCurrCard)->currentSCCB == NULL) && - (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0) && - (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun] - == 0)) { - - ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; - FPT_ssel(p_Sccb->SccbIOPort,thisCard); - } + if ((((struct sccb_card *)pCurrCard)->currentSCCB == NULL) && + (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0) + && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun] + == 0)) { - else { - - if(p_Sccb->OperationCode == RESET_COMMAND) - { - pSaveSccb = ((struct sccb_card *) pCurrCard)->currentSCCB; - ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; - FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard); - ((struct sccb_card *) pCurrCard)->currentSCCB = pSaveSccb; - } - else - { - FPT_queueAddSccb(p_Sccb,thisCard); - } - } + ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb; + FPT_ssel(p_Sccb->SccbIOPort, thisCard); + } + else { + + if (p_Sccb->OperationCode == RESET_COMMAND) { + pSaveSccb = + ((struct sccb_card *)pCurrCard)-> + currentSCCB; + ((struct sccb_card *)pCurrCard)->currentSCCB = + p_Sccb; + FPT_queueSelectFail(&FPT_BL_Card[thisCard], + thisCard); + ((struct sccb_card *)pCurrCard)->currentSCCB = + pSaveSccb; + } else { + FPT_queueAddSccb(p_Sccb, thisCard); + } + } - MENABLE_INT(ioport); - } + MENABLE_INT(ioport); + } } - /*--------------------------------------------------------------------- * * Function: FlashPoint_AbortCCB @@ -1782,98 +1611,106 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb * p_Sccb) * callback function. * *---------------------------------------------------------------------*/ -static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb * p_Sccb) +static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb) { unsigned long ioport; unsigned char thisCard; CALL_BK_FN callback; unsigned char TID; - struct sccb * pSaveSCCB; - struct sccb_mgr_tar_info * currTar_Info; - + struct sccb *pSaveSCCB; + struct sccb_mgr_tar_info *currTar_Info; - ioport = ((struct sccb_card *) pCurrCard)->ioPort; + ioport = ((struct sccb_card *)pCurrCard)->ioPort; thisCard = ((struct sccb_card *)pCurrCard)->cardIndex; - if (!(RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE)) - { + if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) { - if (FPT_queueFindSccb(p_Sccb,thisCard)) - { + if (FPT_queueFindSccb(p_Sccb, thisCard)) { ((struct sccb_card *)pCurrCard)->cmdCounter--; if (!((struct sccb_card *)pCurrCard)->cmdCounter) - WR_HARPOON(ioport+hp_semaphore,(RD_HARPOON(ioport+hp_semaphore) - & (unsigned char)(~(SCCB_MGR_ACTIVE | TICKLE_ME)) )); + WR_HARPOON(ioport + hp_semaphore, + (RD_HARPOON(ioport + hp_semaphore) + & (unsigned + char)(~(SCCB_MGR_ACTIVE | + TICKLE_ME)))); p_Sccb->SccbStatus = SCCB_ABORT; callback = p_Sccb->SccbCallback; callback(p_Sccb); - return(0); + return (0); } - else - { - if (((struct sccb_card *)pCurrCard)->currentSCCB == p_Sccb) - { + else { + if (((struct sccb_card *)pCurrCard)->currentSCCB == + p_Sccb) { p_Sccb->SccbStatus = SCCB_ABORT; - return(0); + return (0); } - else - { + else { TID = p_Sccb->TargID; - - if(p_Sccb->Sccb_tag) - { + if (p_Sccb->Sccb_tag) { MDISABLE_INT(ioport); - if (((struct sccb_card *) pCurrCard)->discQ_Tbl[p_Sccb->Sccb_tag]==p_Sccb) - { + if (((struct sccb_card *)pCurrCard)-> + discQ_Tbl[p_Sccb->Sccb_tag] == + p_Sccb) { p_Sccb->SccbStatus = SCCB_ABORT; - p_Sccb->Sccb_scsistat = ABORT_ST; - p_Sccb->Sccb_scsimsg = SMABORT_TAG; - - if(((struct sccb_card *) pCurrCard)->currentSCCB == NULL) - { - ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; - FPT_ssel(ioport, thisCard); - } - else - { - pSaveSCCB = ((struct sccb_card *) pCurrCard)->currentSCCB; - ((struct sccb_card *) pCurrCard)->currentSCCB = p_Sccb; - FPT_queueSelectFail((struct sccb_card *) pCurrCard, thisCard); - ((struct sccb_card *) pCurrCard)->currentSCCB = pSaveSCCB; + p_Sccb->Sccb_scsistat = + ABORT_ST; + p_Sccb->Sccb_scsimsg = + SMABORT_TAG; + + if (((struct sccb_card *) + pCurrCard)->currentSCCB == + NULL) { + ((struct sccb_card *) + pCurrCard)-> + currentSCCB = p_Sccb; + FPT_ssel(ioport, + thisCard); + } else { + pSaveSCCB = + ((struct sccb_card + *)pCurrCard)-> + currentSCCB; + ((struct sccb_card *) + pCurrCard)-> + currentSCCB = p_Sccb; + FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard); + ((struct sccb_card *) + pCurrCard)-> + currentSCCB = pSaveSCCB; } } MENABLE_INT(ioport); - return(0); - } - else - { - currTar_Info = &FPT_sccbMgrTbl[thisCard][p_Sccb->TargID]; - - if(FPT_BL_Card[thisCard].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_Sccb->Lun]] - == p_Sccb) - { + return (0); + } else { + currTar_Info = + &FPT_sccbMgrTbl[thisCard][p_Sccb-> + TargID]; + + if (FPT_BL_Card[thisCard]. + discQ_Tbl[currTar_Info-> + LunDiscQ_Idx[p_Sccb->Lun]] + == p_Sccb) { p_Sccb->SccbStatus = SCCB_ABORT; - return(0); + return (0); } } } } } - return(-1); + return (-1); } - /*--------------------------------------------------------------------- * * Function: FlashPoint_InterruptPending @@ -1884,22 +1721,19 @@ static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb * p_Sccb) *---------------------------------------------------------------------*/ static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard) { - unsigned long ioport; + unsigned long ioport; - ioport = ((struct sccb_card *)pCurrCard)->ioPort; + ioport = ((struct sccb_card *)pCurrCard)->ioPort; - if (RD_HARPOON(ioport+hp_int_status) & INT_ASSERTED) - { - return(1); - } + if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) { + return (1); + } - else + else - return(0); + return (0); } - - /*--------------------------------------------------------------------- * * Function: FlashPoint_HandleInterrupt @@ -1911,237 +1745,259 @@ static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard) *---------------------------------------------------------------------*/ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) { - struct sccb * currSCCB; - unsigned char thisCard,result,bm_status, bm_int_st; - unsigned short hp_int; - unsigned char i, target; - unsigned long ioport; - - thisCard = ((struct sccb_card *)pCurrCard)->cardIndex; - ioport = ((struct sccb_card *)pCurrCard)->ioPort; - - MDISABLE_INT(ioport); + struct sccb *currSCCB; + unsigned char thisCard, result, bm_status, bm_int_st; + unsigned short hp_int; + unsigned char i, target; + unsigned long ioport; - if ((bm_int_st=RD_HARPOON(ioport+hp_int_status)) & EXT_STATUS_ON) - bm_status = RD_HARPOON(ioport+hp_ext_status) & (unsigned char)BAD_EXT_STATUS; - else - bm_status = 0; + thisCard = ((struct sccb_card *)pCurrCard)->cardIndex; + ioport = ((struct sccb_card *)pCurrCard)->ioPort; - WR_HARPOON(ioport+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); + MDISABLE_INT(ioport); - while ((hp_int = RDW_HARPOON((ioport+hp_intstat)) & FPT_default_intena) | - bm_status) - { + if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON) + bm_status = + RD_HARPOON(ioport + + hp_ext_status) & (unsigned char)BAD_EXT_STATUS; + else + bm_status = 0; - currSCCB = ((struct sccb_card *)pCurrCard)->currentSCCB; + WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); - if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) { - result = FPT_SccbMgr_bad_isr(ioport,thisCard,((struct sccb_card *)pCurrCard),hp_int); - WRW_HARPOON((ioport+hp_intstat), (FIFO | TIMEOUT | RESET | SCAM_SEL)); - bm_status = 0; + while ((hp_int = + RDW_HARPOON((ioport + + hp_intstat)) & FPT_default_intena) | bm_status) { - if (result) { + currSCCB = ((struct sccb_card *)pCurrCard)->currentSCCB; - MENABLE_INT(ioport); - return(result); - } - } + if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) { + result = + FPT_SccbMgr_bad_isr(ioport, thisCard, + ((struct sccb_card *)pCurrCard), + hp_int); + WRW_HARPOON((ioport + hp_intstat), + (FIFO | TIMEOUT | RESET | SCAM_SEL)); + bm_status = 0; + if (result) { - else if (hp_int & ICMD_COMP) { + MENABLE_INT(ioport); + return (result); + } + } - if ( !(hp_int & BUS_FREE) ) { - /* Wait for the BusFree before starting a new command. We - must also check for being reselected since the BusFree - may not show up if another device reselects us in 1.5us or - less. SRR Wednesday, 3/8/1995. - */ - while (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL))) ; - } + else if (hp_int & ICMD_COMP) { + + if (!(hp_int & BUS_FREE)) { + /* Wait for the BusFree before starting a new command. We + must also check for being reselected since the BusFree + may not show up if another device reselects us in 1.5us or + less. SRR Wednesday, 3/8/1995. + */ + while (! + (RDW_HARPOON((ioport + hp_intstat)) & + (BUS_FREE | RSEL))) ; + } - if (((struct sccb_card *)pCurrCard)->globalFlags & F_HOST_XFER_ACT) + if (((struct sccb_card *)pCurrCard)-> + globalFlags & F_HOST_XFER_ACT) - FPT_phaseChkFifo(ioport, thisCard); + FPT_phaseChkFifo(ioport, thisCard); /* WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0)); */ - WRW_HARPOON((ioport+hp_intstat), CLR_ALL_INT_1); - - FPT_autoCmdCmplt(ioport,thisCard); - - } - - - else if (hp_int & ITAR_DISC) - { - - if (((struct sccb_card *)pCurrCard)->globalFlags & F_HOST_XFER_ACT) { - - FPT_phaseChkFifo(ioport, thisCard); - - } - - if (RD_HARPOON(ioport+hp_gp_reg_1) == SMSAVE_DATA_PTR) { - - WR_HARPOON(ioport+hp_gp_reg_1, 0x00); - currSCCB->Sccb_XferState |= F_NO_DATA_YET; + WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1); - currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC; - } + FPT_autoCmdCmplt(ioport, thisCard); - currSCCB->Sccb_scsistat = DISCONNECT_ST; - FPT_queueDisconnect(currSCCB,thisCard); + } - /* Wait for the BusFree before starting a new command. We - must also check for being reselected since the BusFree - may not show up if another device reselects us in 1.5us or - less. SRR Wednesday, 3/8/1995. - */ - while (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL)) && - !((RDW_HARPOON((ioport+hp_intstat)) & PHASE) && - RD_HARPOON((ioport+hp_scsisig)) == - (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG | SCSI_IOBIT))) ; + else if (hp_int & ITAR_DISC) { - /* - The additional loop exit condition above detects a timing problem - with the revision D/E harpoon chips. The caller should reset the - host adapter to recover when 0xFE is returned. - */ - if (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL))) - { - MENABLE_INT(ioport); - return 0xFE; - } + if (((struct sccb_card *)pCurrCard)-> + globalFlags & F_HOST_XFER_ACT) { - WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ITAR_DISC)); + FPT_phaseChkFifo(ioport, thisCard); + } - ((struct sccb_card *)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD; + if (RD_HARPOON(ioport + hp_gp_reg_1) == SMSAVE_DATA_PTR) { - } + WR_HARPOON(ioport + hp_gp_reg_1, 0x00); + currSCCB->Sccb_XferState |= F_NO_DATA_YET; + currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC; + } - else if (hp_int & RSEL) { + currSCCB->Sccb_scsistat = DISCONNECT_ST; + FPT_queueDisconnect(currSCCB, thisCard); + + /* Wait for the BusFree before starting a new command. We + must also check for being reselected since the BusFree + may not show up if another device reselects us in 1.5us or + less. SRR Wednesday, 3/8/1995. + */ + while (! + (RDW_HARPOON((ioport + hp_intstat)) & + (BUS_FREE | RSEL)) + && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE) + && RD_HARPOON((ioport + hp_scsisig)) == + (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG | + SCSI_IOBIT))) ; + + /* + The additional loop exit condition above detects a timing problem + with the revision D/E harpoon chips. The caller should reset the + host adapter to recover when 0xFE is returned. + */ + if (! + (RDW_HARPOON((ioport + hp_intstat)) & + (BUS_FREE | RSEL))) { + MENABLE_INT(ioport); + return 0xFE; + } - WRW_HARPOON((ioport+hp_intstat), (PROG_HLT | RSEL | PHASE | BUS_FREE)); + WRW_HARPOON((ioport + hp_intstat), + (BUS_FREE | ITAR_DISC)); - if (RDW_HARPOON((ioport+hp_intstat)) & ITAR_DISC) - { - if (((struct sccb_card *)pCurrCard)->globalFlags & F_HOST_XFER_ACT) - { - FPT_phaseChkFifo(ioport, thisCard); - } + ((struct sccb_card *)pCurrCard)->globalFlags |= + F_NEW_SCCB_CMD; - if (RD_HARPOON(ioport+hp_gp_reg_1) == SMSAVE_DATA_PTR) - { - WR_HARPOON(ioport+hp_gp_reg_1, 0x00); - currSCCB->Sccb_XferState |= F_NO_DATA_YET; - currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC; - } + } - WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ITAR_DISC)); - currSCCB->Sccb_scsistat = DISCONNECT_ST; - FPT_queueDisconnect(currSCCB,thisCard); - } + else if (hp_int & RSEL) { - FPT_sres(ioport,thisCard,((struct sccb_card *)pCurrCard)); - FPT_phaseDecode(ioport,thisCard); + WRW_HARPOON((ioport + hp_intstat), + (PROG_HLT | RSEL | PHASE | BUS_FREE)); - } + if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) { + if (((struct sccb_card *)pCurrCard)-> + globalFlags & F_HOST_XFER_ACT) { + FPT_phaseChkFifo(ioport, thisCard); + } + if (RD_HARPOON(ioport + hp_gp_reg_1) == + SMSAVE_DATA_PTR) { + WR_HARPOON(ioport + hp_gp_reg_1, 0x00); + currSCCB->Sccb_XferState |= + F_NO_DATA_YET; + currSCCB->Sccb_savedATC = + currSCCB->Sccb_ATC; + } - else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) - { + WRW_HARPOON((ioport + hp_intstat), + (BUS_FREE | ITAR_DISC)); + currSCCB->Sccb_scsistat = DISCONNECT_ST; + FPT_queueDisconnect(currSCCB, thisCard); + } - WRW_HARPOON((ioport+hp_intstat), (IDO_STRT | XFER_CNT_0)); - FPT_phaseDecode(ioport,thisCard); + FPT_sres(ioport, thisCard, + ((struct sccb_card *)pCurrCard)); + FPT_phaseDecode(ioport, thisCard); - } + } + else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) { - else if ( (hp_int & IUNKWN) || (hp_int & PROG_HLT) ) - { - WRW_HARPOON((ioport+hp_intstat), (PHASE | IUNKWN | PROG_HLT)); - if ((RD_HARPOON(ioport+hp_prgmcnt_0) & (unsigned char)0x3f)< (unsigned char)SELCHK) - { - FPT_phaseDecode(ioport,thisCard); - } - else - { - /* Harpoon problem some SCSI target device respond to selection - with short BUSY pulse (<400ns) this will make the Harpoon is not able - to latch the correct Target ID into reg. x53. - The work around require to correct this reg. But when write to this - reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we - need to read this reg first then restore it later. After update to 0x53 */ + WRW_HARPOON((ioport + hp_intstat), + (IDO_STRT | XFER_CNT_0)); + FPT_phaseDecode(ioport, thisCard); - i = (unsigned char)(RD_HARPOON(ioport+hp_fifowrite)); - target = (unsigned char)(RD_HARPOON(ioport+hp_gp_reg_3)); - WR_HARPOON(ioport+hp_xfer_pad, (unsigned char) ID_UNLOCK); - WR_HARPOON(ioport+hp_select_id, (unsigned char)(target | target<<4)); - WR_HARPOON(ioport+hp_xfer_pad, (unsigned char) 0x00); - WR_HARPOON(ioport+hp_fifowrite, i); - WR_HARPOON(ioport+hp_autostart_3, (AUTO_IMMED+TAG_STRT)); - } - } + } - else if (hp_int & XFER_CNT_0) { + else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) { + WRW_HARPOON((ioport + hp_intstat), + (PHASE | IUNKWN | PROG_HLT)); + if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char) + 0x3f) < (unsigned char)SELCHK) { + FPT_phaseDecode(ioport, thisCard); + } else { + /* Harpoon problem some SCSI target device respond to selection + with short BUSY pulse (<400ns) this will make the Harpoon is not able + to latch the correct Target ID into reg. x53. + The work around require to correct this reg. But when write to this + reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we + need to read this reg first then restore it later. After update to 0x53 */ + + i = (unsigned + char)(RD_HARPOON(ioport + hp_fifowrite)); + target = + (unsigned + char)(RD_HARPOON(ioport + hp_gp_reg_3)); + WR_HARPOON(ioport + hp_xfer_pad, + (unsigned char)ID_UNLOCK); + WR_HARPOON(ioport + hp_select_id, + (unsigned char)(target | target << + 4)); + WR_HARPOON(ioport + hp_xfer_pad, + (unsigned char)0x00); + WR_HARPOON(ioport + hp_fifowrite, i); + WR_HARPOON(ioport + hp_autostart_3, + (AUTO_IMMED + TAG_STRT)); + } + } - WRW_HARPOON((ioport+hp_intstat), XFER_CNT_0); + else if (hp_int & XFER_CNT_0) { - FPT_schkdd(ioport,thisCard); + WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0); - } + FPT_schkdd(ioport, thisCard); + } - else if (hp_int & BUS_FREE) { + else if (hp_int & BUS_FREE) { - WRW_HARPOON((ioport+hp_intstat), BUS_FREE); + WRW_HARPOON((ioport + hp_intstat), BUS_FREE); - if (((struct sccb_card *)pCurrCard)->globalFlags & F_HOST_XFER_ACT) { + if (((struct sccb_card *)pCurrCard)-> + globalFlags & F_HOST_XFER_ACT) { - FPT_hostDataXferAbort(ioport,thisCard,currSCCB); - } - - FPT_phaseBusFree(ioport,thisCard); + FPT_hostDataXferAbort(ioport, thisCard, + currSCCB); } + FPT_phaseBusFree(ioport, thisCard); + } - else if (hp_int & ITICKLE) { - - WRW_HARPOON((ioport+hp_intstat), ITICKLE); - ((struct sccb_card *)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD; - } - - - - if (((struct sccb_card *)pCurrCard)->globalFlags & F_NEW_SCCB_CMD) { + else if (hp_int & ITICKLE) { + WRW_HARPOON((ioport + hp_intstat), ITICKLE); + ((struct sccb_card *)pCurrCard)->globalFlags |= + F_NEW_SCCB_CMD; + } - ((struct sccb_card *)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD; + if (((struct sccb_card *)pCurrCard)-> + globalFlags & F_NEW_SCCB_CMD) { + ((struct sccb_card *)pCurrCard)->globalFlags &= + ~F_NEW_SCCB_CMD; - if (((struct sccb_card *)pCurrCard)->currentSCCB == NULL) { + if (((struct sccb_card *)pCurrCard)->currentSCCB == + NULL) { - FPT_queueSearchSelect(((struct sccb_card *)pCurrCard),thisCard); - } + FPT_queueSearchSelect(((struct sccb_card *) + pCurrCard), thisCard); + } - if (((struct sccb_card *)pCurrCard)->currentSCCB != NULL) { - ((struct sccb_card *)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD; - FPT_ssel(ioport,thisCard); - } + if (((struct sccb_card *)pCurrCard)->currentSCCB != + NULL) { + ((struct sccb_card *)pCurrCard)->globalFlags &= + ~F_NEW_SCCB_CMD; + FPT_ssel(ioport, thisCard); + } - break; + break; - } + } - } /*end while */ + } /*end while */ - MENABLE_INT(ioport); + MENABLE_INT(ioport); - return(0); + return (0); } /*--------------------------------------------------------------------- @@ -2154,150 +2010,149 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) * processing time. * *---------------------------------------------------------------------*/ -static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, unsigned char p_card, - struct sccb_card * pCurrCard, unsigned short p_int) +static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, + unsigned char p_card, + struct sccb_card *pCurrCard, + unsigned short p_int) { - unsigned char temp, ScamFlg; - struct sccb_mgr_tar_info * currTar_Info; - struct nvram_info * pCurrNvRam; - - - if (RD_HARPOON(p_port+hp_ext_status) & - (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN) ) - { - - if (pCurrCard->globalFlags & F_HOST_XFER_ACT) - { + unsigned char temp, ScamFlg; + struct sccb_mgr_tar_info *currTar_Info; + struct nvram_info *pCurrNvRam; - FPT_hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB); - } + if (RD_HARPOON(p_port + hp_ext_status) & + (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) { - if (RD_HARPOON(p_port+hp_pci_stat_cfg) & REC_MASTER_ABORT) + if (pCurrCard->globalFlags & F_HOST_XFER_ACT) { - { - WR_HARPOON(p_port+hp_pci_stat_cfg, - (RD_HARPOON(p_port+hp_pci_stat_cfg) & ~REC_MASTER_ABORT)); - - WR_HARPOON(p_port+hp_host_blk_cnt, 0x00); - - } - - if (pCurrCard->currentSCCB != NULL) - { + FPT_hostDataXferAbort(p_port, p_card, + pCurrCard->currentSCCB); + } - if (!pCurrCard->currentSCCB->HostStatus) - pCurrCard->currentSCCB->HostStatus = SCCB_BM_ERR; + if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT) + { + WR_HARPOON(p_port + hp_pci_stat_cfg, + (RD_HARPOON(p_port + hp_pci_stat_cfg) & + ~REC_MASTER_ABORT)); - FPT_sxfrp(p_port,p_card); + WR_HARPOON(p_port + hp_host_blk_cnt, 0x00); - temp = (unsigned char)(RD_HARPOON(p_port+hp_ee_ctrl) & - (EXT_ARB_ACK | SCSI_TERM_ENA_H)); - WR_HARPOON(p_port+hp_ee_ctrl, ((unsigned char)temp | SEE_MS | SEE_CS)); - WR_HARPOON(p_port+hp_ee_ctrl, temp); + } - if (!(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET))) - { - FPT_phaseDecode(p_port,p_card); - } - } - } + if (pCurrCard->currentSCCB != NULL) { + if (!pCurrCard->currentSCCB->HostStatus) + pCurrCard->currentSCCB->HostStatus = + SCCB_BM_ERR; - else if (p_int & RESET) - { + FPT_sxfrp(p_port, p_card); - WR_HARPOON(p_port+hp_clkctrl_0, CLKCTRL_DEFAULT); - WR_HARPOON(p_port+hp_sys_ctrl, 0x00); - if (pCurrCard->currentSCCB != NULL) { + temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) & + (EXT_ARB_ACK | SCSI_TERM_ENA_H)); + WR_HARPOON(p_port + hp_ee_ctrl, + ((unsigned char)temp | SEE_MS | SEE_CS)); + WR_HARPOON(p_port + hp_ee_ctrl, temp); - if (pCurrCard->globalFlags & F_HOST_XFER_ACT) + if (! + (RDW_HARPOON((p_port + hp_intstat)) & + (BUS_FREE | RESET))) { + FPT_phaseDecode(p_port, p_card); + } + } + } - FPT_hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB); - } + else if (p_int & RESET) { + WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT); + WR_HARPOON(p_port + hp_sys_ctrl, 0x00); + if (pCurrCard->currentSCCB != NULL) { - DISABLE_AUTO(p_port); + if (pCurrCard->globalFlags & F_HOST_XFER_ACT) - FPT_sresb(p_port,p_card); + FPT_hostDataXferAbort(p_port, p_card, + pCurrCard->currentSCCB); + } - while(RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST) {} + DISABLE_AUTO(p_port); - pCurrNvRam = pCurrCard->pNvRamInfo; - if(pCurrNvRam){ - ScamFlg = pCurrNvRam->niScamConf; - } - else{ - ScamFlg = (unsigned char) FPT_utilEERead(p_port, SCAM_CONFIG/2); - } + FPT_sresb(p_port, p_card); - FPT_XbowInit(p_port, ScamFlg); + while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) { + } - FPT_scini(p_card, pCurrCard->ourId, 0); + pCurrNvRam = pCurrCard->pNvRamInfo; + if (pCurrNvRam) { + ScamFlg = pCurrNvRam->niScamConf; + } else { + ScamFlg = + (unsigned char)FPT_utilEERead(p_port, + SCAM_CONFIG / 2); + } - return(0xFF); - } + FPT_XbowInit(p_port, ScamFlg); + FPT_scini(p_card, pCurrCard->ourId, 0); - else if (p_int & FIFO) { + return (0xFF); + } - WRW_HARPOON((p_port+hp_intstat), FIFO); + else if (p_int & FIFO) { - if (pCurrCard->currentSCCB != NULL) - FPT_sxfrp(p_port,p_card); - } + WRW_HARPOON((p_port + hp_intstat), FIFO); - else if (p_int & TIMEOUT) - { + if (pCurrCard->currentSCCB != NULL) + FPT_sxfrp(p_port, p_card); + } - DISABLE_AUTO(p_port); + else if (p_int & TIMEOUT) { - WRW_HARPOON((p_port+hp_intstat), - (PROG_HLT | TIMEOUT | SEL |BUS_FREE | PHASE | IUNKWN)); + DISABLE_AUTO(p_port); - pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT; + WRW_HARPOON((p_port + hp_intstat), + (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE | + IUNKWN)); + pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT; - currTar_Info = &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID]; - if((pCurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] = 0; + currTar_Info = + &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID]; + if ((pCurrCard->globalFlags & F_CONLUN_IO) + && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != + TAG_Q_TRYING)) + currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] = + 0; else - currTar_Info->TarLUNBusy[0] = 0; + currTar_Info->TarLUNBusy[0] = 0; + if (currTar_Info->TarEEValue & EE_SYNC_MASK) { + currTar_Info->TarSyncCtrl = 0; + currTar_Info->TarStatus &= ~TAR_SYNC_MASK; + } - if (currTar_Info->TarEEValue & EE_SYNC_MASK) - { - currTar_Info->TarSyncCtrl = 0; - currTar_Info->TarStatus &= ~TAR_SYNC_MASK; - } + if (currTar_Info->TarEEValue & EE_WIDE_SCSI) { + currTar_Info->TarStatus &= ~TAR_WIDE_MASK; + } - if (currTar_Info->TarEEValue & EE_WIDE_SCSI) - { - currTar_Info->TarStatus &= ~TAR_WIDE_MASK; - } + FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI, + currTar_Info); - FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,currTar_Info); + FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card); - FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card); + } - } + else if (p_int & SCAM_SEL) { - else if (p_int & SCAM_SEL) - { + FPT_scarb(p_port, LEVEL2_TAR); + FPT_scsel(p_port); + FPT_scasid(p_card, p_port); - FPT_scarb(p_port,LEVEL2_TAR); - FPT_scsel(p_port); - FPT_scasid(p_card, p_port); + FPT_scbusf(p_port); - FPT_scbusf(p_port); - - WRW_HARPOON((p_port+hp_intstat), SCAM_SEL); - } + WRW_HARPOON((p_port + hp_intstat), SCAM_SEL); + } - return(0x00); + return (0x00); } - /*--------------------------------------------------------------------- * * Function: SccbMgrTableInit @@ -2308,21 +2163,19 @@ static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, unsigned char p_c static void FPT_SccbMgrTableInitAll() { - unsigned char thisCard; + unsigned char thisCard; - for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) - { - FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard],thisCard); + for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) { + FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard); - FPT_BL_Card[thisCard].ioPort = 0x00; - FPT_BL_Card[thisCard].cardInfo = NULL; - FPT_BL_Card[thisCard].cardIndex = 0xFF; - FPT_BL_Card[thisCard].ourId = 0x00; - FPT_BL_Card[thisCard].pNvRamInfo = NULL; - } + FPT_BL_Card[thisCard].ioPort = 0x00; + FPT_BL_Card[thisCard].cardInfo = NULL; + FPT_BL_Card[thisCard].cardIndex = 0xFF; + FPT_BL_Card[thisCard].ourId = 0x00; + FPT_BL_Card[thisCard].pNvRamInfo = NULL; + } } - /*--------------------------------------------------------------------- * * Function: SccbMgrTableInit @@ -2331,33 +2184,30 @@ static void FPT_SccbMgrTableInitAll() * *---------------------------------------------------------------------*/ -static void FPT_SccbMgrTableInitCard(struct sccb_card * pCurrCard, unsigned char p_card) +static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard, + unsigned char p_card) { - unsigned char scsiID, qtag; + unsigned char scsiID, qtag; - for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) - { + for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) { FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL; } - for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) - { - FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0; - FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0; - FPT_SccbMgrTableInitTarget(p_card, scsiID); - } + for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) { + FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0; + FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0; + FPT_SccbMgrTableInitTarget(p_card, scsiID); + } - pCurrCard->scanIndex = 0x00; - pCurrCard->currentSCCB = NULL; - pCurrCard->globalFlags = 0x00; - pCurrCard->cmdCounter = 0x00; + pCurrCard->scanIndex = 0x00; + pCurrCard->currentSCCB = NULL; + pCurrCard->globalFlags = 0x00; + pCurrCard->cmdCounter = 0x00; pCurrCard->tagQ_Lst = 0x01; - pCurrCard->discQCount = 0; - + pCurrCard->discQCount = 0; } - /*--------------------------------------------------------------------- * * Function: SccbMgrTableInit @@ -2366,11 +2216,12 @@ static void FPT_SccbMgrTableInitCard(struct sccb_card * pCurrCard, unsigned char * *---------------------------------------------------------------------*/ -static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char target) +static void FPT_SccbMgrTableInitTarget(unsigned char p_card, + unsigned char target) { unsigned char lun, qtag; - struct sccb_mgr_tar_info * currTar_Info; + struct sccb_mgr_tar_info *currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][target]; @@ -2382,19 +2233,15 @@ static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char targe currTar_Info->TarTagQ_Cnt = 0; currTar_Info->TarLUN_CA = 0; - - for (lun = 0; lun < MAX_LUN; lun++) - { + for (lun = 0; lun < MAX_LUN; lun++) { currTar_Info->TarLUNBusy[lun] = 0; currTar_Info->LunDiscQ_Idx[lun] = 0; } - for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) - { - if(FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) - { - if(FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == target) - { + for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) { + if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) { + if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == + target) { FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL; FPT_BL_Card[p_card].discQCount--; } @@ -2402,7 +2249,6 @@ static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char targe } } - /*--------------------------------------------------------------------- * * Function: sfetm @@ -2412,71 +2258,66 @@ static void FPT_SccbMgrTableInitTarget(unsigned char p_card, unsigned char targe * *---------------------------------------------------------------------*/ -static unsigned char FPT_sfm(unsigned long port, struct sccb * pCurrSCCB) +static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB) { unsigned char message; unsigned short TimeOutLoop; TimeOutLoop = 0; - while( (!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && - (TimeOutLoop++ < 20000) ){} - - - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) && + (TimeOutLoop++ < 20000)) { + } - message = RD_HARPOON(port+hp_scsidata_0); + WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); - WR_HARPOON(port+hp_scsisig, SCSI_ACK + S_MSGI_PH); + message = RD_HARPOON(port + hp_scsidata_0); + WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH); if (TimeOutLoop > 20000) - message = 0x00; /* force message byte = 0 if Time Out on Req */ - - if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && - (RD_HARPOON(port+hp_addstat) & SCSI_PAR_ERR)) - { - WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); - WR_HARPOON(port+hp_xferstat, 0); - WR_HARPOON(port+hp_fiforead, 0); - WR_HARPOON(port+hp_fifowrite, 0); - if (pCurrSCCB != NULL) - { + message = 0x00; /* force message byte = 0 if Time Out on Req */ + + if ((RDW_HARPOON((port + hp_intstat)) & PARITY) && + (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) { + WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH)); + WR_HARPOON(port + hp_xferstat, 0); + WR_HARPOON(port + hp_fiforead, 0); + WR_HARPOON(port + hp_fifowrite, 0); + if (pCurrSCCB != NULL) { pCurrSCCB->Sccb_scsimsg = SMPARITY; } message = 0x00; - do - { + do { ACCEPT_MSG_ATN(port); TimeOutLoop = 0; - while( (!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && - (TimeOutLoop++ < 20000) ){} - if (TimeOutLoop > 20000) - { - WRW_HARPOON((port+hp_intstat), PARITY); - return(message); + while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) && + (TimeOutLoop++ < 20000)) { } - if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) != S_MSGI_PH) - { - WRW_HARPOON((port+hp_intstat), PARITY); - return(message); + if (TimeOutLoop > 20000) { + WRW_HARPOON((port + hp_intstat), PARITY); + return (message); + } + if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) != + S_MSGI_PH) { + WRW_HARPOON((port + hp_intstat), PARITY); + return (message); } - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); - RD_HARPOON(port+hp_scsidata_0); + RD_HARPOON(port + hp_scsidata_0); - WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); + WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH)); - }while(1); + } while (1); } - WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); - WR_HARPOON(port+hp_xferstat, 0); - WR_HARPOON(port+hp_fiforead, 0); - WR_HARPOON(port+hp_fifowrite, 0); - return(message); + WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH)); + WR_HARPOON(port + hp_xferstat, 0); + WR_HARPOON(port + hp_fiforead, 0); + WR_HARPOON(port + hp_fifowrite, 0); + return (message); } - /*--------------------------------------------------------------------- * * Function: FPT_ssel @@ -2488,99 +2329,87 @@ static unsigned char FPT_sfm(unsigned long port, struct sccb * pCurrSCCB) static void FPT_ssel(unsigned long port, unsigned char p_card) { - unsigned char auto_loaded, i, target, *theCCB; - - unsigned long cdb_reg; - struct sccb_card * CurrCard; - struct sccb * currSCCB; - struct sccb_mgr_tar_info * currTar_Info; - unsigned char lastTag, lun; + unsigned char auto_loaded, i, target, *theCCB; - CurrCard = &FPT_BL_Card[p_card]; - currSCCB = CurrCard->currentSCCB; - target = currSCCB->TargID; - currTar_Info = &FPT_sccbMgrTbl[p_card][target]; - lastTag = CurrCard->tagQ_Lst; + unsigned long cdb_reg; + struct sccb_card *CurrCard; + struct sccb *currSCCB; + struct sccb_mgr_tar_info *currTar_Info; + unsigned char lastTag, lun; - ARAM_ACCESS(port); + CurrCard = &FPT_BL_Card[p_card]; + currSCCB = CurrCard->currentSCCB; + target = currSCCB->TargID; + currTar_Info = &FPT_sccbMgrTbl[p_card][target]; + lastTag = CurrCard->tagQ_Lst; + ARAM_ACCESS(port); if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT) currSCCB->ControlByte &= ~F_USE_CMD_Q; - if(((CurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + if (((CurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - lun = currSCCB->Lun; + lun = currSCCB->Lun; else lun = 0; + if (CurrCard->globalFlags & F_TAG_STARTED) { + if (!(currSCCB->ControlByte & F_USE_CMD_Q)) { + if ((currTar_Info->TarLUN_CA == 0) + && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) + == TAG_Q_TRYING)) { + + if (currTar_Info->TarTagQ_Cnt != 0) { + currTar_Info->TarLUNBusy[lun] = 1; + FPT_queueSelectFail(CurrCard, p_card); + SGRAM_ACCESS(port); + return; + } - if (CurrCard->globalFlags & F_TAG_STARTED) - { - if (!(currSCCB->ControlByte & F_USE_CMD_Q)) - { - if ((currTar_Info->TarLUN_CA == 0) - && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) - == TAG_Q_TRYING)) - { - - if (currTar_Info->TarTagQ_Cnt !=0) - { - currTar_Info->TarLUNBusy[lun] = 1; - FPT_queueSelectFail(CurrCard,p_card); - SGRAM_ACCESS(port); - return; - } - - else { - currTar_Info->TarLUNBusy[lun] = 1; - } - - } /*End non-tagged */ - - else { - currTar_Info->TarLUNBusy[lun] = 1; - } - - } /*!Use cmd Q Tagged */ - - else { - if (currTar_Info->TarLUN_CA == 1) - { - FPT_queueSelectFail(CurrCard,p_card); - SGRAM_ACCESS(port); - return; - } - - currTar_Info->TarLUNBusy[lun] = 1; + else { + currTar_Info->TarLUNBusy[lun] = 1; + } - } /*else use cmd Q tagged */ + } + /*End non-tagged */ + else { + currTar_Info->TarLUNBusy[lun] = 1; + } - } /*if glob tagged started */ + } + /*!Use cmd Q Tagged */ + else { + if (currTar_Info->TarLUN_CA == 1) { + FPT_queueSelectFail(CurrCard, p_card); + SGRAM_ACCESS(port); + return; + } - else { - currTar_Info->TarLUNBusy[lun] = 1; - } + currTar_Info->TarLUNBusy[lun] = 1; + } /*else use cmd Q tagged */ + } + /*if glob tagged started */ + else { + currTar_Info->TarLUNBusy[lun] = 1; + } - if((((CurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) - { - if(CurrCard->discQCount >= QUEUE_DEPTH) - { + if ((((CurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) { + if (CurrCard->discQCount >= QUEUE_DEPTH) { currTar_Info->TarLUNBusy[lun] = 1; - FPT_queueSelectFail(CurrCard,p_card); + FPT_queueSelectFail(CurrCard, p_card); SGRAM_ACCESS(port); return; } - for (i = 1; i < QUEUE_DEPTH; i++) - { - if (++lastTag >= QUEUE_DEPTH) lastTag = 1; - if (CurrCard->discQ_Tbl[lastTag] == NULL) - { + for (i = 1; i < QUEUE_DEPTH; i++) { + if (++lastTag >= QUEUE_DEPTH) + lastTag = 1; + if (CurrCard->discQ_Tbl[lastTag] == NULL) { CurrCard->tagQ_Lst = lastTag; currTar_Info->LunDiscQ_Idx[lun] = lastTag; CurrCard->discQ_Tbl[lastTag] = currSCCB; @@ -2588,206 +2417,206 @@ static void FPT_ssel(unsigned long port, unsigned char p_card) break; } } - if(i == QUEUE_DEPTH) - { + if (i == QUEUE_DEPTH) { currTar_Info->TarLUNBusy[lun] = 1; - FPT_queueSelectFail(CurrCard,p_card); + FPT_queueSelectFail(CurrCard, p_card); SGRAM_ACCESS(port); return; } } + auto_loaded = 0; + WR_HARPOON(port + hp_select_id, target); + WR_HARPOON(port + hp_gp_reg_3, target); /* Use by new automation logic */ - auto_loaded = 0; - - WR_HARPOON(port+hp_select_id, target); - WR_HARPOON(port+hp_gp_reg_3, target); /* Use by new automation logic */ + if (currSCCB->OperationCode == RESET_COMMAND) { + WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT + + (currSCCB-> + Sccb_idmsg & ~DISC_PRIV))); - if (currSCCB->OperationCode == RESET_COMMAND) { - WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+ - (currSCCB->Sccb_idmsg & ~DISC_PRIV))); + WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP); - WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+NP); + currSCCB->Sccb_scsimsg = SMDEV_RESET; - currSCCB->Sccb_scsimsg = SMDEV_RESET; + WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT)); + auto_loaded = 1; + currSCCB->Sccb_scsistat = SELECT_BDR_ST; - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); - auto_loaded = 1; - currSCCB->Sccb_scsistat = SELECT_BDR_ST; - - if (currTar_Info->TarEEValue & EE_SYNC_MASK) - { - currTar_Info->TarSyncCtrl = 0; - currTar_Info->TarStatus &= ~TAR_SYNC_MASK; - } - - if (currTar_Info->TarEEValue & EE_WIDE_SCSI) - { - currTar_Info->TarStatus &= ~TAR_WIDE_MASK; - } - - FPT_sssyncv(port, target, NARROW_SCSI,currTar_Info); - FPT_SccbMgrTableInitTarget(p_card, target); + if (currTar_Info->TarEEValue & EE_SYNC_MASK) { + currTar_Info->TarSyncCtrl = 0; + currTar_Info->TarStatus &= ~TAR_SYNC_MASK; + } - } + if (currTar_Info->TarEEValue & EE_WIDE_SCSI) { + currTar_Info->TarStatus &= ~TAR_WIDE_MASK; + } - else if(currSCCB->Sccb_scsistat == ABORT_ST) - { - WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+ - (currSCCB->Sccb_idmsg & ~DISC_PRIV))); + FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info); + FPT_SccbMgrTableInitTarget(p_card, target); - WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); + } - WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+ - (((unsigned char)(currSCCB->ControlByte & TAG_TYPE_MASK) - >> 6) | (unsigned char)0x20))); - WRW_HARPOON((port+SYNC_MSGS+2), - (MPM_OP+AMSG_OUT+currSCCB->Sccb_tag)); - WRW_HARPOON((port+SYNC_MSGS+4), (BRH_OP+ALWAYS+NP )); + else if (currSCCB->Sccb_scsistat == ABORT_ST) { + WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT + + (currSCCB-> + Sccb_idmsg & ~DISC_PRIV))); - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); - auto_loaded = 1; - - } + WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ); - else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) { - auto_loaded = FPT_siwidn(port,p_card); - currSCCB->Sccb_scsistat = SELECT_WN_ST; - } + WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + + (((unsigned + char)(currSCCB-> + ControlByte & + TAG_TYPE_MASK) + >> 6) | (unsigned char) + 0x20))); + WRW_HARPOON((port + SYNC_MSGS + 2), + (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag)); + WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP)); - else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) - == SYNC_SUPPORTED)) { - auto_loaded = FPT_sisyncn(port,p_card, 0); - currSCCB->Sccb_scsistat = SELECT_SN_ST; - } + WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT)); + auto_loaded = 1; + } - if (!auto_loaded) - { + else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) { + auto_loaded = FPT_siwidn(port, p_card); + currSCCB->Sccb_scsistat = SELECT_WN_ST; + } - if (currSCCB->ControlByte & F_USE_CMD_Q) - { + else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) + == SYNC_SUPPORTED)) { + auto_loaded = FPT_sisyncn(port, p_card, 0); + currSCCB->Sccb_scsistat = SELECT_SN_ST; + } - CurrCard->globalFlags |= F_TAG_STARTED; + if (!auto_loaded) { - if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) - == TAG_Q_REJECT) - { - currSCCB->ControlByte &= ~F_USE_CMD_Q; + if (currSCCB->ControlByte & F_USE_CMD_Q) { - /* Fix up the start instruction with a jump to - Non-Tag-CMD handling */ - WRW_HARPOON((port+ID_MSG_STRT),BRH_OP+ALWAYS+NTCMD); + CurrCard->globalFlags |= F_TAG_STARTED; - WRW_HARPOON((port+NON_TAG_ID_MSG), - (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg)); + if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) + == TAG_Q_REJECT) { + currSCCB->ControlByte &= ~F_USE_CMD_Q; - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); + /* Fix up the start instruction with a jump to + Non-Tag-CMD handling */ + WRW_HARPOON((port + ID_MSG_STRT), + BRH_OP + ALWAYS + NTCMD); - /* Setup our STATE so we know what happend when - the wheels fall off. */ - currSCCB->Sccb_scsistat = SELECT_ST; + WRW_HARPOON((port + NON_TAG_ID_MSG), + (MPM_OP + AMSG_OUT + + currSCCB->Sccb_idmsg)); - currTar_Info->TarLUNBusy[lun] = 1; - } + WR_HARPOON(port + hp_autostart_3, + (SELECT + SELCHK_STRT)); - else - { - WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg)); + /* Setup our STATE so we know what happend when + the wheels fall off. */ + currSCCB->Sccb_scsistat = SELECT_ST; - WRW_HARPOON((port+ID_MSG_STRT+2), (MPM_OP+AMSG_OUT+ - (((unsigned char)(currSCCB->ControlByte & TAG_TYPE_MASK) - >> 6) | (unsigned char)0x20))); + currTar_Info->TarLUNBusy[lun] = 1; + } - for (i = 1; i < QUEUE_DEPTH; i++) - { - if (++lastTag >= QUEUE_DEPTH) lastTag = 1; - if (CurrCard->discQ_Tbl[lastTag] == NULL) - { - WRW_HARPOON((port+ID_MSG_STRT+6), - (MPM_OP+AMSG_OUT+lastTag)); + else { + WRW_HARPOON((port + ID_MSG_STRT), + (MPM_OP + AMSG_OUT + + currSCCB->Sccb_idmsg)); + + WRW_HARPOON((port + ID_MSG_STRT + 2), + (MPM_OP + AMSG_OUT + + (((unsigned char)(currSCCB-> + ControlByte & + TAG_TYPE_MASK) + >> 6) | (unsigned char)0x20))); + + for (i = 1; i < QUEUE_DEPTH; i++) { + if (++lastTag >= QUEUE_DEPTH) + lastTag = 1; + if (CurrCard->discQ_Tbl[lastTag] == + NULL) { + WRW_HARPOON((port + + ID_MSG_STRT + 6), + (MPM_OP + AMSG_OUT + + lastTag)); CurrCard->tagQ_Lst = lastTag; currSCCB->Sccb_tag = lastTag; - CurrCard->discQ_Tbl[lastTag] = currSCCB; + CurrCard->discQ_Tbl[lastTag] = + currSCCB; CurrCard->discQCount++; break; } } + if (i == QUEUE_DEPTH) { + currTar_Info->TarLUNBusy[lun] = 1; + FPT_queueSelectFail(CurrCard, p_card); + SGRAM_ACCESS(port); + return; + } - if ( i == QUEUE_DEPTH ) - { - currTar_Info->TarLUNBusy[lun] = 1; - FPT_queueSelectFail(CurrCard,p_card); - SGRAM_ACCESS(port); - return; - } - - currSCCB->Sccb_scsistat = SELECT_Q_ST; - - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); - } - } - - else - { - - WRW_HARPOON((port+ID_MSG_STRT),BRH_OP+ALWAYS+NTCMD); + currSCCB->Sccb_scsistat = SELECT_Q_ST; - WRW_HARPOON((port+NON_TAG_ID_MSG), - (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg)); + WR_HARPOON(port + hp_autostart_3, + (SELECT + SELCHK_STRT)); + } + } - currSCCB->Sccb_scsistat = SELECT_ST; + else { - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); - } + WRW_HARPOON((port + ID_MSG_STRT), + BRH_OP + ALWAYS + NTCMD); + WRW_HARPOON((port + NON_TAG_ID_MSG), + (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg)); - theCCB = (unsigned char *)&currSCCB->Cdb[0]; + currSCCB->Sccb_scsistat = SELECT_ST; - cdb_reg = port + CMD_STRT; + WR_HARPOON(port + hp_autostart_3, + (SELECT + SELCHK_STRT)); + } - for (i=0; i < currSCCB->CdbLength; i++) - { - WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB)); - cdb_reg +=2; - theCCB++; - } + theCCB = (unsigned char *)&currSCCB->Cdb[0]; - if (currSCCB->CdbLength != TWELVE_BYTE_CMD) - WRW_HARPOON(cdb_reg, (BRH_OP+ALWAYS+ NP)); + cdb_reg = port + CMD_STRT; - } /* auto_loaded */ + for (i = 0; i < currSCCB->CdbLength; i++) { + WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB)); + cdb_reg += 2; + theCCB++; + } - WRW_HARPOON((port+hp_fiforead), (unsigned short) 0x00); - WR_HARPOON(port+hp_xferstat, 0x00); + if (currSCCB->CdbLength != TWELVE_BYTE_CMD) + WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP)); - WRW_HARPOON((port+hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE)); + } + /* auto_loaded */ + WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00); + WR_HARPOON(port + hp_xferstat, 0x00); - WR_HARPOON(port+hp_portctrl_0,(SCSI_PORT)); + WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE)); + WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT)); - if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) - { - WR_HARPOON(port+hp_scsictrl_0, (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL)); - } - else - { + if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) { + WR_HARPOON(port + hp_scsictrl_0, + (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL)); + } else { /* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F); auto_loaded |= AUTO_IMMED; */ - auto_loaded = AUTO_IMMED; + auto_loaded = AUTO_IMMED; - DISABLE_AUTO(port); + DISABLE_AUTO(port); - WR_HARPOON(port+hp_autostart_3, auto_loaded); - } + WR_HARPOON(port + hp_autostart_3, auto_loaded); + } - SGRAM_ACCESS(port); + SGRAM_ACCESS(port); } - /*--------------------------------------------------------------------- * * Function: FPT_sres @@ -2796,303 +2625,276 @@ static void FPT_ssel(unsigned long port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_sres(unsigned long port, unsigned char p_card, struct sccb_card * pCurrCard) +static void FPT_sres(unsigned long port, unsigned char p_card, + struct sccb_card *pCurrCard) { - unsigned char our_target, message, lun = 0, tag, msgRetryCount; - - - struct sccb_mgr_tar_info * currTar_Info; - struct sccb * currSCCB; + unsigned char our_target, message, lun = 0, tag, msgRetryCount; + struct sccb_mgr_tar_info *currTar_Info; + struct sccb *currSCCB; - - - if(pCurrCard->currentSCCB != NULL) - { - currTar_Info = &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID]; + if (pCurrCard->currentSCCB != NULL) { + currTar_Info = + &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID]; DISABLE_AUTO(port); - - WR_HARPOON((port+hp_scsictrl_0),(ENA_RESEL | ENA_SCAM_SEL)); - + WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL)); currSCCB = pCurrCard->currentSCCB; - if(currSCCB->Sccb_scsistat == SELECT_WN_ST) - { + if (currSCCB->Sccb_scsistat == SELECT_WN_ST) { currTar_Info->TarStatus &= ~TAR_WIDE_MASK; currSCCB->Sccb_scsistat = BUS_FREE_ST; } - if(currSCCB->Sccb_scsistat == SELECT_SN_ST) - { + if (currSCCB->Sccb_scsistat == SELECT_SN_ST) { currTar_Info->TarStatus &= ~TAR_SYNC_MASK; currSCCB->Sccb_scsistat = BUS_FREE_ST; } - if(((pCurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - currTar_Info->TarLUNBusy[currSCCB->Lun] = 0; - if(currSCCB->Sccb_scsistat != ABORT_ST) - { + if (((pCurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != + TAG_Q_TRYING))) { + currTar_Info->TarLUNBusy[currSCCB->Lun] = 0; + if (currSCCB->Sccb_scsistat != ABORT_ST) { pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[currSCCB->Lun]] - = NULL; + pCurrCard->discQ_Tbl[currTar_Info-> + LunDiscQ_Idx[currSCCB-> + Lun]] + = NULL; } - } - else - { - currTar_Info->TarLUNBusy[0] = 0; - if(currSCCB->Sccb_tag) - { - if(currSCCB->Sccb_scsistat != ABORT_ST) - { + } else { + currTar_Info->TarLUNBusy[0] = 0; + if (currSCCB->Sccb_tag) { + if (currSCCB->Sccb_scsistat != ABORT_ST) { pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currSCCB->Sccb_tag] = NULL; + pCurrCard->discQ_Tbl[currSCCB-> + Sccb_tag] = NULL; } - }else - { - if(currSCCB->Sccb_scsistat != ABORT_ST) - { + } else { + if (currSCCB->Sccb_scsistat != ABORT_ST) { pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL; + pCurrCard->discQ_Tbl[currTar_Info-> + LunDiscQ_Idx[0]] = + NULL; } } } - FPT_queueSelectFail(&FPT_BL_Card[p_card],p_card); + FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card); } - WRW_HARPOON((port+hp_fiforead), (unsigned short) 0x00); + WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00); - - our_target = (unsigned char)(RD_HARPOON(port+hp_select_id) >> 4); + our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4); currTar_Info = &FPT_sccbMgrTbl[p_card][our_target]; - msgRetryCount = 0; - do - { + do { currTar_Info = &FPT_sccbMgrTbl[p_card][our_target]; tag = 0; + while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) { + if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) { - while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) - { - if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) - { - - WRW_HARPOON((port+hp_intstat), PHASE); + WRW_HARPOON((port + hp_intstat), PHASE); return; } } - WRW_HARPOON((port+hp_intstat), PHASE); - if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) - { + WRW_HARPOON((port + hp_intstat), PHASE); + if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) { - message = FPT_sfm(port,pCurrCard->currentSCCB); - if (message) - { + message = FPT_sfm(port, pCurrCard->currentSCCB); + if (message) { - if (message <= (0x80 | LUN_MASK)) - { + if (message <= (0x80 | LUN_MASK)) { lun = message & (unsigned char)LUN_MASK; - if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING) - { - if (currTar_Info->TarTagQ_Cnt != 0) - { - - if (!(currTar_Info->TarLUN_CA)) - { - ACCEPT_MSG(port); /*Release the ACK for ID msg. */ - - - message = FPT_sfm(port,pCurrCard->currentSCCB); - if (message) - { - ACCEPT_MSG(port); + if ((currTar_Info-> + TarStatus & TAR_TAG_Q_MASK) == + TAG_Q_TRYING) { + if (currTar_Info->TarTagQ_Cnt != + 0) { + + if (! + (currTar_Info-> + TarLUN_CA)) { + ACCEPT_MSG(port); /*Release the ACK for ID msg. */ + + message = + FPT_sfm + (port, + pCurrCard-> + currentSCCB); + if (message) { + ACCEPT_MSG + (port); } else - message = 0; - - if(message != 0) - { - tag = FPT_sfm(port,pCurrCard->currentSCCB); - - if (!(tag)) - message = 0; + message + = 0; + + if (message != + 0) { + tag = + FPT_sfm + (port, + pCurrCard-> + currentSCCB); + + if (! + (tag)) + message + = + 0; } - } /*C.A. exists! */ - - } /*End Q cnt != 0 */ - - } /*End Tag cmds supported! */ - - } /*End valid ID message. */ - - else - { + } + /*C.A. exists! */ + } + /*End Q cnt != 0 */ + } + /*End Tag cmds supported! */ + } + /*End valid ID message. */ + else { ACCEPT_MSG_ATN(port); } - } /* End good id message. */ - - else - { + } + /* End good id message. */ + else { message = 0; } - } - else - { + } else { ACCEPT_MSG_ATN(port); - while (!(RDW_HARPOON((port+hp_intstat)) & (PHASE | RESET)) && - !(RD_HARPOON(port+hp_scsisig) & SCSI_REQ) && - (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ; + while (! + (RDW_HARPOON((port + hp_intstat)) & + (PHASE | RESET)) + && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) + && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ; return; } - if(message == 0) - { + if (message == 0) { msgRetryCount++; - if(msgRetryCount == 1) - { + if (msgRetryCount == 1) { FPT_SendMsg(port, SMPARITY); - } - else - { + } else { FPT_SendMsg(port, SMDEV_RESET); - FPT_sssyncv(port, our_target, NARROW_SCSI,currTar_Info); + FPT_sssyncv(port, our_target, NARROW_SCSI, + currTar_Info); - if (FPT_sccbMgrTbl[p_card][our_target].TarEEValue & EE_SYNC_MASK) - { - - FPT_sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_SYNC_MASK; + if (FPT_sccbMgrTbl[p_card][our_target]. + TarEEValue & EE_SYNC_MASK) { + + FPT_sccbMgrTbl[p_card][our_target]. + TarStatus &= ~TAR_SYNC_MASK; } - if (FPT_sccbMgrTbl[p_card][our_target].TarEEValue & EE_WIDE_SCSI) - { + if (FPT_sccbMgrTbl[p_card][our_target]. + TarEEValue & EE_WIDE_SCSI) { - FPT_sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_WIDE_MASK; + FPT_sccbMgrTbl[p_card][our_target]. + TarStatus &= ~TAR_WIDE_MASK; } - - FPT_queueFlushTargSccb(p_card, our_target, SCCB_COMPLETE); - FPT_SccbMgrTableInitTarget(p_card,our_target); + FPT_queueFlushTargSccb(p_card, our_target, + SCCB_COMPLETE); + FPT_SccbMgrTableInitTarget(p_card, our_target); return; } } - }while(message == 0); - + } while (message == 0); - - if(((pCurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { + if (((pCurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) { currTar_Info->TarLUNBusy[lun] = 1; - pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]]; - if(pCurrCard->currentSCCB != NULL) - { + pCurrCard->currentSCCB = + pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]]; + if (pCurrCard->currentSCCB != NULL) { ACCEPT_MSG(port); - } - else - { + } else { ACCEPT_MSG_ATN(port); } - } - else - { + } else { currTar_Info->TarLUNBusy[0] = 1; - - if (tag) - { - if (pCurrCard->discQ_Tbl[tag] != NULL) - { - pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[tag]; - currTar_Info->TarTagQ_Cnt--; + if (tag) { + if (pCurrCard->discQ_Tbl[tag] != NULL) { + pCurrCard->currentSCCB = + pCurrCard->discQ_Tbl[tag]; + currTar_Info->TarTagQ_Cnt--; ACCEPT_MSG(port); + } else { + ACCEPT_MSG_ATN(port); } - else - { - ACCEPT_MSG_ATN(port); - } - }else - { - pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]]; - if(pCurrCard->currentSCCB != NULL) - { + } else { + pCurrCard->currentSCCB = + pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]]; + if (pCurrCard->currentSCCB != NULL) { ACCEPT_MSG(port); - } - else - { + } else { ACCEPT_MSG_ATN(port); } } } - if(pCurrCard->currentSCCB != NULL) - { - if(pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) - { - /* During Abort Tag command, the target could have got re-selected - and completed the command. Check the select Q and remove the CCB - if it is in the Select Q */ + if (pCurrCard->currentSCCB != NULL) { + if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) { + /* During Abort Tag command, the target could have got re-selected + and completed the command. Check the select Q and remove the CCB + if it is in the Select Q */ FPT_queueFindSccb(pCurrCard->currentSCCB, p_card); } } - - while (!(RDW_HARPOON((port+hp_intstat)) & (PHASE | RESET)) && - !(RD_HARPOON(port+hp_scsisig) & SCSI_REQ) && - (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ; + while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) && + !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) && + (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ; } static void FPT_SendMsg(unsigned long port, unsigned char message) { - while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) - { - if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) - { + while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) { + if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) { - WRW_HARPOON((port+hp_intstat), PHASE); + WRW_HARPOON((port + hp_intstat), PHASE); return; } } - WRW_HARPOON((port+hp_intstat), PHASE); - if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) - { - WRW_HARPOON((port+hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0)); - + WRW_HARPOON((port + hp_intstat), PHASE); + if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) { + WRW_HARPOON((port + hp_intstat), + (BUS_FREE | PHASE | XFER_CNT_0)); - WR_HARPOON(port+hp_portctrl_0, SCSI_BUS_EN); + WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN); - WR_HARPOON(port+hp_scsidata_0,message); + WR_HARPOON(port + hp_scsidata_0, message); - WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); + WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH)); ACCEPT_MSG(port); - WR_HARPOON(port+hp_portctrl_0, 0x00); + WR_HARPOON(port + hp_portctrl_0, 0x00); if ((message == SMABORT) || (message == SMDEV_RESET) || - (message == SMABORT_TAG) ) - { - while(!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | PHASE))) {} + (message == SMABORT_TAG)) { + while (! + (RDW_HARPOON((port + hp_intstat)) & + (BUS_FREE | PHASE))) { + } - if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) - { - WRW_HARPOON((port+hp_intstat), BUS_FREE); + if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) { + WRW_HARPOON((port + hp_intstat), BUS_FREE); } } } @@ -3106,37 +2908,35 @@ static void FPT_SendMsg(unsigned long port, unsigned char message) * target device. * *---------------------------------------------------------------------*/ -static void FPT_sdecm(unsigned char message, unsigned long port, unsigned char p_card) +static void FPT_sdecm(unsigned char message, unsigned long port, + unsigned char p_card) { - struct sccb * currSCCB; - struct sccb_card * CurrCard; - struct sccb_mgr_tar_info * currTar_Info; + struct sccb *currSCCB; + struct sccb_card *CurrCard; + struct sccb_mgr_tar_info *currTar_Info; CurrCard = &FPT_BL_Card[p_card]; currSCCB = CurrCard->currentSCCB; currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; - if (message == SMREST_DATA_PTR) - { - if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) - { + if (message == SMREST_DATA_PTR) { + if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) { currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC; FPT_hostDataXferRestart(currSCCB); } ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); } - else if (message == SMCMD_COMP) - { - + else if (message == SMCMD_COMP) { - if (currSCCB->Sccb_scsistat == SELECT_Q_ST) - { - currTar_Info->TarStatus &= ~(unsigned char)TAR_TAG_Q_MASK; + if (currSCCB->Sccb_scsistat == SELECT_Q_ST) { + currTar_Info->TarStatus &= + ~(unsigned char)TAR_TAG_Q_MASK; currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT; } @@ -3144,140 +2944,144 @@ static void FPT_sdecm(unsigned char message, unsigned long port, unsigned char p } - else if ((message == SMNO_OP) || (message >= SMIDENT) - || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) - { + else if ((message == SMNO_OP) || (message >= SMIDENT) + || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) { ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); } - else if (message == SMREJECT) - { + else if (message == SMREJECT) { if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) || - (currSCCB->Sccb_scsistat == SELECT_WN_ST) || - ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING ) || - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING ) ) - + (currSCCB->Sccb_scsistat == SELECT_WN_ST) || + ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING) + || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == + TAG_Q_TRYING)) { - WRW_HARPOON((port+hp_intstat), BUS_FREE); + WRW_HARPOON((port + hp_intstat), BUS_FREE); ACCEPT_MSG(port); - - while ((!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && - (!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE))) {} - - if(currSCCB->Lun == 0x00) + while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) && + (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE))) { - if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) - { + } - currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED; + if (currSCCB->Lun == 0x00) { + if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) { - currTar_Info->TarEEValue &= ~EE_SYNC_MASK; - } + currTar_Info->TarStatus |= + (unsigned char)SYNC_SUPPORTED; - else if ((currSCCB->Sccb_scsistat == SELECT_WN_ST)) - { + currTar_Info->TarEEValue &= + ~EE_SYNC_MASK; + } + else if ((currSCCB->Sccb_scsistat == + SELECT_WN_ST)) { - currTar_Info->TarStatus = (currTar_Info->TarStatus & - ~WIDE_ENABLED) | WIDE_NEGOCIATED; + currTar_Info->TarStatus = + (currTar_Info-> + TarStatus & ~WIDE_ENABLED) | + WIDE_NEGOCIATED; - currTar_Info->TarEEValue &= ~EE_WIDE_SCSI; + currTar_Info->TarEEValue &= + ~EE_WIDE_SCSI; } - else if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING ) - { - currTar_Info->TarStatus = (currTar_Info->TarStatus & - ~(unsigned char)TAR_TAG_Q_MASK) | TAG_Q_REJECT; - + else if ((currTar_Info-> + TarStatus & TAR_TAG_Q_MASK) == + TAG_Q_TRYING) { + currTar_Info->TarStatus = + (currTar_Info-> + TarStatus & ~(unsigned char) + TAR_TAG_Q_MASK) | TAG_Q_REJECT; currSCCB->ControlByte &= ~F_USE_CMD_Q; CurrCard->discQCount--; - CurrCard->discQ_Tbl[currSCCB->Sccb_tag] = NULL; + CurrCard->discQ_Tbl[currSCCB-> + Sccb_tag] = NULL; currSCCB->Sccb_tag = 0x00; } } - if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) - { - + if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) { - if(currSCCB->Lun == 0x00) - { - WRW_HARPOON((port+hp_intstat), BUS_FREE); + if (currSCCB->Lun == 0x00) { + WRW_HARPOON((port + hp_intstat), + BUS_FREE); CurrCard->globalFlags |= F_NEW_SCCB_CMD; } } - else - { + else { - if((CurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - currTar_Info->TarLUNBusy[currSCCB->Lun] = 1; + if ((CurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info-> + TarStatus & TAR_TAG_Q_MASK) != + TAG_Q_TRYING)) + currTar_Info->TarLUNBusy[currSCCB-> + Lun] = 1; else currTar_Info->TarLUNBusy[0] = 1; + currSCCB->ControlByte &= + ~(unsigned char)F_USE_CMD_Q; - currSCCB->ControlByte &= ~(unsigned char)F_USE_CMD_Q; - - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); } } - else - { + else { ACCEPT_MSG(port); - while ((!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && - (!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE))) {} - - if (!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE)) + while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) && + (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE))) { - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + + if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) { + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); } } } - else if (message == SMEXT) - { + else if (message == SMEXT) { ACCEPT_MSG(port); - FPT_shandem(port,p_card,currSCCB); + FPT_shandem(port, p_card, currSCCB); } - else if (message == SMIGNORWR) - { + else if (message == SMIGNORWR) { - ACCEPT_MSG(port); /* ACK the RESIDUE MSG */ + ACCEPT_MSG(port); /* ACK the RESIDUE MSG */ - message = FPT_sfm(port,currSCCB); + message = FPT_sfm(port, currSCCB); - if(currSCCB->Sccb_scsimsg != SMPARITY) + if (currSCCB->Sccb_scsimsg != SMPARITY) ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); } - - else - { + else { currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; currSCCB->Sccb_scsimsg = SMREJECT; ACCEPT_MSG_ATN(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); } } - /*--------------------------------------------------------------------- * * Function: FPT_shandem @@ -3285,76 +3089,65 @@ static void FPT_sdecm(unsigned char message, unsigned long port, unsigned char p * Description: Decide what to do with the extended message. * *---------------------------------------------------------------------*/ -static void FPT_shandem(unsigned long port, unsigned char p_card, struct sccb * pCurrSCCB) +static void FPT_shandem(unsigned long port, unsigned char p_card, + struct sccb *pCurrSCCB) { - unsigned char length,message; + unsigned char length, message; - length = FPT_sfm(port,pCurrSCCB); - if (length) - { + length = FPT_sfm(port, pCurrSCCB); + if (length) { ACCEPT_MSG(port); - message = FPT_sfm(port,pCurrSCCB); - if (message) - { + message = FPT_sfm(port, pCurrSCCB); + if (message) { - if (message == SMSYNC) - { + if (message == SMSYNC) { - if (length == 0x03) - { + if (length == 0x03) { ACCEPT_MSG(port); - FPT_stsyncn(port,p_card); - } - else - { + FPT_stsyncn(port, p_card); + } else { pCurrSCCB->Sccb_scsimsg = SMREJECT; ACCEPT_MSG_ATN(port); } - } - else if (message == SMWDTR) - { + } else if (message == SMWDTR) { - if (length == 0x02) - { + if (length == 0x02) { ACCEPT_MSG(port); - FPT_stwidn(port,p_card); - } - else - { + FPT_stwidn(port, p_card); + } else { pCurrSCCB->Sccb_scsimsg = SMREJECT; ACCEPT_MSG_ATN(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + + DISCONNECT_START)); } - } - else - { + } else { pCurrSCCB->Sccb_scsimsg = SMREJECT; ACCEPT_MSG_ATN(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); } - } - else - { - if(pCurrSCCB->Sccb_scsimsg != SMPARITY) + } else { + if (pCurrSCCB->Sccb_scsimsg != SMPARITY) ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); } - }else - { - if(pCurrSCCB->Sccb_scsimsg == SMPARITY) - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } else { + if (pCurrSCCB->Sccb_scsimsg == SMPARITY) + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); } } - /*--------------------------------------------------------------------- * * Function: FPT_sisyncn @@ -3364,73 +3157,79 @@ static void FPT_shandem(unsigned long port, unsigned char p_card, struct sccb * * *---------------------------------------------------------------------*/ -static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, unsigned char syncFlag) +static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, + unsigned char syncFlag) { - struct sccb * currSCCB; - struct sccb_mgr_tar_info * currTar_Info; - - currSCCB = FPT_BL_Card[p_card].currentSCCB; - currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; - - if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) { - - - WRW_HARPOON((port+ID_MSG_STRT), - (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV))); - - WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); - - WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); - WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x03 )); - WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMSYNC)); + struct sccb *currSCCB; + struct sccb_mgr_tar_info *currTar_Info; + currSCCB = FPT_BL_Card[p_card].currentSCCB; + currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; - if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB) + if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) { - WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 12)); + WRW_HARPOON((port + ID_MSG_STRT), + (MPM_OP + AMSG_OUT + + (currSCCB-> + Sccb_idmsg & ~(unsigned char)DISC_PRIV))); - else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB) + WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ); - WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 25)); + WRW_HARPOON((port + SYNC_MSGS + 0), + (MPM_OP + AMSG_OUT + SMEXT)); + WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03)); + WRW_HARPOON((port + SYNC_MSGS + 4), + (MPM_OP + AMSG_OUT + SMSYNC)); - else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB) + if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB) - WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 50)); + WRW_HARPOON((port + SYNC_MSGS + 6), + (MPM_OP + AMSG_OUT + 12)); - else - WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 00)); + else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == + EE_SYNC_10MB) + WRW_HARPOON((port + SYNC_MSGS + 6), + (MPM_OP + AMSG_OUT + 25)); - WRW_HARPOON((port+SYNC_MSGS+8), (RAT_OP )); - WRW_HARPOON((port+SYNC_MSGS+10),(MPM_OP+AMSG_OUT+DEFAULT_OFFSET)); - WRW_HARPOON((port+SYNC_MSGS+12),(BRH_OP+ALWAYS+NP )); + else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == + EE_SYNC_5MB) + WRW_HARPOON((port + SYNC_MSGS + 6), + (MPM_OP + AMSG_OUT + 50)); - if(syncFlag == 0) - { - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); - currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(unsigned char)TAR_SYNC_MASK) | (unsigned char)SYNC_TRYING); - } else - { - WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT)); + WRW_HARPOON((port + SYNC_MSGS + 6), + (MPM_OP + AMSG_OUT + 00)); + + WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP)); + WRW_HARPOON((port + SYNC_MSGS + 10), + (MPM_OP + AMSG_OUT + DEFAULT_OFFSET)); + WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP)); + + if (syncFlag == 0) { + WR_HARPOON(port + hp_autostart_3, + (SELECT + SELCHK_STRT)); + currTar_Info->TarStatus = + ((currTar_Info-> + TarStatus & ~(unsigned char)TAR_SYNC_MASK) | + (unsigned char)SYNC_TRYING); + } else { + WR_HARPOON(port + hp_autostart_3, + (AUTO_IMMED + CMD_ONLY_STRT)); } + return (1); + } - return(1); - } - - else { + else { - currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED; - currTar_Info->TarEEValue &= ~EE_SYNC_MASK; - return(0); - } + currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED; + currTar_Info->TarEEValue &= ~EE_SYNC_MASK; + return (0); + } } - - /*--------------------------------------------------------------------- * * Function: FPT_stsyncn @@ -3441,129 +3240,126 @@ static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, unsig *---------------------------------------------------------------------*/ static void FPT_stsyncn(unsigned long port, unsigned char p_card) { - unsigned char sync_msg,offset,sync_reg,our_sync_msg; - struct sccb * currSCCB; - struct sccb_mgr_tar_info * currTar_Info; + unsigned char sync_msg, offset, sync_reg, our_sync_msg; + struct sccb *currSCCB; + struct sccb_mgr_tar_info *currTar_Info; - currSCCB = FPT_BL_Card[p_card].currentSCCB; - currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; + currSCCB = FPT_BL_Card[p_card].currentSCCB; + currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; - sync_msg = FPT_sfm(port,currSCCB); + sync_msg = FPT_sfm(port, currSCCB); - if((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) - { - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) { + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); return; } - ACCEPT_MSG(port); - + ACCEPT_MSG(port); - offset = FPT_sfm(port,currSCCB); + offset = FPT_sfm(port, currSCCB); - if((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) - { - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) { + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); return; } - if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB) - - our_sync_msg = 12; /* Setup our Message to 20mb/s */ - - else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB) + if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB) - our_sync_msg = 25; /* Setup our Message to 10mb/s */ + our_sync_msg = 12; /* Setup our Message to 20mb/s */ - else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB) + else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB) - our_sync_msg = 50; /* Setup our Message to 5mb/s */ - else - - our_sync_msg = 0; /* Message = Async */ - - if (sync_msg < our_sync_msg) { - sync_msg = our_sync_msg; /*if faster, then set to max. */ - } + our_sync_msg = 25; /* Setup our Message to 10mb/s */ - if (offset == ASYNC) - sync_msg = ASYNC; + else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB) - if (offset > MAX_OFFSET) - offset = MAX_OFFSET; + our_sync_msg = 50; /* Setup our Message to 5mb/s */ + else - sync_reg = 0x00; + our_sync_msg = 0; /* Message = Async */ - if (sync_msg > 12) + if (sync_msg < our_sync_msg) { + sync_msg = our_sync_msg; /*if faster, then set to max. */ + } - sync_reg = 0x20; /* Use 10MB/s */ + if (offset == ASYNC) + sync_msg = ASYNC; - if (sync_msg > 25) + if (offset > MAX_OFFSET) + offset = MAX_OFFSET; - sync_reg = 0x40; /* Use 6.6MB/s */ + sync_reg = 0x00; - if (sync_msg > 38) + if (sync_msg > 12) - sync_reg = 0x60; /* Use 5MB/s */ + sync_reg = 0x20; /* Use 10MB/s */ - if (sync_msg > 50) + if (sync_msg > 25) - sync_reg = 0x80; /* Use 4MB/s */ + sync_reg = 0x40; /* Use 6.6MB/s */ - if (sync_msg > 62) + if (sync_msg > 38) - sync_reg = 0xA0; /* Use 3.33MB/s */ + sync_reg = 0x60; /* Use 5MB/s */ - if (sync_msg > 75) + if (sync_msg > 50) - sync_reg = 0xC0; /* Use 2.85MB/s */ + sync_reg = 0x80; /* Use 4MB/s */ - if (sync_msg > 87) + if (sync_msg > 62) - sync_reg = 0xE0; /* Use 2.5MB/s */ + sync_reg = 0xA0; /* Use 3.33MB/s */ - if (sync_msg > 100) { + if (sync_msg > 75) - sync_reg = 0x00; /* Use ASYNC */ - offset = 0x00; - } + sync_reg = 0xC0; /* Use 2.85MB/s */ + if (sync_msg > 87) - if (currTar_Info->TarStatus & WIDE_ENABLED) + sync_reg = 0xE0; /* Use 2.5MB/s */ - sync_reg |= offset; + if (sync_msg > 100) { - else + sync_reg = 0x00; /* Use ASYNC */ + offset = 0x00; + } - sync_reg |= (offset | NARROW_SCSI); + if (currTar_Info->TarStatus & WIDE_ENABLED) - FPT_sssyncv(port,currSCCB->TargID,sync_reg,currTar_Info); + sync_reg |= offset; + else - if (currSCCB->Sccb_scsistat == SELECT_SN_ST) { + sync_reg |= (offset | NARROW_SCSI); + FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info); - ACCEPT_MSG(port); + if (currSCCB->Sccb_scsistat == SELECT_SN_ST) { - currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(unsigned char)TAR_SYNC_MASK) | (unsigned char)SYNC_SUPPORTED); + ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } + currTar_Info->TarStatus = ((currTar_Info->TarStatus & + ~(unsigned char)TAR_SYNC_MASK) | + (unsigned char)SYNC_SUPPORTED); - else { + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); + } + else { - ACCEPT_MSG_ATN(port); + ACCEPT_MSG_ATN(port); - FPT_sisyncr(port,sync_msg,offset); + FPT_sisyncr(port, sync_msg, offset); - currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(unsigned char)TAR_SYNC_MASK) | (unsigned char)SYNC_SUPPORTED); - } + currTar_Info->TarStatus = ((currTar_Info->TarStatus & + ~(unsigned char)TAR_SYNC_MASK) | + (unsigned char)SYNC_SUPPORTED); + } } - /*--------------------------------------------------------------------- * * Function: FPT_sisyncr @@ -3571,28 +3367,28 @@ static void FPT_stsyncn(unsigned long port, unsigned char p_card) * Description: Answer the targets sync message. * *---------------------------------------------------------------------*/ -static void FPT_sisyncr(unsigned long port,unsigned char sync_pulse, unsigned char offset) +static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse, + unsigned char offset) { - ARAM_ACCESS(port); - WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); - WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x03 )); - WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMSYNC)); - WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+sync_pulse)); - WRW_HARPOON((port+SYNC_MSGS+8), (RAT_OP )); - WRW_HARPOON((port+SYNC_MSGS+10),(MPM_OP+AMSG_OUT+offset)); - WRW_HARPOON((port+SYNC_MSGS+12),(BRH_OP+ALWAYS+NP )); - SGRAM_ACCESS(port); - - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT_1); - - WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED+CMD_ONLY_STRT)); - - while (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | AUTO_INT))) {} + ARAM_ACCESS(port); + WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT)); + WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03)); + WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC)); + WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse)); + WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP)); + WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset)); + WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP)); + SGRAM_ACCESS(port); + + WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); + WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1); + + WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT)); + + while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) { + } } - - /*--------------------------------------------------------------------- * * Function: FPT_siwidn @@ -3604,48 +3400,51 @@ static void FPT_sisyncr(unsigned long port,unsigned char sync_pulse, unsigned ch static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card) { - struct sccb * currSCCB; - struct sccb_mgr_tar_info * currTar_Info; - - currSCCB = FPT_BL_Card[p_card].currentSCCB; - currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; - - if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) { + struct sccb *currSCCB; + struct sccb_mgr_tar_info *currTar_Info; + currSCCB = FPT_BL_Card[p_card].currentSCCB; + currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; - WRW_HARPOON((port+ID_MSG_STRT), - (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV))); + if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) { - WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); + WRW_HARPOON((port + ID_MSG_STRT), + (MPM_OP + AMSG_OUT + + (currSCCB-> + Sccb_idmsg & ~(unsigned char)DISC_PRIV))); - WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); - WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x02 )); - WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMWDTR)); - WRW_HARPOON((port+SYNC_MSGS+6), (RAT_OP )); - WRW_HARPOON((port+SYNC_MSGS+8), (MPM_OP+AMSG_OUT+ SM16BIT)); - WRW_HARPOON((port+SYNC_MSGS+10),(BRH_OP+ALWAYS+NP )); + WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ); - WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); + WRW_HARPOON((port + SYNC_MSGS + 0), + (MPM_OP + AMSG_OUT + SMEXT)); + WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02)); + WRW_HARPOON((port + SYNC_MSGS + 4), + (MPM_OP + AMSG_OUT + SMWDTR)); + WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP)); + WRW_HARPOON((port + SYNC_MSGS + 8), + (MPM_OP + AMSG_OUT + SM16BIT)); + WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP)); + WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT)); - currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(unsigned char)TAR_WIDE_MASK) | (unsigned char)WIDE_ENABLED); + currTar_Info->TarStatus = ((currTar_Info->TarStatus & + ~(unsigned char)TAR_WIDE_MASK) | + (unsigned char)WIDE_ENABLED); - return(1); - } + return (1); + } - else { + else { - currTar_Info->TarStatus = ((currTar_Info->TarStatus & - ~(unsigned char)TAR_WIDE_MASK) | WIDE_NEGOCIATED); + currTar_Info->TarStatus = ((currTar_Info->TarStatus & + ~(unsigned char)TAR_WIDE_MASK) | + WIDE_NEGOCIATED); - currTar_Info->TarEEValue &= ~EE_WIDE_SCSI; - return(0); - } + currTar_Info->TarEEValue &= ~EE_WIDE_SCSI; + return (0); + } } - - /*--------------------------------------------------------------------- * * Function: FPT_stwidn @@ -3656,77 +3455,68 @@ static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card) *---------------------------------------------------------------------*/ static void FPT_stwidn(unsigned long port, unsigned char p_card) { - unsigned char width; - struct sccb * currSCCB; - struct sccb_mgr_tar_info * currTar_Info; + unsigned char width; + struct sccb *currSCCB; + struct sccb_mgr_tar_info *currTar_Info; - currSCCB = FPT_BL_Card[p_card].currentSCCB; - currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; + currSCCB = FPT_BL_Card[p_card].currentSCCB; + currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; - width = FPT_sfm(port,currSCCB); + width = FPT_sfm(port, currSCCB); - if((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) - { - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) { + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); return; } + if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI)) + width = 0; - if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI)) - width = 0; - - if (width) { - currTar_Info->TarStatus |= WIDE_ENABLED; - width = 0; - } - else { - width = NARROW_SCSI; - currTar_Info->TarStatus &= ~WIDE_ENABLED; - } - - - FPT_sssyncv(port,currSCCB->TargID,width,currTar_Info); - - - if (currSCCB->Sccb_scsistat == SELECT_WN_ST) - { + if (width) { + currTar_Info->TarStatus |= WIDE_ENABLED; + width = 0; + } else { + width = NARROW_SCSI; + currTar_Info->TarStatus &= ~WIDE_ENABLED; + } + FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info); + if (currSCCB->Sccb_scsistat == SELECT_WN_ST) { - currTar_Info->TarStatus |= WIDE_NEGOCIATED; + currTar_Info->TarStatus |= WIDE_NEGOCIATED; - if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_SUPPORTED)) - { - ACCEPT_MSG_ATN(port); - ARAM_ACCESS(port); - FPT_sisyncn(port,p_card, 1); - currSCCB->Sccb_scsistat = SELECT_SN_ST; - SGRAM_ACCESS(port); - } - else - { - ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + if (! + ((currTar_Info->TarStatus & TAR_SYNC_MASK) == + SYNC_SUPPORTED)) { + ACCEPT_MSG_ATN(port); + ARAM_ACCESS(port); + FPT_sisyncn(port, p_card, 1); + currSCCB->Sccb_scsistat = SELECT_SN_ST; + SGRAM_ACCESS(port); + } else { + ACCEPT_MSG(port); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); } - } - - else { + } + else { - ACCEPT_MSG_ATN(port); + ACCEPT_MSG_ATN(port); - if (currTar_Info->TarEEValue & EE_WIDE_SCSI) - width = SM16BIT; - else - width = SM8BIT; + if (currTar_Info->TarEEValue & EE_WIDE_SCSI) + width = SM16BIT; + else + width = SM8BIT; - FPT_siwidr(port,width); + FPT_siwidr(port, width); - currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED); - } + currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED); + } } - /*--------------------------------------------------------------------- * * Function: FPT_siwidr @@ -3736,25 +3526,24 @@ static void FPT_stwidn(unsigned long port, unsigned char p_card) *---------------------------------------------------------------------*/ static void FPT_siwidr(unsigned long port, unsigned char width) { - ARAM_ACCESS(port); - WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); - WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x02 )); - WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMWDTR)); - WRW_HARPOON((port+SYNC_MSGS+6), (RAT_OP )); - WRW_HARPOON((port+SYNC_MSGS+8),(MPM_OP+AMSG_OUT+width)); - WRW_HARPOON((port+SYNC_MSGS+10),(BRH_OP+ALWAYS+NP )); - SGRAM_ACCESS(port); + ARAM_ACCESS(port); + WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT)); + WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02)); + WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR)); + WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP)); + WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width)); + WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP)); + SGRAM_ACCESS(port); - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT_1); + WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); + WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1); - WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED+CMD_ONLY_STRT)); + WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT)); - while (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | AUTO_INT))) {} + while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) { + } } - - /*--------------------------------------------------------------------- * * Function: FPT_sssyncv @@ -3763,71 +3552,71 @@ static void FPT_siwidr(unsigned long port, unsigned char width) * ID specified. * *---------------------------------------------------------------------*/ -static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, unsigned char p_sync_value, - struct sccb_mgr_tar_info * currTar_Info) +static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, + unsigned char p_sync_value, + struct sccb_mgr_tar_info *currTar_Info) { - unsigned char index; - - index = p_id; - - switch (index) { - - case 0: - index = 12; /* hp_synctarg_0 */ - break; - case 1: - index = 13; /* hp_synctarg_1 */ - break; - case 2: - index = 14; /* hp_synctarg_2 */ - break; - case 3: - index = 15; /* hp_synctarg_3 */ - break; - case 4: - index = 8; /* hp_synctarg_4 */ - break; - case 5: - index = 9; /* hp_synctarg_5 */ - break; - case 6: - index = 10; /* hp_synctarg_6 */ - break; - case 7: - index = 11; /* hp_synctarg_7 */ - break; - case 8: - index = 4; /* hp_synctarg_8 */ - break; - case 9: - index = 5; /* hp_synctarg_9 */ - break; - case 10: - index = 6; /* hp_synctarg_10 */ - break; - case 11: - index = 7; /* hp_synctarg_11 */ - break; - case 12: - index = 0; /* hp_synctarg_12 */ - break; - case 13: - index = 1; /* hp_synctarg_13 */ - break; - case 14: - index = 2; /* hp_synctarg_14 */ - break; - case 15: - index = 3; /* hp_synctarg_15 */ + unsigned char index; + + index = p_id; + + switch (index) { + + case 0: + index = 12; /* hp_synctarg_0 */ + break; + case 1: + index = 13; /* hp_synctarg_1 */ + break; + case 2: + index = 14; /* hp_synctarg_2 */ + break; + case 3: + index = 15; /* hp_synctarg_3 */ + break; + case 4: + index = 8; /* hp_synctarg_4 */ + break; + case 5: + index = 9; /* hp_synctarg_5 */ + break; + case 6: + index = 10; /* hp_synctarg_6 */ + break; + case 7: + index = 11; /* hp_synctarg_7 */ + break; + case 8: + index = 4; /* hp_synctarg_8 */ + break; + case 9: + index = 5; /* hp_synctarg_9 */ + break; + case 10: + index = 6; /* hp_synctarg_10 */ + break; + case 11: + index = 7; /* hp_synctarg_11 */ + break; + case 12: + index = 0; /* hp_synctarg_12 */ + break; + case 13: + index = 1; /* hp_synctarg_13 */ + break; + case 14: + index = 2; /* hp_synctarg_14 */ + break; + case 15: + index = 3; /* hp_synctarg_15 */ - } + } - WR_HARPOON(p_port+hp_synctarg_base+index, p_sync_value); + WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value); currTar_Info->TarSyncCtrl = p_sync_value; } - /*--------------------------------------------------------------------- * * Function: FPT_sresb @@ -3837,67 +3626,65 @@ static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, unsigned char *---------------------------------------------------------------------*/ static void FPT_sresb(unsigned long port, unsigned char p_card) { - unsigned char scsiID, i; + unsigned char scsiID, i; - struct sccb_mgr_tar_info * currTar_Info; + struct sccb_mgr_tar_info *currTar_Info; - WR_HARPOON(port+hp_page_ctrl, - (RD_HARPOON(port+hp_page_ctrl) | G_INT_DISABLE)); - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); + WR_HARPOON(port + hp_page_ctrl, + (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE)); + WRW_HARPOON((port + hp_intstat), CLR_ALL_INT); - WR_HARPOON(port+hp_scsictrl_0, SCSI_RST); + WR_HARPOON(port + hp_scsictrl_0, SCSI_RST); - scsiID = RD_HARPOON(port+hp_seltimeout); - WR_HARPOON(port+hp_seltimeout,TO_5ms); - WRW_HARPOON((port+hp_intstat), TIMEOUT); + scsiID = RD_HARPOON(port + hp_seltimeout); + WR_HARPOON(port + hp_seltimeout, TO_5ms); + WRW_HARPOON((port + hp_intstat), TIMEOUT); - WR_HARPOON(port+hp_portctrl_0,(SCSI_PORT | START_TO)); + WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO)); - while (!(RDW_HARPOON((port+hp_intstat)) & TIMEOUT)) {} + while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) { + } - WR_HARPOON(port+hp_seltimeout,scsiID); + WR_HARPOON(port + hp_seltimeout, scsiID); - WR_HARPOON(port+hp_scsictrl_0, ENA_SCAM_SEL); + WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL); - FPT_Wait(port, TO_5ms); + FPT_Wait(port, TO_5ms); - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); + WRW_HARPOON((port + hp_intstat), CLR_ALL_INT); - WR_HARPOON(port+hp_int_mask, (RD_HARPOON(port+hp_int_mask) | 0x00)); + WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00)); - for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) - { - currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID]; + for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) { + currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID]; - if (currTar_Info->TarEEValue & EE_SYNC_MASK) - { - currTar_Info->TarSyncCtrl = 0; - currTar_Info->TarStatus &= ~TAR_SYNC_MASK; - } + if (currTar_Info->TarEEValue & EE_SYNC_MASK) { + currTar_Info->TarSyncCtrl = 0; + currTar_Info->TarStatus &= ~TAR_SYNC_MASK; + } - if (currTar_Info->TarEEValue & EE_WIDE_SCSI) - { - currTar_Info->TarStatus &= ~TAR_WIDE_MASK; - } + if (currTar_Info->TarEEValue & EE_WIDE_SCSI) { + currTar_Info->TarStatus &= ~TAR_WIDE_MASK; + } - FPT_sssyncv(port, scsiID, NARROW_SCSI,currTar_Info); + FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info); - FPT_SccbMgrTableInitTarget(p_card, scsiID); - } + FPT_SccbMgrTableInitTarget(p_card, scsiID); + } - FPT_BL_Card[p_card].scanIndex = 0x00; - FPT_BL_Card[p_card].currentSCCB = NULL; - FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT - | F_NEW_SCCB_CMD); - FPT_BL_Card[p_card].cmdCounter = 0x00; + FPT_BL_Card[p_card].scanIndex = 0x00; + FPT_BL_Card[p_card].currentSCCB = NULL; + FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT + | F_NEW_SCCB_CMD); + FPT_BL_Card[p_card].cmdCounter = 0x00; FPT_BL_Card[p_card].discQCount = 0x00; - FPT_BL_Card[p_card].tagQ_Lst = 0x01; + FPT_BL_Card[p_card].tagQ_Lst = 0x01; - for(i = 0; i < QUEUE_DEPTH; i++) + for (i = 0; i < QUEUE_DEPTH; i++) FPT_BL_Card[p_card].discQ_Tbl[i] = NULL; - WR_HARPOON(port+hp_page_ctrl, - (RD_HARPOON(port+hp_page_ctrl) & ~G_INT_DISABLE)); + WR_HARPOON(port + hp_page_ctrl, + (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE)); } @@ -3908,46 +3695,43 @@ static void FPT_sresb(unsigned long port, unsigned char p_card) * Description: Setup for the Auto Sense command. * *---------------------------------------------------------------------*/ -static void FPT_ssenss(struct sccb_card * pCurrCard) +static void FPT_ssenss(struct sccb_card *pCurrCard) { - unsigned char i; - struct sccb * currSCCB; - - currSCCB = pCurrCard->currentSCCB; + unsigned char i; + struct sccb *currSCCB; + currSCCB = pCurrCard->currentSCCB; - currSCCB->Save_CdbLen = currSCCB->CdbLength; + currSCCB->Save_CdbLen = currSCCB->CdbLength; - for (i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) { - currSCCB->Save_Cdb[i] = currSCCB->Cdb[i]; - } + currSCCB->Save_Cdb[i] = currSCCB->Cdb[i]; + } - currSCCB->CdbLength = SIX_BYTE_CMD; - currSCCB->Cdb[0] = SCSI_REQUEST_SENSE; - currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */ - currSCCB->Cdb[2] = 0x00; - currSCCB->Cdb[3] = 0x00; - currSCCB->Cdb[4] = currSCCB->RequestSenseLength; - currSCCB->Cdb[5] = 0x00; + currSCCB->CdbLength = SIX_BYTE_CMD; + currSCCB->Cdb[0] = SCSI_REQUEST_SENSE; + currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */ + currSCCB->Cdb[2] = 0x00; + currSCCB->Cdb[3] = 0x00; + currSCCB->Cdb[4] = currSCCB->RequestSenseLength; + currSCCB->Cdb[5] = 0x00; - currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength; + currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength; - currSCCB->Sccb_ATC = 0x00; + currSCCB->Sccb_ATC = 0x00; - currSCCB->Sccb_XferState |= F_AUTO_SENSE; + currSCCB->Sccb_XferState |= F_AUTO_SENSE; - currSCCB->Sccb_XferState &= ~F_SG_XFER; + currSCCB->Sccb_XferState &= ~F_SG_XFER; - currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV; + currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV; - currSCCB->ControlByte = 0x00; + currSCCB->ControlByte = 0x00; - currSCCB->Sccb_MGRFlags &= F_STATUSLOADED; + currSCCB->Sccb_MGRFlags &= F_STATUSLOADED; } - - /*--------------------------------------------------------------------- * * Function: FPT_sxfrp @@ -3959,77 +3743,77 @@ static void FPT_ssenss(struct sccb_card * pCurrCard) static void FPT_sxfrp(unsigned long p_port, unsigned char p_card) { - unsigned char curr_phz; + unsigned char curr_phz; + DISABLE_AUTO(p_port); - DISABLE_AUTO(p_port); + if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) { - if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) { + FPT_hostDataXferAbort(p_port, p_card, + FPT_BL_Card[p_card].currentSCCB); - FPT_hostDataXferAbort(p_port,p_card,FPT_BL_Card[p_card].currentSCCB); + } - } + /* If the Automation handled the end of the transfer then do not + match the phase or we will get out of sync with the ISR. */ + + if (RDW_HARPOON((p_port + hp_intstat)) & + (BUS_FREE | XFER_CNT_0 | AUTO_INT)) + return; + + WR_HARPOON(p_port + hp_xfercnt_0, 0x00); + + curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ; - /* If the Automation handled the end of the transfer then do not - match the phase or we will get out of sync with the ISR. */ + WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0); - if (RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | XFER_CNT_0 | AUTO_INT)) - return; + WR_HARPOON(p_port + hp_scsisig, curr_phz); - WR_HARPOON(p_port+hp_xfercnt_0, 0x00); + while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) && + (curr_phz == + (RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ))) + { + if (curr_phz & (unsigned char)SCSI_IOBIT) { + WR_HARPOON(p_port + hp_portctrl_0, + (SCSI_PORT | HOST_PORT | SCSI_INBIT)); - curr_phz = RD_HARPOON(p_port+hp_scsisig) & (unsigned char)S_SCSI_PHZ; + if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) { + RD_HARPOON(p_port + hp_fifodata_0); + } + } else { + WR_HARPOON(p_port + hp_portctrl_0, + (SCSI_PORT | HOST_PORT | HOST_WRT)); + if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) { + WR_HARPOON(p_port + hp_fifodata_0, 0xFA); + } + } + } /* End of While loop for padding data I/O phase */ - WRW_HARPOON((p_port+hp_intstat), XFER_CNT_0); + while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) { + if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) + break; + } + WR_HARPOON(p_port + hp_portctrl_0, + (SCSI_PORT | HOST_PORT | SCSI_INBIT)); + while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) { + RD_HARPOON(p_port + hp_fifodata_0); + } - WR_HARPOON(p_port+hp_scsisig, curr_phz); + if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) { + WR_HARPOON(p_port + hp_autostart_0, + (AUTO_IMMED + DISCONNECT_START)); + while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) { + } - while ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET)) && - (curr_phz == (RD_HARPOON(p_port+hp_scsisig) & (unsigned char)S_SCSI_PHZ)) ) - { - if (curr_phz & (unsigned char)SCSI_IOBIT) - { - WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | SCSI_INBIT)); - - if (!(RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY)) - { - RD_HARPOON(p_port+hp_fifodata_0); - } - } - else - { - WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | HOST_WRT)); - if (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY) - { - WR_HARPOON(p_port+hp_fifodata_0,0xFA); - } - } - } /* End of While loop for padding data I/O phase */ - - while ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET))) - { - if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ) - break; - } - - WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | SCSI_INBIT)); - while (!(RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY)) - { - RD_HARPOON(p_port+hp_fifodata_0); - } - - if ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET))) - { - WR_HARPOON(p_port+hp_autostart_0, (AUTO_IMMED+DISCONNECT_START)); - while (!(RDW_HARPOON((p_port+hp_intstat)) & AUTO_INT)) {} - - if (RDW_HARPOON((p_port+hp_intstat)) & (ICMD_COMP | ITAR_DISC)) - while (!(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RSEL))) ; - } + if (RDW_HARPOON((p_port + hp_intstat)) & + (ICMD_COMP | ITAR_DISC)) + while (! + (RDW_HARPOON((p_port + hp_intstat)) & + (BUS_FREE | RSEL))) ; + } } - /*--------------------------------------------------------------------- * * Function: FPT_schkdd @@ -4041,109 +3825,97 @@ static void FPT_sxfrp(unsigned long p_port, unsigned char p_card) static void FPT_schkdd(unsigned long port, unsigned char p_card) { - unsigned short TimeOutLoop; + unsigned short TimeOutLoop; unsigned char sPhase; - struct sccb * currSCCB; - - currSCCB = FPT_BL_Card[p_card].currentSCCB; - - - if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) && - (currSCCB->Sccb_scsistat != DATA_IN_ST)) { - return; - } + struct sccb *currSCCB; + currSCCB = FPT_BL_Card[p_card].currentSCCB; + if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) && + (currSCCB->Sccb_scsistat != DATA_IN_ST)) { + return; + } - if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) - { + if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) { - currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt-1); + currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1); - currSCCB->Sccb_XferCnt = 1; + currSCCB->Sccb_XferCnt = 1; - currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT; - WRW_HARPOON((port+hp_fiforead), (unsigned short) 0x00); - WR_HARPOON(port+hp_xferstat, 0x00); - } + currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT; + WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00); + WR_HARPOON(port + hp_xferstat, 0x00); + } - else - { + else { - currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt; + currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt; - currSCCB->Sccb_XferCnt = 0; - } + currSCCB->Sccb_XferCnt = 0; + } - if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && - (currSCCB->HostStatus == SCCB_COMPLETE)) { + if ((RDW_HARPOON((port + hp_intstat)) & PARITY) && + (currSCCB->HostStatus == SCCB_COMPLETE)) { - currSCCB->HostStatus = SCCB_PARITY_ERR; - WRW_HARPOON((port+hp_intstat), PARITY); - } + currSCCB->HostStatus = SCCB_PARITY_ERR; + WRW_HARPOON((port + hp_intstat), PARITY); + } + FPT_hostDataXferAbort(port, p_card, currSCCB); - FPT_hostDataXferAbort(port,p_card,currSCCB); + while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) { + } + TimeOutLoop = 0; - while (RD_HARPOON(port+hp_scsisig) & SCSI_ACK) {} + while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) { + if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) { + return; + } + if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) { + break; + } + if (RDW_HARPOON((port + hp_intstat)) & RESET) { + return; + } + if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ) + || (TimeOutLoop++ > 0x3000)) + break; + } - TimeOutLoop = 0; + sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ); + if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) || + (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) || + (sPhase == (SCSI_BSY | S_DATAO_PH)) || + (sPhase == (SCSI_BSY | S_DATAI_PH))) { - while(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY) - { - if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) { - return; - } - if (RD_HARPOON(port+hp_offsetctr) & (unsigned char)0x1F) { - break; - } - if (RDW_HARPOON((port+hp_intstat)) & RESET) { - return; - } - if ((RD_HARPOON(port+hp_scsisig) & SCSI_REQ) || (TimeOutLoop++>0x3000) ) - break; - } + WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); - sPhase = RD_HARPOON(port+hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ); - if ((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) || - (RD_HARPOON(port+hp_offsetctr) & (unsigned char)0x1F) || - (sPhase == (SCSI_BSY | S_DATAO_PH)) || - (sPhase == (SCSI_BSY | S_DATAI_PH))) - { + if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) { + if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) { + FPT_phaseDataIn(port, p_card); + } - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + else { + FPT_phaseDataOut(port, p_card); + } + } else { + FPT_sxfrp(port, p_card); + if (!(RDW_HARPOON((port + hp_intstat)) & + (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) { + WRW_HARPOON((port + hp_intstat), AUTO_INT); + FPT_phaseDecode(port, p_card); + } + } - if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) - { - if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) { - FPT_phaseDataIn(port,p_card); - } + } - else { - FPT_phaseDataOut(port,p_card); - } - } - else - { - FPT_sxfrp(port,p_card); - if (!(RDW_HARPOON((port+hp_intstat)) & - (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) - { - WRW_HARPOON((port+hp_intstat), AUTO_INT); - FPT_phaseDecode(port,p_card); - } - } - - } - - else { - WR_HARPOON(port+hp_portctrl_0, 0x00); - } + else { + WR_HARPOON(port + hp_portctrl_0, 0x00); + } } - /*--------------------------------------------------------------------- * * Function: FPT_sinits @@ -4152,39 +3924,37 @@ static void FPT_schkdd(unsigned long port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_sinits(struct sccb * p_sccb, unsigned char p_card) +static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card) { - struct sccb_mgr_tar_info * currTar_Info; + struct sccb_mgr_tar_info *currTar_Info; - if((p_sccb->TargID > MAX_SCSI_TAR) || (p_sccb->Lun > MAX_LUN)) - { + if ((p_sccb->TargID > MAX_SCSI_TAR) || (p_sccb->Lun > MAX_LUN)) { return; } - currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID]; + currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID]; - p_sccb->Sccb_XferState = 0x00; - p_sccb->Sccb_XferCnt = p_sccb->DataLength; + p_sccb->Sccb_XferState = 0x00; + p_sccb->Sccb_XferCnt = p_sccb->DataLength; - if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) || - (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) { + if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) || + (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) { - p_sccb->Sccb_SGoffset = 0; - p_sccb->Sccb_XferState = F_SG_XFER; - p_sccb->Sccb_XferCnt = 0x00; - } + p_sccb->Sccb_SGoffset = 0; + p_sccb->Sccb_XferState = F_SG_XFER; + p_sccb->Sccb_XferCnt = 0x00; + } - if (p_sccb->DataLength == 0x00) + if (p_sccb->DataLength == 0x00) - p_sccb->Sccb_XferState |= F_ALL_XFERRED; + p_sccb->Sccb_XferState |= F_ALL_XFERRED; - if (p_sccb->ControlByte & F_USE_CMD_Q) - { - if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT) - p_sccb->ControlByte &= ~F_USE_CMD_Q; + if (p_sccb->ControlByte & F_USE_CMD_Q) { + if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT) + p_sccb->ControlByte &= ~F_USE_CMD_Q; - else - currTar_Info->TarStatus |= TAG_Q_TRYING; - } + else + currTar_Info->TarStatus |= TAG_Q_TRYING; + } /* For !single SCSI device in system & device allow Disconnect or command is tag_q type then send Cmd with Disconnect Enable @@ -4195,35 +3965,35 @@ static void FPT_sinits(struct sccb * p_sccb, unsigned char p_card) (currTar_Info->TarStatus & TAR_ALLOW_DISC)) || (currTar_Info->TarStatus & TAG_Q_TRYING)) { */ - if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) || - (currTar_Info->TarStatus & TAG_Q_TRYING)) { - p_sccb->Sccb_idmsg = (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun; - } + if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) || + (currTar_Info->TarStatus & TAG_Q_TRYING)) { + p_sccb->Sccb_idmsg = + (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun; + } - else { + else { - p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun; - } + p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun; + } - p_sccb->HostStatus = 0x00; - p_sccb->TargetStatus = 0x00; - p_sccb->Sccb_tag = 0x00; - p_sccb->Sccb_MGRFlags = 0x00; - p_sccb->Sccb_sgseg = 0x00; - p_sccb->Sccb_ATC = 0x00; - p_sccb->Sccb_savedATC = 0x00; + p_sccb->HostStatus = 0x00; + p_sccb->TargetStatus = 0x00; + p_sccb->Sccb_tag = 0x00; + p_sccb->Sccb_MGRFlags = 0x00; + p_sccb->Sccb_sgseg = 0x00; + p_sccb->Sccb_ATC = 0x00; + p_sccb->Sccb_savedATC = 0x00; /* p_sccb->SccbVirtDataPtr = 0x00; p_sccb->Sccb_forwardlink = NULL; p_sccb->Sccb_backlink = NULL; */ - p_sccb->Sccb_scsistat = BUS_FREE_ST; - p_sccb->SccbStatus = SCCB_IN_PROCESS; - p_sccb->Sccb_scsimsg = SMNO_OP; + p_sccb->Sccb_scsistat = BUS_FREE_ST; + p_sccb->SccbStatus = SCCB_IN_PROCESS; + p_sccb->Sccb_scsimsg = SMNO_OP; } - /*--------------------------------------------------------------------- * * Function: Phase Decode @@ -4234,21 +4004,19 @@ static void FPT_sinits(struct sccb * p_sccb, unsigned char p_card) static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card) { - unsigned char phase_ref; - void (*phase) (unsigned long, unsigned char); - + unsigned char phase_ref; + void (*phase) (unsigned long, unsigned char); - DISABLE_AUTO(p_port); + DISABLE_AUTO(p_port); - phase_ref = (unsigned char) (RD_HARPOON(p_port+hp_scsisig) & S_SCSI_PHZ); + phase_ref = + (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ); - phase = FPT_s_PhaseTbl[phase_ref]; + phase = FPT_s_PhaseTbl[phase_ref]; - (*phase)(p_port, p_card); /* Call the correct phase func */ + (*phase) (p_port, p_card); /* Call the correct phase func */ } - - /*--------------------------------------------------------------------- * * Function: Data Out Phase @@ -4260,39 +4028,36 @@ static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card) static void FPT_phaseDataOut(unsigned long port, unsigned char p_card) { - struct sccb * currSCCB; + struct sccb *currSCCB; - currSCCB = FPT_BL_Card[p_card].currentSCCB; - if (currSCCB == NULL) - { - return; /* Exit if No SCCB record */ - } - - currSCCB->Sccb_scsistat = DATA_OUT_ST; - currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET); + currSCCB = FPT_BL_Card[p_card].currentSCCB; + if (currSCCB == NULL) { + return; /* Exit if No SCCB record */ + } - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + currSCCB->Sccb_scsistat = DATA_OUT_ST; + currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET); - WRW_HARPOON((port+hp_intstat), XFER_CNT_0); + WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); - WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START)); + WRW_HARPOON((port + hp_intstat), XFER_CNT_0); - FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]); + WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START)); - if (currSCCB->Sccb_XferCnt == 0) { + FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]); + if (currSCCB->Sccb_XferCnt == 0) { - if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) && - (currSCCB->HostStatus == SCCB_COMPLETE)) - currSCCB->HostStatus = SCCB_DATA_OVER_RUN; + if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) && + (currSCCB->HostStatus == SCCB_COMPLETE)) + currSCCB->HostStatus = SCCB_DATA_OVER_RUN; - FPT_sxfrp(port,p_card); - if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET))) - FPT_phaseDecode(port,p_card); - } + FPT_sxfrp(port, p_card); + if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET))) + FPT_phaseDecode(port, p_card); + } } - /*--------------------------------------------------------------------- * * Function: Data In Phase @@ -4304,40 +4069,37 @@ static void FPT_phaseDataOut(unsigned long port, unsigned char p_card) static void FPT_phaseDataIn(unsigned long port, unsigned char p_card) { - struct sccb * currSCCB; - - currSCCB = FPT_BL_Card[p_card].currentSCCB; - - if (currSCCB == NULL) - { - return; /* Exit if No SCCB record */ - } + struct sccb *currSCCB; + currSCCB = FPT_BL_Card[p_card].currentSCCB; - currSCCB->Sccb_scsistat = DATA_IN_ST; - currSCCB->Sccb_XferState |= F_HOST_XFER_DIR; - currSCCB->Sccb_XferState &= ~F_NO_DATA_YET; + if (currSCCB == NULL) { + return; /* Exit if No SCCB record */ + } - WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + currSCCB->Sccb_scsistat = DATA_IN_ST; + currSCCB->Sccb_XferState |= F_HOST_XFER_DIR; + currSCCB->Sccb_XferState &= ~F_NO_DATA_YET; - WRW_HARPOON((port+hp_intstat), XFER_CNT_0); + WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); - WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START)); + WRW_HARPOON((port + hp_intstat), XFER_CNT_0); - FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]); + WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START)); - if (currSCCB->Sccb_XferCnt == 0) { + FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]); + if (currSCCB->Sccb_XferCnt == 0) { - if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) && - (currSCCB->HostStatus == SCCB_COMPLETE)) - currSCCB->HostStatus = SCCB_DATA_OVER_RUN; + if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) && + (currSCCB->HostStatus == SCCB_COMPLETE)) + currSCCB->HostStatus = SCCB_DATA_OVER_RUN; - FPT_sxfrp(port,p_card); - if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET))) - FPT_phaseDecode(port,p_card); + FPT_sxfrp(port, p_card); + if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET))) + FPT_phaseDecode(port, p_card); - } + } } /*--------------------------------------------------------------------- @@ -4350,48 +4112,47 @@ static void FPT_phaseDataIn(unsigned long port, unsigned char p_card) static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card) { - struct sccb * currSCCB; - unsigned long cdb_reg; - unsigned char i; - - currSCCB = FPT_BL_Card[p_card].currentSCCB; + struct sccb *currSCCB; + unsigned long cdb_reg; + unsigned char i; - if (currSCCB->OperationCode == RESET_COMMAND) { + currSCCB = FPT_BL_Card[p_card].currentSCCB; - currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; - currSCCB->CdbLength = SIX_BYTE_CMD; - } + if (currSCCB->OperationCode == RESET_COMMAND) { - WR_HARPOON(p_port+hp_scsisig, 0x00); + currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; + currSCCB->CdbLength = SIX_BYTE_CMD; + } - ARAM_ACCESS(p_port); + WR_HARPOON(p_port + hp_scsisig, 0x00); + ARAM_ACCESS(p_port); - cdb_reg = p_port + CMD_STRT; + cdb_reg = p_port + CMD_STRT; - for (i=0; i < currSCCB->CdbLength; i++) { + for (i = 0; i < currSCCB->CdbLength; i++) { - if (currSCCB->OperationCode == RESET_COMMAND) + if (currSCCB->OperationCode == RESET_COMMAND) - WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00)); + WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00)); - else - WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + currSCCB->Cdb[i])); - cdb_reg +=2; - } + else + WRW_HARPOON(cdb_reg, + (MPM_OP + ACOMMAND + currSCCB->Cdb[i])); + cdb_reg += 2; + } - if (currSCCB->CdbLength != TWELVE_BYTE_CMD) - WRW_HARPOON(cdb_reg, (BRH_OP+ALWAYS+ NP)); + if (currSCCB->CdbLength != TWELVE_BYTE_CMD) + WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP)); - WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT)); + WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT)); - currSCCB->Sccb_scsistat = COMMAND_ST; + currSCCB->Sccb_scsistat = COMMAND_ST; - WR_HARPOON(p_port+hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT)); - SGRAM_ACCESS(p_port); + WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT)); + SGRAM_ACCESS(p_port); } - /*--------------------------------------------------------------------- * * Function: Status phase @@ -4402,17 +4163,16 @@ static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card) static void FPT_phaseStatus(unsigned long port, unsigned char p_card) { - /* Start-up the automation to finish off this command and let the - isr handle the interrupt for command complete when it comes in. - We could wait here for the interrupt to be generated? - */ + /* Start-up the automation to finish off this command and let the + isr handle the interrupt for command complete when it comes in. + We could wait here for the interrupt to be generated? + */ - WR_HARPOON(port+hp_scsisig, 0x00); + WR_HARPOON(port + hp_scsisig, 0x00); - WR_HARPOON(port+hp_autostart_0, (AUTO_IMMED+END_DATA_START)); + WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START)); } - /*--------------------------------------------------------------------- * * Function: Phase Message Out @@ -4424,9 +4184,9 @@ static void FPT_phaseStatus(unsigned long port, unsigned char p_card) static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card) { - unsigned char message,scsiID; - struct sccb * currSCCB; - struct sccb_mgr_tar_info * currTar_Info; + unsigned char message, scsiID; + struct sccb *currSCCB; + struct sccb_mgr_tar_info *currTar_Info; currSCCB = FPT_BL_Card[p_card].currentSCCB; @@ -4435,133 +4195,124 @@ static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card) message = currSCCB->Sccb_scsimsg; scsiID = currSCCB->TargID; - if (message == SMDEV_RESET) - { - + if (message == SMDEV_RESET) { currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID]; currTar_Info->TarSyncCtrl = 0; - FPT_sssyncv(port, scsiID, NARROW_SCSI,currTar_Info); + FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info); - if (FPT_sccbMgrTbl[p_card][scsiID].TarEEValue & EE_SYNC_MASK) - { + if (FPT_sccbMgrTbl[p_card][scsiID]. + TarEEValue & EE_SYNC_MASK) { - FPT_sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_SYNC_MASK; + FPT_sccbMgrTbl[p_card][scsiID].TarStatus &= + ~TAR_SYNC_MASK; } - if (FPT_sccbMgrTbl[p_card][scsiID].TarEEValue & EE_WIDE_SCSI) - { + if (FPT_sccbMgrTbl[p_card][scsiID]. + TarEEValue & EE_WIDE_SCSI) { - FPT_sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_WIDE_MASK; + FPT_sccbMgrTbl[p_card][scsiID].TarStatus &= + ~TAR_WIDE_MASK; } - - FPT_queueFlushSccb(p_card,SCCB_COMPLETE); - FPT_SccbMgrTableInitTarget(p_card,scsiID); - } - else if (currSCCB->Sccb_scsistat == ABORT_ST) - { + FPT_queueFlushSccb(p_card, SCCB_COMPLETE); + FPT_SccbMgrTableInitTarget(p_card, scsiID); + } else if (currSCCB->Sccb_scsistat == ABORT_ST) { currSCCB->HostStatus = SCCB_COMPLETE; - if(FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] != NULL) - { - FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; + if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] != + NULL) { + FPT_BL_Card[p_card].discQ_Tbl[currSCCB-> + Sccb_tag] = NULL; FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--; } - - } - else if (currSCCB->Sccb_scsistat < COMMAND_ST) - { + } + else if (currSCCB->Sccb_scsistat < COMMAND_ST) { - if(message == SMNO_OP) - { + if (message == SMNO_OP) { currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED; - - FPT_ssel(port,p_card); + + FPT_ssel(port, p_card); return; } - } - else - { - + } else { if (message == SMABORT) - FPT_queueFlushSccb(p_card,SCCB_COMPLETE); + FPT_queueFlushSccb(p_card, SCCB_COMPLETE); } - } - else - { + } else { message = SMABORT; } - WRW_HARPOON((port+hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0)); - + WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0)); - WR_HARPOON(port+hp_portctrl_0, SCSI_BUS_EN); + WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN); - WR_HARPOON(port+hp_scsidata_0,message); + WR_HARPOON(port + hp_scsidata_0, message); - WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); + WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH)); ACCEPT_MSG(port); - WR_HARPOON(port+hp_portctrl_0, 0x00); + WR_HARPOON(port + hp_portctrl_0, 0x00); - if ((message == SMABORT) || (message == SMDEV_RESET) || - (message == SMABORT_TAG) ) - { + if ((message == SMABORT) || (message == SMDEV_RESET) || + (message == SMABORT_TAG)) { - while(!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | PHASE))) {} + while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) { + } - if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) - { - WRW_HARPOON((port+hp_intstat), BUS_FREE); + if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) { + WRW_HARPOON((port + hp_intstat), BUS_FREE); - if (currSCCB != NULL) - { + if (currSCCB != NULL) { - if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0; + if ((FPT_BL_Card[p_card]. + globalFlags & F_CONLUN_IO) + && + ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus & TAR_TAG_Q_MASK) != + TAG_Q_TRYING)) + FPT_sccbMgrTbl[p_card][currSCCB-> + TargID]. + TarLUNBusy[currSCCB->Lun] = 0; else - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0; + FPT_sccbMgrTbl[p_card][currSCCB-> + TargID]. + TarLUNBusy[0] = 0; - FPT_queueCmdComplete(&FPT_BL_Card[p_card],currSCCB, p_card); + FPT_queueCmdComplete(&FPT_BL_Card[p_card], + currSCCB, p_card); } - else - { - FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; + else { + FPT_BL_Card[p_card].globalFlags |= + F_NEW_SCCB_CMD; } } - else - { + else { - FPT_sxfrp(port,p_card); + FPT_sxfrp(port, p_card); } } - else - { + else { - if(message == SMPARITY) - { + if (message == SMPARITY) { currSCCB->Sccb_scsimsg = SMNO_OP; - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); - } - else - { - FPT_sxfrp(port,p_card); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); + } else { + FPT_sxfrp(port, p_card); } } } - /*--------------------------------------------------------------------- * * Function: Message In phase @@ -4573,46 +4324,40 @@ static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card) static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card) { unsigned char message; - struct sccb * currSCCB; + struct sccb *currSCCB; currSCCB = FPT_BL_Card[p_card].currentSCCB; - if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) - { + if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) { FPT_phaseChkFifo(port, p_card); } - message = RD_HARPOON(port+hp_scsidata_0); - if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) - { + message = RD_HARPOON(port + hp_scsidata_0); + if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) { - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+END_DATA_START)); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + END_DATA_START)); } - else - { - - message = FPT_sfm(port,currSCCB); - if (message) - { + else { + message = FPT_sfm(port, currSCCB); + if (message) { - FPT_sdecm(message,port,p_card); + FPT_sdecm(message, port, p_card); - } - else - { - if(currSCCB->Sccb_scsimsg != SMPARITY) + } else { + if (currSCCB->Sccb_scsimsg != SMPARITY) ACCEPT_MSG(port); - WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + WR_HARPOON(port + hp_autostart_1, + (AUTO_IMMED + DISCONNECT_START)); } } } - /*--------------------------------------------------------------------- * * Function: Illegal phase @@ -4625,23 +4370,21 @@ static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card) static void FPT_phaseIllegal(unsigned long port, unsigned char p_card) { - struct sccb * currSCCB; + struct sccb *currSCCB; - currSCCB = FPT_BL_Card[p_card].currentSCCB; + currSCCB = FPT_BL_Card[p_card].currentSCCB; - WR_HARPOON(port+hp_scsisig, RD_HARPOON(port+hp_scsisig)); - if (currSCCB != NULL) { + WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig)); + if (currSCCB != NULL) { - currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; - currSCCB->Sccb_scsistat = ABORT_ST; - currSCCB->Sccb_scsimsg = SMABORT; - } + currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; + currSCCB->Sccb_scsistat = ABORT_ST; + currSCCB->Sccb_scsimsg = SMABORT; + } - ACCEPT_MSG_ATN(port); + ACCEPT_MSG_ATN(port); } - - /*--------------------------------------------------------------------- * * Function: Phase Check FIFO @@ -4653,74 +4396,67 @@ static void FPT_phaseIllegal(unsigned long port, unsigned char p_card) static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card) { - unsigned long xfercnt; - struct sccb * currSCCB; - - currSCCB = FPT_BL_Card[p_card].currentSCCB; - - if (currSCCB->Sccb_scsistat == DATA_IN_ST) - { - - while((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) && - (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY)) {} - - - if (!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) - { - currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt; + unsigned long xfercnt; + struct sccb *currSCCB; - currSCCB->Sccb_XferCnt = 0; - - if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && - (currSCCB->HostStatus == SCCB_COMPLETE)) - { - currSCCB->HostStatus = SCCB_PARITY_ERR; - WRW_HARPOON((port+hp_intstat), PARITY); - } - - FPT_hostDataXferAbort(port,p_card,currSCCB); + currSCCB = FPT_BL_Card[p_card].currentSCCB; - FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]); + if (currSCCB->Sccb_scsistat == DATA_IN_ST) { - while((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) && - (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY)) {} + while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) && + (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) { + } - } - } /*End Data In specific code. */ + if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) { + currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt; + currSCCB->Sccb_XferCnt = 0; + if ((RDW_HARPOON((port + hp_intstat)) & PARITY) && + (currSCCB->HostStatus == SCCB_COMPLETE)) { + currSCCB->HostStatus = SCCB_PARITY_ERR; + WRW_HARPOON((port + hp_intstat), PARITY); + } - GET_XFER_CNT(port,xfercnt); + FPT_hostDataXferAbort(port, p_card, currSCCB); + FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]); - WR_HARPOON(port+hp_xfercnt_0, 0x00); + while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) + && (RD_HARPOON(port + hp_ext_status) & + BM_CMD_BUSY)) { + } + } + } - WR_HARPOON(port+hp_portctrl_0, 0x00); + /*End Data In specific code. */ + GET_XFER_CNT(port, xfercnt); - currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt); + WR_HARPOON(port + hp_xfercnt_0, 0x00); - currSCCB->Sccb_XferCnt = xfercnt; + WR_HARPOON(port + hp_portctrl_0, 0x00); - if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && - (currSCCB->HostStatus == SCCB_COMPLETE)) { + currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt); - currSCCB->HostStatus = SCCB_PARITY_ERR; - WRW_HARPOON((port+hp_intstat), PARITY); - } + currSCCB->Sccb_XferCnt = xfercnt; + if ((RDW_HARPOON((port + hp_intstat)) & PARITY) && + (currSCCB->HostStatus == SCCB_COMPLETE)) { - FPT_hostDataXferAbort(port,p_card,currSCCB); + currSCCB->HostStatus = SCCB_PARITY_ERR; + WRW_HARPOON((port + hp_intstat), PARITY); + } + FPT_hostDataXferAbort(port, p_card, currSCCB); - WR_HARPOON(port+hp_fifowrite, 0x00); - WR_HARPOON(port+hp_fiforead, 0x00); - WR_HARPOON(port+hp_xferstat, 0x00); + WR_HARPOON(port + hp_fifowrite, 0x00); + WR_HARPOON(port + hp_fiforead, 0x00); + WR_HARPOON(port + hp_xferstat, 0x00); - WRW_HARPOON((port+hp_intstat), XFER_CNT_0); + WRW_HARPOON((port + hp_intstat), XFER_CNT_0); } - /*--------------------------------------------------------------------- * * Function: Phase Bus Free @@ -4731,94 +4467,92 @@ static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card) *---------------------------------------------------------------------*/ static void FPT_phaseBusFree(unsigned long port, unsigned char p_card) { - struct sccb * currSCCB; - - currSCCB = FPT_BL_Card[p_card].currentSCCB; + struct sccb *currSCCB; - if (currSCCB != NULL) - { + currSCCB = FPT_BL_Card[p_card].currentSCCB; - DISABLE_AUTO(port); + if (currSCCB != NULL) { + DISABLE_AUTO(port); - if (currSCCB->OperationCode == RESET_COMMAND) - { + if (currSCCB->OperationCode == RESET_COMMAND) { - if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0; + if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarLUNBusy[currSCCB->Lun] = 0; else - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0; - - FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card); - - FPT_queueSearchSelect(&FPT_BL_Card[p_card],p_card); - - } - - else if(currSCCB->Sccb_scsistat == SELECT_SN_ST) - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= - (unsigned char)SYNC_SUPPORTED; - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK; - } - - else if(currSCCB->Sccb_scsistat == SELECT_WN_ST) - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus = - (FPT_sccbMgrTbl[p_card][currSCCB->TargID]. - TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED; - - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI; - } - - else if(currSCCB->Sccb_scsistat == SELECT_Q_ST) - { - /* Make sure this is not a phony BUS_FREE. If we were - reselected or if BUSY is NOT on then this is a - valid BUS FREE. SRR Wednesday, 5/10/1995. */ - - if ((!(RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) || - (RDW_HARPOON((port+hp_intstat)) & RSEL)) - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_TAG_Q_MASK; - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= TAG_Q_REJECT; - } - - else - { - return; - } - } - - else - { - - currSCCB->Sccb_scsistat = BUS_FREE_ST; - - if (!currSCCB->HostStatus) - { - currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; - } - - if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0; - else - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0; + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarLUNBusy[0] = 0; + + FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, + p_card); + + FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card); + + } + + else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) { + FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= + (unsigned char)SYNC_SUPPORTED; + FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= + ~EE_SYNC_MASK; + } + + else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) { + FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus = + (FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED; + + FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= + ~EE_WIDE_SCSI; + } + + else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) { + /* Make sure this is not a phony BUS_FREE. If we were + reselected or if BUSY is NOT on then this is a + valid BUS FREE. SRR Wednesday, 5/10/1995. */ + + if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) || + (RDW_HARPOON((port + hp_intstat)) & RSEL)) { + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus &= ~TAR_TAG_Q_MASK; + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus |= TAG_Q_REJECT; + } + + else { + return; + } + } - FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card); - return; - } + else { + currSCCB->Sccb_scsistat = BUS_FREE_ST; - FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; + if (!currSCCB->HostStatus) { + currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; + } - } /*end if !=null */ -} + if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarLUNBusy[currSCCB->Lun] = 0; + else + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarLUNBusy[0] = 0; + FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, + p_card); + return; + } + FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; + } /*end if !=null */ +} /*--------------------------------------------------------------------- * @@ -4829,101 +4563,99 @@ static void FPT_phaseBusFree(unsigned long port, unsigned char p_card) *---------------------------------------------------------------------*/ static void FPT_autoLoadDefaultMap(unsigned long p_port) { - unsigned long map_addr; - - ARAM_ACCESS(p_port); - map_addr = p_port + hp_aramBase; - - WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0xC0)); /*ID MESSAGE */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0x20)); /*SIMPLE TAG QUEUEING MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0x00)); /*TAG ID MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 0 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 1 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 2 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 3 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 4 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 5 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 6 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 7 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 8 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 9 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 10 */ - map_addr +=2; - WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 11 */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPE_OP+ADATA_OUT+ DINT)); /*JUMP IF DATA OUT */ - map_addr +=2; - WRW_HARPOON(map_addr, (TCB_OP+FIFO_0+ DI)); /*JUMP IF NO DATA IN FIFO */ - map_addr +=2; /*This means AYNC DATA IN */ - WRW_HARPOON(map_addr, (SSI_OP+ SSI_IDO_STRT)); /*STOP AND INTERRUPT */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPE_OP+ADATA_IN+DINT)); /*JUMP IF NOT DATA IN PHZ */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+ ST)); /*IF NOT MSG IN CHECK 4 DATA IN */ - map_addr +=2; - WRW_HARPOON(map_addr, (CRD_OP+SDATA+ 0x02)); /*SAVE DATA PTR MSG? */ - map_addr +=2; - WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+ DC)); /*GO CHECK FOR DISCONNECT MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_AR1)); /*SAVE DATA PTRS MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+ ST)); /*IF NOT MSG IN CHECK DATA IN */ - map_addr +=2; - WRW_HARPOON(map_addr, (CRD_OP+SDATA+ 0x04)); /*DISCONNECT MSG? */ - map_addr +=2; - WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+ UNKNWN));/*UKNKNOWN MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_BUCKET));/*XFER DISCONNECT MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_ITAR_DISC));/*STOP AND INTERRUPT */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPN_OP+ASTATUS+ UNKNWN));/*JUMP IF NOT STATUS PHZ. */ - map_addr +=2; - WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_AR0)); /*GET STATUS BYTE */ - map_addr +=2; - WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+ CC)); /*ERROR IF NOT MSG IN PHZ */ - map_addr +=2; - WRW_HARPOON(map_addr, (CRD_OP+SDATA+ 0x00)); /*CHECK FOR CMD COMPLETE MSG. */ - map_addr +=2; - WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+ CC)); /*ERROR IF NOT CMD COMPLETE MSG. */ - map_addr +=2; - WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_BUCKET));/*GET CMD COMPLETE MSG */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_ICMD_COMP));/*END OF COMMAND */ - map_addr +=2; - - WRW_HARPOON(map_addr, (SSI_OP+ SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_ITICKLE)); /*BIOS Tickled the Mgr */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */ - map_addr +=2; /* DIDN'T GET ONE */ - WRW_HARPOON(map_addr, (CRR_OP+AR3+ S_IDREG)); /* comp SCSI SEL ID & AR3*/ - map_addr +=2; - WRW_HARPOON(map_addr, (BRH_OP+EQUAL+ 0x00)); /*SEL ID OK then Conti. */ - map_addr +=2; - WRW_HARPOON(map_addr, (SSI_OP+ SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */ - - - - SGRAM_ACCESS(p_port); + unsigned long map_addr; + + ARAM_ACCESS(p_port); + map_addr = p_port + hp_aramBase; + + WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0)); /*ID MESSAGE */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20)); /*SIMPLE TAG QUEUEING MSG */ + map_addr += 2; + WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00)); /*TAG ID MSG */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 0 */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 1 */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 2 */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 3 */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 4 */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 5 */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 6 */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 7 */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 8 */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 9 */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 10 */ + map_addr += 2; + WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 11 */ + map_addr += 2; + WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT)); /*JUMP IF DATA OUT */ + map_addr += 2; + WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI)); /*JUMP IF NO DATA IN FIFO */ + map_addr += 2; /*This means AYNC DATA IN */ + WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT)); /*STOP AND INTERRUPT */ + map_addr += 2; + WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT)); /*JUMP IF NOT DATA IN PHZ */ + map_addr += 2; + WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK 4 DATA IN */ + map_addr += 2; + WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02)); /*SAVE DATA PTR MSG? */ + map_addr += 2; + WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC)); /*GO CHECK FOR DISCONNECT MSG */ + map_addr += 2; + WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1)); /*SAVE DATA PTRS MSG */ + map_addr += 2; + WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK DATA IN */ + map_addr += 2; + WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04)); /*DISCONNECT MSG? */ + map_addr += 2; + WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN)); /*UKNKNOWN MSG */ + map_addr += 2; + WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*XFER DISCONNECT MSG */ + map_addr += 2; + WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC)); /*STOP AND INTERRUPT */ + map_addr += 2; + WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN)); /*JUMP IF NOT STATUS PHZ. */ + map_addr += 2; + WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0)); /*GET STATUS BYTE */ + map_addr += 2; + WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC)); /*ERROR IF NOT MSG IN PHZ */ + map_addr += 2; + WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00)); /*CHECK FOR CMD COMPLETE MSG. */ + map_addr += 2; + WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC)); /*ERROR IF NOT CMD COMPLETE MSG. */ + map_addr += 2; + WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*GET CMD COMPLETE MSG */ + map_addr += 2; + WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP)); /*END OF COMMAND */ + map_addr += 2; + + WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */ + map_addr += 2; + WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */ + map_addr += 2; + WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE)); /*BIOS Tickled the Mgr */ + map_addr += 2; + WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */ + map_addr += 2; /* DIDN'T GET ONE */ + WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG)); /* comp SCSI SEL ID & AR3 */ + map_addr += 2; + WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00)); /*SEL ID OK then Conti. */ + map_addr += 2; + WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */ + + SGRAM_ACCESS(p_port); } /*--------------------------------------------------------------------- @@ -4937,201 +4669,259 @@ static void FPT_autoLoadDefaultMap(unsigned long p_port) static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card) { - struct sccb * currSCCB; - unsigned char status_byte; - - currSCCB = FPT_BL_Card[p_card].currentSCCB; + struct sccb *currSCCB; + unsigned char status_byte; - status_byte = RD_HARPOON(p_port+hp_gp_reg_0); + currSCCB = FPT_BL_Card[p_card].currentSCCB; - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0; + status_byte = RD_HARPOON(p_port + hp_gp_reg_0); - if (status_byte != SSGOOD) { + FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0; - if (status_byte == SSQ_FULL) { + if (status_byte != SSGOOD) { + if (status_byte == SSQ_FULL) { - if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1; - if(FPT_BL_Card[p_card].discQCount != 0) + if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) { + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarLUNBusy[currSCCB->Lun] = 1; + if (FPT_BL_Card[p_card].discQCount != 0) FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; - } - else - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1; - if(currSCCB->Sccb_tag) - { - if(FPT_BL_Card[p_card].discQCount != 0) - FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; - }else - { - if(FPT_BL_Card[p_card].discQCount != 0) - FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; + FPT_BL_Card[p_card]. + discQ_Tbl[FPT_sccbMgrTbl[p_card] + [currSCCB->TargID]. + LunDiscQ_Idx[currSCCB->Lun]] = + NULL; + } else { + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarLUNBusy[0] = 1; + if (currSCCB->Sccb_tag) { + if (FPT_BL_Card[p_card].discQCount != 0) + FPT_BL_Card[p_card]. + discQCount--; + FPT_BL_Card[p_card].discQ_Tbl[currSCCB-> + Sccb_tag] + = NULL; + } else { + if (FPT_BL_Card[p_card].discQCount != 0) + FPT_BL_Card[p_card]. + discQCount--; + FPT_BL_Card[p_card]. + discQ_Tbl[FPT_sccbMgrTbl[p_card] + [currSCCB->TargID]. + LunDiscQ_Idx[0]] = NULL; } } - currSCCB->Sccb_MGRFlags |= F_STATUSLOADED; + currSCCB->Sccb_MGRFlags |= F_STATUSLOADED; - FPT_queueSelectFail(&FPT_BL_Card[p_card],p_card); + FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card); - return; - } + return; + } - if(currSCCB->Sccb_scsistat == SELECT_SN_ST) - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= - (unsigned char)SYNC_SUPPORTED; + if (currSCCB->Sccb_scsistat == SELECT_SN_ST) { + FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= + (unsigned char)SYNC_SUPPORTED; - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK; - FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; + FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= + ~EE_SYNC_MASK; + FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; - if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1; - if(FPT_BL_Card[p_card].discQCount != 0) + if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) { + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarLUNBusy[currSCCB->Lun] = 1; + if (FPT_BL_Card[p_card].discQCount != 0) FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; - } - else - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1; - if(currSCCB->Sccb_tag) - { - if(FPT_BL_Card[p_card].discQCount != 0) - FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; - }else - { - if(FPT_BL_Card[p_card].discQCount != 0) - FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; + FPT_BL_Card[p_card]. + discQ_Tbl[FPT_sccbMgrTbl[p_card] + [currSCCB->TargID]. + LunDiscQ_Idx[currSCCB->Lun]] = + NULL; + } else { + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarLUNBusy[0] = 1; + if (currSCCB->Sccb_tag) { + if (FPT_BL_Card[p_card].discQCount != 0) + FPT_BL_Card[p_card]. + discQCount--; + FPT_BL_Card[p_card].discQ_Tbl[currSCCB-> + Sccb_tag] + = NULL; + } else { + if (FPT_BL_Card[p_card].discQCount != 0) + FPT_BL_Card[p_card]. + discQCount--; + FPT_BL_Card[p_card]. + discQ_Tbl[FPT_sccbMgrTbl[p_card] + [currSCCB->TargID]. + LunDiscQ_Idx[0]] = NULL; } } - return; + return; - } + } - if(currSCCB->Sccb_scsistat == SELECT_WN_ST) - { + if (currSCCB->Sccb_scsistat == SELECT_WN_ST) { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus = - (FPT_sccbMgrTbl[p_card][currSCCB->TargID]. - TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED; + FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus = + (FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED; - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI; - FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; + FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= + ~EE_WIDE_SCSI; + FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; - if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1; - if(FPT_BL_Card[p_card].discQCount != 0) + if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) { + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarLUNBusy[currSCCB->Lun] = 1; + if (FPT_BL_Card[p_card].discQCount != 0) FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; - } - else - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1; - if(currSCCB->Sccb_tag) - { - if(FPT_BL_Card[p_card].discQCount != 0) - FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; - }else - { - if(FPT_BL_Card[p_card].discQCount != 0) - FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; + FPT_BL_Card[p_card]. + discQ_Tbl[FPT_sccbMgrTbl[p_card] + [currSCCB->TargID]. + LunDiscQ_Idx[currSCCB->Lun]] = + NULL; + } else { + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarLUNBusy[0] = 1; + if (currSCCB->Sccb_tag) { + if (FPT_BL_Card[p_card].discQCount != 0) + FPT_BL_Card[p_card]. + discQCount--; + FPT_BL_Card[p_card].discQ_Tbl[currSCCB-> + Sccb_tag] + = NULL; + } else { + if (FPT_BL_Card[p_card].discQCount != 0) + FPT_BL_Card[p_card]. + discQCount--; + FPT_BL_Card[p_card]. + discQ_Tbl[FPT_sccbMgrTbl[p_card] + [currSCCB->TargID]. + LunDiscQ_Idx[0]] = NULL; } } - return; - - } - - if (status_byte == SSCHECK) - { - if(FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) - { - if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_SYNC_MASK) - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_SYNC_MASK; + return; + + } + + if (status_byte == SSCHECK) { + if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) { + if (FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarEEValue & EE_SYNC_MASK) { + FPT_sccbMgrTbl[p_card][currSCCB-> + TargID]. + TarStatus &= ~TAR_SYNC_MASK; } - if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_WIDE_SCSI) - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_WIDE_MASK; + if (FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarEEValue & EE_WIDE_SCSI) { + FPT_sccbMgrTbl[p_card][currSCCB-> + TargID]. + TarStatus &= ~TAR_WIDE_MASK; } } } - if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) { - - currSCCB->SccbStatus = SCCB_ERROR; - currSCCB->TargetStatus = status_byte; - - if (status_byte == SSCHECK) { - - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA - = 1; - - - if (currSCCB->RequestSenseLength != NO_AUTO_REQUEST_SENSE) { - - if (currSCCB->RequestSenseLength == 0) - currSCCB->RequestSenseLength = 14; - - FPT_ssenss(&FPT_BL_Card[p_card]); - FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; - - if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1; - if(FPT_BL_Card[p_card].discQCount != 0) - FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; - } - else - { - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1; - if(currSCCB->Sccb_tag) - { - if(FPT_BL_Card[p_card].discQCount != 0) - FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; - }else - { - if(FPT_BL_Card[p_card].discQCount != 0) - FPT_BL_Card[p_card].discQCount--; - FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; + if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) { + + currSCCB->SccbStatus = SCCB_ERROR; + currSCCB->TargetStatus = status_byte; + + if (status_byte == SSCHECK) { + + FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarLUN_CA = 1; + + if (currSCCB->RequestSenseLength != + NO_AUTO_REQUEST_SENSE) { + + if (currSCCB->RequestSenseLength == 0) + currSCCB->RequestSenseLength = + 14; + + FPT_ssenss(&FPT_BL_Card[p_card]); + FPT_BL_Card[p_card].globalFlags |= + F_NEW_SCCB_CMD; + + if (((FPT_BL_Card[p_card]. + globalFlags & F_CONLUN_IO) + && + ((FPT_sccbMgrTbl[p_card] + [currSCCB->TargID]. + TarStatus & TAR_TAG_Q_MASK) != + TAG_Q_TRYING))) { + FPT_sccbMgrTbl[p_card] + [currSCCB->TargID]. + TarLUNBusy[currSCCB->Lun] = + 1; + if (FPT_BL_Card[p_card]. + discQCount != 0) + FPT_BL_Card[p_card]. + discQCount--; + FPT_BL_Card[p_card]. + discQ_Tbl[FPT_sccbMgrTbl + [p_card] + [currSCCB-> + TargID]. + LunDiscQ_Idx + [currSCCB->Lun]] = + NULL; + } else { + FPT_sccbMgrTbl[p_card] + [currSCCB->TargID]. + TarLUNBusy[0] = 1; + if (currSCCB->Sccb_tag) { + if (FPT_BL_Card[p_card]. + discQCount != 0) + FPT_BL_Card + [p_card]. + discQCount--; + FPT_BL_Card[p_card]. + discQ_Tbl[currSCCB-> + Sccb_tag] + = NULL; + } else { + if (FPT_BL_Card[p_card]. + discQCount != 0) + FPT_BL_Card + [p_card]. + discQCount--; + FPT_BL_Card[p_card]. + discQ_Tbl + [FPT_sccbMgrTbl + [p_card][currSCCB-> + TargID]. + LunDiscQ_Idx[0]] = + NULL; } } - return; - } - } - } - } - + return; + } + } + } + } - if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0; + if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB-> + Lun] = 0; else - FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0; - + FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0; - FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card); + FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card); } #define SHORT_WAIT 0x0000000F #define LONG_WAIT 0x0000FFFFL - /*--------------------------------------------------------------------- * * Function: Data Transfer Processor @@ -5150,37 +4940,33 @@ static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_dataXferProcessor(unsigned long port, struct sccb_card * pCurrCard) +static void FPT_dataXferProcessor(unsigned long port, + struct sccb_card *pCurrCard) { - struct sccb * currSCCB; + struct sccb *currSCCB; - currSCCB = pCurrCard->currentSCCB; + currSCCB = pCurrCard->currentSCCB; - if (currSCCB->Sccb_XferState & F_SG_XFER) - { - if (pCurrCard->globalFlags & F_HOST_XFER_ACT) + if (currSCCB->Sccb_XferState & F_SG_XFER) { + if (pCurrCard->globalFlags & F_HOST_XFER_ACT) + { + currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT; + currSCCB->Sccb_SGoffset = 0x00; + } + pCurrCard->globalFlags |= F_HOST_XFER_ACT; - { - currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT; - currSCCB->Sccb_SGoffset = 0x00; - } + FPT_busMstrSGDataXferStart(port, currSCCB); + } + + else { + if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) { pCurrCard->globalFlags |= F_HOST_XFER_ACT; - - FPT_busMstrSGDataXferStart(port, currSCCB); - } - else - { - if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) - { - pCurrCard->globalFlags |= F_HOST_XFER_ACT; - - FPT_busMstrDataXferStart(port, currSCCB); - } - } + FPT_busMstrDataXferStart(port, currSCCB); + } + } } - /*--------------------------------------------------------------------- * * Function: BusMaster Scatter Gather Data Transfer Start @@ -5188,104 +4974,101 @@ static void FPT_dataXferProcessor(unsigned long port, struct sccb_card * pCurrCa * Description: * *---------------------------------------------------------------------*/ -static void FPT_busMstrSGDataXferStart(unsigned long p_port, struct sccb * pcurrSCCB) +static void FPT_busMstrSGDataXferStart(unsigned long p_port, + struct sccb *pcurrSCCB) { - unsigned long count,addr,tmpSGCnt; - unsigned int sg_index; - unsigned char sg_count, i; - unsigned long reg_offset; - - - if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { - - count = ((unsigned long) HOST_RD_CMD)<<24; - } - - else { - count = ((unsigned long) HOST_WRT_CMD)<<24; - } - - sg_count = 0; - tmpSGCnt = 0; - sg_index = pcurrSCCB->Sccb_sgseg; - reg_offset = hp_aramBase; - - - i = (unsigned char) (RD_HARPOON(p_port+hp_page_ctrl) & ~(SGRAM_ARAM|SCATTER_EN)); + unsigned long count, addr, tmpSGCnt; + unsigned int sg_index; + unsigned char sg_count, i; + unsigned long reg_offset; + if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { - WR_HARPOON(p_port+hp_page_ctrl, i); - - while ((sg_count < (unsigned char)SG_BUF_CNT) && - ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) < pcurrSCCB->DataLength) ) { + count = ((unsigned long)HOST_RD_CMD) << 24; + } - tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer)+ - (sg_index * 2)); + else { + count = ((unsigned long)HOST_WRT_CMD) << 24; + } - count |= *(((unsigned long *)pcurrSCCB->DataPointer)+ - (sg_index * 2)); + sg_count = 0; + tmpSGCnt = 0; + sg_index = pcurrSCCB->Sccb_sgseg; + reg_offset = hp_aramBase; - addr = *(((unsigned long *)pcurrSCCB->DataPointer)+ - ((sg_index * 2) + 1)); + i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) & + ~(SGRAM_ARAM | SCATTER_EN)); + WR_HARPOON(p_port + hp_page_ctrl, i); - if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) { + while ((sg_count < (unsigned char)SG_BUF_CNT) && + ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) < + pcurrSCCB->DataLength)) { - addr += ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset); - count = (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset; + tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer) + + (sg_index * 2)); - tmpSGCnt = count & 0x00FFFFFFL; - } + count |= *(((unsigned long *)pcurrSCCB->DataPointer) + + (sg_index * 2)); - WR_HARP32(p_port,reg_offset,addr); - reg_offset +=4; + addr = *(((unsigned long *)pcurrSCCB->DataPointer) + + ((sg_index * 2) + 1)); - WR_HARP32(p_port,reg_offset,count); - reg_offset +=4; + if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) { - count &= 0xFF000000L; - sg_index++; - sg_count++; + addr += + ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset); + count = + (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset; - } /*End While */ + tmpSGCnt = count & 0x00FFFFFFL; + } - pcurrSCCB->Sccb_XferCnt = tmpSGCnt; + WR_HARP32(p_port, reg_offset, addr); + reg_offset += 4; - WR_HARPOON(p_port+hp_sg_addr,(sg_count<<4)); + WR_HARP32(p_port, reg_offset, count); + reg_offset += 4; - if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { + count &= 0xFF000000L; + sg_index++; + sg_count++; - WR_HARP32(p_port,hp_xfercnt_0,tmpSGCnt); + } /*End While */ + pcurrSCCB->Sccb_XferCnt = tmpSGCnt; - WR_HARPOON(p_port+hp_portctrl_0,(DMA_PORT | SCSI_PORT | SCSI_INBIT)); - WR_HARPOON(p_port+hp_scsisig, S_DATAI_PH); - } + WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4)); - else { + if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { + WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt); - if ((!(RD_HARPOON(p_port+hp_synctarg_0) & NARROW_SCSI)) && - (tmpSGCnt & 0x000000001)) - { + WR_HARPOON(p_port + hp_portctrl_0, + (DMA_PORT | SCSI_PORT | SCSI_INBIT)); + WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH); + } - pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT; - tmpSGCnt--; - } + else { + if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) && + (tmpSGCnt & 0x000000001)) { - WR_HARP32(p_port,hp_xfercnt_0,tmpSGCnt); + pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT; + tmpSGCnt--; + } - WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT | DMA_PORT | DMA_RD)); - WR_HARPOON(p_port+hp_scsisig, S_DATAO_PH); - } + WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt); + WR_HARPOON(p_port + hp_portctrl_0, + (SCSI_PORT | DMA_PORT | DMA_RD)); + WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH); + } - WR_HARPOON(p_port+hp_page_ctrl, (unsigned char) (i | SCATTER_EN)); + WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN)); } - /*--------------------------------------------------------------------- * * Function: BusMaster Data Transfer Start @@ -5293,47 +5076,49 @@ static void FPT_busMstrSGDataXferStart(unsigned long p_port, struct sccb * pcurr * Description: * *---------------------------------------------------------------------*/ -static void FPT_busMstrDataXferStart(unsigned long p_port, struct sccb * pcurrSCCB) +static void FPT_busMstrDataXferStart(unsigned long p_port, + struct sccb *pcurrSCCB) { - unsigned long addr,count; + unsigned long addr, count; - if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) { + if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) { - count = pcurrSCCB->Sccb_XferCnt; - - addr = (unsigned long) pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC; - } + count = pcurrSCCB->Sccb_XferCnt; - else { - addr = pcurrSCCB->SensePointer; - count = pcurrSCCB->RequestSenseLength; + addr = + (unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC; + } - } + else { + addr = pcurrSCCB->SensePointer; + count = pcurrSCCB->RequestSenseLength; - HP_SETUP_ADDR_CNT(p_port,addr,count); + } + HP_SETUP_ADDR_CNT(p_port, addr, count); - if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { + if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { - WR_HARPOON(p_port+hp_portctrl_0,(DMA_PORT | SCSI_PORT | SCSI_INBIT)); - WR_HARPOON(p_port+hp_scsisig, S_DATAI_PH); + WR_HARPOON(p_port + hp_portctrl_0, + (DMA_PORT | SCSI_PORT | SCSI_INBIT)); + WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH); - WR_HARPOON(p_port+hp_xfer_cmd, - (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT)); - } + WR_HARPOON(p_port + hp_xfer_cmd, + (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT)); + } - else { + else { - WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT | DMA_PORT | DMA_RD)); - WR_HARPOON(p_port+hp_scsisig, S_DATAO_PH); + WR_HARPOON(p_port + hp_portctrl_0, + (SCSI_PORT | DMA_PORT | DMA_RD)); + WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH); - WR_HARPOON(p_port+hp_xfer_cmd, - (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT)); + WR_HARPOON(p_port + hp_xfer_cmd, + (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT)); - } + } } - /*--------------------------------------------------------------------- * * Function: BusMaster Timeout Handler @@ -5348,35 +5133,36 @@ static void FPT_busMstrDataXferStart(unsigned long p_port, struct sccb * pcurrSC *---------------------------------------------------------------------*/ static unsigned char FPT_busMstrTimeOut(unsigned long p_port) { - unsigned long timeout; + unsigned long timeout; - timeout = LONG_WAIT; + timeout = LONG_WAIT; - WR_HARPOON(p_port+hp_sys_ctrl, HALT_MACH); + WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH); - while ((!(RD_HARPOON(p_port+hp_ext_status) & CMD_ABORTED)) && timeout--) {} + while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED)) + && timeout--) { + } - - - if (RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) { - WR_HARPOON(p_port+hp_sys_ctrl, HARD_ABORT); + if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) { + WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT); - timeout = LONG_WAIT; - while ((RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {} - } + timeout = LONG_WAIT; + while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) + && timeout--) { + } + } - RD_HARPOON(p_port+hp_int_status); /*Clear command complete */ + RD_HARPOON(p_port + hp_int_status); /*Clear command complete */ - if (RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) { - return(1); - } + if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) { + return (1); + } - else { - return(0); - } + else { + return (0); + } } - /*--------------------------------------------------------------------- * * Function: Host Data Transfer Abort @@ -5384,256 +5170,282 @@ static unsigned char FPT_busMstrTimeOut(unsigned long p_port) * Description: Abort any in progress transfer. * *---------------------------------------------------------------------*/ -static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, struct sccb * pCurrSCCB) +static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, + struct sccb *pCurrSCCB) { - unsigned long timeout; - unsigned long remain_cnt; - unsigned int sg_ptr; - - FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT; - - if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) { - + unsigned long timeout; + unsigned long remain_cnt; + unsigned int sg_ptr; - if (!(RD_HARPOON(port+hp_int_status) & INT_CMD_COMPL)) { + FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT; - WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) | FLUSH_XFER_CNTR)); - timeout = LONG_WAIT; + if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) { - while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {} + if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) { - WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) & ~FLUSH_XFER_CNTR)); + WR_HARPOON(port + hp_bm_ctrl, + (RD_HARPOON(port + hp_bm_ctrl) | + FLUSH_XFER_CNTR)); + timeout = LONG_WAIT; - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { - - if (FPT_busMstrTimeOut(port)) { - - if (pCurrSCCB->HostStatus == 0x00) - - pCurrSCCB->HostStatus = SCCB_BM_ERR; - - } - - if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) - - if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) - - if (pCurrSCCB->HostStatus == 0x00) - - { - pCurrSCCB->HostStatus = SCCB_BM_ERR; - } - } - } - } - - else if (pCurrSCCB->Sccb_XferCnt) { - - if (pCurrSCCB->Sccb_XferState & F_SG_XFER) { - - - WR_HARPOON(port+hp_page_ctrl, (RD_HARPOON(port+hp_page_ctrl) & - ~SCATTER_EN)); + while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) + && timeout--) { + } - WR_HARPOON(port+hp_sg_addr,0x00); + WR_HARPOON(port + hp_bm_ctrl, + (RD_HARPOON(port + hp_bm_ctrl) & + ~FLUSH_XFER_CNTR)); - sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT; + if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) { - if (sg_ptr > (unsigned int)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE)) { + if (FPT_busMstrTimeOut(port)) { - sg_ptr = (unsigned int)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE); - } + if (pCurrSCCB->HostStatus == 0x00) - remain_cnt = pCurrSCCB->Sccb_XferCnt; + pCurrSCCB->HostStatus = + SCCB_BM_ERR; - while (remain_cnt < 0x01000000L) { + } - sg_ptr--; + if (RD_HARPOON(port + hp_int_status) & + INT_EXT_STATUS) - if (remain_cnt > (unsigned long)(*(((unsigned long *)pCurrSCCB-> - DataPointer) + (sg_ptr * 2)))) { + if (RD_HARPOON(port + hp_ext_status) & + BAD_EXT_STATUS) - remain_cnt -= (unsigned long)(*(((unsigned long *)pCurrSCCB-> - DataPointer) + (sg_ptr * 2))); - } + if (pCurrSCCB->HostStatus == + 0x00) + { + pCurrSCCB->HostStatus = + SCCB_BM_ERR; + } + } + } + } - else { + else if (pCurrSCCB->Sccb_XferCnt) { - break; - } - } + if (pCurrSCCB->Sccb_XferState & F_SG_XFER) { + WR_HARPOON(port + hp_page_ctrl, + (RD_HARPOON(port + hp_page_ctrl) & + ~SCATTER_EN)); + WR_HARPOON(port + hp_sg_addr, 0x00); - if (remain_cnt < 0x01000000L) { + sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT; + if (sg_ptr > + (unsigned int)(pCurrSCCB->DataLength / + SG_ELEMENT_SIZE)) { - pCurrSCCB->Sccb_SGoffset = remain_cnt; + sg_ptr = + (unsigned int)(pCurrSCCB->DataLength / + SG_ELEMENT_SIZE); + } - pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr; + remain_cnt = pCurrSCCB->Sccb_XferCnt; + while (remain_cnt < 0x01000000L) { - if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) == pCurrSCCB->DataLength - && (remain_cnt == 0)) + sg_ptr--; - pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; - } + if (remain_cnt > + (unsigned + long)(*(((unsigned long *)pCurrSCCB-> + DataPointer) + (sg_ptr * 2)))) { - else { + remain_cnt -= + (unsigned + long)(*(((unsigned long *) + pCurrSCCB->DataPointer) + + (sg_ptr * 2))); + } + else { - if (pCurrSCCB->HostStatus == 0x00) { + break; + } + } - pCurrSCCB->HostStatus = SCCB_GROSS_FW_ERR; - } - } - } + if (remain_cnt < 0x01000000L) { + pCurrSCCB->Sccb_SGoffset = remain_cnt; - if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) { + pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr; + if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) == + pCurrSCCB->DataLength && (remain_cnt == 0)) - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { + pCurrSCCB->Sccb_XferState |= + F_ALL_XFERRED; + } - FPT_busMstrTimeOut(port); - } + else { - else { + if (pCurrSCCB->HostStatus == 0x00) { - if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) { + pCurrSCCB->HostStatus = + SCCB_GROSS_FW_ERR; + } + } + } - if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) { + if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) { - if (pCurrSCCB->HostStatus == 0x00) { + if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) { - pCurrSCCB->HostStatus = SCCB_BM_ERR; - } - } - } + FPT_busMstrTimeOut(port); + } - } - } + else { - else { + if (RD_HARPOON(port + hp_int_status) & + INT_EXT_STATUS) { + if (RD_HARPOON(port + hp_ext_status) & + BAD_EXT_STATUS) { - if ((RD_HARPOON(port+hp_fifo_cnt)) >= BM_THRESHOLD) { + if (pCurrSCCB->HostStatus == + 0x00) { - timeout = SHORT_WAIT; + pCurrSCCB->HostStatus = + SCCB_BM_ERR; + } + } + } - while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && - ((RD_HARPOON(port+hp_fifo_cnt)) >= BM_THRESHOLD) && - timeout--) {} - } + } + } - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { + else { - WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) | - FLUSH_XFER_CNTR)); + if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) { - timeout = LONG_WAIT; + timeout = SHORT_WAIT; - while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && - timeout--) {} + while ((RD_HARPOON(port + hp_ext_status) & + BM_CMD_BUSY) + && ((RD_HARPOON(port + hp_fifo_cnt)) >= + BM_THRESHOLD) && timeout--) { + } + } - WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) & - ~FLUSH_XFER_CNTR)); + if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) { + WR_HARPOON(port + hp_bm_ctrl, + (RD_HARPOON(port + hp_bm_ctrl) | + FLUSH_XFER_CNTR)); - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { + timeout = LONG_WAIT; - if (pCurrSCCB->HostStatus == 0x00) { + while ((RD_HARPOON(port + hp_ext_status) & + BM_CMD_BUSY) && timeout--) { + } - pCurrSCCB->HostStatus = SCCB_BM_ERR; - } + WR_HARPOON(port + hp_bm_ctrl, + (RD_HARPOON(port + hp_bm_ctrl) & + ~FLUSH_XFER_CNTR)); - FPT_busMstrTimeOut(port); - } - } + if (RD_HARPOON(port + hp_ext_status) & + BM_CMD_BUSY) { - if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) { + if (pCurrSCCB->HostStatus == 0x00) { - if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) { + pCurrSCCB->HostStatus = + SCCB_BM_ERR; + } - if (pCurrSCCB->HostStatus == 0x00) { + FPT_busMstrTimeOut(port); + } + } - pCurrSCCB->HostStatus = SCCB_BM_ERR; - } - } - } - } + if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) { - } + if (RD_HARPOON(port + hp_ext_status) & + BAD_EXT_STATUS) { - else { + if (pCurrSCCB->HostStatus == 0x00) { + pCurrSCCB->HostStatus = + SCCB_BM_ERR; + } + } + } + } - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { + } - timeout = LONG_WAIT; + else { - while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {} + if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) { - if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { + timeout = LONG_WAIT; - if (pCurrSCCB->HostStatus == 0x00) { + while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) + && timeout--) { + } - pCurrSCCB->HostStatus = SCCB_BM_ERR; - } + if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) { - FPT_busMstrTimeOut(port); - } - } + if (pCurrSCCB->HostStatus == 0x00) { + pCurrSCCB->HostStatus = SCCB_BM_ERR; + } - if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) { + FPT_busMstrTimeOut(port); + } + } - if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) { + if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) { - if (pCurrSCCB->HostStatus == 0x00) { + if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) { - pCurrSCCB->HostStatus = SCCB_BM_ERR; - } - } + if (pCurrSCCB->HostStatus == 0x00) { - } + pCurrSCCB->HostStatus = SCCB_BM_ERR; + } + } - if (pCurrSCCB->Sccb_XferState & F_SG_XFER) { + } - WR_HARPOON(port+hp_page_ctrl, (RD_HARPOON(port+hp_page_ctrl) & - ~SCATTER_EN)); + if (pCurrSCCB->Sccb_XferState & F_SG_XFER) { - WR_HARPOON(port+hp_sg_addr,0x00); + WR_HARPOON(port + hp_page_ctrl, + (RD_HARPOON(port + hp_page_ctrl) & + ~SCATTER_EN)); - pCurrSCCB->Sccb_sgseg += SG_BUF_CNT; + WR_HARPOON(port + hp_sg_addr, 0x00); - pCurrSCCB->Sccb_SGoffset = 0x00; + pCurrSCCB->Sccb_sgseg += SG_BUF_CNT; + pCurrSCCB->Sccb_SGoffset = 0x00; - if ((unsigned long)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >= - pCurrSCCB->DataLength) { + if ((unsigned long)(pCurrSCCB->Sccb_sgseg * + SG_ELEMENT_SIZE) >= + pCurrSCCB->DataLength) { - pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; + pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; - pCurrSCCB->Sccb_sgseg = (unsigned short)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE); + pCurrSCCB->Sccb_sgseg = + (unsigned short)(pCurrSCCB->DataLength / + SG_ELEMENT_SIZE); - } - } + } + } - else { + else { - if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE)) + if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE)) - pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; - } - } + pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; + } + } - WR_HARPOON(port+hp_int_mask,(INT_CMD_COMPL | SCSI_INTERRUPT)); + WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); } - - /*--------------------------------------------------------------------- * * Function: Host Data Transfer Restart @@ -5642,47 +5454,47 @@ static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, stru * pointers message. * *---------------------------------------------------------------------*/ -static void FPT_hostDataXferRestart(struct sccb * currSCCB) +static void FPT_hostDataXferRestart(struct sccb *currSCCB) { - unsigned long data_count; - unsigned int sg_index; - unsigned long *sg_ptr; + unsigned long data_count; + unsigned int sg_index; + unsigned long *sg_ptr; - if (currSCCB->Sccb_XferState & F_SG_XFER) { + if (currSCCB->Sccb_XferState & F_SG_XFER) { - currSCCB->Sccb_XferCnt = 0; + currSCCB->Sccb_XferCnt = 0; - sg_index = 0xffff; /*Index by long words into sg list. */ - data_count = 0; /*Running count of SG xfer counts. */ + sg_index = 0xffff; /*Index by long words into sg list. */ + data_count = 0; /*Running count of SG xfer counts. */ - sg_ptr = (unsigned long *)currSCCB->DataPointer; + sg_ptr = (unsigned long *)currSCCB->DataPointer; - while (data_count < currSCCB->Sccb_ATC) { + while (data_count < currSCCB->Sccb_ATC) { - sg_index++; - data_count += *(sg_ptr+(sg_index * 2)); - } + sg_index++; + data_count += *(sg_ptr + (sg_index * 2)); + } - if (data_count == currSCCB->Sccb_ATC) { + if (data_count == currSCCB->Sccb_ATC) { - currSCCB->Sccb_SGoffset = 0; - sg_index++; - } + currSCCB->Sccb_SGoffset = 0; + sg_index++; + } - else { - currSCCB->Sccb_SGoffset = data_count - currSCCB->Sccb_ATC; - } + else { + currSCCB->Sccb_SGoffset = + data_count - currSCCB->Sccb_ATC; + } - currSCCB->Sccb_sgseg = (unsigned short)sg_index; - } + currSCCB->Sccb_sgseg = (unsigned short)sg_index; + } - else { - currSCCB->Sccb_XferCnt = currSCCB->DataLength - currSCCB->Sccb_ATC; - } + else { + currSCCB->Sccb_XferCnt = + currSCCB->DataLength - currSCCB->Sccb_ATC; + } } - - /*--------------------------------------------------------------------- * * Function: FPT_scini @@ -5691,177 +5503,192 @@ static void FPT_hostDataXferRestart(struct sccb * currSCCB) * *---------------------------------------------------------------------*/ -static void FPT_scini(unsigned char p_card, unsigned char p_our_id, unsigned char p_power_up) +static void FPT_scini(unsigned char p_card, unsigned char p_our_id, + unsigned char p_power_up) { - unsigned char loser,assigned_id; - unsigned long p_port; + unsigned char loser, assigned_id; + unsigned long p_port; - unsigned char i,k,ScamFlg ; - struct sccb_card * currCard; - struct nvram_info * pCurrNvRam; + unsigned char i, k, ScamFlg; + struct sccb_card *currCard; + struct nvram_info *pCurrNvRam; - currCard = &FPT_BL_Card[p_card]; - p_port = currCard->ioPort; + currCard = &FPT_BL_Card[p_card]; + p_port = currCard->ioPort; pCurrNvRam = currCard->pNvRamInfo; - - if(pCurrNvRam){ + if (pCurrNvRam) { ScamFlg = pCurrNvRam->niScamConf; i = pCurrNvRam->niSysConf; + } else { + ScamFlg = + (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2); + i = (unsigned + char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2))); } - else{ - ScamFlg = (unsigned char) FPT_utilEERead(p_port, SCAM_CONFIG/2); - i = (unsigned char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG/2))); - } - if(!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */ + if (!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */ return; - FPT_inisci(p_card,p_port, p_our_id); + FPT_inisci(p_card, p_port, p_our_id); - /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW - too slow to return to SCAM selection */ + /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW + too slow to return to SCAM selection */ - /* if (p_power_up) - FPT_Wait1Second(p_port); - else - FPT_Wait(p_port, TO_250ms); */ - - FPT_Wait1Second(p_port); + /* if (p_power_up) + FPT_Wait1Second(p_port); + else + FPT_Wait(p_port, TO_250ms); */ - if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) - { - while (!(FPT_scarb(p_port,INIT_SELTD))) {} + FPT_Wait1Second(p_port); - FPT_scsel(p_port); + if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) { + while (!(FPT_scarb(p_port, INIT_SELTD))) { + } - do { - FPT_scxferc(p_port,SYNC_PTRN); - FPT_scxferc(p_port,DOM_MSTR); - loser = FPT_scsendi(p_port,&FPT_scamInfo[p_our_id].id_string[0]); - } while ( loser == 0xFF ); + FPT_scsel(p_port); - FPT_scbusf(p_port); + do { + FPT_scxferc(p_port, SYNC_PTRN); + FPT_scxferc(p_port, DOM_MSTR); + loser = + FPT_scsendi(p_port, + &FPT_scamInfo[p_our_id].id_string[0]); + } while (loser == 0xFF); - if ((p_power_up) && (!loser)) - { - FPT_sresb(p_port,p_card); - FPT_Wait(p_port, TO_250ms); + FPT_scbusf(p_port); - while (!(FPT_scarb(p_port,INIT_SELTD))) {} + if ((p_power_up) && (!loser)) { + FPT_sresb(p_port, p_card); + FPT_Wait(p_port, TO_250ms); - FPT_scsel(p_port); + while (!(FPT_scarb(p_port, INIT_SELTD))) { + } - do { - FPT_scxferc(p_port, SYNC_PTRN); - FPT_scxferc(p_port, DOM_MSTR); - loser = FPT_scsendi(p_port,&FPT_scamInfo[p_our_id]. - id_string[0]); - } while ( loser == 0xFF ); + FPT_scsel(p_port); - FPT_scbusf(p_port); - } - } + do { + FPT_scxferc(p_port, SYNC_PTRN); + FPT_scxferc(p_port, DOM_MSTR); + loser = + FPT_scsendi(p_port, + &FPT_scamInfo[p_our_id]. + id_string[0]); + } while (loser == 0xFF); - else - { - loser = 0; - } + FPT_scbusf(p_port); + } + } + else { + loser = 0; + } - if (!loser) - { + if (!loser) { + + FPT_scamInfo[p_our_id].state = ID_ASSIGNED; + + if (ScamFlg & SCAM_ENABLED) { + + for (i = 0; i < MAX_SCSI_TAR; i++) { + if ((FPT_scamInfo[i].state == ID_UNASSIGNED) || + (FPT_scamInfo[i].state == ID_UNUSED)) { + if (FPT_scsell(p_port, i)) { + FPT_scamInfo[i].state = LEGACY; + if ((FPT_scamInfo[i]. + id_string[0] != 0xFF) + || (FPT_scamInfo[i]. + id_string[1] != 0xFA)) { + + FPT_scamInfo[i]. + id_string[0] = 0xFF; + FPT_scamInfo[i]. + id_string[1] = 0xFA; + if (pCurrNvRam == NULL) + currCard-> + globalFlags + |= + F_UPDATE_EEPROM; + } + } + } + } - FPT_scamInfo[p_our_id].state = ID_ASSIGNED; + FPT_sresb(p_port, p_card); + FPT_Wait1Second(p_port); + while (!(FPT_scarb(p_port, INIT_SELTD))) { + } + FPT_scsel(p_port); + FPT_scasid(p_card, p_port); + } + } - if (ScamFlg & SCAM_ENABLED) - { + else if ((loser) && (ScamFlg & SCAM_ENABLED)) { + FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0; + assigned_id = 0; + FPT_scwtsel(p_port); - for (i=0; i < MAX_SCSI_TAR; i++) - { - if ((FPT_scamInfo[i].state == ID_UNASSIGNED) || - (FPT_scamInfo[i].state == ID_UNUSED)) - { - if (FPT_scsell(p_port,i)) - { - FPT_scamInfo[i].state = LEGACY; - if ((FPT_scamInfo[i].id_string[0] != 0xFF) || - (FPT_scamInfo[i].id_string[1] != 0xFA)) - { - - FPT_scamInfo[i].id_string[0] = 0xFF; - FPT_scamInfo[i].id_string[1] = 0xFA; - if(pCurrNvRam == NULL) - currCard->globalFlags |= F_UPDATE_EEPROM; - } - } - } - } - - FPT_sresb(p_port,p_card); - FPT_Wait1Second(p_port); - while (!(FPT_scarb(p_port,INIT_SELTD))) {} - FPT_scsel(p_port); - FPT_scasid(p_card, p_port); - } + do { + while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) { + } - } + i = FPT_scxferc(p_port, 0x00); + if (i == ASSIGN_ID) { + if (! + (FPT_scsendi + (p_port, + &FPT_scamInfo[p_our_id].id_string[0]))) { + i = FPT_scxferc(p_port, 0x00); + if (FPT_scvalq(i)) { + k = FPT_scxferc(p_port, 0x00); + + if (FPT_scvalq(k)) { + currCard->ourId = + ((unsigned char)(i + << + 3) + + + (k & + (unsigned char)7)) + & (unsigned char) + 0x3F; + FPT_inisci(p_card, + p_port, + p_our_id); + FPT_scamInfo[currCard-> + ourId]. + state = ID_ASSIGNED; + FPT_scamInfo[currCard-> + ourId]. + id_string[0] + = SLV_TYPE_CODE0; + assigned_id = 1; + } + } + } + } - else if ((loser) && (ScamFlg & SCAM_ENABLED)) - { - FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0; - assigned_id = 0; - FPT_scwtsel(p_port); - - do { - while (FPT_scxferc(p_port,0x00) != SYNC_PTRN) {} - - i = FPT_scxferc(p_port,0x00); - if (i == ASSIGN_ID) - { - if (!(FPT_scsendi(p_port,&FPT_scamInfo[p_our_id].id_string[0]))) - { - i = FPT_scxferc(p_port,0x00); - if (FPT_scvalq(i)) - { - k = FPT_scxferc(p_port,0x00); - - if (FPT_scvalq(k)) - { - currCard->ourId = - ((unsigned char)(i<<3)+(k & (unsigned char)7)) & (unsigned char) 0x3F; - FPT_inisci(p_card, p_port, p_our_id); - FPT_scamInfo[currCard->ourId].state = ID_ASSIGNED; - FPT_scamInfo[currCard->ourId].id_string[0] - = SLV_TYPE_CODE0; - assigned_id = 1; - } - } - } - } - - else if (i == SET_P_FLAG) - { - if (!(FPT_scsendi(p_port, - &FPT_scamInfo[p_our_id].id_string[0]))) - FPT_scamInfo[p_our_id].id_string[0] |= 0x80; - } - }while (!assigned_id); - - while (FPT_scxferc(p_port,0x00) != CFG_CMPLT) {} - } + else if (i == SET_P_FLAG) { + if (!(FPT_scsendi(p_port, + &FPT_scamInfo[p_our_id]. + id_string[0]))) + FPT_scamInfo[p_our_id].id_string[0] |= + 0x80; + } + } while (!assigned_id); - if (ScamFlg & SCAM_ENABLED) - { - FPT_scbusf(p_port); - if (currCard->globalFlags & F_UPDATE_EEPROM) - { - FPT_scsavdi(p_card, p_port); - currCard->globalFlags &= ~F_UPDATE_EEPROM; - } - } + while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) { + } + } + if (ScamFlg & SCAM_ENABLED) { + FPT_scbusf(p_port); + if (currCard->globalFlags & F_UPDATE_EEPROM) { + FPT_scsavdi(p_card, p_port); + currCard->globalFlags &= ~F_UPDATE_EEPROM; + } + } /* for (i=0,k=0; i < MAX_SCSI_TAR; i++) @@ -5878,7 +5705,6 @@ static void FPT_scini(unsigned char p_card, unsigned char p_our_id, unsigned cha */ } - /*--------------------------------------------------------------------- * * Function: FPT_scarb @@ -5889,57 +5715,58 @@ static void FPT_scini(unsigned char p_card, unsigned char p_our_id, unsigned cha static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type) { - if (p_sel_type == INIT_SELTD) - { + if (p_sel_type == INIT_SELTD) { - while (RD_HARPOON(p_port+hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {} - - - if (RD_HARPOON(p_port+hp_scsisig) & SCSI_SEL) - return(0); - - if (RD_HARPOON(p_port+hp_scsidata_0) != 00) - return(0); + while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) { + } - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_BSY)); + if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) + return (0); - if (RD_HARPOON(p_port+hp_scsisig) & SCSI_SEL) { + if (RD_HARPOON(p_port + hp_scsidata_0) != 00) + return (0); - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) & - ~SCSI_BSY)); - return(0); - } + WR_HARPOON(p_port + hp_scsisig, + (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY)); + if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) { - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_SEL)); + WR_HARPOON(p_port + hp_scsisig, + (RD_HARPOON(p_port + hp_scsisig) & + ~SCSI_BSY)); + return (0); + } - if (RD_HARPOON(p_port+hp_scsidata_0) != 00) { + WR_HARPOON(p_port + hp_scsisig, + (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL)); - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) & - ~(SCSI_BSY | SCSI_SEL))); - return(0); - } - } + if (RD_HARPOON(p_port + hp_scsidata_0) != 00) { + WR_HARPOON(p_port + hp_scsisig, + (RD_HARPOON(p_port + hp_scsisig) & + ~(SCSI_BSY | SCSI_SEL))); + return (0); + } + } - WR_HARPOON(p_port+hp_clkctrl_0, (RD_HARPOON(p_port+hp_clkctrl_0) - & ~ACTdeassert)); - WR_HARPOON(p_port+hp_scsireset, SCAM_EN); - WR_HARPOON(p_port+hp_scsidata_0, 0x00); - WR_HARPOON(p_port+hp_scsidata_1, 0x00); - WR_HARPOON(p_port+hp_portctrl_0, SCSI_BUS_EN); + WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0) + & ~ACTdeassert)); + WR_HARPOON(p_port + hp_scsireset, SCAM_EN); + WR_HARPOON(p_port + hp_scsidata_0, 0x00); + WR_HARPOON(p_port + hp_scsidata_1, 0x00); + WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN); - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_MSG)); + WR_HARPOON(p_port + hp_scsisig, + (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG)); - WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) - & ~SCSI_BSY)); + WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig) + & ~SCSI_BSY)); - FPT_Wait(p_port,TO_250ms); + FPT_Wait(p_port, TO_250ms); - return(1); + return (1); } - /*--------------------------------------------------------------------- * * Function: FPT_scbusf @@ -5950,32 +5777,28 @@ static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type) static void FPT_scbusf(unsigned long p_port) { - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)); - + WR_HARPOON(p_port + hp_page_ctrl, + (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE)); - WR_HARPOON(p_port+hp_scsidata_0, 0x00); + WR_HARPOON(p_port + hp_scsidata_0, 0x00); - WR_HARPOON(p_port+hp_portctrl_0, (RD_HARPOON(p_port+hp_portctrl_0) - & ~SCSI_BUS_EN)); + WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0) + & ~SCSI_BUS_EN)); - WR_HARPOON(p_port+hp_scsisig, 0x00); + WR_HARPOON(p_port + hp_scsisig, 0x00); + WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset) + & ~SCAM_EN)); - WR_HARPOON(p_port+hp_scsireset, (RD_HARPOON(p_port+hp_scsireset) - & ~SCAM_EN)); + WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0) + | ACTdeassert)); - WR_HARPOON(p_port+hp_clkctrl_0, (RD_HARPOON(p_port+hp_clkctrl_0) - | ACTdeassert)); + WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL)); - WRW_HARPOON((p_port+hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL)); - - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)); + WR_HARPOON(p_port + hp_page_ctrl, + (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE)); } - - /*--------------------------------------------------------------------- * * Function: FPT_scasid @@ -5986,84 +5809,73 @@ static void FPT_scbusf(unsigned long p_port) static void FPT_scasid(unsigned char p_card, unsigned long p_port) { - unsigned char temp_id_string[ID_STRING_LENGTH]; + unsigned char temp_id_string[ID_STRING_LENGTH]; - unsigned char i,k,scam_id; + unsigned char i, k, scam_id; unsigned char crcBytes[3]; - struct nvram_info * pCurrNvRam; - unsigned short * pCrcBytes; + struct nvram_info *pCurrNvRam; + unsigned short *pCrcBytes; pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo; - i=0; + i = 0; - while (!i) - { + while (!i) { - for (k=0; k < ID_STRING_LENGTH; k++) - { - temp_id_string[k] = (unsigned char) 0x00; - } + for (k = 0; k < ID_STRING_LENGTH; k++) { + temp_id_string[k] = (unsigned char)0x00; + } - FPT_scxferc(p_port,SYNC_PTRN); - FPT_scxferc(p_port,ASSIGN_ID); + FPT_scxferc(p_port, SYNC_PTRN); + FPT_scxferc(p_port, ASSIGN_ID); - if (!(FPT_sciso(p_port,&temp_id_string[0]))) - { - if(pCurrNvRam){ + if (!(FPT_sciso(p_port, &temp_id_string[0]))) { + if (pCurrNvRam) { pCrcBytes = (unsigned short *)&crcBytes[0]; *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]); crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]); temp_id_string[1] = crcBytes[2]; temp_id_string[2] = crcBytes[0]; temp_id_string[3] = crcBytes[1]; - for(k = 4; k < ID_STRING_LENGTH; k++) - temp_id_string[k] = (unsigned char) 0x00; + for (k = 4; k < ID_STRING_LENGTH; k++) + temp_id_string[k] = (unsigned char)0x00; } - i = FPT_scmachid(p_card,temp_id_string); + i = FPT_scmachid(p_card, temp_id_string); - if (i == CLR_PRIORITY) - { - FPT_scxferc(p_port,MISC_CODE); - FPT_scxferc(p_port,CLR_P_FLAG); - i = 0; /*Not the last ID yet. */ - } - - else if (i != NO_ID_AVAIL) - { - if (i < 8 ) - FPT_scxferc(p_port,ID_0_7); - else - FPT_scxferc(p_port,ID_8_F); + if (i == CLR_PRIORITY) { + FPT_scxferc(p_port, MISC_CODE); + FPT_scxferc(p_port, CLR_P_FLAG); + i = 0; /*Not the last ID yet. */ + } - scam_id = (i & (unsigned char) 0x07); + else if (i != NO_ID_AVAIL) { + if (i < 8) + FPT_scxferc(p_port, ID_0_7); + else + FPT_scxferc(p_port, ID_8_F); + scam_id = (i & (unsigned char)0x07); - for (k=1; k < 0x08; k <<= 1) - if (!( k & i )) - scam_id += 0x08; /*Count number of zeros in DB0-3. */ + for (k = 1; k < 0x08; k <<= 1) + if (!(k & i)) + scam_id += 0x08; /*Count number of zeros in DB0-3. */ - FPT_scxferc(p_port,scam_id); + FPT_scxferc(p_port, scam_id); - i = 0; /*Not the last ID yet. */ - } - } + i = 0; /*Not the last ID yet. */ + } + } - else - { - i = 1; - } + else { + i = 1; + } - } /*End while */ + } /*End while */ - FPT_scxferc(p_port,SYNC_PTRN); - FPT_scxferc(p_port,CFG_CMPLT); + FPT_scxferc(p_port, SYNC_PTRN); + FPT_scxferc(p_port, CFG_CMPLT); } - - - - /*--------------------------------------------------------------------- * * Function: FPT_scsel @@ -6075,29 +5887,29 @@ static void FPT_scasid(unsigned char p_card, unsigned long p_port) static void FPT_scsel(unsigned long p_port) { - WR_HARPOON(p_port+hp_scsisig, SCSI_SEL); - FPT_scwiros(p_port, SCSI_MSG); - - WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY)); - + WR_HARPOON(p_port + hp_scsisig, SCSI_SEL); + FPT_scwiros(p_port, SCSI_MSG); - WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); - WR_HARPOON(p_port+hp_scsidata_0, (unsigned char)(RD_HARPOON(p_port+hp_scsidata_0) | - (unsigned char)(BIT(7)+BIT(6)))); + WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY)); + WR_HARPOON(p_port + hp_scsisig, + (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); + WR_HARPOON(p_port + hp_scsidata_0, + (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) | + (unsigned char)(BIT(7) + BIT(6)))); - WR_HARPOON(p_port+hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD)); - FPT_scwiros(p_port, SCSI_SEL); + WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD)); + FPT_scwiros(p_port, SCSI_SEL); - WR_HARPOON(p_port+hp_scsidata_0, (unsigned char)(RD_HARPOON(p_port+hp_scsidata_0) & - ~(unsigned char)BIT(6))); - FPT_scwirod(p_port, BIT(6)); + WR_HARPOON(p_port + hp_scsidata_0, + (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) & + ~(unsigned char)BIT(6))); + FPT_scwirod(p_port, BIT(6)); - WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); + WR_HARPOON(p_port + hp_scsisig, + (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); } - - /*--------------------------------------------------------------------- * * Function: FPT_scxferc @@ -6108,46 +5920,45 @@ static void FPT_scsel(unsigned long p_port) static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data) { - unsigned char curr_data, ret_data; + unsigned char curr_data, ret_data; - curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */ + curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */ - WR_HARPOON(p_port+hp_scsidata_0, curr_data); + WR_HARPOON(p_port + hp_scsidata_0, curr_data); - curr_data &= ~BIT(7); + curr_data &= ~BIT(7); - WR_HARPOON(p_port+hp_scsidata_0, curr_data); + WR_HARPOON(p_port + hp_scsidata_0, curr_data); - FPT_scwirod(p_port,BIT(7)); /*Wait for DB7 to be released. */ - while (!(RD_HARPOON(p_port+hp_scsidata_0) & BIT(5))); + FPT_scwirod(p_port, BIT(7)); /*Wait for DB7 to be released. */ + while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ; - ret_data = (RD_HARPOON(p_port+hp_scsidata_0) & (unsigned char) 0x1F); + ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F); - curr_data |= BIT(6); + curr_data |= BIT(6); - WR_HARPOON(p_port+hp_scsidata_0, curr_data); + WR_HARPOON(p_port + hp_scsidata_0, curr_data); - curr_data &= ~BIT(5); + curr_data &= ~BIT(5); - WR_HARPOON(p_port+hp_scsidata_0, curr_data); + WR_HARPOON(p_port + hp_scsidata_0, curr_data); - FPT_scwirod(p_port,BIT(5)); /*Wait for DB5 to be released. */ + FPT_scwirod(p_port, BIT(5)); /*Wait for DB5 to be released. */ - curr_data &= ~(BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0)); /*Release data bits */ - curr_data |= BIT(7); + curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); /*Release data bits */ + curr_data |= BIT(7); - WR_HARPOON(p_port+hp_scsidata_0, curr_data); + WR_HARPOON(p_port + hp_scsidata_0, curr_data); - curr_data &= ~BIT(6); + curr_data &= ~BIT(6); - WR_HARPOON(p_port+hp_scsidata_0, curr_data); + WR_HARPOON(p_port + hp_scsidata_0, curr_data); - FPT_scwirod(p_port,BIT(6)); /*Wait for DB6 to be released. */ + FPT_scwirod(p_port, BIT(6)); /*Wait for DB6 to be released. */ - return(ret_data); + return (ret_data); } - /*--------------------------------------------------------------------- * * Function: FPT_scsendi @@ -6157,51 +5968,50 @@ static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data) * *---------------------------------------------------------------------*/ -static unsigned char FPT_scsendi(unsigned long p_port, unsigned char p_id_string[]) +static unsigned char FPT_scsendi(unsigned long p_port, + unsigned char p_id_string[]) { - unsigned char ret_data,byte_cnt,bit_cnt,defer; + unsigned char ret_data, byte_cnt, bit_cnt, defer; - defer = 0; + defer = 0; - for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) { + for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) { - for (bit_cnt = 0x80; bit_cnt != 0 ; bit_cnt >>= 1) { + for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) { - if (defer) - ret_data = FPT_scxferc(p_port,00); + if (defer) + ret_data = FPT_scxferc(p_port, 00); - else if (p_id_string[byte_cnt] & bit_cnt) + else if (p_id_string[byte_cnt] & bit_cnt) - ret_data = FPT_scxferc(p_port,02); + ret_data = FPT_scxferc(p_port, 02); - else { + else { - ret_data = FPT_scxferc(p_port,01); - if (ret_data & 02) - defer = 1; - } + ret_data = FPT_scxferc(p_port, 01); + if (ret_data & 02) + defer = 1; + } - if ((ret_data & 0x1C) == 0x10) - return(0x00); /*End of isolation stage, we won! */ + if ((ret_data & 0x1C) == 0x10) + return (0x00); /*End of isolation stage, we won! */ - if (ret_data & 0x1C) - return(0xFF); + if (ret_data & 0x1C) + return (0xFF); - if ((defer) && (!(ret_data & 0x1F))) - return(0x01); /*End of isolation stage, we lost. */ + if ((defer) && (!(ret_data & 0x1F))) + return (0x01); /*End of isolation stage, we lost. */ - } /*bit loop */ + } /*bit loop */ - } /*byte loop */ + } /*byte loop */ - if (defer) - return(0x01); /*We lost */ - else - return(0); /*We WON! Yeeessss! */ + if (defer) + return (0x01); /*We lost */ + else + return (0); /*We WON! Yeeessss! */ } - - /*--------------------------------------------------------------------- * * Function: FPT_sciso @@ -6210,31 +6020,31 @@ static unsigned char FPT_scsendi(unsigned long p_port, unsigned char p_id_string * *---------------------------------------------------------------------*/ -static unsigned char FPT_sciso(unsigned long p_port, unsigned char p_id_string[]) +static unsigned char FPT_sciso(unsigned long p_port, + unsigned char p_id_string[]) { - unsigned char ret_data,the_data,byte_cnt,bit_cnt; + unsigned char ret_data, the_data, byte_cnt, bit_cnt; - the_data = 0; + the_data = 0; - for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) { + for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) { - for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) { + for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) { - ret_data = FPT_scxferc(p_port,0); + ret_data = FPT_scxferc(p_port, 0); - if (ret_data & 0xFC) - return(0xFF); + if (ret_data & 0xFC) + return (0xFF); - else { + else { - the_data <<= 1; - if (ret_data & BIT(1)) { - the_data |= 1; - } - } + the_data <<= 1; + if (ret_data & BIT(1)) { + the_data |= 1; + } + } - if ((ret_data & 0x1F) == 0) - { + if ((ret_data & 0x1F) == 0) { /* if(bit_cnt != 0 || bit_cnt != 8) { @@ -6245,23 +6055,21 @@ static unsigned char FPT_sciso(unsigned long p_port, unsigned char p_id_string[] continue; } */ - if (byte_cnt) - return(0x00); - else - return(0xFF); - } + if (byte_cnt) + return (0x00); + else + return (0xFF); + } - } /*bit loop */ + } /*bit loop */ - p_id_string[byte_cnt] = the_data; + p_id_string[byte_cnt] = the_data; - } /*byte loop */ + } /*byte loop */ - return(0); + return (0); } - - /*--------------------------------------------------------------------- * * Function: FPT_scwirod @@ -6273,24 +6081,22 @@ static unsigned char FPT_sciso(unsigned long p_port, unsigned char p_id_string[] static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit) { - unsigned char i; + unsigned char i; - i = 0; - while ( i < MAX_SCSI_TAR ) { + i = 0; + while (i < MAX_SCSI_TAR) { - if (RD_HARPOON(p_port+hp_scsidata_0) & p_data_bit) + if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit) - i = 0; + i = 0; - else + else - i++; + i++; - } + } } - - /*--------------------------------------------------------------------- * * Function: FPT_scwiros @@ -6302,23 +6108,22 @@ static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit) static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit) { - unsigned char i; + unsigned char i; - i = 0; - while ( i < MAX_SCSI_TAR ) { + i = 0; + while (i < MAX_SCSI_TAR) { - if (RD_HARPOON(p_port+hp_scsisig) & p_data_bit) + if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit) - i = 0; + i = 0; - else + else - i++; + i++; - } + } } - /*--------------------------------------------------------------------- * * Function: FPT_scvalq @@ -6329,21 +6134,20 @@ static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit) static unsigned char FPT_scvalq(unsigned char p_quintet) { - unsigned char count; + unsigned char count; - for (count=1; count < 0x08; count<<=1) { - if (!(p_quintet & count)) - p_quintet -= 0x80; - } + for (count = 1; count < 0x08; count <<= 1) { + if (!(p_quintet & count)) + p_quintet -= 0x80; + } - if (p_quintet & 0x18) - return(0); + if (p_quintet & 0x18) + return (0); - else - return(1); + else + return (1); } - /*--------------------------------------------------------------------- * * Function: FPT_scsell @@ -6356,73 +6160,76 @@ static unsigned char FPT_scvalq(unsigned char p_quintet) static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id) { - unsigned long i; + unsigned long i; - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)); + WR_HARPOON(p_port + hp_page_ctrl, + (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE)); - ARAM_ACCESS(p_port); + ARAM_ACCESS(p_port); - WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) | SCAM_TIMER)); - WR_HARPOON(p_port+hp_seltimeout,TO_4ms); + WR_HARPOON(p_port + hp_addstat, + (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER)); + WR_HARPOON(p_port + hp_seltimeout, TO_4ms); + for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) { + WRW_HARPOON(i, (MPM_OP + ACOMMAND)); + } + WRW_HARPOON(i, (BRH_OP + ALWAYS + NP)); - for (i = p_port+CMD_STRT; i < p_port+CMD_STRT+12; i+=2) { - WRW_HARPOON(i, (MPM_OP+ACOMMAND)); - } - WRW_HARPOON(i, (BRH_OP+ALWAYS+ NP)); - - WRW_HARPOON((p_port+hp_intstat), - (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT)); - - WR_HARPOON(p_port+hp_select_id, targ_id); + WRW_HARPOON((p_port + hp_intstat), + (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT)); - WR_HARPOON(p_port+hp_portctrl_0, SCSI_PORT); - WR_HARPOON(p_port+hp_autostart_3, (SELECT | CMD_ONLY_STRT)); - WR_HARPOON(p_port+hp_scsictrl_0, (SEL_TAR | ENA_RESEL)); + WR_HARPOON(p_port + hp_select_id, targ_id); + WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT); + WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT)); + WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL)); - while (!(RDW_HARPOON((p_port+hp_intstat)) & - (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {} + while (!(RDW_HARPOON((p_port + hp_intstat)) & + (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) { + } - if (RDW_HARPOON((p_port+hp_intstat)) & RESET) - FPT_Wait(p_port, TO_250ms); + if (RDW_HARPOON((p_port + hp_intstat)) & RESET) + FPT_Wait(p_port, TO_250ms); - DISABLE_AUTO(p_port); + DISABLE_AUTO(p_port); - WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) & ~SCAM_TIMER)); - WR_HARPOON(p_port+hp_seltimeout,TO_290ms); + WR_HARPOON(p_port + hp_addstat, + (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER)); + WR_HARPOON(p_port + hp_seltimeout, TO_290ms); - SGRAM_ACCESS(p_port); + SGRAM_ACCESS(p_port); - if (RDW_HARPOON((p_port+hp_intstat)) & (RESET | TIMEOUT) ) { + if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) { - WRW_HARPOON((p_port+hp_intstat), - (RESET | TIMEOUT | SEL | BUS_FREE | PHASE)); + WRW_HARPOON((p_port + hp_intstat), + (RESET | TIMEOUT | SEL | BUS_FREE | PHASE)); - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)); + WR_HARPOON(p_port + hp_page_ctrl, + (RD_HARPOON(p_port + hp_page_ctrl) & + ~G_INT_DISABLE)); - return(0); /*No legacy device */ - } + return (0); /*No legacy device */ + } - else { + else { - while(!(RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE)) { - if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ) - { - WR_HARPOON(p_port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); - ACCEPT_MSG(p_port); - } + while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) { + if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) { + WR_HARPOON(p_port + hp_scsisig, + (SCSI_ACK + S_ILL_PH)); + ACCEPT_MSG(p_port); + } } - WRW_HARPOON((p_port+hp_intstat), CLR_ALL_INT_1); + WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1); - WR_HARPOON(p_port+hp_page_ctrl, - (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)); + WR_HARPOON(p_port + hp_page_ctrl, + (RD_HARPOON(p_port + hp_page_ctrl) & + ~G_INT_DISABLE)); - return(1); /*Found one of them oldies! */ - } + return (1); /*Found one of them oldies! */ + } } /*--------------------------------------------------------------------- @@ -6435,10 +6242,10 @@ static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id) static void FPT_scwtsel(unsigned long p_port) { - while(!(RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) {} + while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) { + } } - /*--------------------------------------------------------------------- * * Function: FPT_inisci @@ -6447,57 +6254,64 @@ static void FPT_scwtsel(unsigned long p_port) * *---------------------------------------------------------------------*/ -static void FPT_inisci(unsigned char p_card, unsigned long p_port, unsigned char p_our_id) +static void FPT_inisci(unsigned char p_card, unsigned long p_port, + unsigned char p_our_id) { - unsigned char i,k,max_id; - unsigned short ee_data; - struct nvram_info * pCurrNvRam; + unsigned char i, k, max_id; + unsigned short ee_data; + struct nvram_info *pCurrNvRam; pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo; - if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD) - max_id = 0x08; + if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD) + max_id = 0x08; - else - max_id = 0x10; + else + max_id = 0x10; - if(pCurrNvRam){ - for(i = 0; i < max_id; i++){ + if (pCurrNvRam) { + for (i = 0; i < max_id; i++) { - for(k = 0; k < 4; k++) - FPT_scamInfo[i].id_string[k] = pCurrNvRam->niScamTbl[i][k]; - for(k = 4; k < ID_STRING_LENGTH; k++) - FPT_scamInfo[i].id_string[k] = (unsigned char) 0x00; + for (k = 0; k < 4; k++) + FPT_scamInfo[i].id_string[k] = + pCurrNvRam->niScamTbl[i][k]; + for (k = 4; k < ID_STRING_LENGTH; k++) + FPT_scamInfo[i].id_string[k] = + (unsigned char)0x00; - if(FPT_scamInfo[i].id_string[0] == 0x00) - FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */ - else - FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */ + if (FPT_scamInfo[i].id_string[0] == 0x00) + FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */ + else + FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */ } - }else { - for (i=0; i < max_id; i++) - { - for (k=0; k < ID_STRING_LENGTH; k+=2) - { - ee_data = FPT_utilEERead(p_port, (unsigned short)((EE_SCAMBASE/2) + - (unsigned short) (i*((unsigned short)ID_STRING_LENGTH/2)) + (unsigned short)(k/2))); - FPT_scamInfo[i].id_string[k] = (unsigned char) ee_data; - ee_data >>= 8; - FPT_scamInfo[i].id_string[k+1] = (unsigned char) ee_data; - } + } else { + for (i = 0; i < max_id; i++) { + for (k = 0; k < ID_STRING_LENGTH; k += 2) { + ee_data = + FPT_utilEERead(p_port, + (unsigned + short)((EE_SCAMBASE / 2) + + (unsigned short)(i * + ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2))); + FPT_scamInfo[i].id_string[k] = + (unsigned char)ee_data; + ee_data >>= 8; + FPT_scamInfo[i].id_string[k + 1] = + (unsigned char)ee_data; + } - if ((FPT_scamInfo[i].id_string[0] == 0x00) || - (FPT_scamInfo[i].id_string[0] == 0xFF)) + if ((FPT_scamInfo[i].id_string[0] == 0x00) || + (FPT_scamInfo[i].id_string[0] == 0xFF)) - FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */ + FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */ - else - FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */ + else + FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */ - } + } } - for(k = 0; k < ID_STRING_LENGTH; k++) + for (k = 0; k < ID_STRING_LENGTH; k++) FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k]; } @@ -6511,127 +6325,114 @@ static void FPT_inisci(unsigned char p_card, unsigned long p_port, unsigned char * *---------------------------------------------------------------------*/ -static unsigned char FPT_scmachid(unsigned char p_card, unsigned char p_id_string[]) +static unsigned char FPT_scmachid(unsigned char p_card, + unsigned char p_id_string[]) { - unsigned char i,k,match; - + unsigned char i, k, match; - for (i=0; i < MAX_SCSI_TAR; i++) { + for (i = 0; i < MAX_SCSI_TAR; i++) { - match = 1; - - for (k=0; k < ID_STRING_LENGTH; k++) - { - if (p_id_string[k] != FPT_scamInfo[i].id_string[k]) - match = 0; - } - - if (match) - { - FPT_scamInfo[i].state = ID_ASSIGNED; - return(i); - } - - } + match = 1; + for (k = 0; k < ID_STRING_LENGTH; k++) { + if (p_id_string[k] != FPT_scamInfo[i].id_string[k]) + match = 0; + } + if (match) { + FPT_scamInfo[i].state = ID_ASSIGNED; + return (i); + } - if (p_id_string[0] & BIT(5)) - i = 8; - else - i = MAX_SCSI_TAR; + } - if (((p_id_string[0] & 0x06) == 0x02) || ((p_id_string[0] & 0x06) == 0x04)) - match = p_id_string[1] & (unsigned char) 0x1F; - else - match = 7; + if (p_id_string[0] & BIT(5)) + i = 8; + else + i = MAX_SCSI_TAR; - while (i > 0) - { - i--; + if (((p_id_string[0] & 0x06) == 0x02) + || ((p_id_string[0] & 0x06) == 0x04)) + match = p_id_string[1] & (unsigned char)0x1F; + else + match = 7; - if (FPT_scamInfo[match].state == ID_UNUSED) - { - for (k=0; k < ID_STRING_LENGTH; k++) - { - FPT_scamInfo[match].id_string[k] = p_id_string[k]; - } + while (i > 0) { + i--; - FPT_scamInfo[match].state = ID_ASSIGNED; + if (FPT_scamInfo[match].state == ID_UNUSED) { + for (k = 0; k < ID_STRING_LENGTH; k++) { + FPT_scamInfo[match].id_string[k] = + p_id_string[k]; + } - if(FPT_BL_Card[p_card].pNvRamInfo == NULL) - FPT_BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM; - return(match); + FPT_scamInfo[match].state = ID_ASSIGNED; - } + if (FPT_BL_Card[p_card].pNvRamInfo == NULL) + FPT_BL_Card[p_card].globalFlags |= + F_UPDATE_EEPROM; + return (match); + } - match--; + match--; - if (match == 0xFF) - { - if (p_id_string[0] & BIT(5)) - match = 7; - else - match = MAX_SCSI_TAR-1; + if (match == 0xFF) { + if (p_id_string[0] & BIT(5)) + match = 7; + else + match = MAX_SCSI_TAR - 1; + } } - } - - - - if (p_id_string[0] & BIT(7)) - { - return(CLR_PRIORITY); - } - - if (p_id_string[0] & BIT(5)) - i = 8; - else - i = MAX_SCSI_TAR; + if (p_id_string[0] & BIT(7)) { + return (CLR_PRIORITY); + } - if (((p_id_string[0] & 0x06) == 0x02) || ((p_id_string[0] & 0x06) == 0x04)) - match = p_id_string[1] & (unsigned char) 0x1F; - else - match = 7; + if (p_id_string[0] & BIT(5)) + i = 8; + else + i = MAX_SCSI_TAR; - while (i > 0) - { + if (((p_id_string[0] & 0x06) == 0x02) + || ((p_id_string[0] & 0x06) == 0x04)) + match = p_id_string[1] & (unsigned char)0x1F; + else + match = 7; - i--; + while (i > 0) { - if (FPT_scamInfo[match].state == ID_UNASSIGNED) - { - for (k=0; k < ID_STRING_LENGTH; k++) - { - FPT_scamInfo[match].id_string[k] = p_id_string[k]; - } + i--; - FPT_scamInfo[match].id_string[0] |= BIT(7); - FPT_scamInfo[match].state = ID_ASSIGNED; - if(FPT_BL_Card[p_card].pNvRamInfo == NULL) - FPT_BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM; - return(match); + if (FPT_scamInfo[match].state == ID_UNASSIGNED) { + for (k = 0; k < ID_STRING_LENGTH; k++) { + FPT_scamInfo[match].id_string[k] = + p_id_string[k]; + } - } + FPT_scamInfo[match].id_string[0] |= BIT(7); + FPT_scamInfo[match].state = ID_ASSIGNED; + if (FPT_BL_Card[p_card].pNvRamInfo == NULL) + FPT_BL_Card[p_card].globalFlags |= + F_UPDATE_EEPROM; + return (match); + } - match--; + match--; - if (match == 0xFF) - { - if (p_id_string[0] & BIT(5)) - match = 7; - else - match = MAX_SCSI_TAR-1; + if (match == 0xFF) { + if (p_id_string[0] & BIT(5)) + match = 7; + else + match = MAX_SCSI_TAR - 1; + } } - } - return(NO_ID_AVAIL); + return (NO_ID_AVAIL); } - /*--------------------------------------------------------------------- * * Function: FPT_scsavdi @@ -6642,43 +6443,39 @@ static unsigned char FPT_scmachid(unsigned char p_card, unsigned char p_id_strin static void FPT_scsavdi(unsigned char p_card, unsigned long p_port) { - unsigned char i,k,max_id; - unsigned short ee_data,sum_data; - - - sum_data = 0x0000; - - for (i = 1; i < EE_SCAMBASE/2; i++) - { - sum_data += FPT_utilEERead(p_port, i); - } - - - FPT_utilEEWriteOnOff(p_port,1); /* Enable write access to the EEPROM */ + unsigned char i, k, max_id; + unsigned short ee_data, sum_data; - if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD) - max_id = 0x08; + sum_data = 0x0000; - else - max_id = 0x10; + for (i = 1; i < EE_SCAMBASE / 2; i++) { + sum_data += FPT_utilEERead(p_port, i); + } - for (i=0; i < max_id; i++) - { + FPT_utilEEWriteOnOff(p_port, 1); /* Enable write access to the EEPROM */ - for (k=0; k < ID_STRING_LENGTH; k+=2) - { - ee_data = FPT_scamInfo[i].id_string[k+1]; - ee_data <<= 8; - ee_data |= FPT_scamInfo[i].id_string[k]; - sum_data += ee_data; - FPT_utilEEWrite(p_port, ee_data, (unsigned short)((EE_SCAMBASE/2) + - (unsigned short)(i*((unsigned short)ID_STRING_LENGTH/2)) + (unsigned short)(k/2))); - } - } + if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD) + max_id = 0x08; + else + max_id = 0x10; + + for (i = 0; i < max_id; i++) { + + for (k = 0; k < ID_STRING_LENGTH; k += 2) { + ee_data = FPT_scamInfo[i].id_string[k + 1]; + ee_data <<= 8; + ee_data |= FPT_scamInfo[i].id_string[k]; + sum_data += ee_data; + FPT_utilEEWrite(p_port, ee_data, + (unsigned short)((EE_SCAMBASE / 2) + + (unsigned short)(i * + ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2))); + } + } - FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM/2); - FPT_utilEEWriteOnOff(p_port,0); /* Turn off write access */ + FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2); + FPT_utilEEWriteOnOff(p_port, 0); /* Turn off write access */ } /*--------------------------------------------------------------------- @@ -6691,46 +6488,45 @@ static void FPT_scsavdi(unsigned char p_card, unsigned long p_port) static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg) { -unsigned char i; + unsigned char i; - i = RD_HARPOON(port+hp_page_ctrl); - WR_HARPOON(port+hp_page_ctrl, (unsigned char) (i | G_INT_DISABLE)); + i = RD_HARPOON(port + hp_page_ctrl); + WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE)); - WR_HARPOON(port+hp_scsireset,0x00); - WR_HARPOON(port+hp_portctrl_1,HOST_MODE8); + WR_HARPOON(port + hp_scsireset, 0x00); + WR_HARPOON(port + hp_portctrl_1, HOST_MODE8); - WR_HARPOON(port+hp_scsireset,(DMA_RESET | HPSCSI_RESET | PROG_RESET | \ - FIFO_CLR)); + WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET | + FIFO_CLR)); - WR_HARPOON(port+hp_scsireset,SCSI_INI); + WR_HARPOON(port + hp_scsireset, SCSI_INI); - WR_HARPOON(port+hp_clkctrl_0,CLKCTRL_DEFAULT); + WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT); - WR_HARPOON(port+hp_scsisig,0x00); /* Clear any signals we might */ - WR_HARPOON(port+hp_scsictrl_0,ENA_SCAM_SEL); + WR_HARPOON(port + hp_scsisig, 0x00); /* Clear any signals we might */ + WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL); - WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); + WRW_HARPOON((port + hp_intstat), CLR_ALL_INT); - FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT | - BUS_FREE | XFER_CNT_0 | AUTO_INT; + FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT | + BUS_FREE | XFER_CNT_0 | AUTO_INT; - if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) + if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) FPT_default_intena |= SCAM_SEL; - WRW_HARPOON((port+hp_intena), FPT_default_intena); + WRW_HARPOON((port + hp_intena), FPT_default_intena); - WR_HARPOON(port+hp_seltimeout,TO_290ms); + WR_HARPOON(port + hp_seltimeout, TO_290ms); - /* Turn on SCSI_MODE8 for narrow cards to fix the - strapping issue with the DUAL CHANNEL card */ - if (RD_HARPOON(port+hp_page_ctrl) & NARROW_SCSI_CARD) - WR_HARPOON(port+hp_addstat,SCSI_MODE8); + /* Turn on SCSI_MODE8 for narrow cards to fix the + strapping issue with the DUAL CHANNEL card */ + if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD) + WR_HARPOON(port + hp_addstat, SCSI_MODE8); - WR_HARPOON(port+hp_page_ctrl, i); + WR_HARPOON(port + hp_page_ctrl, i); } - /*--------------------------------------------------------------------- * * Function: FPT_BusMasterInit @@ -6742,25 +6538,21 @@ unsigned char i; static void FPT_BusMasterInit(unsigned long p_port) { + WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST); + WR_HARPOON(p_port + hp_sys_ctrl, 0x00); - WR_HARPOON(p_port+hp_sys_ctrl, DRVR_RST); - WR_HARPOON(p_port+hp_sys_ctrl, 0x00); - - WR_HARPOON(p_port+hp_host_blk_cnt, XFER_BLK64); - - - WR_HARPOON(p_port+hp_bm_ctrl, (BMCTRL_DEFAULT)); + WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64); - WR_HARPOON(p_port+hp_ee_ctrl, (SCSI_TERM_ENA_H)); + WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT)); + WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H)); - RD_HARPOON(p_port+hp_int_status); /*Clear interrupts. */ - WR_HARPOON(p_port+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); - WR_HARPOON(p_port+hp_page_ctrl, (RD_HARPOON(p_port+hp_page_ctrl) & - ~SCATTER_EN)); + RD_HARPOON(p_port + hp_int_status); /*Clear interrupts. */ + WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); + WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) & + ~SCATTER_EN)); } - /*--------------------------------------------------------------------- * * Function: FPT_DiagEEPROM @@ -6772,156 +6564,151 @@ static void FPT_BusMasterInit(unsigned long p_port) static void FPT_DiagEEPROM(unsigned long p_port) { - unsigned short index,temp,max_wd_cnt; - - if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD) - max_wd_cnt = EEPROM_WD_CNT; - else - max_wd_cnt = EEPROM_WD_CNT * 2; + unsigned short index, temp, max_wd_cnt; - temp = FPT_utilEERead(p_port, FW_SIGNATURE/2); + if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD) + max_wd_cnt = EEPROM_WD_CNT; + else + max_wd_cnt = EEPROM_WD_CNT * 2; - if (temp == 0x4641) { + temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2); - for (index = 2; index < max_wd_cnt; index++) { + if (temp == 0x4641) { - temp += FPT_utilEERead(p_port, index); + for (index = 2; index < max_wd_cnt; index++) { - } + temp += FPT_utilEERead(p_port, index); - if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM/2)) { + } - return; /*EEPROM is Okay so return now! */ - } - } + if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) { + return; /*EEPROM is Okay so return now! */ + } + } - FPT_utilEEWriteOnOff(p_port,(unsigned char)1); + FPT_utilEEWriteOnOff(p_port, (unsigned char)1); - for (index = 0; index < max_wd_cnt; index++) { + for (index = 0; index < max_wd_cnt; index++) { - FPT_utilEEWrite(p_port, 0x0000, index); - } + FPT_utilEEWrite(p_port, 0x0000, index); + } - temp = 0; - - FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE/2); - temp += 0x4641; - FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0/2); - temp += 0x3920; - FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2/2); - temp += 0x3033; - FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4/2); - temp += 0x2020; - FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG/2); - temp += 0x70D3; - FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG/2); - temp += 0x0010; - FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG/2); - temp += 0x0003; - FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID/2); - temp += 0x0007; - - FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN/2); - temp += 0x0000; - FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA/2); - temp += 0x0000; - FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE/2); - temp += 0x0000; - - FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01/2); - temp += 0x4242; - FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23/2); - temp += 0x4242; - FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45/2); - temp += 0x4242; - FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67/2); - temp += 0x4242; - FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89/2); - temp += 0x4242; - FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab/2); - temp += 0x4242; - FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd/2); - temp += 0x4242; - FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef/2); - temp += 0x4242; - - - FPT_utilEEWrite(p_port, 0x6C46, 64/2); /*PRODUCT ID */ - temp += 0x6C46; - FPT_utilEEWrite(p_port, 0x7361, 66/2); /* FlashPoint LT */ - temp += 0x7361; - FPT_utilEEWrite(p_port, 0x5068, 68/2); - temp += 0x5068; - FPT_utilEEWrite(p_port, 0x696F, 70/2); - temp += 0x696F; - FPT_utilEEWrite(p_port, 0x746E, 72/2); - temp += 0x746E; - FPT_utilEEWrite(p_port, 0x4C20, 74/2); - temp += 0x4C20; - FPT_utilEEWrite(p_port, 0x2054, 76/2); - temp += 0x2054; - FPT_utilEEWrite(p_port, 0x2020, 78/2); - temp += 0x2020; - - index = ((EE_SCAMBASE/2)+(7*16)); - FPT_utilEEWrite(p_port, (0x0700+TYPE_CODE0), index); - temp += (0x0700+TYPE_CODE0); - index++; - FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */ - temp += 0x5542; /* BUSLOGIC */ - index++; - FPT_utilEEWrite(p_port, 0x4C53, index); - temp += 0x4C53; - index++; - FPT_utilEEWrite(p_port, 0x474F, index); - temp += 0x474F; - index++; - FPT_utilEEWrite(p_port, 0x4349, index); - temp += 0x4349; - index++; - FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */ - temp += 0x5442; /* BT- 930 */ - index++; - FPT_utilEEWrite(p_port, 0x202D, index); - temp += 0x202D; - index++; - FPT_utilEEWrite(p_port, 0x3339, index); - temp += 0x3339; - index++; /*Serial # */ - FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */ - temp += 0x2030; - index++; - FPT_utilEEWrite(p_port, 0x5453, index); - temp += 0x5453; - index++; - FPT_utilEEWrite(p_port, 0x5645, index); - temp += 0x5645; - index++; - FPT_utilEEWrite(p_port, 0x2045, index); - temp += 0x2045; - index++; - FPT_utilEEWrite(p_port, 0x202F, index); - temp += 0x202F; - index++; - FPT_utilEEWrite(p_port, 0x4F4A, index); - temp += 0x4F4A; - index++; - FPT_utilEEWrite(p_port, 0x204E, index); - temp += 0x204E; - index++; - FPT_utilEEWrite(p_port, 0x3539, index); - temp += 0x3539; - - - - FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM/2); - - FPT_utilEEWriteOnOff(p_port,(unsigned char)0); + temp = 0; + + FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2); + temp += 0x4641; + FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2); + temp += 0x3920; + FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2); + temp += 0x3033; + FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2); + temp += 0x2020; + FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2); + temp += 0x70D3; + FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2); + temp += 0x0010; + FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2); + temp += 0x0003; + FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2); + temp += 0x0007; + + FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2); + temp += 0x0000; + FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2); + temp += 0x0000; + FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2); + temp += 0x0000; + + FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2); + temp += 0x4242; + FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2); + temp += 0x4242; + FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2); + temp += 0x4242; + FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2); + temp += 0x4242; + FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2); + temp += 0x4242; + FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2); + temp += 0x4242; + FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2); + temp += 0x4242; + FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2); + temp += 0x4242; + + FPT_utilEEWrite(p_port, 0x6C46, 64 / 2); /*PRODUCT ID */ + temp += 0x6C46; + FPT_utilEEWrite(p_port, 0x7361, 66 / 2); /* FlashPoint LT */ + temp += 0x7361; + FPT_utilEEWrite(p_port, 0x5068, 68 / 2); + temp += 0x5068; + FPT_utilEEWrite(p_port, 0x696F, 70 / 2); + temp += 0x696F; + FPT_utilEEWrite(p_port, 0x746E, 72 / 2); + temp += 0x746E; + FPT_utilEEWrite(p_port, 0x4C20, 74 / 2); + temp += 0x4C20; + FPT_utilEEWrite(p_port, 0x2054, 76 / 2); + temp += 0x2054; + FPT_utilEEWrite(p_port, 0x2020, 78 / 2); + temp += 0x2020; + + index = ((EE_SCAMBASE / 2) + (7 * 16)); + FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index); + temp += (0x0700 + TYPE_CODE0); + index++; + FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */ + temp += 0x5542; /* BUSLOGIC */ + index++; + FPT_utilEEWrite(p_port, 0x4C53, index); + temp += 0x4C53; + index++; + FPT_utilEEWrite(p_port, 0x474F, index); + temp += 0x474F; + index++; + FPT_utilEEWrite(p_port, 0x4349, index); + temp += 0x4349; + index++; + FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */ + temp += 0x5442; /* BT- 930 */ + index++; + FPT_utilEEWrite(p_port, 0x202D, index); + temp += 0x202D; + index++; + FPT_utilEEWrite(p_port, 0x3339, index); + temp += 0x3339; + index++; /*Serial # */ + FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */ + temp += 0x2030; + index++; + FPT_utilEEWrite(p_port, 0x5453, index); + temp += 0x5453; + index++; + FPT_utilEEWrite(p_port, 0x5645, index); + temp += 0x5645; + index++; + FPT_utilEEWrite(p_port, 0x2045, index); + temp += 0x2045; + index++; + FPT_utilEEWrite(p_port, 0x202F, index); + temp += 0x202F; + index++; + FPT_utilEEWrite(p_port, 0x4F4A, index); + temp += 0x4F4A; + index++; + FPT_utilEEWrite(p_port, 0x204E, index); + temp += 0x204E; + index++; + FPT_utilEEWrite(p_port, 0x3539, index); + temp += 0x3539; + + FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2); + + FPT_utilEEWriteOnOff(p_port, (unsigned char)0); } - /*--------------------------------------------------------------------- * * Function: Queue Search Select @@ -6930,103 +6717,127 @@ static void FPT_DiagEEPROM(unsigned long p_port) * *---------------------------------------------------------------------*/ -static void FPT_queueSearchSelect(struct sccb_card * pCurrCard, unsigned char p_card) +static void FPT_queueSearchSelect(struct sccb_card *pCurrCard, + unsigned char p_card) { - unsigned char scan_ptr, lun; - struct sccb_mgr_tar_info * currTar_Info; - struct sccb * pOldSccb; + unsigned char scan_ptr, lun; + struct sccb_mgr_tar_info *currTar_Info; + struct sccb *pOldSccb; - scan_ptr = pCurrCard->scanIndex; - do - { + scan_ptr = pCurrCard->scanIndex; + do { currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr]; - if((pCurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) - { - if (currTar_Info->TarSelQ_Cnt != 0) - { + if ((pCurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != + TAG_Q_TRYING)) { + if (currTar_Info->TarSelQ_Cnt != 0) { scan_ptr++; if (scan_ptr == MAX_SCSI_TAR) scan_ptr = 0; - - for(lun=0; lun < MAX_LUN; lun++) - { - if(currTar_Info->TarLUNBusy[lun] == 0) - { - pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head; + for (lun = 0; lun < MAX_LUN; lun++) { + if (currTar_Info->TarLUNBusy[lun] == 0) { + + pCurrCard->currentSCCB = + currTar_Info->TarSelQ_Head; pOldSccb = NULL; - while((pCurrCard->currentSCCB != NULL) && - (lun != pCurrCard->currentSCCB->Lun)) - { - pOldSccb = pCurrCard->currentSCCB; - pCurrCard->currentSCCB = (struct sccb *)(pCurrCard->currentSCCB)-> - Sccb_forwardlink; + while ((pCurrCard-> + currentSCCB != NULL) + && (lun != + pCurrCard-> + currentSCCB->Lun)) { + pOldSccb = + pCurrCard-> + currentSCCB; + pCurrCard->currentSCCB = + (struct sccb + *)(pCurrCard-> + currentSCCB)-> + Sccb_forwardlink; } - if(pCurrCard->currentSCCB == NULL) + if (pCurrCard->currentSCCB == + NULL) continue; - if(pOldSccb != NULL) - { - pOldSccb->Sccb_forwardlink = (struct sccb *)(pCurrCard->currentSCCB)-> - Sccb_forwardlink; - pOldSccb->Sccb_backlink = (struct sccb *)(pCurrCard->currentSCCB)-> - Sccb_backlink; - currTar_Info->TarSelQ_Cnt--; - } - else - { - currTar_Info->TarSelQ_Head = (struct sccb *)(pCurrCard->currentSCCB)->Sccb_forwardlink; - - if (currTar_Info->TarSelQ_Head == NULL) - { - currTar_Info->TarSelQ_Tail = NULL; - currTar_Info->TarSelQ_Cnt = 0; - } - else - { - currTar_Info->TarSelQ_Cnt--; - currTar_Info->TarSelQ_Head->Sccb_backlink = (struct sccb *)NULL; + if (pOldSccb != NULL) { + pOldSccb-> + Sccb_forwardlink = + (struct sccb + *)(pCurrCard-> + currentSCCB)-> + Sccb_forwardlink; + pOldSccb-> + Sccb_backlink = + (struct sccb + *)(pCurrCard-> + currentSCCB)-> + Sccb_backlink; + currTar_Info-> + TarSelQ_Cnt--; + } else { + currTar_Info-> + TarSelQ_Head = + (struct sccb + *)(pCurrCard-> + currentSCCB)-> + Sccb_forwardlink; + + if (currTar_Info-> + TarSelQ_Head == + NULL) { + currTar_Info-> + TarSelQ_Tail + = NULL; + currTar_Info-> + TarSelQ_Cnt + = 0; + } else { + currTar_Info-> + TarSelQ_Cnt--; + currTar_Info-> + TarSelQ_Head-> + Sccb_backlink + = + (struct sccb + *)NULL; } } - pCurrCard->scanIndex = scan_ptr; + pCurrCard->scanIndex = scan_ptr; - pCurrCard->globalFlags |= F_NEW_SCCB_CMD; + pCurrCard->globalFlags |= + F_NEW_SCCB_CMD; - break; + break; } } } - else - { + else { scan_ptr++; if (scan_ptr == MAX_SCSI_TAR) { scan_ptr = 0; } } - } - else - { + } else { if ((currTar_Info->TarSelQ_Cnt != 0) && - (currTar_Info->TarLUNBusy[0] == 0)) - { + (currTar_Info->TarLUNBusy[0] == 0)) { - pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head; + pCurrCard->currentSCCB = + currTar_Info->TarSelQ_Head; - currTar_Info->TarSelQ_Head = (struct sccb *)(pCurrCard->currentSCCB)->Sccb_forwardlink; + currTar_Info->TarSelQ_Head = + (struct sccb *)(pCurrCard->currentSCCB)-> + Sccb_forwardlink; - if (currTar_Info->TarSelQ_Head == NULL) - { + if (currTar_Info->TarSelQ_Head == NULL) { currTar_Info->TarSelQ_Tail = NULL; currTar_Info->TarSelQ_Cnt = 0; - } - else - { + } else { currTar_Info->TarSelQ_Cnt--; - currTar_Info->TarSelQ_Head->Sccb_backlink = (struct sccb *)NULL; + currTar_Info->TarSelQ_Head-> + Sccb_backlink = (struct sccb *)NULL; } scan_ptr++; @@ -7040,11 +6851,9 @@ static void FPT_queueSearchSelect(struct sccb_card * pCurrCard, unsigned char p_ break; } - else - { + else { scan_ptr++; - if (scan_ptr == MAX_SCSI_TAR) - { + if (scan_ptr == MAX_SCSI_TAR) { scan_ptr = 0; } } @@ -7052,7 +6861,6 @@ static void FPT_queueSearchSelect(struct sccb_card * pCurrCard, unsigned char p_ } while (scan_ptr != pCurrCard->scanIndex); } - /*--------------------------------------------------------------------- * * Function: Queue Select Fail @@ -7061,37 +6869,39 @@ static void FPT_queueSearchSelect(struct sccb_card * pCurrCard, unsigned char p_ * *---------------------------------------------------------------------*/ -static void FPT_queueSelectFail(struct sccb_card * pCurrCard, unsigned char p_card) +static void FPT_queueSelectFail(struct sccb_card *pCurrCard, + unsigned char p_card) { - unsigned char thisTarg; - struct sccb_mgr_tar_info * currTar_Info; + unsigned char thisTarg; + struct sccb_mgr_tar_info *currTar_Info; - if (pCurrCard->currentSCCB != NULL) - { - thisTarg = (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->TargID); - currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; + if (pCurrCard->currentSCCB != NULL) { + thisTarg = + (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))-> + TargID); + currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; - pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL; + pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL; - pCurrCard->currentSCCB->Sccb_forwardlink = currTar_Info->TarSelQ_Head; + pCurrCard->currentSCCB->Sccb_forwardlink = + currTar_Info->TarSelQ_Head; - if (currTar_Info->TarSelQ_Cnt == 0) - { - currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB; - } - - else - { - currTar_Info->TarSelQ_Head->Sccb_backlink = pCurrCard->currentSCCB; - } + if (currTar_Info->TarSelQ_Cnt == 0) { + currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB; + } + else { + currTar_Info->TarSelQ_Head->Sccb_backlink = + pCurrCard->currentSCCB; + } - currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB; + currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB; - pCurrCard->currentSCCB = NULL; - currTar_Info->TarSelQ_Cnt++; - } + pCurrCard->currentSCCB = NULL; + currTar_Info->TarSelQ_Cnt++; + } } + /*--------------------------------------------------------------------- * * Function: Queue Command Complete @@ -7100,101 +6910,97 @@ static void FPT_queueSelectFail(struct sccb_card * pCurrCard, unsigned char p_ca * *---------------------------------------------------------------------*/ -static void FPT_queueCmdComplete(struct sccb_card * pCurrCard, struct sccb * p_sccb, - unsigned char p_card) +static void FPT_queueCmdComplete(struct sccb_card *pCurrCard, + struct sccb *p_sccb, unsigned char p_card) { - unsigned char i, SCSIcmd; - CALL_BK_FN callback; - struct sccb_mgr_tar_info * currTar_Info; - - SCSIcmd = p_sccb->Cdb[0]; - - - if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) { - - if ((p_sccb->ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN)) && - (p_sccb->HostStatus == SCCB_COMPLETE) && - (p_sccb->TargetStatus != SSCHECK)) - - if ((SCSIcmd == SCSI_READ) || - (SCSIcmd == SCSI_WRITE) || - (SCSIcmd == SCSI_READ_EXTENDED) || - (SCSIcmd == SCSI_WRITE_EXTENDED) || - (SCSIcmd == SCSI_WRITE_AND_VERIFY) || - (SCSIcmd == SCSI_START_STOP_UNIT) || - (pCurrCard->globalFlags & F_NO_FILTER) - ) - p_sccb->HostStatus = SCCB_DATA_UNDER_RUN; - } - + unsigned char i, SCSIcmd; + CALL_BK_FN callback; + struct sccb_mgr_tar_info *currTar_Info; + + SCSIcmd = p_sccb->Cdb[0]; + + if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) { + + if ((p_sccb-> + ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN)) + && (p_sccb->HostStatus == SCCB_COMPLETE) + && (p_sccb->TargetStatus != SSCHECK)) + + if ((SCSIcmd == SCSI_READ) || + (SCSIcmd == SCSI_WRITE) || + (SCSIcmd == SCSI_READ_EXTENDED) || + (SCSIcmd == SCSI_WRITE_EXTENDED) || + (SCSIcmd == SCSI_WRITE_AND_VERIFY) || + (SCSIcmd == SCSI_START_STOP_UNIT) || + (pCurrCard->globalFlags & F_NO_FILTER) + ) + p_sccb->HostStatus = SCCB_DATA_UNDER_RUN; + } - if(p_sccb->SccbStatus == SCCB_IN_PROCESS) - { - if (p_sccb->HostStatus || p_sccb->TargetStatus) - p_sccb->SccbStatus = SCCB_ERROR; - else - p_sccb->SccbStatus = SCCB_SUCCESS; + if (p_sccb->SccbStatus == SCCB_IN_PROCESS) { + if (p_sccb->HostStatus || p_sccb->TargetStatus) + p_sccb->SccbStatus = SCCB_ERROR; + else + p_sccb->SccbStatus = SCCB_SUCCESS; } - if (p_sccb->Sccb_XferState & F_AUTO_SENSE) { + if (p_sccb->Sccb_XferState & F_AUTO_SENSE) { - p_sccb->CdbLength = p_sccb->Save_CdbLen; - for (i=0; i < 6; i++) { - p_sccb->Cdb[i] = p_sccb->Save_Cdb[i]; - } - } + p_sccb->CdbLength = p_sccb->Save_CdbLen; + for (i = 0; i < 6; i++) { + p_sccb->Cdb[i] = p_sccb->Save_Cdb[i]; + } + } - if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) || - (p_sccb->OperationCode == RESIDUAL_COMMAND)) { + if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) || + (p_sccb->OperationCode == RESIDUAL_COMMAND)) { - FPT_utilUpdateResidual(p_sccb); - } + FPT_utilUpdateResidual(p_sccb); + } - pCurrCard->cmdCounter--; - if (!pCurrCard->cmdCounter) { + pCurrCard->cmdCounter--; + if (!pCurrCard->cmdCounter) { - if (pCurrCard->globalFlags & F_GREEN_PC) { - WR_HARPOON(pCurrCard->ioPort+hp_clkctrl_0,(PWR_DWN | CLKCTRL_DEFAULT)); - WR_HARPOON(pCurrCard->ioPort+hp_sys_ctrl, STOP_CLK); - } + if (pCurrCard->globalFlags & F_GREEN_PC) { + WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0, + (PWR_DWN | CLKCTRL_DEFAULT)); + WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK); + } - WR_HARPOON(pCurrCard->ioPort+hp_semaphore, - (RD_HARPOON(pCurrCard->ioPort+hp_semaphore) & ~SCCB_MGR_ACTIVE)); + WR_HARPOON(pCurrCard->ioPort + hp_semaphore, + (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) & + ~SCCB_MGR_ACTIVE)); - } + } - if(pCurrCard->discQCount != 0) - { - currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID]; - if(((pCurrCard->globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { + if (pCurrCard->discQCount != 0) { + currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID]; + if (((pCurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != + TAG_Q_TRYING))) { pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = NULL; - } - else - { - if(p_sccb->Sccb_tag) - { + pCurrCard->discQ_Tbl[currTar_Info-> + LunDiscQ_Idx[p_sccb->Lun]] = NULL; + } else { + if (p_sccb->Sccb_tag) { pCurrCard->discQCount--; pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL; - }else - { + } else { pCurrCard->discQCount--; - pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL; + pCurrCard->discQ_Tbl[currTar_Info-> + LunDiscQ_Idx[0]] = NULL; } } } - callback = (CALL_BK_FN)p_sccb->SccbCallback; - callback(p_sccb); - pCurrCard->globalFlags |= F_NEW_SCCB_CMD; - pCurrCard->currentSCCB = NULL; + callback = (CALL_BK_FN) p_sccb->SccbCallback; + callback(p_sccb); + pCurrCard->globalFlags |= F_NEW_SCCB_CMD; + pCurrCard->currentSCCB = NULL; } - /*--------------------------------------------------------------------- * * Function: Queue Disconnect @@ -7202,33 +7008,32 @@ static void FPT_queueCmdComplete(struct sccb_card * pCurrCard, struct sccb * p_s * Description: Add SCCB to our disconnect array. * *---------------------------------------------------------------------*/ -static void FPT_queueDisconnect(struct sccb * p_sccb, unsigned char p_card) +static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card) { - struct sccb_mgr_tar_info * currTar_Info; + struct sccb_mgr_tar_info *currTar_Info; currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID]; - if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && - ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) - { - FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = p_sccb; - } - else - { - if (p_sccb->Sccb_tag) - { - FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] = p_sccb; - FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] = 0; + if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) { + FPT_BL_Card[p_card].discQ_Tbl[currTar_Info-> + LunDiscQ_Idx[p_sccb->Lun]] = + p_sccb; + } else { + if (p_sccb->Sccb_tag) { + FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] = + p_sccb; + FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] = + 0; FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++; - }else - { - FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = p_sccb; + } else { + FPT_BL_Card[p_card].discQ_Tbl[currTar_Info-> + LunDiscQ_Idx[0]] = p_sccb; } } FPT_BL_Card[p_card].currentSCCB = NULL; } - /*--------------------------------------------------------------------- * * Function: Queue Flush SCCB @@ -7237,33 +7042,35 @@ static void FPT_queueDisconnect(struct sccb * p_sccb, unsigned char p_card) * *---------------------------------------------------------------------*/ -static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code) +static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code) { - unsigned char qtag,thisTarg; - struct sccb * currSCCB; - struct sccb_mgr_tar_info * currTar_Info; + unsigned char qtag, thisTarg; + struct sccb *currSCCB; + struct sccb_mgr_tar_info *currTar_Info; - currSCCB = FPT_BL_Card[p_card].currentSCCB; - if(currSCCB != NULL) - { - thisTarg = (unsigned char)currSCCB->TargID; - currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; + currSCCB = FPT_BL_Card[p_card].currentSCCB; + if (currSCCB != NULL) { + thisTarg = (unsigned char)currSCCB->TargID; + currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; + + for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) { - for (qtag=0; qtagTargID == + thisTarg)) { - if (FPT_BL_Card[p_card].discQ_Tbl[qtag] && - (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) - { + FPT_BL_Card[p_card].discQ_Tbl[qtag]-> + HostStatus = (unsigned char)error_code; - FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (unsigned char)error_code; - - FPT_queueCmdComplete(&FPT_BL_Card[p_card],FPT_BL_Card[p_card].discQ_Tbl[qtag], p_card); + FPT_queueCmdComplete(&FPT_BL_Card[p_card], + FPT_BL_Card[p_card]. + discQ_Tbl[qtag], p_card); - FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL; - currTar_Info->TarTagQ_Cnt--; + FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL; + currTar_Info->TarTagQ_Cnt--; - } - } + } + } } } @@ -7276,61 +7083,57 @@ static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code) * *---------------------------------------------------------------------*/ -static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg, - unsigned char error_code) +static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg, + unsigned char error_code) { - unsigned char qtag; - struct sccb_mgr_tar_info * currTar_Info; + unsigned char qtag; + struct sccb_mgr_tar_info *currTar_Info; - currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; + currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; - for (qtag=0; qtagTargID == thisTarg)) - { + if (FPT_BL_Card[p_card].discQ_Tbl[qtag] && + (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) { - FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (unsigned char)error_code; + FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = + (unsigned char)error_code; - FPT_queueCmdComplete(&FPT_BL_Card[p_card],FPT_BL_Card[p_card].discQ_Tbl[qtag], p_card); + FPT_queueCmdComplete(&FPT_BL_Card[p_card], + FPT_BL_Card[p_card]. + discQ_Tbl[qtag], p_card); - FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL; - currTar_Info->TarTagQ_Cnt--; + FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL; + currTar_Info->TarTagQ_Cnt--; - } - } + } + } } - - - - -static void FPT_queueAddSccb(struct sccb * p_SCCB, unsigned char p_card) +static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card) { - struct sccb_mgr_tar_info * currTar_Info; - currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID]; - - p_SCCB->Sccb_forwardlink = NULL; + struct sccb_mgr_tar_info *currTar_Info; + currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID]; - p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail; + p_SCCB->Sccb_forwardlink = NULL; - if (currTar_Info->TarSelQ_Cnt == 0) { + p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail; - currTar_Info->TarSelQ_Head = p_SCCB; - } + if (currTar_Info->TarSelQ_Cnt == 0) { - else { + currTar_Info->TarSelQ_Head = p_SCCB; + } - currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB; - } + else { + currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB; + } - currTar_Info->TarSelQ_Tail = p_SCCB; - currTar_Info->TarSelQ_Cnt++; + currTar_Info->TarSelQ_Tail = p_SCCB; + currTar_Info->TarSelQ_Cnt++; } - /*--------------------------------------------------------------------- * * Function: Queue Find SCCB @@ -7340,54 +7143,56 @@ static void FPT_queueAddSccb(struct sccb * p_SCCB, unsigned char p_card) * *---------------------------------------------------------------------*/ -static unsigned char FPT_queueFindSccb(struct sccb * p_SCCB, unsigned char p_card) +static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB, + unsigned char p_card) { - struct sccb * q_ptr; - struct sccb_mgr_tar_info * currTar_Info; - - currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID]; + struct sccb *q_ptr; + struct sccb_mgr_tar_info *currTar_Info; - q_ptr = currTar_Info->TarSelQ_Head; + currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID]; - while(q_ptr != NULL) { + q_ptr = currTar_Info->TarSelQ_Head; - if (q_ptr == p_SCCB) { + while (q_ptr != NULL) { + if (q_ptr == p_SCCB) { - if (currTar_Info->TarSelQ_Head == q_ptr) { + if (currTar_Info->TarSelQ_Head == q_ptr) { - currTar_Info->TarSelQ_Head = q_ptr->Sccb_forwardlink; + currTar_Info->TarSelQ_Head = + q_ptr->Sccb_forwardlink; } - if (currTar_Info->TarSelQ_Tail == q_ptr) { + if (currTar_Info->TarSelQ_Tail == q_ptr) { - currTar_Info->TarSelQ_Tail = q_ptr->Sccb_backlink; + currTar_Info->TarSelQ_Tail = + q_ptr->Sccb_backlink; } - if (q_ptr->Sccb_forwardlink != NULL) { - q_ptr->Sccb_forwardlink->Sccb_backlink = q_ptr->Sccb_backlink; + if (q_ptr->Sccb_forwardlink != NULL) { + q_ptr->Sccb_forwardlink->Sccb_backlink = + q_ptr->Sccb_backlink; } - if (q_ptr->Sccb_backlink != NULL) { - q_ptr->Sccb_backlink->Sccb_forwardlink = q_ptr->Sccb_forwardlink; + if (q_ptr->Sccb_backlink != NULL) { + q_ptr->Sccb_backlink->Sccb_forwardlink = + q_ptr->Sccb_forwardlink; } - currTar_Info->TarSelQ_Cnt--; + currTar_Info->TarSelQ_Cnt--; - return(1); - } - - else { - q_ptr = q_ptr->Sccb_forwardlink; - } - } + return (1); + } + else { + q_ptr = q_ptr->Sccb_forwardlink; + } + } - return(0); + return (0); } - /*--------------------------------------------------------------------- * * Function: Utility Update Residual Count @@ -7401,48 +7206,47 @@ static unsigned char FPT_queueFindSccb(struct sccb * p_SCCB, unsigned char p_car * *---------------------------------------------------------------------*/ -static void FPT_utilUpdateResidual(struct sccb * p_SCCB) +static void FPT_utilUpdateResidual(struct sccb *p_SCCB) { - unsigned long partial_cnt; - unsigned int sg_index; - unsigned long *sg_ptr; + unsigned long partial_cnt; + unsigned int sg_index; + unsigned long *sg_ptr; - if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) { + if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) { - p_SCCB->DataLength = 0x0000; - } + p_SCCB->DataLength = 0x0000; + } - else if (p_SCCB->Sccb_XferState & F_SG_XFER) { + else if (p_SCCB->Sccb_XferState & F_SG_XFER) { - partial_cnt = 0x0000; + partial_cnt = 0x0000; - sg_index = p_SCCB->Sccb_sgseg; + sg_index = p_SCCB->Sccb_sgseg; - sg_ptr = (unsigned long *)p_SCCB->DataPointer; + sg_ptr = (unsigned long *)p_SCCB->DataPointer; - if (p_SCCB->Sccb_SGoffset) { + if (p_SCCB->Sccb_SGoffset) { partial_cnt = p_SCCB->Sccb_SGoffset; sg_index++; - } + } - while ( ((unsigned long)sg_index * (unsigned long)SG_ELEMENT_SIZE) < - p_SCCB->DataLength ) { + while (((unsigned long)sg_index * + (unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) { - partial_cnt += *(sg_ptr+(sg_index * 2)); + partial_cnt += *(sg_ptr + (sg_index * 2)); sg_index++; - } + } - p_SCCB->DataLength = partial_cnt; - } + p_SCCB->DataLength = partial_cnt; + } - else { + else { - p_SCCB->DataLength -= p_SCCB->Sccb_ATC; - } + p_SCCB->DataLength -= p_SCCB->Sccb_ATC; + } } - /*--------------------------------------------------------------------- * * Function: Wait 1 Second @@ -7453,21 +7257,20 @@ static void FPT_utilUpdateResidual(struct sccb * p_SCCB) static void FPT_Wait1Second(unsigned long p_port) { - unsigned char i; + unsigned char i; - for(i=0; i < 4; i++) { + for (i = 0; i < 4; i++) { - FPT_Wait(p_port, TO_250ms); + FPT_Wait(p_port, TO_250ms); - if ((RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST)) - break; + if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST)) + break; - if((RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) - break; - } + if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) + break; + } } - /*--------------------------------------------------------------------- * * Function: FPT_Wait @@ -7478,43 +7281,41 @@ static void FPT_Wait1Second(unsigned long p_port) static void FPT_Wait(unsigned long p_port, unsigned char p_delay) { - unsigned char old_timer; - unsigned char green_flag; + unsigned char old_timer; + unsigned char green_flag; - old_timer = RD_HARPOON(p_port+hp_seltimeout); + old_timer = RD_HARPOON(p_port + hp_seltimeout); - green_flag=RD_HARPOON(p_port+hp_clkctrl_0); - WR_HARPOON(p_port+hp_clkctrl_0, CLKCTRL_DEFAULT); + green_flag = RD_HARPOON(p_port + hp_clkctrl_0); + WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT); - WR_HARPOON(p_port+hp_seltimeout,p_delay); - WRW_HARPOON((p_port+hp_intstat), TIMEOUT); - WRW_HARPOON((p_port+hp_intena), (FPT_default_intena & ~TIMEOUT)); + WR_HARPOON(p_port + hp_seltimeout, p_delay); + WRW_HARPOON((p_port + hp_intstat), TIMEOUT); + WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT)); + WR_HARPOON(p_port + hp_portctrl_0, + (RD_HARPOON(p_port + hp_portctrl_0) | START_TO)); - WR_HARPOON(p_port+hp_portctrl_0, - (RD_HARPOON(p_port+hp_portctrl_0) | START_TO)); + while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) { - while (!(RDW_HARPOON((p_port+hp_intstat)) & TIMEOUT)) { + if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST)) + break; - if ((RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST)) - break; - - if ((RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) - break; - } + if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) + break; + } - WR_HARPOON(p_port+hp_portctrl_0, - (RD_HARPOON(p_port+hp_portctrl_0) & ~START_TO)); + WR_HARPOON(p_port + hp_portctrl_0, + (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO)); - WRW_HARPOON((p_port+hp_intstat), TIMEOUT); - WRW_HARPOON((p_port+hp_intena), FPT_default_intena); + WRW_HARPOON((p_port + hp_intstat), TIMEOUT); + WRW_HARPOON((p_port + hp_intena), FPT_default_intena); - WR_HARPOON(p_port+hp_clkctrl_0,green_flag); + WR_HARPOON(p_port + hp_clkctrl_0, green_flag); - WR_HARPOON(p_port+hp_seltimeout,old_timer); + WR_HARPOON(p_port + hp_seltimeout, old_timer); } - /*--------------------------------------------------------------------- * * Function: Enable/Disable Write to EEPROM @@ -7524,26 +7325,26 @@ static void FPT_Wait(unsigned long p_port, unsigned char p_delay) * *---------------------------------------------------------------------*/ -static void FPT_utilEEWriteOnOff(unsigned long p_port,unsigned char p_mode) +static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode) { - unsigned char ee_value; - - ee_value = (unsigned char)(RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H)); + unsigned char ee_value; - if (p_mode) + ee_value = + (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) & + (EXT_ARB_ACK | SCSI_TERM_ENA_H)); - FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR); + if (p_mode) - else + FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR); + else - FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR); + FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR); - WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); /*Turn off Master Select */ + WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */ + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */ } - /*--------------------------------------------------------------------- * * Function: Write EEPROM @@ -7553,46 +7354,46 @@ static void FPT_utilEEWriteOnOff(unsigned long p_port,unsigned char p_mode) * *---------------------------------------------------------------------*/ -static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data, unsigned short ee_addr) +static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data, + unsigned short ee_addr) { - unsigned char ee_value; - unsigned short i; - - ee_value = (unsigned char)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| - (SEE_MS | SEE_CS)); - - + unsigned char ee_value; + unsigned short i; - FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr); + ee_value = + (unsigned + char)((RD_HARPOON(p_port + hp_ee_ctrl) & + (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS)); + FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr); - ee_value |= (SEE_MS + SEE_CS); + ee_value |= (SEE_MS + SEE_CS); - for(i = 0x8000; i != 0; i>>=1) { + for (i = 0x8000; i != 0; i >>= 1) { - if (i & ee_data) - ee_value |= SEE_DO; - else - ee_value &= ~SEE_DO; - - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value |= SEE_CLK; /* Clock data! */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value &= ~SEE_CLK; - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - } - ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H); - WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); + if (i & ee_data) + ee_value |= SEE_DO; + else + ee_value &= ~SEE_DO; + + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + ee_value |= SEE_CLK; /* Clock data! */ + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + ee_value &= ~SEE_CLK; + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + } + ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H); + WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); - FPT_Wait(p_port, TO_10ms); + FPT_Wait(p_port, TO_10ms); - WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */ - WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); /* Turn off Master Select */ + WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */ + WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */ + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /* Turn off Master Select */ } /*--------------------------------------------------------------------- @@ -7604,25 +7405,25 @@ static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data, unsign * *---------------------------------------------------------------------*/ -static unsigned short FPT_utilEERead(unsigned long p_port, unsigned short ee_addr) +static unsigned short FPT_utilEERead(unsigned long p_port, + unsigned short ee_addr) { - unsigned short i, ee_data1, ee_data2; + unsigned short i, ee_data1, ee_data2; i = 0; ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr); - do - { + do { ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr); - if(ee_data1 == ee_data2) - return(ee_data1); + if (ee_data1 == ee_data2) + return (ee_data1); ee_data1 = ee_data2; i++; - }while(i < 4); + } while (i < 4); - return(ee_data1); + return (ee_data1); } /*--------------------------------------------------------------------- @@ -7634,45 +7435,45 @@ static unsigned short FPT_utilEERead(unsigned long p_port, unsigned short ee_add * *---------------------------------------------------------------------*/ -static unsigned short FPT_utilEEReadOrg(unsigned long p_port, unsigned short ee_addr) +static unsigned short FPT_utilEEReadOrg(unsigned long p_port, + unsigned short ee_addr) { - unsigned char ee_value; - unsigned short i, ee_data; + unsigned char ee_value; + unsigned short i, ee_data; - ee_value = (unsigned char)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| - (SEE_MS | SEE_CS)); + ee_value = + (unsigned + char)((RD_HARPOON(p_port + hp_ee_ctrl) & + (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS)); + FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr); - FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr); + ee_value |= (SEE_MS + SEE_CS); + ee_data = 0; + for (i = 1; i <= 16; i++) { - ee_value |= (SEE_MS + SEE_CS); - ee_data = 0; + ee_value |= SEE_CLK; /* Clock data! */ + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + ee_value &= ~SEE_CLK; + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); - for(i = 1; i <= 16; i++) { + ee_data <<= 1; - ee_value |= SEE_CLK; /* Clock data! */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value &= ~SEE_CLK; - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - - ee_data <<= 1; - - if (RD_HARPOON(p_port+hp_ee_ctrl) & SEE_DI) - ee_data |= 1; - } + if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI) + ee_data |= 1; + } - ee_value &= ~(SEE_MS + SEE_CS); - WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); /*Turn off Master Select */ + ee_value &= ~(SEE_MS + SEE_CS); + WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */ + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */ - return(ee_data); + return (ee_data); } - /*--------------------------------------------------------------------- * * Function: Send EE command and Address to the EEPROM @@ -7682,87 +7483,83 @@ static unsigned short FPT_utilEEReadOrg(unsigned long p_port, unsigned short ee_ * *---------------------------------------------------------------------*/ -static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd, unsigned short ee_addr) +static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd, + unsigned short ee_addr) { - unsigned char ee_value; - unsigned char narrow_flg; - - unsigned short i; - - - narrow_flg= (unsigned char)(RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD); - + unsigned char ee_value; + unsigned char narrow_flg; - ee_value = SEE_MS; - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + unsigned short i; - ee_value |= SEE_CS; /* Set CS to EEPROM */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + narrow_flg = + (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) & + NARROW_SCSI_CARD); + ee_value = SEE_MS; + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); - for(i = 0x04; i != 0; i>>=1) { + ee_value |= SEE_CS; /* Set CS to EEPROM */ + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); - if (i & ee_cmd) - ee_value |= SEE_DO; - else - ee_value &= ~SEE_DO; - - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value |= SEE_CLK; /* Clock data! */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value &= ~SEE_CLK; - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - } - - - if (narrow_flg) - i = 0x0080; - - else - i = 0x0200; + for (i = 0x04; i != 0; i >>= 1) { + if (i & ee_cmd) + ee_value |= SEE_DO; + else + ee_value &= ~SEE_DO; + + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + ee_value |= SEE_CLK; /* Clock data! */ + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + ee_value &= ~SEE_CLK; + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + } - while (i != 0) { + if (narrow_flg) + i = 0x0080; - if (i & ee_addr) - ee_value |= SEE_DO; - else - ee_value &= ~SEE_DO; + else + i = 0x0200; - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value |= SEE_CLK; /* Clock data! */ - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - ee_value &= ~SEE_CLK; - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); - WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + while (i != 0) { - i >>= 1; - } + if (i & ee_addr) + ee_value |= SEE_DO; + else + ee_value &= ~SEE_DO; + + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + ee_value |= SEE_CLK; /* Clock data! */ + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + ee_value &= ~SEE_CLK; + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + WR_HARPOON(p_port + hp_ee_ctrl, ee_value); + + i >>= 1; + } } static unsigned short FPT_CalcCrc16(unsigned char buffer[]) { - unsigned short crc=0; - int i,j; - unsigned short ch; - for (i=0; i < ID_STRING_LENGTH; i++) - { - ch = (unsigned short) buffer[i]; - for(j=0; j < 8; j++) - { - if ((crc ^ ch) & 1) - crc = (crc >> 1) ^ CRCMASK; - else - crc >>= 1; - ch >>= 1; - } - } - return(crc); + unsigned short crc = 0; + int i, j; + unsigned short ch; + for (i = 0; i < ID_STRING_LENGTH; i++) { + ch = (unsigned short)buffer[i]; + for (j = 0; j < 8; j++) { + if ((crc ^ ch) & 1) + crc = (crc >> 1) ^ CRCMASK; + else + crc >>= 1; + ch >>= 1; + } + } + return (crc); } static unsigned char FPT_CalcLrc(unsigned char buffer[]) @@ -7770,13 +7567,11 @@ static unsigned char FPT_CalcLrc(unsigned char buffer[]) int i; unsigned char lrc; lrc = 0; - for(i = 0; i < ID_STRING_LENGTH; i++) + for (i = 0; i < ID_STRING_LENGTH; i++) lrc ^= buffer[i]; - return(lrc); + return (lrc); } - - /* The following inline definitions avoid type conflicts. */ @@ -7784,51 +7579,49 @@ static unsigned char FPT_CalcLrc(unsigned char buffer[]) static inline unsigned char FlashPoint__ProbeHostAdapter(struct FlashPoint_Info *FlashPointInfo) { - return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *) FlashPointInfo); + return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *) + FlashPointInfo); } - static inline FlashPoint_CardHandle_T FlashPoint__HardwareResetHostAdapter(struct FlashPoint_Info *FlashPointInfo) { - return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *) FlashPointInfo); + return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *) + FlashPointInfo); } static inline void FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle) { - FlashPoint_ReleaseHostAdapter(CardHandle); + FlashPoint_ReleaseHostAdapter(CardHandle); } - static inline void -FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle, struct BusLogic_CCB *CCB) +FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle, + struct BusLogic_CCB *CCB) { - FlashPoint_StartCCB(CardHandle, (struct sccb *) CCB); + FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB); } - static inline void -FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle, struct BusLogic_CCB *CCB) +FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle, + struct BusLogic_CCB *CCB) { - FlashPoint_AbortCCB(CardHandle, (struct sccb *) CCB); + FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB); } - static inline boolean FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle) { - return FlashPoint_InterruptPending(CardHandle); + return FlashPoint_InterruptPending(CardHandle); } - static inline int FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle) { - return FlashPoint_HandleInterrupt(CardHandle); + return FlashPoint_HandleInterrupt(CardHandle); } - #define FlashPoint_ProbeHostAdapter FlashPoint__ProbeHostAdapter #define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter #define FlashPoint_ReleaseHostAdapter FlashPoint__ReleaseHostAdapter @@ -7837,9 +7630,7 @@ FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle) #define FlashPoint_InterruptPending FlashPoint__InterruptPending #define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt - -#else /* CONFIG_SCSI_OMIT_FLASHPOINT */ - +#else /* CONFIG_SCSI_OMIT_FLASHPOINT */ /* Define prototypes for the FlashPoint SCCB Manager Functions. @@ -7847,12 +7638,11 @@ FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle) extern unsigned char FlashPoint_ProbeHostAdapter(struct FlashPoint_Info *); extern FlashPoint_CardHandle_T - FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *); +FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *); extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *); extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *); extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T); extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T); extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T); - -#endif /* CONFIG_SCSI_OMIT_FLASHPOINT */ +#endif /* CONFIG_SCSI_OMIT_FLASHPOINT */ -- cgit v1.2.3-59-g8ed1b From 5c1b85e209af41c7e99a2bfd21dc8fe840b342d8 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Mar 2006 00:14:37 -0800 Subject: [SCSI] drivers/scsi/FlashPoint.c: don't use parenthesis with "return" Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/FlashPoint.c | 130 +++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index ce49fbcafbb6..8e3d949b7118 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -945,16 +945,16 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo) ioport = pCardInfo->si_baseaddr; if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0) - return ((int)FAILURE); + return (int)FAILURE; if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1)) - return ((int)FAILURE); + return (int)FAILURE; if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0)) - return ((int)FAILURE); + return (int)FAILURE; if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1)) - return ((int)FAILURE); + return (int)FAILURE; if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) { @@ -964,7 +964,7 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo) device. */ if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f) - return ((int)FAILURE); + return (int)FAILURE; } if (first_time) { @@ -986,7 +986,7 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo) pCurrNvRam->niBaseAddr = ioport; FPT_RNVRamData(pCurrNvRam); } else - return ((int)FAILURE); + return (int)FAILURE; } } else pCurrNvRam = NULL; @@ -1194,7 +1194,7 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo) pCardInfo->si_present = 0x01; - return (0); + return 0; } /*--------------------------------------------------------------------- @@ -1220,7 +1220,7 @@ static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info if (thisCard == MAX_CARDS) { - return (FAILURE); + return FAILURE; } if (FPT_BL_Card[thisCard].ioPort == ioport) { @@ -1388,7 +1388,7 @@ static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) | SCCB_MGR_PRESENT)); - return ((unsigned long)CurrCard); + return (unsigned long)CurrCard; } static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard) @@ -1460,7 +1460,7 @@ static void FPT_RNVRamData(struct nvram_info *pNvRamInfo) static unsigned char FPT_RdStack(unsigned long portBase, unsigned char index) { WR_HARPOON(portBase + hp_stack_addr, index); - return (RD_HARPOON(portBase + hp_stack_data)); + return RD_HARPOON(portBase + hp_stack_data); } static void FPT_WrStack(unsigned long portBase, unsigned char index, @@ -1473,14 +1473,14 @@ static void FPT_WrStack(unsigned long portBase, unsigned char index, static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort) { if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4)) - return (0); + return 0; if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT) != CLKCTRL_DEFAULT) - return (0); + return 0; if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) || (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms)) - return (1); - return (0); + return 1; + return 0; } @@ -1642,14 +1642,14 @@ static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb) callback = p_Sccb->SccbCallback; callback(p_Sccb); - return (0); + return 0; } else { if (((struct sccb_card *)pCurrCard)->currentSCCB == p_Sccb) { p_Sccb->SccbStatus = SCCB_ABORT; - return (0); + return 0; } @@ -1691,7 +1691,7 @@ static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb) } } MENABLE_INT(ioport); - return (0); + return 0; } else { currTar_Info = &FPT_sccbMgrTbl[thisCard][p_Sccb-> @@ -1702,13 +1702,13 @@ static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb) LunDiscQ_Idx[p_Sccb->Lun]] == p_Sccb) { p_Sccb->SccbStatus = SCCB_ABORT; - return (0); + return 0; } } } } } - return (-1); + return -1; } /*--------------------------------------------------------------------- @@ -1726,12 +1726,12 @@ static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard) ioport = ((struct sccb_card *)pCurrCard)->ioPort; if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) { - return (1); + return 1; } else - return (0); + return 0; } /*--------------------------------------------------------------------- @@ -1783,7 +1783,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) if (result) { MENABLE_INT(ioport); - return (result); + return result; } } @@ -1997,7 +1997,7 @@ static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) MENABLE_INT(ioport); - return (0); + return 0; } /*--------------------------------------------------------------------- @@ -2092,7 +2092,7 @@ static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, FPT_scini(p_card, pCurrCard->ourId, 0); - return (0xFF); + return 0xFF; } else if (p_int & FIFO) { @@ -2150,7 +2150,7 @@ static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, WRW_HARPOON((p_port + hp_intstat), SCAM_SEL); } - return (0x00); + return 0x00; } /*--------------------------------------------------------------------- @@ -2295,12 +2295,12 @@ static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB) } if (TimeOutLoop > 20000) { WRW_HARPOON((port + hp_intstat), PARITY); - return (message); + return message; } if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) != S_MSGI_PH) { WRW_HARPOON((port + hp_intstat), PARITY); - return (message); + return message; } WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); @@ -2315,7 +2315,7 @@ static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB) WR_HARPOON(port + hp_xferstat, 0); WR_HARPOON(port + hp_fiforead, 0); WR_HARPOON(port + hp_fifowrite, 0); - return (message); + return message; } /*--------------------------------------------------------------------- @@ -3219,14 +3219,14 @@ static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, (AUTO_IMMED + CMD_ONLY_STRT)); } - return (1); + return 1; } else { currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED; currTar_Info->TarEEValue &= ~EE_SYNC_MASK; - return (0); + return 0; } } @@ -3431,7 +3431,7 @@ static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card) ~(unsigned char)TAR_WIDE_MASK) | (unsigned char)WIDE_ENABLED); - return (1); + return 1; } else { @@ -3441,7 +3441,7 @@ static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card) WIDE_NEGOCIATED); currTar_Info->TarEEValue &= ~EE_WIDE_SCSI; - return (0); + return 0; } } @@ -5155,11 +5155,11 @@ static unsigned char FPT_busMstrTimeOut(unsigned long p_port) RD_HARPOON(p_port + hp_int_status); /*Clear command complete */ if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) { - return (1); + return 1; } else { - return (0); + return 0; } } @@ -5721,10 +5721,10 @@ static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type) } if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) - return (0); + return 0; if (RD_HARPOON(p_port + hp_scsidata_0) != 00) - return (0); + return 0; WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY)); @@ -5734,7 +5734,7 @@ static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type) WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig) & ~SCSI_BSY)); - return (0); + return 0; } WR_HARPOON(p_port + hp_scsisig, @@ -5745,7 +5745,7 @@ static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type) WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig) & ~(SCSI_BSY | SCSI_SEL))); - return (0); + return 0; } } @@ -5764,7 +5764,7 @@ static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type) FPT_Wait(p_port, TO_250ms); - return (1); + return 1; } /*--------------------------------------------------------------------- @@ -5956,7 +5956,7 @@ static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data) FPT_scwirod(p_port, BIT(6)); /*Wait for DB6 to be released. */ - return (ret_data); + return ret_data; } /*--------------------------------------------------------------------- @@ -5994,22 +5994,22 @@ static unsigned char FPT_scsendi(unsigned long p_port, } if ((ret_data & 0x1C) == 0x10) - return (0x00); /*End of isolation stage, we won! */ + return 0x00; /*End of isolation stage, we won! */ if (ret_data & 0x1C) - return (0xFF); + return 0xFF; if ((defer) && (!(ret_data & 0x1F))) - return (0x01); /*End of isolation stage, we lost. */ + return 0x01; /*End of isolation stage, we lost. */ } /*bit loop */ } /*byte loop */ if (defer) - return (0x01); /*We lost */ + return 0x01; /*We lost */ else - return (0); /*We WON! Yeeessss! */ + return 0; /*We WON! Yeeessss! */ } /*--------------------------------------------------------------------- @@ -6034,7 +6034,7 @@ static unsigned char FPT_sciso(unsigned long p_port, ret_data = FPT_scxferc(p_port, 0); if (ret_data & 0xFC) - return (0xFF); + return 0xFF; else { @@ -6056,9 +6056,9 @@ static unsigned char FPT_sciso(unsigned long p_port, } */ if (byte_cnt) - return (0x00); + return 0x00; else - return (0xFF); + return 0xFF; } } /*bit loop */ @@ -6067,7 +6067,7 @@ static unsigned char FPT_sciso(unsigned long p_port, } /*byte loop */ - return (0); + return 0; } /*--------------------------------------------------------------------- @@ -6142,10 +6142,10 @@ static unsigned char FPT_scvalq(unsigned char p_quintet) } if (p_quintet & 0x18) - return (0); + return 0; else - return (1); + return 1; } /*--------------------------------------------------------------------- @@ -6209,7 +6209,7 @@ static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id) (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE)); - return (0); /*No legacy device */ + return 0; /*No legacy device */ } else { @@ -6228,7 +6228,7 @@ static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id) (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE)); - return (1); /*Found one of them oldies! */ + return 1; /*Found one of them oldies! */ } } @@ -6342,7 +6342,7 @@ static unsigned char FPT_scmachid(unsigned char p_card, if (match) { FPT_scamInfo[i].state = ID_ASSIGNED; - return (i); + return i; } } @@ -6372,7 +6372,7 @@ static unsigned char FPT_scmachid(unsigned char p_card, if (FPT_BL_Card[p_card].pNvRamInfo == NULL) FPT_BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM; - return (match); + return match; } @@ -6387,7 +6387,7 @@ static unsigned char FPT_scmachid(unsigned char p_card, } if (p_id_string[0] & BIT(7)) { - return (CLR_PRIORITY); + return CLR_PRIORITY; } if (p_id_string[0] & BIT(5)) @@ -6416,7 +6416,7 @@ static unsigned char FPT_scmachid(unsigned char p_card, if (FPT_BL_Card[p_card].pNvRamInfo == NULL) FPT_BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM; - return (match); + return match; } @@ -6430,7 +6430,7 @@ static unsigned char FPT_scmachid(unsigned char p_card, } } - return (NO_ID_AVAIL); + return NO_ID_AVAIL; } /*--------------------------------------------------------------------- @@ -7181,7 +7181,7 @@ static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB, currTar_Info->TarSelQ_Cnt--; - return (1); + return 1; } else { @@ -7189,7 +7189,7 @@ static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB, } } - return (0); + return 0; } @@ -7416,14 +7416,14 @@ static unsigned short FPT_utilEERead(unsigned long p_port, ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr); if (ee_data1 == ee_data2) - return (ee_data1); + return ee_data1; ee_data1 = ee_data2; i++; } while (i < 4); - return (ee_data1); + return ee_data1; } /*--------------------------------------------------------------------- @@ -7471,7 +7471,7 @@ static unsigned short FPT_utilEEReadOrg(unsigned long p_port, WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */ WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */ - return (ee_data); + return ee_data; } /*--------------------------------------------------------------------- @@ -7559,7 +7559,7 @@ static unsigned short FPT_CalcCrc16(unsigned char buffer[]) ch >>= 1; } } - return (crc); + return crc; } static unsigned char FPT_CalcLrc(unsigned char buffer[]) @@ -7569,7 +7569,7 @@ static unsigned char FPT_CalcLrc(unsigned char buffer[]) lrc = 0; for (i = 0; i < ID_STRING_LENGTH; i++) lrc ^= buffer[i]; - return (lrc); + return lrc; } /* -- cgit v1.2.3-59-g8ed1b From a0b6b6e5308d6ef70febfc3cfd5488717809b3e4 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 9 Mar 2006 14:35:13 +0000 Subject: [SCSI] Make sgiwd93_detect and sgiwd93_detect static. Nothing outside sgiwd93.c references them. Signed-off-by: Ralf Baechle Signed-off-by: James Bottomley --- drivers/scsi/sgiwd93.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c index bf2ceb54354c..7cd366fcc571 100644 --- a/drivers/scsi/sgiwd93.c +++ b/drivers/scsi/sgiwd93.c @@ -265,7 +265,7 @@ out_unregister: return NULL; } -int __init sgiwd93_detect(struct scsi_host_template *SGIblows) +static int __init sgiwd93_detect(struct scsi_host_template *SGIblows) { int found = 0; @@ -288,7 +288,7 @@ int __init sgiwd93_detect(struct scsi_host_template *SGIblows) return found; } -int sgiwd93_release(struct Scsi_Host *instance) +static int sgiwd93_release(struct Scsi_Host *instance) { struct ip22_hostdata *hdata = HDATA(instance); int irq = 0; -- cgit v1.2.3-59-g8ed1b From 93f56089898a1b27fc0c89b5c1c748291353f679 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 9 Mar 2006 10:21:27 -0500 Subject: [SCSI] fix two leaks in scsi_alloc_sdev failure paths If the scsi_alloc_queue or the slave_alloc calls in scsi_alloc_device fail, we forget to release the locally allocated sdev on the failure path. Coverity #609 Signed-off-by: Dave Jones Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index be14f9d82fde..5d4ca87af3df 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -251,6 +251,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, /* release fn is set up in scsi_sysfs_device_initialise, so * have to free and put manually here */ put_device(&starget->dev); + kfree(sdev); goto out; } -- cgit v1.2.3-59-g8ed1b From ea5b6382fde00e0dbcd0de2e4aa2fd15705e5fc3 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Thu, 9 Mar 2006 14:27:08 -0800 Subject: [SCSI] qla2xxx: Convert IS_QLA*() defines to bit-operations. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 115 ++++++++++++++-------------------------- drivers/scsi/qla2xxx/qla_init.c | 1 + drivers/scsi/qla2xxx/qla_os.c | 49 +++++++++++++++++ drivers/scsi/qla2xxx/qla_sup.c | 5 -- 4 files changed, 89 insertions(+), 81 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 2e16f3285d5f..00b7e82b99b3 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -31,82 +31,6 @@ #include #include -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) -#if defined(CONFIG_SCSI_QLA21XX) || defined(CONFIG_SCSI_QLA21XX_MODULE) -#define IS_QLA2100(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100) -#else -#define IS_QLA2100(ha) 0 -#endif - -#if defined(CONFIG_SCSI_QLA22XX) || defined(CONFIG_SCSI_QLA22XX_MODULE) -#define IS_QLA2200(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2200) -#else -#define IS_QLA2200(ha) 0 -#endif - -#if defined(CONFIG_SCSI_QLA2300) || defined(CONFIG_SCSI_QLA2300_MODULE) -#define IS_QLA2300(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2300) -#define IS_QLA2312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2312) -#else -#define IS_QLA2300(ha) 0 -#define IS_QLA2312(ha) 0 -#endif - -#if defined(CONFIG_SCSI_QLA2322) || defined(CONFIG_SCSI_QLA2322_MODULE) -#define IS_QLA2322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322) -#else -#define IS_QLA2322(ha) 0 -#endif - -#if defined(CONFIG_SCSI_QLA6312) || defined(CONFIG_SCSI_QLA6312_MODULE) -#define IS_QLA6312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6312) -#define IS_QLA6322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6322) -#else -#define IS_QLA6312(ha) 0 -#define IS_QLA6322(ha) 0 -#endif - -#if defined(CONFIG_SCSI_QLA24XX) || defined(CONFIG_SCSI_QLA24XX_MODULE) -#define IS_QLA2422(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422) -#define IS_QLA2432(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432) -#else -#define IS_QLA2422(ha) 0 -#define IS_QLA2432(ha) 0 -#endif - -#if defined(CONFIG_SCSI_QLA25XX) || defined(CONFIG_SCSI_QLA25XX_MODULE) -#define IS_QLA2512(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2512) -#define IS_QLA2522(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2522) -#else -#define IS_QLA2512(ha) 0 -#define IS_QLA2522(ha) 0 -#endif - -#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ - -#define IS_QLA2100(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100) -#define IS_QLA2200(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2200) -#define IS_QLA2300(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2300) -#define IS_QLA2312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2312) -#define IS_QLA2322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322) -#define IS_QLA6312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6312) -#define IS_QLA6322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6322) -#define IS_QLA2422(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422) -#define IS_QLA2432(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432) -#define IS_QLA2512(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2512) -#define IS_QLA2522(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2522) -#endif - -#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ - IS_QLA6312(ha) || IS_QLA6322(ha)) -#define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha)) -#define IS_QLA25XX(ha) (IS_QLA2512(ha) || IS_QLA2522(ha)) - -/* - * Only non-ISP2[12]00 have extended addressing support in the firmware. - */ -#define HAS_EXTENDED_IDS(ha) (!IS_QLA2100(ha) && !IS_QLA2200(ha)) - /* * 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 @@ -2300,6 +2224,45 @@ typedef struct scsi_qla_host { #define SWITCH_FOUND BIT_3 #define DFLG_NO_CABLE BIT_4 + uint32_t device_type; +#define DT_ISP2100 BIT_0 +#define DT_ISP2200 BIT_1 +#define DT_ISP2300 BIT_2 +#define DT_ISP2312 BIT_3 +#define DT_ISP2322 BIT_4 +#define DT_ISP6312 BIT_5 +#define DT_ISP6322 BIT_6 +#define DT_ISP2422 BIT_7 +#define DT_ISP2432 BIT_8 +#define DT_ISP2512 BIT_9 +#define DT_ISP2522 BIT_10 +#define DT_ISP_LAST (DT_ISP2522 << 1) + +#define DT_OEM_001 BIT_29 +#define DT_ISP2200A BIT_30 +#define DT_EXTENDED_IDS BIT_31 + +#define DT_MASK(ha) ((ha)->device_type & (DT_ISP_LAST - 1)) +#define IS_QLA2100(ha) (DT_MASK(ha) & DT_ISP2100) +#define IS_QLA2200(ha) (DT_MASK(ha) & DT_ISP2200) +#define IS_QLA2300(ha) (DT_MASK(ha) & DT_ISP2300) +#define IS_QLA2312(ha) (DT_MASK(ha) & DT_ISP2312) +#define IS_QLA2322(ha) (DT_MASK(ha) & DT_ISP2322) +#define IS_QLA6312(ha) (DT_MASK(ha) & DT_ISP6312) +#define IS_QLA6322(ha) (DT_MASK(ha) & DT_ISP6322) +#define IS_QLA2422(ha) (DT_MASK(ha) & DT_ISP2422) +#define IS_QLA2432(ha) (DT_MASK(ha) & DT_ISP2432) +#define IS_QLA2512(ha) (DT_MASK(ha) & DT_ISP2512) +#define IS_QLA2522(ha) (DT_MASK(ha) & DT_ISP2522) + +#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ + IS_QLA6312(ha) || IS_QLA6322(ha)) +#define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha)) +#define IS_QLA25XX(ha) (IS_QLA2512(ha) || IS_QLA2522(ha)) + +#define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001) +#define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) + /* SRB cache. */ #define SRB_MIN_REQ 128 mempool_t *srb_mempool; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 634ee174bff2..f49eb06d0dbd 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -727,6 +727,7 @@ qla2x00_chip_diag(scsi_qla_host_t *ha) DEBUG3(printk("scsi(%ld): Found QLA2200A chip.\n", ha->host_no)); + ha->device_type |= DT_ISP2200A; ha->fw_transfer_size = 128; } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 43ca0d8ca384..757c4c43c453 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1146,6 +1146,52 @@ qla2x00_config_dma_addressing(scsi_qla_host_t *ha) pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK); } +static inline void +qla2x00_set_isp_flags(scsi_qla_host_t *ha) +{ + ha->device_type = DT_EXTENDED_IDS; + switch (ha->pdev->device) { + case PCI_DEVICE_ID_QLOGIC_ISP2100: + ha->device_type |= DT_ISP2100; + ha->device_type &= ~DT_EXTENDED_IDS; + break; + case PCI_DEVICE_ID_QLOGIC_ISP2200: + ha->device_type |= DT_ISP2200; + ha->device_type &= ~DT_EXTENDED_IDS; + break; + case PCI_DEVICE_ID_QLOGIC_ISP2300: + ha->device_type |= DT_ISP2300; + break; + case PCI_DEVICE_ID_QLOGIC_ISP2312: + ha->device_type |= DT_ISP2312; + break; + case PCI_DEVICE_ID_QLOGIC_ISP2322: + ha->device_type |= DT_ISP2322; + if (ha->pdev->subsystem_vendor == 0x1028 && + ha->pdev->subsystem_device == 0x0170) + ha->device_type |= DT_OEM_001; + break; + case PCI_DEVICE_ID_QLOGIC_ISP6312: + ha->device_type |= DT_ISP6312; + break; + case PCI_DEVICE_ID_QLOGIC_ISP6322: + ha->device_type |= DT_ISP6322; + break; + case PCI_DEVICE_ID_QLOGIC_ISP2422: + ha->device_type |= DT_ISP2422; + break; + case PCI_DEVICE_ID_QLOGIC_ISP2432: + ha->device_type |= DT_ISP2432; + break; + case PCI_DEVICE_ID_QLOGIC_ISP2512: + ha->device_type |= DT_ISP2512; + break; + case PCI_DEVICE_ID_QLOGIC_ISP2522: + ha->device_type |= DT_ISP2522; + break; + } +} + static int qla2x00_iospace_config(scsi_qla_host_t *ha) { @@ -1307,6 +1353,9 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->brd_info = brd_info; sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no); + /* Set ISP-type information. */ + qla2x00_set_isp_flags(ha); + /* Configure PCI I/O space */ ret = qla2x00_iospace_config(ha); if (ret) diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 8d68c463cd5b..8b0121dceb01 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -1191,11 +1191,6 @@ qla2x00_poll_flash(scsi_qla_host_t *ha, uint32_t addr, uint8_t poll_data, return status; } -#define IS_OEM_001(ha) \ - ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322 && \ - (ha)->pdev->subsystem_vendor == 0x1028 && \ - (ha)->pdev->subsystem_device == 0x0170) - /** * qla2x00_program_flash_address() - Programs a flash address * @ha: HA context -- cgit v1.2.3-59-g8ed1b From 044cc6c8ec311c4ddeebfcc31c53dea282de70b7 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Thu, 9 Mar 2006 14:27:13 -0800 Subject: [SCSI] qla2xxx: Add ISP54xx support. Chip is similar in form to our ISP24xx offering. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/ql2400.c | 27 +++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_attr.c | 8 ++++---- drivers/scsi/qla2xxx/qla_def.h | 12 +++++------ drivers/scsi/qla2xxx/qla_gs.c | 10 ++++------ drivers/scsi/qla2xxx/qla_init.c | 14 ++++++------- drivers/scsi/qla2xxx/qla_inline.h | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 6 +++--- drivers/scsi/qla2xxx/qla_isr.c | 16 +++++++-------- drivers/scsi/qla2xxx/qla_mbx.c | 42 +++++++++++++++++++-------------------- drivers/scsi/qla2xxx/qla_os.c | 18 ++++++++++------- include/linux/pci_ids.h | 2 ++ 11 files changed, 94 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/ql2400.c b/drivers/scsi/qla2xxx/ql2400.c index 6c7165f47e29..77914fcfa2bc 100644 --- a/drivers/scsi/qla2xxx/ql2400.c +++ b/drivers/scsi/qla2xxx/ql2400.c @@ -49,6 +49,18 @@ static struct qla_board_info qla_board_tbl[] = { .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[] = { @@ -66,6 +78,21 @@ static struct pci_device_id qla24xx_pci_tbl[] = { .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); diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 92b3e13e9061..2b9e329a240c 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -50,7 +50,7 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off, ha->host_no); vfree(ha->fw_dump_buffer); - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order); @@ -64,7 +64,7 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off, if ((ha->fw_dump || ha->fw_dumped) && !ha->fw_dump_reading) { ha->fw_dump_reading = 1; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) dump_size = FW_DUMP_SIZE_24XX; else { dump_size = FW_DUMP_SIZE_1M; @@ -138,7 +138,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off, return 0; /* Checksum NVRAM. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { uint32_t *iter; uint32_t chksum; @@ -750,7 +750,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) pfc_host_stat = &ha->fc_host_stat; memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, sizeof(stat_buf) / 4, mb_stat); } else { diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 00b7e82b99b3..e1a7769008ee 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2234,9 +2234,9 @@ typedef struct scsi_qla_host { #define DT_ISP6322 BIT_6 #define DT_ISP2422 BIT_7 #define DT_ISP2432 BIT_8 -#define DT_ISP2512 BIT_9 -#define DT_ISP2522 BIT_10 -#define DT_ISP_LAST (DT_ISP2522 << 1) +#define DT_ISP5422 BIT_9 +#define DT_ISP5432 BIT_10 +#define DT_ISP_LAST (DT_ISP5432 << 1) #define DT_OEM_001 BIT_29 #define DT_ISP2200A BIT_30 @@ -2252,13 +2252,13 @@ typedef struct scsi_qla_host { #define IS_QLA6322(ha) (DT_MASK(ha) & DT_ISP6322) #define IS_QLA2422(ha) (DT_MASK(ha) & DT_ISP2422) #define IS_QLA2432(ha) (DT_MASK(ha) & DT_ISP2432) -#define IS_QLA2512(ha) (DT_MASK(ha) & DT_ISP2512) -#define IS_QLA2522(ha) (DT_MASK(ha) & DT_ISP2522) +#define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422) +#define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432) #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ IS_QLA6312(ha) || IS_QLA6322(ha)) #define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha)) -#define IS_QLA25XX(ha) (IS_QLA2512(ha) || IS_QLA2522(ha)) +#define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha)) #define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001) #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index d620a8e8a614..2ebf259fccb2 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -126,7 +126,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt, DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n", ha->host_no, routine, ms_pkt->entry_status)); } else { - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) comp_status = ((struct ct_entry_24xx *)ms_pkt)->comp_status; else @@ -1200,7 +1200,7 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size) ms_iocb_entry_t *ms_pkt = ha->ms_iocb; struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { ct_pkt->cmd_byte_count = cpu_to_le32(req_size); ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; } else { @@ -1529,9 +1529,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); eiter->len = __constant_cpu_to_be16(4 + 4); - if (IS_QLA25XX(ha)) - eiter->a.sup_speed = __constant_cpu_to_be32(8); - else if (IS_QLA24XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) eiter->a.sup_speed = __constant_cpu_to_be32(4); else if (IS_QLA23XX(ha)) eiter->a.sup_speed = __constant_cpu_to_be32(2); @@ -1566,7 +1564,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); eiter->len = __constant_cpu_to_be16(4 + 4); - max_frame_size = IS_QLA24XX(ha) || IS_QLA25XX(ha) ? + max_frame_size = IS_QLA24XX(ha) || IS_QLA54XX(ha) ? (uint32_t) icb24->frame_payload_size: (uint32_t) ha->init_cb->frame_payload_size; eiter->a.max_frame_size = cpu_to_be32(max_frame_size); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f49eb06d0dbd..e6a2292a2892 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -387,7 +387,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha) /* Verify checksum of loaded RISC code. */ rval = qla2x00_verify_checksum(ha, - IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RISC_SADDRESS : + IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RISC_SADDRESS : *ha->brd_info->fw_info[0].fwstart); } @@ -822,7 +822,7 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) if (IS_QLA2100(ha) || IS_QLA2200(ha)) return; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) qla2x00_alloc_fw_dump(ha); /* Retrieve IOCB counts available to the firmware. */ @@ -2123,7 +2123,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) LIST_HEAD(new_fcports); /* If FL port exists, then SNS is present */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) loop_id = NPH_F_PORT; else loop_id = SNS_FL_PORT; @@ -2149,7 +2149,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) qla2x00_fdmi_register(ha); /* Ensure we are logged into the SNS. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) loop_id = NPH_SNS; else loop_id = SIMPLE_NAME_SERVER; @@ -2640,7 +2640,7 @@ qla2x00_device_resync(scsi_qla_host_t *ha) if (ql2xprocessrscn && !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && !IS_QLA6322(ha) && - !IS_QLA24XX(ha) && !IS_QLA25XX(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, @@ -3130,7 +3130,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) spin_lock_irqsave(&ha->hardware_lock, flags); - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) { + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) { /* * Disable SRAM, Instruction RAM and GP RAM * parity. @@ -3146,7 +3146,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) spin_lock_irqsave(&ha->hardware_lock, flags); - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) { + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) { /* Enable proper parity */ if (IS_QLA2300(ha)) /* SRAM parity */ diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index ecc3741a452e..45007ee58067 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -163,7 +163,7 @@ static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t); static inline int qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id) { - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) return (loop_id > NPH_LAST_HANDLE); return ((loop_id > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) || diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 6544b6d0891d..8f0f4a298357 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -466,7 +466,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, mrk->entry_type = MARKER_TYPE; mrk->modifier = type; if (type != MK_SYNC_ALL) { - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mrk24 = (struct mrk_entry_24xx *) mrk; mrk24->nport_handle = cpu_to_le16(loop_id); mrk24->lun[1] = LSB(lun); @@ -519,7 +519,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha) for (timer = HZ; timer; timer--) { if ((req_cnt + 2) >= ha->req_q_cnt) { /* Calculate number of free request entries. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) cnt = (uint16_t)RD_REG_DWORD( ®->isp24.req_q_out); else @@ -593,7 +593,7 @@ qla2x00_isp_cmd(scsi_qla_host_t *ha) ha->request_ring_ptr++; /* Set chip new ring index. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { WRT_REG_DWORD(®->isp24.req_q_in, ha->req_ring_index); RD_REG_DWORD_RELAXED(®->isp24.req_q_in); } else { diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index c15458c2bf32..2003dbb70579 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -343,7 +343,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ha->isp_ops.fw_dump(ha, 1); - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (mb[1] == 0 && mb[2] == 0) { qla_printk(KERN_ERR, ha, "Unrecoverable Hardware Error: adapter " @@ -521,7 +521,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) */ if (ql2xprocessrscn && !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && - !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(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] != @@ -638,7 +638,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) "scsi(%ld): [R|Z]IO update completion.\n", ha->host_no)); - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) qla24xx_process_response_queue(ha); else qla2x00_process_response_queue(ha); @@ -810,7 +810,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) sts = (sts_entry_t *) pkt; sts24 = (struct sts_entry_24xx *) pkt; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { comp_status = le16_to_cpu(sts24->comp_status); scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; } else { @@ -860,7 +860,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) fcport = sp->fcport; sense_len = rsp_info_len = resid_len = 0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + 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); @@ -878,7 +878,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) /* Check for any FCP transport errors. */ if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { /* Sense data lies beyond any FCP RESPONSE data. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) sense_data += rsp_info_len; if (rsp_info_len > 3 && rsp_info[3]) { DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " @@ -1117,7 +1117,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) case CS_TIMEOUT: cp->result = DID_BUS_BUSY << 16; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d:%d): TIMEOUT status detected " "0x%x-0x%x\n", ha->host_no, cp->device->channel, @@ -1197,7 +1197,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt) } /* Move sense data. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) host_to_fcp_swap(pkt->data, sizeof(pkt->data)); memcpy(sp->request_sense_ptr, pkt->data, sense_sz); DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 584cc2f6dd35..267435f17482 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -91,7 +91,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) spin_lock_irqsave(&ha->hardware_lock, flags); /* Load mailbox registers. */ - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) optr = (uint16_t __iomem *)®->isp24.mailbox0; else optr = (uint16_t __iomem *)MAILBOX_REG(ha, ®->isp, 0); @@ -155,7 +155,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); else WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); @@ -179,7 +179,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__, ha->host_no, command);) - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); else WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); @@ -237,7 +237,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) uint16_t mb0; uint32_t ictrl; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mb0 = RD_REG_WORD(®->isp24.mailbox0); ictrl = RD_REG_DWORD(®->isp24.ictrl); } else { @@ -334,7 +334,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; mcp->mb[8] = MSW(risc_addr); mcp->out_mb = MBX_8|MBX_0; @@ -348,7 +348,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, mcp->mb[6] = MSW(MSD(req_dma)); mcp->mb[7] = LSW(MSD(req_dma)); mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[4] = MSW(risc_code_size); mcp->mb[5] = LSW(risc_code_size); mcp->out_mb |= MBX_5|MBX_4; @@ -399,7 +399,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) mcp->mb[0] = MBC_EXECUTE_FIRMWARE; mcp->out_mb = MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[1] = MSW(risc_addr); mcp->mb[2] = LSW(risc_addr); mcp->mb[3] = 0; @@ -422,7 +422,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__, ha->host_no, rval, mcp->mb[0])); } else { - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { DEBUG11(printk("%s(%ld): done exchanges=%x.\n", __func__, ha->host_no, mcp->mb[1]);) } else { @@ -563,7 +563,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts) mcp->mb[3] = fwopts[3]; mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->in_mb |= MBX_1; } else { mcp->mb[10] = fwopts[10]; @@ -676,7 +676,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) mcp->mb[0] = MBC_VERIFY_CHECKSUM; mcp->out_mb = MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[1] = MSW(risc_addr); mcp->mb[2] = LSW(risc_addr); mcp->out_mb |= MBX_2|MBX_1; @@ -693,7 +693,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) if (rval != QLA_SUCCESS) { DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__, - ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA25XX(ha) ? + ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA54XX(ha) ? (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]));) } else { DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) @@ -751,7 +751,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr, /* Mask reserved bits. */ sts_entry->entry_status &= - IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RF_MASK_24XX :RF_MASK; + IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RF_MASK_24XX :RF_MASK; } return rval; @@ -1091,7 +1091,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE)); mcp->mb[0] = MBC_GET_PORT_DATABASE; - if (opt != 0 && !IS_QLA24XX(ha) && !IS_QLA25XX(ha)) + if (opt != 0 && !IS_QLA24XX(ha) && !IS_QLA54XX(ha)) mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; mcp->mb[2] = MSW(pd_dma); mcp->mb[3] = LSW(pd_dma); @@ -1099,7 +1099,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) mcp->mb[7] = LSW(MSD(pd_dma)); mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[1] = fcport->loop_id; mcp->mb[10] = opt; mcp->out_mb |= MBX_10|MBX_1; @@ -1112,7 +1112,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) mcp->mb[1] = fcport->loop_id << 8 | opt; mcp->out_mb |= MBX_1; } - mcp->buf_size = (IS_QLA24XX(ha) || IS_QLA25XX(ha) ? + mcp->buf_size = (IS_QLA24XX(ha) || IS_QLA54XX(ha) ? PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE); mcp->flags = MBX_DMA_IN; mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); @@ -1120,7 +1120,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) if (rval != QLA_SUCCESS) goto gpd_error_out; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { pd24 = (struct port_database_24xx *) pd; /* Check for logged in state. */ @@ -1337,7 +1337,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha) DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[0] = MBC_LIP_FULL_LOGIN; mcp->mb[1] = BIT_0; mcp->mb[2] = 0xff; @@ -1866,7 +1866,7 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma, mcp->mb[0] = MBC_GET_ID_LIST; mcp->out_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[2] = MSW(id_list_dma); mcp->mb[3] = LSW(id_list_dma); mcp->mb[6] = MSW(MSD(id_list_dma)); @@ -2057,7 +2057,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id, mcp->mb[7] = LSW(MSD(stat_buf_dma)); mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { mcp->mb[1] = loop_id; mcp->mb[4] = 0; mcp->mb[10] = 0; @@ -2324,7 +2324,7 @@ qla2x00_system_error(scsi_qla_host_t *ha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); @@ -2434,7 +2434,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *ha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 757c4c43c453..131614751196 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1183,11 +1183,11 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha) case PCI_DEVICE_ID_QLOGIC_ISP2432: ha->device_type |= DT_ISP2432; break; - case PCI_DEVICE_ID_QLOGIC_ISP2512: - ha->device_type |= DT_ISP2512; + case PCI_DEVICE_ID_QLOGIC_ISP5422: + ha->device_type |= DT_ISP5422; break; - case PCI_DEVICE_ID_QLOGIC_ISP2522: - ha->device_type |= DT_ISP2522; + case PCI_DEVICE_ID_QLOGIC_ISP5432: + ha->device_type |= DT_ISP5432; break; } } @@ -1433,7 +1433,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->gid_list_info_size = 6; if (IS_QLA2322(ha) || IS_QLA6322(ha)) ha->optrom_size = OPTROM_SIZE_2322; - } else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { host->max_id = MAX_TARGETS_2200; ha->mbx_count = MAILBOX_REGISTER_COUNT; ha->request_q_length = REQUEST_ENTRY_CNT_24XX; @@ -1559,7 +1559,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) spin_lock_irqsave(&ha->hardware_lock, flags); reg = ha->iobase; - if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT); WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT); } else { @@ -2631,7 +2631,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha) blob = &qla_fw_blobs[FW_ISP2322]; } else if (IS_QLA6312(ha) || IS_QLA6322(ha)) { blob = &qla_fw_blobs[FW_ISP63XX]; - } else if (IS_QLA24XX(ha)) { + } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { blob = &qla_fw_blobs[FW_ISP24XX]; } @@ -2687,6 +2687,10 @@ static struct pci_device_id qla2xxx_pci_tbl[] = { 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, }, { 0 }, }; MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 82b83da25d77..1afac931351e 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -852,6 +852,8 @@ #define PCI_DEVICE_ID_QLOGIC_ISP2432 0x2432 #define PCI_DEVICE_ID_QLOGIC_ISP2512 0x2512 #define PCI_DEVICE_ID_QLOGIC_ISP2522 0x2522 +#define PCI_DEVICE_ID_QLOGIC_ISP5422 0x5422 +#define PCI_DEVICE_ID_QLOGIC_ISP5432 0x5432 #define PCI_VENDOR_ID_CYRIX 0x1078 #define PCI_DEVICE_ID_CYRIX_5510 0x0000 -- cgit v1.2.3-59-g8ed1b From 48c02fde949f15920c0018d33d285fd39730d24b Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Thu, 9 Mar 2006 14:27:18 -0800 Subject: [SCSI] qla2xxx: Consolidate ISP63xx handling. As new 23xx firmware will accomidate ISP63xx types. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/Kconfig | 31 ++++++++++++------------------- drivers/scsi/qla2xxx/Makefile | 2 -- drivers/scsi/qla2xxx/ql2300.c | 12 ++++++++++++ drivers/scsi/qla2xxx/ql2322.c | 12 ++++++++++++ drivers/scsi/qla2xxx/qla_init.c | 4 ++++ drivers/scsi/qla2xxx/qla_os.c | 12 ++++-------- 6 files changed, 44 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 5758b2566d7f..ff40906c66f9 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig @@ -10,14 +10,13 @@ config SCSI_QLA_FC By default, firmware for the ISP parts will be loaded via the Firmware Loader interface. - ISP Firmware Filename - ---------- ----------------- - 21xx ql2100_fw.bin - 22xx ql2200_fw.bin - 2300, 2312 ql2300_fw.bin - 2322 ql2322_fw.bin - 6312, 6322 ql6312_fw.bin - 24xx ql2400_fw.bin + ISP Firmware Filename + ---------- ----------------- + 21xx ql2100_fw.bin + 22xx ql2200_fw.bin + 2300, 2312, 6312 ql2300_fw.bin + 2322, 6322 ql2322_fw.bin + 24xx ql2400_fw.bin Upon request, the driver caches the firmware image until the driver is unloaded. @@ -51,23 +50,17 @@ config SCSI_QLA22XX This driver supports the QLogic 22xx (ISP2200) host adapter family. config SCSI_QLA2300 - tristate " Build QLogic ISP2300 firmware-module" + tristate " Build QLogic ISP2300/ISP6312 firmware-module" depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE ---help--- - This driver supports the QLogic 2300 (ISP2300 and ISP2312) host - adapter family. + This driver supports the QLogic 2300 (ISP2300, ISP2312 and + ISP6312) host adapter family. config SCSI_QLA2322 - tristate " Build QLogic ISP2322 firmware-module" - depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE - ---help--- - This driver supports the QLogic 2322 (ISP2322) host adapter family. - -config SCSI_QLA6312 - tristate " Build QLogic ISP63xx firmware-module" + tristate " Build QLogic ISP2322/ISP6322 firmware-module" depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE ---help--- - This driver supports the QLogic 63xx (ISP6312 and ISP6322) host + This driver supports the QLogic 2322 (ISP2322 and ISP6322) host adapter family. config SCSI_QLA24XX diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index d028bc50ccf7..c8f670ee60b4 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile @@ -9,12 +9,10 @@ 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 -qla6312-y := ql6312.o ql6312_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_QLA6312) += qla2xxx.o qla6312.o obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o qla2400.o diff --git a/drivers/scsi/qla2xxx/ql2300.c b/drivers/scsi/qla2xxx/ql2300.c index fd2f4b795a8a..e7a93ddda79a 100644 --- a/drivers/scsi/qla2xxx/ql2300.c +++ b/drivers/scsi/qla2xxx/ql2300.c @@ -40,6 +40,11 @@ static struct qla_board_info qla_board_tbl[] = { .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[] = { @@ -57,6 +62,13 @@ static struct pci_device_id qla2300_pci_tbl[] = { .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); diff --git a/drivers/scsi/qla2xxx/ql2322.c b/drivers/scsi/qla2xxx/ql2322.c index c88a22c0d93a..3c8cafc12eee 100644 --- a/drivers/scsi/qla2xxx/ql2322.c +++ b/drivers/scsi/qla2xxx/ql2322.c @@ -52,6 +52,11 @@ static struct qla_board_info qla_board_tbl[] = { .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[] = { @@ -62,6 +67,13 @@ static struct pci_device_id qla2322_pci_tbl[] = { .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); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e6a2292a2892..d4389095b4bc 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1003,6 +1003,10 @@ qla2x00_update_fw_options(scsi_qla_host_t *ha) if (ha->flags.enable_led_scheme) ha->fw_options[2] |= BIT_12; + /* Detect ISP6312. */ + if (IS_QLA6312(ha)) + ha->fw_options[2] |= BIT_13; + /* Update firmware options. */ qla2x00_set_fw_options(ha, ha->fw_options); } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 131614751196..4dc08d94ebec 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2596,13 +2596,12 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) /* Firmware interface routines. */ -#define FW_BLOBS 6 +#define FW_BLOBS 5 #define FW_ISP21XX 0 #define FW_ISP22XX 1 #define FW_ISP2300 2 #define FW_ISP2322 3 -#define FW_ISP63XX 4 -#define FW_ISP24XX 5 +#define FW_ISP24XX 4 static DECLARE_MUTEX(qla_fw_lock); @@ -2611,7 +2610,6 @@ static struct fw_blob qla_fw_blobs[FW_BLOBS] = { { .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, }, { .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, }, { .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, }, - { .name = "ql6312_fw.bin", .segs = { 0x800, 0 }, }, { .name = "ql2400_fw.bin", }, }; @@ -2625,12 +2623,10 @@ qla2x00_request_firmware(scsi_qla_host_t *ha) blob = &qla_fw_blobs[FW_ISP21XX]; } else if (IS_QLA2200(ha)) { blob = &qla_fw_blobs[FW_ISP22XX]; - } else if (IS_QLA2300(ha) || IS_QLA2312(ha)) { + } else if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) { blob = &qla_fw_blobs[FW_ISP2300]; - } else if (IS_QLA2322(ha)) { + } else if (IS_QLA2322(ha) || IS_QLA6322(ha)) { blob = &qla_fw_blobs[FW_ISP2322]; - } else if (IS_QLA6312(ha) || IS_QLA6322(ha)) { - blob = &qla_fw_blobs[FW_ISP63XX]; } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { blob = &qla_fw_blobs[FW_ISP24XX]; } -- cgit v1.2.3-59-g8ed1b From 1328962eb4b00dd1cfd1ffb863b1612b08751768 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Thu, 9 Mar 2006 14:27:24 -0800 Subject: [SCSI] qla2xxx: NVRAM id-list updates. Resync with latest NVRAM subsystem ID list. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_devtbl.h | 219 ++++++++++++++------------------------ drivers/scsi/qla2xxx/qla_init.c | 6 +- 2 files changed, 80 insertions(+), 145 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_devtbl.h b/drivers/scsi/qla2xxx/qla_devtbl.h index 5109735dd891..a8fc0ffc7fc5 100644 --- a/drivers/scsi/qla2xxx/qla_devtbl.h +++ b/drivers/scsi/qla2xxx/qla_devtbl.h @@ -1,146 +1,81 @@ -#define QLA_MODEL_NAMES 0x44 +#define QLA_MODEL_NAMES 0x4A /* - * Adapter model names. + * Adapter model names and descriptions. */ -static char *qla2x00_model_name[QLA_MODEL_NAMES] = { - "QLA2340", /* 0x100 */ - "QLA2342", /* 0x101 */ - "QLA2344", /* 0x102 */ - "QCP2342", /* 0x103 */ - "QSB2340", /* 0x104 */ - "QSB2342", /* 0x105 */ - "QLA2310", /* 0x106 */ - "QLA2332", /* 0x107 */ - "QCP2332", /* 0x108 */ - "QCP2340", /* 0x109 */ - "QLA2342", /* 0x10a */ - "QCP2342", /* 0x10b */ - "QLA2350", /* 0x10c */ - "QLA2352", /* 0x10d */ - "QLA2352", /* 0x10e */ - "HPQ SVS", /* 0x10f */ - "HPQ SVS", /* 0x110 */ - " ", /* 0x111 */ - " ", /* 0x112 */ - " ", /* 0x113 */ - " ", /* 0x114 */ - "QLA2360", /* 0x115 */ - "QLA2362", /* 0x116 */ - "QLE2360", /* 0x117 */ - "QLE2362", /* 0x118 */ - "QLA200", /* 0x119 */ - "QLA200C", /* 0x11a */ - "QLA200P", /* 0x11b */ - "QLA200P", /* 0x11c */ - " ", /* 0x11d */ - " ", /* 0x11e */ - " ", /* 0x11f */ - " ", /* 0x120 */ - " ", /* 0x121 */ - " ", /* 0x122 */ - " ", /* 0x123 */ - " ", /* 0x124 */ - " ", /* 0x125 */ - " ", /* 0x126 */ - " ", /* 0x127 */ - " ", /* 0x128 */ - " ", /* 0x129 */ - " ", /* 0x12a */ - " ", /* 0x12b */ - " ", /* 0x12c */ - " ", /* 0x12d */ - " ", /* 0x12e */ - "QLA210", /* 0x12f */ - "EMC 250", /* 0x130 */ - "HP A7538A", /* 0x131 */ - "QLA210", /* 0x132 */ - "QLA2460", /* 0x133 */ - "QLA2462", /* 0x134 */ - "QMC2462", /* 0x135 */ - "QMC2462S", /* 0x136 */ - "QLE2460", /* 0x137 */ - "QLE2462", /* 0x138 */ - "QME2462", /* 0x139 */ - "QLA2440", /* 0x13a */ - "QLA2442", /* 0x13b */ - "QSM2442", /* 0x13c */ - "QSM2462", /* 0x13d */ - "QLE210", /* 0x13e */ - "QLE220", /* 0x13f */ - "QLA2460", /* 0x140 */ - "QLA2462", /* 0x141 */ - "QLE2460", /* 0x142 */ - "QLE2462" /* 0x143 */ -}; - -static char *qla2x00_model_desc[QLA_MODEL_NAMES] = { - "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x100 */ - "133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x101 */ - "133MHz PCI-X to 2Gb FC, Quad Channel", /* 0x102 */ - " ", /* 0x103 */ - " ", /* 0x104 */ - " ", /* 0x105 */ - " ", /* 0x106 */ - " ", /* 0x107 */ - " ", /* 0x108 */ - " ", /* 0x109 */ - " ", /* 0x10a */ - " ", /* 0x10b */ - "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x10c */ - "133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x10d */ - " ", /* 0x10e */ - "HPQ SVS HBA- Initiator device", /* 0x10f */ - "HPQ SVS HBA- Target device", /* 0x110 */ - " ", /* 0x111 */ - " ", /* 0x112 */ - " ", /* 0x113 */ - " ", /* 0x114 */ - "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x115 */ - "133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x116 */ - "PCI-Express to 2Gb FC, Single Channel", /* 0x117 */ - "PCI-Express to 2Gb FC, Dual Channel", /* 0x118 */ - "133MHz PCI-X to 2Gb FC Optical", /* 0x119 */ - "133MHz PCI-X to 2Gb FC Copper", /* 0x11a */ - "133MHz PCI-X to 2Gb FC SFP", /* 0x11b */ - "133MHz PCI-X to 2Gb FC SFP", /* 0x11c */ - " ", /* 0x11d */ - " ", /* 0x11e */ - " ", /* 0x11f */ - " ", /* 0x120 */ - " ", /* 0x121 */ - " ", /* 0x122 */ - " ", /* 0x123 */ - " ", /* 0x124 */ - " ", /* 0x125 */ - " ", /* 0x126 */ - " ", /* 0x127 */ - " ", /* 0x128 */ - " ", /* 0x129 */ - " ", /* 0x12a */ - " ", /* 0x12b */ - " ", /* 0x12c */ - " ", /* 0x12d */ - " ", /* 0x12e */ - "133MHz PCI-X to 2Gb FC SFF", /* 0x12f */ - "133MHz PCI-X to 2Gb FC SFF", /* 0x130 */ - "HP 1p2g QLA2340", /* 0x131 */ - "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x132 */ - "PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x133 */ - "PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x134 */ - "IBM eServer BC 4Gb FC Expansion Card", /* 0x135 */ - "IBM eServer BC 4Gb FC Expansion Card SFF", /* 0x136 */ - "PCI-Express to 4Gb FC, Single Channel", /* 0x137 */ - "PCI-Express to 4Gb FC, Dual Channel", /* 0x138 */ - "Dell PCI-Express to 4Gb FC, Dual Channel", /* 0x139 */ - "PCI-X 1.0 to 4Gb FC, Single Channel", /* 0x13a */ - "PCI-X 1.0 to 4Gb FC, Dual Channel", /* 0x13b */ - "Server I/O Module 4Gb FC, Single Channel", /* 0x13c */ - "Server I/O Module 4Gb FC, Single Channel", /* 0x13d */ - "PCI-Express to 2Gb FC, Single Channel", /* 0x13e */ - "PCI-Express to 4Gb FC, Single Channel", /* 0x13f */ - "Sun PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x140 */ - "Sun PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x141 */ - "Sun PCI-Express to 2Gb FC, Single Channel", /* 0x142 */ - "Sun PCI-Express to 4Gb FC, Single Channel" /* 0x143 */ +static char *qla2x00_model_name[QLA_MODEL_NAMES*2] = { + "QLA2340", "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x100 */ + "QLA2342", "133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x101 */ + "QLA2344", "133MHz PCI-X to 2Gb FC, Quad Channel", /* 0x102 */ + "QCP2342", "cPCI to 2Gb FC, Dual Channel", /* 0x103 */ + "QSB2340", "SBUS to 2Gb FC, Single Channel", /* 0x104 */ + "QSB2342", "SBUS to 2Gb FC, Dual Channel", /* 0x105 */ + "QLA2310", "Sun 66MHz PCI-X to 2Gb FC, Single Channel", /* 0x106 */ + "QLA2332", "Sun 66MHz PCI-X to 2Gb FC, Single Channel", /* 0x107 */ + "QCP2332", "Sun cPCI to 2Gb FC, Dual Channel", /* 0x108 */ + "QCP2340", "cPCI to 2Gb FC, Single Channel", /* 0x109 */ + "QLA2342", "Sun 133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x10a */ + "QCP2342", "Sun - cPCI to 2Gb FC, Dual Channel", /* 0x10b */ + "QLA2350", "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x10c */ + "QLA2352", "133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x10d */ + "QLA2352", "Sun 133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x10e */ + " ", " ", /* 0x10f */ + " ", " ", /* 0x110 */ + " ", " ", /* 0x111 */ + " ", " ", /* 0x112 */ + " ", " ", /* 0x113 */ + " ", " ", /* 0x114 */ + "QLA2360", "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x115 */ + "QLA2362", "133MHz PCI-X to 2Gb FC, Dual Channel", /* 0x116 */ + "QLE2360", "PCI-Express to 2Gb FC, Single Channel", /* 0x117 */ + "QLE2362", "PCI-Express to 2Gb FC, Dual Channel", /* 0x118 */ + "QLA200", "133MHz PCI-X to 2Gb FC Optical", /* 0x119 */ + " ", " ", /* 0x11a */ + " ", " ", /* 0x11b */ + "QLA200P", "133MHz PCI-X to 2Gb FC SFP", /* 0x11c */ + " ", " ", /* 0x11d */ + " ", " ", /* 0x11e */ + " ", " ", /* 0x11f */ + " ", " ", /* 0x120 */ + " ", " ", /* 0x121 */ + " ", " ", /* 0x122 */ + " ", " ", /* 0x123 */ + " ", " ", /* 0x124 */ + " ", " ", /* 0x125 */ + " ", " ", /* 0x126 */ + " ", " ", /* 0x127 */ + " ", " ", /* 0x128 */ + " ", " ", /* 0x129 */ + " ", " ", /* 0x12a */ + " ", " ", /* 0x12b */ + " ", " ", /* 0x12c */ + " ", " ", /* 0x12d */ + " ", " ", /* 0x12e */ + "QLA210", "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x12f */ + "EMC 250", "133MHz PCI-X to 2Gb FC, Single Channel", /* 0x130 */ + "HP A7538A", "HP 1p2g PCI-X to 2Gb FC, Single Channel", /* 0x131 */ + "QLA210", "Sun 133MHz PCI-X to 2Gb FC, Single Channel", /* 0x132 */ + "QLA2460", "PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x133 */ + "QLA2462", "PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x134 */ + "QMC2462", "IBM eServer BC 4Gb FC Expansion Card", /* 0x135 */ + "QMC2462S", "IBM eServer BC 4Gb FC Expansion Card SFF", /* 0x136 */ + "QLE2460", "PCI-Express to 4Gb FC, Single Channel", /* 0x137 */ + "QLE2462", "PCI-Express to 4Gb FC, Dual Channel", /* 0x138 */ + "QME2462", "Dell BS PCI-Express to 4Gb FC, Dual Channel", /* 0x139 */ + " ", " ", /* 0x13a */ + " ", " ", /* 0x13b */ + " ", " ", /* 0x13c */ + "QEM2462", "Sun Server I/O Module 4Gb FC, Dual Channel", /* 0x13d */ + "QLE210", "PCI-Express to 2Gb FC, Single Channel", /* 0x13e */ + "QLE220", "PCI-Express to 4Gb FC, Single Channel", /* 0x13f */ + "QLA2460", "Sun PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x140 */ + "QLA2462", "Sun PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x141 */ + "QLE2460", "Sun PCI-Express to 2Gb FC, Single Channel", /* 0x142 */ + "QLE2462", "Sun PCI-Express to 4Gb FC, Single Channel", /* 0x143 */ + "QEM2462" "Server I/O Module 4Gb FC, Dual Channel", /* 0x144 */ + "QLE2440", "PCI-Express to 4Gb FC, Single Channel", /* 0x145 */ + "QLE2464", "PCI-Express to 4Gb FC, Quad Channel", /* 0x146 */ + "QLA2440", "PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x147 */ + " ", " ", /* 0x148 */ + "QLA2340", "Sun 133MHz PCI-X to 2Gb FC, Single Channel", /* 0x149 */ }; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index d4389095b4bc..3bc3e1749f32 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1505,9 +1505,9 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) index = (ha->pdev->subsystem_device & 0xff); if (index < QLA_MODEL_NAMES) { strcpy(ha->model_number, - qla2x00_model_name[index]); + qla2x00_model_name[index * 2]); ha->model_desc = - qla2x00_model_desc[index]; + qla2x00_model_name[index * 2 + 1]; } else { strcpy(ha->model_number, "QLA23xx"); } @@ -3373,7 +3373,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) index = (ha->pdev->subsystem_device & 0xff); if (index < QLA_MODEL_NAMES) - ha->model_desc = qla2x00_model_desc[index]; + ha->model_desc = qla2x00_model_name[index * 2 + 1]; } else strcpy(ha->model_number, "QLA2462"); -- cgit v1.2.3-59-g8ed1b From fdbc6833c53a1c2ec2b122cd53e69e6136dcc774 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Thu, 9 Mar 2006 14:27:29 -0800 Subject: [SCSI] qla2xxx: Correct swing/emphasis settings on ISP24xx. Reserved-bit 15 must set when updating the swing/emphasis values. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 267435f17482..85c83e0027ff 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2406,9 +2406,9 @@ qla2x00_set_serdes_params(scsi_qla_host_t *ha, uint16_t sw_em_1g, mcp->mb[0] = MBC_SERDES_PARAMS; mcp->mb[1] = BIT_0; - mcp->mb[2] = sw_em_1g; - mcp->mb[3] = sw_em_2g; - mcp->mb[4] = sw_em_4g; + mcp->mb[2] = sw_em_1g | BIT_15; + mcp->mb[3] = sw_em_2g | BIT_15; + mcp->mb[4] = sw_em_4g | BIT_15; mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_0; mcp->tov = 30; -- cgit v1.2.3-59-g8ed1b From 6f6417905cf272337a9762e1f92a1fffa651fcd3 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Thu, 9 Mar 2006 14:27:34 -0800 Subject: [SCSI] qla2xxx: Add VPD sysfs attribute. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 57 +++++++++++++++++++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_def.h | 2 ++ drivers/scsi/qla2xxx/qla_fw.h | 2 +- drivers/scsi/qla2xxx/qla_init.c | 6 ++++- 4 files changed, 65 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 2b9e329a240c..488b3d16427b 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -308,6 +308,61 @@ static struct bin_attribute sysfs_optrom_ctl_attr = { .write = qla2x00_sysfs_write_optrom_ctl, }; +static ssize_t +qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off, + size_t count) +{ + struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct device, kobj))); + unsigned long flags; + + if (!capable(CAP_SYS_ADMIN) || off != 0) + return 0; + + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + return -ENOTSUPP; + + /* Read NVRAM. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return ha->vpd_size; +} + +static ssize_t +qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off, + size_t count) +{ + struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct device, kobj))); + unsigned long flags; + + if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) + return 0; + + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + return -ENOTSUPP; + + /* Write NVRAM. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return count; +} + +static struct bin_attribute sysfs_vpd_attr = { + .attr = { + .name = "vpd", + .mode = S_IRUSR | S_IWUSR, + .owner = THIS_MODULE, + }, + .size = 0, + .read = qla2x00_sysfs_read_vpd, + .write = qla2x00_sysfs_write_vpd, +}; + void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) { @@ -318,6 +373,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_ctl_attr); + sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr); } void @@ -330,6 +386,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_ctl_attr); + sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr); if (ha->beacon_blink_led == 1) ha->isp_ops.beacon_off(ha); diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index e1a7769008ee..20798f93d8da 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2344,6 +2344,8 @@ typedef struct scsi_qla_host { /* NVRAM configuration data */ uint16_t nvram_size; uint16_t nvram_base; + uint16_t vpd_size; + uint16_t vpd_base; uint16_t loop_reset_delay; uint8_t retry_count; diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 9fb562aa4acc..1ee58ad2f4dd 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -759,7 +759,7 @@ struct device_reg_24xx { #define FA_NVRAM_FUNC0_ADDR 0x80 #define FA_NVRAM_FUNC1_ADDR 0x180 -#define FA_NVRAM_VPD_SIZE 0x80 +#define FA_NVRAM_VPD_SIZE 0x200 #define FA_NVRAM_VPD0_ADDR 0x00 #define FA_NVRAM_VPD1_ADDR 0x100 /* diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3bc3e1749f32..71b6bcc181f9 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3263,8 +3263,12 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) /* Determine NVRAM starting address. */ ha->nvram_size = sizeof(struct nvram_24xx); ha->nvram_base = FA_NVRAM_FUNC0_ADDR; - if (PCI_FUNC(ha->pdev->devfn)) + ha->vpd_size = FA_NVRAM_VPD_SIZE; + ha->vpd_base = FA_NVRAM_VPD0_ADDR; + if (PCI_FUNC(ha->pdev->devfn)) { ha->nvram_base = FA_NVRAM_FUNC1_ADDR; + ha->vpd_base = FA_NVRAM_VPD1_ADDR; + } /* Get NVRAM data and calculate checksum. */ dptr = (uint32_t *)nv; -- cgit v1.2.3-59-g8ed1b From 4a59f71d7f0d6dd433fd509584352cdd7c62e877 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Thu, 9 Mar 2006 14:27:39 -0800 Subject: [SCSI] qla2xxx: Further restrict ZIO mode support. Only support ZIO mode 6 on specific ISP types. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 17 +++++------------ drivers/scsi/qla2xxx/qla_def.h | 3 ++- drivers/scsi/qla2xxx/qla_init.c | 4 ++++ drivers/scsi/qla2xxx/qla_os.c | 5 +++++ 4 files changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 488b3d16427b..fee0c493775b 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -507,9 +507,6 @@ qla2x00_zio_show(struct class_device *cdev, char *buf) int len = 0; switch (ha->zio_mode) { - case QLA_ZIO_MODE_5: - len += snprintf(buf + len, PAGE_SIZE-len, "Mode 5\n"); - break; case QLA_ZIO_MODE_6: len += snprintf(buf + len, PAGE_SIZE-len, "Mode 6\n"); break; @@ -527,20 +524,16 @@ qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count) int val = 0; uint16_t zio_mode; + if (!IS_ZIO_SUPPORTED(ha)) + return -ENOTSUPP; + if (sscanf(buf, "%d", &val) != 1) return -EINVAL; - switch (val) { - case 1: - zio_mode = QLA_ZIO_MODE_5; - break; - case 2: + if (val) zio_mode = QLA_ZIO_MODE_6; - break; - default: + else zio_mode = QLA_ZIO_DISABLED; - break; - } /* Update per-hba values and queue a reset. */ if (zio_mode != QLA_ZIO_DISABLED || ha->zio_mode != QLA_ZIO_DISABLED) { diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 20798f93d8da..53508f3c4ae9 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -762,7 +762,6 @@ typedef struct { #define PD_STATE_WAIT_PORT_LOGOUT_ACK 11 -#define QLA_ZIO_MODE_5 (BIT_2 | BIT_0) #define QLA_ZIO_MODE_6 (BIT_2 | BIT_1) #define QLA_ZIO_DISABLED 0 #define QLA_ZIO_DEFAULT_TIMER 2 @@ -2238,6 +2237,7 @@ typedef struct scsi_qla_host { #define DT_ISP5432 BIT_10 #define DT_ISP_LAST (DT_ISP5432 << 1) +#define DT_ZIO_SUPPORTED BIT_28 #define DT_OEM_001 BIT_29 #define DT_ISP2200A BIT_30 #define DT_EXTENDED_IDS BIT_31 @@ -2260,6 +2260,7 @@ typedef struct scsi_qla_host { #define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha)) #define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha)) +#define IS_ZIO_SUPPORTED(ha) ((ha)->device_type & DT_ZIO_SUPPORTED) #define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001) #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 71b6bcc181f9..ebc7c2498067 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1659,6 +1659,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) ~(BIT_3 | BIT_2 | BIT_1 | BIT_0); ha->flags.process_response_queue = 0; if (ha->zio_mode != QLA_ZIO_DISABLED) { + ha->zio_mode = QLA_ZIO_MODE_6; + DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer " "delay (%d us).\n", ha->host_no, ha->zio_mode, ha->zio_timer * 100)); @@ -3474,6 +3476,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); ha->flags.process_response_queue = 0; if (ha->zio_mode != QLA_ZIO_DISABLED) { + ha->zio_mode = QLA_ZIO_MODE_6; + DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay " "(%d us).\n", ha->host_no, ha->zio_mode, ha->zio_timer * 100)); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 4dc08d94ebec..0fc89ac6a51b 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1161,12 +1161,15 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha) break; case PCI_DEVICE_ID_QLOGIC_ISP2300: ha->device_type |= DT_ISP2300; + ha->device_type |= DT_ZIO_SUPPORTED; break; case PCI_DEVICE_ID_QLOGIC_ISP2312: ha->device_type |= DT_ISP2312; + ha->device_type |= DT_ZIO_SUPPORTED; break; case PCI_DEVICE_ID_QLOGIC_ISP2322: ha->device_type |= DT_ISP2322; + ha->device_type |= DT_ZIO_SUPPORTED; if (ha->pdev->subsystem_vendor == 0x1028 && ha->pdev->subsystem_device == 0x0170) ha->device_type |= DT_OEM_001; @@ -1179,9 +1182,11 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha) break; case PCI_DEVICE_ID_QLOGIC_ISP2422: ha->device_type |= DT_ISP2422; + ha->device_type |= DT_ZIO_SUPPORTED; break; case PCI_DEVICE_ID_QLOGIC_ISP2432: ha->device_type |= DT_ISP2432; + ha->device_type |= DT_ZIO_SUPPORTED; break; case PCI_DEVICE_ID_QLOGIC_ISP5422: ha->device_type |= DT_ISP5422; -- cgit v1.2.3-59-g8ed1b From 9a52a57cb9d247fc1cea018fd3f4421f8fd6642a Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Thu, 9 Mar 2006 14:27:44 -0800 Subject: [SCSI] qla2xxx: Correct FCAL login retry logic for ISP24xx. ISP24XX FW does not support Mbx 0x74 ie Login Local Port. Added the equivalent code for ISP24XX ie to relogin in non fabric case for ISP24XX use login iocb. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gbl.h | 5 +++-- drivers/scsi/qla2xxx/qla_init.c | 4 ++-- drivers/scsi/qla2xxx/qla_mbx.c | 11 ++++++++--- drivers/scsi/qla2xxx/qla_os.c | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index e897eadf0362..91e83e2c1eb8 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -42,7 +42,7 @@ extern int qla2x00_loop_resync(scsi_qla_host_t *); extern int qla2x00_find_new_loop_id(scsi_qla_host_t *, fc_port_t *); extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *); -extern int qla2x00_local_device_login(scsi_qla_host_t *, uint16_t); +extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *); extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t); @@ -166,7 +166,8 @@ qla24xx_login_fabric(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t, uint16_t *, uint8_t); extern int -qla2x00_login_local_device(scsi_qla_host_t *, uint16_t, uint16_t *, uint8_t); +qla2x00_login_local_device(scsi_qla_host_t *, fc_port_t *, uint16_t *, + uint8_t); extern int qla2x00_fabric_logout(scsi_qla_host_t *, uint16_t, uint8_t, uint8_t, uint8_t); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ebc7c2498067..89a3fc0595bb 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2888,13 +2888,13 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, * 3 - Fatal error */ int -qla2x00_local_device_login(scsi_qla_host_t *ha, uint16_t loop_id) +qla2x00_local_device_login(scsi_qla_host_t *ha, fc_port_t *fcport) { int rval; uint16_t mb[MAILBOX_REGISTER_COUNT]; memset(mb, 0, sizeof(mb)); - rval = qla2x00_login_local_device(ha, loop_id, mb, BIT_0); + rval = qla2x00_login_local_device(ha, fcport, mb, BIT_0); if (rval == QLA_SUCCESS) { /* Interrogate mailbox registers for any errors */ if (mb[0] == MBS_COMMAND_ERROR) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 85c83e0027ff..d6cb3bd1a29a 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1631,20 +1631,25 @@ qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, * */ int -qla2x00_login_local_device(scsi_qla_host_t *ha, uint16_t loop_id, +qla2x00_login_local_device(scsi_qla_host_t *ha, fc_port_t *fcport, uint16_t *mb_ret, uint8_t opt) { int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + return qla24xx_login_fabric(ha, fcport->loop_id, + fcport->d_id.b.domain, fcport->d_id.b.area, + fcport->d_id.b.al_pa, mb_ret, opt); + DEBUG3(printk("%s(%ld): entered.\n", __func__, ha->host_no);) mcp->mb[0] = MBC_LOGIN_LOOP_PORT; if (HAS_EXTENDED_IDS(ha)) - mcp->mb[1] = loop_id; + mcp->mb[1] = fcport->loop_id; else - mcp->mb[1] = loop_id << 8; + mcp->mb[1] = fcport->loop_id << 8; mcp->mb[2] = opt; mcp->out_mb = MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 0fc89ac6a51b..029bbf461bb2 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2295,7 +2295,7 @@ qla2x00_do_dpc(void *data) } else status = qla2x00_local_device_login( - ha, fcport->loop_id); + ha, fcport); if (status == QLA_SUCCESS) { fcport->old_loop_id = fcport->loop_id; -- cgit v1.2.3-59-g8ed1b From d584486a1cc9714d5de8dc0a04c2b1f023fbb82a Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 9 Mar 2006 14:31:47 -0800 Subject: [SCSI] qla2xxx: Remove legacy ISP6312 firmware loader. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/ql6312.c | 101 - drivers/scsi/qla2xxx/ql6312_fw.c | 7078 -------------------------------------- 2 files changed, 7179 deletions(-) delete mode 100644 drivers/scsi/qla2xxx/ql6312.c delete mode 100644 drivers/scsi/qla2xxx/ql6312_fw.c (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/ql6312.c b/drivers/scsi/qla2xxx/ql6312.c deleted file mode 100644 index de55397f6f4c..000000000000 --- a/drivers/scsi/qla2xxx/ql6312.c +++ /dev/null @@ -1,101 +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[] = "qla6312"; - -extern unsigned char fw2300flx_version[]; -extern unsigned char fw2300flx_version_str[]; -extern unsigned short fw2300flx_addr01; -extern unsigned short fw2300flx_code01[]; -extern unsigned short fw2300flx_length01; - -static struct qla_fw_info qla_fw_tbl[] = { - { - .addressing = FW_INFO_ADDR_NORMAL, - .fwcode = &fw2300flx_code01[0], - .fwlen = &fw2300flx_length01, - .fwstart = &fw2300flx_addr01, - }, - { FW_INFO_ADDR_NOMORE, }, -}; - -static struct qla_board_info qla_board_tbl[] = { - { - .drv_name = qla_driver_name, - .isp_name = "ISP6312", - .fw_info = qla_fw_tbl, - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP6322", - .fw_info = qla_fw_tbl, - }, -}; - -static struct pci_device_id qla6312_pci_tbl[] = { - { - .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[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, qla6312_pci_tbl); - -static int __devinit -qla6312_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 -qla6312_remove_one(struct pci_dev *pdev) -{ - qla2x00_remove_one(pdev); -} - -static struct pci_driver qla6312_pci_driver = { - .name = "qla6312", - .id_table = qla6312_pci_tbl, - .probe = qla6312_probe_one, - .remove = __devexit_p(qla6312_remove_one), -}; - -static int __init -qla6312_init(void) -{ - return pci_module_init(&qla6312_pci_driver); -} - -static void __exit -qla6312_exit(void) -{ - pci_unregister_driver(&qla6312_pci_driver); -} - -module_init(qla6312_init); -module_exit(qla6312_exit); - -MODULE_AUTHOR("QLogic Corporation"); -MODULE_DESCRIPTION("QLogic ISP63xx FC-SCSI Host Bus Adapter driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql6312_fw.c b/drivers/scsi/qla2xxx/ql6312_fw.c deleted file mode 100644 index 5bb837052ef1..000000000000 --- a/drivers/scsi/qla2xxx/ql6312_fw.c +++ /dev/null @@ -1,7078 +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.18 (12:07 Sep 20, 2005) - */ - -#ifdef UNIQUE_FW_NAME -unsigned short fw2300flx_version = 3*1024+3; -#else -unsigned short risc_code_version = 3*1024+3; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned char fw2300flx_version_str[] = {3, 3,18}; -#else -unsigned char firmware_version[] = {3, 3,18}; -#endif - -#ifdef UNIQUE_FW_NAME -#define fw2300flx_VERSION_STRING "3.03.18" -#else -#define FW_VERSION_STRING "3.03.18" -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2300flx_addr01 = 0x0800 ; -#else -unsigned short risc_code_addr01 = 0x0800 ; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2300flx_code01[] = { -#else -unsigned short risc_code01[] = { -#endif - 0x0470, 0x0000, 0x0000, 0xdbb7, 0x0000, 0x0003, 0x0003, 0x0012, - 0x0317, 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, 0x2e31, 0x3820, 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, 0x2c06, 0x2051, 0x1800, 0x2a70, 0x20e1, - 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e7b, 0x2029, - 0x2480, 0x2031, 0xffff, 0x2039, 0x2450, 0x2021, 0x0050, 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, 0x756a, 0x766e, 0x7766, 0x7472, 0x7476, - 0x00e6, 0x2071, 0x1aa2, 0x2472, 0x00ee, 0x20a1, 0x1cd0, 0x716c, - 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x000f, 0x2001, 0x0001, - 0x9112, 0x900e, 0x21a8, 0x4104, 0x8211, 0x1de0, 0x716c, 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, 0x0f4f, 0x080c, - 0x5e3d, 0x080c, 0x9f80, 0x080c, 0x1106, 0x080c, 0x12fe, 0x080c, - 0x1a75, 0x080c, 0x0d88, 0x080c, 0x108b, 0x080c, 0x32f3, 0x080c, - 0x748e, 0x080c, 0x6784, 0x080c, 0x8194, 0x080c, 0x22b3, 0x080c, - 0x84a5, 0x080c, 0x7b18, 0x080c, 0x20df, 0x080c, 0x2213, 0x080c, - 0x22a8, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004, 0x091d, 0x7880, - 0x9086, 0x0002, 0x1190, 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, - 0x0010, 0x0e04, 0x0911, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x11e6, 0x2071, 0x1800, 0x7003, - 0x0000, 0x2071, 0x1800, 0x7000, 0x908e, 0x0003, 0x1168, 0x080c, - 0x4adc, 0x080c, 0x331a, 0x080c, 0x74f6, 0x080c, 0x6c82, 0x080c, - 0x81bd, 0x080c, 0x2b13, 0x0c68, 0x000b, 0x0c88, 0x0940, 0x0941, - 0x0ad8, 0x093e, 0x0b8f, 0x0d87, 0x0d87, 0x0d87, 0x080c, 0x0df6, - 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0x9086, 0x0001, - 0x1904, 0x0aab, 0x080c, 0x0ebd, 0x080c, 0x717e, 0x0150, 0x080c, - 0x71a1, 0x15a0, 0x2079, 0x0100, 0x7828, 0x9085, 0x1800, 0x782a, - 0x0468, 0x080c, 0x709e, 0x7000, 0x9086, 0x0001, 0x1904, 0x0aab, - 0x7094, 0x9086, 0x0029, 0x1904, 0x0aab, 0x080c, 0x817d, 0x080c, - 0x816f, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, - 0xffff, 0x7a28, 0x9295, 0x5e2f, 0x7a2a, 0x2011, 0x6fed, 0x080c, - 0x8259, 0x2011, 0x6fe0, 0x080c, 0x832d, 0x2011, 0x5c98, 0x080c, - 0x8259, 0x2011, 0x8030, 0x901e, 0x7392, 0x04d0, 0x080c, 0x5545, - 0x2079, 0x0100, 0x7844, 0x9005, 0x1904, 0x0aab, 0x2011, 0x5c98, - 0x080c, 0x8259, 0x2011, 0x6fed, 0x080c, 0x8259, 0x2011, 0x6fe0, - 0x080c, 0x832d, 0x2001, 0x0265, 0x2001, 0x0205, 0x2003, 0x0000, - 0x7840, 0x9084, 0xfffb, 0x7842, 0x2001, 0x1981, 0x2004, 0x9005, - 0x1140, 0x00c6, 0x2061, 0x0100, 0x080c, 0x5de5, 0x00ce, 0x0804, - 0x0aab, 0x780f, 0x006b, 0x7a28, 0x080c, 0x7186, 0x0118, 0x9295, - 0x5e2f, 0x0010, 0x9295, 0x402f, 0x7a2a, 0x2011, 0x8010, 0x73d4, - 0x2001, 0x1982, 0x2003, 0x0001, 0x080c, 0x2974, 0x080c, 0x4a17, - 0x7244, 0xc284, 0x7246, 0x2001, 0x180c, 0x200c, 0xc1ac, 0xc1cc, - 0x2102, 0x080c, 0x9818, 0x2011, 0x0004, 0x080c, 0xbd5e, 0x080c, - 0x65c6, 0x080c, 0x717e, 0x1120, 0x080c, 0x29e1, 0x02e0, 0x0400, - 0x080c, 0x5dec, 0x0140, 0x7093, 0x0001, 0x70cf, 0x0000, 0x080c, - 0x5712, 0x0804, 0x0aab, 0x080c, 0x54db, 0xd094, 0x0188, 0x2011, - 0x180c, 0x2204, 0xc0cd, 0x2012, 0x080c, 0x54df, 0xd0d4, 0x1118, - 0x080c, 0x29e1, 0x1270, 0x2011, 0x180c, 0x2204, 0xc0bc, 0x0088, - 0x080c, 0x54df, 0xd0d4, 0x1db8, 0x2011, 0x180c, 0x2204, 0xc0bd, - 0x0040, 0x2011, 0x180c, 0x2204, 0xc0bd, 0x2012, 0x080c, 0x66c1, - 0x0008, 0x2012, 0x080c, 0x6687, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, - 0x00a8, 0x707b, 0x0000, 0x080c, 0x717e, 0x1130, 0x70ac, 0x9005, - 0x1168, 0x080c, 0xc1a1, 0x0050, 0x080c, 0xc1a1, 0x70d8, 0xd09c, - 0x1128, 0x70ac, 0x9005, 0x0110, 0x080c, 0x5dc2, 0x70e3, 0x0000, - 0x70df, 0x0000, 0x70a3, 0x0000, 0x080c, 0x29e9, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c4, 0x2012, 0x72d8, 0x080c, 0x717e, 0x1178, - 0x9016, 0x0016, 0x2009, 0x0002, 0x2019, 0x1947, 0x211a, 0x001e, - 0x705b, 0xffff, 0x705f, 0x00ef, 0x707f, 0x0000, 0x0020, 0x2019, - 0x1947, 0x201b, 0x0000, 0x2079, 0x185b, 0x7804, 0xd0ac, 0x0108, - 0xc295, 0x72da, 0x080c, 0x717e, 0x0118, 0x9296, 0x0004, 0x0548, - 0x2011, 0x0001, 0x080c, 0xbd5e, 0x70a7, 0x0000, 0x70ab, 0xffff, - 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, - 0x0003, 0x782a, 0x00fe, 0x080c, 0x2e73, 0x2011, 0x0005, 0x080c, - 0x9923, 0x080c, 0x8b8f, 0x080c, 0x717e, 0x0148, 0x00c6, 0x2061, - 0x0100, 0x0016, 0x2009, 0x0002, 0x61e2, 0x001e, 0x00ce, 0x012e, - 0x0420, 0x70a7, 0x0000, 0x70ab, 0xffff, 0x7003, 0x0002, 0x00f6, - 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, 0x782a, - 0x00fe, 0x2011, 0x0005, 0x080c, 0x9923, 0x080c, 0x8b8f, 0x080c, - 0x717e, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x2009, 0x0002, - 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x00b6, - 0x080c, 0x717e, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, - 0x080c, 0x717e, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, - 0x0138, 0x9180, 0x1000, 0x2004, 0x905d, 0x0110, 0xb800, 0xd0bc, - 0x090c, 0x3190, 0x8108, 0x1f04, 0x0abf, 0x707b, 0x0000, 0x707c, - 0x9084, 0x00ff, 0x707e, 0x70af, 0x0000, 0x00be, 0x00ce, 0x0005, - 0x00b6, 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, 0x1904, - 0x0b8c, 0x70a8, 0x9086, 0xffff, 0x0130, 0x080c, 0x2e73, 0x080c, - 0x8b8f, 0x0804, 0x0b8c, 0x70d8, 0xd0ac, 0x1110, 0xd09c, 0x0540, - 0xd084, 0x0530, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, - 0xd08c, 0x01f0, 0x70dc, 0x9086, 0xffff, 0x01b0, 0x080c, 0x3001, - 0x080c, 0x8b8f, 0x70d8, 0xd094, 0x1904, 0x0b8c, 0x2011, 0x0001, - 0x080c, 0xc459, 0x0110, 0x2011, 0x0003, 0x901e, 0x080c, 0x303b, - 0x080c, 0x8b8f, 0x0804, 0x0b8c, 0x70e0, 0x9005, 0x1904, 0x0b8c, - 0x70a4, 0x9005, 0x1904, 0x0b8c, 0x70d8, 0xd0a4, 0x0118, 0xd0b4, - 0x0904, 0x0b8c, 0x080c, 0x6687, 0x1904, 0x0b8c, 0x080c, 0x66da, - 0x1904, 0x0b8c, 0x080c, 0x66c1, 0x01c0, 0x0156, 0x00c6, 0x20a9, - 0x007f, 0x900e, 0x0016, 0x080c, 0x63a3, 0x1118, 0xb800, 0xd0ec, - 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b32, 0x00ce, 0x015e, 0x0028, - 0x001e, 0x00ce, 0x015e, 0x0804, 0x0b8c, 0x0006, 0x2001, 0x0103, - 0x2003, 0x006b, 0x000e, 0x2011, 0x198e, 0x080c, 0x0fbf, 0x2011, - 0x19a8, 0x080c, 0x0fbf, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, - 0x70ab, 0xffff, 0x080c, 0x0e9f, 0x9006, 0x080c, 0x2616, 0x0036, - 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4bb4, 0x004e, - 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x71a1, 0x0150, 0x080c, - 0x717e, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, 0xffdf, - 0x782a, 0x00fe, 0x2001, 0x19c3, 0x2004, 0x9086, 0x0005, 0x1120, - 0x2011, 0x0000, 0x080c, 0x9923, 0x2011, 0x0000, 0x080c, 0x992d, - 0x080c, 0x8b8f, 0x080c, 0x8c6c, 0x012e, 0x00be, 0x0005, 0x0016, - 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x7904, - 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x5dab, 0x7940, - 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, - 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, 0x2001, - 0x0100, 0x2004, 0x9086, 0x000a, 0x1904, 0x0c23, 0x7954, 0xd1ac, - 0x1904, 0x0c23, 0x2001, 0x1982, 0x2004, 0x9005, 0x1518, 0x080c, - 0x2a7f, 0x1148, 0x2001, 0x0001, 0x080c, 0x29a3, 0x2001, 0x0001, - 0x080c, 0x2986, 0x00b8, 0x080c, 0x2a87, 0x1138, 0x9006, 0x080c, - 0x29a3, 0x9006, 0x080c, 0x2986, 0x0068, 0x080c, 0x2a8f, 0x1d50, - 0x2001, 0x1972, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, 0x27b1, - 0x0804, 0x0d2f, 0x080c, 0x718f, 0x0148, 0x080c, 0x71a1, 0x1118, - 0x080c, 0x7489, 0x0050, 0x080c, 0x7186, 0x0dd0, 0x080c, 0x7484, - 0x080c, 0x747a, 0x080c, 0x709e, 0x0058, 0x080c, 0x717e, 0x0140, - 0x2009, 0x00f8, 0x080c, 0x5dab, 0x7843, 0x0090, 0x7843, 0x0010, - 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x717e, 0x0138, - 0x7824, 0xd0ac, 0x1904, 0x0d34, 0x1f04, 0x0c02, 0x0070, 0x7824, - 0x080c, 0x7198, 0x0118, 0xd0ac, 0x1904, 0x0d34, 0x9084, 0x1800, - 0x0d98, 0x7003, 0x0001, 0x0804, 0x0d34, 0x2001, 0x0001, 0x080c, - 0x2616, 0x0804, 0x0d56, 0x2001, 0x1982, 0x2004, 0x9005, 0x1518, - 0x080c, 0x2a7f, 0x1148, 0x2001, 0x0001, 0x080c, 0x29a3, 0x2001, - 0x0001, 0x080c, 0x2986, 0x00b8, 0x080c, 0x2a87, 0x1138, 0x9006, - 0x080c, 0x29a3, 0x9006, 0x080c, 0x2986, 0x0068, 0x080c, 0x2a8f, - 0x1d50, 0x2001, 0x1972, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, - 0x27b1, 0x0804, 0x0d2f, 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, - 0x01f8, 0x7850, 0x9085, 0x0040, 0x7852, 0x7938, 0x7850, 0x9084, - 0xfbcf, 0x7852, 0x080c, 0x2a97, 0x9085, 0x2000, 0x7852, 0x793a, - 0x20a9, 0x0046, 0x1d04, 0x0c62, 0x080c, 0x830d, 0x1f04, 0x0c62, - 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x7852, 0x793a, 0x0040, - 0x20a9, 0x003a, 0x1d04, 0x0c72, 0x080c, 0x830d, 0x1f04, 0x0c72, - 0x080c, 0x718f, 0x0148, 0x080c, 0x71a1, 0x1118, 0x080c, 0x7489, - 0x0050, 0x080c, 0x7186, 0x0dd0, 0x080c, 0x7484, 0x080c, 0x747a, - 0x080c, 0x709e, 0x0020, 0x2009, 0x00f8, 0x080c, 0x5dab, 0x2001, - 0x0100, 0x2004, 0x9086, 0x000a, 0x0168, 0x20a9, 0x0028, 0xa001, - 0x1f04, 0x0c97, 0x7850, 0x9085, 0x1400, 0x7852, 0x080c, 0x717e, - 0x0158, 0x0030, 0x7850, 0xc0e5, 0x7852, 0x080c, 0x717e, 0x0120, - 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, - 0x0d0c, 0x830d, 0x7820, 0xd09c, 0x1590, 0x080c, 0x717e, 0x0904, - 0x0d13, 0x7824, 0xd0ac, 0x1904, 0x0d34, 0x080c, 0x71a1, 0x1538, - 0x0046, 0x2021, 0x0320, 0x8421, 0x1df0, 0x004e, 0x7827, 0x1800, - 0x080c, 0x2a97, 0x7824, 0x9084, 0x1800, 0x1168, 0x9484, 0x0fff, - 0x1140, 0x2001, 0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, - 0x0d64, 0x8421, 0x1160, 0x1d04, 0x0cdf, 0x080c, 0x830d, 0x080c, - 0x7484, 0x080c, 0x747a, 0x7003, 0x0001, 0x0804, 0x0d34, 0x8319, - 0x1938, 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, 0x1140, 0x2001, - 0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, 0x0d64, 0x1d04, - 0x0cfb, 0x080c, 0x830d, 0x2009, 0x1975, 0x2104, 0x9005, 0x0118, - 0x8001, 0x200a, 0x1178, 0x200b, 0x000a, 0x7827, 0x0048, 0x20a9, - 0x0002, 0x080c, 0x2a78, 0x7924, 0x080c, 0x2a97, 0xd19c, 0x0110, - 0x080c, 0x2974, 0x00e0, 0x080c, 0x718f, 0x1140, 0x94a2, 0x03e8, - 0x1128, 0x080c, 0x7156, 0x7003, 0x0001, 0x00b0, 0x7827, 0x1800, - 0x080c, 0x2a97, 0x7824, 0x080c, 0x7198, 0x0110, 0xd0ac, 0x1160, - 0x9084, 0x1800, 0x0904, 0x0ce7, 0x7003, 0x0001, 0x0028, 0x2001, - 0x0001, 0x080c, 0x2616, 0x00c0, 0x2001, 0x0100, 0x2004, 0x9086, - 0x000a, 0x1118, 0x7850, 0xc0e4, 0x7852, 0x2009, 0x180c, 0x210c, - 0xd19c, 0x1120, 0x7904, 0x918d, 0x0002, 0x7906, 0x7827, 0x0048, - 0x7828, 0x9085, 0x0028, 0x782a, 0x2001, 0x0100, 0x2004, 0x9086, - 0x000a, 0x0120, 0x7850, 0x9085, 0x0400, 0x7852, 0x2001, 0x1982, - 0x2003, 0x0000, 0x9006, 0x78f2, 0x015e, 0x003e, 0x000e, 0x012e, - 0x00fe, 0x004e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0036, 0x0046, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0069, 0x0d0c, - 0x830d, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, - 0x003e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x189c, 0x7004, - 0x9086, 0x0001, 0x1110, 0x080c, 0x331a, 0x00ee, 0x0005, 0x0005, - 0x2a70, 0x2061, 0x1986, 0x2063, 0x0003, 0x6007, 0x0003, 0x600b, - 0x0012, 0x600f, 0x0317, 0x2001, 0x1956, 0x900e, 0x2102, 0x7192, - 0x2001, 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x705b, 0xffff, - 0x0008, 0x715a, 0x7063, 0xffff, 0x717a, 0x717e, 0x080c, 0xc1a1, - 0x70e7, 0x00c0, 0x2061, 0x1946, 0x6003, 0x0909, 0x6106, 0x600b, - 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x000f, 0x611a, - 0x601f, 0x07d0, 0x2061, 0x194e, 0x6003, 0x8000, 0x6106, 0x610a, - 0x600f, 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, - 0x2061, 0x1963, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, - 0x600f, 0x2020, 0x2001, 0x182b, 0x2102, 0x0005, 0x9016, 0x080c, - 0x63a3, 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, 0x0df8, 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, 0x1a7a, 0x7a08, 0x226a, 0x2069, 0x1a7b, 0x7a18, 0x226a, - 0x8d68, 0x7a1c, 0x226a, 0x782c, 0x2019, 0x1a88, 0x201a, 0x2019, - 0x1a8b, 0x9016, 0x7808, 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, - 0x8318, 0x9386, 0x1aa0, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, - 0x2011, 0xdead, 0x2019, 0x1a89, 0x782c, 0x201a, 0x8318, 0x221a, - 0x7803, 0x0000, 0x2069, 0x1a5a, 0x901e, 0x20a9, 0x0020, 0x7b26, - 0x7a28, 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0e4f, 0x002e, 0x003e, - 0x00de, 0x015e, 0x2079, 0x1800, 0x7803, 0x0005, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x19f6, 0x2004, - 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, - 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, 0x080c, 0x54ea, 0x1108, - 0x0099, 0x0cd8, 0x0005, 0x918c, 0x03ff, 0x2001, 0x0003, 0x2004, - 0x9084, 0x0600, 0x1118, 0x918d, 0x6c00, 0x0010, 0x918d, 0x6400, - 0x2001, 0x017f, 0x2102, 0x0005, 0x0026, 0x0126, 0x2011, 0x0080, - 0x080c, 0x0f17, 0x20a9, 0x0900, 0x080c, 0x0f38, 0x2011, 0x0040, - 0x080c, 0x0f17, 0x20a9, 0x0900, 0x080c, 0x0f38, 0x0c78, 0x0026, - 0x080c, 0x0f24, 0x1118, 0x2011, 0x0040, 0x0098, 0x2011, 0x010e, - 0x2214, 0x9294, 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0xa880, - 0x0010, 0x2011, 0x6840, 0xd0e4, 0x70eb, 0x0000, 0x1120, 0x70eb, - 0x0fa0, 0x080c, 0x0f29, 0x002e, 0x0005, 0x0026, 0x080c, 0x0f24, - 0x0128, 0xd0a4, 0x1138, 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, - 0x080c, 0x0f29, 0x002e, 0x0005, 0x0026, 0x70eb, 0x0000, 0x080c, - 0x0f24, 0x1148, 0x080c, 0x2a8f, 0x1118, 0x2011, 0x8484, 0x0058, - 0x2011, 0x8282, 0x0040, 0x080c, 0x2a8f, 0x1118, 0x2011, 0xcdc5, - 0x0010, 0x2011, 0xcac2, 0x080c, 0x0f29, 0x002e, 0x0005, 0x00e6, - 0x0006, 0x2071, 0x1800, 0xd0b4, 0x70e4, 0x1110, 0xc0e4, 0x0048, - 0x0006, 0x3b00, 0x9084, 0xff3f, 0x20d8, 0x000e, 0x70eb, 0x0000, - 0xc0e5, 0x0079, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, - 0xd0e4, 0x70e4, 0x1110, 0xc0dc, 0x0008, 0xc0dd, 0x0011, 0x00ee, - 0x0005, 0x70e6, 0x7000, 0x9084, 0x0007, 0x000b, 0x0005, 0x0ee6, - 0x0ebd, 0x0ebd, 0x0e9f, 0x0ecc, 0x0ebd, 0x0ebd, 0x0ecc, 0x0016, - 0x3b08, 0x3a00, 0x9104, 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, - 0x9205, 0x20d0, 0x001e, 0x0005, 0x2001, 0x1839, 0x2004, 0xd0dc, - 0x0005, 0x9e86, 0x1800, 0x190c, 0x0df6, 0x70e4, 0xd0e4, 0x0108, - 0xc2e5, 0x72e6, 0xd0e4, 0x1118, 0x9294, 0x00c0, 0x0c01, 0x0005, - 0x1d04, 0x0f38, 0x2091, 0x6000, 0x1f04, 0x0f38, 0x0005, 0x890e, - 0x810e, 0x810f, 0x9194, 0x003f, 0x918c, 0xffc0, 0x0005, 0x0006, - 0x2200, 0x914d, 0x894f, 0x894d, 0x894d, 0x000e, 0x0005, 0x01d6, - 0x0146, 0x0036, 0x0096, 0x2061, 0x188b, 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, 0x189b, 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, 0x0f3f, 0x2100, 0x9300, 0x2098, - 0x22e0, 0x009e, 0x002e, 0x001e, 0x0036, 0x3518, 0x20a9, 0x0001, - 0x4002, 0x8007, 0x4004, 0x8319, 0x1dd8, 0x003e, 0x0005, 0x20e9, - 0x0001, 0x71b4, 0x81ff, 0x11c0, 0x9006, 0x2009, 0x0200, 0x20a9, - 0x0002, 0x9298, 0x0018, 0x23a0, 0x4001, 0x2009, 0x0700, 0x20a9, - 0x0002, 0x9298, 0x0008, 0x23a0, 0x4001, 0x7078, 0x8007, 0x717c, - 0x810f, 0x20a9, 0x0002, 0x4001, 0x9298, 0x000c, 0x23a0, 0x900e, - 0x080c, 0x0dd6, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x4001, - 0x0005, 0x89ff, 0x0140, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, - 0x1069, 0x009e, 0x0cb0, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, - 0x10e2, 0x090c, 0x0df6, 0x00ee, 0x0005, 0x0086, 0x00e6, 0x0006, - 0x0026, 0x0036, 0x0126, 0x2091, 0x8000, 0x00c9, 0x2071, 0x1800, - 0x73bc, 0x702c, 0x9016, 0x9045, 0x0158, 0x8210, 0x9906, 0x090c, - 0x0df6, 0x2300, 0x9202, 0x0120, 0x1a0c, 0x0df6, 0xa000, 0x0c98, - 0x012e, 0x003e, 0x002e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x0086, - 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x190e, 0x7010, - 0x9005, 0x0140, 0x7018, 0x9045, 0x0128, 0x9906, 0x090c, 0x0df6, - 0xa000, 0x0cc8, 0x012e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x00e6, - 0x2071, 0x1800, 0x0126, 0x2091, 0x8000, 0x70bc, 0x8001, 0x0270, - 0x70be, 0x702c, 0x2048, 0x9085, 0x0001, 0xa800, 0x702e, 0xa803, - 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x904e, 0x0cd8, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x70bc, 0x90ca, - 0x0040, 0x0268, 0x8001, 0x70be, 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, 0x70bc, 0x8000, 0x70be, 0x080c, 0x816f, - 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, 0x188b, 0x7000, 0x9005, 0x11a0, 0x2001, - 0x0492, 0xa802, 0x2048, 0x2009, 0x2480, 0x8940, 0x2800, 0xa802, - 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0800, 0x0120, 0x2848, - 0x9188, 0x0040, 0x0c90, 0x2071, 0x188b, 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, 0x74ba, - 0x74be, 0x0005, 0x00e6, 0x0016, 0x9984, 0xfc00, 0x01e8, 0x908c, - 0xf800, 0x1168, 0x9982, 0x0400, 0x02b8, 0x9982, 0x0440, 0x0278, - 0x9982, 0x0492, 0x0288, 0x9982, 0x0800, 0x1270, 0x0040, 0x9982, - 0x0800, 0x0250, 0x2071, 0x188b, 0x7010, 0x9902, 0x1228, 0x9085, - 0x0001, 0x001e, 0x00ee, 0x0005, 0x9006, 0x0cd8, 0x00e6, 0x2071, - 0x19f5, 0x7007, 0x0000, 0x9006, 0x701e, 0x7022, 0x7002, 0x2071, - 0x0000, 0x7010, 0x9085, 0x8044, 0x7012, 0x2071, 0x0080, 0x9006, - 0x0006, 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, 0x000e, 0x1158, - 0x702b, 0x0060, 0x20a9, 0x0040, 0x7022, 0x1f04, 0x1124, 0x702b, - 0x0060, 0x702b, 0x0020, 0x20a9, 0x0040, 0x7022, 0x1f04, 0x112d, - 0x702b, 0x0020, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, - 0xa06f, 0x0000, 0x2071, 0x19f5, 0x701c, 0x9088, 0x19ff, 0x280a, - 0x8000, 0x9084, 0x003f, 0x701e, 0x7120, 0x9106, 0x090c, 0x0df6, - 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x00a9, 0x00fe, - 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, - 0x19f5, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x0021, - 0x00fe, 0x00ee, 0x012e, 0x0005, 0x7004, 0x9086, 0x0000, 0x1110, - 0x7007, 0x0006, 0x7000, 0x0002, 0x1176, 0x1174, 0x1174, 0x1174, - 0x12ed, 0x12ed, 0x12ed, 0x12ed, 0x080c, 0x0df6, 0x701c, 0x7120, - 0x9106, 0x1148, 0x792c, 0x9184, 0x0001, 0x1120, 0xd1fc, 0x1110, - 0x7007, 0x0000, 0x0005, 0x0096, 0x9180, 0x19ff, 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, 0x19f5, - 0x2104, 0xc095, 0x200a, 0x080c, 0x1153, 0x0005, 0x0016, 0x00e6, - 0x2071, 0x19f5, 0x00f6, 0x2079, 0x0080, 0x792c, 0xd1bc, 0x190c, - 0x0def, 0x782b, 0x0002, 0xd1fc, 0x0120, 0x918c, 0x0700, 0x7004, - 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1164, 0x120c, 0x1240, - 0x0df6, 0x0df6, 0x12f9, 0x0df6, 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, 0x11a9, 0x0005, 0x7008, 0x0096, - 0x2048, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000, 0x080c, 0x1164, - 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x0ca0, - 0x918c, 0x0700, 0x1150, 0x700c, 0x9005, 0x0180, 0x7800, 0x7802, - 0x7804, 0x7806, 0x080c, 0x11be, 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, 0x18b7, 0x2004, 0x9906, 0x1128, 0xa89c, - 0x080f, 0x00de, 0x009e, 0x00a0, 0x00de, 0x009e, 0x0096, 0x00d6, - 0x7008, 0x2048, 0x0081, 0x0150, 0xa89c, 0x0086, 0x2940, 0x080f, - 0x008e, 0x00de, 0x009e, 0x080c, 0x1153, 0x0005, 0x00de, 0x009e, - 0x080c, 0x1153, 0x0005, 0xa8a8, 0xd08c, 0x0005, 0x0096, 0xa0a0, - 0x904d, 0x090c, 0x0df6, 0xa06c, 0x908e, 0x0100, 0x0130, 0xa87b, - 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x080c, 0x6a15, 0xa09f, - 0x0000, 0xa0a3, 0x0000, 0x2848, 0x080c, 0x1069, 0x009e, 0x0005, - 0x00a6, 0xa0a0, 0x904d, 0x090c, 0x0df6, 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, 0x1134, 0x00e8, 0xa97c, 0xa894, - 0x0016, 0x0006, 0x080c, 0x6a15, 0x000e, 0x001e, 0xd1fc, 0x1138, - 0xd1f4, 0x0128, 0x00c6, 0x2060, 0x080c, 0x9fea, 0x00ce, 0x7008, - 0x2048, 0xa89f, 0x0000, 0xa8a3, 0x0000, 0x080c, 0x1069, 0x7007, - 0x0000, 0x080c, 0x1153, 0x00ae, 0x0005, 0x0126, 0x2091, 0x8000, - 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x012e, - 0x0005, 0x7007, 0x0000, 0x080c, 0x1164, 0x0005, 0x0126, 0x2091, - 0x2200, 0x2079, 0x0300, 0x2071, 0x1a3f, 0x7003, 0x0000, 0x78bf, - 0x00f6, 0x0419, 0x7803, 0x0003, 0x780f, 0x0000, 0x2001, 0x0100, - 0x2004, 0x9086, 0x000a, 0x0128, 0x20a9, 0x01e8, 0x2061, 0xdc0a, - 0x0020, 0x20a9, 0x01e8, 0x2061, 0xdfd8, 0x2c0d, 0x7912, 0xe104, - 0x9ce0, 0x0002, 0x7916, 0x1f04, 0x131d, 0x7807, 0x0007, 0x7803, - 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, - 0x7808, 0xd09c, 0x0110, 0x7820, 0x0cd8, 0x2001, 0x1a40, 0x2003, - 0x0000, 0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, - 0x7807, 0x0007, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, - 0x782b, 0x1a5a, 0x781f, 0xff00, 0x781b, 0xff00, 0x2001, 0x0200, - 0x2004, 0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x1a5a, 0x602f, - 0x1cd0, 0x2001, 0x1819, 0x2004, 0x9082, 0x1cd0, 0x6032, 0x603b, - 0x1ebe, 0x783f, 0x31f3, 0x00ce, 0x0005, 0x0126, 0x2091, 0x2200, - 0x7908, 0x9184, 0x0070, 0x190c, 0x0def, 0xd19c, 0x0158, 0x7820, - 0x908c, 0xf000, 0x15e8, 0x908a, 0x0024, 0x1a0c, 0x0df6, 0x0023, - 0x012e, 0x0005, 0x012e, 0x0005, 0x13a0, 0x13a0, 0x13b7, 0x13bc, - 0x13c0, 0x13c5, 0x13ed, 0x13f1, 0x13ff, 0x1403, 0x13a0, 0x148f, - 0x1493, 0x1503, 0x13a0, 0x13a0, 0x13a0, 0x13a0, 0x13a0, 0x13a0, - 0x13a0, 0x13a0, 0x13a0, 0x13a0, 0x13a0, 0x13a0, 0x13a0, 0x13c7, - 0x13a0, 0x13a0, 0x13a0, 0x13a0, 0x13a0, 0x13a0, 0x13a4, 0x13a2, - 0x080c, 0x0df6, 0x080c, 0x0def, 0x080c, 0x150a, 0x2009, 0x1a56, - 0x2104, 0x8000, 0x200a, 0x080c, 0x7bec, 0x080c, 0x1977, 0x0005, - 0x2009, 0x0048, 0x2060, 0x080c, 0xa068, 0x012e, 0x0005, 0x7004, - 0xc085, 0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, - 0x080c, 0x150a, 0x080c, 0x15e4, 0x0005, 0x080c, 0x0df6, 0x080c, - 0x150a, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, - 0x2009, 0x0048, 0x080c, 0xa068, 0x2001, 0x015d, 0x2003, 0x0000, - 0x2009, 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, - 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, 0x150f, - 0x2001, 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, - 0x0005, 0x080c, 0x150a, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, - 0xffff, 0x009e, 0x2009, 0x0048, 0x080c, 0xa068, 0x0005, 0x080c, - 0x150a, 0x080c, 0x0df6, 0x080c, 0x150a, 0x080c, 0x147a, 0x7827, - 0x0018, 0x79ac, 0xd1dc, 0x0540, 0x7827, 0x0015, 0x7828, 0x782b, - 0x0000, 0x9065, 0x0138, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x0400, 0x7004, 0x9005, 0x1180, 0x78ab, 0x0004, 0x7827, - 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0df6, 0x2001, 0x020d, - 0x2003, 0x0050, 0x2003, 0x0020, 0x0490, 0x78ab, 0x0004, 0x7803, - 0x0001, 0x080c, 0x1493, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, - 0x090c, 0x0df6, 0x6014, 0x2048, 0x78ab, 0x0004, 0x918c, 0x0700, - 0x01a8, 0x080c, 0x7bec, 0x080c, 0x1977, 0x080c, 0xbd4e, 0x0158, - 0xa9ac, 0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, - 0xa880, 0xc0bd, 0xa882, 0x080c, 0xb983, 0x0005, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xc13a, 0x2029, - 0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, - 0x7dbc, 0x080c, 0xdbb3, 0xd5a4, 0x1118, 0x080c, 0x150f, 0x0005, - 0x080c, 0x7bec, 0x080c, 0x1977, 0x0005, 0x781f, 0x0300, 0x7803, - 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, - 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, - 0x080c, 0x1580, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, 0x7004, - 0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, 0x190c, 0x0df6, - 0xd184, 0x11b1, 0xd19c, 0x0180, 0xc19c, 0x7106, 0x0016, 0x080c, - 0x15c7, 0x001e, 0x0148, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x080c, 0x150f, 0x0005, 0x81ff, 0x190c, 0x0df6, 0x0005, - 0x2100, 0xc184, 0xc1b4, 0x7106, 0xd0b4, 0x0016, 0x00e6, 0x1904, - 0x14f8, 0x2071, 0x0200, 0x080c, 0x15bb, 0x080c, 0x15c7, 0x05a8, - 0x6014, 0x9005, 0x05a8, 0x0096, 0x2048, 0xa864, 0x009e, 0x9084, - 0x00ff, 0x908e, 0x0029, 0x0160, 0x908e, 0x0048, 0x1548, 0x601c, - 0xd084, 0x11d8, 0x00f6, 0x2c78, 0x080c, 0x1651, 0x00fe, 0x00a8, - 0x00f6, 0x2c78, 0x080c, 0x179b, 0x00fe, 0x2009, 0x01f4, 0x8109, - 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, - 0x2004, 0xd0ec, 0x1110, 0x0419, 0x0040, 0x2001, 0x020d, 0x2003, - 0x0020, 0x080c, 0x132d, 0x7803, 0x0001, 0x00ee, 0x001e, 0x0005, - 0x080c, 0x15c7, 0x0dd0, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x0069, 0x0c90, 0x0031, 0x2060, 0x2009, 0x0053, 0x080c, - 0xa068, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, 0x080c, - 0x147a, 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, 0x1572, 0x6827, 0x0001, 0x8109, 0x1dd0, 0x04d9, 0x6827, - 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, 0x1500, - 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1130, 0x08c0, 0x080c, - 0x7bec, 0x080c, 0x1977, 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, 0x1365, 0x00ce, 0x002e, 0x001e, 0x000e, - 0x0006, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x0059, 0x1118, - 0x000e, 0x00fe, 0x0005, 0x000e, 0x792c, 0x3900, 0x8000, 0x2004, - 0x080c, 0x0df6, 0x2009, 0xff00, 0x8109, 0x0120, 0x7818, 0xd0bc, - 0x1dd8, 0x0005, 0x9085, 0x0001, 0x0005, 0x7832, 0x7936, 0x7a3a, - 0x781b, 0x8080, 0x0c79, 0x1108, 0x0005, 0x792c, 0x3900, 0x8000, - 0x2004, 0x080c, 0x0df6, 0x7037, 0x0001, 0x7150, 0x7037, 0x0002, - 0x7050, 0x2060, 0xd1bc, 0x1110, 0x7054, 0x2060, 0x0005, 0x0006, - 0x0046, 0x00e6, 0x2071, 0x0200, 0x7037, 0x0002, 0x7058, 0x9084, - 0xff00, 0x8007, 0x9086, 0x00bc, 0x1158, 0x2021, 0x1a57, 0x2404, - 0x8000, 0x0208, 0x2022, 0x080c, 0x7bec, 0x080c, 0x1977, 0x9006, - 0x00ee, 0x004e, 0x000e, 0x0005, 0x0c11, 0x1108, 0x0005, 0x00e6, - 0x0016, 0x2071, 0x0200, 0x0879, 0x6124, 0xd1dc, 0x01f8, 0x701c, - 0xd08c, 0x0904, 0x1646, 0x7017, 0x0000, 0x2001, 0x0264, 0x2004, - 0xd0bc, 0x0904, 0x1646, 0x2001, 0x0268, 0x00c6, 0x2064, 0x6104, - 0x6038, 0x00ce, 0x918e, 0x0039, 0x1904, 0x1646, 0x9c06, 0x15f0, - 0x0126, 0x2091, 0x2600, 0x080c, 0x7b33, 0x012e, 0x7358, 0x745c, - 0x6014, 0x905d, 0x0598, 0x2b48, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x190c, 0xc115, 0xab42, 0xac3e, 0x2001, 0x187d, - 0x2004, 0xd0b4, 0x1170, 0x601c, 0xd0e4, 0x1158, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1120, 0xa83b, 0x7fff, 0xa837, - 0xffff, 0x080c, 0x1ede, 0x1190, 0x080c, 0x17f8, 0x2a00, 0xa816, - 0x0130, 0x2800, 0xa80e, 0x2c05, 0xa80a, 0x2c00, 0xa812, 0x7037, - 0x0020, 0x781f, 0x0300, 0x001e, 0x00ee, 0x0005, 0x7037, 0x0050, - 0x7037, 0x0020, 0x001e, 0x00ee, 0x080c, 0x150f, 0x0005, 0x080c, - 0x0df6, 0x0016, 0x2009, 0x00a0, 0x8109, 0xa001, 0xa001, 0xa001, - 0x1dd8, 0x001e, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x0016, 0x00c6, - 0x3e60, 0x6014, 0x2048, 0x2940, 0x903e, 0x2730, 0xa864, 0x2068, - 0xa81a, 0x9d84, 0x000f, 0x9088, 0x1ebe, 0x2165, 0x0002, 0x1686, - 0x16d3, 0x1686, 0x1686, 0x1686, 0x16b5, 0x1686, 0x168a, 0x167f, - 0x16ca, 0x1686, 0x1686, 0x1686, 0x1790, 0x169e, 0x1694, 0xa964, - 0x918c, 0x00ff, 0x918e, 0x0048, 0x0904, 0x16ca, 0x9085, 0x0001, - 0x0804, 0x1786, 0xa87c, 0xd0bc, 0x0dc8, 0xa890, 0xa842, 0xa88c, - 0xa83e, 0xa888, 0x0804, 0x16da, 0xa87c, 0xd0bc, 0x0d78, 0xa890, - 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x1729, 0xa87c, 0xd0bc, - 0x0d28, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa804, 0x9045, 0x090c, - 0x0df6, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x1ebe, 0x2065, - 0xa888, 0xd19c, 0x1904, 0x1729, 0x0428, 0xa87c, 0xd0ac, 0x0970, - 0xa804, 0x9045, 0x090c, 0x0df6, 0xa164, 0xa91a, 0x91ec, 0x000f, - 0x9d80, 0x1ebe, 0x2065, 0x9006, 0xa842, 0xa83e, 0xd19c, 0x1904, - 0x1729, 0x0080, 0xa87c, 0xd0ac, 0x0904, 0x1686, 0x9006, 0xa842, - 0xa83e, 0x0804, 0x1729, 0xa87c, 0xd0ac, 0x0904, 0x1686, 0x9006, - 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0df6, 0x9082, - 0x001b, 0x0002, 0x16fd, 0x16fd, 0x16ff, 0x16fd, 0x16fd, 0x16fd, - 0x1705, 0x16fd, 0x16fd, 0x16fd, 0x170b, 0x16fd, 0x16fd, 0x16fd, - 0x1711, 0x16fd, 0x16fd, 0x16fd, 0x1717, 0x16fd, 0x16fd, 0x16fd, - 0x171d, 0x16fd, 0x16fd, 0x16fd, 0x1723, 0x080c, 0x0df6, 0xa574, - 0xa478, 0xa37c, 0xa280, 0x0804, 0x176e, 0xa584, 0xa488, 0xa38c, - 0xa290, 0x0804, 0x176e, 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, - 0x176e, 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, 0x176e, 0xa5b4, - 0xa4b8, 0xa3bc, 0xa2c0, 0x0804, 0x176e, 0xa5c4, 0xa4c8, 0xa3cc, - 0xa2d0, 0x0804, 0x176e, 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, - 0x176e, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0df6, 0x9082, 0x001b, - 0x0002, 0x174c, 0x174a, 0x174a, 0x174a, 0x174a, 0x174a, 0x1753, - 0x174a, 0x174a, 0x174a, 0x174a, 0x174a, 0x175a, 0x174a, 0x174a, - 0x174a, 0x174a, 0x174a, 0x1761, 0x174a, 0x174a, 0x174a, 0x174a, - 0x174a, 0x1768, 0x080c, 0x0df6, 0xa56c, 0xa470, 0xa774, 0xa678, - 0xa37c, 0xa280, 0x00d8, 0xa584, 0xa488, 0xa78c, 0xa690, 0xa394, - 0xa298, 0x00a0, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, - 0x0068, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, 0xa2c8, 0x0030, - 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 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, 0x1686, 0x0016, 0x2009, 0x00a0, 0x8109, 0xa001, 0xa001, - 0xa001, 0x1dd8, 0x001e, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x0016, - 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0xa80e, 0x2061, 0x1eb9, - 0xa813, 0x1eb9, 0x2c05, 0xa80a, 0xa964, 0xa91a, 0xa87c, 0xd0ac, - 0x090c, 0x0df6, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0034, - 0x1a0c, 0x0df6, 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, - 0x0df6, 0xa80e, 0xa064, 0xa81a, 0x9084, 0x000f, 0x9080, 0x1ebe, - 0x2015, 0x82ff, 0x090c, 0x0df6, 0xaa12, 0x2205, 0xa80a, 0x0c08, - 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x18ed, - 0x184f, 0x184f, 0x18ed, 0x18ed, 0x18e7, 0x18ed, 0x184f, 0x189e, - 0x189e, 0x189e, 0x18ed, 0x18ed, 0x18ed, 0x18e4, 0x189e, 0xc0fc, - 0xa882, 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x18ef, - 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0df6, 0x9082, 0x001b, 0x0002, - 0x183b, 0x1839, 0x1839, 0x1839, 0x1839, 0x1839, 0x183f, 0x1839, - 0x1839, 0x1839, 0x1839, 0x1839, 0x1843, 0x1839, 0x1839, 0x1839, - 0x1839, 0x1839, 0x1847, 0x1839, 0x1839, 0x1839, 0x1839, 0x1839, - 0x184b, 0x080c, 0x0df6, 0xa774, 0xa678, 0x0804, 0x18ef, 0xa78c, - 0xa690, 0x0804, 0x18ef, 0xa7a4, 0xa6a8, 0x0804, 0x18ef, 0xa7bc, - 0xa6c0, 0x0804, 0x18ef, 0xa7d4, 0xa6d8, 0x0804, 0x18ef, 0x2c05, - 0x908a, 0x0036, 0x1a0c, 0x0df6, 0x9082, 0x001b, 0x0002, 0x1872, - 0x1872, 0x1874, 0x1872, 0x1872, 0x1872, 0x187a, 0x1872, 0x1872, - 0x1872, 0x1880, 0x1872, 0x1872, 0x1872, 0x1886, 0x1872, 0x1872, - 0x1872, 0x188c, 0x1872, 0x1872, 0x1872, 0x1892, 0x1872, 0x1872, - 0x1872, 0x1898, 0x080c, 0x0df6, 0xa574, 0xa478, 0xa37c, 0xa280, - 0x0804, 0x18ef, 0xa584, 0xa488, 0xa38c, 0xa290, 0x0804, 0x18ef, - 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x18ef, 0xa5a4, 0xa4a8, - 0xa3ac, 0xa2b0, 0x0804, 0x18ef, 0xa5b4, 0xa4b8, 0xa3bc, 0xa2c0, - 0x0804, 0x18ef, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, 0x0804, 0x18ef, - 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x18ef, 0x2c05, 0x908a, - 0x0034, 0x1a0c, 0x0df6, 0x9082, 0x001b, 0x0002, 0x18c1, 0x18bf, - 0x18bf, 0x18bf, 0x18bf, 0x18bf, 0x18c8, 0x18bf, 0x18bf, 0x18bf, - 0x18bf, 0x18bf, 0x18cf, 0x18bf, 0x18bf, 0x18bf, 0x18bf, 0x18bf, - 0x18d6, 0x18bf, 0x18bf, 0x18bf, 0x18bf, 0x18bf, 0x18dd, 0x080c, - 0x0df6, 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, - 0x1e7c, 0x1904, 0x17f8, 0x900e, 0x0050, 0x080c, 0x0df6, 0xab2e, - 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0x080c, 0x1e7c, 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, 0xa068, 0x0005, - 0xa974, 0xd1dc, 0x1108, 0x0005, 0xa934, 0xa88c, 0x9106, 0x1158, - 0xa938, 0xa890, 0x9106, 0x1138, 0x601c, 0xc084, 0x601e, 0x2009, - 0x0048, 0x0804, 0xa068, 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, 0x1365, - 0x8631, 0x1db8, 0x00ce, 0x781f, 0x0800, 0x2031, 0x0168, 0x00c6, - 0x7808, 0xd09c, 0x190c, 0x1365, 0x00ce, 0x2001, 0x0038, 0x080c, - 0x1a07, 0x7930, 0x9186, 0x0040, 0x0160, 0x9186, 0x0042, 0x190c, - 0x0df6, 0x2001, 0x001e, 0x8001, 0x1df0, 0x8631, 0x1d40, 0x080c, - 0x1a16, 0x000e, 0x6022, 0x012e, 0x0005, 0x080c, 0x1a03, 0x7827, - 0x0015, 0x7828, 0x9c06, 0x1db8, 0x782b, 0x0000, 0x0ca0, 0x00f6, - 0x2079, 0x0300, 0x7803, 0x0000, 0x78ab, 0x0004, 0x2001, 0xf000, - 0x8001, 0x090c, 0x0df6, 0x7aac, 0xd2ac, 0x1dd0, 0x00fe, 0x080c, - 0x717e, 0x1188, 0x2001, 0x0138, 0x2003, 0x0000, 0x2001, 0x0160, - 0x2003, 0x0000, 0x2011, 0x012c, 0xa001, 0xa001, 0x8211, 0x1de0, - 0x0059, 0x0804, 0x7246, 0x0479, 0x0039, 0x2001, 0x0160, 0x2502, - 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, 0x0200, 0x080c, - 0x2aa3, 0x2009, 0x003c, 0x080c, 0x2200, 0x2001, 0x015d, 0x2003, - 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, 0x816f, 0x70a0, - 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, 0x2003, - 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x132d, 0x7803, 0x0001, - 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, - 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x717e, 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, 0x1580, 0x7930, 0x0005, 0x2c08, 0x621c, 0x080c, - 0x15ad, 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, 0x2031, 0x0064, - 0x781c, 0x9084, 0x0007, 0x0170, 0x2001, 0x0038, 0x0c41, 0x9186, - 0x0040, 0x0904, 0x1a74, 0x2001, 0x001e, 0x0c69, 0x8631, 0x1d80, - 0x080c, 0x0df6, 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, 0x1a0d, - 0x9186, 0x0040, 0x190c, 0x0df6, 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, 0x0df6, - 0xa001, 0xa001, 0x781f, 0x0200, 0x0005, 0x0126, 0x2091, 0x2400, - 0x2071, 0x1a42, 0x2079, 0x0090, 0x012e, 0x0005, 0x9280, 0x0005, - 0x2004, 0x2048, 0xa97c, 0xd1dc, 0x1904, 0x1b09, 0xa964, 0x9184, - 0x0007, 0x0002, 0x1a92, 0x1af4, 0x1aa9, 0x1aa9, 0x1aa9, 0x1adc, - 0x1abc, 0x1aab, 0x918c, 0x00ff, 0x9186, 0x0008, 0x1170, 0xa87c, - 0xd0b4, 0x0904, 0x1cbf, 0x9006, 0xa842, 0xa83e, 0xa988, 0x2900, - 0xa85a, 0xa813, 0x1eb9, 0x0804, 0x1b05, 0x9186, 0x0048, 0x0904, - 0x1af4, 0x080c, 0x0df6, 0xa87c, 0xd0b4, 0x0904, 0x1cbf, 0xa890, - 0xa842, 0xa83a, 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, - 0xa84a, 0xa988, 0x0804, 0x1afc, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x001e, 0x1d38, 0xa87c, 0xd0b4, 0x0904, 0x1cbf, 0xa890, 0xa842, - 0xa83a, 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, - 0xa804, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x1ebe, - 0x2005, 0xa812, 0xa988, 0x0448, 0x918c, 0x00ff, 0x9186, 0x0015, - 0x1540, 0xa87c, 0xd0b4, 0x0904, 0x1cbf, 0xa804, 0xa85a, 0x2040, - 0xa064, 0x9084, 0x000f, 0x9080, 0x1ebe, 0x2005, 0xa812, 0xa988, - 0x9006, 0xa842, 0xa83e, 0x0088, 0xa87c, 0xd0b4, 0x0904, 0x1cbf, - 0xa988, 0x9006, 0xa842, 0xa83e, 0x2900, 0xa85a, 0xa864, 0x9084, - 0x000f, 0x9080, 0x1ebe, 0x2005, 0xa812, 0xa916, 0xa87c, 0xc0dd, - 0xa87e, 0x0005, 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, - 0x1d00, 0x00e6, 0x2071, 0x1a42, 0x7000, 0x9005, 0x1904, 0x1b61, - 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, 0x1188, 0xa93c, 0xa834, 0x9106, 0x1168, 0x8aff, - 0x01a8, 0x0126, 0x2091, 0x8000, 0x00a1, 0x0108, 0x0091, 0x012e, - 0x9006, 0x00ee, 0x00fe, 0x0005, 0x0036, 0x0046, 0xab38, 0xac34, - 0x080c, 0x1ede, 0x004e, 0x003e, 0x0d50, 0x0c98, 0x9085, 0x0001, - 0x0c80, 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, - 0x0904, 0x1cb8, 0x700c, 0x7214, 0x923a, 0x7010, 0x7218, 0x9203, - 0x0a04, 0x1cb7, 0x9705, 0x0904, 0x1cb7, 0x903e, 0x2730, 0xa880, - 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1c9b, 0x1bdc, 0x1bdc, 0x1c9b, - 0x1c9b, 0x1c79, 0x1c9b, 0x1bdc, 0x1c7f, 0x1c2b, 0x1c2b, 0x1c9b, - 0x1c9b, 0x1c9b, 0x1c73, 0x1c2b, 0xc0fc, 0xa882, 0xab2c, 0xaa30, - 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x1c9d, 0x2c05, 0x908a, 0x0034, - 0x1a0c, 0x0df6, 0x9082, 0x001b, 0x0002, 0x1bc8, 0x1bc6, 0x1bc6, - 0x1bc6, 0x1bc6, 0x1bc6, 0x1bcc, 0x1bc6, 0x1bc6, 0x1bc6, 0x1bc6, - 0x1bc6, 0x1bd0, 0x1bc6, 0x1bc6, 0x1bc6, 0x1bc6, 0x1bc6, 0x1bd4, - 0x1bc6, 0x1bc6, 0x1bc6, 0x1bc6, 0x1bc6, 0x1bd8, 0x080c, 0x0df6, - 0xa774, 0xa678, 0x0804, 0x1c9d, 0xa78c, 0xa690, 0x0804, 0x1c9d, - 0xa7a4, 0xa6a8, 0x0804, 0x1c9d, 0xa7bc, 0xa6c0, 0x0804, 0x1c9d, - 0xa7d4, 0xa6d8, 0x0804, 0x1c9d, 0x2c05, 0x908a, 0x0036, 0x1a0c, - 0x0df6, 0x9082, 0x001b, 0x0002, 0x1bff, 0x1bff, 0x1c01, 0x1bff, - 0x1bff, 0x1bff, 0x1c07, 0x1bff, 0x1bff, 0x1bff, 0x1c0d, 0x1bff, - 0x1bff, 0x1bff, 0x1c13, 0x1bff, 0x1bff, 0x1bff, 0x1c19, 0x1bff, - 0x1bff, 0x1bff, 0x1c1f, 0x1bff, 0x1bff, 0x1bff, 0x1c25, 0x080c, - 0x0df6, 0xa574, 0xa478, 0xa37c, 0xa280, 0x0804, 0x1c9d, 0xa584, - 0xa488, 0xa38c, 0xa290, 0x0804, 0x1c9d, 0xa594, 0xa498, 0xa39c, - 0xa2a0, 0x0804, 0x1c9d, 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, - 0x1c9d, 0xa5b4, 0xa4b8, 0xa3bc, 0xa2c0, 0x0804, 0x1c9d, 0xa5c4, - 0xa4c8, 0xa3cc, 0xa2d0, 0x0804, 0x1c9d, 0xa5d4, 0xa4d8, 0xa3dc, - 0xa2e0, 0x0804, 0x1c9d, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0df6, - 0x9082, 0x001b, 0x0002, 0x1c4e, 0x1c4c, 0x1c4c, 0x1c4c, 0x1c4c, - 0x1c4c, 0x1c56, 0x1c4c, 0x1c4c, 0x1c4c, 0x1c4c, 0x1c4c, 0x1c5e, - 0x1c4c, 0x1c4c, 0x1c4c, 0x1c4c, 0x1c4c, 0x1c65, 0x1c4c, 0x1c4c, - 0x1c4c, 0x1c4c, 0x1c4c, 0x1c6c, 0x080c, 0x0df6, 0xa56c, 0xa470, - 0xa774, 0xa678, 0xa37c, 0xa280, 0x0804, 0x1c9d, 0xa584, 0xa488, - 0xa78c, 0xa690, 0xa394, 0xa298, 0x0804, 0x1c9d, 0xa59c, 0xa4a0, - 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x04c0, 0xa5b4, 0xa4b8, 0xa7bc, - 0xa6c0, 0xa3c4, 0xa2c8, 0x0488, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, - 0xa3dc, 0xa2e0, 0x0450, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, - 0x1510, 0x080c, 0x1e7c, 0x1904, 0x1b77, 0x900e, 0x04c8, 0xab64, - 0x939c, 0x00ff, 0x9386, 0x0048, 0x1180, 0x00c6, 0x7004, 0x2060, - 0x6004, 0x9086, 0x0043, 0x00ce, 0x0904, 0x1c2b, 0xab9c, 0x9016, - 0xad8c, 0xac90, 0xaf94, 0xae98, 0x0040, 0x9386, 0x0008, 0x0904, - 0x1c2b, 0x080c, 0x0df6, 0x080c, 0x0df6, 0x7b12, 0x7a16, 0x7d02, - 0x7c06, 0x7f0a, 0x7e0e, 0x782b, 0x0001, 0x7000, 0x8000, 0x7002, - 0xa83c, 0x9300, 0xa83e, 0xa840, 0x9201, 0xa842, 0x700c, 0x9300, - 0x700e, 0x7010, 0x9201, 0x7012, 0x080c, 0x1e7c, 0x0008, 0x9006, - 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, - 0x0df6, 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, - 0x7003, 0x0000, 0x7004, 0x2060, 0x6014, 0x2048, 0x080c, 0xbd4e, - 0x0118, 0xa880, 0xc0bd, 0xa882, 0x6020, 0x9086, 0x0006, 0x1180, - 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, - 0x9206, 0x1dc0, 0x60c4, 0xa89a, 0x60c8, 0xa896, 0x7004, 0x2060, - 0x00c6, 0x080c, 0xb983, 0x00ce, 0x2001, 0x19d1, 0x2004, 0x9c06, - 0x1160, 0x2009, 0x0040, 0x080c, 0x2200, 0x080c, 0x9a8f, 0x2011, - 0x0000, 0x080c, 0x992d, 0x080c, 0x8c6c, 0x002e, 0x0804, 0x1e2e, - 0x0126, 0x2091, 0x2400, 0xa858, 0x2040, 0x792c, 0x782b, 0x0002, - 0x9184, 0x0700, 0x1904, 0x1cc1, 0x7000, 0x0002, 0x1e2e, 0x1d12, - 0x1d7f, 0x1e2c, 0x8001, 0x7002, 0xd19c, 0x1150, 0x8aff, 0x05b0, - 0x080c, 0x1b71, 0x0904, 0x1e2e, 0x080c, 0x1b71, 0x0804, 0x1e2e, - 0x782b, 0x0004, 0xd194, 0x0148, 0xa880, 0xc0fc, 0xa882, 0x8aff, - 0x11d8, 0xa87c, 0xc0f5, 0xa87e, 0x00b8, 0x0026, 0x0036, 0xab3c, - 0xaa40, 0x7810, 0xa82e, 0x931a, 0x7814, 0xa832, 0x9213, 0x7800, - 0xa81e, 0x7804, 0xa822, 0xab3e, 0xaa42, 0x003e, 0x002e, 0x080c, - 0x1e94, 0xa880, 0xc0fd, 0xa882, 0x2a00, 0xa816, 0x2800, 0xa85a, - 0x2c00, 0xa812, 0x7003, 0x0000, 0x0804, 0x1e2e, 0x00f6, 0x0026, - 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, - 0x1984, 0x9085, 0x0012, 0x7816, 0x0036, 0x2019, 0x1000, 0x8319, - 0x090c, 0x0df6, 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, 0x0804, 0x1e2e, 0x8001, - 0x7002, 0xd194, 0x0170, 0x782c, 0xd0fc, 0x1904, 0x1d05, 0xd19c, - 0x1904, 0x1e2a, 0x8aff, 0x0904, 0x1e2e, 0x080c, 0x1b71, 0x0804, - 0x1e2e, 0x0026, 0x0036, 0xab3c, 0xaa40, 0x080c, 0x1e94, 0xdd9c, - 0x1904, 0x1de9, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0df6, 0x9082, - 0x001b, 0x0002, 0x1dbd, 0x1dbd, 0x1dbf, 0x1dbd, 0x1dbd, 0x1dbd, - 0x1dc5, 0x1dbd, 0x1dbd, 0x1dbd, 0x1dcb, 0x1dbd, 0x1dbd, 0x1dbd, - 0x1dd1, 0x1dbd, 0x1dbd, 0x1dbd, 0x1dd7, 0x1dbd, 0x1dbd, 0x1dbd, - 0x1ddd, 0x1dbd, 0x1dbd, 0x1dbd, 0x1de3, 0x080c, 0x0df6, 0xa07c, - 0x931a, 0xa080, 0x9213, 0x0804, 0x1d31, 0xa08c, 0x931a, 0xa090, - 0x9213, 0x0804, 0x1d31, 0xa09c, 0x931a, 0xa0a0, 0x9213, 0x0804, - 0x1d31, 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1d31, 0xa0bc, - 0x931a, 0xa0c0, 0x9213, 0x0804, 0x1d31, 0xa0cc, 0x931a, 0xa0d0, - 0x9213, 0x0804, 0x1d31, 0xa0dc, 0x931a, 0xa0e0, 0x9213, 0x0804, - 0x1d31, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0df6, 0x9082, 0x001b, - 0x0002, 0x1e0c, 0x1e0a, 0x1e0a, 0x1e0a, 0x1e0a, 0x1e0a, 0x1e12, - 0x1e0a, 0x1e0a, 0x1e0a, 0x1e0a, 0x1e0a, 0x1e18, 0x1e0a, 0x1e0a, - 0x1e0a, 0x1e0a, 0x1e0a, 0x1e1e, 0x1e0a, 0x1e0a, 0x1e0a, 0x1e0a, - 0x1e0a, 0x1e24, 0x080c, 0x0df6, 0xa07c, 0x931a, 0xa080, 0x9213, - 0x0804, 0x1d31, 0xa094, 0x931a, 0xa098, 0x9213, 0x0804, 0x1d31, - 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1d31, 0xa0c4, 0x931a, - 0xa0c8, 0x9213, 0x0804, 0x1d31, 0xa0dc, 0x931a, 0xa0e0, 0x9213, - 0x0804, 0x1d31, 0x0804, 0x1d2d, 0x080c, 0x0df6, 0x012e, 0x0005, - 0x00f6, 0x00e6, 0x2071, 0x1a42, 0x7000, 0x9086, 0x0000, 0x0904, - 0x1e79, 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, 0xd194, 0x01b8, - 0x2009, 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, 0x080c, 0xdbfc, - 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0df6, 0x0016, 0x2009, - 0x0040, 0x080c, 0x2200, 0x001e, 0x2001, 0x020c, 0x2102, 0x2009, - 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, - 0x0040, 0x080c, 0x2200, 0x782c, 0xd0fc, 0x09a8, 0x080c, 0x1d00, - 0x7000, 0x9086, 0x0000, 0x1978, 0x782b, 0x0004, 0x782c, 0xd0ac, - 0x1de8, 0x2009, 0x0040, 0x080c, 0x2200, 0x782b, 0x0002, 0x7003, - 0x0000, 0x00ee, 0x00fe, 0x0005, 0x8c60, 0x2c05, 0x9005, 0x0110, - 0x8a51, 0x0005, 0xa004, 0x9005, 0x0168, 0xa85a, 0x2040, 0xa064, - 0x9084, 0x000f, 0x9080, 0x1ebe, 0x2065, 0x8cff, 0x090c, 0x0df6, - 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8c61, 0x2c05, 0x9005, - 0x1190, 0x2800, 0x9906, 0x0120, 0xa000, 0x9005, 0x1108, 0x2900, - 0x2040, 0xa85a, 0xa064, 0x9084, 0x000f, 0x9080, 0x1ece, 0x2065, - 0x8cff, 0x090c, 0x0df6, 0x0005, 0x0000, 0x001d, 0x0021, 0x0025, - 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, 0x0021, 0x0027, - 0x002d, 0x0033, 0x0000, 0x0000, 0x0023, 0x0000, 0x0000, 0x1eb1, - 0x1ead, 0x0000, 0x0000, 0x1ebb, 0x0000, 0x1eb1, 0x1eb8, 0x1eb8, - 0x1eb5, 0x0000, 0x0000, 0x0000, 0x1ebb, 0x1eb8, 0x0000, 0x1eb3, - 0x1eb3, 0x0000, 0x0000, 0x1ebb, 0x0000, 0x1eb3, 0x1eb9, 0x1eb9, - 0x1eb9, 0x0000, 0x0000, 0x0000, 0x1ebb, 0x1eb9, 0x00c6, 0x00d6, - 0x0086, 0xab42, 0xac3e, 0xa888, 0x9055, 0x0904, 0x20bd, 0x2940, - 0xa064, 0x90ec, 0x000f, 0x9084, 0x00ff, 0x9086, 0x0008, 0x1118, - 0x2061, 0x1eb9, 0x00d0, 0x9de0, 0x1ebe, 0x9d86, 0x0007, 0x0130, - 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f, 0x1120, 0xa08c, 0x9422, - 0xa090, 0x931b, 0x2c05, 0x9065, 0x1140, 0x0310, 0x0804, 0x20bd, - 0xa004, 0x9045, 0x0904, 0x20bd, 0x08d8, 0x2c05, 0x9005, 0x0904, - 0x1fa5, 0xdd9c, 0x1904, 0x1f61, 0x908a, 0x0036, 0x1a0c, 0x0df6, - 0x9082, 0x001b, 0x0002, 0x1f36, 0x1f36, 0x1f38, 0x1f36, 0x1f36, - 0x1f36, 0x1f3e, 0x1f36, 0x1f36, 0x1f36, 0x1f44, 0x1f36, 0x1f36, - 0x1f36, 0x1f4a, 0x1f36, 0x1f36, 0x1f36, 0x1f50, 0x1f36, 0x1f36, - 0x1f36, 0x1f56, 0x1f36, 0x1f36, 0x1f36, 0x1f5c, 0x080c, 0x0df6, - 0xa07c, 0x9422, 0xa080, 0x931b, 0x0804, 0x1f9b, 0xa08c, 0x9422, - 0xa090, 0x931b, 0x0804, 0x1f9b, 0xa09c, 0x9422, 0xa0a0, 0x931b, - 0x0804, 0x1f9b, 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0804, 0x1f9b, - 0xa0bc, 0x9422, 0xa0c0, 0x931b, 0x0804, 0x1f9b, 0xa0cc, 0x9422, - 0xa0d0, 0x931b, 0x0804, 0x1f9b, 0xa0dc, 0x9422, 0xa0e0, 0x931b, - 0x04d0, 0x908a, 0x0034, 0x1a0c, 0x0df6, 0x9082, 0x001b, 0x0002, - 0x1f83, 0x1f81, 0x1f81, 0x1f81, 0x1f81, 0x1f81, 0x1f88, 0x1f81, - 0x1f81, 0x1f81, 0x1f81, 0x1f81, 0x1f8d, 0x1f81, 0x1f81, 0x1f81, - 0x1f81, 0x1f81, 0x1f92, 0x1f81, 0x1f81, 0x1f81, 0x1f81, 0x1f81, - 0x1f97, 0x080c, 0x0df6, 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, 0x20bd, 0x8c60, 0x0804, 0x1f0d, 0xa004, 0x9045, 0x0904, - 0x20bd, 0x0804, 0x1ee8, 0x8a51, 0x0904, 0x20bd, 0x8c60, 0x2c05, - 0x9005, 0x1158, 0xa004, 0x9045, 0x0904, 0x20bd, 0xa064, 0x90ec, - 0x000f, 0x9de0, 0x1ebe, 0x2c05, 0x2060, 0xa880, 0xc0fc, 0xa882, - 0x0804, 0x20b2, 0x2c05, 0x8422, 0x8420, 0x831a, 0x9399, 0x0000, - 0xac2e, 0xab32, 0xdd9c, 0x1904, 0x204f, 0x9082, 0x001b, 0x0002, - 0x1feb, 0x1feb, 0x1fed, 0x1feb, 0x1feb, 0x1feb, 0x1ffb, 0x1feb, - 0x1feb, 0x1feb, 0x2009, 0x1feb, 0x1feb, 0x1feb, 0x2017, 0x1feb, - 0x1feb, 0x1feb, 0x2025, 0x1feb, 0x1feb, 0x1feb, 0x2033, 0x1feb, - 0x1feb, 0x1feb, 0x2041, 0x080c, 0x0df6, 0xa17c, 0x2400, 0x9122, - 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0df6, 0xa074, 0x9420, 0xa078, - 0x9319, 0x0804, 0x20ad, 0xa18c, 0x2400, 0x9122, 0xa190, 0x2300, - 0x911b, 0x0a0c, 0x0df6, 0xa084, 0x9420, 0xa088, 0x9319, 0x0804, - 0x20ad, 0xa19c, 0x2400, 0x9122, 0xa1a0, 0x2300, 0x911b, 0x0a0c, - 0x0df6, 0xa094, 0x9420, 0xa098, 0x9319, 0x0804, 0x20ad, 0xa1ac, - 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0df6, 0xa0a4, - 0x9420, 0xa0a8, 0x9319, 0x0804, 0x20ad, 0xa1bc, 0x2400, 0x9122, - 0xa1c0, 0x2300, 0x911b, 0x0a0c, 0x0df6, 0xa0b4, 0x9420, 0xa0b8, - 0x9319, 0x0804, 0x20ad, 0xa1cc, 0x2400, 0x9122, 0xa1d0, 0x2300, - 0x911b, 0x0a0c, 0x0df6, 0xa0c4, 0x9420, 0xa0c8, 0x9319, 0x0804, - 0x20ad, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, 0x0a0c, - 0x0df6, 0xa0d4, 0x9420, 0xa0d8, 0x9319, 0x0804, 0x20ad, 0x9082, - 0x001b, 0x0002, 0x206d, 0x206b, 0x206b, 0x206b, 0x206b, 0x206b, - 0x207a, 0x206b, 0x206b, 0x206b, 0x206b, 0x206b, 0x2087, 0x206b, - 0x206b, 0x206b, 0x206b, 0x206b, 0x2094, 0x206b, 0x206b, 0x206b, - 0x206b, 0x206b, 0x20a1, 0x080c, 0x0df6, 0xa17c, 0x2400, 0x9122, - 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0df6, 0xa06c, 0x9420, 0xa070, - 0x9319, 0x0498, 0xa194, 0x2400, 0x9122, 0xa198, 0x2300, 0x911b, - 0x0a0c, 0x0df6, 0xa084, 0x9420, 0xa088, 0x9319, 0x0430, 0xa1ac, - 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0df6, 0xa09c, - 0x9420, 0xa0a0, 0x9319, 0x00c8, 0xa1c4, 0x2400, 0x9122, 0xa1c8, - 0x2300, 0x911b, 0x0a0c, 0x0df6, 0xa0b4, 0x9420, 0xa0b8, 0x9319, - 0x0060, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, 0x0a0c, - 0x0df6, 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, - 0x0def, 0x9084, 0x0007, 0x0002, 0x20de, 0x1d00, 0x20de, 0x20d4, - 0x20d7, 0x20da, 0x20d7, 0x20da, 0x080c, 0x1d00, 0x0005, 0x080c, - 0x11ee, 0x0005, 0x080c, 0x1d00, 0x080c, 0x11ee, 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, 0x21fd, 0x7900, 0xd1dc, 0x1118, 0x9084, - 0x0006, 0x001a, 0x9084, 0x000e, 0x0002, 0x2125, 0x211d, 0x7b33, - 0x211d, 0x211f, 0x211f, 0x211f, 0x211f, 0x7b19, 0x211d, 0x2121, - 0x211d, 0x211f, 0x211d, 0x211f, 0x211d, 0x080c, 0x0df6, 0x0031, - 0x0020, 0x080c, 0x7b19, 0x080c, 0x7b33, 0x0005, 0x0006, 0x0016, - 0x0026, 0x080c, 0xdbfc, 0x7930, 0x9184, 0x0003, 0x01c0, 0x2001, - 0x19d1, 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, 0x2004, 0x9005, - 0x090c, 0x0df6, 0x00c6, 0x2001, 0x19d1, 0x2064, 0x080c, 0xb983, - 0x00ce, 0x00f8, 0x2009, 0x0040, 0x080c, 0x2200, 0x00d0, 0x9184, - 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, 0x080c, 0x717e, - 0x1138, 0x080c, 0x747a, 0x080c, 0x5e2f, 0x080c, 0x709e, 0x0010, - 0x080c, 0x5cee, 0x080c, 0x7be2, 0x0041, 0x0018, 0x9184, 0x9540, - 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x0036, 0x0046, - 0x0056, 0x2071, 0x1a3f, 0x080c, 0x1977, 0x005e, 0x004e, 0x003e, - 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, 0x1800, 0x7128, - 0x2001, 0x1949, 0x2102, 0x2001, 0x1951, 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, 0x0def, - 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, 0x2a9d, 0x080c, 0x2974, - 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, 0x0558, 0x6054, 0x8004, - 0x8004, 0x8004, 0x8004, 0x9084, 0x000c, 0x6150, 0x918c, 0xfff3, - 0x9105, 0x6052, 0x6050, 0x9084, 0xb17f, 0x9085, 0x2000, 0x6052, - 0x2009, 0x1977, 0x2011, 0x1978, 0x6358, 0x939c, 0x38f0, 0x2320, - 0x080c, 0x29e1, 0x1238, 0x939d, 0x4003, 0x94a5, 0x8603, 0x230a, - 0x2412, 0x0030, 0x939d, 0x0203, 0x94a5, 0x8603, 0x230a, 0x2412, - 0x0050, 0x2001, 0x1977, 0x2003, 0x0700, 0x2001, 0x1978, 0x2003, - 0x0700, 0x080c, 0x2ba9, 0x9006, 0x080c, 0x29a3, 0x9006, 0x080c, - 0x2986, 0x20a9, 0x0012, 0x1d04, 0x2263, 0x2091, 0x6000, 0x1f04, - 0x2263, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, - 0x9084, 0xdfff, 0x6052, 0x6024, 0x6026, 0x080c, 0x26a6, 0x2009, - 0x00ef, 0x6132, 0x6136, 0x080c, 0x26b6, 0x60e7, 0x0000, 0x61ea, - 0x60e3, 0x0002, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, - 0x602f, 0x0000, 0x6007, 0x149f, 0x60bb, 0x0000, 0x20a9, 0x0018, - 0x60bf, 0x0000, 0x1f04, 0x2290, 0x60bb, 0x0000, 0x60bf, 0x0108, - 0x60bf, 0x0012, 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, 0x1834, 0x2003, 0x0000, 0x2001, - 0x1833, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, - 0x0016, 0x0026, 0x6124, 0x9184, 0x5e2c, 0x1118, 0x9184, 0x0007, - 0x002a, 0x9195, 0x0004, 0x9284, 0x0007, 0x0002, 0x22f0, 0x22d6, - 0x22d9, 0x22dc, 0x22e1, 0x22e3, 0x22e7, 0x22eb, 0x080c, 0x84e2, - 0x00b8, 0x080c, 0x85b1, 0x00a0, 0x080c, 0x85b1, 0x080c, 0x84e2, - 0x0078, 0x0099, 0x0068, 0x080c, 0x84e2, 0x0079, 0x0048, 0x080c, - 0x85b1, 0x0059, 0x0028, 0x080c, 0x85b1, 0x080c, 0x84e2, 0x0029, - 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x00a6, 0x6124, 0x6028, - 0xd09c, 0x0118, 0xd19c, 0x1904, 0x2547, 0xd1f4, 0x190c, 0x0def, - 0x080c, 0x717e, 0x0904, 0x234b, 0x080c, 0xc459, 0x1120, 0x7000, - 0x9086, 0x0003, 0x0570, 0x6024, 0x9084, 0x1800, 0x0550, 0x080c, - 0x71a1, 0x0118, 0x080c, 0x718f, 0x1520, 0x6027, 0x0020, 0x6043, - 0x0000, 0x080c, 0xc459, 0x0168, 0x080c, 0x71a1, 0x1150, 0x2001, - 0x1982, 0x2003, 0x0001, 0x6027, 0x1800, 0x080c, 0x6fed, 0x0804, - 0x254a, 0x70a0, 0x9005, 0x1150, 0x70a3, 0x0001, 0x00d6, 0x2069, - 0x0140, 0x080c, 0x71d2, 0x00de, 0x1904, 0x254a, 0x080c, 0x7484, - 0x0428, 0x080c, 0x71a1, 0x1590, 0x6024, 0x9084, 0x1800, 0x1108, - 0x0468, 0x080c, 0x7484, 0x080c, 0x747a, 0x080c, 0x5e2f, 0x080c, - 0x709e, 0x0804, 0x2547, 0xd1ac, 0x1508, 0x6024, 0xd0dc, 0x1170, - 0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc, 0x0130, 0x7094, 0x9086, - 0x0029, 0x1110, 0x080c, 0x7369, 0x0804, 0x2547, 0x080c, 0x747f, - 0x0048, 0x2001, 0x1957, 0x2003, 0x0002, 0x0020, 0x080c, 0x72cd, - 0x0804, 0x2547, 0x080c, 0x7403, 0x0804, 0x2547, 0xd1ac, 0x0904, - 0x2468, 0x080c, 0x717e, 0x11c0, 0x6027, 0x0020, 0x0006, 0x0026, - 0x0036, 0x080c, 0x7198, 0x1158, 0x080c, 0x747a, 0x080c, 0x5e2f, - 0x080c, 0x709e, 0x003e, 0x002e, 0x000e, 0x00ae, 0x0005, 0x003e, - 0x002e, 0x000e, 0x080c, 0x7156, 0x0016, 0x0046, 0x00c6, 0x644c, - 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, - 0x6043, 0x0010, 0x74d6, 0x948c, 0xff00, 0x7038, 0xd084, 0x0190, - 0x080c, 0xc459, 0x1118, 0x9186, 0xf800, 0x1160, 0x7044, 0xd084, - 0x1148, 0xc085, 0x7046, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, - 0x4a17, 0x003e, 0x080c, 0xc452, 0x1904, 0x2445, 0x9196, 0xff00, - 0x05a8, 0x705c, 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110, 0x9116, - 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, 0x31ee, 0x0128, 0xc18d, - 0x7132, 0x080c, 0x66c1, 0x1510, 0x6240, 0x9294, 0x0010, 0x0130, - 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030, 0xd08c, - 0x0904, 0x2445, 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, - 0xd1ac, 0x1904, 0x2445, 0xc1ad, 0x2102, 0x0036, 0x73d4, 0x2011, - 0x8013, 0x080c, 0x4a17, 0x003e, 0x0804, 0x2445, 0x7038, 0xd08c, - 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, 0x2445, 0xc1ad, - 0x2102, 0x0036, 0x73d4, 0x2011, 0x8013, 0x080c, 0x4a17, 0x003e, - 0x7130, 0xc185, 0x7132, 0x2011, 0x185c, 0x220c, 0x00f0, 0x0016, - 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8450, 0x2019, 0x000e, - 0x00c6, 0x2061, 0x0000, 0x080c, 0xd7af, 0x00ce, 0x9484, 0x00ff, - 0x9080, 0x31f3, 0x200d, 0x918c, 0xff00, 0x810f, 0x2120, 0x9006, - 0x2009, 0x000e, 0x080c, 0xd837, 0x001e, 0xd1ac, 0x1148, 0x0016, - 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x3060, 0x001e, 0x00a8, - 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x63a3, 0x1140, - 0x7030, 0xd084, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x5e49, - 0x8108, 0x1f04, 0x2435, 0x00be, 0x015e, 0x00ce, 0x004e, 0x080c, - 0x9f70, 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, 0x1825, 0x2003, 0x0000, 0x6027, 0x0020, - 0xd194, 0x0904, 0x2547, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x24f0, - 0x080c, 0x82d9, 0x080c, 0x961a, 0x6027, 0x0004, 0x00f6, 0x2019, - 0x19cb, 0x2304, 0x907d, 0x0904, 0x24bf, 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, - 0x2b7f, 0x2001, 0x001e, 0x8001, 0x0240, 0x20a9, 0x0009, 0x080c, - 0x2a78, 0x6904, 0xd1dc, 0x1140, 0x0cb0, 0x2001, 0x0100, 0x080c, - 0x2b6f, 0x9006, 0x080c, 0x2b6f, 0x080c, 0x8a83, 0x080c, 0x8b8f, - 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, 0x080c, 0x9fea, 0x009e, - 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x00ae, 0x0005, 0x00fe, - 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, - 0x2b7f, 0x00de, 0x00c6, 0x2061, 0x19c2, 0x6028, 0x080c, 0xc459, - 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, 0x909a, 0x00c8, 0x1238, - 0x8000, 0x602a, 0x00ce, 0x080c, 0x95f6, 0x0804, 0x2546, 0x2061, - 0x0100, 0x62c0, 0x080c, 0x9df6, 0x2019, 0x19cb, 0x2304, 0x9065, - 0x0120, 0x2009, 0x0027, 0x080c, 0xa068, 0x00ce, 0x0804, 0x2546, - 0xd2bc, 0x0904, 0x2533, 0x080c, 0x82e6, 0x6014, 0x9084, 0x1984, - 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, - 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2b7f, 0x00de, 0x00c6, - 0x2061, 0x19c2, 0x6044, 0x080c, 0xc459, 0x0120, 0x909a, 0x0003, - 0x1628, 0x0018, 0x909a, 0x00c8, 0x1608, 0x8000, 0x6046, 0x603c, - 0x00ce, 0x9005, 0x0558, 0x2009, 0x07d0, 0x080c, 0x82de, 0x9080, - 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x6114, 0x918c, 0x1984, - 0x918d, 0x0012, 0x6116, 0x00d0, 0x6114, 0x918c, 0x1984, 0x918d, - 0x0016, 0x6116, 0x0098, 0x6027, 0x0004, 0x0080, 0x0036, 0x2019, - 0x0001, 0x080c, 0x98b1, 0x003e, 0x2019, 0x19d1, 0x2304, 0x9065, - 0x0120, 0x2009, 0x004f, 0x080c, 0xa068, 0x00ce, 0x001e, 0xd19c, - 0x0904, 0x2611, 0x7038, 0xd0ac, 0x1904, 0x25e6, 0x0016, 0x0156, - 0x6027, 0x0008, 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, 0x0904, - 0x25c3, 0x6050, 0x9085, 0x0040, 0x6052, 0x6050, 0x9084, 0xfbcf, - 0x6052, 0x080c, 0x2a97, 0x9085, 0x2000, 0x6052, 0x20a9, 0x0012, - 0x1d04, 0x2568, 0x080c, 0x830d, 0x1f04, 0x2568, 0x6050, 0x9085, - 0x0400, 0x9084, 0xdfbf, 0x6052, 0x20a9, 0x0028, 0xa001, 0x1f04, - 0x2576, 0x6150, 0x9185, 0x1400, 0x6052, 0x20a9, 0x0366, 0x1d04, - 0x257f, 0x080c, 0x830d, 0x6020, 0xd09c, 0x1138, 0x015e, 0x6152, - 0x001e, 0x6027, 0x0008, 0x0804, 0x2611, 0x080c, 0x2a5f, 0x1f04, - 0x257f, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, - 0xc09c, 0x602a, 0x080c, 0x9f70, 0x60e3, 0x0000, 0x080c, 0xdbdb, - 0x080c, 0xdbf6, 0x080c, 0x54df, 0xd0fc, 0x1138, 0x080c, 0xc452, - 0x1120, 0x9085, 0x0001, 0x080c, 0x71c2, 0x9006, 0x080c, 0x2b6f, - 0x2009, 0x0002, 0x080c, 0x2a9d, 0x00e6, 0x2071, 0x1800, 0x7003, - 0x0004, 0x080c, 0x0ecc, 0x00ee, 0x6027, 0x0008, 0x080c, 0x0b8f, - 0x001e, 0x0804, 0x2611, 0x080c, 0x2ba9, 0x080c, 0x2bdc, 0x6050, - 0xc0e5, 0x6052, 0x20a9, 0x0367, 0x0f04, 0x25e4, 0x1d04, 0x25ce, - 0x080c, 0x830d, 0x6020, 0xd09c, 0x1db8, 0x00f6, 0x2079, 0x0100, - 0x080c, 0x29f1, 0x00fe, 0x1d80, 0x6050, 0xc0e4, 0x6052, 0x6027, - 0x0008, 0x015e, 0x001e, 0x0468, 0x015e, 0x001e, 0x0016, 0x6028, - 0xc09c, 0x602a, 0x080c, 0x9f70, 0x60e3, 0x0000, 0x080c, 0xdbdb, - 0x080c, 0xdbf6, 0x080c, 0x54df, 0xd0fc, 0x1138, 0x080c, 0xc452, - 0x1120, 0x9085, 0x0001, 0x080c, 0x71c2, 0x9006, 0x080c, 0x2b6f, - 0x2009, 0x0002, 0x080c, 0x2a9d, 0x00e6, 0x2071, 0x1800, 0x7003, - 0x0004, 0x080c, 0x0ecc, 0x00ee, 0x6027, 0x0008, 0x080c, 0x0b8f, - 0x001e, 0x918c, 0xffd0, 0x6126, 0x00ae, 0x0005, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1800, 0x71cc, 0x70ce, 0x9116, 0x0904, 0x2665, 0x81ff, 0x01a0, - 0x2009, 0x0000, 0x080c, 0x2a9d, 0x2011, 0x8011, 0x2019, 0x010e, - 0x231c, 0x939e, 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, - 0x0000, 0x080c, 0x4a17, 0x0448, 0x2001, 0x1983, 0x200c, 0x81ff, - 0x1140, 0x2001, 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, - 0x0008, 0x2118, 0x2011, 0x8012, 0x080c, 0x4a17, 0x080c, 0x0ecc, - 0x080c, 0x54df, 0xd0fc, 0x1188, 0x080c, 0xc452, 0x1170, 0x00c6, - 0x080c, 0x2701, 0x080c, 0x9818, 0x2061, 0x0100, 0x2019, 0x0028, - 0x2009, 0x0002, 0x080c, 0x3060, 0x00ce, 0x012e, 0x00fe, 0x00ee, - 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, - 0x2130, 0x9094, 0xff00, 0x11f0, 0x2011, 0x1836, 0x2214, 0xd2ac, - 0x11c8, 0x81ff, 0x01e8, 0x2011, 0x181e, 0x2204, 0x9106, 0x1190, - 0x2011, 0x181f, 0x2214, 0x9294, 0xff00, 0x9584, 0xff00, 0x9206, - 0x1148, 0x2011, 0x181f, 0x2214, 0x9294, 0x00ff, 0x9584, 0x00ff, - 0x9206, 0x1120, 0x2500, 0x080c, 0x7e3f, 0x0048, 0x9584, 0x00ff, - 0x9080, 0x31f3, 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, - 0x9080, 0x31f3, 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, - 0x0140, 0x2001, 0x1817, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, - 0x6852, 0x6856, 0x1f04, 0x26b1, 0x00de, 0x0005, 0x0006, 0x00d6, - 0x0026, 0x2069, 0x0140, 0x2001, 0x1817, 0x2102, 0x8114, 0x8214, - 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, - 0x1128, 0x9184, 0x000f, 0x9080, 0xe3a6, 0x2005, 0x6856, 0x8211, - 0x1f04, 0x26c6, 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, - 0x26f6, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, - 0x0005, 0x080c, 0x54db, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, - 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0xd837, 0x004e, 0x0005, - 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, - 0x276d, 0x080c, 0x29e1, 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, 0x847e, 0x928c, 0xff00, - 0x0110, 0x2011, 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, - 0x2009, 0x0138, 0x220a, 0x080c, 0x717e, 0x1118, 0x2009, 0x1947, - 0x220a, 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, - 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, - 0x200c, 0x8000, 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0def, - 0x002e, 0x001e, 0x000e, 0x012e, 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, 0x196a, - 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0df6, 0x0033, 0x00ee, 0x002e, - 0x001e, 0x000e, 0x015e, 0x0005, 0x27cb, 0x27e9, 0x280d, 0x280f, - 0x2838, 0x283a, 0x283c, 0x2001, 0x0001, 0x080c, 0x2616, 0x080c, - 0x2a51, 0x2001, 0x196c, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, - 0x782a, 0x9006, 0x20a9, 0x0009, 0x080c, 0x29fd, 0x2001, 0x196a, - 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x283d, 0x080c, 0x82eb, - 0x0005, 0x2009, 0x196f, 0x200b, 0x0000, 0x2001, 0x1974, 0x2003, - 0x0036, 0x2001, 0x1973, 0x2003, 0x002a, 0x2001, 0x196c, 0x2003, - 0x0001, 0x9006, 0x080c, 0x2986, 0x2001, 0xffff, 0x20a9, 0x0009, - 0x080c, 0x29fd, 0x2001, 0x196a, 0x2003, 0x0006, 0x2009, 0x001e, - 0x2011, 0x283d, 0x080c, 0x82eb, 0x0005, 0x080c, 0x0df6, 0x2001, - 0x1974, 0x2003, 0x0036, 0x2001, 0x196c, 0x2003, 0x0003, 0x7a38, - 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x2986, 0x2001, 0x1970, 0x2003, 0x0000, 0x2001, - 0xffff, 0x20a9, 0x0009, 0x080c, 0x29fd, 0x2001, 0x196a, 0x2003, - 0x0006, 0x2009, 0x001e, 0x2011, 0x283d, 0x080c, 0x82eb, 0x0005, - 0x080c, 0x0df6, 0x080c, 0x0df6, 0x0005, 0x0006, 0x0016, 0x0026, - 0x00e6, 0x00f6, 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, - 0x2001, 0x196c, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0df6, 0x0043, - 0x012e, 0x015e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, - 0x285f, 0x287b, 0x28b7, 0x28e3, 0x2903, 0x290f, 0x2911, 0x080c, - 0x29f1, 0x1190, 0x2009, 0x1972, 0x2104, 0x7a38, 0x9294, 0x0005, - 0x9296, 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, - 0x196a, 0x2003, 0x0001, 0x0030, 0x080c, 0x2935, 0x2001, 0xffff, - 0x080c, 0x27da, 0x0005, 0x080c, 0x2913, 0x05c0, 0x2009, 0x1973, - 0x2104, 0x8001, 0x200a, 0x080c, 0x29f1, 0x1158, 0x7a38, 0x9294, - 0x0005, 0x9296, 0x0005, 0x0518, 0x2009, 0x1972, 0x2104, 0xc085, - 0x200a, 0x2009, 0x196f, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, - 0x0118, 0x080c, 0x291b, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, - 0x0006, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x080c, 0x29a3, 0x2001, 0x196c, 0x2003, 0x0002, 0x0028, 0x2001, - 0x196a, 0x2003, 0x0003, 0x0010, 0x080c, 0x27fc, 0x0005, 0x080c, - 0x2913, 0x0540, 0x2009, 0x1973, 0x2104, 0x8001, 0x200a, 0x080c, - 0x29f1, 0x1148, 0x2001, 0x196a, 0x2003, 0x0003, 0x2001, 0x196b, - 0x2003, 0x0000, 0x00b8, 0x2009, 0x1973, 0x2104, 0x9005, 0x1118, - 0x080c, 0x2958, 0x0010, 0x080c, 0x2928, 0x080c, 0x291b, 0x2009, - 0x196f, 0x200b, 0x0000, 0x2001, 0x196c, 0x2003, 0x0001, 0x080c, - 0x27fc, 0x0000, 0x0005, 0x0479, 0x01e8, 0x080c, 0x29f1, 0x1198, - 0x2009, 0x1970, 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, - 0x0078, 0x2001, 0x1975, 0x2003, 0x000a, 0x2009, 0x1972, 0x2104, - 0xc0fd, 0x200a, 0x0038, 0x00f9, 0x2001, 0x196c, 0x2003, 0x0004, - 0x080c, 0x2827, 0x0005, 0x0079, 0x0148, 0x080c, 0x29f1, 0x1118, - 0x080c, 0x2813, 0x0018, 0x0079, 0x080c, 0x2827, 0x0005, 0x080c, - 0x0df6, 0x080c, 0x0df6, 0x2009, 0x1974, 0x2104, 0x8001, 0x200a, - 0x090c, 0x2974, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, - 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29a3, 0x0005, - 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, - 0x2001, 0x0001, 0x080c, 0x2986, 0x0005, 0x2009, 0x196f, 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, 0x29a3, 0x0005, - 0x0086, 0x2001, 0x1972, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0df6, - 0x2009, 0x1971, 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, - 0x1120, 0xd084, 0x1120, 0x080c, 0x0df6, 0x9006, 0x0010, 0x2001, - 0x0001, 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x196a, - 0x20a9, 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, 0x297a, 0x2001, - 0x1971, 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, - 0x0100, 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, - 0x0004, 0x783a, 0x2009, 0x1977, 0x210c, 0x795a, 0x0050, 0x7838, - 0x9084, 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, 0x1978, 0x210c, - 0x795a, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, - 0x0188, 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x2001, - 0x0100, 0x2004, 0x9086, 0x000a, 0x1120, 0x7850, 0x9084, 0xfff0, - 0x7852, 0x0428, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005, 0x783a, - 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, 0x11c8, 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, 0x2a97, 0xd09c, - 0x1110, 0x1f04, 0x29f4, 0x015e, 0x0005, 0x0126, 0x0016, 0x0006, - 0x2091, 0x8000, 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, 0x0170, - 0x7850, 0x9085, 0x0040, 0x7852, 0x7850, 0x9084, 0xfbcf, 0x7852, - 0x080c, 0x2a97, 0x9085, 0x2000, 0x7852, 0x0000, 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, 0x2a31, 0x080c, 0x830d, 0x1f04, 0x2a31, 0x2001, - 0x0100, 0x2004, 0x9086, 0x000a, 0x0160, 0x7850, 0x9085, 0x0400, - 0x9084, 0xdfbf, 0x7852, 0x080c, 0x2a97, 0x9085, 0x1000, 0x7852, - 0x0020, 0x7850, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, 0x012e, - 0x0005, 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, 0x0128, 0x7850, - 0x9084, 0xffcf, 0x7852, 0x0010, 0x080c, 0x2bdc, 0x0005, 0x0006, - 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, - 0x1130, 0x7820, 0xd0e4, 0x1140, 0x1f04, 0x2a69, 0x0028, 0x7854, - 0xd08c, 0x1110, 0x1f04, 0x2a6f, 0x00fe, 0x015e, 0x000e, 0x0005, - 0x1d04, 0x2a78, 0x080c, 0x830d, 0x1f04, 0x2a78, 0x0005, 0x0006, - 0x2001, 0x1976, 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, - 0x2001, 0x1976, 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, 0x0006, - 0x2001, 0x1976, 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, 0xa001, - 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006, 0x2001, 0x1983, - 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, 0x2b10, 0x0048, 0x0016, 0x2009, 0x1a58, 0x2104, 0x8000, - 0x0208, 0x200a, 0x001e, 0x04f0, 0x2009, 0x00a2, 0x080c, 0x0e7b, - 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, 0x1a59, 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, 0x195b, 0x200c, 0x080c, 0x0e7b, - 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, 0x7198, 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, - 0x7198, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, 0x001e, 0x000e, - 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x2061, 0x0100, 0x6050, - 0x9084, 0xfbff, 0x9085, 0x0040, 0x6052, 0x20a9, 0x0002, 0x080c, - 0x2a78, 0x6050, 0x9085, 0x0400, 0x9084, 0xff9f, 0x6052, 0x20a9, - 0x0005, 0x080c, 0x2a78, 0x6054, 0xd0bc, 0x090c, 0x0df6, 0x20a9, - 0x0005, 0x080c, 0x2a78, 0x6054, 0xd0ac, 0x090c, 0x0df6, 0x2009, - 0x198a, 0x9084, 0x7e00, 0x8007, 0x8004, 0x8004, 0x200a, 0x00ce, - 0x003e, 0x002e, 0x001e, 0x0005, 0x0006, 0x00c6, 0x2061, 0x0100, - 0x6050, 0xc0cd, 0x6052, 0x00ce, 0x000e, 0x0005, 0x0006, 0x0156, - 0x6050, 0x9085, 0x0040, 0x6052, 0x6050, 0x9084, 0xfbcf, 0x6052, - 0x080c, 0x2a97, 0x9085, 0x2000, 0x6052, 0x20a9, 0x0012, 0x1d04, - 0x2bf7, 0x080c, 0x830d, 0x1f04, 0x2bf7, 0x6050, 0x9085, 0x0400, - 0x9084, 0xdfbf, 0x6052, 0x015e, 0x000e, 0x0005, 0x2e72, 0x2e72, - 0x2c96, 0x2c96, 0x2ca2, 0x2ca2, 0x2cae, 0x2cae, 0x2cbc, 0x2cbc, - 0x2cc8, 0x2cc8, 0x2cd6, 0x2cd6, 0x2ce4, 0x2ce4, 0x2cf6, 0x2cf6, - 0x2d02, 0x2d02, 0x2d10, 0x2d10, 0x2d2e, 0x2d2e, 0x2d4e, 0x2d4e, - 0x2d1e, 0x2d1e, 0x2d3e, 0x2d3e, 0x2d5c, 0x2d5c, 0x2cf4, 0x2cf4, - 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, - 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, - 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, - 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2d6e, 0x2d6e, - 0x2d7a, 0x2d7a, 0x2d88, 0x2d88, 0x2d96, 0x2d96, 0x2da6, 0x2da6, - 0x2db4, 0x2db4, 0x2dc4, 0x2dc4, 0x2dd4, 0x2dd4, 0x2de6, 0x2de6, - 0x2df4, 0x2df4, 0x2e04, 0x2e04, 0x2e26, 0x2e26, 0x2e48, 0x2e48, - 0x2e14, 0x2e14, 0x2e37, 0x2e37, 0x2e57, 0x2e57, 0x2cf4, 0x2cf4, - 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, - 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, - 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, - 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, - 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, - 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x2cf4, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22bc, - 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x20c3, 0x0804, 0x2e6a, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20c3, - 0x080c, 0x22bc, 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20fe, 0x0804, 0x2e6a, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x22bc, 0x080c, 0x20fe, 0x0804, 0x2e6a, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20c3, - 0x080c, 0x20fe, 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20c3, 0x080c, 0x22bc, - 0x080c, 0x20fe, 0x0804, 0x2e6a, 0xa001, 0x0cf0, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1365, - 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x22bc, 0x080c, 0x1365, 0x0804, 0x2e6a, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20c3, 0x080c, 0x1365, 0x0804, 0x2e6a, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22bc, - 0x080c, 0x1365, 0x080c, 0x20fe, 0x0804, 0x2e6a, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20c3, - 0x080c, 0x22bc, 0x080c, 0x1365, 0x0804, 0x2e6a, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20c3, - 0x080c, 0x1365, 0x080c, 0x20fe, 0x0804, 0x2e6a, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1365, - 0x080c, 0x20fe, 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20c3, 0x080c, 0x22bc, - 0x080c, 0x1365, 0x080c, 0x20fe, 0x0804, 0x2e6a, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2770, - 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2770, 0x080c, 0x22bc, 0x0804, 0x2e6a, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2770, 0x080c, 0x20c3, 0x0804, 0x2e6a, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2770, - 0x080c, 0x20c3, 0x080c, 0x22bc, 0x0804, 0x2e6a, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2770, - 0x080c, 0x20fe, 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2770, 0x080c, 0x22bc, - 0x080c, 0x20fe, 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2770, 0x080c, 0x20c3, - 0x080c, 0x20fe, 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2770, 0x080c, 0x20c3, - 0x080c, 0x22bc, 0x080c, 0x20fe, 0x0804, 0x2e6a, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2770, - 0x080c, 0x1365, 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2770, 0x080c, 0x22bc, - 0x080c, 0x1365, 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2770, 0x080c, 0x20c3, - 0x080c, 0x1365, 0x0804, 0x2e6a, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2770, 0x080c, 0x22bc, - 0x080c, 0x1365, 0x080c, 0x20fe, 0x0804, 0x2e6a, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2770, - 0x080c, 0x20c3, 0x080c, 0x22bc, 0x080c, 0x1365, 0x0498, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2770, 0x080c, 0x20c3, 0x080c, 0x1365, 0x080c, 0x20fe, 0x0410, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2770, 0x080c, 0x1365, 0x080c, 0x20fe, 0x0098, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2770, 0x080c, 0x20c3, 0x080c, 0x22bc, 0x080c, 0x1365, 0x080c, - 0x20fe, 0x0000, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, - 0x000e, 0x010e, 0x000d, 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, - 0x080c, 0x6687, 0x1904, 0x2f7c, 0x72d8, 0x2001, 0x1956, 0x2004, - 0x9005, 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, - 0x2f7c, 0x080c, 0x2f81, 0x0804, 0x2f7c, 0xd2cc, 0x1904, 0x2f7c, - 0x080c, 0x717e, 0x1120, 0x70ab, 0xffff, 0x0804, 0x2f7c, 0xd294, - 0x0120, 0x70ab, 0xffff, 0x0804, 0x2f7c, 0x080c, 0x31e9, 0x0160, - 0x080c, 0xc459, 0x0128, 0x2001, 0x1817, 0x203c, 0x0804, 0x2f0b, - 0x70ab, 0xffff, 0x0804, 0x2f7c, 0x2001, 0x1817, 0x203c, 0x7290, - 0xd284, 0x0904, 0x2f0b, 0xd28c, 0x1904, 0x2f0b, 0x0036, 0x73a8, - 0x938e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, - 0x2c04, 0x938c, 0x0001, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, - 0x9084, 0x00ff, 0x970e, 0x05a8, 0x908e, 0x0000, 0x0590, 0x908e, - 0x00ff, 0x1150, 0x7230, 0xd284, 0x1588, 0x7290, 0xc28d, 0x7292, - 0x70ab, 0xffff, 0x003e, 0x0478, 0x0026, 0x2011, 0x0010, 0x080c, - 0x66ed, 0x002e, 0x0118, 0x70ab, 0xffff, 0x0410, 0x900e, 0x080c, - 0x266d, 0x080c, 0x6343, 0x11c0, 0x080c, 0x66c9, 0x1168, 0x7030, - 0xd08c, 0x0130, 0xb800, 0xd0bc, 0x0138, 0x080c, 0x65c3, 0x0120, - 0x080c, 0x2f9a, 0x0148, 0x0028, 0x080c, 0x30da, 0x080c, 0x2fc6, - 0x0118, 0x8318, 0x0804, 0x2ebd, 0x73aa, 0x0010, 0x70ab, 0xffff, - 0x003e, 0x0804, 0x2f7c, 0x9780, 0x31f3, 0x203d, 0x97bc, 0xff00, - 0x873f, 0x2041, 0x007e, 0x70a8, 0x9096, 0xffff, 0x1118, 0x900e, - 0x28a8, 0x0050, 0x9812, 0x0220, 0x2008, 0x9802, 0x20a8, 0x0020, - 0x70ab, 0xffff, 0x0804, 0x2f7c, 0x2700, 0x0156, 0x0016, 0x9106, - 0x0904, 0x2f71, 0x0026, 0x2011, 0x0010, 0x080c, 0x66ed, 0x002e, - 0x0120, 0x2009, 0xffff, 0x0804, 0x2f79, 0xc484, 0x080c, 0x63a3, - 0x0150, 0x080c, 0xc459, 0x15a8, 0x080c, 0x31e9, 0x1590, 0x080c, - 0x6343, 0x15b8, 0x0008, 0xc485, 0x080c, 0x66c9, 0x1130, 0x7030, - 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0, 0x7290, 0xd28c, 0x0180, - 0x080c, 0x66c9, 0x9082, 0x0006, 0x02e0, 0xd484, 0x1118, 0x080c, - 0x6367, 0x0028, 0x080c, 0x3165, 0x01a0, 0x080c, 0x3190, 0x0088, - 0x080c, 0x30da, 0x080c, 0xc459, 0x1160, 0x080c, 0x2fc6, 0x0188, - 0x0040, 0x080c, 0xc459, 0x1118, 0x080c, 0x3165, 0x0110, 0x0451, - 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2f24, 0x70ab, 0xffff, - 0x0018, 0x001e, 0x015e, 0x71aa, 0x004e, 0x002e, 0x00ce, 0x00be, - 0x0005, 0x00c6, 0x0016, 0x70ab, 0x0001, 0x2009, 0x007e, 0x080c, - 0x6343, 0x1168, 0xb813, 0x00ff, 0xb817, 0xfffe, 0x080c, 0x30da, - 0x04a9, 0x0128, 0x70d8, 0xc0bd, 0x70da, 0x080c, 0xc1a1, 0x001e, - 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x1860, - 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, 0xa03b, 0x01d0, 0x2b00, - 0x6012, 0x080c, 0xc1ca, 0x6023, 0x0001, 0x9006, 0x080c, 0x62e0, - 0x2001, 0x0000, 0x080c, 0x62f4, 0x0126, 0x2091, 0x8000, 0x70a4, - 0x8000, 0x70a6, 0x012e, 0x2009, 0x0004, 0x080c, 0xa068, 0x9085, - 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, 0x0076, - 0x00d6, 0x00c6, 0x2001, 0x1860, 0x2004, 0x9084, 0x00ff, 0xb842, - 0x080c, 0xa03b, 0x0548, 0x2b00, 0x6012, 0xb800, 0xc0c4, 0xb802, - 0xb8a0, 0x9086, 0x007e, 0x0140, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x1110, 0x080c, 0x3095, 0x080c, 0xc1ca, 0x6023, 0x0001, - 0x9006, 0x080c, 0x62e0, 0x2001, 0x0002, 0x080c, 0x62f4, 0x0126, - 0x2091, 0x8000, 0x70a4, 0x8000, 0x70a6, 0x012e, 0x2009, 0x0002, - 0x080c, 0xa068, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, - 0x0005, 0x00b6, 0x00c6, 0x0026, 0x2009, 0x0080, 0x080c, 0x6343, - 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, 0x0039, 0x0110, 0x70df, - 0xffff, 0x002e, 0x00ce, 0x00be, 0x0005, 0x0016, 0x0076, 0x00d6, - 0x00c6, 0x080c, 0x9f94, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xc1ca, - 0x6023, 0x0001, 0x9006, 0x080c, 0x62e0, 0x2001, 0x0002, 0x080c, - 0x62f4, 0x0126, 0x2091, 0x8000, 0x70e0, 0x8000, 0x70e2, 0x012e, - 0x2009, 0x0002, 0x080c, 0xa068, 0x9085, 0x0001, 0x00ce, 0x00de, - 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, 0x8000, - 0x2009, 0x007f, 0x080c, 0x6343, 0x11b8, 0xb813, 0x00ff, 0xb817, - 0xfffd, 0xb8bf, 0x0004, 0x080c, 0x9f94, 0x0170, 0x2b00, 0x6012, - 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, 0xc1ca, 0x2009, 0x0022, - 0x080c, 0xa068, 0x9085, 0x0001, 0x012e, 0x00de, 0x00ce, 0x0005, - 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x00b6, 0x21f0, 0x080c, - 0x878d, 0x080c, 0x8717, 0x080c, 0x9e3d, 0x080c, 0xaf81, 0x3e08, - 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, 0x20a9, - 0x007f, 0x900e, 0x0016, 0x080c, 0x63a3, 0x1140, 0x9686, 0x0002, - 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x5e49, 0x001e, 0x8108, - 0x1f04, 0x307a, 0x9686, 0x0001, 0x190c, 0x31bd, 0x00be, 0x002e, - 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0046, - 0x0036, 0x0026, 0x0016, 0x00b6, 0x6210, 0x2258, 0xbaa0, 0x0026, - 0x2019, 0x0029, 0x080c, 0x8782, 0x0076, 0x2039, 0x0000, 0x080c, - 0x8670, 0x2c08, 0x080c, 0xd556, 0x007e, 0x001e, 0xba10, 0xbb14, - 0xbcb0, 0x080c, 0x5e49, 0xba12, 0xbb16, 0xbcb2, 0x00be, 0x001e, - 0x002e, 0x003e, 0x004e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, - 0x00b6, 0x6010, 0x2058, 0xb8a0, 0x00be, 0x9086, 0x0080, 0x0150, - 0x2071, 0x1800, 0x70a4, 0x9005, 0x0110, 0x8001, 0x70a6, 0x000e, - 0x00ee, 0x0005, 0x2071, 0x1800, 0x70e0, 0x9005, 0x0dc0, 0x8001, - 0x70e2, 0x0ca8, 0xb800, 0xc08c, 0xb802, 0x0005, 0x00f6, 0x00e6, - 0x00c6, 0x00b6, 0x0046, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, - 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0070, 0x080c, 0x54db, 0xd0c4, - 0x0138, 0x0030, 0x9006, 0x2020, 0x2009, 0x002d, 0x080c, 0xd837, - 0x20a9, 0x0800, 0x9016, 0x0026, 0x928e, 0x007e, 0x0904, 0x3144, - 0x928e, 0x007f, 0x0904, 0x3144, 0x928e, 0x0080, 0x05e8, 0x9288, - 0x1000, 0x210c, 0x81ff, 0x05c0, 0x8fff, 0x1148, 0x2001, 0x1968, - 0x0006, 0x2003, 0x0001, 0x04f1, 0x000e, 0x2003, 0x0000, 0x00b6, - 0x00c6, 0x2158, 0x2001, 0x0001, 0x080c, 0x6693, 0x00ce, 0x00be, - 0x2019, 0x0029, 0x080c, 0x8782, 0x0076, 0x2039, 0x0000, 0x080c, - 0x8670, 0x00b6, 0x00c6, 0x0026, 0x2158, 0xba04, 0x9294, 0x00ff, - 0x9286, 0x0006, 0x1118, 0xb807, 0x0404, 0x0028, 0x2001, 0x0004, - 0x8007, 0x9215, 0xba06, 0x002e, 0x00ce, 0x00be, 0x0016, 0x2c08, - 0x080c, 0xd556, 0x001e, 0x007e, 0x002e, 0x8210, 0x1f04, 0x30fb, - 0x015e, 0x001e, 0x002e, 0x003e, 0x004e, 0x00be, 0x00ce, 0x00ee, - 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x080c, 0x54db, 0xd0c4, - 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2220, 0x2009, 0x0029, 0x080c, - 0xd837, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x7290, 0x82ff, 0x01e8, 0x080c, 0x66c1, 0x11d0, 0x2100, - 0x080c, 0x26a0, 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, 0x1a88, 0x001e, 0x6112, 0x080c, 0x3095, 0x001e, - 0x080c, 0x6367, 0x012e, 0x00ce, 0x001e, 0x0005, 0x0016, 0x0026, - 0x2110, 0x080c, 0x9ad0, 0x080c, 0xdaf0, 0x002e, 0x001e, 0x0005, - 0x2001, 0x1836, 0x2004, 0xd0cc, 0x0005, 0x00c6, 0x00b6, 0x080c, - 0x717e, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, 0x080c, - 0x717e, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x9180, 0x1000, - 0x2004, 0x905d, 0x0130, 0x86ff, 0x0110, 0xb800, 0xd0bc, 0x090c, - 0x6367, 0x8108, 0x1f04, 0x31ce, 0x2061, 0x1800, 0x607b, 0x0000, - 0x607c, 0x9084, 0x00ff, 0x607e, 0x60af, 0x0000, 0x00be, 0x00ce, - 0x0005, 0x2001, 0x187d, 0x2004, 0xd0bc, 0x0005, 0x2011, 0x185c, - 0x2214, 0xd2ec, 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, 0x189c, 0x7003, 0x0002, 0x9006, - 0x7016, 0x701a, 0x704a, 0x704e, 0x700e, 0x7042, 0x7046, 0x703b, - 0x18b8, 0x703f, 0x18b8, 0x7007, 0x0001, 0x080c, 0x1050, 0x090c, - 0x0df6, 0x2900, 0x706a, 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x080c, - 0x1050, 0x090c, 0x0df6, 0x2900, 0x706e, 0xa867, 0x0002, 0xa8ab, - 0xdcb0, 0x0005, 0x2071, 0x189c, 0x7004, 0x0002, 0x3322, 0x3323, - 0x3336, 0x334a, 0x0005, 0x1004, 0x3333, 0x0e04, 0x3333, 0x2079, - 0x0000, 0x0126, 0x2091, 0x8000, 0x700c, 0x9005, 0x1128, 0x700f, - 0x0001, 0x012e, 0x0468, 0x0005, 0x012e, 0x0ce8, 0x2079, 0x0000, - 0x2061, 0x18b6, 0x2c4c, 0xa86c, 0x908e, 0x0100, 0x0128, 0x9086, - 0x0200, 0x0904, 0x341e, 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, 0x61cc, 0x0042, - 0x2100, 0x908a, 0x003f, 0x1a04, 0x341b, 0x61cc, 0x0804, 0x33b0, - 0x33f2, 0x342a, 0x341b, 0x3436, 0x3440, 0x3446, 0x344a, 0x345a, - 0x345e, 0x3474, 0x347a, 0x3480, 0x348b, 0x3496, 0x34a5, 0x34b4, - 0x34c2, 0x34d9, 0x34f4, 0x341b, 0x359d, 0x35db, 0x3681, 0x3692, - 0x36b5, 0x341b, 0x341b, 0x341b, 0x36ed, 0x3709, 0x3712, 0x3741, - 0x3747, 0x341b, 0x378d, 0x341b, 0x341b, 0x341b, 0x341b, 0x341b, - 0x3798, 0x37a1, 0x37a9, 0x37ab, 0x341b, 0x341b, 0x341b, 0x341b, - 0x341b, 0x341b, 0x37d7, 0x341b, 0x341b, 0x341b, 0x341b, 0x341b, - 0x37f4, 0x3868, 0x341b, 0x341b, 0x341b, 0x341b, 0x341b, 0x341b, - 0x0002, 0x3892, 0x3895, 0x38f4, 0x390d, 0x393d, 0x3bdf, 0x341b, - 0x509e, 0x341b, 0x341b, 0x341b, 0x341b, 0x341b, 0x341b, 0x341b, - 0x341b, 0x3474, 0x347a, 0x416d, 0x54ff, 0x4183, 0x512d, 0x517f, - 0x528a, 0x341b, 0x52ec, 0x5328, 0x5359, 0x5461, 0x5386, 0x53e1, - 0x341b, 0x4187, 0x4336, 0x434c, 0x4371, 0x43d6, 0x444a, 0x446a, - 0x44e1, 0x453d, 0x4599, 0x459c, 0x45c1, 0x4636, 0x469c, 0x46a4, - 0x47d9, 0x4941, 0x4975, 0x4bbf, 0x341b, 0x4bdd, 0x4c9a, 0x4d77, - 0x341b, 0x341b, 0x341b, 0x341b, 0x4ddd, 0x4df8, 0x46a4, 0x503e, - 0x714c, 0x0000, 0x2021, 0x4000, 0x080c, 0x49f3, 0x0126, 0x2091, - 0x8000, 0x0e04, 0x33fc, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, - 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7c82, - 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x11e6, 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, 0x4a00, 0x2039, 0x0001, - 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x4a03, - 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, 0x33f2, 0x7984, 0x2114, - 0x0804, 0x33f2, 0x20e1, 0x0000, 0x2099, 0x0021, 0x20e9, 0x0000, - 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, 0x7984, 0x7a88, 0x7b8c, - 0x0804, 0x33f2, 0x7884, 0x2060, 0x0804, 0x34a7, 0x2009, 0x0003, - 0x2011, 0x0003, 0x2019, 0x0012, 0x789b, 0x0317, 0x7893, 0xffff, - 0x2001, 0x188d, 0x2004, 0x9005, 0x0118, 0x7896, 0x0804, 0x33f2, - 0x7897, 0x0001, 0x0804, 0x33f2, 0x2039, 0x0001, 0x7d98, 0x7c9c, - 0x0804, 0x342e, 0x2039, 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x343a, - 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x3427, 0x2138, 0x7d98, - 0x7c9c, 0x0804, 0x342e, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, - 0x3427, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x343a, 0x79a0, 0x9182, - 0x0040, 0x0210, 0x0804, 0x3427, 0x21e8, 0x7984, 0x7888, 0x20a9, - 0x0001, 0x21a0, 0x4004, 0x0804, 0x33f2, 0x2061, 0x0800, 0xe10c, - 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0x9005, - 0x0904, 0x33f2, 0x0804, 0x3421, 0x79a0, 0x9182, 0x0040, 0x0210, - 0x0804, 0x3427, 0x21e0, 0x20a9, 0x0001, 0x7984, 0x2198, 0x4012, - 0x0804, 0x33f2, 0x2069, 0x185b, 0x7884, 0x7990, 0x911a, 0x1a04, - 0x3427, 0x8019, 0x0904, 0x3427, 0x684a, 0x6942, 0x788c, 0x6852, - 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, 0x080c, 0x74ab, 0x0804, - 0x33f2, 0x2069, 0x185b, 0x7884, 0x7994, 0x911a, 0x1a04, 0x3427, - 0x8019, 0x0904, 0x3427, 0x684e, 0x6946, 0x788c, 0x6862, 0x7888, - 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, 0x2091, 0x8000, 0x080c, - 0x67f9, 0x012e, 0x0804, 0x33f2, 0x902e, 0x2520, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x3424, 0x7984, 0x7b88, 0x7a8c, 0x20a9, - 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a4, 0x4101, 0x080c, 0x49b7, - 0x1120, 0x2009, 0x0002, 0x0804, 0x3424, 0x2009, 0x0020, 0xa85c, - 0x9080, 0x0019, 0xaf60, 0x080c, 0x4a00, 0x701f, 0x3518, 0x0005, - 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, 0x0168, 0x9096, - 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, 0x9096, 0x0048, 0x0120, - 0x9096, 0x0029, 0x1904, 0x3424, 0x810f, 0x918c, 0x00ff, 0x0904, - 0x3424, 0x7112, 0x7010, 0x8001, 0x0560, 0x7012, 0x080c, 0x49b7, - 0x1120, 0x2009, 0x0002, 0x0804, 0x3424, 0x2009, 0x0020, 0x7068, - 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, 0x9290, 0x0040, 0x9399, - 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0xa85c, 0x9080, 0x0019, - 0xaf60, 0x080c, 0x4a00, 0x701f, 0x3556, 0x0005, 0xa864, 0x9084, - 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, 0x000a, 0x1904, 0x3424, - 0x0888, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, - 0x00ff, 0x9096, 0x0029, 0x1160, 0xc2fd, 0xaa7a, 0x080c, 0x5f3b, - 0x0150, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, 0x012e, 0x0050, - 0x080c, 0x6259, 0x1128, 0x7007, 0x0003, 0x701f, 0x3582, 0x0005, - 0x080c, 0x6c6b, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, - 0x0001, 0x2099, 0x18a4, 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, - 0x94a1, 0x0000, 0x95a9, 0x0000, 0xa85c, 0x9080, 0x0019, 0x2009, - 0x0020, 0x012e, 0xaf60, 0x0804, 0x4a03, 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, - 0x19f6, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, - 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, - 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x3424, 0x7984, 0x080c, - 0x63a3, 0x1904, 0x3427, 0x7e98, 0x9684, 0x3fff, 0x9082, 0x4000, - 0x1a04, 0x3427, 0x7c88, 0x7d8c, 0x080c, 0x6506, 0x080c, 0x64d5, - 0x0000, 0x1518, 0x2061, 0x1cd0, 0x0126, 0x2091, 0x8000, 0x6000, - 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, - 0x1118, 0xa870, 0x9506, 0x0150, 0x012e, 0x9ce0, 0x0018, 0x2001, - 0x1819, 0x2004, 0x9c02, 0x1a04, 0x3424, 0x0c30, 0x080c, 0xb983, - 0x012e, 0x0904, 0x3424, 0x0804, 0x33f2, 0x900e, 0x2001, 0x0005, - 0x080c, 0x6c6b, 0x0126, 0x2091, 0x8000, 0x080c, 0xc04a, 0x080c, - 0x6a22, 0x012e, 0x0804, 0x33f2, 0x00a6, 0x2950, 0xb198, 0x080c, - 0x63a3, 0x1904, 0x366e, 0xb6a4, 0x9684, 0x3fff, 0x9082, 0x4000, - 0x16e8, 0xb49c, 0xb5a0, 0x080c, 0x6506, 0x080c, 0x64d5, 0x1520, - 0x2061, 0x1cd0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, - 0x0148, 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, - 0x9506, 0x0158, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1819, 0x2004, - 0x9c02, 0x2009, 0x000d, 0x12b0, 0x0c28, 0x080c, 0xb983, 0x012e, - 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, 0x0005, 0x080c, - 0x6c6b, 0x0126, 0x2091, 0x8000, 0x080c, 0xc04a, 0x080c, 0x6a15, - 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, 0x3424, 0x080c, 0x49ce, 0x0904, 0x3427, - 0x080c, 0x646a, 0x0904, 0x3424, 0x080c, 0x650c, 0x0904, 0x3424, - 0x0804, 0x4461, 0x81ff, 0x1904, 0x3424, 0x080c, 0x49ea, 0x0904, - 0x3427, 0x080c, 0x659a, 0x0904, 0x3424, 0x2019, 0x0005, 0x79a8, - 0x080c, 0x6527, 0x0904, 0x3424, 0x7888, 0x908a, 0x1000, 0x1a04, - 0x3427, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x8267, 0x79a8, - 0xd184, 0x1904, 0x33f2, 0x0804, 0x4461, 0x0126, 0x2091, 0x8000, - 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x07ff, 0x6458, - 0x2400, 0x9506, 0x01f8, 0x2508, 0x080c, 0x63a3, 0x11d8, 0x080c, - 0x659a, 0x1128, 0x2009, 0x0002, 0x62bc, 0x2518, 0x00c0, 0x2019, - 0x0004, 0x900e, 0x080c, 0x6527, 0x1118, 0x2009, 0x0006, 0x0078, - 0x7884, 0x908a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0x9108, - 0x080c, 0x8267, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x33f2, 0x012e, - 0x0804, 0x3424, 0x012e, 0x0804, 0x3427, 0x080c, 0x49ce, 0x0904, - 0x3427, 0x080c, 0x646a, 0x0904, 0x3424, 0xbaa0, 0x2019, 0x0005, - 0x00c6, 0x9066, 0x080c, 0x8782, 0x0076, 0x903e, 0x080c, 0x8670, - 0x900e, 0x080c, 0xd556, 0x007e, 0x00ce, 0x080c, 0x6506, 0x0804, - 0x33f2, 0x080c, 0x49ce, 0x0904, 0x3427, 0x080c, 0x6506, 0x2208, - 0x0804, 0x33f2, 0x0156, 0x00d6, 0x00e6, 0x2069, 0x190e, 0x6810, - 0x6914, 0x910a, 0x1208, 0x900e, 0x6816, 0x9016, 0x901e, 0x20a9, - 0x007e, 0x2069, 0x1000, 0x2d04, 0x905d, 0x0118, 0xb84c, 0x0059, - 0x9210, 0x8d68, 0x1f04, 0x3723, 0x2300, 0x9218, 0x00ee, 0x00de, - 0x015e, 0x0804, 0x33f2, 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, - 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, - 0x0005, 0x2069, 0x190e, 0x6910, 0x62b8, 0x0804, 0x33f2, 0x81ff, - 0x0120, 0x2009, 0x0001, 0x0804, 0x3424, 0x0126, 0x2091, 0x8000, - 0x080c, 0x54ef, 0x0128, 0x2009, 0x0007, 0x012e, 0x0804, 0x3424, - 0x012e, 0x6158, 0x9190, 0x31f3, 0x2215, 0x9294, 0x00ff, 0x6378, - 0x83ff, 0x0108, 0x627c, 0x67d8, 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, 0x717e, 0x1118, 0x2031, - 0x0004, 0x0038, 0xd79c, 0x0120, 0x2009, 0x0005, 0x0804, 0x3424, - 0x9036, 0x7e9a, 0x7f9e, 0x0804, 0x33f2, 0x6148, 0x624c, 0x2019, - 0x1960, 0x231c, 0x2001, 0x1961, 0x2004, 0x789a, 0x0804, 0x33f2, - 0x0126, 0x2091, 0x8000, 0x6138, 0x623c, 0x6340, 0x012e, 0x0804, - 0x33f2, 0x080c, 0x49ea, 0x0904, 0x3427, 0xba44, 0xbb38, 0x0804, - 0x33f2, 0x080c, 0x0df6, 0x080c, 0x49ea, 0x2110, 0x0904, 0x3427, - 0xb804, 0x908c, 0x00ff, 0x918e, 0x0006, 0x0140, 0x9084, 0xff00, - 0x9086, 0x0600, 0x2009, 0x0009, 0x1904, 0x3424, 0x0126, 0x2091, - 0x8000, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, 0x9ad0, 0x080c, - 0x8782, 0x0076, 0x903e, 0x080c, 0x8670, 0x900e, 0x080c, 0xd556, - 0x007e, 0x00ce, 0xb807, 0x0407, 0x012e, 0x0804, 0x33f2, 0x6148, - 0x624c, 0x7884, 0x604a, 0x7b88, 0x634e, 0x2069, 0x185b, 0x831f, - 0x9305, 0x6816, 0x788c, 0x2069, 0x1960, 0x2d1c, 0x206a, 0x7e98, - 0x9682, 0x0014, 0x1210, 0x2031, 0x07d0, 0x2069, 0x1961, 0x2d04, - 0x266a, 0x789a, 0x0804, 0x33f2, 0x0126, 0x2091, 0x8000, 0x6138, - 0x7884, 0x603a, 0x910e, 0xd1b4, 0x190c, 0x0ee7, 0xd0c4, 0x01a8, - 0x00d6, 0x78a8, 0x2009, 0x1977, 0x200a, 0x78ac, 0x2011, 0x1978, - 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, - 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x2001, 0x0100, 0x2004, - 0x9086, 0x000a, 0x0168, 0x2011, 0x0114, 0x220c, 0x7888, 0xd08c, - 0x0118, 0x918d, 0x0080, 0x0010, 0x918c, 0xff7f, 0x2112, 0x0060, - 0x2011, 0x0116, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0040, - 0x0010, 0x918c, 0xff7f, 0x2112, 0x603c, 0x7988, 0x613e, 0x6140, - 0x910d, 0x788c, 0x6042, 0x7a88, 0x9294, 0x1000, 0x9205, 0x910e, - 0xd1e4, 0x190c, 0x0efd, 0x6040, 0xd0cc, 0x0120, 0x78b0, 0x2011, - 0x0114, 0x2012, 0x012e, 0x0804, 0x33f2, 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, 0x3427, 0x788c, - 0x902d, 0x0904, 0x3427, 0x900e, 0x080c, 0x63a3, 0x1120, 0xba44, - 0xbb38, 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, 0x8108, 0x0ca0, - 0x080c, 0x49ea, 0x0904, 0x3427, 0x7888, 0x900d, 0x0904, 0x3427, - 0x788c, 0x9005, 0x0904, 0x3427, 0xba44, 0xb946, 0xbb38, 0xb83a, - 0x0804, 0x33f2, 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, - 0x54ef, 0x1904, 0x3424, 0x00c6, 0x2061, 0x0100, 0x7984, 0x9186, - 0x00ff, 0x1130, 0x2001, 0x1817, 0x2004, 0x9085, 0xff00, 0x0088, - 0x9182, 0x007f, 0x16e0, 0x9188, 0x31f3, 0x210d, 0x918c, 0x00ff, - 0x2001, 0x1817, 0x2004, 0x0026, 0x9116, 0x002e, 0x0580, 0x810f, - 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x9f94, 0x000e, - 0x0510, 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, 0x6349, 0x2b08, - 0x00be, 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, 0x49b7, 0x01d0, - 0x9006, 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, 0xc0fd, 0xa86a, - 0x701f, 0x38ed, 0x2900, 0x6016, 0x2009, 0x0032, 0x080c, 0xa068, - 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x3424, 0x00ce, - 0x0804, 0x3427, 0x080c, 0x9fea, 0x0cb0, 0xa830, 0x9086, 0x0100, - 0x0904, 0x3424, 0x0804, 0x33f2, 0x2061, 0x1a4c, 0x0126, 0x2091, - 0x8000, 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, 0x2061, 0x1800, - 0x6350, 0x6070, 0x789a, 0x60bc, 0x789e, 0x60b8, 0x78aa, 0x012e, - 0x0804, 0x33f2, 0x900e, 0x2110, 0x0c88, 0x81ff, 0x1904, 0x3424, - 0x080c, 0x717e, 0x0904, 0x3424, 0x0126, 0x2091, 0x8000, 0x6250, - 0x6070, 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x26d6, 0x080c, - 0x5712, 0x012e, 0x0804, 0x33f2, 0x012e, 0x0804, 0x3427, 0x0006, - 0x0016, 0x00c6, 0x00e6, 0x2001, 0x1984, 0x2070, 0x2061, 0x185b, - 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x847e, 0x7206, - 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x33f4, 0x7884, - 0xd0fc, 0x0158, 0x2001, 0x002a, 0x2004, 0x9005, 0x0180, 0x9082, - 0x00e1, 0x0298, 0x012e, 0x0804, 0x3427, 0x2001, 0x002a, 0x2004, - 0x9005, 0x0128, 0x2069, 0x185b, 0x6908, 0x9102, 0x1230, 0x012e, - 0x0804, 0x3427, 0x012e, 0x0804, 0x3424, 0x080c, 0x9f69, 0x0dd0, - 0x7884, 0xd0fc, 0x0904, 0x39bc, 0x00c6, 0x080c, 0x49b7, 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, 0x3b42, 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, 0x4a00, 0x701f, 0x3a7f, - 0x7023, 0x0001, 0x012e, 0x0005, 0x0046, 0x0086, 0x0096, 0x00a6, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3927, 0x2001, - 0x197a, 0x2003, 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, - 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, - 0x3bb1, 0x080c, 0x3b70, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, - 0x1a42, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, - 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, - 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x3fb1, 0x008e, 0x00ee, - 0x00fe, 0x080c, 0x3ed3, 0x080c, 0x3d98, 0x05b8, 0x2001, 0x020b, - 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, 0x4025, 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, 0x181f, 0x2004, 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100, - 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, 0x080c, 0x3da2, 0x080c, - 0x3b6b, 0x0058, 0x080c, 0x3b6b, 0x080c, 0x3f49, 0x080c, 0x3ec9, - 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, - 0x12fe, 0x2009, 0x0028, 0x080c, 0x2200, 0x2001, 0x0227, 0x200c, - 0x2102, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, - 0x008e, 0x004e, 0x2001, 0x197a, 0x2004, 0x9005, 0x1118, 0x012e, - 0x0804, 0x33f2, 0x012e, 0x2021, 0x400c, 0x0804, 0x33f4, 0x0016, - 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, - 0x0156, 0x7014, 0x2048, 0x7020, 0x20a8, 0x8000, 0x7022, 0xa804, - 0x9005, 0x0904, 0x3adb, 0x2048, 0x1f04, 0x3a8f, 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, 0x4a00, 0x701f, - 0x3a7f, 0x00b0, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, - 0x0006, 0x080c, 0x0fb4, 0x000e, 0x080c, 0x4a03, 0x701f, 0x3a7f, - 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, - 0x002e, 0x001e, 0x0005, 0x7014, 0x2048, 0xa864, 0x9086, 0x0103, - 0x1118, 0x701f, 0x3b40, 0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd, - 0xa86a, 0x2009, 0x007f, 0x080c, 0x6343, 0x0110, 0x9006, 0x0030, - 0xb813, 0x00ff, 0xb817, 0xfffd, 0x080c, 0xc21d, 0x015e, 0x00de, - 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, - 0x0904, 0x3424, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, - 0x0086, 0x0096, 0x00d6, 0x0156, 0x701f, 0x3b12, 0x7007, 0x0003, - 0x0804, 0x3ad0, 0xa830, 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, - 0x33f4, 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, 0x0fb4, 0x000e, - 0x080c, 0x4a03, 0x007e, 0x701f, 0x3a7f, 0x7023, 0x0001, 0x0005, - 0x0804, 0x33f2, 0x0156, 0x00c6, 0xa814, 0x908a, 0x001e, 0x0218, - 0xa833, 0x001e, 0x0010, 0xa832, 0x0078, 0x81ff, 0x0168, 0x0016, - 0x080c, 0x49b7, 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, 0x197a, 0x2003, 0x0001, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, 0x1985, 0x2004, - 0x601a, 0x2061, 0x0100, 0x2001, 0x1984, 0x2004, 0x60ce, 0x6104, - 0xc1ac, 0x6106, 0x080c, 0x49b7, 0xa813, 0x0019, 0xa817, 0x0001, - 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, - 0x2004, 0xa86a, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x1984, - 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x2200, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0xa86e, 0x601a, 0xa873, 0x0000, 0x601f, - 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, - 0x0005, 0x00e6, 0x080c, 0x49b7, 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, 0x2a8f, 0x1130, 0x9006, - 0x080c, 0x29a3, 0x9006, 0x080c, 0x2986, 0x2001, 0x1979, 0x2003, - 0x0000, 0x7884, 0x9084, 0x0007, 0x0002, 0x3c00, 0x3c0f, 0x3c1e, - 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x012e, 0x0804, 0x3427, - 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, 0x0db8, 0x2009, 0x0114, - 0x2104, 0x9085, 0x0800, 0x200a, 0x080c, 0x3dec, 0x00f0, 0x2001, - 0x0100, 0x2004, 0x9086, 0x000a, 0x0d40, 0x2009, 0x0114, 0x2104, - 0x9085, 0x4000, 0x200a, 0x080c, 0x3dec, 0x0078, 0x080c, 0x717e, - 0x1128, 0x012e, 0x2009, 0x0016, 0x0804, 0x3424, 0x81ff, 0x0128, - 0x012e, 0x2021, 0x400b, 0x0804, 0x33f4, 0x2001, 0x0141, 0x2004, - 0xd0dc, 0x0db0, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, - 0x00e6, 0x00f6, 0x080c, 0x3927, 0x2009, 0x0101, 0x210c, 0x0016, - 0x7ec8, 0x7dcc, 0x9006, 0x2068, 0x2060, 0x2058, 0x080c, 0x4100, - 0x080c, 0x4050, 0x903e, 0x2720, 0x00f6, 0x00e6, 0x0086, 0x2940, - 0x2071, 0x1a42, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, - 0xd0b4, 0x0120, 0x68d4, 0x780e, 0x68d0, 0x780a, 0x00de, 0x2011, - 0x0001, 0x080c, 0x3fb1, 0x080c, 0x2a97, 0x080c, 0x2a97, 0x080c, - 0x2a97, 0x080c, 0x2a97, 0x080c, 0x3fb1, 0x008e, 0x00ee, 0x00fe, - 0x080c, 0x3ed3, 0x2009, 0x9c40, 0x8109, 0x11b0, 0x080c, 0x3da2, - 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x001e, 0x00fe, - 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x2009, - 0x0017, 0x080c, 0x3424, 0x0cf8, 0x2001, 0x020b, 0x2004, 0x9084, - 0x0140, 0x1d10, 0x00f6, 0x2079, 0x0000, 0x7884, 0x00fe, 0xd0bc, - 0x0178, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0150, 0x080c, 0x3eb1, - 0x2d00, 0x9c05, 0x9b05, 0x0120, 0x080c, 0x3da2, 0x0804, 0x3d42, - 0x080c, 0x4025, 0x080c, 0x3f49, 0x080c, 0x3e94, 0x080c, 0x3ec9, - 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, - 0x3da2, 0x00fe, 0x0804, 0x3d42, 0x00fe, 0x080c, 0x3d98, 0x1150, - 0x8d68, 0x2001, 0x0032, 0x2602, 0x2001, 0x0033, 0x2502, 0x080c, - 0x3da2, 0x0080, 0x87ff, 0x0138, 0x2001, 0x0201, 0x2004, 0x9005, - 0x1908, 0x8739, 0x0038, 0x2001, 0x1a3f, 0x2004, 0x9086, 0x0000, - 0x1904, 0x3c92, 0x2001, 0x032f, 0x2003, 0x00f6, 0x8631, 0x1208, - 0x8529, 0x2500, 0x9605, 0x0904, 0x3d42, 0x7884, 0xd0bc, 0x0128, - 0x2d00, 0x9c05, 0x9b05, 0x1904, 0x3d42, 0xa013, 0x0019, 0x2001, - 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1148, 0x2001, 0x1a3f, - 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x0030, 0xa017, - 0x0001, 0x78b4, 0x9005, 0x0108, 0xa016, 0x2800, 0xa05a, 0x2009, - 0x0040, 0x080c, 0x2200, 0x2900, 0xa85a, 0xa813, 0x0019, 0x7884, - 0xd0a4, 0x1180, 0xa817, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, - 0x0090, 0x602b, 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x3d19, - 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, 0x3c4c, 0x001e, 0x00c6, 0x2001, 0x032a, 0x2003, 0x0004, - 0x2061, 0x0100, 0x6027, 0x0002, 0x6106, 0x2011, 0x020d, 0x2013, - 0x0020, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, - 0x12fe, 0x7884, 0x9084, 0x0003, 0x9086, 0x0002, 0x0508, 0x2009, - 0x0028, 0x080c, 0x2200, 0x2001, 0x0227, 0x200c, 0x2102, 0x6050, - 0x0006, 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, 0x000e, 0x0118, - 0x9084, 0xb7ef, 0x0020, 0x9084, 0xb7ff, 0x080c, 0x2bdc, 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, 0x33f2, 0x012e, 0x2021, 0x400c, 0x0804, 0x33f4, - 0x9085, 0x0001, 0x1d04, 0x3da1, 0x2091, 0x6000, 0x8420, 0x9486, - 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, - 0x2003, 0x0004, 0x2001, 0x1a3f, 0x2003, 0x0000, 0x0071, 0x2009, - 0x0048, 0x080c, 0x2200, 0x2001, 0x0227, 0x2024, 0x2402, 0x2001, - 0x0109, 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, 0x2071, - 0x1a42, 0x7000, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, 0x2009, - 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, - 0x0040, 0x080c, 0x2200, 0x782c, 0xd0fc, 0x0d88, 0x080c, 0x4025, - 0x7000, 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, 0xd0ac, - 0x1de8, 0x2009, 0x0040, 0x080c, 0x2200, 0x782b, 0x0002, 0x7003, - 0x0000, 0x00ee, 0x00fe, 0x0005, 0x2001, 0x0100, 0x2004, 0x9086, - 0x000a, 0x15d0, 0x00f6, 0x2079, 0x0100, 0x2001, 0x1817, 0x200c, - 0x7932, 0x7936, 0x080c, 0x26b6, 0x080c, 0x2ba9, 0x080c, 0x2bdc, - 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x7850, 0xc0e5, - 0x7852, 0x2019, 0x61a8, 0x7820, 0xd09c, 0x0110, 0x8319, 0x1dd8, - 0x7850, 0xc0e4, 0x7852, 0x7827, 0x0048, 0x7843, 0x0040, 0x2019, - 0x01f4, 0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, - 0x2b6f, 0x7827, 0x0020, 0x7843, 0x0000, 0x9006, 0x080c, 0x2b6f, - 0x7827, 0x0048, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, - 0x1817, 0x200c, 0x7932, 0x7936, 0x080c, 0x26b6, 0x7850, 0x9084, - 0xfbff, 0x9085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, - 0x9084, 0xffcf, 0x9085, 0x2000, 0x7852, 0x20a9, 0x0046, 0x1d04, - 0x3e47, 0x2091, 0x6000, 0x1f04, 0x3e47, 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, 0x3e67, 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, - 0x2b6f, 0x7827, 0x0020, 0x7843, 0x0000, 0x9006, 0x080c, 0x2b6f, - 0x7827, 0x0048, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, 0x00f6, - 0x00e6, 0x2071, 0x1a3f, 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, 0x1985, - 0x2004, 0x70e2, 0x080c, 0x3b61, 0x1188, 0x2001, 0x181f, 0x2004, - 0x2009, 0x181e, 0x210c, 0x918c, 0x00ff, 0x706e, 0x716a, 0x7066, - 0x918d, 0x3200, 0x7162, 0x7073, 0xe109, 0x0080, 0x702c, 0x9085, - 0x0002, 0x702e, 0x2009, 0x1817, 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, 0x4025, 0x00f6, 0x2071, 0x1a3f, 0x2079, 0x0320, 0x00d6, - 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, 0x6898, - 0x780a, 0x00de, 0x080c, 0x3b61, 0x0140, 0x2001, 0x1979, 0x200c, - 0x2003, 0x0001, 0x918e, 0x0001, 0x0120, 0x2009, 0x03e8, 0x8109, - 0x1df0, 0x792c, 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, - 0x080c, 0x3fb1, 0x2011, 0x0001, 0x080c, 0x3fb1, 0x00fe, 0x00ee, - 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a3f, 0x2079, 0x0320, 0x792c, - 0xd1fc, 0x0904, 0x3fae, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, - 0x3faa, 0x7000, 0x0002, 0x3fae, 0x3f5f, 0x3f8f, 0x3faa, 0xd1bc, - 0x1170, 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, - 0x3fb1, 0x0904, 0x3fae, 0x080c, 0x3fb1, 0x0804, 0x3fae, 0x00f6, - 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, - 0x0004, 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, - 0x080c, 0x3eb1, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, - 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, - 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x3f53, - 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, 0x0df6, 0x9398, 0x3fdf, 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, 0x401c, - 0x4013, 0x400a, 0x4001, 0x3ff8, 0x3fef, 0x3fe6, 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, 0x1a42, 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, 0x782b, - 0x0002, 0x2940, 0x9026, 0x7000, 0x0002, 0x404c, 0x4038, 0x4043, - 0x8001, 0x7002, 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x3fb1, - 0x190c, 0x3fb1, 0x0048, 0x8001, 0x7002, 0x782c, 0xd0fc, 0x1d38, - 0x2011, 0x0001, 0x080c, 0x3fb1, 0x008e, 0x00ee, 0x00fe, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, 0x1985, - 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x1984, 0x2004, 0x60ce, - 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, 0x0520, - 0x2038, 0x2001, 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, - 0x49b7, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, - 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, - 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x40c8, - 0x1d68, 0x2900, 0xa85a, 0x00d0, 0x080c, 0x49b7, 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, 0x1984, 0x2004, 0x6036, 0x2009, 0x0040, - 0x080c, 0x2200, 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, 0x49b7, 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, 0x49b7, 0x2940, - 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, - 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, - 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x40c8, 0x1d68, - 0x2900, 0xa85a, 0x00d8, 0x080c, 0x49b7, 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, 0x1a3f, 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, 0x001b, 0x20a1, 0x1840, 0x20e9, 0x0001, 0x9006, 0x4004, - 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, 0x9086, 0x0052, 0x0108, - 0x0005, 0x0804, 0x33f2, 0x7d98, 0x7c9c, 0x0804, 0x34f6, 0x080c, - 0x717e, 0x190c, 0x5df4, 0x2069, 0x185b, 0x2d00, 0x2009, 0x0030, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4a00, - 0x701f, 0x419b, 0x0005, 0x080c, 0x54ea, 0x1130, 0x3b00, 0x3a08, - 0xc194, 0xc095, 0x20d8, 0x21d0, 0x2069, 0x185b, 0x6800, 0x9005, - 0x0904, 0x3427, 0x6804, 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, 0x3427, - 0x9288, 0x31f3, 0x210d, 0x918c, 0x00ff, 0x6162, 0xd0dc, 0x0130, - 0x6828, 0x908a, 0x007f, 0x1a04, 0x3427, 0x605a, 0x6888, 0x9084, - 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, 0x0006, 0x2009, 0x198c, - 0x9080, 0x27a9, 0x2005, 0x200a, 0x000e, 0x2009, 0x198d, 0x9080, - 0x27ad, 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, 0x0a04, 0x3427, - 0x908a, 0x0841, 0x1a04, 0x3427, 0x9084, 0x0007, 0x1904, 0x3427, - 0x680c, 0x9005, 0x0904, 0x3427, 0x6810, 0x9005, 0x0904, 0x3427, - 0x6848, 0x6940, 0x910a, 0x1a04, 0x3427, 0x8001, 0x0904, 0x3427, - 0x684c, 0x6944, 0x910a, 0x1a04, 0x3427, 0x8001, 0x0904, 0x3427, - 0x2009, 0x195b, 0x200b, 0x0000, 0x2001, 0x187d, 0x2004, 0xd0c4, - 0x0140, 0x7884, 0x200a, 0x2008, 0x080c, 0x0e7b, 0x3b00, 0xc085, - 0x20d8, 0x6814, 0x908c, 0x00ff, 0x614a, 0x8007, 0x9084, 0x00ff, - 0x604e, 0x080c, 0x74ab, 0x080c, 0x6796, 0x080c, 0x67f9, 0x6808, - 0x602a, 0x080c, 0x2172, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, - 0xa001, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x2710, 0x003e, - 0x6000, 0x9086, 0x0000, 0x1904, 0x4326, 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, 0x198e, 0x20e9, 0x0001, 0x4001, 0x20a9, 0x0004, - 0x20a1, 0x19a8, 0x20e9, 0x0001, 0x4001, 0x080c, 0x8362, 0x00c6, - 0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d, - 0x12b0, 0x3508, 0x8109, 0x080c, 0x7a77, 0x6878, 0x6016, 0x6874, - 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, - 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, - 0x4287, 0x00ce, 0x00c6, 0x2061, 0x1976, 0x2063, 0x0001, 0x9006, - 0x080c, 0x29a3, 0x9006, 0x080c, 0x2986, 0x0000, 0x00ce, 0x00e6, - 0x2c70, 0x080c, 0x0ecc, 0x00ee, 0x2001, 0x0100, 0x2004, 0x9086, - 0x000a, 0x1120, 0x080c, 0x2ba9, 0x080c, 0x2bdc, 0x6888, 0xd0ec, - 0x0198, 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, 0x0138, 0x2011, - 0x0114, 0x2204, 0x9085, 0x0100, 0x2012, 0x0030, 0x2011, 0x0114, - 0x2204, 0x9085, 0x0180, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, - 0x0030, 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, - 0x1956, 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, - 0x0010, 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, - 0x2785, 0x2001, 0x1947, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, - 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x717e, - 0x0128, 0x080c, 0x4dd1, 0x0110, 0x080c, 0x26d6, 0x60d0, 0x9005, - 0x01c0, 0x6003, 0x0001, 0x2009, 0x430e, 0x00d0, 0x080c, 0x717e, - 0x1168, 0x2011, 0x6fed, 0x080c, 0x8259, 0x2011, 0x6fe0, 0x080c, - 0x832d, 0x080c, 0x747f, 0x080c, 0x709e, 0x0040, 0x080c, 0x5cee, - 0x0028, 0x6003, 0x0004, 0x2009, 0x4326, 0x0010, 0x0804, 0x33f2, - 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, 0x1118, - 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d, 0x0817, 0x6000, 0x9086, - 0x0000, 0x0904, 0x3424, 0x2069, 0x185b, 0x7890, 0x6842, 0x7894, - 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x2039, 0x0001, 0x0804, 0x4a03, 0x9006, 0x080c, 0x26d6, 0x81ff, - 0x1904, 0x3424, 0x080c, 0x717e, 0x11b0, 0x080c, 0x747a, 0x080c, - 0x5e2f, 0x080c, 0x31ee, 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, - 0xc459, 0x0130, 0x080c, 0x71a1, 0x1118, 0x080c, 0x7156, 0x0038, - 0x080c, 0x709e, 0x0020, 0x080c, 0x5df4, 0x080c, 0x5cee, 0x0804, - 0x33f2, 0x81ff, 0x1904, 0x3424, 0x080c, 0x717e, 0x1110, 0x0804, - 0x3424, 0x0126, 0x2091, 0x8000, 0x6190, 0x81ff, 0x0190, 0x704f, - 0x0000, 0x2001, 0x1c80, 0x2009, 0x0040, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x2039, 0x0001, 0x080c, 0x4a03, 0x701f, 0x33f0, 0x012e, - 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, 0x1c80, 0x20a9, 0x0040, - 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x2019, 0xffff, 0x4304, 0x6558, - 0x9588, 0x31f3, 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, - 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, 0x63a3, 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, 0x5d7f, 0x0804, 0x4381, 0x080c, 0x49ea, - 0x0904, 0x3427, 0x080c, 0x49b7, 0x1120, 0x2009, 0x0002, 0x0804, - 0x3424, 0x080c, 0x54db, 0xd0b4, 0x0558, 0x7884, 0x908e, 0x007e, - 0x0538, 0x908e, 0x007f, 0x0520, 0x908e, 0x0080, 0x0508, 0x080c, - 0x31e9, 0x1148, 0xb800, 0xd08c, 0x11d8, 0xb804, 0x9084, 0x00ff, - 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0x080c, 0xbf19, 0x1120, 0x2009, 0x0003, 0x0804, 0x3424, 0x7007, - 0x0003, 0x701f, 0x440c, 0x0005, 0x080c, 0x49ea, 0x0904, 0x3427, - 0x20a9, 0x002b, 0xb8b4, 0x20e0, 0xb8b8, 0x2098, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, - 0x0006, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, - 0x080c, 0x0fb4, 0x0070, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x000a, - 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x000a, 0x2098, 0x080c, - 0x0fb4, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x0804, 0x4a03, 0x81ff, 0x1904, 0x3424, 0x080c, 0x49ce, 0x0904, - 0x3427, 0x080c, 0x6515, 0x0904, 0x3424, 0x0058, 0xa878, 0x9005, - 0x0120, 0x2009, 0x0004, 0x0804, 0x3424, 0xa974, 0xaa94, 0x0804, - 0x33f2, 0x080c, 0x54e3, 0x0904, 0x33f2, 0x701f, 0x4456, 0x7007, - 0x0003, 0x0005, 0x81ff, 0x1904, 0x3424, 0x7888, 0x908a, 0x1000, - 0x1a04, 0x3427, 0x080c, 0x49ea, 0x0904, 0x3427, 0x080c, 0x66c9, - 0x0120, 0x080c, 0x66d1, 0x1904, 0x3427, 0x080c, 0x659a, 0x0904, - 0x3424, 0x2019, 0x0004, 0x900e, 0x080c, 0x6527, 0x0904, 0x3424, - 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, 0x908a, 0x1000, 0x12f8, - 0x080c, 0x49e8, 0x01e0, 0x080c, 0x66c9, 0x0118, 0x080c, 0x66d1, - 0x11b0, 0x080c, 0x659a, 0x2009, 0x0002, 0x0168, 0x2009, 0x0002, - 0x2019, 0x0004, 0x080c, 0x6527, 0x2009, 0x0003, 0x0120, 0xa998, - 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, - 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, - 0x4000, 0x080c, 0x54e3, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0000, 0x0005, 0x9186, 0x00ff, 0x0110, 0x0071, - 0x0060, 0x2029, 0x007e, 0x2061, 0x1800, 0x6458, 0x2400, 0x9506, - 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x63a3, - 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x8267, - 0x0005, 0x81ff, 0x1904, 0x3424, 0x798c, 0x2001, 0x195a, 0x918c, - 0x8000, 0x2102, 0x080c, 0x49ce, 0x0904, 0x3427, 0x080c, 0x66c9, - 0x0120, 0x080c, 0x66d1, 0x1904, 0x3427, 0x080c, 0x646a, 0x0904, - 0x3424, 0x080c, 0x651e, 0x0904, 0x3424, 0x2001, 0x195a, 0x2004, - 0xd0fc, 0x1904, 0x33f2, 0x0804, 0x4461, 0xa9a0, 0x2001, 0x195a, - 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x49db, 0x01a0, 0x080c, - 0x66c9, 0x0118, 0x080c, 0x66d1, 0x1170, 0x080c, 0x646a, 0x2009, - 0x0002, 0x0128, 0x080c, 0x651e, 0x1170, 0x2009, 0x0003, 0xa897, - 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x195a, 0x2004, - 0xd0fc, 0x1128, 0x080c, 0x54e3, 0x0110, 0x9006, 0x0018, 0x900e, - 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904, 0x3424, - 0x798c, 0x2001, 0x1959, 0x918c, 0x8000, 0x2102, 0x080c, 0x49ce, - 0x0904, 0x3427, 0x080c, 0x66c9, 0x0120, 0x080c, 0x66d1, 0x1904, - 0x3427, 0x080c, 0x646a, 0x0904, 0x3424, 0x080c, 0x650c, 0x0904, - 0x3424, 0x2001, 0x1959, 0x2004, 0xd0fc, 0x1904, 0x33f2, 0x0804, - 0x4461, 0xa9a0, 0x2001, 0x1959, 0x918c, 0x8000, 0xc18d, 0x2102, - 0x080c, 0x49db, 0x01a0, 0x080c, 0x66c9, 0x0118, 0x080c, 0x66d1, - 0x1170, 0x080c, 0x646a, 0x2009, 0x0002, 0x0128, 0x080c, 0x650c, - 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, - 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, - 0x4000, 0x2001, 0x1959, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x54e3, - 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, - 0x0005, 0x6100, 0x0804, 0x33f2, 0x080c, 0x49ea, 0x0904, 0x3427, - 0x080c, 0x54ef, 0x1904, 0x3424, 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, - 0x33f2, 0x78a8, 0x909c, 0x0003, 0xd0ac, 0x1150, 0xd0b4, 0x1140, - 0x939a, 0x0003, 0x1a04, 0x3424, 0x6258, 0x7884, 0x9206, 0x1560, - 0x2031, 0x1848, 0x2009, 0x013c, 0x2136, 0x2001, 0x1840, 0x2009, - 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0006, - 0x78a8, 0x9084, 0x0080, 0x1118, 0x000e, 0x0804, 0x4a03, 0x000e, - 0x2031, 0x0000, 0x2061, 0x18b6, 0x2c44, 0xa66a, 0xa17a, 0xa772, - 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x1134, 0x7007, - 0x0002, 0x701f, 0x461c, 0x0005, 0x81ff, 0x1904, 0x3424, 0x080c, - 0x49ea, 0x0904, 0x3427, 0x080c, 0x66c9, 0x1904, 0x3424, 0x00c6, - 0x080c, 0x49b7, 0x00ce, 0x0904, 0x3424, 0xa867, 0x0000, 0xa868, - 0xc0fd, 0xa86a, 0x7ea8, 0x080c, 0xbebf, 0x0904, 0x3424, 0x7007, - 0x0003, 0x701f, 0x4620, 0x0005, 0x080c, 0x416d, 0x0804, 0x33f2, - 0xa830, 0x9086, 0x0100, 0x0904, 0x3424, 0x8906, 0x8006, 0x8007, - 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x2009, 0x000c, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4a03, 0x9006, 0x080c, - 0x26d6, 0x78a8, 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, - 0x1904, 0x3424, 0x080c, 0x717e, 0x0110, 0x080c, 0x5df4, 0x7888, - 0x908a, 0x1000, 0x1a04, 0x3427, 0x7984, 0x9186, 0x00ff, 0x0138, - 0x9182, 0x007f, 0x1a04, 0x3427, 0x2100, 0x080c, 0x26a0, 0x0026, - 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0x19d5, 0x601b, 0x0000, - 0x601f, 0x0000, 0x607b, 0x0000, 0x607f, 0x0000, 0x080c, 0x717e, - 0x1158, 0x080c, 0x747a, 0x080c, 0x5e2f, 0x9085, 0x0001, 0x080c, - 0x71c2, 0x080c, 0x709e, 0x00d0, 0x080c, 0x9f70, 0x2061, 0x0100, - 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x810f, 0x9105, 0x604a, - 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x1973, 0x200b, 0x0000, - 0x2009, 0x002d, 0x2011, 0x5d1a, 0x080c, 0x82eb, 0x7984, 0x080c, - 0x717e, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, 0x44c4, 0x012e, - 0x00ce, 0x002e, 0x0804, 0x33f2, 0x7984, 0x080c, 0x6343, 0x2b08, - 0x1904, 0x3427, 0x0804, 0x33f2, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x3424, 0x60d8, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, - 0x0005, 0x0804, 0x3424, 0x080c, 0x49b7, 0x1120, 0x2009, 0x0002, - 0x0804, 0x3424, 0x7984, 0x81ff, 0x0904, 0x3427, 0x9192, 0x0021, - 0x1a04, 0x3427, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, - 0x0019, 0x702a, 0xaf60, 0x7736, 0x080c, 0x4a00, 0x701f, 0x46d7, - 0x7880, 0x9086, 0x006e, 0x0110, 0x701f, 0x4f83, 0x0005, 0x2009, - 0x0080, 0x080c, 0x63a3, 0x1118, 0x080c, 0x66c9, 0x0120, 0x2021, - 0x400a, 0x0804, 0x33f4, 0x00d6, 0x0096, 0xa964, 0xaa6c, 0xab70, - 0xac74, 0xad78, 0xae7c, 0xa884, 0x90be, 0x0100, 0x0904, 0x4770, - 0x90be, 0x0112, 0x0904, 0x4770, 0x90be, 0x0113, 0x0904, 0x4770, - 0x90be, 0x0114, 0x0904, 0x4770, 0x90be, 0x0117, 0x0904, 0x4770, - 0x90be, 0x011a, 0x0904, 0x4770, 0x90be, 0x011c, 0x0904, 0x4770, - 0x90be, 0x0121, 0x0904, 0x4757, 0x90be, 0x0131, 0x0904, 0x4757, - 0x90be, 0x0171, 0x0904, 0x4770, 0x90be, 0x0173, 0x0904, 0x4770, - 0x90be, 0x01a1, 0x1128, 0xa894, 0x8007, 0xa896, 0x0804, 0x477b, - 0x90be, 0x0212, 0x0904, 0x4764, 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, 0x3427, 0x7028, 0x9080, - 0x0010, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0007, - 0x080c, 0x47b9, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, - 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x47b9, 0x00c8, 0x7028, - 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, - 0x0001, 0x080c, 0x47c6, 0x00b8, 0x7028, 0x9080, 0x000e, 0x2098, - 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x47c6, - 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, - 0x20a9, 0x0001, 0x04f1, 0x00c6, 0x080c, 0x49b7, 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, 0xbeda, 0x1120, - 0x2009, 0x0003, 0x0804, 0x3424, 0x7007, 0x0003, 0x701f, 0x47b0, - 0x0005, 0x00ce, 0x009e, 0x00de, 0x2009, 0x0002, 0x0804, 0x3424, - 0xa820, 0x9086, 0x8001, 0x1904, 0x33f2, 0x2009, 0x0004, 0x0804, - 0x3424, 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, 0x3424, 0x60d8, - 0xd0ac, 0x1160, 0xd09c, 0x0120, 0x2009, 0x0016, 0x0804, 0x3424, - 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x3424, 0x7984, 0x78a8, - 0x2040, 0x080c, 0x9f69, 0x1120, 0x9182, 0x007f, 0x0a04, 0x3427, - 0x9186, 0x00ff, 0x0904, 0x3427, 0x9182, 0x0800, 0x1a04, 0x3427, - 0x7a8c, 0x7b88, 0x6078, 0x9306, 0x1158, 0x607c, 0x924e, 0x0904, - 0x3427, 0x080c, 0x9f69, 0x1120, 0x99cc, 0xff00, 0x0904, 0x3427, - 0x0126, 0x2091, 0x8000, 0x9386, 0x00ff, 0x0178, 0x0026, 0x2011, - 0x8008, 0x080c, 0x66ed, 0x002e, 0x0140, 0x918d, 0x8000, 0x080c, - 0x6737, 0x1118, 0x2001, 0x4009, 0x0458, 0x080c, 0x48d1, 0x0560, - 0x90c6, 0x4000, 0x1170, 0x00c6, 0x0006, 0x900e, 0x080c, 0x65c3, - 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, 0x33f4, 0x2b00, 0x7026, 0x0016, 0x00b6, - 0x00c6, 0x00e6, 0x2c70, 0x080c, 0xa03b, 0x0904, 0x489e, 0x2b00, - 0x6012, 0x080c, 0xc1ca, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, - 0x49b7, 0x00ce, 0x2b70, 0x1158, 0x080c, 0x9fea, 0x00ee, 0x00ce, - 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, 0x0804, 0x3424, 0x900e, - 0xa966, 0xa96a, 0x2900, 0x6016, 0xa932, 0xa868, 0xc0fd, 0xd88c, - 0x0108, 0xc0f5, 0xa86a, 0x080c, 0x3095, 0x6023, 0x0001, 0x9006, - 0x080c, 0x62e0, 0x2001, 0x0002, 0x080c, 0x62f4, 0x2009, 0x0002, - 0x080c, 0xa068, 0x78a8, 0xd094, 0x0138, 0x00ee, 0x7024, 0x00e6, - 0x2058, 0xb8bc, 0xc08d, 0xb8be, 0x9085, 0x0001, 0x00ee, 0x00ce, - 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, 0x0003, 0x0804, 0x3424, - 0x7007, 0x0003, 0x701f, 0x48ad, 0x0005, 0xa830, 0x2008, 0x918e, - 0xdead, 0x1120, 0x2021, 0x4009, 0x0804, 0x33f4, 0x9086, 0x0100, - 0x7024, 0x2058, 0x1138, 0x2009, 0x0004, 0xba04, 0x9294, 0x00ff, - 0x0804, 0x542f, 0x900e, 0xa868, 0xd0f4, 0x1904, 0x33f2, 0x080c, - 0x65c3, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, - 0x33f2, 0x00e6, 0x00d6, 0x0096, 0x83ff, 0x0904, 0x4919, 0x902e, - 0x080c, 0x9f69, 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, - 0x0030, 0x2021, 0x007f, 0x20a9, 0x0781, 0x2071, 0x107f, 0x2e04, - 0x9005, 0x11b0, 0x2100, 0x9406, 0x15e8, 0x2428, 0x94ce, 0x007f, - 0x1120, 0x92ce, 0xfffd, 0x1528, 0x0030, 0x94ce, 0x0080, 0x1130, - 0x92ce, 0xfffc, 0x11f0, 0x93ce, 0x00ff, 0x11d8, 0xc5fd, 0x0450, - 0x2058, 0xbf10, 0x2700, 0x9306, 0x11b8, 0xbe14, 0x2600, 0x9206, - 0x1198, 0x2400, 0x9106, 0x1150, 0xd884, 0x0568, 0xd894, 0x1558, - 0x080c, 0x66c9, 0x1540, 0x2001, 0x4000, 0x0430, 0x2001, 0x4007, - 0x0418, 0x2001, 0x4006, 0x0400, 0x2400, 0x9106, 0x1158, 0xbe14, - 0x87ff, 0x1128, 0x86ff, 0x0948, 0x080c, 0x9f69, 0x1930, 0x2001, - 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x48e7, 0x85ff, 0x1130, - 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, 0x080c, 0x6343, - 0x1dd0, 0xbb12, 0xba16, 0x9006, 0x9005, 0x009e, 0x00de, 0x00ee, - 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3424, 0x080c, - 0x49b7, 0x1120, 0x2009, 0x0002, 0x0804, 0x3424, 0xa867, 0x0000, - 0xa868, 0xc0fd, 0xa86a, 0x7884, 0x9005, 0x0904, 0x3427, 0x9096, - 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, 0x3427, 0x2010, 0x2918, - 0x080c, 0x303b, 0x1120, 0x2009, 0x0003, 0x0804, 0x3424, 0x7007, - 0x0003, 0x701f, 0x496c, 0x0005, 0xa830, 0x9086, 0x0100, 0x1904, - 0x33f2, 0x2009, 0x0004, 0x0804, 0x3424, 0x7984, 0x080c, 0x9f69, - 0x1120, 0x9182, 0x007f, 0x0a04, 0x3427, 0x9186, 0x00ff, 0x0904, - 0x3427, 0x9182, 0x0800, 0x1a04, 0x3427, 0x2001, 0x9400, 0x080c, - 0x548a, 0x1904, 0x3424, 0x0804, 0x33f2, 0xa998, 0x080c, 0x9f69, - 0x1118, 0x9182, 0x007f, 0x0280, 0x9186, 0x00ff, 0x0168, 0x9182, - 0x0800, 0x1250, 0x2001, 0x9400, 0x080c, 0x548a, 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, - 0x1037, 0x0198, 0x9006, 0xa802, 0x7014, 0x9005, 0x1120, 0x2900, - 0x7016, 0x701a, 0x0040, 0x7018, 0xa802, 0x0086, 0x2040, 0x2900, - 0xa006, 0x701a, 0x008e, 0x9085, 0x0001, 0x0005, 0x7984, 0x080c, - 0x63a3, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, - 0x905e, 0x8bff, 0x0005, 0xa998, 0x080c, 0x63a3, 0x1130, 0xae9c, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, - 0xae98, 0x0008, 0x7e84, 0x2608, 0x080c, 0x63a3, 0x1108, 0x0008, - 0x905e, 0x8bff, 0x0005, 0x0016, 0x7114, 0x81ff, 0x0128, 0x2148, - 0xa904, 0x080c, 0x1069, 0x0cc8, 0x7116, 0x711a, 0x001e, 0x0005, - 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, 0x18b6, 0x2c44, - 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, - 0x080c, 0x1134, 0x7007, 0x0002, 0x701f, 0x33f2, 0x0005, 0x00f6, - 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, 0x18ae, 0x2004, - 0x9005, 0x1190, 0x0e04, 0x4a34, 0x7a36, 0x7833, 0x0012, 0x7a82, - 0x7b86, 0x7c8a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x11e6, 0x0804, 0x4a9a, 0x0016, 0x0086, 0x0096, 0x00c6, - 0x00e6, 0x2071, 0x189c, 0x7044, 0x9005, 0x1540, 0x7148, 0x9182, - 0x0010, 0x0288, 0x7038, 0x2060, 0x080c, 0x1037, 0x0904, 0x4a92, - 0xa84b, 0x0000, 0x2900, 0x7046, 0x2001, 0x0002, 0x9080, 0x1ebe, - 0x2005, 0xa846, 0x0098, 0x7038, 0x90e0, 0x0004, 0x2001, 0x18b8, - 0x9c82, 0x18f8, 0x0210, 0x2061, 0x18b8, 0x2c00, 0x703a, 0x7148, - 0x81ff, 0x1108, 0x703e, 0x8108, 0x714a, 0x0460, 0x7148, 0x8108, - 0x714a, 0x7044, 0x2040, 0xa144, 0x2105, 0x0016, 0x908a, 0x0036, - 0x1a0c, 0x0df6, 0x2060, 0x001e, 0x8108, 0x2105, 0x9005, 0xa146, - 0x1520, 0x080c, 0x1037, 0x1130, 0x8109, 0xa946, 0x7148, 0x8109, - 0x714a, 0x00d8, 0x9006, 0xa806, 0xa84a, 0xa046, 0x2800, 0xa802, - 0x2900, 0xa006, 0x7046, 0x2001, 0x0002, 0x9080, 0x1ebe, 0x2005, - 0xa846, 0x0058, 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce, 0x009e, - 0x008e, 0x001e, 0x012e, 0x00fe, 0x0005, 0x2c00, 0x9082, 0x001b, - 0x0002, 0x4abc, 0x4abc, 0x4abe, 0x4abc, 0x4abc, 0x4abc, 0x4ac2, - 0x4abc, 0x4abc, 0x4abc, 0x4ac6, 0x4abc, 0x4abc, 0x4abc, 0x4aca, - 0x4abc, 0x4abc, 0x4abc, 0x4ace, 0x4abc, 0x4abc, 0x4abc, 0x4ad2, - 0x4abc, 0x4abc, 0x4abc, 0x4ad7, 0x080c, 0x0df6, 0xa276, 0xa37a, - 0xa47e, 0x0898, 0xa286, 0xa38a, 0xa48e, 0x0878, 0xa296, 0xa39a, - 0xa49e, 0x0858, 0xa2a6, 0xa3aa, 0xa4ae, 0x0838, 0xa2b6, 0xa3ba, - 0xa4be, 0x0818, 0xa2c6, 0xa3ca, 0xa4ce, 0x0804, 0x4a95, 0xa2d6, - 0xa3da, 0xa4de, 0x0804, 0x4a95, 0x00e6, 0x2071, 0x189c, 0x7048, - 0x9005, 0x0904, 0x4b6e, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4b6d, - 0x00f6, 0x2079, 0x0000, 0x00c6, 0x0096, 0x0086, 0x0076, 0x9006, - 0x2038, 0x7040, 0x2048, 0x9005, 0x0500, 0xa948, 0x2105, 0x0016, - 0x908a, 0x0036, 0x1a0c, 0x0df6, 0x2060, 0x001e, 0x8108, 0x2105, - 0x9005, 0xa94a, 0x1904, 0x4b70, 0xa804, 0x9005, 0x090c, 0x0df6, - 0x7042, 0x2938, 0x2040, 0xa003, 0x0000, 0x2001, 0x0002, 0x9080, - 0x1ebe, 0x2005, 0xa04a, 0x0804, 0x4b70, 0x703c, 0x2060, 0x2c14, - 0x6304, 0x6408, 0x650c, 0x2200, 0x7836, 0x7833, 0x0012, 0x7882, - 0x2300, 0x7886, 0x2400, 0x788a, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x11e6, 0x87ff, 0x0118, 0x2748, 0x080c, - 0x1069, 0x7048, 0x8001, 0x704a, 0x9005, 0x1170, 0x7040, 0x2048, - 0x9005, 0x0128, 0x080c, 0x1069, 0x9006, 0x7042, 0x7046, 0x703b, - 0x18b8, 0x703f, 0x18b8, 0x0420, 0x7040, 0x9005, 0x1508, 0x7238, - 0x2c00, 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa, 0x18f8, 0x0210, - 0x2001, 0x18b8, 0x703e, 0x00a0, 0x9006, 0x703e, 0x703a, 0x7044, - 0x9005, 0x090c, 0x0df6, 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, - 0x7042, 0x2001, 0x0002, 0x9080, 0x1ebe, 0x2005, 0xa84a, 0x0000, - 0x007e, 0x008e, 0x009e, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, - 0x2c00, 0x9082, 0x001b, 0x0002, 0x4b8f, 0x4b8f, 0x4b91, 0x4b8f, - 0x4b8f, 0x4b8f, 0x4b96, 0x4b8f, 0x4b8f, 0x4b8f, 0x4b9b, 0x4b8f, - 0x4b8f, 0x4b8f, 0x4ba0, 0x4b8f, 0x4b8f, 0x4b8f, 0x4ba5, 0x4b8f, - 0x4b8f, 0x4b8f, 0x4baa, 0x4b8f, 0x4b8f, 0x4b8f, 0x4baf, 0x080c, - 0x0df6, 0xaa74, 0xab78, 0xac7c, 0x0804, 0x4b1b, 0xaa84, 0xab88, - 0xac8c, 0x0804, 0x4b1b, 0xaa94, 0xab98, 0xac9c, 0x0804, 0x4b1b, - 0xaaa4, 0xaba8, 0xacac, 0x0804, 0x4b1b, 0xaab4, 0xabb8, 0xacbc, - 0x0804, 0x4b1b, 0xaac4, 0xabc8, 0xaccc, 0x0804, 0x4b1b, 0xaad4, - 0xabd8, 0xacdc, 0x0804, 0x4b1b, 0x0026, 0x080c, 0x54db, 0xd0c4, - 0x0120, 0x2011, 0x8014, 0x080c, 0x4a17, 0x002e, 0x0005, 0x81ff, - 0x1904, 0x3424, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, - 0xc0ac, 0x6032, 0x080c, 0x717e, 0x1158, 0x080c, 0x747a, 0x080c, - 0x5e2f, 0x9085, 0x0001, 0x080c, 0x71c2, 0x080c, 0x709e, 0x0010, - 0x080c, 0x5cee, 0x012e, 0x0804, 0x33f2, 0x81ff, 0x0120, 0x2009, - 0x0001, 0x0804, 0x3424, 0x080c, 0x54ef, 0x0120, 0x2009, 0x0007, - 0x0804, 0x3424, 0x080c, 0x66c1, 0x0120, 0x2009, 0x0008, 0x0804, - 0x3424, 0x0026, 0x2011, 0x0010, 0x080c, 0x66ed, 0x002e, 0x0140, - 0x7984, 0x080c, 0x6737, 0x1120, 0x2009, 0x4009, 0x0804, 0x3424, - 0x7984, 0x080c, 0x6343, 0x1904, 0x3427, 0x080c, 0x49ea, 0x0904, - 0x3427, 0x2b00, 0x7026, 0x080c, 0x66c9, 0x7888, 0x1170, 0x9084, - 0x0005, 0x1158, 0x900e, 0x080c, 0x65c3, 0x1108, 0xc185, 0xb800, - 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x33f2, 0x080c, 0x49b7, 0x0904, - 0x3424, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, - 0xbf78, 0x0904, 0x3424, 0x7888, 0xd094, 0x0118, 0xb8bc, 0xc08d, - 0xb8be, 0x7007, 0x0003, 0x701f, 0x4c7f, 0x0005, 0x2061, 0x1800, - 0x080c, 0x54ef, 0x2009, 0x0007, 0x1560, 0x080c, 0x66c1, 0x0118, - 0x2009, 0x0008, 0x0430, 0xa998, 0x080c, 0x6343, 0x1530, 0x080c, - 0x49e8, 0x0518, 0x080c, 0x66c9, 0xa89c, 0x1168, 0x9084, 0x0005, - 0x1150, 0x900e, 0x080c, 0x65c3, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0x00d0, 0xa868, 0xc0fc, 0xa86a, 0x080c, 0xbf78, - 0x11e0, 0xa89c, 0xd094, 0x0118, 0xb8bc, 0xc08d, 0xb8be, 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, - 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, 0x4009, 0x0804, 0x33f4, - 0x9086, 0x0100, 0x7024, 0x2058, 0x1110, 0x0804, 0x542f, 0x900e, - 0x080c, 0x65c3, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, - 0x0804, 0x33f2, 0x080c, 0x54ef, 0x0120, 0x2009, 0x0007, 0x0804, - 0x3424, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x49b7, - 0x1120, 0x2009, 0x0002, 0x0804, 0x3424, 0x900e, 0x2130, 0x7126, - 0x7132, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0005, 0x702a, - 0x20a0, 0x080c, 0x63a3, 0x1904, 0x4d24, 0x080c, 0x66c9, 0x0120, - 0x080c, 0x66d1, 0x1904, 0x4d24, 0x080c, 0x66c1, 0x1130, 0x080c, - 0x65c3, 0x1118, 0xd79c, 0x0904, 0x4d24, 0xd794, 0x1110, 0xd784, - 0x01a8, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, 0x3400, - 0xd794, 0x0198, 0x20a9, 0x0008, 0x4003, 0x2098, 0x20a0, 0x3d00, - 0x20e0, 0x20a9, 0x0002, 0x080c, 0x47c6, 0x0080, 0xb8b4, 0x20e0, - 0xb8b8, 0x9080, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003, - 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x47c6, 0x4104, 0xd794, - 0x0528, 0xb8b4, 0x20e0, 0xb8b8, 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, 0x47b9, 0x9c80, 0x0026, - 0x2098, 0xb8b4, 0x20e0, 0x20a9, 0x0002, 0x4003, 0xd794, 0x0110, - 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, 0x080c, 0x9f69, 0x0118, - 0x9186, 0x0800, 0x0040, 0xd78c, 0x0120, 0x9186, 0x0800, 0x0170, - 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, 0x9686, 0x0020, - 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x4cb9, 0x86ff, 0x1120, - 0x7124, 0x810b, 0x0804, 0x33f2, 0x7033, 0x0001, 0x7122, 0x7024, - 0x9600, 0x7026, 0x772e, 0x2061, 0x18b6, 0x2c44, 0xa06b, 0x0000, - 0xa67a, 0x7034, 0xa072, 0x7028, 0xa076, 0xa28e, 0xa392, 0xa496, - 0xa59a, 0x080c, 0x1134, 0x7007, 0x0002, 0x701f, 0x4d60, 0x0005, - 0x7030, 0x9005, 0x1180, 0x7120, 0x7028, 0x20a0, 0x772c, 0x9036, - 0x7034, 0x20e8, 0x2061, 0x18b6, 0x2c44, 0xa28c, 0xa390, 0xa494, - 0xa598, 0x0804, 0x4cb9, 0x7124, 0x810b, 0x0804, 0x33f2, 0x2029, - 0x007e, 0x7984, 0x7a88, 0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, - 0x90e2, 0x0020, 0x0a04, 0x3427, 0x9502, 0x0a04, 0x3427, 0x9184, - 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x3427, 0x9502, 0x0a04, 0x3427, - 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x3427, 0x9502, - 0x0a04, 0x3427, 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x3427, - 0x9502, 0x0a04, 0x3427, 0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, - 0x0a04, 0x3427, 0x9502, 0x0a04, 0x3427, 0x9384, 0x00ff, 0x90e2, - 0x0020, 0x0a04, 0x3427, 0x9502, 0x0a04, 0x3427, 0x9484, 0xff00, - 0x8007, 0x90e2, 0x0020, 0x0a04, 0x3427, 0x9502, 0x0a04, 0x3427, - 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x3427, 0x9502, 0x0a04, - 0x3427, 0x2061, 0x1963, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, - 0x33f2, 0x0006, 0x080c, 0x54db, 0xd0cc, 0x000e, 0x0005, 0x0006, - 0x080c, 0x54df, 0xd0bc, 0x000e, 0x0005, 0x6170, 0x7a84, 0x6300, - 0x82ff, 0x1118, 0x7986, 0x0804, 0x33f2, 0x83ff, 0x1904, 0x3427, - 0x2001, 0xfff0, 0x9200, 0x1a04, 0x3427, 0x2019, 0xffff, 0x6074, - 0x9302, 0x9200, 0x0a04, 0x3427, 0x7986, 0x6272, 0x0804, 0x33f2, - 0x080c, 0x54ef, 0x1904, 0x3424, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, - 0x080c, 0x49b7, 0x0904, 0x3424, 0x900e, 0x901e, 0x7326, 0x7332, - 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0003, 0x702a, 0x20a0, - 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x66c9, 0x0118, - 0x080c, 0x66d1, 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, 0x847e, 0x2208, 0x0804, 0x33f2, 0x7033, - 0x0001, 0x7122, 0x7024, 0x9300, 0x7026, 0x2061, 0x18b6, 0x2c44, - 0xa06b, 0x0000, 0xa37a, 0x7028, 0xa076, 0x7034, 0xa072, 0xa48e, - 0xa592, 0xa696, 0xa79a, 0x080c, 0x1134, 0x7007, 0x0002, 0x701f, - 0x4e52, 0x0005, 0x7030, 0x9005, 0x1178, 0x7120, 0x7028, 0x20a0, - 0x901e, 0x7034, 0x20e8, 0x2061, 0x18b6, 0x2c44, 0xa48c, 0xa590, - 0xa694, 0xa798, 0x0804, 0x4e10, 0x7224, 0x900e, 0x2001, 0x0003, - 0x080c, 0x847e, 0x2208, 0x0804, 0x33f2, 0x00f6, 0x00e6, 0x080c, - 0x54ef, 0x2009, 0x0007, 0x1904, 0x4ee5, 0x2071, 0x189c, 0x745c, - 0x84ff, 0x2009, 0x000e, 0x1904, 0x4ee5, 0xac9c, 0xad98, 0xaea4, - 0xafa0, 0x0096, 0x080c, 0x1050, 0x2009, 0x0002, 0x0904, 0x4ee5, - 0x2900, 0x705e, 0x900e, 0x901e, 0x7356, 0x7362, 0xa860, 0x7066, - 0xa85c, 0x9080, 0x0003, 0x705a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, - 0x8bff, 0x0178, 0x080c, 0x66c9, 0x0118, 0x080c, 0x66d1, 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, - 0x847e, 0x2208, 0x009e, 0xa897, 0x4000, 0xa99a, 0x715c, 0x81ff, - 0x090c, 0x0df6, 0x2148, 0x080c, 0x1069, 0x9006, 0x705e, 0x918d, - 0x0001, 0x2008, 0x0418, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, - 0x7056, 0x2061, 0x18b7, 0x2c44, 0xa37a, 0x7058, 0xa076, 0x7064, - 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0xa09f, 0x4ef1, 0x000e, - 0xa0a2, 0x080c, 0x1134, 0x9006, 0x0048, 0x009e, 0xa897, 0x4005, - 0xa99a, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ee, 0x00fe, - 0x0005, 0x00f6, 0xa0a0, 0x904d, 0x090c, 0x0df6, 0x00e6, 0x2071, - 0x189c, 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, 0x847e, 0xaa9a, 0x715c, - 0x81ff, 0x090c, 0x0df6, 0x2148, 0x080c, 0x1069, 0x705f, 0x0000, - 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x6a22, 0x012e, - 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91d8, - 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x66c9, 0x0118, 0x080c, - 0x66d1, 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, 0x0df6, 0x2148, 0x080c, - 0x1069, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0xa0a0, 0x2048, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6a22, 0x012e, 0xa09f, 0x0000, - 0xa0a3, 0x0000, 0x0070, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, - 0x7056, 0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x1134, - 0x9006, 0x00ee, 0x0005, 0x0096, 0xa88c, 0x90be, 0x7000, 0x0148, - 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, 0x0118, 0x009e, 0x0804, - 0x3427, 0xa884, 0xa988, 0x080c, 0x266d, 0x1518, 0x080c, 0x6343, - 0x1500, 0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c, 0x49b7, 0x01c8, - 0x080c, 0x49b7, 0x01b0, 0x009e, 0xa867, 0x0000, 0xa868, 0xc0fd, - 0xa86a, 0xa823, 0x0000, 0xa804, 0x2048, 0x080c, 0xbefa, 0x1120, - 0x2009, 0x0003, 0x0804, 0x3424, 0x7007, 0x0003, 0x701f, 0x4fbe, - 0x0005, 0x009e, 0x2009, 0x0002, 0x0804, 0x3424, 0x7124, 0x080c, - 0x3190, 0xa820, 0x9086, 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, - 0x3424, 0x2900, 0x7022, 0xa804, 0x0096, 0x2048, 0x8906, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x009e, 0x9080, 0x0002, - 0x0076, 0x0006, 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, - 0x080c, 0x0fb4, 0xaa6c, 0xab70, 0xac74, 0xad78, 0x2061, 0x18b6, - 0x2c44, 0xa06b, 0x0000, 0xae64, 0xaf8c, 0x97c6, 0x7000, 0x0118, - 0x97c6, 0x7100, 0x1148, 0x96c2, 0x0004, 0x0600, 0x2009, 0x0004, - 0x000e, 0x007e, 0x0804, 0x4a03, 0x97c6, 0x7200, 0x11b8, 0x96c2, - 0x0054, 0x02a0, 0x000e, 0x007e, 0x2061, 0x18b6, 0x2c44, 0xa076, - 0xa772, 0xa07b, 0x002a, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, - 0x1134, 0x7007, 0x0002, 0x701f, 0x501a, 0x0005, 0x000e, 0x007e, - 0x0804, 0x3427, 0x7020, 0x2048, 0xa804, 0x2048, 0xa804, 0x2048, - 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, - 0x0002, 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, - 0x0fb4, 0x2100, 0x2238, 0x2061, 0x18b6, 0x2c44, 0xa28c, 0xa390, - 0xa494, 0xa598, 0x2009, 0x002a, 0x0804, 0x4a03, 0x81ff, 0x1904, - 0x3424, 0x798c, 0x2001, 0x1958, 0x918c, 0x8000, 0x2102, 0x080c, - 0x49ce, 0x0904, 0x3427, 0x080c, 0x66c9, 0x0120, 0x080c, 0x66d1, - 0x1904, 0x3427, 0x080c, 0x646a, 0x0904, 0x3424, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6530, 0x012e, 0x0904, 0x3424, 0x2001, 0x1958, - 0x2004, 0xd0fc, 0x1904, 0x33f2, 0x0804, 0x4461, 0xa9a0, 0x2001, - 0x1958, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x49db, 0x01a0, - 0x080c, 0x66c9, 0x0118, 0x080c, 0x66d1, 0x1170, 0x080c, 0x646a, - 0x2009, 0x0002, 0x0128, 0x080c, 0x6530, 0x1170, 0x2009, 0x0003, - 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x1958, - 0x2004, 0xd0fc, 0x1128, 0x080c, 0x54e3, 0x0110, 0x9006, 0x0018, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x78a8, 0xd08c, - 0x1118, 0xd084, 0x0904, 0x43d6, 0x080c, 0x49ea, 0x0904, 0x3427, - 0x080c, 0x49b7, 0x1120, 0x2009, 0x0002, 0x0804, 0x3424, 0x080c, - 0x66c9, 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, 0x0005, 0x15a0, - 0x78a8, 0xd08c, 0x0120, 0xb800, 0xc08c, 0xb802, 0x0028, 0x080c, - 0x54db, 0xd0b4, 0x0904, 0x4410, 0x7884, 0x908e, 0x007e, 0x0904, - 0x4410, 0x908e, 0x007f, 0x0904, 0x4410, 0x908e, 0x0080, 0x0904, - 0x4410, 0xb800, 0xd08c, 0x1904, 0x4410, 0xa867, 0x0000, 0xa868, - 0xc0fd, 0xa86a, 0x080c, 0xbf19, 0x1120, 0x2009, 0x0003, 0x0804, - 0x3424, 0x7007, 0x0003, 0x701f, 0x50e6, 0x0005, 0x080c, 0x49ea, - 0x0904, 0x3427, 0x0804, 0x4410, 0x080c, 0x31e9, 0x0108, 0x0005, - 0x2009, 0x1833, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x3424, 0x080c, 0x54ef, 0x0120, 0x2009, 0x0007, 0x0804, 0x3424, - 0x080c, 0x66c1, 0x0120, 0x2009, 0x0008, 0x0804, 0x3424, 0xb89c, - 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x4410, 0x9006, 0xa866, 0xa832, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xbf78, 0x1120, 0x2009, 0x0003, - 0x0804, 0x3424, 0x7007, 0x0003, 0x701f, 0x511f, 0x0005, 0xa830, - 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x542f, 0x080c, - 0x49ea, 0x0904, 0x3427, 0x0804, 0x50b8, 0x81ff, 0x2009, 0x0001, - 0x1904, 0x3424, 0x080c, 0x54ef, 0x2009, 0x0007, 0x1904, 0x3424, - 0x080c, 0x66c1, 0x0120, 0x2009, 0x0008, 0x0804, 0x3424, 0x080c, - 0x49ea, 0x0904, 0x3427, 0x080c, 0x66c9, 0x2009, 0x0009, 0x1904, - 0x3424, 0x080c, 0x49b7, 0x2009, 0x0002, 0x0904, 0x3424, 0x9006, - 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x7988, 0xa95a, 0x9194, - 0xfd00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, 0xc0ed, 0xa952, - 0x798c, 0xa956, 0x0038, 0x928e, 0x0100, 0x1904, 0x3427, 0xc0e5, - 0xa952, 0xa956, 0xa83e, 0x080c, 0xc1cb, 0x2009, 0x0003, 0x0904, - 0x3424, 0x7007, 0x0003, 0x701f, 0x5176, 0x0005, 0xa830, 0x9086, - 0x0100, 0x2009, 0x0004, 0x0904, 0x3424, 0x0804, 0x33f2, 0x7aa8, - 0x9284, 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, 0x54ef, 0x1188, - 0x2009, 0x0014, 0x0804, 0x3424, 0xd2dc, 0x1578, 0x81ff, 0x2009, - 0x0001, 0x1904, 0x3424, 0x080c, 0x54ef, 0x2009, 0x0007, 0x1904, - 0x3424, 0xd2f4, 0x0138, 0x9284, 0x5000, 0xc0d5, 0x080c, 0x54b5, - 0x0804, 0x33f2, 0xd2fc, 0x0160, 0x080c, 0x49ea, 0x0904, 0x3427, - 0x7984, 0x9284, 0x9000, 0xc0d5, 0x080c, 0x548a, 0x0804, 0x33f2, - 0x080c, 0x49ea, 0x0904, 0x3427, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x2009, 0x0009, 0x1904, 0x5265, 0x080c, 0x49b7, 0x2009, - 0x0002, 0x0904, 0x5265, 0xa85c, 0x9080, 0x001b, 0xaf60, 0x2009, - 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4a00, 0x701f, - 0x51d2, 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, 0xa870, 0x9005, - 0x1120, 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, 0x3427, 0xa866, - 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x49ea, 0x1110, 0x0804, - 0x3427, 0x2009, 0x0043, 0x080c, 0xc237, 0x2009, 0x0003, 0x0904, - 0x5265, 0x7007, 0x0003, 0x701f, 0x51f6, 0x0005, 0xa830, 0x9086, - 0x0100, 0x2009, 0x0004, 0x0904, 0x5265, 0x7984, 0x7aa8, 0x9284, - 0x1000, 0xc0d5, 0x080c, 0x548a, 0x0804, 0x33f2, 0x00c6, 0xaab0, - 0x9284, 0xc000, 0x0148, 0xd2ec, 0x0170, 0x080c, 0x54ef, 0x1158, - 0x2009, 0x0014, 0x0804, 0x5254, 0x2061, 0x1800, 0x080c, 0x54ef, - 0x2009, 0x0007, 0x15c8, 0xd2f4, 0x0130, 0x9284, 0x5000, 0xc0d5, - 0x080c, 0x54b5, 0x0058, 0xd2fc, 0x0180, 0x080c, 0x49e8, 0x0590, - 0xa998, 0x9284, 0x9000, 0xc0d5, 0x080c, 0x548a, 0xa87b, 0x0000, - 0xa883, 0x0000, 0xa897, 0x4000, 0x0438, 0x080c, 0x49e8, 0x0510, - 0x080c, 0x66c9, 0x2009, 0x0009, 0x11b8, 0xa8c4, 0x9086, 0x0500, - 0x11c8, 0xa8c8, 0x9005, 0x11b0, 0xa8cc, 0x9084, 0xff00, 0x1190, - 0x080c, 0x49e8, 0x1108, 0x0070, 0x2009, 0x004b, 0x080c, 0xc237, - 0x2009, 0x0003, 0x0108, 0x0078, 0x0431, 0x19c0, 0xa897, 0x4005, - 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0030, 0x00ce, 0x0005, 0x9006, 0x0ce0, 0x7aa8, 0xd2dc, 0x0904, - 0x3424, 0x0016, 0x7984, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x548a, - 0x001e, 0x1904, 0x3424, 0x0804, 0x33f2, 0x00f6, 0x2d78, 0xaab0, - 0x0021, 0x00fe, 0x0005, 0xaab0, 0xc2d5, 0xd2dc, 0x0150, 0x0016, - 0xa998, 0x9284, 0x1400, 0xc0fd, 0x080c, 0x548a, 0x001e, 0x9085, - 0x0001, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3424, - 0x080c, 0x54ef, 0x0120, 0x2009, 0x0007, 0x0804, 0x3424, 0x7984, - 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x63a3, 0x1904, 0x3427, 0x9186, - 0x007f, 0x0138, 0x080c, 0x66c9, 0x0120, 0x2009, 0x0009, 0x0804, - 0x3424, 0x080c, 0x49b7, 0x1120, 0x2009, 0x0002, 0x0804, 0x3424, - 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, 0x0100, 0x8007, - 0xa80a, 0x080c, 0xbf33, 0x1120, 0x2009, 0x0003, 0x0804, 0x3424, - 0x7007, 0x0003, 0x701f, 0x52c5, 0x0005, 0xa808, 0x8007, 0x9086, - 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x3424, 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, 0x4a03, 0x080c, 0x49b7, 0x1120, 0x2009, - 0x0002, 0x0804, 0x3424, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, - 0x8217, 0x82ff, 0x1118, 0x7023, 0x198e, 0x0040, 0x92c6, 0x0001, - 0x1118, 0x7023, 0x19a8, 0x0010, 0x0804, 0x3427, 0x2009, 0x001a, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, - 0x080c, 0x4a00, 0x701f, 0x5315, 0x0005, 0x2001, 0x182d, 0x2003, - 0x0001, 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, 0x20e0, 0x20a9, - 0x001a, 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, 0x0804, 0x33f2, - 0x080c, 0x49b7, 0x1120, 0x2009, 0x0002, 0x0804, 0x3424, 0x7984, - 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x2099, - 0x198e, 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, 0x19a8, 0x0010, - 0x0804, 0x3427, 0xa85c, 0x9080, 0x0019, 0x20a0, 0xa860, 0x20e8, - 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x0804, - 0x4a03, 0x7884, 0x908a, 0x1000, 0x1a04, 0x3427, 0x0126, 0x2091, - 0x8000, 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, 0x19d5, - 0x614a, 0x00ce, 0x012e, 0x0804, 0x33f2, 0x00c6, 0x080c, 0x717e, - 0x1160, 0x080c, 0x747a, 0x080c, 0x5e2f, 0x9085, 0x0001, 0x080c, - 0x71c2, 0x080c, 0x709e, 0x080c, 0x0df6, 0x2061, 0x1800, 0x6030, - 0xc09d, 0x6032, 0x080c, 0x5cee, 0x00ce, 0x0005, 0x00c6, 0x2001, - 0x1800, 0x2004, 0x908e, 0x0000, 0x0904, 0x3424, 0x7884, 0x9005, - 0x0188, 0x7888, 0x2061, 0x1976, 0x2c0c, 0x2062, 0x080c, 0x2a7f, - 0x01a0, 0x080c, 0x2a87, 0x0188, 0x080c, 0x2a8f, 0x0170, 0x2162, - 0x0804, 0x3427, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, - 0x2009, 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, 0x9086, 0x0002, - 0x1568, 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, 0x0026, 0x2011, - 0x0003, 0x080c, 0x9923, 0x2011, 0x0002, 0x080c, 0x992d, 0x002e, - 0x080c, 0x983b, 0x0036, 0x901e, 0x080c, 0x98b1, 0x003e, 0x60e3, - 0x0000, 0x080c, 0xdbdb, 0x080c, 0xdbf6, 0x9085, 0x0001, 0x080c, - 0x71c2, 0x9006, 0x080c, 0x2b6f, 0x2001, 0x1800, 0x2003, 0x0004, - 0x2001, 0x1982, 0x2003, 0x0000, 0x6027, 0x0008, 0x00ce, 0x0804, - 0x33f2, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3424, 0x080c, - 0x54ef, 0x0120, 0x2009, 0x0007, 0x0804, 0x3424, 0x7984, 0x7ea8, - 0x96b4, 0x00ff, 0x080c, 0x63a3, 0x1904, 0x3427, 0x9186, 0x007f, - 0x0138, 0x080c, 0x66c9, 0x0120, 0x2009, 0x0009, 0x0804, 0x3424, - 0x080c, 0x49b7, 0x1120, 0x2009, 0x0002, 0x0804, 0x3424, 0xa867, - 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xbf36, 0x1120, 0x2009, - 0x0003, 0x0804, 0x3424, 0x7007, 0x0003, 0x701f, 0x5418, 0x0005, - 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x3424, - 0xa8e0, 0xa866, 0xa834, 0x8007, 0x800c, 0xa85c, 0x9080, 0x000c, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xaf60, 0x0804, 0x4a03, 0xa898, - 0x9086, 0x000d, 0x1904, 0x3424, 0x2021, 0x4005, 0x0126, 0x2091, - 0x8000, 0x0e04, 0x543c, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, - 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, - 0x4005, 0xa998, 0x7986, 0xa9a4, 0x799a, 0xa9a8, 0x799e, 0x080c, - 0x49f3, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11e6, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x19d5, 0x7984, - 0x615a, 0x6156, 0x605f, 0x0000, 0x6053, 0x0009, 0x7898, 0x6072, - 0x789c, 0x606e, 0x7888, 0x606a, 0x788c, 0x6066, 0x2001, 0x19e5, - 0x2044, 0x2001, 0x19ec, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, - 0xa07f, 0x0002, 0xa06b, 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, - 0x0804, 0x33f2, 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, - 0xc000, 0x0168, 0x0006, 0xd0d4, 0x0130, 0x0036, 0x2019, 0x0029, - 0x080c, 0x31ae, 0x003e, 0x080c, 0xbd9b, 0x000e, 0x1198, 0xd0e4, - 0x0160, 0x9180, 0x1000, 0x2004, 0x905d, 0x0160, 0x080c, 0x5e49, - 0x080c, 0x9f69, 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, 0x548a, 0x002e, 0x001e, 0x8108, 0x1f04, 0x54bd, - 0x015e, 0x012e, 0x0005, 0x2001, 0x185c, 0x2004, 0x0005, 0x2001, - 0x187b, 0x2004, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0d4, - 0x000e, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0b4, 0x0005, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, - 0x189c, 0x7108, 0x910d, 0x710a, 0x00ee, 0x001e, 0x0005, 0x79a4, - 0x81ff, 0x0904, 0x3427, 0x9182, 0x0081, 0x1a04, 0x3427, 0x810c, - 0x0016, 0x080c, 0x49b7, 0x0170, 0x080c, 0x0f3f, 0x2100, 0x2238, - 0x7d84, 0x7c88, 0x7b8c, 0x7a90, 0x001e, 0x080c, 0x4a00, 0x701f, - 0x551f, 0x0005, 0x001e, 0x2009, 0x0002, 0x0804, 0x3424, 0x2079, - 0x0000, 0x7d94, 0x7c98, 0x7ba8, 0x7aac, 0x79a4, 0x810c, 0x2061, - 0x18b6, 0x2c44, 0xa770, 0xa074, 0x2071, 0x189c, 0x080c, 0x4a03, - 0x701f, 0x5533, 0x0005, 0x2061, 0x18b6, 0x2c44, 0x0016, 0x0026, - 0xa270, 0xa174, 0x080c, 0x0f47, 0x002e, 0x001e, 0x080c, 0x0ff4, - 0x9006, 0xa802, 0xa806, 0x0804, 0x33f2, 0x0126, 0x0156, 0x0136, - 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, - 0x0100, 0x2069, 0x0200, 0x2071, 0x1800, 0x6044, 0xd0a4, 0x11e8, - 0xd084, 0x0118, 0x080c, 0x56ee, 0x0068, 0xd08c, 0x0118, 0x080c, - 0x55f7, 0x0040, 0xd094, 0x0118, 0x080c, 0x55c7, 0x0018, 0xd09c, - 0x0108, 0x0099, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, - 0x014e, 0x013e, 0x015e, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, - 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, 0x0006, 0x7094, 0x9005, - 0x000e, 0x0120, 0x7097, 0x0000, 0x708f, 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, 0x5dab, 0x00f0, - 0x6040, 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, - 0x7083, 0x0000, 0x709f, 0x0001, 0x70c3, 0x0000, 0x70db, 0x0000, - 0x2009, 0x1c80, 0x200b, 0x0000, 0x7093, 0x0000, 0x7087, 0x000f, - 0x2009, 0x000f, 0x2011, 0x5c91, 0x080c, 0x82eb, 0x0005, 0x2001, - 0x187d, 0x2004, 0xd08c, 0x0110, 0x705b, 0xffff, 0x7084, 0x9005, - 0x1528, 0x2011, 0x5c91, 0x080c, 0x8259, 0x6040, 0x9094, 0x0010, - 0x9285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, - 0x1f04, 0x55dd, 0x6242, 0x7097, 0x0000, 0x6040, 0x9094, 0x0010, - 0x9285, 0x0080, 0x6042, 0x6242, 0x0048, 0x6242, 0x7097, 0x0000, - 0x708b, 0x0000, 0x9006, 0x080c, 0x5e34, 0x0000, 0x0005, 0x7088, - 0x908a, 0x0003, 0x1a0c, 0x0df6, 0x000b, 0x0005, 0x5601, 0x5652, - 0x56ed, 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, 0x708b, 0x0001, - 0x2001, 0x015d, 0x2003, 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, - 0x6800, 0x9084, 0x00fc, 0x0120, 0x1f04, 0x5610, 0x080c, 0x0df6, - 0x68a0, 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, - 0x1600, 0x6902, 0x001e, 0x6837, 0x0020, 0x080c, 0x5e10, 0x2079, - 0x1c00, 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, - 0x1805, 0x20e9, 0x0001, 0x20a1, 0x1c0e, 0x20a9, 0x0004, 0x4003, - 0x080c, 0x9df2, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, - 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, - 0x0000, 0x080c, 0x5cc2, 0x00fe, 0x9006, 0x708e, 0x6043, 0x0008, - 0x6042, 0x0005, 0x00f6, 0x708c, 0x708f, 0x0000, 0x9025, 0x0904, - 0x56ca, 0x6020, 0xd0b4, 0x1904, 0x56c8, 0x719c, 0x81ff, 0x0904, - 0x56b6, 0x9486, 0x000c, 0x1904, 0x56c3, 0x9480, 0x0018, 0x8004, - 0x20a8, 0x080c, 0x5e09, 0x2011, 0x0260, 0x2019, 0x1c00, 0x220c, - 0x2304, 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, 0x566f, 0x6043, - 0x0004, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, - 0x0100, 0x6043, 0x0006, 0x708b, 0x0002, 0x7097, 0x0002, 0x2009, - 0x07d0, 0x2011, 0x5c98, 0x080c, 0x82eb, 0x080c, 0x5e10, 0x04c0, - 0x080c, 0x5e09, 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, - 0x7834, 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, - 0x9005, 0x0190, 0x080c, 0x5e09, 0x2011, 0x026e, 0x2019, 0x1805, - 0x20a9, 0x0004, 0x220c, 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, - 0x8318, 0x1f04, 0x56aa, 0x0078, 0x709f, 0x0000, 0x080c, 0x5e09, - 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, 0x9df2, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, - 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, - 0x2011, 0x19cc, 0x2013, 0x0000, 0x708f, 0x0000, 0x60a3, 0x0056, - 0x60a7, 0x9575, 0x080c, 0x9611, 0x08d8, 0x0005, 0x7094, 0x908a, - 0x001d, 0x1a0c, 0x0df6, 0x000b, 0x0005, 0x571f, 0x5732, 0x575b, - 0x577b, 0x57a1, 0x57d0, 0x57f6, 0x582e, 0x5854, 0x5882, 0x58bd, - 0x58f5, 0x5913, 0x593e, 0x5960, 0x597b, 0x5985, 0x59b9, 0x59df, - 0x5a0e, 0x5a34, 0x5a6c, 0x5ab0, 0x5aed, 0x5b0e, 0x5b67, 0x5b89, - 0x5bb7, 0x5bb7, 0x00c6, 0x2061, 0x1800, 0x6003, 0x0007, 0x2061, - 0x0100, 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, - 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, - 0x0002, 0x7097, 0x0001, 0x2009, 0x07d0, 0x2011, 0x5c98, 0x080c, - 0x82eb, 0x0005, 0x00f6, 0x708c, 0x9086, 0x0014, 0x1510, 0x6042, - 0x6020, 0xd0b4, 0x11f0, 0x080c, 0x5e09, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, - 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x2011, 0x5c98, - 0x080c, 0x8259, 0x7097, 0x0010, 0x080c, 0x5985, 0x0010, 0x708f, - 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0003, 0x6043, 0x0004, - 0x2011, 0x5c98, 0x080c, 0x8259, 0x080c, 0x5d8d, 0x2079, 0x0240, - 0x7833, 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, - 0x200b, 0x0000, 0x8108, 0x1f04, 0x5770, 0x60c3, 0x0014, 0x080c, - 0x5cc2, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, 0x2011, - 0x5c98, 0x080c, 0x8259, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5e09, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, - 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, - 0x0001, 0x7097, 0x0004, 0x0029, 0x0010, 0x080c, 0x5de5, 0x00fe, - 0x0005, 0x00f6, 0x7097, 0x0005, 0x080c, 0x5d8d, 0x2079, 0x0240, - 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x5e09, 0x080c, 0x5dec, - 0x1170, 0x7080, 0x9005, 0x1158, 0x7158, 0x9186, 0xffff, 0x0138, - 0x2011, 0x0008, 0x080c, 0x5c45, 0x0168, 0x080c, 0x5dc2, 0x20a9, - 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5cc2, 0x00fe, 0x0005, - 0x00f6, 0x708c, 0x9005, 0x0500, 0x2011, 0x5c98, 0x080c, 0x8259, - 0x9086, 0x0014, 0x11b8, 0x080c, 0x5e09, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, 0x0006, - 0x0029, 0x0010, 0x080c, 0x5de5, 0x00fe, 0x0005, 0x00f6, 0x7097, - 0x0007, 0x080c, 0x5d8d, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, - 0x0000, 0x080c, 0x5e09, 0x080c, 0x5dec, 0x11b8, 0x7080, 0x9005, - 0x11a0, 0x7160, 0x9186, 0xffff, 0x0180, 0x9180, 0x31f3, 0x200d, - 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5c45, 0x0180, - 0x080c, 0x4dd7, 0x0110, 0x080c, 0x26d6, 0x20a9, 0x0008, 0x20e1, - 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, - 0x60c3, 0x0014, 0x080c, 0x5cc2, 0x00fe, 0x0005, 0x00f6, 0x708c, - 0x9005, 0x0500, 0x2011, 0x5c98, 0x080c, 0x8259, 0x9086, 0x0014, - 0x11b8, 0x080c, 0x5e09, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, - 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, - 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, 0x0008, 0x0029, 0x0010, - 0x080c, 0x5de5, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0009, 0x080c, - 0x5d8d, 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, - 0x5dec, 0x1150, 0x7080, 0x9005, 0x1138, 0x080c, 0x5bb8, 0x1188, - 0x9085, 0x0001, 0x080c, 0x26d6, 0x20a9, 0x0008, 0x080c, 0x5e09, - 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, - 0x4003, 0x60c3, 0x0014, 0x080c, 0x5cc2, 0x0010, 0x080c, 0x5712, - 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x05a8, 0x2011, 0x5c98, - 0x080c, 0x8259, 0x9086, 0x0014, 0x1560, 0x080c, 0x5e09, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, - 0x2011, 0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, - 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, 0x000a, 0x00b1, 0x0098, - 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, - 0x70c3, 0x0001, 0x7093, 0x0000, 0x7097, 0x000e, 0x080c, 0x5960, - 0x0010, 0x080c, 0x5de5, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x000b, - 0x2011, 0x1c0e, 0x20e9, 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, - 0xffff, 0x4304, 0x080c, 0x5d8d, 0x2079, 0x0240, 0x7833, 0x1106, - 0x7837, 0x0000, 0x080c, 0x5dec, 0x0118, 0x2013, 0x0000, 0x0020, - 0x705c, 0x9085, 0x0100, 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, - 0x2011, 0x1c0e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1128, - 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x58e2, 0x60c3, - 0x0084, 0x080c, 0x5cc2, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, - 0x01c0, 0x2011, 0x5c98, 0x080c, 0x8259, 0x9086, 0x0084, 0x1178, - 0x080c, 0x5e09, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, - 0x7834, 0x9005, 0x1120, 0x7097, 0x000c, 0x0029, 0x0010, 0x080c, - 0x5de5, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x000d, 0x080c, 0x5d8d, - 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, 0x5e09, - 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, - 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, - 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5926, - 0x60c3, 0x0084, 0x080c, 0x5cc2, 0x00fe, 0x0005, 0x00f6, 0x708c, - 0x9005, 0x01e0, 0x2011, 0x5c98, 0x080c, 0x8259, 0x9086, 0x0084, - 0x1198, 0x080c, 0x5e09, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, - 0x1158, 0x7834, 0x9005, 0x1140, 0x7093, 0x0001, 0x080c, 0x5d5f, - 0x7097, 0x000e, 0x0029, 0x0010, 0x080c, 0x5de5, 0x00fe, 0x0005, - 0x918d, 0x0001, 0x080c, 0x5e34, 0x7097, 0x000f, 0x708f, 0x0000, - 0x2061, 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, - 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x5c98, - 0x080c, 0x824d, 0x0005, 0x708c, 0x9005, 0x0130, 0x2011, 0x5c98, - 0x080c, 0x8259, 0x7097, 0x0000, 0x0005, 0x7097, 0x0011, 0x080c, - 0x9df2, 0x080c, 0x5e09, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, - 0x0000, 0x20a1, 0x0240, 0x748c, 0x9480, 0x0018, 0x9080, 0x0007, - 0x9084, 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, 0x5dec, 0x11a0, - 0x7178, 0x81ff, 0x0188, 0x900e, 0x707c, 0x9084, 0x00ff, 0x0160, - 0x080c, 0x266d, 0x9186, 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, - 0x2011, 0x0008, 0x080c, 0x5c45, 0x60c3, 0x0014, 0x080c, 0x5cc2, - 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, 0x2011, 0x5c98, 0x080c, - 0x8259, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5e09, 0x2079, 0x0260, - 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, - 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, - 0x0012, 0x0029, 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, 0x00f6, - 0x7097, 0x0013, 0x080c, 0x5d9b, 0x2079, 0x0240, 0x7833, 0x1103, - 0x7837, 0x0000, 0x080c, 0x5e09, 0x080c, 0x5dec, 0x1170, 0x7080, - 0x9005, 0x1158, 0x7158, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, - 0x080c, 0x5c45, 0x0168, 0x080c, 0x5dc2, 0x20a9, 0x0008, 0x20e1, - 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, - 0x60c3, 0x0014, 0x080c, 0x5cc2, 0x00fe, 0x0005, 0x00f6, 0x708c, - 0x9005, 0x0500, 0x2011, 0x5c98, 0x080c, 0x8259, 0x9086, 0x0014, - 0x11b8, 0x080c, 0x5e09, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, - 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, - 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, 0x0014, 0x0029, 0x0010, - 0x708f, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0015, 0x080c, - 0x5d9b, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, - 0x5e09, 0x080c, 0x5dec, 0x11b8, 0x7080, 0x9005, 0x11a0, 0x7160, - 0x9186, 0xffff, 0x0180, 0x9180, 0x31f3, 0x200d, 0x918c, 0xff00, - 0x810f, 0x2011, 0x0008, 0x080c, 0x5c45, 0x0180, 0x080c, 0x4dd7, - 0x0110, 0x080c, 0x26d6, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, - 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, - 0x080c, 0x5cc2, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x05f0, - 0x2011, 0x5c98, 0x080c, 0x8259, 0x9086, 0x0014, 0x15a8, 0x080c, - 0x5e09, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, - 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1168, 0x9085, 0x0001, - 0x080c, 0x5e34, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, - 0x70c3, 0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, - 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x9085, 0x0001, 0x080c, - 0x5e34, 0x7093, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70db, 0x0008, - 0x7097, 0x0016, 0x0029, 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, - 0x080c, 0x9df2, 0x080c, 0x5e09, 0x20e1, 0x0000, 0x2099, 0x0260, - 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, - 0x026d, 0x2204, 0x9084, 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, - 0x026e, 0x7097, 0x0017, 0x080c, 0x5dec, 0x1150, 0x7080, 0x9005, - 0x1138, 0x080c, 0x5bb8, 0x1188, 0x9085, 0x0001, 0x080c, 0x26d6, - 0x20a9, 0x0008, 0x080c, 0x5e09, 0x20e1, 0x0000, 0x2099, 0x026e, - 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, - 0x5cc2, 0x0010, 0x080c, 0x5712, 0x0005, 0x00f6, 0x708c, 0x9005, - 0x01d8, 0x2011, 0x5c98, 0x080c, 0x8259, 0x9086, 0x0084, 0x1190, - 0x080c, 0x5e09, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, - 0x7834, 0x9005, 0x1138, 0x9006, 0x080c, 0x5e34, 0x7097, 0x0018, - 0x0029, 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7097, - 0x0019, 0x080c, 0x5d9b, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, - 0x0000, 0x080c, 0x5e09, 0x2009, 0x026e, 0x2039, 0x1c0e, 0x20a9, - 0x0040, 0x213e, 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, - 0x8000, 0x6816, 0x2009, 0x0260, 0x1f04, 0x5b21, 0x2039, 0x1c0e, - 0x080c, 0x5dec, 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, - 0x8000, 0x2018, 0x9294, 0x00ff, 0x8007, 0x9205, 0x202a, 0x705c, - 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, - 0x5b54, 0x60c3, 0x0084, 0x080c, 0x5cc2, 0x00fe, 0x0005, 0x00f6, - 0x708c, 0x9005, 0x01e0, 0x2011, 0x5c98, 0x080c, 0x8259, 0x9086, - 0x0084, 0x1198, 0x080c, 0x5e09, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x7093, 0x0001, 0x080c, - 0x5d5f, 0x7097, 0x001a, 0x0029, 0x0010, 0x708f, 0x0000, 0x00fe, - 0x0005, 0x9085, 0x0001, 0x080c, 0x5e34, 0x7097, 0x001b, 0x080c, - 0x9df2, 0x080c, 0x5e09, 0x2011, 0x0260, 0x2009, 0x0240, 0x748c, - 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, 0x5ba0, 0x60c3, 0x0084, 0x080c, 0x5cc2, 0x0005, 0x0005, - 0x0086, 0x0096, 0x2029, 0x185c, 0x252c, 0x20a9, 0x0008, 0x2041, - 0x1c0e, 0x20e9, 0x0001, 0x28a0, 0x080c, 0x5e09, 0x20e1, 0x0000, - 0x2099, 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, - 0x0108, 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, - 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x5bd2, 0x0804, - 0x5c41, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, - 0x0020, 0x91a6, 0x3fff, 0x0904, 0x5c41, 0x918d, 0xc000, 0x20a9, - 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, - 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, - 0x8319, 0x0008, 0x8318, 0x1f04, 0x5bf8, 0x04d8, 0x23a8, 0x2021, - 0x0001, 0x8426, 0x8425, 0x1f04, 0x5c0a, 0x2328, 0x8529, 0x92be, - 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, - 0x27a8, 0x95a8, 0x0010, 0x1f04, 0x5c19, 0x755a, 0x95c8, 0x31f3, - 0x292d, 0x95ac, 0x00ff, 0x757e, 0x6532, 0x6536, 0x0016, 0x2508, - 0x080c, 0x26b6, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, - 0x9405, 0x201a, 0x7083, 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, 0x715a, 0x91a0, 0x31f3, 0x242d, 0x95ac, - 0x00ff, 0x757e, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x26b6, - 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7083, 0x0001, 0x9084, 0x0000, - 0x0005, 0x00e6, 0x2071, 0x1800, 0x7087, 0x0000, 0x00ee, 0x0005, - 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x5d4e, - 0x080c, 0x961a, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, 0x2b7f, - 0x0126, 0x2091, 0x8000, 0x2071, 0x1825, 0x2073, 0x0000, 0x7840, - 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x5dab, 0x001e, 0x9094, - 0x0010, 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, - 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x29e9, 0x0228, - 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x2011, 0x19cc, 0x2013, - 0x0000, 0x708f, 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, - 0x080c, 0x9611, 0x6144, 0xd184, 0x0120, 0x7194, 0x918d, 0x2000, - 0x0018, 0x7188, 0x918d, 0x1000, 0x2011, 0x1973, 0x2112, 0x2009, - 0x07d0, 0x2011, 0x5c98, 0x080c, 0x82eb, 0x0005, 0x0016, 0x0026, - 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x9f70, 0x2009, 0x00f7, - 0x080c, 0x5dab, 0x2061, 0x19d5, 0x900e, 0x611a, 0x611e, 0x617a, - 0x617e, 0x2061, 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, - 0x0090, 0x6043, 0x0010, 0x2009, 0x1973, 0x200b, 0x0000, 0x2009, - 0x002d, 0x2011, 0x5d1a, 0x080c, 0x824d, 0x012e, 0x00ce, 0x002e, - 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, - 0x2071, 0x0100, 0x080c, 0x961a, 0x2071, 0x0140, 0x7004, 0x9084, - 0x4000, 0x0110, 0x080c, 0x2b7f, 0x080c, 0x7186, 0x0188, 0x080c, - 0x71a1, 0x1170, 0x080c, 0x7484, 0x0016, 0x080c, 0x2785, 0x2001, - 0x1947, 0x2102, 0x001e, 0x080c, 0x747f, 0x080c, 0x709e, 0x0050, - 0x2009, 0x0001, 0x080c, 0x2a9d, 0x2001, 0x0001, 0x080c, 0x2616, - 0x080c, 0x5cee, 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, - 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, - 0x1973, 0x201c, 0x080c, 0x4a17, 0x003e, 0x002e, 0x0005, 0x20a9, - 0x0012, 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x080c, 0x5e09, 0x20e9, - 0x0000, 0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x5e03, - 0x2099, 0x0260, 0x20a1, 0x1c92, 0x0051, 0x20a9, 0x000e, 0x080c, - 0x5e06, 0x2099, 0x0260, 0x20a1, 0x1cb2, 0x0009, 0x0005, 0x0016, - 0x0026, 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, - 0x1f04, 0x5d83, 0x002e, 0x001e, 0x0005, 0x080c, 0x9df2, 0x20e1, - 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, - 0x000c, 0x4003, 0x0005, 0x080c, 0x9df2, 0x080c, 0x5e09, 0x20e1, - 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, - 0x000c, 0x4003, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, - 0x2001, 0x1833, 0x2004, 0x9005, 0x1138, 0x2001, 0x1817, 0x2004, - 0x9084, 0x00ff, 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, - 0x00ce, 0x0005, 0x0016, 0x0046, 0x080c, 0x66c5, 0x0158, 0x9006, - 0x2020, 0x2009, 0x002a, 0x080c, 0xd837, 0x2001, 0x180c, 0x200c, - 0xc195, 0x2102, 0x2019, 0x002a, 0x900e, 0x080c, 0x3060, 0x080c, - 0xc459, 0x0140, 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, - 0x4bb4, 0x003e, 0x004e, 0x001e, 0x0005, 0x080c, 0x5cee, 0x7097, - 0x0000, 0x708f, 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, 0x1981, 0x0118, 0x2003, - 0x0001, 0x0010, 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, - 0x2009, 0x1000, 0x9006, 0x200a, 0x8108, 0x1f04, 0x5e43, 0x015e, - 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x185b, - 0x9006, 0xb802, 0xb8be, 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, - 0x9198, 0x31f3, 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, - 0xb8b2, 0x080c, 0x9f69, 0x1120, 0x9192, 0x007e, 0x1208, 0xbbb2, - 0x20a9, 0x0004, 0xb8b4, 0x20e8, 0xb9b8, 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, - 0xb8ae, 0xb9a2, 0x0096, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1069, - 0xb8a7, 0x0000, 0x009e, 0x9006, 0xb84a, 0x6810, 0xb83a, 0x680c, - 0xb846, 0x6814, 0x9084, 0x00ff, 0xb842, 0x014e, 0x013e, 0x015e, - 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0xa974, 0xae78, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x5f19, 0x9182, 0x0800, - 0x1a04, 0x5f1d, 0x2001, 0x180c, 0x2004, 0x9084, 0x0003, 0x1904, - 0x5f23, 0x9188, 0x1000, 0x2104, 0x905d, 0x0518, 0xb804, 0x9084, - 0x00ff, 0x908e, 0x0006, 0x1508, 0xb8a4, 0x900d, 0x1904, 0x5f35, - 0xb850, 0x900d, 0x1148, 0xa802, 0x2900, 0xb852, 0xb84e, 0x080c, - 0x8615, 0x9006, 0x012e, 0x0005, 0x00a6, 0x2150, 0x2900, 0xb002, - 0xa803, 0x0000, 0x00ae, 0xb852, 0x0c90, 0x2001, 0x0005, 0x900e, - 0x04b8, 0x2001, 0x0028, 0x900e, 0x0498, 0x9082, 0x0006, 0x1290, - 0x080c, 0x9f69, 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, 0x66c9, 0x1990, - 0xb800, 0xd0bc, 0x0978, 0x0804, 0x5ecc, 0x080c, 0x653f, 0x0904, - 0x5ee5, 0x0804, 0x5ed0, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, - 0xa974, 0x9182, 0x0800, 0x1a04, 0x5fb9, 0x9188, 0x1000, 0x2104, - 0x905d, 0x0904, 0x5f91, 0xb8a0, 0x9086, 0x007f, 0x0190, 0xa87c, - 0xd0fc, 0x1178, 0x080c, 0x66d1, 0x0160, 0xa994, 0x81ff, 0x0130, - 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x080c, 0x66c9, - 0x1598, 0xa87c, 0xd0fc, 0x01e0, 0xa894, 0x9005, 0x01c8, 0x2060, - 0x0026, 0x2010, 0x080c, 0xbd3c, 0x002e, 0x1120, 0x2001, 0x0008, - 0x0804, 0x5fbb, 0x6020, 0x9086, 0x000a, 0x0120, 0x2001, 0x0008, - 0x0804, 0x5fbb, 0x601a, 0x6003, 0x0008, 0x2900, 0x6016, 0x0058, - 0x080c, 0x9f94, 0x05e8, 0x2b00, 0x6012, 0x2900, 0x6016, 0x600b, - 0xffff, 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0xa068, 0x9006, - 0x0458, 0x2001, 0x0028, 0x0438, 0x9082, 0x0006, 0x1290, 0x080c, - 0x9f69, 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, 0x6050, 0x600b, 0x6022, 0x6050, 0x6050, - 0x6050, 0x6050, 0x6050, 0x2100, 0x9082, 0x007e, 0x1278, 0x080c, - 0x6343, 0x0148, 0x9046, 0xb810, 0x9306, 0x1904, 0x6058, 0xb814, - 0x9206, 0x15f0, 0x0028, 0xbb12, 0xba16, 0x0010, 0x080c, 0x48d1, - 0x0150, 0x04b0, 0x080c, 0x63a3, 0x1598, 0xb810, 0x9306, 0x1580, - 0xb814, 0x9206, 0x1568, 0x080c, 0x9f94, 0x0530, 0x2b00, 0x6012, - 0x080c, 0xc1ca, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, - 0xa878, 0x9086, 0x0001, 0x1170, 0x080c, 0x3095, 0x9006, 0x080c, - 0x62e0, 0x2001, 0x0002, 0x080c, 0x62f4, 0x2001, 0x0200, 0xb86e, - 0xb893, 0x0002, 0x2009, 0x0003, 0x080c, 0xa068, 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, 0x6231, 0x90c6, 0x0056, 0x0904, 0x6235, - 0x90c6, 0x0066, 0x0904, 0x6239, 0x90c6, 0x0067, 0x0904, 0x623d, - 0x90c6, 0x0068, 0x0904, 0x6241, 0x90c6, 0x0071, 0x0904, 0x6245, - 0x90c6, 0x0074, 0x0904, 0x6249, 0x90c6, 0x007c, 0x0904, 0x624d, - 0x90c6, 0x007e, 0x0904, 0x6251, 0x90c6, 0x0037, 0x0904, 0x6255, - 0x9016, 0x2079, 0x1800, 0xa974, 0x9186, 0x00ff, 0x0904, 0x622c, - 0x9182, 0x0800, 0x1a04, 0x622c, 0x080c, 0x63a3, 0x1198, 0xb804, - 0x9084, 0x00ff, 0x9082, 0x0006, 0x1268, 0xa894, 0x90c6, 0x006f, - 0x0148, 0x080c, 0x9f69, 0x1904, 0x6215, 0xb8a0, 0x9084, 0xff80, - 0x1904, 0x6215, 0xa894, 0x90c6, 0x006f, 0x0158, 0x90c6, 0x005e, - 0x0904, 0x6175, 0x90c6, 0x0064, 0x0904, 0x619e, 0x2008, 0x0804, - 0x6138, 0xa998, 0xa8b0, 0x2040, 0x080c, 0x9f69, 0x1120, 0x9182, - 0x007f, 0x0a04, 0x6138, 0x9186, 0x00ff, 0x0904, 0x6138, 0x9182, - 0x0800, 0x1a04, 0x6138, 0xaaa0, 0xab9c, 0x7878, 0x9306, 0x11a8, - 0x787c, 0x0096, 0x924e, 0x1128, 0x2208, 0x2310, 0x009e, 0x0804, - 0x6138, 0x080c, 0x9f69, 0x1140, 0x99cc, 0xff00, 0x009e, 0x1128, - 0x2208, 0x2310, 0x0804, 0x6138, 0x009e, 0x080c, 0x48d1, 0x0904, - 0x6141, 0x900e, 0x9016, 0x90c6, 0x4000, 0x1558, 0x0006, 0x080c, - 0x65c3, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x20a9, - 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8b4, - 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fb4, 0x20a9, - 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8b4, - 0x20e0, 0xb8b8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0fb4, 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, - 0x0470, 0x080c, 0x9f94, 0x1130, 0x2001, 0x4005, 0x2009, 0x0003, - 0x9016, 0x0c80, 0x2b00, 0x6012, 0x080c, 0xc1ca, 0x2900, 0x6016, - 0x6023, 0x0001, 0xa868, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0x0126, - 0x2091, 0x8000, 0x080c, 0x3095, 0x012e, 0x9006, 0x080c, 0x62e0, - 0x2001, 0x0002, 0x080c, 0x62f4, 0x2009, 0x0002, 0x080c, 0xa068, - 0xa8b0, 0xd094, 0x0118, 0xb8bc, 0xc08d, 0xb8be, 0x9006, 0x9005, - 0x012e, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x080c, 0x54ef, 0x0118, - 0x2009, 0x0007, 0x00f8, 0xa998, 0xaeb0, 0x080c, 0x63a3, 0x1904, - 0x6133, 0x9186, 0x007f, 0x0130, 0x080c, 0x66c9, 0x0118, 0x2009, - 0x0009, 0x0080, 0x0096, 0x080c, 0x1037, 0x1120, 0x009e, 0x2009, - 0x0002, 0x0040, 0x2900, 0x009e, 0xa806, 0x080c, 0xbf36, 0x19b0, - 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x613a, 0xa998, 0xaeb0, - 0x080c, 0x63a3, 0x1904, 0x6133, 0x0096, 0x080c, 0x1037, 0x1128, - 0x009e, 0x2009, 0x0002, 0x0804, 0x61f2, 0x2900, 0x009e, 0xa806, - 0x0096, 0x2048, 0x20a9, 0x002b, 0xb8b4, 0x20e0, 0xb8b8, 0x2098, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, - 0x0008, 0x9080, 0x0006, 0x20a0, 0xbbb8, 0x9398, 0x0006, 0x2398, - 0x080c, 0x0fb4, 0x009e, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, - 0x4000, 0xd684, 0x1168, 0x080c, 0x54db, 0xd0b4, 0x1118, 0xa89b, - 0x000b, 0x00e0, 0xb800, 0xd08c, 0x0118, 0xa89b, 0x000c, 0x00b0, - 0x080c, 0x66c9, 0x0118, 0xa89b, 0x0009, 0x0080, 0x080c, 0x54ef, - 0x0118, 0xa89b, 0x0007, 0x0050, 0x080c, 0xbf19, 0x1904, 0x616e, - 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x613a, 0xa87b, 0x0030, - 0xa897, 0x4005, 0xa804, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, - 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, 0xab9c, - 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x128e, 0x080c, 0xa4f1, - 0x1904, 0x616e, 0x2009, 0x0002, 0x08e8, 0x2001, 0x0028, 0x900e, - 0x0804, 0x616f, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, - 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, - 0x0029, 0x900e, 0x0804, 0x616f, 0x2001, 0x0029, 0x900e, 0x0804, - 0x616f, 0x080c, 0x3624, 0x0804, 0x6170, 0x080c, 0x5206, 0x0804, - 0x6170, 0x080c, 0x448c, 0x0804, 0x6170, 0x080c, 0x4505, 0x0804, - 0x6170, 0x080c, 0x4561, 0x0804, 0x6170, 0x080c, 0x498d, 0x0804, - 0x6170, 0x080c, 0x4c36, 0x0804, 0x6170, 0x080c, 0x4e6d, 0x0804, - 0x6170, 0x080c, 0x5066, 0x0804, 0x6170, 0x080c, 0x384d, 0x0804, - 0x6170, 0x00b6, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, - 0x1618, 0x9182, 0x0800, 0x1268, 0x9188, 0x1000, 0x2104, 0x905d, - 0x0140, 0x080c, 0x66c9, 0x1148, 0x00e9, 0x080c, 0x64ce, 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, - 0x19c2, 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, 0x66c5, 0x0140, 0x9284, 0xff00, - 0x8007, 0x9086, 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, - 0xff00, 0x9215, 0xba06, 0x0006, 0x9086, 0x0006, 0x1120, 0xba90, - 0x82ff, 0x090c, 0x0df6, 0x000e, 0x00ce, 0x012e, 0x00be, 0x0005, - 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, - 0x0006, 0x9086, 0x0006, 0x1168, 0xb89c, 0xd0a4, 0x0150, 0x080c, - 0x66c1, 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, 0x1180, - 0x0096, 0x080c, 0x1037, 0x2958, 0x009e, 0x0160, 0x2b00, 0x2012, - 0xb85c, 0xb8ba, 0xb860, 0xb8b6, 0x9006, 0xb8a6, 0x080c, 0x5e49, - 0x9006, 0x0010, 0x9085, 0x0001, 0x002e, 0x00de, 0x0005, 0x00b6, - 0x0096, 0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x0800, 0x0218, - 0x9085, 0x0001, 0x0458, 0x00d6, 0x9190, 0x1000, 0x2204, 0x905d, - 0x0518, 0x2013, 0x0000, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1069, - 0x00d6, 0x00c6, 0xb8ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, - 0x6014, 0x2048, 0x080c, 0xbd4e, 0x0110, 0x080c, 0x0fe9, 0x080c, - 0x9fea, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x2b48, 0xb8b8, 0xb85e, - 0xb8b4, 0xb862, 0x080c, 0x1079, 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, 0x717e, 0x1510, 0xb8a0, - 0x9086, 0x007e, 0x0120, 0x080c, 0x9f69, 0x11d8, 0x0078, 0x7040, - 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x195c, 0x7048, 0x2062, 0x704c, - 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c, 0x2069, - 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, 0x1800, - 0x68b2, 0x7040, 0xb85e, 0x7048, 0xb862, 0x704c, 0xb866, 0x20e1, - 0x0000, 0x2099, 0x0276, 0xb8b4, 0x20e8, 0xb8b8, 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, 0xbbbc, 0xc384, 0xba00, 0x2009, 0x187b, 0x210c, - 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, - 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, 0x0128, 0xd38c, 0x1108, - 0xc385, 0x0008, 0xc2bc, 0xba02, 0xbbbe, 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, 0x0df6, 0x3c00, 0x20e8, 0x3300, 0x8001, 0x20a0, - 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, 0x014e, 0x013e, 0x0060, - 0x080c, 0x1037, 0x0170, 0x2900, 0xb8a6, 0xa803, 0x0000, 0x080c, - 0x655f, 0xa807, 0x0001, 0xae12, 0x9085, 0x0001, 0x012e, 0x009e, - 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x0096, 0xb8a4, - 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, 0x080c, 0x656e, 0x1158, - 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, 0xa806, 0x0020, 0x080c, - 0x1069, 0xb8a7, 0x0000, 0x009e, 0x012e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x080c, 0x8615, 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, 0x9955, 0xaa00, 0xb84c, - 0x9906, 0x1110, 0xba4e, 0x0020, 0x00a6, 0x2150, 0xb202, 0x00ae, - 0x82ff, 0x1110, 0xb952, 0x89ff, 0x012e, 0x0005, 0x9016, 0x0489, - 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, 0x65c3, 0x0128, 0x080c, - 0xbe0b, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x65c3, 0x0128, - 0x080c, 0xbdb0, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x65c3, - 0x0128, 0x080c, 0xbe08, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, - 0x65c3, 0x0128, 0x080c, 0xbdcf, 0x0010, 0x9085, 0x0001, 0x0005, - 0x080c, 0x65c3, 0x0128, 0x080c, 0xbe4e, 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, 0x1037, 0x0168, 0x2900, 0xb8a6, 0x080c, 0x655f, - 0xa803, 0x0001, 0xa807, 0x0000, 0x9085, 0x0001, 0x012e, 0x009e, - 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, - 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c, 0x1069, 0x9085, 0x0001, - 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4, 0x0005, 0x00b6, 0x00f6, - 0x080c, 0x717e, 0x01b0, 0x71c0, 0x81ff, 0x1198, 0x71d8, 0xd19c, - 0x0180, 0x2001, 0x007e, 0x9080, 0x1000, 0x2004, 0x905d, 0x0148, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, - 0xb802, 0x2079, 0x185b, 0x7804, 0x00d0, 0x0156, 0x20a9, 0x007f, - 0x900e, 0x0016, 0x080c, 0x63a3, 0x1168, 0xb804, 0x9084, 0xff00, - 0x8007, 0x9096, 0x0004, 0x0118, 0x9086, 0x0006, 0x1118, 0xb800, - 0xc0ed, 0xb802, 0x001e, 0x8108, 0x1f04, 0x65e9, 0x015e, 0x080c, - 0x6687, 0x0120, 0x2001, 0x195f, 0x200c, 0x0030, 0x2079, 0x185b, - 0x7804, 0x0030, 0x2009, 0x07d0, 0x2011, 0x6613, 0x080c, 0x82eb, - 0x00fe, 0x00be, 0x0005, 0x00b6, 0x2011, 0x6613, 0x080c, 0x8259, - 0x080c, 0x6687, 0x01d8, 0x2001, 0x107e, 0x2004, 0x2058, 0xb900, - 0xc1ec, 0xb902, 0x080c, 0x66c5, 0x0130, 0x2009, 0x07d0, 0x2011, - 0x6613, 0x080c, 0x82eb, 0x00e6, 0x2071, 0x1800, 0x9006, 0x707a, - 0x705c, 0x707e, 0x080c, 0x2e73, 0x00ee, 0x04c0, 0x0156, 0x00c6, - 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x63a3, 0x1548, 0xb800, - 0xd0ec, 0x0530, 0xd0bc, 0x1520, 0x0046, 0xbaa0, 0x2220, 0x9006, - 0x2009, 0x0029, 0x080c, 0xd837, 0xb800, 0xc0e5, 0xc0ec, 0xb802, - 0x080c, 0x66c1, 0x2001, 0x0707, 0x1128, 0xb804, 0x9084, 0x00ff, - 0x9085, 0x0700, 0xb806, 0x2019, 0x0029, 0x080c, 0x8782, 0x0076, - 0x903e, 0x080c, 0x8670, 0x900e, 0x080c, 0xd556, 0x007e, 0x004e, - 0x001e, 0x8108, 0x1f04, 0x663b, 0x00ce, 0x015e, 0x00be, 0x0005, - 0x00b6, 0x6010, 0x2058, 0xb800, 0xc0ec, 0xb802, 0x00be, 0x0005, - 0x7810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ac, 0x0005, 0x6010, - 0x00b6, 0x905d, 0x0108, 0xb800, 0x00be, 0xd0bc, 0x0005, 0x00b6, - 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, 0xb800, 0xd0ec, - 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, - 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, 0x0df6, 0x000e, - 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0xba02, 0x002e, - 0x012e, 0x0005, 0x2011, 0x1836, 0x2204, 0xd0cc, 0x0138, 0x2001, - 0x195d, 0x200c, 0x2011, 0x66b7, 0x080c, 0x82eb, 0x0005, 0x2011, - 0x66b7, 0x080c, 0x8259, 0x2011, 0x1836, 0x2204, 0xc0cc, 0x2012, - 0x0005, 0x080c, 0x54db, 0xd0ac, 0x0005, 0x080c, 0x54db, 0xd0a4, - 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, 0x0006, 0x001e, - 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, 0x908e, 0x0006, - 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xc459, 0x0158, 0x70d8, - 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, 0x905d, 0x0110, - 0xb8bc, 0xd094, 0x00fe, 0x00be, 0x0005, 0x0006, 0x0016, 0x0036, - 0x0046, 0x0076, 0x00b6, 0x2001, 0x1817, 0x203c, 0x9780, 0x31f3, - 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, 0x1817, 0x203c, 0x9780, - 0x31f3, 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, 0x2071, 0x190e, 0x7003, 0x0001, - 0x7007, 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, - 0x7046, 0x2001, 0x1920, 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, - 0x2071, 0x1923, 0x900e, 0x710a, 0x080c, 0x54db, 0xd0fc, 0x1140, - 0x080c, 0x54db, 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0438, - 0x2001, 0x187b, 0x200c, 0x9184, 0x0007, 0x9006, 0x0002, 0x67a0, - 0x67a0, 0x67a0, 0x67a0, 0x67a0, 0x67b7, 0x67cc, 0x67da, 0x7003, - 0x0003, 0x2009, 0x187c, 0x210c, 0x9184, 0xff00, 0x908e, 0xff00, - 0x0140, 0x8007, 0x9005, 0x1110, 0x2001, 0x0002, 0x8003, 0x7006, - 0x0030, 0x7007, 0x0001, 0x0018, 0x7003, 0x0005, 0x0c50, 0x2071, - 0x190e, 0x704f, 0x0000, 0x2071, 0x1800, 0x70ef, 0x0001, 0x00ee, - 0x001e, 0x0005, 0x7003, 0x0000, 0x2071, 0x190e, 0x2009, 0x187c, - 0x210c, 0x9184, 0x7f00, 0x8007, 0x908c, 0x000f, 0x0160, 0x714e, - 0x8004, 0x8004, 0x8004, 0x8004, 0x2071, 0x1800, 0x908c, 0x0007, - 0x0128, 0x70ee, 0x0c20, 0x704f, 0x000f, 0x0c90, 0x70ef, 0x0005, - 0x08f0, 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, - 0x2071, 0x190e, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, - 0x0488, 0x6844, 0x9005, 0x0158, 0x080c, 0x74ec, 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, - 0x190e, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, - 0x00ee, 0x9006, 0x00ee, 0x0005, 0xa868, 0xd0fc, 0x1508, 0x00e6, - 0x0026, 0x2001, 0x1923, 0x2004, 0x9015, 0x0904, 0x6a28, 0xa978, - 0xa874, 0x9105, 0x1904, 0x6a28, 0x9286, 0x0003, 0x0904, 0x68c1, - 0x9286, 0x0005, 0x0904, 0x68c1, 0xa87c, 0xd0bc, 0x1904, 0x6a28, - 0x2200, 0x0002, 0x6a28, 0x6885, 0x68c1, 0x68c1, 0x6a28, 0x68c1, - 0x0005, 0xa868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x2009, 0x1923, - 0x210c, 0x81ff, 0x0904, 0x6a28, 0xa880, 0x9084, 0x00ff, 0x9086, - 0x0001, 0x1904, 0x6a28, 0x9186, 0x0003, 0x0904, 0x68c1, 0x9186, - 0x0005, 0x0904, 0x68c1, 0xa87c, 0xd0cc, 0x0904, 0x6a28, 0xa84f, - 0x8021, 0xa853, 0x0017, 0x0028, 0x0005, 0xa84f, 0x8020, 0xa853, - 0x0016, 0x2071, 0x190e, 0x701c, 0x9005, 0x1904, 0x6bf6, 0x0e04, - 0x6c41, 0x2071, 0x0000, 0xa84c, 0x7082, 0xa850, 0x7032, 0xa86c, - 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x11e6, 0x2071, 0x1800, 0x2011, 0x0001, - 0xa804, 0x900d, 0x702c, 0x1158, 0xa802, 0x2900, 0x702e, 0x70bc, - 0x9200, 0x70be, 0x080c, 0x816f, 0x002e, 0x00ee, 0x0005, 0x0096, - 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x009e, - 0x0c58, 0xa84f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x190e, - 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, 0x69ac, 0x782c, 0x908c, - 0x0780, 0x190c, 0x6d6a, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, - 0x0002, 0x68df, 0x69ac, 0x6903, 0x6949, 0x080c, 0x0df6, 0x2071, - 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1168, 0x2071, 0x19d5, - 0x7044, 0x9005, 0x1320, 0x2001, 0x1924, 0x2004, 0x7046, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, - 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, - 0x080c, 0x816f, 0x0c18, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, - 0x900d, 0x1578, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, - 0x1148, 0x2009, 0x182f, 0x210c, 0x918a, 0x0040, 0x0218, 0x7022, - 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70bc, 0x8000, 0x70be, 0x080c, 0x816f, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6d6a, 0xd0a4, 0x19f0, 0x2071, 0x19d5, 0x7044, 0x9005, - 0x1320, 0x2001, 0x1924, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x816f, - 0x0808, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, - 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x816f, - 0x782c, 0x9094, 0x0780, 0x190c, 0x6d6a, 0xd0a4, 0x1d60, 0x00ee, - 0x782c, 0x9094, 0x0780, 0x190c, 0x6d6a, 0xd09c, 0x1198, 0x009e, - 0x2900, 0x7822, 0xa804, 0x900d, 0x1550, 0x2071, 0x19d5, 0x7044, - 0x9005, 0x1320, 0x2001, 0x1924, 0x2004, 0x7046, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, - 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, - 0x900d, 0x1168, 0x2071, 0x19d5, 0x7044, 0x9005, 0x1320, 0x2001, - 0x1924, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, - 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x816f, - 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, - 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, - 0xa804, 0x900d, 0x1904, 0x6a00, 0x782c, 0x9094, 0x0780, 0x190c, - 0x6d6a, 0xd09c, 0x1198, 0x701c, 0x904d, 0x0180, 0x7010, 0x8001, - 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, - 0x9094, 0x0780, 0x190c, 0x6d6a, 0xd09c, 0x0d68, 0x782c, 0x9094, - 0x0780, 0x190c, 0x6d6a, 0xd0a4, 0x01b0, 0x00e6, 0x7824, 0x2048, - 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, - 0x70be, 0x080c, 0x816f, 0x782c, 0x9094, 0x0780, 0x190c, 0x6d6a, - 0xd0a4, 0x1d60, 0x00ee, 0x2071, 0x19d5, 0x7044, 0x9005, 0x1320, - 0x2001, 0x1924, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, - 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, - 0x080c, 0x816f, 0x00ee, 0x0804, 0x69bc, 0xa868, 0xd0fc, 0x1904, - 0x6a76, 0x0096, 0xa804, 0xa807, 0x0000, 0x904d, 0x190c, 0x0fe9, - 0x009e, 0x0020, 0xa868, 0xd0fc, 0x1904, 0x6a76, 0x00e6, 0x0026, - 0xa84f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1800, 0x70e8, - 0x8001, 0x0558, 0x1a04, 0x6a73, 0x2071, 0x190e, 0xa803, 0x0000, - 0xa864, 0x9084, 0x00ff, 0x908e, 0x0016, 0x01a8, 0x7010, 0x9005, - 0x1904, 0x6b72, 0x782c, 0x908c, 0x0780, 0x190c, 0x6d6a, 0x8004, - 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x6a77, 0x6b72, 0x6a92, - 0x6b03, 0x080c, 0x0df6, 0x2009, 0x1923, 0x2104, 0x0002, 0x6a3e, - 0x6a3e, 0x6a3e, 0x68ca, 0x6a3e, 0x68ca, 0x70eb, 0x0fa0, 0x71e4, - 0x8107, 0x9106, 0x9094, 0x00c0, 0x9184, 0xff3f, 0x9205, 0x70e6, - 0x3b08, 0x3a00, 0x9104, 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, - 0x9205, 0x20d0, 0x0808, 0x70ea, 0x0804, 0x6a34, 0x0005, 0x2071, - 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, - 0x816f, 0x0c60, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, - 0x1904, 0x6af2, 0x7830, 0x8007, 0x908c, 0x001f, 0x70ec, 0x9102, - 0x1220, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7824, 0x00e6, 0x2071, - 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x182f, 0x210c, 0x918a, - 0x0040, 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, - 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x816f, - 0x782c, 0x9094, 0x0780, 0x190c, 0x6d6a, 0xd0a4, 0x19f0, 0x0e04, - 0x6ae9, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, - 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, 0x191f, 0x200c, 0xc184, - 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11e6, 0x2001, 0x1920, 0x2003, 0x0000, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x2001, 0x191f, 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, - 0x816f, 0x0804, 0x6aa5, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, - 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, - 0x080c, 0x816f, 0x782c, 0x9094, 0x0780, 0x190c, 0x6d6a, 0xd0a4, - 0x1d60, 0x00ee, 0x0e04, 0x6b45, 0x7838, 0x7938, 0x910e, 0x1de0, - 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, - 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x11e6, 0x704b, 0x0000, 0x782c, 0x9094, 0x0780, 0x190c, - 0x6d6a, 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, 0x70bc, 0x9200, 0x70be, 0x080c, 0x816f, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, - 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, - 0x1904, 0x6be1, 0x782c, 0x9094, 0x0780, 0x190c, 0x6d6a, 0xd09c, - 0x11b0, 0x701c, 0x904d, 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, - 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, - 0x782c, 0x9094, 0x0780, 0x190c, 0x6d6a, 0xd09c, 0x0d50, 0x782c, - 0x9094, 0x0780, 0x190c, 0x6d6a, 0xd0a4, 0x05b8, 0x00e6, 0x7824, - 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, - 0x8000, 0x70be, 0x080c, 0x816f, 0x782c, 0x9094, 0x0780, 0x190c, - 0x6d6a, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, 0x6bda, 0x7838, 0x7938, - 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, - 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x11e6, 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, 0x70bc, 0x9200, - 0x70be, 0x080c, 0x816f, 0x00ee, 0x0804, 0x6b82, 0x2071, 0x190e, - 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, - 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, - 0x1128, 0x1e04, 0x6c21, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x816f, 0x0e04, - 0x6c0b, 0x2071, 0x190e, 0x701c, 0x2048, 0xa84c, 0x900d, 0x0d18, - 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, - 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x11e6, 0x2071, 0x190e, 0x080c, 0x6d56, 0x002e, 0x00ee, - 0x0005, 0x2071, 0x190e, 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, 0x70bc, 0x9200, 0x70be, 0x080c, 0x816f, - 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, 0x190e, 0x7004, 0x0002, 0x6c8e, 0x6c8f, - 0x6d55, 0x6c8f, 0x6c8c, 0x6d55, 0x080c, 0x0df6, 0x0005, 0x2001, - 0x1923, 0x2004, 0x0002, 0x6c99, 0x6c99, 0x6cee, 0x6cef, 0x6c99, - 0x6cef, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x6d75, 0x701c, 0x904d, - 0x01e0, 0xa84c, 0x9005, 0x01d8, 0x0e04, 0x6cbd, 0xa94c, 0x2071, - 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, - 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11e6, 0x2071, 0x190e, 0x080c, 0x6d56, 0x012e, 0x0470, 0x2001, - 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, 0x6d6a, 0xd09c, 0x2071, - 0x190e, 0x1510, 0x2071, 0x190e, 0x700f, 0x0001, 0xa964, 0x9184, - 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, - 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, - 0x2071, 0x190e, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, - 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, - 0x2008, 0x2069, 0x19d5, 0x6844, 0x9005, 0x0760, 0x0158, 0x9186, - 0x0003, 0x0540, 0x2001, 0x1814, 0x2004, 0x2009, 0x1aa2, 0x210c, - 0x9102, 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, - 0x6838, 0x9106, 0x0190, 0x0e04, 0x6d21, 0x2069, 0x0000, 0x6837, - 0x8040, 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x11e6, 0x2069, 0x19d5, 0x6847, - 0xffff, 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x6de0, - 0x701c, 0x904d, 0x0540, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, - 0x15c9, 0xd09c, 0x1500, 0x2071, 0x190e, 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, 0x1069, 0x0005, - 0x012e, 0x0005, 0x2091, 0x8000, 0x0e04, 0x6d6c, 0x0006, 0x0016, - 0x2001, 0x8004, 0x0006, 0x0804, 0x0dff, 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, - 0x11e6, 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, 0x182f, 0x210c, 0x918a, - 0x0040, 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, - 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x816f, - 0x782c, 0x9094, 0x0780, 0x190c, 0x6d6a, 0xd0a4, 0x19f0, 0x7838, - 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, - 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x11e6, 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, 0x11e6, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6d6a, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, - 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, - 0x080c, 0x816f, 0x782c, 0x9094, 0x0780, 0x190c, 0x6d6a, 0xd0a4, - 0x1d70, 0x00d6, 0x2069, 0x0050, 0x693c, 0x2069, 0x1923, 0x6808, - 0x690a, 0x2069, 0x19d5, 0x9102, 0x1118, 0x6844, 0x9005, 0x1320, - 0x2001, 0x1924, 0x200c, 0x6946, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x7094, 0x908a, 0x002a, 0x1a0c, 0x0df6, 0x9082, 0x001d, 0x001b, - 0x6027, 0x1e00, 0x0005, 0x6f21, 0x6e8e, 0x6eaa, 0x6ed4, 0x6f10, - 0x6f50, 0x6f62, 0x6eaa, 0x6f38, 0x6e49, 0x6e77, 0x6efa, 0x6e48, - 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, - 0x9005, 0x1518, 0x7097, 0x0029, 0x2069, 0x1969, 0x2d04, 0x7002, - 0x080c, 0x72cd, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, 0x7097, - 0x0029, 0x2069, 0x1969, 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, - 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a3f, 0x080c, - 0x1977, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, - 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, - 0x7097, 0x0029, 0x2069, 0x1969, 0x2d04, 0x7002, 0x080c, 0x7369, - 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, - 0x0090, 0x080c, 0x2b6f, 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, - 0x6fcf, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x7097, - 0x0020, 0x080c, 0x6fcf, 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, - 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x2b6f, 0x6124, 0xd1cc, - 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, - 0x080c, 0x19a4, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, - 0x71aa, 0x2001, 0x0080, 0x080c, 0x2b6f, 0x7097, 0x0029, 0x0058, - 0x7097, 0x001e, 0x0040, 0x7097, 0x001d, 0x0028, 0x7097, 0x0020, - 0x0010, 0x7097, 0x001f, 0x0005, 0x080c, 0x19a4, 0x60e3, 0x0001, - 0x600c, 0xc0b4, 0x600e, 0x080c, 0x71aa, 0x2001, 0x0080, 0x080c, - 0x2b6f, 0x6124, 0xd1d4, 0x1198, 0xd1dc, 0x1170, 0xd1e4, 0x1148, - 0x9184, 0x1e00, 0x1118, 0x7097, 0x0029, 0x0058, 0x7097, 0x0028, - 0x0040, 0x7097, 0x001e, 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, - 0x001f, 0x0005, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, - 0x1130, 0x9184, 0x1e00, 0x1158, 0x7097, 0x0029, 0x0040, 0x7097, - 0x001e, 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, 0x001f, 0x0005, - 0x2001, 0x00a0, 0x080c, 0x2b6f, 0x6124, 0xd1dc, 0x1138, 0xd1e4, - 0x0138, 0x080c, 0x19a4, 0x7097, 0x001e, 0x0010, 0x7097, 0x001d, - 0x0005, 0x080c, 0x7052, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x6fcf, - 0x0016, 0x080c, 0x19a4, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, - 0x7097, 0x001e, 0x0020, 0x7097, 0x001f, 0x080c, 0x6fcf, 0x0005, - 0x0006, 0x2001, 0x00a0, 0x080c, 0x2b6f, 0x000e, 0x6124, 0xd1d4, - 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7097, - 0x001e, 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, 0x0021, 0x0005, - 0x080c, 0x7052, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, - 0x0140, 0x7097, 0x001e, 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, - 0x001f, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2b6f, 0x000e, - 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, - 0x0158, 0x7097, 0x001e, 0x0040, 0x7097, 0x001d, 0x0028, 0x7097, - 0x0020, 0x0010, 0x7097, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, - 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, - 0x2091, 0x8000, 0x080c, 0x717e, 0x11d8, 0x2001, 0x180c, 0x200c, - 0xd1b4, 0x01b0, 0xc1b4, 0x2102, 0x6027, 0x0200, 0x080c, 0x2a97, - 0x6024, 0xd0cc, 0x0148, 0x2001, 0x00a0, 0x080c, 0x2b6f, 0x080c, - 0x747a, 0x080c, 0x5e2f, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, - 0x080c, 0x7198, 0x0150, 0x080c, 0x718f, 0x1138, 0x2001, 0x0001, - 0x080c, 0x2616, 0x080c, 0x7156, 0x00a0, 0x080c, 0x704f, 0x0178, - 0x2001, 0x0001, 0x080c, 0x2616, 0x7094, 0x9086, 0x001e, 0x0120, - 0x7094, 0x9086, 0x0022, 0x1118, 0x7097, 0x0025, 0x0010, 0x7097, - 0x0021, 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, - 0x2011, 0x6fe0, 0x080c, 0x832d, 0x002e, 0x0016, 0x0026, 0x2009, - 0x0064, 0x2011, 0x6fe0, 0x080c, 0x8324, 0x002e, 0x001e, 0x0005, - 0x00e6, 0x00f6, 0x0016, 0x080c, 0x961a, 0x2071, 0x1800, 0x080c, - 0x6f7d, 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x2071, 0x1800, 0x080c, - 0x961a, 0x2061, 0x0100, 0x2069, 0x0140, 0x2091, 0x8000, 0x6028, - 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, 0x9923, 0x2011, 0x0002, - 0x080c, 0x992d, 0x080c, 0x983b, 0x080c, 0x82d9, 0x0036, 0x901e, - 0x080c, 0x98b1, 0x003e, 0x60e3, 0x0000, 0x080c, 0xdbdb, 0x080c, - 0xdbf6, 0x2009, 0x0004, 0x080c, 0x2a9d, 0x080c, 0x2974, 0x2001, - 0x1800, 0x2003, 0x0004, 0x6027, 0x0008, 0x2011, 0x6fe0, 0x080c, - 0x832d, 0x080c, 0x7198, 0x0118, 0x9006, 0x080c, 0x2b6f, 0x080c, - 0x0b8f, 0x2001, 0x0001, 0x080c, 0x2616, 0x012e, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, - 0x2011, 0x6fed, 0x2071, 0x19d5, 0x701c, 0x9206, 0x1118, 0x7018, - 0x9005, 0x0110, 0x9085, 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, - 0xd09c, 0x0005, 0x6800, 0x9084, 0xfffe, 0x9086, 0x00c0, 0x01b8, - 0x2001, 0x00c0, 0x080c, 0x2b6f, 0x0156, 0x20a9, 0x002d, 0x1d04, - 0x705f, 0x2091, 0x6000, 0x1f04, 0x705f, 0x015e, 0x00d6, 0x2069, - 0x1800, 0x6898, 0x8001, 0x0220, 0x0118, 0x689a, 0x00de, 0x0005, - 0x689b, 0x0014, 0x68e4, 0xd0dc, 0x0dc8, 0x6800, 0x9086, 0x0001, - 0x1da8, 0x080c, 0x8339, 0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x7489, 0x2001, - 0x1947, 0x2003, 0x0000, 0x9006, 0x7096, 0x60e2, 0x6886, 0x080c, - 0x26e1, 0x9006, 0x080c, 0x2b6f, 0x080c, 0x5cee, 0x6027, 0xffff, - 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, - 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, - 0x1957, 0x200c, 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, - 0x9186, 0x0002, 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x7146, - 0x7097, 0x0022, 0x0040, 0x7097, 0x0021, 0x0028, 0x7097, 0x0023, - 0x0010, 0x7097, 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, - 0x0001, 0x080c, 0x26e1, 0x0026, 0x080c, 0x9f70, 0x002e, 0x7000, - 0x908e, 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, - 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, - 0x0150, 0x012e, 0x015e, 0x080c, 0xc459, 0x0118, 0x9006, 0x080c, - 0x2b99, 0x0804, 0x7152, 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, - 0x080c, 0x2a97, 0x6904, 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, - 0x2b6f, 0x1f04, 0x70de, 0x080c, 0x71d2, 0x012e, 0x015e, 0x080c, - 0x718f, 0x0538, 0x6044, 0x9005, 0x01f8, 0x2001, 0x0100, 0x2004, - 0x9086, 0x000a, 0x0158, 0x2011, 0x0114, 0x2204, 0x9085, 0x0100, - 0x2012, 0x6050, 0x0006, 0x9085, 0x0020, 0x6052, 0x080c, 0x71d2, - 0x9006, 0x8001, 0x1df0, 0x2001, 0x0100, 0x2004, 0x9086, 0x000a, - 0x0140, 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, - 0x71d2, 0x080c, 0xc459, 0x0118, 0x9006, 0x080c, 0x2b99, 0x0016, - 0x0026, 0x7000, 0x908e, 0x0004, 0x0130, 0x2009, 0x00c8, 0x2011, - 0x6fed, 0x080c, 0x82eb, 0x002e, 0x001e, 0x080c, 0x8166, 0x7034, - 0xc085, 0x7036, 0x2001, 0x1957, 0x2003, 0x0004, 0x080c, 0x6e30, - 0x080c, 0x718f, 0x0138, 0x6804, 0xd0d4, 0x1120, 0xd0dc, 0x1100, - 0x080c, 0x747f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, - 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, - 0x817d, 0x080c, 0x816f, 0x080c, 0x7489, 0x2001, 0x1947, 0x2003, - 0x0000, 0x9006, 0x7096, 0x60e2, 0x6886, 0x080c, 0x26e1, 0x9006, - 0x080c, 0x2b6f, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027, 0xffff, - 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, - 0x1956, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x080c, - 0x54df, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, - 0x080c, 0x54df, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, 0x0005, - 0x0006, 0x080c, 0x54df, 0x9084, 0x0030, 0x9086, 0x0010, 0x000e, - 0x0005, 0x0006, 0x080c, 0x54df, 0x9084, 0x0030, 0x9086, 0x0020, - 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x180c, 0x2004, 0x908c, - 0x0013, 0x0168, 0x0020, 0x080c, 0x2701, 0x900e, 0x0010, 0x2009, - 0x0002, 0x2019, 0x0028, 0x080c, 0x3060, 0x9006, 0x0019, 0x001e, - 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, 0x080c, - 0xc452, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, - 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, - 0x6004, 0x0006, 0x6028, 0x0006, 0x2001, 0x0100, 0x2004, 0x9086, - 0x000a, 0x0510, 0x0016, 0x6138, 0x6050, 0x9084, 0xfbff, 0x9085, - 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012, 0x1d04, 0x71ed, 0x2091, - 0x6000, 0x1f04, 0x71ed, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, - 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x613a, 0x001e, 0x602f, - 0x0040, 0x602f, 0x0000, 0x00a0, 0x080c, 0x2ba9, 0x080c, 0x2bdc, - 0x602f, 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, - 0x20a9, 0x0002, 0x080c, 0x2a78, 0x0026, 0x6027, 0x0040, 0x002e, - 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, - 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x26e1, - 0x2001, 0x00a0, 0x0006, 0x080c, 0xc459, 0x000e, 0x0130, 0x080c, - 0x2b8d, 0x9006, 0x080c, 0x2b99, 0x0010, 0x080c, 0x2b6f, 0x000e, - 0x6052, 0x6050, 0x0006, 0xc0e5, 0x6052, 0x00f6, 0x2079, 0x0100, - 0x080c, 0x29f1, 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, 0x72bf, 0x2001, 0x180c, - 0x200c, 0xc1c4, 0x2102, 0x6028, 0x9084, 0xe1ff, 0x602a, 0x6027, - 0x0200, 0x2001, 0x0090, 0x080c, 0x2b6f, 0x20a9, 0x0366, 0x6024, - 0xd0cc, 0x1518, 0x1d04, 0x726f, 0x2091, 0x6000, 0x1f04, 0x726f, - 0x2011, 0x0003, 0x080c, 0x9923, 0x2011, 0x0002, 0x080c, 0x992d, - 0x080c, 0x983b, 0x901e, 0x080c, 0x98b1, 0x2001, 0x00a0, 0x080c, - 0x2b6f, 0x080c, 0x747a, 0x080c, 0x5e2f, 0x080c, 0xc459, 0x0110, - 0x080c, 0x0d64, 0x9085, 0x0001, 0x0480, 0x080c, 0x19a4, 0x60e3, - 0x0000, 0x2001, 0x0002, 0x080c, 0x26e1, 0x60e2, 0x2001, 0x0080, - 0x080c, 0x2b6f, 0x20a9, 0x0366, 0x6027, 0x1e00, 0x2009, 0x1e00, - 0x080c, 0x2a97, 0x6024, 0x910c, 0x0138, 0x1d04, 0x72a4, 0x2091, - 0x6000, 0x1f04, 0x72a4, 0x0820, 0x6028, 0x9085, 0x1e00, 0x602a, - 0x70b0, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, - 0xc459, 0x0110, 0x080c, 0x0d64, 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, 0x1a54, 0x2d04, 0x8000, - 0x206a, 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, - 0x9005, 0x1904, 0x7332, 0x2001, 0x0088, 0x080c, 0x2b6f, 0x9006, - 0x60e2, 0x6886, 0x080c, 0x26e1, 0x2069, 0x0200, 0x6804, 0x9005, - 0x1118, 0x6808, 0x9005, 0x01c0, 0x6028, 0x9084, 0xfbff, 0x602a, - 0x6027, 0x0400, 0x2069, 0x1969, 0x7000, 0x206a, 0x7097, 0x0026, - 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x7314, 0x2091, 0x6000, - 0x1f04, 0x7314, 0x0804, 0x7361, 0x2069, 0x0140, 0x20a9, 0x0384, - 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2a97, 0x6024, 0x910c, - 0x0508, 0x9084, 0x1a00, 0x11f0, 0x1d04, 0x7320, 0x2091, 0x6000, - 0x1f04, 0x7320, 0x2011, 0x0003, 0x080c, 0x9923, 0x2011, 0x0002, - 0x080c, 0x992d, 0x080c, 0x983b, 0x901e, 0x080c, 0x98b1, 0x2001, - 0x00a0, 0x080c, 0x2b6f, 0x080c, 0x747a, 0x080c, 0x5e2f, 0x9085, - 0x0001, 0x00b8, 0x080c, 0x19a4, 0x2001, 0x0080, 0x080c, 0x2b6f, - 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b0, 0x9005, 0x1118, 0x6887, - 0x0001, 0x0008, 0x6886, 0x2001, 0x0002, 0x080c, 0x26e1, 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, 0x9923, 0x2011, 0x0002, 0x080c, 0x992d, - 0x080c, 0x983b, 0x901e, 0x080c, 0x98b1, 0x2069, 0x0140, 0x2001, - 0x00a0, 0x080c, 0x2b6f, 0x080c, 0x747a, 0x080c, 0x5e2f, 0x0804, - 0x73fb, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, 0x2102, - 0x080c, 0x6fd5, 0x2069, 0x0140, 0x2001, 0x0080, 0x080c, 0x2b6f, - 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, - 0x9005, 0x0180, 0x6028, 0x9084, 0xfdff, 0x602a, 0x6027, 0x0200, - 0x2069, 0x1969, 0x7000, 0x206a, 0x7097, 0x0027, 0x7003, 0x0001, - 0x0804, 0x73fb, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2a97, - 0x6024, 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x73ba, - 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x81bd, 0x00ee, - 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x19d5, 0x7078, - 0x00ee, 0x9005, 0x19f8, 0x00f8, 0x0026, 0x2011, 0x6fed, 0x080c, - 0x8259, 0x2011, 0x6fe0, 0x080c, 0x832d, 0x002e, 0x2069, 0x0140, - 0x60e3, 0x0000, 0x70b0, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, - 0x6886, 0x2001, 0x0002, 0x080c, 0x26e1, 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, 0xc452, - 0x1904, 0x7468, 0x7130, 0xd184, 0x1170, 0x080c, 0x31ee, 0x0138, - 0xc18d, 0x7132, 0x2011, 0x185c, 0x2214, 0xd2ac, 0x1120, 0x7030, - 0xd08c, 0x0904, 0x7468, 0x2011, 0x185c, 0x220c, 0x0438, 0x0016, - 0x2019, 0x000e, 0x080c, 0xd7af, 0x0156, 0x00b6, 0x20a9, 0x007f, - 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c, - 0x63a3, 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, 0x080c, - 0xd837, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8450, 0x001e, - 0x8108, 0x1f04, 0x7431, 0x00be, 0x015e, 0x001e, 0xd1ac, 0x1148, - 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x3060, 0x001e, - 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x63a3, - 0x1110, 0x080c, 0x5e49, 0x8108, 0x1f04, 0x745e, 0x00be, 0x015e, - 0x080c, 0x19a4, 0x080c, 0x9f70, 0x60e3, 0x0000, 0x080c, 0x5e2f, - 0x080c, 0x709e, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, - 0x015e, 0x0005, 0x2001, 0x1957, 0x2003, 0x0001, 0x0005, 0x2001, - 0x1957, 0x2003, 0x0000, 0x0005, 0x2001, 0x1956, 0x2003, 0xaaaa, - 0x0005, 0x2001, 0x1956, 0x2003, 0x0000, 0x0005, 0x2071, 0x18f8, - 0x7003, 0x0000, 0x7007, 0x0000, 0x080c, 0x1050, 0x090c, 0x0df6, - 0xa8ab, 0xdcb0, 0x2900, 0x704e, 0x080c, 0x1050, 0x090c, 0x0df6, - 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, 0x18f8, 0x6807, 0x0001, 0x00de, 0x080c, - 0x7a7c, 0x9006, 0x00ee, 0x0005, 0x900e, 0x0156, 0x20a9, 0x0006, - 0x8003, 0x818d, 0x1f04, 0x74f0, 0x015e, 0x0005, 0x2079, 0x0040, - 0x2071, 0x18f8, 0x7004, 0x0002, 0x7506, 0x7507, 0x753f, 0x759a, - 0x76df, 0x7504, 0x7504, 0x7709, 0x080c, 0x0df6, 0x0005, 0x2079, - 0x0040, 0x782c, 0x908c, 0x0780, 0x190c, 0x7b08, 0xd0a4, 0x01f8, - 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, - 0x908a, 0x0040, 0x0610, 0x00c0, 0x2001, 0x1800, 0x200c, 0x9186, - 0x0003, 0x1168, 0x7004, 0x0002, 0x752f, 0x7509, 0x752f, 0x752d, - 0x752f, 0x752f, 0x752f, 0x752f, 0x752f, 0x080c, 0x759a, 0x782c, - 0xd09c, 0x090c, 0x7a7c, 0x0005, 0x9082, 0x005a, 0x1218, 0x2100, - 0x003b, 0x0c10, 0x080c, 0x75d0, 0x0c90, 0x00e3, 0x08e8, 0x0005, - 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, - 0x75f2, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, - 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, - 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75dc, 0x75d0, 0x77e3, 0x75d0, - 0x75d0, 0x75d0, 0x75f2, 0x75d0, 0x75dc, 0x7824, 0x7865, 0x78ac, - 0x78c0, 0x75d0, 0x75d0, 0x75f2, 0x75dc, 0x75d0, 0x75d0, 0x76b3, - 0x796b, 0x7986, 0x75d0, 0x75f2, 0x75d0, 0x75d0, 0x75d0, 0x75d0, - 0x76a9, 0x7986, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, - 0x75d0, 0x75d0, 0x75d0, 0x7606, 0x75d0, 0x75d0, 0x75d0, 0x75d0, - 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x75d0, 0x7aac, 0x75d0, 0x75d0, - 0x75d0, 0x75d0, 0x75d0, 0x761a, 0x75d0, 0x75d0, 0x75d0, 0x75d0, - 0x75d0, 0x75d0, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, 0x1198, - 0x782c, 0x080c, 0x7aa5, 0xd0a4, 0x0170, 0x7824, 0x2048, 0x9006, - 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, - 0x002b, 0x0c50, 0x00e9, 0x080c, 0x7a7c, 0x0005, 0x75d0, 0x75dc, - 0x77cf, 0x75d0, 0x75dc, 0x75d0, 0x75dc, 0x75dc, 0x75d0, 0x75dc, - 0x77cf, 0x75dc, 0x75dc, 0x75dc, 0x75dc, 0x75dc, 0x75d0, 0x75dc, - 0x77cf, 0x75d0, 0x75d0, 0x75dc, 0x75d0, 0x75d0, 0x75d0, 0x75dc, - 0x00e6, 0x2071, 0x18f8, 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, 0x6a22, - 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, - 0x1120, 0x7007, 0x0001, 0x0804, 0x7788, 0x7007, 0x0003, 0x7012, - 0x2900, 0x7016, 0x701a, 0x704b, 0x7788, 0x0005, 0xa864, 0x8007, - 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, - 0x77a3, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, - 0x77a3, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, - 0x1904, 0x75d8, 0x7007, 0x0001, 0x2009, 0x1833, 0x210c, 0x81ff, - 0x1904, 0x7680, 0xa99c, 0x9186, 0x00ff, 0x05e8, 0xa994, 0x9186, - 0x006f, 0x0188, 0x9186, 0x0074, 0x15b0, 0x0026, 0x2011, 0x0010, - 0x080c, 0x66ed, 0x002e, 0x0578, 0x0016, 0xa998, 0x080c, 0x6737, - 0x001e, 0x1548, 0x0400, 0x080c, 0x717e, 0x0140, 0xa897, 0x4005, - 0xa89b, 0x0016, 0x2001, 0x0030, 0x900e, 0x0438, 0x0026, 0x2011, - 0x8008, 0x080c, 0x66ed, 0x002e, 0x01b0, 0x0016, 0x0026, 0x0036, - 0xa998, 0xaaa0, 0xab9c, 0x918d, 0x8000, 0x080c, 0x6737, 0x003e, - 0x002e, 0x001e, 0x1140, 0xa897, 0x4005, 0xa89b, 0x4009, 0x2001, - 0x0030, 0x900e, 0x0050, 0xa868, 0x9084, 0x00ff, 0xa86a, 0xa883, - 0x0000, 0x080c, 0x6061, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, - 0xa867, 0x0139, 0xa87a, 0xa982, 0x080c, 0x6a22, 0x012e, 0x0ca0, - 0xa994, 0x9186, 0x0071, 0x0904, 0x762a, 0x9186, 0x0064, 0x0904, - 0x762a, 0x9186, 0x007c, 0x0904, 0x762a, 0x9186, 0x0028, 0x0904, - 0x762a, 0x9186, 0x0038, 0x0904, 0x762a, 0x9186, 0x0078, 0x0904, - 0x762a, 0x9186, 0x005f, 0x0904, 0x762a, 0x9186, 0x0056, 0x0904, - 0x762a, 0xa897, 0x4005, 0xa89b, 0x0001, 0x2001, 0x0030, 0x900e, - 0x0860, 0xa87c, 0x9084, 0x00c0, 0x9086, 0x00c0, 0x1120, 0x7007, - 0x0001, 0x0804, 0x799d, 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, 0x75e0, 0xaab4, 0x928a, 0x0002, - 0x1a04, 0x75e0, 0x82ff, 0x1138, 0xa8b8, 0xa9bc, 0x9105, 0x0118, - 0x2001, 0x7746, 0x0018, 0x9280, 0x773c, 0x2005, 0x7056, 0x7010, - 0x9015, 0x0904, 0x7727, 0x080c, 0x1050, 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, - 0x1134, 0xa06c, 0x908e, 0x0100, 0x0170, 0x9086, 0x0200, 0x0118, - 0x7007, 0x0007, 0x0005, 0x7020, 0x2048, 0x080c, 0x1069, 0x7014, - 0x2048, 0x0804, 0x75e0, 0x7020, 0x2048, 0x7018, 0xa802, 0xa807, - 0x0000, 0x2908, 0x2048, 0xa906, 0x711a, 0x0804, 0x76df, 0x7014, - 0x2048, 0x7007, 0x0001, 0xa8b4, 0x9005, 0x1128, 0xa8b8, 0xa9bc, - 0x9105, 0x0108, 0x00b9, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, - 0x0904, 0x799d, 0x0804, 0x7788, 0x773e, 0x7742, 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, 0x1833, 0x210c, 0x81ff, 0x1178, 0x080c, 0x5eab, 0x1108, - 0x0005, 0x080c, 0x6c6b, 0x0126, 0x2091, 0x8000, 0x080c, 0xc044, - 0x080c, 0x6a22, 0x012e, 0x0ca0, 0x080c, 0xc452, 0x1d70, 0x2001, - 0x0028, 0x900e, 0x0c70, 0x0419, 0x11d8, 0xa888, 0x9005, 0x01e0, - 0xa883, 0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, 0x5fc3, 0x1138, - 0x0005, 0x9006, 0xa87a, 0x080c, 0x5f3b, 0x1108, 0x0005, 0x0126, - 0x2091, 0x8000, 0xa87a, 0xa982, 0x080c, 0x6a22, 0x012e, 0x0cb0, - 0x2001, 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, 0x0c80, 0x00c6, - 0x2061, 0x1800, 0x60cc, 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, 0x63a3, 0x11b8, 0x0066, 0xae80, - 0x080c, 0x64b3, 0x006e, 0x0088, 0x0046, 0x2011, 0x180c, 0x2224, - 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x63a3, 0x1110, 0x080c, - 0x65b3, 0x8108, 0x1f04, 0x780c, 0x00ce, 0xa87c, 0xd084, 0x1120, - 0x080c, 0x1069, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6a22, 0x012e, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x080c, 0x66c5, 0x0580, 0x2061, 0x1a4c, 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, 0x7a66, 0x012e, 0x0804, 0x7a60, 0x012e, - 0x0804, 0x7a5a, 0x012e, 0x0804, 0x7a5d, 0x0126, 0x2091, 0x8000, - 0x7007, 0x0001, 0x080c, 0x66c5, 0x05e0, 0x2061, 0x1a4c, 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, 0x7a66, 0x012e, 0x0804, - 0x7a63, 0x012e, 0x0804, 0x7a60, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x2061, 0x1a4c, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, - 0x0220, 0x630a, 0x012e, 0x0804, 0x7a74, 0x012e, 0x0804, 0x7a63, - 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0xa87c, - 0xd0ac, 0x0148, 0x00c6, 0x2061, 0x1a4c, 0x6000, 0x9084, 0xfcff, - 0x6002, 0x00ce, 0x0440, 0xa888, 0x9005, 0x05d8, 0xa88c, 0x9065, - 0x0598, 0x2001, 0x1833, 0x2004, 0x9005, 0x0118, 0x080c, 0xa01c, - 0x0068, 0x6017, 0xf400, 0x605b, 0x0000, 0xa97c, 0xd1a4, 0x0110, - 0xa980, 0x615a, 0x2009, 0x0041, 0x080c, 0xa068, 0xa988, 0x918c, - 0xff00, 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, - 0x080c, 0x8450, 0x002e, 0xa87c, 0xd0c4, 0x0148, 0x2061, 0x1a4c, - 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, - 0x012e, 0x00be, 0x0804, 0x7a66, 0x00ce, 0x012e, 0x00be, 0x0804, - 0x7a60, 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, 0x63a3, 0x1968, 0xb800, 0xc0e4, - 0xb802, 0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, 0x0024, 0x2001, - 0x1960, 0x2004, 0x601a, 0x0804, 0x78fb, 0xa88c, 0x9065, 0x0960, - 0x00e6, 0xa890, 0x9075, 0x2001, 0x1833, 0x2004, 0x9005, 0x0150, - 0x080c, 0xa01c, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xa01c, 0x00ee, - 0x0804, 0x78fb, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, - 0x003a, 0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, 0xa8a4, 0x602e, - 0xa8a8, 0x6016, 0x6003, 0x0001, 0x080c, 0x85f8, 0x080c, 0x8b8f, - 0x00ee, 0x0804, 0x78fb, 0x2061, 0x1a4c, 0x6000, 0xd084, 0x0190, - 0xd08c, 0x1904, 0x7a74, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, - 0x0220, 0x6206, 0x012e, 0x0804, 0x7a74, 0x012e, 0xa883, 0x0016, - 0x0804, 0x7a6d, 0xa883, 0x0007, 0x0804, 0x7a6d, 0xa864, 0x8007, - 0x9084, 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, - 0x0005, 0x080c, 0x75d8, 0x0040, 0x7007, 0x0003, 0x7012, 0x2900, - 0x7016, 0x701a, 0x704b, 0x799d, 0x0005, 0x00b6, 0x00e6, 0x0126, - 0x2091, 0x8000, 0x903e, 0x2061, 0x1800, 0x61cc, 0x81ff, 0x1904, - 0x7a1f, 0x6130, 0xd194, 0x1904, 0x7a49, 0xa878, 0x2070, 0x9e82, - 0x1cd0, 0x0a04, 0x7a13, 0x6064, 0x9e02, 0x1a04, 0x7a13, 0x7120, - 0x9186, 0x0006, 0x1904, 0x7a05, 0x7010, 0x905d, 0x0904, 0x7a1f, - 0xb800, 0xd0e4, 0x1904, 0x7a43, 0x2061, 0x1a4c, 0x6100, 0x9184, - 0x0301, 0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, 0x1904, 0x7a4c, - 0xa883, 0x0000, 0xa803, 0x0000, 0x2908, 0x7014, 0x9005, 0x1198, - 0x7116, 0xa87c, 0xd0f4, 0x1904, 0x7a4f, 0x080c, 0x54db, 0xd09c, - 0x1118, 0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, 0x8370, 0x012e, - 0x00ee, 0x00be, 0x0005, 0x2048, 0xa800, 0x9005, 0x1de0, 0xa902, - 0x2148, 0xa87c, 0xd0f4, 0x1904, 0x7a4f, 0x012e, 0x00ee, 0x00be, - 0x0005, 0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, 0x0804, 0x7a6d, - 0xd184, 0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, 0x080c, 0x63a3, - 0x15d0, 0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, - 0xa883, 0x0002, 0x0490, 0xa883, 0x0008, 0x0478, 0xa883, 0x000e, - 0x0460, 0xa883, 0x0017, 0x0448, 0xa883, 0x0035, 0x0430, 0x080c, - 0x54df, 0xd0fc, 0x01e8, 0xa878, 0x2070, 0x9e82, 0x1cd0, 0x02c0, - 0x6064, 0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, - 0x905d, 0x0170, 0xb800, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, - 0x9086, 0x0007, 0x1904, 0x79a9, 0x7003, 0x0002, 0x0804, 0x79a9, - 0xa883, 0x0028, 0x0010, 0xa883, 0x0029, 0x012e, 0x00ee, 0x00be, - 0x0420, 0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, 0x0cb0, 0x2e60, - 0x2019, 0x0002, 0x601b, 0x0014, 0x080c, 0xd38f, 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, 0x6a22, 0x012e, 0x0005, 0x080c, 0x1069, 0x0005, 0x00d6, - 0x080c, 0x8367, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, 0x908c, 0x0780, - 0x190c, 0x7b08, 0xd09c, 0x11a8, 0x2071, 0x1800, 0x70bc, 0x90ea, - 0x0040, 0x0278, 0x8001, 0x70be, 0x702c, 0x2048, 0xa800, 0x702e, - 0x9006, 0xa802, 0xa806, 0x2071, 0x0040, 0x2900, 0x7022, 0x702c, - 0x0c28, 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, - 0x190c, 0x7b08, 0x000e, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, - 0x0016, 0x00b6, 0x7007, 0x0001, 0xaa74, 0x9282, 0x0004, 0x1a04, - 0x7af9, 0xa97c, 0x9188, 0x1000, 0x2104, 0x905d, 0xb804, 0xd284, - 0x0140, 0x05e8, 0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, - 0x04b0, 0x2b10, 0x080c, 0x9f94, 0x1118, 0x080c, 0xa03b, 0x05a8, - 0x6212, 0xa874, 0x0002, 0x7ad7, 0x7adc, 0x7adf, 0x7ae5, 0x2019, - 0x0002, 0x080c, 0xd7af, 0x0060, 0x080c, 0xd746, 0x0048, 0x2019, - 0x0002, 0xa980, 0x080c, 0xd761, 0x0018, 0xa980, 0x080c, 0xd746, - 0x080c, 0x9fea, 0xa887, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6a22, 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, 0x7b0a, 0x0006, 0x0016, 0x2001, 0x8003, - 0x0006, 0x0804, 0x0dff, 0x2001, 0x1833, 0x2004, 0x9005, 0x0005, - 0x0005, 0x00f6, 0x2079, 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, - 0xc1dc, 0x2102, 0x2009, 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, - 0x150f, 0x00fe, 0x0005, 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, - 0x0300, 0x00fe, 0x0005, 0x781c, 0xd08c, 0x0904, 0x7b8a, 0x68bc, - 0x90aa, 0x0005, 0x0a04, 0x8166, 0x7d44, 0x7c40, 0x9584, 0x00f6, - 0x1510, 0x9484, 0x7000, 0x0140, 0x908a, 0x2000, 0x1260, 0x9584, - 0x0700, 0x8007, 0x0804, 0x7b91, 0x7000, 0x9084, 0xff00, 0x9086, - 0x8100, 0x0da8, 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, - 0xff00, 0x9086, 0x8100, 0x11c0, 0x080c, 0xdbb3, 0x080c, 0x809b, - 0x7817, 0x0140, 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x80f9, - 0x19c0, 0xd5a4, 0x0148, 0x0046, 0x0056, 0x080c, 0x7bec, 0x080c, - 0x2165, 0x005e, 0x004e, 0x0020, 0x080c, 0xdbb3, 0x7817, 0x0140, - 0x080c, 0x717e, 0x0168, 0x2001, 0x0111, 0x2004, 0xd08c, 0x0140, - 0x688f, 0x0000, 0x2001, 0x0110, 0x2003, 0x0008, 0x2003, 0x0000, - 0x080c, 0x7bcd, 0x2001, 0x19cb, 0x2004, 0x9005, 0x090c, 0x8b8f, - 0x0005, 0x0002, 0x7ba3, 0x7ea3, 0x7b9a, 0x7b9a, 0x7b9a, 0x7b9a, - 0x7b9a, 0x7b9a, 0x7817, 0x0140, 0x2001, 0x19cb, 0x2004, 0x9005, - 0x090c, 0x8b8f, 0x0005, 0x7000, 0x908c, 0xff00, 0x9194, 0xf000, - 0x810f, 0x9484, 0x0fff, 0x688e, 0x9286, 0x2000, 0x1150, 0x6800, - 0x9086, 0x0001, 0x1118, 0x080c, 0x5545, 0x0070, 0x080c, 0x7c0c, - 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, 0x7ddb, 0x0028, 0x9286, - 0x8000, 0x1110, 0x080c, 0x7fc2, 0x7817, 0x0140, 0x2001, 0x19cb, - 0x2004, 0x9005, 0x090c, 0x8b8f, 0x0005, 0x2001, 0x1810, 0x2004, - 0xd08c, 0x0178, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1148, - 0x0026, 0x0036, 0x2011, 0x8048, 0x2518, 0x080c, 0x4a17, 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, 0x4a17, 0x002e, 0x00fe, - 0x005e, 0x004e, 0x003e, 0x0005, 0x00b6, 0x00c6, 0x7010, 0x9084, - 0xff00, 0x8007, 0x9096, 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, - 0x7dac, 0x9186, 0x0023, 0x15c0, 0x080c, 0x8060, 0x0904, 0x7dac, - 0x6120, 0x9186, 0x0001, 0x0150, 0x9186, 0x0004, 0x0138, 0x9186, - 0x0008, 0x0120, 0x9186, 0x000a, 0x1904, 0x7dac, 0x7124, 0x610a, - 0x7030, 0x908e, 0x0200, 0x1130, 0x2009, 0x0015, 0x080c, 0xa068, - 0x0804, 0x7dac, 0x908e, 0x0214, 0x0118, 0x908e, 0x0210, 0x1130, - 0x2009, 0x0015, 0x080c, 0xa068, 0x0804, 0x7dac, 0x908e, 0x0100, - 0x1904, 0x7dac, 0x7034, 0x9005, 0x1904, 0x7dac, 0x2009, 0x0016, - 0x080c, 0xa068, 0x0804, 0x7dac, 0x9186, 0x0022, 0x1904, 0x7dac, - 0x7030, 0x908e, 0x0300, 0x1580, 0x68d8, 0xd0a4, 0x0528, 0xc0b5, - 0x68da, 0x7100, 0x918c, 0x00ff, 0x697a, 0x7004, 0x687e, 0x00f6, - 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0x9084, 0x00ff, 0x0016, - 0x2008, 0x080c, 0x26b6, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, - 0x080c, 0x266d, 0x695a, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, - 0x2071, 0x1800, 0x70b2, 0x00ee, 0x7034, 0x9005, 0x1904, 0x7dac, - 0x2009, 0x0017, 0x0804, 0x7d5c, 0x908e, 0x0400, 0x1190, 0x7034, - 0x9005, 0x1904, 0x7dac, 0x080c, 0x717e, 0x0120, 0x2009, 0x001d, - 0x0804, 0x7d5c, 0x68d8, 0xc0a5, 0x68da, 0x2009, 0x0030, 0x0804, - 0x7d5c, 0x908e, 0x0500, 0x1140, 0x7034, 0x9005, 0x1904, 0x7dac, - 0x2009, 0x0018, 0x0804, 0x7d5c, 0x908e, 0x2010, 0x1120, 0x2009, - 0x0019, 0x0804, 0x7d5c, 0x908e, 0x2110, 0x1120, 0x2009, 0x001a, - 0x0804, 0x7d5c, 0x908e, 0x5200, 0x1140, 0x7034, 0x9005, 0x1904, - 0x7dac, 0x2009, 0x001b, 0x0804, 0x7d5c, 0x908e, 0x5000, 0x1140, - 0x7034, 0x9005, 0x1904, 0x7dac, 0x2009, 0x001c, 0x0804, 0x7d5c, - 0x908e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x7d5c, 0x908e, - 0x1200, 0x1140, 0x7034, 0x9005, 0x1904, 0x7dac, 0x2009, 0x0024, - 0x0804, 0x7d5c, 0x908c, 0xff00, 0x918e, 0x2400, 0x1170, 0x2009, - 0x002d, 0x2001, 0x1810, 0x2004, 0xd09c, 0x0904, 0x7d5c, 0x080c, - 0xcb61, 0x1904, 0x7dac, 0x0804, 0x7d5a, 0x908c, 0xff00, 0x918e, - 0x5300, 0x1120, 0x2009, 0x002a, 0x0804, 0x7d5c, 0x908e, 0x0f00, - 0x1120, 0x2009, 0x0020, 0x0804, 0x7d5c, 0x908e, 0x6104, 0x1528, - 0x2029, 0x0205, 0x2011, 0x026d, 0x8208, 0x2204, 0x9082, 0x0004, - 0x8004, 0x8004, 0x20a8, 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, - 0x2124, 0x080c, 0x4a17, 0x004e, 0x8108, 0x0f04, 0x7d28, 0x9186, - 0x0280, 0x1d88, 0x2504, 0x8000, 0x202a, 0x2009, 0x0260, 0x0c58, - 0x202b, 0x0000, 0x2009, 0x0023, 0x0478, 0x908e, 0x6000, 0x1118, - 0x2009, 0x003f, 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, 0x266d, 0x1904, 0x7daf, 0x080c, 0x6343, - 0x1904, 0x7daf, 0xbe12, 0xbd16, 0x001e, 0x0016, 0x080c, 0x717e, - 0x01c0, 0x68d8, 0xd08c, 0x1148, 0x7000, 0x9084, 0x00ff, 0x1188, - 0x7004, 0x9084, 0xff00, 0x1168, 0x0040, 0x6878, 0x9606, 0x1148, - 0x687c, 0x9506, 0x9084, 0xff00, 0x1120, 0x9584, 0x00ff, 0xb8b2, - 0x0080, 0xb8b0, 0x9005, 0x1168, 0x9186, 0x0046, 0x1150, 0x6878, - 0x9606, 0x1138, 0x687c, 0x9506, 0x9084, 0xff00, 0x1110, 0x001e, - 0x0098, 0x080c, 0x9f94, 0x01a8, 0x2b08, 0x6112, 0x6023, 0x0004, - 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, 0x1110, 0x6023, 0x000a, - 0x0016, 0x001e, 0x080c, 0xa068, 0x00ce, 0x00be, 0x0005, 0x001e, - 0x0cd8, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, - 0x080c, 0x4a17, 0x080c, 0xa03b, 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, 0x8640, 0x08a0, 0x080c, 0x8185, 0x1158, 0x080c, 0x31b8, - 0x1140, 0x7010, 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, - 0x0009, 0x0005, 0x00b6, 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, - 0x810f, 0x9186, 0x0033, 0x11e8, 0x080c, 0x8060, 0x0904, 0x7e3b, - 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, - 0x15d0, 0x2009, 0x0015, 0x080c, 0xa068, 0x04a8, 0x908e, 0x0100, - 0x1590, 0x7034, 0x9005, 0x1578, 0x2009, 0x0016, 0x080c, 0xa068, - 0x0450, 0x9186, 0x0032, 0x1538, 0x7030, 0x908e, 0x1400, 0x1518, - 0x2009, 0x0038, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, - 0x080c, 0x266d, 0x11b8, 0x080c, 0x6343, 0x11a0, 0xbe12, 0xbd16, - 0x080c, 0x9f94, 0x0178, 0x2b08, 0x6112, 0x080c, 0xc1ca, 0x6023, - 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0xa068, 0x080c, 0x8b8f, - 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, 0x7e9d, 0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, - 0x7e9d, 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04f0, 0x2011, - 0x0000, 0x2019, 0x1836, 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, 0x7e72, 0x82ff, 0x1118, - 0x9085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, - 0x004e, 0x00be, 0x0005, 0x2001, 0x1836, 0x200c, 0x9184, 0x0080, - 0x0110, 0xd18c, 0x0138, 0x7000, 0x908c, 0xff00, 0x810f, 0x9184, - 0x000f, 0x004a, 0x7817, 0x0140, 0x2001, 0x19cb, 0x2004, 0x9005, - 0x090c, 0x8b8f, 0x0005, 0x7ecb, 0x7ecb, 0x7ecb, 0x8072, 0x7ecb, - 0x7ed4, 0x7eff, 0x7f8d, 0x7ecb, 0x7ecb, 0x7ecb, 0x7ecb, 0x7ecb, - 0x7ecb, 0x7ecb, 0x7ecb, 0x7817, 0x0140, 0x2001, 0x19cb, 0x2004, - 0x9005, 0x090c, 0x8b8f, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, - 0x7120, 0x2160, 0x9c8c, 0x0007, 0x11c0, 0x9c8a, 0x1cd0, 0x02a8, - 0x6864, 0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, - 0xb910, 0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, - 0x610a, 0x2009, 0x0046, 0x080c, 0xa068, 0x7817, 0x0140, 0x2001, - 0x19cb, 0x2004, 0x9005, 0x090c, 0x8b8f, 0x00be, 0x0005, 0x00b6, - 0x00c6, 0x9484, 0x0fff, 0x0904, 0x7f63, 0x7110, 0xd1bc, 0x1904, - 0x7f63, 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, - 0xff00, 0x15b0, 0x81ff, 0x15a0, 0x9080, 0x31f3, 0x200d, 0x918c, - 0xff00, 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, 0x7f63, 0x080c, - 0x6343, 0x1904, 0x7f63, 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15d8, - 0xba04, 0x9294, 0xff00, 0x9286, 0x0600, 0x11a0, 0x080c, 0x9f94, - 0x05e8, 0x2b08, 0x7028, 0x6046, 0x702c, 0x604a, 0x6112, 0x6023, - 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, 0x2009, 0x0044, 0x080c, - 0xcdd7, 0x0408, 0x080c, 0x66c9, 0x1138, 0xb807, 0x0606, 0x0c30, - 0x190c, 0x7e3f, 0x11c0, 0x0898, 0x080c, 0x9f94, 0x2b08, 0x0198, - 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x9286, 0x0400, 0x1118, - 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, - 0x8640, 0x080c, 0x8b8f, 0x7817, 0x0140, 0x2001, 0x19cb, 0x2004, - 0x9005, 0x090c, 0x8b8f, 0x00ce, 0x00be, 0x0005, 0x2001, 0x180e, - 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4a17, 0x080c, - 0xa03b, 0x0d48, 0x2b08, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, - 0x7130, 0x6156, 0x6017, 0xf300, 0x6003, 0x0001, 0x6007, 0x0041, - 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x08b0, 0x00b6, 0x7110, 0xd1bc, - 0x01e8, 0x7020, 0x2060, 0x9c84, 0x0007, 0x11c0, 0x9c82, 0x1cd0, - 0x02a8, 0x6864, 0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, - 0x2158, 0xb910, 0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, - 0x7124, 0x610a, 0x2009, 0x0045, 0x080c, 0xa068, 0x7817, 0x0140, - 0x2001, 0x19cb, 0x2004, 0x9005, 0x090c, 0x8b8f, 0x00be, 0x0005, - 0x6120, 0x9186, 0x0002, 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, - 0x0001, 0x0005, 0x080c, 0x8185, 0x1180, 0x080c, 0x31b8, 0x1168, - 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, 0x0000, 0x1130, 0x9184, - 0x000f, 0x908a, 0x0006, 0x1208, 0x000b, 0x0005, 0x7fdc, 0x7fdd, - 0x7fdc, 0x7fdc, 0x8042, 0x8051, 0x0005, 0x00b6, 0x700c, 0x7108, - 0x080c, 0x266d, 0x1904, 0x8040, 0x080c, 0x6343, 0x1904, 0x8040, - 0xbe12, 0xbd16, 0x7110, 0xd1bc, 0x0540, 0x702c, 0xd084, 0x1120, - 0xb800, 0xd0bc, 0x1904, 0x8040, 0x080c, 0x66c9, 0x0148, 0x9086, - 0x0004, 0x0130, 0x080c, 0x66d1, 0x0118, 0x9086, 0x0004, 0x1588, - 0x00c6, 0x080c, 0x8060, 0x00ce, 0x05d8, 0x080c, 0x9f94, 0x2b08, - 0x05b8, 0x6112, 0x080c, 0xc1ca, 0x6023, 0x0002, 0x7120, 0x610a, - 0x2009, 0x0088, 0x080c, 0xa068, 0x0458, 0x080c, 0x66c9, 0x0148, - 0x9086, 0x0004, 0x0130, 0x080c, 0x66d1, 0x0118, 0x9086, 0x0004, - 0x1180, 0x080c, 0x9f94, 0x2b08, 0x01d8, 0x6112, 0x080c, 0xc1ca, - 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xa068, - 0x0078, 0x080c, 0x9f94, 0x2b08, 0x0158, 0x6112, 0x080c, 0xc1ca, - 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0xa068, - 0x00be, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, - 0x7fb8, 0x1130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0xa068, - 0x0005, 0x7110, 0xd1bc, 0x0158, 0x0059, 0x0148, 0x080c, 0x7fb8, - 0x1130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0xa068, 0x0005, - 0x7020, 0x2060, 0x9c84, 0x0007, 0x1158, 0x9c82, 0x1cd0, 0x0240, - 0x2001, 0x1819, 0x2004, 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, - 0x9006, 0x0ce8, 0x00b6, 0x7110, 0xd1bc, 0x11d8, 0x7024, 0x2060, - 0x9c84, 0x0007, 0x11b0, 0x9c82, 0x1cd0, 0x0298, 0x6864, 0x9c02, - 0x1280, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, - 0x1140, 0x700c, 0xb914, 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, - 0xa068, 0x7817, 0x0140, 0x2001, 0x19cb, 0x2004, 0x9005, 0x090c, - 0x8b8f, 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, 0x9f94, 0x05b8, 0x0066, - 0x00c6, 0x0046, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, - 0x266d, 0x15a0, 0x080c, 0x6343, 0x1588, 0xbe12, 0xbd16, 0x2b00, - 0x004e, 0x00ce, 0x6012, 0x080c, 0xc1ca, 0x080c, 0x1037, 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, 0x8640, 0x080c, 0x8b8f, 0x00fe, 0x009e, - 0x00ce, 0x0005, 0x080c, 0x9fea, 0x006e, 0x0cc0, 0x004e, 0x00ce, - 0x0cc8, 0x00c6, 0x7000, 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, - 0x9086, 0x2000, 0x1904, 0x8150, 0x9186, 0x0022, 0x15f0, 0x2001, - 0x0111, 0x2004, 0x9005, 0x1904, 0x8152, 0x7030, 0x908e, 0x0400, - 0x0904, 0x8152, 0x908e, 0x6000, 0x05e8, 0x908e, 0x5400, 0x05d0, - 0x908e, 0x0300, 0x11d8, 0x2009, 0x1836, 0x210c, 0xd18c, 0x1590, - 0xd1a4, 0x1580, 0x080c, 0x6687, 0x0588, 0x68ac, 0x9084, 0x00ff, - 0x7100, 0x918c, 0x00ff, 0x9106, 0x1518, 0x687c, 0x69ac, 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, 0x8060, 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, - 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, 0x7030, 0x908e, - 0x0300, 0x0118, 0x908e, 0x5200, 0x1d98, 0x2001, 0x1836, 0x2004, - 0x9084, 0x0009, 0x9086, 0x0008, 0x0d68, 0x0c50, 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, 0x1836, - 0x200c, 0x9184, 0x0080, 0x0118, 0xd18c, 0x0118, 0x9006, 0x001e, - 0x0005, 0x9085, 0x0001, 0x0cd8, 0x2071, 0x19d5, 0x7003, 0x0003, - 0x700f, 0x0361, 0x9006, 0x701a, 0x707a, 0x7012, 0x7017, 0x1cd0, - 0x7007, 0x0000, 0x7026, 0x702b, 0x9630, 0x7032, 0x7037, 0x9698, - 0x7047, 0xffff, 0x704a, 0x704f, 0x536d, 0x7052, 0x7063, 0x82f4, - 0x080c, 0x1050, 0x090c, 0x0df6, 0x2900, 0x7042, 0xa867, 0x0003, - 0xa86f, 0x0100, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x19d5, 0x1d04, - 0x8248, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1510, 0x2001, - 0x187d, 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, - 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0df6, 0x700f, - 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x080c, 0x8339, - 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, 0x9716, - 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, 0x8270, 0x8271, 0x828d, 0x00e6, 0x2071, 0x19d5, - 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, - 0x0005, 0x00e6, 0x0006, 0x2071, 0x19d5, 0x701c, 0x9206, 0x1120, - 0x701a, 0x701e, 0x707a, 0x707e, 0x000e, 0x00ee, 0x0005, 0x00e6, - 0x2071, 0x19d5, 0xb888, 0x9102, 0x0208, 0xb98a, 0x00ee, 0x0005, - 0x0005, 0x00b6, 0x7110, 0x080c, 0x63a3, 0x1168, 0xb888, 0x8001, - 0x0250, 0xb88a, 0x1140, 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, - 0x8b8f, 0x001e, 0x012e, 0x8108, 0x9182, 0x0800, 0x0218, 0x900e, - 0x7007, 0x0002, 0x7112, 0x00be, 0x0005, 0x7014, 0x2060, 0x0126, - 0x2091, 0x8000, 0x6040, 0x9005, 0x0128, 0x8001, 0x6042, 0x1110, - 0x080c, 0xc05b, 0x6018, 0x9005, 0x0528, 0x8001, 0x601a, 0x1510, - 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x11c8, 0x080c, - 0xbd4e, 0x01b0, 0x6014, 0x2048, 0xa884, 0x908a, 0x199a, 0x0280, - 0x9082, 0x1999, 0xa886, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, - 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, 0xd0e4, 0x0110, - 0x080c, 0xba50, 0x012e, 0x9c88, 0x0018, 0x7116, 0x2001, 0x1819, - 0x2004, 0x9102, 0x0220, 0x7017, 0x1cd0, 0x7007, 0x0000, 0x0005, - 0x00e6, 0x2071, 0x19d5, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, - 0x0005, 0x2001, 0x19de, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, - 0x19d5, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x19e1, - 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x19d5, 0x711a, 0x721e, - 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, 0x0026, 0x705c, 0x8000, - 0x705e, 0x2001, 0x19e5, 0x2044, 0xa06c, 0x9086, 0x0000, 0x0150, - 0x7070, 0xa09a, 0x706c, 0xa096, 0x7068, 0xa092, 0x7064, 0xa08e, - 0x080c, 0x1134, 0x002e, 0x008e, 0x0005, 0x0006, 0x0016, 0x0096, - 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x080c, - 0x81bd, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, - 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x19d5, 0x717a, - 0x727e, 0x7077, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, - 0x19d5, 0x707c, 0x9206, 0x1110, 0x707a, 0x707e, 0x000e, 0x00ee, - 0x0005, 0x2069, 0x1800, 0x69e4, 0xd1e4, 0x1518, 0x0026, 0xd1ec, - 0x0140, 0x6a50, 0x6870, 0x9202, 0x0288, 0x8117, 0x9294, 0x00c0, - 0x0088, 0x9184, 0x0007, 0x01a0, 0x8109, 0x9184, 0x0007, 0x0110, - 0x69e6, 0x0070, 0x8107, 0x9084, 0x0007, 0x910d, 0x8107, 0x9106, - 0x9094, 0x00c0, 0x9184, 0xff3f, 0x9205, 0x68e6, 0x080c, 0x0f17, - 0x002e, 0x0005, 0x00c6, 0x2061, 0x1a4c, 0x00ce, 0x0005, 0x9184, - 0x000f, 0x8003, 0x8003, 0x8003, 0x9080, 0x1a4c, 0x2060, 0x0005, - 0xa884, 0x908a, 0x199a, 0x1638, 0x9005, 0x1150, 0x00c6, 0x2061, - 0x1a4c, 0x6014, 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, 0x0018, - 0x908e, 0xffff, 0x01b0, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, - 0xa87c, 0x908c, 0x00c0, 0x918e, 0x00c0, 0x0904, 0x83fa, 0xd0b4, - 0x1168, 0xd0bc, 0x1904, 0x83d3, 0x2009, 0x0006, 0x080c, 0x8427, - 0x0005, 0x900e, 0x0c60, 0x2001, 0x1999, 0x08b0, 0xd0fc, 0x0160, - 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x8421, 0x908c, - 0x2020, 0x918e, 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11e8, 0x2009, - 0x187d, 0x2104, 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, - 0x0804, 0xa068, 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, - 0xa068, 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, 0x8421, 0x908c, 0x2020, 0x918e, 0x2020, - 0x0170, 0x0076, 0x00f6, 0x2c78, 0x080c, 0x1651, 0x00fe, 0x007e, - 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0xa068, 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, 0xa068, 0x0005, 0x00b9, 0x0ce8, 0x87ff, - 0x1dd8, 0x2009, 0x0043, 0x080c, 0xa068, 0x0cb0, 0x6110, 0x00b6, - 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6124, 0xc1cd, 0x6126, - 0x0c00, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x0096, - 0x080c, 0xbd4e, 0x0518, 0x6014, 0x2048, 0xa982, 0xa800, 0x6016, - 0x9186, 0x0001, 0x1188, 0xa97c, 0x918c, 0x8100, 0x918e, 0x8100, - 0x1158, 0x00c6, 0x2061, 0x1a4c, 0x6200, 0xd28c, 0x1120, 0x6204, - 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x6861, 0x6014, 0x904d, - 0x0076, 0x2039, 0x0000, 0x190c, 0x8370, 0x007e, 0x009e, 0x0005, - 0x0156, 0x00c6, 0x2061, 0x1a4c, 0x6000, 0x81ff, 0x0110, 0x9205, - 0x0008, 0x9204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, - 0x1138, 0x6808, 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, 0x0001, - 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x0046, 0x20a9, 0x0010, - 0x9006, 0x8004, 0x8086, 0x818e, 0x1208, 0x9200, 0x1f04, 0x8472, - 0x8086, 0x818e, 0x004e, 0x003e, 0x012e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, 0x01c8, 0x911a, - 0x12b8, 0x8213, 0x818d, 0x0228, 0x911a, 0x1220, 0x1f04, 0x8489, - 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, 0x8489, 0x0006, 0x3200, - 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, 0x007e, 0x012e, 0x0005, - 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, - 0x2079, 0x19c2, 0x012e, 0x00d6, 0x2069, 0x19c2, 0x6803, 0x0005, - 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, - 0x9df2, 0x0401, 0x080c, 0x9ddd, 0x00e9, 0x080c, 0x9de0, 0x00d1, - 0x080c, 0x9de3, 0x00b9, 0x080c, 0x9de6, 0x00a1, 0x080c, 0x9de9, - 0x0089, 0x080c, 0x9dec, 0x0071, 0x080c, 0x9def, 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, 0x84f3, 0x8517, 0x8558, 0x84f9, 0x8517, 0x84f3, 0x84f1, - 0x84f1, 0x080c, 0x0df6, 0x080c, 0x82d9, 0x080c, 0x8b8f, 0x00ce, - 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x5c98, - 0x080c, 0x8259, 0x7828, 0x9092, 0x00c8, 0x1228, 0x8000, 0x782a, - 0x080c, 0x5cd8, 0x0c88, 0x62c0, 0x080c, 0x9df6, 0x080c, 0x5c98, - 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c28, 0x080c, - 0x82d9, 0x6220, 0xd2a4, 0x0170, 0xd2cc, 0x0160, 0x782b, 0x0000, - 0x7824, 0x9065, 0x090c, 0x0df6, 0x2009, 0x0013, 0x080c, 0xa068, - 0x00ce, 0x0005, 0x00c6, 0x7824, 0x9065, 0x090c, 0x0df6, 0x7828, - 0x9092, 0xc350, 0x12c0, 0x8000, 0x782a, 0x00ce, 0x080c, 0x29e9, - 0x0278, 0x00c6, 0x7924, 0x2160, 0x6010, 0x906d, 0x090c, 0x0df6, - 0x7807, 0x0000, 0x7827, 0x0000, 0x00ce, 0x080c, 0x8b8f, 0x0c00, - 0x080c, 0x95f6, 0x08e8, 0x2011, 0x0130, 0x2214, 0x080c, 0x9df6, - 0x080c, 0xdbf0, 0x2009, 0x0014, 0x080c, 0xa068, 0x00ce, 0x0880, - 0x2001, 0x19de, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, - 0x0000, 0x7824, 0x9065, 0x090c, 0x0df6, 0x2009, 0x0013, 0x080c, - 0xa0ba, 0x00ce, 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x7824, 0x9005, - 0x090c, 0x0df6, 0x7828, 0x9092, 0xc350, 0x1648, 0x8000, 0x782a, - 0x00de, 0x00ce, 0x00be, 0x080c, 0x29e9, 0x02f0, 0x00b6, 0x00c6, - 0x00d6, 0x781c, 0x905d, 0x090c, 0x0df6, 0xb800, 0xc0dc, 0xb802, - 0x7924, 0x2160, 0x080c, 0x9fea, 0xb93c, 0x81ff, 0x090c, 0x0df6, - 0x8109, 0xb93e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, - 0x00be, 0x080c, 0x8b8f, 0x0868, 0x080c, 0x95f6, 0x0850, 0x2011, - 0x0130, 0x2214, 0x080c, 0x9df6, 0x080c, 0xdbf0, 0x7824, 0x9065, - 0x2009, 0x0014, 0x080c, 0xa068, 0x00de, 0x00ce, 0x00be, 0x0804, - 0x8569, 0x00c6, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x190c, 0x1d00, - 0x6024, 0x6027, 0x0002, 0xd0f4, 0x1580, 0x62c8, 0x60c4, 0x9205, - 0x1170, 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, 0x080c, 0xa068, - 0x00ce, 0x0005, 0x2011, 0x19e1, 0x2013, 0x0000, 0x0cc8, 0x793c, - 0x81ff, 0x0dc0, 0x7944, 0x9192, 0x7530, 0x12f0, 0x8108, 0x7946, - 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, - 0x9084, 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, 0x6014, 0x9084, - 0x1984, 0x9085, 0x0016, 0x6016, 0x08d8, 0x793c, 0x2160, 0x2009, - 0x004a, 0x080c, 0xa068, 0x08a0, 0x7848, 0xc085, 0x784a, 0x0880, - 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, - 0x2c08, 0x2061, 0x19c2, 0x6020, 0x8000, 0x6022, 0x6010, 0x9005, - 0x0148, 0x9080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, - 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x19c2, - 0xb800, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0x9086, 0x0001, - 0x1110, 0x2b00, 0x681e, 0x00de, 0x0804, 0x8b8f, 0x00de, 0x0005, - 0xc0d5, 0xb802, 0x6818, 0x9005, 0x0168, 0xb856, 0xb85b, 0x0000, - 0x0086, 0x0006, 0x2b00, 0x681a, 0x008e, 0xa05a, 0x008e, 0x2069, - 0x19c2, 0x0c08, 0xb856, 0xb85a, 0x2b00, 0x681a, 0x681e, 0x08d8, - 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, - 0x2c08, 0x2061, 0x19c2, 0x6020, 0x8000, 0x6022, 0x6008, 0x9005, - 0x0148, 0x9080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, - 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, - 0x2c08, 0x2061, 0x19c2, 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, - 0x19c2, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, - 0x86ec, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x86e7, 0x87ff, - 0x0120, 0x6054, 0x9106, 0x1904, 0x86e7, 0x703c, 0x9c06, 0x1178, - 0x0036, 0x2019, 0x0001, 0x080c, 0x98b1, 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, 0xbd4e, 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, - 0x0003, 0x15b8, 0x6004, 0x9086, 0x0040, 0x090c, 0x9a7f, 0xa867, - 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, - 0xc044, 0x080c, 0xdae1, 0x080c, 0x6a22, 0x007e, 0x003e, 0x001e, - 0x080c, 0xbf39, 0x080c, 0xa01c, 0x00ce, 0x0804, 0x8686, 0x2c78, - 0x600c, 0x2060, 0x0804, 0x8686, 0x85ff, 0x0120, 0x0036, 0x080c, - 0x8c6c, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, - 0x006e, 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, - 0x080c, 0xdae1, 0x080c, 0xd7e2, 0x007e, 0x003e, 0x001e, 0x0890, - 0x6020, 0x9086, 0x000a, 0x0904, 0x86d1, 0x0804, 0x86ca, 0x0006, - 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091, - 0x8000, 0x2079, 0x19c2, 0x7838, 0x9065, 0x0904, 0x876c, 0x600c, - 0x0006, 0x600f, 0x0000, 0x783c, 0x9c06, 0x1168, 0x0036, 0x2019, - 0x0001, 0x080c, 0x98b1, 0x7833, 0x0000, 0x901e, 0x7b3e, 0x7b42, - 0x7b46, 0x7b4a, 0x003e, 0x080c, 0xbd4e, 0x0548, 0x6014, 0x2048, - 0x6020, 0x9086, 0x0003, 0x1590, 0x3e08, 0x918e, 0x0002, 0x1188, - 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x0140, 0x6040, 0x9005, 0x11a8, 0x2001, 0x1962, 0x2004, 0x6042, - 0x0080, 0x6004, 0x9086, 0x0040, 0x090c, 0x9a7f, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6a15, 0x080c, 0xbf39, 0x080c, - 0xa01c, 0x000e, 0x0804, 0x8724, 0x7e3a, 0x7e36, 0x012e, 0x00fe, - 0x00de, 0x00ce, 0x009e, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1118, 0x080c, 0xd7e2, 0x0c50, 0x6020, 0x9086, 0x000a, - 0x09f8, 0x08b8, 0x0016, 0x0026, 0x0086, 0x9046, 0x0099, 0x080c, - 0x886d, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, - 0x19c2, 0x2091, 0x8000, 0x080c, 0x8904, 0x080c, 0x8994, 0x012e, - 0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19c2, - 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, 0x8832, 0x6010, 0x2058, - 0xb8a0, 0x9206, 0x1904, 0x882d, 0x88ff, 0x0120, 0x6054, 0x9106, - 0x1904, 0x882d, 0x7024, 0x9c06, 0x1568, 0x2069, 0x0100, 0x6820, - 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x82d9, 0x080c, 0x961a, - 0x68c3, 0x0000, 0x080c, 0x9a7f, 0x7027, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2b6f, 0x9006, 0x080c, 0x2b6f, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, - 0x0804, 0x882d, 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, 0xbd4e, - 0x01e8, 0x6020, 0x9086, 0x0003, 0x1580, 0x080c, 0xbf56, 0x1118, - 0x080c, 0xa9a7, 0x0098, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, - 0x0016, 0x0036, 0x0086, 0x080c, 0xc044, 0x080c, 0xdae1, 0x080c, - 0x6a22, 0x008e, 0x003e, 0x001e, 0x080c, 0xbf39, 0x080c, 0xa01c, - 0x080c, 0x9955, 0x00ce, 0x0804, 0x87ab, 0x2c78, 0x600c, 0x2060, - 0x0804, 0x87ab, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, - 0x00ee, 0x00fe, 0x009e, 0x00be, 0x0005, 0x6020, 0x9086, 0x0006, - 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xdae1, 0x080c, 0xd7e2, - 0x008e, 0x003e, 0x001e, 0x08d0, 0x080c, 0xa9a7, 0x6020, 0x9086, - 0x0002, 0x1160, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0904, - 0x8813, 0x9086, 0x008b, 0x0904, 0x8813, 0x0840, 0x6020, 0x9086, - 0x0005, 0x1920, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x09c8, - 0x9086, 0x008b, 0x09b0, 0x0804, 0x8826, 0x00b6, 0x00a6, 0x0096, - 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x9280, 0x1000, 0x2004, - 0x905d, 0x0904, 0x88fd, 0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, - 0x19c2, 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, 0x62d6, 0x0904, 0x88f9, 0x7624, 0x86ff, 0x0904, 0x88e8, - 0x9680, 0x0005, 0x2004, 0x9906, 0x15d8, 0x00d6, 0x2069, 0x0100, - 0x68c0, 0x9005, 0x0560, 0x080c, 0x82d9, 0x080c, 0x961a, 0x68c3, - 0x0000, 0x080c, 0x9a7f, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, - 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2b6f, - 0x9006, 0x080c, 0x2b6f, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, - 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0xb83c, 0x9005, 0x0110, - 0x8001, 0xb83e, 0x2660, 0x080c, 0xa01c, 0x00ce, 0x0048, 0x00de, - 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x88a0, - 0x89ff, 0x0158, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, - 0xc044, 0x080c, 0xdae1, 0x080c, 0x6a22, 0x080c, 0x9955, 0x0804, - 0x88a0, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, - 0x009e, 0x00ae, 0x00be, 0x0005, 0x0096, 0x0006, 0x0066, 0x00c6, - 0x00d6, 0x9036, 0x7814, 0x9065, 0x0904, 0x8967, 0x600c, 0x0006, - 0x600f, 0x0000, 0x7824, 0x9c06, 0x1580, 0x2069, 0x0100, 0x6820, - 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x82d9, 0x080c, 0x961a, - 0x68c3, 0x0000, 0x080c, 0x9a7f, 0x7827, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2b6f, 0x9006, 0x080c, 0x2b6f, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x0040, 0x080c, 0x667f, 0x1520, - 0x6003, 0x0009, 0x630a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, - 0xbd4c, 0x01b0, 0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xbf56, - 0x1118, 0x080c, 0xa9a7, 0x0060, 0x080c, 0x667f, 0x1168, 0xa867, - 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6a22, 0x080c, 0xbf39, - 0x080c, 0xa01c, 0x080c, 0x9955, 0x000e, 0x0804, 0x890b, 0x7e16, - 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, - 0x9086, 0x0006, 0x1118, 0x080c, 0xd7e2, 0x0c50, 0x080c, 0xa9a7, - 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, 0x8a14, 0xb854, 0x0006, - 0x9006, 0xb856, 0xb85a, 0xb800, 0xc0d4, 0xc0dc, 0xb802, 0x080c, - 0x62d6, 0x0904, 0x8a11, 0x7e24, 0x86ff, 0x0904, 0x8a04, 0x9680, - 0x0005, 0x2004, 0x9906, 0x1904, 0x8a04, 0x00d6, 0x2069, 0x0100, - 0x68c0, 0x9005, 0x0904, 0x89fb, 0x080c, 0x82d9, 0x080c, 0x961a, - 0x68c3, 0x0000, 0x080c, 0x9a7f, 0x7827, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2b6f, 0x9006, 0x080c, 0x2b6f, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x3e08, 0x918e, - 0x0002, 0x1168, 0xb800, 0xd0bc, 0x0150, 0x9680, 0x0010, 0x200c, - 0x81ff, 0x1518, 0x2009, 0x1962, 0x210c, 0x2102, 0x00f0, 0xb83c, - 0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x600f, 0x0000, 0x080c, - 0xa01c, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, - 0x630a, 0x00ce, 0x0804, 0x89a7, 0x89ff, 0x0138, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6a22, 0x080c, 0x9955, 0x0804, - 0x89a7, 0x000e, 0x0804, 0x899b, 0x781e, 0x781a, 0x00de, 0x00ce, - 0x00be, 0x009e, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, - 0x0066, 0xb800, 0xd0dc, 0x01a0, 0xb84c, 0x904d, 0x0188, 0xa878, - 0x9606, 0x1170, 0x2071, 0x19c2, 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, 0x961a, 0x78c3, 0x0000, 0x080c, 0x9a7f, - 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0x9384, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2b6f, 0x9006, 0x080c, 0x2b6f, - 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, - 0x9a7f, 0x003e, 0x080c, 0x62d6, 0x00c6, 0xb83c, 0x9005, 0x0110, - 0x8001, 0xb83e, 0x2660, 0x080c, 0x9fea, 0x00ce, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0xc044, 0x080c, 0x6a22, 0x080c, - 0x9955, 0x00fe, 0x0005, 0x00b6, 0x00e6, 0x00c6, 0x2011, 0x0101, - 0x2204, 0xc0c4, 0x2012, 0x2001, 0x180c, 0x2014, 0xc2e4, 0x2202, - 0x2071, 0x19c2, 0x7004, 0x9084, 0x0007, 0x0002, 0x8aa0, 0x8aa4, - 0x8ac2, 0x8aeb, 0x8b29, 0x8aa0, 0x8abb, 0x8a9e, 0x080c, 0x0df6, - 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, 0x62d6, 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, 0x8b8f, - 0x0ca8, 0x7218, 0x721e, 0x080c, 0x8b8f, 0x0c80, 0xc2ec, 0x2202, - 0x080c, 0x8c6c, 0x0c58, 0x7024, 0x9065, 0x05b8, 0x700c, 0x9c06, - 0x1160, 0x080c, 0x9955, 0x600c, 0x9015, 0x0120, 0x720e, 0x600f, - 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, 0x9c06, 0x1160, - 0x080c, 0x9955, 0x600c, 0x9015, 0x0120, 0x7216, 0x600f, 0x0000, - 0x00d0, 0x7216, 0x7212, 0x00b8, 0x6020, 0x9086, 0x0003, 0x1198, - 0x6010, 0x2058, 0x080c, 0x62d6, 0xb800, 0xc0dc, 0xb802, 0x080c, - 0x9955, 0x701c, 0x9065, 0x0138, 0xb854, 0x9015, 0x0110, 0x721e, - 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, - 0x0005, 0x7024, 0x9065, 0x0140, 0x080c, 0x9955, 0x600c, 0x9015, - 0x0158, 0x720e, 0x600f, 0x0000, 0x080c, 0x9a7f, 0x7027, 0x0000, - 0x00ce, 0x00ee, 0x00be, 0x0005, 0x720e, 0x720a, 0x0ca8, 0x00d6, - 0x2069, 0x19c2, 0x6830, 0x9084, 0x0003, 0x0002, 0x8b4c, 0x8b4e, - 0x8b72, 0x8b4a, 0x080c, 0x0df6, 0x00de, 0x0005, 0x00c6, 0x6840, - 0x9086, 0x0001, 0x01b8, 0x683c, 0x9065, 0x0130, 0x600c, 0x9015, - 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, - 0x2011, 0x19e1, 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, 0x8c6c, - 0x2001, 0x19ce, 0x2004, 0x9086, 0x0001, 0x0d58, 0x00d6, 0x2069, - 0x19c2, 0x6804, 0x9084, 0x0007, 0x0002, 0x8baf, 0x8c54, 0x8c54, - 0x8c54, 0x8c54, 0x8c56, 0x8c54, 0x8bad, 0x080c, 0x0df6, 0x6820, - 0x9005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, 0x0150, - 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x8cc3, 0x00ce, - 0x00de, 0x0005, 0x6814, 0x9065, 0x0150, 0x6807, 0x0001, 0x6826, - 0x682b, 0x0000, 0x080c, 0x8cc3, 0x00ce, 0x00de, 0x0005, 0x00b6, - 0x00e6, 0x6a1c, 0x92dd, 0x0000, 0x0904, 0x8c3e, 0xb84c, 0x900d, - 0x0118, 0xb888, 0x9005, 0x01a0, 0xb854, 0x905d, 0x0120, 0x920e, - 0x0904, 0x8c3e, 0x0028, 0x6818, 0x920e, 0x0904, 0x8c3e, 0x2058, - 0xb84c, 0x900d, 0x0d88, 0xb888, 0x9005, 0x1d70, 0x2b00, 0x681e, - 0xbb3c, 0xb838, 0x9302, 0x1e40, 0x080c, 0x9fc1, 0x0904, 0x8c3e, - 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, 0xbab0, - 0x629a, 0x2069, 0x0200, 0x2071, 0x0240, 0x080c, 0x923f, 0x2069, - 0x19c2, 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, 0x62d6, 0x080c, 0x9e16, 0x00ee, - 0x00be, 0x00ce, 0x00de, 0x0005, 0x00de, 0x0005, 0x00c6, 0x680c, - 0x9065, 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, - 0x8cc3, 0x00ce, 0x00de, 0x0005, 0x2001, 0x180c, 0x2014, 0xc2ed, - 0x2202, 0x00de, 0x00fe, 0x0005, 0x00f6, 0x00d6, 0x2069, 0x19c2, - 0x6830, 0x9086, 0x0000, 0x1548, 0x2001, 0x180c, 0x2014, 0xd2e4, - 0x0130, 0xc2e4, 0x2202, 0x080c, 0x8b9e, 0x2069, 0x19c2, 0x2001, - 0x180c, 0x200c, 0xd1c4, 0x11e0, 0x6838, 0x907d, 0x01b0, 0x6a04, - 0x9296, 0x0000, 0x1568, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, - 0x684b, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, - 0x1b0a, 0x1158, 0x012e, 0x080c, 0x9477, 0x00de, 0x00fe, 0x0005, - 0xc1c4, 0x2102, 0x080c, 0x7246, 0x08f8, 0x012e, 0x6843, 0x0000, - 0x7803, 0x0002, 0x780c, 0x9015, 0x0140, 0x6a3a, 0x780f, 0x0000, - 0x6833, 0x0000, 0x683f, 0x0000, 0x0c40, 0x683a, 0x6836, 0x0cc0, - 0x6a04, 0x9296, 0x0006, 0x1904, 0x8c64, 0x6a30, 0x9296, 0x0000, - 0x0950, 0x0804, 0x8c64, 0x6020, 0x9084, 0x000f, 0x000b, 0x0005, - 0x8cd7, 0x8cdc, 0x916f, 0x9208, 0x8cdc, 0x916f, 0x9208, 0x8cd7, - 0x8cdc, 0x8cd7, 0x8cd7, 0x8cd7, 0x8cd7, 0x8cd7, 0x8cd7, 0x080c, - 0x8a83, 0x080c, 0x8b8f, 0x0005, 0x00b6, 0x0156, 0x0136, 0x0146, - 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, - 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0df6, 0x6110, - 0x2158, 0xb9b0, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a, 0x0040, - 0x1a04, 0x8d48, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, - 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x8ee3, 0x8f1e, - 0x8f47, 0x9000, 0x9021, 0x9027, 0x9034, 0x903c, 0x9048, 0x904e, - 0x905f, 0x904e, 0x90b6, 0x903c, 0x90c2, 0x90c8, 0x9048, 0x90c8, - 0x90d4, 0x8d46, 0x8d46, 0x8d46, 0x8d46, 0x8d46, 0x8d46, 0x8d46, - 0x8d46, 0x8d46, 0x8d46, 0x8d46, 0x9768, 0x978b, 0x979c, 0x97bc, - 0x97ee, 0x9034, 0x8d46, 0x9034, 0x904e, 0x8d46, 0x8f47, 0x9000, - 0x8d46, 0x9b76, 0x904e, 0x8d46, 0x9b92, 0x904e, 0x8d46, 0x9048, - 0x8edd, 0x8d69, 0x8d46, 0x9bae, 0x9c1b, 0x9cf6, 0x8d46, 0x9d03, - 0x9031, 0x9d2e, 0x8d46, 0x97f8, 0x9d5b, 0x8d46, 0x080c, 0x0df6, - 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, - 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x8d67, 0x8d67, 0x8d67, - 0x8da1, 0x8e4d, 0x8e58, 0x8d67, 0x8d67, 0x8d67, 0x8eb2, 0x8ebe, - 0x8dbc, 0x8d67, 0x8dd7, 0x8e0b, 0x9edd, 0x9f22, 0x904e, 0x080c, - 0x0df6, 0x00d6, 0x0096, 0x080c, 0x90e7, 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, 0x95ee, 0x003e, 0x002e, - 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, 0x00be, - 0x080c, 0x9f69, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, 0x0001, - 0x0005, 0x00d6, 0x0096, 0x080c, 0x90e7, 0x7003, 0x0500, 0x7814, - 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, 0xa880, - 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, 0x080c, - 0x95ee, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, 0x90e7, - 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, 0x700e, - 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, 0x701e, - 0x60c3, 0x0010, 0x080c, 0x95ee, 0x009e, 0x00de, 0x0005, 0x00d6, - 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0x90e7, 0x20e9, 0x0000, - 0x2001, 0x197e, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, 0x8003, - 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, - 0x2098, 0x2001, 0x197e, 0x0016, 0x200c, 0x2001, 0x0001, 0x080c, - 0x21e5, 0x080c, 0xcac3, 0x9006, 0x080c, 0x21e5, 0x001e, 0xa804, - 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0x95ee, 0x012e, - 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, - 0x080c, 0x9132, 0x20e9, 0x0000, 0x2001, 0x197e, 0x2003, 0x0000, - 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, 0x8003, - 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, - 0x2098, 0x2001, 0x197e, 0x0016, 0x200c, 0x080c, 0xcac3, 0x001e, - 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, 0x2048, - 0x080c, 0x0fe9, 0x080c, 0x95ee, 0x012e, 0x009e, 0x00de, 0x0005, - 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, 0x0004, - 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x90e7, 0x7003, - 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, 0x95ee, - 0x00d6, 0x00e6, 0x080c, 0x9132, 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, 0x8e78, 0x2069, 0x1801, 0x20a9, - 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x8e81, 0x9096, 0xdf00, - 0x0130, 0x9096, 0xe000, 0x0118, 0x60c3, 0x0018, 0x00f0, 0x2069, - 0x198e, 0x9086, 0xdf00, 0x0110, 0x2069, 0x19a8, 0x20a9, 0x001a, - 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000, - 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68, - 0x8e70, 0x1f04, 0x8e98, 0x60c3, 0x004c, 0x080c, 0x95ee, 0x00ee, - 0x00de, 0x0005, 0x080c, 0x90e7, 0x7003, 0x6300, 0x7007, 0x0028, - 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0x95ee, 0x00d6, 0x0026, - 0x0016, 0x080c, 0x9132, 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6, - 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2073, 0x0800, - 0x8e70, 0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, - 0x95ee, 0x001e, 0x002e, 0x00de, 0x0005, 0x2001, 0x1817, 0x2004, - 0x609a, 0x0804, 0x95ee, 0x080c, 0x90e7, 0x7003, 0x5200, 0x2069, - 0x185b, 0x6804, 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x26a0, - 0x710e, 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, - 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, - 0x1801, 0x20a1, 0x0254, 0x4003, 0x080c, 0x9f69, 0x1120, 0xb8a0, - 0x9082, 0x007f, 0x0248, 0x2001, 0x181e, 0x2004, 0x7032, 0x2001, - 0x181f, 0x2004, 0x7036, 0x0030, 0x2001, 0x1817, 0x2004, 0x9084, - 0x00ff, 0x7036, 0x60c3, 0x001c, 0x0804, 0x95ee, 0x080c, 0x90e7, - 0x7003, 0x0500, 0x080c, 0x9f69, 0x1120, 0xb8a0, 0x9082, 0x007f, - 0x0248, 0x2001, 0x181e, 0x2004, 0x700a, 0x2001, 0x181f, 0x2004, - 0x700e, 0x0030, 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x700e, - 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, - 0x20a1, 0x0250, 0x4003, 0x60c3, 0x0010, 0x0804, 0x95ee, 0x080c, - 0x90e7, 0x9006, 0x080c, 0x6693, 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, 0x8fc8, 0x00d6, 0x2069, - 0x1946, 0x2001, 0x1836, 0x2004, 0xd0a4, 0x0178, 0x6800, 0x700a, - 0x6808, 0x9084, 0x2000, 0x7012, 0x680c, 0x7016, 0x701f, 0x2710, - 0x6818, 0x7022, 0x681c, 0x7026, 0x00f0, 0x6800, 0x700a, 0x6804, - 0x700e, 0x2001, 0x0002, 0x00f6, 0x2079, 0x0100, 0x080c, 0x717e, - 0x1128, 0x78e3, 0x0000, 0x080c, 0x26e1, 0x78e2, 0x00fe, 0x6808, - 0x080c, 0x717e, 0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, - 0x7012, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001, - 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, - 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c, - 0x9ddd, 0x2069, 0x194e, 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002, - 0x080c, 0x54df, 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, 0x04a0, - 0x2001, 0x1836, 0x2004, 0xd0a4, 0x0168, 0x0016, 0x2009, 0x0002, - 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x26e1, - 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, 0x1946, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, - 0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, - 0x20a1, 0x025a, 0x4003, 0x080c, 0x9ddd, 0x20a1, 0x024e, 0x20a9, - 0x0008, 0x2099, 0x194e, 0x4003, 0x60c3, 0x0074, 0x0804, 0x95ee, - 0x080c, 0x90e7, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, - 0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, 0x185b, 0x7904, 0x00fe, - 0xd1ac, 0x1110, 0x9085, 0x0020, 0x0010, 0x9085, 0x0010, 0x9085, - 0x0002, 0x00d6, 0x0804, 0x9097, 0x7026, 0x60c3, 0x0014, 0x0804, - 0x95ee, 0x080c, 0x90e7, 0x7003, 0x5000, 0x0804, 0x8f69, 0x080c, - 0x90e7, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, 0x0804, - 0x95ee, 0x080c, 0x9129, 0x0010, 0x080c, 0x9132, 0x7003, 0x0200, - 0x60c3, 0x0004, 0x0804, 0x95ee, 0x080c, 0x9132, 0x7003, 0x0100, - 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0x95ee, - 0x080c, 0x9132, 0x7003, 0x0200, 0x0804, 0x8f69, 0x080c, 0x9132, - 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, 0x0010, 0x700b, - 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0x95ee, 0x00d6, - 0x080c, 0x9132, 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, 0x185b, 0x7904, - 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0x0010, 0x9085, 0x0010, - 0x2009, 0x187d, 0x210c, 0xd184, 0x1110, 0x9085, 0x0002, 0x0026, - 0x2009, 0x187b, 0x210c, 0xd1e4, 0x0150, 0xc0c5, 0xbabc, 0xd28c, - 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, 0x0140, 0xd1ec, - 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, 0xc0bd, 0x002e, - 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0x95ee, 0x080c, 0x9132, - 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, 0x60c3, 0x0014, - 0x0804, 0x95ee, 0x080c, 0x9132, 0x7003, 0x0200, 0x0804, 0x8ee7, - 0x080c, 0x9132, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, - 0x60c3, 0x0008, 0x0804, 0x95ee, 0x080c, 0x9132, 0x7003, 0x0100, - 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0x95ee, 0x0026, 0x00d6, - 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0040, 0x0026, - 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x080c, - 0x9df2, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, - 0x6878, 0x700a, 0x687c, 0x700e, 0x9485, 0x0029, 0x7012, 0x004e, - 0x003e, 0x00de, 0x080c, 0x95dc, 0x721a, 0x9f95, 0x0000, 0x7222, - 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, 0x0026, 0x080c, - 0x9df2, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6, 0x2069, 0x1800, - 0x6878, 0x700a, 0x687c, 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, 0x9df2, 0xb810, 0x9305, 0x7002, 0xb814, - 0x7006, 0x2069, 0x1800, 0xb810, 0x9005, 0x1140, 0xb814, 0x9005, - 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, 0x6878, 0x700a, - 0x687c, 0x700e, 0x0000, 0x9485, 0x0098, 0x7012, 0x004e, 0x003e, - 0x00de, 0x080c, 0x95dc, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, - 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0x95dc, 0x721a, 0x7a08, - 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, 0x0005, 0x00b6, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, 0x0240, - 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0df6, 0x908a, 0x0092, 0x1a0c, - 0x0df6, 0x6110, 0x2158, 0xb9b0, 0x2c78, 0x2061, 0x0100, 0x619a, - 0x9082, 0x0085, 0x0033, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, - 0x0005, 0x91a0, 0x91af, 0x91ba, 0x919e, 0x919e, 0x919e, 0x91a0, - 0x919e, 0x919e, 0x919e, 0x919e, 0x919e, 0x919e, 0x080c, 0x0df6, - 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x29e9, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804, 0x95ee, 0x0431, - 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, 0x60c3, 0x000c, - 0x0804, 0x95ee, 0x04a1, 0x7003, 0x0003, 0x7007, 0x0300, 0x60c3, - 0x0004, 0x0804, 0x95ee, 0x0026, 0x080c, 0x9df2, 0xb810, 0x9085, - 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, 0x700a, - 0x687c, 0x700e, 0x7013, 0x0009, 0x0804, 0x9102, 0x0026, 0x080c, - 0x9df2, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814, 0x7006, 0x2069, - 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x2001, 0x0099, 0x7a20, - 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804, 0x9164, 0x0026, - 0x080c, 0x9df2, 0xb810, 0x9085, 0x8500, 0x7002, 0xb814, 0x7006, - 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x2001, 0x0099, - 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804, 0x9164, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, 0x0200, - 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0df6, 0x908a, - 0x0054, 0x1a0c, 0x0df6, 0x7910, 0x2158, 0xb9b0, 0x2061, 0x0100, - 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x00be, 0x0005, 0x923f, 0x9306, 0x92d9, 0x9428, 0x923d, 0x923d, - 0x923d, 0x923d, 0x923d, 0x923d, 0x923d, 0x993c, 0x9941, 0x9946, - 0x994b, 0x923d, 0x9d3a, 0x923d, 0x9937, 0x080c, 0x0df6, 0x0096, - 0x780b, 0xffff, 0x080c, 0x92aa, 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, 0x1792, 0x0010, - 0x080c, 0x1651, 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, 0x19de, 0x2003, 0x07d0, 0x2001, 0x19dd, 0x2003, 0x0009, - 0x009e, 0x0005, 0x6813, 0x0008, 0xba8c, 0x8210, 0xb8bc, 0xd084, - 0x0180, 0x2001, 0x1aa1, 0x200c, 0x8108, 0x2102, 0x2001, 0x1aa0, - 0x201c, 0x1218, 0x8318, 0x2302, 0x0ea0, 0x794a, 0x712e, 0x7b46, - 0x732a, 0x9294, 0x00ff, 0xba8e, 0x8217, 0x721a, 0xba10, 0x9295, - 0x0600, 0x7202, 0xba14, 0x7206, 0x2069, 0x1800, 0x6a78, 0x720a, - 0x6a7c, 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, 0x95ee, 0x6813, 0x0008, 0xb810, 0x9085, - 0x0500, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, 0x700a, - 0x687c, 0x700e, 0x7013, 0x0889, 0x080c, 0x95dc, 0x721a, 0x7a08, - 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x0005, 0x00d6, 0x0096, - 0x080c, 0x9406, 0x7814, 0x2048, 0x080c, 0xbd4c, 0x1130, 0x7814, - 0x9084, 0x0700, 0x8007, 0x0033, 0x0010, 0x9006, 0x001b, 0x009e, - 0x00de, 0x0005, 0x9324, 0x938d, 0x939d, 0x93c3, 0x93cf, 0x93e0, - 0x93e8, 0x9322, 0x080c, 0x0df6, 0x0016, 0x0036, 0xa97c, 0x918c, - 0x0003, 0x0118, 0x9186, 0x0003, 0x1198, 0xaba8, 0x7824, 0xd0cc, - 0x1168, 0x7316, 0xa898, 0x701a, 0xa894, 0x701e, 0x003e, 0x001e, - 0x2001, 0x198c, 0x2004, 0x60c2, 0x0804, 0x95ee, 0xc3e5, 0x0c88, - 0x9186, 0x0001, 0x190c, 0x0df6, 0xaba8, 0x7824, 0xd0cc, 0x1904, - 0x938a, 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, 0x95ee, 0xc3e5, 0x0804, 0x9349, 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, 0x95ee, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1128, - 0x7216, 0x60c3, 0x0018, 0x0804, 0x95ee, 0x0cd0, 0xc2e5, 0x2011, - 0x0100, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x702f, 0x0008, - 0x7858, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x0020, 0x0804, 0x95ee, - 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, 0x6878, 0x700a, 0x687c, 0x700e, 0x7824, 0xd0cc, 0x1168, - 0x7013, 0x0898, 0x080c, 0x95dc, 0x721a, 0x7a08, 0x7222, 0x2f10, - 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x7013, 0x0889, 0x0c90, - 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, - 0x9438, 0x9438, 0x943a, 0x9438, 0x9438, 0x9438, 0x9454, 0x9438, - 0x080c, 0x0df6, 0x7914, 0x918c, 0x08ff, 0x918d, 0xf600, 0x7916, - 0x2009, 0x0003, 0x00b9, 0x2069, 0x185b, 0x6804, 0xd0bc, 0x0130, - 0x682c, 0x9084, 0x00ff, 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, - 0x60c3, 0x0001, 0x0804, 0x95ee, 0x2009, 0x0003, 0x0019, 0x7033, - 0x7f00, 0x0cb0, 0x0016, 0x080c, 0x9df2, 0x001e, 0xb810, 0x9085, - 0x0100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6a78, 0x720a, - 0x6a7c, 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, - 0x95dc, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x0005, 0x00b6, - 0x0096, 0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, - 0x0100, 0x2071, 0x1800, 0x7810, 0x2058, 0xb8a0, 0x2028, 0xb910, - 0xba14, 0x7378, 0x747c, 0x7820, 0x90be, 0x0006, 0x0904, 0x954b, - 0x90be, 0x000a, 0x1904, 0x9507, 0xb8b0, 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, 0xb8b0, 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, 0x9dd7, 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, - 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x82de, 0x003e, 0x004e, - 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e, 0x00be, 0x0005, 0x7804, - 0x9086, 0x0040, 0x0904, 0x9587, 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, 0xbab0, 0x629e, 0x080c, 0x9dd7, 0x2009, - 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, - 0x080c, 0x82de, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, - 0x009e, 0x00be, 0x0005, 0x7814, 0x2048, 0xa87c, 0x9084, 0x0003, - 0x9086, 0x0002, 0x0904, 0x95a3, 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, 0xbab0, 0x629e, 0x080c, 0x9db4, 0x0804, 0x9537, 0xb8bc, - 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, 0x951a, 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, 0xbab0, - 0x629e, 0x7824, 0xd0cc, 0x0120, 0x080c, 0x9dd7, 0x0804, 0x9537, - 0x080c, 0x9db4, 0x0804, 0x9537, 0x7a10, 0x00b6, 0x2258, 0xba8c, - 0x8210, 0x9294, 0x00ff, 0xba8e, 0x00be, 0x8217, 0x0005, 0x00d6, - 0x2069, 0x19c2, 0x6843, 0x0001, 0x00de, 0x0005, 0x60a3, 0x0056, - 0x60a7, 0x9575, 0x00f1, 0x080c, 0x82d0, 0x0005, 0x0016, 0x2001, - 0x180c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, 0x0128, 0x0089, - 0x080c, 0x82d0, 0x001e, 0x0005, 0xc1e5, 0x2001, 0x180c, 0x2102, - 0x2001, 0x19c3, 0x2003, 0x0000, 0x2001, 0x19cb, 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, 0x717e, 0x11c0, 0x2001, 0x19de, 0x2004, 0x9005, 0x15d0, - 0x080c, 0x7246, 0x1160, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, - 0x6024, 0xd084, 0x090c, 0x0df6, 0x080c, 0x82d0, 0x0458, 0x00c6, - 0x2061, 0x19c2, 0x00c8, 0x6904, 0x9194, 0x4000, 0x0540, 0x0811, - 0x080c, 0x2b7f, 0x00c6, 0x2061, 0x19c2, 0x6128, 0x9192, 0x0008, - 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, - 0x82d0, 0x080c, 0x9611, 0x0070, 0x6124, 0x91e5, 0x0000, 0x0140, - 0x080c, 0xdbf0, 0x080c, 0x82d9, 0x2009, 0x0014, 0x080c, 0xa068, - 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, - 0x19de, 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, 0x19c2, 0x6128, - 0x9192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x82d0, - 0x080c, 0x5cee, 0x2009, 0x185a, 0x2114, 0x8210, 0x220a, 0x0c10, - 0x0096, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, 0x82e6, - 0x2071, 0x19c2, 0x713c, 0x81ff, 0x0904, 0x970a, 0x2061, 0x0100, - 0x2069, 0x0140, 0x080c, 0x717e, 0x1190, 0x0036, 0x2019, 0x0002, - 0x080c, 0x98b1, 0x003e, 0x713c, 0x2160, 0x080c, 0xdbf0, 0x2009, - 0x004a, 0x080c, 0xa068, 0x080c, 0x7246, 0x0804, 0x970a, 0x6904, - 0xd1f4, 0x0904, 0x9711, 0x080c, 0x2b7f, 0x00c6, 0x703c, 0x9065, - 0x090c, 0x0df6, 0x6020, 0x00ce, 0x9086, 0x0006, 0x1568, 0x61c8, - 0x60c4, 0x9105, 0x1548, 0x2009, 0x180c, 0x2104, 0xd0d4, 0x0520, - 0x6214, 0x9294, 0x1800, 0x1128, 0x6224, 0x9294, 0x0002, 0x1550, - 0x0070, 0xc0d4, 0x200a, 0x0006, 0x2001, 0x0100, 0x2004, 0x9086, - 0x000a, 0x000e, 0x0120, 0xd0cc, 0x0110, 0x080c, 0x2ab1, 0x6014, - 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, 0x703c, 0x2060, 0x2009, - 0x0049, 0x080c, 0xa068, 0x0070, 0x0036, 0x2019, 0x0001, 0x080c, - 0x98b1, 0x003e, 0x713c, 0x2160, 0x080c, 0xdbf0, 0x2009, 0x004a, - 0x080c, 0xa068, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x009e, - 0x0005, 0xd1ec, 0x1904, 0x96c3, 0x0804, 0x96c5, 0x0026, 0x00e6, - 0x2071, 0x19c2, 0x7048, 0xd084, 0x01c0, 0x713c, 0x81ff, 0x01a8, - 0x2071, 0x0100, 0x9188, 0x0008, 0x2114, 0x928e, 0x0006, 0x1138, - 0x7014, 0x9084, 0x1984, 0x9085, 0x0012, 0x7016, 0x0030, 0x7014, - 0x9084, 0x1984, 0x9085, 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005, - 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, - 0x0126, 0x2091, 0x8000, 0x6010, 0x2058, 0xbca0, 0x2071, 0x19c2, - 0x7018, 0x2058, 0x8bff, 0x0190, 0xb8a0, 0x9406, 0x0118, 0xb854, - 0x2058, 0x0cc0, 0x6014, 0x0096, 0x2048, 0xac6c, 0xad70, 0xae78, - 0x009e, 0x080c, 0x64d5, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, - 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, - 0x080c, 0x90e7, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, 0x7016, - 0x00c6, 0x7820, 0x9086, 0x0004, 0x1148, 0x7810, 0x9005, 0x0130, - 0x00b6, 0x2058, 0xb810, 0xb914, 0x00be, 0x0020, 0x2061, 0x1800, - 0x6078, 0x617c, 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, 0x60c3, - 0x002c, 0x0804, 0x95ee, 0x080c, 0x90e7, 0x7003, 0x0f00, 0x7808, - 0xd09c, 0x0128, 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, 0x700e, - 0x60c3, 0x0008, 0x0804, 0x95ee, 0x0156, 0x080c, 0x9132, 0x7003, - 0x0200, 0x2011, 0x1848, 0x63f0, 0x2312, 0x20a9, 0x0006, 0x2011, - 0x1840, 0x2019, 0x1841, 0x9ef0, 0x0002, 0x2376, 0x8e70, 0x2276, - 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0x97ad, 0x60c3, - 0x001c, 0x015e, 0x0804, 0x95ee, 0x0016, 0x0026, 0x080c, 0x910e, - 0x080c, 0x9120, 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, - 0x95ee, 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, - 0x9ddd, 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0x90e7, - 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0x95ee, - 0x0016, 0x0026, 0x080c, 0x90e7, 0x20e9, 0x0000, 0x20a1, 0x024c, - 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, - 0x9080, 0x0023, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, - 0x4003, 0x8003, 0x60c2, 0x080c, 0x95ee, 0x002e, 0x001e, 0x0005, - 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19c2, - 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xbf56, 0x1110, 0x080c, - 0xa9a7, 0x600c, 0x0006, 0x080c, 0xc1c2, 0x080c, 0x9fea, 0x080c, - 0x9955, 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, 0x19c2, 0x7024, 0x2060, 0x8cff, 0x01f8, 0x080c, - 0x961a, 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x82d9, 0x00c6, 0x2061, - 0x0100, 0x080c, 0x9df6, 0x00ce, 0x20a9, 0x01f4, 0x0461, 0x2009, - 0x0013, 0x080c, 0xa068, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x1800, - 0x2004, 0x9096, 0x0001, 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, - 0x82d9, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, - 0x0008, 0x68c3, 0x0000, 0x2011, 0x5c98, 0x080c, 0x8259, 0x20a9, - 0x01f4, 0x0009, 0x08c0, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, - 0x7804, 0x9084, 0x4000, 0x190c, 0x2b7f, 0x0090, 0xd084, 0x0118, - 0x6827, 0x0001, 0x0010, 0x1f04, 0x9893, 0x7804, 0x9084, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2b6f, 0x9006, 0x080c, 0x2b6f, - 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, - 0x918c, 0xdbff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0x19c2, 0x703c, 0x2060, 0x8cff, 0x0904, 0x9918, 0x9386, 0x0002, - 0x1128, 0x6814, 0x9084, 0x0002, 0x0904, 0x9918, 0x68af, 0x95f5, - 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, - 0x0008, 0x080c, 0x82e6, 0x080c, 0x1e30, 0x2001, 0x0032, 0x6920, - 0xd1bc, 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, - 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, - 0x9084, 0x4000, 0x190c, 0x2b7f, 0x0090, 0xd08c, 0x0118, 0x6827, - 0x0002, 0x0010, 0x1f04, 0x98f2, 0x7804, 0x9084, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2b6f, 0x9006, 0x080c, 0x2b6f, 0x6827, - 0x4000, 0x6824, 0x83ff, 0x1120, 0x2009, 0x0049, 0x080c, 0xa068, - 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, - 0x19c2, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, - 0x8000, 0x2069, 0x19c2, 0x6a32, 0x012e, 0x00de, 0x0005, 0x080c, - 0x92aa, 0x7047, 0x1000, 0x0098, 0x080c, 0x92aa, 0x7047, 0x4000, - 0x0070, 0x080c, 0x92aa, 0x7047, 0x2000, 0x0048, 0x080c, 0x92aa, - 0x7047, 0x0400, 0x0020, 0x080c, 0x92aa, 0x7047, 0x0200, 0x7854, - 0x7032, 0x60c3, 0x0020, 0x0804, 0x95ee, 0x00e6, 0x2071, 0x19c2, - 0x7020, 0x9005, 0x0110, 0x8001, 0x7022, 0x00ee, 0x0005, 0x00f6, - 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0x19c2, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, - 0x87ff, 0x0904, 0x99fa, 0x8cff, 0x0904, 0x99fa, 0x6020, 0x9086, - 0x0006, 0x1904, 0x99f5, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, - 0x99f5, 0x2039, 0x0000, 0x0050, 0x6010, 0x9b06, 0x1904, 0x99f5, - 0x85ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x99f5, 0x7024, 0x9c06, - 0x15b0, 0x2069, 0x0100, 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084, - 0x0148, 0x6827, 0x0001, 0x080c, 0x82d9, 0x080c, 0x9a7f, 0x7027, - 0x0000, 0x0428, 0x080c, 0x82d9, 0x6820, 0xd0b4, 0x0110, 0x68a7, - 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x9a7f, 0x7027, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2b6f, 0x9006, 0x080c, 0x2b6f, 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, 0xbd4c, - 0x0110, 0x080c, 0xd7e2, 0x009e, 0x080c, 0xa01c, 0x080c, 0x9955, - 0x88ff, 0x1190, 0x00ce, 0x0804, 0x9970, 0x2c78, 0x600c, 0x2060, - 0x0804, 0x9970, 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, 0x19c2, 0x7638, - 0x2660, 0x2678, 0x8cff, 0x0904, 0x9a6e, 0x6020, 0x9086, 0x0006, - 0x1904, 0x9a69, 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, 0x9a69, - 0x0040, 0x6010, 0x9b06, 0x15e8, 0x85ff, 0x0118, 0x6054, 0x9106, - 0x15c0, 0x703c, 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, - 0x98b1, 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, 0xbd4c, 0x0110, - 0x080c, 0xd7e2, 0x080c, 0xa01c, 0x87ff, 0x1198, 0x00ce, 0x0804, - 0x9a1a, 0x2c78, 0x600c, 0x2060, 0x0804, 0x9a1a, 0x9006, 0x012e, - 0x000e, 0x002e, 0x006e, 0x00ce, 0x009e, 0x00de, 0x00ee, 0x00fe, - 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd, 0x0001, 0x0c80, 0x00e6, - 0x2071, 0x19c2, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1118, - 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, - 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, - 0x2071, 0x19c2, 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, - 0x8a83, 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, 0x19c2, 0x760c, 0x2660, 0x2678, - 0x8cff, 0x0904, 0x9b65, 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, - 0x9206, 0x1904, 0x9b60, 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, - 0x68c0, 0x9005, 0x0904, 0x9b37, 0x080c, 0x961a, 0x68c3, 0x0000, - 0x080c, 0x9a7f, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2b6f, 0x9006, - 0x080c, 0x2b6f, 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, 0xbf45, 0x1180, 0x080c, - 0x30be, 0x080c, 0xbf56, 0x1518, 0x080c, 0xa9a7, 0x0400, 0x080c, - 0x9a7f, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, - 0xbf56, 0x1118, 0x080c, 0xa9a7, 0x0090, 0x6014, 0x2048, 0x080c, - 0xbd4c, 0x0168, 0x6020, 0x9086, 0x0003, 0x1508, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6a15, 0x080c, 0xbf39, 0x080c, - 0xc1c2, 0x080c, 0xa01c, 0x080c, 0x9955, 0x00ce, 0x0804, 0x9ae0, - 0x2c78, 0x600c, 0x2060, 0x0804, 0x9ae0, 0x012e, 0x000e, 0x002e, - 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, 0x0005, 0x6020, - 0x9086, 0x0006, 0x1d20, 0x080c, 0xd7e2, 0x0c08, 0x00d6, 0x080c, - 0x9132, 0x7003, 0x0200, 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, - 0x0001, 0x2099, 0x1963, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x20a9, - 0x0004, 0x4003, 0x7023, 0x0004, 0x7027, 0x7878, 0x080c, 0x95ee, - 0x00de, 0x0005, 0x080c, 0x9132, 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, 0x95ee, 0x00b6, 0x00d6, - 0x0016, 0x00d6, 0x2f68, 0x2009, 0x0035, 0x080c, 0xc3cf, 0x00de, - 0x1904, 0x9c13, 0x080c, 0x90e7, 0x7003, 0x1300, 0x782c, 0x080c, - 0x9d19, 0x2068, 0x6820, 0x9086, 0x0003, 0x0560, 0x7810, 0x2058, - 0xbaa0, 0x080c, 0x9f69, 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, 0x9f69, 0x1130, 0x7810, 0x2058, 0xb8a0, - 0x9082, 0x007e, 0x0250, 0x00d6, 0x2069, 0x181e, 0x2d04, 0x700a, - 0x8d68, 0x2d04, 0x700e, 0x00de, 0x0010, 0x6034, 0x700e, 0x7838, - 0x7012, 0x783c, 0x7016, 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, - 0x95ee, 0x00be, 0x0005, 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, - 0x00de, 0x00be, 0x0005, 0x792c, 0x9180, 0x0008, 0x200c, 0x9186, - 0x0006, 0x01c0, 0x9186, 0x0003, 0x0904, 0x9c8e, 0x9186, 0x0005, - 0x0904, 0x9c76, 0x9186, 0x0004, 0x05d8, 0x9186, 0x0008, 0x0904, - 0x9c7f, 0x7807, 0x0037, 0x782f, 0x0003, 0x7817, 0x1700, 0x080c, - 0x9cf6, 0x0005, 0x080c, 0x9cb7, 0x00d6, 0x0026, 0x792c, 0x2168, - 0x2009, 0x4000, 0x6800, 0x0002, 0x9c57, 0x9c62, 0x9c59, 0x9c62, - 0x9c5e, 0x9c57, 0x9c57, 0x9c62, 0x9c62, 0x9c62, 0x9c62, 0x9c57, - 0x9c57, 0x9c57, 0x9c57, 0x9c57, 0x9c62, 0x9c57, 0x9c62, 0x080c, - 0x0df6, 0x6824, 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, - 0x2009, 0x2000, 0x682c, 0x7022, 0x6830, 0x7026, 0x0804, 0x9cb0, - 0x080c, 0x9cb7, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, - 0x6a00, 0x9286, 0x0002, 0x1108, 0x900e, 0x04d0, 0x080c, 0x9cb7, - 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, 0x95ee, 0x00b6, - 0x0036, 0x0046, 0x0056, 0x0066, 0x080c, 0x9132, 0x9006, 0x7003, - 0x0200, 0x7938, 0x710a, 0x793c, 0x710e, 0x7810, 0x2058, 0xb8a0, - 0x080c, 0x9f69, 0x1118, 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, - 0x181e, 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, 0x9132, - 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x700e, 0x60c3, - 0x0008, 0x0804, 0x95ee, 0x080c, 0x90de, 0x7003, 0x1400, 0x7838, - 0x700a, 0x0079, 0x783c, 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, - 0x7834, 0x9084, 0x00ff, 0x8007, 0x701a, 0x60c3, 0x0010, 0x0804, - 0x95ee, 0x00e6, 0x2071, 0x0240, 0x0006, 0x00f6, 0x2078, 0x7810, - 0x00b6, 0x2058, 0xb8bc, 0xd084, 0x0120, 0x7844, 0x702a, 0x7848, - 0x702e, 0x00be, 0x00fe, 0x000e, 0x00ee, 0x0005, 0x080c, 0x9129, - 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, - 0x0804, 0x95ee, 0x0021, 0x60c3, 0x0000, 0x0804, 0x95ee, 0x00d6, - 0x080c, 0x9df2, 0xb810, 0x9085, 0x0300, 0x7002, 0xb814, 0x7006, - 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x7013, 0x0819, - 0x080c, 0x95dc, 0x721a, 0x2f10, 0x7222, 0x7a08, 0x7226, 0x2071, - 0x024c, 0x00de, 0x0005, 0x00a9, 0x7914, 0x712a, 0x60c3, 0x0000, - 0x60a7, 0x9575, 0x0026, 0x080c, 0x29e9, 0x0228, 0x2011, 0x0101, - 0x2204, 0xc0c5, 0x2012, 0x002e, 0x080c, 0x9611, 0x080c, 0x82d0, - 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, 0x9df2, 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, 0x198d, 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, 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, 0x1ebc, 0x080c, 0x865d, 0x0126, 0x2091, 0x8000, 0x080c, - 0x8c6c, 0x012e, 0x009e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x00a6, 0x0096, 0x0066, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19c2, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9ec9, 0x7024, - 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0x9e9b, - 0x080c, 0x961a, 0x68c3, 0x0000, 0x080c, 0x9a7f, 0x7027, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2b6f, 0x9006, 0x080c, 0x2b6f, 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, 0xbf45, 0x1180, 0x080c, 0x30be, 0x080c, 0xbf56, 0x1518, - 0x080c, 0xa9a7, 0x0400, 0x080c, 0x9a7f, 0x6824, 0xd084, 0x09b0, - 0x6827, 0x0001, 0x0898, 0x080c, 0xbf56, 0x1118, 0x080c, 0xa9a7, - 0x0090, 0x6014, 0x2048, 0x080c, 0xbd4c, 0x0168, 0x6020, 0x9086, - 0x0003, 0x1520, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, - 0x6a22, 0x080c, 0xbf39, 0x080c, 0xc1c2, 0x080c, 0xa01c, 0x080c, - 0x9955, 0x00ce, 0x0804, 0x9e4c, 0x2c78, 0x600c, 0x2060, 0x0804, - 0x9e4c, 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x006e, 0x009e, - 0x00ae, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1d08, 0x080c, 0xd7e2, 0x08f0, 0x00d6, 0x0156, 0x080c, - 0x9132, 0x7a14, 0x82ff, 0x0138, 0x7003, 0x0100, 0x700b, 0x0003, - 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, 0x7007, 0x0000, 0x2069, - 0x1800, 0x901e, 0x6800, 0x9086, 0x0004, 0x1110, 0xc38d, 0x0060, - 0x080c, 0x717e, 0x1110, 0xc3ad, 0x0008, 0xc3a5, 0x6ad8, 0xd29c, - 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, 0x2011, 0x1848, 0x63f0, - 0x2312, 0x20a9, 0x0006, 0x2011, 0x1840, 0x2019, 0x1841, 0x2071, - 0x0250, 0x2376, 0x8e70, 0x2276, 0x8e70, 0x9398, 0x0002, 0x9290, - 0x0002, 0x1f04, 0x9f11, 0x60c3, 0x0020, 0x080c, 0x95ee, 0x015e, - 0x00de, 0x0005, 0x0156, 0x080c, 0x9132, 0x7a14, 0x82ff, 0x0168, - 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, 0x1238, 0x7003, 0x0100, - 0x700b, 0x0003, 0x60c3, 0x0008, 0x0488, 0x7003, 0x0200, 0x7007, - 0x001c, 0x700f, 0x0001, 0x2011, 0x1998, 0x2204, 0x8007, 0x701a, - 0x8210, 0x2204, 0x8007, 0x701e, 0x0421, 0x1120, 0xb8a0, 0x9082, - 0x007f, 0x0248, 0x2001, 0x181e, 0x2004, 0x7022, 0x2001, 0x181f, - 0x2004, 0x7026, 0x0030, 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, - 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, - 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, 0x001c, 0x015e, 0x0804, - 0x95ee, 0x0006, 0x2001, 0x1836, 0x2004, 0xd0ac, 0x000e, 0x0005, - 0x2011, 0x0003, 0x080c, 0x9923, 0x2011, 0x0002, 0x080c, 0x992d, - 0x080c, 0x983b, 0x0036, 0x901e, 0x080c, 0x98b1, 0x003e, 0x0005, - 0x2071, 0x188b, 0x7000, 0x9005, 0x0140, 0x2001, 0x0976, 0x2071, - 0x1800, 0x7072, 0x7076, 0x7067, 0xffe0, 0x2071, 0x1800, 0x7070, - 0x7052, 0x7057, 0x1cd0, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1800, - 0x2091, 0x8000, 0x7550, 0x9582, 0x0010, 0x0608, 0x7054, 0x2060, - 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7064, 0x9c02, - 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008, 0x8529, - 0x7552, 0x9ca8, 0x0018, 0x7064, 0x9502, 0x1230, 0x7556, 0x9085, - 0x0001, 0x012e, 0x00ee, 0x0005, 0x7057, 0x1cd0, 0x0cc0, 0x9006, - 0x0cc0, 0x00e6, 0x2071, 0x1800, 0x7550, 0x9582, 0x0010, 0x0600, - 0x7054, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, - 0x7064, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, - 0x0008, 0x8529, 0x7552, 0x9ca8, 0x0018, 0x7064, 0x9502, 0x1228, - 0x7556, 0x9085, 0x0001, 0x00ee, 0x0005, 0x7057, 0x1cd0, 0x0cc8, - 0x9006, 0x0cc8, 0x9c82, 0x1cd0, 0x0a0c, 0x0df6, 0x2001, 0x1819, - 0x2004, 0x9c02, 0x1a0c, 0x0df6, 0x9006, 0x6006, 0x600a, 0x600e, - 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, - 0x6056, 0x605a, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, - 0x603e, 0x6042, 0x2061, 0x1800, 0x6050, 0x8000, 0x6052, 0x9086, - 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, - 0x8b8f, 0x001e, 0x012e, 0x0cb0, 0x0006, 0x6000, 0x9086, 0x0000, - 0x01c0, 0x601c, 0xd084, 0x190c, 0x192c, 0x6017, 0x0000, 0x6023, - 0x0007, 0x2001, 0x1960, 0x2004, 0x0006, 0x9082, 0x0051, 0x000e, - 0x0208, 0x8004, 0x601a, 0x080c, 0xda94, 0x6043, 0x0000, 0x6013, - 0x0000, 0x000e, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1800, 0x2091, - 0x8000, 0x7550, 0x9582, 0x0001, 0x0608, 0x7054, 0x2060, 0x6000, - 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7064, 0x9c02, 0x1208, - 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7552, - 0x9ca8, 0x0018, 0x7064, 0x9502, 0x1230, 0x7556, 0x9085, 0x0001, - 0x012e, 0x00ee, 0x0005, 0x7057, 0x1cd0, 0x0cc0, 0x9006, 0x0cc0, - 0x6020, 0x9084, 0x000f, 0x0002, 0xa07b, 0xa084, 0xa09f, 0xa0ba, - 0xc4a1, 0xc4be, 0xc4d9, 0xa07b, 0xa084, 0xa07b, 0xa0d3, 0xa07b, - 0xa07b, 0xa07b, 0xa07b, 0x9186, 0x0013, 0x1128, 0x080c, 0x8a83, - 0x080c, 0x8b8f, 0x0005, 0x0005, 0x0066, 0x6000, 0x90b2, 0x0010, - 0x1a0c, 0x0df6, 0x0013, 0x006e, 0x0005, 0xa09d, 0xa803, 0xa9ee, - 0xa09d, 0xaa7c, 0xa3b6, 0xa09d, 0xa09d, 0xa785, 0xb041, 0xa09d, - 0xa09d, 0xa09d, 0xa09d, 0xa09d, 0xa09d, 0x080c, 0x0df6, 0x0066, - 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0df6, 0x0013, 0x006e, 0x0005, - 0xa0b8, 0xb70e, 0xa0b8, 0xa0b8, 0xa0b8, 0xa0b8, 0xa0b8, 0xa0b8, - 0xb6a5, 0xb890, 0xa0b8, 0xb74f, 0xb7ce, 0xb74f, 0xb7ce, 0xa0b8, - 0x080c, 0x0df6, 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0df6, 0x6000, - 0x0002, 0xa0d1, 0xb088, 0xb150, 0xb283, 0xb432, 0xa0d1, 0xa0d1, - 0xa0d1, 0xb05c, 0xb631, 0xb634, 0xa0d1, 0xa0d1, 0xa0d1, 0xa0d1, - 0xb663, 0x080c, 0x0df6, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, - 0x0df6, 0x0013, 0x006e, 0x0005, 0xa0ec, 0xa0ec, 0xa12f, 0xa1ce, - 0xa263, 0xa0ec, 0xa0ec, 0xa0ec, 0xa0ee, 0xa0ec, 0xa0ec, 0xa0ec, - 0xa0ec, 0xa0ec, 0xa0ec, 0xa0ec, 0x080c, 0x0df6, 0x9186, 0x004c, - 0x0588, 0x9186, 0x0003, 0x190c, 0x0df6, 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, - 0x1a7e, 0x080c, 0x865d, 0x0126, 0x2091, 0x8000, 0x080c, 0x8c6c, - 0x012e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, - 0x080c, 0xa285, 0x080c, 0xc471, 0x6003, 0x0007, 0x0005, 0x00d6, - 0x0096, 0x00f6, 0x2079, 0x1800, 0x7a8c, 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, 0xa196, 0xa196, 0xa191, 0xa194, 0xa196, 0xa18e, 0xa181, - 0xa181, 0xa181, 0xa181, 0xa181, 0xa181, 0xa181, 0xa181, 0xa181, - 0xa181, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, - 0x004e, 0x00fe, 0x009e, 0x00de, 0x080c, 0x0df6, 0x080c, 0xac6e, - 0x0028, 0x080c, 0xad9f, 0x0010, 0x080c, 0xae8d, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896, 0x000e, 0x080c, - 0xa343, 0x0530, 0xa804, 0xa80e, 0x00a6, 0x2050, 0xb100, 0x00ae, - 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, - 0x0002, 0xaacc, 0xabd0, 0xacd4, 0xadd8, 0x2031, 0x0000, 0x2041, - 0x12a8, 0x080c, 0xa4f1, 0x0160, 0x000e, 0x9005, 0x0120, 0x00fe, - 0x009e, 0x00de, 0x0005, 0x00fe, 0x009e, 0x00de, 0x0804, 0x9fea, - 0x2001, 0x002c, 0x900e, 0x080c, 0xa3a9, 0x0c70, 0x91b6, 0x0015, - 0x0170, 0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047, 0x0a0c, 0x0df6, - 0x91b2, 0x0050, 0x1a0c, 0x0df6, 0x9182, 0x0047, 0x00ca, 0x2001, - 0x0109, 0x2004, 0xd08c, 0x0198, 0x0126, 0x2091, 0x2800, 0x0006, - 0x0016, 0x0026, 0x080c, 0x85b1, 0x002e, 0x001e, 0x000e, 0x012e, - 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, 0xa12f, 0x0005, - 0xa201, 0xa201, 0xa203, 0xa239, 0xa201, 0xa201, 0xa201, 0xa201, - 0xa24c, 0x080c, 0x0df6, 0x00d6, 0x0016, 0x0096, 0x080c, 0x8b3f, - 0x080c, 0x8c6c, 0x6003, 0x0004, 0x6114, 0x2148, 0xa87c, 0xd0fc, - 0x01c0, 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894, 0x9005, 0x0140, - 0x2001, 0x0000, 0x900e, 0x080c, 0xa3a9, 0x080c, 0x9fea, 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, 0x8b3f, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, - 0xbd4e, 0x0120, 0xa87b, 0x0006, 0x080c, 0x6a22, 0x009e, 0x00de, - 0x080c, 0x9fea, 0x0804, 0x8c6c, 0x080c, 0x8b3f, 0x080c, 0x3095, - 0x080c, 0xc46e, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, 0xbd4e, - 0x0120, 0xa87b, 0x0029, 0x080c, 0x6a22, 0x009e, 0x00de, 0x080c, - 0x9fea, 0x0804, 0x8c6c, 0x9182, 0x0047, 0x0002, 0xa273, 0xa275, - 0xa273, 0xa273, 0xa273, 0xa273, 0xa273, 0xa273, 0xa273, 0xa273, - 0xa273, 0xa273, 0xa275, 0x080c, 0x0df6, 0x00d6, 0x0096, 0x080c, - 0x1577, 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883, 0x0000, 0x080c, - 0x6a22, 0x009e, 0x00de, 0x0804, 0x9fea, 0x0026, 0x0036, 0x0056, - 0x0066, 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c, 0x1037, 0x000e, - 0x090c, 0x0df6, 0xa960, 0x21e8, 0xa95c, 0x9188, 0x0019, 0x21a0, - 0x900e, 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079, 0x1800, 0x798c, - 0x9188, 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76, 0x2950, 0x00a6, - 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, 0x0001, 0x9182, - 0x0035, 0x1228, 0x2011, 0x001f, 0x080c, 0xb915, 0x04c0, 0x2130, - 0x2009, 0x0034, 0x2011, 0x001f, 0x080c, 0xb915, 0x96b2, 0x0034, - 0xb004, 0x904d, 0x0110, 0x080c, 0x0fe9, 0x080c, 0x1037, 0x01d0, - 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, 0xb406, 0x968a, - 0x003d, 0x1230, 0x2608, 0x2011, 0x001b, 0x080c, 0xb915, 0x00b8, - 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, 0x080c, - 0xb915, 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, 0x6a22, 0x000e, - 0x2048, 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e, 0x006e, 0x005e, - 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096, 0x0006, 0x080c, - 0x1037, 0x000e, 0x090c, 0x0df6, 0xa960, 0x21e8, 0xa95c, 0x9188, - 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xaa66, 0xa87a, - 0x2079, 0x1800, 0x798c, 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, 0x6a22, 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, 0x1037, 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, 0xa358, 0x0804, 0xa35a, - 0x9085, 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe, 0x00de, 0x001e, - 0x0005, 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, - 0x080c, 0x6a15, 0x009e, 0x003e, 0x00de, 0x0005, 0x91b6, 0x0015, - 0x1118, 0x080c, 0x9fea, 0x0030, 0x91b6, 0x0016, 0x190c, 0x0df6, - 0x080c, 0x9fea, 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, 0xbd4e, 0x0130, 0x6014, 0x2048, - 0xa807, 0x0000, 0xa867, 0x0103, 0x009e, 0x0804, 0x9fea, 0x0096, - 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11a8, 0x6010, 0x00b6, - 0x2058, 0xb8bf, 0x0000, 0x00be, 0x6014, 0x9005, 0x0130, 0x2048, - 0xa807, 0x0000, 0xa867, 0x0103, 0xab32, 0x080c, 0x9fea, 0x003e, - 0x00de, 0x009e, 0x0005, 0x0011, 0x1d48, 0x0cc8, 0x0006, 0x0016, - 0x080c, 0xc459, 0x0188, 0x6014, 0x9005, 0x1170, 0x600b, 0x0003, - 0x601b, 0x0000, 0x6043, 0x0000, 0x2009, 0x0022, 0x080c, 0xa7db, - 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, 0x9fea, - 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, 0xb915, 0x080c, 0xbd4e, - 0x0140, 0x6014, 0x2048, 0xa807, 0x0000, 0xa864, 0xa8e2, 0xa867, - 0x0103, 0x080c, 0x9fea, 0x001e, 0x009e, 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, 0xb915, 0x009e, - 0x080c, 0xbd4e, 0x0148, 0xa804, 0x9005, 0x1158, 0xa807, 0x0000, - 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0x9fea, 0x009e, 0x001e, - 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, 0x0100, 0x1118, - 0x080c, 0xa9a7, 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, 0x128e, 0x0019, 0x0d08, 0x008e, - 0x0898, 0x0096, 0x0006, 0x080c, 0x1037, 0x000e, 0x01b0, 0xa8ab, - 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, 0x2800, 0xa89e, - 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, 0x0086, 0x2940, - 0x080c, 0x1134, 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, 0xc3cf, 0x001e, 0x1158, 0x622c, 0x2268, - 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, - 0x0128, 0x080c, 0x9fea, 0x0020, 0x0039, 0x0010, 0x080c, 0xa610, - 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, 0x2048, 0x9186, - 0x0015, 0x0904, 0xa5f8, 0x918e, 0x0016, 0x1904, 0xa60e, 0x700c, - 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, - 0xa5d2, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, 0xa5b5, - 0x0804, 0xa60c, 0x6808, 0x9086, 0xffff, 0x1904, 0xa5fa, 0xa87c, - 0x9084, 0x0060, 0x9086, 0x0020, 0x1128, 0xa83c, 0xa940, 0x9105, - 0x1904, 0xa5fa, 0x6824, 0xd084, 0x1904, 0xa5fa, 0xd0b4, 0x0158, - 0x0016, 0x2001, 0x1960, 0x200c, 0x6018, 0x9102, 0x9082, 0x0005, - 0x001e, 0x1a04, 0xa5fa, 0x080c, 0xbf39, 0x685c, 0xa882, 0xa87c, - 0xc0dc, 0xc0f4, 0xc0d4, 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, - 0x000a, 0x080c, 0x847e, 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, - 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xba77, 0x00ce, - 0x0804, 0xa60c, 0x00c6, 0xa868, 0xd0fc, 0x1118, 0x080c, 0x5eab, - 0x0010, 0x080c, 0x6259, 0x00ce, 0x1904, 0xa5fa, 0x00c6, 0x2d60, - 0x080c, 0x9fea, 0x00ce, 0x0804, 0xa60c, 0x00c6, 0x080c, 0xa03b, - 0x0198, 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xc1ca, 0x6023, - 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0x9fea, 0x00ce, 0x080c, - 0xa068, 0x00ce, 0x0804, 0xa60c, 0x2001, 0x1962, 0x2004, 0x6842, - 0x00ce, 0x04d0, 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, - 0x2058, 0xb900, 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, - 0x0003, 0x080c, 0xc413, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x00ce, 0x00e8, 0x700c, - 0x9086, 0x2a00, 0x1138, 0x2001, 0x1962, 0x2004, 0x6842, 0x00a0, - 0x0479, 0x00a0, 0x89ff, 0x090c, 0x0df6, 0x00c6, 0x00d6, 0x2d60, - 0xa867, 0x0103, 0xa87b, 0x0003, 0x080c, 0x683c, 0x080c, 0xbf39, - 0x080c, 0xa01c, 0x00de, 0x00ce, 0x080c, 0x9fea, 0x009e, 0x0005, - 0x9186, 0x0015, 0x1128, 0x2001, 0x1962, 0x2004, 0x6842, 0x0068, - 0x918e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xda94, - 0x080c, 0x8425, 0x080c, 0x9fea, 0x00ce, 0x080c, 0x9fea, 0x0005, - 0x0026, 0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, - 0x2001, 0x1962, 0x2004, 0x6842, 0x0804, 0xa68a, 0x00c6, 0x2d60, - 0x080c, 0xb976, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, - 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x85f8, - 0x080c, 0x8b8f, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8, - 0x89ff, 0x090c, 0x0df6, 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, 0xc0c1, 0x080c, - 0x8b8f, 0x0010, 0x080c, 0x9fea, 0x004e, 0x003e, 0x002e, 0x0005, - 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, - 0x2258, 0xba10, 0x00be, 0x9206, 0x1904, 0xa6f5, 0x700c, 0x6210, - 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xa6f5, 0x6038, - 0x2068, 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, - 0xa6f5, 0x9286, 0x0002, 0x0904, 0xa6f5, 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, 0xbd4e, 0x090c, 0x0df6, 0xa87b, 0x0003, - 0x009e, 0x080c, 0xc413, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x00ce, 0x0030, 0x6038, - 0x2070, 0x2001, 0x1962, 0x2004, 0x7042, 0x080c, 0x9fea, 0x002e, - 0x00de, 0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, - 0x6010, 0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, - 0xc48c, 0xbc02, 0x0460, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, - 0x9e90, 0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, 0xb017, - 0x002e, 0x003e, 0x015e, 0x009e, 0x1904, 0xa764, 0x0096, 0x0156, - 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, - 0x0004, 0x080c, 0xb017, 0x002e, 0x003e, 0x015e, 0x009e, 0x15a0, - 0x7238, 0xba0a, 0x733c, 0xbb0e, 0xbc00, 0xc48d, 0xbc02, 0xa804, - 0x9005, 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804, 0xa3f2, 0x0096, - 0x2048, 0xaa12, 0xab16, 0xac0a, 0x009e, 0x8006, 0x8006, 0x8007, - 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, - 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x128e, - 0x080c, 0xa4f1, 0x0130, 0x00fe, 0x009e, 0x080c, 0x9fea, 0x00be, - 0x0005, 0x080c, 0xa9a7, 0x0cb8, 0x2b78, 0x00f6, 0x080c, 0x3095, - 0x080c, 0xc46e, 0x00fe, 0x00c6, 0x080c, 0x9f94, 0x2f00, 0x6012, - 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, - 0x2001, 0x0007, 0x080c, 0x62f4, 0x080c, 0x6320, 0x080c, 0x8640, - 0x080c, 0x8b8f, 0x00ce, 0x0804, 0xa737, 0x2100, 0x91b2, 0x0053, - 0x1a0c, 0x0df6, 0x91b2, 0x0040, 0x1a04, 0xa7ed, 0x0002, 0xa7db, - 0xa7db, 0xa7d1, 0xa7db, 0xa7db, 0xa7db, 0xa7cf, 0xa7cf, 0xa7cf, - 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, - 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, - 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7db, 0xa7cf, - 0xa7db, 0xa7db, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7d1, - 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, - 0xa7cf, 0xa7db, 0xa7db, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, - 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7db, 0xa7cf, 0xa7cf, 0x080c, - 0x0df6, 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8bc, 0xc08c, 0xb8be, - 0x00be, 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, 0x9186, 0x0032, - 0x0118, 0x080c, 0x8640, 0x0010, 0x080c, 0x85f8, 0x0126, 0x2091, - 0x8000, 0x080c, 0x8b8f, 0x012e, 0x0005, 0x2600, 0x0002, 0xa801, - 0xa801, 0xa801, 0xa7db, 0xa7db, 0xa801, 0xa801, 0xa801, 0xa801, - 0xa7db, 0xa801, 0xa7db, 0xa801, 0xa7db, 0xa801, 0xa801, 0xa801, - 0xa801, 0x080c, 0x0df6, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0df6, - 0x91b6, 0x0013, 0x0904, 0xa8d6, 0x91b6, 0x0027, 0x1904, 0xa880, - 0x080c, 0x8a83, 0x6004, 0x080c, 0xbf45, 0x01b0, 0x080c, 0xbf56, - 0x01a8, 0x908e, 0x0021, 0x0904, 0xa87d, 0x908e, 0x0022, 0x1130, - 0x080c, 0xa41e, 0x0904, 0xa879, 0x0804, 0xa87a, 0x908e, 0x003d, - 0x0904, 0xa87d, 0x0804, 0xa873, 0x080c, 0x30be, 0x2001, 0x0007, - 0x080c, 0x62f4, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, - 0xa9a7, 0x9186, 0x007e, 0x1148, 0x2001, 0x1836, 0x2014, 0xc285, - 0x080c, 0x717e, 0x1108, 0xc2ad, 0x2202, 0x0036, 0x0026, 0x2019, - 0x0028, 0x2110, 0x080c, 0xdaf0, 0x002e, 0x003e, 0x0016, 0x0026, - 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x8782, 0x0076, 0x903e, - 0x080c, 0x8670, 0x6010, 0x00b6, 0x905d, 0x0100, 0x00be, 0x2c08, - 0x080c, 0xd556, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0xc46e, - 0x0016, 0x080c, 0xc1c2, 0x080c, 0x9fea, 0x001e, 0x080c, 0x3190, - 0x080c, 0x8b8f, 0x0030, 0x080c, 0xc1c2, 0x080c, 0x9fea, 0x080c, - 0x8b8f, 0x0005, 0x080c, 0xa9a7, 0x0cb0, 0x080c, 0xa9e3, 0x0c98, - 0x9186, 0x0015, 0x0118, 0x9186, 0x0016, 0x1148, 0x080c, 0xc47f, - 0x0d80, 0x6000, 0x9086, 0x0002, 0x0904, 0xa9ee, 0x0c50, 0x9186, - 0x0014, 0x1d38, 0x080c, 0x8a83, 0x6004, 0x908e, 0x0022, 0x1118, - 0x080c, 0xa41e, 0x09f0, 0x080c, 0x3095, 0x080c, 0xc46e, 0x080c, - 0xbf45, 0x1198, 0x080c, 0x30be, 0x6010, 0x00b6, 0x2058, 0xb9a0, - 0x00be, 0x080c, 0xa9a7, 0x9186, 0x007e, 0x1128, 0x2001, 0x1836, - 0x200c, 0xc185, 0x2102, 0x0804, 0xa873, 0x080c, 0xbf56, 0x1120, - 0x080c, 0xa9a7, 0x0804, 0xa873, 0x6004, 0x908e, 0x0032, 0x1160, - 0x00e6, 0x00f6, 0x2071, 0x189c, 0x2079, 0x0000, 0x080c, 0x3424, - 0x00fe, 0x00ee, 0x0804, 0xa873, 0x6004, 0x908e, 0x0021, 0x0d40, - 0x908e, 0x0022, 0x090c, 0xa9a7, 0x0804, 0xa873, 0x90b2, 0x0040, - 0x1a04, 0xa990, 0x2008, 0x0002, 0xa91e, 0xa91f, 0xa922, 0xa925, - 0xa928, 0xa935, 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, - 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, - 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, - 0xa91c, 0xa91c, 0xa938, 0xa945, 0xa91c, 0xa947, 0xa945, 0xa91c, - 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa945, 0xa945, 0xa91c, 0xa91c, - 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa91c, 0xa977, 0xa945, - 0xa91c, 0xa941, 0xa91c, 0xa91c, 0xa91c, 0xa942, 0xa91c, 0xa91c, - 0xa91c, 0xa945, 0xa96e, 0xa91c, 0x080c, 0x0df6, 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, 0x8a83, 0x6003, 0x0005, 0x080c, 0xc471, 0x080c, 0x8b8f, - 0x0070, 0x0018, 0x0010, 0x080c, 0x62f4, 0x0804, 0xa988, 0x080c, - 0x8a83, 0x080c, 0xc471, 0x6003, 0x0004, 0x080c, 0x8b8f, 0x0005, - 0x080c, 0x62f4, 0x080c, 0x8a83, 0x6003, 0x0002, 0x0036, 0x2019, - 0x1866, 0x2304, 0x9084, 0xff00, 0x1120, 0x2001, 0x1960, 0x201c, - 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, - 0x9318, 0x631a, 0x003e, 0x080c, 0x8b8f, 0x0c08, 0x080c, 0x8a83, - 0x080c, 0xc1c2, 0x080c, 0x9fea, 0x080c, 0x8b8f, 0x08c0, 0x00e6, - 0x00f6, 0x2071, 0x189c, 0x2079, 0x0000, 0x080c, 0x3424, 0x00fe, - 0x00ee, 0x080c, 0x8a83, 0x080c, 0x9fea, 0x080c, 0x8b8f, 0x0838, - 0x080c, 0x8a83, 0x6003, 0x0002, 0x080c, 0xc471, 0x0804, 0x8b8f, - 0x2600, 0x2008, 0x0002, 0xa9a5, 0xa9a5, 0xa9a5, 0xa988, 0xa988, - 0xa9a5, 0xa9a5, 0xa9a5, 0xa9a5, 0xa988, 0xa9a5, 0xa988, 0xa9a5, - 0xa988, 0xa9a5, 0xa9a5, 0xa9a5, 0xa9a5, 0x080c, 0x0df6, 0x00e6, - 0x0096, 0x0026, 0x0016, 0x080c, 0xbd4e, 0x0568, 0x6014, 0x2048, - 0xa864, 0x9086, 0x0139, 0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, - 0x080c, 0x5275, 0x0130, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, - 0x0028, 0x2001, 0x0030, 0x900e, 0x2011, 0x4005, 0x080c, 0xc333, - 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, 0x0df6, - 0x6604, 0x96b6, 0x004d, 0x1120, 0x080c, 0xc252, 0x0804, 0xaa6b, - 0x6604, 0x96b6, 0x0043, 0x1120, 0x080c, 0xc29b, 0x0804, 0xaa6b, - 0x6604, 0x96b6, 0x004b, 0x1120, 0x080c, 0xc2c7, 0x0804, 0xaa6b, - 0x6604, 0x96b6, 0x0033, 0x1120, 0x080c, 0xc1e4, 0x0804, 0xaa6b, - 0x6604, 0x96b6, 0x0028, 0x1120, 0x080c, 0xbf94, 0x0804, 0xaa6b, - 0x6604, 0x96b6, 0x0029, 0x1120, 0x080c, 0xbfd5, 0x0804, 0xaa6b, - 0x6604, 0x96b6, 0x001f, 0x1118, 0x080c, 0xa3c3, 0x04e0, 0x6604, - 0x96b6, 0x0000, 0x1118, 0x080c, 0xa6fb, 0x04a8, 0x6604, 0x96b6, - 0x0022, 0x1118, 0x080c, 0xa3ff, 0x0470, 0x6604, 0x96b6, 0x0035, - 0x1118, 0x080c, 0xa50f, 0x0438, 0x6604, 0x96b6, 0x0039, 0x1118, - 0x080c, 0xa690, 0x0400, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, - 0xa437, 0x00c8, 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xa473, - 0x0090, 0x6604, 0x96b6, 0x0049, 0x1118, 0x080c, 0xa49e, 0x0058, - 0x91b6, 0x0015, 0x1110, 0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, - 0x00be, 0x0804, 0xad46, 0x00be, 0x0005, 0x080c, 0xa083, 0x0cd8, - 0xaa88, 0xaa96, 0xaa88, 0xaada, 0xaa88, 0xac6e, 0xad53, 0xaa88, - 0xaa88, 0xad20, 0xaa88, 0xad34, 0x0096, 0x080c, 0x1577, 0x6014, - 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, 0x009e, 0x0804, 0x9fea, - 0xa001, 0xa001, 0x0005, 0x6604, 0x96b6, 0x0004, 0x1130, 0x2001, - 0x0001, 0x080c, 0x62e0, 0x0804, 0x9fea, 0x0005, 0x00e6, 0x2071, - 0x1800, 0x708c, 0x9086, 0x0074, 0x1540, 0x080c, 0xd527, 0x11b0, - 0x6010, 0x00b6, 0x2058, 0x7030, 0xd08c, 0x0128, 0xb800, 0xd0bc, - 0x0110, 0xc0c5, 0xb802, 0x00e9, 0x00be, 0x2001, 0x0006, 0x080c, - 0x62f4, 0x080c, 0x30be, 0x080c, 0x9fea, 0x0088, 0x2001, 0x000a, - 0x080c, 0x62f4, 0x080c, 0x30be, 0x6003, 0x0001, 0x6007, 0x0001, - 0x080c, 0x8640, 0x080c, 0x8b8f, 0x0010, 0x080c, 0xac59, 0x00ee, - 0x0005, 0x00d6, 0xb800, 0xd084, 0x0158, 0x9006, 0x080c, 0x62e0, - 0x2069, 0x185b, 0x6804, 0x0020, 0x2001, 0x0006, 0x080c, 0x6320, - 0x00de, 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011, 0x1823, 0x2204, - 0x9086, 0x0074, 0x1904, 0xac30, 0x6010, 0x2058, 0xbaa0, 0x9286, - 0x007e, 0x1120, 0x080c, 0xae98, 0x0804, 0xab9d, 0x00d6, 0x080c, - 0x717e, 0x01a0, 0x0026, 0x2011, 0x0010, 0x080c, 0x66ed, 0x002e, - 0x0904, 0xab3e, 0x080c, 0x54ef, 0x1598, 0x6014, 0x2048, 0xa807, - 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x0450, 0x6010, 0x00b6, - 0x2058, 0xb910, 0x00be, 0x9186, 0x00ff, 0x0580, 0x0026, 0x2011, - 0x8008, 0x080c, 0x66ed, 0x002e, 0x0548, 0x6014, 0x9005, 0x090c, - 0x0df6, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, - 0x2001, 0x0030, 0x900e, 0x2011, 0x4009, 0x080c, 0xc333, 0x0040, - 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, - 0x6010, 0x2058, 0xb9a0, 0x0016, 0x080c, 0x30be, 0x080c, 0x9fea, - 0x001e, 0x080c, 0x3190, 0x00de, 0x0804, 0xac33, 0x00de, 0x080c, - 0xae8d, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014, - 0x9005, 0x01a8, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, - 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xc333, - 0x0030, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x2001, - 0x0006, 0x080c, 0x62f4, 0x080c, 0x30be, 0x080c, 0x9fea, 0x0804, - 0xac33, 0x080c, 0xac41, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, - 0xd0f4, 0x01e8, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, - 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xc333, 0x08f8, - 0x080c, 0xac37, 0x0160, 0x9006, 0x080c, 0x62e0, 0x2001, 0x0004, - 0x080c, 0x6320, 0x2001, 0x0007, 0x080c, 0x62f4, 0x08a0, 0x2001, - 0x0004, 0x080c, 0x62f4, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, - 0x8640, 0x080c, 0x8b8f, 0x0804, 0xac33, 0xb85c, 0xd0e4, 0x0178, - 0x080c, 0xc164, 0x080c, 0x717e, 0x0118, 0xd0dc, 0x1904, 0xab5f, - 0x2011, 0x1836, 0x2204, 0xc0ad, 0x2012, 0x0804, 0xab5f, 0x080c, - 0xc1a1, 0x2011, 0x1836, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, - 0xd6c7, 0x000e, 0x1904, 0xab5f, 0xc0b5, 0x2012, 0x2001, 0x0006, - 0x080c, 0x62f4, 0x9006, 0x080c, 0x62e0, 0x00c6, 0x2001, 0x180f, - 0x2004, 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, - 0x1800, 0x700c, 0x9084, 0x00ff, 0x78e6, 0x707a, 0x7010, 0x78ea, - 0x707e, 0x908c, 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, - 0x080c, 0x26b6, 0x00f6, 0x2100, 0x900e, 0x080c, 0x266d, 0x795a, - 0x00fe, 0x9186, 0x0081, 0x01f0, 0x2009, 0x0081, 0x00e0, 0x2009, - 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x78e7, 0x0000, 0x7932, - 0x7936, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x26b6, 0x00f6, - 0x2079, 0x1800, 0x797e, 0x2100, 0x900e, 0x797a, 0x080c, 0x266d, - 0x795a, 0x00fe, 0x8108, 0x080c, 0x6343, 0x2b00, 0x00ce, 0x1904, - 0xab5f, 0x6012, 0x2009, 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, - 0x027c, 0x210c, 0x918c, 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, - 0xb916, 0x2001, 0x0002, 0x080c, 0x62f4, 0x6023, 0x0001, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x8640, 0x080c, 0x8b8f, 0x0018, - 0x080c, 0xa9a7, 0x0431, 0x00de, 0x009e, 0x00be, 0x0005, 0x2001, - 0x1810, 0x2004, 0xd0a4, 0x0120, 0x2001, 0x185c, 0x2004, 0xd0ac, - 0x0005, 0x00e6, 0x080c, 0xdb49, 0x0190, 0x2071, 0x0260, 0x7108, - 0x720c, 0x918c, 0x00ff, 0x1118, 0x9284, 0xff00, 0x0140, 0x6010, - 0x2058, 0xb8a0, 0x9084, 0xff80, 0x1110, 0xb912, 0xba16, 0x00ee, - 0x0005, 0x2030, 0x2001, 0x0007, 0x080c, 0x62f4, 0x080c, 0x54ef, - 0x1120, 0x2001, 0x0007, 0x080c, 0x6320, 0x080c, 0x30be, 0x6020, - 0x9086, 0x000a, 0x1108, 0x0005, 0x0804, 0x9fea, 0x00b6, 0x00e6, - 0x0026, 0x0016, 0x2071, 0x1800, 0x708c, 0x9086, 0x0014, 0x1904, - 0xad17, 0x00d6, 0x080c, 0x717e, 0x01a0, 0x0026, 0x2011, 0x0010, - 0x080c, 0x66ed, 0x002e, 0x0904, 0xacc9, 0x080c, 0x54ef, 0x1598, - 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, - 0x0450, 0x6010, 0x00b6, 0x2058, 0xb910, 0x00be, 0x9186, 0x00ff, - 0x0580, 0x0026, 0x2011, 0x8008, 0x080c, 0x66ed, 0x002e, 0x0548, - 0x6014, 0x9005, 0x090c, 0x0df6, 0x2048, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, 0x900e, 0x2011, 0x4009, - 0x080c, 0xc333, 0x0040, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, - 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, 0xb9a0, 0x0016, 0x080c, - 0x30be, 0x080c, 0x9fea, 0x001e, 0x080c, 0x3190, 0x00de, 0x0804, - 0xad1b, 0x00de, 0x080c, 0x54ef, 0x1170, 0x6014, 0x9005, 0x1158, - 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, - 0x4bb4, 0x004e, 0x003e, 0x00d6, 0x6010, 0x2058, 0x080c, 0x643e, - 0x080c, 0xaac9, 0x00de, 0x080c, 0xaf63, 0x1588, 0x6010, 0x2058, - 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, 0x62f4, 0x0096, - 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, - 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xc333, - 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130, 0xa807, - 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x009e, 0x080c, 0x30be, - 0x6020, 0x9086, 0x000a, 0x0138, 0x080c, 0x9fea, 0x0020, 0x080c, - 0xa9a7, 0x080c, 0xac59, 0x001e, 0x002e, 0x00ee, 0x00be, 0x0005, - 0x2011, 0x1823, 0x2204, 0x9086, 0x0014, 0x1160, 0x2001, 0x0002, - 0x080c, 0x62f4, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x8640, - 0x0804, 0x8b8f, 0x0804, 0xac59, 0x2030, 0x2011, 0x1823, 0x2204, - 0x9086, 0x0004, 0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, 0x0007, - 0x080c, 0x62f4, 0x0804, 0x9fea, 0x0804, 0xac59, 0x0002, 0xaa88, - 0xad5e, 0xaa88, 0xad9f, 0xaa88, 0xae4a, 0xad53, 0xaa8b, 0xaa88, - 0xae5c, 0xaa88, 0xae6c, 0x6604, 0x9686, 0x0003, 0x0904, 0xac6e, - 0x96b6, 0x001e, 0x1110, 0x080c, 0x9fea, 0x0005, 0x00b6, 0x00d6, - 0x00c6, 0x080c, 0xae7c, 0x11a0, 0x9006, 0x080c, 0x62e0, 0x080c, - 0x3095, 0x080c, 0xc46e, 0x2001, 0x0002, 0x080c, 0x62f4, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x8640, 0x080c, 0x8b8f, 0x0418, - 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2058, - 0xb840, 0x9084, 0x00ff, 0x9005, 0x0180, 0x8001, 0xb842, 0x601b, - 0x000a, 0x0088, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x908e, - 0x1900, 0x0148, 0x908e, 0x1e00, 0x0990, 0x080c, 0x3095, 0x080c, - 0xc46e, 0x080c, 0xac59, 0x00ce, 0x00de, 0x00be, 0x0005, 0x0096, - 0x00b6, 0x0026, 0x9016, 0x080c, 0xae8a, 0x00d6, 0x2069, 0x1956, - 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, - 0x1138, 0x2069, 0x181f, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, - 0x00de, 0x0088, 0x9006, 0x080c, 0x62e0, 0x2001, 0x0002, 0x080c, - 0x62f4, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x8640, 0x080c, - 0x8b8f, 0x0804, 0xae1a, 0x080c, 0xbd4e, 0x01b0, 0x6014, 0x2048, - 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, 0x0016, 0x2001, - 0x0002, 0x080c, 0xc390, 0x00b0, 0x6014, 0x2048, 0xa864, 0xd0fc, - 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e, 0x2004, 0xd0dc, - 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x1110, - 0x9006, 0x0c38, 0x080c, 0xa9a7, 0x2009, 0x026e, 0x2134, 0x96b4, - 0x00ff, 0x9686, 0x0005, 0x0510, 0x9686, 0x000b, 0x01c8, 0x2009, - 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, 0x0009, 0x01b0, - 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0180, 0x2001, 0x0004, - 0x080c, 0x62f4, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, 0x0010, - 0x080c, 0xac59, 0x002e, 0x00be, 0x009e, 0x0005, 0x9286, 0x0139, - 0x0160, 0x6014, 0x2048, 0x080c, 0xbd4e, 0x0140, 0xa864, 0x9086, - 0x0139, 0x0118, 0xa868, 0xd0fc, 0x0108, 0x0c50, 0x6010, 0x2058, - 0xb840, 0x9084, 0x00ff, 0x9005, 0x0138, 0x8001, 0xb842, 0x601b, - 0x000a, 0x6007, 0x0016, 0x08f0, 0xb8a0, 0x9086, 0x007e, 0x1138, - 0x00e6, 0x2071, 0x1800, 0x080c, 0x5dc2, 0x00ee, 0x0010, 0x080c, - 0x3095, 0x0870, 0x2001, 0x0004, 0x080c, 0x62f4, 0x04d9, 0x1140, - 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x8640, 0x0804, 0x8b8f, - 0x080c, 0xa9a7, 0x0804, 0xac59, 0x0469, 0x1160, 0x2001, 0x0008, - 0x080c, 0x62f4, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x8640, - 0x0804, 0x8b8f, 0x0804, 0xac59, 0x00e9, 0x1160, 0x2001, 0x000a, - 0x080c, 0x62f4, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x8640, - 0x0804, 0x8b8f, 0x0804, 0xac59, 0x2009, 0x026e, 0x2104, 0x9086, - 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, - 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6, 0x00c6, 0x0016, - 0x6110, 0x2158, 0x080c, 0x63b2, 0x001e, 0x00ce, 0x00be, 0x0005, - 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, 0x2058, - 0x2009, 0x1836, 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0xaf35, - 0x0560, 0x2009, 0x1836, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x66c5, - 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xd837, 0x2001, - 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, - 0x080c, 0x3060, 0x00e6, 0x2071, 0x1800, 0x080c, 0x2e73, 0x00ee, - 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, 0x080c, 0x3190, - 0x8108, 0x1f04, 0xaece, 0x015e, 0x00ce, 0x080c, 0xae8d, 0x2071, - 0x0260, 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, 0x1836, 0x200c, - 0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, 0xd0dc, - 0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1836, 0x2102, 0x9184, - 0x0050, 0x9086, 0x0050, 0x05d0, 0x2079, 0x0100, 0x2e04, 0x9084, - 0x00ff, 0x2069, 0x181e, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, - 0x2069, 0x181f, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0x9084, - 0xff00, 0x001e, 0x9105, 0x2009, 0x182b, 0x200a, 0x2200, 0x9084, - 0x00ff, 0x2008, 0x080c, 0x26b6, 0x080c, 0x717e, 0x0170, 0x2071, - 0x0260, 0x2069, 0x195c, 0x7048, 0x206a, 0x704c, 0x6806, 0x7050, - 0x680a, 0x7054, 0x680e, 0x080c, 0xc164, 0x0040, 0x2001, 0x0006, - 0x080c, 0x62f4, 0x080c, 0x30be, 0x080c, 0x9fea, 0x001e, 0x003e, - 0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x0096, 0x0026, 0x0036, - 0x00e6, 0x0156, 0x2019, 0x182b, 0x231c, 0x83ff, 0x01f0, 0x2071, - 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205, - 0x9306, 0x1198, 0x2011, 0x0276, 0x20a9, 0x0004, 0x2b48, 0x2019, - 0x000a, 0x080c, 0xb017, 0x1148, 0x2011, 0x027a, 0x20a9, 0x0004, - 0x2019, 0x0006, 0x080c, 0xb017, 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, 0x19cb, 0x252c, 0x2021, - 0x19d1, 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7250, 0x7070, - 0x9202, 0x1a04, 0xafef, 0x080c, 0xd868, 0x0904, 0xafe8, 0x6720, - 0x9786, 0x0007, 0x0904, 0xafe8, 0x2500, 0x9c06, 0x0904, 0xafe8, - 0x2400, 0x9c06, 0x05e8, 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, - 0x9005, 0x0130, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1580, - 0x00c6, 0x6000, 0x9086, 0x0004, 0x1110, 0x080c, 0x192c, 0x9786, - 0x000a, 0x0148, 0x080c, 0xbf56, 0x1130, 0x00ce, 0x080c, 0xa9a7, - 0x080c, 0xa01c, 0x00e8, 0x6014, 0x2048, 0x080c, 0xbd4e, 0x01a8, - 0x9786, 0x0003, 0x1530, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, - 0x0096, 0xa878, 0x2048, 0x080c, 0x0fe9, 0x009e, 0xab7a, 0xa877, - 0x0000, 0x080c, 0x6a15, 0x080c, 0xbf39, 0x080c, 0xa01c, 0x00ce, - 0x9ce0, 0x0018, 0x7064, 0x9c02, 0x1210, 0x0804, 0xaf96, 0x012e, - 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x009e, 0x00ee, - 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, 0xd7e2, 0x0c30, 0x9786, - 0x000a, 0x09e0, 0x0880, 0x220c, 0x2304, 0x9106, 0x1130, 0x8210, - 0x8318, 0x1f04, 0xb003, 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, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0df6, 0x080c, 0xbf45, - 0x0120, 0x080c, 0xbf56, 0x0168, 0x0028, 0x080c, 0x30be, 0x080c, - 0xbf56, 0x0138, 0x080c, 0x8a83, 0x080c, 0x9fea, 0x080c, 0x8b8f, - 0x0005, 0x080c, 0xa9a7, 0x0cb0, 0x9182, 0x0054, 0x1220, 0x9182, - 0x0040, 0x0208, 0x000a, 0x0005, 0xb078, 0xb078, 0xb078, 0xb078, - 0xb078, 0xb078, 0xb078, 0xb078, 0xb078, 0xb078, 0xb078, 0xb07a, - 0xb07a, 0xb07a, 0xb07a, 0xb078, 0xb078, 0xb078, 0xb07a, 0xb078, - 0x080c, 0x0df6, 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, - 0x85f8, 0x0126, 0x2091, 0x8000, 0x080c, 0x8b8f, 0x012e, 0x0005, - 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0040, 0x0804, 0xb112, - 0x9186, 0x0027, 0x1520, 0x080c, 0x8a83, 0x080c, 0x3095, 0x080c, - 0xc46e, 0x0096, 0x6114, 0x2148, 0x080c, 0xbd4e, 0x0198, 0x080c, - 0xbf56, 0x1118, 0x080c, 0xa9a7, 0x0068, 0xa867, 0x0103, 0xa87b, - 0x0029, 0xa877, 0x0000, 0xa97c, 0xc1c5, 0xa97e, 0x080c, 0x6a22, - 0x080c, 0xbf39, 0x009e, 0x080c, 0x9fea, 0x0804, 0x8b8f, 0x9186, - 0x0014, 0x1120, 0x6004, 0x9082, 0x0040, 0x00b8, 0x9186, 0x0046, - 0x0150, 0x9186, 0x0045, 0x0138, 0x9186, 0x0053, 0x0120, 0x9186, - 0x0048, 0x190c, 0x0df6, 0x080c, 0xc47f, 0x0130, 0x6000, 0x9086, - 0x0002, 0x1110, 0x0804, 0xb150, 0x0005, 0x0002, 0xb0ec, 0xb0ea, - 0xb0ea, 0xb0ea, 0xb0ea, 0xb0ea, 0xb0ea, 0xb0ea, 0xb0ea, 0xb0ea, - 0xb0ea, 0xb107, 0xb107, 0xb107, 0xb107, 0xb0ea, 0xb107, 0xb0ea, - 0xb107, 0xb0ea, 0x080c, 0x0df6, 0x080c, 0x8a83, 0x0096, 0x6114, - 0x2148, 0x080c, 0xbd4e, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, - 0xa877, 0x0000, 0xa880, 0xc0ec, 0xa882, 0x080c, 0x6a22, 0x080c, - 0xbf39, 0x009e, 0x080c, 0x9fea, 0x080c, 0x8b8f, 0x0005, 0x080c, - 0x8a83, 0x080c, 0xbf56, 0x090c, 0xa9a7, 0x080c, 0x9fea, 0x080c, - 0x8b8f, 0x0005, 0x0002, 0xb129, 0xb127, 0xb127, 0xb127, 0xb127, - 0xb127, 0xb127, 0xb127, 0xb127, 0xb127, 0xb127, 0xb140, 0xb140, - 0xb140, 0xb140, 0xb127, 0xb14a, 0xb127, 0xb140, 0xb127, 0x080c, - 0x0df6, 0x0096, 0x080c, 0x8a83, 0x6014, 0x2048, 0x2001, 0x1962, - 0x2004, 0x6042, 0xa97c, 0xd1ac, 0x0140, 0x6003, 0x0004, 0xa87c, - 0x9085, 0x0400, 0xa87e, 0x009e, 0x0005, 0x6003, 0x0002, 0x0cb8, - 0x080c, 0x8a83, 0x080c, 0xc471, 0x080c, 0xc476, 0x6003, 0x000f, - 0x0804, 0x8b8f, 0x080c, 0x8a83, 0x080c, 0x9fea, 0x0804, 0x8b8f, - 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, - 0xb16c, 0xb16c, 0xb16c, 0xb16c, 0xb16c, 0xb16e, 0xb24e, 0xb16c, - 0xb282, 0xb16c, 0xb16c, 0xb16c, 0xb16c, 0xb16c, 0xb16c, 0xb16c, - 0xb16c, 0xb16c, 0xb16c, 0xb282, 0x080c, 0x0df6, 0x00b6, 0x0096, - 0x6114, 0x2148, 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1528, 0x6010, - 0x2058, 0xb800, 0xd0bc, 0x1904, 0xb23d, 0xa87b, 0x0000, 0xa867, - 0x0103, 0xae76, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, - 0x190c, 0xb41b, 0x080c, 0x683c, 0x6210, 0x2258, 0xba3c, 0x82ff, - 0x0110, 0x8211, 0xba3e, 0x7044, 0xd0e4, 0x1904, 0xb21e, 0x080c, - 0x9fea, 0x009e, 0x00be, 0x0005, 0x968c, 0x0c00, 0x0150, 0x6010, - 0x2058, 0xb800, 0xd0bc, 0x1904, 0xb222, 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, 0xb175, - 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, - 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, - 0xb915, 0x003e, 0xd6cc, 0x0904, 0xb18a, 0x7154, 0xa98a, 0x81ff, - 0x0904, 0xb18a, 0x9192, 0x0021, 0x1278, 0x8304, 0x9098, 0x0018, - 0x2011, 0x0029, 0x080c, 0xb915, 0x2011, 0x0205, 0x2013, 0x0000, - 0x080c, 0xc3fc, 0x0804, 0xb18a, 0xa868, 0xd0fc, 0x0120, 0x2009, - 0x0020, 0xa98a, 0x0c50, 0x00a6, 0x2950, 0x080c, 0xb8b4, 0x00ae, - 0x080c, 0xc3fc, 0x080c, 0xb905, 0x0804, 0xb18c, 0x080c, 0xc04e, - 0x0804, 0xb199, 0xa87c, 0xd0ac, 0x0904, 0xb1a5, 0xa880, 0xd0bc, - 0x1904, 0xb1a5, 0x9684, 0x0400, 0x0130, 0xa838, 0xab34, 0x9305, - 0x0904, 0xb1a5, 0x00b8, 0x7348, 0xa838, 0x9306, 0x1198, 0x734c, - 0xa834, 0x931e, 0x0904, 0xb1a5, 0x0068, 0xa87c, 0xd0ac, 0x0904, - 0xb17d, 0xa838, 0xa934, 0x9105, 0x0904, 0xb17d, 0xa880, 0xd0bc, - 0x1904, 0xb17d, 0x080c, 0xc088, 0x0804, 0xb199, 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, 0x1a7e, 0x080c, 0x865d, 0x080c, 0x8c6c, - 0x009e, 0x0005, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xb29f, 0xb29f, 0xb29f, 0xb29f, 0xb29f, - 0xb2a1, 0xb337, 0xb29f, 0xb29f, 0xb34e, 0xb3de, 0xb29f, 0xb29f, - 0xb29f, 0xb29f, 0xb3f3, 0xb29f, 0xb29f, 0xb29f, 0xb29f, 0x080c, - 0x0df6, 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, 0xb332, 0x9694, 0xff00, 0x9284, 0x0c00, - 0x0120, 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, - 0xb332, 0x080c, 0x1037, 0x090c, 0x0df6, 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, 0xb915, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, - 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, - 0x0029, 0x080c, 0xb915, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, - 0xb068, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, - 0x080c, 0xb8b4, 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, 0x1a7e, 0x0804, 0x95e7, 0x6003, 0x0002, - 0x6004, 0x9086, 0x0040, 0x11c8, 0x0096, 0x6014, 0x2048, 0xa87c, - 0xd0ac, 0x0160, 0x601c, 0xd084, 0x1130, 0x00f6, 0x2c00, 0x2078, - 0x080c, 0x1651, 0x00fe, 0x6003, 0x0004, 0x0010, 0x6003, 0x0002, - 0x009e, 0x080c, 0x8a83, 0x080c, 0x8b8f, 0x0096, 0x2001, 0x1962, - 0x2004, 0x6042, 0x080c, 0x8b3f, 0x080c, 0x8c6c, 0x6114, 0x2148, - 0xa97c, 0xd1e4, 0x0904, 0xb3d9, 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, 0x0fe9, - 0x001e, 0x0458, 0x0016, 0x080c, 0x0fe9, 0x009e, 0xa87c, 0xc0cc, - 0xa87e, 0xa974, 0x0016, 0x080c, 0xb905, 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, 0x683c, 0x001e, 0xd1e4, 0x1120, 0x080c, - 0x9fea, 0x009e, 0x0005, 0x080c, 0xc04e, 0x0cd8, 0x6004, 0x9086, - 0x0040, 0x1120, 0x080c, 0x8a83, 0x080c, 0x8b8f, 0x2019, 0x0001, - 0x080c, 0x98b1, 0x6003, 0x0002, 0x080c, 0xc476, 0x080c, 0x8b3f, - 0x080c, 0x8c6c, 0x0005, 0x6004, 0x9086, 0x0040, 0x1120, 0x080c, - 0x8a83, 0x080c, 0x8b8f, 0x2019, 0x0001, 0x080c, 0x98b1, 0x080c, - 0x8b3f, 0x080c, 0x3095, 0x080c, 0xc46e, 0x0096, 0x6114, 0x2148, - 0x080c, 0xbd4e, 0x0150, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, - 0x0000, 0x080c, 0x6a22, 0x080c, 0xbf39, 0x009e, 0x080c, 0x9fea, - 0x080c, 0x8c6c, 0x0005, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, - 0x0007, 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, - 0x2009, 0x1a55, 0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, - 0xa88e, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, - 0x000a, 0x0005, 0xb44e, 0xb44e, 0xb44e, 0xb44e, 0xb44e, 0xb450, - 0xb44e, 0xb44e, 0xb4f6, 0xb44e, 0xb44e, 0xb44e, 0xb44e, 0xb44e, - 0xb44e, 0xb44e, 0xb44e, 0xb44e, 0xb44e, 0xb628, 0x080c, 0x0df6, - 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, 0xb4ef, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, - 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xb4ef, - 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676, - 0x0c38, 0x080c, 0x1037, 0x090c, 0x0df6, 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, 0xb915, 0x003e, - 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, - 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xb915, - 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, - 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, 0xb8b4, 0x080c, - 0x18f8, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x2001, 0x1962, - 0x2004, 0x6042, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, - 0x1118, 0xa87c, 0xc0dc, 0xa87e, 0x6003, 0x0002, 0xa97c, 0xd1e4, - 0x0904, 0xb623, 0x6043, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xb5f2, 0xa978, 0xa868, - 0xd0fc, 0x0904, 0xb5b3, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, - 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, - 0xb580, 0x9086, 0x0028, 0x1904, 0xb56c, 0xa87b, 0x001c, 0xb07b, - 0x001c, 0x0804, 0xb588, 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, 0x0fe9, 0x009e, - 0x080c, 0xc088, 0x0804, 0xb623, 0xd1dc, 0x0158, 0xa87b, 0x0015, - 0xb07b, 0x0015, 0x080c, 0xc31c, 0x0118, 0xb174, 0xc1dc, 0xb176, - 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xb41b, - 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, 0xc3fc, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0fe9, - 0x001e, 0x0804, 0xb61f, 0x0016, 0x00a6, 0x2150, 0xb174, 0x9184, - 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, 0x0028, 0x1128, 0xa87b, - 0x001c, 0xb07b, 0x001c, 0x00e0, 0xd1dc, 0x0158, 0xa87b, 0x0015, - 0xb07b, 0x0015, 0x080c, 0xc31c, 0x0118, 0xb174, 0xc1dc, 0xb176, - 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xb41b, - 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa87c, 0xb07e, 0x00ae, 0x080c, - 0x0fe9, 0x009e, 0x080c, 0xc3fc, 0xa974, 0x0016, 0x080c, 0xb905, - 0x001e, 0x0468, 0xa867, 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, - 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00d0, - 0xd1dc, 0x0148, 0xa87b, 0x0015, 0x080c, 0xc31c, 0x0118, 0xa974, - 0xc1dc, 0xa976, 0x0078, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0050, - 0xa87b, 0x0000, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, - 0x190c, 0xb41b, 0xa974, 0x0016, 0x080c, 0x683c, 0x001e, 0xd1e4, - 0x1120, 0x080c, 0x9fea, 0x009e, 0x0005, 0x080c, 0xc04e, 0x0cd8, - 0x6114, 0x0096, 0x2148, 0xa97c, 0xd1e4, 0x190c, 0x1918, 0x009e, - 0x0005, 0x080c, 0x8a83, 0x0010, 0x080c, 0x8b3f, 0x080c, 0xbd4e, - 0x01f0, 0x0096, 0x6114, 0x2148, 0x080c, 0xbf56, 0x1118, 0x080c, - 0xa9a7, 0x00a0, 0xa867, 0x0103, 0x2009, 0x180c, 0x210c, 0xd18c, - 0x11b8, 0xd184, 0x1190, 0x6108, 0xa97a, 0x918e, 0x0029, 0x1110, - 0x080c, 0xdae1, 0xa877, 0x0000, 0x080c, 0x6a22, 0x009e, 0x080c, - 0x9fea, 0x080c, 0x8b8f, 0x0804, 0x8c6c, 0xa87b, 0x0004, 0x0c90, - 0xa87b, 0x0004, 0x0c78, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xb67f, 0xb67f, 0xb67f, 0xb67f, 0xb67f, - 0xb681, 0xb67f, 0xb67f, 0xb67f, 0xb67f, 0xb67f, 0xb67f, 0xb67f, - 0xb67f, 0xb67f, 0xb67f, 0xb67f, 0xb67f, 0xb67f, 0xb67f, 0x080c, - 0x0df6, 0x080c, 0x54e3, 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, 0x6a22, 0x009e, 0x0804, 0x9fea, 0x9182, 0x0085, 0x0002, - 0xb6b7, 0xb6b5, 0xb6b5, 0xb6c3, 0xb6b5, 0xb6b5, 0xb6b5, 0xb6b5, - 0xb6b5, 0xb6b5, 0xb6b5, 0xb6b5, 0xb6b5, 0x080c, 0x0df6, 0x6003, - 0x0001, 0x6106, 0x080c, 0x85f8, 0x0126, 0x2091, 0x8000, 0x080c, - 0x8b8f, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, - 0x0260, 0x7224, 0x6216, 0x7220, 0x080c, 0xbd3c, 0x01f8, 0x2268, - 0x6800, 0x9086, 0x0000, 0x01d0, 0x6010, 0x6d10, 0x952e, 0x11b0, - 0x00c6, 0x2d60, 0x00d6, 0x080c, 0xb976, 0x00de, 0x00ce, 0x0158, - 0x702c, 0xd084, 0x1118, 0x080c, 0xb940, 0x0010, 0x6803, 0x0002, - 0x6007, 0x0086, 0x0028, 0x080c, 0xb962, 0x0d90, 0x6007, 0x0087, - 0x6003, 0x0001, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x7220, 0x080c, - 0xbd3c, 0x0178, 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x0140, 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, 0xc088, - 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, - 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0df6, 0x908a, 0x0092, - 0x1a0c, 0x0df6, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, 0x0120, - 0x9186, 0x0014, 0x190c, 0x0df6, 0x080c, 0x8a83, 0x0096, 0x6014, - 0x2048, 0x080c, 0xbd4e, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0029, 0x080c, 0x6a22, 0x009e, 0x080c, 0xa01c, 0x0804, - 0x8b8f, 0xb746, 0xb748, 0xb748, 0xb746, 0xb746, 0xb746, 0xb746, - 0xb746, 0xb746, 0xb746, 0xb746, 0xb746, 0xb746, 0x080c, 0x0df6, - 0x080c, 0x8a83, 0x080c, 0xa01c, 0x080c, 0x8b8f, 0x0005, 0x9186, - 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x04b8, 0x9186, - 0x0027, 0x11f8, 0x080c, 0x8a83, 0x080c, 0x3095, 0x080c, 0xc46e, - 0x0096, 0x6014, 0x2048, 0x080c, 0xbd4e, 0x0150, 0xa867, 0x0103, - 0xa877, 0x0000, 0xa87b, 0x0029, 0x080c, 0x6a22, 0x080c, 0xbf39, - 0x009e, 0x080c, 0x9fea, 0x080c, 0x8b8f, 0x0005, 0x080c, 0xa083, - 0x0ce0, 0x9186, 0x0014, 0x1dd0, 0x080c, 0x8a83, 0x0096, 0x6014, - 0x2048, 0x080c, 0xbd4e, 0x0d60, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, 0x08f0, 0x0002, 0xb79e, - 0xb79c, 0xb79c, 0xb79c, 0xb79c, 0xb79c, 0xb7b6, 0xb79c, 0xb79c, - 0xb79c, 0xb79c, 0xb79c, 0xb79c, 0x080c, 0x0df6, 0x080c, 0x8a83, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x2001, 0x1960, 0x0010, 0x2001, 0x1961, 0x2004, - 0x601a, 0x6003, 0x000c, 0x080c, 0x8b8f, 0x0005, 0x080c, 0x8a83, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x2001, 0x1960, 0x0010, 0x2001, 0x1961, 0x2004, - 0x601a, 0x6003, 0x000e, 0x080c, 0x8b8f, 0x0005, 0x9182, 0x0092, - 0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, 0xa083, 0xb7e4, - 0xb7e4, 0xb7e4, 0xb7e4, 0xb7e6, 0xb833, 0xb7e4, 0xb7e4, 0xb7e4, - 0xb7e4, 0xb7e4, 0xb7e4, 0xb7e4, 0x080c, 0x0df6, 0x0096, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, - 0x009e, 0x0804, 0xb847, 0x080c, 0xbd4e, 0x1118, 0x080c, 0xbf39, - 0x0068, 0x6014, 0x2048, 0xa87c, 0xd0e4, 0x1110, 0x080c, 0xbf39, - 0xa867, 0x0103, 0x080c, 0xc439, 0x080c, 0x6a22, 0x00d6, 0x2c68, - 0x080c, 0x9f94, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, - 0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, - 0x613e, 0x6910, 0x6112, 0x080c, 0xc1ca, 0x6954, 0x6156, 0x6023, - 0x0001, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x2d60, 0x00de, 0x080c, - 0x9fea, 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, 0xc3cf, 0x11f0, 0x080c, 0x9f94, 0x01d8, 0x6106, - 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, - 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, - 0x693c, 0x613e, 0x6954, 0x6156, 0x080c, 0xc1ca, 0x080c, 0x85f8, - 0x080c, 0x8b8f, 0x2d60, 0x00de, 0x0804, 0x9fea, 0x0096, 0x6014, - 0x2048, 0x080c, 0xbd4e, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, - 0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, - 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xc04a, 0xa877, - 0x0000, 0x080c, 0x6a22, 0x080c, 0xbf39, 0x009e, 0x0804, 0x9fea, - 0x0016, 0x0096, 0x6014, 0x2048, 0x080c, 0xbd4e, 0x0140, 0xa867, - 0x0103, 0xa87b, 0x0028, 0xa877, 0x0000, 0x080c, 0x6a22, 0x009e, - 0x001e, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, - 0x0027, 0x0118, 0x080c, 0xa083, 0x0030, 0x080c, 0x8a83, 0x080c, - 0xa01c, 0x080c, 0x8b8f, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, - 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, - 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, - 0x080c, 0xb915, 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c, - 0x0fe9, 0x080c, 0x1037, 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, 0x6a22, 0x2a48, - 0x0cb8, 0x080c, 0x6a22, 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, 0xbd4e, - 0x0150, 0x2001, 0x0006, 0xa980, 0xc1d5, 0x080c, 0x6c6b, 0x080c, - 0x6a15, 0x080c, 0xbf39, 0x009e, 0x080c, 0xa01c, 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, - 0xb9b1, 0xb9b1, 0xb9ac, 0xb9d3, 0xb99f, 0xb9ac, 0xb9d3, 0xb9ac, - 0xb9ac, 0xb99f, 0xb9ac, 0xb9ac, 0xb9ac, 0xb99f, 0xb99f, 0x080c, - 0x0df6, 0x0036, 0x2019, 0x0010, 0x080c, 0xd38f, 0x6023, 0x0006, - 0x6003, 0x0007, 0x003e, 0x0005, 0x9006, 0x0005, 0x9085, 0x0001, - 0x0005, 0x0096, 0x86ff, 0x11d8, 0x6014, 0x2048, 0x080c, 0xbd4e, - 0x01c0, 0xa864, 0x9086, 0x0139, 0x1128, 0xa87b, 0x0005, 0xa883, - 0x0000, 0x0028, 0x900e, 0x2001, 0x0005, 0x080c, 0x6c6b, 0x080c, - 0xc04a, 0x080c, 0x6a15, 0x080c, 0xa01c, 0x9085, 0x0001, 0x009e, - 0x0005, 0x9006, 0x0ce0, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0df6, - 0x0002, 0xb9e9, 0xba19, 0xb9eb, 0xba3a, 0xba14, 0xb9e9, 0xb9ac, - 0xb9b1, 0xb9b1, 0xb9ac, 0xb9ac, 0xb9ac, 0xb9ac, 0xb9ac, 0xb9ac, - 0xb9ac, 0x080c, 0x0df6, 0x86ff, 0x1520, 0x6020, 0x9086, 0x0006, - 0x0500, 0x0096, 0x6014, 0x2048, 0x080c, 0xbd4e, 0x0168, 0xa87c, - 0xd0cc, 0x0140, 0x0096, 0xc0cc, 0xa87e, 0xa878, 0x2048, 0x080c, - 0x0fe9, 0x009e, 0x080c, 0xc04a, 0x009e, 0x080c, 0xc413, 0x6007, - 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x85f8, 0x080c, - 0x8b8f, 0x9085, 0x0001, 0x0005, 0x0066, 0x080c, 0x192c, 0x006e, - 0x0890, 0x00e6, 0x2071, 0x19c2, 0x7024, 0x9c06, 0x1120, 0x080c, - 0x983b, 0x00ee, 0x0840, 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, - 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x995f, - 0x009e, 0x008e, 0x0010, 0x080c, 0x9738, 0x00ee, 0x1904, 0xb9eb, - 0x0804, 0xb9ac, 0x0036, 0x00e6, 0x2071, 0x19c2, 0x703c, 0x9c06, - 0x1138, 0x901e, 0x080c, 0x98b1, 0x00ee, 0x003e, 0x0804, 0xb9eb, - 0x080c, 0x9a8f, 0x00ee, 0x003e, 0x1904, 0xb9eb, 0x0804, 0xb9ac, - 0x00c6, 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xba6d, - 0xbb1d, 0xbc87, 0xba77, 0xa01c, 0xba6d, 0xd381, 0xc47b, 0xbb1d, - 0xba66, 0xbd13, 0xba66, 0xba66, 0xba66, 0xba66, 0x080c, 0x0df6, - 0x080c, 0xbf56, 0x1110, 0x080c, 0xa9a7, 0x0005, 0x080c, 0x8a83, - 0x080c, 0x8b8f, 0x0804, 0x9fea, 0x601b, 0x0001, 0x0005, 0x080c, - 0xbd4e, 0x0130, 0x6014, 0x0096, 0x2048, 0x2c00, 0xa896, 0x009e, - 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0df6, 0x0002, 0xba96, 0xba98, - 0xbabc, 0xbad0, 0xbaf6, 0xba96, 0xba6d, 0xba6d, 0xba6d, 0xbad0, - 0xbad0, 0xba96, 0xba96, 0xba96, 0xba96, 0xbada, 0x080c, 0x0df6, - 0x00e6, 0x6014, 0x0096, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, - 0x2071, 0x19c2, 0x7024, 0x9c06, 0x01a0, 0x080c, 0x9738, 0x080c, - 0xc413, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, - 0x1961, 0x2004, 0x601a, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x00ee, - 0x0005, 0x601b, 0x0001, 0x0cd8, 0x0096, 0x6014, 0x2048, 0xa880, - 0xc0b5, 0xa882, 0x009e, 0x080c, 0xc413, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x0005, - 0x0096, 0x601b, 0x0001, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, - 0x009e, 0x0005, 0x080c, 0x54e3, 0x01b8, 0x6014, 0x0096, 0x904d, - 0x0190, 0xa864, 0xa867, 0x0103, 0xa87b, 0x0006, 0x9086, 0x0139, - 0x1150, 0xa867, 0x0139, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa89b, - 0x0004, 0x080c, 0x6a22, 0x009e, 0x0804, 0x9fea, 0x6014, 0x0096, - 0x904d, 0x01f0, 0xa97c, 0xd1e4, 0x01d8, 0x2001, 0x180f, 0x2004, - 0xd0c4, 0x0110, 0x009e, 0x0005, 0xa884, 0x009e, 0x8003, 0x800b, - 0x810b, 0x9108, 0x611a, 0x00c6, 0x080c, 0x2165, 0x00ce, 0x6000, - 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0xa068, 0x0005, - 0x009e, 0x080c, 0x192c, 0x0804, 0xbabc, 0x6000, 0x908a, 0x0010, - 0x1a0c, 0x0df6, 0x000b, 0x0005, 0xbb34, 0xba74, 0xbb36, 0xbb34, - 0xbb36, 0xbb36, 0xba6e, 0xbb34, 0xba68, 0xba68, 0xbb34, 0xbb34, - 0xbb34, 0xbb34, 0xbb34, 0xbb34, 0x080c, 0x0df6, 0x6010, 0x00b6, - 0x2058, 0xb804, 0x9084, 0x00ff, 0x00be, 0x908a, 0x000c, 0x1a0c, - 0x0df6, 0x00b6, 0x0013, 0x00be, 0x0005, 0xbb51, 0xbc1e, 0xbb53, - 0xbb93, 0xbb53, 0xbb93, 0xbb53, 0xbb61, 0xbb51, 0xbb93, 0xbb51, - 0xbb82, 0x080c, 0x0df6, 0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, - 0x0004, 0x05a8, 0x908e, 0x0002, 0x0590, 0x908e, 0x0052, 0x0904, - 0xbc1a, 0x6004, 0x080c, 0xbf56, 0x0904, 0xbc37, 0x908e, 0x0004, - 0x1110, 0x080c, 0x30be, 0x908e, 0x0021, 0x0904, 0xbc3b, 0x908e, - 0x0022, 0x0904, 0xbc82, 0x908e, 0x003d, 0x0904, 0xbc3b, 0x908e, - 0x0039, 0x0904, 0xbc3f, 0x908e, 0x0035, 0x0904, 0xbc3f, 0x908e, - 0x001e, 0x0178, 0x908e, 0x0001, 0x1140, 0x6010, 0x2058, 0xb804, - 0x9084, 0x00ff, 0x9086, 0x0006, 0x0110, 0x080c, 0x3095, 0x080c, - 0xa9a7, 0x0804, 0xa01c, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, - 0x0904, 0xbc0b, 0x9186, 0x0002, 0x1904, 0xbbe0, 0x2001, 0x1836, - 0x2004, 0xd08c, 0x11c8, 0x080c, 0x717e, 0x11b0, 0x080c, 0xc459, - 0x0138, 0x080c, 0x71a1, 0x1120, 0x080c, 0x707c, 0x0804, 0xbc6b, - 0x2001, 0x1957, 0x2003, 0x0001, 0x2001, 0x1800, 0x2003, 0x0001, - 0x080c, 0x709e, 0x0804, 0xbc6b, 0x6010, 0x2058, 0x2001, 0x1836, - 0x2004, 0xd0ac, 0x1904, 0xbc6b, 0xb8a0, 0x9084, 0xff80, 0x1904, - 0xbc6b, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, 0xb842, - 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, - 0x080c, 0x9f94, 0x0128, 0x2b00, 0x6012, 0x6023, 0x0001, 0x0458, - 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a0, 0x6010, 0x2058, - 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, 0x1836, 0x2104, 0xc085, - 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5dc2, 0x00ee, 0x080c, - 0xa9a7, 0x0030, 0x080c, 0xa9a7, 0x080c, 0x3095, 0x080c, 0xc46e, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x30be, 0x012e, 0x00ee, - 0x080c, 0xa01c, 0x0005, 0x2001, 0x0002, 0x080c, 0x62f4, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x8640, 0x080c, 0x8b8f, 0x00de, - 0x00ce, 0x0c80, 0x080c, 0x30be, 0x0804, 0xbb8f, 0x00c6, 0x00d6, - 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2058, 0xb840, 0x9084, - 0x00ff, 0x9005, 0x0904, 0xbbe0, 0x8001, 0xb842, 0x6003, 0x0001, - 0x080c, 0x8640, 0x080c, 0x8b8f, 0x00de, 0x00ce, 0x0898, 0x080c, - 0xa9a7, 0x0804, 0xbb91, 0x080c, 0xa9e3, 0x0804, 0xbb91, 0x00d6, - 0x2c68, 0x6104, 0x080c, 0xc3cf, 0x00de, 0x0118, 0x080c, 0x9fea, - 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, - 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c, 0x600a, - 0x2001, 0x1961, 0x2004, 0x601a, 0x602c, 0x2c08, 0x2060, 0x6024, - 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160, 0x080c, 0x85f8, - 0x080c, 0x8b8f, 0x0005, 0x00de, 0x00ce, 0x080c, 0xa9a7, 0x080c, - 0x3095, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x30be, 0x6017, - 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, 0x012e, - 0x00ee, 0x0005, 0x080c, 0xa41e, 0x1904, 0xbc37, 0x0005, 0x6000, - 0x908a, 0x0010, 0x1a0c, 0x0df6, 0x0096, 0x00d6, 0x001b, 0x00de, - 0x009e, 0x0005, 0xbca2, 0xbca2, 0xbca2, 0xbca2, 0xbca2, 0xbca2, - 0xbca2, 0xbca2, 0xbca2, 0xba6d, 0xbca2, 0xba74, 0xbca4, 0xba74, - 0xbcbe, 0xbca2, 0x080c, 0x0df6, 0x6004, 0x9086, 0x008b, 0x01b0, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, 0x1130, 0x602c, - 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, 0x6007, 0x008b, 0x6003, - 0x000d, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x0005, 0x080c, 0xc44d, - 0x0118, 0x080c, 0xc460, 0x0010, 0x080c, 0xc46e, 0x080c, 0xbf39, - 0x080c, 0xbd4e, 0x0570, 0x080c, 0x3095, 0x080c, 0xbd4e, 0x0168, - 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, - 0xa880, 0xc0ed, 0xa882, 0x080c, 0x6a22, 0x2c68, 0x080c, 0x9f94, - 0x0150, 0x6810, 0x6012, 0x080c, 0xc1ca, 0x00c6, 0x2d60, 0x080c, - 0xa01c, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023, 0x0001, - 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x8640, 0x080c, 0x8b8f, - 0x00c8, 0x080c, 0xc44d, 0x0138, 0x6034, 0x9086, 0x4000, 0x1118, - 0x080c, 0x3095, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, - 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x3095, 0x0868, - 0x080c, 0xa01c, 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0df6, - 0x0002, 0xbd29, 0xbd29, 0xbd2d, 0xbd2b, 0xbd37, 0xbd29, 0xbd29, - 0xa01c, 0xbd29, 0xbd29, 0xbd29, 0xbd29, 0xbd29, 0xbd29, 0xbd29, - 0xbd29, 0x080c, 0x0df6, 0x080c, 0x9a8f, 0x6114, 0x0096, 0x2148, - 0xa87b, 0x0006, 0x080c, 0x6a22, 0x009e, 0x0804, 0x9fea, 0x601c, - 0xd084, 0x190c, 0x192c, 0x0c88, 0x9284, 0x0007, 0x1158, 0x9282, - 0x1cd0, 0x0240, 0x2001, 0x1819, 0x2004, 0x9202, 0x1218, 0x9085, - 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0096, 0x0028, 0x0096, 0x0006, - 0x6014, 0x2048, 0x000e, 0x0006, 0x9984, 0xf000, 0x9086, 0xf000, - 0x0110, 0x080c, 0x10e2, 0x000e, 0x009e, 0x0005, 0x00e6, 0x00c6, - 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, 0x1cd0, 0x2071, - 0x1800, 0x7350, 0x7070, 0x9302, 0x1640, 0x6020, 0x9206, 0x11f8, - 0x080c, 0xc459, 0x0180, 0x9286, 0x0001, 0x1168, 0x6004, 0x9086, - 0x0004, 0x1148, 0x080c, 0x3095, 0x080c, 0xc46e, 0x00c6, 0x080c, - 0xa01c, 0x00ce, 0x0060, 0x080c, 0xc144, 0x0148, 0x080c, 0xbf56, - 0x1110, 0x080c, 0xa9a7, 0x00c6, 0x080c, 0x9fea, 0x00ce, 0x9ce0, - 0x0018, 0x7064, 0x9c02, 0x1208, 0x08a0, 0x012e, 0x000e, 0x003e, - 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0x9188, 0x1000, - 0x210c, 0x81ff, 0x0128, 0x2061, 0x1a88, 0x6112, 0x080c, 0x3095, - 0x9006, 0x0010, 0x9085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, - 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x9f94, 0x01b0, 0x6656, - 0x2b00, 0x6012, 0x080c, 0x54e3, 0x0118, 0x080c, 0xbe7d, 0x0168, - 0x080c, 0xc1ca, 0x6023, 0x0003, 0x2009, 0x004b, 0x080c, 0xa068, - 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, - 0x0126, 0x2091, 0x8000, 0xbaa0, 0x080c, 0xa03b, 0x0560, 0x6057, - 0x0000, 0x2b00, 0x6012, 0x080c, 0xc1ca, 0x6023, 0x0003, 0x0016, - 0x080c, 0x8782, 0x0076, 0x903e, 0x080c, 0x8670, 0x2c08, 0x080c, - 0xd556, 0x007e, 0x001e, 0xd184, 0x0128, 0x080c, 0x9fea, 0x9085, - 0x0001, 0x0070, 0x080c, 0x54e3, 0x0128, 0xd18c, 0x1170, 0x080c, - 0xbe7d, 0x0148, 0x2009, 0x004c, 0x080c, 0xa068, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2900, 0x6016, 0x0c90, - 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, 0x00c6, 0x0046, - 0x0016, 0x080c, 0x9f94, 0x2c78, 0x05a0, 0x7e56, 0x2b00, 0x7812, - 0x7823, 0x0003, 0x0016, 0x2021, 0x0005, 0x080c, 0xbe8f, 0x001e, - 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148, 0x2001, 0x195a, - 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0x9fea, 0x00d0, 0x2001, - 0x1959, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0x9fea, 0x0088, - 0x2f60, 0x080c, 0x54e3, 0x0138, 0xd18c, 0x1118, 0x04f1, 0x0148, - 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, 0x080c, 0xa068, 0x9085, - 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, - 0x0046, 0x080c, 0x9f94, 0x2c78, 0x0508, 0x7e56, 0x2b00, 0x7812, - 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, 0x0489, 0x009e, 0x2001, - 0x1958, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0x9fea, 0x0060, - 0x2f60, 0x080c, 0x54e3, 0x0120, 0xd18c, 0x1160, 0x0071, 0x0130, - 0x2009, 0x0052, 0x080c, 0xa068, 0x9085, 0x0001, 0x004e, 0x00ce, - 0x00fe, 0x0005, 0x2900, 0x7816, 0x0c98, 0x00c6, 0x080c, 0x49b7, - 0x00ce, 0x1120, 0x080c, 0x9fea, 0x9006, 0x0005, 0xa867, 0x0000, - 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, 0x0001, 0x0005, 0x0096, - 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x64d7, 0x0158, 0x2001, - 0xbe94, 0x0006, 0x900e, 0x2400, 0x080c, 0x6c6b, 0x080c, 0x6a22, - 0x000e, 0x0807, 0x2418, 0x080c, 0x8a1d, 0xbaa0, 0x0086, 0x2041, - 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x879a, 0x008e, 0x080c, - 0x8670, 0x2f08, 0x2648, 0x080c, 0xd556, 0xb93c, 0x81ff, 0x090c, - 0x886d, 0x080c, 0x8b8f, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0x9f94, 0x0190, 0x660a, 0x2b08, - 0x6112, 0x080c, 0xc1ca, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, - 0x001f, 0x080c, 0xa068, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xa03b, - 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, 0xc1ca, 0x6023, 0x0008, - 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, 0x1651, 0x00fe, 0x2009, - 0x0021, 0x080c, 0xa068, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, 0x0126, 0x0016, 0x2091, - 0x8000, 0x080c, 0x9f94, 0x0198, 0x660a, 0x2b08, 0x6112, 0x080c, - 0xc1ca, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, 0x0016, 0x080c, - 0xa068, 0x9085, 0x0001, 0x001e, 0x012e, 0x00ce, 0x0005, 0x9006, - 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xa03b, 0x0188, - 0x2b08, 0x6112, 0x080c, 0xc1ca, 0x6023, 0x0001, 0x2900, 0x6016, - 0x2009, 0x0000, 0x080c, 0xa068, 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, - 0xbd4e, 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, 0xa03b, 0x0198, 0x2b08, - 0x6112, 0x080c, 0xc1ca, 0x6023, 0x0001, 0x2900, 0x6016, 0x080c, - 0x3095, 0x2009, 0x0028, 0x080c, 0xa068, 0x9085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, 0x11a8, 0x2011, - 0x1823, 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6, 0x080c, 0xac41, - 0x00be, 0x080c, 0xae8d, 0x6003, 0x0001, 0x6007, 0x0029, 0x080c, - 0x8640, 0x080c, 0x8b8f, 0x0078, 0x6014, 0x0096, 0x2048, 0xa868, - 0x009e, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, 0xc390, 0x080c, - 0xa9a7, 0x080c, 0x9fea, 0x0005, 0x0096, 0x6014, 0x904d, 0x090c, - 0x0df6, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, - 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, 0x6a22, - 0x012e, 0x009e, 0x080c, 0x9fea, 0x0c30, 0x0096, 0x9186, 0x0016, - 0x1128, 0x2001, 0x0004, 0x080c, 0x62f4, 0x00e8, 0x9186, 0x0015, - 0x1510, 0x2011, 0x1823, 0x2204, 0x9086, 0x0014, 0x11e0, 0x6010, - 0x00b6, 0x2058, 0x080c, 0x643e, 0x00be, 0x080c, 0xaf63, 0x1198, - 0x6010, 0x00b6, 0x2058, 0xb890, 0x00be, 0x9005, 0x0160, 0x2001, - 0x0006, 0x080c, 0x62f4, 0x6014, 0x2048, 0xa868, 0xd0fc, 0x0170, - 0x080c, 0xa3f2, 0x0048, 0x6014, 0x2048, 0xa868, 0xd0fc, 0x0528, - 0x080c, 0xa9a7, 0x080c, 0x9fea, 0x009e, 0x0005, 0x6014, 0x6310, - 0x2358, 0x904d, 0x090c, 0x0df6, 0xa87b, 0x0000, 0xa883, 0x0000, - 0xa897, 0x4000, 0x900e, 0x080c, 0x65c3, 0x1108, 0xc185, 0xb800, - 0xd0bc, 0x0108, 0xc18d, 0xa99a, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6a22, 0x012e, 0x080c, 0x9fea, 0x08f8, 0x6014, 0x904d, 0x090c, - 0x0df6, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, - 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, 0x6a22, - 0x012e, 0x080c, 0x9fea, 0x0840, 0xa878, 0x9086, 0x0005, 0x1108, - 0x0009, 0x0005, 0xa880, 0xc0ad, 0xa882, 0x0005, 0x6043, 0x0000, - 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x85f8, - 0x080c, 0x8b8f, 0x0005, 0x00c6, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x0120, 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, - 0x0005, 0xba6d, 0xc07a, 0xc07a, 0xc07d, 0xd886, 0xd8a1, 0xd8a4, - 0xba6d, 0xba6d, 0xba6d, 0xba6d, 0xba6d, 0xba6d, 0xba6d, 0xba6d, - 0x080c, 0x0df6, 0xa001, 0xa001, 0x0005, 0x0096, 0x6014, 0x904d, - 0x0118, 0xa87c, 0xd0e4, 0x1110, 0x009e, 0x0010, 0x009e, 0x0005, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0550, 0x2001, - 0x1833, 0x2004, 0x9005, 0x1540, 0x00f6, 0x2c78, 0x080c, 0x9f94, - 0x0508, 0x7810, 0x6012, 0x080c, 0xc1ca, 0x7820, 0x9086, 0x0003, - 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, 0x7808, 0x603e, - 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, 0x6007, 0x0035, 0x6003, - 0x0001, 0x7954, 0x6156, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x2f60, - 0x00fe, 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1962, 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, 0x0fe9, - 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, 0x85f8, - 0x080c, 0x8b8f, 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, 0x195c, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, - 0x080c, 0x847e, 0x2001, 0x1960, 0x82ff, 0x1110, 0x2011, 0x0014, - 0x2202, 0x2001, 0x195e, 0x200c, 0x8000, 0x2014, 0x2071, 0x1946, - 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x847e, 0x2001, 0x1961, - 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1962, 0x9288, - 0x000a, 0x2102, 0x2001, 0x1a69, 0x2102, 0x2001, 0x0032, 0x080c, - 0x1580, 0x080c, 0x66aa, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, - 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, 0x1960, 0x2003, 0x0028, - 0x2001, 0x1961, 0x2003, 0x0014, 0x2071, 0x1946, 0x701b, 0x0000, - 0x701f, 0x07d0, 0x2001, 0x1962, 0x2009, 0x001e, 0x2102, 0x2001, - 0x1a69, 0x2102, 0x2001, 0x0032, 0x080c, 0x1580, 0x00ee, 0x001e, - 0x000e, 0x0005, 0x0096, 0x6058, 0x904d, 0x0110, 0x080c, 0x1069, - 0x009e, 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, - 0x9f94, 0x0180, 0x2b08, 0x6112, 0x0ca9, 0x6023, 0x0001, 0x2900, - 0x6016, 0x2009, 0x0033, 0x080c, 0xa068, 0x9085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x00e6, 0x00f6, 0x2071, - 0x1800, 0x9186, 0x0015, 0x1520, 0x708c, 0x9086, 0x0018, 0x0120, - 0x708c, 0x9086, 0x0014, 0x11e0, 0x6014, 0x2048, 0xaa3c, 0xd2e4, - 0x1160, 0x2c78, 0x080c, 0x8d93, 0x01d8, 0x7078, 0xaa50, 0x9206, - 0x1160, 0x707c, 0xaa54, 0x9206, 0x1140, 0x6210, 0x00b6, 0x2258, - 0xbaa0, 0x00be, 0x900e, 0x080c, 0x30de, 0x080c, 0xa3f2, 0x0020, - 0x080c, 0xa9a7, 0x080c, 0x9fea, 0x00fe, 0x00ee, 0x009e, 0x0005, - 0x705c, 0xaa54, 0x9206, 0x0d48, 0x0c80, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0x9f94, 0x0188, 0x2b08, 0x6112, 0x080c, 0xc1ca, - 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x004d, 0x080c, 0xa068, - 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, 0x9f94, 0x0180, 0x2b08, - 0x6112, 0x080c, 0xc1ca, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, - 0x080c, 0xa068, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x001e, - 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0066, - 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1568, - 0x718c, 0x6014, 0x2048, 0xa814, 0x8003, 0x9106, 0x1530, 0x20e1, - 0x0000, 0x2001, 0x197b, 0x2003, 0x0000, 0x6014, 0x2048, 0xa830, - 0x20a8, 0x8906, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e8, 0x9084, - 0xffc0, 0x9080, 0x001b, 0x20a0, 0x2001, 0x197b, 0x0016, 0x200c, - 0x080c, 0xca75, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c38, - 0x6014, 0x2048, 0xa867, 0x0103, 0x0010, 0x080c, 0xa9a7, 0x080c, - 0x9fea, 0x00fe, 0x00ee, 0x009e, 0x006e, 0x005e, 0x004e, 0x003e, - 0x002e, 0x001e, 0x0005, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, - 0x9186, 0x0015, 0x11b8, 0x708c, 0x9086, 0x0004, 0x1198, 0x6014, - 0x2048, 0x2c78, 0x080c, 0x8d93, 0x01a8, 0x7078, 0xaa74, 0x9206, - 0x1130, 0x707c, 0xaa78, 0x9206, 0x1110, 0x080c, 0x3095, 0x080c, - 0xa3f2, 0x0020, 0x080c, 0xa9a7, 0x080c, 0x9fea, 0x00fe, 0x00ee, - 0x009e, 0x0005, 0x705c, 0xaa78, 0x9206, 0x0d78, 0x0c80, 0x0096, - 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1550, 0x708c, - 0x9086, 0x0004, 0x1530, 0x6014, 0x2048, 0x2c78, 0x080c, 0x8d93, - 0x05f0, 0x7078, 0xaacc, 0x9206, 0x1180, 0x707c, 0xaad0, 0x9206, - 0x1160, 0x080c, 0x3095, 0x0016, 0xa998, 0xaab0, 0x9284, 0x1000, - 0xc0fd, 0x080c, 0x548a, 0x001e, 0x0010, 0x080c, 0x5275, 0x080c, - 0xbd4e, 0x0508, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, - 0x0080, 0x080c, 0xbd4e, 0x01b8, 0x6014, 0x2048, 0x080c, 0x5275, - 0x1d70, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, - 0x0004, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0x080c, 0x6a22, - 0x012e, 0x080c, 0x9fea, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x705c, - 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, 0xbd4e, - 0x0904, 0xc38c, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x929e, - 0x4000, 0x1580, 0x6310, 0x00c6, 0x2358, 0x2009, 0x0000, 0xa868, - 0xd0f4, 0x1140, 0x080c, 0x65c3, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0xaa96, 0xa99a, 0x20a9, 0x0004, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, - 0x0006, 0x2098, 0x080c, 0x0fb4, 0x20a9, 0x0004, 0xa85c, 0x9080, - 0x0035, 0x20a0, 0xb8b8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0fb4, - 0x00ce, 0x0090, 0xaa96, 0x3918, 0x9398, 0x0007, 0x231c, 0x6004, - 0x9086, 0x0016, 0x0110, 0xa89b, 0x0004, 0xaba2, 0x6310, 0x2358, - 0xb804, 0x9084, 0x00ff, 0xa89e, 0xa868, 0xc0f4, 0xa86a, 0x080c, - 0x6a15, 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, 0x266d, 0x2118, 0x831f, 0x939c, - 0xff00, 0x7838, 0x9084, 0x00ff, 0x931d, 0x7c3c, 0x2011, 0x8018, - 0x080c, 0x4a17, 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, 0xbd3c, 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, 0xb41b, 0x0005, 0x0036, 0x2019, 0x0001, 0x0010, 0x0036, - 0x901e, 0x0499, 0x01e0, 0x080c, 0xbd4e, 0x01c8, 0x080c, 0xbf39, - 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, 0x0096, 0x2048, 0xa87c, - 0x080c, 0xbf56, 0x1118, 0x080c, 0xa9a7, 0x0040, 0xa867, 0x0103, - 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x6a22, 0x009e, 0x003e, - 0x0005, 0xa880, 0xd0b4, 0x0128, 0xa87b, 0x0006, 0xc0ec, 0xa882, - 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, - 0x080c, 0xc04a, 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, 0x4bb4, 0x004e, 0x003e, 0x0005, 0x0c51, 0x1d81, - 0x0005, 0x2001, 0x1960, 0x2004, 0x601a, 0x0005, 0x2001, 0x1962, - 0x2004, 0x6042, 0x0005, 0x080c, 0x9fea, 0x0804, 0x8b8f, 0x2001, - 0x0109, 0x2004, 0xd084, 0x01e0, 0x0126, 0x2091, 0x2800, 0x0006, - 0x0016, 0x0026, 0x0036, 0x00f6, 0x00e6, 0x00c6, 0x2079, 0x19c2, - 0x2071, 0x1800, 0x2061, 0x0100, 0x080c, 0x84e2, 0x00ce, 0x00ee, - 0x00fe, 0x003e, 0x002e, 0x001e, 0x000e, 0x012e, 0x9085, 0x0001, - 0x0005, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0df6, - 0x001b, 0x006e, 0x00be, 0x0005, 0xc4bc, 0xcbd4, 0xcd47, 0xc4bc, - 0xc4bc, 0xc4bc, 0xc4bc, 0xc4bc, 0xc4f3, 0xcdcb, 0xc4bc, 0xc4bc, - 0xc4bc, 0xc4bc, 0xc4bc, 0xc4bc, 0x080c, 0x0df6, 0x0066, 0x6000, - 0x90b2, 0x0010, 0x1a0c, 0x0df6, 0x0013, 0x006e, 0x0005, 0xc4d7, - 0xd31a, 0xc4d7, 0xc4d7, 0xc4d7, 0xc4d7, 0xc4d7, 0xc4d7, 0xd2c7, - 0xd36e, 0xc4d7, 0xd9c1, 0xd9f7, 0xd9c1, 0xd9f7, 0xc4d7, 0x080c, - 0x0df6, 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0df6, 0x6000, 0x000a, - 0x0005, 0xc4f1, 0xcfa9, 0xd078, 0xd09b, 0xd15b, 0xc4f1, 0xd23a, - 0xd1e3, 0xcdd7, 0xd29d, 0xd2b2, 0xc4f1, 0xc4f1, 0xc4f1, 0xc4f1, - 0xc4f1, 0x080c, 0x0df6, 0x91b2, 0x0053, 0x1a0c, 0x0df6, 0x2100, - 0x91b2, 0x0040, 0x1a04, 0xc971, 0x0002, 0xc53d, 0xc73f, 0xc53d, - 0xc53d, 0xc53d, 0xc748, 0xc53d, 0xc53d, 0xc53d, 0xc53d, 0xc53d, - 0xc53d, 0xc53d, 0xc53d, 0xc53d, 0xc53d, 0xc53d, 0xc53d, 0xc53d, - 0xc53d, 0xc53d, 0xc53d, 0xc53d, 0xc53f, 0xc5a2, 0xc5b1, 0xc615, - 0xc640, 0xc6b8, 0xc72a, 0xc53d, 0xc53d, 0xc74b, 0xc53d, 0xc53d, - 0xc760, 0xc76d, 0xc53d, 0xc53d, 0xc53d, 0xc53d, 0xc53d, 0xc813, - 0xc53d, 0xc53d, 0xc827, 0xc53d, 0xc53d, 0xc7e2, 0xc53d, 0xc53d, - 0xc53d, 0xc83f, 0xc53d, 0xc53d, 0xc53d, 0xc8bc, 0xc53d, 0xc53d, - 0xc53d, 0xc53d, 0xc53d, 0xc53d, 0xc939, 0x080c, 0x0df6, 0x080c, - 0x6687, 0x1150, 0x2001, 0x1836, 0x2004, 0xd0cc, 0x1128, 0x9084, - 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, 0x602f, 0x0009, - 0x6017, 0x0000, 0x0804, 0xc738, 0x080c, 0x6670, 0x00e6, 0x00c6, - 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, - 0x0029, 0x080c, 0x8782, 0x0076, 0x903e, 0x080c, 0x8670, 0x2c08, - 0x080c, 0xd556, 0x007e, 0x001e, 0x001e, 0x002e, 0x003e, 0x00ce, - 0x00ee, 0x6610, 0x2658, 0x080c, 0x63b2, 0xbe04, 0x9684, 0x00ff, - 0x9082, 0x0006, 0x1268, 0x0016, 0x0026, 0x6210, 0x00b6, 0x2258, - 0xbaa0, 0x00be, 0x2c08, 0x080c, 0xdb71, 0x002e, 0x001e, 0x1178, - 0x080c, 0xd489, 0x1904, 0xc60d, 0x080c, 0xd425, 0x1120, 0x6007, - 0x0008, 0x0804, 0xc738, 0x6007, 0x0009, 0x0804, 0xc738, 0x080c, - 0xd6c7, 0x0128, 0x080c, 0xd489, 0x0d78, 0x0804, 0xc60d, 0x6017, - 0x1900, 0x0c88, 0x080c, 0x31b8, 0x1904, 0xc96e, 0x6106, 0x080c, - 0xd3c9, 0x6007, 0x0006, 0x0804, 0xc738, 0x6007, 0x0007, 0x0804, - 0xc738, 0x080c, 0xda33, 0x1904, 0xc96e, 0x080c, 0x31b8, 0x1904, - 0xc96e, 0x00d6, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, - 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x62e0, 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, 0xd4ec, 0x1190, 0x9686, 0x0006, - 0x1140, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x30de, - 0x002e, 0x080c, 0x643e, 0x6007, 0x000a, 0x00de, 0x0804, 0xc738, - 0x6007, 0x000b, 0x00de, 0x0804, 0xc738, 0x080c, 0x3095, 0x080c, - 0xc46e, 0x6007, 0x0001, 0x0804, 0xc738, 0x080c, 0xda33, 0x1904, - 0xc96e, 0x080c, 0x31b8, 0x1904, 0xc96e, 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, 0x30de, 0x002e, - 0x6007, 0x000c, 0x2001, 0x0001, 0x080c, 0xdb50, 0x0804, 0xc738, - 0x080c, 0x6687, 0x1140, 0x2001, 0x1836, 0x2004, 0x9084, 0x0009, - 0x9086, 0x0008, 0x1110, 0x0804, 0xc54c, 0x080c, 0x6670, 0x6610, - 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06c0, 0x1138, - 0x0026, 0x2001, 0x0006, 0x080c, 0x6320, 0x002e, 0x0050, 0x96b4, - 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, - 0xc60d, 0x080c, 0xd4f9, 0x1120, 0x6007, 0x000e, 0x0804, 0xc738, - 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x3095, 0x080c, - 0xc46e, 0x004e, 0x0016, 0x9006, 0x2009, 0x185c, 0x210c, 0x0048, - 0x2009, 0x0029, 0x080c, 0xd837, 0x6010, 0x2058, 0xb800, 0xc0e5, - 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, 0xc738, 0x2001, - 0x0001, 0x080c, 0x62e0, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x0270, 0x080c, 0xb003, 0x003e, - 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, - 0x9682, 0x0004, 0x0a04, 0xc60d, 0x9682, 0x0007, 0x0a04, 0xc669, - 0x0804, 0xc60d, 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, 0xc738, - 0x080c, 0x6687, 0x1140, 0x2001, 0x1836, 0x2004, 0x9084, 0x0009, - 0x9086, 0x0008, 0x1110, 0x0804, 0xc54c, 0x080c, 0x6670, 0x6610, - 0x2658, 0xbe04, 0x9684, 0x00ff, 0x0006, 0x0016, 0x908e, 0x0001, - 0x0118, 0x908e, 0x0000, 0x1118, 0x001e, 0x000e, 0x0080, 0x001e, - 0x000e, 0x9082, 0x0006, 0x0698, 0x0150, 0x96b4, 0xff00, 0x8637, - 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xc60d, 0x080c, - 0xd527, 0x1138, 0x080c, 0xd425, 0x1120, 0x6007, 0x0010, 0x0804, - 0xc738, 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x3095, - 0x080c, 0xc46e, 0x004e, 0x0016, 0x9006, 0x2009, 0x185c, 0x210c, - 0x0048, 0x2009, 0x0029, 0x080c, 0xd837, 0x6010, 0x2058, 0xb800, - 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x0448, 0x080c, - 0xd6c7, 0x0198, 0x0016, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0160, - 0x9186, 0x0003, 0x0148, 0x001e, 0x96b4, 0xff00, 0x8637, 0x9686, - 0x0006, 0x0928, 0x0804, 0xc60d, 0x001e, 0x6017, 0x1900, 0x6007, - 0x0009, 0x0070, 0x080c, 0x31b8, 0x1904, 0xc96e, 0x080c, 0xda33, - 0x1904, 0xc96e, 0x080c, 0xcb12, 0x1904, 0xc60d, 0x6007, 0x0012, - 0x6003, 0x0001, 0x080c, 0x8640, 0x080c, 0x8b8f, 0x0005, 0x6007, - 0x0001, 0x6003, 0x0001, 0x080c, 0x8640, 0x080c, 0x8b8f, 0x0cb0, - 0x6007, 0x0005, 0x0c68, 0x080c, 0xda33, 0x1904, 0xc96e, 0x080c, - 0x31b8, 0x1904, 0xc96e, 0x080c, 0xcb12, 0x1904, 0xc60d, 0x6007, - 0x0020, 0x6003, 0x0001, 0x080c, 0x8640, 0x080c, 0x8b8f, 0x0005, - 0x080c, 0x31b8, 0x1904, 0xc96e, 0x6007, 0x0023, 0x6003, 0x0001, - 0x080c, 0x8640, 0x080c, 0x8b8f, 0x0005, 0x080c, 0xda33, 0x1904, - 0xc96e, 0x080c, 0x31b8, 0x1904, 0xc96e, 0x080c, 0xcb12, 0x1904, - 0xc60d, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x2c08, 0x2011, - 0x181f, 0x2214, 0x703c, 0x9206, 0x11e0, 0x2011, 0x181e, 0x2214, - 0x7038, 0x9084, 0x00ff, 0x9206, 0x11a0, 0x7240, 0x080c, 0xbd3c, - 0x0570, 0x2260, 0x6008, 0x9086, 0xffff, 0x0120, 0x7244, 0x6008, - 0x9206, 0x1528, 0x6020, 0x9086, 0x0007, 0x1508, 0x080c, 0x9fea, - 0x04a0, 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, 0xbd3c, - 0x01b0, 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, - 0x0004, 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, - 0x080c, 0xd809, 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, 0x9fea, 0x2160, 0x6007, 0x0025, - 0x6003, 0x0001, 0x080c, 0x8640, 0x080c, 0x8b8f, 0x00ee, 0x002e, - 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x62e0, 0x0156, 0x0016, - 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, - 0x080c, 0xb003, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, - 0x0031, 0x0804, 0xc738, 0x080c, 0xac59, 0x080c, 0x717e, 0x1190, - 0x0006, 0x0026, 0x0036, 0x080c, 0x7198, 0x1138, 0x080c, 0x747a, - 0x080c, 0x5e2f, 0x080c, 0x709e, 0x0010, 0x080c, 0x7156, 0x003e, - 0x002e, 0x000e, 0x0005, 0x080c, 0x31b8, 0x1904, 0xc96e, 0x080c, - 0xcb12, 0x1904, 0xc60d, 0x6106, 0x080c, 0xcb2e, 0x1120, 0x6007, - 0x002b, 0x0804, 0xc738, 0x6007, 0x002c, 0x0804, 0xc738, 0x080c, - 0xda33, 0x1904, 0xc96e, 0x080c, 0x31b8, 0x1904, 0xc96e, 0x080c, - 0xcb12, 0x1904, 0xc60d, 0x6106, 0x080c, 0xcb33, 0x1120, 0x6007, - 0x002e, 0x0804, 0xc738, 0x6007, 0x002f, 0x0804, 0xc738, 0x080c, - 0x31b8, 0x1904, 0xc96e, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x2058, - 0xb904, 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, - 0x8007, 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, - 0xc73f, 0x080c, 0x54df, 0xd0e4, 0x0904, 0xc8b9, 0x2071, 0x026c, - 0x7010, 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, 0x66c5, - 0x0140, 0x6010, 0x2058, 0xb810, 0x9106, 0x1118, 0xb814, 0x9206, - 0x0510, 0x080c, 0x66c1, 0x15b8, 0x2069, 0x1800, 0x687c, 0x9206, - 0x1590, 0x6878, 0x9106, 0x1578, 0x7210, 0x080c, 0xbd3c, 0x0590, - 0x080c, 0xc9ff, 0x0578, 0x080c, 0xd8b3, 0x0560, 0x622e, 0x6007, - 0x0036, 0x6003, 0x0001, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x00ce, - 0x00de, 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, - 0xbd3c, 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, - 0x08e0, 0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, 0xd809, 0x2c10, - 0x2160, 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, - 0x1500, 0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, 0x6017, 0x1700, - 0x0880, 0x6007, 0x0012, 0x0868, 0x080c, 0x31b8, 0x1904, 0xc96e, - 0x6010, 0x2058, 0xb804, 0x9084, 0xff00, 0x8007, 0x9086, 0x0006, - 0x1904, 0xc73f, 0x00e6, 0x00d6, 0x00c6, 0x080c, 0x54df, 0xd0e4, - 0x0904, 0xc931, 0x2069, 0x1800, 0x2071, 0x026c, 0x7008, 0x603a, - 0x720c, 0x623e, 0x9286, 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, - 0x9085, 0x0001, 0x080c, 0xd809, 0x2c10, 0x00ce, 0x05e8, 0x080c, - 0xbd3c, 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, - 0x00c6, 0x0026, 0x2260, 0x080c, 0xb976, 0x002e, 0x00ce, 0x7118, - 0x918c, 0xff00, 0x810f, 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, - 0x0118, 0x9186, 0x0007, 0x1198, 0x9280, 0x0005, 0x2004, 0x9005, - 0x0170, 0x080c, 0xc9ff, 0x0904, 0xc8b2, 0x0056, 0x7510, 0x7614, - 0x080c, 0xd8cc, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, - 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x080c, - 0x85f8, 0x080c, 0x8b8f, 0x0c78, 0x6007, 0x003b, 0x602f, 0x0003, - 0x6017, 0x0300, 0x6003, 0x0001, 0x080c, 0x85f8, 0x080c, 0x8b8f, - 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, 0x0804, - 0xc889, 0x00e6, 0x0026, 0x080c, 0x6687, 0x0550, 0x080c, 0x6670, - 0x080c, 0xdaa4, 0x1518, 0x2071, 0x1800, 0x70d8, 0x9085, 0x0003, - 0x70da, 0x00f6, 0x2079, 0x0100, 0x72ac, 0x9284, 0x00ff, 0x707a, - 0x78e6, 0x9284, 0xff00, 0x727c, 0x9205, 0x707e, 0x78ea, 0x00fe, - 0x70e3, 0x0000, 0x080c, 0x66c5, 0x0120, 0x2011, 0x19db, 0x2013, - 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2e73, 0x0010, 0x080c, 0xdad8, - 0x002e, 0x00ee, 0x080c, 0x9fea, 0x0804, 0xc73e, 0x080c, 0x9fea, - 0x0005, 0x2600, 0x0002, 0xc985, 0xc985, 0xc985, 0xc985, 0xc985, - 0xc987, 0xc985, 0xc985, 0xc985, 0xc985, 0xc9a1, 0xc985, 0xc985, - 0xc985, 0xc9b3, 0xc9c9, 0xc9fa, 0xc985, 0x080c, 0x0df6, 0x080c, - 0xda33, 0x1d20, 0x080c, 0x31b8, 0x1d08, 0x7038, 0x6016, 0x6007, - 0x0045, 0x6003, 0x0001, 0x080c, 0x8640, 0x0005, 0x080c, 0x3095, - 0x080c, 0xc46e, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x8640, - 0x0005, 0x080c, 0xda33, 0x1950, 0x080c, 0x31b8, 0x1938, 0x080c, - 0xcb12, 0x1d60, 0x703c, 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, - 0x080c, 0x8640, 0x0005, 0x2001, 0x1823, 0x2004, 0x9082, 0x00e1, - 0x1268, 0x080c, 0xca1c, 0x0904, 0xc96e, 0x6007, 0x004e, 0x6003, - 0x0001, 0x080c, 0x8640, 0x080c, 0x8b8f, 0x0005, 0x6007, 0x0012, - 0x0cb0, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, 0x00ff, - 0x81ff, 0x0508, 0x9186, 0x0001, 0x1160, 0x7140, 0x2001, 0x1998, - 0x2004, 0x9106, 0x11b0, 0x7144, 0x2001, 0x1999, 0x2004, 0x9106, - 0x0190, 0x9186, 0x0002, 0x1168, 0x2011, 0x0276, 0x20a9, 0x0004, - 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xb017, 0x009e, - 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, 0x8640, 0x080c, - 0x8b8f, 0x0005, 0x6007, 0x0050, 0x703c, 0x6016, 0x0ca0, 0x0016, - 0x00e6, 0x2071, 0x0260, 0x00b6, 0x00c6, 0x2260, 0x6010, 0x2058, - 0xb8bc, 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, 0x197b, 0x2003, 0x0000, 0x080c, 0x1050, 0x05a0, - 0x2900, 0x6016, 0x708c, 0x8004, 0xa816, 0x908a, 0x001e, 0x02d0, - 0xa833, 0x001e, 0x20a9, 0x001e, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x001b, 0x20a0, 0x2001, 0x197b, 0x0016, 0x200c, 0x0471, 0x001e, - 0x81ff, 0x01b8, 0x2940, 0x080c, 0x1050, 0x01b0, 0x2900, 0xa006, - 0x2100, 0x0c18, 0xa832, 0x20a8, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x001b, 0x20a0, 0x2001, 0x197b, 0x0016, 0x200c, 0x00b1, 0x001e, - 0x0000, 0x9085, 0x0001, 0x0048, 0x2071, 0x1800, 0x708f, 0x0000, - 0x6014, 0x2048, 0x080c, 0x0fe9, 0x9006, 0x012e, 0x01de, 0x01ce, - 0x00ee, 0x008e, 0x009e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0026, - 0x0036, 0x00c6, 0x918c, 0xffff, 0x11b0, 0x080c, 0x21d9, 0x2099, - 0x026c, 0x2001, 0x0014, 0x3518, 0x9312, 0x0108, 0x1218, 0x23a8, - 0x4003, 0x0400, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x21d9, - 0x2099, 0x0260, 0x0ca8, 0x080c, 0x21d9, 0x2061, 0x197b, 0x6004, - 0x2098, 0x6008, 0x3518, 0x9312, 0x0108, 0x1218, 0x23a8, 0x4003, - 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x21d9, 0x2099, - 0x0260, 0x0ca8, 0x2061, 0x197b, 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, 0x21f1, 0x20a1, 0x024c, 0x2001, 0x0014, - 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, 0x20a8, 0x4003, - 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, 0x21f1, 0x20a1, 0x0240, - 0x0c98, 0x080c, 0x21f1, 0x2061, 0x197e, 0x6004, 0x20a0, 0x6008, - 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, 0x20a8, 0x4003, - 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, 0x21f1, 0x20a1, 0x0240, - 0x0c98, 0x2061, 0x197e, 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, - 0xcbaa, 0x00de, 0x0005, 0x00d6, 0x080c, 0xcbb7, 0x1520, 0x680c, - 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, 0x6824, - 0x602e, 0xd1e4, 0x0130, 0x9006, 0x080c, 0xdb50, 0x2009, 0x0001, - 0x0078, 0xd1ec, 0x0180, 0x6920, 0x918c, 0x00ff, 0x6824, 0x080c, - 0x266d, 0x1148, 0x2001, 0x0001, 0x080c, 0xdb50, 0x2110, 0x900e, - 0x080c, 0x30de, 0x0018, 0x9085, 0x0001, 0x0008, 0x9006, 0x00de, - 0x0005, 0x00b6, 0x00c6, 0x080c, 0xa03b, 0x05a8, 0x0016, 0x0026, - 0x00c6, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x266d, - 0x1578, 0x080c, 0x6343, 0x1560, 0xbe12, 0xbd16, 0x00ce, 0x002e, - 0x001e, 0x2b00, 0x6012, 0x080c, 0xda33, 0x11d8, 0x080c, 0x31b8, - 0x11c0, 0x080c, 0xcb12, 0x0510, 0x2001, 0x0007, 0x080c, 0x62f4, - 0x2001, 0x0007, 0x080c, 0x6320, 0x6017, 0x0000, 0x6023, 0x0001, - 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x8640, 0x080c, 0x8b8f, - 0x0010, 0x080c, 0x9fea, 0x9085, 0x0001, 0x00ce, 0x00be, 0x0005, - 0x080c, 0x9fea, 0x00ce, 0x002e, 0x001e, 0x0ca8, 0x080c, 0x9fea, - 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, - 0x0df6, 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, 0x0040, 0x1a04, - 0xcd17, 0x040a, 0x91b6, 0x0027, 0x0198, 0x9186, 0x0015, 0x0118, - 0x9186, 0x0016, 0x1148, 0x080c, 0xc47f, 0x0128, 0x6000, 0x9086, - 0x0002, 0x0904, 0xa9ee, 0x0005, 0x91b6, 0x0014, 0x190c, 0x0df6, - 0x2001, 0x0007, 0x080c, 0x6320, 0x080c, 0x8a83, 0x080c, 0xa01c, - 0x080c, 0x8b8f, 0x0005, 0xcc43, 0xcc45, 0xcc43, 0xcc43, 0xcc43, - 0xcc45, 0xcc54, 0xcd10, 0xcc98, 0xcd10, 0xccbe, 0xcd10, 0xcc54, - 0xcd10, 0xcd08, 0xcd10, 0xcd08, 0xcd10, 0xcd10, 0xcc43, 0xcc43, - 0xcc43, 0xcc43, 0xcc43, 0xcc43, 0xcc43, 0xcc43, 0xcc43, 0xcc43, - 0xcc43, 0xcc45, 0xcc43, 0xcd10, 0xcc43, 0xcc43, 0xcd10, 0xcc43, - 0xcd0d, 0xcd10, 0xcc43, 0xcc43, 0xcc43, 0xcc43, 0xcd10, 0xcd10, - 0xcc43, 0xcd10, 0xcd10, 0xcc43, 0xcc4f, 0xcc43, 0xcc43, 0xcc43, - 0xcc43, 0xcd0c, 0xcd10, 0xcc43, 0xcc43, 0xcd10, 0xcd10, 0xcc43, - 0xcc43, 0xcc43, 0xcc43, 0x080c, 0x0df6, 0x080c, 0x8a83, 0x080c, - 0xc471, 0x6003, 0x0002, 0x080c, 0x8b8f, 0x0804, 0xcd16, 0x9006, - 0x080c, 0x62e0, 0x0804, 0xcd10, 0x080c, 0x66c1, 0x1904, 0xcd10, - 0x9006, 0x080c, 0x62e0, 0x6010, 0x2058, 0xb810, 0x9086, 0x00ff, - 0x1140, 0x00f6, 0x2079, 0x1800, 0x78a4, 0x8000, 0x78a6, 0x00fe, - 0x00b8, 0x6010, 0x2058, 0xb8b0, 0x9005, 0x0904, 0xcd10, 0x080c, - 0x31e9, 0x1904, 0xcd10, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, - 0x1138, 0x00f6, 0x2079, 0x1800, 0x78a4, 0x8000, 0x78a6, 0x00fe, - 0x2001, 0x0002, 0x080c, 0x62f4, 0x080c, 0x8a83, 0x6023, 0x0001, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x8640, 0x080c, 0x8b8f, - 0x6110, 0x2158, 0x2009, 0x0001, 0x080c, 0x8267, 0x0804, 0xcd16, - 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, - 0x0138, 0x9686, 0x0004, 0x0120, 0x2001, 0x0004, 0x080c, 0x6320, - 0x080c, 0xdb9f, 0x0904, 0xcd10, 0x080c, 0x8a83, 0x2001, 0x0004, - 0x080c, 0x62f4, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0003, - 0x080c, 0x8640, 0x080c, 0x8b8f, 0x0804, 0xcd16, 0x2001, 0x1800, - 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, - 0xbba0, 0x2021, 0x0006, 0x080c, 0x4bb4, 0x004e, 0x003e, 0x2001, - 0x0006, 0x080c, 0xcd34, 0x6610, 0x2658, 0xbe04, 0x0066, 0x96b4, - 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, 0x0180, 0x2001, 0x0006, - 0x080c, 0x6320, 0x9284, 0x00ff, 0x908e, 0x0007, 0x0118, 0x908e, - 0x0004, 0x1120, 0x2001, 0x0006, 0x080c, 0x62f4, 0x080c, 0x66c1, - 0x11f8, 0x2001, 0x1836, 0x2004, 0xd0a4, 0x01d0, 0xbe04, 0x96b4, - 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6, 0x2079, 0x1800, 0x78a4, - 0x8000, 0x78a6, 0x00fe, 0x0804, 0xcc80, 0x2001, 0x0004, 0x0030, - 0x2001, 0x0006, 0x0449, 0x0020, 0x0018, 0x0010, 0x080c, 0x6320, - 0x080c, 0x8a83, 0x080c, 0x9fea, 0x080c, 0x8b8f, 0x0005, 0x2600, - 0x0002, 0xcd2b, 0xcd2b, 0xcd2b, 0xcd2b, 0xcd2b, 0xcd2d, 0xcd2b, - 0xcd2b, 0xcd2b, 0xcd2b, 0xcd2d, 0xcd2b, 0xcd2b, 0xcd2b, 0xcd2d, - 0xcd2d, 0xcd2d, 0xcd2d, 0x080c, 0x0df6, 0x080c, 0x8a83, 0x080c, - 0x9fea, 0x080c, 0x8b8f, 0x0005, 0x0016, 0x00b6, 0x00d6, 0x6110, - 0x2158, 0xb900, 0xd184, 0x0138, 0x080c, 0x62f4, 0x9006, 0x080c, - 0x62e0, 0x080c, 0x30be, 0x00de, 0x00be, 0x001e, 0x0005, 0x6610, - 0x2658, 0xb804, 0x9084, 0xff00, 0x8007, 0x90b2, 0x000c, 0x1a0c, - 0x0df6, 0x91b6, 0x0015, 0x1110, 0x003b, 0x0028, 0x91b6, 0x0016, - 0x190c, 0x0df6, 0x006b, 0x0005, 0xaa88, 0xaa88, 0xaa88, 0xaa88, - 0xcdc9, 0xaa88, 0xcdb3, 0xcd74, 0xaa88, 0xaa88, 0xaa88, 0xaa88, - 0xaa88, 0xaa88, 0xaa88, 0xaa88, 0xcdc9, 0xaa88, 0xcdb3, 0xcdba, - 0xaa88, 0xaa88, 0xaa88, 0xaa88, 0x00f6, 0x080c, 0x66c1, 0x11d8, - 0x080c, 0xc459, 0x11c0, 0x6010, 0x905d, 0x01a8, 0xb8b0, 0x9005, - 0x0190, 0x9006, 0x080c, 0x62e0, 0x2001, 0x0002, 0x080c, 0x62f4, - 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x8640, - 0x080c, 0x8b8f, 0x00f0, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, - 0x080c, 0x266d, 0x11b0, 0x080c, 0x63a3, 0x0118, 0x080c, 0x9fea, - 0x0080, 0xb810, 0x0006, 0xb814, 0x0006, 0xb8b0, 0x0006, 0x080c, - 0x5e49, 0x000e, 0xb8b2, 0x000e, 0xb816, 0x000e, 0xb812, 0x080c, - 0x9fea, 0x00fe, 0x0005, 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, - 0x9fea, 0x0005, 0x080c, 0xae8a, 0x1148, 0x6003, 0x0001, 0x6007, - 0x0001, 0x080c, 0x8640, 0x080c, 0x8b8f, 0x0010, 0x080c, 0x9fea, - 0x0005, 0x0804, 0x9fea, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0df6, - 0x080c, 0x8a83, 0x080c, 0xa01c, 0x080c, 0x8b8f, 0x0005, 0x9182, - 0x0040, 0x0002, 0xcdee, 0xcdee, 0xcdee, 0xcdee, 0xcdf0, 0xcdee, - 0xcdee, 0xcdee, 0xcdee, 0xcdee, 0xcdee, 0xcdee, 0xcdee, 0xcdee, - 0xcdee, 0xcdee, 0xcdee, 0xcdee, 0xcdee, 0xcdee, 0x080c, 0x0df6, - 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, 0x6210, - 0x2258, 0xb8ac, 0x9005, 0x11a8, 0x6106, 0x2071, 0x0260, 0x7444, - 0x94a4, 0xff00, 0x0904, 0xce56, 0x080c, 0xdb44, 0x1170, 0x9486, - 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x8450, - 0x0020, 0x9026, 0x080c, 0xda78, 0x0c38, 0x080c, 0x1037, 0x090c, - 0x0df6, 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, 0x6a22, 0x001e, 0x080c, 0xdb44, 0x1904, - 0xceb6, 0x9486, 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0xd7af, - 0x0804, 0xceb6, 0x9486, 0x0200, 0x1120, 0x080c, 0xd746, 0x0804, - 0xceb6, 0x9486, 0x0400, 0x0120, 0x9486, 0x1000, 0x1904, 0xceb6, - 0x2019, 0x0002, 0x080c, 0xd761, 0x0804, 0xceb6, 0x2069, 0x1a4c, - 0x6a00, 0xd284, 0x0904, 0xcf20, 0x9284, 0x0300, 0x1904, 0xcf19, - 0x6804, 0x9005, 0x0904, 0xcf01, 0x2d78, 0x6003, 0x0007, 0x080c, - 0x1050, 0x0904, 0xcec2, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, - 0x7806, 0x6017, 0x0000, 0x2001, 0x180f, 0x2004, 0xd084, 0x1904, - 0xcf24, 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, 0xcebe, 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, 0x6a22, 0x002e, 0x004e, - 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e, 0x0005, 0x0000, 0x0080, - 0x0040, 0x0000, 0x2001, 0x1810, 0x2004, 0xd084, 0x0120, 0x080c, - 0x1037, 0x1904, 0xce6b, 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, - 0x0041, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x0c00, 0x2069, 0x0260, - 0x6848, 0x9084, 0xff00, 0x9086, 0x1200, 0x1198, 0x686c, 0x9084, - 0x00ff, 0x0016, 0x6114, 0x918c, 0xf700, 0x910d, 0x6116, 0x001e, - 0x6003, 0x0001, 0x6007, 0x0043, 0x080c, 0x85f8, 0x080c, 0x8b8f, - 0x0828, 0x6868, 0x602e, 0x686c, 0x6032, 0x6017, 0xf200, 0x6003, - 0x0001, 0x6007, 0x0041, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x0804, - 0xceb6, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, - 0x080c, 0x4a17, 0x6017, 0xf300, 0x0010, 0x6017, 0xf100, 0x6003, - 0x0001, 0x6007, 0x0041, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x0804, - 0xceb6, 0x6017, 0xf500, 0x0c98, 0x6017, 0xf600, 0x0804, 0xced6, - 0x6017, 0xf200, 0x0804, 0xced6, 0xa867, 0x0146, 0xa86b, 0x0000, - 0x6008, 0xa886, 0x2c00, 0xa87a, 0x7044, 0x9084, 0x0003, 0x9080, - 0xcebe, 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, 0x0df6, 0x8210, 0x821c, 0x2001, 0x026c, - 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0029, 0x20a0, 0x2011, - 0xcfa0, 0x2041, 0x0001, 0x223d, 0x9784, 0x00ff, 0x9322, 0x1208, - 0x2300, 0x20a8, 0x4003, 0x931a, 0x0530, 0x8210, 0xd7fc, 0x1130, - 0x8d68, 0x2d0a, 0x2001, 0x0260, 0x2098, 0x0c68, 0x2950, 0x080c, - 0x1050, 0x0170, 0x2900, 0xb002, 0xa867, 0x0147, 0xa86b, 0x0000, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x8840, 0x08d8, - 0x2548, 0xa800, 0x902d, 0x0118, 0x080c, 0x1069, 0x0cc8, 0x080c, - 0x1069, 0x0804, 0xcec2, 0x2548, 0x8847, 0x9885, 0x0046, 0xa866, - 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, 0xd7e2, 0x0804, 0xceb6, - 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, 0x0008, 0x8016, 0x000a, - 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0054, 0x1a0c, - 0x0df6, 0x9082, 0x0040, 0x0a0c, 0x0df6, 0x2008, 0x0804, 0xd02f, - 0x9186, 0x0051, 0x0108, 0x0048, 0x080c, 0xc47f, 0x0500, 0x6000, - 0x9086, 0x0002, 0x11e0, 0x0804, 0xd078, 0x9186, 0x0027, 0x0190, - 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0160, 0x190c, 0x0df6, - 0x080c, 0xc47f, 0x0160, 0x6000, 0x9086, 0x0004, 0x190c, 0x0df6, - 0x0804, 0xd15b, 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, - 0xa083, 0x0005, 0xcff6, 0xcff8, 0xcff8, 0xd01f, 0xcff6, 0xcff6, - 0xcff6, 0xcff6, 0xcff6, 0xcff6, 0xcff6, 0xcff6, 0xcff6, 0xcff6, - 0xcff6, 0xcff6, 0xcff6, 0xcff6, 0xcff6, 0xcff6, 0x080c, 0x0df6, - 0x080c, 0x8a83, 0x080c, 0x8b8f, 0x0036, 0x0096, 0x6014, 0x904d, - 0x01d8, 0x080c, 0xbd4e, 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, - 0xd7e2, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x1961, - 0x2004, 0x601a, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x0096, - 0x080c, 0x8a83, 0x080c, 0x8b8f, 0x080c, 0xbd4e, 0x0120, 0x6014, - 0x2048, 0x080c, 0x1069, 0x080c, 0xa01c, 0x009e, 0x0005, 0x0002, - 0xd044, 0xd05b, 0xd046, 0xd072, 0xd044, 0xd044, 0xd044, 0xd044, - 0xd044, 0xd044, 0xd044, 0xd044, 0xd044, 0xd044, 0xd044, 0xd044, - 0xd044, 0xd044, 0xd044, 0xd044, 0x080c, 0x0df6, 0x0096, 0x080c, - 0x8a83, 0x6014, 0x2048, 0xa87c, 0xd0b4, 0x0138, 0x6003, 0x0007, - 0x2009, 0x0043, 0x080c, 0xa068, 0x0010, 0x6003, 0x0004, 0x080c, - 0x8b8f, 0x009e, 0x0005, 0x080c, 0x8a83, 0x080c, 0xbd4e, 0x0138, - 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e, 0xd1ec, 0x1138, 0x080c, - 0x8425, 0x080c, 0x9fea, 0x080c, 0x8b8f, 0x0005, 0x080c, 0xda3c, - 0x0db0, 0x0cc8, 0x080c, 0x8a83, 0x2009, 0x0041, 0x0804, 0xd1e3, - 0x9182, 0x0040, 0x0002, 0xd08f, 0xd091, 0xd08f, 0xd08f, 0xd08f, - 0xd08f, 0xd08f, 0xd08f, 0xd08f, 0xd08f, 0xd08f, 0xd08f, 0xd08f, - 0xd08f, 0xd08f, 0xd08f, 0xd08f, 0xd092, 0xd08f, 0xd08f, 0x080c, - 0x0df6, 0x0005, 0x00d6, 0x080c, 0x8425, 0x00de, 0x080c, 0xda94, - 0x080c, 0x9fea, 0x0005, 0x9182, 0x0040, 0x0002, 0xd0b2, 0xd0b2, - 0xd0b2, 0xd0b2, 0xd0b2, 0xd0b2, 0xd0b2, 0xd0b2, 0xd0b2, 0xd0b4, - 0xd123, 0xd0b2, 0xd0b2, 0xd0b2, 0xd0b2, 0xd123, 0xd0b2, 0xd0b2, - 0xd0b2, 0xd0b2, 0x080c, 0x0df6, 0x2001, 0x0105, 0x2004, 0x9084, - 0x1800, 0x01c8, 0x2001, 0x0132, 0x200c, 0x2001, 0x0131, 0x2004, - 0x9105, 0x1904, 0xd123, 0x2009, 0x180c, 0x2104, 0xd0d4, 0x0904, - 0xd123, 0xc0d4, 0x200a, 0x2009, 0x0105, 0x2104, 0x9084, 0xe7fd, - 0x9085, 0x0010, 0x200a, 0x2001, 0x187b, 0x2004, 0xd0e4, 0x1528, - 0x603b, 0x0000, 0x080c, 0x8b3f, 0x6014, 0x0096, 0x2048, 0xa87c, - 0xd0fc, 0x0188, 0x908c, 0x0003, 0x918e, 0x0002, 0x0508, 0x2001, - 0x180c, 0x2004, 0xd0d4, 0x11e0, 0x080c, 0x8c6c, 0x2009, 0x0041, - 0x009e, 0x0804, 0xd1e3, 0x080c, 0x8c6c, 0x6003, 0x0007, 0x601b, - 0x0000, 0x080c, 0x8425, 0x009e, 0x0005, 0x2001, 0x0100, 0x2004, - 0x9082, 0x0005, 0x0aa8, 0x2001, 0x011f, 0x2004, 0x603a, 0x0890, - 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, 0xd1cc, 0x0110, 0x080c, - 0x2ab1, 0x080c, 0x8c6c, 0x6014, 0x2048, 0xa97c, 0xd1ec, 0x1130, - 0x080c, 0x8425, 0x080c, 0x9fea, 0x009e, 0x0005, 0x080c, 0xda3c, - 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, - 0x0036, 0x080c, 0x8b3f, 0x080c, 0x8c6c, 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, 0xd7e2, 0x6018, 0x9005, 0x1128, 0x2001, - 0x1961, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, 0x6003, 0x0007, - 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, 0xd172, 0xd172, - 0xd172, 0xd172, 0xd172, 0xd172, 0xd172, 0xd172, 0xd174, 0xd172, - 0xd172, 0xd172, 0xd172, 0xd172, 0xd172, 0xd172, 0xd172, 0xd172, - 0xd172, 0xd1bf, 0x080c, 0x0df6, 0x6014, 0x0096, 0x2048, 0xa834, - 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1190, - 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, 0x2009, 0x0041, 0x009e, - 0x0804, 0xd1e3, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x8425, - 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, - 0x8427, 0x009e, 0x0005, 0x6003, 0x0002, 0x009e, 0x0005, 0x6024, - 0xd0f4, 0x0128, 0x080c, 0x1577, 0x1904, 0xd174, 0x0005, 0x6014, - 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, 0x9105, 0x1120, 0x080c, - 0x1577, 0x1904, 0xd174, 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, 0x0df6, 0x6024, 0xd0dc, - 0x090c, 0x0df6, 0x0005, 0xd207, 0xd213, 0xd21f, 0xd22b, 0xd207, - 0xd207, 0xd207, 0xd207, 0xd20e, 0xd209, 0xd209, 0xd207, 0xd207, - 0xd207, 0xd207, 0xd209, 0xd207, 0xd209, 0xd207, 0xd20e, 0x080c, - 0x0df6, 0x6024, 0xd0dc, 0x090c, 0x0df6, 0x0005, 0x6014, 0x9005, - 0x190c, 0x0df6, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x85f8, - 0x0126, 0x2091, 0x8000, 0x080c, 0x8b8f, 0x012e, 0x0005, 0x6003, - 0x0001, 0x6106, 0x080c, 0x85f8, 0x0126, 0x2091, 0x8000, 0x080c, - 0x8b8f, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, - 0x1a7e, 0x0126, 0x2091, 0x8000, 0x080c, 0x865d, 0x080c, 0x8c6c, - 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x0096, 0x9182, - 0x0040, 0x0023, 0x009e, 0x003e, 0x012e, 0x0005, 0xd25a, 0xd25c, - 0xd26e, 0xd288, 0xd25a, 0xd25a, 0xd25a, 0xd25a, 0xd25a, 0xd25a, - 0xd25a, 0xd25a, 0xd25a, 0xd25a, 0xd25a, 0xd25a, 0xd25a, 0xd25a, - 0xd25a, 0xd25a, 0x080c, 0x0df6, 0x6014, 0x2048, 0xa87c, 0xd0fc, - 0x01f8, 0x909c, 0x0003, 0x939e, 0x0003, 0x01d0, 0x6003, 0x0001, - 0x6106, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x0470, 0x6014, 0x2048, - 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, 0x0140, - 0x6003, 0x0001, 0x6106, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x00e0, - 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xd7e2, 0x00a0, - 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, 0x909c, 0x0003, 0x939e, - 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1a7e, - 0x080c, 0x865d, 0x080c, 0x8c6c, 0x0005, 0x080c, 0x8a83, 0x6114, - 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xdae1, 0x0036, 0x2019, - 0x0029, 0x080c, 0xd7e2, 0x003e, 0x009e, 0x080c, 0xa01c, 0x080c, - 0x8b8f, 0x0005, 0x080c, 0x8b3f, 0x6114, 0x81ff, 0x0158, 0x0096, - 0x2148, 0x080c, 0xdae1, 0x0036, 0x2019, 0x0029, 0x080c, 0xd7e2, - 0x003e, 0x009e, 0x080c, 0xa01c, 0x080c, 0x8c6c, 0x0005, 0x9182, - 0x0085, 0x0002, 0xd2d9, 0xd2d7, 0xd2d7, 0xd2e5, 0xd2d7, 0xd2d7, - 0xd2d7, 0xd2d7, 0xd2d7, 0xd2d7, 0xd2d7, 0xd2d7, 0xd2d7, 0x080c, - 0x0df6, 0x6003, 0x000b, 0x6106, 0x080c, 0x85f8, 0x0126, 0x2091, - 0x8000, 0x080c, 0x8b8f, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, - 0xda33, 0x0118, 0x080c, 0x9fea, 0x0450, 0x2071, 0x0260, 0x7224, - 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4, 0x0150, 0x6010, 0x00b6, - 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011, 0x014e, 0x080c, 0xa30b, - 0x7220, 0x080c, 0xd637, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, - 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, - 0x0001, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x080c, 0x8c6c, 0x00ee, - 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, - 0x0a0c, 0x0df6, 0x908a, 0x0092, 0x1a0c, 0x0df6, 0x9082, 0x0085, - 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, 0x080c, - 0xa083, 0x0050, 0x2001, 0x0007, 0x080c, 0x6320, 0x080c, 0x8a83, - 0x080c, 0xa01c, 0x080c, 0x8b8f, 0x0005, 0xd34a, 0xd34c, 0xd34c, - 0xd34a, 0xd34a, 0xd34a, 0xd34a, 0xd34a, 0xd34a, 0xd34a, 0xd34a, - 0xd34a, 0xd34a, 0x080c, 0x0df6, 0x080c, 0x8a83, 0x080c, 0xa01c, - 0x080c, 0x8b8f, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0df6, 0x9182, - 0x0092, 0x1a0c, 0x0df6, 0x9182, 0x0085, 0x0002, 0xd36b, 0xd36b, - 0xd36b, 0xd36d, 0xd36b, 0xd36b, 0xd36b, 0xd36b, 0xd36b, 0xd36b, - 0xd36b, 0xd36b, 0xd36b, 0x080c, 0x0df6, 0x0005, 0x9186, 0x0013, - 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, - 0xa083, 0x0030, 0x080c, 0x8a83, 0x080c, 0xa01c, 0x080c, 0x8b8f, - 0x0005, 0x0036, 0x080c, 0xda94, 0x6043, 0x0000, 0x2019, 0x000b, - 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, - 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, - 0x995f, 0x009e, 0x008e, 0x1550, 0x0076, 0x2c38, 0x080c, 0x9a0a, - 0x007e, 0x1520, 0x6000, 0x9086, 0x0000, 0x0500, 0x6020, 0x9086, - 0x0007, 0x01e0, 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, 0xda94, - 0x080c, 0xc471, 0x080c, 0x192c, 0x6023, 0x0007, 0x6014, 0x2048, - 0x080c, 0xbd4e, 0x0110, 0x080c, 0xd7e2, 0x009e, 0x6017, 0x0000, - 0x080c, 0xda94, 0x6023, 0x0007, 0x080c, 0xc471, 0x003e, 0x012e, - 0x0005, 0x00f6, 0x00c6, 0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, - 0x7938, 0x783c, 0x080c, 0x266d, 0x1904, 0xd41f, 0x0016, 0x00c6, - 0x080c, 0x63a3, 0x1904, 0xd41d, 0x001e, 0x00c6, 0x080c, 0xc459, - 0x1130, 0xb8b0, 0x9005, 0x0118, 0x080c, 0x31e9, 0x0148, 0x2b10, - 0x2160, 0x6010, 0x0006, 0x6212, 0x080c, 0xc460, 0x000e, 0x6012, - 0x00ce, 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x9ad0, - 0x080c, 0x8782, 0x0076, 0x903e, 0x080c, 0x8670, 0x007e, 0x001e, - 0x0076, 0x903e, 0x080c, 0xd556, 0x007e, 0x0026, 0xba04, 0x9294, - 0xff00, 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, - 0xbaa0, 0x080c, 0x3152, 0x002e, 0xbcb0, 0x001e, 0x080c, 0x5e49, - 0xbe12, 0xbd16, 0xbcb2, 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, - 0x003e, 0x00be, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00b6, - 0x0016, 0x2009, 0x1823, 0x2104, 0x9086, 0x0074, 0x1904, 0xd47e, - 0x2069, 0x0260, 0x6944, 0x9182, 0x0100, 0x06e0, 0x6940, 0x9184, - 0x8000, 0x0904, 0xd47b, 0x2001, 0x1956, 0x2004, 0x9005, 0x1140, - 0x6010, 0x2058, 0xb8b0, 0x9005, 0x0118, 0x9184, 0x0800, 0x0598, - 0x6948, 0x918a, 0x0001, 0x0648, 0x080c, 0xdb49, 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, 0x63b2, 0x0804, 0xd4e5, 0x2011, 0x0276, - 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xb017, - 0x009e, 0x15a0, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, - 0x2019, 0x0006, 0x080c, 0xb017, 0x009e, 0x1540, 0x0046, 0x0016, - 0xbaa0, 0x2220, 0x9006, 0x2009, 0x185c, 0x210c, 0x0038, 0x2009, - 0x0029, 0x080c, 0xd837, 0xb800, 0xc0e5, 0xb802, 0x2019, 0x0029, - 0x080c, 0x8782, 0x0076, 0x2039, 0x0000, 0x080c, 0x8670, 0x2c08, - 0x080c, 0xd556, 0x007e, 0x2001, 0x0007, 0x080c, 0x6320, 0x2001, - 0x0007, 0x080c, 0x62f4, 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, 0x266d, 0x11d0, 0x080c, 0x63a3, - 0x11b8, 0x2011, 0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, - 0x000a, 0x080c, 0xb017, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, - 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xb017, 0x009e, - 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, - 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, - 0x8211, 0x220c, 0x080c, 0x266d, 0x11d0, 0x080c, 0x63a3, 0x11b8, - 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, - 0x080c, 0xb017, 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, - 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xb017, 0x009e, 0x015e, - 0x003e, 0x002e, 0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, - 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, - 0x8000, 0x2740, 0x2029, 0x19cb, 0x252c, 0x2021, 0x19d1, 0x2424, - 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7650, 0x7070, 0x81ff, 0x0150, - 0x0006, 0x9186, 0x1a88, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, - 0xd5f0, 0x0018, 0x9606, 0x0904, 0xd5f0, 0x2100, 0x9c06, 0x0904, - 0xd5e7, 0x6720, 0x9786, 0x0007, 0x0904, 0xd5e7, 0x080c, 0xd878, - 0x1904, 0xd5e7, 0x080c, 0xdb67, 0x0904, 0xd5e7, 0x080c, 0xd868, - 0x0904, 0xd5e7, 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, 0x31e9, - 0x0904, 0xd60b, 0x6004, 0x9086, 0x0000, 0x1904, 0xd60b, 0x9786, - 0x0004, 0x0904, 0xd60b, 0x2500, 0x9c06, 0x0904, 0xd5e7, 0x2400, - 0x9c06, 0x05e8, 0x88ff, 0x0118, 0x6054, 0x9906, 0x15c0, 0x0096, - 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x192c, 0x001e, - 0x9786, 0x000a, 0x0148, 0x080c, 0xbf56, 0x1130, 0x080c, 0xa9a7, - 0x009e, 0x080c, 0xa01c, 0x0418, 0x6014, 0x2048, 0x080c, 0xbd4e, - 0x01d8, 0x9786, 0x0003, 0x1570, 0xa867, 0x0103, 0xa87c, 0xd0cc, - 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fe9, 0x009e, 0xab7a, - 0xa877, 0x0000, 0x080c, 0xdae1, 0x0016, 0x080c, 0xc044, 0x080c, - 0x6a15, 0x001e, 0x080c, 0xbf39, 0x009e, 0x080c, 0xa01c, 0x9ce0, - 0x0018, 0x2001, 0x1819, 0x2004, 0x9c02, 0x1210, 0x0804, 0xd56a, - 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, - 0x00ee, 0x0005, 0x9786, 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, - 0x080c, 0xdae1, 0x080c, 0xd7e2, 0x08f8, 0x009e, 0x0c00, 0x9786, - 0x000a, 0x0968, 0x0808, 0x81ff, 0x09d0, 0x9180, 0x0001, 0x2004, - 0x9086, 0x0018, 0x0130, 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, - 0x1970, 0x6000, 0x9086, 0x0002, 0x1950, 0x080c, 0xbf45, 0x0130, - 0x080c, 0xbf56, 0x1920, 0x080c, 0xa9a7, 0x0038, 0x080c, 0x30be, - 0x080c, 0xbf56, 0x1110, 0x080c, 0xa9a7, 0x080c, 0xa01c, 0x0804, - 0xd5e7, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x0005, 0x00c6, - 0x00e6, 0x0016, 0x2c08, 0x2170, 0x9006, 0x080c, 0xd809, 0x001e, - 0x0120, 0x6020, 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, - 0xd656, 0xd656, 0xd656, 0xd656, 0xd656, 0xd656, 0xd658, 0xd656, - 0xd656, 0xd656, 0xd681, 0xa01c, 0xa01c, 0xd656, 0x9006, 0x0005, - 0x0036, 0x0046, 0x0016, 0x7010, 0x00b6, 0x2058, 0xbca0, 0x00be, - 0x2c00, 0x2009, 0x0020, 0x080c, 0xd837, 0x001e, 0x004e, 0x2019, - 0x0002, 0x080c, 0xd38f, 0x003e, 0x9085, 0x0001, 0x0005, 0x0096, - 0x080c, 0xbd4e, 0x0140, 0x6014, 0x904d, 0x080c, 0xb983, 0x687b, - 0x0005, 0x080c, 0x6a22, 0x009e, 0x080c, 0xa01c, 0x9085, 0x0001, - 0x0005, 0x0019, 0x9085, 0x0001, 0x0005, 0x6000, 0x908a, 0x0010, - 0x1a0c, 0x0df6, 0x000b, 0x0005, 0xd69c, 0xd69c, 0xd6b3, 0xd6a3, - 0xd6c2, 0xd69c, 0xd69c, 0xd69e, 0xd69c, 0xd69c, 0xd69c, 0xd69c, - 0xd69c, 0xd69c, 0xd69c, 0xd69c, 0x080c, 0x0df6, 0x080c, 0xa01c, - 0x9085, 0x0001, 0x0005, 0x0036, 0x00e6, 0x2071, 0x19c2, 0x703c, - 0x9c06, 0x1128, 0x2019, 0x0001, 0x080c, 0x98b1, 0x0010, 0x080c, - 0x9a8f, 0x00ee, 0x003e, 0x0096, 0x00d6, 0x6014, 0x2048, 0xa87b, - 0x0005, 0x080c, 0x6a22, 0x080c, 0xa01c, 0x00de, 0x009e, 0x9085, - 0x0001, 0x0005, 0x601c, 0xd084, 0x190c, 0x192c, 0x0c60, 0x2001, - 0x0001, 0x080c, 0x62e0, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, 0xb003, 0x003e, - 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x0086, 0x0076, 0x0066, 0x00b6, 0x0126, 0x2091, 0x8000, 0x2740, - 0x2061, 0x1cd0, 0x2079, 0x0001, 0x8fff, 0x0904, 0xd739, 0x2071, - 0x1800, 0x7650, 0x7070, 0x8001, 0x9602, 0x1a04, 0xd739, 0x88ff, - 0x0120, 0x2800, 0x9c06, 0x15a0, 0x2078, 0x080c, 0xd868, 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, 0xda94, 0x080c, 0xc471, 0x080c, 0x192c, - 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xbd4e, 0x0120, 0x0046, - 0x080c, 0xd7e2, 0x004e, 0x009e, 0x080c, 0xa01c, 0x88ff, 0x1198, - 0x9ce0, 0x0018, 0x2001, 0x1819, 0x2004, 0x9c02, 0x1210, 0x0804, - 0xd6ec, 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, 0x995f, 0x009e, 0x008e, - 0x903e, 0x080c, 0x9a0a, 0x080c, 0xd6dd, 0x005e, 0x007e, 0x00be, - 0x0005, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, - 0x2128, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, 0x63a3, - 0x1180, 0x0056, 0x0086, 0x9046, 0x2508, 0x2029, 0x0001, 0x0096, - 0x904e, 0x080c, 0x995f, 0x009e, 0x008e, 0x903e, 0x080c, 0x9a0a, - 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xd76c, 0x0036, 0x2508, - 0x2029, 0x0003, 0x080c, 0xd6dd, 0x003e, 0x015e, 0x00ce, 0x007e, - 0x005e, 0x004e, 0x00be, 0x0005, 0x00b6, 0x0076, 0x0056, 0x6210, - 0x2258, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, - 0x904e, 0x080c, 0x995f, 0x009e, 0x008e, 0x903e, 0x080c, 0x9a0a, - 0x2c20, 0x080c, 0xd6dd, 0x005e, 0x007e, 0x00be, 0x0005, 0x00b6, - 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, 0x0800, - 0x900e, 0x0016, 0x0036, 0x080c, 0x63a3, 0x1190, 0x0086, 0x9046, - 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, 0xda78, 0x004e, 0x0096, - 0x904e, 0x080c, 0x995f, 0x009e, 0x008e, 0x903e, 0x080c, 0x9a0a, - 0x003e, 0x001e, 0x8108, 0x1f04, 0xd7b9, 0x0036, 0x2029, 0x0002, - 0x080c, 0xd6dd, 0x003e, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, - 0x00be, 0x0005, 0x0016, 0x00f6, 0x080c, 0xbd4c, 0x0198, 0xa864, - 0x9084, 0x00ff, 0x9086, 0x0046, 0x0180, 0xa800, 0x907d, 0x0138, - 0xa803, 0x0000, 0xab82, 0x080c, 0x6a22, 0x2f48, 0x0cb0, 0xab82, - 0x080c, 0x6a22, 0x00fe, 0x001e, 0x0005, 0xa800, 0x907d, 0x0130, - 0xa803, 0x0000, 0x080c, 0x6a22, 0x2f48, 0x0cb8, 0x080c, 0x6a22, - 0x0c88, 0x00e6, 0x0046, 0x0036, 0x2061, 0x1cd0, 0x9005, 0x1138, - 0x2071, 0x1800, 0x7450, 0x7070, 0x8001, 0x9402, 0x12d8, 0x2100, - 0x9c06, 0x0168, 0x6000, 0x9086, 0x0000, 0x0148, 0x6008, 0x9206, - 0x1130, 0x6010, 0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, - 0x0018, 0x2001, 0x1819, 0x2004, 0x9c02, 0x1220, 0x0c40, 0x9085, - 0x0001, 0x0008, 0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x0096, - 0x0006, 0x080c, 0x1037, 0x000e, 0x090c, 0x0df6, 0xaae2, 0xa867, - 0x010d, 0xa88e, 0x0026, 0x2010, 0x080c, 0xbd3c, 0x2001, 0x0000, - 0x0120, 0x2200, 0x9080, 0x0015, 0x2004, 0x002e, 0xa87a, 0x9186, - 0x0020, 0x0110, 0xa8e3, 0xffff, 0xa986, 0xac76, 0xa87f, 0x0000, - 0x2001, 0x1968, 0x2004, 0xa882, 0x9006, 0xa802, 0xa86a, 0xa88a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6a22, 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, - 0x1961, 0x2004, 0x601a, 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x001e, - 0x0005, 0xa001, 0xa001, 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, - 0x0118, 0x080c, 0xc088, 0x0030, 0x080c, 0xda94, 0x080c, 0x8425, - 0x080c, 0x9fea, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, - 0x0002, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c9, 0xd8c7, 0xd8c9, 0xd8c9, - 0xd8c7, 0xd8c9, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0x9006, - 0x0005, 0x9085, 0x0001, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, - 0x000f, 0x0002, 0xd8e0, 0xd8e0, 0xd8e0, 0xd8e0, 0xd8e0, 0xd8e0, - 0xd8ed, 0xd8e0, 0xd8e0, 0xd8e0, 0xd8e0, 0xd8e0, 0xd8e0, 0xd8e0, - 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, - 0x080c, 0x85f8, 0x080c, 0x8b8f, 0x0005, 0x0096, 0x00c6, 0x2260, - 0x080c, 0xda94, 0x6043, 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, - 0x603b, 0x0000, 0x00ce, 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, - 0xd946, 0x6814, 0x9005, 0x0138, 0x2048, 0xa87c, 0xd0fc, 0x1118, - 0x00de, 0x009e, 0x08a8, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, - 0x85f8, 0x080c, 0x8b8f, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, - 0x1904, 0xd9bd, 0x6014, 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, - 0x190c, 0x0df6, 0x0804, 0xd9bd, 0x2048, 0x080c, 0xbd4e, 0x1130, - 0x0028, 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, 0x2048, 0xa87c, - 0x9084, 0x0003, 0x9086, 0x0002, 0x1168, 0xa87c, 0xc0dc, 0xc0f4, - 0xa87e, 0xa880, 0xc0fc, 0xa882, 0x2009, 0x0043, 0x080c, 0xd1e3, - 0x0804, 0xd9bd, 0x2009, 0x0041, 0x0804, 0xd9b7, 0x9186, 0x0005, - 0x15a0, 0x6814, 0x2048, 0xa87c, 0xd0bc, 0x1120, 0x00de, 0x009e, - 0x0804, 0xd8e0, 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x0df6, 0x0804, - 0xd901, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, 0x85f8, 0x080c, - 0x8b8f, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, - 0x0004, 0x1904, 0xd9bd, 0x6814, 0x2048, 0xa97c, 0xc1f4, 0xc1dc, - 0xa97e, 0xa980, 0xc1fc, 0xc1bc, 0xa982, 0x00f6, 0x2c78, 0x080c, - 0x1651, 0x00fe, 0x2009, 0x0042, 0x04d0, 0x0036, 0x080c, 0x1037, - 0x090c, 0x0df6, 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, 0x6a22, 0x2019, 0x0045, - 0x6008, 0x2068, 0x080c, 0xd38f, 0x2d00, 0x600a, 0x6023, 0x0006, - 0x6003, 0x0007, 0x901e, 0x631a, 0x6342, 0x003e, 0x0038, 0x6043, - 0x0000, 0x6003, 0x0007, 0x080c, 0xd1e3, 0x00ce, 0x00de, 0x009e, - 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, - 0x00c2, 0x9186, 0x0027, 0x1178, 0x080c, 0x8a83, 0x0036, 0x0096, - 0x6014, 0x2048, 0x2019, 0x0004, 0x080c, 0xd7e2, 0x009e, 0x003e, - 0x080c, 0x8b8f, 0x0005, 0x9186, 0x0014, 0x0d70, 0x080c, 0xa083, - 0x0005, 0xd9f0, 0xd9ee, 0xd9ee, 0xd9ee, 0xd9ee, 0xd9ee, 0xd9f0, - 0xd9ee, 0xd9ee, 0xd9ee, 0xd9ee, 0xd9ee, 0xd9ee, 0x080c, 0x0df6, - 0x080c, 0x8a83, 0x6003, 0x000c, 0x080c, 0x8b8f, 0x0005, 0x9182, - 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, 0x001a, 0x080c, 0xa083, - 0x0005, 0xda0e, 0xda0e, 0xda0e, 0xda0e, 0xda10, 0xda30, 0xda0e, - 0xda0e, 0xda0e, 0xda0e, 0xda0e, 0xda0e, 0xda0e, 0x080c, 0x0df6, - 0x00d6, 0x2c68, 0x080c, 0x9f94, 0x01b0, 0x6003, 0x0001, 0x6007, - 0x001e, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, - 0x613e, 0x600b, 0xffff, 0x6910, 0x6112, 0x6023, 0x0004, 0x080c, - 0x85f8, 0x080c, 0x8b8f, 0x2d60, 0x080c, 0x9fea, 0x00de, 0x0005, - 0x080c, 0x9fea, 0x0005, 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0ec, 0x00ee, 0x0005, 0x2009, 0x187b, 0x210c, 0xd1ec, - 0x05b0, 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026, 0xd0cc, 0x0150, - 0x2001, 0x1962, 0x2004, 0x6042, 0x2009, 0x187b, 0x210c, 0xd1f4, - 0x1520, 0x00a0, 0x2009, 0x187b, 0x210c, 0xd1f4, 0x0128, 0x6024, - 0xc0e4, 0x6026, 0x9006, 0x00d8, 0x2001, 0x1962, 0x200c, 0x2001, - 0x1960, 0x2004, 0x9100, 0x9080, 0x000a, 0x6042, 0x6010, 0x00b6, - 0x2058, 0xb8ac, 0x00be, 0x0008, 0x2104, 0x9005, 0x0118, 0x9088, - 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0x9085, 0x0001, 0x0005, - 0x0016, 0x00c6, 0x00e6, 0x6154, 0xb8ac, 0x2060, 0x8cff, 0x0180, - 0x84ff, 0x1118, 0x6054, 0x9106, 0x1138, 0x600c, 0x2072, 0x080c, - 0x8425, 0x080c, 0x9fea, 0x0010, 0x9cf0, 0x0003, 0x2e64, 0x0c70, - 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x00b6, 0x6010, 0x2058, - 0xb8ac, 0x906d, 0x0130, 0x9c06, 0x0110, 0x680c, 0x0cd0, 0x600c, - 0x680e, 0x00be, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156, 0x2011, - 0x182b, 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, 0xb017, 0x009e, 0x1168, 0x2011, - 0x0274, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x0006, - 0x080c, 0xb017, 0x009e, 0x1100, 0x015e, 0x003e, 0x002e, 0x0005, - 0x00e6, 0x2071, 0x1800, 0x080c, 0x5dc2, 0x080c, 0x2e73, 0x00ee, - 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, 0x19cb, 0x252c, 0x2021, - 0x19d1, 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7650, 0x7070, - 0x9606, 0x0578, 0x6720, 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, - 0x1500, 0x2500, 0x9c06, 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, - 0xd868, 0x01b8, 0x080c, 0xd878, 0x11a0, 0x6000, 0x9086, 0x0004, - 0x1120, 0x0016, 0x080c, 0x192c, 0x001e, 0x080c, 0xbf45, 0x1110, - 0x080c, 0x30be, 0x080c, 0xbf56, 0x1110, 0x080c, 0xa9a7, 0x080c, - 0xa01c, 0x9ce0, 0x0018, 0x2001, 0x1819, 0x2004, 0x9c02, 0x1208, - 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, - 0x00ce, 0x00de, 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0dc, - 0x0005, 0x0006, 0x2001, 0x1836, 0x2004, 0xd09c, 0x000e, 0x0005, - 0x0006, 0x0036, 0x0046, 0x080c, 0xc459, 0x0168, 0x2019, 0xffff, - 0x9005, 0x0128, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, - 0x0004, 0x080c, 0x4bb4, 0x004e, 0x003e, 0x000e, 0x0005, 0x6004, - 0x9086, 0x0001, 0x1128, 0x080c, 0x9ad0, 0x080c, 0xa01c, 0x9006, - 0x0005, 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x2061, 0x1cd0, 0x2071, - 0x1800, 0x7450, 0x7070, 0x8001, 0x9402, 0x12d8, 0x2100, 0x9c06, - 0x0168, 0x6000, 0x9086, 0x0000, 0x0148, 0x6010, 0x2058, 0xb8a0, - 0x9206, 0x1120, 0x6004, 0x9086, 0x0002, 0x0140, 0x9ce0, 0x0018, - 0x2001, 0x1819, 0x2004, 0x9c02, 0x1220, 0x0c40, 0x9085, 0x0001, - 0x0008, 0x9006, 0x004e, 0x00be, 0x00ce, 0x00ee, 0x0005, 0x2001, - 0x1810, 0x2004, 0xd0a4, 0x0160, 0x2001, 0x1836, 0x2004, 0xd0a4, - 0x0138, 0x2001, 0x185c, 0x2004, 0xd0a4, 0x1118, 0x9085, 0x0001, - 0x0005, 0x9006, 0x0ce8, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, - 0x8000, 0x2071, 0x1840, 0xd5a4, 0x0118, 0x7054, 0x8000, 0x7056, - 0xd5b4, 0x0118, 0x7050, 0x8000, 0x7052, 0xd5ac, 0x0178, 0x2500, - 0x9084, 0x0007, 0x908e, 0x0003, 0x0148, 0x908e, 0x0004, 0x0130, - 0x908e, 0x0005, 0x0118, 0x2071, 0x184a, 0x0089, 0x001e, 0x00ee, - 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, - 0x2071, 0x1842, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, - 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, - 0x00e6, 0x2071, 0x1840, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, - 0x1844, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, - 0x8000, 0x2071, 0x1840, 0x7064, 0x8000, 0x7066, 0x00ee, 0x000e, - 0x012e, 0x0005, 0x0003, 0x000b, 0x03ce, 0x0000, 0xc000, 0x0001, - 0x8064, 0x0008, 0x0010, 0x0000, 0x8066, 0x0000, 0x0101, 0x0008, - 0x4407, 0x0003, 0x8060, 0x0000, 0x0400, 0x0000, 0x580d, 0x000b, - 0x7924, 0x0003, 0x5096, 0x000b, 0x4c0a, 0x0003, 0xbac0, 0x0009, - 0x008a, 0x0000, 0x0c0a, 0x000b, 0x15fe, 0x0008, 0x340a, 0x0003, - 0xc4c0, 0x0009, 0x7000, 0x0000, 0xffa0, 0x0001, 0x2000, 0x0000, - 0x15bf, 0x000b, 0x808c, 0x0008, 0x0001, 0x0000, 0x0000, 0x0007, - 0x4047, 0x000a, 0x808c, 0x0008, 0x0002, 0x0000, 0x0821, 0x0003, - 0x4022, 0x0000, 0x0022, 0x000b, 0x4122, 0x0008, 0x4447, 0x0002, - 0x0de3, 0x000b, 0x0bfe, 0x0008, 0x11a0, 0x0001, 0x11c5, 0x000b, - 0x0ca0, 0x0001, 0x11c5, 0x000b, 0x9180, 0x0001, 0x0004, 0x0000, - 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x0009, 0x0008, 0x4430, 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, - 0x0060, 0x0008, 0x8062, 0x0008, 0x0004, 0x0000, 0x8066, 0x0000, - 0x0411, 0x0000, 0x4438, 0x0003, 0x03fe, 0x0000, 0x43e0, 0x0001, - 0x0dc2, 0x000b, 0xc2c0, 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001, - 0x0dc2, 0x000b, 0x9180, 0x0001, 0x0005, 0x0008, 0x8060, 0x0000, - 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0019, 0x0000, - 0x4447, 0x000b, 0x0240, 0x0002, 0x09bf, 0x0003, 0x00fe, 0x0000, - 0x31c2, 0x000b, 0x112a, 0x0000, 0x002e, 0x0008, 0x022c, 0x0008, - 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x808c, 0x0008, 0x0002, 0x0000, - 0x1760, 0x0008, 0x8062, 0x0008, 0x000f, 0x0008, 0x8066, 0x0000, - 0x0011, 0x0008, 0x4458, 0x0003, 0x01fe, 0x0008, 0x42e0, 0x0009, - 0x0db5, 0x000b, 0x00fe, 0x0000, 0x43e0, 0x0001, 0x0db5, 0x000b, - 0x1734, 0x0000, 0x1530, 0x0000, 0x1632, 0x0008, 0x0d2a, 0x0008, - 0x9880, 0x0001, 0x0010, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x1e0a, 0x0008, 0x446a, 0x000b, - 0x808a, 0x0008, 0x0003, 0x0008, 0x1a60, 0x0000, 0x8062, 0x0008, - 0x0002, 0x0000, 0x5870, 0x000b, 0x8066, 0x0000, 0x3679, 0x0000, - 0x4473, 0x0003, 0x5874, 0x0003, 0x8054, 0x0008, 0x0011, 0x0008, - 0x8074, 0x0000, 0x1010, 0x0008, 0x1efe, 0x0000, 0x300a, 0x000b, - 0x007d, 0x0004, 0x000a, 0x000b, 0x1c60, 0x0000, 0x1b62, 0x0000, - 0x8066, 0x0000, 0x0231, 0x0008, 0x4481, 0x000b, 0x5882, 0x0003, - 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, 0x0002, 0x0c8c, 0x0003, - 0x0d44, 0x0000, 0x0d46, 0x0008, 0x0348, 0x0008, 0x044a, 0x0008, - 0x0090, 0x000b, 0x0344, 0x0008, 0x0446, 0x0008, 0x0548, 0x0008, - 0x064a, 0x0000, 0x5890, 0x0003, 0x8054, 0x0008, 0x0001, 0x0000, - 0x8074, 0x0000, 0x2020, 0x0008, 0x4000, 0x000f, 0x3a40, 0x000a, - 0x0c0d, 0x0003, 0xabd0, 0x0001, 0x0000, 0x0008, 0x7f24, 0x0000, - 0x589b, 0x000b, 0x8054, 0x0008, 0x0002, 0x0000, 0x1242, 0x0002, - 0x08e1, 0x0003, 0x3a45, 0x000a, 0x08d0, 0x000b, 0x1e10, 0x000a, - 0x7f3c, 0x0000, 0x08cd, 0x000b, 0x1d00, 0x0002, 0x7f3a, 0x0000, - 0x0d60, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, - 0x44ab, 0x0003, 0x00fe, 0x0000, 0x34ca, 0x0003, 0x1c60, 0x0000, - 0x8062, 0x0008, 0x0001, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, - 0x44b3, 0x0003, 0x00fe, 0x0000, 0x319e, 0x000b, 0x0038, 0x0000, - 0x0060, 0x0008, 0x8062, 0x0008, 0x0019, 0x0000, 0x8066, 0x0000, - 0x0009, 0x0008, 0x44bc, 0x0003, 0x80c0, 0x0009, 0x00ff, 0x0008, - 0x7f3e, 0x0008, 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x44c6, 0x000b, - 0x003a, 0x0008, 0x1dfe, 0x0000, 0x00a7, 0x0003, 0x0036, 0x0008, - 0x007d, 0x0004, 0x00e1, 0x000b, 0x8074, 0x0000, 0x2000, 0x0000, - 0x00e1, 0x000b, 0x3a44, 0x0002, 0x09c8, 0x0003, 0x8074, 0x0000, - 0x1000, 0x0000, 0xadd0, 0x0001, 0x0000, 0x0008, 0x7f0e, 0x0008, - 0x359b, 0x0003, 0xa7d0, 0x0001, 0x0000, 0x0008, 0x7f00, 0x0000, - 0xa6d0, 0x0009, 0x0000, 0x0008, 0x00d0, 0x0009, 0x0cf1, 0x0003, - 0x8074, 0x0000, 0x4040, 0x0008, 0x58e1, 0x0003, 0x5096, 0x000b, - 0x3a46, 0x000a, 0x0cf1, 0x0003, 0x3a47, 0x0002, 0x08ec, 0x000b, - 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0x8000, 0x0000, - 0x0118, 0x0003, 0x92c0, 0x0009, 0x0fc8, 0x0000, 0x080a, 0x0003, - 0x1246, 0x000a, 0x0d95, 0x0003, 0x1a60, 0x0000, 0x8062, 0x0008, - 0x0002, 0x0000, 0x8066, 0x0000, 0x367a, 0x0000, 0x44f6, 0x000b, - 0x92c0, 0x0009, 0x0780, 0x0008, 0x0daf, 0x0003, 0x124b, 0x0002, - 0x08ff, 0x0003, 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x099b, 0x0003, - 0x3a46, 0x000a, 0x0d0c, 0x0003, 0x5901, 0x0003, 0x8054, 0x0008, - 0x0004, 0x0000, 0x1243, 0x000a, 0x0916, 0x0003, 0x8010, 0x0008, - 0x000d, 0x0000, 0x0189, 0x0004, 0x1810, 0x0000, 0x0189, 0x0004, - 0x0116, 0x000b, 0x194d, 0x000a, 0x0910, 0x0003, 0x1243, 0x000a, - 0x09a5, 0x000b, 0x5910, 0x0003, 0x8054, 0x0008, 0x0004, 0x0000, - 0x017e, 0x000c, 0x1810, 0x0000, 0x0189, 0x0004, 0x8074, 0x0000, - 0xf000, 0x0008, 0x0d30, 0x0000, 0x3a42, 0x0002, 0x0d1e, 0x0003, - 0x15fe, 0x0008, 0x3451, 0x000b, 0x000a, 0x000b, 0x8074, 0x0000, - 0x0501, 0x0000, 0x8010, 0x0008, 0x000c, 0x0008, 0x0189, 0x0004, - 0x000a, 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0d34, 0x000b, - 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0931, 0x0003, 0x15fe, 0x0008, - 0x3ce0, 0x0009, 0x0931, 0x0003, 0x0179, 0x0004, 0x8076, 0x0008, - 0x0040, 0x0000, 0x0176, 0x000b, 0x8076, 0x0008, 0x0041, 0x0008, - 0x0176, 0x000b, 0xbbe0, 0x0009, 0x0032, 0x0000, 0x0d39, 0x0003, - 0x3c1e, 0x0008, 0x0176, 0x000b, 0xbbe0, 0x0009, 0x0037, 0x0000, - 0x0d5b, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0d31, 0x000b, - 0x8076, 0x0008, 0x0040, 0x0000, 0x1a60, 0x0000, 0x8062, 0x0008, - 0x000d, 0x0000, 0xa6d0, 0x0009, 0x0000, 0x0008, 0x7f04, 0x0008, - 0xa7d0, 0x0001, 0x0000, 0x0008, 0x7f06, 0x0000, 0xa8d0, 0x0001, - 0x0000, 0x0008, 0x7f08, 0x0008, 0xa9d0, 0x0009, 0x0000, 0x0008, - 0x7f0a, 0x0000, 0x8066, 0x0000, 0x0422, 0x0000, 0x4552, 0x000b, - 0x017e, 0x000c, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, - 0xf000, 0x0008, 0x8072, 0x0000, 0x8000, 0x0000, 0x0118, 0x0003, - 0xbbe0, 0x0009, 0x0038, 0x0000, 0x0d6d, 0x000b, 0x18fe, 0x0000, - 0x3ce0, 0x0009, 0x096a, 0x000b, 0x15fe, 0x0008, 0x3ce0, 0x0009, - 0x0d2d, 0x0003, 0x0179, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, - 0x8072, 0x0000, 0x8000, 0x0000, 0x01bf, 0x000b, 0x8076, 0x0008, - 0x0042, 0x0008, 0x0176, 0x000b, 0xbbe0, 0x0009, 0x0016, 0x0000, - 0x0d76, 0x000b, 0x3a44, 0x0002, 0x0c0c, 0x000b, 0x8072, 0x0000, - 0x8000, 0x0000, 0x8000, 0x000f, 0x000a, 0x000b, 0x8072, 0x0000, - 0x8000, 0x0000, 0x000a, 0x000b, 0x3d30, 0x000a, 0x7f00, 0x0000, - 0xbc80, 0x0001, 0x0007, 0x0000, 0x0182, 0x0003, 0x1930, 0x000a, - 0x7f00, 0x0000, 0x9880, 0x0001, 0x0007, 0x0000, 0x8060, 0x0000, - 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x000a, 0x0008, - 0x4587, 0x0003, 0x4000, 0x000f, 0x2189, 0x0003, 0x0870, 0x0008, - 0x4000, 0x000f, 0xbac0, 0x0009, 0x0090, 0x0008, 0x0992, 0x0003, - 0x8074, 0x0000, 0x0706, 0x0000, 0x0194, 0x000b, 0x8074, 0x0000, - 0x0703, 0x0000, 0x4000, 0x000f, 0x8010, 0x0008, 0x0023, 0x0000, - 0x01cd, 0x000b, 0x8010, 0x0008, 0x0008, 0x0000, 0x01cd, 0x000b, - 0x8010, 0x0008, 0x0022, 0x0008, 0x01cd, 0x000b, 0x017e, 0x000c, - 0x8010, 0x0008, 0x0007, 0x0000, 0x0189, 0x0004, 0x1810, 0x0000, - 0x0189, 0x0004, 0x01d7, 0x0003, 0x017e, 0x000c, 0x8010, 0x0008, - 0x001b, 0x0008, 0x0189, 0x0004, 0x1810, 0x0000, 0x0189, 0x0004, - 0x8074, 0x0000, 0xf080, 0x0000, 0x0d30, 0x0000, 0x000a, 0x000b, - 0x8010, 0x0008, 0x0009, 0x0008, 0x01cd, 0x000b, 0x8010, 0x0008, - 0x0005, 0x0008, 0x01cd, 0x000b, 0x808c, 0x0008, 0x0001, 0x0000, - 0x8010, 0x0008, 0x0004, 0x0000, 0x4143, 0x000a, 0x085f, 0x0003, - 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x0d2a, 0x0008, 0x01cd, 0x000b, - 0x8010, 0x0008, 0x0003, 0x0008, 0x01cf, 0x0003, 0x8010, 0x0008, - 0x000b, 0x0000, 0x01cf, 0x0003, 0x8010, 0x0008, 0x0002, 0x0000, - 0x01cf, 0x0003, 0x3a47, 0x0002, 0x0ce1, 0x000b, 0x8010, 0x0008, - 0x0006, 0x0008, 0x01cf, 0x0003, 0x8074, 0x0000, 0xf000, 0x0008, - 0x0189, 0x0004, 0x018c, 0x0004, 0x3a40, 0x000a, 0x080a, 0x0003, - 0x8010, 0x0008, 0x000c, 0x0008, 0x0189, 0x0004, 0x000a, 0x000b, - 0x8074, 0x0000, 0xf080, 0x0000, 0x0d30, 0x0000, 0x2e4d, 0x0002, - 0x2e4d, 0x0002, 0x09e0, 0x0003, 0x8054, 0x0008, 0x0019, 0x0000, - 0x000a, 0x000b, 0x8054, 0x0008, 0x0009, 0x0008, 0x000a, 0x000b, - 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x01c2, 0x000b, 0x0a0b, 0xf5dd, - 0x0003, 0x000b, 0x03ce, 0x0000, 0xc000, 0x0001, 0x8064, 0x0008, - 0x0010, 0x0000, 0x8066, 0x0000, 0x0101, 0x0008, 0xc007, 0x0003, - 0x8060, 0x0000, 0x0400, 0x0000, 0x580d, 0x000b, 0x7924, 0x0003, - 0x5096, 0x000b, 0xc80a, 0x0003, 0xbac0, 0x0009, 0x008a, 0x0000, - 0x880a, 0x000b, 0x15fe, 0x0008, 0xb00a, 0x0003, 0xc4c0, 0x0009, - 0x7000, 0x0000, 0xffa0, 0x0001, 0x2000, 0x0000, 0x91bf, 0x000b, - 0x808c, 0x0008, 0x0001, 0x0000, 0x0000, 0x0007, 0x4047, 0x000a, - 0x808c, 0x0008, 0x0002, 0x0000, 0x0821, 0x0003, 0x4022, 0x0000, - 0x0022, 0x000b, 0x4122, 0x0008, 0x4447, 0x0002, 0x89e3, 0x000b, - 0x0bfe, 0x0008, 0x11a0, 0x0001, 0x11c5, 0x000b, 0x0ca0, 0x0001, - 0x11c5, 0x000b, 0x9180, 0x0001, 0x0004, 0x0000, 0x8060, 0x0000, - 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, - 0xc030, 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, 0x0060, 0x0008, - 0x8062, 0x0008, 0x0004, 0x0000, 0x8066, 0x0000, 0x0411, 0x0000, - 0xc038, 0x0003, 0x03fe, 0x0000, 0x43e0, 0x0001, 0x89c2, 0x000b, - 0xc2c0, 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001, 0x89c2, 0x000b, - 0x9180, 0x0001, 0x0005, 0x0008, 0x8060, 0x0000, 0x0400, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0019, 0x0000, 0xc047, 0x000b, - 0x0240, 0x0002, 0x09bf, 0x0003, 0x00fe, 0x0000, 0x31c2, 0x000b, - 0x112a, 0x0000, 0x002e, 0x0008, 0x022c, 0x0008, 0x3a44, 0x0002, - 0x880a, 0x000b, 0x808c, 0x0008, 0x0002, 0x0000, 0x1760, 0x0008, - 0x8062, 0x0008, 0x000f, 0x0008, 0x8066, 0x0000, 0x0011, 0x0008, - 0xc058, 0x0003, 0x01fe, 0x0008, 0x42e0, 0x0009, 0x89b5, 0x000b, - 0x00fe, 0x0000, 0x43e0, 0x0001, 0x89b5, 0x000b, 0x1734, 0x0000, - 0x1530, 0x0000, 0x1632, 0x0008, 0x0d2a, 0x0008, 0x9880, 0x0001, - 0x0010, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x1e0a, 0x0008, 0xc06a, 0x000b, 0x808a, 0x0008, - 0x0003, 0x0008, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0002, 0x0000, - 0x5870, 0x000b, 0x8066, 0x0000, 0x3679, 0x0000, 0xc073, 0x0003, - 0x5874, 0x0003, 0x8054, 0x0008, 0x0011, 0x0008, 0x8074, 0x0000, - 0x1010, 0x0008, 0x1efe, 0x0000, 0x300a, 0x000b, 0x007d, 0x0004, - 0x000a, 0x000b, 0x1c60, 0x0000, 0x1b62, 0x0000, 0x8066, 0x0000, - 0x0231, 0x0008, 0xc081, 0x000b, 0x5882, 0x0003, 0x0140, 0x0008, - 0x0242, 0x0000, 0x1f43, 0x0002, 0x888c, 0x0003, 0x0d44, 0x0000, - 0x0d46, 0x0008, 0x0348, 0x0008, 0x044a, 0x0008, 0x0090, 0x000b, - 0x0344, 0x0008, 0x0446, 0x0008, 0x0548, 0x0008, 0x064a, 0x0000, - 0x5890, 0x0003, 0x8054, 0x0008, 0x0001, 0x0000, 0x8074, 0x0000, - 0x2020, 0x0008, 0x4000, 0x000f, 0x3a40, 0x000a, 0x880d, 0x0003, - 0xabd0, 0x0001, 0x0000, 0x0008, 0x7f24, 0x0000, 0x589b, 0x000b, - 0x8054, 0x0008, 0x0002, 0x0000, 0x1242, 0x0002, 0x08e1, 0x0003, - 0x3a45, 0x000a, 0x08d0, 0x000b, 0x1e10, 0x000a, 0x7f3c, 0x0000, - 0x08cd, 0x000b, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0xc0ab, 0x0003, - 0x00fe, 0x0000, 0xb0ca, 0x0003, 0x1c60, 0x0000, 0x8062, 0x0008, - 0x0001, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, 0xc0b3, 0x0003, - 0x00fe, 0x0000, 0x319e, 0x000b, 0x0038, 0x0000, 0x0060, 0x0008, - 0x8062, 0x0008, 0x0019, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, - 0xc0bc, 0x0003, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, 0x0008, - 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x0009, 0x0008, 0xc0c6, 0x000b, 0x003a, 0x0008, - 0x1dfe, 0x0000, 0x00a7, 0x0003, 0x0036, 0x0008, 0x007d, 0x0004, - 0x00e1, 0x000b, 0x8074, 0x0000, 0x2000, 0x0000, 0x00e1, 0x000b, - 0x3a44, 0x0002, 0x09c8, 0x0003, 0x8074, 0x0000, 0x1000, 0x0000, - 0xadd0, 0x0001, 0x0000, 0x0008, 0x7f0e, 0x0008, 0xb19b, 0x0003, - 0xa7d0, 0x0001, 0x0000, 0x0008, 0x7f00, 0x0000, 0xa6d0, 0x0009, - 0x0000, 0x0008, 0x00d0, 0x0009, 0x88f1, 0x0003, 0x8074, 0x0000, - 0x4040, 0x0008, 0x58e1, 0x0003, 0x5096, 0x000b, 0x3a46, 0x000a, - 0x88f1, 0x0003, 0x3a47, 0x0002, 0x08ec, 0x000b, 0x8054, 0x0008, - 0x0004, 0x0000, 0x8074, 0x0000, 0x8000, 0x0000, 0x0118, 0x0003, - 0x92c0, 0x0009, 0x0fc8, 0x0000, 0x080a, 0x0003, 0x1246, 0x000a, - 0x8995, 0x0003, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0002, 0x0000, - 0x8066, 0x0000, 0x367a, 0x0000, 0xc0f6, 0x000b, 0x92c0, 0x0009, - 0x0780, 0x0008, 0x89af, 0x0003, 0x124b, 0x0002, 0x08ff, 0x0003, - 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x099b, 0x0003, 0x3a46, 0x000a, - 0x890c, 0x0003, 0x5901, 0x0003, 0x8054, 0x0008, 0x0004, 0x0000, - 0x1243, 0x000a, 0x0916, 0x0003, 0x8010, 0x0008, 0x000d, 0x0000, - 0x0189, 0x0004, 0x1810, 0x0000, 0x0189, 0x0004, 0x0116, 0x000b, - 0x194d, 0x000a, 0x0910, 0x0003, 0x1243, 0x000a, 0x09a5, 0x000b, - 0x5910, 0x0003, 0x8054, 0x0008, 0x0004, 0x0000, 0x017e, 0x000c, - 0x1810, 0x0000, 0x0189, 0x0004, 0x8074, 0x0000, 0xf000, 0x0008, - 0x0d30, 0x0000, 0x3a42, 0x0002, 0x891e, 0x0003, 0x15fe, 0x0008, - 0xb051, 0x000b, 0x000a, 0x000b, 0x8074, 0x0000, 0x0501, 0x0000, - 0x8010, 0x0008, 0x000c, 0x0008, 0x0189, 0x0004, 0x000a, 0x000b, - 0xbbe0, 0x0009, 0x0030, 0x0008, 0x8934, 0x000b, 0x18fe, 0x0000, - 0x3ce0, 0x0009, 0x0931, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, - 0x0931, 0x0003, 0x0179, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, - 0x0176, 0x000b, 0x8076, 0x0008, 0x0041, 0x0008, 0x0176, 0x000b, - 0xbbe0, 0x0009, 0x0032, 0x0000, 0x8939, 0x0003, 0x3c1e, 0x0008, - 0x0176, 0x000b, 0xbbe0, 0x0009, 0x0037, 0x0000, 0x895b, 0x000b, - 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x8931, 0x000b, 0x8076, 0x0008, - 0x0040, 0x0000, 0x1a60, 0x0000, 0x8062, 0x0008, 0x000d, 0x0000, - 0xa6d0, 0x0009, 0x0000, 0x0008, 0x7f04, 0x0008, 0xa7d0, 0x0001, - 0x0000, 0x0008, 0x7f06, 0x0000, 0xa8d0, 0x0001, 0x0000, 0x0008, - 0x7f08, 0x0008, 0xa9d0, 0x0009, 0x0000, 0x0008, 0x7f0a, 0x0000, - 0x8066, 0x0000, 0x0422, 0x0000, 0xc152, 0x000b, 0x017e, 0x000c, - 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0xf000, 0x0008, - 0x8072, 0x0000, 0x8000, 0x0000, 0x0118, 0x0003, 0xbbe0, 0x0009, - 0x0038, 0x0000, 0x896d, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, - 0x096a, 0x000b, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x892d, 0x0003, - 0x0179, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x8072, 0x0000, - 0x8000, 0x0000, 0x01bf, 0x000b, 0x8076, 0x0008, 0x0042, 0x0008, - 0x0176, 0x000b, 0xbbe0, 0x0009, 0x0016, 0x0000, 0x8976, 0x000b, - 0x3a44, 0x0002, 0x880c, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, - 0x8000, 0x000f, 0x000a, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, - 0x000a, 0x000b, 0x3d30, 0x000a, 0x7f00, 0x0000, 0xbc80, 0x0001, - 0x0007, 0x0000, 0x0182, 0x0003, 0x1930, 0x000a, 0x7f00, 0x0000, - 0x9880, 0x0001, 0x0007, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x000a, 0x0008, 0xc187, 0x0003, - 0x4000, 0x000f, 0x2189, 0x0003, 0x0870, 0x0008, 0x4000, 0x000f, - 0xbac0, 0x0009, 0x0090, 0x0008, 0x0992, 0x0003, 0x8074, 0x0000, - 0x0706, 0x0000, 0x0194, 0x000b, 0x8074, 0x0000, 0x0703, 0x0000, - 0x4000, 0x000f, 0x8010, 0x0008, 0x0023, 0x0000, 0x01cd, 0x000b, - 0x8010, 0x0008, 0x0008, 0x0000, 0x01cd, 0x000b, 0x8010, 0x0008, - 0x0022, 0x0008, 0x01cd, 0x000b, 0x017e, 0x000c, 0x8010, 0x0008, - 0x0007, 0x0000, 0x0189, 0x0004, 0x1810, 0x0000, 0x0189, 0x0004, - 0x01d7, 0x0003, 0x017e, 0x000c, 0x8010, 0x0008, 0x001b, 0x0008, - 0x0189, 0x0004, 0x1810, 0x0000, 0x0189, 0x0004, 0x8074, 0x0000, - 0xf080, 0x0000, 0x0d30, 0x0000, 0x000a, 0x000b, 0x8010, 0x0008, - 0x0009, 0x0008, 0x01cd, 0x000b, 0x8010, 0x0008, 0x0005, 0x0008, - 0x01cd, 0x000b, 0x808c, 0x0008, 0x0001, 0x0000, 0x8010, 0x0008, - 0x0004, 0x0000, 0x4143, 0x000a, 0x085f, 0x0003, 0x3a44, 0x0002, - 0x880a, 0x000b, 0x0d2a, 0x0008, 0x01cd, 0x000b, 0x8010, 0x0008, - 0x0003, 0x0008, 0x01cf, 0x0003, 0x8010, 0x0008, 0x000b, 0x0000, - 0x01cf, 0x0003, 0x8010, 0x0008, 0x0002, 0x0000, 0x01cf, 0x0003, - 0x3a47, 0x0002, 0x88e1, 0x000b, 0x8010, 0x0008, 0x0006, 0x0008, - 0x01cf, 0x0003, 0x8074, 0x0000, 0xf000, 0x0008, 0x0189, 0x0004, - 0x018c, 0x0004, 0x3a40, 0x000a, 0x080a, 0x0003, 0x8010, 0x0008, - 0x000c, 0x0008, 0x0189, 0x0004, 0x000a, 0x000b, 0x8074, 0x0000, - 0xf080, 0x0000, 0x0d30, 0x0000, 0x2e4d, 0x0002, 0x2e4d, 0x0002, - 0x09e0, 0x0003, 0x8054, 0x0008, 0x0019, 0x0000, 0x000a, 0x000b, - 0x8054, 0x0008, 0x0009, 0x0008, 0x000a, 0x000b, 0x3a44, 0x0002, - 0x880a, 0x000b, 0x01c2, 0x000b, 0x460b, 0xf5c6, 0x0001, 0x0002, - 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, - 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x92c4 -}; -#ifdef UNIQUE_FW_NAME -unsigned short fw2300flx_length01 = 0xdbb7; -#else -unsigned short risc_code_length01 = 0xdbb7; -#endif - -- cgit v1.2.3-59-g8ed1b From 1757b67809078439662d62a266db45eae3a3d214 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 9 Mar 2006 14:32:04 -0800 Subject: [SCSI] qla2xxx: Firmware updates. Resync with latest 23xx firmware -- 3.03.20. Resync with latest 24xx firmware -- 4.00.18. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/ql2300_fw.c | 14624 +++++++++++++------------- drivers/scsi/qla2xxx/ql2322_fw.c | 14135 ++++++++++++------------- drivers/scsi/qla2xxx/ql2400_fw.c | 20826 ++++++++++++++++++------------------- 3 files changed, 24866 insertions(+), 24719 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/ql2300_fw.c b/drivers/scsi/qla2xxx/ql2300_fw.c index dfc9cd58dc06..b8ce7fe5d8de 100644 --- a/drivers/scsi/qla2xxx/ql2300_fw.c +++ b/drivers/scsi/qla2xxx/ql2300_fw.c @@ -6,7 +6,7 @@ */ /* - * Firmware Version 3.03.18 (12:09 Sep 20, 2005) + * Firmware Version 3.03.20 (15:39 Feb 01, 2006) */ #ifdef UNIQUE_FW_NAME @@ -16,15 +16,15 @@ unsigned short risc_code_version = 3*1024+3; #endif #ifdef UNIQUE_FW_NAME -unsigned char fw2300ipx_version_str[] = {3, 3,18}; +unsigned char fw2300ipx_version_str[] = {3, 3,20}; #else -unsigned char firmware_version[] = {3, 3,18}; +unsigned char firmware_version[] = {3, 3,20}; #endif #ifdef UNIQUE_FW_NAME -#define fw2300ipx_VERSION_STRING "3.03.18" +#define fw2300ipx_VERSION_STRING "3.03.20" #else -#define FW_VERSION_STRING "3.03.18" +#define FW_VERSION_STRING "3.03.20" #endif #ifdef UNIQUE_FW_NAME @@ -38,12 +38,12 @@ unsigned short fw2300ipx_code01[] = { #else unsigned short risc_code01[] = { #endif - 0x0470, 0x0000, 0x0000, 0xee08, 0x0000, 0x0003, 0x0003, 0x0012, + 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, 0x2e31, 0x3820, 0x2020, 0x2020, 0x2400, 0x20a9, + 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, @@ -52,173 +52,173 @@ unsigned short risc_code01[] = { 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, 0x2dac, 0x2051, 0x1800, 0x2a70, 0x20e1, + 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, 0x1ad2, 0x2472, 0x00ee, 0x20a1, 0x1cd0, 0x7170, + 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, - 0x6135, 0x080c, 0xb097, 0x080c, 0x10dd, 0x080c, 0x12fc, 0x080c, - 0x1c00, 0x080c, 0x0d57, 0x080c, 0x1062, 0x080c, 0x34ac, 0x080c, - 0x7862, 0x080c, 0x6ab6, 0x080c, 0x8935, 0x080c, 0x8616, 0x080c, - 0x24d8, 0x080c, 0x91e1, 0x080c, 0x7f32, 0x080c, 0x2311, 0x080c, - 0x2445, 0x080c, 0x24cd, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004, + 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, 0x4cae, 0x080c, 0x34d3, 0x080c, 0x78d3, 0x080c, - 0x7054, 0x080c, 0x8a1c, 0x080c, 0x8642, 0x080c, 0x2cf6, 0x0c58, + 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, 0x7569, 0x0150, 0x080c, 0x758c, 0x15a0, 0x2079, 0x0100, - 0x7828, 0x9085, 0x1800, 0x782a, 0x0468, 0x080c, 0x7495, 0x7000, + 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, 0x85ff, 0x080c, 0x85f1, 0x2001, 0x0161, 0x2003, + 0x0ab3, 0x080c, 0x8733, 0x080c, 0x8725, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0x9295, 0x5e2f, - 0x7a2a, 0x2011, 0x73e4, 0x080c, 0x8709, 0x2011, 0x73d7, 0x080c, - 0x87e3, 0x2011, 0x5f90, 0x080c, 0x8709, 0x2011, 0x8030, 0x901e, - 0x7396, 0x04d0, 0x080c, 0x583d, 0x2079, 0x0100, 0x7844, 0x9005, - 0x1904, 0x0ab3, 0x2011, 0x5f90, 0x080c, 0x8709, 0x2011, 0x73e4, - 0x080c, 0x8709, 0x2011, 0x73d7, 0x080c, 0x87e3, 0x2001, 0x0265, + 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, 0x19a8, 0x2004, 0x9005, 0x1140, 0x00c6, 0x2061, 0x0100, - 0x080c, 0x60dd, 0x00ce, 0x0804, 0x0ab3, 0x780f, 0x006b, 0x7a28, - 0x080c, 0x7571, 0x0118, 0x9295, 0x5e2f, 0x0010, 0x9295, 0x402f, - 0x7a2a, 0x2011, 0x8010, 0x73d8, 0x2001, 0x19a9, 0x2003, 0x0001, - 0x080c, 0x2b9b, 0x080c, 0x4be9, 0x7248, 0xc284, 0x724a, 0x2001, - 0x180c, 0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x080c, 0xa7de, 0x2011, - 0x0004, 0x080c, 0xce66, 0x080c, 0x6940, 0x080c, 0x7569, 0x1120, - 0x080c, 0x2bdf, 0x02e0, 0x0400, 0x080c, 0x60e4, 0x0140, 0x7097, - 0x0001, 0x70d3, 0x0000, 0x080c, 0x5a0a, 0x0804, 0x0ab3, 0x080c, - 0x57d3, 0xd094, 0x0188, 0x2011, 0x180c, 0x2204, 0xc0cd, 0x2012, - 0x080c, 0x57d7, 0xd0d4, 0x1118, 0x080c, 0x2bdf, 0x1270, 0x2011, - 0x180c, 0x2204, 0xc0bc, 0x00a8, 0x080c, 0x57d7, 0xd0d4, 0x1db8, + 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, 0x6a8a, 0x1128, 0xd0a4, 0x0118, 0x2204, - 0xc0fd, 0x2012, 0x080c, 0x6a50, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, - 0x00a8, 0x707f, 0x0000, 0x080c, 0x7569, 0x1130, 0x70b0, 0x9005, - 0x1168, 0x080c, 0xd2a9, 0x0050, 0x080c, 0xd2a9, 0x70dc, 0xd09c, - 0x1128, 0x70b0, 0x9005, 0x0110, 0x080c, 0x60ba, 0x70e7, 0x0000, - 0x70e3, 0x0000, 0x70a7, 0x0000, 0x080c, 0x2be7, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c4, 0x2012, 0x72dc, 0x080c, 0x7569, 0x1178, - 0x9016, 0x0016, 0x080c, 0x29ac, 0x2019, 0x196e, 0x211a, 0x001e, + 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, - 0x196e, 0x201b, 0x0000, 0x2079, 0x1847, 0x7804, 0xd0ac, 0x0108, - 0xc295, 0x72de, 0x080c, 0x7569, 0x0118, 0x9296, 0x0004, 0x0548, - 0x2011, 0x0001, 0x080c, 0xce66, 0x70ab, 0x0000, 0x70af, 0xffff, + 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, 0x3019, 0x2011, 0x0005, 0x080c, - 0xa8ed, 0x080c, 0x98ed, 0x080c, 0x7569, 0x0148, 0x00c6, 0x2061, - 0x0100, 0x0016, 0x080c, 0x29ac, 0x61e2, 0x001e, 0x00ce, 0x012e, + 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, 0xa8ed, 0x080c, 0x98ed, 0x080c, - 0x7569, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x29ac, + 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, 0x7569, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, - 0x080c, 0x7569, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, + 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, 0x3342, 0x8108, 0x1f04, 0x0ac7, 0x707f, 0x0000, 0x7080, + 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, 0x3019, 0x080c, - 0x98ed, 0x0804, 0x0b9d, 0x70dc, 0xd0ac, 0x1110, 0xd09c, 0x0558, + 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, 0x33a5, 0x11d0, 0x70e0, 0x9086, 0xffff, - 0x01b0, 0x080c, 0x31b2, 0x080c, 0x98ed, 0x70dc, 0xd094, 0x1904, - 0x0b9d, 0x2011, 0x0001, 0x080c, 0xd561, 0x0110, 0x2011, 0x0003, - 0x901e, 0x080c, 0x31ec, 0x080c, 0x98ed, 0x0804, 0x0b9d, 0x70e4, + 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, 0x6a50, 0x1904, - 0x0b9d, 0x080c, 0x6aa3, 0x1904, 0x0b9d, 0x080c, 0x6a8a, 0x01c0, - 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x671d, + 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, 0x19b5, - 0x080c, 0x0f96, 0x2011, 0x19cf, 0x080c, 0x0f96, 0x7030, 0xc08c, + 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, 0x283d, 0x080c, 0x33a5, 0x0118, 0x080c, 0x4d86, 0x0050, - 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4da0, - 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x758c, 0x0150, - 0x080c, 0x7569, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, - 0xffdf, 0x782a, 0x00fe, 0x2001, 0x19ea, 0x2004, 0x9086, 0x0005, - 0x1120, 0x2011, 0x0000, 0x080c, 0xa8ed, 0x2011, 0x0000, 0x080c, - 0xa8f7, 0x080c, 0x98ed, 0x080c, 0x9a0f, 0x012e, 0x00be, 0x0005, + 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, 0x60a3, + 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, 0x19a9, 0x2004, 0x9005, - 0x1518, 0x080c, 0x2c62, 0x1148, 0x2001, 0x0001, 0x080c, 0x2bca, - 0x2001, 0x0001, 0x080c, 0x2bad, 0x00b8, 0x080c, 0x2c6a, 0x1138, - 0x9006, 0x080c, 0x2bca, 0x9006, 0x080c, 0x2bad, 0x0068, 0x080c, - 0x2c72, 0x1d50, 0x2001, 0x1999, 0x2004, 0xd0fc, 0x0108, 0x0020, - 0x080c, 0x29d8, 0x0804, 0x0d0d, 0x080c, 0x757a, 0x0148, 0x080c, - 0x758c, 0x1118, 0x080c, 0x785d, 0x0050, 0x080c, 0x7571, 0x0dd0, - 0x080c, 0x7858, 0x080c, 0x784e, 0x080c, 0x7495, 0x0058, 0x080c, - 0x7569, 0x0140, 0x2009, 0x00f8, 0x080c, 0x60a3, 0x7843, 0x0090, + 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, - 0x7569, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x0d12, 0x1f04, 0x0c0c, - 0x0070, 0x7824, 0x080c, 0x7583, 0x0118, 0xd0ac, 0x1904, 0x0d12, + 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, 0x283d, 0x0804, 0x0d25, 0x2001, 0x19a9, 0x2004, - 0x9005, 0x1518, 0x080c, 0x2c62, 0x1148, 0x2001, 0x0001, 0x080c, - 0x2bca, 0x2001, 0x0001, 0x080c, 0x2bad, 0x00b8, 0x080c, 0x2c6a, - 0x1138, 0x9006, 0x080c, 0x2bca, 0x9006, 0x080c, 0x2bad, 0x0068, - 0x080c, 0x2c72, 0x1d50, 0x2001, 0x1999, 0x2004, 0xd0fc, 0x0108, - 0x0020, 0x080c, 0x29d8, 0x0804, 0x0d0d, 0x7850, 0x9085, 0x0040, - 0x7852, 0x7938, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2c7a, + 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, 0x87c3, 0x1f04, 0x0c66, 0x7850, 0x9085, 0x0400, 0x9084, - 0xdfbf, 0x7852, 0x793a, 0x080c, 0x757a, 0x0148, 0x080c, 0x758c, - 0x1118, 0x080c, 0x785d, 0x0050, 0x080c, 0x7571, 0x0dd0, 0x080c, - 0x7858, 0x080c, 0x784e, 0x080c, 0x7495, 0x0020, 0x2009, 0x00f8, - 0x080c, 0x60a3, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x0c8c, 0x7850, - 0x9085, 0x1400, 0x7852, 0x080c, 0x7569, 0x0120, 0x7843, 0x0090, - 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, 0x0d0c, 0x87c3, - 0x7820, 0xd09c, 0x1588, 0x080c, 0x7569, 0x0904, 0x0cf2, 0x7824, - 0xd0ac, 0x1904, 0x0d12, 0x080c, 0x758c, 0x1530, 0x0046, 0x2021, - 0x0320, 0x8421, 0x1df0, 0x004e, 0x7827, 0x1800, 0x080c, 0x2c7a, + 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, 0x87c3, 0x080c, 0x7858, 0x080c, - 0x784e, 0x7003, 0x0001, 0x04f0, 0x8319, 0x1940, 0x1d04, 0x0cda, - 0x080c, 0x87c3, 0x2009, 0x199c, 0x2104, 0x9005, 0x0118, 0x8001, + 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, 0x2c5b, 0x7924, 0x080c, 0x2c7a, 0xd19c, 0x0110, 0x080c, - 0x2b9b, 0x00d8, 0x080c, 0x757a, 0x1140, 0x94a2, 0x03e8, 0x1128, - 0x080c, 0x7541, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0x080c, - 0x2c7a, 0x7824, 0x080c, 0x7583, 0x0110, 0xd0ac, 0x1158, 0x9084, + 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, - 0x283d, 0x0078, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904, + 0x281c, 0x0078, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904, 0x918d, 0x0002, 0x7906, 0x7827, 0x0048, 0x7828, 0x9085, 0x0028, - 0x782a, 0x7850, 0x9085, 0x0400, 0x7852, 0x2001, 0x19a9, 0x2003, + 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, 0x87c3, + 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, 0x34d3, 0x00ee, 0x0005, 0x0005, 0x2a70, - 0x2061, 0x19ad, 0x2063, 0x0003, 0x6007, 0x0003, 0x600b, 0x0012, - 0x600f, 0x0137, 0x2001, 0x197d, 0x900e, 0x2102, 0x7196, 0x2001, + 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, 0xd2a9, 0x70eb, - 0x00c0, 0x2061, 0x196d, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, + 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, 0x1975, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, + 0x07d0, 0x2061, 0x1974, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, - 0x198a, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, - 0x2020, 0x2001, 0x182c, 0x2102, 0x0005, 0x9016, 0x080c, 0x671d, + 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, @@ -226,20 +226,20 @@ unsigned short risc_code01[] = { 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, 0x1a0a, 0x2004, 0x78b6, 0x2001, 0x1a87, + 0x681c, 0x78b2, 0x2001, 0x1a09, 0x2004, 0x78b6, 0x2001, 0x1a86, 0x2004, 0x78ba, 0x6808, 0x78be, 0x00de, 0x7833, 0x0012, 0x2091, 0x5000, 0x0156, 0x00d6, 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, - 0x1aaa, 0x7a08, 0x226a, 0x2069, 0x1aab, 0x7a18, 0x226a, 0x8d68, - 0x7a1c, 0x226a, 0x782c, 0x2019, 0x1ab8, 0x201a, 0x2019, 0x1abb, + 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, 0x1ad0, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, - 0xdead, 0x2019, 0x1ab9, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, - 0x0000, 0x2069, 0x1a8a, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, + 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, 0x1a1d, 0x2004, 0x9005, + 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a1c, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, - 0x2003, 0x0002, 0x2003, 0x1001, 0x080c, 0x57e2, 0x1108, 0x0099, + 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, @@ -251,8 +251,8 @@ unsigned short risc_code01[] = { 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, 0x2c72, 0x1118, 0x2011, 0x8484, 0x0058, 0x2011, - 0x8282, 0x0040, 0x080c, 0x2c72, 0x1118, 0x2011, 0xcdc5, 0x0010, + 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, @@ -305,7 +305,7 @@ unsigned short risc_code01[] = { 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, 0x85f1, 0x012e, + 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, @@ -321,21 +321,21 @@ unsigned short risc_code01[] = { 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, 0x1a1c, + 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, 0x1a1c, - 0x701c, 0x9088, 0x1a26, 0x280a, 0x8000, 0x9084, 0x003f, 0x701e, + 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, 0x1a1c, 0x7004, 0x9005, 0x1128, + 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, 0x1a26, 0x2004, 0x700a, 0x2048, 0x8108, 0x918c, 0x003f, + 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, @@ -347,8 +347,8 @@ unsigned short risc_code01[] = { 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, 0x1a1c, 0x2104, 0xc095, 0x200a, 0x080c, - 0x1117, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1a1c, 0x00f6, 0x2079, + 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, @@ -370,45 +370,45 @@ unsigned short risc_code01[] = { 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, 0x6dc4, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x2848, + 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, 0x6dc4, + 0x10f8, 0x00e8, 0xa97c, 0xa894, 0x0016, 0x0006, 0x080c, 0x6e92, 0x000e, 0x001e, 0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060, - 0x080c, 0xb101, 0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, 0xa8a3, + 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, 0x1930, + 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, 0x1930, 0x204c, 0xaa7c, 0x009e, - 0x080c, 0x8c5a, 0x2009, 0x188c, 0x2104, 0x9084, 0xfffc, 0x200a, - 0x080c, 0x8abf, 0x7007, 0x0000, 0x080c, 0x1128, 0x0005, 0x7007, + 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, 0x1a66, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x781b, - 0x4800, 0x00c1, 0x7803, 0x0003, 0x780f, 0x0000, 0x20a9, 0x03e8, - 0x2061, 0xee29, 0x2c0d, 0x7912, 0xe104, 0x9ce0, 0x0002, 0x7916, + 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, 0x1a67, 0x2003, 0x0000, + 0x7820, 0x080c, 0x1376, 0x0cc8, 0x2001, 0x1a66, 0x2003, 0x0000, 0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807, 0x0007, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, 0x782b, - 0x1a8a, 0x781f, 0xff00, 0x781b, 0xb700, 0x2001, 0x0200, 0x2004, - 0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x1a8a, 0x602f, 0x1cd0, - 0x2001, 0x181a, 0x2004, 0x9082, 0x1cd0, 0x6032, 0x603b, 0x20f0, - 0x2001, 0x33ac, 0xd0fc, 0x190c, 0x0dc5, 0x2001, 0x1810, 0x2004, + 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, - 0x33ac, 0x0020, 0x9084, 0xc000, 0x783f, 0xb3ac, 0x604f, 0x193e, - 0x2001, 0x1929, 0x2004, 0x6042, 0x00ce, 0x0005, 0x9086, 0x000d, + 0x33b6, 0x0020, 0x9084, 0xc000, 0x783f, 0xb3b6, 0x604f, 0x193d, + 0x2001, 0x1928, 0x2004, 0x6042, 0x00ce, 0x0005, 0x9086, 0x000d, 0x11d0, 0x7808, 0xd09c, 0x01b8, 0x7820, 0x0026, 0x2010, 0x080c, - 0xce44, 0x0180, 0x2260, 0x6000, 0x9086, 0x0004, 0x1158, 0x0016, + 0xd0c6, 0x0180, 0x2260, 0x6000, 0x9086, 0x0004, 0x1158, 0x0016, 0x6120, 0x9186, 0x0009, 0x0108, 0x0020, 0x2009, 0x004c, 0x080c, - 0xb180, 0x001e, 0x002e, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908, + 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, @@ -416,18 +416,18 @@ unsigned short risc_code01[] = { 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, 0x1a7f, 0x2104, - 0x8000, 0x200a, 0x080c, 0x8006, 0x080c, 0x1b02, 0x0005, 0x2009, - 0x0048, 0x2060, 0x080c, 0xb180, 0x012e, 0x0005, 0x7004, 0xc085, + 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, 0xb180, 0x2001, 0x015d, 0x2003, 0x0000, 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, 0xb180, 0x0005, 0x080c, 0x159b, + 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, @@ -437,20 +437,20 @@ unsigned short risc_code01[] = { 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, 0x1b02, 0x080c, 0x1322, 0x7803, 0x0001, + 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, 0x8006, 0x080c, 0x1b02, 0x080c, 0xce56, 0x0158, 0xa9ac, + 0x080c, 0x813a, 0x080c, 0x1ad9, 0x080c, 0xd0d8, 0x0158, 0xa9ac, 0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, 0xa880, - 0xc0bd, 0xa882, 0x080c, 0xca71, 0x0005, 0x6020, 0x9086, 0x0009, - 0x1128, 0x2009, 0x004c, 0x080c, 0xb180, 0x0048, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xd242, 0x2029, + 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, 0xedd2, 0xd5a4, 0x1118, 0x080c, 0x15a0, 0x0005, - 0x080c, 0x8006, 0x080c, 0x1b02, 0x0005, 0x781f, 0x0300, 0x7803, + 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, @@ -463,15 +463,15 @@ unsigned short risc_code01[] = { 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, 0x18f1, 0x00fe, 0x2009, 0x01f4, + 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, 0xb180, 0x0005, 0x0005, 0x0005, 0x00e1, 0x2008, - 0x00d1, 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, 0x080c, 0x8fab, - 0x0005, 0x0089, 0x9005, 0x0118, 0x080c, 0x8bae, 0x0cd0, 0x0005, + 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, @@ -481,7 +481,7 @@ unsigned short risc_code01[] = { 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, 0x8006, 0x080c, 0x1b02, 0x0090, 0x7827, 0x0015, 0x782b, + 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, @@ -497,17 +497,17 @@ unsigned short risc_code01[] = { 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, 0x1a82, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, - 0x92ed, 0x001e, 0x002e, 0x00fe, 0x012e, 0x015e, 0x014e, 0x013e, + 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, 0x1a83, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, - 0x1f14, 0x001e, 0x00fe, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, + 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, 0x19f8, 0x2004, - 0x9005, 0x01b8, 0x2001, 0x1a6a, 0x2004, 0x9086, 0x0000, 0x0188, - 0x2009, 0x1a81, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, 0xa595, + 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, @@ -515,7150 +515,7232 @@ unsigned short risc_code01[] = { 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, 0x1a80, 0x2404, 0x8000, - 0x0208, 0x2022, 0x080c, 0x8006, 0x080c, 0x1b02, 0x9006, 0x00ee, + 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, 0x7f4d, 0x012e, 0x7358, 0x745c, 0x6014, + 0x2091, 0x2600, 0x080c, 0x8081, 0x012e, 0x7358, 0x745c, 0x6014, 0x905d, 0x0598, 0x2b48, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x190c, 0xd21d, 0xab42, 0xac3e, 0x2001, 0x1869, 0x2004, + 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, 0x2110, 0x1190, 0x080c, 0x194e, 0x2a00, 0xa816, 0x0130, + 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, - 0x2ff0, 0x0126, 0x2091, 0x2200, 0x0016, 0x00c6, 0x3e60, 0x6014, - 0x2048, 0x2940, 0x903e, 0x2730, 0xa864, 0x2068, 0xa81a, 0x9d84, - 0x000f, 0x9088, 0x20f0, 0x2165, 0x0002, 0x1794, 0x1802, 0x1794, - 0x1794, 0x1798, 0x17e3, 0x1794, 0x17b8, 0x178d, 0x17f9, 0x1794, - 0x1794, 0x179d, 0x18ef, 0x17cc, 0x17c2, 0xa964, 0x918c, 0x00ff, - 0x918e, 0x0048, 0x0904, 0x17f9, 0x9085, 0x0001, 0x0804, 0x18e5, - 0xa87c, 0xd0ac, 0x0dc8, 0x0804, 0x1809, 0xa87c, 0xd0ac, 0x0da0, - 0x0804, 0x1874, 0xa898, 0x901d, 0x1108, 0xab9c, 0x9016, 0xaab2, - 0xaa3e, 0xaa42, 0x3e00, 0x9080, 0x0008, 0x2004, 0x9080, 0x9179, - 0x2005, 0x9005, 0x090c, 0x0dc5, 0x2004, 0xa8ae, 0x0804, 0x18cd, - 0xa87c, 0xd0bc, 0x09c8, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, - 0x0804, 0x1809, 0xa87c, 0xd0bc, 0x0978, 0xa890, 0xa842, 0xa88c, - 0xa83e, 0xa888, 0x0804, 0x1874, 0xa87c, 0xd0bc, 0x0928, 0xa890, - 0xa842, 0xa88c, 0xa83e, 0xa804, 0x9045, 0x090c, 0x0dc5, 0xa164, - 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x20f0, 0x2065, 0xa888, 0xd19c, - 0x1904, 0x1874, 0x0430, 0xa87c, 0xd0ac, 0x0904, 0x1794, 0xa804, - 0x9045, 0x090c, 0x0dc5, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, - 0x20f0, 0x2065, 0x9006, 0xa842, 0xa83e, 0xd19c, 0x1904, 0x1874, - 0x0080, 0xa87c, 0xd0ac, 0x0904, 0x1794, 0x9006, 0xa842, 0xa83e, - 0x0804, 0x1874, 0xa87c, 0xd0ac, 0x0904, 0x1794, 0x9006, 0xa842, - 0xa83e, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, - 0x0002, 0x182c, 0x182c, 0x182e, 0x182c, 0x182c, 0x182c, 0x1838, - 0x182c, 0x182c, 0x182c, 0x1842, 0x182c, 0x182c, 0x182c, 0x184c, - 0x182c, 0x182c, 0x182c, 0x1856, 0x182c, 0x182c, 0x182c, 0x1860, - 0x182c, 0x182c, 0x182c, 0x186a, 0x080c, 0x0dc5, 0xa574, 0xa478, - 0x9d86, 0x0024, 0x0904, 0x17a2, 0xa37c, 0xa280, 0x0804, 0x18cd, - 0xa584, 0xa488, 0x9d86, 0x0024, 0x0904, 0x17a2, 0xa38c, 0xa290, - 0x0804, 0x18cd, 0xa594, 0xa498, 0x9d86, 0x0024, 0x0904, 0x17a2, - 0xa39c, 0xa2a0, 0x0804, 0x18cd, 0xa5a4, 0xa4a8, 0x9d86, 0x0024, - 0x0904, 0x17a2, 0xa3ac, 0xa2b0, 0x0804, 0x18cd, 0xa5b4, 0xa4b8, - 0x9d86, 0x0024, 0x0904, 0x17a2, 0xa3bc, 0xa2c0, 0x0804, 0x18cd, - 0xa5c4, 0xa4c8, 0x9d86, 0x0024, 0x0904, 0x17a2, 0xa3cc, 0xa2d0, - 0x0804, 0x18cd, 0xa5d4, 0xa4d8, 0x9d86, 0x0024, 0x0904, 0x17a2, - 0xa3dc, 0xa2e0, 0x0804, 0x18cd, 0x2c05, 0x908a, 0x0034, 0x1a0c, - 0x0dc5, 0x9082, 0x001b, 0x0002, 0x1897, 0x1895, 0x1895, 0x1895, - 0x1895, 0x1895, 0x18a2, 0x1895, 0x1895, 0x1895, 0x1895, 0x1895, - 0x18ad, 0x1895, 0x1895, 0x1895, 0x1895, 0x1895, 0x18b8, 0x1895, - 0x1895, 0x1895, 0x1895, 0x1895, 0x18c3, 0x080c, 0x0dc5, 0xa56c, - 0xa470, 0xa774, 0xa678, 0x9d86, 0x002c, 0x0904, 0x17a2, 0xa37c, - 0xa280, 0x0458, 0xa584, 0xa488, 0xa78c, 0xa690, 0x9d86, 0x002c, - 0x0904, 0x17a2, 0xa394, 0xa298, 0x0400, 0xa59c, 0xa4a0, 0xa7a4, - 0xa6a8, 0x9d86, 0x002c, 0x0904, 0x17a2, 0xa3ac, 0xa2b0, 0x00a8, - 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0x9d86, 0x002c, 0x0904, 0x17a2, - 0xa3c4, 0xa2c8, 0x0050, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0x9d86, - 0x002c, 0x0904, 0x17a2, 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, - 0x1794, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x0016, 0x00c6, 0x3e60, - 0x6014, 0x2048, 0x2940, 0xa80e, 0x2061, 0x20eb, 0xa813, 0x20eb, - 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, 0x20f0, 0x2015, 0x82ff, - 0x090c, 0x0dc5, 0xaa12, 0x2205, 0xa80a, 0x0c08, 0x903e, 0x2730, - 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1a78, 0x19a5, 0x19a5, - 0x1a78, 0x19a5, 0x1a72, 0x1a78, 0x19a5, 0x1a15, 0x1a15, 0x1a15, - 0x1a78, 0x1a15, 0x1a78, 0x1a6f, 0x1a15, 0xc0fc, 0xa882, 0xab2c, - 0xaa30, 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x1a7a, 0x2c05, 0x908a, - 0x0034, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002, 0x1991, 0x198f, - 0x198f, 0x198f, 0x198f, 0x198f, 0x1995, 0x198f, 0x198f, 0x198f, - 0x198f, 0x198f, 0x1999, 0x198f, 0x198f, 0x198f, 0x198f, 0x198f, - 0x199d, 0x198f, 0x198f, 0x198f, 0x198f, 0x198f, 0x19a1, 0x080c, - 0x0dc5, 0xa774, 0xa678, 0x0804, 0x1a7a, 0xa78c, 0xa690, 0x0804, - 0x1a7a, 0xa7a4, 0xa6a8, 0x0804, 0x1a7a, 0xa7bc, 0xa6c0, 0x0804, - 0x1a7a, 0xa7d4, 0xa6d8, 0x0804, 0x1a7a, 0xa898, 0x901d, 0x1108, - 0xab9c, 0x9016, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x19cd, 0x19cd, 0x19cf, 0x19cd, 0x19cd, 0x19cd, - 0x19d9, 0x19cd, 0x19cd, 0x19cd, 0x19e3, 0x19cd, 0x19cd, 0x19cd, - 0x19ed, 0x19cd, 0x19cd, 0x19cd, 0x19f7, 0x19cd, 0x19cd, 0x19cd, - 0x1a01, 0x19cd, 0x19cd, 0x19cd, 0x1a0b, 0x080c, 0x0dc5, 0xa574, - 0xa478, 0x9d86, 0x0004, 0x0904, 0x1a7a, 0xa37c, 0xa280, 0x0804, - 0x1a7a, 0xa584, 0xa488, 0x9d86, 0x0004, 0x0904, 0x1a7a, 0xa38c, - 0xa290, 0x0804, 0x1a7a, 0xa594, 0xa498, 0x9d86, 0x0004, 0x0904, - 0x1a7a, 0xa39c, 0xa2a0, 0x0804, 0x1a7a, 0xa5a4, 0xa4a8, 0x9d86, - 0x0004, 0x0904, 0x1a7a, 0xa3ac, 0xa2b0, 0x0804, 0x1a7a, 0xa5b4, - 0xa4b8, 0x9d86, 0x0004, 0x0904, 0x1a7a, 0xa3bc, 0xa2c0, 0x0804, - 0x1a7a, 0xa5c4, 0xa4c8, 0x9d86, 0x0004, 0x0904, 0x1a7a, 0xa3cc, - 0xa2d0, 0x0804, 0x1a7a, 0xa5d4, 0xa4d8, 0x9d86, 0x0004, 0x0904, - 0x1a7a, 0xa3dc, 0xa2e0, 0x0804, 0x1a7a, 0xa898, 0x901d, 0x1108, - 0xab9c, 0x9016, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x1a3d, 0x1a3b, 0x1a3b, 0x1a3b, 0x1a3b, 0x1a3b, - 0x1a47, 0x1a3b, 0x1a3b, 0x1a3b, 0x1a3b, 0x1a3b, 0x1a51, 0x1a3b, - 0x1a3b, 0x1a3b, 0x1a3b, 0x1a3b, 0x1a5b, 0x1a3b, 0x1a3b, 0x1a3b, - 0x1a3b, 0x1a3b, 0x1a65, 0x080c, 0x0dc5, 0xa56c, 0xa470, 0xa774, - 0xa678, 0x9d86, 0x000c, 0x05b0, 0xa37c, 0xa280, 0x0498, 0xa584, - 0xa488, 0xa78c, 0xa690, 0x9d86, 0x000c, 0x0560, 0xa394, 0xa298, - 0x0448, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86, 0x000c, 0x0510, - 0xa3ac, 0xa2b0, 0x00f8, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0x9d86, - 0x000c, 0x01c0, 0xa3c4, 0xa2c8, 0x00a8, 0xa5cc, 0xa4d0, 0xa7d4, - 0xa6d8, 0x9d86, 0x000c, 0x0170, 0xa3dc, 0xa2e0, 0x0058, 0x9d86, - 0x000e, 0x1130, 0x080c, 0x20a8, 0x1904, 0x194e, 0x900e, 0x0050, - 0x080c, 0x0dc5, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, - 0x080c, 0x20a8, 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, 0xb180, 0x0005, 0xa974, 0xd1dc, 0x1108, 0x0005, 0xa934, - 0xa88c, 0x9106, 0x1158, 0xa938, 0xa890, 0x9106, 0x1138, 0x601c, - 0xc084, 0x601e, 0x2009, 0x0048, 0x0804, 0xb180, 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, 0x1b92, 0x7930, 0x9186, 0x0040, 0x0160, - 0x9186, 0x0042, 0x190c, 0x0dc5, 0x2001, 0x001e, 0x8001, 0x1df0, - 0x8631, 0x1d40, 0x080c, 0x1ba1, 0x000e, 0x6022, 0x012e, 0x0005, - 0x080c, 0x1b8e, 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, 0x7569, 0x1188, 0x2001, 0x0138, 0x2003, - 0x0000, 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, 0xa001, - 0xa001, 0x8211, 0x1de0, 0x0059, 0x0804, 0x7616, 0x0479, 0x0039, - 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, - 0x2071, 0x0200, 0x080c, 0x2c86, 0x2009, 0x003c, 0x080c, 0x2432, - 0x2001, 0x015d, 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, - 0x080c, 0x85f1, 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, 0x7569, 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, 0x1bff, 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, 0x1b98, 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, 0x1a6a, 0x2079, 0x0090, 0x012e, - 0x0005, 0x9280, 0x0005, 0x2004, 0x2048, 0xa97c, 0xd1dc, 0x1904, - 0x1ca1, 0xa964, 0x9184, 0x0007, 0x0002, 0x1c1d, 0x1c8c, 0x1c34, - 0x1c36, 0x1c34, 0x1c74, 0x1c54, 0x1c43, 0x918c, 0x00ff, 0x9186, - 0x0008, 0x1170, 0xa87c, 0xd0b4, 0x0904, 0x1ece, 0x9006, 0xa842, - 0xa83e, 0xa988, 0x2900, 0xa85a, 0xa813, 0x20eb, 0x0804, 0x1c9d, - 0x9186, 0x0048, 0x0904, 0x1c8c, 0x080c, 0x0dc5, 0x9184, 0x00ff, - 0x9086, 0x0013, 0x0904, 0x1c8c, 0x9184, 0x00ff, 0x9086, 0x001b, - 0x0904, 0x1c8c, 0x0c88, 0xa87c, 0xd0b4, 0x0904, 0x1ece, 0xa890, - 0xa842, 0xa83a, 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, - 0xa84a, 0xa988, 0x0804, 0x1c94, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x001e, 0x19d0, 0xa87c, 0xd0b4, 0x0904, 0x1ece, 0xa890, 0xa842, + 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, - 0xa804, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x20f0, - 0x2005, 0xa812, 0xa988, 0x0448, 0x918c, 0x00ff, 0x9186, 0x0015, - 0x1540, 0xa87c, 0xd0b4, 0x0904, 0x1ece, 0xa804, 0xa85a, 0x2040, - 0xa064, 0x9084, 0x000f, 0x9080, 0x20f0, 0x2005, 0xa812, 0xa988, - 0x9006, 0xa842, 0xa83e, 0x0088, 0xa87c, 0xd0b4, 0x0904, 0x1ece, - 0xa988, 0x9006, 0xa842, 0xa83e, 0x2900, 0xa85a, 0xa864, 0x9084, - 0x000f, 0x9080, 0x20f0, 0x2005, 0xa812, 0xa916, 0xa87c, 0xc0dd, - 0xa87e, 0x0005, 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, - 0x1f14, 0x00e6, 0x2071, 0x1a6a, 0x7000, 0x9005, 0x1904, 0x1d08, - 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, - 0x2110, 0x004e, 0x003e, 0x0d30, 0x0c98, 0x9085, 0x0001, 0x0c80, - 0x2009, 0x0306, 0x200b, 0x4800, 0x7027, 0x0000, 0x0005, 0x0076, - 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x1ec7, - 0x700c, 0x7214, 0x923a, 0x7010, 0x7218, 0x9203, 0x0a04, 0x1ec6, - 0x9705, 0x0904, 0x1ec6, 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, - 0x2d00, 0x0002, 0x1e4b, 0x1d8a, 0x1d8a, 0x1e4b, 0x1e4b, 0x1e28, - 0x1e4b, 0x1d8a, 0x1e2f, 0x1dd9, 0x1dd9, 0x1e4b, 0x1e4b, 0x1e4b, - 0x1e22, 0x1dd9, 0xc0fc, 0xa882, 0xab2c, 0xaa30, 0xad1c, 0xac20, - 0xdd9c, 0x0904, 0x1e58, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, - 0x9082, 0x001b, 0x0002, 0x1d76, 0x1d74, 0x1d74, 0x1d74, 0x1d74, - 0x1d74, 0x1d7a, 0x1d74, 0x1d74, 0x1d74, 0x1d74, 0x1d74, 0x1d7e, - 0x1d74, 0x1d74, 0x1d74, 0x1d74, 0x1d74, 0x1d82, 0x1d74, 0x1d74, - 0x1d74, 0x1d74, 0x1d74, 0x1d86, 0x080c, 0x0dc5, 0xa774, 0xa678, - 0x0804, 0x1e58, 0xa78c, 0xa690, 0x0804, 0x1e58, 0xa7a4, 0xa6a8, - 0x0804, 0x1e58, 0xa7bc, 0xa6c0, 0x0804, 0x1e58, 0xa7d4, 0xa6d8, - 0x0804, 0x1e58, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x1dad, 0x1dad, 0x1daf, 0x1dad, 0x1dad, 0x1dad, - 0x1db5, 0x1dad, 0x1dad, 0x1dad, 0x1dbb, 0x1dad, 0x1dad, 0x1dad, - 0x1dc1, 0x1dad, 0x1dad, 0x1dad, 0x1dc7, 0x1dad, 0x1dad, 0x1dad, - 0x1dcd, 0x1dad, 0x1dad, 0x1dad, 0x1dd3, 0x080c, 0x0dc5, 0xa574, - 0xa478, 0xa37c, 0xa280, 0x0804, 0x1e58, 0xa584, 0xa488, 0xa38c, - 0xa290, 0x0804, 0x1e58, 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, - 0x1e58, 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, 0x1e58, 0xa5b4, - 0xa4b8, 0xa3bc, 0xa2c0, 0x0804, 0x1e58, 0xa5c4, 0xa4c8, 0xa3cc, - 0xa2d0, 0x0804, 0x1e58, 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, - 0x1e58, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, 0x001b, - 0x0002, 0x1dfc, 0x1dfa, 0x1dfa, 0x1dfa, 0x1dfa, 0x1dfa, 0x1e04, - 0x1dfa, 0x1dfa, 0x1dfa, 0x1dfa, 0x1dfa, 0x1e0c, 0x1dfa, 0x1dfa, - 0x1dfa, 0x1dfa, 0x1dfa, 0x1e14, 0x1dfa, 0x1dfa, 0x1dfa, 0x1dfa, - 0x1dfa, 0x1e1b, 0x080c, 0x0dc5, 0xa56c, 0xa470, 0xa774, 0xa678, - 0xa37c, 0xa280, 0x0804, 0x1e58, 0xa584, 0xa488, 0xa78c, 0xa690, - 0xa394, 0xa298, 0x0804, 0x1e58, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, - 0xa3ac, 0xa2b0, 0x0804, 0x1e58, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, - 0xa3c4, 0xa2c8, 0x04e8, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, - 0xa2e0, 0x04b0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x1518, - 0x080c, 0x20a8, 0x1904, 0x1d25, 0x900e, 0x0804, 0x1ec7, 0xab64, - 0x939c, 0x00ff, 0x9386, 0x0048, 0x1180, 0x00c6, 0x7004, 0x2060, - 0x6004, 0x9086, 0x0043, 0x00ce, 0x0904, 0x1dd9, 0xab9c, 0x9016, - 0xad8c, 0xac90, 0xaf94, 0xae98, 0x0098, 0x9386, 0x0008, 0x0904, - 0x1dd9, 0x080c, 0x0dc5, 0xa964, 0x918c, 0x00ff, 0x9186, 0x0013, - 0x0904, 0x1d8a, 0x9186, 0x001b, 0x0904, 0x1dd9, 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, 0x20a8, 0x0448, 0xd6b4, 0x0110, - 0x200b, 0x4040, 0x2031, 0x0080, 0x9584, 0x007f, 0x0108, 0x9632, - 0x7124, 0x7000, 0x9086, 0x0000, 0x1198, 0xc185, 0x7126, 0x2009, - 0x0306, 0x2104, 0xd0b4, 0x1904, 0x1e69, 0x200b, 0x4040, 0x2009, - 0x1a84, 0x2104, 0x8000, 0x0a04, 0x1e69, 0x200a, 0x0804, 0x1e69, - 0xc18d, 0x7126, 0xd184, 0x1d58, 0x0804, 0x1e69, 0x9006, 0x002e, - 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x0dc5, - 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7003, - 0x0000, 0x7004, 0x2060, 0x6014, 0x2048, 0x080c, 0xce56, 0x0118, - 0xa880, 0xc0bd, 0xa882, 0x782c, 0xd0ac, 0x1de8, 0x080c, 0x1d18, - 0x6020, 0x9086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, - 0x00fa, 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0xa89a, - 0x60c8, 0xa896, 0x7004, 0x2060, 0x00c6, 0x080c, 0xca71, 0x00ce, - 0x2001, 0x19f8, 0x2004, 0x9c06, 0x1160, 0x2009, 0x0040, 0x080c, - 0x2432, 0x080c, 0xaa59, 0x2011, 0x0000, 0x080c, 0xa8f7, 0x080c, - 0x9a0f, 0x002e, 0x0804, 0x2058, 0x0126, 0x2091, 0x2400, 0xa858, - 0x2040, 0x792c, 0x782b, 0x0002, 0x9184, 0x0700, 0x1904, 0x1ed0, - 0x7000, 0x0002, 0x2058, 0x1f26, 0x1fa6, 0x2056, 0x8001, 0x7002, - 0x7027, 0x0000, 0xd19c, 0x1158, 0x8aff, 0x0904, 0x1f73, 0x080c, - 0x1d1f, 0x0904, 0x2058, 0x080c, 0x1d1f, 0x0804, 0x2058, 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, 0x20c3, - 0xa880, 0xc0fd, 0xa882, 0x2a00, 0xa816, 0x2800, 0xa85a, 0x2c00, - 0xa812, 0x7003, 0x0000, 0x2009, 0x0306, 0x200b, 0x4800, 0x7027, - 0x0000, 0x0804, 0x2058, 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, 0x1d18, 0x0804, 0x2058, 0x8001, 0x7002, - 0x7024, 0x8004, 0x7026, 0xd194, 0x0170, 0x782c, 0xd0fc, 0x1904, - 0x1f19, 0xd19c, 0x1904, 0x2054, 0x8aff, 0x0904, 0x2058, 0x080c, - 0x1d1f, 0x0804, 0x2058, 0x0026, 0x0036, 0xab3c, 0xaa40, 0x080c, - 0x20c3, 0xdd9c, 0x1904, 0x2013, 0x2c05, 0x908a, 0x0036, 0x1a0c, - 0x0dc5, 0x9082, 0x001b, 0x0002, 0x1fe7, 0x1fe7, 0x1fe9, 0x1fe7, - 0x1fe7, 0x1fe7, 0x1fef, 0x1fe7, 0x1fe7, 0x1fe7, 0x1ff5, 0x1fe7, - 0x1fe7, 0x1fe7, 0x1ffb, 0x1fe7, 0x1fe7, 0x1fe7, 0x2001, 0x1fe7, - 0x1fe7, 0x1fe7, 0x2007, 0x1fe7, 0x1fe7, 0x1fe7, 0x200d, 0x080c, - 0x0dc5, 0xa07c, 0x931a, 0xa080, 0x9213, 0x0804, 0x1f48, 0xa08c, - 0x931a, 0xa090, 0x9213, 0x0804, 0x1f48, 0xa09c, 0x931a, 0xa0a0, - 0x9213, 0x0804, 0x1f48, 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, - 0x1f48, 0xa0bc, 0x931a, 0xa0c0, 0x9213, 0x0804, 0x1f48, 0xa0cc, - 0x931a, 0xa0d0, 0x9213, 0x0804, 0x1f48, 0xa0dc, 0x931a, 0xa0e0, - 0x9213, 0x0804, 0x1f48, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, - 0x9082, 0x001b, 0x0002, 0x2036, 0x2034, 0x2034, 0x2034, 0x2034, - 0x2034, 0x203c, 0x2034, 0x2034, 0x2034, 0x2034, 0x2034, 0x2042, - 0x2034, 0x2034, 0x2034, 0x2034, 0x2034, 0x2048, 0x2034, 0x2034, - 0x2034, 0x2034, 0x2034, 0x204e, 0x080c, 0x0dc5, 0xa07c, 0x931a, - 0xa080, 0x9213, 0x0804, 0x1f48, 0xa094, 0x931a, 0xa098, 0x9213, - 0x0804, 0x1f48, 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1f48, - 0xa0c4, 0x931a, 0xa0c8, 0x9213, 0x0804, 0x1f48, 0xa0dc, 0x931a, - 0xa0e0, 0x9213, 0x0804, 0x1f48, 0x0804, 0x1f44, 0x080c, 0x0dc5, - 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a6a, 0x7000, 0x9086, - 0x0000, 0x0904, 0x20a3, 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, - 0xd194, 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, - 0x080c, 0xee1b, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0dc5, - 0x0016, 0x2009, 0x0040, 0x080c, 0x2432, 0x001e, 0x2001, 0x020c, - 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, - 0x1120, 0x2009, 0x0040, 0x080c, 0x2432, 0x782c, 0xd0fc, 0x09a8, - 0x080c, 0x1f14, 0x7000, 0x9086, 0x0000, 0x1978, 0x782b, 0x0004, - 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2432, 0x782b, - 0x0002, 0x7003, 0x0000, 0x080c, 0x1d18, 0x00ee, 0x00fe, 0x0005, - 0xa880, 0xd0fc, 0x11a8, 0x8c60, 0x2c05, 0x9005, 0x0110, 0x8a51, - 0x0005, 0xa004, 0x9005, 0x0168, 0xa85a, 0x2040, 0xa064, 0x9084, - 0x000f, 0x9080, 0x20f0, 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, - 0x2100, 0x2065, 0x8cff, 0x090c, 0x0dc5, 0x0005, 0x0000, 0x001d, - 0x0021, 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, - 0x0021, 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, 0x0023, 0x0000, - 0x0000, 0x20e3, 0x20df, 0x20e3, 0x20e3, 0x20ed, 0x0000, 0x20e3, - 0x20ea, 0x20ea, 0x20e7, 0x20ea, 0x20ea, 0x0000, 0x20ed, 0x20ea, - 0x0000, 0x20e5, 0x20e5, 0x0000, 0x20e5, 0x20ed, 0x0000, 0x20e5, - 0x20eb, 0x20eb, 0x20eb, 0x0000, 0x20eb, 0x0000, 0x20ed, 0x20eb, - 0x00c6, 0x00d6, 0x0086, 0xab42, 0xac3e, 0xa888, 0x9055, 0x0904, - 0x22ef, 0x2940, 0xa064, 0x90ec, 0x000f, 0x9084, 0x00ff, 0x9086, - 0x0008, 0x1118, 0x2061, 0x20eb, 0x00d0, 0x9de0, 0x20f0, 0x9d86, - 0x0007, 0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f, 0x1120, - 0xa08c, 0x9422, 0xa090, 0x931b, 0x2c05, 0x9065, 0x1140, 0x0310, - 0x0804, 0x22ef, 0xa004, 0x9045, 0x0904, 0x22ef, 0x08d8, 0x2c05, - 0x9005, 0x0904, 0x21d7, 0xdd9c, 0x1904, 0x2193, 0x908a, 0x0036, - 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002, 0x2168, 0x2168, 0x216a, - 0x2168, 0x2168, 0x2168, 0x2170, 0x2168, 0x2168, 0x2168, 0x2176, - 0x2168, 0x2168, 0x2168, 0x217c, 0x2168, 0x2168, 0x2168, 0x2182, - 0x2168, 0x2168, 0x2168, 0x2188, 0x2168, 0x2168, 0x2168, 0x218e, - 0x080c, 0x0dc5, 0xa07c, 0x9422, 0xa080, 0x931b, 0x0804, 0x21cd, - 0xa08c, 0x9422, 0xa090, 0x931b, 0x0804, 0x21cd, 0xa09c, 0x9422, - 0xa0a0, 0x931b, 0x0804, 0x21cd, 0xa0ac, 0x9422, 0xa0b0, 0x931b, - 0x0804, 0x21cd, 0xa0bc, 0x9422, 0xa0c0, 0x931b, 0x0804, 0x21cd, - 0xa0cc, 0x9422, 0xa0d0, 0x931b, 0x0804, 0x21cd, 0xa0dc, 0x9422, - 0xa0e0, 0x931b, 0x04d0, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x21b5, 0x21b3, 0x21b3, 0x21b3, 0x21b3, 0x21b3, - 0x21ba, 0x21b3, 0x21b3, 0x21b3, 0x21b3, 0x21b3, 0x21bf, 0x21b3, - 0x21b3, 0x21b3, 0x21b3, 0x21b3, 0x21c4, 0x21b3, 0x21b3, 0x21b3, - 0x21b3, 0x21b3, 0x21c9, 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, 0x22ef, 0x8c60, 0x0804, 0x213f, 0xa004, - 0x9045, 0x0904, 0x22ef, 0x0804, 0x211a, 0x8a51, 0x0904, 0x22ef, - 0x8c60, 0x2c05, 0x9005, 0x1158, 0xa004, 0x9045, 0x0904, 0x22ef, - 0xa064, 0x90ec, 0x000f, 0x9de0, 0x20f0, 0x2c05, 0x2060, 0xa880, - 0xc0fc, 0xa882, 0x0804, 0x22e4, 0x2c05, 0x8422, 0x8420, 0x831a, - 0x9399, 0x0000, 0xac2e, 0xab32, 0xdd9c, 0x1904, 0x2281, 0x9082, - 0x001b, 0x0002, 0x221d, 0x221d, 0x221f, 0x221d, 0x221d, 0x221d, - 0x222d, 0x221d, 0x221d, 0x221d, 0x223b, 0x221d, 0x221d, 0x221d, - 0x2249, 0x221d, 0x221d, 0x221d, 0x2257, 0x221d, 0x221d, 0x221d, - 0x2265, 0x221d, 0x221d, 0x221d, 0x2273, 0x080c, 0x0dc5, 0xa17c, - 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa074, - 0x9420, 0xa078, 0x9319, 0x0804, 0x22df, 0xa18c, 0x2400, 0x9122, - 0xa190, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa084, 0x9420, 0xa088, - 0x9319, 0x0804, 0x22df, 0xa19c, 0x2400, 0x9122, 0xa1a0, 0x2300, - 0x911b, 0x0a0c, 0x0dc5, 0xa094, 0x9420, 0xa098, 0x9319, 0x0804, - 0x22df, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, - 0x0dc5, 0xa0a4, 0x9420, 0xa0a8, 0x9319, 0x0804, 0x22df, 0xa1bc, - 0x2400, 0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa0b4, - 0x9420, 0xa0b8, 0x9319, 0x0804, 0x22df, 0xa1cc, 0x2400, 0x9122, - 0xa1d0, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa0c4, 0x9420, 0xa0c8, - 0x9319, 0x0804, 0x22df, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, - 0x911b, 0x0a0c, 0x0dc5, 0xa0d4, 0x9420, 0xa0d8, 0x9319, 0x0804, - 0x22df, 0x9082, 0x001b, 0x0002, 0x229f, 0x229d, 0x229d, 0x229d, - 0x229d, 0x229d, 0x22ac, 0x229d, 0x229d, 0x229d, 0x229d, 0x229d, - 0x22b9, 0x229d, 0x229d, 0x229d, 0x229d, 0x229d, 0x22c6, 0x229d, - 0x229d, 0x229d, 0x229d, 0x229d, 0x22d3, 0x080c, 0x0dc5, 0xa17c, - 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa06c, - 0x9420, 0xa070, 0x9319, 0x0498, 0xa194, 0x2400, 0x9122, 0xa198, + 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, - 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, 0x2310, 0x1f14, - 0x2310, 0x2306, 0x2309, 0x230c, 0x2309, 0x230c, 0x080c, 0x1f14, - 0x0005, 0x080c, 0x11b2, 0x0005, 0x080c, 0x1f14, 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, 0x242f, 0x7900, 0xd1dc, - 0x1118, 0x9084, 0x0006, 0x001a, 0x9084, 0x000e, 0x0002, 0x2357, - 0x234f, 0x7f4d, 0x234f, 0x2351, 0x2351, 0x2351, 0x2351, 0x7f33, - 0x234f, 0x2353, 0x234f, 0x2351, 0x234f, 0x2351, 0x234f, 0x080c, - 0x0dc5, 0x0031, 0x0020, 0x080c, 0x7f33, 0x080c, 0x7f4d, 0x0005, - 0x0006, 0x0016, 0x0026, 0x080c, 0xee1b, 0x7930, 0x9184, 0x0003, - 0x01c0, 0x2001, 0x19f8, 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, - 0x2004, 0x9005, 0x090c, 0x0dc5, 0x00c6, 0x2001, 0x19f8, 0x2064, - 0x080c, 0xca71, 0x00ce, 0x00f8, 0x2009, 0x0040, 0x080c, 0x2432, - 0x00d0, 0x9184, 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, - 0x080c, 0x7569, 0x1138, 0x080c, 0x784e, 0x080c, 0x6127, 0x080c, - 0x7495, 0x0010, 0x080c, 0x5fe6, 0x080c, 0x7ffc, 0x0041, 0x0018, - 0x9184, 0x9540, 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, - 0x0036, 0x0046, 0x0056, 0x2071, 0x1a66, 0x080c, 0x1b02, 0x005e, - 0x004e, 0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, - 0x1800, 0x7128, 0x2001, 0x1970, 0x2102, 0x2001, 0x1978, 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, 0x2c80, - 0x080c, 0x2b9b, 0x6054, 0x8004, 0x8004, 0x8004, 0x8004, 0x9084, - 0x000c, 0x6150, 0x918c, 0xfff3, 0x9105, 0x6052, 0x6050, 0x9084, - 0xb17f, 0x9085, 0x2000, 0x6052, 0x2009, 0x199e, 0x2011, 0x199f, - 0x6358, 0x939c, 0x38f0, 0x2320, 0x080c, 0x2bdf, 0x1238, 0x939d, - 0x4003, 0x94a5, 0x8603, 0x230a, 0x2412, 0x0030, 0x939d, 0x0203, - 0x94a5, 0x8603, 0x230a, 0x2412, 0x9006, 0x080c, 0x2bca, 0x9006, - 0x080c, 0x2bad, 0x20a9, 0x0012, 0x1d04, 0x2484, 0x2091, 0x6000, - 0x1f04, 0x2484, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, - 0x0400, 0x9084, 0xdfff, 0x6052, 0x6024, 0x6026, 0x080c, 0x28cd, - 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x28dd, 0x60e7, 0x0000, - 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, - 0x0080, 0x602f, 0x0000, 0x6007, 0x349f, 0x60bb, 0x0000, 0x20a9, - 0x0018, 0x60bf, 0x0000, 0x1f04, 0x24b1, 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, 0x2534, 0x251a, 0x251d, 0x2520, 0x2525, 0x2527, - 0x252b, 0x252f, 0x080c, 0x921e, 0x00b8, 0x080c, 0x92ed, 0x00a0, - 0x080c, 0x92ed, 0x080c, 0x921e, 0x0078, 0x0099, 0x0068, 0x080c, - 0x921e, 0x0079, 0x0048, 0x080c, 0x92ed, 0x0059, 0x0028, 0x080c, - 0x92ed, 0x080c, 0x921e, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, - 0x0005, 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, - 0x27a5, 0xd1f4, 0x190c, 0x0dbe, 0x080c, 0x7569, 0x0904, 0x258f, - 0x080c, 0xd561, 0x1120, 0x7000, 0x9086, 0x0003, 0x0570, 0x6024, - 0x9084, 0x1800, 0x0550, 0x080c, 0x758c, 0x0118, 0x080c, 0x757a, - 0x1520, 0x6027, 0x0020, 0x6043, 0x0000, 0x080c, 0xd561, 0x0168, - 0x080c, 0x758c, 0x1150, 0x2001, 0x19a9, 0x2003, 0x0001, 0x6027, - 0x1800, 0x080c, 0x73e4, 0x0804, 0x27a8, 0x70a4, 0x9005, 0x1150, - 0x70a7, 0x0001, 0x00d6, 0x2069, 0x0140, 0x080c, 0x75bd, 0x00de, - 0x1904, 0x27a8, 0x080c, 0x7858, 0x0428, 0x080c, 0x758c, 0x1590, - 0x6024, 0x9084, 0x1800, 0x1108, 0x0468, 0x080c, 0x7858, 0x080c, - 0x784e, 0x080c, 0x6127, 0x080c, 0x7495, 0x0804, 0x27a5, 0xd1ac, - 0x1508, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1178, 0xd0d4, 0x1190, - 0xd0cc, 0x0130, 0x7098, 0x9086, 0x0029, 0x1110, 0x080c, 0x773b, - 0x0804, 0x27a5, 0x080c, 0x7853, 0x0048, 0x2001, 0x197e, 0x2003, - 0x0002, 0x0020, 0x080c, 0x769e, 0x0804, 0x27a5, 0x080c, 0x77d6, - 0x0804, 0x27a5, 0x6220, 0xd1bc, 0x0138, 0xd2bc, 0x1904, 0x2802, - 0xd2b4, 0x1904, 0x2815, 0x0000, 0xd1ac, 0x0904, 0x26ba, 0x0036, - 0x6328, 0xc3bc, 0x632a, 0x003e, 0x080c, 0x7569, 0x11c0, 0x6027, - 0x0020, 0x0006, 0x0026, 0x0036, 0x080c, 0x7583, 0x1158, 0x080c, - 0x784e, 0x080c, 0x6127, 0x080c, 0x7495, 0x003e, 0x002e, 0x000e, - 0x00ae, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x7541, 0x0016, - 0x0046, 0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, - 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74da, 0x948c, 0xff00, - 0x7038, 0xd084, 0x0190, 0x080c, 0xd561, 0x1118, 0x9186, 0xf800, - 0x1160, 0x7048, 0xd084, 0x1148, 0xc085, 0x704a, 0x0036, 0x2418, - 0x2011, 0x8016, 0x080c, 0x4be9, 0x003e, 0x080c, 0xd55a, 0x1904, - 0x2697, 0x9196, 0xff00, 0x05a8, 0x7060, 0x9084, 0x00ff, 0x810f, - 0x81ff, 0x0110, 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, - 0x33a0, 0x0128, 0xc18d, 0x7132, 0x080c, 0x6a8a, 0x1510, 0x6240, - 0x9294, 0x0010, 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, - 0x01c0, 0x7030, 0xd08c, 0x0904, 0x2697, 0x7038, 0xd08c, 0x1140, - 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, 0x2697, 0xc1ad, 0x2102, - 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c, 0x4be9, 0x003e, 0x0804, - 0x2697, 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, - 0x1904, 0x2697, 0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, - 0x080c, 0x4be9, 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1848, - 0x220c, 0xd1a4, 0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, - 0x080c, 0x891c, 0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, - 0xe915, 0x00ce, 0x9484, 0x00ff, 0x9080, 0x33ac, 0x200d, 0x918c, - 0xff00, 0x810f, 0x2120, 0x9006, 0x2009, 0x000e, 0x080c, 0xe9a5, - 0x001e, 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x3211, - 0x001e, 0x00a8, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, - 0x671d, 0x1140, 0x7030, 0xd084, 0x1118, 0xb800, 0xd0bc, 0x1110, - 0x080c, 0x6141, 0x8108, 0x1f04, 0x2687, 0x00be, 0x015e, 0x00ce, - 0x004e, 0x080c, 0xb072, 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, 0x27a5, 0x0016, 0x6220, 0xd2b4, - 0x0904, 0x2742, 0x080c, 0x878f, 0x080c, 0xa517, 0x6027, 0x0004, - 0x00f6, 0x2019, 0x19f2, 0x2304, 0x907d, 0x0904, 0x2711, 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, 0x2d62, 0x2001, 0x001e, 0x8001, 0x0240, 0x20a9, - 0x0009, 0x080c, 0x2c5b, 0x6904, 0xd1dc, 0x1140, 0x0cb0, 0x2001, - 0x0100, 0x080c, 0x2d52, 0x9006, 0x080c, 0x2d52, 0x080c, 0x97e1, - 0x080c, 0x98ed, 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, 0x080c, - 0xb101, 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x00ae, - 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, - 0x0110, 0x080c, 0x2d62, 0x00de, 0x00c6, 0x2061, 0x19e9, 0x6028, - 0x080c, 0xd561, 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, 0x909a, - 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0xa4f3, 0x0804, - 0x27a4, 0x2061, 0x0100, 0x62c0, 0x080c, 0xaef8, 0x2019, 0x19f2, - 0x2304, 0x9065, 0x0120, 0x2009, 0x0027, 0x080c, 0xb180, 0x00ce, - 0x0804, 0x27a4, 0xd2bc, 0x0904, 0x278b, 0x080c, 0x879c, 0x6014, - 0x9084, 0x1984, 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, - 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2d62, - 0x00de, 0x00c6, 0x2061, 0x19e9, 0x6044, 0x080c, 0xd561, 0x0120, - 0x909a, 0x0003, 0x1658, 0x0018, 0x909a, 0x00c8, 0x1638, 0x8000, - 0x6046, 0x603c, 0x00ce, 0x9005, 0x05b8, 0x2009, 0x07d0, 0x080c, - 0x8794, 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, 0xa877, 0x003e, 0x2019, 0x19f8, 0x2304, 0x9065, - 0x0150, 0x2009, 0x004f, 0x6020, 0x9086, 0x0009, 0x1110, 0x2009, - 0x004f, 0x080c, 0xb180, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x27fd, - 0x7038, 0xd0ac, 0x1538, 0x0016, 0x0156, 0x6027, 0x0008, 0x080c, - 0x2d8c, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x27b3, 0x6150, 0x9185, - 0x1400, 0x6052, 0x20a9, 0x0366, 0x1d04, 0x27bc, 0x080c, 0x87c3, - 0x6020, 0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, - 0x04a0, 0x080c, 0x2c42, 0x1f04, 0x27bc, 0x015e, 0x6152, 0x001e, - 0x6027, 0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x080c, 0xb072, - 0x60e3, 0x0000, 0x080c, 0xedfa, 0x080c, 0xee15, 0x080c, 0x57d7, - 0xd0fc, 0x1138, 0x080c, 0xd55a, 0x1120, 0x9085, 0x0001, 0x080c, - 0x75ad, 0x9006, 0x080c, 0x2d52, 0x2009, 0x0002, 0x080c, 0x2c80, - 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, 0x25bc, 0x0016, 0x2009, 0x280e, 0x00d0, 0x2001, 0x188b, - 0x200c, 0xc184, 0x2102, 0x001e, 0x0c40, 0x0016, 0x2001, 0x188b, - 0x200c, 0xd194, 0x001e, 0x0904, 0x25bc, 0x0016, 0x2009, 0x2821, - 0x0038, 0x2001, 0x188b, 0x200c, 0xc194, 0x2102, 0x001e, 0x08a8, - 0x6028, 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, 0xbc91, 0x8000, - 0x2003, 0xffff, 0x6043, 0x0001, 0x080c, 0x2c7a, 0x6027, 0x0080, - 0x6017, 0x0000, 0x6043, 0x0000, 0x0817, 0x0006, 0x0016, 0x0026, - 0x0036, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, - 0x71d0, 0x70d2, 0x9116, 0x0904, 0x288c, 0x81ff, 0x01a0, 0x2009, - 0x0000, 0x080c, 0x2c80, 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, - 0x939e, 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, - 0x080c, 0x4be9, 0x0448, 0x2001, 0x19aa, 0x200c, 0x81ff, 0x1140, - 0x2001, 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, - 0x2118, 0x2011, 0x8012, 0x080c, 0x4be9, 0x080c, 0x0ea3, 0x080c, - 0x57d7, 0xd0fc, 0x1188, 0x080c, 0xd55a, 0x1170, 0x00c6, 0x080c, - 0x2928, 0x080c, 0xa7de, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, - 0x0002, 0x080c, 0x3211, 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, 0x8271, 0x0048, 0x9584, 0x00ff, 0x9080, - 0x33ac, 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, - 0x33ac, 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, - 0x2001, 0x1818, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, - 0x6856, 0x1f04, 0x28d8, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, - 0x2069, 0x0140, 0x2001, 0x1818, 0x2102, 0x8114, 0x8214, 0x8214, - 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, - 0x9184, 0x000f, 0x9080, 0xf5f7, 0x2005, 0x6856, 0x8211, 0x1f04, - 0x28ed, 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, 0x291d, - 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, - 0x080c, 0x57d3, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, - 0x2020, 0x2009, 0x002e, 0x080c, 0xe9a5, 0x004e, 0x0005, 0x00f6, - 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x2994, - 0x080c, 0x2bdf, 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, 0x91b1, 0x928c, 0xff00, 0x0110, - 0x2011, 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, - 0x0138, 0x220a, 0x080c, 0x7569, 0x1118, 0x2009, 0x196e, 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, 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, 0x1991, 0x2004, - 0x908a, 0x0007, 0x1a0c, 0x0dc5, 0x0033, 0x00ee, 0x002e, 0x001e, - 0x000e, 0x015e, 0x0005, 0x29f2, 0x2a10, 0x2a34, 0x2a36, 0x2a5f, - 0x2a61, 0x2a63, 0x2001, 0x0001, 0x080c, 0x283d, 0x080c, 0x2c3d, - 0x2001, 0x1993, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, - 0x9006, 0x20a9, 0x0009, 0x080c, 0x2bfb, 0x2001, 0x1991, 0x2003, - 0x0006, 0x2009, 0x001e, 0x2011, 0x2a64, 0x080c, 0x87a1, 0x0005, - 0x2009, 0x1996, 0x200b, 0x0000, 0x2001, 0x199b, 0x2003, 0x0036, - 0x2001, 0x199a, 0x2003, 0x002a, 0x2001, 0x1993, 0x2003, 0x0001, - 0x9006, 0x080c, 0x2bad, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, - 0x2bfb, 0x2001, 0x1991, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, - 0x2a64, 0x080c, 0x87a1, 0x0005, 0x080c, 0x0dc5, 0x2001, 0x199b, - 0x2003, 0x0036, 0x2001, 0x1993, 0x2003, 0x0003, 0x7a38, 0x9294, - 0x0005, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x080c, 0x2bad, 0x2001, 0x1997, 0x2003, 0x0000, 0x2001, 0xffff, - 0x20a9, 0x0009, 0x080c, 0x2bfb, 0x2001, 0x1991, 0x2003, 0x0006, - 0x2009, 0x001e, 0x2011, 0x2a64, 0x080c, 0x87a1, 0x0005, 0x080c, - 0x0dc5, 0x080c, 0x0dc5, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, - 0x00f6, 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, - 0x1993, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0dc5, 0x0043, 0x012e, - 0x015e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x2a86, - 0x2aa2, 0x2ade, 0x2b0a, 0x2b2a, 0x2b36, 0x2b38, 0x080c, 0x2bef, - 0x1190, 0x2009, 0x1999, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, - 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x1991, - 0x2003, 0x0001, 0x0030, 0x080c, 0x2b5c, 0x2001, 0xffff, 0x080c, - 0x2a01, 0x0005, 0x080c, 0x2b3a, 0x05c0, 0x2009, 0x199a, 0x2104, - 0x8001, 0x200a, 0x080c, 0x2bef, 0x1158, 0x7a38, 0x9294, 0x0005, - 0x9296, 0x0005, 0x0518, 0x2009, 0x1999, 0x2104, 0xc085, 0x200a, - 0x2009, 0x1996, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, - 0x080c, 0x2b42, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, + 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, - 0x2bca, 0x2001, 0x1993, 0x2003, 0x0002, 0x0028, 0x2001, 0x1991, - 0x2003, 0x0003, 0x0010, 0x080c, 0x2a23, 0x0005, 0x080c, 0x2b3a, - 0x0540, 0x2009, 0x199a, 0x2104, 0x8001, 0x200a, 0x080c, 0x2bef, - 0x1148, 0x2001, 0x1991, 0x2003, 0x0003, 0x2001, 0x1992, 0x2003, - 0x0000, 0x00b8, 0x2009, 0x199a, 0x2104, 0x9005, 0x1118, 0x080c, - 0x2b7f, 0x0010, 0x080c, 0x2b4f, 0x080c, 0x2b42, 0x2009, 0x1996, - 0x200b, 0x0000, 0x2001, 0x1993, 0x2003, 0x0001, 0x080c, 0x2a23, - 0x0000, 0x0005, 0x0479, 0x01e8, 0x080c, 0x2bef, 0x1198, 0x2009, - 0x1997, 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, - 0x2001, 0x199c, 0x2003, 0x000a, 0x2009, 0x1999, 0x2104, 0xc0fd, - 0x200a, 0x0038, 0x00f9, 0x2001, 0x1993, 0x2003, 0x0004, 0x080c, - 0x2a4e, 0x0005, 0x0079, 0x0148, 0x080c, 0x2bef, 0x1118, 0x080c, - 0x2a3a, 0x0018, 0x0079, 0x080c, 0x2a4e, 0x0005, 0x080c, 0x0dc5, - 0x080c, 0x0dc5, 0x2009, 0x199b, 0x2104, 0x8001, 0x200a, 0x090c, - 0x2b9b, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, - 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2bca, 0x0005, 0x7a38, - 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x2bad, 0x0005, 0x2009, 0x1996, 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, 0x2bca, 0x0005, 0x0086, - 0x2001, 0x1999, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0dc5, 0x2009, - 0x1998, 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, - 0xd084, 0x1120, 0x080c, 0x0dc5, 0x9006, 0x0010, 0x2001, 0x0001, - 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x1991, 0x20a9, - 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, 0x2ba1, 0x2001, 0x1998, - 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, - 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, - 0x783a, 0x2009, 0x199e, 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, - 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, 0x199f, 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, 0x2c7a, 0xd09c, 0x1110, 0x1f04, - 0x2bf2, 0x015e, 0x0005, 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, - 0x7850, 0x9085, 0x0040, 0x7852, 0x7850, 0x9084, 0xfbcf, 0x7852, - 0x080c, 0x2c7a, 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, 0x2c28, 0x080c, 0x87c3, 0x1f04, 0x2c28, 0x7850, 0x9085, - 0x0400, 0x9084, 0xdfbf, 0x7852, 0x080c, 0x2c7a, 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, - 0x2c4c, 0x0028, 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2c52, 0x00fe, - 0x015e, 0x000e, 0x0005, 0x1d04, 0x2c5b, 0x080c, 0x87c3, 0x1f04, - 0x2c5b, 0x0005, 0x0006, 0x2001, 0x199d, 0x2004, 0x9086, 0x0000, - 0x000e, 0x0005, 0x0006, 0x2001, 0x199d, 0x2004, 0x9086, 0x0001, - 0x000e, 0x0005, 0x0006, 0x2001, 0x199d, 0x2004, 0x9086, 0x0002, - 0x000e, 0x0005, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, - 0x0006, 0x2001, 0x19aa, 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, 0x2cf3, 0x0048, 0x0016, 0x2009, - 0x1a88, 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, - 0x1a89, 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, 0x1982, - 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, 0x7583, 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, 0x7583, 0x0110, 0xc0bc, 0x0008, 0xc0bd, - 0x200a, 0x001e, 0x000e, 0x0005, 0x0006, 0x0156, 0x6050, 0x9085, - 0x0040, 0x6052, 0x6050, 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2c7a, - 0x9085, 0x2000, 0x6052, 0x20a9, 0x0012, 0x1d04, 0x2d9d, 0x080c, - 0x87c3, 0x1f04, 0x2d9d, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, - 0x6052, 0x015e, 0x000e, 0x0005, 0x3018, 0x3018, 0x2e3c, 0x2e3c, - 0x2e48, 0x2e48, 0x2e54, 0x2e54, 0x2e62, 0x2e62, 0x2e6e, 0x2e6e, - 0x2e7c, 0x2e7c, 0x2e8a, 0x2e8a, 0x2e9c, 0x2e9c, 0x2ea8, 0x2ea8, - 0x2eb6, 0x2eb6, 0x2ed4, 0x2ed4, 0x2ef4, 0x2ef4, 0x2ec4, 0x2ec4, - 0x2ee4, 0x2ee4, 0x2f02, 0x2f02, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, - 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, - 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, - 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, - 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2f14, 0x2f14, 0x2f20, 0x2f20, - 0x2f2e, 0x2f2e, 0x2f3c, 0x2f3c, 0x2f4c, 0x2f4c, 0x2f5a, 0x2f5a, - 0x2f6a, 0x2f6a, 0x2f7a, 0x2f7a, 0x2f8c, 0x2f8c, 0x2f9a, 0x2f9a, - 0x2faa, 0x2faa, 0x2fcc, 0x2fcc, 0x2fee, 0x2fee, 0x2fba, 0x2fba, - 0x2fdd, 0x2fdd, 0x2ffd, 0x2ffd, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, - 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, - 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, - 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, - 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, - 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, - 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x24e1, 0x0804, 0x3010, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x22f5, 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22f5, 0x080c, 0x24e1, - 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2330, 0x0804, 0x3010, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x24e1, - 0x080c, 0x2330, 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22f5, 0x080c, 0x2330, - 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x22f5, 0x080c, 0x24e1, 0x080c, 0x2330, - 0x0804, 0x3010, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1394, 0x0804, 0x3010, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x24e1, 0x080c, 0x1394, 0x0804, 0x3010, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22f5, - 0x080c, 0x1394, 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x24e1, 0x080c, 0x1394, - 0x080c, 0x2330, 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22f5, 0x080c, 0x24e1, - 0x080c, 0x1394, 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22f5, 0x080c, 0x1394, - 0x080c, 0x2330, 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1394, 0x080c, 0x2330, - 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x22f5, 0x080c, 0x24e1, 0x080c, 0x1394, - 0x080c, 0x2330, 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2997, 0x0804, 0x3010, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2997, 0x080c, 0x24e1, 0x0804, 0x3010, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2997, - 0x080c, 0x22f5, 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, 0x22f5, - 0x080c, 0x24e1, 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, 0x2330, - 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, 0x24e1, 0x080c, 0x2330, - 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, 0x22f5, 0x080c, 0x2330, - 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, 0x22f5, 0x080c, 0x24e1, - 0x080c, 0x2330, 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, 0x1394, - 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, 0x24e1, 0x080c, 0x1394, - 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, 0x22f5, 0x080c, 0x1394, - 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, 0x24e1, 0x080c, 0x1394, - 0x080c, 0x2330, 0x0804, 0x3010, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, 0x22f5, - 0x080c, 0x24e1, 0x080c, 0x1394, 0x0498, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, - 0x22f5, 0x080c, 0x1394, 0x080c, 0x2330, 0x0410, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2997, - 0x080c, 0x1394, 0x080c, 0x2330, 0x0098, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2997, 0x080c, - 0x22f5, 0x080c, 0x24e1, 0x080c, 0x1394, 0x080c, 0x2330, 0x0000, - 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, - 0x000d, 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6a50, - 0x1904, 0x312d, 0x72dc, 0x2001, 0x197d, 0x2004, 0x9005, 0x1110, - 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x312d, 0x080c, - 0x3132, 0x0804, 0x312d, 0xd2cc, 0x1904, 0x312d, 0x080c, 0x7569, - 0x1120, 0x70af, 0xffff, 0x0804, 0x312d, 0xd294, 0x0120, 0x70af, - 0xffff, 0x0804, 0x312d, 0x080c, 0x339b, 0x0160, 0x080c, 0xd561, - 0x0128, 0x2001, 0x1818, 0x203c, 0x0804, 0x30b6, 0x70af, 0xffff, - 0x0804, 0x312d, 0x2001, 0x1818, 0x203c, 0x7294, 0xd284, 0x0904, - 0x30b6, 0xd28c, 0x1904, 0x30b6, 0x0036, 0x73ac, 0x938e, 0xffff, - 0x1110, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, 0x2c04, 0x938c, - 0x0001, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, - 0x970e, 0x05d0, 0x908e, 0x0000, 0x05b8, 0x908e, 0x00ff, 0x1150, - 0x7230, 0xd284, 0x15b0, 0x7294, 0xc28d, 0x7296, 0x70af, 0xffff, - 0x003e, 0x04a0, 0x900e, 0x080c, 0x2894, 0x080c, 0x66b2, 0x1538, - 0x9006, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, 0x2060, - 0x080c, 0x8bc3, 0x00ce, 0x090c, 0x8f64, 0xb8af, 0x0000, 0x080c, - 0x6a92, 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, 0xd0bc, 0x0138, - 0x080c, 0x693d, 0x0120, 0x080c, 0x314b, 0x0148, 0x0028, 0x080c, - 0x328b, 0x080c, 0x3177, 0x0118, 0x8318, 0x0804, 0x3063, 0x73ae, - 0x0010, 0x70af, 0xffff, 0x003e, 0x0804, 0x312d, 0x9780, 0x33ac, - 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x70ac, 0x9096, - 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, 0x0220, 0x2008, - 0x9802, 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804, 0x312d, 0x2700, - 0x0156, 0x0016, 0x9106, 0x0904, 0x3122, 0xc484, 0x080c, 0x671d, - 0x0168, 0x080c, 0xd561, 0x1904, 0x3122, 0x080c, 0x339b, 0x1904, - 0x3122, 0x080c, 0x66b2, 0x1904, 0x312a, 0x0008, 0xc485, 0xb8bb, - 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c, 0x8bc3, - 0x00ce, 0x090c, 0x8f64, 0xb8af, 0x0000, 0x080c, 0x6a92, 0x1130, - 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0, 0x7294, 0xd28c, - 0x0180, 0x080c, 0x6a92, 0x9082, 0x0006, 0x02e0, 0xd484, 0x1118, - 0x080c, 0x66d7, 0x0028, 0x080c, 0x3317, 0x01a0, 0x080c, 0x3342, - 0x0088, 0x080c, 0x328b, 0x080c, 0xd561, 0x1160, 0x080c, 0x3177, - 0x0188, 0x0040, 0x080c, 0xd561, 0x1118, 0x080c, 0x3317, 0x0110, - 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x30cf, 0x70af, - 0xffff, 0x0018, 0x001e, 0x015e, 0x71ae, 0x004e, 0x002e, 0x00ce, - 0x00be, 0x0005, 0x00c6, 0x0016, 0x70af, 0x0001, 0x2009, 0x007e, - 0x080c, 0x66b2, 0x1168, 0xb813, 0x00ff, 0xb817, 0xfffe, 0x080c, - 0x328b, 0x04a9, 0x0128, 0x70dc, 0xc0bd, 0x70de, 0x080c, 0xd2a9, - 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, - 0x184c, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, 0xb153, 0x01d0, - 0x2b00, 0x6012, 0x080c, 0xd2d2, 0x6023, 0x0001, 0x9006, 0x080c, - 0x664f, 0x2001, 0x0000, 0x080c, 0x6663, 0x0126, 0x2091, 0x8000, - 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, 0x0004, 0x080c, 0xb180, - 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, - 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, 0x2004, 0x9084, 0x00ff, - 0xb842, 0x080c, 0xb153, 0x0548, 0x2b00, 0x6012, 0xb800, 0xc0c4, - 0xb802, 0xb8a0, 0x9086, 0x007e, 0x0140, 0xb804, 0x9084, 0x00ff, - 0x9086, 0x0006, 0x1110, 0x080c, 0x3246, 0x080c, 0xd2d2, 0x6023, - 0x0001, 0x9006, 0x080c, 0x664f, 0x2001, 0x0002, 0x080c, 0x6663, - 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, - 0x0002, 0x080c, 0xb180, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, - 0x001e, 0x0005, 0x00b6, 0x00c6, 0x0026, 0x2009, 0x0080, 0x080c, - 0x66b2, 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, 0x0039, 0x0110, - 0x70e3, 0xffff, 0x002e, 0x00ce, 0x00be, 0x0005, 0x0016, 0x0076, - 0x00d6, 0x00c6, 0x080c, 0xb0ab, 0x01d0, 0x2b00, 0x6012, 0x080c, - 0xd2d2, 0x6023, 0x0001, 0x9006, 0x080c, 0x664f, 0x2001, 0x0002, - 0x080c, 0x6663, 0x0126, 0x2091, 0x8000, 0x70e4, 0x8000, 0x70e6, - 0x012e, 0x2009, 0x0002, 0x080c, 0xb180, 0x9085, 0x0001, 0x00ce, - 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, - 0x8000, 0x2009, 0x007f, 0x080c, 0x66b2, 0x11b8, 0xb813, 0x00ff, - 0xb817, 0xfffd, 0xb8cf, 0x0004, 0x080c, 0xb0ab, 0x0170, 0x2b00, - 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, 0xd2d2, 0x2009, - 0x0022, 0x080c, 0xb180, 0x9085, 0x0001, 0x012e, 0x00de, 0x00ce, - 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x00b6, 0x21f0, - 0x080c, 0x94eb, 0x080c, 0x946b, 0x080c, 0xaf3f, 0x080c, 0xc051, - 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, - 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x671d, 0x1140, 0x9686, - 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x6141, 0x001e, - 0x8108, 0x1f04, 0x322b, 0x9686, 0x0001, 0x190c, 0x336f, 0x00be, - 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, - 0x0046, 0x0036, 0x0026, 0x0016, 0x00b6, 0x6210, 0x2258, 0xbaa0, - 0x0026, 0x2019, 0x0029, 0x080c, 0x94e0, 0x0076, 0x2039, 0x0000, - 0x080c, 0x93b3, 0x2c08, 0x080c, 0xe690, 0x007e, 0x001e, 0xba10, - 0xbb14, 0xbcc0, 0x080c, 0x6141, 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, 0x57d3, - 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2020, 0x2009, 0x002d, - 0x080c, 0xe9a5, 0x20a9, 0x0800, 0x9016, 0x0026, 0x928e, 0x007e, - 0x0904, 0x32f6, 0x928e, 0x007f, 0x0904, 0x32f6, 0x928e, 0x0080, - 0x05e8, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05c0, 0x8fff, 0x1148, - 0x2001, 0x198f, 0x0006, 0x2003, 0x0001, 0x04f1, 0x000e, 0x2003, - 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, 0x0001, 0x080c, 0x6a5c, - 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, 0x94e0, 0x0076, 0x2039, - 0x0000, 0x080c, 0x93b3, 0x00b6, 0x00c6, 0x0026, 0x2158, 0xba04, - 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, 0xb807, 0x0404, 0x0028, - 0x2001, 0x0004, 0x8007, 0x9215, 0xba06, 0x002e, 0x00ce, 0x00be, - 0x0016, 0x2c08, 0x080c, 0xe690, 0x001e, 0x007e, 0x002e, 0x8210, - 0x1f04, 0x32ad, 0x015e, 0x001e, 0x002e, 0x003e, 0x004e, 0x00be, - 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x080c, - 0x57d3, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2220, 0x2009, - 0x0029, 0x080c, 0xe9a5, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, - 0x0026, 0x0036, 0x00c6, 0x7294, 0x82ff, 0x01e8, 0x080c, 0x6a8a, - 0x11d0, 0x2100, 0x080c, 0x28c7, 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, 0x1ab8, 0x001e, 0x6112, 0x080c, - 0x3246, 0x001e, 0x080c, 0x66d7, 0x012e, 0x00ce, 0x001e, 0x0005, - 0x0016, 0x0026, 0x2110, 0x080c, 0xaa9a, 0x080c, 0xed0f, 0x002e, - 0x001e, 0x0005, 0x2001, 0x1837, 0x2004, 0xd0cc, 0x0005, 0x00c6, - 0x00b6, 0x080c, 0x7569, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, - 0x0782, 0x080c, 0x7569, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, - 0x9180, 0x1000, 0x2004, 0x905d, 0x0130, 0x86ff, 0x0110, 0xb800, - 0xd0bc, 0x090c, 0x66d7, 0x8108, 0x1f04, 0x3380, 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, + 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, 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, 0x34db, - 0x34dc, 0x34ef, 0x3503, 0x0005, 0x1004, 0x34ec, 0x0e04, 0x34ec, - 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, 0x35d7, 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, 0x35d4, 0x61d0, 0x0804, - 0x3569, 0x35ab, 0x35e3, 0x35d4, 0x35ef, 0x35f9, 0x35ff, 0x3603, - 0x3613, 0x3617, 0x362d, 0x3633, 0x3639, 0x3644, 0x364f, 0x365e, - 0x366d, 0x367b, 0x3692, 0x36ad, 0x35d4, 0x3756, 0x3794, 0x383a, - 0x384b, 0x386e, 0x35d4, 0x35d4, 0x35d4, 0x38a6, 0x38c2, 0x38cb, - 0x38fa, 0x3900, 0x35d4, 0x3946, 0x35d4, 0x35d4, 0x35d4, 0x35d4, - 0x35d4, 0x3951, 0x395a, 0x3962, 0x3964, 0x35d4, 0x35d4, 0x35d4, - 0x35d4, 0x35d4, 0x35d4, 0x3990, 0x35d4, 0x35d4, 0x35d4, 0x35d4, - 0x35d4, 0x39ad, 0x3a22, 0x35d4, 0x35d4, 0x35d4, 0x35d4, 0x35d4, - 0x35d4, 0x0002, 0x3a4c, 0x3a4f, 0x3aae, 0x3ac7, 0x3af7, 0x3d99, - 0x35d4, 0x5396, 0x35d4, 0x35d4, 0x35d4, 0x35d4, 0x35d4, 0x35d4, - 0x35d4, 0x35d4, 0x362d, 0x3633, 0x42ce, 0x57f7, 0x42ec, 0x5425, - 0x5477, 0x5582, 0x35d4, 0x55e4, 0x5620, 0x5651, 0x5759, 0x567e, - 0x56d9, 0x35d4, 0x42f0, 0x44b6, 0x44cc, 0x44f1, 0x4556, 0x45ca, - 0x45ea, 0x4661, 0x46bd, 0x4719, 0x471c, 0x4741, 0x47f8, 0x485e, - 0x4866, 0x499b, 0x4b13, 0x4b47, 0x4dab, 0x35d4, 0x4dc9, 0x4e6f, - 0x4f58, 0x4fb2, 0x35d4, 0x5069, 0x35d4, 0x50d5, 0x50f0, 0x4866, - 0x5336, 0x714c, 0x0000, 0x2021, 0x4000, 0x080c, 0x4bc5, 0x0126, - 0x2091, 0x8000, 0x0e04, 0x35b5, 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, 0x4bd2, 0x2039, - 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, - 0x4bd5, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, 0x35ab, 0x7984, - 0x2114, 0x0804, 0x35ab, 0x20e1, 0x0000, 0x2099, 0x0021, 0x20e9, - 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, 0x7984, 0x7a88, - 0x7b8c, 0x0804, 0x35ab, 0x7884, 0x2060, 0x0804, 0x3660, 0x2009, - 0x0003, 0x2011, 0x0003, 0x2019, 0x0012, 0x789b, 0x0137, 0x7893, - 0xffff, 0x2001, 0x188f, 0x2004, 0x9005, 0x0118, 0x7896, 0x0804, - 0x35ab, 0x7897, 0x0001, 0x0804, 0x35ab, 0x2039, 0x0001, 0x7d98, - 0x7c9c, 0x0804, 0x35e7, 0x2039, 0x0001, 0x7d98, 0x7c9c, 0x0804, - 0x35f3, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x35e0, 0x2138, - 0x7d98, 0x7c9c, 0x0804, 0x35e7, 0x79a0, 0x9182, 0x0040, 0x0210, - 0x0804, 0x35e0, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x35f3, 0x79a0, - 0x9182, 0x0040, 0x0210, 0x0804, 0x35e0, 0x21e8, 0x7984, 0x7888, - 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x35ab, 0x2061, 0x0800, - 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, 0x1dd8, 0x2010, - 0x9005, 0x0904, 0x35ab, 0x0804, 0x35da, 0x79a0, 0x9182, 0x0040, - 0x0210, 0x0804, 0x35e0, 0x21e0, 0x20a9, 0x0001, 0x7984, 0x2198, - 0x4012, 0x0804, 0x35ab, 0x2069, 0x1847, 0x7884, 0x7990, 0x911a, - 0x1a04, 0x35e0, 0x8019, 0x0904, 0x35e0, 0x684a, 0x6942, 0x788c, - 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, 0x080c, 0x787f, - 0x0804, 0x35ab, 0x2069, 0x1847, 0x7884, 0x7994, 0x911a, 0x1a04, - 0x35e0, 0x8019, 0x0904, 0x35e0, 0x684e, 0x6946, 0x788c, 0x6862, - 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6b2a, 0x012e, 0x0804, 0x35ab, 0x902e, 0x2520, 0x81ff, - 0x0120, 0x2009, 0x0001, 0x0804, 0x35dd, 0x7984, 0x7b88, 0x7a8c, - 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a6, 0x4101, 0x080c, - 0x4b89, 0x1120, 0x2009, 0x0002, 0x0804, 0x35dd, 0x2009, 0x0020, - 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4bd2, 0x701f, 0x36d1, - 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, 0x0168, - 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, 0x9096, 0x0048, - 0x0120, 0x9096, 0x0029, 0x1904, 0x35dd, 0x810f, 0x918c, 0x00ff, - 0x0904, 0x35dd, 0x7112, 0x7010, 0x8001, 0x0560, 0x7012, 0x080c, - 0x4b89, 0x1120, 0x2009, 0x0002, 0x0804, 0x35dd, 0x2009, 0x0020, - 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, 0x9290, 0x0040, - 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0xa85c, 0x9080, - 0x0019, 0xaf60, 0x080c, 0x4bd2, 0x701f, 0x370f, 0x0005, 0xa864, - 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, 0x000a, 0x1904, - 0x35dd, 0x0888, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, - 0x9084, 0x00ff, 0x9096, 0x0029, 0x1160, 0xc2fd, 0xaa7a, 0x080c, - 0x6298, 0x0150, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, 0x012e, - 0x0050, 0x080c, 0x65c8, 0x1128, 0x7007, 0x0003, 0x701f, 0x373b, - 0x0005, 0x080c, 0x703d, 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, 0x4bd5, 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, 0x1a1d, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, - 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, - 0x2071, 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x35dd, 0x7984, - 0x080c, 0x671d, 0x1904, 0x35e0, 0x7e98, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x1a04, 0x35e0, 0x7c88, 0x7d8c, 0x080c, 0x6880, 0x080c, - 0x684f, 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, 0x35dd, 0x0c30, 0x080c, - 0xca71, 0x012e, 0x0904, 0x35dd, 0x0804, 0x35ab, 0x900e, 0x2001, - 0x0005, 0x080c, 0x703d, 0x0126, 0x2091, 0x8000, 0x080c, 0xd152, - 0x080c, 0x6dd1, 0x012e, 0x0804, 0x35ab, 0x00a6, 0x2950, 0xb198, - 0x080c, 0x671d, 0x1904, 0x3827, 0xb6a4, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x16e8, 0xb49c, 0xb5a0, 0x080c, 0x6880, 0x080c, 0x684f, - 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, 0xca71, - 0x012e, 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, 0x0005, - 0x080c, 0x703d, 0x0126, 0x2091, 0x8000, 0x080c, 0xd152, 0x080c, - 0x6dc4, 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, 0x35dd, 0x080c, 0x4ba0, 0x0904, - 0x35e0, 0x080c, 0x67e4, 0x0904, 0x35dd, 0x080c, 0x6886, 0x0904, - 0x35dd, 0x0804, 0x45e1, 0x81ff, 0x1904, 0x35dd, 0x080c, 0x4bbc, - 0x0904, 0x35e0, 0x080c, 0x6914, 0x0904, 0x35dd, 0x2019, 0x0005, - 0x79a8, 0x080c, 0x68a1, 0x0904, 0x35dd, 0x7888, 0x908a, 0x1000, - 0x1a04, 0x35e0, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x8717, - 0x79a8, 0xd184, 0x1904, 0x35ab, 0x0804, 0x45e1, 0x0126, 0x2091, - 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x07ff, - 0x645c, 0x2400, 0x9506, 0x01f8, 0x2508, 0x080c, 0x671d, 0x11d8, - 0x080c, 0x6914, 0x1128, 0x2009, 0x0002, 0x62c0, 0x2518, 0x00c0, - 0x2019, 0x0004, 0x900e, 0x080c, 0x68a1, 0x1118, 0x2009, 0x0006, - 0x0078, 0x7884, 0x908a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, - 0x9108, 0x080c, 0x8717, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x35ab, - 0x012e, 0x0804, 0x35dd, 0x012e, 0x0804, 0x35e0, 0x080c, 0x4ba0, - 0x0904, 0x35e0, 0x080c, 0x67e4, 0x0904, 0x35dd, 0xbaa0, 0x2019, - 0x0005, 0x00c6, 0x9066, 0x080c, 0x94e0, 0x0076, 0x903e, 0x080c, - 0x93b3, 0x900e, 0x080c, 0xe690, 0x007e, 0x00ce, 0x080c, 0x6880, - 0x0804, 0x35ab, 0x080c, 0x4ba0, 0x0904, 0x35e0, 0x080c, 0x6880, - 0x2208, 0x0804, 0x35ab, 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, 0x38dc, 0x2300, 0x9218, 0x00ee, - 0x00de, 0x015e, 0x0804, 0x35ab, 0x00f6, 0x0016, 0x907d, 0x0138, - 0x9006, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, - 0x00fe, 0x0005, 0x2069, 0x1910, 0x6910, 0x62bc, 0x0804, 0x35ab, - 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35dd, 0x0126, 0x2091, - 0x8000, 0x080c, 0x57e7, 0x0128, 0x2009, 0x0007, 0x012e, 0x0804, - 0x35dd, 0x012e, 0x615c, 0x9190, 0x33ac, 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, 0x7569, 0x1118, - 0x2031, 0x0004, 0x0038, 0xd79c, 0x0120, 0x2009, 0x0005, 0x0804, - 0x35dd, 0x9036, 0x7e9a, 0x7f9e, 0x0804, 0x35ab, 0x614c, 0x6250, - 0x2019, 0x1987, 0x231c, 0x2001, 0x1988, 0x2004, 0x789a, 0x0804, - 0x35ab, 0x0126, 0x2091, 0x8000, 0x6138, 0x623c, 0x6340, 0x012e, - 0x0804, 0x35ab, 0x080c, 0x4bbc, 0x0904, 0x35e0, 0xba44, 0xbb38, - 0x0804, 0x35ab, 0x080c, 0x0dc5, 0x080c, 0x4bbc, 0x2110, 0x0904, - 0x35e0, 0xb804, 0x908c, 0x00ff, 0x918e, 0x0006, 0x0140, 0x9084, - 0xff00, 0x9086, 0x0600, 0x2009, 0x0009, 0x1904, 0x35dd, 0x0126, - 0x2091, 0x8000, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, 0xaa9a, - 0x080c, 0x94e0, 0x0076, 0x903e, 0x080c, 0x93b3, 0x900e, 0x080c, - 0xe690, 0x007e, 0x00ce, 0xb807, 0x0407, 0x012e, 0x0804, 0x35ab, - 0x614c, 0x6250, 0x7884, 0x604e, 0x7b88, 0x6352, 0x2069, 0x1847, - 0x831f, 0x9305, 0x6816, 0x788c, 0x2069, 0x1987, 0x2d1c, 0x206a, - 0x7e98, 0x9682, 0x0014, 0x1210, 0x2031, 0x07d0, 0x2069, 0x1988, - 0x2d04, 0x266a, 0x789a, 0x0804, 0x35ab, 0x0126, 0x2091, 0x8000, - 0x6138, 0x7884, 0x603a, 0x910e, 0xd1b4, 0x190c, 0x0ebe, 0xd094, - 0x0148, 0x00e6, 0x2071, 0x19fc, 0x79b4, 0x9192, 0x07d0, 0x1208, - 0x713e, 0x00ee, 0xd0c4, 0x01a8, 0x00d6, 0x78a8, 0x2009, 0x199e, - 0x200a, 0x78ac, 0x2011, 0x199f, 0x2012, 0x2069, 0x0100, 0x6838, - 0x9086, 0x0007, 0x1118, 0x2214, 0x6a5a, 0x0010, 0x210c, 0x695a, - 0x00de, 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, 0x42ce, 0x6040, 0xd0cc, 0x0120, - 0x78b0, 0x2011, 0x0114, 0x2012, 0x012e, 0x0804, 0x35ab, 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, - 0x35e0, 0x788c, 0x902d, 0x0904, 0x35e0, 0x900e, 0x080c, 0x671d, - 0x1120, 0xba44, 0xbb38, 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, - 0x8108, 0x0ca0, 0x080c, 0x4bbc, 0x0904, 0x35e0, 0x7888, 0x900d, - 0x0904, 0x35e0, 0x788c, 0x9005, 0x0904, 0x35e0, 0xba44, 0xb946, - 0xbb38, 0xb83a, 0x0804, 0x35ab, 0x2011, 0xbc09, 0x0010, 0x2011, - 0xbc05, 0x080c, 0x57e7, 0x1904, 0x35dd, 0x00c6, 0x2061, 0x0100, - 0x7984, 0x9186, 0x00ff, 0x1130, 0x2001, 0x1818, 0x2004, 0x9085, - 0xff00, 0x0088, 0x9182, 0x007f, 0x16e0, 0x9188, 0x33ac, 0x210d, - 0x918c, 0x00ff, 0x2001, 0x1818, 0x2004, 0x0026, 0x9116, 0x002e, - 0x0580, 0x810f, 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, - 0xb0ab, 0x000e, 0x0510, 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, - 0x66b8, 0x2b08, 0x00be, 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, - 0x4b89, 0x01d0, 0x9006, 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, - 0xc0fd, 0xa86a, 0x701f, 0x3aa7, 0x2900, 0x6016, 0x2009, 0x0032, - 0x080c, 0xb180, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, - 0x35dd, 0x00ce, 0x0804, 0x35e0, 0x080c, 0xb101, 0x0cb0, 0xa830, - 0x9086, 0x0100, 0x0904, 0x35dd, 0x0804, 0x35ab, 0x2061, 0x1a75, - 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, - 0x2061, 0x1800, 0x6354, 0x6074, 0x789a, 0x60c0, 0x789e, 0x60bc, - 0x78aa, 0x012e, 0x0804, 0x35ab, 0x900e, 0x2110, 0x0c88, 0x81ff, - 0x1904, 0x35dd, 0x080c, 0x7569, 0x0904, 0x35dd, 0x0126, 0x2091, - 0x8000, 0x6254, 0x6074, 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, - 0x28fd, 0x080c, 0x5a0a, 0x012e, 0x0804, 0x35ab, 0x012e, 0x0804, - 0x35e0, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0x19ab, 0x2070, - 0x2061, 0x1847, 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, - 0x91b1, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, - 0x35ad, 0x7884, 0xd0fc, 0x0158, 0x2001, 0x002a, 0x2004, 0x9005, - 0x0180, 0x9082, 0x00e1, 0x0298, 0x012e, 0x0804, 0x35e0, 0x2001, - 0x002a, 0x2004, 0x9005, 0x0128, 0x2069, 0x1847, 0x6908, 0x9102, - 0x1230, 0x012e, 0x0804, 0x35e0, 0x012e, 0x0804, 0x35dd, 0x080c, - 0xb06b, 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x3b76, 0x00c6, 0x080c, - 0x4b89, 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, 0x3cfc, 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, 0x4bd2, - 0x701f, 0x3c39, 0x7023, 0x0001, 0x012e, 0x0005, 0x0046, 0x0086, - 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, - 0x3ae1, 0x2001, 0x19a1, 0x2003, 0x0000, 0x2021, 0x000a, 0x2061, - 0x0100, 0x6104, 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, 0x60bf, - 0x0012, 0x080c, 0x3d6b, 0x080c, 0x3d2a, 0x00f6, 0x00e6, 0x0086, - 0x2940, 0x2071, 0x1a6a, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, - 0x6884, 0xd0b4, 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, - 0x0034, 0x2004, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x4112, - 0x008e, 0x00ee, 0x00fe, 0x080c, 0x4034, 0x080c, 0x3f39, 0x05b8, - 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, 0x4186, - 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, - 0x3f43, 0x080c, 0x3d25, 0x0058, 0x080c, 0x3d25, 0x080c, 0x40aa, - 0x080c, 0x402a, 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, 0x2432, 0x2001, - 0x0227, 0x200c, 0x2102, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, - 0x00ae, 0x009e, 0x008e, 0x004e, 0x2001, 0x19a1, 0x2004, 0x9005, - 0x1118, 0x012e, 0x0804, 0x35ab, 0x012e, 0x2021, 0x400c, 0x0804, - 0x35ad, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, - 0x0096, 0x00d6, 0x0156, 0x7014, 0x2048, 0x7020, 0x20a8, 0x8000, - 0x7022, 0xa804, 0x9005, 0x0904, 0x3c95, 0x2048, 0x1f04, 0x3c49, - 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, - 0x4bd2, 0x701f, 0x3c39, 0x00b0, 0x8906, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, - 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0f8b, 0x000e, 0x080c, 0x4bd5, - 0x701f, 0x3c39, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, - 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x7014, 0x2048, 0xa864, - 0x9086, 0x0103, 0x1118, 0x701f, 0x3cfa, 0x0450, 0x7014, 0x2048, - 0xa868, 0xc0fd, 0xa86a, 0x2009, 0x007f, 0x080c, 0x66b2, 0x0110, - 0x9006, 0x0030, 0xb813, 0x00ff, 0xb817, 0xfffd, 0x080c, 0xd325, + 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, 0x0904, 0x35dd, 0x0016, 0x0026, 0x0036, 0x0046, - 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, 0x0156, 0x701f, 0x3ccc, - 0x7007, 0x0003, 0x0804, 0x3c8a, 0xa830, 0x9086, 0x0100, 0x2021, - 0x400c, 0x0904, 0x35ad, 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, 0x4bd5, 0x007e, 0x701f, 0x3c39, 0x7023, - 0x0001, 0x0005, 0x0804, 0x35ab, 0x0156, 0x00c6, 0xa814, 0x908a, - 0x001e, 0x0218, 0xa833, 0x001e, 0x0010, 0xa832, 0x0078, 0x81ff, - 0x0168, 0x0016, 0x080c, 0x4b89, 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, 0x19a1, 0x2003, - 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, - 0x19ac, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x19ab, 0x2004, - 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, 0x4b89, 0xa813, 0x0019, - 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, - 0x2001, 0x002f, 0x2004, 0xa86a, 0x2061, 0x0090, 0x2079, 0x0100, - 0x2001, 0x19ab, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x2432, - 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0x601a, 0xa873, - 0x0000, 0x601f, 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, 0x00ce, - 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x080c, 0x4b89, 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, 0x2c72, - 0x1130, 0x9006, 0x080c, 0x2bca, 0x9006, 0x080c, 0x2bad, 0x2001, - 0x19a0, 0x2003, 0x0000, 0x7884, 0x9084, 0x0007, 0x0002, 0x3dba, - 0x3dc3, 0x3dcc, 0x3db7, 0x3db7, 0x3db7, 0x3db7, 0x3db7, 0x012e, - 0x0804, 0x35e0, 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, - 0x080c, 0x3f8d, 0x00c0, 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, - 0x200a, 0x080c, 0x3f8d, 0x0078, 0x080c, 0x7569, 0x1128, 0x012e, - 0x2009, 0x0016, 0x0804, 0x35dd, 0x81ff, 0x0128, 0x012e, 0x2021, - 0x400b, 0x0804, 0x35ad, 0x2001, 0x0141, 0x2004, 0xd0dc, 0x0db0, - 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x080c, 0x3ae1, 0x2009, 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, - 0x9006, 0x2068, 0x2060, 0x2058, 0x080c, 0x4261, 0x080c, 0x41b1, - 0x903e, 0x2720, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, 0x1a6a, - 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, - 0x68d4, 0x780e, 0x68d0, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, - 0x4112, 0x080c, 0x2c7a, 0x080c, 0x2c7a, 0x080c, 0x2c7a, 0x080c, - 0x2c7a, 0x080c, 0x4112, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x4034, - 0x2009, 0x9c40, 0x8109, 0x11b0, 0x080c, 0x3f43, 0x2001, 0x0004, - 0x200c, 0x918c, 0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, - 0x35dd, 0x0cf8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, - 0x00f6, 0x2079, 0x0000, 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, - 0x0201, 0x200c, 0x81ff, 0x0150, 0x080c, 0x4012, 0x2d00, 0x9c05, - 0x9b05, 0x0120, 0x080c, 0x3f43, 0x0804, 0x3ef0, 0x080c, 0x4186, - 0x080c, 0x40aa, 0x080c, 0x3ff5, 0x080c, 0x402a, 0x00f6, 0x2079, - 0x0100, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x3f43, 0x00fe, - 0x0804, 0x3ef0, 0x00fe, 0x080c, 0x3f39, 0x1150, 0x8d68, 0x2001, - 0x0032, 0x2602, 0x2001, 0x0033, 0x2502, 0x080c, 0x3f43, 0x0080, - 0x87ff, 0x0138, 0x2001, 0x0201, 0x2004, 0x9005, 0x1908, 0x8739, - 0x0038, 0x2001, 0x1a66, 0x2004, 0x9086, 0x0000, 0x1904, 0x3e40, - 0x2001, 0x032f, 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, - 0x9605, 0x0904, 0x3ef0, 0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, - 0x9b05, 0x1904, 0x3ef0, 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, - 0x0004, 0x7884, 0xd0ac, 0x1148, 0x2001, 0x1a66, 0x2003, 0x0003, - 0x2001, 0x032a, 0x2003, 0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, - 0x9005, 0x0108, 0xa016, 0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, - 0x2432, 0x2900, 0xa85a, 0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, - 0xa817, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, - 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x3ec7, 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, 0x3dfa, - 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, - 0x2432, 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, 0x35ab, 0x012e, 0x2021, 0x400c, 0x0804, - 0x35ad, 0x9085, 0x0001, 0x1d04, 0x3f42, 0x2091, 0x6000, 0x8420, - 0x9486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, - 0x032a, 0x2003, 0x0004, 0x2001, 0x1a66, 0x2003, 0x0000, 0x0071, - 0x2009, 0x0048, 0x080c, 0x2432, 0x2001, 0x0227, 0x2024, 0x2402, - 0x2001, 0x0109, 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, - 0x2071, 0x1a6a, 0x7000, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, - 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, - 0x2009, 0x0040, 0x080c, 0x2432, 0x782c, 0xd0fc, 0x0d88, 0x080c, - 0x4186, 0x7000, 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, - 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2432, 0x782b, 0x0002, - 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, - 0x2001, 0x1818, 0x200c, 0x7932, 0x7936, 0x080c, 0x28dd, 0x7850, - 0x9084, 0xfbff, 0x9085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, - 0x1df0, 0x9084, 0xffcf, 0x9085, 0x2000, 0x7852, 0x20a9, 0x0046, - 0x1d04, 0x3fa8, 0x2091, 0x6000, 0x1f04, 0x3fa8, 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, 0x3fc8, 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, 0x2d52, 0x7827, 0x0020, 0x7843, 0x0000, 0x9006, 0x080c, - 0x2d52, 0x7827, 0x0048, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, - 0x00f6, 0x00e6, 0x2071, 0x1a66, 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, - 0x19ac, 0x2004, 0x70e2, 0x080c, 0x3d1b, 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, 0x4186, 0x00f6, 0x2071, 0x1a66, 0x2079, 0x0320, - 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, - 0x6898, 0x780a, 0x00de, 0x080c, 0x3d1b, 0x0140, 0x2001, 0x19a0, - 0x200c, 0x2003, 0x0001, 0x918e, 0x0001, 0x0120, 0x2009, 0x03e8, - 0x8109, 0x1df0, 0x792c, 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, - 0x0011, 0x080c, 0x4112, 0x2011, 0x0001, 0x080c, 0x4112, 0x00fe, - 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a66, 0x2079, 0x0320, - 0x792c, 0xd1fc, 0x0904, 0x410f, 0x782b, 0x0002, 0x9026, 0xd19c, - 0x1904, 0x410b, 0x7000, 0x0002, 0x410f, 0x40c0, 0x40f0, 0x410b, - 0xd1bc, 0x1170, 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, - 0x080c, 0x4112, 0x0904, 0x410f, 0x080c, 0x4112, 0x0804, 0x410f, - 0x00f6, 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, - 0x782b, 0x0004, 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, - 0x0de8, 0x080c, 0x4012, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, - 0x78b8, 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, - 0x8001, 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, - 0x40b4, 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, 0x4140, 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, - 0x417d, 0x4174, 0x416b, 0x4162, 0x4159, 0x4150, 0x4147, 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, 0x1a6a, 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, - 0x782b, 0x0002, 0x2940, 0x9026, 0x7000, 0x0002, 0x41ad, 0x4199, - 0x41a4, 0x8001, 0x7002, 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, - 0x4112, 0x190c, 0x4112, 0x0048, 0x8001, 0x7002, 0x782c, 0xd0fc, - 0x1d38, 0x2011, 0x0001, 0x080c, 0x4112, 0x008e, 0x00ee, 0x00fe, - 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, - 0x19ac, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x19ab, 0x2004, - 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, - 0x0520, 0x2038, 0x2001, 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, - 0x080c, 0x4b89, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, - 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, - 0x0096, 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, - 0x4229, 0x1d68, 0x2900, 0xa85a, 0x00d0, 0x080c, 0x4b89, 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, 0x19ab, 0x2004, 0x6036, 0x2009, - 0x0040, 0x080c, 0x2432, 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, 0x4b89, 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, 0x4b89, - 0x2940, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, - 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, - 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x4229, - 0x1d68, 0x2900, 0xa85a, 0x00d8, 0x080c, 0x4b89, 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, 0x1a66, - 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, 0x35ab, 0x7d98, 0x7c9c, 0x0804, 0x36af, - 0x080c, 0x7569, 0x190c, 0x60ec, 0x6040, 0x9084, 0x0020, 0x09b1, - 0x2069, 0x1847, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x2039, 0x0001, 0x080c, 0x4bd2, 0x701f, 0x4308, 0x0005, - 0x080c, 0x57e2, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, 0x20d8, - 0x21d0, 0x2069, 0x1847, 0x6800, 0x9005, 0x0904, 0x35e0, 0x6804, - 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x35e0, 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, 0x35e0, 0x9288, 0x33ac, 0x210d, 0x918c, 0x00ff, 0x6166, - 0xd0dc, 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, 0x35e0, 0x605e, - 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, 0x0006, - 0x2009, 0x19b3, 0x9080, 0x29d0, 0x2005, 0x200a, 0x000e, 0x2009, - 0x19b4, 0x9080, 0x29d4, 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, - 0x0a04, 0x35e0, 0x908a, 0x0841, 0x1a04, 0x35e0, 0x9084, 0x0007, - 0x1904, 0x35e0, 0x680c, 0x9005, 0x0904, 0x35e0, 0x6810, 0x9005, - 0x0904, 0x35e0, 0x6848, 0x6940, 0x910a, 0x1a04, 0x35e0, 0x8001, - 0x0904, 0x35e0, 0x684c, 0x6944, 0x910a, 0x1a04, 0x35e0, 0x8001, - 0x0904, 0x35e0, 0x2009, 0x1982, 0x200b, 0x0000, 0x2001, 0x1869, - 0x2004, 0xd0c4, 0x0140, 0x7884, 0x200a, 0x2008, 0x080c, 0x0e52, - 0x3b00, 0xc085, 0x20d8, 0x6814, 0x908c, 0x00ff, 0x614e, 0x8007, - 0x9084, 0x00ff, 0x6052, 0x080c, 0x787f, 0x080c, 0x6ac8, 0x080c, - 0x6b2a, 0x6808, 0x602a, 0x080c, 0x23a4, 0x2009, 0x0170, 0x200b, - 0x0080, 0xa001, 0xa001, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, - 0x2937, 0x003e, 0x6000, 0x9086, 0x0000, 0x1904, 0x44a4, 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, 0x19b5, 0x20e9, 0x0001, 0x4001, - 0x20a9, 0x0004, 0x20a1, 0x19cf, 0x20e9, 0x0001, 0x4001, 0x080c, - 0x882e, 0x00c6, 0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0510, - 0x0068, 0x2009, 0x0100, 0x210c, 0x918e, 0x0008, 0x1110, 0x839d, - 0x0010, 0x83f5, 0x3e18, 0x12b0, 0x3508, 0x8109, 0x080c, 0x7e3b, - 0x6878, 0x6016, 0x6874, 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, - 0x9184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, - 0x6003, 0x0001, 0x1f04, 0x43f9, 0x00ce, 0x00c6, 0x2061, 0x199d, - 0x6a88, 0x9284, 0xc000, 0x2010, 0x9286, 0x0000, 0x1158, 0x2063, - 0x0000, 0x2001, 0x0001, 0x080c, 0x2bca, 0x2001, 0x0001, 0x080c, - 0x2bad, 0x0088, 0x9286, 0x4000, 0x1148, 0x2063, 0x0001, 0x9006, - 0x080c, 0x2bca, 0x9006, 0x080c, 0x2bad, 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, 0x197d, 0x6a80, - 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, 0x0118, - 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x29ac, 0x2001, - 0x196e, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, - 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x7569, 0x0128, 0x080c, - 0x50c9, 0x0110, 0x080c, 0x28fd, 0x60d4, 0x9005, 0x01c0, 0x6003, - 0x0001, 0x2009, 0x448c, 0x00e0, 0x080c, 0x7569, 0x1168, 0x2011, - 0x73e4, 0x080c, 0x8709, 0x2011, 0x73d7, 0x080c, 0x87e3, 0x080c, - 0x7853, 0x080c, 0x7495, 0x0040, 0x080c, 0x5fe6, 0x0028, 0x6003, - 0x0004, 0x2009, 0x44a4, 0x0020, 0x080c, 0x69f4, 0x0804, 0x35ab, - 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, 0x1118, - 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d, 0x0817, 0x6000, 0x9086, - 0x0000, 0x0904, 0x35dd, 0x2069, 0x1847, 0x7890, 0x6842, 0x7894, - 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x2039, 0x0001, 0x0804, 0x4bd5, 0x9006, 0x080c, 0x28fd, 0x81ff, - 0x1904, 0x35dd, 0x080c, 0x7569, 0x11b0, 0x080c, 0x784e, 0x080c, - 0x6127, 0x080c, 0x33a0, 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, - 0xd561, 0x0130, 0x080c, 0x758c, 0x1118, 0x080c, 0x7541, 0x0038, - 0x080c, 0x7495, 0x0020, 0x080c, 0x60ec, 0x080c, 0x5fe6, 0x0804, - 0x35ab, 0x81ff, 0x1904, 0x35dd, 0x080c, 0x7569, 0x1110, 0x0804, - 0x35dd, 0x0126, 0x2091, 0x8000, 0x6194, 0x81ff, 0x0190, 0x704f, - 0x0000, 0x2001, 0x1c80, 0x2009, 0x0040, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x2039, 0x0001, 0x080c, 0x4bd5, 0x701f, 0x35a9, 0x012e, - 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, 0x1c80, 0x20a9, 0x0040, - 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x2019, 0xffff, 0x4304, 0x655c, - 0x9588, 0x33ac, 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, - 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, 0x671d, 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, 0x6077, 0x0804, 0x4501, 0x080c, 0x4bbc, - 0x0904, 0x35e0, 0x080c, 0x4b89, 0x1120, 0x2009, 0x0002, 0x0804, - 0x35dd, 0x080c, 0x57d3, 0xd0b4, 0x0558, 0x7884, 0x908e, 0x007e, - 0x0538, 0x908e, 0x007f, 0x0520, 0x908e, 0x0080, 0x0508, 0x080c, - 0x339b, 0x1148, 0xb800, 0xd08c, 0x11d8, 0xb804, 0x9084, 0x00ff, - 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0x080c, 0xd021, 0x1120, 0x2009, 0x0003, 0x0804, 0x35dd, 0x7007, - 0x0003, 0x701f, 0x458c, 0x0005, 0x080c, 0x4bbc, 0x0904, 0x35e0, - 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, 0x4bd5, 0x81ff, 0x1904, 0x35dd, 0x080c, 0x4ba0, 0x0904, - 0x35e0, 0x080c, 0x688f, 0x0904, 0x35dd, 0x0058, 0xa878, 0x9005, - 0x0120, 0x2009, 0x0004, 0x0804, 0x35dd, 0xa974, 0xaa94, 0x0804, - 0x35ab, 0x080c, 0x57db, 0x0904, 0x35ab, 0x701f, 0x45d6, 0x7007, - 0x0003, 0x0005, 0x81ff, 0x1904, 0x35dd, 0x7888, 0x908a, 0x1000, - 0x1a04, 0x35e0, 0x080c, 0x4bbc, 0x0904, 0x35e0, 0x080c, 0x6a92, - 0x0120, 0x080c, 0x6a9a, 0x1904, 0x35e0, 0x080c, 0x6914, 0x0904, - 0x35dd, 0x2019, 0x0004, 0x900e, 0x080c, 0x68a1, 0x0904, 0x35dd, - 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, 0x908a, 0x1000, 0x12f8, - 0x080c, 0x4bba, 0x01e0, 0x080c, 0x6a92, 0x0118, 0x080c, 0x6a9a, - 0x11b0, 0x080c, 0x6914, 0x2009, 0x0002, 0x0168, 0x2009, 0x0002, - 0x2019, 0x0004, 0x080c, 0x68a1, 0x2009, 0x0003, 0x0120, 0xa998, - 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, - 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, - 0x4000, 0x080c, 0x57db, 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, 0x671d, - 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x8717, - 0x0005, 0x81ff, 0x1904, 0x35dd, 0x798c, 0x2001, 0x1981, 0x918c, - 0x8000, 0x2102, 0x080c, 0x4ba0, 0x0904, 0x35e0, 0x080c, 0x6a92, - 0x0120, 0x080c, 0x6a9a, 0x1904, 0x35e0, 0x080c, 0x67e4, 0x0904, - 0x35dd, 0x080c, 0x6898, 0x0904, 0x35dd, 0x2001, 0x1981, 0x2004, - 0xd0fc, 0x1904, 0x35ab, 0x0804, 0x45e1, 0xa9a0, 0x2001, 0x1981, - 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4bad, 0x01a0, 0x080c, - 0x6a92, 0x0118, 0x080c, 0x6a9a, 0x1170, 0x080c, 0x67e4, 0x2009, - 0x0002, 0x0128, 0x080c, 0x6898, 0x1170, 0x2009, 0x0003, 0xa897, - 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x1981, 0x2004, - 0xd0fc, 0x1128, 0x080c, 0x57db, 0x0110, 0x9006, 0x0018, 0x900e, - 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904, 0x35dd, - 0x798c, 0x2001, 0x1980, 0x918c, 0x8000, 0x2102, 0x080c, 0x4ba0, - 0x0904, 0x35e0, 0x080c, 0x6a92, 0x0120, 0x080c, 0x6a9a, 0x1904, - 0x35e0, 0x080c, 0x67e4, 0x0904, 0x35dd, 0x080c, 0x6886, 0x0904, - 0x35dd, 0x2001, 0x1980, 0x2004, 0xd0fc, 0x1904, 0x35ab, 0x0804, - 0x45e1, 0xa9a0, 0x2001, 0x1980, 0x918c, 0x8000, 0xc18d, 0x2102, - 0x080c, 0x4bad, 0x01a0, 0x080c, 0x6a92, 0x0118, 0x080c, 0x6a9a, - 0x1170, 0x080c, 0x67e4, 0x2009, 0x0002, 0x0128, 0x080c, 0x6886, - 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, - 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, - 0x4000, 0x2001, 0x1980, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x57db, - 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, - 0x0005, 0x6100, 0x0804, 0x35ab, 0x080c, 0x4bbc, 0x0904, 0x35e0, - 0x080c, 0x57e7, 0x1904, 0x35dd, 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, - 0x35ab, 0x78a8, 0x909c, 0x0003, 0xd0ac, 0x1158, 0xd0b4, 0x1148, - 0x939a, 0x0003, 0x1a04, 0x35dd, 0x625c, 0x7884, 0x9206, 0x1904, - 0x479c, 0x080c, 0x8818, 0x2001, 0xffec, 0x2009, 0x000c, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0000, 0x0006, 0x78a8, 0x9084, - 0x0080, 0x1528, 0x0006, 0x0036, 0x2001, 0x1a84, 0x201c, 0x7b9a, - 0x2003, 0x0000, 0x2001, 0x1a85, 0x201c, 0x7b9e, 0x2003, 0x0000, - 0x2001, 0x1a86, 0x201c, 0x7bae, 0x2003, 0x0000, 0x2001, 0x1a80, - 0x201c, 0x7baa, 0x2003, 0x0000, 0x2001, 0x1a87, 0x201c, 0x7bb2, - 0x2003, 0x0000, 0x003e, 0x000e, 0x000e, 0x0804, 0x4bd5, 0x000e, - 0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, - 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10f8, 0x7007, - 0x0002, 0x701f, 0x47bc, 0x0005, 0x81ff, 0x1904, 0x35dd, 0x080c, - 0x4bbc, 0x0904, 0x35e0, 0x080c, 0x6a92, 0x1904, 0x35dd, 0x00c6, - 0x080c, 0x4b89, 0x00ce, 0x0904, 0x35dd, 0xa867, 0x0000, 0xa868, - 0xc0fd, 0xa86a, 0x7ea8, 0x080c, 0xcfc7, 0x0904, 0x35dd, 0x7007, - 0x0003, 0x701f, 0x47e2, 0x0005, 0x080c, 0x42ce, 0x0006, 0x0036, - 0x2001, 0x1a84, 0x201c, 0x7b9a, 0x2003, 0x0000, 0x2001, 0x1a85, - 0x201c, 0x7b9e, 0x2003, 0x0000, 0x2001, 0x1a86, 0x201c, 0x7bae, - 0x2003, 0x0000, 0x2001, 0x1a80, 0x201c, 0x7baa, 0x2003, 0x0000, - 0x2001, 0x1a87, 0x201c, 0x7bb2, 0x2003, 0x0000, 0x003e, 0x000e, - 0x0804, 0x35ab, 0xa830, 0x9086, 0x0100, 0x0904, 0x35dd, 0x8906, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, - 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4bd5, - 0x9006, 0x080c, 0x28fd, 0x78a8, 0x9084, 0x00ff, 0x9086, 0x00ff, - 0x0118, 0x81ff, 0x1904, 0x35dd, 0x080c, 0x7569, 0x0110, 0x080c, - 0x60ec, 0x7888, 0x908a, 0x1000, 0x1a04, 0x35e0, 0x7984, 0x9186, - 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04, 0x35e0, 0x2100, 0x080c, - 0x28c7, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0x19fc, - 0x601b, 0x0000, 0x601f, 0x0000, 0x607b, 0x0000, 0x607f, 0x0000, - 0x080c, 0x7569, 0x1158, 0x080c, 0x784e, 0x080c, 0x6127, 0x9085, - 0x0001, 0x080c, 0x75ad, 0x080c, 0x7495, 0x00d0, 0x080c, 0xb072, - 0x2061, 0x0100, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x810f, - 0x9105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x199a, - 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x6012, 0x080c, 0x87a1, - 0x7984, 0x080c, 0x7569, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, - 0x4644, 0x012e, 0x00ce, 0x002e, 0x0804, 0x35ab, 0x7984, 0x080c, - 0x66b2, 0x2b08, 0x1904, 0x35e0, 0x0804, 0x35ab, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x35dd, 0x60dc, 0xd0ac, 0x1130, 0xd09c, - 0x1120, 0x2009, 0x0005, 0x0804, 0x35dd, 0x080c, 0x4b89, 0x1120, - 0x2009, 0x0002, 0x0804, 0x35dd, 0x7984, 0x81ff, 0x0904, 0x35e0, - 0x9192, 0x0021, 0x1a04, 0x35e0, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0xa85c, 0x9080, 0x0019, 0x702a, 0xaf60, 0x7736, 0x080c, 0x4bd2, - 0x701f, 0x4899, 0x7880, 0x9086, 0x006e, 0x0110, 0x701f, 0x527b, - 0x0005, 0x2009, 0x0080, 0x080c, 0x671d, 0x1118, 0x080c, 0x6a92, - 0x0120, 0x2021, 0x400a, 0x0804, 0x35ad, 0x00d6, 0x0096, 0xa964, - 0xaa6c, 0xab70, 0xac74, 0xad78, 0xae7c, 0xa884, 0x90be, 0x0100, - 0x0904, 0x4932, 0x90be, 0x0112, 0x0904, 0x4932, 0x90be, 0x0113, - 0x0904, 0x4932, 0x90be, 0x0114, 0x0904, 0x4932, 0x90be, 0x0117, - 0x0904, 0x4932, 0x90be, 0x011a, 0x0904, 0x4932, 0x90be, 0x011c, - 0x0904, 0x4932, 0x90be, 0x0121, 0x0904, 0x4919, 0x90be, 0x0131, - 0x0904, 0x4919, 0x90be, 0x0171, 0x0904, 0x4932, 0x90be, 0x0173, - 0x0904, 0x4932, 0x90be, 0x01a1, 0x1128, 0xa894, 0x8007, 0xa896, - 0x0804, 0x493d, 0x90be, 0x0212, 0x0904, 0x4926, 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, 0x35e0, - 0x7028, 0x9080, 0x0010, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, - 0x20a9, 0x0007, 0x080c, 0x497b, 0x7028, 0x9080, 0x000e, 0x2098, - 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x497b, - 0x00c8, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, - 0x20e8, 0x20a9, 0x0001, 0x080c, 0x4988, 0x00b8, 0x7028, 0x9080, - 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, - 0x080c, 0x4988, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, - 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x04f1, 0x00c6, 0x080c, 0x4b89, - 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, - 0xcfe2, 0x1120, 0x2009, 0x0003, 0x0804, 0x35dd, 0x7007, 0x0003, - 0x701f, 0x4972, 0x0005, 0x00ce, 0x009e, 0x00de, 0x2009, 0x0002, - 0x0804, 0x35dd, 0xa820, 0x9086, 0x8001, 0x1904, 0x35ab, 0x2009, - 0x0004, 0x0804, 0x35dd, 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, - 0x35dd, 0x60dc, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, - 0x0804, 0x35dd, 0x7984, 0x78a8, 0x2040, 0x080c, 0xb06b, 0x1120, - 0x9182, 0x007f, 0x0a04, 0x35e0, 0x9186, 0x00ff, 0x0904, 0x35e0, - 0x9182, 0x0800, 0x1a04, 0x35e0, 0x7a8c, 0x7b88, 0x607c, 0x9306, - 0x1158, 0x6080, 0x924e, 0x0904, 0x35e0, 0x080c, 0xb06b, 0x1120, - 0x99cc, 0xff00, 0x0904, 0x35e0, 0x0126, 0x2091, 0x8000, 0x080c, - 0x4a9c, 0x0904, 0x4a1c, 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, 0x6a92, - 0x0110, 0xc89d, 0x0438, 0x900e, 0x080c, 0x693d, 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, 0x35ad, 0x000e, 0x00ce, 0x2b00, 0x7026, 0x0016, 0x00b6, - 0x00c6, 0x00e6, 0x2c70, 0x080c, 0xb153, 0x0904, 0x4a71, 0x2b00, - 0x6012, 0x080c, 0xd2d2, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, - 0x4b89, 0x00ce, 0x2b70, 0x1158, 0x080c, 0xb101, 0x00ee, 0x00ce, - 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, 0x0804, 0x35dd, 0x900e, - 0xa966, 0xa96a, 0x2900, 0x6016, 0xa932, 0xa868, 0xc0fd, 0xd88c, - 0x0108, 0xc0f5, 0xa86a, 0xd89c, 0x1110, 0x080c, 0x3246, 0x6023, - 0x0001, 0x9006, 0x080c, 0x664f, 0xd89c, 0x0138, 0x2001, 0x0004, - 0x080c, 0x6663, 0x2009, 0x0003, 0x0030, 0x2001, 0x0002, 0x080c, - 0x6663, 0x2009, 0x0002, 0x080c, 0xb180, 0x78a8, 0xd094, 0x0138, - 0x00ee, 0x7024, 0x00e6, 0x2058, 0xb8cc, 0xc08d, 0xb8ce, 0x9085, - 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, - 0x0003, 0x0804, 0x35dd, 0x7007, 0x0003, 0x701f, 0x4a80, 0x0005, - 0xa830, 0x9086, 0x0100, 0x7024, 0x2058, 0x1138, 0x2009, 0x0004, - 0xba04, 0x9294, 0x00ff, 0x0804, 0x5727, 0x900e, 0xa868, 0xd0f4, - 0x1904, 0x35ab, 0x080c, 0x693d, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0x0804, 0x35ab, 0x00e6, 0x00d6, 0x0096, 0x83ff, - 0x0904, 0x4aeb, 0x902e, 0x080c, 0xb06b, 0x0130, 0x9026, 0x20a9, - 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x007f, 0x20a9, 0x0781, - 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b8, 0x2100, 0x9406, 0x1904, - 0x4afc, 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, 0x6a32, 0x1570, 0x2001, - 0x4000, 0x0460, 0x080c, 0x6a92, 0x1540, 0x2001, 0x4000, 0x0430, - 0x2001, 0x4007, 0x0418, 0x2001, 0x4006, 0x0400, 0x2400, 0x9106, - 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, 0x0918, 0x080c, 0xb06b, - 0x1900, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x4ab2, - 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, - 0x080c, 0x66b2, 0x1dd0, 0xbb12, 0xba16, 0x9006, 0x9005, 0x009e, - 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x35dd, 0x080c, 0x4b89, 0x1120, 0x2009, 0x0002, 0x0804, 0x35dd, - 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7884, 0x9005, 0x0904, - 0x35e0, 0x9096, 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, 0x35e0, - 0x2010, 0x2918, 0x080c, 0x31ec, 0x1120, 0x2009, 0x0003, 0x0804, - 0x35dd, 0x7007, 0x0003, 0x701f, 0x4b3e, 0x0005, 0xa830, 0x9086, - 0x0100, 0x1904, 0x35ab, 0x2009, 0x0004, 0x0804, 0x35dd, 0x7984, - 0x080c, 0xb06b, 0x1120, 0x9182, 0x007f, 0x0a04, 0x35e0, 0x9186, - 0x00ff, 0x0904, 0x35e0, 0x9182, 0x0800, 0x1a04, 0x35e0, 0x2001, - 0x9400, 0x080c, 0x5782, 0x1904, 0x35dd, 0x0804, 0x35ab, 0xa998, - 0x080c, 0xb06b, 0x1118, 0x9182, 0x007f, 0x0280, 0x9186, 0x00ff, - 0x0168, 0x9182, 0x0800, 0x1250, 0x2001, 0x9400, 0x080c, 0x5782, - 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, + 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, - 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, 0x671d, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xa998, 0x080c, 0x671d, - 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, - 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, 0x2608, 0x080c, 0x671d, - 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, 0x35ab, - 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, - 0x18b0, 0x2004, 0x9005, 0x1190, 0x0e04, 0x4c06, 0x7a36, 0x7833, - 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x11aa, 0x0804, 0x4c6c, 0x0016, 0x0086, - 0x0096, 0x00c6, 0x00e6, 0x2071, 0x189e, 0x7044, 0x9005, 0x1540, - 0x7148, 0x9182, 0x0010, 0x0288, 0x7038, 0x2060, 0x080c, 0x100e, - 0x0904, 0x4c64, 0xa84b, 0x0000, 0x2900, 0x7046, 0x2001, 0x0002, - 0x9080, 0x20f0, 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, - 0x20f0, 0x2005, 0xa846, 0x0058, 0x2262, 0x6306, 0x640a, 0x00ee, - 0x00ce, 0x009e, 0x008e, 0x001e, 0x012e, 0x00fe, 0x0005, 0x2c00, - 0x9082, 0x001b, 0x0002, 0x4c8e, 0x4c8e, 0x4c90, 0x4c8e, 0x4c8e, - 0x4c8e, 0x4c94, 0x4c8e, 0x4c8e, 0x4c8e, 0x4c98, 0x4c8e, 0x4c8e, - 0x4c8e, 0x4c9c, 0x4c8e, 0x4c8e, 0x4c8e, 0x4ca0, 0x4c8e, 0x4c8e, - 0x4c8e, 0x4ca4, 0x4c8e, 0x4c8e, 0x4c8e, 0x4ca9, 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, - 0x4c67, 0xa2d6, 0xa3da, 0xa4de, 0x0804, 0x4c67, 0x00e6, 0x2071, - 0x189e, 0x7048, 0x9005, 0x0904, 0x4d40, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x4d3f, 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, 0x4d42, 0xa804, 0x9005, - 0x090c, 0x0dc5, 0x7042, 0x2938, 0x2040, 0xa003, 0x0000, 0x2001, - 0x0002, 0x9080, 0x20f0, 0x2005, 0xa04a, 0x0804, 0x4d42, 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, 0x20f0, 0x2005, - 0xa84a, 0x0000, 0x007e, 0x008e, 0x009e, 0x00ce, 0x00fe, 0x012e, - 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4d61, 0x4d61, - 0x4d63, 0x4d61, 0x4d61, 0x4d61, 0x4d68, 0x4d61, 0x4d61, 0x4d61, - 0x4d6d, 0x4d61, 0x4d61, 0x4d61, 0x4d72, 0x4d61, 0x4d61, 0x4d61, - 0x4d77, 0x4d61, 0x4d61, 0x4d61, 0x4d7c, 0x4d61, 0x4d61, 0x4d61, - 0x4d81, 0x080c, 0x0dc5, 0xaa74, 0xab78, 0xac7c, 0x0804, 0x4ced, - 0xaa84, 0xab88, 0xac8c, 0x0804, 0x4ced, 0xaa94, 0xab98, 0xac9c, - 0x0804, 0x4ced, 0xaaa4, 0xaba8, 0xacac, 0x0804, 0x4ced, 0xaab4, - 0xabb8, 0xacbc, 0x0804, 0x4ced, 0xaac4, 0xabc8, 0xaccc, 0x0804, - 0x4ced, 0xaad4, 0xabd8, 0xacdc, 0x0804, 0x4ced, 0x0016, 0x0026, - 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, 0x080c, 0x671d, 0x2019, - 0x0001, 0xb85c, 0xd0ac, 0x0110, 0x2019, 0x0000, 0x2011, 0x801b, - 0x080c, 0x4be9, 0x00ce, 0x00be, 0x003e, 0x002e, 0x001e, 0x0005, - 0x0026, 0x080c, 0x57d3, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, - 0x4be9, 0x002e, 0x0005, 0x81ff, 0x1904, 0x35dd, 0x0126, 0x2091, - 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x7569, - 0x1158, 0x080c, 0x784e, 0x080c, 0x6127, 0x9085, 0x0001, 0x080c, - 0x75ad, 0x080c, 0x7495, 0x0010, 0x080c, 0x5fe6, 0x012e, 0x0804, - 0x35ab, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35dd, 0x080c, - 0x57e7, 0x0120, 0x2009, 0x0007, 0x0804, 0x35dd, 0x080c, 0x6a8a, - 0x0120, 0x2009, 0x0008, 0x0804, 0x35dd, 0x7984, 0x080c, 0x66b2, - 0x1904, 0x35e0, 0x080c, 0x4bbc, 0x0904, 0x35e0, 0x2b00, 0x7026, - 0x080c, 0x6a92, 0x7888, 0x1170, 0x9084, 0x0005, 0x1158, 0x900e, - 0x080c, 0x693d, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, - 0x0804, 0x35ab, 0x080c, 0x4b89, 0x0904, 0x35dd, 0x9006, 0xa866, - 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd080, 0x0904, 0x35dd, - 0x7888, 0xd094, 0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x7007, 0x0003, - 0x701f, 0x4e5c, 0x0005, 0x2061, 0x1800, 0x080c, 0x57e7, 0x2009, - 0x0007, 0x1560, 0x080c, 0x6a8a, 0x0118, 0x2009, 0x0008, 0x0430, - 0xa998, 0x080c, 0x66b2, 0x1530, 0x080c, 0x4bba, 0x0518, 0x080c, - 0x6a92, 0xa89c, 0x1168, 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, - 0x693d, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x00d0, - 0xa868, 0xc0fc, 0xa86a, 0x080c, 0xd080, 0x11e0, 0xa89c, 0xd094, - 0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x2009, 0x0003, 0xa897, 0x4005, + 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, 0xa99a, 0x9006, 0x918d, 0x0001, - 0x2008, 0x0005, 0x9006, 0x0005, 0xa830, 0x9086, 0x0100, 0x7024, - 0x2058, 0x1110, 0x0804, 0x5727, 0x900e, 0x080c, 0x693d, 0x1108, - 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x35ab, 0x080c, - 0x57e7, 0x0120, 0x2009, 0x0007, 0x0804, 0x35dd, 0x7f84, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4b89, 0x1120, 0x2009, 0x0002, - 0x0804, 0x35dd, 0x900e, 0x2130, 0x7126, 0x7132, 0xa860, 0x20e8, - 0x7036, 0xa85c, 0x9080, 0x0005, 0x702a, 0x20a0, 0x080c, 0x671d, - 0x1904, 0x4f05, 0x080c, 0x6a92, 0x0138, 0x080c, 0x6a9a, 0x0120, - 0x080c, 0x6a32, 0x1904, 0x4f05, 0xd794, 0x1110, 0xd784, 0x01a8, - 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x3400, 0xd794, - 0x0198, 0x20a9, 0x0008, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, - 0x20a9, 0x0002, 0x080c, 0x4988, 0x0080, 0xb8c4, 0x20e0, 0xb8c8, - 0x9080, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003, 0x2098, - 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x4988, 0x9186, 0x007e, 0x0170, - 0x9186, 0x0080, 0x0158, 0x080c, 0x6a92, 0x90c2, 0x0006, 0x1210, - 0xc1fd, 0x0020, 0x080c, 0x693d, 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, 0x497b, 0x9c80, - 0x0026, 0x2098, 0xb8c4, 0x20e0, 0x20a9, 0x0002, 0x4003, 0xd794, - 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, 0x080c, 0xb06b, - 0x0118, 0x9186, 0x0800, 0x0040, 0xd78c, 0x0120, 0x9186, 0x0800, - 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, 0x9686, - 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x4e8e, 0x86ff, - 0x1120, 0x7124, 0x810b, 0x0804, 0x35ab, 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, 0x4f41, - 0x0005, 0x7030, 0x9005, 0x1180, 0x7120, 0x7028, 0x20a0, 0x772c, - 0x9036, 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, 0xa28c, 0xa390, - 0xa494, 0xa598, 0x0804, 0x4e8e, 0x7124, 0x810b, 0x0804, 0x35ab, - 0x2029, 0x007e, 0x7984, 0x7a88, 0x7b8c, 0x7c98, 0x9184, 0xff00, - 0x8007, 0x90e2, 0x0020, 0x0a04, 0x35e0, 0x9502, 0x0a04, 0x35e0, - 0x9184, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x35e0, 0x9502, 0x0a04, - 0x35e0, 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x35e0, - 0x9502, 0x0a04, 0x35e0, 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, - 0x35e0, 0x9502, 0x0a04, 0x35e0, 0x9384, 0xff00, 0x8007, 0x90e2, - 0x0020, 0x0a04, 0x35e0, 0x9502, 0x0a04, 0x35e0, 0x9384, 0x00ff, - 0x90e2, 0x0020, 0x0a04, 0x35e0, 0x9502, 0x0a04, 0x35e0, 0x9484, - 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x35e0, 0x9502, 0x0a04, - 0x35e0, 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x35e0, 0x9502, - 0x0a04, 0x35e0, 0x2061, 0x198a, 0x6102, 0x6206, 0x630a, 0x640e, - 0x0804, 0x35ab, 0x080c, 0x4b89, 0x0904, 0x35dd, 0x2009, 0x0016, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, - 0x080c, 0x4bd2, 0x701f, 0x4fc5, 0x0005, 0x2001, 0x0138, 0x2003, - 0x0000, 0x00e6, 0x2071, 0x0300, 0x701c, 0xd0a4, 0x1de8, 0x00ee, - 0x20a9, 0x0016, 0x896e, 0x8d6e, 0x8d6f, 0x9d84, 0xffc0, 0x9080, - 0x0019, 0x2098, 0x9d84, 0x003f, 0x20e0, 0x2069, 0x1877, 0x20e9, - 0x0001, 0x2da0, 0x4003, 0x6800, 0x9005, 0x0904, 0x5046, 0x6804, - 0x2008, 0x918c, 0xfff8, 0x1904, 0x5046, 0x680c, 0x9005, 0x0904, - 0x5046, 0x9082, 0xff01, 0x1a04, 0x5046, 0x6810, 0x9082, 0x005c, - 0x0a04, 0x5046, 0x6824, 0x2008, 0x9082, 0x0008, 0x0a04, 0x5046, - 0x9182, 0x0400, 0x1a04, 0x5046, 0x0056, 0x2029, 0x0000, 0x080c, - 0x8d49, 0x005e, 0x6944, 0x6820, 0x9102, 0x06c0, 0x6820, 0x9082, - 0x0019, 0x16a0, 0x6828, 0x6944, 0x810c, 0x9102, 0x0678, 0x6840, - 0x9082, 0x000f, 0x1658, 0x080c, 0x1027, 0x2900, 0x0904, 0x5062, - 0x684e, 0x00e6, 0x2071, 0x1932, 0x00b6, 0x2059, 0x0000, 0x080c, - 0x8c05, 0x00be, 0x00ee, 0x0568, 0x080c, 0x8950, 0x080c, 0x899f, - 0x11e0, 0x6857, 0x0000, 0x00c6, 0x2061, 0x0100, 0x6104, 0x918d, - 0x2000, 0x6106, 0x6b10, 0x2061, 0x1a66, 0x630a, 0x00ce, 0x080c, - 0x29ac, 0x2001, 0x0138, 0x2102, 0x0804, 0x35ab, 0x080c, 0x29ac, - 0x2001, 0x0138, 0x2102, 0x0804, 0x35e0, 0x080c, 0x8998, 0x00e6, - 0x2071, 0x1932, 0x080c, 0x8dc9, 0x080c, 0x8dd8, 0x080c, 0x8be8, - 0x00ee, 0x2001, 0x188a, 0x204c, 0x080c, 0x1040, 0x2001, 0x188a, - 0x2003, 0x0000, 0x080c, 0x29ac, 0x2001, 0x0138, 0x2102, 0x0804, - 0x35dd, 0x2001, 0x1926, 0x200c, 0x918e, 0x0000, 0x0904, 0x50c7, - 0x080c, 0x8be3, 0x0904, 0x50c7, 0x2001, 0x0101, 0x200c, 0x918c, - 0xdfff, 0x2102, 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, 0x2071, - 0x0300, 0x701c, 0xd0a4, 0x1de8, 0x00ee, 0x080c, 0x8be8, 0x0126, - 0x2091, 0x8000, 0x2001, 0x0035, 0x080c, 0x1611, 0x012e, 0x00c6, - 0x2061, 0x193e, 0x6004, 0x6100, 0x9106, 0x1de0, 0x00ce, 0x080c, - 0x29ac, 0x2001, 0x0138, 0x2102, 0x00e6, 0x00f6, 0x2071, 0x1925, - 0x080c, 0x8b22, 0x0120, 0x2f00, 0x080c, 0x8bae, 0x0cc8, 0x00fe, - 0x00ee, 0x0126, 0x2091, 0x8000, 0x2001, 0x188a, 0x200c, 0x81ff, - 0x0138, 0x2148, 0x080c, 0x1040, 0x2001, 0x188a, 0x2003, 0x0000, - 0x2001, 0x183d, 0x2003, 0x0020, 0x080c, 0x8998, 0x00e6, 0x2071, - 0x1932, 0x080c, 0x8dc9, 0x080c, 0x8dd8, 0x00ee, 0x012e, 0x0804, - 0x35ab, 0x0006, 0x080c, 0x57d3, 0xd0cc, 0x000e, 0x0005, 0x0006, - 0x080c, 0x57d7, 0xd0bc, 0x000e, 0x0005, 0x6174, 0x7a84, 0x6300, - 0x82ff, 0x1118, 0x7986, 0x0804, 0x35ab, 0x83ff, 0x1904, 0x35e0, - 0x2001, 0xfff0, 0x9200, 0x1a04, 0x35e0, 0x2019, 0xffff, 0x6078, - 0x9302, 0x9200, 0x0a04, 0x35e0, 0x7986, 0x6276, 0x0804, 0x35ab, - 0x080c, 0x57e7, 0x1904, 0x35dd, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, - 0x080c, 0x4b89, 0x0904, 0x35dd, 0x900e, 0x901e, 0x7326, 0x7332, - 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0003, 0x702a, 0x20a0, - 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6a92, 0x0118, - 0x080c, 0x6a9a, 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, 0x91b1, 0x2208, 0x0804, 0x35ab, 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, - 0x514a, 0x0005, 0x7030, 0x9005, 0x1178, 0x7120, 0x7028, 0x20a0, - 0x901e, 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, 0xa48c, 0xa590, - 0xa694, 0xa798, 0x0804, 0x5108, 0x7224, 0x900e, 0x2001, 0x0003, - 0x080c, 0x91b1, 0x2208, 0x0804, 0x35ab, 0x00f6, 0x00e6, 0x080c, - 0x57e7, 0x2009, 0x0007, 0x1904, 0x51dd, 0x2071, 0x189e, 0x745c, - 0x84ff, 0x2009, 0x000e, 0x1904, 0x51dd, 0xac9c, 0xad98, 0xaea4, - 0xafa0, 0x0096, 0x080c, 0x1027, 0x2009, 0x0002, 0x0904, 0x51dd, - 0x2900, 0x705e, 0x900e, 0x901e, 0x7356, 0x7362, 0xa860, 0x7066, - 0xa85c, 0x9080, 0x0003, 0x705a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, - 0x8bff, 0x0178, 0x080c, 0x6a92, 0x0118, 0x080c, 0x6a9a, 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, - 0x91b1, 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, 0x51e9, 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, 0x91b1, 0xaa9a, 0x715c, - 0x81ff, 0x090c, 0x0dc5, 0x2148, 0x080c, 0x1040, 0x705f, 0x0000, - 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x6dd1, 0x012e, - 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91d8, - 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6a92, 0x0118, 0x080c, - 0x6a9a, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, + 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, 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, 0x6dd1, 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, - 0x35e0, 0xa884, 0xa988, 0x080c, 0x2894, 0x1518, 0x080c, 0x66b2, - 0x1500, 0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c, 0x4b89, 0x01c8, - 0x080c, 0x4b89, 0x01b0, 0x009e, 0xa867, 0x0000, 0xa868, 0xc0fd, - 0xa86a, 0xa823, 0x0000, 0xa804, 0x2048, 0x080c, 0xd002, 0x1120, - 0x2009, 0x0003, 0x0804, 0x35dd, 0x7007, 0x0003, 0x701f, 0x52b6, - 0x0005, 0x009e, 0x2009, 0x0002, 0x0804, 0x35dd, 0x7124, 0x080c, - 0x3342, 0xa820, 0x9086, 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, - 0x35dd, 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, 0x4bd5, 0x97c6, 0x7200, 0x11b8, 0x96c2, - 0x0054, 0x02a0, 0x000e, 0x007e, 0x2061, 0x18b8, 0x2c44, 0xa076, - 0xa772, 0xa07b, 0x002a, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, - 0x10f8, 0x7007, 0x0002, 0x701f, 0x5312, 0x0005, 0x000e, 0x007e, - 0x0804, 0x35e0, 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, 0x4bd5, 0x81ff, 0x1904, - 0x35dd, 0x798c, 0x2001, 0x197f, 0x918c, 0x8000, 0x2102, 0x080c, - 0x4ba0, 0x0904, 0x35e0, 0x080c, 0x6a92, 0x0120, 0x080c, 0x6a9a, - 0x1904, 0x35e0, 0x080c, 0x67e4, 0x0904, 0x35dd, 0x0126, 0x2091, - 0x8000, 0x080c, 0x68aa, 0x012e, 0x0904, 0x35dd, 0x2001, 0x197f, - 0x2004, 0xd0fc, 0x1904, 0x35ab, 0x0804, 0x45e1, 0xa9a0, 0x2001, - 0x197f, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4bad, 0x01a0, - 0x080c, 0x6a92, 0x0118, 0x080c, 0x6a9a, 0x1170, 0x080c, 0x67e4, - 0x2009, 0x0002, 0x0128, 0x080c, 0x68aa, 0x1170, 0x2009, 0x0003, + 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, 0x0005, 0xa897, 0x4000, 0x2001, 0x197f, - 0x2004, 0xd0fc, 0x1128, 0x080c, 0x57db, 0x0110, 0x9006, 0x0018, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x78a8, 0xd08c, - 0x1118, 0xd084, 0x0904, 0x4556, 0x080c, 0x4bbc, 0x0904, 0x35e0, - 0x080c, 0x4b89, 0x1120, 0x2009, 0x0002, 0x0804, 0x35dd, 0x080c, - 0x6a92, 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, 0x0005, 0x15a0, - 0x78a8, 0xd08c, 0x0120, 0xb800, 0xc08c, 0xb802, 0x0028, 0x080c, - 0x57d3, 0xd0b4, 0x0904, 0x4590, 0x7884, 0x908e, 0x007e, 0x0904, - 0x4590, 0x908e, 0x007f, 0x0904, 0x4590, 0x908e, 0x0080, 0x0904, - 0x4590, 0xb800, 0xd08c, 0x1904, 0x4590, 0xa867, 0x0000, 0xa868, - 0xc0fd, 0xa86a, 0x080c, 0xd021, 0x1120, 0x2009, 0x0003, 0x0804, - 0x35dd, 0x7007, 0x0003, 0x701f, 0x53de, 0x0005, 0x080c, 0x4bbc, - 0x0904, 0x35e0, 0x0804, 0x4590, 0x080c, 0x339b, 0x0108, 0x0005, - 0x2009, 0x1834, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x35dd, 0x080c, 0x57e7, 0x0120, 0x2009, 0x0007, 0x0804, 0x35dd, - 0x080c, 0x6a8a, 0x0120, 0x2009, 0x0008, 0x0804, 0x35dd, 0xb89c, - 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x4590, 0x9006, 0xa866, 0xa832, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd080, 0x1120, 0x2009, 0x0003, - 0x0804, 0x35dd, 0x7007, 0x0003, 0x701f, 0x5417, 0x0005, 0xa830, - 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x5727, 0x080c, - 0x4bbc, 0x0904, 0x35e0, 0x0804, 0x53b0, 0x81ff, 0x2009, 0x0001, - 0x1904, 0x35dd, 0x080c, 0x57e7, 0x2009, 0x0007, 0x1904, 0x35dd, - 0x080c, 0x6a8a, 0x0120, 0x2009, 0x0008, 0x0804, 0x35dd, 0x080c, - 0x4bbc, 0x0904, 0x35e0, 0x080c, 0x6a92, 0x2009, 0x0009, 0x1904, - 0x35dd, 0x080c, 0x4b89, 0x2009, 0x0002, 0x0904, 0x35dd, 0x9006, - 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x7988, 0xa95a, 0x9194, - 0xfd00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, 0xc0ed, 0xa952, - 0x798c, 0xa956, 0x0038, 0x928e, 0x0100, 0x1904, 0x35e0, 0xc0e5, - 0xa952, 0xa956, 0xa83e, 0x080c, 0xd2d3, 0x2009, 0x0003, 0x0904, - 0x35dd, 0x7007, 0x0003, 0x701f, 0x546e, 0x0005, 0xa830, 0x9086, - 0x0100, 0x2009, 0x0004, 0x0904, 0x35dd, 0x0804, 0x35ab, 0x7aa8, - 0x9284, 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, 0x57e7, 0x1188, - 0x2009, 0x0014, 0x0804, 0x35dd, 0xd2dc, 0x1578, 0x81ff, 0x2009, - 0x0001, 0x1904, 0x35dd, 0x080c, 0x57e7, 0x2009, 0x0007, 0x1904, - 0x35dd, 0xd2f4, 0x0138, 0x9284, 0x5000, 0xc0d5, 0x080c, 0x57ad, - 0x0804, 0x35ab, 0xd2fc, 0x0160, 0x080c, 0x4bbc, 0x0904, 0x35e0, - 0x7984, 0x9284, 0x9000, 0xc0d5, 0x080c, 0x5782, 0x0804, 0x35ab, - 0x080c, 0x4bbc, 0x0904, 0x35e0, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x2009, 0x0009, 0x1904, 0x555d, 0x080c, 0x4b89, 0x2009, - 0x0002, 0x0904, 0x555d, 0xa85c, 0x9080, 0x001b, 0xaf60, 0x2009, - 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4bd2, 0x701f, - 0x54ca, 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, 0xa870, 0x9005, - 0x1120, 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, 0x35e0, 0xa866, - 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x4bbc, 0x1110, 0x0804, - 0x35e0, 0x2009, 0x0043, 0x080c, 0xd33f, 0x2009, 0x0003, 0x0904, - 0x555d, 0x7007, 0x0003, 0x701f, 0x54ee, 0x0005, 0xa830, 0x9086, - 0x0100, 0x2009, 0x0004, 0x0904, 0x555d, 0x7984, 0x7aa8, 0x9284, - 0x1000, 0xc0d5, 0x080c, 0x5782, 0x0804, 0x35ab, 0x00c6, 0xaab0, - 0x9284, 0xc000, 0x0148, 0xd2ec, 0x0170, 0x080c, 0x57e7, 0x1158, - 0x2009, 0x0014, 0x0804, 0x554c, 0x2061, 0x1800, 0x080c, 0x57e7, - 0x2009, 0x0007, 0x15c8, 0xd2f4, 0x0130, 0x9284, 0x5000, 0xc0d5, - 0x080c, 0x57ad, 0x0058, 0xd2fc, 0x0180, 0x080c, 0x4bba, 0x0590, - 0xa998, 0x9284, 0x9000, 0xc0d5, 0x080c, 0x5782, 0xa87b, 0x0000, - 0xa883, 0x0000, 0xa897, 0x4000, 0x0438, 0x080c, 0x4bba, 0x0510, - 0x080c, 0x6a92, 0x2009, 0x0009, 0x11b8, 0xa8c4, 0x9086, 0x0500, - 0x11c8, 0xa8c8, 0x9005, 0x11b0, 0xa8cc, 0x9084, 0xff00, 0x1190, - 0x080c, 0x4bba, 0x1108, 0x0070, 0x2009, 0x004b, 0x080c, 0xd33f, - 0x2009, 0x0003, 0x0108, 0x0078, 0x0431, 0x19c0, 0xa897, 0x4005, - 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0030, 0x00ce, 0x0005, 0x9006, 0x0ce0, 0x7aa8, 0xd2dc, 0x0904, - 0x35dd, 0x0016, 0x7984, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x5782, - 0x001e, 0x1904, 0x35dd, 0x0804, 0x35ab, 0x00f6, 0x2d78, 0xaab0, - 0x0021, 0x00fe, 0x0005, 0xaab0, 0xc2d5, 0xd2dc, 0x0150, 0x0016, - 0xa998, 0x9284, 0x1400, 0xc0fd, 0x080c, 0x5782, 0x001e, 0x9085, - 0x0001, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35dd, - 0x080c, 0x57e7, 0x0120, 0x2009, 0x0007, 0x0804, 0x35dd, 0x7984, - 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x671d, 0x1904, 0x35e0, 0x9186, - 0x007f, 0x0138, 0x080c, 0x6a92, 0x0120, 0x2009, 0x0009, 0x0804, - 0x35dd, 0x080c, 0x4b89, 0x1120, 0x2009, 0x0002, 0x0804, 0x35dd, - 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, 0x0100, 0x8007, - 0xa80a, 0x080c, 0xd03b, 0x1120, 0x2009, 0x0003, 0x0804, 0x35dd, - 0x7007, 0x0003, 0x701f, 0x55bd, 0x0005, 0xa808, 0x8007, 0x9086, - 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x35dd, 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, 0x4bd5, 0x080c, 0x4b89, 0x1120, 0x2009, - 0x0002, 0x0804, 0x35dd, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, - 0x8217, 0x82ff, 0x1118, 0x7023, 0x19b5, 0x0040, 0x92c6, 0x0001, - 0x1118, 0x7023, 0x19cf, 0x0010, 0x0804, 0x35e0, 0x2009, 0x001a, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, - 0x080c, 0x4bd2, 0x701f, 0x560d, 0x0005, 0x2001, 0x182e, 0x2003, - 0x0001, 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, 0x20e0, 0x20a9, - 0x001a, 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, 0x0804, 0x35ab, - 0x080c, 0x4b89, 0x1120, 0x2009, 0x0002, 0x0804, 0x35dd, 0x7984, - 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x2099, - 0x19b5, 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, 0x19cf, 0x0010, - 0x0804, 0x35e0, 0xa85c, 0x9080, 0x0019, 0x20a0, 0xa860, 0x20e8, - 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x0804, - 0x4bd5, 0x7884, 0x908a, 0x1000, 0x1a04, 0x35e0, 0x0126, 0x2091, - 0x8000, 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, 0x19fc, - 0x614a, 0x00ce, 0x012e, 0x0804, 0x35ab, 0x00c6, 0x080c, 0x7569, - 0x1160, 0x080c, 0x784e, 0x080c, 0x6127, 0x9085, 0x0001, 0x080c, - 0x75ad, 0x080c, 0x7495, 0x080c, 0x0dc5, 0x2061, 0x1800, 0x6030, - 0xc09d, 0x6032, 0x080c, 0x5fe6, 0x00ce, 0x0005, 0x00c6, 0x2001, - 0x1800, 0x2004, 0x908e, 0x0000, 0x0904, 0x35dd, 0x7884, 0x9005, - 0x0188, 0x7888, 0x2061, 0x199d, 0x2c0c, 0x2062, 0x080c, 0x2c62, - 0x01a0, 0x080c, 0x2c6a, 0x0188, 0x080c, 0x2c72, 0x0170, 0x2162, - 0x0804, 0x35e0, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, - 0x2009, 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, 0x9086, 0x0002, - 0x1568, 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, 0x0026, 0x2011, - 0x0003, 0x080c, 0xa8ed, 0x2011, 0x0002, 0x080c, 0xa8f7, 0x002e, - 0x080c, 0xa801, 0x0036, 0x901e, 0x080c, 0xa877, 0x003e, 0x60e3, - 0x0000, 0x080c, 0xedfa, 0x080c, 0xee15, 0x9085, 0x0001, 0x080c, - 0x75ad, 0x9006, 0x080c, 0x2d52, 0x2001, 0x1800, 0x2003, 0x0004, - 0x2001, 0x19a9, 0x2003, 0x0000, 0x6027, 0x0008, 0x00ce, 0x0804, - 0x35ab, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35dd, 0x080c, - 0x57e7, 0x0120, 0x2009, 0x0007, 0x0804, 0x35dd, 0x7984, 0x7ea8, - 0x96b4, 0x00ff, 0x080c, 0x671d, 0x1904, 0x35e0, 0x9186, 0x007f, - 0x0138, 0x080c, 0x6a92, 0x0120, 0x2009, 0x0009, 0x0804, 0x35dd, - 0x080c, 0x4b89, 0x1120, 0x2009, 0x0002, 0x0804, 0x35dd, 0xa867, - 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd03e, 0x1120, 0x2009, - 0x0003, 0x0804, 0x35dd, 0x7007, 0x0003, 0x701f, 0x5710, 0x0005, - 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x35dd, - 0xa8e0, 0xa866, 0xa834, 0x8007, 0x800c, 0xa85c, 0x9080, 0x000c, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xaf60, 0x0804, 0x4bd5, 0xa898, - 0x9086, 0x000d, 0x1904, 0x35dd, 0x2021, 0x4005, 0x0126, 0x2091, - 0x8000, 0x0e04, 0x5734, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, - 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, - 0x4005, 0xa998, 0x7986, 0xa9a4, 0x799a, 0xa9a8, 0x799e, 0x080c, - 0x4bc5, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11aa, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x19fc, 0x7984, - 0x615a, 0x6156, 0x605f, 0x0000, 0x6053, 0x0009, 0x7898, 0x6072, - 0x789c, 0x606e, 0x7888, 0x606a, 0x788c, 0x6066, 0x2001, 0x1a0c, - 0x2044, 0x2001, 0x1a13, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, - 0xa07f, 0x0002, 0xa06b, 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, - 0x0804, 0x35ab, 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, - 0xc000, 0x0168, 0x0006, 0xd0d4, 0x0130, 0x0036, 0x2019, 0x0029, - 0x080c, 0x3360, 0x003e, 0x080c, 0xcea3, 0x000e, 0x1198, 0xd0e4, - 0x0160, 0x9180, 0x1000, 0x2004, 0x905d, 0x0160, 0x080c, 0x6141, - 0x080c, 0xb06b, 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, 0x5782, 0x002e, 0x001e, 0x8108, 0x1f04, 0x57b5, - 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, 0x35e0, 0x9182, 0x0081, 0x1a04, 0x35e0, 0x810c, - 0x0016, 0x080c, 0x4b89, 0x0170, 0x080c, 0x0f16, 0x2100, 0x2238, - 0x7d84, 0x7c88, 0x7b8c, 0x7a90, 0x001e, 0x080c, 0x4bd2, 0x701f, - 0x5817, 0x0005, 0x001e, 0x2009, 0x0002, 0x0804, 0x35dd, 0x2079, - 0x0000, 0x7d94, 0x7c98, 0x7ba8, 0x7aac, 0x79a4, 0x810c, 0x2061, - 0x18b8, 0x2c44, 0xa770, 0xa074, 0x2071, 0x189e, 0x080c, 0x4bd5, - 0x701f, 0x582b, 0x0005, 0x2061, 0x18b8, 0x2c44, 0x0016, 0x0026, - 0xa270, 0xa174, 0x080c, 0x0f1e, 0x002e, 0x001e, 0x080c, 0x0fcb, - 0x9006, 0xa802, 0xa806, 0x0804, 0x35ab, 0x0126, 0x0156, 0x0136, - 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, - 0x0100, 0x2069, 0x0200, 0x2071, 0x1800, 0x6044, 0xd0a4, 0x11e8, - 0xd084, 0x0118, 0x080c, 0x59e6, 0x0068, 0xd08c, 0x0118, 0x080c, - 0x58ef, 0x0040, 0xd094, 0x0118, 0x080c, 0x58bf, 0x0018, 0xd09c, - 0x0108, 0x0099, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, - 0x014e, 0x013e, 0x015e, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, - 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, 0x0006, 0x7098, 0x9005, - 0x000e, 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, 0x60a3, 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, 0x5f89, 0x080c, 0x87a1, 0x0005, 0x2001, - 0x1869, 0x2004, 0xd08c, 0x0110, 0x705f, 0xffff, 0x7088, 0x9005, - 0x1528, 0x2011, 0x5f89, 0x080c, 0x8709, 0x6040, 0x9094, 0x0010, - 0x9285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, - 0x1f04, 0x58d5, 0x6242, 0x709b, 0x0000, 0x6040, 0x9094, 0x0010, - 0x9285, 0x0080, 0x6042, 0x6242, 0x0048, 0x6242, 0x709b, 0x0000, - 0x708f, 0x0000, 0x9006, 0x080c, 0x612c, 0x0000, 0x0005, 0x708c, - 0x908a, 0x0003, 0x1a0c, 0x0dc5, 0x000b, 0x0005, 0x58f9, 0x594a, - 0x59e5, 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, 0x708f, 0x0001, - 0x2001, 0x015d, 0x2003, 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, - 0x6800, 0x9084, 0x00fc, 0x0120, 0x1f04, 0x5908, 0x080c, 0x0dc5, - 0x68a0, 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, - 0x1600, 0x6902, 0x001e, 0x6837, 0x0020, 0x080c, 0x6108, 0x2079, - 0x1c00, 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, - 0x1805, 0x20e9, 0x0001, 0x20a1, 0x1c0e, 0x20a9, 0x0004, 0x4003, - 0x080c, 0xadbc, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, - 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, - 0x0000, 0x080c, 0x5fba, 0x00fe, 0x9006, 0x7092, 0x6043, 0x0008, - 0x6042, 0x0005, 0x00f6, 0x7090, 0x7093, 0x0000, 0x9025, 0x0904, - 0x59c2, 0x6020, 0xd0b4, 0x1904, 0x59c0, 0x71a0, 0x81ff, 0x0904, - 0x59ae, 0x9486, 0x000c, 0x1904, 0x59bb, 0x9480, 0x0018, 0x8004, - 0x20a8, 0x080c, 0x6101, 0x2011, 0x0260, 0x2019, 0x1c00, 0x220c, - 0x2304, 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, 0x5967, 0x6043, - 0x0004, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, - 0x0100, 0x6043, 0x0006, 0x708f, 0x0002, 0x709b, 0x0002, 0x2009, - 0x07d0, 0x2011, 0x5f90, 0x080c, 0x87a1, 0x080c, 0x6108, 0x04c0, - 0x080c, 0x6101, 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, - 0x7834, 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, - 0x9005, 0x0190, 0x080c, 0x6101, 0x2011, 0x026e, 0x2019, 0x1805, - 0x20a9, 0x0004, 0x220c, 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, - 0x8318, 0x1f04, 0x59a2, 0x0078, 0x70a3, 0x0000, 0x080c, 0x6101, - 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, 0xadbc, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, - 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, - 0x2011, 0x19f3, 0x2013, 0x0000, 0x7093, 0x0000, 0x60a3, 0x0056, - 0x60a7, 0x9575, 0x080c, 0xa50e, 0x08d8, 0x0005, 0x7098, 0x908a, - 0x001d, 0x1a0c, 0x0dc5, 0x000b, 0x0005, 0x5a17, 0x5a2a, 0x5a53, - 0x5a73, 0x5a99, 0x5ac8, 0x5aee, 0x5b26, 0x5b4c, 0x5b7a, 0x5bb5, - 0x5bed, 0x5c0b, 0x5c36, 0x5c58, 0x5c73, 0x5c7d, 0x5cb1, 0x5cd7, - 0x5d06, 0x5d2c, 0x5d64, 0x5da8, 0x5de5, 0x5e06, 0x5e5f, 0x5e81, - 0x5eaf, 0x5eaf, 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, 0x5f90, 0x080c, - 0x87a1, 0x0005, 0x00f6, 0x7090, 0x9086, 0x0014, 0x1510, 0x6042, - 0x6020, 0xd0b4, 0x11f0, 0x080c, 0x6101, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x2011, 0x5f90, - 0x080c, 0x8709, 0x709b, 0x0010, 0x080c, 0x5c7d, 0x0010, 0x7093, - 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0003, 0x6043, 0x0004, - 0x2011, 0x5f90, 0x080c, 0x8709, 0x080c, 0x6085, 0x2079, 0x0240, - 0x7833, 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, - 0x200b, 0x0000, 0x8108, 0x1f04, 0x5a68, 0x60c3, 0x0014, 0x080c, - 0x5fba, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, - 0x5f90, 0x080c, 0x8709, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6101, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, - 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, - 0x0001, 0x709b, 0x0004, 0x0029, 0x0010, 0x080c, 0x60dd, 0x00fe, - 0x0005, 0x00f6, 0x709b, 0x0005, 0x080c, 0x6085, 0x2079, 0x0240, - 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x6101, 0x080c, 0x60e4, - 0x1170, 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, - 0x2011, 0x0008, 0x080c, 0x5f3d, 0x0168, 0x080c, 0x60ba, 0x20a9, - 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5fba, 0x00fe, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5f90, 0x080c, 0x8709, - 0x9086, 0x0014, 0x11b8, 0x080c, 0x6101, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0006, - 0x0029, 0x0010, 0x080c, 0x60dd, 0x00fe, 0x0005, 0x00f6, 0x709b, - 0x0007, 0x080c, 0x6085, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, - 0x0000, 0x080c, 0x6101, 0x080c, 0x60e4, 0x11b8, 0x7084, 0x9005, - 0x11a0, 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, 0x33ac, 0x200d, - 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5f3d, 0x0180, - 0x080c, 0x50cf, 0x0110, 0x080c, 0x28fd, 0x20a9, 0x0008, 0x20e1, - 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, - 0x60c3, 0x0014, 0x080c, 0x5fba, 0x00fe, 0x0005, 0x00f6, 0x7090, - 0x9005, 0x0500, 0x2011, 0x5f90, 0x080c, 0x8709, 0x9086, 0x0014, - 0x11b8, 0x080c, 0x6101, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, - 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, - 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0008, 0x0029, 0x0010, - 0x080c, 0x60dd, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0009, 0x080c, - 0x6085, 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, - 0x60e4, 0x1150, 0x7084, 0x9005, 0x1138, 0x080c, 0x5eb0, 0x1188, - 0x9085, 0x0001, 0x080c, 0x28fd, 0x20a9, 0x0008, 0x080c, 0x6101, + 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, 0x5fba, 0x0010, 0x080c, 0x5a0a, - 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x05a8, 0x2011, 0x5f90, - 0x080c, 0x8709, 0x9086, 0x0014, 0x1560, 0x080c, 0x6101, 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, 0x5c58, - 0x0010, 0x080c, 0x60dd, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000b, - 0x2011, 0x1c0e, 0x20e9, 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, - 0xffff, 0x4304, 0x080c, 0x6085, 0x2079, 0x0240, 0x7833, 0x1106, - 0x7837, 0x0000, 0x080c, 0x60e4, 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, 0x5bda, 0x60c3, - 0x0084, 0x080c, 0x5fba, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x01c0, 0x2011, 0x5f90, 0x080c, 0x8709, 0x9086, 0x0084, 0x1178, - 0x080c, 0x6101, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, - 0x7834, 0x9005, 0x1120, 0x709b, 0x000c, 0x0029, 0x0010, 0x080c, - 0x60dd, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000d, 0x080c, 0x6085, - 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, 0x6101, - 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, - 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, - 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5c1e, - 0x60c3, 0x0084, 0x080c, 0x5fba, 0x00fe, 0x0005, 0x00f6, 0x7090, - 0x9005, 0x01e0, 0x2011, 0x5f90, 0x080c, 0x8709, 0x9086, 0x0084, - 0x1198, 0x080c, 0x6101, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, - 0x1158, 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, 0x6057, - 0x709b, 0x000e, 0x0029, 0x0010, 0x080c, 0x60dd, 0x00fe, 0x0005, - 0x918d, 0x0001, 0x080c, 0x612c, 0x709b, 0x000f, 0x7093, 0x0000, - 0x2061, 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, - 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x5f90, - 0x080c, 0x86fd, 0x0005, 0x7090, 0x9005, 0x0130, 0x2011, 0x5f90, - 0x080c, 0x8709, 0x709b, 0x0000, 0x0005, 0x709b, 0x0011, 0x080c, - 0xadbc, 0x080c, 0x6101, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, - 0x0000, 0x20a1, 0x0240, 0x7490, 0x9480, 0x0018, 0x9080, 0x0007, - 0x9084, 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, 0x60e4, 0x11a0, - 0x717c, 0x81ff, 0x0188, 0x900e, 0x7080, 0x9084, 0x00ff, 0x0160, - 0x080c, 0x2894, 0x9186, 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, - 0x2011, 0x0008, 0x080c, 0x5f3d, 0x60c3, 0x0014, 0x080c, 0x5fba, - 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5f90, 0x080c, - 0x8709, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6101, 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, 0x6093, 0x2079, 0x0240, 0x7833, 0x1103, - 0x7837, 0x0000, 0x080c, 0x6101, 0x080c, 0x60e4, 0x1170, 0x7084, - 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, - 0x080c, 0x5f3d, 0x0168, 0x080c, 0x60ba, 0x20a9, 0x0008, 0x20e1, + 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, 0x5fba, 0x00fe, 0x0005, 0x00f6, 0x7090, - 0x9005, 0x0500, 0x2011, 0x5f90, 0x080c, 0x8709, 0x9086, 0x0014, - 0x11b8, 0x080c, 0x6101, 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, - 0x6093, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, - 0x6101, 0x080c, 0x60e4, 0x11b8, 0x7084, 0x9005, 0x11a0, 0x7164, - 0x9186, 0xffff, 0x0180, 0x9180, 0x33ac, 0x200d, 0x918c, 0xff00, - 0x810f, 0x2011, 0x0008, 0x080c, 0x5f3d, 0x0180, 0x080c, 0x50cf, - 0x0110, 0x080c, 0x28fd, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, - 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, - 0x080c, 0x5fba, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x05f0, - 0x2011, 0x5f90, 0x080c, 0x8709, 0x9086, 0x0014, 0x15a8, 0x080c, - 0x6101, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, - 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1168, 0x9085, 0x0001, - 0x080c, 0x612c, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, - 0x70c7, 0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, - 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x9085, 0x0001, 0x080c, - 0x612c, 0x7097, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70df, 0x0008, - 0x709b, 0x0016, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, - 0x080c, 0xadbc, 0x080c, 0x6101, 0x20e1, 0x0000, 0x2099, 0x0260, - 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, - 0x026d, 0x2204, 0x9084, 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, - 0x026e, 0x709b, 0x0017, 0x080c, 0x60e4, 0x1150, 0x7084, 0x9005, - 0x1138, 0x080c, 0x5eb0, 0x1188, 0x9085, 0x0001, 0x080c, 0x28fd, - 0x20a9, 0x0008, 0x080c, 0x6101, 0x20e1, 0x0000, 0x2099, 0x026e, - 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, - 0x5fba, 0x0010, 0x080c, 0x5a0a, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x01d8, 0x2011, 0x5f90, 0x080c, 0x8709, 0x9086, 0x0084, 0x1190, - 0x080c, 0x6101, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, - 0x7834, 0x9005, 0x1138, 0x9006, 0x080c, 0x612c, 0x709b, 0x0018, + 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, - 0x0019, 0x080c, 0x6093, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, - 0x0000, 0x080c, 0x6101, 0x2009, 0x026e, 0x2039, 0x1c0e, 0x20a9, - 0x0040, 0x213e, 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, - 0x8000, 0x6816, 0x2009, 0x0260, 0x1f04, 0x5e19, 0x2039, 0x1c0e, - 0x080c, 0x60e4, 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, - 0x5e4c, 0x60c3, 0x0084, 0x080c, 0x5fba, 0x00fe, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x01e0, 0x2011, 0x5f90, 0x080c, 0x8709, 0x9086, - 0x0084, 0x1198, 0x080c, 0x6101, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, - 0x6057, 0x709b, 0x001a, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, - 0x0005, 0x9085, 0x0001, 0x080c, 0x612c, 0x709b, 0x001b, 0x080c, - 0xadbc, 0x080c, 0x6101, 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, 0x5e98, 0x60c3, 0x0084, 0x080c, 0x5fba, 0x0005, 0x0005, - 0x0086, 0x0096, 0x2029, 0x1848, 0x252c, 0x20a9, 0x0008, 0x2041, - 0x1c0e, 0x20e9, 0x0001, 0x28a0, 0x080c, 0x6101, 0x20e1, 0x0000, - 0x2099, 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, - 0x0108, 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, - 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x5eca, 0x0804, - 0x5f39, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, - 0x0020, 0x91a6, 0x3fff, 0x0904, 0x5f39, 0x918d, 0xc000, 0x20a9, - 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, - 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, - 0x8319, 0x0008, 0x8318, 0x1f04, 0x5ef0, 0x04d8, 0x23a8, 0x2021, - 0x0001, 0x8426, 0x8425, 0x1f04, 0x5f02, 0x2328, 0x8529, 0x92be, - 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, - 0x27a8, 0x95a8, 0x0010, 0x1f04, 0x5f11, 0x755e, 0x95c8, 0x33ac, - 0x292d, 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, - 0x080c, 0x28dd, 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, 0x33ac, 0x242d, 0x95ac, - 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x28dd, - 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7087, 0x0001, 0x9084, 0x0000, - 0x0005, 0x00e6, 0x2071, 0x1800, 0x708b, 0x0000, 0x00ee, 0x0005, - 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x6046, - 0x080c, 0xa517, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, 0x2d62, - 0x0126, 0x2091, 0x8000, 0x2071, 0x1826, 0x2073, 0x0000, 0x7840, - 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x60a3, 0x001e, 0x9094, - 0x0010, 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, - 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x2be7, 0x0228, - 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x2011, 0x19f3, 0x2013, - 0x0000, 0x7093, 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, - 0x080c, 0xa50e, 0x6144, 0xd184, 0x0120, 0x7198, 0x918d, 0x2000, - 0x0018, 0x718c, 0x918d, 0x1000, 0x2011, 0x199a, 0x2112, 0x2009, - 0x07d0, 0x2011, 0x5f90, 0x080c, 0x87a1, 0x0005, 0x0016, 0x0026, - 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb072, 0x2009, 0x00f7, - 0x080c, 0x60a3, 0x2061, 0x19fc, 0x900e, 0x611a, 0x611e, 0x617a, - 0x617e, 0x2061, 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, - 0x0090, 0x6043, 0x0010, 0x2009, 0x199a, 0x200b, 0x0000, 0x2009, - 0x002d, 0x2011, 0x6012, 0x080c, 0x86fd, 0x012e, 0x00ce, 0x002e, - 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, - 0x2071, 0x0100, 0x080c, 0xa517, 0x2071, 0x0140, 0x7004, 0x9084, - 0x4000, 0x0110, 0x080c, 0x2d62, 0x080c, 0x7571, 0x0188, 0x080c, - 0x758c, 0x1170, 0x080c, 0x7858, 0x0016, 0x080c, 0x29ac, 0x2001, - 0x196e, 0x2102, 0x001e, 0x080c, 0x7853, 0x080c, 0x7495, 0x0050, - 0x2009, 0x0001, 0x080c, 0x2c80, 0x2001, 0x0001, 0x080c, 0x283d, - 0x080c, 0x5fe6, 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, - 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, - 0x199a, 0x201c, 0x080c, 0x4be9, 0x003e, 0x002e, 0x0005, 0x20a9, - 0x0012, 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x080c, 0x6101, 0x20e9, - 0x0000, 0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x60fb, - 0x2099, 0x0260, 0x20a1, 0x1c92, 0x0051, 0x20a9, 0x000e, 0x080c, - 0x60fe, 0x2099, 0x0260, 0x20a1, 0x1cb2, 0x0009, 0x0005, 0x0016, - 0x0026, 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, - 0x1f04, 0x607b, 0x002e, 0x001e, 0x0005, 0x080c, 0xadbc, 0x20e1, - 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, - 0x000c, 0x4003, 0x0005, 0x080c, 0xadbc, 0x080c, 0x6101, 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, 0x6a8e, 0x0158, 0x9006, - 0x2020, 0x2009, 0x002a, 0x080c, 0xe9a5, 0x2001, 0x180c, 0x200c, - 0xc195, 0x2102, 0x2019, 0x002a, 0x900e, 0x080c, 0x3211, 0x080c, - 0xd561, 0x0140, 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, - 0x4da0, 0x003e, 0x004e, 0x001e, 0x0005, 0x080c, 0x5fe6, 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, 0x19a8, 0x0118, 0x2003, - 0x0001, 0x0010, 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, - 0x2009, 0x1000, 0x9006, 0x200a, 0x8108, 0x1f04, 0x613b, 0x015e, - 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x1847, - 0x9006, 0xb802, 0xb8ce, 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, - 0x9198, 0x33ac, 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, - 0xb8c2, 0x080c, 0xb06b, 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, 0x8bc3, 0x00ce, 0x090c, 0x8f64, 0xb8af, - 0x0000, 0x6814, 0x9084, 0x00ff, 0xb842, 0x014e, 0x013e, 0x015e, - 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0xa974, 0xae78, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x6229, 0x9182, 0x0800, - 0x1a04, 0x622d, 0x2001, 0x180c, 0x2004, 0x9084, 0x0003, 0x1904, - 0x6233, 0x9188, 0x1000, 0x2104, 0x905d, 0x0518, 0xb804, 0x9084, - 0x00ff, 0x908e, 0x0006, 0x1508, 0xb8a4, 0x900d, 0x1904, 0x6245, - 0xb850, 0x900d, 0x1148, 0xa802, 0x2900, 0xb852, 0xb84e, 0x080c, - 0x9358, 0x9006, 0x012e, 0x0005, 0x00a6, 0x2150, 0x2900, 0xb002, - 0xa803, 0x0000, 0x00ae, 0xb852, 0x0c90, 0x2001, 0x0005, 0x900e, - 0x04b8, 0x2001, 0x0028, 0x900e, 0x0498, 0x9082, 0x0006, 0x1290, - 0x080c, 0xb06b, 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, 0x6a92, 0x1990, - 0xb800, 0xd0bc, 0x0978, 0x0804, 0x61dc, 0x080c, 0x68b9, 0x0904, - 0x61f5, 0x0804, 0x61e0, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, - 0xa874, 0x908e, 0x00ff, 0x1120, 0x2001, 0x196c, 0x205c, 0x0060, - 0xa974, 0x9182, 0x0800, 0x1690, 0x9188, 0x1000, 0x2104, 0x905d, - 0x01d0, 0x080c, 0x6a32, 0x11d0, 0x080c, 0xb0ab, 0x0570, 0x2b00, - 0x6012, 0x2900, 0x6016, 0x6023, 0x0009, 0x600b, 0x0000, 0xa874, - 0x908e, 0x00ff, 0x1110, 0x600b, 0x8000, 0x2009, 0x0043, 0x080c, - 0xb180, 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, 0x6316, 0x9188, 0x1000, 0x2104, 0x905d, 0x0904, 0x62ee, - 0xb8a0, 0x9086, 0x007f, 0x0190, 0xa87c, 0xd0fc, 0x1178, 0x080c, - 0x6a9a, 0x0160, 0xa994, 0x81ff, 0x0130, 0x908e, 0x0004, 0x0130, - 0x908e, 0x0005, 0x0118, 0x080c, 0x6a92, 0x1598, 0xa87c, 0xd0fc, - 0x01e0, 0xa894, 0x9005, 0x01c8, 0x2060, 0x0026, 0x2010, 0x080c, - 0xce44, 0x002e, 0x1120, 0x2001, 0x0008, 0x0804, 0x6318, 0x6020, - 0x9086, 0x000a, 0x0120, 0x2001, 0x0008, 0x0804, 0x6318, 0x601a, - 0x6003, 0x0008, 0x2900, 0x6016, 0x0058, 0x080c, 0xb0ab, 0x05e8, - 0x2b00, 0x6012, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, - 0x2009, 0x0003, 0x080c, 0xb180, 0x9006, 0x0458, 0x2001, 0x0028, - 0x0438, 0x9082, 0x0006, 0x1290, 0x080c, 0xb06b, 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, - 0x63ad, 0x6368, 0x637f, 0x63ad, 0x63ad, 0x63ad, 0x63ad, 0x63ad, - 0x2100, 0x9082, 0x007e, 0x1278, 0x080c, 0x66b2, 0x0148, 0x9046, - 0xb810, 0x9306, 0x1904, 0x63b5, 0xb814, 0x9206, 0x15f0, 0x0028, - 0xbb12, 0xba16, 0x0010, 0x080c, 0x4a9c, 0x0150, 0x04b0, 0x080c, - 0x671d, 0x1598, 0xb810, 0x9306, 0x1580, 0xb814, 0x9206, 0x1568, - 0x080c, 0xb0ab, 0x0530, 0x2b00, 0x6012, 0x080c, 0xd2d2, 0x2900, - 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0xa878, 0x9086, 0x0001, - 0x1170, 0x080c, 0x3246, 0x9006, 0x080c, 0x664f, 0x2001, 0x0002, - 0x080c, 0x6663, 0x2001, 0x0200, 0xb86e, 0xb893, 0x0002, 0x2009, - 0x0003, 0x080c, 0xb180, 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, - 0x65a0, 0x90c6, 0x0056, 0x0904, 0x65a4, 0x90c6, 0x0066, 0x0904, - 0x65a8, 0x90c6, 0x0067, 0x0904, 0x65ac, 0x90c6, 0x0068, 0x0904, - 0x65b0, 0x90c6, 0x0071, 0x0904, 0x65b4, 0x90c6, 0x0074, 0x0904, - 0x65b8, 0x90c6, 0x007c, 0x0904, 0x65bc, 0x90c6, 0x007e, 0x0904, - 0x65c0, 0x90c6, 0x0037, 0x0904, 0x65c4, 0x9016, 0x2079, 0x1800, - 0xa974, 0x9186, 0x00ff, 0x0904, 0x659b, 0x9182, 0x0800, 0x1a04, - 0x659b, 0x080c, 0x671d, 0x1198, 0xb804, 0x9084, 0x00ff, 0x9082, - 0x0006, 0x1268, 0xa894, 0x90c6, 0x006f, 0x0148, 0x080c, 0xb06b, - 0x1904, 0x6584, 0xb8a0, 0x9084, 0xff80, 0x1904, 0x6584, 0xa894, - 0x90c6, 0x006f, 0x0158, 0x90c6, 0x005e, 0x0904, 0x64e4, 0x90c6, - 0x0064, 0x0904, 0x650d, 0x2008, 0x0804, 0x64a6, 0xa998, 0xa8b0, - 0x2040, 0x080c, 0xb06b, 0x1120, 0x9182, 0x007f, 0x0a04, 0x64a6, - 0x9186, 0x00ff, 0x0904, 0x64a6, 0x9182, 0x0800, 0x1a04, 0x64a6, - 0xaaa0, 0xab9c, 0x787c, 0x9306, 0x11a8, 0x7880, 0x0096, 0x924e, - 0x1128, 0x2208, 0x2310, 0x009e, 0x0804, 0x64a6, 0x080c, 0xb06b, - 0x1140, 0x99cc, 0xff00, 0x009e, 0x1128, 0x2208, 0x2310, 0x0804, - 0x64a6, 0x009e, 0x080c, 0x4a9c, 0x0904, 0x64b0, 0x900e, 0x9016, - 0x90c6, 0x4000, 0x15e0, 0x0006, 0x080c, 0x693d, 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, 0xb0ab, 0x1130, 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, - 0x0c78, 0x2b00, 0x6012, 0x080c, 0xd2d2, 0x2900, 0x6016, 0x6023, - 0x0001, 0xa868, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x3246, 0x012e, 0x9006, 0x080c, 0x664f, 0x2001, - 0x0002, 0x080c, 0x6663, 0x2009, 0x0002, 0x080c, 0xb180, 0xa8b0, - 0xd094, 0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x9006, 0x9005, 0x012e, - 0x00ee, 0x00fe, 0x00be, 0x0005, 0x080c, 0x57e7, 0x0118, 0x2009, - 0x0007, 0x00f8, 0xa998, 0xaeb0, 0x080c, 0x671d, 0x1904, 0x64a1, - 0x9186, 0x007f, 0x0130, 0x080c, 0x6a92, 0x0118, 0x2009, 0x0009, - 0x0080, 0x0096, 0x080c, 0x100e, 0x1120, 0x009e, 0x2009, 0x0002, - 0x0040, 0x2900, 0x009e, 0xa806, 0x080c, 0xd03e, 0x19b0, 0x2009, - 0x0003, 0x2001, 0x4005, 0x0804, 0x64a8, 0xa998, 0xaeb0, 0x080c, - 0x671d, 0x1904, 0x64a1, 0x0096, 0x080c, 0x100e, 0x1128, 0x009e, - 0x2009, 0x0002, 0x0804, 0x6561, 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, 0x57d3, 0xd0b4, 0x1118, 0xa89b, 0x000b, - 0x00e0, 0xb800, 0xd08c, 0x0118, 0xa89b, 0x000c, 0x00b0, 0x080c, - 0x6a92, 0x0118, 0xa89b, 0x0009, 0x0080, 0x080c, 0x57e7, 0x0118, - 0xa89b, 0x0007, 0x0050, 0x080c, 0xd021, 0x1904, 0x64dd, 0x2009, - 0x0003, 0x2001, 0x4005, 0x0804, 0x64a8, 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, 0xb61f, 0x1904, - 0x64dd, 0x2009, 0x0002, 0x08e8, 0x2001, 0x0028, 0x900e, 0x0804, - 0x64de, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, - 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, - 0x900e, 0x0804, 0x64de, 0x2001, 0x0029, 0x900e, 0x0804, 0x64de, - 0x080c, 0x37dd, 0x0804, 0x64df, 0x080c, 0x54fe, 0x0804, 0x64df, - 0x080c, 0x460c, 0x0804, 0x64df, 0x080c, 0x4685, 0x0804, 0x64df, - 0x080c, 0x46e1, 0x0804, 0x64df, 0x080c, 0x4b5f, 0x0804, 0x64df, - 0x080c, 0x4e13, 0x0804, 0x64df, 0x080c, 0x5165, 0x0804, 0x64df, - 0x080c, 0x535e, 0x0804, 0x64df, 0x080c, 0x3a07, 0x0804, 0x64df, - 0x00b6, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1618, - 0x9182, 0x0800, 0x1268, 0x9188, 0x1000, 0x2104, 0x905d, 0x0140, - 0x080c, 0x6a92, 0x1148, 0x00e9, 0x080c, 0x6848, 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, 0x19e9, - 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, 0x6a8e, 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, 0x6a8a, - 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, 0x6141, - 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, 0xce56, 0x0110, 0x080c, 0x0fc0, 0x080c, - 0xb101, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x00c6, 0xb8ac, 0x9065, - 0x0128, 0x621c, 0xd2c4, 0x0110, 0x080c, 0x8f64, 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, 0x7569, - 0x1510, 0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, 0xb06b, 0x11d8, - 0x0078, 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x1983, 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, 0x68d9, 0xa807, 0x0001, 0xae12, 0x9085, 0x0001, - 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, - 0x0096, 0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, 0x080c, - 0x68e8, 0x1158, 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, 0xa806, - 0x0020, 0x080c, 0x1040, 0xb8a7, 0x0000, 0x009e, 0x012e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x080c, 0x9358, 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, 0xa91f, - 0xaa00, 0xb84c, 0x9906, 0x1110, 0xba4e, 0x0020, 0x00a6, 0x2150, - 0xb202, 0x00ae, 0x82ff, 0x1110, 0xb952, 0x89ff, 0x012e, 0x0005, - 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, 0x693d, - 0x0128, 0x080c, 0xcf13, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, - 0x693d, 0x0128, 0x080c, 0xceb8, 0x0010, 0x9085, 0x0001, 0x0005, - 0x080c, 0x693d, 0x0128, 0x080c, 0xcf10, 0x0010, 0x9085, 0x0001, - 0x0005, 0x080c, 0x693d, 0x0128, 0x080c, 0xced7, 0x0010, 0x9085, - 0x0001, 0x0005, 0x080c, 0x693d, 0x0128, 0x080c, 0xcf56, 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, + 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, 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, 0x68d9, 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, 0x7569, 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, 0x671d, 0x1168, - 0xb804, 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, 0x9086, - 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, 0x1f04, - 0x6964, 0x015e, 0x080c, 0x6a50, 0x0120, 0x2001, 0x1986, 0x200c, - 0x0038, 0x2079, 0x1847, 0x7804, 0xd0a4, 0x0130, 0x2009, 0x07d0, - 0x2011, 0x698f, 0x080c, 0x87a1, 0x00fe, 0x00be, 0x0005, 0x00b6, - 0x2011, 0x698f, 0x080c, 0x8709, 0x080c, 0x6a50, 0x01d8, 0x2001, - 0x107e, 0x2004, 0x2058, 0xb900, 0xc1ec, 0xb902, 0x080c, 0x6a8e, - 0x0130, 0x2009, 0x07d0, 0x2011, 0x698f, 0x080c, 0x87a1, 0x00e6, - 0x2071, 0x1800, 0x9006, 0x707e, 0x7060, 0x7082, 0x080c, 0x3019, - 0x00ee, 0x04c0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, - 0x080c, 0x671d, 0x1548, 0xb800, 0xd0ec, 0x0530, 0xd0bc, 0x1520, - 0x0046, 0xbaa0, 0x2220, 0x9006, 0x2009, 0x0029, 0x080c, 0xe9a5, - 0xb800, 0xc0e5, 0xc0ec, 0xb802, 0x080c, 0x6a8a, 0x2001, 0x0707, - 0x1128, 0xb804, 0x9084, 0x00ff, 0x9085, 0x0700, 0xb806, 0x2019, - 0x0029, 0x080c, 0x94e0, 0x0076, 0x903e, 0x080c, 0x93b3, 0x900e, - 0x080c, 0xe690, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x69b7, - 0x00ce, 0x015e, 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058, 0xb800, - 0xc0ec, 0xb802, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x0096, 0x080c, - 0x1027, 0x090c, 0x0dc5, 0x2958, 0x009e, 0x2001, 0x196c, 0x2b02, - 0x8b07, 0x8006, 0x8006, 0x908c, 0x003f, 0xb9c6, 0x908c, 0xffc0, - 0xb9ca, 0xb8af, 0x0000, 0x2009, 0x00ff, 0x080c, 0x6141, 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, 0x1984, 0x200c, 0x2011, 0x6a80, 0x080c, 0x87a1, 0x0005, - 0x2011, 0x6a80, 0x080c, 0x8709, 0x2011, 0x1837, 0x2204, 0xc0cc, - 0x2012, 0x0005, 0x080c, 0x57d3, 0xd0ac, 0x0005, 0x080c, 0x57d3, - 0xd0a4, 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, 0x0006, - 0x001e, 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, 0x908e, - 0x0006, 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xd561, 0x0158, - 0x70dc, 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, 0x905d, - 0x0110, 0xb8cc, 0xd094, 0x00fe, 0x00be, 0x0005, 0x2071, 0x1910, - 0x7003, 0x0001, 0x7007, 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, - 0x701e, 0x700a, 0x7046, 0x2001, 0x1922, 0x2003, 0x0000, 0x0005, - 0x0016, 0x00e6, 0x2071, 0x1949, 0x900e, 0x710a, 0x080c, 0x57d3, - 0xd0fc, 0x1140, 0x080c, 0x57d3, 0x900e, 0xd09c, 0x0108, 0x8108, - 0x7102, 0x0430, 0x2001, 0x1867, 0x200c, 0x9184, 0x0007, 0x0002, - 0x6ad2, 0x6ad2, 0x6ad2, 0x6ad2, 0x6ad2, 0x6ae8, 0x6afd, 0x6b0b, - 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, 0x78c0, 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, - 0x1949, 0x7000, 0x9015, 0x0904, 0x6dd7, 0x9286, 0x0003, 0x0904, - 0x6c70, 0x9286, 0x0005, 0x0904, 0x6c70, 0x2071, 0x1877, 0xa87c, - 0x9005, 0x0904, 0x6bcb, 0x7140, 0xa868, 0x9102, 0x0a04, 0x6dd7, - 0xa878, 0xd084, 0x15d8, 0xa853, 0x0019, 0x2001, 0x8023, 0xa84e, - 0x2071, 0x1910, 0x701c, 0x9005, 0x1904, 0x6fa5, 0x0e04, 0x7013, - 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, 0x6c53, 0xa853, 0x001b, - 0x2001, 0x8027, 0x0820, 0x7004, 0xd08c, 0x1904, 0x6dd7, 0xa853, - 0x001a, 0x2001, 0x8024, 0x0804, 0x6b8f, 0x00e6, 0x0026, 0x2071, - 0x1949, 0x7000, 0x9015, 0x0904, 0x6dd7, 0x9286, 0x0003, 0x0904, - 0x6c70, 0x9286, 0x0005, 0x0904, 0x6c70, 0xa84f, 0x8022, 0xa853, - 0x0018, 0x0804, 0x6c38, 0xa868, 0xd0fc, 0x1508, 0x00e6, 0x0026, - 0x2001, 0x1949, 0x2004, 0x9015, 0x0904, 0x6dd7, 0xa978, 0xa874, - 0x9105, 0x1904, 0x6dd7, 0x9286, 0x0003, 0x0904, 0x6c70, 0x9286, - 0x0005, 0x0904, 0x6c70, 0xa87c, 0xd0bc, 0x1904, 0x6dd7, 0x2200, - 0x0002, 0x6dd7, 0x6c34, 0x6c70, 0x6c70, 0x6dd7, 0x6c70, 0x0005, - 0xa868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x2009, 0x1949, 0x210c, - 0x81ff, 0x0904, 0x6dd7, 0xa880, 0x9084, 0x00ff, 0x9086, 0x0001, - 0x1904, 0x6dd7, 0x9186, 0x0003, 0x0904, 0x6c70, 0x9186, 0x0005, - 0x0904, 0x6c70, 0xa87c, 0xd0cc, 0x0904, 0x6dd7, 0xa84f, 0x8021, - 0xa853, 0x0017, 0x0028, 0x0005, 0xa84f, 0x8020, 0xa853, 0x0016, - 0x2071, 0x1910, 0x701c, 0x9005, 0x1904, 0x6fa5, 0x0e04, 0x7013, - 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, 0x85f1, 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, 0x6d5b, 0x782c, 0x908c, 0x0780, - 0x190c, 0x7161, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, - 0x6c8e, 0x6d5b, 0x6cb2, 0x6cf8, 0x080c, 0x0dc5, 0x2071, 0x1800, - 0x2900, 0x7822, 0xa804, 0x900d, 0x1168, 0x2071, 0x19fc, 0x7044, - 0x9005, 0x1320, 0x2001, 0x194a, 0x2004, 0x7046, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, - 0x85f1, 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, 0x85f1, 0x782c, 0x9094, 0x0780, 0x190c, - 0x7161, 0xd0a4, 0x19f0, 0x2071, 0x19fc, 0x7044, 0x9005, 0x1320, - 0x2001, 0x194a, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x85f1, 0x0808, - 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x85f1, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7161, 0xd0a4, 0x1d60, 0x00ee, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7161, 0xd09c, 0x1198, 0x009e, 0x2900, - 0x7822, 0xa804, 0x900d, 0x1550, 0x2071, 0x19fc, 0x7044, 0x9005, - 0x1320, 0x2001, 0x194a, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, - 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, - 0x1168, 0x2071, 0x19fc, 0x7044, 0x9005, 0x1320, 0x2001, 0x194a, - 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, + 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, 0x85f1, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, - 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, - 0x900d, 0x1904, 0x6daf, 0x782c, 0x9094, 0x0780, 0x190c, 0x7161, - 0xd09c, 0x1198, 0x701c, 0x904d, 0x0180, 0x7010, 0x8001, 0x7012, - 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, - 0x0780, 0x190c, 0x7161, 0xd09c, 0x0d68, 0x782c, 0x9094, 0x0780, - 0x190c, 0x7161, 0xd0a4, 0x01b0, 0x00e6, 0x7824, 0x2048, 0x2071, - 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, - 0x080c, 0x85f1, 0x782c, 0x9094, 0x0780, 0x190c, 0x7161, 0xd0a4, - 0x1d60, 0x00ee, 0x2071, 0x19fc, 0x7044, 0x9005, 0x1320, 0x2001, - 0x194a, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, - 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, - 0x85f1, 0x00ee, 0x0804, 0x6d6b, 0xa868, 0xd0fc, 0x1904, 0x6e25, - 0x0096, 0xa804, 0xa807, 0x0000, 0x904d, 0x190c, 0x0fc0, 0x009e, - 0x0020, 0xa868, 0xd0fc, 0x1904, 0x6e25, 0x00e6, 0x0026, 0xa84f, - 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1800, 0x70ec, 0x8001, - 0x0558, 0x1a04, 0x6e22, 0x2071, 0x1910, 0xa803, 0x0000, 0xa864, - 0x9084, 0x00ff, 0x908e, 0x0016, 0x01a8, 0x7010, 0x9005, 0x1904, - 0x6f21, 0x782c, 0x908c, 0x0780, 0x190c, 0x7161, 0x8004, 0x8004, - 0x8004, 0x9084, 0x0003, 0x0002, 0x6e26, 0x6f21, 0x6e41, 0x6eb2, - 0x080c, 0x0dc5, 0x2009, 0x1949, 0x2104, 0x0002, 0x6ded, 0x6ded, - 0x6ded, 0x6c79, 0x6ded, 0x6c79, 0x70ef, 0x0fa0, 0x71e8, 0x8107, - 0x9106, 0x9094, 0x00c0, 0x9184, 0xff3f, 0x9205, 0x70ea, 0x3b08, - 0x3a00, 0x9104, 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205, - 0x20d0, 0x0808, 0x70ee, 0x0804, 0x6de3, 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, 0x85f1, - 0x0c60, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1904, - 0x6ea1, 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, 0x85f1, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7161, 0xd0a4, 0x19f0, 0x0e04, 0x6e98, - 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, 0x85f1, - 0x0804, 0x6e54, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, - 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x85f1, 0x782c, 0x9094, 0x0780, 0x190c, 0x7161, 0xd0a4, 0x1d60, - 0x00ee, 0x0e04, 0x6ef4, 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, 0x7161, - 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, + 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, 0x85f1, 0x00fe, 0x002e, 0x00ee, + 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, - 0x6f90, 0x782c, 0x9094, 0x0780, 0x190c, 0x7161, 0xd09c, 0x11b0, - 0x701c, 0x904d, 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, 0x8001, - 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7161, 0xd09c, 0x0d50, 0x782c, 0x9094, - 0x0780, 0x190c, 0x7161, 0xd0a4, 0x05b8, 0x00e6, 0x7824, 0x2048, - 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, - 0x70c2, 0x080c, 0x85f1, 0x782c, 0x9094, 0x0780, 0x190c, 0x7161, - 0xd0a4, 0x1d60, 0x00ee, 0x0e04, 0x6f89, 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, 0x85f1, 0x00ee, 0x0804, 0x6f31, 0x2071, 0x1910, 0xa803, - 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, - 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1128, - 0x1e04, 0x6fd0, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, + 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, 0x85f1, 0x0e04, 0x6fba, - 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, - 0x714d, 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, + 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, 0x1118, 0x002e, 0x00ee, - 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, - 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, - 0x080c, 0x85f1, 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, - 0x7060, 0x7061, 0x714c, 0x7061, 0x705e, 0x714c, 0x080c, 0x0dc5, - 0x0005, 0x2001, 0x1949, 0x2004, 0x0002, 0x706b, 0x706b, 0x70e5, - 0x70e6, 0x706b, 0x70e6, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x716c, - 0x701c, 0x904d, 0x0508, 0xa84c, 0x9005, 0x0904, 0x70b6, 0x0e04, - 0x7094, 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, 0x714d, 0x012e, 0x0804, 0x70e4, 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, 0x7161, 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, 0x19fc, 0x6844, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, - 0x0540, 0x2001, 0x1815, 0x2004, 0x2009, 0x1ad2, 0x210c, 0x9102, - 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, - 0x9106, 0x0190, 0x0e04, 0x7118, 0x2069, 0x0000, 0x6837, 0x8040, - 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x11aa, 0x2069, 0x19fc, 0x6847, 0xffff, - 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x71d7, 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, 0x7163, 0x0006, 0x0016, 0x2001, - 0x8004, 0x0006, 0x0804, 0x0dce, 0x0096, 0x00f6, 0x2079, 0x0050, - 0x7044, 0xd084, 0x01d0, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, + 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, - 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, 0x85f1, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7161, 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, - 0x7161, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, - 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x85f1, 0x782c, 0x9094, 0x0780, 0x190c, 0x7161, 0xd0a4, 0x1d70, - 0x00d6, 0x2069, 0x0050, 0x693c, 0x2069, 0x1949, 0x6808, 0x690a, - 0x2069, 0x19fc, 0x9102, 0x1118, 0x6844, 0x9005, 0x1320, 0x2001, - 0x194a, 0x200c, 0x6946, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7098, - 0x908a, 0x002a, 0x1a0c, 0x0dc5, 0x9082, 0x001d, 0x001b, 0x6027, - 0x1e00, 0x0005, 0x7318, 0x7285, 0x72a1, 0x72cb, 0x7307, 0x7347, - 0x7359, 0x72a1, 0x732f, 0x7240, 0x726e, 0x72f1, 0x723f, 0x0005, - 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, 0x9005, - 0x1518, 0x709b, 0x0029, 0x2069, 0x1990, 0x2d04, 0x7002, 0x080c, - 0x769e, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, 0x709b, 0x0029, - 0x2069, 0x1990, 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, 0x602a, - 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a66, 0x080c, 0x1b02, - 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, - 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, 0x709b, - 0x0029, 0x2069, 0x1990, 0x2d04, 0x7002, 0x080c, 0x773b, 0x6028, - 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, 0x0090, - 0x080c, 0x2d52, 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x73c6, - 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x709b, 0x0020, - 0x080c, 0x73c6, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, - 0x0005, 0x2001, 0x0088, 0x080c, 0x2d52, 0x6124, 0xd1cc, 0x11e8, - 0xd1dc, 0x11c0, 0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, 0x080c, - 0x1b2f, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x7595, - 0x2001, 0x0080, 0x080c, 0x2d52, 0x709b, 0x0029, 0x0058, 0x709b, - 0x001e, 0x0040, 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, - 0x709b, 0x001f, 0x0005, 0x080c, 0x1b2f, 0x60e3, 0x0001, 0x600c, - 0xc0b4, 0x600e, 0x080c, 0x7595, 0x2001, 0x0080, 0x080c, 0x2d52, - 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, + 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, - 0x00a0, 0x080c, 0x2d52, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, - 0x080c, 0x1b2f, 0x709b, 0x001e, 0x0010, 0x709b, 0x001d, 0x0005, - 0x080c, 0x7449, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x73c6, 0x0016, - 0x080c, 0x1b2f, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x709b, - 0x001e, 0x0020, 0x709b, 0x001f, 0x080c, 0x73c6, 0x0005, 0x0006, - 0x2001, 0x00a0, 0x080c, 0x2d52, 0x000e, 0x6124, 0xd1d4, 0x1160, - 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, 0x001e, - 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x0021, 0x0005, 0x080c, - 0x7449, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, - 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, - 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2d52, 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, 0x7569, 0x11d8, 0x2001, 0x180c, 0x200c, 0xd1b4, - 0x01b0, 0xc1b4, 0x2102, 0x6027, 0x0200, 0x080c, 0x2c7a, 0x6024, - 0xd0cc, 0x0148, 0x2001, 0x00a0, 0x080c, 0x2d52, 0x080c, 0x784e, - 0x080c, 0x6127, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, - 0x7583, 0x0150, 0x080c, 0x757a, 0x1138, 0x2001, 0x0001, 0x080c, - 0x283d, 0x080c, 0x7541, 0x00a0, 0x080c, 0x7446, 0x0178, 0x2001, - 0x0001, 0x080c, 0x283d, 0x7098, 0x9086, 0x001e, 0x0120, 0x7098, - 0x9086, 0x0022, 0x1118, 0x709b, 0x0025, 0x0010, 0x709b, 0x0021, - 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, - 0x73d7, 0x080c, 0x87e3, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, - 0x2011, 0x73d7, 0x080c, 0x87da, 0x002e, 0x001e, 0x0005, 0x00e6, - 0x00f6, 0x0016, 0x080c, 0xa517, 0x2071, 0x1800, 0x080c, 0x7374, - 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x2071, 0x1800, 0x080c, 0xa517, - 0x2061, 0x0100, 0x2069, 0x0140, 0x2091, 0x8000, 0x6028, 0xc09c, - 0x602a, 0x2011, 0x0003, 0x080c, 0xa8ed, 0x2011, 0x0002, 0x080c, - 0xa8f7, 0x080c, 0xa801, 0x080c, 0x878f, 0x0036, 0x901e, 0x080c, - 0xa877, 0x003e, 0x60e3, 0x0000, 0x080c, 0xedfa, 0x080c, 0xee15, - 0x2009, 0x0004, 0x080c, 0x2c80, 0x080c, 0x2b9b, 0x2001, 0x1800, - 0x2003, 0x0004, 0x6027, 0x0008, 0x2011, 0x73d7, 0x080c, 0x87e3, - 0x080c, 0x7583, 0x0118, 0x9006, 0x080c, 0x2d52, 0x080c, 0x0ba0, - 0x2001, 0x0001, 0x080c, 0x283d, 0x012e, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, - 0x73e4, 0x2071, 0x19fc, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, - 0x0110, 0x9085, 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, - 0x0005, 0x6800, 0x9084, 0xfffe, 0x9086, 0x00c0, 0x01b8, 0x2001, - 0x00c0, 0x080c, 0x2d52, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x7456, - 0x2091, 0x6000, 0x1f04, 0x7456, 0x015e, 0x00d6, 0x2069, 0x1800, - 0x689c, 0x8001, 0x0220, 0x0118, 0x689e, 0x00de, 0x0005, 0x689f, - 0x0014, 0x68e8, 0xd0dc, 0x0dc8, 0x6800, 0x9086, 0x0001, 0x1da8, - 0x080c, 0x87ef, 0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x785d, 0x2001, 0x196e, - 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, 0x6886, 0x080c, 0x2908, - 0x9006, 0x080c, 0x2d52, 0x080c, 0x5fe6, 0x6027, 0xffff, 0x602b, - 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, - 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x197e, - 0x200c, 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, - 0x0002, 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x7531, 0x709b, - 0x0022, 0x0040, 0x709b, 0x0021, 0x0028, 0x709b, 0x0023, 0x0010, - 0x709b, 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, - 0x080c, 0x2908, 0x0026, 0x080c, 0xb072, 0x002e, 0x7000, 0x908e, - 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, - 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, - 0x012e, 0x015e, 0x080c, 0xd561, 0x0118, 0x9006, 0x080c, 0x2d7c, - 0x0804, 0x753d, 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, - 0x2c7a, 0x6904, 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2d52, - 0x1f04, 0x74d5, 0x080c, 0x75bd, 0x012e, 0x015e, 0x080c, 0x757a, - 0x01d8, 0x6044, 0x9005, 0x0198, 0x2011, 0x0114, 0x2204, 0x9085, - 0x0100, 0x2012, 0x6050, 0x0006, 0x9085, 0x0020, 0x6052, 0x080c, - 0x75bd, 0x9006, 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, - 0xd0d4, 0x1110, 0x080c, 0x75bd, 0x080c, 0xd561, 0x0118, 0x9006, - 0x080c, 0x2d7c, 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, 0x0130, - 0x2009, 0x00c8, 0x2011, 0x73e4, 0x080c, 0x87a1, 0x002e, 0x001e, - 0x080c, 0x85e8, 0x7034, 0xc085, 0x7036, 0x2001, 0x197e, 0x2003, - 0x0004, 0x080c, 0x7227, 0x080c, 0x757a, 0x0138, 0x6804, 0xd0d4, - 0x1120, 0xd0dc, 0x1100, 0x080c, 0x7853, 0x00ee, 0x00de, 0x00ce, - 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, - 0x2071, 0x1800, 0x080c, 0x85ff, 0x080c, 0x85f1, 0x080c, 0x785d, - 0x2001, 0x196e, 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, 0x6886, - 0x080c, 0x2908, 0x9006, 0x080c, 0x2d52, 0x6043, 0x0090, 0x6043, - 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, - 0x0005, 0x0006, 0x2001, 0x197d, 0x2004, 0x9086, 0xaaaa, 0x000e, - 0x0005, 0x0006, 0x080c, 0x57d7, 0x9084, 0x0030, 0x9086, 0x0000, - 0x000e, 0x0005, 0x0006, 0x080c, 0x57d7, 0x9084, 0x0030, 0x9086, - 0x0030, 0x000e, 0x0005, 0x0006, 0x080c, 0x57d7, 0x9084, 0x0030, - 0x9086, 0x0010, 0x000e, 0x0005, 0x0006, 0x080c, 0x57d7, 0x9084, - 0x0030, 0x9086, 0x0020, 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, - 0x180c, 0x2004, 0x908c, 0x0013, 0x0168, 0x0020, 0x080c, 0x2928, - 0x900e, 0x0010, 0x2009, 0x0002, 0x2019, 0x0028, 0x080c, 0x3211, - 0x9006, 0x0019, 0x001e, 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, - 0x2e04, 0x0130, 0x080c, 0xd55a, 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, 0x75d2, 0x2091, 0x6000, 0x1f04, 0x75d2, - 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, 0x2908, - 0x2001, 0x00a0, 0x0006, 0x080c, 0xd561, 0x000e, 0x0130, 0x080c, - 0x2d70, 0x9006, 0x080c, 0x2d7c, 0x0010, 0x080c, 0x2d52, 0x000e, - 0x6052, 0x6050, 0x0006, 0xc0e5, 0x6052, 0x00f6, 0x2079, 0x0100, - 0x080c, 0x2bef, 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, 0x7690, 0x2001, 0x180c, - 0x200c, 0xc1c4, 0x2102, 0x6028, 0x9084, 0xe1ff, 0x602a, 0x6027, - 0x0200, 0x2001, 0x0090, 0x080c, 0x2d52, 0x20a9, 0x0366, 0x6024, - 0xd0cc, 0x1518, 0x1d04, 0x763f, 0x2091, 0x6000, 0x1f04, 0x763f, - 0x2011, 0x0003, 0x080c, 0xa8ed, 0x2011, 0x0002, 0x080c, 0xa8f7, - 0x080c, 0xa801, 0x901e, 0x080c, 0xa877, 0x2001, 0x00a0, 0x080c, - 0x2d52, 0x080c, 0x784e, 0x080c, 0x6127, 0x080c, 0xd561, 0x0110, - 0x080c, 0x0d33, 0x9085, 0x0001, 0x0488, 0x080c, 0x1b2f, 0x60e3, - 0x0000, 0x2001, 0x196e, 0x2004, 0x080c, 0x2908, 0x60e2, 0x2001, - 0x0080, 0x080c, 0x2d52, 0x20a9, 0x0366, 0x6027, 0x1e00, 0x2009, - 0x1e00, 0x080c, 0x2c7a, 0x6024, 0x910c, 0x0138, 0x1d04, 0x7675, - 0x2091, 0x6000, 0x1f04, 0x7675, 0x0818, 0x6028, 0x9085, 0x1e00, - 0x602a, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, - 0x080c, 0xd561, 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, 0x1a7d, 0x2d04, - 0x8000, 0x206a, 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, - 0x6884, 0x9005, 0x1904, 0x7703, 0x2001, 0x0088, 0x080c, 0x2d52, - 0x9006, 0x60e2, 0x6886, 0x080c, 0x2908, 0x2069, 0x0200, 0x6804, - 0x9005, 0x1118, 0x6808, 0x9005, 0x01c0, 0x6028, 0x9084, 0xfbff, - 0x602a, 0x6027, 0x0400, 0x2069, 0x1990, 0x7000, 0x206a, 0x709b, - 0x0026, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x76e5, 0x2091, - 0x6000, 0x1f04, 0x76e5, 0x0804, 0x7733, 0x2069, 0x0140, 0x20a9, - 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c7a, 0x6024, - 0x910c, 0x0508, 0x9084, 0x1a00, 0x11f0, 0x1d04, 0x76f1, 0x2091, - 0x6000, 0x1f04, 0x76f1, 0x2011, 0x0003, 0x080c, 0xa8ed, 0x2011, - 0x0002, 0x080c, 0xa8f7, 0x080c, 0xa801, 0x901e, 0x080c, 0xa877, - 0x2001, 0x00a0, 0x080c, 0x2d52, 0x080c, 0x784e, 0x080c, 0x6127, - 0x9085, 0x0001, 0x00c0, 0x080c, 0x1b2f, 0x2001, 0x0080, 0x080c, - 0x2d52, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, - 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x196e, 0x2004, 0x080c, - 0x2908, 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, 0xa8ed, 0x2011, 0x0002, - 0x080c, 0xa8f7, 0x080c, 0xa801, 0x901e, 0x080c, 0xa877, 0x2069, - 0x0140, 0x2001, 0x00a0, 0x080c, 0x2d52, 0x080c, 0x784e, 0x080c, - 0x6127, 0x0804, 0x77ce, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x1160, - 0xc1b5, 0x2102, 0x080c, 0x73cc, 0x2069, 0x0140, 0x2001, 0x0080, - 0x080c, 0x2d52, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0x9005, - 0x1118, 0x6808, 0x9005, 0x0180, 0x6028, 0x9084, 0xfdff, 0x602a, - 0x6027, 0x0200, 0x2069, 0x1990, 0x7000, 0x206a, 0x709b, 0x0027, - 0x7003, 0x0001, 0x0804, 0x77ce, 0x6027, 0x1e00, 0x2009, 0x1e00, - 0x080c, 0x2c7a, 0x6024, 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, - 0x1d04, 0x778c, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, - 0x8642, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, - 0x19fc, 0x7078, 0x00ee, 0x9005, 0x19f8, 0x0400, 0x0026, 0x2011, - 0x73e4, 0x080c, 0x8709, 0x2011, 0x73d7, 0x080c, 0x87e3, 0x002e, - 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, - 0x0001, 0x0008, 0x6886, 0x2001, 0x196e, 0x2004, 0x080c, 0x2908, - 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, 0xd55a, 0x1904, 0x783c, 0x7130, 0xd184, 0x1170, - 0x080c, 0x33a0, 0x0138, 0xc18d, 0x7132, 0x2011, 0x1848, 0x2214, - 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x783c, 0x2011, 0x1848, - 0x220c, 0xd1a4, 0x0538, 0x0016, 0x2019, 0x000e, 0x080c, 0xe915, - 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x9186, 0x007e, 0x01a0, - 0x9186, 0x0080, 0x0188, 0x080c, 0x671d, 0x1170, 0x2120, 0x9006, - 0x0016, 0x2009, 0x000e, 0x080c, 0xe9a5, 0x2009, 0x0001, 0x2011, - 0x0100, 0x080c, 0x891c, 0x001e, 0x8108, 0x1f04, 0x7805, 0x00be, - 0x015e, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0002, 0x2019, - 0x0004, 0x080c, 0x3211, 0x001e, 0x0078, 0x0156, 0x00b6, 0x20a9, - 0x007f, 0x900e, 0x080c, 0x671d, 0x1110, 0x080c, 0x6141, 0x8108, - 0x1f04, 0x7832, 0x00be, 0x015e, 0x080c, 0x1b2f, 0x080c, 0xb072, - 0x60e3, 0x0000, 0x080c, 0x6127, 0x080c, 0x7495, 0x00ee, 0x00ce, - 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x197e, - 0x2003, 0x0001, 0x0005, 0x2001, 0x197e, 0x2003, 0x0000, 0x0005, - 0x2001, 0x197d, 0x2003, 0xaaaa, 0x0005, 0x2001, 0x197d, 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, 0x7e40, 0x9006, 0x00ee, 0x0005, - 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, 0x2011, 0x0100, 0x2214, - 0x9296, 0x0008, 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, 0x1f04, - 0x78c4, 0x015e, 0x0005, 0x2079, 0x0040, 0x2071, 0x18fa, 0x7004, - 0x0002, 0x78e3, 0x78e4, 0x791c, 0x7977, 0x7a87, 0x78e1, 0x78e1, - 0x7ab1, 0x080c, 0x0dc5, 0x0005, 0x2079, 0x0040, 0x782c, 0x908c, - 0x0780, 0x190c, 0x7f22, 0xd0a4, 0x01f8, 0x7824, 0x2048, 0x9006, - 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x0040, 0x0610, - 0x00c0, 0x2001, 0x1800, 0x200c, 0x9186, 0x0003, 0x1168, 0x7004, - 0x0002, 0x790c, 0x78e6, 0x790c, 0x790a, 0x790c, 0x790c, 0x790c, - 0x790c, 0x790c, 0x080c, 0x7977, 0x782c, 0xd09c, 0x090c, 0x7e40, - 0x0005, 0x9082, 0x005a, 0x1218, 0x2100, 0x003b, 0x0c10, 0x080c, - 0x79ad, 0x0c90, 0x00e3, 0x08e8, 0x0005, 0x79ad, 0x79ad, 0x79ad, - 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79cf, 0x79ad, 0x79ad, - 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, - 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, - 0x79ad, 0x79b9, 0x79ad, 0x7ba7, 0x79ad, 0x79ad, 0x79ad, 0x79cf, - 0x79ad, 0x79b9, 0x7be8, 0x7c29, 0x7c70, 0x7c84, 0x79ad, 0x79ad, - 0x79cf, 0x79b9, 0x79e3, 0x79ad, 0x7a5b, 0x7d2f, 0x7d4a, 0x79ad, - 0x79cf, 0x79ad, 0x79e3, 0x79ad, 0x79ad, 0x7a51, 0x7d4a, 0x79ad, - 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, - 0x79f7, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, - 0x79ad, 0x79ad, 0x7ec6, 0x79ad, 0x7e70, 0x79ad, 0x7e70, 0x79ad, - 0x7a0c, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x79ad, 0x2079, - 0x0040, 0x7004, 0x9086, 0x0003, 0x1198, 0x782c, 0x080c, 0x7e69, - 0xd0a4, 0x0170, 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, - 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, 0x002b, 0x0c50, 0x00e9, - 0x080c, 0x7e40, 0x0005, 0x79ad, 0x79b9, 0x7b93, 0x79ad, 0x79b9, - 0x79ad, 0x79b9, 0x79b9, 0x79ad, 0x79b9, 0x7b93, 0x79b9, 0x79b9, - 0x79b9, 0x79b9, 0x79b9, 0x79ad, 0x79b9, 0x7b93, 0x79ad, 0x79ad, - 0x79b9, 0x79ad, 0x79ad, 0x79ad, 0x79b9, 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, 0x6dd1, 0x012e, 0x0005, 0xa864, - 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, 0x1120, 0x7007, 0x0001, - 0x0804, 0x7b30, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, - 0x704b, 0x7b30, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0968, - 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7b4b, 0x7007, 0x0003, - 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7b4b, 0x0005, 0xa864, - 0x8007, 0x9084, 0x00ff, 0x0904, 0x79b5, 0x8001, 0x1120, 0x7007, - 0x0001, 0x0804, 0x7b67, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, - 0x701a, 0x704b, 0x7b67, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, - 0x9086, 0x0001, 0x1904, 0x79b5, 0x7007, 0x0001, 0x2009, 0x1834, - 0x210c, 0x81ff, 0x11a8, 0xa868, 0x9084, 0x00ff, 0xa86a, 0xa883, - 0x0000, 0x080c, 0x63be, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, - 0xa867, 0x0139, 0xa87a, 0xa982, 0x080c, 0x6dd1, 0x012e, 0x0ca0, - 0xa994, 0x9186, 0x0071, 0x0d38, 0x9186, 0x0064, 0x0d20, 0x9186, - 0x007c, 0x0d08, 0x9186, 0x0028, 0x09f0, 0x9186, 0x0038, 0x09d8, - 0x9186, 0x0078, 0x09c0, 0x9186, 0x005f, 0x09a8, 0x9186, 0x0056, - 0x0990, 0xa897, 0x4005, 0xa89b, 0x0001, 0x2001, 0x0030, 0x900e, - 0x08a0, 0xa87c, 0x9084, 0x00c0, 0x9086, 0x00c0, 0x1120, 0x7007, - 0x0001, 0x0804, 0x7d61, 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, 0x79bd, 0xaab4, 0x928a, 0x0002, - 0x1a04, 0x79bd, 0x82ff, 0x1138, 0xa8b8, 0xa9bc, 0x9105, 0x0118, - 0x2001, 0x7aee, 0x0018, 0x9280, 0x7ae4, 0x2005, 0x7056, 0x7010, - 0x9015, 0x0904, 0x7acf, 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, 0x79bd, 0x7020, 0x2048, 0x7018, 0xa802, 0xa807, - 0x0000, 0x2908, 0x2048, 0xa906, 0x711a, 0x0804, 0x7a87, 0x7014, - 0x2048, 0x7007, 0x0001, 0xa8b4, 0x9005, 0x1128, 0xa8b8, 0xa9bc, - 0x9105, 0x0108, 0x00b9, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, - 0x0904, 0x7d61, 0x0804, 0x7b30, 0x7ae6, 0x7aea, 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, 0x61bb, 0x1108, - 0x0005, 0x080c, 0x703d, 0x0126, 0x2091, 0x8000, 0x080c, 0xd14c, - 0x080c, 0x6dd1, 0x012e, 0x0ca0, 0x080c, 0xd55a, 0x1d70, 0x2001, - 0x0028, 0x900e, 0x0c70, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1188, - 0xa888, 0x9005, 0x0188, 0xa883, 0x0000, 0x080c, 0x624b, 0x1108, - 0x0005, 0xa87a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6dd1, 0x012e, - 0x0cb8, 0x2001, 0x0028, 0x0ca8, 0x2001, 0x0000, 0x0c90, 0x0419, - 0x11d8, 0xa888, 0x9005, 0x01e0, 0xa883, 0x0000, 0xa87c, 0xd0f4, - 0x0120, 0x080c, 0x6320, 0x1138, 0x0005, 0x9006, 0xa87a, 0x080c, - 0x6298, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, - 0x080c, 0x6dd1, 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, - 0x671d, 0x11b8, 0x0066, 0xae80, 0x080c, 0x682d, 0x006e, 0x0088, - 0x0046, 0x2011, 0x180c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, - 0x080c, 0x671d, 0x1110, 0x080c, 0x692d, 0x8108, 0x1f04, 0x7bd0, - 0x00ce, 0xa87c, 0xd084, 0x1120, 0x080c, 0x1040, 0x00be, 0x0005, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6dd1, 0x012e, 0x00be, 0x0005, - 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x6a8e, 0x0580, - 0x2061, 0x1a75, 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, 0x7e2a, - 0x012e, 0x0804, 0x7e24, 0x012e, 0x0804, 0x7e1e, 0x012e, 0x0804, - 0x7e21, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x6a8e, - 0x05e0, 0x2061, 0x1a75, 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, 0x7e2a, 0x012e, 0x0804, 0x7e27, 0x012e, 0x0804, 0x7e24, - 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0x1a75, 0x6300, - 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, - 0x7e38, 0x012e, 0x0804, 0x7e27, 0x00b6, 0x0126, 0x00c6, 0x2091, - 0x8000, 0x7007, 0x0001, 0xa87c, 0xd0ac, 0x0148, 0x00c6, 0x2061, - 0x1a75, 0x6000, 0x9084, 0xfcff, 0x6002, 0x00ce, 0x0440, 0xa888, - 0x9005, 0x05d8, 0xa88c, 0x9065, 0x0598, 0x2001, 0x1834, 0x2004, - 0x9005, 0x0118, 0x080c, 0xb134, 0x0068, 0x6017, 0xf400, 0x605b, - 0x0000, 0xa97c, 0xd1a4, 0x0110, 0xa980, 0x615a, 0x2009, 0x0041, - 0x080c, 0xb180, 0xa988, 0x918c, 0xff00, 0x9186, 0x2000, 0x1138, - 0x0026, 0x900e, 0x2011, 0xfdff, 0x080c, 0x891c, 0x002e, 0xa87c, - 0xd0c4, 0x0148, 0x2061, 0x1a75, 0x6000, 0xd08c, 0x1120, 0x6008, - 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, 0x00be, 0x0804, 0x7e2a, - 0x00ce, 0x012e, 0x00be, 0x0804, 0x7e24, 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, - 0x671d, 0x1968, 0xb800, 0xc0e4, 0xb802, 0x0848, 0xa88c, 0x9065, - 0x09b8, 0x6007, 0x0024, 0x2001, 0x1987, 0x2004, 0x601a, 0x0804, - 0x7cbf, 0xa88c, 0x9065, 0x0960, 0x00e6, 0xa890, 0x9075, 0x2001, - 0x1834, 0x2004, 0x9005, 0x0150, 0x080c, 0xb134, 0x8eff, 0x0118, - 0x2e60, 0x080c, 0xb134, 0x00ee, 0x0804, 0x7cbf, 0x6024, 0xc0dc, - 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0xa8a0, 0x9005, 0x0130, - 0x6007, 0x003b, 0xa8a4, 0x602e, 0xa8a8, 0x6016, 0x6003, 0x0001, - 0x080c, 0x933b, 0x080c, 0x98ed, 0x00ee, 0x0804, 0x7cbf, 0x2061, - 0x1a75, 0x6000, 0xd084, 0x0190, 0xd08c, 0x1904, 0x7e38, 0x0126, - 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, - 0x7e38, 0x012e, 0xa883, 0x0016, 0x0804, 0x7e31, 0xa883, 0x0007, - 0x0804, 0x7e31, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0130, 0x8001, - 0x1138, 0x7007, 0x0001, 0x0069, 0x0005, 0x080c, 0x79b5, 0x0040, - 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7d61, - 0x0005, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x903e, 0x2061, - 0x1800, 0x61d0, 0x81ff, 0x1904, 0x7de3, 0x6130, 0xd194, 0x1904, - 0x7e0d, 0xa878, 0x2070, 0x9e82, 0x1cd0, 0x0a04, 0x7dd7, 0x6068, - 0x9e02, 0x1a04, 0x7dd7, 0x7120, 0x9186, 0x0006, 0x1904, 0x7dc9, - 0x7010, 0x905d, 0x0904, 0x7de3, 0xb800, 0xd0e4, 0x1904, 0x7e07, - 0x2061, 0x1a75, 0x6100, 0x9184, 0x0301, 0x9086, 0x0001, 0x15a0, - 0x7024, 0xd0dc, 0x1904, 0x7e10, 0xa883, 0x0000, 0xa803, 0x0000, - 0x2908, 0x7014, 0x9005, 0x1198, 0x7116, 0xa87c, 0xd0f4, 0x1904, - 0x7e13, 0x080c, 0x57d3, 0xd09c, 0x1118, 0xa87c, 0xc0cc, 0xa87e, - 0x2e60, 0x080c, 0x883c, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2048, - 0xa800, 0x9005, 0x1de0, 0xa902, 0x2148, 0xa87c, 0xd0f4, 0x1904, - 0x7e13, 0x012e, 0x00ee, 0x00be, 0x0005, 0x012e, 0x00ee, 0xa883, - 0x0006, 0x00be, 0x0804, 0x7e31, 0xd184, 0x0db8, 0xd1c4, 0x1190, - 0x00a0, 0xa974, 0x080c, 0x671d, 0x15d0, 0xb800, 0xd0e4, 0x15b8, - 0x7120, 0x9186, 0x0007, 0x1118, 0xa883, 0x0002, 0x0490, 0xa883, - 0x0008, 0x0478, 0xa883, 0x000e, 0x0460, 0xa883, 0x0017, 0x0448, - 0xa883, 0x0035, 0x0430, 0x080c, 0x57d7, 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, 0x7d6d, - 0x7003, 0x0002, 0x0804, 0x7d6d, 0xa883, 0x0028, 0x0010, 0xa883, - 0x0029, 0x012e, 0x00ee, 0x00be, 0x0420, 0xa883, 0x002a, 0x0cc8, - 0xa883, 0x0045, 0x0cb0, 0x2e60, 0x2019, 0x0002, 0x601b, 0x0014, - 0x080c, 0xe4c8, 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, 0x6dd1, 0x012e, 0x0005, - 0x080c, 0x1040, 0x0005, 0x00d6, 0x080c, 0x8833, 0x00de, 0x0005, - 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x0040, 0x702c, - 0xd084, 0x01d8, 0x908c, 0x0780, 0x190c, 0x7f22, 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, 0x7f22, 0x000e, 0x0005, - 0xa898, 0x9084, 0x0003, 0x05a8, 0x080c, 0xb0ab, 0x05d8, 0x2900, - 0x6016, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x1138, 0x6008, - 0xc0fd, 0x600a, 0x2001, 0x196c, 0x2004, 0x0098, 0xa8a0, 0x9084, - 0x00ff, 0xa99c, 0x918c, 0xff00, 0x9105, 0xa99c, 0x918c, 0x00ff, - 0x080c, 0x2894, 0x1540, 0x00b6, 0x080c, 0x671d, 0x2b00, 0x00be, - 0x1510, 0x6012, 0x6023, 0x0001, 0x2009, 0x0040, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x0035, 0x0110, 0x2009, 0x0041, 0x080c, 0xb180, - 0x0005, 0xa87b, 0x0101, 0x0126, 0x2091, 0x8000, 0x080c, 0x6dd1, - 0x012e, 0x0005, 0xa87b, 0x002c, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6dd1, 0x012e, 0x0005, 0xa87b, 0x0028, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6dd1, 0x012e, 0x080c, 0xb101, 0x0005, 0x00d6, 0x00c6, - 0x0036, 0x0026, 0x0016, 0x00b6, 0x7007, 0x0001, 0xaa74, 0x9282, - 0x0004, 0x1a04, 0x7f13, 0xa97c, 0x9188, 0x1000, 0x2104, 0x905d, - 0xb804, 0xd284, 0x0140, 0x05e8, 0x8007, 0x9084, 0x00ff, 0x9084, - 0x0006, 0x1108, 0x04b0, 0x2b10, 0x080c, 0xb0ab, 0x1118, 0x080c, - 0xb153, 0x05a8, 0x6212, 0xa874, 0x0002, 0x7ef1, 0x7ef6, 0x7ef9, - 0x7eff, 0x2019, 0x0002, 0x080c, 0xe915, 0x0060, 0x080c, 0xe8ac, - 0x0048, 0x2019, 0x0002, 0xa980, 0x080c, 0xe8c7, 0x0018, 0xa980, - 0x080c, 0xe8ac, 0x080c, 0xb101, 0xa887, 0x0000, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6dd1, 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, 0x7f24, 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, - 0x7fa4, 0x68c0, 0x90aa, 0x0005, 0x0a04, 0x85e8, 0x7d44, 0x7c40, - 0x9584, 0x00f6, 0x1510, 0x9484, 0x7000, 0x0140, 0x908a, 0x2000, - 0x1260, 0x9584, 0x0700, 0x8007, 0x0804, 0x7fab, 0x7000, 0x9084, - 0xff00, 0x9086, 0x8100, 0x0da8, 0x00b0, 0x9484, 0x0fff, 0x1130, - 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x11c0, 0x080c, 0xedd2, - 0x080c, 0x84cd, 0x7817, 0x0140, 0x00a8, 0x9584, 0x0076, 0x1118, - 0x080c, 0x852b, 0x19c0, 0xd5a4, 0x0148, 0x0046, 0x0056, 0x080c, - 0x8006, 0x080c, 0x2397, 0x005e, 0x004e, 0x0020, 0x080c, 0xedd2, - 0x7817, 0x0140, 0x080c, 0x7569, 0x0168, 0x2001, 0x0111, 0x2004, - 0xd08c, 0x0140, 0x6893, 0x0000, 0x2001, 0x0110, 0x2003, 0x0008, - 0x2003, 0x0000, 0x080c, 0x7fe7, 0x2001, 0x19f2, 0x2004, 0x9005, - 0x090c, 0x98ed, 0x0005, 0x0002, 0x7fbd, 0x82d5, 0x7fb4, 0x7fb4, - 0x7fb4, 0x7fb4, 0x7fb4, 0x7fb4, 0x7817, 0x0140, 0x2001, 0x19f2, - 0x2004, 0x9005, 0x090c, 0x98ed, 0x0005, 0x7000, 0x908c, 0xff00, - 0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x6892, 0x9286, 0x2000, - 0x1150, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, 0x583d, 0x0070, - 0x080c, 0x8026, 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, 0x820d, - 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x83f4, 0x7817, 0x0140, - 0x2001, 0x19f2, 0x2004, 0x9005, 0x090c, 0x98ed, 0x0005, 0x2001, - 0x1810, 0x2004, 0xd08c, 0x0178, 0x2001, 0x1800, 0x2004, 0x9086, - 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, 0x8048, 0x2518, 0x080c, - 0x4be9, 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, 0x4be9, - 0x002e, 0x00fe, 0x005e, 0x004e, 0x003e, 0x0005, 0x00b6, 0x00c6, - 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, 0x0001, 0x0120, 0x9096, - 0x0023, 0x1904, 0x81de, 0x9186, 0x0023, 0x15c0, 0x080c, 0x8492, - 0x0904, 0x81de, 0x6120, 0x9186, 0x0001, 0x0150, 0x9186, 0x0004, - 0x0138, 0x9186, 0x0008, 0x0120, 0x9186, 0x000a, 0x1904, 0x81de, - 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, 0x2009, 0x0015, - 0x080c, 0xb180, 0x0804, 0x81de, 0x908e, 0x0214, 0x0118, 0x908e, - 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0xb180, 0x0804, 0x81de, - 0x908e, 0x0100, 0x1904, 0x81de, 0x7034, 0x9005, 0x1904, 0x81de, - 0x2009, 0x0016, 0x080c, 0xb180, 0x0804, 0x81de, 0x9186, 0x0022, - 0x1904, 0x81de, 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, 0x28dd, 0x7932, 0x7936, 0x001e, - 0x000e, 0x00fe, 0x080c, 0x2894, 0x695e, 0x703c, 0x00e6, 0x2071, - 0x0140, 0x7086, 0x2071, 0x1800, 0x70b6, 0x00ee, 0x7034, 0x9005, - 0x1904, 0x81de, 0x2009, 0x0017, 0x0804, 0x818e, 0x908e, 0x0400, - 0x1190, 0x7034, 0x9005, 0x1904, 0x81de, 0x080c, 0x7569, 0x0120, - 0x2009, 0x001d, 0x0804, 0x818e, 0x68dc, 0xc0a5, 0x68de, 0x2009, - 0x0030, 0x0804, 0x818e, 0x908e, 0x0500, 0x1140, 0x7034, 0x9005, - 0x1904, 0x81de, 0x2009, 0x0018, 0x0804, 0x818e, 0x908e, 0x2010, - 0x1120, 0x2009, 0x0019, 0x0804, 0x818e, 0x908e, 0x2110, 0x1120, - 0x2009, 0x001a, 0x0804, 0x818e, 0x908e, 0x5200, 0x1140, 0x7034, - 0x9005, 0x1904, 0x81de, 0x2009, 0x001b, 0x0804, 0x818e, 0x908e, - 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, 0x81de, 0x2009, 0x001c, - 0x0804, 0x818e, 0x908e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, - 0x818e, 0x908e, 0x1200, 0x1140, 0x7034, 0x9005, 0x1904, 0x81de, - 0x2009, 0x0024, 0x0804, 0x818e, 0x908c, 0xff00, 0x918e, 0x2400, - 0x1170, 0x2009, 0x002d, 0x2001, 0x1810, 0x2004, 0xd09c, 0x0904, - 0x818e, 0x080c, 0xdc98, 0x1904, 0x81de, 0x0804, 0x818c, 0x908c, - 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, 0x0804, 0x818e, - 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, 0x818e, 0x908e, - 0x6104, 0x1530, 0x2029, 0x0205, 0x2011, 0x026d, 0x8208, 0x2204, - 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, 0x8015, 0x211c, - 0x8108, 0x0046, 0x2124, 0x080c, 0x4be9, 0x004e, 0x8108, 0x0f04, - 0x8142, 0x9186, 0x0280, 0x1d88, 0x2504, 0x8000, 0x202a, 0x2009, - 0x0260, 0x0c58, 0x202b, 0x0000, 0x2009, 0x0023, 0x0804, 0x818e, - 0x908e, 0x6000, 0x1120, 0x2009, 0x003f, 0x0804, 0x818e, 0x908e, - 0x5400, 0x1138, 0x080c, 0x8598, 0x1904, 0x81de, 0x2009, 0x0046, - 0x04a8, 0x908e, 0x5500, 0x1148, 0x080c, 0x85c0, 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, 0x2894, 0x1904, 0x81e1, - 0x080c, 0x66b2, 0x1904, 0x81e1, 0xbe12, 0xbd16, 0x001e, 0x0016, - 0x080c, 0x7569, 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, 0xb0ab, 0x01a8, 0x2b08, 0x6112, - 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, 0x1110, - 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, 0xb180, 0x00ce, 0x00be, - 0x0005, 0x001e, 0x0cd8, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, - 0x2011, 0x8049, 0x080c, 0x4be9, 0x080c, 0xb153, 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, 0x9383, 0x08a0, 0x080c, 0x8607, 0x1158, - 0x080c, 0x336a, 0x1140, 0x7010, 0x9084, 0xff00, 0x8007, 0x908e, - 0x0008, 0x1108, 0x0009, 0x0005, 0x00b6, 0x00c6, 0x0046, 0x7000, - 0x908c, 0xff00, 0x810f, 0x9186, 0x0033, 0x11e8, 0x080c, 0x8492, - 0x0904, 0x826d, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1140, - 0x7034, 0x9005, 0x15d0, 0x2009, 0x0015, 0x080c, 0xb180, 0x04a8, - 0x908e, 0x0100, 0x1590, 0x7034, 0x9005, 0x1578, 0x2009, 0x0016, - 0x080c, 0xb180, 0x0450, 0x9186, 0x0032, 0x1538, 0x7030, 0x908e, - 0x1400, 0x1518, 0x2009, 0x0038, 0x0016, 0x2011, 0x0263, 0x2204, - 0x8211, 0x220c, 0x080c, 0x2894, 0x11b8, 0x080c, 0x66b2, 0x11a0, - 0xbe12, 0xbd16, 0x080c, 0xb0ab, 0x0178, 0x2b08, 0x6112, 0x080c, - 0xd2d2, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0xb180, - 0x080c, 0x98ed, 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, 0x82cf, 0x9596, 0xfffe, 0x1120, 0x2009, - 0x007e, 0x0804, 0x82cf, 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, 0x82a4, - 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, 0x19f2, - 0x2004, 0x9005, 0x090c, 0x98ed, 0x0005, 0x82fd, 0x82fd, 0x82fd, - 0x84a4, 0x82fd, 0x8306, 0x8331, 0x83bf, 0x82fd, 0x82fd, 0x82fd, - 0x82fd, 0x82fd, 0x82fd, 0x82fd, 0x82fd, 0x7817, 0x0140, 0x2001, - 0x19f2, 0x2004, 0x9005, 0x090c, 0x98ed, 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, 0xb180, 0x7817, - 0x0140, 0x2001, 0x19f2, 0x2004, 0x9005, 0x090c, 0x98ed, 0x00be, - 0x0005, 0x00b6, 0x00c6, 0x9484, 0x0fff, 0x0904, 0x8395, 0x7110, - 0xd1bc, 0x1904, 0x8395, 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, - 0x2130, 0x9094, 0xff00, 0x15b0, 0x81ff, 0x15a0, 0x9080, 0x33ac, - 0x200d, 0x918c, 0xff00, 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, - 0x8395, 0x080c, 0x66b2, 0x1904, 0x8395, 0xbe12, 0xbd16, 0xb800, - 0xd0ec, 0x15d8, 0xba04, 0x9294, 0xff00, 0x9286, 0x0600, 0x11a0, - 0x080c, 0xb0ab, 0x05e8, 0x2b08, 0x7028, 0x6046, 0x702c, 0x604a, - 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, 0x2009, - 0x0044, 0x080c, 0xdf10, 0x0408, 0x080c, 0x6a92, 0x1138, 0xb807, - 0x0606, 0x0c30, 0x190c, 0x8271, 0x11c0, 0x0898, 0x080c, 0xb0ab, - 0x2b08, 0x0198, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x9286, - 0x0400, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, - 0x0001, 0x080c, 0x9383, 0x080c, 0x98ed, 0x7817, 0x0140, 0x2001, - 0x19f2, 0x2004, 0x9005, 0x090c, 0x98ed, 0x00ce, 0x00be, 0x0005, - 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, - 0x4be9, 0x080c, 0xb153, 0x0d48, 0x2b08, 0x6112, 0x6023, 0x0006, - 0x7120, 0x610a, 0x7130, 0x6156, 0x6017, 0xf300, 0x6003, 0x0001, - 0x6007, 0x0041, 0x080c, 0x933b, 0x080c, 0x98ed, 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, 0xb180, - 0x7817, 0x0140, 0x2001, 0x19f2, 0x2004, 0x9005, 0x090c, 0x98ed, - 0x00be, 0x0005, 0x6120, 0x9186, 0x0002, 0x0128, 0x9186, 0x0005, - 0x0110, 0x9085, 0x0001, 0x0005, 0x080c, 0x8607, 0x1180, 0x080c, - 0x336a, 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, 0x0000, - 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, 0x000b, 0x0005, - 0x840e, 0x840f, 0x840e, 0x840e, 0x8474, 0x8483, 0x0005, 0x00b6, - 0x700c, 0x7108, 0x080c, 0x2894, 0x1904, 0x8472, 0x080c, 0x66b2, - 0x1904, 0x8472, 0xbe12, 0xbd16, 0x7110, 0xd1bc, 0x0540, 0x702c, - 0xd084, 0x1120, 0xb800, 0xd0bc, 0x1904, 0x8472, 0x080c, 0x6a92, - 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6a9a, 0x0118, 0x9086, - 0x0004, 0x1588, 0x00c6, 0x080c, 0x8492, 0x00ce, 0x05d8, 0x080c, - 0xb0ab, 0x2b08, 0x05b8, 0x6112, 0x080c, 0xd2d2, 0x6023, 0x0002, - 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xb180, 0x0458, 0x080c, - 0x6a92, 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6a9a, 0x0118, - 0x9086, 0x0004, 0x1180, 0x080c, 0xb0ab, 0x2b08, 0x01d8, 0x6112, - 0x080c, 0xd2d2, 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, - 0x080c, 0xb180, 0x0078, 0x080c, 0xb0ab, 0x2b08, 0x0158, 0x6112, - 0x080c, 0xd2d2, 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, - 0x080c, 0xb180, 0x00be, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x00d1, - 0x0148, 0x080c, 0x83ea, 0x1130, 0x7124, 0x610a, 0x2009, 0x0089, - 0x080c, 0xb180, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x0059, 0x0148, - 0x080c, 0x83ea, 0x1130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, - 0xb180, 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, 0xb180, 0x7817, 0x0140, 0x2001, 0x19f2, 0x2004, - 0x9005, 0x090c, 0x98ed, 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, 0xb0ab, - 0x05b8, 0x0066, 0x00c6, 0x0046, 0x2011, 0x0263, 0x2204, 0x8211, - 0x220c, 0x080c, 0x2894, 0x15a0, 0x080c, 0x66b2, 0x1588, 0xbe12, - 0xbd16, 0x2b00, 0x004e, 0x00ce, 0x6012, 0x080c, 0xd2d2, 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, 0x9383, 0x080c, 0x98ed, - 0x00fe, 0x009e, 0x00ce, 0x0005, 0x080c, 0xb101, 0x006e, 0x0cc0, - 0x004e, 0x00ce, 0x0cc8, 0x00c6, 0x7000, 0x908c, 0xff00, 0x9184, - 0xf000, 0x810f, 0x9086, 0x2000, 0x1904, 0x8582, 0x9186, 0x0022, - 0x15f0, 0x2001, 0x0111, 0x2004, 0x9005, 0x1904, 0x8584, 0x7030, - 0x908e, 0x0400, 0x0904, 0x8584, 0x908e, 0x6000, 0x05e8, 0x908e, - 0x5400, 0x05d0, 0x908e, 0x0300, 0x11d8, 0x2009, 0x1837, 0x210c, - 0xd18c, 0x1590, 0xd1a4, 0x1580, 0x080c, 0x6a50, 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, 0x8492, 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, 0xc0e3, 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004, - 0x2019, 0x1801, 0x2011, 0x027e, 0x080c, 0xc0e3, 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, 0xc0e3, 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004, - 0x2019, 0x1801, 0x2011, 0x0276, 0x080c, 0xc0e3, 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, 0x19fc, - 0x7003, 0x0003, 0x700f, 0x0361, 0x9006, 0x701a, 0x707a, 0x7012, - 0x7017, 0x1cd0, 0x7007, 0x0000, 0x7026, 0x702b, 0xa52d, 0x7032, - 0x703a, 0x703f, 0x0064, 0x7037, 0xa595, 0x7047, 0xffff, 0x704a, - 0x704f, 0x5665, 0x7052, 0x7063, 0x87aa, 0x080c, 0x1027, 0x090c, - 0x0dc5, 0x2900, 0x7042, 0xa867, 0x0003, 0xa86f, 0x0100, 0xa8ab, - 0xdcb0, 0x0005, 0x2071, 0x19fc, 0x1d04, 0x86f8, 0x2091, 0x6000, - 0x700c, 0x8001, 0x700e, 0x1540, 0x2001, 0x013c, 0x2004, 0x9005, - 0x190c, 0x8818, 0x2001, 0x1869, 0x2004, 0xd0c4, 0x0158, 0x3a00, - 0xd08c, 0x1140, 0x20d1, 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, - 0x080c, 0x0dc5, 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, - 0x8000, 0x080c, 0x87ef, 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, 0x7569, 0x0178, 0x00e6, - 0x2071, 0x19e9, 0x080c, 0xa623, 0x00ee, 0x1140, 0x2009, 0x1a87, - 0x2104, 0x8000, 0x0208, 0x200a, 0x001e, 0x0068, 0x001e, 0x702f, - 0x0009, 0x8109, 0x7132, 0x0128, 0x9184, 0x007f, 0x090c, 0xa6d9, - 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, 0x8720, 0x8721, 0x873d, 0x00e6, 0x2071, 0x19fc, - 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, - 0x0005, 0x00e6, 0x0006, 0x2071, 0x19fc, 0x701c, 0x9206, 0x1120, - 0x701a, 0x701e, 0x707a, 0x707e, 0x000e, 0x00ee, 0x0005, 0x00e6, - 0x2071, 0x19fc, 0xb888, 0x9102, 0x0208, 0xb98a, 0x00ee, 0x0005, - 0x0005, 0x00b6, 0x7110, 0x080c, 0x671d, 0x1168, 0xb888, 0x8001, - 0x0250, 0xb88a, 0x1140, 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, - 0x98ed, 0x001e, 0x012e, 0x8108, 0x9182, 0x0800, 0x0218, 0x900e, - 0x7007, 0x0002, 0x7112, 0x00be, 0x0005, 0x7014, 0x2060, 0x0126, - 0x2091, 0x8000, 0x6040, 0x9005, 0x0128, 0x8001, 0x6042, 0x1110, - 0x080c, 0xd163, 0x6018, 0x9005, 0x0558, 0x8001, 0x601a, 0x1540, - 0x6120, 0x9186, 0x0003, 0x0148, 0x9186, 0x0006, 0x0130, 0x9186, - 0x0009, 0x11e0, 0x611c, 0xd1c4, 0x1100, 0x080c, 0xce56, 0x01b0, - 0x6014, 0x2048, 0xa884, 0x908a, 0x199a, 0x0280, 0x9082, 0x1999, - 0xa886, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, - 0x810b, 0x9108, 0x611a, 0xa87c, 0xd0e4, 0x0110, 0x080c, 0xcb3e, - 0x012e, 0x9c88, 0x0018, 0x7116, 0x2001, 0x181a, 0x2004, 0x9102, - 0x0220, 0x7017, 0x1cd0, 0x7007, 0x0000, 0x0005, 0x00e6, 0x2071, - 0x19fc, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, - 0x1a05, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, 0x19fc, 0x7132, - 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x1a08, 0x2013, 0x0000, - 0x0005, 0x00e6, 0x2071, 0x19fc, 0x711a, 0x721e, 0x700b, 0x0009, - 0x00ee, 0x0005, 0x0086, 0x0026, 0x705c, 0x8000, 0x705e, 0x2001, - 0x1a0c, 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, 0x8642, 0x015e, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x001e, - 0x000e, 0x0005, 0x00e6, 0x2071, 0x19fc, 0x717a, 0x727e, 0x7077, - 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x19fc, 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, - 0x1a75, 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, 0x8003, 0x8003, - 0x9080, 0x1a75, 0x2060, 0x0005, 0xa884, 0x908a, 0x199a, 0x1638, - 0x9005, 0x1150, 0x00c6, 0x2061, 0x1a75, 0x6014, 0x00ce, 0x9005, - 0x1130, 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, 0x01b0, 0x8003, - 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, 0x908c, 0x00c0, 0x918e, - 0x00c0, 0x0904, 0x88c6, 0xd0b4, 0x1168, 0xd0bc, 0x1904, 0x889f, - 0x2009, 0x0006, 0x080c, 0x88f3, 0x0005, 0x900e, 0x0c60, 0x2001, - 0x1999, 0x08b0, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, - 0x0003, 0x1904, 0x88ed, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, - 0x6024, 0xd0d4, 0x11e8, 0x2009, 0x1869, 0x2104, 0xd084, 0x1138, - 0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0xb180, 0x0005, 0x87ff, - 0x1de8, 0x2009, 0x0042, 0x0804, 0xb180, 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, 0x88ed, - 0x908c, 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, 0x2c78, - 0x080c, 0x1768, 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, 0x0042, - 0x080c, 0xb180, 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, 0xb180, - 0x0005, 0x00b9, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, - 0xb180, 0x0cb0, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, - 0x0d20, 0x6124, 0xc1cd, 0x6126, 0x0c00, 0x2009, 0x0004, 0x0019, - 0x0005, 0x2009, 0x0001, 0x0096, 0x080c, 0xce56, 0x0518, 0x6014, - 0x2048, 0xa982, 0xa800, 0x6016, 0x9186, 0x0001, 0x1188, 0xa97c, - 0x918c, 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, 0x2061, 0x1a75, - 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, - 0x080c, 0x6c10, 0x6014, 0x904d, 0x0076, 0x2039, 0x0000, 0x190c, - 0x883c, 0x007e, 0x009e, 0x0005, 0x0156, 0x00c6, 0x2061, 0x1a75, - 0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, 0x6002, 0x00ce, - 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0x9005, 0x0120, - 0x8001, 0x680a, 0x9085, 0x0001, 0x0005, 0x2071, 0x1925, 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, 0x1925, 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, 0x1ad2, 0x2104, 0x9082, 0x0007, 0x200a, 0x000e, 0xc095, - 0x7012, 0x2008, 0x2001, 0x003b, 0x080c, 0x1611, 0x9006, 0x2071, - 0x193e, 0x7002, 0x7006, 0x702a, 0x00ee, 0x009e, 0x012e, 0x0005, - 0x2009, 0x1ad2, 0x2104, 0x9080, 0x0007, 0x200a, 0x0005, 0x00e6, - 0x0126, 0x0156, 0x2091, 0x8000, 0x2071, 0x1800, 0x7154, 0x2001, - 0x0008, 0x910a, 0x0638, 0x2001, 0x187d, 0x20ac, 0x9006, 0x9080, - 0x0008, 0x1f04, 0x89af, 0x71c0, 0x9102, 0x02e0, 0x2071, 0x1877, - 0x20a9, 0x0007, 0x00c6, 0x080c, 0xb0ab, 0x6023, 0x0009, 0x6003, - 0x0004, 0x601f, 0x0101, 0x0089, 0x0126, 0x2091, 0x8000, 0x080c, - 0x8b2d, 0x012e, 0x1f04, 0x89bb, 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, 0x1925, - 0x7004, 0x004b, 0x700c, 0x0002, 0x8a27, 0x8a20, 0x8a20, 0x0005, - 0x8a31, 0x8a87, 0x8a87, 0x8a87, 0x8a88, 0x8a99, 0x8a99, 0x700c, - 0x0cba, 0x0126, 0x2091, 0x8000, 0x78a0, 0x79a0, 0x9106, 0x1904, - 0x8a79, 0x7814, 0xd0bc, 0x1904, 0x8a82, 0x012e, 0x7018, 0x910a, - 0x1128, 0x7030, 0x9005, 0x1904, 0x8acb, 0x0005, 0x1210, 0x7114, - 0x910a, 0x9192, 0x000a, 0x0210, 0x2009, 0x000a, 0x2001, 0x1888, - 0x2014, 0x2001, 0x1937, 0x2004, 0x9100, 0x9202, 0x0e50, 0x080c, - 0x8c25, 0x2200, 0x9102, 0x0208, 0x2208, 0x0096, 0x702c, 0x2048, - 0xa873, 0x0001, 0xa976, 0x080c, 0x8d2e, 0x2100, 0xa87e, 0xa86f, - 0x0000, 0x009e, 0x0126, 0x2091, 0x8000, 0x2009, 0x1a1c, 0x2104, - 0xc085, 0x200a, 0x700f, 0x0002, 0x012e, 0x080c, 0x1117, 0x1de8, - 0x0005, 0x78a0, 0x79a0, 0x9106, 0x0904, 0x8a39, 0x080c, 0x8bfd, - 0x012e, 0x0005, 0x7810, 0xc0c5, 0x7812, 0x0804, 0x8a39, 0x0005, - 0x700c, 0x0002, 0x8a8d, 0x8a90, 0x8a8f, 0x080c, 0x8a2f, 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, 0x8d2e, 0x2100, 0xaa8c, 0x9210, 0xaa8e, 0x1220, - 0xa890, 0x9081, 0x0000, 0xa892, 0x000e, 0x009e, 0x0126, 0x2091, - 0x8000, 0x78a2, 0x701a, 0x080c, 0x8bfd, 0x012e, 0x0005, 0x00e6, - 0x2071, 0x1925, 0x700c, 0x0002, 0x8ac9, 0x8ac9, 0x8ac7, 0x700f, - 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x7030, 0x9005, - 0x0508, 0x2078, 0x7814, 0x2048, 0xae88, 0x00b6, 0x2059, 0x0000, - 0x080c, 0x8b36, 0x00be, 0x01b0, 0x00e6, 0x2071, 0x193e, 0x080c, - 0x8b7d, 0x00ee, 0x0178, 0x0096, 0x080c, 0x1027, 0x2900, 0x009e, - 0x0148, 0xa8aa, 0x04b9, 0x0041, 0x2001, 0x1948, 0x2003, 0x0000, - 0x012e, 0x08c8, 0x012e, 0x0005, 0x00d6, 0x00c6, 0x0086, 0x00a6, - 0x2940, 0x2650, 0x2600, 0x9005, 0x0180, 0xa864, 0x9084, 0x000f, - 0x2068, 0x9d88, 0x20f0, 0x2165, 0x0056, 0x2029, 0x0000, 0x080c, - 0x8cb3, 0x080c, 0x20a8, 0x1dd8, 0x005e, 0x00ae, 0x2001, 0x187f, - 0x2004, 0xa88a, 0x080c, 0x1768, 0x781f, 0x0101, 0x7813, 0x0000, - 0x0126, 0x2091, 0x8000, 0x080c, 0x8b8c, 0x012e, 0x008e, 0x00ce, - 0x00de, 0x0005, 0x7030, 0x9005, 0x0138, 0x2078, 0x780c, 0x7032, - 0x2001, 0x1948, 0x2003, 0x0001, 0x0005, 0x00e6, 0x2071, 0x1925, - 0x7030, 0x600e, 0x2c00, 0x7032, 0x00ee, 0x0005, 0x00d6, 0x00c6, - 0x0026, 0x9b80, 0x8dfc, 0x2005, 0x906d, 0x090c, 0x0dc5, 0x9b80, - 0x8df4, 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, 0x4be9, 0x684c, 0x0096, - 0x904d, 0x090c, 0x0dc5, 0xa804, 0x8000, 0xa806, 0x009e, 0x9006, - 0x2030, 0x0c20, 0x6854, 0xd08c, 0x1d08, 0xc08d, 0x6856, 0x2011, - 0x8025, 0x080c, 0x4be9, 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, 0x193e, 0x6804, 0x9080, 0x1940, 0x2f08, - 0x2102, 0x6904, 0x8108, 0x9182, 0x0008, 0x0208, 0x900e, 0x6906, - 0x9180, 0x1940, 0x2003, 0x0000, 0x00de, 0x0005, 0x0096, 0x00c6, - 0x2060, 0x6014, 0x2048, 0xa8a8, 0x0096, 0x2048, 0x9005, 0x190c, - 0x1040, 0x009e, 0xa8ab, 0x0000, 0x080c, 0x0fc0, 0x080c, 0xb101, - 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, 0x8f31, 0x00be, 0x6013, 0x0000, 0x601b, 0x0000, 0x0010, - 0x2c00, 0x0861, 0x0005, 0x2009, 0x1929, 0x210c, 0xd194, 0x0005, - 0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, 0x1925, 0x7110, 0xc194, - 0xd19c, 0x1118, 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, 0x8d7c, 0x0170, 0x080c, 0x8db1, 0x0158, - 0x2900, 0x7002, 0x700a, 0x701a, 0x7013, 0x0001, 0x701f, 0x000a, - 0x00de, 0x009e, 0x0005, 0x900e, 0x0cd8, 0x00e6, 0x0096, 0x0086, - 0x00d6, 0x00c6, 0x2071, 0x1932, 0x721c, 0x2100, 0x9202, 0x1618, - 0x080c, 0x8db1, 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, 0x1932, 0x7300, 0x831f, 0x831e, 0x831e, - 0x9384, 0x003f, 0x20e8, 0x939c, 0xffc0, 0x9398, 0x0003, 0x7104, - 0x080c, 0x8d2e, 0x810c, 0x2100, 0x9318, 0x8003, 0x2228, 0x2021, - 0x0078, 0x9402, 0x9532, 0x0208, 0x2028, 0x2500, 0x8004, 0x20a8, - 0x23a0, 0xa001, 0xa001, 0x4005, 0x2508, 0x080c, 0x8d37, 0x2130, - 0x7014, 0x9600, 0x7016, 0x2600, 0x711c, 0x9102, 0x701e, 0x7004, - 0x9600, 0x2008, 0x9082, 0x000a, 0x1190, 0x7000, 0x2048, 0xa800, - 0x9005, 0x1148, 0x2009, 0x0001, 0x0026, 0x080c, 0x8c25, 0x002e, - 0x7000, 0x2048, 0xa800, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, - 0x2500, 0x9212, 0x1904, 0x8c64, 0x012e, 0x00ee, 0x014e, 0x013e, - 0x015e, 0x009e, 0x0005, 0x0016, 0x0026, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x9580, 0x8df4, 0x2005, 0x9075, 0x090c, 0x0dc5, 0x080c, - 0x8d09, 0x012e, 0x9580, 0x8df0, 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, 0x8cf3, 0x8cf3, 0x8cf5, 0x8cf3, 0x8cf5, - 0x8cf3, 0x8cf3, 0x8cf3, 0x8cf3, 0x8cf3, 0x8cfb, 0x8cf3, 0x8cfb, - 0x8cf3, 0x8cf3, 0x8cf3, 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, 0x8dc0, - 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, 0x8d7a, 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, 0x8df8, 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, - 0x1a68, 0x0000, 0x0000, 0x0000, 0x1932, 0x0000, 0x0000, 0x0000, - 0x1888, 0x0000, 0x0000, 0x0000, 0x1877, 0x0000, 0x0000, 0x0000, - 0x00e6, 0x00c6, 0x00b6, 0x00a6, 0xa8a8, 0x2040, 0x2071, 0x1877, - 0x080c, 0x8f1c, 0xa067, 0x0023, 0x6010, 0x905d, 0x0904, 0x8ef1, - 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, 0x20f0, 0x2c65, 0x9786, 0x0024, - 0x2c05, 0x1590, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, - 0x0002, 0x8e5c, 0x8e5c, 0x8e5e, 0x8e5c, 0x8e5c, 0x8e5c, 0x8e60, - 0x8e5c, 0x8e5c, 0x8e5c, 0x8e62, 0x8e5c, 0x8e5c, 0x8e5c, 0x8e64, - 0x8e5c, 0x8e5c, 0x8e5c, 0x8e66, 0x8e5c, 0x8e5c, 0x8e5c, 0x8e68, - 0x8e5c, 0x8e5c, 0x8e5c, 0x8e6a, 0x080c, 0x0dc5, 0xa180, 0x04b8, - 0xa190, 0x04a8, 0xa1a0, 0x0498, 0xa1b0, 0x0488, 0xa1c0, 0x0478, - 0xa1d0, 0x0468, 0xa1e0, 0x0458, 0x908a, 0x0034, 0x1a0c, 0x0dc5, - 0x9082, 0x001b, 0x0002, 0x8e8e, 0x8e8c, 0x8e8c, 0x8e8c, 0x8e8c, - 0x8e8c, 0x8e90, 0x8e8c, 0x8e8c, 0x8e8c, 0x8e8c, 0x8e8c, 0x8e92, - 0x8e8c, 0x8e8c, 0x8e8c, 0x8e8c, 0x8e8c, 0x8e94, 0x8e8c, 0x8e8c, - 0x8e8c, 0x8e8c, 0x8e8c, 0x8e96, 0x080c, 0x0dc5, 0xa180, 0x0038, - 0xa198, 0x0028, 0xa1b0, 0x0018, 0xa1c8, 0x0008, 0xa1e0, 0x2600, - 0x0002, 0x8eb2, 0x8eb4, 0x8eb6, 0x8eb8, 0x8eba, 0x8ebc, 0x8ebe, - 0x8ec0, 0x8ec2, 0x8ec4, 0x8ec6, 0x8ec8, 0x8eca, 0x8ecc, 0x8ece, - 0x8ed0, 0x8ed2, 0x8ed4, 0x8ed6, 0x8ed8, 0x8eda, 0x8edc, 0x8ede, - 0x8ee0, 0x8ee2, 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, 0x20a8, - 0x090c, 0x0dc5, 0x0804, 0x8e36, 0x00ae, 0x00be, 0x00ce, 0x00ee, - 0x0005, 0xa86c, 0xa06e, 0xa870, 0xa072, 0xa077, 0x00ff, 0x9006, - 0x0804, 0x8e18, 0x0006, 0x0016, 0x00b6, 0x6010, 0x2058, 0xb810, - 0x9005, 0x01b0, 0x2001, 0x1926, 0x2004, 0x9005, 0x0188, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0xbba0, - 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4be9, 0x004e, 0x003e, - 0x00be, 0x001e, 0x000e, 0x0005, 0x9016, 0x710c, 0xa834, 0x910a, - 0xa936, 0x7008, 0x9005, 0x0120, 0x8210, 0x910a, 0x0238, 0x0130, - 0x7010, 0x8210, 0x910a, 0x0210, 0x0108, 0x0cd8, 0xaa8a, 0xa26a, - 0x0005, 0x00f6, 0x00d6, 0x0036, 0x2079, 0x0300, 0x781b, 0x0200, - 0x7818, 0xd094, 0x1dd8, 0x781b, 0x0202, 0xa001, 0xa001, 0x7818, - 0xd094, 0x1da0, 0xb8ac, 0x9005, 0x01b8, 0x2068, 0x2079, 0x0000, - 0x2c08, 0x911e, 0x1118, 0x680c, 0xb8ae, 0x0060, 0x9106, 0x0140, - 0x2d00, 0x2078, 0x680c, 0x9005, 0x090c, 0x0dc5, 0x2068, 0x0cb0, - 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, 0x8f71, - 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, 0xd094, 0x1d90, 0xb8ac, - 0x9005, 0x01e8, 0x2060, 0x600c, 0xb8ae, 0x6024, 0xc08d, 0x6026, - 0x6003, 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, 0x601f, 0x0101, - 0x6014, 0x2048, 0xa88b, 0x0000, 0xa8a8, 0xa8ab, 0x0000, 0x904d, - 0x090c, 0x0dc5, 0x080c, 0x1040, 0x080c, 0x8b2d, 0x0c00, 0x2071, - 0x0300, 0x701b, 0x0200, 0x015e, 0x012e, 0x003e, 0x00ce, 0x009e, - 0x00de, 0x00ee, 0x0005, 0x00c6, 0x00b6, 0x0016, 0x0006, 0x0156, - 0x080c, 0x2894, 0x015e, 0x11b0, 0x080c, 0x66b2, 0x190c, 0x0dc5, - 0x000e, 0x001e, 0xb912, 0xb816, 0x080c, 0xb0ab, 0x0140, 0x2b00, - 0x6012, 0x6023, 0x0001, 0x2009, 0x0001, 0x080c, 0xb180, 0x00be, - 0x00ce, 0x0005, 0x000e, 0x001e, 0x0cd0, 0x0066, 0x6000, 0x90b2, - 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, 0x0005, 0x8fe6, 0x8fe6, - 0x8fe6, 0x8fe8, 0x9039, 0x8fe6, 0x8fe6, 0x8fe6, 0x90a0, 0x8fe6, - 0x90dd, 0x8fe6, 0x8fe6, 0x8fe6, 0x8fe6, 0x8fe6, 0x080c, 0x0dc5, - 0x9182, 0x0040, 0x0002, 0x8ffb, 0x8ffb, 0x8ffb, 0x8ffb, 0x8ffb, - 0x8ffb, 0x8ffb, 0x8ffb, 0x8ffb, 0x8ffd, 0x9012, 0x8ffb, 0x8ffb, - 0x8ffb, 0x8ffb, 0x9025, 0x080c, 0x0dc5, 0x0096, 0x080c, 0x989d, - 0x080c, 0x9a0f, 0x6114, 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, - 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, 0x6bd5, 0x080c, 0xb101, - 0x009e, 0x0005, 0x080c, 0x989d, 0x00d6, 0x6114, 0x080c, 0xce56, - 0x0130, 0x0096, 0x6114, 0x2148, 0x080c, 0x6dd1, 0x009e, 0x00de, - 0x080c, 0xb101, 0x080c, 0x9a0f, 0x0005, 0x080c, 0x989d, 0x080c, - 0x3246, 0x6114, 0x0096, 0x2148, 0x080c, 0xce56, 0x0120, 0xa87b, - 0x0029, 0x080c, 0x6dd1, 0x009e, 0x080c, 0xb101, 0x080c, 0x9a0f, - 0x0005, 0x601b, 0x0000, 0x9182, 0x0040, 0x0096, 0x0002, 0x9054, - 0x9054, 0x9054, 0x9054, 0x9054, 0x9054, 0x9054, 0x9054, 0x9056, - 0x9054, 0x9054, 0x9054, 0x909c, 0x9054, 0x9054, 0x9054, 0x9054, - 0x9054, 0x9054, 0x905d, 0x9054, 0x080c, 0x0dc5, 0x6114, 0x2148, - 0xa938, 0x918e, 0xffff, 0x0904, 0x909c, 0x6024, 0xd08c, 0x15c0, - 0x00e6, 0x6114, 0x2148, 0x080c, 0x8e00, 0x0096, 0xa8a8, 0x2048, - 0x080c, 0x6b6d, 0x009e, 0xa8ab, 0x0000, 0x6010, 0x9005, 0x0128, - 0x00b6, 0x2058, 0x080c, 0x8f31, 0x00be, 0xae88, 0x00b6, 0x2059, - 0x0000, 0x080c, 0x8b36, 0x00be, 0x01e0, 0x2071, 0x193e, 0x080c, - 0x8b7d, 0x01b8, 0x9086, 0x0001, 0x1128, 0x2001, 0x1948, 0x2004, - 0x9005, 0x1178, 0x0096, 0x080c, 0x100e, 0x2900, 0x009e, 0x0148, - 0xa8aa, 0x00f6, 0x2c78, 0x080c, 0x8af4, 0x00fe, 0x00ee, 0x009e, - 0x0005, 0x080c, 0x8b2d, 0x0cd0, 0x080c, 0x914a, 0x009e, 0x0005, - 0x9182, 0x0040, 0x0096, 0x0002, 0x90b4, 0x90b4, 0x90b4, 0x90b6, - 0x90b4, 0x90b4, 0x90b4, 0x90db, 0x90b4, 0x90b4, 0x90b4, 0x90b4, - 0x90b4, 0x90b4, 0x90b4, 0x90b4, 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, - 0x1c09, 0x080c, 0x93a0, 0x0126, 0x2091, 0x8000, 0x080c, 0x9a0f, - 0x012e, 0x009e, 0x0005, 0x080c, 0x0dc5, 0x080c, 0x989d, 0x080c, - 0x9a0f, 0x6114, 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, - 0xb8bb, 0x0500, 0x00be, 0x080c, 0x6dd1, 0x080c, 0xb101, 0x009e, - 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0096, 0x0013, - 0x009e, 0x0005, 0x910a, 0x910a, 0x910a, 0x910c, 0x911d, 0x910a, - 0x910a, 0x910a, 0x910a, 0x910a, 0x910a, 0x910a, 0x910a, 0x910a, - 0x910a, 0x910a, 0x080c, 0x0dc5, 0x080c, 0xaa59, 0x6114, 0x2148, - 0xa87b, 0x0006, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, - 0x080c, 0x6dd1, 0x080c, 0xb101, 0x0005, 0x0461, 0x0005, 0x6000, + 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, - 0x9138, 0x9138, 0x9138, 0x913a, 0x914a, 0x9138, 0x9138, 0x9138, - 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, 0x9138, - 0x080c, 0x0dc5, 0x0036, 0x00e6, 0x2071, 0x19e9, 0x703c, 0x9c06, - 0x1120, 0x2019, 0x0000, 0x080c, 0xa877, 0x080c, 0xaa59, 0x00ee, - 0x003e, 0x0005, 0x6024, 0xd08c, 0x11f0, 0x00f6, 0x00e6, 0x601b, - 0x0000, 0x6014, 0x2048, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, - 0x080c, 0x8f31, 0x00be, 0x2071, 0x193e, 0x080c, 0x8b7d, 0x0160, - 0x2001, 0x187f, 0x2004, 0xa88a, 0x2031, 0x0000, 0x2c78, 0x080c, - 0x8af4, 0x00ee, 0x00fe, 0x0005, 0x0096, 0xa88b, 0x0000, 0xa8a8, - 0x2048, 0x080c, 0x1040, 0x009e, 0xa8ab, 0x0000, 0x080c, 0x8b2d, - 0x0c80, 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, 0x9192, 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, 0x91bc, 0x0028, 0x911a, 0x2308, 0x8210, - 0x1f04, 0x91bc, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, 0x000e, - 0x015e, 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, 0x1000, - 0x0ca8, 0x0126, 0x2091, 0x2800, 0x2079, 0x19e9, 0x012e, 0x00d6, - 0x2069, 0x19e9, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, 0x20e9, - 0x0000, 0x2069, 0x0200, 0x080c, 0xadbc, 0x0401, 0x080c, 0xada7, - 0x00e9, 0x080c, 0xadaa, 0x00d1, 0x080c, 0xadad, 0x00b9, 0x080c, - 0xadb0, 0x00a1, 0x080c, 0xadb3, 0x0089, 0x080c, 0xadb6, 0x0071, - 0x080c, 0xadb9, 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, 0x922f, 0x9253, 0x9294, - 0x9235, 0x9253, 0x922f, 0x922d, 0x922d, 0x080c, 0x0dc5, 0x080c, - 0x878f, 0x080c, 0x98ed, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, - 0x00ce, 0x0005, 0x2011, 0x5f90, 0x080c, 0x8709, 0x7828, 0x9092, - 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, 0x5fd0, 0x0c88, 0x62c0, - 0x080c, 0xaef8, 0x080c, 0x5f90, 0x7807, 0x0003, 0x7827, 0x0000, - 0x782b, 0x0000, 0x0c28, 0x080c, 0x878f, 0x6220, 0xd2a4, 0x0170, - 0xd2cc, 0x0160, 0x782b, 0x0000, 0x7824, 0x9065, 0x090c, 0x0dc5, - 0x2009, 0x0013, 0x080c, 0xb180, 0x00ce, 0x0005, 0x00c6, 0x7824, - 0x9065, 0x090c, 0x0dc5, 0x7828, 0x9092, 0xc350, 0x12c0, 0x8000, - 0x782a, 0x00ce, 0x080c, 0x2be7, 0x0278, 0x00c6, 0x7924, 0x2160, - 0x6010, 0x906d, 0x090c, 0x0dc5, 0x7807, 0x0000, 0x7827, 0x0000, - 0x00ce, 0x080c, 0x98ed, 0x0c00, 0x080c, 0xa4f3, 0x08e8, 0x2011, - 0x0130, 0x2214, 0x080c, 0xaef8, 0x080c, 0xee0f, 0x2009, 0x0014, - 0x080c, 0xb180, 0x00ce, 0x0880, 0x2001, 0x1a05, 0x2003, 0x0000, - 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0x9065, 0x090c, - 0x0dc5, 0x2009, 0x0013, 0x080c, 0xb1d2, 0x00ce, 0x0005, 0x00b6, - 0x00c6, 0x00d6, 0x7824, 0x9005, 0x090c, 0x0dc5, 0x7828, 0x9092, - 0xc350, 0x1648, 0x8000, 0x782a, 0x00de, 0x00ce, 0x00be, 0x080c, - 0x2be7, 0x02f0, 0x00b6, 0x00c6, 0x00d6, 0x781c, 0x905d, 0x090c, - 0x0dc5, 0xb800, 0xc0dc, 0xb802, 0x7924, 0x2160, 0x080c, 0xb101, - 0xb93c, 0x81ff, 0x090c, 0x0dc5, 0x8109, 0xb93e, 0x7807, 0x0000, - 0x7827, 0x0000, 0x00de, 0x00ce, 0x00be, 0x080c, 0x98ed, 0x0868, - 0x080c, 0xa4f3, 0x0850, 0x2011, 0x0130, 0x2214, 0x080c, 0xaef8, - 0x080c, 0xee0f, 0x7824, 0x9065, 0x2009, 0x0014, 0x080c, 0xb180, - 0x00de, 0x00ce, 0x00be, 0x0804, 0x92a5, 0x00c6, 0x2001, 0x009b, - 0x2004, 0xd0fc, 0x190c, 0x1f14, 0x6024, 0x6027, 0x0002, 0xd0f4, - 0x15b8, 0x62c8, 0x60c4, 0x9205, 0x1170, 0x783c, 0x9065, 0x0130, - 0x2009, 0x0049, 0x080c, 0xb180, 0x00ce, 0x0005, 0x2011, 0x1a08, - 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, 0xb180, 0x0868, 0x7848, - 0xc085, 0x784a, 0x0848, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0x19e9, 0x6020, 0x8000, - 0x6022, 0x6010, 0x9005, 0x0148, 0x9080, 0x0003, 0x2102, 0x6112, - 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, - 0x00d6, 0x2069, 0x19e9, 0xb800, 0xd0d4, 0x0168, 0x6820, 0x8000, - 0x6822, 0x9086, 0x0001, 0x1110, 0x2b00, 0x681e, 0x00de, 0x0804, - 0x98ed, 0x00de, 0x0005, 0xc0d5, 0xb802, 0x6818, 0x9005, 0x0168, - 0xb856, 0xb85b, 0x0000, 0x0086, 0x0006, 0x2b00, 0x681a, 0x008e, - 0xa05a, 0x008e, 0x2069, 0x19e9, 0x0c08, 0xb856, 0xb85a, 0x2b00, - 0x681a, 0x681e, 0x08d8, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0x19e9, 0x6020, 0x8000, - 0x6022, 0x6008, 0x9005, 0x0148, 0x9080, 0x0003, 0x2102, 0x610a, - 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, - 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, 0x19e9, 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, 0x19e9, 0x7638, 0x2660, 0x2678, 0x2091, - 0x8000, 0x8cff, 0x0904, 0x942f, 0x6010, 0x2058, 0xb8a0, 0x9206, - 0x1904, 0x942a, 0x87ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x942a, - 0x703c, 0x9c06, 0x1178, 0x0036, 0x2019, 0x0001, 0x080c, 0xa877, - 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, 0xce56, 0x01f0, 0x6014, - 0x2048, 0x6020, 0x9086, 0x0003, 0x15b8, 0x6004, 0x9086, 0x0040, - 0x090c, 0xaa49, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, - 0x0036, 0x0076, 0x080c, 0xd14c, 0x080c, 0xed00, 0x080c, 0x6dd1, - 0x007e, 0x003e, 0x001e, 0x080c, 0xd041, 0x080c, 0xb134, 0x00ce, - 0x0804, 0x93c9, 0x2c78, 0x600c, 0x2060, 0x0804, 0x93c9, 0x85ff, - 0x0120, 0x0036, 0x080c, 0x9a0f, 0x003e, 0x012e, 0x000e, 0x001e, - 0x002e, 0x003e, 0x005e, 0x006e, 0x007e, 0x009e, 0x00be, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, - 0x0016, 0x0036, 0x0076, 0x080c, 0xed00, 0x080c, 0xe948, 0x007e, - 0x003e, 0x001e, 0x0890, 0x6020, 0x9086, 0x0009, 0x1168, 0xa87b, - 0x0006, 0x0016, 0x0036, 0x0076, 0x080c, 0x6dd1, 0x080c, 0xb101, - 0x007e, 0x003e, 0x001e, 0x0818, 0x6020, 0x9086, 0x000a, 0x0904, - 0x9414, 0x0804, 0x940d, 0x0006, 0x0066, 0x0096, 0x00c6, 0x00d6, - 0x00f6, 0x9036, 0x0126, 0x2091, 0x8000, 0x2079, 0x19e9, 0x7838, - 0x9065, 0x0904, 0x94c0, 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, - 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, 0xa877, 0x7833, - 0x0000, 0x901e, 0x7b3e, 0x7b42, 0x7b46, 0x7b4a, 0x003e, 0x080c, - 0xce56, 0x0548, 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, 0x1590, - 0x3e08, 0x918e, 0x0002, 0x1188, 0x6010, 0x9005, 0x0170, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, 0x6040, 0x9005, 0x11a8, - 0x2001, 0x1989, 0x2004, 0x6042, 0x0080, 0x6004, 0x9086, 0x0040, - 0x090c, 0xaa49, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, - 0x6dc4, 0x080c, 0xd041, 0x080c, 0xb134, 0x000e, 0x0804, 0x9478, - 0x7e3a, 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x009e, 0x006e, - 0x000e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xe948, - 0x0c50, 0x6020, 0x9086, 0x0009, 0x1130, 0xab7a, 0x080c, 0x6dd1, - 0x080c, 0xb101, 0x0c10, 0x6020, 0x9086, 0x000a, 0x09a8, 0x0868, - 0x0016, 0x0026, 0x0086, 0x9046, 0x0099, 0x080c, 0x95cb, 0x008e, - 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0x19e9, 0x2091, - 0x8000, 0x080c, 0x9662, 0x080c, 0x96f2, 0x012e, 0x00fe, 0x0005, - 0x00b6, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e9, 0x7614, 0x2660, - 0x2678, 0x8cff, 0x0904, 0x9590, 0x6010, 0x2058, 0xb8a0, 0x9206, - 0x1904, 0x958b, 0x88ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x958b, - 0x7024, 0x9c06, 0x1568, 0x2069, 0x0100, 0x6820, 0xd0a4, 0x0110, - 0xd0cc, 0x1508, 0x080c, 0x878f, 0x080c, 0xa517, 0x68c3, 0x0000, - 0x080c, 0xaa49, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d52, 0x9006, - 0x080c, 0x2d52, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, - 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, 0x0804, 0x958b, - 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, 0xce56, 0x01e8, 0x6020, - 0x9086, 0x0003, 0x1580, 0x080c, 0xd05e, 0x1118, 0x080c, 0xbae2, - 0x0098, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, - 0x0086, 0x080c, 0xd14c, 0x080c, 0xed00, 0x080c, 0x6dd1, 0x008e, - 0x003e, 0x001e, 0x080c, 0xd041, 0x080c, 0xb134, 0x080c, 0xa91f, - 0x00ce, 0x0804, 0x9509, 0x2c78, 0x600c, 0x2060, 0x0804, 0x9509, - 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x009e, 0x00be, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, - 0x0036, 0x0086, 0x080c, 0xed00, 0x080c, 0xe948, 0x008e, 0x003e, - 0x001e, 0x08d0, 0x080c, 0xbae2, 0x6020, 0x9086, 0x0002, 0x1160, - 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0904, 0x9571, 0x9086, - 0x008b, 0x0904, 0x9571, 0x0840, 0x6020, 0x9086, 0x0005, 0x1920, - 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x09c8, 0x9086, 0x008b, - 0x09b0, 0x0804, 0x9584, 0x00b6, 0x00a6, 0x0096, 0x00c6, 0x0006, - 0x0126, 0x2091, 0x8000, 0x9280, 0x1000, 0x2004, 0x905d, 0x0904, - 0x965b, 0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, 0x19e9, 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, 0x6645, - 0x0904, 0x9657, 0x7624, 0x86ff, 0x0904, 0x9646, 0x9680, 0x0005, - 0x2004, 0x9906, 0x15d8, 0x00d6, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x0560, 0x080c, 0x878f, 0x080c, 0xa517, 0x68c3, 0x0000, 0x080c, - 0xaa49, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, - 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d52, 0x9006, 0x080c, - 0x2d52, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, - 0x003e, 0x00de, 0x00c6, 0xb83c, 0x9005, 0x0110, 0x8001, 0xb83e, - 0x2660, 0x080c, 0xb134, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, - 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x95fe, 0x89ff, 0x0158, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd14c, 0x080c, - 0xed00, 0x080c, 0x6dd1, 0x080c, 0xa91f, 0x0804, 0x95fe, 0x006e, - 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, 0x009e, 0x00ae, - 0x00be, 0x0005, 0x0096, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x9036, - 0x7814, 0x9065, 0x0904, 0x96c5, 0x600c, 0x0006, 0x600f, 0x0000, - 0x7824, 0x9c06, 0x1580, 0x2069, 0x0100, 0x6820, 0xd0a4, 0x0110, - 0xd0cc, 0x1508, 0x080c, 0x878f, 0x080c, 0xa517, 0x68c3, 0x0000, - 0x080c, 0xaa49, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d52, 0x9006, - 0x080c, 0x2d52, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, - 0x0001, 0x003e, 0x0040, 0x080c, 0x6a2a, 0x1520, 0x6003, 0x0009, - 0x630a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, 0xce54, 0x01b0, - 0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xd05e, 0x1118, 0x080c, - 0xbae2, 0x0060, 0x080c, 0x6a2a, 0x1168, 0xa867, 0x0103, 0xab7a, - 0xa877, 0x0000, 0x080c, 0x6dd1, 0x080c, 0xd041, 0x080c, 0xb134, - 0x080c, 0xa91f, 0x000e, 0x0804, 0x9669, 0x7e16, 0x7e12, 0x00de, - 0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, - 0x1118, 0x080c, 0xe948, 0x0c50, 0x080c, 0xbae2, 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, 0x9772, 0xb854, 0x0006, 0x9006, 0xb856, - 0xb85a, 0xb800, 0xc0d4, 0xc0dc, 0xb802, 0x080c, 0x6645, 0x0904, - 0x976f, 0x7e24, 0x86ff, 0x0904, 0x9762, 0x9680, 0x0005, 0x2004, - 0x9906, 0x1904, 0x9762, 0x00d6, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x0904, 0x9759, 0x080c, 0x878f, 0x080c, 0xa517, 0x68c3, 0x0000, - 0x080c, 0xaa49, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d52, 0x9006, - 0x080c, 0x2d52, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, - 0x0001, 0x003e, 0x00de, 0x00c6, 0x3e08, 0x918e, 0x0002, 0x1168, - 0xb800, 0xd0bc, 0x0150, 0x9680, 0x0010, 0x200c, 0x81ff, 0x1518, - 0x2009, 0x1989, 0x210c, 0x2102, 0x00f0, 0xb83c, 0x9005, 0x0110, - 0x8001, 0xb83e, 0x2660, 0x600f, 0x0000, 0x080c, 0xb134, 0x00ce, + 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, 0x9705, 0x89ff, 0x0138, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x080c, 0x6dd1, 0x080c, 0xa91f, 0x0804, 0x9705, 0x000e, - 0x0804, 0x96f9, 0x781e, 0x781a, 0x00de, 0x00ce, 0x00be, 0x009e, - 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, 0x0066, 0xb800, - 0xd0dc, 0x01a0, 0xb84c, 0x904d, 0x0188, 0xa878, 0x9606, 0x1170, - 0x2071, 0x19e9, 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, 0xa517, 0x78c3, 0x0000, 0x080c, 0xaa49, 0x7027, 0x0000, - 0x0036, 0x2079, 0x0140, 0x7b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2d52, 0x9006, 0x080c, 0x2d52, 0x2079, 0x0100, - 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0xaa49, 0x003e, - 0x080c, 0x6645, 0x00c6, 0xb83c, 0x9005, 0x0110, 0x8001, 0xb83e, - 0x2660, 0x080c, 0xb101, 0x00ce, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x080c, 0xd14c, 0x080c, 0x6dd1, 0x080c, 0xa91f, 0x00fe, - 0x0005, 0x00b6, 0x00e6, 0x00c6, 0x2011, 0x0101, 0x2204, 0xc0c4, - 0x2012, 0x2001, 0x180c, 0x2014, 0xc2e4, 0x2202, 0x2071, 0x19e9, - 0x7004, 0x9084, 0x0007, 0x0002, 0x97fe, 0x9802, 0x9820, 0x9849, - 0x9887, 0x97fe, 0x9819, 0x97fc, 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, 0x6645, 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, 0x98ed, 0x0ca8, 0x7218, - 0x721e, 0x080c, 0x98ed, 0x0c80, 0xc2ec, 0x2202, 0x080c, 0x9a0f, - 0x0c58, 0x7024, 0x9065, 0x05b8, 0x700c, 0x9c06, 0x1160, 0x080c, - 0xa91f, 0x600c, 0x9015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0448, - 0x720e, 0x720a, 0x0430, 0x7014, 0x9c06, 0x1160, 0x080c, 0xa91f, - 0x600c, 0x9015, 0x0120, 0x7216, 0x600f, 0x0000, 0x00d0, 0x7216, - 0x7212, 0x00b8, 0x6020, 0x9086, 0x0003, 0x1198, 0x6010, 0x2058, - 0x080c, 0x6645, 0xb800, 0xc0dc, 0xb802, 0x080c, 0xa91f, 0x701c, - 0x9065, 0x0138, 0xb854, 0x9015, 0x0110, 0x721e, 0x0010, 0x7218, - 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x7024, - 0x9065, 0x0140, 0x080c, 0xa91f, 0x600c, 0x9015, 0x0158, 0x720e, - 0x600f, 0x0000, 0x080c, 0xaa49, 0x7027, 0x0000, 0x00ce, 0x00ee, - 0x00be, 0x0005, 0x720e, 0x720a, 0x0ca8, 0x00d6, 0x2069, 0x19e9, - 0x6830, 0x9084, 0x0003, 0x0002, 0x98aa, 0x98ac, 0x98d0, 0x98a8, - 0x080c, 0x0dc5, 0x00de, 0x0005, 0x00c6, 0x6840, 0x9086, 0x0001, - 0x01b8, 0x683c, 0x9065, 0x0130, 0x600c, 0x9015, 0x0170, 0x6a3a, - 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, 0x1a08, - 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, 0x9a0f, 0x2001, 0x19f5, - 0x2004, 0x9086, 0x0001, 0x0d58, 0x00d6, 0x2069, 0x19e9, 0x6804, - 0x9084, 0x0007, 0x0006, 0x9005, 0x11c8, 0x2001, 0x1837, 0x2004, - 0x9084, 0x0028, 0x1198, 0x2001, 0x197d, 0x2004, 0x9086, 0xaaaa, - 0x0168, 0x2001, 0x188b, 0x2004, 0xd08c, 0x1118, 0xd084, 0x1118, - 0x0028, 0x080c, 0x9a0f, 0x000e, 0x00de, 0x0005, 0x000e, 0x0002, - 0x992a, 0x99e3, 0x99e3, 0x99e3, 0x99e3, 0x99e5, 0x99e3, 0x9928, - 0x080c, 0x0dc5, 0x6820, 0x9005, 0x1110, 0x00de, 0x0005, 0x00c6, - 0x680c, 0x9065, 0x01f0, 0x6104, 0x918e, 0x0040, 0x1180, 0x2009, - 0x1837, 0x210c, 0x918c, 0x0028, 0x1150, 0x080c, 0x7569, 0x0138, - 0x0006, 0x2009, 0x188b, 0x2104, 0xc095, 0x200a, 0x000e, 0x6807, - 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x9ab8, 0x00ce, 0x00de, - 0x0005, 0x6814, 0x9065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, - 0x0000, 0x080c, 0x9ab8, 0x00ce, 0x00de, 0x0005, 0x00b6, 0x00e6, - 0x6a1c, 0x92dd, 0x0000, 0x0904, 0x99cd, 0xb84c, 0x900d, 0x0118, - 0xb888, 0x9005, 0x01a0, 0xb854, 0x905d, 0x0120, 0x920e, 0x0904, - 0x99cd, 0x0028, 0x6818, 0x920e, 0x0904, 0x99cd, 0x2058, 0xb84c, - 0x900d, 0x0d88, 0xb888, 0x9005, 0x1d70, 0x2b00, 0x681e, 0xbb3c, - 0xb838, 0x9302, 0x1e40, 0x080c, 0xb0d8, 0x0904, 0x99cd, 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, 0xa047, 0x2069, 0x19e9, - 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, 0x6645, 0x080c, 0xaf18, 0x00ee, 0x00be, - 0x00ce, 0x00de, 0x0005, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, - 0x01d8, 0x6104, 0x918e, 0x0040, 0x1180, 0x2009, 0x1837, 0x210c, - 0x918c, 0x0028, 0x1150, 0x080c, 0x7569, 0x0138, 0x0006, 0x2009, - 0x188b, 0x2104, 0xc095, 0x200a, 0x000e, 0x6807, 0x0004, 0x6826, - 0x682b, 0x0000, 0x080c, 0x9ab8, 0x00ce, 0x00de, 0x0005, 0x2001, - 0x180c, 0x2014, 0xc2ed, 0x2202, 0x00de, 0x00fe, 0x0005, 0x00f6, - 0x00d6, 0x2069, 0x19e9, 0x6830, 0x9086, 0x0000, 0x1570, 0x2001, - 0x180c, 0x2014, 0xd2e4, 0x0130, 0xc2e4, 0x2202, 0x080c, 0x98fc, - 0x2069, 0x19e9, 0x2001, 0x180c, 0x200c, 0xd1c4, 0x1508, 0x6838, - 0x907d, 0x01d8, 0x6a04, 0x9296, 0x0000, 0x1904, 0x9aac, 0x7920, - 0x918e, 0x0009, 0x0568, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, - 0x684b, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, - 0x1ca2, 0x1158, 0x012e, 0x080c, 0xa374, 0x00de, 0x00fe, 0x0005, - 0xc1c4, 0x2102, 0x080c, 0x7616, 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, - 0x1ca2, 0x19d8, 0x012e, 0x080c, 0xa2f5, 0x0878, 0x2001, 0x1837, - 0x2004, 0x9084, 0x0028, 0x1188, 0x2001, 0x197d, 0x2004, 0x9086, - 0xaaaa, 0x0158, 0x2001, 0x19ea, 0x2004, 0x9005, 0x11f0, 0x2001, - 0x188b, 0x200c, 0xc185, 0xc18c, 0x2102, 0x2f00, 0x6833, 0x0001, - 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, 0x2091, - 0x2400, 0x002e, 0x080c, 0x1ca2, 0x1904, 0x9a4d, 0x012e, 0x6a3c, - 0x2278, 0x080c, 0xa27f, 0x0804, 0x9a45, 0x2011, 0x188b, 0x2204, - 0xc08d, 0x2012, 0x0804, 0x9a45, 0x6a04, 0x9296, 0x0006, 0x1904, - 0x9a07, 0x6a30, 0x9296, 0x0000, 0x0904, 0x9a2f, 0x0804, 0x9a07, - 0x6020, 0x9084, 0x000f, 0x000b, 0x0005, 0x9acc, 0x9ad1, 0x9f77, - 0xa010, 0x9ad1, 0x9f77, 0xa010, 0x9acc, 0x9ad1, 0x9acc, 0x9acc, - 0x9acc, 0x9acc, 0x9acc, 0x9acc, 0x080c, 0x97e1, 0x080c, 0x98ed, - 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, 0x9b3d, 0x005b, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, - 0x015e, 0x00be, 0x0005, 0x9ce6, 0x9d21, 0x9d4a, 0x9e06, 0x9e28, - 0x9e2e, 0x9e3b, 0x9e43, 0x9e4f, 0x9e55, 0x9e66, 0x9e55, 0x9ebe, - 0x9e43, 0x9eca, 0x9ed0, 0x9e4f, 0x9ed0, 0x9edc, 0x9b3b, 0x9b3b, - 0x9b3b, 0x9b3b, 0x9b3b, 0x9b3b, 0x9b3b, 0x9b3b, 0x9b3b, 0x9b3b, - 0x9b3b, 0xa72e, 0xa751, 0xa762, 0xa782, 0xa7b4, 0x9e3b, 0x9b3b, - 0x9e3b, 0x9e55, 0x9b3b, 0x9d4a, 0x9e06, 0x9b3b, 0xab40, 0x9e55, - 0x9b3b, 0xab5c, 0x9e55, 0x9b3b, 0x9e4f, 0x9ce0, 0x9b5e, 0x9b3b, - 0xab78, 0xabe5, 0xacc0, 0x9b3b, 0xaccd, 0x9e38, 0xacf8, 0x9b3b, - 0xa7be, 0xad25, 0x9b3b, 0x080c, 0x0dc5, 0x2100, 0x005b, 0x00fe, - 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, - 0x00be, 0x0005, 0xadc0, 0xae72, 0x9b5c, 0x9b96, 0x9c42, 0x9c4d, - 0x9b5c, 0x9e3b, 0x9b5c, 0x9ca7, 0x9cb3, 0x9bb1, 0x9b5c, 0x9bcc, - 0x9c00, 0xafdf, 0xb024, 0x9e55, 0x080c, 0x0dc5, 0x00d6, 0x0096, - 0x080c, 0x9eef, 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, 0xa4eb, 0x003e, 0x002e, 0x009e, 0x00de, 0x0005, - 0x7810, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x080c, 0xb06b, 0x1118, - 0x9084, 0xff80, 0x0110, 0x9085, 0x0001, 0x0005, 0x00d6, 0x0096, - 0x080c, 0x9eef, 0x7003, 0x0500, 0x7814, 0x2048, 0xa874, 0x700a, - 0xa878, 0x700e, 0xa87c, 0x7012, 0xa880, 0x7016, 0xa884, 0x701a, - 0xa888, 0x701e, 0x60c3, 0x0010, 0x080c, 0xa4eb, 0x009e, 0x00de, - 0x0005, 0x00d6, 0x0096, 0x080c, 0x9eef, 0x7003, 0x0500, 0x7814, - 0x2048, 0xa8cc, 0x700a, 0xa8d0, 0x700e, 0xa8d4, 0x7012, 0xa8d8, - 0x7016, 0xa8dc, 0x701a, 0xa8e0, 0x701e, 0x60c3, 0x0010, 0x080c, - 0xa4eb, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, - 0x8000, 0x080c, 0x9eef, 0x20e9, 0x0000, 0x2001, 0x19a5, 0x2003, - 0x0000, 0x7814, 0x2048, 0xa814, 0x8003, 0x60c2, 0xa830, 0x20a8, - 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, 0x2001, 0x19a5, - 0x0016, 0x200c, 0x2001, 0x0001, 0x080c, 0x2417, 0x080c, 0xdbfa, - 0x9006, 0x080c, 0x2417, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, - 0x0c28, 0x04d9, 0x080c, 0xa4eb, 0x012e, 0x009e, 0x00de, 0x0005, - 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0x9f3a, 0x20e9, - 0x0000, 0x2001, 0x19a5, 0x2003, 0x0000, 0x7814, 0x2048, 0xa86f, - 0x0200, 0xa873, 0x0000, 0xa814, 0x8003, 0x60c2, 0xa830, 0x20a8, - 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, 0x2001, 0x19a5, - 0x0016, 0x200c, 0x080c, 0xdbfa, 0x001e, 0xa804, 0x9005, 0x0110, - 0x2048, 0x0c60, 0x0051, 0x7814, 0x2048, 0x080c, 0x0fc0, 0x080c, - 0xa4eb, 0x012e, 0x009e, 0x00de, 0x0005, 0x60c0, 0x8004, 0x9084, - 0x0003, 0x9005, 0x0130, 0x9082, 0x0004, 0x20a3, 0x0000, 0x8000, - 0x1de0, 0x0005, 0x080c, 0x9eef, 0x7003, 0x7800, 0x7808, 0x8007, - 0x700a, 0x60c3, 0x0008, 0x0804, 0xa4eb, 0x00d6, 0x00e6, 0x080c, - 0x9f3a, 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, 0x9c6d, 0x2069, 0x1801, 0x20a9, 0x0004, 0x2d76, 0x8d68, - 0x8e70, 0x1f04, 0x9c76, 0x9096, 0xdf00, 0x0130, 0x9096, 0xe000, - 0x0118, 0x60c3, 0x0018, 0x00f0, 0x2069, 0x19b5, 0x9086, 0xdf00, - 0x0110, 0x2069, 0x19cf, 0x20a9, 0x001a, 0x9e86, 0x0260, 0x1148, - 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000, 0x6012, 0x00ce, 0x2071, - 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68, 0x8e70, 0x1f04, 0x9c8d, - 0x60c3, 0x004c, 0x080c, 0xa4eb, 0x00ee, 0x00de, 0x0005, 0x080c, - 0x9eef, 0x7003, 0x6300, 0x7007, 0x0028, 0x7808, 0x700e, 0x60c3, - 0x0008, 0x0804, 0xa4eb, 0x00d6, 0x0026, 0x0016, 0x080c, 0x9f3a, - 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6, 0x9ef0, 0x0004, 0x2009, - 0x0001, 0x2011, 0x000c, 0x2069, 0x1925, 0x6810, 0xd084, 0x1148, - 0x2073, 0x0500, 0x8e70, 0x2073, 0x0000, 0x8e70, 0x8108, 0x9290, - 0x0004, 0x2073, 0x0800, 0x8e70, 0x2073, 0x0000, 0x00ee, 0x7206, - 0x710a, 0x62c2, 0x080c, 0xa4eb, 0x001e, 0x002e, 0x00de, 0x0005, - 0x2001, 0x1818, 0x2004, 0x609a, 0x0804, 0xa4eb, 0x080c, 0x9eef, - 0x7003, 0x5200, 0x2069, 0x1847, 0x6804, 0xd084, 0x0130, 0x6828, - 0x0016, 0x080c, 0x28c7, 0x710e, 0x001e, 0x20a9, 0x0004, 0x20e1, - 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, - 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x0254, 0x4003, 0x080c, - 0xb06b, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, - 0x2004, 0x7032, 0x2001, 0x1820, 0x2004, 0x7036, 0x0030, 0x2001, - 0x1818, 0x2004, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x001c, 0x0804, - 0xa4eb, 0x080c, 0x9eef, 0x7003, 0x0500, 0x080c, 0xb06b, 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, 0xa4eb, 0x080c, 0x9eef, 0x9006, 0x080c, 0x6a5c, 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, - 0x9dcd, 0x00d6, 0x2069, 0x196d, 0x2001, 0x1837, 0x2004, 0xd0a4, - 0x0188, 0x6800, 0x700a, 0x6808, 0x9084, 0x2000, 0x7012, 0x080c, - 0xb082, 0x680c, 0x7016, 0x701f, 0x2710, 0x6818, 0x7022, 0x681c, - 0x7026, 0x00f0, 0x6800, 0x700a, 0x6804, 0x700e, 0x00f6, 0x2079, - 0x0100, 0x080c, 0x7569, 0x1128, 0x78e3, 0x0000, 0x080c, 0x2908, - 0x78e2, 0x00fe, 0x6808, 0x080c, 0x7569, 0x1118, 0x9084, 0x37ff, - 0x0010, 0x9084, 0x3fff, 0x7012, 0x080c, 0xb082, 0x680c, 0x7016, - 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, - 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, - 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c, 0xada7, 0x2069, 0x1975, - 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002, 0x080c, 0x57d7, 0xd0e4, - 0x0110, 0x680c, 0x700e, 0x00de, 0x04a8, 0x2001, 0x1837, 0x2004, - 0xd0a4, 0x0170, 0x0016, 0x2001, 0x196e, 0x200c, 0x60e0, 0x9106, - 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x2908, 0x61e2, 0x001e, - 0x20e1, 0x0001, 0x2099, 0x196d, 0x20e9, 0x0000, 0x20a1, 0x024e, - 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1805, 0x20a1, - 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, - 0x4003, 0x080c, 0xada7, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x2099, - 0x1975, 0x4003, 0x60c3, 0x0074, 0x0804, 0xa4eb, 0x080c, 0x9eef, - 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, 0x9e9f, 0x7026, 0x60c3, 0x0014, 0x0804, 0xa4eb, - 0x080c, 0x9eef, 0x7003, 0x5000, 0x0804, 0x9d6c, 0x080c, 0x9eef, - 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, 0x0804, 0xa4eb, - 0x080c, 0x9f31, 0x0010, 0x080c, 0x9f3a, 0x7003, 0x0200, 0x60c3, - 0x0004, 0x0804, 0xa4eb, 0x080c, 0x9f3a, 0x7003, 0x0100, 0x700b, - 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0xa4eb, 0x080c, - 0x9f3a, 0x7003, 0x0200, 0x0804, 0x9d6c, 0x080c, 0x9f3a, 0x7003, - 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, 0x0010, 0x700b, 0x0003, - 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa4eb, 0x00d6, 0x080c, - 0x9f3a, 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, + 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, - 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, 0xa4eb, 0x080c, 0x9f3a, - 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, 0x60c3, 0x0014, - 0x0804, 0xa4eb, 0x080c, 0x9f3a, 0x7003, 0x0200, 0x0804, 0x9cea, - 0x080c, 0x9f3a, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, - 0x60c3, 0x0008, 0x0804, 0xa4eb, 0x080c, 0x9f3a, 0x7003, 0x0100, - 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0xa4eb, 0x0026, 0x00d6, - 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0040, 0x0026, - 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x080c, - 0xadbc, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, - 0x687c, 0x700a, 0x6880, 0x700e, 0x9485, 0x0029, 0x7012, 0x004e, - 0x003e, 0x00de, 0x080c, 0xa4d9, 0x721a, 0x9f95, 0x0000, 0x7222, - 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, 0x0026, 0x080c, - 0xadbc, 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, 0xadbc, 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, 0xa4d9, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, - 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0xa4d9, 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, 0x9fa8, 0x9fb7, 0x9fc2, 0x9fa6, 0x9fa6, 0x9fa6, 0x9fa8, - 0x9fa6, 0x9fa6, 0x9fa6, 0x9fa6, 0x9fa6, 0x9fa6, 0x080c, 0x0dc5, - 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x2be7, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804, 0xa4eb, 0x0431, - 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, 0x60c3, 0x000c, - 0x0804, 0xa4eb, 0x04a1, 0x7003, 0x0003, 0x7007, 0x0300, 0x60c3, - 0x0004, 0x0804, 0xa4eb, 0x0026, 0x080c, 0xadbc, 0xb810, 0x9085, - 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, - 0x6880, 0x700e, 0x7013, 0x0009, 0x0804, 0x9f0a, 0x0026, 0x080c, - 0xadbc, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814, 0x7006, 0x2069, - 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, 0x0099, 0x7a20, - 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804, 0x9f6c, 0x0026, - 0x080c, 0xadbc, 0xb810, 0x9085, 0x8500, 0x7002, 0xb814, 0x7006, - 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, 0x0099, - 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804, 0x9f6c, - 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, 0xa047, 0xa10e, 0xa0e1, 0xa230, 0xa045, 0xa045, - 0xa045, 0xa045, 0xa045, 0xa045, 0xa045, 0xa906, 0xa90b, 0xa910, - 0xa915, 0xa045, 0xad04, 0xa045, 0xa901, 0x080c, 0x0dc5, 0x0096, - 0x780b, 0xffff, 0x080c, 0xa0b2, 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, 0x18f1, 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, 0x1a05, 0x2003, 0x07d0, 0x2001, 0x1a04, 0x2003, 0x0009, - 0x009e, 0x0005, 0x6813, 0x0008, 0xba8c, 0x8210, 0xb8cc, 0xd084, - 0x0180, 0x2001, 0x1ad1, 0x200c, 0x8108, 0x2102, 0x2001, 0x1ad0, - 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, 0xa4eb, 0x6813, 0x0008, 0xb810, 0x9085, - 0x0500, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, - 0x6880, 0x700e, 0x7013, 0x0889, 0x080c, 0xa4d9, 0x721a, 0x7a08, - 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x0005, 0x00d6, 0x0096, - 0x080c, 0xa20e, 0x7814, 0x2048, 0x080c, 0xce54, 0x1130, 0x7814, - 0x9084, 0x0700, 0x8007, 0x0033, 0x0010, 0x9006, 0x001b, 0x009e, - 0x00de, 0x0005, 0xa12c, 0xa195, 0xa1a5, 0xa1cb, 0xa1d7, 0xa1e8, - 0xa1f0, 0xa12a, 0x080c, 0x0dc5, 0x0016, 0x0036, 0xa97c, 0x918c, - 0x0003, 0x0118, 0x9186, 0x0003, 0x1198, 0xaba8, 0x7824, 0xd0cc, - 0x1168, 0x7316, 0xa898, 0x701a, 0xa894, 0x701e, 0x003e, 0x001e, - 0x2001, 0x19b3, 0x2004, 0x60c2, 0x0804, 0xa4eb, 0xc3e5, 0x0c88, - 0x9186, 0x0001, 0x190c, 0x0dc5, 0xaba8, 0x7824, 0xd0cc, 0x1904, - 0xa192, 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, 0xa4eb, 0xc3e5, 0x0804, 0xa151, 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, 0xa4eb, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1128, - 0x7216, 0x60c3, 0x0018, 0x0804, 0xa4eb, 0x0cd0, 0xc2e5, 0x2011, - 0x0100, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x702f, 0x0008, - 0x7858, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x0020, 0x0804, 0xa4eb, - 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, 0xa4d9, 0x721a, 0x7a08, 0x7222, 0x2f10, - 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x7013, 0x0889, 0x0c90, - 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, - 0xa240, 0xa240, 0xa242, 0xa240, 0xa240, 0xa240, 0xa25c, 0xa240, - 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, 0xa4eb, 0x2009, 0x0003, 0x0019, 0x7033, - 0x7f00, 0x0cb0, 0x0016, 0x080c, 0xadbc, 0x001e, 0xb810, 0x9085, - 0x0100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6a7c, 0x720a, - 0x6a80, 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, - 0xa4d9, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x0005, 0x00b6, + 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, 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, 0x8794, 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, 0x33ac, 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, 0x8794, 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, 0xa448, 0x90be, 0x000a, 0x1904, - 0xa404, 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, + 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, 0x080c, 0xada1, - 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, - 0x1b58, 0x080c, 0x8794, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, - 0x00ee, 0x009e, 0x00be, 0x0005, 0x7804, 0x9086, 0x0040, 0x0904, - 0xa484, 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, 0xada1, 0x2009, 0x07d0, 0x60c4, 0x9084, - 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x8794, 0x003e, - 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e, 0x00be, 0x0005, - 0x7814, 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0904, - 0xa4a0, 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, 0xad7e, 0x0804, 0xa434, 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, 0xa417, - 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, 0xada1, 0x0804, 0xa434, 0x080c, 0xad7e, 0x0804, - 0xa434, 0x7a10, 0x00b6, 0x2258, 0xba8c, 0x8210, 0x9294, 0x00ff, - 0xba8e, 0x00be, 0x8217, 0x0005, 0x00d6, 0x2069, 0x19e9, 0x6843, - 0x0001, 0x00de, 0x0005, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, - 0x080c, 0x8786, 0x0005, 0x0016, 0x2001, 0x180c, 0x200c, 0x9184, - 0x0600, 0x9086, 0x0600, 0x0128, 0x0089, 0x080c, 0x8786, 0x001e, - 0x0005, 0xc1e5, 0x2001, 0x180c, 0x2102, 0x2001, 0x19ea, 0x2003, - 0x0000, 0x2001, 0x19f2, 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, 0x7569, 0x11c0, - 0x2001, 0x1a05, 0x2004, 0x9005, 0x15d0, 0x080c, 0x7616, 0x1160, - 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, 0x6024, 0xd084, 0x090c, - 0x0dc5, 0x080c, 0x8786, 0x0458, 0x00c6, 0x2061, 0x19e9, 0x00c8, - 0x6904, 0x9194, 0x4000, 0x0540, 0x0811, 0x080c, 0x2d62, 0x00c6, - 0x2061, 0x19e9, 0x6128, 0x9192, 0x0008, 0x1258, 0x8108, 0x612a, - 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x8786, 0x080c, 0xa50e, - 0x0070, 0x6124, 0x91e5, 0x0000, 0x0140, 0x080c, 0xee0f, 0x080c, - 0x878f, 0x2009, 0x0014, 0x080c, 0xb180, 0x00ce, 0x0000, 0x002e, - 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0x1a05, 0x2004, 0x9005, - 0x1db0, 0x00c6, 0x2061, 0x19e9, 0x6128, 0x9192, 0x0003, 0x1e08, - 0x8108, 0x612a, 0x00ce, 0x080c, 0x8786, 0x080c, 0x5fe6, 0x2009, - 0x1846, 0x2114, 0x8210, 0x220a, 0x0c10, 0x0096, 0x00c6, 0x00d6, - 0x00e6, 0x0016, 0x0026, 0x080c, 0x879c, 0x2071, 0x19e9, 0x713c, - 0x81ff, 0x0904, 0xa617, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, - 0x7569, 0x11e0, 0x0036, 0x2019, 0x0002, 0x080c, 0xa877, 0x003e, - 0x713c, 0x2160, 0x080c, 0xee0f, 0x2009, 0x004a, 0x6220, 0x9296, - 0x0009, 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, - 0x080c, 0xb180, 0x080c, 0x7616, 0x0804, 0xa617, 0x080c, 0xa623, - 0x0904, 0xa617, 0x6904, 0xd1f4, 0x0904, 0xa61e, 0x080c, 0x2d62, - 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, 0x2c94, 0x6014, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, - 0x703c, 0x2060, 0x2009, 0x0049, 0x080c, 0xb180, 0x00c0, 0x0036, - 0x2019, 0x0001, 0x080c, 0xa877, 0x003e, 0x713c, 0x2160, 0x080c, - 0xee0f, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, - 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x080c, 0xb180, 0x002e, - 0x001e, 0x00ee, 0x00de, 0x00ce, 0x009e, 0x0005, 0xd1ec, 0x1904, - 0xa5ce, 0x0804, 0xa5d0, 0x00d6, 0x00c6, 0x0096, 0x703c, 0x9065, - 0x090c, 0x0dc5, 0x2001, 0x0306, 0x200c, 0x9184, 0x0030, 0x0904, - 0xa6d6, 0x9184, 0x0048, 0x9086, 0x0008, 0x1904, 0xa6d6, 0x2009, - 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1904, 0xa6d6, - 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, 0xa6d6, 0x2009, 0x1a85, 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, 0x1a6a, 0x2003, 0x0000, 0x2001, 0x1a73, 0x2003, - 0x0000, 0x6a88, 0x698c, 0x2200, 0x9105, 0x1170, 0x0096, 0x6014, - 0x2048, 0xa87c, 0xc0dc, 0xa87e, 0xa880, 0xc0fc, 0xa882, 0x009e, - 0x2c10, 0x080c, 0x1c09, 0x0040, 0x6014, 0x2048, 0xaa3a, 0xa936, - 0x6ac4, 0x69c8, 0xa946, 0xaa4a, 0x0126, 0x00c6, 0x2091, 0x2400, - 0x002e, 0x080c, 0x1ca2, 0x190c, 0x0dc5, 0x012e, 0x0090, 0x2009, - 0x1a86, 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, - 0x8794, 0x9006, 0x009e, 0x00ce, 0x00de, 0x0005, 0x9085, 0x0001, - 0x0cc8, 0x0026, 0x00e6, 0x2071, 0x19e9, 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, 0x19e9, 0x7018, 0x2058, - 0x8bff, 0x0190, 0xb8a0, 0x9406, 0x0118, 0xb854, 0x2058, 0x0cc0, - 0x6014, 0x0096, 0x2048, 0xac6c, 0xad70, 0xae78, 0x009e, 0x080c, - 0x684f, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, 0x004e, 0x005e, - 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, 0x080c, 0x9eef, - 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, - 0xa4eb, 0x080c, 0x9eef, 0x7003, 0x0f00, 0x7808, 0xd09c, 0x0128, - 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, 0x700e, 0x60c3, 0x0008, - 0x0804, 0xa4eb, 0x0156, 0x080c, 0x9f3a, 0x7003, 0x0200, 0x080c, - 0x8818, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, 0xffed, 0x9ef0, - 0x0002, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, - 0x0002, 0x9290, 0x0002, 0x1f04, 0xa771, 0x60c3, 0x001c, 0x015e, - 0x0804, 0xa4eb, 0x0016, 0x0026, 0x080c, 0x9f16, 0x080c, 0x9f28, - 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, 0xa4eb, 0x002e, - 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, 0xada7, 0x20a1, - 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0x9eef, 0x7003, 0x6200, - 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa4eb, 0x0016, 0x0026, - 0x080c, 0x9eef, 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, 0x0096, - 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0023, - 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x4003, 0x8003, - 0x60c2, 0x080c, 0xa4eb, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00c6, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e9, 0x700c, 0x2060, - 0x8cff, 0x0178, 0x080c, 0xd05e, 0x1110, 0x080c, 0xbae2, 0x600c, - 0x0006, 0x080c, 0xd2ca, 0x080c, 0xb101, 0x080c, 0xa91f, 0x00ce, - 0x0c78, 0x2c00, 0x700e, 0x700a, 0x012e, 0x000e, 0x00ce, 0x00ee, + 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, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0x19e9, 0x7024, 0x2060, 0x8cff, 0x01f8, 0x080c, 0xa517, 0x6ac0, - 0x68c3, 0x0000, 0x080c, 0x878f, 0x00c6, 0x2061, 0x0100, 0x080c, - 0xaef8, 0x00ce, 0x20a9, 0x01f4, 0x0461, 0x2009, 0x0013, 0x080c, - 0xb180, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x1800, 0x2004, 0x9096, - 0x0001, 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, 0x878f, 0x6814, - 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, - 0x0000, 0x2011, 0x5f90, 0x080c, 0x8709, 0x20a9, 0x01f4, 0x0009, - 0x08c0, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, - 0x4000, 0x190c, 0x2d62, 0x0090, 0xd084, 0x0118, 0x6827, 0x0001, - 0x0010, 0x1f04, 0xa859, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2d52, 0x9006, 0x080c, 0x2d52, 0x0005, 0x0126, - 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, - 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xdbff, - 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x19e9, 0x703c, - 0x2060, 0x8cff, 0x0904, 0xa8e2, 0x9386, 0x0002, 0x1128, 0x6814, - 0x9084, 0x0002, 0x0904, 0xa8e2, 0x68af, 0x95f5, 0x6817, 0x0010, - 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, 0x0008, 0x080c, - 0x879c, 0x080c, 0x205a, 0x2001, 0x0032, 0x6920, 0xd1bc, 0x0130, - 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, 0x20a9, 0x03e8, - 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, - 0x190c, 0x2d62, 0x0090, 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, - 0x1f04, 0xa8b8, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2d52, 0x9006, 0x080c, 0x2d52, 0x6827, 0x4000, 0x6824, - 0x83ff, 0x1140, 0x2009, 0x0049, 0x6020, 0x9086, 0x0009, 0x0110, - 0x080c, 0xb180, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, - 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, - 0x8000, 0x2069, 0x19e9, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, - 0x0126, 0x2091, 0x8000, 0x2069, 0x19e9, 0x6a32, 0x012e, 0x00de, - 0x0005, 0x080c, 0xa0b2, 0x7047, 0x1000, 0x0098, 0x080c, 0xa0b2, - 0x7047, 0x4000, 0x0070, 0x080c, 0xa0b2, 0x7047, 0x2000, 0x0048, - 0x080c, 0xa0b2, 0x7047, 0x0400, 0x0020, 0x080c, 0xa0b2, 0x7047, - 0x0200, 0x7854, 0x7032, 0x60c3, 0x0020, 0x0804, 0xa4eb, 0x00e6, - 0x2071, 0x19e9, 0x7020, 0x9005, 0x0110, 0x8001, 0x7022, 0x00ee, - 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, - 0x0126, 0x2091, 0x8000, 0x2071, 0x19e9, 0x7614, 0x2660, 0x2678, - 0x2039, 0x0001, 0x87ff, 0x0904, 0xa9c4, 0x8cff, 0x0904, 0xa9c4, - 0x6020, 0x9086, 0x0006, 0x1904, 0xa9bf, 0x88ff, 0x0138, 0x2800, - 0x9c06, 0x1904, 0xa9bf, 0x2039, 0x0000, 0x0050, 0x6010, 0x9b06, - 0x1904, 0xa9bf, 0x85ff, 0x0120, 0x6054, 0x9106, 0x1904, 0xa9bf, - 0x7024, 0x9c06, 0x15b0, 0x2069, 0x0100, 0x68c0, 0x9005, 0x1160, - 0x6824, 0xd084, 0x0148, 0x6827, 0x0001, 0x080c, 0x878f, 0x080c, - 0xaa49, 0x7027, 0x0000, 0x0428, 0x080c, 0x878f, 0x6820, 0xd0b4, - 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, - 0xaa49, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, - 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d52, 0x9006, 0x080c, - 0x2d52, 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, 0xce54, 0x0110, 0x080c, 0xe948, 0x009e, 0x080c, 0xb134, - 0x080c, 0xa91f, 0x88ff, 0x1190, 0x00ce, 0x0804, 0xa93a, 0x2c78, - 0x600c, 0x2060, 0x0804, 0xa93a, 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, - 0x19e9, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, 0xaa38, 0x6020, - 0x9086, 0x0006, 0x1904, 0xaa33, 0x87ff, 0x0128, 0x2700, 0x9c06, - 0x1904, 0xaa33, 0x0040, 0x6010, 0x9b06, 0x15e8, 0x85ff, 0x0118, - 0x6054, 0x9106, 0x15c0, 0x703c, 0x9c06, 0x1168, 0x0036, 0x2019, - 0x0001, 0x080c, 0xa877, 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, - 0xce54, 0x0110, 0x080c, 0xe948, 0x080c, 0xb134, 0x87ff, 0x1198, - 0x00ce, 0x0804, 0xa9e4, 0x2c78, 0x600c, 0x2060, 0x0804, 0xa9e4, - 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x009e, 0x00de, - 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd, 0x0001, - 0x0c80, 0x00e6, 0x2071, 0x19e9, 0x2001, 0x1800, 0x2004, 0x9086, - 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, - 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0x19e9, 0x2c10, 0x7638, 0x2660, 0x2678, - 0x8cff, 0x0540, 0x2200, 0x9c06, 0x1508, 0x7038, 0x9c36, 0x1110, + 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, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6004, 0x9086, - 0x0040, 0x090c, 0x97e1, 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, 0x19e9, 0x760c, - 0x2660, 0x2678, 0x8cff, 0x0904, 0xab2f, 0x6010, 0x00b6, 0x2058, - 0xb8a0, 0x00be, 0x9206, 0x1904, 0xab2a, 0x7024, 0x9c06, 0x1520, - 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xab01, 0x080c, 0xa517, - 0x68c3, 0x0000, 0x080c, 0xaa49, 0x7027, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2d52, 0x9006, 0x080c, 0x2d52, 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, 0xd04d, - 0x1180, 0x080c, 0x326f, 0x080c, 0xd05e, 0x1518, 0x080c, 0xbae2, - 0x0400, 0x080c, 0xaa49, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, - 0x0898, 0x080c, 0xd05e, 0x1118, 0x080c, 0xbae2, 0x0090, 0x6014, - 0x2048, 0x080c, 0xce54, 0x0168, 0x6020, 0x9086, 0x0003, 0x1508, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6dc4, 0x080c, - 0xd041, 0x080c, 0xd2ca, 0x080c, 0xb134, 0x080c, 0xa91f, 0x00ce, - 0x0804, 0xaaaa, 0x2c78, 0x600c, 0x2060, 0x0804, 0xaaaa, 0x012e, - 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, - 0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, 0x080c, 0xe948, 0x0c08, - 0x00d6, 0x080c, 0x9f3a, 0x7003, 0x0200, 0x7007, 0x0014, 0x60c3, - 0x0014, 0x20e1, 0x0001, 0x2099, 0x198a, 0x20e9, 0x0000, 0x20a1, - 0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, 0x0004, 0x7027, 0x7878, - 0x080c, 0xa4eb, 0x00de, 0x0005, 0x080c, 0x9f3a, 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, 0xa4eb, - 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, 0x2009, 0x0035, 0x080c, - 0xd4d7, 0x00de, 0x1904, 0xabdd, 0x080c, 0x9eef, 0x7003, 0x1300, - 0x782c, 0x080c, 0xace3, 0x2068, 0x6820, 0x9086, 0x0003, 0x0560, - 0x7810, 0x2058, 0xbaa0, 0x080c, 0xb06b, 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, 0xb06b, 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, 0xa4eb, 0x00be, 0x0005, 0x781b, 0x0001, 0x7803, - 0x0006, 0x001e, 0x00de, 0x00be, 0x0005, 0x792c, 0x9180, 0x0008, - 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, 0x0003, 0x0904, 0xac58, - 0x9186, 0x0005, 0x0904, 0xac40, 0x9186, 0x0004, 0x05d8, 0x9186, - 0x0008, 0x0904, 0xac49, 0x7807, 0x0037, 0x782f, 0x0003, 0x7817, - 0x1700, 0x080c, 0xacc0, 0x0005, 0x080c, 0xac81, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x0002, 0xac21, 0xac2c, - 0xac23, 0xac2c, 0xac28, 0xac21, 0xac21, 0xac2c, 0xac2c, 0xac2c, - 0xac2c, 0xac21, 0xac21, 0xac21, 0xac21, 0xac21, 0xac2c, 0xac21, - 0xac2c, 0x080c, 0x0dc5, 0x6824, 0xd0e4, 0x0110, 0xd0cc, 0x0110, - 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, 0x7022, 0x6830, 0x7026, - 0x0804, 0xac7a, 0x080c, 0xac81, 0x00d6, 0x0026, 0x792c, 0x2168, - 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, 0x1108, 0x900e, 0x04d0, - 0x080c, 0xac81, 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, - 0xa4eb, 0x00b6, 0x0036, 0x0046, 0x0056, 0x0066, 0x080c, 0x9f3a, - 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, 0x793c, 0x710e, 0x7810, - 0x2058, 0xb8a0, 0x080c, 0xb06b, 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, 0x9f3a, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, - 0x700e, 0x60c3, 0x0008, 0x0804, 0xa4eb, 0x080c, 0x9ee6, 0x7003, - 0x1400, 0x7838, 0x700a, 0x0079, 0x783c, 0x700e, 0x782c, 0x7012, - 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, 0x8007, 0x701a, 0x60c3, - 0x0010, 0x0804, 0xa4eb, 0x00e6, 0x2071, 0x0240, 0x0006, 0x00f6, - 0x2078, 0x7810, 0x00b6, 0x2058, 0xb8cc, 0xd084, 0x0120, 0x7844, - 0x702a, 0x7848, 0x702e, 0x00be, 0x00fe, 0x000e, 0x00ee, 0x0005, - 0x080c, 0x9f31, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, - 0x60c3, 0x0008, 0x0804, 0xa4eb, 0x0021, 0x60c3, 0x0000, 0x0804, - 0xa4eb, 0x00d6, 0x080c, 0xadbc, 0xb810, 0x9085, 0x0300, 0x7002, - 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, - 0x7013, 0x0819, 0x080c, 0xa4d9, 0x721a, 0x2f10, 0x7222, 0x7a08, - 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x00a9, 0x7914, 0x712a, - 0x60c3, 0x0000, 0x60a7, 0x9575, 0x0026, 0x080c, 0x2be7, 0x0228, - 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x080c, 0xa50e, - 0x080c, 0x8786, 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, - 0xadbc, 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, 0x19b4, 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, 0x9eef, 0x0016, 0x0026, 0x0096, 0x00d6, 0x7814, 0x2048, - 0x7013, 0x0138, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1138, - 0x2001, 0x197d, 0x2004, 0x9086, 0xaaaa, 0x1904, 0xae61, 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, 0xadf2, - 0x20a9, 0x0004, 0x2009, 0x1801, 0x2104, 0x2012, 0x8108, 0x8210, - 0x1f04, 0xadfc, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, - 0x2009, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, - 0x8109, 0x1dc0, 0x00d6, 0x2069, 0x0200, 0x080c, 0xada7, 0x00de, - 0x2071, 0x0240, 0x2011, 0x0240, 0x2009, 0x0002, 0x20a9, 0x0001, - 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0x2009, 0x0008, + 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, - 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, 0x7569, 0x0150, 0x6028, 0xc0bd, - 0x602a, 0x6014, 0x9084, 0x1804, 0x9085, 0x0029, 0x6016, 0x0010, - 0x080c, 0xa4eb, 0x080c, 0x8786, 0x00de, 0x009e, 0x002e, 0x001e, - 0x0005, 0x00e6, 0x2071, 0x0240, 0x2001, 0x2200, 0x9085, 0x00ff, - 0x7002, 0x7007, 0xffff, 0x2071, 0x0100, 0x709b, 0x00ff, 0x00ee, - 0x0804, 0xadd7, 0x080c, 0x9eef, 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, - 0xaeb3, 0x20a9, 0x0002, 0x2009, 0x1801, 0x2104, 0x2012, 0x8108, - 0x8210, 0x1f04, 0xaebd, 0x00d6, 0x0016, 0x2069, 0x0200, 0x080c, - 0xada7, 0x001e, 0x00de, 0x2071, 0x0240, 0x20a9, 0x0002, 0x2009, - 0x1803, 0x2011, 0x0240, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, - 0xaed3, 0x2009, 0x0008, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, - 0x1dd0, 0x9006, 0x20a9, 0x0008, 0x2012, 0x8210, 0x1f04, 0xaee4, - 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, - 0xa4eb, 0x080c, 0x8786, 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, 0x20ee, 0x080c, 0x93a0, 0x0126, 0x2091, - 0x8000, 0x080c, 0x9a0f, 0x012e, 0x009e, 0x00de, 0x0005, 0x00f6, - 0x00e6, 0x00d6, 0x00c6, 0x00a6, 0x0096, 0x0066, 0x0126, 0x2091, - 0x8000, 0x2071, 0x19e9, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, - 0xafcb, 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x0904, 0xaf9d, 0x080c, 0xa517, 0x68c3, 0x0000, 0x080c, 0xaa49, - 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2d52, 0x9006, 0x080c, 0x2d52, - 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, 0xd04d, 0x1180, 0x080c, 0x326f, 0x080c, - 0xd05e, 0x1518, 0x080c, 0xbae2, 0x0400, 0x080c, 0xaa49, 0x6824, - 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, 0xd05e, 0x1118, - 0x080c, 0xbae2, 0x0090, 0x6014, 0x2048, 0x080c, 0xce54, 0x0168, - 0x6020, 0x9086, 0x0003, 0x1520, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x080c, 0x6dd1, 0x080c, 0xd041, 0x080c, 0xd2ca, 0x080c, - 0xb134, 0x080c, 0xa91f, 0x00ce, 0x0804, 0xaf4e, 0x2c78, 0x600c, - 0x2060, 0x0804, 0xaf4e, 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, - 0x006e, 0x009e, 0x00ae, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x6020, 0x9086, 0x0006, 0x1d08, 0x080c, 0xe948, 0x08f0, 0x00d6, - 0x0156, 0x080c, 0x9f3a, 0x7a14, 0x82ff, 0x0138, 0x7003, 0x0100, - 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, 0x7007, - 0x0000, 0x2069, 0x1800, 0x901e, 0x6800, 0x9086, 0x0004, 0x1110, - 0xc38d, 0x0060, 0x080c, 0x7569, 0x1110, 0xc3ad, 0x0008, 0xc3a5, - 0x6adc, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, 0x080c, - 0x8818, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, 0xffed, 0x2071, - 0x0250, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, - 0x0002, 0x9290, 0x0002, 0x1f04, 0xb011, 0x60c3, 0x0020, 0x080c, - 0xa4eb, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, 0x9f3a, 0x7a14, - 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, 0x1238, - 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0488, 0x7003, - 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2011, 0x19bf, 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, 0xa4eb, 0x0006, 0x2001, 0x1837, 0x2004, 0xd0ac, - 0x000e, 0x0005, 0x2011, 0x0003, 0x080c, 0xa8ed, 0x2011, 0x0002, - 0x080c, 0xa8f7, 0x080c, 0xa801, 0x0036, 0x901e, 0x080c, 0xa877, - 0x003e, 0x0005, 0x080c, 0x33a5, 0x0188, 0x0016, 0x00b6, 0x00c6, - 0x7010, 0x9085, 0x0020, 0x7012, 0x2009, 0x007e, 0x080c, 0x671d, - 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, + 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, 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, - 0x98ed, 0x001e, 0x012e, 0x0cb0, 0x0006, 0x6000, 0x9086, 0x0000, - 0x01c0, 0x601c, 0xd084, 0x190c, 0x1ab7, 0x6017, 0x0000, 0x6023, - 0x0007, 0x2001, 0x1987, 0x2004, 0x0006, 0x9082, 0x0051, 0x000e, - 0x0208, 0x8004, 0x601a, 0x080c, 0xec02, 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, 0xb193, 0xb19c, 0xb1b7, 0xb1d2, - 0xd5a9, 0xd5c6, 0xd5e1, 0xb193, 0xb19c, 0x8fcd, 0xb1eb, 0xb193, - 0xb193, 0xb193, 0xb193, 0x9186, 0x0013, 0x1128, 0x080c, 0x97e1, - 0x080c, 0x98ed, 0x0005, 0x0005, 0x0066, 0x6000, 0x90b2, 0x0010, - 0x1a0c, 0x0dc5, 0x0013, 0x006e, 0x0005, 0xb1b5, 0xb931, 0xbb29, - 0xb1b5, 0xbbbf, 0xb4ce, 0xb1b5, 0xb1b5, 0xb8b3, 0xc12f, 0xb1b5, - 0xb1b5, 0xb1b5, 0xb1b5, 0xb1b5, 0xb1b5, 0x080c, 0x0dc5, 0x0066, - 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, 0x0005, - 0xb1d0, 0xc7fc, 0xb1d0, 0xb1d0, 0xb1d0, 0xb1d0, 0xb1d0, 0xb1d0, - 0xc793, 0xc97e, 0xb1d0, 0xc83d, 0xc8bc, 0xc83d, 0xc8bc, 0xb1d0, - 0x080c, 0x0dc5, 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0dc5, 0x6000, - 0x0002, 0xb1e9, 0xc176, 0xc23e, 0xc371, 0xc520, 0xb1e9, 0xb1e9, - 0xb1e9, 0xc14a, 0xc71f, 0xc722, 0xb1e9, 0xb1e9, 0xb1e9, 0xb1e9, - 0xc751, 0x080c, 0x0dc5, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, - 0x0dc5, 0x0013, 0x006e, 0x0005, 0xb204, 0xb204, 0xb247, 0xb2e6, - 0xb37b, 0xb204, 0xb204, 0xb204, 0xb206, 0xb204, 0xb204, 0xb204, - 0xb204, 0xb204, 0xb204, 0xb204, 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, - 0x1c09, 0x080c, 0x93a0, 0x0126, 0x2091, 0x8000, 0x080c, 0x9a0f, - 0x012e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, - 0x080c, 0xb39d, 0x080c, 0xd579, 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, 0xb2ae, 0xb2ae, 0xb2a9, 0xb2ac, 0xb2ae, 0xb2a6, 0xb299, - 0xb299, 0xb299, 0xb299, 0xb299, 0xb299, 0xb299, 0xb299, 0xb299, - 0xb299, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, - 0x004e, 0x00fe, 0x009e, 0x00de, 0x080c, 0x0dc5, 0x080c, 0xbd80, - 0x0028, 0x080c, 0xbe67, 0x0010, 0x080c, 0xbf5d, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896, 0x000e, 0x080c, - 0xb45b, 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, 0xb61f, 0x0160, 0x000e, 0x9005, 0x0120, 0x00fe, - 0x009e, 0x00de, 0x0005, 0x00fe, 0x009e, 0x00de, 0x0804, 0xb101, - 0x2001, 0x002c, 0x900e, 0x080c, 0xb4c1, 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, 0x92ed, 0x002e, 0x001e, 0x000e, 0x012e, - 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, 0xb247, 0x0005, - 0xb319, 0xb319, 0xb31b, 0xb351, 0xb319, 0xb319, 0xb319, 0xb319, - 0xb364, 0x080c, 0x0dc5, 0x00d6, 0x0016, 0x0096, 0x080c, 0x989d, - 0x080c, 0x9a0f, 0x6003, 0x0004, 0x6114, 0x2148, 0xa87c, 0xd0fc, - 0x01c0, 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894, 0x9005, 0x0140, - 0x2001, 0x0000, 0x900e, 0x080c, 0xb4c1, 0x080c, 0xb101, 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, 0x989d, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, - 0xce56, 0x0120, 0xa87b, 0x0006, 0x080c, 0x6dd1, 0x009e, 0x00de, - 0x080c, 0xb101, 0x0804, 0x9a0f, 0x080c, 0x989d, 0x080c, 0x3246, - 0x080c, 0xd576, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, 0xce56, - 0x0120, 0xa87b, 0x0029, 0x080c, 0x6dd1, 0x009e, 0x00de, 0x080c, - 0xb101, 0x0804, 0x9a0f, 0x9182, 0x0047, 0x0002, 0xb38b, 0xb38d, - 0xb38b, 0xb38b, 0xb38b, 0xb38b, 0xb38b, 0xb38b, 0xb38b, 0xb38b, - 0xb38b, 0xb38b, 0xb38d, 0x080c, 0x0dc5, 0x00d6, 0x0096, 0x601f, - 0x0000, 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883, 0x0000, 0x080c, - 0x6dd1, 0x009e, 0x00de, 0x0804, 0xb101, 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, 0xca03, 0x04c0, 0x2130, - 0x2009, 0x0034, 0x2011, 0x001f, 0x080c, 0xca03, 0x96b2, 0x0034, - 0xb004, 0x904d, 0x0110, 0x080c, 0x0fc0, 0x080c, 0x100e, 0x01d0, - 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, 0xb406, 0x968a, - 0x003d, 0x1230, 0x2608, 0x2011, 0x001b, 0x080c, 0xca03, 0x00b8, - 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, 0x080c, - 0xca03, 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, 0x6dd1, 0x000e, - 0x2048, 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e, 0x006e, 0x005e, - 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096, 0x0006, 0x080c, + 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, 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, 0x6dd1, 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, 0xb470, 0x0804, 0xb472, - 0x9085, 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe, 0x00de, 0x001e, - 0x0005, 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, - 0x080c, 0x6dc4, 0x009e, 0x003e, 0x00de, 0x0005, 0x91b6, 0x0015, - 0x1118, 0x080c, 0xb101, 0x0030, 0x91b6, 0x0016, 0x190c, 0x0dc5, - 0x080c, 0xb101, 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, 0xce56, 0x0130, 0x6014, 0x2048, - 0xa807, 0x0000, 0xa867, 0x0103, 0x009e, 0x0804, 0xb101, 0x0096, - 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11a8, 0x6010, 0x00b6, - 0x2058, 0xb8cf, 0x0000, 0x00be, 0x6014, 0x9005, 0x0130, 0x2048, - 0xa807, 0x0000, 0xa867, 0x0103, 0xab32, 0x080c, 0xb101, 0x003e, - 0x00de, 0x009e, 0x0005, 0x0011, 0x1d48, 0x0cc8, 0x0006, 0x0016, - 0x080c, 0xd561, 0x0188, 0x6014, 0x9005, 0x1170, 0x600b, 0x0003, - 0x601b, 0x0000, 0x6043, 0x0000, 0x2009, 0x0022, 0x080c, 0xb909, - 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, 0xb101, - 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, 0xca03, 0x080c, 0xce56, - 0x0140, 0x6014, 0x2048, 0xa807, 0x0000, 0xa864, 0xa8e2, 0xa867, - 0x0103, 0x080c, 0xb101, 0x001e, 0x009e, 0x0005, 0x0016, 0x2009, - 0x0000, 0x7030, 0x9086, 0x0200, 0x0110, 0x2009, 0x0001, 0x0096, - 0x6014, 0x904d, 0x090c, 0x0dc5, 0xa97a, 0x080c, 0x6dd1, 0x009e, - 0x080c, 0xb101, 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, 0xca03, 0x009e, 0x080c, 0xce56, - 0x0148, 0xa804, 0x9005, 0x1158, 0xa807, 0x0000, 0xa864, 0xa8e2, - 0xa867, 0x0103, 0x080c, 0xb101, 0x009e, 0x001e, 0x0005, 0x0086, - 0x2040, 0xa030, 0x8007, 0x9086, 0x0100, 0x1118, 0x080c, 0xbae2, - 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, 0xd4d7, 0x001e, 0x1158, 0x622c, 0x2268, 0x2071, 0x026c, - 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, 0x0128, 0x080c, - 0xb101, 0x0020, 0x0039, 0x0010, 0x080c, 0xb73e, 0x002e, 0x00de, - 0x00ee, 0x0005, 0x0096, 0x6814, 0x2048, 0x9186, 0x0015, 0x0904, - 0xb726, 0x918e, 0x0016, 0x1904, 0xb73c, 0x700c, 0x908c, 0xff00, - 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, 0xb700, 0x89ff, - 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, 0xb6e3, 0x0804, 0xb73a, - 0x6808, 0x9086, 0xffff, 0x1904, 0xb728, 0xa87c, 0x9084, 0x0060, - 0x9086, 0x0020, 0x1128, 0xa83c, 0xa940, 0x9105, 0x1904, 0xb728, - 0x6824, 0xd084, 0x1904, 0xb728, 0xd0b4, 0x0158, 0x0016, 0x2001, - 0x1987, 0x200c, 0x6018, 0x9102, 0x9082, 0x0005, 0x001e, 0x1a04, - 0xb728, 0x080c, 0xd041, 0x685c, 0xa882, 0xa87c, 0xc0dc, 0xc0f4, - 0xc0d4, 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, 0x080c, - 0x91b1, 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, 0x82ff, 0x002e, - 0x1138, 0x00c6, 0x2d60, 0x080c, 0xcb65, 0x00ce, 0x0804, 0xb73a, - 0x00c6, 0xa868, 0xd0fc, 0x1118, 0x080c, 0x61bb, 0x0010, 0x080c, - 0x65c8, 0x00ce, 0x1904, 0xb728, 0x00c6, 0x2d60, 0x080c, 0xb101, - 0x00ce, 0x0804, 0xb73a, 0x00c6, 0x080c, 0xb153, 0x0198, 0x6017, - 0x0000, 0x6810, 0x6012, 0x080c, 0xd2d2, 0x6023, 0x0003, 0x6904, - 0x00c6, 0x2d60, 0x080c, 0xb101, 0x00ce, 0x080c, 0xb180, 0x00ce, - 0x0804, 0xb73a, 0x2001, 0x1989, 0x2004, 0x6842, 0x00ce, 0x04d0, - 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, 0x2058, 0xb900, - 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, 0x0003, 0x080c, - 0xd51b, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, - 0x933b, 0x080c, 0x98ed, 0x00ce, 0x00e8, 0x700c, 0x9086, 0x2a00, - 0x1138, 0x2001, 0x1989, 0x2004, 0x6842, 0x00a0, 0x0479, 0x00a0, - 0x89ff, 0x090c, 0x0dc5, 0x00c6, 0x00d6, 0x2d60, 0xa867, 0x0103, - 0xa87b, 0x0003, 0x080c, 0x6beb, 0x080c, 0xd041, 0x080c, 0xb134, - 0x00de, 0x00ce, 0x080c, 0xb101, 0x009e, 0x0005, 0x9186, 0x0015, - 0x1128, 0x2001, 0x1989, 0x2004, 0x6842, 0x0068, 0x918e, 0x0016, - 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xec02, 0x080c, 0x88f1, - 0x080c, 0xb101, 0x00ce, 0x080c, 0xb101, 0x0005, 0x0026, 0x0036, - 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, 0x2001, 0x1989, - 0x2004, 0x6842, 0x0804, 0xb7b8, 0x00c6, 0x2d60, 0x080c, 0xca64, - 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, - 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x933b, 0x080c, 0x98ed, - 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, 0xd1c9, 0x080c, 0x98ed, 0x0010, - 0x080c, 0xb101, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, - 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, 0xba10, - 0x00be, 0x9206, 0x1904, 0xb823, 0x700c, 0x6210, 0x00b6, 0x2258, - 0xba14, 0x00be, 0x9206, 0x1904, 0xb823, 0x6038, 0x2068, 0x6824, - 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, 0xb823, 0x9286, - 0x0002, 0x0904, 0xb823, 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, 0xce56, 0x090c, 0x0dc5, 0xa87b, 0x0003, 0x009e, 0x080c, - 0xd51b, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, - 0x933b, 0x080c, 0x98ed, 0x00ce, 0x0030, 0x6038, 0x2070, 0x2001, - 0x1989, 0x2004, 0x7042, 0x080c, 0xb101, 0x002e, 0x00de, 0x00ee, - 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, 0x6010, 0x2058, - 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, 0xc48c, 0xbc02, - 0x0460, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0010, - 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, 0xc0f7, 0x002e, 0x003e, - 0x015e, 0x009e, 0x1904, 0xb892, 0x0096, 0x0156, 0x0036, 0x0026, - 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, 0x0004, 0x080c, - 0xc0f7, 0x002e, 0x003e, 0x015e, 0x009e, 0x15a0, 0x7238, 0xba0a, - 0x733c, 0xbb0e, 0xbc00, 0xc48d, 0xbc02, 0xa804, 0x9005, 0x1128, - 0x00fe, 0x009e, 0x00be, 0x0804, 0xb50a, 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, 0xb61f, - 0x0130, 0x00fe, 0x009e, 0x080c, 0xb101, 0x00be, 0x0005, 0x080c, - 0xbae2, 0x0cb8, 0x2b78, 0x00f6, 0x080c, 0x3246, 0x080c, 0xd576, - 0x00fe, 0x00c6, 0x080c, 0xb0ab, 0x2f00, 0x6012, 0x6017, 0x0000, - 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, - 0x080c, 0x6663, 0x080c, 0x668f, 0x080c, 0x9383, 0x080c, 0x98ed, - 0x00ce, 0x0804, 0xb865, 0x2100, 0x91b2, 0x0053, 0x1a0c, 0x0dc5, - 0x91b2, 0x0040, 0x1a04, 0xb91b, 0x0002, 0xb909, 0xb909, 0xb8ff, - 0xb909, 0xb909, 0xb909, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, - 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, - 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, - 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb909, 0xb8fd, 0xb909, 0xb909, - 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8ff, 0xb8fd, 0xb8fd, - 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb909, - 0xb909, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, 0xb8fd, - 0xb8fd, 0xb8fd, 0xb909, 0xb8fd, 0xb8fd, 0x080c, 0x0dc5, 0x0066, - 0x00b6, 0x6610, 0x2658, 0xb8cc, 0xc08c, 0xb8ce, 0x00be, 0x006e, - 0x0000, 0x6003, 0x0001, 0x6106, 0x9186, 0x0032, 0x0118, 0x080c, - 0x9383, 0x0010, 0x080c, 0x933b, 0x0126, 0x2091, 0x8000, 0x080c, - 0x98ed, 0x012e, 0x0005, 0x2600, 0x0002, 0xb909, 0xb909, 0xb92f, - 0xb909, 0xb909, 0xb92f, 0xb92f, 0xb92f, 0xb92f, 0xb909, 0xb92f, - 0xb909, 0xb92f, 0xb909, 0xb92f, 0xb92f, 0xb92f, 0xb92f, 0x080c, - 0x0dc5, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0dc5, 0x91b6, 0x0013, - 0x0904, 0xba04, 0x91b6, 0x0027, 0x1904, 0xb9ae, 0x080c, 0x97e1, - 0x6004, 0x080c, 0xd04d, 0x01b0, 0x080c, 0xd05e, 0x01a8, 0x908e, - 0x0021, 0x0904, 0xb9ab, 0x908e, 0x0022, 0x1130, 0x080c, 0xb536, - 0x0904, 0xb9a7, 0x0804, 0xb9a8, 0x908e, 0x003d, 0x0904, 0xb9ab, - 0x0804, 0xb9a1, 0x080c, 0x326f, 0x2001, 0x0007, 0x080c, 0x6663, - 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, 0xbae2, 0x9186, - 0x007e, 0x1148, 0x2001, 0x1837, 0x2014, 0xc285, 0x080c, 0x7569, - 0x1108, 0xc2ad, 0x2202, 0x0036, 0x0026, 0x2019, 0x0028, 0x2110, - 0x080c, 0xed0f, 0x002e, 0x003e, 0x0016, 0x0026, 0x0036, 0x2110, - 0x2019, 0x0028, 0x080c, 0x94e0, 0x0076, 0x903e, 0x080c, 0x93b3, - 0x6010, 0x00b6, 0x905d, 0x0100, 0x00be, 0x2c08, 0x080c, 0xe690, - 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0xd576, 0x0016, 0x080c, - 0xd2ca, 0x080c, 0xb101, 0x001e, 0x080c, 0x3342, 0x080c, 0x98ed, - 0x0030, 0x080c, 0xd2ca, 0x080c, 0xb101, 0x080c, 0x98ed, 0x0005, - 0x080c, 0xbae2, 0x0cb0, 0x080c, 0xbb1e, 0x0c98, 0x9186, 0x0015, - 0x0118, 0x9186, 0x0016, 0x1148, 0x080c, 0xd587, 0x0d80, 0x6000, - 0x9086, 0x0002, 0x0904, 0xbb29, 0x0c50, 0x9186, 0x0014, 0x1d38, - 0x080c, 0x97e1, 0x6004, 0x908e, 0x0022, 0x1118, 0x080c, 0xb536, - 0x09f0, 0x080c, 0x3246, 0x080c, 0xd576, 0x080c, 0xd04d, 0x1198, - 0x080c, 0x326f, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, - 0xbae2, 0x9186, 0x007e, 0x1128, 0x2001, 0x1837, 0x200c, 0xc185, - 0x2102, 0x0804, 0xb9a1, 0x080c, 0xd05e, 0x1120, 0x080c, 0xbae2, - 0x0804, 0xb9a1, 0x6004, 0x908e, 0x0032, 0x1160, 0x00e6, 0x00f6, - 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, 0x35dd, 0x00fe, 0x00ee, - 0x0804, 0xb9a1, 0x6004, 0x908e, 0x0021, 0x0d40, 0x908e, 0x0022, - 0x090c, 0xbae2, 0x0804, 0xb9a1, 0x90b2, 0x0040, 0x1a04, 0xbabe, - 0x2008, 0x0002, 0xba4c, 0xba4d, 0xba50, 0xba53, 0xba56, 0xba63, - 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, - 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, - 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xba4a, - 0xba66, 0xba73, 0xba4a, 0xba75, 0xba73, 0xba4a, 0xba4a, 0xba4a, - 0xba4a, 0xba4a, 0xba73, 0xba73, 0xba4a, 0xba4a, 0xba4a, 0xba4a, - 0xba4a, 0xba4a, 0xba4a, 0xba4a, 0xbaa5, 0xba73, 0xba4a, 0xba6f, - 0xba4a, 0xba4a, 0xba4a, 0xba70, 0xba4a, 0xba4a, 0xba4a, 0xba73, - 0xba9c, 0xba4a, 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, 0x97e1, - 0x6003, 0x0005, 0x080c, 0xd579, 0x080c, 0x98ed, 0x0070, 0x0018, - 0x0010, 0x080c, 0x6663, 0x0804, 0xbab6, 0x080c, 0x97e1, 0x080c, - 0xd579, 0x6003, 0x0004, 0x080c, 0x98ed, 0x0005, 0x080c, 0x6663, - 0x080c, 0x97e1, 0x6003, 0x0002, 0x0036, 0x2019, 0x1852, 0x2304, - 0x9084, 0xff00, 0x1120, 0x2001, 0x1987, 0x201c, 0x0040, 0x8007, - 0x909a, 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, - 0x003e, 0x080c, 0x98ed, 0x0c08, 0x080c, 0x97e1, 0x080c, 0xd2ca, - 0x080c, 0xb101, 0x080c, 0x98ed, 0x08c0, 0x00e6, 0x00f6, 0x2071, - 0x189e, 0x2079, 0x0000, 0x080c, 0x35dd, 0x00fe, 0x00ee, 0x080c, - 0x97e1, 0x080c, 0xb101, 0x080c, 0x98ed, 0x0838, 0x080c, 0x97e1, - 0x6003, 0x0002, 0x080c, 0xd579, 0x0804, 0x98ed, 0x2600, 0x2008, - 0x0002, 0xbad5, 0xbab6, 0xbad3, 0xbab6, 0xbab6, 0xbad3, 0xbad3, - 0xbad3, 0xbad3, 0xbab6, 0xbad3, 0xbab6, 0xbad3, 0xbab6, 0xbad3, - 0xbad3, 0xbad3, 0xbad3, 0x080c, 0x0dc5, 0x080c, 0x97e1, 0x0096, - 0x6014, 0x2048, 0x080c, 0x6dd1, 0x009e, 0x080c, 0xb101, 0x080c, - 0x98ed, 0x0005, 0x00e6, 0x0096, 0x0026, 0x0016, 0x080c, 0xce56, - 0x0568, 0x6014, 0x2048, 0xa864, 0x9086, 0x0139, 0x11a8, 0xa894, - 0x9086, 0x0056, 0x1148, 0x080c, 0x556d, 0x0130, 0x2001, 0x0000, - 0x900e, 0x2011, 0x4000, 0x0028, 0x2001, 0x0030, 0x900e, 0x2011, - 0x4005, 0x080c, 0xd43b, 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, - 0xd35a, 0x0804, 0xbbae, 0x6604, 0x96b6, 0x0043, 0x1120, 0x080c, - 0xd3a3, 0x0804, 0xbbae, 0x6604, 0x96b6, 0x004b, 0x1120, 0x080c, - 0xd3cf, 0x0804, 0xbbae, 0x6604, 0x96b6, 0x0033, 0x1120, 0x080c, - 0xd2ec, 0x0804, 0xbbae, 0x6604, 0x96b6, 0x0028, 0x1120, 0x080c, - 0xd09c, 0x0804, 0xbbae, 0x6604, 0x96b6, 0x0029, 0x1120, 0x080c, - 0xd0dd, 0x0804, 0xbbae, 0x6604, 0x96b6, 0x001f, 0x1120, 0x080c, - 0xb4db, 0x0804, 0xbbae, 0x6604, 0x96b6, 0x0000, 0x1118, 0x080c, - 0xb829, 0x04e0, 0x6604, 0x96b6, 0x0022, 0x1118, 0x080c, 0xb517, - 0x04a8, 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, 0xb63d, 0x0470, - 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, 0xb7be, 0x0438, 0x6604, - 0x96b6, 0x003d, 0x1118, 0x080c, 0xb54f, 0x0400, 0x6604, 0x96b6, - 0x0044, 0x1118, 0x080c, 0xb58b, 0x00c8, 0x6604, 0x96b6, 0x0049, - 0x1118, 0x080c, 0xb5cc, 0x0090, 0x6604, 0x96b6, 0x0041, 0x1118, - 0x080c, 0xb5b6, 0x0058, 0x91b6, 0x0015, 0x1110, 0x0063, 0x0030, - 0x91b6, 0x0016, 0x1128, 0x00be, 0x0804, 0xbe0c, 0x00be, 0x0005, - 0x080c, 0xb19b, 0x0cd8, 0xbbcb, 0xbbd9, 0xbbcb, 0xbc20, 0xbbcb, - 0xbd80, 0xbe19, 0xbbcb, 0xbbcb, 0xbde2, 0xbbcb, 0xbdf8, 0x0096, - 0x601f, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, - 0x009e, 0x0804, 0xb101, 0xa001, 0xa001, 0x0005, 0x6604, 0x96b6, - 0x0004, 0x1130, 0x2001, 0x0001, 0x080c, 0x664f, 0x0804, 0xb101, - 0x0005, 0x00e6, 0x2071, 0x1800, 0x7090, 0x9086, 0x0074, 0x1540, - 0x080c, 0xe661, 0x11b0, 0x6010, 0x00b6, 0x2058, 0x7030, 0xd08c, - 0x0128, 0xb800, 0xd0bc, 0x0110, 0xc0c5, 0xb802, 0x00f9, 0x00be, - 0x2001, 0x0006, 0x080c, 0x6663, 0x080c, 0x326f, 0x080c, 0xb101, - 0x0098, 0x2001, 0x000a, 0x080c, 0x6663, 0x080c, 0x326f, 0x6003, - 0x0001, 0x6007, 0x0001, 0x080c, 0x9383, 0x080c, 0x98ed, 0x0020, - 0x2001, 0x0001, 0x080c, 0xbd50, 0x00ee, 0x0005, 0x00d6, 0xb800, - 0xd084, 0x0160, 0x9006, 0x080c, 0x664f, 0x2069, 0x1847, 0x6804, - 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x668f, 0x00de, 0x0005, - 0x00b6, 0x0096, 0x00d6, 0x2011, 0x1824, 0x2204, 0x9086, 0x0074, - 0x1904, 0xbd25, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x007e, 0x1120, - 0x080c, 0xbf68, 0x0804, 0xbc92, 0x080c, 0xbf5d, 0x6010, 0x2058, - 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014, 0x9005, 0x01a8, 0x2048, - 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, - 0x900e, 0x2011, 0x4000, 0x080c, 0xd43b, 0x0030, 0xa807, 0x0000, - 0xa867, 0x0103, 0xa833, 0x0200, 0x2001, 0x0006, 0x080c, 0x6663, - 0x080c, 0x326f, 0x080c, 0xb101, 0x0804, 0xbd2a, 0x080c, 0xbd38, - 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, 0xd0f4, 0x01e8, 0xa864, - 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, 0x2001, 0x0000, 0x900e, - 0x2011, 0x4000, 0x080c, 0xd43b, 0x08f8, 0x080c, 0xbd2e, 0x0160, - 0x9006, 0x080c, 0x664f, 0x2001, 0x0004, 0x080c, 0x668f, 0x2001, - 0x0007, 0x080c, 0x6663, 0x08a0, 0x2001, 0x0004, 0x080c, 0x6663, - 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x9383, 0x080c, 0x98ed, - 0x0804, 0xbd2a, 0xb85c, 0xd0e4, 0x0178, 0x080c, 0xd26c, 0x080c, - 0x7569, 0x0118, 0xd0dc, 0x1904, 0xbc54, 0x2011, 0x1837, 0x2204, - 0xc0ad, 0x2012, 0x0804, 0xbc54, 0x080c, 0xd2a9, 0x2011, 0x1837, - 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xe82d, 0x000e, 0x1904, - 0xbc54, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x6663, 0x9006, - 0x080c, 0x664f, 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, 0x28dd, 0x00f6, - 0x2100, 0x900e, 0x080c, 0x2894, 0x795e, 0x00fe, 0x9186, 0x0081, - 0x01f0, 0x2009, 0x0081, 0x00e0, 0x2009, 0x00ef, 0x00f6, 0x2079, - 0x0100, 0x79ea, 0x78e7, 0x0000, 0x7932, 0x7936, 0x780c, 0xc0b5, - 0x780e, 0x00fe, 0x080c, 0x28dd, 0x00f6, 0x2079, 0x1800, 0x7982, - 0x2100, 0x900e, 0x797e, 0x080c, 0x2894, 0x795e, 0x00fe, 0x8108, - 0x080c, 0x66b2, 0x2b00, 0x00ce, 0x1904, 0xbc54, 0x6012, 0x2009, - 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, 0x027c, 0x210c, 0x918c, - 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, 0xb916, 0x2001, 0x0002, - 0x080c, 0x6663, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, - 0x080c, 0x9383, 0x080c, 0x98ed, 0x0028, 0x080c, 0xbae2, 0x2001, - 0x0001, 0x0431, 0x00de, 0x009e, 0x00be, 0x0005, 0x2001, 0x1810, - 0x2004, 0xd0a4, 0x0120, 0x2001, 0x1848, 0x2004, 0xd0ac, 0x0005, - 0x00e6, 0x080c, 0xed68, 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, 0x6663, 0x080c, - 0x57e7, 0x1120, 0x2001, 0x0007, 0x080c, 0x668f, 0x2600, 0x9005, - 0x11b0, 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, 0x1178, - 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, - 0x0004, 0x2011, 0x8014, 0x080c, 0x4be9, 0x004e, 0x003e, 0x080c, - 0x326f, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, 0x0804, 0xb101, - 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1800, 0x7090, 0x9086, - 0x0014, 0x1904, 0xbdd8, 0x080c, 0x57e7, 0x1170, 0x6014, 0x9005, - 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, - 0x080c, 0x4da0, 0x004e, 0x003e, 0x00d6, 0x6010, 0x2058, 0x080c, - 0x67b8, 0x080c, 0xbc0e, 0x00de, 0x080c, 0xc033, 0x1588, 0x6010, - 0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, 0x6663, - 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, - 0xd43b, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130, - 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x009e, 0x080c, - 0x326f, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c, 0xb101, 0x0028, - 0x080c, 0xbae2, 0x9006, 0x080c, 0xbd50, 0x001e, 0x002e, 0x00ee, - 0x00be, 0x0005, 0x2011, 0x1824, 0x2204, 0x9086, 0x0014, 0x1160, - 0x2001, 0x0002, 0x080c, 0x6663, 0x6003, 0x0001, 0x6007, 0x0001, - 0x080c, 0x9383, 0x0804, 0x98ed, 0x2001, 0x0001, 0x0804, 0xbd50, - 0x2030, 0x2011, 0x1824, 0x2204, 0x9086, 0x0004, 0x1148, 0x96b6, - 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x6663, 0x0804, 0xb101, - 0x2001, 0x0001, 0x0804, 0xbd50, 0x0002, 0xbbcb, 0xbe24, 0xbbcb, - 0xbe67, 0xbbcb, 0xbf14, 0xbe19, 0xbbce, 0xbbcb, 0xbf28, 0xbbcb, - 0xbf3a, 0x6604, 0x9686, 0x0003, 0x0904, 0xbd80, 0x96b6, 0x001e, - 0x1110, 0x080c, 0xb101, 0x0005, 0x00b6, 0x00d6, 0x00c6, 0x080c, - 0xbf4c, 0x11a0, 0x9006, 0x080c, 0x664f, 0x080c, 0x3246, 0x080c, - 0xd576, 0x2001, 0x0002, 0x080c, 0x6663, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x9383, 0x080c, 0x98ed, 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, 0x3246, 0x080c, 0xd576, 0x2001, - 0x0001, 0x080c, 0xbd50, 0x00ce, 0x00de, 0x00be, 0x0005, 0x0096, - 0x00b6, 0x0026, 0x9016, 0x080c, 0xbf5a, 0x00d6, 0x2069, 0x197d, - 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, - 0x1138, 0x2069, 0x1820, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, - 0x00de, 0x0088, 0x9006, 0x080c, 0x664f, 0x2001, 0x0002, 0x080c, - 0x6663, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9383, 0x080c, - 0x98ed, 0x0804, 0xbee4, 0x080c, 0xce56, 0x01b0, 0x6014, 0x2048, - 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, 0x0016, 0x2001, - 0x0002, 0x080c, 0xd498, 0x00b0, 0x6014, 0x2048, 0xa864, 0xd0fc, - 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e, 0x2004, 0xd0dc, - 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x1110, - 0x9006, 0x0c38, 0x080c, 0xbae2, 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, 0x6663, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, 0x0020, - 0x2001, 0x0001, 0x080c, 0xbd50, 0x002e, 0x00be, 0x009e, 0x0005, - 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, 0x080c, 0xce56, 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, 0x60ba, 0x00ee, - 0x0010, 0x080c, 0x3246, 0x0860, 0x2001, 0x0004, 0x080c, 0x6663, - 0x080c, 0xbf5a, 0x1140, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, - 0x9383, 0x0804, 0x98ed, 0x080c, 0xbae2, 0x9006, 0x0804, 0xbd50, - 0x0489, 0x1160, 0x2001, 0x0008, 0x080c, 0x6663, 0x6003, 0x0001, - 0x6007, 0x0005, 0x080c, 0x9383, 0x0804, 0x98ed, 0x2001, 0x0001, - 0x0804, 0xbd50, 0x00f9, 0x1160, 0x2001, 0x000a, 0x080c, 0x6663, - 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9383, 0x0804, 0x98ed, - 0x2001, 0x0001, 0x0804, 0xbd50, 0x2009, 0x026e, 0x2104, 0x9086, - 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, - 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6, 0x00c6, 0x0016, - 0x6110, 0x2158, 0x080c, 0x672c, 0x001e, 0x00ce, 0x00be, 0x0005, - 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, 0x2058, - 0x2009, 0x1837, 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0xc005, - 0x0560, 0x2009, 0x1837, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x6a8e, - 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xe9a5, 0x2001, - 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, - 0x080c, 0x3211, 0x00e6, 0x2071, 0x1800, 0x080c, 0x3019, 0x00ee, - 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, 0x080c, 0x3342, - 0x8108, 0x1f04, 0xbf9e, 0x015e, 0x00ce, 0x080c, 0xbf5d, 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, 0x28dd, 0x080c, 0x7569, 0x0170, 0x2071, - 0x0260, 0x2069, 0x1983, 0x7048, 0x206a, 0x704c, 0x6806, 0x7050, - 0x680a, 0x7054, 0x680e, 0x080c, 0xd26c, 0x0040, 0x2001, 0x0006, - 0x080c, 0x6663, 0x080c, 0x326f, 0x080c, 0xb101, 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, 0xc0f7, 0x1148, 0x2011, 0x027a, 0x20a9, 0x0004, - 0x2019, 0x0006, 0x080c, 0xc0f7, 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, 0x19f2, 0x252c, 0x2021, - 0x19f8, 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7254, 0x7074, - 0x9202, 0x1a04, 0xc0c3, 0x080c, 0x8bc3, 0x0904, 0xc0bc, 0x080c, - 0xe9d6, 0x0904, 0xc0bc, 0x6720, 0x9786, 0x0007, 0x0904, 0xc0bc, - 0x2500, 0x9c06, 0x0904, 0xc0bc, 0x2400, 0x9c06, 0x05e8, 0x3e08, - 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, 0x0130, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0bc, 0x1580, 0x00c6, 0x6000, 0x9086, 0x0004, - 0x1110, 0x080c, 0x1ab7, 0x9786, 0x000a, 0x0148, 0x080c, 0xd05e, - 0x1130, 0x00ce, 0x080c, 0xbae2, 0x080c, 0xb134, 0x00e8, 0x6014, - 0x2048, 0x080c, 0xce56, 0x01a8, 0x9786, 0x0003, 0x1530, 0xa867, - 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, - 0x0fc0, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6dc4, 0x080c, - 0xd041, 0x080c, 0xb134, 0x00ce, 0x9ce0, 0x0018, 0x7068, 0x9c02, - 0x1210, 0x0804, 0xc066, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, - 0x007e, 0x00ce, 0x009e, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, - 0x080c, 0xe948, 0x0c30, 0x9786, 0x0009, 0x1148, 0x6000, 0x9086, - 0x0004, 0x0d08, 0x2009, 0x004c, 0x080c, 0xb180, 0x08e0, 0x9786, - 0x000a, 0x0980, 0x0820, 0x220c, 0x2304, 0x9106, 0x1130, 0x8210, - 0x8318, 0x1f04, 0xc0e3, 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, 0xc121, 0x9006, 0x0005, 0x918d, 0x0001, 0x0005, 0x6004, - 0x908a, 0x0053, 0x1a0c, 0x0dc5, 0x080c, 0xd04d, 0x0120, 0x080c, - 0xd05e, 0x0168, 0x0028, 0x080c, 0x326f, 0x080c, 0xd05e, 0x0138, - 0x080c, 0x97e1, 0x080c, 0xb101, 0x080c, 0x98ed, 0x0005, 0x080c, - 0xbae2, 0x0cb0, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, - 0x000a, 0x0005, 0xc166, 0xc166, 0xc166, 0xc166, 0xc166, 0xc166, - 0xc166, 0xc166, 0xc166, 0xc166, 0xc166, 0xc168, 0xc168, 0xc168, - 0xc168, 0xc166, 0xc166, 0xc166, 0xc168, 0xc166, 0x080c, 0x0dc5, - 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, 0x933b, 0x0126, - 0x2091, 0x8000, 0x080c, 0x98ed, 0x012e, 0x0005, 0x9186, 0x0013, - 0x1128, 0x6004, 0x9082, 0x0040, 0x0804, 0xc200, 0x9186, 0x0027, - 0x1520, 0x080c, 0x97e1, 0x080c, 0x3246, 0x080c, 0xd576, 0x0096, - 0x6114, 0x2148, 0x080c, 0xce56, 0x0198, 0x080c, 0xd05e, 0x1118, - 0x080c, 0xbae2, 0x0068, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, - 0x0000, 0xa97c, 0xc1c5, 0xa97e, 0x080c, 0x6dd1, 0x080c, 0xd041, - 0x009e, 0x080c, 0xb101, 0x0804, 0x98ed, 0x9186, 0x0014, 0x1120, - 0x6004, 0x9082, 0x0040, 0x00b8, 0x9186, 0x0046, 0x0150, 0x9186, - 0x0045, 0x0138, 0x9186, 0x0053, 0x0120, 0x9186, 0x0048, 0x190c, - 0x0dc5, 0x080c, 0xd587, 0x0130, 0x6000, 0x9086, 0x0002, 0x1110, - 0x0804, 0xc23e, 0x0005, 0x0002, 0xc1da, 0xc1d8, 0xc1d8, 0xc1d8, - 0xc1d8, 0xc1d8, 0xc1d8, 0xc1d8, 0xc1d8, 0xc1d8, 0xc1d8, 0xc1f5, - 0xc1f5, 0xc1f5, 0xc1f5, 0xc1d8, 0xc1f5, 0xc1d8, 0xc1f5, 0xc1d8, - 0x080c, 0x0dc5, 0x080c, 0x97e1, 0x0096, 0x6114, 0x2148, 0x080c, - 0xce56, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, - 0xa880, 0xc0ec, 0xa882, 0x080c, 0x6dd1, 0x080c, 0xd041, 0x009e, - 0x080c, 0xb101, 0x080c, 0x98ed, 0x0005, 0x080c, 0x97e1, 0x080c, - 0xd05e, 0x090c, 0xbae2, 0x080c, 0xb101, 0x080c, 0x98ed, 0x0005, - 0x0002, 0xc217, 0xc215, 0xc215, 0xc215, 0xc215, 0xc215, 0xc215, - 0xc215, 0xc215, 0xc215, 0xc215, 0xc22e, 0xc22e, 0xc22e, 0xc22e, - 0xc215, 0xc238, 0xc215, 0xc22e, 0xc215, 0x080c, 0x0dc5, 0x0096, - 0x080c, 0x97e1, 0x6014, 0x2048, 0x2001, 0x1989, 0x2004, 0x6042, - 0xa97c, 0xd1ac, 0x0140, 0x6003, 0x0004, 0xa87c, 0x9085, 0x0400, - 0xa87e, 0x009e, 0x0005, 0x6003, 0x0002, 0x0cb8, 0x080c, 0x97e1, - 0x080c, 0xd579, 0x080c, 0xd57e, 0x6003, 0x000f, 0x0804, 0x98ed, - 0x080c, 0x97e1, 0x080c, 0xb101, 0x0804, 0x98ed, 0x9182, 0x0054, - 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xc25a, 0xc25a, - 0xc25a, 0xc25a, 0xc25a, 0xc25c, 0xc33c, 0xc25a, 0xc370, 0xc25a, - 0xc25a, 0xc25a, 0xc25a, 0xc25a, 0xc25a, 0xc25a, 0xc25a, 0xc25a, - 0xc25a, 0xc370, 0x080c, 0x0dc5, 0x00b6, 0x0096, 0x6114, 0x2148, - 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1528, 0x6010, 0x2058, 0xb800, - 0xd0bc, 0x1904, 0xc32b, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc509, - 0x080c, 0x6beb, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, - 0xba3e, 0x7044, 0xd0e4, 0x1904, 0xc30c, 0x080c, 0xb101, 0x009e, - 0x00be, 0x0005, 0x968c, 0x0c00, 0x0150, 0x6010, 0x2058, 0xb800, - 0xd0bc, 0x1904, 0xc310, 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, 0xc263, 0x735c, 0xab86, - 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, - 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xca03, 0x003e, - 0xd6cc, 0x0904, 0xc278, 0x7154, 0xa98a, 0x81ff, 0x0904, 0xc278, - 0x9192, 0x0021, 0x1278, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, - 0x080c, 0xca03, 0x2011, 0x0205, 0x2013, 0x0000, 0x080c, 0xd504, - 0x0804, 0xc278, 0xa868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, - 0x0c50, 0x00a6, 0x2950, 0x080c, 0xc9a2, 0x00ae, 0x080c, 0xd504, - 0x080c, 0xc9f3, 0x0804, 0xc27a, 0x080c, 0xd156, 0x0804, 0xc287, - 0xa87c, 0xd0ac, 0x0904, 0xc293, 0xa880, 0xd0bc, 0x1904, 0xc293, - 0x9684, 0x0400, 0x0130, 0xa838, 0xab34, 0x9305, 0x0904, 0xc293, - 0x00b8, 0x7348, 0xa838, 0x9306, 0x1198, 0x734c, 0xa834, 0x931e, - 0x0904, 0xc293, 0x0068, 0xa87c, 0xd0ac, 0x0904, 0xc26b, 0xa838, - 0xa934, 0x9105, 0x0904, 0xc26b, 0xa880, 0xd0bc, 0x1904, 0xc26b, - 0x080c, 0xd190, 0x0804, 0xc287, 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, 0x1c09, 0x080c, 0x93a0, 0x080c, 0x9a0f, 0x009e, 0x0005, - 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, - 0x0005, 0xc38d, 0xc38d, 0xc38d, 0xc38d, 0xc38d, 0xc38f, 0xc425, - 0xc38d, 0xc38d, 0xc43c, 0xc4cc, 0xc38d, 0xc38d, 0xc38d, 0xc38d, - 0xc4e1, 0xc38d, 0xc38d, 0xc38d, 0xc38d, 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, 0xc420, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, - 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xc420, 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, 0xca03, - 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, - 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, - 0xca03, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, - 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, 0xc9a2, - 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, 0x1c09, 0x0804, 0xa4e4, 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, - 0x97e1, 0x080c, 0x98ed, 0x0096, 0x2001, 0x1989, 0x2004, 0x6042, - 0x080c, 0x989d, 0x080c, 0x9a0f, 0x6114, 0x2148, 0xa97c, 0xd1e4, - 0x0904, 0xc4c7, 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, 0xc9f3, 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, 0x6beb, 0x001e, 0xd1e4, 0x1120, 0x080c, 0xb101, 0x009e, - 0x0005, 0x080c, 0xd156, 0x0cd8, 0x6004, 0x9086, 0x0040, 0x1120, - 0x080c, 0x97e1, 0x080c, 0x98ed, 0x2019, 0x0001, 0x080c, 0xa877, - 0x6003, 0x0002, 0x080c, 0xd57e, 0x080c, 0x989d, 0x080c, 0x9a0f, - 0x0005, 0x6004, 0x9086, 0x0040, 0x1120, 0x080c, 0x97e1, 0x080c, - 0x98ed, 0x2019, 0x0001, 0x080c, 0xa877, 0x080c, 0x989d, 0x080c, - 0x3246, 0x080c, 0xd576, 0x0096, 0x6114, 0x2148, 0x080c, 0xce56, - 0x0150, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, 0x080c, - 0x6dd1, 0x080c, 0xd041, 0x009e, 0x080c, 0xb101, 0x080c, 0x9a0f, - 0x0005, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, 0x0007, 0x8002, - 0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, 0x2009, 0x1a7e, - 0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, 0xa88e, 0x0005, + 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, - 0xc53c, 0xc53c, 0xc53c, 0xc53c, 0xc53c, 0xc53e, 0xc53c, 0xc53c, - 0xc5e4, 0xc53c, 0xc53c, 0xc53c, 0xc53c, 0xc53c, 0xc53c, 0xc53c, - 0xc53c, 0xc53c, 0xc53c, 0xc716, 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, - 0xc5dd, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0xb092, - 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xc5dd, 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, 0xca03, 0x003e, 0xd6cc, 0x01e8, - 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, - 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xca03, 0x2011, 0x0205, - 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, 0x2009, 0x0020, - 0xa98a, 0x0c68, 0x2950, 0x080c, 0xc9a2, 0x080c, 0x1a83, 0x009e, - 0x00ee, 0x00ae, 0x007e, 0x0005, 0x2001, 0x1989, 0x2004, 0x6042, - 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, 0x1118, 0xa87c, - 0xc0dc, 0xa87e, 0x6003, 0x0002, 0xa97c, 0xd1e4, 0x0904, 0xc711, - 0x6043, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x1500, 0xd1cc, 0x0904, 0xc6e0, 0xa978, 0xa868, 0xd0fc, 0x0904, - 0xc6a1, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, 0x00a6, 0x2150, - 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, 0xc66e, 0x9086, - 0x0028, 0x1904, 0xc65a, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x0804, - 0xc676, 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, 0xd190, - 0x0804, 0xc711, 0xd1dc, 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, - 0x080c, 0xd424, 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, - 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, - 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc509, 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, 0xd504, - 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0fc0, 0x001e, 0x0804, - 0xc70d, 0x0016, 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, - 0x0002, 0x01e0, 0x9086, 0x0028, 0x1128, 0xa87b, 0x001c, 0xb07b, - 0x001c, 0x00e0, 0xd1dc, 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, - 0x080c, 0xd424, 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, - 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, - 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc509, 0xa890, 0xb092, - 0xa88c, 0xb08e, 0xa87c, 0xb07e, 0x00ae, 0x080c, 0x0fc0, 0x009e, - 0x080c, 0xd504, 0xa974, 0x0016, 0x080c, 0xc9f3, 0x001e, 0x0468, - 0xa867, 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, - 0x9086, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00d0, 0xd1dc, 0x0148, - 0xa87b, 0x0015, 0x080c, 0xd424, 0x0118, 0xa974, 0xc1dc, 0xa976, - 0x0078, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0050, 0xa87b, 0x0000, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc509, - 0xa974, 0x0016, 0x080c, 0x6beb, 0x001e, 0xd1e4, 0x1120, 0x080c, - 0xb101, 0x009e, 0x0005, 0x080c, 0xd156, 0x0cd8, 0x6114, 0x0096, - 0x2148, 0xa97c, 0xd1e4, 0x190c, 0x1aa3, 0x009e, 0x0005, 0x080c, - 0x97e1, 0x0010, 0x080c, 0x989d, 0x080c, 0xce56, 0x01f0, 0x0096, - 0x6114, 0x2148, 0x080c, 0xd05e, 0x1118, 0x080c, 0xbae2, 0x00a0, - 0xa867, 0x0103, 0x2009, 0x180c, 0x210c, 0xd18c, 0x11b8, 0xd184, - 0x1190, 0x6108, 0xa97a, 0x918e, 0x0029, 0x1110, 0x080c, 0xed00, - 0xa877, 0x0000, 0x080c, 0x6dd1, 0x009e, 0x080c, 0xb101, 0x080c, - 0x98ed, 0x0804, 0x9a0f, 0xa87b, 0x0004, 0x0c90, 0xa87b, 0x0004, - 0x0c78, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, - 0x0005, 0xc76d, 0xc76d, 0xc76d, 0xc76d, 0xc76d, 0xc76f, 0xc76d, - 0xc76d, 0xc76d, 0xc76d, 0xc76d, 0xc76d, 0xc76d, 0xc76d, 0xc76d, - 0xc76d, 0xc76d, 0xc76d, 0xc76d, 0xc76d, 0x080c, 0x0dc5, 0x080c, - 0x57db, 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, 0x6dd1, - 0x009e, 0x0804, 0xb101, 0x9182, 0x0085, 0x0002, 0xc7a5, 0xc7a3, - 0xc7a3, 0xc7b1, 0xc7a3, 0xc7a3, 0xc7a3, 0xc7a3, 0xc7a3, 0xc7a3, - 0xc7a3, 0xc7a3, 0xc7a3, 0x080c, 0x0dc5, 0x6003, 0x0001, 0x6106, - 0x080c, 0x933b, 0x0126, 0x2091, 0x8000, 0x080c, 0x98ed, 0x012e, - 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0x0260, 0x7224, - 0x6216, 0x7220, 0x080c, 0xce44, 0x01f8, 0x2268, 0x6800, 0x9086, - 0x0000, 0x01d0, 0x6010, 0x6d10, 0x952e, 0x11b0, 0x00c6, 0x2d60, - 0x00d6, 0x080c, 0xca64, 0x00de, 0x00ce, 0x0158, 0x702c, 0xd084, - 0x1118, 0x080c, 0xca2e, 0x0010, 0x6803, 0x0002, 0x6007, 0x0086, - 0x0028, 0x080c, 0xca50, 0x0d90, 0x6007, 0x0087, 0x6003, 0x0001, - 0x080c, 0x933b, 0x080c, 0x98ed, 0x7220, 0x080c, 0xce44, 0x0178, - 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, 0x6824, - 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, 0xd190, 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, 0x97e1, 0x0096, 0x6014, 0x2048, 0x080c, - 0xce56, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0029, - 0x080c, 0x6dd1, 0x009e, 0x080c, 0xb134, 0x0804, 0x98ed, 0xc834, - 0xc836, 0xc836, 0xc834, 0xc834, 0xc834, 0xc834, 0xc834, 0xc834, - 0xc834, 0xc834, 0xc834, 0xc834, 0x080c, 0x0dc5, 0x080c, 0x97e1, - 0x080c, 0xb134, 0x080c, 0x98ed, 0x0005, 0x9186, 0x0013, 0x1128, - 0x6004, 0x9082, 0x0085, 0x2008, 0x04b8, 0x9186, 0x0027, 0x11f8, - 0x080c, 0x97e1, 0x080c, 0x3246, 0x080c, 0xd576, 0x0096, 0x6014, - 0x2048, 0x080c, 0xce56, 0x0150, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0029, 0x080c, 0x6dd1, 0x080c, 0xd041, 0x009e, 0x080c, - 0xb101, 0x080c, 0x98ed, 0x0005, 0x080c, 0xb19b, 0x0ce0, 0x9186, - 0x0014, 0x1dd0, 0x080c, 0x97e1, 0x0096, 0x6014, 0x2048, 0x080c, - 0xce56, 0x0d60, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0006, - 0xa880, 0xc0ec, 0xa882, 0x08f0, 0x0002, 0xc88c, 0xc88a, 0xc88a, - 0xc88a, 0xc88a, 0xc88a, 0xc8a4, 0xc88a, 0xc88a, 0xc88a, 0xc88a, - 0xc88a, 0xc88a, 0x080c, 0x0dc5, 0x080c, 0x97e1, 0x6034, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, - 0x2001, 0x1987, 0x0010, 0x2001, 0x1988, 0x2004, 0x601a, 0x6003, - 0x000c, 0x080c, 0x98ed, 0x0005, 0x080c, 0x97e1, 0x6034, 0x908c, + 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, - 0x2001, 0x1987, 0x0010, 0x2001, 0x1988, 0x2004, 0x601a, 0x6003, - 0x000e, 0x080c, 0x98ed, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, - 0x0085, 0x0208, 0x0012, 0x0804, 0xb19b, 0xc8d2, 0xc8d2, 0xc8d2, - 0xc8d2, 0xc8d4, 0xc921, 0xc8d2, 0xc8d2, 0xc8d2, 0xc8d2, 0xc8d2, - 0xc8d2, 0xc8d2, 0x080c, 0x0dc5, 0x0096, 0x6010, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, 0xff00, 0x810f, - 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x009e, 0x0804, - 0xc935, 0x080c, 0xce56, 0x1118, 0x080c, 0xd041, 0x0068, 0x6014, - 0x2048, 0xa87c, 0xd0e4, 0x1110, 0x080c, 0xd041, 0xa867, 0x0103, - 0x080c, 0xd541, 0x080c, 0x6dd1, 0x00d6, 0x2c68, 0x080c, 0xb0ab, - 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, - 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x6910, - 0x6112, 0x080c, 0xd2d2, 0x6954, 0x6156, 0x6023, 0x0001, 0x080c, - 0x933b, 0x080c, 0x98ed, 0x2d60, 0x00de, 0x080c, 0xb101, 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, - 0xd4d7, 0x11f0, 0x080c, 0xb0ab, 0x01d8, 0x6106, 0x6003, 0x0001, - 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, 0x6930, 0x6132, - 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, 0x693c, 0x613e, - 0x6954, 0x6156, 0x080c, 0xd2d2, 0x080c, 0x933b, 0x080c, 0x98ed, - 0x2d60, 0x00de, 0x0804, 0xb101, 0x0096, 0x6014, 0x2048, 0x080c, - 0xce56, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, 0x0128, 0xc0ec, - 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, - 0x0020, 0xa87b, 0x0005, 0x080c, 0xd152, 0xa877, 0x0000, 0x080c, - 0x6dd1, 0x080c, 0xd041, 0x009e, 0x0804, 0xb101, 0x0016, 0x0096, - 0x6014, 0x2048, 0x080c, 0xce56, 0x0140, 0xa867, 0x0103, 0xa87b, - 0x0028, 0xa877, 0x0000, 0x080c, 0x6dd1, 0x009e, 0x001e, 0x9186, - 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, - 0x080c, 0xb19b, 0x0030, 0x080c, 0x97e1, 0x080c, 0xb134, 0x080c, - 0x98ed, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, 0x2029, 0x0001, - 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, 0x8304, - 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, 0x080c, 0xca03, - 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, 0x6dd1, 0x2a48, 0x0cb8, 0x080c, - 0x6dd1, 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, 0xce56, 0x0150, 0x2001, - 0x0006, 0xa980, 0xc1d5, 0x080c, 0x703d, 0x080c, 0x6dc4, 0x080c, - 0xd041, 0x009e, 0x080c, 0xb134, 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, 0xca9f, 0xca9f, - 0xca9a, 0xcac1, 0xca8d, 0xca9a, 0xcac1, 0xca9a, 0xca9a, 0x911f, - 0xca9a, 0xca9a, 0xca9a, 0xca8d, 0xca8d, 0x080c, 0x0dc5, 0x0036, - 0x2019, 0x0010, 0x080c, 0xe4c8, 0x6023, 0x0006, 0x6003, 0x0007, - 0x003e, 0x0005, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x0096, - 0x86ff, 0x11d8, 0x6014, 0x2048, 0x080c, 0xce56, 0x01c0, 0xa864, - 0x9086, 0x0139, 0x1128, 0xa87b, 0x0005, 0xa883, 0x0000, 0x0028, - 0x900e, 0x2001, 0x0005, 0x080c, 0x703d, 0x080c, 0xd152, 0x080c, - 0x6dc4, 0x080c, 0xb134, 0x9085, 0x0001, 0x009e, 0x0005, 0x9006, - 0x0ce0, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0002, 0xcad7, - 0xcb07, 0xcad9, 0xcb28, 0xcb02, 0xcad7, 0xca9a, 0xca9f, 0xca9f, - 0xca9a, 0xca9a, 0xca9a, 0xca9a, 0xca9a, 0xca9a, 0xca9a, 0x080c, - 0x0dc5, 0x86ff, 0x1520, 0x6020, 0x9086, 0x0006, 0x0500, 0x0096, - 0x6014, 0x2048, 0x080c, 0xce56, 0x0168, 0xa87c, 0xd0cc, 0x0140, - 0x0096, 0xc0cc, 0xa87e, 0xa878, 0x2048, 0x080c, 0x0fc0, 0x009e, - 0x080c, 0xd152, 0x009e, 0x080c, 0xd51b, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x080c, 0x933b, 0x080c, 0x98ed, 0x9085, - 0x0001, 0x0005, 0x0066, 0x080c, 0x1ab7, 0x006e, 0x0890, 0x00e6, - 0x2071, 0x19e9, 0x7024, 0x9c06, 0x1120, 0x080c, 0xa801, 0x00ee, - 0x0840, 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, - 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0xa929, 0x009e, 0x008e, - 0x0010, 0x080c, 0xa6fe, 0x00ee, 0x1904, 0xcad9, 0x0804, 0xca9a, - 0x0036, 0x00e6, 0x2071, 0x19e9, 0x703c, 0x9c06, 0x1138, 0x901e, - 0x080c, 0xa877, 0x00ee, 0x003e, 0x0804, 0xcad9, 0x080c, 0xaa59, - 0x00ee, 0x003e, 0x1904, 0xcad9, 0x0804, 0xca9a, 0x00c6, 0x6020, - 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xcb5b, 0xcc25, 0xcd8f, - 0xcb65, 0xb134, 0xcb5b, 0xe4ba, 0xd583, 0xcc25, 0x90f1, 0xce1b, - 0xcb54, 0xcb54, 0xcb54, 0xcb54, 0x080c, 0x0dc5, 0x080c, 0xd05e, - 0x1110, 0x080c, 0xbae2, 0x0005, 0x080c, 0x97e1, 0x080c, 0x98ed, - 0x0804, 0xb101, 0x601b, 0x0001, 0x0005, 0x080c, 0xce56, 0x0130, - 0x6014, 0x0096, 0x2048, 0x2c00, 0xa896, 0x009e, 0x6000, 0x908a, - 0x0010, 0x1a0c, 0x0dc5, 0x0002, 0xcb84, 0xcb86, 0xcbaa, 0xcbbe, - 0xcbe4, 0xcb84, 0xcb5b, 0xcb5b, 0xcb5b, 0xcbbe, 0xcbbe, 0xcb84, - 0xcb84, 0xcb84, 0xcb84, 0xcbc8, 0x080c, 0x0dc5, 0x00e6, 0x6014, - 0x0096, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x2071, 0x19e9, - 0x7024, 0x9c06, 0x01a0, 0x080c, 0xa6fe, 0x080c, 0xd51b, 0x6007, - 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, 0x1988, 0x2004, - 0x601a, 0x080c, 0x933b, 0x080c, 0x98ed, 0x00ee, 0x0005, 0x601b, - 0x0001, 0x0cd8, 0x0096, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, - 0x009e, 0x080c, 0xd51b, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x080c, 0x933b, 0x080c, 0x98ed, 0x0005, 0x0096, 0x601b, - 0x0001, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x0005, - 0x080c, 0x57db, 0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, 0xa864, - 0xa867, 0x0103, 0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, 0xa867, - 0x0139, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, 0x080c, - 0x6dd1, 0x009e, 0x0804, 0xb101, 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, 0x2397, 0x00ce, 0x6000, - 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0xb180, 0x0005, - 0x009e, 0x080c, 0x1ab7, 0x0804, 0xcbaa, 0x6000, 0x908a, 0x0010, - 0x1a0c, 0x0dc5, 0x000b, 0x0005, 0xcc3c, 0xcb62, 0xcc3e, 0xcc3c, - 0xcc3e, 0xcc3e, 0xcb5c, 0xcc3c, 0xcb56, 0xcb56, 0xcc3c, 0xcc3c, - 0xcc3c, 0xcc3c, 0xcc3c, 0xcc3c, 0x080c, 0x0dc5, 0x6010, 0x00b6, - 0x2058, 0xb804, 0x9084, 0x00ff, 0x00be, 0x908a, 0x000c, 0x1a0c, - 0x0dc5, 0x00b6, 0x0013, 0x00be, 0x0005, 0xcc59, 0xcd26, 0xcc5b, - 0xcc9b, 0xcc5b, 0xcc9b, 0xcc5b, 0xcc69, 0xcc59, 0xcc9b, 0xcc59, - 0xcc8a, 0x080c, 0x0dc5, 0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, - 0x0004, 0x05a8, 0x908e, 0x0002, 0x0590, 0x908e, 0x0052, 0x0904, - 0xcd22, 0x6004, 0x080c, 0xd05e, 0x0904, 0xcd3f, 0x908e, 0x0004, - 0x1110, 0x080c, 0x326f, 0x908e, 0x0021, 0x0904, 0xcd43, 0x908e, - 0x0022, 0x0904, 0xcd8a, 0x908e, 0x003d, 0x0904, 0xcd43, 0x908e, - 0x0039, 0x0904, 0xcd47, 0x908e, 0x0035, 0x0904, 0xcd47, 0x908e, - 0x001e, 0x0178, 0x908e, 0x0001, 0x1140, 0x6010, 0x2058, 0xb804, - 0x9084, 0x00ff, 0x9086, 0x0006, 0x0110, 0x080c, 0x3246, 0x080c, - 0xbae2, 0x0804, 0xb134, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, - 0x0904, 0xcd13, 0x9186, 0x0002, 0x1904, 0xcce8, 0x2001, 0x1837, - 0x2004, 0xd08c, 0x11c8, 0x080c, 0x7569, 0x11b0, 0x080c, 0xd561, - 0x0138, 0x080c, 0x758c, 0x1120, 0x080c, 0x7473, 0x0804, 0xcd73, - 0x2001, 0x197e, 0x2003, 0x0001, 0x2001, 0x1800, 0x2003, 0x0001, - 0x080c, 0x7495, 0x0804, 0xcd73, 0x6010, 0x2058, 0x2001, 0x1837, - 0x2004, 0xd0ac, 0x1904, 0xcd73, 0xb8a0, 0x9084, 0xff80, 0x1904, - 0xcd73, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, 0xb842, - 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, - 0x080c, 0xb0ab, 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, 0x60ba, 0x00ee, 0x080c, - 0xbae2, 0x0030, 0x080c, 0xbae2, 0x080c, 0x3246, 0x080c, 0xd576, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x326f, 0x012e, 0x00ee, - 0x080c, 0xb134, 0x0005, 0x2001, 0x0002, 0x080c, 0x6663, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x9383, 0x080c, 0x98ed, 0x00de, - 0x00ce, 0x0c80, 0x080c, 0x326f, 0x0804, 0xcc97, 0x00c6, 0x00d6, - 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2058, 0xb840, 0x9084, - 0x00ff, 0x9005, 0x0904, 0xcce8, 0x8001, 0xb842, 0x6003, 0x0001, - 0x080c, 0x9383, 0x080c, 0x98ed, 0x00de, 0x00ce, 0x0898, 0x080c, - 0xbae2, 0x0804, 0xcc99, 0x080c, 0xbb1e, 0x0804, 0xcc99, 0x00d6, - 0x2c68, 0x6104, 0x080c, 0xd4d7, 0x00de, 0x0118, 0x080c, 0xb101, - 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, - 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c, 0x600a, - 0x2001, 0x1988, 0x2004, 0x601a, 0x602c, 0x2c08, 0x2060, 0x6024, - 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160, 0x080c, 0x933b, - 0x080c, 0x98ed, 0x0005, 0x00de, 0x00ce, 0x080c, 0xbae2, 0x080c, - 0x3246, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x326f, 0x6017, - 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, 0x012e, - 0x00ee, 0x0005, 0x080c, 0xb536, 0x1904, 0xcd3f, 0x0005, 0x6000, - 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0096, 0x00d6, 0x001b, 0x00de, - 0x009e, 0x0005, 0xcdaa, 0xcdaa, 0xcdaa, 0xcdaa, 0xcdaa, 0xcdaa, - 0xcdaa, 0xcdaa, 0xcdaa, 0xcb5b, 0xcdaa, 0xcb62, 0xcdac, 0xcb62, - 0xcdc6, 0xcdaa, 0x080c, 0x0dc5, 0x6004, 0x9086, 0x008b, 0x01b0, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, 0x1130, 0x602c, - 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, 0x6007, 0x008b, 0x6003, - 0x000d, 0x080c, 0x933b, 0x080c, 0x98ed, 0x0005, 0x080c, 0xd555, - 0x0118, 0x080c, 0xd568, 0x0010, 0x080c, 0xd576, 0x080c, 0xd041, - 0x080c, 0xce56, 0x0570, 0x080c, 0x3246, 0x080c, 0xce56, 0x0168, - 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, - 0xa880, 0xc0ed, 0xa882, 0x080c, 0x6dd1, 0x2c68, 0x080c, 0xb0ab, - 0x0150, 0x6810, 0x6012, 0x080c, 0xd2d2, 0x00c6, 0x2d60, 0x080c, - 0xb134, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023, 0x0001, - 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9383, 0x080c, 0x98ed, - 0x00c8, 0x080c, 0xd555, 0x0138, 0x6034, 0x9086, 0x4000, 0x1118, - 0x080c, 0x3246, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, - 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x3246, 0x0868, - 0x080c, 0xb134, 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0dc5, - 0x0002, 0xce31, 0xce31, 0xce35, 0xce33, 0xce3f, 0xce31, 0xce31, - 0xb134, 0xce31, 0xce31, 0xce31, 0xce31, 0xce31, 0xce31, 0xce31, - 0xce31, 0x080c, 0x0dc5, 0x080c, 0xaa59, 0x6114, 0x0096, 0x2148, - 0xa87b, 0x0006, 0x080c, 0x6dd1, 0x009e, 0x0804, 0xb101, 0x601c, - 0xd084, 0x190c, 0x1ab7, 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, 0xd561, 0x0180, 0x9286, 0x0001, 0x1168, 0x6004, 0x9086, - 0x0004, 0x1148, 0x080c, 0x3246, 0x080c, 0xd576, 0x00c6, 0x080c, - 0xb134, 0x00ce, 0x0060, 0x080c, 0xd24c, 0x0148, 0x080c, 0xd05e, - 0x1110, 0x080c, 0xbae2, 0x00c6, 0x080c, 0xb101, 0x00ce, 0x9ce0, - 0x0018, 0x7068, 0x9c02, 0x1208, 0x08a0, 0x012e, 0x000e, 0x003e, - 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0x9188, 0x1000, - 0x210c, 0x81ff, 0x0128, 0x2061, 0x1ab8, 0x6112, 0x080c, 0x3246, - 0x9006, 0x0010, 0x9085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, - 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb0ab, 0x01b0, 0x6656, - 0x2b00, 0x6012, 0x080c, 0x57db, 0x0118, 0x080c, 0xcf85, 0x0168, - 0x080c, 0xd2d2, 0x6023, 0x0003, 0x2009, 0x004b, 0x080c, 0xb180, - 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, - 0x0126, 0x2091, 0x8000, 0xbaa0, 0x080c, 0xb153, 0x0560, 0x6057, - 0x0000, 0x2b00, 0x6012, 0x080c, 0xd2d2, 0x6023, 0x0003, 0x0016, - 0x080c, 0x94e0, 0x0076, 0x903e, 0x080c, 0x93b3, 0x2c08, 0x080c, - 0xe690, 0x007e, 0x001e, 0xd184, 0x0128, 0x080c, 0xb101, 0x9085, - 0x0001, 0x0070, 0x080c, 0x57db, 0x0128, 0xd18c, 0x1170, 0x080c, - 0xcf85, 0x0148, 0x2009, 0x004c, 0x080c, 0xb180, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2900, 0x6016, 0x0c90, - 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, 0x00c6, 0x0046, - 0x0016, 0x080c, 0xb0ab, 0x2c78, 0x05a0, 0x7e56, 0x2b00, 0x7812, - 0x7823, 0x0003, 0x0016, 0x2021, 0x0005, 0x080c, 0xcf97, 0x001e, - 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148, 0x2001, 0x1981, - 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0xb101, 0x00d0, 0x2001, - 0x1980, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xb101, 0x0088, - 0x2f60, 0x080c, 0x57db, 0x0138, 0xd18c, 0x1118, 0x04f1, 0x0148, - 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, 0x080c, 0xb180, 0x9085, - 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, - 0x0046, 0x080c, 0xb0ab, 0x2c78, 0x0508, 0x7e56, 0x2b00, 0x7812, - 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, 0x0489, 0x009e, 0x2001, - 0x197f, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xb101, 0x0060, - 0x2f60, 0x080c, 0x57db, 0x0120, 0xd18c, 0x1160, 0x0071, 0x0130, - 0x2009, 0x0052, 0x080c, 0xb180, 0x9085, 0x0001, 0x004e, 0x00ce, - 0x00fe, 0x0005, 0x2900, 0x7816, 0x0c98, 0x00c6, 0x080c, 0x4b89, - 0x00ce, 0x1120, 0x080c, 0xb101, 0x9006, 0x0005, 0xa867, 0x0000, - 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, 0x0001, 0x0005, 0x0096, - 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x6851, 0x0158, 0x2001, - 0xcf9c, 0x0006, 0x900e, 0x2400, 0x080c, 0x703d, 0x080c, 0x6dd1, - 0x000e, 0x0807, 0x2418, 0x080c, 0x977b, 0xbaa0, 0x0086, 0x2041, - 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x94f8, 0x008e, 0x080c, - 0x93b3, 0x2f08, 0x2648, 0x080c, 0xe690, 0xb93c, 0x81ff, 0x090c, - 0x95cb, 0x080c, 0x98ed, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0xb0ab, 0x0190, 0x660a, 0x2b08, - 0x6112, 0x080c, 0xd2d2, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, - 0x001f, 0x080c, 0xb180, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb153, - 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, 0xd2d2, 0x6023, 0x0008, - 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, 0x1768, 0x00fe, 0x2009, - 0x0021, 0x080c, 0xb180, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, 0x0126, 0x0016, 0x2091, - 0x8000, 0x080c, 0xb0ab, 0x0198, 0x660a, 0x2b08, 0x6112, 0x080c, - 0xd2d2, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, 0x0016, 0x080c, - 0xb180, 0x9085, 0x0001, 0x001e, 0x012e, 0x00ce, 0x0005, 0x9006, - 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb153, 0x0188, - 0x2b08, 0x6112, 0x080c, 0xd2d2, 0x6023, 0x0001, 0x2900, 0x6016, - 0x2009, 0x0000, 0x080c, 0xb180, 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, - 0xce56, 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, 0xb153, 0x0198, 0x2b08, - 0x6112, 0x080c, 0xd2d2, 0x6023, 0x0001, 0x2900, 0x6016, 0x080c, - 0x3246, 0x2009, 0x0028, 0x080c, 0xb180, 0x9085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, 0x11a8, 0x2011, - 0x1824, 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6, 0x080c, 0xbd38, - 0x00be, 0x080c, 0xbf5d, 0x6003, 0x0001, 0x6007, 0x0029, 0x080c, - 0x9383, 0x080c, 0x98ed, 0x0078, 0x6014, 0x0096, 0x2048, 0xa868, - 0x009e, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, 0xd498, 0x080c, - 0xbae2, 0x080c, 0xb101, 0x0005, 0x0096, 0x6014, 0x904d, 0x090c, - 0x0dc5, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, - 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, 0x6dd1, - 0x012e, 0x009e, 0x080c, 0xb101, 0x0c30, 0x0096, 0x9186, 0x0016, - 0x1128, 0x2001, 0x0004, 0x080c, 0x6663, 0x00e8, 0x9186, 0x0015, - 0x1510, 0x2011, 0x1824, 0x2204, 0x9086, 0x0014, 0x11e0, 0x6010, - 0x00b6, 0x2058, 0x080c, 0x67b8, 0x00be, 0x080c, 0xc033, 0x1198, - 0x6010, 0x00b6, 0x2058, 0xb890, 0x00be, 0x9005, 0x0160, 0x2001, - 0x0006, 0x080c, 0x6663, 0x6014, 0x2048, 0xa868, 0xd0fc, 0x0170, - 0x080c, 0xb50a, 0x0048, 0x6014, 0x2048, 0xa868, 0xd0fc, 0x0528, - 0x080c, 0xbae2, 0x080c, 0xb101, 0x009e, 0x0005, 0x6014, 0x6310, - 0x2358, 0x904d, 0x090c, 0x0dc5, 0xa87b, 0x0000, 0xa883, 0x0000, - 0xa897, 0x4000, 0x900e, 0x080c, 0x693d, 0x1108, 0xc185, 0xb800, - 0xd0bc, 0x0108, 0xc18d, 0xa99a, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6dd1, 0x012e, 0x080c, 0xb101, 0x08f8, 0x6014, 0x904d, 0x090c, - 0x0dc5, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, - 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, 0x6dd1, - 0x012e, 0x080c, 0xb101, 0x0840, 0xa878, 0x9086, 0x0005, 0x1108, - 0x0009, 0x0005, 0xa880, 0xc0ad, 0xa882, 0x0005, 0x6043, 0x0000, - 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x933b, - 0x080c, 0x98ed, 0x0005, 0x00c6, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x0120, 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, - 0x0005, 0xcb5b, 0xd182, 0xd182, 0xd185, 0xe9f4, 0xea0f, 0xea12, - 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5b, - 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, 0xb0ab, - 0x0508, 0x7810, 0x6012, 0x080c, 0xd2d2, 0x7820, 0x9086, 0x0003, - 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, 0x7808, 0x603e, - 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, 0x6007, 0x0035, 0x6003, - 0x0001, 0x7954, 0x6156, 0x080c, 0x933b, 0x080c, 0x98ed, 0x2f60, - 0x00fe, 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1989, 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, 0x933b, - 0x080c, 0x98ed, 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, 0x1983, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, - 0x080c, 0x91b1, 0x2001, 0x1987, 0x82ff, 0x1110, 0x2011, 0x0014, - 0x2202, 0x2001, 0x1985, 0x200c, 0x8000, 0x2014, 0x2071, 0x196d, - 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x91b1, 0x2001, 0x1988, - 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1989, 0x9288, - 0x000a, 0x2102, 0x2001, 0x1a99, 0x2102, 0x2001, 0x0032, 0x080c, - 0x1611, 0x080c, 0x6a73, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, - 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, 0x1987, 0x2003, 0x0028, - 0x2001, 0x1988, 0x2003, 0x0014, 0x2071, 0x196d, 0x701b, 0x0000, - 0x701f, 0x07d0, 0x2001, 0x1989, 0x2009, 0x001e, 0x2102, 0x2001, - 0x1a99, 0x2102, 0x2001, 0x0032, 0x080c, 0x1611, 0x00ee, 0x001e, - 0x000e, 0x0005, 0x0096, 0x6058, 0x904d, 0x0110, 0x080c, 0x1040, - 0x009e, 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, - 0xb0ab, 0x0180, 0x2b08, 0x6112, 0x0ca9, 0x6023, 0x0001, 0x2900, - 0x6016, 0x2009, 0x0033, 0x080c, 0xb180, 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, 0x9b88, 0x01d8, 0x707c, 0xaa50, 0x9206, - 0x1160, 0x7080, 0xaa54, 0x9206, 0x1140, 0x6210, 0x00b6, 0x2258, - 0xbaa0, 0x00be, 0x900e, 0x080c, 0x328f, 0x080c, 0xb50a, 0x0020, - 0x080c, 0xbae2, 0x080c, 0xb101, 0x00fe, 0x00ee, 0x009e, 0x0005, - 0x7060, 0xaa54, 0x9206, 0x0d48, 0x0c80, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0xb0ab, 0x0188, 0x2b08, 0x6112, 0x080c, 0xd2d2, - 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x004d, 0x080c, 0xb180, - 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, 0xb0ab, 0x0180, 0x2b08, - 0x6112, 0x080c, 0xd2d2, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, - 0x080c, 0xb180, 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, 0x19a2, 0x2003, 0x0000, 0x6014, 0x2048, 0xa830, - 0x20a8, 0x8906, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e8, 0x9084, - 0xffc0, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a2, 0x0016, 0x200c, - 0x080c, 0xdbac, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c38, - 0x6014, 0x2048, 0xa867, 0x0103, 0x0010, 0x080c, 0xbae2, 0x080c, - 0xb101, 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, 0x9b88, 0x01a8, 0x707c, 0xaa74, 0x9206, - 0x1130, 0x7080, 0xaa78, 0x9206, 0x1110, 0x080c, 0x3246, 0x080c, - 0xb50a, 0x0020, 0x080c, 0xbae2, 0x080c, 0xb101, 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, 0x9b88, - 0x05f0, 0x707c, 0xaacc, 0x9206, 0x1180, 0x7080, 0xaad0, 0x9206, - 0x1160, 0x080c, 0x3246, 0x0016, 0xa998, 0xaab0, 0x9284, 0x1000, - 0xc0fd, 0x080c, 0x5782, 0x001e, 0x0010, 0x080c, 0x556d, 0x080c, - 0xce56, 0x0508, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, - 0x0080, 0x080c, 0xce56, 0x01b8, 0x6014, 0x2048, 0x080c, 0x556d, - 0x1d70, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, - 0x0004, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0x080c, 0x6dd1, - 0x012e, 0x080c, 0xb101, 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, 0xce56, - 0x0904, 0xd494, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x929e, - 0x4000, 0x1580, 0x6310, 0x00c6, 0x2358, 0x2009, 0x0000, 0xa868, - 0xd0f4, 0x1140, 0x080c, 0x693d, 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, - 0x6dc4, 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, 0x2894, 0x2118, 0x831f, 0x939c, - 0xff00, 0x7838, 0x9084, 0x00ff, 0x931d, 0x7c3c, 0x2011, 0x8018, - 0x080c, 0x4be9, 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, 0xce44, 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, 0xc509, 0x0005, 0x0036, 0x2019, 0x0001, 0x0010, 0x0036, - 0x901e, 0x0499, 0x01e0, 0x080c, 0xce56, 0x01c8, 0x080c, 0xd041, - 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, 0x0096, 0x2048, 0xa87c, - 0x080c, 0xd05e, 0x1118, 0x080c, 0xbae2, 0x0040, 0xa867, 0x0103, - 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x6dd1, 0x009e, 0x003e, - 0x0005, 0xa880, 0xd0b4, 0x0128, 0xa87b, 0x0006, 0xc0ec, 0xa882, - 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, - 0x080c, 0xd152, 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, 0x4da0, 0x004e, 0x003e, 0x0005, 0x0c51, 0x1d81, - 0x0005, 0x2001, 0x1987, 0x2004, 0x601a, 0x0005, 0x2001, 0x1989, - 0x2004, 0x6042, 0x0005, 0x080c, 0xb101, 0x0804, 0x98ed, 0x2001, - 0x0109, 0x2004, 0xd084, 0x01e0, 0x0126, 0x2091, 0x2800, 0x0006, - 0x0016, 0x0026, 0x0036, 0x00f6, 0x00e6, 0x00c6, 0x2079, 0x19e9, - 0x2071, 0x1800, 0x2061, 0x0100, 0x080c, 0x921e, 0x00ce, 0x00ee, - 0x00fe, 0x003e, 0x002e, 0x001e, 0x000e, 0x012e, 0x9085, 0x0001, - 0x0005, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0dc5, - 0x001b, 0x006e, 0x00be, 0x0005, 0xd5c4, 0xdd0b, 0xde80, 0xd5c4, - 0xd5c4, 0xd5c4, 0xd5c4, 0xd5c4, 0xd5fb, 0xdf04, 0xd5c4, 0xd5c4, - 0xd5c4, 0xd5c4, 0xd5c4, 0xd5c4, 0x080c, 0x0dc5, 0x0066, 0x6000, - 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, 0x0005, 0xd5df, - 0xe453, 0xd5df, 0xd5df, 0xd5df, 0xd5df, 0xd5df, 0xd5df, 0xe400, - 0xe4a7, 0xd5df, 0xeb2f, 0xeb65, 0xeb2f, 0xeb65, 0xd5df, 0x080c, - 0x0dc5, 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0dc5, 0x6000, 0x000a, - 0x0005, 0xd5f9, 0xe0e2, 0xe1b1, 0xe1d4, 0xe294, 0xd5f9, 0xe373, - 0xe31c, 0xdf10, 0xe3d6, 0xe3eb, 0xd5f9, 0xd5f9, 0xd5f9, 0xd5f9, - 0xd5f9, 0x080c, 0x0dc5, 0x91b2, 0x0053, 0x1a0c, 0x0dc5, 0x2100, - 0x91b2, 0x0040, 0x1a04, 0xda7b, 0x0002, 0xd645, 0xd849, 0xd645, - 0xd645, 0xd645, 0xd852, 0xd645, 0xd645, 0xd645, 0xd645, 0xd645, - 0xd645, 0xd645, 0xd645, 0xd645, 0xd645, 0xd645, 0xd645, 0xd645, - 0xd645, 0xd645, 0xd645, 0xd645, 0xd647, 0xd6aa, 0xd6b9, 0xd71d, - 0xd748, 0xd7c1, 0xd834, 0xd645, 0xd645, 0xd855, 0xd645, 0xd645, - 0xd86a, 0xd877, 0xd645, 0xd645, 0xd645, 0xd645, 0xd645, 0xd91d, - 0xd645, 0xd645, 0xd931, 0xd645, 0xd645, 0xd8ec, 0xd645, 0xd645, - 0xd645, 0xd949, 0xd645, 0xd645, 0xd645, 0xd9c6, 0xd645, 0xd645, - 0xd645, 0xd645, 0xd645, 0xd645, 0xda43, 0x080c, 0x0dc5, 0x080c, - 0x6a50, 0x1150, 0x2001, 0x1837, 0x2004, 0xd0cc, 0x1128, 0x9084, - 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, 0x602f, 0x0009, - 0x6017, 0x0000, 0x0804, 0xd842, 0x080c, 0x69ec, 0x00e6, 0x00c6, - 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, - 0x0029, 0x080c, 0x94e0, 0x0076, 0x903e, 0x080c, 0x93b3, 0x2c08, - 0x080c, 0xe690, 0x007e, 0x001e, 0x001e, 0x002e, 0x003e, 0x00ce, - 0x00ee, 0x6610, 0x2658, 0x080c, 0x672c, 0xbe04, 0x9684, 0x00ff, - 0x9082, 0x0006, 0x1268, 0x0016, 0x0026, 0x6210, 0x00b6, 0x2258, - 0xbaa0, 0x00be, 0x2c08, 0x080c, 0xed90, 0x002e, 0x001e, 0x1178, - 0x080c, 0xe5c2, 0x1904, 0xd715, 0x080c, 0xe55e, 0x1120, 0x6007, - 0x0008, 0x0804, 0xd842, 0x6007, 0x0009, 0x0804, 0xd842, 0x080c, - 0xe82d, 0x0128, 0x080c, 0xe5c2, 0x0d78, 0x0804, 0xd715, 0x6017, - 0x1900, 0x0c88, 0x080c, 0x336a, 0x1904, 0xda78, 0x6106, 0x080c, - 0xe502, 0x6007, 0x0006, 0x0804, 0xd842, 0x6007, 0x0007, 0x0804, - 0xd842, 0x080c, 0xeba1, 0x1904, 0xda78, 0x080c, 0x336a, 0x1904, - 0xda78, 0x00d6, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, - 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x664f, 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, 0xe626, 0x1190, 0x9686, 0x0006, - 0x1140, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x328f, - 0x002e, 0x080c, 0x67b8, 0x6007, 0x000a, 0x00de, 0x0804, 0xd842, - 0x6007, 0x000b, 0x00de, 0x0804, 0xd842, 0x080c, 0x3246, 0x080c, - 0xd576, 0x6007, 0x0001, 0x0804, 0xd842, 0x080c, 0xeba1, 0x1904, - 0xda78, 0x080c, 0x336a, 0x1904, 0xda78, 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, 0x328f, 0x002e, - 0x6007, 0x000c, 0x2001, 0x0001, 0x080c, 0xed6f, 0x0804, 0xd842, - 0x080c, 0x6a50, 0x1140, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, - 0x9086, 0x0008, 0x1110, 0x0804, 0xd654, 0x080c, 0x69ec, 0x6610, - 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06c8, 0x1138, - 0x0026, 0x2001, 0x0006, 0x080c, 0x668f, 0x002e, 0x0050, 0x96b4, - 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, - 0xd715, 0x080c, 0xe633, 0x1120, 0x6007, 0x000e, 0x0804, 0xd842, - 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x3246, 0x080c, - 0xd576, 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, - 0x0148, 0x2009, 0x0029, 0x080c, 0xe9a5, 0x6010, 0x2058, 0xb800, - 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, 0xd842, - 0x2001, 0x0001, 0x080c, 0x664f, 0x0156, 0x0016, 0x0026, 0x0036, - 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0270, 0x080c, 0xc0e3, - 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, - 0x8637, 0x9682, 0x0004, 0x0a04, 0xd715, 0x9682, 0x0007, 0x0a04, - 0xd771, 0x0804, 0xd715, 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, - 0xd842, 0x080c, 0x6a50, 0x1140, 0x2001, 0x1837, 0x2004, 0x9084, - 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xd654, 0x080c, 0x69ec, - 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, 0xd715, - 0x080c, 0xe661, 0x1138, 0x080c, 0xe55e, 0x1120, 0x6007, 0x0010, - 0x0804, 0xd842, 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, - 0x3246, 0x080c, 0xd576, 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, - 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, 0x080c, 0xe9a5, 0x6010, + 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, - 0x0448, 0x080c, 0xe82d, 0x0198, 0x0016, 0x968c, 0x00ff, 0x9186, - 0x0002, 0x0160, 0x9186, 0x0003, 0x0148, 0x001e, 0x96b4, 0xff00, - 0x8637, 0x9686, 0x0006, 0x0920, 0x0804, 0xd715, 0x001e, 0x6017, - 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, 0x336a, 0x1904, 0xda78, - 0x080c, 0xeba1, 0x1904, 0xda78, 0x080c, 0xdc49, 0x1904, 0xd715, - 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x9383, 0x080c, 0x98ed, - 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9383, 0x080c, - 0x98ed, 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c, 0xeba1, 0x1904, - 0xda78, 0x080c, 0x336a, 0x1904, 0xda78, 0x080c, 0xdc49, 0x1904, - 0xd715, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x9383, 0x080c, - 0x98ed, 0x0005, 0x080c, 0x336a, 0x1904, 0xda78, 0x6007, 0x0023, - 0x6003, 0x0001, 0x080c, 0x9383, 0x080c, 0x98ed, 0x0005, 0x080c, - 0xeba1, 0x1904, 0xda78, 0x080c, 0x336a, 0x1904, 0xda78, 0x080c, - 0xdc49, 0x1904, 0xd715, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, - 0x2c08, 0x2011, 0x1820, 0x2214, 0x703c, 0x9206, 0x11e0, 0x2011, - 0x181f, 0x2214, 0x7038, 0x9084, 0x00ff, 0x9206, 0x11a0, 0x7240, - 0x080c, 0xce44, 0x0570, 0x2260, 0x6008, 0x9086, 0xffff, 0x0120, - 0x7244, 0x6008, 0x9206, 0x1528, 0x6020, 0x9086, 0x0007, 0x1508, - 0x080c, 0xb101, 0x04a0, 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, - 0x080c, 0xce44, 0x01b0, 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, - 0x6010, 0x9190, 0x0004, 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, - 0x2c08, 0x9006, 0x080c, 0xe96f, 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, 0xb101, 0x2160, - 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x9383, 0x080c, 0x98ed, - 0x00ee, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x664f, - 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, - 0x2011, 0x0276, 0x080c, 0xc0e3, 0x003e, 0x002e, 0x001e, 0x015e, - 0x0120, 0x6007, 0x0031, 0x0804, 0xd842, 0x080c, 0xbd50, 0x080c, - 0x7569, 0x1190, 0x0006, 0x0026, 0x0036, 0x080c, 0x7583, 0x1138, - 0x080c, 0x784e, 0x080c, 0x6127, 0x080c, 0x7495, 0x0010, 0x080c, - 0x7541, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, 0x336a, 0x1904, - 0xda78, 0x080c, 0xdc49, 0x1904, 0xd715, 0x6106, 0x080c, 0xdc65, - 0x1120, 0x6007, 0x002b, 0x0804, 0xd842, 0x6007, 0x002c, 0x0804, - 0xd842, 0x080c, 0xeba1, 0x1904, 0xda78, 0x080c, 0x336a, 0x1904, - 0xda78, 0x080c, 0xdc49, 0x1904, 0xd715, 0x6106, 0x080c, 0xdc6a, - 0x1120, 0x6007, 0x002e, 0x0804, 0xd842, 0x6007, 0x002f, 0x0804, - 0xd842, 0x080c, 0x336a, 0x1904, 0xda78, 0x00e6, 0x00d6, 0x00c6, - 0x6010, 0x2058, 0xb904, 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, - 0x9184, 0xff00, 0x8007, 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, - 0x00ee, 0x0804, 0xd849, 0x080c, 0x57d7, 0xd0e4, 0x0904, 0xd9c3, - 0x2071, 0x026c, 0x7010, 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, - 0x080c, 0x6a8e, 0x0140, 0x6010, 0x2058, 0xb810, 0x9106, 0x1118, - 0xb814, 0x9206, 0x0510, 0x080c, 0x6a8a, 0x15b8, 0x2069, 0x1800, - 0x6880, 0x9206, 0x1590, 0x687c, 0x9106, 0x1578, 0x7210, 0x080c, - 0xce44, 0x0590, 0x080c, 0xdb36, 0x0578, 0x080c, 0xea21, 0x0560, - 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x933b, 0x080c, - 0x98ed, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, - 0x0150, 0x080c, 0xce44, 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, - 0x9106, 0x1190, 0x08e0, 0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, - 0xe96f, 0x2c10, 0x2160, 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, - 0x0009, 0x6017, 0x1500, 0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, - 0x6017, 0x1700, 0x0880, 0x6007, 0x0012, 0x0868, 0x080c, 0x336a, - 0x1904, 0xda78, 0x6010, 0x2058, 0xb804, 0x9084, 0xff00, 0x8007, - 0x9086, 0x0006, 0x1904, 0xd849, 0x00e6, 0x00d6, 0x00c6, 0x080c, - 0x57d7, 0xd0e4, 0x0904, 0xda3b, 0x2069, 0x1800, 0x2071, 0x026c, - 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, 0xffff, 0x1150, 0x7208, - 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, 0xe96f, 0x2c10, 0x00ce, - 0x05e8, 0x080c, 0xce44, 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, - 0x9106, 0x15a0, 0x00c6, 0x0026, 0x2260, 0x080c, 0xca64, 0x002e, - 0x00ce, 0x7118, 0x918c, 0xff00, 0x810f, 0x9186, 0x0001, 0x0178, - 0x9186, 0x0005, 0x0118, 0x9186, 0x0007, 0x1198, 0x9280, 0x0005, - 0x2004, 0x9005, 0x0170, 0x080c, 0xdb36, 0x0904, 0xd9bc, 0x0056, - 0x7510, 0x7614, 0x080c, 0xea3a, 0x005e, 0x00ce, 0x00de, 0x00ee, - 0x0005, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, - 0x0001, 0x080c, 0x933b, 0x080c, 0x98ed, 0x0c78, 0x6007, 0x003b, - 0x602f, 0x0003, 0x6017, 0x0300, 0x6003, 0x0001, 0x080c, 0x933b, - 0x080c, 0x98ed, 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, - 0x0000, 0x0804, 0xd993, 0x00e6, 0x0026, 0x080c, 0x6a50, 0x0550, - 0x080c, 0x69ec, 0x080c, 0xec12, 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, 0x6a8e, 0x0120, 0x2011, - 0x1a02, 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x3019, 0x0010, - 0x080c, 0xec46, 0x002e, 0x00ee, 0x080c, 0xb101, 0x0804, 0xd848, - 0x080c, 0xb101, 0x0005, 0x2600, 0x0002, 0xda8f, 0xdabd, 0xdace, - 0xda8f, 0xda8f, 0xda91, 0xdadf, 0xda8f, 0xda8f, 0xda8f, 0xdaab, - 0xda8f, 0xda8f, 0xda8f, 0xdaea, 0xdb00, 0xdb31, 0xda8f, 0x080c, - 0x0dc5, 0x080c, 0xeba1, 0x1d20, 0x080c, 0x336a, 0x1d08, 0x7038, - 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x9383, 0x0005, - 0x080c, 0x3246, 0x080c, 0xd576, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x9383, 0x0005, 0x080c, 0xeba1, 0x1950, 0x080c, 0x336a, - 0x1938, 0x080c, 0xdc49, 0x1d60, 0x703c, 0x6016, 0x6007, 0x004a, - 0x6003, 0x0001, 0x080c, 0x9383, 0x0005, 0x080c, 0x336a, 0x1904, - 0xda78, 0x2009, 0x0041, 0x080c, 0xec4f, 0x6007, 0x0047, 0x6003, - 0x0001, 0x080c, 0x9383, 0x080c, 0x98ed, 0x0005, 0x080c, 0x336a, - 0x1904, 0xda78, 0x2009, 0x0042, 0x080c, 0xec4f, 0x6007, 0x0047, - 0x6003, 0x0001, 0x080c, 0x9383, 0x080c, 0x98ed, 0x0005, 0x080c, - 0x336a, 0x1904, 0xda78, 0x2009, 0x0046, 0x080c, 0xec4f, 0x080c, - 0xb101, 0x0005, 0x2001, 0x1824, 0x2004, 0x9082, 0x00e1, 0x1268, - 0x080c, 0xdb53, 0x0904, 0xda78, 0x6007, 0x004e, 0x6003, 0x0001, - 0x080c, 0x9383, 0x080c, 0x98ed, 0x0005, 0x6007, 0x0012, 0x0cb0, - 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, 0x00ff, 0x81ff, - 0x0508, 0x9186, 0x0001, 0x1160, 0x7140, 0x2001, 0x19bf, 0x2004, - 0x9106, 0x11b0, 0x7144, 0x2001, 0x19c0, 0x2004, 0x9106, 0x0190, - 0x9186, 0x0002, 0x1168, 0x2011, 0x0276, 0x20a9, 0x0004, 0x6010, - 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xc0f7, 0x009e, 0x0110, - 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, 0x9383, 0x080c, 0x98ed, - 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, 0x19a2, 0x2003, 0x0000, 0x080c, 0x1027, 0x05a0, 0x2900, - 0x6016, 0x7090, 0x8004, 0xa816, 0x908a, 0x001e, 0x02d0, 0xa833, - 0x001e, 0x20a9, 0x001e, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, - 0x20a0, 0x2001, 0x19a2, 0x0016, 0x200c, 0x0471, 0x001e, 0x81ff, - 0x01b8, 0x2940, 0x080c, 0x1027, 0x01b0, 0x2900, 0xa006, 0x2100, - 0x0c18, 0xa832, 0x20a8, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, - 0x20a0, 0x2001, 0x19a2, 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, 0x240b, 0x2099, 0x026c, - 0x2001, 0x0014, 0x3518, 0x9312, 0x0108, 0x1218, 0x23a8, 0x4003, - 0x0400, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x240b, 0x2099, - 0x0260, 0x0ca8, 0x080c, 0x240b, 0x2061, 0x19a2, 0x6004, 0x2098, - 0x6008, 0x3518, 0x9312, 0x0108, 0x1218, 0x23a8, 0x4003, 0x0048, - 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x240b, 0x2099, 0x0260, - 0x0ca8, 0x2061, 0x19a2, 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, 0x2423, 0x20a1, 0x024c, 0x2001, 0x0014, 0x3518, - 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, 0x20a8, 0x4003, 0x82ff, - 0x01f8, 0x22a8, 0x8108, 0x080c, 0x2423, 0x20a1, 0x0240, 0x0c98, - 0x080c, 0x2423, 0x2061, 0x19a5, 0x6004, 0x20a0, 0x6008, 0x3518, - 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, 0x20a8, 0x4003, 0x82ff, - 0x0138, 0x22a8, 0x8108, 0x080c, 0x2423, 0x20a1, 0x0240, 0x0c98, - 0x2061, 0x19a5, 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, 0xdce1, - 0x00de, 0x0005, 0x00d6, 0x080c, 0xdcee, 0x1520, 0x680c, 0x908c, - 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, - 0xd1e4, 0x0130, 0x9006, 0x080c, 0xed6f, 0x2009, 0x0001, 0x0078, - 0xd1ec, 0x0180, 0x6920, 0x918c, 0x00ff, 0x6824, 0x080c, 0x2894, - 0x1148, 0x2001, 0x0001, 0x080c, 0xed6f, 0x2110, 0x900e, 0x080c, - 0x328f, 0x0018, 0x9085, 0x0001, 0x0008, 0x9006, 0x00de, 0x0005, - 0x00b6, 0x00c6, 0x080c, 0xb153, 0x05a8, 0x0016, 0x0026, 0x00c6, - 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2894, 0x1578, - 0x080c, 0x66b2, 0x1560, 0xbe12, 0xbd16, 0x00ce, 0x002e, 0x001e, - 0x2b00, 0x6012, 0x080c, 0xeba1, 0x11d8, 0x080c, 0x336a, 0x11c0, - 0x080c, 0xdc49, 0x0510, 0x2001, 0x0007, 0x080c, 0x6663, 0x2001, - 0x0007, 0x080c, 0x668f, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, - 0x0001, 0x6003, 0x0001, 0x080c, 0x9383, 0x080c, 0x98ed, 0x0010, - 0x080c, 0xb101, 0x9085, 0x0001, 0x00ce, 0x00be, 0x0005, 0x080c, - 0xb101, 0x00ce, 0x002e, 0x001e, 0x0ca8, 0x080c, 0xb101, 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, 0xde50, - 0x040a, 0x91b6, 0x0027, 0x0198, 0x9186, 0x0015, 0x0118, 0x9186, - 0x0016, 0x1148, 0x080c, 0xd587, 0x0128, 0x6000, 0x9086, 0x0002, - 0x0904, 0xbb29, 0x0005, 0x91b6, 0x0014, 0x190c, 0x0dc5, 0x2001, - 0x0007, 0x080c, 0x668f, 0x080c, 0x97e1, 0x080c, 0xb134, 0x080c, - 0x98ed, 0x0005, 0xdd7a, 0xdd7c, 0xdd7a, 0xdd7a, 0xdd7a, 0xdd7c, - 0xdd8b, 0xde49, 0xddcf, 0xde49, 0xddf7, 0xde49, 0xdd8b, 0xde49, - 0xde41, 0xde49, 0xde41, 0xde49, 0xde49, 0xdd7a, 0xdd7a, 0xdd7a, - 0xdd7a, 0xdd7a, 0xdd7a, 0xdd7a, 0xdd7a, 0xdd7a, 0xdd7a, 0xdd7a, - 0xdd7c, 0xdd7a, 0xde49, 0xdd7a, 0xdd7a, 0xde49, 0xdd7a, 0xde46, - 0xde49, 0xdd7a, 0xdd7a, 0xdd7a, 0xdd7a, 0xde49, 0xde49, 0xdd7a, - 0xde49, 0xde49, 0xdd7a, 0xdd86, 0xdd7a, 0xdd7a, 0xdd7a, 0xdd7a, - 0xde45, 0xde49, 0xdd7a, 0xdd7a, 0xde49, 0xde49, 0xdd7a, 0xdd7a, - 0xdd7a, 0xdd7a, 0x080c, 0x0dc5, 0x080c, 0x97e1, 0x080c, 0xd579, - 0x6003, 0x0002, 0x080c, 0x98ed, 0x0804, 0xde4f, 0x9006, 0x080c, - 0x664f, 0x0804, 0xde49, 0x080c, 0x6a8a, 0x1904, 0xde49, 0x9006, - 0x080c, 0x664f, 0x6010, 0x2058, 0xb810, 0x9086, 0x00ff, 0x1140, - 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x00b8, - 0x6010, 0x2058, 0xb8c0, 0x9005, 0x0904, 0xde49, 0x080c, 0x339b, - 0x1904, 0xde49, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1138, - 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x2001, - 0x0002, 0x080c, 0x6663, 0x080c, 0x97e1, 0x6023, 0x0001, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x9383, 0x080c, 0x98ed, 0x6110, - 0x2158, 0x2009, 0x0001, 0x080c, 0x8717, 0x0804, 0xde4f, 0x6610, - 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0148, - 0x9686, 0x0004, 0x0130, 0x080c, 0x8efa, 0x2001, 0x0004, 0x080c, - 0x668f, 0x080c, 0xedbe, 0x0904, 0xde49, 0x080c, 0x97e1, 0x2001, - 0x0004, 0x080c, 0x6663, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0003, 0x080c, 0x9383, 0x080c, 0x98ed, 0x0804, 0xde4f, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0x6010, - 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4da0, 0x004e, 0x003e, - 0x2001, 0x0006, 0x080c, 0xde6d, 0x6610, 0x2658, 0xbe04, 0x0066, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, 0x0180, 0x2001, - 0x0006, 0x080c, 0x668f, 0x9284, 0x00ff, 0x908e, 0x0007, 0x0118, - 0x908e, 0x0004, 0x1120, 0x2001, 0x0006, 0x080c, 0x6663, 0x080c, - 0x6a8a, 0x11f8, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x01d0, 0xbe04, - 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6, 0x2079, 0x1800, - 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x0804, 0xddb7, 0x2001, 0x0004, - 0x0030, 0x2001, 0x0006, 0x0449, 0x0020, 0x0018, 0x0010, 0x080c, - 0x668f, 0x080c, 0x97e1, 0x080c, 0xb101, 0x080c, 0x98ed, 0x0005, - 0x2600, 0x0002, 0xde64, 0xde64, 0xde64, 0xde64, 0xde64, 0xde66, - 0xde64, 0xde66, 0xde64, 0xde64, 0xde66, 0xde64, 0xde64, 0xde64, - 0xde66, 0xde66, 0xde66, 0xde66, 0x080c, 0x0dc5, 0x080c, 0x97e1, - 0x080c, 0xb101, 0x080c, 0x98ed, 0x0005, 0x0016, 0x00b6, 0x00d6, - 0x6110, 0x2158, 0xb900, 0xd184, 0x0138, 0x080c, 0x6663, 0x9006, - 0x080c, 0x664f, 0x080c, 0x326f, 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, 0xbbcb, 0xbbcb, 0xbbcb, - 0xbbcb, 0xdf02, 0xbbcb, 0xdeec, 0xdead, 0xbbcb, 0xbbcb, 0xbbcb, - 0xbbcb, 0xbbcb, 0xbbcb, 0xbbcb, 0xbbcb, 0xdf02, 0xbbcb, 0xdeec, - 0xdef3, 0xbbcb, 0xbbcb, 0xbbcb, 0xbbcb, 0x00f6, 0x080c, 0x6a8a, - 0x11d8, 0x080c, 0xd561, 0x11c0, 0x6010, 0x905d, 0x01a8, 0xb8c0, - 0x9005, 0x0190, 0x9006, 0x080c, 0x664f, 0x2001, 0x0002, 0x080c, - 0x6663, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, - 0x9383, 0x080c, 0x98ed, 0x00f0, 0x2011, 0x0263, 0x2204, 0x8211, - 0x220c, 0x080c, 0x2894, 0x11b0, 0x080c, 0x671d, 0x0118, 0x080c, - 0xb101, 0x0080, 0xb810, 0x0006, 0xb814, 0x0006, 0xb8c0, 0x0006, - 0x080c, 0x6141, 0x000e, 0xb8c2, 0x000e, 0xb816, 0x000e, 0xb812, - 0x080c, 0xb101, 0x00fe, 0x0005, 0x6604, 0x96b6, 0x001e, 0x1110, - 0x080c, 0xb101, 0x0005, 0x080c, 0xbf5a, 0x1148, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x9383, 0x080c, 0x98ed, 0x0010, 0x080c, - 0xb101, 0x0005, 0x0804, 0xb101, 0x6004, 0x908a, 0x0053, 0x1a0c, - 0x0dc5, 0x080c, 0x97e1, 0x080c, 0xb134, 0x080c, 0x98ed, 0x0005, - 0x9182, 0x0040, 0x0002, 0xdf27, 0xdf27, 0xdf27, 0xdf27, 0xdf29, - 0xdf27, 0xdf27, 0xdf27, 0xdf27, 0xdf27, 0xdf27, 0xdf27, 0xdf27, - 0xdf27, 0xdf27, 0xdf27, 0xdf27, 0xdf27, 0xdf27, 0xdf27, 0x080c, - 0x0dc5, 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, - 0x6210, 0x2258, 0xb8bc, 0x9005, 0x11a8, 0x6106, 0x2071, 0x0260, - 0x7444, 0x94a4, 0xff00, 0x0904, 0xdf8f, 0x080c, 0xed63, 0x1170, - 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, - 0x891c, 0x0020, 0x9026, 0x080c, 0xebe6, 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, 0x6dd1, 0x001e, 0x080c, 0xed63, - 0x1904, 0xdfef, 0x9486, 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, - 0xe915, 0x0804, 0xdfef, 0x9486, 0x0200, 0x1120, 0x080c, 0xe8ac, - 0x0804, 0xdfef, 0x9486, 0x0400, 0x0120, 0x9486, 0x1000, 0x1904, - 0xdfef, 0x2019, 0x0002, 0x080c, 0xe8c7, 0x0804, 0xdfef, 0x2069, - 0x1a75, 0x6a00, 0xd284, 0x0904, 0xe059, 0x9284, 0x0300, 0x1904, - 0xe052, 0x6804, 0x9005, 0x0904, 0xe03a, 0x2d78, 0x6003, 0x0007, - 0x080c, 0x1027, 0x0904, 0xdffb, 0x7800, 0xd08c, 0x1118, 0x7804, - 0x8001, 0x7806, 0x6017, 0x0000, 0x2001, 0x180f, 0x2004, 0xd084, - 0x1904, 0xe05d, 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, 0xdff7, - 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, 0x6dd1, 0x002e, - 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e, 0x0005, 0x0000, - 0x0080, 0x0040, 0x0000, 0x2001, 0x1810, 0x2004, 0xd084, 0x0120, - 0x080c, 0x100e, 0x1904, 0xdfa4, 0x6017, 0xf100, 0x6003, 0x0001, - 0x6007, 0x0041, 0x080c, 0x933b, 0x080c, 0x98ed, 0x0c00, 0x2069, - 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, 0x1200, 0x1198, 0x686c, - 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, 0xf700, 0x910d, 0x6116, - 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x080c, 0x933b, 0x080c, - 0x98ed, 0x0828, 0x6868, 0x602e, 0x686c, 0x6032, 0x6017, 0xf200, - 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x933b, 0x080c, 0x98ed, - 0x0804, 0xdfef, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, - 0x8049, 0x080c, 0x4be9, 0x6017, 0xf300, 0x0010, 0x6017, 0xf100, - 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x933b, 0x080c, 0x98ed, - 0x0804, 0xdfef, 0x6017, 0xf500, 0x0c98, 0x6017, 0xf600, 0x0804, - 0xe00f, 0x6017, 0xf200, 0x0804, 0xe00f, 0xa867, 0x0146, 0xa86b, - 0x0000, 0x6008, 0xa886, 0x2c00, 0xa87a, 0x7044, 0x9084, 0x0003, - 0x9080, 0xdff7, 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, 0xe0d9, 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, 0xdffb, 0x2548, 0x8847, 0x9885, 0x0046, - 0xa866, 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, 0xe948, 0x0804, - 0xdfef, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, 0x0008, 0x8016, - 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0054, - 0x1a0c, 0x0dc5, 0x9082, 0x0040, 0x0a0c, 0x0dc5, 0x2008, 0x0804, - 0xe168, 0x9186, 0x0051, 0x0108, 0x0048, 0x080c, 0xd587, 0x0500, - 0x6000, 0x9086, 0x0002, 0x11e0, 0x0804, 0xe1b1, 0x9186, 0x0027, - 0x0190, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0160, 0x190c, - 0x0dc5, 0x080c, 0xd587, 0x0160, 0x6000, 0x9086, 0x0004, 0x190c, - 0x0dc5, 0x0804, 0xe294, 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, - 0x080c, 0xb19b, 0x0005, 0xe12f, 0xe131, 0xe131, 0xe158, 0xe12f, - 0xe12f, 0xe12f, 0xe12f, 0xe12f, 0xe12f, 0xe12f, 0xe12f, 0xe12f, - 0xe12f, 0xe12f, 0xe12f, 0xe12f, 0xe12f, 0xe12f, 0xe12f, 0x080c, - 0x0dc5, 0x080c, 0x97e1, 0x080c, 0x98ed, 0x0036, 0x0096, 0x6014, - 0x904d, 0x01d8, 0x080c, 0xce56, 0x01c0, 0x6003, 0x0002, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, - 0x080c, 0xe948, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, - 0x1988, 0x2004, 0x601a, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, - 0x0096, 0x080c, 0x97e1, 0x080c, 0x98ed, 0x080c, 0xce56, 0x0120, - 0x6014, 0x2048, 0x080c, 0x1040, 0x080c, 0xb134, 0x009e, 0x0005, - 0x0002, 0xe17d, 0xe194, 0xe17f, 0xe1ab, 0xe17d, 0xe17d, 0xe17d, - 0xe17d, 0xe17d, 0xe17d, 0xe17d, 0xe17d, 0xe17d, 0xe17d, 0xe17d, - 0xe17d, 0xe17d, 0xe17d, 0xe17d, 0xe17d, 0x080c, 0x0dc5, 0x0096, - 0x080c, 0x97e1, 0x6014, 0x2048, 0xa87c, 0xd0b4, 0x0138, 0x6003, - 0x0007, 0x2009, 0x0043, 0x080c, 0xb180, 0x0010, 0x6003, 0x0004, - 0x080c, 0x98ed, 0x009e, 0x0005, 0x080c, 0x97e1, 0x080c, 0xce56, - 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e, 0xd1ec, 0x1138, - 0x080c, 0x88f1, 0x080c, 0xb101, 0x080c, 0x98ed, 0x0005, 0x080c, - 0xebaa, 0x0db0, 0x0cc8, 0x080c, 0x97e1, 0x2009, 0x0041, 0x0804, - 0xe31c, 0x9182, 0x0040, 0x0002, 0xe1c8, 0xe1ca, 0xe1c8, 0xe1c8, - 0xe1c8, 0xe1c8, 0xe1c8, 0xe1c8, 0xe1c8, 0xe1c8, 0xe1c8, 0xe1c8, - 0xe1c8, 0xe1c8, 0xe1c8, 0xe1c8, 0xe1c8, 0xe1cb, 0xe1c8, 0xe1c8, - 0x080c, 0x0dc5, 0x0005, 0x00d6, 0x080c, 0x88f1, 0x00de, 0x080c, - 0xec02, 0x080c, 0xb101, 0x0005, 0x9182, 0x0040, 0x0002, 0xe1eb, - 0xe1eb, 0xe1eb, 0xe1eb, 0xe1eb, 0xe1eb, 0xe1eb, 0xe1eb, 0xe1eb, - 0xe1ed, 0xe25c, 0xe1eb, 0xe1eb, 0xe1eb, 0xe1eb, 0xe25c, 0xe1eb, - 0xe1eb, 0xe1eb, 0xe1eb, 0x080c, 0x0dc5, 0x2001, 0x0105, 0x2004, - 0x9084, 0x1800, 0x01c8, 0x2001, 0x0132, 0x200c, 0x2001, 0x0131, - 0x2004, 0x9105, 0x1904, 0xe25c, 0x2009, 0x180c, 0x2104, 0xd0d4, - 0x0904, 0xe25c, 0xc0d4, 0x200a, 0x2009, 0x0105, 0x2104, 0x9084, - 0xe7fd, 0x9085, 0x0010, 0x200a, 0x2001, 0x1867, 0x2004, 0xd0e4, - 0x1528, 0x603b, 0x0000, 0x080c, 0x989d, 0x6014, 0x0096, 0x2048, - 0xa87c, 0xd0fc, 0x0188, 0x908c, 0x0003, 0x918e, 0x0002, 0x0508, - 0x2001, 0x180c, 0x2004, 0xd0d4, 0x11e0, 0x080c, 0x9a0f, 0x2009, - 0x0041, 0x009e, 0x0804, 0xe31c, 0x080c, 0x9a0f, 0x6003, 0x0007, - 0x601b, 0x0000, 0x080c, 0x88f1, 0x009e, 0x0005, 0x2001, 0x0100, - 0x2004, 0x9082, 0x0005, 0x0aa8, 0x2001, 0x011f, 0x2004, 0x603a, - 0x0890, 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, 0xd1cc, 0x0110, - 0x080c, 0x2c94, 0x080c, 0x9a0f, 0x6014, 0x2048, 0xa97c, 0xd1ec, - 0x1130, 0x080c, 0x88f1, 0x080c, 0xb101, 0x009e, 0x0005, 0x080c, - 0xebaa, 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, 0x200c, 0xc1d4, - 0x2102, 0x0036, 0x080c, 0x989d, 0x080c, 0x9a0f, 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, 0xe948, 0x6018, 0x9005, 0x1128, - 0x2001, 0x1988, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, 0x6003, - 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, 0xe2ab, - 0xe2ab, 0xe2ab, 0xe2ab, 0xe2ab, 0xe2ab, 0xe2ab, 0xe2ab, 0xe2ad, - 0xe2ab, 0xe2ab, 0xe2ab, 0xe2ab, 0xe2ab, 0xe2ab, 0xe2ab, 0xe2ab, - 0xe2ab, 0xe2ab, 0xe2f8, 0x080c, 0x0dc5, 0x6014, 0x0096, 0x2048, - 0xa834, 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, - 0x1190, 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, 0x2009, 0x0041, - 0x009e, 0x0804, 0xe31c, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, - 0x88f1, 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, 0x88f3, 0x009e, 0x0005, 0x6003, 0x0002, 0x009e, 0x0005, - 0x6024, 0xd0f4, 0x0128, 0x080c, 0x1608, 0x1904, 0xe2ad, 0x0005, - 0x6014, 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, 0x9105, 0x1120, - 0x080c, 0x1608, 0x1904, 0xe2ad, 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, 0xe340, 0xe34c, 0xe358, 0xe364, - 0xe340, 0xe340, 0xe340, 0xe340, 0xe347, 0xe342, 0xe342, 0xe340, - 0xe340, 0xe340, 0xe340, 0xe342, 0xe340, 0xe342, 0xe340, 0xe347, - 0x080c, 0x0dc5, 0x6024, 0xd0dc, 0x090c, 0x0dc5, 0x0005, 0x6014, - 0x9005, 0x190c, 0x0dc5, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, - 0x933b, 0x0126, 0x2091, 0x8000, 0x080c, 0x98ed, 0x012e, 0x0005, - 0x6003, 0x0001, 0x6106, 0x080c, 0x933b, 0x0126, 0x2091, 0x8000, - 0x080c, 0x98ed, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, - 0x080c, 0x1c09, 0x0126, 0x2091, 0x8000, 0x080c, 0x93a0, 0x080c, - 0x9a0f, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x0096, - 0x9182, 0x0040, 0x0023, 0x009e, 0x003e, 0x012e, 0x0005, 0xe393, - 0xe395, 0xe3a7, 0xe3c1, 0xe393, 0xe393, 0xe393, 0xe393, 0xe393, - 0xe393, 0xe393, 0xe393, 0xe393, 0xe393, 0xe393, 0xe393, 0xe393, - 0xe393, 0xe393, 0xe393, 0x080c, 0x0dc5, 0x6014, 0x2048, 0xa87c, - 0xd0fc, 0x01f8, 0x909c, 0x0003, 0x939e, 0x0003, 0x01d0, 0x6003, - 0x0001, 0x6106, 0x080c, 0x933b, 0x080c, 0x98ed, 0x0470, 0x6014, - 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, - 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x933b, 0x080c, 0x98ed, - 0x00e0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xe948, - 0x00a0, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, 0x909c, 0x0003, - 0x939e, 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, - 0x1c09, 0x080c, 0x93a0, 0x080c, 0x9a0f, 0x0005, 0x080c, 0x97e1, - 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xed00, 0x0036, - 0x2019, 0x0029, 0x080c, 0xe948, 0x003e, 0x009e, 0x080c, 0xb134, - 0x080c, 0x98ed, 0x0005, 0x080c, 0x989d, 0x6114, 0x81ff, 0x0158, - 0x0096, 0x2148, 0x080c, 0xed00, 0x0036, 0x2019, 0x0029, 0x080c, - 0xe948, 0x003e, 0x009e, 0x080c, 0xb134, 0x080c, 0x9a0f, 0x0005, - 0x9182, 0x0085, 0x0002, 0xe412, 0xe410, 0xe410, 0xe41e, 0xe410, - 0xe410, 0xe410, 0xe410, 0xe410, 0xe410, 0xe410, 0xe410, 0xe410, - 0x080c, 0x0dc5, 0x6003, 0x000b, 0x6106, 0x080c, 0x933b, 0x0126, - 0x2091, 0x8000, 0x080c, 0x98ed, 0x012e, 0x0005, 0x0026, 0x00e6, - 0x080c, 0xeba1, 0x0118, 0x080c, 0xb101, 0x0450, 0x2071, 0x0260, - 0x7224, 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4, 0x0150, 0x6010, - 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011, 0x014e, 0x080c, - 0xb423, 0x7220, 0x080c, 0xe79d, 0x0118, 0x6007, 0x0086, 0x0040, - 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, 0x6007, 0x0086, - 0x6003, 0x0001, 0x080c, 0x933b, 0x080c, 0x98ed, 0x080c, 0x9a0f, - 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, 0xb19b, 0x0050, 0x2001, 0x0007, 0x080c, 0x668f, 0x080c, - 0x97e1, 0x080c, 0xb134, 0x080c, 0x98ed, 0x0005, 0xe483, 0xe485, - 0xe485, 0xe483, 0xe483, 0xe483, 0xe483, 0xe483, 0xe483, 0xe483, - 0xe483, 0xe483, 0xe483, 0x080c, 0x0dc5, 0x080c, 0x97e1, 0x080c, - 0xb134, 0x080c, 0x98ed, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0dc5, - 0x9182, 0x0092, 0x1a0c, 0x0dc5, 0x9182, 0x0085, 0x0002, 0xe4a4, - 0xe4a4, 0xe4a4, 0xe4a6, 0xe4a4, 0xe4a4, 0xe4a4, 0xe4a4, 0xe4a4, - 0xe4a4, 0xe4a4, 0xe4a4, 0xe4a4, 0x080c, 0x0dc5, 0x0005, 0x9186, - 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, - 0x080c, 0xb19b, 0x0030, 0x080c, 0x97e1, 0x080c, 0xb134, 0x080c, - 0x98ed, 0x0005, 0x0036, 0x080c, 0xec02, 0x6043, 0x0000, 0x2019, - 0x000b, 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, - 0x0126, 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x904e, - 0x080c, 0xa929, 0x009e, 0x008e, 0x1550, 0x0076, 0x2c38, 0x080c, - 0xa9d4, 0x007e, 0x1520, 0x6000, 0x9086, 0x0000, 0x0500, 0x6020, - 0x9086, 0x0007, 0x01e0, 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, - 0xec02, 0x080c, 0xd579, 0x080c, 0x1ab7, 0x6023, 0x0007, 0x6014, - 0x2048, 0x080c, 0xce56, 0x0110, 0x080c, 0xe948, 0x009e, 0x6017, - 0x0000, 0x080c, 0xec02, 0x6023, 0x0007, 0x080c, 0xd579, 0x003e, - 0x012e, 0x0005, 0x00f6, 0x00c6, 0x00b6, 0x0036, 0x0156, 0x2079, - 0x0260, 0x7938, 0x783c, 0x080c, 0x2894, 0x1904, 0xe558, 0x0016, - 0x00c6, 0x080c, 0x671d, 0x1904, 0xe556, 0x001e, 0x00c6, 0x080c, - 0xd561, 0x1130, 0xb8c0, 0x9005, 0x0118, 0x080c, 0x339b, 0x0148, - 0x2b10, 0x2160, 0x6010, 0x0006, 0x6212, 0x080c, 0xd568, 0x000e, - 0x6012, 0x00ce, 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, - 0xaa9a, 0x080c, 0x94e0, 0x0076, 0x903e, 0x080c, 0x93b3, 0x007e, - 0x001e, 0x0076, 0x903e, 0x080c, 0xe690, 0x007e, 0x0026, 0xba04, - 0x9294, 0xff00, 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, - 0x1118, 0xbaa0, 0x080c, 0x3304, 0x002e, 0xbcc0, 0x001e, 0x080c, - 0x6141, 0xbe12, 0xbd16, 0xbcc2, 0x9006, 0x0010, 0x00ce, 0x001e, - 0x015e, 0x003e, 0x00be, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, - 0x00b6, 0x0016, 0x2009, 0x1824, 0x2104, 0x9086, 0x0074, 0x1904, - 0xe5b7, 0x2069, 0x0260, 0x6944, 0x9182, 0x0100, 0x06e0, 0x6940, - 0x9184, 0x8000, 0x0904, 0xe5b4, 0x2001, 0x197d, 0x2004, 0x9005, - 0x1140, 0x6010, 0x2058, 0xb8c0, 0x9005, 0x0118, 0x9184, 0x0800, - 0x0598, 0x6948, 0x918a, 0x0001, 0x0648, 0x080c, 0xed68, 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, 0x672c, 0x0804, 0xe61f, 0x2011, - 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, - 0xc0f7, 0x009e, 0x15a8, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x0006, 0x080c, 0xc0f7, 0x009e, 0x1548, 0x0046, - 0x0016, 0xbaa0, 0x2220, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, - 0x0138, 0x2009, 0x0029, 0x080c, 0xe9a5, 0xb800, 0xc0e5, 0xb802, - 0x2019, 0x0029, 0x080c, 0x94e0, 0x0076, 0x2039, 0x0000, 0x080c, - 0x93b3, 0x2c08, 0x080c, 0xe690, 0x007e, 0x2001, 0x0007, 0x080c, - 0x668f, 0x2001, 0x0007, 0x080c, 0x6663, 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, 0x2894, 0x11d0, - 0x080c, 0x671d, 0x11b8, 0x2011, 0x0270, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x000a, 0x080c, 0xc0f7, 0x009e, 0x1158, 0x2011, - 0x0274, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, - 0xc0f7, 0x009e, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00be, - 0x0005, 0x00b6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, - 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2894, 0x11d0, 0x080c, - 0x671d, 0x11b8, 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, - 0x2019, 0x000a, 0x080c, 0xc0f7, 0x009e, 0x1158, 0x2011, 0x027a, - 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xc0f7, - 0x009e, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, 0x00be, 0x0005, - 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, - 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0x19f2, 0x252c, 0x2021, - 0x19f8, 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7654, 0x7074, - 0x81ff, 0x0150, 0x0006, 0x9186, 0x1ab8, 0x000e, 0x0128, 0x8001, - 0x9602, 0x1a04, 0xe72e, 0x0018, 0x9606, 0x0904, 0xe72e, 0x080c, - 0x8bc3, 0x0904, 0xe725, 0x2100, 0x9c06, 0x0904, 0xe725, 0x6720, - 0x9786, 0x0007, 0x0904, 0xe725, 0x080c, 0xe9e6, 0x1904, 0xe725, - 0x080c, 0xed86, 0x0904, 0xe725, 0x080c, 0xe9d6, 0x0904, 0xe725, - 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, 0x339b, 0x0904, 0xe76d, - 0x6004, 0x9086, 0x0000, 0x1904, 0xe76d, 0x9786, 0x0004, 0x0904, - 0xe76d, 0x2500, 0x9c06, 0x0904, 0xe725, 0x2400, 0x9c06, 0x05e8, - 0x88ff, 0x0118, 0x6054, 0x9906, 0x15c0, 0x0096, 0x6000, 0x9086, - 0x0004, 0x1120, 0x0016, 0x080c, 0x1ab7, 0x001e, 0x9786, 0x000a, - 0x0148, 0x080c, 0xd05e, 0x1130, 0x080c, 0xbae2, 0x009e, 0x080c, - 0xb134, 0x0418, 0x6014, 0x2048, 0x080c, 0xce56, 0x01d8, 0x9786, - 0x0003, 0x1570, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, - 0xa878, 0x2048, 0x080c, 0x0fc0, 0x009e, 0xab7a, 0xa877, 0x0000, - 0x080c, 0xed00, 0x0016, 0x080c, 0xd14c, 0x080c, 0x6dc4, 0x001e, - 0x080c, 0xd041, 0x009e, 0x080c, 0xb134, 0x9ce0, 0x0018, 0x2001, - 0x181a, 0x2004, 0x9c02, 0x1210, 0x0804, 0xe6a4, 0x012e, 0x002e, - 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, - 0x9786, 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, 0x080c, 0xed00, - 0x080c, 0xe948, 0x08f8, 0x009e, 0x0c00, 0x9786, 0x0009, 0x11f8, - 0x6000, 0x9086, 0x0004, 0x01c0, 0x6000, 0x9086, 0x0003, 0x11a0, - 0x080c, 0x989d, 0x0096, 0x6114, 0x2148, 0x080c, 0xce56, 0x0118, - 0x6010, 0x080c, 0x6dd1, 0x009e, 0x00c6, 0x080c, 0xb101, 0x00ce, - 0x0036, 0x080c, 0x9a0f, 0x003e, 0x009e, 0x0804, 0xe725, 0x9786, - 0x000a, 0x0904, 0xe715, 0x0804, 0xe70a, 0x81ff, 0x0904, 0xe725, - 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, 0x0138, 0x9180, 0x0001, - 0x2004, 0x9086, 0x002d, 0x1904, 0xe725, 0x6000, 0x9086, 0x0002, - 0x1904, 0xe725, 0x080c, 0xd04d, 0x0138, 0x080c, 0xd05e, 0x1904, - 0xe725, 0x080c, 0xbae2, 0x0038, 0x080c, 0x326f, 0x080c, 0xd05e, - 0x1110, 0x080c, 0xbae2, 0x080c, 0xb134, 0x0804, 0xe725, 0xa864, - 0x9084, 0x00ff, 0x9086, 0x0039, 0x0005, 0x00c6, 0x00e6, 0x0016, - 0x2c08, 0x2170, 0x9006, 0x080c, 0xe96f, 0x001e, 0x0120, 0x6020, - 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xe7bc, 0xe7bc, - 0xe7bc, 0xe7bc, 0xe7bc, 0xe7bc, 0xe7be, 0xe7bc, 0xe7bc, 0xe7bc, - 0xe7e7, 0xb134, 0xb134, 0xe7bc, 0x9006, 0x0005, 0x0036, 0x0046, - 0x0016, 0x7010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2009, - 0x0020, 0x080c, 0xe9a5, 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, - 0xe4c8, 0x003e, 0x9085, 0x0001, 0x0005, 0x0096, 0x080c, 0xce56, - 0x0140, 0x6014, 0x904d, 0x080c, 0xca71, 0x687b, 0x0005, 0x080c, - 0x6dd1, 0x009e, 0x080c, 0xb134, 0x9085, 0x0001, 0x0005, 0x0019, - 0x9085, 0x0001, 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0dc5, - 0x000b, 0x0005, 0xe802, 0xe802, 0xe819, 0xe809, 0xe828, 0xe802, - 0xe802, 0xe804, 0xe802, 0xe802, 0xe802, 0xe802, 0xe802, 0xe802, - 0xe802, 0xe802, 0x080c, 0x0dc5, 0x080c, 0xb134, 0x9085, 0x0001, - 0x0005, 0x0036, 0x00e6, 0x2071, 0x19e9, 0x703c, 0x9c06, 0x1128, - 0x2019, 0x0001, 0x080c, 0xa877, 0x0010, 0x080c, 0xaa59, 0x00ee, - 0x003e, 0x0096, 0x00d6, 0x6014, 0x2048, 0xa87b, 0x0005, 0x080c, - 0x6dd1, 0x080c, 0xb134, 0x00de, 0x009e, 0x9085, 0x0001, 0x0005, - 0x601c, 0xd084, 0x190c, 0x1ab7, 0x0c60, 0x2001, 0x0001, 0x080c, - 0x664f, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, - 0x1805, 0x2011, 0x0276, 0x080c, 0xc0e3, 0x003e, 0x002e, 0x001e, - 0x015e, 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076, - 0x0066, 0x00b6, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, 0x1cd0, - 0x2079, 0x0001, 0x8fff, 0x0904, 0xe89f, 0x2071, 0x1800, 0x7654, - 0x7074, 0x8001, 0x9602, 0x1a04, 0xe89f, 0x88ff, 0x0120, 0x2800, - 0x9c06, 0x15a0, 0x2078, 0x080c, 0xe9d6, 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, 0xec02, 0x080c, 0xd579, 0x080c, 0x1ab7, 0x6023, 0x0007, - 0x6014, 0x2048, 0x080c, 0xce56, 0x0120, 0x0046, 0x080c, 0xe948, - 0x004e, 0x009e, 0x080c, 0xb134, 0x88ff, 0x1198, 0x9ce0, 0x0018, - 0x2001, 0x181a, 0x2004, 0x9c02, 0x1210, 0x0804, 0xe852, 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, 0xa929, 0x009e, 0x008e, 0x903e, 0x080c, - 0xa9d4, 0x080c, 0xe843, 0x005e, 0x007e, 0x00be, 0x0005, 0x00b6, - 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, - 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, 0x671d, 0x1180, 0x0056, - 0x0086, 0x9046, 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, - 0xa929, 0x009e, 0x008e, 0x903e, 0x080c, 0xa9d4, 0x005e, 0x003e, - 0x001e, 0x8108, 0x1f04, 0xe8d2, 0x0036, 0x2508, 0x2029, 0x0003, - 0x080c, 0xe843, 0x003e, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, - 0x00be, 0x0005, 0x00b6, 0x0076, 0x0056, 0x6210, 0x2258, 0x0086, - 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, 0x904e, 0x080c, - 0xa929, 0x009e, 0x008e, 0x903e, 0x080c, 0xa9d4, 0x2c20, 0x080c, - 0xe843, 0x005e, 0x007e, 0x00be, 0x0005, 0x00b6, 0x0046, 0x0056, - 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, 0x0800, 0x900e, 0x0016, - 0x0036, 0x080c, 0x671d, 0x1190, 0x0086, 0x9046, 0x2828, 0x0046, - 0x2021, 0x0001, 0x080c, 0xebe6, 0x004e, 0x0096, 0x904e, 0x080c, - 0xa929, 0x009e, 0x008e, 0x903e, 0x080c, 0xa9d4, 0x003e, 0x001e, - 0x8108, 0x1f04, 0xe91f, 0x0036, 0x2029, 0x0002, 0x080c, 0xe843, - 0x003e, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x0005, - 0x0016, 0x00f6, 0x080c, 0xce54, 0x0198, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0046, 0x0180, 0xa800, 0x907d, 0x0138, 0xa803, 0x0000, - 0xab82, 0x080c, 0x6dd1, 0x2f48, 0x0cb0, 0xab82, 0x080c, 0x6dd1, - 0x00fe, 0x001e, 0x0005, 0xa800, 0x907d, 0x0130, 0xa803, 0x0000, - 0x080c, 0x6dd1, 0x2f48, 0x0cb8, 0x080c, 0x6dd1, 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, 0xce44, 0x2001, 0x0000, 0x0120, 0x2200, - 0x9080, 0x0015, 0x2004, 0x002e, 0xa87a, 0x9186, 0x0020, 0x0110, - 0xa8e3, 0xffff, 0xa986, 0xac76, 0xa87f, 0x0000, 0x2001, 0x198f, - 0x2004, 0xa882, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6dd1, 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, 0x1988, 0x2004, - 0x601a, 0x080c, 0x933b, 0x080c, 0x98ed, 0x001e, 0x0005, 0xa001, - 0xa001, 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, - 0xd190, 0x0030, 0x080c, 0xec02, 0x080c, 0x88f1, 0x080c, 0xb101, - 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xea35, - 0xea35, 0xea35, 0xea37, 0xea35, 0xea37, 0xea37, 0xea35, 0xea37, - 0xea35, 0xea35, 0xea35, 0xea35, 0xea35, 0x9006, 0x0005, 0x9085, - 0x0001, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, - 0xea4e, 0xea4e, 0xea4e, 0xea4e, 0xea4e, 0xea4e, 0xea5b, 0xea4e, - 0xea4e, 0xea4e, 0xea4e, 0xea4e, 0xea4e, 0xea4e, 0x6007, 0x003b, - 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x080c, 0x933b, - 0x080c, 0x98ed, 0x0005, 0x0096, 0x00c6, 0x2260, 0x080c, 0xec02, - 0x6043, 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, 0x603b, 0x0000, - 0x00ce, 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, 0xeab4, 0x6814, - 0x9005, 0x0138, 0x2048, 0xa87c, 0xd0fc, 0x1118, 0x00de, 0x009e, - 0x08a8, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, 0x933b, 0x080c, - 0x98ed, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, 0xeb2b, - 0x6014, 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, 0x190c, 0x0dc5, - 0x0804, 0xeb2b, 0x2048, 0x080c, 0xce56, 0x1130, 0x0028, 0x2048, - 0xa800, 0x9005, 0x1de0, 0x2900, 0x2048, 0xa87c, 0x9084, 0x0003, - 0x9086, 0x0002, 0x1168, 0xa87c, 0xc0dc, 0xc0f4, 0xa87e, 0xa880, - 0xc0fc, 0xa882, 0x2009, 0x0043, 0x080c, 0xe31c, 0x0804, 0xeb2b, - 0x2009, 0x0041, 0x0804, 0xeb25, 0x9186, 0x0005, 0x15a0, 0x6814, - 0x2048, 0xa87c, 0xd0bc, 0x1120, 0x00de, 0x009e, 0x0804, 0xea4e, - 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x0dc5, 0x0804, 0xea6f, 0x6007, - 0x003a, 0x6003, 0x0001, 0x080c, 0x933b, 0x080c, 0x98ed, 0x00c6, - 0x2d60, 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, 0x1904, - 0xeb2b, 0x6814, 0x2048, 0xa97c, 0xc1f4, 0xc1dc, 0xa97e, 0xa980, - 0xc1fc, 0xc1bc, 0xa982, 0x00f6, 0x2c78, 0x080c, 0x1768, 0x00fe, - 0x2009, 0x0042, 0x04d0, 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, 0x6dd1, 0x2019, 0x0045, 0x6008, 0x2068, - 0x080c, 0xe4c8, 0x2d00, 0x600a, 0x6023, 0x0006, 0x6003, 0x0007, - 0x901e, 0x631a, 0x6342, 0x003e, 0x0038, 0x6043, 0x0000, 0x6003, - 0x0007, 0x080c, 0xe31c, 0x00ce, 0x00de, 0x009e, 0x0005, 0x9186, - 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, - 0x0027, 0x1178, 0x080c, 0x97e1, 0x0036, 0x0096, 0x6014, 0x2048, - 0x2019, 0x0004, 0x080c, 0xe948, 0x009e, 0x003e, 0x080c, 0x98ed, - 0x0005, 0x9186, 0x0014, 0x0d70, 0x080c, 0xb19b, 0x0005, 0xeb5e, - 0xeb5c, 0xeb5c, 0xeb5c, 0xeb5c, 0xeb5c, 0xeb5e, 0xeb5c, 0xeb5c, - 0xeb5c, 0xeb5c, 0xeb5c, 0xeb5c, 0x080c, 0x0dc5, 0x080c, 0x97e1, - 0x6003, 0x000c, 0x080c, 0x98ed, 0x0005, 0x9182, 0x0092, 0x1220, - 0x9182, 0x0085, 0x0208, 0x001a, 0x080c, 0xb19b, 0x0005, 0xeb7c, - 0xeb7c, 0xeb7c, 0xeb7c, 0xeb7e, 0xeb9e, 0xeb7c, 0xeb7c, 0xeb7c, - 0xeb7c, 0xeb7c, 0xeb7c, 0xeb7c, 0x080c, 0x0dc5, 0x00d6, 0x2c68, - 0x080c, 0xb0ab, 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, - 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, - 0xffff, 0x6910, 0x6112, 0x6023, 0x0004, 0x080c, 0x933b, 0x080c, - 0x98ed, 0x2d60, 0x080c, 0xb101, 0x00de, 0x0005, 0x080c, 0xb101, - 0x0005, 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, - 0x00ee, 0x0005, 0x2009, 0x1867, 0x210c, 0xd1ec, 0x05b0, 0x6003, - 0x0002, 0x6024, 0xc0e5, 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1989, - 0x2004, 0x6042, 0x2009, 0x1867, 0x210c, 0xd1f4, 0x1520, 0x00a0, - 0x2009, 0x1867, 0x210c, 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, - 0x9006, 0x00d8, 0x2001, 0x1989, 0x200c, 0x2001, 0x1987, 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, 0x88f1, 0x080c, - 0xb101, 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, 0xc0f7, 0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, - 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x0006, 0x080c, 0xc0f7, - 0x009e, 0x1100, 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, - 0x1800, 0x080c, 0x60ba, 0x080c, 0x3019, 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, 0x6dd1, 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, 0x19f2, 0x252c, 0x2021, 0x19f8, - 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7654, 0x7074, 0x9606, - 0x0578, 0x6720, 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, - 0x2500, 0x9c06, 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, 0xe9d6, - 0x01b8, 0x080c, 0xe9e6, 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, - 0x0016, 0x080c, 0x1ab7, 0x001e, 0x080c, 0xd04d, 0x1110, 0x080c, - 0x326f, 0x080c, 0xd05e, 0x1110, 0x080c, 0xbae2, 0x080c, 0xb134, - 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, 0xd561, 0x0168, 0x2019, 0xffff, 0x9005, - 0x0128, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, 0x0004, - 0x080c, 0x4da0, 0x004e, 0x003e, 0x000e, 0x0005, 0x6004, 0x9086, - 0x0001, 0x1128, 0x080c, 0xaa9a, 0x080c, 0xb134, 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, 0x07ce, 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, 0x1a0b, 0x0001, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0409, - 0x0000, 0x44bc, 0x0003, 0x80fe, 0x0008, 0x1a0a, 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, 0x039c, - 0x000b, 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, 0x03a5, 0x0004, 0x808c, 0x0008, 0x0001, - 0x0000, 0x04fe, 0x0008, 0x3388, 0x000b, 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, 0x0f88, 0x000b, 0xc4c0, 0x0009, 0x7000, 0x0000, 0xffe0, - 0x0009, 0x1000, 0x0000, 0x0b21, 0x0003, 0x0396, 0x0004, 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, 0x0379, 0x0003, 0x0396, 0x0004, 0x3941, 0x0002, 0x0b27, - 0x0003, 0x8072, 0x0000, 0x0400, 0x0000, 0x000a, 0x000b, 0x035e, - 0x000c, 0x11fe, 0x0000, 0x372f, 0x000b, 0x8072, 0x0000, 0x0400, - 0x0000, 0x8010, 0x0008, 0x000e, 0x0000, 0x0379, 0x0003, 0x8060, - 0x0000, 0x0400, 0x0000, 0x04fe, 0x0008, 0x3744, 0x0003, 0x808c, - 0x0008, 0x0000, 0x0008, 0x9180, 0x0001, 0x0005, 0x0008, 0x7f62, - 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x473a, 0x000b, 0x0060, - 0x0008, 0x8062, 0x0008, 0x001b, 0x0008, 0x4304, 0x0008, 0x4206, - 0x0008, 0x8066, 0x0000, 0x0412, 0x0000, 0x4742, 0x000b, 0x035b, - 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x0460, 0x0000, 0x8062, - 0x0008, 0x002b, 0x0008, 0x8066, 0x0000, 0x0609, 0x0008, 0x474b, - 0x000b, 0x8066, 0x0000, 0x220a, 0x0008, 0x474e, 0x000b, 0x42fe, - 0x0000, 0xffc0, 0x0001, 0xff00, 0x0008, 0x7f04, 0x0008, 0x8060, - 0x0000, 0x0400, 0x0000, 0x9180, 0x0001, 0x0002, 0x0000, 0x7f62, - 0x0008, 0x8066, 0x0000, 0x041a, 0x0008, 0x475a, 0x000b, 0x8072, - 0x0000, 0x0400, 0x0000, 0x0046, 0x0003, 0x8060, 0x0000, 0x0400, - 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x0411, 0x0000, 0x4763, - 0x000b, 0x02fe, 0x0008, 0x03e0, 0x0009, 0x0f69, 0x000b, 0x0d22, - 0x0000, 0x4000, 0x000f, 0x8280, 0x0009, 0x0002, 0x0000, 0x1380, - 0x0001, 0x7f62, 0x0008, 0x8066, 0x0000, 0x2209, 0x0008, 0x476f, - 0x000b, 0x0200, 0x000a, 0xffc0, 0x0001, 0x0007, 0x0000, 0x7f06, - 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x060a, 0x0008, 0x4777, - 0x000b, 0x4000, 0x000f, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x2f44, - 0x000a, 0x2f44, 0x000a, 0x0e83, 0x000b, 0x808a, 0x0008, 0x0003, - 0x0008, 0x8074, 0x0000, 0xf080, 0x0000, 0x8072, 0x0000, 0x3000, - 0x0008, 0x5b84, 0x0003, 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, 0x0b99, - 0x0003, 0x4000, 0x000f, 0x8072, 0x0000, 0x0404, 0x0008, 0x4000, - 0x000f, 0x8010, 0x0008, 0x0012, 0x0008, 0x0233, 0x000c, 0x035e, - 0x000c, 0x1110, 0x0000, 0x0233, 0x000c, 0x11fe, 0x0000, 0x379f, - 0x0003, 0x000a, 0x000b, 0xc2c0, 0x0009, 0x00ff, 0x0008, 0x7f00, - 0x0000, 0xc3c0, 0x0001, 0xff00, 0x0008, 0x00d0, 0x0009, 0x0bca, - 0x0003, 0x0d0a, 0x0000, 0x8580, 0x0001, 0x1000, 0x0000, 0x7f62, - 0x0008, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066, 0x0000, 0x0809, - 0x0000, 0x47b4, 0x000b, 0x04fe, 0x0008, 0x33c3, 0x000b, 0x0460, - 0x0000, 0x8062, 0x0008, 0x0004, 0x0000, 0x8066, 0x0000, 0x0211, - 0x0000, 0x47bc, 0x0003, 0x01fe, 0x0008, 0x00e0, 0x0009, 0x0fc3, - 0x000b, 0x02fe, 0x0008, 0x43e0, 0x0001, 0x0bc9, 0x0003, 0x0500, - 0x0002, 0x7f0a, 0x0000, 0xffe0, 0x0009, 0x0800, 0x0000, 0x0fad, - 0x0003, 0x0d08, 0x0008, 0x4000, 0x000f, 0x43fe, 0x0008, 0x3e80, - 0x0001, 0xffc0, 0x0001, 0x7fff, 0x0000, 0x0d60, 0x0000, 0x7f62, - 0x0008, 0x8066, 0x0000, 0x0809, 0x0000, 0x47d2, 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, 0x47e4, 0x000b, 0x4000, 0x000f, 0xa90f, 0xeaf9, 0x0001, - 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, - 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x95d0 + 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 = 0xee08; +unsigned short fw2300ipx_length01 = 0xf091; #else -unsigned short risc_code_length01 = 0xee08; +unsigned short risc_code_length01 = 0xf091; #endif diff --git a/drivers/scsi/qla2xxx/ql2322_fw.c b/drivers/scsi/qla2xxx/ql2322_fw.c index cb968e7a0fcd..53599a8e2a92 100644 --- a/drivers/scsi/qla2xxx/ql2322_fw.c +++ b/drivers/scsi/qla2xxx/ql2322_fw.c @@ -6,7 +6,7 @@ */ /* - * Firmware Version 3.03.18 (12:14 Sep 20, 2005) + * Firmware Version 3.03.20 (15:42 Feb 01, 2006) */ #ifdef UNIQUE_FW_NAME @@ -16,15 +16,15 @@ unsigned short risc_code_version = 3*1024+3; #endif #ifdef UNIQUE_FW_NAME -unsigned char fw2322ipx_version_str[] = {3, 3,18}; +unsigned char fw2322ipx_version_str[] = {3, 3,20}; #else -unsigned char firmware_version[] = {3, 3,18}; +unsigned char firmware_version[] = {3, 3,20}; #endif #ifdef UNIQUE_FW_NAME -#define fw2322ipx_VERSION_STRING "3.03.18" +#define fw2322ipx_VERSION_STRING "3.03.20" #else -#define FW_VERSION_STRING "3.03.18" +#define FW_VERSION_STRING "3.03.20" #endif #ifdef UNIQUE_FW_NAME @@ -38,12 +38,12 @@ unsigned short fw2322ipx_code01[] = { #else unsigned short risc_code01[] = { #endif - 0x0470, 0x0000, 0x0000, 0xe428, 0x0000, 0x0003, 0x0003, 0x0012, + 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, 0x2e31, 0x3820, 0x2020, 0x2020, 0x2400, 0x20a9, + 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, @@ -52,6331 +52,6424 @@ unsigned short risc_code01[] = { 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, 0x2bcb, 0x2051, 0x1800, 0x2a70, 0x20e1, - 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e68, 0x00f6, - 0x7888, 0x9005, 0x11f8, 0x2061, 0xc000, 0x080c, 0x20e3, 0x1170, - 0x2079, 0x0300, 0x080c, 0x20f9, 0x2061, 0xe000, 0x080c, 0x20e3, - 0x1128, 0x2079, 0x0380, 0x080c, 0x20f9, 0x0060, 0x00fe, 0x7883, + 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, 0x1b74, 0x2472, + 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, 0x0f65, 0x080c, 0x6186, 0x080c, 0xaee4, 0x080c, - 0x111c, 0x080c, 0x1346, 0x080c, 0x1c39, 0x080c, 0x938b, 0x080c, - 0x0d0b, 0x080c, 0x10a1, 0x080c, 0x3574, 0x080c, 0x79b3, 0x080c, - 0x6bf1, 0x080c, 0x8af6, 0x080c, 0x8757, 0x080c, 0x22d4, 0x080c, - 0x808e, 0x080c, 0x2112, 0x080c, 0x2250, 0x080c, 0x22c9, 0x2091, + 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, 0x11f4, 0x2071, 0x1800, 0x7003, 0x0000, 0x780c, - 0x9084, 0x0030, 0x9086, 0x0000, 0x190c, 0x0d79, 0x2071, 0x1800, - 0x7000, 0x908e, 0x0003, 0x1168, 0x080c, 0x4ced, 0x080c, 0x359b, - 0x080c, 0x7a1b, 0x080c, 0x7174, 0x080c, 0x8bdd, 0x080c, 0x8780, - 0x0c68, 0x000b, 0x0c88, 0x096d, 0x096e, 0x0b09, 0x096b, 0x0bc3, - 0x0d0a, 0x0d0a, 0x0d0a, 0x080c, 0x0d79, 0x0005, 0x0126, 0x00f6, - 0x2091, 0x8000, 0x7000, 0x9086, 0x0001, 0x1904, 0x0adc, 0x080c, - 0x0eb8, 0x080c, 0x769d, 0x0150, 0x080c, 0x76c0, 0x15b0, 0x2079, - 0x0100, 0x7828, 0x9085, 0x1800, 0x782a, 0x0478, 0x080c, 0x75cc, - 0x7000, 0x9086, 0x0001, 0x1904, 0x0adc, 0x7098, 0x9086, 0x0029, - 0x1904, 0x0adc, 0x080c, 0x8740, 0x080c, 0x8732, 0x2001, 0x0161, - 0x2003, 0x0001, 0x2079, 0x0100, 0x2011, 0xffff, 0x080c, 0x2adc, - 0x7a28, 0x9295, 0x5e2c, 0x7a2a, 0x2011, 0x7511, 0x080c, 0x882c, - 0x2011, 0x7504, 0x080c, 0x8938, 0x2011, 0x5fdd, 0x080c, 0x882c, - 0x2011, 0x8030, 0x901e, 0x7396, 0x04d0, 0x080c, 0x588a, 0x2079, - 0x0100, 0x7844, 0x9005, 0x1904, 0x0adc, 0x2011, 0x5fdd, 0x080c, - 0x882c, 0x2011, 0x7511, 0x080c, 0x882c, 0x2011, 0x7504, 0x080c, - 0x8938, 0x2001, 0x0265, 0x2001, 0x0205, 0x2003, 0x0000, 0x7840, - 0x9084, 0xfffb, 0x7842, 0x2001, 0x19a8, 0x2004, 0x9005, 0x1140, - 0x00c6, 0x2061, 0x0100, 0x080c, 0x612e, 0x00ce, 0x0804, 0x0adc, - 0x780f, 0x006b, 0x7a28, 0x080c, 0x76a5, 0x0118, 0x9295, 0x5e2c, - 0x0010, 0x9295, 0x402c, 0x7a2a, 0x2011, 0x8010, 0x73d8, 0x2001, - 0x19a9, 0x2003, 0x0001, 0x080c, 0x29a8, 0x080c, 0x4c28, 0x7248, - 0xc284, 0x724a, 0x2001, 0x180c, 0x200c, 0xc1ac, 0xc1cc, 0x2102, - 0x2001, 0x0390, 0x2003, 0x0400, 0x080c, 0xaaf7, 0x080c, 0xa2ec, - 0x2011, 0x0004, 0x080c, 0xcc43, 0x080c, 0xab13, 0x080c, 0x6a77, - 0x080c, 0x769d, 0x1120, 0x080c, 0x2a09, 0x0600, 0x0420, 0x080c, - 0x6135, 0x0140, 0x7097, 0x0001, 0x70d3, 0x0000, 0x080c, 0x5a57, - 0x0804, 0x0adc, 0x2001, 0x0390, 0x2003, 0x0404, 0x080c, 0x5820, - 0xd094, 0x0188, 0x2011, 0x180c, 0x2204, 0xc0cd, 0x2012, 0x080c, - 0x5824, 0xd0d4, 0x1118, 0x080c, 0x2a09, 0x1270, 0x2011, 0x180c, - 0x2204, 0xc0bc, 0x00a8, 0x080c, 0x5824, 0xd0d4, 0x1db8, 0x2011, - 0x180c, 0x2204, 0xc0bd, 0x0060, 0x2011, 0x180c, 0x2204, 0xc0bd, - 0x2012, 0x080c, 0x6bc5, 0x1128, 0xd0a4, 0x0118, 0x2204, 0xc0fd, - 0x2012, 0x080c, 0x6b8b, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x00a8, - 0x707f, 0x0000, 0x080c, 0x769d, 0x1130, 0x70b0, 0x9005, 0x1168, - 0x080c, 0xd0a1, 0x0050, 0x080c, 0xd0a1, 0x70dc, 0xd09c, 0x1128, - 0x70b0, 0x9005, 0x0110, 0x080c, 0x610b, 0x70e7, 0x0000, 0x70e3, - 0x0000, 0x70a7, 0x0000, 0x080c, 0x2a11, 0x0228, 0x2011, 0x0101, - 0x2204, 0xc0c4, 0x2012, 0x72dc, 0x080c, 0x769d, 0x1178, 0x9016, - 0x0016, 0x080c, 0x27b9, 0x2019, 0x196e, 0x211a, 0x001e, 0x705f, - 0xffff, 0x7063, 0x00ef, 0x7083, 0x0000, 0x0020, 0x2019, 0x196e, - 0x201b, 0x0000, 0x2079, 0x1847, 0x7804, 0xd0ac, 0x0108, 0xc295, - 0x72de, 0x080c, 0x769d, 0x0118, 0x9296, 0x0004, 0x0518, 0x2011, - 0x0001, 0x080c, 0xcc43, 0x70ab, 0x0000, 0x70af, 0xffff, 0x7003, - 0x0002, 0x00fe, 0x080c, 0x30c8, 0x080c, 0xaaf7, 0x2011, 0x0005, - 0x080c, 0xa426, 0x080c, 0xab13, 0x080c, 0x769d, 0x0148, 0x00c6, - 0x2061, 0x0100, 0x0016, 0x080c, 0x27b9, 0x61e2, 0x001e, 0x00ce, - 0x012e, 0x00e0, 0x70ab, 0x0000, 0x70af, 0xffff, 0x7003, 0x0002, - 0x080c, 0xaaf7, 0x2011, 0x0005, 0x080c, 0xa426, 0x080c, 0xab13, - 0x080c, 0x769d, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, - 0x27b9, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, - 0x00b6, 0x080c, 0x769d, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, - 0x0782, 0x080c, 0x769d, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, - 0x86ff, 0x0138, 0x9180, 0x1000, 0x2004, 0x905d, 0x0110, 0xb800, - 0xd0bc, 0x090c, 0x3404, 0x8108, 0x1f04, 0x0af0, 0x707f, 0x0000, - 0x7080, 0x9084, 0x00ff, 0x7082, 0x70b3, 0x0000, 0x00be, 0x00ce, - 0x0005, 0x00b6, 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, - 0x1904, 0x0bc0, 0x70ac, 0x9086, 0xffff, 0x0120, 0x080c, 0x30c8, - 0x0804, 0x0bc0, 0x70dc, 0xd0ac, 0x1110, 0xd09c, 0x0538, 0xd084, - 0x0528, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0xd08c, - 0x01e8, 0x080c, 0x346d, 0x11b0, 0x70e0, 0x9086, 0xffff, 0x0190, - 0x080c, 0x3261, 0x70dc, 0xd094, 0x1904, 0x0bc0, 0x2011, 0x0001, - 0x080c, 0xd35d, 0x0110, 0x2011, 0x0003, 0x901e, 0x080c, 0x329b, - 0x0804, 0x0bc0, 0x70e4, 0x9005, 0x1904, 0x0bc0, 0x70a8, 0x9005, - 0x1904, 0x0bc0, 0x70dc, 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x0bc0, - 0x080c, 0x6b8b, 0x1904, 0x0bc0, 0x080c, 0x6bde, 0x1904, 0x0bc0, - 0x080c, 0x6bc5, 0x01c0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, - 0x0016, 0x080c, 0x6783, 0x1118, 0xb800, 0xd0ec, 0x1138, 0x001e, - 0x8108, 0x1f04, 0x0b60, 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, - 0x015e, 0x0804, 0x0bc0, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, - 0x000e, 0x2011, 0x19b5, 0x080c, 0x0fd5, 0x2011, 0x19cf, 0x080c, - 0x0fd5, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x70af, 0xffff, - 0x080c, 0x0e8c, 0x9006, 0x080c, 0x2646, 0x080c, 0x346d, 0x0118, - 0x080c, 0x4dc5, 0x0050, 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, - 0x0006, 0x080c, 0x4ddf, 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, - 0x080c, 0x76c0, 0x0150, 0x080c, 0x769d, 0x7828, 0x0118, 0x9084, - 0xe1ff, 0x0010, 0x9084, 0xffdf, 0x782a, 0x00fe, 0x080c, 0xaaf7, - 0x2001, 0x19ea, 0x2004, 0x9086, 0x0005, 0x1120, 0x2011, 0x0000, - 0x080c, 0xa426, 0x2011, 0x0000, 0x080c, 0xa430, 0x080c, 0xab13, - 0x012e, 0x00be, 0x0005, 0x0016, 0x0026, 0x0046, 0x00f6, 0x0126, - 0x2091, 0x8000, 0x2079, 0x0100, 0x7904, 0x918c, 0xfffd, 0x7906, - 0x2009, 0x00f7, 0x080c, 0x60f4, 0x7940, 0x918c, 0x0010, 0x7942, - 0x7924, 0xd1b4, 0x0120, 0x2011, 0x0040, 0x080c, 0x2adc, 0xd19c, - 0x0120, 0x2011, 0x0008, 0x080c, 0x2adc, 0x0006, 0x0036, 0x0156, - 0x0000, 0x2001, 0x19a9, 0x2004, 0x9005, 0x1518, 0x080c, 0x2a70, - 0x1148, 0x2001, 0x0001, 0x080c, 0x29d7, 0x2001, 0x0001, 0x080c, - 0x29ba, 0x00b8, 0x080c, 0x2a78, 0x1138, 0x9006, 0x080c, 0x29d7, - 0x9006, 0x080c, 0x29ba, 0x0068, 0x080c, 0x2a80, 0x1d50, 0x2001, - 0x1999, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, 0x27e5, 0x0804, - 0x0cbd, 0x20a9, 0x003a, 0x1d04, 0x0c13, 0x080c, 0x8918, 0x1f04, - 0x0c13, 0x080c, 0x76ae, 0x0148, 0x080c, 0x76c0, 0x1118, 0x080c, - 0x79ae, 0x0050, 0x080c, 0x76a5, 0x0dd0, 0x080c, 0x79a9, 0x080c, - 0x799f, 0x080c, 0x75cc, 0x0020, 0x2009, 0x00f8, 0x080c, 0x60f4, - 0x7850, 0xc0e5, 0x7852, 0x080c, 0x769d, 0x0120, 0x7843, 0x0090, - 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, 0x0d0c, 0x8918, - 0x7820, 0xd09c, 0x15a0, 0x080c, 0x769d, 0x0904, 0x0c9f, 0x7824, - 0xd0ac, 0x1904, 0x0cc2, 0x080c, 0x76c0, 0x1548, 0x0046, 0x2021, - 0x0320, 0x8421, 0x1df0, 0x004e, 0x2011, 0x1800, 0x080c, 0x2adc, - 0x080c, 0x2a88, 0x7824, 0x9084, 0x1800, 0x1168, 0x9484, 0x0fff, - 0x1140, 0x2001, 0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, - 0x0ce5, 0x8421, 0x1160, 0x1d04, 0x0c6f, 0x080c, 0x8918, 0x080c, - 0x79a9, 0x080c, 0x799f, 0x7003, 0x0001, 0x0804, 0x0cc2, 0x8319, - 0x1928, 0x2001, 0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, - 0x0ce5, 0x1d04, 0x0c85, 0x080c, 0x8918, 0x2009, 0x199c, 0x2104, - 0x9005, 0x0118, 0x8001, 0x200a, 0x1188, 0x200b, 0x000a, 0x2011, - 0x0048, 0x080c, 0x2adc, 0x20a9, 0x0002, 0x080c, 0x2a69, 0x7924, - 0x080c, 0x2a88, 0xd19c, 0x0110, 0x080c, 0x29a8, 0x00f0, 0x080c, - 0x76ae, 0x1140, 0x94a2, 0x03e8, 0x1128, 0x080c, 0x7671, 0x7003, - 0x0001, 0x00c0, 0x2011, 0x1800, 0x080c, 0x2adc, 0x080c, 0x2a88, - 0x7824, 0x080c, 0x76b7, 0x0110, 0xd0ac, 0x1160, 0x9084, 0x1800, - 0x0904, 0x0c77, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, - 0x2646, 0x00a0, 0x7850, 0xc0e4, 0x7852, 0x2009, 0x180c, 0x210c, - 0xd19c, 0x1120, 0x7904, 0x918d, 0x0002, 0x7906, 0x2011, 0x0048, - 0x080c, 0x2adc, 0x7828, 0x9085, 0x0028, 0x782a, 0x2001, 0x19a9, - 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, 0x8918, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x00be, 0x004e, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, - 0x2071, 0x189e, 0x7004, 0x9086, 0x0001, 0x1110, 0x080c, 0x359b, - 0x00ee, 0x0005, 0x0005, 0x2a70, 0x2061, 0x19ad, 0x2063, 0x0003, - 0x6007, 0x0003, 0x600b, 0x0012, 0x600f, 0x0137, 0x2001, 0x197d, - 0x900e, 0x2102, 0x7196, 0x2001, 0x0100, 0x2004, 0x9082, 0x0002, - 0x0218, 0x705f, 0xffff, 0x0008, 0x715e, 0x7067, 0xffff, 0x717e, - 0x7182, 0x080c, 0xd0a1, 0x70ef, 0x00c0, 0x2061, 0x196d, 0x6003, - 0x0909, 0x6106, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, - 0x6017, 0x001f, 0x611a, 0x601f, 0x07d0, 0x2061, 0x1975, 0x6003, - 0x8000, 0x6106, 0x610a, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6116, - 0x601b, 0x0001, 0x611e, 0x2061, 0x198a, 0x6003, 0x514c, 0x6007, - 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0x182c, 0x2102, - 0x0005, 0x9016, 0x080c, 0x6783, 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, 0x0d7b, 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, 0x1b2c, 0x7a08, 0x226a, 0x2069, - 0x1b2d, 0x7a18, 0x226a, 0x8d68, 0x7a1c, 0x226a, 0x782c, 0x2019, - 0x1b3a, 0x201a, 0x2019, 0x1b3d, 0x9016, 0x7808, 0xd09c, 0x0168, - 0x7820, 0x201a, 0x8210, 0x8318, 0x9386, 0x1b56, 0x0108, 0x0ca8, - 0x7808, 0xd09c, 0x0110, 0x2011, 0xdead, 0x2019, 0x1b3b, 0x782c, - 0x201a, 0x8318, 0x221a, 0x7803, 0x0000, 0x2069, 0x1a82, 0x901e, - 0x20a9, 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, 0x8318, 0x1f04, - 0x0dd2, 0x2069, 0x1aa2, 0x2019, 0x0050, 0x20a9, 0x0020, 0x7b26, - 0x7a28, 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0ddf, 0x0491, 0x002e, - 0x003e, 0x00de, 0x015e, 0x2079, 0x1800, 0x7803, 0x0005, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a26, - 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, - 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, 0x080c, 0x582f, - 0x1170, 0x080c, 0x0f26, 0x0110, 0x080c, 0x0e79, 0x080c, 0x582f, - 0x1130, 0x2071, 0x1800, 0x2011, 0x8000, 0x080c, 0x0f3a, 0x0c70, - 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, - 0x1120, 0x2001, 0x0015, 0x080c, 0xaae8, 0x2079, 0x0380, 0x2069, - 0x1b0c, 0x7818, 0x6802, 0x781c, 0x6806, 0x7840, 0x680a, 0x7844, - 0x680e, 0x782c, 0x6812, 0x2019, 0x1b17, 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, 0x1acc, - 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7828, 0x206a, 0x8d68, 0x8318, - 0x1f04, 0x0e53, 0x2069, 0x1aec, 0x2019, 0x00b0, 0x20a9, 0x0020, - 0x7b26, 0x7828, 0x206a, 0x8d68, 0x8318, 0x1f04, 0x0e60, 0x0005, - 0x918c, 0x03ff, 0x2001, 0x0003, 0x2004, 0x9084, 0x0600, 0x1118, - 0x918d, 0x6c00, 0x0010, 0x918d, 0x6400, 0x2001, 0x017f, 0x2102, - 0x0005, 0x0026, 0x0126, 0x2011, 0x0080, 0x080c, 0x0f18, 0x20a9, - 0x0900, 0x080c, 0x0f4e, 0x2011, 0x0040, 0x080c, 0x0f18, 0x20a9, - 0x0900, 0x080c, 0x0f4e, 0x0c78, 0x0026, 0x080c, 0x0f26, 0x1188, - 0x2011, 0x010e, 0x2214, 0x9294, 0x0007, 0x9296, 0x0007, 0x0118, - 0x2011, 0x0947, 0x0010, 0x2011, 0x1b47, 0x080c, 0x0f3a, 0x002e, - 0x0005, 0x2011, 0x010e, 0x2214, 0x9294, 0x0007, 0x9296, 0x0007, - 0x0118, 0x2011, 0xa880, 0x0010, 0x2011, 0x6840, 0xd0e4, 0x70f3, - 0x0000, 0x1120, 0x70f3, 0x0fa0, 0x080c, 0x0f2b, 0x002e, 0x0005, - 0x0026, 0x080c, 0x0f26, 0x0148, 0xd0a4, 0x1138, 0x2011, 0xcdd5, - 0x0010, 0x2011, 0x0080, 0x080c, 0x0f2b, 0x002e, 0x0005, 0x0026, - 0x70f3, 0x0000, 0x080c, 0x0f26, 0x1130, 0x2011, 0x8040, 0x080c, - 0x0f3a, 0x002e, 0x0005, 0x080c, 0x2a80, 0x1118, 0x2011, 0xcdc5, - 0x0010, 0x2011, 0xcac2, 0x080c, 0x0f2b, 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, - 0x0ede, 0x0eb8, 0x0eb8, 0x0e8c, 0x0ec7, 0x0eb8, 0x0eb8, 0x0ec7, - 0xc284, 0x0016, 0x3b08, 0x3a00, 0x9104, 0x918d, 0x00c1, 0x21d8, - 0x9084, 0xff3e, 0x9205, 0x20d0, 0x001e, 0x0005, 0x2001, 0x183b, - 0x2004, 0xd0dc, 0x0005, 0x9e86, 0x1800, 0x190c, 0x0d79, 0x70ec, - 0xd0e4, 0x0108, 0xc2e5, 0x72ee, 0xd0e4, 0x1118, 0x9294, 0x00c1, - 0x08f9, 0x0005, 0x9e86, 0x1800, 0x190c, 0x0d79, 0x70e8, 0xd0f4, - 0x0108, 0xc2f5, 0x72ea, 0xd0f4, 0x1140, 0x9284, 0x8000, 0x8005, - 0xc284, 0x9215, 0x9294, 0x00c1, 0x0861, 0x0005, 0x1d04, 0x0f4e, - 0x2091, 0x6000, 0x1f04, 0x0f4e, 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, 0x0f55, 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, 0x0d59, - 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x4001, 0x0005, 0x89ff, - 0x0140, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, 0x107f, 0x009e, - 0x0cb0, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, 0x10f8, 0x090c, - 0x0d79, 0x00ee, 0x0005, 0x0086, 0x00e6, 0x0006, 0x0026, 0x0036, - 0x0126, 0x2091, 0x8000, 0x00c9, 0x2071, 0x1800, 0x73c0, 0x702c, - 0x9016, 0x9045, 0x0158, 0x8210, 0x9906, 0x090c, 0x0d79, 0x2300, - 0x9202, 0x0120, 0x1a0c, 0x0d79, 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, 0x0d79, 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, 0x8732, 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, 0x1a25, 0x7007, - 0x0000, 0x9006, 0x701e, 0x7022, 0x7002, 0x2071, 0x0000, 0x7010, - 0x9085, 0x8044, 0x7012, 0x2071, 0x0080, 0x9006, 0x702b, 0x0060, - 0x20a9, 0x0040, 0x7022, 0x1f04, 0x1132, 0x702b, 0x0060, 0x702b, - 0x0020, 0x20a9, 0x0040, 0x7022, 0x1f04, 0x113b, 0x702b, 0x0020, - 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0xa06f, 0x0000, - 0x2071, 0x1a25, 0x701c, 0x9088, 0x1a2f, 0x280a, 0x8000, 0x9084, - 0x003f, 0x701e, 0x7120, 0x9106, 0x090c, 0x0d79, 0x7004, 0x9005, - 0x1128, 0x00f6, 0x2079, 0x0080, 0x00a9, 0x00fe, 0x00ee, 0x012e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, 0x1a25, 0x7004, - 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x0021, 0x00fe, 0x00ee, - 0x012e, 0x0005, 0x7004, 0x9086, 0x0000, 0x1110, 0x7007, 0x0006, - 0x7000, 0x0002, 0x1184, 0x1307, 0x1182, 0x1182, 0x12fb, 0x12fb, - 0x12fb, 0x12fb, 0x080c, 0x0d79, 0x701c, 0x7120, 0x9106, 0x1148, - 0x792c, 0x9184, 0x0001, 0x1120, 0xd1fc, 0x1110, 0x7007, 0x0000, - 0x0005, 0x0096, 0x9180, 0x1a2f, 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, 0x1a25, 0x2104, 0xc095, - 0x200a, 0x080c, 0x1161, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1a25, - 0x00f6, 0x2079, 0x0080, 0x792c, 0xd1bc, 0x190c, 0x0d72, 0x782b, - 0x0002, 0xd1fc, 0x0120, 0x918c, 0x0700, 0x7004, 0x0023, 0x00fe, - 0x00ee, 0x001e, 0x0005, 0x1172, 0x121a, 0x124e, 0x1326, 0x0d79, - 0x1341, 0x0d79, 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, 0x11b7, 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, - 0x0100, 0x009e, 0x7007, 0x0000, 0x080c, 0x1172, 0x0005, 0x7008, - 0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x0ca0, 0x918c, 0x0700, - 0x1150, 0x700c, 0x9005, 0x0180, 0x7800, 0x7802, 0x7804, 0x7806, - 0x080c, 0x11cc, 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, 0x1161, 0x0005, 0x00de, 0x009e, 0x080c, 0x1161, - 0x0005, 0xa8a8, 0xd08c, 0x0005, 0x0096, 0xa0a0, 0x904d, 0x090c, - 0x0d79, 0xa06c, 0x908e, 0x0100, 0x0130, 0xa87b, 0x0030, 0xa883, - 0x0000, 0xa897, 0x4002, 0x080c, 0x6f05, 0xa09f, 0x0000, 0xa0a3, - 0x0000, 0x2848, 0x080c, 0x107f, 0x009e, 0x0005, 0x00a6, 0xa0a0, - 0x904d, 0x090c, 0x0d79, 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, 0x1142, 0x00e8, 0xa97c, 0xa894, 0x0016, 0x0006, - 0x080c, 0x6f05, 0x000e, 0x001e, 0xd1fc, 0x1138, 0xd1f4, 0x0128, - 0x00c6, 0x2060, 0x080c, 0xaf4e, 0x00ce, 0x7008, 0x2048, 0xa89f, - 0x0000, 0xa8a3, 0x0000, 0x080c, 0x107f, 0x7007, 0x0000, 0x080c, - 0x1161, 0x00ae, 0x0005, 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, - 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x012e, 0x0005, 0x0096, - 0x2001, 0x1930, 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, 0x1930, 0x204c, - 0xaa7c, 0x009e, 0x080c, 0x8e1e, 0x2009, 0x188c, 0x2104, 0x9084, - 0xfffc, 0x200a, 0x080c, 0x8c80, 0x7007, 0x0000, 0x080c, 0x1172, - 0x0005, 0x7007, 0x0000, 0x080c, 0x1172, 0x0005, 0x0126, 0x2091, - 0x2200, 0x2079, 0x0300, 0x2071, 0x1a6f, 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, 0x13aa, 0x0cc8, - 0x2001, 0x1a70, 0x2003, 0x0000, 0x78ab, 0x0004, 0x78ac, 0xd0ac, - 0x1de8, 0x78ab, 0x0002, 0x7807, 0x0007, 0x7827, 0x0030, 0x782b, - 0x0400, 0x7827, 0x0031, 0x782b, 0x1a82, 0x78e3, 0xff00, 0x781f, - 0xff00, 0x781b, 0xff00, 0x2001, 0x1a71, 0x2003, 0x0000, 0x2001, - 0x0200, 0x2004, 0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x1a82, - 0x602f, 0x1ddc, 0x2001, 0x181a, 0x2004, 0x9082, 0x1ddc, 0x6032, - 0x603b, 0x1ede, 0x602b, 0x1ac2, 0x6007, 0x1aa2, 0x2061, 0x1aa2, - 0x606f, 0x193e, 0x2001, 0x1929, 0x2004, 0x607a, 0x783f, 0x3474, - 0x00ce, 0x0005, 0x9086, 0x000d, 0x11d0, 0x7808, 0xd09c, 0x01b8, - 0x7820, 0x0026, 0x2010, 0x080c, 0xcc21, 0x0180, 0x2260, 0x6000, - 0x9086, 0x0004, 0x1158, 0x0016, 0x6120, 0x9186, 0x0009, 0x0108, - 0x0020, 0x2009, 0x004c, 0x080c, 0xafec, 0x001e, 0x002e, 0x0005, - 0x0126, 0x2091, 0x2200, 0x7908, 0x9184, 0x0070, 0x190c, 0x0d72, - 0xd19c, 0x05a0, 0x7820, 0x908c, 0xf000, 0x0540, 0x2060, 0x6020, - 0x9086, 0x0003, 0x1550, 0x6000, 0x9086, 0x0004, 0x1530, 0x6114, - 0x2148, 0xa876, 0xa87a, 0xa867, 0x0103, 0x080c, 0x6d26, 0x00b6, - 0x6010, 0x2058, 0xba3c, 0x8211, 0x0208, 0xba3e, 0xb8d0, 0x9005, - 0x190c, 0x68ae, 0x00be, 0x6044, 0xd0fc, 0x190c, 0xab20, 0x080c, - 0xaf77, 0x7808, 0xd09c, 0x19b0, 0x012e, 0x0005, 0x908a, 0x0024, - 0x1a0c, 0x0d79, 0x002b, 0x012e, 0x0005, 0x04b0, 0x012e, 0x0005, - 0x142c, 0x1452, 0x1482, 0x1487, 0x148b, 0x1490, 0x14b8, 0x14bc, - 0x14ca, 0x14ce, 0x142c, 0x159b, 0x159f, 0x1611, 0x1618, 0x142c, - 0x1619, 0x161a, 0x1625, 0x162c, 0x142c, 0x142c, 0x142c, 0x142c, - 0x142c, 0x142c, 0x142c, 0x1492, 0x142c, 0x145a, 0x147f, 0x1446, - 0x142c, 0x1466, 0x1430, 0x142e, 0x080c, 0x0d79, 0x080c, 0x0d72, - 0x080c, 0x1637, 0x2009, 0x1a7e, 0x2104, 0x8000, 0x200a, 0x080c, - 0x8151, 0x080c, 0x1b3b, 0x0005, 0x6044, 0xd0fc, 0x190c, 0xab20, - 0x2009, 0x0055, 0x080c, 0xafec, 0x012e, 0x0005, 0x080c, 0x1637, - 0x2060, 0x6044, 0xd0fc, 0x190c, 0xab20, 0x2009, 0x0055, 0x080c, - 0xafec, 0x0005, 0x2009, 0x0048, 0x080c, 0x1637, 0x2060, 0x080c, - 0xafec, 0x0005, 0x2009, 0x0054, 0x080c, 0x1637, 0x2060, 0x6044, - 0xd0fc, 0x190c, 0xab20, 0x080c, 0xafec, 0x0005, 0x080c, 0x1637, - 0x2060, 0x0056, 0x0066, 0x080c, 0x1637, 0x2028, 0x080c, 0x1637, - 0x2030, 0x0036, 0x0046, 0x2021, 0x0000, 0x2418, 0x2009, 0x0056, - 0x080c, 0xafec, 0x004e, 0x003e, 0x006e, 0x005e, 0x0005, 0x080c, - 0x1637, 0x0005, 0x7004, 0xc085, 0xc0b5, 0x7006, 0x0005, 0x7004, - 0xc085, 0x7006, 0x0005, 0x080c, 0x1637, 0x080c, 0x1734, 0x0005, - 0x080c, 0x0d79, 0x080c, 0x1637, 0x2060, 0x6014, 0x0096, 0x2048, - 0xa83b, 0xffff, 0x009e, 0x2009, 0x0048, 0x080c, 0xafec, 0x2001, - 0x015d, 0x2003, 0x0000, 0x2009, 0x03e8, 0x8109, 0x0160, 0x2001, - 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, - 0x1110, 0x080c, 0x163c, 0x2001, 0x0307, 0x2003, 0x8000, 0x0005, - 0x7004, 0xc095, 0x7006, 0x0005, 0x080c, 0x1637, 0x2060, 0x6014, - 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009, 0x0048, 0x080c, - 0xafec, 0x0005, 0x080c, 0x1637, 0x080c, 0x0d79, 0x080c, 0x1637, - 0x080c, 0x1586, 0x7827, 0x0018, 0x79ac, 0xd1dc, 0x0904, 0x1537, - 0x7827, 0x0015, 0x7828, 0x782b, 0x0000, 0x9065, 0x0140, 0x2001, - 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0804, 0x153d, 0x7004, - 0x9005, 0x01c8, 0x1188, 0x78ab, 0x0004, 0x7827, 0x0018, 0x782b, - 0x0000, 0xd1bc, 0x090c, 0x0d79, 0x2001, 0x020d, 0x2003, 0x0050, - 0x2003, 0x0020, 0x0804, 0x156b, 0x78ab, 0x0004, 0x7803, 0x0001, - 0x080c, 0x159f, 0x0005, 0x7827, 0x0018, 0xa001, 0x7828, 0x7827, - 0x0011, 0xa001, 0x7928, 0x9106, 0x0110, 0x79ac, 0x08e0, 0x00e6, - 0x2071, 0x0200, 0x702c, 0xd0c4, 0x0140, 0x00ee, 0x080c, 0x1b3b, - 0x080c, 0x135a, 0x7803, 0x0001, 0x0005, 0x7037, 0x0001, 0xa001, - 0x7150, 0x00ee, 0x918c, 0xff00, 0x9186, 0x0500, 0x0110, 0x79ac, - 0x0810, 0x7004, 0xc09d, 0x7006, 0x78ab, 0x0004, 0x7803, 0x0001, - 0x080c, 0x159f, 0x2001, 0x020d, 0x2003, 0x0020, 0x0005, 0x7828, - 0x782b, 0x0000, 0x9065, 0x090c, 0x0d79, 0x6014, 0x2048, 0x78ab, - 0x0004, 0x918c, 0x0700, 0x01a8, 0x080c, 0x8151, 0x080c, 0x1b3b, - 0x080c, 0xcc33, 0x0158, 0xa9ac, 0xa936, 0xa9b0, 0xa93a, 0xa83f, - 0xffff, 0xa843, 0xffff, 0xa880, 0xc0bd, 0xa882, 0x080c, 0xc81b, - 0x0005, 0x6020, 0x9086, 0x0009, 0x1128, 0x2009, 0x004c, 0x080c, - 0xafec, 0x0048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x6024, 0x190c, 0xd036, 0x2029, 0x00c8, 0x8529, 0x0128, 0x2001, - 0x0201, 0x2004, 0x9005, 0x0dc8, 0x7dbc, 0x080c, 0xebc0, 0xd5a4, - 0x1118, 0x080c, 0x163c, 0x0005, 0x080c, 0x8151, 0x080c, 0x1b3b, - 0x0005, 0x781f, 0x0300, 0x7803, 0x0001, 0x0005, 0x0016, 0x0066, - 0x0076, 0x00f6, 0x2079, 0x0300, 0x7908, 0x918c, 0x0007, 0x9186, - 0x0003, 0x0120, 0x2001, 0x0016, 0x080c, 0x16ad, 0x00fe, 0x007e, - 0x006e, 0x001e, 0x0005, 0x7004, 0xc09d, 0x7006, 0x0005, 0x7104, - 0x9184, 0x0004, 0x190c, 0x0d79, 0xd184, 0x11b1, 0xd19c, 0x0180, - 0xc19c, 0x7106, 0x0016, 0x080c, 0x1717, 0x001e, 0x0148, 0x2001, - 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x080c, 0x163c, 0x0005, - 0x81ff, 0x190c, 0x0d79, 0x0005, 0x2100, 0xc184, 0xc1b4, 0x7106, - 0xd0b4, 0x0016, 0x00e6, 0x1904, 0x1606, 0x2071, 0x0200, 0x080c, - 0x1704, 0x05e0, 0x080c, 0x1717, 0x05b0, 0x6014, 0x9005, 0x05b0, - 0x0096, 0x2048, 0xa864, 0x009e, 0x9084, 0x00ff, 0x908e, 0x0029, - 0x0160, 0x908e, 0x0048, 0x1550, 0x601c, 0xd084, 0x11e0, 0x00f6, - 0x2c78, 0x080c, 0x17a1, 0x00fe, 0x00b0, 0x00f6, 0x2c78, 0x080c, - 0x192a, 0x00fe, 0x2009, 0x01f4, 0x8109, 0x0168, 0x2001, 0x0201, - 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1118, - 0x080c, 0x163c, 0x0040, 0x2001, 0x020d, 0x2003, 0x0020, 0x080c, - 0x135a, 0x7803, 0x0001, 0x00ee, 0x001e, 0x0005, 0x080c, 0x1717, - 0x0dd0, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0461, - 0x0c90, 0x0429, 0x2060, 0x2009, 0x0053, 0x080c, 0xafec, 0x0005, - 0x0005, 0x0005, 0x00e1, 0x2008, 0x00d1, 0x0006, 0x7004, 0xc09d, - 0x7006, 0x000e, 0x080c, 0x916f, 0x0005, 0x0089, 0x9005, 0x0118, - 0x080c, 0x8d72, 0x0cd0, 0x0005, 0x2001, 0x0036, 0x2009, 0x1820, - 0x210c, 0x2011, 0x181f, 0x2214, 0x080c, 0x16ad, 0x0005, 0x7808, - 0xd09c, 0x0de8, 0x7820, 0x0005, 0x080c, 0x1586, 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, 0x169f, 0x6827, - 0x0001, 0x8109, 0x1dd0, 0x04d9, 0x6827, 0x0002, 0x04c1, 0x6804, - 0x9005, 0x1130, 0x682c, 0xd0e4, 0x1500, 0x6804, 0x9005, 0x0de8, - 0x79b8, 0xd1ec, 0x1130, 0x08c0, 0x080c, 0x8151, 0x080c, 0x1b3b, - 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, 0x1a6f, 0x7008, 0x9005, 0x1110, 0x78e3, - 0x0c0c, 0x8000, 0x700a, 0x0026, 0x2011, 0x0006, 0x7808, 0xd09c, - 0x0150, 0x0016, 0x0026, 0x00c6, 0x080c, 0x13c8, 0x00ce, 0x002e, - 0x001e, 0x8211, 0x1d98, 0x002e, 0x000e, 0x0006, 0x7832, 0x7936, - 0x7a3a, 0x781b, 0x8080, 0x00b9, 0x1178, 0x2071, 0x1a6f, 0x7008, - 0x9005, 0x0130, 0x8001, 0x0a0c, 0x0d79, 0x700a, 0x78e3, 0x0c00, - 0x000e, 0x00ee, 0x00fe, 0x0005, 0x000e, 0x792c, 0x3900, 0x8000, - 0x2004, 0x080c, 0x0d79, 0x2009, 0xff00, 0x8109, 0x0120, 0x7818, - 0xd0bc, 0x1dd8, 0x0005, 0x9085, 0x0001, 0x0005, 0x7832, 0x7936, - 0x7a3a, 0x781b, 0x8080, 0x0c79, 0x1108, 0x0005, 0x792c, 0x3900, - 0x8000, 0x2004, 0x080c, 0x0d79, 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, 0x8151, 0x080c, 0x1b3b, 0x9006, - 0x00ee, 0x004e, 0x000e, 0x0005, 0x0c11, 0x1108, 0x0005, 0x00e6, - 0x0016, 0x2071, 0x0200, 0x0841, 0x6124, 0xd1dc, 0x01f8, 0x701c, - 0xd08c, 0x0904, 0x1796, 0x7017, 0x0000, 0x2001, 0x0264, 0x2004, - 0xd0bc, 0x0904, 0x1796, 0x2001, 0x0268, 0x00c6, 0x2064, 0x6104, - 0x6038, 0x00ce, 0x918e, 0x0039, 0x1904, 0x1796, 0x9c06, 0x15f0, - 0x0126, 0x2091, 0x2600, 0x080c, 0x80a9, 0x012e, 0x7358, 0x745c, - 0x6014, 0x905d, 0x0598, 0x2b48, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x190c, 0xd011, 0xab42, 0xac3e, 0x2001, 0x1869, - 0x2004, 0xd0b4, 0x1170, 0x601c, 0xd0e4, 0x1158, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1120, 0xa83b, 0x7fff, 0xa837, - 0xffff, 0x080c, 0x1efe, 0x1190, 0x080c, 0x1987, 0x2a00, 0xa816, - 0x0130, 0x2800, 0xa80e, 0x2c05, 0xa80a, 0x2c00, 0xa812, 0x7037, - 0x0020, 0x781f, 0x0300, 0x001e, 0x00ee, 0x0005, 0x7037, 0x0050, - 0x7037, 0x0020, 0x001e, 0x00ee, 0x080c, 0x163c, 0x0005, 0x080c, - 0x0d79, 0x2cf0, 0x0126, 0x2091, 0x2200, 0x0016, 0x00c6, 0x3e60, - 0x6014, 0x2048, 0x2940, 0x903e, 0x2730, 0xa864, 0x2068, 0xa81a, - 0x9d84, 0x000f, 0x9088, 0x1ede, 0x2165, 0x0002, 0x17cd, 0x183b, - 0x17cd, 0x17cd, 0x17d1, 0x181c, 0x17cd, 0x17f1, 0x17c6, 0x1832, - 0x17cd, 0x17cd, 0x17d6, 0x1928, 0x1805, 0x17fb, 0xa964, 0x918c, - 0x00ff, 0x918e, 0x0048, 0x0904, 0x1832, 0x9085, 0x0001, 0x0804, - 0x191e, 0xa87c, 0xd0ac, 0x0dc8, 0x0804, 0x1842, 0xa87c, 0xd0ac, - 0x0da0, 0x0804, 0x18ad, 0xa898, 0x901d, 0x1108, 0xab9c, 0x9016, - 0xaab2, 0xaa3e, 0xaa42, 0x3e00, 0x9080, 0x0008, 0x2004, 0x9080, - 0x933f, 0x2005, 0x9005, 0x090c, 0x0d79, 0x2004, 0xa8ae, 0x0804, - 0x1906, 0xa87c, 0xd0bc, 0x09c8, 0xa890, 0xa842, 0xa88c, 0xa83e, - 0xa888, 0x0804, 0x1842, 0xa87c, 0xd0bc, 0x0978, 0xa890, 0xa842, - 0xa88c, 0xa83e, 0xa888, 0x0804, 0x18ad, 0xa87c, 0xd0bc, 0x0928, - 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa804, 0x9045, 0x090c, 0x0d79, - 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x1ede, 0x2065, 0xa888, - 0xd19c, 0x1904, 0x18ad, 0x0430, 0xa87c, 0xd0ac, 0x0904, 0x17cd, - 0xa804, 0x9045, 0x090c, 0x0d79, 0xa164, 0xa91a, 0x91ec, 0x000f, - 0x9d80, 0x1ede, 0x2065, 0x9006, 0xa842, 0xa83e, 0xd19c, 0x1904, - 0x18ad, 0x0080, 0xa87c, 0xd0ac, 0x0904, 0x17cd, 0x9006, 0xa842, - 0xa83e, 0x0804, 0x18ad, 0xa87c, 0xd0ac, 0x0904, 0x17cd, 0x9006, - 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0d79, 0x9082, - 0x001b, 0x0002, 0x1865, 0x1865, 0x1867, 0x1865, 0x1865, 0x1865, - 0x1871, 0x1865, 0x1865, 0x1865, 0x187b, 0x1865, 0x1865, 0x1865, - 0x1885, 0x1865, 0x1865, 0x1865, 0x188f, 0x1865, 0x1865, 0x1865, - 0x1899, 0x1865, 0x1865, 0x1865, 0x18a3, 0x080c, 0x0d79, 0xa574, - 0xa478, 0x9d86, 0x0024, 0x0904, 0x17db, 0xa37c, 0xa280, 0x0804, - 0x1906, 0xa584, 0xa488, 0x9d86, 0x0024, 0x0904, 0x17db, 0xa38c, - 0xa290, 0x0804, 0x1906, 0xa594, 0xa498, 0x9d86, 0x0024, 0x0904, - 0x17db, 0xa39c, 0xa2a0, 0x0804, 0x1906, 0xa5a4, 0xa4a8, 0x9d86, - 0x0024, 0x0904, 0x17db, 0xa3ac, 0xa2b0, 0x0804, 0x1906, 0xa5b4, - 0xa4b8, 0x9d86, 0x0024, 0x0904, 0x17db, 0xa3bc, 0xa2c0, 0x0804, - 0x1906, 0xa5c4, 0xa4c8, 0x9d86, 0x0024, 0x0904, 0x17db, 0xa3cc, - 0xa2d0, 0x0804, 0x1906, 0xa5d4, 0xa4d8, 0x9d86, 0x0024, 0x0904, - 0x17db, 0xa3dc, 0xa2e0, 0x0804, 0x1906, 0x2c05, 0x908a, 0x0034, - 0x1a0c, 0x0d79, 0x9082, 0x001b, 0x0002, 0x18d0, 0x18ce, 0x18ce, - 0x18ce, 0x18ce, 0x18ce, 0x18db, 0x18ce, 0x18ce, 0x18ce, 0x18ce, - 0x18ce, 0x18e6, 0x18ce, 0x18ce, 0x18ce, 0x18ce, 0x18ce, 0x18f1, - 0x18ce, 0x18ce, 0x18ce, 0x18ce, 0x18ce, 0x18fc, 0x080c, 0x0d79, - 0xa56c, 0xa470, 0xa774, 0xa678, 0x9d86, 0x002c, 0x0904, 0x17db, - 0xa37c, 0xa280, 0x0458, 0xa584, 0xa488, 0xa78c, 0xa690, 0x9d86, - 0x002c, 0x0904, 0x17db, 0xa394, 0xa298, 0x0400, 0xa59c, 0xa4a0, - 0xa7a4, 0xa6a8, 0x9d86, 0x002c, 0x0904, 0x17db, 0xa3ac, 0xa2b0, - 0x00a8, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0x9d86, 0x002c, 0x0904, - 0x17db, 0xa3c4, 0xa2c8, 0x0050, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, - 0x9d86, 0x002c, 0x0904, 0x17db, 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, 0x17cd, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x0016, 0x00c6, - 0x3e60, 0x6014, 0x2048, 0x2940, 0xa80e, 0x2061, 0x1ed9, 0xa813, - 0x1ed9, 0x2c05, 0xa80a, 0xa964, 0xa91a, 0xa87c, 0xd0ac, 0x090c, - 0x0d79, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0034, 0x1a0c, - 0x0d79, 0xadcc, 0xacd0, 0xafd4, 0xaed8, 0xabdc, 0xaae0, 0xab2e, + 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, 0x0d79, - 0xa80e, 0xa064, 0xa81a, 0x9084, 0x000f, 0x9080, 0x1ede, 0x2015, - 0x82ff, 0x090c, 0x0d79, 0xaa12, 0x2205, 0xa80a, 0x0c08, 0x903e, - 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1ab1, 0x19de, - 0x19de, 0x1ab1, 0x19de, 0x1aab, 0x1ab1, 0x19de, 0x1a4e, 0x1a4e, - 0x1a4e, 0x1ab1, 0x1a4e, 0x1ab1, 0x1aa8, 0x1a4e, 0xc0fc, 0xa882, - 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x1ab3, 0x2c05, - 0x908a, 0x0034, 0x1a0c, 0x0d79, 0x9082, 0x001b, 0x0002, 0x19ca, - 0x19c8, 0x19c8, 0x19c8, 0x19c8, 0x19c8, 0x19ce, 0x19c8, 0x19c8, - 0x19c8, 0x19c8, 0x19c8, 0x19d2, 0x19c8, 0x19c8, 0x19c8, 0x19c8, - 0x19c8, 0x19d6, 0x19c8, 0x19c8, 0x19c8, 0x19c8, 0x19c8, 0x19da, - 0x080c, 0x0d79, 0xa774, 0xa678, 0x0804, 0x1ab3, 0xa78c, 0xa690, - 0x0804, 0x1ab3, 0xa7a4, 0xa6a8, 0x0804, 0x1ab3, 0xa7bc, 0xa6c0, - 0x0804, 0x1ab3, 0xa7d4, 0xa6d8, 0x0804, 0x1ab3, 0xa898, 0x901d, - 0x1108, 0xab9c, 0x9016, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0d79, - 0x9082, 0x001b, 0x0002, 0x1a06, 0x1a06, 0x1a08, 0x1a06, 0x1a06, - 0x1a06, 0x1a12, 0x1a06, 0x1a06, 0x1a06, 0x1a1c, 0x1a06, 0x1a06, - 0x1a06, 0x1a26, 0x1a06, 0x1a06, 0x1a06, 0x1a30, 0x1a06, 0x1a06, - 0x1a06, 0x1a3a, 0x1a06, 0x1a06, 0x1a06, 0x1a44, 0x080c, 0x0d79, - 0xa574, 0xa478, 0x9d86, 0x0004, 0x0904, 0x1ab3, 0xa37c, 0xa280, - 0x0804, 0x1ab3, 0xa584, 0xa488, 0x9d86, 0x0004, 0x0904, 0x1ab3, - 0xa38c, 0xa290, 0x0804, 0x1ab3, 0xa594, 0xa498, 0x9d86, 0x0004, - 0x0904, 0x1ab3, 0xa39c, 0xa2a0, 0x0804, 0x1ab3, 0xa5a4, 0xa4a8, - 0x9d86, 0x0004, 0x0904, 0x1ab3, 0xa3ac, 0xa2b0, 0x0804, 0x1ab3, - 0xa5b4, 0xa4b8, 0x9d86, 0x0004, 0x0904, 0x1ab3, 0xa3bc, 0xa2c0, - 0x0804, 0x1ab3, 0xa5c4, 0xa4c8, 0x9d86, 0x0004, 0x0904, 0x1ab3, - 0xa3cc, 0xa2d0, 0x0804, 0x1ab3, 0xa5d4, 0xa4d8, 0x9d86, 0x0004, - 0x0904, 0x1ab3, 0xa3dc, 0xa2e0, 0x0804, 0x1ab3, 0xa898, 0x901d, - 0x1108, 0xab9c, 0x9016, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0d79, - 0x9082, 0x001b, 0x0002, 0x1a76, 0x1a74, 0x1a74, 0x1a74, 0x1a74, - 0x1a74, 0x1a80, 0x1a74, 0x1a74, 0x1a74, 0x1a74, 0x1a74, 0x1a8a, - 0x1a74, 0x1a74, 0x1a74, 0x1a74, 0x1a74, 0x1a94, 0x1a74, 0x1a74, - 0x1a74, 0x1a74, 0x1a74, 0x1a9e, 0x080c, 0x0d79, 0xa56c, 0xa470, - 0xa774, 0xa678, 0x9d86, 0x000c, 0x05b0, 0xa37c, 0xa280, 0x0498, - 0xa584, 0xa488, 0xa78c, 0xa690, 0x9d86, 0x000c, 0x0560, 0xa394, - 0xa298, 0x0448, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86, 0x000c, - 0x0510, 0xa3ac, 0xa2b0, 0x00f8, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, - 0x9d86, 0x000c, 0x01c0, 0xa3c4, 0xa2c8, 0x00a8, 0xa5cc, 0xa4d0, - 0xa7d4, 0xa6d8, 0x9d86, 0x000c, 0x0170, 0xa3dc, 0xa2e0, 0x0058, - 0x9d86, 0x000e, 0x1130, 0x080c, 0x1eb4, 0x1904, 0x1987, 0x900e, - 0x0050, 0x080c, 0x0d79, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, - 0xae2a, 0x080c, 0x1eb4, 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, 0xafec, 0x0005, 0xa974, 0xd1dc, 0x1108, 0x0005, - 0xa934, 0xa88c, 0x9106, 0x1158, 0xa938, 0xa890, 0x9106, 0x1138, - 0x601c, 0xc084, 0x601e, 0x2009, 0x0048, 0x0804, 0xafec, 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, 0x13c8, 0x8631, 0x1db8, 0x00ce, 0x781f, - 0x0800, 0x2031, 0x0168, 0x00c6, 0x7808, 0xd09c, 0x190c, 0x13c8, - 0x00ce, 0x2001, 0x0038, 0x080c, 0x1bcb, 0x7930, 0x9186, 0x0040, - 0x0160, 0x9186, 0x0042, 0x190c, 0x0d79, 0x2001, 0x001e, 0x8001, - 0x1df0, 0x8631, 0x1d40, 0x080c, 0x1bda, 0x000e, 0x6022, 0x012e, - 0x0005, 0x080c, 0x1bc7, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db8, - 0x782b, 0x0000, 0x0ca0, 0x00f6, 0x2079, 0x0300, 0x7803, 0x0000, - 0x78ab, 0x0004, 0x2001, 0xf000, 0x8001, 0x090c, 0x0d79, 0x7aac, - 0xd2ac, 0x1dd0, 0x00fe, 0x080c, 0x769d, 0x1188, 0x2001, 0x0138, - 0x2003, 0x0000, 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, - 0xa001, 0xa001, 0x8211, 0x1de0, 0x0059, 0x0804, 0x773f, 0x0479, - 0x0039, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, - 0x00e6, 0x2071, 0x0200, 0x080c, 0x2a94, 0x2009, 0x003c, 0x080c, - 0x223d, 0x2001, 0x015d, 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, - 0x1de0, 0x080c, 0x8732, 0x70a0, 0x70a2, 0x7098, 0x709a, 0x709c, - 0x709e, 0x2001, 0x020d, 0x2003, 0x0020, 0x00f6, 0x2079, 0x0300, - 0x080c, 0x135a, 0x7803, 0x0001, 0x00fe, 0x00ee, 0x0005, 0x2001, - 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, - 0x0000, 0x080c, 0x769d, 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, 0x16ad, 0x7930, - 0x0005, 0x2c08, 0x621c, 0x080c, 0x16f6, 0x7930, 0x0005, 0x8001, - 0x1df0, 0x0005, 0x2031, 0x0064, 0x781c, 0x9084, 0x0007, 0x0170, - 0x2001, 0x0038, 0x0c41, 0x9186, 0x0040, 0x0904, 0x1c38, 0x2001, - 0x001e, 0x0c69, 0x8631, 0x1d80, 0x080c, 0x0d79, 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, 0x1bd1, 0x9186, 0x0040, 0x190c, 0x0d79, - 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, 0x0d79, 0xa001, 0xa001, 0x781f, 0x0200, - 0x0005, 0x0126, 0x2091, 0x2400, 0x2079, 0x0380, 0x2001, 0x19e9, - 0x2070, 0x012e, 0x0005, 0x2cf0, 0x0126, 0x2091, 0x2400, 0x3e60, - 0x6014, 0x2048, 0xa964, 0xa91a, 0x918c, 0x00ff, 0x9184, 0x000f, - 0x0002, 0x1c6d, 0x1c6d, 0x1c6d, 0x1c6f, 0x1c6d, 0x1c6d, 0x1c6d, - 0x1c6d, 0x1c61, 0x1c77, 0x1c6d, 0x1c73, 0x1c6d, 0x1c6d, 0x1c6d, - 0x1c6d, 0x9086, 0x0008, 0x1148, 0xa87c, 0xd0b4, 0x0904, 0x1de7, - 0x2011, 0x1ed9, 0x2205, 0xab88, 0x00a8, 0x080c, 0x0d79, 0x9186, - 0x0013, 0x0128, 0x0cd0, 0x9186, 0x001b, 0x0108, 0x0cb0, 0xa87c, - 0xd0b4, 0x0904, 0x1de7, 0x9184, 0x000f, 0x9080, 0x1ede, 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, 0x1ede, 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, 0x1db1, 0xc1dd, 0xa97e, 0x9006, - 0xa842, 0xa83e, 0xa988, 0x8109, 0xa916, 0xa964, 0xa91a, 0x9184, - 0x000f, 0x9088, 0x1ede, 0x2145, 0x0002, 0x1ce5, 0x1cf3, 0x1ce5, - 0x1ce5, 0x1ce5, 0x1ce7, 0x1ce5, 0x1ce5, 0x1d48, 0x1d48, 0x1ce5, - 0x1ce5, 0x1ce5, 0x1d46, 0x1ce5, 0x1ce5, 0x080c, 0x0d79, 0xa804, - 0x2050, 0xb164, 0xa91a, 0x9184, 0x000f, 0x9080, 0x1ede, 0x2045, - 0xd19c, 0x1904, 0x1d48, 0x9036, 0x2638, 0x2805, 0x908a, 0x0036, - 0x1a0c, 0x0d79, 0x9082, 0x001b, 0x0002, 0x1d18, 0x1d18, 0x1d1a, - 0x1d18, 0x1d18, 0x1d18, 0x1d20, 0x1d18, 0x1d18, 0x1d18, 0x1d26, - 0x1d18, 0x1d18, 0x1d18, 0x1d2c, 0x1d18, 0x1d18, 0x1d18, 0x1d32, - 0x1d18, 0x1d18, 0x1d18, 0x1d38, 0x1d18, 0x1d18, 0x1d18, 0x1d3e, - 0x080c, 0x0d79, 0xb574, 0xb478, 0xb37c, 0xb280, 0x0804, 0x1d8d, - 0xb584, 0xb488, 0xb38c, 0xb290, 0x0804, 0x1d8d, 0xb594, 0xb498, - 0xb39c, 0xb2a0, 0x0804, 0x1d8d, 0xb5a4, 0xb4a8, 0xb3ac, 0xb2b0, - 0x0804, 0x1d8d, 0xb5b4, 0xb4b8, 0xb3bc, 0xb2c0, 0x0804, 0x1d8d, - 0xb5c4, 0xb4c8, 0xb3cc, 0xb2d0, 0x0804, 0x1d8d, 0xb5d4, 0xb4d8, - 0xb3dc, 0xb2e0, 0x0804, 0x1d8d, 0x0804, 0x1d8d, 0x080c, 0x0d79, - 0x2805, 0x908a, 0x0034, 0x1a0c, 0x0d79, 0x9082, 0x001b, 0x0002, - 0x1d6b, 0x1d69, 0x1d69, 0x1d69, 0x1d69, 0x1d69, 0x1d72, 0x1d69, - 0x1d69, 0x1d69, 0x1d69, 0x1d69, 0x1d79, 0x1d69, 0x1d69, 0x1d69, - 0x1d69, 0x1d69, 0x1d80, 0x1d69, 0x1d69, 0x1d69, 0x1d69, 0x1d69, - 0x1d87, 0x080c, 0x0d79, 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, 0x0d79, 0x2050, 0xb164, 0xa91a, 0x9184, 0x000f, 0x9080, - 0x1ede, 0x2045, 0x2805, 0x2810, 0x2a08, 0xa80a, 0xa90e, 0xaa12, - 0x0c30, 0x3e60, 0x6344, 0xd3fc, 0x190c, 0x0d79, 0xa93c, 0xaa40, - 0xa844, 0x9106, 0x1118, 0xa848, 0x9206, 0x0508, 0x2958, 0xab48, - 0xac44, 0x2940, 0x080c, 0x1efe, 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, 0x1d9a, 0x2009, - 0x8005, 0x3e60, 0x6044, 0x9105, 0x6046, 0x0804, 0x1d97, 0x080c, - 0x0d79, 0x00f6, 0x00e6, 0x0096, 0x00c6, 0x0026, 0x704c, 0x9c06, - 0x190c, 0x0d79, 0x2079, 0x0090, 0x2001, 0x0105, 0x2003, 0x0010, - 0x782b, 0x0004, 0x7057, 0x0000, 0x6014, 0x2048, 0x080c, 0xcc33, - 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, 0xc81b, 0x080c, 0xaaf7, 0x00ce, 0x704c, 0x9c06, - 0x1150, 0x2009, 0x0040, 0x080c, 0x223d, 0x080c, 0xa59c, 0x2011, - 0x0000, 0x080c, 0xa430, 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, 0x0d79, 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, 0x19e9, 0x7054, 0x9086, 0x0000, - 0x0904, 0x1eaf, 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, 0xd194, - 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, 0x080c, - 0xec09, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0d79, 0x0016, - 0x2009, 0x0040, 0x080c, 0x223d, 0x001e, 0x2001, 0x020c, 0x2102, - 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, - 0x2009, 0x0040, 0x080c, 0x223d, 0x782c, 0xd0fc, 0x09a8, 0x080c, - 0xab13, 0x782c, 0xd0fc, 0x1de8, 0x080c, 0xaaf7, 0x7054, 0x9086, - 0x0000, 0x1950, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, - 0x0040, 0x080c, 0x223d, 0x782b, 0x0002, 0x7057, 0x0000, 0x00ee, - 0x00fe, 0x0005, 0x080c, 0x0d79, 0x8c60, 0x2c05, 0x9005, 0x0110, - 0x8a51, 0x0005, 0xa004, 0x9005, 0x0168, 0xa85a, 0x2040, 0xa064, - 0x9084, 0x000f, 0x9080, 0x1ede, 0x2065, 0x8cff, 0x090c, 0x0d79, - 0x8a51, 0x0005, 0x2050, 0x0005, 0x0000, 0x001d, 0x0021, 0x0025, - 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, 0x0021, 0x0027, - 0x002d, 0x0033, 0x0000, 0x0000, 0x0023, 0x0000, 0x0000, 0x1ed1, - 0x1ecd, 0x1ed1, 0x1ed1, 0x1edb, 0x0000, 0x1ed1, 0x1ed8, 0x1ed8, - 0x1ed5, 0x1ed8, 0x1ed8, 0x0000, 0x1edb, 0x1ed8, 0x0000, 0x1ed3, - 0x1ed3, 0x0000, 0x1ed3, 0x1edb, 0x0000, 0x1ed3, 0x1ed9, 0x1ed9, - 0x1ed9, 0x0000, 0x1ed9, 0x0000, 0x1edb, 0x1ed9, 0x00c6, 0x00d6, - 0x0086, 0xab42, 0xac3e, 0xa888, 0x9055, 0x0904, 0x20dd, 0x2940, - 0xa064, 0x90ec, 0x000f, 0x9084, 0x00ff, 0x9086, 0x0008, 0x1118, - 0x2061, 0x1ed9, 0x00d0, 0x9de0, 0x1ede, 0x9d86, 0x0007, 0x0130, - 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f, 0x1120, 0xa08c, 0x9422, - 0xa090, 0x931b, 0x2c05, 0x9065, 0x1140, 0x0310, 0x0804, 0x20dd, - 0xa004, 0x9045, 0x0904, 0x20dd, 0x08d8, 0x2c05, 0x9005, 0x0904, - 0x1fc5, 0xdd9c, 0x1904, 0x1f81, 0x908a, 0x0036, 0x1a0c, 0x0d79, - 0x9082, 0x001b, 0x0002, 0x1f56, 0x1f56, 0x1f58, 0x1f56, 0x1f56, - 0x1f56, 0x1f5e, 0x1f56, 0x1f56, 0x1f56, 0x1f64, 0x1f56, 0x1f56, - 0x1f56, 0x1f6a, 0x1f56, 0x1f56, 0x1f56, 0x1f70, 0x1f56, 0x1f56, - 0x1f56, 0x1f76, 0x1f56, 0x1f56, 0x1f56, 0x1f7c, 0x080c, 0x0d79, - 0xa07c, 0x9422, 0xa080, 0x931b, 0x0804, 0x1fbb, 0xa08c, 0x9422, - 0xa090, 0x931b, 0x0804, 0x1fbb, 0xa09c, 0x9422, 0xa0a0, 0x931b, - 0x0804, 0x1fbb, 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0804, 0x1fbb, - 0xa0bc, 0x9422, 0xa0c0, 0x931b, 0x0804, 0x1fbb, 0xa0cc, 0x9422, - 0xa0d0, 0x931b, 0x0804, 0x1fbb, 0xa0dc, 0x9422, 0xa0e0, 0x931b, - 0x04d0, 0x908a, 0x0034, 0x1a0c, 0x0d79, 0x9082, 0x001b, 0x0002, - 0x1fa3, 0x1fa1, 0x1fa1, 0x1fa1, 0x1fa1, 0x1fa1, 0x1fa8, 0x1fa1, - 0x1fa1, 0x1fa1, 0x1fa1, 0x1fa1, 0x1fad, 0x1fa1, 0x1fa1, 0x1fa1, - 0x1fa1, 0x1fa1, 0x1fb2, 0x1fa1, 0x1fa1, 0x1fa1, 0x1fa1, 0x1fa1, - 0x1fb7, 0x080c, 0x0d79, 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, 0x20dd, 0x8c60, 0x0804, 0x1f2d, 0xa004, 0x9045, 0x0904, - 0x20dd, 0x0804, 0x1f08, 0x8a51, 0x0904, 0x20dd, 0x8c60, 0x2c05, - 0x9005, 0x1158, 0xa004, 0x9045, 0x0904, 0x20dd, 0xa064, 0x90ec, - 0x000f, 0x9de0, 0x1ede, 0x2c05, 0x2060, 0xa880, 0xc0fc, 0xa882, - 0x0804, 0x20d2, 0x2c05, 0x8422, 0x8420, 0x831a, 0x9399, 0x0000, - 0xac2e, 0xab32, 0xdd9c, 0x1904, 0x206f, 0x9082, 0x001b, 0x0002, - 0x200b, 0x200b, 0x200d, 0x200b, 0x200b, 0x200b, 0x201b, 0x200b, - 0x200b, 0x200b, 0x2029, 0x200b, 0x200b, 0x200b, 0x2037, 0x200b, - 0x200b, 0x200b, 0x2045, 0x200b, 0x200b, 0x200b, 0x2053, 0x200b, - 0x200b, 0x200b, 0x2061, 0x080c, 0x0d79, 0xa17c, 0x2400, 0x9122, - 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0d79, 0xa074, 0x9420, 0xa078, - 0x9319, 0x0804, 0x20cd, 0xa18c, 0x2400, 0x9122, 0xa190, 0x2300, - 0x911b, 0x0a0c, 0x0d79, 0xa084, 0x9420, 0xa088, 0x9319, 0x0804, - 0x20cd, 0xa19c, 0x2400, 0x9122, 0xa1a0, 0x2300, 0x911b, 0x0a0c, - 0x0d79, 0xa094, 0x9420, 0xa098, 0x9319, 0x0804, 0x20cd, 0xa1ac, - 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0d79, 0xa0a4, - 0x9420, 0xa0a8, 0x9319, 0x0804, 0x20cd, 0xa1bc, 0x2400, 0x9122, - 0xa1c0, 0x2300, 0x911b, 0x0a0c, 0x0d79, 0xa0b4, 0x9420, 0xa0b8, - 0x9319, 0x0804, 0x20cd, 0xa1cc, 0x2400, 0x9122, 0xa1d0, 0x2300, - 0x911b, 0x0a0c, 0x0d79, 0xa0c4, 0x9420, 0xa0c8, 0x9319, 0x0804, - 0x20cd, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, 0x0a0c, - 0x0d79, 0xa0d4, 0x9420, 0xa0d8, 0x9319, 0x0804, 0x20cd, 0x9082, - 0x001b, 0x0002, 0x208d, 0x208b, 0x208b, 0x208b, 0x208b, 0x208b, - 0x209a, 0x208b, 0x208b, 0x208b, 0x208b, 0x208b, 0x20a7, 0x208b, - 0x208b, 0x208b, 0x208b, 0x208b, 0x20b4, 0x208b, 0x208b, 0x208b, - 0x208b, 0x208b, 0x20c1, 0x080c, 0x0d79, 0xa17c, 0x2400, 0x9122, - 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0d79, 0xa06c, 0x9420, 0xa070, - 0x9319, 0x0498, 0xa194, 0x2400, 0x9122, 0xa198, 0x2300, 0x911b, - 0x0a0c, 0x0d79, 0xa084, 0x9420, 0xa088, 0x9319, 0x0430, 0xa1ac, - 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0d79, 0xa09c, - 0x9420, 0xa0a0, 0x9319, 0x00c8, 0xa1c4, 0x2400, 0x9122, 0xa1c8, - 0x2300, 0x911b, 0x0a0c, 0x0d79, 0xa0b4, 0x9420, 0xa0b8, 0x9319, - 0x0060, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, 0x0a0c, - 0x0d79, 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, 0x0d72, 0xd094, 0x0110, 0x080c, - 0x11fc, 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, 0x223a, 0x7900, - 0xd1dc, 0x1118, 0x9084, 0x0006, 0x001a, 0x9084, 0x000e, 0x0002, - 0x2158, 0x2150, 0x80a9, 0x2150, 0x2152, 0x2152, 0x2152, 0x2152, - 0x808f, 0x2150, 0x2154, 0x2150, 0x2152, 0x2150, 0x2152, 0x2150, - 0x080c, 0x0d79, 0x0031, 0x0020, 0x080c, 0x808f, 0x080c, 0x80a9, - 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, 0xec09, 0x7930, 0x9184, - 0x0003, 0x0510, 0x080c, 0xaaf7, 0x2001, 0x19fc, 0x2004, 0x9005, - 0x01a0, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0d79, 0x00c6, - 0x2001, 0x19fc, 0x2064, 0x080c, 0xab13, 0x080c, 0xc81b, 0x2009, - 0x0040, 0x080c, 0x223d, 0x00ce, 0x0408, 0x2009, 0x0040, 0x080c, - 0x223d, 0x080c, 0xab13, 0x00d0, 0x9184, 0x0014, 0x01a0, 0x6a00, - 0x9286, 0x0003, 0x0160, 0x080c, 0x769d, 0x1138, 0x080c, 0x799f, - 0x080c, 0x6178, 0x080c, 0x75cc, 0x0010, 0x080c, 0x6033, 0x080c, - 0x8147, 0x0041, 0x0018, 0x9184, 0x9540, 0x1dc8, 0x002e, 0x001e, - 0x000e, 0x0005, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a6f, - 0x080c, 0x1b3b, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x2e00, 0x2071, 0x1800, 0x7128, 0x2001, 0x1970, 0x2102, - 0x2001, 0x1978, 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, 0x0d72, 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, 0x2a8e, 0x080c, 0x29a8, 0x2001, 0x199e, 0x2003, - 0x0700, 0x2001, 0x199f, 0x2003, 0x0700, 0x080c, 0x2aff, 0x9006, - 0x080c, 0x29d7, 0x9006, 0x080c, 0x29ba, 0x20a9, 0x0012, 0x1d04, - 0x226f, 0x2091, 0x6000, 0x1f04, 0x226f, 0x602f, 0x0100, 0x602f, - 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x6224, - 0x080c, 0x2adc, 0x080c, 0x26da, 0x2009, 0x00ef, 0x6132, 0x6136, - 0x080c, 0x26ea, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 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, - 0x22ad, 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, - 0x231b, 0x2318, 0x2318, 0x2318, 0x231a, 0x2318, 0x2318, 0x2318, - 0x080c, 0x0d79, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, - 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, 0x25a0, - 0xd1f4, 0x190c, 0x0d72, 0x080c, 0x769d, 0x0904, 0x2378, 0x080c, - 0xd35d, 0x1120, 0x7000, 0x9086, 0x0003, 0x0580, 0x6024, 0x9084, - 0x1800, 0x0560, 0x080c, 0x76c0, 0x0118, 0x080c, 0x76ae, 0x1530, - 0x2011, 0x0020, 0x080c, 0x2adc, 0x6043, 0x0000, 0x080c, 0xd35d, - 0x0168, 0x080c, 0x76c0, 0x1150, 0x2001, 0x19a9, 0x2003, 0x0001, - 0x6027, 0x1800, 0x080c, 0x7511, 0x0804, 0x25a3, 0x70a4, 0x9005, - 0x1150, 0x70a7, 0x0001, 0x00d6, 0x2069, 0x0140, 0x080c, 0x76f1, - 0x00de, 0x1904, 0x25a3, 0x080c, 0x79a9, 0x0428, 0x080c, 0x76c0, - 0x1590, 0x6024, 0x9084, 0x1800, 0x1108, 0x0468, 0x080c, 0x79a9, - 0x080c, 0x799f, 0x080c, 0x6178, 0x080c, 0x75cc, 0x0804, 0x25a0, - 0xd1ac, 0x1508, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1178, 0xd0d4, - 0x1190, 0xd0cc, 0x0130, 0x7098, 0x9086, 0x0029, 0x1110, 0x080c, - 0x7880, 0x0804, 0x25a0, 0x080c, 0x79a4, 0x0048, 0x2001, 0x197e, - 0x2003, 0x0002, 0x0020, 0x080c, 0x77db, 0x0804, 0x25a0, 0x080c, - 0x7923, 0x0804, 0x25a0, 0x6220, 0xd1bc, 0x0138, 0xd2bc, 0x1904, - 0x260b, 0xd2b4, 0x1904, 0x261d, 0x0000, 0xd1ac, 0x0904, 0x24ad, - 0x0036, 0x6328, 0xc3bc, 0x632a, 0x003e, 0x080c, 0x769d, 0x11d0, - 0x2011, 0x0020, 0x080c, 0x2adc, 0x0006, 0x0026, 0x0036, 0x080c, - 0x76b7, 0x1158, 0x080c, 0x799f, 0x080c, 0x6178, 0x080c, 0x75cc, - 0x003e, 0x002e, 0x000e, 0x00ae, 0x0005, 0x003e, 0x002e, 0x000e, - 0x080c, 0x7671, 0x0016, 0x0046, 0x00c6, 0x644c, 0x9486, 0xf0f0, - 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, - 0x74da, 0x948c, 0xff00, 0x7038, 0xd084, 0x0190, 0x080c, 0xd35d, - 0x1118, 0x9186, 0xf800, 0x1160, 0x7048, 0xd084, 0x1148, 0xc085, - 0x704a, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x4c28, 0x003e, - 0x080c, 0xd356, 0x1904, 0x2482, 0x9196, 0xff00, 0x05a8, 0x7060, - 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110, 0x9116, 0x0568, 0x7130, - 0xd184, 0x1550, 0x080c, 0x3468, 0x0128, 0xc18d, 0x7132, 0x080c, - 0x6bc5, 0x1510, 0x6240, 0x9294, 0x0010, 0x0130, 0x6248, 0x9294, - 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, 0x2482, - 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, - 0x2482, 0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c, - 0x4c28, 0x003e, 0x0804, 0x2482, 0x7038, 0xd08c, 0x1140, 0x2001, - 0x180c, 0x200c, 0xd1ac, 0x1904, 0x2482, 0xc1ad, 0x2102, 0x0036, - 0x73d8, 0x2011, 0x8013, 0x080c, 0x4c28, 0x003e, 0x7130, 0xc185, - 0x7132, 0x2011, 0x1848, 0x220c, 0xd1a4, 0x01f0, 0x0016, 0x2009, - 0x0001, 0x2011, 0x0100, 0x080c, 0x8add, 0x2019, 0x000e, 0x00c6, - 0x2061, 0x0000, 0x080c, 0xe701, 0x00ce, 0x9484, 0x00ff, 0x9080, - 0x3474, 0x200d, 0x918c, 0xff00, 0x810f, 0x2120, 0x9006, 0x2009, - 0x000e, 0x080c, 0xe795, 0x001e, 0x0016, 0x2009, 0x0002, 0x2019, - 0x0004, 0x080c, 0x32c0, 0x001e, 0x00a8, 0x0156, 0x00b6, 0x20a9, - 0x007f, 0x900e, 0x080c, 0x6783, 0x1140, 0x7030, 0xd084, 0x1118, - 0xb800, 0xd0bc, 0x1110, 0x080c, 0x6192, 0x8108, 0x1f04, 0x2472, - 0x00be, 0x015e, 0x00ce, 0x004e, 0x080c, 0xaaf7, 0x080c, 0xadbe, - 0x080c, 0xae87, 0x080c, 0xab13, 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, 0x2adc, 0xd194, 0x0904, 0x25a0, - 0x0016, 0x080c, 0xaaf7, 0x6220, 0xd2b4, 0x0904, 0x253b, 0x080c, - 0x88e4, 0x080c, 0xa09b, 0x2011, 0x0004, 0x080c, 0x2adc, 0x00f6, - 0x2019, 0x19f5, 0x2304, 0x907d, 0x0904, 0x2508, 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, 0x2ab2, 0x2001, 0x001e, 0x8001, 0x0240, 0x20a9, 0x0009, - 0x080c, 0x2a69, 0x6904, 0xd1dc, 0x1140, 0x0cb0, 0x2001, 0x0100, - 0x080c, 0x2aa2, 0x9006, 0x080c, 0x2aa2, 0x080c, 0x97f6, 0x080c, - 0xab13, 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, 0x080c, 0xaf4e, - 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x00ae, 0x0005, - 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, - 0x080c, 0x2ab2, 0x00de, 0x00c6, 0x2061, 0x19e9, 0x6034, 0x080c, - 0xd35d, 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, 0x909a, 0x00c8, - 0x1238, 0x8000, 0x6036, 0x00ce, 0x080c, 0xa073, 0x0804, 0x259d, - 0x2061, 0x0100, 0x62c0, 0x080c, 0xaa28, 0x2019, 0x19f5, 0x2304, - 0x9065, 0x0130, 0x6003, 0x0001, 0x2009, 0x0027, 0x080c, 0xafec, - 0x00ce, 0x0804, 0x259d, 0xd2bc, 0x0904, 0x2580, 0x080c, 0x88f1, - 0x2011, 0x0004, 0x080c, 0x2adc, 0x00d6, 0x2069, 0x0140, 0x6804, - 0x9084, 0x4000, 0x0110, 0x080c, 0x2ab2, 0x00de, 0x00c6, 0x2061, - 0x19e9, 0x6050, 0x080c, 0xd35d, 0x0120, 0x909a, 0x0003, 0x1668, - 0x0018, 0x909a, 0x00c8, 0x1648, 0x8000, 0x6052, 0x604c, 0x00ce, - 0x9005, 0x05d8, 0x2009, 0x07d0, 0x080c, 0x88e9, 0x9080, 0x0008, - 0x2004, 0x9086, 0x0006, 0x1138, 0x2009, 0x1984, 0x2011, 0x0012, - 0x080c, 0x2aeb, 0x0450, 0x9080, 0x0008, 0x2004, 0x9086, 0x0009, - 0x0d98, 0x2009, 0x1984, 0x2011, 0x0016, 0x080c, 0x2aeb, 0x00e8, - 0x2011, 0x0004, 0x080c, 0x2adc, 0x00c0, 0x0036, 0x2019, 0x0001, - 0x080c, 0xa391, 0x003e, 0x2019, 0x19fc, 0x2304, 0x9065, 0x0160, - 0x2009, 0x004f, 0x6020, 0x9086, 0x0009, 0x1110, 0x2009, 0x004f, - 0x6003, 0x0003, 0x080c, 0xafec, 0x00ce, 0x080c, 0xab13, 0x001e, - 0xd19c, 0x0904, 0x2604, 0x7038, 0xd0ac, 0x1558, 0x0016, 0x0156, - 0x2011, 0x0008, 0x080c, 0x2adc, 0x080c, 0x2aff, 0x080c, 0x2b32, - 0x6050, 0xc0e5, 0x6052, 0x20a9, 0x0367, 0x0f04, 0x25cf, 0x1d04, - 0x25b7, 0x080c, 0x8918, 0x6020, 0xd09c, 0x1db8, 0x00f6, 0x2079, - 0x0100, 0x080c, 0x2a19, 0x00fe, 0x1d80, 0x6050, 0xc0e4, 0x6052, - 0x2011, 0x0008, 0x080c, 0x2adc, 0x015e, 0x001e, 0x04a8, 0x015e, - 0x001e, 0x0016, 0x6028, 0xc09c, 0x602a, 0x080c, 0xaaf7, 0x080c, - 0xadbe, 0x080c, 0xae87, 0x080c, 0xab13, 0x60e3, 0x0000, 0x080c, - 0xebe8, 0x080c, 0xec03, 0x080c, 0x5824, 0xd0fc, 0x1138, 0x080c, - 0xd356, 0x1120, 0x9085, 0x0001, 0x080c, 0x76e1, 0x9006, 0x080c, - 0x2aa2, 0x2009, 0x0002, 0x080c, 0x2a8e, 0x00e6, 0x2071, 0x1800, - 0x7003, 0x0004, 0x080c, 0x0ec7, 0x00ee, 0x2011, 0x0008, 0x080c, - 0x2adc, 0x080c, 0x0bc3, 0x001e, 0x918c, 0xffd0, 0x2110, 0x080c, - 0x2adc, 0x00ae, 0x0005, 0x0016, 0x2001, 0x0387, 0x200c, 0xd1a4, - 0x001e, 0x0904, 0x23a5, 0x0016, 0x2009, 0x2617, 0x00c0, 0x2001, - 0x0387, 0x2003, 0x1000, 0x001e, 0x0c38, 0x0016, 0x2001, 0x0387, - 0x200c, 0xd1b4, 0x001e, 0x0904, 0x23a5, 0x0016, 0x2009, 0x2629, - 0x0030, 0x2001, 0x0387, 0x2003, 0x4000, 0x001e, 0x08a8, 0x6028, - 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, 0xbc91, 0x8000, 0x2003, - 0xffff, 0x6043, 0x0001, 0x080c, 0x2a88, 0x2011, 0x0080, 0x080c, - 0x2adc, 0x6017, 0x0000, 0x6043, 0x0000, 0x0817, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1800, 0x71d0, 0x70d2, 0x9116, 0x0904, 0x2699, 0x81ff, 0x01a0, - 0x2009, 0x0000, 0x080c, 0x2a8e, 0x2011, 0x8011, 0x2019, 0x010e, - 0x231c, 0x939e, 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, - 0x0000, 0x080c, 0x4c28, 0x0468, 0x2001, 0x19aa, 0x200c, 0x81ff, - 0x1140, 0x2001, 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, - 0x0008, 0x2118, 0x2011, 0x8012, 0x080c, 0x4c28, 0x080c, 0x0ec7, - 0x080c, 0x5824, 0xd0fc, 0x11a8, 0x080c, 0xd356, 0x1190, 0x00c6, - 0x080c, 0x2735, 0x080c, 0xaaf7, 0x080c, 0xa2ec, 0x080c, 0xab13, - 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0002, 0x080c, 0x32c0, - 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, - 0x83ba, 0x0048, 0x9584, 0x00ff, 0x9080, 0x3474, 0x200d, 0x918c, - 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, 0x3474, 0x200d, 0x918c, - 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, 0x1818, 0x2003, - 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856, 0x1f04, 0x26e5, - 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, - 0x1818, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, - 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184, 0x000f, 0x9080, - 0xec17, 0x2005, 0x6856, 0x8211, 0x1f04, 0x26fa, 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, 0x272a, 0x680f, 0x0000, 0x000e, - 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x080c, 0x5820, 0xd0c4, - 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, 0x002e, - 0x080c, 0xe795, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, - 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x27a1, 0x080c, 0x2a09, 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, 0x9364, 0x928c, 0xff00, 0x0110, 0x2011, 0x00ff, 0x2200, - 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, 0x220a, 0x080c, - 0x769d, 0x1118, 0x2009, 0x196e, 0x220a, 0x002e, 0x001e, 0x00fe, - 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, - 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0x9184, - 0x0003, 0x0110, 0x080c, 0x0d72, 0x002e, 0x001e, 0x000e, 0x012e, - 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, 0x1991, 0x2004, 0x908a, 0x0007, 0x1a0c, - 0x0d79, 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, 0x015e, 0x0005, - 0x27ff, 0x281d, 0x2841, 0x2843, 0x286c, 0x286e, 0x2870, 0x2001, - 0x0001, 0x080c, 0x2646, 0x080c, 0x2a53, 0x2001, 0x1993, 0x2003, - 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, 0x20a9, 0x0009, - 0x080c, 0x2a25, 0x2001, 0x1991, 0x2003, 0x0006, 0x2009, 0x001e, - 0x2011, 0x2871, 0x080c, 0x88f6, 0x0005, 0x2009, 0x1996, 0x200b, - 0x0000, 0x2001, 0x199b, 0x2003, 0x0036, 0x2001, 0x199a, 0x2003, - 0x002a, 0x2001, 0x1993, 0x2003, 0x0001, 0x9006, 0x080c, 0x29ba, - 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x2a25, 0x2001, 0x1991, - 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2871, 0x080c, 0x88f6, - 0x0005, 0x080c, 0x0d79, 0x2001, 0x199b, 0x2003, 0x0036, 0x2001, - 0x1993, 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, - 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29ba, 0x2001, - 0x1997, 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, - 0x2a25, 0x2001, 0x1991, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, - 0x2871, 0x080c, 0x88f6, 0x0005, 0x080c, 0x0d79, 0x080c, 0x0d79, - 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0156, 0x0126, - 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, 0x1993, 0x2004, 0x908a, - 0x0007, 0x1a0c, 0x0d79, 0x0043, 0x012e, 0x015e, 0x00fe, 0x00ee, - 0x002e, 0x001e, 0x000e, 0x0005, 0x2893, 0x28af, 0x28eb, 0x2917, - 0x2937, 0x2943, 0x2945, 0x080c, 0x2a19, 0x1190, 0x2009, 0x1999, - 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, 0xc08d, - 0x0008, 0xc085, 0x200a, 0x2001, 0x1991, 0x2003, 0x0001, 0x0030, - 0x080c, 0x2969, 0x2001, 0xffff, 0x080c, 0x280e, 0x0005, 0x080c, - 0x2947, 0x05c0, 0x2009, 0x199a, 0x2104, 0x8001, 0x200a, 0x080c, - 0x2a19, 0x1158, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0518, - 0x2009, 0x1999, 0x2104, 0xc085, 0x200a, 0x2009, 0x1996, 0x2104, - 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, 0x294f, 0x00c0, - 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0004, 0x0110, - 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29d7, 0x2001, 0x1993, - 0x2003, 0x0002, 0x0028, 0x2001, 0x1991, 0x2003, 0x0003, 0x0010, - 0x080c, 0x2830, 0x0005, 0x080c, 0x2947, 0x0540, 0x2009, 0x199a, - 0x2104, 0x8001, 0x200a, 0x080c, 0x2a19, 0x1148, 0x2001, 0x1991, - 0x2003, 0x0003, 0x2001, 0x1992, 0x2003, 0x0000, 0x00b8, 0x2009, - 0x199a, 0x2104, 0x9005, 0x1118, 0x080c, 0x298c, 0x0010, 0x080c, - 0x295c, 0x080c, 0x294f, 0x2009, 0x1996, 0x200b, 0x0000, 0x2001, - 0x1993, 0x2003, 0x0001, 0x080c, 0x2830, 0x0000, 0x0005, 0x0479, - 0x01e8, 0x080c, 0x2a19, 0x1198, 0x2009, 0x1997, 0x2104, 0x8000, - 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, 0x199c, 0x2003, - 0x000a, 0x2009, 0x1999, 0x2104, 0xc0fd, 0x200a, 0x0038, 0x00f9, - 0x2001, 0x1993, 0x2003, 0x0004, 0x080c, 0x285b, 0x0005, 0x0079, - 0x0148, 0x080c, 0x2a19, 0x1118, 0x080c, 0x2847, 0x0018, 0x0079, - 0x080c, 0x285b, 0x0005, 0x080c, 0x0d79, 0x080c, 0x0d79, 0x2009, - 0x199b, 0x2104, 0x8001, 0x200a, 0x090c, 0x29a8, 0x0005, 0x7a38, - 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x29d7, 0x0005, 0x7a38, 0x9294, 0x0006, 0x9296, - 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29ba, - 0x0005, 0x2009, 0x1996, 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, 0x29d7, 0x0005, 0x0086, 0x2001, 0x1999, 0x2004, - 0x9084, 0x7fff, 0x090c, 0x0d79, 0x2009, 0x1998, 0x2144, 0x8846, - 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, 0xd084, 0x1120, 0x080c, - 0x0d79, 0x9006, 0x0010, 0x2001, 0x0001, 0x00a1, 0x008e, 0x0005, - 0x0006, 0x0156, 0x2001, 0x1991, 0x20a9, 0x0009, 0x2003, 0x0000, - 0x8000, 0x1f04, 0x29ae, 0x2001, 0x1998, 0x2003, 0x8000, 0x015e, - 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, - 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, 0x783a, 0x2009, 0x199e, - 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0006, - 0x783a, 0x2009, 0x199f, 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, 0x2a88, 0xd09c, - 0x1110, 0x1f04, 0x2a1c, 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, 0x2a45, 0x080c, - 0x8918, 0x1f04, 0x2a45, 0x7850, 0x9085, 0x1000, 0x7852, 0x000e, - 0x001e, 0x012e, 0x0005, 0x080c, 0x2b32, 0x0005, 0x0006, 0x0156, - 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, 0x1100, - 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2a60, 0x00fe, 0x015e, 0x000e, - 0x0005, 0x1d04, 0x2a69, 0x080c, 0x8918, 0x1f04, 0x2a69, 0x0005, - 0x0006, 0x2001, 0x199d, 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, - 0x0006, 0x2001, 0x199d, 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, - 0x0006, 0x2001, 0x199d, 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, - 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006, 0x2001, - 0x19aa, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, - 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xa001, 0xa001, - 0x200a, 0x0005, 0x0016, 0x0026, 0x080c, 0x76b7, 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, 0x76b7, 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, 0x2a69, 0x6050, - 0x9085, 0x0400, 0x9084, 0xff9f, 0x6052, 0x20a9, 0x0005, 0x080c, - 0x2a69, 0x6054, 0xd0bc, 0x090c, 0x0d79, 0x20a9, 0x0005, 0x080c, - 0x2a69, 0x6054, 0xd0ac, 0x090c, 0x0d79, 0x2009, 0x19b1, 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, 0x0d79, 0x2001, - 0x0338, 0x2004, 0xd084, 0x1dc0, 0x6028, 0x0006, 0x60e0, 0x0006, - 0x6888, 0x0006, 0x688c, 0x0006, 0x6890, 0x0006, 0x080c, 0x769d, - 0x1110, 0x6884, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xa001, - 0xa001, 0xa001, 0xa001, 0x602f, 0x0040, 0x602f, 0x0000, 0x080c, - 0x769d, 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, 0x26ea, 0x000e, 0x00de, - 0x00ce, 0x001e, 0x0005, 0x0006, 0x0156, 0x6050, 0x9085, 0x0040, - 0x6052, 0x6050, 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2a88, 0x9085, - 0x2000, 0x6052, 0x20a9, 0x0012, 0x1d04, 0x2bbc, 0x080c, 0x8918, - 0x1f04, 0x2bbc, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, - 0x015e, 0x000e, 0x0005, 0x30c7, 0x30c7, 0x2ccb, 0x2ccb, 0x2cd7, - 0x2cd7, 0x2ce3, 0x2ce3, 0x2cf1, 0x2cf1, 0x2cfd, 0x2cfd, 0x2d0b, - 0x2d0b, 0x2d19, 0x2d19, 0x2d2b, 0x2d2b, 0x2d37, 0x2d37, 0x2d45, - 0x2d45, 0x2d63, 0x2d63, 0x2d83, 0x2d83, 0x2d53, 0x2d53, 0x2d73, - 0x2d73, 0x2d91, 0x2d91, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2da3, 0x2da3, 0x2daf, 0x2daf, 0x2dbd, - 0x2dbd, 0x2dcb, 0x2dcb, 0x2ddb, 0x2ddb, 0x2de9, 0x2de9, 0x2df9, - 0x2df9, 0x2e09, 0x2e09, 0x2e1b, 0x2e1b, 0x2e29, 0x2e29, 0x2e39, - 0x2e39, 0x2e5b, 0x2e5b, 0x2e7f, 0x2e7f, 0x2e49, 0x2e49, 0x2e6d, - 0x2e6d, 0x2e8f, 0x2e8f, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2ea3, 0x2ea3, 0x2eaf, 0x2eaf, 0x2ebd, - 0x2ebd, 0x2ecb, 0x2ecb, 0x2edb, 0x2edb, 0x2ee9, 0x2ee9, 0x2ef9, - 0x2ef9, 0x2f09, 0x2f09, 0x2f1b, 0x2f1b, 0x2f29, 0x2f29, 0x2f39, - 0x2f39, 0x2f49, 0x2f49, 0x2f5b, 0x2f5b, 0x2f6b, 0x2f6b, 0x2f7d, - 0x2f7d, 0x2f8f, 0x2f8f, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2fa3, 0x2fa3, 0x2fb1, 0x2fb1, 0x2fc1, - 0x2fc1, 0x2fd1, 0x2fd1, 0x2fe3, 0x2fe3, 0x2ff3, 0x2ff3, 0x3005, - 0x3005, 0x3017, 0x3017, 0x302b, 0x302b, 0x303b, 0x303b, 0x304d, - 0x304d, 0x305f, 0x305f, 0x3073, 0x3073, 0x3084, 0x3084, 0x3097, - 0x3097, 0x30aa, 0x30aa, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, 0x2d29, - 0x2d29, 0x2d29, 0x2d29, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x22dd, 0x0804, 0x30bf, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2107, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2107, 0x080c, 0x22dd, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22dd, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2107, 0x080c, 0x2131, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2107, 0x080c, 0x22dd, 0x080c, 0x2131, 0x0804, - 0x30bf, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x13c8, 0x0804, 0x30bf, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x22dd, 0x080c, 0x13c8, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2107, 0x080c, - 0x13c8, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x22dd, 0x080c, 0x13c8, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2107, 0x080c, 0x22dd, 0x080c, - 0x13c8, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2107, 0x080c, 0x13c8, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x13c8, 0x080c, 0x2131, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2107, 0x080c, 0x22dd, 0x080c, 0x13c8, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x0804, 0x30bf, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x27a4, 0x080c, 0x22dd, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, - 0x2107, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0x2107, 0x080c, - 0x22dd, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0x2131, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x27a4, 0x080c, 0x22dd, 0x080c, 0x2131, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x27a4, 0x080c, 0x2107, 0x080c, 0x2131, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x27a4, 0x080c, 0x2107, 0x080c, 0x22dd, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0x13c8, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x27a4, 0x080c, 0x22dd, 0x080c, 0x13c8, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x27a4, 0x080c, 0x2107, 0x080c, 0x13c8, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x27a4, 0x080c, 0x22dd, 0x080c, 0x13c8, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0x2107, 0x080c, - 0x22dd, 0x080c, 0x13c8, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, - 0x2107, 0x080c, 0x13c8, 0x080c, 0x2131, 0x0804, 0x30bf, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x27a4, 0x080c, 0x13c8, 0x080c, 0x2131, 0x0804, 0x30bf, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x27a4, 0x080c, 0x2107, 0x080c, 0x22dd, 0x080c, 0x13c8, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0xab5d, 0x0804, 0x30bf, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0xab5d, 0x080c, 0x22dd, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2107, 0x080c, - 0xab5d, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2107, 0x080c, 0xab5d, 0x080c, - 0x22dd, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0xab5d, 0x080c, 0x2131, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0xab5d, 0x080c, 0x22dd, 0x080c, 0x2131, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2107, 0x080c, 0xab5d, 0x080c, 0x2131, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2107, 0x080c, 0xab5d, 0x080c, 0x22dd, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0xab5d, 0x080c, 0x13c8, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0xab5d, 0x080c, 0x22dd, 0x080c, 0x13c8, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2107, 0x080c, 0xab5d, 0x080c, 0x13c8, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2107, 0x080c, 0xab5d, 0x080c, 0x22dd, 0x080c, - 0x13c8, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0xab5d, 0x080c, 0x13c8, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0xab5d, 0x080c, 0x22dd, 0x080c, - 0x13c8, 0x080c, 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2107, 0x080c, - 0xab5d, 0x080c, 0x13c8, 0x080c, 0x2131, 0x0804, 0x30bf, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2107, 0x080c, 0xab5d, 0x080c, 0x22dd, 0x080c, 0x13c8, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0xab5d, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x27a4, 0x080c, 0xab5d, 0x080c, 0x22dd, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x27a4, 0x080c, 0x2107, 0x080c, 0xab5d, 0x0804, - 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x27a4, 0x080c, 0x2107, 0x080c, 0xab5d, 0x080c, - 0x22dd, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0xab5d, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0xab5d, 0x080c, - 0x22dd, 0x080c, 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, - 0x2107, 0x080c, 0xab5d, 0x080c, 0x2131, 0x0804, 0x30bf, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x27a4, 0x080c, 0x2107, 0x080c, 0xab5d, 0x080c, 0x22dd, 0x080c, - 0x2131, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0xab5d, 0x080c, - 0x13c8, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0xab5d, 0x080c, - 0x22dd, 0x080c, 0x13c8, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, - 0x2107, 0x080c, 0xab5d, 0x080c, 0x13c8, 0x0804, 0x30bf, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x27a4, 0x080c, 0x2107, 0x080c, 0xab5d, 0x080c, 0x22dd, 0x080c, - 0x13c8, 0x0804, 0x30bf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0xab5d, 0x080c, - 0x13c8, 0x080c, 0x2131, 0x04d8, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0xab5d, - 0x080c, 0x22dd, 0x080c, 0x13c8, 0x080c, 0x2131, 0x0440, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x27a4, 0x080c, 0x2107, 0x080c, 0x13c8, 0x080c, 0xab5d, 0x080c, - 0x2131, 0x00a8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x27a4, 0x080c, 0x2107, 0x080c, 0xab5d, - 0x080c, 0x22dd, 0x080c, 0x13c8, 0x080c, 0x2131, 0x0000, 0x015e, - 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, - 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6b8b, 0x1904, - 0x31dc, 0x72dc, 0x2001, 0x197d, 0x2004, 0x9005, 0x1110, 0xd29c, - 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x31dc, 0x080c, 0x31e1, - 0x0804, 0x31dc, 0xd2cc, 0x1904, 0x31dc, 0x080c, 0x769d, 0x1120, - 0x70af, 0xffff, 0x0804, 0x31dc, 0xd294, 0x0120, 0x70af, 0xffff, - 0x0804, 0x31dc, 0x080c, 0x3463, 0x0160, 0x080c, 0xd35d, 0x0128, - 0x2001, 0x1818, 0x203c, 0x0804, 0x3165, 0x70af, 0xffff, 0x0804, - 0x31dc, 0x2001, 0x1818, 0x203c, 0x7294, 0xd284, 0x0904, 0x3165, - 0xd28c, 0x1904, 0x3165, 0x0036, 0x73ac, 0x938e, 0xffff, 0x1110, - 0x2019, 0x0001, 0x8314, 0x92e0, 0x1d80, 0x2c04, 0x938c, 0x0001, - 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, - 0x05d0, 0x908e, 0x0000, 0x05b8, 0x908e, 0x00ff, 0x1150, 0x7230, - 0xd284, 0x15b0, 0x7294, 0xc28d, 0x7296, 0x70af, 0xffff, 0x003e, - 0x04a0, 0x900e, 0x080c, 0x26a1, 0x080c, 0x6718, 0x1538, 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, - 0x8d87, 0x00ce, 0x090c, 0x9128, 0xb8af, 0x0000, 0x080c, 0x6bcd, - 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, 0xd0bc, 0x0138, 0x080c, - 0x6a74, 0x0120, 0x080c, 0x31fa, 0x0148, 0x0028, 0x080c, 0x3346, - 0x080c, 0x3226, 0x0118, 0x8318, 0x0804, 0x3112, 0x73ae, 0x0010, - 0x70af, 0xffff, 0x003e, 0x0804, 0x31dc, 0x9780, 0x3474, 0x203d, - 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x70ac, 0x9096, 0xffff, - 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, 0x0220, 0x2008, 0x9802, - 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804, 0x31dc, 0x2700, 0x0156, - 0x0016, 0x9106, 0x0904, 0x31d1, 0xc484, 0x080c, 0x6783, 0x0168, - 0x080c, 0xd35d, 0x1904, 0x31d1, 0x080c, 0x3463, 0x1904, 0x31d1, - 0x080c, 0x6718, 0x1904, 0x31d9, 0x0008, 0xc485, 0xb8bb, 0x0520, - 0xb8ac, 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c, 0x8d87, 0x00ce, - 0x090c, 0x9128, 0xb8af, 0x0000, 0x080c, 0x6bcd, 0x1130, 0x7030, - 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0, 0x7294, 0xd28c, 0x0180, - 0x080c, 0x6bcd, 0x9082, 0x0006, 0x02e0, 0xd484, 0x1118, 0x080c, - 0x673d, 0x0028, 0x080c, 0x33d9, 0x01a0, 0x080c, 0x3404, 0x0088, - 0x080c, 0x3346, 0x080c, 0xd35d, 0x1160, 0x080c, 0x3226, 0x0188, - 0x0040, 0x080c, 0xd35d, 0x1118, 0x080c, 0x33d9, 0x0110, 0x0451, - 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x317e, 0x70af, 0xffff, - 0x0018, 0x001e, 0x015e, 0x71ae, 0x004e, 0x002e, 0x00ce, 0x00be, - 0x0005, 0x00c6, 0x0016, 0x70af, 0x0001, 0x2009, 0x007e, 0x080c, - 0x6718, 0x1168, 0xb813, 0x00ff, 0xb817, 0xfffe, 0x080c, 0x3346, - 0x04a9, 0x0128, 0x70dc, 0xc0bd, 0x70de, 0x080c, 0xd0a1, 0x001e, - 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, - 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, 0xafbf, 0x01d0, 0x2b00, - 0x6012, 0x080c, 0xd0ce, 0x6023, 0x0001, 0x9006, 0x080c, 0x66b5, - 0x2001, 0x0000, 0x080c, 0x66c9, 0x0126, 0x2091, 0x8000, 0x70a8, - 0x8000, 0x70aa, 0x012e, 0x2009, 0x0004, 0x080c, 0xafec, 0x9085, - 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, 0x0076, - 0x00d6, 0x00c6, 0x2001, 0x184c, 0x2004, 0x9084, 0x00ff, 0xb842, - 0x080c, 0xafbf, 0x0548, 0x2b00, 0x6012, 0xb800, 0xc0c4, 0xb802, - 0xb8a0, 0x9086, 0x007e, 0x0140, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x1110, 0x080c, 0x32fb, 0x080c, 0xd0ce, 0x6023, 0x0001, - 0x9006, 0x080c, 0x66b5, 0x2001, 0x0002, 0x080c, 0x66c9, 0x0126, - 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, 0x0002, - 0x080c, 0xafec, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, - 0x0005, 0x00b6, 0x00c6, 0x0026, 0x2009, 0x0080, 0x080c, 0x6718, - 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, 0x0039, 0x0110, 0x70e3, - 0xffff, 0x002e, 0x00ce, 0x00be, 0x0005, 0x0016, 0x0076, 0x00d6, - 0x00c6, 0x080c, 0xaef8, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xd0ce, - 0x6023, 0x0001, 0x9006, 0x080c, 0x66b5, 0x2001, 0x0002, 0x080c, - 0x66c9, 0x0126, 0x2091, 0x8000, 0x70e4, 0x8000, 0x70e6, 0x012e, - 0x2009, 0x0002, 0x080c, 0xafec, 0x9085, 0x0001, 0x00ce, 0x00de, - 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, 0x8000, - 0x2009, 0x007f, 0x080c, 0x6718, 0x11b8, 0xb813, 0x00ff, 0xb817, - 0xfffd, 0xb8d7, 0x0004, 0x080c, 0xaef8, 0x0170, 0x2b00, 0x6012, - 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, 0xd0ce, 0x2009, 0x0022, - 0x080c, 0xafec, 0x9085, 0x0001, 0x012e, 0x00de, 0x00ce, 0x0005, - 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x00b6, 0x21f0, 0x080c, - 0xaaf7, 0x0106, 0x080c, 0x95c4, 0x080c, 0x9530, 0x080c, 0xaa48, - 0x080c, 0xbeab, 0x010e, 0x090c, 0xab13, 0x3e08, 0x2130, 0x81ff, - 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, 0x20a9, 0x007f, 0x900e, - 0x0016, 0x080c, 0x6783, 0x1140, 0x9686, 0x0002, 0x1118, 0xb800, - 0xd0bc, 0x1110, 0x080c, 0x6192, 0x001e, 0x8108, 0x1f04, 0x32e0, - 0x9686, 0x0001, 0x190c, 0x3437, 0x00be, 0x002e, 0x003e, 0x006e, - 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0046, 0x0036, 0x0026, - 0x0016, 0x00b6, 0x080c, 0xaaf7, 0x0106, 0x6210, 0x2258, 0xbaa0, - 0x0026, 0x2019, 0x0029, 0x080c, 0x95b9, 0x0076, 0x2039, 0x0000, - 0x080c, 0x9476, 0x2c08, 0x080c, 0xe465, 0x007e, 0x001e, 0x010e, - 0x090c, 0xab13, 0xba10, 0xbb14, 0xbc84, 0x080c, 0x6192, 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, 0xaaf7, 0x0106, 0x81ff, - 0x1118, 0x20a9, 0x0001, 0x0078, 0x080c, 0x5820, 0xd0c4, 0x0140, - 0xd0a4, 0x0130, 0x9006, 0x2020, 0x2009, 0x002d, 0x080c, 0xe795, - 0x20a9, 0x0800, 0x9016, 0x0026, 0x928e, 0x007e, 0x0904, 0x33b5, - 0x928e, 0x007f, 0x0904, 0x33b5, 0x928e, 0x0080, 0x05f0, 0x9288, - 0x1000, 0x210c, 0x81ff, 0x05c8, 0x8fff, 0x1150, 0x2001, 0x198f, - 0x0006, 0x2003, 0x0001, 0x080c, 0x33c6, 0x000e, 0x2003, 0x0000, - 0x00b6, 0x00c6, 0x2158, 0x2001, 0x0001, 0x080c, 0x6b97, 0x00ce, - 0x00be, 0x2019, 0x0029, 0x080c, 0x95b9, 0x0076, 0x2039, 0x0000, - 0x080c, 0x9476, 0x00b6, 0x00c6, 0x0026, 0x2158, 0xba04, 0x9294, - 0x00ff, 0x9286, 0x0006, 0x1118, 0xb807, 0x0404, 0x0028, 0x2001, - 0x0004, 0x8007, 0x9215, 0xba06, 0x002e, 0x00ce, 0x00be, 0x0016, - 0x2c08, 0x080c, 0xe465, 0x001e, 0x007e, 0x002e, 0x8210, 0x1f04, - 0x336b, 0x010e, 0x090c, 0xab13, 0x015e, 0x001e, 0x002e, 0x003e, - 0x004e, 0x00be, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, - 0x0016, 0x080c, 0x5820, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, - 0x2220, 0x2009, 0x0029, 0x080c, 0xe795, 0x001e, 0x002e, 0x004e, - 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x7294, 0x82ff, 0x01e8, - 0x080c, 0x6bc5, 0x11d0, 0x2100, 0x080c, 0x26d4, 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, 0xaaf7, 0x0106, 0x0036, 0x2019, 0x0029, 0x00c1, - 0x003e, 0x010e, 0x090c, 0xab13, 0x9180, 0x1000, 0x2004, 0x9065, - 0x0158, 0x0016, 0x00c6, 0x2061, 0x1b3a, 0x001e, 0x6112, 0x080c, - 0x32fb, 0x001e, 0x080c, 0x673d, 0x012e, 0x00ce, 0x001e, 0x0005, - 0x0016, 0x0026, 0x2110, 0x080c, 0xa5dd, 0x080c, 0xeafd, 0x002e, - 0x001e, 0x0005, 0x2001, 0x1837, 0x2004, 0xd0cc, 0x0005, 0x00c6, - 0x00b6, 0x080c, 0x769d, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, - 0x0782, 0x080c, 0x769d, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, - 0x9180, 0x1000, 0x2004, 0x905d, 0x0130, 0x86ff, 0x0110, 0xb800, - 0xd0bc, 0x090c, 0x673d, 0x8108, 0x1f04, 0x3448, 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, + 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, 0x2071, 0x189e, 0x7003, 0x0002, - 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, 0x700e, 0x7042, 0x7046, - 0x703b, 0x18ba, 0x703f, 0x18ba, 0x7007, 0x0001, 0x080c, 0x1066, - 0x090c, 0x0d79, 0x2900, 0x706a, 0xa867, 0x0002, 0xa8ab, 0xdcb0, - 0x080c, 0x1066, 0x090c, 0x0d79, 0x2900, 0x706e, 0xa867, 0x0002, - 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x189e, 0x7004, 0x0002, 0x35a3, - 0x35a4, 0x35b7, 0x35cb, 0x0005, 0x1004, 0x35b4, 0x0e04, 0x35b4, - 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, 0x369f, 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, 0x369c, 0x61d0, 0x0804, - 0x3631, 0x3673, 0x36ab, 0x369c, 0x36b7, 0x36c1, 0x36c7, 0x36cb, - 0x36db, 0x36df, 0x36f5, 0x36fb, 0x3701, 0x370c, 0x3717, 0x3726, - 0x3735, 0x3743, 0x375a, 0x3775, 0x369c, 0x381e, 0x385c, 0x3901, - 0x3912, 0x3935, 0x369c, 0x369c, 0x369c, 0x396d, 0x398d, 0x3996, - 0x39c2, 0x39c8, 0x369c, 0x3a0e, 0x369c, 0x369c, 0x369c, 0x369c, - 0x369c, 0x3a19, 0x3a22, 0x3a2a, 0x3a2c, 0x369c, 0x369c, 0x369c, - 0x369c, 0x369c, 0x369c, 0x3a5c, 0x369c, 0x369c, 0x369c, 0x369c, - 0x369c, 0x3a79, 0x3add, 0x369c, 0x369c, 0x369c, 0x369c, 0x369c, - 0x369c, 0x0002, 0x3b07, 0x3b0a, 0x3b69, 0x3b82, 0x3bb2, 0x3e58, - 0x369c, 0x53d5, 0x369c, 0x369c, 0x369c, 0x369c, 0x369c, 0x369c, - 0x369c, 0x369c, 0x36f5, 0x36fb, 0x435b, 0x5844, 0x4379, 0x5464, - 0x54b6, 0x55c1, 0x369c, 0x5623, 0x565f, 0x5690, 0x57a0, 0x56bd, - 0x5720, 0x369c, 0x437d, 0x4536, 0x454c, 0x4571, 0x45d6, 0x464a, - 0x466a, 0x46e1, 0x473d, 0x4799, 0x479c, 0x47c1, 0x4833, 0x489d, - 0x48a5, 0x49da, 0x4b52, 0x4b86, 0x4dea, 0x369c, 0x4e08, 0x4eae, - 0x4f97, 0x4ff1, 0x369c, 0x50a8, 0x369c, 0x5114, 0x512f, 0x48a5, - 0x5375, 0x714c, 0x0000, 0x2021, 0x4000, 0x080c, 0x4c04, 0x0126, - 0x2091, 0x8000, 0x0e04, 0x367d, 0x0010, 0x012e, 0x0cc0, 0x7c36, - 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, - 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x11f4, 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, 0x4c11, 0x2039, - 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, - 0x4c14, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, 0x3673, 0x7984, - 0x2114, 0x0804, 0x3673, 0x20e1, 0x0000, 0x2099, 0x0021, 0x20e9, - 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, 0x7984, 0x7a88, - 0x7b8c, 0x0804, 0x3673, 0x7884, 0x2060, 0x0804, 0x3728, 0x2009, - 0x0003, 0x2011, 0x0003, 0x2019, 0x0012, 0x789b, 0x0137, 0x7893, - 0xffff, 0x2001, 0x188f, 0x2004, 0x9005, 0x0118, 0x7896, 0x0804, - 0x3673, 0x7897, 0x0001, 0x0804, 0x3673, 0x2039, 0x0001, 0x7d98, - 0x7c9c, 0x0804, 0x36af, 0x2039, 0x0001, 0x7d98, 0x7c9c, 0x0804, - 0x36bb, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x36a8, 0x2138, - 0x7d98, 0x7c9c, 0x0804, 0x36af, 0x79a0, 0x9182, 0x0040, 0x0210, - 0x0804, 0x36a8, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x36bb, 0x79a0, - 0x9182, 0x0040, 0x0210, 0x0804, 0x36a8, 0x21e8, 0x7984, 0x7888, - 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x3673, 0x2061, 0x0800, - 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, 0x1dd8, 0x2010, - 0x9005, 0x0904, 0x3673, 0x0804, 0x36a2, 0x79a0, 0x9182, 0x0040, - 0x0210, 0x0804, 0x36a8, 0x21e0, 0x20a9, 0x0001, 0x7984, 0x2198, - 0x4012, 0x0804, 0x3673, 0x2069, 0x1847, 0x7884, 0x7990, 0x911a, - 0x1a04, 0x36a8, 0x8019, 0x0904, 0x36a8, 0x684a, 0x6942, 0x788c, - 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, 0x080c, 0x79d0, - 0x0804, 0x3673, 0x2069, 0x1847, 0x7884, 0x7994, 0x911a, 0x1a04, - 0x36a8, 0x8019, 0x0904, 0x36a8, 0x684e, 0x6946, 0x788c, 0x6862, - 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6c65, 0x012e, 0x0804, 0x3673, 0x902e, 0x2520, 0x81ff, - 0x0120, 0x2009, 0x0001, 0x0804, 0x36a5, 0x7984, 0x7b88, 0x7a8c, - 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a6, 0x4101, 0x080c, - 0x4bc8, 0x1120, 0x2009, 0x0002, 0x0804, 0x36a5, 0x2009, 0x0020, - 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c11, 0x701f, 0x3799, - 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, 0x0168, - 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, 0x9096, 0x0048, - 0x0120, 0x9096, 0x0029, 0x1904, 0x36a5, 0x810f, 0x918c, 0x00ff, - 0x0904, 0x36a5, 0x7112, 0x7010, 0x8001, 0x0560, 0x7012, 0x080c, - 0x4bc8, 0x1120, 0x2009, 0x0002, 0x0804, 0x36a5, 0x2009, 0x0020, - 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, 0x9290, 0x0040, - 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0xa85c, 0x9080, - 0x0019, 0xaf60, 0x080c, 0x4c11, 0x701f, 0x37d7, 0x0005, 0xa864, - 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, 0x000a, 0x1904, - 0x36a5, 0x0888, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, - 0x9084, 0x00ff, 0x9096, 0x0029, 0x1160, 0xc2fd, 0xaa7a, 0x080c, - 0x62e5, 0x0150, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, 0x012e, - 0x0050, 0x080c, 0x6615, 0x1128, 0x7007, 0x0003, 0x701f, 0x3803, - 0x0005, 0x080c, 0x715d, 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, 0x4c14, 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, 0x1a26, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, - 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, - 0x2071, 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x36a5, 0x7984, - 0x080c, 0x6783, 0x1904, 0x36a8, 0x7e98, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x1a04, 0x36a8, 0x7c88, 0x7d8c, 0x080c, 0x69b7, 0x080c, - 0x6944, 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, 0x36a5, 0x0c30, 0x080c, 0xc81b, - 0x012e, 0x0904, 0x36a5, 0x0804, 0x3673, 0x900e, 0x2001, 0x0005, - 0x080c, 0x715d, 0x0126, 0x2091, 0x8000, 0x080c, 0xcf3e, 0x080c, - 0x6f11, 0x012e, 0x0804, 0x3673, 0x00a6, 0x2950, 0xb198, 0x080c, - 0x6783, 0x1904, 0x38ee, 0xb6a4, 0x9684, 0x3fff, 0x9082, 0x4000, - 0x16e8, 0xb49c, 0xb5a0, 0x080c, 0x69b7, 0x080c, 0x6944, 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, 0xc81b, 0x012e, - 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, 0x0005, 0x080c, - 0x715d, 0x0126, 0x2091, 0x8000, 0x080c, 0xcf3e, 0x080c, 0x6f05, - 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, 0x36a5, 0x080c, 0x4bdf, 0x0904, 0x36a8, - 0x080c, 0x684a, 0x0904, 0x36a5, 0x080c, 0x69bd, 0x0904, 0x36a5, - 0x0804, 0x4661, 0x81ff, 0x1904, 0x36a5, 0x080c, 0x4bfb, 0x0904, - 0x36a8, 0x080c, 0x6a4b, 0x0904, 0x36a5, 0x2019, 0x0005, 0x79a8, - 0x080c, 0x69d8, 0x0904, 0x36a5, 0x7888, 0x908a, 0x1000, 0x1a04, - 0x36a8, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x883a, 0x79a8, - 0xd184, 0x1904, 0x3673, 0x0804, 0x4661, 0x0126, 0x2091, 0x8000, - 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x07ff, 0x645c, - 0x2400, 0x9506, 0x01f8, 0x2508, 0x080c, 0x6783, 0x11d8, 0x080c, - 0x6a4b, 0x1128, 0x2009, 0x0002, 0x62c0, 0x2518, 0x00c0, 0x2019, - 0x0004, 0x900e, 0x080c, 0x69d8, 0x1118, 0x2009, 0x0006, 0x0078, - 0x7884, 0x908a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0x9108, - 0x080c, 0x883a, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x3673, 0x012e, - 0x0804, 0x36a5, 0x012e, 0x0804, 0x36a8, 0x080c, 0x4bdf, 0x0904, - 0x36a8, 0x080c, 0x684a, 0x0904, 0x36a5, 0x080c, 0xaaf7, 0xbaa0, - 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, 0x95b9, 0x0076, 0x903e, - 0x080c, 0x9476, 0x900e, 0x080c, 0xe465, 0x007e, 0x00ce, 0x080c, - 0xab13, 0x080c, 0x69b7, 0x0804, 0x3673, 0x080c, 0x4bdf, 0x0904, - 0x36a8, 0x080c, 0x69b7, 0x2208, 0x0804, 0x3673, 0x0156, 0x00d6, - 0x00e6, 0x00c6, 0x2069, 0x1910, 0x6810, 0x6914, 0x910a, 0x1208, - 0x900e, 0x6816, 0x9016, 0x901e, 0x2071, 0x19e9, 0x7028, 0x9065, - 0x0118, 0x8210, 0x600c, 0x0cd8, 0x2300, 0x9218, 0x00ce, 0x00ee, - 0x00de, 0x015e, 0x0804, 0x3673, 0x00f6, 0x0016, 0x907d, 0x0138, - 0x9006, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, - 0x00fe, 0x0005, 0x2069, 0x1910, 0x6910, 0x62bc, 0x0804, 0x3673, - 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36a5, 0x0126, 0x2091, - 0x8000, 0x080c, 0x5834, 0x0128, 0x2009, 0x0007, 0x012e, 0x0804, - 0x36a5, 0x012e, 0x615c, 0x9190, 0x3474, 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, 0x769d, 0x1118, - 0x2031, 0x0004, 0x0038, 0xd79c, 0x0120, 0x2009, 0x0005, 0x0804, - 0x36a5, 0x9036, 0x7e9a, 0x7f9e, 0x0804, 0x3673, 0x614c, 0x6250, - 0x2019, 0x1987, 0x231c, 0x2001, 0x1988, 0x2004, 0x789a, 0x0804, - 0x3673, 0x0126, 0x2091, 0x8000, 0x6138, 0x623c, 0x6340, 0x012e, - 0x0804, 0x3673, 0x080c, 0x4bfb, 0x0904, 0x36a8, 0xba44, 0xbb38, - 0x0804, 0x3673, 0x080c, 0x0d79, 0x080c, 0x4bfb, 0x2110, 0x0904, - 0x36a8, 0xb804, 0x908c, 0x00ff, 0x918e, 0x0006, 0x0140, 0x9084, - 0xff00, 0x9086, 0x0600, 0x2009, 0x0009, 0x1904, 0x36a5, 0x0126, - 0x2091, 0x8000, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, 0xaaf7, - 0x080c, 0xa5dd, 0x080c, 0x95b9, 0x0076, 0x903e, 0x080c, 0x9476, - 0x900e, 0x080c, 0xe465, 0x007e, 0x00ce, 0x080c, 0xab13, 0xb807, - 0x0407, 0x012e, 0x0804, 0x3673, 0x614c, 0x6250, 0x7884, 0x604e, - 0x7b88, 0x6352, 0x2069, 0x1847, 0x831f, 0x9305, 0x6816, 0x788c, - 0x2069, 0x1987, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, 0x1210, - 0x2031, 0x07d0, 0x2069, 0x1988, 0x2d04, 0x266a, 0x789a, 0x0804, - 0x3673, 0x0126, 0x2091, 0x8000, 0x6138, 0x7884, 0x603a, 0x910e, - 0xd1b4, 0x190c, 0x0edf, 0xd0c4, 0x01a8, 0x00d6, 0x78a8, 0x2009, - 0x199e, 0x200a, 0x78ac, 0x2011, 0x199f, 0x2012, 0x2069, 0x0100, - 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, 0x6a5a, 0x0010, 0x210c, - 0x695a, 0x00de, 0x2011, 0x0116, 0x220c, 0x7888, 0xd08c, 0x0118, - 0x918d, 0x0040, 0x0010, 0x918c, 0xff7f, 0x2112, 0x7988, 0x613e, - 0x6140, 0x788c, 0x6042, 0x910e, 0xd1e4, 0x190c, 0x0efa, 0x9084, - 0x0020, 0x0130, 0x78b4, 0x6046, 0x9084, 0x0001, 0x090c, 0x435b, - 0x6040, 0xd0cc, 0x0120, 0x78b0, 0x2011, 0x0114, 0x2012, 0x012e, - 0x0804, 0x3673, 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, 0x36a8, 0x788c, 0x902d, 0x0904, 0x36a8, - 0x900e, 0x080c, 0x6783, 0x1120, 0xba44, 0xbb38, 0xbc46, 0xbd3a, - 0x9186, 0x07ff, 0x0190, 0x8108, 0x0ca0, 0x080c, 0x4bfb, 0x0904, - 0x36a8, 0x7888, 0x900d, 0x0904, 0x36a8, 0x788c, 0x9005, 0x0904, - 0x36a8, 0xba44, 0xb946, 0xbb38, 0xb83a, 0x0804, 0x3673, 0x2011, - 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, 0x5834, 0x1904, 0x36a5, - 0x00c6, 0x2061, 0x0100, 0x7984, 0x9186, 0x00ff, 0x1130, 0x2001, - 0x1818, 0x2004, 0x9085, 0xff00, 0x0088, 0x9182, 0x007f, 0x16e0, - 0x9188, 0x3474, 0x210d, 0x918c, 0x00ff, 0x2001, 0x1818, 0x2004, - 0x0026, 0x9116, 0x002e, 0x0580, 0x810f, 0x9105, 0x0126, 0x2091, - 0x8000, 0x0006, 0x080c, 0xaef8, 0x000e, 0x0510, 0x602e, 0x620a, - 0x7984, 0x00b6, 0x080c, 0x671e, 0x2b08, 0x00be, 0x1500, 0x6112, - 0x6023, 0x0001, 0x080c, 0x4bc8, 0x01d0, 0x9006, 0xa866, 0x7007, - 0x0003, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x701f, 0x3b62, 0x2900, - 0x6016, 0x2009, 0x0032, 0x080c, 0xafec, 0x012e, 0x00ce, 0x0005, - 0x012e, 0x00ce, 0x0804, 0x36a5, 0x00ce, 0x0804, 0x36a8, 0x080c, - 0xaf4e, 0x0cb0, 0xa830, 0x9086, 0x0100, 0x0904, 0x36a5, 0x0804, - 0x3673, 0x2061, 0x1a74, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, - 0x0170, 0x6104, 0x6208, 0x2061, 0x1800, 0x6354, 0x6074, 0x789a, - 0x60c0, 0x789e, 0x60bc, 0x78aa, 0x012e, 0x0804, 0x3673, 0x900e, - 0x2110, 0x0c88, 0x81ff, 0x1904, 0x36a5, 0x080c, 0x769d, 0x0904, - 0x36a5, 0x0126, 0x2091, 0x8000, 0x6254, 0x6074, 0x9202, 0x0248, - 0x9085, 0x0001, 0x080c, 0x270a, 0x080c, 0x5a57, 0x012e, 0x0804, - 0x3673, 0x012e, 0x0804, 0x36a8, 0x0006, 0x0016, 0x00c6, 0x00e6, - 0x2001, 0x19ab, 0x2070, 0x2061, 0x1847, 0x6008, 0x2072, 0x900e, - 0x2011, 0x1400, 0x080c, 0x9364, 0x7206, 0x00ee, 0x00ce, 0x001e, - 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0128, 0x012e, - 0x2021, 0x400b, 0x0804, 0x3675, 0x7884, 0xd0fc, 0x0158, 0x2001, - 0x002a, 0x2004, 0x9005, 0x0180, 0x9082, 0x00e1, 0x0298, 0x012e, - 0x0804, 0x36a8, 0x2001, 0x002a, 0x2004, 0x9005, 0x0128, 0x2069, - 0x1847, 0x6908, 0x9102, 0x1230, 0x012e, 0x0804, 0x36a8, 0x012e, - 0x0804, 0x36a5, 0x080c, 0xae80, 0x0dd0, 0x7884, 0xd0fc, 0x0904, - 0x3c31, 0x00c6, 0x080c, 0x4bc8, 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, - 0x3dbb, 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, 0x4c11, 0x701f, 0x3cf8, 0x7023, 0x0001, 0x012e, - 0x0005, 0x080c, 0xaaf7, 0x0046, 0x0086, 0x0096, 0x00a6, 0x00b6, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3b9c, 0x2001, 0x19a1, - 0x2003, 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, 0x0016, - 0x60bb, 0x0000, 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, 0x3e2a, - 0x080c, 0x3de9, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, 0x19e9, - 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0140, - 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, 0x780a, - 0x00de, 0x2011, 0x0001, 0x080c, 0x419f, 0x008e, 0x00ee, 0x00fe, - 0x080c, 0x40c1, 0x080c, 0x3fee, 0x05b8, 0x2001, 0x020b, 0x2004, - 0x9084, 0x0140, 0x1db8, 0x080c, 0x4213, 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, 0x3ff8, 0x080c, 0x3de4, - 0x0058, 0x080c, 0x3de4, 0x080c, 0x4137, 0x080c, 0x40b7, 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, 0x1346, - 0x2009, 0x0028, 0x080c, 0x223d, 0x2001, 0x0227, 0x200c, 0x2102, - 0x080c, 0xab13, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, - 0x009e, 0x008e, 0x004e, 0x2001, 0x19a1, 0x2004, 0x9005, 0x1118, - 0x012e, 0x0804, 0x3673, 0x012e, 0x2021, 0x400c, 0x0804, 0x3675, - 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, - 0x00d6, 0x0156, 0x7014, 0x2048, 0x7020, 0x20a8, 0x8000, 0x7022, - 0xa804, 0x9005, 0x0904, 0x3d54, 0x2048, 0x1f04, 0x3d08, 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, 0x4c11, - 0x701f, 0x3cf8, 0x00b0, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, - 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, - 0x20a0, 0x0006, 0x080c, 0x0fca, 0x000e, 0x080c, 0x4c14, 0x701f, - 0x3cf8, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, - 0x003e, 0x002e, 0x001e, 0x0005, 0x7014, 0x2048, 0xa864, 0x9086, - 0x0103, 0x1118, 0x701f, 0x3db9, 0x0450, 0x7014, 0x2048, 0xa868, - 0xc0fd, 0xa86a, 0x2009, 0x007f, 0x080c, 0x6718, 0x0110, 0x9006, - 0x0030, 0xb813, 0x00ff, 0xb817, 0xfffd, 0x080c, 0xd121, 0x015e, - 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, - 0x001e, 0x0904, 0x36a5, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, - 0x0076, 0x0086, 0x0096, 0x00d6, 0x0156, 0x701f, 0x3d8b, 0x7007, - 0x0003, 0x0804, 0x3d49, 0xa830, 0x9086, 0x0100, 0x2021, 0x400c, - 0x0904, 0x3675, 0x0076, 0xad10, 0xac0c, 0xab24, 0xaa20, 0xa930, - 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, + 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, 0x0fca, - 0x000e, 0x080c, 0x4c14, 0x007e, 0x701f, 0x3cf8, 0x7023, 0x0001, - 0x0005, 0x0804, 0x3673, 0x0156, 0x00c6, 0xa814, 0x908a, 0x001e, - 0x0218, 0xa833, 0x001e, 0x0010, 0xa832, 0x0078, 0x81ff, 0x0168, - 0x0016, 0x080c, 0x4bc8, 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, 0x19a1, 0x2003, 0x0001, - 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, 0x19ac, - 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x19ab, 0x2004, 0x60ce, - 0x6104, 0xc1ac, 0x6106, 0x080c, 0x4bc8, 0xa813, 0x0019, 0xa817, - 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, - 0x002f, 0x2004, 0xa86a, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, - 0x19ab, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x223d, 0x2001, - 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0x601a, 0xa873, 0x0000, - 0x601f, 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, - 0x00fe, 0x0005, 0x00e6, 0x080c, 0x4bc8, 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, 0x2a80, 0x1130, - 0x9006, 0x080c, 0x29d7, 0x9006, 0x080c, 0x29ba, 0x2001, 0x19a0, - 0x2003, 0x0000, 0x7884, 0x9084, 0x0007, 0x0002, 0x3e79, 0x3e7a, - 0x3e7b, 0x3e76, 0x3e76, 0x3e76, 0x3e76, 0x3e76, 0x012e, 0x0804, - 0x36a8, 0x0ce0, 0x0cd8, 0x080c, 0x769d, 0x1128, 0x012e, 0x2009, - 0x0016, 0x0804, 0x36a5, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, - 0x0804, 0x3675, 0x2001, 0x0141, 0x2004, 0xd0dc, 0x0db0, 0x080c, - 0xaaf7, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x080c, 0x3b9c, 0x2009, 0x0101, 0x210c, 0x0016, 0x7ec8, - 0x7dcc, 0x9006, 0x2068, 0x2060, 0x2058, 0x080c, 0x42ee, 0x080c, - 0x423e, 0x903e, 0x2720, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, - 0x19e9, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, - 0x0120, 0x68d4, 0x780e, 0x68d0, 0x780a, 0x00de, 0x2011, 0x0001, - 0x080c, 0x419f, 0x080c, 0x2a88, 0x080c, 0x2a88, 0x080c, 0x2a88, - 0x080c, 0x2a88, 0x080c, 0x419f, 0x008e, 0x00ee, 0x00fe, 0x080c, - 0x40c1, 0x2009, 0x9c40, 0x8109, 0x11b0, 0x080c, 0x3ff8, 0x2001, - 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x2009, 0x0017, - 0x080c, 0x36a5, 0x0cf8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, - 0x1d10, 0x00f6, 0x2079, 0x0000, 0x7884, 0x00fe, 0xd0bc, 0x0178, - 0x2001, 0x0201, 0x200c, 0x81ff, 0x0150, 0x080c, 0x409f, 0x2d00, - 0x9c05, 0x9b05, 0x0120, 0x080c, 0x3ff8, 0x0804, 0x3fa1, 0x080c, - 0x4213, 0x080c, 0x4137, 0x080c, 0x4082, 0x080c, 0x40b7, 0x00f6, - 0x2079, 0x0100, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x3ff8, - 0x00fe, 0x0804, 0x3fa1, 0x00fe, 0x080c, 0x3fee, 0x1150, 0x8d68, - 0x2001, 0x0032, 0x2602, 0x2001, 0x0033, 0x2502, 0x080c, 0x3ff8, - 0x0080, 0x87ff, 0x0138, 0x2001, 0x0201, 0x2004, 0x9005, 0x1908, - 0x8739, 0x0038, 0x2001, 0x1a6f, 0x2004, 0x9086, 0x0000, 0x1904, - 0x3ef1, 0x2001, 0x032f, 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, - 0x2500, 0x9605, 0x0904, 0x3fa1, 0x7884, 0xd0bc, 0x0128, 0x2d00, - 0x9c05, 0x9b05, 0x1904, 0x3fa1, 0xa013, 0x0019, 0x2001, 0x032a, - 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1148, 0x2001, 0x1a6f, 0x2003, - 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x0030, 0xa017, 0x0001, - 0x78b4, 0x9005, 0x0108, 0xa016, 0x2800, 0xa05a, 0x2009, 0x0040, - 0x080c, 0x223d, 0x2900, 0xa85a, 0xa813, 0x0019, 0x7884, 0xd0a4, - 0x1180, 0xa817, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, - 0x602b, 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x3f78, 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, - 0x3eab, 0x001e, 0x00c6, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, - 0x0100, 0x6027, 0x0002, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, - 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x1346, - 0x7884, 0x9084, 0x0003, 0x9086, 0x0002, 0x01b0, 0x2009, 0x0028, - 0x080c, 0x223d, 0x2001, 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, - 0xb7ff, 0x080c, 0x2b32, 0x6052, 0x602f, 0x0000, 0x604b, 0xf7f7, - 0x6043, 0x0090, 0x6043, 0x0010, 0x080c, 0xab13, 0x00ce, 0x2d08, - 0x2c10, 0x2b18, 0x2b00, 0x9c05, 0x9d05, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, - 0x3673, 0x012e, 0x2021, 0x400c, 0x0804, 0x3675, 0x9085, 0x0001, - 0x1d04, 0x3ff7, 0x2091, 0x6000, 0x8420, 0x9486, 0x0064, 0x0005, - 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, 0x2003, 0x0004, - 0x2001, 0x1a6f, 0x2003, 0x0000, 0x0071, 0x2009, 0x0048, 0x080c, - 0x223d, 0x2001, 0x0227, 0x2024, 0x2402, 0x2001, 0x0109, 0x2003, - 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x19e9, 0x7054, - 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, 0x2009, 0x0206, 0x2104, - 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, - 0x223d, 0x782c, 0xd0fc, 0x0d88, 0x080c, 0x4213, 0x7054, 0x9086, - 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, - 0x0040, 0x080c, 0x223d, 0x782b, 0x0002, 0x7057, 0x0000, 0x00ee, - 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, 0x1818, 0x200c, - 0x7932, 0x7936, 0x080c, 0x26ea, 0x080c, 0x2aff, 0x080c, 0x2b32, - 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x7850, 0xc0e5, - 0x7852, 0x2019, 0x61a8, 0x7820, 0xd09c, 0x0110, 0x8319, 0x1dd8, - 0x7850, 0xc0e4, 0x7852, 0x2011, 0x0048, 0x080c, 0x2adc, 0x7843, - 0x0040, 0x2019, 0x01f4, 0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, - 0x0100, 0x080c, 0x2aa2, 0x2011, 0x0020, 0x080c, 0x2adc, 0x7843, - 0x0000, 0x9006, 0x080c, 0x2aa2, 0x2011, 0x0048, 0x080c, 0x2adc, - 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, - 0x1a6f, 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, 0x19ac, 0x2004, 0x70e2, - 0x080c, 0x3dda, 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, 0x4213, - 0x00f6, 0x2071, 0x1a6f, 0x2079, 0x0320, 0x00d6, 0x2069, 0x0000, - 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, 0x6898, 0x780a, 0x00de, - 0x080c, 0x3dda, 0x0140, 0x2001, 0x19a0, 0x200c, 0x2003, 0x0001, - 0x918e, 0x0001, 0x0120, 0x2009, 0x03e8, 0x8109, 0x1df0, 0x792c, - 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, 0x080c, 0x419f, - 0x2011, 0x0001, 0x080c, 0x419f, 0x00fe, 0x00ee, 0x0005, 0x00f6, - 0x00e6, 0x2071, 0x1a6f, 0x2079, 0x0320, 0x792c, 0xd1fc, 0x0904, - 0x419c, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, 0x4198, 0x7000, - 0x0002, 0x419c, 0x414d, 0x417d, 0x4198, 0xd1bc, 0x1170, 0xd1dc, - 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, 0x419f, 0x0904, - 0x419c, 0x080c, 0x419f, 0x0804, 0x419c, 0x00f6, 0x2079, 0x0300, - 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, 0x0004, 0x7812, - 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x409f, - 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, 0x00fe, 0xd0ec, - 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, 0x7002, 0x9184, - 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x4141, 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, 0x0d79, 0x9398, 0x41cd, 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, 0x420a, 0x4201, 0x41f8, - 0x41ef, 0x41e6, 0x41dd, 0x41d4, 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, 0x19e9, - 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, 0x782b, 0x0002, 0x2940, - 0x9026, 0x7054, 0x0002, 0x423a, 0x4226, 0x4231, 0x8001, 0x7056, - 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x419f, 0x190c, 0x419f, - 0x0048, 0x8001, 0x7056, 0x782c, 0xd0fc, 0x1d38, 0x2011, 0x0001, - 0x080c, 0x419f, 0x008e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, - 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, 0x19ac, 0x2004, 0x601a, - 0x2061, 0x0100, 0x2001, 0x19ab, 0x2004, 0x60ce, 0x6104, 0xc1ac, - 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, 0x0520, 0x2038, 0x2001, - 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, 0x4bc8, 0xa813, - 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, - 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, 0x2048, - 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x42b6, 0x1d68, 0x2900, - 0xa85a, 0x00d0, 0x080c, 0x4bc8, 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, 0x19ab, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x223d, - 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, 0x4bc8, - 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, 0x4bc8, 0x2940, 0xa813, 0x0019, - 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, - 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, 0x2048, 0xa85c, - 0x9080, 0x0019, 0x009e, 0x080c, 0x42b6, 0x1d68, 0x2900, 0xa85a, - 0x00d8, 0x080c, 0x4bc8, 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, 0x1a6f, 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, - 0x3673, 0x7d98, 0x7c9c, 0x0804, 0x3777, 0x080c, 0x769d, 0x190c, - 0x613d, 0x6040, 0x9084, 0x0020, 0x09b1, 0x2069, 0x1847, 0x2d00, - 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, - 0x080c, 0x4c11, 0x701f, 0x4395, 0x0005, 0x080c, 0x582f, 0x1130, - 0x3b00, 0x3a08, 0xc194, 0xc095, 0x20d8, 0x21d0, 0x2069, 0x1847, - 0x6800, 0x9005, 0x0904, 0x36a8, 0x6804, 0xd0ac, 0x0118, 0xd0a4, - 0x0904, 0x36a8, 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, 0x36a8, 0x9288, - 0x3474, 0x210d, 0x918c, 0x00ff, 0x6166, 0xd0dc, 0x0130, 0x6828, - 0x908a, 0x007f, 0x1a04, 0x36a8, 0x605e, 0x6888, 0x9084, 0x0030, - 0x8004, 0x8004, 0x8004, 0x8004, 0x0006, 0x2009, 0x19b3, 0x9080, - 0x27dd, 0x2005, 0x200a, 0x2008, 0x2001, 0x0018, 0x080c, 0xaae8, - 0x2009, 0x0390, 0x200b, 0x0400, 0x000e, 0x2009, 0x19b4, 0x9080, - 0x27e1, 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, 0x0a04, 0x36a8, - 0x908a, 0x0841, 0x1a04, 0x36a8, 0x9084, 0x0007, 0x1904, 0x36a8, - 0x680c, 0x9005, 0x0904, 0x36a8, 0x6810, 0x9005, 0x0904, 0x36a8, - 0x6848, 0x6940, 0x910a, 0x1a04, 0x36a8, 0x8001, 0x0904, 0x36a8, - 0x684c, 0x6944, 0x910a, 0x1a04, 0x36a8, 0x8001, 0x0904, 0x36a8, - 0x6814, 0x908c, 0x00ff, 0x614e, 0x8007, 0x9084, 0x00ff, 0x6052, - 0x080c, 0x79d0, 0x080c, 0x6c03, 0x080c, 0x6c65, 0x6808, 0x602a, - 0x080c, 0x21af, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, 0xa001, - 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x2744, 0x003e, 0x6000, - 0x9086, 0x0000, 0x1904, 0x4524, 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, 0x19b5, 0x20e9, 0x0001, 0x4001, 0x20a9, 0x0004, 0x20a1, - 0x19cf, 0x20e9, 0x0001, 0x4001, 0x080c, 0x89bf, 0x00c6, 0x900e, - 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, - 0x3508, 0x8109, 0x080c, 0x7f97, 0x6878, 0x6016, 0x6874, 0x2008, - 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, 0x8108, - 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x447e, - 0x00ce, 0x00c6, 0x2061, 0x199d, 0x6a88, 0x9284, 0xc000, 0x2010, - 0x9286, 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, 0x080c, - 0x29d7, 0x2001, 0x0001, 0x080c, 0x29ba, 0x0088, 0x9286, 0x4000, - 0x1148, 0x2063, 0x0001, 0x9006, 0x080c, 0x29d7, 0x9006, 0x080c, - 0x29ba, 0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, 0x00ce, - 0x00e6, 0x2c70, 0x080c, 0x0ec7, 0x00ee, 0x080c, 0x2aff, 0x080c, - 0x2b32, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, 0x9085, - 0x0180, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, 0x1128, - 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x197d, 0x6a80, - 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, 0x0118, - 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x27b9, 0x2001, - 0x196e, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, - 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x769d, 0x0128, 0x080c, - 0x5108, 0x0110, 0x080c, 0x270a, 0x60d4, 0x9005, 0x01c0, 0x6003, - 0x0001, 0x2009, 0x450c, 0x00e0, 0x080c, 0x769d, 0x1168, 0x2011, - 0x7511, 0x080c, 0x882c, 0x2011, 0x7504, 0x080c, 0x8938, 0x080c, - 0x79a4, 0x080c, 0x75cc, 0x0040, 0x080c, 0x6033, 0x0028, 0x6003, - 0x0004, 0x2009, 0x4524, 0x0020, 0x080c, 0x6b2f, 0x0804, 0x3673, - 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, 0x1118, - 0x2091, 0x31bd, 0x0817, 0x2091, 0x313d, 0x0817, 0x6000, 0x9086, - 0x0000, 0x0904, 0x36a5, 0x2069, 0x1847, 0x7890, 0x6842, 0x7894, - 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x2039, 0x0001, 0x0804, 0x4c14, 0x9006, 0x080c, 0x270a, 0x81ff, - 0x1904, 0x36a5, 0x080c, 0x769d, 0x11b0, 0x080c, 0x799f, 0x080c, - 0x6178, 0x080c, 0x3468, 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, - 0xd35d, 0x0130, 0x080c, 0x76c0, 0x1118, 0x080c, 0x7671, 0x0038, - 0x080c, 0x75cc, 0x0020, 0x080c, 0x613d, 0x080c, 0x6033, 0x0804, - 0x3673, 0x81ff, 0x1904, 0x36a5, 0x080c, 0x769d, 0x1110, 0x0804, - 0x36a5, 0x0126, 0x2091, 0x8000, 0x6194, 0x81ff, 0x0190, 0x704f, - 0x0000, 0x2001, 0x1d80, 0x2009, 0x0040, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x2039, 0x0001, 0x080c, 0x4c14, 0x701f, 0x3671, 0x012e, - 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, 0x1d80, 0x20a9, 0x0040, - 0x20e9, 0x0001, 0x20a1, 0x1d80, 0x2019, 0xffff, 0x4304, 0x655c, - 0x9588, 0x3474, 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, - 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, 0x6783, 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, 0x60c8, 0x0804, 0x4581, 0x080c, 0x4bfb, - 0x0904, 0x36a8, 0x080c, 0x4bc8, 0x1120, 0x2009, 0x0002, 0x0804, - 0x36a5, 0x080c, 0x5820, 0xd0b4, 0x0558, 0x7884, 0x908e, 0x007e, - 0x0538, 0x908e, 0x007f, 0x0520, 0x908e, 0x0080, 0x0508, 0x080c, - 0x3463, 0x1148, 0xb800, 0xd08c, 0x11d8, 0xb804, 0x9084, 0x00ff, - 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0x080c, 0xce04, 0x1120, 0x2009, 0x0003, 0x0804, 0x36a5, 0x7007, - 0x0003, 0x701f, 0x460c, 0x0005, 0x080c, 0x4bfb, 0x0904, 0x36a8, - 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, 0x0fca, 0x0070, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x000a, - 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, - 0x0fca, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x0804, 0x4c14, 0x81ff, 0x1904, 0x36a5, 0x080c, 0x4bdf, 0x0904, - 0x36a8, 0x080c, 0x69c6, 0x0904, 0x36a5, 0x0058, 0xa878, 0x9005, - 0x0120, 0x2009, 0x0004, 0x0804, 0x36a5, 0xa974, 0xaa94, 0x0804, - 0x3673, 0x080c, 0x5828, 0x0904, 0x3673, 0x701f, 0x4656, 0x7007, - 0x0003, 0x0005, 0x81ff, 0x1904, 0x36a5, 0x7888, 0x908a, 0x1000, - 0x1a04, 0x36a8, 0x080c, 0x4bfb, 0x0904, 0x36a8, 0x080c, 0x6bcd, - 0x0120, 0x080c, 0x6bd5, 0x1904, 0x36a8, 0x080c, 0x6a4b, 0x0904, - 0x36a5, 0x2019, 0x0004, 0x900e, 0x080c, 0x69d8, 0x0904, 0x36a5, - 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, 0x908a, 0x1000, 0x12f8, - 0x080c, 0x4bf9, 0x01e0, 0x080c, 0x6bcd, 0x0118, 0x080c, 0x6bd5, - 0x11b0, 0x080c, 0x6a4b, 0x2009, 0x0002, 0x0168, 0x2009, 0x0002, - 0x2019, 0x0004, 0x080c, 0x69d8, 0x2009, 0x0003, 0x0120, 0xa998, - 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, - 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, - 0x4000, 0x080c, 0x5828, 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, 0x6783, - 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x883a, - 0x0005, 0x81ff, 0x1904, 0x36a5, 0x798c, 0x2001, 0x1981, 0x918c, - 0x8000, 0x2102, 0x080c, 0x4bdf, 0x0904, 0x36a8, 0x080c, 0x6bcd, - 0x0120, 0x080c, 0x6bd5, 0x1904, 0x36a8, 0x080c, 0x684a, 0x0904, - 0x36a5, 0x080c, 0x69cf, 0x0904, 0x36a5, 0x2001, 0x1981, 0x2004, - 0xd0fc, 0x1904, 0x3673, 0x0804, 0x4661, 0xa9a0, 0x2001, 0x1981, - 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4bec, 0x01a0, 0x080c, - 0x6bcd, 0x0118, 0x080c, 0x6bd5, 0x1170, 0x080c, 0x684a, 0x2009, - 0x0002, 0x0128, 0x080c, 0x69cf, 0x1170, 0x2009, 0x0003, 0xa897, - 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x1981, 0x2004, - 0xd0fc, 0x1128, 0x080c, 0x5828, 0x0110, 0x9006, 0x0018, 0x900e, - 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904, 0x36a5, - 0x798c, 0x2001, 0x1980, 0x918c, 0x8000, 0x2102, 0x080c, 0x4bdf, - 0x0904, 0x36a8, 0x080c, 0x6bcd, 0x0120, 0x080c, 0x6bd5, 0x1904, - 0x36a8, 0x080c, 0x684a, 0x0904, 0x36a5, 0x080c, 0x69bd, 0x0904, - 0x36a5, 0x2001, 0x1980, 0x2004, 0xd0fc, 0x1904, 0x3673, 0x0804, - 0x4661, 0xa9a0, 0x2001, 0x1980, 0x918c, 0x8000, 0xc18d, 0x2102, - 0x080c, 0x4bec, 0x01a0, 0x080c, 0x6bcd, 0x0118, 0x080c, 0x6bd5, - 0x1170, 0x080c, 0x684a, 0x2009, 0x0002, 0x0128, 0x080c, 0x69bd, - 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, - 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, - 0x4000, 0x2001, 0x1980, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x5828, - 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, - 0x0005, 0x6100, 0x0804, 0x3673, 0x080c, 0x4bfb, 0x0904, 0x36a8, - 0x080c, 0x5834, 0x1904, 0x36a5, 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, - 0x3673, 0x78a8, 0x909c, 0x0003, 0xd0ac, 0x1150, 0xd0b4, 0x1140, - 0x939a, 0x0003, 0x1a04, 0x36a5, 0x625c, 0x7884, 0x9206, 0x1548, - 0x080c, 0x89a9, 0x2001, 0xffec, 0x2009, 0x000c, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x2039, 0x0000, 0x0006, 0x78a8, 0x9084, 0x0080, - 0x1118, 0x000e, 0x0804, 0x4c14, 0x000e, 0x2031, 0x0000, 0x2061, + 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, 0x1142, 0x7007, 0x0002, 0x701f, 0x4819, - 0x0005, 0x81ff, 0x1904, 0x36a5, 0x080c, 0x4bfb, 0x0904, 0x36a8, - 0x080c, 0x6bcd, 0x1904, 0x36a5, 0x00c6, 0x080c, 0x4bc8, 0x00ce, - 0x0904, 0x36a5, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7ea8, - 0x080c, 0xcdaa, 0x0904, 0x36a5, 0x7007, 0x0003, 0x701f, 0x481d, - 0x0005, 0x080c, 0x435b, 0x0804, 0x3673, 0xa830, 0x9086, 0x0100, - 0x0904, 0x36a5, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x0804, 0x4c14, 0x9006, 0x080c, 0x270a, 0x78a8, 0x9084, - 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x36a5, 0x080c, - 0x769d, 0x0110, 0x080c, 0x613d, 0x7888, 0x908a, 0x1000, 0x1a04, - 0x36a8, 0x7984, 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04, - 0x36a8, 0x2100, 0x080c, 0x26d4, 0x0026, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x2061, 0x1a05, 0x601b, 0x0000, 0x601f, 0x0000, 0x607b, - 0x0000, 0x607f, 0x0000, 0x080c, 0x769d, 0x1158, 0x080c, 0x799f, - 0x080c, 0x6178, 0x9085, 0x0001, 0x080c, 0x76e1, 0x080c, 0x75cc, - 0x00f0, 0x080c, 0xaaf7, 0x080c, 0xae87, 0x080c, 0xab13, 0x2061, - 0x0100, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x810f, 0x9105, - 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x199a, 0x200b, - 0x0000, 0x2009, 0x002d, 0x2011, 0x6063, 0x080c, 0x88f6, 0x7984, - 0x080c, 0x769d, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, 0x46c4, - 0x012e, 0x00ce, 0x002e, 0x0804, 0x3673, 0x7984, 0x080c, 0x6718, - 0x2b08, 0x1904, 0x36a8, 0x0804, 0x3673, 0x81ff, 0x0120, 0x2009, - 0x0001, 0x0804, 0x36a5, 0x60dc, 0xd0ac, 0x1130, 0xd09c, 0x1120, - 0x2009, 0x0005, 0x0804, 0x36a5, 0x080c, 0x4bc8, 0x1120, 0x2009, - 0x0002, 0x0804, 0x36a5, 0x7984, 0x81ff, 0x0904, 0x36a8, 0x9192, - 0x0021, 0x1a04, 0x36a8, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, - 0x9080, 0x0019, 0x702a, 0xaf60, 0x7736, 0x080c, 0x4c11, 0x701f, - 0x48d8, 0x7880, 0x9086, 0x006e, 0x0110, 0x701f, 0x52ba, 0x0005, - 0x2009, 0x0080, 0x080c, 0x6783, 0x1118, 0x080c, 0x6bcd, 0x0120, - 0x2021, 0x400a, 0x0804, 0x3675, 0x00d6, 0x0096, 0xa964, 0xaa6c, - 0xab70, 0xac74, 0xad78, 0xae7c, 0xa884, 0x90be, 0x0100, 0x0904, - 0x4971, 0x90be, 0x0112, 0x0904, 0x4971, 0x90be, 0x0113, 0x0904, - 0x4971, 0x90be, 0x0114, 0x0904, 0x4971, 0x90be, 0x0117, 0x0904, - 0x4971, 0x90be, 0x011a, 0x0904, 0x4971, 0x90be, 0x011c, 0x0904, - 0x4971, 0x90be, 0x0121, 0x0904, 0x4958, 0x90be, 0x0131, 0x0904, - 0x4958, 0x90be, 0x0171, 0x0904, 0x4971, 0x90be, 0x0173, 0x0904, - 0x4971, 0x90be, 0x01a1, 0x1128, 0xa894, 0x8007, 0xa896, 0x0804, - 0x497c, 0x90be, 0x0212, 0x0904, 0x4965, 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, 0x36a8, 0x7028, - 0x9080, 0x0010, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, - 0x0007, 0x080c, 0x49ba, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, - 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x49ba, 0x00c8, - 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, - 0x20a9, 0x0001, 0x080c, 0x49c7, 0x00b8, 0x7028, 0x9080, 0x000e, - 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, - 0x49c7, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, - 0x20e8, 0x20a9, 0x0001, 0x04f1, 0x00c6, 0x080c, 0x4bc8, 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, 0xcdc5, - 0x1120, 0x2009, 0x0003, 0x0804, 0x36a5, 0x7007, 0x0003, 0x701f, - 0x49b1, 0x0005, 0x00ce, 0x009e, 0x00de, 0x2009, 0x0002, 0x0804, - 0x36a5, 0xa820, 0x9086, 0x8001, 0x1904, 0x3673, 0x2009, 0x0004, - 0x0804, 0x36a5, 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, 0x36a5, - 0x60dc, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, - 0x36a5, 0x7984, 0x78a8, 0x2040, 0x080c, 0xae80, 0x1120, 0x9182, - 0x007f, 0x0a04, 0x36a8, 0x9186, 0x00ff, 0x0904, 0x36a8, 0x9182, - 0x0800, 0x1a04, 0x36a8, 0x7a8c, 0x7b88, 0x607c, 0x9306, 0x1158, - 0x6080, 0x924e, 0x0904, 0x36a8, 0x080c, 0xae80, 0x1120, 0x99cc, - 0xff00, 0x0904, 0x36a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x4adb, - 0x0904, 0x4a5b, 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, 0x6bcd, 0x0110, - 0xc89d, 0x0438, 0x900e, 0x080c, 0x6a74, 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, - 0x3675, 0x000e, 0x00ce, 0x2b00, 0x7026, 0x0016, 0x00b6, 0x00c6, - 0x00e6, 0x2c70, 0x080c, 0xafbf, 0x0904, 0x4ab0, 0x2b00, 0x6012, - 0x080c, 0xd0ce, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x4bc8, - 0x00ce, 0x2b70, 0x1158, 0x080c, 0xaf4e, 0x00ee, 0x00ce, 0x00be, - 0x001e, 0x012e, 0x2009, 0x0002, 0x0804, 0x36a5, 0x900e, 0xa966, - 0xa96a, 0x2900, 0x6016, 0xa932, 0xa868, 0xc0fd, 0xd88c, 0x0108, - 0xc0f5, 0xa86a, 0xd89c, 0x1110, 0x080c, 0x32fb, 0x6023, 0x0001, - 0x9006, 0x080c, 0x66b5, 0xd89c, 0x0138, 0x2001, 0x0004, 0x080c, - 0x66c9, 0x2009, 0x0003, 0x0030, 0x2001, 0x0002, 0x080c, 0x66c9, - 0x2009, 0x0002, 0x080c, 0xafec, 0x78a8, 0xd094, 0x0138, 0x00ee, - 0x7024, 0x00e6, 0x2058, 0xb8d4, 0xc08d, 0xb8d6, 0x9085, 0x0001, - 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, 0x0003, - 0x0804, 0x36a5, 0x7007, 0x0003, 0x701f, 0x4abf, 0x0005, 0xa830, - 0x9086, 0x0100, 0x7024, 0x2058, 0x1138, 0x2009, 0x0004, 0xba04, - 0x9294, 0x00ff, 0x0804, 0x576e, 0x900e, 0xa868, 0xd0f4, 0x1904, - 0x3673, 0x080c, 0x6a74, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, - 0xc18d, 0x0804, 0x3673, 0x00e6, 0x00d6, 0x0096, 0x83ff, 0x0904, - 0x4b2a, 0x902e, 0x080c, 0xae80, 0x0130, 0x9026, 0x20a9, 0x0800, - 0x2071, 0x1000, 0x0030, 0x2021, 0x007f, 0x20a9, 0x0781, 0x2071, - 0x107f, 0x2e04, 0x9005, 0x11b8, 0x2100, 0x9406, 0x1904, 0x4b3b, - 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, 0x6b6d, 0x1570, 0x2001, 0x4000, - 0x0460, 0x080c, 0x6bcd, 0x1540, 0x2001, 0x4000, 0x0430, 0x2001, - 0x4007, 0x0418, 0x2001, 0x4006, 0x0400, 0x2400, 0x9106, 0x1158, - 0xbe14, 0x87ff, 0x1128, 0x86ff, 0x0918, 0x080c, 0xae80, 0x1900, - 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x4af1, 0x85ff, - 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, 0x080c, - 0x6718, 0x1dd0, 0xbb12, 0xba16, 0x9006, 0x9005, 0x009e, 0x00de, - 0x00ee, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36a5, - 0x080c, 0x4bc8, 0x1120, 0x2009, 0x0002, 0x0804, 0x36a5, 0xa867, - 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7884, 0x9005, 0x0904, 0x36a8, - 0x9096, 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, 0x36a8, 0x2010, - 0x2918, 0x080c, 0x329b, 0x1120, 0x2009, 0x0003, 0x0804, 0x36a5, - 0x7007, 0x0003, 0x701f, 0x4b7d, 0x0005, 0xa830, 0x9086, 0x0100, - 0x1904, 0x3673, 0x2009, 0x0004, 0x0804, 0x36a5, 0x7984, 0x080c, - 0xae80, 0x1120, 0x9182, 0x007f, 0x0a04, 0x36a8, 0x9186, 0x00ff, - 0x0904, 0x36a8, 0x9182, 0x0800, 0x1a04, 0x36a8, 0x2001, 0x9400, - 0x080c, 0x57c9, 0x1904, 0x36a5, 0x0804, 0x3673, 0xa998, 0x080c, - 0xae80, 0x1118, 0x9182, 0x007f, 0x0280, 0x9186, 0x00ff, 0x0168, - 0x9182, 0x0800, 0x1250, 0x2001, 0x9400, 0x080c, 0x57c9, 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, 0x104d, 0x0198, 0x9006, 0xa802, 0x7014, 0x9005, 0x1120, - 0x2900, 0x7016, 0x701a, 0x0040, 0x7018, 0xa802, 0x0086, 0x2040, - 0x2900, 0xa006, 0x701a, 0x008e, 0x9085, 0x0001, 0x0005, 0x7984, - 0x080c, 0x6783, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, 0x4000, - 0x0208, 0x905e, 0x8bff, 0x0005, 0xa998, 0x080c, 0x6783, 0x1130, - 0xae9c, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, 0x8bff, - 0x0005, 0xae98, 0x0008, 0x7e84, 0x2608, 0x080c, 0x6783, 0x1108, - 0x0008, 0x905e, 0x8bff, 0x0005, 0x0016, 0x7114, 0x81ff, 0x0128, - 0x2148, 0xa904, 0x080c, 0x107f, 0x0cc8, 0x7116, 0x711a, 0x001e, - 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, 0x18b8, - 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, 0xa496, - 0xa59a, 0x080c, 0x1142, 0x7007, 0x0002, 0x701f, 0x3673, 0x0005, - 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, 0x18b0, - 0x2004, 0x9005, 0x1190, 0x0e04, 0x4c45, 0x7a36, 0x7833, 0x0012, - 0x7a82, 0x7b86, 0x7c8a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x11f4, 0x0804, 0x4cab, 0x0016, 0x0086, 0x0096, - 0x00c6, 0x00e6, 0x2071, 0x189e, 0x7044, 0x9005, 0x1540, 0x7148, - 0x9182, 0x0010, 0x0288, 0x7038, 0x2060, 0x080c, 0x104d, 0x0904, - 0x4ca3, 0xa84b, 0x0000, 0x2900, 0x7046, 0x2001, 0x0002, 0x9080, - 0x1ede, 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, 0x0d79, 0x2060, 0x001e, 0x8108, 0x2105, 0x9005, - 0xa146, 0x1520, 0x080c, 0x104d, 0x1130, 0x8109, 0xa946, 0x7148, - 0x8109, 0x714a, 0x00d8, 0x9006, 0xa806, 0xa84a, 0xa046, 0x2800, - 0xa802, 0x2900, 0xa006, 0x7046, 0x2001, 0x0002, 0x9080, 0x1ede, - 0x2005, 0xa846, 0x0058, 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce, - 0x009e, 0x008e, 0x001e, 0x012e, 0x00fe, 0x0005, 0x2c00, 0x9082, - 0x001b, 0x0002, 0x4ccd, 0x4ccd, 0x4ccf, 0x4ccd, 0x4ccd, 0x4ccd, - 0x4cd3, 0x4ccd, 0x4ccd, 0x4ccd, 0x4cd7, 0x4ccd, 0x4ccd, 0x4ccd, - 0x4cdb, 0x4ccd, 0x4ccd, 0x4ccd, 0x4cdf, 0x4ccd, 0x4ccd, 0x4ccd, - 0x4ce3, 0x4ccd, 0x4ccd, 0x4ccd, 0x4ce8, 0x080c, 0x0d79, 0xa276, - 0xa37a, 0xa47e, 0x0898, 0xa286, 0xa38a, 0xa48e, 0x0878, 0xa296, - 0xa39a, 0xa49e, 0x0858, 0xa2a6, 0xa3aa, 0xa4ae, 0x0838, 0xa2b6, - 0xa3ba, 0xa4be, 0x0818, 0xa2c6, 0xa3ca, 0xa4ce, 0x0804, 0x4ca6, - 0xa2d6, 0xa3da, 0xa4de, 0x0804, 0x4ca6, 0x00e6, 0x2071, 0x189e, - 0x7048, 0x9005, 0x0904, 0x4d7f, 0x0126, 0x2091, 0x8000, 0x0e04, - 0x4d7e, 0x00f6, 0x2079, 0x0000, 0x00c6, 0x0096, 0x0086, 0x0076, - 0x9006, 0x2038, 0x7040, 0x2048, 0x9005, 0x0500, 0xa948, 0x2105, - 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0d79, 0x2060, 0x001e, 0x8108, - 0x2105, 0x9005, 0xa94a, 0x1904, 0x4d81, 0xa804, 0x9005, 0x090c, - 0x0d79, 0x7042, 0x2938, 0x2040, 0xa003, 0x0000, 0x2001, 0x0002, - 0x9080, 0x1ede, 0x2005, 0xa04a, 0x0804, 0x4d81, 0x703c, 0x2060, - 0x2c14, 0x6304, 0x6408, 0x650c, 0x2200, 0x7836, 0x7833, 0x0012, - 0x7882, 0x2300, 0x7886, 0x2400, 0x788a, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x11f4, 0x87ff, 0x0118, 0x2748, - 0x080c, 0x107f, 0x7048, 0x8001, 0x704a, 0x9005, 0x1170, 0x7040, - 0x2048, 0x9005, 0x0128, 0x080c, 0x107f, 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, 0x0d79, 0x2048, 0xa800, 0x9005, 0x1de0, - 0x2900, 0x7042, 0x2001, 0x0002, 0x9080, 0x1ede, 0x2005, 0xa84a, - 0x0000, 0x007e, 0x008e, 0x009e, 0x00ce, 0x00fe, 0x012e, 0x00ee, - 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4da0, 0x4da0, 0x4da2, - 0x4da0, 0x4da0, 0x4da0, 0x4da7, 0x4da0, 0x4da0, 0x4da0, 0x4dac, - 0x4da0, 0x4da0, 0x4da0, 0x4db1, 0x4da0, 0x4da0, 0x4da0, 0x4db6, - 0x4da0, 0x4da0, 0x4da0, 0x4dbb, 0x4da0, 0x4da0, 0x4da0, 0x4dc0, - 0x080c, 0x0d79, 0xaa74, 0xab78, 0xac7c, 0x0804, 0x4d2c, 0xaa84, - 0xab88, 0xac8c, 0x0804, 0x4d2c, 0xaa94, 0xab98, 0xac9c, 0x0804, - 0x4d2c, 0xaaa4, 0xaba8, 0xacac, 0x0804, 0x4d2c, 0xaab4, 0xabb8, - 0xacbc, 0x0804, 0x4d2c, 0xaac4, 0xabc8, 0xaccc, 0x0804, 0x4d2c, - 0xaad4, 0xabd8, 0xacdc, 0x0804, 0x4d2c, 0x0016, 0x0026, 0x0036, - 0x00b6, 0x00c6, 0x2009, 0x007e, 0x080c, 0x6783, 0x2019, 0x0001, - 0xb85c, 0xd0ac, 0x0110, 0x2019, 0x0000, 0x2011, 0x801b, 0x080c, - 0x4c28, 0x00ce, 0x00be, 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, - 0x080c, 0x5820, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x4c28, - 0x002e, 0x0005, 0x81ff, 0x1904, 0x36a5, 0x0126, 0x2091, 0x8000, - 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x769d, 0x1158, - 0x080c, 0x799f, 0x080c, 0x6178, 0x9085, 0x0001, 0x080c, 0x76e1, - 0x080c, 0x75cc, 0x0010, 0x080c, 0x6033, 0x012e, 0x0804, 0x3673, - 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36a5, 0x080c, 0x5834, - 0x0120, 0x2009, 0x0007, 0x0804, 0x36a5, 0x080c, 0x6bc5, 0x0120, - 0x2009, 0x0008, 0x0804, 0x36a5, 0x7984, 0x080c, 0x6718, 0x1904, - 0x36a8, 0x080c, 0x4bfb, 0x0904, 0x36a8, 0x2b00, 0x7026, 0x080c, - 0x6bcd, 0x7888, 0x1170, 0x9084, 0x0005, 0x1158, 0x900e, 0x080c, - 0x6a74, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, - 0x3673, 0x080c, 0x4bc8, 0x0904, 0x36a5, 0x9006, 0xa866, 0xa832, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xce6c, 0x0904, 0x36a5, 0x7888, - 0xd094, 0x0118, 0xb8d4, 0xc08d, 0xb8d6, 0x7007, 0x0003, 0x701f, - 0x4e9b, 0x0005, 0x2061, 0x1800, 0x080c, 0x5834, 0x2009, 0x0007, - 0x1560, 0x080c, 0x6bc5, 0x0118, 0x2009, 0x0008, 0x0430, 0xa998, - 0x080c, 0x6718, 0x1530, 0x080c, 0x4bf9, 0x0518, 0x080c, 0x6bcd, - 0xa89c, 0x1168, 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, 0x6a74, - 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868, - 0xc0fc, 0xa86a, 0x080c, 0xce6c, 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, 0x9086, 0x0100, 0x7024, 0x2058, - 0x1110, 0x0804, 0x576e, 0x900e, 0x080c, 0x6a74, 0x1108, 0xc185, - 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x3673, 0x080c, 0x5834, - 0x0120, 0x2009, 0x0007, 0x0804, 0x36a5, 0x7f84, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x080c, 0x4bc8, 0x1120, 0x2009, 0x0002, 0x0804, - 0x36a5, 0x900e, 0x2130, 0x7126, 0x7132, 0xa860, 0x20e8, 0x7036, - 0xa85c, 0x9080, 0x0005, 0x702a, 0x20a0, 0x080c, 0x6783, 0x1904, - 0x4f44, 0x080c, 0x6bcd, 0x0138, 0x080c, 0x6bd5, 0x0120, 0x080c, - 0x6b6d, 0x1904, 0x4f44, 0xd794, 0x1110, 0xd784, 0x01a8, 0xb8c4, - 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x3400, 0xd794, 0x0198, - 0x20a9, 0x0008, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x20a9, - 0x0002, 0x080c, 0x49c7, 0x0080, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, - 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003, 0x2098, 0x20a0, - 0x3d00, 0x20e0, 0x080c, 0x49c7, 0x9186, 0x007e, 0x0170, 0x9186, - 0x0080, 0x0158, 0x080c, 0x6bcd, 0x90c2, 0x0006, 0x1210, 0xc1fd, - 0x0020, 0x080c, 0x6a74, 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, 0x49ba, 0x9c80, 0x0026, - 0x2098, 0xb8c4, 0x20e0, 0x20a9, 0x0002, 0x4003, 0xd794, 0x0110, - 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, 0x080c, 0xae80, 0x0118, - 0x9186, 0x0800, 0x0040, 0xd78c, 0x0120, 0x9186, 0x0800, 0x0170, - 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, 0x9686, 0x0020, - 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x4ecd, 0x86ff, 0x1120, - 0x7124, 0x810b, 0x0804, 0x3673, 0x7033, 0x0001, 0x7122, 0x7024, - 0x9600, 0x7026, 0x772e, 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, - 0xa67a, 0x7034, 0xa072, 0x7028, 0xa076, 0xa28e, 0xa392, 0xa496, - 0xa59a, 0x080c, 0x1142, 0x7007, 0x0002, 0x701f, 0x4f80, 0x0005, - 0x7030, 0x9005, 0x1180, 0x7120, 0x7028, 0x20a0, 0x772c, 0x9036, - 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, 0xa28c, 0xa390, 0xa494, - 0xa598, 0x0804, 0x4ecd, 0x7124, 0x810b, 0x0804, 0x3673, 0x2029, - 0x007e, 0x7984, 0x7a88, 0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, - 0x90e2, 0x0020, 0x0a04, 0x36a8, 0x9502, 0x0a04, 0x36a8, 0x9184, - 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36a8, 0x9502, 0x0a04, 0x36a8, - 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x36a8, 0x9502, - 0x0a04, 0x36a8, 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36a8, - 0x9502, 0x0a04, 0x36a8, 0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, - 0x0a04, 0x36a8, 0x9502, 0x0a04, 0x36a8, 0x9384, 0x00ff, 0x90e2, - 0x0020, 0x0a04, 0x36a8, 0x9502, 0x0a04, 0x36a8, 0x9484, 0xff00, - 0x8007, 0x90e2, 0x0020, 0x0a04, 0x36a8, 0x9502, 0x0a04, 0x36a8, - 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36a8, 0x9502, 0x0a04, - 0x36a8, 0x2061, 0x198a, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, - 0x3673, 0x080c, 0x4bc8, 0x0904, 0x36a5, 0x2009, 0x0016, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, - 0x4c11, 0x701f, 0x5004, 0x0005, 0x2001, 0x0138, 0x2003, 0x0000, - 0x00e6, 0x2071, 0x0300, 0x701c, 0xd0a4, 0x1de8, 0x00ee, 0x20a9, - 0x0016, 0x896e, 0x8d6e, 0x8d6f, 0x9d84, 0xffc0, 0x9080, 0x0019, - 0x2098, 0x9d84, 0x003f, 0x20e0, 0x2069, 0x1877, 0x20e9, 0x0001, - 0x2da0, 0x4003, 0x6800, 0x9005, 0x0904, 0x5085, 0x6804, 0x2008, - 0x918c, 0xfff8, 0x1904, 0x5085, 0x680c, 0x9005, 0x0904, 0x5085, - 0x9082, 0xff01, 0x1a04, 0x5085, 0x6810, 0x9082, 0x005c, 0x0a04, - 0x5085, 0x6824, 0x2008, 0x9082, 0x0008, 0x0a04, 0x5085, 0x9182, - 0x0400, 0x1a04, 0x5085, 0x0056, 0x2029, 0x0000, 0x080c, 0x8f0d, - 0x005e, 0x6944, 0x6820, 0x9102, 0x06c0, 0x6820, 0x9082, 0x0019, - 0x16a0, 0x6828, 0x6944, 0x810c, 0x9102, 0x0678, 0x6840, 0x9082, - 0x000f, 0x1658, 0x080c, 0x1066, 0x2900, 0x0904, 0x50a1, 0x684e, - 0x00e6, 0x2071, 0x1932, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8dc9, - 0x00be, 0x00ee, 0x0568, 0x080c, 0x8b11, 0x080c, 0x8b60, 0x11e0, - 0x6857, 0x0000, 0x00c6, 0x2061, 0x0100, 0x6104, 0x918d, 0x2000, - 0x6106, 0x6b10, 0x2061, 0x1a6f, 0x630e, 0x00ce, 0x080c, 0x27b9, - 0x2001, 0x0138, 0x2102, 0x0804, 0x3673, 0x080c, 0x27b9, 0x2001, - 0x0138, 0x2102, 0x0804, 0x36a8, 0x080c, 0x8b59, 0x00e6, 0x2071, - 0x1932, 0x080c, 0x8f8d, 0x080c, 0x8f9c, 0x080c, 0x8dac, 0x00ee, - 0x2001, 0x188a, 0x204c, 0x080c, 0x107f, 0x2001, 0x188a, 0x2003, - 0x0000, 0x080c, 0x27b9, 0x2001, 0x0138, 0x2102, 0x0804, 0x36a5, - 0x2001, 0x1926, 0x200c, 0x918e, 0x0000, 0x0904, 0x5106, 0x080c, - 0x8da7, 0x0904, 0x5106, 0x2001, 0x0101, 0x200c, 0x918c, 0xdfff, - 0x2102, 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, 0x2071, 0x0300, - 0x701c, 0xd0a4, 0x1de8, 0x00ee, 0x080c, 0x8dac, 0x0126, 0x2091, - 0x8000, 0x2001, 0x0035, 0x080c, 0x16ad, 0x012e, 0x00c6, 0x2061, - 0x193e, 0x6004, 0x6100, 0x9106, 0x1de0, 0x00ce, 0x080c, 0x27b9, - 0x2001, 0x0138, 0x2102, 0x00e6, 0x00f6, 0x2071, 0x1925, 0x080c, - 0x8ce6, 0x0120, 0x2f00, 0x080c, 0x8d72, 0x0cc8, 0x00fe, 0x00ee, - 0x0126, 0x2091, 0x8000, 0x2001, 0x188a, 0x200c, 0x81ff, 0x0138, - 0x2148, 0x080c, 0x107f, 0x2001, 0x188a, 0x2003, 0x0000, 0x2001, - 0x183e, 0x2003, 0x0020, 0x080c, 0x8b59, 0x00e6, 0x2071, 0x1932, - 0x080c, 0x8f8d, 0x080c, 0x8f9c, 0x00ee, 0x012e, 0x0804, 0x3673, - 0x0006, 0x080c, 0x5820, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x080c, - 0x5824, 0xd0bc, 0x000e, 0x0005, 0x6174, 0x7a84, 0x6300, 0x82ff, - 0x1118, 0x7986, 0x0804, 0x3673, 0x83ff, 0x1904, 0x36a8, 0x2001, - 0xfff0, 0x9200, 0x1a04, 0x36a8, 0x2019, 0xffff, 0x6078, 0x9302, - 0x9200, 0x0a04, 0x36a8, 0x7986, 0x6276, 0x0804, 0x3673, 0x080c, - 0x5834, 0x1904, 0x36a5, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, 0x080c, - 0x4bc8, 0x0904, 0x36a5, 0x900e, 0x901e, 0x7326, 0x7332, 0xa860, + 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, 0x6bcd, 0x0118, 0x080c, - 0x6bd5, 0x1148, 0x20a9, 0x0001, 0xb814, 0x4004, 0xb810, 0x4004, + 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, 0x9364, 0x2208, 0x0804, 0x3673, 0x7033, 0x0001, + 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, 0x1142, 0x7007, 0x0002, 0x701f, 0x5189, + 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, 0x5147, 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, - 0x9364, 0x2208, 0x0804, 0x3673, 0x00f6, 0x00e6, 0x080c, 0x5834, - 0x2009, 0x0007, 0x1904, 0x521c, 0x2071, 0x189e, 0x745c, 0x84ff, - 0x2009, 0x000e, 0x1904, 0x521c, 0xac9c, 0xad98, 0xaea4, 0xafa0, - 0x0096, 0x080c, 0x1066, 0x2009, 0x0002, 0x0904, 0x521c, 0x2900, + 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, 0x6bcd, 0x0118, 0x080c, 0x6bd5, 0x1148, 0xb814, + 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, 0x9364, + 0x83ff, 0x11c0, 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x955b, 0x2208, 0x009e, 0xa897, 0x4000, 0xa99a, 0x715c, 0x81ff, 0x090c, - 0x0d79, 0x2148, 0x080c, 0x107f, 0x9006, 0x705e, 0x918d, 0x0001, + 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, 0x5228, 0x000e, 0xa0a2, - 0x080c, 0x1142, 0x9006, 0x0048, 0x009e, 0xa897, 0x4005, 0xa99a, + 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, 0x0d79, 0x00e6, 0x2071, 0x189e, + 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, 0x9364, 0xaa9a, 0x715c, 0x81ff, - 0x090c, 0x0d79, 0x2148, 0x080c, 0x107f, 0x705f, 0x0000, 0xa0a0, - 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x6f11, 0x012e, 0xa09f, + 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, 0x6bcd, 0x0118, 0x080c, 0x6bd5, + 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, 0x0d79, 0x2148, 0x080c, 0x107f, + 0x4000, 0x715c, 0x81ff, 0x090c, 0x0d85, 0x2148, 0x080c, 0x108b, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0xa0a0, 0x2048, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6f11, 0x012e, 0xa09f, 0x0000, 0xa0a3, + 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x0070, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056, - 0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x1142, 0x9006, + 0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x114e, 0x9006, 0x00ee, 0x0005, 0x0096, 0xa88c, 0x90be, 0x7000, 0x0148, 0x90be, - 0x7100, 0x0130, 0x90be, 0x7200, 0x0118, 0x009e, 0x0804, 0x36a8, - 0xa884, 0xa988, 0x080c, 0x26a1, 0x1518, 0x080c, 0x6718, 0x1500, - 0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c, 0x4bc8, 0x01c8, 0x080c, - 0x4bc8, 0x01b0, 0x009e, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0xa823, 0x0000, 0xa804, 0x2048, 0x080c, 0xcde5, 0x1120, 0x2009, - 0x0003, 0x0804, 0x36a5, 0x7007, 0x0003, 0x701f, 0x52f5, 0x0005, - 0x009e, 0x2009, 0x0002, 0x0804, 0x36a5, 0x7124, 0x080c, 0x3404, - 0xa820, 0x9086, 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, 0x36a5, + 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, - 0x0fca, 0xaa6c, 0xab70, 0xac74, 0xad78, 0x2061, 0x18b8, 0x2c44, + 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, 0x4c14, 0x97c6, 0x7200, 0x11b8, 0x96c2, 0x0054, + 0x007e, 0x0804, 0x4c8d, 0x97c6, 0x7200, 0x11b8, 0x96c2, 0x0054, 0x02a0, 0x000e, 0x007e, 0x2061, 0x18b8, 0x2c44, 0xa076, 0xa772, - 0xa07b, 0x002a, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x1142, - 0x7007, 0x0002, 0x701f, 0x5351, 0x0005, 0x000e, 0x007e, 0x0804, - 0x36a8, 0x7020, 0x2048, 0xa804, 0x2048, 0xa804, 0x2048, 0x8906, + 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, 0x0fca, + 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, 0x0fd6, 0x2100, 0x2238, 0x2061, 0x18b8, 0x2c44, 0xa28c, 0xa390, 0xa494, - 0xa598, 0x2009, 0x002a, 0x0804, 0x4c14, 0x81ff, 0x1904, 0x36a5, - 0x798c, 0x2001, 0x197f, 0x918c, 0x8000, 0x2102, 0x080c, 0x4bdf, - 0x0904, 0x36a8, 0x080c, 0x6bcd, 0x0120, 0x080c, 0x6bd5, 0x1904, - 0x36a8, 0x080c, 0x684a, 0x0904, 0x36a5, 0x0126, 0x2091, 0x8000, - 0x080c, 0x69e1, 0x012e, 0x0904, 0x36a5, 0x2001, 0x197f, 0x2004, - 0xd0fc, 0x1904, 0x3673, 0x0804, 0x4661, 0xa9a0, 0x2001, 0x197f, - 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4bec, 0x01a0, 0x080c, - 0x6bcd, 0x0118, 0x080c, 0x6bd5, 0x1170, 0x080c, 0x684a, 0x2009, - 0x0002, 0x0128, 0x080c, 0x69e1, 0x1170, 0x2009, 0x0003, 0xa897, + 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, 0x197f, 0x2004, - 0xd0fc, 0x1128, 0x080c, 0x5828, 0x0110, 0x9006, 0x0018, 0x900e, + 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, 0x45d6, 0x080c, 0x4bfb, 0x0904, 0x36a8, 0x080c, - 0x4bc8, 0x1120, 0x2009, 0x0002, 0x0804, 0x36a5, 0x080c, 0x6bcd, + 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, 0x5820, - 0xd0b4, 0x0904, 0x4610, 0x7884, 0x908e, 0x007e, 0x0904, 0x4610, - 0x908e, 0x007f, 0x0904, 0x4610, 0x908e, 0x0080, 0x0904, 0x4610, - 0xb800, 0xd08c, 0x1904, 0x4610, 0xa867, 0x0000, 0xa868, 0xc0fd, - 0xa86a, 0x080c, 0xce04, 0x1120, 0x2009, 0x0003, 0x0804, 0x36a5, - 0x7007, 0x0003, 0x701f, 0x541d, 0x0005, 0x080c, 0x4bfb, 0x0904, - 0x36a8, 0x0804, 0x4610, 0x080c, 0x3463, 0x0108, 0x0005, 0x2009, - 0x1834, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36a5, - 0x080c, 0x5834, 0x0120, 0x2009, 0x0007, 0x0804, 0x36a5, 0x080c, - 0x6bc5, 0x0120, 0x2009, 0x0008, 0x0804, 0x36a5, 0xb89c, 0xd0a4, - 0x1118, 0xd0ac, 0x1904, 0x4610, 0x9006, 0xa866, 0xa832, 0xa868, - 0xc0fd, 0xa86a, 0x080c, 0xce6c, 0x1120, 0x2009, 0x0003, 0x0804, - 0x36a5, 0x7007, 0x0003, 0x701f, 0x5456, 0x0005, 0xa830, 0x9086, - 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x576e, 0x080c, 0x4bfb, - 0x0904, 0x36a8, 0x0804, 0x53ef, 0x81ff, 0x2009, 0x0001, 0x1904, - 0x36a5, 0x080c, 0x5834, 0x2009, 0x0007, 0x1904, 0x36a5, 0x080c, - 0x6bc5, 0x0120, 0x2009, 0x0008, 0x0804, 0x36a5, 0x080c, 0x4bfb, - 0x0904, 0x36a8, 0x080c, 0x6bcd, 0x2009, 0x0009, 0x1904, 0x36a5, - 0x080c, 0x4bc8, 0x2009, 0x0002, 0x0904, 0x36a5, 0x9006, 0xa866, + 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, 0x36a8, 0xc0e5, 0xa952, - 0xa956, 0xa83e, 0x080c, 0xd0cf, 0x2009, 0x0003, 0x0904, 0x36a5, - 0x7007, 0x0003, 0x701f, 0x54ad, 0x0005, 0xa830, 0x9086, 0x0100, - 0x2009, 0x0004, 0x0904, 0x36a5, 0x0804, 0x3673, 0x7aa8, 0x9284, - 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, 0x5834, 0x1188, 0x2009, - 0x0014, 0x0804, 0x36a5, 0xd2dc, 0x1578, 0x81ff, 0x2009, 0x0001, - 0x1904, 0x36a5, 0x080c, 0x5834, 0x2009, 0x0007, 0x1904, 0x36a5, - 0xd2f4, 0x0138, 0x9284, 0x5000, 0xc0d5, 0x080c, 0x57fa, 0x0804, - 0x3673, 0xd2fc, 0x0160, 0x080c, 0x4bfb, 0x0904, 0x36a8, 0x7984, - 0x9284, 0x9000, 0xc0d5, 0x080c, 0x57c9, 0x0804, 0x3673, 0x080c, - 0x4bfb, 0x0904, 0x36a8, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x2009, 0x0009, 0x1904, 0x559c, 0x080c, 0x4bc8, 0x2009, 0x0002, - 0x0904, 0x559c, 0xa85c, 0x9080, 0x001b, 0xaf60, 0x2009, 0x0008, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4c11, 0x701f, 0x5509, + 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, 0x36a8, 0xa866, 0xa832, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x4bfb, 0x1110, 0x0804, 0x36a8, - 0x2009, 0x0043, 0x080c, 0xd13b, 0x2009, 0x0003, 0x0904, 0x559c, - 0x7007, 0x0003, 0x701f, 0x552d, 0x0005, 0xa830, 0x9086, 0x0100, - 0x2009, 0x0004, 0x0904, 0x559c, 0x7984, 0x7aa8, 0x9284, 0x1000, - 0xc0d5, 0x080c, 0x57c9, 0x0804, 0x3673, 0x00c6, 0xaab0, 0x9284, - 0xc000, 0x0148, 0xd2ec, 0x0170, 0x080c, 0x5834, 0x1158, 0x2009, - 0x0014, 0x0804, 0x558b, 0x2061, 0x1800, 0x080c, 0x5834, 0x2009, + 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, - 0x57fa, 0x0058, 0xd2fc, 0x0180, 0x080c, 0x4bf9, 0x0590, 0xa998, - 0x9284, 0x9000, 0xc0d5, 0x080c, 0x57c9, 0xa87b, 0x0000, 0xa883, - 0x0000, 0xa897, 0x4000, 0x0438, 0x080c, 0x4bf9, 0x0510, 0x080c, - 0x6bcd, 0x2009, 0x0009, 0x11b8, 0xa8c4, 0x9086, 0x0500, 0x11c8, + 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, - 0x4bf9, 0x1108, 0x0070, 0x2009, 0x004b, 0x080c, 0xd13b, 0x2009, + 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, 0x36a5, - 0x0016, 0x7984, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x57c9, 0x001e, - 0x1904, 0x36a5, 0x0804, 0x3673, 0x00f6, 0x2d78, 0xaab0, 0x0021, + 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, 0x57c9, 0x001e, 0x9085, 0x0001, - 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36a5, 0x080c, - 0x5834, 0x0120, 0x2009, 0x0007, 0x0804, 0x36a5, 0x7984, 0x7ea8, - 0x96b4, 0x00ff, 0x080c, 0x6783, 0x1904, 0x36a8, 0x9186, 0x007f, - 0x0138, 0x080c, 0x6bcd, 0x0120, 0x2009, 0x0009, 0x0804, 0x36a5, - 0x080c, 0x4bc8, 0x1120, 0x2009, 0x0002, 0x0804, 0x36a5, 0xa867, + 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, 0xce1e, 0x1120, 0x2009, 0x0003, 0x0804, 0x36a5, 0x7007, - 0x0003, 0x701f, 0x55fc, 0x0005, 0xa808, 0x8007, 0x9086, 0x0100, - 0x1120, 0x2009, 0x0004, 0x0804, 0x36a5, 0xa8e0, 0xa866, 0xa810, + 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, 0x4c14, 0x080c, 0x4bc8, 0x1120, 0x2009, 0x0002, - 0x0804, 0x36a5, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, - 0x82ff, 0x1118, 0x7023, 0x19b5, 0x0040, 0x92c6, 0x0001, 0x1118, - 0x7023, 0x19cf, 0x0010, 0x0804, 0x36a8, 0x2009, 0x001a, 0x7a8c, + 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, - 0x4c11, 0x701f, 0x564c, 0x0005, 0x2001, 0x182e, 0x2003, 0x0001, + 0x4c8a, 0x701f, 0x566c, 0x0005, 0x2001, 0x182e, 0x2003, 0x0001, 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, 0x20e0, 0x20a9, 0x001a, - 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, 0x0804, 0x3673, 0x080c, - 0x4bc8, 0x1120, 0x2009, 0x0002, 0x0804, 0x36a5, 0x7984, 0x9194, - 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x2099, 0x19b5, - 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, 0x19cf, 0x0010, 0x0804, - 0x36a8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0xa860, 0x20e8, 0x20a9, + 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, 0x4c14, - 0x7884, 0x908a, 0x1000, 0x1a04, 0x36a8, 0x0126, 0x2091, 0x8000, - 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, 0x1a05, 0x614a, - 0x00ce, 0x012e, 0x0804, 0x3673, 0x00c6, 0x080c, 0x769d, 0x1160, - 0x080c, 0x799f, 0x080c, 0x6178, 0x9085, 0x0001, 0x080c, 0x76e1, - 0x080c, 0x75cc, 0x080c, 0x0d79, 0x2061, 0x1800, 0x6030, 0xc09d, - 0x6032, 0x080c, 0x6033, 0x00ce, 0x0005, 0x00c6, 0x2001, 0x1800, - 0x2004, 0x908e, 0x0000, 0x0904, 0x36a5, 0x7884, 0x9005, 0x0188, - 0x7888, 0x2061, 0x199d, 0x2c0c, 0x2062, 0x080c, 0x2a70, 0x01a0, - 0x080c, 0x2a78, 0x0188, 0x080c, 0x2a80, 0x0170, 0x2162, 0x0804, - 0x36a8, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, + 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, 0xaaf7, 0x0026, - 0x2011, 0x0003, 0x080c, 0xa426, 0x2011, 0x0002, 0x080c, 0xa430, - 0x002e, 0x080c, 0xa311, 0x0036, 0x901e, 0x080c, 0xa391, 0x003e, - 0x080c, 0xab13, 0x60e3, 0x0000, 0x080c, 0xebe8, 0x080c, 0xec03, - 0x9085, 0x0001, 0x080c, 0x76e1, 0x9006, 0x080c, 0x2aa2, 0x2001, - 0x1800, 0x2003, 0x0004, 0x2001, 0x19a9, 0x2003, 0x0000, 0x0026, - 0x2011, 0x0008, 0x080c, 0x2adc, 0x002e, 0x00ce, 0x0804, 0x3673, - 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36a5, 0x080c, 0x5834, - 0x0120, 0x2009, 0x0007, 0x0804, 0x36a5, 0x7984, 0x7ea8, 0x96b4, - 0x00ff, 0x080c, 0x6783, 0x1904, 0x36a8, 0x9186, 0x007f, 0x0138, - 0x080c, 0x6bcd, 0x0120, 0x2009, 0x0009, 0x0804, 0x36a5, 0x080c, - 0x4bc8, 0x1120, 0x2009, 0x0002, 0x0804, 0x36a5, 0xa867, 0x0000, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xce21, 0x1120, 0x2009, 0x0003, - 0x0804, 0x36a5, 0x7007, 0x0003, 0x701f, 0x5757, 0x0005, 0xa830, - 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x36a5, 0xa8e0, + 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, 0x4c14, 0xa898, 0x9086, - 0x000d, 0x1904, 0x36a5, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x577b, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, + 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, 0x4c04, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11f4, + 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, 0x1a05, 0x7984, 0x615a, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x1a04, 0x7984, 0x615a, 0x6156, 0x605f, 0x0000, 0x6053, 0x0009, 0x7898, 0x6072, 0x789c, - 0x606e, 0x7888, 0x606a, 0x788c, 0x6066, 0x2001, 0x1a15, 0x2044, - 0x2001, 0x1a1c, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, 0xa07f, + 0x606e, 0x7888, 0x606a, 0x788c, 0x6066, 0x2001, 0x1a14, 0x2044, + 0x2001, 0x1a1b, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, 0xa07f, 0x0002, 0xa06b, 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, 0x0804, - 0x3673, 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, 0xc000, + 0x368d, 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, 0xc000, 0x0198, 0x0006, 0xd0d4, 0x0160, 0x0036, 0x2019, 0x0029, 0x080c, - 0xaaf7, 0x0106, 0x080c, 0x3428, 0x010e, 0x090c, 0xab13, 0x003e, - 0x080c, 0xcc80, 0x000e, 0x1198, 0xd0e4, 0x0160, 0x9180, 0x1000, - 0x2004, 0x905d, 0x0160, 0x080c, 0x6192, 0x080c, 0xae80, 0x0110, + 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, 0x57c9, - 0x002e, 0x001e, 0x8108, 0x1f04, 0x5802, 0x015e, 0x012e, 0x0005, + 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, 0x36a8, - 0x9182, 0x0081, 0x1a04, 0x36a8, 0x810c, 0x0016, 0x080c, 0x4bc8, - 0x0170, 0x080c, 0x0f55, 0x2100, 0x2238, 0x7d84, 0x7c88, 0x7b8c, - 0x7a90, 0x001e, 0x080c, 0x4c11, 0x701f, 0x5864, 0x0005, 0x001e, - 0x2009, 0x0002, 0x0804, 0x36a5, 0x2079, 0x0000, 0x7d94, 0x7c98, + 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, 0x4c14, 0x701f, 0x5878, 0x0005, + 0xa074, 0x2071, 0x189e, 0x080c, 0x4c8d, 0x701f, 0x5898, 0x0005, 0x2061, 0x18b8, 0x2c44, 0x0016, 0x0026, 0xa270, 0xa174, 0x080c, - 0x0f5d, 0x002e, 0x001e, 0x080c, 0x100a, 0x9006, 0xa802, 0xa806, - 0x0804, 0x3673, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, + 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, - 0x5a33, 0x0068, 0xd08c, 0x0118, 0x080c, 0x593c, 0x0040, 0xd094, - 0x0118, 0x080c, 0x590c, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, + 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, 0x0006, 0x7098, 0x9005, 0x000e, 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, 0x60f4, 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, - 0x5fd6, 0x080c, 0x88f6, 0x0005, 0x2001, 0x1869, 0x2004, 0xd08c, - 0x0110, 0x705f, 0xffff, 0x7088, 0x9005, 0x1528, 0x2011, 0x5fd6, - 0x080c, 0x882c, 0x6040, 0x9094, 0x0010, 0x9285, 0x0020, 0x6042, - 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x5922, 0x6242, - 0x709b, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, 0x0080, 0x6042, - 0x6242, 0x0048, 0x6242, 0x709b, 0x0000, 0x708f, 0x0000, 0x9006, - 0x080c, 0x617d, 0x0000, 0x0005, 0x708c, 0x908a, 0x0003, 0x1a0c, - 0x0d79, 0x000b, 0x0005, 0x5946, 0x5997, 0x5a32, 0x00f6, 0x0016, - 0x6900, 0x918c, 0x0800, 0x708f, 0x0001, 0x2001, 0x015d, 0x2003, - 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, 0x9084, 0x00fc, - 0x0120, 0x1f04, 0x5955, 0x080c, 0x0d79, 0x68a0, 0x68a2, 0x689c, - 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, 0x1600, 0x6902, 0x001e, - 0x6837, 0x0020, 0x080c, 0x6159, 0x2079, 0x1d00, 0x7833, 0x1101, - 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0001, - 0x20a1, 0x1d0e, 0x20a9, 0x0004, 0x4003, 0x080c, 0xa8ec, 0x20e1, - 0x0001, 0x2099, 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, - 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, 0x6007, - 0x00fe, 0x9006, 0x7092, 0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, - 0x7090, 0x7093, 0x0000, 0x9025, 0x0904, 0x5a0f, 0x6020, 0xd0b4, - 0x1904, 0x5a0d, 0x71a0, 0x81ff, 0x0904, 0x59fb, 0x9486, 0x000c, - 0x1904, 0x5a08, 0x9480, 0x0018, 0x8004, 0x20a8, 0x080c, 0x6152, - 0x2011, 0x0260, 0x2019, 0x1d00, 0x220c, 0x2304, 0x9106, 0x11e8, - 0x8210, 0x8318, 0x1f04, 0x59b4, 0x6043, 0x0004, 0x2061, 0x0140, - 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, - 0x708f, 0x0002, 0x709b, 0x0002, 0x2009, 0x07d0, 0x2011, 0x5fdd, - 0x080c, 0x88f6, 0x080c, 0x6159, 0x04c0, 0x080c, 0x6152, 0x2079, - 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, 0x7834, 0x9005, 0x1540, - 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005, 0x0190, 0x080c, - 0x6152, 0x2011, 0x026e, 0x2019, 0x1805, 0x20a9, 0x0004, 0x220c, - 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318, 0x1f04, 0x59ef, - 0x0078, 0x70a3, 0x0000, 0x080c, 0x6152, 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, 0xa8ec, - 0x20e1, 0x0001, 0x2099, 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, - 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, 0x19f6, 0x2013, - 0x0000, 0x7093, 0x0000, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, - 0xa08e, 0x08d8, 0x0005, 0x7098, 0x908a, 0x001d, 0x1a0c, 0x0d79, - 0x000b, 0x0005, 0x5a64, 0x5a77, 0x5aa0, 0x5ac0, 0x5ae6, 0x5b15, - 0x5b3b, 0x5b73, 0x5b99, 0x5bc7, 0x5c02, 0x5c3a, 0x5c58, 0x5c83, - 0x5ca5, 0x5cc0, 0x5cca, 0x5cfe, 0x5d24, 0x5d53, 0x5d79, 0x5db1, - 0x5df5, 0x5e32, 0x5e53, 0x5eac, 0x5ece, 0x5efc, 0x5efc, 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, 0x5fdd, 0x080c, 0x88f6, 0x0005, 0x00f6, - 0x7090, 0x9086, 0x0014, 0x1510, 0x6042, 0x6020, 0xd0b4, 0x11f0, - 0x080c, 0x6152, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, - 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, - 0x1110, 0x70c7, 0x0001, 0x2011, 0x5fdd, 0x080c, 0x882c, 0x709b, - 0x0010, 0x080c, 0x5cca, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, - 0x00f6, 0x709b, 0x0003, 0x6043, 0x0004, 0x2011, 0x5fdd, 0x080c, - 0x882c, 0x080c, 0x60d6, 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, - 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, 0x200b, 0x0000, 0x8108, - 0x1f04, 0x5ab5, 0x60c3, 0x0014, 0x080c, 0x6007, 0x00fe, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5fdd, 0x080c, 0x882c, - 0x9086, 0x0014, 0x11b8, 0x080c, 0x6152, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0004, - 0x0029, 0x0010, 0x080c, 0x612e, 0x00fe, 0x0005, 0x00f6, 0x709b, - 0x0005, 0x080c, 0x60d6, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, - 0x0000, 0x080c, 0x6152, 0x080c, 0x6135, 0x1170, 0x7084, 0x9005, - 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, - 0x5f8a, 0x0168, 0x080c, 0x610b, 0x20a9, 0x0008, 0x20e1, 0x0000, - 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, - 0x0014, 0x080c, 0x6007, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x0500, 0x2011, 0x5fdd, 0x080c, 0x882c, 0x9086, 0x0014, 0x11b8, - 0x080c, 0x6152, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, + 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, 0x0006, 0x0029, 0x0010, 0x080c, - 0x612e, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0007, 0x080c, 0x60d6, - 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x6152, - 0x080c, 0x6135, 0x11b8, 0x7084, 0x9005, 0x11a0, 0x7164, 0x9186, - 0xffff, 0x0180, 0x9180, 0x3474, 0x200d, 0x918c, 0xff00, 0x810f, - 0x2011, 0x0008, 0x080c, 0x5f8a, 0x0180, 0x080c, 0x510e, 0x0110, - 0x080c, 0x270a, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, - 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, - 0x6007, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, - 0x5fdd, 0x080c, 0x882c, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6152, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, - 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, - 0x0001, 0x709b, 0x0008, 0x0029, 0x0010, 0x080c, 0x612e, 0x00fe, - 0x0005, 0x00f6, 0x709b, 0x0009, 0x080c, 0x60d6, 0x2079, 0x0240, - 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, 0x6135, 0x1150, 0x7084, - 0x9005, 0x1138, 0x080c, 0x5efd, 0x1188, 0x9085, 0x0001, 0x080c, - 0x270a, 0x20a9, 0x0008, 0x080c, 0x6152, 0x20e1, 0x0000, 0x2099, - 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, - 0x080c, 0x6007, 0x0010, 0x080c, 0x5a57, 0x00fe, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x05a8, 0x2011, 0x5fdd, 0x080c, 0x882c, 0x9086, - 0x0014, 0x1560, 0x080c, 0x6152, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, + 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, 0x000a, 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, - 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x7097, - 0x0000, 0x709b, 0x000e, 0x080c, 0x5ca5, 0x0010, 0x080c, 0x612e, - 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000b, 0x2011, 0x1d0e, 0x20e9, - 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x4304, 0x080c, - 0x60d6, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, - 0x6135, 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, 0x5c27, 0x60c3, 0x0084, 0x080c, 0x6007, - 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01c0, 0x2011, 0x5fdd, - 0x080c, 0x882c, 0x9086, 0x0084, 0x1178, 0x080c, 0x6152, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834, 0x9005, 0x1120, - 0x709b, 0x000c, 0x0029, 0x0010, 0x080c, 0x612e, 0x00fe, 0x0005, - 0x00f6, 0x709b, 0x000d, 0x080c, 0x60d6, 0x2079, 0x0240, 0x7833, - 0x1107, 0x7837, 0x0000, 0x080c, 0x6152, 0x20a9, 0x0040, 0x2011, - 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, - 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, - 0x6816, 0x2011, 0x0260, 0x1f04, 0x5c6b, 0x60c3, 0x0084, 0x080c, - 0x6007, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01e0, 0x2011, - 0x5fdd, 0x080c, 0x882c, 0x9086, 0x0084, 0x1198, 0x080c, 0x6152, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, - 0x1140, 0x7097, 0x0001, 0x080c, 0x60a8, 0x709b, 0x000e, 0x0029, - 0x0010, 0x080c, 0x612e, 0x00fe, 0x0005, 0x918d, 0x0001, 0x080c, - 0x617d, 0x709b, 0x000f, 0x7093, 0x0000, 0x2061, 0x0140, 0x605b, - 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, 0x0005, 0x6043, - 0x0004, 0x2009, 0x07d0, 0x2011, 0x5fdd, 0x080c, 0x8820, 0x0005, - 0x7090, 0x9005, 0x0130, 0x2011, 0x5fdd, 0x080c, 0x882c, 0x709b, - 0x0000, 0x0005, 0x709b, 0x0011, 0x080c, 0xa8ec, 0x080c, 0x6152, - 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, - 0x7490, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, - 0x20a8, 0x4003, 0x080c, 0x6135, 0x11a0, 0x717c, 0x81ff, 0x0188, - 0x900e, 0x7080, 0x9084, 0x00ff, 0x0160, 0x080c, 0x26a1, 0x9186, - 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, 0x2011, 0x0008, 0x080c, - 0x5f8a, 0x60c3, 0x0014, 0x080c, 0x6007, 0x0005, 0x00f6, 0x7090, - 0x9005, 0x0500, 0x2011, 0x5fdd, 0x080c, 0x882c, 0x9086, 0x0014, - 0x11b8, 0x080c, 0x6152, 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, - 0x60e4, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, - 0x6152, 0x080c, 0x6135, 0x1170, 0x7084, 0x9005, 0x1158, 0x715c, - 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5f8a, 0x0168, - 0x080c, 0x610b, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, - 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, - 0x6007, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, - 0x5fdd, 0x080c, 0x882c, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6152, - 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, 0x60e4, 0x2079, 0x0240, - 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x6152, 0x080c, 0x6135, - 0x11b8, 0x7084, 0x9005, 0x11a0, 0x7164, 0x9186, 0xffff, 0x0180, - 0x9180, 0x3474, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, - 0x080c, 0x5f8a, 0x0180, 0x080c, 0x510e, 0x0110, 0x080c, 0x270a, - 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x6007, 0x00fe, - 0x0005, 0x00f6, 0x7090, 0x9005, 0x05f0, 0x2011, 0x5fdd, 0x080c, - 0x882c, 0x9086, 0x0014, 0x15a8, 0x080c, 0x6152, 0x2079, 0x0260, - 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, 0x9084, 0x0100, 0x2011, - 0x0100, 0x921e, 0x1168, 0x9085, 0x0001, 0x080c, 0x617d, 0x7a38, - 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x0080, - 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, - 0x70c7, 0x0001, 0x9085, 0x0001, 0x080c, 0x617d, 0x7097, 0x0000, - 0x7a38, 0xd2f4, 0x0110, 0x70df, 0x0008, 0x709b, 0x0016, 0x0029, - 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x080c, 0xa8ec, 0x080c, - 0x6152, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, - 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, 0x026d, 0x2204, 0x9084, - 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, 0x026e, 0x709b, 0x0017, - 0x080c, 0x6135, 0x1150, 0x7084, 0x9005, 0x1138, 0x080c, 0x5efd, - 0x1188, 0x9085, 0x0001, 0x080c, 0x270a, 0x20a9, 0x0008, 0x080c, - 0x6152, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x6007, 0x0010, 0x080c, - 0x5a57, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01d8, 0x2011, 0x5fdd, - 0x080c, 0x882c, 0x9086, 0x0084, 0x1190, 0x080c, 0x6152, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, 0x7834, 0x9005, 0x1138, - 0x9006, 0x080c, 0x617d, 0x709b, 0x0018, 0x0029, 0x0010, 0x7093, - 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0019, 0x080c, 0x60e4, - 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x6152, - 0x2009, 0x026e, 0x2039, 0x1d0e, 0x20a9, 0x0040, 0x213e, 0x8738, - 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, 0x8000, 0x6816, 0x2009, - 0x0260, 0x1f04, 0x5e66, 0x2039, 0x1d0e, 0x080c, 0x6135, 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, 0x5e99, 0x60c3, 0x0084, - 0x080c, 0x6007, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01e0, - 0x2011, 0x5fdd, 0x080c, 0x882c, 0x9086, 0x0084, 0x1198, 0x080c, - 0x6152, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, - 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, 0x60a8, 0x709b, 0x001a, - 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x9085, 0x0001, - 0x080c, 0x617d, 0x709b, 0x001b, 0x080c, 0xa8ec, 0x080c, 0x6152, - 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, 0x5ee5, 0x60c3, - 0x0084, 0x080c, 0x6007, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, - 0x1848, 0x252c, 0x20a9, 0x0008, 0x2041, 0x1d0e, 0x20e9, 0x0001, - 0x28a0, 0x080c, 0x6152, 0x20e1, 0x0000, 0x2099, 0x026e, 0x4003, - 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108, 0x9016, 0x2800, - 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, - 0x0008, 0x8211, 0x1f04, 0x5f17, 0x0804, 0x5f86, 0x82ff, 0x1160, - 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, 0x0020, 0x91a6, 0x3fff, - 0x0904, 0x5f86, 0x918d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, - 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, - 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, - 0x1f04, 0x5f3d, 0x04d8, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, - 0x1f04, 0x5f4f, 0x2328, 0x8529, 0x92be, 0x0007, 0x0158, 0x0006, - 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, 0x27a8, 0x95a8, 0x0010, - 0x1f04, 0x5f5e, 0x755e, 0x95c8, 0x3474, 0x292d, 0x95ac, 0x00ff, - 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x26ea, 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, 0x3474, 0x242d, 0x95ac, 0x00ff, 0x7582, 0x6532, - 0x6536, 0x0016, 0x2508, 0x080c, 0x26ea, 0x001e, 0x60e7, 0x0000, - 0x65ea, 0x7087, 0x0001, 0x9084, 0x0000, 0x0005, 0x00e6, 0x2071, - 0x1800, 0x708b, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, - 0x0100, 0x2071, 0x0140, 0x080c, 0x6097, 0x080c, 0xa09b, 0x7004, - 0x9084, 0x4000, 0x0110, 0x080c, 0x2ab2, 0x0126, 0x2091, 0x8000, - 0x2071, 0x1826, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, - 0x00f7, 0x080c, 0x60f4, 0x001e, 0x9094, 0x0010, 0x9285, 0x0080, - 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x8000, 0x080c, 0x2a11, 0x0228, 0x2011, 0x0101, 0x2204, - 0xc0c5, 0x2012, 0x2011, 0x19f6, 0x2013, 0x0000, 0x7093, 0x0000, - 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0xa08e, 0x6144, - 0xd184, 0x0120, 0x7198, 0x918d, 0x2000, 0x0018, 0x718c, 0x918d, - 0x1000, 0x2011, 0x199a, 0x2112, 0x2009, 0x07d0, 0x2011, 0x5fdd, - 0x080c, 0x88f6, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0xaaf7, 0x080c, 0xae87, 0x080c, 0xab13, 0x2009, - 0x00f7, 0x080c, 0x60f4, 0x2061, 0x1a05, 0x900e, 0x611a, 0x611e, - 0x617a, 0x617e, 0x2061, 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, - 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x199a, 0x200b, 0x0000, - 0x2009, 0x002d, 0x2011, 0x6063, 0x080c, 0x8820, 0x012e, 0x00ce, - 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, - 0x0471, 0x2071, 0x0100, 0x080c, 0xa09b, 0x2071, 0x0140, 0x7004, - 0x9084, 0x4000, 0x0110, 0x080c, 0x2ab2, 0x080c, 0x76a5, 0x0188, - 0x080c, 0x76c0, 0x1170, 0x080c, 0x79a9, 0x0016, 0x080c, 0x27b9, - 0x2001, 0x196e, 0x2102, 0x001e, 0x080c, 0x79a4, 0x080c, 0x75cc, - 0x0050, 0x2009, 0x0001, 0x080c, 0x2a8e, 0x2001, 0x0001, 0x080c, - 0x2646, 0x080c, 0x6033, 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, - 0x180e, 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, - 0x2001, 0x199a, 0x201c, 0x080c, 0x4c28, 0x003e, 0x002e, 0x0005, - 0x20a9, 0x0012, 0x20e9, 0x0001, 0x20a1, 0x1d80, 0x080c, 0x6152, - 0x20e9, 0x0000, 0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, - 0x614c, 0x2099, 0x0260, 0x20a1, 0x1d92, 0x0051, 0x20a9, 0x000e, - 0x080c, 0x614f, 0x2099, 0x0260, 0x20a1, 0x1db2, 0x0009, 0x0005, - 0x0016, 0x0026, 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, - 0x8210, 0x1f04, 0x60cc, 0x002e, 0x001e, 0x0005, 0x080c, 0xa8ec, - 0x20e1, 0x0001, 0x2099, 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, - 0x20a9, 0x000c, 0x4003, 0x0005, 0x080c, 0xa8ec, 0x080c, 0x6152, - 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, 0x6bc9, 0x0158, - 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xe795, 0x2001, 0x180c, - 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x900e, 0x080c, 0x32c0, - 0x080c, 0xd35d, 0x0140, 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, - 0x080c, 0x4ddf, 0x003e, 0x004e, 0x001e, 0x0005, 0x080c, 0x6033, - 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, 0x19a8, 0x0118, - 0x2003, 0x0001, 0x0010, 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, - 0x0800, 0x2009, 0x1000, 0x9006, 0x200a, 0x8108, 0x1f04, 0x618c, - 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, - 0x1847, 0x9006, 0xb802, 0xb8d6, 0xb807, 0x0707, 0xb80a, 0xb80e, - 0xb812, 0x9198, 0x3474, 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, - 0x0026, 0xb886, 0x080c, 0xae80, 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, 0x107f, 0xb8a7, - 0x0000, 0x009e, 0x9006, 0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846, - 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82, - 0x1ddc, 0x0a0c, 0x0d79, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, - 0x0d79, 0x080c, 0x8d87, 0x00ce, 0x090c, 0x9128, 0xb8af, 0x0000, - 0x6814, 0x9084, 0x00ff, 0xb842, 0x014e, 0x013e, 0x015e, 0x003e, - 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0xa974, 0xae78, 0x9684, - 0x3fff, 0x9082, 0x4000, 0x1a04, 0x6268, 0x9182, 0x0800, 0x1a04, - 0x626c, 0x2001, 0x180c, 0x2004, 0x9084, 0x0003, 0x1904, 0x6272, - 0x9188, 0x1000, 0x2104, 0x905d, 0x0198, 0xb804, 0x9084, 0x00ff, - 0x908e, 0x0006, 0x1188, 0xb8a4, 0x900d, 0x1904, 0x6284, 0x080c, - 0x6644, 0x9006, 0x012e, 0x0005, 0x2001, 0x0005, 0x900e, 0x04b8, - 0x2001, 0x0028, 0x900e, 0x0498, 0x9082, 0x0006, 0x1290, 0x080c, - 0xae80, 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, 0x6bcd, 0x1990, 0xb800, - 0xd0bc, 0x0978, 0x0804, 0x622b, 0x080c, 0x69f0, 0x0904, 0x6234, - 0x0804, 0x622f, 0x00e6, 0x2071, 0x19e9, 0x7004, 0x9086, 0x0002, - 0x1128, 0x7030, 0x9080, 0x0004, 0x2004, 0x9b06, 0x00ee, 0x0005, - 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa874, 0x908e, 0x00ff, - 0x1120, 0x2001, 0x196c, 0x205c, 0x0060, 0xa974, 0x9182, 0x0800, - 0x1690, 0x9188, 0x1000, 0x2104, 0x905d, 0x01d0, 0x080c, 0x6b6d, - 0x11d0, 0x080c, 0xaef8, 0x0570, 0x2b00, 0x6012, 0x2900, 0x6016, - 0x6023, 0x0009, 0x602b, 0x0000, 0xa874, 0x908e, 0x00ff, 0x1110, - 0x602b, 0x8000, 0x2009, 0x0043, 0x080c, 0xafec, 0x9006, 0x00b0, - 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, + 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, 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, - 0x00be, 0x0005, 0x2001, 0x002c, 0x0cc0, 0x00b6, 0x00e6, 0x0126, - 0x2091, 0x8000, 0xa974, 0x9182, 0x0800, 0x1a04, 0x6363, 0x9188, - 0x1000, 0x2104, 0x905d, 0x0904, 0x633b, 0xb8a0, 0x9086, 0x007f, - 0x0190, 0xa87c, 0xd0fc, 0x1178, 0x080c, 0x6bd5, 0x0160, 0xa994, - 0x81ff, 0x0130, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, - 0x080c, 0x6bcd, 0x1598, 0xa87c, 0xd0fc, 0x01e0, 0xa894, 0x9005, - 0x01c8, 0x2060, 0x0026, 0x2010, 0x080c, 0xcc21, 0x002e, 0x1120, - 0x2001, 0x0008, 0x0804, 0x6365, 0x6020, 0x9086, 0x000a, 0x0120, - 0x2001, 0x0008, 0x0804, 0x6365, 0x601a, 0x6003, 0x0008, 0x2900, - 0x6016, 0x0058, 0x080c, 0xaef8, 0x05e8, 0x2b00, 0x6012, 0x2900, - 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, - 0xafec, 0x9006, 0x0458, 0x2001, 0x0028, 0x0438, 0x9082, 0x0006, - 0x1290, 0x080c, 0xae80, 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, 0x63fa, 0x63b5, 0x63cc, - 0x63fa, 0x63fa, 0x63fa, 0x63fa, 0x63fa, 0x2100, 0x9082, 0x007e, - 0x1278, 0x080c, 0x6718, 0x0148, 0x9046, 0xb810, 0x9306, 0x1904, - 0x6402, 0xb814, 0x9206, 0x15f0, 0x0028, 0xbb12, 0xba16, 0x0010, - 0x080c, 0x4adb, 0x0150, 0x04b0, 0x080c, 0x6783, 0x1598, 0xb810, - 0x9306, 0x1580, 0xb814, 0x9206, 0x1568, 0x080c, 0xaef8, 0x0530, - 0x2b00, 0x6012, 0x080c, 0xd0ce, 0x2900, 0x6016, 0x600b, 0xffff, - 0x6023, 0x000a, 0xa878, 0x9086, 0x0001, 0x1170, 0x080c, 0x32fb, - 0x9006, 0x080c, 0x66b5, 0x2001, 0x0002, 0x080c, 0x66c9, 0x2001, - 0x0200, 0xb86e, 0xb893, 0x0002, 0x2009, 0x0003, 0x080c, 0xafec, - 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, 0x65ed, 0x90c6, 0x0056, - 0x0904, 0x65f1, 0x90c6, 0x0066, 0x0904, 0x65f5, 0x90c6, 0x0067, - 0x0904, 0x65f9, 0x90c6, 0x0068, 0x0904, 0x65fd, 0x90c6, 0x0071, - 0x0904, 0x6601, 0x90c6, 0x0074, 0x0904, 0x6605, 0x90c6, 0x007c, - 0x0904, 0x6609, 0x90c6, 0x007e, 0x0904, 0x660d, 0x90c6, 0x0037, - 0x0904, 0x6611, 0x9016, 0x2079, 0x1800, 0xa974, 0x9186, 0x00ff, - 0x0904, 0x65e8, 0x9182, 0x0800, 0x1a04, 0x65e8, 0x080c, 0x6783, - 0x1198, 0xb804, 0x9084, 0x00ff, 0x9082, 0x0006, 0x1268, 0xa894, - 0x90c6, 0x006f, 0x0148, 0x080c, 0xae80, 0x1904, 0x65d1, 0xb8a0, - 0x9084, 0xff80, 0x1904, 0x65d1, 0xa894, 0x90c6, 0x006f, 0x0158, - 0x90c6, 0x005e, 0x0904, 0x6531, 0x90c6, 0x0064, 0x0904, 0x655a, - 0x2008, 0x0804, 0x64f3, 0xa998, 0xa8b0, 0x2040, 0x080c, 0xae80, - 0x1120, 0x9182, 0x007f, 0x0a04, 0x64f3, 0x9186, 0x00ff, 0x0904, - 0x64f3, 0x9182, 0x0800, 0x1a04, 0x64f3, 0xaaa0, 0xab9c, 0x787c, - 0x9306, 0x11a8, 0x7880, 0x0096, 0x924e, 0x1128, 0x2208, 0x2310, - 0x009e, 0x0804, 0x64f3, 0x080c, 0xae80, 0x1140, 0x99cc, 0xff00, - 0x009e, 0x1128, 0x2208, 0x2310, 0x0804, 0x64f3, 0x009e, 0x080c, - 0x4adb, 0x0904, 0x64fd, 0x900e, 0x9016, 0x90c6, 0x4000, 0x15e0, - 0x0006, 0x080c, 0x6a74, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, - 0xc18d, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, - 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, - 0x0fca, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0035, - 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, - 0x0fca, 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, 0xaef8, 0x1130, - 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c78, 0x2b00, 0x6012, - 0x080c, 0xd0ce, 0x2900, 0x6016, 0x6023, 0x0001, 0xa868, 0xd88c, - 0x0108, 0xc0f5, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, 0x32fb, - 0x012e, 0x9006, 0x080c, 0x66b5, 0x2001, 0x0002, 0x080c, 0x66c9, - 0x2009, 0x0002, 0x080c, 0xafec, 0xa8b0, 0xd094, 0x0118, 0xb8d4, - 0xc08d, 0xb8d6, 0x9006, 0x9005, 0x012e, 0x00ee, 0x00fe, 0x00be, - 0x0005, 0x080c, 0x5834, 0x0118, 0x2009, 0x0007, 0x00f8, 0xa998, - 0xaeb0, 0x080c, 0x6783, 0x1904, 0x64ee, 0x9186, 0x007f, 0x0130, - 0x080c, 0x6bcd, 0x0118, 0x2009, 0x0009, 0x0080, 0x0096, 0x080c, - 0x104d, 0x1120, 0x009e, 0x2009, 0x0002, 0x0040, 0x2900, 0x009e, - 0xa806, 0x080c, 0xce21, 0x19b0, 0x2009, 0x0003, 0x2001, 0x4005, - 0x0804, 0x64f5, 0xa998, 0xaeb0, 0x080c, 0x6783, 0x1904, 0x64ee, - 0x0096, 0x080c, 0x104d, 0x1128, 0x009e, 0x2009, 0x0002, 0x0804, - 0x65ae, 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, 0x0fca, 0x009e, 0xa87b, - 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xd684, 0x1168, 0x080c, - 0x5820, 0xd0b4, 0x1118, 0xa89b, 0x000b, 0x00e0, 0xb800, 0xd08c, - 0x0118, 0xa89b, 0x000c, 0x00b0, 0x080c, 0x6bcd, 0x0118, 0xa89b, - 0x0009, 0x0080, 0x080c, 0x5834, 0x0118, 0xa89b, 0x0007, 0x0050, - 0x080c, 0xce04, 0x1904, 0x652a, 0x2009, 0x0003, 0x2001, 0x4005, - 0x0804, 0x64f5, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa804, 0x8006, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, - 0x2041, 0x129c, 0x080c, 0xb473, 0x1904, 0x652a, 0x2009, 0x0002, - 0x08e8, 0x2001, 0x0028, 0x900e, 0x0804, 0x652b, 0x2009, 0x180c, - 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, - 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0804, 0x652b, - 0x2001, 0x0029, 0x900e, 0x0804, 0x652b, 0x080c, 0x38a4, 0x0804, - 0x652c, 0x080c, 0x553d, 0x0804, 0x652c, 0x080c, 0x468c, 0x0804, - 0x652c, 0x080c, 0x4705, 0x0804, 0x652c, 0x080c, 0x4761, 0x0804, - 0x652c, 0x080c, 0x4b9e, 0x0804, 0x652c, 0x080c, 0x4e52, 0x0804, - 0x652c, 0x080c, 0x51a4, 0x0804, 0x652c, 0x080c, 0x539d, 0x0804, - 0x652c, 0x080c, 0x3ac2, 0x0804, 0x652c, 0x00b6, 0xa974, 0xae78, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x1608, 0x9182, 0x0800, 0x1258, - 0x9188, 0x1000, 0x2104, 0x905d, 0x0130, 0x080c, 0x6bcd, 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, 0x66a9, 0xb888, 0x9005, 0x1904, 0x66a9, 0xb838, 0xb93c, - 0x9102, 0x1a04, 0x66a9, 0x2b10, 0x080c, 0xaf25, 0x0904, 0x66a5, - 0x8108, 0xb93e, 0x6212, 0x2900, 0x6016, 0x6023, 0x0003, 0x600b, - 0xffff, 0x6007, 0x0040, 0xa878, 0x605e, 0xa880, 0x6066, 0xa883, - 0x0000, 0xa87c, 0xd0ac, 0x0588, 0xc0dd, 0xa87e, 0xa888, 0x8001, - 0x1530, 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, - 0x17a1, 0x601c, 0xc0bd, 0x601e, 0x0c38, 0xd0b4, 0x190c, 0x1cb9, - 0x2001, 0x8004, 0x6003, 0x0002, 0x0c18, 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, 0x6bc9, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, 0x0007, - 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, 0xba06, - 0x0006, 0x9086, 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c, 0x0d79, - 0x000e, 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, - 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, - 0x1168, 0xb89c, 0xd0a4, 0x0150, 0x080c, 0x6bc5, 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, 0x104d, - 0x2958, 0x009e, 0x0168, 0x2b00, 0x2012, 0xb85c, 0xb8ca, 0xb860, - 0xb8c6, 0x9006, 0xb8a6, 0xb8ae, 0x080c, 0x6192, 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, 0x107f, 0x00d6, 0x00c6, - 0xb8bc, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, 0x2048, - 0x080c, 0xcc33, 0x0110, 0x080c, 0x0fff, 0x080c, 0xaf4e, 0x00ce, - 0x0c88, 0x00ce, 0x00de, 0x00c6, 0xb8ac, 0x9065, 0x0128, 0x621c, - 0xd2c4, 0x0110, 0x080c, 0x9128, 0x00ce, 0x2b48, 0xb8c8, 0xb85e, - 0xb8c4, 0xb862, 0x080c, 0x108f, 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, 0x769d, 0x1510, 0xb8a0, - 0x9086, 0x007e, 0x0120, 0x080c, 0xae80, 0x11d8, 0x0078, 0x7040, - 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x1983, 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, 0x0d79, 0x3c00, 0x20e8, 0x3300, 0x8001, 0x20a0, - 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, 0x014e, 0x013e, 0x0060, - 0x080c, 0x104d, 0x0170, 0x2900, 0xb8a6, 0xa803, 0x0000, 0x080c, - 0x6a10, 0xa807, 0x0001, 0xae12, 0x9085, 0x0001, 0x012e, 0x009e, - 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x0096, 0xb8a4, - 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, 0x080c, 0x6a1f, 0x1158, - 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, 0xa806, 0x0020, 0x080c, - 0x107f, 0xb8a7, 0x0000, 0x009e, 0x012e, 0x0005, 0x0096, 0x00c6, - 0xb888, 0x9005, 0x1904, 0x6905, 0xb8d0, 0x904d, 0x0904, 0x6905, - 0x080c, 0xaf25, 0x0904, 0x6903, 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, 0x1cb9, 0x2001, 0x8004, 0x6003, 0x0002, 0x6046, - 0x2001, 0x0010, 0x2c08, 0x080c, 0xaae8, 0xb838, 0xba3c, 0x9202, - 0x0a04, 0x68b4, 0x0010, 0xb88b, 0x0001, 0x00ce, 0x009e, 0x0005, - 0x080c, 0x17a1, 0x601c, 0xc0bd, 0x601e, 0x08f0, 0x00b6, 0x0096, - 0x0016, 0x20a9, 0x0800, 0x900e, 0x0016, 0x080c, 0x6783, 0x1158, - 0xb8d0, 0x904d, 0x0140, 0x3e00, 0x9086, 0x0002, 0x1118, 0xb800, - 0xd0bc, 0x1108, 0x0041, 0x001e, 0x8108, 0x1f04, 0x6914, 0x001e, - 0x00be, 0x009e, 0x0005, 0x0096, 0x0016, 0xb8d0, 0x904d, 0x0188, - 0xa800, 0xb8d2, 0x9005, 0x1108, 0xb8ce, 0x9006, 0xa802, 0xa867, - 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xcf38, 0x080c, 0x6f11, - 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, 0x19e9, 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, 0xa21b, 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, 0x6a74, 0x0128, - 0x080c, 0xccf4, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6a74, - 0x0128, 0x080c, 0xcc95, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, - 0x6a74, 0x0128, 0x080c, 0xccf1, 0x0010, 0x9085, 0x0001, 0x0005, - 0x080c, 0x6a74, 0x0128, 0x080c, 0xccb4, 0x0010, 0x9085, 0x0001, - 0x0005, 0x080c, 0x6a74, 0x0128, 0x080c, 0xcd37, 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, 0x104d, 0x0168, 0x2900, 0xb8a6, 0x080c, - 0x6a10, 0xa803, 0x0001, 0xa807, 0x0000, 0x9085, 0x0001, 0x012e, - 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126, 0x2091, 0x8000, - 0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c, 0x107f, 0x9085, - 0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4, 0x0005, 0x00b6, - 0x00f6, 0x080c, 0x769d, 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, 0x6783, 0x1168, 0xb804, - 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, 0x9086, 0x0006, - 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, 0x1f04, 0x6a9b, - 0x015e, 0x080c, 0x6b8b, 0x0120, 0x2001, 0x1986, 0x200c, 0x0038, - 0x2079, 0x1847, 0x7804, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, - 0x6ac6, 0x080c, 0x88f6, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x2011, - 0x6ac6, 0x080c, 0x882c, 0x080c, 0x6b8b, 0x01d8, 0x2001, 0x107e, - 0x2004, 0x2058, 0xb900, 0xc1ec, 0xb902, 0x080c, 0x6bc9, 0x0130, - 0x2009, 0x07d0, 0x2011, 0x6ac6, 0x080c, 0x88f6, 0x00e6, 0x2071, - 0x1800, 0x9006, 0x707e, 0x7060, 0x7082, 0x080c, 0x30c8, 0x00ee, - 0x04e0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, - 0x6783, 0x1568, 0xb800, 0xd0ec, 0x0550, 0xd0bc, 0x1540, 0x0046, - 0xbaa0, 0x2220, 0x9006, 0x2009, 0x0029, 0x080c, 0xe795, 0xb800, - 0xc0e5, 0xc0ec, 0xb802, 0x080c, 0x6bc5, 0x2001, 0x0707, 0x1128, - 0xb804, 0x9084, 0x00ff, 0x9085, 0x0700, 0xb806, 0x080c, 0xaaf7, - 0x2019, 0x0029, 0x080c, 0x95b9, 0x0076, 0x903e, 0x080c, 0x9476, - 0x900e, 0x080c, 0xe465, 0x007e, 0x004e, 0x080c, 0xab13, 0x001e, - 0x8108, 0x1f04, 0x6aee, 0x00ce, 0x015e, 0x00be, 0x0005, 0x00b6, - 0x6010, 0x2058, 0xb800, 0xc0ec, 0xb802, 0x00be, 0x0005, 0x00b6, - 0x00c6, 0x0096, 0x080c, 0x1066, 0x090c, 0x0d79, 0x2958, 0x009e, - 0x2001, 0x196c, 0x2b02, 0x8b07, 0x8006, 0x8006, 0x908c, 0x003f, - 0xb9c6, 0x908c, 0xffc0, 0xb9ca, 0xb8af, 0x0000, 0x2009, 0x00ff, - 0x080c, 0x6192, 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, 0x0d79, 0x000e, 0xba00, 0x9005, 0x0110, 0xc2fd, - 0x0008, 0xc2fc, 0xba02, 0x002e, 0x012e, 0x0005, 0x2011, 0x1837, - 0x2204, 0xd0cc, 0x0138, 0x2001, 0x1984, 0x200c, 0x2011, 0x6bbb, - 0x080c, 0x88f6, 0x0005, 0x2011, 0x6bbb, 0x080c, 0x882c, 0x2011, - 0x1837, 0x2204, 0xc0cc, 0x2012, 0x0005, 0x080c, 0x5820, 0xd0ac, - 0x0005, 0x080c, 0x5820, 0xd0a4, 0x0005, 0x0016, 0xb904, 0x9184, - 0x00ff, 0x908e, 0x0006, 0x001e, 0x0005, 0x0016, 0xb904, 0x9184, - 0xff00, 0x8007, 0x908e, 0x0006, 0x001e, 0x0005, 0x00b6, 0x00f6, - 0x080c, 0xd35d, 0x0158, 0x70dc, 0x9084, 0x0028, 0x0138, 0x2001, - 0x107f, 0x2004, 0x905d, 0x0110, 0xb8d4, 0xd094, 0x00fe, 0x00be, - 0x0005, 0x2071, 0x1910, 0x7003, 0x0001, 0x7007, 0x0000, 0x9006, - 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, 0x7046, 0x2001, 0x1922, - 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1949, 0x900e, - 0x710a, 0x080c, 0x5820, 0xd0fc, 0x1140, 0x080c, 0x5820, 0x900e, - 0xd09c, 0x0108, 0x8108, 0x7102, 0x0430, 0x2001, 0x1867, 0x200c, - 0x9184, 0x0007, 0x0002, 0x6c0d, 0x6c0d, 0x6c0d, 0x6c0d, 0x6c0d, - 0x6c23, 0x6c38, 0x6c46, 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, 0x7a11, 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, 0x1949, 0x7000, 0x9015, 0x0904, 0x6f16, - 0x9286, 0x0003, 0x0904, 0x6dab, 0x9286, 0x0005, 0x0904, 0x6dab, - 0x2071, 0x1877, 0xa87c, 0x9005, 0x0904, 0x6d06, 0x7140, 0xa868, - 0x9102, 0x0a04, 0x6f16, 0xa878, 0xd084, 0x15d8, 0xa853, 0x0019, - 0x2001, 0x8023, 0xa84e, 0x2071, 0x1910, 0x701c, 0x9005, 0x1904, - 0x70c5, 0x0e04, 0x7133, 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, 0x11f4, 0x0804, - 0x6d8e, 0xa853, 0x001b, 0x2001, 0x8027, 0x0820, 0x7004, 0xd08c, - 0x1904, 0x6f16, 0xa853, 0x001a, 0x2001, 0x8024, 0x0804, 0x6cca, - 0x00e6, 0x0026, 0x2071, 0x1949, 0x7000, 0x9015, 0x0904, 0x6f16, - 0x9286, 0x0003, 0x0904, 0x6dab, 0x9286, 0x0005, 0x0904, 0x6dab, - 0xa84f, 0x8022, 0xa853, 0x0018, 0x0804, 0x6d73, 0xa868, 0xd0fc, - 0x1508, 0x00e6, 0x0026, 0x2001, 0x1949, 0x2004, 0x9015, 0x0904, - 0x6f16, 0xa978, 0xa874, 0x9105, 0x1904, 0x6f16, 0x9286, 0x0003, - 0x0904, 0x6dab, 0x9286, 0x0005, 0x0904, 0x6dab, 0xa87c, 0xd0bc, - 0x1904, 0x6f16, 0x2200, 0x0002, 0x6f16, 0x6d6f, 0x6dab, 0x6dab, - 0x6f16, 0x6dab, 0x0005, 0xa868, 0xd0fc, 0x1500, 0x00e6, 0x0026, - 0x2009, 0x1949, 0x210c, 0x81ff, 0x0904, 0x6f16, 0xa880, 0x9084, - 0x00ff, 0x9086, 0x0001, 0x1904, 0x6f16, 0x9186, 0x0003, 0x0904, - 0x6dab, 0x9186, 0x0005, 0x0904, 0x6dab, 0xa87c, 0xd0cc, 0x0904, - 0x6f16, 0xa84f, 0x8021, 0xa853, 0x0017, 0x0028, 0x0005, 0xa84f, - 0x8020, 0xa853, 0x0016, 0x2071, 0x1910, 0x701c, 0x9005, 0x1904, - 0x70c5, 0x0e04, 0x7133, 0x2071, 0x0000, 0xa84c, 0x7082, 0xa850, - 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11f4, 0x2071, 0x1800, - 0x2011, 0x0001, 0xa804, 0x900d, 0x702c, 0x1158, 0xa802, 0x2900, - 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8732, 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, 0x6e9c, - 0x782c, 0x908c, 0x0780, 0x190c, 0x7281, 0x8004, 0x8004, 0x8004, - 0x9084, 0x0003, 0x0002, 0x6dc9, 0x6e9c, 0x6ded, 0x6e39, 0x080c, - 0x0d79, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1168, - 0x2071, 0x1a05, 0x7044, 0x9005, 0x1320, 0x2001, 0x194a, 0x2004, - 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, - 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, - 0x9200, 0x70c2, 0x080c, 0x8732, 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, 0x8732, 0x782c, 0x9094, 0x0780, 0x190c, - 0x7281, 0xd0a4, 0x19c8, 0x2071, 0x1a05, 0x7044, 0x9005, 0x1320, - 0x2001, 0x194a, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8732, 0x0804, - 0x6df4, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, - 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8732, - 0x782c, 0x9094, 0x0780, 0x190c, 0x7281, 0xd0a4, 0x1d60, 0x00ee, - 0x782c, 0x9094, 0x0780, 0x190c, 0x7281, 0xd09c, 0x1198, 0x009e, - 0x2900, 0x7822, 0xa804, 0x900d, 0x1550, 0x2071, 0x1a05, 0x7044, - 0x9005, 0x1320, 0x2001, 0x194a, 0x2004, 0x7046, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, - 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, - 0x900d, 0x1168, 0x2071, 0x1a05, 0x7044, 0x9005, 0x1320, 0x2001, - 0x194a, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, - 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8732, - 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, - 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, - 0xa804, 0x900d, 0x1904, 0x6ef0, 0x782c, 0x9094, 0x0780, 0x190c, - 0x7281, 0xd09c, 0x1198, 0x701c, 0x904d, 0x0180, 0x7010, 0x8001, - 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7281, 0xd09c, 0x0d68, 0x782c, 0x9094, - 0x0780, 0x190c, 0x7281, 0xd0a4, 0x01b0, 0x00e6, 0x7824, 0x2048, - 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, - 0x70c2, 0x080c, 0x8732, 0x782c, 0x9094, 0x0780, 0x190c, 0x7281, - 0xd0a4, 0x1d60, 0x00ee, 0x2071, 0x1a05, 0x7044, 0x9005, 0x1320, - 0x2001, 0x194a, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, - 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, - 0x080c, 0x8732, 0x00ee, 0x0804, 0x6eac, 0xa868, 0xd0fc, 0x15e0, - 0x0096, 0xa804, 0xa807, 0x0000, 0x904d, 0x190c, 0x0fff, 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, - 0x7041, 0x782c, 0x908c, 0x0780, 0x190c, 0x7281, 0x8004, 0x8004, - 0x8004, 0x9084, 0x0003, 0x0002, 0x6f45, 0x7041, 0x6f60, 0x6fd2, - 0x080c, 0x0d79, 0x2009, 0x1949, 0x2104, 0x0002, 0x6f25, 0x6f25, - 0x6f25, 0x6db4, 0x6f25, 0x6db4, 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, 0x8732, 0x0c60, - 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1904, 0x6fc1, - 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, 0x8732, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7281, 0xd0a4, 0x19c8, 0x0e04, 0x6fb8, - 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, - 0x6833, 0x0013, 0x00de, 0x2001, 0x1921, 0x200c, 0xc184, 0x2102, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11f4, - 0x2001, 0x1922, 0x2003, 0x0000, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x2001, 0x1921, 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, 0x00ee, + 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, 0x8732, - 0x0804, 0x6f6f, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, + 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, + 0x0804, 0x6ef5, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x8732, 0x782c, 0x9094, 0x0780, 0x190c, 0x7281, 0xd0a4, 0x1d60, - 0x00ee, 0x0e04, 0x7014, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, - 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, - 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11f4, 0x704b, 0x0000, 0x782c, 0x9094, 0x0780, 0x190c, 0x7281, - 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, 0x8732, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, - 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, - 0x70b0, 0x782c, 0x9094, 0x0780, 0x190c, 0x7281, 0xd09c, 0x11b0, - 0x701c, 0x904d, 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, 0x8001, - 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7281, 0xd09c, 0x0d50, 0x782c, 0x9094, - 0x0780, 0x190c, 0x7281, 0xd0a4, 0x05b8, 0x00e6, 0x7824, 0x2048, - 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, - 0x70c2, 0x080c, 0x8732, 0x782c, 0x9094, 0x0780, 0x190c, 0x7281, - 0xd0a4, 0x1d60, 0x00ee, 0x0e04, 0x70a9, 0x7838, 0x7938, 0x910e, - 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, - 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x11f4, 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, 0x8732, 0x00ee, 0x0804, 0x7051, 0x2071, 0x1910, 0xa803, - 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, - 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1128, - 0x1e04, 0x70f0, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, + 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, 0x8732, 0x0e04, 0x70da, - 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, 0x11f4, 0x2071, 0x1910, 0x080c, - 0x726d, 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, 0x8732, 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, - 0x7180, 0x7181, 0x726c, 0x7181, 0x717e, 0x726c, 0x080c, 0x0d79, - 0x0005, 0x2001, 0x1949, 0x2004, 0x0002, 0x718b, 0x718b, 0x7205, - 0x7206, 0x718b, 0x7206, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x728c, - 0x701c, 0x904d, 0x0508, 0xa84c, 0x9005, 0x0904, 0x71d6, 0x0e04, - 0x71b4, 0xa94c, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, - 0x7086, 0x7036, 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, 0x1278, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11f4, - 0x2071, 0x1910, 0x080c, 0x726d, 0x012e, 0x0804, 0x7204, 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, 0x7281, 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, 0x1a05, 0x6844, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, - 0x0540, 0x2001, 0x1815, 0x2004, 0x2009, 0x1b74, 0x210c, 0x9102, - 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, - 0x9106, 0x0190, 0x0e04, 0x7238, 0x2069, 0x0000, 0x6837, 0x8040, - 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x11f4, 0x2069, 0x1a05, 0x6847, 0xffff, - 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x72fc, 0x701c, - 0x904d, 0x0540, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x15c9, - 0xd09c, 0x1500, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, + 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, - 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, 0x107f, 0x0005, 0x012e, - 0x0005, 0x2091, 0x8000, 0x0e04, 0x7283, 0x0006, 0x0016, 0x2001, - 0x8004, 0x0006, 0x0804, 0x0d82, 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, 0x11f4, - 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, 0x8732, 0x782c, 0x9094, 0x0780, 0x190c, - 0x7281, 0xd0a4, 0x19c8, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, - 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11f4, 0x00ee, 0x704b, - 0x0000, 0x00fe, 0x009e, 0x0005, 0x00f6, 0x2079, 0x0050, 0x7044, - 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, + 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, 0x11f4, 0x00fe, - 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, 0x7281, 0xd0a4, 0x0db8, - 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, 0x702c, 0xa802, 0x2900, - 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8732, 0x782c, 0x9094, - 0x0780, 0x190c, 0x7281, 0xd0a4, 0x1d70, 0x00d6, 0x2069, 0x0050, - 0x693c, 0x2069, 0x1949, 0x6808, 0x690a, 0x2069, 0x1a05, 0x9102, - 0x1118, 0x6844, 0x9005, 0x1320, 0x2001, 0x194a, 0x200c, 0x6946, - 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7098, 0x908a, 0x002a, 0x1a0c, - 0x0d79, 0x9082, 0x001d, 0x003b, 0x0026, 0x2011, 0x1e00, 0x080c, - 0x2adc, 0x002e, 0x0005, 0x7441, 0x73ae, 0x73ca, 0x73f4, 0x7430, - 0x7470, 0x7482, 0x73ca, 0x7458, 0x7369, 0x7397, 0x741a, 0x7368, - 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, - 0x9005, 0x1518, 0x709b, 0x0029, 0x2069, 0x1990, 0x2d04, 0x7002, - 0x080c, 0x77db, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, 0x709b, - 0x0029, 0x2069, 0x1990, 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, - 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a6f, 0x080c, - 0x1b3b, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, - 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, - 0x709b, 0x0029, 0x2069, 0x1990, 0x2d04, 0x7002, 0x080c, 0x7880, - 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, - 0x0090, 0x080c, 0x2aa2, 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, - 0x74f3, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x709b, - 0x0020, 0x080c, 0x74f3, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, - 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x2aa2, 0x6124, 0xd1cc, - 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, - 0x080c, 0x1b68, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, - 0x76c9, 0x2001, 0x0080, 0x080c, 0x2aa2, 0x709b, 0x0029, 0x0058, - 0x709b, 0x001e, 0x0040, 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, - 0x0010, 0x709b, 0x001f, 0x0005, 0x080c, 0x1b68, 0x60e3, 0x0001, - 0x600c, 0xc0b4, 0x600e, 0x080c, 0x76c9, 0x2001, 0x0080, 0x080c, - 0x2aa2, 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, 0x2aa2, 0x6124, 0xd1dc, 0x1138, 0xd1e4, - 0x0138, 0x080c, 0x1b68, 0x709b, 0x001e, 0x0010, 0x709b, 0x001d, - 0x0005, 0x080c, 0x757c, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x74f3, - 0x0016, 0x080c, 0x1b68, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, - 0x709b, 0x001e, 0x0020, 0x709b, 0x001f, 0x080c, 0x74f3, 0x0005, - 0x0006, 0x2001, 0x00a0, 0x080c, 0x2aa2, 0x000e, 0x6124, 0xd1d4, - 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, - 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x0021, 0x0005, - 0x080c, 0x757c, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, - 0x0140, 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, - 0x001f, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2aa2, 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, 0x769d, 0x11f8, 0x2001, 0x180c, 0x200c, - 0xd1b4, 0x01d0, 0xc1b4, 0x2102, 0x0026, 0x2011, 0x0200, 0x080c, - 0x2adc, 0x002e, 0x080c, 0x2a88, 0x6024, 0xd0cc, 0x0148, 0x2001, - 0x00a0, 0x080c, 0x2aa2, 0x080c, 0x799f, 0x080c, 0x6178, 0x0428, - 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x76b7, 0x0150, 0x080c, - 0x76ae, 0x1138, 0x2001, 0x0001, 0x080c, 0x2646, 0x080c, 0x7671, - 0x00a0, 0x080c, 0x7579, 0x0178, 0x2001, 0x0001, 0x080c, 0x2646, - 0x7098, 0x9086, 0x001e, 0x0120, 0x7098, 0x9086, 0x0022, 0x1118, - 0x709b, 0x0025, 0x0010, 0x709b, 0x0021, 0x012e, 0x00ee, 0x00de, - 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x7504, 0x080c, 0x8938, - 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x7504, 0x080c, - 0x892f, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, 0x080c, - 0xa09b, 0x2071, 0x1800, 0x080c, 0x749d, 0x001e, 0x00fe, 0x00ee, - 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x0126, 0x2071, 0x1800, 0x080c, 0xa09b, 0x2061, 0x0100, 0x2069, - 0x0140, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x080c, 0xaaf7, - 0x2011, 0x0003, 0x080c, 0xa426, 0x2011, 0x0002, 0x080c, 0xa430, - 0x080c, 0xa311, 0x080c, 0x88e4, 0x0036, 0x901e, 0x080c, 0xa391, - 0x003e, 0x080c, 0xab13, 0x60e3, 0x0000, 0x080c, 0xebe8, 0x080c, - 0xec03, 0x2009, 0x0004, 0x080c, 0x2a8e, 0x080c, 0x29a8, 0x2001, - 0x1800, 0x2003, 0x0004, 0x2011, 0x0008, 0x080c, 0x2adc, 0x2011, - 0x7504, 0x080c, 0x8938, 0x080c, 0x76b7, 0x0118, 0x9006, 0x080c, - 0x2aa2, 0x080c, 0x0bc3, 0x2001, 0x0001, 0x080c, 0x2646, 0x012e, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, - 0x0026, 0x00e6, 0x2011, 0x7511, 0x2071, 0x1a05, 0x701c, 0x9206, - 0x1118, 0x7018, 0x9005, 0x0110, 0x9085, 0x0001, 0x00ee, 0x002e, - 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, 0x9084, 0xfffe, 0x9086, - 0x00c0, 0x01b8, 0x2001, 0x00c0, 0x080c, 0x2aa2, 0x0156, 0x20a9, - 0x002d, 0x1d04, 0x7589, 0x2091, 0x6000, 0x1f04, 0x7589, 0x015e, - 0x00d6, 0x2069, 0x1800, 0x689c, 0x8001, 0x0220, 0x0118, 0x689e, - 0x00de, 0x0005, 0x689f, 0x0014, 0x68ec, 0xd0dc, 0x0dc8, 0x6800, - 0x9086, 0x0001, 0x1da8, 0x080c, 0x8944, 0x0c90, 0x00c6, 0x00d6, - 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, - 0x79ae, 0x2001, 0x196e, 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, - 0x6886, 0x080c, 0x2715, 0x9006, 0x080c, 0x2aa2, 0x080c, 0x6033, - 0x0026, 0x2011, 0xffff, 0x080c, 0x2adc, 0x002e, 0x602b, 0x182c, - 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x197e, 0x200c, - 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, 0x0002, - 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x7661, 0x709b, 0x0022, - 0x0040, 0x709b, 0x0021, 0x0028, 0x709b, 0x0023, 0x0010, 0x709b, - 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, - 0x2715, 0x080c, 0xaaf7, 0x0026, 0x080c, 0xadbe, 0x080c, 0xae87, - 0x002e, 0x080c, 0xab13, 0x7000, 0x908e, 0x0004, 0x0118, 0x602b, - 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, - 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, 0x015e, 0x080c, - 0xd35d, 0x0118, 0x9006, 0x080c, 0x2acc, 0x0804, 0x766d, 0x6800, - 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2a88, 0x6904, 0xd1d4, - 0x1140, 0x2001, 0x0100, 0x080c, 0x2aa2, 0x1f04, 0x7612, 0x080c, - 0x76f1, 0x012e, 0x015e, 0x080c, 0x76ae, 0x0170, 0x6044, 0x9005, - 0x0130, 0x080c, 0x76f1, 0x9006, 0x8001, 0x1df0, 0x0028, 0x6804, - 0xd0d4, 0x1110, 0x080c, 0x76f1, 0x080c, 0xd35d, 0x0118, 0x9006, - 0x080c, 0x2acc, 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, 0x0130, - 0x2009, 0x00c8, 0x2011, 0x7511, 0x080c, 0x88f6, 0x002e, 0x001e, - 0x080c, 0x8729, 0x7034, 0xc085, 0x7036, 0x2001, 0x197e, 0x2003, - 0x0004, 0x080c, 0x734c, 0x080c, 0x76ae, 0x0138, 0x6804, 0xd0d4, - 0x1120, 0xd0dc, 0x1100, 0x080c, 0x79a4, 0x00ee, 0x00de, 0x00ce, - 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, - 0x2071, 0x1800, 0x080c, 0x8740, 0x080c, 0x8732, 0x080c, 0x79ae, - 0x2001, 0x196e, 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, 0x6886, - 0x080c, 0x2715, 0x9006, 0x080c, 0x2aa2, 0x6043, 0x0090, 0x6043, - 0x0010, 0x0026, 0x2011, 0xffff, 0x080c, 0x2adc, 0x002e, 0x602b, - 0x182c, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, 0x197d, - 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x080c, 0x5824, - 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, 0x080c, - 0x5824, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, 0x0005, 0x0006, - 0x080c, 0x5824, 0x9084, 0x0030, 0x9086, 0x0010, 0x000e, 0x0005, - 0x0006, 0x080c, 0x5824, 0x9084, 0x0030, 0x9086, 0x0020, 0x000e, - 0x0005, 0x0036, 0x0016, 0x2001, 0x180c, 0x2004, 0x908c, 0x0013, - 0x0168, 0x0020, 0x080c, 0x2735, 0x900e, 0x0010, 0x2009, 0x0002, - 0x2019, 0x0028, 0x080c, 0x32c0, 0x9006, 0x0019, 0x001e, 0x003e, - 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, 0x080c, 0xd356, - 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, 0x00ee, - 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, - 0x0006, 0x6028, 0x0006, 0x080c, 0x2aff, 0x080c, 0x2b32, 0x602f, - 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, 0x20a9, - 0x0002, 0x080c, 0x2a69, 0x0026, 0x2011, 0x0040, 0x080c, 0x2adc, - 0x002e, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, - 0x60ee, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, - 0x2715, 0x2001, 0x00a0, 0x0006, 0x080c, 0xd35d, 0x000e, 0x0130, - 0x080c, 0x2ac0, 0x9006, 0x080c, 0x2acc, 0x0010, 0x080c, 0x2aa2, - 0x000e, 0x6052, 0x6050, 0x0006, 0xc0e5, 0x6052, 0x00f6, 0x2079, - 0x0100, 0x080c, 0x2a19, 0x00fe, 0x000e, 0x6052, 0x0005, 0x0156, - 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0xab55, 0x0158, 0x2001, - 0x0386, 0x2004, 0xd0b4, 0x1130, 0x2001, 0x0016, 0x080c, 0xaae8, - 0x0804, 0x77cd, 0x2001, 0x180c, 0x200c, 0xc1c4, 0x2102, 0x6028, - 0x9084, 0xe1ff, 0x602a, 0x2011, 0x0200, 0x080c, 0x2adc, 0x2001, - 0x0090, 0x080c, 0x2aa2, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1558, - 0x1d04, 0x776d, 0x2091, 0x6000, 0x1f04, 0x776d, 0x080c, 0xaaf7, - 0x2011, 0x0003, 0x080c, 0xa426, 0x2011, 0x0002, 0x080c, 0xa430, - 0x080c, 0xa311, 0x901e, 0x080c, 0xa391, 0x2001, 0x0386, 0x2003, - 0x7000, 0x080c, 0xab13, 0x2001, 0x00a0, 0x080c, 0x2aa2, 0x080c, - 0x799f, 0x080c, 0x6178, 0x080c, 0xd35d, 0x0110, 0x080c, 0x0ce5, - 0x9085, 0x0001, 0x04c0, 0x080c, 0x1b68, 0x60e3, 0x0000, 0x2001, - 0x196e, 0x2004, 0x080c, 0x2715, 0x60e2, 0x2001, 0x0080, 0x080c, - 0x2aa2, 0x20a9, 0x0366, 0x2011, 0x1e00, 0x080c, 0x2adc, 0x2009, - 0x1e00, 0x080c, 0x2a88, 0x6024, 0x910c, 0x0140, 0x1d04, 0x77ab, - 0x2091, 0x6000, 0x1f04, 0x77ab, 0x0804, 0x7776, 0x2001, 0x0386, - 0x2003, 0x7000, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b4, 0x9005, - 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xd35d, 0x0110, - 0x080c, 0x0ce5, 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, - 0x7844, 0x2001, 0x0088, 0x080c, 0x2aa2, 0x9006, 0x60e2, 0x6886, - 0x080c, 0x2715, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, - 0x9005, 0x01d0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x2011, 0x0400, - 0x080c, 0x2adc, 0x2069, 0x1990, 0x7000, 0x206a, 0x709b, 0x0026, - 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x7824, 0x2091, 0x6000, - 0x1f04, 0x7824, 0x0804, 0x7878, 0x2069, 0x0140, 0x20a9, 0x0384, - 0x2011, 0x1e00, 0x080c, 0x2adc, 0x2009, 0x1e00, 0x080c, 0x2a88, - 0x6024, 0x910c, 0x0528, 0x9084, 0x1a00, 0x1510, 0x1d04, 0x7830, - 0x2091, 0x6000, 0x1f04, 0x7830, 0x080c, 0xaaf7, 0x2011, 0x0003, - 0x080c, 0xa426, 0x2011, 0x0002, 0x080c, 0xa430, 0x080c, 0xa311, - 0x901e, 0x080c, 0xa391, 0x080c, 0xab13, 0x2001, 0x00a0, 0x080c, - 0x2aa2, 0x080c, 0x799f, 0x080c, 0x6178, 0x9085, 0x0001, 0x00c0, - 0x080c, 0x1b68, 0x2001, 0x0080, 0x080c, 0x2aa2, 0x2069, 0x0140, - 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, - 0x6886, 0x2001, 0x196e, 0x2004, 0x080c, 0x2715, 0x60e2, 0x9006, + 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, - 0xaaf7, 0x2011, 0x0003, 0x080c, 0xa426, 0x2011, 0x0002, 0x080c, - 0xa430, 0x080c, 0xa311, 0x901e, 0x080c, 0xa391, 0x080c, 0xab13, - 0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x2aa2, 0x080c, 0x799f, - 0x080c, 0x6178, 0x0804, 0x791b, 0x2001, 0x180c, 0x200c, 0xd1b4, - 0x1160, 0xc1b5, 0x2102, 0x080c, 0x74f9, 0x2069, 0x0140, 0x2001, - 0x0080, 0x080c, 0x2aa2, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, + 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, 0x2adc, 0x2069, 0x1990, 0x7000, - 0x206a, 0x709b, 0x0027, 0x7003, 0x0001, 0x0804, 0x791b, 0x2011, - 0x1e00, 0x080c, 0x2adc, 0x2009, 0x1e00, 0x080c, 0x2a88, 0x6024, - 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x78d7, 0x0006, - 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x8780, 0x00ee, 0x00de, - 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x1a05, 0x7078, 0x00ee, - 0x9005, 0x19e8, 0x0400, 0x0026, 0x2011, 0x7511, 0x080c, 0x882c, - 0x2011, 0x7504, 0x080c, 0x8938, 0x002e, 0x2069, 0x0140, 0x60e3, + 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, 0x196e, 0x2004, 0x080c, 0x2715, 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, 0xd356, - 0x1904, 0x7989, 0x7130, 0xd184, 0x1170, 0x080c, 0x3468, 0x0138, - 0xc18d, 0x7132, 0x2011, 0x1848, 0x2214, 0xd2ac, 0x1120, 0x7030, - 0xd08c, 0x0904, 0x7989, 0x2011, 0x1848, 0x220c, 0xd1a4, 0x0538, - 0x0016, 0x2019, 0x000e, 0x080c, 0xe701, 0x0156, 0x00b6, 0x20a9, - 0x007f, 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, - 0x080c, 0x6783, 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, - 0x080c, 0xe795, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8add, - 0x001e, 0x8108, 0x1f04, 0x7952, 0x00be, 0x015e, 0x001e, 0xd1ac, - 0x1148, 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x32c0, - 0x001e, 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, - 0x6783, 0x1110, 0x080c, 0x6192, 0x8108, 0x1f04, 0x797f, 0x00be, - 0x015e, 0x080c, 0x1b68, 0x080c, 0xaaf7, 0x080c, 0xae87, 0x080c, - 0xab13, 0x60e3, 0x0000, 0x080c, 0x6178, 0x080c, 0x75cc, 0x00ee, - 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, - 0x197e, 0x2003, 0x0001, 0x0005, 0x2001, 0x197e, 0x2003, 0x0000, - 0x0005, 0x2001, 0x197d, 0x2003, 0xaaaa, 0x0005, 0x2001, 0x197d, - 0x2003, 0x0000, 0x0005, 0x2071, 0x18fa, 0x7003, 0x0000, 0x7007, - 0x0000, 0x080c, 0x1066, 0x090c, 0x0d79, 0xa8ab, 0xdcb0, 0x2900, - 0x704e, 0x080c, 0x1066, 0x090c, 0x0d79, 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, 0x7f9c, 0x9006, 0x00ee, - 0x0005, 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, 0x818d, 0x1f04, - 0x7a15, 0x015e, 0x0005, 0x2079, 0x0040, 0x2071, 0x18fa, 0x7004, - 0x0002, 0x7a2b, 0x7a2c, 0x7a78, 0x7ad3, 0x7be3, 0x7a29, 0x7a29, - 0x7c0d, 0x080c, 0x0d79, 0x0005, 0x2079, 0x0040, 0x2001, 0x1dc0, - 0x2003, 0x0000, 0x782c, 0x908c, 0x0780, 0x190c, 0x807e, 0xd0a4, - 0x0578, 0x2001, 0x1dc0, 0x2004, 0x9082, 0x0080, 0x1648, 0x1d04, - 0x7a49, 0x2001, 0x1a08, 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, 0x7a68, 0x7a32, 0x7a68, - 0x7a66, 0x7a68, 0x7a68, 0x7a68, 0x7a68, 0x7a68, 0x080c, 0x7ad3, - 0x782c, 0xd09c, 0x090c, 0x7f9c, 0x0005, 0x9082, 0x005a, 0x1218, - 0x2100, 0x003b, 0x0c10, 0x080c, 0x7b09, 0x0c90, 0x00e3, 0x08e8, - 0x0005, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, - 0x7b09, 0x7b2b, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, - 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, - 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b15, 0x7b09, 0x7d03, - 0x7b09, 0x7b09, 0x7b09, 0x7b2b, 0x7b09, 0x7b15, 0x7d44, 0x7d85, - 0x7dcc, 0x7de0, 0x7b09, 0x7b09, 0x7b2b, 0x7b15, 0x7b3f, 0x7b09, - 0x7bb7, 0x7e8b, 0x7ea6, 0x7b09, 0x7b2b, 0x7b09, 0x7b3f, 0x7b09, - 0x7b09, 0x7bad, 0x7ea6, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, - 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b53, 0x7b09, 0x7b09, 0x7b09, - 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x7b09, 0x8022, 0x7b09, - 0x7fcc, 0x7b09, 0x7fcc, 0x7b09, 0x7b68, 0x7b09, 0x7b09, 0x7b09, - 0x7b09, 0x7b09, 0x7b09, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, - 0x1198, 0x782c, 0x080c, 0x7fc5, 0xd0a4, 0x0170, 0x7824, 0x2048, - 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x001a, - 0x1210, 0x002b, 0x0c50, 0x00e9, 0x080c, 0x7f9c, 0x0005, 0x7b09, - 0x7b15, 0x7cef, 0x7b09, 0x7b15, 0x7b09, 0x7b15, 0x7b15, 0x7b09, - 0x7b15, 0x7cef, 0x7b15, 0x7b15, 0x7b15, 0x7b15, 0x7b15, 0x7b09, - 0x7b15, 0x7cef, 0x7b09, 0x7b09, 0x7b15, 0x7b09, 0x7b09, 0x7b09, - 0x7b15, 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, - 0x6f11, 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0d08, - 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7c8c, 0x7007, 0x0003, - 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7c8c, 0x0005, 0xa864, - 0x8007, 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, - 0x0804, 0x7ca7, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, - 0x704b, 0x7ca7, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0904, - 0x7b11, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7cc3, 0x7007, - 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7cc3, 0x0005, - 0xa864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7b11, - 0x7007, 0x0001, 0x2009, 0x1834, 0x210c, 0x81ff, 0x11a8, 0xa868, - 0x9084, 0x00ff, 0xa86a, 0xa883, 0x0000, 0x080c, 0x640b, 0x1108, - 0x0005, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0xa87a, 0xa982, - 0x080c, 0x6f11, 0x012e, 0x0ca0, 0xa994, 0x9186, 0x0071, 0x0d38, - 0x9186, 0x0064, 0x0d20, 0x9186, 0x007c, 0x0d08, 0x9186, 0x0028, - 0x09f0, 0x9186, 0x0038, 0x09d8, 0x9186, 0x0078, 0x09c0, 0x9186, - 0x005f, 0x09a8, 0x9186, 0x0056, 0x0990, 0xa897, 0x4005, 0xa89b, - 0x0001, 0x2001, 0x0030, 0x900e, 0x08a0, 0xa87c, 0x9084, 0x00c0, - 0x9086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x7ebd, 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, - 0x7b19, 0xaab4, 0x928a, 0x0002, 0x1a04, 0x7b19, 0x82ff, 0x1138, - 0xa8b8, 0xa9bc, 0x9105, 0x0118, 0x2001, 0x7c4a, 0x0018, 0x9280, - 0x7c40, 0x2005, 0x7056, 0x7010, 0x9015, 0x0904, 0x7c2b, 0x080c, - 0x1066, 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, 0x1142, 0xa06c, 0x908e, 0x0100, - 0x0170, 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, - 0x2048, 0x080c, 0x107f, 0x7014, 0x2048, 0x0804, 0x7b19, 0x7020, - 0x2048, 0x7018, 0xa802, 0xa807, 0x0000, 0x2908, 0x2048, 0xa906, - 0x711a, 0x0804, 0x7be3, 0x7014, 0x2048, 0x7007, 0x0001, 0xa8b4, - 0x9005, 0x1128, 0xa8b8, 0xa9bc, 0x9105, 0x0108, 0x00b9, 0xa864, - 0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, 0x7ebd, 0x0804, 0x7c8c, - 0x7c42, 0x7c46, 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, 0x620a, 0x1108, 0x0005, 0x080c, 0x715d, 0x0126, - 0x2091, 0x8000, 0x080c, 0xcf38, 0x080c, 0x6f11, 0x012e, 0x0ca0, - 0x080c, 0xd356, 0x1d70, 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009, - 0x1834, 0x210c, 0x81ff, 0x1188, 0xa888, 0x9005, 0x0188, 0xa883, - 0x0000, 0x080c, 0x6298, 0x1108, 0x0005, 0xa87a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6f11, 0x012e, 0x0cb8, 0x2001, 0x0028, 0x0ca8, - 0x2001, 0x0000, 0x0c90, 0x0419, 0x11d8, 0xa888, 0x9005, 0x01e0, - 0xa883, 0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, 0x636d, 0x1138, - 0x0005, 0x9006, 0xa87a, 0x080c, 0x62e5, 0x1108, 0x0005, 0x0126, - 0x2091, 0x8000, 0xa87a, 0xa982, 0x080c, 0x6f11, 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, 0x6783, 0x11b8, 0x0066, 0xae80, - 0x080c, 0x6893, 0x006e, 0x0088, 0x0046, 0x2011, 0x180c, 0x2224, - 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x6783, 0x1110, 0x080c, - 0x6a64, 0x8108, 0x1f04, 0x7d2c, 0x00ce, 0xa87c, 0xd084, 0x1120, - 0x080c, 0x107f, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6f11, 0x012e, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x080c, 0x6bc9, 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, 0x7f86, 0x012e, 0x0804, 0x7f80, 0x012e, - 0x0804, 0x7f7a, 0x012e, 0x0804, 0x7f7d, 0x0126, 0x2091, 0x8000, - 0x7007, 0x0001, 0x080c, 0x6bc9, 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, 0x7f86, 0x012e, 0x0804, - 0x7f83, 0x012e, 0x0804, 0x7f80, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x2061, 0x1a74, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, - 0x0220, 0x630a, 0x012e, 0x0804, 0x7f94, 0x012e, 0x0804, 0x7f83, - 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, 0xaf89, - 0x0068, 0x6017, 0xf400, 0x6063, 0x0000, 0xa97c, 0xd1a4, 0x0110, - 0xa980, 0x6162, 0x2009, 0x0041, 0x080c, 0xafec, 0xa988, 0x918c, - 0xff00, 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, - 0x080c, 0x8add, 0x002e, 0xa87c, 0xd0c4, 0x0148, 0x2061, 0x1a74, - 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, - 0x012e, 0x00be, 0x0804, 0x7f86, 0x00ce, 0x012e, 0x00be, 0x0804, - 0x7f80, 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, 0x6783, 0x1968, 0xb800, 0xc0e4, - 0xb802, 0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, 0x0024, 0x2001, - 0x1987, 0x2004, 0x601a, 0x0804, 0x7e1b, 0xa88c, 0x9065, 0x0960, - 0x00e6, 0xa890, 0x9075, 0x2001, 0x1834, 0x2004, 0x9005, 0x0150, - 0x080c, 0xaf89, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xaf89, 0x00ee, - 0x0804, 0x7e1b, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, - 0x003a, 0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, 0xa8a4, 0x602e, - 0xa8a8, 0x6016, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9420, - 0x00ee, 0x0804, 0x7e1b, 0x2061, 0x1a74, 0x6000, 0xd084, 0x0190, - 0xd08c, 0x1904, 0x7f94, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, - 0x0220, 0x6206, 0x012e, 0x0804, 0x7f94, 0x012e, 0xa883, 0x0016, - 0x0804, 0x7f8d, 0xa883, 0x0007, 0x0804, 0x7f8d, 0xa864, 0x8007, - 0x9084, 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, - 0x0005, 0x080c, 0x7b11, 0x0040, 0x7007, 0x0003, 0x7012, 0x2900, - 0x7016, 0x701a, 0x704b, 0x7ebd, 0x0005, 0x00b6, 0x00e6, 0x0126, - 0x2091, 0x8000, 0x903e, 0x2061, 0x1800, 0x61d0, 0x81ff, 0x1904, - 0x7f3f, 0x6130, 0xd194, 0x1904, 0x7f69, 0xa878, 0x2070, 0x9e82, - 0x1ddc, 0x0a04, 0x7f33, 0x6068, 0x9e02, 0x1a04, 0x7f33, 0x7120, - 0x9186, 0x0006, 0x1904, 0x7f25, 0x7010, 0x905d, 0x0904, 0x7f3f, - 0xb800, 0xd0e4, 0x1904, 0x7f63, 0x2061, 0x1a74, 0x6100, 0x9184, - 0x0301, 0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, 0x1904, 0x7f6c, - 0xa883, 0x0000, 0xa803, 0x0000, 0x2908, 0x7014, 0x9005, 0x1198, - 0x7116, 0xa87c, 0xd0f4, 0x1904, 0x7f6f, 0x080c, 0x5820, 0xd09c, - 0x1118, 0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, 0x89cd, 0x012e, - 0x00ee, 0x00be, 0x0005, 0x2048, 0xa800, 0x9005, 0x1de0, 0xa902, - 0x2148, 0xa87c, 0xd0f4, 0x1904, 0x7f6f, 0x012e, 0x00ee, 0x00be, - 0x0005, 0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, 0x0804, 0x7f8d, - 0xd184, 0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, 0x080c, 0x6783, - 0x15d0, 0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, - 0xa883, 0x0002, 0x0490, 0xa883, 0x0008, 0x0478, 0xa883, 0x000e, - 0x0460, 0xa883, 0x0017, 0x0448, 0xa883, 0x0035, 0x0430, 0x080c, - 0x5824, 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, 0x7ec9, 0x7003, 0x0002, 0x0804, 0x7ec9, - 0xa883, 0x0028, 0x0010, 0xa883, 0x0029, 0x012e, 0x00ee, 0x00be, - 0x0420, 0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, 0x0cb0, 0x2e60, - 0x2019, 0x0002, 0x601b, 0x0014, 0x080c, 0xe28e, 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, 0x6f11, 0x012e, 0x0005, 0x080c, 0x107f, 0x0005, 0x00d6, - 0x080c, 0x89c4, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, 0x908c, 0x0780, - 0x190c, 0x807e, 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, 0x807e, 0x000e, 0x0005, 0xa898, 0x9084, 0x0003, 0x05a8, - 0x080c, 0xaef8, 0x05d8, 0x2900, 0x6016, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0035, 0x1138, 0x6028, 0xc0fd, 0x602a, 0x2001, 0x196c, - 0x2004, 0x0098, 0xa8a0, 0x9084, 0x00ff, 0xa99c, 0x918c, 0xff00, - 0x9105, 0xa99c, 0x918c, 0x00ff, 0x080c, 0x26a1, 0x1540, 0x00b6, - 0x080c, 0x6783, 0x2b00, 0x00be, 0x1510, 0x6012, 0x6023, 0x0001, - 0x2009, 0x0040, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x0110, - 0x2009, 0x0041, 0x080c, 0xafec, 0x0005, 0xa87b, 0x0101, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6f11, 0x012e, 0x0005, 0xa87b, 0x002c, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6f11, 0x012e, 0x0005, 0xa87b, - 0x0028, 0x0126, 0x2091, 0x8000, 0x080c, 0x6f11, 0x012e, 0x080c, - 0xaf4e, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x00b6, - 0x7007, 0x0001, 0xaa74, 0x9282, 0x0004, 0x1a04, 0x806f, 0xa97c, - 0x9188, 0x1000, 0x2104, 0x905d, 0xb804, 0xd284, 0x0140, 0x05e8, - 0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04b0, 0x2b10, - 0x080c, 0xaef8, 0x1118, 0x080c, 0xafbf, 0x05a8, 0x6212, 0xa874, - 0x0002, 0x804d, 0x8052, 0x8055, 0x805b, 0x2019, 0x0002, 0x080c, - 0xe701, 0x0060, 0x080c, 0xe68c, 0x0048, 0x2019, 0x0002, 0xa980, - 0x080c, 0xe6ab, 0x0018, 0xa980, 0x080c, 0xe68c, 0x080c, 0xaf4e, - 0xa887, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x6f11, 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, 0x8080, 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, - 0x0d82, 0x2001, 0x1834, 0x2004, 0x9005, 0x0005, 0x0005, 0x00f6, - 0x2079, 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, - 0x2009, 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x163c, 0x00fe, - 0x0005, 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe, - 0x0005, 0x781c, 0xd08c, 0x0904, 0x8101, 0x68c0, 0x90aa, 0x0005, - 0x0a04, 0x8729, 0x7d44, 0x7c40, 0xd59c, 0x190c, 0x0d79, 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, 0xebc0, 0x080c, 0x8610, - 0x7817, 0x0140, 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x866c, - 0x19c8, 0xd5a4, 0x0148, 0x0046, 0x0056, 0x080c, 0x8151, 0x080c, - 0x21a2, 0x005e, 0x004e, 0x0020, 0x080c, 0xebc0, 0x7817, 0x0140, - 0x080c, 0x769d, 0x0168, 0x2001, 0x0111, 0x2004, 0xd08c, 0x0140, - 0x6893, 0x0000, 0x2001, 0x0110, 0x2003, 0x0008, 0x2003, 0x0000, - 0x0489, 0x0005, 0x0002, 0x810e, 0x841e, 0x810b, 0x810b, 0x810b, - 0x810b, 0x810b, 0x810b, 0x7817, 0x0140, 0x0005, 0x7000, 0x908c, - 0xff00, 0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x6892, 0x9286, - 0x2000, 0x1150, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, 0x588a, - 0x0070, 0x080c, 0x8171, 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, - 0x8358, 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x853d, 0x7817, - 0x0140, 0x0005, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0178, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, - 0x8048, 0x2518, 0x080c, 0x4c28, 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, 0x4c28, 0x002e, 0x00fe, 0x005e, 0x004e, 0x003e, - 0x0005, 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, - 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, 0x8329, 0x9186, 0x0023, - 0x15c0, 0x080c, 0x85db, 0x0904, 0x8329, 0x6120, 0x9186, 0x0001, - 0x0150, 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, 0x9186, - 0x000a, 0x1904, 0x8329, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, - 0x1130, 0x2009, 0x0015, 0x080c, 0xafec, 0x0804, 0x8329, 0x908e, - 0x0214, 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, - 0xafec, 0x0804, 0x8329, 0x908e, 0x0100, 0x1904, 0x8329, 0x7034, - 0x9005, 0x1904, 0x8329, 0x2009, 0x0016, 0x080c, 0xafec, 0x0804, - 0x8329, 0x9186, 0x0022, 0x1904, 0x8329, 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, 0x26ea, - 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x26a1, 0x695e, - 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1800, 0x70b6, - 0x00ee, 0x7034, 0x9005, 0x1904, 0x8329, 0x2009, 0x0017, 0x0804, - 0x82d9, 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, 0x8329, - 0x080c, 0x769d, 0x0120, 0x2009, 0x001d, 0x0804, 0x82d9, 0x68dc, - 0xc0a5, 0x68de, 0x2009, 0x0030, 0x0804, 0x82d9, 0x908e, 0x0500, - 0x1140, 0x7034, 0x9005, 0x1904, 0x8329, 0x2009, 0x0018, 0x0804, - 0x82d9, 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x82d9, - 0x908e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x82d9, 0x908e, - 0x5200, 0x1140, 0x7034, 0x9005, 0x1904, 0x8329, 0x2009, 0x001b, - 0x0804, 0x82d9, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, - 0x8329, 0x2009, 0x001c, 0x0804, 0x82d9, 0x908e, 0x1300, 0x1120, - 0x2009, 0x0034, 0x0804, 0x82d9, 0x908e, 0x1200, 0x1140, 0x7034, - 0x9005, 0x1904, 0x8329, 0x2009, 0x0024, 0x0804, 0x82d9, 0x908c, - 0xff00, 0x918e, 0x2400, 0x1170, 0x2009, 0x002d, 0x2001, 0x1810, - 0x2004, 0xd09c, 0x0904, 0x82d9, 0x080c, 0xdaa3, 0x1904, 0x8329, - 0x0804, 0x82d7, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, - 0x002a, 0x0804, 0x82d9, 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, - 0x0804, 0x82d9, 0x908e, 0x6104, 0x1530, 0x2029, 0x0205, 0x2011, - 0x026d, 0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, - 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x4c28, - 0x004e, 0x8108, 0x0f04, 0x828d, 0x9186, 0x0280, 0x1d88, 0x2504, - 0x8000, 0x202a, 0x2009, 0x0260, 0x0c58, 0x202b, 0x0000, 0x2009, - 0x0023, 0x0804, 0x82d9, 0x908e, 0x6000, 0x1120, 0x2009, 0x003f, - 0x0804, 0x82d9, 0x908e, 0x5400, 0x1138, 0x080c, 0x86d9, 0x1904, - 0x8329, 0x2009, 0x0046, 0x04a8, 0x908e, 0x5500, 0x1148, 0x080c, - 0x8701, 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, - 0x26a1, 0x1904, 0x832c, 0x080c, 0x6718, 0x1904, 0x832c, 0xbe12, - 0xbd16, 0x001e, 0x0016, 0x080c, 0x769d, 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, 0xaef8, - 0x01a8, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, - 0x9186, 0x004c, 0x1110, 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, - 0xafec, 0x00ce, 0x00be, 0x0005, 0x001e, 0x0cd8, 0x2001, 0x180e, - 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4c28, 0x080c, - 0xafbf, 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, 0x9427, 0x08a0, - 0x080c, 0x8748, 0x1158, 0x080c, 0x3432, 0x1140, 0x7010, 0x9084, - 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005, 0x00b6, - 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, 0x0033, - 0x11e8, 0x080c, 0x85db, 0x0904, 0x83b6, 0x7124, 0x610a, 0x7030, - 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15c0, 0x2009, 0x0015, - 0x080c, 0xafec, 0x0498, 0x908e, 0x0100, 0x1580, 0x7034, 0x9005, - 0x1568, 0x2009, 0x0016, 0x080c, 0xafec, 0x0440, 0x9186, 0x0032, - 0x1528, 0x7030, 0x908e, 0x1400, 0x1508, 0x2009, 0x0038, 0x0016, - 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x26a1, 0x11a8, - 0x080c, 0x6718, 0x1190, 0xbe12, 0xbd16, 0x080c, 0xaef8, 0x0168, - 0x2b08, 0x6112, 0x080c, 0xd0ce, 0x6023, 0x0004, 0x7120, 0x610a, - 0x001e, 0x080c, 0xafec, 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, 0x8418, 0x9596, 0xfffe, 0x1120, - 0x2009, 0x007e, 0x0804, 0x8418, 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, - 0x83ed, 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, - 0x8440, 0x8440, 0x8440, 0x85ed, 0x8440, 0x8443, 0x8468, 0x84f1, - 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, - 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, 0xafec, 0x7817, 0x0140, 0x00be, 0x0005, - 0x00b6, 0x00c6, 0x9484, 0x0fff, 0x0904, 0x84cd, 0x7110, 0xd1bc, - 0x1904, 0x84cd, 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, - 0x9094, 0xff00, 0x15c8, 0x81ff, 0x15b8, 0x9080, 0x3474, 0x200d, - 0x918c, 0xff00, 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, 0x84cd, - 0x9182, 0x0801, 0x1a04, 0x84cd, 0x9190, 0x1000, 0x2204, 0x905d, - 0x05e0, 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15b8, 0xba04, 0x9294, - 0xff00, 0x9286, 0x0600, 0x1190, 0x080c, 0xaef8, 0x0598, 0x2b08, - 0x7028, 0x604e, 0x702c, 0x6052, 0x6112, 0x6023, 0x0006, 0x7120, - 0x610a, 0x7130, 0x615e, 0x080c, 0xdd1f, 0x00f8, 0x080c, 0x6bcd, - 0x1138, 0xb807, 0x0606, 0x0c40, 0x190c, 0x83ba, 0x11b0, 0x0880, - 0x080c, 0xaef8, 0x2b08, 0x0188, 0x6112, 0x6023, 0x0004, 0x7120, - 0x610a, 0x9286, 0x0400, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, - 0x0001, 0x6003, 0x0001, 0x080c, 0x9427, 0x7817, 0x0140, 0x00ce, - 0x00be, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, - 0x8049, 0x080c, 0x4c28, 0x080c, 0xafbf, 0x0d78, 0x2b08, 0x6112, - 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x615e, 0x6017, 0xf300, - 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9420, - 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, 0xafec, 0x7817, - 0x0140, 0x00be, 0x0005, 0x6120, 0x9186, 0x0002, 0x0128, 0x9186, - 0x0005, 0x0110, 0x9085, 0x0001, 0x0005, 0x080c, 0x8748, 0x1180, - 0x080c, 0x3432, 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, - 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, 0x000b, - 0x0005, 0x8557, 0x8558, 0x8557, 0x8557, 0x85bd, 0x85cc, 0x0005, - 0x00b6, 0x700c, 0x7108, 0x080c, 0x26a1, 0x1904, 0x85bb, 0x080c, - 0x6718, 0x1904, 0x85bb, 0xbe12, 0xbd16, 0x7110, 0xd1bc, 0x0540, - 0x702c, 0xd084, 0x1120, 0xb800, 0xd0bc, 0x1904, 0x85bb, 0x080c, - 0x6bcd, 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6bd5, 0x0118, - 0x9086, 0x0004, 0x1588, 0x00c6, 0x080c, 0x85db, 0x00ce, 0x05d8, - 0x080c, 0xaef8, 0x2b08, 0x05b8, 0x6112, 0x080c, 0xd0ce, 0x6023, - 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xafec, 0x0458, - 0x080c, 0x6bcd, 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6bd5, - 0x0118, 0x9086, 0x0004, 0x1180, 0x080c, 0xaef8, 0x2b08, 0x01d8, - 0x6112, 0x080c, 0xd0ce, 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, - 0x0088, 0x080c, 0xafec, 0x0078, 0x080c, 0xaef8, 0x2b08, 0x0158, - 0x6112, 0x080c, 0xd0ce, 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, - 0x0001, 0x080c, 0xafec, 0x00be, 0x0005, 0x7110, 0xd1bc, 0x0158, - 0x00d1, 0x0148, 0x080c, 0x8533, 0x1130, 0x7124, 0x610a, 0x2009, - 0x0089, 0x080c, 0xafec, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x0059, - 0x0148, 0x080c, 0x8533, 0x1130, 0x7124, 0x610a, 0x2009, 0x008a, - 0x080c, 0xafec, 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, 0xafec, 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, 0xaef8, 0x05a8, 0x0066, 0x00c6, 0x0046, 0x2011, - 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x26a1, 0x1590, 0x080c, - 0x6718, 0x1578, 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce, 0x6012, - 0x080c, 0xd0ce, 0x080c, 0x104d, 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, - 0x9427, 0x00fe, 0x009e, 0x00ce, 0x0005, 0x080c, 0xaf4e, 0x006e, - 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6, 0x7000, 0x908c, 0xff00, - 0x9184, 0xf000, 0x810f, 0x9086, 0x2000, 0x1904, 0x86c3, 0x9186, - 0x0022, 0x15f0, 0x2001, 0x0111, 0x2004, 0x9005, 0x1904, 0x86c5, - 0x7030, 0x908e, 0x0400, 0x0904, 0x86c5, 0x908e, 0x6000, 0x05e8, - 0x908e, 0x5400, 0x05d0, 0x908e, 0x0300, 0x11d8, 0x2009, 0x1837, - 0x210c, 0xd18c, 0x1590, 0xd1a4, 0x1580, 0x080c, 0x6b8b, 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, 0x85db, 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, 0xbf40, 0x1178, 0xd48c, 0x0148, 0x20a9, - 0x0004, 0x2019, 0x1801, 0x2011, 0x027e, 0x080c, 0xbf40, 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, 0xbf40, 0x1178, 0xd48c, 0x0148, 0x20a9, - 0x0004, 0x2019, 0x1801, 0x2011, 0x0276, 0x080c, 0xbf40, 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, - 0x1a05, 0x7003, 0x0003, 0x700f, 0x0361, 0x9006, 0x701a, 0x707a, - 0x7012, 0x7017, 0x1ddc, 0x7007, 0x0000, 0x7026, 0x702b, 0xa0bb, - 0x7032, 0x7037, 0xa138, 0x7047, 0xffff, 0x704a, 0x704f, 0x56a4, - 0x7052, 0x7063, 0x88ff, 0x080c, 0x1066, 0x090c, 0x0d79, 0x2900, - 0x7042, 0xa867, 0x0003, 0xa86f, 0x0100, 0xa8ab, 0xdcb0, 0x0005, - 0x2071, 0x1a05, 0x1d04, 0x881b, 0x2091, 0x6000, 0x700c, 0x8001, - 0x700e, 0x1590, 0x2001, 0x013c, 0x2004, 0x9005, 0x190c, 0x89a9, - 0x2001, 0x1869, 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, - 0x20d1, 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0d79, - 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x2069, - 0x1800, 0x69ec, 0xd1e4, 0x1138, 0xd1dc, 0x1118, 0x080c, 0x896d, - 0x0010, 0x080c, 0x8944, 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, 0xa1e6, 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, 0x8843, 0x8844, 0x886e, - 0x00e6, 0x2071, 0x1a05, 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, - 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x1a05, - 0x701c, 0x9206, 0x1120, 0x701a, 0x701e, 0x707a, 0x707e, 0x000e, - 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1a05, 0xb888, 0x9102, 0x0208, - 0xb98a, 0x00ee, 0x0005, 0x0005, 0x00b6, 0x2031, 0x0010, 0x7110, - 0x080c, 0x6783, 0x11a8, 0xb888, 0x8001, 0x0290, 0xb88a, 0x1180, - 0x0126, 0x2091, 0x8000, 0x0066, 0xb8d0, 0x9005, 0x0138, 0x0026, - 0xba3c, 0x0016, 0x080c, 0x68ae, 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, 0xcf4f, 0x6018, 0x9005, 0x0904, - 0x88c6, 0x00f6, 0x2079, 0x0300, 0x7918, 0xd1b4, 0x1904, 0x88d9, - 0x781b, 0x2020, 0xa001, 0x7918, 0xd1b4, 0x0120, 0x781b, 0x2000, - 0x0804, 0x88d9, 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, 0xcc33, 0x01b0, 0x6014, 0x2048, - 0xa884, 0x908a, 0x199a, 0x0280, 0x9082, 0x1999, 0xa886, 0x908a, - 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, - 0x611a, 0x080c, 0xd389, 0x0110, 0x080c, 0xc910, 0x012e, 0x9c88, - 0x001c, 0x7116, 0x2001, 0x181a, 0x2004, 0x9102, 0x1228, 0x8631, - 0x0138, 0x2160, 0x0804, 0x8872, 0x7017, 0x1ddc, 0x7007, 0x0000, - 0x0005, 0x00fe, 0x0c58, 0x00e6, 0x2071, 0x1a05, 0x7027, 0x07d0, - 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, 0x1a0e, 0x2003, 0x0000, - 0x0005, 0x00e6, 0x2071, 0x1a05, 0x7132, 0x702f, 0x0009, 0x00ee, - 0x0005, 0x2011, 0x1a11, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, - 0x1a05, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, - 0x0026, 0x705c, 0x8000, 0x705e, 0x2001, 0x1a15, 0x2044, 0xa06c, - 0x9086, 0x0000, 0x0150, 0x7070, 0xa09a, 0x706c, 0xa096, 0x7068, - 0xa092, 0x7064, 0xa08e, 0x080c, 0x1142, 0x002e, 0x008e, 0x0005, - 0x0006, 0x0016, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x0156, 0x080c, 0x8780, 0x015e, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x00be, 0x00ae, 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, - 0x2071, 0x1a05, 0x717a, 0x727e, 0x7077, 0x0009, 0x00ee, 0x0005, - 0x00e6, 0x0006, 0x2071, 0x1a05, 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, 0x0f18, 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, 0x0f3a, 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, 0x0f3a, 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, 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, 0x8a87, 0xd0b4, 0x1168, 0xd0bc, 0x1904, - 0x8a60, 0x2009, 0x0006, 0x080c, 0x8ab4, 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, 0x1c8c, 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, 0x8aae, 0x908c, 0x2020, 0x918e, 0x2020, - 0x01a8, 0x6024, 0xd0d4, 0x11e8, 0x2009, 0x1869, 0x2104, 0xd084, - 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0xafec, 0x0005, - 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, 0xafec, 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, - 0x8aae, 0x908c, 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, - 0x2c78, 0x080c, 0x17a1, 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, - 0x0042, 0x080c, 0xafec, 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, - 0xafec, 0x0005, 0x00b9, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, - 0x080c, 0xafec, 0x0cb0, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, - 0xd1ac, 0x0d20, 0x6124, 0xc1cd, 0x6126, 0x0c00, 0x2009, 0x0004, - 0x0019, 0x0005, 0x2009, 0x0001, 0x0096, 0x080c, 0xcc33, 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, 0x6d4b, 0x6014, 0x904d, 0x0076, 0x2039, 0x0000, - 0x190c, 0x89cd, 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, 0x1925, - 0x7003, 0x0006, 0x7007, 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, - 0x080c, 0x1066, 0x090c, 0x0d79, 0xa867, 0x0006, 0xa86b, 0x0001, - 0xa8ab, 0xdcb0, 0xa89f, 0x0000, 0x2900, 0x702e, 0x7033, 0x0000, - 0x0005, 0x0126, 0x2091, 0x8000, 0x0096, 0x00e6, 0x2071, 0x1925, - 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, 0x1b74, 0x2104, 0x9082, 0x0007, 0x200a, 0x000e, - 0xc095, 0x7012, 0x2008, 0x2001, 0x003b, 0x080c, 0x16ad, 0x9006, - 0x2071, 0x193e, 0x7002, 0x7006, 0x702a, 0x00ee, 0x009e, 0x012e, - 0x0005, 0x2009, 0x1b74, 0x2104, 0x9080, 0x0007, 0x200a, 0x0005, - 0x00e6, 0x0126, 0x0156, 0x2091, 0x8000, 0x2071, 0x1800, 0x7154, - 0x2001, 0x0008, 0x910a, 0x0638, 0x2001, 0x187d, 0x20ac, 0x9006, - 0x9080, 0x0008, 0x1f04, 0x8b70, 0x71c0, 0x9102, 0x02e0, 0x2071, - 0x1877, 0x20a9, 0x0007, 0x00c6, 0x080c, 0xaef8, 0x6023, 0x0009, - 0x6003, 0x0004, 0x601f, 0x0101, 0x0089, 0x0126, 0x2091, 0x8000, - 0x080c, 0x8cf1, 0x012e, 0x1f04, 0x8b7c, 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, 0x104d, 0x090c, 0x0d79, - 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, 0x104d, 0x090c, 0x0d79, 0xad66, 0x2b00, 0xa802, - 0x2900, 0xb806, 0x2058, 0x8109, 0x1da0, 0x002e, 0x004e, 0x005e, - 0x008e, 0x009e, 0x00be, 0x00ee, 0x0005, 0x2079, 0x0000, 0x2071, - 0x1925, 0x7004, 0x004b, 0x700c, 0x0002, 0x8be8, 0x8be1, 0x8be1, - 0x0005, 0x8bf2, 0x8c48, 0x8c48, 0x8c48, 0x8c49, 0x8c5a, 0x8c5a, - 0x700c, 0x0cba, 0x0126, 0x2091, 0x8000, 0x78a0, 0x79a0, 0x9106, - 0x1904, 0x8c3a, 0x7814, 0xd0bc, 0x1904, 0x8c43, 0x012e, 0x7018, - 0x910a, 0x1128, 0x7030, 0x9005, 0x1904, 0x8c8c, 0x0005, 0x1210, - 0x7114, 0x910a, 0x9192, 0x000a, 0x0210, 0x2009, 0x000a, 0x2001, - 0x1888, 0x2014, 0x2001, 0x1937, 0x2004, 0x9100, 0x9202, 0x0e50, - 0x080c, 0x8de9, 0x2200, 0x9102, 0x0208, 0x2208, 0x0096, 0x702c, - 0x2048, 0xa873, 0x0001, 0xa976, 0x080c, 0x8ef2, 0x2100, 0xa87e, - 0xa86f, 0x0000, 0x009e, 0x0126, 0x2091, 0x8000, 0x2009, 0x1a25, - 0x2104, 0xc085, 0x200a, 0x700f, 0x0002, 0x012e, 0x080c, 0x1161, - 0x1de8, 0x0005, 0x78a0, 0x79a0, 0x9106, 0x0904, 0x8bfa, 0x080c, - 0x8dc1, 0x012e, 0x0005, 0x7810, 0xc0c5, 0x7812, 0x0804, 0x8bfa, - 0x0005, 0x700c, 0x0002, 0x8c4e, 0x8c51, 0x8c50, 0x080c, 0x8bf0, - 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, 0x8ef2, 0x2100, 0xaa8c, 0x9210, 0xaa8e, - 0x1220, 0xa890, 0x9081, 0x0000, 0xa892, 0x000e, 0x009e, 0x0126, - 0x2091, 0x8000, 0x78a2, 0x701a, 0x080c, 0x8dc1, 0x012e, 0x0005, - 0x00e6, 0x2071, 0x1925, 0x700c, 0x0002, 0x8c8a, 0x8c8a, 0x8c88, - 0x700f, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x7030, - 0x9005, 0x0508, 0x2078, 0x7814, 0x2048, 0xae88, 0x00b6, 0x2059, - 0x0000, 0x080c, 0x8cfa, 0x00be, 0x01b0, 0x00e6, 0x2071, 0x193e, - 0x080c, 0x8d41, 0x00ee, 0x0178, 0x0096, 0x080c, 0x1066, 0x2900, - 0x009e, 0x0148, 0xa8aa, 0x04d1, 0x0041, 0x2001, 0x1948, 0x2003, - 0x0000, 0x012e, 0x08c8, 0x012e, 0x0005, 0x00d6, 0x00c6, 0x0086, - 0x00a6, 0x2940, 0x2650, 0x2600, 0x9005, 0x0180, 0xa864, 0x9084, - 0x000f, 0x2068, 0x9d88, 0x1ede, 0x2165, 0x0056, 0x2029, 0x0000, - 0x080c, 0x8e77, 0x080c, 0x1eb4, 0x1dd8, 0x005e, 0x00ae, 0x2001, - 0x187f, 0x2004, 0xa88a, 0x00c6, 0x2f60, 0x080c, 0x17a1, 0x00ce, - 0x781f, 0x0101, 0x7813, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, - 0x8d50, 0x012e, 0x008e, 0x00ce, 0x00de, 0x0005, 0x7030, 0x9005, - 0x0138, 0x2078, 0x780c, 0x7032, 0x2001, 0x1948, 0x2003, 0x0001, - 0x0005, 0x00e6, 0x2071, 0x1925, 0x7030, 0x600e, 0x2c00, 0x7032, - 0x00ee, 0x0005, 0x00d6, 0x00c6, 0x0026, 0x9b80, 0x8fc0, 0x2005, - 0x906d, 0x090c, 0x0d79, 0x9b80, 0x8fb8, 0x2005, 0x9065, 0x090c, - 0x0d79, 0x6114, 0x2600, 0x9102, 0x0248, 0x6828, 0x9102, 0x02f0, - 0x9085, 0x0001, 0x002e, 0x00ce, 0x00de, 0x0005, 0x6804, 0xd094, - 0x0148, 0x6854, 0xd084, 0x1178, 0xc085, 0x6856, 0x2011, 0x8026, - 0x080c, 0x4c28, 0x684c, 0x0096, 0x904d, 0x090c, 0x0d79, 0xa804, - 0x8000, 0xa806, 0x009e, 0x9006, 0x2030, 0x0c20, 0x6854, 0xd08c, - 0x1d08, 0xc08d, 0x6856, 0x2011, 0x8025, 0x080c, 0x4c28, 0x684c, - 0x0096, 0x904d, 0x090c, 0x0d79, 0xa800, 0x8000, 0xa802, 0x009e, - 0x0888, 0x7000, 0x2019, 0x0008, 0x8319, 0x7104, 0x9102, 0x1118, - 0x2300, 0x9005, 0x0020, 0x0210, 0x9302, 0x0008, 0x8002, 0x0005, - 0x00d6, 0x7814, 0x9005, 0x090c, 0x0d79, 0x781c, 0x9084, 0x0101, - 0x9086, 0x0101, 0x190c, 0x0d79, 0x7827, 0x0000, 0x2069, 0x193e, - 0x6804, 0x9080, 0x1940, 0x2f08, 0x2102, 0x6904, 0x8108, 0x9182, - 0x0008, 0x0208, 0x900e, 0x6906, 0x9180, 0x1940, 0x2003, 0x0000, - 0x00de, 0x0005, 0x0096, 0x00c6, 0x2060, 0x6014, 0x2048, 0xa8a8, - 0x0096, 0x2048, 0x9005, 0x190c, 0x107f, 0x009e, 0xa8ab, 0x0000, - 0x080c, 0x0fff, 0x080c, 0xaf4e, 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, 0x90f5, 0x00be, 0x6013, - 0x0000, 0x601b, 0x0000, 0x0010, 0x2c00, 0x0861, 0x0005, 0x2009, - 0x1929, 0x210c, 0xd194, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, - 0x2071, 0x1925, 0x7110, 0xc194, 0xd19c, 0x1118, 0xc185, 0x7007, - 0x0000, 0x7112, 0x2001, 0x003b, 0x080c, 0x16ad, 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, 0x8f40, - 0x0170, 0x080c, 0x8f75, 0x0158, 0x2900, 0x7002, 0x700a, 0x701a, - 0x7013, 0x0001, 0x701f, 0x000a, 0x00de, 0x009e, 0x0005, 0x900e, - 0x0cd8, 0x00e6, 0x0096, 0x0086, 0x00d6, 0x00c6, 0x2071, 0x1932, - 0x721c, 0x2100, 0x9202, 0x1618, 0x080c, 0x8f75, 0x090c, 0x0d79, - 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, 0x1932, - 0x7300, 0x831f, 0x831e, 0x831e, 0x9384, 0x003f, 0x20e8, 0x939c, - 0xffc0, 0x9398, 0x0003, 0x7104, 0x080c, 0x8ef2, 0x810c, 0x2100, - 0x9318, 0x8003, 0x2228, 0x2021, 0x0078, 0x9402, 0x9532, 0x0208, - 0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0, 0xa001, 0xa001, 0x4005, - 0x2508, 0x080c, 0x8efb, 0x2130, 0x7014, 0x9600, 0x7016, 0x2600, - 0x711c, 0x9102, 0x701e, 0x7004, 0x9600, 0x2008, 0x9082, 0x000a, - 0x1190, 0x7000, 0x2048, 0xa800, 0x9005, 0x1148, 0x2009, 0x0001, - 0x0026, 0x080c, 0x8de9, 0x002e, 0x7000, 0x2048, 0xa800, 0x7002, - 0x7007, 0x0000, 0x0008, 0x7106, 0x2500, 0x9212, 0x1904, 0x8e28, - 0x012e, 0x00ee, 0x014e, 0x013e, 0x015e, 0x009e, 0x0005, 0x0016, - 0x0026, 0x00e6, 0x0126, 0x2091, 0x8000, 0x9580, 0x8fb8, 0x2005, - 0x9075, 0x090c, 0x0d79, 0x080c, 0x8ecd, 0x012e, 0x9580, 0x8fb4, - 0x2005, 0x9075, 0x090c, 0x0d79, 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, 0x8eb7, - 0x8eb7, 0x8eb9, 0x8eb7, 0x8eb9, 0x8eb7, 0x8eb7, 0x8eb7, 0x8eb7, - 0x8eb7, 0x8ebf, 0x8eb7, 0x8ebf, 0x8eb7, 0x8eb7, 0x8eb7, 0x080c, - 0x0d79, 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, 0x8f84, 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, 0x8f3e, 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, 0x8fbc, - 0x2005, 0x9005, 0x090c, 0x0d79, 0x2004, 0x90a0, 0x000a, 0x080c, - 0x1066, 0x01d0, 0x2900, 0x7026, 0xa803, 0x0000, 0xa807, 0x0000, - 0x080c, 0x1066, 0x0188, 0x7024, 0xa802, 0xa807, 0x0000, 0x2900, - 0x7026, 0x94a2, 0x000a, 0x0110, 0x0208, 0x0c90, 0x9085, 0x0001, - 0x012e, 0x004e, 0x009e, 0x0005, 0x7024, 0x9005, 0x0dc8, 0x2048, - 0xac00, 0x080c, 0x107f, 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, 0x107f, - 0x000e, 0x0cb8, 0x009e, 0x0005, 0x0096, 0x7008, 0x9005, 0x0138, - 0x2048, 0xa800, 0x0006, 0x080c, 0x107f, 0x000e, 0x0cb8, 0x9006, - 0x7002, 0x700a, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x702a, - 0x7026, 0x702e, 0x009e, 0x0005, 0x1a72, 0x0000, 0x0000, 0x0000, - 0x1932, 0x0000, 0x0000, 0x0000, 0x1888, 0x0000, 0x0000, 0x0000, - 0x1877, 0x0000, 0x0000, 0x0000, 0x00e6, 0x00c6, 0x00b6, 0x00a6, - 0xa8a8, 0x2040, 0x2071, 0x1877, 0x080c, 0x90e0, 0xa067, 0x0023, - 0x6010, 0x905d, 0x0904, 0x90b5, 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, 0x0d79, 0x2020, - 0x2050, 0x2940, 0xa864, 0x90bc, 0x00ff, 0x908c, 0x000f, 0x91e0, - 0x1ede, 0x2c65, 0x9786, 0x0024, 0x2c05, 0x1590, 0x908a, 0x0036, - 0x1a0c, 0x0d79, 0x9082, 0x001b, 0x0002, 0x9020, 0x9020, 0x9022, - 0x9020, 0x9020, 0x9020, 0x9024, 0x9020, 0x9020, 0x9020, 0x9026, - 0x9020, 0x9020, 0x9020, 0x9028, 0x9020, 0x9020, 0x9020, 0x902a, - 0x9020, 0x9020, 0x9020, 0x902c, 0x9020, 0x9020, 0x9020, 0x902e, - 0x080c, 0x0d79, 0xa180, 0x04b8, 0xa190, 0x04a8, 0xa1a0, 0x0498, - 0xa1b0, 0x0488, 0xa1c0, 0x0478, 0xa1d0, 0x0468, 0xa1e0, 0x0458, - 0x908a, 0x0034, 0x1a0c, 0x0d79, 0x9082, 0x001b, 0x0002, 0x9052, - 0x9050, 0x9050, 0x9050, 0x9050, 0x9050, 0x9054, 0x9050, 0x9050, - 0x9050, 0x9050, 0x9050, 0x9056, 0x9050, 0x9050, 0x9050, 0x9050, - 0x9050, 0x9058, 0x9050, 0x9050, 0x9050, 0x9050, 0x9050, 0x905a, - 0x080c, 0x0d79, 0xa180, 0x0038, 0xa198, 0x0028, 0xa1b0, 0x0018, - 0xa1c8, 0x0008, 0xa1e0, 0x2600, 0x0002, 0x9076, 0x9078, 0x907a, - 0x907c, 0x907e, 0x9080, 0x9082, 0x9084, 0x9086, 0x9088, 0x908a, - 0x908c, 0x908e, 0x9090, 0x9092, 0x9094, 0x9096, 0x9098, 0x909a, - 0x909c, 0x909e, 0x90a0, 0x90a2, 0x90a4, 0x90a6, 0x080c, 0x0d79, - 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, 0x1eb4, 0x090c, 0x0d79, 0x0804, 0x8ffa, - 0x00ae, 0x00be, 0x00ce, 0x00ee, 0x0005, 0xa86c, 0xa06e, 0xa870, - 0xa072, 0xa077, 0x00ff, 0x9006, 0x0804, 0x8fdc, 0x0006, 0x0016, - 0x00b6, 0x6010, 0x2058, 0xb810, 0x9005, 0x01b0, 0x2001, 0x1926, - 0x2004, 0x9005, 0x0188, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, - 0x1158, 0x0036, 0x0046, 0xbba0, 0x2021, 0x0004, 0x2011, 0x8014, - 0x080c, 0x4c28, 0x004e, 0x003e, 0x00be, 0x001e, 0x000e, 0x0005, - 0x9016, 0x710c, 0xa834, 0x910a, 0xa936, 0x7008, 0x9005, 0x0120, - 0x8210, 0x910a, 0x0238, 0x0130, 0x7010, 0x8210, 0x910a, 0x0210, - 0x0108, 0x0cd8, 0xaa8a, 0xa26a, 0x0005, 0x00f6, 0x00d6, 0x0036, - 0x2079, 0x0300, 0x781b, 0x0200, 0x7818, 0xd094, 0x1dd8, 0x781b, - 0x0202, 0xa001, 0xa001, 0x7818, 0xd094, 0x1da0, 0xb8ac, 0x9005, - 0x01b8, 0x2068, 0x2079, 0x0000, 0x2c08, 0x911e, 0x1118, 0x680c, - 0xb8ae, 0x0060, 0x9106, 0x0140, 0x2d00, 0x2078, 0x680c, 0x9005, - 0x090c, 0x0d79, 0x2068, 0x0cb0, 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, 0x9135, 0x701b, 0x0202, 0xa001, 0xa001, - 0x7018, 0xd094, 0x1d90, 0xb8ac, 0x9005, 0x01e8, 0x2060, 0x600c, - 0xb8ae, 0x6024, 0xc08d, 0x6026, 0x6003, 0x0004, 0x601b, 0x0000, - 0x6013, 0x0000, 0x601f, 0x0101, 0x6014, 0x2048, 0xa88b, 0x0000, - 0xa8a8, 0xa8ab, 0x0000, 0x904d, 0x090c, 0x0d79, 0x080c, 0x107f, - 0x080c, 0x8cf1, 0x0c00, 0x2071, 0x0300, 0x701b, 0x0200, 0x015e, - 0x012e, 0x003e, 0x00ce, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, - 0x00b6, 0x0016, 0x0006, 0x0156, 0x080c, 0x26a1, 0x015e, 0x11b0, - 0x080c, 0x6718, 0x190c, 0x0d79, 0x000e, 0x001e, 0xb912, 0xb816, - 0x080c, 0xaef8, 0x0140, 0x2b00, 0x6012, 0x6023, 0x0001, 0x2009, - 0x0001, 0x080c, 0xafec, 0x00be, 0x00ce, 0x0005, 0x000e, 0x001e, - 0x0cd0, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d79, 0x0013, - 0x006e, 0x0005, 0x91aa, 0x91aa, 0x91aa, 0x91ac, 0x91f5, 0x91aa, - 0x91aa, 0x91aa, 0x925c, 0x91aa, 0x9294, 0x91aa, 0x91aa, 0x91aa, - 0x91aa, 0x91aa, 0x080c, 0x0d79, 0x9182, 0x0040, 0x0002, 0x91bf, - 0x91bf, 0x91bf, 0x91bf, 0x91bf, 0x91bf, 0x91bf, 0x91bf, 0x91bf, - 0x91c1, 0x91d2, 0x91bf, 0x91bf, 0x91bf, 0x91bf, 0x91e3, 0x080c, - 0x0d79, 0x0096, 0x6114, 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, - 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, 0x6d10, 0x080c, 0xaf4e, - 0x009e, 0x0005, 0x080c, 0x9851, 0x00d6, 0x6114, 0x080c, 0xcc33, - 0x0130, 0x0096, 0x6114, 0x2148, 0x080c, 0x6f11, 0x009e, 0x00de, - 0x080c, 0xaf4e, 0x0005, 0x080c, 0x9851, 0x080c, 0x32fb, 0x6114, - 0x0096, 0x2148, 0x080c, 0xcc33, 0x0120, 0xa87b, 0x0029, 0x080c, - 0x6f11, 0x009e, 0x080c, 0xaf4e, 0x0005, 0x601b, 0x0000, 0x9182, - 0x0040, 0x0096, 0x0002, 0x9210, 0x9210, 0x9210, 0x9210, 0x9210, - 0x9210, 0x9210, 0x9210, 0x9212, 0x9210, 0x9210, 0x9210, 0x9258, - 0x9210, 0x9210, 0x9210, 0x9210, 0x9210, 0x9210, 0x9219, 0x9210, - 0x080c, 0x0d79, 0x6114, 0x2148, 0xa938, 0x918e, 0xffff, 0x0904, - 0x9258, 0x6024, 0xd08c, 0x15c0, 0x00e6, 0x6114, 0x2148, 0x080c, - 0x8fc4, 0x0096, 0xa8a8, 0x2048, 0x080c, 0x6ca8, 0x009e, 0xa8ab, - 0x0000, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, 0x90f5, - 0x00be, 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8cfa, 0x00be, - 0x01e0, 0x2071, 0x193e, 0x080c, 0x8d41, 0x01b8, 0x9086, 0x0001, - 0x1128, 0x2001, 0x1948, 0x2004, 0x9005, 0x1178, 0x0096, 0x080c, - 0x104d, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x00f6, 0x2c78, 0x080c, - 0x8cb5, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x080c, 0x8cf1, 0x0cd0, - 0x080c, 0x9310, 0x009e, 0x0005, 0x9182, 0x0040, 0x0096, 0x0002, - 0x9270, 0x9270, 0x9270, 0x9272, 0x9270, 0x9270, 0x9270, 0x9292, - 0x9270, 0x9270, 0x9270, 0x9270, 0x9270, 0x9270, 0x9270, 0x9270, - 0x080c, 0x0d79, 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, 0x1c43, 0x2009, 0x8030, 0x080c, 0x9467, - 0x009e, 0x0005, 0x080c, 0x0d79, 0x080c, 0x9851, 0x6114, 0x2148, - 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, - 0x080c, 0x6f11, 0x080c, 0xaf4e, 0x009e, 0x0005, 0x080c, 0xaaf7, - 0x6144, 0xd1fc, 0x0120, 0xd1ac, 0x1110, 0x6003, 0x0003, 0x6000, - 0x908a, 0x0010, 0x1a0c, 0x0d79, 0x0096, 0x0023, 0x009e, 0x080c, - 0xab13, 0x0005, 0x92ca, 0x92ca, 0x92ca, 0x92cc, 0x92dd, 0x92ca, - 0x92ca, 0x92ca, 0x92ca, 0x92ca, 0x92ca, 0x92ca, 0x92ca, 0x92ca, - 0x92ca, 0x92ca, 0x080c, 0x0d79, 0x080c, 0xaccf, 0x6114, 0x2148, - 0xa87b, 0x0006, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, - 0x080c, 0x6f11, 0x080c, 0xaf4e, 0x0005, 0x0491, 0x0005, 0x080c, - 0xaaf7, 0x6000, 0x6144, 0xd1fc, 0x0130, 0xd1ac, 0x1120, 0x6003, - 0x0003, 0x2009, 0x0003, 0x908a, 0x0010, 0x1a0c, 0x0d79, 0x0096, - 0x0033, 0x009e, 0x0106, 0x080c, 0xab13, 0x010e, 0x0005, 0x9307, - 0x9307, 0x9307, 0x9309, 0x9310, 0x9307, 0x9307, 0x9307, 0x9307, - 0x9307, 0x9307, 0x9307, 0x9307, 0x9307, 0x9307, 0x9307, 0x080c, - 0x0d79, 0x0036, 0x00e6, 0x080c, 0xaccf, 0x00ee, 0x003e, 0x0005, - 0x6024, 0xd08c, 0x11f0, 0x00f6, 0x00e6, 0x601b, 0x0000, 0x6014, - 0x2048, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, 0x90f5, - 0x00be, 0x2071, 0x193e, 0x080c, 0x8d41, 0x0160, 0x2001, 0x187f, - 0x2004, 0xa88a, 0x2031, 0x0000, 0x2c78, 0x080c, 0x8cb5, 0x00ee, - 0x00fe, 0x0005, 0x0096, 0xa88b, 0x0000, 0xa8a8, 0x2048, 0x080c, - 0x107f, 0x009e, 0xa8ab, 0x0000, 0x080c, 0x8cf1, 0x0c80, 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, 0x9358, 0x8086, 0x818e, - 0x004e, 0x003e, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0076, - 0x0156, 0x20a9, 0x0010, 0x9005, 0x01c8, 0x911a, 0x12b8, 0x8213, - 0x818d, 0x0228, 0x911a, 0x1220, 0x1f04, 0x936f, 0x0028, 0x911a, - 0x2308, 0x8210, 0x1f04, 0x936f, 0x0006, 0x3200, 0x9084, 0xefff, - 0x2080, 0x000e, 0x015e, 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, - 0x9085, 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, 0x2079, 0x19e9, - 0x012e, 0x00d6, 0x2069, 0x19e9, 0x6803, 0x0005, 0x0156, 0x0146, - 0x01d6, 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, 0xa8ec, 0x04c9, - 0x080c, 0xa8d7, 0x04b1, 0x080c, 0xa8da, 0x0499, 0x080c, 0xa8dd, - 0x0481, 0x080c, 0xa8e0, 0x0469, 0x080c, 0xa8e3, 0x0451, 0x080c, - 0xa8e6, 0x0439, 0x080c, 0xa8e9, 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, 0x1b5e, 0x2003, 0x0000, 0x00de, - 0x0005, 0x20a9, 0x0020, 0x20a1, 0x0240, 0x2001, 0x0000, 0x4004, - 0x0005, 0x00c6, 0x7803, 0x0000, 0x9006, 0x7827, 0x0030, 0x782b, - 0x0400, 0x7827, 0x0031, 0x782b, 0x1af7, 0x781f, 0xff00, 0x781b, - 0xff00, 0x2061, 0x1aec, 0x602f, 0x19e9, 0x6033, 0x1800, 0x6037, - 0x1a05, 0x603b, 0x1ede, 0x603f, 0x1eee, 0x6042, 0x6047, 0x1ac2, - 0x00ce, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, - 0x0001, 0x01b0, 0x00c6, 0x6146, 0x600f, 0x0000, 0x2c08, 0x2061, - 0x19e9, 0x602c, 0x8000, 0x602e, 0x601c, 0x9005, 0x0130, 0x9080, - 0x0003, 0x2102, 0x611e, 0x00ce, 0x0005, 0x6122, 0x611e, 0x0cd8, - 0x6146, 0x2c08, 0x2001, 0x0012, 0x080c, 0xaae8, 0x0005, 0x0016, - 0x2009, 0x8020, 0x6146, 0x2c08, 0x2001, 0x0382, 0x2004, 0x9084, - 0x0007, 0x9086, 0x0001, 0x1128, 0x2001, 0x0019, 0x080c, 0xaae8, - 0x0088, 0x00c6, 0x2061, 0x19e9, 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, 0x19e9, 0x6044, 0x9005, 0x0130, 0x9080, 0x0003, - 0x2102, 0x6146, 0x00ce, 0x0005, 0x614a, 0x6146, 0x0cd8, 0x6146, - 0x600f, 0x0000, 0x2c08, 0x2001, 0x0013, 0x080c, 0xaae8, 0x0005, - 0x6044, 0xd0dc, 0x0110, 0x080c, 0xa585, 0x0005, 0x00f6, 0x00e6, - 0x00d6, 0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, 0x0056, 0x0036, - 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x19e9, 0x7648, - 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x94fa, 0x9c86, - 0x1b56, 0x0904, 0x94f5, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, - 0x94f5, 0x87ff, 0x0120, 0x605c, 0x9106, 0x1904, 0x94f5, 0x704c, - 0x9c06, 0x1188, 0x0036, 0x2019, 0x0001, 0x080c, 0xa391, 0x703f, - 0x0000, 0x9006, 0x704e, 0x706a, 0x7052, 0x706e, 0x080c, 0xade0, - 0x003e, 0x2029, 0x0001, 0x080c, 0x9470, 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, - 0xcc33, 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, 0x1588, - 0x6004, 0x9086, 0x0040, 0x090c, 0xa585, 0xa867, 0x0103, 0xab7a, - 0xa877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xcf38, 0x080c, - 0xeaee, 0x080c, 0x6f11, 0x007e, 0x003e, 0x001e, 0x080c, 0xce24, - 0x080c, 0xaf89, 0x00ce, 0x0804, 0x948c, 0x2c78, 0x600c, 0x2060, - 0x0804, 0x948c, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, - 0x006e, 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, - 0x080c, 0xeaee, 0x080c, 0xe738, 0x007e, 0x003e, 0x001e, 0x08c0, - 0x6020, 0x9086, 0x0009, 0x1168, 0xa87b, 0x0006, 0x0016, 0x0036, - 0x0076, 0x080c, 0x6f11, 0x080c, 0xaf4e, 0x007e, 0x003e, 0x001e, - 0x0848, 0x6020, 0x9086, 0x000a, 0x0904, 0x94df, 0x0804, 0x94d8, - 0x0006, 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, - 0x2091, 0x8000, 0x2079, 0x19e9, 0x7848, 0x9065, 0x0904, 0x9599, - 0x600c, 0x0006, 0x600f, 0x0000, 0x784c, 0x9c06, 0x11b0, 0x0036, - 0x2019, 0x0001, 0x080c, 0xa391, 0x783f, 0x0000, 0x901e, 0x7b4e, - 0x7b6a, 0x7b52, 0x7b6e, 0x080c, 0xade0, 0x003e, 0x000e, 0x9005, - 0x1118, 0x600c, 0x600f, 0x0000, 0x0006, 0x9c86, 0x1b56, 0x05b0, - 0x00e6, 0x2f70, 0x080c, 0x9470, 0x00ee, 0x080c, 0xcc33, 0x0548, - 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, 0x15a8, 0x3e08, 0x918e, - 0x0002, 0x1188, 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x0140, 0x6048, 0x9005, 0x11c0, 0x2001, 0x1989, - 0x2004, 0x604a, 0x0098, 0x6004, 0x9086, 0x0040, 0x090c, 0xa585, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6f05, 0x080c, - 0xce24, 0x6044, 0xc0fc, 0x6046, 0x080c, 0xaf89, 0x000e, 0x0804, - 0x953d, 0x7e4a, 0x7e46, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x009e, - 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, - 0xe738, 0x0c38, 0x6020, 0x9086, 0x0009, 0x1130, 0xab7a, 0x080c, - 0x6f11, 0x080c, 0xaf4e, 0x0c10, 0x6020, 0x9086, 0x000a, 0x0990, - 0x0850, 0x0016, 0x0026, 0x0086, 0x9046, 0x00a9, 0x080c, 0x96ac, - 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0x19e9, - 0x2091, 0x8000, 0x080c, 0x96f5, 0x080c, 0x978b, 0x080c, 0x690e, - 0x012e, 0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19e9, 0x7620, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9671, 0x6010, - 0x2058, 0xb8a0, 0x9206, 0x1904, 0x966c, 0x88ff, 0x0120, 0x605c, - 0x9106, 0x1904, 0x966c, 0x7030, 0x9c06, 0x1580, 0x2069, 0x0100, - 0x6820, 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x88e4, 0x080c, - 0xa09b, 0x68c3, 0x0000, 0x080c, 0xa585, 0x7033, 0x0000, 0x0036, - 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2aa2, 0x9006, 0x080c, 0x2aa2, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0040, 0x7008, 0xc0ad, - 0x700a, 0x6003, 0x0009, 0x630a, 0x0804, 0x966c, 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, 0xcc33, 0x01e8, - 0x6020, 0x9086, 0x0003, 0x1580, 0x080c, 0xce4a, 0x1118, 0x080c, - 0xb93c, 0x0098, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, - 0x0036, 0x0086, 0x080c, 0xcf38, 0x080c, 0xeaee, 0x080c, 0x6f11, - 0x008e, 0x003e, 0x001e, 0x080c, 0xce24, 0x080c, 0xaf89, 0x080c, - 0xa458, 0x00ce, 0x0804, 0x95e4, 0x2c78, 0x600c, 0x2060, 0x0804, - 0x95e4, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x009e, 0x00be, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, - 0x0016, 0x0036, 0x0086, 0x080c, 0xeaee, 0x080c, 0xe738, 0x008e, - 0x003e, 0x001e, 0x08d0, 0x080c, 0xb93c, 0x6020, 0x9086, 0x0002, - 0x1160, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0904, 0x9652, - 0x9086, 0x008b, 0x0904, 0x9652, 0x0840, 0x6020, 0x9086, 0x0005, - 0x1920, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x09c8, 0x9086, - 0x008b, 0x09b0, 0x0804, 0x9665, 0x0006, 0x00f6, 0x00e6, 0x0096, - 0x00b6, 0x00c6, 0x0066, 0x0016, 0x0126, 0x2091, 0x8000, 0x9280, - 0x1000, 0x2004, 0x905d, 0x2079, 0x19e9, 0x9036, 0x7828, 0x2060, - 0x8cff, 0x0538, 0x6010, 0x9b06, 0x1500, 0x6043, 0xffff, 0x080c, - 0xad1a, 0x01d8, 0x610c, 0x0016, 0x080c, 0xa21b, 0x6014, 0x2048, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0086, - 0x080c, 0xcf38, 0x080c, 0xeaee, 0x080c, 0x6f11, 0x008e, 0x003e, - 0x001e, 0x080c, 0xaf89, 0x00ce, 0x08d8, 0x2c30, 0x600c, 0x2060, - 0x08b8, 0x080c, 0x692b, 0x012e, 0x001e, 0x006e, 0x00ce, 0x00be, - 0x009e, 0x00ee, 0x00fe, 0x000e, 0x0005, 0x0096, 0x0006, 0x0066, - 0x00c6, 0x00d6, 0x9036, 0x7820, 0x9065, 0x0904, 0x975e, 0x600c, - 0x0006, 0x6044, 0xc0fc, 0x6046, 0x600f, 0x0000, 0x7830, 0x9c06, - 0x1598, 0x2069, 0x0100, 0x6820, 0xd0a4, 0x0110, 0xd0cc, 0x1508, - 0x080c, 0x88e4, 0x080c, 0xa09b, 0x68c3, 0x0000, 0x080c, 0xa585, - 0x7833, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2aa2, 0x9006, 0x080c, 0x2aa2, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, - 0x0058, 0x080c, 0x6b65, 0x1538, 0x6003, 0x0009, 0x630a, 0x7808, - 0xc0ad, 0x780a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, 0xcc31, - 0x01b0, 0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xce4a, 0x1118, - 0x080c, 0xb93c, 0x0060, 0x080c, 0x6b65, 0x1168, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6f11, 0x080c, 0xce24, 0x080c, - 0xaf89, 0x080c, 0xa458, 0x000e, 0x0804, 0x96fc, 0x7e22, 0x7e1e, - 0x00de, 0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1118, 0x080c, 0xe738, 0x0c50, 0x080c, 0xb93c, 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, 0xad1a, 0x0180, 0x610c, 0x080c, 0xa21b, 0x6014, - 0x2048, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6f11, - 0x080c, 0xaf89, 0x000e, 0x08f0, 0x2c30, 0x0ce0, 0x006e, 0x00ce, - 0x00be, 0x009e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, 0x0066, - 0x080c, 0x628a, 0x11b0, 0x2071, 0x19e9, 0x7030, 0x9080, 0x0005, - 0x2004, 0x904d, 0x0170, 0xa878, 0x9606, 0x1158, 0x2071, 0x19e9, - 0x7030, 0x9035, 0x0130, 0x9080, 0x0005, 0x2004, 0x9906, 0x1108, - 0x0029, 0x006e, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x2660, - 0x6043, 0xffff, 0x080c, 0xad1a, 0x0178, 0x080c, 0xa21b, 0x6014, - 0x2048, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xcf38, - 0x080c, 0x6f11, 0x080c, 0xaf89, 0x00ce, 0x0005, 0x00b6, 0x00e6, - 0x00c6, 0x080c, 0xaaf7, 0x0106, 0x2071, 0x0101, 0x2e04, 0xc0c4, - 0x2072, 0x6044, 0xd0fc, 0x1138, 0x010e, 0x090c, 0xab13, 0x00ce, - 0x00ee, 0x00be, 0x0005, 0x2071, 0x19e9, 0x7030, 0x9005, 0x0da0, - 0x9c06, 0x190c, 0x0d79, 0x7036, 0x080c, 0x88e4, 0x7004, 0x9084, - 0x0007, 0x0002, 0x9824, 0x9826, 0x982d, 0x9837, 0x9845, 0x9824, - 0x9832, 0x9822, 0x080c, 0x0d79, 0x0428, 0x0005, 0x080c, 0xad05, - 0x7007, 0x0000, 0x7033, 0x0000, 0x00e8, 0x0066, 0x9036, 0x080c, - 0xa21b, 0x006e, 0x7007, 0x0000, 0x7033, 0x0000, 0x0098, 0x080c, - 0xacf0, 0x0140, 0x080c, 0xad05, 0x0128, 0x0066, 0x9036, 0x080c, - 0xa21b, 0x006e, 0x7033, 0x0000, 0x0028, 0x080c, 0xacf0, 0x080c, - 0xa585, 0x0000, 0x010e, 0x090c, 0xab13, 0x00ce, 0x00ee, 0x00be, - 0x0005, 0x00d6, 0x00c6, 0x080c, 0xaaf7, 0x0106, 0x6044, 0xd0fc, - 0x1130, 0x010e, 0x090c, 0xab13, 0x00ce, 0x00de, 0x0005, 0x2069, - 0x19e9, 0x684c, 0x9005, 0x0da8, 0x9c06, 0x190c, 0x0d79, 0x6852, - 0x00e6, 0x2d70, 0x080c, 0x9470, 0x00ee, 0x080c, 0x88f1, 0x0016, - 0x2009, 0x0040, 0x080c, 0x223d, 0x001e, 0x683c, 0x9084, 0x0003, - 0x0002, 0x987f, 0x9880, 0x989f, 0x987d, 0x080c, 0x0d79, 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, 0xade0, 0x684f, 0x0000, 0x010e, 0x090c, - 0xab13, 0x00ce, 0x00de, 0x0005, 0x0005, 0x6020, 0x9084, 0x000f, - 0x000b, 0x0005, 0x98d2, 0x98d5, 0x9d7b, 0x9e14, 0x98d5, 0x9d7b, - 0x9e14, 0x98d2, 0x98d5, 0x98d2, 0x98d2, 0x98d2, 0x98d2, 0x98d2, - 0x98d2, 0x98d2, 0x080c, 0x97f6, 0x0005, 0x00b6, 0x0156, 0x0136, - 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, - 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d79, - 0x6110, 0x2158, 0xb984, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a, - 0x0040, 0x1a04, 0x9941, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x9aea, - 0x9b25, 0x9b4e, 0x9c0a, 0x9c2c, 0x9c32, 0x9c3f, 0x9c47, 0x9c53, - 0x9c59, 0x9c6a, 0x9c59, 0x9cc2, 0x9c47, 0x9cce, 0x9cd4, 0x9c53, - 0x9cd4, 0x9ce0, 0x993f, 0x993f, 0x993f, 0x993f, 0x993f, 0x993f, - 0x993f, 0x993f, 0x993f, 0x993f, 0x993f, 0xa23c, 0xa25f, 0xa270, - 0xa290, 0xa2c2, 0x9c3f, 0x993f, 0x9c3f, 0x9c59, 0x993f, 0x9b4e, - 0x9c0a, 0x993f, 0xa683, 0x9c59, 0x993f, 0xa69f, 0x9c59, 0x993f, - 0x9c53, 0x9ae4, 0x9962, 0x993f, 0xa6bb, 0xa728, 0xa80c, 0x993f, - 0xa819, 0x9c3c, 0xa844, 0x993f, 0xa2cc, 0xa850, 0x993f, 0x080c, - 0x0d79, 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, - 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0xa8f0, 0xa9a2, - 0x9960, 0x999a, 0x9a46, 0x9a51, 0x9960, 0x9c3f, 0x9960, 0x9aab, - 0x9ab7, 0x99b5, 0x9960, 0x99d0, 0x9a04, 0xadf4, 0xae39, 0x9c59, - 0x080c, 0x0d79, 0x00d6, 0x0096, 0x080c, 0x9cf3, 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, 0xa06b, 0x003e, - 0x002e, 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, - 0x00be, 0x080c, 0xae80, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, - 0x0001, 0x0005, 0x00d6, 0x0096, 0x080c, 0x9cf3, 0x7003, 0x0500, - 0x7814, 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, - 0xa880, 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, - 0x080c, 0xa06b, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, - 0x9cf3, 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, - 0x700e, 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, - 0x701e, 0x60c3, 0x0010, 0x080c, 0xa06b, 0x009e, 0x00de, 0x0005, - 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0x9cf3, 0x20e9, - 0x0000, 0x2001, 0x19a5, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, - 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x001b, 0x2098, 0x2001, 0x19a5, 0x0016, 0x200c, 0x2001, 0x0001, - 0x080c, 0x2222, 0x080c, 0xda05, 0x9006, 0x080c, 0x2222, 0x001e, - 0xa804, 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0xa06b, - 0x012e, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, - 0x8000, 0x080c, 0x9d3e, 0x20e9, 0x0000, 0x2001, 0x19a5, 0x2003, - 0x0000, 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, - 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x001b, 0x2098, 0x2001, 0x19a5, 0x0016, 0x200c, 0x080c, 0xda05, - 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, - 0x2048, 0x080c, 0x0fff, 0x080c, 0xa06b, 0x012e, 0x009e, 0x00de, - 0x0005, 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, - 0x0004, 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x9cf3, - 0x7003, 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, - 0xa06b, 0x00d6, 0x00e6, 0x080c, 0x9d3e, 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, 0x9a71, 0x2069, 0x1801, - 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9a7a, 0x9096, - 0xdf00, 0x0130, 0x9096, 0xe000, 0x0118, 0x60c3, 0x0018, 0x00f0, - 0x2069, 0x19b5, 0x9086, 0xdf00, 0x0110, 0x2069, 0x19cf, 0x20a9, - 0x001a, 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, - 0x8000, 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, - 0x8d68, 0x8e70, 0x1f04, 0x9a91, 0x60c3, 0x004c, 0x080c, 0xa06b, - 0x00ee, 0x00de, 0x0005, 0x080c, 0x9cf3, 0x7003, 0x6300, 0x7007, - 0x0028, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa06b, 0x00d6, - 0x0026, 0x0016, 0x080c, 0x9d3e, 0x7003, 0x0200, 0x7814, 0x700e, - 0x00e6, 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2069, - 0x1925, 0x6810, 0xd084, 0x1148, 0x2073, 0x0500, 0x8e70, 0x2073, - 0x0000, 0x8e70, 0x8108, 0x9290, 0x0004, 0x2073, 0x0800, 0x8e70, - 0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, 0xa06b, - 0x001e, 0x002e, 0x00de, 0x0005, 0x2001, 0x1818, 0x2004, 0x609a, - 0x0804, 0xa06b, 0x080c, 0x9cf3, 0x7003, 0x5200, 0x2069, 0x1847, - 0x6804, 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x26d4, 0x710e, - 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, - 0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, - 0x20a1, 0x0254, 0x4003, 0x080c, 0xae80, 0x1120, 0xb8a0, 0x9082, - 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, 0x7032, 0x2001, 0x1820, - 0x2004, 0x7036, 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, - 0x7036, 0x60c3, 0x001c, 0x0804, 0xa06b, 0x080c, 0x9cf3, 0x7003, - 0x0500, 0x080c, 0xae80, 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, 0xa06b, 0x080c, 0x9cf3, - 0x9006, 0x080c, 0x6b97, 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, 0x9bd1, 0x00d6, 0x2069, 0x196d, - 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0188, 0x6800, 0x700a, 0x6808, - 0x9084, 0x2000, 0x7012, 0x080c, 0xae97, 0x680c, 0x7016, 0x701f, - 0x2710, 0x6818, 0x7022, 0x681c, 0x7026, 0x00f0, 0x6800, 0x700a, - 0x6804, 0x700e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x769d, 0x1128, - 0x78e3, 0x0000, 0x080c, 0x2715, 0x78e2, 0x00fe, 0x6808, 0x080c, - 0x769d, 0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, - 0x080c, 0xae97, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, - 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, - 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, - 0x080c, 0xa8d7, 0x2069, 0x1975, 0x2071, 0x024e, 0x6800, 0xc0dd, - 0x7002, 0x080c, 0x5824, 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, - 0x04a8, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0170, 0x0016, 0x2001, - 0x196e, 0x200c, 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, - 0x080c, 0x2715, 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, 0x196d, - 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, - 0x0004, 0x2099, 0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, - 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x080c, 0xa8d7, 0x20a1, - 0x024e, 0x20a9, 0x0008, 0x2099, 0x1975, 0x4003, 0x60c3, 0x0074, - 0x0804, 0xa06b, 0x080c, 0x9cf3, 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, 0x9ca3, 0x7026, - 0x60c3, 0x0014, 0x0804, 0xa06b, 0x080c, 0x9cf3, 0x7003, 0x5000, - 0x0804, 0x9b70, 0x080c, 0x9cf3, 0x7003, 0x2110, 0x7007, 0x0014, - 0x60c3, 0x0014, 0x0804, 0xa06b, 0x080c, 0x9d35, 0x0010, 0x080c, - 0x9d3e, 0x7003, 0x0200, 0x60c3, 0x0004, 0x0804, 0xa06b, 0x080c, - 0x9d3e, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, - 0x0008, 0x0804, 0xa06b, 0x080c, 0x9d3e, 0x7003, 0x0200, 0x0804, - 0x9b70, 0x080c, 0x9d3e, 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, - 0x700a, 0x0010, 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, - 0x0804, 0xa06b, 0x00d6, 0x080c, 0x9d3e, 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, 0xa06b, 0x080c, 0x9d3e, 0x7003, 0x0210, 0x7007, 0x0014, - 0x700f, 0x0100, 0x60c3, 0x0014, 0x0804, 0xa06b, 0x080c, 0x9d3e, - 0x7003, 0x0200, 0x0804, 0x9aee, 0x080c, 0x9d3e, 0x7003, 0x0100, - 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0xa06b, - 0x080c, 0x9d3e, 0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, - 0x0804, 0xa06b, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, + 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, - 0x2200, 0x2021, 0x0100, 0x080c, 0xa8ec, 0xb810, 0x9305, 0x7002, - 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, - 0x9485, 0x0029, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0xa05f, - 0x721a, 0x9f95, 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, - 0x002e, 0x0005, 0x0026, 0x080c, 0xa8ec, 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, 0xa8ec, - 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, 0xa05f, 0x721a, - 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, - 0x080c, 0xa05f, 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, - 0x024c, 0x002e, 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, - 0x0d79, 0x908a, 0x0092, 0x1a0c, 0x0d79, 0x6110, 0x2158, 0xb984, - 0x2c78, 0x2061, 0x0100, 0x619a, 0x9082, 0x0085, 0x0033, 0x00fe, - 0x00ee, 0x00de, 0x00ce, 0x00be, 0x0005, 0x9dac, 0x9dbb, 0x9dc6, - 0x9daa, 0x9daa, 0x9daa, 0x9dac, 0x9daa, 0x9daa, 0x9daa, 0x9daa, - 0x9daa, 0x9daa, 0x080c, 0x0d79, 0x0411, 0x60c3, 0x0000, 0x0026, - 0x080c, 0x2a11, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, - 0x002e, 0x0804, 0xa06b, 0x0431, 0x7808, 0x700a, 0x7814, 0x700e, - 0x7017, 0xffff, 0x60c3, 0x000c, 0x0804, 0xa06b, 0x04a1, 0x7003, - 0x0003, 0x7007, 0x0300, 0x60c3, 0x0004, 0x0804, 0xa06b, 0x0026, - 0x080c, 0xa8ec, 0xb810, 0x9085, 0x8100, 0x7002, 0xb814, 0x7006, - 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x7013, 0x0009, - 0x0804, 0x9d0e, 0x0026, 0x080c, 0xa8ec, 0xb810, 0x9085, 0x8400, - 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, - 0x700e, 0x2001, 0x0099, 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, - 0x7012, 0x0804, 0x9d70, 0x0026, 0x080c, 0xa8ec, 0xb810, 0x9085, - 0x8500, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, - 0x6880, 0x700e, 0x2001, 0x0099, 0x7a20, 0x9296, 0x0005, 0x0108, - 0xc0bc, 0x7012, 0x0804, 0x9d70, 0x00b6, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x2c78, 0x2069, 0x0200, 0x2071, 0x0240, 0x7804, 0x908a, - 0x0040, 0x0a0c, 0x0d79, 0x908a, 0x0057, 0x1a0c, 0x0d79, 0x7910, - 0x2158, 0xb984, 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, 0x0033, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x0005, 0x9e49, 0x9e49, - 0x9e49, 0x9e7a, 0x9e49, 0x9e49, 0x9e49, 0x9e49, 0x9e49, 0x9e49, - 0x9e49, 0xa43f, 0xa444, 0xa449, 0xa44e, 0x9e49, 0x9e49, 0x9e49, - 0xa43a, 0x080c, 0x0d79, 0x6813, 0x0008, 0xba8c, 0x8210, 0xb8d4, - 0xd084, 0x0180, 0x2001, 0x1b73, 0x200c, 0x8108, 0x2102, 0x2001, - 0x1b72, 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, 0x9e8a, 0x9e8a, 0x9e8c, 0x9e8a, 0x9e8a, 0x9e8a, - 0x9ea6, 0x9e8a, 0x080c, 0x0d79, 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, 0xa06b, 0x2009, 0x0003, - 0x0019, 0x7033, 0x7f00, 0x0cb0, 0x0016, 0x080c, 0xa8ec, 0x001e, - 0xb810, 0x9085, 0x0100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, - 0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, - 0x7116, 0x080c, 0xa05f, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, + 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, - 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, - 0x2adc, 0x2001, 0x00b2, 0x2010, 0x900e, 0x080c, 0x2aeb, 0x2009, - 0x07d0, 0x080c, 0x88e9, 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, - 0x3474, 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, 0x2aeb, - 0x2009, 0x07d0, 0x080c, 0x88e9, 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, 0x9fea, 0x9fea, 0x9fea, 0x9fea, 0x9fea, - 0x9fea, 0x9fea, 0x9fea, 0x9fea, 0x9fea, 0x9fec, 0x9fea, 0x9fea, - 0x9fea, 0x9fea, 0x080c, 0x0d79, 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, 0xa8cc, 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, - 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x88e9, 0x003e, 0x004e, - 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e, 0x00be, 0x0005, 0x7a40, - 0x9294, 0x00ff, 0x8217, 0x0005, 0x00d6, 0x2069, 0x19e9, 0x686b, - 0x0001, 0x00de, 0x0005, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, - 0x080c, 0x88db, 0x0005, 0x0016, 0x2001, 0x180c, 0x200c, 0x9184, - 0x0600, 0x9086, 0x0600, 0x0128, 0x0089, 0x080c, 0x88db, 0x001e, - 0x0005, 0xc1e5, 0x2001, 0x180c, 0x2102, 0x2001, 0x19ea, 0x2003, - 0x0000, 0x2001, 0x19f5, 0x2003, 0x0000, 0x0c88, 0x0006, 0x0016, - 0x0026, 0x2009, 0x1804, 0x2011, 0x0009, 0x080c, 0x2aeb, 0x002e, - 0x001e, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x080c, 0xaaf7, - 0x0106, 0x2061, 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x0016, 0x0026, - 0x2009, 0x1804, 0x2011, 0x0008, 0x080c, 0x2aeb, 0x002e, 0x001e, - 0x010e, 0x090c, 0xab13, 0x000e, 0xa001, 0xa001, 0xa001, 0x61a6, - 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, - 0x0100, 0x2069, 0x0140, 0x080c, 0x769d, 0x1510, 0x2001, 0x1a0e, - 0x2004, 0x9005, 0x1904, 0xa11a, 0x080c, 0x773f, 0x11a8, 0x2069, - 0x0380, 0x6843, 0x0101, 0x6844, 0xd084, 0x1de8, 0x2061, 0x0100, - 0x6020, 0xd0b4, 0x1120, 0x6024, 0xd084, 0x090c, 0x0d79, 0x6843, - 0x0100, 0x080c, 0x88db, 0x04b0, 0x00c6, 0x2061, 0x19e9, 0x00f0, - 0x6904, 0x9194, 0x4000, 0x0598, 0x080c, 0xa09b, 0x080c, 0x2ab2, - 0x00c6, 0x2061, 0x19e9, 0x6134, 0x9192, 0x0008, 0x1278, 0x8108, - 0x6136, 0x080c, 0xaaf7, 0x6130, 0x080c, 0xab13, 0x00ce, 0x81ff, - 0x01c8, 0x080c, 0x88db, 0x080c, 0xa08e, 0x00a0, 0x080c, 0xaaf7, - 0x6130, 0x91e5, 0x0000, 0x0150, 0x080c, 0xebfd, 0x080c, 0x88e4, - 0x6003, 0x0001, 0x2009, 0x0014, 0x080c, 0xafec, 0x080c, 0xab13, - 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, - 0x1a0e, 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, 0x19e9, 0x6134, - 0x9192, 0x0003, 0x1ad8, 0x8108, 0x6136, 0x00ce, 0x080c, 0x88db, - 0x080c, 0x6033, 0x2009, 0x1846, 0x2114, 0x8210, 0x220a, 0x0c10, - 0x0096, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, 0x88f1, - 0x080c, 0xaaf7, 0x2001, 0x0387, 0x2003, 0x0202, 0x2071, 0x19e9, - 0x714c, 0x81ff, 0x0904, 0xa1d4, 0x2061, 0x0100, 0x2069, 0x0140, - 0x080c, 0x769d, 0x1518, 0x0036, 0x2019, 0x0002, 0x080c, 0xa391, - 0x003e, 0x080c, 0xebfd, 0x704c, 0x9065, 0x0180, 0x2009, 0x004a, - 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, - 0x2009, 0x004a, 0x6003, 0x0003, 0x080c, 0xafec, 0x2001, 0x0386, - 0x2003, 0x5040, 0x080c, 0x773f, 0x0804, 0xa1d4, 0x6904, 0xd1f4, - 0x0904, 0xa1e1, 0x080c, 0x2ab2, 0x00c6, 0x704c, 0x9065, 0x090c, - 0x0d79, 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, 0x9851, 0x2009, 0x0049, 0x080c, - 0xafec, 0x0450, 0x080c, 0xebfd, 0x704c, 0x9065, 0x9086, 0x1b56, - 0x1158, 0x080c, 0xadbe, 0x1500, 0x2061, 0x1b56, 0x6064, 0x8000, - 0x6066, 0x080c, 0x6033, 0x00c0, 0x0036, 0x2019, 0x0001, 0x080c, - 0xa391, 0x003e, 0x714c, 0x2160, 0x2009, 0x004a, 0x6220, 0x9296, - 0x0009, 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, - 0x6003, 0x0003, 0x080c, 0xafec, 0x2001, 0x0387, 0x2003, 0x0200, - 0x080c, 0xab13, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x009e, - 0x0005, 0xd1ec, 0x1904, 0xa17a, 0x0804, 0xa17c, 0x0026, 0x00e6, - 0x2071, 0x19e9, 0x706c, 0xd084, 0x01e8, 0xc084, 0x706e, 0x714c, - 0x81ff, 0x01c0, 0x2071, 0x0100, 0x9188, 0x0008, 0x2114, 0x928e, - 0x0006, 0x1138, 0x2009, 0x1984, 0x2011, 0x0012, 0x080c, 0x2aeb, - 0x0048, 0x928e, 0x0009, 0x0db0, 0x2009, 0x1984, 0x2011, 0x0016, - 0x080c, 0x2aeb, 0x00ee, 0x002e, 0x0005, 0x9036, 0x2001, 0x19f3, - 0x2004, 0x9005, 0x0128, 0x9c06, 0x0128, 0x2c30, 0x600c, 0x0cc8, - 0x9085, 0x0001, 0x0005, 0x00f6, 0x2079, 0x19e9, 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, 0xa458, - 0x080c, 0xce24, 0x00fe, 0x0005, 0x080c, 0x9cf3, 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, 0xa06b, 0x080c, - 0x9cf3, 0x7003, 0x0f00, 0x7808, 0xd09c, 0x0128, 0xb810, 0x9084, - 0x00ff, 0x700a, 0xb814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa06b, - 0x0156, 0x080c, 0x9d3e, 0x7003, 0x0200, 0x080c, 0x89a9, 0x20a9, - 0x0006, 0x2011, 0xffec, 0x2019, 0xffed, 0x9ef0, 0x0002, 0x2305, - 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, 0x0002, 0x9290, - 0x0002, 0x1f04, 0xa27f, 0x60c3, 0x001c, 0x015e, 0x0804, 0xa06b, - 0x0016, 0x0026, 0x080c, 0x9d1a, 0x080c, 0x9d2c, 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, 0xa06b, 0x002e, 0x001e, 0x0005, - 0x20a9, 0x0010, 0x4003, 0x080c, 0xa8d7, 0x20a1, 0x0240, 0x22a8, - 0x4003, 0x0c68, 0x080c, 0x9cf3, 0x7003, 0x6200, 0x7808, 0x700e, - 0x60c3, 0x0008, 0x0804, 0xa06b, 0x0016, 0x0026, 0x080c, 0x9cf3, - 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, 0x0096, 0x2048, 0xa800, - 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0023, 0x2098, 0x009e, - 0x7808, 0x9088, 0x0002, 0x21a8, 0x4003, 0x8003, 0x60c2, 0x080c, - 0xa06b, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0x19e9, 0x7010, 0x2060, 0x8cff, 0x0188, - 0x080c, 0xce4a, 0x1110, 0x080c, 0xb93c, 0x600c, 0x0006, 0x080c, - 0xd0c6, 0x600f, 0x0000, 0x080c, 0xaf4e, 0x080c, 0xa458, 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, - 0x19e9, 0x7030, 0x2060, 0x8cff, 0x0548, 0x080c, 0xa09b, 0x6ac0, - 0x68c3, 0x0000, 0x080c, 0x88e4, 0x00c6, 0x2061, 0x0100, 0x080c, - 0xaa28, 0x00ce, 0x20a9, 0x01f4, 0x04b1, 0x080c, 0x97f6, 0x6044, - 0xd0ac, 0x1128, 0x2001, 0x1989, 0x2004, 0x604a, 0x0020, 0x2009, - 0x0013, 0x080c, 0xafec, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x1800, - 0x2004, 0x9096, 0x0001, 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, - 0x88e4, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, - 0x0008, 0x68c3, 0x0000, 0x2011, 0x5fdd, 0x080c, 0x882c, 0x20a9, - 0x01f4, 0x0009, 0x08c0, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, - 0x7804, 0x9084, 0x4000, 0x190c, 0x2ab2, 0x0090, 0xd084, 0x0118, - 0x6827, 0x0001, 0x0010, 0x1f04, 0xa373, 0x7804, 0x9084, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2aa2, 0x9006, 0x080c, 0x2aa2, - 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, 0x19e9, 0x704c, - 0x2060, 0x8cff, 0x0904, 0xa414, 0x080c, 0xad70, 0x0904, 0xa414, - 0x9386, 0x0002, 0x1128, 0x6814, 0x9084, 0x0002, 0x0904, 0xa414, - 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, - 0x69c6, 0x68cb, 0x0008, 0x080c, 0x88f1, 0x080c, 0x1e61, 0x2001, - 0x0032, 0x6920, 0xd1bc, 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, - 0x0008, 0x692e, 0x0016, 0x2009, 0x0040, 0x080c, 0x223d, 0x001e, - 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, - 0x9084, 0x4000, 0x190c, 0x2ab2, 0x0090, 0xd08c, 0x0118, 0x6827, - 0x0002, 0x0010, 0x1f04, 0xa3e2, 0x7804, 0x9084, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2aa2, 0x9006, 0x080c, 0x2aa2, 0x6827, - 0x4000, 0x6824, 0x83ff, 0x1180, 0x2009, 0x0049, 0x6020, 0x9086, - 0x0009, 0x0150, 0x080c, 0x9851, 0x6044, 0xd0ac, 0x1118, 0x6003, - 0x0002, 0x0010, 0x080c, 0xafec, 0x000e, 0x2071, 0x0380, 0xd08c, - 0x1110, 0x701f, 0x0200, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, - 0x2091, 0x8000, 0x2069, 0x19e9, 0x6a06, 0x012e, 0x00de, 0x0005, - 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x19e9, 0x6a3e, 0x012e, - 0x00de, 0x0005, 0x080c, 0x9e4b, 0x7047, 0x1000, 0x0098, 0x080c, - 0x9e4b, 0x7047, 0x4000, 0x0070, 0x080c, 0x9e4b, 0x7047, 0x2000, - 0x0048, 0x080c, 0x9e4b, 0x7047, 0x0400, 0x0020, 0x080c, 0x9e4b, - 0x7047, 0x0200, 0x785c, 0x7032, 0x60c3, 0x0020, 0x0804, 0xa06b, - 0x00e6, 0x2071, 0x19e9, 0x702c, 0x9005, 0x0110, 0x8001, 0x702e, - 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e9, 0x7620, 0x2660, - 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0xa4fd, 0x8cff, 0x0904, - 0xa4fd, 0x6020, 0x9086, 0x0006, 0x1904, 0xa4f8, 0x88ff, 0x0138, - 0x2800, 0x9c06, 0x1904, 0xa4f8, 0x2039, 0x0000, 0x0050, 0x6010, - 0x9b06, 0x1904, 0xa4f8, 0x85ff, 0x0120, 0x605c, 0x9106, 0x1904, - 0xa4f8, 0x7030, 0x9c06, 0x15b0, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x1160, 0x6824, 0xd084, 0x0148, 0x6827, 0x0001, 0x080c, 0x88e4, - 0x080c, 0xa585, 0x7033, 0x0000, 0x0428, 0x080c, 0x88e4, 0x6820, - 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, - 0x080c, 0xa585, 0x7033, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2aa2, 0x9006, - 0x080c, 0x2aa2, 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, 0xcc31, 0x0110, 0x080c, 0xe738, 0x009e, 0x080c, - 0xaf89, 0x080c, 0xa458, 0x88ff, 0x1190, 0x00ce, 0x0804, 0xa473, - 0x2c78, 0x600c, 0x2060, 0x0804, 0xa473, 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, 0x19e9, 0x7648, 0x2660, 0x2678, 0x8cff, 0x0904, 0xa574, - 0x6020, 0x9086, 0x0006, 0x1904, 0xa56f, 0x87ff, 0x0128, 0x2700, - 0x9c06, 0x1904, 0xa56f, 0x0048, 0x6010, 0x9b06, 0x1904, 0xa56f, - 0x85ff, 0x0118, 0x605c, 0x9106, 0x15d0, 0x704c, 0x9c06, 0x1178, - 0x0036, 0x2019, 0x0001, 0x080c, 0xa391, 0x703f, 0x0000, 0x9006, - 0x704e, 0x706a, 0x7052, 0x706e, 0x080c, 0xade0, 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, 0xcc31, 0x0110, 0x080c, 0xe738, - 0x080c, 0xaf89, 0x87ff, 0x1198, 0x00ce, 0x0804, 0xa51d, 0x2c78, - 0x600c, 0x2060, 0x0804, 0xa51d, 0x9006, 0x012e, 0x000e, 0x002e, - 0x006e, 0x00ce, 0x009e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, - 0x0000, 0x00ce, 0x97bd, 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19e9, - 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, 0x19e9, 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, 0x97f6, 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, 0x19e9, 0x7610, 0x2660, 0x2678, 0x8cff, 0x0904, 0xa672, - 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x1904, 0xa66d, - 0x7030, 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, - 0xa644, 0x080c, 0xa09b, 0x68c3, 0x0000, 0x080c, 0xa585, 0x7033, + 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, 0x2aa2, 0x9006, 0x080c, 0x2aa2, 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, 0xce39, 0x1180, 0x080c, 0x332a, 0x080c, 0xce4a, - 0x1518, 0x080c, 0xb93c, 0x0400, 0x080c, 0xa585, 0x6824, 0xd084, - 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, 0xce4a, 0x1118, 0x080c, - 0xb93c, 0x0090, 0x6014, 0x2048, 0x080c, 0xcc31, 0x0168, 0x6020, - 0x9086, 0x0003, 0x1508, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, - 0x080c, 0x6f05, 0x080c, 0xce24, 0x080c, 0xd0c6, 0x080c, 0xaf89, - 0x080c, 0xa458, 0x00ce, 0x0804, 0xa5ed, 0x2c78, 0x600c, 0x2060, - 0x0804, 0xa5ed, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, - 0x00ee, 0x00fe, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, - 0x080c, 0xe738, 0x0c08, 0x00d6, 0x080c, 0x9d3e, 0x7003, 0x0200, - 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, 0x198a, - 0x20e9, 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, - 0x0004, 0x7027, 0x7878, 0x080c, 0xa06b, 0x00de, 0x0005, 0x080c, - 0x9d3e, 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, 0xa06b, 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, - 0x2009, 0x0035, 0x080c, 0xd2d3, 0x00de, 0x1904, 0xa720, 0x080c, - 0x9cf3, 0x7003, 0x1300, 0x782c, 0x080c, 0xa82f, 0x2068, 0x6820, - 0x9086, 0x0003, 0x0560, 0x7810, 0x2058, 0xbaa0, 0x080c, 0xae80, - 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, - 0xae80, 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, 0xa06b, 0x00be, 0x0005, - 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x00be, 0x0005, - 0x792c, 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, - 0x0003, 0x0904, 0xa79f, 0x9186, 0x0005, 0x0904, 0xa787, 0x9186, - 0x0004, 0x05f0, 0x9186, 0x0008, 0x0904, 0xa790, 0x7807, 0x0037, - 0x782f, 0x0003, 0x7817, 0x1700, 0x080c, 0xa80c, 0x0005, 0x080c, - 0xa7cd, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, - 0x6a44, 0xd2fc, 0x11f8, 0x0002, 0xa767, 0xa772, 0xa769, 0xa772, - 0xa76e, 0xa767, 0xa767, 0xa772, 0xa772, 0xa772, 0xa772, 0xa767, - 0xa767, 0xa767, 0xa767, 0xa767, 0xa772, 0xa767, 0xa772, 0x080c, - 0x0d79, 0x6824, 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, - 0x2009, 0x2000, 0x682c, 0x7022, 0x6830, 0x7026, 0x0804, 0xa7c6, - 0x080c, 0xa7cd, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, - 0x6a00, 0x9286, 0x0002, 0x1108, 0x900e, 0x0804, 0xa7c6, 0x080c, - 0xa7cd, 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, 0xa06b, 0x00b6, 0x0036, 0x0046, - 0x0056, 0x0066, 0x080c, 0x9d3e, 0x9006, 0x7003, 0x0200, 0x7938, - 0x710a, 0x793c, 0x710e, 0x7810, 0x2058, 0xb8a0, 0x080c, 0xae80, - 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, 0x9d3e, 0x7003, 0x0100, - 0x782c, 0x700a, 0x7814, 0x700e, 0x700e, 0x60c3, 0x0008, 0x0804, - 0xa06b, 0x080c, 0x9cea, 0x7003, 0x1400, 0x7838, 0x700a, 0x0079, - 0x783c, 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, - 0x00ff, 0x8007, 0x701a, 0x60c3, 0x0010, 0x0804, 0xa06b, 0x00e6, - 0x2071, 0x0240, 0x0006, 0x00f6, 0x2078, 0x7810, 0x00b6, 0x2058, - 0xb8d4, 0xd084, 0x0120, 0x784c, 0x702a, 0x7850, 0x702e, 0x00be, - 0x00fe, 0x000e, 0x00ee, 0x0005, 0x080c, 0x9d35, 0x7003, 0x0100, - 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa06b, - 0x00a9, 0x7914, 0x712a, 0x60c3, 0x0000, 0x60a7, 0x9575, 0x0026, - 0x080c, 0x2a11, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, - 0x002e, 0x080c, 0xa08e, 0x080c, 0x88db, 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, 0xa8ec, 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, 0x19b4, 0x210c, - 0x009e, 0x918d, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, - 0x0026, 0x2110, 0x900e, 0x080c, 0x2aeb, 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, 0x9cf3, 0x0016, 0x0026, 0x0096, 0x00d6, 0x7814, 0x2048, - 0x7013, 0x0138, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1138, - 0x2001, 0x197d, 0x2004, 0x9086, 0xaaaa, 0x1904, 0xa991, 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, 0xa922, - 0x20a9, 0x0004, 0x2009, 0x1801, 0x2104, 0x2012, 0x8108, 0x8210, - 0x1f04, 0xa92c, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, - 0x2009, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, - 0x8109, 0x1dc0, 0x00d6, 0x2069, 0x0200, 0x080c, 0xa8d7, 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, 0x769d, 0x0150, 0x6028, 0xc0bd, - 0x602a, 0x2009, 0x1804, 0x2011, 0x0029, 0x080c, 0x2aeb, 0x0010, - 0x080c, 0xa06b, 0x080c, 0x88db, 0x00de, 0x009e, 0x002e, 0x001e, - 0x0005, 0x00e6, 0x2071, 0x0240, 0x2001, 0x2200, 0x9085, 0x00ff, - 0x7002, 0x7007, 0xffff, 0x2071, 0x0100, 0x709b, 0x00ff, 0x00ee, - 0x0804, 0xa907, 0x080c, 0x9cf3, 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, - 0xa9e3, 0x20a9, 0x0002, 0x2009, 0x1801, 0x2104, 0x2012, 0x8108, - 0x8210, 0x1f04, 0xa9ed, 0x00d6, 0x0016, 0x2069, 0x0200, 0x080c, - 0xa8d7, 0x001e, 0x00de, 0x2071, 0x0240, 0x20a9, 0x0002, 0x2009, - 0x1803, 0x2011, 0x0240, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, - 0xaa03, 0x2009, 0x0008, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, - 0x1dd0, 0x9006, 0x20a9, 0x0008, 0x2012, 0x8210, 0x1f04, 0xaa14, - 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, - 0xa06b, 0x080c, 0x88db, 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, 0x19e9, 0x7610, 0x2660, 0x2678, 0x8cff, - 0x0904, 0xaad4, 0x7030, 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, - 0x9005, 0x0904, 0xaaa6, 0x080c, 0xa09b, 0x68c3, 0x0000, 0x080c, - 0xa585, 0x7033, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, - 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2aa2, 0x9006, 0x080c, - 0x2aa2, 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, 0xce39, 0x1180, 0x080c, 0x332a, - 0x080c, 0xce4a, 0x1518, 0x080c, 0xb93c, 0x0400, 0x080c, 0xa585, - 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, 0xce4a, - 0x1118, 0x080c, 0xb93c, 0x0090, 0x6014, 0x2048, 0x080c, 0xcc31, - 0x0168, 0x6020, 0x9086, 0x0003, 0x1520, 0xa867, 0x0103, 0xab7a, - 0xa877, 0x0000, 0x080c, 0x6f11, 0x080c, 0xce24, 0x080c, 0xd0c6, - 0x080c, 0xaf89, 0x080c, 0xa458, 0x00ce, 0x0804, 0xaa57, 0x2c78, - 0x600c, 0x2060, 0x0804, 0xaa57, 0x7013, 0x0000, 0x700f, 0x0000, - 0x012e, 0x006e, 0x009e, 0x00ae, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x0005, 0x6020, 0x9086, 0x0006, 0x1d08, 0x080c, 0xe738, 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, - 0x0d79, 0x001e, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, - 0x9086, 0x0003, 0x1120, 0x2001, 0x0380, 0x2003, 0x0001, 0x0005, - 0x0156, 0x0016, 0x0026, 0x00e6, 0x900e, 0x2071, 0x19e9, 0x0469, - 0x0106, 0x0190, 0x7004, 0x9086, 0x0003, 0x0148, 0x20a9, 0x1000, - 0x6044, 0xd0fc, 0x01d8, 0x1f04, 0xab30, 0x080c, 0x0d79, 0x080c, - 0xaaf7, 0x6044, 0xd0fc, 0x0190, 0x7030, 0x9c06, 0x1148, 0x080c, - 0x97f6, 0x6044, 0xd0dc, 0x0150, 0xc0dc, 0x6046, 0x700a, 0x7042, - 0x704c, 0x9c06, 0x190c, 0x0d79, 0x080c, 0x9851, 0x010e, 0x1919, - 0x00ee, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x0382, 0x2004, - 0x9084, 0x0007, 0x9086, 0x0003, 0x0005, 0x0126, 0x2091, 0x2400, - 0x7808, 0xd0a4, 0x190c, 0x0d72, 0xd09c, 0x0128, 0x7820, 0x908c, - 0xf000, 0x11b8, 0x0012, 0x012e, 0x0005, 0xab7d, 0xabbb, 0xabe5, - 0xac23, 0xac33, 0xac44, 0xac53, 0xac61, 0xac8e, 0xac92, 0xab7d, - 0xab7d, 0xac95, 0xacb1, 0xab7d, 0xab7d, 0x080c, 0x0d79, 0x012e, - 0x0005, 0x2060, 0x6044, 0xd0bc, 0x0140, 0xc0bc, 0x6046, 0x6000, - 0x908a, 0x0010, 0x1a0c, 0x0d79, 0x0012, 0x012e, 0x0005, 0xaba2, - 0xaba4, 0xaba2, 0xabaa, 0xaba2, 0xaba2, 0xaba2, 0xaba2, 0xaba2, - 0xaba4, 0xaba2, 0xaba4, 0xaba2, 0xaba4, 0xaba2, 0xaba2, 0xaba2, - 0xaba4, 0xaba2, 0x080c, 0x0d79, 0x2009, 0x0013, 0x080c, 0xafec, - 0x012e, 0x0005, 0x6014, 0x2048, 0xa87c, 0xd0dc, 0x0130, 0x080c, - 0x8ab2, 0x080c, 0xaf4e, 0x012e, 0x0005, 0x2009, 0x0049, 0x080c, - 0xafec, 0x012e, 0x0005, 0x080c, 0xaaf7, 0x2001, 0x1a0e, 0x2003, - 0x0000, 0x7030, 0x9065, 0x090c, 0x0d79, 0x7034, 0x9092, 0xc350, - 0x1258, 0x8000, 0x7036, 0x7004, 0x9086, 0x0003, 0x0110, 0x7007, - 0x0000, 0x781f, 0x0808, 0x0058, 0x080c, 0xaeac, 0x0140, 0x080c, - 0xebfd, 0x6003, 0x0001, 0x2009, 0x0014, 0x080c, 0xafec, 0x781f, - 0x0100, 0x080c, 0xab13, 0x012e, 0x0005, 0x080c, 0xaaf7, 0x714c, - 0x81ff, 0x1128, 0x2011, 0x1a11, 0x2013, 0x0000, 0x0470, 0x2061, - 0x0100, 0x7150, 0x9192, 0x7530, 0x1628, 0x8108, 0x7152, 0x714c, - 0x9186, 0x1b56, 0x0120, 0x2001, 0x0391, 0x2003, 0x0400, 0x9188, - 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, 0x9084, 0x1984, - 0x9085, 0x0012, 0x6016, 0x0088, 0x714c, 0x9188, 0x0008, 0x210c, - 0x918e, 0x0009, 0x0d90, 0x6014, 0x9084, 0x1984, 0x9085, 0x0016, - 0x6016, 0x0018, 0x706c, 0xc085, 0x706e, 0x781f, 0x0200, 0x080c, - 0xab13, 0x012e, 0x0005, 0x080c, 0xaaf7, 0x714c, 0x2160, 0x6003, - 0x0003, 0x2009, 0x004a, 0x080c, 0xafec, 0x781f, 0x0200, 0x080c, - 0xab13, 0x012e, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x2060, - 0x6003, 0x0003, 0x080c, 0xaaf7, 0x080c, 0x1de9, 0x781f, 0x0400, - 0x080c, 0xab13, 0x012e, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, - 0x2060, 0x080c, 0xaaf7, 0x080c, 0x1e31, 0x781f, 0x0400, 0x080c, - 0xab13, 0x012e, 0x0005, 0x7030, 0x9065, 0x0148, 0x6044, 0xc0bc, - 0x6046, 0x7104, 0x9186, 0x0003, 0x0110, 0x080c, 0x98bd, 0x012e, - 0x0005, 0x00f6, 0x703c, 0x9086, 0x0002, 0x0528, 0x704c, 0x907d, - 0x0510, 0x7844, 0xc0bc, 0x7846, 0x7820, 0x9086, 0x0009, 0x0118, - 0x080c, 0x9fc5, 0x00c0, 0x7828, 0xd0fc, 0x1118, 0x080c, 0x9f44, - 0x0090, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1130, 0x2001, - 0x197d, 0x2004, 0x9086, 0xaaaa, 0x1120, 0x2001, 0x0387, 0x2003, - 0x1000, 0x080c, 0x9ec9, 0x00fe, 0x012e, 0x0005, 0x080c, 0x773f, - 0x012e, 0x0005, 0x080c, 0x0d79, 0x0005, 0x2009, 0x1b67, 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, 0x88f1, 0x2009, 0x010b, 0x2104, 0xd08c, 0x01a8, - 0xc08c, 0x200a, 0x2001, 0x1848, 0x2004, 0xd094, 0x1130, 0x2009, - 0x0101, 0x2104, 0x9085, 0x0020, 0x200a, 0x2009, 0x1b67, 0x200b, - 0x0000, 0x2001, 0x001b, 0x080c, 0xaae8, 0x012e, 0x0005, 0x00e6, - 0x2071, 0x19e9, 0x6044, 0xc0bc, 0x6046, 0xd0fc, 0x01b8, 0x704c, - 0x9c06, 0x1190, 0x2019, 0x0001, 0x080c, 0xa391, 0x704f, 0x0000, - 0x2001, 0x0109, 0x2004, 0xd08c, 0x1138, 0x2001, 0x0108, 0x2004, - 0xd0bc, 0x1110, 0x703f, 0x0000, 0x080c, 0xa59c, 0x00ee, 0x0005, - 0x0026, 0x7010, 0x9c06, 0x1178, 0x080c, 0xa458, 0x6044, 0xc0fc, - 0x6046, 0x600c, 0x9015, 0x0120, 0x7212, 0x600f, 0x0000, 0x0010, - 0x7212, 0x720e, 0x9006, 0x002e, 0x0005, 0x0026, 0x7020, 0x9c06, - 0x1178, 0x080c, 0xa458, 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, 0x88e4, 0x080c, 0xa09b, - 0x68c3, 0x0000, 0x080c, 0xa585, 0x2069, 0x0140, 0x6b04, 0x9384, - 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2aa2, 0x9006, 0x080c, - 0x2aa2, 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, 0xab5d, - 0x003e, 0x001e, 0x012e, 0x00ce, 0x6200, 0x2200, 0x9106, 0x0d58, - 0x2200, 0x0010, 0x8319, 0x1d38, 0x003e, 0x002e, 0x001e, 0x0005, - 0x00e6, 0x00d6, 0x00c6, 0x080c, 0xaaf7, 0x0106, 0x2071, 0x19e9, - 0x2069, 0x0100, 0x704c, 0x2060, 0x9086, 0x1b56, 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, 0x9851, 0x682c, - 0x9084, 0xfffd, 0x682e, 0x2001, 0x1848, 0x2004, 0xd094, 0x1120, - 0x6804, 0x9085, 0x0020, 0x6806, 0x2069, 0x0000, 0x010e, 0x090c, - 0xab13, 0x8dff, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, - 0x00c6, 0x080c, 0xaaf7, 0x0106, 0x2071, 0x19e9, 0x2069, 0x0100, - 0x080c, 0xad70, 0x68d0, 0x9005, 0x0158, 0x9082, 0x0005, 0x1240, - 0x080c, 0x2b3c, 0x2001, 0x0391, 0x2003, 0x0400, 0x2069, 0x0000, - 0x010e, 0x090c, 0xab13, 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, 0x9d3e, - 0x7a14, 0x82ff, 0x0138, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, - 0x0008, 0x0490, 0x7003, 0x0200, 0x7007, 0x0000, 0x2069, 0x1800, - 0x901e, 0x6800, 0x9086, 0x0004, 0x1110, 0xc38d, 0x0060, 0x080c, - 0x769d, 0x1110, 0xc3ad, 0x0008, 0xc3a5, 0x6adc, 0xd29c, 0x1110, - 0xd2ac, 0x0108, 0xc39d, 0x730e, 0x080c, 0x89a9, 0x20a9, 0x0006, - 0x2011, 0xffec, 0x2019, 0xffed, 0x2071, 0x0250, 0x2305, 0x2072, - 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, - 0x1f04, 0xae26, 0x60c3, 0x0020, 0x080c, 0xa06b, 0x015e, 0x00de, - 0x0005, 0x0156, 0x080c, 0x9d3e, 0x7a14, 0x82ff, 0x0168, 0x9286, - 0xffff, 0x0118, 0x9282, 0x000e, 0x1238, 0x7003, 0x0100, 0x700b, - 0x0003, 0x60c3, 0x0008, 0x0488, 0x7003, 0x0200, 0x7007, 0x001c, - 0x700f, 0x0001, 0x2011, 0x19bf, 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, 0xa06b, - 0x0006, 0x2001, 0x1837, 0x2004, 0xd0ac, 0x000e, 0x0005, 0x2011, - 0x0003, 0x080c, 0xa426, 0x2011, 0x0002, 0x080c, 0xa430, 0x080c, - 0xa311, 0x0036, 0x901e, 0x080c, 0xa391, 0x003e, 0x0005, 0x080c, - 0x346d, 0x0188, 0x0016, 0x00b6, 0x00c6, 0x7010, 0x9085, 0x0020, - 0x7012, 0x2009, 0x007e, 0x080c, 0x6783, 0xb85c, 0xc0ac, 0xb85e, - 0x00ce, 0x00be, 0x001e, 0x0005, 0x00d6, 0x00f6, 0x7104, 0x9186, - 0x0004, 0x1120, 0x7410, 0x9e90, 0x0004, 0x0068, 0x9186, 0x0001, - 0x1120, 0x7420, 0x9e90, 0x0008, 0x0030, 0x9186, 0x0002, 0x1508, - 0x7428, 0x9e90, 0x000a, 0x6110, 0x2468, 0x680c, 0x907d, 0x01c8, - 0x7810, 0x9106, 0x1128, 0x2f68, 0x780c, 0x907d, 0x1dc8, 0x0088, - 0x780c, 0x680e, 0x7c0e, 0x2f12, 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, + 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, 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, 0x0d79, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0d79, - 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, 0x1af0, 0x6023, 0x0007, 0x2001, 0x1987, 0x2004, 0x0006, - 0x9082, 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xe9f0, - 0x604b, 0x0000, 0x6044, 0xd0fc, 0x1131, 0x9006, 0x6046, 0x6016, - 0x6012, 0x000e, 0x0005, 0x080c, 0xaaf7, 0x0106, 0x2001, 0x19fc, - 0x2004, 0x9c06, 0x1130, 0x0036, 0x2019, 0x0001, 0x080c, 0xa391, - 0x003e, 0x080c, 0xa59c, 0x010e, 0x090c, 0xab13, 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, - 0xb000, 0xb00a, 0xb025, 0xb040, 0xd3b0, 0xd3cd, 0xd3e8, 0xb000, - 0xb00a, 0x9191, 0xb059, 0xb000, 0xb000, 0xb000, 0xb000, 0xb000, - 0x9186, 0x0013, 0x1130, 0x6044, 0xd0fc, 0x0110, 0x080c, 0x97f6, - 0x0005, 0x0005, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d79, - 0x0013, 0x006e, 0x0005, 0xb023, 0xb79c, 0xb983, 0xb023, 0xba19, - 0xb322, 0xb023, 0xb023, 0xb71e, 0xbf8c, 0xb023, 0xb023, 0xb023, - 0xb023, 0xb023, 0xb023, 0x080c, 0x0d79, 0x0066, 0x6000, 0x90b2, - 0x0010, 0x1a0c, 0x0d79, 0x0013, 0x006e, 0x0005, 0xb03e, 0xc5a7, - 0xb03e, 0xb03e, 0xb03e, 0xb03e, 0xb03e, 0xb03e, 0xc53e, 0xc72a, - 0xb03e, 0xc5e4, 0xc668, 0xc5e4, 0xc668, 0xb03e, 0x080c, 0x0d79, - 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0d79, 0x6000, 0x0002, 0xb057, - 0xbfd6, 0xc070, 0xc1f3, 0xc262, 0xb057, 0xb057, 0xb057, 0xbfa5, - 0xc4bf, 0xc4c2, 0xb057, 0xb057, 0xb057, 0xb057, 0xc4f2, 0x080c, - 0x0d79, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d79, 0x0013, - 0x006e, 0x0005, 0xb072, 0xb072, 0xb0b0, 0xb14f, 0xb1cf, 0xb072, - 0xb072, 0xb072, 0xb074, 0xb072, 0xb072, 0xb072, 0xb072, 0xb072, - 0xb072, 0xb072, 0x080c, 0x0d79, 0x9186, 0x004c, 0x0560, 0x9186, - 0x0003, 0x190c, 0x0d79, 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, 0x1c43, 0x2009, 0x8030, - 0x080c, 0x9467, 0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, - 0x2c00, 0x080c, 0xb1f1, 0x080c, 0xd375, 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, 0xb117, 0xb117, 0xb112, 0xb115, 0xb117, 0xb10f, - 0xb102, 0xb102, 0xb102, 0xb102, 0xb102, 0xb102, 0xb102, 0xb102, - 0xb102, 0xb102, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, - 0x000e, 0x004e, 0x00fe, 0x009e, 0x00de, 0x080c, 0x0d79, 0x080c, - 0xbbda, 0x0028, 0x080c, 0xbcc1, 0x0010, 0x080c, 0xbdb7, 0x00fe, - 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896, 0x000e, - 0x080c, 0xb2af, 0x0530, 0xa804, 0xa80e, 0x00a6, 0x2050, 0xb100, - 0x00ae, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x0002, 0xaacc, 0xabd0, 0xacd4, 0xadd8, 0x2031, 0x0000, - 0x2041, 0x12b6, 0x080c, 0xb473, 0x0160, 0x000e, 0x9005, 0x0120, - 0x00fe, 0x009e, 0x00de, 0x0005, 0x00fe, 0x009e, 0x00de, 0x0804, - 0xaf4e, 0x2001, 0x002c, 0x900e, 0x080c, 0xb315, 0x0c70, 0x91b6, - 0x0015, 0x0170, 0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047, 0x0a0c, - 0x0d79, 0x91b2, 0x0050, 0x1a0c, 0x0d79, 0x9182, 0x0047, 0x0042, - 0x080c, 0xad4d, 0x0120, 0x9086, 0x0002, 0x0904, 0xb0b0, 0x0005, - 0xb171, 0xb171, 0xb173, 0xb1a5, 0xb171, 0xb171, 0xb171, 0xb171, - 0xb1b8, 0x080c, 0x0d79, 0x00d6, 0x0016, 0x0096, 0x6003, 0x0004, - 0x6114, 0x2148, 0xa87c, 0xd0fc, 0x01c0, 0xa878, 0xc0fc, 0x9005, - 0x1158, 0xa894, 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, - 0xb315, 0x080c, 0xaf4e, 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, 0x9851, 0x00d6, - 0x0096, 0x6114, 0x2148, 0x080c, 0xcc33, 0x0120, 0xa87b, 0x0006, - 0x080c, 0x6f11, 0x009e, 0x00de, 0x080c, 0xaf4e, 0x0804, 0x98bc, - 0x080c, 0x9851, 0x080c, 0x32fb, 0x080c, 0xd372, 0x00d6, 0x0096, - 0x6114, 0x2148, 0x080c, 0xcc33, 0x0120, 0xa87b, 0x0029, 0x080c, - 0x6f11, 0x009e, 0x00de, 0x080c, 0xaf4e, 0x0804, 0x98bc, 0x9182, - 0x0047, 0x0002, 0xb1df, 0xb1e1, 0xb1df, 0xb1df, 0xb1df, 0xb1df, - 0xb1df, 0xb1df, 0xb1df, 0xb1df, 0xb1df, 0xb1df, 0xb1e1, 0x080c, - 0x0d79, 0x00d6, 0x0096, 0x601f, 0x0000, 0x6114, 0x2148, 0xa87b, - 0x0000, 0xa883, 0x0000, 0x080c, 0x6f11, 0x009e, 0x00de, 0x0804, - 0xaf4e, 0x0026, 0x0036, 0x0056, 0x0066, 0x0096, 0x00a6, 0x00f6, - 0x0006, 0x080c, 0x104d, 0x000e, 0x090c, 0x0d79, 0xa960, 0x21e8, + 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, - 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, 0xc7ad, 0x04c0, 0x2130, 0x2009, 0x0034, 0x2011, 0x001f, - 0x080c, 0xc7ad, 0x96b2, 0x0034, 0xb004, 0x904d, 0x0110, 0x080c, - 0x0fff, 0x080c, 0x104d, 0x01d0, 0x8528, 0xa867, 0x0110, 0xa86b, - 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, 0x1230, 0x2608, 0x2011, - 0x001b, 0x080c, 0xc7ad, 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, - 0x2950, 0x2011, 0x001b, 0x080c, 0xc7ad, 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, 0x6f11, 0x000e, 0x2048, 0x9005, 0x1db0, 0x00fe, - 0x00ae, 0x009e, 0x006e, 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, - 0x00f6, 0x0096, 0x0006, 0x080c, 0x104d, 0x000e, 0x090c, 0x0d79, - 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, 0x6f11, 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, 0x104d, 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, 0xb2c4, 0x0804, 0xb2c6, 0x9085, 0x0001, 0x7817, 0x0000, - 0x009e, 0x00fe, 0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, 0x0096, - 0x6314, 0x2348, 0xa87a, 0xa982, 0x080c, 0x6f05, 0x009e, 0x003e, - 0x00de, 0x0005, 0x91b6, 0x0015, 0x1118, 0x080c, 0xaf4e, 0x0030, - 0x91b6, 0x0016, 0x190c, 0x0d79, 0x080c, 0xaf4e, 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, - 0xcc33, 0x0130, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0x009e, 0x0804, 0xaf4e, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, - 0x0200, 0x11a8, 0x6010, 0x00b6, 0x2058, 0xb8d7, 0x0000, 0x00be, - 0x6014, 0x9005, 0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0xab32, 0x080c, 0xaf4e, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, - 0x1d48, 0x0cc8, 0x0006, 0x0016, 0x080c, 0xd35d, 0x0188, 0x6014, - 0x9005, 0x1170, 0x600b, 0x0003, 0x601b, 0x0000, 0x604b, 0x0000, - 0x2009, 0x0022, 0x080c, 0xb774, 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, 0xaf4e, 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, 0xc7ad, 0x080c, 0xcc33, 0x0140, 0x6014, 0x2048, 0xa807, - 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xaf4e, 0x001e, - 0x009e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, 0x9086, 0x0200, - 0x0110, 0x2009, 0x0001, 0x0096, 0x6014, 0x904d, 0x090c, 0x0d79, - 0xa97a, 0x080c, 0x6f11, 0x009e, 0x080c, 0xaf4e, 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, - 0xc7ad, 0x009e, 0x080c, 0xcc33, 0x0148, 0xa804, 0x9005, 0x1158, - 0xa807, 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xaf4e, - 0x009e, 0x001e, 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, - 0x0100, 0x1118, 0x080c, 0xb93c, 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, 0x129c, 0x0019, - 0x0d08, 0x008e, 0x0898, 0x0096, 0x0006, 0x080c, 0x104d, 0x000e, - 0x01b0, 0xa8ab, 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, - 0x2800, 0xa89e, 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, - 0x0086, 0x2940, 0x080c, 0x1142, 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, 0xd2d3, 0x001e, 0x1158, - 0x622c, 0x2268, 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, - 0x9386, 0x0006, 0x0128, 0x080c, 0xaf4e, 0x0020, 0x0039, 0x0010, - 0x080c, 0xb5a9, 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, - 0x2048, 0x9186, 0x0015, 0x0904, 0xb588, 0x918e, 0x0016, 0x1904, - 0xb5a7, 0x700c, 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, - 0x0300, 0x1904, 0xb562, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, - 0x0904, 0xb544, 0x0804, 0xb5a5, 0x6808, 0x9086, 0xffff, 0x1904, - 0xb58a, 0xa87c, 0x9084, 0x0060, 0x9086, 0x0020, 0x1150, 0xa8ac, - 0xa934, 0x9106, 0x1904, 0xb58a, 0xa8b0, 0xa938, 0x9106, 0x1904, - 0xb58a, 0x6824, 0xd084, 0x1904, 0xb58a, 0xd0b4, 0x0158, 0x0016, - 0x2001, 0x1987, 0x200c, 0x6018, 0x9102, 0x9082, 0x0005, 0x001e, - 0x1a04, 0xb58a, 0x080c, 0xce24, 0x6810, 0x0096, 0x2048, 0xa9a0, - 0x009e, 0x685c, 0xa87a, 0xa976, 0x6864, 0xa882, 0xa87c, 0xc0dc, - 0xc0f4, 0xc0d4, 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, - 0x080c, 0x9364, 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, 0x82ff, - 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xc938, 0x00ce, 0x0804, - 0xb5a5, 0x00c6, 0xa868, 0xd0fc, 0x1118, 0x080c, 0x620a, 0x0010, - 0x080c, 0x6615, 0x00ce, 0x1904, 0xb58a, 0x00c6, 0x2d60, 0x080c, - 0xaf4e, 0x00ce, 0x0804, 0xb5a5, 0x00c6, 0x080c, 0xafbf, 0x0198, - 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xd0ce, 0x6023, 0x0003, - 0x6904, 0x00c6, 0x2d60, 0x080c, 0xaf4e, 0x00ce, 0x080c, 0xafec, - 0x00ce, 0x0804, 0xb5a5, 0x2001, 0x1989, 0x2004, 0x684a, 0x00ce, - 0x0804, 0xb5a5, 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, - 0x2058, 0xb900, 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, - 0x0003, 0x080c, 0xd317, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x2009, 0x8020, 0x080c, 0x9420, 0x00ce, 0x0430, 0x700c, - 0x9086, 0x2a00, 0x1138, 0x2001, 0x1989, 0x2004, 0x684a, 0x00e8, - 0x04c1, 0x00e8, 0x89ff, 0x090c, 0x0d79, 0x00c6, 0x00d6, 0x2d60, - 0xa867, 0x0103, 0xa87b, 0x0003, 0x080c, 0x6d26, 0x080c, 0xce24, - 0x080c, 0xaf89, 0x0026, 0x6010, 0x00b6, 0x2058, 0xba3c, 0x080c, - 0x68ae, 0x00be, 0x002e, 0x00de, 0x00ce, 0x080c, 0xaf4e, 0x009e, - 0x0005, 0x9186, 0x0015, 0x1128, 0x2001, 0x1989, 0x2004, 0x684a, - 0x0068, 0x918e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, - 0xe9f0, 0x080c, 0x8ab2, 0x080c, 0xaf4e, 0x00ce, 0x080c, 0xaf4e, - 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, - 0x0130, 0x2001, 0x1989, 0x2004, 0x684a, 0x0804, 0xb623, 0x00c6, - 0x2d60, 0x080c, 0xc80e, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, - 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x2009, - 0x8023, 0x080c, 0x9420, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, - 0x01a8, 0x89ff, 0x090c, 0x0d79, 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, 0xcfb8, - 0x080c, 0x98bc, 0x0010, 0x080c, 0xaf4e, 0x004e, 0x003e, 0x002e, - 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, - 0x00b6, 0x2258, 0xba10, 0x00be, 0x9206, 0x1904, 0xb68e, 0x700c, - 0x6210, 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xb68e, - 0x6038, 0x2068, 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, - 0x0904, 0xb68e, 0x9286, 0x0002, 0x0904, 0xb68e, 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, 0xcc33, 0x090c, 0x0d79, 0xa87b, - 0x0003, 0x009e, 0x080c, 0xd317, 0x6007, 0x0085, 0x6003, 0x000b, - 0x6023, 0x0002, 0x2009, 0x8020, 0x080c, 0x9420, 0x00ce, 0x0030, - 0x6038, 0x2070, 0x2001, 0x1989, 0x2004, 0x704a, 0x080c, 0xaf4e, - 0x002e, 0x00de, 0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, - 0x2048, 0x6010, 0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, - 0xbc00, 0xc48c, 0xbc02, 0x0460, 0x0096, 0x0156, 0x0036, 0x0026, - 0x2b48, 0x9e90, 0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, - 0xbf54, 0x002e, 0x003e, 0x015e, 0x009e, 0x1904, 0xb6fd, 0x0096, - 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, - 0x20a9, 0x0004, 0x080c, 0xbf54, 0x002e, 0x003e, 0x015e, 0x009e, - 0x15a0, 0x7238, 0xba0a, 0x733c, 0xbb0e, 0xbc00, 0xc48d, 0xbc02, - 0xa804, 0x9005, 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804, 0xb35e, + 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, - 0x129c, 0x080c, 0xb473, 0x0130, 0x00fe, 0x009e, 0x080c, 0xaf4e, - 0x00be, 0x0005, 0x080c, 0xb93c, 0x0cb8, 0x2b78, 0x00f6, 0x080c, - 0x32fb, 0x080c, 0xd372, 0x00fe, 0x00c6, 0x080c, 0xaef8, 0x2f00, + 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, 0x66c9, 0x080c, 0x66f5, 0x080c, - 0x9427, 0x080c, 0x98bc, 0x00ce, 0x0804, 0xb6d0, 0x2100, 0x91b2, - 0x0053, 0x1a0c, 0x0d79, 0x91b2, 0x0040, 0x1a04, 0xb786, 0x0002, - 0xb774, 0xb774, 0xb76a, 0xb774, 0xb774, 0xb774, 0xb768, 0xb768, - 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, - 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, - 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb774, - 0xb768, 0xb774, 0xb774, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, - 0xb76a, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, - 0xb768, 0xb768, 0xb774, 0xb774, 0xb768, 0xb768, 0xb768, 0xb768, - 0xb768, 0xb768, 0xb768, 0xb768, 0xb768, 0xb774, 0xb768, 0xb768, - 0x080c, 0x0d79, 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8d4, 0xc08c, + 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, 0x9427, 0x0010, 0x080c, 0x9420, 0x0126, - 0x2091, 0x8000, 0x080c, 0x98bc, 0x012e, 0x0005, 0x2600, 0x0002, - 0xb774, 0xb774, 0xb79a, 0xb774, 0xb774, 0xb79a, 0xb79a, 0xb79a, - 0xb79a, 0xb774, 0xb79a, 0xb774, 0xb79a, 0xb774, 0xb79a, 0xb79a, - 0xb79a, 0xb79a, 0x080c, 0x0d79, 0x6004, 0x90b2, 0x0053, 0x1a0c, - 0x0d79, 0x91b6, 0x0013, 0x0904, 0xb871, 0x91b6, 0x0027, 0x1904, - 0xb81d, 0x080c, 0x97f6, 0x6004, 0x080c, 0xce39, 0x01b0, 0x080c, - 0xce4a, 0x01a8, 0x908e, 0x0021, 0x0904, 0xb81a, 0x908e, 0x0022, - 0x1130, 0x080c, 0xb38a, 0x0904, 0xb816, 0x0804, 0xb817, 0x908e, - 0x003d, 0x0904, 0xb81a, 0x0804, 0xb810, 0x080c, 0x332a, 0x2001, - 0x0007, 0x080c, 0x66c9, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, - 0x080c, 0xb93c, 0x9186, 0x007e, 0x1148, 0x2001, 0x1837, 0x2014, - 0xc285, 0x080c, 0x769d, 0x1108, 0xc2ad, 0x2202, 0x080c, 0xaaf7, - 0x0036, 0x0026, 0x2019, 0x0028, 0x2110, 0x080c, 0xeafd, 0x002e, + 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, - 0x95b9, 0x0076, 0x903e, 0x080c, 0x9476, 0x6010, 0x00b6, 0x905d, - 0x0100, 0x00be, 0x2c08, 0x080c, 0xe465, 0x007e, 0x003e, 0x002e, - 0x001e, 0x080c, 0xab13, 0x080c, 0xd372, 0x0016, 0x080c, 0xd0c6, - 0x080c, 0xaf4e, 0x001e, 0x080c, 0x3404, 0x080c, 0x98bc, 0x0030, - 0x080c, 0xd0c6, 0x080c, 0xaf4e, 0x080c, 0x98bc, 0x0005, 0x080c, - 0xb93c, 0x0cb0, 0x080c, 0xb978, 0x0c98, 0x9186, 0x0015, 0x0118, - 0x9186, 0x0016, 0x1140, 0x080c, 0xad4d, 0x0d80, 0x9086, 0x0002, - 0x0904, 0xb983, 0x0c58, 0x9186, 0x0014, 0x1d40, 0x080c, 0x97f6, - 0x6004, 0x908e, 0x0022, 0x1118, 0x080c, 0xb38a, 0x09f8, 0x080c, - 0x32fb, 0x080c, 0xd372, 0x080c, 0xce39, 0x1190, 0x080c, 0x332a, - 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, 0xb93c, 0x9186, + 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, 0xce4a, 0x1120, 0x080c, 0xb93c, 0x0804, 0xb810, 0x6004, + 0x080c, 0xd132, 0x1120, 0x080c, 0xbb5c, 0x0804, 0xba30, 0x6004, 0x908e, 0x0032, 0x1160, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079, - 0x0000, 0x080c, 0x36a5, 0x00fe, 0x00ee, 0x0804, 0xb810, 0x6004, - 0x908e, 0x0021, 0x0d40, 0x908e, 0x0022, 0x090c, 0xb93c, 0x0804, - 0xb810, 0x90b2, 0x0040, 0x1a04, 0xb91c, 0x2008, 0x0002, 0xb8b9, - 0xb8ba, 0xb8bd, 0xb8c0, 0xb8c3, 0xb8d0, 0xb8b7, 0xb8b7, 0xb8b7, - 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, - 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, - 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8d3, 0xb8de, 0xb8b7, - 0xb8df, 0xb8de, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8de, - 0xb8de, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8b7, - 0xb8b7, 0xb907, 0xb8de, 0xb8b7, 0xb8da, 0xb8b7, 0xb8b7, 0xb8b7, - 0xb8db, 0xb8b7, 0xb8b7, 0xb8b7, 0xb8de, 0xb902, 0xb8b7, 0x080c, - 0x0d79, 0x0420, 0x2001, 0x000b, 0x0448, 0x2001, 0x0003, 0x0430, + 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, 0xd375, 0x080c, - 0x98bc, 0x0058, 0x0018, 0x0010, 0x080c, 0x66c9, 0x04b8, 0x080c, - 0xd375, 0x6003, 0x0004, 0x080c, 0x98bc, 0x0005, 0x080c, 0x66c9, + 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, 0x1987, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, + 0x1120, 0x2001, 0x1986, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c, - 0x98bc, 0x0c18, 0x080c, 0xd0c6, 0x080c, 0xaf4e, 0x08f0, 0x00e6, - 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, 0x36a5, 0x00fe, - 0x00ee, 0x080c, 0x97f6, 0x080c, 0xaf4e, 0x0878, 0x6003, 0x0002, - 0x080c, 0xd375, 0x0804, 0x98bc, 0x2600, 0x2008, 0x0002, 0xb933, - 0xb916, 0xb931, 0xb916, 0xb916, 0xb931, 0xb931, 0xb931, 0xb931, - 0xb916, 0xb931, 0xb916, 0xb931, 0xb916, 0xb931, 0xb931, 0xb931, - 0xb931, 0x080c, 0x0d79, 0x0096, 0x6014, 0x2048, 0x080c, 0x6f11, - 0x009e, 0x080c, 0xaf4e, 0x0005, 0x00e6, 0x0096, 0x0026, 0x0016, - 0x080c, 0xcc33, 0x0568, 0x6014, 0x2048, 0xa864, 0x9086, 0x0139, - 0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, 0x080c, 0x55ac, 0x0130, + 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, 0xd237, 0x0090, 0xa868, 0xd0fc, + 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, 0x0d79, 0x6604, 0x96b6, 0x004d, - 0x1120, 0x080c, 0xd156, 0x0804, 0xba08, 0x6604, 0x96b6, 0x0043, - 0x1120, 0x080c, 0xd19f, 0x0804, 0xba08, 0x6604, 0x96b6, 0x004b, - 0x1120, 0x080c, 0xd1cb, 0x0804, 0xba08, 0x6604, 0x96b6, 0x0033, - 0x1120, 0x080c, 0xd0e8, 0x0804, 0xba08, 0x6604, 0x96b6, 0x0028, - 0x1120, 0x080c, 0xce88, 0x0804, 0xba08, 0x6604, 0x96b6, 0x0029, - 0x1120, 0x080c, 0xcec9, 0x0804, 0xba08, 0x6604, 0x96b6, 0x001f, - 0x1120, 0x080c, 0xb32f, 0x0804, 0xba08, 0x6604, 0x96b6, 0x0000, - 0x1118, 0x080c, 0xb694, 0x04e0, 0x6604, 0x96b6, 0x0022, 0x1118, - 0x080c, 0xb36b, 0x04a8, 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, - 0xb491, 0x0470, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, 0xb629, - 0x0438, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0xb3a3, 0x0400, - 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xb3df, 0x00c8, 0x6604, - 0x96b6, 0x0049, 0x1118, 0x080c, 0xb420, 0x0090, 0x6604, 0x96b6, - 0x0041, 0x1118, 0x080c, 0xb40a, 0x0058, 0x91b6, 0x0015, 0x1110, - 0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, 0x00be, 0x0804, 0xbc66, - 0x00be, 0x0005, 0x080c, 0xb009, 0x0cd8, 0xba25, 0xba33, 0xba25, - 0xba7a, 0xba25, 0xbbda, 0xbc73, 0xba25, 0xba25, 0xbc3c, 0xba25, - 0xbc52, 0x0096, 0x601f, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, - 0xa867, 0x0103, 0x009e, 0x0804, 0xaf4e, 0xa001, 0xa001, 0x0005, - 0x6604, 0x96b6, 0x0004, 0x1130, 0x2001, 0x0001, 0x080c, 0x66b5, - 0x0804, 0xaf4e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7090, 0x9086, - 0x0074, 0x1540, 0x080c, 0xe436, 0x11b0, 0x6010, 0x00b6, 0x2058, + 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, 0x66c9, 0x080c, 0x332a, - 0x080c, 0xaf4e, 0x0098, 0x2001, 0x000a, 0x080c, 0x66c9, 0x080c, - 0x332a, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9427, 0x080c, - 0x98bc, 0x0020, 0x2001, 0x0001, 0x080c, 0xbbaa, 0x00ee, 0x0005, - 0x00d6, 0xb800, 0xd084, 0x0160, 0x9006, 0x080c, 0x66b5, 0x2069, - 0x1847, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x66f5, + 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, 0xbb7f, 0x6010, 0x2058, 0xbaa0, 0x9286, - 0x007e, 0x1120, 0x080c, 0xbdc2, 0x0804, 0xbaec, 0x080c, 0xbdb7, - 0x6010, 0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014, 0x9005, - 0x01a8, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, - 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd237, 0x0030, - 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x2001, 0x0006, - 0x080c, 0x66c9, 0x080c, 0x332a, 0x080c, 0xaf4e, 0x0804, 0xbb84, - 0x080c, 0xbb92, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, 0xd0f4, - 0x01e8, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, 0x2001, - 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd237, 0x08f8, 0x080c, - 0xbb88, 0x0160, 0x9006, 0x080c, 0x66b5, 0x2001, 0x0004, 0x080c, - 0x66f5, 0x2001, 0x0007, 0x080c, 0x66c9, 0x08a0, 0x2001, 0x0004, - 0x080c, 0x66c9, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x9427, - 0x080c, 0x98bc, 0x0804, 0xbb84, 0xb85c, 0xd0e4, 0x0178, 0x080c, - 0xd060, 0x080c, 0x769d, 0x0118, 0xd0dc, 0x1904, 0xbaae, 0x2011, - 0x1837, 0x2204, 0xc0ad, 0x2012, 0x0804, 0xbaae, 0x080c, 0xd0a1, - 0x2011, 0x1837, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xe60d, - 0x000e, 0x1904, 0xbaae, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, - 0x66c9, 0x9006, 0x080c, 0x66b5, 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, - 0x26ea, 0x00f6, 0x2100, 0x900e, 0x080c, 0x26a1, 0x795e, 0x00fe, - 0x9186, 0x0081, 0x01f0, 0x2009, 0x0081, 0x00e0, 0x2009, 0x00ef, - 0x00f6, 0x2079, 0x0100, 0x79ea, 0x78e7, 0x0000, 0x7932, 0x7936, - 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x26ea, 0x00f6, 0x2079, - 0x1800, 0x7982, 0x2100, 0x900e, 0x797e, 0x080c, 0x26a1, 0x795e, - 0x00fe, 0x8108, 0x080c, 0x6718, 0x2b00, 0x00ce, 0x1904, 0xbaae, - 0x6012, 0x2009, 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, 0x027c, - 0x210c, 0x918c, 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, 0xb916, - 0x2001, 0x0002, 0x080c, 0x66c9, 0x6023, 0x0001, 0x6003, 0x0001, - 0x6007, 0x0002, 0x080c, 0x9427, 0x080c, 0x98bc, 0x0028, 0x080c, - 0xb93c, 0x2001, 0x0001, 0x0431, 0x00de, 0x009e, 0x00be, 0x0005, - 0x2001, 0x1810, 0x2004, 0xd0a4, 0x0120, 0x2001, 0x1848, 0x2004, - 0xd0ac, 0x0005, 0x00e6, 0x080c, 0xeb56, 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, - 0x66c9, 0x080c, 0x5834, 0x1120, 0x2001, 0x0007, 0x080c, 0x66f5, - 0x2600, 0x9005, 0x11b0, 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, - 0xd0fc, 0x1178, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, - 0x00be, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4c28, 0x004e, - 0x003e, 0x080c, 0x332a, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, - 0x0804, 0xaf4e, 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1800, - 0x7090, 0x9086, 0x0014, 0x1904, 0xbc32, 0x080c, 0x5834, 0x1170, - 0x6014, 0x9005, 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, - 0x2021, 0x0006, 0x080c, 0x4ddf, 0x004e, 0x003e, 0x00d6, 0x6010, - 0x2058, 0x080c, 0x681e, 0x080c, 0xba68, 0x00de, 0x080c, 0xbe8d, - 0x1588, 0x6010, 0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, - 0x080c, 0x66c9, 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, - 0x4000, 0x080c, 0xd237, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0029, 0x0130, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, - 0x009e, 0x080c, 0x332a, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c, - 0xaf4e, 0x0028, 0x080c, 0xb93c, 0x9006, 0x080c, 0xbbaa, 0x001e, - 0x002e, 0x00ee, 0x00be, 0x0005, 0x2011, 0x1824, 0x2204, 0x9086, - 0x0014, 0x1160, 0x2001, 0x0002, 0x080c, 0x66c9, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x9427, 0x0804, 0x98bc, 0x2001, 0x0001, - 0x0804, 0xbbaa, 0x2030, 0x2011, 0x1824, 0x2204, 0x9086, 0x0004, - 0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x66c9, - 0x0804, 0xaf4e, 0x2001, 0x0001, 0x0804, 0xbbaa, 0x0002, 0xba25, - 0xbc7e, 0xba25, 0xbcc1, 0xba25, 0xbd6e, 0xbc73, 0xba28, 0xba25, - 0xbd82, 0xba25, 0xbd94, 0x6604, 0x9686, 0x0003, 0x0904, 0xbbda, - 0x96b6, 0x001e, 0x1110, 0x080c, 0xaf4e, 0x0005, 0x00b6, 0x00d6, - 0x00c6, 0x080c, 0xbda6, 0x11a0, 0x9006, 0x080c, 0x66b5, 0x080c, - 0x32fb, 0x080c, 0xd372, 0x2001, 0x0002, 0x080c, 0x66c9, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x9427, 0x080c, 0x98bc, 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, 0x32fb, 0x080c, - 0xd372, 0x2001, 0x0001, 0x080c, 0xbbaa, 0x00ce, 0x00de, 0x00be, - 0x0005, 0x0096, 0x00b6, 0x0026, 0x9016, 0x080c, 0xbdb4, 0x00d6, - 0x2069, 0x197d, 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0, - 0x9086, 0x007e, 0x1138, 0x2069, 0x1820, 0x2d04, 0x8000, 0x206a, - 0x00de, 0x0010, 0x00de, 0x0088, 0x9006, 0x080c, 0x66b5, 0x2001, - 0x0002, 0x080c, 0x66c9, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, - 0x9427, 0x080c, 0x98bc, 0x0804, 0xbd3e, 0x080c, 0xcc33, 0x01b0, - 0x6014, 0x2048, 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, - 0x0016, 0x2001, 0x0002, 0x080c, 0xd294, 0x00b0, 0x6014, 0x2048, - 0xa864, 0xd0fc, 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e, - 0x2004, 0xd0dc, 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, - 0x9005, 0x1110, 0x9006, 0x0c38, 0x080c, 0xb93c, 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, 0x66c9, 0x2001, 0x0028, 0x601a, 0x6007, - 0x0052, 0x0020, 0x2001, 0x0001, 0x080c, 0xbbaa, 0x002e, 0x00be, - 0x009e, 0x0005, 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, 0x080c, - 0xcc33, 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, - 0x610b, 0x00ee, 0x0010, 0x080c, 0x32fb, 0x0860, 0x2001, 0x0004, - 0x080c, 0x66c9, 0x080c, 0xbdb4, 0x1140, 0x6003, 0x0001, 0x6007, - 0x0003, 0x080c, 0x9427, 0x0804, 0x98bc, 0x080c, 0xb93c, 0x9006, - 0x0804, 0xbbaa, 0x0489, 0x1160, 0x2001, 0x0008, 0x080c, 0x66c9, - 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x9427, 0x0804, 0x98bc, - 0x2001, 0x0001, 0x0804, 0xbbaa, 0x00f9, 0x1160, 0x2001, 0x000a, - 0x080c, 0x66c9, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9427, - 0x0804, 0x98bc, 0x2001, 0x0001, 0x0804, 0xbbaa, 0x2009, 0x026e, - 0x2104, 0x9086, 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, - 0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6, - 0x00c6, 0x0016, 0x6110, 0x2158, 0x080c, 0x6792, 0x001e, 0x00ce, - 0x00be, 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, - 0x6010, 0x2058, 0x2009, 0x1837, 0x2104, 0x9085, 0x0003, 0x200a, - 0x080c, 0xbe5f, 0x0560, 0x2009, 0x1837, 0x2104, 0xc0cd, 0x200a, - 0x080c, 0x6bc9, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, - 0xe795, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, - 0x2009, 0x0001, 0x080c, 0x32c0, 0x00e6, 0x2071, 0x1800, 0x080c, - 0x30c8, 0x00ee, 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, - 0x080c, 0x3404, 0x8108, 0x1f04, 0xbdf8, 0x015e, 0x00ce, 0x080c, - 0xbdb7, 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, 0x26ea, 0x080c, 0x769d, - 0x0170, 0x2071, 0x0260, 0x2069, 0x1983, 0x7048, 0x206a, 0x704c, - 0x6806, 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, 0xd060, 0x0040, - 0x2001, 0x0006, 0x080c, 0x66c9, 0x080c, 0x332a, 0x080c, 0xaf4e, - 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, 0xbf54, 0x1148, 0x2011, 0x027a, - 0x20a9, 0x0004, 0x2019, 0x0006, 0x080c, 0xbf54, 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, 0x19f5, - 0x252c, 0x2021, 0x19fc, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, - 0x7254, 0x7074, 0x9202, 0x1a04, 0xbf20, 0x080c, 0x8d87, 0x0904, - 0xbf19, 0x080c, 0xe7c6, 0x0904, 0xbf19, 0x6720, 0x9786, 0x0007, - 0x0904, 0xbf19, 0x2500, 0x9c06, 0x0904, 0xbf19, 0x2400, 0x9c06, - 0x0904, 0xbf19, 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, - 0x0130, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1590, 0x00c6, - 0x6043, 0xffff, 0x6000, 0x9086, 0x0004, 0x1110, 0x080c, 0x1af0, - 0x9786, 0x000a, 0x0148, 0x080c, 0xce4a, 0x1130, 0x00ce, 0x080c, - 0xb93c, 0x080c, 0xaf89, 0x00e8, 0x6014, 0x2048, 0x080c, 0xcc33, - 0x01a8, 0x9786, 0x0003, 0x1530, 0xa867, 0x0103, 0xa87c, 0xd0cc, - 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fff, 0x009e, 0xab7a, - 0xa877, 0x0000, 0x080c, 0x6f05, 0x080c, 0xce24, 0x080c, 0xaf89, - 0x00ce, 0x9ce0, 0x001c, 0x7068, 0x9c02, 0x1210, 0x0804, 0xbec0, - 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x009e, - 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, 0xe738, 0x0c30, - 0x9786, 0x0009, 0x1148, 0x6000, 0x9086, 0x0004, 0x0d08, 0x2009, - 0x004c, 0x080c, 0xafec, 0x08e0, 0x9786, 0x000a, 0x0980, 0x0820, - 0x220c, 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xbf40, - 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, 0xbf7e, 0x9006, - 0x0005, 0x918d, 0x0001, 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, - 0x0d79, 0x080c, 0xce39, 0x0120, 0x080c, 0xce4a, 0x0158, 0x0028, - 0x080c, 0x332a, 0x080c, 0xce4a, 0x0128, 0x080c, 0x97f6, 0x080c, - 0xaf4e, 0x0005, 0x080c, 0xb93c, 0x0cc0, 0x9182, 0x0057, 0x1220, - 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xbfc4, 0xbfc4, 0xbfc4, - 0xbfc4, 0xbfc4, 0xbfc4, 0xbfc4, 0xbfc4, 0xbfc4, 0xbfc4, 0xbfc4, - 0xbfc6, 0xbfc6, 0xbfc6, 0xbfc6, 0xbfc4, 0xbfc4, 0xbfc4, 0xbfc6, - 0xbfc4, 0xbfc4, 0xbfc4, 0xbfc4, 0x080c, 0x0d79, 0x600b, 0xffff, - 0x6003, 0x000f, 0x6106, 0x0126, 0x2091, 0x8000, 0x080c, 0xd375, - 0x2009, 0x8000, 0x080c, 0x9420, 0x012e, 0x0005, 0x9186, 0x0013, - 0x1128, 0x6004, 0x9082, 0x0040, 0x0804, 0xc04e, 0x9186, 0x0027, - 0x1520, 0x080c, 0x97f6, 0x080c, 0x32fb, 0x080c, 0xd372, 0x0096, - 0x6114, 0x2148, 0x080c, 0xcc33, 0x0198, 0x080c, 0xce4a, 0x1118, - 0x080c, 0xb93c, 0x0068, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, - 0x0000, 0xa97c, 0xc1c5, 0xa97e, 0x080c, 0x6f11, 0x080c, 0xce24, - 0x009e, 0x080c, 0xaf4e, 0x0804, 0x98bc, 0x9186, 0x0014, 0x1120, - 0x6004, 0x9082, 0x0040, 0x0030, 0x9186, 0x0053, 0x0110, 0x080c, - 0x0d79, 0x0005, 0x0002, 0xc02c, 0xc02a, 0xc02a, 0xc02a, 0xc02a, - 0xc02a, 0xc02a, 0xc02a, 0xc02a, 0xc02a, 0xc02a, 0xc045, 0xc045, - 0xc045, 0xc045, 0xc02a, 0xc045, 0xc02a, 0xc045, 0xc02a, 0xc02a, - 0xc02a, 0xc02a, 0x080c, 0x0d79, 0x080c, 0x97f6, 0x0096, 0x6114, - 0x2148, 0x080c, 0xcc33, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, - 0xa877, 0x0000, 0xa880, 0xc0ec, 0xa882, 0x080c, 0x6f11, 0x080c, - 0xce24, 0x009e, 0x080c, 0xaf4e, 0x0005, 0x080c, 0x97f6, 0x080c, - 0xce4a, 0x090c, 0xb93c, 0x080c, 0xaf4e, 0x0005, 0x0002, 0xc068, - 0xc066, 0xc066, 0xc066, 0xc066, 0xc066, 0xc066, 0xc066, 0xc066, - 0xc066, 0xc066, 0xc06a, 0xc06a, 0xc06a, 0xc06a, 0xc066, 0xc06c, - 0xc066, 0xc06a, 0xc066, 0xc066, 0xc066, 0xc066, 0x080c, 0x0d79, - 0x080c, 0x0d79, 0x080c, 0x0d79, 0x080c, 0xaf4e, 0x0804, 0x98bc, + 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, - 0xc08f, 0xc08f, 0xc08f, 0xc08f, 0xc08f, 0xc0c8, 0xc1ba, 0xc08f, - 0xc1c6, 0xc08f, 0xc08f, 0xc08f, 0xc08f, 0xc08f, 0xc08f, 0xc08f, - 0xc08f, 0xc08f, 0xc08f, 0xc1c6, 0xc091, 0xc08f, 0xc1c4, 0x080c, - 0x0d79, 0x00b6, 0x0096, 0x6114, 0x2148, 0x6010, 0x2058, 0xb800, - 0xd0bc, 0x1508, 0xa87b, 0x0000, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc24b, - 0x080c, 0x6d26, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, - 0xba3e, 0xb8d0, 0x9005, 0x0110, 0x080c, 0x68ae, 0x080c, 0xaf4e, - 0x009e, 0x00be, 0x0005, 0xa87c, 0xd0ac, 0x09e0, 0xa838, 0xa934, - 0x9105, 0x09c0, 0xa880, 0xd0bc, 0x19a8, 0x080c, 0xcf7f, 0x0c80, - 0x00b6, 0x0096, 0x6114, 0x2148, 0x601c, 0xd0fc, 0x1110, 0x7644, - 0x0008, 0x9036, 0x96b4, 0x0fff, 0x86ff, 0x1590, 0x6010, 0x2058, - 0xb800, 0xd0bc, 0x1904, 0xc1a9, 0xa87b, 0x0000, 0xa867, 0x0103, - 0xae76, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, - 0xc24b, 0x080c, 0x6d26, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, - 0x8211, 0xba3e, 0xb8d0, 0x9005, 0x0110, 0x080c, 0x68ae, 0x601c, - 0xd0fc, 0x1148, 0x7044, 0xd0e4, 0x1904, 0xc18a, 0x080c, 0xaf4e, - 0x009e, 0x00be, 0x0005, 0x2009, 0x0211, 0x210c, 0x080c, 0x0d79, - 0x968c, 0x0c00, 0x0150, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, - 0xc18e, 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, 0xc0d4, 0x735c, 0xab86, 0x83ff, 0x0170, - 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, - 0x0018, 0x2011, 0x0025, 0x080c, 0xc7ad, 0x003e, 0xd6cc, 0x0904, - 0xc0e9, 0x7154, 0xa98a, 0x81ff, 0x0904, 0xc0e9, 0x9192, 0x0021, - 0x1278, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xc7ad, - 0x2011, 0x0205, 0x2013, 0x0000, 0x080c, 0xd300, 0x0804, 0xc0e9, - 0xa868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c50, 0x00a6, - 0x2950, 0x080c, 0xc74c, 0x00ae, 0x080c, 0xd300, 0x080c, 0xc79d, - 0x0804, 0xc0eb, 0x080c, 0xcf42, 0x0804, 0xc100, 0xa87c, 0xd0ac, - 0x0904, 0xc111, 0xa880, 0xd0bc, 0x1904, 0xc111, 0x9684, 0x0400, - 0x0130, 0xa838, 0xab34, 0x9305, 0x0904, 0xc111, 0x00b8, 0x7348, - 0xa838, 0x9306, 0x1198, 0x734c, 0xa834, 0x931e, 0x0904, 0xc111, - 0x0068, 0xa87c, 0xd0ac, 0x0904, 0xc0dc, 0xa838, 0xa934, 0x9105, - 0x0904, 0xc0dc, 0xa880, 0xd0bc, 0x1904, 0xc0dc, 0x080c, 0xcf7f, - 0x0804, 0xc100, 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, - 0xab20, 0x604b, 0x0000, 0x080c, 0x1cb9, 0x1118, 0x6144, 0x080c, - 0x944c, 0x009e, 0x0005, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xc212, 0xc212, 0xc212, 0xc212, 0xc212, - 0xc212, 0xc212, 0xc212, 0xc212, 0xc212, 0xc214, 0xc212, 0xc212, - 0xc212, 0xc212, 0xc225, 0xc212, 0xc212, 0xc212, 0xc212, 0xc249, - 0xc212, 0xc212, 0x080c, 0x0d79, 0x6004, 0x9086, 0x0040, 0x1110, - 0x080c, 0x97f6, 0x2019, 0x0001, 0x080c, 0xa391, 0x6003, 0x0002, - 0x080c, 0xd37a, 0x080c, 0x9851, 0x0005, 0x6004, 0x9086, 0x0040, - 0x1110, 0x080c, 0x97f6, 0x2019, 0x0001, 0x080c, 0xa391, 0x080c, - 0x9851, 0x080c, 0x32fb, 0x080c, 0xd372, 0x0096, 0x6114, 0x2148, - 0x080c, 0xcc33, 0x0150, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, - 0x0000, 0x080c, 0x6f11, 0x080c, 0xce24, 0x009e, 0x080c, 0xaf4e, - 0x0005, 0x080c, 0x0d79, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, - 0x0007, 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, - 0x2009, 0x1a7d, 0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, - 0xa88e, 0x0005, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, - 0x000a, 0x0005, 0xc281, 0xc281, 0xc281, 0xc281, 0xc281, 0xc283, - 0xc281, 0xc281, 0xc340, 0xc281, 0xc281, 0xc281, 0xc281, 0xc281, - 0xc281, 0xc281, 0xc281, 0xc281, 0xc281, 0xc480, 0xc281, 0xc48a, - 0xc281, 0x080c, 0x0d79, 0x601c, 0xd0bc, 0x0178, 0xd084, 0x0168, - 0xd0f4, 0x0120, 0xc084, 0x601e, 0x0804, 0xc070, 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, 0xc339, 0x9694, 0xff00, 0x9284, - 0x0c00, 0x0120, 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, - 0x0904, 0xc339, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, - 0xc6c4, 0xb676, 0x0c38, 0x080c, 0x104d, 0x090c, 0x0d79, 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, - 0xc7ad, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, - 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, - 0x080c, 0xc7ad, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, - 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, - 0xc74c, 0x080c, 0x1abc, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, - 0x2001, 0x1989, 0x2004, 0x604a, 0x0096, 0x6114, 0x2148, 0xa83c, - 0xa940, 0x9105, 0x1118, 0xa87c, 0xc0dc, 0xa87e, 0x6003, 0x0002, - 0x080c, 0xd383, 0x0904, 0xc47b, 0x604b, 0x0000, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xc43f, - 0xa978, 0xa868, 0xd0fc, 0x0904, 0xc400, 0x0016, 0xa87c, 0x0006, - 0xa880, 0x0006, 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, - 0x0002, 0x0904, 0xc3cd, 0x9086, 0x0028, 0x1904, 0xc3b9, 0xa87b, - 0x001c, 0xb07b, 0x001c, 0x0804, 0xc3d5, 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, 0x0fff, 0x009e, 0x080c, 0xcf7f, 0x0804, - 0xc47b, 0xd1dc, 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, - 0xd220, 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, - 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, - 0xa834, 0xa938, 0x9115, 0x190c, 0xc24b, 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, 0xd300, 0x001e, - 0xa874, 0x0006, 0x2148, 0x080c, 0x0fff, 0x001e, 0x0804, 0xc46c, - 0x0016, 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, - 0x01e0, 0x9086, 0x0028, 0x1128, 0xa87b, 0x001c, 0xb07b, 0x001c, - 0x00e0, 0xd1dc, 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, - 0xd220, 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, - 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, - 0xa834, 0xa938, 0x9115, 0x190c, 0xc24b, 0xa890, 0xb092, 0xa88c, - 0xb08e, 0xa87c, 0xb07e, 0x00ae, 0x080c, 0x0fff, 0x009e, 0x080c, - 0xd300, 0xa974, 0x0016, 0x080c, 0xc79d, 0x001e, 0x0468, 0xa867, - 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, - 0x0028, 0x1118, 0xa87b, 0x001c, 0x00d0, 0xd1dc, 0x0148, 0xa87b, - 0x0015, 0x080c, 0xd220, 0x0118, 0xa974, 0xc1dc, 0xa976, 0x0078, - 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0050, 0xa87b, 0x0000, 0xa87c, - 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc24b, 0xa974, - 0x0016, 0x080c, 0x6d26, 0x001e, 0x6010, 0x00b6, 0x2058, 0xba3c, - 0xb8d0, 0x0016, 0x9005, 0x190c, 0x68ae, 0x001e, 0x00be, 0xd1e4, - 0x1120, 0x080c, 0xaf4e, 0x009e, 0x0005, 0x080c, 0xcf42, 0x0cd8, - 0x6114, 0x0096, 0x2148, 0xa97c, 0x080c, 0xd383, 0x190c, 0x1adc, - 0x009e, 0x0005, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, - 0x01e8, 0xa877, 0x0000, 0xa87b, 0x0000, 0xa867, 0x0103, 0x00b6, - 0x6010, 0x2058, 0xa834, 0xa938, 0x9115, 0x11a0, 0x080c, 0x6d26, - 0xba3c, 0x8211, 0x0208, 0xba3e, 0xb8d0, 0x9005, 0x0110, 0x080c, - 0x68ae, 0x080c, 0xaf4e, 0x00be, 0x009e, 0x0005, 0xa87c, 0xc0dc, - 0xa87e, 0x08f8, 0xb800, 0xd0bc, 0x1120, 0xa834, 0x080c, 0xc24b, - 0x0c28, 0xa880, 0xd0bc, 0x1dc8, 0x080c, 0xcf7f, 0x0c60, 0x080c, - 0x97f6, 0x0010, 0x080c, 0x9851, 0x601c, 0xd084, 0x0110, 0x080c, - 0x1af0, 0x080c, 0xcc33, 0x01f0, 0x0096, 0x6114, 0x2148, 0x080c, - 0xce4a, 0x1118, 0x080c, 0xb93c, 0x00a0, 0xa867, 0x0103, 0x2009, - 0x180c, 0x210c, 0xd18c, 0x1198, 0xd184, 0x1170, 0x6108, 0xa97a, - 0x918e, 0x0029, 0x1110, 0x080c, 0xeaee, 0xa877, 0x0000, 0x080c, - 0x6f11, 0x009e, 0x0804, 0xaf89, 0xa87b, 0x0004, 0x0cb0, 0xa87b, - 0x0004, 0x0c98, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, - 0x000a, 0x0005, 0xc511, 0xc511, 0xc511, 0xc511, 0xc511, 0xc513, - 0xc511, 0xc511, 0xc511, 0xc511, 0xc511, 0xc511, 0xc511, 0xc511, - 0xc511, 0xc511, 0xc511, 0xc511, 0xc511, 0xc511, 0xc537, 0xc511, - 0xc511, 0x080c, 0x0d79, 0x080c, 0x5828, 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, 0x6f11, 0x009e, 0x0804, 0xaf4e, 0x080c, - 0x5828, 0x0dd8, 0x6014, 0x900e, 0x9016, 0x0c10, 0x9182, 0x0085, - 0x0002, 0xc550, 0xc54e, 0xc54e, 0xc55c, 0xc54e, 0xc54e, 0xc54e, - 0xc54e, 0xc54e, 0xc54e, 0xc54e, 0xc54e, 0xc54e, 0x080c, 0x0d79, - 0x6003, 0x0001, 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0x8020, - 0x080c, 0x9420, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, - 0x2071, 0x0260, 0x7224, 0x6216, 0x7220, 0x080c, 0xcc21, 0x01f8, - 0x2268, 0x6800, 0x9086, 0x0000, 0x01d0, 0x6010, 0x6d10, 0x952e, - 0x11b0, 0x00c6, 0x2d60, 0x00d6, 0x080c, 0xc80e, 0x00de, 0x00ce, - 0x0158, 0x702c, 0xd084, 0x1118, 0x080c, 0xc7d8, 0x0010, 0x6803, - 0x0002, 0x6007, 0x0086, 0x0028, 0x080c, 0xc7fa, 0x0d90, 0x6007, - 0x0087, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9420, 0x7220, - 0x080c, 0xcc21, 0x0178, 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x0140, 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, - 0xcf7f, 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, - 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d79, 0x908a, - 0x0092, 0x1a0c, 0x0d79, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, - 0x0120, 0x9186, 0x0014, 0x190c, 0x0d79, 0x080c, 0x97f6, 0x0096, - 0x6014, 0x2048, 0x080c, 0xcc33, 0x0140, 0xa867, 0x0103, 0xa877, - 0x0000, 0xa87b, 0x0029, 0x080c, 0x6f11, 0x009e, 0x080c, 0xaf89, - 0x0804, 0x98bc, 0xc5df, 0xc5e1, 0xc5e1, 0xc5df, 0xc5df, 0xc5df, - 0xc5df, 0xc5df, 0xc5df, 0xc5df, 0xc5df, 0xc5df, 0xc5df, 0x080c, - 0x0d79, 0x080c, 0xaf89, 0x0005, 0x9186, 0x0013, 0x1130, 0x6004, - 0x9082, 0x0085, 0x2008, 0x0804, 0xc630, 0x9186, 0x0027, 0x1558, - 0x080c, 0x97f6, 0x080c, 0x32fb, 0x080c, 0xd372, 0x0096, 0x6014, - 0x2048, 0x080c, 0xcc33, 0x0150, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0029, 0x080c, 0x6f11, 0x080c, 0xce24, 0x009e, 0x080c, - 0xaf4e, 0x0005, 0x9186, 0x0089, 0x0118, 0x9186, 0x008a, 0x1140, - 0x080c, 0xad4d, 0x0128, 0x9086, 0x000c, 0x0904, 0xc668, 0x0000, - 0x080c, 0xb009, 0x0c70, 0x9186, 0x0014, 0x1d60, 0x080c, 0x97f6, - 0x0096, 0x6014, 0x2048, 0x080c, 0xcc33, 0x0d00, 0xa867, 0x0103, - 0xa877, 0x0000, 0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, 0x0890, - 0x0002, 0xc640, 0xc63e, 0xc63e, 0xc63e, 0xc63e, 0xc63e, 0xc654, - 0xc63e, 0xc63e, 0xc63e, 0xc63e, 0xc63e, 0xc63e, 0x080c, 0x0d79, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x2001, 0x1987, 0x0010, 0x2001, 0x1988, 0x2004, - 0x601a, 0x6003, 0x000c, 0x0005, 0x6034, 0x908c, 0xff00, 0x810f, - 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x1987, - 0x0010, 0x2001, 0x1988, 0x2004, 0x601a, 0x6003, 0x000e, 0x0005, - 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, - 0xb009, 0xc67e, 0xc67e, 0xc67e, 0xc67e, 0xc680, 0xc6cd, 0xc67e, - 0xc67e, 0xc67e, 0xc67e, 0xc67e, 0xc67e, 0xc67e, 0x080c, 0x0d79, - 0x0096, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x009e, 0x0804, 0xc6e1, 0x080c, 0xcc33, 0x1118, - 0x080c, 0xce24, 0x0068, 0x6014, 0x2048, 0x080c, 0xd389, 0x1110, - 0x080c, 0xce24, 0xa867, 0x0103, 0x080c, 0xd33d, 0x080c, 0x6f11, - 0x00d6, 0x2c68, 0x080c, 0xaef8, 0x01d0, 0x6003, 0x0001, 0x6007, - 0x001e, 0x600b, 0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, - 0x026f, 0x210c, 0x613e, 0x6910, 0x6112, 0x080c, 0xd0ce, 0x695c, - 0x615e, 0x6023, 0x0001, 0x2009, 0x8020, 0x080c, 0x9420, 0x2d60, - 0x00de, 0x080c, 0xaf4e, 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, 0xd2d3, 0x11f0, 0x080c, 0xaef8, - 0x01d8, 0x6106, 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, - 0x692c, 0x612e, 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, - 0x6938, 0x613a, 0x693c, 0x613e, 0x695c, 0x615e, 0x080c, 0xd0ce, - 0x2009, 0x8020, 0x080c, 0x9420, 0x2d60, 0x00de, 0x0804, 0xaf4e, - 0x0096, 0x6014, 0x2048, 0x080c, 0xcc33, 0x01c8, 0xa867, 0x0103, - 0xa880, 0xd0b4, 0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, - 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, - 0xcf3e, 0xa877, 0x0000, 0x080c, 0x6f11, 0x080c, 0xce24, 0x009e, - 0x0804, 0xaf4e, 0x0016, 0x0096, 0x6014, 0x2048, 0x080c, 0xcc33, - 0x0140, 0xa867, 0x0103, 0xa87b, 0x0028, 0xa877, 0x0000, 0x080c, - 0x6f11, 0x009e, 0x001e, 0x9186, 0x0013, 0x0158, 0x9186, 0x0014, - 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, 0xb009, 0x0020, 0x080c, - 0x97f6, 0x080c, 0xaf89, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, - 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, - 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, - 0x080c, 0xc7ad, 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c, - 0x0fff, 0x080c, 0x104d, 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, 0x6f11, 0x2a48, - 0x0cb8, 0x080c, 0x6f11, 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, 0xcc33, - 0x0150, 0x2001, 0x0006, 0xa980, 0xc1d5, 0x080c, 0x715d, 0x080c, - 0x6f05, 0x080c, 0xce24, 0x009e, 0x080c, 0xaf89, 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, - 0xc860, 0xc860, 0xc85b, 0xc884, 0xc838, 0xc85b, 0xc83a, 0xc85b, - 0xc85b, 0x92df, 0xc85b, 0xc85b, 0xc85b, 0xc838, 0xc838, 0xc838, - 0x080c, 0x0d79, 0x6010, 0x9080, 0x0000, 0x2004, 0xd0bc, 0x190c, - 0xc884, 0x0036, 0x6014, 0x0096, 0x2048, 0xa880, 0x009e, 0xd0cc, - 0x0118, 0x2019, 0x000c, 0x0038, 0xd094, 0x0118, 0x2019, 0x000d, - 0x0010, 0x2019, 0x0010, 0x080c, 0xe28e, 0x6023, 0x0006, 0x6003, - 0x0007, 0x003e, 0x0005, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, - 0x0096, 0x86ff, 0x11e8, 0x6014, 0x2048, 0x080c, 0xcc33, 0x01d0, - 0x6043, 0xffff, 0xa864, 0x9086, 0x0139, 0x1128, 0xa87b, 0x0005, - 0xa883, 0x0000, 0x0028, 0x900e, 0x2001, 0x0005, 0x080c, 0x715d, - 0x080c, 0xcf3e, 0x080c, 0x6f05, 0x080c, 0xaf89, 0x9085, 0x0001, - 0x009e, 0x0005, 0x9006, 0x0ce0, 0x080c, 0xaaf7, 0x080c, 0xd397, - 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d79, 0x002b, 0x0106, 0x080c, - 0xab13, 0x010e, 0x0005, 0xc8a3, 0xc8d3, 0xc8a5, 0xc8fa, 0xc8ce, - 0xc8a3, 0xc85b, 0xc860, 0xc860, 0xc85b, 0xc85b, 0xc85b, 0xc85b, - 0xc85b, 0xc85b, 0xc85b, 0x080c, 0x0d79, 0x86ff, 0x1520, 0x6020, - 0x9086, 0x0006, 0x0500, 0x0096, 0x6014, 0x2048, 0x080c, 0xcc33, - 0x0168, 0xa87c, 0xd0cc, 0x0140, 0x0096, 0xc0cc, 0xa87e, 0xa878, - 0x2048, 0x080c, 0x0fff, 0x009e, 0x080c, 0xcf3e, 0x009e, 0x080c, - 0xd317, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2009, - 0x8020, 0x080c, 0x9402, 0x9085, 0x0001, 0x0005, 0x0066, 0x080c, - 0x1af0, 0x006e, 0x0890, 0x00e6, 0x2071, 0x19e9, 0x7030, 0x9c06, - 0x1120, 0x080c, 0xa311, 0x00ee, 0x0840, 0x6020, 0x9084, 0x000f, - 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, - 0x080c, 0xa462, 0x009e, 0x008e, 0x0040, 0x0066, 0x080c, 0xa20d, - 0x190c, 0x0d79, 0x080c, 0xa21b, 0x006e, 0x00ee, 0x1904, 0xc8a5, - 0x0804, 0xc85b, 0x0036, 0x00e6, 0x2071, 0x19e9, 0x704c, 0x9c06, - 0x1138, 0x901e, 0x080c, 0xa391, 0x00ee, 0x003e, 0x0804, 0xc8a5, - 0x080c, 0xa59c, 0x00ee, 0x003e, 0x1904, 0xc8a5, 0x0804, 0xc85b, - 0x00c6, 0x0066, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x00ce, - 0x0005, 0xc930, 0xc9fe, 0xcb68, 0xc938, 0xaf89, 0xc930, 0xe280, - 0xd37f, 0xc9fe, 0x92a6, 0xcbf4, 0xc929, 0xc929, 0xc929, 0xc929, - 0xc929, 0x080c, 0x0d79, 0x080c, 0xce4a, 0x1110, 0x080c, 0xb93c, - 0x0005, 0x080c, 0x97f6, 0x0804, 0xaf4e, 0x601b, 0x0001, 0x0005, - 0x080c, 0xcc33, 0x0130, 0x6014, 0x0096, 0x2048, 0x2c00, 0xa896, - 0x009e, 0x080c, 0xaaf7, 0x080c, 0xd397, 0x6000, 0x908a, 0x0010, - 0x1a0c, 0x0d79, 0x0013, 0x0804, 0xab13, 0xc95d, 0xc95f, 0xc989, - 0xc99d, 0xc9ca, 0xc95d, 0xc930, 0xc930, 0xc930, 0xc9a4, 0xc9a4, - 0xc95d, 0xc95d, 0xc95d, 0xc95d, 0xc9ae, 0x080c, 0x0d79, 0x00e6, + 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, - 0x19e9, 0x7030, 0x9c06, 0x01d0, 0x0066, 0x080c, 0xa20d, 0x190c, - 0x0d79, 0x080c, 0xa21b, 0x006e, 0x080c, 0xd317, 0x6007, 0x0085, - 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, 0x1988, 0x2004, 0x601a, - 0x2009, 0x8020, 0x080c, 0x9402, 0x00ee, 0x0005, 0x601b, 0x0001, + 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, 0xd317, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x2009, 0x8020, 0x080c, 0x9402, 0x0005, 0x080c, 0xaaf7, 0x080c, - 0xaccf, 0x080c, 0xab13, 0x0c28, 0x0096, 0x601b, 0x0001, 0x6014, - 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x0005, 0x080c, 0x5828, + 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, 0x6f11, 0x009e, - 0x0804, 0xaf4e, 0x6014, 0x0096, 0x904d, 0x0558, 0xa97c, 0xd1e4, - 0x1158, 0x611c, 0xd1fc, 0x0528, 0x6110, 0x00b6, 0x2158, 0xb93c, - 0x8109, 0x0208, 0xb93e, 0x00be, 0x080c, 0xab13, 0x2001, 0x180f, - 0x2004, 0xd0c4, 0x0110, 0x009e, 0x0005, 0xa884, 0x009e, 0x8003, - 0x800b, 0x810b, 0x9108, 0x611a, 0x00c6, 0x080c, 0x21a2, 0x00ce, - 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0xafec, - 0x0005, 0x009e, 0x080c, 0x1af0, 0x0804, 0xc989, 0x6000, 0x908a, - 0x0010, 0x1a0c, 0x0d79, 0x000b, 0x0005, 0xca15, 0xc935, 0xca17, - 0xca15, 0xca17, 0xca17, 0xc931, 0xca15, 0xc92b, 0xc92b, 0xca15, - 0xca15, 0xca15, 0xca15, 0xca15, 0xca15, 0x080c, 0x0d79, 0x6010, - 0x00b6, 0x2058, 0xb804, 0x9084, 0x00ff, 0x00be, 0x908a, 0x000c, - 0x1a0c, 0x0d79, 0x00b6, 0x0013, 0x00be, 0x0005, 0xca32, 0xcaff, - 0xca34, 0xca74, 0xca34, 0xca74, 0xca34, 0xca42, 0xca32, 0xca74, - 0xca32, 0xca63, 0x080c, 0x0d79, 0x6004, 0x908e, 0x0016, 0x05c0, - 0x908e, 0x0004, 0x05a8, 0x908e, 0x0002, 0x0590, 0x908e, 0x0052, - 0x0904, 0xcafb, 0x6004, 0x080c, 0xce4a, 0x0904, 0xcb18, 0x908e, - 0x0004, 0x1110, 0x080c, 0x332a, 0x908e, 0x0021, 0x0904, 0xcb1c, - 0x908e, 0x0022, 0x0904, 0xcb63, 0x908e, 0x003d, 0x0904, 0xcb1c, - 0x908e, 0x0039, 0x0904, 0xcb20, 0x908e, 0x0035, 0x0904, 0xcb20, - 0x908e, 0x001e, 0x0178, 0x908e, 0x0001, 0x1140, 0x6010, 0x2058, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0110, 0x080c, 0x32fb, - 0x080c, 0xb93c, 0x0804, 0xaf89, 0x00c6, 0x00d6, 0x6104, 0x9186, - 0x0016, 0x0904, 0xcaec, 0x9186, 0x0002, 0x1904, 0xcac1, 0x2001, - 0x1837, 0x2004, 0xd08c, 0x11c8, 0x080c, 0x769d, 0x11b0, 0x080c, - 0xd35d, 0x0138, 0x080c, 0x76c0, 0x1120, 0x080c, 0x75a6, 0x0804, - 0xcb4c, 0x2001, 0x197e, 0x2003, 0x0001, 0x2001, 0x1800, 0x2003, - 0x0001, 0x080c, 0x75cc, 0x0804, 0xcb4c, 0x6010, 0x2058, 0x2001, - 0x1837, 0x2004, 0xd0ac, 0x1904, 0xcb4c, 0xb8a0, 0x9084, 0xff80, - 0x1904, 0xcb4c, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, + 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, 0xaef8, 0x0128, 0x2b00, 0x6012, 0x6023, 0x0001, + 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, 0x610b, 0x00ee, - 0x080c, 0xb93c, 0x0030, 0x080c, 0xb93c, 0x080c, 0x32fb, 0x080c, - 0xd372, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x332a, 0x012e, - 0x00ee, 0x080c, 0xaf89, 0x0005, 0x2001, 0x0002, 0x080c, 0x66c9, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9427, 0x080c, 0x98bc, - 0x00de, 0x00ce, 0x0c80, 0x080c, 0x332a, 0x0804, 0xca70, 0x00c6, + 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, 0xcac1, 0x8001, 0xb842, 0x6003, - 0x0001, 0x080c, 0x9427, 0x080c, 0x98bc, 0x00de, 0x00ce, 0x0898, - 0x080c, 0xb93c, 0x0804, 0xca72, 0x080c, 0xb978, 0x0804, 0xca72, - 0x00d6, 0x2c68, 0x6104, 0x080c, 0xd2d3, 0x00de, 0x0118, 0x080c, - 0xaf4e, 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, + 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, 0x1988, 0x2004, 0x601a, 0x602c, 0x2c08, 0x2060, + 0x600a, 0x2001, 0x1987, 0x2004, 0x601a, 0x602c, 0x2c08, 0x2060, 0x6024, 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160, 0x2009, - 0x8020, 0x080c, 0x9420, 0x0005, 0x00de, 0x00ce, 0x080c, 0xb93c, - 0x080c, 0x32fb, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x332a, + 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, 0xb38a, 0x1904, 0xcb18, 0x0005, - 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d79, 0x0096, 0x00d6, 0x001b, - 0x00de, 0x009e, 0x0005, 0xcb83, 0xcb83, 0xcb83, 0xcb83, 0xcb83, - 0xcb83, 0xcb83, 0xcb83, 0xcb83, 0xc930, 0xcb83, 0xc935, 0xcb85, - 0xc935, 0xcb9f, 0xcb83, 0x080c, 0x0d79, 0x6004, 0x9086, 0x008b, + 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, 0x9420, 0x0005, 0x080c, - 0xd351, 0x0118, 0x080c, 0xd364, 0x0010, 0x080c, 0xd372, 0x080c, - 0xce24, 0x080c, 0xcc33, 0x0570, 0x080c, 0x32fb, 0x080c, 0xcc33, + 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, 0x6f11, 0x2c68, 0x080c, - 0xaef8, 0x0150, 0x6810, 0x6012, 0x080c, 0xd0ce, 0x00c6, 0x2d60, - 0x080c, 0xaf89, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023, - 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9427, 0x080c, - 0x98bc, 0x00c8, 0x080c, 0xd351, 0x0138, 0x6034, 0x9086, 0x4000, - 0x1118, 0x080c, 0x32fb, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f, - 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x32fb, - 0x0868, 0x080c, 0xaf89, 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, - 0x0d79, 0x0002, 0xcc0a, 0xcc0a, 0xcc12, 0xcc0c, 0xcc1c, 0xcc0a, - 0xcc0a, 0xaf89, 0xcc0a, 0xcc0a, 0xcc0a, 0xcc0a, 0xcc0a, 0xcc0a, - 0xcc0a, 0xcc0a, 0x080c, 0x0d79, 0x080c, 0xaaf7, 0x080c, 0xaccf, - 0x080c, 0xab13, 0x6114, 0x0096, 0x2148, 0xa87b, 0x0006, 0x080c, - 0x6f11, 0x009e, 0x0804, 0xaf4e, 0x601c, 0xd084, 0x190c, 0x1af0, + 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, 0x10f8, + 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, 0xd35d, 0x0180, + 0x9302, 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xd645, 0x0180, 0x9286, 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, - 0x32fb, 0x080c, 0xd372, 0x00c6, 0x080c, 0xaf89, 0x00ce, 0x0060, - 0x080c, 0xd040, 0x0148, 0x080c, 0xce4a, 0x1110, 0x080c, 0xb93c, - 0x00c6, 0x080c, 0xaf4e, 0x00ce, 0x9ce0, 0x001c, 0x7068, 0x9c02, + 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, 0x1b3a, 0x6112, 0x080c, 0x32fb, 0x9006, 0x0010, 0x9085, + 0x2061, 0x1b39, 0x6112, 0x080c, 0x3315, 0x9006, 0x0010, 0x9085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0xaef8, 0x01b0, 0x665e, 0x2b00, 0x6012, 0x080c, - 0x5828, 0x0118, 0x080c, 0xcd66, 0x0168, 0x080c, 0xd0ce, 0x6023, - 0x0003, 0x2009, 0x004b, 0x080c, 0xafec, 0x9085, 0x0001, 0x012e, + 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, 0xafbf, 0x0580, 0x605f, 0x0000, 0x2b00, 0x6012, - 0x080c, 0xd0ce, 0x6023, 0x0003, 0x0016, 0x080c, 0xaaf7, 0x080c, - 0x95b9, 0x0076, 0x903e, 0x080c, 0x9476, 0x2c08, 0x080c, 0xe465, - 0x007e, 0x080c, 0xab13, 0x001e, 0xd184, 0x0128, 0x080c, 0xaf4e, - 0x9085, 0x0001, 0x0070, 0x080c, 0x5828, 0x0128, 0xd18c, 0x1170, - 0x080c, 0xcd66, 0x0148, 0x2009, 0x004c, 0x080c, 0xafec, 0x9085, + 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, 0xaef8, 0x2c78, 0x05a0, 0x7e5e, 0x2b00, - 0x7812, 0x7823, 0x0003, 0x0016, 0x2021, 0x0005, 0x080c, 0xcd78, + 0x0046, 0x0016, 0x080c, 0xb116, 0x2c78, 0x05a0, 0x7e5e, 0x2b00, + 0x7812, 0x7823, 0x0003, 0x0016, 0x2021, 0x0005, 0x080c, 0xd060, 0x001e, 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148, 0x2001, - 0x1981, 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0xaf4e, 0x00d0, - 0x2001, 0x1980, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xaf4e, - 0x0088, 0x2f60, 0x080c, 0x5828, 0x0138, 0xd18c, 0x1118, 0x04f1, - 0x0148, 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, 0x080c, 0xafec, + 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, 0xaef8, 0x2c78, 0x0508, 0x7e5e, 0x2b00, + 0x00c6, 0x0046, 0x080c, 0xb116, 0x2c78, 0x0508, 0x7e5e, 0x2b00, 0x7812, 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, 0x0489, 0x009e, - 0x2001, 0x197f, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xaf4e, - 0x0060, 0x2f60, 0x080c, 0x5828, 0x0120, 0xd18c, 0x1160, 0x0071, - 0x0130, 0x2009, 0x0052, 0x080c, 0xafec, 0x9085, 0x0001, 0x004e, + 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, - 0x4bc8, 0x00ce, 0x1120, 0x080c, 0xaf4e, 0x9006, 0x0005, 0xa867, + 0x4c41, 0x00ce, 0x1120, 0x080c, 0xb16c, 0x9006, 0x0005, 0xa867, 0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, 0x0001, 0x0005, - 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0xaaf7, 0x080c, - 0x6963, 0x0158, 0x2001, 0xcd7f, 0x0006, 0x900e, 0x2400, 0x080c, - 0x715d, 0x080c, 0x6f11, 0x000e, 0x0807, 0x2418, 0x080c, 0x97bc, + 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, - 0x95d3, 0x008e, 0x080c, 0x9476, 0x2f08, 0x2648, 0x080c, 0xe465, - 0xb93c, 0x81ff, 0x090c, 0x96ac, 0x080c, 0xab13, 0x012e, 0x007e, - 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xaef8, - 0x0190, 0x660a, 0x2b08, 0x6112, 0x080c, 0xd0ce, 0x6023, 0x0001, - 0x2900, 0x6016, 0x2009, 0x001f, 0x080c, 0xafec, 0x9085, 0x0001, + 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, 0xafbf, 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, - 0xd0ce, 0x6023, 0x0008, 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, - 0x17a1, 0x00fe, 0x2009, 0x0021, 0x080c, 0xafec, 0x9085, 0x0001, + 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, 0xaef8, 0x0198, 0x660a, - 0x2b08, 0x6112, 0x080c, 0xd0ce, 0x6023, 0x0001, 0x2900, 0x6016, - 0x001e, 0x0016, 0x080c, 0xafec, 0x9085, 0x0001, 0x001e, 0x012e, + 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, 0xafbf, 0x0188, 0x2b08, 0x6112, 0x080c, 0xd0ce, 0x6023, - 0x0001, 0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0xafec, 0x9085, + 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, @@ -6384,62 +6477,62 @@ unsigned short risc_code01[] = { 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, 0xcc33, 0x0180, 0xa864, 0x9086, + 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, 0xafbf, 0x0198, 0x2b08, 0x6112, 0x080c, 0xd0ce, 0x6023, - 0x0001, 0x2900, 0x6016, 0x080c, 0x32fb, 0x2009, 0x0028, 0x080c, - 0xafec, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 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, 0xbb92, 0x00be, 0x080c, 0xbdb7, 0x6003, - 0x0001, 0x6007, 0x0029, 0x080c, 0x9427, 0x080c, 0x98bc, 0x0078, + 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, 0xd294, 0x080c, 0xb93c, 0x080c, 0xaf4e, 0x0005, - 0x0096, 0x6014, 0x904d, 0x090c, 0x0d79, 0xa87b, 0x0030, 0xa883, + 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, 0x6f11, 0x012e, 0x009e, 0x080c, 0xaf4e, + 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x009e, 0x080c, 0xb16c, 0x0c30, 0x0096, 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, - 0x66c9, 0x00e8, 0x9186, 0x0015, 0x1510, 0x2011, 0x1824, 0x2204, - 0x9086, 0x0014, 0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x681e, - 0x00be, 0x080c, 0xbe8d, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, - 0x00be, 0x9005, 0x0160, 0x2001, 0x0006, 0x080c, 0x66c9, 0x6014, - 0x2048, 0xa868, 0xd0fc, 0x0170, 0x080c, 0xb35e, 0x0048, 0x6014, - 0x2048, 0xa868, 0xd0fc, 0x0528, 0x080c, 0xb93c, 0x080c, 0xaf4e, - 0x009e, 0x0005, 0x6014, 0x6310, 0x2358, 0x904d, 0x090c, 0x0d79, + 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, - 0x6a74, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6f11, 0x012e, 0x080c, 0xaf4e, - 0x08f8, 0x6014, 0x904d, 0x090c, 0x0d79, 0xa87b, 0x0030, 0xa883, + 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, 0x6f11, 0x012e, 0x080c, 0xaf4e, 0x0840, + 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, 0x9420, 0x0005, 0x00c6, + 0x6007, 0x0050, 0x2009, 0x8023, 0x080c, 0x9617, 0x0005, 0x00c6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0130, 0x0066, - 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x00ce, 0x0005, 0xc930, - 0xcf71, 0xcf71, 0xcf74, 0xe7e4, 0xe7ff, 0xe802, 0xc930, 0xc930, - 0xc930, 0xc930, 0xc930, 0xc930, 0xc930, 0xc930, 0xc930, 0x080c, - 0x0d79, 0xa001, 0xa001, 0x0005, 0x0096, 0x6014, 0x904d, 0x0118, + 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, 0xaef8, 0x0508, - 0x7810, 0x6012, 0x080c, 0xd0ce, 0x7820, 0x9086, 0x0003, 0x0128, + 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, 0x9420, 0x2f60, 0x00fe, - 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1989, 0x2004, 0x604a, 0x0005, + 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, 0x0fff, 0x6830, 0x6036, 0x908e, 0x0001, + 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, 0x9420, 0x009e, 0x001e, + 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, @@ -6450,613 +6543,615 @@ unsigned short risc_code01[] = { 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, 0x1983, 0x200c, - 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x9364, 0x2001, 0x1987, - 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1985, 0x200c, - 0x8000, 0x2014, 0x2071, 0x196d, 0x711a, 0x721e, 0x2001, 0x0064, - 0x080c, 0x9364, 0x2001, 0x1988, 0x82ff, 0x1110, 0x2011, 0x0014, - 0x2202, 0x2001, 0x1989, 0x9288, 0x000a, 0x2102, 0x2001, 0x0017, - 0x080c, 0xaae8, 0x2001, 0x1a91, 0x2102, 0x2001, 0x0032, 0x080c, - 0x16ad, 0x080c, 0x6bae, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, - 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, 0x1987, 0x2003, 0x0028, - 0x2001, 0x1988, 0x2003, 0x0014, 0x2071, 0x196d, 0x701b, 0x0000, - 0x701f, 0x07d0, 0x2001, 0x1989, 0x2009, 0x001e, 0x2102, 0x2001, - 0x0017, 0x080c, 0xaae8, 0x2001, 0x1a91, 0x2102, 0x2001, 0x0032, - 0x080c, 0x16ad, 0x00ee, 0x001e, 0x000e, 0x0005, 0x0096, 0x6060, - 0x904d, 0x0110, 0x080c, 0x107f, 0x009e, 0x0005, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0xaef8, 0x0180, 0x2b08, 0x6112, + 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, - 0xafec, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 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, 0x998c, + 0x6014, 0x2048, 0xaa3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x9b83, 0x01d8, 0x707c, 0xaa50, 0x9206, 0x1160, 0x7080, 0xaa54, 0x9206, 0x1140, 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x900e, 0x080c, - 0x334a, 0x080c, 0xb35e, 0x0020, 0x080c, 0xb93c, 0x080c, 0xaf4e, + 0x3364, 0x080c, 0xb57c, 0x0020, 0x080c, 0xbb5c, 0x080c, 0xb16c, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa54, 0x9206, 0x0d48, - 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xaef8, 0x0188, - 0x2b08, 0x6112, 0x080c, 0xd0ce, 0x6023, 0x0001, 0x2900, 0x6016, - 0x2009, 0x004d, 0x080c, 0xafec, 0x9085, 0x0001, 0x012e, 0x00ce, + 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, 0xaef8, 0x0180, 0x2b08, 0x6112, 0x080c, 0xd0ce, 0x6023, - 0x0001, 0x2900, 0x6016, 0x001e, 0x080c, 0xafec, 0x9085, 0x0001, + 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, 0x19a2, 0x2003, + 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, 0x19a2, 0x0016, 0x200c, 0x080c, 0xd9b7, 0x001e, 0xa804, + 0x2001, 0x19a1, 0x0016, 0x200c, 0x080c, 0xdca1, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c38, 0x6014, 0x2048, 0xa867, 0x0103, - 0x0010, 0x080c, 0xb93c, 0x080c, 0xaf4e, 0x00fe, 0x00ee, 0x009e, + 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, 0x998c, + 0x9086, 0x0004, 0x1198, 0x6014, 0x2048, 0x2c78, 0x080c, 0x9b83, 0x01a8, 0x707c, 0xaa74, 0x9206, 0x1130, 0x7080, 0xaa78, 0x9206, - 0x1110, 0x080c, 0x32fb, 0x080c, 0xb35e, 0x0020, 0x080c, 0xb93c, - 0x080c, 0xaf4e, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa78, + 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, 0x998c, 0x05f0, 0x707c, 0xaacc, 0x9206, - 0x1180, 0x7080, 0xaad0, 0x9206, 0x1160, 0x080c, 0x32fb, 0x0016, - 0xa998, 0xaab0, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x57c9, 0x001e, - 0x0010, 0x080c, 0x55ac, 0x080c, 0xcc33, 0x0508, 0xa87b, 0x0000, - 0xa883, 0x0000, 0xa897, 0x4000, 0x0080, 0x080c, 0xcc33, 0x01b8, - 0x6014, 0x2048, 0x080c, 0x55ac, 0x1d70, 0xa87b, 0x0030, 0xa883, + 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, 0x6f11, 0x012e, 0x080c, 0xaf4e, 0x00fe, + 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, 0xcc33, 0x0904, 0xd290, 0x0096, 0x6314, + 0x00d6, 0x0036, 0x080c, 0xcf1b, 0x0904, 0xd578, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x929e, 0x4000, 0x1580, 0x6310, 0x00c6, - 0x2358, 0x2009, 0x0000, 0xa868, 0xd0f4, 0x1140, 0x080c, 0x6a74, + 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, 0x0fca, + 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fd6, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c8, 0x9080, - 0x000a, 0x2098, 0x080c, 0x0fca, 0x00ce, 0x0090, 0xaa96, 0x3918, + 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, 0x6f05, 0x6017, 0x0000, 0x009e, + 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, - 0x26a1, 0x2118, 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, - 0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, 0x4c28, 0x00a8, 0x9096, + 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, 0xcc21, 0x01f0, 0x2260, + 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, 0xc24b, 0x0005, 0x0036, + 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0x0005, 0x0036, 0x2019, 0x0001, 0x0010, 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c, - 0xcc33, 0x01c8, 0x080c, 0xce24, 0x6037, 0x4000, 0x6014, 0x6017, - 0x0000, 0x0096, 0x2048, 0xa87c, 0x080c, 0xce4a, 0x1118, 0x080c, - 0xb93c, 0x0040, 0xa867, 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129, - 0x080c, 0x6f11, 0x009e, 0x003e, 0x0005, 0xa880, 0xd0b4, 0x0128, + 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, 0xcf3e, 0xa877, 0x0000, + 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, 0x4ddf, 0x004e, - 0x003e, 0x0005, 0x0c51, 0x1d81, 0x0005, 0x2001, 0x1987, 0x2004, - 0x601a, 0x0005, 0x2001, 0x1989, 0x2004, 0x604a, 0x0005, 0x080c, - 0xaf4e, 0x0804, 0x98bc, 0x611c, 0xd1fc, 0xa97c, 0x1108, 0xd1e4, + 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, 0x0198, 0xc0bc, 0x6046, 0x6003, 0x0002, - 0x0070, 0xd0ac, 0x1160, 0xd0dc, 0x1128, 0x908c, 0x000f, 0x9186, - 0x0005, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x0005, - 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d79, 0x001b, - 0x006e, 0x00be, 0x0005, 0xd3cb, 0xdb14, 0xdc78, 0xd3cb, 0xd3cb, - 0xd3cb, 0xd3cb, 0xd3cb, 0xd402, 0xdcfc, 0xd3cb, 0xd3cb, 0xd3cb, - 0xd3cb, 0xd3cb, 0xd3cb, 0x080c, 0x0d79, 0x0066, 0x6000, 0x90b2, - 0x0010, 0x1a0c, 0x0d79, 0x0013, 0x006e, 0x0005, 0xd3e6, 0xe21d, - 0xd3e6, 0xd3e6, 0xd3e6, 0xd3e6, 0xd3e6, 0xd3e6, 0xe1cc, 0xe26f, - 0xd3e6, 0xe91f, 0xe953, 0xe91f, 0xe953, 0xd3e6, 0x080c, 0x0d79, - 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0d79, 0x6000, 0x000a, 0x0005, - 0xd400, 0xded9, 0xdfa4, 0xdfc7, 0xe043, 0xd400, 0xe13e, 0xe0cb, - 0xdd06, 0xe1a4, 0xe1b9, 0xd400, 0xd400, 0xd400, 0xd400, 0xd400, - 0x080c, 0x0d79, 0x91b2, 0x0053, 0x1a0c, 0x0d79, 0x2100, 0x91b2, - 0x0040, 0x1a04, 0xd886, 0x0002, 0xd44c, 0xd654, 0xd44c, 0xd44c, - 0xd44c, 0xd65d, 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd44c, - 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd44c, - 0xd44c, 0xd44c, 0xd44c, 0xd44e, 0xd4b5, 0xd4c4, 0xd528, 0xd553, - 0xd5cc, 0xd63f, 0xd44c, 0xd44c, 0xd660, 0xd44c, 0xd44c, 0xd675, - 0xd682, 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd728, 0xd44c, - 0xd44c, 0xd73c, 0xd44c, 0xd44c, 0xd6f7, 0xd44c, 0xd44c, 0xd44c, - 0xd754, 0xd44c, 0xd44c, 0xd44c, 0xd7d1, 0xd44c, 0xd44c, 0xd44c, - 0xd44c, 0xd44c, 0xd44c, 0xd84e, 0x080c, 0x0d79, 0x080c, 0x6b8b, - 0x1150, 0x2001, 0x1837, 0x2004, 0xd0cc, 0x1128, 0x9084, 0x0009, - 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, 0x602f, 0x0009, 0x6017, - 0x0000, 0x0804, 0xd64d, 0x080c, 0x6b27, 0x00e6, 0x00c6, 0x0036, - 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, - 0x080c, 0xaaf7, 0x080c, 0x95b9, 0x0076, 0x903e, 0x080c, 0x9476, - 0x2c08, 0x080c, 0xe465, 0x007e, 0x001e, 0x080c, 0xab13, 0x001e, - 0x002e, 0x003e, 0x00ce, 0x00ee, 0x6610, 0x2658, 0x080c, 0x6792, - 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1268, 0x0016, 0x0026, - 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x2c08, 0x080c, 0xeb7e, - 0x002e, 0x001e, 0x1178, 0x080c, 0xe393, 0x1904, 0xd520, 0x080c, - 0xe32f, 0x1120, 0x6007, 0x0008, 0x0804, 0xd64d, 0x6007, 0x0009, - 0x0804, 0xd64d, 0x080c, 0xe60d, 0x0128, 0x080c, 0xe393, 0x0d78, - 0x0804, 0xd520, 0x6017, 0x1900, 0x0c88, 0x080c, 0x3432, 0x1904, - 0xd883, 0x6106, 0x080c, 0xe2cf, 0x6007, 0x0006, 0x0804, 0xd64d, - 0x6007, 0x0007, 0x0804, 0xd64d, 0x080c, 0xe98f, 0x1904, 0xd883, - 0x080c, 0x3432, 0x1904, 0xd883, 0x00d6, 0x6610, 0x2658, 0xbe04, - 0x9684, 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, - 0x66b5, 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, 0xe3fb, - 0x1190, 0x9686, 0x0006, 0x1140, 0x0026, 0x6210, 0x2258, 0xbaa0, - 0x900e, 0x080c, 0x334a, 0x002e, 0x080c, 0x681e, 0x6007, 0x000a, - 0x00de, 0x0804, 0xd64d, 0x6007, 0x000b, 0x00de, 0x0804, 0xd64d, - 0x080c, 0x32fb, 0x080c, 0xd372, 0x6007, 0x0001, 0x0804, 0xd64d, - 0x080c, 0xe98f, 0x1904, 0xd883, 0x080c, 0x3432, 0x1904, 0xd883, - 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, 0x334a, 0x002e, 0x6007, 0x000c, 0x2001, 0x0001, 0x080c, - 0xeb5d, 0x0804, 0xd64d, 0x080c, 0x6b8b, 0x1140, 0x2001, 0x1837, - 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xd45b, - 0x080c, 0x6b27, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, - 0x0006, 0x06c8, 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x66f5, - 0x002e, 0x0050, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, - 0x9686, 0x0006, 0x1904, 0xd520, 0x080c, 0xe408, 0x1120, 0x6007, - 0x000e, 0x0804, 0xd64d, 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, - 0x080c, 0x32fb, 0x080c, 0xd372, 0x004e, 0x0016, 0x9006, 0x2009, - 0x1848, 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, 0x080c, 0xe795, - 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, - 0x0001, 0x0804, 0xd64d, 0x2001, 0x0001, 0x080c, 0x66b5, 0x0156, - 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, - 0x0270, 0x080c, 0xbf40, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, - 0x0168, 0x96b4, 0xff00, 0x8637, 0x9682, 0x0004, 0x0a04, 0xd520, - 0x9682, 0x0007, 0x0a04, 0xd57c, 0x0804, 0xd520, 0x6017, 0x1900, - 0x6007, 0x0009, 0x0804, 0xd64d, 0x080c, 0x6b8b, 0x1140, 0x2001, - 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, - 0xd45b, 0x080c, 0x6b27, 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, 0xd520, 0x080c, 0xe436, 0x1138, 0x080c, 0xe32f, - 0x1120, 0x6007, 0x0010, 0x0804, 0xd64d, 0x0046, 0x6410, 0x2458, - 0xbca0, 0x0046, 0x080c, 0x32fb, 0x080c, 0xd372, 0x004e, 0x0016, + 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, 0xe795, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, - 0x004e, 0x6007, 0x0001, 0x0448, 0x080c, 0xe60d, 0x0198, 0x0016, - 0x968c, 0x00ff, 0x9186, 0x0002, 0x0160, 0x9186, 0x0003, 0x0148, - 0x001e, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0920, 0x0804, - 0xd520, 0x001e, 0x6017, 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, - 0x3432, 0x1904, 0xd883, 0x080c, 0xe98f, 0x1904, 0xd883, 0x080c, - 0xda54, 0x1904, 0xd520, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, - 0x9427, 0x080c, 0x98bc, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x9427, 0x080c, 0x98bc, 0x0cb0, 0x6007, 0x0005, 0x0c68, - 0x080c, 0xe98f, 0x1904, 0xd883, 0x080c, 0x3432, 0x1904, 0xd883, - 0x080c, 0xda54, 0x1904, 0xd520, 0x6007, 0x0020, 0x6003, 0x0001, - 0x080c, 0x9427, 0x080c, 0x98bc, 0x0005, 0x080c, 0x3432, 0x1904, - 0xd883, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x9427, 0x080c, - 0x98bc, 0x0005, 0x080c, 0xe98f, 0x1904, 0xd883, 0x080c, 0x3432, - 0x1904, 0xd883, 0x080c, 0xda54, 0x1904, 0xd520, 0x0016, 0x0026, - 0x00e6, 0x2071, 0x0260, 0x2c08, 0x2011, 0x1820, 0x2214, 0x703c, - 0x9206, 0x11e0, 0x2011, 0x181f, 0x2214, 0x7038, 0x9084, 0x00ff, - 0x9206, 0x11a0, 0x7240, 0x080c, 0xcc21, 0x0570, 0x2260, 0x6008, - 0x9086, 0xffff, 0x0120, 0x7244, 0x6008, 0x9206, 0x1528, 0x6020, - 0x9086, 0x0007, 0x1508, 0x080c, 0xaf4e, 0x04a0, 0x7244, 0x9286, - 0xffff, 0x0180, 0x2c08, 0x080c, 0xcc21, 0x01b0, 0x2260, 0x7240, - 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, 0x2214, 0x9206, - 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, 0xe75f, 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, 0xaf4e, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, - 0x9427, 0x080c, 0x98bc, 0x00ee, 0x002e, 0x001e, 0x0005, 0x2001, - 0x0001, 0x080c, 0x66b5, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, 0xbf40, 0x003e, - 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, 0xd64d, - 0x080c, 0xbbaa, 0x080c, 0x769d, 0x1190, 0x0006, 0x0026, 0x0036, - 0x080c, 0x76b7, 0x1138, 0x080c, 0x799f, 0x080c, 0x6178, 0x080c, - 0x75cc, 0x0010, 0x080c, 0x7671, 0x003e, 0x002e, 0x000e, 0x0005, - 0x080c, 0x3432, 0x1904, 0xd883, 0x080c, 0xda54, 0x1904, 0xd520, - 0x6106, 0x080c, 0xda70, 0x1120, 0x6007, 0x002b, 0x0804, 0xd64d, - 0x6007, 0x002c, 0x0804, 0xd64d, 0x080c, 0xe98f, 0x1904, 0xd883, - 0x080c, 0x3432, 0x1904, 0xd883, 0x080c, 0xda54, 0x1904, 0xd520, - 0x6106, 0x080c, 0xda75, 0x1120, 0x6007, 0x002e, 0x0804, 0xd64d, - 0x6007, 0x002f, 0x0804, 0xd64d, 0x080c, 0x3432, 0x1904, 0xd883, - 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x2058, 0xb904, 0x9184, 0x00ff, - 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, 0x9086, 0x0006, - 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xd654, 0x080c, 0x5824, - 0xd0e4, 0x0904, 0xd7ce, 0x2071, 0x026c, 0x7010, 0x603a, 0x7014, - 0x603e, 0x7108, 0x720c, 0x080c, 0x6bc9, 0x0140, 0x6010, 0x2058, - 0xb810, 0x9106, 0x1118, 0xb814, 0x9206, 0x0510, 0x080c, 0x6bc5, - 0x15b8, 0x2069, 0x1800, 0x6880, 0x9206, 0x1590, 0x687c, 0x9106, - 0x1578, 0x7210, 0x080c, 0xcc21, 0x0590, 0x080c, 0xd941, 0x0578, - 0x080c, 0xe811, 0x0560, 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, - 0x2009, 0x8020, 0x080c, 0x9420, 0x00ce, 0x00de, 0x00ee, 0x0005, - 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xcc21, 0x01c0, 0x9280, - 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, 0x7210, 0x2c08, - 0x9085, 0x0001, 0x080c, 0xe75f, 0x2c10, 0x2160, 0x0140, 0x0890, - 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, 0x1500, 0x08b8, 0x6007, - 0x0037, 0x602f, 0x0003, 0x6017, 0x1700, 0x0880, 0x6007, 0x0012, - 0x0868, 0x080c, 0x3432, 0x1904, 0xd883, 0x6010, 0x2058, 0xb804, - 0x9084, 0xff00, 0x8007, 0x9086, 0x0006, 0x1904, 0xd654, 0x00e6, - 0x00d6, 0x00c6, 0x080c, 0x5824, 0xd0e4, 0x0904, 0xd846, 0x2069, - 0x1800, 0x2071, 0x026c, 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, - 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, - 0xe75f, 0x2c10, 0x00ce, 0x05e8, 0x080c, 0xcc21, 0x05d0, 0x7108, - 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, 0x00c6, 0x0026, 0x2260, - 0x080c, 0xc80e, 0x002e, 0x00ce, 0x7118, 0x918c, 0xff00, 0x810f, - 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, 0x0118, 0x9186, 0x0007, - 0x1198, 0x9280, 0x0005, 0x2004, 0x9005, 0x0170, 0x080c, 0xd941, - 0x0904, 0xd7c7, 0x0056, 0x7510, 0x7614, 0x080c, 0xe82a, 0x005e, - 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, 0x602f, 0x0009, - 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9420, - 0x0c78, 0x6007, 0x003b, 0x602f, 0x0003, 0x6017, 0x0300, 0x6003, - 0x0001, 0x2009, 0x8020, 0x080c, 0x9420, 0x0c10, 0x6007, 0x003b, - 0x602f, 0x000b, 0x6017, 0x0000, 0x0804, 0xd79e, 0x00e6, 0x0026, - 0x080c, 0x6b8b, 0x0550, 0x080c, 0x6b27, 0x080c, 0xea00, 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, - 0x6bc9, 0x0120, 0x2011, 0x1a0b, 0x2013, 0x07d0, 0xd0ac, 0x1128, - 0x080c, 0x30c8, 0x0010, 0x080c, 0xea34, 0x002e, 0x00ee, 0x080c, - 0xaf4e, 0x0804, 0xd653, 0x080c, 0xaf4e, 0x0005, 0x2600, 0x0002, - 0xd89a, 0xd8c8, 0xd8d9, 0xd89a, 0xd89a, 0xd89c, 0xd8ea, 0xd89a, - 0xd89a, 0xd89a, 0xd8b6, 0xd89a, 0xd89a, 0xd89a, 0xd8f5, 0xd90b, - 0xd93c, 0xd89a, 0x080c, 0x0d79, 0x080c, 0xe98f, 0x1d20, 0x080c, - 0x3432, 0x1d08, 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, - 0x080c, 0x9427, 0x0005, 0x080c, 0x32fb, 0x080c, 0xd372, 0x6007, - 0x0001, 0x6003, 0x0001, 0x080c, 0x9427, 0x0005, 0x080c, 0xe98f, - 0x1950, 0x080c, 0x3432, 0x1938, 0x080c, 0xda54, 0x1d60, 0x703c, - 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, 0x9427, 0x0005, - 0x080c, 0x3432, 0x1904, 0xd883, 0x2009, 0x0041, 0x080c, 0xea3d, - 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x9427, 0x080c, 0x98bc, - 0x0005, 0x080c, 0x3432, 0x1904, 0xd883, 0x2009, 0x0042, 0x080c, - 0xea3d, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x9427, 0x080c, - 0x98bc, 0x0005, 0x080c, 0x3432, 0x1904, 0xd883, 0x2009, 0x0046, - 0x080c, 0xea3d, 0x080c, 0xaf4e, 0x0005, 0x2001, 0x1824, 0x2004, - 0x9082, 0x00e1, 0x1268, 0x080c, 0xd95e, 0x0904, 0xd883, 0x6007, - 0x004e, 0x6003, 0x0001, 0x080c, 0x9427, 0x080c, 0x98bc, 0x0005, - 0x6007, 0x0012, 0x0cb0, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, - 0x918c, 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, 0x1160, 0x7140, - 0x2001, 0x19bf, 0x2004, 0x9106, 0x11b0, 0x7144, 0x2001, 0x19c0, - 0x2004, 0x9106, 0x0190, 0x9186, 0x0002, 0x1168, 0x2011, 0x0276, - 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, - 0xbf54, 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, - 0x9427, 0x080c, 0x98bc, 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, 0x19a2, 0x2003, 0x0000, 0x080c, - 0x1066, 0x05a0, 0x2900, 0x6016, 0x7090, 0x8004, 0xa816, 0x908a, - 0x001e, 0x02d0, 0xa833, 0x001e, 0x20a9, 0x001e, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a2, 0x0016, 0x200c, - 0x0471, 0x001e, 0x81ff, 0x01b8, 0x2940, 0x080c, 0x1066, 0x01b0, - 0x2900, 0xa006, 0x2100, 0x0c18, 0xa832, 0x20a8, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a2, 0x0016, 0x200c, - 0x00b1, 0x001e, 0x0000, 0x9085, 0x0001, 0x0048, 0x2071, 0x1800, - 0x7093, 0x0000, 0x6014, 0x2048, 0x080c, 0x0fff, 0x9006, 0x012e, - 0x01de, 0x01ce, 0x00ee, 0x008e, 0x009e, 0x001e, 0x0005, 0x0006, - 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, 0xffff, 0x11b0, 0x080c, - 0x2216, 0x2099, 0x026c, 0x2001, 0x0014, 0x3518, 0x9312, 0x0108, - 0x1218, 0x23a8, 0x4003, 0x0400, 0x20a8, 0x4003, 0x22a8, 0x8108, - 0x080c, 0x2216, 0x2099, 0x0260, 0x0ca8, 0x080c, 0x2216, 0x2061, - 0x19a2, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, 0x0108, 0x1218, - 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, - 0x2216, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x19a2, 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, 0x222e, 0x20a1, 0x024c, - 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, - 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, 0x222e, - 0x20a1, 0x0240, 0x0c98, 0x080c, 0x222e, 0x2061, 0x19a5, 0x6004, - 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, - 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, 0x222e, - 0x20a1, 0x0240, 0x0c98, 0x2061, 0x19a5, 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, 0xdaea, 0x00de, 0x0005, 0x00d6, 0x080c, 0xdaf7, - 0x1520, 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, - 0x6216, 0x6824, 0x602e, 0xd1e4, 0x0130, 0x9006, 0x080c, 0xeb5d, - 0x2009, 0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920, 0x918c, 0x00ff, - 0x6824, 0x080c, 0x26a1, 0x1148, 0x2001, 0x0001, 0x080c, 0xeb5d, - 0x2110, 0x900e, 0x080c, 0x334a, 0x0018, 0x9085, 0x0001, 0x0008, - 0x9006, 0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c, 0xafbf, 0x0598, - 0x0016, 0x0026, 0x00c6, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, - 0x080c, 0x26a1, 0x1568, 0x080c, 0x6718, 0x1550, 0xbe12, 0xbd16, - 0x00ce, 0x002e, 0x001e, 0x2b00, 0x6012, 0x080c, 0xe98f, 0x11c8, - 0x080c, 0x3432, 0x11b0, 0x080c, 0xda54, 0x0500, 0x2001, 0x0007, - 0x080c, 0x66c9, 0x2001, 0x0007, 0x080c, 0x66f5, 0x6017, 0x0000, - 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9427, - 0x0010, 0x080c, 0xaf4e, 0x9085, 0x0001, 0x00ce, 0x00be, 0x0005, - 0x080c, 0xaf4e, 0x00ce, 0x002e, 0x001e, 0x0ca8, 0x080c, 0xaf4e, - 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, - 0x0d79, 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, 0x0040, 0x1a04, - 0xdc4c, 0x0402, 0x91b6, 0x0027, 0x0190, 0x9186, 0x0015, 0x0118, - 0x9186, 0x0016, 0x1140, 0x080c, 0xad4d, 0x0120, 0x9086, 0x0002, - 0x0904, 0xb983, 0x0005, 0x91b6, 0x0014, 0x190c, 0x0d79, 0x2001, - 0x0007, 0x080c, 0x66f5, 0x080c, 0x97f6, 0x080c, 0xaf89, 0x080c, - 0x98bc, 0x0005, 0xdb82, 0xdb84, 0xdb82, 0xdb82, 0xdb82, 0xdb84, - 0xdb91, 0xdc49, 0xdbd3, 0xdc49, 0xdbf7, 0xdc49, 0xdb91, 0xdc49, - 0xdc41, 0xdc49, 0xdc41, 0xdc49, 0xdc49, 0xdb82, 0xdb82, 0xdb82, - 0xdb82, 0xdb82, 0xdb82, 0xdb82, 0xdb82, 0xdb82, 0xdb82, 0xdb82, - 0xdb84, 0xdb82, 0xdc49, 0xdb82, 0xdb82, 0xdc49, 0xdb82, 0xdc46, - 0xdc49, 0xdb82, 0xdb82, 0xdb82, 0xdb82, 0xdc49, 0xdc49, 0xdb82, - 0xdc49, 0xdc49, 0xdb82, 0xdb8c, 0xdb82, 0xdb82, 0xdb82, 0xdb82, - 0xdc45, 0xdc49, 0xdb82, 0xdb82, 0xdc49, 0xdc49, 0xdb82, 0xdb82, - 0xdb82, 0xdb82, 0x080c, 0x0d79, 0x080c, 0xd375, 0x6003, 0x0002, - 0x080c, 0x98bc, 0x0804, 0xdc4b, 0x9006, 0x080c, 0x66b5, 0x0804, - 0xdc49, 0x080c, 0x6bc5, 0x1904, 0xdc49, 0x9006, 0x080c, 0x66b5, - 0x6010, 0x2058, 0xb810, 0x9086, 0x00ff, 0x1140, 0x00f6, 0x2079, - 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x00b8, 0x6010, 0x2058, - 0xb884, 0x9005, 0x0904, 0xdc49, 0x080c, 0x3463, 0x1904, 0xdc49, - 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1138, 0x00f6, 0x2079, - 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x2001, 0x0002, 0x080c, - 0x66c9, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, - 0x9427, 0x080c, 0x98bc, 0x6110, 0x2158, 0x2009, 0x0001, 0x080c, - 0x883a, 0x0804, 0xdc4b, 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, - 0x8637, 0x9686, 0x0006, 0x0148, 0x9686, 0x0004, 0x0130, 0x080c, - 0x90be, 0x2001, 0x0004, 0x080c, 0x66f5, 0x080c, 0xebac, 0x0904, - 0xdc49, 0x2001, 0x0004, 0x080c, 0x66c9, 0x6023, 0x0001, 0x6003, - 0x0001, 0x6007, 0x0003, 0x080c, 0x9427, 0x0804, 0xdc4b, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0x6010, - 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4ddf, 0x004e, 0x003e, - 0x2001, 0x0006, 0x080c, 0xdc65, 0x6610, 0x2658, 0xbe04, 0x0066, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, 0x0180, 0x2001, - 0x0006, 0x080c, 0x66f5, 0x9284, 0x00ff, 0x908e, 0x0007, 0x0118, - 0x908e, 0x0004, 0x1120, 0x2001, 0x0006, 0x080c, 0x66c9, 0x080c, - 0x6bc5, 0x11f8, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x01d0, 0xbe04, - 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6, 0x2079, 0x1800, - 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x0804, 0xdbbd, 0x2001, 0x0004, - 0x0030, 0x2001, 0x0006, 0x0409, 0x0020, 0x0018, 0x0010, 0x080c, - 0x66f5, 0x080c, 0xaf4e, 0x0005, 0x2600, 0x0002, 0xdc60, 0xdc60, - 0xdc60, 0xdc60, 0xdc60, 0xdc62, 0xdc60, 0xdc62, 0xdc60, 0xdc60, - 0xdc62, 0xdc60, 0xdc60, 0xdc60, 0xdc62, 0xdc62, 0xdc62, 0xdc62, - 0x080c, 0x0d79, 0x080c, 0xaf4e, 0x0005, 0x0016, 0x00b6, 0x00d6, - 0x6110, 0x2158, 0xb900, 0xd184, 0x0138, 0x080c, 0x66c9, 0x9006, - 0x080c, 0x66b5, 0x080c, 0x332a, 0x00de, 0x00be, 0x001e, 0x0005, - 0x6610, 0x2658, 0xb804, 0x9084, 0xff00, 0x8007, 0x90b2, 0x000c, - 0x1a0c, 0x0d79, 0x91b6, 0x0015, 0x1110, 0x003b, 0x0028, 0x91b6, - 0x0016, 0x190c, 0x0d79, 0x006b, 0x0005, 0xba25, 0xba25, 0xba25, - 0xba25, 0xdcfa, 0xba25, 0xdce4, 0xdca5, 0xba25, 0xba25, 0xba25, - 0xba25, 0xba25, 0xba25, 0xba25, 0xba25, 0xdcfa, 0xba25, 0xdce4, - 0xdceb, 0xba25, 0xba25, 0xba25, 0xba25, 0x00f6, 0x080c, 0x6bc5, - 0x11d8, 0x080c, 0xd35d, 0x11c0, 0x6010, 0x905d, 0x01a8, 0xb884, - 0x9005, 0x0190, 0x9006, 0x080c, 0x66b5, 0x2001, 0x0002, 0x080c, - 0x66c9, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, - 0x9427, 0x080c, 0x98bc, 0x00f0, 0x2011, 0x0263, 0x2204, 0x8211, - 0x220c, 0x080c, 0x26a1, 0x11b0, 0x080c, 0x6783, 0x0118, 0x080c, - 0xaf4e, 0x0080, 0xb810, 0x0006, 0xb814, 0x0006, 0xb884, 0x0006, - 0x080c, 0x6192, 0x000e, 0xb886, 0x000e, 0xb816, 0x000e, 0xb812, - 0x080c, 0xaf4e, 0x00fe, 0x0005, 0x6604, 0x96b6, 0x001e, 0x1110, - 0x080c, 0xaf4e, 0x0005, 0x080c, 0xbdb4, 0x1148, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x9427, 0x080c, 0x98bc, 0x0010, 0x080c, - 0xaf4e, 0x0005, 0x0804, 0xaf4e, 0x6004, 0x908a, 0x0053, 0x1a0c, - 0x0d79, 0x080c, 0x97f6, 0x080c, 0xaf89, 0x0005, 0x9182, 0x0040, - 0x0002, 0xdd1d, 0xdd1d, 0xdd1d, 0xdd1d, 0xdd1f, 0xdd1d, 0xdd1d, - 0xdd1d, 0xdd1d, 0xdd1d, 0xdd1d, 0xdd1d, 0xdd1d, 0xdd1d, 0xdd1d, - 0xdd1d, 0xdd1d, 0xdd1d, 0xdd1d, 0xdd1d, 0x080c, 0x0d79, 0x0096, - 0x00b6, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, 0x6210, 0x2258, - 0xb8bc, 0x9005, 0x11b0, 0x6007, 0x0044, 0x2071, 0x0260, 0x7444, - 0x94a4, 0xff00, 0x0904, 0xdd86, 0x080c, 0xeb51, 0x1170, 0x9486, - 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x8add, - 0x0020, 0x9026, 0x080c, 0xe9d4, 0x0c30, 0x080c, 0x104d, 0x090c, - 0x0d79, 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, 0x6f11, 0x001e, 0x080c, 0xeb51, 0x1904, - 0xdde6, 0x9486, 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0xe701, - 0x0804, 0xdde6, 0x9486, 0x0200, 0x1120, 0x080c, 0xe68c, 0x0804, - 0xdde6, 0x9486, 0x0400, 0x0120, 0x9486, 0x1000, 0x1904, 0xdde6, - 0x2019, 0x0002, 0x080c, 0xe6ab, 0x0804, 0xdde6, 0x2069, 0x1a74, - 0x6a00, 0xd284, 0x0904, 0xde50, 0x9284, 0x0300, 0x1904, 0xde49, - 0x6804, 0x9005, 0x0904, 0xde31, 0x2d78, 0x6003, 0x0007, 0x080c, - 0x1066, 0x0904, 0xddf2, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, - 0x7806, 0x6017, 0x0000, 0x2001, 0x180f, 0x2004, 0xd084, 0x1904, - 0xde54, 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, 0xddee, 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, 0x6f14, 0x002e, 0x004e, - 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e, 0x0005, 0x0000, 0x0080, - 0x0040, 0x0000, 0x2001, 0x1810, 0x2004, 0xd084, 0x0120, 0x080c, - 0x104d, 0x1904, 0xdd9b, 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, - 0x0041, 0x2009, 0xa022, 0x080c, 0x9420, 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, 0x9420, - 0x0828, 0x6868, 0x602e, 0x686c, 0x6032, 0x6017, 0xf200, 0x6003, - 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9420, 0x0804, - 0xdde6, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, - 0x080c, 0x4c28, 0x6017, 0xf300, 0x0010, 0x6017, 0xf100, 0x6003, - 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9420, 0x0804, - 0xdde6, 0x6017, 0xf500, 0x0c98, 0x6017, 0xf600, 0x0804, 0xde06, - 0x6017, 0xf200, 0x0804, 0xde06, 0xa867, 0x0146, 0xa86b, 0x0000, - 0x6008, 0xa886, 0x2c00, 0xa87a, 0x7044, 0x9084, 0x0003, 0x9080, - 0xddee, 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, 0x0d79, 0x8210, 0x821c, 0x2001, 0x026c, - 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0029, 0x20a0, 0x2011, - 0xded0, 0x2041, 0x0001, 0x223d, 0x9784, 0x00ff, 0x9322, 0x1208, - 0x2300, 0x20a8, 0x4003, 0x931a, 0x0530, 0x8210, 0xd7fc, 0x1130, - 0x8d68, 0x2d0a, 0x2001, 0x0260, 0x2098, 0x0c68, 0x2950, 0x080c, - 0x1066, 0x0170, 0x2900, 0xb002, 0xa867, 0x0147, 0xa86b, 0x0000, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x8840, 0x08d8, - 0x2548, 0xa800, 0x902d, 0x0118, 0x080c, 0x107f, 0x0cc8, 0x080c, - 0x107f, 0x0804, 0xddf2, 0x2548, 0x8847, 0x9885, 0x0046, 0xa866, - 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, 0xe738, 0x0804, 0xdde6, - 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, 0x0008, 0x8016, 0x000a, - 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0057, 0x1a0c, - 0x0d79, 0x9082, 0x0040, 0x0a0c, 0x0d79, 0x2008, 0x0804, 0xdf5c, - 0x9186, 0x0051, 0x0108, 0x0040, 0x080c, 0xad4d, 0x01e8, 0x9086, - 0x0002, 0x0904, 0xdfa4, 0x00c0, 0x9186, 0x0027, 0x0180, 0x9186, - 0x0048, 0x0128, 0x9186, 0x0014, 0x0150, 0x190c, 0x0d79, 0x080c, - 0xad4d, 0x0150, 0x9086, 0x0004, 0x0904, 0xe043, 0x0028, 0x6004, - 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, 0xb009, 0x0005, 0xdf23, - 0xdf25, 0xdf25, 0xdf4c, 0xdf23, 0xdf23, 0xdf23, 0xdf23, 0xdf23, - 0xdf23, 0xdf23, 0xdf23, 0xdf23, 0xdf23, 0xdf23, 0xdf23, 0xdf23, - 0xdf23, 0xdf23, 0xdf23, 0x080c, 0x0d79, 0x080c, 0x97f6, 0x080c, - 0x98bc, 0x0036, 0x0096, 0x6014, 0x904d, 0x01d8, 0x080c, 0xcc33, - 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xe738, 0x6017, 0x0000, - 0x6018, 0x9005, 0x1120, 0x2001, 0x1988, 0x2004, 0x601a, 0x6003, - 0x0007, 0x009e, 0x003e, 0x0005, 0x0096, 0x080c, 0x97f6, 0x080c, - 0x98bc, 0x080c, 0xcc33, 0x0120, 0x6014, 0x2048, 0x080c, 0x107f, - 0x080c, 0xaf89, 0x009e, 0x0005, 0x0002, 0xdf71, 0xdf86, 0xdf73, - 0xdf9b, 0xdf71, 0xdf71, 0xdf71, 0xdf71, 0xdf71, 0xdf71, 0xdf71, - 0xdf71, 0xdf71, 0xdf71, 0xdf71, 0xdf71, 0xdf71, 0xdf71, 0xdf71, - 0xdf71, 0x080c, 0x0d79, 0x0096, 0x6014, 0x2048, 0xa87c, 0xd0b4, - 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0xafec, 0x0010, - 0x6003, 0x0004, 0x080c, 0x98bc, 0x009e, 0x0005, 0x080c, 0xcc33, - 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e, 0xd1ec, 0x1138, - 0x080c, 0x8ab2, 0x080c, 0xaf4e, 0x080c, 0x98bc, 0x0005, 0x080c, - 0xe998, 0x0db0, 0x0cc8, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, - 0xa022, 0x080c, 0x9420, 0x0005, 0x9182, 0x0040, 0x0002, 0xdfbb, - 0xdfbd, 0xdfbb, 0xdfbb, 0xdfbb, 0xdfbb, 0xdfbb, 0xdfbb, 0xdfbb, - 0xdfbb, 0xdfbb, 0xdfbb, 0xdfbb, 0xdfbb, 0xdfbb, 0xdfbb, 0xdfbb, - 0xdfbe, 0xdfbb, 0xdfbb, 0x080c, 0x0d79, 0x0005, 0x00d6, 0x080c, - 0x8ab2, 0x00de, 0x080c, 0xe9f0, 0x080c, 0xaf4e, 0x0005, 0x9182, - 0x0040, 0x0002, 0xdfde, 0xdfde, 0xdfde, 0xdfde, 0xdfde, 0xdfde, - 0xdfde, 0xdfde, 0xdfde, 0xdfe0, 0xe00b, 0xdfde, 0xdfde, 0xdfde, - 0xdfde, 0xe00b, 0xdfde, 0xdfde, 0xdfde, 0xdfde, 0x080c, 0x0d79, - 0x6014, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x908c, 0x0003, - 0x918e, 0x0002, 0x0180, 0x6144, 0xd1e4, 0x1168, 0x2009, 0x0041, - 0x009e, 0x0804, 0xe0cb, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, - 0x8ab2, 0x009e, 0x0005, 0x6014, 0x2048, 0xa97c, 0xd1ec, 0x1130, - 0x080c, 0x8ab2, 0x080c, 0xaf4e, 0x009e, 0x0005, 0x080c, 0xe998, - 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, - 0x0036, 0x080c, 0x9851, 0x080c, 0x98bc, 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, 0xe738, 0x6018, 0x9005, 0x1128, 0x2001, - 0x1988, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, 0x6003, 0x0007, - 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, 0xe05a, 0xe05a, - 0xe05a, 0xe05a, 0xe05a, 0xe05a, 0xe05a, 0xe05a, 0xe05c, 0xe05a, - 0xe05a, 0xe05a, 0xe05a, 0xe05a, 0xe05a, 0xe05a, 0xe05a, 0xe05a, - 0xe05a, 0xe0a7, 0x080c, 0x0d79, 0x6014, 0x0096, 0x2048, 0xa834, - 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1190, - 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, 0x2009, 0x0041, 0x009e, - 0x0804, 0xe0cb, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x8ab2, - 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, - 0x8ab4, 0x009e, 0x0005, 0x6003, 0x0002, 0x009e, 0x0005, 0x6024, - 0xd0f4, 0x0128, 0x080c, 0x16a4, 0x1904, 0xe05c, 0x0005, 0x6014, - 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, 0x9105, 0x1120, 0x080c, - 0x16a4, 0x1904, 0xe05c, 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, 0x0d79, 0x6024, 0xd0dc, - 0x090c, 0x0d79, 0x0005, 0xe0ef, 0xe0fb, 0xe107, 0xe113, 0xe0ef, - 0xe0ef, 0xe0ef, 0xe0ef, 0xe0f6, 0xe0f1, 0xe0f1, 0xe0ef, 0xe0ef, - 0xe0ef, 0xe0ef, 0xe0f1, 0xe0ef, 0xe0f1, 0xe0ef, 0xe0f6, 0x080c, - 0x0d79, 0x6024, 0xd0dc, 0x090c, 0x0d79, 0x0005, 0x6014, 0x9005, - 0x190c, 0x0d79, 0x0005, 0x6003, 0x0001, 0x6106, 0x0126, 0x2091, - 0x8000, 0x2009, 0xa022, 0x080c, 0x9402, 0x012e, 0x0005, 0x6003, - 0x0004, 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0xa001, 0x080c, - 0x9420, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x080c, 0x1c8c, - 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, 0x9467, - 0x012e, 0x0005, 0x6144, 0x918d, 0xa032, 0x0cb8, 0x0126, 0x2091, - 0x8000, 0x0036, 0x0096, 0x9182, 0x0040, 0x0023, 0x009e, 0x003e, - 0x012e, 0x0005, 0xe15e, 0xe160, 0xe175, 0xe18f, 0xe15e, 0xe15e, - 0xe15e, 0xe15e, 0xe15e, 0xe15e, 0xe15e, 0xe15e, 0xe15e, 0xe15e, - 0xe15e, 0xe15e, 0xe15e, 0xe15e, 0xe15e, 0xe15e, 0x080c, 0x0d79, - 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0510, 0x909c, 0x0003, 0x939e, - 0x0003, 0x01e8, 0x6003, 0x0001, 0x6106, 0x0126, 0x2091, 0x8000, - 0x2009, 0xa022, 0x080c, 0x9420, 0x0470, 0x6014, 0x2048, 0xa87c, - 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, 0x0140, 0x6003, - 0x0001, 0x6106, 0x2009, 0xa001, 0x080c, 0x9420, 0x00e0, 0x901e, - 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xe738, 0x00a0, 0x6014, - 0x2048, 0xa87c, 0xd0fc, 0x0d98, 0x909c, 0x0003, 0x939e, 0x0003, - 0x0d70, 0x6003, 0x0003, 0x6106, 0x080c, 0x1c8c, 0x6144, 0x918d, - 0xa035, 0x080c, 0x9467, 0x0005, 0x080c, 0x97f6, 0x6114, 0x81ff, - 0x0158, 0x0096, 0x2148, 0x080c, 0xeaee, 0x0036, 0x2019, 0x0029, - 0x080c, 0xe738, 0x003e, 0x009e, 0x080c, 0xaf89, 0x080c, 0x98bc, - 0x0005, 0x080c, 0x9851, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, - 0x080c, 0xeaee, 0x0036, 0x2019, 0x0029, 0x080c, 0xe738, 0x003e, - 0x009e, 0x080c, 0xaf89, 0x0005, 0x9182, 0x0085, 0x0002, 0xe1de, - 0xe1dc, 0xe1dc, 0xe1ea, 0xe1dc, 0xe1dc, 0xe1dc, 0xe1dc, 0xe1dc, - 0xe1dc, 0xe1dc, 0xe1dc, 0xe1dc, 0x080c, 0x0d79, 0x6003, 0x000b, - 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0x8020, 0x080c, 0x9420, - 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, 0xe98f, 0x0118, 0x080c, - 0xaf4e, 0x0440, 0x2071, 0x0260, 0x7224, 0x6216, 0x2001, 0x180e, - 0x2004, 0xd0e4, 0x0150, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, - 0x2c00, 0x2011, 0x014e, 0x080c, 0xb277, 0x7220, 0x080c, 0xe57d, - 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, - 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, 0x2009, 0x8020, - 0x080c, 0x9420, 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, - 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d79, 0x908a, 0x0092, 0x1a0c, - 0x0d79, 0x9082, 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, - 0x0014, 0x0118, 0x080c, 0xb009, 0x0050, 0x2001, 0x0007, 0x080c, - 0x66f5, 0x080c, 0x97f6, 0x080c, 0xaf89, 0x080c, 0x98bc, 0x0005, - 0xe24d, 0xe24f, 0xe24f, 0xe24d, 0xe24d, 0xe24d, 0xe24d, 0xe24d, - 0xe24d, 0xe24d, 0xe24d, 0xe24d, 0xe24d, 0x080c, 0x0d79, 0x080c, - 0xaf89, 0x080c, 0x98bc, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0d79, - 0x9182, 0x0092, 0x1a0c, 0x0d79, 0x9182, 0x0085, 0x0002, 0xe26c, - 0xe26c, 0xe26c, 0xe26e, 0xe26c, 0xe26c, 0xe26c, 0xe26c, 0xe26c, - 0xe26c, 0xe26c, 0xe26c, 0xe26c, 0x080c, 0x0d79, 0x0005, 0x9186, - 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, - 0x080c, 0xb009, 0x0020, 0x080c, 0x97f6, 0x080c, 0xaf89, 0x0005, - 0x0036, 0x080c, 0xe9f0, 0x604b, 0x0000, 0x2019, 0x000b, 0x0031, - 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, - 0x2091, 0x8000, 0x080c, 0xaaf7, 0x0106, 0x0086, 0x2c40, 0x0096, - 0x904e, 0x080c, 0xa462, 0x009e, 0x008e, 0x1558, 0x0076, 0x2c38, - 0x080c, 0xa50d, 0x007e, 0x1528, 0x6000, 0x9086, 0x0000, 0x0508, + 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, 0xe9f0, 0x080c, 0xd375, 0x080c, 0x1af0, 0x6023, 0x0007, - 0x6014, 0x2048, 0x080c, 0xcc33, 0x0110, 0x080c, 0xe738, 0x009e, - 0x9006, 0x6046, 0x6016, 0x080c, 0xe9f0, 0x6023, 0x0007, 0x080c, - 0xd375, 0x010e, 0x090c, 0xab13, 0x003e, 0x012e, 0x0005, 0x00f6, + 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, 0x26a1, 0x1904, 0xe329, 0x0016, 0x00c6, 0x080c, 0x6783, - 0x1904, 0xe327, 0x001e, 0x00c6, 0x080c, 0xd35d, 0x1130, 0xb884, - 0x9005, 0x0118, 0x080c, 0x3463, 0x0148, 0x2b10, 0x2160, 0x6010, - 0x0006, 0x6212, 0x080c, 0xd364, 0x000e, 0x6012, 0x00ce, 0x002e, - 0x0026, 0x0016, 0x080c, 0xaaf7, 0x2019, 0x0029, 0x080c, 0xa5dd, - 0x080c, 0x95b9, 0x0076, 0x903e, 0x080c, 0x9476, 0x007e, 0x001e, - 0x0076, 0x903e, 0x080c, 0xe465, 0x007e, 0x080c, 0xab13, 0x0026, + 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, 0x33c6, 0x002e, 0xbc84, 0x001e, - 0x080c, 0x6192, 0xbe12, 0xbd16, 0xbc86, 0x9006, 0x0010, 0x00ce, + 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, 0xe388, 0x2069, 0x0260, 0x6944, 0x9182, 0x0100, 0x06e0, - 0x6940, 0x9184, 0x8000, 0x0904, 0xe385, 0x2001, 0x197d, 0x2004, + 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, 0xeb56, + 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, @@ -7067,125 +7162,125 @@ unsigned short risc_code01[] = { 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, 0x6792, 0x0804, 0xe3f4, + 0x0138, 0x9286, 0x0004, 0x0120, 0x080c, 0x67c3, 0x0804, 0xe6ec, 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, - 0x080c, 0xbf54, 0x009e, 0x15c8, 0x2011, 0x027a, 0x20a9, 0x0004, - 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xbf54, 0x009e, 0x1568, + 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, 0xe795, 0xb800, 0xc0e5, - 0xb802, 0x080c, 0xaaf7, 0x2019, 0x0029, 0x080c, 0x95b9, 0x0076, - 0x2039, 0x0000, 0x080c, 0x9476, 0x2c08, 0x080c, 0xe465, 0x007e, - 0x080c, 0xab13, 0x2001, 0x0007, 0x080c, 0x66f5, 0x2001, 0x0007, - 0x080c, 0x66c9, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, + 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, 0x26a1, 0x11d0, 0x080c, 0x6783, 0x11b8, + 0x7930, 0x7834, 0x080c, 0x268c, 0x11d0, 0x080c, 0x67b4, 0x11b8, 0x2011, 0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, - 0x080c, 0xbf54, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004, - 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xbf54, 0x009e, 0x015e, + 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, 0x26a1, 0x11d0, 0x080c, 0x6783, 0x11b8, 0x2011, + 0x220c, 0x080c, 0x268c, 0x11d0, 0x080c, 0x67b4, 0x11b8, 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, - 0xbf54, 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x0006, 0x080c, 0xbf54, 0x009e, 0x015e, 0x003e, + 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, 0xab55, 0x0106, 0x190c, 0xaaf7, 0x2740, 0x2029, 0x19f5, - 0x252c, 0x2021, 0x19fc, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, - 0x7654, 0x7074, 0x81ff, 0x0150, 0x0006, 0x9186, 0x1b3a, 0x000e, - 0x0128, 0x8001, 0x9602, 0x1a04, 0xe50b, 0x0018, 0x9606, 0x0904, - 0xe50b, 0x080c, 0x8d87, 0x0904, 0xe502, 0x2100, 0x9c06, 0x0904, - 0xe502, 0x6720, 0x9786, 0x0007, 0x0904, 0xe502, 0x080c, 0xe7d6, - 0x1904, 0xe502, 0x080c, 0xeb74, 0x0904, 0xe502, 0x080c, 0xe7c6, - 0x0904, 0xe502, 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, 0x3463, - 0x0904, 0xe54d, 0x6004, 0x9086, 0x0000, 0x1904, 0xe54d, 0x9786, - 0x0004, 0x0904, 0xe54d, 0x2500, 0x9c06, 0x0904, 0xe502, 0x2400, - 0x9c06, 0x0904, 0xe502, 0x88ff, 0x0118, 0x605c, 0x9906, 0x15d0, + 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, 0x1af0, 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xce4a, - 0x1130, 0x080c, 0xb93c, 0x009e, 0x080c, 0xaf89, 0x0418, 0x6014, - 0x2048, 0x080c, 0xcc33, 0x01d8, 0x9786, 0x0003, 0x1588, 0xa867, + 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, - 0x0fff, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0xeaee, 0x0016, - 0x080c, 0xcf38, 0x080c, 0x6f05, 0x001e, 0x080c, 0xce24, 0x009e, - 0x080c, 0xaf89, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, - 0x1210, 0x0804, 0xe47e, 0x010e, 0x190c, 0xab13, 0x012e, 0x002e, + 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, 0xeaee, - 0x080c, 0xe738, 0x08e0, 0x009e, 0x08e8, 0x9786, 0x0009, 0x11f8, + 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, 0x9851, 0x0096, 0x6114, 0x2148, 0x080c, 0xcc33, 0x0118, - 0x6010, 0x080c, 0x6f11, 0x009e, 0x00c6, 0x080c, 0xaf4e, 0x00ce, - 0x0036, 0x080c, 0x98bc, 0x003e, 0x009e, 0x0804, 0xe502, 0x9786, - 0x000a, 0x0904, 0xe4f2, 0x0804, 0xe4e7, 0x81ff, 0x0904, 0xe502, + 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, 0xe502, 0x6000, 0x9086, 0x0002, - 0x1904, 0xe502, 0x080c, 0xce39, 0x0138, 0x080c, 0xce4a, 0x1904, - 0xe502, 0x080c, 0xb93c, 0x0038, 0x080c, 0x332a, 0x080c, 0xce4a, - 0x1110, 0x080c, 0xb93c, 0x080c, 0xaf89, 0x0804, 0xe502, 0xa864, + 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, 0xe75f, 0x001e, 0x0120, 0x6020, - 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xe59c, 0xe59c, - 0xe59c, 0xe59c, 0xe59c, 0xe59c, 0xe59e, 0xe59c, 0xe59c, 0xe59c, - 0xe5c7, 0xaf89, 0xaf89, 0xe59c, 0x9006, 0x0005, 0x0036, 0x0046, + 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, 0xe795, 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, - 0xe28e, 0x003e, 0x9085, 0x0001, 0x0005, 0x0096, 0x080c, 0xcc33, - 0x0140, 0x6014, 0x904d, 0x080c, 0xc81b, 0x687b, 0x0005, 0x080c, - 0x6f11, 0x009e, 0x080c, 0xaf89, 0x9085, 0x0001, 0x0005, 0x0019, - 0x9085, 0x0001, 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d79, - 0x000b, 0x0005, 0xe5e2, 0xe5e2, 0xe5f9, 0xe5e9, 0xe608, 0xe5e2, - 0xe5e2, 0xe5e4, 0xe5e2, 0xe5e2, 0xe5e2, 0xe5e2, 0xe5e2, 0xe5e2, - 0xe5e2, 0xe5e2, 0x080c, 0x0d79, 0x080c, 0xaf89, 0x9085, 0x0001, - 0x0005, 0x0036, 0x00e6, 0x2071, 0x19e9, 0x704c, 0x9c06, 0x1128, - 0x2019, 0x0001, 0x080c, 0xa391, 0x0010, 0x080c, 0xa59c, 0x00ee, + 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, - 0x6f11, 0x080c, 0xaf89, 0x00de, 0x009e, 0x9085, 0x0001, 0x0005, - 0x601c, 0xd084, 0x190c, 0x1af0, 0x0c60, 0x2001, 0x0001, 0x080c, - 0x66b5, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, - 0x1805, 0x2011, 0x0276, 0x080c, 0xbf40, 0x003e, 0x002e, 0x001e, + 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, 0xe67f, 0x2071, 0x1800, 0x7654, - 0x7074, 0x8001, 0x9602, 0x1a04, 0xe67f, 0x88ff, 0x0120, 0x2800, - 0x9c06, 0x15a0, 0x2078, 0x080c, 0xe7c6, 0x0580, 0x2400, 0x9c06, + 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, 0xe9f0, 0x080c, 0xd375, 0x080c, 0x1af0, 0x6023, 0x0007, - 0x6014, 0x2048, 0x080c, 0xcc33, 0x0120, 0x0046, 0x080c, 0xe738, - 0x004e, 0x009e, 0x080c, 0xaf89, 0x88ff, 0x1198, 0x9ce0, 0x001c, - 0x2001, 0x181a, 0x2004, 0x9c02, 0x1210, 0x0804, 0xe632, 0x9006, + 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, 0xaaf7, 0x00b6, 0x0076, + 0x0005, 0x98c5, 0x0001, 0x0ca0, 0x080c, 0xacfc, 0x00b6, 0x0076, 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, - 0x6210, 0x2258, 0x0096, 0x904e, 0x080c, 0xa462, 0x009e, 0x008e, - 0x903e, 0x080c, 0xa50d, 0x080c, 0xe623, 0x005e, 0x007e, 0x00be, - 0x080c, 0xab13, 0x0005, 0x080c, 0xaaf7, 0x00b6, 0x0046, 0x0056, + 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, 0x6783, 0x1180, 0x0056, 0x0086, 0x9046, - 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, 0xa462, 0x009e, - 0x008e, 0x903e, 0x080c, 0xa50d, 0x005e, 0x003e, 0x001e, 0x8108, - 0x1f04, 0xe6b8, 0x0036, 0x2508, 0x2029, 0x0003, 0x080c, 0xe623, + 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, - 0xab13, 0x0005, 0x080c, 0xaaf7, 0x00b6, 0x0076, 0x0056, 0x6210, + 0xad18, 0x0005, 0x080c, 0xacfc, 0x00b6, 0x0076, 0x0056, 0x6210, 0x2258, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, - 0x904e, 0x080c, 0xa462, 0x009e, 0x008e, 0x903e, 0x080c, 0xa50d, - 0x2c20, 0x080c, 0xe623, 0x005e, 0x007e, 0x00be, 0x080c, 0xab13, - 0x0005, 0x080c, 0xaaf7, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, + 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, - 0x6783, 0x1190, 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, - 0x080c, 0xe9d4, 0x004e, 0x0096, 0x904e, 0x080c, 0xa462, 0x009e, - 0x008e, 0x903e, 0x080c, 0xa50d, 0x003e, 0x001e, 0x8108, 0x1f04, - 0xe70d, 0x0036, 0x2029, 0x0002, 0x080c, 0xe623, 0x003e, 0x015e, - 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x080c, 0xab13, 0x0005, - 0x0016, 0x00f6, 0x080c, 0xcc31, 0x0198, 0xa864, 0x9084, 0x00ff, + 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, 0x6f11, 0x2f48, 0x0cb0, 0xab82, 0x080c, 0x6f11, + 0xab82, 0x080c, 0x7012, 0x2f48, 0x0cb0, 0xab82, 0x080c, 0x7012, 0x00fe, 0x001e, 0x0005, 0xa800, 0x907d, 0x0130, 0xa803, 0x0000, - 0x080c, 0x6f11, 0x2f48, 0x0cb8, 0x080c, 0x6f11, 0x0c88, 0x00e6, + 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, @@ -7193,157 +7288,157 @@ unsigned short risc_code01[] = { 0x0140, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1220, 0x0c20, 0x9085, 0x0001, 0x0008, 0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x631c, 0xd3c4, 0x1d68, 0x0c30, 0x0096, 0x0006, 0x080c, - 0x104d, 0x000e, 0x090c, 0x0d79, 0xaae2, 0xa867, 0x010d, 0xa88e, - 0x0026, 0x2010, 0x080c, 0xcc21, 0x2001, 0x0000, 0x0120, 0x2200, + 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, 0x198f, + 0xa8e3, 0xffff, 0xa986, 0xac76, 0xa87f, 0x0000, 0x2001, 0x198e, 0x2004, 0xa882, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6f11, 0x012e, 0x009e, 0x0005, 0x6700, 0x9786, + 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, 0x1988, 0x2004, - 0x601a, 0x2009, 0x8020, 0x080c, 0x9420, 0x001e, 0x0005, 0xa001, + 0x0085, 0x6003, 0x000b, 0x6023, 0x0005, 0x2001, 0x1987, 0x2004, + 0x601a, 0x2009, 0x8020, 0x080c, 0x9617, 0x001e, 0x0005, 0xa001, 0xa001, 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, - 0xcf7f, 0x0030, 0x080c, 0xe9f0, 0x080c, 0x8ab2, 0x080c, 0xaf4e, - 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xe825, - 0xe825, 0xe825, 0xe827, 0xe825, 0xe827, 0xe827, 0xe825, 0xe827, - 0xe825, 0xe825, 0xe825, 0xe825, 0xe825, 0x9006, 0x0005, 0x9085, + 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, - 0xe83e, 0xe83e, 0xe83e, 0xe83e, 0xe83e, 0xe83e, 0xe84b, 0xe83e, - 0xe83e, 0xe83e, 0xe83e, 0xe83e, 0xe83e, 0xe83e, 0x6007, 0x003b, + 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, 0x9420, 0x0005, 0x0096, 0x00c6, 0x2260, 0x080c, 0xe9f0, + 0x080c, 0x9617, 0x0005, 0x0096, 0x00c6, 0x2260, 0x080c, 0xece1, 0x604b, 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, 0x603b, 0x0000, - 0x00ce, 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, 0xe8a4, 0x6814, + 0x00ce, 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, 0xeb9c, 0x6814, 0x9005, 0x0138, 0x2048, 0xa87c, 0xd0fc, 0x1118, 0x00de, 0x009e, 0x08a8, 0x6007, 0x003a, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, - 0x9420, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, 0xe91b, - 0x6014, 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, 0x190c, 0x0d79, - 0x0804, 0xe91b, 0x2048, 0x080c, 0xcc33, 0x1130, 0x0028, 0x2048, + 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, 0xe0cb, 0x0804, 0xe91b, - 0x2009, 0x0041, 0x0804, 0xe915, 0x9186, 0x0005, 0x15a0, 0x6814, - 0x2048, 0xa87c, 0xd0bc, 0x1120, 0x00de, 0x009e, 0x0804, 0xe83e, - 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x0d79, 0x0804, 0xe85f, 0x6007, - 0x003a, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9420, 0x00c6, + 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, - 0xe91b, 0x6814, 0x2048, 0xa97c, 0xc1f4, 0xc1dc, 0xa97e, 0xa980, - 0xc1fc, 0xc1bc, 0xa982, 0x00f6, 0x2c78, 0x080c, 0x17a1, 0x00fe, - 0x2009, 0x0042, 0x04d0, 0x0036, 0x080c, 0x104d, 0x090c, 0x0d79, + 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, 0x6f11, 0x2019, 0x0045, 0x6008, 0x2068, - 0x080c, 0xe28e, 0x2d00, 0x600a, 0x6023, 0x0006, 0x6003, 0x0007, - 0x901e, 0x631a, 0x634a, 0x003e, 0x0038, 0x604b, 0x0000, 0x6003, - 0x0007, 0x080c, 0xe0cb, 0x00ce, 0x00de, 0x009e, 0x0005, 0x9186, - 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, - 0x0027, 0x1178, 0x080c, 0x97f6, 0x0036, 0x0096, 0x6014, 0x2048, - 0x2019, 0x0004, 0x080c, 0xe738, 0x009e, 0x003e, 0x080c, 0x98bc, - 0x0005, 0x9186, 0x0014, 0x0d70, 0x080c, 0xb009, 0x0005, 0xe94e, - 0xe94c, 0xe94c, 0xe94c, 0xe94c, 0xe94c, 0xe94e, 0xe94c, 0xe94c, - 0xe94c, 0xe94c, 0xe94c, 0xe94c, 0x080c, 0x0d79, 0x6003, 0x000c, - 0x080c, 0x98bc, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, - 0x0208, 0x001a, 0x080c, 0xb009, 0x0005, 0xe96a, 0xe96a, 0xe96a, - 0xe96a, 0xe96c, 0xe98c, 0xe96a, 0xe96a, 0xe96a, 0xe96a, 0xe96a, - 0xe96a, 0xe96a, 0x080c, 0x0d79, 0x00d6, 0x2c68, 0x080c, 0xaef8, - 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, 0x210c, - 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, 0x6910, - 0x6112, 0x6023, 0x0004, 0x2009, 0x8020, 0x080c, 0x9420, 0x2d60, - 0x080c, 0xaf4e, 0x00de, 0x0005, 0x080c, 0xaf4e, 0x0005, 0x00e6, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee, 0x0005, - 0x2009, 0x1867, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, 0x6024, - 0xc0e5, 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1989, 0x2004, 0x604a, - 0x2009, 0x1867, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, 0x1867, - 0x210c, 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, 0x00d8, - 0x2001, 0x1989, 0x200c, 0x2001, 0x1987, 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, 0x8ab2, 0x080c, 0xaf4e, 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, - 0xbf54, 0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, 0x0004, 0x6010, - 0x0096, 0x2048, 0x2019, 0x0006, 0x080c, 0xbf54, 0x009e, 0x1100, - 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, - 0x610b, 0x080c, 0x30c8, 0x00ee, 0x0005, 0x0096, 0x0026, 0x080c, - 0x104d, 0x090c, 0x0d79, 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, 0x6f11, 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, 0x19f5, 0x252c, 0x2021, 0x19fc, 0x2424, 0x2061, - 0x1ddc, 0x2071, 0x1800, 0x7654, 0x7074, 0x9606, 0x0578, 0x6720, - 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, - 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, 0xe7c6, 0x01b8, 0x080c, - 0xe7d6, 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, - 0x1af0, 0x001e, 0x080c, 0xce39, 0x1110, 0x080c, 0x332a, 0x080c, - 0xce4a, 0x1110, 0x080c, 0xb93c, 0x080c, 0xaf89, 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, 0xd35d, 0x0168, 0x2019, 0xffff, 0x9005, 0x0128, 0x6010, - 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, 0x0004, 0x080c, 0x4ddf, - 0x004e, 0x003e, 0x000e, 0x0005, 0x6004, 0x9086, 0x0001, 0x1128, - 0x080c, 0xa5dd, 0x080c, 0xaf89, 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, 0x7163 + 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 = 0xe428; +unsigned short fw2322ipx_length01 = 0xe719; #else -unsigned short risc_code_length01 = 0xe428; +unsigned short risc_code_length01 = 0xe719; #endif /* @@ -7352,7 +7447,7 @@ unsigned short risc_code_length01 = 0xe428; unsigned long rseqipx_code_addr01 = 0x0001c000 ; unsigned short rseqipx_code01[] = { -0x000b, 0x0003, 0x0000, 0x0a4a, 0x0001, 0xc000, 0x0008, 0x8064, +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, @@ -7555,7 +7650,7 @@ unsigned short rseqipx_code01[] = { 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, 0x04e3, 0x0009, 0xbbe0, 0x0008, 0x0036, + 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, @@ -7614,8 +7709,8 @@ unsigned short rseqipx_code01[] = { 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, 0x0004, 0x04ec, 0x0008, 0x808c, - 0x0000, 0x0001, 0x0000, 0x04fc, 0x0003, 0x34cf, 0x0000, 0x0460, + 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, @@ -7623,8 +7718,8 @@ unsigned short rseqipx_code01[] = { 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, 0x8ccf, 0x0009, 0xc4c0, 0x0000, 0x7000, - 0x0009, 0xffe0, 0x0000, 0x1000, 0x000b, 0x0c6a, 0x000c, 0x04dd, + 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, @@ -7634,56 +7729,56 @@ unsigned short rseqipx_code01[] = { 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, 0x04c2, 0x000c, 0x04dd, 0x0002, 0x3941, + 0x0000, 0x0010, 0x000b, 0x04c4, 0x0004, 0x04df, 0x0002, 0x3941, 0x0003, 0x0c70, 0x0000, 0x8072, 0x0000, 0x0400, 0x0003, 0x0013, - 0x0004, 0x04a7, 0x0008, 0x11fc, 0x000b, 0xb478, 0x0000, 0x8072, - 0x0000, 0x0400, 0x0008, 0x8010, 0x0000, 0x000e, 0x000b, 0x04c2, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x04fc, 0x000b, 0xb48d, - 0x0008, 0x808c, 0x0008, 0x0000, 0x0001, 0x9180, 0x0008, 0x0005, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc483, - 0x0008, 0x0060, 0x0008, 0x8062, 0x0008, 0x001b, 0x0008, 0x4304, - 0x0008, 0x4206, 0x0000, 0x8066, 0x0000, 0x0412, 0x0003, 0xc48b, - 0x000b, 0x04a4, 0x0008, 0x808c, 0x0000, 0x0001, 0x0000, 0x0460, - 0x0008, 0x8062, 0x0008, 0x002b, 0x0000, 0x8066, 0x0008, 0x0609, - 0x000b, 0xc494, 0x0000, 0x8066, 0x0008, 0x220a, 0x000b, 0xc497, - 0x0000, 0x42fe, 0x0001, 0xffc0, 0x0008, 0xff00, 0x0008, 0x7f04, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0001, 0x9180, 0x0000, 0x0002, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x041a, 0x0003, 0xc4a3, - 0x0000, 0x8072, 0x0000, 0x0400, 0x000b, 0x0056, 0x0000, 0x8060, - 0x0000, 0x0400, 0x0008, 0x6b62, 0x0000, 0x8066, 0x0000, 0x0411, - 0x0003, 0xc4ac, 0x0008, 0x02fe, 0x0009, 0x03e0, 0x0003, 0x8cb2, - 0x0000, 0x0d22, 0x000f, 0x4000, 0x0009, 0x8280, 0x0000, 0x0002, - 0x0001, 0x6b80, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x2209, - 0x0003, 0xc4b8, 0x000a, 0x0200, 0x0001, 0xffc0, 0x0000, 0x0007, - 0x0000, 0x7f06, 0x0008, 0x6b62, 0x0000, 0x8066, 0x0008, 0x060a, - 0x0003, 0xc4c0, 0x000f, 0x4000, 0x0002, 0x3a44, 0x0003, 0x8813, - 0x000a, 0x2f44, 0x000a, 0x2f44, 0x0003, 0x8bd0, 0x0008, 0x808a, - 0x0008, 0x0003, 0x0000, 0x8074, 0x0000, 0xf080, 0x0003, 0x5ccb, - 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, 0x0003, 0x0ce0, 0x000f, 0x4000, - 0x0000, 0x8072, 0x0008, 0x0404, 0x000f, 0x4000, 0x0008, 0x8010, - 0x0008, 0x0012, 0x0004, 0x0387, 0x0004, 0x04a7, 0x0000, 0x1110, - 0x0004, 0x0387, 0x0008, 0x11fc, 0x0003, 0xb4e6, 0x0003, 0x0013, - 0x0009, 0xc2c0, 0x0008, 0x00ff, 0x0000, 0x7f00, 0x0001, 0xc3c0, - 0x0008, 0xff00, 0x0009, 0x00d0, 0x0003, 0x0d11, 0x0000, 0x0d0a, - 0x0001, 0x8580, 0x0000, 0x1000, 0x0008, 0x7f62, 0x0000, 0x8060, - 0x0000, 0x0400, 0x0000, 0x8066, 0x0000, 0x0809, 0x000b, 0xc4fb, - 0x0000, 0x04fc, 0x000b, 0x350a, 0x0000, 0x0460, 0x0008, 0x8062, - 0x0000, 0x0004, 0x0000, 0x8066, 0x0000, 0x0211, 0x000b, 0xc503, - 0x0008, 0x01fe, 0x0009, 0x00e0, 0x000b, 0x8d0a, 0x0008, 0x02fe, - 0x0001, 0x43e0, 0x000b, 0x0d10, 0x0002, 0x0500, 0x0000, 0x7f0a, - 0x0009, 0xffe0, 0x0000, 0x0800, 0x000b, 0x8cf4, 0x0008, 0x0d08, - 0x000f, 0x4000, 0x0008, 0x43fe, 0x0001, 0x3e80, 0x0000, 0x0d60, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0000, 0x0809, 0x000b, 0xc517, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0001, 0x84c0, 0x0008, 0xff00, - 0x0002, 0x7f70, 0x0009, 0xff80, 0x0000, 0x1000, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0000, 0x0809, 0x000b, 0xc522, 0x000f, 0x4000, - 0xe4ae, 0x1eb8 + 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 = 0x0a4a; +unsigned short rseqipx_code_length01 = 0x0a4e; /* * */ @@ -7902,10 +7997,10 @@ unsigned short xseqipx_code01[] = { 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, 0x1b56, - 0x000b, 0x1367, 0x0005, 0x0031, 0x0011, 0x1b6e, 0x0015, 0x0033, + 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, 0x1b6e, 0x0015, 0x0033, 0x0010, 0xb40a, + 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, @@ -7980,7 +8075,7 @@ unsigned short xseqipx_code01[] = { 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, 0x1b56, 0x0015, 0x0011, 0x0001, 0x1b56, 0x0001, 0x1288, + 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, @@ -8019,7 +8114,7 @@ unsigned short xseqipx_code01[] = { 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, 0x1b72, 0x0015, 0x0033, + 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, @@ -8111,7 +8206,7 @@ unsigned short xseqipx_code01[] = { 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, 0x1b56, 0x0003, 0x1845, + 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, @@ -8221,15 +8316,15 @@ unsigned short xseqipx_code01[] = { 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, 0x0011, 0x1b6d, 0x0015, 0x0033, 0x0010, 0xb211, + 0x0005, 0x0031, 0x0001, 0x1b6c, 0x0015, 0x0033, 0x0010, 0xb211, 0x000b, 0x8850, 0x0002, 0xb200, 0x0010, 0xffb2, 0x0005, 0x0031, - 0x0011, 0x1b6d, 0x0015, 0x0033, 0x0010, 0xb20a, 0x001b, 0x8857, + 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, 0x1b56, + 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, @@ -8276,6 +8371,6 @@ unsigned short xseqipx_code01[] = { 0x0010, 0xffb2, 0x0011, 0x1388, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb20a, 0x001b, 0x8922, 0x0015, 0x00b8, 0x0000, 0x0007, 0x0013, 0x4925, 0x0000, 0xb838, 0x0017, 0x4000, - 0x9a6c, 0xaf33 + 0x9a8c, 0xaf3d }; unsigned short xseqipx_code_length01 = 0x1252; diff --git a/drivers/scsi/qla2xxx/ql2400_fw.c b/drivers/scsi/qla2xxx/ql2400_fw.c index 5977795854f8..282b2d33ebf2 100644 --- a/drivers/scsi/qla2xxx/ql2400_fw.c +++ b/drivers/scsi/qla2xxx/ql2400_fw.c @@ -7,7 +7,7 @@ #include /* - * Firmware Version 4.00.16 (08:09 Oct 26, 2005) + * Firmware Version 4.00.18 (14:53 Jan 30, 2006) */ #ifdef UNIQUE_FW_NAME @@ -17,15 +17,15 @@ uint32_t risc_code_version = 4*1024+0; #endif #ifdef UNIQUE_FW_NAME -uint32_t fw2400_version_str[] = {4, 0,16}; +uint32_t fw2400_version_str[] = {4, 0,18}; #else -uint32_t firmware_version[] = {4, 0,16}; +uint32_t firmware_version[] = {4, 0,18}; #endif #ifdef UNIQUE_FW_NAME -#define fw2400_VERSION_STRING "4.00.16" +#define fw2400_VERSION_STRING "4.00.18" #else -#define FW_VERSION_STRING "4.00.16" +#define FW_VERSION_STRING "4.00.18" #endif #ifdef UNIQUE_FW_NAME @@ -39,19 +39,19 @@ uint32_t fw2400_code01[] = { #else uint32_t risc_code01[] = { #endif - 0x0401f17c, 0x0010e000, 0x00100000, 0x0000ab4a, - 0x00000004, 0x00000000, 0x00000010, 0x00000002, + 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, 0x31362020, + 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, 0x0010b8fe, + 0x42001800, 0x0010014f, 0x42002000, 0x0010b6fd, 0x500c0800, 0x800c1800, 0x500c1000, 0x800c1800, 0x54042000, 0x80102000, 0x80040800, 0x80081040, 0x040207fc, 0x500c0800, 0x800409c0, 0x040207f6, @@ -138,7 +138,7 @@ uint32_t risc_code01[] = { 0x42000800, 0x00021f00, 0x45780800, 0x80040800, 0x80000040, 0x040207fd, 0x4203f000, 0x00021fff, 0x40000000, 0x4203e000, 0x90000100, 0x40000000, - 0x0201f800, 0x001006fd, 0x42000000, 0x00001000, + 0x0201f800, 0x00100743, 0x42000000, 0x00001000, 0x50000000, 0x82000480, 0x24320002, 0x04020015, 0x42000800, 0x00000064, 0x80040840, 0x04000007, 0x4a030000, 0x00000001, 0x40000000, 0x59800000, @@ -149,742 +149,759 @@ uint32_t risc_code01[] = { 0x59e00023, 0x8c000500, 0x04020039, 0x42000000, 0x00100001, 0x50000800, 0x82040c00, 0x00000004, 0x58042003, 0x42001000, 0xffffffff, 0x0201f800, - 0x001006f4, 0x0402004e, 0x58042003, 0x42001000, - 0xffffffff, 0x0201f800, 0x001006f4, 0x04020048, + 0x0010073a, 0x0402004e, 0x58042003, 0x42001000, + 0xffffffff, 0x0201f800, 0x0010073a, 0x04020048, 0x58042003, 0x42001000, 0x00ffffff, 0x0201f800, - 0x001006f4, 0x04020042, 0x58042003, 0x42001000, - 0x00ffffff, 0x0201f800, 0x001006f4, 0x0402003c, + 0x0010073a, 0x04020042, 0x58042003, 0x42001000, + 0x00ffffff, 0x0201f800, 0x0010073a, 0x0402003c, 0x42000000, 0x00100001, 0x5000a000, 0x8250a400, 0x00000004, 0x4200a800, 0x00020000, 0x5850b003, - 0x0201f800, 0x0010ab17, 0x8250a400, 0x00000005, + 0x0201f800, 0x0010a93e, 0x8250a400, 0x00000005, 0x4a0370e8, 0x00000003, 0x4200a800, 0x0000c000, - 0x5850b003, 0x0201f800, 0x0010ab17, 0x4a0378e8, + 0x5850b003, 0x0201f800, 0x0010a93e, 0x4a0378e8, 0x00000003, 0x4200a800, 0x00008000, 0x5850b003, - 0x0201f800, 0x0010ab17, 0x0401f02b, 0x42000800, + 0x0201f800, 0x0010a93e, 0x0401f02b, 0x42000800, 0x00020000, 0x58042003, 0x42001000, 0xffffffff, - 0x0201f800, 0x001006f4, 0x04020019, 0x4a0370e8, + 0x0201f800, 0x0010073a, 0x04020019, 0x4a0370e8, 0x00000003, 0x42000800, 0x0000c000, 0x58042003, 0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff, - 0x0201f800, 0x001006f4, 0x0402000d, 0x4a0378e8, + 0x0201f800, 0x0010073a, 0x0402000d, 0x4a0378e8, 0x00000003, 0x42000800, 0x00008000, 0x58042003, 0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff, - 0x0201f800, 0x001006f4, 0x0400000b, 0x4a03c020, + 0x0201f800, 0x0010073a, 0x0400000b, 0x4a03c020, 0x00004010, 0x4a03c011, 0x40100011, 0x04006000, 0x4203e000, 0x40000000, 0x4203e000, 0x30000001, - 0x0401f000, 0x0201f800, 0x00100791, 0x42001000, - 0x0010ab4a, 0x40080000, 0x80140480, 0x82001d00, + 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, 0x59a80005, - 0x8400054e, 0x48035005, 0x0401f008, 0x59e00003, - 0x82000500, 0x00030000, 0x04000004, 0x59a80005, - 0x84000554, 0x48035005, 0x42000800, 0x00000040, - 0x59a80005, 0x8c000514, 0x0402000e, 0x42000800, - 0x00001000, 0x82141480, 0x0017ffff, 0x04021009, - 0x80040902, 0x82141480, 0x0013ffff, 0x04021005, - 0x80040902, 0x82141480, 0x0011ffff, 0x04001b8d, - 0x4807500e, 0x42001000, 0x00000024, 0x0201f800, - 0x00106681, 0x82040c00, 0x0010d1c0, 0x4807500b, - 0x4a03c810, 0x00100000, 0x4a03c811, 0x0010ab4a, - 0x4a03c829, 0x00000004, 0x59e40001, 0x82000540, - 0x0003001d, 0x4803c801, 0x4a03c014, 0x001c001c, - 0x42001000, 0x0000001c, 0x0201f800, 0x001006e2, - 0x4202c000, 0x0010d1c0, 0x59aab00b, 0x59aaa00b, - 0x59aaa80b, 0x59aac80e, 0x49675069, 0x59a8000b, - 0x4803500c, 0x0401fbf5, 0x0201f800, 0x00107903, - 0x0201f800, 0x001007be, 0x0201f800, 0x00100807, - 0x0201f800, 0x00101a05, 0x0201f800, 0x00101354, - 0x0201f800, 0x00100969, 0x0201f800, 0x00101354, - 0x0201f800, 0x00100f4c, 0x0201f800, 0x001066c1, - 0x0401fb1a, 0x0201f800, 0x0010220e, 0x0201f800, - 0x001053bb, 0x0201f800, 0x00104c90, 0x0201f800, - 0x00106194, 0x0201f800, 0x00105f28, 0x0201f800, - 0x001013ed, 0x0201f800, 0x0010126f, 0x4203e000, - 0xf0000001, 0x42000000, 0x00001000, 0x50000000, - 0x82000480, 0x24220001, 0x04000016, 0x59e00002, - 0x8c00051e, 0x42000000, 0x7ffe00fe, 0x04020003, - 0x42000000, 0x7ffe01fe, 0x50000800, 0x48075058, - 0x80040920, 0x82040580, 0x0000013a, 0x04000004, - 0x82040580, 0x0000013b, 0x04020006, 0x59a80005, - 0x84000552, 0x48035005, 0x4a0378e4, 0x000c0000, - 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, 0x59a80005, - 0x42000800, 0x00000002, 0x8c000512, 0x04020007, - 0x42000800, 0x0000000f, 0x8c000514, 0x04020003, - 0x42000800, 0x00000001, 0x4007f800, 0x59a80005, - 0x8c000514, 0x02020000, 0x00020004, 0x59e00003, - 0x82000500, 0x00030000, 0x82000580, 0x00000000, - 0x04020af8, 0x0201f000, 0x00020004, 0x4df00000, - 0x4203e000, 0x50000000, 0x416c0000, 0x82000c80, - 0x00000008, 0x04021aef, 0x0c01f804, 0x5c03e000, - 0x0201f000, 0x00020008, 0x001002f7, 0x0010030a, - 0x001003d7, 0x001002f6, 0x00100452, 0x001002f6, - 0x001002f6, 0x00100593, 0x0401fae2, 0x42000800, - 0x0010b4a4, 0x5804001d, 0x4803c857, 0x8c000500, - 0x0400000d, 0x84000500, 0x4800081d, 0x4202d800, - 0x00000004, 0x0401fbd3, 0x49f3c857, 0x5c000800, - 0x5c000000, 0x82000540, 0x00003e00, 0x4c000000, - 0x4c040000, 0x1c01f000, 0x0401fbbd, 0x0201f800, - 0x0010513b, 0x04000009, 0x0201f800, 0x00105151, + 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, 0x001050a2, - 0x836c0580, 0x00000001, 0x040200bc, 0x59a80017, - 0x82000580, 0x00000009, 0x040200b8, 0x497b5010, + 0x48038806, 0x0401f029, 0x0201f800, 0x00104d76, + 0x836c0580, 0x00000001, 0x040200be, 0x59a80017, + 0x82000580, 0x00000009, 0x040200ba, 0x497b5010, 0x4a038893, 0x00000001, 0x42001000, 0x000000f0, - 0x0201f800, 0x0010193d, 0x0201f800, 0x00105149, + 0x0201f800, 0x001019aa, 0x0201f800, 0x00104e1b, 0x59c41006, 0x04020006, 0x82081540, 0x000000f1, 0x82081500, 0xbbffffff, 0x0401f003, 0x82081540, - 0x440000f1, 0x480b8806, 0x0201f800, 0x0010609e, - 0x4a0378e4, 0x00002000, 0x42000000, 0x0010b83a, - 0x0201f800, 0x0010aa47, 0x42001000, 0x00008030, - 0x497b5013, 0x0401f035, 0x0201f800, 0x00103b38, + 0x440000f1, 0x480b8806, 0x0201f800, 0x00105de2, + 0x0201f800, 0x001069b8, 0x42000000, 0x0010b638, + 0x0201f800, 0x0010a86e, 0x42001000, 0x00008030, + 0x497b5013, 0x0401f037, 0x0201f800, 0x00103951, 0x59c400a4, 0x82000500, 0x0000000f, 0x82000480, - 0x00000007, 0x04021091, 0x0201f800, 0x0010609e, + 0x00000007, 0x04021093, 0x0201f800, 0x00105de2, 0x59c400a3, 0x82000500, 0xffefffff, 0x480388a3, 0x59a8004b, 0x800001c0, 0x04020004, 0x0201f800, - 0x00104139, 0x0401f085, 0x59a80015, 0x84000546, - 0x48035015, 0x0201f800, 0x00105141, 0x59c41006, + 0x00103f53, 0x0401f087, 0x59a80015, 0x84000546, + 0x48035015, 0x0201f800, 0x00104e13, 0x59c41006, 0x04020006, 0x82081540, 0x44000001, 0x82081500, 0xffffff0f, 0x0401f003, 0x82081540, 0x440000f1, 0x480b8806, 0x497b9005, 0x4a038802, 0x0000ffff, - 0x4a0378e4, 0x00003000, 0x42000000, 0x0010b80c, - 0x0201f800, 0x0010aa47, 0x59a81010, 0x42000800, - 0x00000003, 0x0201f800, 0x00106c78, 0x42001000, - 0x00008010, 0x59a8180a, 0x0201f800, 0x00103a3e, - 0x0201f800, 0x00101815, 0x59a80805, 0x82040d00, - 0xffffffdf, 0x48075005, 0x0201f800, 0x0010483d, - 0x0201f800, 0x0010513b, 0x0400000a, 0x0201f800, - 0x0010413e, 0x04000007, 0x4a035013, 0x00000001, - 0x497b5021, 0x0201f800, 0x00103c80, 0x0401f04f, - 0x0201f800, 0x001048ec, 0x04000005, 0x59c41002, - 0x8408150c, 0x480b8802, 0x0401f012, 0x0201f800, - 0x0010513b, 0x04020006, 0x59a8001d, 0x80000540, - 0x02000800, 0x0010930f, 0x0401f00a, 0x0201f800, - 0x0010930f, 0x59a80026, 0x8c000506, 0x04020005, - 0x59a8001d, 0x80000540, 0x02020800, 0x00104245, - 0x497b5028, 0x497b5027, 0x497b5018, 0x0201f800, - 0x0010513b, 0x59a81026, 0x0402000a, 0x0201f800, - 0x0010162a, 0x80001580, 0x59a8002a, 0x82000500, - 0xffff0000, 0x80040d40, 0x4807502a, 0x0401f005, - 0x59a8002a, 0x82000500, 0xffff0000, 0x4803502a, - 0x599c0017, 0x8c00050a, 0x04000002, 0x84081544, - 0x480b5026, 0x0201f800, 0x0010513b, 0x04000004, - 0x0201f800, 0x0010162a, 0x48078880, 0x42001000, - 0x00000005, 0x0201f800, 0x001070b0, 0x497b5028, - 0x497b501b, 0x4a03501c, 0x0000ffff, 0x4a0378e4, - 0x000000c0, 0x4202d800, 0x00000002, 0x0201f800, - 0x0010513b, 0x04000007, 0x59a80026, 0x82000500, - 0x0000000c, 0x82000580, 0x00000004, 0x04000003, - 0x0201f800, 0x00101e45, 0x1c01f000, 0x59a8001c, - 0x82000580, 0x0000ffff, 0x04000004, 0x0201f800, - 0x00101e45, 0x0401f074, 0x59a80026, 0x8c00050a, - 0x04020003, 0x8c000506, 0x0400001c, 0x8c000500, - 0x0400001a, 0x4a038802, 0x0000ffbf, 0x8c000502, - 0x04000016, 0x599c0018, 0x8c000516, 0x04020010, - 0x59a80027, 0x82000580, 0x0000ffff, 0x0400000c, - 0x0201f800, 0x00101f9a, 0x59a80026, 0x8c000504, - 0x0402005d, 0x42001000, 0x00000003, 0x417a5800, - 0x0201f800, 0x00101fbf, 0x0401f057, 0x59a80028, - 0x80000540, 0x04020054, 0x59a80026, 0x8c000508, - 0x04020005, 0x59a8001b, 0x80000540, 0x0402004e, - 0x0401f003, 0x8c000516, 0x0400004b, 0x0201f800, - 0x001048ec, 0x04020048, 0x599c0018, 0x8c000516, - 0x04020004, 0x0201f800, 0x00104c51, 0x04020042, - 0x599c0017, 0x8c00050a, 0x0400000d, 0x4200b000, - 0x000007f0, 0x417a8800, 0x0201f800, 0x00020245, - 0x04020004, 0x59340200, 0x8c00051a, 0x04020036, - 0x81468800, 0x8058b040, 0x040207f8, 0x4a038802, - 0x0000ffff, 0x42001800, 0x0010b4eb, 0x0401fb8c, - 0x42001800, 0x0010b4f8, 0x0401fb89, 0x59a80005, - 0x84000502, 0x48035005, 0x4a0378e4, 0x00000080, - 0x4202d800, 0x00000003, 0x4a03501c, 0x0000ffff, - 0x0401fa7f, 0x80000580, 0x0201f800, 0x00101590, - 0x599c0018, 0x8c000516, 0x04000004, 0x0201f800, - 0x00103b10, 0x0401f009, 0x42001800, 0x0000ffff, - 0x42002000, 0x00000006, 0x42003000, 0x00000000, - 0x0201f800, 0x00103aae, 0x0201f800, 0x00105151, - 0x0400000b, 0x59c40006, 0x0201f800, 0x0010513b, - 0x04000004, 0x82000500, 0xffffff0f, 0x0401f003, - 0x82000500, 0xfbffffff, 0x48038806, 0x0201f800, - 0x00106f36, 0x1c01f000, 0x4c040000, 0x4c080000, - 0x4c100000, 0x59a8003e, 0x82000c80, 0x00000004, - 0x04021980, 0x0c01f805, 0x5c002000, 0x5c001000, - 0x5c000800, 0x1c01f000, 0x00100462, 0x001004ea, - 0x00100516, 0x00100577, 0x42000000, 0x00000001, - 0x0201f800, 0x00101590, 0x0201f800, 0x0010609e, - 0x59c408a3, 0x82040d00, 0xfffffff7, 0x480788a3, - 0x0201f800, 0x00105141, 0x0400000e, 0x0201f800, - 0x00105151, 0x0400000b, 0x0201f800, 0x00105149, - 0x04020964, 0x59c400a3, 0x84000532, 0x84000570, - 0x480388a3, 0x4a038808, 0x00000008, 0x0401f010, - 0x59c400a3, 0x84000530, 0x82000500, 0xbf7fffff, - 0x480388a3, 0x42000800, 0x000000f8, 0x0201f800, - 0x00104200, 0x59c400a3, 0x82000540, 0x00018000, - 0x8400051c, 0x480388a3, 0x497b8808, 0x59c40006, - 0x82000500, 0xfbffff0e, 0x48038806, 0x497b2822, - 0x497b2823, 0x42000800, 0x000001f4, 0x42001000, - 0x00100591, 0x0201f800, 0x00105f83, 0x59c40805, - 0x42001000, 0x00000001, 0x0201f800, 0x0010193d, - 0x0201f800, 0x0010163b, 0x0402000a, 0x42000000, - 0x00000001, 0x0201f800, 0x0010188c, 0x42000000, - 0x00000001, 0x0201f800, 0x00101821, 0x0401f022, - 0x0201f800, 0x00101642, 0x04020008, 0x41780000, - 0x0201f800, 0x0010188c, 0x41780000, 0x0201f800, - 0x00101821, 0x0401f018, 0x0201f800, 0x00101649, - 0x0402000a, 0x42000000, 0x00000002, 0x0201f800, - 0x0010188c, 0x42000000, 0x00000002, 0x0201f800, - 0x00101821, 0x0401f00c, 0x0201f800, 0x00101650, - 0x04020918, 0x59a80049, 0x800001c0, 0x04000006, - 0x0201f800, 0x00101656, 0x4a03503e, 0x00000001, - 0x0401f021, 0x0201f800, 0x00101927, 0x4a03503e, - 0x00000001, 0x0201f800, 0x00105141, 0x0400000c, - 0x0201f800, 0x00105151, 0x04000009, 0x0201f800, - 0x00105149, 0x04020903, 0x4a035033, 0x00000001, - 0x0201f800, 0x001050a2, 0x0401f00f, 0x59c400a4, - 0x82000500, 0x0000000f, 0x82000580, 0x00000008, - 0x04000003, 0x4a038805, 0x04000000, 0x59c400a3, - 0x82000540, 0x0001c000, 0x480388a3, 0x84000520, - 0x480388a3, 0x1c01f000, 0x0401f8a3, 0x04020004, - 0x4a03503e, 0x00000003, 0x0401f027, 0x0201f800, - 0x00101650, 0x04020011, 0x59a80049, 0x800001c0, - 0x0400000e, 0x0201f800, 0x00101656, 0x59a80048, - 0x8c00051e, 0x0400001c, 0x0201f800, 0x00105149, - 0x04020009, 0x4a035033, 0x00000001, 0x0201f800, - 0x001050a2, 0x0401f004, 0x0201f800, 0x001018d3, - 0x04020011, 0x0201f800, 0x00101815, 0x4a03503e, - 0x00000002, 0x497b5049, 0x59c400a3, 0x84000520, - 0x480388a3, 0x497b2822, 0x497b2823, 0x42000800, - 0x0000002d, 0x42001000, 0x00100591, 0x0201f800, - 0x00105f83, 0x1c01f000, 0x0401f877, 0x04020004, - 0x4a03503e, 0x00000003, 0x0401f05b, 0x4a038805, - 0x000000f0, 0x0201f800, 0x001018d3, 0x04020050, - 0x0201f800, 0x00105149, 0x04000044, 0x59c400a4, - 0x82000500, 0x0000000f, 0x82000580, 0x00000008, - 0x04000020, 0x59c40005, 0x8c000534, 0x0402001d, - 0x59940022, 0x82000580, 0x00000001, 0x04020046, - 0x0201f800, 0x00105151, 0x04020043, 0x4a038805, - 0x000000f0, 0x0201f800, 0x00105196, 0x4a035032, - 0x0000aaaa, 0x4a035033, 0x00000000, 0x59c408a3, - 0x82040d40, 0x00000008, 0x480788a3, 0x4202d800, - 0x00000001, 0x4a03503e, 0x00000000, 0x4a038805, - 0x00000001, 0x497b2822, 0x497b2823, 0x0401f01f, - 0x0201f800, 0x00105151, 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, - 0x00101650, 0x04020004, 0x59a80049, 0x800001c0, - 0x040207a4, 0x497b8885, 0x1c01f000, 0x4803c856, - 0x42000000, 0x00000001, 0x0201f800, 0x00101590, - 0x4a03503e, 0x00000000, 0x0201f800, 0x00101650, - 0x0402000b, 0x59a80052, 0x800001c0, 0x04000004, - 0x80000040, 0x48035052, 0x04020005, 0x4a035052, - 0x0000000a, 0x4a035049, 0x00000001, 0x497b8885, - 0x0401f0ed, 0x59940022, 0x59940823, 0x80040540, - 0x1c01f000, 0x497b2823, 0x1c01f000, 0x4c080000, - 0x42001000, 0x000000f0, 0x0201f800, 0x0010193d, - 0x5c001000, 0x1c01f000, 0x4a03505c, 0x00000004, - 0x4a03505d, 0x00000000, 0x4a03505e, 0x00000010, - 0x4a03505f, 0x00000002, 0x4a035010, 0x00ffffff, - 0x0201f800, 0x0010930f, 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, 0x00020245, - 0x04020005, 0x0201f800, 0x001049e7, 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, 0x00106c6c, 0x5c000800, 0x4807c025, - 0x80040920, 0x4807c026, 0x5c000000, 0x4803c023, - 0x80000120, 0x4803c024, 0x5c000000, 0x4803c857, - 0x4803c021, 0x80000120, 0x4803c022, 0x41f80000, - 0x4803c027, 0x80000120, 0x4803c028, 0x42000000, - 0x00001000, 0x50000000, 0x82000480, 0x24320001, - 0x4803c857, 0x0400104f, 0x42000800, 0x00000064, - 0x80040840, 0x04000007, 0x4a030000, 0x00000001, - 0x40000000, 0x59800000, 0x8c000500, 0x040007f9, - 0x04000042, 0x42000800, 0x0010c1a3, 0x46000800, - 0xfaceface, 0x80040800, 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, 0x4a030000, 0x00000000, - 0x485fc020, 0x905cb9c0, 0x825cbd40, 0x00000012, - 0x485fc011, 0x4203e000, 0x40000000, 0x4202d800, - 0x00000005, 0x59e00017, 0x8c000508, 0x04000003, - 0x4a03c017, 0x00000002, 0x4203e000, 0x30000001, - 0x0401f81a, 0x0401f7ff, 0x4a03c850, 0x0010c1bf, - 0x4a03c851, 0x0010d1be, 0x4a03c853, 0x00000800, - 0x4a03c855, 0x0001eb5a, 0x59e40001, 0x82000540, - 0x00003f00, 0x4803c801, 0x4a03b104, 0x70000002, - 0x4a03a804, 0x70000002, 0x4a03b004, 0x70000002, - 0x42000000, 0x0010b8ec, 0x49780001, 0x49780002, - 0x1c01f000, 0x1c01f000, 0x59a8006b, 0x8c000530, - 0x040207fe, 0x4c080000, 0x42001000, 0x00000004, - 0x0401f862, 0x5c001000, 0x4201d000, 0x00028b0a, - 0x0201f800, 0x0010608e, 0x4c080000, 0x42001000, - 0x00000008, 0x0401f859, 0x5c001000, 0x4201d000, - 0x00028b0a, 0x0201f800, 0x0010608e, 0x4c080000, - 0x42001000, 0x00000010, 0x0401f850, 0x5c001000, - 0x4201d000, 0x00028b0a, 0x0201f800, 0x0010608e, - 0x0401f7e2, 0x8c00050c, 0x59a8086b, 0x04020003, - 0x84040d30, 0x0401f006, 0x84040d70, 0x4807506b, - 0x42001000, 0x00000000, 0x0401f040, 0x4807506b, - 0x836c0500, 0x00000007, 0x0c01f001, 0x001006e1, - 0x001006c7, 0x001006c7, 0x001006af, 0x001006d4, - 0x001006c7, 0x001006c7, 0x001006d4, 0x59a80005, - 0x8c000514, 0x04020013, 0x59c40801, 0x82040d00, - 0x00018000, 0x82040580, 0x00010000, 0x0400000a, - 0x82040580, 0x00008000, 0x04000004, 0x42001000, - 0x42004000, 0x0401f006, 0x42001000, 0x22002000, - 0x0401f003, 0x42001000, 0x12001000, 0x0401f025, - 0x42001000, 0x00001004, 0x0401f022, 0x59a80005, - 0x8c000514, 0x04020008, 0x59a8006b, 0x8c000534, - 0x04020004, 0x42001000, 0x74057005, 0x0401f819, - 0x1c01f000, 0x42001000, 0x00002008, 0x0401f7fc, - 0x59a8006b, 0x8c000534, 0x0402000a, 0x59a80005, - 0x8c000514, 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, 0x0010b537, 0x42019800, - 0x0010b50e, 0x4179a000, 0x4179b000, 0x4179a800, - 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, 0x0010b806, - 0x42031800, 0x0000bf1d, 0x42032000, 0x0000bf32, - 0x42032800, 0x0010b7ce, 0x42033000, 0x0010b46e, - 0x42034000, 0x0010b4a4, 0x42033800, 0x0010b4c3, - 0x42034800, 0x0010b544, 0x42035000, 0x0010b400, - 0x42035800, 0x0010ac00, 0x42030800, 0x0010b505, - 0x417b6000, 0x42036800, 0x00006f00, 0x4203c800, - 0x00003000, 0x42037000, 0x0000ff00, 0x42037800, - 0x0000bf00, 0x42038000, 0x00007700, 0x42038800, - 0x00004000, 0x42039000, 0x00006000, 0x42039800, - 0x0010bedb, 0x4203a000, 0x00007600, 0x4203a800, - 0x00007400, 0x4203b000, 0x00007200, 0x4203b800, - 0x00007100, 0x4203c000, 0x00007000, 0x4203d000, - 0x00000000, 0x4203e800, 0x00101b95, 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, 0x0401fe01, 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, 0x0010b853, - 0x0201f800, 0x0010aa47, 0x417a5800, 0x0401f7f9, - 0x815eb840, 0x04001008, 0x416a5800, 0x492fc857, - 0x592ed000, 0x497a5800, 0x497a5801, 0x812e59c0, - 0x1c01f000, 0x42000000, 0x0010b853, 0x0201f800, - 0x0010aa47, 0x417ab800, 0x417a5800, 0x0401f7f8, - 0x492fc857, 0x496a5800, 0x412ed000, 0x815eb800, - 0x59c80000, 0x82000540, 0x00001200, 0x48039000, - 0x1c01f000, 0x492fc857, 0x812e59c0, 0x04000007, - 0x592c0001, 0x497a5801, 0x4c000000, 0x0401fff1, - 0x5c025800, 0x0401f7f9, 0x1c01f000, 0x4807c856, - 0x42007000, 0x0010b7f8, 0x4a007001, 0x00000000, - 0x59e00003, 0x82000540, 0x00008080, 0x4803c003, - 0x4a03b805, 0x90000001, 0x59dc0006, 0x4a03b805, - 0x70000000, 0x59dc0006, 0x4a03b805, 0x30000000, - 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, 0x0401ffa1, 0x04000da5, - 0x42001000, 0x0010b7f6, 0x452c1000, 0x4a025801, - 0x00000001, 0x4a025802, 0x00000100, 0x4a025809, - 0x00107149, 0x497a580a, 0x497a580b, 0x497a580c, - 0x0401ff93, 0x04000d97, 0x42001000, 0x0010b7f7, - 0x452c1000, 0x4a025801, 0x00000000, 0x4a025802, - 0x00000100, 0x4a025809, 0x001011bc, 0x497a5803, - 0x497a5807, 0x497a5808, 0x497a580a, 0x59a80005, - 0x8c00050e, 0x04000006, 0x4a03b805, 0xe0000001, - 0x59dc0006, 0x8c000522, 0x040007fc, 0x1c01f000, - 0x4df00000, 0x4203e000, 0x50000000, 0x4c380000, - 0x40087000, 0x480bc857, 0x4a007002, 0x00000000, - 0x42007000, 0x0010b7f8, 0x82080400, 0x00000000, + 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, - 0x04000005, 0x82000400, 0x00000000, 0x44080000, - 0x0401f003, 0x480bc857, 0x48087006, 0x58380001, - 0x80000540, 0x0400080c, 0x5c007000, 0x5c03e000, - 0x1c01f000, 0x4c380000, 0x42007000, 0x0010b7f8, - 0x58380001, 0x80000540, 0x04000803, 0x5c007000, - 0x1c01f000, 0x42007000, 0x0010b7f8, 0x58380001, - 0x82000580, 0x00000000, 0x04020012, 0x58380000, - 0x0c01f001, 0x0010088e, 0x0010088d, 0x0010088d, - 0x0010088d, 0x0010088d, 0x0010088d, 0x0010088d, - 0x0010088d, 0x0401fd4b, 0x58380808, 0x800409c0, - 0x04020024, 0x58380006, 0x80000540, 0x04020002, - 0x1c01f000, 0x4803c857, 0x48007002, 0x40006800, - 0x58340000, 0x80000540, 0x04020002, 0x48007005, - 0x48007006, 0x4a03b805, 0x20000000, 0x59dc0006, - 0x4a03b805, 0x30000000, 0x58340007, 0x4803b800, - 0x58340008, 0x4803b801, 0x58340004, 0x48007003, - 0x58340003, 0x48007004, 0x4803b803, 0x58340001, + 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, 0x0401f03d, - 0x0201f800, 0x001093ea, 0x0201f800, 0x0010a69d, + 0x0401f028, 0x4a007001, 0x00000002, 0x0401f03e, + 0x0201f800, 0x001091b3, 0x0201f800, 0x0010a4b8, 0x04000017, 0x4a03b805, 0x20000000, 0x59dc0006, 0x4a03b805, 0x30000000, 0x4807b800, 0x480bb801, 0x4a007003, 0x00000010, 0x480c7009, 0x42001000, - 0x00100875, 0x0201f800, 0x00105f9a, 0x58380008, + 0x001008be, 0x0201f800, 0x00105cd3, 0x58380008, 0x82000400, 0x00000004, 0x48007004, 0x4803b803, - 0x4a007001, 0x00000007, 0x0401f022, 0x0201f800, - 0x00109402, 0x42000800, 0x00000001, 0x42001000, - 0x00100875, 0x0201f800, 0x00105f76, 0x0401f7ba, + 0x4a007001, 0x00000007, 0x0401f023, 0x0201f800, + 0x001091cb, 0x42000800, 0x00000001, 0x42001000, + 0x001008be, 0x0201f800, 0x00105caf, 0x0401f7b7, 0x4c040000, 0x4c080000, 0x58380803, 0x42001000, 0x00003fff, 0x82040480, 0x00003fff, 0x04021003, - 0x40041000, 0x80000580, 0x48007003, 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, 0x4a03b805, 0x10000002, - 0x5c001000, 0x5c000800, 0x1c01f000, 0x4c040000, - 0x4c380000, 0x42007000, 0x0010b7f8, 0x59dc0806, - 0x4807c857, 0x4a03b805, 0x20000000, 0x8c040d3e, - 0x04000007, 0x8c040d08, 0x04020cca, 0x58380001, - 0x82000500, 0x00000007, 0x0c01f804, 0x5c007000, - 0x5c000800, 0x1c01f000, 0x0010087d, 0x0010091e, - 0x0010092e, 0x001005d8, 0x001005d8, 0x001005d8, - 0x001005d8, 0x001011ea, 0x4807c856, 0x82040d00, - 0x43000f80, 0x04020009, 0x58380003, 0x80000540, - 0x0400001c, 0x59dc0000, 0x4803b800, 0x59dc0001, - 0x4803b801, 0x0401f7af, 0x58380802, 0x4a000802, - 0x00000200, 0x0401f01e, 0x4807c856, 0x82040d00, - 0x43000f80, 0x04020009, 0x58380003, 0x80000540, - 0x0400000c, 0x59dc0000, 0x4803b800, 0x59dc0001, - 0x4803b801, 0x0401f7b7, 0x58380002, 0x82000400, - 0x00000002, 0x46000000, 0x00000200, 0x0401f00c, - 0x4c340000, 0x58386802, 0x59dc0000, 0x4803c857, - 0x48006807, 0x59dc0001, 0x4803c857, 0x48006808, - 0x4a006802, 0x00000100, 0x5c006800, 0x4a007001, - 0x00000000, 0x4c300000, 0x58386002, 0x0401f80c, - 0x04000009, 0x58300009, 0x82000c80, 0x0010ab4a, - 0x04021c84, 0x82000c80, 0x00020000, 0x04001c81, - 0x0801f800, 0x5c006000, 0x0401f723, 0x4833c857, - 0x803061c0, 0x04000009, 0x59a8000c, 0x80300480, - 0x04001007, 0x59a8000d, 0x80300480, 0x04021004, - 0x82000540, 0x00000001, 0x1c01f000, 0x80000580, - 0x1c01f000, 0x4803c856, 0x4dc00000, 0x42007000, - 0x0010b803, 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, 0x00100ec1, 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, 0x0401fc11, - 0x83c00580, 0x00007700, 0x04000004, 0x42038000, - 0x00007700, 0x0401f7f1, 0x805cb9c0, 0x0402001d, - 0x4200b000, 0x00000020, 0x83b8ac00, 0x00000020, - 0x0201f800, 0x0010ab20, 0x4a0370fb, 0x00000001, - 0x4a037020, 0x001010bd, 0x59a80039, 0x82000500, - 0x0000ffff, 0x48037021, 0x4a037035, 0x0010bddb, - 0x4a037030, 0x0010b410, 0x4a037031, 0x0010ac00, - 0x4a037032, 0x0010b519, 0x4a037036, 0x0010b524, - 0x59840002, 0x48037034, 0x4a037038, 0x001010b4, - 0x4a0370fb, 0x00000001, 0x4178a000, 0x4200b000, - 0x00000020, 0x83b8ac00, 0x00000000, 0x0201f800, - 0x0010ab20, 0x4200b000, 0x00000040, 0x83b8ac00, - 0x00000040, 0x0201f800, 0x0010ab20, 0x805cb9c0, - 0x04020004, 0x4a0370e4, 0xaaaaaaaa, 0x0401f003, - 0x4a0370e4, 0xa2aaaa82, 0x4a0370e5, 0xaaaaaaaa, - 0x4a0370e6, 0xaaaaaaaa, 0x4a0370fb, 0x00000000, - 0x4a0370e6, 0xaaaaaaaa, 0x42038000, 0x00007720, - 0x4a038006, 0x90000000, 0x59c00007, 0x8c00051e, - 0x02020800, 0x001005d8, 0x42038000, 0x00007700, - 0x4a038006, 0x90000000, 0x59c00007, 0x8c00051e, - 0x02020800, 0x001005d8, 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, - 0x000207a1, 0x5c027000, 0x5c026000, 0x1c01f000, - 0x4d300000, 0x4d2c0000, 0x4d340000, 0x4d400000, - 0x4cfc0000, 0x4d380000, 0x4d3c0000, 0x4d440000, - 0x4d4c0000, 0x4d480000, 0x4c5c0000, 0x4c600000, - 0x4c640000, 0x4cc80000, 0x4ccc0000, 0x4cf00000, - 0x4cf40000, 0x4cf80000, 0x4cfc0000, 0x4d000000, - 0x4d040000, 0x0201f800, 0x00020015, 0x5c020800, - 0x5c020000, 0x5c01f800, 0x5c01f000, 0x5c01e800, - 0x5c01e000, 0x5c019800, 0x5c019000, 0x5c00c800, - 0x5c00c000, 0x5c00b800, 0x5c029000, 0x5c029800, - 0x5c028800, 0x5c027800, 0x5c027000, 0x5c01f800, - 0x5c028000, 0x5c026800, 0x5c025800, 0x5c026000, - 0x1c01f000, 0x493bc857, 0x0201f000, 0x00020044, - 0x83300500, 0x1f000000, 0x04000008, 0x81326580, - 0x80000130, 0x82000c80, 0x00000014, 0x02021800, - 0x001005d8, 0x0c01f013, 0x83300500, 0x000000ff, - 0x82000c80, 0x00000007, 0x02021800, 0x001005d8, - 0x0c01f025, 0x1c01f000, 0x82000d00, 0xc0000038, - 0x02020800, 0x001005d0, 0x0201f800, 0x001005d8, - 0x00000000, 0x00000048, 0x00000054, 0x00000053, - 0x00100a9b, 0x00100abf, 0x00100aba, 0x00100adf, - 0x00100aa6, 0x00100ab2, 0x00100a9b, 0x00100ada, - 0x00100b1a, 0x00100a9b, 0x00100a9b, 0x00100a9b, - 0x00100a9b, 0x00100b1d, 0x00100b23, 0x00100b34, - 0x00100b45, 0x00100a9b, 0x00100b4e, 0x00100b5a, - 0x00100a9b, 0x00100a9b, 0x00100a9b, 0x0201f800, - 0x001005d8, 0x00100aa4, 0x00100bff, 0x00100aec, - 0x00100b0f, 0x00100aa4, 0x00100aa4, 0x00100aa4, - 0x0201f800, 0x001005d8, 0x4803c856, 0x59300004, - 0x8c00053e, 0x04020005, 0x42027000, 0x00000055, - 0x0201f000, 0x000207a1, 0x0201f800, 0x00106f60, - 0x040007fa, 0x1c01f000, 0x4803c856, 0x0401f8a9, - 0x40002800, 0x41782000, 0x42027000, 0x00000056, - 0x0201f000, 0x000207a1, 0x4803c856, 0x42027000, - 0x00000057, 0x0201f000, 0x000207a1, 0x4803c856, - 0x59300007, 0x8c00051a, 0x04020010, 0x59325808, - 0x812e59c0, 0x04000014, 0x592c0408, 0x8c00051c, - 0x04020003, 0x4a026011, 0xffffffff, 0x59300004, - 0x8c00053e, 0x04020009, 0x42027000, 0x00000048, - 0x0201f000, 0x000207a1, 0x59325808, 0x4a025a06, - 0x00000007, 0x0401f7f4, 0x0201f800, 0x00106f60, - 0x040007f6, 0x1c01f000, 0x4803c856, 0x83300500, - 0x00ffffff, 0x0201f000, 0x001064d7, 0x1c01f000, - 0x4c040000, 0x59b808ea, 0x82040d00, 0x00000007, - 0x82040580, 0x00000003, 0x04000004, 0x42000000, - 0x60000000, 0x0401f8ab, 0x5c000800, 0x1c01f000, - 0x0401f8f9, 0x59325808, 0x812e59c0, 0x04000018, - 0x592c0204, 0x82000500, 0x000000ff, 0x82000d80, - 0x00000029, 0x04020012, 0x59300203, 0x82000580, - 0x00000003, 0x0400000b, 0x59300807, 0x84040d26, - 0x48066007, 0x0201f800, 0x00020086, 0x4a03900d, - 0x00000040, 0x4a0370e5, 0x00000008, 0x1c01f000, - 0x0201f800, 0x00106f60, 0x040007f4, 0x59880052, - 0x80000000, 0x48031052, 0x4a03900d, 0x00000040, - 0x42000000, 0xc0000000, 0x0401f05a, 0x42007800, - 0x0010bde2, 0x42002000, 0x00003000, 0x42003000, - 0x00000105, 0x0201f800, 0x00105e04, 0x4a0370e4, - 0x02000000, 0x1c01f000, 0x4933c857, 0x0201f000, - 0x0002077d, 0x41300800, 0x800409c0, 0x02020800, - 0x001005d8, 0x0201f800, 0x001005d0, 0x4933c857, - 0x813261c0, 0x02000800, 0x001005d8, 0x0401f835, - 0x40002800, 0x0201f800, 0x0010a99c, 0x0401f8ae, - 0x04000007, 0x59326809, 0x59340200, 0x8c00050e, - 0x59300414, 0x02020800, 0x001092ce, 0x1c01f000, - 0x4933c857, 0x813261c0, 0x02000800, 0x001005d8, - 0x0401f8a1, 0x0400000b, 0x59325808, 0x0201f800, - 0x00109037, 0x04000007, 0x592c0208, 0x8400054e, - 0x48025a08, 0x417a7800, 0x0201f800, 0x00108be3, - 0x1c01f000, 0x485fc857, 0x5c000000, 0x4d780000, - 0x4203e000, 0x50000000, 0x4200b800, 0x00008005, - 0x0201f000, 0x001005dd, 0x4933c857, 0x83300480, - 0x00000020, 0x02021800, 0x001005d8, 0x83300c00, - 0x0010b8cc, 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, - 0x0401febc, 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, 0x0010b804, - 0x50080000, 0x80000540, 0x04020005, 0x4a0370e5, - 0x00000003, 0x4a0370e4, 0x00000300, 0x80000000, - 0x44001000, 0x42001000, 0x00000400, 0x59b800ea, - 0x8c000510, 0x0400000c, 0x0401ffd5, 0x82100480, - 0x00000008, 0x04001007, 0x4c040000, 0x4c080000, - 0x0401fe88, 0x5c001000, 0x5c000800, 0x0401f020, - 0x59b800ea, 0x8c000516, 0x0402001d, 0x4a0370e4, - 0x00300000, 0x480770e1, 0x42001000, 0x0000ff00, - 0x80081040, 0x04000012, 0x59b808e4, 0x8c040d28, - 0x040207fc, 0x42001000, 0x0010b804, 0x50080000, - 0x80000040, 0x04020005, 0x4a0370e5, 0x00000002, - 0x4a0370e4, 0x00000200, 0x02001800, 0x001005d8, - 0x44001000, 0x8c040d2c, 0x1c01f000, 0x41f80000, - 0x50000000, 0x0201f800, 0x001005d8, 0x80081040, - 0x040207d3, 0x41f80000, 0x50000000, 0x0201f800, - 0x001005d8, 0x4d380000, 0x59300c06, 0x82040580, - 0x00000009, 0x04020006, 0x42027000, 0x00000047, - 0x0201f800, 0x000207a1, 0x80000580, 0x5c027000, - 0x1c01f000, 0x4c500000, 0x4a03900d, 0x00000001, - 0x59c8a020, 0x4a03900d, 0x00000002, 0x59c80820, - 0x8c50a52e, 0x04000002, 0x900409c0, 0x82040d00, - 0x0000ffff, 0x0201f800, 0x00105dd7, 0x02000800, - 0x001005d8, 0x4933c857, 0x8250a500, 0xff000000, - 0x82500580, 0x05000000, 0x04000003, 0x82000540, - 0x00000001, 0x5c00a000, 0x1c01f000, 0x0401ffe6, - 0x4933c857, 0x59300406, 0x82000580, 0x00000000, - 0x04000040, 0x59c82021, 0x4a03900d, 0x00000001, - 0x59c82821, 0x82142d00, 0x0000ffff, 0x59325808, - 0x812e59c0, 0x04000037, 0x59326809, 0x0201f800, - 0x001048d9, 0x02020800, 0x001092b6, 0x599c0019, - 0x8c00050c, 0x04020018, 0x0201f800, 0x001048d9, - 0x04020015, 0x59300811, 0x4807c857, 0x592c0408, - 0x8c00051c, 0x0402000e, 0x8400055c, 0x48025c08, - 0x592c0a04, 0x82040d00, 0x000000ff, 0x82040580, - 0x00000048, 0x04000004, 0x82040580, 0x00000018, - 0x04020003, 0x59300811, 0x48065803, 0x4a026011, - 0x7fffffff, 0x48166013, 0x0201f800, 0x001010dd, - 0x04020014, 0x0401f9fd, 0x40280000, 0x4802600d, - 0x04000005, 0x4832600b, 0x50200000, 0x4802600a, - 0x4822600c, 0x59300414, 0x8c00051c, 0x04020004, - 0x599c0019, 0x8c00050c, 0x0402086e, 0x4a03900d, - 0x00000040, 0x4a0370e5, 0x00000008, 0x1c01f000, - 0x59880052, 0x80000000, 0x48031052, 0x4a03900d, - 0x00000040, 0x42000000, 0xc0000000, 0x0401f71d, - 0x4cf80000, 0x58f40000, 0x8001f540, 0x0401f820, - 0x41781800, 0x0401f8e4, 0x04020014, 0x44140800, - 0x0401f82a, 0x04000011, 0x40043800, 0x42001800, - 0x00000001, 0x40142000, 0x0401f8db, 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, - 0x001005d8, 0x4801ec01, 0x0401f00b, 0x58f80401, - 0x82000480, 0x00000002, 0x02001800, 0x001005d8, - 0x4801f401, 0x82000580, 0x00000002, 0x04020002, - 0x0401f809, 0x58f40202, 0x80000040, 0x4801ea02, - 0x02000800, 0x001005d8, 0x82000580, 0x00000001, - 0x1c01f000, 0x4d2c0000, 0x40fa5800, 0x0201f800, - 0x001007f4, 0x4979e800, 0x4179f000, 0x5c025800, - 0x1c01f000, 0x80f5e9c0, 0x04000009, 0x80f9f1c0, - 0x04020ff5, 0x4d2c0000, 0x40f65800, 0x0201f800, - 0x001007f4, 0x4179e800, 0x5c025800, 0x1c01f000, - 0x4cf40000, 0x59300807, 0x82040500, 0x00003100, + 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, 0x001005d8, 0x82000580, + 0x8001ed40, 0x02000800, 0x00100615, 0x82000580, 0xffffffff, 0x04000029, 0x58f40201, 0x82000580, - 0x0000dcb3, 0x02020800, 0x001005d8, 0x58f40a02, - 0x82040500, 0x0000fffe, 0x04000003, 0x0401ff89, + 0x0000dcb3, 0x02020800, 0x00100615, 0x58f40a02, + 0x82040500, 0x0000fffe, 0x04000003, 0x0401ff86, 0x58f40a02, 0x82040480, 0x0000000f, 0x04021059, 0x80040800, 0x4805ea02, 0x82040580, 0x00000008, 0x0400005d, 0x82040480, 0x00000008, 0x0400100a, - 0x58f40000, 0x8001ed40, 0x02000800, 0x001005d8, + 0x58f40000, 0x8001ed40, 0x02000800, 0x00100615, 0x58f40201, 0x82000580, 0x0000ddb9, 0x02020800, - 0x001005d8, 0x58f40401, 0x82000c00, 0x00000002, + 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, 0x001007d3, 0x04000025, + 0x4d2c0000, 0x0201f800, 0x00100819, 0x04000025, 0x492e601f, 0x4a025a01, 0x0000dcb3, 0x59300008, - 0x80001d40, 0x02000800, 0x001005d8, 0x580c080f, + 0x80001d40, 0x02000800, 0x00100615, 0x580c080f, 0x48065803, 0x59301811, 0x40040000, 0x800c0580, 0x0402000d, 0x497a5a02, 0x4a025c01, 0x00000004, 0x0401f011, 0x4a0370e4, 0x00020000, 0x40000000, - 0x40000000, 0x80081040, 0x02000800, 0x001005d8, + 0x40000000, 0x80081040, 0x02000800, 0x00100615, 0x0401f7d6, 0x4a025a02, 0x00000001, 0x4a025c01, 0x00000006, 0x497a5804, 0x400c0000, 0x80040480, 0x48025805, 0x412de800, 0x5c025800, 0x0401f7a9, 0x5c025800, 0x4a02601f, 0xffffffff, 0x0401f7c3, - 0x4d2c0000, 0x58f65800, 0x0201f800, 0x001007f4, - 0x40f65800, 0x0201f800, 0x001007f4, 0x5c025800, - 0x0401f7f5, 0x4d2c0000, 0x0201f800, 0x001007d3, + 0x4d2c0000, 0x58f65800, 0x0201f800, 0x0010083a, + 0x40f65800, 0x0201f800, 0x0010083a, 0x5c025800, + 0x0401f7f5, 0x4d2c0000, 0x0201f800, 0x00100819, 0x040007f8, 0x4a025a01, 0x0000ddb9, 0x4a025c01, 0x00000002, 0x492de800, 0x412de800, 0x5c025800, - 0x0401f7a5, 0x0401ff33, 0x82f40400, 0x00000004, + 0x0401f7a5, 0x0401ff30, 0x82f40400, 0x00000004, 0x800c0400, 0x40000800, 0x50040000, 0x80100580, 0x04000016, 0x82040c00, 0x00000002, 0x80081040, 0x040207fa, 0x80f9f1c0, 0x04000011, 0x58f41202, @@ -893,202 +910,205 @@ uint32_t risc_code01[] = { 0x04000006, 0x82040c00, 0x00000002, 0x80081040, 0x040207fa, 0x0401f002, 0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fd, 0x4cf40000, 0x4cf80000, - 0x4001e800, 0x592c0a06, 0x800409c0, 0x0402001d, - 0x82f40580, 0xffffffff, 0x04000017, 0x58f40201, - 0x82000580, 0x0000dcb3, 0x02020800, 0x001005d8, + 0x4001e800, 0x592c0a06, 0x800409c0, 0x04020021, + 0x82f40580, 0xffffffff, 0x0400001b, 0x58f40201, + 0x82000580, 0x0000dcb3, 0x02020800, 0x00100615, 0x58f40000, 0x8001f540, 0x04000006, 0x58f80201, - 0x82000580, 0x0000ddb9, 0x02020800, 0x001005d8, - 0x41783800, 0x0401f839, 0x04020006, 0x0401ff32, - 0x497a601f, 0x5c01f000, 0x5c01e800, 0x1c01f000, - 0x0401ff2d, 0x4a025a06, 0x00000011, 0x0401f7f9, - 0x82f40580, 0xffffffff, 0x04020f27, 0x0401f7f5, + 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, 0x0402001f, 0x82f40580, 0xffffffff, - 0x04000019, 0x58f40201, 0x82000580, 0x0000dcb3, - 0x02020800, 0x001005d8, 0x58f40000, 0x8001f540, + 0x00000001, 0x04020020, 0x82f40580, 0xffffffff, + 0x0400001a, 0x58f40201, 0x82000580, 0x0000dcb3, + 0x02020800, 0x00100615, 0x58f40000, 0x8001f540, 0x04000006, 0x58f80201, 0x82000580, 0x0000ddb9, - 0x02020800, 0x001005d8, 0x41783800, 0x0401f813, - 0x04020008, 0x0401ff0c, 0x42000800, 0x00000001, - 0x497a601f, 0x5c01f000, 0x5c01e800, 0x1c01f000, - 0x0401ff05, 0x42000800, 0x00000011, 0x0401f7f9, - 0x4c040000, 0x82f40580, 0xffffffff, 0x04020efe, - 0x5c000800, 0x0401f7f3, 0x4803c856, 0x401c2000, - 0x41781800, 0x0401ff8c, 0x0402002c, 0x58f42003, - 0x42001800, 0x00000001, 0x0401ff87, 0x04020027, - 0x0401feb8, 0x40082800, 0x82f40400, 0x00000004, - 0x40003000, 0x50182000, 0x40100000, 0x801c0580, - 0x04000005, 0x42001800, 0x00000001, 0x0401ff7a, - 0x0402001a, 0x82183400, 0x00000002, 0x80142840, - 0x040207f5, 0x80f9f1c0, 0x04000013, 0x58f42a02, - 0x82142c80, 0x00000007, 0x82f80400, 0x00000003, - 0x40003000, 0x50182000, 0x40100000, 0x801c0580, - 0x04000005, 0x42001800, 0x00000001, 0x0401ff66, - 0x04020006, 0x82183400, 0x00000002, 0x80142840, - 0x040207f5, 0x1c01f000, 0x82000540, 0x00000001, - 0x0401f7fd, 0x0201f800, 0x001005d8, 0x58380207, - 0x8c000502, 0x040007fc, 0x50200000, 0x80387c00, - 0x583c2800, 0x583c2001, 0x58380404, 0x80001540, - 0x04020002, 0x58381407, 0x58c83401, 0x58380c08, - 0x59303807, 0x497a6012, 0x497a6013, 0x0201f000, - 0x000200be, 0x592c0408, 0x8c000502, 0x040007ea, - 0x592c0409, 0x80000540, 0x040007e7, 0x82000c80, - 0x00000002, 0x04001011, 0x58380001, 0x80007540, - 0x02000800, 0x001005d8, 0x58380204, 0x82000500, - 0x0000000f, 0x82000400, 0x001010bd, 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, 0x000200c6, 0x80204000, 0x50201800, - 0x800c19c0, 0x0402000c, 0x58380001, 0x80007540, - 0x02000800, 0x001005d8, 0x58380204, 0x82000500, - 0x0000000f, 0x82000400, 0x001010bd, 0x50004000, - 0x50201800, 0x483a600b, 0x480e600a, 0x4822600c, - 0x0201f000, 0x000200c6, 0x4803c856, 0x592c0208, - 0x8c00051e, 0x04020017, 0x50200000, 0x80306c00, - 0x40240000, 0x0c01f001, 0x00100e46, 0x00100e46, - 0x00100e4f, 0x00100e46, 0x00100e46, 0x00100e46, - 0x00100e46, 0x00100e46, 0x00100e4f, 0x00100e46, - 0x00100e4f, 0x00100e46, 0x00100e46, 0x00100e4f, - 0x00100e46, 0x00100e46, 0x0201f800, 0x001005d8, - 0x8400051e, 0x48025a08, 0x50200000, 0x80306c00, - 0x58343801, 0x481e600f, 0x0401f007, 0x58341802, - 0x58342800, 0x58343801, 0x480e6010, 0x4816600e, - 0x481e600f, 0x0401f246, 0x4933c857, 0x5931f808, - 0x59300a06, 0x800409c0, 0x04000005, 0x80040906, - 0x04020002, 0x80040800, 0x4805fc06, 0x4a026206, - 0x00000002, 0x592c0409, 0x82000500, 0x00000008, - 0x0400000b, 0x0401f834, 0x59300203, 0x82000580, - 0x00000004, 0x04020005, 0x42027000, 0x00000048, - 0x0201f800, 0x000207a1, 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, - 0x000207a1, 0x5c01f800, 0x1c01f000, 0x58fdf809, - 0x0401f7ec, 0x4933c857, 0x59b808ea, 0x82040d00, - 0x00000007, 0x82040580, 0x00000000, 0x0400001e, - 0x82040580, 0x00000003, 0x0400001b, 0x59300406, - 0x4c000000, 0x4a026406, 0x00000000, 0x42003000, - 0x00000041, 0x42000000, 0x50000000, 0x41300800, - 0x4c180000, 0x0401fce7, 0x5c003000, 0x0400000b, - 0x42000000, 0x0000001e, 0x80000040, 0x040207ff, - 0x80183040, 0x040207f4, 0x42000000, 0x40000000, - 0x41300800, 0x0401fcdb, 0x5c000000, 0x48026406, - 0x1c01f000, 0x59300007, 0x84000500, 0x48026007, - 0x0401f7fc, 0x59c00007, 0x4a038006, 0x30000000, - 0x40000000, 0x59c00007, 0x8c00050a, 0x040207fe, + 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, - 0x4dc00000, 0x4a0370e8, 0x00000000, 0x42038000, - 0x00007720, 0x0401fff0, 0x42038000, 0x00007700, - 0x0401ffed, 0x0201f800, 0x0010513b, 0x04020013, - 0x4a038891, 0x0000ffff, 0x497b8880, 0x497b8892, - 0x42001000, 0x00000190, 0x40000000, 0x40000000, - 0x80081040, 0x040207fd, 0x42000000, 0x0010b8a6, - 0x0201f800, 0x0010aa47, 0x0401f80e, 0x5c038000, - 0x0201f000, 0x00105258, 0x0401f82d, 0x42000000, - 0x0010b8a7, 0x0201f800, 0x0010aa47, 0x0401f805, - 0x48178892, 0x480b8880, 0x5c038000, 0x1c01f000, - 0x496fc857, 0x836c0580, 0x00000003, 0x0402000b, - 0x4c080000, 0x4c0c0000, 0x42001000, 0x00008048, - 0x42001800, 0x0000ffff, 0x0201f800, 0x00103a3e, - 0x5c001800, 0x5c001000, 0x42000800, 0x0000003c, - 0x0201f800, 0x00101345, 0x59a8006c, 0x80000540, - 0x04000006, 0x59a8106d, 0x800811c0, 0x04000003, - 0x0201f800, 0x00101aaf, 0x4a038891, 0x0000ffff, - 0x4a03900d, 0x00000040, 0x0201f800, 0x0010098e, - 0x4a0370e8, 0x00000001, 0x1c01f000, 0x5c000000, - 0x4c000000, 0x4803c857, 0x59c41080, 0x497b8880, - 0x59c42892, 0x497b8892, 0x0201f800, 0x0010513b, - 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, 0x00101937, 0x50001800, 0x820c1d00, - 0x00000001, 0x04000005, 0x80102040, 0x040207f7, - 0x5c002000, 0x0401f7f0, 0x5c002000, 0x0401f7ec, - 0x4803c856, 0x1c01f000, 0x4d2c0000, 0x59325808, - 0x592c0a04, 0x4807c857, 0x82040d00, 0x000000ff, - 0x82040500, 0x0000000f, 0x0c01f001, 0x00100f67, - 0x00100f67, 0x00100f67, 0x00100f7f, 0x00100f67, - 0x00100f67, 0x00100f67, 0x00100f67, 0x00100f67, - 0x00100f7f, 0x00100f67, 0x00100f69, 0x00100f67, - 0x00100f67, 0x00100f67, 0x00100f67, 0x0201f800, - 0x001005d8, 0x82040580, 0x0000003b, 0x02020800, - 0x001005d8, 0x592c020a, 0x8c000500, 0x0400005f, - 0x592c1a07, 0x82040500, 0x0000000f, 0x82000400, - 0x001010bd, 0x50001000, 0x50080000, 0x59302013, + 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, - 0x48126012, 0x5c025800, 0x1c01f000, 0x82040500, - 0x0000000f, 0x82000400, 0x001010bd, 0x50001000, - 0x50080000, 0x592c1a07, 0x4802600a, 0x492e600b, - 0x480a600c, 0x480e600d, 0x497a6012, 0x0401f7f2, - 0x8c040d00, 0x04020041, 0x82040d00, 0x00000080, - 0x0400003e, 0x0201f000, 0x000200cf, 0x59300013, - 0x59301012, 0x80080580, 0x0402000c, 0x42007800, - 0x80000005, 0x592c1208, 0x82080500, 0xffff7fff, - 0x48025a08, 0x8c08151e, 0x0402002d, 0x823c7d40, - 0x00000020, 0x0401f02a, 0x480bc857, 0x42000000, - 0x0010b851, 0x0201f800, 0x0010aa47, 0x59300414, - 0x4803c857, 0x8c000514, 0x04020007, 0x599c1819, - 0x8c0c1d12, 0x04020004, 0x820c1d40, 0x00000001, - 0x0401f01d, 0x59302013, 0x0401f92b, 0x0402001a, - 0x42007800, 0x80000005, 0x5930500d, 0x592c0208, - 0x4803c857, 0x8c00051e, 0x04020005, 0x823c7d40, - 0x00000020, 0x5930400c, 0x0401f004, 0x8400051e, - 0x48025a08, 0x0401f8da, 0x50201800, 0x480e600a, - 0x4832600b, 0x4822600c, 0x482a600d, 0x480fc857, - 0x4833c857, 0x4823c857, 0x482bc857, 0x80000580, - 0x483e6004, 0x1c01f000, 0x0201f800, 0x001005d8, + 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, 0x001005d8, 0x0201f800, 0x00109037, - 0x02000800, 0x001005d8, 0x59325808, 0x4d3c0000, - 0x4d400000, 0x59300004, 0x4803c857, 0x4c000000, - 0x0201f800, 0x00106dc3, 0x0201f800, 0x00106b8a, - 0x5c000000, 0x8c000516, 0x04000010, 0x592c000f, - 0x4803c857, 0x48025807, 0x41780800, 0x42028000, - 0x00000002, 0x0201f800, 0x00104e70, 0x4a025c06, - 0x0000ffff, 0x0201f800, 0x000202da, 0x0201f800, - 0x00107911, 0x0401f015, 0x4a026203, 0x00000002, - 0x592c0208, 0x8400054e, 0x48025a08, 0x59300406, - 0x82000580, 0x00000006, 0x04020009, 0x811800ca, - 0x81c80c00, 0x58040939, 0x592c000d, 0x80040480, - 0x592c080f, 0x80040480, 0x4802580b, 0x417a7800, - 0x0201f800, 0x00108be3, 0x5c028000, 0x5c027800, - 0x5c025800, 0x1c01f000, 0x4933c857, 0x4d2c0000, - 0x59900004, 0x81300580, 0x02020800, 0x001005d8, - 0x0201f800, 0x00109037, 0x02000800, 0x001005d8, - 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, 0x0400002f, 0x82080500, 0x40008000, - 0x040007f8, 0x800409c0, 0x0402002a, 0x811a31c0, - 0x04000028, 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, 0x0401f00d, + 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, 0x040007f9, - 0x59d01006, 0x82080500, 0x00006000, 0x040207f5, + 0x00006000, 0x04000007, 0x8c08151e, 0x040007f7, + 0x59d01006, 0x82080500, 0x00006000, 0x040207f3, 0x83d3a400, 0x00000020, 0x80040800, 0x82040480, - 0x00000005, 0x040017bf, 0x5c03a000, 0x1c01f000, + 0x00000005, 0x040017bd, 0x5c03a000, 0x1c01f000, 0x491bc857, 0x49d3c857, 0x4dd00000, 0x41780800, 0x8007a0ca, 0x83d3a400, 0x00007600, 0x4a03a005, 0x80000001, 0x59d00006, 0x83d3a400, 0x00000020, @@ -1105,19 +1125,19 @@ uint32_t risc_code01[] = { 0x80204000, 0x50200000, 0x80000540, 0x04000003, 0x80285040, 0x1c01f000, 0x58300001, 0x80000540, 0x0400000e, 0x4802600b, 0x40006000, 0x58300204, - 0x82000500, 0x0000000f, 0x82000400, 0x001010bd, - 0x50004000, 0x802041c0, 0x02000800, 0x001005d8, + 0x82000500, 0x0000000f, 0x82000400, 0x0010110d, + 0x50004000, 0x802041c0, 0x02000800, 0x00100615, 0x80285040, 0x1c01f000, 0x40005000, 0x1c01f000, 0x00000005, 0x00000008, 0x0000000b, 0x0000000e, 0x00000011, 0x00000000, 0x00000000, 0x0000000b, - 0x00000000, 0x00000000, 0x00000000, 0x001010b8, - 0x001010b7, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x001010b8, 0x001010b7, 0x001010b4, - 0x001010b8, 0x001010b7, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x001010b8, + 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, 0x001010b8, 0x001010b8, 0x001010b8, - 0x00000000, 0x001010b8, 0x00000000, 0x00000000, + 0x00000000, 0x00101108, 0x00101108, 0x00101108, + 0x00000000, 0x00101108, 0x00000000, 0x00000000, 0x00000000, 0x4813c857, 0x492fc857, 0x4933c857, 0x48126012, 0x592c5207, 0x802851c0, 0x0400004a, 0x412c6000, 0x0401f84b, 0x04000009, 0x82240580, @@ -1130,34 +1150,34 @@ uint32_t risc_code01[] = { 0x80285040, 0x0400002c, 0x80204000, 0x50200000, 0x80000540, 0x0402000a, 0x58300001, 0x80006540, 0x04000025, 0x58300204, 0x82004d00, 0x0000000f, - 0x82244400, 0x001010bd, 0x50204000, 0x592c0208, + 0x82244400, 0x0010110d, 0x50204000, 0x592c0208, 0x8400051e, 0x48025a08, 0x0401f013, 0x80102080, 0x80102000, 0x48126010, 0x4813c857, 0x58080802, - 0x40100000, 0x80042480, 0x02001800, 0x001005d8, + 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, - 0x001010bd, 0x82000500, 0x000000ff, 0x82000580, + 0x0010110d, 0x82000500, 0x000000ff, 0x82000580, 0x00000029, 0x0402001b, 0x50204000, 0x592c0409, - 0x80000540, 0x02000800, 0x001005d8, 0x82000c80, + 0x80000540, 0x02000800, 0x00100615, 0x82000c80, 0x00000002, 0x04001011, 0x58300001, 0x80006540, - 0x02000800, 0x001005d8, 0x58300204, 0x82000500, - 0x0000000f, 0x82000400, 0x001010bd, 0x50004000, + 0x02000800, 0x00100615, 0x58300204, 0x82000500, + 0x0000000f, 0x82000400, 0x0010110d, 0x50004000, 0x40040000, 0x800409c0, 0x04000006, 0x82040c80, 0x00000005, 0x040217f1, 0x80204400, 0x80000580, 0x1c01f000, 0x59e00004, 0x8c00050e, 0x02020000, - 0x00100903, 0x1c01f000, 0x4c5c0000, 0x59e4b800, + 0x00100951, 0x1c01f000, 0x4c5c0000, 0x59e4b800, 0x485fc857, 0x825c0500, 0x0000001f, 0x04000004, - 0x59e40862, 0x0201f800, 0x001005d8, 0x825c0500, - 0x000000e0, 0x02000800, 0x001005d8, 0x8c5cbd0e, + 0x59e40862, 0x0201f800, 0x00100615, 0x825c0500, + 0x000000e0, 0x02000800, 0x00100615, 0x8c5cbd0e, 0x04020807, 0x8c5cbd0c, 0x04020809, 0x8c5cbd0a, 0x04020878, 0x5c00b800, 0x1c01f000, 0x4803c856, 0x4a03c800, 0x00000080, 0x1c01f000, 0x4d2c0000, - 0x42007800, 0x0010b8ec, 0x583c0001, 0x583c0802, - 0x80040540, 0x0400003f, 0x42000800, 0x0010b7f7, + 0x42007800, 0x0010b6eb, 0x583c0001, 0x583c0802, + 0x80040540, 0x0400003f, 0x42000800, 0x0010b5f5, 0x50065800, 0x592c0002, 0x82000580, 0x00000000, 0x0400000e, 0x59e40850, 0x59e41853, 0x400c0000, 0x80040400, 0x59e40852, 0x4807c857, 0x80041480, @@ -1170,12 +1190,12 @@ uint32_t risc_code01[] = { 0x04000007, 0x592c1007, 0x480bc857, 0x583c0003, 0x4803c857, 0x80080480, 0x04001003, 0x583c1001, 0x480bc857, 0x583c0802, 0x480bc857, 0x4807c857, - 0x4a025801, 0x00000000, 0x4a025809, 0x001011bc, + 0x4a025801, 0x00000000, 0x4a025809, 0x0010120c, 0x480a5807, 0x48065808, 0x59e40053, 0x48025804, - 0x412c1000, 0x492fc857, 0x0201f800, 0x00100858, + 0x412c1000, 0x492fc857, 0x0201f800, 0x001008a1, 0x5c025800, 0x4a03c800, 0x00000040, 0x1c01f000, - 0x42007800, 0x0010b7f7, 0x503c7800, 0x4a007802, - 0x00000100, 0x42007800, 0x0010b8ec, 0x583c0000, + 0x42007800, 0x0010b5f5, 0x503c7800, 0x4a007802, + 0x00000100, 0x42007800, 0x0010b6eb, 0x583c0000, 0x4803c857, 0x82000d80, 0x00000001, 0x04000004, 0x80000000, 0x48007800, 0x0401f019, 0x49787800, 0x583c1806, 0x583c0005, 0x800c1800, 0x480c7806, @@ -1183,73 +1203,73 @@ uint32_t risc_code01[] = { 0x800409c0, 0x0400000e, 0x583c0008, 0x80000000, 0x48007808, 0x80040580, 0x04020009, 0x49787808, 0x583c2006, 0x42001800, 0x00000001, 0x42001000, - 0x00008028, 0x0201f800, 0x00103a3e, 0x1c01f000, - 0x4a03c800, 0x00000020, 0x0201f800, 0x0010aa40, + 0x00008028, 0x0201f800, 0x00103857, 0x1c01f000, + 0x4a03c800, 0x00000020, 0x0201f800, 0x0010a867, 0x59e40000, 0x1c01f000, 0x4d2c0000, 0x4a007001, 0x00000000, 0x82040d00, 0x43000f80, 0x02020800, - 0x001005d8, 0x58380009, 0x4803c00f, 0x0201f800, - 0x00109402, 0x583a5808, 0x592c0000, 0x48007008, + 0x00100615, 0x58380009, 0x4803c00f, 0x0201f800, + 0x001091cb, 0x583a5808, 0x592c0000, 0x48007008, 0x800001c0, 0x04020002, 0x49787007, 0x0201f800, - 0x001007f4, 0x5c025800, 0x0201f000, 0x0010087d, + 0x0010083a, 0x5c025800, 0x0201f000, 0x001008c6, 0x4803c856, 0x4c3c0000, 0x4d2c0000, 0x4d300000, - 0x5830000a, 0x80025d40, 0x02000800, 0x001005d8, - 0x592e6008, 0x4c300000, 0x0201f800, 0x0010941a, - 0x5c006000, 0x02000800, 0x001005d8, 0x58300002, + 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, - 0x00100858, 0x0401f00c, 0x4a025a06, 0x00000002, - 0x4c300000, 0x0201f800, 0x000202da, 0x5c006000, - 0x40325800, 0x0201f800, 0x001007f4, 0x0201f800, - 0x0002077d, 0x5c026000, 0x5c025800, 0x5c007800, + 0x001008a1, 0x0401f00c, 0x4a025a06, 0x00000002, + 0x4c300000, 0x0201f800, 0x00020381, 0x5c006000, + 0x40325800, 0x0201f800, 0x0010083a, 0x0201f800, + 0x000208b4, 0x5c026000, 0x5c025800, 0x5c007800, 0x1c01f000, 0x4803c856, 0x4d2c0000, 0x4d300000, - 0x42007000, 0x0010b7f8, 0x58380801, 0x82040580, + 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, 0x001005d8, 0x5830000a, + 0x803061c0, 0x02000800, 0x00100615, 0x5830000a, 0x812c0580, 0x04000004, 0x40305000, 0x58306000, 0x0401f7f8, 0x40280000, 0x80300580, 0x58300000, 0x04000006, 0x48005000, 0x800001c0, 0x04020007, 0x48287005, 0x0401f005, 0x800001c0, 0x04020002, 0x48007005, 0x48007006, 0x40325800, 0x0201f800, - 0x001007f4, 0x42007000, 0x0010b7f8, 0x58380001, - 0x82000580, 0x00000000, 0x02000800, 0x0010087d, + 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, 0x0010d1c0, - 0x4a039010, 0x0010d1c0, 0x4a039015, 0x0000007f, + 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, 0x001012a8, 0x001012a6, - 0x00105999, 0x001012a6, 0x001012aa, 0x001012a6, - 0x001012aa, 0x001012aa, 0x001012a6, 0x001012a6, - 0x001012a6, 0x001012a6, 0x001012aa, 0x001012a6, - 0x001012aa, 0x001012a6, 0x0201f800, 0x001005d8, + 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, - 0x0010aa03, 0x0401f006, 0x82040500, 0x007f0000, - 0x04000006, 0x0201f800, 0x0010a9d5, 0x0201f800, - 0x00106eb3, 0x0401f02b, 0x82040500, 0x00000014, - 0x04000014, 0x0201f800, 0x0010aa32, 0x836c0580, - 0x00000003, 0x0400000d, 0x0201f800, 0x0010513b, - 0x04000004, 0x0201f800, 0x0010411d, 0x0401f007, + 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, 0x001050a2, 0x0401f817, 0x0401f015, + 0x0201f800, 0x00104d76, 0x0401f817, 0x0401f015, 0x82040500, 0x00001c00, 0x04000005, 0x0201f800, - 0x0010aa11, 0x0401f810, 0x0401f00e, 0x82040500, - 0x00000140, 0x04000005, 0x0201f800, 0x0010aa24, + 0x0010a838, 0x0401f810, 0x0401f00e, 0x82040500, + 0x00000140, 0x04000005, 0x0201f800, 0x0010a84b, 0x0401f809, 0x0401f007, 0x82040500, 0x00008000, - 0x04000004, 0x0201f800, 0x0010a9fc, 0x0401f802, + 0x04000004, 0x0201f800, 0x0010a823, 0x0401f802, 0x1c01f000, 0x4c0c0000, 0x4c100000, 0x4c140000, - 0x0201f800, 0x00100ec9, 0x5c002800, 0x5c002000, + 0x0201f800, 0x00100f17, 0x5c002800, 0x5c002000, 0x5c001800, 0x1c01f000, 0x4803c856, 0x59a80804, 0x59a8002b, 0x82000500, 0xfffff000, 0x80040540, 0x4803502b, 0x59a8002f, 0x82000500, 0xfffff000, @@ -1272,35 +1292,35 @@ uint32_t risc_code01[] = { 0x801020c2, 0x82100480, 0x00000110, 0x80000080, 0x80002000, 0x800800d0, 0x80140540, 0x80100540, 0x48039035, 0x1c01f000, 0x59c80815, 0x0201f800, - 0x001005d0, 0x82040d00, 0x0000007c, 0x48079000, + 0x0010060d, 0x82040d00, 0x0000007c, 0x48079000, 0x59c80000, 0x80040500, 0x040207fe, 0x8c040d04, 0x04000003, 0x59c80035, 0x48039035, 0x59c80000, 0x82000540, 0x00001200, 0x48039000, 0x1c01f000, 0x4803c856, 0x497b88a9, 0x4a038807, 0x00000001, 0x497b8807, 0x59c40005, 0x48038805, 0x0201f800, - 0x00101815, 0x4201d000, 0x000001f4, 0x0201f800, - 0x0010608e, 0x497b880e, 0x4200b000, 0x000001f4, + 0x00101886, 0x4201d000, 0x000001f4, 0x0201f800, + 0x00105dd2, 0x497b880e, 0x4200b000, 0x000001f4, 0x42000000, 0x00000001, 0x42000800, 0x00000014, - 0x0201f800, 0x00101944, 0x42000800, 0x00000014, - 0x0201f800, 0x0010193f, 0x8c040d00, 0x04000005, - 0x8058b040, 0x040207f3, 0x0201f800, 0x001005d8, + 0x0201f800, 0x001019b1, 0x42000800, 0x00000014, + 0x0201f800, 0x001019ac, 0x8c040d00, 0x04000005, + 0x8058b040, 0x040207f3, 0x0201f800, 0x00100615, 0x4200b000, 0x00000032, 0x42000000, 0x00000001, - 0x42000800, 0x000000b4, 0x0201f800, 0x00101944, - 0x42000800, 0x000000b4, 0x0201f800, 0x0010193f, + 0x42000800, 0x000000b4, 0x0201f800, 0x001019b1, + 0x42000800, 0x000000b4, 0x0201f800, 0x001019ac, 0x8c040d00, 0x04000005, 0x8058b040, 0x040207f3, - 0x0201f800, 0x001005d8, 0x59c40005, 0x48038805, + 0x0201f800, 0x00100615, 0x59c40005, 0x48038805, 0x42000000, 0x00000089, 0x800008d0, 0x48075054, 0x48075055, 0x48075056, 0x42000800, 0x000000e0, - 0x0201f800, 0x00101944, 0x42000800, 0x000000f4, - 0x0201f800, 0x0010193f, 0x82040500, 0xffffffd1, + 0x0201f800, 0x001019b1, 0x42000800, 0x000000f4, + 0x0201f800, 0x001019ac, 0x82040500, 0xffffffd1, 0x82000540, 0x00000002, 0x42000800, 0x000000f4, - 0x0201f800, 0x00101944, 0x42000800, 0x000000a0, - 0x0201f800, 0x0010193f, 0x82040540, 0x00000001, - 0x42000800, 0x000000a0, 0x0201f800, 0x00101944, - 0x42000800, 0x00000000, 0x0201f800, 0x0010193f, + 0x0201f800, 0x001019b1, 0x42000800, 0x000000a0, + 0x0201f800, 0x001019ac, 0x82040540, 0x00000001, + 0x42000800, 0x000000a0, 0x0201f800, 0x001019b1, + 0x42000800, 0x00000000, 0x0201f800, 0x001019ac, 0x82040540, 0x00000001, 0x42000800, 0x00000000, - 0x0201f800, 0x00101944, 0x4201d000, 0x0001d4c0, - 0x0201f800, 0x0010608e, 0x0401fa2b, 0x4a0388a7, + 0x0201f800, 0x001019b1, 0x4201d000, 0x0001d4c0, + 0x0201f800, 0x00105dd2, 0x0401fa45, 0x4a0388a7, 0x0000f7f7, 0x4a0388a3, 0x8000403c, 0x4a0388ae, 0x000061a8, 0x4a038801, 0x00032063, 0x4a038810, 0x00410108, 0x4a038811, 0x00520608, 0x4a038812, @@ -1315,2246 +1335,2101 @@ uint32_t risc_code01[] = { 0x4a0388a6, 0x0000001e, 0x4a0388b0, 0x00007530, 0x4a038802, 0x0000ffff, 0x4a038806, 0xc0e00800, 0x1c01f000, 0x497b5022, 0x4a035021, 0x00000001, - 0x42000800, 0x00000040, 0x0201f800, 0x0010193f, + 0x42000800, 0x00000040, 0x0201f800, 0x001019ac, 0x82040500, 0xffffffaf, 0x82000540, 0x00000000, - 0x42000800, 0x00000040, 0x0201f800, 0x00101944, - 0x42000800, 0x000000f4, 0x0201f800, 0x0010193f, + 0x42000800, 0x00000040, 0x0201f800, 0x001019b1, + 0x42000800, 0x000000f4, 0x0201f800, 0x001019ac, 0x4c040000, 0x40040000, 0x84000548, 0x42000800, - 0x000000f4, 0x0201f800, 0x00101944, 0x42000800, - 0x00000000, 0x0201f800, 0x0010193f, 0x82040500, + 0x000000f4, 0x0201f800, 0x001019b1, 0x42000800, + 0x00000000, 0x0201f800, 0x001019ac, 0x82040500, 0xffffffc1, 0x82000540, 0x00000038, 0x42000800, - 0x00000000, 0x0201f800, 0x00101944, 0x5c000000, - 0x42000800, 0x000000f4, 0x0201f000, 0x00101944, - 0x59c40805, 0x4807c857, 0x59c40006, 0x80040d00, - 0x02000800, 0x001005d8, 0x82040500, 0x00e00800, - 0x04020004, 0x8c040d3e, 0x040208c4, 0x0401f007, - 0x82040500, 0x00800800, 0x02020800, 0x001005d0, - 0x0201f800, 0x001005d8, 0x4c5c0000, 0x4c600000, - 0x59c4b805, 0x485fc857, 0x59c40006, 0x8c000500, - 0x04000003, 0x8c5cbd00, 0x04020079, 0x0201f800, - 0x0010513b, 0x04000014, 0x59c40005, 0x82000500, - 0x000000c0, 0x04000036, 0x0201f800, 0x00105151, - 0x04020033, 0x4a038805, 0x04000000, 0x59c400a3, - 0x82000500, 0xbf203fff, 0x480388a3, 0x497b5049, - 0x4a038805, 0x000000c0, 0x0201f800, 0x00105065, - 0x0401f063, 0x8c5cbd34, 0x04020025, 0x59c40005, - 0x8c00050c, 0x04020012, 0x8c00050e, 0x04020013, - 0x8c00050a, 0x04020014, 0x8c000508, 0x0400000b, - 0x59a80017, 0x82000580, 0x00000009, 0x04020007, - 0x42000000, 0x0010b844, 0x0201f800, 0x0010aa47, - 0x0201f800, 0x00105318, 0x0401f04b, 0x4a035033, + 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, 0x0010b846, 0x0201f800, - 0x0010aa47, 0x0201f800, 0x001052c2, 0x0401f03e, - 0x0201f800, 0x00105378, 0x0401f03b, 0x8c5cbd34, - 0x04000037, 0x59c40005, 0x8c00053a, 0x04020005, - 0x42000000, 0x0010b818, 0x0201f800, 0x0010aa47, - 0x4a038805, 0x02000000, 0x0201f800, 0x0010513b, + 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, - 0x00105149, 0x04020008, 0x4a035033, 0x00000001, - 0x4202d800, 0x00000001, 0x0201f800, 0x001050a2, - 0x0401f05b, 0x41780000, 0x0201f800, 0x00105113, - 0x0201f800, 0x001019fe, 0x4000c000, 0x0201f800, - 0x00101963, 0x836c1580, 0x00000004, 0x0402000d, - 0x8c5cbd00, 0x04020012, 0x59a81005, 0x8c081506, + 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, 0x0201f800, 0x00103b38, 0x8c5cbd3c, - 0x04020858, 0x8c5cbd00, 0x04000036, 0x42000000, - 0x0010b8ca, 0x0201f800, 0x0010aa47, 0x4a038805, - 0x00000001, 0x4200b000, 0x000003e8, 0x4201d000, - 0x00000064, 0x4c580000, 0x0201f800, 0x0010608e, - 0x0201f800, 0x001018d3, 0x5c00b000, 0x04000004, - 0x8058b040, 0x040207f6, 0x0401f004, 0x4a038805, - 0x00000001, 0x0401f01f, 0x59c40006, 0x84000500, - 0x48038806, 0x0201f800, 0x00106ede, 0x497b8880, - 0x0201f800, 0x0010a9c0, 0x59c4000d, 0x8c000500, - 0x02020800, 0x0010a9ce, 0x59c400a3, 0x82000500, - 0xfcf8ffff, 0x480388a3, 0x4a03504c, 0x00000002, - 0x4202d800, 0x00000004, 0x4a038805, 0x00000001, - 0x0201f800, 0x001006d4, 0x0401fb3b, 0x497b5052, - 0x4a035049, 0x00000001, 0x0201f800, 0x00100452, - 0x825cbd00, 0xbbfffffe, 0x485f8805, 0x5c00c000, - 0x5c00b800, 0x1c01f000, 0x59c41004, 0x480bc857, - 0x8c081500, 0x04000006, 0x4803c856, 0x497b2807, - 0x0201f800, 0x00106fa4, 0x0401f00a, 0x82080500, - 0x000001f0, 0x04000007, 0x4803c856, 0x417a3000, - 0x0201f800, 0x00106062, 0x0201f800, 0x00106fc6, - 0x4a038805, 0x80000000, 0x1c01f000, 0x59c408a3, - 0x4807c857, 0x84040d40, 0x480788a3, 0x1c01f000, - 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, - 0x4a038805, 0x40000000, 0x42000000, 0x0010b8c6, - 0x0201f800, 0x0010aa47, 0x0201f800, 0x00106c55, - 0x59c41004, 0x8c081500, 0x04000054, 0x598e600d, - 0x497b2807, 0x813261c0, 0x04000032, 0x59300403, - 0x82000580, 0x00000032, 0x0402002e, 0x5930001c, - 0x48038833, 0x4a038807, 0x00018000, 0x4201d000, - 0x00000002, 0x0201f800, 0x0010608e, 0x497b8807, - 0x4201d000, 0x00000002, 0x0201f800, 0x0010608e, - 0x0201f800, 0x00106e21, 0x4201d000, 0x00007530, - 0x0201f800, 0x0010608e, 0x59c408a4, 0x82040d00, - 0x0000000f, 0x82040d80, 0x00000000, 0x04000005, - 0x42000000, 0x00200000, 0x0201f800, 0x00101949, - 0x0201f800, 0x00106bbf, 0x59300008, 0x80000540, - 0x02000800, 0x001005d8, 0x40025800, 0x4a025a04, - 0x00000103, 0x5931d821, 0x58ef400b, 0x58ec0009, - 0x0801f800, 0x0201f800, 0x0002077d, 0x0401f047, - 0x598c000f, 0x82001c80, 0x000000c8, 0x0402100f, - 0x80000000, 0x4803180f, 0x59c400a4, 0x82000500, - 0x0000000f, 0x82000580, 0x00000002, 0x04020004, - 0x42000000, 0x00200000, 0x0401fbf7, 0x0201f800, - 0x0010604d, 0x0401f035, 0x4933c857, 0x0201f800, - 0x00106e21, 0x813261c0, 0x04000030, 0x4a026203, - 0x00000001, 0x42027000, 0x00000027, 0x0201f800, - 0x000207a1, 0x0401f029, 0x8c081508, 0x04000027, - 0x417a3000, 0x0201f800, 0x001070d8, 0x42032000, - 0x0000bf32, 0x0201f800, 0x00106062, 0x59926004, - 0x813261c0, 0x04000012, 0x42001800, 0x000000c8, - 0x0201f800, 0x001070a4, 0x0402000d, 0x59c400a4, - 0x82000500, 0x0000000f, 0x82000580, 0x00000002, - 0x04020004, 0x42000000, 0x00200000, 0x0401fbce, - 0x0201f800, 0x00106052, 0x0401f00c, 0x4933c857, - 0x0201f800, 0x00106dc3, 0x813261c0, 0x04000007, - 0x42027000, 0x0000004f, 0x4a026203, 0x00000003, - 0x0201f800, 0x000207a1, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x0201f000, 0x00106c4b, - 0x4803c857, 0x59a80821, 0x48035021, 0x80041580, - 0x04000045, 0x800409c0, 0x04000023, 0x497b504c, - 0x42000000, 0x0010b80d, 0x0201f800, 0x0010aa47, - 0x0201f800, 0x0010aaf9, 0x42001000, 0x00008011, - 0x59c40001, 0x82000500, 0x00018000, 0x82001d80, - 0x00000000, 0x04000009, 0x82001d80, 0x00008000, - 0x04000009, 0x82001d80, 0x00010000, 0x04000009, - 0x0201f800, 0x001005d8, 0x42001800, 0x00000000, - 0x0401f006, 0x42001800, 0x00000001, 0x0401f003, - 0x42001800, 0x00000003, 0x0201f800, 0x00103a3e, - 0x0401f021, 0x59a8084c, 0x800409c0, 0x04020007, - 0x59c4000d, 0x8c000520, 0x04000004, 0x42001800, - 0x00000003, 0x0401f002, 0x40041800, 0x0201f800, - 0x0010aadd, 0x42001000, 0x00008012, 0x0201f800, - 0x00103a3e, 0x0201f800, 0x001006d4, 0x0201f800, - 0x0010ab33, 0x0402000c, 0x0401f853, 0x4d400000, - 0x4d3c0000, 0x42028000, 0x00000028, 0x42027800, - 0x00000408, 0x0201f800, 0x00101fe5, 0x5c027800, - 0x5c028000, 0x1c01f000, 0x4803c857, 0x82000400, - 0x0010210e, 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, 0x0010ab38, - 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, 0x00103b25, - 0x04000005, 0x42028000, 0x0000002e, 0x0201f000, - 0x0010a449, 0x1c01f000, 0x42000800, 0x00000002, - 0x59a80005, 0x8c000514, 0x0402000b, 0x59c80835, - 0x82040d00, 0x00001f00, 0x80040910, 0x80040800, - 0x59a8006c, 0x80000540, 0x04000003, 0x42000800, - 0x0000025a, 0x4807c857, 0x1c01f000, 0x4c000000, - 0x59a80053, 0x4803c857, 0x82000580, 0x00000000, + 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, 0x00000001, 0x5c000000, - 0x1c01f000, 0x4c000000, 0x59a80053, 0x4803c857, - 0x82000580, 0x00000003, 0x5c000000, 0x1c01f000, - 0x4c000000, 0x59a80053, 0x82000580, 0x00000002, - 0x5c000000, 0x1c01f000, 0x4c000000, 0x4c040000, - 0x4c080000, 0x4c380000, 0x59a80040, 0x82000c80, - 0x00000007, 0x02021800, 0x001005d8, 0x0c01f806, - 0x5c007000, 0x5c001000, 0x5c000800, 0x5c000000, - 0x1c01f000, 0x0010166c, 0x0010167f, 0x00101693, - 0x00101695, 0x001016bc, 0x001016be, 0x001016c0, - 0x4803c856, 0x4a035042, 0x00000000, 0x42000000, - 0x00000002, 0x0401fa1b, 0x42000000, 0x00000002, - 0x0401f9ad, 0x0401fab2, 0x4803c856, 0x4a035040, - 0x00000006, 0x42000800, 0x0000001e, 0x42001000, - 0x001016c1, 0x0201f000, 0x0010606e, 0x497b5045, - 0x4a035050, 0x00000036, 0x4a03504f, 0x0000002a, - 0x4803c856, 0x4a035042, 0x00000001, 0x42000000, - 0x00000002, 0x0401f998, 0x4803c856, 0x4a035040, - 0x00000006, 0x42000800, 0x0000001e, 0x42001000, - 0x001016c1, 0x0201f000, 0x0010606e, 0x0201f800, - 0x001005d8, 0x4a035050, 0x00000036, 0x4803c856, - 0x4a035042, 0x00000003, 0x42000800, 0x00000000, - 0x0401faa3, 0x82040d00, 0x00000090, 0x82040580, - 0x00000090, 0x04000009, 0x82040580, 0x00000010, - 0x04000009, 0x82040580, 0x00000000, 0x04000008, - 0x0201f800, 0x001005d8, 0x42000000, 0x00000001, - 0x0401f005, 0x41780000, 0x0401f003, 0x42000000, - 0x00000002, 0x0401f970, 0x497b5046, 0x4803c856, + 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, 0x001016c1, 0x0201f000, 0x0010606e, - 0x0201f800, 0x001005d8, 0x0201f800, 0x001005d8, - 0x1c01f000, 0x4c000000, 0x4c040000, 0x4c080000, - 0x4c380000, 0x59a80042, 0x82000c80, 0x00000007, - 0x02021800, 0x001005d8, 0x0c01f806, 0x5c007000, - 0x5c001000, 0x5c000800, 0x5c000000, 0x1c01f000, - 0x001016d7, 0x001016f6, 0x0010174a, 0x00101761, - 0x00101778, 0x00101781, 0x00101783, 0x0401f9fc, - 0x0402001b, 0x59a81048, 0x42000800, 0x00000000, - 0x0401fa63, 0x82040d00, 0x00000090, 0x82040580, - 0x00000090, 0x04000009, 0x82040580, 0x00000010, - 0x04000008, 0x82040580, 0x00000000, 0x04000007, - 0x0201f800, 0x001005d8, 0x84081540, 0x0401f004, - 0x84081542, 0x0401f002, 0x84081544, 0x480b5048, - 0x4a035040, 0x00000001, 0x0401f003, 0x0401f8cb, - 0x0401ff82, 0x1c01f000, 0x0401f88f, 0x04000052, - 0x0401f9db, 0x0402002a, 0x42000800, 0x00000000, - 0x0401fa43, 0x82040d00, 0x00000090, 0x82040580, - 0x00000000, 0x04000044, 0x82040580, 0x00000010, - 0x04000006, 0x82040580, 0x00000090, 0x04000009, - 0x0201f800, 0x001005d8, 0x59c40801, 0x82040d00, - 0x00018000, 0x82040580, 0x00000000, 0x04000036, - 0x42000800, 0x00000000, 0x0401fa2d, 0x82040d00, - 0x00000090, 0x82040580, 0x00000010, 0x04000006, - 0x82040580, 0x00000090, 0x04000006, 0x02020800, - 0x001005d8, 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, 0x001005d8, 0x42000000, 0x00000001, - 0x0401f005, 0x41780000, 0x0401f003, 0x42000000, - 0x00000002, 0x0401f94b, 0x4a035042, 0x00000002, - 0x0401f004, 0x4a035040, 0x00000003, 0x0401f002, - 0x0401ff42, 0x1c01f000, 0x0401f83b, 0x04000015, - 0x59a8004f, 0x80000040, 0x4803504f, 0x0401f984, - 0x04020005, 0x4a035040, 0x00000003, 0x497b5041, - 0x0401f00c, 0x59a8004f, 0x80000540, 0x04020003, - 0x0401f89e, 0x0401f002, 0x0401f84b, 0x0401f82f, - 0x497b5045, 0x4a035042, 0x00000001, 0x0401ff2b, - 0x1c01f000, 0x0401f824, 0x04000015, 0x0401f970, - 0x0402000f, 0x59a80046, 0x80000000, 0x48035046, - 0x82000580, 0x00000007, 0x0402000c, 0x4a035052, - 0x0000000a, 0x497b5049, 0x59a80048, 0x8400055e, - 0x48035048, 0x4803c857, 0x0401f005, 0x0401f817, - 0x4a035042, 0x00000004, 0x0401ff3d, 0x1c01f000, - 0x0401f80d, 0x04000007, 0x0401f959, 0x04020003, - 0x0401ff1b, 0x0401f003, 0x0401f80c, 0x0401ff34, - 0x1c01f000, 0x0201f800, 0x001005d8, 0x0201f800, - 0x001005d8, 0x59a80050, 0x80000040, 0x48035050, - 0x0400088d, 0x1c01f000, 0x4c040000, 0x42000800, - 0x00000000, 0x0401f9b2, 0x82040d00, 0x00000090, + 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, - 0x04000009, 0x0201f800, 0x001005d8, 0x42000000, - 0x00000002, 0x0401f005, 0x42000000, 0x00000001, - 0x0401f002, 0x41780000, 0x0401f8ea, 0x5c000800, - 0x1c01f000, 0x4c040000, 0x59c40801, 0x82040d00, - 0x00018000, 0x82040580, 0x00000000, 0x04000009, - 0x82040580, 0x00008000, 0x04000009, 0x82040580, - 0x00010000, 0x04000009, 0x0201f800, 0x001005d8, - 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, 0x001005d8, - 0x42000000, 0x00000002, 0x0401f005, 0x42000000, - 0x00000001, 0x0401f002, 0x41780000, 0x0401f846, - 0x42000800, 0x00000000, 0x0401f961, 0x82040d00, + 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, 0x001005d8, + 0x00000000, 0x04000009, 0x0201f800, 0x00100615, 0x42000000, 0x00000002, 0x0401f005, 0x42000000, - 0x00000001, 0x0401f002, 0x41780000, 0x0401f899, - 0x5c000800, 0x1c01f000, 0x4c200000, 0x59a80048, - 0x82000500, 0x00007fff, 0x02000800, 0x001005d8, - 0x59a84047, 0x80204102, 0x02001800, 0x001005d8, - 0x48235047, 0x80204500, 0x040007fa, 0x8c000504, - 0x04020007, 0x8c000502, 0x04020008, 0x8c000500, - 0x04020008, 0x0201f800, 0x001005d8, 0x42000000, - 0x00000002, 0x0401f005, 0x41780000, 0x0401f003, - 0x42000000, 0x00000001, 0x0401f80f, 0x5c004000, - 0x1c01f000, 0x04011000, 0x4a03c840, 0x0010b440, - 0x4a03c842, 0x00000009, 0x40000000, 0x040117ff, - 0x4a035047, 0x00000004, 0x4a03503e, 0x00000000, - 0x1c01f000, 0x59a80858, 0x82040d80, 0x01391077, - 0x04020008, 0x59e00813, 0x8c040d00, 0x04000005, - 0x82000d80, 0x00000002, 0x04020002, 0x41780000, - 0x4c000000, 0x0401f9b1, 0x5c000000, 0x800001c0, - 0x04000040, 0x82000d80, 0x00000001, 0x0402001d, - 0x42000800, 0x000000a0, 0x0401f909, 0x82040540, - 0x00000004, 0x42000800, 0x000000a0, 0x0401f909, - 0x42000800, 0x000000c0, 0x0401f901, 0x82040540, - 0x00000020, 0x42000800, 0x000000c0, 0x0401f901, - 0x59c40001, 0x82000500, 0xfffe7fff, 0x82000540, - 0x00000000, 0x48038801, 0x59a80054, 0x80000110, - 0x42000800, 0x000000e0, 0x0401f8f6, 0x0401f03c, - 0x82000d80, 0x00000002, 0x02020800, 0x001005d8, - 0x42000800, 0x000000a0, 0x0401f8e9, 0x82040500, - 0xfffffffb, 0x42000800, 0x000000a0, 0x0401f8e9, - 0x42000800, 0x000000c0, 0x0401f8e1, 0x82040500, - 0xffffffdf, 0x42000800, 0x000000c0, 0x0401f8e1, - 0x59c40001, 0x82000500, 0xfffe7fff, 0x82000540, - 0x00010000, 0x48038801, 0x59a80056, 0x80000110, - 0x42000800, 0x000000e0, 0x0401f8d6, 0x0401f01c, - 0x42000800, 0x000000a0, 0x0401f8cd, 0x82040540, - 0x00000004, 0x42000800, 0x000000a0, 0x0401f8cd, - 0x42000800, 0x000000c0, 0x0401f8c5, 0x82040500, - 0xffffffdf, 0x42000800, 0x000000c0, 0x0401f8c5, - 0x59c40001, 0x82000500, 0xfffe7fff, 0x82000540, - 0x00008000, 0x48038801, 0x59a80055, 0x80000110, - 0x42000800, 0x000000e0, 0x0401f8ba, 0x0401f163, - 0x4803c857, 0x59a80858, 0x82040d80, 0x01391077, - 0x04020008, 0x59e00813, 0x8c040d00, 0x04000005, - 0x82000d80, 0x00000002, 0x04020002, 0x41780000, - 0x4c000000, 0x0401f94d, 0x5c000000, 0x800001c0, - 0x04000026, 0x82000d80, 0x00000001, 0x04020010, + 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, - 0x00000000, 0x0401fa0a, 0x42000800, 0x00000000, - 0x0401f897, 0x82040540, 0x00000090, 0x42000800, - 0x00000000, 0x0401f897, 0x0401f024, 0x82000d80, - 0x00000002, 0x02020800, 0x001005d8, 0x59a8006c, - 0x80000540, 0x04000004, 0x42001000, 0x00010000, - 0x0401f9f7, 0x42000800, 0x00000000, 0x0401f884, - 0x82040500, 0xffffff6f, 0x42000800, 0x00000000, - 0x0401f884, 0x0401f011, 0x59a8006c, 0x80000540, - 0x04000004, 0x42001000, 0x00008000, 0x0401f9e8, - 0x42000800, 0x00000000, 0x0401f875, 0x82040500, - 0xffffff6f, 0x82000540, 0x00000010, 0x42000800, - 0x00000000, 0x0401f873, 0x0401f124, 0x4c580000, - 0x4200b000, 0x00000014, 0x8058b040, 0x04000043, - 0x59c4000d, 0x8c000520, 0x040207fc, 0x0401f85c, - 0x59c4000d, 0x8c000520, 0x040207f8, 0x59c40808, - 0x84040d50, 0x48078808, 0x4200b000, 0x000000c8, - 0x8058b040, 0x040207ff, 0x4200b000, 0x00000014, - 0x8058b040, 0x04000031, 0x59c4000d, 0x8c000520, - 0x0402002e, 0x42000800, 0x00001000, 0x50040800, - 0x82040c80, 0x24220001, 0x04020003, 0x8c000504, - 0x040007f4, 0x0401f842, 0x59c4000d, 0x8c000520, - 0x04020022, 0x42000800, 0x00001000, 0x50040800, - 0x82040c80, 0x24220001, 0x04020003, 0x8c000504, - 0x040007e8, 0x4200b000, 0x0000000a, 0x8058b040, - 0x04000003, 0x0401f832, 0x0401f7fd, 0x4200b000, - 0x00000064, 0x59c4000d, 0x8c00051e, 0x0400000f, - 0x8058b040, 0x040207fc, 0x42000000, 0x00001000, - 0x50000000, 0x82000480, 0x24220001, 0x04020004, - 0x59c40808, 0x84040d10, 0x48078808, 0x80000580, - 0x4803c857, 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, + 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, - 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, 0x00106ede, 0x4863500a, 0x0201f800, - 0x0010ab33, 0x0402006c, 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, - 0x0400003e, 0x84000542, 0x48035005, 0x4200c800, - 0x00000002, 0x42028000, 0x00000004, 0x42027800, - 0x00000008, 0x0401f008, 0x59a80805, 0x84040d40, - 0x48075005, 0x42028000, 0x00000004, 0x42027800, - 0x00000400, 0x59a80006, 0x8c000502, 0x04020006, - 0x59a80805, 0x8c040d0a, 0x04020033, 0x84040d4a, - 0x48075005, 0x42000000, 0x0010b812, 0x0201f800, - 0x0010aa47, 0x59a8180a, 0x42001000, 0x00008013, - 0x0201f800, 0x00103a3e, 0x0201f800, 0x00103b25, + 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, 0x0010a446, 0x42000800, + 0x0000000e, 0x0201f800, 0x0010a258, 0x42000800, 0x00000001, 0x42001000, 0x00000100, 0x0201f800, - 0x0010618b, 0x5c028000, 0x599c0817, 0x8c040d0a, - 0x04020011, 0x493fc857, 0x4943c857, 0x0201f800, - 0x00101fe5, 0x0401f00c, 0x0201f800, 0x00103b25, - 0x04000009, 0x42028000, 0x0000000f, 0x42028800, - 0x0000ffff, 0x42003000, 0x00000000, 0x0201f800, - 0x0010a449, 0x497b8880, 0x5c028000, 0x5c027800, - 0x5c00c800, 0x1c01f000, 0x42000800, 0x000000a0, - 0x0401ff5f, 0x82040540, 0x00000002, 0x42000800, - 0x000000a0, 0x0401f75f, 0x42000800, 0x00000000, - 0x0401ff57, 0x82040540, 0x00000002, 0x42000800, - 0x00000000, 0x0401f757, 0x42000800, 0x000000a0, - 0x0401ff4f, 0x82040500, 0xfffffffd, 0x42000800, - 0x000000a0, 0x0401f74f, 0x42000800, 0x00000000, - 0x0401ff47, 0x82040500, 0xfffffffd, 0x42000800, - 0x00000000, 0x0401f747, 0x59c408a8, 0x0401ff38, - 0x0401ff37, 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, - 0x0010ab38, 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, 0x0010ab38, 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, + 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, - 0x0401ff7a, 0x42006800, 0x0000003c, 0x0401ff7d, + 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, - 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, 0x00020103, 0x00101bd5, 0x00101bdb, - 0x00101be1, 0x00101be9, 0x00101bef, 0x00101bf7, - 0x00101bff, 0x00101c09, 0x00101c0f, 0x00101c17, - 0x00101c1f, 0x00101c29, 0x00101c31, 0x00101c3b, - 0x00101c45, 0x000200f8, 0x00101c51, 0x00101c59, - 0x00101c61, 0x00101c6b, 0x00101c73, 0x00101c7d, - 0x00101c87, 0x00101c93, 0x00101c9b, 0x00101ca5, - 0x00101caf, 0x00101cbb, 0x00101cc5, 0x00101cd1, - 0x00101cdd, 0x000200fd, 0x00101ceb, 0x00101cf3, - 0x00101cfb, 0x00101d05, 0x00101d0d, 0x00101d17, - 0x00101d21, 0x00101d2d, 0x00101d35, 0x00101d3f, - 0x00101d49, 0x00101d55, 0x00101d5f, 0x00101d6b, - 0x00101d77, 0x00101d85, 0x00101d8d, 0x00101d97, - 0x00101da1, 0x00101dad, 0x00101db7, 0x00101dc3, - 0x00101dcf, 0x00101ddd, 0x00101de7, 0x00101df3, - 0x00101dff, 0x00101e0d, 0x00101e19, 0x00101e27, - 0x00101e35, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101418, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800, - 0x00101418, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800, - 0x00101418, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101289, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101289, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00101289, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00101289, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00101289, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00101289, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800, - 0x00101418, 0x0201f800, 0x00101289, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00101418, 0x0201f800, - 0x00101289, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101418, 0x0201f800, 0x00020729, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101418, 0x0201f800, 0x00020729, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800, - 0x00020729, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020729, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800, - 0x00101418, 0x0201f800, 0x00020729, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00020729, 0x0201f800, - 0x00101289, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00020729, 0x0201f800, - 0x00101289, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101418, 0x0201f800, 0x00020729, 0x0201f800, - 0x00101289, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020729, 0x0201f800, 0x00101289, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800, - 0x00020729, 0x0201f800, 0x00101289, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00020729, 0x0201f800, - 0x00101289, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020729, 0x0201f800, 0x00101289, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020729, 0x0201f800, 0x00101289, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00020015, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020015, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020015, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00020015, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00020015, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00101155, 0x0201f800, 0x00020015, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101418, 0x0201f800, 0x00101155, 0x0201f800, - 0x00020015, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00020015, 0x0201f800, 0x00101289, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00020015, 0x0201f800, 0x00101289, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020015, 0x0201f800, 0x00101289, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101418, 0x0201f800, 0x00020015, 0x0201f800, - 0x00101289, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00020015, 0x0201f800, 0x00101289, 0x0201f800, - 0x00101155, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00020015, 0x0201f800, - 0x00101289, 0x0201f800, 0x00101155, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020015, 0x0201f800, 0x00101289, 0x0201f800, - 0x00101155, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020015, 0x0201f800, 0x00101289, 0x0201f800, - 0x00101155, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020015, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020015, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020015, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101418, 0x0201f800, 0x00020729, 0x0201f800, - 0x00020015, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020015, 0x0201f800, - 0x00101155, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00020729, 0x0201f800, - 0x00020015, 0x0201f800, 0x00101155, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020015, 0x0201f800, - 0x00101155, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020015, 0x0201f800, - 0x00101155, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020015, 0x0201f800, - 0x00101289, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00020729, 0x0201f800, - 0x00020015, 0x0201f800, 0x00101289, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020015, 0x0201f800, - 0x00101289, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020015, 0x0201f800, - 0x00101289, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00020729, 0x0201f800, - 0x00020015, 0x0201f800, 0x00101289, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00020729, 0x0201f800, - 0x00020015, 0x0201f800, 0x00101289, 0x0201f800, - 0x00020104, 0x0201f000, 0x00020101, 0x4c000000, - 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800, - 0x00101418, 0x0201f800, 0x00020729, 0x0201f800, - 0x00020015, 0x0201f800, 0x00101289, 0x0201f000, - 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800, - 0x00101155, 0x0201f800, 0x00101418, 0x0201f800, - 0x00020729, 0x0201f800, 0x00020015, 0x0201f800, - 0x00101289, 0x0201f800, 0x00020104, 0x0201f000, - 0x00020101, 0x4c5c0000, 0x4c600000, 0x4178b800, - 0x0201f800, 0x001048ec, 0x040200fd, 0x59a8c026, - 0x0201f800, 0x0010513b, 0x04000003, 0x8c60c506, - 0x0400000e, 0x8c60c500, 0x04020004, 0x8c60c50e, - 0x040008f6, 0x0401f0f2, 0x0401fab4, 0x040200f0, - 0x0201f800, 0x0010513b, 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, 0x0010be21, - 0x50300800, 0x825c0500, 0x00000003, 0x0c01f001, - 0x00101e81, 0x00101e7c, 0x00101e80, 0x00101e7e, - 0x80040910, 0x0401f004, 0x80040930, 0x0401f002, - 0x80040920, 0x82040500, 0x000000ff, 0x82000d80, - 0x000000ff, 0x0400000f, 0x4c000000, 0x82000400, - 0x0010210e, 0x50000800, 0x80040910, 0x82040580, - 0x00000080, 0x5c000000, 0x04000030, 0x80600d80, - 0x0400002e, 0x80000540, 0x0400002c, 0x0401f00b, - 0x59a81005, 0x82081500, 0x00000003, 0x0402002b, - 0x59a81013, 0x84081542, 0x480b5013, 0x4a03501c, - 0x0000ffff, 0x0401f028, 0x4c000000, 0x59a80005, - 0x8c000514, 0x42001000, 0x00000010, 0x02020800, - 0x00104c6d, 0x5c000000, 0x0402001c, 0x417a8800, - 0x0201f800, 0x00105c9a, 0x04020016, 0x0201f800, - 0x001045e5, 0x04000006, 0x0201f800, 0x00104c62, - 0x0401f8b1, 0x0400000f, 0x0401f00c, 0x599c0019, - 0x8c00050e, 0x04020009, 0x0201f800, 0x001045a6, - 0x04020008, 0x0201f800, 0x00104c62, 0x0401f9e1, - 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, 0x0010210e, 0x50000000, - 0x82000500, 0x000000ff, 0x80604580, 0x0400005c, - 0x0201f800, 0x00105c9b, 0x04020061, 0x59a80005, - 0x8c000514, 0x42001000, 0x00000010, 0x02020800, - 0x00104c6d, 0x5c00b000, 0x5c000800, 0x040207d7, - 0x4c040000, 0x4c580000, 0x845cbd00, 0x0201f800, - 0x00020245, 0x04000008, 0x599c0019, 0x8c00050e, - 0x04020047, 0x0201f800, 0x001045ab, 0x0402004c, - 0x0401f002, 0x845cbd40, 0x0201f800, 0x00104c62, - 0x0201f800, 0x001049e7, 0x04020007, 0x59a80005, - 0x8c000502, 0x04000033, 0x59340200, 0x8c00050e, - 0x04020030, 0x59a81013, 0x8c081502, 0x04000025, - 0x0201f800, 0x00104a09, 0x04000031, 0x8c5cbd00, - 0x04020004, 0x0201f800, 0x001045ff, 0x0401f02c, - 0x0401f9cd, 0x0400002a, 0x42026000, 0x0010bde9, - 0x49366009, 0x497a6008, 0x417a7800, 0x0401f925, - 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47, - 0x0201f800, 0x00103b25, 0x0400001d, 0x41782800, - 0x42003000, 0x00000008, 0x4d400000, 0x4d440000, - 0x59368c03, 0x42028000, 0x00000029, 0x0201f800, - 0x0010a446, 0x5c028800, 0x5c028000, 0x0401f010, - 0x4937c857, 0x599c0019, 0x8c00050e, 0x0402000c, - 0x0401f96c, 0x0401f849, 0x04000011, 0x0401f008, - 0x59a80013, 0x8c000500, 0x04000003, 0x0401f9a6, - 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, 0x001045a6, 0x0402000c, - 0x0401f948, 0x0401f825, 0x04000009, 0x59a80026, - 0x8400054e, 0x48035026, 0x0201f800, 0x0010930f, - 0x82000540, 0x00000001, 0x1c01f000, 0x80000580, - 0x0401f7fe, 0x4937c857, 0x0201f800, 0x00107942, - 0x04000015, 0x49366009, 0x4a026406, 0x00000001, - 0x417a7800, 0x0201f800, 0x00104567, 0x59a8001b, - 0x80000000, 0x4803501b, 0x42027000, 0x00000004, - 0x599c0019, 0x8c00050e, 0x04000003, 0x42027000, - 0x00000000, 0x0201f800, 0x000207a1, 0x82000540, - 0x00000001, 0x1c01f000, 0x4937c857, 0x0201f800, - 0x00107942, 0x0400001c, 0x49366009, 0x59340403, - 0x82000580, 0x000007fe, 0x04000005, 0x4d3c0000, - 0x417a7800, 0x0401f8b7, 0x5c027800, 0x4a026406, - 0x00000001, 0x417a7800, 0x0201f800, 0x00104567, - 0x42000800, 0x00000003, 0x0201f800, 0x00104571, - 0x59a8001b, 0x80000000, 0x4803501b, 0x42027000, - 0x00000002, 0x0201f800, 0x000207a1, 0x82000540, - 0x00000001, 0x1c01f000, 0x4803c856, 0x42028800, - 0x000007fc, 0x42003000, 0x00fffffc, 0x0201f800, - 0x001045a6, 0x04020005, 0x0401f805, 0x04000003, - 0x4a035027, 0x0000ffff, 0x1c01f000, 0x4937c857, - 0x0201f800, 0x00107942, 0x04000014, 0x49366009, - 0x4a026406, 0x00000001, 0x417a7800, 0x0201f800, - 0x00104567, 0x42000800, 0x00000003, 0x0201f800, - 0x00104571, 0x59a80028, 0x80000000, 0x48035028, - 0x42027000, 0x00000002, 0x0201f800, 0x000207a1, - 0x82000540, 0x00000001, 0x1c01f000, 0x480bc857, - 0x492fc857, 0x4c5c0000, 0x4008b800, 0x42028800, - 0x000007fd, 0x42003000, 0x00fffffd, 0x0201f800, - 0x001045a6, 0x0402001a, 0x0201f800, 0x0002075a, - 0x04000017, 0x49366009, 0x5934000a, 0x84000544, - 0x4802680a, 0x812e59c0, 0x04000005, 0x592c0404, - 0x8c00051e, 0x04000002, 0x48ee6021, 0x492e6008, - 0x4a026406, 0x00000001, 0x485e601c, 0x42027000, - 0x00000022, 0x0201f800, 0x000207a1, 0x82000540, - 0x00000001, 0x5c00b800, 0x1c01f000, 0x80000580, - 0x0401f7fd, 0x5c000000, 0x4c000000, 0x4803c857, - 0x4943c857, 0x493fc857, 0x4d340000, 0x4d440000, - 0x4c580000, 0x4d2c0000, 0x4c5c0000, 0x0201f800, - 0x00106c55, 0x4df00000, 0x0201f800, 0x001069f1, - 0x0201f800, 0x00106aac, 0x0201f800, 0x00106737, - 0x0201f800, 0x0010848a, 0x5c03e000, 0x02000800, - 0x00106c4b, 0x4200b000, 0x000007f0, 0x417a8800, - 0x0201f800, 0x00020245, 0x0402001f, 0x8d3e7d14, - 0x04000005, 0x59340212, 0x82000500, 0x0000ff00, - 0x04000019, 0x8d3e7d06, 0x04000004, 0x59340200, - 0x8c00050e, 0x04020014, 0x8d3e7d18, 0x0400000f, - 0x5934b80f, 0x805cb9c0, 0x04000009, 0x49425a06, - 0x592cb800, 0x0201f800, 0x000202ce, 0x805cb9c0, - 0x040207fb, 0x497a680f, 0x497a6810, 0x4a026c00, - 0x00000707, 0x0401f004, 0x4937c857, 0x0201f800, - 0x001042b4, 0x81468800, 0x8058b040, 0x040207dd, - 0x8d3e7d02, 0x04000011, 0x497b501d, 0x42028800, - 0x000007f0, 0x4200b000, 0x00000010, 0x0201f800, - 0x00020245, 0x04020006, 0x4937c857, 0x4a026c00, - 0x00000707, 0x0201f800, 0x001042b4, 0x81468800, - 0x8058b040, 0x040207f6, 0x5c00b800, 0x5c025800, - 0x5c00b000, 0x5c028800, 0x5c026800, 0x1c01f000, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4933c857, - 0x493fc857, 0x4d340000, 0x4d400000, 0x4d440000, - 0x4d2c0000, 0x4c5c0000, 0x0201f800, 0x00106c55, - 0x4df00000, 0x59326809, 0x813669c0, 0x04000020, - 0x59368c03, 0x42028000, 0x00000029, 0x0201f800, - 0x00106a50, 0x0201f800, 0x00106ab4, 0x0201f800, - 0x001067fd, 0x0201f800, 0x0010a2ff, 0x4937c857, - 0x8d3e7d18, 0x04000010, 0x5934b80f, 0x805cb9c0, - 0x0400000a, 0x405e5800, 0x49425a06, 0x592cb800, - 0x0201f800, 0x000202ce, 0x805cb9c0, 0x040207fa, - 0x497a680f, 0x497a6810, 0x4a026c00, 0x00000707, - 0x0401f003, 0x0201f800, 0x001042b4, 0x5c03e000, - 0x02000800, 0x00106c4b, 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, 0x001005d8, - 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, - 0x4d3c0000, 0x4d400000, 0x4d340000, 0x4d440000, - 0x4c580000, 0x0201f800, 0x00106c55, 0x4df00000, - 0x813e79c0, 0x04020004, 0x4200b000, 0x00000001, - 0x0401f004, 0x4200b000, 0x000007f0, 0x417a8800, - 0x41440000, 0x81ac0400, 0x50000000, 0x80026d40, - 0x04000019, 0x42027800, 0x00000001, 0x0201f800, - 0x001048f6, 0x42028000, 0x00000029, 0x417a7800, - 0x0201f800, 0x00106a50, 0x0201f800, 0x00106ab4, - 0x0201f800, 0x001067fd, 0x0201f800, 0x001049e7, - 0x04020005, 0x4937c857, 0x4a026c00, 0x00000404, - 0x0401f003, 0x0201f800, 0x00104a14, 0x0201f800, - 0x0010a2ff, 0x81468800, 0x8058b040, 0x040207e1, - 0x5c03e000, 0x02000800, 0x00106c4b, 0x5c00b000, - 0x5c028800, 0x5c026800, 0x5c028000, 0x5c027800, - 0x1c01f000, 0x4937c857, 0x4947c857, 0x4c5c0000, - 0x4c600000, 0x4c640000, 0x59a80013, 0x8c000500, - 0x0400001f, 0x599c0017, 0x8c00050a, 0x0402001c, - 0x5934ba02, 0x825cbd00, 0x000000ff, 0x485fc857, - 0x4178c000, 0x4178c800, 0x82600400, 0x0010be21, - 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, 0x4803c857, - 0x8c000512, 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, + 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, - 0x00008000, 0x00003300, 0x00003200, 0x00008000, + 0x00003300, 0x00003200, 0x00008000, 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, + 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, - 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, + 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, - 0x00008000, 0x00000000, 0x00008000, 0x00008000, + 0x00000000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x0201f800, 0x001007d3, - 0x02000800, 0x001005d8, 0x492f4016, 0x1c01f000, - 0x83a0ac00, 0x00000006, 0x83a00580, 0x0010b4a4, - 0x0400000c, 0x492fc857, 0x812e59c0, 0x02000800, - 0x001005d8, 0x832ca400, 0x00000006, 0x4200b000, - 0x0000000d, 0x0201f800, 0x0010ab17, 0x0401f00f, - 0x4200b000, 0x00000010, 0x83e0a400, 0x00000020, - 0x50500000, 0x8050a000, 0x50500800, 0x900409c0, - 0x80040540, 0x4400a800, 0x8050a000, 0x8054a800, - 0x8058b040, 0x040207f7, 0x1c01f000, 0x59a00206, - 0x4803c857, 0x82000c80, 0x0000007f, 0x040210c9, - 0x59a80821, 0x0c01f001, 0x001022c0, 0x00102300, - 0x00102300, 0x0010234b, 0x0010236d, 0x00102300, - 0x001022c0, 0x0010238f, 0x001023a0, 0x00102300, - 0x00102300, 0x001023ad, 0x001023c5, 0x001023dd, - 0x00102300, 0x001023e7, 0x001023f4, 0x00102300, - 0x0010241d, 0x00102300, 0x0010247a, 0x00102300, - 0x00102300, 0x00102300, 0x00102300, 0x00102300, - 0x00102300, 0x00102300, 0x00102300, 0x00102300, - 0x00102300, 0x00102300, 0x00102491, 0x00102300, - 0x001024e3, 0x00102300, 0x00102300, 0x00102300, - 0x00102300, 0x001024e8, 0x00102560, 0x00102300, - 0x00102567, 0x00102300, 0x00102300, 0x00102300, - 0x00102300, 0x00102300, 0x00102569, 0x001025ea, - 0x00102727, 0x00102300, 0x00102300, 0x00102300, - 0x00102300, 0x00102300, 0x00102736, 0x00102300, - 0x00102300, 0x00102300, 0x00102300, 0x00102300, - 0x00102300, 0x00102300, 0x00102753, 0x001027a6, - 0x00102802, 0x00102816, 0x00102835, 0x00102a70, - 0x00102dff, 0x00102300, 0x00102300, 0x00102300, - 0x00102300, 0x00102300, 0x00102300, 0x00102300, - 0x00102300, 0x00102300, 0x00102300, 0x00102300, - 0x00102300, 0x00102fb4, 0x00103028, 0x00102300, - 0x00102300, 0x00103094, 0x00102300, 0x00103126, - 0x001031d8, 0x00102300, 0x00102300, 0x0010320f, - 0x0010326b, 0x00102300, 0x001032bd, 0x00103419, - 0x00102300, 0x0010342d, 0x001034b8, 0x00102300, - 0x00102300, 0x00102300, 0x00102300, 0x00103522, - 0x00103526, 0x00103545, 0x00102300, 0x001035e7, - 0x00102300, 0x00102300, 0x00103615, 0x00102300, - 0x00103643, 0x00102300, 0x00102300, 0x001036aa, - 0x001037b7, 0x00103814, 0x00102300, 0x0010387a, - 0x00102300, 0x00102300, 0x001038d3, 0x00103936, - 0x00102300, 0x48efc857, 0x4031d800, 0x58ef400b, - 0x58ec0002, 0x82000580, 0x00000200, 0x04000045, - 0x48efc857, 0x4a034206, 0x00004000, 0x0201f800, - 0x00103a15, 0x83a00580, 0x0010b4a4, 0x0400000d, - 0x58ee580a, 0x4d2c0000, 0x0401f856, 0x41a25800, - 0x0201f800, 0x001007f4, 0x40ee5800, 0x0201f800, - 0x001007f4, 0x5c025800, 0x0201f000, 0x000202da, - 0x04026007, 0x59a0001d, 0x84000542, 0x4803401d, - 0x4a01d809, 0x001022d4, 0x1c01f000, 0x59a00206, - 0x82000d80, 0x00004000, 0x04000006, 0x900001c0, - 0x82000540, 0x00000011, 0x4803c011, 0x0401f005, - 0x900001c0, 0x82000540, 0x00000010, 0x4803c011, - 0x0401f845, 0x59e00017, 0x8c000508, 0x0402000c, - 0x4203e000, 0x30000001, 0x4203e000, 0x40000000, - 0x40ee5800, 0x0201f800, 0x001007f4, 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, - 0x48efc857, 0x58eca80a, 0x8054a9c0, 0x02000800, - 0x001005d8, 0x83a0a400, 0x00000006, 0x8254ac00, - 0x00000006, 0x4200b000, 0x0000000d, 0x0201f000, - 0x0010ab17, 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, - 0x59a80805, 0x8c040d0e, 0x040207ba, 0x42000800, - 0x00000064, 0x80040840, 0x04000007, 0x4a030000, - 0x00000001, 0x40000000, 0x59801000, 0x8c081500, - 0x040007f9, 0x04000005, 0x48030004, 0x4a030000, - 0x00000000, 0x0401f75b, 0x4a030000, 0x00000000, - 0x4a034406, 0x00000004, 0x040007a2, 0x4803880e, - 0x0401f754, 0x59a00406, 0x800000c2, 0x59a00c07, - 0x8c040d00, 0x0400001a, 0x59a80805, 0x8c040d0e, - 0x0402079c, 0x42000800, 0x00000064, 0x80040840, + 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, - 0x59801000, 0x8c081500, 0x040007f9, 0x04000007, - 0x48030004, 0x59800805, 0x48074406, 0x4a030000, - 0x00000000, 0x0401f73b, 0x4a030000, 0x00000000, - 0x4a034406, 0x00000004, 0x04000782, 0x4803880e, - 0x59c4080f, 0x48074406, 0x0401f732, 0x59a01c06, - 0x59a00207, 0x900c19c0, 0x800c1d40, 0x580c0803, - 0x80000580, 0x500c1000, 0x80080400, 0x800c1800, - 0x80040840, 0x040207fc, 0x48034406, 0x900001c0, - 0x48034207, 0x800001c0, 0x04000722, 0x0401f769, - 0x4a034406, 0x00000004, 0x4a034207, 0x00000000, - 0x4a034407, 0x00000010, 0x59a8000d, 0x48034208, - 0x900001c0, 0x48034408, 0x4a034209, 0x00000002, - 0x0401f714, 0x59a00407, 0x59a01207, 0x900811c0, - 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0, - 0x800c1d40, 0x59a00a08, 0x59a00408, 0x900409c0, - 0x80040d40, 0x59a0020a, 0x82002480, 0x00000010, - 0x04001754, 0x59a02406, 0x900001c0, 0x80100540, - 0x59a8280d, 0x80142480, 0x0400174e, 0x0201f000, - 0x00103a25, 0x59a00407, 0x59a01207, 0x900811c0, + 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, 0x59a00a08, 0x59a00408, 0x900409c0, - 0x80040d40, 0x59a0020a, 0x82002480, 0x00000010, - 0x0400173c, 0x59a02406, 0x900001c0, 0x80100540, - 0x59a8280d, 0x80142480, 0x04001736, 0x0201f000, - 0x00103a28, 0x59a00a0a, 0x59a00406, 0x900409c0, - 0x80040d40, 0x59a01407, 0x59a00207, 0x900811c0, - 0x80081540, 0x44080800, 0x0401f6da, 0x59a00a0a, - 0x59a00406, 0x900409c0, 0x80040d40, 0x50040000, - 0x82000d00, 0x0000ffff, 0x48074207, 0x82000d00, - 0xffff0000, 0x900409c0, 0x48074407, 0x0401f6cd, - 0x59a00406, 0x8c000500, 0x04000020, 0x59a01207, - 0x59a01c07, 0x59a02208, 0x480b5054, 0x480f5055, - 0x48135056, 0x59c40801, 0x82040d00, 0x00018000, - 0x82040580, 0x00000000, 0x04000009, 0x82040580, - 0x00008000, 0x04000008, 0x82040580, 0x00010000, - 0x04000007, 0x0201f800, 0x001005d8, 0x40080000, - 0x0401f004, 0x400c0000, 0x0401f002, 0x40100000, - 0x80000110, 0x42000800, 0x000000e0, 0x0201f800, - 0x00101944, 0x0401f007, 0x59a81054, 0x59a81855, - 0x59a82056, 0x480b4207, 0x480f4407, 0x48134208, - 0x0401f6a4, 0x4d2c0000, 0x4d340000, 0x4d300000, - 0x4d440000, 0x59a28c06, 0x0201f800, 0x00020245, - 0x04000006, 0x5c028800, 0x5c026000, 0x5c026800, - 0x5c025800, 0x0401f6e7, 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, 0x0401f67a, 0x5c028800, - 0x5c026000, 0x5c026800, 0x5c025800, 0x0401f6c1, - 0x4937c856, 0x4823c856, 0x4d2c0000, 0x5934000f, - 0x80025d40, 0x04000007, 0x592c0005, 0x80200580, - 0x592c0000, 0x040207fb, 0x82000540, 0x00000001, - 0x5c025800, 0x1c01f000, 0x4823c857, 0x4d2c0000, - 0x4d300000, 0x42026000, 0x0010d1c0, 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, 0x0010b4a4, - 0x04020684, 0x59a80005, 0x8c00050e, 0x04020003, - 0x4a030000, 0x00000000, 0x4a034206, 0x00004000, - 0x4a03c011, 0x40000010, 0x0401fea7, 0x59e00017, - 0x8c000508, 0x04000003, 0x4a03c017, 0x00000000, - 0x4203e000, 0x30000001, 0x4203e000, 0x40000000, - 0x0401f000, 0x800409c0, 0x04000004, 0x4a034406, - 0x00000001, 0x0401f677, 0x836c0580, 0x00000003, - 0x04020010, 0x59a80010, 0x497b4406, 0x0201f800, - 0x0010513b, 0x0400000f, 0x82000d00, 0x00ffff00, - 0x0402000c, 0x82000c00, 0x0010210e, 0x50040800, - 0x80040910, 0x82041580, 0x00000080, 0x04020004, - 0x4a034406, 0x00000007, 0x0401f662, 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, 0x0010513b, 0x04020004, - 0x4a034209, 0x00000004, 0x0401f5e6, 0x8c000506, - 0x04000004, 0x4a034406, 0x00000005, 0x0401f62d, - 0x4a034209, 0x00000000, 0x0401f5de, 0x59a80037, - 0x48034407, 0x59a80038, 0x48034209, 0x0401f5d9, - 0x42007800, 0x0010b8ec, 0x59a00406, 0x4803c857, - 0x82000c80, 0x00000006, 0x04021622, 0x0c01f001, - 0x001024f6, 0x001024f7, 0x00102505, 0x00102518, - 0x00102539, 0x001024f6, 0x0401f61a, 0x836c0580, - 0x00000000, 0x04000613, 0x59a00a07, 0x59a00407, - 0x900001c0, 0x80040d40, 0x4807c857, 0x59a00a08, - 0x59a00408, 0x900001c0, 0x80040d40, 0x4807c857, - 0x0401f056, 0x836c0580, 0x00000000, 0x04000605, - 0x59a00407, 0x59a01207, 0x900001c0, 0x80081540, - 0x59a00408, 0x59a01a08, 0x900001c0, 0x800c1d40, - 0x42000000, 0x0010c1bf, 0x480fc857, 0x480bc857, - 0x42000800, 0x00001000, 0x0201f000, 0x00103a28, - 0x59a00a07, 0x59a00407, 0x900001c0, 0x80041d40, - 0x820c0c80, 0x0010ab4a, 0x040215f2, 0x820c0c80, - 0x00100000, 0x040015ef, 0x480fc857, 0x823c7c00, - 0x00000009, 0x503c0800, 0x800409c0, 0x04000006, - 0x823c0580, 0x0000000d, 0x040005e6, 0x803c7800, - 0x0401f7f9, 0x59e41001, 0x82080d00, 0xfffeffcf, - 0x4807c801, 0x440c7800, 0x46001800, 0x0201f800, - 0x800c1800, 0x46001800, 0x001005cb, 0x480bc801, - 0x0401f022, 0x59a01a07, 0x59a00407, 0x900001c0, - 0x800c1d40, 0x480c7801, 0x59a02208, 0x59a00408, - 0x900001c0, 0x80102540, 0x48107802, 0x59a00209, - 0x80000040, 0x040015cb, 0x48007806, 0x80000000, - 0x48007805, 0x42000800, 0x00004000, 0x40001000, - 0x0201f800, 0x00106681, 0x80000540, 0x04000003, - 0x49787801, 0x0401f5bf, 0x40040000, 0x800c1c00, - 0x040015bc, 0x480c7803, 0x48107804, 0x49787808, - 0x59a00409, 0x48007807, 0x59e40001, 0x4803c857, - 0x82000540, 0x00040000, 0x4803c801, 0x0401f561, - 0x59a80006, 0x48034406, 0x59a80007, 0x48034207, - 0x59a80008, 0x48034407, 0x0401f55a, 0x0201f800, - 0x001005d8, 0x4803c856, 0x4a03c013, 0x03800300, + 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, - 0x0402002b, 0x59a0140a, 0x82080480, 0x00000100, - 0x04021027, 0x59a0020b, 0x8c000500, 0x0402002e, - 0x59a00a0a, 0x800409c0, 0x04000021, 0x82040480, - 0x00000041, 0x0402101e, 0x82040c00, 0x00000003, - 0x82040d00, 0x000000fc, 0x80040904, 0x59a00407, - 0x59a01207, 0x900811c0, 0x80081540, 0x59a00409, - 0x59a01a09, 0x900c19c0, 0x800c1d40, 0x0201f800, - 0x00103a00, 0x04020006, 0x4a034406, 0x00000002, - 0x4a03c014, 0x03800000, 0x0401f576, 0x832e5c00, - 0x00000004, 0x412c0000, 0x0201f800, 0x00103a25, - 0x4a01d809, 0x001025a2, 0x1c01f000, 0x4a03c014, - 0x03800000, 0x0401f56f, 0x4031d800, 0x58ef400b, - 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200, - 0x0400055c, 0x59a00c06, 0x59a0140a, 0x59a0020b, - 0x8c000500, 0x04020031, 0x832e5c00, 0x00000004, + 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, - 0x50004000, 0x82201d00, 0x000000ff, 0x4c040000, - 0x0401f8ac, 0x5c000800, 0x0400002d, 0x80244840, - 0x04000028, 0x80081000, 0x82201d00, 0x0000ff00, - 0x800c1910, 0x4c040000, 0x0401f8a2, 0x5c000800, - 0x04000023, 0x80244840, 0x0400001e, 0x80081000, - 0x82201d00, 0x00ff0000, 0x800c1920, 0x4c040000, - 0x0401f898, 0x5c000800, 0x04000019, 0x80244840, - 0x04000014, 0x80081000, 0x82201d00, 0xff000000, - 0x800c1930, 0x4c040000, 0x0401f88e, 0x5c000800, - 0x0400000f, 0x80244840, 0x0400000a, 0x80081000, - 0x801c3800, 0x0401f7d5, 0x59a0020a, 0x82000500, - 0x000000ff, 0x40001800, 0x0401f882, 0x04000004, - 0x4a03c014, 0x03800000, 0x0401f4da, 0x4a03c014, - 0x03800000, 0x0401f523, 0x4803c856, 0x4a03c013, - 0x03800300, 0x4a03c014, 0x03800380, 0x59a00c06, - 0x82040580, 0x000000a0, 0x04000004, 0x82040580, - 0x000000a2, 0x0402006c, 0x59a0140a, 0x82080480, - 0x00000100, 0x04021068, 0x59a0020b, 0x8c000500, - 0x0402005c, 0x59a01a0a, 0x800c19c0, 0x04000062, - 0x820c0480, 0x00000041, 0x0402105f, 0x0201f800, - 0x00103a00, 0x04020006, 0x4a034406, 0x00000002, - 0x4a03c014, 0x03800000, 0x0401f502, 0x832e5c00, - 0x00000004, 0x41783800, 0x59a04a0a, 0x401c0000, - 0x812c0400, 0x40004000, 0x4c040000, 0x4c080000, - 0x0401f874, 0x5c001000, 0x5c000800, 0x04000047, - 0x44144000, 0x80244840, 0x0400002b, 0x80081000, - 0x4c040000, 0x4c080000, 0x0401f86a, 0x5c001000, - 0x5c000800, 0x0400003d, 0x50200000, 0x801428d0, - 0x80140540, 0x44004000, 0x80244840, 0x0400001e, - 0x80081000, 0x4c040000, 0x4c080000, 0x0401f85d, - 0x5c001000, 0x5c000800, 0x04000030, 0x50200000, - 0x801428e0, 0x80140540, 0x44004000, 0x80244840, - 0x04000011, 0x80081000, 0x4c040000, 0x4c080000, - 0x0401f850, 0x5c001000, 0x5c000800, 0x04000023, - 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, 0x00103a28, - 0x0401f830, 0x04000005, 0x48174406, 0x4a03c014, - 0x03800000, 0x0401f463, 0x4a03c014, 0x03800000, - 0x0401f4ac, 0x4a03c014, 0x03800000, 0x0401f4ad, - 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, + 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, 0x02000000, 0x82000540, - 0x00000001, 0x0401f002, 0x80000580, 0x5c000800, - 0x1c01f000, 0x4a03c013, 0x01000000, 0x42000000, + 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, 0x4a03c013, 0x01000100, 0x1c01f000, - 0x42002000, 0x00000008, 0x82040500, 0x00000080, - 0x800000c2, 0x82000540, 0x01000000, 0x4803c013, + 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, 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, + 0x80000040, 0x040207ff, 0x59e00013, 0x82000500, + 0x00000100, 0x80000110, 0x800408c2, 0x80040d40, + 0x4a03c013, 0x02000000, 0x80081040, 0x040207ed, + 0x40042800, 0x1c01f000, 0x4a03c013, 0x01000100, 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, 0x001022c0, 0x836c0580, 0x00000000, - 0x0400000e, 0x59a80006, 0x59a00c06, 0x80041580, - 0x82081500, 0x00000040, 0x02000000, 0x001022c0, - 0x80080580, 0x48035006, 0x0201f800, 0x00100699, - 0x0201f000, 0x001022c0, 0x59a00406, 0x59a80806, - 0x48035006, 0x80040d80, 0x8c040d0c, 0x02020800, - 0x00100699, 0x59a00207, 0x48035007, 0x59a00407, - 0x48035008, 0x0201f000, 0x001022c0, 0x800409c0, - 0x04000005, 0x4a034406, 0x00000001, 0x0201f000, - 0x0010230c, 0x0201f800, 0x0010513b, 0x04020005, - 0x4a034406, 0x00000016, 0x0201f000, 0x0010230c, - 0x836c0580, 0x00000003, 0x04000005, 0x4a034406, - 0x00000007, 0x0201f000, 0x0010230c, 0x59a00c06, - 0x82040500, 0xffffff00, 0x02020000, 0x00102310, - 0x82041580, 0x000000ff, 0x04020007, 0x59a80010, - 0x82000500, 0x000000ff, 0x82001540, 0x0000ff00, - 0x0401f011, 0x82040400, 0x0010210e, 0x50000000, - 0x80000110, 0x82000580, 0x00000080, 0x02000000, - 0x00102310, 0x59a80010, 0x82000500, 0x000000ff, - 0x80041580, 0x02000000, 0x00102310, 0x840409c0, - 0x80041540, 0x0201f800, 0x0002075a, 0x04020005, - 0x4a034406, 0x00000003, 0x0201f000, 0x0010230c, - 0x48ee6021, 0x480a621c, 0x4a02641c, 0x0000bc09, - 0x4a026406, 0x00000001, 0x0201f800, 0x00103a00, - 0x04020007, 0x0201f800, 0x0002077d, 0x4a034406, - 0x00000002, 0x0201f000, 0x0010230c, 0x497a5a04, - 0x497a5805, 0x4a025c04, 0x00008000, 0x4a01d809, - 0x001027f9, 0x492e6008, 0x42027000, 0x00000032, - 0x0201f000, 0x000207a1, 0x800409c0, 0x04000005, - 0x4a034406, 0x00000001, 0x0201f000, 0x0010230c, - 0x0201f800, 0x0010513b, 0x04020005, 0x4a034406, - 0x00000016, 0x0201f000, 0x0010230c, 0x836c0580, - 0x00000003, 0x04000005, 0x4a034406, 0x00000007, - 0x0201f000, 0x0010230c, 0x59a00c06, 0x82040500, - 0xffffff00, 0x02020000, 0x00102310, 0x82041580, - 0x000000ff, 0x04020007, 0x59a80010, 0x82000500, - 0x000000ff, 0x82001540, 0x0000ff00, 0x0401f011, - 0x82040400, 0x0010210e, 0x50000000, 0x80000110, - 0x82000580, 0x00000080, 0x02000000, 0x00102310, - 0x59a80010, 0x82000500, 0x000000ff, 0x80041580, - 0x02000000, 0x00102310, 0x840409c0, 0x80041540, - 0x0201f800, 0x0002075a, 0x04020005, 0x4a034406, - 0x00000003, 0x0201f000, 0x0010230c, 0x48ee6021, - 0x480a621c, 0x4a02641c, 0x0000bc05, 0x4a026406, - 0x00000001, 0x0201f800, 0x00103a00, 0x04020007, - 0x0201f800, 0x0002077d, 0x4a034406, 0x00000002, - 0x0201f000, 0x0010230c, 0x497a5a04, 0x497a5805, - 0x4a025c04, 0x00008000, 0x4a01d809, 0x001027f9, - 0x492e6008, 0x42027000, 0x00000032, 0x0201f000, - 0x000207a1, 0x592c0005, 0x82000580, 0x01000000, - 0x02020000, 0x001022c0, 0x4a034406, 0x00000004, - 0x0201f000, 0x0010230c, 0x497b4406, 0x497b4207, - 0x0201f800, 0x00103b25, 0x04000008, 0x59a80066, - 0x59a8086a, 0x80040480, 0x59a80867, 0x48074406, - 0x80041480, 0x480b4207, 0x49674407, 0x59a8000e, - 0x48034209, 0x495f4409, 0x59a80020, 0x4803420b, - 0x0201f000, 0x001022c0, 0x800409c0, 0x04000005, - 0x4a034406, 0x00000001, 0x0201f000, 0x0010230c, - 0x59a00406, 0x8c000500, 0x0402000f, 0x59a80069, - 0x81640480, 0x04001008, 0x59a8000b, 0x81500580, - 0x04000009, 0x59a8006a, 0x59a81066, 0x80080580, - 0x04000005, 0x4a034406, 0x00000018, 0x0201f000, - 0x0010230c, 0x82000540, 0x00000001, 0x0201f800, - 0x001015fe, 0x0201f800, 0x00103c80, 0x0201f000, - 0x001022c0, 0x4803c856, 0x800409c0, 0x02020000, - 0x00102314, 0x59a00406, 0x8c00051e, 0x04000008, - 0x4803c856, 0x59a0020b, 0x82000480, 0x00000800, - 0x04001015, 0x0201f000, 0x00102310, 0x4803c856, - 0x59a0020b, 0x599c0a01, 0x80040480, 0x04021003, - 0x0201f000, 0x00102310, 0x59a8000e, 0x81640580, - 0x04000009, 0x4a034406, 0x00000018, 0x0201f000, - 0x0010230c, 0x4a034406, 0x00000005, 0x0201f000, - 0x0010230c, 0x59a80026, 0x8c00050a, 0x040007fa, - 0x59a00406, 0x8c00051e, 0x04000036, 0x0201f800, - 0x0002075a, 0x040007f4, 0x0201f800, 0x00103a00, - 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, 0x00103a25, 0x4a01d809, 0x001029e5, - 0x4a034000, 0x00000001, 0x49334001, 0x1c01f000, - 0x0201f800, 0x00106c55, 0x0201f800, 0x00100ae0, - 0x0401f86d, 0x497b5057, 0x4201d000, 0x00002710, - 0x0201f800, 0x001060c6, 0x59c40880, 0x4c040000, - 0x59c408a3, 0x4c040000, 0x497b4002, 0x0401f876, - 0x0401f893, 0x4a03a005, 0x10000000, 0x0401f8b4, - 0x0401f901, 0x04000048, 0x59c80001, 0x800001c0, - 0x040007fc, 0x59c80018, 0x82000500, 0xf0000000, - 0x59c00808, 0x82040d00, 0x0fffffff, 0x80040540, - 0x48038008, 0x0201f800, 0x00100ec1, 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, 0x001005d8, - 0x59c00807, 0x82040d00, 0x0000000c, 0x040007fa, - 0x0401f003, 0x4a035057, 0x00000001, 0x0401f8da, - 0x0201f800, 0x00106f36, 0x0401f818, 0x4201d000, - 0x000186a0, 0x0201f800, 0x001060c6, 0x5c000800, - 0x480788a3, 0x5c000800, 0x48078880, 0x59a80057, - 0x800001c0, 0x02000000, 0x001022c0, 0x0201f000, - 0x00102318, 0x599c0201, 0x48035059, 0x41780800, - 0x42001000, 0x00003b10, 0x0201f800, 0x001066a0, - 0x480b505a, 0x1c01f000, 0x0201f800, 0x00106c4b, - 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, 0x00101345, 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, 0x001066a0, - 0x59940024, 0x80080400, 0x48032824, 0x80000580, - 0x1c01f000, 0x4d900000, 0x4dd00000, 0x4da40000, - 0x4d140000, 0x417a3000, 0x0201f800, 0x001070d8, - 0x0201f800, 0x00106dc3, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x1c01f000, 0x59c80007, - 0x8c000500, 0x04000003, 0x4a03900d, 0x00000030, - 0x1c01f000, 0x4a038805, 0x00020000, 0x42000800, - 0x0000003c, 0x0201f800, 0x00101345, 0x4a038891, - 0x0000ffff, 0x59c80035, 0x48039035, 0x4a03900d, - 0x00000040, 0x42038000, 0x00007700, 0x0201f800, - 0x00100ec1, 0x42038000, 0x00007720, 0x0201f800, - 0x00100ec1, 0x4a03a005, 0x20000000, 0x4a03a005, - 0x30000000, 0x59d00806, 0x8c040d0a, 0x040207fe, - 0x1c01f000, 0x4d300000, 0x4031d800, 0x58ef400b, - 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200, - 0x5c026000, 0x02000000, 0x00102304, 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, 0x00103a25, 0x4a01d809, 0x001029e5, - 0x0401f007, 0x832c0400, 0x00000006, 0x0201f800, - 0x00103a28, 0x4a01d809, 0x001029e5, 0x5c026000, - 0x1c01f000, 0x58ec000d, 0x40025800, 0x592c0204, - 0x82000580, 0x00000103, 0x04020006, 0x0201f800, - 0x0002077d, 0x5c026000, 0x0201f000, 0x001022c0, - 0x58ec000d, 0x40025800, 0x592c0404, 0x8400055e, - 0x48025c04, 0x42028800, 0x000007fd, 0x42003000, - 0x00fffffd, 0x0201f800, 0x001045a6, 0x04000003, - 0x80000580, 0x0401f004, 0x59a26001, 0x0201f800, - 0x0010937d, 0x5c026000, 0x02000000, 0x0010230c, - 0x4d300000, 0x4a01d809, 0x00102a38, 0x0401f7dc, - 0x592c0005, 0x82000580, 0x01000000, 0x02000000, - 0x00102318, 0x4d300000, 0x59a26001, 0x5930020b, - 0x59301c0a, 0x900001c0, 0x800c1d40, 0x5930040d, - 0x5930120d, 0x900001c0, 0x80081540, 0x592c0a05, - 0x832c0400, 0x00000006, 0x0201f800, 0x00103a28, - 0x4a01d809, 0x001029e5, 0x4a034000, 0x00000001, - 0x5c026000, 0x1c01f000, 0x4933c857, 0x4c300000, - 0x5930040b, 0x82000c80, 0x0000000e, 0x04001004, - 0x4a025a05, 0x0000000e, 0x0401f003, 0x48025a05, - 0x0401f00c, 0x800409c0, 0x0400000a, 0x4c040000, - 0x0201f800, 0x00103a00, 0x5c000800, 0x04000003, - 0x40040000, 0x0401f7f0, 0x80000580, 0x0401f003, - 0x82000540, 0x00000001, 0x5c006000, 0x1c01f000, - 0x59a00206, 0x82000580, 0x00000044, 0x1c01f000, - 0x4807c857, 0x800409c0, 0x0400000c, 0x0201f800, - 0x00101650, 0x04020009, 0x42000000, 0x00000002, - 0x0201f800, 0x0010188c, 0x42000000, 0x00000002, - 0x0201f800, 0x00101821, 0x59a00406, 0x82000500, - 0x00000007, 0x0c01f001, 0x00102a8c, 0x00102aa1, - 0x00102ab7, 0x00102a8a, 0x00102a8a, 0x00102a8a, - 0x00102a8a, 0x00102a8a, 0x0201f000, 0x00102310, - 0x42000800, 0x000000c0, 0x0201f800, 0x0010193f, - 0x82040540, 0x00000002, 0x42000800, 0x000000c0, - 0x0201f800, 0x00101944, 0x42000800, 0x00000000, - 0x0201f800, 0x0010193f, 0x82040540, 0x00000008, - 0x42000800, 0x00000000, 0x0201f800, 0x00101944, - 0x0401f00b, 0x42000800, 0x000000c0, 0x0201f800, - 0x0010193f, 0x82040540, 0x00000001, 0x42000800, - 0x000000c0, 0x0201f800, 0x00101944, 0x59c80040, - 0x4c000000, 0x59a80010, 0x4c000000, 0x59c400a3, - 0x4c000000, 0x59c40008, 0x4c000000, 0x0401f911, - 0x04000021, 0x0201f800, 0x001005d8, 0x59a80821, - 0x800409c0, 0x02020000, 0x00102314, 0x0201f800, - 0x0010513b, 0x04020005, 0x4a034406, 0x00000016, - 0x0201f000, 0x0010230c, 0x836c0580, 0x00000003, - 0x02020000, 0x00102314, 0x59c408a4, 0x82040d00, - 0x0000000f, 0x82040580, 0x00000000, 0x02020000, - 0x00102314, 0x59c80040, 0x4c000000, 0x59a80010, - 0x4c000000, 0x59c400a3, 0x4c000000, 0x59c40008, - 0x4c000000, 0x59c40080, 0x4c000000, 0x59a0020f, - 0x59a0bc0f, 0x905cb9c0, 0x805cbd40, 0x41784800, - 0x41785000, 0x41785800, 0x41789000, 0x41789800, - 0x0401fe21, 0x0201f800, 0x00106c55, 0x0201f800, - 0x00100ae0, 0x4178c000, 0x497b4002, 0x0401f95c, - 0x0401f9aa, 0x59a0020c, 0x59a00c0c, 0x80040d40, - 0x04000002, 0x0401f9fb, 0x0401f9fa, 0x0401fe68, - 0x8060c1c0, 0x04020014, 0x0401fa98, 0x0401feb2, - 0x0402000e, 0x0201f800, 0x001018d3, 0x04020008, - 0x4a034406, 0x00000017, 0x0201f800, 0x0010230c, + 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, - 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, 0x001018d3, 0x04020008, 0x4a034406, - 0x00000017, 0x0201f800, 0x0010230c, 0x4203e000, - 0x50000000, 0x0401f000, 0x42005800, 0x0000dddd, - 0x0401f005, 0x59c00807, 0x82040d00, 0x0000000c, - 0x040007ea, 0x0401fe5c, 0x59a0040c, 0x800001c0, - 0x04000002, 0x0401f856, 0x0401fe6b, 0x40240000, - 0x80280540, 0x802c0540, 0x04020003, 0x805cb9c0, - 0x04020781, 0x0201f800, 0x00106f36, 0x0401fda3, - 0x4201d000, 0x000186a0, 0x0201f800, 0x001060c6, - 0x5c000800, 0x48078880, 0x5c000800, 0x48078808, - 0x5c000800, 0x480788a3, 0x5c000800, 0x48075010, - 0x5c000800, 0x48079040, 0x0201f800, 0x00100969, - 0x59a00406, 0x82000500, 0x00000003, 0x82000580, - 0x00000002, 0x0400002c, 0x42000800, 0x000000c0, - 0x0201f800, 0x0010193f, 0x82040500, 0xfffffffc, - 0x42000800, 0x000000c0, 0x0201f800, 0x00101944, - 0x42000800, 0x00000000, 0x0201f800, 0x0010193f, - 0x82040500, 0xfffffff7, 0x42000800, 0x00000000, - 0x0201f800, 0x00101944, 0x42000800, 0x00000000, - 0x0201f800, 0x0010193f, 0x82040500, 0xfffffffb, - 0x42000800, 0x00000000, 0x0201f800, 0x00101944, - 0x4a0388a7, 0x0000f7f7, 0x42006000, 0xbeffffff, - 0x42006800, 0x80018000, 0x0201f800, 0x0010427d, - 0x42006000, 0xfffeffff, 0x41786800, 0x0201f800, - 0x0010427d, 0x402c0000, 0x80280540, 0x80240540, - 0x02000000, 0x001022c0, 0x48274406, 0x482b4207, - 0x482f4407, 0x0201f000, 0x0010231c, 0x59a26000, - 0x813261c0, 0x0400000e, 0x59325808, 0x812e59c0, - 0x0400000b, 0x0201f800, 0x0002077d, 0x0201f800, - 0x001007fd, 0x59a26001, 0x59325808, 0x0201f800, - 0x0002077d, 0x0201f800, 0x001007fd, 0x1c01f000, - 0x42000800, 0x000000ef, 0x0201f800, 0x001015eb, - 0x59c400a3, 0x8400055a, 0x8400053a, 0x480388a3, - 0x0201f800, 0x0010163b, 0x0402000a, 0x42000000, - 0x00000001, 0x0201f800, 0x0010188c, 0x42000000, - 0x00000001, 0x0201f800, 0x00101821, 0x0401f013, - 0x0201f800, 0x00101642, 0x04020008, 0x41780000, - 0x0201f800, 0x0010188c, 0x41780000, 0x0201f800, - 0x00101821, 0x0401f009, 0x42000000, 0x00000002, - 0x0201f800, 0x0010188c, 0x42000000, 0x00000002, - 0x0201f800, 0x00101821, 0x42000800, 0x00000000, - 0x0201f800, 0x0010193f, 0x82040540, 0x00000004, - 0x42000800, 0x00000000, 0x0201f800, 0x00101944, - 0x4201d000, 0x00000014, 0x0201f800, 0x0010608e, - 0x59c40008, 0x8400054e, 0x82000500, 0xffffffe1, - 0x48038808, 0x4a0388a7, 0x0000f7f7, 0x42001000, - 0x04000001, 0x0201f800, 0x0010193d, 0x42006000, - 0xbe20bfff, 0x42006800, 0x80018000, 0x0201f800, - 0x0010427d, 0x42006000, 0xfffeffff, 0x41786800, - 0x0201f800, 0x0010427d, 0x4200b000, 0x00001388, - 0x4201d000, 0x00000014, 0x4c580000, 0x0201f800, - 0x0010608e, 0x0201f800, 0x001018d3, 0x5c00b000, - 0x04000004, 0x8058b040, 0x040207f6, 0x0401f025, - 0x59c40005, 0x8c000534, 0x04020007, 0x59c400a4, - 0x82000500, 0x0000000f, 0x82000580, 0x00000008, - 0x0402001c, 0x42006000, 0x00020000, 0x0201f800, - 0x00104282, 0x4201d000, 0x00000064, 0x0201f800, - 0x0010608e, 0x42006000, 0xfeffffff, 0x42006800, - 0x02000000, 0x0201f800, 0x0010427d, 0x42006000, - 0xfdffffff, 0x41786800, 0x0201f800, 0x0010427d, - 0x4a038805, 0x04000001, 0x59c400a4, 0x82000500, - 0x0000000f, 0x82000580, 0x00000000, 0x04000003, - 0x82000540, 0x00000001, 0x1c01f000, 0x4803c856, - 0x42038000, 0x00007700, 0x0201f800, 0x00100ec1, - 0x59c00006, 0x59a0040c, 0x800001c0, 0x0400003f, - 0x59a03c0c, 0x59a00209, 0x59a01c09, 0x900c19c0, - 0x800c1d40, 0x59a0020e, 0x59a0240e, 0x901021c0, - 0x80102540, 0x59a0020b, 0x82000500, 0x0000fffc, - 0x59a0140b, 0x900811c0, 0x80081540, 0x480b8003, - 0x0201f800, 0x0002075a, 0x02000800, 0x001005d8, - 0x49334000, 0x0201f800, 0x001007e4, 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, 0x00101345, 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, 0x0002075a, 0x02000800, - 0x001005d8, 0x49334001, 0x0201f800, 0x001007e4, + 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, 0x0401f906, 0x0401f004, - 0x41783800, 0x0401f903, 0x0401f011, 0x821c0c80, + 0x04000004, 0x801c3840, 0x0401f963, 0x0401f004, + 0x41783800, 0x0401f960, 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, + 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, - 0x0400001a, 0x492e600b, 0x832c0c00, 0x00000005, + 0x0400001d, 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, 0x001060c6, 0x480ba002, 0x59a80059, - 0x4803a008, 0x4813a000, 0x480fa001, 0x4a03a005, - 0x10000000, 0x02005800, 0x001005d8, 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, 0x001005d8, - 0x404c0000, 0x0c01f001, 0x00102da1, 0x00102da3, - 0x00102da9, 0x0201f800, 0x001005d8, 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, 0x001005d8, 0x40480000, - 0x0c01f001, 0x00102dc4, 0x00102dc6, 0x00102dce, - 0x0201f800, 0x001005d8, 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, 0x001007e4, - 0x5c000800, 0x02000800, 0x001005d8, 0x4a025a04, - 0x0000000a, 0x492c0801, 0x1c01f000, 0x42006000, - 0x00102fb2, 0x0201f800, 0x00101345, 0x4a03902c, - 0x00200000, 0x4200b000, 0x000001f4, 0x59c8002c, - 0x8c00052c, 0x04000007, 0x8058b040, 0x040207fc, - 0x42000000, 0x00004003, 0x41781000, 0x0401f196, - 0x50301000, 0x41784800, 0x4a03902d, 0x00008000, - 0x4200b000, 0x000001f4, 0x59c8002c, 0x8c000534, + 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, 0x0401f187, 0x0401f8f8, - 0x80244800, 0x40240000, 0x82000580, 0x000003b1, - 0x040207fb, 0x0401f988, 0x41784800, 0x0401f920, - 0x80244800, 0x40240000, 0x82000580, 0x000003b1, - 0x040207fb, 0x80306000, 0x82300580, 0x00102fb4, - 0x040207e0, 0x59a80863, 0x800409c0, 0x04000007, - 0x42000000, 0x00004004, 0x42001000, 0x00000002, - 0x59a81862, 0x0401f16c, 0x42006000, 0x00102fb2, - 0x4a035064, 0x00000004, 0x50301000, 0x41784800, - 0x4a03902d, 0x00004000, 0x4200b000, 0x000001f4, - 0x59c8002c, 0x8c000532, 0x04000007, 0x8058b040, - 0x040207fc, 0x42000000, 0x00004003, 0x41781000, - 0x0401f159, 0x0401f8ca, 0x80244800, 0x40240000, - 0x82000580, 0x00000154, 0x040207fb, 0x0401f95a, - 0x41784800, 0x0401f8f2, 0x80244800, 0x40240000, - 0x82000580, 0x00000154, 0x040207fb, 0x80306000, - 0x82300580, 0x00102fb4, 0x040207e0, 0x59a80863, - 0x800409c0, 0x04000007, 0x42000000, 0x00004004, - 0x42001000, 0x00000004, 0x59a81862, 0x0401f13e, - 0x42006000, 0x00102fb2, 0x497b5064, 0x50301000, - 0x41784800, 0x4a03902d, 0x00001000, 0x4200b000, - 0x000001f4, 0x59c8002c, 0x8c00052e, 0x04000007, + 0x00004003, 0x41781000, 0x0401f11e, 0x50301000, + 0x41784800, 0x4a03902d, 0x00008000, 0x4200b000, + 0x000001f4, 0x59c8002c, 0x8c000534, 0x04000007, 0x8058b040, 0x040207fc, 0x42000000, 0x00004003, - 0x41781000, 0x0401f12c, 0x0401f89d, 0x80244800, - 0x40240000, 0x82000580, 0x00000088, 0x040207fb, - 0x0401f92d, 0x41784800, 0x0401f8c5, 0x80244800, - 0x40240000, 0x82000580, 0x00000088, 0x040207fb, - 0x80306000, 0x82300580, 0x00102fb4, 0x040207e0, - 0x59a80863, 0x800409c0, 0x04000007, 0x42000000, - 0x00004004, 0x42001000, 0x00000001, 0x59a81862, - 0x0401f111, 0x42006000, 0x00102fb2, 0x50301000, - 0x41784800, 0x4a03902d, 0x00000800, 0x0401f87c, - 0x80244800, 0x40240000, 0x82000580, 0x00000018, - 0x040207fb, 0x0401f90c, 0x41784800, 0x0401f8a4, - 0x80244800, 0x40240000, 0x82000580, 0x00000018, - 0x040207fb, 0x80306000, 0x82300580, 0x00102fb4, - 0x040207eb, 0x59a80863, 0x800409c0, 0x04000007, + 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, 0x0401f0f0, 0x42006000, 0x00102fb2, + 0x59a81862, 0x0401f0d7, 0x42006000, 0x00102d9d, 0x50301000, 0x41784800, 0x4a03902d, 0x00000400, - 0x0401f85b, 0x80244800, 0x40240000, 0x82000580, - 0x00000088, 0x040207fb, 0x0401f8eb, 0x41784800, - 0x0401f883, 0x80244800, 0x40240000, 0x82000580, - 0x00000088, 0x040207fb, 0x80306000, 0x82300580, - 0x00102fb4, 0x040207eb, 0x59a80863, 0x800409c0, - 0x04000007, 0x42000000, 0x00004004, 0x42001000, - 0x00000008, 0x59a81862, 0x0401f0cf, 0x42006000, - 0x00102fb2, 0x50301000, 0x41784800, 0x4a03902d, - 0x00002000, 0x4200b000, 0x000001f4, 0x59c8002c, - 0x8c000530, 0x04000007, 0x8058b040, 0x040207fc, - 0x42000000, 0x00004003, 0x41781000, 0x0401f0be, - 0x59c8002c, 0x82000500, 0xffe0ffff, 0x82080d00, - 0x001f0000, 0x80040540, 0x4803902c, 0x0401f828, - 0x80244800, 0x40240000, 0x82000580, 0x00000110, - 0x040207fb, 0x0401f8b8, 0x41784800, 0x0401f850, - 0x59c80034, 0x82080d00, 0x001f0000, 0x82000500, - 0x001f0000, 0x80040580, 0x04000006, 0x59a80063, - 0x80000000, 0x48035063, 0x40240000, 0x48035062, - 0x80244800, 0x40240000, 0x82000580, 0x00000110, - 0x040207ef, 0x80306000, 0x82300580, 0x00102fb4, - 0x040207cd, 0x59a80863, 0x800409c0, 0x04000006, + 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, 0x001022c0, 0x59c8002c, + 0x59a81862, 0x0201f000, 0x00102066, 0x59c8002c, 0x82000500, 0xffff0000, 0x82080d00, 0x0000ffff, - 0x80040540, 0x4803902c, 0x40080000, 0x48039028, - 0x48039029, 0x59a80064, 0x82000580, 0x00000004, - 0x04000004, 0x40080000, 0x4803902a, 0x4803902b, - 0x59c8082d, 0x82040d00, 0xfffffc00, 0x40240000, - 0x80040d40, 0x4807902d, 0x4200b000, 0x000001f4, + 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, 0x0401f06c, 0x4a03902e, 0x00000001, - 0x4200b000, 0x000001f4, 0x59c8002e, 0x8c000500, - 0x04000006, 0x8058b040, 0x040207fc, 0x42000000, - 0x00004003, 0x0401f060, 0x1c01f000, 0x41783800, - 0x59c8082d, 0x82040d00, 0xfffffc00, 0x40240000, - 0x80040d40, 0x4807902d, 0x4200b000, 0x000001f4, - 0x59c8002c, 0x82000500, 0x18000000, 0x04000007, - 0x8058b040, 0x040207fb, 0x42000000, 0x00004003, - 0x41781000, 0x0401f04c, 0x59c80030, 0x59c80830, - 0x80040580, 0x040207fd, 0x40041800, 0x59c80031, - 0x59c80831, 0x80040580, 0x040207fd, 0x40042000, - 0x59c80032, 0x59c80832, 0x80040580, 0x040207fd, - 0x40042800, 0x59c80033, 0x59c80833, 0x80040580, - 0x040207fd, 0x40043000, 0x400c0000, 0x80080580, - 0x04000002, 0x801c3800, 0x40100000, 0x80080580, - 0x04000002, 0x801c3800, 0x59a80064, 0x82000580, - 0x00000004, 0x04000009, 0x40140000, 0x80080580, - 0x04000002, 0x801c3800, 0x40180000, 0x80080580, - 0x04000002, 0x801c3800, 0x59a80064, 0x82000580, - 0x00000004, 0x0400000d, 0x59c80034, 0x59c80834, - 0x80040580, 0x040207fd, 0x82040500, 0x0000ffff, - 0x82080d00, 0x0000ffff, 0x80040580, 0x0400000e, - 0x801c3800, 0x0401f00c, 0x59c80034, 0x59c80834, - 0x80040580, 0x040207fd, 0x82040500, 0x000000ff, - 0x82080d00, 0x000000ff, 0x80040580, 0x04000002, - 0x801c3800, 0x801c39c0, 0x04000006, 0x59a80063, - 0x801c0400, 0x48035063, 0x40240000, 0x48035062, - 0x1c01f000, 0x48034206, 0x48074406, 0x480b4207, - 0x480f4407, 0x48134208, 0x48174408, 0x0201f000, - 0x001022c3, 0x42000000, 0x00600000, 0x80000040, - 0x040207ff, 0x1c01f000, 0x5a5a5a5a, 0xa5a5a5a5, - 0x59a00c0a, 0x800409c0, 0x02000000, 0x00102310, - 0x82040480, 0x00000021, 0x02021000, 0x00102310, + 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, 0x0201f800, 0x00103a00, 0x04000006, - 0x0201f800, 0x00103a25, 0x4a01d809, 0x00102fd5, - 0x1c01f000, 0x4a034406, 0x00000002, 0x0201f000, - 0x0010230c, 0x4031d800, 0x58ef400b, 0x58ec0002, - 0x82000580, 0x00000200, 0x02000000, 0x00102304, - 0x59a00c0a, 0x82040480, 0x00000011, 0x04001003, - 0x42000800, 0x00000010, 0x59a0040b, 0x59a0120b, - 0x900811c0, 0x80081540, 0x59a00209, 0x59a01c08, - 0x900c19c0, 0x800c1d40, 0x58ec0003, 0x0201f800, - 0x00103a28, 0x4a01d809, 0x00102ff0, 0x1c01f000, - 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x00102304, 0x59a00c0a, - 0x82040480, 0x00000011, 0x02001000, 0x001022c0, - 0x82040c80, 0x00000010, 0x59a00208, 0x59a01407, - 0x900811c0, 0x80081540, 0x59a00207, 0x59a01c06, - 0x900c19c0, 0x800c1d40, 0x82081400, 0x00000040, - 0x58ec0003, 0x0201f800, 0x00103a25, 0x4a01d809, - 0x0010300e, 0x1c01f000, 0x4031d800, 0x58ef400b, + 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, - 0x00102304, 0x59a0040a, 0x82000c80, 0x00000010, - 0x59a0040b, 0x59a0120b, 0x900811c0, 0x80081540, - 0x59a00209, 0x59a01c08, 0x900c19c0, 0x800c1d40, - 0x82081400, 0x00000040, 0x58ec0003, 0x0201f800, - 0x00103a28, 0x4a01d809, 0x001022b9, 0x1c01f000, - 0x48efc857, 0x59a00207, 0x59a01407, 0x900001c0, - 0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0, - 0x800c1d40, 0x59a00406, 0x48034000, 0x480b4001, - 0x480f4002, 0x0201f800, 0x00103a00, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c, - 0x42000800, 0x00000010, 0x0201f800, 0x00103a25, - 0x4a01d809, 0x00103043, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x00102304, 0x48efc857, - 0x49a3c857, 0x492fc857, 0x592c0a04, 0x80040910, - 0x04020005, 0x4a034406, 0x00000019, 0x0201f000, - 0x0010230c, 0x4805d80c, 0x0401f00a, 0x4031d800, - 0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x00102304, 0x48efc857, 0x49a3c857, - 0x48efc857, 0x49a3c857, 0x58ec000c, 0x80000040, - 0x04000012, 0x4801d80c, 0x0201f800, 0x00103a00, - 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x0010230c, 0x42000800, 0x00000010, 0x58ec1007, - 0x58ec1808, 0x0201f800, 0x00103a25, 0x4a01d809, - 0x00103057, 0x1c01f000, 0x58ee580d, 0x48efc857, - 0x49a3c857, 0x492fc857, 0x492f3006, 0x592c0404, - 0x8400055e, 0x48025c04, 0x4a01d809, 0x00103081, + 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, 0x0201f000, 0x00103a28, - 0x800409c0, 0x04000005, 0x4a034406, 0x00000001, - 0x0201f000, 0x0010230c, 0x836c0580, 0x00000003, - 0x04000005, 0x4a034406, 0x00000007, 0x0201f000, - 0x0010230c, 0x59a0320b, 0x82183500, 0x000000ff, - 0x59a28c06, 0x0201f800, 0x00020245, 0x02020000, - 0x00102310, 0x83440580, 0x000007fd, 0x04000008, - 0x0201f800, 0x001049e7, 0x04000005, 0x4a034406, - 0x00000009, 0x0201f000, 0x0010230c, 0x0201f800, - 0x00103a00, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x0010230c, 0x801831c0, 0x0400000a, - 0x412c0800, 0x0201f800, 0x00103a00, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c, - 0x40065800, 0x4a025c04, 0x00008000, 0x497a5a04, - 0x0201f800, 0x00109100, 0x04020005, 0x4a034406, - 0x00000003, 0x0201f000, 0x0010230c, 0x4a01d809, - 0x001030d2, 0x1c01f000, 0x592c0005, 0x82000580, - 0x01000000, 0x04020005, 0x4a034406, 0x00000004, - 0x0201f000, 0x0010230c, 0x592c0406, 0x82002d00, - 0x0000ff00, 0x82000500, 0x000000ff, 0x80000904, - 0x80040800, 0x82040480, 0x00000006, 0x04001003, - 0x42000800, 0x00000005, 0x832ca400, 0x00000006, - 0x4050a800, 0x4004b000, 0x0201f800, 0x0010ab28, + 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, - 0x00103a28, 0x5c002800, 0x801429c0, 0x04000003, - 0x4a01d809, 0x001030ff, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x00102304, 0x812e59c0, - 0x02000800, 0x001005d8, 0x592c0006, 0x82000500, - 0xff000000, 0x80000904, 0x800409c0, 0x02000000, - 0x00102304, 0x82040480, 0x0000000e, 0x04001003, - 0x42000800, 0x0000000d, 0x592e5801, 0x812e59c0, - 0x02000800, 0x001005d8, 0x832ca400, 0x00000005, - 0x4050a800, 0x4004b000, 0x0201f800, 0x0010ab28, - 0x58ec1007, 0x58ec1808, 0x832c0400, 0x00000005, - 0x0201f000, 0x00103a28, 0x0201f800, 0x00103a00, - 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x0010230c, 0x59a00c06, 0x82040500, 0x0000ff00, - 0x840001c0, 0x82001480, 0x00000007, 0x02021000, - 0x00102310, 0x0c01f001, 0x0010313d, 0x00103144, - 0x0010314b, 0x0010314b, 0x0010314b, 0x0010314d, - 0x00103152, 0x42000800, 0x0000000d, 0x42003800, - 0x00103166, 0x4a034000, 0x0010b4eb, 0x0401f013, - 0x42000800, 0x0000000d, 0x42003800, 0x00103166, - 0x4a034000, 0x0010b4f8, 0x0401f00c, 0x0201f000, - 0x00102310, 0x42000800, 0x00000008, 0x42003800, - 0x00103179, 0x0401f005, 0x42000800, 0x00000004, - 0x42003800, 0x001031c3, 0x59a00207, 0x59a01407, - 0x900001c0, 0x80081540, 0x59a00209, 0x59a01c09, - 0x900001c0, 0x800c1d40, 0x832c0400, 0x00000005, - 0x4c1c0000, 0x0201f800, 0x00103a25, 0x5c003800, - 0x481dd809, 0x1c01f000, 0x4031d800, 0x58ef400b, + 0x00103841, 0x5c002800, 0x801429c0, 0x04000003, + 0x4a01d809, 0x00102ef2, 0x5c00b000, 0x5c00a800, + 0x5c00a000, 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x00102304, 0x4a03501f, 0x00000001, - 0x4200b000, 0x0000000d, 0x59a0a800, 0x832ca400, - 0x00000005, 0x0201f800, 0x0010ab17, 0x0201f000, - 0x001022c0, 0x4031d800, 0x58ef400b, 0x58ee580d, - 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x00102304, 0x832ca400, 0x00000005, 0x50500000, - 0x82001500, 0x000c0016, 0x02020000, 0x00102310, - 0x82500c00, 0x00000003, 0x50040000, 0x82001500, - 0x00000001, 0x02020000, 0x00102310, 0x50500000, - 0x82001500, 0x00000028, 0x0400001d, 0x82081580, - 0x00000028, 0x02020000, 0x00102310, 0x80500800, - 0x50040000, 0x82001500, 0x00000013, 0x82081580, - 0x00000013, 0x02020000, 0x00102310, 0x80040800, - 0x50040000, 0x82001500, 0x00010000, 0x82081580, - 0x00010000, 0x02020000, 0x00102310, 0x836c0580, - 0x00000000, 0x04000012, 0x599c0019, 0x8c00050e, - 0x0402000f, 0x0201f000, 0x00102310, 0x80500800, - 0x50040000, 0x82001500, 0x00000013, 0x02020000, - 0x00102310, 0x80040800, 0x50040000, 0x82001500, - 0x00010000, 0x02020000, 0x00102310, 0x4200b000, - 0x00000008, 0x4200a800, 0x0010b4e3, 0x0201f800, - 0x0010ab17, 0x0201f000, 0x001022c0, 0x4031d800, - 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x00102304, 0x4200b000, - 0x00000004, 0x4200a800, 0x0010b8fa, 0x832ca400, - 0x00000005, 0x0201f800, 0x0010ab17, 0x59a80005, - 0x84000550, 0x48035005, 0x0201f000, 0x001022c0, - 0x0201f800, 0x00103a00, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x0010230c, 0x59a00c06, - 0x82040500, 0x0000ff00, 0x840001c0, 0x82001480, - 0x00000006, 0x02021000, 0x00102310, 0x0c01f001, - 0x001031ee, 0x001031f3, 0x001031f8, 0x001031f8, - 0x001031f8, 0x001031fa, 0x42000800, 0x0000000d, - 0x4200a000, 0x0010b4eb, 0x0401f00c, 0x42000800, - 0x0000000d, 0x4200a000, 0x0010b4f8, 0x0401f007, - 0x0201f000, 0x00102310, 0x42000800, 0x00000008, - 0x4200a000, 0x0010b4e3, 0x4004b000, 0x832cac00, - 0x00000005, 0x0201f800, 0x0010ab17, 0x59a00207, + 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, 0x0201f000, 0x00103a28, 0x836c0580, - 0x00000000, 0x04020005, 0x4a034406, 0x00000007, - 0x0201f000, 0x0010230c, 0x59a00406, 0x800001c0, - 0x0400001a, 0x59a80005, 0x8c000514, 0x04000005, - 0x42000000, 0x00000001, 0x40000800, 0x0401f003, - 0x59a00207, 0x59a80853, 0x48035053, 0x0201f800, - 0x0010163b, 0x04000022, 0x0201f800, 0x00101642, - 0x0400001f, 0x0201f800, 0x00101649, 0x0400001c, - 0x0201f800, 0x00101650, 0x04000019, 0x48075053, - 0x0201f000, 0x00102310, 0x59c40801, 0x82040d00, + 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, 0x0401f00d, 0x82040580, + 0x4a034406, 0x00000000, 0x0401f048, 0x82040580, 0x00008000, 0x04020004, 0x4a034406, 0x00000001, - 0x0401f007, 0x82040580, 0x00010000, 0x02020800, - 0x001005d8, 0x4a034406, 0x00000003, 0x59a00406, - 0x82000580, 0x00000002, 0x0402001f, 0x59c40006, - 0x84000500, 0x48038806, 0x0201f800, 0x00106ede, - 0x497b8880, 0x0201f800, 0x0010a9c0, 0x0201f800, - 0x0010a9ce, 0x42000000, 0x0010b8ca, 0x0201f800, - 0x0010aa47, 0x82000540, 0x00000001, 0x0201f800, - 0x0010518c, 0x4a038808, 0x00000000, 0x4202d800, - 0x00000004, 0x42001000, 0x00000001, 0x0201f800, - 0x0010193d, 0x4a035049, 0x00000001, 0x0201f800, - 0x001006d4, 0x0201f000, 0x001022c0, 0x800409c0, - 0x04000005, 0x4a034406, 0x00000001, 0x0201f000, - 0x0010230c, 0x836c0580, 0x00000003, 0x04000005, - 0x4a034406, 0x00000007, 0x0201f000, 0x0010230c, - 0x59a28c06, 0x59a0320b, 0x82183500, 0x000000ff, - 0x0201f800, 0x00020245, 0x02020000, 0x00102310, - 0x83440580, 0x000007fd, 0x04000008, 0x0201f800, - 0x001049e7, 0x04000005, 0x42000800, 0x00000009, - 0x0201f000, 0x0010230c, 0x0201f800, 0x00103a00, - 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x0010230c, 0x497a5a04, 0x4a025c04, 0x00008000, - 0x0201f800, 0x00109115, 0x04020005, 0x4a034406, - 0x00000003, 0x0201f000, 0x0010230c, 0x4a01d809, - 0x0010329e, 0x1c01f000, 0x592c0005, 0x82000d00, - 0x0000ffff, 0x82000500, 0xffff0000, 0x82000580, - 0x01000000, 0x04020005, 0x4a034406, 0x00000004, - 0x0201f000, 0x0010230c, 0x80040904, 0x832ca400, + 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, - 0x0010ab28, 0x59a00207, 0x59a01407, 0x900001c0, - 0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0, - 0x800c1d40, 0x832c0400, 0x00000005, 0x0201f000, - 0x00103a28, 0x496fc857, 0x836c0580, 0x00000000, - 0x04000005, 0x4a034406, 0x0000001a, 0x0201f000, - 0x0010230c, 0x0201f800, 0x0010513b, 0x02020800, - 0x00104142, 0x42000800, 0x00000020, 0x59a00407, - 0x59a01207, 0x900811c0, 0x80081540, 0x59a00409, - 0x59a01a09, 0x900c19c0, 0x800c1d40, 0x419c0000, - 0x49a3c857, 0x0201f800, 0x00103a25, 0x4a01d809, - 0x001032da, 0x1c01f000, 0x4833c857, 0x4031d800, - 0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x00102304, 0x599c0200, 0x800001c0, - 0x02000000, 0x00102310, 0x59a80005, 0x8c000512, - 0x04000004, 0x599c0019, 0x8400050c, 0x48033819, - 0x0201f800, 0x001097d7, 0x59a80005, 0x8c000514, - 0x04000004, 0x599c0017, 0x84000508, 0x48033817, - 0x0201f800, 0x00103b25, 0x04020004, 0x8c00050a, - 0x02020000, 0x00102310, 0x4803c857, 0x8c000504, - 0x04020004, 0x59c408a3, 0x84040d7a, 0x480788a3, - 0x8c000502, 0x04020004, 0x59c408a3, 0x84040d08, - 0x480788a3, 0x599c0c02, 0x8c000500, 0x04020004, - 0x8c000516, 0x04000012, 0x0401f001, 0x82041480, - 0x0000007f, 0x02021000, 0x00102310, 0x82041400, - 0x0010210e, 0x50081000, 0x82081500, 0x000000ff, - 0x8c000500, 0x04020006, 0x480b5010, 0x42000800, - 0x00000003, 0x0201f800, 0x00106c78, 0x599c0019, - 0x8c00050e, 0x0402000b, 0x59a80806, 0x8c040d14, - 0x04000008, 0x42000800, 0x0010b4e3, 0x50040800, - 0x82040d00, 0x00000028, 0x02020000, 0x00102310, - 0x82000500, 0x00000030, 0x04000003, 0x80000108, - 0x0401f003, 0x42000000, 0x00000002, 0x48039040, - 0x42000800, 0x00000002, 0x82000400, 0x00103415, - 0x50001000, 0x0201f800, 0x00106c78, 0x599c0201, - 0x82000c80, 0x00000100, 0x02001000, 0x00102310, - 0x82000c80, 0x00000841, 0x02021000, 0x00102310, - 0x82000500, 0x00000007, 0x02020000, 0x00102310, - 0x599c0401, 0x80000540, 0x02000000, 0x00102310, - 0x599c0409, 0x599c0c07, 0x80040c80, 0x02021000, - 0x00102310, 0x80000040, 0x02000000, 0x00102310, - 0x599c0209, 0x599c0a07, 0x80040c80, 0x02021000, - 0x00102310, 0x80000040, 0x02000000, 0x00102310, - 0x0201f800, 0x001053cd, 0x0201f800, 0x00104cb6, - 0x599c0201, 0x48035004, 0x0201f800, 0x001012ee, - 0x599c020a, 0x800001c0, 0x04000003, 0x4803504d, - 0x0401f003, 0x4a03504d, 0x000000c8, 0x0201f800, - 0x00103b25, 0x04000004, 0x0201f800, 0x001060df, - 0x417a5000, 0x836c0580, 0x00000000, 0x04020098, - 0x599c0003, 0x599c0804, 0x9c0001c0, 0x9c0409c0, - 0x48035002, 0x48075003, 0x599c1017, 0x8c08151c, - 0x04000006, 0x599c0005, 0x599c0806, 0x9c0001c0, - 0x9c0409c0, 0x0401f003, 0x82000500, 0xf0ffffff, - 0x48035000, 0x48075001, 0x42001000, 0x0010b4eb, - 0x48001000, 0x48041001, 0x42001000, 0x0010b4f8, - 0x48001000, 0x48041001, 0x59a80005, 0x8c000514, - 0x04020015, 0x599c1019, 0x82081500, 0x0000e000, - 0x82080580, 0x00000000, 0x0402000c, 0x4a035053, - 0x00000000, 0x42000000, 0x00000001, 0x0201f800, - 0x0010188c, 0x42000000, 0x00000001, 0x0201f800, - 0x00101821, 0x0401f02b, 0x82080580, 0x00002000, - 0x0402000a, 0x4a035053, 0x00000001, 0x41780000, - 0x0201f800, 0x0010188c, 0x41780000, 0x0201f800, - 0x00101821, 0x0401f01f, 0x82080580, 0x00004000, - 0x04020006, 0x4a035053, 0x00000002, 0x4a035049, - 0x00000001, 0x0401f017, 0x82080580, 0x00006000, - 0x02020000, 0x00102310, 0x59a80858, 0x82040d80, - 0x01391077, 0x04020005, 0x59e00813, 0x8c040d00, - 0x02020000, 0x00102310, 0x4a035053, 0x00000003, - 0x42000000, 0x00000002, 0x0201f800, 0x0010188c, - 0x42000000, 0x00000002, 0x0201f800, 0x00101821, - 0x599c0019, 0x8c000520, 0x0400000d, 0x42000000, - 0x00000004, 0x42000800, 0x00000040, 0x0201f800, - 0x00101944, 0x42000000, 0x00000010, 0x42000800, - 0x000000c0, 0x0201f800, 0x00101944, 0x4a035032, - 0x0000aaaa, 0x599c1018, 0x82081500, 0x00000030, - 0x59a8006c, 0x80000540, 0x0400000c, 0x82080580, - 0x00000000, 0x02000000, 0x00102310, 0x599c1018, - 0x82081500, 0xffffffcf, 0x82081540, 0x00000010, - 0x480b3818, 0x0401f010, 0x82080d80, 0x00000000, - 0x04000007, 0x82080d80, 0x00000010, 0x0400000a, - 0x82080d80, 0x00000020, 0x04020002, 0x48075032, - 0x0201f800, 0x00103aba, 0x04000008, 0x0201f800, - 0x001015fe, 0x0201f800, 0x0010162a, 0x59a8002a, - 0x80040540, 0x4803502a, 0x49f3c857, 0x42001000, - 0x00105065, 0x0201f800, 0x00105f90, 0x42001000, - 0x00105058, 0x0201f800, 0x00106084, 0x4a038805, - 0xffffffff, 0x4a03c014, 0x00400040, 0x4a03c013, - 0x00400000, 0x0201f800, 0x001048c7, 0x59a0001d, - 0x84000540, 0x4803401d, 0x49f3c857, 0x0201f000, - 0x001022c0, 0x00000018, 0x0000000c, 0x00000018, - 0x00000020, 0x836c0580, 0x00000000, 0x04020005, - 0x42000800, 0x00000007, 0x0201f000, 0x0010230c, + 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, 0x0201f000, - 0x00103a28, 0x800409c0, 0x04000005, 0x4a034406, - 0x00000001, 0x0201f000, 0x0010230c, 0x0201f800, - 0x0010513b, 0x04020005, 0x4a034406, 0x00000016, - 0x0201f000, 0x0010230c, 0x59a80013, 0x8c000500, - 0x04000011, 0x4a034406, 0x00000000, 0x42000800, + 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, 0x42000000, 0x0010be21, 0x0201f000, - 0x00103a28, 0x4a034406, 0x00000001, 0x4200b000, - 0x00000020, 0x4200a800, 0x0010be21, 0x4200a000, - 0xffffffff, 0x4450a800, 0x8054a800, 0x8058b040, - 0x040207fd, 0x4d440000, 0x4d340000, 0x42028800, - 0xffffffff, 0x42002000, 0xffffffff, 0x42003000, - 0x00000001, 0x42003800, 0x00000001, 0x42001800, - 0x0010be21, 0x59a81010, 0x82081500, 0x000000ff, - 0x40180000, 0x0c01f001, 0x0010346e, 0x00103471, - 0x00103475, 0x00103479, 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, 0x00020245, - 0x5c003800, 0x5c003000, 0x5c001800, 0x5c001000, - 0x040207f2, 0x0201f800, 0x001049f3, 0x040207ef, - 0x80183000, 0x801c3800, 0x59341202, 0x40180000, - 0x0c01f7ce, 0x82100580, 0xffffffff, 0x04000002, - 0x44101800, 0x42001800, 0x0010be21, 0x500c0000, - 0x82000500, 0xffffff00, 0x801c0540, 0x44001800, - 0x5c026800, 0x5c028800, 0x42000800, 0x00000020, + 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, 0x0010be21, 0x0201f000, 0x00103a28, - 0x59a28c06, 0x59a0020b, 0x8c000500, 0x0400000e, - 0x59a01208, 0x59a00408, 0x82000500, 0x000000ff, - 0x900001c0, 0x80081540, 0x41784000, 0x0201f800, - 0x00104919, 0x04000008, 0x48034406, 0x0201f000, - 0x00102310, 0x0201f800, 0x00020245, 0x02020000, - 0x00102310, 0x0201f800, 0x00103a00, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c, - 0x59a0020b, 0x8c000500, 0x04000005, 0x0201f800, - 0x001049f3, 0x02020000, 0x00103ac4, 0x59a0020b, - 0x8c000502, 0x04000019, 0x83440480, 0x000007f0, - 0x04021016, 0x0201f800, 0x001049fc, 0x04020013, - 0x497a5a04, 0x4a025c04, 0x00008000, 0x0201f800, - 0x001090e6, 0x04020005, 0x4a034406, 0x00000003, - 0x0201f000, 0x0010230c, 0x4a01d809, 0x001034f1, - 0x1c01f000, 0x59a28c06, 0x0201f800, 0x00020245, - 0x02020000, 0x00102310, 0x4200b000, 0x0000000a, - 0x4134a000, 0x832e5c00, 0x00000002, 0x412ca800, - 0x0201f800, 0x0010ab17, 0x832cac00, 0x00000006, - 0x4054a000, 0x4200b000, 0x00000004, 0x0201f800, - 0x0010ab28, 0x592c0802, 0x82040500, 0x00ff00ff, - 0x900001c0, 0x82041500, 0xff00ff00, 0x80080540, - 0x48025802, 0x592c0801, 0x82040500, 0x00ff00ff, - 0x900001c0, 0x82041500, 0xff00ff00, 0x80080540, - 0x48025801, 0x42000800, 0x0000000a, 0x59a00407, + 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, 0x412c0000, - 0x0201f000, 0x00103a28, 0x496fc857, 0x496f4406, - 0x0201f000, 0x001022c0, 0x59a28c06, 0x0201f800, - 0x00020245, 0x02020000, 0x00102310, 0x836c0580, - 0x00000003, 0x04000005, 0x4a034406, 0x00000007, - 0x0201f000, 0x0010230c, 0x83340c00, 0x00000006, - 0x59a0020b, 0x8c000500, 0x04000003, 0x83340c00, - 0x00000008, 0x58040001, 0x48034409, 0x900001c0, - 0x48034209, 0x50040000, 0x48034407, 0x900001c0, - 0x48034207, 0x59340200, 0x48034406, 0x0201f000, - 0x001022c0, 0x800409c0, 0x04000005, 0x4a034406, - 0x00000001, 0x0201f000, 0x0010230c, 0x59a0220b, - 0x8c102500, 0x0402002e, 0x8c102506, 0x04020006, - 0x59a03208, 0x82180480, 0x00000003, 0x02021000, - 0x00102310, 0x59a28c06, 0x0201f800, 0x00020245, - 0x02020000, 0x00102310, 0x0201f800, 0x001049e7, - 0x04000005, 0x4a034406, 0x00000009, 0x0201f000, - 0x0010230c, 0x0201f800, 0x00103a00, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c, - 0x59a0220b, 0x8c102506, 0x04000004, 0x59343002, - 0x82183500, 0x00ffffff, 0x497a5a04, 0x4a025c04, - 0x00008000, 0x0201f800, 0x001090a8, 0x04020005, - 0x4a034406, 0x00000003, 0x0201f000, 0x0010230c, - 0x4a01d809, 0x001035d1, 0x1c01f000, 0x59a28c06, - 0x0201f800, 0x00020245, 0x02020000, 0x00102310, - 0x0201f800, 0x001049e7, 0x04000005, 0x4a034406, - 0x00000009, 0x0201f000, 0x0010230c, 0x0201f800, - 0x00103a00, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x0010230c, 0x497a5a04, 0x4a025c04, - 0x00008000, 0x0201f800, 0x00103a00, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c, - 0x592e5800, 0x0201f800, 0x001090bd, 0x04020005, - 0x4a034406, 0x00000003, 0x0201f000, 0x0010230c, - 0x4a01d809, 0x001035a3, 0x1c01f000, 0x592c2805, - 0x82140d80, 0x01000000, 0x04020005, 0x4a034406, - 0x00000004, 0x0201f000, 0x0010230c, 0x42000800, - 0x00000008, 0x59a00207, 0x59a01407, 0x900001c0, - 0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0, - 0x800c1d40, 0x832c0400, 0x00000005, 0x0201f800, - 0x00103a28, 0x8c142d00, 0x04000003, 0x4a01d809, - 0x001035be, 0x1c01f000, 0x4031d800, 0x58ef400b, - 0x58ee580e, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x00102304, 0x812e59c0, 0x02000800, - 0x001005d8, 0x42000800, 0x00000008, 0x832c0400, - 0x00000005, 0x58ec1007, 0x58ec1808, 0x0201f000, - 0x00103a28, 0x592c0005, 0x82000580, 0x01000000, - 0x04020005, 0x4a034406, 0x00000004, 0x0201f000, - 0x0010230c, 0x59a00207, 0x59a01407, 0x900001c0, + 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, 0x42000800, 0x00000006, 0x832c0400, - 0x00000006, 0x0201f000, 0x00103a28, 0x59a00a0a, - 0x800409c0, 0x02000000, 0x00102310, 0x82040480, - 0x000000e7, 0x04001003, 0x42000800, 0x000000e6, - 0x59a00207, 0x59a01407, 0x900001c0, 0x80081540, - 0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40, - 0x83880400, 0x00000000, 0x0201f800, 0x00103a28, - 0x4a01d809, 0x001035ff, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x00102304, 0x58ef400b, 0x59a0020b, + 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, 0x000000e6, 0x0201f000, - 0x001022c0, 0x800409c0, 0x04000005, 0x4a034406, - 0x00000001, 0x0201f000, 0x0010230c, 0x0401fbe5, + 0x497b8885, 0x4a034207, 0x000000e7, 0x0201f000, + 0x00102066, 0x800409c0, 0x04000005, 0x4a034406, + 0x00000001, 0x0201f000, 0x001020b2, 0x0401fbf3, 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x0010230c, 0x497a5a04, 0x4a025c04, 0x00008000, - 0x59a00406, 0x800001c0, 0x02000000, 0x00102310, + 0x001020b2, 0x497a5a04, 0x4a025c04, 0x00008000, + 0x59a00406, 0x800001c0, 0x02000000, 0x001020b6, 0x82001580, 0x000000ff, 0x04000005, 0x82001480, - 0x00000004, 0x02021000, 0x00102310, 0x40001000, - 0x0201f800, 0x00101fbf, 0x04020005, 0x4a034406, - 0x00000003, 0x0201f000, 0x0010230c, 0x4a01d809, - 0x0010363a, 0x1c01f000, 0x592c0005, 0x82000580, - 0x01000000, 0x02020000, 0x001022c0, 0x4a034406, - 0x00000004, 0x0201f000, 0x0010230c, 0x59a01406, + 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, 0x0010230c, + 0x4a034406, 0x00000001, 0x0201f000, 0x001020b2, 0x59a01c07, 0x820c0480, 0x00001000, 0x02021000, - 0x00102310, 0x497b2804, 0x497b2805, 0x497b281c, + 0x001020b6, 0x497b2804, 0x497b2805, 0x497b281c, 0x497b281d, 0x497b281f, 0x497b2820, 0x497b2822, - 0x497b2823, 0x80000580, 0x0201f800, 0x001015fe, + 0x497b2823, 0x80000580, 0x0201f800, 0x00101668, 0x59a80805, 0x8c081500, 0x04000004, 0x82040d40, 0x00000011, 0x0401f004, 0x8c081506, 0x04000002, 0x84040d42, 0x84040d0a, 0x48075005, 0x4202d800, 0x00000001, 0x82081500, 0x000000e0, 0x8008010a, - 0x0c020036, 0x0201f800, 0x0010513b, 0x04020009, - 0x4a035033, 0x00000001, 0x0201f800, 0x001050a2, + 0x0c020036, 0x0201f800, 0x00104e0d, 0x04020009, + 0x4a035033, 0x00000001, 0x0201f800, 0x00104d76, 0x0401f01f, 0x4a035033, 0x00000000, 0x0401f7fb, - 0x497b5032, 0x0201f800, 0x00104142, 0x0201f800, - 0x00106c55, 0x0201f800, 0x00106ede, 0x0201f800, - 0x00106c4b, 0x59a00a07, 0x480788a7, 0x59c400a3, + 0x497b5032, 0x0201f800, 0x00103f5c, 0x0201f800, + 0x0010698c, 0x0201f800, 0x00106c32, 0x0201f800, + 0x00106982, 0x59a00a07, 0x480788a7, 0x59c400a3, 0x82000500, 0xfeffffff, 0x82000540, 0x80018000, 0x40000800, 0x84040d20, 0x480388a3, 0x480788a3, 0x497b504e, 0x42000800, 0x0000002d, 0x42001000, - 0x001041bc, 0x0201f800, 0x00105f69, 0x59a00407, + 0x00103fe4, 0x0201f800, 0x00105ca2, 0x59a00407, 0x800000c2, 0x800008c4, 0x8005d400, 0x42000000, - 0x0000ffff, 0x0201f800, 0x0010513b, 0x04000003, - 0x59a00207, 0x80000110, 0x0201f800, 0x00103afc, - 0x0201f000, 0x001022c0, 0x0010366d, 0x00103670, - 0x00103678, 0x00102310, 0x00103675, 0x00102310, - 0x00102310, 0x00102310, 0x836c0580, 0x00000003, + 0x0000ffff, 0x0201f800, 0x00104e0d, 0x04000003, + 0x59a00207, 0x80000110, 0x0201f800, 0x00103915, + 0x0201f000, 0x00102066, 0x00103479, 0x0010347c, + 0x00103484, 0x001020b6, 0x00103481, 0x001020b6, + 0x001020b6, 0x001020b6, 0x836c0580, 0x00000003, 0x04000005, 0x4a034406, 0x00000007, 0x0201f000, - 0x0010230c, 0x59a03c06, 0x59a00407, 0x59a04a07, + 0x001020b2, 0x59a03c06, 0x59a00407, 0x59a04a07, 0x902449c0, 0x80244d40, 0x59a00409, 0x59a05209, - 0x902851c0, 0x80285540, 0x0401fb46, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c, + 0x902851c0, 0x80285540, 0x0401fb54, 0x04020005, + 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, 0x417a8800, 0x41783000, 0x497b4001, 0x497b4004, 0x832c4400, 0x00000005, 0x48234002, 0x8c1c3d04, - 0x04020078, 0x0201f800, 0x00020245, 0x0402002a, - 0x0201f800, 0x001049e7, 0x04000004, 0x0201f800, - 0x001048e3, 0x04020024, 0x8c1c3d00, 0x04000008, + 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, - 0x001049f3, 0x04000003, 0x85468d5e, 0x0401f005, - 0x0201f800, 0x00104838, 0x04020002, 0x85468d5e, + 0x00104842, 0x04000003, 0x85468d5e, 0x0401f005, + 0x0201f800, 0x00104686, 0x04020002, 0x85468d5e, 0x45444000, 0x85468d1e, 0x80204000, 0x82183400, 0x00000003, 0x81468800, 0x83440480, 0x000007f0, 0x0400100e, 0x8c1c3d06, 0x04000010, 0x83440580, @@ -3563,27 +3438,27 @@ uint32_t risc_code01[] = { 0x42028800, 0x000007fc, 0x82180580, 0x0000000f, 0x0400000b, 0x0401f7c0, 0x801831c0, 0x04020006, 0x59a00801, 0x800408c4, 0x48074406, 0x0201f000, - 0x001022c0, 0x4a034004, 0x00000001, 0x49474000, + 0x00102066, 0x4a034004, 0x00000001, 0x49474000, 0x59a00001, 0x80180400, 0x48034001, 0x481f4003, 0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002, 0x4801d803, 0x4825d807, 0x4829d808, 0x4000a800, - 0x4000a000, 0x4018b000, 0x0201f800, 0x0010ab17, - 0x40ec1000, 0x0201f800, 0x00100858, 0x4a01d809, - 0x0010372a, 0x1c01f000, 0x4031d800, 0x58ef400b, + 0x4000a000, 0x4018b000, 0x0201f800, 0x0010a93e, + 0x40ec1000, 0x0201f800, 0x001008a1, 0x4a01d809, + 0x00103536, 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x00102304, 0x59a00004, 0x80000540, 0x04020008, + 0x001020aa, 0x59a00004, 0x80000540, 0x04020008, 0x59a28800, 0x59a04002, 0x59a03803, 0x41783000, 0x58ec4807, 0x58ec5008, 0x0401f78f, 0x59a00801, - 0x800408c4, 0x48074406, 0x0201f000, 0x001022c0, - 0x0201f800, 0x00020245, 0x0402002f, 0x0201f800, - 0x001049e7, 0x04000004, 0x0201f800, 0x001048e3, + 0x800408c4, 0x48074406, 0x0201f000, 0x00102066, + 0x0201f800, 0x00020267, 0x0402002f, 0x0201f800, + 0x00104836, 0x04000004, 0x0201f800, 0x00104732, 0x04020029, 0x83440580, 0x000007fe, 0x04000011, 0x83440580, 0x000007fc, 0x0400000e, 0x0201f800, - 0x001049f3, 0x04000005, 0x59340403, 0x8400055e, - 0x48026c03, 0x0401f007, 0x0201f800, 0x00104838, + 0x00104842, 0x04000005, 0x59340403, 0x8400055e, + 0x48026c03, 0x0401f007, 0x0201f800, 0x00104686, 0x04020004, 0x59340403, 0x8400055e, 0x48026c03, 0x4134a000, 0x4020a800, 0x4200b000, 0x00000006, - 0x0201f800, 0x0010ab17, 0x59340007, 0x4400a800, + 0x0201f800, 0x0010a93e, 0x59340007, 0x4400a800, 0x59340006, 0x4800a801, 0x59340009, 0x4800a802, 0x59340008, 0x4800a803, 0x59340403, 0x8400051e, 0x48026c03, 0x82204400, 0x0000000a, 0x82183400, @@ -3594,650 +3469,657 @@ uint32_t risc_code01[] = { 0x42028800, 0x000007fc, 0x82180580, 0x0000000a, 0x0400000b, 0x0401f7bb, 0x801831c0, 0x04020006, 0x59a00801, 0x800408c4, 0x48074406, 0x0201f000, - 0x001022c0, 0x4a034004, 0x00000001, 0x49474000, + 0x00102066, 0x4a034004, 0x00000001, 0x49474000, 0x59a00001, 0x80180400, 0x48034001, 0x481f4003, 0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002, 0x4801d803, 0x4825d807, 0x4829d808, 0x40ec1000, - 0x0201f800, 0x00100858, 0x4a01d809, 0x001037a1, + 0x0201f800, 0x001008a1, 0x4a01d809, 0x001035ad, 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ec0002, - 0x82000580, 0x00000200, 0x02000000, 0x00102304, + 0x82000580, 0x00000200, 0x02000000, 0x001020aa, 0x59a00004, 0x80000540, 0x04020008, 0x59a28800, 0x59a04002, 0x59a03803, 0x41783000, 0x58ec4807, 0x58ec5008, 0x0401f78f, 0x59a00801, 0x800408c4, - 0x48074406, 0x0201f000, 0x001022c0, 0x42002800, + 0x48074406, 0x0201f000, 0x00102066, 0x42002800, 0x0000007e, 0x59a00c06, 0x59a01207, 0x59a01c07, 0x59a02209, 0x82040500, 0x0000ff00, 0x840001c0, - 0x82003480, 0x00000020, 0x02001000, 0x00102310, - 0x80140480, 0x02001000, 0x00102310, 0x82040500, + 0x82003480, 0x00000020, 0x02001000, 0x001020b6, + 0x80140480, 0x02001000, 0x001020b6, 0x82040500, 0x000000ff, 0x82003480, 0x00000020, 0x02001000, - 0x00102310, 0x80140480, 0x02001000, 0x00102310, + 0x001020b6, 0x80140480, 0x02001000, 0x001020b6, 0x82080500, 0x0000ff00, 0x840001c0, 0x82003480, - 0x00000020, 0x02001000, 0x00102310, 0x80140480, - 0x02001000, 0x00102310, 0x82080500, 0x000000ff, - 0x82003480, 0x00000020, 0x02001000, 0x00102310, - 0x80140480, 0x02001000, 0x00102310, 0x820c0500, + 0x00000020, 0x02001000, 0x001020b6, 0x80140480, + 0x02001000, 0x001020b6, 0x82080500, 0x000000ff, + 0x82003480, 0x00000020, 0x02001000, 0x001020b6, + 0x80140480, 0x02001000, 0x001020b6, 0x820c0500, 0x0000ff00, 0x840001c0, 0x82003480, 0x00000020, - 0x02001000, 0x00102310, 0x80140480, 0x02001000, - 0x00102310, 0x820c0500, 0x000000ff, 0x82003480, - 0x00000020, 0x02001000, 0x00102310, 0x80140480, - 0x02001000, 0x00102310, 0x82100500, 0x0000ff00, + 0x02001000, 0x001020b6, 0x80140480, 0x02001000, + 0x001020b6, 0x820c0500, 0x000000ff, 0x82003480, + 0x00000020, 0x02001000, 0x001020b6, 0x80140480, + 0x02001000, 0x001020b6, 0x82100500, 0x0000ff00, 0x840001c0, 0x82003480, 0x00000020, 0x02001000, - 0x00102310, 0x80140480, 0x02001000, 0x00102310, + 0x001020b6, 0x80140480, 0x02001000, 0x001020b6, 0x82100500, 0x000000ff, 0x82003480, 0x00000020, - 0x02001000, 0x00102310, 0x80140480, 0x02001000, - 0x00102310, 0x900401c0, 0x80080d40, 0x900c01c0, + 0x02001000, 0x001020b6, 0x80140480, 0x02001000, + 0x001020b6, 0x900401c0, 0x80080d40, 0x900c01c0, 0x80101d40, 0x83a83400, 0x0000003a, 0x44043000, - 0x80183000, 0x440c3000, 0x0201f000, 0x001022c0, - 0x0401f9ec, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x0010230c, 0x42000800, 0x0000000c, - 0x0401f853, 0x4a01d809, 0x00103820, 0x1c01f000, + 0x80183000, 0x440c3000, 0x0201f000, 0x00102066, + 0x0401f9fa, 0x04020005, 0x4a034406, 0x00000002, + 0x0201f000, 0x001020b2, 0x42000800, 0x0000000c, + 0x0401f853, 0x4a01d809, 0x0010362c, 0x1c01f000, 0x4031d800, 0x58ee580d, 0x58ef400b, 0x58ec0002, - 0x82000580, 0x00000200, 0x02000000, 0x00102304, + 0x82000580, 0x00000200, 0x02000000, 0x001020aa, 0x832ca400, 0x00000004, 0x4200b000, 0x0000000c, - 0x40c8a800, 0x0201f800, 0x0010ab17, 0x58c80200, + 0x40c8a800, 0x0201f800, 0x0010a93e, 0x58c80200, 0x80000540, 0x04000034, 0x58c80400, 0x82000500, 0xfffffffb, 0x04020030, 0x58c80401, 0x80000540, 0x0400002d, 0x82000480, 0x0000ff01, 0x0402102a, 0x58c80202, 0x82000480, 0x0000005c, 0x04001026, - 0x0201f800, 0x001063a3, 0x58c80c08, 0x58c80204, + 0x0201f800, 0x001060db, 0x58c80c08, 0x58c80204, 0x80040480, 0x04001020, 0x58c80204, 0x82000480, 0x00000005, 0x0402101c, 0x58c80205, 0x58c80c08, 0x80040902, 0x80040480, 0x04001017, 0x58c80c08, - 0x0201f800, 0x001062f1, 0x0400001b, 0x0201f800, - 0x001061b9, 0x04020012, 0x4979940b, 0x59c408a3, + 0x0201f800, 0x0010602a, 0x0400001b, 0x0201f800, + 0x00105ef2, 0x04020012, 0x4979940b, 0x59c408a3, 0x82040d40, 0x00000002, 0x480788a3, 0x4a038830, 0x00000001, 0x4a038832, 0x01ffffff, 0x58c80202, - 0x48030804, 0x0201f800, 0x0010619b, 0x0201f000, - 0x001022c0, 0x0201f000, 0x00102310, 0x0201f800, - 0x001063f5, 0x0201f800, 0x00106402, 0x0201f800, - 0x001062e4, 0x0201f000, 0x0010230c, 0x4c000000, + 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, 0x0401f1ac, 0x59840000, 0x82000580, - 0x00000000, 0x04000054, 0x59840002, 0x8c000504, - 0x04000051, 0x84000546, 0x48030802, 0x0201f800, - 0x001062e4, 0x59c408a3, 0x82040d00, 0xfffffffd, - 0x480788a3, 0x4c5c0000, 0x4200b800, 0x0010ac00, + 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, 0x001062d5, - 0x02000800, 0x001064ad, 0x805cb800, 0x825c0580, - 0x0010b3f0, 0x040207f3, 0x59866003, 0x813261c0, + 0x813261c0, 0x04000005, 0x0201f800, 0x0010600e, + 0x02000800, 0x001061e5, 0x805cb800, 0x825c0580, + 0x0010b1f0, 0x040207f3, 0x59866003, 0x813261c0, 0x0400000b, 0x59300406, 0x82000580, 0x00000009, - 0x02020800, 0x001005d8, 0x5930b800, 0x0201f800, - 0x001062c1, 0x405e6000, 0x0401f7f5, 0x497b0803, - 0x4200b800, 0x0010b51b, 0x505e6000, 0x813261c0, + 0x02020800, 0x00100615, 0x5930b800, 0x0201f800, + 0x00105ffa, 0x405e6000, 0x0401f7f5, 0x497b0803, + 0x4200b800, 0x0010b317, 0x505e6000, 0x813261c0, 0x04000011, 0x59300406, 0x82000580, 0x00000009, 0x0402000d, 0x59300203, 0x82000580, 0x00000004, 0x04020009, 0x59326809, 0x813669c0, 0x02020800, - 0x001005d8, 0x0201f800, 0x00100e99, 0x0201f800, - 0x001062c1, 0x4578b800, 0x805cb800, 0x825c0580, - 0x0010b523, 0x040207e9, 0x42000800, 0x0010b519, - 0x49780801, 0x49780800, 0x59a80069, 0x82000400, - 0x00000007, 0x48035069, 0x0201f800, 0x001063f5, - 0x0201f800, 0x00106402, 0x5c00b800, 0x0201f800, - 0x001061b4, 0x0201f000, 0x001022c0, 0x836c0580, + 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, 0x0010230c, 0x59a00407, 0x59a02207, + 0x0201f000, 0x001020b2, 0x59a00407, 0x59a02207, 0x901021c0, 0x80102540, 0x59a00409, 0x59a02a09, - 0x901429c0, 0x80142d40, 0x0401f91e, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c, + 0x901429c0, 0x80142d40, 0x0401f930, 0x04020005, + 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, 0x417a8800, 0x41781800, 0x497b4001, 0x497b4003, 0x832c3400, 0x00000004, 0x481b4002, 0x41440000, 0x81ac0400, 0x50026800, 0x813669c0, 0x0400000b, - 0x0201f800, 0x001049e7, 0x04020008, 0x59340002, + 0x0201f800, 0x00104836, 0x04020008, 0x59340002, 0x48003000, 0x49443001, 0x82183400, 0x00000002, 0x820c1c00, 0x00000002, 0x81468800, 0x83440480, 0x00000800, 0x04000005, 0x820c0480, 0x00000010, 0x0402100b, 0x0401f7ea, 0x800c19c0, 0x04020006, 0x59a00801, 0x80040902, 0x48074406, 0x0201f000, - 0x001022c0, 0x4a034003, 0x00000001, 0x49474000, + 0x00102066, 0x4a034003, 0x00000001, 0x49474000, 0x59a00001, 0x800c0400, 0x48034001, 0x40ec1000, 0x4a001001, 0x00000000, 0x480c1004, 0x59a00002, 0x48001003, 0x48101007, 0x48141008, 0x0201f800, - 0x00100858, 0x4a01d809, 0x00103920, 0x1c01f000, + 0x001008a1, 0x4a01d809, 0x00103728, 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x00102304, 0x59a00003, + 0x00000200, 0x02000000, 0x001020aa, 0x59a00003, 0x80000540, 0x04020008, 0x59a28800, 0x59a03002, 0x41781800, 0x40ec1000, 0x58082007, 0x58082808, 0x0401f7bf, 0x59a00801, 0x80040902, 0x48074406, - 0x0201f000, 0x001022c0, 0x800409c0, 0x04000005, - 0x4a034406, 0x00000001, 0x0201f000, 0x0010230c, + 0x0201f000, 0x00102066, 0x800409c0, 0x04000005, + 0x4a034406, 0x00000001, 0x0201f000, 0x001020b2, 0x59a80026, 0x8c00050a, 0x04020007, 0x8c000506, 0x04020005, 0x4a034406, 0x00000016, 0x0201f000, - 0x0010230c, 0x0401f8bb, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x0010230c, 0x59a00c06, + 0x001020b2, 0x0401f8cd, 0x04020005, 0x4a034406, + 0x00000002, 0x0201f000, 0x001020b2, 0x59a00c06, 0x80040902, 0x59a00407, 0x59a01207, 0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0, - 0x800c1d40, 0x832c0400, 0x00000005, 0x0401f8ce, - 0x4a01d809, 0x0010395b, 0x1c01f000, 0x4031d800, + 0x800c1d40, 0x832c0400, 0x00000005, 0x0401f8df, + 0x4a01d809, 0x00103763, 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x00102304, 0x592c0009, - 0x0201f800, 0x00105c9a, 0x02000800, 0x001045a6, - 0x02020000, 0x00102310, 0x49474001, 0x481a6802, + 0x00000200, 0x02000000, 0x001020aa, 0x592c0009, + 0x0201f800, 0x001059b9, 0x02000800, 0x001043fc, + 0x02020000, 0x001020b6, 0x49474001, 0x481a6802, 0x592c000a, 0x82001d80, 0x70000000, 0x04020007, - 0x0401f890, 0x04020011, 0x4a034406, 0x00000002, - 0x0201f000, 0x0010230c, 0x82001d80, 0x72000000, - 0x02020000, 0x00102310, 0x0401f886, 0x04020885, - 0x04020884, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x0010230c, 0x58ee580d, 0x4a025c04, + 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, - 0x001090d1, 0x04020005, 0x4a034406, 0x00000003, - 0x0201f000, 0x0010230c, 0x4a01d809, 0x00103995, + 0x00108e8e, 0x04020005, 0x4a034406, 0x00000003, + 0x0201f000, 0x001020b2, 0x4a01d809, 0x0010379d, 0x1c01f000, 0x592c4000, 0x592c0005, 0x82000580, 0x01000000, 0x04020005, 0x4a034406, 0x00000004, - 0x0201f000, 0x0010230c, 0x832c3c00, 0x00000005, - 0x401ca000, 0x401ca800, 0x5820280a, 0x4200b000, - 0x00000002, 0x82143580, 0x70000000, 0x04000003, - 0x4200b000, 0x0000000f, 0x0201f800, 0x0010ab28, - 0x401c0000, 0x58201006, 0x58201807, 0x58202205, - 0x80102102, 0x82143580, 0x70000000, 0x04020008, - 0x82103480, 0x00000002, 0x02001000, 0x00102310, - 0x42000800, 0x00000002, 0x0401f06e, 0x82143580, - 0x72000000, 0x02020000, 0x00102310, 0x82103480, - 0x0000002a, 0x02001000, 0x00102310, 0x42000800, - 0x0000000f, 0x0401f863, 0x4a01d809, 0x001039c9, - 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ee580e, - 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x00102304, 0x592e5800, 0x832c0c00, 0x00000005, - 0x4004a000, 0x4004a800, 0x4200b000, 0x0000000f, - 0x0201f800, 0x0010ab28, 0x40ec1000, 0x4a001001, + 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, 0x00100858, 0x4a01d809, 0x001039e5, + 0x0201f800, 0x001008a1, 0x4a01d809, 0x001037f9, 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ee580e, 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x00102304, 0x832c0c00, 0x00000005, 0x4004a000, - 0x4004a800, 0x4200b000, 0x0000000c, 0x0201f800, - 0x0010ab28, 0x40ec1000, 0x4a001001, 0x00000000, - 0x4a001004, 0x0000000c, 0x48041003, 0x0201f800, - 0x00100858, 0x4a01d809, 0x001022b9, 0x1c01f000, - 0x0201f800, 0x001007e4, 0x04000010, 0x497a5800, - 0x58ec000d, 0x80000540, 0x04020004, 0x492dd80d, - 0x492dd80e, 0x0401f007, 0x58ec000e, 0x48025800, - 0x82000400, 0x00000001, 0x452c0000, 0x492dd80e, - 0x832c0400, 0x00000004, 0x492fc857, 0x4803c857, - 0x1c01f000, 0x4d2c0000, 0x48efc857, 0x58ec400d, - 0x4823c857, 0x802041c0, 0x04000007, 0x40225800, - 0x592c4001, 0x497a5801, 0x0201f800, 0x001007f4, - 0x0401f7f8, 0x4979d80d, 0x4979d80e, 0x5c025800, - 0x1c01f000, 0x42003000, 0x00000001, 0x0401f003, - 0x42003000, 0x00000000, 0x4803c857, 0x4807c857, - 0x480bc857, 0x480fc857, 0x481bc857, 0x48efc857, - 0x4819d801, 0x800409c0, 0x02000800, 0x001005d8, - 0x4805d804, 0x4801d803, 0x4809d807, 0x480dd808, - 0x40ec1000, 0x0201f800, 0x00100858, 0x4a01d809, - 0x001022b9, 0x1c01f000, 0x80002d80, 0x480bc857, - 0x480fc857, 0x4813c857, 0x4817c857, 0x4d2c0000, - 0x4da00000, 0x42034000, 0x0010b4a4, 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, - 0x001007e4, 0x04000007, 0x492f401a, 0x492f401b, - 0x412c3800, 0x497b421c, 0x497a5813, 0x0401f026, - 0x59880051, 0x80000000, 0x48031051, 0x59a00017, - 0x80000040, 0x48034017, 0x59a00219, 0x59a03816, - 0x801c3c00, 0x0401f01c, 0x59a0021c, 0x82000400, - 0x00000002, 0x82000c80, 0x00000012, 0x04021004, - 0x4803421c, 0x801c3c00, 0x0401f013, 0x0201f800, - 0x001007e4, 0x0402000b, 0x59880051, 0x80000000, - 0x48031051, 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, 0x0010b813, 0x0201f800, - 0x0010aa47, 0x801800d0, 0x40002800, 0x42001000, - 0x00008014, 0x0401f786, 0x4c000000, 0x599c0017, - 0x8c000512, 0x5c000000, 0x1c01f000, 0x4c000000, - 0x599c0018, 0x8c00050e, 0x5c000000, 0x1c01f000, - 0x59a80821, 0x800409c0, 0x04000005, 0x4a034406, - 0x00000001, 0x0201f000, 0x0010230c, 0x836c0580, - 0x00000003, 0x04000005, 0x4a034406, 0x00000007, - 0x0201f000, 0x0010230c, 0x599c0017, 0x8c00050a, - 0x04000005, 0x4a034406, 0x00000008, 0x0201f000, - 0x0010230c, 0x59340405, 0x8c000508, 0x04020004, - 0x8c00050a, 0x02020000, 0x001034db, 0x497a5a04, - 0x497a5805, 0x4a025c04, 0x00008000, 0x0201f800, - 0x00109176, 0x04020005, 0x4a034406, 0x00000003, - 0x0201f000, 0x0010230c, 0x4a01d809, 0x00103aed, - 0x1c01f000, 0x592c0005, 0x82000580, 0x01000000, - 0x04020005, 0x4a034406, 0x00000004, 0x0201f000, - 0x0010230c, 0x59a28c06, 0x0201f800, 0x00020245, - 0x02020000, 0x00102310, 0x0201f000, 0x001034db, - 0x82001580, 0x0000ffff, 0x04000009, 0x0201f800, - 0x00105c9a, 0x02000800, 0x00020245, 0x0402000c, - 0x0201f800, 0x00105fae, 0x0401f009, 0x42028800, - 0x000007ef, 0x0201f800, 0x00020245, 0x02000800, - 0x00105fae, 0x81468840, 0x040217fb, 0x1c01f000, - 0x4803c856, 0x4c0c0000, 0x4d340000, 0x4d440000, - 0x42028800, 0x000007fe, 0x0201f800, 0x00020245, - 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, 0x00000006, 0x02021800, - 0x001005d8, 0x0c01f807, 0x5c00a800, 0x5c00a000, - 0x5c00b000, 0x1c01f000, 0x0401f906, 0x0401f7fb, - 0x00103b51, 0x00103b57, 0x00103b7c, 0x00103b9e, - 0x00103c59, 0x59c40806, 0x8c040d00, 0x04020003, - 0x84040d40, 0x48078806, 0x1c01f000, 0x59c40005, - 0x8c000534, 0x02020000, 0x0010429e, 0x4a038805, - 0xffffffff, 0x42006000, 0x00020000, 0x0201f800, - 0x00104282, 0x59a80015, 0x82000500, 0xfffffffa, - 0x84000542, 0x48035015, 0x497b5026, 0x42000800, - 0x0010be21, 0x45780800, 0x497b5013, 0x42006000, - 0xffefffff, 0x42006800, 0x40000000, 0x0201f800, - 0x0010427d, 0x59c40006, 0x82000500, 0xffffff0f, - 0x48038806, 0x42000800, 0x00000010, 0x42001000, - 0x001041f3, 0x0201f800, 0x00105f83, 0x0401f001, - 0x42006000, 0xffffffff, 0x42006800, 0x00800000, - 0x0201f800, 0x0010427d, 0x4200b000, 0x000000c8, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, - 0x0000000a, 0x0400000f, 0x8058b040, 0x040207f9, - 0x497b5014, 0x42006000, 0xbf7fffff, 0x42006800, - 0x00018000, 0x0201f800, 0x0010427d, 0x42006000, - 0xfffeffff, 0x41786800, 0x0201f000, 0x0010427d, - 0x497b5014, 0x4a035012, 0x00000000, 0x80000580, - 0x0201f000, 0x00104289, 0x4a038805, 0xffffffff, - 0x59a80012, 0x82000c80, 0x00000004, 0x02021800, - 0x001005d8, 0x0c01f001, 0x00103ba9, 0x00103bd6, - 0x00103c4f, 0x4803c856, 0x59c400a3, 0x8400051e, - 0x480388a3, 0x4a035012, 0x00000001, 0x59c40008, - 0x8400054e, 0x48038808, 0x0201f800, 0x00104263, - 0x42007800, 0x0010b54c, 0x4a007806, 0x11010000, - 0x4200a000, 0x0010b402, 0x4200a800, 0x0010b553, - 0x4200b000, 0x00000002, 0x0201f800, 0x0010ab17, - 0x497b8802, 0x42000800, 0x00000003, 0x497b504a, - 0x0201f800, 0x0010416e, 0x4a03504a, 0x00000001, - 0x497b5016, 0x0201f800, 0x00104290, 0x42006000, - 0xffffffff, 0x42006800, 0x00080000, 0x0201f800, - 0x0010427d, 0x42006000, 0xfff7ffff, 0x41786800, - 0x0201f000, 0x0010427d, 0x59a80016, 0x497b5016, - 0x80002540, 0x04000066, 0x59c40004, 0x82000500, - 0x00000003, 0x04020071, 0x59a80815, 0x8c040d02, - 0x0400004b, 0x82100580, 0x0000000c, 0x0402004f, - 0x82100400, 0x00000018, 0x8000b104, 0x41cc1000, - 0x42001800, 0x0010b54c, 0x50080800, 0x500c0000, - 0x80040580, 0x0402001a, 0x80081000, 0x800c1800, - 0x8058b040, 0x040207f9, 0x0201f800, 0x00104290, - 0x42006000, 0xffffffff, 0x42006800, 0x00500000, - 0x0201f800, 0x0010427d, 0x4a035012, 0x00000002, - 0x4a035014, 0x00000002, 0x42000800, 0x000007d0, - 0x42001000, 0x00104148, 0x0201f800, 0x0010606e, - 0x0201f800, 0x00104263, 0x0401f048, 0x59cc0806, - 0x82040d80, 0x11010000, 0x04020028, 0x59cc0800, - 0x82040500, 0x00ffffff, 0x0400001a, 0x82000580, - 0x000000ef, 0x04020017, 0x59cc0801, 0x82040500, - 0x00ffffff, 0x82000580, 0x000000ef, 0x04020011, - 0x83cca400, 0x00000007, 0x4200a800, 0x0010b402, - 0x4200b000, 0x00000002, 0x50500800, 0x50540000, - 0x80040480, 0x04001007, 0x04020010, 0x8050a000, - 0x8054a800, 0x8058b040, 0x040207f8, 0x0401f00b, - 0x59a80015, 0x84000502, 0x48035015, 0x41cca000, - 0x4200a800, 0x0010b54c, 0x4200b000, 0x00000009, - 0x0201f800, 0x0010ab17, 0x0201f800, 0x00104290, - 0x42006000, 0xffffffff, 0x42006800, 0x00080000, - 0x0201f800, 0x0010427d, 0x42006000, 0xfff7ffff, - 0x41786800, 0x0201f800, 0x0010427d, 0x42006000, - 0xffffffff, 0x42006800, 0x00004000, 0x0201f800, - 0x0010427d, 0x59c40004, 0x82000500, 0x00000003, - 0x04020006, 0x497b5016, 0x42000800, 0x00000003, - 0x0201f000, 0x0010416e, 0x1c01f000, 0x1c01f000, - 0x59a80014, 0x82006d80, 0x0000000f, 0x04000005, - 0x82000580, 0x0000001b, 0x02020800, 0x00104139, - 0x1c01f000, 0x59a80015, 0x84000506, 0x48035015, - 0x497b504a, 0x59a80014, 0x82000c80, 0x0000001e, - 0x02021800, 0x001005d8, 0x0c01f001, 0x00103c97, - 0x00103cac, 0x00103cd5, 0x00103cf0, 0x00103d14, - 0x00103d45, 0x00103d68, 0x00103d9b, 0x00103dbe, - 0x00103de4, 0x00103e21, 0x00103e48, 0x00103e5f, - 0x00103e71, 0x00103e8a, 0x00103ea0, 0x00103ea5, - 0x00103ecd, 0x00103ef0, 0x00103f16, 0x00103f39, - 0x00103f6c, 0x00103fae, 0x00103fd8, 0x00103ff0, - 0x00104030, 0x00104049, 0x0010405c, 0x0010405d, - 0x4803c856, 0x4202d800, 0x00000007, 0x0201f800, - 0x0010513b, 0x04000007, 0x42006000, 0xffffffd7, - 0x41786800, 0x0201f800, 0x0010427d, 0x0401f00b, + 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, - 0x42001000, 0x000000f0, 0x0201f800, 0x0010193d, - 0x0201f800, 0x00105098, 0x1c01f000, 0x4803c856, - 0x42006000, 0xbf7fffff, 0x42006800, 0x00400000, - 0x0201f800, 0x0010427d, 0x4a035014, 0x00000001, - 0x42001000, 0x001041f3, 0x0201f800, 0x00105fa4, - 0x0201f800, 0x001041f8, 0x42000800, 0x000007d0, - 0x42001000, 0x00104148, 0x0201f000, 0x0010606e, - 0x59a80016, 0x82000580, 0x00000014, 0x04020025, - 0x4803c857, 0x42006000, 0xffbfffff, 0x41786800, - 0x0201f800, 0x0010427d, 0x59c40004, 0x82000500, - 0x00000003, 0x0402001b, 0x59cc1006, 0x82081580, - 0x11020000, 0x04020016, 0x59cc1007, 0x8c08153e, - 0x0400000b, 0x59a80015, 0x8c000504, 0x04020008, - 0x42000000, 0x0010b83f, 0x0201f800, 0x0010aa47, - 0x59a80015, 0x84000544, 0x48035015, 0x42001000, - 0x00104148, 0x0201f800, 0x00105f90, 0x4a035014, - 0x00000010, 0x0401f9d4, 0x0401f002, 0x497b5016, - 0x1c01f000, 0x4803c856, 0x4a035014, 0x00000003, - 0x42006000, 0xbf3fffff, 0x42006800, 0x00100000, - 0x0201f800, 0x0010427d, 0x42001000, 0x001041f3, - 0x0201f800, 0x00105fa4, 0x0201f800, 0x001041f8, - 0x42001000, 0x00104148, 0x0201f800, 0x00105f90, - 0x42007800, 0x0010b552, 0x46007800, 0x11020000, - 0x42000800, 0x00000005, 0x0201f000, 0x0010416e, - 0x59a80016, 0x80000540, 0x04000021, 0x4803c857, - 0x42001000, 0x00104148, 0x0201f800, 0x00105f90, - 0x59a80016, 0x82000580, 0x00000014, 0x04020016, - 0x59cc1006, 0x82081580, 0x11020000, 0x04020012, - 0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015, - 0x8c000504, 0x04020008, 0x42000000, 0x0010b83f, - 0x0201f800, 0x0010aa47, 0x59a80015, 0x84000544, - 0x48035015, 0x4a035014, 0x00000004, 0x0401f805, - 0x0401f003, 0x0201f800, 0x00104139, 0x1c01f000, + 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, 0x0010b552, 0x4200b000, - 0x00000005, 0x0201f800, 0x0010ab17, 0x42007800, - 0x0010b552, 0x46007800, 0x11030000, 0x0201f800, - 0x0010413e, 0x04020014, 0x59a80015, 0x8c000500, + 0x00000006, 0x4200a800, 0x0010b350, 0x4200b000, + 0x00000005, 0x0201f800, 0x0010a93e, 0x42007800, + 0x0010b350, 0x46007800, 0x11030000, 0x0201f800, + 0x00103f58, 0x04020014, 0x59a80015, 0x8c000500, 0x04020011, 0x59a80810, 0x82040580, 0x00ffffff, 0x0400000d, 0x82040d00, 0x000000ff, 0x82040400, - 0x0010210e, 0x50000800, 0x80040910, 0x42001000, - 0x00000004, 0x0401fb9b, 0x0400000b, 0x0201f800, - 0x0010420d, 0x4200b000, 0x00000004, 0x83cca400, - 0x00000007, 0x4200a800, 0x0010b553, 0x0201f800, - 0x0010ab17, 0x42000800, 0x00000005, 0x0201f000, - 0x0010416e, 0x59a80016, 0x80000540, 0x04000020, - 0x4803c857, 0x42001000, 0x00104148, 0x0201f800, - 0x00105f90, 0x59a80016, 0x82000580, 0x00000014, + 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, - 0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015, + 0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015, 0x84000544, 0x48035015, 0x4a035014, 0x00000006, - 0x0401f804, 0x0401f002, 0x0401fbd3, 0x1c01f000, - 0x4803c856, 0x4a035014, 0x00000007, 0x83cca400, - 0x00000006, 0x4200a800, 0x0010b552, 0x4200b000, - 0x00000005, 0x0201f800, 0x0010ab17, 0x42007800, - 0x0010b552, 0x46007800, 0x11040000, 0x0401fbc7, - 0x04020020, 0x59a80015, 0x8c000500, 0x0402001d, - 0x599c0017, 0x8c000500, 0x0400001a, 0x599c1402, - 0x82080480, 0x0000007f, 0x02021800, 0x001005d8, - 0x4c080000, 0x82081400, 0x0010210e, 0x50081000, - 0x82081500, 0x000000ff, 0x480b5010, 0x42000800, - 0x00000003, 0x0201f800, 0x00106c78, 0x5c000800, - 0x42001000, 0x00000004, 0x0401fb3e, 0x04000005, - 0x0401fd2b, 0x04000003, 0x0201f800, 0x001015fe, - 0x42000800, 0x00000005, 0x0401f3d4, 0x59a80016, - 0x80000540, 0x04000020, 0x4803c857, 0x42001000, - 0x00104148, 0x0201f800, 0x00105f90, 0x59a80016, - 0x82000580, 0x00000014, 0x04020016, 0x59cc1006, - 0x82081580, 0x11040000, 0x04020012, 0x59cc1007, - 0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504, - 0x04020008, 0x42000000, 0x0010b83f, 0x0201f800, - 0x0010aa47, 0x59a80015, 0x84000544, 0x48035015, - 0x4a035014, 0x00000008, 0x0401f804, 0x0401f002, - 0x0401fb7d, 0x1c01f000, 0x4803c856, 0x4a035014, - 0x00000009, 0x83cca400, 0x00000006, 0x4200a800, - 0x0010b552, 0x4200b000, 0x00000005, 0x0201f800, - 0x0010ab17, 0x42007800, 0x0010b552, 0x46007800, - 0x11050100, 0x0401fb71, 0x0402000a, 0x59a80015, - 0x8c000500, 0x04020007, 0x0401fa8c, 0x04020005, - 0x82000540, 0x00000001, 0x0201f800, 0x001015fe, - 0x42000800, 0x00000005, 0x0401fb94, 0x0401fb63, - 0x04020ea4, 0x4d3c0000, 0x42027800, 0x00000001, - 0x0201f800, 0x00109874, 0x5c027800, 0x1c01f000, - 0x59a80016, 0x80000540, 0x0400003a, 0x4803c857, - 0x42001000, 0x00104148, 0x0201f800, 0x00105f90, + 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, 0x0010b83f, - 0x0201f800, 0x0010aa47, 0x59a80015, 0x84000544, + 0x8c000504, 0x04020008, 0x42000000, 0x0010b63d, + 0x0201f800, 0x0010a86e, 0x59a80015, 0x84000544, 0x48035015, 0x4a035013, 0x00000001, 0x4a035014, - 0x0000000a, 0x0401f818, 0x0401f016, 0x80000540, + 0x0000000a, 0x0401f817, 0x0401f014, 0x80000540, 0x04020013, 0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504, 0x04020008, 0x42000000, - 0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015, + 0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015, 0x84000544, 0x48035015, 0x497b5013, 0x4a035014, - 0x0000000e, 0x0401f86d, 0x0401f002, 0x0401fb1a, - 0x1c01f000, 0x4803c856, 0x4a035014, 0x0000000b, - 0x42001000, 0x0010b553, 0x4008a800, 0x4200b000, - 0x00000020, 0x4600a800, 0xffffffff, 0x8054a800, - 0x8058b040, 0x040207fc, 0x42007800, 0x0010b552, - 0x46007800, 0x11060000, 0x42001000, 0x0010b553, - 0x0401fb0a, 0x04000005, 0x50080000, 0x46001000, - 0x00ffffff, 0x0401f00c, 0x50080800, 0x82040d00, - 0x0000ffff, 0x59a80010, 0x82000500, 0x000000ff, - 0x82000540, 0x00000100, 0x800000e0, 0x80040d40, - 0x44041000, 0x42000800, 0x00000021, 0x0401f327, - 0x59a80016, 0x80000540, 0x04000014, 0x4803c857, - 0x59a80016, 0x42001000, 0x00104148, 0x0201f800, - 0x00105f90, 0x59a80016, 0x82000580, 0x00000084, - 0x04020009, 0x59cc1006, 0x82081580, 0x11060000, - 0x04020005, 0x4a035014, 0x0000000c, 0x0401f804, - 0x0401f002, 0x0401fadc, 0x1c01f000, 0x4803c856, - 0x4a035014, 0x0000000d, 0x83cca400, 0x00000006, - 0x4200a800, 0x0010b552, 0x4200b000, 0x00000021, - 0x0201f800, 0x0010ab17, 0x42007800, 0x0010b552, - 0x46007800, 0x11070000, 0x42000800, 0x00000021, - 0x0401f2fe, 0x59a80016, 0x80000540, 0x04000016, - 0x4803c857, 0x59a80016, 0x42001000, 0x00104148, - 0x0201f800, 0x00105f90, 0x82000580, 0x00000084, - 0x0402000c, 0x59cc1006, 0x82081580, 0x11070000, - 0x04020008, 0x4a035013, 0x00000001, 0x0401fa91, - 0x4a035014, 0x0000000e, 0x0401f804, 0x0401f002, - 0x0401fab1, 0x1c01f000, 0x4803c856, 0x82040d40, - 0x00000001, 0x0401fbfc, 0x4a035014, 0x0000000f, - 0x497b5016, 0x42006000, 0xffffffff, 0x42006800, - 0x00300000, 0x0401fbe8, 0x42006000, 0xffdfffff, - 0x41786800, 0x0401fbe4, 0x42000800, 0x000007d0, - 0x42001000, 0x00104148, 0x0201f000, 0x00105f69, - 0x4803c856, 0x59a80016, 0x80000540, 0x04020296, - 0x1c01f000, 0x4803c856, 0x4a035014, 0x00000011, - 0x83cca400, 0x00000006, 0x4200a800, 0x0010b552, - 0x4200b000, 0x00000005, 0x0201f800, 0x0010ab17, - 0x4200a800, 0x0010b552, 0x4600a800, 0x11020000, - 0x0401fa8a, 0x04020015, 0x59a80010, 0x82000d00, - 0xffff0000, 0x04000011, 0x82000500, 0x000000ff, - 0x0400000e, 0x82000c00, 0x0010210e, 0x50040800, - 0x80040910, 0x82040580, 0x0000007e, 0x04000007, - 0x82040580, 0x00000080, 0x04000004, 0x42001000, - 0x00000004, 0x0401fa07, 0x42000800, 0x00000005, - 0x0401f2a2, 0x59a80016, 0x80000540, 0x04000020, - 0x4803c857, 0x42001000, 0x00104148, 0x0201f800, - 0x00105f90, 0x59a80016, 0x82000580, 0x00000014, - 0x04020016, 0x59cc1006, 0x82081580, 0x11030000, - 0x04020012, 0x59cc1007, 0x8c08153e, 0x0400000b, - 0x59a80015, 0x8c000504, 0x04020008, 0x42000000, - 0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015, - 0x84000544, 0x48035015, 0x4a035014, 0x00000012, - 0x0401f804, 0x0401f002, 0x0401fa4b, 0x1c01f000, - 0x4803c856, 0x4a035014, 0x00000013, 0x83cca400, - 0x00000006, 0x4200a800, 0x0010b552, 0x4200b000, - 0x00000005, 0x0201f800, 0x0010ab17, 0x4200a800, - 0x0010b552, 0x4600a800, 0x11030000, 0x0401fa3f, - 0x04020013, 0x59a80015, 0x8c000500, 0x04020010, - 0x59a80810, 0x82040580, 0x00ffffff, 0x0400000c, - 0x82040d00, 0x000000ff, 0x82040400, 0x0010210e, - 0x50000800, 0x80040910, 0x42001000, 0x00000004, - 0x0401f9c0, 0x04000002, 0x0401fafb, 0x42000800, - 0x00000005, 0x0401f259, 0x59a80016, 0x80000540, - 0x04000020, 0x4803c857, 0x42001000, 0x00104148, - 0x0201f800, 0x00105f90, 0x59a80016, 0x82000580, - 0x00000014, 0x04020016, 0x59cc1006, 0x82081580, - 0x11040000, 0x04020012, 0x59cc1007, 0x8c08153e, - 0x0400000b, 0x59a80015, 0x8c000504, 0x04020008, - 0x42000000, 0x0010b83f, 0x0201f800, 0x0010aa47, - 0x59a80015, 0x84000544, 0x48035015, 0x4a035014, - 0x00000014, 0x0401f804, 0x0401f002, 0x0401fa02, - 0x1c01f000, 0x4803c856, 0x4a035014, 0x00000015, - 0x83cca400, 0x00000006, 0x4200a800, 0x0010b552, - 0x4200b000, 0x00000005, 0x0201f800, 0x0010ab17, - 0x4200a800, 0x0010b552, 0x4600a800, 0x11040000, - 0x0401f9f6, 0x04020020, 0x59a80015, 0x8c000500, - 0x0402001d, 0x599c0017, 0x8c000500, 0x0400001a, - 0x599c1402, 0x82080480, 0x0000007f, 0x02021800, - 0x001005d8, 0x4c080000, 0x82081400, 0x0010210e, - 0x50081000, 0x82081500, 0x000000ff, 0x480b5010, - 0x42000800, 0x00000003, 0x0201f800, 0x00106c78, - 0x5c000800, 0x42001000, 0x00000004, 0x0401f96d, - 0x04000005, 0x0201f800, 0x00103abf, 0x02020800, - 0x001015fe, 0x42000800, 0x00000005, 0x0401f203, - 0x59a80016, 0x80000540, 0x0400003f, 0x4803c857, - 0x42001000, 0x00104148, 0x0201f800, 0x00105f90, - 0x59a80016, 0x82000580, 0x00000014, 0x04020035, - 0x59cc1006, 0x82080500, 0x11050000, 0x82000580, - 0x11050000, 0x0402002f, 0x8c081510, 0x04000010, - 0x0401fb09, 0x59cc1007, 0x8c08153e, 0x0400000b, - 0x59a80015, 0x8c000504, 0x04020008, 0x42000000, - 0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015, - 0x84000544, 0x48035015, 0x0401f013, 0x59cc1007, + 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, 0x0010b83f, 0x0201f800, - 0x0010aa47, 0x59a80015, 0x84000544, 0x48035015, - 0x82000540, 0x00000001, 0x0401faeb, 0x497b5013, - 0x0401f003, 0x4a035013, 0x00000001, 0x59cc1007, - 0x8c08153c, 0x04000003, 0x4a035026, 0x00000008, - 0x4a035014, 0x00000016, 0x0401f804, 0x0401f002, - 0x0401f98d, 0x1c01f000, 0x4803c856, 0x83cca400, - 0x00000006, 0x4200a800, 0x0010b552, 0x4200b000, - 0x00000005, 0x0201f800, 0x0010ab17, 0x4a035014, - 0x00000017, 0x59a80013, 0x8c000500, 0x04000006, - 0x42001000, 0x0010b552, 0x46001000, 0x11050100, - 0x0401f003, 0x4a035014, 0x0000001b, 0x0401f97b, - 0x0402000a, 0x59a80015, 0x8c000500, 0x04020007, - 0x0401f896, 0x04020005, 0x82000540, 0x00000001, - 0x0201f800, 0x001015fe, 0x42000800, 0x00000005, - 0x0401f99e, 0x4d3c0000, 0x42027800, 0x00000001, - 0x0201f800, 0x00109874, 0x5c027800, 0x1c01f000, - 0x59a80016, 0x80000540, 0x04000015, 0x4803c857, - 0x42001000, 0x00104148, 0x0201f800, 0x00105f90, - 0x59a80016, 0x82000580, 0x00000084, 0x0402000b, - 0x59cc1006, 0x82081580, 0x11060000, 0x04020007, - 0x80000580, 0x0401faa0, 0x4a035014, 0x00000018, - 0x0401f804, 0x0401f002, 0x0401f94b, 0x1c01f000, - 0x4803c856, 0x4a035014, 0x00000019, 0x83cca400, - 0x00000006, 0x4200a800, 0x0010b552, 0x4200b000, - 0x00000021, 0x0201f800, 0x0010ab17, 0x42003800, - 0x0010b553, 0x0401f941, 0x04020018, 0x401c2800, - 0x50141000, 0x80080130, 0x80000000, 0x40001800, - 0x82081500, 0x00ffffff, 0x800000f0, 0x80080540, - 0x44002800, 0x59a80810, 0x82040d00, 0x000000ff, - 0x400c1000, 0x80081104, 0x82082400, 0x0010b553, - 0x50101000, 0x820c0500, 0x00000003, 0x0c01f806, - 0x80081540, 0x44082000, 0x42000800, 0x00000021, - 0x0401f156, 0x0010401d, 0x00104022, 0x00104027, - 0x0010402c, 0x800408f0, 0x40040000, 0x82081500, - 0x00ffffff, 0x1c01f000, 0x800408e0, 0x40040000, - 0x82081500, 0xff00ffff, 0x1c01f000, 0x800408d0, - 0x40040000, 0x82081500, 0xffff00ff, 0x1c01f000, - 0x40040000, 0x82081500, 0xffffff00, 0x1c01f000, - 0x59a80016, 0x80000540, 0x04000016, 0x4803c857, - 0x42001000, 0x00104148, 0x0201f800, 0x00105f90, - 0x59a80016, 0x82000580, 0x00000084, 0x0402000c, - 0x59cc1006, 0x82081580, 0x11070000, 0x04020008, - 0x4a035013, 0x00000001, 0x0401f8d2, 0x4a035014, - 0x0000001a, 0x0401f804, 0x0401f002, 0x0401f8f2, - 0x1c01f000, 0x82000540, 0x00000001, 0x0401fa3e, - 0x4a035014, 0x0000001b, 0x83cca400, 0x00000006, - 0x4200a800, 0x0010b552, 0x59a82016, 0x40100000, - 0x8000b104, 0x40580800, 0x5450a800, 0x8050a000, - 0x8054a800, 0x8058b040, 0x040207fc, 0x0401f113, - 0x1c01f000, 0x1c01f000, 0x4803c856, 0x42003000, - 0x00000004, 0x42004000, 0x0010b553, 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, 0x0010210e, - 0x50242800, 0x82142d00, 0x000000ff, 0x48175010, - 0x4c040000, 0x40140800, 0x0201f800, 0x001015eb, - 0x5c000800, 0x40001800, 0x500c0000, 0x80100540, - 0x44001800, 0x59a80015, 0x84000540, 0x48035015, - 0x4200a800, 0x0010b553, 0x4020a000, 0x4200b000, - 0x00000004, 0x0201f800, 0x0010ab17, 0x82000540, - 0x00000001, 0x0401f002, 0x80000580, 0x1c01f000, - 0x4807c857, 0x480bc857, 0x4008b000, 0x83cca400, - 0x00000007, 0x4200a800, 0x0010b553, 0x40541000, - 0x0201f800, 0x0010ab17, 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, - 0x0010210e, 0x50102800, 0x82142d00, 0x000000ff, - 0x48175010, 0x4c040000, 0x40140800, 0x0201f800, - 0x001015eb, 0x5c000800, 0x59a80015, 0x84000540, - 0x48035015, 0x80000580, 0x1c01f000, 0x4807c856, - 0x42001000, 0x00008017, 0x59a8184e, 0x0201f800, - 0x0010aa4f, 0x0201f800, 0x00103a3e, 0x1c01f000, - 0x4807c856, 0x4200b000, 0x00000020, 0x83cca400, - 0x00000007, 0x4200a800, 0x0010be21, 0x0201f000, - 0x0010ab28, 0x4807c856, 0x0201f800, 0x00106ede, - 0x42000800, 0x000000f7, 0x0401f8de, 0x497b2804, - 0x497b2805, 0x497b281c, 0x497b281d, 0x4202d800, - 0x00000001, 0x42006000, 0xbf7fffff, 0x42006800, - 0x00018000, 0x0401f950, 0x42006000, 0xfffeffff, - 0x41786800, 0x0401f94c, 0x497b504e, 0x42000800, - 0x0000002d, 0x42001000, 0x001041bc, 0x0201f000, - 0x00105f69, 0x4807c856, 0x0401ffe3, 0x497b5014, - 0x497b5016, 0x1c01f000, 0x4807c856, 0x59a80005, - 0x8c000506, 0x1c01f000, 0x4807c856, 0x42006000, - 0xffffffff, 0x42006800, 0x00000028, 0x0401f136, - 0x4807c856, 0x0401ffc2, 0x0201f800, 0x00106c55, - 0x4df00000, 0x0201f800, 0x00106e21, 0x5c03e000, - 0x02000800, 0x00106c4b, 0x59c400a4, 0x82000500, - 0x0000000f, 0x82000580, 0x00000002, 0x0402000a, - 0x42006000, 0xffffffff, 0x42006800, 0x00200000, - 0x0401f921, 0x42006000, 0xffdfffff, 0x41786800, - 0x0401f91d, 0x497b5014, 0x42000800, 0x000000f7, - 0x0401f89c, 0x59c400a3, 0x82000500, 0xbf20bfff, - 0x82000540, 0x0001c000, 0x480388a3, 0x84000520, - 0x480388a3, 0x1c01f000, 0x497b5016, 0x59b400f5, + 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, 0x0010b54b, 0x42000000, - 0x0010b552, 0x480368f1, 0x82040400, 0x0000dc00, + 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, 0x0010b818, 0x0201f800, 0x0010aa47, - 0x4a038805, 0x02000000, 0x0201f800, 0x001019fe, - 0x4000c000, 0x0201f800, 0x00101963, 0x4202d800, + 0x42000000, 0x0010b616, 0x0201f800, 0x0010a86e, + 0x4a038805, 0x02000000, 0x0201f800, 0x00101a59, + 0x4000c000, 0x0201f800, 0x001019d0, 0x4202d800, 0x00000001, 0x497b5014, 0x5c00c000, 0x5c00b800, 0x1c01f000, 0x59c8010b, 0x8c000502, 0x040007e2, 0x59c408a4, 0x82040d00, 0x0000000f, 0x82040d80, @@ -4245,52 +4127,54 @@ uint32_t risc_code01[] = { 0x00002000, 0x0401f004, 0x59a80812, 0x82040d40, 0x00001000, 0x4807504e, 0x59a8084a, 0x800409c0, 0x04020007, 0x42000800, 0x000007d0, 0x42001000, - 0x00104148, 0x0201f800, 0x0010606e, 0x1c01f000, - 0x4807c856, 0x0401ff4e, 0x0201f800, 0x00106c55, - 0x4df00000, 0x0201f800, 0x00106e21, 0x5c03e000, - 0x02000800, 0x00106c4b, 0x59c400a4, 0x82000500, + 0x00103f62, 0x0201f800, 0x00105da7, 0x1c01f000, + 0x4807c856, 0x0401ff40, 0x0201f800, 0x0010698c, + 0x4df00000, 0x0201f800, 0x00106b71, 0x5c03e000, + 0x02000800, 0x00106982, 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, 0x00000002, 0x0402000a, 0x42006000, 0xffffffff, 0x42006800, 0x00200000, - 0x0401f8ad, 0x42006000, 0xffdfffff, 0x41786800, - 0x0401f8a9, 0x0201f800, 0x00105141, 0x04000014, - 0x0201f800, 0x00105151, 0x04020011, 0x4a035032, - 0x0000aaaa, 0x4c040000, 0x0201f800, 0x0010162a, + 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, 0x001050a2, 0x0401f008, 0x4a03504c, + 0x0201f800, 0x00104d76, 0x0401f008, 0x4a03504c, 0x00000005, 0x42000000, 0x00000001, 0x0201f800, - 0x00101590, 0x0401ff2c, 0x1c01f000, 0x0401f805, - 0x42006000, 0xbf7f7fff, 0x41786800, 0x0401f086, - 0x0201f800, 0x00105151, 0x04020005, 0x59c40006, - 0x82000540, 0x000000f0, 0x48038806, 0x1c01f000, + 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, 0x0010b83b, - 0x0201f800, 0x0010aa47, 0x42003000, 0x00000005, + 0x1c01f000, 0x4807c856, 0x42000000, 0x0010b639, + 0x0201f800, 0x0010a86e, 0x42003000, 0x00000005, 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000d, 0x42027800, 0x00000002, 0x0401f038, 0x4807c856, - 0x42000000, 0x0010b86b, 0x0201f800, 0x0010aa47, + 0x42000000, 0x0010b66a, 0x0201f800, 0x0010a86e, 0x42003000, 0x00000000, 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000f, 0x42027800, 0x00000002, - 0x0401f02a, 0x4807c856, 0x42000000, 0x0010b86a, - 0x0201f800, 0x0010aa47, 0x42003000, 0x00000003, + 0x0401f02a, 0x4807c856, 0x42000000, 0x0010b669, + 0x0201f800, 0x0010a86e, 0x42003000, 0x00000003, 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000e, 0x42027800, 0x00000202, 0x0401f01c, 0x4807c856, - 0x42000000, 0x0010b869, 0x0201f800, 0x0010aa47, + 0x42000000, 0x0010b668, 0x0201f800, 0x0010a86e, 0x42003000, 0x00000004, 0x4d3c0000, 0x4c180000, 0x42003000, 0x00000010, 0x42027800, 0x00000202, - 0x0401f00e, 0x4807c856, 0x42000000, 0x0010b83e, - 0x0201f800, 0x0010aa47, 0x42003000, 0x00000001, + 0x0401f00e, 0x4807c856, 0x42000000, 0x0010b63c, + 0x0201f800, 0x0010a86e, 0x42003000, 0x00000001, 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000c, 0x42027800, 0x00000202, 0x42001800, 0x0000ffff, - 0x42002000, 0x00000007, 0x0201f800, 0x00103aae, - 0x5c003000, 0x4d400000, 0x0201f800, 0x0010a95d, - 0x42028000, 0x0000002a, 0x0201f800, 0x00101fe5, + 0x42002000, 0x00000007, 0x0201f800, 0x001038c7, + 0x5c003000, 0x4d400000, 0x0201f800, 0x0010a784, + 0x42028000, 0x0000002a, 0x0201f800, 0x00101d90, 0x5c028000, 0x5c027800, 0x1c01f000, 0x4807c856, - 0x04011000, 0x4a03c840, 0x0010b54b, 0x4a03c842, + 0x04011000, 0x4a03c840, 0x0010b349, 0x4a03c842, 0x00000040, 0x40000000, 0x040117ff, 0x42007800, - 0x0010b54b, 0x46007800, 0x00000011, 0x803c7800, + 0x0010b349, 0x46007800, 0x00000011, 0x803c7800, 0x4a007800, 0x220000ef, 0x4a007801, 0x000000ef, 0x4a007802, 0x01380000, 0x4a007803, 0x00000000, 0x4a007804, 0xffffffff, 0x4a007805, 0x00000000, @@ -4304,27 +4188,27 @@ uint32_t risc_code01[] = { 0x42000000, 0x00000006, 0x80000040, 0x040207ff, 0x0401f7f4, 0x1c01f000, 0x4c5c0000, 0x4c600000, 0x59c4b805, 0x485fc856, 0x8c5cbd3a, 0x04020005, - 0x42000000, 0x0010b818, 0x0201f800, 0x0010aa47, - 0x4a038805, 0x02000000, 0x0201f800, 0x001019fe, - 0x4000c000, 0x0201f800, 0x00101963, 0x4a038805, + 0x42000000, 0x0010b616, 0x0201f800, 0x0010a86e, + 0x4a038805, 0x02000000, 0x0201f800, 0x00101a59, + 0x4000c000, 0x0201f800, 0x001019d0, 0x4a038805, 0x04000000, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x497a6a00, 0x4937c857, 0x4a026c00, 0x00000707, - 0x497a6801, 0x497a6808, 0x497a6809, 0x497a6806, - 0x497a6807, 0x497a6c0b, 0x497a680c, 0x0201f800, - 0x00103b25, 0x04020006, 0x5934080f, 0x59340010, - 0x80040540, 0x02020800, 0x001005d8, 0x4a026a04, - 0x00000100, 0x497a6a03, 0x59340402, 0x82000500, - 0x000000ff, 0x48026c02, 0x497a6c04, 0x497a6a05, - 0x497a6c05, 0x497a6811, 0x4d2c0000, 0x5934000d, - 0x49466c03, 0x80025d40, 0x04000004, 0x0201f800, - 0x001007fd, 0x497a680d, 0x5c025800, 0x599c0401, - 0x48026a0b, 0x599c0208, 0x48026c12, 0x497a680a, - 0x0201f000, 0x00104c62, 0x42000000, 0x00000005, - 0x80000d80, 0x0401f02d, 0x0201f800, 0x00104a09, + 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, - 0x000201c4, 0x42000000, 0x00000029, 0x42000800, + 0x000201f8, 0x42000000, 0x00000029, 0x42000800, 0x00001000, 0x492fc857, 0x0401f018, 0x492fc857, 0x42000000, 0x00000028, 0x0401f012, 0x59a80805, 0x8c040d02, 0x04020003, 0x8c040d00, 0x04000004, @@ -4333,25 +4217,25 @@ uint32_t risc_code01[] = { 0x492fc857, 0x42000800, 0x00001000, 0x0401f003, 0x492fc857, 0x80000d80, 0x4803c857, 0x80028540, 0x1c01f000, 0x4803c857, 0x59a80005, 0x8c000500, - 0x040207ec, 0x0201f800, 0x001049e7, 0x040207e4, + 0x040207ec, 0x0201f800, 0x00104836, 0x040207e4, 0x59340200, 0x8c00050e, 0x040007e1, 0x0201f000, - 0x000201c4, 0x0201f800, 0x001047eb, 0x040007bf, - 0x0201f000, 0x000201c8, 0x592c0206, 0x492fc857, + 0x000201f8, 0x0201f800, 0x00104639, 0x040007bf, + 0x0201f000, 0x000201fc, 0x592c0206, 0x492fc857, 0x82000d80, 0x000007ff, 0x04020006, 0x4a025c0a, - 0x00000030, 0x42026800, 0x0010b524, 0x0401f021, + 0x00000030, 0x42026800, 0x0010b320, 0x0401f021, 0x82000c80, 0x000007f0, 0x04021046, 0x81ac0400, 0x50000000, 0x80026d40, 0x04000038, 0x0201f800, - 0x001048e3, 0x04020038, 0x592c040a, 0x8c00050a, - 0x04020014, 0x592e6009, 0x83300480, 0x0010d1c0, + 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, 0x0002075a, 0x04000019, 0x592c0206, + 0x0201f800, 0x00020892, 0x04000019, 0x592c0206, 0x49366009, 0x492e6008, 0x4a026406, 0x00000009, 0x497a6015, 0x49325809, 0x82000d80, 0x000007ff, 0x04020003, 0x4a026015, 0x00008000, 0x42027000, - 0x00000043, 0x0201f800, 0x000207a1, 0x80000580, + 0x00000043, 0x0201f800, 0x000208d8, 0x80000580, 0x0401f020, 0x40000800, 0x58040000, 0x80000d40, 0x040207fd, 0x492c0800, 0x0401f01a, 0x42000000, 0x0000002c, 0x0401f016, 0x42000000, 0x00000028, @@ -4362,198 +4246,207 @@ uint32_t risc_code01[] = { 0x040207fb, 0x42000000, 0x00000005, 0x80000540, 0x1c01f000, 0x492fc857, 0x592e8c06, 0x83440d80, 0x000007fc, 0x04000004, 0x83440480, 0x000007f0, - 0x04021014, 0x0201f800, 0x00020245, 0x04020011, - 0x0201f800, 0x001049f3, 0x04020011, 0x0201f800, - 0x0002075a, 0x0400001c, 0x49366009, 0x492e6008, + 0x04021014, 0x0201f800, 0x00020267, 0x04020011, + 0x0201f800, 0x00104842, 0x04020011, 0x0201f800, + 0x00020892, 0x0400001c, 0x49366009, 0x492e6008, 0x4a026406, 0x0000000a, 0x42027000, 0x00000040, - 0x0201f800, 0x000207a1, 0x80000580, 0x0401f011, + 0x0201f800, 0x000208d8, 0x80000580, 0x0401f011, 0x42000000, 0x00000028, 0x0401f00d, 0x0201f800, - 0x00104a09, 0x040007fb, 0x59a80805, 0x82040d00, + 0x00104858, 0x040007fb, 0x59a80805, 0x82040d00, 0x00000003, 0x04000004, 0x42000000, 0x00000004, 0x0401f003, 0x42000000, 0x00000029, 0x80000540, 0x1c01f000, 0x42000000, 0x0000002c, 0x0401f7fc, 0x492fc857, 0x592e8c06, 0x4947c857, 0x83440c80, - 0x00000800, 0x42000000, 0x0000000a, 0x04021176, + 0x00000800, 0x42000000, 0x0000000a, 0x0402119c, 0x592c4207, 0x4823c857, 0x82200500, 0x0000000f, - 0x0c01f001, 0x001043d5, 0x0010445d, 0x001044a9, - 0x001044b4, 0x001044bf, 0x001043d1, 0x001043d1, - 0x001043d1, 0x001044cf, 0x00104513, 0x00104530, - 0x001043d1, 0x001043d1, 0x001043d1, 0x001043d1, - 0x001043d1, 0x4803c857, 0x42000000, 0x0000000c, - 0x0401f15d, 0x592c1008, 0x82081500, 0x00ffffff, + 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, - 0x04000155, 0x0201f800, 0x00104919, 0x04000036, + 0x0400017b, 0x0201f800, 0x00104768, 0x04000036, 0x4803c857, 0x82004d80, 0x0000001d, 0x0402001a, - 0x0201f800, 0x00105755, 0x59340405, 0x4c000000, - 0x0201f800, 0x001049e7, 0x5c000000, 0x04000004, + 0x0201f800, 0x00105439, 0x59340405, 0x4c000000, + 0x0201f800, 0x00104836, 0x5c000000, 0x04000004, 0x8c20450a, 0x04000028, 0x80000580, 0x44002800, 0x59340008, 0x48002802, 0x59340009, 0x48002801, 0x59340006, 0x48002804, 0x59340007, 0x48002803, - 0x4200b000, 0x00000005, 0x0201f800, 0x0010955f, - 0x0401f166, 0x4803c857, 0x82004d80, 0x0000001a, - 0x04020003, 0x40101000, 0x0401f136, 0x4803c857, + 0x4200b000, 0x00000005, 0x0201f800, 0x00109328, + 0x0401f18c, 0x4803c857, 0x82004d80, 0x0000001a, + 0x04020003, 0x40101000, 0x0401f15c, 0x4803c857, 0x82004d80, 0x0000001b, 0x04020003, 0x40181000, - 0x0401f130, 0x4803c857, 0x82004d80, 0x0000001c, - 0x04000131, 0x82004d80, 0x00000019, 0x42000000, - 0x0000000a, 0x04000120, 0x42000000, 0x0000000a, - 0x04020137, 0x59a80005, 0x8c000514, 0x0400001b, - 0x0201f800, 0x001049e7, 0x04000018, 0x59340212, + 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, 0x00104c6d, 0x42000000, 0x0000001c, - 0x40181000, 0x04020107, 0x0201f800, 0x0002075a, - 0x04000111, 0x49366009, 0x492e6008, 0x4a026406, + 0x0201f800, 0x00104ada, 0x42000000, 0x0000001c, + 0x40181000, 0x0402012d, 0x0201f800, 0x00020892, + 0x04000137, 0x49366009, 0x492e6008, 0x4a026406, 0x00000001, 0x8c20450a, 0x04000004, 0x592c0404, 0x8400055c, 0x48025c04, 0x4c200000, 0x4d3c0000, - 0x42027800, 0x00001000, 0x0201f800, 0x0010203c, + 0x42027800, 0x00001800, 0x0201f800, 0x00101de2, 0x5c027800, 0x5c004000, 0x8c204512, 0x0400000b, 0x599c0018, 0x8c000518, 0x04000008, 0x592c0009, 0x82000500, 0x00000380, 0x5934080a, 0x80040d40, - 0x84040d54, 0x4806680a, 0x417a7800, 0x0401f914, - 0x42000800, 0x00000003, 0x0401f91b, 0x42027000, - 0x00000002, 0x0201f800, 0x000207a1, 0x80000580, - 0x0401f10a, 0x0201f800, 0x00020245, 0x040200ec, - 0x0201f800, 0x001049ed, 0x04000008, 0x0201f800, - 0x001049e7, 0x040200ec, 0x417a7800, 0x417a6000, - 0x0201f800, 0x001020a1, 0x59a80005, 0x8c000514, - 0x0400001b, 0x0201f800, 0x001049e7, 0x04000018, + 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, 0x00104c6d, 0x42000000, - 0x0000001c, 0x40181000, 0x040200b2, 0x0201f800, - 0x0002075a, 0x040000bc, 0x5934080a, 0x8c204512, + 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, 0x0401f8c8, - 0x42000800, 0x00000005, 0x0401f8cf, 0x42027000, - 0x00000003, 0x0201f800, 0x000207a1, 0x80000580, - 0x0401f0be, 0x0201f800, 0x00020245, 0x040200a0, - 0x0201f800, 0x001049fc, 0x040200a3, 0x0201f800, - 0x00109517, 0x04000094, 0x80000580, 0x0401f0b3, - 0x0201f800, 0x00020245, 0x04020095, 0x0201f800, - 0x001049fc, 0x04020098, 0x0201f800, 0x001090e6, - 0x04000089, 0x80000580, 0x0401f0a8, 0x0201f800, - 0x00020245, 0x0402008a, 0x83444d80, 0x000007fe, - 0x42000000, 0x0000000a, 0x0402006b, 0x0201f800, - 0x001049e7, 0x04020088, 0x0201f800, 0x0010952f, - 0x04000079, 0x80000580, 0x0401f098, 0x82200500, + 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, 0x0402005c, 0x8c20450a, 0x0400000d, + 0x0000000c, 0x0402007e, 0x8c20450a, 0x0400000d, 0x4d3c0000, 0x42027800, 0x00001000, 0x8c20450e, 0x04020002, 0x853e7d56, 0x82200500, 0x000000a0, - 0x0201f800, 0x001049d3, 0x5c027800, 0x0401f07f, - 0x0201f800, 0x00020245, 0x04020065, 0x8c204508, - 0x04000010, 0x4d3c0000, 0x42027800, 0x00001000, - 0x8c20450e, 0x04020002, 0x853e7d56, 0x82200500, - 0x00000090, 0x0201f800, 0x001049bb, 0x5c027800, - 0x42000000, 0x0000000a, 0x0402003b, 0x0401f06b, - 0x836c0580, 0x00000003, 0x42000800, 0x00000007, - 0x0402000f, 0x0201f800, 0x001049f3, 0x04000007, - 0x4c000000, 0x0201f800, 0x00104a1f, 0x5c000000, - 0x0400004d, 0x0401f05d, 0x0201f800, 0x001094c5, - 0x04000007, 0x80000580, 0x0401f05c, 0x0201f800, - 0x00104a1f, 0x04000051, 0x0401f054, 0x0201f800, - 0x00104a1f, 0x04000034, 0x0401f050, 0x0201f800, - 0x00020245, 0x04020036, 0x836c0580, 0x00000003, - 0x04020040, 0x8c204508, 0x04000006, 0x417a7800, - 0x417a6000, 0x0201f800, 0x001020a1, 0x0401f043, - 0x0201f800, 0x001049ed, 0x04000008, 0x0201f800, - 0x001049e7, 0x0402002c, 0x417a7800, 0x417a6000, - 0x0201f800, 0x001020a1, 0x480bc856, 0x0201f800, - 0x00109332, 0x04000018, 0x80000580, 0x0401f037, - 0x0401f7e3, 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, 0x001005d8, - 0x4803c857, 0x48026c00, 0x82040d80, 0x00000006, - 0x04020005, 0x59341404, 0x800811c0, 0x02000800, - 0x001005d8, 0x1c01f000, 0x5c000000, 0x4c000000, - 0x4803c857, 0x4947c857, 0x481bc857, 0x83440480, - 0x00000800, 0x04021034, 0x83441400, 0x0010ac00, - 0x50080000, 0x80026d40, 0x04020011, 0x4c180000, - 0x4d2c0000, 0x0201f800, 0x001007d3, 0x412e6800, - 0x5c025800, 0x5c003000, 0x04000027, 0x45341000, - 0x497a680d, 0x497a6810, 0x497a680f, 0x497a680e, - 0x4c180000, 0x0401fcf3, 0x5c003000, 0x59340a12, - 0x4c040000, 0x0201f800, 0x0010513b, 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, 0x0010ac00, 0x50080000, - 0x80026d40, 0x0400000b, 0x0401fbf9, 0x0402000a, - 0x59a80005, 0x8c000502, 0x04000004, 0x59340200, - 0x8c00050e, 0x04000004, 0x82000540, 0x00000001, - 0x1c01f000, 0x80000580, 0x0401f7fe, 0x5c000000, - 0x4c000000, 0x4803c857, 0x4947c857, 0x4d2c0000, - 0x4d300000, 0x83440480, 0x00000800, 0x04021024, - 0x83441400, 0x0010ac00, 0x50080000, 0x80026d40, - 0x0400001b, 0x45781000, 0x5934000d, 0x80025d40, - 0x02020800, 0x001007fd, 0x59366011, 0x813261c0, - 0x0400000e, 0x4c640000, 0x5930c800, 0x59325808, - 0x0201f800, 0x00109037, 0x02020800, 0x001007fd, - 0x0201f800, 0x0002077d, 0x82666540, 0x00000000, - 0x040207f6, 0x5c00c800, 0x0201f800, 0x00104c62, - 0x41365800, 0x0201f800, 0x001007f5, 0x80000580, - 0x5c026000, 0x5c025800, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fb, 0x4937c857, 0x4c580000, - 0x59cc0001, 0x82000500, 0x00ffffff, 0x48026802, - 0x497a6c01, 0x497a6a01, 0x59340200, 0x84000502, - 0x48026a00, 0x0201f800, 0x0010513b, 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, 0x0010ab17, 0x83cca400, - 0x0000000d, 0x8334ac00, 0x00000008, 0x4200b000, - 0x00000002, 0x0201f800, 0x0010ab17, 0x59cc0a18, - 0x82040480, 0x00000800, 0x0402100c, 0x82040480, - 0x00000400, 0x04001004, 0x42000800, 0x00000400, - 0x0401f006, 0x82040480, 0x00000200, 0x04001003, - 0x42000800, 0x00000200, 0x48066a04, 0x59340403, + 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, 0x42000800, 0x00000004, 0x59cc1207, - 0x800811c0, 0x04000005, 0x82080480, 0x00000004, - 0x04021002, 0x40080800, 0x48066c04, 0x5c00b000, + 0x48066a04, 0x0201f800, 0x00104afd, 0x5c00b000, 0x1c01f000, 0x4937c857, 0x59a80026, 0x8c000508, 0x04000004, 0x84000556, 0x4803c857, 0x48035026, 0x59cc0207, 0x4803c857, 0x48026a05, 0x59cc020a, @@ -4573,15 +4466,15 @@ uint32_t risc_code01[] = { 0x4c580000, 0x5934000d, 0x80025d40, 0x04000029, 0x592c0003, 0x82000480, 0x00000008, 0x0400100b, 0x412cb800, 0x592c0001, 0x80025d40, 0x040207f9, - 0x0201f800, 0x001007e4, 0x04000037, 0x492fc857, + 0x0201f800, 0x0010082a, 0x04000037, 0x492fc857, 0x492cb801, 0x0401f020, 0x832c0c00, 0x00000004, 0x4200b000, 0x00000008, 0x50040000, 0x82000580, 0xffffffff, 0x04020006, 0x80041000, 0x50080000, 0x82000580, 0xffffffff, 0x04000007, 0x82040c00, 0x00000002, 0x8058b040, 0x040207f4, 0x0201f800, - 0x001005d8, 0x45480800, 0x454c1000, 0x592c1803, + 0x00100615, 0x45480800, 0x454c1000, 0x592c1803, 0x800c1800, 0x480e5803, 0x480fc857, 0x0401f014, - 0x0201f800, 0x001007e4, 0x04000017, 0x492fc857, + 0x0201f800, 0x0010082a, 0x04000017, 0x492fc857, 0x492e680d, 0x497a5802, 0x4a025803, 0x00000001, 0x494a5804, 0x494e5805, 0x832c0c00, 0x00000006, 0x4200b000, 0x0000000e, 0x46000800, 0xffffffff, @@ -4590,307 +4483,311 @@ uint32_t risc_code01[] = { 0x1c01f000, 0x80000580, 0x0401f7fb, 0x4803c856, 0x4d3c0000, 0x4d2c0000, 0x5934000d, 0x80025d40, 0x0400001f, 0x592c0002, 0x80000540, 0x0402001f, - 0x412e7800, 0x0401f8ce, 0x0402001c, 0x46000800, + 0x412e7800, 0x0401f8c8, 0x0402001c, 0x46000800, 0xffffffff, 0x46001000, 0xffffffff, 0x4813c857, 0x480fc857, 0x580c0003, 0x82000c80, 0x00000002, 0x04021014, 0x480fc857, 0x400c0000, 0x812c0580, 0x04020004, 0x580c0001, 0x4802680d, 0x0401f003, 0x580c0001, 0x48002001, 0x400e5800, 0x0201f800, - 0x001007f4, 0x82000540, 0x00000001, 0x5c025800, + 0x0010083a, 0x82000540, 0x00000001, 0x5c025800, 0x5c027800, 0x1c01f000, 0x80000580, 0x0401f7fc, 0x80000040, 0x48001803, 0x4803c857, 0x0401f7f6, - 0x0201f800, 0x00020086, 0x59300007, 0x8400054e, + 0x0201f800, 0x00020087, 0x59300007, 0x8400054e, 0x48026007, 0x592c1a04, 0x820c1d00, 0x000000ff, 0x820c0580, 0x00000048, 0x04000013, 0x0201f000, - 0x0002028e, 0x8c000500, 0x02020800, 0x000200e5, + 0x000202b0, 0x8c000500, 0x02020800, 0x000200e6, 0x4a026203, 0x00000002, 0x592c1a04, 0x820c1d00, 0x000000ff, 0x820c0580, 0x00000018, 0x02000000, - 0x0002028e, 0x820c0580, 0x00000048, 0x02020000, - 0x0002028e, 0x42000800, 0x80000804, 0x0201f800, - 0x00106721, 0x0201f000, 0x00020297, 0x4a025a06, - 0x00000008, 0x0201f000, 0x000202da, 0x4a025a06, - 0x00000029, 0x0201f000, 0x000202da, 0x4a025a06, - 0x0000002a, 0x0201f000, 0x000202da, 0x4a025a06, - 0x00000028, 0x0201f000, 0x000202da, 0x4943c857, + 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, - 0x00020245, 0x0402000d, 0x8d3e7d14, 0x04000005, - 0x59340212, 0x82000500, 0x0000ff00, 0x04000007, - 0x8d3e7d06, 0x04000004, 0x59340200, 0x8c00050e, - 0x04020002, 0x0401f813, 0x81468800, 0x8058b040, - 0x040207ef, 0x83440480, 0x00000800, 0x04021008, - 0x8d3e7d02, 0x04000006, 0x42028800, 0x000007f0, - 0x4200b000, 0x00000010, 0x0401f7e5, 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, 0x001091c6, 0x0201f800, 0x000202da, - 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, 0x001007e4, 0x04000010, - 0x492e680d, 0x4a025802, 0x00000001, 0x497a5803, - 0x832c0c00, 0x00000004, 0x4200b000, 0x00000010, - 0x46000800, 0xffffffff, 0x80040800, 0x8058b040, - 0x040207fc, 0x82000540, 0x00000001, 0x5c025800, - 0x5c00b000, 0x1c01f000, 0x4d2c0000, 0x592e5801, - 0x0201f800, 0x001007fd, 0x5c025800, 0x0401f7ea, - 0x4d2c0000, 0x5936580d, 0x812e59c0, 0x04000007, - 0x4937c857, 0x497a680d, 0x0201f800, 0x001007fd, - 0x82000540, 0x00000001, 0x5c025800, 0x1c01f000, - 0x59340405, 0x4937c857, 0x4803c857, 0x8c000508, - 0x1c01f000, 0x4803c856, 0x0201f800, 0x0010513b, - 0x04000011, 0x59a80815, 0x8c040d04, 0x0402000e, - 0x59a80826, 0x8c040d06, 0x0400000b, 0x83ac0400, - 0x000007fe, 0x50000000, 0x80026d40, 0x04000006, - 0x0401f9a7, 0x04020004, 0x59340200, 0x8400055a, - 0x48026a00, 0x599c0017, 0x8c000508, 0x04000015, - 0x4200b000, 0x000007f0, 0x417a8800, 0x0201f800, - 0x00020245, 0x0402000c, 0x0401f999, 0x0402000a, - 0x59a80010, 0x59340802, 0x80040580, 0x82000500, - 0x00ffff00, 0x04020004, 0x59340200, 0x8400055a, - 0x48026a00, 0x81468800, 0x8058b040, 0x040207f0, - 0x0401f884, 0x04000003, 0x59a80836, 0x0401f006, - 0x599c0017, 0x8c000508, 0x04000007, 0x42000800, - 0x000007d0, 0x42001000, 0x00104876, 0x0201f800, - 0x0010606e, 0x1c01f000, 0x4803c856, 0x4d340000, - 0x4d440000, 0x4d3c0000, 0x4c580000, 0x42001000, - 0x00104876, 0x0201f800, 0x00105f90, 0x59a80826, - 0x8c040d06, 0x04000015, 0x0401f86a, 0x04000013, - 0x83ae6c00, 0x000007fe, 0x51366800, 0x59340200, - 0x8400051a, 0x48026a00, 0x599c0017, 0x8c000508, + 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, - 0x00104876, 0x0201f800, 0x0010606e, 0x0201f800, - 0x00101e45, 0x0401f027, 0x4200b000, 0x000007f0, - 0x80028d80, 0x0201f800, 0x00020245, 0x0402001e, - 0x59340200, 0x8c00051a, 0x0400001b, 0x59368c03, - 0x417a7800, 0x42028000, 0x00000029, 0x41783000, - 0x0201f800, 0x0010a446, 0x59340200, 0x84000558, - 0x8400051a, 0x48026a00, 0x4937c857, 0x4a026c00, - 0x00000707, 0x42028000, 0x00000029, 0x0201f800, - 0x00106ab4, 0x417a7800, 0x0201f800, 0x001067fd, - 0x80000d80, 0x0201f800, 0x0010a2ff, 0x0201f800, - 0x00106c4b, 0x81468800, 0x8058b040, 0x040207de, - 0x5c00b000, 0x5c027800, 0x5c028800, 0x5c026800, + 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, 0x4803c856, - 0x42026800, 0x0010b524, 0x497a680e, 0x42028800, - 0x000007ff, 0x0201f800, 0x001042b4, 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, 0x001005d8, 0x59341200, 0x813e79c0, - 0x04000003, 0x8408155e, 0x0401f002, 0x8408151e, - 0x480a6a00, 0x1c01f000, 0x4937c857, 0x0201f800, - 0x0010210a, 0x04000006, 0x59a80835, 0x42001000, - 0x00104910, 0x0201f800, 0x0010606e, 0x1c01f000, - 0x4937c857, 0x42001000, 0x00104910, 0x0201f800, - 0x00105f90, 0x59a81026, 0x84081512, 0x480b5026, - 0x1c01f000, 0x4c380000, 0x4c340000, 0x4c240000, - 0x4c600000, 0x4008c000, 0x83440480, 0x00000800, - 0x04021045, 0x80002d80, 0x41442000, 0x83447400, - 0x0010ac00, 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, 0x0010b3f0, - 0x0401f007, 0x82104d80, 0x000007f0, 0x04020004, - 0x41782000, 0x42007000, 0x0010ac00, 0x8058b040, - 0x040207a4, 0x801429c0, 0x04020007, 0x0201f800, - 0x001005d8, 0x4947c857, 0x42000000, 0x0000000a, - 0x0401f01c, 0x4d2c0000, 0x4c180000, 0x40603000, - 0x0401fc12, 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, 0x00020253, 0x1c01f000, 0x4803c857, - 0x4947c857, 0x4c300000, 0x82006500, 0x00000030, - 0x04000006, 0x4c000000, 0x0201f800, 0x0010942a, - 0x5c000000, 0x0402000b, 0x8c00050e, 0x04000006, - 0x0201f800, 0x00020245, 0x04020006, 0x4937c857, - 0x0401fc2f, 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, + 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, 0x4c600000, 0x59340400, 0x8200bd00, - 0x0000ff00, 0x825cc580, 0x00000400, 0x04000003, - 0x825cc580, 0x00000600, 0x5c00c000, 0x5c00b800, - 0x1c01f000, 0x4c5c0000, 0x59340400, 0x82000500, - 0x000000ff, 0x8200bd80, 0x00000003, 0x04000003, - 0x8200bd80, 0x00000005, 0x5c00b800, 0x1c01f000, - 0x4c5c0000, 0x59340400, 0x82000500, 0x0000ff00, - 0x8400b9c0, 0x805c0580, 0x4937c857, 0x4803c857, - 0x48026c00, 0x5c00b800, 0x1c01f000, 0x4c040000, - 0x4c080000, 0x592c0207, 0x8c00050c, 0x0400000f, - 0x592e8c06, 0x82000500, 0x00000080, 0x84000548, - 0x4d3c0000, 0x42027800, 0x00001000, 0x0401ff90, - 0x5c027800, 0x82000540, 0x00000001, 0x5c001000, - 0x5c000800, 0x1c01f000, 0x80000580, 0x0401f7fc, - 0x592c040b, 0x82000500, 0x0000e000, 0x82000580, - 0x00006000, 0x04000019, 0x836c0580, 0x00000003, - 0x04000016, 0x836c0580, 0x00000002, 0x040200ff, - 0x59a80026, 0x82000d00, 0x00000038, 0x04020005, - 0x59a80832, 0x800409c0, 0x0400000c, 0x0401f0f7, - 0x82000d00, 0x00000003, 0x82040d80, 0x00000003, - 0x040200f2, 0x82000d00, 0x00000028, 0x04020003, - 0x8c00050c, 0x040000ed, 0x592c100a, 0x82080500, - 0xff000000, 0x040200ce, 0x59a80010, 0x80080580, - 0x040000c8, 0x592c0c0b, 0x82040d00, 0x0000e000, - 0x82040480, 0x00008000, 0x040210c8, 0x592e8c06, - 0x83440480, 0x00000800, 0x04001007, 0x83440580, - 0x0000ffff, 0x040200af, 0x800409c0, 0x040200f7, - 0x0401f0ac, 0x800409c0, 0x040200f4, 0x41784000, - 0x0401fead, 0x040200db, 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, - 0x59a80005, 0x8c000514, 0x04000016, 0x0401ff4c, - 0x04000014, 0x59340212, 0x82000500, 0x0000ff00, - 0x42001000, 0x00000010, 0x0402000c, 0x59a80026, - 0x8c000506, 0x0402006f, 0x42001000, 0x00000008, - 0x59340002, 0x82000500, 0x00ff0000, 0x82000580, - 0x00ff0000, 0x04000003, 0x0401f9bf, 0x04020065, - 0x0201f800, 0x0002075a, 0x0400007e, 0x4a026406, - 0x00000010, 0x49366009, 0x42000800, 0x00000003, - 0x83380580, 0x00000002, 0x04000003, 0x42000800, - 0x0000000b, 0x0201f800, 0x00104571, 0x0401f044, - 0x42027000, 0x00000000, 0x0401f003, 0x42027000, - 0x00000004, 0x0401ff37, 0x04020071, 0x0401f036, - 0x42027000, 0x00000033, 0x0401f006, 0x42027000, - 0x00000005, 0x0401f003, 0x42027000, 0x00000003, - 0x0401ff23, 0x04020066, 0x59a80005, 0x8c000514, - 0x04000016, 0x0401ff12, 0x04000014, 0x59340212, + 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, 0x04020035, + 0x0402000c, 0x59a80026, 0x8c000506, 0x0402006f, 0x42001000, 0x00000008, 0x59340002, 0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000, 0x04000003, - 0x0401f985, 0x0402002b, 0x0201f800, 0x0002075a, - 0x04000044, 0x4a026406, 0x00000010, 0x49366009, - 0x42000800, 0x00000005, 0x83380580, 0x00000003, - 0x04000003, 0x42000800, 0x00000009, 0x0201f800, - 0x00104571, 0x0401f00a, 0x82102580, 0x00000011, - 0x0402002d, 0x0201f800, 0x0002075a, 0x04000031, - 0x4a026406, 0x00000010, 0x49366009, 0x492e6008, - 0x49325808, 0x813669c0, 0x04000007, 0x592c0c0b, - 0x8c040d18, 0x04000004, 0x59340200, 0x84000514, - 0x48026a00, 0x0201f800, 0x000207a1, 0x80000580, - 0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fd, - 0x42001000, 0x0000000a, 0x0401f015, 0x42001000, - 0x00000010, 0x0401f012, 0x42001000, 0x00000016, - 0x0401f00f, 0x42001000, 0x00000017, 0x0401f00c, - 0x42001000, 0x00000018, 0x0401f009, 0x42001000, - 0x0000001b, 0x0401f006, 0x42001000, 0x0000001e, - 0x0401f003, 0x42001000, 0x00000020, 0x42000800, - 0x00000019, 0x42028000, 0x00000031, 0x0401f7e2, - 0x42000800, 0x00000003, 0x0401f003, 0x42000800, - 0x0000000a, 0x41781000, 0x0401f7f7, 0x42000800, - 0x00000009, 0x59341400, 0x0401f7f3, 0x42028000, - 0x00000008, 0x0401f005, 0x42000800, 0x00000007, - 0x416c1000, 0x0401f7ec, 0x41780800, 0x41781000, - 0x0401f7cd, 0x42028000, 0x00000000, 0x0401f7fb, - 0x82004d80, 0x0000001d, 0x02000800, 0x001005d8, - 0x82004d80, 0x0000001a, 0x04020004, 0x40101000, - 0x40000800, 0x0401f7dc, 0x82004d80, 0x0000001b, - 0x04020003, 0x40181000, 0x0401f7fa, 0x82004d80, - 0x0000001c, 0x040007f7, 0x82004d80, 0x00000019, - 0x040007b8, 0x0401f7d6, 0x592e6008, 0x0201f800, - 0x0010941a, 0x040007b6, 0x59300c06, 0x82040580, - 0x00000011, 0x040207d6, 0x83440580, 0x0000ffff, - 0x04020005, 0x59326809, 0x813669c0, 0x0400000e, - 0x0401f7cf, 0x592c100a, 0x82081500, 0x00ffffff, - 0x41784000, 0x0401fda8, 0x040207d6, 0x59300009, - 0x800001c0, 0x04000003, 0x81340580, 0x040207c4, - 0x49366009, 0x592c0c0b, 0x82041500, 0x0000e000, - 0x82080580, 0x00006000, 0x04000009, 0x59300a03, - 0x82040580, 0x00000007, 0x040207b9, 0x492e6008, - 0x42027000, 0x00000054, 0x0401f77f, 0x0201f800, - 0x0010a8d4, 0x040007bc, 0x0401f7b1, 0x492fc857, - 0x59a80021, 0x800001c0, 0x04020073, 0x592e6008, - 0x4933c857, 0x0201f800, 0x0010941a, 0x04000041, - 0x59301406, 0x82080580, 0x00000005, 0x0402005b, + 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, - 0x0401fd75, 0x0402005f, 0x59300009, 0x800001c0, + 0x0401fd60, 0x0402005f, 0x59300009, 0x800001c0, 0x04000003, 0x81340580, 0x04020048, 0x4d300000, 0x592e6013, 0x4933c857, 0x83300580, 0xffffffff, - 0x0400000d, 0x0201f800, 0x0010941a, 0x5c026000, + 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, 0x000207a1, 0x80000580, + 0x00000092, 0x0201f800, 0x000208d8, 0x80000580, 0x1c01f000, 0x42001000, 0x0000000a, 0x0401f00c, 0x42001000, 0x00000010, 0x0401f009, 0x42001000, 0x00000014, 0x0401f006, 0x42001000, 0x00000018, @@ -4904,231 +4801,131 @@ uint32_t risc_code01[] = { 0x4803c857, 0x42028000, 0x00000008, 0x41780800, 0x41781000, 0x0401f7e8, 0x42000800, 0x0000001e, 0x0401f7f0, 0x42000800, 0x00000001, 0x0401f7ed, - 0x82004d80, 0x0000001d, 0x02000800, 0x001005d8, + 0x82004d80, 0x0000001d, 0x02000800, 0x00100615, 0x82004d80, 0x0000001a, 0x04020003, 0x40101000, 0x0401f7dc, 0x82004d80, 0x0000001b, 0x04020003, 0x40181000, 0x0401f7d7, 0x82004d80, 0x0000001c, 0x040007d4, 0x82004d80, 0x00000019, 0x040007d1, - 0x0401f7d5, 0x59302009, 0x801021c0, 0x04000035, - 0x58101400, 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, 0x04020019, - 0x820c0580, 0x00000009, 0x0400000d, 0x0401f015, - 0x820c0580, 0x00000005, 0x04000009, 0x0401f011, - 0x820c0580, 0x0000000b, 0x04000005, 0x0401f00d, - 0x820c0580, 0x00000003, 0x0402000a, 0x82081d00, - 0xffffff00, 0x840c01c0, 0x800c0540, 0x4813c857, - 0x480bc857, 0x4807c857, 0x4803c857, 0x48002400, - 0x1c01f000, 0x599c0017, 0x8c00050a, 0x04000003, - 0x80000580, 0x1c01f000, 0x59a80026, 0x82000500, - 0x00000028, 0x04000008, 0x42028800, 0x000007fd, - 0x0201f800, 0x00020245, 0x04020003, 0x5934000a, - 0x8c000504, 0x1c01f000, 0x4d300000, 0x5934000e, - 0x80026540, 0x04000006, 0x0201f800, 0x001062d5, - 0x02000800, 0x001064ad, 0x497a680e, 0x5c026000, - 0x1c01f000, 0x4d440000, 0x4d340000, 0x80000580, - 0x40001800, 0x40028800, 0x82080580, 0x00000008, - 0x04020003, 0x42001800, 0x00000001, 0x0201f800, - 0x00020245, 0x0402000a, 0x0401fd6d, 0x04020008, - 0x800c19c0, 0x04000004, 0x59340405, 0x8c000508, - 0x04000003, 0x80081040, 0x04000009, 0x81468800, - 0x83440480, 0x00000800, 0x040017f1, 0x80000580, - 0x5c026800, 0x5c028800, 0x1c01f000, 0x82000540, - 0x00000001, 0x5c026800, 0x5c028800, 0x1c01f000, - 0x4a033020, 0x00000000, 0x497b3026, 0x497b3027, + 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, 0x4803c856, - 0x599c0018, 0x497b3024, 0x497b3025, 0x82000500, - 0x0000000f, 0x82000d80, 0x00000005, 0x04000006, - 0x82000580, 0x00000006, 0x0400000d, 0x497b3022, - 0x1c01f000, 0x4a033022, 0x00000005, 0x599c0216, + 0x4a03b104, 0x60000001, 0x1c01f000, 0x599c0018, + 0x4803c856, 0x497b3024, 0x497b3025, 0x82000500, + 0x0000000f, 0x48033022, 0x04000008, 0x599c0216, 0x82000500, 0x0000ffff, 0x04020003, 0x42000000, - 0x00000002, 0x48033023, 0x1c01f000, 0x4a033022, - 0x00000006, 0x0401f7f6, 0x0401ffe5, 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, 0x59980022, 0x4803c856, - 0x80000540, 0x02000000, 0x000202de, 0x0401f017, - 0x42034000, 0x0010b4a4, 0x59a1d81e, 0x80edd9c0, - 0x02000800, 0x001005d8, 0x58ec0009, 0x48efc857, - 0x49a3c857, 0x492fc857, 0x4803c857, 0x800001c0, - 0x08020000, 0x0201f800, 0x001005d8, 0x5931d821, - 0x58ef400b, 0x58ec0009, 0x800001c0, 0x08020000, - 0x0201f800, 0x001005d8, 0x497a5800, 0x59980026, - 0x80000540, 0x0402008c, 0x59d80105, 0x82000d00, - 0x00018780, 0x040201da, 0x80000106, 0x82000500, - 0x00000003, 0x0c01f001, 0x00104d0a, 0x00104d89, - 0x00104d22, 0x00104d50, 0x592c0001, 0x492fc857, - 0x492fb107, 0x80000d40, 0x04020007, 0x59940019, - 0x80000540, 0x04022003, 0x59980023, 0x48032819, - 0x1c01f000, 0x497a5801, 0x40065800, 0x592c0001, - 0x496a5800, 0x815eb800, 0x412ed000, 0x80000d40, - 0x040207f9, 0x59c80000, 0x82000540, 0x00001200, - 0x48039000, 0x0401f7ee, 0x492fc857, 0x492fb107, - 0x592c0001, 0x80000d40, 0x04020012, 0x59da5908, - 0x835c0480, 0x00000020, 0x0400101c, 0x0402b01a, - 0x492fb007, 0x0400e7fa, 0x59d80105, 0x82000500, - 0x00018780, 0x040201aa, 0x59940019, 0x80000540, - 0x04022003, 0x59980023, 0x48032819, 0x1c01f000, - 0x497a5801, 0x40065800, 0x592c0001, 0x496a5800, - 0x815eb800, 0x412ed000, 0x80000d40, 0x040207f9, - 0x59c80000, 0x82000540, 0x00001200, 0x48039000, - 0x0401f7e3, 0x0400f009, 0x496a5800, 0x412ed000, - 0x815eb800, 0x59c80000, 0x82000540, 0x00001200, - 0x48039000, 0x0401f7e0, 0x492fa807, 0x0401f7de, - 0x492fc857, 0x59d81108, 0x45681000, 0x400ad000, - 0x815eb800, 0x0400e7fc, 0x59c80000, 0x82000540, - 0x00001200, 0x48039000, 0x0402d00c, 0x592c0001, - 0x492fc857, 0x492fb107, 0x80000d40, 0x0402001d, - 0x59940019, 0x80000540, 0x04022003, 0x59980023, - 0x48032819, 0x1c01f000, 0x59d80105, 0x82000500, - 0x00018780, 0x04020172, 0x42000000, 0x0010b855, - 0x0201f800, 0x0010aa47, 0x59980026, 0x59980828, + 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, 0x040007e5, - 0x497a5801, 0x40065800, 0x592c0001, 0x496a5800, - 0x815eb800, 0x412ed000, 0x80000d40, 0x040207f9, - 0x59c80000, 0x82000540, 0x00001200, 0x48039000, - 0x0401f7d8, 0x59980026, 0x59980828, 0x80000000, - 0x48033026, 0x492fc857, 0x800409c0, 0x492f3028, - 0x04000003, 0x492c0800, 0x0401f002, 0x492f3029, - 0x592c0001, 0x80000d40, 0x04020027, 0x0402d00e, - 0x59980029, 0x80025d40, 0x0400000f, 0x59980026, - 0x80000040, 0x48033026, 0x04020002, 0x48033028, - 0x592c0000, 0x48033029, 0x492fc857, 0x492fb107, - 0x0400d7f4, 0x42000000, 0x0010b855, 0x0201f800, - 0x0010aa47, 0x0402e00a, 0x59da5908, 0x496a5800, - 0x412ed000, 0x815eb800, 0x0400e7fc, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x59d80105, - 0x82000500, 0x00018780, 0x04020125, 0x59940019, - 0x80000540, 0x04022003, 0x59980023, 0x48032819, - 0x1c01f000, 0x497a5801, 0x40065800, 0x592c0001, - 0x496a5800, 0x815eb800, 0x412ed000, 0x80000d40, - 0x040207f9, 0x59c80000, 0x82000540, 0x00001200, - 0x48039000, 0x0401f7ce, 0x592c0204, 0x4803c856, - 0x04000008, 0x42034000, 0x0010b4a4, 0x59a1d81e, - 0x80edd9c0, 0x02000800, 0x001005d8, 0x0401f003, - 0x5931d821, 0x58ef400b, 0x58ec0009, 0x800001c0, - 0x08020000, 0x0201f800, 0x001005d8, 0x497a5801, - 0x40065800, 0x592c0001, 0x496a5800, 0x412ed000, - 0x815eb800, 0x80000d40, 0x040207f9, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x1c01f000, - 0x497a5801, 0x40065800, 0x592c0001, 0x496a5800, - 0x412ed000, 0x815eb800, 0x80000d40, 0x040207f9, - 0x59c80000, 0x82000540, 0x00001200, 0x48039000, - 0x0200e000, 0x000202fb, 0x0201f000, 0x00020302, - 0x5998002b, 0x84000540, 0x4803302b, 0x0201f000, - 0x0002035e, 0x42000000, 0x0010b855, 0x0201f800, - 0x0010aa47, 0x492fc857, 0x59980026, 0x59980828, - 0x80000000, 0x48033026, 0x800409c0, 0x492f3028, - 0x04000003, 0x492c0800, 0x0401f002, 0x492f3029, - 0x592c0001, 0x80000d40, 0x04020002, 0x1c01f000, - 0x497a5801, 0x40065800, 0x592c0001, 0x496a5800, - 0x412ed000, 0x815eb800, 0x80000d40, 0x040207f9, - 0x59c80000, 0x82000540, 0x00001200, 0x48039000, - 0x1c01f000, 0x59980026, 0x59980828, 0x80000000, - 0x48033026, 0x492fc857, 0x800409c0, 0x492f3028, - 0x04000003, 0x492c0800, 0x0401f002, 0x492f3029, - 0x592c0001, 0x80000d40, 0x04020039, 0x0402d00e, - 0x59980029, 0x80025d40, 0x0400000f, 0x59980026, - 0x80000040, 0x48033026, 0x04020002, 0x48033028, - 0x592c0000, 0x48033029, 0x492fc857, 0x492fb107, - 0x0400d7f4, 0x42000000, 0x0010b855, 0x0201f800, - 0x0010aa47, 0x0402e01d, 0x59da5908, 0x496a5800, - 0x412ed000, 0x815eb800, 0x0400e7fc, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x04006018, - 0x59d8010a, 0x59d8090a, 0x80040d80, 0x040207fd, - 0x900001c0, 0x82000540, 0x00000013, 0x4803c011, - 0x5998002b, 0x84000500, 0x4803302b, 0x59e00017, - 0x8c000508, 0x04000003, 0x4a03c017, 0x00000003, - 0x4203e000, 0x30000001, 0x59d80105, 0x82000500, - 0x00018780, 0x0402007e, 0x1c01f000, 0x5998002b, - 0x84000540, 0x4803302b, 0x0401f7f8, 0x497a5801, - 0x40065800, 0x592c0001, 0x496a5800, 0x412ed000, - 0x815eb800, 0x80000d40, 0x040207f9, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x0401f7bc, - 0x5c000000, 0x4c000000, 0x4803c857, 0x492fc857, - 0x4943c857, 0x4807c857, 0x4a025a04, 0x00000103, - 0x49425a06, 0x48065a08, 0x4a025c06, 0x0000ffff, - 0x813261c0, 0x04000003, 0x59300402, 0x48025c06, - 0x832c0400, 0x00000009, 0x04011000, 0x4803c840, - 0x4a03c842, 0x0000000b, 0x04011000, 0x1c01f000, - 0x4df00000, 0x4203e000, 0x50000000, 0x599cb817, - 0x59940019, 0x80000540, 0x04002023, 0x0400000e, - 0x59980022, 0x82000580, 0x00000005, 0x0400001e, - 0x59a80069, 0x81640580, 0x0402001b, 0x8c5cbd08, - 0x04000005, 0x59a8006a, 0x59a80866, 0x80040580, - 0x04020015, 0x8c5cbd08, 0x04020030, 0x59d8090b, - 0x59d8010a, 0x80040580, 0x0400000d, 0x0400600e, - 0x4a03c011, 0x80400012, 0x4a03c020, 0x00008040, - 0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017, - 0x00000002, 0x4203e000, 0x30000001, 0x4a032819, - 0xffff0000, 0x04026835, 0x04006003, 0x8c5cbd08, - 0x04020860, 0x59980029, 0x80025d40, 0x04000010, - 0x59d80105, 0x82000500, 0x00018780, 0x04020020, - 0x0402d00d, 0x59980026, 0x492fc857, 0x80000040, - 0x48033026, 0x592c0000, 0x492fb107, 0x48033029, - 0x04020003, 0x4803c856, 0x48033028, 0x5c03e000, - 0x1c01f000, 0x42000000, 0x0010b855, 0x0201f800, - 0x0010aa47, 0x0401f7fa, 0x59e0000f, 0x59e0080f, - 0x80040580, 0x040207fd, 0x59e00010, 0x59e01010, - 0x80081580, 0x040207fd, 0x40065000, 0x80041580, - 0x040007c7, 0x040067dc, 0x0401f7ca, 0x4803c857, - 0x485fc857, 0x8c00050e, 0x02020800, 0x001005d0, - 0x4203e000, 0x50000000, 0x4200b800, 0x00008004, - 0x0201f000, 0x001005dd, 0x5998002b, 0x8c000500, - 0x04000013, 0x84000500, 0x4803302b, 0x59d8010a, - 0x59d8090a, 0x80040580, 0x040207fd, 0x800408e0, - 0x82040d40, 0x00000013, 0x4807c011, 0x59e00017, - 0x8c000508, 0x04000003, 0x4a03c017, 0x00000003, - 0x4203e000, 0x30000001, 0x1c01f000, 0x0402e014, + 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, 0x59d8090b, 0x59980024, 0x48073024, - 0x80040480, 0x04020004, 0x59940019, 0x80000540, - 0x04022003, 0x59980823, 0x48072819, 0x59d80105, - 0x82000500, 0x00018780, 0x040207c9, 0x1c01f000, - 0x59981025, 0x59e00010, 0x59e00810, 0x80041d80, - 0x040207fd, 0x80080580, 0x04000013, 0x48073025, - 0x59e0000f, 0x59e0100f, 0x80081d80, 0x040207fd, - 0x81280580, 0x04000008, 0x400a5000, 0x40080000, - 0x80040580, 0x04000003, 0x59980823, 0x48072819, - 0x1c01f000, 0x59940019, 0x80000540, 0x040227f8, - 0x0401f7fc, 0x59e0000f, 0x59e0100f, 0x80081d80, - 0x040207fd, 0x81280580, 0x040007f6, 0x400a5000, - 0x59940019, 0x80000540, 0x040027ed, 0x0401f7f1, + 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, - 0x001005d8, 0x0c01f809, 0x4a038805, 0x000000f0, + 0x00100615, 0x0c01f809, 0x4a038805, 0x000000f0, 0x59c400a3, 0x82000500, 0x02870000, 0x02020800, - 0x001005d8, 0x1c01f000, 0x00104fc5, 0x00104f51, - 0x00104f6c, 0x00104f95, 0x00104fb8, 0x00104ff2, - 0x00105004, 0x00104f6c, 0x00104fd6, 0x00104f50, + 0x00100615, 0x1c01f000, 0x00104c99, 0x00104c25, + 0x00104c40, 0x00104c69, 0x00104c8c, 0x00104cc6, + 0x00104cd8, 0x00104c40, 0x00104caa, 0x00104c24, 0x1c01f000, 0x4a038808, 0x00000004, 0x0401f8f9, - 0x0201f800, 0x001053ab, 0x59c40805, 0x8c040d0e, + 0x0201f800, 0x0010507b, 0x59c40805, 0x8c040d0e, 0x04020013, 0x8c040d0a, 0x0402000b, 0x8c040d0c, 0x04020006, 0x8c040d08, 0x0400000d, 0x4a035017, 0x00000003, 0x0401f00a, 0x4a035017, 0x00000000, - 0x0401f007, 0x42000000, 0x0010b844, 0x0201f800, - 0x0010aa47, 0x4a035017, 0x00000002, 0x1c01f000, + 0x0401f007, 0x42000000, 0x0010b642, 0x0201f800, + 0x0010a86e, 0x4a035017, 0x00000002, 0x1c01f000, 0x4a038808, 0x00000002, 0x0401f8de, 0x59c40805, 0x8c040d08, 0x04020021, 0x8c040d0c, 0x0402001c, 0x8c040d0e, 0x04020017, 0x82040500, 0x000000f0, - 0x0402001c, 0x0201f800, 0x001053ab, 0x4a038808, + 0x0402001c, 0x0201f800, 0x0010507b, 0x4a038808, 0x00000080, 0x59c40002, 0x8400050c, 0x48038802, - 0x0401f9d9, 0x4d3c0000, 0x42027800, 0x00000001, - 0x0201f800, 0x00109874, 0x5c027800, 0x4a038808, + 0x0401f9d7, 0x4d3c0000, 0x42027800, 0x00000001, + 0x0201f800, 0x00109640, 0x5c027800, 0x4a038808, 0x00000080, 0x4a035017, 0x00000009, 0x0401f009, 0x4a035017, 0x00000001, 0x0401f006, 0x4a035017, 0x00000000, 0x0401f003, 0x4a035017, 0x00000003, @@ -5136,8 +4933,8 @@ uint32_t risc_code01[] = { 0x59c40805, 0x8c040d0a, 0x0402001b, 0x8c040d0c, 0x04020016, 0x8c040d0e, 0x04020011, 0x82040500, 0x000000f0, 0x04020016, 0x59c40002, 0x8400050c, - 0x48038802, 0x0401f9b4, 0x4d3c0000, 0x42027800, - 0x00000001, 0x0201f800, 0x00109874, 0x5c027800, + 0x48038802, 0x0401f9b2, 0x4d3c0000, 0x42027800, + 0x00000001, 0x0201f800, 0x00109640, 0x5c027800, 0x4a035017, 0x00000009, 0x0401f009, 0x4a035017, 0x00000001, 0x0401f006, 0x4a035017, 0x00000000, 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000, @@ -5149,12 +4946,12 @@ uint32_t risc_code01[] = { 0x8c040d0a, 0x04020006, 0x8c040d0e, 0x04000006, 0x4a035017, 0x00000001, 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000, 0x4a038808, 0x00000008, - 0x42001000, 0x00105058, 0x0201f800, 0x00106084, + 0x42001000, 0x00104d2c, 0x0201f800, 0x00105dbd, 0x59c40805, 0x8c040d0a, 0x0402000d, 0x8c040d08, 0x0402000b, 0x8c040d0c, 0x04020006, 0x8c040d0e, 0x0400000d, 0x4a035017, 0x00000001, 0x0401f00a, 0x4a035017, 0x00000000, 0x0401f007, 0x42000000, - 0x0010b844, 0x0201f800, 0x0010aa47, 0x4a035017, + 0x0010b642, 0x0201f800, 0x0010a86e, 0x4a035017, 0x00000004, 0x1c01f000, 0x0401f8a6, 0x0401f859, 0x59c40805, 0x8c040d0a, 0x0402000b, 0x8c040d0c, 0x04020006, 0x8c040d0e, 0x04000009, 0x4a035017, @@ -5166,243 +4963,242 @@ uint32_t risc_code01[] = { 0x4a035017, 0x00000001, 0x0401f009, 0x4a035017, 0x00000000, 0x0401f006, 0x4a035017, 0x00000003, 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000, - 0x0401f91f, 0x02020800, 0x001005d8, 0x59a80805, + 0x0401f91d, 0x02020800, 0x00100615, 0x59a80805, 0x8c040d0c, 0x04000015, 0x84040d0c, 0x48075005, - 0x4a038805, 0x00000010, 0x0201f800, 0x00101937, + 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, 0x0010b844, - 0x0201f800, 0x0010aa47, 0x4a035017, 0x00000008, - 0x0401f007, 0x42000000, 0x0010b844, 0x0201f800, - 0x0010aa47, 0x4a035017, 0x00000004, 0x1c01f000, + 0x00000005, 0x0402000c, 0x42000000, 0x0010b642, + 0x0201f800, 0x0010a86e, 0x4a035017, 0x00000008, + 0x0401f007, 0x42000000, 0x0010b642, 0x0201f800, + 0x0010a86e, 0x4a035017, 0x00000004, 0x1c01f000, 0x4803c856, 0x4c040000, 0x4c080000, 0x42000800, - 0x00000064, 0x42001000, 0x00105058, 0x0201f800, - 0x00106079, 0x5c001000, 0x5c000800, 0x1c01f000, - 0x4803c856, 0x4c040000, 0x0201f800, 0x00106c55, - 0x4df00000, 0x0201f800, 0x00106e21, 0x5c03e000, - 0x02000800, 0x00106c4b, 0x0401ffba, 0x5c000800, + 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, 0x00106c55, 0x4df00000, 0x0201f800, - 0x00106e21, 0x5c03e000, 0x02000800, 0x00106c4b, + 0x0201f800, 0x0010698c, 0x4df00000, 0x0201f800, + 0x00106b71, 0x5c03e000, 0x02000800, 0x00106982, 0x59c40006, 0x84000500, 0x48038806, 0x0201f800, - 0x00106ede, 0x497b8880, 0x0201f800, 0x0010a9c0, - 0x0201f800, 0x0010a9ce, 0x0201f800, 0x00101815, + 0x00106c32, 0x497b8880, 0x0201f800, 0x0010a7e7, + 0x0201f800, 0x0010a7f5, 0x0201f800, 0x00101886, 0x4a03504c, 0x00000004, 0x4202d800, 0x00000004, - 0x4a038805, 0x00000001, 0x42001000, 0x00105058, - 0x0201f800, 0x00106084, 0x0201f800, 0x001006d4, - 0x0401f8c1, 0x04000006, 0x42006000, 0xfeffffff, - 0x41786800, 0x0201f800, 0x0010427d, 0x0201f800, - 0x00100452, 0x42000000, 0x00000001, 0x0201f800, - 0x00101590, 0x5c001000, 0x5c000800, 0x1c01f000, + 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, - 0x0010608e, 0x1c01f000, 0x4c040000, 0x59a80833, + 0x00105dd2, 0x1c01f000, 0x4c040000, 0x59a80833, 0x82040580, 0x00000000, 0x0400000b, 0x82040580, 0x00000001, 0x0400000b, 0x82040580, 0x00000002, 0x0400000b, 0x82040580, 0x00000003, 0x0400000b, - 0x0401f057, 0x4a035017, 0x00000000, 0x0401f009, + 0x0401f055, 0x4a035017, 0x00000000, 0x0401f009, 0x4a035017, 0x00000004, 0x0401f006, 0x4a035017, 0x00000001, 0x0401f003, 0x4a035017, 0x00000007, 0x497b8880, 0x4a038893, 0x00000001, 0x41780000, - 0x0201f800, 0x00101606, 0x0201f800, 0x00106ede, + 0x0201f800, 0x00101670, 0x0201f800, 0x00106c32, 0x836c0d80, 0x00000004, 0x04000008, 0x59c40006, 0x82000500, 0xffffff0f, 0x82000540, 0x04000001, 0x48038806, 0x0401f007, 0x59c40006, 0x82000500, 0xffffff0f, 0x82000540, 0x04000000, 0x48038806, - 0x0401f875, 0x04020005, 0x59c40806, 0x82040d00, - 0xfbffff0f, 0x48078806, 0x4200b000, 0x00000005, - 0x59c40005, 0x8c000534, 0x04020033, 0x42006000, - 0xfc18ffff, 0x42006800, 0x01000000, 0x0201f800, - 0x0010427d, 0x0201f800, 0x00101937, 0x59c408a4, - 0x82040d00, 0x0000000f, 0x82040d80, 0x0000000c, - 0x0400000a, 0x42006000, 0xfeffffff, 0x42006800, - 0x02000000, 0x0201f800, 0x0010427d, 0x8058b040, - 0x040207e8, 0x0401f8a1, 0x0401f853, 0x04000006, - 0x42006000, 0xfeffffff, 0x41786800, 0x0201f800, - 0x0010427d, 0x836c0d80, 0x00000004, 0x04000006, - 0x59a8084d, 0x42001000, 0x00105065, 0x0201f800, - 0x0010606e, 0x4a035033, 0x00000004, 0x0401fe31, - 0x0401f841, 0x04020008, 0x59c408a4, 0x82040d00, - 0x0000000f, 0x82040580, 0x0000000c, 0x02020800, - 0x001005d8, 0x5c000800, 0x1c01f000, 0x4803c856, - 0x4c000000, 0x0201f800, 0x0010609e, 0x4a035010, - 0x00ffffff, 0x497b5032, 0x59a8002a, 0x82000500, - 0xffff0000, 0x4803502a, 0x497b8880, 0x497b8893, - 0x41780000, 0x0201f800, 0x00101606, 0x59c40001, - 0x82000500, 0xfffffcff, 0x48038801, 0x42006000, - 0xfc18ffff, 0x41786800, 0x0201f800, 0x0010427d, - 0x4a038808, 0x00000000, 0x5c000000, 0x800001c0, - 0x02020800, 0x0010411d, 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, 0x04000025, 0x599c1017, 0x4d3c0000, - 0x82000500, 0x00000011, 0x04000007, 0x42027800, - 0x00000400, 0x0201f800, 0x00103b25, 0x0402000a, - 0x0401f012, 0x42027800, 0x00000408, 0x0201f800, - 0x00103b25, 0x0400000d, 0x42003000, 0x00000003, - 0x0401f003, 0x42003000, 0x00000004, 0x42028000, - 0x0000000e, 0x0201f800, 0x0010a449, 0x599c1017, - 0x8c08150a, 0x04020007, 0x42028000, 0x00000004, - 0x0201f800, 0x00101fe5, 0x80000580, 0x0401f80d, - 0x5c027800, 0x0401f00a, 0x0201f800, 0x00103b25, - 0x04000007, 0x42028000, 0x0000000f, 0x42003000, - 0x00000001, 0x0201f800, 0x0010a449, 0x1c01f000, - 0x59a80005, 0x04000004, 0x82000540, 0x00000010, - 0x0401f003, 0x82000500, 0xffffffef, 0x48035005, - 0x4803c857, 0x1c01f000, 0x4803c856, 0x4c580000, - 0x42000000, 0x0010b8cb, 0x0201f800, 0x0010aa47, - 0x42000800, 0x0010c0f1, 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, - 0x001005d8, 0x59b800e5, 0x8c000538, 0x040207fb, - 0x4a0370e4, 0x00000200, 0x42006000, 0xffffffff, - 0x42006800, 0x80000000, 0x0201f800, 0x0010427d, - 0x4a038807, 0x00000001, 0x497b8807, 0x4a038808, - 0x00000010, 0x42006000, 0xfcf8ffff, 0x42006800, - 0x01000000, 0x0201f800, 0x0010427d, 0x5c001000, - 0x480b8801, 0x42000800, 0x0010c0f1, 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, + 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, 0x50040000, - 0x48001810, 0x80040800, 0x800c1800, 0x8058b040, + 0x41c41800, 0x4200b000, 0x00000020, 0x580c0010, + 0x44000800, 0x80040800, 0x800c1800, 0x8058b040, 0x040207fb, 0x497b8830, 0x4200b000, 0x00000040, - 0x50040000, 0x48038831, 0x80040800, 0x8058b040, + 0x59c40031, 0x44000800, 0x80040800, 0x8058b040, 0x040207fc, 0x497b88ac, 0x4200b000, 0x00000010, - 0x50040000, 0x480388ad, 0x80040800, 0x8058b040, - 0x040207fc, 0x497b8880, 0x41780000, 0x0201f800, - 0x00101606, 0x59c408a4, 0x82040d00, 0x0000000f, - 0x82040580, 0x0000000c, 0x02020800, 0x001005d8, - 0x4a038805, 0x04000000, 0x5c00b000, 0x1c01f000, - 0x4803c856, 0x4c580000, 0x4ce80000, 0x42000000, - 0x0010b845, 0x0201f800, 0x0010aa47, 0x59c41008, - 0x4c080000, 0x82080500, 0xffffff7f, 0x48038808, - 0x59c40004, 0x82000500, 0x00003e02, 0x04000005, - 0x4201d000, 0x00000014, 0x0201f800, 0x0010608e, - 0x59c40006, 0x82000500, 0xffffff0f, 0x48038806, - 0x4a038805, 0x00000010, 0x4a038808, 0x00000004, - 0x4200b000, 0x00000065, 0x59c40005, 0x8c000508, - 0x04020012, 0x4201d000, 0x000003e8, 0x0201f800, - 0x0010608e, 0x8058b040, 0x040207f8, 0x0201f800, - 0x00106ede, 0x4a038808, 0x00000008, 0x4a035033, - 0x00000001, 0x4202d800, 0x00000001, 0x82000540, - 0x00000001, 0x0401f030, 0x0201f800, 0x00100ae0, - 0x42000000, 0x0010b8a8, 0x0201f800, 0x0010aa47, - 0x0201f800, 0x00100ef4, 0x497b8880, 0x59a8002a, + 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, - 0x00101606, 0x5c000000, 0x48038880, 0x4a038808, - 0x00000000, 0x4200b000, 0x00000065, 0x4a038805, - 0x000000f0, 0x0201f800, 0x00101937, 0x42000800, - 0x000000f0, 0x59c40005, 0x80040d00, 0x04000008, - 0x4201d000, 0x000003e8, 0x0201f800, 0x0010608e, - 0x8058b040, 0x040207f2, 0x0401f7d1, 0x59c40006, - 0x82000540, 0x000000f0, 0x48038806, 0x59a8001e, - 0x80000540, 0x04020002, 0x80000000, 0x48038893, - 0x80000580, 0x5c001000, 0x4df00000, 0x0201f800, - 0x0010195d, 0x5c03e000, 0x480b8808, 0x5c01d000, - 0x5c00b000, 0x1c01f000, 0x4803c856, 0x4c580000, - 0x4ce80000, 0x59c41008, 0x82080500, 0xffffff7f, - 0x48038808, 0x4c080000, 0x59c40004, 0x82000500, - 0x00003e02, 0x04000005, 0x4201d000, 0x00000014, - 0x0201f800, 0x0010608e, 0x0201f800, 0x00100ae0, - 0x42000000, 0x0010b8a9, 0x0201f800, 0x0010aa47, - 0x0201f800, 0x00100ef4, 0x4a038808, 0x00000002, - 0x80000580, 0x48038880, 0x48038893, 0x0201f800, - 0x00101606, 0x4200b000, 0x00000384, 0x4a038805, - 0x000000f0, 0x0201f800, 0x00101937, 0x42000800, - 0x000000f0, 0x59c40005, 0x80040d00, 0x04000015, - 0x82000500, 0x000000d0, 0x04020012, 0x4201d000, - 0x00000067, 0x0201f800, 0x0010608e, 0x8058b040, - 0x040207ef, 0x0201f800, 0x00106ede, 0x4a038808, - 0x00000008, 0x4a035033, 0x00000001, 0x4202d800, - 0x00000001, 0x82000540, 0x00000001, 0x0401f010, + 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, 0x00101606, - 0x5c000000, 0x48038880, 0x80000580, 0x5c001000, - 0x4df00000, 0x0201f800, 0x0010195d, 0x5c03e000, - 0x480b8808, 0x5c01d000, 0x5c00b000, 0x1c01f000, - 0x4803c856, 0x59c40004, 0x82000500, 0x00003e02, - 0x0400000a, 0x0201f800, 0x00106ede, 0x4a038808, - 0x00000008, 0x4a035033, 0x00000001, 0x4202d800, - 0x00000001, 0x0401f052, 0x0201f800, 0x00100ae0, - 0x42000000, 0x0010b8aa, 0x0201f800, 0x0010aa47, - 0x0201f800, 0x00100ef4, 0x59c40006, 0x84000508, - 0x48038806, 0x4a038805, 0x00000010, 0x59a80805, - 0x84040d4c, 0x48075005, 0x42000800, 0x00000064, - 0x42001000, 0x00105058, 0x0201f800, 0x0010606e, - 0x4a038808, 0x00000000, 0x497b8880, 0x4a038805, - 0x000000f0, 0x0201f800, 0x00101937, 0x42000800, - 0x000000f0, 0x59c40005, 0x80040d00, 0x0400000e, - 0x82000500, 0x000000e0, 0x0402000b, 0x4201d000, - 0x000003e8, 0x0201f800, 0x0010608e, 0x0201f800, - 0x00105f48, 0x59940004, 0x80000540, 0x040207ec, - 0x0401f023, 0x4c080000, 0x42001000, 0x00105065, - 0x0201f800, 0x00105f90, 0x42001000, 0x00105058, - 0x0201f800, 0x00106084, 0x5c001000, 0x497b8880, - 0x59a8001e, 0x80000540, 0x04020002, 0x80000000, - 0x48038893, 0x59a8002a, 0x82000500, 0x0000ffff, - 0x4c000000, 0x0201f800, 0x00101606, 0x5c000000, - 0x48038880, 0x59a80805, 0x84040d0c, 0x48075005, - 0x59c40006, 0x84000548, 0x48038806, 0x0201f800, - 0x0010195d, 0x4a038808, 0x00000080, 0x1c01f000, - 0x4803c856, 0x4d400000, 0x4d3c0000, 0x0201f800, - 0x00106ede, 0x0201f800, 0x0010ab33, 0x04020025, - 0x599c1017, 0x59a80805, 0x8c040d00, 0x0402000c, - 0x8c08151a, 0x0400001f, 0x84040d42, 0x48075005, - 0x42028000, 0x00000004, 0x42027800, 0x0000000c, - 0x8c081508, 0x04020008, 0x0401f012, 0x42028000, - 0x00000004, 0x42027800, 0x00000004, 0x8c081508, + 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, 0x0010a446, + 0x42028800, 0x0000ffff, 0x0201f800, 0x0010a258, 0x5c028000, 0x599c0817, 0x8c040d0a, 0x04020005, - 0x4943c857, 0x493fc857, 0x0201f800, 0x00101fe5, - 0x497b8880, 0x4202d800, 0x00000001, 0x0401fcfb, + 0x4943c857, 0x493fc857, 0x0201f800, 0x00101d90, + 0x497b8880, 0x4202d800, 0x00000001, 0x0401fcff, 0x5c027800, 0x5c028000, 0x1c01f000, 0x0201f800, - 0x00100ae0, 0x42000000, 0x0010b8ab, 0x0201f800, - 0x0010aa47, 0x0201f800, 0x00100ef4, 0x42000000, - 0x00000001, 0x0201f800, 0x00101606, 0x4a038880, - 0x00000001, 0x0201f000, 0x0010195d, 0x4202e000, + 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, - 0x00105983, 0x4a03c825, 0x00000004, 0x4a03c827, + 0x00105667, 0x4a03c825, 0x00000004, 0x4a03c827, 0x00000004, 0x599c0409, 0x80000d40, 0x04000020, 0x599c0407, 0x80000540, 0x04000007, 0x800000cc, 0x599c100b, 0x80080400, 0x4803b000, 0x497bb002, @@ -5421,71 +5217,75 @@ uint32_t risc_code01[] = { 0x00000004, 0x4a03a804, 0x10000001, 0x59e00803, 0x82040d00, 0xfffffbff, 0x82040d40, 0x00008000, 0x4807c003, 0x800409c0, 0x04000007, 0x4202e000, - 0x00000001, 0x0200b800, 0x00020551, 0x0200f000, - 0x00020566, 0x1c01f000, 0x0201f800, 0x001005d8, + 0x00000001, 0x0200b800, 0x00020685, 0x0200f000, + 0x0002069a, 0x1c01f000, 0x0201f800, 0x00100615, 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, 0x59981005, 0x800811c0, 0x0400001e, 0x58080005, - 0x82000d00, 0x43018780, 0x02020000, 0x00105846, + 0x82000d00, 0x43018780, 0x02020000, 0x0010552a, 0x8c000508, 0x04000015, 0x580a5808, 0x592c0204, 0x497a5800, 0x497a5801, 0x82000500, 0x000000ff, 0x82000c80, 0x0000004b, 0x0402100b, 0x0c01f80f, 0x5c03e000, 0x83700580, 0x00000003, 0x040007e6, - 0x0200f800, 0x00020566, 0x0200b000, 0x00020551, + 0x0200f800, 0x0002069a, 0x0200b000, 0x00020685, 0x1c01f000, 0x0401f850, 0x5c03e000, 0x0401f7f9, - 0x0401f8de, 0x0401f7fd, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x001054a1, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105519, 0x00105491, 0x00105491, 0x001054a1, - 0x001054a1, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x492fc857, 0x42000000, 0x0010b85e, - 0x0201f800, 0x0010aa47, 0x42000000, 0x00000400, - 0x0401f019, 0x492fc857, 0x42000000, 0x0010b85d, - 0x0201f800, 0x0010aa47, 0x42000000, 0x00001000, - 0x0401f011, 0x492fc857, 0x42000000, 0x0010b85c, - 0x0201f800, 0x0010aa47, 0x42000000, 0x00002000, - 0x0401f009, 0x492fc857, 0x42000000, 0x0010b85f, - 0x0201f800, 0x0010aa47, 0x42000000, 0x00000800, + 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, 0x000202da, 0x592c0204, + 0x48025c04, 0x0201f000, 0x00020381, 0x592c0204, 0x492fc857, 0x80000110, 0x040007db, 0x80000040, - 0x04000025, 0x48033002, 0x492f3003, 0x492f3004, - 0x4a033008, 0x001054e5, 0x4202e000, 0x00000003, + 0x04000035, 0x48033002, 0x492f3003, 0x492f3004, + 0x4a033008, 0x001051c5, 0x4202e000, 0x00000003, 0x1c01f000, 0x592c0204, 0x492fc857, 0x80000110, - 0x040007cd, 0x80000040, 0x04000033, 0x48033002, - 0x492f3003, 0x492f3004, 0x4a033008, 0x00105501, - 0x4202e000, 0x00000003, 0x1c01f000, 0x0201f800, - 0x0010ab33, 0x02020000, 0x000204d9, 0x42028000, + 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, - 0x00104e70, 0x0201f800, 0x001091c6, 0x0201f000, - 0x000202da, 0x592c0a0a, 0x8c040d02, 0x04020016, + 0x00104bee, 0x0201f800, 0x00108f7d, 0x0201f000, + 0x00020381, 0x592c0a0a, 0x8c040d02, 0x04020016, 0x59a80021, 0x492fc857, 0x80000540, 0x0402000f, 0x592c0207, 0x80000540, 0x04000005, 0x0201f800, - 0x00104326, 0x04020004, 0x1c01f000, 0x42000000, + 0x00104156, 0x04020004, 0x1c01f000, 0x42000000, 0x00000000, 0x592c0a06, 0x48065c06, 0x48025a06, - 0x0201f000, 0x000202da, 0x42000000, 0x00000028, + 0x0201f000, 0x00020381, 0x42000000, 0x00000028, 0x0401f7f9, 0x42000800, 0x00000009, 0x0201f000, - 0x0010665b, 0x592c0208, 0x492fc857, 0x82000c80, - 0x0000199a, 0x040217a4, 0x592c0408, 0x80000540, - 0x040207a1, 0x59a80821, 0x800409c0, 0x04020009, - 0x592c0207, 0x80000540, 0x0400079b, 0x497a5a06, - 0x0201f800, 0x00104385, 0x04020004, 0x1c01f000, + 0x001063a9, 0x592c0208, 0x492fc857, 0x82000c80, + 0x0000199a, 0x04021794, 0x592c0408, 0x80000540, + 0x04020791, 0x59a80821, 0x800409c0, 0x04020009, + 0x592c0207, 0x80000540, 0x0400078b, 0x497a5a06, + 0x0201f800, 0x001041b5, 0x04020004, 0x1c01f000, 0x42000000, 0x00000028, 0x48025a06, 0x0201f000, - 0x000202da, 0x59980804, 0x59980002, 0x48065800, + 0x00020381, 0x59980804, 0x59980002, 0x48065800, 0x492c0801, 0x492f3004, 0x80000040, 0x48033002, 0x04000002, 0x1c01f000, 0x599a5803, 0x59980008, 0x4202e000, 0x00000001, 0x0801f000, 0x592e8a06, @@ -5493,69 +5293,70 @@ uint32_t risc_code01[] = { 0x4200b800, 0x00000001, 0x82000d80, 0x00000001, 0x04000015, 0x417a8800, 0x4200b800, 0x000007f0, 0x82000d80, 0x00000002, 0x0400000f, 0x80000540, - 0x02020000, 0x000202da, 0x592e8a06, 0x0201f800, - 0x00020245, 0x02020000, 0x000202da, 0x592e9008, - 0x592e9809, 0x0201f800, 0x00104713, 0x0201f000, - 0x000202da, 0x59a80805, 0x84040d00, 0x48075005, - 0x0201f800, 0x00020245, 0x02000800, 0x0010482c, + 0x02020000, 0x00020381, 0x592e8a06, 0x0201f800, + 0x00020267, 0x02020000, 0x00020381, 0x592e9008, + 0x592e9809, 0x0201f800, 0x00104567, 0x0201f000, + 0x00020381, 0x59a80805, 0x84040d00, 0x48075005, + 0x0201f800, 0x00020267, 0x02000800, 0x0010467a, 0x81468800, 0x805cb840, 0x040207fa, 0x0201f000, - 0x000202da, 0x592c0a08, 0x4807c857, 0x82040580, + 0x00020381, 0x592c0a08, 0x4807c857, 0x82040580, 0x0000000e, 0x04000045, 0x82040580, 0x00000046, 0x04000046, 0x82040580, 0x00000045, 0x04000020, 0x82040580, 0x00000029, 0x04000010, 0x82040580, 0x0000002a, 0x04000009, 0x82040580, 0x0000000f, - 0x040001fc, 0x82040580, 0x0000002e, 0x040001f9, - 0x4807c856, 0x0401f1f2, 0x59a80805, 0x84040d04, - 0x48075005, 0x0401f1f3, 0x592e8a06, 0x0201f800, - 0x00020245, 0x040201ef, 0x59340200, 0x84000518, + 0x04000200, 0x82040580, 0x0000002e, 0x040001fd, + 0x4807c856, 0x0401f1f6, 0x59a80805, 0x84040d04, + 0x48075005, 0x0401f1f7, 0x592e8a06, 0x0201f800, + 0x00020267, 0x040201f3, 0x59340200, 0x84000518, 0x48026a00, 0x592e6009, 0x4933c857, 0x83300580, - 0xffffffff, 0x0402002a, 0x0401f1e6, 0x592c1407, - 0x480bc857, 0x0201f800, 0x00109410, 0x411e6000, - 0x04020003, 0x4803c856, 0x0401f1d9, 0x592e3809, + 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, - 0x00020721, 0x0401f1c7, 0x59a80068, 0x84000510, - 0x48035068, 0x0401f1c3, 0x592c1207, 0x8c081500, - 0x040201c0, 0x592e8a06, 0x592e6009, 0x0201f800, - 0x0010941a, 0x04020003, 0x4803c856, 0x0401f1b4, + 0x00020855, 0x0401f1cb, 0x59a80068, 0x84000510, + 0x48035068, 0x0401f1c7, 0x592c1207, 0x8c081500, + 0x040201c4, 0x592e8a06, 0x592e6009, 0x0201f800, + 0x001091e3, 0x04020003, 0x4803c856, 0x0401f1b8, 0x59300c06, 0x82040580, 0x00000004, 0x04000003, - 0x4803c856, 0x0401f1ae, 0x59300a03, 0x82040580, - 0x00000007, 0x04000003, 0x4803c856, 0x0401f1a8, - 0x59300c03, 0x82040580, 0x00000001, 0x04000021, - 0x82040580, 0x00000003, 0x04000016, 0x82040580, - 0x00000006, 0x04000020, 0x82040580, 0x00000008, - 0x04000015, 0x82040580, 0x0000000a, 0x0400000a, + 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, 0x04020018, 0x42000800, 0x00000009, - 0x0401f013, 0x42000800, 0x00000005, 0x0401f010, - 0x417a7800, 0x0201f800, 0x0010203c, 0x4a026406, + 0x0000002e, 0x0402001c, 0x42000800, 0x00000009, + 0x0401f017, 0x59326809, 0x0201f800, 0x0010484b, + 0x04020015, 0x42000800, 0x00000005, 0x0401f010, + 0x417a7800, 0x0201f800, 0x00101de2, 0x4a026406, 0x00000001, 0x42000800, 0x00000003, 0x0401f008, - 0x417a7800, 0x0201f800, 0x0010203c, 0x4a026406, + 0x417a7800, 0x0201f800, 0x00101de2, 0x4a026406, 0x00000001, 0x42000800, 0x0000000b, 0x0201f800, - 0x00104571, 0x4a026203, 0x00000001, 0x0201f800, - 0x0010672b, 0x0401f17b, 0x40000800, 0x58040000, + 0x001043c7, 0x4a026203, 0x00000001, 0x0201f800, + 0x00106470, 0x0401f17b, 0x40000800, 0x58040000, 0x80000540, 0x040207fd, 0x492c0800, 0x1c01f000, 0x492fc857, 0x59300c06, 0x82040580, 0x00000006, - 0x04020094, 0x0201f800, 0x001049e7, 0x04020005, - 0x59340200, 0x8c00051a, 0x02000000, 0x00020533, + 0x04020094, 0x0201f800, 0x00104836, 0x04020005, + 0x59340200, 0x8c00051a, 0x02000000, 0x00020667, 0x59340200, 0x8c00050e, 0x0400008a, 0x59300203, 0x42027800, 0x00000001, 0x82000580, 0x00000007, - 0x02020000, 0x00020533, 0x4a026203, 0x00000002, - 0x0201f000, 0x00020533, 0x42028000, 0x00000002, + 0x02020000, 0x00020667, 0x4a026203, 0x00000002, + 0x0201f000, 0x00020667, 0x42028000, 0x00000002, 0x4a026206, 0x00000014, 0x4d2c0000, 0x0201f800, - 0x0010a1d1, 0x5c025800, 0x59300c06, 0x4807c857, + 0x00109fc0, 0x5c025800, 0x59300c06, 0x4807c857, 0x82040580, 0x00000007, 0x04020063, 0x492fc857, - 0x4a025a06, 0x00000001, 0x0201f000, 0x000202da, + 0x4a025a06, 0x00000001, 0x0201f000, 0x00020381, 0x592c240a, 0x492fc857, 0x4813c857, 0x8c10251c, 0x04020016, 0x8c10251a, 0x04000003, 0x8c10250a, 0x04000069, 0x59340a00, 0x8c040d0e, 0x04000003, - 0x8c10251e, 0x04000064, 0x0201f800, 0x0002075a, + 0x8c10251e, 0x04000064, 0x0201f800, 0x00020892, 0x0400006b, 0x592c240a, 0x49366009, 0x49325809, 0x4a026406, 0x00000006, 0x4a026203, 0x00000007, - 0x0201f000, 0x0002052f, 0x592c0a0c, 0x5934000f, + 0x0201f000, 0x00020663, 0x592c0a0c, 0x5934000f, 0x41784000, 0x80001540, 0x0400006d, 0x58080204, 0x82000500, 0x000000ff, 0x82000580, 0x00000012, 0x04020004, 0x5808020c, 0x80040580, 0x04000004, @@ -5564,104 +5365,104 @@ uint32_t risc_code01[] = { 0x80000540, 0x04020007, 0x48226810, 0x0401f005, 0x4802680f, 0x80000540, 0x04020002, 0x497a6810, 0x4d2c0000, 0x400a5800, 0x4a025a06, 0x00000002, - 0x0201f800, 0x000202da, 0x5c025800, 0x0401f7bc, + 0x0201f800, 0x00020381, 0x5c025800, 0x0401f7bc, 0x592c040a, 0x8c00051c, 0x04000016, 0x592c0206, 0x82000580, 0x0000ffff, 0x04020012, 0x592e6009, 0x83300580, 0xffffffff, 0x040007b1, 0x83300480, - 0x0010d1c0, 0x04001010, 0x59a8000b, 0x81300480, + 0x0010cfc0, 0x04001010, 0x59a8000b, 0x81300480, 0x0402100d, 0x59300008, 0x800001c0, 0x04020005, 0x59300203, 0x82000580, 0x00000007, 0x04000797, 0x492fc857, 0x4a025a06, 0x00000029, 0x0201f000, - 0x000202da, 0x492fc857, 0x4a025a06, 0x00000008, - 0x0201f000, 0x000202da, 0x492fc857, 0x4a025a06, - 0x00000045, 0x0201f000, 0x000202da, 0x492fc857, - 0x4a025a06, 0x0000002a, 0x0201f000, 0x000202da, + 0x00020381, 0x492fc857, 0x4a025a06, 0x00000008, + 0x0201f000, 0x00020381, 0x492fc857, 0x4a025a06, + 0x00000045, 0x0201f000, 0x00020381, 0x492fc857, + 0x4a025a06, 0x0000002a, 0x0201f000, 0x00020381, 0x492fc857, 0x4a025a06, 0x00000028, 0x0201f000, - 0x000202da, 0x492fc857, 0x4a025a06, 0x00000006, - 0x0201f000, 0x000202da, 0x492fc857, 0x4a025a06, - 0x0000000e, 0x0201f000, 0x000202da, 0x59340010, + 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, 0x0010d1c0, + 0x81640480, 0x0402176e, 0x42026000, 0x0010cfc0, 0x59300009, 0x81340580, 0x04020004, 0x59300202, 0x80040580, 0x04000759, 0x83326400, 0x00000024, 0x41580000, 0x81300480, 0x040017f6, 0x0401f760, 0x492fc857, 0x592c0407, 0x82000c80, 0x0000199a, - 0x040215f1, 0x592c0204, 0x80000112, 0x040205de, - 0x592e8a06, 0x0201f800, 0x00020245, 0x04020059, - 0x0201f800, 0x001049e7, 0x04020059, 0x592e780a, + 0x040215dd, 0x592c0204, 0x80000112, 0x040205ca, + 0x592e8a06, 0x0201f800, 0x00020267, 0x04020059, + 0x0201f800, 0x00104836, 0x04020059, 0x592e780a, 0x493fc857, 0x8d3e7d3e, 0x04020007, 0x59a80021, - 0x80000540, 0x0402004f, 0x0201f800, 0x00104838, - 0x040005dd, 0x833c1d00, 0x0000001f, 0x040005da, - 0x592c0207, 0x82000c80, 0x00001000, 0x040215d6, + 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, 0x040205c7, 0x0c01f001, - 0x001056e9, 0x001056ec, 0x001056f9, 0x001056fc, - 0x001056ff, 0x0201f800, 0x0010903e, 0x0401f01a, - 0x0201f800, 0x0010480b, 0x04000027, 0x80e9d1c0, - 0x02020800, 0x00105fae, 0x42028000, 0x00000005, - 0x417a9000, 0x417a9800, 0x0201f800, 0x0010904e, + 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, 0x001046c9, 0x02020800, - 0x0010907e, 0x04000010, 0x8d3e7d3e, 0x04020017, + 0x00000052, 0x0201f800, 0x0010451d, 0x02020800, + 0x00108e3b, 0x04000010, 0x8d3e7d3e, 0x04020017, 0x1c01f000, 0x58040002, 0x80000540, 0x04020007, - 0x4d3c0000, 0x40067800, 0x0201f800, 0x001047eb, + 0x4d3c0000, 0x40067800, 0x0201f800, 0x00104639, 0x5c027800, 0x040207cb, 0x4a025a06, 0x00000030, 0x0401f00d, 0x4a025a06, 0x0000002c, 0x0401f00a, 0x4a025a06, 0x00000028, 0x0401f007, 0x4a025a06, 0x00000029, 0x0401f004, 0x497a5c09, 0x4a025a06, 0x00000000, 0x4a025a04, 0x00000103, 0x0201f000, - 0x000202da, 0x492fc857, 0x592c0204, 0x80000110, - 0x80000040, 0x04000002, 0x0401f56f, 0x592c0207, + 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, 0x001043b4, 0x04020002, + 0x48025c08, 0x0201f800, 0x001041e4, 0x04020002, 0x1c01f000, 0x49425a06, 0x8058b1c0, 0x04000009, - 0x0201f800, 0x0010955f, 0x0401f80f, 0x44042800, + 0x0201f800, 0x00109328, 0x0401f80f, 0x44042800, 0x82580580, 0x00000002, 0x04020002, 0x48082801, - 0x0201f000, 0x000202da, 0x42028000, 0x00000031, + 0x0201f000, 0x00020381, 0x42028000, 0x00000031, 0x42000800, 0x00000001, 0x4200b000, 0x00000001, 0x0401f7ed, 0x592c0408, 0x80000118, 0x832c2c00, 0x00000009, 0x80142c00, 0x1c01f000, 0x492fc857, - 0x4a025a08, 0x00000006, 0x0201f000, 0x000202da, + 0x4a025a08, 0x00000006, 0x0201f000, 0x00020381, 0x492fc857, 0x4a025a08, 0x00000001, 0x0201f000, - 0x000202da, 0x492fc857, 0x592c040a, 0x82000500, - 0x00000003, 0x04000020, 0x0201f800, 0x0002075a, + 0x00020381, 0x492fc857, 0x592c040a, 0x82000500, + 0x00000003, 0x04000020, 0x0201f800, 0x00020892, 0x04000021, 0x592c0204, 0x492e6008, 0x82000500, 0x000000ff, 0x82000580, 0x00000045, 0x0400000e, - 0x592c000b, 0x0201f800, 0x00105c9a, 0x02000800, - 0x00020245, 0x04020018, 0x42027000, 0x00000041, + 0x592c000b, 0x0201f800, 0x001059b9, 0x02000800, + 0x00020267, 0x04020018, 0x42027000, 0x00000041, 0x49366009, 0x4a026406, 0x00000001, 0x0201f000, - 0x000207a1, 0x59300015, 0x8400055e, 0x48026015, - 0x42026800, 0x0010b524, 0x42027000, 0x00000040, + 0x000208d8, 0x59300015, 0x8400055e, 0x48026015, + 0x42026800, 0x0010b320, 0x42027000, 0x00000040, 0x0401f7f4, 0x4a025a06, 0x00000101, 0x0201f000, - 0x000202da, 0x4a025a06, 0x0000002c, 0x0201f000, - 0x000202da, 0x4a025a06, 0x00000028, 0x0201f800, - 0x000202da, 0x0201f000, 0x0002077d, 0x492fc857, - 0x0201f800, 0x001062e1, 0x0400000b, 0x592c0204, - 0x80000110, 0x80000040, 0x040204fb, 0x592c0c06, + 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, 0x000202da, 0x592c0c07, 0x800409c0, + 0x0201f000, 0x00020381, 0x592c0c07, 0x800409c0, 0x04000024, 0x82040480, 0x00000005, 0x04021021, - 0x4c040000, 0x80040800, 0x0201f800, 0x00106306, + 0x4c040000, 0x80040800, 0x0201f800, 0x0010603f, 0x5c001000, 0x04020018, 0x832c0400, 0x00000008, - 0x4000a000, 0x0201f800, 0x0010632f, 0x04020012, - 0x592c1207, 0x82cc0580, 0x0010b50e, 0x04020009, + 0x4000a000, 0x0201f800, 0x00106068, 0x04020012, + 0x592c1207, 0x82cc0580, 0x0010b30a, 0x04020009, 0x58c80c0b, 0x84040d00, 0x84040d02, 0x8c081500, 0x04000002, 0x84040d5e, 0x4805940b, 0x0401f001, 0x42000000, 0x00000000, 0x48025a06, 0x0201f000, - 0x000202da, 0x42000000, 0x00000103, 0x0401f7fb, + 0x00020381, 0x42000000, 0x00000103, 0x0401f7fb, 0x42000000, 0x00000102, 0x0401f7f8, 0x492fc857, 0x592e7c06, 0x833c0500, 0xfffffffe, 0x04020043, - 0x592c4007, 0x42026000, 0x0010d1c0, 0x41581800, + 0x592c4007, 0x42026000, 0x0010cfc0, 0x41581800, 0x400c0000, 0x81300480, 0x04021023, 0x59300203, 0x82000580, 0x00000000, 0x04000007, 0x59300008, 0x80000d40, 0x04000004, 0x58040005, 0x80200580, @@ -5669,79 +5470,79 @@ uint32_t risc_code01[] = { 0x58040204, 0x82000500, 0x000000ff, 0x82000d80, 0x00000053, 0x04000007, 0x82000d80, 0x00000048, 0x04000004, 0x82000580, 0x00000018, 0x04020023, - 0x4d2c0000, 0x0201f800, 0x00108be3, 0x5c025800, + 0x4d2c0000, 0x0201f800, 0x00108997, 0x5c025800, 0x0400001e, 0x4a025a06, 0x00000000, 0x0201f000, - 0x000202da, 0x592e8a06, 0x83440480, 0x000007f0, - 0x04021016, 0x83440400, 0x0010ac00, 0x50000000, + 0x00020381, 0x592e8a06, 0x83440480, 0x000007f0, + 0x04021016, 0x83440400, 0x0010aa00, 0x50000000, 0x80026d40, 0x04000011, 0x4d2c0000, 0x0201f800, - 0x001047cb, 0x0400000c, 0x42028000, 0x00000005, - 0x592c0a08, 0x0201f800, 0x00104e70, 0x0201f800, - 0x001091cc, 0x0201f800, 0x000202da, 0x5c025800, + 0x00104619, 0x0400000c, 0x42028000, 0x00000005, + 0x592c0a08, 0x0201f800, 0x00104bee, 0x0201f800, + 0x00108f83, 0x0201f800, 0x00020381, 0x5c025800, 0x0401f7e5, 0x5c025800, 0x4a025a06, 0x00000031, - 0x0201f000, 0x000202da, 0x492fc857, 0x4d2c0000, - 0x0201f800, 0x001007e4, 0x04000016, 0x492fc857, - 0x412f4000, 0x0201f800, 0x001007e4, 0x0400000e, - 0x492fc857, 0x412dd800, 0x0201f800, 0x00103b28, - 0x0201f800, 0x00103b32, 0x49a1d80b, 0x5c025800, - 0x492dd80a, 0x0201f800, 0x00102214, 0x0201f000, - 0x00102233, 0x41a25800, 0x0201f800, 0x001007f4, + 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, 0x000202da, 0x4807c857, + 0x00000002, 0x0201f000, 0x00020381, 0x4807c857, 0x485fc857, 0x4200b800, 0x00000001, 0x5c000800, 0x4c5c0000, 0x0401f005, 0x4807c857, 0x485fc857, 0x5c000800, 0x4d780000, 0x4803c857, 0x492fc857, - 0x8c00050e, 0x02020800, 0x001005d0, 0x4203e000, + 0x8c00050e, 0x02020800, 0x0010060d, 0x4203e000, 0x50000000, 0x4200b800, 0x00008003, 0x0201f000, - 0x001005dd, 0x592c0204, 0x80000110, 0x80000040, - 0x04020441, 0x0201f800, 0x00104a34, 0x04020002, + 0x0010061a, 0x592c0204, 0x80000110, 0x80000040, + 0x0402042d, 0x0201f800, 0x00104886, 0x04020002, 0x1c01f000, 0x49425a06, 0x4806580d, 0x480a580e, 0x4943c857, 0x4807c857, 0x480bc857, 0x0201f000, - 0x000202da, 0x592c0204, 0x80000110, 0x80000040, - 0x04020431, 0x0201f800, 0x00104b8b, 0x04020002, + 0x00020381, 0x592c0204, 0x80000110, 0x80000040, + 0x0402041d, 0x0201f800, 0x001049ec, 0x04020002, 0x1c01f000, 0x49425a06, 0x48065811, 0x480a5812, - 0x0201f000, 0x000202da, 0x592c0204, 0x80000110, - 0x04000425, 0x80000040, 0x0402000c, 0x4202e000, + 0x0201f000, 0x00020381, 0x592c0204, 0x80000110, + 0x04000411, 0x80000040, 0x0402000c, 0x4202e000, 0x00000001, 0x592c020a, 0x8c000504, 0x02000000, - 0x000204d0, 0x592c0207, 0x82000c80, 0x00001001, - 0x04021429, 0x0401f009, 0x4202e000, 0x00000003, + 0x00020603, 0x592c0207, 0x82000c80, 0x00001001, + 0x04021415, 0x0401f009, 0x4202e000, 0x00000003, 0x48033002, 0x492f3003, 0x492f3004, 0x4a033008, - 0x000204d0, 0x1c01f000, 0x4202e000, 0x00000002, - 0x42000000, 0x0010beda, 0x50007000, 0x492c700b, + 0x00020603, 0x1c01f000, 0x4202e000, 0x00000002, + 0x42000000, 0x0010bcd9, 0x50007000, 0x492c700b, 0x4978700e, 0x4978700c, 0x592c0011, 0x592c0812, 0x48007007, 0x48047008, 0x592c1013, 0x82080500, - 0xffff0000, 0x04000003, 0x0201f800, 0x001005d8, + 0xffff0000, 0x04000003, 0x0201f800, 0x00100615, 0x4978700d, 0x82080480, 0x00000180, 0x4803c857, 0x04001007, 0x4800700f, 0x4a007005, 0x00000180, 0x4a007004, 0x00000060, 0x0401f005, 0x4978700f, 0x48087005, 0x80081104, 0x48087004, 0x5838000a, - 0x48007003, 0x40381000, 0x0201f000, 0x00100858, - 0x0201f800, 0x001007d3, 0x04000003, 0x59980007, + 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, 0x000202c1, 0x0401f005, 0x4a025a06, - 0x00000010, 0x0201f800, 0x000202da, 0x5c007000, + 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, 0x0010ab17, 0x5c007000, + 0x4c380000, 0x0201f800, 0x0010a93e, 0x5c007000, 0x5838000d, 0x82000400, 0x00000003, 0x4800700d, 0x4a007010, 0x00000001, 0x58380004, 0x82000480, 0x00000003, 0x48007004, 0x82000580, 0x00000003, 0x0400006c, 0x5838000e, 0x80001d40, 0x04020020, - 0x4c380000, 0x0201f800, 0x001007d3, 0x5c007000, + 0x4c380000, 0x0201f800, 0x00100819, 0x5c007000, 0x04000010, 0x4a025a04, 0x0000010a, 0x42001800, 0x00000005, 0x480c700e, 0x5838000c, 0x80000540, 0x04020002, 0x5838000b, 0x40000800, 0x492c0801, 0x492c700c, 0x42000800, 0x0000000f, 0x0401f011, - 0x4202e000, 0x00000008, 0x4a033007, 0x00105915, + 0x4202e000, 0x00000008, 0x4a033007, 0x001055f9, 0x1c01f000, 0x4202e000, 0x00000002, 0x42000000, - 0x0010beda, 0x50007000, 0x0401f7e7, 0x583a580c, + 0x0010bcd9, 0x50007000, 0x0401f7e7, 0x583a580c, 0x400c0000, 0x42000800, 0x00000014, 0x80040c80, 0x58381004, 0x5838000f, 0x41783000, 0x80000540, 0x04020005, 0x84183540, 0x82081480, 0x00000003, @@ -5749,7 +5550,7 @@ uint32_t risc_code01[] = { 0x40080800, 0x4004b000, 0x412c0000, 0x800c0400, 0x4000a800, 0x5838000a, 0x5838100d, 0x8008a400, 0x4c080000, 0x4c040000, 0x4c0c0000, 0x4c380000, - 0x0201f800, 0x0010ab17, 0x5c007000, 0x5c001800, + 0x0201f800, 0x0010a93e, 0x5c007000, 0x5c001800, 0x5c000800, 0x40040000, 0x58381004, 0x80080480, 0x48007004, 0x82000580, 0x00000003, 0x04000002, 0x84183500, 0x5c000000, 0x80041400, 0x82080480, @@ -5757,659 +5558,680 @@ uint32_t risc_code01[] = { 0x400c0000, 0x80041c00, 0x820c0480, 0x00000014, 0x04020003, 0x84183544, 0x40001800, 0x40080800, 0x4804700d, 0x480c700e, 0x40180000, 0x0c01f001, - 0x00105960, 0x00105964, 0x00105962, 0x00105960, - 0x001058fc, 0x00105964, 0x00105962, 0x00105960, - 0x0201f800, 0x001005d8, 0x5838100f, 0x0401f739, + 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, 0x00020507, - 0x0201f000, 0x000204d0, 0x5838000a, 0x80040c00, + 0x82000580, 0x00000012, 0x02000000, 0x0002063b, + 0x0201f000, 0x00020603, 0x5838000a, 0x80040c00, 0x82381c00, 0x00000007, 0x54041800, 0x80040800, 0x800c1800, 0x54041800, 0x0401f71a, 0x0201f800, - 0x001007d3, 0x02000800, 0x001005d8, 0x4a02580a, - 0x0010be79, 0x42000800, 0x0010beda, 0x452c0800, + 0x00100819, 0x02000800, 0x00100615, 0x4a02580a, + 0x0010bc78, 0x42000800, 0x0010bcd9, 0x452c0800, 0x497a580b, 0x497a580c, 0x497a580d, 0x497a580e, - 0x497a580f, 0x4a025809, 0x001058b6, 0x497a5810, + 0x497a580f, 0x4a025809, 0x0010559a, 0x497a5810, 0x4a025802, 0x00000100, 0x4a025801, 0x00000001, - 0x1c01f000, 0x59c80007, 0x8c000502, 0x04000070, - 0x835c2c80, 0x00000005, 0x02001000, 0x00105f23, - 0x59c82817, 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, 0x82140500, 0x0e000000, - 0x80000132, 0x0c01f840, 0x4a039005, 0x00000140, - 0x1c01f000, 0x59cc0400, 0x82000500, 0x0000ff00, - 0x82000580, 0x00008100, 0x040007f4, 0x0401f01c, - 0x4817c857, 0x82140500, 0x000003ff, 0x04020007, - 0x59cc0400, 0x82000500, 0x0000ff00, 0x82000580, - 0x00008100, 0x04020012, 0x42000000, 0x0010b8bd, - 0x0201f800, 0x0010aa47, 0x0201f800, 0x00105dfa, - 0x4803c856, 0x4a039005, 0x00000140, 0x0401f020, - 0x4817c857, 0x82140500, 0x00f60000, 0x04020004, - 0x0201f800, 0x00105e35, 0x040207d2, 0x0201f800, - 0x0010513b, 0x04000010, 0x59c400a4, 0x4803c857, - 0x82000500, 0x0000000f, 0x82000580, 0x0000000a, - 0x04020009, 0x497b5016, 0x59c400a3, 0x82000540, - 0x00080000, 0x480388a3, 0x82000500, 0xfff7ffff, - 0x480388a3, 0x4817c856, 0x0201f800, 0x0010a978, - 0x4a039005, 0x00000140, 0x0401f842, 0x4803c856, - 0x1c01f000, 0x00105a1d, 0x00105cf4, 0x00105a15, - 0x00105a15, 0x00105a15, 0x00105a15, 0x00105a15, - 0x00105a15, 0x4803c857, 0x42000000, 0x0010b85a, - 0x0201f800, 0x0010aa47, 0x4a039005, 0x00000140, - 0x1c01f000, 0x4817c857, 0x59cc0400, 0x4803c857, - 0x82000d00, 0x0000ff00, 0x82041500, 0x0000f000, - 0x840409c0, 0x82140500, 0x000003ff, 0x800018c4, - 0x8c142d14, 0x04000005, 0x59cc0002, 0x82000500, - 0x00000003, 0x800c1c80, 0x480f5016, 0x82080580, - 0x00002000, 0x04020011, 0x836c0580, 0x00000001, - 0x0402000c, 0x59cc0006, 0x82000500, 0xff000000, - 0x82000580, 0x11000000, 0x04020011, 0x0201f800, - 0x00103b38, 0x0201f800, 0x00105f48, 0x0401f00c, - 0x0401f81f, 0x0401f00a, 0x82080580, 0x00003000, - 0x04020003, 0x0401fa06, 0x0401f005, 0x82080580, - 0x00008000, 0x04020002, 0x0401fafc, 0x1c01f000, - 0x4817c857, 0x42000000, 0x0010b859, 0x0201f800, - 0x0010aa47, 0x836c0580, 0x00000003, 0x0402000b, - 0x4c080000, 0x4c0c0000, 0x42001000, 0x00008048, - 0x40141800, 0x80142120, 0x0201f800, 0x00103a3e, - 0x5c001800, 0x5c001000, 0x1c01f000, 0x4807c857, + 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, 0x04000004, 0x82001580, 0x23000000, - 0x04020192, 0x82040580, 0x00000023, 0x0402003f, - 0x0401fb6a, 0x0400018d, 0x59300c06, 0x82040580, - 0x00000010, 0x04000013, 0x82040580, 0x00000011, - 0x04000010, 0x82040580, 0x00000001, 0x0400000d, - 0x82040580, 0x00000004, 0x0400000a, 0x82040580, - 0x00000008, 0x04000007, 0x82040580, 0x0000000a, - 0x04000004, 0x4933c857, 0x4807c857, 0x0401f177, - 0x59300004, 0x82000500, 0x80010000, 0x04000004, - 0x0201f800, 0x00106f60, 0x04020170, 0x59cc0a04, - 0x48066202, 0x59cc0006, 0x82000500, 0xffff0000, + 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, 0x000207a1, 0x82000d80, + 0x00000015, 0x0201f000, 0x000208d8, 0x82000d80, 0x02140000, 0x040007fa, 0x82000d80, 0x02100000, 0x040007f7, 0x82000d80, 0x02100000, 0x040007f4, - 0x82000d80, 0x01000000, 0x04020158, 0x59cc0006, - 0x82000500, 0x0000ffff, 0x04020154, 0x42027000, - 0x00000016, 0x0401f7ec, 0x82040580, 0x00000022, - 0x0402014e, 0x59a80806, 0x8c040d14, 0x04000011, - 0x0401f967, 0x0402000f, 0x0401f97d, 0x0400000d, - 0x42027000, 0x0000004c, 0x59cc0001, 0x82000500, - 0x00ffffff, 0x0201f800, 0x00105eec, 0x0400012a, - 0x42028800, 0x0000ffff, 0x417a6800, 0x0401f126, + 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, - 0x03000000, 0x04020021, 0x59a80026, 0x8c000508, - 0x04000017, 0x8400054c, 0x48035026, 0x59cc0800, - 0x82040d00, 0x00ffffff, 0x48075010, 0x497b8830, - 0x84040d70, 0x48078832, 0x59c40802, 0x84040d4c, - 0x48078802, 0x59cc0007, 0x82000500, 0x0000ffff, - 0x48038893, 0x4803501e, 0x42000800, 0x00000003, - 0x59a81010, 0x0201f800, 0x00106c78, 0x59cc0006, - 0x82000500, 0x0000ffff, 0x04020118, 0x42027000, - 0x00000017, 0x0401f0d9, 0x82000d80, 0x04000000, - 0x04020011, 0x59cc0006, 0x82000500, 0x0000ffff, - 0x0402010e, 0x0201f800, 0x0010513b, 0x04000004, - 0x42027000, 0x0000001d, 0x0401f0cc, 0x59a80026, - 0x84000548, 0x48035026, 0x42027000, 0x00000030, - 0x0401f0c6, 0x82000d80, 0x05000000, 0x04020008, - 0x59cc0006, 0x82000500, 0x0000ffff, 0x040200fb, - 0x42027000, 0x00000018, 0x0401f0bc, 0x82000d80, - 0x20100000, 0x04020004, 0x42027000, 0x00000019, - 0x0401f0b6, 0x82000d80, 0x21100000, 0x04020004, - 0x42027000, 0x0000001a, 0x0401f0b0, 0x82000d80, - 0x52000000, 0x04020008, 0x59cc0006, 0x82000500, - 0x0000ffff, 0x040200e5, 0x42027000, 0x0000001b, - 0x0401f0a6, 0x82000d80, 0x50000000, 0x04020008, - 0x59cc0006, 0x82000500, 0x0000ffff, 0x040200db, - 0x42027000, 0x0000001c, 0x0401f09c, 0x82000d80, - 0x13000000, 0x04020004, 0x42027000, 0x00000034, - 0x0401f096, 0x82000d80, 0x12000000, 0x04020008, - 0x59cc0006, 0x82000500, 0x0000ffff, 0x040200cb, - 0x42027000, 0x00000024, 0x0401f08c, 0x82000d00, - 0xff000000, 0x82040d80, 0x24000000, 0x04020004, - 0x42027000, 0x0000002d, 0x0401f084, 0x82000d00, - 0xff000000, 0x82040d80, 0x53000000, 0x04020004, - 0x42027000, 0x0000002a, 0x0401f07c, 0x82000d80, - 0x0f000000, 0x04020004, 0x42027000, 0x00000020, - 0x0401f076, 0x82000d80, 0x61040000, 0x04020036, - 0x83cc1400, 0x00000006, 0x80080800, 0x50080000, - 0x82000500, 0x0000ffff, 0x82000480, 0x00000004, - 0x4c580000, 0x8000b104, 0x8058b1c0, 0x04000026, - 0x4c100000, 0x50041800, 0x820c1500, 0x03000000, - 0x80081130, 0x42000000, 0x0010b817, 0x82082580, - 0x00000000, 0x04020004, 0x42000000, 0x0010b814, - 0x0401f00c, 0x82082580, 0x00000001, 0x04020004, - 0x42000000, 0x0010b815, 0x0401f006, 0x82082580, - 0x00000002, 0x04020003, 0x42000000, 0x0010b816, - 0x0201f800, 0x0010aa47, 0x42001000, 0x00008015, - 0x820c2500, 0x0000ffff, 0x800c1920, 0x0201f800, - 0x00103a3e, 0x5c002000, 0x80040800, 0x8058b040, - 0x040207da, 0x5c00b000, 0x42027000, 0x00000023, - 0x0401f03e, 0x82000d80, 0x60000000, 0x04020004, - 0x42027000, 0x0000003f, 0x0401f038, 0x82000d80, - 0x54000000, 0x04020006, 0x0401fb12, 0x0402006f, - 0x42027000, 0x00000046, 0x0401f030, 0x82000d80, - 0x55000000, 0x04020009, 0x0401fb32, 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, - 0x0401f003, 0x0401f8d1, 0x04020030, 0x0201f800, - 0x001045a6, 0x0402002d, 0x83380580, 0x00000046, - 0x04020004, 0x59a80010, 0x80180580, 0x04000027, - 0x59340200, 0x8c000514, 0x0400000f, 0x83380580, - 0x00000030, 0x0400000c, 0x83380580, 0x0000003f, - 0x04000009, 0x83380580, 0x00000034, 0x04000006, - 0x83380580, 0x00000024, 0x04000003, 0x42027000, - 0x0000004c, 0x0201f800, 0x0002075a, 0x04000018, - 0x49366009, 0x4a026406, 0x00000004, 0x59cc0c04, - 0x48066202, 0x83380580, 0x0000004c, 0x04020009, - 0x4a026406, 0x00000011, 0x813669c0, 0x04020005, - 0x59cc0001, 0x82000500, 0x00ffffff, 0x4802601e, - 0x0201f000, 0x000207a1, 0x59880052, 0x4803c857, - 0x80000000, 0x48031052, 0x1c01f000, 0x42001000, - 0x00008049, 0x59cc1806, 0x800c1930, 0x0201f800, - 0x00103a3e, 0x0201f800, 0x00107942, 0x040007f3, - 0x49366009, 0x4a026406, 0x00000004, 0x59cc0c04, - 0x48066202, 0x4a026403, 0x00000009, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00002900, 0x4a026203, - 0x00000001, 0x0201f000, 0x0010672b, 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, 0x0010b4e3, 0x500c1800, 0x800c0500, - 0x4803c857, 0x1c01f000, 0x40100800, 0x41781800, - 0x82040480, 0x00000020, 0x04001004, 0x800c1800, - 0x40000800, 0x0401f7fb, 0x82040500, 0x0000000f, - 0x82000400, 0x0010ab38, 0x50000000, 0x8c040d08, - 0x04000002, 0x900001c0, 0x1c01f000, 0x4803c856, - 0x0401fac3, 0x0402000a, 0x0201f800, 0x0010210a, - 0x04020007, 0x59cc0002, 0x82000500, 0xff000000, - 0x82000d80, 0x08000000, 0x04000802, 0x1c01f000, - 0x4803c856, 0x59cc0400, 0x82000d00, 0x0000ff00, - 0x840409c0, 0x82040580, 0x00000033, 0x0402001f, - 0x0401f976, 0x04000038, 0x59cc0a04, 0x48066202, - 0x59cc0006, 0x4803c857, 0x82000500, 0xffff0000, - 0x82000d80, 0x02000000, 0x04020009, 0x59cc0006, - 0x82000500, 0x0000ffff, 0x0402002b, 0x42027000, - 0x00000015, 0x0201f000, 0x000207a1, 0x82000d80, - 0x01000000, 0x04020024, 0x59cc0006, 0x82000500, - 0x0000ffff, 0x04020020, 0x42027000, 0x00000016, - 0x0201f000, 0x000207a1, 0x82040580, 0x00000032, - 0x04020019, 0x59cc0006, 0x82000500, 0xffff0000, - 0x82000d80, 0x14000000, 0x04020013, 0x42027000, - 0x00000038, 0x59cc0001, 0x0401f810, 0x0402000e, - 0x0201f800, 0x001045a6, 0x0402000b, 0x0201f800, - 0x0002075a, 0x04000008, 0x49366009, 0x4a026406, - 0x00000004, 0x59cc0c04, 0x48066202, 0x0201f000, - 0x000207a1, 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, 0x00105d0f, - 0x00105d0f, 0x00105d0f, 0x00105de5, 0x00105d0f, - 0x00105d11, 0x00105d29, 0x00105d2c, 0x00105d0f, - 0x00105d0f, 0x00105d0f, 0x00105d0f, 0x00105d0f, - 0x00105d0f, 0x00105d0f, 0x00105d0f, 0x4803c856, - 0x1c01f000, 0x0401f8c5, 0x04000014, 0x82140500, - 0x000003ff, 0x800000c4, 0x82000480, 0x00000008, - 0x0400100e, 0x59cc0001, 0x59326809, 0x59340802, - 0x80040580, 0x82000500, 0x00ffffff, 0x04020007, - 0x59cc0a04, 0x48066202, 0x42027000, 0x00000046, - 0x0201f000, 0x000207a1, 0x59cc0004, 0x4803c857, - 0x1c01f000, 0x59cc0004, 0x4803c857, 0x1c01f000, - 0x0401f8aa, 0x04000016, 0x82140500, 0x000003ff, - 0x800000c4, 0x82000480, 0x0000000c, 0x04001010, - 0x59cc0001, 0x82000500, 0x00ffffff, 0x59326809, - 0x59340802, 0x82040d00, 0x00ffffff, 0x80040580, - 0x04020007, 0x59cc0a04, 0x48066202, 0x42027000, - 0x00000045, 0x0201f000, 0x000207a1, 0x59cc0004, - 0x4803c857, 0x1c01f000, 0x4817c857, 0x0401f9c8, - 0x04020011, 0x0201f800, 0x0010210a, 0x0402000e, - 0x59cc0002, 0x82000500, 0xff000000, 0x82000580, - 0x00000000, 0x04020008, 0x82040500, 0x0000000f, - 0x82000c80, 0x00000006, 0x04021003, 0x4803c857, - 0x0c01f002, 0x1c01f000, 0x00105d60, 0x00105d64, - 0x00105d60, 0x00105d60, 0x00105db2, 0x00105dc3, - 0x4803c857, 0x59cc0004, 0x4803c857, 0x1c01f000, - 0x59cc0004, 0x4803c857, 0x59a80016, 0x800001c0, - 0x040207f8, 0x59cc0802, 0x8c040d2e, 0x0402001d, - 0x0201f800, 0x00107942, 0x02000800, 0x001005d8, - 0x59cc0001, 0x4803c857, 0x0401ff28, 0x0402000d, - 0x0201f800, 0x00020245, 0x0402000a, 0x4a026406, - 0x00000005, 0x49366009, 0x59cc0c04, 0x48066202, - 0x42027000, 0x00000088, 0x0201f000, 0x000207a1, + 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, 0x0401f7f0, - 0x59cc0001, 0x4803c857, 0x0401ff10, 0x040207d5, - 0x0201f800, 0x001045a6, 0x040207d2, 0x59cc0005, - 0x8c000500, 0x04020004, 0x59340200, 0x8c00050e, - 0x040207cc, 0x0201f800, 0x001049f3, 0x0402000f, - 0x0401f83e, 0x040007c7, 0x0201f800, 0x0002075a, - 0x040007c4, 0x49366009, 0x4a026406, 0x00000002, - 0x59cc0c04, 0x48066202, 0x42027000, 0x00000088, - 0x0201f000, 0x000207a1, 0x0201f800, 0x0002075a, - 0x040007b8, 0x49366009, 0x4a026406, 0x00000004, - 0x59cc0c04, 0x48066202, 0x42027000, 0x00000001, - 0x0201f000, 0x000207a1, 0x59cc0004, 0x4803c857, + 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, 0x0401f960, 0x04020007, 0x59cc0a04, + 0x04000009, 0x0401f961, 0x04020007, 0x59cc0a04, 0x48066202, 0x42027000, 0x00000089, 0x0201f000, - 0x000207a1, 0x4933c857, 0x1c01f000, 0x59cc0004, + 0x000208d8, 0x4933c857, 0x1c01f000, 0x59cc0004, 0x4803c857, 0x59cc0802, 0x8c040d2e, 0x0400000b, - 0x0401f80e, 0x04000009, 0x0401f94f, 0x04020007, + 0x0401f80e, 0x04000009, 0x0401f950, 0x04020007, 0x59cc0a04, 0x48066202, 0x42027000, 0x0000008a, - 0x0201f000, 0x000207a1, 0x4933c857, 0x1c01f000, + 0x0201f000, 0x000208d8, 0x4933c857, 0x1c01f000, 0x59cc0a04, 0x0401f002, 0x59cc0c04, 0x59a8000e, 0x59a81067, 0x80080400, 0x80040480, 0x04021008, 0x40040000, 0x800000c4, 0x800408ca, 0x80040c00, - 0x82066400, 0x0010d1c0, 0x1c01f000, 0x80000580, + 0x82066400, 0x0010cfc0, 0x1c01f000, 0x80000580, 0x0401f7fe, 0x59cc0802, 0x8c040d2e, 0x04020010, 0x0401ffec, 0x0400000e, 0x59cc0001, 0x82000500, 0x00ffffff, 0x59326809, 0x59340802, 0x82040d00, 0x00ffffff, 0x80040580, 0x04020005, 0x42027000, - 0x00000051, 0x0201f000, 0x000207a1, 0x59cc0004, + 0x00000051, 0x0201f000, 0x000208d8, 0x59cc0004, 0x4803c857, 0x1c01f000, 0x4803c856, 0x42003000, 0x00000105, 0x0401f001, 0x4803c856, 0x4c3c0000, - 0x41cc7800, 0x0401f803, 0x5c007800, 0x1c01f000, - 0x4803c856, 0x4c580000, 0x583c0400, 0x82000500, - 0x0000f000, 0x82000580, 0x0000c000, 0x04000024, - 0x0201f800, 0x0002075a, 0x04000021, 0x4c180000, - 0x583c0001, 0x0401fe89, 0x0402001f, 0x0201f800, - 0x001045a6, 0x0402001c, 0x49366009, 0x0201f800, - 0x001007e4, 0x04000018, 0x492e6017, 0x497a5800, - 0x497a5a04, 0x48125c04, 0x832cac00, 0x00000005, - 0x4200b000, 0x00000007, 0x403ca000, 0x0201f800, - 0x0010ab17, 0x5c003000, 0x481a641a, 0x4a026403, - 0x0000003e, 0x4a026406, 0x00000001, 0x4a026203, - 0x00000001, 0x0201f800, 0x0010672b, 0x5c00b000, - 0x1c01f000, 0x0201f800, 0x0002077d, 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, - 0x001048ec, 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, 0x0401ff58, 0x04000008, - 0x59300c03, 0x82040580, 0x00000002, 0x04000006, - 0x82040580, 0x00000051, 0x04000003, 0x80000580, - 0x0401f003, 0x82000540, 0x00000001, 0x1c01f000, + 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, - 0x03000000, 0x04000004, 0x82000d80, 0x52000000, - 0x040207f3, 0x59a80026, 0x82000500, 0x00000009, - 0x82000580, 0x00000008, 0x040007ef, 0x0401f7ec, - 0x4803c856, 0x4c5c0000, 0x4c580000, 0x59a80016, - 0x82000580, 0x0000004c, 0x0402001f, 0x59ccb807, - 0x9c5cb9c0, 0x825cbd00, 0x00000007, 0x8c5cbd00, + 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, - 0x00000002, 0x83cc1400, 0x0000000d, 0x0201f800, - 0x0010855a, 0x04020010, 0x8c5cbd02, 0x0400000a, - 0x4200b000, 0x00000002, 0x83a81c00, 0x00000000, - 0x83cc1400, 0x0000000f, 0x0201f800, 0x0010855a, - 0x04020005, 0x8c5cbd04, 0x04000003, 0x82000540, - 0x00000001, 0x5c00b000, 0x5c00b800, 0x1c01f000, - 0x4803c856, 0x4c5c0000, 0x4c580000, 0x59a80016, - 0x82000580, 0x0000004c, 0x0402001f, 0x59ccb807, - 0x9c5cb9c0, 0x825cbd00, 0x00000007, 0x8c5cbd00, + 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, - 0x00000002, 0x83cc1400, 0x00000009, 0x0201f800, - 0x0010855a, 0x04020010, 0x8c5cbd02, 0x0400000a, - 0x4200b000, 0x00000002, 0x83a81c00, 0x00000000, - 0x83cc1400, 0x0000000b, 0x0201f800, 0x0010855a, - 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, 0x0010d1c0, - 0x4a032800, 0x00000000, 0x4a032808, 0x00107049, - 0x42000000, 0x00000005, 0x83947c00, 0x00000009, - 0x49787801, 0x4a007802, 0x00106fff, 0x823c7c00, - 0x00000003, 0x80000040, 0x040207fa, 0x4a032819, - 0xffff0000, 0x4201d000, 0x00000064, 0x0401f96e, - 0x4201d000, 0x000186a0, 0x0401f184, 0x00000000, - 0x00000003, 0x00000006, 0x00000009, 0x0000000c, - 0x4d300000, 0x4d2c0000, 0x4d340000, 0x4d400000, - 0x4cfc0000, 0x4d380000, 0x4d3c0000, 0x4d440000, - 0x4d4c0000, 0x4d480000, 0x4c5c0000, 0x4c600000, - 0x4c640000, 0x4cc80000, 0x4ccc0000, 0x0201f800, - 0x0002057b, 0x5c019800, 0x5c019000, 0x5c00c800, - 0x5c00c000, 0x5c00b800, 0x5c029000, 0x5c029800, - 0x5c028800, 0x5c027800, 0x5c027000, 0x5c01f800, - 0x5c028000, 0x5c026800, 0x5c025800, 0x5c026000, - 0x1c01f000, 0x59940004, 0x80000540, 0x0402000a, - 0x59940025, 0x80040400, 0x02001800, 0x001005d8, - 0x48032804, 0x480b2805, 0x4a032803, 0x0000000a, - 0x80000580, 0x1c01f000, 0x5994001f, 0x80000540, + 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, - 0x001005d8, 0x4803281f, 0x480b2820, 0x4a03281e, - 0x00000001, 0x80000580, 0x1c01f000, 0x59940022, + 0x00100615, 0x48032804, 0x480b2805, 0x4a032803, + 0x0000000a, 0x80000580, 0x1c01f000, 0x5994001f, 0x80000540, 0x0402000a, 0x59940025, 0x80040400, - 0x02001800, 0x001005d8, 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, - 0x00020245, 0x04020012, 0x59341a03, 0x800c1840, - 0x0400100f, 0x59940027, 0x800c0480, 0x04000003, - 0x48026a03, 0x0402100a, 0x5934000f, 0x497a6a03, - 0x80000540, 0x04000006, 0x4c3c0000, 0x5934140b, - 0x0201f800, 0x00020253, 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, 0x0010d1c0, - 0x497b2826, 0x80000540, 0x0400000f, 0x4a032800, - 0x00000001, 0x5c03e000, 0x1c01f000, 0x4c3c0000, - 0x0201f800, 0x001091db, 0x5c007800, 0x0401f7d1, - 0x4c3c0000, 0x0201f800, 0x00108d5d, 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, 0x001006e2, - 0x1c01f000, 0x4a032807, 0x000007d0, 0x4a032806, - 0x0000000a, 0x1c01f000, 0x42000800, 0x000007d0, - 0x83180480, 0x00000005, 0x02021800, 0x001005d8, - 0x83947c00, 0x00000009, 0x83180400, 0x00105f43, - 0x50000000, 0x803c7c00, 0x48047801, 0x4a007800, - 0x0000000a, 0x1c01f000, 0x83180480, 0x00000005, - 0x02021800, 0x001005d8, 0x83947c00, 0x00000009, - 0x83180400, 0x00105f43, 0x50000000, 0x803c7c00, - 0x49787801, 0x1c01f000, 0x4807c857, 0x480bc857, - 0x59940025, 0x80040400, 0x02001800, 0x001005d8, - 0x48032804, 0x480b2805, 0x4a032803, 0x0000000a, - 0x1c01f000, 0x4807c857, 0x480bc857, 0x59940025, - 0x80040400, 0x02001800, 0x001005d8, 0x4803281c, - 0x480b281d, 0x4a03281b, 0x0000000a, 0x1c01f000, - 0x4c000000, 0x5994001d, 0x4803c857, 0x480bc857, - 0x80080580, 0x04020003, 0x4803281c, 0x4803281d, - 0x5c000000, 0x1c01f000, 0x80e9d1c0, 0x0400000e, - 0x0401f836, 0x04025000, 0x4203e000, 0x80000000, + 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, 0x001066a0, 0x59940024, 0x80080400, - 0x48032824, 0x1c01f000, 0x42001000, 0x00105065, - 0x0401fef0, 0x42001000, 0x00105058, 0x0401ffe1, - 0x42001000, 0x00104148, 0x0401feea, 0x42001000, - 0x001041bc, 0x0401fee7, 0x42001000, 0x001041f3, - 0x0401f6f8, 0x4203e000, 0x70000000, 0x4203e000, - 0xb0300000, 0x41fc0000, 0x40ebf800, 0x80e80480, - 0x04001011, 0x04000004, 0x82000480, 0x00000003, - 0x0402100d, 0x42000000, 0x0000000f, 0x04004004, + 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, 0x0010b87e, 0x0201f800, - 0x0010aa47, 0x1c01f000, 0x4203e000, 0x80000000, - 0x4203e000, 0xb0400000, 0x41fc0000, 0x40ebf800, - 0x80e80480, 0x04001011, 0x04000004, 0x82000480, - 0x00000003, 0x0402100d, 0x42000000, 0x0000000f, - 0x04005004, 0x80000040, 0x040207fe, 0x0401f007, - 0x4203e000, 0x80000000, 0x42000000, 0x0010b87f, - 0x0201f800, 0x0010aa47, 0x1c01f000, 0x59a8000e, - 0x82000480, 0x00000100, 0x599c0a02, 0x800409c0, - 0x04020002, 0x80040800, 0x80041480, 0x04001002, - 0x40000800, 0x48075067, 0x59a8100e, 0x40040000, - 0x800acc80, 0x4967500e, 0x49675069, 0x59aaa80b, - 0x41640800, 0x42001000, 0x00000024, 0x0201f800, - 0x00106681, 0x8206a400, 0x0010d1c0, 0x49535065, - 0x4152b000, 0x42006000, 0x0010be65, 0x4a006004, - 0x0000012c, 0x4a006005, 0xda10da10, 0x4a006008, - 0x00000011, 0x4a006009, 0x0010be65, 0x4a00600a, - 0x001010b8, 0x599c0014, 0x48006011, 0x599c0015, - 0x48006012, 0x42006000, 0x0010be41, 0x4a006203, - 0x00000008, 0x4a006406, 0x00000006, 0x4a006002, - 0xffff0000, 0x4a006008, 0x0010be65, 0x4a006014, - 0x0010be65, 0x599c0014, 0x48006015, 0x599c0015, - 0x48006016, 0x599c0413, 0x48006017, 0x49506018, - 0x49546019, 0x59a80067, 0x4800601a, 0x4a00601b, - 0x0010b465, 0x4a00601c, 0x0010b466, 0x4a00601d, - 0x0010b46a, 0x42000000, 0xb0000000, 0x42000800, - 0x0010be41, 0x0201f800, 0x00100b68, 0x1c01f000, - 0x82000d00, 0x000000c0, 0x04000004, 0x82040d80, - 0x000000c0, 0x04020055, 0x82000d00, 0x00002020, - 0x59300414, 0x84000512, 0x82040d80, 0x00002020, - 0x0400000b, 0x8c000514, 0x0402000f, 0x48026414, - 0x813e79c0, 0x02020000, 0x000206d0, 0x42027000, - 0x00000043, 0x0201f000, 0x000207a1, 0x59326809, - 0x59340a00, 0x8c040d0a, 0x040007f3, 0x84000552, - 0x0401f7f1, 0x84000514, 0x592c080d, 0x48066015, - 0x0401f7ef, 0x59326809, 0x59340a00, 0x8c040d0a, - 0x02000000, 0x000206e3, 0x59300c14, 0x84040d52, - 0x48066414, 0x0201f000, 0x000206e3, 0x0201f800, - 0x00020086, 0x813e79c0, 0x02020000, 0x000206d0, - 0x0201f000, 0x000206f1, 0x8c00051e, 0x02000000, - 0x000206fd, 0x82000d00, 0x00002020, 0x82040d80, - 0x00002020, 0x04000014, 0x82000500, 0x000000c0, - 0x82000d80, 0x00000080, 0x04000008, 0x813e79c0, - 0x02020000, 0x000206d0, 0x42027000, 0x00000041, - 0x0201f000, 0x000207a1, 0x813e79c0, 0x02020000, - 0x000206d0, 0x42027000, 0x00000043, 0x0201f000, - 0x000207a1, 0x59326809, 0x59340a00, 0x8c040d0a, - 0x040007ea, 0x59300c14, 0x84040d52, 0x48066414, - 0x0401f7e6, 0x492fc857, 0x42000800, 0x00000006, - 0x0201f000, 0x000206f8, 0x492fc857, 0x42000800, - 0x00000004, 0x0201f000, 0x000206f8, 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, 0x00100b94, 0x59a80069, 0x82000480, - 0x00000007, 0x48035069, 0x80000580, 0x42000800, - 0x0010b519, 0x48000800, 0x48000801, 0x1c01f000, - 0x59a80069, 0x82000480, 0x00000007, 0x48035069, - 0x1c01f000, 0x83640480, 0x00000008, 0x0400101b, - 0x58c80a03, 0x80000580, 0x82000400, 0x00000008, - 0x80040840, 0x040207fd, 0x815c0480, 0x04001013, - 0x4200b000, 0x00000007, 0x0201f800, 0x0002075a, - 0x4a026203, 0x00000004, 0x4a026406, 0x00000009, - 0x4a026203, 0x00000004, 0x4a026007, 0x00000101, - 0x0401f809, 0x0401f880, 0x8058b040, 0x040207f3, - 0x80000580, 0x1c01f000, 0x82000540, 0x00000001, - 0x0401f7fd, 0x0201f800, 0x001007e4, 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, - 0x001007e4, 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, 0x0010b519, - 0x0401f87f, 0x04000012, 0x0201f800, 0x001007d3, - 0x0400000f, 0x492cb805, 0x585c0005, 0x80000540, - 0x02000800, 0x001005d8, 0x0401f830, 0x585c5408, - 0x0401f80b, 0x5c00b800, 0x5c03e000, 0x817ef840, - 0x040207e1, 0x5c02f800, 0x1c01f000, 0x5c00b800, - 0x5c03e000, 0x5c02f800, 0x1c01f000, 0x4803c856, - 0x405c6000, 0x802851c0, 0x04000018, 0x585c0204, - 0x82000d00, 0x0000000f, 0x82040c00, 0x001010bd, - 0x50044000, 0x4cf00000, 0x4d000000, 0x4d040000, - 0x4021e000, 0x40320800, 0x59860004, 0x4c280000, - 0x0401f934, 0x5c005000, 0x40f04000, 0x41046000, - 0x0201f800, 0x0010109b, 0x040207f6, 0x5c020800, - 0x5c020000, 0x5c01e000, 0x58c80204, 0x4800bc08, - 0x0201f800, 0x00020086, 0x4a026007, 0x00000101, - 0x497a6009, 0x0401f055, 0x4803c856, 0x59840003, - 0x80026540, 0x04000003, 0x59300000, 0x48030803, - 0x1c01f000, 0x4803c856, 0x59840003, 0x48026000, - 0x49330803, 0x1c01f000, 0x58cc0805, 0x40180000, - 0x80040480, 0x0400100d, 0x82cc0580, 0x0010b50e, - 0x02020800, 0x001005d8, 0x58c80205, 0x80040480, - 0x0400101d, 0x82000540, 0x00000001, 0x1c01f000, - 0x80003580, 0x0401f7fe, 0x82cc0580, 0x0010b50e, - 0x02020800, 0x001005d8, 0x58c80400, 0x8c000504, - 0x040007f8, 0x58c8040b, 0x8c00051e, 0x040007f5, - 0x8c000500, 0x040207f3, 0x84000540, 0x4801940b, - 0x42000000, 0x0010b839, 0x0201f800, 0x0010aa47, - 0x42001000, 0x00008026, 0x0201f800, 0x00103a3e, - 0x0401f7e8, 0x58c8040b, 0x8c00051e, 0x040007e2, - 0x8c000502, 0x040207e0, 0x84000542, 0x4801940b, - 0x42000000, 0x0010b838, 0x0201f800, 0x0010aa47, - 0x42001000, 0x00008025, 0x42001800, 0x00000000, - 0x0201f800, 0x00103a3e, 0x0401f7d3, 0x4803c856, - 0x58080000, 0x42001800, 0x00000007, 0x58080801, - 0x80040480, 0x04020004, 0x400c0000, 0x80000540, - 0x0401f005, 0x04001003, 0x800c0480, 0x0401f002, - 0x80000080, 0x1c01f000, 0x4803c856, 0x59300008, - 0x80000d40, 0x02000800, 0x001005d8, 0x58040005, - 0x80000540, 0x02000800, 0x001005d8, 0x59300007, - 0x82000500, 0x00000101, 0x82000580, 0x00000101, - 0x02020800, 0x001005d8, 0x42001000, 0x0010b519, - 0x58080801, 0x82040400, 0x0010b51b, 0x497a6414, - 0x4a026015, 0x0000ffff, 0x45300000, 0x80040800, - 0x82040480, 0x00000008, 0x04001002, 0x80000d80, - 0x48041001, 0x82040400, 0x0010b51b, 0x45780000, - 0x1c01f000, 0x4933c857, 0x59300808, 0x800409c0, - 0x02000800, 0x001005d8, 0x4d2c0000, 0x58065805, - 0x812e59c0, 0x02020800, 0x001007f4, 0x49780805, - 0x40065800, 0x0201f800, 0x001007fd, 0x5c025800, - 0x4d300000, 0x0201f800, 0x0002077d, 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, - 0x00100b94, 0x4807c857, 0x4805980a, 0x49799801, - 0x49799803, 0x49799806, 0x49799807, 0x49799808, - 0x49799805, 0x49799809, 0x0401f8c9, 0x0400000a, - 0x0401f8eb, 0x04000008, 0x48359800, 0x48359802, - 0x48359806, 0x4a019804, 0x00000001, 0x4a019807, - 0x00000005, 0x1c01f000, 0x4807c857, 0x58cc1007, - 0x40040000, 0x80080480, 0x04021020, 0x4c040000, - 0x4c080000, 0x0401f8da, 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, - 0x001005d8, 0x82040400, 0x00106418, 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, 0x001005d8, - 0x58040800, 0x48059800, 0x41782000, 0x0401f7ee, - 0x0401f813, 0x50f00000, 0x81040400, 0x40001800, + 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, 0x001005d8, 0x58040202, 0x800000e0, - 0x81000540, 0x48001802, 0x58040000, 0x48001800, + 0x02020800, 0x00100615, 0x58040202, 0x800000e0, + 0x80640540, 0x48001802, 0x58040000, 0x48001800, 0x58040001, 0x48001801, 0x1c01f000, 0x4807c856, - 0x58cc0005, 0x80000040, 0x02001800, 0x001005d8, + 0x58cc0005, 0x80000040, 0x02001800, 0x00100615, 0x48019805, 0x58cc1003, 0x82080480, 0x00000005, - 0x02021800, 0x001005d8, 0x82080400, 0x00106418, + 0x02021800, 0x00100615, 0x82080400, 0x00106150, 0x50000000, 0x58cc0802, 0x80040c00, 0x80081000, 0x82080480, 0x00000005, 0x0402000f, 0x58cc2002, 0x58100000, 0x80006d40, 0x04000009, 0x4c340000, @@ -6425,30 +6247,30 @@ uint32_t risc_code01[] = { 0x80102000, 0x82000480, 0x00000005, 0x04000002, 0x040217fc, 0x48119203, 0x1c01f000, 0x4807c856, 0x4d2c0000, 0x58cc000a, 0x80000540, 0x02000800, - 0x001005d8, 0x82002400, 0x00000005, 0x0201f800, - 0x001007d3, 0x04000012, 0x492d9809, 0x497a5800, - 0x497a5801, 0x0201f800, 0x001007d3, 0x0400000c, + 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, - 0x001007f4, 0x40100000, 0x0401f7fa, 0x58cc0009, + 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, 0x001007f4, 0x5c000000, 0x0401f7f9, + 0x0201f800, 0x0010083a, 0x5c000000, 0x0401f7f9, 0x5c025800, 0x1c01f000, 0x4807c856, 0x4d2c0000, 0x58cc0002, 0x80025d40, 0x04000007, 0x592c0000, - 0x4c000000, 0x0201f800, 0x001007f4, 0x5c000000, + 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, - 0x0010b524, 0x04000013, 0x58080802, 0x82040d00, + 0x0010b320, 0x04000013, 0x58080802, 0x82040d00, 0x00ffffff, 0x58080403, 0x4804c005, 0x4800c406, 0x4a00c207, 0x00000003, 0x59300811, 0x585c0404, 0x4978c206, 0x4804c407, 0x80000540, 0x0400000d, @@ -6457,17 +6279,17 @@ uint32_t risc_code01[] = { 0x4a00c406, 0x000007ff, 0x4978c207, 0x0401f7ef, 0x82603c00, 0x00000008, 0x58605404, 0x40282000, 0x405c6000, 0x585c0a04, 0x82040d00, 0x0000000f, - 0x82040c00, 0x001010bd, 0x50044000, 0x80004d80, + 0x82040c00, 0x0010110d, 0x50044000, 0x80004d80, 0x50200000, 0x80307400, 0x58380402, 0x8c244d00, 0x04020003, 0x48003a00, 0x0401f003, 0x48003c00, 0x801c3800, 0x80244800, 0x80102040, 0x04000006, - 0x0201f800, 0x0010109b, 0x02000800, 0x001005d8, + 0x0201f800, 0x001010eb, 0x02000800, 0x00100615, 0x0401f7f0, 0x1c01f000, 0x4803c856, 0x4d340000, - 0x59300009, 0x80026d40, 0x02000800, 0x001005d8, + 0x59300009, 0x80026d40, 0x02000800, 0x00100615, 0x59340401, 0x80000540, 0x0400000e, 0x59840000, 0x80000540, 0x0400000b, 0x836c0580, 0x00000003, 0x04020008, 0x59341c03, 0x42002000, 0x00000004, - 0x42003000, 0x00000004, 0x0201f800, 0x00103aae, + 0x42003000, 0x00000004, 0x0201f800, 0x001038c7, 0x5c026800, 0x1c01f000, 0x4803c856, 0x80001580, 0x58c80c01, 0x59300011, 0x80040c80, 0x48066011, 0x58c80201, 0x80000540, 0x04000005, 0x80081000, @@ -6480,172 +6302,176 @@ uint32_t risc_code01[] = { 0x5934000e, 0x80006d40, 0x04000010, 0x81300580, 0x04020004, 0x58340000, 0x4802680e, 0x0401f00a, 0x40347800, 0x58340000, 0x80006d40, 0x02000800, - 0x001005d8, 0x81300580, 0x040207fa, 0x58340000, + 0x00100615, 0x81300580, 0x040207fa, 0x58340000, 0x48007800, 0x497a6000, 0x4a0370e5, 0x00020000, 0x1c01f000, 0x4803c856, 0x4d300000, 0x4d2c0000, 0x42000800, 0x000003ff, 0x4a0370e5, 0x00020000, 0x59b800e5, 0x8c000524, 0x04000005, 0x80040840, - 0x040207fa, 0x0201f800, 0x001005d8, 0x4a0370e5, + 0x040207fa, 0x0201f800, 0x00100615, 0x4a0370e5, 0x00030000, 0x40000000, 0x40000000, 0x59b800e5, 0x8c000524, 0x040207f1, 0x5934000e, 0x80026540, 0x0400000e, 0x4933c857, 0x59300000, 0x4802680e, 0x4a026203, 0x00000004, 0x497a6206, 0x497a6009, 0x4a026007, 0x00000101, 0x59325808, 0x497a5c08, - 0x0401fd81, 0x0401f7f1, 0x4a0370e5, 0x00020000, + 0x0401fd82, 0x0401f7f1, 0x4a0370e5, 0x00020000, 0x5c025800, 0x5c026000, 0x1c01f000, 0x4803c856, - 0x4c000000, 0x0201f800, 0x00105c9a, 0x04020011, - 0x0201f800, 0x001045a6, 0x02020800, 0x001005d8, - 0x5c000000, 0x48026802, 0x0201f800, 0x0002075a, + 0x4c000000, 0x0201f800, 0x001059b9, 0x04020011, + 0x0201f800, 0x001043fc, 0x02020800, 0x00100615, + 0x5c000000, 0x48026802, 0x0201f800, 0x00020892, 0x04000009, 0x49366009, 0x4a026406, 0x00000001, - 0x42027000, 0x00000001, 0x0201f000, 0x000207a1, + 0x42027000, 0x00000001, 0x0201f000, 0x000208d8, 0x5c000000, 0x1c01f000, 0x59300203, 0x82000c80, - 0x0000000e, 0x02021800, 0x001005d8, 0x4803c857, - 0x0c01f001, 0x00106503, 0x00106503, 0x00106503, - 0x00106505, 0x00106565, 0x00106503, 0x00106503, - 0x001065b7, 0x001065b8, 0x00106503, 0x00106503, - 0x00106503, 0x00106503, 0x00106503, 0x0201f800, - 0x001005d8, 0x493bc857, 0x83380480, 0x00000050, - 0x02021800, 0x001005d8, 0x83380480, 0x00000049, - 0x02001800, 0x001005d8, 0x0c01f001, 0x00106518, - 0x0010653a, 0x00106516, 0x00106516, 0x00106516, - 0x00106516, 0x00106549, 0x0201f800, 0x001005d8, + 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, 0x00104cde, + 0x592c0000, 0x48026008, 0x0201f800, 0x00020385, 0x59300008, 0x80000540, 0x04000008, 0x4a026203, 0x00000007, 0x42027000, 0x00000043, 0x5c00b800, 0x5c025800, 0x0401f08a, 0x8c5cbd08, 0x04020006, 0x4a026203, 0x00000007, 0x497a6206, 0x497a6008, - 0x0401f003, 0x0201f800, 0x0002077d, 0x5c00b800, - 0x5c025800, 0x1c01f000, 0x0201f800, 0x00106b8a, - 0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037, + 0x0401f003, 0x0201f800, 0x000208b4, 0x5c00b800, + 0x5c025800, 0x1c01f000, 0x0201f800, 0x001068c1, + 0x4d2c0000, 0x59325808, 0x0201f800, 0x00108df4, 0x04000006, 0x4d400000, 0x42028000, 0x00000001, - 0x0401f8f8, 0x5c028000, 0x5c025800, 0x0201f000, - 0x0002077d, 0x0201f800, 0x00106b8a, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x0010203c, 0x5c027800, - 0x42003000, 0x00000014, 0x0201f800, 0x0010a942, - 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47, - 0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037, + 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, - 0x0401f8dc, 0x5c028000, 0x5c025800, 0x0201f000, - 0x0002077d, 0x493bc857, 0x497a6206, 0x83380480, - 0x00000054, 0x02021800, 0x001005d8, 0x83380480, - 0x00000047, 0x02001800, 0x001005d8, 0x0c01f001, - 0x001065b6, 0x0010657f, 0x0010657d, 0x0010657d, - 0x0010657d, 0x0010657d, 0x0010657d, 0x0010657d, - 0x0010657d, 0x0010657d, 0x0010657d, 0x0010657d, - 0x00106583, 0x0201f800, 0x001005d8, 0x59300011, + 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, - 0x001005d8, 0x0401fe8d, 0x40625800, 0x0201f800, - 0x00104cde, 0x4978b805, 0x0401fef5, 0x497a6009, - 0x585c3408, 0x0401fcbd, 0x0400000e, 0x42001000, - 0x0010b519, 0x0401fcf2, 0x0400000a, 0x0201f800, - 0x001007e4, 0x04000007, 0x492cb805, 0x585c5408, - 0x0401fc83, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x0401fca9, 0x0401f7fc, 0x8c040d06, 0x040207fc, + 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, 0x001005d8, 0x497a6009, - 0x0401fd0d, 0x0401f7f2, 0x0401f06f, 0x4803c856, + 0x80000540, 0x02020800, 0x00100615, 0x497a6009, + 0x0401fd0e, 0x0401f7f2, 0x0401f085, 0x4803c856, 0x4803c856, 0x83380580, 0x00000043, 0x02020800, - 0x001005d8, 0x4a026203, 0x00000003, 0x493a6403, + 0x00100615, 0x4a026203, 0x00000003, 0x493a6403, 0x59325808, 0x592c000f, 0x48026011, 0x497a6013, 0x592c0406, 0x800000c2, 0x800010c4, 0x80081400, - 0x480a6206, 0x0201f800, 0x00100f4e, 0x42000800, - 0x80000060, 0x0401f154, 0x42000000, 0x0010b875, - 0x0201f800, 0x0010aa47, 0x59300203, 0x82000c80, - 0x0000000e, 0x02021800, 0x001005d8, 0x4803c857, + 0x480a6206, 0x0201f800, 0x00100f9c, 0x42000800, + 0x80000060, 0x0401f161, 0x42000000, 0x0010b674, + 0x0201f800, 0x0010a86e, 0x59300203, 0x82000c80, + 0x0000000e, 0x02021800, 0x00100615, 0x4803c857, 0x82000d80, 0x00000003, 0x04000006, 0x82000d80, - 0x00000004, 0x04000045, 0x0201f800, 0x001005d8, - 0x0201f800, 0x00106c55, 0x59300004, 0x8c00053e, - 0x04020007, 0x0201f800, 0x00106b6c, 0x02020800, - 0x001005d8, 0x0201f000, 0x00106c4b, 0x0401f9c3, - 0x0201f800, 0x00106c4b, 0x59325808, 0x42028000, - 0x00000006, 0x0401f84b, 0x0201f000, 0x0002077d, + 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, 0x001005d8, 0x82000d80, 0x00000003, - 0x04000006, 0x82000d80, 0x00000004, 0x04000023, - 0x0201f800, 0x001005d8, 0x4803c856, 0x0201f800, - 0x00106c55, 0x4df00000, 0x59300004, 0x8c00053e, - 0x04020006, 0x0201f800, 0x00106f60, 0x02020800, - 0x001005d8, 0x0401f010, 0x0201f800, 0x00108cd6, - 0x04020004, 0x0201f800, 0x00106e62, 0x0402000a, - 0x0401f99a, 0x02020800, 0x001005d8, 0x5c03e000, - 0x02000800, 0x00106c4b, 0x82000540, 0x00000001, - 0x1c01f000, 0x5c03e000, 0x02000800, 0x00106c4b, - 0x80000580, 0x1c01f000, 0x4933c857, 0x0201f800, - 0x00100e99, 0x4933c857, 0x4c5c0000, 0x4d340000, - 0x497a6206, 0x5930b808, 0x59300009, 0x80026d40, - 0x04020e5f, 0x42001000, 0x0010b519, 0x0401fc60, - 0x04000009, 0x58c80204, 0x4800bc08, 0x41785000, - 0x0201f800, 0x00106227, 0x5c026800, 0x5c00b800, - 0x1c01f000, 0x4978bc08, 0x0401fc17, 0x0401f7fb, - 0x4803c856, 0x0201f800, 0x00109037, 0x0400000f, - 0x592c0000, 0x80000d40, 0x04000009, 0x497a5800, - 0x49425a06, 0x4c040000, 0x0201f800, 0x000202da, - 0x5c000800, 0x40065800, 0x0401f7f6, 0x49425a06, - 0x0201f800, 0x000202da, 0x1c01f000, 0x4933c857, - 0x59300c06, 0x82040580, 0x0000000e, 0x04000004, - 0x82040580, 0x00000009, 0x04020004, 0x0401ffe5, - 0x497a6008, 0x80000580, 0x1c01f000, 0x592e6009, - 0x83300480, 0x0010d1c0, 0x04001016, 0x41580000, - 0x81300480, 0x04021013, 0x40040000, 0x59300c06, - 0x80040580, 0x04020012, 0x59300a03, 0x82040580, - 0x00000007, 0x02020800, 0x001005d8, 0x59300008, - 0x80000540, 0x02020800, 0x001005d8, 0x0201f800, - 0x0002077d, 0x42000000, 0x00000000, 0x0401f009, - 0x42000000, 0x00000008, 0x0401f006, 0x82040580, - 0x00000007, 0x040207fb, 0x42000000, 0x00000005, - 0x592c0a06, 0x48065c06, 0x48025a06, 0x0201f000, - 0x000202da, 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, 0x4a0378e8, 0x00000000, 0x4a03c821, - 0x00000010, 0x4a03c823, 0x00000004, 0x0401f82c, - 0x4a0378e9, 0x00003a0d, 0x4a0378e8, 0x00000001, - 0x42000000, 0x00001000, 0x50000000, 0x82000480, - 0x24220001, 0x04000004, 0x59e00002, 0x84000548, - 0x4803c002, 0x42000800, 0x00000005, 0x4203a000, - 0x00007600, 0x42000000, 0x00001000, 0x50000000, - 0x82000480, 0x24320001, 0x04021003, 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, 0x42000800, 0x0000bf00, 0x4a00081a, - 0x0010b7d4, 0x4a00081b, 0x001010bd, 0x4a00081c, - 0x001010cd, 0x4a031800, 0x00000000, 0x4a031801, - 0x0010b544, 0x4a031802, 0x0010b54b, 0x42000800, - 0x0010b7d7, 0x417a3000, 0x811b20c8, 0x83932400, - 0x0000bf32, 0x48072000, 0x4a032001, 0x00000000, - 0x83180400, 0x001070ea, 0x50000000, 0x48032002, - 0x82040c00, 0x00000003, 0x811a3000, 0x83180480, - 0x00000005, 0x040017f1, 0x5c023000, 0x5c032000, - 0x1c01f000, 0x48066004, 0x497a6000, 0x497a6001, - 0x59bc00ea, 0x8c000516, 0x040207fe, 0x83300400, - 0xa0000000, 0x480378e1, 0x1c01f000, 0x4933c857, - 0x42000800, 0x80000040, 0x48066004, 0x497a6000, + 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, - 0x00106c55, 0x4df00000, 0x4d300000, 0x4d340000, + 0x0010698c, 0x4df00000, 0x4d300000, 0x4d340000, 0x4d2c0000, 0x4d180000, 0x4c5c0000, 0x4c600000, 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, 0x42003000, 0x0000bf2e, 0x581a6001, 0x813261c0, @@ -6654,438 +6480,440 @@ uint32_t risc_code01[] = { 0x82000d80, 0x00000006, 0x04020003, 0x8d3e7d18, 0x04000010, 0x8d3e7d06, 0x04000007, 0x82000580, 0x00000003, 0x04020004, 0x59340200, 0x8c00050e, - 0x04020008, 0x0401f92f, 0x4c0c0000, 0x4c140000, - 0x0401fb5f, 0x5c002800, 0x5c001800, 0x0401f005, + 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, 0x001070d8, 0x59926004, + 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, 0x0401f8dc, 0x4c140000, - 0x0401fb2f, 0x5c002800, 0x0401f002, 0x41302800, + 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, - 0x00106c4b, 0x1c01f000, 0x4933c857, 0x0201f800, - 0x00106c55, 0x4df00000, 0x4d340000, 0x4d180000, + 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, 0x0401f8bd, + 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, 0x0401f881, 0x5c032000, 0x5c023000, - 0x5c026800, 0x5c03e000, 0x02000800, 0x00106c4b, - 0x80000580, 0x1c01f000, 0x0401fb6f, 0x040007f7, - 0x5c032000, 0x5c023000, 0x5c026800, 0x5c03e000, - 0x02000800, 0x00106c4b, 0x82000540, 0x00000001, - 0x1c01f000, 0x0201f800, 0x00106c55, 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, 0x0401fb67, 0x0402000e, 0x59300406, - 0x82000580, 0x00000006, 0x04020003, 0x8d3e7d18, - 0x04000008, 0x0401f867, 0x4c0c0000, 0x4c140000, - 0x0401fa97, 0x5c002800, 0x5c001800, 0x0401f002, - 0x41301800, 0x405e6000, 0x813261c0, 0x040207eb, - 0x0401f02d, 0x417a3000, 0x0201f800, 0x001070d8, - 0x59926004, 0x813261c0, 0x04000005, 0x59326809, - 0x59340403, 0x81440580, 0x04000006, 0x811a3000, - 0x83180480, 0x00000005, 0x040017f4, 0x0401f01e, - 0x4130c000, 0x59300001, 0x8000bd40, 0x04000012, - 0x40026000, 0x40602800, 0x5930b801, 0x8d3e7d00, - 0x04000003, 0x0401fb3b, 0x0402000a, 0x59300406, - 0x82000580, 0x00000006, 0x04000006, 0x0401f81b, - 0x4c140000, 0x0401fa6e, 0x5c002800, 0x0401f002, - 0x41302800, 0x405e6000, 0x813261c0, 0x040207ef, - 0x8060c1c0, 0x04000004, 0x40626000, 0x4178c000, - 0x0401f7eb, 0x5c022800, 0x5c034800, 0x5c03a000, - 0x5c032000, 0x5c00c000, 0x5c00b800, 0x5c025800, - 0x5c023000, 0x5c026800, 0x5c026000, 0x5c03e000, - 0x04000be3, 0x1c01f000, 0x0401fbc8, 0x59900004, - 0x81300580, 0x04020018, 0x4c140000, 0x0201f800, - 0x00106dc3, 0x0401fbb8, 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, - 0x0401fba6, 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, 0x0401fb82, - 0x4df00000, 0x0401f839, 0x040208c4, 0x04020945, - 0x04020a89, 0x04020005, 0x5c03e000, 0x04000b70, - 0x80000580, 0x1c01f000, 0x5c03e000, 0x04000b6c, - 0x82000540, 0x00000001, 0x1c01f000, 0x4d2c0000, - 0x4d340000, 0x4d300000, 0x41783000, 0x598e6009, - 0x813261c0, 0x04000021, 0x59300406, 0x82000580, - 0x00000006, 0x04020004, 0x8d3e7d18, 0x0402000a, - 0x0401f017, 0x82040580, 0x00000005, 0x04020006, - 0x8d3e7d16, 0x04000004, 0x59300420, 0x8c000500, - 0x0402000f, 0x0401fa4e, 0x59300000, 0x4c000000, - 0x8d3e7d06, 0x04000004, 0x0201f800, 0x001092d7, - 0x04000005, 0x0401f867, 0x4c180000, 0x0401f9bc, - 0x5c003000, 0x5c026000, 0x0401f7e2, 0x41303000, - 0x59326000, 0x0401f7df, 0x5c026000, 0x5c026800, - 0x5c025800, 0x1c01f000, 0x4933c857, 0x4c5c0000, - 0x813261c0, 0x02000800, 0x001005d8, 0x41300000, - 0x598cb809, 0x41783000, 0x805cb9c0, 0x04000013, - 0x805c0d80, 0x04000004, 0x405c3000, 0x5818b800, - 0x0401f7fa, 0x0401f84b, 0x598c000d, 0x81300580, - 0x02000800, 0x001070b9, 0x59300403, 0x82000580, - 0x00000042, 0x04020002, 0x497a6007, 0x80000580, - 0x5c00b800, 0x1c01f000, 0x82000540, 0x00000001, - 0x5c00b800, 0x1c01f000, 0x0401fb27, 0x4df00000, + 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, 0x0400002c, 0x59300c06, - 0x82040580, 0x00000006, 0x04020004, 0x8d3e7d18, - 0x0402000a, 0x0401f022, 0x82040580, 0x00000005, - 0x04020006, 0x8d3e7d18, 0x04000004, 0x59300420, - 0x8c000500, 0x0402001a, 0x59326809, 0x59340403, - 0x81440580, 0x04020016, 0x8d3e7d00, 0x04000006, - 0x82040580, 0x00000003, 0x04020011, 0x0401fa35, - 0x0402000f, 0x0401f9f6, 0x59300000, 0x4c000000, - 0x8d3e7d06, 0x04000004, 0x0201f800, 0x001092d7, - 0x04000005, 0x0401f80f, 0x4c180000, 0x0401f964, - 0x5c003000, 0x5c026000, 0x0401f7d7, 0x41303000, - 0x59326000, 0x0401f7d4, 0x5c026000, 0x5c026800, - 0x5c025800, 0x5c03e000, 0x04000ae5, 0x1c01f000, - 0x59300800, 0x497a6000, 0x0401fac8, 0x801831c0, - 0x04020009, 0x598c0008, 0x81300580, 0x04020004, - 0x48031808, 0x48031809, 0x0401f008, 0x48071809, - 0x0401f006, 0x48043000, 0x598c0008, 0x81300580, - 0x04020002, 0x481b1808, 0x0401f2ca, 0x4d2c0000, - 0x4d300000, 0x4d340000, 0x41783000, 0x598e600b, - 0x813261c0, 0x04000013, 0x8d3e7d06, 0x04000005, - 0x59326809, 0x59340200, 0x8c00050e, 0x0402000a, - 0x0401f9bf, 0x59300000, 0x4c000000, 0x0401f853, - 0x4c180000, 0x0401f932, 0x5c003000, 0x5c026000, - 0x0401f7f0, 0x41303000, 0x59326000, 0x0401f7ed, - 0x0201f800, 0x00104773, 0x5c026800, 0x5c026000, - 0x5c025800, 0x1c01f000, 0x4933c857, 0x4c5c0000, - 0x813261c0, 0x02000800, 0x001005d8, 0x41300000, - 0x598cb80b, 0x41783000, 0x805cb9c0, 0x0400000f, - 0x805c0d80, 0x04000004, 0x405c3000, 0x5818b800, - 0x0401f7fa, 0x0401f835, 0x598c000d, 0x81300580, - 0x02000800, 0x001070b9, 0x497a6007, 0x80000580, + 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, - 0x5c00b800, 0x1c01f000, 0x0401fa9f, 0x4df00000, - 0x4d340000, 0x4d300000, 0x4d2c0000, 0x0201f800, - 0x00020245, 0x02020800, 0x001005d8, 0x41783000, - 0x598e600b, 0x813261c0, 0x04000014, 0x59300009, - 0x81340580, 0x0402000e, 0x8d3e7d00, 0x04000003, - 0x0401f9bc, 0x0402000a, 0x0401f97d, 0x59300000, - 0x4c000000, 0x0401f811, 0x4c180000, 0x0401f8f0, - 0x5c003000, 0x5c026000, 0x0401f7ef, 0x41303000, - 0x59326000, 0x0401f7ec, 0x0201f800, 0x0010479c, - 0x5c025800, 0x5c026000, 0x5c026800, 0x5c03e000, - 0x04000a6f, 0x1c01f000, 0x59300800, 0x497a6000, - 0x0401fa52, 0x801831c0, 0x04020009, 0x598c000a, - 0x81300580, 0x04020004, 0x4803180a, 0x4803180b, - 0x0401f008, 0x4807180b, 0x0401f006, 0x48043000, - 0x598c000a, 0x81300580, 0x04020002, 0x481b180a, - 0x0401f254, 0x0401fa64, 0x4df00000, 0x4d300000, - 0x598e6005, 0x813261c0, 0x04000020, 0x59300000, - 0x4c000000, 0x59300c06, 0x82040580, 0x00000011, - 0x04020007, 0x833c0500, 0x00001800, 0x04000015, - 0x8d3e7d16, 0x04020013, 0x0401f009, 0x82040580, - 0x00000004, 0x04020006, 0x8d3e7d16, 0x04000004, - 0x59300420, 0x8c000500, 0x0402000a, 0x0201f800, - 0x0010914e, 0x02000800, 0x0010801c, 0x0201f800, - 0x00109326, 0x0201f800, 0x0002077d, 0x0401fa31, - 0x5c026000, 0x0401f7e0, 0x497b1805, 0x497b1804, - 0x5c026000, 0x5c03e000, 0x04000a31, 0x1c01f000, - 0x4933c857, 0x4c5c0000, 0x4c600000, 0x813261c0, - 0x02000800, 0x001005d8, 0x41300000, 0x598cb805, - 0x405cc000, 0x805cb9c0, 0x04000025, 0x805c0d80, - 0x04000004, 0x405cc000, 0x5860b800, 0x0401f7fa, - 0x598c000d, 0x81300580, 0x02000800, 0x001070b9, - 0x0401fa02, 0x598c0005, 0x805c0580, 0x04020009, - 0x585c0000, 0x48031805, 0x4978b800, 0x598c0004, - 0x805c0580, 0x0402000d, 0x497b1804, 0x0401f00b, - 0x598c0004, 0x805c0580, 0x04020005, 0x48631804, - 0x4978b800, 0x4978c000, 0x0401f004, 0x585c0000, - 0x4800c000, 0x4978b800, 0x0401f9fe, 0x80000580, - 0x5c00c000, 0x5c00b800, 0x1c01f000, 0x82000540, - 0x00000001, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x4933c857, 0x0401fa04, 0x4df00000, 0x4d2c0000, - 0x4d340000, 0x4d300000, 0x4c5c0000, 0x4178b800, - 0x8d3e7d18, 0x0400000d, 0x8d3e7d16, 0x0402000b, - 0x0201f800, 0x00109037, 0x04000008, 0x0201f800, - 0x00109597, 0x04020005, 0x592c0207, 0x492fc857, - 0x8200bd00, 0x0000000f, 0x41783000, 0x598e6005, - 0x813261c0, 0x04000029, 0x59326809, 0x813669c0, - 0x04000023, 0x59340403, 0x81440580, 0x04020020, + 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, 0x04020016, 0x0201f800, 0x00109037, - 0x04000008, 0x0201f800, 0x00109597, 0x04020005, - 0x59300403, 0x82000580, 0x00000043, 0x0400000c, - 0x0401f8c3, 0x59300000, 0x4c000000, 0x0401f812, - 0x4c180000, 0x0401f836, 0x5c003000, 0x5c026000, - 0x0401f7dc, 0x805cb9c0, 0x040207ec, 0x41303000, - 0x59326000, 0x0401f7d7, 0x5c00b800, 0x5c026000, - 0x5c026800, 0x5c025800, 0x5c03e000, 0x040009b4, - 0x1c01f000, 0x59300800, 0x497a6000, 0x0401f997, - 0x801831c0, 0x04020009, 0x598c0004, 0x81300580, - 0x04020004, 0x48031804, 0x48031805, 0x0401f008, - 0x48071805, 0x0401f006, 0x48043000, 0x598c0004, - 0x81300580, 0x04020002, 0x481b1804, 0x0401f199, - 0x4943c857, 0x0401f9a8, 0x4df00000, 0x0401fe34, - 0x0401fecb, 0x5c03e000, 0x04000999, 0x1c01f000, - 0x4947c857, 0x0401f9a0, 0x4df00000, 0x4d3c0000, - 0x853e7d00, 0x0401fe75, 0x0401fefc, 0x5c027800, - 0x5c03e000, 0x0400098e, 0x1c01f000, 0x5c000000, - 0x4c000000, 0x4803c857, 0x4d340000, 0x4d2c0000, - 0x59326809, 0x59325808, 0x59300406, 0x82000c80, - 0x00000012, 0x02021800, 0x001005d8, 0x4933c857, - 0x4943c857, 0x493fc857, 0x4803c857, 0x0c01f804, - 0x5c025800, 0x5c026800, 0x1c01f000, 0x00106ae5, - 0x00106ae7, 0x00106af1, 0x00106b0b, 0x00106ae7, - 0x00106afb, 0x00106b23, 0x00106ae5, 0x00106ae5, - 0x00106b36, 0x00106b2d, 0x00106ae5, 0x00106ae5, - 0x00106ae5, 0x00106ae5, 0x00106ae5, 0x00106b3c, - 0x00106b3c, 0x0201f800, 0x001005d8, 0x0201f800, - 0x00109134, 0x02000800, 0x00102074, 0x0201f800, - 0x00109326, 0x0201f800, 0x0010801c, 0x0201f000, - 0x00107911, 0x812e59c0, 0x02020800, 0x001005d8, - 0x5930021d, 0x82000580, 0x00000003, 0x02000800, - 0x0010912a, 0x0201f000, 0x00107911, 0x0201f800, - 0x00109037, 0x02000000, 0x00107911, 0x592c1204, - 0x82081500, 0x000000ff, 0x82080580, 0x00000055, - 0x02020800, 0x001005d8, 0x49425a06, 0x0201f800, - 0x000202da, 0x0201f000, 0x00107911, 0x59300004, - 0x8400055c, 0x48026004, 0x59300007, 0x8c000500, - 0x02020800, 0x00100e99, 0x0201f800, 0x00109037, - 0x0400000d, 0x4a025a04, 0x00000103, 0x49425a06, - 0x497a5c09, 0x0201f800, 0x001091c6, 0x0201f800, - 0x0010a693, 0x0201f800, 0x000202da, 0x0201f800, - 0x0010912a, 0x0201f000, 0x00107911, 0x59300007, - 0x8c000500, 0x02020800, 0x00100e99, 0x0201f800, - 0x00109037, 0x02020800, 0x0010a3ef, 0x0201f000, - 0x00107911, 0x0201f800, 0x00109037, 0x04000005, - 0x49425a06, 0x497a5c09, 0x0201f800, 0x000202da, - 0x0201f000, 0x00107911, 0x0201f800, 0x00109037, - 0x02020800, 0x0010664f, 0x0201f000, 0x00107911, - 0x0201f800, 0x00109037, 0x04000004, 0x49425a06, - 0x0201f800, 0x000202da, 0x59325817, 0x0201f800, - 0x001007fd, 0x0201f000, 0x00107911, 0x598c000d, - 0x81300580, 0x04000003, 0x497a6007, 0x1c01f000, - 0x59c40004, 0x82000500, 0x0000000c, 0x04000005, - 0x4a038804, 0x0000000c, 0x497b2807, 0x0401f00a, - 0x0401facd, 0x59300403, 0x82000d80, 0x00000040, - 0x04000004, 0x82000580, 0x00000042, 0x04020002, - 0x497a6007, 0x0201f800, 0x001070b9, 0x80000580, - 0x1c01f000, 0x59300804, 0x8c040d3e, 0x04020004, - 0x82000540, 0x00000001, 0x0401f005, 0x4933c857, - 0x84040d3e, 0x48066004, 0x80000580, 0x1c01f000, - 0x59300804, 0x8c040d20, 0x04020004, 0x82000540, - 0x00000001, 0x1c01f000, 0x4933c857, 0x4d380000, - 0x59300804, 0x84040d20, 0x48066004, 0x42027000, - 0x00000049, 0x59300203, 0x82000580, 0x00000003, - 0x04000003, 0x42027000, 0x00000013, 0x0201f800, - 0x000207a1, 0x80000580, 0x5c027000, 0x1c01f000, - 0x59300017, 0x81480580, 0x04020003, 0x59300018, - 0x814c0580, 0x1c01f000, 0x4d2c0000, 0x4d300000, - 0x0401f8c9, 0x4df00000, 0x0201f800, 0x00106062, - 0x59900001, 0x82000500, 0x00000003, 0x0c01f001, - 0x00106bba, 0x00106b9a, 0x00106b98, 0x00106b98, - 0x0201f800, 0x001005d8, 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, - 0x001005d8, 0x4978080c, 0x5c03e000, 0x04000890, - 0x5c026000, 0x5c025800, 0x1c01f000, 0x4d300000, - 0x497b2807, 0x0401f894, 0x4df00000, 0x598c0000, - 0x82000500, 0x00000007, 0x4803c857, 0x0c01f001, - 0x00106bef, 0x00106bd2, 0x00106bdb, 0x00106bdf, - 0x00106bea, 0x00106bef, 0x00106bd0, 0x00106bd0, - 0x0201f800, 0x001005d8, 0x598c000d, 0x80026540, - 0x04000004, 0x0401f81e, 0x02020800, 0x001005d8, - 0x0201f800, 0x001070b9, 0x0401f015, 0x0401f827, - 0x0201f800, 0x001070b9, 0x0401f011, 0x598c000d, - 0x80026540, 0x0400000e, 0x0401f838, 0x04000004, - 0x0401f80f, 0x04000002, 0x0401f81c, 0x0201f800, - 0x001070b9, 0x0401f006, 0x0401f830, 0x02020800, - 0x001005d8, 0x0201f800, 0x001070b9, 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, 0x001005d8, 0x1c01f000, + 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, 0x02020800, 0x001005d8, 0x59bc00ea, - 0x8c000516, 0x040207fe, 0x480778e1, 0x1c01f000, - 0x59bc00ea, 0x8c000516, 0x040207fe, 0x480778e1, - 0x59bc00ea, 0x8c000516, 0x040207fe, 0x480b78e1, - 0x1c01f000, 0x82000d00, 0x80000018, 0x02020800, - 0x001005d0, 0x0201f800, 0x001005d8, 0x00106c97, - 0x00106d3b, 0x00106d55, 0x00106c97, 0x00106c99, - 0x00106cba, 0x00106cd9, 0x00106d0d, 0x00106c97, - 0x00106d39, 0x00106c97, 0x00106c97, 0x00106c97, - 0x00106c97, 0x00106c97, 0x00106c97, 0x0201f800, - 0x001005d8, 0x4d300000, 0x4d900000, 0x4dd00000, - 0x4da40000, 0x4d140000, 0x0201f800, 0x001070d8, - 0x59bc00ea, 0x8c000510, 0x040007fe, 0x59be60e0, - 0x59300004, 0x8c000520, 0x04000011, 0x82000500, - 0xfffefeff, 0x48026004, 0x4a026203, 0x00000003, - 0x0401ffa9, 0x0201f800, 0x00100fd0, 0x5c022800, - 0x5c034800, 0x5c03a000, 0x5c032000, 0x5c026000, - 0x4a0378e4, 0x00000008, 0x0401f795, 0x84000510, - 0x48026004, 0x0401f7f6, 0x4d300000, 0x4d900000, + 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, - 0x001070d8, 0x59bc00ea, 0x8c000510, 0x040007fe, - 0x59be60e0, 0x59300004, 0x8c000520, 0x0400000f, - 0x82000500, 0xfffefeff, 0x48026004, 0x0401ff8a, - 0x0201f800, 0x0010100e, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x5c026000, 0x4a0378e4, - 0x00000008, 0x0401f776, 0x84000510, 0x48026004, - 0x0401f7f6, 0x4d300000, 0x4d2c0000, 0x4d340000, - 0x4da40000, 0x4cd00000, 0x59bc00ea, 0x8c000510, - 0x040007fe, 0x59be60e0, 0x813261c0, 0x02000800, - 0x001005d8, 0x59300004, 0x8c000520, 0x0400001d, - 0x82000500, 0xfffefeff, 0x48026004, 0x59326809, - 0x42034800, 0x0010b544, 0x04011000, 0x4a03c840, - 0x0010b54b, 0x4a03c842, 0x00000012, 0x04011000, - 0x4a03c840, 0x0010b55d, 0x4a03c842, 0x000000ff, - 0x04011000, 0x4a03c840, 0x0010b65c, 0x4a03c842, - 0x000000ff, 0x0401fbf2, 0x5c01a000, 0x5c034800, - 0x5c026800, 0x5c025800, 0x5c026000, 0x1c01f000, - 0x84000510, 0x48026004, 0x5c01a000, 0x5c034800, - 0x5c026800, 0x5c025800, 0x5c026000, 0x1c01f000, - 0x1c01f000, 0x4d300000, 0x4d2c0000, 0x4d340000, - 0x4cd00000, 0x4d900000, 0x4dd00000, 0x4da40000, - 0x4d140000, 0x0401fbc3, 0x59bc00ea, 0x8c000510, - 0x040007fe, 0x59be60e0, 0x813261c0, 0x02000800, - 0x001005d8, 0x59300004, 0x8c000520, 0x0400000f, - 0x82000500, 0xfffefeff, 0x48026004, 0x0201f800, - 0x0010783a, 0x5c022800, 0x5c034800, 0x5c03a000, - 0x5c032000, 0x5c01a000, 0x5c026800, 0x5c025800, - 0x5c026000, 0x1c01f000, 0x84000510, 0x48026004, + 0x00106e2f, 0x59bc00ea, 0x8c000510, 0x040007fe, + 0x59be60e0, 0x59300004, 0x8c000520, 0x04000011, + 0x82000500, 0xfffefeff, 0x48026004, 0x4a026203, + 0x00000003, 0x0401ff9b, 0x0201f800, 0x0010101e, 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, - 0x5c01a000, 0x5c026800, 0x5c025800, 0x5c026000, - 0x1c01f000, 0x0201f800, 0x001005d8, 0x4d300000, - 0x4d380000, 0x42000000, 0x0010b8c4, 0x0201f800, - 0x0010aa47, 0x0401ff14, 0x598e600d, 0x59c40004, - 0x8c000506, 0x04000004, 0x0401f8db, 0x4a038804, - 0x00000008, 0x813261c0, 0x04000006, 0x0401fb87, - 0x42027000, 0x00000014, 0x0201f800, 0x000207a1, - 0x4a0378e4, 0x00000002, 0x5c027000, 0x5c026000, - 0x0401f6f7, 0x4d180000, 0x4d300000, 0x4d380000, + 0x5c026000, 0x4a0378e4, 0x00000008, 0x0401f787, + 0x84000510, 0x48026004, 0x0401f7f6, 0x4d300000, 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, - 0x0401fef9, 0x417a3000, 0x59c40804, 0x83180400, - 0x0010709f, 0x50000000, 0x80040500, 0x0400001b, - 0x42000000, 0x0010b8c5, 0x0201f800, 0x0010aa47, - 0x0401fb70, 0x59926004, 0x0401f859, 0x83180400, - 0x0010709f, 0x50000000, 0x48038804, 0x813261c0, - 0x0400000a, 0x59300004, 0x8c00050c, 0x04020003, - 0x4a026203, 0x00000003, 0x42027000, 0x0000004a, - 0x0201f800, 0x000207a1, 0x59c40004, 0x82000500, - 0x00f80000, 0x04000005, 0x811a3000, 0x83180480, - 0x00000005, 0x040017dd, 0x4a0378e4, 0x00000008, - 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, - 0x5c027000, 0x5c026000, 0x5c023000, 0x0401f6c0, - 0x4d2c0000, 0x4d340000, 0x59326809, 0x598c0800, - 0x82040580, 0x00000004, 0x04020004, 0x838c1400, - 0x00000005, 0x0401f00c, 0x82040580, 0x00000001, - 0x04020004, 0x838c1400, 0x00000009, 0x0401f006, - 0x82040580, 0x00000002, 0x04020022, 0x838c1400, - 0x0000000b, 0x41306800, 0x58340000, 0x80007d40, - 0x0400001c, 0x583c0009, 0x81340580, 0x04020006, + 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, - 0x0401f014, 0x4933c857, 0x483fc857, 0x583c0000, - 0x48006800, 0x49307800, 0x443c1000, 0x80000580, + 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, 0x0401fabb, 0x04020007, - 0x0401fabf, 0x04000022, 0x48038804, 0x0201f800, - 0x0010107a, 0x0401f042, 0x4a038803, 0x00000008, + 0x4c040000, 0x4c080000, 0x0401fac2, 0x04020007, + 0x0401fac6, 0x04000022, 0x48038804, 0x0201f800, + 0x001010ca, 0x0401f042, 0x4a038803, 0x00000008, 0x59c40003, 0x82000500, 0x00000003, 0x040007fd, - 0x8c000502, 0x04020007, 0x0401fab1, 0x04000014, - 0x48038804, 0x0201f800, 0x0010107a, 0x0401f034, + 0x8c000502, 0x04020007, 0x0401fab8, 0x04000014, + 0x48038804, 0x0201f800, 0x001010ca, 0x0401f034, 0x59c80040, 0x8400056a, 0x48039040, 0x59c80040, 0x8c00052a, 0x040207fe, 0x59c40005, 0x82000500, 0xc0000000, 0x04000006, 0x59c400a3, 0x84000540, 0x480388a3, 0x4a038805, 0xc0000000, 0x0201f800, - 0x0010101d, 0x4a03a005, 0x30000000, 0x59d00006, + 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, 0x00101068, 0x83180400, - 0x0010709f, 0x50000000, 0x48038804, 0x80000580, - 0x4df00000, 0x0201f800, 0x00106062, 0x5c03e000, + 0x040207fd, 0x0201f800, 0x001010b8, 0x83180400, + 0x00106df6, 0x50000000, 0x48038804, 0x80000580, + 0x4df00000, 0x0201f800, 0x00105d9b, 0x5c03e000, 0x5c001000, 0x5c000800, 0x480b8808, 0x48079040, 0x1c01f000, 0x4803c856, 0x59c80840, 0x82040540, 0x00000010, 0x48039040, 0x59c41008, 0x82080500, @@ -7103,287 +6931,297 @@ uint32_t risc_code01[] = { 0xc0000000, 0x04000007, 0x59c400a3, 0x84000540, 0x480388a3, 0x4a038805, 0xc0000000, 0x80000580, 0x497b2807, 0x5c001000, 0x5c000800, 0x480b8808, - 0x48079040, 0x1c01f000, 0x4933c857, 0x4d900000, - 0x4dd00000, 0x4da40000, 0x4d140000, 0x0401fdee, - 0x4df00000, 0x0401fa6f, 0x59900004, 0x800001c0, + 0x48079040, 0x1c01f000, 0x5c000000, 0x4c000000, + 0x4803c857, 0x491bc857, 0x4933c857, 0x4d900000, + 0x4dd00000, 0x4da40000, 0x4d140000, 0x0401fdd1, + 0x4df00000, 0x0401fa72, 0x59900004, 0x800001c0, 0x04000011, 0x81300580, 0x0402000f, 0x59300004, - 0x84000520, 0x48026004, 0x0401ff51, 0x04020009, - 0x5c03e000, 0x04000dd6, 0x80000580, 0x5c022800, + 0x84000520, 0x48026004, 0x0401ff4d, 0x04020009, + 0x5c03e000, 0x04000db9, 0x80000580, 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, 0x1c01f000, - 0x0401fd0e, 0x42027000, 0x00000049, 0x59300004, + 0x0401fcf1, 0x42027000, 0x00000049, 0x59300004, 0x84000520, 0x48026004, 0x8c00050c, 0x02020800, - 0x000207a1, 0x5c03e000, 0x04000dc5, 0x82000540, + 0x000208d8, 0x5c03e000, 0x04000da8, 0x82000540, 0x00000001, 0x5c022800, 0x5c034800, 0x5c03a000, - 0x5c032000, 0x1c01f000, 0x4933c857, 0x0401fdc6, + 0x5c032000, 0x1c01f000, 0x4933c857, 0x0401fda9, 0x4df00000, 0x598c000d, 0x80026540, 0x04000012, - 0x59300004, 0x84000520, 0x48026004, 0x0401ff8a, - 0x04000017, 0x0401fd26, 0x42027000, 0x00000013, - 0x59300004, 0x8c00050c, 0x02020800, 0x000207a1, - 0x5c03e000, 0x04000daa, 0x82000540, 0x00000001, + 0x59300004, 0x84000520, 0x48026004, 0x0401ff86, + 0x04000017, 0x0401fd09, 0x42027000, 0x00000013, + 0x59300004, 0x8c00050c, 0x02020800, 0x000208d8, + 0x5c03e000, 0x04000d8d, 0x82000540, 0x00000001, 0x1c01f000, 0x836c1580, 0x00000001, 0x040007f9, 0x836c1580, 0x00000004, 0x040007f6, 0x42001000, - 0x00104148, 0x0201f800, 0x00105f90, 0x5c03e000, - 0x04000d9b, 0x80000580, 0x1c01f000, 0x4d300000, - 0x4d180000, 0x4d3c0000, 0x0401fd9f, 0x4df00000, - 0x4a0378e4, 0x0000000f, 0x0401f9ff, 0x417a3000, + 0x00103f62, 0x0201f800, 0x00105cc9, 0x5c03e000, + 0x04000d7e, 0x80000580, 0x1c01f000, 0x4d300000, + 0x4d180000, 0x4d3c0000, 0x0401fd82, 0x4df00000, + 0x4a0378e4, 0x0000000f, 0x0401fa02, 0x417a3000, 0x59926004, 0x813261c0, 0x04000010, 0x417a7800, - 0x0201f800, 0x001048d9, 0x0400000a, 0x59300c06, + 0x0201f800, 0x00104728, 0x0400000a, 0x59300c06, 0x82040580, 0x00000003, 0x04000004, 0x82040580, 0x00000006, 0x04020003, 0x42027800, 0x00000002, - 0x0201f800, 0x00108be3, 0x811a3000, 0x83180480, + 0x0201f800, 0x00108997, 0x811a3000, 0x83180480, 0x00000005, 0x040017eb, 0x42000800, 0x00000040, - 0x0201f800, 0x00101345, 0x4a0378e4, 0x0000000a, - 0x5c03e000, 0x04000d72, 0x5c027800, 0x5c023000, + 0x0201f800, 0x00101395, 0x4a0378e4, 0x0000000a, + 0x5c03e000, 0x04000d55, 0x5c027800, 0x5c023000, 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000, - 0x0401fd75, 0x4df00000, 0x59c80840, 0x82040540, + 0x0401fd58, 0x4df00000, 0x59c80840, 0x82040540, 0x00000010, 0x48039040, 0x59c41008, 0x82080500, 0xffffff7f, 0x48038808, 0x4c040000, 0x4c080000, - 0x42001000, 0x00000003, 0x0401f9c2, 0x598e600d, - 0x813261c0, 0x04020f9d, 0x040009c7, 0x497b2807, + 0x42001000, 0x00000003, 0x0401f9c5, 0x598e600d, + 0x813261c0, 0x04020f9d, 0x040009ca, 0x497b2807, 0x0401f80a, 0x5c001000, 0x5c000800, 0x480b8808, - 0x84040d74, 0x48079040, 0x5c03e000, 0x04000d50, + 0x84040d74, 0x48079040, 0x5c03e000, 0x04000d33, 0x5c026000, 0x1c01f000, 0x4d380000, 0x4d180000, 0x4d300000, 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, 0x59c41004, 0x480bc857, 0x82080500, 0x00003ff0, 0x04000025, 0x417a3000, 0x4c080000, - 0x0201f800, 0x00106062, 0x5c001000, 0x82080500, + 0x0201f800, 0x00105d9b, 0x5c001000, 0x82080500, 0x00000210, 0x04020004, 0x811a3000, 0x80081102, - 0x0401f7f7, 0x0401f9c3, 0x59926004, 0x4933c857, + 0x0401f7f7, 0x0401f9c6, 0x59926004, 0x4933c857, 0x813261c0, 0x04020005, 0x59c400a3, 0x8c00051a, - 0x02000800, 0x001005d8, 0x0401fea5, 0x04000009, - 0x0401fc6a, 0x42027000, 0x00000049, 0x59300004, - 0x8c00050c, 0x02020800, 0x000207a1, 0x0401f007, + 0x02000800, 0x00100615, 0x0401fea1, 0x04000009, + 0x0401fc4d, 0x42027000, 0x00000049, 0x59300004, + 0x8c00050c, 0x02020800, 0x000208d8, 0x0401f007, 0x42027000, 0x0000004a, 0x4a026203, 0x00000003, - 0x0201f800, 0x000207a1, 0x5c022800, 0x5c034800, + 0x0201f800, 0x000208d8, 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, 0x5c026000, 0x5c023000, 0x5c027000, 0x1c01f000, 0x4d300000, 0x4d180000, - 0x4d900000, 0x0401fd1c, 0x42001000, 0x00000000, - 0x598c0000, 0x82000580, 0x00000005, 0x04000971, + 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, 0x00106054, + 0x42000800, 0x00001b58, 0x0201f800, 0x00105d8d, 0x811a3000, 0x83180480, 0x00000005, 0x040017ea, - 0x59c81040, 0x84081534, 0x480b9040, 0x0401fcf0, + 0x59c81040, 0x84081534, 0x480b9040, 0x0401fcd3, 0x5c032000, 0x5c023000, 0x5c026000, 0x1c01f000, 0x4933c857, 0x4d900000, 0x4dd00000, 0x4da40000, - 0x4d140000, 0x4d380000, 0x0401fcef, 0x4df00000, + 0x4d140000, 0x4d380000, 0x0401fcd2, 0x4df00000, 0x59300004, 0x8c00053e, 0x04020007, 0x8c000520, - 0x04000025, 0x0201f800, 0x00106b6c, 0x04000022, - 0x0401f02a, 0x598c000d, 0x81300580, 0x04000011, - 0x0201f800, 0x00108cd6, 0x04020024, 0x0401f918, - 0x04000022, 0x48038804, 0x0401f95e, 0x0201f800, - 0x0010107a, 0x0401fc0d, 0x42027000, 0x00000049, - 0x59300004, 0x8c00050c, 0x0402000d, 0x0401f00e, - 0x59c40004, 0x8c000504, 0x04000014, 0x4a038804, - 0x00000004, 0x0401fc36, 0x42027000, 0x00000013, - 0x59300004, 0x8c00050c, 0x04000003, 0x0201f800, - 0x000207a1, 0x5c03e000, 0x04000cb9, 0x5c027000, - 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, - 0x80000580, 0x1c01f000, 0x5c03e000, 0x04000cb0, + 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, 0x82000540, 0x00000001, 0x1c01f000, - 0x497b2807, 0x0401fcb0, 0x59c400af, 0x800001c0, - 0x04020004, 0x0401fca2, 0x0201f000, 0x001014fb, - 0x598c000f, 0x82001480, 0x00000002, 0x04021007, - 0x80000000, 0x4803180f, 0x80000580, 0x0201f800, - 0x0010604d, 0x0400000e, 0x0401fed8, 0x0402000c, - 0x0401fdd4, 0x0400000a, 0x0201f800, 0x0010a9c7, - 0x0401f916, 0x4d380000, 0x42027000, 0x00000014, - 0x0201f800, 0x000207a1, 0x5c027000, 0x0401fc88, - 0x0201f000, 0x001014fb, 0x4d900000, 0x4dd00000, - 0x4da40000, 0x4d140000, 0x4d300000, 0x0201f800, - 0x00106062, 0x0401fc88, 0x59c400af, 0x800001c0, - 0x04000027, 0x0401f907, 0x59926004, 0x4933c857, - 0x59300004, 0x8c000516, 0x0400000b, 0x0401fe8b, - 0x0402001f, 0x0201f800, 0x00106b8a, 0x0401fc70, - 0x42000800, 0x80000804, 0x0201f800, 0x00106721, - 0x0401f017, 0x42001800, 0x00007530, 0x0401f8c1, - 0x04020004, 0x0201f800, 0x00106052, 0x0401f010, - 0x0401fe7a, 0x0402000e, 0x0201f800, 0x0010a9c7, - 0x59300004, 0x8c00050c, 0x04020003, 0x4a026203, - 0x00000003, 0x4d380000, 0x42027000, 0x0000004a, - 0x0201f800, 0x000207a1, 0x5c027000, 0x0401fc54, - 0x5c026000, 0x5c022800, 0x5c034800, 0x5c03a000, - 0x5c032000, 0x0201f000, 0x001014fb, 0x4d900000, + 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, - 0x4d2c0000, 0x0401fc50, 0x0401f8d2, 0x59926004, - 0x4933c857, 0x0401f880, 0x04000016, 0x0201f800, - 0x00106062, 0x813261c0, 0x04000034, 0x59325808, - 0x812e59c0, 0x02000800, 0x001005d8, 0x0201f800, - 0x0010513b, 0x0402001d, 0x592c0208, 0x84000550, - 0x48025a08, 0x0201f800, 0x00105258, 0x04020027, - 0x592c0208, 0x84000510, 0x48025a08, 0x0401f023, - 0x0201f800, 0x00106052, 0x0401f020, 0x0201f800, - 0x0010a9c7, 0x0401fd9e, 0x592c0208, 0x84000550, - 0x48025a08, 0x4d380000, 0x42027000, 0x0000004a, - 0x4a026203, 0x00000003, 0x0201f800, 0x000207a1, - 0x5c027000, 0x0401f011, 0x59900006, 0x82000500, - 0xffff0000, 0x040207ee, 0x59c408af, 0x82040480, - 0x000003e8, 0x040217ea, 0x59900006, 0x82000400, - 0x00010000, 0x48032006, 0x0201f800, 0x00106052, - 0x0201f800, 0x0010411d, 0x5c025800, 0x5c026000, - 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, - 0x0401f403, 0x4d300000, 0x4d2c0000, 0x0401fc0a, - 0x598e600d, 0x4933c857, 0x59c41004, 0x8c081500, - 0x04000007, 0x0201f800, 0x0010513b, 0x04020007, - 0x0201f800, 0x00105258, 0x0402002f, 0x0201f800, - 0x0010604d, 0x0401f02c, 0x598c000f, 0x80000540, - 0x04020011, 0x59c408af, 0x82040480, 0x000003e8, - 0x0402100d, 0x598c080f, 0x80040800, 0x4807180f, - 0x0201f800, 0x0010604d, 0x42000000, 0x0010b852, - 0x0201f800, 0x0010aa47, 0x0201f800, 0x0010411d, - 0x0401f019, 0x0401fdb4, 0x813261c0, 0x04020003, - 0x0401f849, 0x0401f014, 0x0201f800, 0x0010a9c7, - 0x59300406, 0x82000580, 0x00000003, 0x04020007, - 0x59325808, 0x812e59c0, 0x04000004, 0x592c0208, - 0x84000550, 0x48025a08, 0x0401f854, 0x4d380000, - 0x42027000, 0x00000014, 0x0201f800, 0x000207a1, - 0x5c027000, 0x5c025800, 0x5c026000, 0x0201f000, - 0x00106c4b, 0x59c40804, 0x83180400, 0x00107095, - 0x50000000, 0x80040500, 0x1c01f000, 0x59c40804, - 0x83180400, 0x0010709a, 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, 0x00106c55, 0x4df00000, - 0x480b1800, 0x5c03e000, 0x02000800, 0x00106c4b, - 0x1c01f000, 0x4803c856, 0x0201f800, 0x00106c55, - 0x4df00000, 0x497b180d, 0x497b1803, 0x497b180e, - 0x497b180f, 0x497b1810, 0x598c0000, 0x82000580, - 0x00000003, 0x04000009, 0x836c0580, 0x00000002, - 0x04020004, 0x4a031800, 0x00000005, 0x0401f003, - 0x4a031800, 0x00000000, 0x5c03e000, 0x02000800, - 0x00106c4b, 0x1c01f000, 0x59300004, 0x8c00050c, - 0x04020003, 0x4a026203, 0x00000001, 0x1c01f000, - 0x83180480, 0x00000005, 0x02021800, 0x001005d8, - 0x491bc857, 0x811b20c8, 0x83932400, 0x0000bf32, - 0x811ba0ca, 0x83d3a400, 0x00007600, 0x83180400, - 0x001070ea, 0x50034800, 0x811a28c2, 0x83162c00, - 0x00006100, 0x1c01f000, 0x0010b75b, 0x0010b772, - 0x0010b789, 0x0010b7a0, 0x0010b7b7, 0x4933c857, - 0x59300406, 0x82000c80, 0x00000012, 0x04021016, - 0x4803c857, 0x04011000, 0x0c01f001, 0x00107109, - 0x00107198, 0x001074d1, 0x00107556, 0x00107198, - 0x001074d1, 0x00107556, 0x00107109, 0x00107198, - 0x00107109, 0x00107109, 0x00107109, 0x00107109, - 0x00107109, 0x00107109, 0x00107109, 0x0010710f, - 0x0010710f, 0x0201f800, 0x00106c55, 0x0201f800, - 0x00106bbf, 0x0201f000, 0x00106c4b, 0x42001000, - 0x0010b7f6, 0x50081000, 0x4930100c, 0x58080002, - 0x82000580, 0x00000100, 0x04020032, 0x59325808, - 0x812e59c0, 0x02000800, 0x001005d8, 0x59326809, - 0x813669c0, 0x04000019, 0x592c040b, 0x82000500, - 0x0000e000, 0x04000003, 0x0401fba8, 0x0401f002, - 0x0401fb98, 0x42001000, 0x0010b7f6, 0x50081000, - 0x4930100b, 0x492c100a, 0x82d00400, 0x00000006, - 0x48001003, 0x592c000d, 0x80000104, 0x48001004, - 0x592c000e, 0x48001007, 0x592c000f, 0x48001008, - 0x0201f000, 0x00100858, 0x42026800, 0x0010be0d, - 0x592c080a, 0x48066802, 0x82040500, 0x00ffff00, - 0x04000007, 0x497a6a12, 0x59a81010, 0x82081500, - 0x00ffff00, 0x80080580, 0x040207dc, 0x82040d00, - 0x000000ff, 0x800408d0, 0x48066a12, 0x0401f7d7, - 0x1c01f000, 0x4d2c0000, 0x4d300000, 0x4c580000, - 0x4c540000, 0x4c500000, 0x5832580a, 0x812e59c0, - 0x02000800, 0x001005d8, 0x58300002, 0x4a006002, - 0x00000100, 0x82000580, 0x00000100, 0x0402001c, - 0x5830000b, 0x5832600c, 0x81300580, 0x04020010, - 0x0401f828, 0x04020010, 0x592c080d, 0x80040904, - 0x4004b000, 0x4200a000, 0x0010b54b, 0x4050a800, - 0x0201f800, 0x0010ab28, 0x42001000, 0x0000dc00, - 0x0201f800, 0x001078bc, 0x0401f003, 0x0401f819, - 0x04000fa3, 0x5c00a000, 0x5c00a800, 0x5c00b000, - 0x5c026000, 0x5c025800, 0x1c01f000, 0x5830000b, - 0x5832600c, 0x81300580, 0x040207f5, 0x0401f80d, - 0x040207f5, 0x0201f800, 0x001068d3, 0x02020800, - 0x001005d8, 0x4a025a06, 0x00000002, 0x0201f800, - 0x000202da, 0x0201f800, 0x00107911, 0x0401f7ea, - 0x0201f800, 0x00106c55, 0x4df00000, 0x598c000d, - 0x81300580, 0x04020009, 0x598c0005, 0x81300580, - 0x04020006, 0x5c03e000, 0x02000800, 0x00106c4b, - 0x80000580, 0x1c01f000, 0x5c03e000, 0x02000800, - 0x00106c4b, 0x82000540, 0x00000001, 0x1c01f000, - 0x59300403, 0x82000c80, 0x00000056, 0x02021800, - 0x001005d8, 0x4803c857, 0x0c01f001, 0x00107302, - 0x0010731d, 0x0010732e, 0x00107431, 0x001073f1, - 0x001073f5, 0x00107406, 0x0010741a, 0x0010740f, - 0x0010741a, 0x00107455, 0x0010741a, 0x00107497, - 0x0010741a, 0x001074a5, 0x0010741a, 0x0010740f, - 0x0010741a, 0x001074a9, 0x001071f5, 0x001071f5, - 0x001071f5, 0x001071f5, 0x001071f5, 0x001071f5, - 0x001071f5, 0x001071f5, 0x001071f5, 0x001071f5, - 0x001071f5, 0x00107574, 0x00107593, 0x0010759d, - 0x001071f5, 0x001075b3, 0x00107406, 0x001071f5, - 0x00107406, 0x0010741a, 0x001071f5, 0x0010732e, - 0x00107431, 0x001071f5, 0x00107603, 0x0010741a, - 0x001071f5, 0x00107613, 0x0010741a, 0x001071f5, - 0x0010740f, 0x001072f3, 0x001071f7, 0x001071f5, - 0x0010762a, 0x0010765d, 0x001076d7, 0x001071f5, - 0x001076e7, 0x00107404, 0x001076da, 0x001071f5, - 0x001075bf, 0x00107700, 0x001071f5, 0x00107735, - 0x00107788, 0x001071f5, 0x0010720c, 0x00107265, - 0x00107272, 0x001071f5, 0x00107406, 0x001071f5, - 0x001072b9, 0x001072c4, 0x001071f5, 0x001071f5, - 0x00107220, 0x00107245, 0x001077c7, 0x00107808, - 0x0010782e, 0x001071f5, 0x001071f5, 0x001071f5, - 0x001077fc, 0x0201f800, 0x001005d8, 0x0401fac5, - 0x59325808, 0x592c0009, 0x4801a006, 0x592c000a, - 0x4801a007, 0x592c000b, 0x4801a008, 0x592c000c, - 0x4801a009, 0x592c000d, 0x4801a00a, 0x4979a00b, - 0x592c0809, 0x82040d00, 0x00000fff, 0x80040904, - 0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc, - 0x4a026202, 0x0000ffff, 0x0401faae, 0x4d2c0000, - 0x4a01a006, 0x05000000, 0x59325808, 0x592c0009, - 0x4801a007, 0x592c000a, 0x4801a008, 0x592c000b, - 0x4801a009, 0x42000800, 0x00000004, 0x42001000, - 0x0000dc00, 0x5c025800, 0x0201f000, 0x001078bc, + 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, - 0x0401fa98, 0x59325808, 0x5930040b, 0x800000c2, - 0x4200a800, 0x0010b54b, 0x592cb205, 0x832ca400, - 0x00000006, 0x0201f800, 0x0010ab17, 0x40580000, - 0x8054ac00, 0x592c0001, 0x80000540, 0x04000003, - 0x40025800, 0x0401f7f5, 0x4200a000, 0x0010b54b, - 0x4050a800, 0x5930b40b, 0x0201f800, 0x0010ab28, - 0x59300c0b, 0x42001000, 0x0000dc00, 0x5c025800, - 0x5c00a800, 0x5c00b000, 0x5c00a000, 0x0201f000, - 0x001078bc, 0x4c580000, 0x4c500000, 0x4c540000, - 0x4d2c0000, 0x42034800, 0x0010b544, 0x0401fa7f, - 0x59325808, 0x4a025805, 0x02000000, 0x592c0802, + 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, 0x0010ab17, 0x40580000, + 0x00000005, 0x0201f800, 0x0010a93e, 0x40580000, 0x8054ac00, 0x592e5801, 0x41780000, 0x812e5d40, 0x040207f6, 0x42001000, 0x0000dc00, 0x5c025800, 0x5c00a800, 0x5c00b000, 0x5c00a000, 0x0201f000, - 0x001078bc, 0x0401fa57, 0x4a01a006, 0x78000000, + 0x0010763b, 0x0401fa57, 0x4a01a006, 0x78000000, 0x5930001c, 0x840001c0, 0x4801a407, 0x4979a207, 0x42000800, 0x00000002, 0x42001000, 0x0000dc00, - 0x0201f000, 0x001078bc, 0x4c580000, 0x4c540000, + 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, 0x0010b4eb, 0x4a03c842, 0x0000000d, - 0x42001800, 0x0010b4eb, 0x0201f800, 0x001007af, - 0x42000000, 0x0000df00, 0x4200a000, 0x0010b4eb, - 0x0401f00d, 0x4a03c840, 0x0010b4f8, 0x4a03c842, - 0x0000000d, 0x42001800, 0x0010b4f8, 0x0201f800, - 0x001007af, 0x42000000, 0x0000e000, 0x4200a000, - 0x0010b4f8, 0x82000540, 0x00000010, 0x4801a407, + 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, 0x0010ab17, + 0x82d0ac00, 0x0000000c, 0x0201f800, 0x0010a93e, 0x42000800, 0x00000013, 0x42001000, 0x0000dc00, 0x5c00a000, 0x5c00a800, 0x5c00b000, 0x0201f000, - 0x001078bc, 0x0401fa03, 0x4a01a006, 0x63000028, + 0x0010763b, 0x0401fa03, 0x4a01a006, 0x63000028, 0x5930001c, 0x4801a007, 0x42000800, 0x00000002, - 0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc, + 0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b, 0x0401fa06, 0x41780000, 0x41780800, 0x42002000, 0x00080000, 0x0c01f81b, 0x80000000, 0x80040800, 0x42001000, 0x0000000c, 0x59841802, 0x8c0c1d00, @@ -7391,28 +7229,28 @@ uint32_t risc_code01[] = { 0x80000000, 0x80040800, 0x82081400, 0x00000004, 0x82080540, 0x02000000, 0x4801a006, 0x800408e0, 0x5930001c, 0x80040540, 0x4801a007, 0x80080904, - 0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc, - 0x001072e9, 0x001072eb, 0x001072ed, 0x001072ef, - 0x001072f1, 0x4811a008, 0x1c01f000, 0x4811a009, + 0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b, + 0x00107061, 0x00107063, 0x00107065, 0x00107067, + 0x00107069, 0x4811a008, 0x1c01f000, 0x4811a009, 0x1c01f000, 0x4811a00a, 0x1c01f000, 0x4811a00b, 0x1c01f000, 0x4811a00c, 0x1c01f000, 0x4a026009, - 0x0010be0d, 0x59a80010, 0x82000500, 0x000000ff, - 0x800000d0, 0x42026800, 0x0010be0d, 0x48026a12, - 0x0401fa3b, 0x41780800, 0x42001000, 0x00005c00, - 0x0201f000, 0x001078bc, 0x0401f9ba, 0x4a01a006, + 0x0010bc0c, 0x59a80010, 0x82000500, 0x000000ff, + 0x800000d0, 0x42026800, 0x0010bc0c, 0x48026a12, + 0x0401fa3c, 0x41780800, 0x42001000, 0x00005c00, + 0x0201f000, 0x0010763b, 0x0401f9ba, 0x4a01a006, 0x52000000, 0x4979a007, 0x599c0017, 0x8c000500, - 0x04000005, 0x599c0402, 0x0201f800, 0x001015da, + 0x04000005, 0x599c0402, 0x0201f800, 0x00101644, 0x4805a007, 0x59a80002, 0x4801a008, 0x59a80003, 0x4801a009, 0x59a80000, 0x4801a00a, 0x59a80001, 0x4801a00b, 0x59a80010, 0x4801a00c, 0x42000800, 0x00000007, 0x42001000, 0x0000dc00, 0x0201f000, - 0x001078bc, 0x4a026202, 0x0000ffff, 0x0401f99d, + 0x0010763b, 0x4a026202, 0x0000ffff, 0x0401f99d, 0x4a01a006, 0x05000000, 0x59a80010, 0x4801a007, 0x59a80002, 0x59a80803, 0x4801a008, 0x4805a009, 0x42000800, 0x00000004, 0x42001000, 0x0000dc00, - 0x0201f000, 0x001078bc, 0x4a026202, 0x0000ffff, + 0x0201f000, 0x0010763b, 0x4a026202, 0x0000ffff, 0x0401f98c, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x001048f6, 0x5c027800, 0x4a01a006, 0x03000000, + 0x00104745, 0x5c027800, 0x4a01a006, 0x03000000, 0x59340403, 0x82000580, 0x000007fe, 0x0402006e, 0x4a01a006, 0x04000000, 0x81a40800, 0x4a000800, 0x22fffffe, 0x5934000a, 0x84000500, 0x4802680a, @@ -7422,18 +7260,18 @@ uint32_t risc_code01[] = { 0x8c040d16, 0x04000002, 0x8400056a, 0x4801a008, 0x4a01a009, 0x00002710, 0x59a8002d, 0x4801a00a, 0x0401f039, 0x59a8002a, 0x4801a007, 0x0201f800, - 0x0010513b, 0x04020009, 0x497b8880, 0x82000500, - 0x0000ffff, 0x4c000000, 0x0201f800, 0x00101606, + 0x00104e0d, 0x04020009, 0x497b8880, 0x82000500, + 0x0000ffff, 0x4c000000, 0x0201f800, 0x00101670, 0x5c000000, 0x48038880, 0x59a8002b, 0x0201f800, - 0x0010513b, 0x04020004, 0x82000500, 0x37ffffff, + 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, 0x0010b8fa, + 0x4200b000, 0x00000004, 0x4200a000, 0x0010b6f9, 0x82d0ac00, 0x0000001f, 0x4c000000, 0x0201f800, - 0x0010ab17, 0x5c000000, 0x5c00a800, 0x5c00a000, + 0x0010a93e, 0x5c000000, 0x5c00a800, 0x5c00a000, 0x5c00b000, 0x8400057a, 0x4801a008, 0x4979a009, 0x4979a00a, 0x59a80002, 0x59a80803, 0x4801a00b, 0x4805a00c, 0x59a80000, 0x59a80801, 0x4801a00d, @@ -7444,10 +7282,10 @@ uint32_t risc_code01[] = { 0x0401f043, 0x59a80026, 0x8c000508, 0x0400000d, 0x59a8002a, 0x82000500, 0x0000ffff, 0x59c40880, 0x80040d80, 0x04000007, 0x497b8880, 0x4c000000, - 0x0201f800, 0x00101606, 0x5c000000, 0x48038880, + 0x0201f800, 0x00101670, 0x5c000000, 0x48038880, 0x59a8002a, 0x4801a007, 0x4c640000, 0x4d2c0000, - 0x59a8c82b, 0x0201f800, 0x00109037, 0x0400000d, - 0x0201f800, 0x00109597, 0x0402000a, 0x592c0207, + 0x59a8c82b, 0x0201f800, 0x00108df4, 0x0400000d, + 0x0201f800, 0x00109360, 0x0402000a, 0x592c0207, 0x8c00050e, 0x04000007, 0x8264cd00, 0x0000ffff, 0x592c0009, 0x82000500, 0xffff0000, 0x8064cd40, 0x4865a008, 0x5c025800, 0x5c00c800, 0x59a8002c, @@ -7459,14 +7297,14 @@ uint32_t risc_code01[] = { 0x4801a017, 0x59a8002f, 0x4801a018, 0x59a80030, 0x4801a019, 0x59a80031, 0x4801a01a, 0x42000800, 0x0000001d, 0x42001000, 0x0000dc00, 0x0201f000, - 0x001078bc, 0x0401f8cb, 0x4a01a006, 0x50000000, + 0x0010763b, 0x0401f8cb, 0x4a01a006, 0x50000000, 0x0401f7b5, 0x0401f8c7, 0x4a01a406, 0x21000010, 0x4a01a206, 0x00000014, 0x4979a007, 0x4979a008, 0x4979a009, 0x4979a00a, 0x42000800, 0x00000005, - 0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc, + 0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b, 0x0401f8bf, 0x0401f002, 0x0401f8c4, 0x4a01a006, 0x02000000, 0x42000800, 0x00000001, 0x42001000, - 0x0000dc00, 0x0201f000, 0x001078bc, 0x0401f8bb, + 0x0000dc00, 0x0201f000, 0x0010763b, 0x0401f8bb, 0x4a01a006, 0x02000000, 0x59300403, 0x82000580, 0x00000031, 0x04020794, 0x81a40800, 0x4a000801, 0x00fffffe, 0x0401f72b, 0x0401f8b0, 0x4a01a006, @@ -7475,7 +7313,7 @@ uint32_t risc_code01[] = { 0x5930021a, 0x80000540, 0x04000003, 0x4801a207, 0x0401f003, 0x4a01a207, 0x00002a00, 0x42000800, 0x00000002, 0x42001000, 0x0000dc00, 0x0201f000, - 0x001078bc, 0x4a026202, 0x0000ffff, 0x0401f889, + 0x0010763b, 0x4a026202, 0x0000ffff, 0x0401f889, 0x4a01a406, 0x00002010, 0x4a01a206, 0x00000014, 0x4a01a407, 0x00000800, 0x4a01a207, 0x00002000, 0x80000580, 0x599c0817, 0x8c040d0a, 0x04020003, @@ -7500,1447 +7338,1462 @@ uint32_t risc_code01[] = { 0x8c08150a, 0x04020004, 0x8c040d0a, 0x04000002, 0x8400054e, 0x8c040d1c, 0x04000002, 0x84000552, 0x4801a20a, 0x42000800, 0x00000005, 0x42001000, - 0x0000dc00, 0x0201f000, 0x001078bc, 0x0401f833, + 0x0000dc00, 0x0201f000, 0x0010763b, 0x0401f833, 0x4a01a006, 0x02100014, 0x4a01a007, 0x01000000, 0x4979a008, 0x4979a009, 0x4979a00a, 0x42000800, 0x00000005, 0x42001000, 0x0000dc00, 0x0201f000, - 0x001078bc, 0x0401f825, 0x4a01a006, 0x02000000, + 0x0010763b, 0x0401f825, 0x4a01a006, 0x02000000, 0x0401f65d, 0x4933c857, 0x0401f820, 0x4a01a006, 0x01000000, 0x4a01a407, 0x0000000b, 0x42000800, 0x00000002, 0x42001000, 0x0000dc00, 0x0201f000, - 0x001078bc, 0x42005000, 0x32000000, 0x42006000, - 0x08290000, 0x41786800, 0x41787800, 0x0401f3df, + 0x0010763b, 0x42005000, 0x32000000, 0x42006000, + 0x08290000, 0x41786800, 0x41787800, 0x0401f3e6, 0x42005000, 0x22000000, 0x42006000, 0x01290000, - 0x41786800, 0x41787800, 0x0401f3d8, 0x42005000, + 0x41786800, 0x41787800, 0x0401f3df, 0x42005000, 0x33000000, 0x42006000, 0x08980000, 0x41786800, - 0x41787800, 0x0401f3d1, 0x42005000, 0x23000000, + 0x41787800, 0x0401f3d8, 0x42005000, 0x23000000, 0x42006000, 0x01980000, 0x41786800, 0x41787800, - 0x0401f3ca, 0x59300403, 0x82000c80, 0x00000085, - 0x02001800, 0x001005d8, 0x82000c80, 0x00000093, - 0x02021800, 0x001005d8, 0x82000480, 0x00000085, - 0x0c01f001, 0x001074eb, 0x001074ed, 0x001074fb, - 0x001074eb, 0x001074eb, 0x001074eb, 0x001074eb, - 0x001074eb, 0x001074eb, 0x001074eb, 0x001074eb, - 0x001074eb, 0x001074eb, 0x00107506, 0x0201f800, - 0x001005d8, 0x4933c857, 0x0401f850, 0x59300402, - 0x4801a407, 0x5930001c, 0x4801a207, 0x4979a408, - 0x4a01a208, 0x0000ffff, 0x42000800, 0x00000003, - 0x42001000, 0x0000dc00, 0x0401f3c2, 0x4933c857, - 0x0401f84e, 0x4a01a406, 0x00000003, 0x4a01a206, - 0x00000300, 0x42000800, 0x00000001, 0x42001000, - 0x0000dc00, 0x0401f3b7, 0x4d2c0000, 0x59325808, - 0x4933c857, 0x492fc857, 0x812e59c0, 0x02000800, - 0x001005d8, 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, 0x001005d8, 0x42001000, - 0x00000007, 0x42000800, 0x00000001, 0x832c1c00, - 0x00000009, 0x500c0000, 0x4401a000, 0x800c1800, - 0x80d1a000, 0x80081040, 0x040207fb, 0x42001000, - 0x0000dc00, 0x5c025800, 0x0401f386, 0x42005000, - 0x81000000, 0x42006000, 0x00090000, 0x41786800, - 0x41787800, 0x0401f35d, 0x42005000, 0x84000000, - 0x42006000, 0x00990000, 0x59300406, 0x82000580, - 0x00000005, 0x04000002, 0x8430652e, 0x41786800, - 0x41787800, 0x0401f351, 0x42005000, 0x85000000, - 0x42006000, 0x00990000, 0x59300406, 0x82000580, - 0x00000005, 0x04000002, 0x8430652e, 0x41786800, - 0x41787800, 0x0401f345, 0x59300403, 0x82000c80, - 0x00000053, 0x02021800, 0x001005d8, 0x82000480, - 0x0000004b, 0x02001800, 0x001005d8, 0x59326809, - 0x59368c03, 0x4803c857, 0x0c01f001, 0x001075da, - 0x001075e2, 0x001075ea, 0x001075f2, 0x0010756b, - 0x0010756b, 0x0010756b, 0x001075d2, 0x0201f800, - 0x001005d8, 0x42005000, 0x06000000, 0x42006000, - 0x08290000, 0x41786800, 0x41787800, 0x0401f327, - 0x4933c857, 0x0401ff47, 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, 0x0401f32a, 0x0401ff29, - 0x4a01a006, 0x0f000000, 0x5930001c, 0x4801a007, - 0x42000800, 0x00000002, 0x42001000, 0x0000dc00, - 0x0401f320, 0x0401ff2d, 0x4a01a006, 0x02000000, - 0x59c40085, 0x48031004, 0x59880000, 0x4801a007, - 0x59880001, 0x4801a008, 0x59880002, 0x4801a009, - 0x59880003, 0x4801a00a, 0x59880004, 0x4801a00b, - 0x59880005, 0x4801a00c, 0x42000800, 0x00000007, - 0x42001000, 0x0000dc00, 0x0401f30a, 0x4a026202, - 0x0000ffff, 0x0401ff07, 0x4a01a006, 0x62000000, - 0x5930001c, 0x4801a007, 0x42000800, 0x00000002, - 0x42001000, 0x0000dc00, 0x0401f2fe, 0x0401fefd, - 0x59300808, 0x4c500000, 0x4c540000, 0x4c580000, - 0x8204a400, 0x0000000a, 0x5930b01c, 0x82d0ac00, - 0x00000006, 0x0201f800, 0x0010ab17, 0x5930081c, - 0x42001000, 0x0000dc00, 0x5c00b000, 0x5c00a800, - 0x5c00a000, 0x0401f2eb, 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, 0x0401f2ba, 0x0401fec7, - 0x4a01a006, 0x02000014, 0x4979a407, 0x4979a207, - 0x59a8003a, 0x4801a008, 0x59a8003b, 0x4801a009, - 0x4a01a00a, 0x00047878, 0x42000800, 0x00000005, - 0x42001000, 0x0000dc00, 0x0401f2aa, 0x0401feb7, - 0x4a01a006, 0x02140018, 0x4a01a407, 0x00000800, - 0x5930001c, 0x82000d00, 0xff000000, 0x900409c0, - 0x4805a207, 0x82000500, 0x00ffffff, 0x4801a00a, - 0x4979a408, 0x4979a208, 0x4979a409, 0x4979a209, - 0x4979a00b, 0x42000800, 0x00000006, 0x42001000, - 0x0000dc00, 0x0401f293, 0x4803c856, 0x4d380000, - 0x4d1c0000, 0x42027000, 0x00000035, 0x0201f800, - 0x001093ba, 0x0402001e, 0x0401fe8a, 0x4a01a006, - 0x13000000, 0x5932381e, 0x591c0019, 0x4801a005, - 0x591c0406, 0x82000580, 0x00000003, 0x04000007, - 0x59300809, 0x58040002, 0x82000500, 0x00ffffff, - 0x4801a007, 0x0401f003, 0x59a80010, 0x4801a007, - 0x59300419, 0x4801a408, 0x59300219, 0x4801a208, - 0x42000800, 0x00000003, 0x42001000, 0x0000dc00, - 0x5c023800, 0x5c027000, 0x0401f26e, 0x0201f800, - 0x00106c55, 0x598c000d, 0x81300580, 0x02020800, - 0x001005d8, 0x0201f800, 0x00106bbf, 0x0201f800, - 0x0002077d, 0x5c023800, 0x5c027000, 0x0201f000, - 0x00106c4b, 0x4803c856, 0x4d2c0000, 0x4d1c0000, - 0x5932381e, 0x811e39c0, 0x02000800, 0x001005d8, - 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, 0x001005d8, - 0x00107691, 0x0010769d, 0x00107693, 0x0010769d, - 0x00107699, 0x00107691, 0x00107691, 0x0010769d, - 0x0010769d, 0x00107691, 0x00107691, 0x00107691, - 0x00107691, 0x00107691, 0x0010769d, 0x00107691, - 0x0010769d, 0x0201f800, 0x001005d8, 0x591c0414, - 0x4803c857, 0x8c000518, 0x04000003, 0x8c000512, - 0x04000003, 0x80001580, 0x0401f003, 0x42001000, - 0x20000000, 0x591c0015, 0x4801a00a, 0x0401f018, - 0x0401f81f, 0x591e5808, 0x812e59c0, 0x02000800, - 0x001005d8, 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, - 0x0401fe0a, 0x4a01a006, 0x02000000, 0x59300c19, - 0x4805a407, 0x59300a19, 0x4805a207, 0x59a81010, - 0x59300809, 0x58041802, 0x820c1d00, 0x00ffffff, - 0x5930081e, 0x58040406, 0x82000580, 0x00000003, - 0x04020004, 0x4809a008, 0x480da009, 0x0401f003, - 0x480da008, 0x4809a009, 0x1c01f000, 0x4803c856, - 0x0401fdf2, 0x0401f003, 0x4803c856, 0x0401fde8, - 0x4a01a006, 0x01000000, 0x5930041a, 0x4801a407, - 0x5930021a, 0x4801a207, 0x42000800, 0x00000002, - 0x42001000, 0x0000dc00, 0x0401f1d6, 0x4803c856, - 0x4d1c0000, 0x0401fdcc, 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, 0x0401f9ec, 0x41780800, 0x42001000, - 0x00005c00, 0x0401f9b3, 0x0201f000, 0x0010604d, - 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, + 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, 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, 0x0401fd03, - 0x5930001c, 0x800001c0, 0x04000008, 0x4a01a006, - 0x01000000, 0x4a01a407, 0x00000003, 0x42000800, - 0x00000002, 0x0401f028, 0x4a01a006, 0x02000000, - 0x41780800, 0x836c0580, 0x00000004, 0x04020003, - 0x84040d42, 0x0401f00d, 0x0201f800, 0x0010513b, - 0x04020003, 0x84040d4a, 0x0401f002, 0x84040d48, - 0x59a80026, 0x8c000506, 0x04020003, 0x8c00050a, - 0x04000002, 0x84040d46, 0x4805a207, 0x59c40085, - 0x48031004, 0x4c580000, 0x4c500000, 0x4c540000, - 0x4200b000, 0x00000006, 0x8388a400, 0x00000000, - 0x82d0ac00, 0x00000008, 0x0201f800, 0x0010ab17, - 0x5c00a800, 0x5c00a000, 0x5c00b000, 0x42000800, - 0x00000008, 0x42001000, 0x0000dc00, 0x0401f0c1, - 0x0401fcc0, 0x4a01a006, 0x56000000, 0x59340006, - 0x4801a007, 0x59340007, 0x4801a008, 0x42000800, - 0x00000003, 0x42001000, 0x0000dc00, 0x0401f0b5, - 0x4803c856, 0x0401fcc1, 0x5930081c, 0x800409c0, - 0x0400000e, 0x82040580, 0x0000ffff, 0x04000004, - 0x82040480, 0x00000007, 0x04021008, 0x4a01a006, - 0x01000000, 0x4a01a407, 0x00000003, 0x42000800, - 0x00000002, 0x0401f012, 0x4a01a006, 0x0200001c, - 0x4a01a007, 0x00000001, 0x42001000, 0x0010b4f0, - 0x50080000, 0x9c0001c0, 0x4801a009, 0x59a80010, - 0x4801a00a, 0x59a80002, 0x59a80803, 0x4801a00b, - 0x4805a00c, 0x42000800, 0x00000007, 0x42001000, - 0x0000dc00, 0x0401f08f, 0x4d2c0000, 0x0401fc8d, - 0x59325808, 0x592c0008, 0x82000500, 0x00ffffff, - 0x4801a001, 0x4a01a006, 0x51000000, 0x5c025800, - 0x0201f000, 0x00107344, 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, 0x001005d8, - 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, 0x0401f860, - 0x0201f000, 0x00106052, 0x59a80026, 0x82000500, - 0x00000028, 0x04000003, 0x497a6a12, 0x0401f7dc, - 0x4a026a12, 0x0000ff00, 0x0401f7d9, 0x42005000, - 0x02000000, 0x42006000, 0x20290000, 0x41786800, - 0x41787800, 0x0401f812, 0x83180d40, 0x00000038, - 0x42001000, 0x0000c9a0, 0x0401f849, 0x42000800, - 0x000007d0, 0x59300011, 0x82000500, 0xfff00000, - 0x80000540, 0x04000003, 0x42000800, 0x00001b58, - 0x41781000, 0x0201f000, 0x00106054, 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, - 0x4803c856, 0x4c040000, 0x0401f822, 0x5c000800, - 0x40040000, 0x80081540, 0x800000c4, 0x82000540, - 0x00002000, 0x4803910a, 0x59b400f6, 0x82000500, - 0x00000018, 0x040207fd, 0x4a0368f0, 0x0010b544, - 0x4a0368f1, 0x0010b54b, 0x480b68f3, 0x4a0378e4, - 0x00008000, 0x0201f000, 0x0010604d, 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, 0x001005d8, 0x0401f7fa, - 0x1c01f000, 0x82000500, 0xffff0000, 0x82000580, - 0x01050000, 0x0402000d, 0x599c0818, 0x8c040d10, - 0x0400000a, 0x59a80807, 0x8c040d0a, 0x04000007, - 0x42001000, 0x0000804f, 0x41781800, 0x41782000, - 0x0201f800, 0x00103a3e, 0x1c01f000, 0x41781000, - 0x42026000, 0x0010d1c0, 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, 0x0010a5df, 0x5930001c, 0x800001c0, - 0x02020800, 0x0010984e, 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, 0x0010d1c0, - 0x0401f7f6, 0x4933c857, 0x8166c840, 0x83300c00, - 0x00000024, 0x80040480, 0x04021006, 0x4006c000, - 0x4a026203, 0x00000008, 0x813261c0, 0x1c01f000, - 0x4202c000, 0x0010d1c0, 0x0401f7fa, 0x42000000, - 0x0010b854, 0x0201f800, 0x0010aa47, 0x4933c856, - 0x417a6000, 0x0401f7f5, 0x4933c857, 0x83380580, - 0x00000013, 0x0402000b, 0x59300004, 0x8c00053e, - 0x04000007, 0x0201f800, 0x00106c55, 0x0201f800, - 0x00106bbf, 0x0201f800, 0x00106c4b, 0x1c01f000, - 0x4933c857, 0x59880052, 0x80000000, 0x48031052, - 0x1c01f000, 0x4933c857, 0x59300203, 0x82003480, - 0x0000000e, 0x02021800, 0x001005d8, 0x4d2c0000, - 0x0c01f803, 0x5c025800, 0x1c01f000, 0x00107991, - 0x00107efd, 0x0010804a, 0x00107991, 0x001080b0, - 0x00107af5, 0x00107991, 0x00107991, 0x00107e93, - 0x00107991, 0x00107991, 0x00107991, 0x00107991, - 0x00107991, 0x0201f800, 0x001005d8, 0x4933c857, - 0x59300203, 0x82003480, 0x0000000e, 0x02021800, - 0x001005d8, 0x0c01f001, 0x001079a8, 0x00108a3d, - 0x001079a8, 0x001079a8, 0x001079a8, 0x001079a8, - 0x001079a8, 0x001079a8, 0x001089e5, 0x00108a58, - 0x00108ac6, 0x00108a58, 0x00108ac6, 0x001079a8, - 0x0201f800, 0x001005d8, 0x0201f800, 0x001005d8, - 0x4933c857, 0x4d2c0000, 0x59325808, 0x59300203, - 0x82003480, 0x0000000e, 0x02021800, 0x001005d8, - 0x0c01f803, 0x5c025800, 0x1c01f000, 0x001079c5, - 0x001079c5, 0x001079c5, 0x001079e1, 0x00107a2d, - 0x001079c5, 0x001079c5, 0x001079c5, 0x001079c7, - 0x001079c5, 0x001079c5, 0x001079c5, 0x001079c5, - 0x001079c5, 0x0201f800, 0x001005d8, 0x4933c857, - 0x83380580, 0x00000040, 0x02020800, 0x001005d8, - 0x4a026007, 0x00082000, 0x4a026203, 0x00000003, - 0x493a6403, 0x4a025c08, 0x00000001, 0x592c000d, - 0x48026011, 0x497a6013, 0x592c0208, 0x800000c2, - 0x800010c4, 0x80081400, 0x480a6206, 0x0201f800, - 0x00100f4e, 0x42000800, 0x80000060, 0x0201f000, - 0x00106721, 0x4933c857, 0x83380480, 0x00000050, - 0x02021800, 0x001005d8, 0x83380480, 0x00000049, - 0x02001800, 0x001005d8, 0x0c01f001, 0x001079f4, - 0x001079ff, 0x001079f2, 0x001079f2, 0x001079f2, - 0x001079f2, 0x00107a0a, 0x0201f800, 0x001005d8, - 0x4a026203, 0x00000004, 0x4a025c08, 0x00000002, - 0x592c0207, 0x48025c09, 0x592c0209, 0x48025a07, - 0x592c000c, 0x4802580d, 0x1c01f000, 0x0201f800, - 0x00106b8a, 0x0201f800, 0x00109037, 0x04000005, - 0x4a025a06, 0x00000006, 0x0201f800, 0x000202da, - 0x0201f000, 0x0002077d, 0x0201f800, 0x00106b8a, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c, - 0x5c027800, 0x42003000, 0x00000014, 0x41782800, - 0x42002000, 0x00000002, 0x4d400000, 0x4d440000, - 0x59368c03, 0x42028000, 0x00000029, 0x0201f800, - 0x0010985e, 0x5c028800, 0x5c028000, 0x42000000, - 0x0010b864, 0x0201f800, 0x0010aa47, 0x0201f800, - 0x00109037, 0x02000000, 0x0002077d, 0x4a025a06, - 0x00000029, 0x0201f800, 0x000202da, 0x0201f000, - 0x0002077d, 0x4933c857, 0x83380580, 0x00000048, - 0x04000005, 0x83380580, 0x00000053, 0x02020800, - 0x001005d8, 0x592c0206, 0x82000580, 0x00000007, - 0x04000009, 0x59300011, 0x80000540, 0x04000006, - 0x592c080c, 0x80040480, 0x4802580c, 0x4a025a06, - 0x00000015, 0x592c0206, 0x80000540, 0x04020003, - 0x4a025a06, 0x00000000, 0x0201f800, 0x000202da, - 0x0201f000, 0x0002077d, 0x4933c857, 0x4d2c0000, - 0x4c500000, 0x4c540000, 0x4c580000, 0x0201f800, - 0x001007e4, 0x02000800, 0x001005d8, 0x497a5a06, - 0x59c80017, 0x82000500, 0x0000f000, 0x48025c07, - 0x59a80816, 0x82040c00, 0x00000018, 0x48065a07, - 0x412c7800, 0x4d2c0000, 0x41cca000, 0x42002800, - 0x00000001, 0x42001000, 0x0000002c, 0x82040480, - 0x0000002d, 0x04021006, 0x832cac00, 0x00000009, - 0x0201f800, 0x00108b96, 0x0401f02e, 0x40043000, - 0x42000800, 0x0000002c, 0x832cac00, 0x00000009, - 0x0201f800, 0x00108b96, 0x82183480, 0x0000002c, - 0x0201f800, 0x001007e4, 0x0400001a, 0x80142800, - 0x4a025804, 0x00000110, 0x492c7801, 0x82180c80, - 0x0000003d, 0x04021007, 0x40180800, 0x832cac00, - 0x00000005, 0x0201f800, 0x00108b96, 0x0401f015, - 0x82081400, 0x0000003c, 0x82183480, 0x0000003c, - 0x42000800, 0x0000003c, 0x412c7800, 0x832cac00, - 0x00000005, 0x0201f800, 0x00108b96, 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, - 0x000202da, 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, 0x001007e4, 0x04000023, - 0x5c001800, 0x492c1801, 0x485a5800, 0x832cac00, - 0x00000002, 0x0201f800, 0x0010ab28, 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, 0x0002077d, 0x83380d80, - 0x00000016, 0x02020800, 0x001005d8, 0x0201f000, - 0x0002077d, 0x4933c857, 0x4d2c0000, 0x4c500000, - 0x4c540000, 0x4c580000, 0x59325808, 0x83cca400, - 0x00000006, 0x59cc1806, 0x820c0580, 0x01000000, - 0x04020004, 0x4200b000, 0x00000002, 0x0401f00f, - 0x4200b000, 0x00000008, 0x832cac00, 0x00000005, - 0x0201f800, 0x0010ab17, 0x8c0c1d00, 0x0400000b, - 0x4200b000, 0x00000008, 0x592e5801, 0x812e59c0, - 0x02000800, 0x001005d8, 0x832cac00, 0x00000005, - 0x0201f800, 0x0010ab17, 0x0401f816, 0x5c00b000, + 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, - 0x4933c857, 0x4c500000, 0x4c540000, 0x4c580000, - 0x83cca400, 0x00000006, 0x5930a808, 0x8254ac00, - 0x00000005, 0x4200b000, 0x00000007, 0x0201f800, - 0x0010ab17, 0x5c00b000, 0x5c00a800, 0x5c00a000, - 0x4933c857, 0x0201f800, 0x00109037, 0x02000000, - 0x0002077d, 0x4d2c0000, 0x0201f800, 0x00109597, - 0x0402000b, 0x41780800, 0x4d400000, 0x42028000, - 0x00000000, 0x0201f800, 0x0010943b, 0x5c028000, - 0x5c025800, 0x0201f000, 0x0002077d, 0x5931d821, - 0x58ef400b, 0x58ee580d, 0x4a025a04, 0x00000103, - 0x58ec0009, 0x0801f800, 0x5c025800, 0x0201f000, - 0x0002077d, 0x4933c857, 0x59cc1806, 0x820c0580, - 0x02000000, 0x04020014, 0x4a026802, 0x00fffffd, - 0x5934000a, 0x84000504, 0x4802680a, 0x59300808, - 0x800409c0, 0x02000000, 0x0002077d, 0x4a000a04, - 0x00000103, 0x480c0805, 0x5931d821, 0x58ef400b, - 0x58ee580d, 0x58ec0009, 0x0801f800, 0x0201f000, - 0x0002077d, 0x42000000, 0x0010b86c, 0x0201f800, - 0x0010aa47, 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, - 0x59c80817, 0x82040d00, 0x000003ff, 0x82041480, - 0x0000000f, 0x0400101b, 0x4200b000, 0x0000000f, - 0x0201f800, 0x0010ab17, 0x592e5801, 0x832cac00, - 0x00000005, 0x82080c80, 0x0000000f, 0x0400100d, - 0x4200b000, 0x0000000f, 0x0201f800, 0x0010ab17, - 0x592e5801, 0x832cac00, 0x00000005, 0x82041480, - 0x0000000f, 0x04001007, 0x42001000, 0x0000000f, - 0x4008b000, 0x0201f800, 0x0010ab17, 0x0401f004, - 0x4004b000, 0x0201f800, 0x0010ab17, 0x5931d821, - 0x58ef400b, 0x58ee580d, 0x4a025a04, 0x00000103, - 0x592e5801, 0x58ec0009, 0x0801f800, 0x0201f800, - 0x0002077d, 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, - 0x001005d8, 0x8208ac00, 0x00000005, 0x0201f800, - 0x0010ab17, 0x82000d00, 0xff000000, 0x800409c0, - 0x04000019, 0x8200b500, 0x000000ff, 0x8058b104, - 0x82580c80, 0x0000000e, 0x04001003, 0x4200b000, - 0x0000000d, 0x58081001, 0x800811c0, 0x02000800, - 0x001005d8, 0x8208ac00, 0x00000005, 0x0201f800, - 0x0010ab17, 0x0401f008, 0x59301008, 0x800811c0, - 0x02000800, 0x001005d8, 0x48001005, 0x59cc0007, - 0x48001006, 0x0401ff3b, 0x5c00b000, 0x5c00a800, + 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, - 0x42000800, 0x00000000, 0x59cc0006, 0x82000580, - 0x02000000, 0x04000003, 0x42000800, 0x00000001, - 0x4d2c0000, 0x59325808, 0x812e59c0, 0x02000800, - 0x001005d8, 0x48065a06, 0x0201f800, 0x000202da, - 0x5c025800, 0x0201f000, 0x0002077d, 0x4933c857, - 0x4d2c0000, 0x4c500000, 0x4c540000, 0x4c580000, - 0x4200b000, 0x00000002, 0x59cc0806, 0x82040580, - 0x01000000, 0x04000004, 0x8204b500, 0x0000ffff, - 0x8058b104, 0x83cca400, 0x00000006, 0x59300008, - 0x8200ac00, 0x00000005, 0x0201f800, 0x0010ab17, - 0x0401ff0c, 0x5c00b000, 0x5c00a800, 0x5c00a000, - 0x5c025800, 0x1c01f000, 0x4933c857, 0x4803c857, - 0x4807c857, 0x480bc857, 0x480fc857, 0x4813c857, - 0x481bc857, 0x492fc857, 0x4d2c0000, 0x4c000000, - 0x0201f800, 0x001007d3, 0x5c000000, 0x0400000f, - 0x48025803, 0x5c000000, 0x4802580a, 0x4c000000, - 0x481a5801, 0x48125809, 0x48065804, 0x480a5807, - 0x480e5808, 0x412c1000, 0x0201f800, 0x00100858, - 0x82000540, 0x00000001, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x4d1c0000, 0x59cc0001, 0x82000500, - 0x00ffffff, 0x59341002, 0x82081500, 0x00ffffff, - 0x80080580, 0x0402001f, 0x497a6205, 0x4d380000, - 0x42027000, 0x00000035, 0x0201f800, 0x001093ba, - 0x5c027000, 0x04020012, 0x591c001c, 0x800001c0, - 0x0400000f, 0x497a381c, 0x591c0414, 0x8c000502, - 0x02000800, 0x001005d8, 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, - 0x001066a0, 0x592c0406, 0x4803c857, 0x800001c0, - 0x0400000c, 0x80080c80, 0x04001004, 0x02020800, - 0x001005d8, 0x80001040, 0x480a5c06, 0x800811c0, - 0x04020004, 0x0201f800, 0x00108d88, 0x0401f06b, - 0x0201f800, 0x0010912a, 0x591c0817, 0x591c0018, - 0x48065808, 0x48025809, 0x59300007, 0x8c000500, - 0x02020800, 0x00100e99, 0x497a3808, 0x0201f800, - 0x000201ba, 0x0402004a, 0x411e6000, 0x0401fc3e, - 0x0401f05a, 0x0401fc6d, 0x04000013, 0x49366009, - 0x4a026406, 0x00000003, 0x492e6008, 0x591c0817, - 0x591c1018, 0x48066017, 0x480a6018, 0x4d380000, - 0x591e7403, 0x4d300000, 0x411e6000, 0x0401fc2e, - 0x5c026000, 0x0201f800, 0x000207a1, 0x5c027000, - 0x0401f046, 0x59a80039, 0x48023a05, 0x0401f043, - 0x59cc0407, 0x82000580, 0x0000000b, 0x04020025, - 0x59340a00, 0x84040d0e, 0x48066a00, 0x592c0a04, - 0x82040d00, 0x000000ff, 0x82040d80, 0x00000014, - 0x04000003, 0x4a02621d, 0x00000003, 0x59300007, - 0x8c000500, 0x02020800, 0x00100e99, 0x4d400000, - 0x42028000, 0x00000003, 0x592c0a08, 0x0201f800, - 0x00104e70, 0x0201f800, 0x000202da, 0x5c028000, - 0x497a6008, 0x4a026403, 0x00000085, 0x4a026203, - 0x00000009, 0x4a026406, 0x00000002, 0x42000800, - 0x8000404b, 0x0201f800, 0x00020721, 0x0401f01b, - 0x59cc0207, 0x82000580, 0x00002a00, 0x04020004, - 0x59a80039, 0x48023a05, 0x0401f014, 0x812e59c0, - 0x02000800, 0x001005d8, 0x4a025a04, 0x00000103, - 0x591c0007, 0x8c000500, 0x02020800, 0x00100e99, - 0x591c0402, 0x48025c06, 0x4a025a06, 0x00000003, - 0x0201f800, 0x000202c1, 0x0201f800, 0x00107911, - 0x0201f800, 0x001049b2, 0x5c026000, 0x0201f800, - 0x0002077d, 0x0401f002, 0x5c026000, 0x5c025800, - 0x1c01f000, 0x0401f819, 0x0401f7fd, 0x4933c857, - 0x83380580, 0x00000015, 0x04020004, 0x59a80039, - 0x48023a05, 0x0401f00d, 0x83380580, 0x00000016, - 0x0402000d, 0x4d300000, 0x411e6000, 0x0201f800, - 0x0010a5df, 0x0201f800, 0x000206fd, 0x0201f800, - 0x0002077d, 0x5c026000, 0x497a381c, 0x0201f800, - 0x0002077d, 0x1c01f000, 0x591c0414, 0x84000540, - 0x48023c14, 0x59cc100b, 0x4933c857, 0x491fc857, - 0x492fc857, 0x4803c857, 0x480bc857, 0x8c08153c, - 0x04000006, 0x59a80039, 0x48023a05, 0x497a381c, - 0x0201f000, 0x0002077d, 0x4d300000, 0x411e6000, - 0x0201f800, 0x00108bd7, 0x5c026000, 0x591c0406, - 0x82000580, 0x00000000, 0x02000000, 0x0002077d, - 0x591c0403, 0x82000580, 0x00000050, 0x0402000d, - 0x4d300000, 0x411e6000, 0x4a026203, 0x00000001, - 0x42000800, 0x80000043, 0x0201f800, 0x00020721, - 0x5c026000, 0x497a381c, 0x0201f000, 0x0002077d, - 0x591c0203, 0x82000580, 0x0000000d, 0x04000014, - 0x812e59c0, 0x02000800, 0x001005d8, 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, - 0x00109259, 0x4933c857, 0x4d1c0000, 0x59cc0001, - 0x59341002, 0x80080580, 0x82000500, 0x00ffffff, - 0x04020041, 0x59301419, 0x0201f800, 0x00109410, - 0x02000800, 0x001005d8, 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, 0x00109037, - 0x02000800, 0x001005d8, 0x592c0204, 0x82000500, - 0x000000ff, 0x82000580, 0x00000014, 0x04000003, - 0x4a02621d, 0x00000003, 0x42028000, 0x00000003, - 0x592c0a08, 0x0201f800, 0x00104e70, 0x0201f800, - 0x000202da, 0x5c025800, 0x497a6008, 0x4a026403, - 0x00000085, 0x4a026203, 0x00000009, 0x4a026406, - 0x00000002, 0x42000800, 0x8000404b, 0x0201f800, - 0x00020721, 0x5c026000, 0x0401f003, 0x59a80039, - 0x48023a05, 0x497a381c, 0x0201f800, 0x0002077d, - 0x5c023800, 0x1c01f000, 0x4933c857, 0x4c580000, - 0x4d2c0000, 0x59325808, 0x83383580, 0x00000015, - 0x04000010, 0x59342200, 0x84102502, 0x48126a00, - 0x0201f800, 0x00109037, 0x04000066, 0x0201f800, - 0x00109597, 0x04020005, 0x4200b000, 0x00000002, - 0x0201f800, 0x0010957d, 0x0401fa0a, 0x0401f079, - 0x83cc1400, 0x00000008, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000006, 0x0201f800, 0x0010855a, - 0x04020015, 0x83cc1400, 0x0000000a, 0x4200b000, - 0x00000002, 0x83341c00, 0x00000008, 0x0201f800, - 0x0010855a, 0x0402000c, 0x0201f800, 0x00102074, - 0x59342200, 0x59cc1007, 0x800811c0, 0x04000003, - 0x480a6801, 0x84102542, 0x8410251a, 0x48126a00, - 0x0401f05f, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x0010203c, 0x5c027800, 0x42000000, 0x0010b864, - 0x0201f800, 0x0010aa47, 0x59340200, 0x84000558, - 0x48026a00, 0x4d300000, 0x0201f800, 0x0002075a, - 0x02000800, 0x001005d8, 0x49366009, 0x497a6008, - 0x4a026406, 0x00000001, 0x4a026403, 0x00000001, - 0x42003000, 0x00000003, 0x0201f800, 0x0010a942, - 0x0201f800, 0x00103b25, 0x04000011, 0x41782800, - 0x42003000, 0x00000001, 0x4d400000, 0x42028000, - 0x00000029, 0x0201f800, 0x0010a43e, 0x5c028000, + 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, 0x0401f009, 0x4a026203, - 0x00000001, 0x42000800, 0x0000000b, 0x0201f800, - 0x00104571, 0x0201f800, 0x0010672b, 0x5c026000, - 0x0201f800, 0x00109037, 0x04000022, 0x0201f800, - 0x00109597, 0x04020022, 0x0401f9ae, 0x0401f01d, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c, - 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47, - 0x59340200, 0x84000558, 0x48026a00, 0x42003000, - 0x00000003, 0x41782800, 0x42002000, 0x00000005, - 0x4d400000, 0x4d440000, 0x59368c03, 0x42028000, - 0x00000029, 0x0201f800, 0x0010985e, 0x5c028800, - 0x5c028000, 0x5c027800, 0x0201f800, 0x00102074, - 0x0201f800, 0x0002077d, 0x0401f002, 0x0401fca9, - 0x5c025800, 0x5c00b000, 0x1c01f000, 0x4933c857, - 0x41380000, 0x83383480, 0x00000056, 0x02021800, - 0x001005d8, 0x0c01f001, 0x00107ef7, 0x00107ef2, - 0x00107ef7, 0x00107ef7, 0x00107ef7, 0x00107ef7, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0, - 0x00107ef0, 0x00107ef7, 0x00107ef0, 0x00107ef7, - 0x00107ef7, 0x00107ef0, 0x00107ef0, 0x00107ef0, - 0x00107ef0, 0x00107ef0, 0x00107ef7, 0x00107ef0, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0, - 0x00107ef7, 0x00107ef7, 0x00107ef0, 0x00107ef0, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7, - 0x00107ef0, 0x00107ef0, 0x00107ef7, 0x00107ef7, - 0x00107ef0, 0x00107ef7, 0x00107ef7, 0x00107ef0, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7, - 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7, - 0x0201f800, 0x001005d8, 0x4a026203, 0x00000001, - 0x493a6403, 0x0201f000, 0x0010672b, 0x4933c857, - 0x4a026203, 0x00000001, 0x493a6403, 0x0201f000, - 0x0010672b, 0x4933c857, 0x59300403, 0x82003480, - 0x00000056, 0x02021800, 0x001005d8, 0x83383580, - 0x00000013, 0x04000093, 0x83383580, 0x00000027, - 0x0402004b, 0x0201f800, 0x00106bbf, 0x0201f800, - 0x00109134, 0x0400000b, 0x0201f800, 0x0010914e, - 0x04000041, 0x59300403, 0x82000d80, 0x00000022, - 0x04020038, 0x0401fc61, 0x0400003a, 0x0401f03a, - 0x0201f800, 0x00102074, 0x42000800, 0x00000007, - 0x0201f800, 0x00104571, 0x0401f8fe, 0x4d440000, - 0x59368c03, 0x83440580, 0x000007fe, 0x04020008, - 0x59a81026, 0x84081540, 0x0201f800, 0x0010513b, - 0x04020002, 0x8408154a, 0x480b5026, 0x42028000, - 0x00000029, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x0010203c, 0x5c027800, 0x836c0580, 0x00000003, - 0x0400000c, 0x59326809, 0x59340008, 0x800001c0, - 0x04020008, 0x59368c03, 0x4933c857, 0x4937c857, - 0x4947c857, 0x0201f800, 0x001045fb, 0x0401f00c, - 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47, - 0x42003000, 0x00000015, 0x41782800, 0x42002000, - 0x00000003, 0x0201f800, 0x0010985e, 0x5c028800, - 0x0201f800, 0x00109326, 0x0201f000, 0x0002077d, - 0x1c01f000, 0x0401f8cb, 0x0401f7fa, 0x83380580, - 0x00000014, 0x0400000b, 0x0201f800, 0x00106f60, - 0x02020000, 0x00107974, 0x59300203, 0x82000580, - 0x00000002, 0x040000ed, 0x0201f800, 0x001005d8, - 0x0201f800, 0x00106bbf, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x0010203c, 0x5c027800, 0x42003000, - 0x00000016, 0x41782800, 0x4d400000, 0x4d440000, - 0x59368c03, 0x42002000, 0x00000009, 0x42028000, - 0x00000029, 0x0201f800, 0x0010985e, 0x5c028800, - 0x5c028000, 0x42000000, 0x0010b864, 0x0201f800, - 0x0010aa47, 0x0201f800, 0x00109134, 0x0402000c, - 0x0201f800, 0x00102074, 0x0401f89e, 0x59340c03, - 0x82040580, 0x000007fe, 0x040207ca, 0x59a80826, - 0x84040d40, 0x48075026, 0x0401f7c6, 0x0201f800, - 0x0010914e, 0x04020003, 0x0401f892, 0x0401f7c1, - 0x59300403, 0x82000d80, 0x00000032, 0x04020004, - 0x0201f800, 0x0010230c, 0x0401f7ba, 0x59300403, - 0x82000d80, 0x00000022, 0x04000886, 0x0401f7b5, - 0x4803c857, 0x0c01f001, 0x00108016, 0x00108016, - 0x00108016, 0x00108016, 0x00108016, 0x00108016, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0, - 0x00107ff9, 0x00108016, 0x00107ff0, 0x00108016, - 0x00108016, 0x00107ff0, 0x00107ff0, 0x00107ff0, - 0x00107ff0, 0x00107ff0, 0x00108016, 0x00108016, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0, - 0x00108007, 0x00108016, 0x00107ff0, 0x00108000, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108000, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016, - 0x00108003, 0x00107ff0, 0x00107ff2, 0x00108016, - 0x00107ff0, 0x00108016, 0x00108016, 0x00107ff0, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016, - 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016, - 0x0201f800, 0x001005d8, 0x4d2c0000, 0x59325808, - 0x0201f800, 0x000202da, 0x5c025800, 0x0201f000, - 0x0002077d, 0x4a026203, 0x00000005, 0x59a80039, - 0x48026205, 0x59a80037, 0x48026206, 0x1c01f000, - 0x5930081e, 0x49780a05, 0x0401f014, 0x0201f800, - 0x00109326, 0x0201f000, 0x0002077d, 0x0201f800, - 0x0010230c, 0x0201f800, 0x00106c55, 0x04000005, - 0x0201f800, 0x00106bbf, 0x0201f000, 0x0002077d, - 0x0201f800, 0x00106bbf, 0x0201f800, 0x0002077d, - 0x0201f000, 0x00106c4b, 0x4933c857, 0x4a026203, - 0x00000002, 0x59a80037, 0x48026206, 0x1c01f000, - 0x4933c857, 0x0201f800, 0x00109037, 0x0400002a, - 0x4d2c0000, 0x0201f800, 0x00109597, 0x0402000a, - 0x4d400000, 0x42028000, 0x00000031, 0x42000800, - 0x00000004, 0x0201f800, 0x0010943b, 0x5c028000, - 0x0401f01c, 0x59300c06, 0x82040580, 0x00000010, - 0x04000004, 0x82040580, 0x00000011, 0x0402000a, - 0x4a025a06, 0x00000031, 0x4a02580d, 0x00000004, - 0x4a02580e, 0x000000ff, 0x0201f800, 0x000202da, - 0x0401f00c, 0x592c0404, 0x8c00051e, 0x04000009, - 0x4a025a04, 0x00000103, 0x4a025805, 0x01000000, - 0x5931d821, 0x58ef400b, 0x58ec0009, 0x0801f800, - 0x5c025800, 0x1c01f000, 0x4933c857, 0x59340400, - 0x82000500, 0x000000ff, 0x82003480, 0x0000000c, - 0x02021800, 0x001005d8, 0x59303403, 0x82180d80, - 0x0000004d, 0x02000000, 0x0010938b, 0x82180d80, - 0x00000033, 0x02000000, 0x00109349, 0x82180d80, - 0x00000028, 0x02000000, 0x0010918f, 0x82180d80, - 0x00000029, 0x02000000, 0x001091a3, 0x82180d80, - 0x0000001f, 0x02000000, 0x00107b28, 0x82180d80, - 0x00000055, 0x02000000, 0x00107b01, 0x82180d80, - 0x00000000, 0x04000591, 0x82180d80, 0x00000022, - 0x02000000, 0x00107b55, 0x82180d80, 0x00000035, - 0x02000000, 0x00107c50, 0x82180d80, 0x00000039, - 0x04000539, 0x82180d80, 0x0000003d, 0x02000000, - 0x00107b85, 0x82180d80, 0x00000044, 0x02000000, - 0x00107bc2, 0x82180d80, 0x00000049, 0x02000000, - 0x00107c17, 0x82180d80, 0x00000041, 0x02000000, - 0x00107c03, 0x82180d80, 0x00000043, 0x02000000, - 0x001094dc, 0x82180d80, 0x00000051, 0x02000000, - 0x00109542, 0x82180d80, 0x00000004, 0x04020003, - 0x42000000, 0x00000001, 0x83380d80, 0x00000015, - 0x04000006, 0x83380d80, 0x00000016, 0x02020000, - 0x00107974, 0x0401f20f, 0x4d2c0000, 0x4d3c0000, + 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, - 0x001080b8, 0x001080bc, 0x001080b8, 0x00108131, - 0x001080b8, 0x00108226, 0x001082bf, 0x001080b8, - 0x001080b8, 0x00108288, 0x001080b8, 0x0010829a, - 0x4933c857, 0x497a6007, 0x59300808, 0x58040000, - 0x4a000a04, 0x00000103, 0x0201f000, 0x0002077d, - 0x4933c857, 0x40000000, 0x40000000, 0x1c01f000, - 0x4933c857, 0x59a80016, 0x82000580, 0x00000074, - 0x0402005c, 0x0201f800, 0x0010a2c8, 0x04020016, - 0x0401f85c, 0x0201f800, 0x00109037, 0x0400000c, - 0x0201f800, 0x00109597, 0x04020009, 0x41780800, - 0x4d400000, 0x42028000, 0x00000000, 0x0201f800, - 0x0010943b, 0x5c028000, 0x0401f003, 0x0201f800, - 0x00102074, 0x0201f800, 0x001048c1, 0x0201f000, - 0x0002077d, 0x0201f800, 0x00109037, 0x04000007, - 0x0201f800, 0x00109597, 0x04020004, 0x0401ff3d, - 0x0201f000, 0x0002077d, 0x417a7800, 0x0201f800, - 0x0010203c, 0x42000000, 0x0010b864, 0x0201f800, - 0x0010aa47, 0x59340200, 0x84000558, 0x48026a00, - 0x42003000, 0x00000003, 0x0201f800, 0x0010a942, - 0x4d300000, 0x0201f800, 0x0002075a, 0x02000800, - 0x001005d8, 0x49366009, 0x497a6008, 0x4a026406, - 0x00000001, 0x4a026403, 0x00000001, 0x0201f800, - 0x00103b25, 0x04000011, 0x4a026406, 0x00000004, - 0x4a026203, 0x00000007, 0x4a026420, 0x00000001, - 0x42003000, 0x00000001, 0x4d400000, 0x42028000, - 0x00000029, 0x41782800, 0x0201f800, 0x0010a43e, - 0x5c028000, 0x0401f009, 0x42000800, 0x0000000b, - 0x0201f800, 0x00104571, 0x4a026203, 0x00000001, - 0x0201f800, 0x0010672b, 0x5c026000, 0x0401ff05, - 0x0201f800, 0x00102074, 0x0201f000, 0x0002077d, - 0x0401ff00, 0x42000000, 0x00000001, 0x0401f0c7, - 0x4933c857, 0x59340200, 0x8c000500, 0x0400000d, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00104567, - 0x5c027800, 0x0201f800, 0x00103b25, 0x04000005, - 0x42000800, 0x00000006, 0x0201f800, 0x00104571, - 0x1c01f000, 0x4933c857, 0x59a80816, 0x82040580, - 0x00000074, 0x0400000e, 0x4807c857, 0x82040580, - 0x00000100, 0x040200a0, 0x59cc0408, 0x4803c857, - 0x8c000500, 0x0400009c, 0x59341403, 0x82080580, - 0x000007fe, 0x04000006, 0x0401f097, 0x59341403, - 0x82080580, 0x000007fe, 0x04020003, 0x0401fa9c, - 0x0401f04c, 0x0201f800, 0x0010462a, 0x59341403, - 0x82080580, 0x000007fc, 0x0402001f, 0x4a026802, - 0x00fffffc, 0x0201f800, 0x00109037, 0x04000012, - 0x0201f800, 0x00109597, 0x0402000f, 0x0401f8a9, - 0x41780800, 0x4d400000, 0x42028000, 0x00000000, - 0x0201f800, 0x0010943b, 0x5c028000, 0x42000800, - 0x00000004, 0x0201f800, 0x00104571, 0x0201f000, - 0x0002077d, 0x42000800, 0x00000004, 0x0201f800, - 0x00104571, 0x0201f800, 0x00102074, 0x0201f000, - 0x0002077d, 0x59a80005, 0x8c000514, 0x04000011, - 0x0201f800, 0x0010513b, 0x42001000, 0x00000010, - 0x04020009, 0x59340002, 0x82000500, 0x00ff0000, - 0x82000580, 0x00ff0000, 0x04000006, 0x42001000, - 0x00000008, 0x0201f800, 0x00104c6d, 0x0402005a, - 0x0201f800, 0x00109037, 0x0400005b, 0x0201f800, - 0x00109597, 0x04020005, 0x592c0404, 0x8c00051c, - 0x040207c9, 0x0401f877, 0x42000800, 0x00000005, - 0x0201f800, 0x00104571, 0x4a026203, 0x00000001, - 0x4a026403, 0x00000003, 0x0201f000, 0x0010672b, - 0x59cc0408, 0x8c000518, 0x04000010, 0x0201f800, - 0x001092e5, 0x0201f800, 0x0010513b, 0x04000004, - 0x59cc0408, 0x8c000516, 0x040207b3, 0x59a80026, - 0x8400054a, 0x48035026, 0x59a80010, 0x84000570, - 0x48038832, 0x0401f7ac, 0x42001000, 0x000000ef, - 0x480b5010, 0x497b8830, 0x84081570, 0x480b8832, - 0x59c40802, 0x84040d4c, 0x48078802, 0x0201f800, - 0x0010930f, 0x59a80026, 0x84000548, 0x48035026, - 0x0201f800, 0x0010a3da, 0x0402079b, 0x59a80026, - 0x8400054c, 0x48035026, 0x42000800, 0x00000006, - 0x0201f800, 0x00104571, 0x417a7800, 0x0201f800, - 0x00104567, 0x42000000, 0x000000e8, 0x0201f800, - 0x00105c9a, 0x02000800, 0x001045a6, 0x02020800, - 0x001005d8, 0x49366009, 0x59340200, 0x8400051a, - 0x48026a00, 0x42000800, 0x00000003, 0x0201f800, - 0x00104571, 0x4a026406, 0x00000001, 0x4a026203, - 0x00000001, 0x4a026403, 0x00000002, 0x0201f000, - 0x0010672b, 0x0401fe43, 0x42000000, 0x00000001, - 0x0401f00a, 0x599c0017, 0x8c00050a, 0x040007ab, - 0x42000800, 0x00000004, 0x0201f800, 0x00104571, - 0x0201f000, 0x0002077d, 0x4933c857, 0x80003540, - 0x04000005, 0x42000800, 0x00000007, 0x0201f800, - 0x00104571, 0x801831c0, 0x0402000e, 0x59302008, - 0x801021c0, 0x04000004, 0x58100404, 0x8c00051e, - 0x04020008, 0x59341c03, 0x42002000, 0x00000004, - 0x42003000, 0x00000012, 0x0201f800, 0x00103aae, - 0x0201f800, 0x00102074, 0x0201f000, 0x0002077d, - 0x4c5c0000, 0x4d2c0000, 0x59325808, 0x0201f800, - 0x00105755, 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, 0x59a80005, - 0x8c000514, 0x04000015, 0x0201f800, 0x0010513b, - 0x42001000, 0x00000010, 0x04020009, 0x59340002, - 0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000, - 0x0400000a, 0x42001000, 0x00000008, 0x0201f800, - 0x00104c6d, 0x04000005, 0x59a80005, 0x84000556, - 0x48035005, 0x0401f031, 0x836c0580, 0x00000003, - 0x0402000b, 0x59300008, 0x80000540, 0x04020008, - 0x59341c03, 0x42002000, 0x00000006, 0x42003000, - 0x00000013, 0x0201f800, 0x00103aae, 0x0201f800, - 0x0010468d, 0x0401fecf, 0x0401fa1d, 0x0402001f, - 0x59340404, 0x80000540, 0x0400001c, 0x42000800, - 0x00000006, 0x0201f800, 0x00104571, 0x0201f800, - 0x00109037, 0x04000011, 0x0201f800, 0x00109597, - 0x0402000a, 0x41780800, 0x4d400000, 0x42028000, - 0x00000000, 0x0201f800, 0x0010943b, 0x5c028000, - 0x0201f000, 0x0002077d, 0x4a025a04, 0x00000103, - 0x4a025805, 0x02000000, 0x0201f800, 0x00102074, - 0x0201f000, 0x0002077d, 0x0201f800, 0x00104c19, - 0x0201f800, 0x00109037, 0x04000007, 0x0201f800, - 0x00109597, 0x04020004, 0x0401fda2, 0x0201f000, - 0x0002077d, 0x0401fd9f, 0x80000580, 0x59a80005, - 0x8c000516, 0x04000005, 0x84000516, 0x48035005, - 0x82000540, 0x00000001, 0x0401ff60, 0x1c01f000, - 0x4933c857, 0x59a80016, 0x82000580, 0x00000014, + 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, - 0x00104571, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000001, 0x0201f000, 0x0010672b, 0x42000000, - 0x00000001, 0x0401f74d, 0x4933c857, 0x40003000, - 0x59a80016, 0x82000580, 0x00000004, 0x0402000a, - 0x82183580, 0x0000000b, 0x04020005, 0x42000800, - 0x00000007, 0x0201f800, 0x00104571, 0x0201f000, - 0x0002077d, 0x42000000, 0x00000001, 0x0401f73b, - 0x4803c857, 0x4d2c0000, 0x4d3c0000, 0x0c01f804, - 0x5c027800, 0x5c025800, 0x1c01f000, 0x001080b8, - 0x001082ce, 0x001080b8, 0x00108323, 0x001080b8, - 0x00108391, 0x001082bf, 0x001080b8, 0x001080b8, - 0x001083b1, 0x001080b8, 0x001083c1, 0x4933c857, - 0x4d1c0000, 0x59301403, 0x82080580, 0x00000003, - 0x04000008, 0x82081580, 0x0000001e, 0x04020003, - 0x0201f800, 0x0002077d, 0x5c023800, 0x1c01f000, - 0x0401ff5a, 0x0401f7fd, 0x4933c857, 0x0201f800, - 0x00109037, 0x0400000b, 0x0201f800, 0x00109597, - 0x04020008, 0x4200b000, 0x00000002, 0x0201f800, - 0x0010957d, 0x0401fd43, 0x0201f000, 0x0002077d, - 0x0401f8f5, 0x04020030, 0x417a7800, 0x0201f800, - 0x00104567, 0x417a7800, 0x0201f800, 0x0010203c, - 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47, - 0x59340200, 0x84000558, 0x48026a00, 0x4a026403, - 0x00000002, 0x42003000, 0x00000003, 0x0201f800, - 0x0010a942, 0x0201f800, 0x00103b25, 0x04000011, - 0x4d400000, 0x41782800, 0x42003000, 0x00000005, - 0x42028000, 0x00000029, 0x0201f800, 0x0010a43e, - 0x5c028000, 0x4a026203, 0x00000007, 0x4a026406, - 0x00000004, 0x4a026420, 0x00000001, 0x1c01f000, - 0x42000800, 0x00000003, 0x0201f800, 0x00104571, - 0x4a026203, 0x00000001, 0x0201f800, 0x0010672b, - 0x0401f7f7, 0x59cc0407, 0x82000580, 0x00000009, - 0x0402000a, 0x59340412, 0x82000500, 0x000000ff, - 0x0400000c, 0x80000040, 0x48026c12, 0x4a026206, - 0x0000000a, 0x0401f7ea, 0x59cc0207, 0x82000500, - 0x0000ff00, 0x82000580, 0x00001900, 0x040007c2, - 0x0401fcfc, 0x80000580, 0x0401f6c4, 0x4933c857, - 0x59a80032, 0x80000540, 0x04000015, 0x59340403, - 0x82000580, 0x000007fe, 0x04020011, 0x59a80010, - 0x80000000, 0x48035010, 0x417a7800, 0x0201f800, - 0x00104567, 0x42000800, 0x00000003, 0x0201f800, - 0x00104571, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000002, 0x0201f000, 0x0010672b, 0x0201f800, - 0x00109037, 0x04000011, 0x0201f800, 0x00109597, - 0x0402000e, 0x4c580000, 0x4200b000, 0x00000002, - 0x0201f800, 0x0010957d, 0x5c00b000, 0x0401fcd5, - 0x42000800, 0x00000007, 0x0201f800, 0x00104571, - 0x0201f000, 0x0002077d, 0x0401fcce, 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, - 0x00104571, 0x0201f800, 0x00102074, 0x0201f000, - 0x0002077d, 0x42000000, 0x00000001, 0x0401f677, - 0x0201f800, 0x00109037, 0x59325808, 0x04000008, - 0x592c0204, 0x82000580, 0x00000139, 0x040007f6, - 0x592c0404, 0x8c00051e, 0x040207f3, 0x59340403, - 0x82000580, 0x000007fe, 0x04020007, 0x59a80026, - 0x84000540, 0x48035026, 0x0201f800, 0x00104229, - 0x0401f7e9, 0x417a7800, 0x0201f800, 0x0010203c, - 0x42003000, 0x00000005, 0x0201f800, 0x0010a942, - 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47, - 0x0401f7dd, 0x4933c857, 0x0401f84d, 0x0402000b, - 0x42000800, 0x00000005, 0x0201f800, 0x00104571, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000003, - 0x0201f000, 0x0010672b, 0x42000800, 0x00000004, - 0x0201f800, 0x00104571, 0x0201f800, 0x00109597, - 0x0402000a, 0x4c580000, 0x4200b000, 0x00000002, - 0x0201f800, 0x0010957d, 0x5c00b000, 0x0401fc71, - 0x0201f000, 0x0002077d, 0x0401fc6e, 0x80000580, - 0x0401f636, 0x4933c857, 0x0401f82d, 0x0402000b, - 0x42000800, 0x00000009, 0x0201f800, 0x00104571, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000005, - 0x0201f000, 0x0010672b, 0x42000000, 0x00000001, - 0x0401f626, 0x4933c857, 0x0401f81d, 0x0402000b, - 0x42000800, 0x0000000b, 0x0201f800, 0x00104571, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000001, - 0x0201f000, 0x0010672b, 0x42000000, 0x00000001, - 0x0401f616, 0x4933c857, 0x59cc0407, 0x82000580, - 0x00000003, 0x04020009, 0x59cc0207, 0x82000500, - 0x0000ff00, 0x82000d80, 0x00002a00, 0x04000003, - 0x82000d80, 0x00001e00, 0x1c01f000, 0x4933c857, + 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, - 0x4d400000, 0x4c580000, 0x59a80026, 0x82000540, - 0x00000003, 0x48035026, 0x0401f85c, 0x04000038, - 0x4d340000, 0x4d440000, 0x59a80026, 0x84000552, - 0x48035026, 0x0201f800, 0x00103b25, 0x0400000c, - 0x42028000, 0x0000002a, 0x42028800, 0x0000ffff, - 0x42003000, 0x00000002, 0x0201f800, 0x0010a446, - 0x59a80805, 0x84040d44, 0x48075005, 0x42028000, - 0x0000002a, 0x4d3c0000, 0x42027800, 0x00000204, - 0x0201f800, 0x00101fe5, 0x5c027800, 0x42000000, - 0x0010b864, 0x0201f800, 0x0010aa47, 0x0201f800, - 0x00101e45, 0x4200b000, 0x00000010, 0x42028800, - 0x000007f0, 0x4d2c0000, 0x83440580, 0x000007fe, - 0x04000003, 0x0201f800, 0x001045fb, 0x81468800, - 0x8058b040, 0x040207f9, 0x5c025800, 0x59cc0408, - 0x8c00051e, 0x04000004, 0x59a80026, 0x84000512, - 0x48035026, 0x5c028800, 0x5c026800, 0x0201f800, - 0x0010462a, 0x4a026802, 0x00fffffe, 0x59a80826, - 0x84040d50, 0x59cc0013, 0x8c00053e, 0x04000003, - 0x8c000536, 0x04000004, 0x59cc0017, 0x8c000536, - 0x04020002, 0x84040d10, 0x48075026, 0x59cc0800, - 0x82040d00, 0x00ffffff, 0x48075010, 0x80040110, - 0x4803501d, 0x48038881, 0x0201f800, 0x0010513b, - 0x04000007, 0x59cc0009, 0x48035035, 0x59cc000a, - 0x48035036, 0x0201f800, 0x001092e5, 0x5c00b000, - 0x5c028000, 0x1c01f000, 0x4933c857, 0x4c580000, - 0x59a80010, 0x82000500, 0x00ffff00, 0x04000022, - 0x59cc1000, 0x82081500, 0x00ffff00, 0x80080580, - 0x04000004, 0x42000000, 0x0010b83b, 0x0401f016, - 0x83cc1400, 0x0000000b, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000006, 0x0401f900, 0x04000004, - 0x42000000, 0x0010b83c, 0x0401f00b, 0x83cc1400, - 0x0000000d, 0x4200b000, 0x00000002, 0x83341c00, - 0x00000008, 0x0401f8f5, 0x04000007, 0x42000000, - 0x0010b83d, 0x0201f800, 0x0010aa47, 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, - 0x0010d1c0, 0x59a8000e, 0x81640480, 0x040210bd, - 0x8d3e7d12, 0x04000004, 0x405c0000, 0x81300580, - 0x040000b3, 0x59300406, 0x82000c80, 0x00000012, - 0x04021015, 0x59326809, 0x0c01f001, 0x0010854f, - 0x001084bc, 0x001084d3, 0x001084de, 0x001084b7, - 0x001084ce, 0x00108507, 0x0010854f, 0x001084b5, - 0x0010851b, 0x0010852a, 0x001084b5, 0x001084b5, - 0x001084b5, 0x001084b5, 0x0010854f, 0x00108540, - 0x00108538, 0x0201f800, 0x001005d8, 0x8d3e7d18, - 0x04000004, 0x59300420, 0x8c000500, 0x04020094, - 0x59300403, 0x82000580, 0x00000043, 0x04000090, - 0x0201f800, 0x00109134, 0x02000800, 0x00102074, - 0x0201f800, 0x0010914e, 0x02000800, 0x0010801c, - 0x8d3e7d06, 0x04000084, 0x0201f800, 0x001092d7, - 0x04000083, 0x0401f080, 0x8d3e7d16, 0x04000004, - 0x59300420, 0x8c000500, 0x0402007d, 0x59325808, - 0x0201f800, 0x00109037, 0x04000077, 0x49425a06, - 0x497a5c09, 0x0201f800, 0x000202da, 0x0201f800, - 0x0010912a, 0x0401f070, 0x813669c0, 0x02000800, - 0x001005d8, 0x8d3e7d06, 0x04000004, 0x59340200, - 0x8c00050e, 0x0402006a, 0x59300004, 0x8400055c, - 0x48026004, 0x59300203, 0x82000580, 0x00000004, - 0x02000800, 0x00100e99, 0x59325808, 0x0201f800, - 0x00109037, 0x0400005c, 0x4a025a04, 0x00000103, - 0x59300402, 0x48025c06, 0x592c0408, 0x8c000512, - 0x04000006, 0x4d2c0000, 0x592e5809, 0x0201f800, - 0x001007fd, 0x5c025800, 0x49425a06, 0x497a5c09, - 0x0201f800, 0x0010959c, 0x0201f800, 0x000202da, - 0x0201f800, 0x0010912a, 0x0401f047, 0x8c000518, - 0x04000047, 0x59300203, 0x82000580, 0x00000004, - 0x02000800, 0x00100e99, 0x59325808, 0x0201f800, - 0x00109037, 0x0400003c, 0x49425a06, 0x497a5c09, - 0x0201f800, 0x0010a693, 0x0201f800, 0x0010959c, - 0x0201f800, 0x000202da, 0x0401f033, 0x0201f800, - 0x001062d5, 0x04000032, 0x59300203, 0x82000580, - 0x00000004, 0x04020004, 0x0201f800, 0x00100e99, - 0x0401f02b, 0x42027000, 0x00000047, 0x0201f800, - 0x000207a1, 0x0401f026, 0x59300203, 0x82000580, - 0x00000004, 0x02000800, 0x00100e99, 0x59325808, - 0x0201f800, 0x00109037, 0x0400001b, 0x49425a06, - 0x497a5c09, 0x0201f800, 0x000202da, 0x0401f016, - 0x833c0500, 0x00001800, 0x04000015, 0x8d3e7d16, - 0x04020013, 0x59325817, 0x0201f800, 0x001007fd, - 0x59300203, 0x82000580, 0x00000004, 0x02000800, - 0x00100e99, 0x59325808, 0x0201f800, 0x00109037, - 0x04000005, 0x49425a06, 0x497a5c09, 0x0201f800, - 0x000202da, 0x0201f800, 0x00107911, 0x83326400, - 0x00000024, 0x41580000, 0x81300480, 0x04001742, - 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, 0x001005d8, 0x83380480, - 0x0000004b, 0x02001800, 0x001005d8, 0x0c01f001, - 0x0010858a, 0x0010858a, 0x0010858a, 0x0010858a, - 0x00108588, 0x00108588, 0x00108588, 0x0010858a, - 0x0201f800, 0x001005d8, 0x493bc857, 0x4a026203, - 0x0000000d, 0x493a6403, 0x42000800, 0x80000000, - 0x0201f000, 0x00020721, 0x83380580, 0x00000013, - 0x04020008, 0x59300403, 0x82000580, 0x00000050, - 0x02020800, 0x001005d8, 0x0201f000, 0x0002077d, - 0x4933c857, 0x83380580, 0x00000027, 0x04020030, - 0x4933c857, 0x0201f800, 0x00106bbf, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x0010203c, 0x5c027800, - 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47, - 0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037, - 0x492fc857, 0x0400000d, 0x4a025a04, 0x00000103, - 0x59300c02, 0x48065c06, 0x4a025a06, 0x00000029, - 0x497a5c09, 0x592c0c08, 0x84040d50, 0x48065c08, - 0x0201f800, 0x000202da, 0x5c025800, 0x42003000, - 0x00000015, 0x41782800, 0x42002000, 0x00000003, - 0x4d400000, 0x4d440000, 0x59368c03, 0x42028000, - 0x00000029, 0x0201f800, 0x0010985e, 0x5c028800, - 0x5c028000, 0x0201f000, 0x0002077d, 0x83380580, - 0x00000014, 0x0402000c, 0x59300403, 0x82000c80, - 0x00000053, 0x02021800, 0x001005d8, 0x82000480, - 0x00000040, 0x02001800, 0x001005d8, 0x4803c857, - 0x0c01f00e, 0x83380580, 0x00000053, 0x0400000a, - 0x83380580, 0x00000048, 0x02020800, 0x001005d8, - 0x59300403, 0x82000580, 0x00000050, 0x02020800, - 0x001005d8, 0x1c01f000, 0x001085ff, 0x001085fd, - 0x001085fd, 0x001085fd, 0x001085fd, 0x001085fd, - 0x001085fd, 0x001085fd, 0x001085fd, 0x001085fd, - 0x001085fd, 0x00108616, 0x00108616, 0x00108616, - 0x00108616, 0x001085fd, 0x00108616, 0x001085fd, - 0x00108616, 0x0201f800, 0x001005d8, 0x4933c857, - 0x0201f800, 0x00106bbf, 0x0201f800, 0x00109037, - 0x02000000, 0x0002077d, 0x4d2c0000, 0x59325808, - 0x4a025a04, 0x00000103, 0x59300402, 0x48025c06, - 0x4a025a06, 0x00000006, 0x497a5c09, 0x0201f800, - 0x000202da, 0x5c025800, 0x0201f800, 0x0010912a, - 0x0201f000, 0x0002077d, 0x4933c857, 0x0201f800, - 0x00106bbf, 0x0201f000, 0x0002077d, 0x0201f800, - 0x001005d8, 0x5930001c, 0x800001c0, 0x02020800, - 0x0010984e, 0x59300004, 0x8c00053e, 0x04020029, - 0x59325808, 0x592c0c08, 0x59cc2a08, 0x82141d00, - 0x00000c00, 0x04000002, 0x59cc1809, 0x84040d58, - 0x48065c08, 0x82143500, 0x00000fff, 0x04020027, - 0x59340200, 0x8c00050e, 0x04020080, 0x0201f800, - 0x0002082b, 0x04020006, 0x4a025a06, 0x00000000, - 0x59300811, 0x800409c0, 0x0402094b, 0x4a025a04, - 0x00000103, 0x48065807, 0x480e580a, 0x48165c09, - 0x59300c02, 0x48065c06, 0x0201f800, 0x000202c1, - 0x0201f800, 0x001049b2, 0x59cc0208, 0x8c000518, - 0x02020000, 0x001091d1, 0x0201f000, 0x0002077d, - 0x0201f800, 0x00106f60, 0x040007d6, 0x4d3c0000, - 0x42027800, 0x00000002, 0x0201f800, 0x00108be3, - 0x5c027800, 0x0401f7cf, 0x4817c857, 0x480fc857, - 0x82180500, 0x000000ff, 0x0400000e, 0x592c0204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000048, - 0x04020008, 0x592c0407, 0x800001c0, 0x04000005, - 0x0201f800, 0x0010973f, 0x0201f000, 0x00109787, - 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, - 0x00108b9f, 0x5c00a800, 0x5c00a000, 0x0401f7a5, - 0x59300011, 0x59301402, 0x480a5c06, 0x48025807, - 0x480e580a, 0x48165c09, 0x0201f800, 0x00108b48, - 0x0201f800, 0x00108b84, 0x0401f7a6, 0x592c020a, - 0x8c000502, 0x040007cd, 0x592c0208, 0x8c00050e, - 0x040207ca, 0x59300011, 0x800c0d80, 0x040007c7, - 0x4803c857, 0x480fc857, 0x8c183514, 0x02000000, - 0x0010920f, 0x80000540, 0x040007c0, 0x4807c856, - 0x0201f000, 0x0010920f, 0x592c020a, 0x8c000502, - 0x04000782, 0x59300011, 0x800001c0, 0x0400077f, - 0x592c0208, 0x8c00050e, 0x0402077c, 0x0201f000, - 0x0010920f, 0x59cc2006, 0x59cc2807, 0x0401f035, - 0x0401f034, 0x1c01f000, 0x4933c857, 0x5930001c, - 0x800001c0, 0x02020800, 0x0010984e, 0x59325808, - 0x592c0c08, 0x41782800, 0x41781800, 0x84040d58, - 0x48065c08, 0x41783000, 0x59340200, 0x8c00050e, - 0x04020018, 0x0201f800, 0x0002082b, 0x04020007, - 0x4a025a06, 0x00000000, 0x59300811, 0x4807c857, - 0x800409c0, 0x040208ac, 0x4a025a04, 0x00000103, - 0x48065807, 0x480e580a, 0x48165c09, 0x4933c857, - 0x59300c02, 0x48065c06, 0x0201f800, 0x000202c1, - 0x0201f800, 0x001049b2, 0x0201f000, 0x0002077d, - 0x592c020a, 0x8c000502, 0x040007ea, 0x59300011, - 0x4803c857, 0x800001c0, 0x040007e6, 0x592c0208, - 0x8c00050e, 0x040207e3, 0x0201f000, 0x0010920f, + 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, 0x0010984e, 0x5c002800, 0x5c002000, + 0x02020800, 0x0010961a, 0x5c002800, 0x5c002000, 0x4a026203, 0x00000002, 0x4a026403, 0x00000043, - 0x59325808, 0x592c020a, 0x8c000502, 0x04020018, + 0x59325808, 0x592c020a, 0x8c000502, 0x0402001c, 0x40100000, 0x592c080f, 0x80040c80, 0x40140000, - 0x80040480, 0x04001014, 0x48126013, 0x48166011, - 0x59300004, 0x8c00053e, 0x04020008, 0x497a6205, - 0x0201f800, 0x00100f93, 0x04020009, 0x59300804, - 0x0201f000, 0x00106721, 0x0201f800, 0x00106f60, - 0x040007f7, 0x0201f000, 0x00107974, 0x4933c857, - 0x1c01f000, 0x4807c857, 0x40042800, 0x0401f7eb, + 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, - 0x00108740, 0x00108740, 0x00108740, 0x00108740, - 0x00108740, 0x00108740, 0x00108740, 0x00108740, - 0x00108740, 0x00108740, 0x00108742, 0x00108740, - 0x00108740, 0x00108740, 0x00108740, 0x0010874f, - 0x00108740, 0x00108740, 0x00108740, 0x00108740, - 0x0010877d, 0x00108740, 0x00108740, 0x00108740, - 0x0201f800, 0x001005d8, 0x4933c857, 0x0201f800, - 0x00106dc3, 0x4a026203, 0x00000002, 0x59a80039, + 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, 0x00106b8a, 0x4933c857, - 0x0201f800, 0x00106b8a, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x0010203c, 0x5c027800, 0x42000000, - 0x0010b864, 0x0201f800, 0x0010aa47, 0x0201f800, - 0x00109037, 0x04000010, 0x4d2c0000, 0x59325808, + 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, 0x000202da, + 0x84040d50, 0x48065c08, 0x0201f800, 0x00020381, 0x5c025800, 0x42003000, 0x00000014, 0x41782800, 0x4d400000, 0x4d440000, 0x59368c03, 0x42002000, 0x00000002, 0x42028000, 0x00000029, 0x0201f800, - 0x0010985e, 0x5c028800, 0x5c028000, 0x0201f000, - 0x0002077d, 0x4933c857, 0x59300808, 0x49780c09, + 0x0010962a, 0x5c028800, 0x5c028000, 0x0201f000, + 0x000208b4, 0x4933c857, 0x59300808, 0x49780c09, 0x4978080a, 0x58041408, 0x84081558, 0x48080c08, - 0x1c01f000, 0x4807c857, 0x8c040d3e, 0x04020023, - 0x497a5a06, 0x5930001f, 0x80000540, 0x04000017, + 0x1c01f000, 0x4807c857, 0x8c040d3e, 0x04020024, + 0x497a5a06, 0x5930001f, 0x80000540, 0x04000018, 0x497a5a06, 0x4c040000, 0x4c080000, 0x4c0c0000, - 0x4c100000, 0x4c140000, 0x58f41003, 0x40040000, - 0x80081480, 0x5930001f, 0x4809e803, 0x0201f800, - 0x00100d56, 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, 0x00100d56, 0x5c000800, - 0x0401f7f5, 0x4807c856, 0x4a025a06, 0x00000007, - 0x1c01f000, 0x83380480, 0x00000058, 0x04021007, - 0x83380480, 0x00000040, 0x04001004, 0x4d2c0000, - 0x0c01f803, 0x5c025800, 0x1c01f000, 0x001087db, - 0x001087db, 0x001087db, 0x001087db, 0x001087db, - 0x001087dd, 0x001087db, 0x001087db, 0x00108860, - 0x001087db, 0x001087db, 0x001087db, 0x001087db, - 0x001087db, 0x001087db, 0x001087db, 0x001087db, - 0x001087db, 0x001087db, 0x00108910, 0x00108939, - 0x00108918, 0x001087db, 0x00108945, 0x0201f800, - 0x001005d8, 0x5930001c, 0x800001c0, 0x02020800, - 0x0010984e, 0x59300007, 0x8c00050e, 0x0400007c, - 0x8c000500, 0x0400006e, 0x8c00051c, 0x04000009, - 0x84000500, 0x48026007, 0x59325808, 0x592c3c08, - 0x841c3d58, 0x481e5c08, 0x0201f000, 0x000207dd, + 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, 0x040207f3, 0x481e5c08, 0x42000000, + 0x8c00051c, 0x040207f2, 0x481e5c08, 0x42000000, 0x00000005, 0x40000000, 0x80000040, 0x040207fe, - 0x59300007, 0x8c00051c, 0x040207ea, 0x59cc0a08, - 0x592c0204, 0x82000500, 0x000000ff, 0x82000580, - 0x00000048, 0x0402000c, 0x497a580b, 0x82040500, - 0x000000ff, 0x04000008, 0x592c0407, 0x800001c0, - 0x04000005, 0x0201f800, 0x0010973f, 0x0201f000, - 0x00100e56, 0x48065c09, 0x41782000, 0x82040500, - 0x00000c00, 0x04000002, 0x59cc2009, 0x82043500, - 0x00000fff, 0x04020027, 0x481e5c08, 0x4a025a06, - 0x00000000, 0x801831c0, 0x02000000, 0x00100e56, - 0x41782000, 0x8c183510, 0x04000002, 0x59cc200b, - 0x4812580c, 0x41780000, 0x8c183512, 0x04000002, - 0x59cc000a, 0x4802580b, 0x80100c00, 0x02001800, - 0x001005d8, 0x02000000, 0x00100e56, 0x82041480, - 0x0000001d, 0x0402100c, 0x4c500000, 0x4c540000, - 0x83cca400, 0x0000000c, 0x832cac00, 0x0000000d, - 0x0401fb67, 0x5c00a800, 0x5c00a000, 0x0201f000, - 0x00100e56, 0x0401fb0b, 0x0201f000, 0x00100e56, - 0x412c7800, 0x0201f800, 0x001007e4, 0x02000800, - 0x001005d8, 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, 0x00109787, 0x4a025a06, 0x00000000, - 0x8c040d1e, 0x04000027, 0x41780800, 0x497a5c09, - 0x592c1c09, 0x59300011, 0x59341200, 0x497a6205, - 0x8c08150e, 0x0402006e, 0x4807c857, 0x4806580a, - 0x80000d40, 0x04020f04, 0x59300402, 0x48025c06, - 0x48065807, 0x4a025a04, 0x00000103, 0x4c040000, - 0x4c0c0000, 0x4c100000, 0x0201f800, 0x0010959c, - 0x5c002000, 0x5c001800, 0x5c000800, 0x8c102512, - 0x0402001a, 0x4c0c0000, 0x0201f800, 0x000202c1, - 0x0201f800, 0x001049b2, 0x5c001800, 0x8c0c1d18, - 0x02000000, 0x0002077d, 0x0201f000, 0x001091d1, - 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, - 0x001007fd, 0x403e5800, 0x0401faca, 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, - 0x0401facb, 0x5c007800, 0x5c002000, 0x5c00a800, - 0x5c00a000, 0x84102512, 0x48125c08, 0x403e5800, - 0x0201f800, 0x001007fd, 0x42034000, 0x0010b4a4, - 0x59a1d81e, 0x80edd9c0, 0x02000800, 0x001005d8, - 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, 0x4a025c09, - 0x00000001, 0x0201f800, 0x0010959c, 0x497a5c09, - 0x8c102512, 0x04000006, 0x4d2c0000, 0x403e5800, - 0x0201f800, 0x001007fd, 0x5c025800, 0x82102500, - 0xffffedff, 0x48125c08, 0x0201f000, 0x0010920f, - 0x59325808, 0x592c0408, 0x8c000518, 0x04000004, - 0x412df800, 0x0201f000, 0x00100e6f, 0x1c01f000, - 0x4933c857, 0x59325808, 0x497a5c09, 0x4a025a06, - 0x00000000, 0x4a025a04, 0x00000103, 0x59300811, - 0x4807c857, 0x800409c0, 0x0402000a, 0x48065807, - 0x59300c02, 0x48065c06, 0x0201f800, 0x000202c1, - 0x0201f800, 0x001049b2, 0x0201f000, 0x0002077d, - 0x59340200, 0x8c00050e, 0x04020005, 0x59300811, - 0x0401fe55, 0x48065807, 0x0401f7f2, 0x592c0208, - 0x8c00050e, 0x040207fa, 0x4933c857, 0x0201f000, - 0x0010920f, 0x4933c857, 0x59325808, 0x812e59c0, - 0x02000800, 0x001005d8, 0x592c020a, 0x8c000502, - 0x02000800, 0x001005d8, 0x4a026206, 0x00000002, - 0x1c01f000, 0x5930001c, 0x800001c0, 0x02020800, - 0x0010984e, 0x59300007, 0x4933c857, 0x4803c857, - 0x8c00050e, 0x04000037, 0x8c000500, 0x04000029, - 0x8c00051c, 0x0400000a, 0x84000500, 0x48026007, - 0x59325808, 0x592c3c08, 0x481fc857, 0x841c3d58, - 0x481e5c08, 0x0201f000, 0x000207dd, 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, 0x00100e56, - 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, 0x0002077d, - 0x493bc857, 0x1c01f000, 0x001089ae, 0x001089ae, - 0x001089ae, 0x001089ae, 0x001089ae, 0x001089b0, - 0x001089ae, 0x001089ae, 0x001089ae, 0x001089ae, - 0x001089ae, 0x001089ae, 0x001089ae, 0x001089ae, - 0x001089ae, 0x001089ae, 0x001089ae, 0x001089ae, - 0x001089ae, 0x001089ae, 0x001089b5, 0x001089ae, - 0x001089ae, 0x001089ae, 0x0201f800, 0x001005d8, - 0x59cc0a08, 0x497a5807, 0x4807c857, 0x82040d00, - 0x00000fff, 0x59300402, 0x48025c06, 0x4a025a04, - 0x00000103, 0x48065c09, 0x4a025a06, 0x00000000, - 0x800409c0, 0x02000000, 0x000202c1, 0x59cc0009, - 0x4802580a, 0x82042500, 0x00000100, 0x04000002, - 0x59cc200b, 0x4812580c, 0x82040500, 0x00000200, - 0x04000002, 0x59cc000a, 0x4802580b, 0x80100c00, - 0x02001800, 0x001005d8, 0x02000000, 0x000202da, - 0x82041480, 0x0000001d, 0x04001006, 0x592c0404, - 0x8c00051e, 0x0400000e, 0x42000800, 0x0000001c, - 0x4c500000, 0x4c540000, 0x83cca400, 0x0000000c, - 0x832cac00, 0x0000000d, 0x0401f9c1, 0x5c00a800, - 0x5c00a000, 0x0201f000, 0x000202da, 0x0401f965, - 0x0401f1a0, 0x83380480, 0x00000093, 0x02021800, - 0x001005d8, 0x83380480, 0x00000085, 0x02001800, - 0x001005d8, 0x0c01f001, 0x001089fd, 0x001089fb, - 0x001089fb, 0x00108a04, 0x001089fb, 0x001089fb, - 0x001089fb, 0x001089fb, 0x001089fb, 0x001089fb, - 0x001089fb, 0x001089fb, 0x001089fb, 0x0201f800, - 0x001005d8, 0x4a026203, 0x00000001, 0x493a6403, - 0x42000800, 0x80000040, 0x0201f000, 0x00020721, - 0x4933c857, 0x59cc1204, 0x480a601c, 0x59cc1404, - 0x0201f800, 0x00109410, 0x0400001b, 0x591c0203, - 0x82000580, 0x00000000, 0x04000017, 0x591c0009, - 0x81340580, 0x04020014, 0x4d300000, 0x4d1c0000, - 0x411e6000, 0x0401f9c2, 0x5c023800, 0x5c026000, - 0x0400000b, 0x59cc0005, 0x8c000500, 0x04020003, - 0x0401f98c, 0x0401f003, 0x4a023a03, 0x00000002, - 0x4a026403, 0x00000086, 0x0401f005, 0x0401f9a6, - 0x040007f5, 0x4a026403, 0x00000087, 0x4a026203, - 0x00000001, 0x42000800, 0x80000040, 0x0201f800, - 0x00020721, 0x59340200, 0x8c00050e, 0x0400000d, - 0x59cc1404, 0x0201f800, 0x00109410, 0x04000009, - 0x591c0414, 0x8c00051a, 0x04000006, 0x4d300000, - 0x411e6000, 0x0201f800, 0x0010921e, 0x5c026000, - 0x1c01f000, 0x83380580, 0x00000013, 0x0402000a, - 0x59300403, 0x82000d80, 0x00000086, 0x04000012, - 0x82000d80, 0x00000087, 0x02020800, 0x001005d8, + 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, 0x001005d8, - 0x493bc857, 0x0201f800, 0x00106bbf, 0x0201f000, - 0x00107911, 0x4933c857, 0x0201f000, 0x00107911, + 0x83380580, 0x00000014, 0x02020800, 0x00100615, + 0x493bc857, 0x0201f800, 0x001068f6, 0x0201f000, + 0x00107698, 0x4933c857, 0x0201f000, 0x00107698, 0x83380580, 0x00000013, 0x04020005, 0x59300403, 0x82000480, 0x00000085, 0x0c01f04d, 0x83380580, 0x00000027, 0x04020041, 0x4933c857, 0x0201f800, - 0x00106bbf, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x0010203c, 0x5c027800, 0x42003000, 0x00000015, + 0x001068f6, 0x4d3c0000, 0x417a7800, 0x0201f800, + 0x00101de2, 0x5c027800, 0x42003000, 0x00000015, 0x41782800, 0x42002000, 0x00000003, 0x42028000, 0x00000029, 0x4d400000, 0x4d440000, 0x59368c03, - 0x0201f800, 0x0010985e, 0x5c028800, 0x5c028000, - 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47, - 0x0201f800, 0x00109037, 0x0400000c, 0x4d2c0000, + 0x0201f800, 0x0010962a, 0x5c028800, 0x5c028000, + 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, + 0x0201f800, 0x00108df4, 0x0400000c, 0x4d2c0000, 0x59325808, 0x4a025a04, 0x00000103, 0x59300402, 0x48025c06, 0x497a5c09, 0x49425a06, 0x0201f800, - 0x000202da, 0x5c025800, 0x0201f800, 0x0010912a, - 0x0201f000, 0x0002077d, 0x83380580, 0x00000089, + 0x00020381, 0x5c025800, 0x0201f800, 0x00108ee7, + 0x0201f000, 0x000208b4, 0x83380580, 0x00000089, 0x04000005, 0x83380580, 0x0000008a, 0x02020000, - 0x00107974, 0x0201f800, 0x00106f60, 0x02020000, - 0x00107974, 0x59300a03, 0x82040580, 0x0000000a, + 0x001076fb, 0x0201f800, 0x00106cb4, 0x02020000, + 0x001076fb, 0x59300a03, 0x82040580, 0x0000000a, 0x0400002a, 0x82040580, 0x0000000c, 0x04000027, - 0x0201f800, 0x001005d8, 0x83380580, 0x00000014, - 0x040207ea, 0x4933c857, 0x0201f800, 0x00106bbf, - 0x42028000, 0x00000006, 0x0401f7d2, 0x00108aba, - 0x00108ab8, 0x00108ab8, 0x00108ab8, 0x00108ab8, - 0x00108ab8, 0x00108ac0, 0x00108ab8, 0x00108ab8, - 0x00108ab8, 0x00108ab8, 0x00108ab8, 0x00108ab8, - 0x0201f800, 0x001005d8, 0x4933c857, 0x59a80037, + 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, 0x00107974, + 0x4933c857, 0x493bc857, 0x0201f000, 0x001076fb, 0x4933c857, 0x59325808, 0x59300a1d, 0x82040580, - 0x00000003, 0x04020004, 0x0201f800, 0x001049b2, + 0x00000003, 0x04020004, 0x0201f800, 0x00104801, 0x0401f00c, 0x5930021d, 0x82000580, 0x00000001, 0x04020008, 0x59300c16, 0x82040580, 0x00000039, 0x0400002c, 0x82040580, 0x00000035, 0x04000029, - 0x4c340000, 0x41306800, 0x0201f800, 0x0002075a, + 0x4c5c0000, 0x4130b800, 0x0201f800, 0x00020892, 0x04000010, 0x4a026203, 0x00000001, 0x4a026403, 0x0000001e, 0x59cc0c07, 0x48066419, 0x59cc0a07, 0x48066219, 0x49366009, 0x4a026406, 0x00000001, - 0x42000800, 0x80000040, 0x0201f800, 0x00020721, - 0x40366000, 0x0201f800, 0x0002077d, 0x5c006800, + 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, 0x001093ba, 0x04020029, - 0x0201f800, 0x0002075a, 0x04000026, 0x491fc857, + 0x40067000, 0x0201f800, 0x00109183, 0x04020029, + 0x0201f800, 0x00020892, 0x04000026, 0x491fc857, 0x4933c857, 0x83380580, 0x00000035, 0x04000004, 0x83380580, 0x00000039, 0x04020002, 0x4932381c, 0x493a6403, 0x4a026203, 0x00000001, 0x4a026406, @@ -8949,17 +8802,17 @@ uint32_t risc_code01[] = { 0x4807c857, 0x48066215, 0x58500a16, 0x4807c857, 0x48066216, 0x58500c19, 0x4807c857, 0x48066419, 0x58500a19, 0x4807c857, 0x48066219, 0x491e601e, - 0x42000800, 0x80000040, 0x0201f800, 0x00020721, + 0x42000800, 0x80000040, 0x0201f800, 0x00020855, 0x40526000, 0x5c023800, 0x5c00a000, 0x0201f000, - 0x0002077d, 0x5930021d, 0x82000580, 0x00000003, - 0x02000800, 0x001049b2, 0x0201f000, 0x0002077d, + 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, 0x001007fd, 0x0201f800, 0x001007e4, + 0x02020800, 0x00100843, 0x0201f800, 0x0010082a, 0x04000017, 0x80142800, 0x4a025a04, 0x00000110, 0x497a5c04, 0x492c7801, 0x82180c80, 0x0000003d, 0x04021006, 0x40180800, 0x832cac00, 0x00000005, @@ -8970,89 +8823,89 @@ uint32_t risc_code01[] = { 0x403e5800, 0x5c00a800, 0x5c00a000, 0x1c01f000, 0x492fc857, 0x812e59c0, 0x0400000f, 0x4d2c0000, 0x4c3c0000, 0x592c7801, 0x803c79c0, 0x04000006, - 0x497a5801, 0x0201f800, 0x000202da, 0x403e5800, - 0x0401f7f9, 0x5c007800, 0x0201f800, 0x000202da, + 0x497a5801, 0x0201f800, 0x00020381, 0x403e5800, + 0x0401f7f9, 0x5c007800, 0x0201f800, 0x00020381, 0x5c025800, 0x1c01f000, 0x4803c856, 0x4c580000, 0x82040c00, 0x00000003, 0x8004b104, 0x0201f800, - 0x0010ab17, 0x5c00b000, 0x1c01f000, 0x4803c856, + 0x0010a93e, 0x5c00b000, 0x1c01f000, 0x4803c856, 0x4c580000, 0x82040c00, 0x00000003, 0x8004b104, - 0x0201f800, 0x0010ab17, 0x5c00b000, 0x1c01f000, + 0x0201f800, 0x0010a93e, 0x5c00b000, 0x1c01f000, 0x591c0c06, 0x82040580, 0x00000003, 0x04000004, 0x82040580, 0x00000002, 0x0402001a, 0x4d300000, 0x4d2c0000, 0x411e6000, 0x59325808, 0x0201f800, - 0x00109037, 0x0400000f, 0x4d400000, 0x42028000, + 0x00108df4, 0x0400000f, 0x4d400000, 0x42028000, 0x00000013, 0x592c0a08, 0x84040d54, 0x0201f800, - 0x00104e70, 0x5c028000, 0x0201f800, 0x0010959c, - 0x0201f800, 0x000202da, 0x0201f800, 0x0010912a, - 0x0201f800, 0x00107911, 0x5c025800, 0x5c026000, + 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, 0x001005d8, + 0x82000c80, 0x00000012, 0x02021800, 0x00100615, 0x0c01f80a, 0x5c027800, 0x1c01f000, 0x4933c857, 0x59300406, 0x82000c80, 0x00000012, 0x02021800, - 0x001005d8, 0x0c01f001, 0x00108c01, 0x00108bfe, - 0x00108bfe, 0x00108c29, 0x00108bfc, 0x00108bfe, - 0x00108c1a, 0x00108bfe, 0x00108bfc, 0x001065f4, - 0x00108bfe, 0x00108bfe, 0x00108bfe, 0x00108bfc, - 0x00108bfc, 0x00108bfc, 0x00108cf9, 0x00108bfe, - 0x0201f800, 0x001005d8, 0x4803c856, 0x80000580, + 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, 0x00109037, 0x0400000f, 0x59325808, + 0x0201f800, 0x00108df4, 0x0400000f, 0x59325808, 0x41780800, 0x4d400000, 0x42028000, 0x00000005, - 0x0201f800, 0x00104e70, 0x5c028000, 0x0201f800, - 0x0010959c, 0x0201f800, 0x001091cc, 0x0201f800, - 0x000202da, 0x0201f800, 0x00107911, 0x82000540, + 0x0201f800, 0x00104bee, 0x5c028000, 0x0201f800, + 0x00109365, 0x0201f800, 0x00108f83, 0x0201f800, + 0x00020381, 0x0201f800, 0x00107698, 0x82000540, 0x00000001, 0x1c01f000, 0x4933c857, 0x0201f800, - 0x001048d9, 0x0402000c, 0x4d400000, 0x42028000, - 0x00000010, 0x0201f800, 0x0010a1d1, 0x4a026406, + 0x00104728, 0x0402000c, 0x4d400000, 0x42028000, + 0x00000010, 0x0201f800, 0x00109fc0, 0x4a026406, 0x00000006, 0x4a026203, 0x00000007, 0x5c028000, - 0x1c01f000, 0x4933c857, 0x0201f800, 0x00106c55, + 0x1c01f000, 0x4933c857, 0x0201f800, 0x0010698c, 0x4df00000, 0x0401f8b8, 0x82000c80, 0x0000000e, - 0x02021800, 0x001005d8, 0x0c01f001, 0x00108c43, - 0x00108cb0, 0x00108c5a, 0x00108cc3, 0x00108cab, - 0x00108c41, 0x00108c43, 0x00108c43, 0x00108c47, - 0x00108c43, 0x00108c43, 0x00108c43, 0x00108c43, - 0x00108c5a, 0x0201f800, 0x001005d8, 0x5c03e000, - 0x02000800, 0x00106c4b, 0x0401f7b8, 0x5c03e000, - 0x02000800, 0x00106c4b, 0x59300406, 0x82000580, + 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, 0x001049b2, + 0x4d340000, 0x59326809, 0x0201f800, 0x00104801, 0x5c026800, 0x0401f7a8, 0x59300004, 0x8400055c, - 0x48026004, 0x0201f800, 0x00106c4b, 0x59300406, + 0x48026004, 0x0201f800, 0x00106982, 0x59300406, 0x82000580, 0x00000006, 0x04000043, 0x8d3e7d02, 0x04020041, 0x497a621d, 0x59300203, 0x82000580, 0x0000000d, 0x04000003, 0x4a02621d, 0x00000003, - 0x0401fbcb, 0x04000024, 0x4d2c0000, 0x4d400000, - 0x59325808, 0x0201f800, 0x001091cc, 0x592c0408, + 0x0401fbd4, 0x04000024, 0x4d2c0000, 0x4d400000, + 0x59325808, 0x0201f800, 0x00108f83, 0x592c0408, 0x8c000512, 0x04000009, 0x4d2c0000, 0x84000512, 0x48025c08, 0x592c0809, 0x40065800, 0x0201f800, - 0x001007fd, 0x5c025800, 0x4d400000, 0x42028000, + 0x00100843, 0x5c025800, 0x4d400000, 0x42028000, 0x00000005, 0x592c0a08, 0x8c040d0e, 0x04000004, 0x42028000, 0x00000002, 0x0401f001, 0x0201f800, - 0x00104e70, 0x5c028000, 0x0201f800, 0x0010959c, - 0x0201f800, 0x000202da, 0x497a6008, 0x5c028000, + 0x00104bee, 0x5c028000, 0x0201f800, 0x00109365, + 0x0201f800, 0x00020381, 0x497a6008, 0x5c028000, 0x5c025800, 0x8d3e7d00, 0x04000009, 0x4d340000, - 0x59326809, 0x0201f800, 0x001049b2, 0x5c026800, - 0x0201f800, 0x00107911, 0x0401f00b, 0x4a026403, + 0x59326809, 0x0201f800, 0x00104801, 0x5c026800, + 0x0201f800, 0x00107698, 0x0401f00b, 0x4a026403, 0x00000085, 0x4a026203, 0x00000009, 0x4a026406, 0x00000002, 0x42000800, 0x8000404b, 0x0201f800, - 0x00020721, 0x5c03e000, 0x02020800, 0x00106c55, + 0x00020855, 0x5c03e000, 0x02020800, 0x0010698c, 0x82000540, 0x00000001, 0x1c01f000, 0x0201f800, - 0x00106c4b, 0x0201f800, 0x00100e99, 0x0401f7ab, + 0x00106982, 0x0201f800, 0x00100ee4, 0x0401f7ab, 0x598c000d, 0x81300580, 0x04020004, 0x0201f800, - 0x00106e8e, 0x0402001b, 0x0201f800, 0x001068d3, + 0x00106be2, 0x0402001b, 0x0201f800, 0x00106619, 0x04020006, 0x59300c03, 0x82040580, 0x00000040, - 0x0400078b, 0x0401f79d, 0x0201f800, 0x00106b6c, - 0x04000010, 0x0201f800, 0x001005d8, 0x0401f813, - 0x04020004, 0x0201f800, 0x00106e62, 0x04020009, - 0x0201f800, 0x001067ae, 0x040207f4, 0x59300c03, + 0x0400078b, 0x0401f79d, 0x0201f800, 0x001068a3, + 0x04000010, 0x0201f800, 0x00100615, 0x0401f813, + 0x04020004, 0x0201f800, 0x00106bb2, 0x04020009, + 0x0201f800, 0x001064f6, 0x040207f4, 0x59300c03, 0x82040580, 0x00000040, 0x04000779, 0x0401f78b, 0x59300203, 0x82000c80, 0x0000000e, 0x02021800, - 0x001005d8, 0x0c01f75e, 0x417a3000, 0x42032000, + 0x00100615, 0x0c01f75e, 0x417a3000, 0x42032000, 0x0000bf32, 0x59900004, 0x81300580, 0x04000009, 0x83932400, 0x00000010, 0x811a3000, 0x83180480, 0x00000005, 0x040017f8, 0x82000540, 0x00000001, @@ -9061,585 +8914,591 @@ uint32_t risc_code01[] = { 0x82000d00, 0x0000001f, 0x82040580, 0x00000005, 0x04020004, 0x42000000, 0x00000003, 0x0401f005, 0x42000000, 0x00000001, 0x0401f002, 0x59300203, - 0x1c01f000, 0x4933c857, 0x0201f800, 0x00106c55, + 0x1c01f000, 0x4933c857, 0x0201f800, 0x0010698c, 0x4df00000, 0x59300203, 0x82000c80, 0x0000000e, - 0x02021800, 0x001005d8, 0x0c01f001, 0x00108d13, - 0x00108d30, 0x00108d17, 0x00108d11, 0x00108d11, - 0x00108d11, 0x00108d11, 0x00108d11, 0x00108d11, - 0x00108d11, 0x00108d11, 0x00108d11, 0x00108d11, - 0x00108d11, 0x0201f800, 0x001005d8, 0x5c03e000, - 0x02000800, 0x00106c4b, 0x0401f6e8, 0x5c03e000, - 0x02000800, 0x00106c4b, 0x4d2c0000, 0x59325808, + 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, - 0x00101231, 0x0401fb16, 0x02000800, 0x001005d8, - 0x4a025a06, 0x00000005, 0x0201f800, 0x000202da, - 0x0201f800, 0x00104c19, 0x0201f800, 0x00107911, + 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, 0x0010b7f6, 0x50081000, + 0x0401f01a, 0x42001000, 0x0010b5f4, 0x50081000, 0x58080002, 0x82000580, 0x00000100, 0x0400000a, - 0x5808000c, 0x81300580, 0x02020800, 0x001005d8, - 0x0201f800, 0x001068d3, 0x02020800, 0x001005d8, - 0x0401f7cf, 0x0201f800, 0x00106e8e, 0x0402000c, + 0x5808000c, 0x81300580, 0x02020800, 0x00100615, + 0x0201f800, 0x00106619, 0x02020800, 0x00100615, + 0x0401f7cf, 0x0201f800, 0x00106be2, 0x0402000c, 0x59300004, 0x8c000520, 0x04000004, 0x84000520, - 0x48026004, 0x0401f7c6, 0x0201f800, 0x001068d3, - 0x040007c3, 0x0201f800, 0x001005d8, 0x59300203, - 0x82000c80, 0x0000000e, 0x02021800, 0x001005d8, + 0x48026004, 0x0401f7c6, 0x0201f800, 0x00106619, + 0x040007c3, 0x0201f800, 0x00100615, 0x59300203, + 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, 0x0c01f7a7, 0x59300406, 0x4933c857, 0x4803c857, - 0x82000c80, 0x00000012, 0x02021800, 0x001005d8, - 0x0c01f001, 0x00108d7c, 0x00108e41, 0x00108f79, - 0x00108d88, 0x00107911, 0x00108d7c, 0x0010a1c0, - 0x0002077d, 0x00108e41, 0x001065ce, 0x00108fda, - 0x00108d77, 0x00108d77, 0x00108d77, 0x00108d77, - 0x00108d77, 0x001096eb, 0x001096eb, 0x0201f800, - 0x001005d8, 0x0401fbd5, 0x02000000, 0x0010801c, - 0x1c01f000, 0x0201f800, 0x00106c55, 0x0201f800, - 0x00106bbf, 0x0201f800, 0x00106c4b, 0x0201f000, - 0x0002077d, 0x4a026206, 0x00000001, 0x1c01f000, - 0x42000000, 0x0010b872, 0x0201f800, 0x0010aa47, - 0x4d2c0000, 0x4d400000, 0x417a5800, 0x0401faa8, + 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, - 0x00106c55, 0x0401ff4c, 0x4803c857, 0x82000c80, - 0x0000000e, 0x02021800, 0x001005d8, 0x0c01f806, - 0x0201f800, 0x00106c4b, 0x5c028000, 0x5c025800, - 0x1c01f000, 0x00108e40, 0x00108db5, 0x00108dc3, - 0x00108de5, 0x00108e11, 0x00108db3, 0x00108d7c, - 0x00108d7c, 0x00108d7c, 0x00108db3, 0x00108db3, - 0x00108db3, 0x00108db3, 0x00108dc3, 0x0201f800, - 0x001005d8, 0x598c000d, 0x81300580, 0x04020004, - 0x0201f800, 0x00106e8e, 0x04020038, 0x0201f800, - 0x001068d3, 0x0400003b, 0x0201f800, 0x00106b6c, - 0x04000032, 0x0201f800, 0x001005d8, 0x497a621d, - 0x812e59c0, 0x02000800, 0x001005d8, 0x592c0204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000014, - 0x04000003, 0x4a02621d, 0x00000003, 0x592c0a08, - 0x0201f800, 0x00104e70, 0x0201f800, 0x0010959c, - 0x0201f800, 0x000202da, 0x497a6008, 0x4a026403, - 0x00000085, 0x4a026203, 0x00000009, 0x4a026406, - 0x00000002, 0x4a026004, 0x8000404b, 0x0201f800, - 0x00106c4b, 0x42000800, 0x8000404b, 0x0201f000, - 0x00020721, 0x0401fef1, 0x04020004, 0x0201f800, - 0x00106e62, 0x04020009, 0x0201f800, 0x001067ae, - 0x040207d2, 0x59300c03, 0x82040580, 0x00000040, - 0x04000008, 0x0401f7d2, 0x59300203, 0x82000c80, - 0x0000000e, 0x02021800, 0x001005d8, 0x0c01f7ae, - 0x0201f800, 0x00106c4b, 0x812e59c0, 0x04000013, - 0x592c0a08, 0x0201f800, 0x00104e70, 0x0201f800, - 0x0010959c, 0x0201f800, 0x000202da, 0x59300203, - 0x82000580, 0x0000000d, 0x04000008, 0x0201f800, - 0x00106c4b, 0x4d340000, 0x59326809, 0x0201f800, - 0x001049b2, 0x5c026800, 0x0201f800, 0x00107911, - 0x0401f030, 0x812e59c0, 0x02000800, 0x001005d8, - 0x0201f800, 0x0010940a, 0x04020004, 0x0201f800, - 0x00100e99, 0x0401f7aa, 0x0201f800, 0x00106c4b, - 0x592c0208, 0x8400050c, 0x48025a08, 0x592c0406, - 0x800000c2, 0x800008c4, 0x80040c00, 0x48066206, - 0x42000000, 0x10000000, 0x41300800, 0x0201f800, - 0x00100b94, 0x0400000d, 0x592c0208, 0x8c00051c, - 0x04020006, 0x8400055c, 0x48025a08, 0x4a026206, - 0x00000002, 0x0401f00f, 0x4d300000, 0x0201f800, - 0x001012e5, 0x5c026000, 0x59300203, 0x82000580, - 0x00000004, 0x04020007, 0x4d380000, 0x42027000, - 0x00000048, 0x0201f800, 0x000207a1, 0x5c027000, - 0x1c01f000, 0x42000000, 0x0010b86e, 0x0201f800, - 0x0010aa47, 0x59300203, 0x82000c80, 0x0000000e, - 0x02021800, 0x001005d8, 0x4803c857, 0x0c01f001, - 0x00108e5a, 0x00108d85, 0x00108e5c, 0x00108e5a, - 0x00108e5c, 0x00108e5c, 0x00108d7d, 0x00108e5a, - 0x00108d79, 0x00108e5a, 0x00108e5a, 0x00108e5a, - 0x00108e5a, 0x00108e5a, 0x0201f800, 0x001005d8, - 0x4d340000, 0x4d2c0000, 0x59326809, 0x59340400, - 0x82000500, 0x000000ff, 0x82000c80, 0x0000000c, - 0x02021800, 0x001005d8, 0x59303403, 0x82180d80, - 0x00000004, 0x04020004, 0x42000000, 0x00000001, - 0x0401f006, 0x82180d80, 0x00000000, 0x04020003, - 0x42000000, 0x00000001, 0x4803c857, 0x0c01f804, - 0x5c025800, 0x5c026800, 0x1c01f000, 0x00108e83, - 0x00108f22, 0x00108e85, 0x00108eba, 0x00108e85, - 0x00108f3f, 0x00108e85, 0x00108e8f, 0x00108e83, - 0x00108f3f, 0x00108e83, 0x00108e9e, 0x0201f800, - 0x001005d8, 0x59300403, 0x82000d80, 0x00000016, - 0x0400002e, 0x82000d80, 0x00000004, 0x0400002b, - 0x82000d80, 0x00000002, 0x04000028, 0x0401fabf, - 0x04000079, 0x59300403, 0x82000d80, 0x00000022, - 0x040000ae, 0x82000d80, 0x00000039, 0x040000b3, - 0x82000d80, 0x00000035, 0x040000b0, 0x82000d80, - 0x0000001e, 0x0400001b, 0x0401f999, 0x04000007, - 0x0201f800, 0x00109597, 0x04020004, 0x0201f800, - 0x00104a14, 0x0401f011, 0x59300403, 0x82000d80, - 0x00000001, 0x04020004, 0x0201f800, 0x001049e7, - 0x0400000a, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x0010203c, 0x5c027800, 0x42000000, 0x0010b864, - 0x0201f800, 0x0010aa47, 0x0201f800, 0x0010801c, - 0x0201f000, 0x00107911, 0x0401f97d, 0x04000004, - 0x0201f800, 0x00109597, 0x040000a9, 0x59300c03, - 0x82040580, 0x00000016, 0x04000056, 0x82040580, - 0x00000002, 0x04020034, 0x59a80026, 0x8c000502, - 0x04020013, 0x0201f800, 0x0010513b, 0x04020010, - 0x0201f800, 0x00105151, 0x04020006, 0x42000000, - 0x00000001, 0x0201f800, 0x00105113, 0x0401f094, - 0x4a035033, 0x00000001, 0x4202d800, 0x00000001, - 0x0201f800, 0x001050a2, 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, 0x0002075a, - 0x04000005, 0x49366009, 0x4a026406, 0x00000001, - 0x0401f020, 0x59300403, 0x82000d80, 0x00000002, - 0x0402000d, 0x59340403, 0x82000580, 0x000007fe, - 0x04020009, 0x59a80026, 0x84000540, 0x48035026, - 0x0201f800, 0x00104237, 0x0201f800, 0x0010801c, - 0x0401f00c, 0x0201f800, 0x0010801c, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x0010203c, 0x5c027800, - 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47, - 0x0201f800, 0x00102074, 0x0201f000, 0x00107911, - 0x42000800, 0x00000003, 0x0201f800, 0x00104571, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000002, - 0x0201f000, 0x0010672b, 0x0401f915, 0x04020793, - 0x0201f800, 0x00102074, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x0010203c, 0x5c027800, 0x42000000, - 0x0010b864, 0x0201f800, 0x0010aa47, 0x42003000, - 0x00000018, 0x41782800, 0x42002000, 0x00000000, - 0x4d400000, 0x4d440000, 0x59368c03, 0x42028000, - 0x00000029, 0x0201f800, 0x0010985e, 0x5c028800, - 0x5c028000, 0x0201f000, 0x00107911, 0x0201f800, - 0x00104a14, 0x0401f7c8, 0x42000000, 0x0010b86d, - 0x0201f800, 0x0010aa47, 0x0201f800, 0x00107b76, - 0x040207c1, 0x1c01f000, 0x4d380000, 0x59327403, - 0x0201f800, 0x001093ba, 0x5c027000, 0x02020000, - 0x0002077d, 0x836c0580, 0x00000003, 0x04000004, - 0x4a026206, 0x00000002, 0x1c01f000, 0x59300403, - 0x48026416, 0x4a02621d, 0x00000001, 0x4a026403, - 0x00000085, 0x4a026203, 0x00000009, 0x4a026406, - 0x00000002, 0x42000800, 0x8000004b, 0x0201f000, - 0x00020721, 0x0201f800, 0x00102074, 0x0201f800, - 0x0010801c, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x0010203c, 0x5c027800, 0x42000000, 0x0010b864, - 0x0201f800, 0x0010aa47, 0x497a6008, 0x4a026406, - 0x00000007, 0x4a026206, 0x00000398, 0x497a6205, - 0x1c01f000, 0x42000000, 0x0010b870, 0x0201f800, - 0x0010aa47, 0x4d340000, 0x59326809, 0x59300203, - 0x82000c80, 0x0000000e, 0x02021800, 0x001005d8, - 0x4803c857, 0x0c01f803, 0x5c026800, 0x1c01f000, - 0x00108f96, 0x00108d85, 0x00108f96, 0x00108f96, - 0x00108f96, 0x00108f96, 0x00108f96, 0x00108f96, - 0x00108f96, 0x00108d85, 0x00108f98, 0x00108d85, - 0x00108fa0, 0x00108f96, 0x0201f800, 0x001005d8, - 0x4a026403, 0x0000008b, 0x4a026203, 0x0000000b, - 0x42000800, 0x8000404b, 0x0201f000, 0x00020721, - 0x59300a1d, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x0010203c, 0x5c027800, 0x42003000, 0x00000011, - 0x0201f800, 0x0010a942, 0x42000000, 0x0010b864, - 0x0201f800, 0x0010aa47, 0x41306800, 0x0201f800, - 0x0002075a, 0x04000008, 0x49366009, 0x4d300000, - 0x40366000, 0x0201f800, 0x00107911, 0x5c026000, - 0x0401f002, 0x40366000, 0x497a6008, 0x4a026406, - 0x00000001, 0x4a026403, 0x00000001, 0x0201f800, - 0x00103b25, 0x04000011, 0x4a026406, 0x00000004, - 0x4a026203, 0x00000007, 0x4a026420, 0x00000001, - 0x42003000, 0x00000004, 0x4d400000, 0x42028000, - 0x00000029, 0x41782800, 0x0201f800, 0x0010a43e, - 0x5c028000, 0x1c01f000, 0x42000800, 0x0000000b, - 0x0201f800, 0x00104571, 0x4a026203, 0x00000001, - 0x0201f000, 0x0010672b, 0x42000000, 0x0010b876, - 0x0201f800, 0x0010aa47, 0x59300203, 0x82000c80, - 0x0000000e, 0x02021800, 0x001005d8, 0x4803c857, - 0x0c01f001, 0x0010900b, 0x00108ff3, 0x00108ff7, - 0x0010900c, 0x00108ff5, 0x00108ff3, 0x00108ff3, - 0x00108ff3, 0x00108ff3, 0x00108ff3, 0x00108ff3, - 0x00108ff3, 0x00108ff3, 0x00108ff3, 0x0201f800, - 0x001005d8, 0x0201f800, 0x00100e99, 0x4d2c0000, - 0x59325808, 0x4a025a06, 0x00000006, 0x0201f800, - 0x000202da, 0x5c025800, 0x497a6008, 0x4a02621d, - 0x0000000a, 0x4a026403, 0x00000085, 0x4a026203, - 0x00000009, 0x4a026406, 0x00000002, 0x42000800, - 0x8000404b, 0x0201f000, 0x00020721, 0x1c01f000, - 0x0201f800, 0x00106c55, 0x4df00000, 0x0401fcc7, - 0x04020004, 0x0201f800, 0x00106e62, 0x0402000c, - 0x0201f800, 0x001067ae, 0x04020005, 0x5c03e000, - 0x0201f800, 0x00106c4b, 0x0401f7dd, 0x0201f800, - 0x00106b6c, 0x02020800, 0x001005d8, 0x5c03e000, - 0x0201f800, 0x00106c4b, 0x59300203, 0x82000d80, - 0x00000003, 0x02000800, 0x001005d8, 0x82000c80, - 0x0000000e, 0x02021800, 0x001005d8, 0x0c01f7ba, - 0x4803c856, 0x59a8000e, 0x59a80867, 0x80040400, - 0x80080480, 0x04021004, 0x82000540, 0x00000001, - 0x1c01f000, 0x80000580, 0x1c01f000, 0x4803c856, - 0x4c080000, 0x59301008, 0x82081500, 0xfff00000, - 0x5c001000, 0x1c01f000, 0x4803c856, 0x4d300000, - 0x0201f800, 0x0002075a, 0x0400000a, 0x0401f82f, - 0x4d380000, 0x42027000, 0x0000004b, 0x0201f800, - 0x000207a1, 0x5c027000, 0x82000540, 0x00000001, + 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, 0x00107942, 0x0400001b, 0x0401f81f, - 0x4d300000, 0x0201f800, 0x00106c55, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00106ab4, 0x0201f800, - 0x001067fd, 0x5c027800, 0x0201f800, 0x0010a2ff, - 0x0201f800, 0x00106c4b, 0x5c026000, 0x8d3e7d3e, - 0x0402000b, 0x4d380000, 0x42027000, 0x0000004c, - 0x0201f800, 0x000207a1, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x0201f800, - 0x0002077d, 0x0401f7fa, 0x592c0407, 0x494a6017, - 0x494e6018, 0x49366009, 0x492e6008, 0x4a026406, - 0x00000003, 0x800000c2, 0x800008c4, 0x80040400, - 0x48026206, 0x1c01f000, 0x493bc857, 0x4d300000, - 0x0201f800, 0x0002075a, 0x0400000d, 0x0401ffef, - 0x4d400000, 0x42028000, 0x00000005, 0x0401f80d, - 0x5c028000, 0x8d3e7d3e, 0x04020007, 0x0201f800, - 0x000207a1, 0x82000540, 0x00000001, 0x5c026000, - 0x1c01f000, 0x0201f800, 0x0002077d, 0x0401f7fa, - 0x4803c856, 0x0201f800, 0x00106c55, 0x4d3c0000, - 0x4d440000, 0x59368c03, 0x42027800, 0x00000001, - 0x0201f800, 0x001069b6, 0x0201f800, 0x0010692e, - 0x0201f800, 0x001067fd, 0x0201f800, 0x0010a2ff, - 0x5c028800, 0x5c027800, 0x0201f000, 0x00106c4b, - 0x4803c856, 0x4d300000, 0x0201f800, 0x0002075a, - 0x0400000f, 0x481a601c, 0x48ee6021, 0x49366009, - 0x4a026406, 0x00000001, 0x492e6008, 0x4d380000, - 0x42027000, 0x0000001f, 0x0201f800, 0x000207a1, - 0x5c027000, 0x82000540, 0x00000001, 0x5c026000, - 0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800, - 0x0002075a, 0x0400000e, 0x48ee6021, 0x49366009, - 0x4a026406, 0x00000001, 0x492e6008, 0x4d380000, - 0x42027000, 0x00000055, 0x0201f800, 0x000207a1, - 0x5c027000, 0x82000540, 0x00000001, 0x5c026000, - 0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800, - 0x0002075a, 0x0400000f, 0x481a601c, 0x48ee6021, + 0x0201f800, 0x00020892, 0x0400000e, 0x48ee6021, 0x49366009, 0x4a026406, 0x00000001, 0x492e6008, - 0x4d380000, 0x42027000, 0x0000003d, 0x0201f800, - 0x000207a1, 0x5c027000, 0x82000540, 0x00000001, + 0x4d380000, 0x42027000, 0x00000055, 0x0201f800, + 0x000208d8, 0x5c027000, 0x82000540, 0x00000001, 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000, - 0x0201f800, 0x00107942, 0x04000014, 0x49366009, - 0x492fc857, 0x4933c857, 0x592c0404, 0x8c00051e, - 0x04000003, 0x48efc857, 0x48ee6021, 0x4a026406, - 0x00000001, 0x492e6008, 0x4d380000, 0x42027000, - 0x00000000, 0x0201f800, 0x000207a1, 0x5c027000, - 0x82000540, 0x00000001, 0x5c026000, 0x1c01f000, - 0x4803c856, 0x4d300000, 0x0201f800, 0x0002075a, - 0x0400000f, 0x48ee6021, 0x481a601c, 0x49366009, + 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, 0x00000044, 0x0201f800, 0x000207a1, + 0x42027000, 0x00000000, 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, 0x00000001, 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800, - 0x0002075a, 0x0400000f, 0x481a601c, 0x48ee6021, + 0x00020892, 0x0400000f, 0x48ee6021, 0x481a601c, 0x49366009, 0x4a026406, 0x00000001, 0x492e6008, - 0x4d380000, 0x42027000, 0x00000049, 0x0201f800, - 0x000207a1, 0x5c027000, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x59300009, 0x80001540, - 0x02000800, 0x001005d8, 0x5808040b, 0x4803c856, - 0x80000040, 0x04001002, 0x4800140b, 0x1c01f000, - 0x4803c856, 0x59300403, 0x82000d80, 0x00000002, - 0x04000015, 0x82000d80, 0x00000003, 0x04000012, - 0x82000d80, 0x00000004, 0x0400000f, 0x82000d80, - 0x00000008, 0x0400000c, 0x82000d80, 0x0000000a, - 0x04000009, 0x599c0819, 0x8c040d0e, 0x04000004, - 0x82000d80, 0x00000000, 0x04000003, 0x82000540, - 0x00000001, 0x1c01f000, 0x4803c856, 0x4c000000, - 0x4d2c0000, 0x59300406, 0x82000580, 0x00000004, - 0x0400001d, 0x59300008, 0x80025d40, 0x800001c0, - 0x04000019, 0x0201f800, 0x00109597, 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, 0x00107942, 0x04000013, 0x49366009, - 0x48ee6021, 0x4a026406, 0x00000001, 0x492e6008, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c, - 0x5c027800, 0x4d380000, 0x42027000, 0x00000028, - 0x0201f800, 0x000207a1, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4803c856, - 0x83380580, 0x00000015, 0x0402000d, 0x59a80016, - 0x82000580, 0x00000074, 0x04020009, 0x0201f800, - 0x0010462a, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000029, 0x0201f000, 0x0010672b, 0x0201f800, - 0x0010801c, 0x0201f000, 0x0002077d, 0x4803c856, - 0x83380580, 0x00000016, 0x04020007, 0x42000800, - 0x00000004, 0x0201f800, 0x00104571, 0x0201f000, - 0x00107b38, 0x83380580, 0x00000015, 0x04020013, - 0x59a80016, 0x82000580, 0x00000014, 0x0402000f, - 0x0201f800, 0x0010468d, 0x0201f800, 0x0010846f, - 0x0402000a, 0x59340404, 0x80000540, 0x04000007, - 0x42000800, 0x00000006, 0x0201f800, 0x00104571, - 0x0201f000, 0x00107b38, 0x0201f800, 0x0010801c, - 0x0201f000, 0x0002077d, 0x4803c856, 0x592c0206, - 0x82000580, 0x00000005, 0x04000002, 0x1c01f000, - 0x4803c856, 0x592c0208, 0x8400054a, 0x48025a08, - 0x1c01f000, 0x497a6205, 0x497a6008, 0x4a026203, - 0x00000001, 0x4a026403, 0x00000050, 0x42000800, - 0x80000043, 0x0201f000, 0x00020721, 0x4933c857, + 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, - 0x04000006, 0x59300406, 0x82000c80, 0x00000012, - 0x04021004, 0x0c01f806, 0x5c026800, 0x1c01f000, - 0x0201f800, 0x00108d7c, 0x0401f7fc, 0x00108d7c, - 0x001091fd, 0x00109201, 0x00109204, 0x0010a49b, - 0x0010a4b8, 0x0010a4bc, 0x00108d7c, 0x00108d7c, - 0x00108d7c, 0x00108d7c, 0x00108d7c, 0x00108d7c, - 0x00108d7c, 0x00108d7c, 0x00108d7c, 0x00108d7c, - 0x00108d7c, 0x4803c856, 0x40000000, 0x40000000, - 0x1c01f000, 0x40000000, 0x40000000, 0x1c01f000, - 0x5930001c, 0x4803c857, 0x59300414, 0x4933c857, - 0x4803c857, 0x8c000502, 0x04000005, 0x84000502, - 0x84000540, 0x48026414, 0x1c01f000, 0x42000000, - 0xd0000000, 0x41300800, 0x0201f800, 0x00100b94, - 0x0401f80a, 0x04020008, 0x59a80037, 0x82000400, - 0x0000000a, 0x48026205, 0x59300414, 0x84000542, - 0x48026414, 0x1c01f000, 0x4933c857, 0x4d340000, - 0x59326809, 0x59340200, 0x8c00050e, 0x02000800, - 0x001005d8, 0x5930001c, 0x80000540, 0x0402002f, - 0x59a80021, 0x80000540, 0x0402002a, 0x4d1c0000, - 0x41323800, 0x0201f800, 0x0002075a, 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, - 0x00020721, 0x411e6000, 0x5c023800, 0x80000580, - 0x5c026800, 0x1c01f000, 0x411e6000, 0x5c023800, - 0x59a80039, 0x48026205, 0x82000540, 0x00000001, - 0x0401f7f8, 0x4933c857, 0x4d2c0000, 0x4932381c, - 0x4a026202, 0x0000ffff, 0x591e5808, 0x591c0007, - 0x8c00051e, 0x04000005, 0x8400051e, 0x48023807, - 0x497a5c09, 0x0401f014, 0x592c0408, 0x8c000518, - 0x04000011, 0x84000518, 0x48025c08, 0x4a025c09, - 0x00000001, 0x0401fb2f, 0x497a5c09, 0x592c0408, - 0x8c000512, 0x04000008, 0x4d2c0000, 0x84000512, - 0x48025c08, 0x592e5809, 0x0201f800, 0x001007fd, - 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, 0x00020721, - 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, 0x001066a0, 0x800811c0, - 0x04020003, 0x42001000, 0x00000014, 0x480b5037, - 0x59a81036, 0x480b502d, 0x41780800, 0x42000000, - 0x00000064, 0x0201f800, 0x001066a0, 0x800811c0, - 0x04020003, 0x42001000, 0x00000014, 0x480b5038, - 0x82081400, 0x0000000a, 0x480b5039, 0x42000800, - 0x00000001, 0x0201f800, 0x00106c78, 0x42000000, - 0x30000000, 0x40080800, 0x0201f800, 0x00100b68, - 0x42000800, 0x00000003, 0x59a81010, 0x0201f800, - 0x00106c78, 0x0201f000, 0x00104906, 0x4a035037, - 0x00000028, 0x4a035038, 0x00000014, 0x4a03502d, - 0x000007d0, 0x42001000, 0x0000001e, 0x480b5039, - 0x42000800, 0x00000001, 0x0201f800, 0x00106c78, - 0x42000000, 0x30000000, 0x40080800, 0x0201f800, - 0x00100b68, 0x42000800, 0x00000003, 0x59a81010, - 0x0201f000, 0x00106c78, 0x4933c857, 0x4d2c0000, - 0x59300403, 0x82000580, 0x0000003e, 0x04020005, - 0x59325817, 0x812e59c0, 0x02020800, 0x001007f4, - 0x5c025800, 0x1c01f000, 0x4937c857, 0x4d300000, - 0x0201f800, 0x0002075a, 0x04000011, 0x49366009, + 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, - 0x00000009, 0x0201f800, 0x00104571, 0x4d380000, - 0x42027000, 0x00000033, 0x0201f800, 0x000207a1, + 0x0000000b, 0x0201f800, 0x001043c7, 0x4d380000, + 0x42027000, 0x00000043, 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, 0x00000001, 0x5c026000, - 0x1c01f000, 0x4933c857, 0x4d2c0000, 0x4c580000, - 0x4d3c0000, 0x59325808, 0x83380580, 0x00000015, - 0x04020022, 0x59a8b016, 0x82580c80, 0x00000019, - 0x04001003, 0x4200b000, 0x00000018, 0x8058b104, - 0x0401fa07, 0x80000580, 0x0401fa17, 0x832cac00, - 0x00000009, 0x83cca400, 0x00000006, 0x0201f800, - 0x0010ab17, 0x42027800, 0x00000001, 0x592c100a, - 0x8c081518, 0x04020006, 0x59a80010, 0x592c100d, - 0x80080580, 0x04020006, 0x417a7800, 0x59301009, - 0x58081403, 0x0201f800, 0x001020a1, 0x0201f800, - 0x00107b38, 0x0401f008, 0x4200b000, 0x00000002, - 0x0401fa09, 0x0201f800, 0x0010801c, 0x0201f800, - 0x0002077d, 0x5c027800, 0x5c00b000, 0x5c025800, - 0x1c01f000, 0x4933c856, 0x49366009, 0x4a026406, - 0x00000001, 0x492e6008, 0x4d380000, 0x42027000, - 0x0000004d, 0x0201f800, 0x000207a1, 0x5c027000, - 0x82000540, 0x00000001, 0x1c01f000, 0x4803c856, - 0x4d2c0000, 0x83380580, 0x00000015, 0x04020027, - 0x59a80816, 0x59325808, 0x5930040b, 0x800000c4, - 0x80040580, 0x04020021, 0x4c500000, 0x4c540000, - 0x4c580000, 0x83cca400, 0x00000006, 0x4050a800, - 0x5930b40b, 0x0201f800, 0x0010ab28, 0x83cca400, - 0x00000006, 0x592cb205, 0x832cac00, 0x00000006, - 0x0201f800, 0x0010ab17, 0x592e5801, 0x812e59c0, - 0x040207f9, 0x5931d821, 0x58ef400b, 0x58ee580d, - 0x4a025a04, 0x00000103, 0x58ec0009, 0x0801f800, - 0x59300402, 0x5c00b000, 0x5c00a800, 0x5c00a000, - 0x5c025800, 0x1c01f000, 0x0201f800, 0x0010801c, - 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, 0x001005d8, 0x42000800, - 0x0000012c, 0x4a0370e4, 0x20000000, 0x59b800e4, - 0x80040840, 0x02000800, 0x001005d8, 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, - 0x0401fc1c, 0x04000008, 0x42000800, 0x00000024, - 0x0201f800, 0x00106681, 0x82063c00, 0x0010d1c0, - 0x491fc857, 0x1c01f000, 0x83300480, 0x0010d1c0, - 0x0400100a, 0x59a8000b, 0x81300480, 0x04021007, - 0x59301402, 0x0401ffef, 0x04000007, 0x411c0000, - 0x81300580, 0x04000003, 0x81780500, 0x0401f002, - 0x81300540, 0x1c01f000, 0x4947c857, 0x4d300000, - 0x0201f800, 0x00020245, 0x0402000a, 0x42026000, - 0x0010bde9, 0x49366009, 0x492e6008, 0x0201f800, - 0x0010203c, 0x80000580, 0x5c026000, 0x1c01f000, - 0x82000540, 0x00000001, 0x0401f7fc, 0x4933c857, - 0x0201f800, 0x00109037, 0x02000800, 0x001005d8, - 0x4d2c0000, 0x4d340000, 0x4d440000, 0x4c580000, - 0x59325808, 0x59326809, 0x49425a06, 0x0201f800, - 0x00105755, 0x592e8c06, 0x592c4207, 0x82200500, - 0x0000000f, 0x0c01f806, 0x5c00b000, 0x5c028800, - 0x5c026800, 0x5c025800, 0x1c01f000, 0x00109466, - 0x00109488, 0x0010948f, 0x00109493, 0x0010949c, - 0x00109463, 0x00109463, 0x00109463, 0x001094a0, - 0x001094ac, 0x001094ac, 0x00109463, 0x00109463, - 0x00109463, 0x00109463, 0x00109463, 0x4803c857, - 0x0201f800, 0x001005d8, 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, - 0x00104a1f, 0x04000014, 0x8c20450e, 0x04000002, - 0x497a6009, 0x4178b000, 0x497a5a06, 0x0401f004, - 0x8340b540, 0x00000000, 0x0402000b, 0x592c0404, - 0x8400051c, 0x48025c04, 0x592c0207, 0x8400051e, - 0x48025a07, 0x0401f8aa, 0x497a6008, 0x0201f000, - 0x000202da, 0x592c0207, 0x8c00051e, 0x4200b000, - 0x00000002, 0x040207f2, 0x8204b540, 0x00000000, - 0x040007ef, 0x44042800, 0x4200b000, 0x00000001, - 0x0401f7eb, 0x4937c857, 0x4d300000, 0x0201f800, - 0x0002075a, 0x04000011, 0x49366009, 0x4a026406, - 0x00000001, 0x492e6008, 0x42000800, 0x0000000b, - 0x0201f800, 0x00104571, 0x4d380000, 0x42027000, - 0x00000043, 0x0201f800, 0x000207a1, 0x5c027000, + 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, 0x4d2c0000, 0x59325808, 0x83380580, - 0x00000015, 0x04020025, 0x59a80016, 0x82000580, - 0x00000004, 0x04020021, 0x59a80010, 0x592c1009, - 0x80080580, 0x04020010, 0x4d440000, 0x592e8c06, - 0x592c0207, 0x4803c856, 0x82000500, 0x00000080, - 0x84000548, 0x4d3c0000, 0x42027800, 0x00001000, - 0x0201f800, 0x001049bb, 0x5c027800, 0x5c028800, - 0x0401f004, 0x4803c856, 0x0201f800, 0x00104a1f, - 0x0201f800, 0x00109037, 0x04000017, 0x4d400000, - 0x42028000, 0x00000000, 0x41780800, 0x0401ff38, - 0x5c028000, 0x0401f00e, 0x0201f800, 0x00104a1f, - 0x040207f4, 0x0201f800, 0x00109037, 0x0400000a, - 0x4c580000, 0x4200b000, 0x00000002, 0x0401f86e, - 0x5c00b000, 0x0201f800, 0x0010801c, 0x0201f800, - 0x0002077d, 0x5c025800, 0x1c01f000, 0x4937c857, - 0x4d300000, 0x0201f800, 0x0002075a, 0x04000012, - 0x49366009, 0x4a026406, 0x00000001, 0x4d3c0000, - 0x4d380000, 0x417a7800, 0x0201f800, 0x00104567, - 0x492e6008, 0x42027000, 0x00000004, 0x0201f800, - 0x000207a1, 0x5c027000, 0x5c027800, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4937c857, - 0x4d300000, 0x0201f800, 0x00107942, 0x0400000d, - 0x49366009, 0x4a026406, 0x00000001, 0x492e6008, - 0x4d380000, 0x42027000, 0x00000051, 0x0201f800, - 0x000207a1, 0x5c027000, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x4933c857, 0x4c580000, - 0x59325808, 0x83383580, 0x00000015, 0x04020011, - 0x592c0008, 0x82000500, 0x00ffffff, 0x0402000a, - 0x0201f800, 0x00105755, 0x59cc0000, 0x82000500, - 0x00ffffff, 0x44002800, 0x4200b000, 0x00000001, - 0x0401f80b, 0x0201f800, 0x00107b38, 0x0401f006, - 0x4200b000, 0x00000002, 0x0401f823, 0x0201f800, - 0x0010801c, 0x5c00b000, 0x1c01f000, 0x492fc857, - 0x4c580000, 0x4c000000, 0x8058b1c0, 0x0400000b, - 0x82580500, 0xfffffff0, 0x02020800, 0x001005d8, - 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, - 0x00105755, 0x46002800, 0x00000018, 0x80142800, - 0x8058b040, 0x83cca400, 0x00000007, 0x4014a800, - 0x0201f800, 0x0010ab17, 0x5c00b000, 0x5c00a800, - 0x5c00a000, 0x5c025800, 0x1c01f000, 0x59325808, - 0x592c0204, 0x82000580, 0x00000152, 0x1c01f000, - 0x5930001f, 0x80000540, 0x02020800, 0x00100d56, - 0x1c01f000, 0x4d2c0000, 0x59325808, 0x59300203, - 0x4933c857, 0x492fc857, 0x493bc857, 0x4803c857, - 0x82003480, 0x0000000e, 0x02021800, 0x001005d8, - 0x0c01f803, 0x5c025800, 0x1c01f000, 0x001095bd, - 0x001095c8, 0x00109603, 0x001095bd, 0x001095bd, - 0x001095bd, 0x001095bd, 0x001095bd, 0x001095bf, - 0x001095bd, 0x001095bd, 0x001095bd, 0x001095bd, - 0x001095bd, 0x0201f800, 0x001005d8, 0x83383480, - 0x00000056, 0x02021800, 0x001005d8, 0x493a6403, - 0x4a026203, 0x00000001, 0x0201f000, 0x0010672b, - 0x83380580, 0x00000013, 0x0402000f, 0x592c000c, - 0x800001c0, 0x04000006, 0x4a026203, 0x00000002, - 0x59a80037, 0x48026206, 0x1c01f000, 0x4a025a06, - 0x00000000, 0x0201f800, 0x000202da, 0x0201f000, - 0x0002077d, 0x83380580, 0x00000027, 0x0400001a, - 0x83380580, 0x00000014, 0x04000012, 0x83380580, - 0x00000015, 0x04000005, 0x83380580, 0x00000016, - 0x02020800, 0x001005d8, 0x0201f800, 0x00106f60, - 0x02020000, 0x00107974, 0x59300203, 0x82000580, - 0x00000002, 0x02020800, 0x001005d8, 0x0401f014, - 0x0201f800, 0x00106bbf, 0x4a02580e, 0x00000011, - 0x0401f005, 0x0201f800, 0x00106bbf, 0x4a02580e, + 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, 0x000202da, 0x0201f800, - 0x00104c19, 0x0201f000, 0x00107911, 0x59341400, + 0x00000004, 0x0201f800, 0x00020381, 0x0201f800, + 0x00104a83, 0x0201f000, 0x00107698, 0x59341400, 0x82081d00, 0x000000ff, 0x59300c03, 0x480bc857, 0x4807c857, 0x82040580, 0x00000053, 0x0400002e, 0x82040580, 0x00000002, 0x04000016, 0x82040580, @@ -9647,10 +9506,10 @@ uint32_t risc_code01[] = { 0x0400001c, 0x82040580, 0x00000005, 0x0400001d, 0x82040580, 0x00000033, 0x0400001a, 0x82040580, 0x00000000, 0x0400001b, 0x82040580, 0x00000004, - 0x02020800, 0x001005d8, 0x0401f8a1, 0x0401f016, + 0x02020800, 0x00100615, 0x0401f8a1, 0x0401f016, 0x820c0580, 0x00000003, 0x0400084c, 0x0401f012, 0x820c0580, 0x0000000b, 0x0402000f, 0x42000800, - 0x00000007, 0x0201f800, 0x00104571, 0x0401f00a, + 0x00000007, 0x0201f800, 0x001043c7, 0x0401f00a, 0x820c0580, 0x00000005, 0x04000864, 0x0401f006, 0x820c0580, 0x00000009, 0x04000889, 0x0401f002, 0x0401f893, 0x4a026403, 0x00000052, 0x59a81016, @@ -9661,80 +9520,80 @@ uint32_t risc_code01[] = { 0x4a025a06, 0x00000007, 0x40001000, 0x0401f006, 0x4a025a06, 0x00000015, 0x0401f003, 0x4a025a06, 0x00000000, 0x480a580c, 0x82081400, 0x00000003, - 0x80081104, 0x0201f800, 0x00107ab5, 0x04000010, + 0x80081104, 0x0201f800, 0x0010783c, 0x04000010, 0x592c1001, 0x480a600b, 0x58080800, 0x82080400, 0x00000002, 0x592c1011, 0x592c1812, 0x42003000, - 0x00000000, 0x42002000, 0x00101200, 0x0201f800, - 0x00107c32, 0x04000002, 0x1c01f000, 0x4a025a06, - 0x0000002c, 0x497a580c, 0x0201f800, 0x000202da, - 0x0201f000, 0x0002077d, 0x83380580, 0x00000015, - 0x0402000a, 0x59a80005, 0x8c000514, 0x0402000b, - 0x0201f800, 0x0010462a, 0x42000800, 0x00000004, - 0x0201f000, 0x00104571, 0x42000800, 0x00000007, - 0x0201f000, 0x00104571, 0x0201f800, 0x0010513b, + 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, - 0x00104c6d, 0x040007e7, 0x592c040b, 0x84000540, + 0x00104ada, 0x040007e7, 0x592c040b, 0x84000540, 0x48025c0b, 0x0401f7e9, 0x83380580, 0x00000015, - 0x0402000f, 0x59a80005, 0x8c000514, 0x04020010, - 0x0201f800, 0x0010468d, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00104567, 0x5c027800, 0x42000800, - 0x00000006, 0x0201f000, 0x00104571, 0x42000800, - 0x00000004, 0x0201f000, 0x00104571, 0x0201f800, - 0x0010513b, 0x42001000, 0x00000010, 0x04020009, + 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, 0x00104c6d, 0x040007e2, 0x592c040b, + 0x0201f800, 0x00104ada, 0x040007e2, 0x592c040b, 0x84000540, 0x48025c0b, 0x0401f7e9, 0x42000800, - 0x00000004, 0x0201f000, 0x00104571, 0x83380580, - 0x00000015, 0x04020005, 0x0201f800, 0x0010a2c8, - 0x02000800, 0x001048c1, 0x1c01f000, 0x83380580, + 0x00000004, 0x0201f000, 0x001043c7, 0x83380580, + 0x00000015, 0x04020005, 0x0201f800, 0x0010a0b1, + 0x02000800, 0x00104711, 0x1c01f000, 0x83380580, 0x00000015, 0x0402001d, 0x4c580000, 0x83cc1400, 0x00000008, 0x4200b000, 0x00000002, 0x83341c00, - 0x00000006, 0x0201f800, 0x0010855a, 0x04020012, + 0x00000006, 0x0201f800, 0x001082ff, 0x04020012, 0x83cc1400, 0x0000000a, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000008, 0x0201f800, 0x0010855a, + 0x83341c00, 0x00000008, 0x0201f800, 0x001082ff, 0x04020009, 0x59342200, 0x59cc1007, 0x800811c0, 0x04000003, 0x480a6801, 0x84102542, 0x8410251a, 0x48126a00, 0x5c00b000, 0x1c01f000, 0x42000000, - 0x0010b87b, 0x0201f800, 0x0010aa47, 0x0201f800, - 0x00106c55, 0x59300203, 0x4933c857, 0x4803c857, - 0x82000c80, 0x0000000e, 0x02021800, 0x001005d8, - 0x0c01f803, 0x0201f000, 0x00106c4b, 0x0010970b, - 0x0010971a, 0x0010970c, 0x00109709, 0x00109709, - 0x00109709, 0x00109709, 0x00109709, 0x00109709, - 0x00109709, 0x00109709, 0x00109709, 0x00109709, - 0x00109709, 0x0201f800, 0x001005d8, 0x1c01f000, + 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, - 0x00108d85, 0x0201f800, 0x00104c19, 0x59325808, - 0x4a025a06, 0x00000006, 0x0201f800, 0x000202da, - 0x0201f000, 0x00107911, 0x59301804, 0x840c0520, + 0x00108b39, 0x0201f800, 0x00104a83, 0x59325808, + 0x4a025a06, 0x00000006, 0x0201f800, 0x00020381, + 0x0201f000, 0x00107698, 0x59301804, 0x840c0520, 0x48026004, 0x598c000d, 0x81300580, 0x04020010, - 0x8c0c1d20, 0x04020010, 0x42001000, 0x0010b7f6, + 0x8c0c1d20, 0x04020010, 0x42001000, 0x0010b5f4, 0x50081000, 0x58080002, 0x82000580, 0x00000100, 0x0400000e, 0x5808000c, 0x81300580, 0x02020800, - 0x001005d8, 0x4978100c, 0x0401f003, 0x8c0c1d20, - 0x040207dc, 0x0201f800, 0x001068d3, 0x040007d9, - 0x0201f800, 0x001005d8, 0x0201f800, 0x00106e8e, + 0x00100615, 0x4978100c, 0x0401f003, 0x8c0c1d20, + 0x040207dc, 0x0201f800, 0x00106619, 0x040007d9, + 0x0201f800, 0x00100615, 0x0201f800, 0x00106be2, 0x040007f9, 0x59300203, 0x82000c80, 0x0000000e, - 0x02021800, 0x001005d8, 0x0c01f7bd, 0x4933c857, + 0x02021800, 0x00100615, 0x0c01f7bd, 0x4933c857, 0x4c500000, 0x4c540000, 0x4c580000, 0x592c0c07, 0x4806580a, 0x59cc0809, 0x48065807, 0x59cc0a08, - 0x4806580b, 0x59c80817, 0x82040500, 0x000003ff, + 0x4806580b, 0x59a8086e, 0x82040500, 0x000003ff, 0x800010c4, 0x8c040d14, 0x04000005, 0x59cc0002, 0x82000500, 0x00000003, 0x80081480, 0x82080480, - 0x000000f1, 0x02021800, 0x001005d8, 0x480a621a, - 0x412c0800, 0x0201f800, 0x001007d3, 0x02000800, - 0x001005d8, 0x492c0809, 0x58040408, 0x84000552, + 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, 0x0010ab28, + 0x4004b000, 0x4c000000, 0x0201f800, 0x0010a94f, 0x5c000000, 0x800001c0, 0x0400000d, 0x412c1000, - 0x4c000000, 0x0201f800, 0x001007d3, 0x02000800, - 0x001005d8, 0x492c1001, 0x832cac00, 0x00000004, + 0x4c000000, 0x0201f800, 0x00100819, 0x02000800, + 0x00100615, 0x492c1001, 0x832cac00, 0x00000004, 0x5c000000, 0x40001000, 0x0401f7e9, 0x5c00b000, 0x5c00a800, 0x5c00a000, 0x1c01f000, 0x4933c857, 0x4d2c0000, 0x4c380000, 0x59325808, 0x5930021a, @@ -9743,7 +9602,7 @@ uint32_t risc_code01[] = { 0x00000c00, 0x0400000b, 0x0401f00b, 0x8c08153e, 0x04000006, 0x4a025a06, 0x00000007, 0x80081080, 0x80081000, 0x0401f003, 0x4a025a06, 0x00000015, - 0x480a5807, 0x42000000, 0x0010bed9, 0x50007000, + 0x480a5807, 0x42000000, 0x0010bcd8, 0x50007000, 0x5838000b, 0x80000540, 0x04020008, 0x4930700c, 0x4930700b, 0x58380002, 0x82000580, 0x00000000, 0x04020809, 0x0401f005, 0x82001400, 0x00000000, @@ -9756,613 +9615,622 @@ uint32_t risc_code01[] = { 0x82080480, 0x00000010, 0x04021003, 0x80000580, 0x0401f003, 0x42001000, 0x00000010, 0x4800700d, 0x48087004, 0x800810c4, 0x48087005, 0x40381000, - 0x0201f800, 0x00100858, 0x1c01f000, 0x4d2c0000, - 0x0201f800, 0x001007d3, 0x02000800, 0x001005d8, - 0x42000800, 0x0010bed9, 0x452c0800, 0x497a580b, - 0x497a580c, 0x497a580d, 0x4a025809, 0x001097ea, + 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, - 0x001007f4, 0x5c000800, 0x800409c0, 0x0400001c, + 0x0010083a, 0x5c000800, 0x800409c0, 0x0400001c, 0x4804b80a, 0x585c100d, 0x800811c0, 0x04020005, - 0x40065800, 0x0201f800, 0x001007fd, 0x0401f014, + 0x40065800, 0x0201f800, 0x00100843, 0x0401f014, 0x82080480, 0x00000010, 0x04021003, 0x80000580, 0x0401f003, 0x42001000, 0x00000010, 0x4800b80d, 0x4808b804, 0x800810c4, 0x4808b805, 0x82040400, 0x00000004, 0x4800b803, 0x405c1000, 0x0201f800, - 0x00100858, 0x0401f025, 0x0401f828, 0x585c000c, + 0x001008a1, 0x0401f025, 0x0401f828, 0x585c000c, 0x80026540, 0x59300000, 0x80000d40, 0x04020002, 0x4800b80b, 0x4800b80c, 0x497a6000, 0x4c000000, 0x4978b80a, 0x59325808, 0x4a025a04, 0x00000103, 0x59300402, 0x48025c06, 0x592c100b, 0x4c080000, - 0x0201f800, 0x000202c1, 0x0201f800, 0x0010912a, + 0x0201f800, 0x00020381, 0x0201f800, 0x00108ee7, 0x5c001000, 0x8c081518, 0x04000004, 0x0201f800, - 0x001091d1, 0x0401f003, 0x0201f800, 0x0002077d, + 0x00108f88, 0x0401f003, 0x0201f800, 0x000208b4, 0x405c7000, 0x5c000000, 0x80026540, 0x04000003, 0x59325808, 0x0401ff78, 0x5c00b800, 0x5c025800, 0x5c026000, 0x1c01f000, 0x483bc857, 0x5838000a, - 0x40025800, 0x0201f800, 0x001007fd, 0x5838000c, + 0x40025800, 0x0201f800, 0x00100843, 0x5838000c, 0x80026540, 0x59300008, 0x80025d40, 0x4a025a06, 0x00000002, 0x1c01f000, 0x4803c857, 0x4d1c0000, 0x497a601c, 0x41323800, 0x40026000, 0x4d3c0000, - 0x42027800, 0x00000005, 0x0401f83c, 0x5c027800, + 0x42027800, 0x00000005, 0x0401f840, 0x5c027800, 0x411e6000, 0x59300414, 0x84000502, 0x48026414, 0x5c023800, 0x1c01f000, 0x481bc857, 0x4933c857, 0x4c5c0000, 0x4c600000, 0x4010b800, 0x4014c000, - 0x0201f800, 0x0010a942, 0x0201f800, 0x00103b25, + 0x0201f800, 0x0010a766, 0x0201f800, 0x0010393e, 0x04000008, 0x40602800, 0x405c3000, 0x0201f800, - 0x0010a446, 0x82000540, 0x00000001, 0x0401f002, + 0x0010a258, 0x82000540, 0x00000001, 0x0401f002, 0x80000580, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x4803c856, 0x4d300000, 0x42026000, 0x0010d1c0, - 0x59a8000e, 0x81640580, 0x04000016, 0x59300c06, - 0x82040580, 0x00000001, 0x04000009, 0x82040580, + 0x4803c856, 0x4d300000, 0x42026000, 0x0010cfc0, + 0x59a8000e, 0x81640580, 0x0400001a, 0x59300c06, + 0x82040580, 0x00000001, 0x0400000d, 0x82040580, 0x00000004, 0x04000006, 0x82040580, 0x00000010, - 0x02000800, 0x00108cf9, 0x0401f005, 0x4807c857, - 0x0201f800, 0x001092d7, 0x04020808, 0x83326400, - 0x00000024, 0x41580000, 0x81300480, 0x040017e9, + 0x02000800, 0x00108aad, 0x0401f009, 0x59300203, + 0x82000d80, 0x00000007, 0x04000005, 0x4807c857, + 0x0201f800, 0x0010909d, 0x04020808, 0x83326400, + 0x00000024, 0x41580000, 0x81300480, 0x040017e5, 0x5c026000, 0x1c01f000, 0x4933c857, 0x59300403, - 0x4803c857, 0x0201f800, 0x00106c55, 0x4df00000, + 0x4803c857, 0x0201f800, 0x0010698c, 0x4df00000, 0x59300406, 0x4803c857, 0x82000d80, 0x00000002, 0x04000018, 0x82000d80, 0x00000001, 0x04000009, 0x82000d80, 0x00000004, 0x04000006, 0x4933c856, - 0x5c03e000, 0x02000800, 0x00106c4b, 0x0401f03c, + 0x5c03e000, 0x02000800, 0x00106982, 0x0401f03c, 0x59300203, 0x82000d80, 0x00000001, 0x04000018, 0x82000d80, 0x00000002, 0x04000026, 0x82000d80, - 0x00000005, 0x04000023, 0x0201f800, 0x001005d8, + 0x00000005, 0x04000023, 0x0201f800, 0x00100615, 0x59300203, 0x82000d80, 0x00000009, 0x0400000c, 0x82000d80, 0x0000000b, 0x04000009, 0x82000d80, 0x0000000a, 0x04000017, 0x82000d80, 0x0000000c, - 0x04000014, 0x0201f800, 0x001005d8, 0x598c000d, - 0x81300580, 0x04020004, 0x0201f800, 0x00106e8e, + 0x04000014, 0x0201f800, 0x00100615, 0x598c000d, + 0x81300580, 0x04020004, 0x0201f800, 0x00106be2, 0x0402000c, 0x59300004, 0x4803c857, 0x8c000520, 0x04000004, 0x84000520, 0x48026004, 0x0401f005, - 0x0201f800, 0x001068d3, 0x02020800, 0x001005d8, - 0x5c03e000, 0x02000800, 0x00106c4b, 0x59300406, + 0x0201f800, 0x00106619, 0x02020800, 0x00100615, + 0x5c03e000, 0x02000800, 0x00106982, 0x59300406, 0x82000d80, 0x00000002, 0x04000009, 0x0201f800, - 0x00104c19, 0x0201f800, 0x0010914e, 0x02000800, - 0x0010801c, 0x8d3e7d00, 0x04000003, 0x0201f000, - 0x00107911, 0x4a02621d, 0x00000001, 0x4a026403, + 0x00104a83, 0x0201f800, 0x00108f05, 0x02000800, + 0x00107da6, 0x8d3e7d00, 0x04000003, 0x0201f000, + 0x00107698, 0x4a02621d, 0x00000001, 0x4a026403, 0x00000085, 0x4a026203, 0x00000009, 0x4a026406, 0x00000002, 0x42000800, 0x8000004b, 0x0201f000, - 0x00020721, 0x4933c857, 0x59368c03, 0x4c180000, + 0x00020855, 0x4933c857, 0x59368c03, 0x4c180000, 0x59300203, 0x82003480, 0x0000000e, 0x02021800, - 0x001005d8, 0x0c01f803, 0x5c003000, 0x1c01f000, - 0x0010990a, 0x00109dcf, 0x00109edb, 0x0010990a, - 0x0010990a, 0x0010990a, 0x0010990a, 0x0010990a, - 0x0010992d, 0x0010990a, 0x0010990a, 0x0010990a, - 0x0010990a, 0x0010990a, 0x0201f800, 0x001005d8, + 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, 0x001005d8, - 0x0c01f803, 0x5c003000, 0x1c01f000, 0x00109929, - 0x0010a180, 0x00109929, 0x00109929, 0x00109929, - 0x00109929, 0x00109929, 0x0010a952, 0x0010a0ed, - 0x0010a52c, 0x0010a562, 0x0010a52c, 0x0010a562, - 0x00109929, 0x0201f800, 0x001005d8, 0x0201f800, - 0x001005d8, 0x83383480, 0x00000051, 0x02021800, - 0x001005d8, 0x41380000, 0x493bc857, 0x4d1c0000, + 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, 0x0010998a, 0x00109b69, 0x0010998a, - 0x0010998a, 0x0010998a, 0x00109b74, 0x0010998a, - 0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a, - 0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a, - 0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a, - 0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a, - 0x001099ac, 0x001099f5, 0x00109a0c, 0x00109a62, - 0x00109ac6, 0x00109b04, 0x00109b34, 0x0010998a, - 0x0010998a, 0x00109b7c, 0x0010998a, 0x0010998a, - 0x00109b8a, 0x00109b93, 0x0010998a, 0x0010998a, - 0x0010998a, 0x0010998a, 0x0010998a, 0x00109c15, - 0x0010998a, 0x0010998a, 0x00109a9a, 0x0010998a, - 0x0010998a, 0x00109bec, 0x0010998a, 0x0010998a, - 0x0010998a, 0x00109c23, 0x0010998a, 0x0010998a, - 0x0010998a, 0x00109c6c, 0x0010998a, 0x0010998a, - 0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a, - 0x00109cb9, 0x0010998a, 0x00109ce5, 0x00109cf0, - 0x0010998a, 0x0010998a, 0x0010998c, 0x00109cfb, - 0x0010998a, 0x0010998a, 0x0010998a, 0x0010999b, - 0x0010998a, 0x0010998a, 0x0010998a, 0x00109d02, - 0x00109d0a, 0x00109d28, 0x0201f800, 0x001005d8, - 0x4933c857, 0x0201f800, 0x0010a592, 0x040203a4, - 0x0201f800, 0x0010210a, 0x040203a1, 0x59cc0407, + 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, 0x0010672b, 0x4933c857, - 0x0201f800, 0x0010a592, 0x04020395, 0x0201f800, - 0x0010210a, 0x04020392, 0x0401fbce, 0x040201a0, + 0x00000001, 0x0201f000, 0x00106470, 0x4933c857, + 0x0201f800, 0x0010a3b0, 0x04020399, 0x0201f800, + 0x00101eb0, 0x04020396, 0x0401fbd6, 0x0402019e, 0x59cc0007, 0x4802601c, 0x4a026403, 0x0000004a, - 0x4a026203, 0x00000001, 0x0201f000, 0x0010672b, - 0x4933c857, 0x0201f800, 0x0010210a, 0x04020009, - 0x0201f800, 0x001048ec, 0x04020006, 0x82000500, + 0x4a026203, 0x00000001, 0x0201f000, 0x00106470, + 0x4933c857, 0x0201f800, 0x00101eb0, 0x04020009, + 0x0201f800, 0x0010473b, 0x04020006, 0x82000500, 0x00000009, 0x82000580, 0x00000008, 0x04020008, 0x4a026403, 0x00000009, 0x4a02641a, 0x00000009, - 0x4a02621a, 0x00000000, 0x0401f1b2, 0x0201f800, - 0x001048c1, 0x0201f800, 0x00104a09, 0x04000021, - 0x0201f800, 0x001049ed, 0x0400001e, 0x0201f800, - 0x0010a252, 0x04020025, 0x42028000, 0x00000029, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c, - 0x5c027800, 0x0201f800, 0x0010462a, 0x836c0580, - 0x00000002, 0x04020004, 0x59a8001b, 0x80000000, - 0x4803501b, 0x4a026403, 0x00000008, 0x42003000, - 0x00000003, 0x0201f800, 0x00103b25, 0x04000191, - 0x4a026203, 0x00000007, 0x41782800, 0x0401f180, - 0x0201f800, 0x0010a3da, 0x040207e1, 0x4a026403, - 0x00000009, 0x4a02641a, 0x0000000e, 0x4a02621a, - 0x00001900, 0x0401f183, 0x4a026403, 0x00000009, - 0x4a02641a, 0x00000003, 0x4a02621a, 0x00000f00, - 0x0401f17c, 0x4933c857, 0x0201f800, 0x0010210a, - 0x0402033b, 0x0201f800, 0x001048ec, 0x04020338, - 0x493a6403, 0x0201f800, 0x0010a22d, 0x04020006, - 0x42003000, 0x00000005, 0x4a026403, 0x00000006, - 0x0401f7d9, 0x4a026403, 0x00000007, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00000000, 0x0401f165, - 0x4933c857, 0x0201f800, 0x001048ec, 0x04020324, - 0x0201f800, 0x0010a592, 0x02000800, 0x0010210a, - 0x0402031f, 0x0201f800, 0x00104a09, 0x04020005, - 0x42027800, 0x00000001, 0x0201f800, 0x00104567, - 0x0201f800, 0x001049fc, 0x0402002b, 0x59cc0206, - 0x82003500, 0x00000003, 0x0402002e, 0x82003480, - 0x00000014, 0x0400102b, 0x5934300a, 0x84183516, - 0x82000580, 0x00000014, 0x04020002, 0x84183556, - 0x481a680a, 0x59cc0406, 0x82000500, 0x00000003, - 0x04020020, 0x0201f800, 0x0010a29f, 0x04020028, - 0x0201f800, 0x001049e7, 0x0402000c, 0x417a7800, - 0x0201f800, 0x001020a1, 0x42003000, 0x00000006, - 0x0201f800, 0x0010a93a, 0x42000000, 0x0010b865, - 0x0201f800, 0x0010aa47, 0x0201f800, 0x0010468d, - 0x4a026403, 0x0000000a, 0x42003000, 0x00000020, - 0x0401f795, 0x4a026403, 0x0000000b, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00001e00, 0x0401f121, - 0x42000000, 0x0010b860, 0x0201f800, 0x0010aa47, - 0x4a026403, 0x0000000b, 0x4a02641a, 0x00000007, - 0x4a02621a, 0x00000000, 0x0401f116, 0x4a026403, - 0x0000000b, 0x4a02641a, 0x00000003, 0x4a02621a, - 0x00000000, 0x0401f10f, 0x4933c857, 0x0201f800, - 0x001048ec, 0x040202ce, 0x0201f800, 0x0010a592, - 0x040202cb, 0x0201f800, 0x0010210a, 0x040202c8, - 0x59cc0206, 0x82003500, 0x00000003, 0x0402001d, - 0x82003480, 0x00000014, 0x0400101a, 0x59cc0406, - 0x82000500, 0x00000003, 0x04020016, 0x59340400, - 0x82000580, 0x00000707, 0x04000019, 0x417a7800, - 0x0201f800, 0x001020a1, 0x42003000, 0x0000000a, - 0x0201f800, 0x0010a93a, 0x42000000, 0x0010b862, - 0x0201f800, 0x0010aa47, 0x4a026403, 0x0000000c, - 0x41782800, 0x42003000, 0x00000021, 0x0401f752, - 0x4a026403, 0x0000000d, 0x4a02641a, 0x00000007, - 0x4a02621a, 0x00000000, 0x0401f0de, 0x4a026403, - 0x0000000d, 0x4a02641a, 0x00000009, 0x4a02621a, - 0x00001e00, 0x0401f0d7, 0x4933c857, 0x0201f800, - 0x001048ec, 0x04020296, 0x0201f800, 0x0010a592, - 0x04020293, 0x0201f800, 0x0010210a, 0x04020290, - 0x0401facc, 0x0402001a, 0x493a6403, 0x4c5c0000, - 0x0401fad2, 0x0402000e, 0x4a026403, 0x0000002e, - 0x405c2800, 0x42003000, 0x00000024, 0x0201f800, - 0x00103b25, 0x0400000c, 0x4a026203, 0x00000007, - 0x405c2800, 0x5c00b800, 0x0401f0ad, 0x4a026403, - 0x0000000d, 0x4a02641a, 0x00000007, 0x4a02621a, - 0x00000000, 0x5c00b800, 0x0401f0b2, 0x4a026403, - 0x0000000d, 0x4a02641a, 0x00000009, 0x4a02621a, - 0x00001e00, 0x0401f0ab, 0x4933c857, 0x0201f800, - 0x001048ec, 0x040206ef, 0x59a80026, 0x82000500, - 0x00000009, 0x82000580, 0x00000008, 0x040006e9, - 0x0201f800, 0x001049fc, 0x0402002d, 0x0201f800, - 0x0010a2a7, 0x04020007, 0x4a026403, 0x0000000e, - 0x41782800, 0x42003000, 0x00000052, 0x0401f702, - 0x4933c857, 0x42003000, 0x00000003, 0x0201f800, - 0x0010a942, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x0010203c, 0x5c027800, 0x42000000, 0x0010b864, - 0x0201f800, 0x0010aa47, 0x59340200, 0x84000558, - 0x48026a00, 0x42000800, 0x0000000b, 0x0201f800, - 0x00104571, 0x0201f800, 0x00103b25, 0x04000076, - 0x42003000, 0x00000007, 0x0401f062, 0x4933c857, - 0x4a026403, 0x0000000f, 0x4a02641a, 0x00000003, - 0x4a02621a, 0x00001e00, 0x0401f072, 0x59340400, - 0x82000580, 0x00000703, 0x040007f5, 0x0401f040, - 0x4933c857, 0x0201f800, 0x001048ec, 0x0402022c, + 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, 0x04000226, 0x0201f800, 0x001049f3, - 0x0402002f, 0x0201f800, 0x0010a2c8, 0x02000800, - 0x0010a252, 0x04020007, 0x4a026403, 0x00000010, - 0x41782800, 0x42003000, 0x00000050, 0x0401f6c2, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c, - 0x5c027800, 0x42003000, 0x00000003, 0x0201f800, - 0x0010a942, 0x42000000, 0x0010b864, 0x0201f800, - 0x0010aa47, 0x59340200, 0x84000558, 0x48026a00, - 0x0401f7c5, 0x4a026403, 0x00000011, 0x4a02641a, - 0x00000003, 0x4a02621a, 0x00001e00, 0x0401f03d, - 0x4933c857, 0x0201f800, 0x0010210a, 0x02000800, - 0x0010a592, 0x040201fa, 0x0401fa36, 0x04020008, - 0x4a026403, 0x00000012, 0x0401f032, 0x59340400, - 0x82000580, 0x00000703, 0x040007eb, 0x4d3c0000, - 0x417a7800, 0x42028000, 0x00000029, 0x0201f800, - 0x0010203c, 0x5c027800, 0x42003000, 0x00000017, - 0x0201f800, 0x0010a942, 0x42000000, 0x0010b864, - 0x0201f800, 0x0010aa47, 0x0201f800, 0x00103b25, - 0x04000015, 0x42003000, 0x00000006, 0x41782800, - 0x42028000, 0x00000029, 0x4933c857, 0x4a026403, - 0x00000001, 0x4a026203, 0x00000007, 0x0201f800, - 0x0010a974, 0x0201f000, 0x0010a43e, 0x42028000, - 0x00000046, 0x0201f800, 0x0010a974, 0x0201f000, - 0x0010a43e, 0x4933c857, 0x4a026403, 0x00000001, - 0x42000800, 0x0000000b, 0x0201f800, 0x00104571, - 0x4a026203, 0x00000001, 0x0201f000, 0x0010672b, + 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, - 0x00104571, 0x4a026403, 0x00000005, 0x0401f7f5, - 0x0201f800, 0x0010a592, 0x040201b5, 0x0201f800, - 0x0010210a, 0x040201b2, 0x0401f9ee, 0x040207c0, + 0x001043c7, 0x4a026403, 0x00000005, 0x0401f7f5, + 0x0201f800, 0x0010a3b0, 0x040201b5, 0x0201f800, + 0x00101eb0, 0x040201b2, 0x0401f9f2, 0x040207ba, 0x4a026403, 0x00000020, 0x4a026203, 0x00000001, - 0x0201f000, 0x0010672b, 0x0201f800, 0x0010210a, + 0x0201f000, 0x00106470, 0x0201f800, 0x00101eb0, 0x040201a7, 0x4a026403, 0x00000023, 0x4a026203, - 0x00000001, 0x0201f000, 0x0010672b, 0x0201f800, - 0x0010a592, 0x02000800, 0x0010210a, 0x0402019c, - 0x0401f9d8, 0x040207aa, 0x40300800, 0x59a81010, + 0x00000001, 0x0201f000, 0x00106470, 0x0201f800, + 0x0010a3b0, 0x02000800, 0x00101eb0, 0x0402019c, + 0x0401f9dc, 0x040207a4, 0x40300800, 0x59a81010, 0x59cc0007, 0x82000500, 0x00ffffff, 0x80080580, - 0x04000019, 0x59cc1408, 0x0201f800, 0x0010902c, + 0x04000019, 0x59cc1408, 0x0201f800, 0x00108de9, 0x0400002d, 0x59cc0c08, 0x4d300000, 0x0201f800, - 0x00105dd7, 0x41323800, 0x5c026000, 0x04000026, + 0x00105b0f, 0x41323800, 0x5c026000, 0x04000026, 0x591c0202, 0x82000580, 0x0000ffff, 0x04000005, 0x59cc1208, 0x591c0202, 0x80080580, 0x0402001e, 0x591c0406, 0x82000580, 0x00000007, 0x0402001a, 0x0401f02c, 0x59cc1208, 0x82080580, 0x0000ffff, - 0x0400000c, 0x0201f800, 0x00109410, 0x04000012, + 0x0400000c, 0x0201f800, 0x001091d9, 0x04000012, 0x59cc1408, 0x591c0202, 0x80080580, 0x0402000e, 0x591c0009, 0x81340580, 0x04000016, 0x0401f00a, - 0x59cc1408, 0x417a7800, 0x0201f800, 0x0010a405, + 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, 0x0002077d, + 0x4d300000, 0x411e6000, 0x0201f800, 0x000208b4, 0x5c026000, 0x4a026403, 0x00000025, 0x0401f785, 0x4933c857, 0x4d3c0000, 0x42027800, 0x00000001, - 0x0201f800, 0x00104567, 0x5c027800, 0x4c580000, + 0x0201f800, 0x001043bd, 0x5c027800, 0x4c580000, 0x4200b000, 0x00000002, 0x83a81c00, 0x00000002, - 0x83cc1400, 0x0000000b, 0x0201f800, 0x0010855a, + 0x83cc1400, 0x0000000b, 0x0201f800, 0x001082ff, 0x5c00b000, 0x04000004, 0x4a026403, 0x00000031, - 0x0401f770, 0x0201f800, 0x00107911, 0x0201f800, - 0x0010513b, 0x0402000f, 0x0201f800, 0x00105149, + 0x0401f770, 0x0201f800, 0x00107698, 0x0201f800, + 0x00104e0d, 0x0402000f, 0x0201f800, 0x00104e1b, 0x04020008, 0x4a035033, 0x00000001, 0x4202d800, - 0x00000001, 0x0201f800, 0x001050a2, 0x0401f005, - 0x42000000, 0x00000001, 0x0201f800, 0x00105113, - 0x1c01f000, 0x0201f800, 0x0010210a, 0x0402011c, - 0x0401f958, 0x0402072a, 0x493a6403, 0x0401f996, + 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, 0x0010210a, 0x0402010d, 0x0201f800, - 0x001049e7, 0x04020740, 0x0201f800, 0x001048d9, + 0x0201f800, 0x00101eb0, 0x0402010d, 0x0201f800, + 0x00104836, 0x04020740, 0x0201f800, 0x00104728, 0x0400003c, 0x59cc0408, 0x48026419, 0x59cc0208, 0x48026219, 0x59cc0807, 0x59340002, 0x82000500, 0x00ffffff, 0x80040580, 0x04000012, 0x59a80010, 0x80040580, 0x04020021, 0x59cc1408, 0x0201f800, - 0x00109410, 0x04000023, 0x0201f800, 0x0010a4ca, - 0x04000020, 0x0201f800, 0x0010a921, 0x0400001d, + 0x001091d9, 0x04000023, 0x0201f800, 0x0010a2e8, + 0x04000020, 0x0201f800, 0x0010a745, 0x0400001d, 0x491e601e, 0x4a026403, 0x00000036, 0x0401f0e6, 0x59cc1208, 0x82080580, 0x0000ffff, 0x04000009, - 0x0201f800, 0x00109410, 0x04000012, 0x591c0202, + 0x0201f800, 0x001091d9, 0x04000012, 0x591c0202, 0x59cc0c08, 0x80040580, 0x0402000e, 0x0401f7eb, - 0x59cc1408, 0x41327800, 0x0201f800, 0x0010a405, + 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, 0x0010210a, 0x040200c4, - 0x0201f800, 0x001049e7, 0x040206f7, 0x0201f800, - 0x001048d9, 0x0400003e, 0x59cc0407, 0x48026419, + 0x4933c857, 0x0201f800, 0x00101eb0, 0x040200c4, + 0x0201f800, 0x00104836, 0x040206f7, 0x0201f800, + 0x00104728, 0x0400003e, 0x59cc0407, 0x48026419, 0x59cc1207, 0x480a6219, 0x82080580, 0x0000ffff, - 0x04000005, 0x0201f800, 0x00109410, 0x0400002c, + 0x04000005, 0x0201f800, 0x001091d9, 0x0400002c, 0x0401f006, 0x59cc1407, 0x41327800, 0x0201f800, - 0x0010a405, 0x04000026, 0x59cc0c07, 0x591c0202, + 0x0010a217, 0x04000026, 0x59cc0c07, 0x591c0202, 0x80040580, 0x04020022, 0x4d300000, 0x411e6000, - 0x0201f800, 0x00108bd7, 0x5c026000, 0x59cc0c09, + 0x0201f800, 0x0010898b, 0x5c026000, 0x59cc0c09, 0x82040d00, 0x0000ff00, 0x840409c0, 0x0201f800, - 0x0010a921, 0x04000016, 0x82040580, 0x00000001, + 0x0010a745, 0x04000016, 0x82040580, 0x00000001, 0x0400000a, 0x82040580, 0x00000005, 0x04000004, 0x82040580, 0x00000007, 0x04020007, 0x591c0008, 0x80000540, 0x04000004, 0x59cc2808, 0x0201f000, - 0x0010a4de, 0x4803c856, 0x4a02641a, 0x00000009, + 0x0010a2fc, 0x4803c856, 0x4a02641a, 0x00000009, 0x4a02621a, 0x00002a00, 0x0401f006, 0x4803c856, 0x4a02641a, 0x00000003, 0x4a02621a, 0x00000300, 0x4a026403, 0x0000003b, 0x0401f07b, 0x4803c856, 0x4a02641a, 0x0000000b, 0x4a02621a, 0x00000000, - 0x0401f7f8, 0x4c080000, 0x0201f800, 0x001048ec, - 0x04000026, 0x0201f800, 0x001048c1, 0x0201f800, - 0x0010a601, 0x0402001e, 0x59a80026, 0x82000540, + 0x0401f7f8, 0x4c080000, 0x0201f800, 0x0010473b, + 0x04000026, 0x0201f800, 0x00104711, 0x0201f800, + 0x0010a41c, 0x0402001e, 0x59a80026, 0x82000540, 0x00000003, 0x48035026, 0x59a8001d, 0x800000d0, 0x59a80810, 0x82040d00, 0x000000ff, 0x80041540, 0x480b5010, 0x42000800, 0x00000003, 0x0201f800, - 0x00106c78, 0x497b5028, 0x0201f800, 0x00103b25, + 0x001069af, 0x497b5028, 0x0201f800, 0x0010393e, 0x04000003, 0x4a032804, 0x000007d0, 0x8c00050a, - 0x0402000a, 0x0201f800, 0x0002077d, 0x0201f800, - 0x00101e45, 0x5c001000, 0x1c01f000, 0x0201f800, - 0x0010a623, 0x0401f7fc, 0x5c001000, 0x0201f000, - 0x0002077d, 0x0201f800, 0x0010210a, 0x0402004c, - 0x0201f800, 0x0010a628, 0x4a026403, 0x00000047, - 0x4a026203, 0x00000001, 0x0201f000, 0x0010672b, - 0x0201f800, 0x0010210a, 0x04020041, 0x0201f800, - 0x0010a628, 0x4a026403, 0x00000047, 0x4a026203, - 0x00000001, 0x0201f000, 0x0010672b, 0x0201f800, - 0x0010210a, 0x04020036, 0x0201f800, 0x0010a628, - 0x0201f000, 0x0002077d, 0x0401f834, 0x04000030, + 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, 0x0010672b, 0x4a026403, 0x0000004f, + 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, 0x0010855a, + 0x83341c00, 0x00000006, 0x0201f800, 0x001082ff, 0x0400064c, 0x4a02601c, 0x00000001, 0x0401f649, 0x4a026403, 0x00000050, 0x59cc0207, 0x4802601c, 0x0401f644, 0x4a026203, 0x00000001, 0x42000800, - 0x80000040, 0x0201f000, 0x00020721, 0x4803c857, - 0x0201f000, 0x0002077d, 0x4d2c0000, 0x4c500000, + 0x80000040, 0x0201f000, 0x00020855, 0x4803c857, + 0x0201f000, 0x000208b4, 0x4d2c0000, 0x4c500000, 0x4c580000, 0x4c540000, 0x59a80016, 0x82000c80, - 0x00000829, 0x04021029, 0x0201f800, 0x001007d3, - 0x04000026, 0x492e6008, 0x59a80016, 0x80000104, - 0x48025802, 0x83cca400, 0x00000006, 0x82000c80, - 0x0000000b, 0x04001013, 0x4a025811, 0x0000000b, - 0x4200b000, 0x0000000b, 0x832c0400, 0x00000005, - 0x4000a800, 0x0201f800, 0x0010ab17, 0x412c7000, - 0x0201f800, 0x001007d3, 0x04000010, 0x492c7001, - 0x40040000, 0x800409c0, 0x04000009, 0x0401f7ec, + 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, 0x0010ab17, 0x82000540, + 0x4000a800, 0x0201f800, 0x0010a93e, 0x82000540, 0x00000001, 0x0401f006, 0x497b5016, 0x59325808, - 0x0201f800, 0x001007fd, 0x80000580, 0x5c00a800, + 0x0201f800, 0x00100843, 0x80000580, 0x5c00a800, 0x5c00b000, 0x5c00a000, 0x5c025800, 0x1c01f000, 0x4d340000, 0x59326809, 0x59343400, 0x4933c857, - 0x4937c857, 0x481bc857, 0x0201f800, 0x001049f3, - 0x5c026800, 0x1c01f000, 0x4933c857, 0x4c5c0000, - 0x4d3c0000, 0x0401f840, 0x0402002c, 0x59cc0207, - 0x82000d00, 0x0000ff00, 0x900411c0, 0x59cc000a, - 0x82000500, 0x00ffffff, 0x80081540, 0x480a601c, - 0x8c040d18, 0x0400000e, 0x42003000, 0x00000008, - 0x0201f800, 0x0010a932, 0x42000000, 0x0010b863, - 0x0201f800, 0x0010aa47, 0x4200b800, 0x00000002, - 0x42027800, 0x00000001, 0x0401f011, 0x4178b800, - 0x8c040d1a, 0x04000011, 0x59cc000a, 0x0201f800, - 0x00105c9a, 0x0402000d, 0x42003000, 0x00000009, - 0x0201f800, 0x0010a93a, 0x42000000, 0x0010b863, - 0x0201f800, 0x0010aa47, 0x417a7800, 0x0201f800, - 0x001020a1, 0x0401f004, 0x82000540, 0x00000001, - 0x0401f002, 0x80000580, 0x5c027800, 0x5c00b800, - 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, 0x4933c857, - 0x59300403, 0x82003480, 0x00000051, 0x02021800, - 0x001005d8, 0x83383580, 0x00000013, 0x04020003, - 0x4803c857, 0x0c01f012, 0x83383580, 0x00000027, - 0x04000005, 0x83383580, 0x00000014, 0x02020800, - 0x001005d8, 0x0201f800, 0x001048c1, 0x42000800, - 0x00000007, 0x0201f800, 0x00104571, 0x0201f800, - 0x00106bbf, 0x0201f000, 0x00107911, 0x00109e3c, - 0x00109e45, 0x00109e3c, 0x00109e3c, 0x00109e3c, - 0x00109e45, 0x00109e50, 0x00109ecd, 0x00109e95, - 0x00109ecd, 0x00109ead, 0x00109ecd, 0x00109ebe, - 0x00109ecd, 0x00109ec6, 0x00109ecd, 0x00109ec6, - 0x00109ecd, 0x00109ecd, 0x00109e3c, 0x00109e3c, - 0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c, - 0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c, - 0x00109e3c, 0x00109e45, 0x00109e3c, 0x00109ecd, - 0x00109e3c, 0x00109e3c, 0x00109ecd, 0x00109e3c, - 0x00109eca, 0x00109ecd, 0x00109e3c, 0x00109e3c, - 0x00109e3c, 0x00109e3c, 0x00109ecd, 0x00109ecd, - 0x00109e3c, 0x00109ec3, 0x00109ecd, 0x00109e3c, - 0x00109e4a, 0x00109e3c, 0x00109e3c, 0x00109e3c, - 0x00109e3c, 0x00109ec9, 0x00109ecd, 0x00109e3c, - 0x00109e3c, 0x00109ecd, 0x00109ecd, 0x00109e3c, - 0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c, - 0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c, - 0x00109e3e, 0x00109e3c, 0x00109e3e, 0x00109e3c, - 0x00109e3c, 0x00109e3e, 0x00109e3c, 0x00109e3c, - 0x00109e3c, 0x00109e3e, 0x00109e3e, 0x00109e3e, - 0x0201f800, 0x001005d8, 0x4d2c0000, 0x59325808, - 0x0201f800, 0x001007fd, 0x5c025800, 0x0201f000, - 0x0002077d, 0x59a80037, 0x48026206, 0x4a026203, - 0x00000002, 0x1c01f000, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00104567, 0x5c027800, 0x0401f07e, - 0x42000800, 0x00000007, 0x0201f800, 0x00104571, - 0x59a80026, 0x8c000508, 0x04000012, 0x59326809, - 0x4c580000, 0x4200b000, 0x00000002, 0x83a81c00, - 0x00000002, 0x83341400, 0x00000006, 0x0201f800, - 0x0010855a, 0x80000540, 0x5c00b000, 0x0402006a, - 0x59340200, 0x8400051a, 0x48026a00, 0x0401f01b, - 0x599c0017, 0x8c00050a, 0x04020063, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00104567, 0x5c027800, - 0x42000800, 0x00000007, 0x0201f800, 0x00104571, - 0x59340212, 0x82000500, 0x0000ff00, 0x04000056, - 0x599c0019, 0x8c00050e, 0x04020053, 0x416c0000, - 0x82000580, 0x00000002, 0x04020004, 0x59a8001b, - 0x80000000, 0x4803501b, 0x42000800, 0x00000003, - 0x0201f800, 0x00104571, 0x4a026406, 0x00000001, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000002, - 0x0201f800, 0x0010672b, 0x4ce80000, 0x4201d000, - 0x00000001, 0x0201f800, 0x00105fae, 0x5c01d000, - 0x1c01f000, 0x0201f800, 0x001049f3, 0x04000036, - 0x0201f800, 0x0010645e, 0x42000800, 0x00000004, - 0x0201f800, 0x00104571, 0x0201f800, 0x0010a96a, - 0x0402002d, 0x42000800, 0x00000005, 0x0201f800, - 0x00104571, 0x4a026406, 0x00000001, 0x4a026203, - 0x00000001, 0x4a026403, 0x00000003, 0x0201f000, - 0x0010672b, 0x42000800, 0x00000006, 0x0401f820, - 0x59303009, 0x599c0017, 0x8c00050a, 0x0402001a, - 0x59a80026, 0x8c000508, 0x04000017, 0x0201f800, - 0x001049e7, 0x04000014, 0x59a8001b, 0x80000000, - 0x4803501b, 0x0401f7c5, 0x42000800, 0x00000004, - 0x0201f800, 0x00104571, 0x0401f792, 0x42000800, - 0x00000004, 0x0401f006, 0x0201f800, 0x001048c1, - 0x0401f005, 0x0401f004, 0x0401f003, 0x0201f800, - 0x00104571, 0x0201f000, 0x0002077d, 0x4933c857, - 0x4807c857, 0x0201f800, 0x00104571, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00104567, 0x5c027800, - 0x0201f800, 0x00102074, 0x1c01f000, 0x4933c857, - 0x59340400, 0x80000110, 0x82003480, 0x0000000c, - 0x02021800, 0x001005d8, 0x83383580, 0x00000015, - 0x04020002, 0x0c01f006, 0x83383580, 0x00000016, - 0x02020800, 0x001005d8, 0x0c01f00d, 0x001080b8, - 0x001080b8, 0x001080b8, 0x001080b8, 0x001080b8, - 0x001080b8, 0x00109f30, 0x00109f03, 0x001080b8, - 0x001080b8, 0x001080b8, 0x001080b8, 0x001080b8, - 0x001080b8, 0x001080b8, 0x001080b8, 0x001080b8, - 0x001080b8, 0x00109f30, 0x00109f37, 0x001080b8, - 0x001080b8, 0x001080b8, 0x001080b8, 0x4933c857, - 0x599c0017, 0x8c00050a, 0x0402001b, 0x813669c0, - 0x04000019, 0x59340212, 0x82000500, 0x0000ff00, - 0x04000015, 0x599c0019, 0x8c00050e, 0x04020012, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00104567, - 0x5c027800, 0x42000800, 0x00000003, 0x0201f800, - 0x00104571, 0x4a026406, 0x00000001, 0x4a026203, - 0x00000001, 0x4a026403, 0x00000002, 0x0201f000, - 0x0010672b, 0x59cc0001, 0x0201f800, 0x00105c9a, - 0x0402000b, 0x0201f800, 0x00020245, 0x02020000, - 0x0002077d, 0x59345002, 0x0201f800, 0x001042b4, - 0x482a6802, 0x0201f000, 0x0002077d, 0x1c01f000, - 0x4933c857, 0x59303403, 0x82183580, 0x0000001e, - 0x02000000, 0x0002077d, 0x1c01f000, 0x4933c857, - 0x0201f800, 0x001083df, 0x02020000, 0x0002077d, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000001, - 0x0201f000, 0x0010672b, 0x493bc857, 0x83380580, - 0x00000051, 0x0402000b, 0x0201f800, 0x00106f60, - 0x02020000, 0x00107974, 0x59300203, 0x82000580, - 0x00000002, 0x0400006d, 0x0201f800, 0x001005d8, - 0x83380580, 0x00000027, 0x04000014, 0x83380580, - 0x00000048, 0x04000006, 0x83380580, 0x00000014, - 0x0400000e, 0x02020800, 0x001005d8, 0x0201f800, - 0x00106f60, 0x02020000, 0x00107974, 0x59300203, - 0x82000580, 0x00000004, 0x02000000, 0x0002086e, - 0x0201f800, 0x001005d8, 0x59300403, 0x82000c80, - 0x00000044, 0x02021800, 0x001005d8, 0x82000480, - 0x00000040, 0x02001800, 0x001005d8, 0x40027000, - 0x4803c857, 0x0c01f001, 0x00109f76, 0x00109f78, - 0x00109f78, 0x00109f93, 0x0201f800, 0x001005d8, - 0x0201f800, 0x00106bbf, 0x59325808, 0x812e59c0, - 0x04000016, 0x832c0500, 0x00ff0000, 0x04000013, - 0x4a026203, 0x00000002, 0x59326809, 0x59340200, - 0x8c00050e, 0x0402000d, 0x42028000, 0x00000004, - 0x0201f800, 0x0010a3ef, 0x497a6008, 0x59300206, - 0x80000540, 0x04020003, 0x59a80038, 0x48026206, - 0x4a026203, 0x00000007, 0x1c01f000, 0x0201f800, - 0x00106bbf, 0x0201f800, 0x00109037, 0x02000000, - 0x00107911, 0x59325808, 0x0201f800, 0x001007f4, - 0x0201f000, 0x00107911, 0x0201f800, 0x001005d8, - 0x59325808, 0x592c040a, 0x8c000502, 0x04000007, - 0x4a026203, 0x00000007, 0x42027000, 0x00000043, - 0x0201f000, 0x000207a1, 0x4a026203, 0x00000004, - 0x1c01f000, 0x0201f800, 0x0010a597, 0x02000000, - 0x0002086c, 0x1c01f000, 0x4a026203, 0x00000001, - 0x4a026403, 0x00000041, 0x42027800, 0x80002042, - 0x0201f000, 0x00020721, 0x83380580, 0x00000051, - 0x04000006, 0x83380580, 0x00000041, 0x02020800, - 0x001005d8, 0x1c01f000, 0x0201f800, 0x000206fd, - 0x0201f800, 0x0010a5df, 0x0201f000, 0x0002077d, - 0x83380480, 0x00000050, 0x02021800, 0x001005d8, - 0x83380480, 0x00000049, 0x02001800, 0x001005d8, - 0x0c01f001, 0x00109fda, 0x00109ffb, 0x00109fd8, - 0x00109fd8, 0x00109fd8, 0x00109fd8, 0x00109ffb, - 0x0201f800, 0x001005d8, 0x59325808, 0x592c040a, + 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, 0x0002088d, 0x4a026203, 0x00000007, - 0x497a6206, 0x0201f000, 0x000206fd, 0x59325808, + 0x0201f000, 0x000209c4, 0x4a026203, 0x00000007, + 0x497a6206, 0x0201f000, 0x00020831, 0x59325808, 0x592c0c0a, 0x8c040d1a, 0x04020005, 0x0201f800, - 0x000206fd, 0x0201f000, 0x0002077d, 0x0201f800, - 0x0010a597, 0x040007fa, 0x1c01f000, 0x0201f800, - 0x00106b8a, 0x59325808, 0x59326809, 0x59340200, + 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, 0x0401f00d, 0x42028000, - 0x00000004, 0x0401fbde, 0x59300206, 0x80000540, - 0x04020004, 0x59a80038, 0x800000c2, 0x48026206, - 0x497a6008, 0x4a026203, 0x00000007, 0x1c01f000, + 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, - 0x000206fd, 0x4a026203, 0x00000007, 0x497a6206, - 0x0201f000, 0x000206f8, 0x59300414, 0x8c00051c, - 0x02020000, 0x0002087e, 0x59325808, 0x592c200f, + 0x00020831, 0x4a026203, 0x00000007, 0x497a6206, + 0x0201f000, 0x0002082c, 0x59300414, 0x8c00051c, + 0x02020000, 0x000209b5, 0x59325808, 0x592c200f, 0x40080000, 0x80102480, 0x59300015, 0x80102400, - 0x48126015, 0x0201f000, 0x0002087e, 0x8c040d0e, + 0x48126015, 0x0201f000, 0x000209b5, 0x8c040d0e, 0x0402000a, 0x4a026203, 0x00000006, 0x0401f823, - 0x5930001f, 0x80000540, 0x02020800, 0x00100d7c, - 0x0201f000, 0x000206f8, 0x4a026203, 0x00000002, + 0x5930001f, 0x80000540, 0x02020800, 0x00100dc4, + 0x0201f000, 0x0002082c, 0x4a026203, 0x00000002, 0x1c01f000, 0x42000800, 0x00000001, 0x0201f800, - 0x00100d7c, 0x82040580, 0x00000001, 0x02000000, - 0x00020885, 0x0401f7d8, 0x59300414, 0x8c00051c, - 0x04000006, 0x0201f800, 0x00100b63, 0x02000000, - 0x00020877, 0x1c01f000, 0x59300011, 0x80000540, - 0x04020005, 0x0201f800, 0x00100b63, 0x02000000, - 0x00020877, 0x1c01f000, 0x492fc857, 0x480bc857, + 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, 0x001005d8, 0x59300414, 0x8c000516, - 0x02000800, 0x001005d8, 0x1c01f000, 0x0201f800, - 0x001005d8, 0x59300008, 0x80000540, 0x02020800, - 0x001005d8, 0x1c01f000, 0x59300414, 0x8c000516, - 0x02000800, 0x001005d8, 0x1c01f000, 0x4a026203, + 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, 0x00020721, 0x4a026203, 0x00000003, - 0x493a6403, 0x0201f800, 0x000200c9, 0x59325808, + 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, 0x00106721, - 0x82080d40, 0x80002065, 0x0201f000, 0x00106721, - 0x82080d40, 0x80002042, 0x0201f000, 0x00106721, + 0x82080d40, 0x80003065, 0x0201f000, 0x00106466, + 0x82080d40, 0x80002065, 0x0201f000, 0x00106466, + 0x82080d40, 0x80002042, 0x0201f000, 0x00106466, 0x4933c857, 0x493bc857, 0x83380480, 0x00000044, - 0x02021800, 0x001005d8, 0x83380480, 0x00000041, - 0x02001800, 0x001005d8, 0x0c01f001, 0x0010a0b6, - 0x0010a0c6, 0x0010a0db, 0x59325808, 0x592c040a, + 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, 0x00020721, 0x59325808, 0x592c040a, + 0x0201f000, 0x00020855, 0x59325808, 0x592c040a, 0x8c00051e, 0x0400000d, 0x82001d00, 0x000000c0, 0x820c1d80, 0x000000c0, 0x04000008, 0x4a026203, 0x00000001, 0x493a6403, 0x42000800, 0x80002001, - 0x0201f000, 0x00020721, 0x497a6008, 0x497a6206, - 0x42028000, 0x00000004, 0x0401f315, 0x59325808, + 0x0201f000, 0x00020855, 0x497a6008, 0x497a6206, + 0x42028000, 0x00000004, 0x0401f337, 0x59325808, 0x592c040a, 0x8c00051e, 0x040007f8, 0x82001d00, 0x000000c0, 0x820c1d80, 0x000000c0, 0x040007f3, 0x4a026203, 0x00000003, 0x493a6403, 0x0201f800, - 0x000200c9, 0x82080d40, 0x80002065, 0x0201f000, - 0x00106721, 0x4933c857, 0x493bc857, 0x83380580, + 0x000200ca, 0x82080d40, 0x80002065, 0x0201f000, + 0x00106466, 0x4933c857, 0x493bc857, 0x83380580, 0x00000085, 0x04000006, 0x83380580, 0x00000088, - 0x0400000a, 0x0201f800, 0x001005d8, 0x4a026203, + 0x0400000a, 0x0201f800, 0x00100615, 0x4a026203, 0x00000009, 0x493a6403, 0x42000800, 0x8000004b, - 0x0201f000, 0x00020721, 0x4d1c0000, 0x813669c0, - 0x04000004, 0x0201f800, 0x0010a592, 0x04020044, + 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, 0x00107a4a, + 0x42002000, 0x00000054, 0x0201f800, 0x001077d1, 0x4a026203, 0x00000007, 0x493a6403, 0x0201f800, - 0x0010a974, 0x0401f02c, 0x0201f800, 0x00103b25, + 0x0010a79b, 0x0401f02c, 0x0201f800, 0x0010393e, 0x04000004, 0x42023800, 0xffffffff, 0x0401f7f1, 0x813669c0, 0x04020009, 0x59cc0001, 0x0201f800, - 0x00105c9a, 0x0402001e, 0x0201f800, 0x001045a6, + 0x001059b9, 0x0402001e, 0x0201f800, 0x001043fc, 0x0402001b, 0x49366009, 0x4a026403, 0x00000087, 0x59cc1204, 0x82081580, 0x0000ffff, 0x04020003, 0x4a026403, 0x00000086, 0x4a026203, 0x00000001, - 0x42000800, 0x80000040, 0x0201f800, 0x00020721, + 0x42000800, 0x80000040, 0x0201f800, 0x00020855, 0x0401f00d, 0x591c0203, 0x82000580, 0x00000007, 0x040207de, 0x4d300000, 0x411e6000, 0x0201f800, - 0x00107911, 0x5c026000, 0x0401f7d8, 0x0201f800, - 0x00107911, 0x5c023800, 0x1c01f000, 0x4933c857, - 0x480bc857, 0x42002800, 0x0010d1c0, 0x41300000, + 0x00107698, 0x5c026000, 0x0401f7d8, 0x0201f800, + 0x00107698, 0x5c023800, 0x1c01f000, 0x4933c857, + 0x480bc857, 0x42002800, 0x0010cfc0, 0x41300000, 0x80140580, 0x04000017, 0x58140203, 0x82000580, 0x00000000, 0x04000013, 0x58140202, 0x80080580, 0x04020010, 0x58141c06, 0x820c0580, 0x00000005, @@ -10375,646 +10243,660 @@ uint32_t risc_code01[] = { 0x0401f7f2, 0x5810201e, 0x0401f7f0, 0x40163800, 0x81300540, 0x0401f002, 0x80000580, 0x1c01f000, 0x58141807, 0x8c0c1d10, 0x040207ea, 0x0401f7e1, - 0x4933c857, 0x493bc857, 0x83380580, 0x00000013, - 0x0402000e, 0x59300403, 0x82000c80, 0x00000085, - 0x02001800, 0x001005d8, 0x82000c80, 0x00000093, - 0x02021800, 0x001005d8, 0x82000480, 0x00000085, - 0x4803c857, 0x0c01f018, 0x83380580, 0x00000027, - 0x04000005, 0x83380580, 0x00000014, 0x02020000, - 0x00107974, 0x0201f800, 0x00106bbf, 0x59325808, - 0x812e59c0, 0x02000000, 0x00107911, 0x4a025a06, - 0x00000031, 0x4a025811, 0x00000004, 0x4a025812, - 0x000000ff, 0x0201f800, 0x000202da, 0x0201f000, - 0x00107911, 0x0010a1b7, 0x0010a1be, 0x0010a1be, - 0x0010a1b7, 0x0010a1b7, 0x0010a1b7, 0x0010a1b7, - 0x0010a1b7, 0x0010a1b7, 0x0010a1b7, 0x0010a1b7, - 0x0010a1b7, 0x0010a1b7, 0x0010a1b9, 0x0201f800, - 0x001005d8, 0x59325808, 0x4a025a06, 0x00000000, - 0x0201f800, 0x000202da, 0x0201f000, 0x00107911, - 0x4933c857, 0x42000000, 0x0010b873, 0x0201f800, - 0x0010aa47, 0x0201f800, 0x0010a5df, 0x497a6205, - 0x42028000, 0x0000000b, 0x0401f807, 0x4a026406, - 0x00000006, 0x4a026203, 0x00000007, 0x497a6206, - 0x1c01f000, 0x4933c857, 0x4943c857, 0x59300406, - 0x82000580, 0x00000007, 0x04020002, 0x1c01f000, - 0x0201f800, 0x00106c55, 0x4df00000, 0x0201f800, - 0x00108ce5, 0x82000c80, 0x0000000e, 0x02021800, - 0x001005d8, 0x0c01f001, 0x0010a205, 0x0010a209, - 0x0010a1f0, 0x0010a217, 0x0010a22a, 0x0010a1f0, - 0x0010a1f0, 0x0010a1f0, 0x0010a1f0, 0x0010a1f0, - 0x0010a1f0, 0x0010a1f0, 0x0010a1f0, 0x0010a1f0, - 0x4d400000, 0x5930001f, 0x80000540, 0x04000005, - 0x41400800, 0x0201f800, 0x00100d7c, 0x40068000, - 0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037, - 0x040209f3, 0x4c5c0000, 0x5930b809, 0x0201f800, - 0x00107911, 0x485e6009, 0x5c00b800, 0x5c025800, - 0x5c028000, 0x5c03e000, 0x02000000, 0x00106c4b, - 0x1c01f000, 0x598c000d, 0x81300580, 0x04020004, - 0x0201f800, 0x00106e8e, 0x04020016, 0x0201f800, - 0x001068d3, 0x040007df, 0x0201f800, 0x00106b6c, - 0x04000010, 0x0201f800, 0x001005d8, 0x0201f800, - 0x00108cd6, 0x04020004, 0x0201f800, 0x00106e62, - 0x04020008, 0x0201f800, 0x001067ae, 0x040007d1, - 0x0201f800, 0x00106b6c, 0x02020800, 0x001005d8, - 0x59300203, 0x82000c80, 0x0000000e, 0x02021800, - 0x001005d8, 0x0c01f7b9, 0x0201f800, 0x00100e99, - 0x0401f7c4, 0x4933c857, 0x4d440000, 0x4d340000, - 0x59cc0007, 0x0201f800, 0x00105c9a, 0x02000800, - 0x00020245, 0x0402001a, 0x59300009, 0x4c000000, - 0x49366009, 0x42003000, 0x0000000b, 0x0201f800, - 0x0010a942, 0x42000000, 0x0010b861, 0x0201f800, - 0x0010aa47, 0x4d3c0000, 0x4d400000, 0x42028000, - 0x00000029, 0x417a7800, 0x0201f800, 0x0010203c, - 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, - 0x4c040000, 0x4c080000, 0x4c0c0000, 0x4c580000, - 0x59cc000c, 0x0201f800, 0x00105c9a, 0x02000800, - 0x00020245, 0x04020012, 0x83cc1400, 0x00000008, + 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, 0x0010855a, 0x04020009, 0x83cc1400, + 0x0201f800, 0x001082ff, 0x04020009, 0x83cc1400, 0x0000000a, 0x4200b000, 0x00000002, 0x83341c00, - 0x00000008, 0x0201f800, 0x0010855a, 0x5c00b000, - 0x5c001800, 0x5c001000, 0x5c000800, 0x1c01f000, - 0x4933c857, 0x4c000000, 0x4c040000, 0x4c080000, - 0x4c0c0000, 0x4c580000, 0x59cc0001, 0x0201f800, - 0x00105c9a, 0x02000800, 0x00020245, 0x04020014, - 0x83cc1400, 0x0000000b, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000006, 0x0201f800, 0x0010855a, - 0x0402000c, 0x83cc1400, 0x0000000d, 0x4200b000, - 0x00000002, 0x83341c00, 0x00000008, 0x0201f800, - 0x0010855a, 0x04000014, 0x4933c856, 0x4933c856, - 0x4933c857, 0x59340009, 0x4803c857, 0x5934000e, - 0x4803c857, 0x59340008, 0x4803c857, 0x5934000d, - 0x4803c857, 0x59340007, 0x4803c857, 0x5934000c, - 0x4803c857, 0x59340006, 0x4803c857, 0x5934000b, - 0x4803c857, 0x5c00b000, 0x5c001800, 0x5c001000, - 0x5c000800, 0x5c000000, 0x1c01f000, 0x4933c857, - 0x4947c857, 0x4943c857, 0x4c600000, 0x0201f800, - 0x00106c55, 0x4df00000, 0x4d2c0000, 0x4d300000, - 0x4d340000, 0x4130c000, 0x42026000, 0x0010d1c0, + 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, - 0x0010bde9, 0x04000002, 0x80000040, 0x81640480, - 0x040210be, 0x40600000, 0x81300580, 0x040000b6, - 0x0401f97a, 0x040200b4, 0x59326809, 0x59300406, - 0x82000c80, 0x00000012, 0x02021800, 0x001005d8, - 0x0c01f001, 0x0010a3cd, 0x0010a338, 0x0010a351, - 0x0010a35c, 0x0010a335, 0x0010a34c, 0x0010a387, - 0x0010a3cd, 0x0010a333, 0x0010a39a, 0x0010a3ae, - 0x0010a333, 0x0010a333, 0x0010a333, 0x0010a333, - 0x0010a3cd, 0x0010a3c4, 0x0010a3bc, 0x0201f800, - 0x001005d8, 0x59300420, 0x8c000500, 0x04020096, - 0x59300403, 0x82000580, 0x00000043, 0x04000092, - 0x0201f800, 0x00109134, 0x04000007, 0x0201f800, - 0x0010914e, 0x0402008a, 0x0201f800, 0x0010801c, - 0x0401f087, 0x0201f800, 0x00102074, 0x0201f800, - 0x0010914e, 0x02000800, 0x0010801c, 0x0401f080, - 0x8d3e7d18, 0x04000004, 0x59300420, 0x8c000500, - 0x0402007d, 0x59325808, 0x0201f800, 0x00109037, - 0x04000077, 0x49425a06, 0x497a5c09, 0x0201f800, - 0x000202da, 0x0201f800, 0x0010912a, 0x0401f070, - 0x8d3e7d00, 0x04000007, 0x59300017, 0x81480580, - 0x0402006d, 0x59300018, 0x814c0580, 0x0402006a, + 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, - 0x00100e99, 0x59325808, 0x0201f800, 0x00109037, - 0x0400005f, 0x4a025a04, 0x00000103, 0x59300004, - 0x8400055c, 0x48026004, 0x592c0408, 0x8c000512, - 0x04000007, 0x4d2c0000, 0x592c0009, 0x40025800, - 0x0201f800, 0x001007fd, 0x5c025800, 0x49425a06, - 0x497a5c09, 0x0401fb16, 0x0201f800, 0x0010959c, - 0x0201f800, 0x001091c6, 0x0201f800, 0x000202da, - 0x0201f800, 0x0010912a, 0x0401f045, 0x8d3e7d18, - 0x04000045, 0x59300203, 0x82000580, 0x00000004, - 0x02000800, 0x00100e99, 0x59325808, 0x0201f800, - 0x00109037, 0x0400003a, 0x49425a06, 0x497a5c09, - 0x0401faff, 0x0201f800, 0x0010959c, 0x0201f800, - 0x000202da, 0x0401f032, 0x0201f800, 0x001062d5, - 0x04000031, 0x59300203, 0x82000580, 0x00000004, - 0x0400002d, 0x59300203, 0x82000580, 0x00000003, - 0x04020029, 0x0201f800, 0x00106b8a, 0x59325808, - 0x0201f800, 0x00109037, 0x04000021, 0x0201f800, - 0x000202da, 0x0401f01e, 0x59300203, 0x82000580, - 0x00000004, 0x02000800, 0x00100e99, 0x59325808, - 0x0201f800, 0x00109037, 0x04000015, 0x49425a06, - 0x497a5c09, 0x0201f800, 0x000202da, 0x0401f010, - 0x833c0500, 0x00001800, 0x0400000f, 0x8d3e7d16, - 0x0402000d, 0x59325817, 0x0201f800, 0x001007fd, - 0x59325808, 0x0201f800, 0x00109037, 0x04000004, - 0x49425a06, 0x0201f800, 0x000202da, 0x0201f800, - 0x00107911, 0x83326400, 0x00000024, 0x41580000, - 0x81300480, 0x0400173b, 0x5c026800, 0x5c026000, - 0x5c025800, 0x5c03e000, 0x02000800, 0x00106c4b, - 0x5c00c000, 0x1c01f000, 0x5c000000, 0x4c000000, - 0x4803c857, 0x4d3c0000, 0x42027800, 0x00000001, - 0x0201f800, 0x00104567, 0x5c027800, 0x4c580000, - 0x4200b000, 0x00000002, 0x83a81c00, 0x00000002, - 0x83cc1400, 0x0000000b, 0x0201f800, 0x0010855a, - 0x5c00b000, 0x80000540, 0x1c01f000, 0x492fc857, - 0x4943c857, 0x59a8000c, 0x812c0480, 0x04001011, - 0x59a8000d, 0x812c0480, 0x0402100e, 0x592c0000, - 0x80005d40, 0x04000008, 0x497a5800, 0x49425a06, - 0x4c2c0000, 0x0201f800, 0x000202da, 0x5c025800, - 0x0401f7f7, 0x49425a06, 0x0201f000, 0x000202da, - 0x1c01f000, 0x493fc857, 0x4933c857, 0x480bc857, - 0x0201f800, 0x00103b25, 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, - 0x0201f800, 0x001007e4, 0x02000800, 0x001005d8, - 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, 0x0400000e, 0x4d440000, - 0x4d340000, 0x40128800, 0x0201f800, 0x00020245, - 0x02020800, 0x001005d8, 0x59340002, 0x82000500, + 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, - 0x497a5800, 0x497a5c04, 0x83400580, 0x00000046, - 0x04020002, 0x48165a07, 0x481a5c08, 0x0401fbed, - 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, 0x00020721, 0x5c000800, 0x1c01f000, - 0x4933c857, 0x40000000, 0x40000000, 0x1c01f000, - 0x59300414, 0x4933c857, 0x4803c857, 0x8c000518, - 0x04000009, 0x8c000512, 0x02020000, 0x0010921e, - 0x0401f91b, 0x0201f800, 0x000206fd, 0x0201f800, - 0x0002077d, 0x1c01f000, 0x591c0406, 0x4803c857, - 0x82000c80, 0x00000009, 0x0402100b, 0x0c01f001, - 0x0010a4d9, 0x0010a4d9, 0x0010a4d9, 0x0010a4db, - 0x0010a4d9, 0x0010a4db, 0x0010a4db, 0x0010a4d9, - 0x0010a4db, 0x80000580, 0x1c01f000, 0x82000540, - 0x00000001, 0x1c01f000, 0x591c0406, 0x82000500, - 0x0000001f, 0x82000580, 0x00000006, 0x0400000e, - 0x4803c857, 0x4a026403, 0x0000003b, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00002a00, 0x4a026203, - 0x00000001, 0x42000800, 0x80000040, 0x0201f000, - 0x00020721, 0x4803c856, 0x4c040000, 0x4c140000, - 0x4d300000, 0x411e6000, 0x0401f8e9, 0x497a6205, - 0x59300414, 0x4803c857, 0x82000500, 0xffffadff, - 0x48026414, 0x497a6405, 0x5c026000, 0x0201f800, - 0x001007e4, 0x02000800, 0x001005d8, 0x5c002800, - 0x5c000800, 0x4a025a04, 0x0000010d, 0x497a5800, - 0x497a5c04, 0x4a025a08, 0x00000045, 0x491e5809, - 0x59300402, 0x48025c07, 0x59300419, 0x48025c0b, - 0x591c0414, 0x84000556, 0x48023c14, 0x591c1809, - 0x580c0403, 0x48025a06, 0x4816580a, 0x48065a0b, - 0x0401f99d, 0x4d400000, 0x42028000, 0x00000045, - 0x591c0202, 0x4c000000, 0x4d300000, 0x411e6000, - 0x0401fcb1, 0x5c026000, 0x5c000000, 0x48023a02, - 0x5c028000, 0x4a023c06, 0x00000006, 0x4a023a03, - 0x00000007, 0x497a3a06, 0x497a3a05, 0x1c01f000, - 0x4933c857, 0x83380580, 0x00000013, 0x0402000b, - 0x59300403, 0x4803c857, 0x82000d80, 0x00000085, - 0x0400002b, 0x82000d80, 0x0000008b, 0x04000028, - 0x0201f800, 0x001005d8, 0x83380580, 0x00000027, - 0x0402000c, 0x0201f800, 0x00106bbf, 0x4d2c0000, - 0x4d400000, 0x59325808, 0x42028000, 0x00000004, - 0x0401feab, 0x5c028000, 0x5c025800, 0x1c01f000, - 0x83380580, 0x00000014, 0x040007f3, 0x83380580, - 0x00000089, 0x04000005, 0x83380580, 0x0000008a, - 0x02020000, 0x00107974, 0x0201f800, 0x00106f60, - 0x02020000, 0x00107974, 0x59300a03, 0x82040580, - 0x0000000a, 0x04000009, 0x82040580, 0x0000000c, - 0x04000006, 0x0201f800, 0x001005d8, 0x4a026203, - 0x0000000a, 0x1c01f000, 0x83380480, 0x00000093, - 0x0402100c, 0x83380480, 0x00000085, 0x04001009, - 0x83380580, 0x00000089, 0x0400000a, 0x83380580, - 0x0000008a, 0x04000022, 0x0201f800, 0x001005d8, - 0x493bc857, 0x4933c857, 0x0201f000, 0x00107974, - 0x4933c857, 0x4c340000, 0x41306800, 0x0201f800, - 0x0002075a, 0x04000011, 0x4a026203, 0x00000001, - 0x4a026403, 0x0000001e, 0x59cc0c07, 0x48066419, - 0x59cc0a07, 0x48066219, 0x58340809, 0x48066009, - 0x4a026406, 0x00000004, 0x42000800, 0x80000040, - 0x0201f800, 0x00020721, 0x40366000, 0x0201f800, - 0x0002077d, 0x5c006800, 0x1c01f000, 0x4933c857, - 0x0201f000, 0x0002077d, 0x4933c857, 0x59300809, - 0x58040200, 0x8c00051a, 0x1c01f000, 0x0201f800, - 0x001048df, 0x0400001e, 0x4a026203, 0x00000002, - 0x59300414, 0x84000558, 0x48026414, 0x8c000512, - 0x04000004, 0x59a80039, 0x48026205, 0x0401f007, - 0x59a80839, 0x59a80037, 0x80040400, 0x82000400, - 0x0000000a, 0x48026205, 0x59300009, 0x82000c00, - 0x00000011, 0x50040000, 0x80000540, 0x04000004, - 0x82000c00, 0x00000000, 0x0401f7fb, 0x45300800, - 0x497a6000, 0x82000540, 0x00000001, 0x1c01f000, - 0x82100500, 0xfffffeef, 0x04020020, 0x4d2c0000, - 0x4937c857, 0x59340811, 0x83341400, 0x00000011, - 0x800409c0, 0x0400000e, 0x40040000, 0x81300580, - 0x04000005, 0x58040800, 0x82041400, 0x00000000, - 0x0401f7f8, 0x59300800, 0x497a6000, 0x44041000, - 0x0201f800, 0x000206fd, 0x0401f002, 0x4933c857, - 0x592c0000, 0x80000540, 0x02020800, 0x001005d8, - 0x5c025800, 0x492e6008, 0x0201f800, 0x000206fd, - 0x0201f000, 0x0002077d, 0x492fc857, 0x4a025a06, - 0x00000006, 0x0201f000, 0x000202da, 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, - 0x001005d8, 0x4933c857, 0x4c080000, 0x4c0c0000, - 0x4c580000, 0x59a8101d, 0x59cc1807, 0x820c1d00, - 0x00ffffff, 0x800c0110, 0x80083580, 0x04020014, - 0x83cc1400, 0x00000008, 0x4200b000, 0x00000002, - 0x59300009, 0x82001c00, 0x00000006, 0x0201f800, - 0x0010855a, 0x0402000a, 0x83cc1400, 0x0000000a, - 0x4200b000, 0x00000002, 0x59300009, 0x82001c00, - 0x00000008, 0x0201f800, 0x0010855a, 0x5c00b000, - 0x5c001800, 0x5c001000, 0x1c01f000, 0x4933c856, - 0x0201f800, 0x0010421b, 0x0201f000, 0x00101e45, - 0x493bc857, 0x4d2c0000, 0x0201f800, 0x001007e4, - 0x02000800, 0x001005d8, 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, - 0x000202da, 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, 0x492fc857, 0x42007000, 0x0010b7f8, - 0x58380807, 0x800409c0, 0x04020005, 0x492c7008, - 0x492c7007, 0x0201f000, 0x00100875, 0x492c0800, - 0x492c7007, 0x1c01f000, 0x59300203, 0x4933c857, - 0x4937c857, 0x493bc857, 0x4803c857, 0x82003480, - 0x0000000e, 0x02021800, 0x001005d8, 0x0c01f001, - 0x0010a6da, 0x0010a82c, 0x0010a6da, 0x0010a6da, - 0x0010a6da, 0x0010a6da, 0x0010a6da, 0x0010a791, - 0x0010a6dc, 0x0010a6da, 0x0010a6da, 0x0010a6da, - 0x0010a6da, 0x0010a6da, 0x0201f800, 0x001005d8, - 0x83380580, 0x0000004c, 0x02020800, 0x001005d8, - 0x0201f800, 0x001048ec, 0x04020020, 0x59a80826, - 0x82040500, 0x00000009, 0x82000580, 0x00000008, - 0x0400001a, 0x8c040d12, 0x0400003d, 0x59cc0806, - 0x82040d00, 0xff000000, 0x82040580, 0x03000000, - 0x0400001f, 0x82040580, 0x50000000, 0x04000005, - 0x82040580, 0x52000000, 0x02020000, 0x0002077d, - 0x813669c0, 0x04000006, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x0010203c, 0x5c027800, 0x4a026403, - 0x00000001, 0x0401f014, 0x59cc0806, 0x82040d00, - 0xff000000, 0x82040580, 0x03000000, 0x04000008, - 0x82040580, 0x50000000, 0x04000005, 0x82040580, - 0x52000000, 0x02020000, 0x0002077d, 0x4a026403, + 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, - 0x00000000, 0x813669c0, 0x0402000b, 0x59cc0001, - 0x0201f800, 0x00105c9a, 0x02020000, 0x0002077d, - 0x0201f800, 0x001045a6, 0x02020000, 0x0002077d, - 0x49366009, 0x4a026406, 0x00000004, 0x4a026203, - 0x00000001, 0x0201f000, 0x0010672b, 0x0201f800, - 0x00103b25, 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, 0x0401fcf3, - 0x0401f93c, 0x02000800, 0x001005d8, 0x42002000, - 0x00000051, 0x0201f800, 0x00107a4a, 0x59cc0000, - 0x82000500, 0x00ffffff, 0x82000580, 0x00ffffff, - 0x04000005, 0x4a026203, 0x00000007, 0x493a6403, - 0x1c01f000, 0x59325817, 0x812e59c0, 0x02020800, - 0x001007fd, 0x0201f000, 0x0002077d, 0x813669c0, - 0x040007df, 0x59340400, 0x82000500, 0x000000ff, - 0x82000580, 0x00000003, 0x040207d9, 0x0401fc6f, - 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, 0x001005d8, 0x59325808, 0x592c0c0b, - 0x82040d00, 0x0000e000, 0x82040580, 0x00002000, - 0x04020076, 0x59300817, 0x800409c0, 0x04000014, - 0x58041404, 0x41cca800, 0x8204a400, 0x00000005, - 0x82080480, 0x00000010, 0x04021004, 0x4008b000, - 0x0401fb6b, 0x0401f00a, 0x40001000, 0x4200b000, - 0x0000000f, 0x0401fb66, 0x58040801, 0x800409c0, - 0x040207f2, 0x0201f800, 0x001005d8, 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, - 0x00104571, 0x42005000, 0x0000000c, 0x0401f037, - 0x4a025a06, 0x00000031, 0x4a02580d, 0x00000009, - 0x59340400, 0x4802580e, 0x0201f800, 0x000202da, - 0x0201f800, 0x00107911, 0x0401f03d, 0x0201f800, - 0x001042b4, 0x0201f800, 0x0010462a, 0x42000800, - 0x00000003, 0x0201f800, 0x00104571, 0x42005000, - 0x00000008, 0x0401f021, 0x59cc0007, 0x0201f800, - 0x00105eec, 0x0402001d, 0x0201f800, 0x001042b4, - 0x0401f01a, 0x82240500, 0x0000ff00, 0x82000580, - 0x00000007, 0x040007df, 0x82240500, 0x000000ff, - 0x82000580, 0x00000009, 0x040007da, 0x0201f800, - 0x0010468d, 0x42005000, 0x0000000a, 0x0401f00b, - 0x42005000, 0x0000000e, 0x0401f003, 0x42005000, - 0x00000010, 0x82240500, 0x0000ff00, 0x82000580, - 0x00000007, 0x040007cb, 0x482a6403, 0x4a026203, - 0x00000001, 0x592c000d, 0x48026011, 0x497a6013, - 0x59a80038, 0x48026206, 0x417a7800, 0x0201f800, - 0x0010672b, 0x59325817, 0x812e59c0, 0x04000004, - 0x0201f800, 0x001007fd, 0x497a6017, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x5c025800, 0x1c01f000, - 0x4d2c0000, 0x59325808, 0x83380580, 0x00000013, - 0x04020029, 0x59300c03, 0x82040580, 0x00000054, - 0x0400001e, 0x82040580, 0x00000010, 0x04000018, - 0x82040580, 0x0000000e, 0x04000015, 0x82040580, - 0x00000008, 0x0400000d, 0x82040580, 0x0000000c, - 0x0400000a, 0x82040580, 0x0000000a, 0x02020800, - 0x001005d8, 0x42000800, 0x00000006, 0x0201f800, - 0x00104571, 0x0401f009, 0x42000800, 0x00000004, - 0x0201f800, 0x00104571, 0x0401f004, 0x59340200, - 0x8400051a, 0x48026a00, 0x4a025a06, 0x00000000, - 0x0201f800, 0x000202da, 0x0201f800, 0x0002077d, - 0x0401f022, 0x83380580, 0x00000027, 0x0400000e, - 0x83380580, 0x00000014, 0x02020800, 0x001005d8, - 0x0201f800, 0x00106bbf, 0x42028000, 0x00000031, + 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, - 0x0401f009, 0x0201f800, 0x00106bbf, 0x42028000, - 0x00000031, 0x42000800, 0x00000004, 0x42001000, - 0x00000010, 0x49425a06, 0x4806580d, 0x480a580e, - 0x0201f800, 0x000202da, 0x0201f800, 0x00104c19, - 0x0201f800, 0x00107911, 0x5c025800, 0x1c01f000, - 0x42007000, 0x0010b7f8, 0x58380807, 0x800409c0, - 0x04020005, 0x492c7008, 0x492c7007, 0x0201f000, - 0x00100875, 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, 0x001007e4, 0x0400002c, - 0x492fc857, 0x492e6017, 0x59a8b016, 0x8258b400, - 0x0000001b, 0x8258b500, 0xfffffffc, 0x8058b104, - 0x485a5c04, 0x412c7800, 0x41cca000, 0x82580480, - 0x00000010, 0x04021005, 0x832cac00, 0x00000005, - 0x0401fa63, 0x0401f015, 0x40580800, 0x4200b000, - 0x0000000f, 0x832cac00, 0x00000005, 0x0401fa5c, - 0x8204b480, 0x0000000f, 0x0201f800, 0x001007e4, - 0x04000004, 0x492c7801, 0x412c7800, 0x0401f7ec, - 0x59325817, 0x0201f800, 0x001007fd, 0x497a6017, - 0x80000580, 0x0401f006, 0x59340200, 0x84000554, - 0x48026a00, 0x82000540, 0x00000001, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x492fc857, 0x4d2c0000, 0x59300a03, - 0x82040580, 0x00000007, 0x04000036, 0x82040580, - 0x00000001, 0x02020800, 0x001005d8, 0x0201f800, - 0x00106c55, 0x4df00000, 0x598c000d, 0x81300580, - 0x04020016, 0x59300004, 0x8c000520, 0x04000004, - 0x84000520, 0x48026004, 0x0401f016, 0x42001000, - 0x0010b7f6, 0x50081000, 0x58080002, 0x82000580, - 0x00000100, 0x04000006, 0x5808000c, 0x81300580, - 0x02020800, 0x001005d8, 0x0401f00a, 0x0201f800, - 0x00106e8e, 0x04020020, 0x59300004, 0x8c000520, - 0x04000004, 0x84000520, 0x48026004, 0x0401f003, - 0x0201f800, 0x001068d3, 0x5c03e000, 0x02000800, - 0x00106c4b, 0x0201f800, 0x00109037, 0x02000800, - 0x001005d8, 0x59325808, 0x4a025a06, 0x00000005, - 0x0201f800, 0x000202da, 0x0201f800, 0x00104c19, - 0x59325817, 0x812e59c0, 0x02020800, 0x001007fd, - 0x0201f800, 0x00107911, 0x80000580, 0x5c025800, - 0x1c01f000, 0x5c03e000, 0x02000800, 0x00106c4b, - 0x59300406, 0x82000580, 0x00000011, 0x040007b8, - 0x0401f7f7, 0x4c040000, 0x59340200, 0x4803c857, + 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, 0x0401f010, 0x4c000000, 0x4c0c0000, - 0x4c100000, 0x59302009, 0x58101c03, 0x42002000, - 0x00000004, 0x0401f008, 0x4c000000, 0x4c0c0000, + 0x00000004, 0x0401f013, 0x4c000000, 0x4c0c0000, 0x4c100000, 0x59302009, 0x58101c03, 0x42002000, - 0x00000007, 0x480fc857, 0x4813c857, 0x481bc857, - 0x0201f800, 0x00103aae, 0x5c002000, 0x5c001800, - 0x5c000000, 0x1c01f000, 0x83380580, 0x00000092, - 0x02020800, 0x001005d8, 0x42000800, 0x80000040, - 0x4a026203, 0x00000001, 0x493a6403, 0x0201f000, - 0x00020721, 0x4d400000, 0x0201f800, 0x00103b25, - 0x04000008, 0x59a80005, 0x84000544, 0x48035005, - 0x42028000, 0x0000002a, 0x0201f800, 0x0010a449, - 0x5c028000, 0x1c01f000, 0x59a80026, 0x8c000508, - 0x04000005, 0x599c0017, 0x8c00050a, 0x04020002, - 0x1c01f000, 0x82000540, 0x00000001, 0x1c01f000, - 0x59300420, 0x84000540, 0x48026420, 0x1c01f000, - 0x4817c857, 0x4c000000, 0x4c040000, 0x8c142d2a, - 0x04000004, 0x598800b8, 0x80000000, 0x480310b8, - 0x8c142d2e, 0x04000004, 0x598800b9, 0x80000000, - 0x480310b9, 0x8c142d2c, 0x04000013, 0x40140000, - 0x82000500, 0x00070000, 0x82000d80, 0x00030000, - 0x0400000d, 0x82000d80, 0x00040000, 0x0400000a, - 0x82000d80, 0x00050000, 0x04000007, 0x59880005, - 0x80000000, 0x48031005, 0x598800ba, 0x80000000, - 0x480310ba, 0x5c000800, 0x5c000000, 0x1c01f000, - 0x4817c857, 0x4c000000, 0x4c040000, 0x8c142d2a, - 0x04000004, 0x598800bb, 0x80000000, 0x480310bb, - 0x8c142d2e, 0x04000004, 0x598800bc, 0x80000000, - 0x480310bc, 0x8c142d2c, 0x04000013, 0x40140000, - 0x82000500, 0x00070000, 0x82000d80, 0x00030000, - 0x0400000d, 0x82000d80, 0x00040000, 0x0400000a, - 0x82000d80, 0x00050000, 0x04000007, 0x59880005, - 0x80000000, 0x48031005, 0x598800bd, 0x80000000, - 0x480310bd, 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, 0x598800a6, 0x80000000, 0x480310a6, - 0x8c040d2a, 0x04000004, 0x598800a7, 0x80000000, - 0x480310a7, 0x8c040d28, 0x04000004, 0x598800a8, - 0x80000000, 0x480310a8, 0x8c040d26, 0x04000004, - 0x598800a9, 0x80000000, 0x480310a9, 0x8c040d24, - 0x04000004, 0x598800aa, 0x80000000, 0x480310aa, - 0x8c040d22, 0x04000004, 0x598800ab, 0x80000000, - 0x480310ab, 0x8c040d20, 0x04000004, 0x598800ac, - 0x80000000, 0x480310ac, 0x5c000000, 0x1c01f000, - 0x4807c857, 0x4c000000, 0x598800ad, 0x80000000, + 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, 0x8c040d1c, 0x04000004, 0x598800ae, - 0x80000000, 0x480310ae, 0x8c040d1a, 0x04000004, - 0x598800af, 0x80000000, 0x480310af, 0x5c000000, - 0x1c01f000, 0x4807c857, 0x4c000000, 0x8c040d18, - 0x04000004, 0x598800b0, 0x80000000, 0x480310b0, - 0x8c040d16, 0x04000004, 0x598800b1, 0x80000000, - 0x480310b1, 0x8c040d14, 0x04000004, 0x598800b2, - 0x80000000, 0x480310b2, 0x5c000000, 0x1c01f000, - 0x4807c857, 0x4c000000, 0x8c040d10, 0x04000004, - 0x598800b3, 0x80000000, 0x480310b3, 0x8c040d0c, - 0x04000004, 0x598800b4, 0x80000000, 0x480310b4, + 0x4c000000, 0x598800ae, 0x80000000, 0x480310ae, 0x5c000000, 0x1c01f000, 0x4807c857, 0x4c000000, - 0x8c040d08, 0x04000004, 0x598800b5, 0x80000000, - 0x480310b5, 0x8c040d04, 0x04000004, 0x598800b6, - 0x80000000, 0x480310b6, 0x5c000000, 0x1c01f000, - 0x4807c856, 0x4c000000, 0x5988007f, 0x80000000, - 0x4803107f, 0x5c000000, 0x1c01f000, 0x4803c857, - 0x4c040000, 0x50000800, 0x80040800, 0x4807c857, - 0x44040000, 0x5c000800, 0x1c01f000, 0x480fc857, - 0x4c000000, 0x820c0580, 0x00000000, 0x04020004, - 0x42000000, 0x0010b819, 0x0401f014, 0x820c0580, - 0x00001001, 0x04020004, 0x42000000, 0x0010b81a, - 0x0401f00e, 0x820c0580, 0x00001002, 0x04020004, - 0x42000000, 0x0010b81b, 0x0401f008, 0x820c0c80, - 0x0000201c, 0x02021800, 0x001005d8, 0x820c0500, - 0x0000001f, 0x0c01f804, 0x0401ffdd, 0x5c000000, - 0x1c01f000, 0x0010aa89, 0x0010aa8c, 0x0010aa8f, - 0x0010aa92, 0x0010aa95, 0x0010aa98, 0x0010aa9b, - 0x0010aa9e, 0x0010aaa1, 0x0010aaa4, 0x0010aaa7, - 0x0010aaaa, 0x0010aaad, 0x0010aab0, 0x0010aab3, - 0x0010aab6, 0x0010aab9, 0x0010aabc, 0x0010aabf, - 0x0010aac2, 0x0010aac5, 0x0010aac8, 0x0010aacb, - 0x0010aace, 0x0010aad1, 0x0010aad4, 0x0010aad7, - 0x0010aada, 0x42000000, 0x0010b81c, 0x1c01f000, - 0x42000000, 0x0010b81d, 0x1c01f000, 0x42000000, - 0x0010b81e, 0x1c01f000, 0x42000000, 0x0010b81f, - 0x1c01f000, 0x42000000, 0x0010b820, 0x1c01f000, - 0x42000000, 0x0010b821, 0x1c01f000, 0x42000000, - 0x0010b822, 0x1c01f000, 0x42000000, 0x0010b823, - 0x1c01f000, 0x42000000, 0x0010b824, 0x1c01f000, - 0x42000000, 0x0010b825, 0x1c01f000, 0x42000000, - 0x0010b826, 0x1c01f000, 0x42000000, 0x0010b827, - 0x1c01f000, 0x42000000, 0x0010b828, 0x1c01f000, - 0x42000000, 0x0010b829, 0x1c01f000, 0x42000000, - 0x0010b82a, 0x1c01f000, 0x42000000, 0x0010b82b, - 0x1c01f000, 0x42000000, 0x0010b82c, 0x1c01f000, - 0x42000000, 0x0010b82d, 0x1c01f000, 0x42000000, - 0x0010b82e, 0x1c01f000, 0x42000000, 0x0010b82f, - 0x1c01f000, 0x42000000, 0x0010b830, 0x1c01f000, - 0x42000000, 0x0010b831, 0x1c01f000, 0x42000000, - 0x0010b832, 0x1c01f000, 0x42000000, 0x0010b833, - 0x1c01f000, 0x42000000, 0x0010b834, 0x1c01f000, - 0x42000000, 0x0010b835, 0x1c01f000, 0x42000000, - 0x0010b836, 0x1c01f000, 0x42000000, 0x0010b837, - 0x1c01f000, 0x480fc857, 0x4c000000, 0x820c0580, - 0x00000001, 0x04020004, 0x42000000, 0x0010b80e, - 0x0401f012, 0x820c0580, 0x00000002, 0x04020004, - 0x42000000, 0x0010b80f, 0x0401f00c, 0x820c0580, - 0x00000003, 0x04020004, 0x42000000, 0x0010b810, - 0x0401f006, 0x820c0580, 0x00000004, 0x04020004, - 0x42000000, 0x0010b811, 0x0401ff51, 0x5c000000, - 0x1c01f000, 0x4c000000, 0x59a80026, 0x4803c857, - 0x8c000502, 0x04000010, 0x8c000506, 0x04000004, - 0x42000000, 0x0010b841, 0x0401f012, 0x8c00050a, - 0x04000004, 0x42000000, 0x0010b840, 0x0401f00d, - 0x8c000508, 0x04000004, 0x42000000, 0x0010b843, - 0x0401f008, 0x0201f800, 0x0010513b, 0x04000006, - 0x8c000506, 0x04020004, 0x42000000, 0x0010b842, - 0x0401ff33, 0x5c000000, 0x1c01f000, 0x8058b1c0, - 0x02000800, 0x001005d8, 0x5450a800, 0x8050a000, - 0x8054a800, 0x8058b040, 0x040207fc, 0x1c01f000, - 0x8058b1c0, 0x02000800, 0x001005d8, 0x4450a800, - 0x8054a800, 0x8058b040, 0x040207fd, 0x1c01f000, - 0x8058b1c0, 0x02000800, 0x001005d8, 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, 0xa5f2b3ac + 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 = 0x0000ab4a ; +uint32_t fw2400_length01 = 0x0000a971 ; #else -uint32_t risc_code_length01 = 0x0000ab4a ; +uint32_t risc_code_length01 = 0x0000a971 ; #endif #ifdef UNIQUE_FW_NAME -uint32_t fw2400_addr02 = 0x0010e000 ; +uint32_t fw2400_addr02 = 0x0010d000 ; #else -uint32_t risc_code_addr02 = 0x0010e000 ; +uint32_t risc_code_addr02 = 0x0010d000 ; #endif #ifdef UNIQUE_FW_NAME @@ -11022,100 +10904,113 @@ uint32_t fw2400_code02[] = { #else uint32_t risc_code02[] = { #endif - 0x00000000, 0x00000000, 0x0010e000, 0x000014ff, - 0x00000000, 0x00000000, 0x00020000, 0x000008c0, - 0x836c0580, 0x00000003, 0x02020000, 0x001002e3, - 0x42000000, 0x0010b4bb, 0x50000000, 0x800001c0, - 0x04020956, 0x0401f923, 0x0401fbe3, 0x0401fb5c, - 0x0201f800, 0x00020718, 0x0201f800, 0x0002057b, - 0x0401f7f0, 0x59b800ea, 0x82000d00, 0xf0000038, - 0x02020000, 0x00100a7a, 0x8c000510, 0x02000000, - 0x00100a79, 0x59ba60e0, 0x81300182, 0x0402104e, - 0x04002030, 0x8532653e, 0x59300406, 0x82000580, - 0x00000003, 0x04020028, 0x59300203, 0x82000580, - 0x00000004, 0x04020024, 0x59325808, 0x59300402, - 0x4a025a04, 0x00000103, 0x900001c0, 0x48025806, - 0x497a5807, 0x497a5c09, 0x5930001f, 0x80000540, - 0x02020800, 0x00100d56, 0x59300004, 0x8c00053e, - 0x04020010, 0x0401fa88, 0x59326809, 0x0201f800, - 0x0002077d, 0x5934000f, 0x5934140b, 0x80081040, - 0x04001002, 0x480a6c0b, 0x80000540, 0x04020a10, - 0x59b800ea, 0x8c000510, 0x040207d7, 0x1c01f000, - 0x0201f800, 0x00106f60, 0x040007ef, 0x0201f000, - 0x00100a65, 0x42027000, 0x00000055, 0x0401f027, - 0x83326500, 0x3fffffff, 0x59300406, 0x82000580, - 0x00000003, 0x04020015, 0x59325808, 0x59326809, - 0x59301402, 0x4a025a04, 0x00000103, 0x900811c0, - 0x480a5806, 0x497a5c09, 0x497a5807, 0x0401fa62, - 0x0201f800, 0x0002077d, 0x5934000f, 0x5934140b, + 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, - 0x040209eb, 0x0401f7db, 0x42027000, 0x00000054, - 0x0401f00a, 0x83300500, 0x60000000, 0x02000000, - 0x00100a68, 0x81326580, 0x8000013a, 0x82000400, - 0x00100a80, 0x50027000, 0x59300c06, 0x82040580, - 0x00000002, 0x02000000, 0x00100a65, 0x59300004, - 0x8c00053e, 0x04020004, 0x0201f800, 0x000207a1, - 0x0401f7c4, 0x0201f800, 0x00106f60, 0x040007fb, - 0x0201f000, 0x00100a65, 0x59325808, 0x412c7000, - 0x58380a04, 0x82040500, 0x0000000f, 0x82000c00, - 0x001010bd, 0x50044000, 0x0c01f001, 0x00100dd9, - 0x00100dd9, 0x0002009f, 0x00100dd9, 0x00100dd9, - 0x00100dd9, 0x00100dd9, 0x00100dd9, 0x000200af, - 0x00100ded, 0x00100dd9, 0x00100dd9, 0x00100ddb, - 0x00100dd9, 0x00100dd9, 0x00100dd9, 0x5838040a, - 0x8c000500, 0x02000800, 0x001005d8, 0x50200000, - 0x80387c00, 0x583c1002, 0x583c2800, 0x583c2001, - 0x58380a07, 0x5838300f, 0x59303807, 0x58384c08, - 0x5838000d, 0x48026012, 0x0401f010, 0x5838020a, - 0x8c000502, 0x02000000, 0x00100dd9, 0x50200000, - 0x80387c00, 0x583c2800, 0x583c2001, 0x583c1002, - 0x592c0a07, 0x592c4c08, 0x592c300f, 0x59303807, - 0x497a6012, 0x497a6013, 0x4816600e, 0x4812600f, - 0x480a6010, 0x481a6011, 0x80040840, 0x4806600d, - 0x02020000, 0x00100e1a, 0x841c3d40, 0x481e6007, - 0x1c01f000, 0x41787800, 0x59325808, 0x592c0c0a, - 0x8c040d02, 0x02000000, 0x00100f8c, 0x592c000d, - 0x592c100f, 0x592c0a04, 0x480a6011, 0x48026012, - 0x48026013, 0x412c3000, 0x82040500, 0x0000000f, - 0x82000400, 0x001010bd, 0x50003800, 0x501c0000, - 0x401c1000, 0x592c1a07, 0x4802600a, 0x481a600b, - 0x480a600c, 0x480e600d, 0x843c7d4a, 0x403c1000, - 0x1c01f000, 0x41787800, 0x497a6012, 0x592c0a04, - 0x412c3000, 0x592c1a07, 0x82040500, 0x0000000f, - 0x82000400, 0x001010bd, 0x50004000, 0x50200000, - 0x40201000, 0x4802600a, 0x481a600b, 0x480a600c, - 0x480e600d, 0x80000580, 0x483e6004, 0x1c01f000, - 0x4c000000, 0x4df00000, 0x0201f800, 0x00020729, - 0x0401f005, 0x4c000000, 0x4df00000, 0x0401ff16, - 0x0401f001, 0x5c03e000, 0x5c000000, 0x1801f000, - 0x4203e000, 0xb0100000, 0x41fc0000, 0x82000500, - 0x00000011, 0x0c01f001, 0x0002012a, 0x00020697, - 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a, - 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a, - 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a, - 0x0002012a, 0x0002012a, 0x0010115a, 0x0002012c, - 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a, - 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a, - 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a, - 0x0002012a, 0x0002012a, 0x0201f800, 0x001005d8, - 0x0201f800, 0x00020697, 0x0201f000, 0x0010115a, - 0x42000000, 0x0010b4c1, 0x50000000, 0x8c000504, - 0x04000014, 0x42000000, 0x0010b4c1, 0x50000000, - 0x8c000502, 0x04020002, 0x1c01f000, 0x4df00000, - 0x4203e000, 0x50000000, 0x42034000, 0x0010b4a4, - 0x59a0001d, 0x59a1d81e, 0x84000502, 0x4803401d, - 0x58ec0009, 0x0801f800, 0x5c03e000, 0x1c01f000, - 0x04027002, 0x04026002, 0x1c01f000, 0x4df00000, - 0x4203e000, 0x50000000, 0x0201f800, 0x001007e4, - 0x04000010, 0x412dd800, 0x48efc857, 0x0201f800, - 0x00103b28, 0x42034000, 0x0010b4a4, 0x49a1d80b, - 0x48ef401e, 0x59a0001d, 0x84000544, 0x4803401d, - 0x0201f800, 0x00102214, 0x0201f800, 0x00102233, + 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, 0x40001000, - 0x42034000, 0x0010b4a4, 0x59a01818, 0x800c19c0, + 0x4203e000, 0x50000000, 0x04006051, 0x42034000, + 0x0010b2a0, 0x59a01017, 0x59a01818, 0x800c19c0, 0x04020008, 0x59a0381b, 0x801c39c0, 0x02000800, - 0x001005d8, 0x59a0041c, 0x801c3c00, 0x0401f00c, + 0x00100615, 0x59a0041c, 0x801c3c00, 0x0401f00c, 0x59a00419, 0x82000400, 0x00000002, 0x48034419, 0x82000c80, 0x00000013, 0x04001003, 0x497b4419, 0x41780000, 0x59a03816, 0x801c3c00, 0x80081040, @@ -11127,255 +11022,319 @@ uint32_t risc_code02[] = { 0x800c19c0, 0x04000007, 0x800c1840, 0x480f4018, 0x0402001f, 0x497b4419, 0x497b4219, 0x0401f01c, 0x800811c0, 0x0402000b, 0x4d2c0000, 0x59a2581b, - 0x0201f800, 0x001007f4, 0x5c025800, 0x497b401b, + 0x0201f800, 0x0010083a, 0x5c025800, 0x497b401b, 0x497b401a, 0x497b441c, 0x497b421c, 0x0401f010, 0x59a0041c, 0x82000400, 0x00000002, 0x82000c80, 0x00000012, 0x4803441c, 0x04001009, 0x4d2c0000, 0x59a2581b, 0x592c3813, 0x481f401b, 0x497b441c, - 0x0201f800, 0x001007f4, 0x5c025800, 0x5c03e000, + 0x0201f800, 0x0010083a, 0x5c025800, 0x5c03e000, 0x5c034000, 0x1c01f000, 0x59a80005, 0x82000500, - 0x00000003, 0x02020000, 0x00104315, 0x59340400, - 0x82000580, 0x00000606, 0x02020000, 0x001042e6, - 0x5934000d, 0x80027d40, 0x02020000, 0x00104321, + 0x00000003, 0x02020000, 0x00104145, 0x59340400, + 0x82000580, 0x00000606, 0x02020000, 0x00104116, + 0x5934000d, 0x80027d40, 0x02020000, 0x00104151, 0x0401f803, 0x80000580, 0x1c01f000, 0x5934000f, - 0x59341203, 0x80080540, 0x0402006f, 0x5934020b, - 0x5934140b, 0x80080480, 0x0402106b, 0x0201f800, - 0x0002075a, 0x04000064, 0x80081000, 0x592c0406, - 0x480a6c0b, 0x49366009, 0x492e6008, 0x4a026406, - 0x00000003, 0x4a026403, 0x00000040, 0x800000c2, + 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, 0x04000030, 0x4a026203, 0x00000004, - 0x592c0207, 0x80000040, 0x04020020, 0x59a80005, - 0x8c000514, 0x42000000, 0x00000055, 0x04020003, - 0x42000000, 0x00000033, 0x80000040, 0x040207ff, - 0x592c0204, 0x82000500, 0x000000ff, 0x82000580, - 0x00000018, 0x04020011, 0x592c180f, 0x59300007, - 0x82000540, 0x00000091, 0x480e6011, 0x48026007, - 0x42000000, 0x80000004, 0x48026004, 0x59bc00ea, - 0x8c000516, 0x040207fe, 0x83300400, 0x20000000, - 0x480378e1, 0x1c01f000, 0x0401fe78, 0x59300007, - 0x8400054e, 0x48026007, 0x592c1a04, 0x820c1d00, - 0x000000ff, 0x820c0580, 0x00000048, 0x04000017, - 0x0401f7ec, 0x8c000500, 0x04020ecb, 0x4a026203, - 0x00000002, 0x59a80805, 0x82040500, 0x00000600, - 0x04020012, 0x42000000, 0x00000030, 0x80000040, - 0x040207ff, 0x592c1a04, 0x820c1d00, 0x000000ff, - 0x820c0580, 0x00000018, 0x040007da, 0x820c0580, - 0x00000048, 0x040207d7, 0x42000800, 0x80000804, - 0x0201f000, 0x00106721, 0x8c040d12, 0x42000000, - 0x00000010, 0x040207ee, 0x42000000, 0x00000051, - 0x0401f7eb, 0x800811c0, 0x04020003, 0x4a026a03, - 0x00000001, 0x59340010, 0x492e6810, 0x80000d40, - 0x04020003, 0x492e680f, 0x1c01f000, 0x492c0800, - 0x1c01f000, 0x83440c80, 0x00000800, 0x04021009, - 0x83440400, 0x0010ac00, 0x50000000, 0x80000540, - 0x04000004, 0x40026800, 0x80000580, 0x1c01f000, - 0x82000540, 0x00000001, 0x1c01f000, 0x59340203, - 0x80000540, 0x0402004b, 0x4d300000, 0x4d2c0000, - 0x5934000f, 0x80025d40, 0x04000044, 0x0201f800, - 0x0002075a, 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, 0x0010474d, 0x4a026203, 0x00000004, - 0x592c0207, 0x80000040, 0x02020000, 0x00104740, - 0x82140580, 0x00000018, 0x02020000, 0x00104740, + 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, 0x5934020b, - 0x5934140b, 0x80080480, 0x040017be, 0x0401f003, - 0x4a026a03, 0x00000001, 0x5c025800, 0x5c026000, - 0x1c01f000, 0x497a5800, 0x49325809, 0x4a026406, - 0x00000006, 0x4a026203, 0x00000007, 0x0401f802, - 0x0401f7ef, 0x59a80021, 0x800001c0, 0x02020000, - 0x0010476f, 0x59a80005, 0x8c000504, 0x02020000, - 0x0010476b, 0x59340200, 0x8c000518, 0x02020000, - 0x00104767, 0x592c0a0c, 0x48066202, 0x4a025a06, - 0x00000000, 0x8c000508, 0x02020000, 0x00104763, - 0x4d3c0000, 0x417a7800, 0x0401fbdf, 0x5c027800, + 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, - 0x00104ce4, 0x59980022, 0x80000540, 0x04000017, - 0x592c0a06, 0x592c0409, 0x80040540, 0x04020013, - 0x0201f000, 0x00104cfa, 0x592c0404, 0x8c00051e, - 0x02020000, 0x00104cf3, 0x59980022, 0x80000540, - 0x0400000a, 0x82040580, 0x00000001, 0x04020007, - 0x0201f000, 0x00104cfa, 0x592c0404, 0x8c00051e, - 0x02020000, 0x00104dca, 0x59980026, 0x497a5800, - 0x80000540, 0x02020000, 0x00104e1d, 0x59d80105, - 0x82000d00, 0x00018780, 0x02020000, 0x00104edb, - 0x80000106, 0x82000500, 0x00000003, 0x0c01f001, - 0x000202f0, 0x00104e1d, 0x000202f6, 0x00020341, - 0x592c0001, 0x492fb107, 0x80000d40, 0x02020000, - 0x00104ddb, 0x1c01f000, 0x592c0001, 0x492fb107, - 0x80000d40, 0x02020000, 0x00104de8, 0x59da5908, - 0x835c0480, 0x00000020, 0x0400102c, 0x0402b034, - 0x492fb007, 0x0400e7fa, 0x59d80105, 0x82000500, - 0x00018780, 0x02020000, 0x00104edb, 0x0400601f, + 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, 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, 0x0400e7ca, 0x0401f7d0, 0x0402f7f7, - 0x492fa807, 0x0400e7c6, 0x0401f7cc, 0x59e0000f, - 0x59e0100f, 0x80081580, 0x040207fd, 0x81281580, - 0x040007d4, 0x40025000, 0x82040d40, 0x0000001d, - 0x0401f7d2, 0x59d80908, 0x45680800, 0x4006d000, - 0x815eb800, 0x0400e7fc, 0x59c80000, 0x82000540, - 0x00001200, 0x48039000, 0x02006000, 0x00104df8, - 0x59d8010a, 0x59d8090a, 0x80040d80, 0x040207fd, - 0x900001c0, 0x82000540, 0x00000013, 0x4803c011, - 0x5998002b, 0x84000500, 0x4803302b, 0x59e00017, - 0x8c000508, 0x04000003, 0x4a03c017, 0x00000003, - 0x4203e000, 0x30000001, 0x59d80105, 0x82000500, - 0x00018780, 0x02020000, 0x00104edb, 0x0202d000, - 0x00104dfd, 0x592c0001, 0x492fb107, 0x80000d40, - 0x02020000, 0x00104e10, 0x1c01f000, 0x59980020, - 0x0c01f001, 0x00020370, 0x00020371, 0x00104e88, - 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, - 0x0402681e, 0x04006004, 0x599c0017, 0x8c000508, - 0x04020865, 0x59980029, 0x80025d40, 0x0400000a, - 0x0402d00b, 0x59980026, 0x80000040, 0x48033026, - 0x592c0000, 0x492fb107, 0x48033029, 0x04020002, - 0x48033028, 0x5c03e000, 0x1c01f000, 0x59d80105, - 0x82000500, 0x00018780, 0x02020000, 0x00104edb, - 0x42000000, 0x0010b855, 0x0201f800, 0x0010aa47, - 0x5c03e000, 0x1c01f000, 0x5998002b, 0x8c000500, - 0x0402003b, 0x0400e007, 0x59d80105, 0x82000500, - 0x00018780, 0x02020000, 0x00104edb, 0x1c01f000, - 0x59da5908, 0x835c0c80, 0x00000020, 0x04001003, - 0x0400b029, 0x0400f02b, 0x496a5800, 0x412ed000, - 0x815eb800, 0x59c80000, 0x82000540, 0x00001200, - 0x48039000, 0x0400e7f3, 0x59d8010a, 0x59d8090a, - 0x80040580, 0x040207fd, 0x800408e0, 0x599c1017, - 0x8c081508, 0x04020022, 0x82040d40, 0x00000013, - 0x4807c011, 0x59e00017, 0x8c000508, 0x0400000a, - 0x4a03c017, 0x00000003, 0x82040500, 0x000000ff, - 0x82000580, 0x0000001d, 0x04020003, 0x4a03c017, - 0x0000000d, 0x4203e000, 0x30000001, 0x59d80105, - 0x82000500, 0x00018780, 0x02020000, 0x00104edb, - 0x1c01f000, 0x492fb007, 0x0400e7d2, 0x0401f7df, - 0x492fa807, 0x0400e7cf, 0x0401f7dc, 0x84000500, - 0x4803302b, 0x0400e7cb, 0x0401f7d8, 0x59e0000f, - 0x59e0100f, 0x80081580, 0x040207fd, 0x81281580, - 0x040007da, 0x40025000, 0x82040d40, 0x0000001d, - 0x0401f7d8, 0x59e0000f, 0x59e0100f, 0x80080d80, - 0x040207fd, 0x81280580, 0x04020002, 0x1c01f000, - 0x400a5000, 0x900811c0, 0x82081540, 0x0000001c, - 0x480bc011, 0x59e00017, 0x8c000508, 0x04000003, - 0x4a03c017, 0x0000000c, 0x4203e000, 0x30000001, - 0x1c01f000, 0x41700000, 0x0c01f001, 0x00105420, - 0x000203fc, 0x00105420, 0x00105421, 0x0010541e, - 0x0010541e, 0x0010541e, 0x0010541e, 0x001058b0, - 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, - 0x0400f94a, 0x0400b134, 0x59d40005, 0x82000500, - 0x43018780, 0x02020000, 0x0010583f, 0x59d80005, - 0x82000500, 0x43018780, 0x02020000, 0x00105846, - 0x1c01f000, 0x83700580, 0x00000003, 0x02000800, - 0x00105421, 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, 0x00105491, 0x5c03e000, - 0x0401f7d4, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105527, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x001054a1, - 0x00105491, 0x00105491, 0x00105491, 0x00105551, - 0x00105491, 0x00105491, 0x00105491, 0x000204ef, - 0x00105491, 0x001056b4, 0x00105491, 0x00105491, - 0x00105491, 0x000204c2, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x001054c9, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x001057d3, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x0010581e, 0x00105491, - 0x001054bb, 0x00105491, 0x00105797, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105765, 0x00105491, - 0x00105765, 0x00105872, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105725, - 0x00105855, 0x00105491, 0x00105865, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x00105491, 0x00105491, - 0x00105491, 0x00105491, 0x592c0204, 0x80000110, - 0x02000000, 0x00105499, 0x80000040, 0x04000009, - 0x48033002, 0x492f3003, 0x492f3004, 0x4a033008, - 0x000204d0, 0x4202e000, 0x00000003, 0x1c01f000, - 0x592c0406, 0x82000c80, 0x0000199a, 0x02021000, - 0x001054a9, 0x59a80021, 0x80000540, 0x02020000, - 0x001054d7, 0x592e8a06, 0x83440c80, 0x000007f0, - 0x02021000, 0x001054a9, 0x83440400, 0x0010ac00, - 0x50000000, 0x80026d40, 0x02000000, 0x001054db, - 0x59340002, 0x592c0810, 0x80040580, 0x82000500, - 0x00ffffff, 0x02020000, 0x001054a9, 0x0401fccf, - 0x02020000, 0x001054de, 0x1c01f000, 0x592c0204, - 0x80000110, 0x02000000, 0x00105499, 0x80000040, + 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, - 0x001054a9, 0x0201f000, 0x0010588a, 0x48033002, - 0x492f3003, 0x492f3004, 0x4a033008, 0x00020507, + 0x00105179, 0x0201f000, 0x0010556e, 0x48033002, + 0x492f3003, 0x492f3004, 0x4a033008, 0x0002063b, 0x4202e000, 0x00000003, 0x1c01f000, 0x592c0406, - 0x82000c80, 0x0000199a, 0x02021000, 0x001054a9, - 0x592e8a06, 0x417a7800, 0x0401fd37, 0x02020000, - 0x00105658, 0x59340002, 0x592c0808, 0x80040580, - 0x82000500, 0x00ffffff, 0x02020000, 0x001054a9, + 0x82000c80, 0x0000199a, 0x02021000, 0x00105179, + 0x592e8a06, 0x417a7800, 0x0401fc25, 0x02020000, + 0x0010533c, 0x59340002, 0x592c0808, 0x80040580, + 0x82000500, 0x00ffffff, 0x02020000, 0x00105179, 0x497a5808, 0x592e6009, 0x83300580, 0xffffffff, - 0x02000000, 0x00105618, 0x83300480, 0x0010d1c0, - 0x02001000, 0x00105675, 0x59a8000b, 0x81300480, - 0x02021000, 0x00105675, 0x592c240a, 0x49366009, - 0x8c10251c, 0x02020000, 0x00105606, 0x59a80068, - 0x8c000510, 0x02020000, 0x0010568e, 0x59a80821, - 0x800409c0, 0x02020000, 0x001055ec, 0x59a80805, - 0x8c040d04, 0x02020000, 0x0010567f, 0x59340200, - 0x8c000518, 0x02020000, 0x00105670, 0x59300c06, - 0x82040580, 0x00000006, 0x02020000, 0x00105610, - 0x59300414, 0x8c000516, 0x02020000, 0x0010567a, - 0x8c102508, 0x02020000, 0x0010a5b8, 0x59300808, + 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, - 0x001055e7, 0x592c0a0c, 0x48066202, 0x492e6008, - 0x0401f14d, 0x4df00000, 0x4203e000, 0x50000000, + 0x001052cb, 0x592c0a0c, 0x48066202, 0x492e6008, + 0x0401f14a, 0x4df00000, 0x4203e000, 0x50000000, 0x0402b00b, 0x835c0480, 0x00000020, 0x0400100d, 0x815eb840, 0x416a5800, 0x592ed000, 0x492fb007, 0x497a5800, 0x497a5801, 0x0400b7f7, 0x59d80005, - 0x82000500, 0x43018780, 0x02020000, 0x00105846, + 0x82000500, 0x43018780, 0x02020000, 0x0010552a, 0x5c03e000, 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, 0x0402f00b, 0x835c0480, 0x00000020, 0x0400100d, 0x815eb840, 0x416a5800, 0x592ed000, 0x492fa807, 0x497a5800, 0x497a5801, 0x0400f7f7, 0x59d40005, 0x82000500, 0x43018780, 0x02020000, - 0x0010583f, 0x5c03e000, 0x1c01f000, 0x4df00000, + 0x00105523, 0x5c03e000, 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, 0x59940024, 0x80000540, - 0x04000112, 0x4c000000, 0x42000000, 0x00001000, + 0x0400010f, 0x4c000000, 0x42000000, 0x00001000, 0x50000000, 0x82000480, 0x24320001, 0x04020015, 0x42000800, 0x00000064, 0x80040840, 0x04000007, 0x4a030000, 0x00000001, 0x40000000, 0x59800000, @@ -11397,7 +11356,7 @@ uint32_t risc_code02[] = { 0x483fc857, 0x59e40852, 0x59a80025, 0x80040580, 0x04000004, 0x480bc857, 0x59e40052, 0x48035025, 0x59940026, 0x803c0400, 0x48032826, 0x0201f800, - 0x00106021, 0x59940000, 0x82000580, 0x00000000, + 0x00105d5a, 0x59940000, 0x82000580, 0x00000000, 0x04020006, 0x59940026, 0x48032827, 0x497b2826, 0x4a032800, 0x00000001, 0x4c0c0000, 0x59940007, 0x80000d40, 0x0400001d, 0x59941006, 0x59940025, @@ -11418,54 +11377,54 @@ uint32_t risc_code02[] = { 0x0000000a, 0x48007800, 0x040027fa, 0x82040500, 0x0000007f, 0x0401f7e8, 0x583c0002, 0x4c3c0000, 0x0801f800, 0x5c007800, 0x0401f7e3, 0x5c023000, - 0x59940019, 0x80001540, 0x04000008, 0x04002007, - 0x59940025, 0x80080480, 0x497b2819, 0x04001003, - 0x04000002, 0x48032819, 0x59940004, 0x80000d40, - 0x0400002a, 0x4c040000, 0x5994001c, 0x80000d40, - 0x04000013, 0x5994101b, 0x59940025, 0x80080480, - 0x04001005, 0x04000004, 0x4803281b, 0x80000040, - 0x0402100b, 0x80040840, 0x4807281c, 0x04020004, - 0x5994001d, 0x0801f800, 0x0401f005, 0x82000400, - 0x0000000a, 0x4803281b, 0x040027f7, 0x5c000800, - 0x59941003, 0x59940025, 0x80080480, 0x04001005, - 0x04000004, 0x48032803, 0x80000040, 0x0402100b, - 0x80040840, 0x48072804, 0x04020004, 0x59940005, + 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, - 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, - 0x001005d8, 0x48032824, 0x59940000, 0x0c01f001, - 0x00105fb5, 0x00105fb7, 0x00105fdd, 0x59940024, - 0x80000000, 0x48032824, 0x4203e000, 0x70000000, - 0x1c01f000, 0x592c0406, 0x800000c2, 0x800008c4, - 0x80040c00, 0x592c040a, 0x48066206, 0x82000d00, - 0x00000003, 0x02000000, 0x0010615e, 0x8c000500, - 0x04020029, 0x8c00051e, 0x02000000, 0x00106139, - 0x82000d00, 0x000000c0, 0x02020000, 0x0010612f, - 0x82000d00, 0x00002020, 0x02020000, 0x0010612c, - 0x813e79c0, 0x02020000, 0x0010612c, 0x592c0c0c, - 0x800409c0, 0x02020000, 0x0010612c, 0x59300a03, - 0x82040d80, 0x00000007, 0x02020000, 0x0010612c, + 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, 0x000200c9, 0x82080d40, 0x80003465, + 0x0201f800, 0x000200ca, 0x82080d40, 0x80003465, 0x48066004, 0x497a6000, 0x59bc00ea, 0x8c000516, 0x040207fe, 0x83300400, 0xa0000000, 0x480378e1, - 0x1c01f000, 0x8c000502, 0x02020000, 0x00106181, + 0x1c01f000, 0x8c000502, 0x02020000, 0x00105eba, 0x8c00051e, 0x0400000e, 0x82000d00, 0x000000c0, 0x04000005, 0x82040d80, 0x000000c0, 0x02020000, - 0x00106186, 0x82000d00, 0x00002020, 0x82040d80, - 0x00002020, 0x02000000, 0x0010614d, 0x592c0207, - 0x80000040, 0x02020000, 0x00106157, 0x592c180d, - 0x800c19c0, 0x02020000, 0x00106157, 0x592c180f, + 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, @@ -11473,904 +11432,915 @@ uint32_t risc_code02[] = { 0x0401f003, 0x42000800, 0x00000001, 0x59325808, 0x832c0500, 0x00ff0000, 0x0400000d, 0x592c0000, 0x48065a06, 0x48026008, 0x592c040a, 0x8c000510, - 0x04020008, 0x0201f800, 0x000202ce, 0x417a7800, - 0x59300008, 0x80025d40, 0x0402078f, 0x1c01f000, + 0x04020008, 0x0201f800, 0x00020381, 0x417a7800, + 0x59300008, 0x80025d40, 0x0402078c, 0x1c01f000, 0x456a5800, 0x412ed000, 0x815eb800, 0x59c80000, 0x82000540, 0x00001200, 0x48039000, 0x0401f7f4, 0x59840000, 0x80000540, 0x04020002, 0x1c01f000, - 0x59840003, 0x80000540, 0x02020000, 0x001061fe, - 0x1c01f000, 0x48066004, 0x59bc00ea, 0x8c000516, + 0x59840003, 0x80000540, 0x02020000, 0x00105f37, + 0x1c01f000, 0x59300004, 0x82000500, 0x00000100, + 0x80040d40, 0x48066004, 0x59bc00ea, 0x8c000516, 0x040207fe, 0x83300400, 0x40000000, 0x480378e1, 0x1c01f000, 0x59bc00ea, 0x82001500, 0xb0000018, - 0x02020000, 0x00106c81, 0x8c000510, 0x0400002a, + 0x02020000, 0x001069c6, 0x8c000510, 0x0400002a, 0x59bc10e0, 0x82080500, 0xfffff000, 0x0402000a, 0x80080108, 0x820a3500, 0x0000000f, 0x4803c857, - 0x1201f000, 0x00106c87, 0x84000510, 0x48026004, + 0x1201f000, 0x001069cc, 0x84000510, 0x48026004, 0x0401f016, 0x840a653e, 0x59300004, 0x8c000520, 0x040007fa, 0x82000500, 0xfffefeff, 0x48026004, 0x8c08153e, 0x04020005, 0x42027000, 0x00000013, - 0x0401f859, 0x0401f009, 0x59300004, 0x8c000514, - 0x04000003, 0x0401ffb0, 0x0401f02f, 0x42027000, - 0x00000049, 0x0401f850, 0x59bc00ea, 0x82001500, - 0xb0000018, 0x02020000, 0x00106c81, 0x8c000510, + 0x0401f858, 0x0401f009, 0x59300004, 0x8c000514, + 0x04000003, 0x0401ffac, 0x0401f02e, 0x42027000, + 0x00000049, 0x0401f84f, 0x59bc00ea, 0x82001500, + 0xb0000018, 0x02020000, 0x001069c6, 0x8c000510, 0x040207d8, 0x1c01f000, 0x83640480, 0x00000010, - 0x0400101a, 0x41626000, 0x41580000, 0x59300a03, + 0x04001019, 0x41626000, 0x41580000, 0x59300a03, 0x82040d80, 0x00000000, 0x04000008, 0x83326400, 0x00000024, 0x81300c80, 0x040017f9, 0x42026000, - 0x0010d1c0, 0x0401f7f6, 0x8166c840, 0x83300c00, - 0x00000024, 0x80040480, 0x04021005, 0x4006c000, - 0x4a026203, 0x00000008, 0x1c01f000, 0x837ac540, - 0x0010d1c0, 0x0401f7fb, 0x42000000, 0x0010b854, - 0x0201f800, 0x0010aa47, 0x4967c857, 0x80026580, - 0x1c01f000, 0x83300480, 0x0010d1c0, 0x02001800, - 0x001005d8, 0x41580000, 0x81300480, 0x0402100c, - 0x04011000, 0x457a6000, 0x4a026202, 0x0000ffff, - 0x83300400, 0x00000003, 0x4803c840, 0x4a03c842, - 0x00000021, 0x8166c800, 0x1c01f000, 0x41540000, - 0x81300480, 0x02021800, 0x001005d8, 0x04011000, + 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, - 0x59a80066, 0x49335065, 0x80000000, 0x48035066, - 0x1c01f000, 0x4d340000, 0x59326809, 0x59300406, - 0x82000500, 0x0000001f, 0x0c01f803, 0x5c026800, - 0x1c01f000, 0x00107966, 0x00107979, 0x00107993, - 0x000207c9, 0x001098f1, 0x0010990c, 0x0002083e, - 0x00107966, 0x00107979, 0x001064ee, 0x001079ac, - 0x00107966, 0x00107966, 0x00107966, 0x00107966, - 0x00107966, 0x001095a1, 0x0010a6c2, 0x00107966, - 0x00107966, 0x00107966, 0x00107966, 0x00107966, - 0x00107966, 0x00107966, 0x00107966, 0x00107966, - 0x00107966, 0x00107966, 0x00107966, 0x00107966, - 0x00107966, 0x59300203, 0x82000c80, 0x0000000e, - 0x02021800, 0x001005d8, 0x0c01f001, 0x001079aa, - 0x00108592, 0x000207dd, 0x00108720, 0x001087b9, - 0x001079aa, 0x001079aa, 0x001079aa, 0x00108577, - 0x001079aa, 0x001079aa, 0x001079aa, 0x001079aa, - 0x00108985, 0x83380480, 0x00000058, 0x04021007, - 0x83380480, 0x00000040, 0x04001004, 0x4d2c0000, - 0x0c01f803, 0x5c025800, 0x1c01f000, 0x0010861b, - 0x0010861b, 0x0010861b, 0x0010861b, 0x0010861b, - 0x0010861d, 0x001086bd, 0x0010861b, 0x0010861b, - 0x0010861b, 0x0010861b, 0x0010861b, 0x0010861b, - 0x0010861b, 0x0010861b, 0x0010861b, 0x0010861b, - 0x0010861b, 0x0010861b, 0x001086c1, 0x000207ff, - 0x0010861b, 0x001086c0, 0x001086c2, 0x59325808, - 0x59300811, 0x59301402, 0x59340200, 0x8c00050e, - 0x0402001c, 0x0401f826, 0x04000005, 0x4a025a04, - 0x00000103, 0x497a5c09, 0x0401f009, 0x4a025a04, - 0x00000103, 0x4a025a06, 0x00000000, 0x497a5c09, - 0x800409c0, 0x02020800, 0x00108785, 0x48065807, - 0x480a5c06, 0x0201f800, 0x000202c1, 0x5934000f, - 0x5934140b, 0x80081040, 0x04001002, 0x480a6c0b, - 0x80000540, 0x02020800, 0x00020253, 0x0401f75e, - 0x592c020a, 0x8c000502, 0x040007e9, 0x800409c0, - 0x040007e7, 0x592c0208, 0x8c00050e, 0x040207e4, - 0x4933c857, 0x0201f000, 0x0010920f, 0x592c020a, - 0x8c000500, 0x04000010, 0x59300015, 0x592c380f, - 0x801c3c80, 0x0400000c, 0x4a025a06, 0x00000015, - 0x8c1c3d3e, 0x04000005, 0x4a025a06, 0x00000007, - 0x801c3880, 0x801c3800, 0x481fc857, 0x821c0d40, - 0x00000000, 0x1c01f000, 0x59300203, 0x82003480, - 0x0000000e, 0x02021800, 0x001005d8, 0x0c01f001, - 0x0010992b, 0x00020852, 0x00109fba, 0x00109fc8, - 0x0002086e, 0x0010992b, 0x0010a0a8, 0x0002088d, - 0x0010992b, 0x0010992b, 0x0010992b, 0x0010992b, - 0x0010992b, 0x0010992b, 0x83380580, 0x00000013, - 0x02020000, 0x00109f42, 0x59300403, 0x82027480, - 0x00000044, 0x02021800, 0x001005d8, 0x82000480, - 0x00000040, 0x02001800, 0x001005d8, 0x0c01f001, - 0x00109f9e, 0x00020864, 0x00109fa0, 0x00109fb2, - 0x59325808, 0x832c0500, 0x00ff0000, 0x04000005, - 0x592c0c0a, 0x8c040d1a, 0x02020000, 0x00109fad, - 0x0401fe91, 0x0401f710, 0x83380580, 0x00000048, - 0x04000007, 0x83380580, 0x00000053, 0x02000000, - 0x0010a04a, 0x0201f800, 0x001005d8, 0x5930001f, - 0x59301011, 0x59300809, 0x58040a00, 0x8c040d0e, - 0x02020000, 0x0010a026, 0x800811c0, 0x02020000, - 0x0010a033, 0x5930001f, 0x80000540, 0x02020000, - 0x0010a041, 0x59325808, 0x592c040a, 0x8c00051e, - 0x02000000, 0x0010a01c, 0x42027000, 0x00000041, - 0x0401f001, 0x83380480, 0x00000054, 0x02021800, - 0x001005d8, 0x83380480, 0x00000040, 0x02001000, - 0x0010a067, 0x0c01f001, 0x0010a073, 0x000208aa, - 0x0010a07f, 0x0010a086, 0x0010a073, 0x0010a073, - 0x0010a073, 0x0010a073, 0x0010a075, 0x0010a07a, - 0x0010a07a, 0x0010a073, 0x0010a073, 0x0010a073, - 0x0010a073, 0x0010a07a, 0x0010a073, 0x0010a07a, - 0x0010a073, 0x0010a075, 0x4a026203, 0x00000001, - 0x493a6403, 0x42000800, 0x80002042, 0x0401f672, + 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, 0x00000000, 0x14aa62b1, - 0x00000000, 0x00000000, 0x00000000, 0x00000005, - 0xfffffffb, 0x02800004, 0x00000000, 0x0000c000, - 0x0000071d, 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, 0x058185c6, 0x027c0045, - 0x03020000, 0x06810037, 0x027c0045, 0x03040000, - 0x068100c7, 0x027c0045, 0x03080000, 0x0781061e, - 0x04908037, 0x029105c4, 0x010410a6, 0x0379ff41, - 0x037fffff, 0x072d6000, 0x07601241, 0x050f80ff, - 0x032fa009, 0x05600400, 0x050f80ff, 0x056c04ff, - 0x068105dc, 0x073fa009, 0x06000001, 0x0279ff02, - 0x0700ffff, 0x070ff0d1, 0x0179feff, 0x0700ffff, - 0x045c0402, 0x048185dc, 0x060ff0d0, 0x0179feff, - 0x0700ffff, 0x057dfeff, 0x0700ffff, 0x078105be, - 0x05600e41, 0x050f80ff, 0x032fa069, 0x07480000, - 0x068105d0, 0x06780043, 0x070000f0, 0x0781005f, - 0x037c00ff, 0x06000010, 0x0781005f, 0x038005cc, - 0x0379ff00, 0x070fffff, 0x06780043, 0x07f00000, - 0x075a0000, 0x020ef001, 0x028605ce, 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, 0x078105d7, 0x050020ff, - 0x027c0002, 0x06000010, 0x078100c3, 0x038005d7, - 0x0700c0d1, 0x0379ff0c, 0x070000ff, 0x0380008e, - 0x0204a051, 0x06780043, 0x070000f0, 0x037c00ff, - 0x06000010, 0x0781816a, 0x072d6000, 0x019485c0, - 0x050fb056, 0x044880e6, 0x04818010, 0x060ff0d0, - 0x0179feff, 0x0700ffff, 0x057dfeff, 0x0700ffff, - 0x078105be, 0x05a00212, 0x0349c0e4, 0x0781811d, - 0x070ff093, 0x050010ff, 0x070ff093, 0x045c0401, - 0x058180db, 0x02046092, 0x04002046, 0x04600202, - 0x00540401, 0x048280e6, 0x04500425, 0x070060ff, - 0x0730ffff, 0x0700000f, 0x0742000f, 0x05810190, - 0x07a005a6, 0x0648a002, 0x048180e9, 0x00047089, - 0x070ff047, 0x045c0443, 0x077800ff, 0x07f00000, - 0x0781818e, 0x07780047, 0x0500e000, 0x048185ad, - 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, - 0x078105b4, 0x027c0001, 0x06000020, 0x078105b4, - 0x038005cc, 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, - 0x06810510, 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, 0x00a1860e, - 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, 0x06a0060e, 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, 0x02800013, 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, 0x07810533, 0x052e6200, 0x070ff088, - 0x0179feff, 0x070fffff, 0x04818501, 0x060ff083, - 0x0086836d, 0x033e6000, 0x07000003, 0x068d0352, - 0x07286000, 0x07f00000, 0x078d0355, 0x038c0306, - 0x0648c0e6, 0x05818372, 0x0448e0e6, 0x0781036a, - 0x004920e6, 0x07810365, 0x07a0056f, 0x05001088, - 0x00700101, 0x03100000, 0x00088001, 0x033e6000, - 0x07000088, 0x03800560, 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, 0x05818521, 0x0448b075, 0x06810385, - 0x02493075, 0x0681050e, 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, 0x07a00578, 0x033e6a00, 0x0302000a, - 0x062e5020, 0x003e4002, 0x07000a00, 0x028003f1, - 0x07420003, 0x0781844e, 0x00798002, 0x06000507, - 0x06818451, 0x0180045c, 0x05930478, 0x01257000, - 0x073c3fff, 0x0700000f, 0x052e4003, 0x072e5030, - 0x0304c050, 0x067800e6, 0x07000041, 0x0581047d, - 0x07a00581, 0x04818016, 0x002fb008, 0x067800e6, - 0x07000041, 0x04810483, 0x07a00581, 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, 0x00a18608, - 0x05a004cc, 0x05308000, 0x05001000, 0x06009079, - 0x04a004dc, 0x03800560, 0x0249c0e6, 0x058104f9, - 0x0280036d, 0x0648307a, 0x07818196, 0x05a004cf, - 0x05308000, 0x03013000, 0x03209006, 0x04a004dc, - 0x033e6000, 0x07030000, 0x02800345, 0x02490075, - 0x0781051e, 0x04002089, 0x04780102, 0x07f00000, - 0x05001088, 0x07a0056f, 0x04740101, 0x03100000, - 0x060ff002, 0x045c0401, 0x0481851f, 0x00088001, - 0x033e6000, 0x070000c0, 0x0380055c, 0x07f00000, - 0x0220951f, 0x018004e4, 0x0648307a, 0x07810527, - 0x06780075, 0x06000007, 0x0581852e, 0x06a00608, - 0x06486075, 0x06818194, 0x02490075, 0x0781819a, - 0x04487075, 0x05818536, 0x0280053d, 0x05308000, - 0x03010000, 0x06009079, 0x04a004dc, 0x02800010, - 0x0448e0e6, 0x04818352, 0x00800192, 0x05308000, - 0x0500e000, 0x06009079, 0x04a004dc, 0x04008089, - 0x05a004e1, 0x0380055c, 0x05a004cc, 0x05308000, - 0x0700f000, 0x06009079, 0x07000088, 0x06a00545, - 0x04a004dc, 0x02800010, 0x03386000, 0x07030000, - 0x07f00000, 0x078d0548, 0x033e6a00, 0x0202000e, - 0x02079051, 0x0448b075, 0x07810553, 0x02493075, - 0x07810553, 0x05301005, 0x03010000, 0x03800555, - 0x05301006, 0x03010000, 0x05002087, 0x06485002, - 0x05818555, 0x0744c000, 0x01088000, 0x02086001, - 0x07c00000, 0x05001088, 0x07a0056f, 0x0644c001, - 0x00088001, 0x033e6a00, 0x0202000e, 0x004920e6, - 0x05818565, 0x02079051, 0x078d0565, 0x060ff089, - 0x034990ff, 0x0781056c, 0x03386005, 0x03010000, - 0x02800010, 0x03386006, 0x03010000, 0x02800010, - 0x078d056f, 0x03386000, 0x07030000, 0x07f00000, - 0x068d0573, 0x070ff087, 0x074850ff, 0x05818574, - 0x07c00000, 0x078d0578, 0x02386001, 0x07030000, - 0x07f00000, 0x068d057c, 0x070ff087, 0x074850ff, - 0x0581857d, 0x07c00000, 0x05002087, 0x0049d002, - 0x05818590, 0x002fb008, 0x067800e6, 0x07000041, - 0x002fb008, 0x05818590, 0x07a005a6, 0x0448e002, - 0x07810593, 0x0648a002, 0x0481859d, 0x06486002, - 0x06810597, 0x02400057, 0x056a02ff, 0x07c00000, - 0x07a005a6, 0x06788102, 0x06000004, 0x05818590, - 0x04002089, 0x070ff0d4, 0x045c0402, 0x077800ff, - 0x07f00000, 0x05818590, 0x00202010, 0x038c0590, - 0x07f00000, 0x06420002, 0x0481859e, 0x07a00578, - 0x033e6a00, 0x0302000a, 0x07c00000, 0x07f00000, - 0x060ff0a2, 0x050020ff, 0x060ff0a2, 0x045c0402, - 0x048185a7, 0x07c00000, 0x05a00218, 0x03495047, - 0x078105b2, 0x0320901d, 0x02800604, 0x0220901f, - 0x02800604, 0x014980e4, 0x04818010, 0x013e4000, - 0x07003000, 0x05600e35, 0x050f80ff, 0x07a006fc, - 0x01208003, 0x05a004e1, 0x038005cc, 0x03209009, - 0x02800604, 0x03209011, 0x02800604, 0x02209007, - 0x02800604, 0x03209003, 0x02800604, 0x00498043, - 0x058185be, 0x00497043, 0x048185c2, 0x02209001, - 0x02800604, 0x0220900d, 0x02800604, 0x0320900f, - 0x02800604, 0x03493000, 0x068105d5, 0x027c0045, - 0x070a0000, 0x078105de, 0x0220900b, 0x02800604, - 0x02209013, 0x05308000, 0x01012000, 0x04a004dc, - 0x00800183, 0x03209005, 0x02800604, 0x072e500c, - 0x00208002, 0x05a004e1, 0x02800010, 0x02209015, - 0x02800604, 0x072d6000, 0x05308000, 0x05007000, - 0x07f00000, 0x070090d1, 0x0379ff09, 0x0700ffff, - 0x04a004dc, 0x03209017, 0x02800604, 0x033e5000, - 0x06000080, 0x02209019, 0x02800604, 0x072d6000, - 0x033e5000, 0x06000080, 0x07f00000, 0x060ff0d0, + 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, - 0x04818010, 0x02400058, 0x00642058, 0x06820010, - 0x033e5000, 0x06000080, 0x04058051, 0x0320901b, - 0x02800604, 0x05308000, 0x01012000, 0x04a004dc, - 0x00800176, 0x05a00218, 0x05308000, 0x05008000, - 0x06009079, 0x04a004dc, 0x07c00000, 0x034900e4, - 0x05818618, 0x013e4000, 0x070000c0, 0x07f00000, - 0x034900e4, 0x04818616, 0x07c00000, 0x013e4000, - 0x06000080, 0x07f00000, 0x07f00000, 0x07f00000, - 0x034900e4, 0x06810610, 0x03800618, 0x072d6000, - 0x00498043, 0x06810632, 0x060ff0d0, 0x0179feff, - 0x0700ffff, 0x057dfeff, 0x0700ffff, 0x058185e2, - 0x050f8030, 0x032fa009, 0x0379ff00, 0x0700ffff, - 0x070ff0d1, 0x0179feff, 0x0700ffff, 0x055c0400, - 0x078105e2, 0x04004051, 0x0280067a, 0x06a006dc, - 0x062d6001, 0x020ef004, 0x038605e4, 0x06600004, - 0x050f80ff, 0x032fa009, 0x074b0000, 0x05002000, - 0x0769ff00, 0x01640800, 0x078205e4, 0x01640e00, - 0x058285e4, 0x070ff036, 0x045c0404, 0x0581864d, - 0x072d6000, 0x050f8030, 0x032fa009, 0x0379ff00, + 0x048185e0, 0x050f8030, 0x032fa009, 0x0379ff00, 0x0700ffff, 0x070ff0d1, 0x0179feff, 0x0700ffff, - 0x055c0400, 0x078105e2, 0x04482034, 0x078105ff, - 0x06483034, 0x058185ff, 0x070ff0d4, 0x077800ff, - 0x070000f0, 0x037c00ff, 0x06000010, 0x0681067a, - 0x06a006d6, 0x024900e5, 0x0681065d, 0x033e5000, - 0x06000080, 0x02800010, 0x04601c04, 0x050f80ff, - 0x053fa809, 0x06000020, 0x030ef041, 0x038605ee, - 0x062d6002, 0x05602a41, 0x050f80ff, 0x012fa809, - 0x060ff0d0, 0x074b00ff, 0x045c0401, 0x05818678, - 0x062d6001, 0x07602841, 0x050f80ff, 0x053fa809, - 0x06000001, 0x070ff0d1, 0x054b80ff, 0x074b0003, - 0x055c0403, 0x05818678, 0x033e5000, 0x06000080, - 0x0080070e, 0x07600041, 0x0280065e, 0x06a006d6, - 0x024900e5, 0x06810680, 0x033e5000, 0x06000080, - 0x02800010, 0x06a006c2, 0x030ef041, 0x028605f2, - 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, 0x028606bf, - 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, 0x0080070e, 0x040f8032, - 0x073fa011, 0x06000001, 0x060ff002, 0x055c0403, - 0x058186ca, 0x00041051, 0x07c00000, 0x04600402, - 0x04500432, 0x050f80ff, 0x053fa809, 0x06000020, - 0x00400402, 0x01680eff, 0x070030ff, 0x040f8032, - 0x053fa80a, 0x06000001, 0x07c00000, 0x024900e5, - 0x068106d9, 0x07c00000, 0x033e5000, 0x070000c0, - 0x07c00000, 0x05004036, 0x060000d0, 0x0179fe00, - 0x0700ffff, 0x057dfeff, 0x0700ffff, 0x068106fb, - 0x070000d1, 0x0379ff00, 0x0700ffff, 0x06005051, - 0x060ff031, 0x05500405, 0x050f80ff, 0x073fa009, - 0x06000002, 0x020ef004, 0x038606f5, 0x04600404, - 0x050f80ff, 0x012fa809, 0x0079fe01, 0x0700ffff, - 0x055c0400, 0x068106fb, 0x01400405, 0x070050ff, - 0x057de0ff, 0x06000007, 0x058186e7, 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, 0xba6b4e34, 0x02800004, 0x00000000, - 0x00008000, 0x00000518, 0x040f801f, 0x012fa8c9, - 0x040f801f, 0x073fa081, 0x06000010, 0x03200005, - 0x07420000, 0x050fb000, 0x040f801f, 0x073fa011, - 0x06000038, 0x040f801f, 0x053fa859, 0x0700003a, - 0x050fe000, 0x0581800a, 0x0684003d, 0x04958019, - 0x030e0011, 0x072e4200, 0x03800014, 0x0291001f, - 0x050010c0, 0x04482001, 0x058180e8, 0x06483001, - 0x0781814b, 0x02920029, 0x068b0029, 0x018a0150, - 0x050010c0, 0x06780001, 0x050007c0, 0x06818223, - 0x06780001, 0x0500f800, 0x07818263, 0x03910030, - 0x040fe029, 0x03860030, 0x076c001d, 0x04810294, - 0x076c0a1d, 0x048102b9, 0x0292003d, 0x040fe02f, - 0x0286003d, 0x06000013, 0x050fb000, 0x066c0073, - 0x068103c2, 0x0297003d, 0x014920e4, 0x0481803d, - 0x03400000, 0x076c0a00, 0x04818034, 0x0796003f, - 0x03b900b8, 0x05908014, 0x010170e1, 0x07780017, - 0x03e00000, 0x06810092, 0x050010ff, 0x0179fe17, + 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, 0x0681005e, 0x0249f002, - 0x068100ab, 0x0448e002, 0x0681005e, 0x07600c00, + 0x037c00ff, 0x03800000, 0x0681005d, 0x0249f002, + 0x078100aa, 0x0448e002, 0x0681005d, 0x07600c00, 0x050f80ff, 0x073fa009, 0x06000001, 0x06780002, - 0x07ffff00, 0x037c00ff, 0x05000200, 0x048180ab, - 0x064bd401, 0x03d00060, 0x038000a9, 0x02800068, - 0x03800072, 0x0280007c, 0x02800086, 0x03800090, - 0x038000a9, 0x038000a9, 0x050fe027, 0x0186806c, - 0x01028000, 0x0380006f, 0x07600027, 0x050f80ff, - 0x032fa00a, 0x01027000, 0x02400029, 0x028000ab, - 0x040fe025, 0x00868076, 0x03026000, 0x02800079, + 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, 0x028000ab, 0x050fe021, 0x00868080, - 0x01022000, 0x02800083, 0x07600021, 0x050f80ff, - 0x032fa00a, 0x01021000, 0x02400029, 0x028000ab, - 0x040fe023, 0x0086808a, 0x01024000, 0x0380008d, + 0x02400029, 0x038000aa, 0x050fe021, 0x0086807f, + 0x01022000, 0x03800082, 0x07600021, 0x050f80ff, + 0x032fa00a, 0x01021000, 0x02400029, 0x038000aa, + 0x040fe023, 0x00868089, 0x01024000, 0x0280008c, 0x06600023, 0x050f80ff, 0x032fa00a, 0x03023000, - 0x02400029, 0x028000ab, 0x06a000c8, 0x028000ab, - 0x01640817, 0x058280a9, 0x070ff017, 0x03d00096, - 0x0280009e, 0x038000a0, 0x038000a3, 0x038000a6, - 0x038000a9, 0x038000a9, 0x038000a9, 0x038000a9, - 0x03e00000, 0x03800014, 0x059080a0, 0x030160e1, - 0x028000ab, 0x059080a3, 0x030150e1, 0x028000ab, - 0x059080a6, 0x010140e1, 0x028000ab, 0x060fc013, - 0x06a00510, 0x03800014, 0x072e4800, 0x07000012, - 0x038000bb, 0x0747f000, 0x05600800, 0x050f80ff, - 0x012fa809, 0x0249f001, 0x078100bb, 0x01012000, - 0x052e4c00, 0x07c00000, 0x070000eb, 0x0349f000, - 0x058180af, 0x05600800, 0x050f80ff, 0x012fa809, - 0x0448e001, 0x068100c1, 0x07c00000, 0x0079c101, - 0x07ffffff, 0x027a4b01, 0x03800000, 0x05600800, - 0x050f80ff, 0x012fa80a, 0x07600c00, 0x050f80ff, - 0x012fa821, 0x06780001, 0x07ffff00, 0x037c00ff, - 0x05000700, 0x078100dd, 0x06601804, 0x070030ff, - 0x050f80ff, 0x012fa809, 0x05002000, 0x050f8003, - 0x073fa00a, 0x06000001, 0x040fe001, 0x038600de, - 0x04600201, 0x050f80ff, 0x032fa00a, 0x07c00000, - 0x050fe02e, 0x008680e3, 0x0102e000, 0x0302f000, - 0x038000e7, 0x0760002e, 0x050f80ff, 0x032fa00a, - 0x0102e000, 0x07c00000, 0x022c0004, 0x056c041d, - 0x078100fc, 0x056c021d, 0x04810113, 0x056c081d, - 0x04810125, 0x076c061d, 0x0581013f, 0x0521d000, - 0x0202c013, 0x0202a013, 0x02020013, 0x0460021a, - 0x050f80ff, 0x053fa80a, 0x07000009, 0x03b600ac, - 0x0484801f, 0x0280003d, 0x040fe02a, 0x028600f2, - 0x06000013, 0x04001013, 0x0560102b, 0x050f80ff, - 0x032fa012, 0x06420029, 0x0660002a, 0x050f80ff, - 0x053fa809, 0x06000001, 0x050fe003, 0x00860110, - 0x01028003, 0x0660002a, 0x050f80ff, 0x053fa80a, - 0x07000009, 0x00800140, 0x00028013, 0x00027013, - 0x00800140, 0x040fe02a, 0x028600f1, 0x06420029, - 0x0660002a, 0x050f80ff, 0x053fa809, 0x06000001, - 0x050fe003, 0x01860122, 0x03026003, 0x0660002a, - 0x050f80ff, 0x053fa80a, 0x07000009, 0x00800140, - 0x02026013, 0x02025013, 0x00800140, 0x040fe02a, - 0x028600f1, 0x06420029, 0x0660002a, 0x050f80ff, - 0x053fa809, 0x06000001, 0x050fe003, 0x00860134, - 0x01022003, 0x0660002a, 0x050f80ff, 0x053fa80a, - 0x07000009, 0x01800136, 0x00022013, 0x00021013, - 0x0647f020, 0x007a0120, 0x04000101, 0x04a00285, - 0x0400802a, 0x05a004f5, 0x009480f1, 0x0521d005, - 0x028000f2, 0x038000fa, 0x0647f020, 0x06486020, - 0x06818145, 0x04a00285, 0x028000f1, 0x007a0120, - 0x04000101, 0x04a00285, 0x0400802a, 0x05a004f5, - 0x028000f1, 0x040fd02a, 0x052e4003, 0x00208010, - 0x05a004f5, 0x038000fa, 0x00018098, 0x07480018, - 0x06818161, 0x05481018, 0x0781815f, 0x05482018, - 0x0681815d, 0x07483018, 0x0681815b, 0x002fb004, - 0x00800162, 0x012fb003, 0x00800162, 0x002fb002, - 0x00800162, 0x002fb001, 0x00800162, 0x012fb000, - 0x0179fe78, 0x070000ff, 0x030190ff, 0x00017086, - 0x058b0166, 0x03385000, 0x03020000, 0x07780017, - 0x00430407, 0x078181ee, 0x046c0419, 0x048101a2, - 0x046c0219, 0x05810172, 0x07219000, 0x00800186, - 0x07219000, 0x07483017, 0x0481018c, 0x05482017, - 0x05810193, 0x0448b075, 0x06818186, 0x06601476, - 0x050f80ff, 0x073fa022, 0x0600003e, 0x06000080, - 0x05001081, 0x05002082, 0x06003083, 0x05004084, - 0x04601c76, 0x050f80ff, 0x022fa02a, 0x07219000, - 0x07780078, 0x07ffff00, 0x045a0419, 0x010780ff, - 0x0484801f, 0x0280003d, 0x040fe07f, 0x0086019b, - 0x05a001bb, 0x00920186, 0x040fe07f, 0x07a681bb, - 0x00800186, 0x0560107b, 0x050f80ff, 0x032fa009, - 0x0744f000, 0x0560107b, 0x050f80ff, 0x032fa00a, - 0x00800179, 0x052e400c, 0x040080fb, 0x046aa108, - 0x06009076, 0x04002075, 0x05a004fc, 0x00800186, - 0x06219001, 0x05482017, 0x058101af, 0x058b01a5, - 0x060ff086, 0x0349f0ff, 0x07818165, 0x07483017, - 0x058101ac, 0x050fd0ff, 0x040fe07f, 0x07a681bb, - 0x00800186, 0x05004084, 0x05a00205, 0x00920186, - 0x070ff07d, 0x0450047c, 0x056004ff, 0x050f80ff, - 0x032fa009, 0x070ff000, 0x00540479, 0x030790ff, - 0x01800193, 0x060ff079, 0x0054047a, 0x058201e7, - 0x058101e7, 0x070ff07d, 0x0450047c, 0x050f80ff, - 0x002fa819, 0x058b01c3, 0x02080001, 0x00081002, - 0x01082003, 0x048b01c7, 0x03385000, 0x03010000, - 0x02400019, 0x070ff003, 0x04500479, 0x030790ff, - 0x0340007e, 0x0642007f, 0x058101e7, 0x070ff07e, - 0x050f80ff, 0x032fa009, 0x050fe000, 0x028681e6, - 0x070ff07d, 0x056002ff, 0x050f80ff, 0x032fa009, - 0x0107d000, 0x018601e8, 0x0560087d, 0x050f80ff, - 0x032fa009, 0x0569fe00, 0x0550041b, 0x050f80ff, - 0x032fa009, 0x0107e000, 0x070ff07e, 0x018001d2, - 0x0307c000, 0x07c00000, 0x052e400c, 0x040080fb, - 0x046aa108, 0x06009076, 0x04002075, 0x018004fc, - 0x040fd076, 0x050fd017, 0x060ff086, 0x077800ff, - 0x07000060, 0x037c00ff, 0x07000060, 0x078181f0, - 0x07780078, 0x07ffff00, 0x045a0419, 0x010780ff, - 0x06601476, 0x050f80ff, 0x073fa022, 0x0600003e, - 0x052e400c, 0x040080fb, 0x066a8108, 0x06009076, - 0x04002075, 0x05a004fc, 0x02800029, 0x0240007f, - 0x0742007e, 0x050f807e, 0x032fa009, 0x050fe000, - 0x0286821f, 0x070ff07d, 0x055c047b, 0x05810214, - 0x0760007d, 0x050f80ff, 0x032fa009, 0x050fe000, - 0x03868214, 0x070ff07b, 0x0107d0ff, 0x0560087d, - 0x050f80ff, 0x032fa009, 0x03681e00, 0x0450041c, - 0x0107e0ff, 0x050f80ff, 0x032fa009, 0x050fe000, - 0x01860221, 0x0307c000, 0x07c00000, 0x040fd076, - 0x02800510, 0x010180c0, 0x0548e018, 0x0781823c, - 0x0748f018, 0x06818238, 0x03490018, 0x06818234, - 0x01491018, 0x07818230, 0x073c0000, 0x06000040, - 0x02200004, 0x0180023f, 0x073c0000, 0x06000020, - 0x03200003, 0x0180023f, 0x073c0000, 0x06000010, - 0x02200002, 0x0180023f, 0x073c0000, 0x06000008, - 0x02200001, 0x0180023f, 0x073c0000, 0x06000004, - 0x06000013, 0x050fb000, 0x040fe076, 0x00860258, - 0x046c0273, 0x04810268, 0x066c0073, 0x04810249, - 0x040fd076, 0x06a00510, 0x03800014, 0x040fd076, - 0x0080024c, 0x00452075, 0x00077013, 0x0647f075, - 0x06486075, 0x06818252, 0x05a0028b, 0x00800258, - 0x007a0175, 0x04000101, 0x05a0028b, 0x04008076, - 0x0245f008, 0x05a004f5, 0x07273000, 0x05600272, - 0x050f80ff, 0x053fa80a, 0x07000009, 0x0379ff78, - 0x070000ff, 0x02076013, 0x02075013, 0x0484801f, - 0x0280003d, 0x070fc0ff, 0x052e400c, 0x00208020, - 0x05a004f5, 0x00800261, 0x04600276, 0x050010ff, - 0x040f8001, 0x032fa009, 0x040f8001, 0x053fa80a, - 0x07000009, 0x070ff000, 0x0286827a, 0x06601276, - 0x050f80ff, 0x073fa009, 0x0700000c, 0x07601818, - 0x050f80ff, 0x053fa80a, 0x07000009, 0x0180027b, - 0x07a000de, 0x0448b075, 0x0581024b, 0x06000013, - 0x04001013, 0x0560107b, 0x050f80ff, 0x032fa012, - 0x0046b075, 0x03b600ac, 0x0080024c, 0x06000020, - 0x04001016, 0x0460082a, 0x050f80ff, 0x032fa012, - 0x07c00000, 0x06000075, 0x040010a2, 0x044b0801, - 0x060ff016, 0x065a0001, 0x04600876, 0x050f80ff, - 0x032fa012, 0x07c00000, 0x050fe022, 0x0186029a, - 0x0421d004, 0x0302a022, 0x04a002c1, 0x018002b1, - 0x040fe026, 0x008602b3, 0x0421d001, 0x0202a026, - 0x04a002c1, 0x0202c013, 0x00683e20, 0x070060ff, - 0x056c0206, 0x048102f4, 0x056c0406, 0x0781030a, - 0x076c0606, 0x06810379, 0x056c1606, 0x078182b1, - 0x04488020, 0x07810387, 0x040fd02a, 0x0521d000, - 0x0202a013, 0x02020013, 0x008002b3, 0x04a004ec, - 0x008002bf, 0x050fe028, 0x008602bf, 0x0302a028, - 0x0421d002, 0x04a002c1, 0x008002c8, 0x050fe022, - 0x008602bf, 0x0421d004, 0x0302a022, 0x04a002c1, - 0x04a004ec, 0x05848030, 0x0280003d, 0x0460082a, - 0x050f80ff, 0x022fa031, 0x03020000, 0x0002b004, - 0x01018005, 0x07c00000, 0x0400702a, 0x06a003ba, + 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, 0x068182d6, 0x06006013, 0x018002dd, - 0x02400010, 0x048102d6, 0x06006010, 0x0460322a, - 0x050f80ff, 0x073fa00a, 0x07000003, 0x050f801e, - 0x032fa03a, 0x063aa020, 0x06000002, 0x013e4000, - 0x07000030, 0x009802e3, 0x070ff0f6, 0x036830ff, - 0x078182e4, 0x070f001e, 0x0560102b, 0x050f10ff, - 0x063f3c08, 0x0600000d, 0x013e4000, 0x06000020, - 0x040f801a, 0x0320000a, 0x022017d0, 0x032fa012, - 0x0202c013, 0x008002bf, 0x04007013, 0x06a003ba, - 0x007a0101, 0x07050000, 0x07303000, 0x07008890, - 0x074d0005, 0x06006013, 0x050f801e, 0x032fa03a, - 0x05601a2b, 0x050f80ff, 0x022fa019, 0x04001002, - 0x04002013, 0x040f801f, 0x022fa01a, 0x073aa00c, - 0x06000002, 0x07300c03, 0x0600000d, 0x028003a7, - 0x04007013, 0x06a003ba, 0x007a0101, 0x03070000, - 0x0660282a, 0x050f80ff, 0x073fa009, 0x06000004, - 0x02499008, 0x07810317, 0x07303000, 0x07008890, - 0x02800319, 0x07303000, 0x04008980, 0x05007003, - 0x074d0005, 0x06006013, 0x050f801e, 0x032fa03a, - 0x0760142b, 0x050f80ff, 0x032fa021, 0x064b0002, - 0x02499008, 0x06810325, 0x0644c002, 0x054b0400, - 0x050040ff, 0x06698104, 0x0581833a, 0x06000013, - 0x04001013, 0x04780102, 0x06000010, 0x06003013, - 0x04004013, 0x06005013, 0x06006013, 0x04007013, - 0x00644015, 0x07820336, 0x04448002, 0x02205008, - 0x040f801f, 0x032fa042, 0x04008015, 0x03800371, - 0x046c8004, 0x05818348, 0x01208018, 0x06780002, - 0x07000003, 0x0581834b, 0x06003001, 0x06000013, - 0x04001013, 0x04004013, 0x06005013, 0x040f801f, - 0x022fa032, 0x03800371, 0x040fd02a, 0x06a00510, - 0x03800014, 0x04488002, 0x07810350, 0x070ff003, - 0x04500408, 0x050080ff, 0x06489002, 0x06810357, - 0x0379ff00, 0x070000ff, 0x070ff000, 0x04500408, - 0x050080ff, 0x07005003, 0x05004000, 0x06003001, - 0x06000013, 0x04001013, 0x040f801f, 0x022fa032, - 0x05601c2b, 0x050f80ff, 0x022fa031, 0x06600c1f, - 0x050f80ff, 0x022fa032, 0x02680608, 0x07810371, - 0x016408ff, 0x057dfeff, 0x07ffffff, 0x034000ff, - 0x045a0407, 0x070000ff, 0x0760061e, 0x050f80ff, - 0x032fa00a, 0x06600908, 0x0669f908, 0x027a0008, - 0x06000020, 0x070aa0ff, 0x014a20ff, 0x037a00ff, - 0x060000dc, 0x070000ff, 0x028003a7, 0x04007013, - 0x06a003ba, 0x007a0101, 0x07030000, 0x07303000, - 0x07008190, 0x06006013, 0x050f801e, 0x032fa03a, - 0x073aa000, 0x06000002, 0x07300c00, 0x07000005, - 0x028003a7, 0x04007013, 0x06a003ba, 0x007a0101, - 0x07810000, 0x07303000, 0x07000090, 0x06006013, - 0x06600c2a, 0x050f80ff, 0x053fa809, 0x07000003, - 0x04780107, 0x07ffff00, 0x007c0107, 0x07000500, - 0x0581839a, 0x07303000, 0x05000890, 0x074d0005, - 0x0660282a, 0x050f80ff, 0x053fa809, 0x07000003, - 0x0049d007, 0x068103a1, 0x02206001, 0x050f801e, - 0x032fa03a, 0x073aa000, 0x06000002, 0x07300c00, - 0x07000005, 0x013e4000, 0x07000030, 0x039803a9, - 0x070ff0f6, 0x036830ff, 0x058183aa, 0x070f001e, - 0x040f101f, 0x070f3000, 0x013e4000, 0x06000020, - 0x040f801a, 0x0320000a, 0x022017d0, 0x032fa012, - 0x008002bf, 0x03200000, 0x06006076, 0x028003bc, - 0x03200011, 0x0600602a, 0x05a00441, 0x05600406, - 0x050f80ff, 0x053fa809, 0x06000002, 0x07c00000, - 0x0207602f, 0x04600876, 0x050f80ff, 0x022fa031, - 0x03075000, 0x0007b004, 0x01018005, 0x06600076, - 0x050020ff, 0x050f80ff, 0x012fa809, 0x0202f001, - 0x008683d0, 0x0002e013, 0x040f8002, 0x053fa80a, - 0x07000009, 0x06273001, 0x0448b075, 0x048183da, - 0x04602076, 0x050f80ff, 0x053fa811, 0x0700003c, - 0x0179fe78, 0x070000ff, 0x030190ff, 0x018683e2, - 0x07a003f6, 0x00078019, 0x039203f5, 0x0180043a, - 0x040fd076, 0x040fd019, 0x04600276, 0x050020ff, - 0x050f80ff, 0x032fa009, 0x040f8002, 0x053fa80a, - 0x07000009, 0x050fe000, 0x008683f2, 0x07601818, - 0x050f80ff, 0x053fa80a, 0x07000009, 0x038003f3, - 0x07a000de, 0x07273000, 0x02076013, 0x0280003d, - 0x078b03f6, 0x03385000, 0x07030000, 0x05600818, - 0x050f80ff, 0x032fa009, 0x054b0400, 0x0308a0ff, - 0x0179fe00, 0x070000ff, 0x010880ff, 0x0448b075, - 0x04810410, 0x0760147b, 0x050f80ff, 0x002fa819, - 0x064b0001, 0x02080002, 0x01081003, 0x00082001, - 0x02083001, 0x02079001, 0x0207a001, 0x00084013, - 0x0207f013, 0x00800432, 0x06485075, 0x05810428, - 0x02465075, 0x06601476, 0x050f80ff, 0x073fa021, - 0x0600003e, 0x070ff07d, 0x0450047c, 0x050f80ff, - 0x002fa819, 0x058b041b, 0x02080001, 0x00081002, - 0x01082003, 0x03079003, 0x0208307a, 0x0340007e, - 0x0642007f, 0x0581042d, 0x070ff07e, 0x05a001d2, - 0x0392842d, 0x01800439, 0x058b0428, 0x06601476, - 0x050f80ff, 0x073fa041, 0x0600003e, 0x06602476, - 0x050f80ff, 0x073fa009, 0x06000007, 0x0008400e, - 0x048b0432, 0x03385000, 0x03010000, 0x06219001, - 0x040fe07f, 0x01860439, 0x018001bb, 0x07c00000, - 0x00683e75, 0x0581043f, 0x0448d075, 0x05810465, - 0x01800493, 0x05a004f0, 0x038003f5, 0x0297844c, - 0x07602418, 0x050f80ff, 0x012fa809, 0x06780001, - 0x070000ff, 0x075a0000, 0x070ff014, 0x0569feff, - 0x054b08ff, 0x075a0000, 0x05600418, 0x050f80ff, - 0x012fa809, 0x040fe007, 0x03868453, 0x01204000, - 0x00800461, 0x00700101, 0x03010000, 0x06780001, - 0x07ff0000, 0x076c00ff, 0x0681845b, 0x00700101, - 0x03010000, 0x05600418, 0x050f80ff, 0x012fa80a, - 0x06780001, 0x07ff0000, 0x050040ff, 0x0279ff01, - 0x0700ffff, 0x05002014, 0x07c00000, 0x04007076, - 0x0448b075, 0x0481047f, 0x03200011, 0x06006076, - 0x06a003bc, 0x007a0101, 0x07060000, 0x07303000, - 0x07008290, 0x07600018, 0x050f80ff, 0x053fa809, - 0x07000003, 0x0448e007, 0x07818477, 0x06006013, - 0x0180048e, 0x02400010, 0x05810477, 0x06006010, - 0x04603276, 0x050f80ff, 0x073fa00a, 0x07000003, - 0x0180048e, 0x04602a76, 0x050f80ff, 0x032fa009, - 0x060ff07a, 0x05500400, 0x070000ff, 0x04602a76, - 0x050f80ff, 0x032fa00a, 0x07a003b7, 0x007a0101, - 0x03010000, 0x06303008, 0x05008000, 0x0600600e, - 0x050f8074, 0x032fa03a, 0x053079a0, 0x0700000c, - 0x008004d3, 0x00683e75, 0x076c0aff, 0x058104b2, - 0x04007013, 0x03200011, 0x06006076, 0x06a003bc, - 0x007a0101, 0x03070000, 0x06602876, 0x050f80ff, - 0x053fa809, 0x06000001, 0x03499003, 0x048104a7, - 0x07303000, 0x07008890, 0x053079a0, 0x0700000c, - 0x008004ab, 0x07303000, 0x04008980, 0x04307920, - 0x0700000c, 0x074d0005, 0x06006013, 0x050f8074, - 0x032fa03a, 0x04307920, 0x0700000c, 0x008004d3, + 0x0448e007, 0x068184a1, 0x06006013, 0x018004b8, + 0x02400010, 0x048104a1, 0x06006010, 0x04603276, + 0x050f80ff, 0x073fa00a, 0x07000003, 0x018004b8, 0x04602a76, 0x050f80ff, 0x032fa009, 0x060ff07a, 0x05500400, 0x070000ff, 0x04602a76, 0x050f80ff, - 0x032fa00a, 0x04007076, 0x07a003b7, 0x007a0101, - 0x03010000, 0x06303008, 0x07008800, 0x074d0005, - 0x06600a76, 0x050f80ff, 0x073fa009, 0x07000003, - 0x054b0406, 0x045a0404, 0x050040ff, 0x0600600e, - 0x050f8074, 0x032fa03a, 0x0648c075, 0x058104d1, - 0x06307d20, 0x0700000c, 0x008004d3, 0x04307920, - 0x0700000c, 0x013e4000, 0x07000030, 0x009804d5, - 0x070ff0f6, 0x074850ff, 0x068184d6, 0x050f2074, - 0x060a0007, 0x040070fb, 0x046a7007, 0x050f40ff, - 0x013e4000, 0x06000020, 0x0678007a, 0x07fff000, - 0x068184e6, 0x0320000a, 0x022017d0, 0x008004e9, - 0x0320000a, 0x06301b58, 0x06000001, 0x050f8072, - 0x032fa012, 0x038003f5, 0x01208060, 0x0600902a, - 0x04002020, 0x018004fc, 0x040080fb, 0x066ae108, - 0x06009076, 0x04002075, 0x018004fc, 0x03201100, - 0x078484fa, 0x06420001, 0x078184f6, 0x02800513, - 0x020e0008, 0x07c00000, 0x050fd009, 0x040fd008, - 0x03201100, 0x05848503, 0x06420001, 0x078184ff, - 0x02800513, 0x007a0102, 0x04000101, 0x05600809, - 0x050f80ff, 0x073fa00a, 0x06000001, 0x020e0008, - 0x0684050d, 0x030e0009, 0x07c00000, 0x01011009, - 0x052e4300, 0x07c00000, 0x052e400f, 0x01208090, - 0x018004f5, 0x070fc0ff, 0x040f8013, 0x032fa009, - 0x02800516, 0x15416ea9, 0xffef0b01 + 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 = 0x000014ff ; +uint32_t fw2400_length02 = 0x0000165e ; #else -uint32_t risc_code_length02 = 0x000014ff ; +uint32_t risc_code_length02 = 0x0000165e ; #endif -- cgit v1.2.3-59-g8ed1b From 72df0ebf95561694c06adca62e590e37ec549579 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 10 Mar 2006 07:18:22 -0700 Subject: [SCSI] Missing names from SPI3, SPI4 and SPI5 Add several missing messages from SPI3, SPI4 and SPI5: - Terminate Process - Continue Task - Target Transfer Disable - Clear ACA - LUN Reset - ACA - QAS Request Rename some older commands to their SPI5 names: - Command Complete -> Task Complete - Abort -> Abort Task Set - Bus device Reset -> Target Reset - Clear Queue -> Clear Task Set Change spi_print_msg() to always consume one byte, even if we don't recognise it. That allows drivers to call it in a loop to print all messages. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 0b29ee9989a4..4855d1602d6b 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -1089,17 +1089,19 @@ EXPORT_SYMBOL_GPL(spi_populate_ppr_msg); #ifdef CONFIG_SCSI_CONSTANTS static const char * const one_byte_msgs[] = { -/* 0x00 */ "Command Complete", NULL, "Save Pointers", +/* 0x00 */ "Task Complete", NULL /* Extended Message */, "Save Pointers", /* 0x03 */ "Restore Pointers", "Disconnect", "Initiator Error", -/* 0x06 */ "Abort", "Message Reject", "Nop", "Message Parity Error", +/* 0x06 */ "Abort Task Set", "Message Reject", "Nop", "Message Parity Error", /* 0x0a */ "Linked Command Complete", "Linked Command Complete w/flag", -/* 0x0c */ "Bus device reset", "Abort Tag", "Clear Queue", -/* 0x0f */ "Initiate Recovery", "Release Recovery" +/* 0x0c */ "Target Reset", "Abort Task", "Clear Task Set", +/* 0x0f */ "Initiate Recovery", "Release Recovery", +/* 0x11 */ "Terminate Process", "Continue Task", "Target Transfer Disable", +/* 0x14 */ NULL, NULL, "Clear ACA", "LUN Reset" }; static const char * const two_byte_msgs[] = { /* 0x20 */ "Simple Queue Tag", "Head of Queue Tag", "Ordered Queue Tag", -/* 0x23 */ "Ignore Wide Residue" +/* 0x23 */ "Ignore Wide Residue", "ACA" }; static const char * const extended_msgs[] = { @@ -1131,7 +1133,7 @@ static void print_ptr(const unsigned char *msg, int msb, const char *desc) int spi_print_msg(const unsigned char *msg) { - int len = 0, i; + int len = 1, i; if (msg[0] == EXTENDED_MESSAGE) { len = 2 + msg[1]; if (len == 2) @@ -1168,14 +1170,14 @@ int spi_print_msg(const unsigned char *msg) (msg[0] & 0x40) ? "" : "not ", (msg[0] & 0x20) ? "target routine" : "lun", msg[0] & 0x7); - len = 1; /* Normal One byte */ } else if (msg[0] < 0x1f) { - if (msg[0] < ARRAY_SIZE(one_byte_msgs)) + if (msg[0] < ARRAY_SIZE(one_byte_msgs) && one_byte_msgs[msg[0]]) printk("%s ", one_byte_msgs[msg[0]]); else printk("reserved (%02x) ", msg[0]); - len = 1; + } else if (msg[0] == 0x55) { + printk("QAS Request "); /* Two byte */ } else if (msg[0] <= 0x2f) { if ((msg[0] - 0x20) < ARRAY_SIZE(two_byte_msgs)) @@ -1195,7 +1197,7 @@ EXPORT_SYMBOL(spi_print_msg); int spi_print_msg(const unsigned char *msg) { - int len = 0, i; + int len = 1, i; if (msg[0] == EXTENDED_MESSAGE) { len = 2 + msg[1]; @@ -1206,11 +1208,9 @@ int spi_print_msg(const unsigned char *msg) /* Identify */ } else if (msg[0] & 0x80) { printk("%02x ", msg[0]); - len = 1; /* Normal One byte */ - } else if (msg[0] < 0x1f) { + } else if ((msg[0] < 0x1f) || (msg == 0x55)) { printk("%02x ", msg[0]); - len = 1; /* Two byte */ } else if (msg[0] <= 0x2f) { printk("%02x %02x", msg[0], msg[1]); -- cgit v1.2.3-59-g8ed1b From 8800727ae8a20146981a9531ac833cb889666247 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 10 Mar 2006 23:24:08 +0100 Subject: [SCSI] NCR_D700: fix a NULL dereference The Coverity checker spotted this NULL dereference. Signed-off-by: Adrian Bunk Signed-off-by: James Bottomley --- drivers/scsi/NCR_D700.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c index e993a7ba276f..577e63499778 100644 --- a/drivers/scsi/NCR_D700.c +++ b/drivers/scsi/NCR_D700.c @@ -218,7 +218,7 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq, return 0; detect_failed: - release_region(host->base, 64); + release_region(region, 64); region_failed: kfree(hostdata); -- cgit v1.2.3-59-g8ed1b From c3c026ba5a16867af47578ab2030ef51f9080084 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 10 Mar 2006 23:24:21 +0100 Subject: [SCSI] dmx3191d: fix a NULL pointer dereference This patch fixes a NULL pointer dereference spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: James Bottomley --- drivers/scsi/dmx3191d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 7905b904e01d..38e4010eff96 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -116,7 +116,7 @@ static int __devinit dmx3191d_probe_one(struct pci_dev *pdev, out_free_irq: free_irq(shost->irq, shost); out_release_region: - release_region(shost->io_port, DMX3191D_REGION_LEN); + release_region(io, DMX3191D_REGION_LEN); out_disable_device: pci_disable_device(pdev); out: -- cgit v1.2.3-59-g8ed1b From a6becb084d4beb0b0c83651541f5b53f6da01e36 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 10 Mar 2006 23:24:47 +0100 Subject: [SCSI] ibmmca: fix a NULL pointer dereference The variable was dereferenced only if it was NULL (sic)... Spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: James Bottomley --- drivers/scsi/ibmmca.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index b60c1b9270f1..3a8462e8d063 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -2412,8 +2412,7 @@ static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, spin_lock_irqsave(hosts[i]->host_lock, flags); /* Check it */ host_index = i; if (!shpnt) { - len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter for host number %d\n", - shpnt->host_no); + len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter"); return len; } max_pun = subsystem_maxid(host_index); -- cgit v1.2.3-59-g8ed1b From a1d4f73a00958162f91311396d37080f5e9b9ef1 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 10 Mar 2006 23:25:00 +0100 Subject: [SCSI] sim710: fix a NULL pointer dereference This patch fixes a NULL pointer dereference spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: James Bottomley --- drivers/scsi/sim710.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c index 9171788348c4..3274ab76c8d3 100644 --- a/drivers/scsi/sim710.c +++ b/drivers/scsi/sim710.c @@ -146,7 +146,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr, out_put_host: scsi_host_put(host); out_release: - release_region(host->base, 64); + release_region(base_addr, 64); out_free: kfree(hostdata); out: -- cgit v1.2.3-59-g8ed1b From 597705aa7fbf3e600283f4a870fb700385eacb13 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 12 Mar 2006 09:54:19 -0600 Subject: [SCSI] fix minor problem in spi transport message functions The check for a one byte message should be msg[0] == 0x55 not msg == 0x55 Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 4855d1602d6b..780aaedcbce9 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -1209,7 +1209,7 @@ int spi_print_msg(const unsigned char *msg) } else if (msg[0] & 0x80) { printk("%02x ", msg[0]); /* Normal One byte */ - } else if ((msg[0] < 0x1f) || (msg == 0x55)) { + } else if ((msg[0] < 0x1f) || (msg[0] == 0x55)) { printk("%02x ", msg[0]); /* Two byte */ } else if (msg[0] <= 0x2f) { -- cgit v1.2.3-59-g8ed1b From ce313db240862d809c736c5b1dfc759817fc7ca9 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 12 Mar 2006 10:02:15 -0600 Subject: [SCSI] mptscsih: remove unused page 1 setting function It was actually rendered unused by the move to the spi transport class, but never taken out. Signed-off-by: James Bottomley --- drivers/message/fusion/mptscsih.c | 44 --------------------------------------- 1 file changed, 44 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index ff83e21e1000..a2183103b8c3 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2786,50 +2786,6 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, /* * SCSI Config Page functionality ... */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags - * based on width, factor and offset parameters. - * @width: bus width - * @factor: sync factor - * @offset: sync offset - * @requestedPtr: pointer to requested values (updated) - * @configurationPtr: pointer to configuration values (updated) - * @flags: flags to block WDTR or SDTR negotiation - * - * Return: None. - * - * Remark: Called by writeSDP1 and _dv_params - */ -static void -mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags) -{ - u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE; - u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC; - - *configurationPtr = 0; - *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0; - *requestedPtr |= (offset << 16) | (factor << 8); - - if (width && offset && !nowide && !nosync) { - if (factor < MPT_ULTRA160) { - *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT); - if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0) - *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS; - if (flags & MPT_TAPE_NEGO_IDP) - *requestedPtr |= 0x08000000; - } else if (factor < MPT_ULTRA2) { - *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT; - } - } - - if (nowide) - *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED; - - if (nosync) - *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED; - - return; -} /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* mptscsih_writeIOCPage4 - write IOC Page 4 -- cgit v1.2.3-59-g8ed1b From 2044470cccec1bfe6bb819027975df302ff43bf8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 13 Mar 2006 01:57:01 +0900 Subject: [PATCH] libata: fix class handling in ata_bus_probe() ata_bus_probe() didn't set classes[] properly for port disabled case of ->phy_reset() compatibility path. This patch moves classes[] initialization and normalization out of ->probe_reset block such that it applies to both ->probe_reset and ->phy_reset paths. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 42d43b55fb8f..c17df3f22fd1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1344,32 +1344,30 @@ static int ata_bus_probe(struct ata_port *ap) ata_port_probe(ap); - /* reset */ - if (ap->ops->probe_reset) { - for (i = 0; i < ATA_MAX_DEVICES; i++) - classes[i] = ATA_DEV_UNKNOWN; + /* reset and determine device classes */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_UNKNOWN; + 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); return rc; } - - for (i = 0; i < ATA_MAX_DEVICES; i++) - if (classes[i] == ATA_DEV_UNKNOWN) - classes[i] = ATA_DEV_NONE; } else { ap->ops->phy_reset(ap); - for (i = 0; i < ATA_MAX_DEVICES; i++) { - if (!(ap->flags & ATA_FLAG_PORT_DISABLED)) + if (!(ap->flags & ATA_FLAG_PORT_DISABLED)) + for (i = 0; i < ATA_MAX_DEVICES; i++) classes[i] = ap->device[i].class; - else - ap->device[i].class = ATA_DEV_UNKNOWN; - } + ata_port_probe(ap); } + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (classes[i] == ATA_DEV_UNKNOWN) + classes[i] = ATA_DEV_NONE; + /* read IDENTIFY page and configure devices */ for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; -- cgit v1.2.3-59-g8ed1b From fb21f0d0ec7e31cc814165e1a9d2662d9c9dd980 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 12 Mar 2006 12:34:35 +0900 Subject: [PATCH] libata: check Word 88 validity in ata_id_xfer_mask() Check bit 2 of Word 53 for Word 88 validity before using Word 88 to determine UDMA mask. Note that the original xfer mask implementation using ata_get_mode_mask() didn't consider bit 2 of Word 53. This patch introduces different (correct) behavior. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c17df3f22fd1..439b6db13802 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -819,7 +819,10 @@ static unsigned int ata_id_xfermask(const u16 *id) } mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07; - udma_mask = id[ATA_ID_UDMA_MODES] & 0xff; + + udma_mask = 0; + if (id[ATA_ID_FIELD_VALID] & (1 << 2)) + udma_mask = id[ATA_ID_UDMA_MODES] & 0xff; return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask); } -- cgit v1.2.3-59-g8ed1b From c829c394165f981d49f05a9be228404d7a9398d4 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 13 Mar 2006 08:28:57 -0500 Subject: [SCSI] FC transport : Avoid device offline cases by stalling aborts until device unblocked This moves the eh_timed_out functionality from the scsi_host_template to the transport_template. Given that this is now a transport function, the EH_RESET_TIMER case no longer caps the timer reschedulings. The transport guarantees that this is not an infinite condition. Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 9 +++------ drivers/scsi/scsi_transport_fc.c | 37 +++++++++++++++++++++++++++++++++++++ include/scsi/scsi_host.h | 14 -------------- include/scsi/scsi_transport.h | 11 +++++++++++ 4 files changed, 51 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 5cc97b721661..9cf020622134 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -163,16 +164,12 @@ void scsi_times_out(struct scsi_cmnd *scmd) { scsi_log_completion(scmd, TIMEOUT_ERROR); - if (scmd->device->host->hostt->eh_timed_out) - switch (scmd->device->host->hostt->eh_timed_out(scmd)) { + if (scmd->device->host->transportt->eh_timed_out) + switch (scmd->device->host->transportt->eh_timed_out(scmd)) { case EH_HANDLED: __scsi_done(scmd); return; case EH_RESET_TIMER: - /* This allows a single retry even of a command - * with allowed == 0 */ - if (scmd->retries++ > scmd->allowed) - break; scsi_add_timer(scmd, scmd->timeout_per_command, scsi_times_out); return; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 56012b2694d2..3c3baa9f5f28 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "scsi_priv.h" /* @@ -1090,6 +1091,40 @@ static int fc_rport_match(struct attribute_container *cont, } +/** + * fc_timed_out - FC Transport I/O timeout intercept handler + * + * @scmd: The SCSI command which timed out + * + * This routine protects against error handlers getting invoked while a + * rport is in a blocked state, typically due to a temporarily loss of + * connectivity. If the error handlers are allowed to proceed, requests + * to abort i/o, reset the target, etc will likely fail as there is no way + * to communicate with the device to perform the requested function. These + * failures may result in the midlayer taking the device offline, requiring + * manual intervention to restore operation. + * + * This routine, called whenever an i/o times out, validates the state of + * the underlying rport. If the rport is blocked, it returns + * EH_RESET_TIMER, which will continue to reschedule the timeout. + * Eventually, either the device will return, or devloss_tmo will fire, + * and when the timeout then fires, it will be handled normally. + * If the rport is not blocked, normal error handling continues. + * + * Notes: + * This routine assumes no locks are held on entry. + **/ +static enum scsi_eh_timer_return +fc_timed_out(struct scsi_cmnd *scmd) +{ + struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device)); + + if (rport->port_state == FC_PORTSTATE_BLOCKED) + return EH_RESET_TIMER; + + return EH_NOT_HANDLED; +} + /* * Must be called with shost->host_lock held */ @@ -1146,6 +1181,8 @@ fc_attach_transport(struct fc_function_template *ft) /* Transport uses the shost workq for scsi scanning */ i->t.create_work_queue = 1; + i->t.eh_timed_out = fc_timed_out; + i->t.user_scan = fc_user_scan; /* diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 827992949c4b..a6cf3e535c0b 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -146,20 +146,6 @@ struct scsi_host_template { int (* eh_bus_reset_handler)(struct scsi_cmnd *); int (* eh_host_reset_handler)(struct scsi_cmnd *); - /* - * This is an optional routine to notify the host that the scsi - * timer just fired. The returns tell the timer routine what to - * do about this: - * - * EH_HANDLED: I fixed the error, please complete the command - * EH_RESET_TIMER: I need more time, reset the timer and - * begin counting again - * EH_NOT_HANDLED Begin normal error recovery - * - * Status: OPTIONAL - */ - enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); - /* * Before the mid layer attempts to scan for a new device where none * currently exists, it will call this entry in your driver. Should diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index e7b1054adf86..b3657f111937 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -48,6 +48,17 @@ struct scsi_transport_template { * True if the transport wants to use a host-based work-queue */ unsigned int create_work_queue : 1; + + /* + * This is an optional routine that allows the transport to become + * involved when a scsi io timer fires. The return value tells the + * timer routine how to finish the io timeout handling: + * EH_HANDLED: I fixed the error, please complete the command + * EH_RESET_TIMER: I need more time, reset the timer and + * begin counting again + * EH_NOT_HANDLED Begin normal error recovery + */ + enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); }; #define transport_class_to_shost(tc) \ -- cgit v1.2.3-59-g8ed1b From 3cb4f09fc2e98bbf26f8c900a94bf3910cd4d823 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 13 Mar 2006 21:20:40 -0800 Subject: [PATCH] mtd_dataflash, fix block vs page erase Fix a bug in the block-erase optimization for Dataflash; it was using block erase even for smaller segments that need page erase. That wouldn't matter for JFFS2, which never erases less than one block (sometimes several blocks), but for other callers it might. Signed-off-by: David Brownell Acked-by: David Woodhouse Acked-by: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/devices/mtd_dataflash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 155737e7483f..a19480d07888 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -178,7 +178,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) * we're at a block boundary and need to erase the whole block. */ pageaddr = instr->addr / priv->page_size; - do_block = (pageaddr & 0x7) == 0 && instr->len <= blocksize; + do_block = (pageaddr & 0x7) == 0 && instr->len >= blocksize; pageaddr = pageaddr << priv->page_offset; command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; -- cgit v1.2.3-59-g8ed1b From 6acaba8e22bb355409e06d9e7ce4e7bef1bcaa04 Mon Sep 17 00:00:00 2001 From: Michael Hunold Date: Mon, 13 Mar 2006 21:20:41 -0800 Subject: [PATCH] Restore tuning capabilities in V4L2 MXB driver The behaviour of the all-in-one Video4Linux tuner driver apparently changed. It now wants to know the tv standard, otherwise it refuses to tune. Restore tuning functionality in my driver for the "Multimedia eXtension Board". The all-in-one tuner driver apparently changed its behaviour. Signed-off-by: Michael Hunold Cc: Mauro Carvalho Chehab Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/mxb.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 8416ceff524b..41715cacf926 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -1,7 +1,7 @@ /* mxb - v4l2 driver for the Multimedia eXtension Board - Copyright (C) 1998-2003 Michael Hunold + Copyright (C) 1998-2006 Michael Hunold Visit http://www.mihu.de/linux/saa7146/mxb/ for further details about this card. @@ -327,6 +327,7 @@ static int mxb_init_done(struct saa7146_dev* dev) struct video_decoder_init init; struct i2c_msg msg; struct tuner_setup tun_setup; + v4l2_std_id std = V4L2_STD_PAL_BG; int i = 0, err = 0; struct tea6415c_multiplex vm; @@ -361,6 +362,9 @@ static int mxb_init_done(struct saa7146_dev* dev) mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq); + /* set a default video standard */ + mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); + /* mute audio on tea6420s */ mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]); mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]); @@ -921,17 +925,21 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) int one = 1; if(V4L2_STD_PAL_I == std->id ) { + v4l2_std_id std = V4L2_STD_PAL_I; DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* unset the 7111 gpio register -- I don't know what this does exactly */ mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero); + mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); } else { + v4l2_std_id std = V4L2_STD_PAL_BG; DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* set the 7111 gpio register -- I don't know what this does exactly */ mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one); + mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); } return 0; } -- cgit v1.2.3-59-g8ed1b From 63e1fd41c7127650d355e7db7dd92890edf5523b Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 13 Mar 2006 21:20:42 -0800 Subject: [PATCH] macintosh: correct AC Power info in /proc/pmu/info Report AC Power present in /proc/pmu/info if there is no battery. Signed-off-by: Olaf Hering Signed-off-by: Benjamin Herrenschmidt , Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/macintosh/via-pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 6eb93e45fcd3..4a478eb0e27d 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -825,7 +825,7 @@ proc_get_info(char *page, char **start, off_t off, p += sprintf(p, "PMU driver version : %d\n", PMU_DRIVER_VERSION); p += sprintf(p, "PMU firmware version : %02x\n", pmu_version); p += sprintf(p, "AC Power : %d\n", - ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0)); + ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0) || pmu_battery_count == 0); p += sprintf(p, "Battery count : %d\n", pmu_battery_count); return p - page; -- cgit v1.2.3-59-g8ed1b From ceb2ca9cb0bfd885127fa9a2c27127b3fe1c8f28 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Mon, 13 Mar 2006 21:20:50 -0800 Subject: [PATCH] EDAC: disable sysfs interface - Disable the EDAC sysfs code. The sysfs interface that EDAC presents to user space needs more thought, and is likely to change substantially. Therefore disable it for now so users don't start depending on it in its current form. - Disable the default behavior of calling panic() when an uncorrectible error is detected (since for now, there is no sysfs interface that allows the user to configure this behavior). Signed-off-by: David S. Peterson Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/edac_mc.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 262e44544dc8..9c205274c1cb 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -38,6 +38,12 @@ #define EDAC_MC_VERSION "edac_mc Ver: 2.0.0 " __DATE__ +/* For now, disable the EDAC sysfs code. The sysfs interface that EDAC + * presents to user space needs more thought, and is likely to change + * substantially. + */ +#define DISABLE_EDAC_SYSFS + #ifdef CONFIG_EDAC_DEBUG /* Values of 0 to 4 will generate output */ int edac_debug_level = 1; @@ -47,7 +53,7 @@ EXPORT_SYMBOL(edac_debug_level); /* EDAC Controls, setable by module parameter, and sysfs */ static int log_ue = 1; static int log_ce = 1; -static int panic_on_ue = 1; +static int panic_on_ue; static int poll_msec = 1000; static int check_pci_parity = 0; /* default YES check PCI parity */ @@ -77,6 +83,8 @@ static int pci_whitelist_count ; /* START sysfs data and methods */ +#ifndef DISABLE_EDAC_SYSFS + static const char *mem_types[] = { [MEM_EMPTY] = "Empty", [MEM_RESERVED] = "Reserved", @@ -241,6 +249,7 @@ static struct kobj_type ktype_memctrl = { .default_attrs = (struct attribute **) memctrl_attr, }; +#endif /* DISABLE_EDAC_SYSFS */ /* Initialize the main sysfs entries for edac: * /sys/devices/system/edac @@ -251,6 +260,11 @@ static struct kobj_type ktype_memctrl = { * !0 FAILURE */ static int edac_sysfs_memctrl_setup(void) +#ifdef DISABLE_EDAC_SYSFS +{ + return 0; +} +#else { int err=0; @@ -283,6 +297,7 @@ static int edac_sysfs_memctrl_setup(void) return err; } +#endif /* DISABLE_EDAC_SYSFS */ /* * MC teardown: @@ -290,6 +305,7 @@ static int edac_sysfs_memctrl_setup(void) */ static void edac_sysfs_memctrl_teardown(void) { +#ifndef DISABLE_EDAC_SYSFS debugf0("MC: " __FILE__ ": %s()\n", __func__); /* Unregister the MC's kobject */ @@ -300,8 +316,11 @@ static void edac_sysfs_memctrl_teardown(void) /* Unregister the 'edac' object */ sysdev_class_unregister(&edac_class); +#endif /* DISABLE_EDAC_SYSFS */ } +#ifndef DISABLE_EDAC_SYSFS + /* * /sys/devices/system/edac/pci; * data structures and methods @@ -554,11 +573,18 @@ static struct kobj_type ktype_edac_pci = { .default_attrs = (struct attribute **) edac_pci_attr, }; +#endif /* DISABLE_EDAC_SYSFS */ + /** * edac_sysfs_pci_setup() * */ static int edac_sysfs_pci_setup(void) +#ifdef DISABLE_EDAC_SYSFS +{ + return 0; +} +#else { int err; @@ -582,16 +608,20 @@ static int edac_sysfs_pci_setup(void) } return err; } - +#endif /* DISABLE_EDAC_SYSFS */ static void edac_sysfs_pci_teardown(void) { +#ifndef DISABLE_EDAC_SYSFS debugf0("MC: " __FILE__ ": %s()\n", __func__); kobject_unregister(&edac_pci_kobj); kobject_put(&edac_pci_kobj); +#endif } +#ifndef DISABLE_EDAC_SYSFS + /* EDAC sysfs CSROW data structures and methods */ /* Set of more detailed csrow attribute show/store functions */ @@ -1045,6 +1075,8 @@ static struct kobj_type ktype_mci = { .default_attrs = (struct attribute **) mci_attr, }; +#endif /* DISABLE_EDAC_SYSFS */ + #define EDAC_DEVICE_SYMLINK "device" /* @@ -1056,6 +1088,11 @@ static struct kobj_type ktype_mci = { * !0 Failure */ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) +#ifdef DISABLE_EDAC_SYSFS +{ + return 0; +} +#else { int i; int err; @@ -1124,12 +1161,14 @@ fail: return err; } +#endif /* DISABLE_EDAC_SYSFS */ /* * remove a Memory Controller instance */ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) { +#ifndef DISABLE_EDAC_SYSFS int i; debugf0("MC: " __FILE__ ": %s()\n", __func__); @@ -1146,6 +1185,7 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) kobject_unregister(&mci->edac_mci_kobj); kobject_put(&mci->edac_mci_kobj); +#endif /* DISABLE_EDAC_SYSFS */ } /* END OF sysfs data and methods */ -- cgit v1.2.3-59-g8ed1b From 79cb1819e231f811211133a09a5382cb89d7ec67 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 13 Mar 2006 13:50:04 -0600 Subject: [SCSI] add preliminary expander support to the sas transport class This patch makes expanders appear as labelled objects with properties in the SAS tree. I've also modified the phy code to make expander phys appear labelled by host number, expander number and phy index. So, for my current config, you see something like this in sysfs: /sys/class/scsi_host/host1/device/phy-1:4/expander-1:0/phy-1-0:12/rphy-1:0-12/target1:0:1 And the expander properties are: jejb@sparkweed> cd /sys/class/sas_expander/expander-1\:0/ jejb@sparkweed> for f in *; do echo -n $f ": "; cat $f; done component_id : 29024 component_revision_id : 4 component_vendor_id : VITESSE device : cat: device: Is a directory level : 0 product_id : VSC7160 Eval Brd product_rev : 4 uevent : cat: uevent: Permission denied vendor_id : VITESSE Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 141 ++++++++++++++++++++++++++++++++++++-- include/scsi/scsi_transport_sas.h | 31 +++++++++ 2 files changed, 166 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 3eb11a175904..5a70d04352cc 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -40,6 +40,7 @@ #define SAS_PORT_ATTRS 17 #define SAS_RPORT_ATTRS 7 #define SAS_END_DEV_ATTRS 3 +#define SAS_EXPANDER_ATTRS 7 struct sas_internal { struct scsi_transport_template t; @@ -49,10 +50,12 @@ struct sas_internal { struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS]; struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS]; struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS]; + struct class_device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS]; struct transport_container phy_attr_cont; struct transport_container rphy_attr_cont; struct transport_container end_dev_attr_cont; + struct transport_container expander_attr_cont; /* * The array of null terminated pointers to attributes @@ -62,6 +65,7 @@ struct sas_internal { struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1]; struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1]; struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1]; + struct class_device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1]; }; #define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t) @@ -69,6 +73,7 @@ struct sas_host_attrs { struct list_head rphy_list; struct mutex lock; u32 next_target_id; + u32 next_expander_id; }; #define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) @@ -173,6 +178,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev, INIT_LIST_HEAD(&sas_host->rphy_list); mutex_init(&sas_host->lock); sas_host->next_target_id = 0; + sas_host->next_expander_id = 0; return 0; } @@ -407,7 +413,12 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number) device_initialize(&phy->dev); phy->dev.parent = get_device(parent); phy->dev.release = sas_phy_release; - sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number); + if (scsi_is_sas_expander_device(parent)) { + struct sas_rphy *rphy = dev_to_rphy(parent); + sprintf(phy->dev.bus_id, "phy-%d-%d:%d", shost->host_no, + rphy->scsi_target_id, number); + } else + sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number); transport_setup_device(&phy->dev); @@ -635,6 +646,9 @@ int sas_read_port_mode_page(struct scsi_device *sdev) } EXPORT_SYMBOL(sas_read_port_mode_page); +static DECLARE_TRANSPORT_CLASS(sas_end_dev_class, + "sas_end_device", NULL, NULL, NULL); + #define sas_end_dev_show_simple(field, name, format_string, cast) \ static ssize_t \ show_sas_end_dev_##name(struct class_device *cdev, char *buf) \ @@ -656,8 +670,33 @@ sas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, "%d\n", int); -static DECLARE_TRANSPORT_CLASS(sas_end_dev_class, - "sas_end_device", NULL, NULL, NULL); +static DECLARE_TRANSPORT_CLASS(sas_expander_class, + "sas_expander", NULL, NULL, NULL); + +#define sas_expander_show_simple(field, name, format_string, cast) \ +static ssize_t \ +show_sas_expander_##name(struct class_device *cdev, char *buf) \ +{ \ + struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ + struct sas_expander_device *edev = rphy_to_expander_device(rphy); \ + \ + return snprintf(buf, 20, format_string, cast edev->field); \ +} + +#define sas_expander_simple_attr(field, name, format_string, type) \ + sas_expander_show_simple(field, name, format_string, (type)) \ +static SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO, \ + show_sas_expander_##name, NULL) + +sas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *); +sas_expander_simple_attr(product_id, product_id, "%s\n", char *); +sas_expander_simple_attr(product_rev, product_rev, "%s\n", char *); +sas_expander_simple_attr(component_vendor_id, component_vendor_id, + "%s\n", char *); +sas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int); +sas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", + unsigned int); +sas_expander_simple_attr(level, level, "%d\n", int); static DECLARE_TRANSPORT_CLASS(sas_rphy_class, "sas_rphy", NULL, NULL, NULL); @@ -706,6 +745,32 @@ static int sas_end_dev_match(struct attribute_container *cont, rphy->contained; } +static int sas_expander_match(struct attribute_container *cont, + struct device *dev) +{ + struct Scsi_Host *shost; + struct sas_internal *i; + struct sas_rphy *rphy; + + if (!scsi_is_sas_rphy(dev)) + return 0; + shost = dev_to_shost(dev->parent->parent); + rphy = dev_to_rphy(dev); + + if (!shost->transportt) + return 0; + if (shost->transportt->host_attrs.ac.class != + &sas_host_class.class) + return 0; + + i = to_sas_internal(shost->transportt); + return &i->expander_attr_cont.ac == cont && + (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || + rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) && + /* FIXME: remove contained eventually */ + rphy->contained; +} + static void sas_rphy_release(struct device *dev) { struct sas_rphy *rphy = dev_to_rphy(dev); @@ -778,6 +843,46 @@ struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent) } EXPORT_SYMBOL(sas_end_device_alloc); +/** + * sas_expander_alloc - allocate an rphy for an end device + * + * Allocates an SAS remote PHY structure, connected to @parent. + * + * Returns: + * SAS PHY allocated or %NULL if the allocation failed. + */ +struct sas_rphy *sas_expander_alloc(struct sas_phy *parent, + enum sas_device_type type) +{ + struct Scsi_Host *shost = dev_to_shost(&parent->dev); + struct sas_expander_device *rdev; + struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); + + BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE && + type != SAS_FANOUT_EXPANDER_DEVICE); + + rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); + if (!rdev) { + put_device(&parent->dev); + return NULL; + } + + device_initialize(&rdev->rphy.dev); + rdev->rphy.dev.parent = get_device(&parent->dev); + rdev->rphy.dev.release = sas_rphy_release; + mutex_lock(&sas_host->lock); + rdev->rphy.scsi_target_id = sas_host->next_expander_id++; + mutex_unlock(&sas_host->lock); + sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", + shost->host_no, rdev->rphy.scsi_target_id); + rdev->rphy.identify.device_type = type; + /* FIXME: mark the rphy as being contained in a larger structure */ + rdev->rphy.contained = 1; + transport_setup_device(&rdev->rphy.dev); + + return &rdev->rphy; +} +EXPORT_SYMBOL(sas_expander_alloc); /** * sas_rphy_add -- add a SAS remote PHY to the device hierachy @@ -809,11 +914,10 @@ int sas_rphy_add(struct sas_rphy *rphy) (identify->target_port_protocols & (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) rphy->scsi_target_id = sas_host->next_target_id++; - else - rphy->scsi_target_id = -1; mutex_unlock(&sas_host->lock); - if (rphy->scsi_target_id != -1) { + if (identify->device_type == SAS_END_DEVICE && + rphy->scsi_target_id != -1) { scsi_scan_target(&rphy->dev, parent->port_identifier, rphy->scsi_target_id, ~0, 0); } @@ -967,6 +1071,9 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, #define SETUP_END_DEV_ATTRIBUTE(field) \ SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) +#define SETUP_EXPANDER_ATTRIBUTE(field) \ + SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1) + /** * sas_attach_transport -- instantiate SAS transport template * @ft: SAS transport class function template @@ -1004,6 +1111,11 @@ sas_attach_transport(struct sas_function_template *ft) i->end_dev_attr_cont.ac.match = sas_end_dev_match; transport_container_register(&i->end_dev_attr_cont); + i->expander_attr_cont.ac.class = &sas_expander_class.class; + i->expander_attr_cont.ac.attrs = &i->expander_attrs[0]; + i->expander_attr_cont.ac.match = sas_expander_match; + transport_container_register(&i->expander_attr_cont); + i->f = ft; count = 0; @@ -1048,6 +1160,16 @@ sas_attach_transport(struct sas_function_template *ft) SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); i->end_dev_attrs[count] = NULL; + count = 0; + SETUP_EXPANDER_ATTRIBUTE(vendor_id); + SETUP_EXPANDER_ATTRIBUTE(product_id); + SETUP_EXPANDER_ATTRIBUTE(product_rev); + SETUP_EXPANDER_ATTRIBUTE(component_vendor_id); + SETUP_EXPANDER_ATTRIBUTE(component_id); + SETUP_EXPANDER_ATTRIBUTE(component_revision_id); + SETUP_EXPANDER_ATTRIBUTE(level); + i->expander_attrs[count] = NULL; + return &i->t; } EXPORT_SYMBOL(sas_attach_transport); @@ -1064,6 +1186,7 @@ void sas_release_transport(struct scsi_transport_template *t) transport_container_unregister(&i->phy_attr_cont); transport_container_unregister(&i->rphy_attr_cont); transport_container_unregister(&i->end_dev_attr_cont); + transport_container_unregister(&i->expander_attr_cont); kfree(i); } @@ -1085,9 +1208,14 @@ static __init int sas_transport_init(void) error = transport_class_register(&sas_end_dev_class); if (error) goto out_unregister_rphy; + error = transport_class_register(&sas_expander_class); + if (error) + goto out_unregister_end_dev; return 0; + out_unregister_end_dev: + transport_class_unregister(&sas_end_dev_class); out_unregister_rphy: transport_class_unregister(&sas_rphy_class); out_unregister_phy: @@ -1105,6 +1233,7 @@ static void __exit sas_transport_exit(void) transport_class_unregister(&sas_phy_class); transport_class_unregister(&sas_rphy_class); transport_class_unregister(&sas_end_dev_class); + transport_class_unregister(&sas_expander_class); } MODULE_AUTHOR("Christoph Hellwig"); diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 8fded431cf46..2943ccc22a43 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -108,6 +108,25 @@ struct sas_end_device { #define rphy_to_end_device(r) \ container_of((r), struct sas_end_device, rphy) +struct sas_expander_device { + int level; + + #define SAS_EXPANDER_VENDOR_ID_LEN 8 + char vendor_id[SAS_EXPANDER_VENDOR_ID_LEN+1]; + #define SAS_EXPANDER_PRODUCT_ID_LEN 16 + char product_id[SAS_EXPANDER_PRODUCT_ID_LEN+1]; + #define SAS_EXPANDER_PRODUCT_REV_LEN 4 + char product_rev[SAS_EXPANDER_PRODUCT_REV_LEN+1]; + #define SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN 8 + char component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN+1]; + u16 component_id; + u8 component_revision_id; + + struct sas_rphy rphy; + +}; +#define rphy_to_expander_device(r) \ + container_of((r), struct sas_expander_device, rphy) /* The functions by which the transport class and the driver communicate */ struct sas_function_template { @@ -128,6 +147,7 @@ extern int scsi_is_sas_phy(const struct device *); extern struct sas_rphy *sas_rphy_alloc(struct sas_phy *); extern struct sas_rphy *sas_end_device_alloc(struct sas_phy *); +extern struct sas_rphy *sas_expander_alloc(struct sas_phy *, enum sas_device_type); void sas_rphy_free(struct sas_rphy *); extern int sas_rphy_add(struct sas_rphy *); extern void sas_rphy_delete(struct sas_rphy *); @@ -138,4 +158,15 @@ sas_attach_transport(struct sas_function_template *); extern void sas_release_transport(struct scsi_transport_template *); int sas_read_port_mode_page(struct scsi_device *); +static inline int +scsi_is_sas_expander_device(struct device *dev) +{ + struct sas_rphy *rphy; + if (!scsi_is_sas_rphy(dev)) + return 0; + rphy = dev_to_rphy(dev); + return rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE || + rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE; +} + #endif /* SCSI_TRANSPORT_SAS_H */ -- cgit v1.2.3-59-g8ed1b From e935d5da8e5d12fabe5b632736c50eae0427e8c8 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:18:18 -0700 Subject: [SCSI] drivers/base/bus.c - export reprobe Adding support for exposing hidden raid components for sg interface. The sdev->no_uld_attach flag will set set accordingly. The sas module supports adding/removing raid volumes using online storage management application interface. This patch was provided to me by Christoph Hellwig. Signed-off-by: Eric Moore Signed-off-by: Greg Kroah-Hartman Signed-off-by: James Bottomley --- drivers/base/bus.c | 22 ++++++++++++++++++++++ include/linux/device.h | 1 + 2 files changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index c3141565d59d..48718b7f4fa0 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -536,6 +536,28 @@ void bus_rescan_devices(struct bus_type * bus) bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper); } +/** + * device_reprobe - remove driver for a device and probe for a new driver + * @dev: the device to reprobe + * + * This function detaches the attached driver (if any) for the given + * device and restarts the driver probing process. It is intended + * to use if probing criteria changed during a devices lifetime and + * driver attachment should change accordingly. + */ +void device_reprobe(struct device *dev) +{ + if (dev->driver) { + if (dev->parent) /* Needed for USB */ + down(&dev->parent->sem); + device_release_driver(dev); + if (dev->parent) + up(&dev->parent->sem); + } + + bus_rescan_devices_helper(dev, NULL); +} +EXPORT_SYMBOL_GPL(device_reprobe); struct bus_type * get_bus(struct bus_type * bus) { diff --git a/include/linux/device.h b/include/linux/device.h index 58df18d9cd3e..e8ac5bcfbec7 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -378,6 +378,7 @@ extern void device_bind_driver(struct device * dev); extern void device_release_driver(struct device * dev); extern int device_attach(struct device * dev); extern void driver_attach(struct device_driver * drv); +extern void device_reprobe(struct device *dev); /* -- cgit v1.2.3-59-g8ed1b From e5b3a65fd7244e662691cf617145983ecde28cc9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 10 Mar 2006 17:08:57 +0100 Subject: [SCSI] megaraid_sas: fix extended timeout handling Replace the eh_timed_out method usage with setting sdev->timeout in slave_configure. Also only use the extended timeout for raid volumes, physical devices shouldn't need it. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 4f39dd01936d..38ede24b22a6 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -772,8 +772,6 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) goto out_return_cmd; cmd->scmd = scmd; - scmd->SCp.ptr = (char *)cmd; - scmd->SCp.sent_command = jiffies; /* * Issue the command to the FW @@ -804,6 +802,12 @@ static int megasas_slave_configure(struct scsi_device *sdev) */ if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK) return -ENXIO; + + /* + * The RAID firmware may require extended timeouts. + */ + if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS) + sdev->timeout = 90 * HZ; return 0; } @@ -875,23 +879,6 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd) return ret_val; } -static enum scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) -{ - unsigned long seconds; - - if (scmd->SCp.ptr) { - seconds = (jiffies - scmd->SCp.sent_command) / HZ; - - if (seconds < 90) { - return EH_RESET_TIMER; - } else { - return EH_NOT_HANDLED; - } - } - - return EH_HANDLED; -} - /** * megasas_reset_device - Device reset handler entry point */ @@ -962,7 +949,6 @@ static struct scsi_host_template megasas_template = { .eh_device_reset_handler = megasas_reset_device, .eh_bus_reset_handler = megasas_reset_bus_host, .eh_host_reset_handler = megasas_reset_bus_host, - .eh_timed_out = megasas_reset_timer, .use_clustering = ENABLE_CLUSTERING, }; -- cgit v1.2.3-59-g8ed1b From 5bf52c4fda97325976ffaf338d2e81b73b3db446 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:01 -0700 Subject: [SCSI] fusion - loginfo header update This header is provided to better understand loginfo codes returned by the mpt fusion firmware. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/lsi/mpi_log_sas.h | 105 ++++++++++++++++++------------- drivers/message/fusion/mptbase.c | 4 +- 2 files changed, 63 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h index 9259d1ad6e6e..a9c14ad132ce 100644 --- a/drivers/message/fusion/lsi/mpi_log_sas.h +++ b/drivers/message/fusion/lsi/mpi_log_sas.h @@ -3,38 +3,11 @@ * * * Copyright 2003 LSI Logic Corporation. All rights reserved. * * * - * This file is confidential and a trade secret of LSI Logic. The * - * receipt of or possession of this file does not convey any rights to * - * reproduce or disclose its contents or to manufacture, use, or sell * - * anything it may describe, in whole, or in part, without the specific * - * written consent of LSI Logic Corporation. * + * Description * + * ------------ * + * This include file contains SAS firmware interface IOC Log Info codes * * * - *************************************************************************** - * - * Name: iopiIocLogInfo.h - * Title: SAS Firmware IOP Interface IOC Log Info Definitions - * Programmer: Guy Kendall - * Creation Date: September 24, 2003 - * - * Version History - * --------------- - * - * Last Updated - * ------------- - * Version %version: 22 % - * Date Updated %date_modified: % - * Programmer %created_by: nperucca % - * - * Date Who Description - * -------- --- ------------------------------------------------------- - * 09/24/03 GWK Initial version - * - * - * Description - * ------------ - * This include file contains SAS firmware interface IOC Log Info codes - * - *------------------------------------------------------------------------- + *-------------------------------------------------------------------------* */ #ifndef IOPI_IOCLOGINFO_H_INCLUDED @@ -57,6 +30,8 @@ #define IOC_LOGINFO_ORIGINATOR_PL (0x01000000) #define IOC_LOGINFO_ORIGINATOR_IR (0x02000000) +#define IOC_LOGINFO_ORIGINATOR_MASK (0x0F000000) + /****************************************************************************/ /* LOGINFO_CODE defines */ /****************************************************************************/ @@ -78,11 +53,27 @@ #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */ #define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000) +#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R (0x00060001) /* Read Action not supported for SEP msg */ +#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */ + +#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED (0x00070001) +#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED (0x00070002) +#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO (0x00070003) +#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO (0x00070004) +#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005) /****************************************************************************/ /* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */ /****************************************************************************/ #define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000) +#define PL_LOG_INFO_CODE_OPEN_FAILURE_NO_DEST_TIME_OUT (0x00010001) +#define PL_LOGINFO_CODE_OPEN_FAILURE_BAD_DESTINATION (0x00010011) +#define PL_LOGINFO_CODE_OPEN_FAILURE_PROTOCOL_NOT_SUPPORTED (0x00010013) +#define PL_LOGINFO_CODE_OPEN_FAILURE_STP_RESOURCES_BSY (0x00010018) +#define PL_LOGINFO_CODE_OPEN_FAILURE_WRONG_DESTINATION (0x00010019) +#define PL_LOGINFO_CODE_OPEN_FAILURE_ORR_TIMEOUT (0X0001001A) +#define PL_LOGINFO_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0001001B) +#define PL_LOGINFO_CODE_OPEN_FAILURE_AWT_MAXED (0x0001001C) #define PL_LOGINFO_CODE_INVALID_SGL (0x00020000) #define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000) #define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000) @@ -97,6 +88,7 @@ #define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000) #define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000) #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000) +#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED (0x000F0001) /* PL not yet initialized, can't do config page req. */ #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */ #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */ #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */ @@ -105,11 +97,23 @@ #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */ #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */ #define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000) -#define PL_LOGINFO_CODE_RESET (0x00110000) -#define PL_LOGINFO_CODE_ABORT (0x00120000) +#define PL_LOGINFO_CODE_RESET (0x00110000) /* See Sub-Codes below */ +#define PL_LOGINFO_CODE_ABORT (0x00120000) /* See Sub-Codes below */ #define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000) #define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000) +#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER (0x00150000) +#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT (0x00160000) #define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT (0x00000101) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT (0x0000011A) /* Open Reject (Retry) Timeout */ +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0000011B) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED (0x0000011C) /* Arbitration Wait Timer Maxed */ + +#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET (0x00000120) +#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER (0x00000130) /* Leave lower nibble (1-f) reserved. */ +#define PL_LOGINFO_SUB_CODE_PORT_LAYER (0x00000140) /* Leave lower nibble (1-f) reserved. */ + + #define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200) #define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300) #define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) @@ -123,26 +127,39 @@ #define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00) #define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00) #define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00) +#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET (0x00000E01) +#define PL_LOGINFO_SUB_CODE_SECOND_OPEN (0x00000F00) #define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000) #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200001) /* Error occured on SMP Read */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200002) /* Error occured on SMP Write */ -#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200004) /* Encl Mgmt services not available for this WWID */ -#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200005) /* Address Mode not suppored */ -#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200006) /* Invalid Slot Number in SEP Msg */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200007) /* SGPIO not present/enabled */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200020) /* Error occured on SMP Write */ +#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200040) /* Encl Mgmt services not available for this WWID */ +#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200050) /* Address Mode not suppored */ +#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200060) /* Invalid Slot Number in SEP Msg */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200070) /* SGPIO not present/enabled */ +#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED (0x00200080) /* GPIO not configured */ +#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR (0x00200090) /* GPIO can't allocate a frame */ +#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR (0x002000A0) /* GPIO failed config page request */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR (0x002000B0) /* Can't get frame for SES command */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR (0x002000C0) /* I/O execution error */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED (0x002000D0) /* SEP I/O retries exhausted */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR (0x002000E0) /* Can't get frame for SMP command */ #define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */ #define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */ #define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */ #define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */ -#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200104) /* SEP stopped or sent bad chksum in Hdr */ -#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200105) /* SEP returned unknown scsi status */ -#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200106) /* SEP returned unknown scsi status */ -#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x00200107) /* SEP returned bad chksum after STOP */ -#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/ +#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */ +#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200105) /* SEP stopped or sent bad chksum in Hdr */ +#define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transfering data */ +#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transfering sense data */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200108) /* SEP returned unknown scsi status */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200109) /* SEP returned unknown scsi status */ +#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x0020010A) /* SEP returned bad chksum after STOP */ +#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND (0x0020010C) /* SEP doesn't support CDB opcode */ /****************************************************************************/ diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index f2721ea30aa7..39c0b16d8d04 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -6138,8 +6138,8 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) "Abort", /* 12h */ "IO Not Yet Executed", /* 13h */ "IO Executed", /* 14h */ - NULL, /* 15h */ - NULL, /* 16h */ + "Persistant Reservation Out Not Affiliation Owner", /* 15h */ + "Open Transmit DMA Abort", /* 16h */ NULL, /* 17h */ NULL, /* 18h */ NULL, /* 19h */ -- cgit v1.2.3-59-g8ed1b From 3a892bef3f7e94c4d6c2c20b9a1b546f43679fd3 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:03 -0700 Subject: [SCSI] fusion - move some debug firmware event debug msgs to verbose level Created a debug level MPT_DEBUG_VERBOSE_EVENTS. Moving some of the more vebose debug messages for firwmare events into new debug level. Also added some more firmware events descriptions. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/Makefile | 1 + drivers/message/fusion/mptbase.c | 125 ++++++++++++++++++++++++++++++++------ drivers/message/fusion/mptbase.h | 8 ++- drivers/message/fusion/mptctl.c | 6 +- drivers/message/fusion/mptfc.c | 2 +- drivers/message/fusion/mptsas.c | 2 +- drivers/message/fusion/mptscsih.c | 2 +- drivers/message/fusion/mptspi.c | 2 +- 8 files changed, 122 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 33ace373241c..51740b346224 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -4,6 +4,7 @@ #EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME #EXTRA_CFLAGS += -DMPT_DEBUG_SG #EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS +#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE_EVENTS #EXTRA_CFLAGS += -DMPT_DEBUG_INIT #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 39c0b16d8d04..9960ef10366f 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -428,7 +428,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) results = ProcessEventNotification(ioc, pEvReply, &evHandlers); if (results != evHandlers) { /* CHECKME! Any special handling needed here? */ - devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", + devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", ioc->name, evHandlers, results)); } @@ -438,10 +438,10 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) */ if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) { freereq = 0; - devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n", + devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n", ioc->name, pEvReply)); } else { - devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", + devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", ioc->name, pEvReply)); } @@ -5079,13 +5079,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch) evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc); if (evnp == NULL) { - devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", + devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", ioc->name)); return 0; } memset(evnp, 0, sizeof(*evnp)); - devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); + devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; evnp->ChainOffset = 0; @@ -5840,24 +5840,27 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) break; case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: { + char buf[50]; + u8 id = (u8)(evData0); u8 ReasonCode = (u8)(evData0 >> 16); switch (ReasonCode) { case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: - ds = "SAS Device Status Change: Added"; + sprintf(buf,"SAS Device Status Change: Added: id=%d", id); break; case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: - ds = "SAS Device Status Change: Deleted"; + sprintf(buf,"SAS Device Status Change: Deleted: id=%d", id); break; case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: - ds = "SAS Device Status Change: SMART Data"; + sprintf(buf,"SAS Device Status Change: SMART Data: id=%d", id); break; case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: - ds = "SAS Device Status Change: No Persistancy Added"; + sprintf(buf,"SAS Device Status Change: No Persistancy Added: id=%d", id); break; default: - ds = "SAS Device Status Change: Unknown"; + sprintf(buf,"SAS Device Status Change: Unknown: id=%d", id); break; } + ds = buf; break; } case MPI_EVENT_ON_BUS_TIMER_EXPIRED: @@ -5873,11 +5876,97 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) ds = "Persistent Table Full"; break; case MPI_EVENT_SAS_PHY_LINK_STATUS: - ds = "SAS PHY Link Status"; + { + char buf[50]; + u8 LinkRates = (u8)(evData0 >> 8); + u8 PhyNumber = (u8)(evData0); + LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >> + MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT; + switch (LinkRates) { + case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Rate Unknown",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Phy Disabled",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Failed Speed Nego",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Sata OOB Completed",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_1_5: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Rate 1.5 Gbps",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_3_0: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Rate 3.0 Gpbs",PhyNumber); + break; + default: + sprintf(buf,"SAS PHY Link Status: Phy=%d", PhyNumber); + break; + } + ds = buf; break; + } case MPI_EVENT_SAS_DISCOVERY_ERROR: ds = "SAS Discovery Error"; break; + case MPI_EVENT_IR_RESYNC_UPDATE: + { + u8 resync_complete = (u8)(evData0 >> 16); + char buf[40]; + sprintf(buf,"IR Resync Update: Complete = %d:",resync_complete); + ds = buf; + break; + } + case MPI_EVENT_IR2: + { + u8 ReasonCode = (u8)(evData0 >> 16); + switch (ReasonCode) { + case MPI_EVENT_IR2_RC_LD_STATE_CHANGED: + ds = "IR2: LD State Changed"; + break; + case MPI_EVENT_IR2_RC_PD_STATE_CHANGED: + ds = "IR2: PD State Changed"; + break; + case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL: + ds = "IR2: Bad Block Table Full"; + break; + case MPI_EVENT_IR2_RC_PD_INSERTED: + ds = "IR2: PD Inserted"; + break; + case MPI_EVENT_IR2_RC_PD_REMOVED: + ds = "IR2: PD Removed"; + break; + case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: + ds = "IR2: Foreign CFG Detected"; + break; + case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR: + ds = "IR2: Rebuild Medium Error"; + break; + default: + ds = "IR2"; + break; + } + break; + } + case MPI_EVENT_SAS_DISCOVERY: + { + if (evData0) + ds = "SAS Discovery: Start"; + else + ds = "SAS Discovery: Stop"; + break; + } + case MPI_EVENT_LOG_ENTRY_ADDED: + ds = "SAS Log Entry Added"; + break; /* * MPT base "custom" events may be added here... @@ -5922,12 +6011,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply } EventDescriptionStr(event, evData0, evStr); - devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", + devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n", ioc->name, - evStr, - event)); + event, + evStr)); -#if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS) +#if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS) printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO); for (ii = 0; ii < evDataLen; ii++) printk(" %08x", le32_to_cpu(pEventReply->Data[ii])); @@ -5986,7 +6075,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply */ for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { if (MptEvHandlers[ii]) { - devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", + devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", ioc->name, ii)); r += (*(MptEvHandlers[ii]))(ioc, pEventReply); handlers++; @@ -5998,10 +6087,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply * If needed, send (a single) EventAck. */ if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) { - devtprintk((MYIOC_s_WARN_FMT + devtverboseprintk((MYIOC_s_WARN_FMT "EventAck required\n",ioc->name)); if ((ii = SendEventAck(ioc, pEventReply)) != 0) { - devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", + devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", ioc->name, ii)); } } diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index f4197a9962a3..fb22b28d1ab6 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -719,12 +719,18 @@ typedef struct _mpt_sge { #define dhsprintk(x) #endif -#ifdef MPT_DEBUG_EVENTS +#if defined(MPT_DEBUG_EVENTS) || defined(MPT_DEBUG_VERBOSE_EVENTS) #define devtprintk(x) printk x #else #define devtprintk(x) #endif +#ifdef MPT_DEBUG_VERBOSE_EVENTS +#define devtverboseprintk(x) printk x +#else +#define devtverboseprintk(x) +#endif + #ifdef MPT_DEBUG_RESET #define drsprintk(x) printk x #else diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 9b64e07400da..3d555b724ed0 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -497,7 +497,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) if (event == 0x21 ) { ioc->aen_event_read_flag=1; dctlprintk(("Raised SIGIO to application\n")); - devtprintk(("Raised SIGIO to application\n")); + devtverboseprintk(("Raised SIGIO to application\n")); kill_fasync(&async_queue, SIGIO, POLL_IN); return 1; } @@ -515,7 +515,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) if (ioc->events && (ioc->eventTypes & ( 1 << event))) { ioc->aen_event_read_flag=1; dctlprintk(("Raised SIGIO to application\n")); - devtprintk(("Raised SIGIO to application\n")); + devtverboseprintk(("Raised SIGIO to application\n")); kill_fasync(&async_queue, SIGIO, POLL_IN); } return 1; @@ -2968,7 +2968,7 @@ static int __init mptctl_init(void) } if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) { - devtprintk((KERN_INFO MYNAM + devtverboseprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 8ea12ea652ad..5a30621051c3 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -941,7 +941,7 @@ mptfc_init(void) mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { - devtprintk((KERN_INFO MYNAM + devtverboseprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 74f4368c79ab..ba93ef13a41e 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -1993,7 +1993,7 @@ mptsas_init(void) mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) { - devtprintk((KERN_INFO MYNAM + devtverboseprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index a2183103b8c3..77289fd07fe7 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2531,7 +2531,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) int work_count; unsigned long flags; - devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", + devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); if (ioc->sh == NULL || diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 437189f871b0..9af69dd66f8b 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -1057,7 +1057,7 @@ mptspi_init(void) mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) { - devtprintk((KERN_INFO MYNAM + devtverboseprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } -- cgit v1.2.3-59-g8ed1b From c972c70fa03097be4235fc441658290a3b7af06f Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:06 -0700 Subject: [SCSI] fusion - static fix's Patch previously provided from Adrian Bunk , moving some functions to static. This is already in the -mm tree. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 4 ++-- drivers/message/fusion/mptbase.h | 1 - drivers/message/fusion/mptctl.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 9960ef10366f..266414ca2814 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -180,6 +180,7 @@ static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); +static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); /* module entry point */ static int __init fusion_init (void); @@ -4871,7 +4872,7 @@ done_and_free: return rc; } -int +static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) { IOCPage3_t *pIoc3; @@ -6453,7 +6454,6 @@ EXPORT_SYMBOL(mpt_stm_index); EXPORT_SYMBOL(mpt_HardResetHandler); EXPORT_SYMBOL(mpt_config); EXPORT_SYMBOL(mpt_findImVolumes); -EXPORT_SYMBOL(mpt_read_ioc_pg_3); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mptbase_sas_persist_operation); diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index fb22b28d1ab6..2b9c8b5522fa 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -1027,7 +1027,6 @@ extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg); 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 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 3d555b724ed0..b4967bb8a7d6 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -140,7 +140,7 @@ static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase); * Event Handler function */ static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); -struct fasync_struct *async_queue=NULL; +static struct fasync_struct *async_queue=NULL; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* -- cgit v1.2.3-59-g8ed1b From 914c2d8e597798d62c2e0a3cba737bf6f611eecf Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:19:36 -0700 Subject: [SCSI] fusion - removing target_id/bus_id from the VirtDevice structure It makes no sense in keeping the target_id and bus_id in the VirtDevice structure, when it can be obtained from the VirtTarget structure. In addition, this patch fix's couple compilation bugs in mptfc.c when MPT_DEBUG_FC is enabled. This provided by Micheal Reed. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 5 +---- drivers/message/fusion/mptfc.c | 33 ++++++++------------------------- drivers/message/fusion/mptsas.c | 24 +++++++++++------------- drivers/message/fusion/mptscsih.c | 19 ++++++++----------- drivers/message/fusion/mptspi.c | 4 ++-- 5 files changed, 30 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 2b9c8b5522fa..9b58234add36 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -347,10 +347,7 @@ typedef struct _VirtTarget { } VirtTarget; typedef struct _VirtDevice { - VirtTarget *vtarget; - u8 ioc_id; - u8 bus_id; - u8 target_id; + VirtTarget *vtarget; u8 configured_lun; u32 lun; } VirtDevice; diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 5a30621051c3..b343f2a68b1c 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -348,24 +348,6 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid) return 0; } -static void -mptfc_remap_sdev(struct scsi_device *sdev, void *arg) -{ - VirtDevice *vdev; - VirtTarget *vtarget; - struct scsi_target *starget; - - starget = scsi_target(sdev); - if (starget->hostdata == arg) { - vtarget = arg; - vdev = sdev->hostdata; - if (vdev) { - vdev->bus_id = vtarget->bus_id; - vdev->target_id = vtarget->target_id; - } - } -} - static void mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) { @@ -423,8 +405,6 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) if (vtarget) { vtarget->target_id = pg0->CurrentTargetID; vtarget->bus_id = pg0->CurrentBus; - starget_for_each_device(ri->starget, - vtarget,mptfc_remap_sdev); } ri->remap_needed = 0; } @@ -432,7 +412,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " "rport tid %d, tmo %d\n", ioc->name, - oc->sh->host_no, + ioc->sh->host_no, pg0->PortIdentifier, pg0->WWNN, pg0->WWPN, @@ -553,23 +533,26 @@ mptfc_slave_alloc(struct scsi_device *sdev) } vdev->vtarget = vtarget; - vdev->ioc_id = hd->ioc->id; vdev->lun = sdev->lun; - vdev->target_id = vtarget->target_id; - vdev->bus_id = vtarget->bus_id; spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); vtarget->num_luns++; +#ifdef DMPT_DEBUG_FC + { + struct mptfc_rport_info *ri; + ri = *((struct mptfc_rport_info **)rport->dd_data); dfcprintk ((MYIOC_s_INFO_FMT "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " "CurrentTargetID %d, %x %llx %llx\n", - ioc->name, + hd->ioc->name, sdev->host->host_no, vtarget->num_luns, sdev->id, ri->pg0.CurrentTargetID, ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN)); + } +#endif return 0; } diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index ba93ef13a41e..ba555a60bf7f 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -350,6 +350,7 @@ mptsas_slave_alloc(struct scsi_device *sdev) VirtTarget *vtarget; VirtDevice *vdev; struct scsi_target *starget; + u32 target_id; int i; vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); @@ -358,10 +359,10 @@ mptsas_slave_alloc(struct scsi_device *sdev) hd->ioc->name, sizeof(VirtDevice)); return -ENOMEM; } - vdev->ioc_id = hd->ioc->id; sdev->hostdata = vdev; starget = scsi_target(sdev); vtarget = starget->hostdata; + vtarget->ioc_id = hd->ioc->id; vdev->vtarget = vtarget; if (vtarget->num_luns == 0) { vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; @@ -372,8 +373,8 @@ mptsas_slave_alloc(struct scsi_device *sdev) RAID volumes placed beyond the last expected port. */ if (sdev->channel == hd->ioc->num_ports) { - vdev->target_id = sdev->id; - vdev->bus_id = 0; + target_id = sdev->id; + vtarget->bus_id = 0; vdev->lun = 0; goto out; } @@ -384,11 +385,10 @@ mptsas_slave_alloc(struct scsi_device *sdev) for (i = 0; i < p->num_phys; i++) { if (p->phy_info[i].attached.sas_address == rphy->identify.sas_address) { - vdev->target_id = - p->phy_info[i].attached.id; - vdev->bus_id = p->phy_info[i].attached.channel; + target_id = p->phy_info[i].attached.id; + vtarget->bus_id = p->phy_info[i].attached.channel; vdev->lun = sdev->lun; - mutex_unlock(&hd->ioc->sas_topology_mutex); + mutex_unlock(&hd->ioc->sas_topology_mutex); goto out; } } @@ -399,9 +399,7 @@ mptsas_slave_alloc(struct scsi_device *sdev) return -ENXIO; out: - vtarget->ioc_id = vdev->ioc_id; - vtarget->target_id = vdev->target_id; - vtarget->bus_id = vdev->bus_id; + vtarget->target_id = target_id; vtarget->num_luns++; return 0; } @@ -444,8 +442,8 @@ mptsas_slave_destroy(struct scsi_device *sdev) if (vdev->configured_lun){ if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - vdev->bus_id, - vdev->target_id, + vdev->vtarget->bus_id, + vdev->vtarget->target_id, 0, 0, 5 /* 5 second timeout */) < 0){ @@ -455,7 +453,7 @@ mptsas_slave_destroy(struct scsi_device *sdev) printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt id=%d TARGET_RESET\n", hd->ioc->name, - vdev->target_id); + vdev->vtarget->target_id); hd->tmPending = 0; hd->tmState = TM_STATE_NONE; diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 77289fd07fe7..c99a918feb58 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -887,7 +887,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n", hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); - if ((mf->TargetID != ((u8)vdevice->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) + if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) continue; /* Cleanup @@ -1285,8 +1285,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* Use the above information to set up the message frame */ - pScsiReq->TargetID = (u8) vdev->target_id; - pScsiReq->Bus = vdev->bus_id; + pScsiReq->TargetID = (u8) vdev->vtarget->target_id; + pScsiReq->Bus = vdev->vtarget->bus_id; pScsiReq->ChainOffset = 0; if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; @@ -1701,7 +1701,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, - vdev->bus_id, vdev->target_id, vdev->lun, + vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun, ctx2abort, mptscsih_get_tm_timeout(ioc)); printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", @@ -1752,7 +1752,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - vdev->bus_id, vdev->target_id, + vdev->vtarget->bus_id, vdev->vtarget->target_id, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", @@ -1803,7 +1803,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); + vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", hd->ioc->name, @@ -2162,9 +2162,6 @@ mptscsih_slave_alloc(struct scsi_device *sdev) return -ENOMEM; } - vdev->ioc_id = hd->ioc->id; - vdev->target_id = sdev->id; - vdev->bus_id = sdev->channel; vdev->lun = sdev->lun; sdev->hostdata = vdev; @@ -3366,8 +3363,8 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) iocmd.data_dma = -1; iocmd.size = 0; iocmd.rsvd = iocmd.rsvd2 = 0; - iocmd.bus = vdevice->bus_id; - iocmd.id = vdevice->target_id; + iocmd.bus = vdevice->vtarget->bus_id; + iocmd.id = vdevice->vtarget->target_id; iocmd.lun = (u8)vdevice->lun; if ((vdevice->vtarget->type == TYPE_DISK) && diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 9af69dd66f8b..09c745b19cc8 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -343,9 +343,9 @@ static int mptspi_slave_alloc(struct scsi_device *sdev) sdev->no_uld_attach = 1; vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; /* The real channel for this device is zero */ - vdev->bus_id = 0; + vdev->vtarget->bus_id = 0; /* The actual physdisknum (for RAID passthrough) */ - vdev->target_id = physdisknum; + vdev->vtarget->target_id = physdisknum; } return 0; -- cgit v1.2.3-59-g8ed1b From 4b766471e388352f35a6171563dfc0d272f12b59 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:12 -0700 Subject: [SCSI] fusion - cleanup mptsas event handling functions Cleanup of mptsas firmware event handlers. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 96 ++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index ba555a60bf7f..84643ac6c70f 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -1441,6 +1441,17 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) return phy_info; } +/* + * Work queue thread to clear the persitency table + */ +static void +mptscsih_sas_persist_clear_table(void * arg) +{ + MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + + mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); +} + static void mptsas_hotplug_work(void *arg) { @@ -1537,7 +1548,7 @@ mptsas_hotplug_work(void *arg) break; } printk(MYIOC_s_INFO_FMT - "attaching device, channel %d, id %d\n", + "attaching raid volume, channel %d, id %d\n", ioc->name, ioc->num_ports, ev->id); scsi_add_device(ioc->sh, ioc->num_ports, @@ -1554,7 +1565,7 @@ mptsas_hotplug_work(void *arg) if (!sdev) break; printk(MYIOC_s_INFO_FMT - "removing device, channel %d, id %d\n", + "removing raid volume, channel %d, id %d\n", ioc->name, ioc->num_ports, ev->id); scsi_remove_device(sdev); scsi_device_put(sdev); @@ -1579,35 +1590,51 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc, MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) return; - if ((sas_event_data->ReasonCode & - (MPI_EVENT_SAS_DEV_STAT_RC_ADDED | - MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0) - return; + switch (sas_event_data->ReasonCode) { + case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: + case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + printk(KERN_WARNING "mptsas: lost hotplug event\n"); + break; + } - ev = kmalloc(sizeof(*ev), GFP_ATOMIC); - if (!ev) { - printk(KERN_WARNING "mptsas: lost hotplug event\n"); - return; + INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + ev->ioc = ioc; + ev->handle = le16_to_cpu(sas_event_data->DevHandle); + ev->parent_handle = + le16_to_cpu(sas_event_data->ParentDevHandle); + ev->channel = sas_event_data->Bus; + ev->id = sas_event_data->TargetID; + ev->phy_id = sas_event_data->PhyNum; + memcpy(&sas_address, &sas_event_data->SASAddress, + sizeof(__le64)); + ev->sas_address = le64_to_cpu(sas_address); + ev->device_info = device_info; + + if (sas_event_data->ReasonCode & + MPI_EVENT_SAS_DEV_STAT_RC_ADDED) + ev->event_type = MPTSAS_ADD_DEVICE; + else + ev->event_type = MPTSAS_DEL_DEVICE; + schedule_work(&ev->work); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: + /* + * Persistent table is full. + */ + INIT_WORK(&ioc->mptscsih_persistTask, + mptscsih_sas_persist_clear_table, + (void *)ioc); + schedule_work(&ioc->mptscsih_persistTask); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: + /* TODO */ + case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: + /* TODO */ + default: + break; } - - - INIT_WORK(&ev->work, mptsas_hotplug_work, ev); - ev->ioc = ioc; - ev->handle = le16_to_cpu(sas_event_data->DevHandle); - ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle); - ev->channel = sas_event_data->Bus; - ev->id = sas_event_data->TargetID; - ev->phy_id = sas_event_data->PhyNum; - memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64)); - ev->sas_address = le64_to_cpu(sas_address); - ev->device_info = device_info; - - if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED) - ev->event_type = MPTSAS_ADD_DEVICE; - else - ev->event_type = MPTSAS_DEL_DEVICE; - - schedule_work(&ev->work); } static void @@ -1657,16 +1684,6 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc, schedule_work(&ev->work); } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* work queue thread to clear the persitency table */ -static void -mptscsih_sas_persist_clear_table(void * arg) -{ - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; - - mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); -} - static int mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) { @@ -1691,6 +1708,7 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) (void *)ioc); schedule_work(&ioc->mptscsih_persistTask); break; + case MPI_EVENT_SAS_DISCOVERY: default: rc = mptscsih_event_process(ioc, reply); break; -- cgit v1.2.3-59-g8ed1b From 52435430fc8724f09ad0e917eddf677583cdd45c Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:15 -0700 Subject: [SCSI] fusion - exclosure misspelled exclosure should be enclosure Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 84643ac6c70f..cea10aa50d4a 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -271,7 +271,7 @@ static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy) } static int -mptsas_sas_exclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, +mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, u32 form, u32 form_specific) { ConfigExtendedPageHeader_t hdr; @@ -655,7 +655,7 @@ mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) found_info: mutex_unlock(&ioc->sas_topology_mutex); memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure)); - error = mptsas_sas_exclosure_pg0(ioc, &enclosure_info, + error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info, (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle); if (!error) -- cgit v1.2.3-59-g8ed1b From db9c9174e42bdc8d52bc18df7c55823cf4546eda Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:18 -0700 Subject: [SCSI] fusion - memory leak, and initializing fields Changelog: (1) fix memory leak: p->phy_info (2) initialize device_info and port_info data fields (3) initialize the hba firmware handle (4) initialize phy_id for attached phy_info data fields (5) initialize attached phy_info data fields Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index cea10aa50d4a..b6a6f27082b6 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -749,6 +749,9 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) goto out_free_consistent; } + if (port_info->num_phys) + port_info->handle = + le16_to_cpu(buffer->PhyData[0].ControllerDevHandle); for (i = 0; i < port_info->num_phys; i++) { mptsas_print_phy_data(&buffer->PhyData[i]); port_info->phy_info[i].phy_id = i; @@ -855,6 +858,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, cfg.dir = 0; /* read */ cfg.timeout = 10; + memset(device_info, 0, sizeof(struct mptsas_devinfo)); error = mpt_config(ioc, &cfg); if (error) goto out; @@ -925,6 +929,7 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, cfg.dir = 0; /* read */ cfg.timeout = 10; + memset(port_info, 0, sizeof(struct mptsas_portinfo)); error = mpt_config(ioc, &cfg); if (error) goto out; @@ -1334,6 +1339,8 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << MPI_SAS_DEVICE_PGAD_FORM_SHIFT), port_info->phy_info[i].attached.handle); + port_info->phy_info[i].attached.phy_id = + port_info->phy_info[i].phy_id; } /* @@ -1360,6 +1367,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) return 0; out_free_port_info: + kfree(port_info->phy_info); kfree(port_info); out: return error; @@ -1485,6 +1493,7 @@ mptsas_hotplug_work(void *arg) if (phy_info->rphy) { sas_rphy_delete(phy_info->rphy); + memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); phy_info->rphy = NULL; } break; @@ -1955,6 +1964,8 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { list_del(&p->list); + if (p->phy_info) + kfree(p->phy_info); kfree(p); } mutex_unlock(&ioc->sas_topology_mutex); -- cgit v1.2.3-59-g8ed1b From f44e5461d919a344d44f7ca4f06cf8d169da8454 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:21 -0700 Subject: [SCSI] fusion - exposing raid components in mptsas Suppport for exposing hidden raid components for sg interface. The sdev->no_uld_attach flag will set set accordingly. The sas module supports adding/removing raid volumes using online storage management application interface. This patch rely's on patch's provided to me by Christoph Hellwig, that exports device_reprobe. I will post those patch's on behalf of Christoph. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 112 +++++++++++++++++++++++++++++--------- drivers/message/fusion/mptscsih.c | 21 ++++++- drivers/message/fusion/mptscsih.h | 1 + 3 files changed, 107 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index b6a6f27082b6..289fcdbe89ba 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -104,6 +104,8 @@ struct mptsas_hotplug_event { u16 handle; u16 parent_handle; u8 phy_id; + u8 phys_disk_num; + u8 phys_disk_num_valid; }; /* @@ -139,6 +141,7 @@ struct mptsas_phyinfo { struct mptsas_devinfo attached; /* point to attached device info */ struct sas_phy *phy; struct sas_rphy *rphy; + struct scsi_target *starget; }; struct mptsas_portinfo { @@ -388,6 +391,17 @@ mptsas_slave_alloc(struct scsi_device *sdev) target_id = p->phy_info[i].attached.id; vtarget->bus_id = p->phy_info[i].attached.channel; vdev->lun = sdev->lun; + p->phy_info[i].starget = sdev->sdev_target; + /* + * Exposing hidden disk (RAID) + */ + if (mptscsih_is_phys_disk(hd->ioc, target_id)) { + target_id = mptscsih_raid_id_to_num(hd, + target_id); + vdev->vtarget->tflags |= + MPT_TARGET_FLAGS_RAID_COMPONENT; + sdev->no_uld_attach = 1; + } mutex_unlock(&hd->ioc->sas_topology_mutex); goto out; } @@ -1378,10 +1392,24 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) { u32 handle = 0xFFFF; int index = 0; + int i; mptsas_probe_hba_phys(ioc, &index); while (!mptsas_probe_expander_phys(ioc, &handle, &index)) ; + /* + Reporting RAID volumes. + */ + if (!ioc->raid_data.pIocPg2) + goto out; + if (!ioc->raid_data.pIocPg2->NumActiveVolumes) + goto out; + for (i=0; iraid_data.pIocPg2->NumActiveVolumes; i++) { + scsi_add_device(ioc->sh, ioc->num_ports, + ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); + } + out: + return; } static struct mptsas_phyinfo * @@ -1460,6 +1488,20 @@ mptscsih_sas_persist_clear_table(void * arg) mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); } +static void +mptsas_reprobe_lun(struct scsi_device *sdev, void *data) +{ + sdev->no_uld_attach = data ? 1 : 0; + scsi_device_reprobe(sdev); +} + +static void +mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) +{ + starget_for_each_device(starget, uld_attach ? (void *)1 : NULL, + mptsas_reprobe_lun); +} + static void mptsas_hotplug_work(void *arg) { @@ -1470,14 +1512,33 @@ mptsas_hotplug_work(void *arg) struct scsi_device *sdev; char *ds = NULL; struct mptsas_devinfo sas_device; + VirtTarget *vtarget; switch (ev->event_type) { case MPTSAS_DEL_DEVICE: phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); - if (!phy_info) { - printk("mptsas: remove event for non-existant PHY.\n"); + /* + * Sanity checks, for non-existing phys and remote rphys. + */ + if (!phy_info) break; + if (!phy_info->rphy) + break; + if (phy_info->starget) { + vtarget = phy_info->starget->hostdata; + + if (!vtarget) + break; + /* + * Handling RAID components + */ + if (ev->phys_disk_num_valid) { + vtarget->target_id = ev->phys_disk_num; + vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; + mptsas_reprobe_target(vtarget->starget, 1); + break; + } } if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) @@ -1491,11 +1552,10 @@ mptsas_hotplug_work(void *arg) "removing %s device, channel %d, id %d, phy %d\n", ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); - if (phy_info->rphy) { - sas_rphy_delete(phy_info->rphy); - memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); - phy_info->rphy = NULL; - } + sas_rphy_delete(phy_info->rphy); + memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); + phy_info->rphy = NULL; + phy_info->starget = NULL; break; case MPTSAS_ADD_DEVICE: @@ -1509,16 +1569,27 @@ mptsas_hotplug_work(void *arg) phy_info = mptsas_find_phyinfo_by_parent(ioc, sas_device.handle_parent, sas_device.phy_id); - if (!phy_info) { - printk("mptsas: add event for non-existant PHY.\n"); + if (!phy_info) break; - } + if (phy_info->starget) { + vtarget = phy_info->starget->hostdata; - if (phy_info->rphy) { - printk("mptsas: trying to add existing device.\n"); + if (!vtarget) + break; + /* + * Handling RAID components + */ + if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { + vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; + vtarget->target_id = ev->id; + mptsas_reprobe_target(phy_info->starget, 0); + } break; } + if (phy_info->rphy) + break; + memcpy(&phy_info->attached, &sas_device, sizeof(struct mptsas_devinfo)); @@ -1672,6 +1743,9 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc, ev->event_type = MPTSAS_ADD_DEVICE; break; case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: + ioc->raid_data.isRaid = 1; + ev->phys_disk_num_valid = 1; + ev->phys_disk_num = raid_event_data->PhysDiskNum; ev->event_type = MPTSAS_DEL_DEVICE; break; case MPI_EVENT_RAID_RC_VOLUME_DELETED: @@ -1932,20 +2006,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) mptsas_scan_sas_topology(ioc); - /* - Reporting RAID volumes. - */ - if (!ioc->raid_data.pIocPg2) - return 0; - if (!ioc->raid_data.pIocPg2->NumActiveVolumes) - return 0; - for (ii=0;iiraid_data.pIocPg2->NumActiveVolumes;ii++) { - scsi_add_device(sh, - ioc->num_ports, - ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID, - 0); - } - return 0; out_mptsas_probe: diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index c99a918feb58..3729062db317 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1235,7 +1235,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return SCSI_MLQUEUE_HOST_BUSY; } - if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && + if ((hd->ioc->bus_type == SPI) && + vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); @@ -2103,6 +2104,24 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, return 0; } +/* Search IOC page 3 to determine if this is hidden physical disk + * + */ +int +mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) +{ + int i; + + if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) + return 0; + for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { + if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) + return 1; + } + return 0; +} +EXPORT_SYMBOL(mptscsih_is_phys_disk); + int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) { diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 2447a203513f..14a5b6c2e2bd 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -100,3 +100,4 @@ extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern void mptscsih_timer_expired(unsigned long data); extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid); +extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); -- cgit v1.2.3-59-g8ed1b From e6b2d76a49f0ee48527691867d8af2b8f9c10452 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:24 -0700 Subject: [SCSI] fusion - expander hotplug suport in mptsas module This adds support for hot adding and removing expanders, and its associated attached devices. When there is a change in topology, the fusion firmware sends the MPI_EVENT_SAS_DISCOVERY event to the driver. The driver will read firmware config pages to determine what changes took place, and refresh drivers view of the world stored in ioc->sas_topology. Here is the details of the action the driver does: (1) Expander Added : The mptsas_discovery_work workqueue is called. Config pages read, and ioc->sas_topology is refreshed. The sas_phy_add() is called for each phy of the expander. The expanders attached devices are added via sas_rphy_add(). Added end devices are handled within the MPT_ADD_DEVICE logic in mptsas_hotplug_work workqueue. (2) Expander Delete : The sas_rphy_delete() will be called for the top most compenent of the parent that the expander is attached to. The sas_rphy_delete call will delete all the children phys, rphys, and end devices. This is handled from mptsas_discovery_work workqueue. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 4 + drivers/message/fusion/mptsas.c | 354 +++++++++++++++++++++++++++++++-------- 2 files changed, 289 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 9b58234add36..892af47cb91c 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -619,6 +619,10 @@ typedef struct _MPT_ADAPTER struct net_device *netdev; struct list_head sas_topology; struct mutex sas_topology_mutex; + struct mutex sas_discovery_mutex; + u8 sas_discovery_runtime; + u8 sas_discovery_ignore_events; + int sas_index; /* index refrencing */ MPT_SAS_MGMT sas_mgmt; int num_ports; struct work_struct mptscsih_persistTask; diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 289fcdbe89ba..be4eb8a308b7 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -108,6 +108,11 @@ struct mptsas_hotplug_event { u8 phys_disk_num_valid; }; +struct mptsas_discovery_event { + struct work_struct work; + MPT_ADAPTER *ioc; +}; + /* * SAS topology structures * @@ -163,7 +168,6 @@ struct mptsas_enclosure { u8 sep_channel; /* SEP channel logical channel id */ }; - #ifdef SASDEBUG static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) { @@ -273,6 +277,27 @@ static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy) return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; } +/* + * mptsas_find_portinfo_by_handle + * + * This function should be called with the sas_topology_mutex already held + */ +static struct mptsas_portinfo * +mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) +{ + struct mptsas_portinfo *port_info, *rc=NULL; + int i; + + list_for_each_entry(port_info, &ioc->sas_topology, list) + for (i = 0; i < port_info->num_phys; i++) + if (port_info->phy_info[i].identify.handle == handle) { + rc = port_info; + goto out; + } + out: + return rc; +} + static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, u32 form, u32 form_specific) @@ -423,32 +448,8 @@ mptsas_slave_destroy(struct scsi_device *sdev) { struct Scsi_Host *host = sdev->host; MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; - struct sas_rphy *rphy; - struct mptsas_portinfo *p; - int i; VirtDevice *vdev; - /* - * Handle hotplug removal case. - * We need to clear out attached data structure. - */ - rphy = dev_to_rphy(sdev->sdev_target->dev.parent); - - mutex_lock(&hd->ioc->sas_topology_mutex); - list_for_each_entry(p, &hd->ioc->sas_topology, list) { - for (i = 0; i < p->num_phys; i++) { - if (p->phy_info[i].attached.sas_address == - rphy->identify.sas_address) { - memset(&p->phy_info[i].attached, 0, - sizeof(struct mptsas_devinfo)); - p->phy_info[i].rphy = NULL; - goto out; - } - } - } - - out: - mutex_unlock(&hd->ioc->sas_topology_mutex); /* * Issue target reset to flush firmware outstanding commands. */ @@ -1044,7 +1045,6 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle); phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle); - out_free_consistent: pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, buffer, dma_handle); @@ -1134,12 +1134,19 @@ mptsas_parse_device_info(struct sas_identify *identify, static int mptsas_probe_one_phy(struct device *dev, struct mptsas_phyinfo *phy_info, int index, int local) { + MPT_ADAPTER *ioc; struct sas_phy *phy; int error; - phy = sas_phy_alloc(dev, index); - if (!phy) - return -ENOMEM; + if (!dev) + return -ENODEV; + + if (!phy_info->phy) { + phy = sas_phy_alloc(dev, index); + if (!phy) + return -ENOMEM; + } else + phy = phy_info->phy; phy->port_identifier = phy_info->port_id; mptsas_parse_device_info(&phy->identify, &phy_info->identify); @@ -1225,19 +1232,35 @@ static int mptsas_probe_one_phy(struct device *dev, break; } - if (local) - phy->local_attached = 1; + if (!phy_info->phy) { - error = sas_phy_add(phy); - if (error) { - sas_phy_free(phy); - return error; + if (local) + phy->local_attached = 1; + + error = sas_phy_add(phy); + if (error) { + sas_phy_free(phy); + return error; + } + phy_info->phy = phy; } - phy_info->phy = phy; - if (phy_info->attached.handle) { + if ((phy_info->attached.handle) && + (!phy_info->rphy)) { + struct sas_rphy *rphy; + ioc = phy_to_ioc(phy_info->phy); + + /* + * Let the hotplug_work thread handle processing + * the adding/removing of devices that occur + * after start of day. + */ + if (ioc->sas_discovery_runtime && + mptsas_is_end_device(&phy_info->attached)) + return 0; + rphy = sas_rphy_alloc(phy); if (!rphy) return 0; /* non-fatal: an rphy can be added later */ @@ -1256,24 +1279,37 @@ static int mptsas_probe_one_phy(struct device *dev, } static int -mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) +mptsas_probe_hba_phys(MPT_ADAPTER *ioc) { - struct mptsas_portinfo *port_info; + struct mptsas_portinfo *port_info, *hba; u32 handle = 0xFFFF; int error = -ENOMEM, i; - port_info = kzalloc(sizeof(*port_info), GFP_KERNEL); - if (!port_info) + hba = kzalloc(sizeof(*port_info), GFP_KERNEL); + if (! hba) goto out; - error = mptsas_sas_io_unit_pg0(ioc, port_info); + error = mptsas_sas_io_unit_pg0(ioc, hba); if (error) goto out_free_port_info; - ioc->num_ports = port_info->num_phys; mutex_lock(&ioc->sas_topology_mutex); - list_add_tail(&port_info->list, &ioc->sas_topology); + port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle); + if (!port_info) { + port_info = hba; + list_add_tail(&port_info->list, &ioc->sas_topology); + } else { + port_info->handle = hba->handle; + for (i = 0; i < hba->num_phys; i++) + port_info->phy_info[i].negotiated_link_rate = + hba->phy_info[i].negotiated_link_rate; + if (hba->phy_info) + kfree(hba->phy_info); + kfree(hba); + hba = NULL; + } mutex_unlock(&ioc->sas_topology_mutex); + ioc->num_ports = port_info->num_phys; for (i = 0; i < port_info->num_phys; i++) { mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], @@ -1296,38 +1332,49 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) } mptsas_probe_one_phy(&ioc->sh->shost_gendev, - &port_info->phy_info[i], *index, 1); - (*index)++; + &port_info->phy_info[i], ioc->sas_index, 1); + ioc->sas_index++; } return 0; out_free_port_info: - kfree(port_info); + if (hba) + kfree(hba); out: return error; } static int -mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) +mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) { - struct mptsas_portinfo *port_info, *p; + struct mptsas_portinfo *port_info, *p, *ex; int error = -ENOMEM, i, j; - port_info = kzalloc(sizeof(*port_info), GFP_KERNEL); - if (!port_info) + ex = kzalloc(sizeof(*port_info), GFP_KERNEL); + if (!ex) goto out; - error = mptsas_sas_expander_pg0(ioc, port_info, + error = mptsas_sas_expander_pg0(ioc, ex, (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); if (error) goto out_free_port_info; - *handle = port_info->handle; + *handle = ex->handle; mutex_lock(&ioc->sas_topology_mutex); - list_add_tail(&port_info->list, &ioc->sas_topology); + port_info = mptsas_find_portinfo_by_handle(ioc, *handle); + if (!port_info) { + port_info = ex; + list_add_tail(&port_info->list, &ioc->sas_topology); + } else { + port_info->handle = ex->handle; + if (ex->phy_info) + kfree(ex->phy_info); + kfree(ex); + ex = NULL; + } mutex_unlock(&ioc->sas_topology_mutex); for (i = 0; i < port_info->num_phys; i++) { @@ -1374,28 +1421,101 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) mutex_unlock(&ioc->sas_topology_mutex); mptsas_probe_one_phy(parent, &port_info->phy_info[i], - *index, 0); - (*index)++; + ioc->sas_index, 0); + ioc->sas_index++; } return 0; out_free_port_info: - kfree(port_info->phy_info); - kfree(port_info); + if (ex) { + if (ex->phy_info) + kfree(ex->phy_info); + kfree(ex); + } out: return error; } +/* + * mptsas_delete_expander_phys + * + * + * This will traverse topology, and remove expanders + * that are no longer present + */ +static void +mptsas_delete_expander_phys(MPT_ADAPTER *ioc) +{ + struct mptsas_portinfo buffer; + struct mptsas_portinfo *port_info, *n, *parent; + int i; + + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) { + + if (port_info->phy_info && + (!(port_info->phy_info[0].identify.device_info & + MPI_SAS_DEVICE_INFO_SMP_TARGET))) + continue; + + if (mptsas_sas_expander_pg0(ioc, &buffer, + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << + MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) { + + /* + * Obtain the port_info instance to the parent port + */ + parent = mptsas_find_portinfo_by_handle(ioc, + port_info->phy_info[0].identify.handle_parent); + + if (!parent) + goto next_port; + + /* + * Delete rphys in the parent that point + * to this expander. The transport layer will + * cleanup all the children. + */ + for (i = 0; i < parent->num_phys; i++) { + if ((!parent->phy_info[i].rphy) || + (parent->phy_info[i].attached.sas_address != + port_info->phy_info[i].identify.sas_address)) + continue; + sas_rphy_delete(parent->phy_info[i].rphy); + memset(&parent->phy_info[i].attached, 0, + sizeof(struct mptsas_devinfo)); + parent->phy_info[i].rphy = NULL; + parent->phy_info[i].starget = NULL; + } + next_port: + list_del(&port_info->list); + if (port_info->phy_info) + kfree(port_info->phy_info); + kfree(port_info); + } + /* + * Free this memory allocated from inside + * mptsas_sas_expander_pg0 + */ + if (buffer.phy_info) + kfree(buffer.phy_info); + } + mutex_unlock(&ioc->sas_topology_mutex); +} + +/* + * Start of day discovery + */ static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc) { u32 handle = 0xFFFF; - int index = 0; int i; - mptsas_probe_hba_phys(ioc, &index); - while (!mptsas_probe_expander_phys(ioc, &handle, &index)) + mutex_lock(&ioc->sas_discovery_mutex); + mptsas_probe_hba_phys(ioc); + while (!mptsas_probe_expander_phys(ioc, &handle)) ; /* Reporting RAID volumes. @@ -1409,7 +1529,29 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); } out: - return; + mutex_unlock(&ioc->sas_discovery_mutex); +} + +/* + * Work queue thread to handle Runtime discovery + * Mere purpose is the hot add/delete of expanders + */ +static void +mptscsih_discovery_work(void * arg) +{ + struct mptsas_discovery_event *ev = arg; + MPT_ADAPTER *ioc = ev->ioc; + u32 handle = 0xFFFF; + + mutex_lock(&ioc->sas_discovery_mutex); + ioc->sas_discovery_runtime=1; + mptsas_delete_expander_phys(ioc); + mptsas_probe_hba_phys(ioc); + while (!mptsas_probe_expander_phys(ioc, &handle)) + ; + kfree(ev); + ioc->sas_discovery_runtime=0; + mutex_unlock(&ioc->sas_discovery_mutex); } static struct mptsas_phyinfo * @@ -1427,10 +1569,8 @@ mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id) (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << MPI_SAS_DEVICE_PGAD_FORM_SHIFT), parent_handle); - if (error) { - printk("mptsas: failed to retrieve device page\n"); + if (error) return NULL; - } /* * The phy_info structures are never deallocated during lifetime of @@ -1502,6 +1642,10 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) mptsas_reprobe_lun); } + +/* + * Work queue thread to handle SAS hotplug events + */ static void mptsas_hotplug_work(void *arg) { @@ -1514,10 +1658,13 @@ mptsas_hotplug_work(void *arg) struct mptsas_devinfo sas_device; VirtTarget *vtarget; + mutex_lock(&ioc->sas_discovery_mutex); + switch (ev->event_type) { case MPTSAS_DEL_DEVICE: phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); + /* * Sanity checks, for non-existing phys and remote rphys. */ @@ -1569,8 +1716,36 @@ mptsas_hotplug_work(void *arg) phy_info = mptsas_find_phyinfo_by_parent(ioc, sas_device.handle_parent, sas_device.phy_id); - if (!phy_info) - break; + + if (!phy_info) { + u32 handle = 0xFFFF; + + /* + * Its possible when an expander has been hot added + * containing attached devices, the sas firmware + * may send a RC_ADDED event prior to the + * DISCOVERY STOP event. If that occurs, our + * view of the topology in the driver in respect to this + * expander might of not been setup, and we hit this + * condition. + * Therefore, this code kicks off discovery to + * refresh the data. + * Then again, we check whether the parent phy has + * been created. + */ + ioc->sas_discovery_runtime=1; + mptsas_delete_expander_phys(ioc); + mptsas_probe_hba_phys(ioc); + while (!mptsas_probe_expander_phys(ioc, &handle)) + ; + ioc->sas_discovery_runtime=0; + + phy_info = mptsas_find_phyinfo_by_parent(ioc, + sas_device.handle_parent, sas_device.phy_id); + if (!phy_info) + break; + } + if (phy_info->starget) { vtarget = phy_info->starget->hostdata; @@ -1604,7 +1779,6 @@ mptsas_hotplug_work(void *arg) "attaching %s device, channel %d, id %d, phy %d\n", ioc->name, ds, ev->channel, ev->id, ev->phy_id); - rphy = sas_rphy_alloc(phy_info->phy); if (!rphy) break; /* non-fatal: an rphy can be added later */ @@ -1654,6 +1828,7 @@ mptsas_hotplug_work(void *arg) } kfree(ev); + mutex_unlock(&ioc->sas_discovery_mutex); } static void @@ -1767,6 +1942,32 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc, schedule_work(&ev->work); } +static void +mptscsih_send_discovery(MPT_ADAPTER *ioc, + EVENT_DATA_SAS_DISCOVERY *discovery_data) +{ + struct mptsas_discovery_event *ev; + + /* + * DiscoveryStatus + * + * This flag will be non-zero when firmware + * kicks off discovery, and return to zero + * once its completed. + */ + if (discovery_data->DiscoveryStatus) + return; + + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) + return; + memset(ev,0,sizeof(struct mptsas_discovery_event)); + INIT_WORK(&ev->work, mptscsih_discovery_work, ev); + ev->ioc = ioc; + schedule_work(&ev->work); +}; + + static int mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) { @@ -1776,6 +1977,17 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) if (!ioc->sh) goto out; + /* + * sas_discovery_ignore_events + * + * This flag is to prevent anymore processing of + * sas events once mptsas_remove function is called. + */ + if (ioc->sas_discovery_ignore_events) { + rc = mptscsih_event_process(ioc, reply); + goto out; + } + switch (event) { case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: mptscsih_send_sas_event(ioc, @@ -1792,6 +2004,9 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) schedule_work(&ioc->mptscsih_persistTask); break; case MPI_EVENT_SAS_DISCOVERY: + mptscsih_send_discovery(ioc, + (EVENT_DATA_SAS_DISCOVERY *)reply->Data); + break; default: rc = mptscsih_event_process(ioc, reply); break; @@ -1893,7 +2108,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&ioc->sas_topology); mutex_init(&ioc->sas_topology_mutex); - + mutex_init(&ioc->sas_discovery_mutex); mutex_init(&ioc->sas_mgmt.mutex); init_completion(&ioc->sas_mgmt.done); @@ -2019,6 +2234,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct mptsas_portinfo *p, *n; + ioc->sas_discovery_ignore_events=1; sas_remove_host(ioc->sh); mutex_lock(&ioc->sas_topology_mutex); -- cgit v1.2.3-59-g8ed1b From 9dec70e053613c31e8feab9e14607eaaed99d77c Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:26 -0700 Subject: [SCSI] fusion - bump version version bump Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 892af47cb91c..be7e8501b53c 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.07" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.07" +#define MPT_LINUX_VERSION_COMMON "3.03.08" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.08" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ -- cgit v1.2.3-59-g8ed1b From a50a5e3792a6c65f95dab547dba45608bd193404 Mon Sep 17 00:00:00 2001 From: Mike Anderson Date: Tue, 14 Mar 2006 11:18:46 -0800 Subject: [SCSI] scsi: move target_destroy call This patch moves the calling of target_destroy next to the list_del. This closed a race being seen while doing a device add on the aic7xxx. Signed-off-by: Mike Anderson Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 9cd4404cf9ab..f14945996ede 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -288,10 +288,7 @@ static void scsi_target_dev_release(struct device *dev) { struct device *parent = dev->parent; struct scsi_target *starget = to_scsi_target(dev); - struct Scsi_Host *shost = dev_to_shost(parent); - if (shost->hostt->target_destroy) - shost->hostt->target_destroy(starget); kfree(starget); put_device(parent); } @@ -416,6 +413,8 @@ static void scsi_target_reap_usercontext(void *data) device_del(&starget->dev); transport_destroy_device(&starget->dev); spin_lock_irqsave(shost->host_lock, flags); + if (shost->hostt->target_destroy) + shost->hostt->target_destroy(starget); list_del_init(&starget->siblings); spin_unlock_irqrestore(shost->host_lock, flags); put_device(&starget->dev); -- cgit v1.2.3-59-g8ed1b From e843e280cbe218fc8387339806d344708dee348a Mon Sep 17 00:00:00 2001 From: Greg Smith Date: Tue, 14 Mar 2006 19:50:17 -0800 Subject: [PATCH] "s390: multiple subchannel sets support" fix It seems this patch got dropped (it was in addition to the `s390: improve response code handling in chsc_enable_facility()' patch). Acked-by: Cornelia Huck Cc: Martin Schwidefsky Cc: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/css.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 1bbf231f8aaf..3c77d65960db 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -409,6 +409,9 @@ __init_channel_subsystem(struct subchannel_id schid, void *data) /* -ENXIO: no more subchannels. */ case -ENXIO: return ret; + /* -EIO: this subchannel set not supported. */ + case -EIO: + return ret; default: return 0; } -- cgit v1.2.3-59-g8ed1b From aa49cdd93be6328113f0c146fc72be173d578d27 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 15 Mar 2006 10:55:24 -0800 Subject: e100: fix eeh on pseries during ethtool -t Olaf Hering reported a problem on pseries with e100 where ethtool -t would cause a bus error, and the e100 driver would stop working. Due to the new load ucode command the cb list must be allocated before calling e100_init_hw, so remove the call and just let e100_up take care of it. Signed-off-by: Jesse Brandeburg --- drivers/net/e100.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 24253c807e55..f57a85feda3d 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2154,6 +2154,9 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) msleep(10); + pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, + RFD_BUF_LEN, PCI_DMA_FROMDEVICE); + if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), skb->data, ETH_DATA_LEN)) err = -EAGAIN; @@ -2161,8 +2164,8 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) err_loopback_none: mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); nic->loopback = lb_none; - e100_hw_init(nic); e100_clean_cbs(nic); + e100_hw_reset(nic); err_clean_rx: e100_rx_clean_list(nic); return err; -- cgit v1.2.3-59-g8ed1b From c3d7a3a4eb5e8f290d7b1d61430eed1ebedeb936 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 15 Mar 2006 14:26:28 -0800 Subject: [PATCH] e1000 endianness bugs return -E_NO_BIG_ENDIAN_TESTING; [E1000]: Fix 4 missed endianness conversions on RX descriptor fields. Signed-off-by: David S. Miller Signed-off-by: Jeff Garzik --- drivers/net/e1000/e1000_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 4c4db96d0b7b..84dcca3776ee 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3710,7 +3710,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, e1000_rx_checksum(adapter, (uint32_t)(status) | ((uint32_t)(rx_desc->errors) << 24), - rx_desc->csum, skb); + le16_to_cpu(rx_desc->csum), skb); skb->protocol = eth_type_trans(skb, netdev); #ifdef CONFIG_E1000_NAPI @@ -3854,11 +3854,11 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, } e1000_rx_checksum(adapter, staterr, - rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); + le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb); skb->protocol = eth_type_trans(skb, netdev); if (likely(rx_desc->wb.upper.header_status & - E1000_RXDPS_HDRSTAT_HDRSP)) + cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))) adapter->rx_hdr_split++; #ifdef CONFIG_E1000_NAPI if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { @@ -3884,7 +3884,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, #endif next_desc: - rx_desc->wb.middle.status_error &= ~0xFF; + rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF); buffer_info->skb = NULL; /* return some buffers to hardware, one at a time is too slow */ -- cgit v1.2.3-59-g8ed1b From 232a347a444e687b5f8cf0f6485704db1c6024d3 Mon Sep 17 00:00:00 2001 From: Scott Bardone Date: Thu, 16 Mar 2006 19:20:40 -0500 Subject: [netdrvr] fix array overflows in Chelsio driver Adrian Bunk wrote: > The Coverity checker spotted the following two array overflows in > drivers/net/chelsio/sge.c (in both cases, the arrays contain 3 > elements): [snip] This is a bug. The array should contain 2 elements. Here is the fix. Signed-off-by: Scott Bardone Signed-off-by: Jeff Garzik --- drivers/net/chelsio/sge.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 2c5b849b7ba4..30ff8ea1a402 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -1021,7 +1021,7 @@ static void restart_tx_queues(struct sge *sge) if (test_and_clear_bit(nd->if_port, &sge->stopped_tx_queues) && netif_running(nd)) { - sge->stats.cmdQ_restarted[3]++; + sge->stats.cmdQ_restarted[2]++; netif_wake_queue(nd); } } @@ -1350,7 +1350,7 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter, if (unlikely(credits < count)) { netif_stop_queue(dev); set_bit(dev->if_port, &sge->stopped_tx_queues); - sge->stats.cmdQ_full[3]++; + sge->stats.cmdQ_full[2]++; spin_unlock(&q->lock); if (!netif_queue_stopped(dev)) CH_ERR("%s: Tx ring full while queue awake!\n", @@ -1358,7 +1358,7 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter, return NETDEV_TX_BUSY; } if (unlikely(credits - count < q->stop_thres)) { - sge->stats.cmdQ_full[3]++; + sge->stats.cmdQ_full[2]++; netif_stop_queue(dev); set_bit(dev->if_port, &sge->stopped_tx_queues); } -- cgit v1.2.3-59-g8ed1b From 1148c3a78aa9f1e84229cd17f94fd38a15ca65bd Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 13 Mar 2006 19:48:04 +0900 Subject: [PATCH] libata: use local *id instead of dev->id in ata_dev_configure() dev->id is used many times in ata_dev_configure(). Use local variable id instead for shorter notation. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 439b6db13802..6fe41fb03929 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1193,6 +1193,7 @@ static inline u8 ata_dev_knobble(const struct ata_port *ap, static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, int print_info) { + const u16 *id = dev->id; unsigned int xfer_mask; int i, rc; @@ -1218,27 +1219,27 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, */ /* we require DMA support (bits 8 of word 49) */ - if (!ata_id_has_dma(dev->id)) { + if (!ata_id_has_dma(id)) { printk(KERN_DEBUG "ata%u: no dma\n", ap->id); rc = -EINVAL; goto err_out_nosup; } /* find max transfer mode; for printk only */ - xfer_mask = ata_id_xfermask(dev->id); + xfer_mask = ata_id_xfermask(id); - ata_dump_id(dev->id); + ata_dump_id(id); /* ATA-specific feature tests */ if (dev->class == ATA_DEV_ATA) { - dev->n_sectors = ata_id_n_sectors(dev->id); + dev->n_sectors = ata_id_n_sectors(id); - if (ata_id_has_lba(dev->id)) { + if (ata_id_has_lba(id)) { const char *lba_desc; lba_desc = "LBA"; dev->flags |= ATA_DFLAG_LBA; - if (ata_id_has_lba48(dev->id)) { + if (ata_id_has_lba48(id)) { dev->flags |= ATA_DFLAG_LBA48; lba_desc = "LBA48"; } @@ -1248,7 +1249,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, printk(KERN_INFO "ata%u: dev %u ATA-%d, " "max %s, %Lu sectors: %s\n", ap->id, dev->devno, - ata_id_major_version(dev->id), + ata_id_major_version(id), ata_mode_string(xfer_mask), (unsigned long long)dev->n_sectors, lba_desc); @@ -1256,15 +1257,15 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, /* CHS */ /* Default translation */ - dev->cylinders = dev->id[1]; - dev->heads = dev->id[3]; - dev->sectors = dev->id[6]; + dev->cylinders = id[1]; + dev->heads = id[3]; + dev->sectors = id[6]; - if (ata_id_current_chs_valid(dev->id)) { + if (ata_id_current_chs_valid(id)) { /* Current CHS translation is valid. */ - dev->cylinders = dev->id[54]; - dev->heads = dev->id[55]; - dev->sectors = dev->id[56]; + dev->cylinders = id[54]; + dev->heads = id[55]; + dev->sectors = id[56]; } /* print device info to dmesg */ @@ -1272,7 +1273,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, 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(dev->id), + ata_id_major_version(id), ata_mode_string(xfer_mask), (unsigned long long)dev->n_sectors, dev->cylinders, dev->heads, dev->sectors); @@ -1283,7 +1284,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, /* ATAPI-specific feature tests */ else if (dev->class == ATA_DEV_ATAPI) { - rc = atapi_cdb_len(dev->id); + rc = atapi_cdb_len(id); if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); rc = -EINVAL; -- cgit v1.2.3-59-g8ed1b From c39f5ebe0a542caab30c88e60623709c7bc6fe30 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 13 Mar 2006 19:51:19 +0900 Subject: [PATCH] libata: move IDENTIFY info printing from ata_dev_read_id() to ata_dev_configure() Move IDENTIFY info printing from ata_dev_read_id() to ata_dev_configure() and print only if @print_info is non-zero. This kills duplicate IDENTIFY info printing during probing. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 6fe41fb03929..714b42bad935 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1120,12 +1120,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, swap_buf_le16(id, ATA_ID_WORDS); - /* print device capabilities */ - 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]); - /* sanity check */ if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) { rc = -EINVAL; @@ -1205,6 +1199,13 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); + /* 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]); + /* initialize to-be-configured parameters */ dev->flags = 0; dev->max_sectors = 0; -- cgit v1.2.3-59-g8ed1b From 9b15879aefe6a4c2236297df68c46498af26143d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 15 Mar 2006 11:30:44 +0100 Subject: [PATCH] spidernet: select FW_LOADER The spidernet drivers uses request_firmware() and thus needs to select FW_LOADER. Signed-off-by: Christoph Hellwig Signed-off-by: Paul Mackerras --- drivers/net/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index aa633fa95e64..8c1ad0fac7b6 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2176,6 +2176,7 @@ config BNX2 config SPIDER_NET tristate "Spider Gigabit Ethernet driver" depends on PCI && PPC_CELL + select FW_LOADER help This driver supports the Gigabit Ethernet chips present on the Cell Processor-Based Blades from IBM. -- cgit v1.2.3-59-g8ed1b From 8ba32fde2c5be52865b2fd7e5e3752a46971fabe Mon Sep 17 00:00:00 2001 From: Kevin Corry Date: Thu, 16 Mar 2006 23:04:03 -0800 Subject: [PATCH] dm stripe: Fix bounds The dm-stripe target currently does not enforce that the size of a stripe device be a multiple of the chunk-size. Under certain conditions, this can lead to I/O requests going off the end of an underlying device. This test-case shows one example. echo "0 100 linear /dev/hdb1 0" | dmsetup create linear0 echo "0 100 linear /dev/hdb1 100" | dmsetup create linear1 echo "0 200 striped 2 32 /dev/mapper/linear0 0 /dev/mapper/linear1 0" | \ dmsetup create stripe0 dd if=/dev/zero of=/dev/mapper/stripe0 bs=1k This will produce the output: dd: writing '/dev/mapper/stripe0': Input/output error 97+0 records in 96+0 records out And in the kernel log will be: attempt to access beyond end of device dm-0: rw=0, want=104, limit=100 The patch will check that the table size is a multiple of the stripe chunk-size when the table is created, which will prevent the above striped device from being created. This should not affect tools like LVM or EVMS, since in all the cases I can think of, striped devices are always created with the sizes being a multiple of the chunk-size. The size of a stripe device must be a multiple of its chunk-size. (akpm: that typecast is quite gratuitous) Signed-off-by: Kevin Corry Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-stripe.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index ab89278a56bf..697aacafb02a 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -103,9 +103,15 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) return -EINVAL; } + if (((uint32_t)ti->len) & (chunk_size - 1)) { + ti->error = "dm-stripe: Target length not divisible by " + "chunk size"; + return -EINVAL; + } + width = ti->len; if (sector_div(width, stripes)) { - ti->error = "dm-stripe: Target length not divisable by " + ti->error = "dm-stripe: Target length not divisible by " "number of stripes"; return -EINVAL; } -- cgit v1.2.3-59-g8ed1b From 1867b117d944ce333e79b9a61c9a048656bee14b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 28 Feb 2006 09:48:28 -0600 Subject: [PATCH] Remove duplicated code from ipw2200.c As stated in a comment, the ipw2200 driver uses several routines that were borrowed from ieee80211_geo.c. As ipw2200 requires ieee80211, these routines are duplicated. The attached patch, which is sent as an attachment to preserve whitespace, converts ipw2200.c to use the ieee80211 versions, thereby reducing bloat in both the source and binary. Signed-Off-By: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 128 ++++++----------------------------------- 1 file changed, 16 insertions(+), 112 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index ed37141319ea..77932cf85008 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -153,12 +153,6 @@ static int init_supported_rates(struct ipw_priv *priv, static void ipw_set_hwcrypto_keys(struct ipw_priv *); static void ipw_send_wep_keys(struct ipw_priv *, int); -static int ipw_is_valid_channel(struct ieee80211_device *, u8); -static int ipw_channel_to_index(struct ieee80211_device *, u8); -static u8 ipw_freq_to_channel(struct ieee80211_device *, u32); -static int ipw_set_geo(struct ieee80211_device *, const struct ieee80211_geo *); -static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *); - static int snprint_line(char *buf, size_t count, const u8 * data, u32 len, u32 ofs) { @@ -1654,7 +1648,7 @@ static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr, break; } - if (ipw_is_valid_channel(priv->ieee, channel)) + if (ieee80211_is_valid_channel(priv->ieee, channel)) priv->speed_scan[pos++] = channel; else IPW_WARNING("Skipping invalid channel request: %d\n", @@ -2222,7 +2216,7 @@ static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) static int ipw_set_tx_power(struct ipw_priv *priv) { - const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); + const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); struct ipw_tx_power tx_power; s8 max_power; int i; @@ -5562,7 +5556,7 @@ static int ipw_best_network(struct ipw_priv *priv, } /* Filter out invalid channel in current GEO */ - if (!ipw_is_valid_channel(priv->ieee, network->channel)) { + if (!ieee80211_is_valid_channel(priv->ieee, network->channel)) { IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " "because of invalid channel in current GEO\n", escape_essid(network->ssid, network->ssid_len), @@ -5607,7 +5601,7 @@ static int ipw_best_network(struct ipw_priv *priv, static void ipw_adhoc_create(struct ipw_priv *priv, struct ieee80211_network *network) { - const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); + const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); int i; /* @@ -5622,10 +5616,10 @@ static void ipw_adhoc_create(struct ipw_priv *priv, * FW fatal error. * */ - switch (ipw_is_valid_channel(priv->ieee, priv->channel)) { + switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { case IEEE80211_52GHZ_BAND: network->mode = IEEE_A; - i = ipw_channel_to_index(priv->ieee, priv->channel); + i = ieee80211_channel_to_index(priv->ieee, priv->channel); if (i == -1) BUG(); if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { @@ -5639,7 +5633,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv, network->mode = IEEE_G; else network->mode = IEEE_B; - i = ipw_channel_to_index(priv->ieee, priv->channel); + i = ieee80211_channel_to_index(priv->ieee, priv->channel); if (i == -1) BUG(); if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) { @@ -5963,7 +5957,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, const struct ieee80211_geo *geo; int i; - geo = ipw_get_geo(priv->ieee); + geo = ieee80211_get_geo(priv->ieee); if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { int start = channel_index; @@ -6023,7 +6017,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, channel_index++; scan->channels_list[channel_index] = channel; index = - ipw_channel_to_index(priv->ieee, channel); + ieee80211_channel_to_index(priv->ieee, channel); ipw_set_scan_type(scan, channel_index, geo->bg[index]. flags & @@ -6105,7 +6099,7 @@ static int ipw_request_scan(struct ipw_priv *priv) u8 channel; u8 band = 0; - switch (ipw_is_valid_channel(priv->ieee, priv->channel)) { + switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { case IEEE80211_52GHZ_BAND: band = (u8) (IPW_A_MODE << 6) | 1; channel = priv->channel; @@ -8200,7 +8194,7 @@ static int ipw_wx_set_freq(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); + const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); struct iw_freq *fwrq = &wrqu->freq; int ret = 0, i; u8 channel, flags; @@ -8215,17 +8209,17 @@ static int ipw_wx_set_freq(struct net_device *dev, } /* if setting by freq convert to channel */ if (fwrq->e == 1) { - channel = ipw_freq_to_channel(priv->ieee, fwrq->m); + channel = ieee80211_freq_to_channel(priv->ieee, fwrq->m); if (channel == 0) return -EINVAL; } else channel = fwrq->m; - if (!(band = ipw_is_valid_channel(priv->ieee, channel))) + if (!(band = ieee80211_is_valid_channel(priv->ieee, channel))) return -EINVAL; if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - i = ipw_channel_to_index(priv->ieee, channel); + i = ieee80211_channel_to_index(priv->ieee, channel); if (i == -1) return -EINVAL; @@ -8353,7 +8347,7 @@ static int ipw_wx_get_range(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); struct iw_range *range = (struct iw_range *)extra; - const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); + const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); int i = 0, j; wrqu->data.length = sizeof(*range); @@ -10617,96 +10611,6 @@ static const struct ieee80211_geo ipw_geos[] = { } }; -/* GEO code borrowed from ieee80211_geo.c */ -static int ipw_is_valid_channel(struct ieee80211_device *ieee, u8 channel) -{ - int i; - - /* Driver needs to initialize the geography map before using - * these helper functions */ - BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); - - if (ieee->freq_band & IEEE80211_24GHZ_BAND) - for (i = 0; i < ieee->geo.bg_channels; i++) - /* NOTE: If G mode is currently supported but - * this is a B only channel, we don't see it - * as valid. */ - if ((ieee->geo.bg[i].channel == channel) && - (!(ieee->mode & IEEE_G) || - !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY))) - return IEEE80211_24GHZ_BAND; - - if (ieee->freq_band & IEEE80211_52GHZ_BAND) - for (i = 0; i < ieee->geo.a_channels; i++) - if (ieee->geo.a[i].channel == channel) - return IEEE80211_52GHZ_BAND; - - return 0; -} - -static int ipw_channel_to_index(struct ieee80211_device *ieee, u8 channel) -{ - int i; - - /* Driver needs to initialize the geography map before using - * these helper functions */ - BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); - - if (ieee->freq_band & IEEE80211_24GHZ_BAND) - for (i = 0; i < ieee->geo.bg_channels; i++) - if (ieee->geo.bg[i].channel == channel) - return i; - - if (ieee->freq_band & IEEE80211_52GHZ_BAND) - for (i = 0; i < ieee->geo.a_channels; i++) - if (ieee->geo.a[i].channel == channel) - return i; - - return -1; -} - -static u8 ipw_freq_to_channel(struct ieee80211_device *ieee, u32 freq) -{ - int i; - - /* Driver needs to initialize the geography map before using - * these helper functions */ - BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); - - freq /= 100000; - - if (ieee->freq_band & IEEE80211_24GHZ_BAND) - for (i = 0; i < ieee->geo.bg_channels; i++) - if (ieee->geo.bg[i].freq == freq) - return ieee->geo.bg[i].channel; - - if (ieee->freq_band & IEEE80211_52GHZ_BAND) - for (i = 0; i < ieee->geo.a_channels; i++) - if (ieee->geo.a[i].freq == freq) - return ieee->geo.a[i].channel; - - return 0; -} - -static int ipw_set_geo(struct ieee80211_device *ieee, - const struct ieee80211_geo *geo) -{ - memcpy(ieee->geo.name, geo->name, 3); - ieee->geo.name[3] = '\0'; - ieee->geo.bg_channels = geo->bg_channels; - ieee->geo.a_channels = geo->a_channels; - memcpy(ieee->geo.bg, geo->bg, geo->bg_channels * - sizeof(struct ieee80211_channel)); - memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels * - sizeof(struct ieee80211_channel)); - return 0; -} - -static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *ieee) -{ - return &ieee->geo; -} - #define MAX_HW_RESTARTS 5 static int ipw_up(struct ipw_priv *priv) { @@ -10753,7 +10657,7 @@ static int ipw_up(struct ipw_priv *priv) priv->eeprom[EEPROM_COUNTRY_CODE + 2]); j = 0; } - if (ipw_set_geo(priv->ieee, &ipw_geos[j])) { + if (ieee80211_set_geo(priv->ieee, &ipw_geos[j])) { IPW_WARNING("Could not set geography."); return 0; } -- cgit v1.2.3-59-g8ed1b From 53d0bcf82a5f59c96f1ffb202c02d2541200bf58 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 4 Mar 2006 13:14:31 +0100 Subject: [PATCH] drivers/net/wireless/ipw2200.c: make ipw_qos_current_mode() static This patch makes the needlessly global function ipw_qos_current_mode() static. Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 77932cf85008..d8a2a6fa72e3 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -6562,7 +6562,7 @@ static int ipw_wx_set_mlme(struct net_device *dev, * get the modulation type of the current network or * the card current mode */ -u8 ipw_qos_current_mode(struct ipw_priv * priv) +static u8 ipw_qos_current_mode(struct ipw_priv * priv) { u8 mode = 0; -- cgit v1.2.3-59-g8ed1b From 48a847709f821b5eecd45ae7660add1869f9cd37 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 14 Feb 2006 09:09:52 +0800 Subject: [PATCH] ipw2200: print geography code upon module load Given the amount of support requests for the meaning of the geography code I've written a patch for printing this information on module load no matter the debug level. I've also added a section to the README.ipw2200 file listing the geography codes and their meaning. Signed-off-by: Henrik Brix Andersen Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- Documentation/networking/README.ipw2200 | 30 ++++++++++++++++++++++++++++++ drivers/net/wireless/ipw2200.c | 12 +++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/README.ipw2200 b/Documentation/networking/README.ipw2200 index c6492d3839fa..712c5681338b 100644 --- a/Documentation/networking/README.ipw2200 +++ b/Documentation/networking/README.ipw2200 @@ -26,6 +26,7 @@ Index 1.2. Module parameters 1.3. Wireless Extension Private Methods 1.4. Sysfs Helper Files +1.5. Supported channels 2. Ad-Hoc Networking 3. Interacting with Wireless Tools 3.1. iwconfig mode @@ -314,6 +315,35 @@ For the device level files, see /sys/bus/pci/drivers/ipw2200: running ifconfig and is therefore disabled by default. +1.5. Supported channels +----------------------------------------------- + +Upon loading the Intel(R) PRO/Wireless 2915ABG Driver for Linux, a +message stating the detected geography code and the number of 802.11 +channels supported by the card will be displayed in the log. + +The geography code corresponds to a regulatory domain as shown in the +table below. + + Supported channels +Code Geography 802.11bg 802.11a + +--- Restricted 11 0 +ZZF Custom US/Canada 11 8 +ZZD Rest of World 13 0 +ZZA Custom USA & Europe & High 11 13 +ZZB Custom NA & Europe 11 13 +ZZC Custom Japan 11 4 +ZZM Custom 11 0 +ZZE Europe 13 19 +ZZJ Custom Japan 14 4 +ZZR Rest of World 14 0 +ZZH High Band 13 4 +ZZG Custom Europe 13 4 +ZZK Europe 13 24 +ZZL Europe 11 13 + + 2. Ad-Hoc Networking ----------------------------------------------- diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index d8a2a6fa72e3..a7483809d872 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -10364,6 +10364,9 @@ static int ipw_config(struct ipw_priv *priv) * not intended for resale of the above mentioned Intel adapters has * not been tested. * + * Remember to update the table in README.ipw2200 when changing this + * table. + * */ static const struct ieee80211_geo ipw_geos[] = { { /* Restricted */ @@ -10662,9 +10665,6 @@ static int ipw_up(struct ipw_priv *priv) return 0; } - IPW_DEBUG_INFO("Geography %03d [%s] detected.\n", - j, priv->ieee->geo.name); - if (priv->status & STATUS_RF_KILL_SW) { IPW_WARNING("Radio disabled by module parameter.\n"); return 0; @@ -10985,6 +10985,12 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) IPW_ERROR("failed to register network device\n"); goto out_remove_sysfs; } + + printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg " + "channels, %d 802.11a channels)\n", + priv->ieee->geo.name, priv->ieee->geo.bg_channels, + priv->ieee->geo.a_channels); + return 0; out_remove_sysfs: -- cgit v1.2.3-59-g8ed1b From f697014af90c1db3c7b299327bf5a9548945b8bf Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Tue, 14 Feb 2006 09:10:51 +0800 Subject: [PATCH] ipw2200: stop netdev queue if h/w doesn't have space for new packets The patch roll back the change we made to support for the ability to start/stop independent Tx queues within a single net device in order to support 802.11e QoS. We need to be able to indicate to the upper layers that packets of a given priority can not be sent any more without halting transmission of all packets, and without rescheduling high priority packets down to the next priority level. So we return NETDEV_TX_BUSY in this case and rely on the stack would take care of rescheduling... which it apparently does immediately and consumes the CPU. This caused the ksoftirqd kernel thread consuming almost all the CPU... To put the code back to the way it was before we made these changes we put the call netif_queue_stop back in ipw_tx_skb. This effectively disables multiple priority based transmit queues for 802.11e, but given that its broken anyway... Signed-off-by: James Ketrenos Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index a7483809d872..4722de13f1db 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -9648,11 +9648,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, u16 remaining_bytes; int fc; - /* If there isn't room in the queue, we return busy and let the - * network stack requeue the packet for us */ - if (ipw_queue_space(q) < q->high_mark) - return NETDEV_TX_BUSY; - switch (priv->ieee->iw_mode) { case IW_MODE_ADHOC: hdr_len = IEEE80211_3ADDR_LEN; @@ -9818,6 +9813,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd); ipw_write32(priv, q->reg_w, q->first_empty); + if (ipw_queue_space(q) < q->high_mark) + netif_stop_queue(priv->net_dev); + return NETDEV_TX_OK; drop: -- cgit v1.2.3-59-g8ed1b From 85149bace30eae1dc1f86d2c327329673123dd22 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 14 Feb 2006 16:02:22 +0800 Subject: [PATCH] ipw2200: fix a potential NULL pointer dereference Only on CONFIG_IPW2200_DEBUG is not defined Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 4722de13f1db..129891feb43f 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7809,12 +7809,10 @@ static void ipw_rx(struct ipw_priv *priv) while (i != r) { rxb = priv->rxq->queue[i]; -#ifdef CONFIG_IPW2200_DEBUG if (unlikely(rxb == NULL)) { printk(KERN_CRIT "Queue not allocated!\n"); break; } -#endif priv->rxq->queue[i] = NULL; pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, -- cgit v1.2.3-59-g8ed1b From 9d0be03aeeadcd59bd8f57219817e876a5e88e88 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Wed, 15 Feb 2006 06:18:19 +0800 Subject: [PATCH] ipw2200: use generic ieee80211_get_hdrlen() to get packet length replace ipw2200 specific frame_hdr_len() with generic ieee80211 routine ieee80211_get_hdrlen() Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 3 ++- drivers/net/wireless/ipw2200.h | 23 ----------------------- 2 files changed, 2 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 129891feb43f..b2bbdf982b01 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7895,7 +7895,8 @@ static void ipw_rx(struct ipw_priv *priv) le16_to_cpu(pkt->u.frame.length)); if (le16_to_cpu(pkt->u.frame.length) < - frame_hdr_len(header)) { + ieee80211_get_hdrlen(le16_to_cpu( + header->frame_ctl))) { IPW_DEBUG_DROP ("Received packet is too small. " "Dropping.\n"); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 5405ba105abf..c2a7aa32f724 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1907,27 +1907,4 @@ struct ipw_cmd_log { #define IPW_MAX_CONFIG_RETRIES 10 -static inline u32 frame_hdr_len(struct ieee80211_hdr_4addr *hdr) -{ - u32 retval; - u16 fc; - - retval = sizeof(struct ieee80211_hdr_3addr); - fc = le16_to_cpu(hdr->frame_ctl); - - /* - * Function ToDS FromDS - * IBSS 0 0 - * To AP 1 0 - * From AP 0 1 - * WDS (bridge) 1 1 - * - * Only WDS frames use Address4 among them. --YZ - */ - if (!(fc & IEEE80211_FCTL_TODS) || !(fc & IEEE80211_FCTL_FROMDS)) - retval -= ETH_ALEN; - - return retval; -} - #endif /* __ipw2200_h__ */ -- cgit v1.2.3-59-g8ed1b From b191608a451e75ed7f979cac268f5f423176feb3 Mon Sep 17 00:00:00 2001 From: Bill Moss Date: Wed, 15 Feb 2006 08:50:18 +0800 Subject: [PATCH] ipw2200: Add signal level to iwlist scan output This patch does two things. It uses the parameter IW_QUAL_DBM which is new in WE-19 to cause signal level and noise to be reported in dBm by the wireless tools. It also defines the signal level as an unsigned integer so that the signal level will be reported by iwlist iface scan. Signed-off-by: Bill Moss Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index b2bbdf982b01..c38d6a5fe9a3 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7831,7 +7831,8 @@ static void ipw_rx(struct ipw_priv *priv) le16_to_cpu(pkt->u.frame.rssi_dbm) - IPW_RSSI_TO_DBM, .signal = - le16_to_cpu(pkt->u.frame.signal), + le16_to_cpu(pkt->u.frame.rssi_dbm) - + IPW_RSSI_TO_DBM + 0x100, .noise = le16_to_cpu(pkt->u.frame.noise), .rate = pkt->u.frame.rate, @@ -8358,7 +8359,7 @@ static int ipw_wx_get_range(struct net_device *dev, range->max_qual.qual = 100; /* TODO: Find real max RSSI and stick here */ range->max_qual.level = 0; - range->max_qual.noise = priv->ieee->worst_rssi + 0x100; + range->max_qual.noise = 0; range->max_qual.updated = 7; /* Updated all three */ range->avg_qual.qual = 70; @@ -9568,7 +9569,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) wstats->qual.level = average_value(&priv->average_rssi); wstats->qual.noise = average_value(&priv->average_noise); wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | - IW_QUAL_NOISE_UPDATED; + IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; wstats->miss.beacon = average_value(&priv->average_missed_beacons); wstats->discard.retries = priv->last_tx_failures; -- cgit v1.2.3-59-g8ed1b From 8da374fc44a5e0fb71a485497cae38eb562d078c Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 17 Feb 2006 07:46:16 +0800 Subject: [PATCH] ipw2200: remove the WPA card associates to non-WPA AP checking wpa_supplicant needs to set wpa_enabled unconditionally, with this check it hasn't been possible to connect to non-WPA networks using wpa_supplicant. So remove below check. if (priv->ieee->wpa_enabled && network->wpa_ie_len == 0 && network->rsn_ie_len == 0) Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index c38d6a5fe9a3..dfa2efb3e215 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -5527,15 +5527,6 @@ static int ipw_best_network(struct ipw_priv *priv, return 0; } - if (priv->ieee->wpa_enabled && - network->wpa_ie_len == 0 && network->rsn_ie_len == 0) { - IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " - "because of WPA capability mismatch.\n", - escape_essid(network->ssid, network->ssid_len), - MAC_ARG(network->bssid)); - return 0; - } - if ((priv->config & CFG_STATIC_BSSID) && memcmp(network->bssid, priv->bssid, ETH_ALEN)) { IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " -- cgit v1.2.3-59-g8ed1b From d6d5b5c13e5003c9d33dcdcfdf1febc6efd7d319 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Feb 2006 16:21:09 +0800 Subject: [PATCH] ipw2200: Fix rf_kill is activated after mode change with 'disable=1' When loading the ipw2200 module with disabled=1, rf_kill is activated after every mode change. This is caused by ipw_sw_reset() is called when a mode is changed. The patch fixed the problem by distinguishing the purposes with the 'option' paramenter. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index dfa2efb3e215..b80ebd37483e 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7978,7 +7978,14 @@ static void ipw_rx(struct ipw_priv *priv) #define DEFAULT_SHORT_RETRY_LIMIT 7U #define DEFAULT_LONG_RETRY_LIMIT 4U -static int ipw_sw_reset(struct ipw_priv *priv, int init) +/** + * ipw_sw_reset + * @option: options to control different reset behaviour + * 0 = reset everything except the 'disable' module_param + * 1 = reset everything and print out driver info (for probe only) + * 2 = reset everything + */ +static int ipw_sw_reset(struct ipw_priv *priv, int option) { int band, modulation; int old_mode = priv->ieee->iw_mode; @@ -8005,7 +8012,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) priv->essid_len = 0; memset(priv->essid, 0, IW_ESSID_MAX_SIZE); - if (disable) { + if (disable && option) { priv->status |= STATUS_RF_KILL_SW; IPW_DEBUG_INFO("Radio disabled.\n"); } @@ -8057,7 +8064,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) if ((priv->pci_dev->device == 0x4223) || (priv->pci_dev->device == 0x4224)) { - if (init) + if (option == 2) printk(KERN_INFO DRV_NAME ": Detected Intel PRO/Wireless 2915ABG Network " "Connection\n"); @@ -8068,7 +8075,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) priv->adapter = IPW_2915ABG; priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; } else { - if (init) + if (option == 2) printk(KERN_INFO DRV_NAME ": Detected Intel PRO/Wireless 2200BG Network " "Connection\n"); @@ -9380,7 +9387,7 @@ static int ipw_wx_sw_reset(struct net_device *dev, mutex_lock(&priv->mutex); - ret = ipw_sw_reset(priv, 0); + ret = ipw_sw_reset(priv, 2); if (!ret) { free_firmware(); ipw_adapter_restart(priv); -- cgit v1.2.3-59-g8ed1b From e8c69e27d14a5fb15df9967f8c8ec5978af33ba8 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 17 Feb 2006 08:25:12 +0800 Subject: [PATCH] ipw2200: Fix ipw_sw_reset() implementation inconsistent with comment Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index b80ebd37483e..e9804450ca6c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -8064,7 +8064,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) if ((priv->pci_dev->device == 0x4223) || (priv->pci_dev->device == 0x4224)) { - if (option == 2) + if (option == 1) printk(KERN_INFO DRV_NAME ": Detected Intel PRO/Wireless 2915ABG Network " "Connection\n"); @@ -8075,7 +8075,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) priv->adapter = IPW_2915ABG; priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; } else { - if (option == 2) + if (option == 1) printk(KERN_INFO DRV_NAME ": Detected Intel PRO/Wireless 2200BG Network " "Connection\n"); -- cgit v1.2.3-59-g8ed1b From e815de422c1dc2fe787c6f3edba81f3cf0176e32 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 2 Mar 2006 05:55:51 +0800 Subject: [PATCH] ipw2200: Filter unsupported channels out in ad-hoc mode Currently iwlist ethX freq[uency]/channel lists all the channels the card supported for the current region, which includes some channels can only be used in infrastructure mode. This patch filters these channels out if the card is currently in ad-hoc mode. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index e9804450ca6c..d2fc8400d3ab 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -8387,20 +8387,28 @@ static int ipw_wx_get_range(struct net_device *dev, i = 0; if (priv->ieee->mode & (IEEE_B | IEEE_G)) { - for (j = 0; j < geo->bg_channels && i < IW_MAX_FREQUENCIES; - i++, j++) { + for (j = 0; j < geo->bg_channels && i < IW_MAX_FREQUENCIES; j++) { + if ((priv->ieee->iw_mode == IW_MODE_ADHOC) && + (geo->bg[j].flags & IEEE80211_CH_PASSIVE_ONLY)) + continue; + range->freq[i].i = geo->bg[j].channel; range->freq[i].m = geo->bg[j].freq * 100000; range->freq[i].e = 1; + i++; } } if (priv->ieee->mode & IEEE_A) { - for (j = 0; j < geo->a_channels && i < IW_MAX_FREQUENCIES; - i++, j++) { + for (j = 0; j < geo->a_channels && i < IW_MAX_FREQUENCIES; j++) { + if ((priv->ieee->iw_mode == IW_MODE_ADHOC) && + (geo->a[j].flags & IEEE80211_CH_PASSIVE_ONLY)) + continue; + range->freq[i].i = geo->a[j].channel; range->freq[i].m = geo->a[j].freq * 100000; range->freq[i].e = 1; + i++; } } -- cgit v1.2.3-59-g8ed1b From 1d1b09eb144e414ade1f44e21852fc60f2cf965b Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 2 Mar 2006 06:40:59 +0800 Subject: [PATCH] ipw2200: Change debug level for firmware error logging Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index d2fc8400d3ab..d12ef04fb4be 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1796,9 +1796,9 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) } if (inta & IPW_INTA_BIT_FATAL_ERROR) { - IPW_ERROR("Firmware error detected. Restarting.\n"); + IPW_WARNING("Firmware error detected. Restarting.\n"); if (priv->error) { - IPW_ERROR("Sysfs 'error' log already exists.\n"); + IPW_DEBUG_FW("Sysfs 'error' log already exists.\n"); #ifdef CONFIG_IPW2200_DEBUG if (ipw_debug_level & IPW_DL_FW_ERRORS) { struct ipw_fw_error *error = @@ -1811,10 +1811,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) } else { priv->error = ipw_alloc_error_log(priv); if (priv->error) - IPW_ERROR("Sysfs 'error' log captured.\n"); + IPW_DEBUG_FW("Sysfs 'error' log captured.\n"); else - IPW_ERROR("Error allocating sysfs 'error' " - "log.\n"); + IPW_DEBUG_FW("Error allocating sysfs 'error' " + "log.\n"); #ifdef CONFIG_IPW2200_DEBUG if (ipw_debug_level & IPW_DL_FW_ERRORS) ipw_dump_error_log(priv, priv->error); -- cgit v1.2.3-59-g8ed1b From 3e1555bae145ab2d079a1823cbdd5c486503d147 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 6 Mar 2006 05:48:37 +0800 Subject: [PATCH] ipw2200: export `debug' module param only if CONFIG_IPW2200_DEBUG Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index d12ef04fb4be..a56a77e8f32b 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -11185,8 +11185,10 @@ MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); module_param(led, int, 0444); MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)\n"); +#ifdef CONFIG_IPW2200_DEBUG module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); +#endif module_param(channel, int, 0444); MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); -- cgit v1.2.3-59-g8ed1b From 12977154e7cb4d72b1295f009a040c56a7e05d90 Mon Sep 17 00:00:00 2001 From: "Cahill, Ben M" Date: Wed, 8 Mar 2006 02:58:02 +0800 Subject: [PATCH] ipw2200: Set a meaningful silence threshold value Set a meaningful silence threshold value (replacing our previous "0" default), which gets rid of the gratuitous "Link deterioration" notifications that we've been receiving from firmware. This notification feature tells the driver information to help it determine when to pre-emptively restart the firmware/ucode in anticipation of firmware errors! But since setting this new threshold, I haven't seen any such notifications. At least it keeps the logs a little less busy. Signed-off-by: Cahill, Ben M Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 8 ++++---- drivers/net/wireless/ipw2200.h | 9 ++++++--- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index a56a77e8f32b..06909cbc9808 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -4541,10 +4541,9 @@ static void ipw_rx_notification(struct ipw_priv *priv, if (notif->size == sizeof(*x)) { IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, - "link deterioration: '%s' " MAC_FMT - " \n", escape_essid(priv->essid, - priv->essid_len), - MAC_ARG(priv->bssid)); + "link deterioration: type %d, cnt %d\n", + x->silence_notification_type, + x->silence_count); memcpy(&priv->last_link_deterioration, x, sizeof(*x)); } else { @@ -9607,6 +9606,7 @@ static void init_sys_config(struct ipw_sys_config *sys_config) sys_config->enable_cts_to_self = 0; sys_config->bt_coexist_collision_thr = 0; sys_config->pass_noise_stats_to_host = 1; //1 -- fix for 256 + sys_config->silence_threshold = 0x1e; } static int ipw_net_open(struct net_device *dev) diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index c2a7aa32f724..d9f57f456fb7 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -618,13 +618,16 @@ struct notif_tgi_tx_key { u8 reserved; } __attribute__ ((packed)); +#define SILENCE_OVER_THRESH (1) +#define SILENCE_UNDER_THRESH (2) + struct notif_link_deterioration { struct ipw_cmd_stats stats; u8 rate; u8 modulation; struct rate_histogram histogram; - u8 reserved1; - u16 reserved2; + u8 silence_notification_type; /* SILENCE_OVER/UNDER_THRESH */ + u16 silence_count; } __attribute__ ((packed)); struct notif_association { @@ -782,7 +785,7 @@ struct ipw_sys_config { u8 enable_cts_to_self; u8 enable_multicast_filtering; u8 bt_coexist_collision_thr; - u8 reserved2; + u8 silence_threshold; u8 accept_all_mgmt_bcpr; u8 accept_all_mgtm_frames; u8 pass_noise_stats_to_host; -- cgit v1.2.3-59-g8ed1b From 71de1f3dd14e3e39cef929506a9526779f5a447d Mon Sep 17 00:00:00 2001 From: "Cahill, Ben M" Date: Wed, 8 Mar 2006 03:02:27 +0800 Subject: [PATCH] ipw2200: Enables the "slow diversity" algorithm This forces one antenna or the other, if the background noise is significantly quieter in one than the other. It favors the quieter antenna, and won't kick in unless the difference is significant. Signed-off-by: Cahill, Ben M Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 2 +- drivers/net/wireless/ipw2200.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 06909cbc9808..954a095eeb51 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -9600,7 +9600,7 @@ static void init_sys_config(struct ipw_sys_config *sys_config) sys_config->disable_unicast_decryption = 1; sys_config->exclude_multicast_unencrypted = 0; sys_config->disable_multicast_decryption = 1; - sys_config->antenna_diversity = CFG_SYS_ANTENNA_BOTH; + sys_config->antenna_diversity = CFG_SYS_ANTENNA_SLOW_DIV; sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */ sys_config->dot11g_auto_detection = 0; sys_config->enable_cts_to_self = 0; diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index d9f57f456fb7..e8f133666c65 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1895,6 +1895,7 @@ struct ipw_cmd_log { #define CFG_SYS_ANTENNA_BOTH 0x00 /* NIC selects best antenna */ #define CFG_SYS_ANTENNA_A 0x01 /* force antenna A */ #define CFG_SYS_ANTENNA_B 0x03 /* force antenna B */ +#define CFG_SYS_ANTENNA_SLOW_DIV 0x02 /* consider background noise */ /* * The definitions below were lifted off the ipw2100 driver, which only -- cgit v1.2.3-59-g8ed1b From 651be26f2daf31e61faf4b55ada709cf39ec76a2 Mon Sep 17 00:00:00 2001 From: Olivier Hochreutiner Date: Wed, 8 Mar 2006 03:13:55 +0800 Subject: [PATCH] ipw2200: wireless extension sensitivity threshold support The patch allows the user to set the handover threshold, i.e. the number of consecutively missed beacons that will trigger a roaming attempt. The disassociation threshold is set to 3 times the handover threshold. Signed-off-by: Olivier Hochreutiner Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- Documentation/networking/README.ipw2200 | 10 +++++++ drivers/net/wireless/ipw2200.c | 48 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ipw2200.h | 4 ++- 3 files changed, 61 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/networking/README.ipw2200 b/Documentation/networking/README.ipw2200 index 712c5681338b..c2f693e24c7d 100644 --- a/Documentation/networking/README.ipw2200 +++ b/Documentation/networking/README.ipw2200 @@ -30,6 +30,7 @@ Index 2. Ad-Hoc Networking 3. Interacting with Wireless Tools 3.1. iwconfig mode +3.2. iwconfig sens 4. About the Version Numbers 5. Firmware installation 6. Support @@ -383,6 +384,15 @@ When configuring the mode of the adapter, all run-time configured parameters are reset to the value used when the module was loaded. This includes channels, rates, ESSID, etc. +3.2 iwconfig sens +----------------------------------------------- + +The 'iwconfig ethX sens XX' command will not set the signal sensitivity +threshold, as described in iwconfig documentation, but rather the number +of consecutive missed beacons that will trigger handover, i.e. roaming +to another access point. At the same time, it will set the disassociation +threshold to 3 times the given value. + 4. About the Version Numbers ----------------------------------------------- diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 954a095eeb51..078f33b01c2f 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -8608,6 +8608,52 @@ static int ipw_wx_get_nick(struct net_device *dev, return 0; } +static int ipw_wx_set_sens(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + int err = 0; + + IPW_DEBUG_WX("Setting roaming threshold to %d\n", wrqu->sens.value); + IPW_DEBUG_WX("Setting disassociate threshold to %d\n", 3*wrqu->sens.value); + mutex_lock(&priv->mutex); + + if (wrqu->sens.fixed == 0) + { + priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT; + priv->disassociate_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT; + goto out; + } + if ((wrqu->sens.value > IPW_MB_ROAMING_THRESHOLD_MAX) || + (wrqu->sens.value < IPW_MB_ROAMING_THRESHOLD_MIN)) { + err = -EINVAL; + goto out; + } + + priv->roaming_threshold = wrqu->sens.value; + priv->disassociate_threshold = 3*wrqu->sens.value; + out: + mutex_unlock(&priv->mutex); + return err; +} + +static int ipw_wx_get_sens(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + mutex_lock(&priv->mutex); + wrqu->sens.fixed = 1; + wrqu->sens.value = priv->roaming_threshold; + mutex_unlock(&priv->mutex); + + IPW_DEBUG_WX("GET roaming threshold -> %s %d \n", + wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); + + return 0; +} + static int ipw_wx_set_rate(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -9429,6 +9475,8 @@ static iw_handler ipw_wx_handlers[] = { IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode, + IW_IOCTL(SIOCSIWSENS) = ipw_wx_set_sens, + IW_IOCTL(SIOCGIWSENS) = ipw_wx_get_sens, IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range, IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap, IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap, diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index e8f133666c65..2033fc6f1892 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -246,8 +246,10 @@ enum connection_manager_assoc_states { #define HOST_NOTIFICATION_S36_MEASUREMENT_REFUSED 31 #define HOST_NOTIFICATION_STATUS_BEACON_MISSING 1 -#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT 24 +#define IPW_MB_ROAMING_THRESHOLD_MIN 1 #define IPW_MB_ROAMING_THRESHOLD_DEFAULT 8 +#define IPW_MB_ROAMING_THRESHOLD_MAX 30 +#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT 3*IPW_MB_ROAMING_THRESHOLD_DEFAULT #define IPW_REAL_RATE_RX_PACKET_THRESHOLD 300 #define MACADRR_BYTE_LEN 6 -- cgit v1.2.3-59-g8ed1b From 9006ea75cfaded82acbc34d03e9d4e86447f40a9 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 8 Mar 2006 03:22:28 +0800 Subject: [PATCH] ipw2200: switch to the new ipw2200-fw-3.0 image format This patch modifies the driver to support the ipw2200-fw-3.0 image format. The 3.0 fw image does not add any new capabilities, but as a result of image format changes, it should fix two problems experienced by users: 1) Race conditions with the request_firmware interface and udev/hotplug are improved as only a single request_firmware call is now required to load the firmware and microcode (vs. 3 separate calls previously) 2) The monitor mode firmware (sniffer) is now packaged with the correct boot image so it can now function without frequent restarts. Note: Once you apply this patch, you will also need to upgrade your firmware image to the 3.0 version available from: http://ipw2200.sf.net/firmware.php Signed-off-by: James Ketrenos Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 165 ++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 078f33b01c2f..0b74b5a16647 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -2829,33 +2829,11 @@ static void ipw_arc_release(struct ipw_priv *priv) mdelay(5); } -struct fw_header { - u32 version; - u32 mode; -}; - struct fw_chunk { u32 address; u32 length; }; -#define IPW_FW_MAJOR_VERSION 2 -#define IPW_FW_MINOR_VERSION 4 - -#define IPW_FW_MINOR(x) ((x & 0xff) >> 8) -#define IPW_FW_MAJOR(x) (x & 0xff) - -#define IPW_FW_VERSION ((IPW_FW_MINOR_VERSION << 8) | IPW_FW_MAJOR_VERSION) - -#define IPW_FW_PREFIX "ipw-" __stringify(IPW_FW_MAJOR_VERSION) \ -"." __stringify(IPW_FW_MINOR_VERSION) "-" - -#if IPW_FW_MAJOR_VERSION >= 2 && IPW_FW_MINOR_VERSION > 0 -#define IPW_FW_NAME(x) IPW_FW_PREFIX "" x ".fw" -#else -#define IPW_FW_NAME(x) "ipw2200_" x ".fw" -#endif - static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) { int rc = 0, i, addr; @@ -3124,33 +3102,47 @@ static int ipw_reset_nic(struct ipw_priv *priv) return rc; } + +struct ipw_fw { + u32 ver; + u32 boot_size; + u32 ucode_size; + u32 fw_size; + u8 data[0]; +}; + static int ipw_get_fw(struct ipw_priv *priv, - const struct firmware **fw, const char *name) + const struct firmware **raw, const char *name) { - struct fw_header *header; + struct ipw_fw *fw; int rc; /* ask firmware_class module to get the boot firmware off disk */ - rc = request_firmware(fw, name, &priv->pci_dev->dev); + rc = request_firmware(raw, name, &priv->pci_dev->dev); if (rc < 0) { - IPW_ERROR("%s load failed: Reason %d\n", name, rc); + IPW_ERROR("%s request_firmware failed: Reason %d\n", name, rc); return rc; } - header = (struct fw_header *)(*fw)->data; - if (IPW_FW_MAJOR(le32_to_cpu(header->version)) != IPW_FW_MAJOR_VERSION) { - IPW_ERROR("'%s' firmware version not compatible (%d != %d)\n", - name, - IPW_FW_MAJOR(le32_to_cpu(header->version)), - IPW_FW_MAJOR_VERSION); + if ((*raw)->size < sizeof(*fw)) { + IPW_ERROR("%s is too small (%zd)\n", name, (*raw)->size); + return -EINVAL; + } + + fw = (void *)(*raw)->data; + + if ((*raw)->size < sizeof(*fw) + + fw->boot_size + fw->ucode_size + fw->fw_size) { + IPW_ERROR("%s is too small or corrupt (%zd)\n", + name, (*raw)->size); return -EINVAL; } - IPW_DEBUG_INFO("Loading firmware '%s' file v%d.%d (%zd bytes)\n", + IPW_DEBUG_INFO("Read firmware '%s' image v%d.%d (%zd bytes)\n", name, - IPW_FW_MAJOR(le32_to_cpu(header->version)), - IPW_FW_MINOR(le32_to_cpu(header->version)), - (*fw)->size - sizeof(struct fw_header)); + le32_to_cpu(fw->ver) >> 16, + le32_to_cpu(fw->ver) & 0xff, + (*raw)->size - sizeof(*fw)); return 0; } @@ -3190,17 +3182,13 @@ static void ipw_rx_queue_reset(struct ipw_priv *priv, #ifdef CONFIG_PM static int fw_loaded = 0; -static const struct firmware *bootfw = NULL; -static const struct firmware *firmware = NULL; -static const struct firmware *ucode = NULL; +static const struct firmware *raw = NULL; static void free_firmware(void) { if (fw_loaded) { - release_firmware(bootfw); - release_firmware(ucode); - release_firmware(firmware); - bootfw = ucode = firmware = NULL; + release_firmware(raw); + raw = NULL; fw_loaded = 0; } } @@ -3211,32 +3199,46 @@ static void free_firmware(void) static int ipw_load(struct ipw_priv *priv) { #ifndef CONFIG_PM - const struct firmware *bootfw = NULL; - const struct firmware *firmware = NULL; - const struct firmware *ucode = NULL; + const struct firmware *raw = NULL; #endif - char *ucode_name; - char *fw_name; + struct ipw_fw *fw; + u8 *boot_img, *ucode_img, *fw_img; + u8 *name = NULL; int rc = 0, retries = 3; switch (priv->ieee->iw_mode) { case IW_MODE_ADHOC: - ucode_name = IPW_FW_NAME("ibss_ucode"); - fw_name = IPW_FW_NAME("ibss"); + name = "ipw2200-ibss.fw"; break; #ifdef CONFIG_IPW2200_MONITOR case IW_MODE_MONITOR: - ucode_name = IPW_FW_NAME("sniffer_ucode"); - fw_name = IPW_FW_NAME("sniffer"); + name = "ipw2200-sniffer.fw"; break; #endif case IW_MODE_INFRA: - ucode_name = IPW_FW_NAME("bss_ucode"); - fw_name = IPW_FW_NAME("bss"); + name = "ipw2200-bss.fw"; break; - default: + } + + if (!name) { rc = -EINVAL; + goto error; + } + +#ifdef CONFIG_PM + if (!fw_loaded) { +#endif + rc = ipw_get_fw(priv, &raw, name); + if (rc < 0) + goto error; +#ifdef CONFIG_PM } +#endif + + fw = (void *)raw->data; + boot_img = &fw->data[0]; + ucode_img = &fw->data[fw->boot_size]; + fw_img = &fw->data[fw->boot_size + fw->ucode_size]; if (rc < 0) goto error; @@ -3269,18 +3271,8 @@ static int ipw_load(struct ipw_priv *priv) ipw_zero_memory(priv, IPW_NIC_SRAM_LOWER_BOUND, IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); -#ifdef CONFIG_PM - if (!fw_loaded) { -#endif - rc = ipw_get_fw(priv, &bootfw, IPW_FW_NAME("boot")); - if (rc < 0) - goto error; -#ifdef CONFIG_PM - } -#endif /* DMA the initial boot firmware into the device */ - rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header), - bootfw->size - sizeof(struct fw_header)); + rc = ipw_load_firmware(priv, boot_img, fw->boot_size); if (rc < 0) { IPW_ERROR("Unable to load boot firmware: %d\n", rc); goto error; @@ -3301,19 +3293,8 @@ static int ipw_load(struct ipw_priv *priv) /* ack fw init done interrupt */ ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); -#ifdef CONFIG_PM - if (!fw_loaded) { -#endif - rc = ipw_get_fw(priv, &ucode, ucode_name); - if (rc < 0) - goto error; -#ifdef CONFIG_PM - } -#endif - /* DMA the ucode into the device */ - rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header), - ucode->size - sizeof(struct fw_header)); + rc = ipw_load_ucode(priv, ucode_img, fw->ucode_size); if (rc < 0) { IPW_ERROR("Unable to load ucode: %d\n", rc); goto error; @@ -3322,20 +3303,8 @@ static int ipw_load(struct ipw_priv *priv) /* stop nic */ ipw_stop_nic(priv); -#ifdef CONFIG_PM - if (!fw_loaded) { -#endif - rc = ipw_get_fw(priv, &firmware, fw_name); - if (rc < 0) - goto error; -#ifdef CONFIG_PM - } -#endif - /* DMA bss firmware into the device */ - rc = ipw_load_firmware(priv, firmware->data + - sizeof(struct fw_header), - firmware->size - sizeof(struct fw_header)); + rc = ipw_load_firmware(priv, fw_img, fw->fw_size); if (rc < 0) { IPW_ERROR("Unable to load firmware: %d\n", rc); goto error; @@ -3400,9 +3369,7 @@ static int ipw_load(struct ipw_priv *priv) ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); #ifndef CONFIG_PM - release_firmware(bootfw); - release_firmware(ucode); - release_firmware(firmware); + release_firmware(raw); #endif return 0; @@ -3412,15 +3379,11 @@ static int ipw_load(struct ipw_priv *priv) priv->rxq = NULL; } ipw_tx_queue_free(priv); - if (bootfw) - release_firmware(bootfw); - if (ucode) - release_firmware(ucode); - if (firmware) - release_firmware(firmware); + if (raw) + release_firmware(raw); #ifdef CONFIG_PM fw_loaded = 0; - bootfw = ucode = firmware = NULL; + raw = NULL; #endif return rc; -- cgit v1.2.3-59-g8ed1b From 7c567894480daef05bc13abdc4b9414541e245cb Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 24 Feb 2006 04:20:48 +0800 Subject: [PATCH] ipw2200: Update ipw2200 version stamp to 1.1.1 Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 0b74b5a16647..65c5b1422ec9 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -33,7 +33,7 @@ #include "ipw2200.h" #include -#define IPW2200_VERSION "git-1.0.10" +#define IPW2200_VERSION "git-1.1.1" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation" #define DRV_VERSION IPW2200_VERSION -- cgit v1.2.3-59-g8ed1b From 71e585fca25c9ccde82196fd1aef78e34312e899 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 11 Mar 2006 04:42:58 +0100 Subject: [PATCH] drivers/net/wireless/ipw2200.c: fix an array overun This patch fixes a big array overun found by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 65c5b1422ec9..93d53f9dab0e 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -9972,9 +9972,8 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev, return -EINVAL; mutex_lock(&p->mutex); memcpy(&p->eeprom[eeprom->offset], bytes, eeprom->len); - for (i = IPW_EEPROM_DATA; - i < IPW_EEPROM_DATA + IPW_EEPROM_IMAGE_SIZE; i++) - ipw_write8(p, i, p->eeprom[i]); + for (i = 0; i < IPW_EEPROM_IMAGE_SIZE; i++) + ipw_write8(p, i + IPW_EEPROM_DATA, p->eeprom[i]); mutex_unlock(&p->mutex); return 0; } -- cgit v1.2.3-59-g8ed1b From 171e7b2f1f50f112d3ce8a829a3e79c5739b3132 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Wed, 15 Feb 2006 07:17:56 +0800 Subject: [PATCH] ipw2x00: expend Copyright to 2006 Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- Documentation/networking/README.ipw2100 | 12 ++++++------ Documentation/networking/README.ipw2200 | 4 ++-- drivers/net/wireless/ipw2100.c | 4 ++-- drivers/net/wireless/ipw2100.h | 2 +- drivers/net/wireless/ipw2200.c | 4 ++-- drivers/net/wireless/ipw2200.h | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/README.ipw2100 b/Documentation/networking/README.ipw2100 index 3ab40379d1cf..f3fcaa41f774 100644 --- a/Documentation/networking/README.ipw2100 +++ b/Documentation/networking/README.ipw2100 @@ -3,18 +3,18 @@ Intel(R) PRO/Wireless 2100 Driver for Linux in support of: Intel(R) PRO/Wireless 2100 Network Connection -Copyright (C) 2003-2005, Intel Corporation +Copyright (C) 2003-2006, Intel Corporation README.ipw2100 -Version: 1.1.3 -Date : October 17, 2005 +Version: git-1.1.5 +Date : January 25, 2006 Index ----------------------------------------------- 0. IMPORTANT INFORMATION BEFORE USING THIS DRIVER 1. Introduction -2. Release 1.1.3 Current Features +2. Release git-1.1.5 Current Features 3. Command Line Parameters 4. Sysfs Helper Files 5. Radio Kill Switch @@ -89,7 +89,7 @@ potential fixes and patches, as well as links to the development mailing list for the driver project. -2. Release 1.1.3 Current Supported Features +2. Release git-1.1.5 Current Supported Features ----------------------------------------------- - Managed (BSS) and Ad-Hoc (IBSS) - WEP (shared key and open) @@ -270,7 +270,7 @@ For installation support on the ipw2100 1.1.0 driver on Linux kernels 9. License ----------------------------------------------- - Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 2003 - 2006 Intel Corporation. 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 (version 2) as diff --git a/Documentation/networking/README.ipw2200 b/Documentation/networking/README.ipw2200 index c2f693e24c7d..acb30c5dcff3 100644 --- a/Documentation/networking/README.ipw2200 +++ b/Documentation/networking/README.ipw2200 @@ -10,7 +10,7 @@ both hardware adapters listed above. In this document the Intel(R) PRO/Wireless 2915ABG Driver for Linux will be used to reference the unified driver. -Copyright (C) 2004-2005, Intel Corporation +Copyright (C) 2004-2006, Intel Corporation README.ipw2200 @@ -448,7 +448,7 @@ For general information and support, go to: 7. License ----------------------------------------------- - Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 2003 - 2006 Intel Corporation. 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 version 2 as diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index eb79198ac450..84f63876bf75 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 2003 - 2006 Intel Corporation. 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 as @@ -172,7 +172,7 @@ that only one external action is invoked at a time. #define DRV_NAME "ipw2100" #define DRV_VERSION IPW2100_VERSION #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" /* Debugging stuff */ #ifdef CONFIG_IPW2100_DEBUG diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index 51360910d222..948d426fcf9d 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. + Copyright(c) 2003 - 2006 Intel Corporation. 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 as diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 93d53f9dab0e..9dce522526c5 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved. 802.11 status code portion of this file from ethereal-0.10.6: Copyright 2000, Axis Communications AB @@ -35,7 +35,7 @@ #define IPW2200_VERSION "git-1.1.1" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" #define DRV_VERSION IPW2200_VERSION #define ETH_P_80211_STATS (ETH_P_80211_RAW + 1) diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 2033fc6f1892..4b9804900702 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 2003 - 2006 Intel Corporation. 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 as -- cgit v1.2.3-59-g8ed1b From 15745a7dd1ac6bf1ef7959040f864c78a95aa35b Mon Sep 17 00:00:00 2001 From: Stefan Rompf Date: Tue, 21 Feb 2006 18:36:17 +0800 Subject: [PATCH] ipw2100: add radiotap headers to packtes captured in monitor mode Signed-off-by: Stefan Rompf Signed-off-by: Andrea Merello Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2100.c | 95 +++++++++++++++++++++++++++++++++++++----- drivers/net/wireless/ipw2100.h | 4 ++ 2 files changed, 88 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 84f63876bf75..d429fd576a66 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -2390,15 +2390,6 @@ static void isr_rx(struct ipw2100_priv *priv, int i, IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; } -#ifdef CONFIG_IPW2100_MONITOR - if (unlikely(priv->ieee->iw_mode == IW_MODE_MONITOR && - priv->config & CFG_CRC_CHECK && - status->flags & IPW_STATUS_FLAG_CRC_ERROR)) { - IPW_DEBUG_RX("CRC error in packet. Dropping.\n"); - priv->ieee->stats.rx_errors++; - return; - } -#endif if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR && !(priv->status & STATUS_ASSOCIATED))) { @@ -2446,6 +2437,88 @@ static void isr_rx(struct ipw2100_priv *priv, int i, priv->rx_queue.drv[i].host_addr = packet->dma_addr; } +#ifdef CONFIG_IPW2100_MONITOR + +static void isr_rx_monitor(struct ipw2100_priv *priv, int i, + struct ieee80211_rx_stats *stats) +{ + struct ipw2100_status *status = &priv->status_queue.drv[i]; + struct ipw2100_rx_packet *packet = &priv->rx_buffers[i]; + + IPW_DEBUG_RX("Handler...\n"); + + /* Magic struct that slots into the radiotap header -- no reason + * to build this manually element by element, we can write it much + * more efficiently than we can parse it. ORDER MATTERS HERE */ + struct ipw_rt_hdr { + struct ieee80211_radiotap_header rt_hdr; + s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ + } *ipw_rt; + + if (unlikely(status->frame_size > skb_tailroom(packet->skb) - sizeof(struct ipw_rt_hdr))) { + IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!" + " Dropping.\n", + priv->net_dev->name, + status->frame_size, skb_tailroom(packet->skb)); + priv->ieee->stats.rx_errors++; + return; + } + + if (unlikely(!netif_running(priv->net_dev))) { + priv->ieee->stats.rx_errors++; + priv->wstats.discard.misc++; + IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); + return; + } + + if (unlikely(priv->config & CFG_CRC_CHECK && + status->flags & IPW_STATUS_FLAG_CRC_ERROR)) { + IPW_DEBUG_RX("CRC error in packet. Dropping.\n"); + priv->ieee->stats.rx_errors++; + return; + } + + pci_unmap_single(priv->pci_dev, + packet->dma_addr, + sizeof(struct ipw2100_rx), PCI_DMA_FROMDEVICE); + memmove(packet->skb->data + sizeof(struct ipw_rt_hdr), + packet->skb->data, status->frame_size); + + ipw_rt = (struct ipw_rt_hdr *) packet->skb->data; + + ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; + ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ + ipw_rt->rt_hdr.it_len = sizeof(struct ipw_rt_hdr); /* total header+data */ + + ipw_rt->rt_hdr.it_present = 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL; + + ipw_rt->rt_dbmsignal = status->rssi + IPW2100_RSSI_TO_DBM; + + skb_put(packet->skb, status->frame_size + sizeof(struct ipw_rt_hdr)); + + if (!ieee80211_rx(priv->ieee, packet->skb, stats)) { + priv->ieee->stats.rx_errors++; + + /* ieee80211_rx failed, so it didn't free the SKB */ + dev_kfree_skb_any(packet->skb); + packet->skb = NULL; + } + + /* We need to allocate a new SKB and attach it to the RDB. */ + if (unlikely(ipw2100_alloc_skb(priv, packet))) { + IPW_DEBUG_WARNING( + "%s: Unable to allocate SKB onto RBD ring - disabling " + "adapter.\n", priv->net_dev->name); + /* TODO: schedule adapter shutdown */ + IPW_DEBUG_INFO("TODO: Shutdown adapter...\n"); + } + + /* Update the RDB entry */ + priv->rx_queue.drv[i].host_addr = packet->dma_addr; +} + +#endif + static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) { struct ipw2100_status *status = &priv->status_queue.drv[i]; @@ -2577,7 +2650,7 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv) case P8023_DATA_VAL: #ifdef CONFIG_IPW2100_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { - isr_rx(priv, i, &stats); + isr_rx_monitor(priv, i, &stats); break; } #endif @@ -3882,7 +3955,7 @@ static int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode) #ifdef CONFIG_IPW2100_MONITOR case IW_MODE_MONITOR: priv->last_mode = priv->ieee->iw_mode; - priv->net_dev->type = ARPHRD_IEEE80211; + priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; break; #endif /* CONFIG_IPW2100_MONITOR */ } diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index 948d426fcf9d..6f0b40f96abd 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -41,6 +41,10 @@ #include +#ifdef CONFIG_IPW2100_MONITOR +#include +#endif + #include struct ipw2100_priv; -- cgit v1.2.3-59-g8ed1b From cae1629515cf6d166fa20657e68b75619d563280 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 21 Feb 2006 18:41:14 +0800 Subject: [PATCH] ipw2100: Fix radiotap code gcc warning Fix gcc warning: ipw2100.c:2460: ISO C90 forbids mixed declarations and code Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2100.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index d429fd576a66..b0e23a88250f 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -2445,8 +2445,6 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, struct ipw2100_status *status = &priv->status_queue.drv[i]; struct ipw2100_rx_packet *packet = &priv->rx_buffers[i]; - IPW_DEBUG_RX("Handler...\n"); - /* Magic struct that slots into the radiotap header -- no reason * to build this manually element by element, we can write it much * more efficiently than we can parse it. ORDER MATTERS HERE */ @@ -2455,11 +2453,15 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ } *ipw_rt; - if (unlikely(status->frame_size > skb_tailroom(packet->skb) - sizeof(struct ipw_rt_hdr))) { + IPW_DEBUG_RX("Handler...\n"); + + if (unlikely(status->frame_size > skb_tailroom(packet->skb) - + sizeof(struct ipw_rt_hdr))) { IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!" " Dropping.\n", priv->net_dev->name, - status->frame_size, skb_tailroom(packet->skb)); + status->frame_size, + skb_tailroom(packet->skb)); priv->ieee->stats.rx_errors++; return; } @@ -2478,8 +2480,7 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, return; } - pci_unmap_single(priv->pci_dev, - packet->dma_addr, + pci_unmap_single(priv->pci_dev, packet->dma_addr, sizeof(struct ipw2100_rx), PCI_DMA_FROMDEVICE); memmove(packet->skb->data + sizeof(struct ipw_rt_hdr), packet->skb->data, status->frame_size); @@ -2488,7 +2489,7 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ - ipw_rt->rt_hdr.it_len = sizeof(struct ipw_rt_hdr); /* total header+data */ + ipw_rt->rt_hdr.it_len = sizeof(struct ipw_rt_hdr); /* total hdr+data */ ipw_rt->rt_hdr.it_present = 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL; -- cgit v1.2.3-59-g8ed1b From 752e377bfdad61482e39cafedb3a6bb1b5bb0289 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 28 Feb 2006 07:20:54 +0800 Subject: [PATCH] ipw2100: semaphore to mutexes conversion semaphore to mutexes conversion. the conversion was generated via scripts, and the result was validated automatically via a script as well. build-tested. Signed-off-by: Ingo Molnar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2100.c | 119 +++++++++++++++++++++-------------------- drivers/net/wireless/ipw2100.h | 4 +- 2 files changed, 62 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index b0e23a88250f..54437206f31e 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -194,6 +194,7 @@ static struct ipw2100_fw ipw2100_firmware; #endif #include +#include module_param(debug, int, 0444); module_param(mode, int, 0444); module_param(channel, int, 0444); @@ -1418,7 +1419,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv) if (priv->status & STATUS_ENABLED) return 0; - down(&priv->adapter_sem); + mutex_lock(&priv->adapter_mutex); if (rf_kill_active(priv)) { IPW_DEBUG_HC("Command aborted due to RF kill active.\n"); @@ -1444,7 +1445,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv) } fail_up: - up(&priv->adapter_sem); + mutex_unlock(&priv->adapter_mutex); return err; } @@ -1576,7 +1577,7 @@ static int ipw2100_disable_adapter(struct ipw2100_priv *priv) cancel_delayed_work(&priv->hang_check); } - down(&priv->adapter_sem); + mutex_lock(&priv->adapter_mutex); err = ipw2100_hw_send_command(priv, &cmd); if (err) { @@ -1595,7 +1596,7 @@ static int ipw2100_disable_adapter(struct ipw2100_priv *priv) IPW_DEBUG_INFO("TODO: implement scan state machine\n"); fail_up: - up(&priv->adapter_sem); + mutex_unlock(&priv->adapter_mutex); return err; } @@ -1888,7 +1889,7 @@ static void ipw2100_reset_adapter(struct ipw2100_priv *priv) priv->status |= STATUS_RESET_PENDING; spin_unlock_irqrestore(&priv->low_lock, flags); - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); /* stop timed checks so that they don't interfere with reset */ priv->stop_hang_check = 1; cancel_delayed_work(&priv->hang_check); @@ -1898,7 +1899,7 @@ static void ipw2100_reset_adapter(struct ipw2100_priv *priv) wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); ipw2100_up(priv, 0); - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); } @@ -4212,7 +4213,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio) IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO %s\n", disable_radio ? "OFF" : "ON"); - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (disable_radio) { priv->status |= STATUS_RF_KILL_SW; @@ -4230,7 +4231,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio) schedule_reset(priv); } - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return 1; } @@ -5534,7 +5535,7 @@ static void shim__set_security(struct net_device *dev, struct ipw2100_priv *priv = ieee80211_priv(dev); int i, force_update = 0; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) goto done; @@ -5607,7 +5608,7 @@ static void shim__set_security(struct net_device *dev, if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) ipw2100_configure_security(priv, 0); done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); } static int ipw2100_adapter_setup(struct ipw2100_priv *priv) @@ -5731,7 +5732,7 @@ static int ipw2100_set_address(struct net_device *dev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); priv->config |= CFG_CUSTOM_MAC; memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN); @@ -5741,12 +5742,12 @@ static int ipw2100_set_address(struct net_device *dev, void *p) goto done; priv->reset_backoff = 0; - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); ipw2100_reset_adapter(priv); return 0; done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -6089,8 +6090,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, strcpy(priv->nick, "ipw2100"); spin_lock_init(&priv->low_lock); - sema_init(&priv->action_sem, 1); - sema_init(&priv->adapter_sem, 1); + mutex_init(&priv->action_mutex); + mutex_init(&priv->adapter_mutex); init_waitqueue_head(&priv->wait_command_queue); @@ -6255,7 +6256,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, * member to call a function that then just turns and calls ipw2100_up. * net_dev->init is called after name allocation but before the * notifier chain is called */ - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); err = register_netdev(dev); if (err) { printk(KERN_WARNING DRV_NAME @@ -6291,12 +6292,12 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, priv->status |= STATUS_INITIALIZED; - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return 0; fail_unlock: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); fail: if (dev) { @@ -6336,7 +6337,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) struct net_device *dev; if (priv) { - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); priv->status &= ~STATUS_INITIALIZED; @@ -6351,9 +6352,9 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) /* Take down the hardware */ ipw2100_down(priv); - /* Release the semaphore so that the network subsystem can + /* Release the mutex so that the network subsystem can * complete any needed calls into the driver... */ - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); /* Unregister the device first - this results in close() * being called if the device is open. If we free storage @@ -6392,7 +6393,7 @@ static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state) IPW_DEBUG_INFO("%s: Going into suspend...\n", dev->name); - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (priv->status & STATUS_INITIALIZED) { /* Take down the device; powers it off, etc. */ ipw2100_down(priv); @@ -6405,7 +6406,7 @@ static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state) pci_disable_device(pci_dev); pci_set_power_state(pci_dev, PCI_D3hot); - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return 0; } @@ -6419,7 +6420,7 @@ static int ipw2100_resume(struct pci_dev *pci_dev) if (IPW2100_PM_DISABLED) return 0; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); IPW_DEBUG_INFO("%s: Coming out of suspend...\n", dev->name); @@ -6445,7 +6446,7 @@ static int ipw2100_resume(struct pci_dev *pci_dev) if (!(priv->status & STATUS_RF_KILL_SW)) ipw2100_up(priv, 0); - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return 0; } @@ -6609,7 +6610,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev, if (priv->ieee->iw_mode == IW_MODE_INFRA) return -EOPNOTSUPP; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -6640,7 +6641,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev, } done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -6681,7 +6682,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev, if (wrqu->mode == priv->ieee->iw_mode) return 0; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -6704,7 +6705,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev, } done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -6886,7 +6887,7 @@ static int ipw2100_wx_set_wap(struct net_device *dev, if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) return -EINVAL; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -6915,7 +6916,7 @@ static int ipw2100_wx_set_wap(struct net_device *dev, wrqu->ap_addr.sa_data[5] & 0xff); done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -6951,7 +6952,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev, int length = 0; int err = 0; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -6988,7 +6989,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev, err = ipw2100_set_essid(priv, essid, length, 0); done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -7069,7 +7070,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev, u32 rate; int err = 0; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -7096,7 +7097,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev, IPW_DEBUG_WX("SET Rate -> %04X \n", rate); done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -7116,7 +7117,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev, return 0; } - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -7148,7 +7149,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev, IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -7163,7 +7164,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev, if (wrqu->rts.fixed == 0) return -EINVAL; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -7183,7 +7184,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev, IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value); done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -7234,7 +7235,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev, value = wrqu->txpower.value; } - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -7245,7 +7246,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev, IPW_DEBUG_WX("SET TX Power -> %d \n", value); done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -7337,7 +7338,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev, if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) return 0; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -7364,7 +7365,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev, IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value); done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -7407,7 +7408,7 @@ static int ipw2100_wx_set_scan(struct net_device *dev, struct ipw2100_priv *priv = ieee80211_priv(dev); int err = 0; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -7422,7 +7423,7 @@ static int ipw2100_wx_set_scan(struct net_device *dev, } done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -7472,7 +7473,7 @@ static int ipw2100_wx_set_power(struct net_device *dev, struct ipw2100_priv *priv = ieee80211_priv(dev); int err = 0; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -7505,7 +7506,7 @@ static int ipw2100_wx_set_power(struct net_device *dev, IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode); done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -7809,7 +7810,7 @@ static int ipw2100_wx_set_promisc(struct net_device *dev, int enable = (parms[0] > 0); int err = 0; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -7827,7 +7828,7 @@ static int ipw2100_wx_set_promisc(struct net_device *dev, err = ipw2100_switch_mode(priv, priv->last_mode); } done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -7850,7 +7851,7 @@ static int ipw2100_wx_set_powermode(struct net_device *dev, struct ipw2100_priv *priv = ieee80211_priv(dev); int err = 0, mode = *(int *)extra; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -7862,7 +7863,7 @@ static int ipw2100_wx_set_powermode(struct net_device *dev, if (priv->power_mode != mode) err = ipw2100_set_power_mode(priv, mode); done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -7914,7 +7915,7 @@ static int ipw2100_wx_set_preamble(struct net_device *dev, struct ipw2100_priv *priv = ieee80211_priv(dev); int err, mode = *(int *)extra; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -7932,7 +7933,7 @@ static int ipw2100_wx_set_preamble(struct net_device *dev, err = ipw2100_system_config(priv, 0); done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -7962,7 +7963,7 @@ static int ipw2100_wx_set_crc_check(struct net_device *dev, struct ipw2100_priv *priv = ieee80211_priv(dev); int err, mode = *(int *)extra; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); if (!(priv->status & STATUS_INITIALIZED)) { err = -EIO; goto done; @@ -7979,7 +7980,7 @@ static int ipw2100_wx_set_crc_check(struct net_device *dev, err = 0; done: - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); return err; } @@ -8284,11 +8285,11 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv) if (priv->status & STATUS_STOPPING) return; - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); IPW_DEBUG_WX("enter\n"); - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); wrqu.ap_addr.sa_family = ARPHRD_ETHER; @@ -8311,7 +8312,7 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv) if (!(priv->status & STATUS_ASSOCIATED)) { IPW_DEBUG_WX("Configuring ESSID\n"); - down(&priv->action_sem); + mutex_lock(&priv->action_mutex); /* This is a disassociation event, so kick the firmware to * look for another AP */ if (priv->config & CFG_STATIC_ESSID) @@ -8319,7 +8320,7 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv) 0); else ipw2100_set_essid(priv, NULL, 0, 0); - up(&priv->action_sem); + mutex_unlock(&priv->action_mutex); } wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index 6f0b40f96abd..7d390f74160f 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -594,8 +594,8 @@ struct ipw2100_priv { int inta_other; spinlock_t low_lock; - struct semaphore action_sem; - struct semaphore adapter_sem; + struct mutex action_mutex; + struct mutex adapter_mutex; wait_queue_head_t wait_command_queue; }; -- cgit v1.2.3-59-g8ed1b From 3234eeec18315356166cd89bd93fc4630192eece Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 28 Feb 2006 08:38:07 +0800 Subject: [PATCH] ipw2100: move mutex.h include from ipw2100.c to ipw2100.h Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2100.c | 1 - drivers/net/wireless/ipw2100.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 54437206f31e..e1bba481982d 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -194,7 +194,6 @@ static struct ipw2100_fw ipw2100_firmware; #endif #include -#include module_param(debug, int, 0444); module_param(mode, int, 0444); module_param(channel, int, 0444); diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index 7d390f74160f..55b7227198df 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -46,6 +46,7 @@ #endif #include +#include struct ipw2100_priv; struct ipw2100_tx_packet; -- cgit v1.2.3-59-g8ed1b From cc8279f68c34c3f32b3a85f3103b0ad755c57846 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 21 Feb 2006 18:46:15 +0800 Subject: [PATCH] ipw2100: Update version ipw2100 stamp to 1.2.2 Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index e1bba481982d..72335c8eb97f 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -167,7 +167,7 @@ that only one external action is invoked at a time. #include "ipw2100.h" -#define IPW2100_VERSION "git-1.1.4" +#define IPW2100_VERSION "git-1.2.2" #define DRV_NAME "ipw2100" #define DRV_VERSION IPW2100_VERSION -- cgit v1.2.3-59-g8ed1b From 7215fdb214ad8d76c9d667be07f870f0f0544959 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 7 Feb 2006 08:49:13 -0200 Subject: [PATCH] Fixed em28xx based system lockup Fixed em28xx based system lockup, device needs to be initialized before starting the isoc transfer otherwise the system will completly lock up. Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-video.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 94a14a2bb6d6..5b267808a9d4 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -367,6 +367,9 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) em28xx_capture_start(dev, 1); em28xx_resolution_set(dev); + /* device needs to be initialized before isoc transfer */ + video_mux(dev, 0); + /* start the transfer */ errCode = em28xx_init_isoc(dev); if (errCode) -- cgit v1.2.3-59-g8ed1b From 60a6dc55b93b3321afa52f650a149fb7e87fa85a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 15 Mar 2006 02:36:13 -0300 Subject: [PATCH] Kconfig: swap VIDEO_CX88_ALSA and VIDEO_CX88_DVB VIDEO_CX88_ALSA should not be between VIDEO_CX88_DVB and VIDEO_CX88_DVB_ALL_FRONTENDS When cx88-alsa was added to cx88/Kconfig, it was added in between VIDEO_CX88_DVB and VIDEO_CX88_DVB_ALL_FRONTENDS. This caused undesireable effects to the appearance of the menu options in menuconfig. This fix reorders cx88-alsa and cx88-dvb in Kconfig, to match saa7134, and restore the correct menuconfig appearance. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/Kconfig | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index e99dfbbf3e95..87d79df05336 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -15,20 +15,6 @@ config VIDEO_CX88 To compile this driver as a module, choose M here: the module will be called cx8800 -config VIDEO_CX88_DVB - tristate "DVB/ATSC Support for cx2388x based TV cards" - depends on VIDEO_CX88 && DVB_CORE - select VIDEO_BUF_DVB - ---help--- - This adds support for DVB/ATSC cards based on the - Connexant 2388x chip. - - To compile this driver as a module, choose M here: the - module will be called cx88-dvb. - - You must also select one or more DVB/ATSC demodulators. - If you are unsure which you need, choose all of them. - config VIDEO_CX88_ALSA tristate "ALSA DMA audio support" depends on VIDEO_CX88 && SND && EXPERIMENTAL @@ -44,6 +30,20 @@ config VIDEO_CX88_ALSA To compile this driver as a module, choose M here: the module will be called cx88-alsa. +config VIDEO_CX88_DVB + tristate "DVB/ATSC Support for cx2388x based TV cards" + depends on VIDEO_CX88 && DVB_CORE + select VIDEO_BUF_DVB + ---help--- + This adds support for DVB/ATSC cards based on the + Connexant 2388x chip. + + To compile this driver as a module, choose M here: the + module will be called cx88-dvb. + + You must also select one or more DVB/ATSC demodulators. + If you are unsure which you need, choose all of them. + config VIDEO_CX88_DVB_ALL_FRONTENDS bool "Build all supported frontends for cx2388x based TV cards" default y -- cgit v1.2.3-59-g8ed1b From 1312f40e11c57edb5c3250f1b782cef8e3efea82 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 Mar 2006 11:02:03 -0500 Subject: [PATCH] regularize blk_cleanup_queue() use Signed-off-by: Al Viro --- drivers/block/loop.c | 4 ++-- drivers/block/pktcdvd.c | 4 ++-- drivers/block/umem.c | 2 +- drivers/md/dm.c | 4 ++-- drivers/md/md.c | 5 ++++- drivers/s390/block/dcssblk.c | 8 ++++---- 6 files changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 5f6d1a5cce11..0010704739e3 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1307,7 +1307,7 @@ static int __init loop_init(void) out_mem4: while (i--) - blk_put_queue(loop_dev[i].lo_queue); + blk_cleanup_queue(loop_dev[i].lo_queue); devfs_remove("loop"); i = max_loop; out_mem3: @@ -1328,7 +1328,7 @@ static void loop_exit(void) for (i = 0; i < max_loop; i++) { del_gendisk(disks[i]); - blk_put_queue(loop_dev[i].lo_queue); + blk_cleanup_queue(loop_dev[i].lo_queue); put_disk(disks[i]); } devfs_remove("loop"); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index bc9b2bcd7dba..476a5b553f34 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2514,7 +2514,7 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) return 0; out_new_dev: - blk_put_queue(disk->queue); + blk_cleanup_queue(disk->queue); out_mem2: put_disk(disk); out_mem: @@ -2555,7 +2555,7 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) DPRINTK("pktcdvd: writer %s unmapped\n", pd->name); del_gendisk(pd->disk); - blk_put_queue(pd->disk->queue); + blk_cleanup_queue(pd->disk->queue); put_disk(pd->disk); pkt_devs[idx] = NULL; diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 4ada1268b40d..c16e66b9c7a7 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -1131,7 +1131,7 @@ static void mm_pci_remove(struct pci_dev *dev) pci_free_consistent(card->dev, PAGE_SIZE*2, card->mm_pages[1].desc, card->mm_pages[1].page_dma); - blk_put_queue(card->queue); + blk_cleanup_queue(card->queue); } static const struct pci_device_id mm_pci_ids[] = { { diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 745ca1f67b14..88d60202b9db 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -840,7 +840,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) bad3: mempool_destroy(md->io_pool); bad2: - blk_put_queue(md->queue); + blk_cleanup_queue(md->queue); free_minor(minor); bad1: kfree(md); @@ -860,7 +860,7 @@ static void free_dev(struct mapped_device *md) del_gendisk(md->disk); free_minor(minor); put_disk(md->disk); - blk_put_queue(md->queue); + blk_cleanup_queue(md->queue); kfree(md); } diff --git a/drivers/md/md.c b/drivers/md/md.c index d05e3125d298..5ed2228745cb 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -213,8 +213,11 @@ static void mddev_put(mddev_t *mddev) return; if (!mddev->raid_disks && list_empty(&mddev->disks)) { list_del(&mddev->all_mddevs); - blk_put_queue(mddev->queue); + /* that blocks */ + blk_cleanup_queue(mddev->queue); + /* that also blocks */ kobject_unregister(&mddev->kobj); + /* result blows... */ } spin_unlock(&all_mddevs_lock); } diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 2e727f49ad19..44133250da2e 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -273,7 +273,7 @@ removeseg: list_del(&dev_info->lh); del_gendisk(dev_info->gd); - blk_put_queue(dev_info->dcssblk_queue); + blk_cleanup_queue(dev_info->dcssblk_queue); dev_info->gd->queue = NULL; put_disk(dev_info->gd); device_unregister(dev); @@ -491,7 +491,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char unregister_dev: PRINT_ERR("device_create_file() failed!\n"); list_del(&dev_info->lh); - blk_put_queue(dev_info->dcssblk_queue); + blk_cleanup_queue(dev_info->dcssblk_queue); dev_info->gd->queue = NULL; put_disk(dev_info->gd); device_unregister(&dev_info->dev); @@ -505,7 +505,7 @@ list_del: unload_seg: segment_unload(local_buf); dealloc_gendisk: - blk_put_queue(dev_info->dcssblk_queue); + blk_cleanup_queue(dev_info->dcssblk_queue); dev_info->gd->queue = NULL; put_disk(dev_info->gd); free_dev_info: @@ -562,7 +562,7 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch list_del(&dev_info->lh); del_gendisk(dev_info->gd); - blk_put_queue(dev_info->dcssblk_queue); + blk_cleanup_queue(dev_info->dcssblk_queue); dev_info->gd->queue = NULL; put_disk(dev_info->gd); device_unregister(&dev_info->dev); -- cgit v1.2.3-59-g8ed1b From ddf19b973be5a96d77c8467f657fe5bd7d126e0f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 18:56:12 +1100 Subject: drm: fixup PCI DMA support This patch makes the PCI support use the correct Linux interfaces finally. Tested in DRM CVS on PCI MGA card. Signed-off-by: Dave Airlie --- drivers/char/drm/drmP.h | 14 +++++++------- drivers/char/drm/drm_bufs.c | 20 +++++++++++--------- drivers/char/drm/drm_dma.c | 4 +--- drivers/char/drm/drm_pci.c | 29 +++++++++++++++++++++++++---- 4 files changed, 44 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 107df9fdba4e..dbe952f899c0 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -357,6 +357,12 @@ typedef struct drm_freelist { spinlock_t lock; } drm_freelist_t; +typedef struct drm_dma_handle { + dma_addr_t busaddr; + void *vaddr; + size_t size; +} drm_dma_handle_t; + /** * Buffer entry. There is one of this for each buffer size order. */ @@ -366,7 +372,7 @@ typedef struct drm_buf_entry { drm_buf_t *buflist; /**< buffer list */ int seg_count; int page_order; - unsigned long *seglist; + drm_dma_handle_t **seglist; drm_freelist_t freelist; } drm_buf_entry_t; @@ -483,12 +489,6 @@ typedef struct drm_sigdata { drm_hw_lock_t *lock; } drm_sigdata_t; -typedef struct drm_dma_handle { - dma_addr_t busaddr; - void *vaddr; - size_t size; -} drm_dma_handle_t; - /** * Mappings list */ diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index e2637b4d51de..8a9cf12e6183 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c @@ -474,8 +474,7 @@ static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry) if (entry->seg_count) { for (i = 0; i < entry->seg_count; i++) { if (entry->seglist[i]) { - drm_free_pages(entry->seglist[i], - entry->page_order, DRM_MEM_DMA); + drm_pci_free(dev, entry->seglist[i]); } } drm_free(entry->seglist, @@ -678,7 +677,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) int total; int page_order; drm_buf_entry_t *entry; - unsigned long page; + drm_dma_handle_t *dmah; drm_buf_t *buf; int alignment; unsigned long offset; @@ -781,8 +780,10 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) page_count = 0; while (entry->buf_count < count) { - page = drm_alloc_pages(page_order, DRM_MEM_DMA); - if (!page) { + + dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful); + + if (!dmah) { /* Set count correctly so we free the proper amount. */ entry->buf_count = count; entry->seg_count = count; @@ -794,13 +795,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) atomic_dec(&dev->buf_alloc); return -ENOMEM; } - entry->seglist[entry->seg_count++] = page; + entry->seglist[entry->seg_count++] = dmah; for (i = 0; i < (1 << page_order); i++) { DRM_DEBUG("page %d @ 0x%08lx\n", dma->page_count + page_count, - page + PAGE_SIZE * i); + (unsigned long)dmah->vaddr + PAGE_SIZE * i); temp_pagelist[dma->page_count + page_count++] - = page + PAGE_SIZE * i; + = (unsigned long)dmah->vaddr + PAGE_SIZE * i; } for (offset = 0; offset + size <= total && entry->buf_count < count; @@ -811,7 +812,8 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) buf->order = order; buf->used = 0; buf->offset = (dma->byte_count + byte_count + offset); - buf->address = (void *)(page + offset); + buf->address = (void *)(dmah->vaddr + offset); + buf->bus_address = dmah->busaddr + offset; buf->next = NULL; buf->waiting = 0; buf->pending = 0; diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c index 2afab95ca036..892db7096986 100644 --- a/drivers/char/drm/drm_dma.c +++ b/drivers/char/drm/drm_dma.c @@ -85,9 +85,7 @@ void drm_dma_takedown(drm_device_t * dev) dma->bufs[i].seg_count); for (j = 0; j < dma->bufs[i].seg_count; j++) { if (dma->bufs[i].seglist[j]) { - drm_free_pages(dma->bufs[i].seglist[j], - dma->bufs[i].page_order, - DRM_MEM_DMA); + drm_pci_free(dev, dma->bufs[i].seglist[j]); } } drm_free(dma->bufs[i].seglist, diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c index 1fd7ff164817..b28ca9cea8a2 100644 --- a/drivers/char/drm/drm_pci.c +++ b/drivers/char/drm/drm_pci.c @@ -50,6 +50,10 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, dma_addr_t maxaddr) { drm_dma_handle_t *dmah; +#if 1 + unsigned long addr; + size_t sz; +#endif #ifdef DRM_DEBUG_MEMORY int area = DRM_MEM_DMA; @@ -79,7 +83,7 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, return NULL; dmah->size = size; - dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr); + dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP); #ifdef DRM_DEBUG_MEMORY if (dmah->vaddr == NULL) { @@ -104,18 +108,29 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, memset(dmah->vaddr, 0, size); + /* XXX - Is virt_to_page() legal for consistent mem? */ + /* Reserve */ + for (addr = (unsigned long)dmah->vaddr, sz = size; + sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { + SetPageReserved(virt_to_page(addr)); + } + return dmah; } EXPORT_SYMBOL(drm_pci_alloc); /** - * \brief Free a PCI consistent memory block with freeing its descriptor. + * \brief Free a PCI consistent memory block without freeing its descriptor. * * This function is for internal use in the Linux-specific DRM core code. */ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) { +#if 1 + unsigned long addr; + size_t sz; +#endif #ifdef DRM_DEBUG_MEMORY int area = DRM_MEM_DMA; int alloc_count; @@ -127,8 +142,14 @@ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) DRM_MEM_ERROR(area, "Attempt to free address 0\n"); #endif } else { - pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr, - dmah->busaddr); + /* XXX - Is virt_to_page() legal for consistent mem? */ + /* Unreserve */ + for (addr = (unsigned long)dmah->vaddr, sz = dmah->size; + sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { + ClearPageReserved(virt_to_page(addr)); + } + dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr, + dmah->busaddr); } #ifdef DRM_DEBUG_MEMORY -- cgit v1.2.3-59-g8ed1b From 45f17100bfd18c99d6479e94598f4e533bbe30d8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 19:12:10 +1100 Subject: drm: update r300 register names Update some of the DRM register names from DRM CVS Signed-off-by: Dave Airlie --- drivers/char/drm/r300_cmdbuf.c | 4 ++-- drivers/char/drm/r300_reg.h | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index c08fa5076f05..9fbadb965858 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c @@ -214,13 +214,13 @@ void r300_init_reg_flags(void) ADD_RANGE(0x4F54, 1); ADD_RANGE(R300_TX_FILTER_0, 16); - ADD_RANGE(R300_TX_UNK1_0, 16); + ADD_RANGE(R300_TX_FILTER1_0, 16); ADD_RANGE(R300_TX_SIZE_0, 16); ADD_RANGE(R300_TX_FORMAT_0, 16); ADD_RANGE(R300_TX_PITCH_0, 16); /* Texture offset is dangerous and needs more checking */ ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); - ADD_RANGE(R300_TX_UNK4_0, 16); + ADD_RANGE(R300_TX_CHROMA_KEY_0, 16); ADD_RANGE(R300_TX_BORDER_COLOR_0, 16); /* Sporadic registers used as primitives are emitted */ diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h index d1e19954406b..a881f96c983e 100644 --- a/drivers/char/drm/r300_reg.h +++ b/drivers/char/drm/r300_reg.h @@ -711,8 +711,22 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_MAX_ANISO_16_TO_1 (8 << 21) # define R300_TX_MAX_ANISO_MASK (14 << 21) -#define R300_TX_UNK1_0 0x4440 +#define R300_TX_FILTER1_0 0x4440 +# define R300_CHROMA_KEY_MODE_DISABLE 0 +# define R300_CHROMA_KEY_FORCE 1 +# define R300_CHROMA_KEY_BLEND 2 +# define R300_MC_ROUND_NORMAL (0<<2) +# define R300_MC_ROUND_MPEG4 (1<<2) # define R300_LOD_BIAS_MASK 0x1fff +# define R300_EDGE_ANISO_EDGE_DIAG (0<<13) +# define R300_EDGE_ANISO_EDGE_ONLY (1<<13) +# define R300_MC_COORD_TRUNCATE_DISABLE (0<<14) +# define R300_MC_COORD_TRUNCATE_MPEG (1<<14) +# define R300_TX_TRI_PERF_0_8 (0<<15) +# define R300_TX_TRI_PERF_1_8 (1<<15) +# define R300_TX_TRI_PERF_1_4 (2<<15) +# define R300_TX_TRI_PERF_3_8 (3<<15) +# define R300_ANISO_THRESHOLD_MASK (7<<17) #define R300_TX_SIZE_0 0x4480 # define R300_TX_WIDTHMASK_SHIFT 0 @@ -722,6 +736,8 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_UNK23 (1 << 23) # define R300_TX_SIZE_SHIFT 26 /* largest of width, height */ # define R300_TX_SIZE_MASK (15 << 26) +# define R300_TX_SIZE_PROJECTED (1<<30) +# define R300_TX_SIZE_TXPITCH_EN (1<<31) #define R300_TX_FORMAT_0 0x44C0 /* The interpretation of the format word by Wladimir van der Laan */ /* The X, Y, Z and W refer to the layout of the components. @@ -750,7 +766,8 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ # define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ /* 0x16 - some 16 bit green format.. ?? */ -# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ +# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ +# define R300_TX_FORMAT_CUBIC_MAP (1 << 26) /* gap */ /* Floating point formats */ @@ -800,18 +817,20 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_FORMAT_YUV_MODE 0x00800000 -#define R300_TX_PITCH_0 0x4500 +#define R300_TX_PITCH_0 0x4500 /* obvious missing in gap */ #define R300_TX_OFFSET_0 0x4540 /* BEGIN: Guess from R200 */ # define R300_TXO_ENDIAN_NO_SWAP (0 << 0) # define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0) # define R300_TXO_ENDIAN_WORD_SWAP (2 << 0) # define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +# define R300_TXO_MACRO_TILE (1 << 2) +# define R300_TXO_MICRO_TILE (1 << 3) # define R300_TXO_OFFSET_MASK 0xffffffe0 # define R300_TXO_OFFSET_SHIFT 5 /* END */ -#define R300_TX_UNK4_0 0x4580 -#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 } +#define R300_TX_CHROMA_KEY_0 0x4580 /* 32 bit chroma key */ +#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 } /* END */ @@ -868,7 +887,9 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_PFS_NODE_TEX_OFFSET_MASK (31 << 12) # define R300_PFS_NODE_TEX_END_SHIFT 17 # define R300_PFS_NODE_TEX_END_MASK (31 << 17) -# define R300_PFS_NODE_LAST_NODE (1 << 22) +/*# define R300_PFS_NODE_LAST_NODE (1 << 22) */ +# define R300_PFS_NODE_OUTPUT_COLOR (1 << 22) +# define R300_PFS_NODE_OUTPUT_DEPTH (1 << 23) /* TEX // As far as I can tell, texture instructions cannot write into output @@ -887,6 +908,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. */ # define R300_FPITX_OPCODE_SHIFT 15 # define R300_FPITX_OP_TEX 1 +# define R300_FPITX_OP_KIL 2 # define R300_FPITX_OP_TXP 3 # define R300_FPITX_OP_TXB 4 @@ -962,9 +984,11 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_FPI1_SRC2C_CONST (1 << 17) # define R300_FPI1_DSTC_SHIFT 18 # define R300_FPI1_DSTC_MASK (31 << 18) +# define R300_FPI1_DSTC_REG_MASK_SHIFT 23 # define R300_FPI1_DSTC_REG_X (1 << 23) # define R300_FPI1_DSTC_REG_Y (1 << 24) # define R300_FPI1_DSTC_REG_Z (1 << 25) +# define R300_FPI1_DSTC_OUTPUT_MASK_SHIFT 26 # define R300_FPI1_DSTC_OUTPUT_X (1 << 26) # define R300_FPI1_DSTC_OUTPUT_Y (1 << 27) # define R300_FPI1_DSTC_OUTPUT_Z (1 << 28) @@ -983,6 +1007,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_FPI3_DSTA_MASK (31 << 18) # define R300_FPI3_DSTA_REG (1 << 23) # define R300_FPI3_DSTA_OUTPUT (1 << 24) +# define R300_FPI3_DSTA_DEPTH (1 << 27) #define R300_PFS_INSTR0_0 0x48C0 # define R300_FPI0_ARGC_SRC0C_XYZ 0 @@ -1036,7 +1061,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_FPI0_OUTC_FRC (9 << 23) # define R300_FPI0_OUTC_REPL_ALPHA (10 << 23) # define R300_FPI0_OUTC_SAT (1 << 30) -# define R300_FPI0_UNKNOWN_31 (1 << 31) +# define R300_FPI0_INSERT_NOP (1 << 31) #define R300_PFS_INSTR2_0 0x49C0 # define R300_FPI2_ARGA_SRC0C_X 0 -- cgit v1.2.3-59-g8ed1b From d5ea702f1e8e3edeea6b673a58281bf99f3dbec5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 19:37:55 +1100 Subject: drm: rework radeon memory map (radeon 1.23) This code reworks the radeon memory map so it works better for newer r300 chips and for a lot of older PCI chips. It really requires a new X driver in order to take advantage of this code. From: Ben Herrenschmidt Signed-off-by: Dave Airlie --- drivers/char/drm/r300_cmdbuf.c | 15 +++-- drivers/char/drm/radeon_cp.c | 143 ++++++++++++++++++++++++++++------------ drivers/char/drm/radeon_drm.h | 1 + drivers/char/drm/radeon_drv.h | 10 ++- drivers/char/drm/radeon_state.c | 58 ++++++++++++---- 5 files changed, 163 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 9fbadb965858..20b6cb39213d 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c @@ -242,8 +242,10 @@ static __inline__ int r300_check_range(unsigned reg, int count) return 0; } - /* we expect offsets passed to the framebuffer to be either within video memory or - within AGP space */ +/* + * we expect offsets passed to the framebuffer to be either within video + * memory or within AGP space + */ static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, u32 offset) { @@ -251,11 +253,11 @@ static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, but this value is not being kept. This code is correct for now (does the same thing as the code that sets MC_FB_LOCATION) in radeon_cp.c */ - if ((offset >= dev_priv->fb_location) && - (offset < dev_priv->gart_vm_start)) + if (offset >= dev_priv->fb_location && + offset < (dev_priv->fb_location + dev_priv->fb_size)) return 0; - if ((offset >= dev_priv->gart_vm_start) && - (offset < dev_priv->gart_vm_start + dev_priv->gart_size)) + if (offset >= dev_priv->gart_vm_start && + offset < (dev_priv->gart_vm_start + dev_priv->gart_size)) return 0; return 1; } @@ -490,6 +492,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, return 0; } + static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, drm_radeon_kcmd_buffer_t *cmdbuf) { diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 9bb8ae0c1c27..cc4942a112cb 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -1118,14 +1118,20 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, { u32 ring_start, cur_read_ptr; u32 tmp; - - /* Initialize the memory controller */ - RADEON_WRITE(RADEON_MC_FB_LOCATION, - ((dev_priv->gart_vm_start - 1) & 0xffff0000) - | (dev_priv->fb_location >> 16)); + + /* Initialize the memory controller. With new memory map, the fb location + * is not changed, it should have been properly initialized already. Part + * of the problem is that the code below is bogus, assuming the GART is + * always appended to the fb which is not necessarily the case + */ + if (!dev_priv->new_memmap) + RADEON_WRITE(RADEON_MC_FB_LOCATION, + ((dev_priv->gart_vm_start - 1) & 0xffff0000) + | (dev_priv->fb_location >> 16)); #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { + RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); RADEON_WRITE(RADEON_MC_AGP_LOCATION, (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & 0xffff0000) | @@ -1153,8 +1159,6 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { - /* set RADEON_AGP_BASE here instead of relying on X from user space */ - RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset - dev->agp->base + dev_priv->gart_vm_start); @@ -1174,6 +1178,17 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, entry->handle + tmp_ofs); } + /* Set ring buffer size */ +#ifdef __BIG_ENDIAN + RADEON_WRITE(RADEON_CP_RB_CNTL, + dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT); +#else + RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw); +#endif + + /* Start with assuming that writeback doesn't work */ + dev_priv->writeback_works = 0; + /* Initialize the scratch register pointer. This will cause * the scratch register values to be written out to memory * whenever they are updated. @@ -1190,28 +1205,9 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); - /* Writeback doesn't seem to work everywhere, test it first */ - DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); - RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); - - for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { - if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) == - 0xdeadbeef) - break; - DRM_UDELAY(1); - } - - if (tmp < dev_priv->usec_timeout) { - dev_priv->writeback_works = 1; - DRM_DEBUG("writeback test succeeded, tmp=%d\n", tmp); - } else { - dev_priv->writeback_works = 0; - DRM_DEBUG("writeback test failed\n"); - } - if (radeon_no_wb == 1) { - dev_priv->writeback_works = 0; - DRM_DEBUG("writeback forced off\n"); - } + /* Turn on bus mastering */ + tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; + RADEON_WRITE(RADEON_BUS_CNTL, tmp); dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); @@ -1223,26 +1219,45 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear); - /* Set ring buffer size */ -#ifdef __BIG_ENDIAN - RADEON_WRITE(RADEON_CP_RB_CNTL, - dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT); -#else - RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw); -#endif - radeon_do_wait_for_idle(dev_priv); - /* Turn on bus mastering */ - tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; - RADEON_WRITE(RADEON_BUS_CNTL, tmp); - /* Sync everything up */ RADEON_WRITE(RADEON_ISYNC_CNTL, (RADEON_ISYNC_ANY2D_IDLE3D | RADEON_ISYNC_ANY3D_IDLE2D | RADEON_ISYNC_WAIT_IDLEGUI | RADEON_ISYNC_CPSCRATCH_IDLEGUI)); + +} + +static void radeon_test_writeback(drm_radeon_private_t * dev_priv) +{ + u32 tmp; + + /* Writeback doesn't seem to work everywhere, test it here and possibly + * enable it if it appears to work + */ + DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); + RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); + + for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { + if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) == + 0xdeadbeef) + break; + DRM_UDELAY(1); + } + + if (tmp < dev_priv->usec_timeout) { + dev_priv->writeback_works = 1; + DRM_INFO("writeback test succeeded in %d usecs\n", tmp); + } else { + dev_priv->writeback_works = 0; + DRM_INFO("writeback test failed\n"); + } + if (radeon_no_wb == 1) { + dev_priv->writeback_works = 0; + DRM_INFO("writeback forced off\n"); + } } /* Enable or disable PCI-E GART on the chip */ @@ -1496,6 +1511,9 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff) << 16; + dev_priv->fb_size = + ((RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u) + 0x10000) + - dev_priv->fb_location; dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | ((dev_priv->front_offset @@ -1510,8 +1528,46 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) + dev_priv->fb_location) >> 10)); dev_priv->gart_size = init->gart_size; - dev_priv->gart_vm_start = dev_priv->fb_location - + RADEON_READ(RADEON_CONFIG_APER_SIZE); + + /* New let's set the memory map ... */ + if (dev_priv->new_memmap) { + u32 base = 0; + + DRM_INFO("Setting GART location based on new memory map\n"); + + /* If using AGP, try to locate the AGP aperture at the same + * location in the card and on the bus, though we have to + * align it down. + */ +#if __OS_HAS_AGP + if (dev_priv->flags & CHIP_IS_AGP) { + base = dev->agp->base; + /* Check if valid */ + if ((base + dev_priv->gart_size) > dev_priv->fb_location && + base < (dev_priv->fb_location + dev_priv->fb_size)) { + DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", + dev->agp->base); + base = 0; + } + } +#endif + /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ + if (base == 0) { + base = dev_priv->fb_location + dev_priv->fb_size; + if (((base + dev_priv->gart_size) & 0xfffffffful) + < base) + base = dev_priv->fb_location + - dev_priv->gart_size; + } + dev_priv->gart_vm_start = base & 0xffc00000u; + if (dev_priv->gart_vm_start != base) + DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n", + base, dev_priv->gart_vm_start); + } else { + DRM_INFO("Setting GART location based on old memory map\n"); + dev_priv->gart_vm_start = dev_priv->fb_location + + RADEON_READ(RADEON_CONFIG_APER_SIZE); + } #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) @@ -1596,6 +1652,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) dev_priv->last_buf = 0; radeon_do_engine_reset(dev); + radeon_test_writeback(dev_priv); return 0; } diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index 9c177a6b2a4c..bb63e6806fd1 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h @@ -697,6 +697,7 @@ typedef struct drm_radeon_setparam { #define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ +#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ /* 1.14: Clients can allocate/free a surface */ diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 1f7d2ab8c4fc..a0c198895a27 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -38,7 +38,7 @@ #define DRIVER_NAME "radeon" #define DRIVER_DESC "ATI Radeon" -#define DRIVER_DATE "20051229" +#define DRIVER_DATE "20060225" /* Interface history: * @@ -91,9 +91,10 @@ * 1.20- Add support for r300 texrect * 1.21- Add support for card type getparam * 1.22- Add support for texture cache flushes (R300_TX_CNTL) + * 1.23- Add new radeon memory map work from benh */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 22 +#define DRIVER_MINOR 23 #define DRIVER_PATCHLEVEL 0 /* @@ -138,7 +139,8 @@ enum radeon_chip_flags { CHIP_IS_PCIE = 0x00200000UL, }; -#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 ) +#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ + DRM_READ32( (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR)) #define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) ) typedef struct drm_radeon_freelist { @@ -199,6 +201,8 @@ typedef struct drm_radeon_private { drm_radeon_sarea_t *sarea_priv; u32 fb_location; + u32 fb_size; + int new_memmap; int gart_size; u32 gart_vm_start; diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 7bc27516d425..56e56b873616 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -45,22 +45,53 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * u32 off = *offset; struct drm_radeon_driver_file_fields *radeon_priv; - if (off >= dev_priv->fb_location && - off < (dev_priv->gart_vm_start + dev_priv->gart_size)) - return 0; - - radeon_priv = filp_priv->driver_priv; - off += radeon_priv->radeon_fb_delta; + /* Hrm ... the story of the offset ... So this function converts + * the various ideas of what userland clients might have for an + * offset in the card address space into an offset into the card + * address space :) So with a sane client, it should just keep + * the value intact and just do some boundary checking. However, + * not all clients are sane. Some older clients pass us 0 based + * offsets relative to the start of the framebuffer and some may + * assume the AGP aperture it appended to the framebuffer, so we + * try to detect those cases and fix them up. + * + * Note: It might be a good idea here to make sure the offset lands + * in some "allowed" area to protect things like the PCIE GART... + */ - DRM_DEBUG("offset fixed up to 0x%x\n", off); + /* First, the best case, the offset already lands in either the + * framebuffer or the GART mapped space + */ + if ((off >= dev_priv->fb_location && + off < (dev_priv->fb_location + dev_priv->fb_size)) || + (off >= dev_priv->gart_vm_start && + off < (dev_priv->gart_vm_start + dev_priv->gart_size))) + return 0; - if (off < dev_priv->fb_location || - off >= (dev_priv->gart_vm_start + dev_priv->gart_size)) - return DRM_ERR(EINVAL); + /* Ok, that didn't happen... now check if we have a zero based + * offset that fits in the framebuffer + gart space, apply the + * magic offset we get from SETPARAM or calculated from fb_location + */ + if (off < (dev_priv->fb_size + dev_priv->gart_size)) { + radeon_priv = filp_priv->driver_priv; + off += radeon_priv->radeon_fb_delta; + } - *offset = off; + /* Finally, assume we aimed at a GART offset if beyond the fb */ + if (off > (dev_priv->fb_location + dev_priv->fb_size)) + off = off - (dev_priv->fb_location + dev_priv->fb_size) + + dev_priv->gart_vm_start; - return 0; + /* Now recheck and fail if out of bounds */ + if ((off >= dev_priv->fb_location && + off < (dev_priv->fb_location + dev_priv->fb_size)) || + (off >= dev_priv->gart_vm_start && + off < (dev_priv->gart_vm_start + dev_priv->gart_size))) { + DRM_DEBUG("offset fixed up to 0x%x\n", off); + *offset = off; + return 0; + } + return DRM_ERR(EINVAL); } static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * @@ -3012,6 +3043,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) case RADEON_SETPARAM_PCIGART_LOCATION: dev_priv->pcigart_offset = sp.value; break; + case RADEON_SETPARAM_NEW_MEMMAP: + dev_priv->new_memmap = sp.value; + break; default: DRM_DEBUG("Invalid parameter %d\n", sp.param); return DRM_ERR(EINVAL); -- cgit v1.2.3-59-g8ed1b From ee4621f011750a6eff9f56631e12ab7fd9503aaa Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 19:45:26 +1100 Subject: drm: Add general-purpose packet for manipulating scratch registers (r300) From: Aapo Tahkola (via DRM CVS) Signed-off-by: Dave Airlie --- drivers/char/drm/r300_cmdbuf.c | 67 ++++++++++++++++++++++++++++++++++++++++++ drivers/char/drm/radeon_drm.h | 4 +++ drivers/char/drm/radeon_drv.h | 5 +++- 3 files changed, 75 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 20b6cb39213d..b108c7f913b2 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c @@ -704,6 +704,64 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf) buf->used = 0; } +static int r300_scratch(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + drm_r300_cmd_header_t header) +{ + u32 *ref_age_base; + u32 i, buf_idx, h_pending; + RING_LOCALS; + + if (cmdbuf->bufsz < + (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) { + return DRM_ERR(EINVAL); + } + + if (header.scratch.reg >= 5) { + return DRM_ERR(EINVAL); + } + + dev_priv->scratch_ages[header.scratch.reg]++; + + ref_age_base = *(u32 **)cmdbuf->buf; + + cmdbuf->buf += sizeof(u64); + cmdbuf->bufsz -= sizeof(u64); + + for (i=0; i < header.scratch.n_bufs; i++) { + buf_idx = *(u32 *)cmdbuf->buf; + buf_idx *= 2; /* 8 bytes per buf */ + + if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + if (h_pending == 0) { + return DRM_ERR(EINVAL); + } + + h_pending--; + + if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + cmdbuf->buf += sizeof(buf_idx); + cmdbuf->bufsz -= sizeof(buf_idx); + } + + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0)); + OUT_RING(dev_priv->scratch_ages[header.scratch.reg]); + ADVANCE_RING(); + + return 0; +} + /** * Parses and validates a user-supplied command buffer and emits appropriate * commands on the DMA ring buffer. @@ -841,6 +899,15 @@ int r300_do_cp_cmdbuf(drm_device_t *dev, } break; + case R300_CMD_SCRATCH: + DRM_DEBUG("R300_CMD_SCRATCH\n"); + ret = r300_scratch(dev_priv, cmdbuf, header); + if (ret) { + DRM_ERROR("r300_scratch failed\n"); + goto cleanup; + } + break; + default: DRM_ERROR("bad cmd_type %i at %p\n", header.header.cmd_type, diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index bb63e6806fd1..c8e279e89c2e 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h @@ -222,6 +222,7 @@ typedef union { # define R300_WAIT_3D 0x2 # define R300_WAIT_2D_CLEAN 0x3 # define R300_WAIT_3D_CLEAN 0x4 +#define R300_CMD_SCRATCH 8 typedef union { unsigned int u; @@ -247,6 +248,9 @@ typedef union { struct { unsigned char cmd_type, flags, pad0, pad1; } wait; + struct { + unsigned char cmd_type, reg, n_bufs, flags; + } scratch; } drm_r300_cmd_header_t; #define RADEON_FRONT 0x1 diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index a0c198895a27..5cf555e4637b 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -92,9 +92,10 @@ * 1.21- Add support for card type getparam * 1.22- Add support for texture cache flushes (R300_TX_CNTL) * 1.23- Add new radeon memory map work from benh + * 1.24- Add general-purpose packet for manipulating scratch registers (r300) */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 23 +#define DRIVER_MINOR 24 #define DRIVER_PATCHLEVEL 0 /* @@ -276,6 +277,8 @@ typedef struct drm_radeon_private { unsigned long pcigart_offset; drm_ati_pcigart_info gart_info; + u32 scratch_ages[5]; + /* starting from here on, data is preserved accross an open */ uint32_t flags; /* see radeon_chip_flags */ } drm_radeon_private_t; -- cgit v1.2.3-59-g8ed1b From dfab11542fbecd8539c092fe36155909b4812f73 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 20:01:37 +1100 Subject: drm: rationalise some pci ids This is the start of some work from Roland Scheidegger to align the X DDX pci ids and the drm ones, however we don't want to put r300 ids in the kernel just yet, they destabilise a few machines. From: Roland Scheidegger (via DRM CVS) Signed-off-by: Dave Airlie --- drivers/char/drm/drm_pciids.h | 19 ++++++++----------- drivers/char/drm/radeon_drv.h | 11 ++++++----- 2 files changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 2c17e88a8847..24b80357b967 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -3,7 +3,7 @@ Please contact dri-devel@lists.sf.net to add new cards to this list */ #define radeon_PCI_IDS \ - {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350},\ + {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY},\ {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ @@ -16,26 +16,23 @@ {0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ - {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP}, \ + {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ - {0x1002, 0x4965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ - {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ - {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ + {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ + {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 5cf555e4637b..31bacfa2edee 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -103,20 +103,21 @@ */ enum radeon_family { CHIP_R100, - CHIP_RS100, CHIP_RV100, + CHIP_RS100, CHIP_RV200, - CHIP_R200, CHIP_RS200, - CHIP_R250, - CHIP_RS250, + CHIP_R200, CHIP_RV250, + CHIP_RS300, CHIP_RV280, CHIP_R300, - CHIP_RS300, CHIP_R350, CHIP_RV350, + CHIP_RV380, CHIP_R420, + CHIP_RV410, + CHIP_RS400, CHIP_LAST, }; -- cgit v1.2.3-59-g8ed1b From f15e92d702bba47f451bd5f63e170252c6e1bba2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 20:12:23 +1100 Subject: drm: fixup improper cast. Signed-off-by: Dave Airlie --- drivers/char/drm/radeon_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 56e56b873616..b006b1c5d856 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -1996,7 +1996,7 @@ static int radeon_surface_free(DRM_IOCTL_ARGS) return DRM_ERR(EINVAL); } - DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data, + DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data, sizeof(memfree)); if (free_surface(filp, dev_priv, memfree.address)) -- cgit v1.2.3-59-g8ed1b From 2fab58d1a18c752887c2b9f6ee7b6997ced4a77a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 20:15:41 +1100 Subject: drm: remove pointless checks in radeon_state If these were valid checks, we'd have already oopsed several lines above where we were already dereferencing them. DA: these used to be valid but other changes made them unnecessary. Coverity: 776,777,778 Signed-off-by: Dave Jones Signed-off-by: Dave Airlie --- drivers/char/drm/radeon_state.c | 45 ----------------------------------------- 1 file changed, 45 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index b006b1c5d856..c5b8f774a599 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -1970,11 +1970,6 @@ static int radeon_surface_alloc(DRM_IOCTL_ARGS) drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_surface_alloc_t alloc; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_surface_alloc_t __user *) data, sizeof(alloc)); @@ -1991,11 +1986,6 @@ static int radeon_surface_free(DRM_IOCTL_ARGS) drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_surface_free_t memfree; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data, sizeof(memfree)); @@ -2131,11 +2121,6 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data, @@ -2220,11 +2205,6 @@ static int radeon_cp_indices(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data, @@ -2371,11 +2351,6 @@ static int radeon_cp_indirect(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_COPY_FROM_USER_IOCTL(indirect, (drm_radeon_indirect_t __user *) data, sizeof(indirect)); @@ -2448,11 +2423,6 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data, @@ -2769,11 +2739,6 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(cmdbuf, @@ -2928,11 +2893,6 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) drm_radeon_getparam_t param; int value; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data, sizeof(param)); @@ -3012,11 +2972,6 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) drm_radeon_setparam_t sp; struct drm_radeon_driver_file_fields *radeon_priv; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data, -- cgit v1.2.3-59-g8ed1b From e7f947b908921a661efcbc08ce42d7de67691b07 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 20:28:19 +1100 Subject: drm: fixup i915 breadcrumb read/write Some minor issues in the i915 breadcrumb code. Signed-off-by: Dave Airlie --- drivers/char/drm/i915_dma.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 1ff4c7ca0bff..9f4b8ce4c05e 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c @@ -495,8 +495,6 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev, } } - dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; - i915_emit_breadcrumb(dev); return 0; -- cgit v1.2.3-59-g8ed1b From 75913d9bb8328c4eca54cad39a5fb665b48383eb Mon Sep 17 00:00:00 2001 From: adam radford Date: Wed, 15 Mar 2006 12:43:19 -0800 Subject: [SCSI] 3ware 9000 add big endian support The attached patch updates the 3ware 9000 driver: - Fix 9550SX pchip reset timeout. - Add big endian support. Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/3w-9xxx.c | 138 ++++++++++++++++++++++++------------------------- drivers/scsi/3w-9xxx.h | 18 ++----- 2 files changed, 73 insertions(+), 83 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index d9152d02088c..0ab26d01877b 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -2,8 +2,9 @@ 3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux. Written By: Adam Radford + Modifications By: Tom Couch - Copyright (C) 2004-2005 Applied Micro Circuits Corporation. + Copyright (C) 2004-2006 Applied Micro Circuits 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 @@ -62,6 +63,8 @@ 2.26.02.003 - Correctly handle single sgl's with use_sg=1. 2.26.02.004 - Add support for 9550SX controllers. 2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher. + 2.26.02.006 - Fix 9550SX pchip reset timeout. + Add big endian support. */ #include @@ -85,7 +88,7 @@ #include "3w-9xxx.h" /* Globals */ -#define TW_DRIVER_VERSION "2.26.02.005" +#define TW_DRIVER_VERSION "2.26.02.006" static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; static unsigned int twa_device_extension_count; static int twa_major = -1; @@ -208,7 +211,7 @@ static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id) header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id]; tw_dev->posted_request_count--; - aen = header->status_block.error; + aen = le16_to_cpu(header->status_block.error); full_command_packet = tw_dev->command_packet_virt[request_id]; command_packet = &full_command_packet->command.oldcommand; @@ -305,7 +308,7 @@ static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset) tw_dev->posted_request_count--; header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id]; - aen = header->status_block.error; + aen = le16_to_cpu(header->status_block.error); queue = 0; count++; @@ -365,7 +368,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H tw_dev->aen_clobber = 1; } - aen = header->status_block.error; + aen = le16_to_cpu(header->status_block.error); memset(event, 0, sizeof(TW_Event)); event->severity = TW_SEV_OUT(header->status_block.severity__reserved); @@ -382,7 +385,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0'; event->parameter_len = strlen(header->err_specific_desc); - memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len); + memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len + (error_str[0] == '\0' ? 0 : (1 + strlen(error_str)))); if (event->severity != TW_AEN_SEVERITY_DEBUG) printk(KERN_WARNING "3w-9xxx:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n", host, @@ -462,24 +465,24 @@ static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id) command_packet = &full_command_packet->command.oldcommand; command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM); command_packet->request_id = request_id; - command_packet->byte8_offset.param.sgl[0].address = tw_dev->generic_buffer_phys[request_id]; - command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE; + command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); + command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE); command_packet->size = TW_COMMAND_SIZE; - command_packet->byte6_offset.parameter_count = 1; + command_packet->byte6_offset.parameter_count = cpu_to_le16(1); /* Setup the param */ param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id]; memset(param, 0, TW_SECTOR_SIZE); - param->table_id = TW_TIMEKEEP_TABLE | 0x8000; /* Controller time keep table */ - param->parameter_id = 0x3; /* SchedulerTime */ - param->parameter_size_bytes = 4; + param->table_id = cpu_to_le16(TW_TIMEKEEP_TABLE | 0x8000); /* Controller time keep table */ + param->parameter_id = cpu_to_le16(0x3); /* SchedulerTime */ + param->parameter_size_bytes = cpu_to_le16(4); /* Convert system time in UTC to local time seconds since last Sunday 12:00AM */ do_gettimeofday(&utc); local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60)); schedulertime = local_time - (3 * 86400); - schedulertime = schedulertime % 604800; + schedulertime = cpu_to_le32(schedulertime % 604800); memcpy(param->data, &schedulertime, sizeof(u32)); @@ -931,26 +934,19 @@ out: /* This function will clear the pchip/response queue on 9550SX */ static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev) { - u32 status_reg_value, response_que_value; - int count = 0, retval = 1; + u32 response_que_value = 0; + unsigned long before; + int retval = 1; if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) { - status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); - - while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) { + before = jiffies; + while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); - if ((response_que_value & TW_9550SX_DRAIN_COMPLETED) == TW_9550SX_DRAIN_COMPLETED) { - /* P-chip settle time */ - msleep(500); - retval = 0; + if (time_after(jiffies, before + HZ * 30)) goto out; - } - status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); - count++; } - if (count == TW_MAX_RESPONSE_DRAIN) - goto out; - + /* P-chip settle time */ + msleep(500); retval = 0; } else retval = 0; @@ -972,7 +968,7 @@ static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_ error_str = &(full_command_packet->header.err_specific_desc[strlen(full_command_packet->header.err_specific_desc) + 1]); /* Don't print error for Logical unit not supported during rollcall */ - error = full_command_packet->header.status_block.error; + error = le16_to_cpu(full_command_packet->header.status_block.error); if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE)) { if (print_host) printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s:%s.\n", @@ -1047,18 +1043,18 @@ static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int tabl command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM); command_packet->size = TW_COMMAND_SIZE; command_packet->request_id = request_id; - command_packet->byte6_offset.block_count = 1; + command_packet->byte6_offset.block_count = cpu_to_le16(1); /* Now setup the param */ param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id]; memset(param, 0, TW_SECTOR_SIZE); - param->table_id = table_id | 0x8000; - param->parameter_id = parameter_id; - param->parameter_size_bytes = parameter_size_bytes; + param->table_id = cpu_to_le16(table_id | 0x8000); + param->parameter_id = cpu_to_le16(parameter_id); + param->parameter_size_bytes = cpu_to_le16(parameter_size_bytes); param_value = tw_dev->generic_buffer_phys[request_id]; - command_packet->byte8_offset.param.sgl[0].address = param_value; - command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE; + command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(param_value); + command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE); /* Post the command packet to the board */ twa_post_command_packet(tw_dev, request_id, 1); @@ -1107,18 +1103,20 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits, tw_initconnect = (TW_Initconnect *)&full_command_packet->command.oldcommand; tw_initconnect->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION); tw_initconnect->request_id = request_id; - tw_initconnect->message_credits = message_credits; + tw_initconnect->message_credits = cpu_to_le16(message_credits); tw_initconnect->features = set_features; /* Turn on 64-bit sgl support if we need to */ tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0; + tw_initconnect->features = cpu_to_le32(tw_initconnect->features); + if (set_features & TW_EXTENDED_INIT_CONNECT) { tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED; - tw_initconnect->fw_srl = current_fw_srl; - tw_initconnect->fw_arch_id = current_fw_arch_id; - tw_initconnect->fw_branch = current_fw_branch; - tw_initconnect->fw_build = current_fw_build; + tw_initconnect->fw_srl = cpu_to_le16(current_fw_srl); + tw_initconnect->fw_arch_id = cpu_to_le16(current_fw_arch_id); + tw_initconnect->fw_branch = cpu_to_le16(current_fw_branch); + tw_initconnect->fw_build = cpu_to_le16(current_fw_build); } else tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE; @@ -1130,11 +1128,11 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits, TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "No valid response during init connection"); } else { if (set_features & TW_EXTENDED_INIT_CONNECT) { - *fw_on_ctlr_srl = tw_initconnect->fw_srl; - *fw_on_ctlr_arch_id = tw_initconnect->fw_arch_id; - *fw_on_ctlr_branch = tw_initconnect->fw_branch; - *fw_on_ctlr_build = tw_initconnect->fw_build; - *init_connect_result = tw_initconnect->result; + *fw_on_ctlr_srl = le16_to_cpu(tw_initconnect->fw_srl); + *fw_on_ctlr_arch_id = le16_to_cpu(tw_initconnect->fw_arch_id); + *fw_on_ctlr_branch = le16_to_cpu(tw_initconnect->fw_branch); + *fw_on_ctlr_build = le16_to_cpu(tw_initconnect->fw_build); + *init_connect_result = le32_to_cpu(tw_initconnect->result); } retval = 0; } @@ -1358,10 +1356,10 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d newcommand = &full_command_packet->command.newcommand; newcommand->request_id__lunl = TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id); - newcommand->sg_list[0].address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1; - newcommand->sg_list[0].length = length; + newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); + newcommand->sg_list[0].length = cpu_to_le32(length); newcommand->sgl_entries__lunh = - TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1); + cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1)); } else { oldcommand = &full_command_packet->command.oldcommand; oldcommand->request_id = request_id; @@ -1369,8 +1367,8 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { /* Load the sg list */ sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); - sgl->address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1; - sgl->length = length; + sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); + sgl->length = cpu_to_le32(length); if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) oldcommand->size += 1; @@ -1828,10 +1826,10 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, if (srb) { command_packet->unit = srb->device->id; command_packet->request_id__lunl = - TW_REQ_LUN_IN(srb->device->lun, request_id); + cpu_to_le16(TW_REQ_LUN_IN(srb->device->lun, request_id)); } else { command_packet->request_id__lunl = - TW_REQ_LUN_IN(0, request_id); + cpu_to_le16(TW_REQ_LUN_IN(0, request_id)); command_packet->unit = 0; } @@ -1841,8 +1839,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, /* Map sglist from scsi layer to cmd packet */ if (tw_dev->srb[request_id]->use_sg == 0) { if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) { - command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id]; - command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH; + command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); + command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH); if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen); } else { @@ -1850,12 +1848,12 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, if (buffaddr == 0) goto out; - command_packet->sg_list[0].address = buffaddr; - command_packet->sg_list[0].length = tw_dev->srb[request_id]->request_bufflen; + command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr); + command_packet->sg_list[0].length = cpu_to_le32(tw_dev->srb[request_id]->request_bufflen); } - command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), 1); + command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1)); - if (command_packet->sg_list[0].address & TW_ALIGNMENT_9000_SGL) { + if (command_packet->sg_list[0].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi"); goto out; } @@ -1869,35 +1867,35 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length); kunmap_atomic(buf - sg->offset, KM_IRQ0); } - command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id]; - command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH; + command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); + command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH); } else { sg_count = twa_map_scsi_sg_data(tw_dev, request_id); if (sg_count == 0) goto out; for (i = 0; i < sg_count; i++) { - command_packet->sg_list[i].address = sg_dma_address(&sglist[i]); - command_packet->sg_list[i].length = sg_dma_len(&sglist[i]); - if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) { + command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i])); + command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i])); + if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi"); goto out; } } } - command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg); + command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg)); } } else { /* Internal cdb post */ for (i = 0; i < use_sg; i++) { - command_packet->sg_list[i].address = sglistarg[i].address; - command_packet->sg_list[i].length = sglistarg[i].length; - if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) { + command_packet->sg_list[i].address = TW_CPU_TO_SGL(sglistarg[i].address); + command_packet->sg_list[i].length = cpu_to_le32(sglistarg[i].length); + if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2f, "Found unaligned sgl address during internal post"); goto out; } } - command_packet->sgl_entries__lunh = TW_REQ_LUN_IN(0, use_sg); + command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN(0, use_sg)); } if (srb) { @@ -2115,8 +2113,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id TW_PARAM_FWVER, TW_PARAM_FWVER_LENGTH), (char *)twa_get_param(tw_dev, 1, TW_VERSION_TABLE, TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH), - *(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE, - TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH)); + le32_to_cpu(*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE, + TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH))); /* Now setup the interrupt handler */ retval = request_irq(pdev->irq, twa_interrupt, SA_SHIRQ, "3w-9xxx", tw_dev); diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index 1b16d57f0314..e5685be96f45 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h @@ -2,8 +2,9 @@ 3w-9xxx.h -- 3ware 9000 Storage Controller device driver for Linux. Written By: Adam Radford + Modifications By: Tom Couch - Copyright (C) 2004-2005 Applied Micro Circuits Corporation. + Copyright (C) 2004-2006 Applied Micro Circuits 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 @@ -287,9 +288,6 @@ static twa_message_type twa_error_table[] = { #define TW_STATUS_UNEXPECTED_BITS 0x00F00000 #define TW_STATUS_VALID_INTERRUPT 0x00DF0000 -/* RESPONSE QUEUE BIT DEFINITIONS */ -#define TW_RESPONSE_ID_MASK 0x00000FF0 - /* PCI related defines */ #define TW_NUMDEVICES 1 #define TW_PCI_CLEAR_PARITY_ERRORS 0xc100 @@ -471,6 +469,7 @@ printk(KERN_WARNING "3w-9xxx: ERROR: (0x%02X:0x%04X): %s.\n",a,b,c); \ #define TW_APACHE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 72 : 109) #define TW_ESCALADE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 41 : 62) #define TW_PADDING_LENGTH (sizeof(dma_addr_t) > 4 ? 8 : 0) +#define TW_CPU_TO_SGL(x) (sizeof(dma_addr_t) > 4 ? cpu_to_le64(x) : cpu_to_le32(x)) #pragma pack(1) @@ -614,13 +613,6 @@ typedef union TAG_TW_Response_Queue { u32 value; } TW_Response_Queue; -typedef struct TAG_TW_Info { - char *buffer; - int length; - int offset; - int position; -} TW_Info; - /* Compatibility information structure */ typedef struct TAG_TW_Compatibility_Info { @@ -636,6 +628,8 @@ typedef struct TAG_TW_Compatibility_Info unsigned short driver_build_low; } TW_Compatibility_Info; +#pragma pack() + typedef struct TAG_TW_Device_Extension { u32 __iomem *base_addr; unsigned long *generic_buffer_virt[TW_Q_LENGTH]; @@ -679,7 +673,5 @@ typedef struct TAG_TW_Device_Extension { unsigned short working_build; } TW_Device_Extension; -#pragma pack() - #endif /* _3W_9XXX_H */ -- cgit v1.2.3-59-g8ed1b From 5baba830e93732e802dc7e0a362eb730e1917f58 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 18 Mar 2006 14:10:35 -0600 Subject: [SCSI] add scsi_mode_select to scsi_lib.c This complements the scsi_mode_sense() function Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 81 +++++++++++++++++++++++++++++++++++++++++++++- include/scsi/scsi_device.h | 5 +++ 2 files changed, 85 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9a05076f9cf4..ede158d08d9d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1811,6 +1811,84 @@ void scsi_exit_queue(void) kmem_cache_destroy(sgp->slab); } } + +/** + * scsi_mode_select - issue a mode select + * @sdev: SCSI device to be queried + * @pf: Page format bit (1 == standard, 0 == vendor specific) + * @sp: Save page bit (0 == don't save, 1 == save) + * @modepage: mode page being requested + * @buffer: request buffer (may not be smaller than eight bytes) + * @len: length of request buffer. + * @timeout: command timeout + * @retries: number of retries before failing + * @data: returns a structure abstracting the mode header data + * @sense: place to put sense data (or NULL if no sense to be collected). + * must be SCSI_SENSE_BUFFERSIZE big. + * + * Returns zero if successful; negative error number or scsi + * status on error + * + */ +int +scsi_mode_select(struct scsi_device *sdev, int pf, int sp, int modepage, + unsigned char *buffer, int len, int timeout, int retries, + struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) +{ + unsigned char cmd[10]; + unsigned char *real_buffer; + int ret; + + memset(cmd, 0, sizeof(cmd)); + cmd[1] = (pf ? 0x10 : 0) | (sp ? 0x01 : 0); + + if (sdev->use_10_for_ms) { + if (len > 65535) + return -EINVAL; + real_buffer = kmalloc(8 + len, GFP_KERNEL); + if (!real_buffer) + return -ENOMEM; + memcpy(real_buffer + 8, buffer, len); + len += 8; + real_buffer[0] = 0; + real_buffer[1] = 0; + real_buffer[2] = data->medium_type; + real_buffer[3] = data->device_specific; + real_buffer[4] = data->longlba ? 0x01 : 0; + real_buffer[5] = 0; + real_buffer[6] = data->block_descriptor_length >> 8; + real_buffer[7] = data->block_descriptor_length; + + cmd[0] = MODE_SELECT_10; + cmd[7] = len >> 8; + cmd[8] = len; + } else { + if (len > 255 || data->block_descriptor_length > 255 || + data->longlba) + return -EINVAL; + + real_buffer = kmalloc(4 + len, GFP_KERNEL); + if (!real_buffer) + return -ENOMEM; + memcpy(real_buffer + 4, buffer, len); + len += 4; + real_buffer[0] = 0; + real_buffer[1] = data->medium_type; + real_buffer[2] = data->device_specific; + real_buffer[3] = data->block_descriptor_length; + + + cmd[0] = MODE_SELECT; + cmd[4] = len; + } + + ret = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, real_buffer, len, + sshdr, timeout, retries); + kfree(real_buffer); + return ret; +} +EXPORT_SYMBOL_GPL(scsi_mode_select); + /** * scsi_mode_sense - issue a mode sense, falling back from 10 to * six bytes if necessary. @@ -1832,7 +1910,8 @@ void scsi_exit_queue(void) int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, int retries, - struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) { + struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) +{ unsigned char cmd[12]; int use_10_for_ms; int header_length; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index f2193cd0d31f..895d212864cd 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -261,6 +261,11 @@ extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, int retries, struct scsi_mode_data *data, struct scsi_sense_hdr *); +extern int scsi_mode_select(struct scsi_device *sdev, int pf, int sp, + int modepage, unsigned char *buffer, int len, + int timeout, int retries, + struct scsi_mode_data *data, + struct scsi_sense_hdr *); extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries); extern int scsi_device_set_state(struct scsi_device *sdev, -- cgit v1.2.3-59-g8ed1b From 6bdaa1f17dd32ec62345c7b57842f53e6278a2fa Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 18 Mar 2006 14:14:21 -0600 Subject: [SCSI] allow displaying and setting of cache type via sysfs I think I promised to do this two years ago This patch adds a scsi_disk class with the cache type and FUA parameters, so user land application can easily obtain them without having to parse dmesg. It also allows setting the cache type (use with care...) This patch is a bit dangerous because I've replaced the disk kref with a class device reference ... Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 136 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 113 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3b01e5d6221c..024ef86c5242 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -115,12 +114,10 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR); */ #define SD_BUF_SIZE 512 -static void scsi_disk_release(struct kref *kref); - struct scsi_disk { struct scsi_driver *driver; /* always &sd_template */ struct scsi_device *device; - struct kref kref; + struct class_device cdev; struct gendisk *disk; unsigned int openers; /* protected by BKL for now, yuck */ sector_t capacity; /* size in 512-byte sectors */ @@ -131,6 +128,7 @@ struct scsi_disk { unsigned RCD : 1; /* state of disk RCD bit, unused */ unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ }; +#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev) static DEFINE_IDR(sd_index_idr); static DEFINE_SPINLOCK(sd_index_lock); @@ -152,6 +150,92 @@ static int sd_issue_flush(struct device *, sector_t *); static void sd_prepare_flush(request_queue_t *, struct request *); static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, unsigned char *buffer); +static void scsi_disk_release(struct class_device *cdev); + +static const char *sd_cache_types[] = { + "write through", "none", "write back", + "write back, no read (daft)" +}; + +static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf, + size_t count) +{ + int i, ct = -1, rcd, wce, sp; + struct scsi_disk *sdkp = to_scsi_disk(cdev); + struct scsi_device *sdp = sdkp->device; + char buffer[64]; + char *buffer_data; + struct scsi_mode_data data; + struct scsi_sense_hdr sshdr; + int len; + + if (sdp->type != TYPE_DISK) + /* no cache control on RBC devices; theoretically they + * can do it, but there's probably so many exceptions + * it's not worth the risk */ + return -EINVAL; + + for (i = 0; i < sizeof(sd_cache_types)/sizeof(sd_cache_types[0]); i++) { + const int len = strlen(sd_cache_types[i]); + if (strncmp(sd_cache_types[i], buf, len) == 0 && + buf[len] == '\n') { + ct = i; + break; + } + } + if (ct < 0) + return -EINVAL; + rcd = ct & 0x01 ? 1 : 0; + wce = ct & 0x02 ? 1 : 0; + if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT, + SD_MAX_RETRIES, &data, NULL)) + return -EINVAL; + len = min(sizeof(buffer), data.length - data.header_length - + data.block_descriptor_length); + buffer_data = buffer + data.header_length + + data.block_descriptor_length; + buffer_data[2] &= ~0x05; + buffer_data[2] |= wce << 2 | rcd; + sp = buffer_data[0] & 0x80 ? 1 : 0; + + if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT, + SD_MAX_RETRIES, &data, &sshdr)) { + if (scsi_sense_valid(&sshdr)) + scsi_print_sense_hdr(sdkp->disk->disk_name, &sshdr); + return -EINVAL; + } + sd_revalidate_disk(sdkp->disk); + return count; +} + +static ssize_t sd_show_cache_type(struct class_device *cdev, char *buf) +{ + struct scsi_disk *sdkp = to_scsi_disk(cdev); + int ct = sdkp->RCD + 2*sdkp->WCE; + + return snprintf(buf, 40, "%s\n", sd_cache_types[ct]); +} + +static ssize_t sd_show_fua(struct class_device *cdev, char *buf) +{ + struct scsi_disk *sdkp = to_scsi_disk(cdev); + + return snprintf(buf, 20, "%u\n", sdkp->DPOFUA); +} + +static struct class_device_attribute sd_disk_attrs[] = { + __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, + sd_store_cache_type), + __ATTR(FUA, S_IRUGO, sd_show_fua, NULL), + __ATTR_NULL, +}; + +static struct class sd_disk_class = { + .name = "scsi_disk", + .owner = THIS_MODULE, + .release = scsi_disk_release, + .class_dev_attrs = sd_disk_attrs, +}; static struct scsi_driver sd_template = { .owner = THIS_MODULE, @@ -195,8 +279,6 @@ static int sd_major(int major_idx) } } -#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,kref) - static inline struct scsi_disk *scsi_disk(struct gendisk *disk) { return container_of(disk->private_data, struct scsi_disk, driver); @@ -209,7 +291,7 @@ static struct scsi_disk *__scsi_disk_get(struct gendisk *disk) if (disk->private_data) { sdkp = scsi_disk(disk); if (scsi_device_get(sdkp->device) == 0) - kref_get(&sdkp->kref); + class_device_get(&sdkp->cdev); else sdkp = NULL; } @@ -243,7 +325,7 @@ static void scsi_disk_put(struct scsi_disk *sdkp) struct scsi_device *sdev = sdkp->device; mutex_lock(&sd_ref_mutex); - kref_put(&sdkp->kref, scsi_disk_release); + class_device_put(&sdkp->cdev); scsi_device_put(sdev); mutex_unlock(&sd_ref_mutex); } @@ -1381,10 +1463,6 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); if (scsi_status_is_good(res)) { - const char *types[] = { - "write through", "none", "write back", - "write back, no read (daft)" - }; int ct = 0; int offset = data.header_length + data.block_descriptor_length; @@ -1417,7 +1495,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, ct = sdkp->RCD + 2*sdkp->WCE; printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n", - diskname, types[ct], + diskname, sd_cache_types[ct], sdkp->DPOFUA ? " w/ FUA" : ""); return; @@ -1548,8 +1626,6 @@ static int sd_probe(struct device *dev) if (!sdkp) goto out; - kref_init(&sdkp->kref); - gd = alloc_disk(16); if (!gd) goto out_free; @@ -1566,7 +1642,16 @@ static int sd_probe(struct device *dev) if (error) goto out_put; + class_device_initialize(&sdkp->cdev); + sdkp->cdev.dev = &sdp->sdev_gendev; + sdkp->cdev.class = &sd_disk_class; + strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE); + + if (class_device_add(&sdkp->cdev)) + goto out_put; + get_device(&sdp->sdev_gendev); + sdkp->device = sdp; sdkp->driver = &sd_template; sdkp->disk = gd; @@ -1616,11 +1701,11 @@ static int sd_probe(struct device *dev) return 0; -out_put: + out_put: put_disk(gd); -out_free: + out_free: kfree(sdkp); -out: + out: return error; } @@ -1639,12 +1724,13 @@ static int sd_remove(struct device *dev) { struct scsi_disk *sdkp = dev_get_drvdata(dev); + class_device_del(&sdkp->cdev); del_gendisk(sdkp->disk); sd_shutdown(dev); mutex_lock(&sd_ref_mutex); dev_set_drvdata(dev, NULL); - kref_put(&sdkp->kref, scsi_disk_release); + class_device_put(&sdkp->cdev); mutex_unlock(&sd_ref_mutex); return 0; @@ -1652,16 +1738,16 @@ static int sd_remove(struct device *dev) /** * scsi_disk_release - Called to free the scsi_disk structure - * @kref: pointer to embedded kref + * @cdev: pointer to embedded class device * * sd_ref_mutex must be held entering this routine. Because it is * called on last put, you should always use the scsi_disk_get() * scsi_disk_put() helpers which manipulate the semaphore directly - * and never do a direct kref_put(). + * and never do a direct class_device_put(). **/ -static void scsi_disk_release(struct kref *kref) +static void scsi_disk_release(struct class_device *cdev) { - struct scsi_disk *sdkp = to_scsi_disk(kref); + struct scsi_disk *sdkp = to_scsi_disk(cdev); struct gendisk *disk = sdkp->disk; spin_lock(&sd_index_lock); @@ -1715,6 +1801,8 @@ static int __init init_sd(void) if (!majors) return -ENODEV; + class_register(&sd_disk_class); + return scsi_register_driver(&sd_template.gendrv); } @@ -1732,6 +1820,8 @@ static void __exit exit_sd(void) scsi_unregister_driver(&sd_template.gendrv); for (i = 0; i < SD_MAJORS; i++) unregister_blkdev(sd_major(i), "sd"); + + class_unregister(&sd_disk_class); } module_init(init_sd); -- cgit v1.2.3-59-g8ed1b From f013db3284376070fc4c196e58d204180b8ed62a Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 18 Mar 2006 14:54:36 -0600 Subject: [SCSI] convert mptsas over to end_device/expander allocations The conversion of mptsas should allow the elimination of the contained flag in the sas transport class. Acked-by: "Moore, Eric" Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 45 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index be4eb8a308b7..010d4a39269b 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -363,6 +363,14 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, return error; } +static int +mptsas_slave_configure(struct scsi_device *sdev) +{ + sas_read_port_mode_page(sdev); + + return mptscsih_slave_configure(sdev); +} + /* * This is pretty ugly. We will be able to seriously clean it up * once the DV code in mptscsih goes away and we can properly @@ -486,7 +494,7 @@ static struct scsi_host_template mptsas_driver_template = { .queuecommand = mptscsih_qcmd, .target_alloc = mptscsih_target_alloc, .slave_alloc = mptsas_slave_alloc, - .slave_configure = mptscsih_slave_configure, + .slave_configure = mptsas_slave_configure, .target_destroy = mptscsih_target_destroy, .slave_destroy = mptsas_slave_destroy, .change_queue_depth = mptscsih_change_queue_depth, @@ -1249,6 +1257,7 @@ static int mptsas_probe_one_phy(struct device *dev, (!phy_info->rphy)) { struct sas_rphy *rphy; + struct sas_identify identify; ioc = phy_to_ioc(phy_info->phy); @@ -1261,11 +1270,24 @@ static int mptsas_probe_one_phy(struct device *dev, mptsas_is_end_device(&phy_info->attached)) return 0; - rphy = sas_rphy_alloc(phy); + mptsas_parse_device_info(&identify, &phy_info->attached); + switch (identify.device_type) { + case SAS_END_DEVICE: + rphy = sas_end_device_alloc(phy); + break; + case SAS_EDGE_EXPANDER_DEVICE: + case SAS_FANOUT_EXPANDER_DEVICE: + rphy = sas_expander_alloc(phy, identify.device_type); + break; + default: + rphy = NULL; + break; + } if (!rphy) return 0; /* non-fatal: an rphy can be added later */ - mptsas_parse_device_info(&rphy->identify, &phy_info->attached); + rphy->identify = identify; + error = sas_rphy_add(rphy); if (error) { sas_rphy_free(rphy); @@ -1654,6 +1676,7 @@ mptsas_hotplug_work(void *arg) struct mptsas_phyinfo *phy_info; struct sas_rphy *rphy; struct scsi_device *sdev; + struct sas_identify identify; char *ds = NULL; struct mptsas_devinfo sas_device; VirtTarget *vtarget; @@ -1779,11 +1802,23 @@ mptsas_hotplug_work(void *arg) "attaching %s device, channel %d, id %d, phy %d\n", ioc->name, ds, ev->channel, ev->id, ev->phy_id); - rphy = sas_rphy_alloc(phy_info->phy); + mptsas_parse_device_info(&identify, &phy_info->attached); + switch (identify.device_type) { + case SAS_END_DEVICE: + rphy = sas_end_device_alloc(phy_info->phy); + break; + case SAS_EDGE_EXPANDER_DEVICE: + case SAS_FANOUT_EXPANDER_DEVICE: + rphy = sas_expander_alloc(phy_info->phy, identify.device_type); + break; + default: + rphy = NULL; + break; + } if (!rphy) break; /* non-fatal: an rphy can be added later */ - mptsas_parse_device_info(&rphy->identify, &phy_info->attached); + rphy->identify = identify; if (sas_rphy_add(rphy)) { sas_rphy_free(rphy); break; -- cgit v1.2.3-59-g8ed1b From 2f8600dff2b140096a7df781884e918a16aa90e0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 18 Mar 2006 15:00:50 -0600 Subject: [SCSI] eliminate rphy allocation in favour of expander/end device allocation This allows the removal of the contained flag and also does a bit of class renaming (sas_rphy->sas_device). Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 72 +++++++++++++++------------------------ include/scsi/scsi_transport_sas.h | 5 --- 2 files changed, 27 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 5a70d04352cc..134c44c8538a 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -699,7 +699,7 @@ sas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", sas_expander_simple_attr(level, level, "%d\n", int); static DECLARE_TRANSPORT_CLASS(sas_rphy_class, - "sas_rphy", NULL, NULL, NULL); + "sas_device", NULL, NULL, NULL); static int sas_rphy_match(struct attribute_container *cont, struct device *dev) { @@ -740,9 +740,7 @@ static int sas_end_dev_match(struct attribute_container *cont, i = to_sas_internal(shost->transportt); return &i->end_dev_attr_cont.ac == cont && - rphy->identify.device_type == SAS_END_DEVICE && - /* FIXME: remove contained eventually */ - rphy->contained; + rphy->identify.device_type == SAS_END_DEVICE; } static int sas_expander_match(struct attribute_container *cont, @@ -766,49 +764,26 @@ static int sas_expander_match(struct attribute_container *cont, i = to_sas_internal(shost->transportt); return &i->expander_attr_cont.ac == cont && (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || - rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) && - /* FIXME: remove contained eventually */ - rphy->contained; + rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE); } -static void sas_rphy_release(struct device *dev) +static void sas_expander_release(struct device *dev) { struct sas_rphy *rphy = dev_to_rphy(dev); + struct sas_expander_device *edev = rphy_to_expander_device(rphy); put_device(dev->parent); - kfree(rphy); + kfree(edev); } -/** - * sas_rphy_alloc -- allocates and initialize a SAS remote PHY structure - * @parent: SAS PHY this remote PHY is conneted to - * - * Allocates an SAS remote PHY structure, connected to @parent. - * - * Returns: - * SAS PHY allocated or %NULL if the allocation failed. - */ -struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent) +static void sas_end_device_release(struct device *dev) { - struct Scsi_Host *shost = dev_to_shost(&parent->dev); - struct sas_rphy *rphy; - - rphy = kzalloc(sizeof(*rphy), GFP_KERNEL); - if (!rphy) { - put_device(&parent->dev); - return NULL; - } - - device_initialize(&rphy->dev); - rphy->dev.parent = get_device(&parent->dev); - rphy->dev.release = sas_rphy_release; - sprintf(rphy->dev.bus_id, "rphy-%d:%d-%d", - shost->host_no, parent->port_identifier, parent->number); - transport_setup_device(&rphy->dev); + struct sas_rphy *rphy = dev_to_rphy(dev); + struct sas_end_device *edev = rphy_to_end_device(rphy); - return rphy; + put_device(dev->parent); + kfree(edev); } -EXPORT_SYMBOL(sas_rphy_alloc); /** * sas_end_device_alloc - allocate an rphy for an end device @@ -831,12 +806,10 @@ struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent) device_initialize(&rdev->rphy.dev); rdev->rphy.dev.parent = get_device(&parent->dev); - rdev->rphy.dev.release = sas_rphy_release; - sprintf(rdev->rphy.dev.bus_id, "rphy-%d:%d-%d", + rdev->rphy.dev.release = sas_end_device_release; + 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; - /* FIXME: mark the rphy as being contained in a larger structure */ - rdev->rphy.contained = 1; transport_setup_device(&rdev->rphy.dev); return &rdev->rphy; @@ -869,15 +842,13 @@ struct sas_rphy *sas_expander_alloc(struct sas_phy *parent, device_initialize(&rdev->rphy.dev); rdev->rphy.dev.parent = get_device(&parent->dev); - rdev->rphy.dev.release = sas_rphy_release; + rdev->rphy.dev.release = sas_expander_release; mutex_lock(&sas_host->lock); rdev->rphy.scsi_target_id = sas_host->next_expander_id++; mutex_unlock(&sas_host->lock); sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", shost->host_no, rdev->rphy.scsi_target_id); rdev->rphy.identify.device_type = type; - /* FIXME: mark the rphy as being contained in a larger structure */ - rdev->rphy.contained = 1; transport_setup_device(&rdev->rphy.dev); return &rdev->rphy; @@ -950,7 +921,17 @@ void sas_rphy_free(struct sas_rphy *rphy) put_device(rphy->dev.parent); put_device(rphy->dev.parent); put_device(rphy->dev.parent); - kfree(rphy); + if (rphy->identify.device_type == SAS_END_DEVICE) { + struct sas_end_device *edev = rphy_to_end_device(rphy); + + kfree(edev); + } else { + /* must be expander */ + struct sas_expander_device *edev = + rphy_to_expander_device(rphy); + + kfree(edev); + } } EXPORT_SYMBOL(sas_rphy_free); @@ -1003,7 +984,8 @@ EXPORT_SYMBOL(sas_rphy_delete); */ int scsi_is_sas_rphy(const struct device *dev) { - return dev->release == sas_rphy_release; + return dev->release == sas_end_device_release || + dev->release == sas_expander_release; } EXPORT_SYMBOL(scsi_is_sas_rphy); diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 2943ccc22a43..93cfb4bf4211 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -82,10 +82,6 @@ struct sas_rphy { struct sas_identify identify; struct list_head list; u32 scsi_target_id; - /* temporary expedient: mark the rphy as being contained - * within a type specific rphy - * FIXME: pull this out when everything uses the containers */ - unsigned contained:1; }; #define dev_to_rphy(d) \ @@ -145,7 +141,6 @@ extern int sas_phy_add(struct sas_phy *); extern void sas_phy_delete(struct sas_phy *); extern int scsi_is_sas_phy(const struct device *); -extern struct sas_rphy *sas_rphy_alloc(struct sas_phy *); extern struct sas_rphy *sas_end_device_alloc(struct sas_phy *); extern struct sas_rphy *sas_expander_alloc(struct sas_phy *, enum sas_device_type); void sas_rphy_free(struct sas_rphy *); -- cgit v1.2.3-59-g8ed1b From 4a29cc2e503b33a1e96db4c3f9a94165f153f259 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Mar 2006 13:21:12 -0800 Subject: [TG3]: 40-bit DMA workaround part 2 The 40-bit DMA workaround recently implemented for 5714, 5715, and 5780 needs to be expanded because there may be other tg3 devices behind the EPB Express to PCIX bridge in the 5780 class device. For example, some 4-port card or mother board designs have 5704 behind the 5714. All devices behind the EPB require the 40-bit DMA workaround. Thanks to Chris Elmquist again for reporting the problem and testing the patch. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 52 ++++++++++++++++++++++++++++++++++++++++--------- drivers/net/tg3.h | 1 + include/linux/pci_ids.h | 1 + 3 files changed, 45 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b8f1524da557..caf4102b54ce 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9552,12 +9552,36 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } - /* Find msi capability. */ + /* The EPB bridge inside 5714, 5715, and 5780 cannot support + * DMA addresses > 40-bit. This bridge may have other additional + * 57xx devices behind it in some 4-port NIC designs for example. + * Any tg3 device found behind the bridge will also need the 40-bit + * DMA workaround. + */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { tp->tg3_flags2 |= TG3_FLG2_5780_CLASS; + tp->tg3_flags |= TG3_FLAG_40BIT_DMA_BUG; tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI); } + else { + struct pci_dev *bridge = NULL; + + do { + bridge = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_EPB, + bridge); + if (bridge && bridge->subordinate && + (bridge->subordinate->number <= + tp->pdev->bus->number) && + (bridge->subordinate->subordinate >= + tp->pdev->bus->number)) { + tp->tg3_flags |= TG3_FLAG_40BIT_DMA_BUG; + pci_dev_put(bridge); + break; + } + } while (bridge); + } /* Initialize misc host control in PCI block. */ tp->misc_host_ctrl |= (misc_ctrl_reg & @@ -10303,7 +10327,14 @@ static int __devinit tg3_test_dma(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f); - if (ccval == 0x6 || ccval == 0x7) + /* If the 5704 is behind the EPB bridge, we can + * do the less restrictive ONE_DMA workaround for + * better performance. + */ + if ((tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) && + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) + tp->dma_rwctrl |= 0x8000; + else if (ccval == 0x6 || ccval == 0x7) tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA; /* Set bit 23 to enable PCIX hw bug fix */ @@ -10759,19 +10790,20 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_iounmap; } - /* 5714, 5715 and 5780 cannot support DMA addresses > 40-bit. + /* The EPB bridge inside 5714, 5715, and 5780 and any + * device behind the EPB cannot support DMA addresses > 40-bit. * On 64-bit systems with IOMMU, use 40-bit dma_mask. * On 64-bit systems without IOMMU, use 64-bit dma_mask and * do DMA address check in tg3_start_xmit(). */ - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { + if (tp->tg3_flags2 & TG3_FLG2_IS_5788) + persist_dma_mask = dma_mask = DMA_32BIT_MASK; + else if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) { persist_dma_mask = dma_mask = DMA_40BIT_MASK; #ifdef CONFIG_HIGHMEM dma_mask = DMA_64BIT_MASK; #endif - } else if (tp->tg3_flags2 & TG3_FLG2_IS_5788) - persist_dma_mask = dma_mask = DMA_32BIT_MASK; - else + } else persist_dma_mask = dma_mask = DMA_64BIT_MASK; /* Configure DMA attributes. */ @@ -10908,8 +10940,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0, (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0, (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0); - printk(KERN_INFO "%s: dma_rwctrl[%08x]\n", - dev->name, tp->dma_rwctrl); + printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n", + dev->name, tp->dma_rwctrl, + (pdev->dma_mask == DMA_32BIT_MASK) ? 32 : + (((u64) pdev->dma_mask == DMA_40BIT_MASK) ? 40 : 64)); return 0; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 7f4b7f6ac40d..7e3b613afb29 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2163,6 +2163,7 @@ struct tg3 { #define TG3_FLAG_10_100_ONLY 0x01000000 #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 #define TG3_FLAG_IN_RESET_TASK 0x04000000 +#define TG3_FLAG_40BIT_DMA_BUG 0x08000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 #define TG3_FLAG_SPLIT_MODE 0x40000000 diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 1709b5009d2e..751eea58bde8 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1365,6 +1365,7 @@ #define PCI_DEVICE_ID_SERVERWORKS_HE 0x0008 #define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009 #define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017 +#define PCI_DEVICE_ID_SERVERWORKS_EPB 0x0103 #define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 #define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 #define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 -- cgit v1.2.3-59-g8ed1b From 6e5fca53c72c95da92c092411c7ec81e926af632 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 20 Mar 2006 18:34:29 +1100 Subject: drm: read breadcrumb in IRQ handler From: Keith Whitwell Signed-off-by: Dave Airlie --- drivers/char/drm/i915_irq.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index d3879ac9970f..a752afd86ab8 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c @@ -53,6 +53,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_WRITE16(I915REG_INT_IDENTITY_R, temp); + dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + if (temp & USER_INT_FLAG) DRM_WAKEUP(&dev_priv->irq_queue); -- cgit v1.2.3-59-g8ed1b From 02fd473bd4844befc74f7ca67cd60891e0a2d890 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 11 Feb 2006 02:25:21 -0800 Subject: [SPARC64]: Add SUN4V Hypervisor Console driver. Since it can do things like BREAK and HUP, we implement this as a serial uart driver. This still needs interrupt probing code, as I haven't figured out how interrupts will work or be probed for on SUN4V yet. Signed-off-by: David S. Miller --- drivers/serial/Kconfig | 7 + drivers/serial/Makefile | 1 + drivers/serial/sunhv.c | 481 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/serial_core.h | 3 + 4 files changed, 492 insertions(+) create mode 100644 drivers/serial/sunhv.c (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b3c561abe3f6..89e5413cc2a3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -582,6 +582,13 @@ config SERIAL_SUNSAB_CONSOLE on your Sparc system as the console, you can do so by answering Y to this option. +config SERIAL_SUNHV + bool "Sun4v Hypervisor Console support" + depends on SPARC64 + help + This driver supports the console device found on SUN4V Sparc + systems. Say Y if you want to be able to use this device. + config SERIAL_IP22_ZILOG tristate "IP22 Zilog8530 serial support" depends on SGI_IP22 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index eaf8e01db198..0f7f8d73d3ca 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o +obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o obj-$(CONFIG_SERIAL_68360) += 68360serial.o diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c new file mode 100644 index 000000000000..2ba716eeb0bf --- /dev/null +++ b/drivers/serial/sunhv.c @@ -0,0 +1,481 @@ +/* sunhv.c: Serial driver for SUN4V hypervisor console. + * + * Copyright (C) 2006 David S. Miller (davem@davemloft.net) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#if defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include + +#include "suncore.h" + +#define CON_BREAK ((long)-1) +#define CON_HUP ((long)-2) + +static inline long hypervisor_con_getchar(long *status) +{ + register unsigned long func asm("%o5"); + register unsigned long arg0 asm("%o0"); + register unsigned long arg1 asm("%o1"); + + func = HV_FAST_CONS_GETCHAR; + arg0 = 0; + arg1 = 0; + __asm__ __volatile__("ta %6" + : "=&r" (func), "=&r" (arg0), "=&r" (arg1) + : "0" (func), "1" (arg0), "2" (arg1), + "i" (HV_FAST_TRAP)); + + *status = arg0; + + return (long) arg1; +} + +static inline long hypervisor_con_putchar(long ch) +{ + register unsigned long func asm("%o5"); + register unsigned long arg0 asm("%o0"); + + func = HV_FAST_CONS_PUTCHAR; + arg0 = ch; + __asm__ __volatile__("ta %4" + : "=&r" (func), "=&r" (arg0) + : "0" (func), "1" (arg0), "i" (HV_FAST_TRAP)); + + return (long) arg0; +} + +#define IGNORE_BREAK 0x1 +#define IGNORE_ALL 0x2 + +static int hung_up = 0; + +static struct tty_struct *receive_chars(struct uart_port *port, struct pt_regs *regs) +{ + struct tty_struct *tty = NULL; + int saw_console_brk = 0; + int limit = 10000; + + if (port->info != NULL) /* Unopened serial console */ + tty = port->info->tty; + + while (limit-- > 0) { + long status; + long c = hypervisor_con_getchar(&status); + unsigned char flag; + + if (status == HV_EWOULDBLOCK) + break; + + if (c == CON_BREAK) { + saw_console_brk = 1; + c = 0; + } + + if (c == CON_HUP) { + hung_up = 1; + uart_handle_dcd_change(port, 0); + } else if (hung_up) { + hung_up = 0; + uart_handle_dcd_change(port, 1); + } + + if (tty == NULL) { + uart_handle_sysrq_char(port, c, regs); + continue; + } + + flag = TTY_NORMAL; + port->icount.rx++; + if (c == CON_BREAK) { + port->icount.brk++; + if (uart_handle_break(port)) + continue; + flag = TTY_BREAK; + } + + if (uart_handle_sysrq_char(port, c, regs)) + continue; + + if ((port->ignore_status_mask & IGNORE_ALL) || + ((port->ignore_status_mask & IGNORE_BREAK) && + (c == CON_BREAK))) + continue; + + tty_insert_flip_char(tty, c, flag); + } + + if (saw_console_brk) + sun_do_break(); + + return tty; +} + +static void transmit_chars(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + return; + + while (!uart_circ_empty(xmit)) { + long status = hypervisor_con_putchar(xmit->buf[xmit->tail]); + + if (status != HV_EOK) + break; + + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); +} + +static irqreturn_t sunhv_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_port *port = dev_id; + struct tty_struct *tty; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + tty = receive_chars(port, regs); + transmit_chars(port); + spin_unlock_irqrestore(&port->lock, flags); + + if (tty) + tty_flip_buffer_push(tty); + + return IRQ_HANDLED; +} + +/* port->lock is not held. */ +static unsigned int sunhv_tx_empty(struct uart_port *port) +{ + /* Transmitter is always empty for us. If the circ buffer + * is non-empty or there is an x_char pending, our caller + * will do the right thing and ignore what we return here. + */ + return TIOCSER_TEMT; +} + +/* port->lock held by caller. */ +static void sunhv_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + return; +} + +/* port->lock is held by caller and interrupts are disabled. */ +static unsigned int sunhv_get_mctrl(struct uart_port *port) +{ + return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS; +} + +/* port->lock held by caller. */ +static void sunhv_stop_tx(struct uart_port *port) +{ + return; +} + +/* port->lock held by caller. */ +static void sunhv_start_tx(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + + while (!uart_circ_empty(xmit)) { + long status = hypervisor_con_putchar(xmit->buf[xmit->tail]); + + if (status != HV_EOK) + break; + + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + } + + spin_unlock_irqrestore(&port->lock, flags); +} + +/* port->lock is not held. */ +static void sunhv_send_xchar(struct uart_port *port, char ch) +{ + unsigned long flags; + int limit = 10000; + + spin_lock_irqsave(&port->lock, flags); + + while (limit-- > 0) { + long status = hypervisor_con_putchar(ch); + if (status == HV_EOK) + break; + } + + spin_unlock_irqrestore(&port->lock, flags); +} + +/* port->lock held by caller. */ +static void sunhv_stop_rx(struct uart_port *port) +{ +} + +/* port->lock held by caller. */ +static void sunhv_enable_ms(struct uart_port *port) +{ +} + +/* port->lock is not held. */ +static void sunhv_break_ctl(struct uart_port *port, int break_state) +{ + if (break_state) { + unsigned long flags; + int limit = 10000; + + spin_lock_irqsave(&port->lock, flags); + + while (limit-- > 0) { + long status = hypervisor_con_putchar(CON_BREAK); + if (status == HV_EOK) + break; + } + + spin_unlock_irqrestore(&port->lock, flags); + } +} + +/* port->lock is not held. */ +static int sunhv_startup(struct uart_port *port) +{ + return 0; +} + +/* port->lock is not held. */ +static void sunhv_shutdown(struct uart_port *port) +{ +} + +/* port->lock is not held. */ +static void sunhv_set_termios(struct uart_port *port, struct termios *termios, + struct termios *old) +{ + unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); + unsigned int quot = uart_get_divisor(port, baud); + unsigned int iflag, cflag; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + + iflag = termios->c_iflag; + cflag = termios->c_cflag; + + port->ignore_status_mask = 0; + if (iflag & IGNBRK) + port->ignore_status_mask |= IGNORE_BREAK; + if ((cflag & CREAD) == 0) + port->ignore_status_mask |= IGNORE_ALL; + + /* XXX */ + uart_update_timeout(port, cflag, + (port->uartclk / (16 * quot))); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char *sunhv_type(struct uart_port *port) +{ + return "SUN4V HCONS"; +} + +static void sunhv_release_port(struct uart_port *port) +{ +} + +static int sunhv_request_port(struct uart_port *port) +{ + return 0; +} + +static void sunhv_config_port(struct uart_port *port, int flags) +{ +} + +static int sunhv_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + return -EINVAL; +} + +static struct uart_ops sunhv_pops = { + .tx_empty = sunhv_tx_empty, + .set_mctrl = sunhv_set_mctrl, + .get_mctrl = sunhv_get_mctrl, + .stop_tx = sunhv_stop_tx, + .start_tx = sunhv_start_tx, + .send_xchar = sunhv_send_xchar, + .stop_rx = sunhv_stop_rx, + .enable_ms = sunhv_enable_ms, + .break_ctl = sunhv_break_ctl, + .startup = sunhv_startup, + .shutdown = sunhv_shutdown, + .set_termios = sunhv_set_termios, + .type = sunhv_type, + .release_port = sunhv_release_port, + .request_port = sunhv_request_port, + .config_port = sunhv_config_port, + .verify_port = sunhv_verify_port, +}; + +static struct uart_driver sunhv_reg = { + .owner = THIS_MODULE, + .driver_name = "serial", + .devfs_name = "tts/", + .dev_name = "ttyS", + .major = TTY_MAJOR, +}; + +static struct uart_port *sunhv_port; + +static inline void sunhv_console_putchar(struct uart_port *port, char c) +{ + unsigned long flags; + int limit = 10000; + + spin_lock_irqsave(&port->lock, flags); + + while (limit-- > 0) { + long status = hypervisor_con_putchar(c); + if (status == HV_EOK) + break; + } + + spin_unlock_irqrestore(&port->lock, flags); +} + +static void sunhv_console_write(struct console *con, const char *s, unsigned n) +{ + struct uart_port *port = sunhv_port; + int i; + + for (i = 0; i < n; i++) { + if (*s == '\n') + sunhv_console_putchar(port, '\r'); + sunhv_console_putchar(port, *s++); + } +} + +static int sunhv_console_setup(struct console *con, char *options) +{ + return 0; +} + +static struct console sunhv_console = { + .name = "ttyS", + .write = sunhv_console_write, + .device = uart_console_device, + .setup = sunhv_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &sunhv_reg, +}; + +static void __init sunhv_console_init(void) +{ + if (con_is_present()) + return; + + sunhv_console.index = 0; + register_console(&sunhv_console); +} + +static int __init sunhv_init(void) +{ + struct uart_port *port; + int ret; + + if (tlb_type != hypervisor) + return -ENODEV; + + port = kmalloc(sizeof(struct uart_port), GFP_KERNEL); + if (unlikely(!port)) + return -ENOMEM; + + port->line = 0; + port->ops = &sunhv_pops; + port->type = PORT_SUNHV; + port->uartclk = ( 29491200 / 16 ); /* arbitrary */ + + /* XXX Get interrupt. XXX */ + if (request_irq(0 /* XXX */, sunhv_interrupt, + SA_SHIRQ, "serial(sunhv)", port)) { + printk("sunhv: Cannot get IRQ %x\n", + 0 /* XXX */); + kfree(port); + return -ENODEV; + } + + sunhv_reg.minor = sunserial_current_minor; + sunhv_reg.nr = 1; + sunhv_reg.cons = &sunhv_console; + + ret = uart_register_driver(&sunhv_reg); + if (ret < 0) { + free_irq(0 /* XXX */, up); + kfree(port); + + return ret; + } + + sunhv_port = port; + + sunserial_current_minor += 1; + + sunhv_console_init(); + + uart_add_one_port(&sunhv_reg, port); + + return 0; +} + +static void __exit sunhv_exit(void) +{ + struct uart_port *port = sunhv_port; + + BUG_ON(!port); + + uart_remove_one_port(&sunhv_reg, port); + free_irq(0 /* XXX */, port); + + sunserial_current_minor -= 1; + + uart_unregister_driver(&sunhv_reg); + + kfree(sunhv_port); + sunhv_port = NULL; +} + +module_init(sunhv_init); +module_exit(sunhv_exit); + +MODULE_AUTHOR("David S. Miller"); +MODULE_DESCRIPTION("SUN4V Hypervisor console driver") +MODULE_LICENSE("GPL"); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 4041122dabfc..57abcea1cb5d 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -127,6 +127,9 @@ /* Hilscher netx */ #define PORT_NETX 71 +/* SUN4V Hypervisor Console */ +#define PORT_SUNHV 72 + #ifdef __KERNEL__ #include -- cgit v1.2.3-59-g8ed1b From 1ddb7c98d44b898cfe0443c1e242cebfb0479d46 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 13 Feb 2006 20:09:10 -0800 Subject: [SPARC64]: Prevent registering wrong serial console. If the console is not for a particular Sun serial controller, set the drv->cons to NULL. Signed-off-by: David S. Miller --- drivers/serial/sunsab.c | 17 ++++++++--------- drivers/serial/sunsu.c | 22 +++++++++++----------- drivers/serial/sunzilog.c | 34 ++++++++++++++++++++++++++++------ 3 files changed, 47 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 85664228a0b6..02f62da546b5 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -955,14 +955,13 @@ static struct console sunsab_console = { .index = -1, .data = &sunsab_reg, }; -#define SUNSAB_CONSOLE (&sunsab_console) -static void __init sunsab_console_init(void) +static inline struct console *SUNSAB_CONSOLE(void) { int i; if (con_is_present()) - return; + return NULL; for (i = 0; i < num_channels; i++) { int this_minor = sunsab_reg.minor + i; @@ -971,13 +970,14 @@ static void __init sunsab_console_init(void) break; } if (i == num_channels) - return; + return NULL; sunsab_console.index = i; - register_console(&sunsab_console); + + return &sunsab_console; } #else -#define SUNSAB_CONSOLE (NULL) +#define SUNSAB_CONSOLE() (NULL) #define sunsab_console_init() do { } while (0) #endif @@ -1124,7 +1124,6 @@ static int __init sunsab_init(void) sunsab_reg.minor = sunserial_current_minor; sunsab_reg.nr = num_channels; - sunsab_reg.cons = SUNSAB_CONSOLE; ret = uart_register_driver(&sunsab_reg); if (ret < 0) { @@ -1143,10 +1142,10 @@ static int __init sunsab_init(void) return ret; } + sunsab_reg.cons = SUNSAB_CONSOLE(); + sunserial_current_minor += num_channels; - sunsab_console_init(); - for (i = 0; i < num_channels; i++) { struct uart_sunsab_port *up = &sunsab_ports[i]; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 4e453fa966ae..3313cb2a355a 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1464,18 +1464,17 @@ static struct console sunsu_cons = { .index = -1, .data = &sunsu_reg, }; -#define SUNSU_CONSOLE (&sunsu_cons) /* * Register console. */ -static int __init sunsu_serial_console_init(void) +static inline struct console *SUNSU_CONSOLE(void) { int i; if (con_is_present()) - return 0; + return NULL; for (i = 0; i < UART_NR; i++) { int this_minor = sunsu_reg.minor + i; @@ -1484,16 +1483,16 @@ static int __init sunsu_serial_console_init(void) break; } if (i == UART_NR) - return 0; + return NULL; if (sunsu_ports[i].port_node == 0) - return 0; + return NULL; sunsu_cons.index = i; - register_console(&sunsu_cons); - return 0; + + return &sunsu_cons; } #else -#define SUNSU_CONSOLE (NULL) +#define SUNSU_CONSOLE() (NULL) #define sunsu_serial_console_init() do { } while (0) #endif @@ -1523,16 +1522,17 @@ static int __init sunsu_serial_init(void) } sunsu_reg.minor = sunserial_current_minor; - sunserial_current_minor += instance; sunsu_reg.nr = instance; - sunsu_reg.cons = SUNSU_CONSOLE; ret = uart_register_driver(&sunsu_reg); if (ret < 0) return ret; - sunsu_serial_console_init(); + sunserial_current_minor += instance; + + sunsu_reg.cons = SUNSU_CONSOLE(); + for (i = 0; i < UART_NR; i++) { struct uart_sunsu_port *up = &sunsu_ports[i]; diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 5cc4d4c2935c..5aa74e7a954e 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1390,7 +1390,6 @@ static struct console sunzilog_console = { .index = -1, .data = &sunzilog_reg, }; -#define SUNZILOG_CONSOLE (&sunzilog_console) static int __init sunzilog_console_init(void) { @@ -1413,8 +1412,31 @@ static int __init sunzilog_console_init(void) register_console(&sunzilog_console); return 0; } + +static inline struct console *SUNZILOG_CONSOLE(void) +{ + int i; + + if (con_is_present()) + return NULL; + + for (i = 0; i < NUM_CHANNELS; i++) { + int this_minor = sunzilog_reg.minor + i; + + if ((this_minor - 64) == (serial_console - 1)) + break; + } + if (i == NUM_CHANNELS) + return NULL; + + sunzilog_console.index = i; + sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS; + + return &sunzilog_console; +} + #else -#define SUNZILOG_CONSOLE (NULL) +#define SUNZILOG_CONSOLE() (NULL) #define sunzilog_console_init() do { } while (0) #endif @@ -1666,14 +1688,14 @@ static int __init sunzilog_ports_init(void) } sunzilog_reg.nr = uart_count; - sunzilog_reg.cons = SUNZILOG_CONSOLE; - sunzilog_reg.minor = sunserial_current_minor; - sunserial_current_minor += uart_count; ret = uart_register_driver(&sunzilog_reg); if (ret == 0) { - sunzilog_console_init(); + sunzilog_reg.cons = SUNZILOG_CONSOLE(); + + sunserial_current_minor += uart_count; + for (i = 0; i < NUM_CHANNELS; i++) { struct uart_sunzilog_port *up = &sunzilog_port_table[i]; -- cgit v1.2.3-59-g8ed1b From f4266ab45a3f08bd76c2d414a2d7a1a9dc2501c0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 13 Feb 2006 20:43:02 -0800 Subject: [SPARC64] sunhv: Use virtual-devices layer to get interrupt. Signed-off-by: David S. Miller --- drivers/serial/sunhv.c | 73 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 2ba716eeb0bf..d3a9dd739da3 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -20,6 +20,8 @@ #include #include +#include +#include #if defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -407,6 +409,60 @@ static void __init sunhv_console_init(void) register_console(&sunhv_console); } +static int __init hv_console_compatible(char *buf, int len) +{ + while (len) { + int this_len; + + if (!strcmp(buf, "qcn")) + return 1; + + this_len = strlen(buf) + 1; + + buf += this_len; + len -= this_len; + } + + return 0; +} + +static unsigned int __init get_interrupt(void) +{ + const char *cons_str = "console"; + const char *compat_str = "compatible"; + int node = prom_getchild(sun4v_vdev_root); + unsigned int irq; + char buf[64]; + int err, len; + + node = prom_searchsiblings(node, cons_str); + if (!node) + return 0; + + len = prom_getproplen(node, compat_str); + if (len == 0 || len == -1) + return 0; + + err = prom_getproperty(node, compat_str, buf, 64); + if (err == -1) + return 0; + + if (!hv_console_compatible(buf, len)) + return 0; + + /* Ok, the this is the OBP node for the sun4v hypervisor + * console device. Decode the interrupt. + */ + err = prom_getproperty(node, "interrupts", + (char *) &irq, sizeof(irq)); + if (err == -1) + return 0; + + return sun4v_build_irq(sun4v_vdev_devhandle, irq, 4, 0); +} + +static u32 sunhv_irq; + static int __init sunhv_init(void) { struct uart_port *port; @@ -415,6 +471,10 @@ static int __init sunhv_init(void) if (tlb_type != hypervisor) return -ENODEV; + sunhv_irq = get_interrupt(); + if (!sunhv_irq) + return -ENODEV; + port = kmalloc(sizeof(struct uart_port), GFP_KERNEL); if (unlikely(!port)) return -ENOMEM; @@ -424,22 +484,23 @@ static int __init sunhv_init(void) port->type = PORT_SUNHV; port->uartclk = ( 29491200 / 16 ); /* arbitrary */ - /* XXX Get interrupt. XXX */ - if (request_irq(0 /* XXX */, sunhv_interrupt, + if (request_irq(sunhv_irq, sunhv_interrupt, SA_SHIRQ, "serial(sunhv)", port)) { - printk("sunhv: Cannot get IRQ %x\n", - 0 /* XXX */); + printk("sunhv: Cannot get IRQ %x\n", sunhv_irq); kfree(port); return -ENODEV; } + printk("SUNHV: SUN4V virtual console, IRQ[%08x]\n", + sunhv_irq); + sunhv_reg.minor = sunserial_current_minor; sunhv_reg.nr = 1; sunhv_reg.cons = &sunhv_console; ret = uart_register_driver(&sunhv_reg); if (ret < 0) { - free_irq(0 /* XXX */, up); + free_irq(sunhv_irq, up); kfree(port); return ret; @@ -463,7 +524,7 @@ static void __exit sunhv_exit(void) BUG_ON(!port); uart_remove_one_port(&sunhv_reg, port); - free_irq(0 /* XXX */, port); + free_irq(sunhv_irq, port); sunserial_current_minor -= 1; -- cgit v1.2.3-59-g8ed1b From d5a2aa241aa0babf382d42d6033b30a5112e4c1e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 13 Feb 2006 21:28:40 -0800 Subject: [SPARC64] sunhv: Bug fixes. Add udelay to polling console write loop, and increment the loop limit. Name the device "ttyHV" and pass that to add_preferred_console() when we're using hypervisor console. Kill sunhv_console_setup(), it's empty. Handle the case where we don't want to use hypervisor console. (ie. we have a head attached to a sun4v machine) Signed-off-by: David S. Miller --- arch/sparc64/kernel/setup.c | 1 + drivers/serial/sunhv.c | 25 ++++++++++--------------- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 4f253a0755b0..06807cf95ee1 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -410,6 +410,7 @@ static int __init set_preferred_console(void) * value anyways... */ serial_console = 4; + return add_preferred_console("ttyHV", 0, NULL); } else { prom_printf("Inconsistent console: " "input %d, output %d\n", diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index d3a9dd739da3..71c70d7a998c 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -360,7 +360,7 @@ static struct uart_port *sunhv_port; static inline void sunhv_console_putchar(struct uart_port *port, char c) { unsigned long flags; - int limit = 10000; + int limit = 1000000; spin_lock_irqsave(&port->lock, flags); @@ -368,6 +368,7 @@ static inline void sunhv_console_putchar(struct uart_port *port, char c) long status = hypervisor_con_putchar(c); if (status == HV_EOK) break; + udelay(2); } spin_unlock_irqrestore(&port->lock, flags); @@ -385,28 +386,23 @@ static void sunhv_console_write(struct console *con, const char *s, unsigned n) } } -static int sunhv_console_setup(struct console *con, char *options) -{ - return 0; -} - static struct console sunhv_console = { - .name = "ttyS", + .name = "ttyHV", .write = sunhv_console_write, .device = uart_console_device, - .setup = sunhv_console_setup, .flags = CON_PRINTBUFFER, .index = -1, .data = &sunhv_reg, }; -static void __init sunhv_console_init(void) +static inline struct console *SUNHV_CONSOLE(void) { if (con_is_present()) - return; + return NULL; sunhv_console.index = 0; - register_console(&sunhv_console); + + return &sunhv_console; } static int __init hv_console_compatible(char *buf, int len) @@ -496,7 +492,6 @@ static int __init sunhv_init(void) sunhv_reg.minor = sunserial_current_minor; sunhv_reg.nr = 1; - sunhv_reg.cons = &sunhv_console; ret = uart_register_driver(&sunhv_reg); if (ret < 0) { @@ -506,11 +501,11 @@ static int __init sunhv_init(void) return ret; } - sunhv_port = port; - sunserial_current_minor += 1; - sunhv_console_init(); + sunhv_reg.cons = SUNHV_CONSOLE(); + + sunhv_port = port; uart_add_one_port(&sunhv_reg, port); -- cgit v1.2.3-59-g8ed1b From 9d29a3fafd06534ad73427fee3c968c094d05b9b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 15 Feb 2006 19:48:54 -0800 Subject: [SPARC64]: Decode virtual-devices interrupts correctly. Need to translate through the interrupt-map{,-mask] properties. Signed-off-by: David S. Miller --- arch/sparc64/kernel/devices.c | 98 +++++++++++++++++++++++++++++++++++++------ drivers/serial/sunhv.c | 14 ++----- include/asm-sparc64/vdev.h | 6 +-- 3 files changed, 92 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c index 71eee392e141..1341b99ca7aa 100644 --- a/arch/sparc64/kernel/devices.c +++ b/arch/sparc64/kernel/devices.c @@ -22,6 +22,7 @@ #include #include #include +#include /* Used to synchronize acceses to NatSemi SUPER I/O chip configure * operations in asm/ns87303.h @@ -33,14 +34,28 @@ extern void central_probe(void); u32 sun4v_vdev_devhandle; int sun4v_vdev_root; -struct linux_prom_pci_intmap *sun4v_vdev_intmap; -int sun4v_vdev_num_intmap; -struct linux_prom_pci_intmap sun4v_vdev_intmask; + +struct vdev_intmap { + unsigned int phys; + unsigned int irq; + unsigned int cnode; + unsigned int cinterrupt; +}; + +struct vdev_intmask { + unsigned int phys; + unsigned int interrupt; + unsigned int __unused; +}; + +static struct vdev_intmap *vdev_intmap; +static int vdev_num_intmap; +static struct vdev_intmask vdev_intmask; static void __init sun4v_virtual_device_probe(void) { struct linux_prom64_registers regs; - struct linux_prom_pci_intmap *ip; + struct vdev_intmap *ip; int node, sz, err; if (tlb_type != hypervisor) @@ -58,10 +73,21 @@ static void __init sun4v_virtual_device_probe(void) prom_getproperty(node, "reg", (char *)®s, sizeof(regs)); sun4v_vdev_devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; - sz = sizeof(*ip) * 64; - sun4v_vdev_intmap = ip = alloc_bootmem_low_pages(sz); - if (!sun4v_vdev_intmap) { - prom_printf("SUN4V: Error, cannot allocate vdev intmap.\n"); + sz = prom_getproplen(node, "interrupt-map"); + if (sz <= 0) { + prom_printf("SUN4V: Error, no vdev interrupt-map.\n"); + prom_halt(); + } + + if ((sz % sizeof(*ip)) != 0) { + prom_printf("SUN4V: Bogus interrupt-map property size %d\n", + sz); + prom_halt(); + } + + vdev_intmap = ip = alloc_bootmem_low_pages(sz); + if (!vdev_intmap) { + prom_printf("SUN4V: Error, cannot allocate vdev_intmap.\n"); prom_halt(); } @@ -70,22 +96,70 @@ static void __init sun4v_virtual_device_probe(void) prom_printf("SUN4V: Fatal error, no vdev interrupt-map.\n"); prom_halt(); } + if (err != sz) { + prom_printf("SUN4V: Inconsistent interrupt-map size, " + "proplen(%d) vs getprop(%d).\n", sz,err); + prom_halt(); + } - sun4v_vdev_num_intmap = err / sizeof(*ip); + vdev_num_intmap = err / sizeof(*ip); err = prom_getproperty(node, "interrupt-map-mask", - (char *) &sun4v_vdev_intmask, - sizeof(sun4v_vdev_intmask)); - if (err == -1) { + (char *) &vdev_intmask, + sizeof(vdev_intmask)); + if (err <= 0) { prom_printf("SUN4V: Fatal error, no vdev " "interrupt-map-mask.\n"); prom_halt(); } + if (err % sizeof(vdev_intmask)) { + prom_printf("SUN4V: Bogus interrupt-map-mask " + "property size %d\n", err); + prom_halt(); + } printk("SUN4V: virtual-devices devhandle[%x]\n", sun4v_vdev_devhandle); } +unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node) +{ + unsigned int irq, reg; + int err, i; + + err = prom_getproperty(dev_node, "interrupts", + (char *) &irq, sizeof(irq)); + if (err <= 0) { + printk("VDEV: Cannot get \"interrupts\" " + "property for OBP node %x\n", dev_node); + return 0; + } + + err = prom_getproperty(dev_node, "reg", + (char *) ®, sizeof(reg)); + if (err <= 0) { + printk("VDEV: Cannot get \"reg\" " + "property for OBP node %x\n", dev_node); + return 0; + } + + for (i = 0; i < vdev_num_intmap; i++) { + if (vdev_intmap[i].phys == (reg & vdev_intmask.phys) && + vdev_intmap[i].irq == (irq & vdev_intmask.interrupt)) { + irq = vdev_intmap[i].cinterrupt; + break; + } + } + + if (i == vdev_num_intmap) { + printk("VDEV: No matching interrupt map entry " + "for OBP node %x\n", dev_node); + return 0; + } + + return sun4v_build_irq(sun4v_vdev_devhandle, irq, 4, 0); +} + static const char *cpu_mid_prop(void) { if (tlb_type == spitfire) diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 71c70d7a998c..cc46206a1065 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #if defined(CONFIG_MAGIC_SYSRQ) @@ -427,7 +428,6 @@ static unsigned int __init get_interrupt(void) const char *cons_str = "console"; const char *compat_str = "compatible"; int node = prom_getchild(sun4v_vdev_root); - unsigned int irq; char buf[64]; int err, len; @@ -449,12 +449,7 @@ static unsigned int __init get_interrupt(void) /* Ok, the this is the OBP node for the sun4v hypervisor * console device. Decode the interrupt. */ - err = prom_getproperty(node, "interrupts", - (char *) &irq, sizeof(irq)); - if (err == -1) - return 0; - - return sun4v_build_irq(sun4v_vdev_devhandle, irq, 4, 0); + return sun4v_vdev_device_interrupt(node); } static u32 sunhv_irq; @@ -487,8 +482,8 @@ static int __init sunhv_init(void) return -ENODEV; } - printk("SUNHV: SUN4V virtual console, IRQ[%08x]\n", - sunhv_irq); + printk("SUNHV: SUN4V virtual console, IRQ %s\n", + __irq_itoa(sunhv_irq)); sunhv_reg.minor = sunserial_current_minor; sunhv_reg.nr = 1; @@ -520,7 +515,6 @@ static void __exit sunhv_exit(void) uart_remove_one_port(&sunhv_reg, port); free_irq(sunhv_irq, port); - sunserial_current_minor -= 1; uart_unregister_driver(&sunhv_reg); diff --git a/include/asm-sparc64/vdev.h b/include/asm-sparc64/vdev.h index ebaac41a6e1a..996e6be7b976 100644 --- a/include/asm-sparc64/vdev.h +++ b/include/asm-sparc64/vdev.h @@ -7,12 +7,10 @@ #define _SPARC64_VDEV_H #include -#include extern u32 sun4v_vdev_devhandle; extern int sun4v_vdev_root; -extern struct linux_prom_pci_intmap *sun4v_vdev_intmap; -extern int sun4v_vdev_num_intmap; -extern struct linux_prom_pci_intmap sun4v_vdev_intmask; + +extern unsigned int sun4v_vdev_device_interrupt(unsigned int); #endif /* !(_SPARC64_VDEV_H) */ -- cgit v1.2.3-59-g8ed1b From db33f9bc09aaf68db7866374f9219c676787b4a2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 15 Feb 2006 21:56:49 -0800 Subject: [SPARC64]: Fix OOPS on sunhv interrupts. Until the uart is openned, port->info is NULL. Also, init the port->irq properly and give a non-zero port->membase so that the uart device reporting is done. Signed-off-by: David S. Miller --- drivers/serial/sunhv.c | 52 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index cc46206a1065..7f73907db7b6 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -136,8 +136,12 @@ static struct tty_struct *receive_chars(struct uart_port *port, struct pt_regs * static void transmit_chars(struct uart_port *port) { - struct circ_buf *xmit = &port->info->xmit; + struct circ_buf *xmit; + + if (!port->info) + return; + xmit = &port->info->xmit; if (uart_circ_empty(xmit) || uart_tx_stopped(port)) return; @@ -452,8 +456,6 @@ static unsigned int __init get_interrupt(void) return sun4v_vdev_device_interrupt(node); } -static u32 sunhv_irq; - static int __init sunhv_init(void) { struct uart_port *port; @@ -462,35 +464,33 @@ static int __init sunhv_init(void) if (tlb_type != hypervisor) return -ENODEV; - sunhv_irq = get_interrupt(); - if (!sunhv_irq) - return -ENODEV; - port = kmalloc(sizeof(struct uart_port), GFP_KERNEL); if (unlikely(!port)) return -ENOMEM; + memset(port, 0, sizeof(struct uart_port)); + port->line = 0; port->ops = &sunhv_pops; port->type = PORT_SUNHV; port->uartclk = ( 29491200 / 16 ); /* arbitrary */ - if (request_irq(sunhv_irq, sunhv_interrupt, - SA_SHIRQ, "serial(sunhv)", port)) { - printk("sunhv: Cannot get IRQ %x\n", sunhv_irq); + /* Set this just to make uart_configure_port() happy. */ + port->membase = (unsigned char __iomem *) __pa(port); + + port->irq = get_interrupt(); + if (!port->irq) { kfree(port); return -ENODEV; } - printk("SUNHV: SUN4V virtual console, IRQ %s\n", - __irq_itoa(sunhv_irq)); - sunhv_reg.minor = sunserial_current_minor; sunhv_reg.nr = 1; ret = uart_register_driver(&sunhv_reg); if (ret < 0) { - free_irq(sunhv_irq, up); + printk(KERN_ERR "SUNHV: uart_register_driver() failed %d\n", + ret); kfree(port); return ret; @@ -502,7 +502,26 @@ static int __init sunhv_init(void) sunhv_port = port; - uart_add_one_port(&sunhv_reg, port); + ret = uart_add_one_port(&sunhv_reg, port); + if (ret < 0) { + printk(KERN_ERR "SUNHV: uart_add_one_port() failed %d\n", ret); + sunserial_current_minor -= 1; + uart_unregister_driver(&sunhv_reg); + kfree(port); + sunhv_port = NULL; + return -ENODEV; + } + + if (request_irq(port->irq, sunhv_interrupt, + SA_SHIRQ, "serial(sunhv)", port)) { + printk(KERN_ERR "sunhv: Cannot register IRQ\n"); + uart_remove_one_port(&sunhv_reg, port); + sunserial_current_minor -= 1; + uart_unregister_driver(&sunhv_reg); + kfree(port); + sunhv_port = NULL; + return -ENODEV; + } return 0; } @@ -513,8 +532,9 @@ static void __exit sunhv_exit(void) BUG_ON(!port); + free_irq(port->irq, port); + uart_remove_one_port(&sunhv_reg, port); - free_irq(sunhv_irq, port); sunserial_current_minor -= 1; uart_unregister_driver(&sunhv_reg); -- cgit v1.2.3-59-g8ed1b From 135066a21129760e44a51a7ef31d8c861f8ddace Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 16 Feb 2006 00:42:21 -0800 Subject: [SPARC64] sunhv: Support SYSRQ properly. By calling uart_handle_break(). We'll still do the "sun_do_break()" handling if the user gives two breaks in a row. We should probably do this in the other Sparc serial drivers too. Signed-off-by: David S. Miller --- drivers/serial/sunhv.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 7f73907db7b6..378a1784ce9a 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -91,6 +91,8 @@ static struct tty_struct *receive_chars(struct uart_port *port, struct pt_regs * break; if (c == CON_BREAK) { + if (uart_handle_break(port)) + continue; saw_console_brk = 1; c = 0; } -- cgit v1.2.3-59-g8ed1b From 11fc04e46a892563d0a9bb98560339f1672e3213 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 18 Feb 2006 16:30:59 -0800 Subject: [SPARC64]: Put sunhv.o earliest in the list of sparc serial drivers. So that it will show up as /dev/ttyS0. Otherwise things like installers will try to run on whatever serial port gets probed first. Signed-off-by: David S. Miller --- drivers/serial/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 0f7f8d73d3ca..50c221af9e6d 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -30,11 +30,11 @@ obj-$(CONFIG_SERIAL_PXA) += pxa.o obj-$(CONFIG_SERIAL_SA1100) += sa1100.o obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o +obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o -obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o obj-$(CONFIG_SERIAL_68360) += 68360serial.o -- cgit v1.2.3-59-g8ed1b From 843dfb4d99c41116601694f314092b3b6c4511f4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 18 Feb 2006 16:32:22 -0800 Subject: [SPARC64] sunhv: Fix locking in sunhv_start_tx() Caller takes the lock already. Also, fixup the poll loop in sunhv_break_ctl(). Just like in console write, we udelay(2) and use a loop limit of 1000000 iterations. Signed-off-by: David S. Miller --- drivers/serial/sunhv.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 378a1784ce9a..8537839f9abb 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -210,9 +210,6 @@ static void sunhv_stop_tx(struct uart_port *port) static void sunhv_start_tx(struct uart_port *port) { struct circ_buf *xmit = &port->info->xmit; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); while (!uart_circ_empty(xmit)) { long status = hypervisor_con_putchar(xmit->buf[xmit->tail]); @@ -223,8 +220,6 @@ static void sunhv_start_tx(struct uart_port *port) xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; } - - spin_unlock_irqrestore(&port->lock, flags); } /* port->lock is not held. */ @@ -259,7 +254,7 @@ static void sunhv_break_ctl(struct uart_port *port, int break_state) { if (break_state) { unsigned long flags; - int limit = 10000; + int limit = 1000000; spin_lock_irqsave(&port->lock, flags); @@ -267,6 +262,7 @@ static void sunhv_break_ctl(struct uart_port *port, int break_state) long status = hypervisor_con_putchar(CON_BREAK); if (status == HV_EOK) break; + udelay(2); } spin_unlock_irqrestore(&port->lock, flags); -- cgit v1.2.3-59-g8ed1b From f5deb807b8cd5c8fe48cbb4f7f5dd70cfbdb1178 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 20 Feb 2006 14:39:16 -0800 Subject: [SPARC] serial: Make sure sysfs nodes get named correctly. Because we play this trick where we use ttyS? in increasing minor numbers for different sunfoo.c drivers, we have to inform the TTY layer of this. Do so by setting the tty->name_base appropriately. Probably there should be a generic way to do this in the serial core, but for now... Signed-off-by: David S. Miller --- drivers/serial/sunhv.c | 1 + drivers/serial/sunsab.c | 2 ++ drivers/serial/sunsu.c | 2 ++ drivers/serial/sunzilog.c | 1 + 4 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 8537839f9abb..f137804b3133 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -494,6 +494,7 @@ static int __init sunhv_init(void) return ret; } + sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64; sunserial_current_minor += 1; sunhv_reg.cons = SUNHV_CONSOLE(); diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 02f62da546b5..a2fb0c2fb121 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -1142,6 +1142,8 @@ static int __init sunsab_init(void) return ret; } + sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64; + sunsab_reg.cons = SUNSAB_CONSOLE(); sunserial_current_minor += num_channels; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 3313cb2a355a..46510e7f505c 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1529,6 +1529,8 @@ static int __init sunsu_serial_init(void) if (ret < 0) return ret; + sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64; + sunserial_current_minor += instance; sunsu_reg.cons = SUNSU_CONSOLE(); diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 5aa74e7a954e..10b35c6f287d 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1692,6 +1692,7 @@ static int __init sunzilog_ports_init(void) ret = uart_register_driver(&sunzilog_reg); if (ret == 0) { + sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64; sunzilog_reg.cons = SUNZILOG_CONSOLE(); sunserial_current_minor += uart_count; -- cgit v1.2.3-59-g8ed1b From 72b845e04e99298e5179b31e8de16afed52a2627 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 14 Mar 2006 14:11:48 -0800 Subject: [TG3]: Do not try to access NIC_SRAM_DATA_SIG on Sun parts. Sun does't put an SEEPROM behind the tigon3 chip, among other things, so accesses to these areas just give bus timeouts. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index caf4102b54ce..31a16fa67558 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9097,6 +9097,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->phy_id = PHY_ID_INVALID; tp->led_ctrl = LED_CTRL_MODE_PHY_1; + /* Do not even try poking around in here on Sun parts. */ + if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) + return; + tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { u32 nic_cfg, led_cfg; -- cgit v1.2.3-59-g8ed1b From a858f1ca726edc5eb7ed39722f7966d005f1c9ca Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 16 Mar 2006 00:55:30 -0800 Subject: [SUNSU]: Fix missing spinlock initialization. Caught by CONFIG_DEBUG_SPINLOCK. Signed-off-by: David S. Miller --- drivers/serial/sunsu.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 46510e7f505c..46c44b83f57c 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1280,6 +1280,7 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel) struct serio *serio; #endif + spin_lock_init(&up->port.lock); up->port.line = channel; up->port.type = PORT_UNKNOWN; up->port.uartclk = (SU_BASE_BAUD * 16); @@ -1509,6 +1510,7 @@ static int __init sunsu_serial_init(void) up->su_type == SU_PORT_KBD) continue; + spin_lock_init(&up->port.lock); up->port.flags |= UPF_BOOT_AUTOCONF; up->port.type = PORT_UNKNOWN; up->port.uartclk = (SU_BASE_BAUD * 16); -- cgit v1.2.3-59-g8ed1b From b5e7ae5dd034c2c0ed75c31fca04a805097817bc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 17 Mar 2006 13:23:56 -0800 Subject: [SPARC64] bbc_i2c: Fix cpu check and add missing module license. Should allow cheetah_plus cpu types and don't taint the kernel. Signed-off-by: David S. Miller --- drivers/sbus/char/bbc_i2c.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 1c8b612d8234..3e156e005f2e 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -440,7 +440,8 @@ static int __init bbc_i2c_init(void) struct linux_ebus_device *edev = NULL; int err, index = 0; - if (tlb_type != cheetah || !bbc_present()) + if ((tlb_type != cheetah && tlb_type != cheetah_plus) || + !bbc_present()) return -ENODEV; for_each_ebus(ebus) { @@ -486,3 +487,4 @@ static void bbc_i2c_cleanup(void) module_init(bbc_i2c_init); module_exit(bbc_i2c_cleanup); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From d9b98b0f11ee7dd39429001ba289f095b9d66917 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 31 Jan 2006 20:45:51 -0800 Subject: IB/mthca: Make functions that never fail return void The function mthca_free_err_wqe() can never fail, so get rid of its return value. That means handle_error_cqe() doesn't have to check what mthca_free_err_wqe() returns, which means it can't fail either and doesn't have to return anything either. All this results in simpler source code and a slight object code improvement: add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-10 (-10) function old new delta mthca_free_err_wqe 83 81 -2 mthca_poll_cq 1758 1750 -8 Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cq.c | 25 ++++++++++--------------- drivers/infiniband/hw/mthca/mthca_dev.h | 4 ++-- drivers/infiniband/hw/mthca/mthca_qp.c | 8 +++----- 3 files changed, 15 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 96f1a86bf049..16a851b341f8 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -324,12 +324,11 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, wake_up(&cq->wait); } -static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, - struct mthca_qp *qp, int wqe_index, int is_send, - struct mthca_err_cqe *cqe, - struct ib_wc *entry, int *free_cqe) +static void handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, + struct mthca_qp *qp, int wqe_index, int is_send, + struct mthca_err_cqe *cqe, + struct ib_wc *entry, int *free_cqe) { - int err; int dbd; __be32 new_wqe; @@ -412,11 +411,9 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, * error case, so we don't have to check the doorbell count, etc. */ if (mthca_is_memfree(dev)) - return 0; + return; - err = mthca_free_err_wqe(dev, qp, is_send, wqe_index, &dbd, &new_wqe); - if (err) - return err; + mthca_free_err_wqe(dev, qp, is_send, wqe_index, &dbd, &new_wqe); /* * If we're at the end of the WQE chain, or we've used up our @@ -424,15 +421,13 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, * the next poll operation. */ if (!(new_wqe & cpu_to_be32(0x3f)) || (!cqe->db_cnt && dbd)) - return 0; + return; cqe->db_cnt = cpu_to_be16(be16_to_cpu(cqe->db_cnt) - dbd); cqe->wqe = new_wqe; cqe->syndrome = SYNDROME_WR_FLUSH_ERR; *free_cqe = 0; - - return 0; } static inline int mthca_poll_one(struct mthca_dev *dev, @@ -518,9 +513,9 @@ static inline int mthca_poll_one(struct mthca_dev *dev, } if (is_error) { - err = handle_error_cqe(dev, cq, *cur_qp, wqe_index, is_send, - (struct mthca_err_cqe *) cqe, - entry, &free_cqe); + handle_error_cqe(dev, cq, *cur_qp, wqe_index, is_send, + (struct mthca_err_cqe *) cqe, + entry, &free_cqe); goto out; } diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index e481037288d6..c98628ab8a09 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -495,8 +495,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, struct ib_send_wr **bad_wr); int mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, struct ib_recv_wr **bad_wr); -int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send, - int index, int *dbd, __be32 *new_wqe); +void mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send, + int index, int *dbd, __be32 *new_wqe); int mthca_alloc_qp(struct mthca_dev *dev, struct mthca_pd *pd, struct mthca_cq *send_cq, diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index fba608ed7df2..79245717e98f 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -2182,8 +2182,8 @@ out: return err; } -int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send, - int index, int *dbd, __be32 *new_wqe) +void mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send, + int index, int *dbd, __be32 *new_wqe) { struct mthca_next_seg *next; @@ -2193,7 +2193,7 @@ int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send, */ if (qp->ibqp.srq) { *new_wqe = 0; - return 0; + return; } if (is_send) @@ -2207,8 +2207,6 @@ int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send, (next->ee_nds & cpu_to_be32(0x3f)); else *new_wqe = 0; - - return 0; } int __devinit mthca_init_qp_table(struct mthca_dev *dev) -- cgit v1.2.3-59-g8ed1b From 399d7921299fc4f146bd62bfa6312382a5429bcc Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 31 Jan 2006 21:14:18 -0800 Subject: IB/mthca: Get rid of might_sleep() annotations The might_sleep() annotations in mthca are silly -- they all occur shortly before calls that will end up in core functions like kmalloc() that will print the same warning in an unsafe context anyway. In fact, beyond cluttering the source, we're actually bloating text with CONFIG_DEBUG_SPINLOCK_SLEEP and/or CONFIG_PREEMPT_VOLUNTARY set. With both options set, getting rid of the might_sleep()s saves a lot: add/remove: 0/0 grow/shrink: 0/7 up/down: 0/-171 (-171) function old new delta mthca_pd_alloc 132 109 -23 mthca_init_cq 969 946 -23 mthca_mr_alloc 592 568 -24 mthca_pd_free 67 42 -25 mthca_free_mr 219 194 -25 mthca_free_cq 570 545 -25 mthca_fmr_alloc 742 716 -26 Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cq.c | 4 ---- drivers/infiniband/hw/mthca/mthca_mr.c | 6 ------ drivers/infiniband/hw/mthca/mthca_pd.c | 3 --- 3 files changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 16a851b341f8..78d9cc119f33 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -696,8 +696,6 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, u8 status; int i; - might_sleep(); - cq->ibcq.cqe = nent - 1; cq->is_kernel = !ctx; @@ -827,8 +825,6 @@ void mthca_free_cq(struct mthca_dev *dev, int err; u8 status; - might_sleep(); - mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); if (IS_ERR(mailbox)) { mthca_warn(dev, "No memory for mailbox to free CQ.\n"); diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index e995e2aa016d..551320fdc9c5 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -340,8 +340,6 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift, int err; u8 status; - might_sleep(); - WARN_ON(buffer_size_shift >= 32); key = mthca_alloc(&dev->mr_table.mpt_alloc); @@ -467,8 +465,6 @@ void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr) int err; u8 status; - might_sleep(); - err = mthca_HW2SW_MPT(dev, NULL, key_to_hw_index(dev, mr->ibmr.lkey) & (dev->limits.num_mpts - 1), @@ -495,8 +491,6 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, int err = -ENOMEM; int i; - might_sleep(); - if (mr->attr.page_size < 12 || mr->attr.page_size >= 32) return -EINVAL; diff --git a/drivers/infiniband/hw/mthca/mthca_pd.c b/drivers/infiniband/hw/mthca/mthca_pd.c index 3dbf06a6e6f4..105fc5faaddf 100644 --- a/drivers/infiniband/hw/mthca/mthca_pd.c +++ b/drivers/infiniband/hw/mthca/mthca_pd.c @@ -43,8 +43,6 @@ int mthca_pd_alloc(struct mthca_dev *dev, int privileged, struct mthca_pd *pd) { int err = 0; - might_sleep(); - pd->privileged = privileged; atomic_set(&pd->sqp_count, 0); @@ -66,7 +64,6 @@ int mthca_pd_alloc(struct mthca_dev *dev, int privileged, struct mthca_pd *pd) void mthca_pd_free(struct mthca_dev *dev, struct mthca_pd *pd) { - might_sleep(); if (pd->privileged) mthca_free_mr(dev, &pd->ntmr); mthca_free(&dev->pd_table.alloc, pd->pd_num); -- cgit v1.2.3-59-g8ed1b From 33b9b3ee9709b19c4f02ab91571d53540d05c3d1 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 30 Jan 2006 14:29:21 -0800 Subject: IB: Add userspace support for resizing CQs Add support to uverbs to handle resizing userspace CQs (completion queues), including adding an ABI for marshalling requests and responses. The kernel midlayer already has ib_resize_cq(). Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs.h | 3 ++- drivers/infiniband/core/uverbs_cmd.c | 42 ++++++++++++++++++++++++++++++++++- drivers/infiniband/core/uverbs_main.c | 3 ++- drivers/infiniband/core/verbs.c | 4 ++-- include/rdma/ib_user_verbs.h | 13 ++++++++++- include/rdma/ib_verbs.h | 5 +++-- 6 files changed, 62 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index f7eecbc6af6c..3207239819ce 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. * Copyright (c) 2005 Voltaire, Inc. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. @@ -178,6 +178,7 @@ IB_UVERBS_DECLARE_CMD(reg_mr); IB_UVERBS_DECLARE_CMD(dereg_mr); IB_UVERBS_DECLARE_CMD(create_comp_channel); IB_UVERBS_DECLARE_CMD(create_cq); +IB_UVERBS_DECLARE_CMD(resize_cq); IB_UVERBS_DECLARE_CMD(poll_cq); IB_UVERBS_DECLARE_CMD(req_notify_cq); IB_UVERBS_DECLARE_CMD(destroy_cq); diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 407b6284d7d5..be1cef1b3116 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. * * This software is available to you under a choice of one of two @@ -675,6 +675,46 @@ err: return ret; } +ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file, + const char __user *buf, int in_len, + int out_len) +{ + struct ib_uverbs_resize_cq cmd; + struct ib_uverbs_resize_cq_resp resp; + struct ib_udata udata; + struct ib_cq *cq; + int ret = -EINVAL; + + if (copy_from_user(&cmd, buf, sizeof cmd)) + return -EFAULT; + + INIT_UDATA(&udata, buf + sizeof cmd, + (unsigned long) cmd.response + sizeof resp, + in_len - sizeof cmd, out_len - sizeof resp); + + mutex_lock(&ib_uverbs_idr_mutex); + + cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); + if (!cq || cq->uobject->context != file->ucontext || !cq->device->resize_cq) + goto out; + + ret = cq->device->resize_cq(cq, cmd.cqe, &udata); + if (ret) + goto out; + + memset(&resp, 0, sizeof resp); + resp.cqe = cq->cqe; + + if (copy_to_user((void __user *) (unsigned long) cmd.response, + &resp, sizeof resp)) + ret = -EFAULT; + +out: + mutex_unlock(&ib_uverbs_idr_mutex); + + return ret ? ret : in_len; +} + ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len) diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 903f85a4bc0c..099fe6cde68c 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. * Copyright (c) 2005 Voltaire, Inc. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. @@ -91,6 +91,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file, [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr, [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel, [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq, + [IB_USER_VERBS_CMD_RESIZE_CQ] = ib_uverbs_resize_cq, [IB_USER_VERBS_CMD_POLL_CQ] = ib_uverbs_poll_cq, [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ] = ib_uverbs_req_notify_cq, [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq, diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index c857361be449..8e0ba16bcbdd 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -5,7 +5,7 @@ * Copyright (c) 2004 Topspin Corporation. All rights reserved. * Copyright (c) 2004 Voltaire Corporation. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -326,7 +326,7 @@ int ib_resize_cq(struct ib_cq *cq, int cqe) { return cq->device->resize_cq ? - cq->device->resize_cq(cq, cqe) : -ENOSYS; + cq->device->resize_cq(cq, cqe, NULL) : -ENOSYS; } EXPORT_SYMBOL(ib_resize_cq); diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index 5ff1490c08db..6ad1207e4235 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. * * This software is available to you under a choice of one of two @@ -265,6 +265,17 @@ struct ib_uverbs_create_cq_resp { __u32 cqe; }; +struct ib_uverbs_resize_cq { + __u64 response; + __u32 cq_handle; + __u32 cqe; + __u64 driver_data[0]; +}; + +struct ib_uverbs_resize_cq_resp { + __u32 cqe; +}; + struct ib_uverbs_poll_cq { __u64 response; __u32 cq_handle; diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 22fc886b9695..38fa6c082eae 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -5,7 +5,7 @@ * Copyright (c) 2004 Topspin Corporation. All rights reserved. * Copyright (c) 2004 Voltaire Corporation. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -880,7 +880,8 @@ struct ib_device { struct ib_ucontext *context, struct ib_udata *udata); int (*destroy_cq)(struct ib_cq *cq); - int (*resize_cq)(struct ib_cq *cq, int cqe); + int (*resize_cq)(struct ib_cq *cq, int cqe, + struct ib_udata *udata); int (*poll_cq)(struct ib_cq *cq, int num_entries, struct ib_wc *wc); int (*peek_cq)(struct ib_cq *cq, int wc_cnt); -- cgit v1.2.3-59-g8ed1b From 4885bf64bc2eb242ebebe67077cfe3688283b586 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 30 Jan 2006 14:31:33 -0800 Subject: IB/mthca: Add device-specific support for resizing CQs Add low-level driver support for resizing CQs (both kernel and userspace) to mthca. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cmd.c | 33 ++++++- drivers/infiniband/hw/mthca/mthca_cmd.h | 3 + drivers/infiniband/hw/mthca/mthca_cq.c | 132 +++++++++++++++++++++------ drivers/infiniband/hw/mthca/mthca_dev.h | 5 +- drivers/infiniband/hw/mthca/mthca_provider.c | 127 +++++++++++++++++++++++++- drivers/infiniband/hw/mthca/mthca_provider.h | 53 +++++++---- drivers/infiniband/hw/mthca/mthca_user.h | 7 +- 7 files changed, 308 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 2825615ce81c..7780e974cfb5 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -1514,6 +1514,37 @@ int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, CMD_TIME_CLASS_A, status); } +int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size, + u8 *status) +{ + struct mthca_mailbox *mailbox; + __be32 *inbox; + int err; + +#define RESIZE_CQ_IN_SIZE 0x40 +#define RESIZE_CQ_LOG_SIZE_OFFSET 0x0c +#define RESIZE_CQ_LKEY_OFFSET 0x1c + + mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + inbox = mailbox->buf; + + memset(inbox, 0, RESIZE_CQ_IN_SIZE); + /* + * Leave start address fields zeroed out -- mthca assumes that + * MRs for CQs always start at virtual address 0. + */ + MTHCA_PUT(inbox, log_size, RESIZE_CQ_LOG_SIZE_OFFSET); + MTHCA_PUT(inbox, lkey, RESIZE_CQ_LKEY_OFFSET); + + err = mthca_cmd(dev, mailbox->dma, cq_num, 1, CMD_RESIZE_CQ, + CMD_TIME_CLASS_B, status); + + mthca_free_mailbox(dev, mailbox); + return err; +} + int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, int srq_num, u8 *status) { diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h index 18175bec84c2..3473b8235ee0 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.h +++ b/drivers/infiniband/hw/mthca/mthca_cmd.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. + * Copyright (c) 2006 Cisco Systems. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -298,6 +299,8 @@ int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, int cq_num, u8 *status); int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, int cq_num, u8 *status); +int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size, + u8 *status); int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, int srq_num, u8 *status); int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 78d9cc119f33..76aabc5bf371 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. * Copyright (c) 2004 Voltaire, Inc. All rights reserved. * @@ -150,24 +150,29 @@ struct mthca_err_cqe { #define MTHCA_ARBEL_CQ_DB_REQ_NOT (2 << 24) #define MTHCA_ARBEL_CQ_DB_REQ_NOT_MULT (3 << 24) -static inline struct mthca_cqe *get_cqe(struct mthca_cq *cq, int entry) +static inline struct mthca_cqe *get_cqe_from_buf(struct mthca_cq_buf *buf, + int entry) { - if (cq->is_direct) - return cq->queue.direct.buf + (entry * MTHCA_CQ_ENTRY_SIZE); + if (buf->is_direct) + return buf->queue.direct.buf + (entry * MTHCA_CQ_ENTRY_SIZE); else - return cq->queue.page_list[entry * MTHCA_CQ_ENTRY_SIZE / PAGE_SIZE].buf + return buf->queue.page_list[entry * MTHCA_CQ_ENTRY_SIZE / PAGE_SIZE].buf + (entry * MTHCA_CQ_ENTRY_SIZE) % PAGE_SIZE; } -static inline struct mthca_cqe *cqe_sw(struct mthca_cq *cq, int i) +static inline struct mthca_cqe *get_cqe(struct mthca_cq *cq, int entry) +{ + return get_cqe_from_buf(&cq->buf, entry); +} + +static inline struct mthca_cqe *cqe_sw(struct mthca_cqe *cqe) { - struct mthca_cqe *cqe = get_cqe(cq, i); return MTHCA_CQ_ENTRY_OWNER_HW & cqe->owner ? NULL : cqe; } static inline struct mthca_cqe *next_cqe_sw(struct mthca_cq *cq) { - return cqe_sw(cq, cq->cons_index & cq->ibcq.cqe); + return cqe_sw(get_cqe(cq, cq->cons_index & cq->ibcq.cqe)); } static inline void set_cqe_hw(struct mthca_cqe *cqe) @@ -289,7 +294,7 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, * from our QP and therefore don't need to be checked. */ for (prod_index = cq->cons_index; - cqe_sw(cq, prod_index & cq->ibcq.cqe); + cqe_sw(get_cqe(cq, prod_index & cq->ibcq.cqe)); ++prod_index) if (prod_index == cq->cons_index + cq->ibcq.cqe) break; @@ -324,6 +329,53 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, wake_up(&cq->wait); } +void mthca_cq_resize_copy_cqes(struct mthca_cq *cq) +{ + int i; + + /* + * In Tavor mode, the hardware keeps the consumer and producer + * indices mod the CQ size. Since we might be making the CQ + * bigger, we need to deal with the case where the producer + * index wrapped around before the CQ was resized. + */ + if (!mthca_is_memfree(to_mdev(cq->ibcq.device)) && + cq->ibcq.cqe < cq->resize_buf->cqe) { + cq->cons_index &= cq->ibcq.cqe; + if (cqe_sw(get_cqe(cq, cq->ibcq.cqe))) + cq->cons_index -= cq->ibcq.cqe + 1; + } + + for (i = cq->cons_index; cqe_sw(get_cqe(cq, i & cq->ibcq.cqe)); ++i) + memcpy(get_cqe_from_buf(&cq->resize_buf->buf, + i & cq->resize_buf->cqe), + get_cqe(cq, i & cq->ibcq.cqe), MTHCA_CQ_ENTRY_SIZE); +} + +int mthca_alloc_cq_buf(struct mthca_dev *dev, struct mthca_cq_buf *buf, int nent) +{ + int ret; + int i; + + ret = mthca_buf_alloc(dev, nent * MTHCA_CQ_ENTRY_SIZE, + MTHCA_MAX_DIRECT_CQ_SIZE, + &buf->queue, &buf->is_direct, + &dev->driver_pd, 1, &buf->mr); + if (ret) + return ret; + + for (i = 0; i < nent; ++i) + set_cqe_hw(get_cqe_from_buf(buf, i)); + + return 0; +} + +void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq_buf *buf, int cqe) +{ + mthca_buf_free(dev, (cqe + 1) * MTHCA_CQ_ENTRY_SIZE, &buf->queue, + buf->is_direct, &buf->mr); +} + static void handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, struct mthca_qp *qp, int wqe_index, int is_send, struct mthca_err_cqe *cqe, @@ -609,11 +661,14 @@ int mthca_poll_cq(struct ib_cq *ibcq, int num_entries, spin_lock_irqsave(&cq->lock, flags); - for (npolled = 0; npolled < num_entries; ++npolled) { + npolled = 0; +repoll: + while (npolled < num_entries) { err = mthca_poll_one(dev, cq, &qp, &freed, entry + npolled); if (err) break; + ++npolled; } if (freed) { @@ -621,6 +676,42 @@ int mthca_poll_cq(struct ib_cq *ibcq, int num_entries, update_cons_index(dev, cq, freed); } + /* + * If a CQ resize is in progress and we discovered that the + * old buffer is empty, then peek in the new buffer, and if + * it's not empty, switch to the new buffer and continue + * polling there. + */ + if (unlikely(err == -EAGAIN && cq->resize_buf && + cq->resize_buf->state == CQ_RESIZE_READY)) { + /* + * In Tavor mode, the hardware keeps the producer + * index modulo the CQ size. Since we might be making + * the CQ bigger, we need to mask our consumer index + * using the size of the old CQ buffer before looking + * in the new CQ buffer. + */ + if (!mthca_is_memfree(dev)) + cq->cons_index &= cq->ibcq.cqe; + + if (cqe_sw(get_cqe_from_buf(&cq->resize_buf->buf, + cq->cons_index & cq->resize_buf->cqe))) { + struct mthca_cq_buf tbuf; + int tcqe; + + tbuf = cq->buf; + tcqe = cq->ibcq.cqe; + cq->buf = cq->resize_buf->buf; + cq->ibcq.cqe = cq->resize_buf->cqe; + + cq->resize_buf->buf = tbuf; + cq->resize_buf->cqe = tcqe; + cq->resize_buf->state = CQ_RESIZE_SWAPPED; + + goto repoll; + } + } + spin_unlock_irqrestore(&cq->lock, flags); return err == 0 || err == -EAGAIN ? npolled : err; @@ -679,22 +770,14 @@ int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify) return 0; } -static void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq *cq) -{ - mthca_buf_free(dev, (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE, - &cq->queue, cq->is_direct, &cq->mr); -} - int mthca_init_cq(struct mthca_dev *dev, int nent, struct mthca_ucontext *ctx, u32 pdn, struct mthca_cq *cq) { - int size = nent * MTHCA_CQ_ENTRY_SIZE; struct mthca_mailbox *mailbox; struct mthca_cq_context *cq_context; int err = -ENOMEM; u8 status; - int i; cq->ibcq.cqe = nent - 1; cq->is_kernel = !ctx; @@ -732,14 +815,9 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, cq_context = mailbox->buf; if (cq->is_kernel) { - err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_CQ_SIZE, - &cq->queue, &cq->is_direct, - &dev->driver_pd, 1, &cq->mr); + err = mthca_alloc_cq_buf(dev, &cq->buf, nent); if (err) goto err_out_mailbox; - - for (i = 0; i < nent; ++i) - set_cqe_hw(get_cqe(cq, i)); } spin_lock_init(&cq->lock); @@ -758,7 +836,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, cq_context->error_eqn = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn); cq_context->comp_eqn = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_COMP].eqn); cq_context->pd = cpu_to_be32(pdn); - cq_context->lkey = cpu_to_be32(cq->mr.ibmr.lkey); + cq_context->lkey = cpu_to_be32(cq->buf.mr.ibmr.lkey); cq_context->cqn = cpu_to_be32(cq->cqn); if (mthca_is_memfree(dev)) { @@ -796,7 +874,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, err_out_free_mr: if (cq->is_kernel) - mthca_free_cq_buf(dev, cq); + mthca_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe); err_out_mailbox: mthca_free_mailbox(dev, mailbox); @@ -862,7 +940,7 @@ void mthca_free_cq(struct mthca_dev *dev, wait_event(cq->wait, !atomic_read(&cq->refcount)); if (cq->is_kernel) { - mthca_free_cq_buf(dev, cq); + mthca_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe); if (mthca_is_memfree(dev)) { mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index); mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index); diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index c98628ab8a09..d827558c27be 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. * Copyright (c) 2004 Voltaire, Inc. All rights reserved. * @@ -470,6 +470,9 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn, enum ib_event_type event_type); void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, struct mthca_srq *srq); +void mthca_cq_resize_copy_cqes(struct mthca_cq *cq); +int mthca_alloc_cq_buf(struct mthca_dev *dev, struct mthca_cq_buf *buf, int nent); +void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq_buf *buf, int cqe); int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, struct ib_srq_attr *attr, struct mthca_srq *srq); diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index e88e39aef85a..cd2038bdd1ac 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. * Copyright (c) 2004 Voltaire, Inc. All rights reserved. * @@ -669,9 +669,9 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries, } if (context) { - cq->mr.ibmr.lkey = ucmd.lkey; - cq->set_ci_db_index = ucmd.set_db_index; - cq->arm_db_index = ucmd.arm_db_index; + cq->buf.mr.ibmr.lkey = ucmd.lkey; + cq->set_ci_db_index = ucmd.set_db_index; + cq->arm_db_index = ucmd.arm_db_index; } for (nent = 1; nent <= entries; nent <<= 1) @@ -689,6 +689,8 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries, goto err_free; } + cq->resize_buf = NULL; + return &cq->ibcq; err_free: @@ -707,6 +709,121 @@ err_unmap_set: return ERR_PTR(err); } +static int mthca_alloc_resize_buf(struct mthca_dev *dev, struct mthca_cq *cq, + int entries) +{ + int ret; + + spin_lock_irq(&cq->lock); + if (cq->resize_buf) { + ret = -EBUSY; + goto unlock; + } + + cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC); + if (!cq->resize_buf) { + ret = -ENOMEM; + goto unlock; + } + + cq->resize_buf->state = CQ_RESIZE_ALLOC; + + ret = 0; + +unlock: + spin_unlock_irq(&cq->lock); + + if (ret) + return ret; + + ret = mthca_alloc_cq_buf(dev, &cq->resize_buf->buf, entries); + if (ret) { + spin_lock_irq(&cq->lock); + kfree(cq->resize_buf); + cq->resize_buf = NULL; + spin_unlock_irq(&cq->lock); + return ret; + } + + cq->resize_buf->cqe = entries - 1; + + spin_lock_irq(&cq->lock); + cq->resize_buf->state = CQ_RESIZE_READY; + spin_unlock_irq(&cq->lock); + + return 0; +} + +static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) +{ + struct mthca_dev *dev = to_mdev(ibcq->device); + struct mthca_cq *cq = to_mcq(ibcq); + struct mthca_resize_cq ucmd; + u32 lkey; + u8 status; + int ret; + + if (entries < 1 || entries > dev->limits.max_cqes) + return -EINVAL; + + entries = roundup_pow_of_two(entries + 1); + if (entries == ibcq->cqe + 1) + return 0; + + if (cq->is_kernel) { + ret = mthca_alloc_resize_buf(dev, cq, entries); + if (ret) + return ret; + lkey = cq->resize_buf->buf.mr.ibmr.lkey; + } else { + if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) + return -EFAULT; + lkey = ucmd.lkey; + } + + ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, long_log2(entries), &status); + if (status) + ret = -EINVAL; + + if (ret) { + if (cq->resize_buf) { + mthca_free_cq_buf(dev, &cq->resize_buf->buf, + cq->resize_buf->cqe); + kfree(cq->resize_buf); + spin_lock_irq(&cq->lock); + cq->resize_buf = NULL; + spin_unlock_irq(&cq->lock); + } + return ret; + } + + if (cq->is_kernel) { + struct mthca_cq_buf tbuf; + int tcqe; + + spin_lock_irq(&cq->lock); + if (cq->resize_buf->state == CQ_RESIZE_READY) { + mthca_cq_resize_copy_cqes(cq); + tbuf = cq->buf; + tcqe = cq->ibcq.cqe; + cq->buf = cq->resize_buf->buf; + cq->ibcq.cqe = cq->resize_buf->cqe; + } else { + tbuf = cq->resize_buf->buf; + tcqe = cq->resize_buf->cqe; + } + + kfree(cq->resize_buf); + cq->resize_buf = NULL; + spin_unlock_irq(&cq->lock); + + mthca_free_cq_buf(dev, &tbuf, tcqe); + } else + ibcq->cqe = entries - 1; + + return 0; +} + static int mthca_destroy_cq(struct ib_cq *cq) { if (cq->uobject) { @@ -1113,6 +1230,7 @@ int mthca_register_device(struct mthca_dev *dev) (1ull << IB_USER_VERBS_CMD_DEREG_MR) | (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | + (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) | (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | (1ull << IB_USER_VERBS_CMD_CREATE_QP) | (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | @@ -1154,6 +1272,7 @@ int mthca_register_device(struct mthca_dev *dev) dev->ib_dev.modify_qp = mthca_modify_qp; dev->ib_dev.destroy_qp = mthca_destroy_qp; dev->ib_dev.create_cq = mthca_create_cq; + dev->ib_dev.resize_cq = mthca_resize_cq; dev->ib_dev.destroy_cq = mthca_destroy_cq; dev->ib_dev.poll_cq = mthca_poll_cq; dev->ib_dev.get_dma_mr = mthca_get_dma_mr; diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h index 1e73947b4702..2e7f52136965 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.h +++ b/drivers/infiniband/hw/mthca/mthca_provider.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. * * This software is available to you under a choice of one of two @@ -164,9 +164,11 @@ struct mthca_ah { * - wait_event until ref count is zero * * It is the consumer's responsibilty to make sure that no QP - * operations (WQE posting or state modification) are pending when the + * operations (WQE posting or state modification) are pending when a * QP is destroyed. Also, the consumer must make sure that calls to - * qp_modify are serialized. + * qp_modify are serialized. Similarly, the consumer is responsible + * for ensuring that no CQ resize operations are pending when a CQ + * is destroyed. * * Possible optimizations (wait for profile data to see if/where we * have locks bouncing between CPUs): @@ -176,25 +178,40 @@ struct mthca_ah { * send queue and one for the receive queue) */ +struct mthca_cq_buf { + union mthca_buf queue; + struct mthca_mr mr; + int is_direct; +}; + +struct mthca_cq_resize { + struct mthca_cq_buf buf; + int cqe; + enum { + CQ_RESIZE_ALLOC, + CQ_RESIZE_READY, + CQ_RESIZE_SWAPPED + } state; +}; + struct mthca_cq { - struct ib_cq ibcq; - spinlock_t lock; - atomic_t refcount; - int cqn; - u32 cons_index; - int is_direct; - int is_kernel; + struct ib_cq ibcq; + spinlock_t lock; + atomic_t refcount; + int cqn; + u32 cons_index; + struct mthca_cq_buf buf; + struct mthca_cq_resize *resize_buf; + int is_kernel; /* Next fields are Arbel only */ - int set_ci_db_index; - __be32 *set_ci_db; - int arm_db_index; - __be32 *arm_db; - int arm_sn; + int set_ci_db_index; + __be32 *set_ci_db; + int arm_db_index; + __be32 *arm_db; + int arm_sn; - union mthca_buf queue; - struct mthca_mr mr; - wait_queue_head_t wait; + wait_queue_head_t wait; }; struct mthca_srq { diff --git a/drivers/infiniband/hw/mthca/mthca_user.h b/drivers/infiniband/hw/mthca/mthca_user.h index bb015c6494c4..02cc0a766f3a 100644 --- a/drivers/infiniband/hw/mthca/mthca_user.h +++ b/drivers/infiniband/hw/mthca/mthca_user.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -75,6 +75,11 @@ struct mthca_create_cq_resp { __u32 reserved; }; +struct mthca_resize_cq { + __u32 lkey; + __u32 reserved; +}; + struct mthca_create_srq { __u32 lkey; __u32 db_index; -- cgit v1.2.3-59-g8ed1b From 2fa5e2ebbe2d81f741ba7bed9e07dc38cc734625 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 1 Feb 2006 13:38:24 -0800 Subject: IB/mthca: Whitespace cleanups Remove trailing whitespace and fix indentation that with spaces instead of tabs. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_av.c | 2 +- drivers/infiniband/hw/mthca/mthca_cmd.c | 2 +- drivers/infiniband/hw/mthca/mthca_cmd.h | 4 ++-- drivers/infiniband/hw/mthca/mthca_eq.c | 2 +- drivers/infiniband/hw/mthca/mthca_mcg.c | 2 +- drivers/infiniband/hw/mthca/mthca_mr.c | 6 +++--- drivers/infiniband/hw/mthca/mthca_provider.c | 4 ++-- drivers/infiniband/hw/mthca/mthca_qp.c | 28 ++++++++++++++-------------- drivers/infiniband/hw/mthca/mthca_srq.c | 2 +- 9 files changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index a19e0ed03d7c..198f1267e984 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c @@ -147,7 +147,7 @@ int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah) switch (ah->type) { case MTHCA_AH_ON_HCA: mthca_free(&dev->av_table.alloc, - (ah->avdma - dev->av_table.ddr_av_base) / + (ah->avdma - dev->av_table.ddr_av_base) / MTHCA_AV_SIZE); break; diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 7780e974cfb5..7150fd143bff 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -275,7 +275,7 @@ static int mthca_cmd_poll(struct mthca_dev *dev, } if (out_is_imm) - *out_param = + *out_param = (u64) be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET)) << 32 | (u64) be32_to_cpu((__force __be32) diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h index 3473b8235ee0..a8da84b0a0f1 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.h +++ b/drivers/infiniband/hw/mthca/mthca_cmd.h @@ -74,9 +74,9 @@ enum { MTHCA_CMD_STAT_REG_BOUND = 0x21, /* HCA local attached memory not present: */ MTHCA_CMD_STAT_LAM_NOT_PRE = 0x22, - /* Bad management packet (silently discarded): */ + /* Bad management packet (silently discarded): */ MTHCA_CMD_STAT_BAD_PKT = 0x30, - /* More outstanding CQEs in CQ than new CQ size: */ + /* More outstanding CQEs in CQ than new CQ size: */ MTHCA_CMD_STAT_BAD_SIZE = 0x40 }; diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index 2eabb27804cd..cf43a5388397 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -497,7 +497,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, eq->dev = dev; eq->nent = roundup_pow_of_two(max(nent, 2)); - npages = ALIGN(eq->nent * MTHCA_EQ_ENTRY_SIZE, PAGE_SIZE) / PAGE_SIZE; + npages = ALIGN(eq->nent * MTHCA_EQ_ENTRY_SIZE, PAGE_SIZE) / PAGE_SIZE; eq->page_list = kmalloc(npages * sizeof *eq->page_list, GFP_KERNEL); diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index 321f11e707f2..9965bda9afed 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c @@ -187,7 +187,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) for (i = 0; i < MTHCA_QP_PER_MGM; ++i) if (mgm->qp[i] == cpu_to_be32(ibqp->qp_num | (1 << 31))) { - mthca_dbg(dev, "QP %06x already a member of MGM\n", + mthca_dbg(dev, "QP %06x already a member of MGM\n", ibqp->qp_num); err = 0; goto out; diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 551320fdc9c5..653f1321a13f 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -517,7 +517,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, BUG_ON(!mr->mem.arbel.mpt); } else mr->mem.tavor.mpt = dev->mr_table.tavor_fmr.mpt_base + - sizeof *(mr->mem.tavor.mpt) * idx; + sizeof *(mr->mem.tavor.mpt) * idx; mr->mtt = __mthca_alloc_mtt(dev, list_len, dev->mr_table.fmr_mtt_buddy); if (IS_ERR(mr->mtt)) @@ -779,7 +779,7 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev) } dev->mr_table.tavor_fmr.mpt_base = - ioremap(dev->mr_table.mpt_base, + ioremap(dev->mr_table.mpt_base, (1 << i) * sizeof (struct mthca_mpt_entry)); if (!dev->mr_table.tavor_fmr.mpt_base) { @@ -807,7 +807,7 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev) goto err_reserve_fmr; dev->mr_table.fmr_mtt_buddy = - &dev->mr_table.tavor_fmr.mtt_buddy; + &dev->mr_table.tavor_fmr.mtt_buddy; } else dev->mr_table.fmr_mtt_buddy = &dev->mr_table.mtt_buddy; diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index cd2038bdd1ac..76321f0ef019 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -108,12 +108,12 @@ static int mthca_query_device(struct ib_device *ibdev, props->max_srq_wr = mdev->limits.max_srq_wqes; props->max_srq_sge = mdev->limits.max_sg; props->local_ca_ack_delay = mdev->limits.local_ca_ack_delay; - props->atomic_cap = mdev->limits.flags & DEV_LIM_FLAG_ATOMIC ? + props->atomic_cap = mdev->limits.flags & DEV_LIM_FLAG_ATOMIC ? IB_ATOMIC_HCA : IB_ATOMIC_NONE; props->max_pkeys = mdev->limits.pkey_table_len; props->max_mcast_grp = mdev->limits.num_mgms + mdev->limits.num_amgms; props->max_mcast_qp_attach = MTHCA_QP_PER_MGM; - props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * + props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * props->max_mcast_grp; err = 0; diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 79245717e98f..bdba39a8d9f9 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -2,7 +2,7 @@ * Copyright (c) 2004 Topspin Communications. All rights reserved. * Copyright (c) 2005 Cisco Systems. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2004 Voltaire, Inc. All rights reserved. + * Copyright (c) 2004 Voltaire, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -559,9 +559,9 @@ static void mthca_path_set(struct ib_ah_attr *ah, struct mthca_qp_path *path) path->g_mylmc |= 1 << 7; path->mgid_index = ah->grh.sgid_index; path->hop_limit = ah->grh.hop_limit; - path->sl_tclass_flowlabel = + path->sl_tclass_flowlabel = cpu_to_be32((ah->sl << 28) | - (ah->grh.traffic_class << 20) | + (ah->grh.traffic_class << 20) | (ah->grh.flow_label)); memcpy(path->rgid, ah->grh.dgid.raw, 16); } else @@ -597,7 +597,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) } if (attr_mask & IB_QP_STATE) { - if (attr->qp_state < 0 || attr->qp_state > IB_QPS_ERR) + if (attr->qp_state < 0 || attr->qp_state > IB_QPS_ERR) return -EINVAL; new_state = attr->qp_state; } else @@ -630,10 +630,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) return -EINVAL; } - if ((attr_mask & IB_QP_PKEY_INDEX) && + if ((attr_mask & IB_QP_PKEY_INDEX) && attr->pkey_index >= dev->limits.pkey_table_len) { mthca_dbg(dev, "PKey index (%u) too large. max is %d\n", - attr->pkey_index,dev->limits.pkey_table_len-1); + attr->pkey_index,dev->limits.pkey_table_len-1); return -EINVAL; } @@ -733,7 +733,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) if (attr_mask & IB_QP_RNR_RETRY) { qp_context->alt_path.rnr_retry = qp_context->pri_path.rnr_retry = attr->rnr_retry << 5; - qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY | + qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY | MTHCA_QP_OPTPAR_ALT_RNR_RETRY); } @@ -749,13 +749,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) if (attr_mask & IB_QP_ALT_PATH) { if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) { - mthca_dbg(dev, "Alternate port number (%u) is invalid\n", + mthca_dbg(dev, "Alternate port number (%u) is invalid\n", attr->alt_port_num); return -EINVAL; } mthca_path_set(&attr->alt_ah_attr, &qp_context->alt_path); - qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index | + qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index | attr->alt_port_num << 24); qp_context->alt_path.ackto = attr->alt_timeout << 3; qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ALT_ADDR_PATH); @@ -1078,10 +1078,10 @@ static int mthca_map_memfree(struct mthca_dev *dev, if (ret) goto err_qpc; - ret = mthca_table_get(dev, dev->qp_table.rdb_table, - qp->qpn << dev->qp_table.rdb_shift); - if (ret) - goto err_eqpc; + ret = mthca_table_get(dev, dev->qp_table.rdb_table, + qp->qpn << dev->qp_table.rdb_shift); + if (ret) + goto err_eqpc; } @@ -2115,7 +2115,7 @@ int mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, int i; void *wqe; - spin_lock_irqsave(&qp->rq.lock, flags); + spin_lock_irqsave(&qp->rq.lock, flags); /* XXX check that state is OK to post receive */ diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index e7e153d9c4c6..f1a1da147d0b 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -339,7 +339,7 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq) int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, enum ib_srq_attr_mask attr_mask) -{ +{ struct mthca_dev *dev = to_mdev(ibsrq->device); struct mthca_srq *srq = to_msrq(ibsrq); int ret; -- cgit v1.2.3-59-g8ed1b From c5bcbbb9fe00128d500c2f473d5ddc8d8c2c53a7 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 2 Feb 2006 09:47:14 -0800 Subject: IB: Allow userspace to set node description Expose a writable "node_desc" sysfs attribute for InfiniBand devices. This allows userspace to update the node description with information such as the node's hostname, so that IB network management software can tie its view to the real world. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/core/sysfs.c | 30 +++++++++++++++++++++++++++++- include/rdma/ib_verbs.h | 5 ++++- 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 5982d687a000..49601bb8475b 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -628,14 +628,42 @@ static ssize_t show_node_guid(struct class_device *cdev, char *buf) be16_to_cpu(((__be16 *) &dev->node_guid)[3])); } +static ssize_t show_node_desc(struct class_device *cdev, char *buf) +{ + struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); + + return sprintf(buf, "%.64s\n", dev->node_desc); +} + +static ssize_t set_node_desc(struct class_device *cdev, const char *buf, + size_t count) +{ + struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); + struct ib_device_modify desc = {}; + int ret; + + if (!dev->modify_device) + return -EIO; + + memcpy(desc.node_desc, buf, min_t(int, count, 64)); + ret = ib_modify_device(dev, IB_DEVICE_MODIFY_NODE_DESC, &desc); + if (ret) + return ret; + + return count; +} + static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); static CLASS_DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL); static CLASS_DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL); +static CLASS_DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc, + set_node_desc); static struct class_device_attribute *ib_class_attributes[] = { &class_device_attr_node_type, &class_device_attr_sys_image_guid, - &class_device_attr_node_guid + &class_device_attr_node_guid, + &class_device_attr_node_desc }; static struct class ib_class = { diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 38fa6c082eae..1d31c8cd5ce0 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -222,11 +222,13 @@ struct ib_port_attr { }; enum ib_device_modify_flags { - IB_DEVICE_MODIFY_SYS_IMAGE_GUID = 1 + IB_DEVICE_MODIFY_SYS_IMAGE_GUID = 1 << 0, + IB_DEVICE_MODIFY_NODE_DESC = 1 << 1 }; struct ib_device_modify { u64 sys_image_guid; + char node_desc[64]; }; enum ib_port_modify_flags { @@ -951,6 +953,7 @@ struct ib_device { u64 uverbs_cmd_mask; int uverbs_abi_ver; + char node_desc[64]; __be64 node_guid; u8 node_type; u8 phys_port_cnt; -- cgit v1.2.3-59-g8ed1b From 6dfc3901b04d1b79fa982d6de6d5af3b50c6cea8 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 2 Feb 2006 10:04:19 -0800 Subject: IB/mthca: Add modify_device method to set node description Add a modify_device method to mthca, which implements setting the node description. This makes the writable "node_desc" sysfs attribute work for Mellanox HCAs. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_mad.c | 17 ++++++++++++++- drivers/infiniband/hw/mthca/mthca_provider.c | 32 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 1229c604c6e0..4ace6a392f41 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c @@ -109,6 +109,19 @@ static void smp_snoop(struct ib_device *ibdev, } } +static void node_desc_override(struct ib_device *dev, + struct ib_mad *mad) +{ + if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || + mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && + mad->mad_hdr.method == IB_MGMT_METHOD_GET_RESP && + mad->mad_hdr.attr_id == IB_SMP_ATTR_NODE_DESC) { + mutex_lock(&to_mdev(dev)->cap_mask_mutex); + memcpy(((struct ib_smp *) mad)->data, dev->node_desc, 64); + mutex_unlock(&to_mdev(dev)->cap_mask_mutex); + } +} + static void forward_trap(struct mthca_dev *dev, u8 port_num, struct ib_mad *mad) @@ -207,8 +220,10 @@ int mthca_process_mad(struct ib_device *ibdev, return IB_MAD_RESULT_FAILURE; } - if (!out_mad->mad_hdr.status) + if (!out_mad->mad_hdr.status) { smp_snoop(ibdev, port_num, in_mad); + node_desc_override(ibdev, out_mad); + } /* set return bit in status of directed route responses */ if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 76321f0ef019..1fa1b55ffffe 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -176,6 +176,23 @@ static int mthca_query_port(struct ib_device *ibdev, return err; } +static int mthca_modify_device(struct ib_device *ibdev, + int mask, + struct ib_device_modify *props) +{ + if (mask & ~IB_DEVICE_MODIFY_NODE_DESC) + return -EOPNOTSUPP; + + if (mask & IB_DEVICE_MODIFY_NODE_DESC) { + if (mutex_lock_interruptible(&to_mdev(ibdev)->cap_mask_mutex)) + return -ERESTARTSYS; + memcpy(ibdev->node_desc, props->node_desc, 64); + mutex_unlock(&to_mdev(ibdev)->cap_mask_mutex); + } + + return 0; +} + static int mthca_modify_port(struct ib_device *ibdev, u8 port, int port_modify_mask, struct ib_port_modify *props) @@ -1187,6 +1204,20 @@ static int mthca_init_node_data(struct mthca_dev *dev) goto out; init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; + + err = mthca_MAD_IFC(dev, 1, 1, + 1, NULL, NULL, in_mad, out_mad, + &status); + if (err) + goto out; + if (status) { + err = -EINVAL; + goto out; + } + + memcpy(dev->ib_dev.node_desc, out_mad->data, 64); + in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; err = mthca_MAD_IFC(dev, 1, 1, @@ -1246,6 +1277,7 @@ int mthca_register_device(struct mthca_dev *dev) dev->ib_dev.class_dev.dev = &dev->pdev->dev; dev->ib_dev.query_device = mthca_query_device; dev->ib_dev.query_port = mthca_query_port; + dev->ib_dev.modify_device = mthca_modify_device; dev->ib_dev.modify_port = mthca_modify_port; dev->ib_dev.query_pkey = mthca_query_pkey; dev->ib_dev.query_gid = mthca_query_gid; -- cgit v1.2.3-59-g8ed1b From d36f34aadf184d8cc4c240de2b6319ccea8334bb Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Thu, 2 Feb 2006 10:43:45 -0800 Subject: IB: Enable FMR pool user to set page size This patch allows the consumer to set the page size of "pages" mapped by the pool FMRs, which is a feature already existing in the base verbs API. On the cosmetic side it changes ib_fmr_attr.page_size field to be named page_shift. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/core/fmr_pool.c | 6 +++--- drivers/infiniband/hw/mthca/mthca_mr.c | 10 +++++----- include/rdma/ib_fmr_pool.h | 2 ++ include/rdma/ib_verbs.h | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c index d34a6f1c4f4c..838bf54458d2 100644 --- a/drivers/infiniband/core/fmr_pool.c +++ b/drivers/infiniband/core/fmr_pool.c @@ -278,9 +278,9 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd *pd, { struct ib_pool_fmr *fmr; struct ib_fmr_attr attr = { - .max_pages = params->max_pages_per_fmr, - .max_maps = IB_FMR_MAX_REMAPS, - .page_size = PAGE_SHIFT + .max_pages = params->max_pages_per_fmr, + .max_maps = IB_FMR_MAX_REMAPS, + .page_shift = params->page_shift }; for (i = 0; i < params->pool_size; ++i) { diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 653f1321a13f..0b48048ad0f8 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -491,7 +491,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, int err = -ENOMEM; int i; - if (mr->attr.page_size < 12 || mr->attr.page_size >= 32) + if (mr->attr.page_shift < 12 || mr->attr.page_shift >= 32) return -EINVAL; /* For Arbel, all MTTs must fit in the same page. */ @@ -543,7 +543,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, MTHCA_MPT_FLAG_REGION | access); - mpt_entry->page_size = cpu_to_be32(mr->attr.page_size - 12); + mpt_entry->page_size = cpu_to_be32(mr->attr.page_shift - 12); mpt_entry->key = cpu_to_be32(key); mpt_entry->pd = cpu_to_be32(pd); memset(&mpt_entry->start, 0, @@ -611,7 +611,7 @@ static inline int mthca_check_fmr(struct mthca_fmr *fmr, u64 *page_list, if (list_len > fmr->attr.max_pages) return -EINVAL; - page_mask = (1 << fmr->attr.page_size) - 1; + page_mask = (1 << fmr->attr.page_shift) - 1; /* We are getting page lists, so va must be page aligned. */ if (iova & page_mask) @@ -659,7 +659,7 @@ int mthca_tavor_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, } mpt_entry.lkey = cpu_to_be32(key); - mpt_entry.length = cpu_to_be64(list_len * (1ull << fmr->attr.page_size)); + mpt_entry.length = cpu_to_be64(list_len * (1ull << fmr->attr.page_shift)); mpt_entry.start = cpu_to_be64(iova); __raw_writel((__force u32) mpt_entry.lkey, &fmr->mem.tavor.mpt->key); @@ -700,7 +700,7 @@ int mthca_arbel_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, fmr->mem.arbel.mpt->key = cpu_to_be32(key); fmr->mem.arbel.mpt->lkey = cpu_to_be32(key); - fmr->mem.arbel.mpt->length = cpu_to_be64(list_len * (1ull << fmr->attr.page_size)); + fmr->mem.arbel.mpt->length = cpu_to_be64(list_len * (1ull << fmr->attr.page_shift)); fmr->mem.arbel.mpt->start = cpu_to_be64(iova); wmb(); diff --git a/include/rdma/ib_fmr_pool.h b/include/rdma/ib_fmr_pool.h index 86b7e93f198b..4ace54cd0cce 100644 --- a/include/rdma/ib_fmr_pool.h +++ b/include/rdma/ib_fmr_pool.h @@ -43,6 +43,7 @@ struct ib_fmr_pool; /** * struct ib_fmr_pool_param - Parameters for creating FMR pool * @max_pages_per_fmr:Maximum number of pages per map request. + * @page_shift: Log2 of sizeof "pages" mapped by this fmr * @access:Access flags for FMRs in pool. * @pool_size:Number of FMRs to allocate for pool. * @dirty_watermark:Flush is triggered when @dirty_watermark dirty @@ -55,6 +56,7 @@ struct ib_fmr_pool; */ struct ib_fmr_pool_param { int max_pages_per_fmr; + int page_shift; enum ib_access_flags access; int pool_size; int dirty_watermark; diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 1d31c8cd5ce0..61a4390ae9d8 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -651,7 +651,7 @@ struct ib_mw_bind { struct ib_fmr_attr { int max_pages; int max_maps; - u8 page_size; + u8 page_shift; }; struct ib_ucontext { -- cgit v1.2.3-59-g8ed1b From 5f0b67e0d5c2807337b8fee4aa71b05f4f641534 Mon Sep 17 00:00:00 2001 From: Ralph Campbell Date: Fri, 3 Feb 2006 14:30:24 -0800 Subject: IB/mad: Remove redundant check from smi_check_local_dr_smp() smi_check_local_dr_smp() is called only from two places in core/mad.c It returns 0 or 1. In smi_check_local_dr_smp(), it checks for a directed route SMP but this function is only called when the SMP is a directed route so this is a NOP. Signed-off-by: Hal Rosenstock Signed-off-by: Roland Dreier --- drivers/infiniband/core/agent.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c index 34b724afd28d..1a8f94588364 100644 --- a/drivers/infiniband/core/agent.c +++ b/drivers/infiniband/core/agent.c @@ -84,9 +84,6 @@ int smi_check_local_dr_smp(struct ib_smp *smp, { struct ib_agent_port_private *port_priv; - if (smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) - return 1; - port_priv = ib_get_agent_port(device, port_num); if (!port_priv) { printk(KERN_DEBUG SPFX "smi_check_local_dr_smp %s port %d " -- cgit v1.2.3-59-g8ed1b From 5e9f71a16c56af7e2ff8b7ea251e0fd90b5de560 Mon Sep 17 00:00:00 2001 From: Ralph Campbell Date: Fri, 3 Feb 2006 14:32:01 -0800 Subject: IB/mad: Simplify SMI by eliminating smi_check_local_dr_smp() The call to ib_get_agent_port() shouldn't be possible to fail when smi_check_local_dr_smp() is called from ib_mad_recv_done_handler(). When it is called from handle_outgoing_dr_smp(), the device and port_num come from mad_agent_priv so I assume the call to ib_get_agent_port() shouldn't fail either. In either case, smi_check_local_smp() only uses the mad_agent pointer to check that mad_agent->device->process_mad is not NULL. The device pointer would have to be the same as the one passed to smi_check_local_dr_smp() since that pointer is used later instead of the one checked in smi_check_local_smp(). Signed-off-by: Hal Rosenstock Signed-off-by: Roland Dreier --- drivers/infiniband/core/agent.c | 16 ---------------- drivers/infiniband/core/mad.c | 8 +++----- drivers/infiniband/core/smi.h | 9 +++------ 3 files changed, 6 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c index 1a8f94588364..ecd1a3057c61 100644 --- a/drivers/infiniband/core/agent.c +++ b/drivers/infiniband/core/agent.c @@ -78,22 +78,6 @@ ib_get_agent_port(struct ib_device *device, int port_num) return entry; } -int smi_check_local_dr_smp(struct ib_smp *smp, - struct ib_device *device, - int port_num) -{ - struct ib_agent_port_private *port_priv; - - port_priv = ib_get_agent_port(device, port_num); - if (!port_priv) { - printk(KERN_DEBUG SPFX "smi_check_local_dr_smp %s port %d " - "not open\n", device->name, port_num); - return 1; - } - - return smi_check_local_smp(port_priv->agent[0], smp); -} - int agent_send_response(struct ib_mad *mad, struct ib_grh *grh, struct ib_wc *wc, struct ib_device *device, int port_num, int qpn) diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index c82f47a66e48..445ad0dda213 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -679,8 +679,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, goto out; } /* Check to post send on QP or process locally */ - ret = smi_check_local_dr_smp(smp, device, port_num); - if (!ret || !device->process_mad) + ret = smi_check_local_smp(smp, device); + if (!ret) goto out; local = kmalloc(sizeof *local, GFP_ATOMIC); @@ -1661,9 +1661,7 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv, port_priv->device->node_type, port_priv->port_num)) goto out; - if (!smi_check_local_dr_smp(&recv->mad.smp, - port_priv->device, - port_priv->port_num)) + if (!smi_check_local_smp(&recv->mad.smp, port_priv->device)) goto out; } diff --git a/drivers/infiniband/core/smi.h b/drivers/infiniband/core/smi.h index 2b3c40198f81..3011bfd86dc5 100644 --- a/drivers/infiniband/core/smi.h +++ b/drivers/infiniband/core/smi.h @@ -49,19 +49,16 @@ extern int smi_check_forward_dr_smp(struct ib_smp *smp); extern int smi_handle_dr_smp_send(struct ib_smp *smp, u8 node_type, int port_num); -extern int smi_check_local_dr_smp(struct ib_smp *smp, - struct ib_device *device, - int port_num); /* * Return 1 if the SMP should be handled by the local SMA/SM via process_mad */ -static inline int smi_check_local_smp(struct ib_mad_agent *mad_agent, - struct ib_smp *smp) +static inline int smi_check_local_smp(struct ib_smp *smp, + struct ib_device *device) { /* C14-9:3 -- We're at the end of the DR segment of path */ /* C14-9:4 -- Hop Pointer = Hop Count + 1 -> give to SMA/SM */ - return ((mad_agent->device->process_mad && + return ((device->process_mad && !ib_get_smp_direction(smp) && (smp->hop_ptr == smp->hop_cnt + 1))); } -- cgit v1.2.3-59-g8ed1b From 3fa1fa3e809dc009a080ca9f052cee2e17836c63 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 3 Feb 2006 14:53:28 -0800 Subject: IB/mthca: Generate SQ drained events when requested Add low-level driver support to ib_mthca so that consumers can request a "send queue drained" event be generated when a transiton to the SQD state completes. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cmd.c | 3 ++- drivers/infiniband/hw/mthca/mthca_qp.c | 14 +++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 7150fd143bff..9e7baa8b57a9 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -1638,7 +1638,8 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, } } else - err = mthca_cmd(dev, mailbox->dma, (!!is_ee << 24) | num, + err = mthca_cmd(dev, mailbox->dma, + optmask | (!!is_ee << 24) | num, op_mod, op[trans], CMD_TIME_CLASS_C, status); if (my_mailbox) diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index bdba39a8d9f9..97f5303d2c02 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -415,6 +415,12 @@ static const struct { }, [IB_QPS_SQD] = { .trans = MTHCA_TRANS_RTS2SQD, + .opt_param = { + [UD] = IB_QP_EN_SQD_ASYNC_NOTIFY, + [UC] = IB_QP_EN_SQD_ASYNC_NOTIFY, + [RC] = IB_QP_EN_SQD_ASYNC_NOTIFY, + [MLX] = IB_QP_EN_SQD_ASYNC_NOTIFY + } }, }, [IB_QPS_SQD] = { @@ -577,6 +583,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) struct mthca_qp_param *qp_param; struct mthca_qp_context *qp_context; u32 req_param, opt_param; + u32 sqd_event = 0; u8 status; int err; @@ -841,8 +848,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) qp_context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->srqn); + if (cur_state == IB_QPS_RTS && new_state == IB_QPS_SQD && + attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY && + attr->en_sqd_async_notify) + sqd_event = 1 << 31; + err = mthca_MODIFY_QP(dev, state_table[cur_state][new_state].trans, - qp->qpn, 0, mailbox, 0, &status); + qp->qpn, 0, mailbox, sqd_event, &status); if (status) { mthca_warn(dev, "modify QP %d returned status %02x.\n", state_table[cur_state][new_state].trans, status); -- cgit v1.2.3-59-g8ed1b From 8a51866f08103ba04894ce0f65eef567ddc3ed40 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 13 Feb 2006 12:48:12 -0800 Subject: IB: Add ib_modify_qp_is_ok() library function The in-kernel mthca driver contains a table of which attributes are valid for each queue pair state transition. It turns out that both other IB drivers -- ipath and ehca -- which are being prepared for merging have copied this table, errors and all. To forestall this code duplication, move this table and the code to check parameters against it into a midlayer library function, ib_modify_qp_is_ok(). Signed-off-by: Roland Dreier --- drivers/infiniband/core/verbs.c | 252 ++++++++++++++++++++++++++++++++++++++++ include/rdma/ib_verbs.h | 18 +++ 2 files changed, 270 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 8e0ba16bcbdd..ca07a2be87d3 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -245,6 +245,258 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd, } EXPORT_SYMBOL(ib_create_qp); +static const struct { + int valid; + enum ib_qp_attr_mask req_param[IB_QPT_RAW_ETY + 1]; + enum ib_qp_attr_mask opt_param[IB_QPT_RAW_ETY + 1]; +} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { + [IB_QPS_RESET] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_INIT] = { + .valid = 1, + .req_param = { + [IB_QPT_UD] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_ACCESS_FLAGS), + [IB_QPT_RC] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_ACCESS_FLAGS), + [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + } + }, + }, + [IB_QPS_INIT] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_INIT] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_ACCESS_FLAGS), + [IB_QPT_RC] = (IB_QP_PKEY_INDEX | + IB_QP_PORT | + IB_QP_ACCESS_FLAGS), + [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + } + }, + [IB_QPS_RTR] = { + .valid = 1, + .req_param = { + [IB_QPT_UC] = (IB_QP_AV | + IB_QP_PATH_MTU | + IB_QP_DEST_QPN | + IB_QP_RQ_PSN), + [IB_QPT_RC] = (IB_QP_AV | + IB_QP_PATH_MTU | + IB_QP_DEST_QPN | + IB_QP_RQ_PSN | + IB_QP_MAX_DEST_RD_ATOMIC | + IB_QP_MIN_RNR_TIMER), + }, + .opt_param = { + [IB_QPT_UD] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX), + [IB_QPT_RC] = (IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX), + [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + } + } + }, + [IB_QPS_RTR] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_RTS] = { + .valid = 1, + .req_param = { + [IB_QPT_UD] = IB_QP_SQ_PSN, + [IB_QPT_UC] = IB_QP_SQ_PSN, + [IB_QPT_RC] = (IB_QP_TIMEOUT | + IB_QP_RETRY_CNT | + IB_QP_RNR_RETRY | + IB_QP_SQ_PSN | + IB_QP_MAX_QP_RD_ATOMIC), + [IB_QPT_SMI] = IB_QP_SQ_PSN, + [IB_QPT_GSI] = IB_QP_SQ_PSN, + }, + .opt_param = { + [IB_QPT_UD] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PATH_MIG_STATE), + [IB_QPT_RC] = (IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_MIN_RNR_TIMER | + IB_QP_PATH_MIG_STATE), + [IB_QPT_SMI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + } + } + }, + [IB_QPS_RTS] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_RTS] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_ACCESS_FLAGS | + IB_QP_ALT_PATH | + IB_QP_PATH_MIG_STATE), + [IB_QPT_RC] = (IB_QP_ACCESS_FLAGS | + IB_QP_ALT_PATH | + IB_QP_PATH_MIG_STATE | + IB_QP_MIN_RNR_TIMER), + [IB_QPT_SMI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + } + }, + [IB_QPS_SQD] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY, + [IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY, + [IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY, + [IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY, + [IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY + } + }, + }, + [IB_QPS_SQD] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_RTS] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PATH_MIG_STATE), + [IB_QPT_RC] = (IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_MIN_RNR_TIMER | + IB_QP_PATH_MIG_STATE), + [IB_QPT_SMI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + } + }, + [IB_QPS_SQD] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_AV | + IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX | + IB_QP_PATH_MIG_STATE), + [IB_QPT_RC] = (IB_QP_PORT | + IB_QP_AV | + IB_QP_TIMEOUT | + IB_QP_RETRY_CNT | + IB_QP_RNR_RETRY | + IB_QP_MAX_QP_RD_ATOMIC | + IB_QP_MAX_DEST_RD_ATOMIC | + IB_QP_CUR_STATE | + IB_QP_ALT_PATH | + IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX | + IB_QP_MIN_RNR_TIMER | + IB_QP_PATH_MIG_STATE), + [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | + IB_QP_QKEY), + } + } + }, + [IB_QPS_SQE] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 }, + [IB_QPS_RTS] = { + .valid = 1, + .opt_param = { + [IB_QPT_UD] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_UC] = (IB_QP_CUR_STATE | + IB_QP_ACCESS_FLAGS), + [IB_QPT_SMI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + [IB_QPT_GSI] = (IB_QP_CUR_STATE | + IB_QP_QKEY), + } + } + }, + [IB_QPS_ERR] = { + [IB_QPS_RESET] = { .valid = 1 }, + [IB_QPS_ERR] = { .valid = 1 } + } +}; + +int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, + enum ib_qp_type type, enum ib_qp_attr_mask mask) +{ + enum ib_qp_attr_mask req_param, opt_param; + + if (cur_state < 0 || cur_state > IB_QPS_ERR || + next_state < 0 || next_state > IB_QPS_ERR) + return 0; + + if (mask & IB_QP_CUR_STATE && + cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS && + cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE) + return 0; + + if (!qp_state_table[cur_state][next_state].valid) + return 0; + + req_param = qp_state_table[cur_state][next_state].req_param[type]; + opt_param = qp_state_table[cur_state][next_state].opt_param[type]; + + if ((mask & req_param) != req_param) + return 0; + + if (mask & ~(req_param | opt_param | IB_QP_STATE)) + return 0; + + return 1; +} +EXPORT_SYMBOL(ib_modify_qp_is_ok); + int ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, int qp_attr_mask) diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 61a4390ae9d8..010287c844e7 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -990,6 +990,24 @@ static inline int ib_copy_to_udata(struct ib_udata *udata, void *src, size_t len return copy_to_user(udata->outbuf, src, len) ? -EFAULT : 0; } +/** + * ib_modify_qp_is_ok - Check that the supplied attribute mask + * contains all required attributes and no attributes not allowed for + * the given QP state transition. + * @cur_state: Current QP state + * @next_state: Next QP state + * @type: QP type + * @mask: Mask of supplied QP attributes + * + * This function is a helper function that a low-level driver's + * modify_qp method can use to validate the consumer's input. It + * checks that cur_state and next_state are valid QP states, that a + * transition from cur_state to next_state is allowed by the IB spec, + * and that the attribute mask supplied is allowed for the transition. + */ +int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, + enum ib_qp_type type, enum ib_qp_attr_mask mask); + int ib_register_event_handler (struct ib_event_handler *event_handler); int ib_unregister_event_handler(struct ib_event_handler *event_handler); void ib_dispatch_event(struct ib_event *event); -- cgit v1.2.3-59-g8ed1b From d844183d9c7b103da1d7a1c753a1c171e9ce26b3 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 13 Feb 2006 16:30:18 -0800 Subject: IB/mthca: Convert to use ib_modify_qp_is_ok() Use ib_modify_qp_is_ok() in mthca, and delete the big table of attributes for queue pair state transitions. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cmd.c | 98 +++++++----- drivers/infiniband/hw/mthca/mthca_cmd.h | 5 +- drivers/infiniband/hw/mthca/mthca_qp.c | 263 ++------------------------------ 3 files changed, 76 insertions(+), 290 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 9e7baa8b57a9..acd00831ef08 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -1566,31 +1566,56 @@ int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status) CMD_TIME_CLASS_B, status); } -int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, - int is_ee, struct mthca_mailbox *mailbox, u32 optmask, +int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur, + enum ib_qp_state next, u32 num, int is_ee, + struct mthca_mailbox *mailbox, u32 optmask, u8 *status) { - static const u16 op[] = { - [MTHCA_TRANS_RST2INIT] = CMD_RST2INIT_QPEE, - [MTHCA_TRANS_INIT2INIT] = CMD_INIT2INIT_QPEE, - [MTHCA_TRANS_INIT2RTR] = CMD_INIT2RTR_QPEE, - [MTHCA_TRANS_RTR2RTS] = CMD_RTR2RTS_QPEE, - [MTHCA_TRANS_RTS2RTS] = CMD_RTS2RTS_QPEE, - [MTHCA_TRANS_SQERR2RTS] = CMD_SQERR2RTS_QPEE, - [MTHCA_TRANS_ANY2ERR] = CMD_2ERR_QPEE, - [MTHCA_TRANS_RTS2SQD] = CMD_RTS2SQD_QPEE, - [MTHCA_TRANS_SQD2SQD] = CMD_SQD2SQD_QPEE, - [MTHCA_TRANS_SQD2RTS] = CMD_SQD2RTS_QPEE, - [MTHCA_TRANS_ANY2RST] = CMD_ERR2RST_QPEE + static const u16 op[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { + [IB_QPS_RESET] = { + [IB_QPS_RESET] = CMD_ERR2RST_QPEE, + [IB_QPS_ERR] = CMD_2ERR_QPEE, + [IB_QPS_INIT] = CMD_RST2INIT_QPEE, + }, + [IB_QPS_INIT] = { + [IB_QPS_RESET] = CMD_ERR2RST_QPEE, + [IB_QPS_ERR] = CMD_2ERR_QPEE, + [IB_QPS_INIT] = CMD_INIT2INIT_QPEE, + [IB_QPS_RTR] = CMD_INIT2RTR_QPEE, + }, + [IB_QPS_RTR] = { + [IB_QPS_RESET] = CMD_ERR2RST_QPEE, + [IB_QPS_ERR] = CMD_2ERR_QPEE, + [IB_QPS_RTS] = CMD_RTR2RTS_QPEE, + }, + [IB_QPS_RTS] = { + [IB_QPS_RESET] = CMD_ERR2RST_QPEE, + [IB_QPS_ERR] = CMD_2ERR_QPEE, + [IB_QPS_RTS] = CMD_RTS2RTS_QPEE, + [IB_QPS_SQD] = CMD_RTS2SQD_QPEE, + }, + [IB_QPS_SQD] = { + [IB_QPS_RESET] = CMD_ERR2RST_QPEE, + [IB_QPS_ERR] = CMD_2ERR_QPEE, + [IB_QPS_RTS] = CMD_SQD2RTS_QPEE, + [IB_QPS_SQD] = CMD_SQD2SQD_QPEE, + }, + [IB_QPS_SQE] = { + [IB_QPS_RESET] = CMD_ERR2RST_QPEE, + [IB_QPS_ERR] = CMD_2ERR_QPEE, + [IB_QPS_RTS] = CMD_SQERR2RTS_QPEE, + }, + [IB_QPS_ERR] = { + [IB_QPS_RESET] = CMD_ERR2RST_QPEE, + [IB_QPS_ERR] = CMD_2ERR_QPEE, + } }; + u8 op_mod = 0; int my_mailbox = 0; int err; - if (trans < 0 || trans >= ARRAY_SIZE(op)) - return -EINVAL; - - if (trans == MTHCA_TRANS_ANY2RST) { + if (op[cur][next] == CMD_ERR2RST_QPEE) { op_mod = 3; /* don't write outbox, any->reset */ /* For debugging */ @@ -1602,34 +1627,35 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, } else mailbox = NULL; } - } else { - if (0) { + + err = mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, + (!!is_ee << 24) | num, op_mod, + op[cur][next], CMD_TIME_CLASS_C, status); + + if (0 && mailbox) { int i; mthca_dbg(dev, "Dumping QP context:\n"); - printk(" opt param mask: %08x\n", be32_to_cpup(mailbox->buf)); + printk(" %08x\n", be32_to_cpup(mailbox->buf)); for (i = 0; i < 0x100 / 4; ++i) { if (i % 8 == 0) - printk(" [%02x] ", i * 4); + printk("[%02x] ", i * 4); printk(" %08x", be32_to_cpu(((__be32 *) mailbox->buf)[i + 2])); if ((i + 1) % 8 == 0) printk("\n"); } } - } - if (trans == MTHCA_TRANS_ANY2RST) { - err = mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, - (!!is_ee << 24) | num, op_mod, - op[trans], CMD_TIME_CLASS_C, status); - - if (0 && mailbox) { + if (my_mailbox) + mthca_free_mailbox(dev, mailbox); + } else { + if (0) { int i; mthca_dbg(dev, "Dumping QP context:\n"); - printk(" %08x\n", be32_to_cpup(mailbox->buf)); + printk(" opt param mask: %08x\n", be32_to_cpup(mailbox->buf)); for (i = 0; i < 0x100 / 4; ++i) { if (i % 8 == 0) - printk("[%02x] ", i * 4); + printk(" [%02x] ", i * 4); printk(" %08x", be32_to_cpu(((__be32 *) mailbox->buf)[i + 2])); if ((i + 1) % 8 == 0) @@ -1637,13 +1663,9 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, } } - } else - err = mthca_cmd(dev, mailbox->dma, - optmask | (!!is_ee << 24) | num, - op_mod, op[trans], CMD_TIME_CLASS_C, status); - - if (my_mailbox) - mthca_free_mailbox(dev, mailbox); + err = mthca_cmd(dev, mailbox->dma, optmask | (!!is_ee << 24) | num, + op_mod, op[cur][next], CMD_TIME_CLASS_C, status); + } return err; } diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h index a8da84b0a0f1..5156701ae52c 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.h +++ b/drivers/infiniband/hw/mthca/mthca_cmd.h @@ -306,8 +306,9 @@ int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, int srq_num, u8 *status); int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status); -int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num, - int is_ee, struct mthca_mailbox *mailbox, u32 optmask, +int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur, + enum ib_qp_state next, u32 num, int is_ee, + struct mthca_mailbox *mailbox, u32 optmask, u8 *status); int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee, struct mthca_mailbox *mailbox, u8 *status); diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 97f5303d2c02..c2d3300dace9 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -286,213 +286,6 @@ static int to_mthca_st(int transport) } } -static const struct { - int trans; - u32 req_param[NUM_TRANS]; - u32 opt_param[NUM_TRANS]; -} state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { - [IB_QPS_RESET] = { - [IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST }, - [IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR }, - [IB_QPS_INIT] = { - .trans = MTHCA_TRANS_RST2INIT, - .req_param = { - [UD] = (IB_QP_PKEY_INDEX | - IB_QP_PORT | - IB_QP_QKEY), - [UC] = (IB_QP_PKEY_INDEX | - IB_QP_PORT | - IB_QP_ACCESS_FLAGS), - [RC] = (IB_QP_PKEY_INDEX | - IB_QP_PORT | - IB_QP_ACCESS_FLAGS), - [MLX] = (IB_QP_PKEY_INDEX | - IB_QP_QKEY), - }, - /* bug-for-bug compatibility with VAPI: */ - .opt_param = { - [MLX] = IB_QP_PORT - } - }, - }, - [IB_QPS_INIT] = { - [IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST }, - [IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR }, - [IB_QPS_INIT] = { - .trans = MTHCA_TRANS_INIT2INIT, - .opt_param = { - [UD] = (IB_QP_PKEY_INDEX | - IB_QP_PORT | - IB_QP_QKEY), - [UC] = (IB_QP_PKEY_INDEX | - IB_QP_PORT | - IB_QP_ACCESS_FLAGS), - [RC] = (IB_QP_PKEY_INDEX | - IB_QP_PORT | - IB_QP_ACCESS_FLAGS), - [MLX] = (IB_QP_PKEY_INDEX | - IB_QP_QKEY), - } - }, - [IB_QPS_RTR] = { - .trans = MTHCA_TRANS_INIT2RTR, - .req_param = { - [UC] = (IB_QP_AV | - IB_QP_PATH_MTU | - IB_QP_DEST_QPN | - IB_QP_RQ_PSN), - [RC] = (IB_QP_AV | - IB_QP_PATH_MTU | - IB_QP_DEST_QPN | - IB_QP_RQ_PSN | - IB_QP_MAX_DEST_RD_ATOMIC | - IB_QP_MIN_RNR_TIMER), - }, - .opt_param = { - [UD] = (IB_QP_PKEY_INDEX | - IB_QP_QKEY), - [UC] = (IB_QP_ALT_PATH | - IB_QP_ACCESS_FLAGS | - IB_QP_PKEY_INDEX), - [RC] = (IB_QP_ALT_PATH | - IB_QP_ACCESS_FLAGS | - IB_QP_PKEY_INDEX), - [MLX] = (IB_QP_PKEY_INDEX | - IB_QP_QKEY), - } - } - }, - [IB_QPS_RTR] = { - [IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST }, - [IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR }, - [IB_QPS_RTS] = { - .trans = MTHCA_TRANS_RTR2RTS, - .req_param = { - [UD] = IB_QP_SQ_PSN, - [UC] = IB_QP_SQ_PSN, - [RC] = (IB_QP_TIMEOUT | - IB_QP_RETRY_CNT | - IB_QP_RNR_RETRY | - IB_QP_SQ_PSN | - IB_QP_MAX_QP_RD_ATOMIC), - [MLX] = IB_QP_SQ_PSN, - }, - .opt_param = { - [UD] = (IB_QP_CUR_STATE | - IB_QP_QKEY), - [UC] = (IB_QP_CUR_STATE | - IB_QP_ALT_PATH | - IB_QP_ACCESS_FLAGS | - IB_QP_PATH_MIG_STATE), - [RC] = (IB_QP_CUR_STATE | - IB_QP_ALT_PATH | - IB_QP_ACCESS_FLAGS | - IB_QP_MIN_RNR_TIMER | - IB_QP_PATH_MIG_STATE), - [MLX] = (IB_QP_CUR_STATE | - IB_QP_QKEY), - } - } - }, - [IB_QPS_RTS] = { - [IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST }, - [IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR }, - [IB_QPS_RTS] = { - .trans = MTHCA_TRANS_RTS2RTS, - .opt_param = { - [UD] = (IB_QP_CUR_STATE | - IB_QP_QKEY), - [UC] = (IB_QP_ACCESS_FLAGS | - IB_QP_ALT_PATH | - IB_QP_PATH_MIG_STATE), - [RC] = (IB_QP_ACCESS_FLAGS | - IB_QP_ALT_PATH | - IB_QP_PATH_MIG_STATE | - IB_QP_MIN_RNR_TIMER), - [MLX] = (IB_QP_CUR_STATE | - IB_QP_QKEY), - } - }, - [IB_QPS_SQD] = { - .trans = MTHCA_TRANS_RTS2SQD, - .opt_param = { - [UD] = IB_QP_EN_SQD_ASYNC_NOTIFY, - [UC] = IB_QP_EN_SQD_ASYNC_NOTIFY, - [RC] = IB_QP_EN_SQD_ASYNC_NOTIFY, - [MLX] = IB_QP_EN_SQD_ASYNC_NOTIFY - } - }, - }, - [IB_QPS_SQD] = { - [IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST }, - [IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR }, - [IB_QPS_RTS] = { - .trans = MTHCA_TRANS_SQD2RTS, - .opt_param = { - [UD] = (IB_QP_CUR_STATE | - IB_QP_QKEY), - [UC] = (IB_QP_CUR_STATE | - IB_QP_ALT_PATH | - IB_QP_ACCESS_FLAGS | - IB_QP_PATH_MIG_STATE), - [RC] = (IB_QP_CUR_STATE | - IB_QP_ALT_PATH | - IB_QP_ACCESS_FLAGS | - IB_QP_MIN_RNR_TIMER | - IB_QP_PATH_MIG_STATE), - [MLX] = (IB_QP_CUR_STATE | - IB_QP_QKEY), - } - }, - [IB_QPS_SQD] = { - .trans = MTHCA_TRANS_SQD2SQD, - .opt_param = { - [UD] = (IB_QP_PKEY_INDEX | - IB_QP_QKEY), - [UC] = (IB_QP_AV | - IB_QP_CUR_STATE | - IB_QP_ALT_PATH | - IB_QP_ACCESS_FLAGS | - IB_QP_PKEY_INDEX | - IB_QP_PATH_MIG_STATE), - [RC] = (IB_QP_AV | - IB_QP_TIMEOUT | - IB_QP_RETRY_CNT | - IB_QP_RNR_RETRY | - IB_QP_MAX_QP_RD_ATOMIC | - IB_QP_MAX_DEST_RD_ATOMIC | - IB_QP_CUR_STATE | - IB_QP_ALT_PATH | - IB_QP_ACCESS_FLAGS | - IB_QP_PKEY_INDEX | - IB_QP_MIN_RNR_TIMER | - IB_QP_PATH_MIG_STATE), - [MLX] = (IB_QP_PKEY_INDEX | - IB_QP_QKEY), - } - } - }, - [IB_QPS_SQE] = { - [IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST }, - [IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR }, - [IB_QPS_RTS] = { - .trans = MTHCA_TRANS_SQERR2RTS, - .opt_param = { - [UD] = (IB_QP_CUR_STATE | - IB_QP_QKEY), - [UC] = (IB_QP_CUR_STATE | - IB_QP_ACCESS_FLAGS), - [MLX] = (IB_QP_CUR_STATE | - IB_QP_QKEY), - } - } - }, - [IB_QPS_ERR] = { - [IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST }, - [IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR } - } -}; - static void store_attrs(struct mthca_sqp *sqp, struct ib_qp_attr *attr, int attr_mask) { @@ -582,19 +375,12 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) struct mthca_mailbox *mailbox; struct mthca_qp_param *qp_param; struct mthca_qp_context *qp_context; - u32 req_param, opt_param; u32 sqd_event = 0; u8 status; int err; if (attr_mask & IB_QP_CUR_STATE) { - if (attr->cur_qp_state != IB_QPS_RTR && - attr->cur_qp_state != IB_QPS_RTS && - attr->cur_qp_state != IB_QPS_SQD && - attr->cur_qp_state != IB_QPS_SQE) - return -EINVAL; - else - cur_state = attr->cur_qp_state; + cur_state = attr->cur_qp_state; } else { spin_lock_irq(&qp->sq.lock); spin_lock(&qp->rq.lock); @@ -603,37 +389,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) spin_unlock_irq(&qp->sq.lock); } - if (attr_mask & IB_QP_STATE) { - if (attr->qp_state < 0 || attr->qp_state > IB_QPS_ERR) - return -EINVAL; - new_state = attr->qp_state; - } else - new_state = cur_state; - - if (state_table[cur_state][new_state].trans == MTHCA_TRANS_INVALID) { - mthca_dbg(dev, "Illegal QP transition " - "%d->%d\n", cur_state, new_state); - return -EINVAL; - } - - req_param = state_table[cur_state][new_state].req_param[qp->transport]; - opt_param = state_table[cur_state][new_state].opt_param[qp->transport]; - - if ((req_param & attr_mask) != req_param) { - mthca_dbg(dev, "QP transition " - "%d->%d missing req attr 0x%08x\n", - cur_state, new_state, - req_param & ~attr_mask); - return -EINVAL; - } + new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; - if (attr_mask & ~(req_param | opt_param | IB_QP_STATE)) { - mthca_dbg(dev, "QP transition (transport %d) " - "%d->%d has extra attr 0x%08x\n", - qp->transport, - cur_state, new_state, - attr_mask & ~(req_param | opt_param | - IB_QP_STATE)); + if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) { + mthca_dbg(dev, "Bad QP transition (transport %d) " + "%d->%d with attr 0x%08x\n", + qp->transport, cur_state, new_state, + attr_mask); return -EINVAL; } @@ -853,11 +615,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) attr->en_sqd_async_notify) sqd_event = 1 << 31; - err = mthca_MODIFY_QP(dev, state_table[cur_state][new_state].trans, - qp->qpn, 0, mailbox, sqd_event, &status); + err = mthca_MODIFY_QP(dev, cur_state, new_state, qp->qpn, 0, + mailbox, sqd_event, &status); if (status) { - mthca_warn(dev, "modify QP %d returned status %02x.\n", - state_table[cur_state][new_state].trans, status); + mthca_warn(dev, "modify QP %d->%d returned status %02x.\n", + cur_state, new_state, status); err = -EINVAL; } @@ -1405,7 +1167,8 @@ void mthca_free_qp(struct mthca_dev *dev, wait_event(qp->wait, !atomic_read(&qp->refcount)); if (qp->state != IB_QPS_RESET) - mthca_MODIFY_QP(dev, MTHCA_TRANS_ANY2RST, qp->qpn, 0, NULL, 0, &status); + mthca_MODIFY_QP(dev, qp->state, IB_QPS_RESET, qp->qpn, 0, + NULL, 0, &status); /* * If this is a userspace QP, the buffers, MR, CQs and so on -- cgit v1.2.3-59-g8ed1b From a74cd4af0bfa9578594acbb711a958104c93b772 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 13 Feb 2006 16:30:49 -0800 Subject: IB: Whitespace cleanups Remove trailing whitespace and fix indentation that with spaces instead of tabs. Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs_cmd.c | 12 ++++++------ drivers/infiniband/core/uverbs_main.c | 1 - drivers/infiniband/core/verbs.c | 3 +-- include/rdma/ib_user_verbs.h | 4 ++-- 4 files changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index be1cef1b3116..398c125d908c 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1134,8 +1134,8 @@ out: } ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, - const char __user *buf, int in_len, - int out_len) + const char __user *buf, int in_len, + int out_len) { struct ib_uverbs_post_send cmd; struct ib_uverbs_post_send_resp resp; @@ -1363,8 +1363,8 @@ err: } ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, - const char __user *buf, int in_len, - int out_len) + const char __user *buf, int in_len, + int out_len) { struct ib_uverbs_post_recv cmd; struct ib_uverbs_post_recv_resp resp; @@ -1414,8 +1414,8 @@ out: } ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, - const char __user *buf, int in_len, - int out_len) + const char __user *buf, int in_len, + int out_len) { struct ib_uverbs_post_srq_recv cmd; struct ib_uverbs_post_srq_recv_resp resp; diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 099fe6cde68c..335b6938a656 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -462,7 +462,6 @@ void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr) ib_uverbs_async_handler(uobj->uverbs_file, uobj->uobject.user_handle, event->event, &uobj->async_list, &uobj->async_events_reported); - } void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr) diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index ca07a2be87d3..c69334dc8012 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -574,8 +574,7 @@ int ib_destroy_cq(struct ib_cq *cq) } EXPORT_SYMBOL(ib_destroy_cq); -int ib_resize_cq(struct ib_cq *cq, - int cqe) +int ib_resize_cq(struct ib_cq *cq, int cqe) { return cq->device->resize_cq ? cq->device->resize_cq(cq, cqe, NULL) : -ENOSYS; diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index 6ad1207e4235..fb94c08169ce 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -426,7 +426,7 @@ struct ib_uverbs_sge { }; struct ib_uverbs_send_wr { - __u64 wr_id; + __u64 wr_id; __u32 num_sge; __u32 opcode; __u32 send_flags; @@ -500,7 +500,7 @@ struct ib_uverbs_post_srq_recv_resp { struct ib_uverbs_global_route { __u8 dgid[16]; - __u32 flow_label; + __u32 flow_label; __u8 sgid_index; __u8 hop_limit; __u8 traffic_class; -- cgit v1.2.3-59-g8ed1b From 7ccc9a24e01258a31ee2b964215e4ddddd2a02c4 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Mon, 13 Feb 2006 16:31:25 -0800 Subject: IB/uverbs: Support for query QP from userspace Add support to uverbs to handle querying userspace QPs (queue pairs), including adding an ABI for marshalling requests and responses. The kernel midlayer already has the underlying ib_query_qp() function. Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs.h | 1 + drivers/infiniband/core/uverbs_cmd.c | 100 ++++++++++++++++++++++++++++++++++ drivers/infiniband/core/uverbs_main.c | 1 + include/rdma/ib_user_verbs.h | 41 ++++++++++++++ 4 files changed, 143 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 3207239819ce..89c798eb5749 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -183,6 +183,7 @@ IB_UVERBS_DECLARE_CMD(poll_cq); IB_UVERBS_DECLARE_CMD(req_notify_cq); IB_UVERBS_DECLARE_CMD(destroy_cq); IB_UVERBS_DECLARE_CMD(create_qp); +IB_UVERBS_DECLARE_CMD(query_qp); IB_UVERBS_DECLARE_CMD(modify_qp); IB_UVERBS_DECLARE_CMD(destroy_qp); IB_UVERBS_DECLARE_CMD(post_send); diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 398c125d908c..4cbef8c06634 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -996,6 +996,106 @@ err_up: return ret; } +ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file, + const char __user *buf, int in_len, + int out_len) +{ + struct ib_uverbs_query_qp cmd; + struct ib_uverbs_query_qp_resp resp; + struct ib_qp *qp; + struct ib_qp_attr *attr; + struct ib_qp_init_attr *init_attr; + int ret; + + if (copy_from_user(&cmd, buf, sizeof cmd)) + return -EFAULT; + + attr = kmalloc(sizeof *attr, GFP_KERNEL); + init_attr = kmalloc(sizeof *init_attr, GFP_KERNEL); + if (!attr || !init_attr) { + ret = -ENOMEM; + goto out; + } + + mutex_lock(&ib_uverbs_idr_mutex); + + qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); + if (qp && qp->uobject->context == file->ucontext) + ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr); + else + ret = -EINVAL; + + mutex_unlock(&ib_uverbs_idr_mutex); + + if (ret) + goto out; + + memset(&resp, 0, sizeof resp); + + resp.qp_state = attr->qp_state; + resp.cur_qp_state = attr->cur_qp_state; + resp.path_mtu = attr->path_mtu; + resp.path_mig_state = attr->path_mig_state; + resp.qkey = attr->qkey; + resp.rq_psn = attr->rq_psn; + resp.sq_psn = attr->sq_psn; + resp.dest_qp_num = attr->dest_qp_num; + resp.qp_access_flags = attr->qp_access_flags; + resp.pkey_index = attr->pkey_index; + resp.alt_pkey_index = attr->alt_pkey_index; + resp.en_sqd_async_notify = attr->en_sqd_async_notify; + resp.max_rd_atomic = attr->max_rd_atomic; + resp.max_dest_rd_atomic = attr->max_dest_rd_atomic; + resp.min_rnr_timer = attr->min_rnr_timer; + resp.port_num = attr->port_num; + resp.timeout = attr->timeout; + resp.retry_cnt = attr->retry_cnt; + resp.rnr_retry = attr->rnr_retry; + resp.alt_port_num = attr->alt_port_num; + resp.alt_timeout = attr->alt_timeout; + + memcpy(resp.dest.dgid, attr->ah_attr.grh.dgid.raw, 16); + resp.dest.flow_label = attr->ah_attr.grh.flow_label; + resp.dest.sgid_index = attr->ah_attr.grh.sgid_index; + resp.dest.hop_limit = attr->ah_attr.grh.hop_limit; + resp.dest.traffic_class = attr->ah_attr.grh.traffic_class; + resp.dest.dlid = attr->ah_attr.dlid; + resp.dest.sl = attr->ah_attr.sl; + resp.dest.src_path_bits = attr->ah_attr.src_path_bits; + resp.dest.static_rate = attr->ah_attr.static_rate; + resp.dest.is_global = !!(attr->ah_attr.ah_flags & IB_AH_GRH); + resp.dest.port_num = attr->ah_attr.port_num; + + memcpy(resp.alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16); + resp.alt_dest.flow_label = attr->alt_ah_attr.grh.flow_label; + resp.alt_dest.sgid_index = attr->alt_ah_attr.grh.sgid_index; + resp.alt_dest.hop_limit = attr->alt_ah_attr.grh.hop_limit; + resp.alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class; + resp.alt_dest.dlid = attr->alt_ah_attr.dlid; + resp.alt_dest.sl = attr->alt_ah_attr.sl; + resp.alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits; + resp.alt_dest.static_rate = attr->alt_ah_attr.static_rate; + resp.alt_dest.is_global = !!(attr->alt_ah_attr.ah_flags & IB_AH_GRH); + resp.alt_dest.port_num = attr->alt_ah_attr.port_num; + + resp.max_send_wr = init_attr->cap.max_send_wr; + resp.max_recv_wr = init_attr->cap.max_recv_wr; + resp.max_send_sge = init_attr->cap.max_send_sge; + resp.max_recv_sge = init_attr->cap.max_recv_sge; + resp.max_inline_data = init_attr->cap.max_inline_data; + resp.sq_sig_all = !!init_attr->sq_sig_type; + + if (copy_to_user((void __user *) (unsigned long) cmd.response, + &resp, sizeof resp)) + ret = -EFAULT; + +out: + kfree(attr); + kfree(init_attr); + + return ret ? ret : in_len; +} + ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len) diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 335b6938a656..91e4750fa319 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -96,6 +96,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file, [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ] = ib_uverbs_req_notify_cq, [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq, [IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp, + [IB_USER_VERBS_CMD_QUERY_QP] = ib_uverbs_query_qp, [IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp, [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp, [IB_USER_VERBS_CMD_POST_SEND] = ib_uverbs_post_send, diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index fb94c08169ce..58662c34a3de 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -370,6 +370,47 @@ struct ib_uverbs_qp_dest { __u8 port_num; }; +struct ib_uverbs_query_qp { + __u64 response; + __u32 qp_handle; + __u32 attr_mask; + __u64 driver_data[0]; +}; + +struct ib_uverbs_query_qp_resp { + struct ib_uverbs_qp_dest dest; + struct ib_uverbs_qp_dest alt_dest; + __u32 max_send_wr; + __u32 max_recv_wr; + __u32 max_send_sge; + __u32 max_recv_sge; + __u32 max_inline_data; + __u32 qkey; + __u32 rq_psn; + __u32 sq_psn; + __u32 dest_qp_num; + __u32 qp_access_flags; + __u16 pkey_index; + __u16 alt_pkey_index; + __u8 qp_state; + __u8 cur_qp_state; + __u8 path_mtu; + __u8 path_mig_state; + __u8 en_sqd_async_notify; + __u8 max_rd_atomic; + __u8 max_dest_rd_atomic; + __u8 min_rnr_timer; + __u8 port_num; + __u8 timeout; + __u8 retry_cnt; + __u8 rnr_retry; + __u8 alt_port_num; + __u8 alt_timeout; + __u8 sq_sig_all; + __u8 reserved[5]; + __u64 driver_data[0]; +}; + struct ib_uverbs_modify_qp { struct ib_uverbs_qp_dest dest; struct ib_uverbs_qp_dest alt_dest; -- cgit v1.2.3-59-g8ed1b From 8bdb0e8632e0f5061bd18b6934346cb609490135 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Mon, 13 Feb 2006 16:31:57 -0800 Subject: IB/uverbs: Support for query SRQ from userspace Add support to uverbs to handle querying userspace SRQs (shared receive queues), including adding an ABI for marshalling requests and responses. The kernel midlayer already has the underlying ib_query_srq() function. Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs.h | 1 + drivers/infiniband/core/uverbs_cmd.c | 44 +++++++++++++++++++++++++++++++++++ drivers/infiniband/core/uverbs_main.c | 1 + include/rdma/ib_user_verbs.h | 15 ++++++++++++ 4 files changed, 61 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 89c798eb5749..3372d67ff139 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -195,6 +195,7 @@ IB_UVERBS_DECLARE_CMD(attach_mcast); IB_UVERBS_DECLARE_CMD(detach_mcast); IB_UVERBS_DECLARE_CMD(create_srq); IB_UVERBS_DECLARE_CMD(modify_srq); +IB_UVERBS_DECLARE_CMD(query_srq); IB_UVERBS_DECLARE_CMD(destroy_srq); #endif /* UVERBS_H */ diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 4cbef8c06634..38a66fbef36d 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -2,6 +2,7 @@ * Copyright (c) 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. + * Copyright (c) 2006 Mellanox Technologies. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -1923,6 +1924,49 @@ out: return ret ? ret : in_len; } +ssize_t ib_uverbs_query_srq(struct ib_uverbs_file *file, + const char __user *buf, + int in_len, int out_len) +{ + struct ib_uverbs_query_srq cmd; + struct ib_uverbs_query_srq_resp resp; + struct ib_srq_attr attr; + struct ib_srq *srq; + int ret; + + if (out_len < sizeof resp) + return -ENOSPC; + + if (copy_from_user(&cmd, buf, sizeof cmd)) + return -EFAULT; + + mutex_lock(&ib_uverbs_idr_mutex); + + srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); + if (srq && srq->uobject->context == file->ucontext) + ret = ib_query_srq(srq, &attr); + else + ret = -EINVAL; + + mutex_unlock(&ib_uverbs_idr_mutex); + + if (ret) + goto out; + + memset(&resp, 0, sizeof resp); + + resp.max_wr = attr.max_wr; + resp.max_sge = attr.max_sge; + resp.srq_limit = attr.srq_limit; + + if (copy_to_user((void __user *) (unsigned long) cmd.response, + &resp, sizeof resp)) + ret = -EFAULT; + +out: + return ret ? ret : in_len; +} + ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len) diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 91e4750fa319..ff092a0a94da 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -108,6 +108,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file, [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast, [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq, [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq, + [IB_USER_VERBS_CMD_QUERY_SRQ] = ib_uverbs_query_srq, [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq, }; diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index 58662c34a3de..0edd3a6fe8f5 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -2,6 +2,7 @@ * Copyright (c) 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. + * Copyright (c) 2006 Mellanox Technologies. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -613,6 +614,20 @@ struct ib_uverbs_modify_srq { __u64 driver_data[0]; }; +struct ib_uverbs_query_srq { + __u64 response; + __u32 srq_handle; + __u32 reserved; + __u64 driver_data[0]; +}; + +struct ib_uverbs_query_srq_resp { + __u32 max_wr; + __u32 max_sge; + __u32 srq_limit; + __u32 reserved; +}; + struct ib_uverbs_destroy_srq { __u64 response; __u32 srq_handle; -- cgit v1.2.3-59-g8ed1b From 8ebe5077e37a0cb0da527e397460188e6bfdd3ee Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Mon, 13 Feb 2006 16:40:21 -0800 Subject: IB/mthca: Support for query QP and SRQ Implement the query_qp and query_srq methods in mthca. Signed-off-by: Eli Cohen Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cmd.c | 7 ++ drivers/infiniband/hw/mthca/mthca_cmd.h | 2 + drivers/infiniband/hw/mthca/mthca_dev.h | 3 + drivers/infiniband/hw/mthca/mthca_provider.c | 6 +- drivers/infiniband/hw/mthca/mthca_qp.c | 135 +++++++++++++++++++++++++++ drivers/infiniband/hw/mthca/mthca_srq.c | 32 +++++++ 6 files changed, 184 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index acd00831ef08..890c060ff4d1 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -1560,6 +1560,13 @@ int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, CMD_TIME_CLASS_A, status); } +int mthca_QUERY_SRQ(struct mthca_dev *dev, u32 num, + struct mthca_mailbox *mailbox, u8 *status) +{ + return mthca_cmd_box(dev, 0, mailbox->dma, num, 0, + CMD_QUERY_SRQ, CMD_TIME_CLASS_A, status); +} + int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status) { return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ, diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h index 5156701ae52c..e4ec35c40dd3 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.h +++ b/drivers/infiniband/hw/mthca/mthca_cmd.h @@ -305,6 +305,8 @@ int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, int srq_num, u8 *status); int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox, int srq_num, u8 *status); +int mthca_QUERY_SRQ(struct mthca_dev *dev, u32 num, + struct mthca_mailbox *mailbox, u8 *status); int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status); int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur, enum ib_qp_state next, u32 num, int is_ee, diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index d827558c27be..2f4500f85ae0 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -479,6 +479,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq); int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, enum ib_srq_attr_mask attr_mask); +int mthca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr); void mthca_srq_event(struct mthca_dev *dev, u32 srqn, enum ib_event_type event_type); void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr); @@ -489,6 +490,8 @@ int mthca_arbel_post_srq_recv(struct ib_srq *srq, struct ib_recv_wr *wr, void mthca_qp_event(struct mthca_dev *dev, u32 qpn, enum ib_event_type event_type); +int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask, + struct ib_qp_init_attr *qp_init_attr); int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask); int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, struct ib_send_wr **bad_wr); diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 1fa1b55ffffe..084bea592df5 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -1264,12 +1264,14 @@ int mthca_register_device(struct mthca_dev *dev) (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) | (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | (1ull << IB_USER_VERBS_CMD_CREATE_QP) | + (1ull << IB_USER_VERBS_CMD_QUERY_QP) | (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) | (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | + (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ); dev->ib_dev.node_type = IB_NODE_CA; dev->ib_dev.phys_port_cnt = dev->limits.num_ports; @@ -1291,7 +1293,8 @@ int mthca_register_device(struct mthca_dev *dev) if (dev->mthca_flags & MTHCA_FLAG_SRQ) { dev->ib_dev.create_srq = mthca_create_srq; - dev->ib_dev.modify_srq = mthca_modify_srq; + dev->ib_dev.modify_srq = mthca_modify_srq; + dev->ib_dev.query_srq = mthca_query_srq; dev->ib_dev.destroy_srq = mthca_destroy_srq; if (mthca_is_memfree(dev)) @@ -1302,6 +1305,7 @@ int mthca_register_device(struct mthca_dev *dev) dev->ib_dev.create_qp = mthca_create_qp; dev->ib_dev.modify_qp = mthca_modify_qp; + dev->ib_dev.query_qp = mthca_query_qp; dev->ib_dev.destroy_qp = mthca_destroy_qp; dev->ib_dev.create_cq = mthca_create_cq; dev->ib_dev.resize_cq = mthca_resize_cq; diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index c2d3300dace9..e99d735f5f36 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -348,6 +348,141 @@ static __be32 get_hw_access_flags(struct mthca_qp *qp, struct ib_qp_attr *attr, return cpu_to_be32(hw_access_flags); } +static inline enum ib_qp_state to_ib_qp_state(int mthca_state) +{ + switch (mthca_state) { + case MTHCA_QP_STATE_RST: return IB_QPS_RESET; + case MTHCA_QP_STATE_INIT: return IB_QPS_INIT; + case MTHCA_QP_STATE_RTR: return IB_QPS_RTR; + case MTHCA_QP_STATE_RTS: return IB_QPS_RTS; + case MTHCA_QP_STATE_DRAINING: + case MTHCA_QP_STATE_SQD: return IB_QPS_SQD; + case MTHCA_QP_STATE_SQE: return IB_QPS_SQE; + case MTHCA_QP_STATE_ERR: return IB_QPS_ERR; + default: return -1; + } +} + +static inline enum ib_mig_state to_ib_mig_state(int mthca_mig_state) +{ + switch (mthca_mig_state) { + case 0: return IB_MIG_ARMED; + case 1: return IB_MIG_REARM; + case 3: return IB_MIG_MIGRATED; + default: return -1; + } +} + +static int to_ib_qp_access_flags(int mthca_flags) +{ + int ib_flags = 0; + + if (mthca_flags & MTHCA_QP_BIT_RRE) + ib_flags |= IB_ACCESS_REMOTE_READ; + if (mthca_flags & MTHCA_QP_BIT_RWE) + ib_flags |= IB_ACCESS_REMOTE_WRITE; + if (mthca_flags & MTHCA_QP_BIT_RAE) + ib_flags |= IB_ACCESS_REMOTE_ATOMIC; + + return ib_flags; +} + +static void to_ib_ah_attr(struct mthca_dev *dev, struct ib_ah_attr *ib_ah_attr, + struct mthca_qp_path *path) +{ + memset(ib_ah_attr, 0, sizeof *path); + ib_ah_attr->port_num = (be32_to_cpu(path->port_pkey) >> 24) & 0x3; + ib_ah_attr->dlid = be16_to_cpu(path->rlid); + ib_ah_attr->sl = be32_to_cpu(path->sl_tclass_flowlabel) >> 28; + ib_ah_attr->src_path_bits = path->g_mylmc & 0x7f; + ib_ah_attr->static_rate = path->static_rate & 0x7; + ib_ah_attr->ah_flags = (path->g_mylmc & (1 << 7)) ? IB_AH_GRH : 0; + if (ib_ah_attr->ah_flags) { + ib_ah_attr->grh.sgid_index = path->mgid_index & (dev->limits.gid_table_len - 1); + ib_ah_attr->grh.hop_limit = path->hop_limit; + ib_ah_attr->grh.traffic_class = + (be32_to_cpu(path->sl_tclass_flowlabel) >> 20) & 0xff; + ib_ah_attr->grh.flow_label = + be32_to_cpu(path->sl_tclass_flowlabel) & 0xfffff; + memcpy(ib_ah_attr->grh.dgid.raw, + path->rgid, sizeof ib_ah_attr->grh.dgid.raw); + } +} + +int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask, + struct ib_qp_init_attr *qp_init_attr) +{ + struct mthca_dev *dev = to_mdev(ibqp->device); + struct mthca_qp *qp = to_mqp(ibqp); + int err; + struct mthca_mailbox *mailbox; + struct mthca_qp_param *qp_param; + struct mthca_qp_context *context; + int mthca_state; + u8 status; + + mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + err = mthca_QUERY_QP(dev, qp->qpn, 0, mailbox, &status); + if (err) + goto out; + if (status) { + mthca_warn(dev, "QUERY_QP returned status %02x\n", status); + err = -EINVAL; + goto out; + } + + qp_param = mailbox->buf; + context = &qp_param->context; + mthca_state = be32_to_cpu(context->flags) >> 28; + + qp_attr->qp_state = to_ib_qp_state(mthca_state); + qp_attr->cur_qp_state = qp_attr->qp_state; + qp_attr->path_mtu = context->mtu_msgmax >> 5; + qp_attr->path_mig_state = + to_ib_mig_state((be32_to_cpu(context->flags) >> 11) & 0x3); + qp_attr->qkey = be32_to_cpu(context->qkey); + qp_attr->rq_psn = be32_to_cpu(context->rnr_nextrecvpsn) & 0xffffff; + qp_attr->sq_psn = be32_to_cpu(context->next_send_psn) & 0xffffff; + qp_attr->dest_qp_num = be32_to_cpu(context->remote_qpn) & 0xffffff; + qp_attr->qp_access_flags = + to_ib_qp_access_flags(be32_to_cpu(context->params2)); + qp_attr->cap.max_send_wr = qp->sq.max; + qp_attr->cap.max_recv_wr = qp->rq.max; + qp_attr->cap.max_send_sge = qp->sq.max_gs; + qp_attr->cap.max_recv_sge = qp->rq.max_gs; + qp_attr->cap.max_inline_data = qp->max_inline_data; + + to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path); + to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path); + + qp_attr->pkey_index = be32_to_cpu(context->pri_path.port_pkey) & 0x7f; + qp_attr->alt_pkey_index = be32_to_cpu(context->alt_path.port_pkey) & 0x7f; + + /* qp_attr->en_sqd_async_notify is only applicable in modify qp */ + qp_attr->sq_draining = mthca_state == MTHCA_QP_STATE_DRAINING; + + qp_attr->max_rd_atomic = 1 << ((be32_to_cpu(context->params1) >> 21) & 0x7); + + qp_attr->max_dest_rd_atomic = + 1 << ((be32_to_cpu(context->params2) >> 21) & 0x7); + qp_attr->min_rnr_timer = + (be32_to_cpu(context->rnr_nextrecvpsn) >> 24) & 0x1f; + qp_attr->port_num = qp_attr->ah_attr.port_num; + qp_attr->timeout = context->pri_path.ackto >> 3; + qp_attr->retry_cnt = (be32_to_cpu(context->params1) >> 16) & 0x7; + qp_attr->rnr_retry = context->pri_path.rnr_retry >> 5; + qp_attr->alt_port_num = qp_attr->alt_ah_attr.port_num; + qp_attr->alt_timeout = context->alt_path.ackto >> 3; + qp_init_attr->cap = qp_attr->cap; + +out: + mthca_free_mailbox(dev, mailbox); + return err; +} + static void mthca_path_set(struct ib_ah_attr *ah, struct mthca_qp_path *path) { path->g_mylmc = ah->src_path_bits & 0x7f; diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index f1a1da147d0b..deb526ce013d 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -360,6 +360,38 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, return 0; } +int mthca_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr) +{ + struct mthca_dev *dev = to_mdev(ibsrq->device); + struct mthca_srq *srq = to_msrq(ibsrq); + struct mthca_mailbox *mailbox; + struct mthca_arbel_srq_context *arbel_ctx; + u8 status; + int err; + + mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + err = mthca_QUERY_SRQ(dev, srq->srqn, mailbox, &status); + if (err) + goto out; + + if (mthca_is_memfree(dev)) { + arbel_ctx = mailbox->buf; + srq_attr->srq_limit = arbel_ctx->limit_watermark; + } else + srq_attr->srq_limit = 0; + + srq_attr->max_wr = srq->max; + srq_attr->max_sge = srq->max_gs; + +out: + mthca_free_mailbox(dev, mailbox); + + return err; +} + void mthca_srq_event(struct mthca_dev *dev, u32 srqn, enum ib_event_type event_type) { -- cgit v1.2.3-59-g8ed1b From 00df1b2c8b1f07e02a74e2d10b176f29395ce7d2 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 13 Feb 2006 17:21:09 -0800 Subject: IB/mthca: Bump driver version and release date Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_dev.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 2f4500f85ae0..7f0dc221fa47 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -53,8 +53,8 @@ #define DRV_NAME "ib_mthca" #define PFX DRV_NAME ": " -#define DRV_VERSION "0.07" -#define DRV_RELDATE "February 13, 2006" +#define DRV_VERSION "0.08" +#define DRV_RELDATE "February 14, 2006" enum { MTHCA_FLAG_DDR_HIDDEN = 1 << 1, -- cgit v1.2.3-59-g8ed1b From 44af79f9524c29d6850591cc972f2667a27234d4 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 20 Feb 2006 21:50:39 -0800 Subject: IPoIB: clarify to_ipoib_neigh() Cosmetic change: make alignment explicit in to_ipoib_neigh. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 2f85a9a831b1..638eff745b2f 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -217,10 +217,16 @@ struct ipoib_neigh { struct list_head list; }; +/* + * We stash a pointer to our private neighbour information after our + * hardware address in neigh->ha. The ALIGN() expression here makes + * sure that this pointer is stored aligned so that an unaligned + * load is not needed to dereference it. + */ static inline struct ipoib_neigh **to_ipoib_neigh(struct neighbour *neigh) { - return (struct ipoib_neigh **) (neigh->ha + 24 - - (offsetof(struct neighbour, ha) & 4)); + return (void*) neigh + ALIGN(offsetof(struct neighbour, ha) + + INFINIBAND_ALEN, sizeof(void *)); } extern struct workqueue_struct *ipoib_workqueue; -- cgit v1.2.3-59-g8ed1b From abb6e9ba17eb133ab385d0f9017fa8afa809d52a Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Thu, 23 Feb 2006 12:13:51 -0800 Subject: IB/mthca: Return actual capacity from create_srq Have mthca's create_srq method return the actual capacity of the SRQ that gets created. Also update comments in to clarify that this is what is expected from ib_create_srq(). Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_srq.c | 3 +++ include/rdma/ib_verbs.h | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index deb526ce013d..209d2bae2256 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -271,6 +271,9 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, srq->first_free = 0; srq->last_free = srq->max - 1; + attr->max_wr = srq->max; + attr->max_sge = srq->max_gs; + return 0; err_out_free_srq: diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 010287c844e7..c1ad6273ac6c 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -1100,7 +1100,9 @@ int ib_destroy_ah(struct ib_ah *ah); * ib_create_srq - Creates a SRQ associated with the specified protection * domain. * @pd: The protection domain associated with the SRQ. - * @srq_init_attr: A list of initial attributes required to create the SRQ. + * @srq_init_attr: A list of initial attributes required to create the + * SRQ. If SRQ creation succeeds, then the attributes are updated to + * the actual capabilities of the created SRQ. * * srq_attr->max_wr and srq_attr->max_sge are read the determine the * requested size of the SRQ, and set to the actual values allocated @@ -1159,7 +1161,9 @@ static inline int ib_post_srq_recv(struct ib_srq *srq, * ib_create_qp - Creates a QP associated with the specified protection * domain. * @pd: The protection domain associated with the QP. - * @qp_init_attr: A list of initial attributes required to create the QP. + * @qp_init_attr: A list of initial attributes required to create the + * QP. If QP creation succeeds, then the attributes are updated to + * the actual capabilities of the created QP. */ struct ib_qp *ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *qp_init_attr); -- cgit v1.2.3-59-g8ed1b From ea88fd16d6e85f4bc71b6053180b64f04be1ff14 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Thu, 23 Feb 2006 12:36:18 -0800 Subject: IB/uverbs: Return actual capacity from create SRQ operation Pass actual capacity of created SRQ back to userspace, so that userspace can report accurate capacities. This requires an ABI bump, to change struct ib_uverbs_create_srq_resp. Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs_cmd.c | 2 ++ include/rdma/ib_user_verbs.h | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 38a66fbef36d..b157e5ff7dad 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1864,6 +1864,8 @@ retry: goto err_destroy; resp.srq_handle = uobj->uobject.id; + resp.max_wr = attr.attr.max_wr; + resp.max_sge = attr.attr.max_sge; if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index 3bf4402f466a..338ed4333063 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -44,7 +44,7 @@ * Increment this value if any changes that break userspace ABI * compatibility are made. */ -#define IB_USER_VERBS_ABI_VERSION 5 +#define IB_USER_VERBS_ABI_VERSION 6 enum { IB_USER_VERBS_CMD_GET_CONTEXT, @@ -605,6 +605,9 @@ struct ib_uverbs_create_srq { struct ib_uverbs_create_srq_resp { __u32 srq_handle; + __u32 max_wr; + __u32 max_sge; + __u32 reserved; }; struct ib_uverbs_modify_srq { -- cgit v1.2.3-59-g8ed1b From 14abdffcc0a0ca9c5bb3274648d073e09a6fd2ba Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Sun, 26 Feb 2006 14:36:06 -0800 Subject: IB/mthca: Write FW commands through doorbell page This patch is checks whether the HCA supports posting FW commands through a doorbell page (user access region 0, or "UAR0"). If this is supported, the driver maps UAR0 and uses it for FW commands. This can be controlled by the value of a writable module parameter fw_cmd_doorbell. When the parameter is 0, the commands are posted through HCR using the old method; otherwise if HCA is capable commands go through UAR0. This use of UAR0 to post commands eliminates the need for polling the "go" bit prior to posting a new command. Since reading from a PCI device is much more expensive then issuing a posted write, it is expected that issuing FW commands this way will provide better CPU utilization. Signed-off-by: Eli Cohen Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cmd.c | 146 +++++++++++++++++++++++++++----- drivers/infiniband/hw/mthca/mthca_dev.h | 13 ++- 2 files changed, 136 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 890c060ff4d1..d1e7ecb5f233 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -182,25 +182,58 @@ struct mthca_cmd_context { u8 status; }; +static int fw_cmd_doorbell = 1; +module_param(fw_cmd_doorbell, int, 0644); +MODULE_PARM_DESC(fw_cmd_doorbell, "post FW commands through doorbell page if nonzero " + "(and supported by FW)"); + static inline int go_bit(struct mthca_dev *dev) { return readl(dev->hcr + HCR_STATUS_OFFSET) & swab32(1 << HCR_GO_BIT); } -static int mthca_cmd_post(struct mthca_dev *dev, - u64 in_param, - u64 out_param, - u32 in_modifier, - u8 op_modifier, - u16 op, - u16 token, - int event) +static void mthca_cmd_post_dbell(struct mthca_dev *dev, + u64 in_param, + u64 out_param, + u32 in_modifier, + u8 op_modifier, + u16 op, + u16 token) { - int err = 0; + void __iomem *ptr = dev->cmd.dbell_map; + u16 *offs = dev->cmd.dbell_offsets; - mutex_lock(&dev->cmd.hcr_mutex); + __raw_writel((__force u32) cpu_to_be32(in_param >> 32), ptr + offs[0]); + wmb(); + __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), ptr + offs[1]); + wmb(); + __raw_writel((__force u32) cpu_to_be32(in_modifier), ptr + offs[2]); + wmb(); + __raw_writel((__force u32) cpu_to_be32(out_param >> 32), ptr + offs[3]); + wmb(); + __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), ptr + offs[4]); + wmb(); + __raw_writel((__force u32) cpu_to_be32(token << 16), ptr + offs[5]); + wmb(); + __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) | + (1 << HCA_E_BIT) | + (op_modifier << HCR_OPMOD_SHIFT) | + op), ptr + offs[6]); + wmb(); + __raw_writel((__force u32) 0, ptr + offs[7]); + wmb(); +} +static int mthca_cmd_post_hcr(struct mthca_dev *dev, + u64 in_param, + u64 out_param, + u32 in_modifier, + u8 op_modifier, + u16 op, + u16 token, + int event) +{ if (event) { unsigned long end = jiffies + GO_BIT_TIMEOUT; @@ -210,10 +243,8 @@ static int mthca_cmd_post(struct mthca_dev *dev, } } - if (go_bit(dev)) { - err = -EAGAIN; - goto out; - } + if (go_bit(dev)) + return -EAGAIN; /* * We use writel (instead of something like memcpy_toio) @@ -236,7 +267,29 @@ static int mthca_cmd_post(struct mthca_dev *dev, (op_modifier << HCR_OPMOD_SHIFT) | op), dev->hcr + 6 * 4); -out: + return 0; +} + +static int mthca_cmd_post(struct mthca_dev *dev, + u64 in_param, + u64 out_param, + u32 in_modifier, + u8 op_modifier, + u16 op, + u16 token, + int event) +{ + int err = 0; + + mutex_lock(&dev->cmd.hcr_mutex); + + if (event && dev->cmd.flags & MTHCA_CMD_POST_DOORBELLS && fw_cmd_doorbell) + mthca_cmd_post_dbell(dev, in_param, out_param, in_modifier, + op_modifier, op, token); + else + err = mthca_cmd_post_hcr(dev, in_param, out_param, in_modifier, + op_modifier, op, token, event); + mutex_unlock(&dev->cmd.hcr_mutex); return err; } @@ -386,7 +439,7 @@ static int mthca_cmd_box(struct mthca_dev *dev, unsigned long timeout, u8 *status) { - if (dev->cmd.use_events) + if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS) return mthca_cmd_wait(dev, in_param, &out_param, 0, in_modifier, op_modifier, op, timeout, status); @@ -423,7 +476,7 @@ static int mthca_cmd_imm(struct mthca_dev *dev, unsigned long timeout, u8 *status) { - if (dev->cmd.use_events) + if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS) return mthca_cmd_wait(dev, in_param, out_param, 1, in_modifier, op_modifier, op, timeout, status); @@ -437,7 +490,7 @@ int mthca_cmd_init(struct mthca_dev *dev) { mutex_init(&dev->cmd.hcr_mutex); sema_init(&dev->cmd.poll_sem, 1); - dev->cmd.use_events = 0; + dev->cmd.flags = 0; dev->hcr = ioremap(pci_resource_start(dev->pdev, 0) + MTHCA_HCR_BASE, MTHCA_HCR_SIZE); @@ -461,6 +514,8 @@ void mthca_cmd_cleanup(struct mthca_dev *dev) { pci_pool_destroy(dev->cmd.pool); iounmap(dev->hcr); + if (dev->cmd.flags & MTHCA_CMD_POST_DOORBELLS) + iounmap(dev->cmd.dbell_map); } /* @@ -498,7 +553,8 @@ int mthca_cmd_use_events(struct mthca_dev *dev) ; /* nothing */ --dev->cmd.token_mask; - dev->cmd.use_events = 1; + dev->cmd.flags |= MTHCA_CMD_USE_EVENTS; + down(&dev->cmd.poll_sem); return 0; @@ -511,7 +567,7 @@ void mthca_cmd_use_polling(struct mthca_dev *dev) { int i; - dev->cmd.use_events = 0; + dev->cmd.flags &= ~MTHCA_CMD_USE_EVENTS; for (i = 0; i < dev->cmd.max_cmds; ++i) down(&dev->cmd.event_sem); @@ -661,12 +717,41 @@ int mthca_RUN_FW(struct mthca_dev *dev, u8 *status) return mthca_cmd(dev, 0, 0, 0, CMD_RUN_FW, CMD_TIME_CLASS_A, status); } +static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base) +{ + unsigned long addr; + u16 max_off = 0; + int i; + + for (i = 0; i < 8; ++i) + max_off = max(max_off, dev->cmd.dbell_offsets[i]); + + if ((base & PAGE_MASK) != ((base + max_off) & PAGE_MASK)) { + mthca_warn(dev, "Firmware doorbell region at 0x%016llx, " + "length 0x%x crosses a page boundary\n", + (unsigned long long) base, max_off); + return; + } + + addr = pci_resource_start(dev->pdev, 2) + + ((pci_resource_len(dev->pdev, 2) - 1) & base); + dev->cmd.dbell_map = ioremap(addr, max_off + sizeof(u32)); + if (!dev->cmd.dbell_map) + return; + + dev->cmd.flags |= MTHCA_CMD_POST_DOORBELLS; + mthca_dbg(dev, "Mapped doorbell page for posting FW commands\n"); +} + int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) { struct mthca_mailbox *mailbox; u32 *outbox; + u64 base; + u32 tmp; int err = 0; u8 lg; + int i; #define QUERY_FW_OUT_SIZE 0x100 #define QUERY_FW_VER_OFFSET 0x00 @@ -674,6 +759,10 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) #define QUERY_FW_ERR_START_OFFSET 0x30 #define QUERY_FW_ERR_SIZE_OFFSET 0x38 +#define QUERY_FW_CMD_DB_EN_OFFSET 0x10 +#define QUERY_FW_CMD_DB_OFFSET 0x50 +#define QUERY_FW_CMD_DB_BASE 0x60 + #define QUERY_FW_START_OFFSET 0x20 #define QUERY_FW_END_OFFSET 0x28 @@ -702,16 +791,29 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) ((dev->fw_ver & 0xffff0000ull) >> 16) | ((dev->fw_ver & 0x0000ffffull) << 16); + mthca_dbg(dev, "FW version %012llx, max commands %d\n", + (unsigned long long) dev->fw_ver, dev->cmd.max_cmds); + MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); dev->cmd.max_cmds = 1 << lg; MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET); MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET); - mthca_dbg(dev, "FW version %012llx, max commands %d\n", - (unsigned long long) dev->fw_ver, dev->cmd.max_cmds); mthca_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x\n", (unsigned long long) dev->catas_err.addr, dev->catas_err.size); + MTHCA_GET(tmp, outbox, QUERY_FW_CMD_DB_EN_OFFSET); + if (tmp & 0x1) { + mthca_dbg(dev, "FW supports commands through doorbells\n"); + + MTHCA_GET(base, outbox, QUERY_FW_CMD_DB_BASE); + for (i = 0; i < MTHCA_CMD_NUM_DBELL_DWORDS; ++i) + MTHCA_GET(dev->cmd.dbell_offsets[i], outbox, + QUERY_FW_CMD_DB_OFFSET + (i << 1)); + + mthca_setup_cmd_doorbells(dev, base); + } + if (mthca_is_memfree(dev)) { MTHCA_GET(dev->fw.arbel.fw_pages, outbox, QUERY_FW_SIZE_OFFSET); MTHCA_GET(dev->fw.arbel.clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET); diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 7f0dc221fa47..b2aea80a683f 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -110,9 +110,17 @@ enum { MTHCA_OPCODE_INVALID = 0xff }; +enum { + MTHCA_CMD_USE_EVENTS = 1 << 0, + MTHCA_CMD_POST_DOORBELLS = 1 << 1 +}; + +enum { + MTHCA_CMD_NUM_DBELL_DWORDS = 8 +}; + struct mthca_cmd { struct pci_pool *pool; - int use_events; struct mutex hcr_mutex; struct semaphore poll_sem; struct semaphore event_sem; @@ -121,6 +129,9 @@ struct mthca_cmd { int free_head; struct mthca_cmd_context *context; u16 token_mask; + u32 flags; + void __iomem *dbell_map; + u16 dbell_offsets[MTHCA_CMD_NUM_DBELL_DWORDS]; }; struct mthca_limits { -- cgit v1.2.3-59-g8ed1b From 1d89b1ae6c203bc68a3f424be144abcdf62773c9 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Sun, 26 Feb 2006 16:05:59 -0800 Subject: IB/mthca: Implement query_ah method Implement query_ah (except for AVs which are in HCA memory). This is needed to implement RMPP duplicate session detection on sending side (extraction of DGID/DLID and GRH flag from address handle). Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_av.c | 31 ++++++++++++++++++++++++++++ drivers/infiniband/hw/mthca/mthca_dev.h | 1 + drivers/infiniband/hw/mthca/mthca_provider.c | 1 + 3 files changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index 198f1267e984..f023d3936518 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c @@ -193,6 +193,37 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, return 0; } +int mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr) +{ + struct mthca_ah *ah = to_mah(ibah); + struct mthca_dev *dev = to_mdev(ibah->device); + + /* Only implement for MAD and memfree ah for now. */ + if (ah->type == MTHCA_AH_ON_HCA) + return -ENOSYS; + + memset(attr, 0, sizeof *attr); + attr->dlid = be16_to_cpu(ah->av->dlid); + attr->sl = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; + attr->static_rate = ah->av->msg_sr & 0x7; + attr->src_path_bits = ah->av->g_slid & 0x7F; + attr->port_num = be32_to_cpu(ah->av->port_pd) >> 24; + attr->ah_flags = mthca_ah_grh_present(ah) ? IB_AH_GRH : 0; + + if (attr->ah_flags) { + attr->grh.traffic_class = + be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20; + attr->grh.flow_label = + be32_to_cpu(ah->av->sl_tclass_flowlabel) & 0xfffff; + attr->grh.hop_limit = ah->av->hop_limit; + attr->grh.sgid_index = ah->av->gid_index & + (dev->limits.gid_table_len - 1); + memcpy(attr->grh.dgid.raw, ah->av->dgid, 16); + } + + return 0; +} + int __devinit mthca_init_av_table(struct mthca_dev *dev) { int err; diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index b2aea80a683f..ea48c897c7ce 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -539,6 +539,7 @@ int mthca_create_ah(struct mthca_dev *dev, int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah); int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, struct ib_ud_header *header); +int mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr); int mthca_ah_grh_present(struct mthca_ah *ah); int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 084bea592df5..2c250bc11c33 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -1289,6 +1289,7 @@ int mthca_register_device(struct mthca_dev *dev) dev->ib_dev.alloc_pd = mthca_alloc_pd; dev->ib_dev.dealloc_pd = mthca_dealloc_pd; dev->ib_dev.create_ah = mthca_ah_create; + dev->ib_dev.query_ah = mthca_ah_query; dev->ib_dev.destroy_ah = mthca_ah_destroy; if (dev->mthca_flags & MTHCA_FLAG_SRQ) { -- cgit v1.2.3-59-g8ed1b From 7343b231f22cec11f069bcdbb0c9a417df2750d3 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Mon, 27 Feb 2006 20:47:43 -0800 Subject: IPoIB: Close race in setting mcast->ah ipoib_mcast_send() tests mcast->ah twice. If this value is changed between these two points, we leak an skb. However, ipoib_mcast_join_finish() sets mcast->ah with no locking, so it could race against ipoib_mcast_send(). As a solution, take priv->lock around assignment to mcast->ah thus making sure ipoib_mcast_send() (which also takes priv->lock) is not in flight. Signed-off-by: Eli Cohen Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index a2408d7ec598..e5dc2a034530 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -213,6 +213,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, { struct net_device *dev = mcast->dev; struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_ah *ah; int ret; mcast->mcmember = *mcmember; @@ -269,8 +270,8 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, av.static_rate, priv->local_rate, ib_sa_rate_enum_to_int(mcast->mcmember.rate)); - mcast->ah = ipoib_create_ah(dev, priv->pd, &av); - if (!mcast->ah) { + ah = ipoib_create_ah(dev, priv->pd, &av); + if (!ah) { ipoib_warn(priv, "ib_address_create failed\n"); } else { ipoib_dbg_mcast(priv, "MGID " IPOIB_GID_FMT @@ -280,6 +281,10 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, be16_to_cpu(mcast->mcmember.mlid), mcast->mcmember.sl); } + + spin_lock_irq(&priv->lock); + mcast->ah = ah; + spin_unlock_irq(&priv->lock); } /* actually send any queued packets */ -- cgit v1.2.3-59-g8ed1b From 7667abd1528782003d8b83c54756523ec547af6e Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Mon, 27 Feb 2006 21:02:00 -0800 Subject: IB/mthca: Add support for send work request fence flag Add support for IB_SEND_FENCE flag in post_send methods. Signed-off-by: Dotan Barak Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_qp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index e99d735f5f36..c24260845bfd 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -1609,7 +1609,9 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, mthca_opcode[wr->opcode]); wmb(); ((struct mthca_next_seg *) prev_wqe)->ee_nds = - cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size); + cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size | + ((wr->send_flags & IB_SEND_FENCE) ? + MTHCA_NEXT_FENCE : 0)); if (!size0) { size0 = size; @@ -1971,7 +1973,9 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, mthca_opcode[wr->opcode]); wmb(); ((struct mthca_next_seg *) prev_wqe)->ee_nds = - cpu_to_be32(MTHCA_NEXT_DBD | size); + cpu_to_be32(MTHCA_NEXT_DBD | size | + ((wr->send_flags & IB_SEND_FENCE) ? + MTHCA_NEXT_FENCE : 0)); if (!size0) { size0 = size; -- cgit v1.2.3-59-g8ed1b From 67e7377661db4e341ed5e9a0358d11a55e532aa8 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Wed, 1 Mar 2006 14:28:12 -0800 Subject: IB/mthca: Check alternate P_Key index when setting alternate path Check that the alternate P_Key index is in range when setting the alternate path for a QP. Also make a cosmetic touch up to the debug message printed when the main P_Key index is out of range. Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_qp.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index c24260845bfd..f673c461e30b 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -536,8 +536,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) if ((attr_mask & IB_QP_PKEY_INDEX) && attr->pkey_index >= dev->limits.pkey_table_len) { - mthca_dbg(dev, "PKey index (%u) too large. max is %d\n", - attr->pkey_index,dev->limits.pkey_table_len-1); + mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n", + attr->pkey_index, dev->limits.pkey_table_len-1); return -EINVAL; } @@ -652,6 +652,12 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) } if (attr_mask & IB_QP_ALT_PATH) { + if (attr->alt_pkey_index >= dev->limits.pkey_table_len) { + mthca_dbg(dev, "Alternate P_Key index (%u) too large. max is %d\n", + attr->alt_pkey_index, dev->limits.pkey_table_len-1); + return -EINVAL; + } + if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) { mthca_dbg(dev, "Alternate port number (%u) is invalid\n", attr->alt_port_num); -- cgit v1.2.3-59-g8ed1b From 8d3ef29d6be1e750512e0a9dbea6225290b81d0a Mon Sep 17 00:00:00 2001 From: Ishai Rabinovitz Date: Wed, 1 Mar 2006 22:33:11 -0800 Subject: IB/mthca: Use an enum for HCA page size Use a named enum for the HCA's internal page size, rather than having magic values of 4096 and shifts by 12 all over the code. Also, fix one minor bug in EQ handling: only one HCA page is mapped to the HCA during initialization, but a full kernel page is unmapped during cleanup. This might cause problems when PAGE_SIZE != 4096. Signed-off-by: Ishai Rabinovitz Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cmd.c | 26 ++++++++++++++------------ drivers/infiniband/hw/mthca/mthca_eq.c | 2 +- drivers/infiniband/hw/mthca/mthca_memfree.c | 29 ++++++++++++++++------------- drivers/infiniband/hw/mthca/mthca_memfree.h | 10 ++++++---- 4 files changed, 37 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index d1e7ecb5f233..948a2861cae3 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -652,8 +652,9 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, * address or size and use that as our log2 size. */ lg = ffs(mthca_icm_addr(&iter) | mthca_icm_size(&iter)) - 1; - if (lg < 12) { - mthca_warn(dev, "Got FW area not aligned to 4K (%llx/%lx).\n", + if (lg < MTHCA_ICM_PAGE_SHIFT) { + mthca_warn(dev, "Got FW area not aligned to %d (%llx/%lx).\n", + MTHCA_ICM_PAGE_SIZE, (unsigned long long) mthca_icm_addr(&iter), mthca_icm_size(&iter)); err = -EINVAL; @@ -665,8 +666,9 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, virt += 1 << lg; } - pages[nent * 2 + 1] = cpu_to_be64((mthca_icm_addr(&iter) + - (i << lg)) | (lg - 12)); + pages[nent * 2 + 1] = + cpu_to_be64((mthca_icm_addr(&iter) + (i << lg)) | + (lg - MTHCA_ICM_PAGE_SHIFT)); ts += 1 << (lg - 10); ++tc; @@ -822,12 +824,12 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) mthca_dbg(dev, "FW size %d KB\n", dev->fw.arbel.fw_pages << 2); /* - * Arbel page size is always 4 KB; round up number of - * system pages needed. + * Round up number of system pages needed in case + * MTHCA_ICM_PAGE_SIZE < PAGE_SIZE. */ dev->fw.arbel.fw_pages = - ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE >> 12) >> - (PAGE_SHIFT - 12); + ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE / MTHCA_ICM_PAGE_SIZE) >> + (PAGE_SHIFT - MTHCA_ICM_PAGE_SHIFT); mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n", (unsigned long long) dev->fw.arbel.clr_int_base, @@ -1540,11 +1542,11 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages, return ret; /* - * Arbel page size is always 4 KB; round up number of system - * pages needed. + * Round up number of system pages needed in case + * MTHCA_ICM_PAGE_SIZE < PAGE_SIZE. */ - *aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12); - *aux_pages = ALIGN(*aux_pages, PAGE_SIZE >> 12) >> (PAGE_SHIFT - 12); + *aux_pages = ALIGN(*aux_pages, PAGE_SIZE / MTHCA_ICM_PAGE_SIZE) >> + (PAGE_SHIFT - MTHCA_ICM_PAGE_SHIFT); return 0; } diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index cf43a5388397..a44b12dd7952 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -825,7 +825,7 @@ void __devexit mthca_unmap_eq_icm(struct mthca_dev *dev) { u8 status; - mthca_UNMAP_ICM(dev, dev->eq_table.icm_virt, PAGE_SIZE / 4096, &status); + mthca_UNMAP_ICM(dev, dev->eq_table.icm_virt, 1, &status); pci_unmap_page(dev->pdev, dev->eq_table.icm_dma, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); __free_page(dev->eq_table.icm_page); diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index d709cb162a72..15cc2f6eb475 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -202,7 +202,8 @@ void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int o if (--table->icm[i]->refcount == 0) { mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE, - MTHCA_TABLE_CHUNK_SIZE >> 12, &status); + MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE, + &status); mthca_free_icm(dev, table->icm[i]); table->icm[i] = NULL; } @@ -336,7 +337,8 @@ err: for (i = 0; i < num_icm; ++i) if (table->icm[i]) { mthca_UNMAP_ICM(dev, virt + i * MTHCA_TABLE_CHUNK_SIZE, - MTHCA_TABLE_CHUNK_SIZE >> 12, &status); + MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE, + &status); mthca_free_icm(dev, table->icm[i]); } @@ -353,7 +355,8 @@ void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table) for (i = 0; i < table->num_icm; ++i) if (table->icm[i]) { mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE, - MTHCA_TABLE_CHUNK_SIZE >> 12, &status); + MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE, + &status); mthca_free_icm(dev, table->icm[i]); } @@ -364,7 +367,7 @@ static u64 mthca_uarc_virt(struct mthca_dev *dev, struct mthca_uar *uar, int pag { return dev->uar_table.uarc_base + uar->index * dev->uar_table.uarc_size + - page * 4096; + page * MTHCA_ICM_PAGE_SIZE; } int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, @@ -401,7 +404,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, if (ret < 0) goto out; - db_tab->page[i].mem.length = 4096; + db_tab->page[i].mem.length = MTHCA_ICM_PAGE_SIZE; db_tab->page[i].mem.offset = uaddr & ~PAGE_MASK; ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); @@ -455,7 +458,7 @@ struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev) if (!mthca_is_memfree(dev)) return NULL; - npages = dev->uar_table.uarc_size / 4096; + npages = dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE; db_tab = kmalloc(sizeof *db_tab + npages * sizeof *db_tab->page, GFP_KERNEL); if (!db_tab) return ERR_PTR(-ENOMEM); @@ -478,7 +481,7 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar, if (!mthca_is_memfree(dev)) return; - for (i = 0; i < dev->uar_table.uarc_size / 4096; ++i) { + for (i = 0; i < dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE; ++i) { if (db_tab->page[i].uvirt) { mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1, &status); pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); @@ -551,20 +554,20 @@ int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type, page = dev->db_tab->page + end; alloc: - page->db_rec = dma_alloc_coherent(&dev->pdev->dev, 4096, + page->db_rec = dma_alloc_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE, &page->mapping, GFP_KERNEL); if (!page->db_rec) { ret = -ENOMEM; goto out; } - memset(page->db_rec, 0, 4096); + memset(page->db_rec, 0, MTHCA_ICM_PAGE_SIZE); ret = mthca_MAP_ICM_page(dev, page->mapping, mthca_uarc_virt(dev, &dev->driver_uar, i), &status); if (!ret && status) ret = -EINVAL; if (ret) { - dma_free_coherent(&dev->pdev->dev, 4096, + dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE, page->db_rec, page->mapping); goto out; } @@ -612,7 +615,7 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index) i >= dev->db_tab->max_group1 - 1) { mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status); - dma_free_coherent(&dev->pdev->dev, 4096, + dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE, page->db_rec, page->mapping); page->db_rec = NULL; @@ -640,7 +643,7 @@ int mthca_init_db_tab(struct mthca_dev *dev) mutex_init(&dev->db_tab->mutex); - dev->db_tab->npages = dev->uar_table.uarc_size / 4096; + dev->db_tab->npages = dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE; dev->db_tab->max_group1 = 0; dev->db_tab->min_group2 = dev->db_tab->npages - 1; @@ -681,7 +684,7 @@ void mthca_cleanup_db_tab(struct mthca_dev *dev) mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status); - dma_free_coherent(&dev->pdev->dev, 4096, + dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE, dev->db_tab->page[i].db_rec, dev->db_tab->page[i].mapping); } diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h index 36f1141a08aa..6d42947e1dc4 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.h +++ b/drivers/infiniband/hw/mthca/mthca_memfree.h @@ -45,6 +45,12 @@ ((256 - sizeof (struct list_head) - 2 * sizeof (int)) / \ (sizeof (struct scatterlist))) +enum { + MTHCA_ICM_PAGE_SHIFT = 12, + MTHCA_ICM_PAGE_SIZE = 1 << MTHCA_ICM_PAGE_SHIFT, + MTHCA_DB_REC_PER_PAGE = MTHCA_ICM_PAGE_SIZE / 8 +}; + struct mthca_icm_chunk { struct list_head list; int npages; @@ -131,10 +137,6 @@ static inline unsigned long mthca_icm_size(struct mthca_icm_iter *iter) return sg_dma_len(&iter->chunk->mem[iter->page_idx]); } -enum { - MTHCA_DB_REC_PER_PAGE = 4096 / 8 -}; - struct mthca_db_page { DECLARE_BITMAP(used, MTHCA_DB_REC_PER_PAGE); __be64 *db_rec; -- cgit v1.2.3-59-g8ed1b From 54d07e2a1ead2f093ce054cda2e0f5ec163c650c Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 2 Mar 2006 11:05:19 -0800 Subject: IPoIB: Clean up if posting receives fails If posting receives in ipoib_ib_dev_open() fails, call ipoib_ib_dev_stop() to move the device's QP back to the RESET state so that we can try again later. Signed-off-by: Eli Cohen Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 86bcdd72a107..5a5367d10875 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -416,6 +416,7 @@ int ipoib_ib_dev_open(struct net_device *dev) ret = ipoib_ib_post_receives(dev); if (ret) { ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret); + ipoib_ib_dev_stop(dev); return -1; } -- cgit v1.2.3-59-g8ed1b From 9acf6a8570dcfc9f55724b8b71099fc8768e8c26 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 2 Mar 2006 11:07:47 -0800 Subject: IPoIB: Fix multicast race between canceling and completing ipoib_mcast_stop_thread currently tests mcast->query and if it is NULL, does not perform wait_for_completion on the mcast and frees the mcast object directly. However, since both operations are done without locking, it is possible that ipoib_mcast_join_complete is in progress on this mcast object and has set mcast->query to NULL already. Solve this by: - taking priv->lock before we change mcast->query in ipoib_mcast_join_complete, and keeping it until we no longer need the mcast object - taking priv->lock around mcast->query test in ipoib_mcast_stop_thread Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index e5dc2a034530..fde442a1996d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -437,9 +437,11 @@ static void ipoib_mcast_join_complete(int status, if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; + mutex_lock(&mcast_mutex); + + spin_lock_irq(&priv->lock); mcast->query = NULL; - mutex_lock(&mcast_mutex); if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { if (status == -ETIMEDOUT) queue_work(ipoib_workqueue, &priv->mcast_task); @@ -448,6 +450,7 @@ static void ipoib_mcast_join_complete(int status, mcast->backoff * HZ); } else complete(&mcast->done); + spin_unlock_irq(&priv->lock); mutex_unlock(&mcast_mutex); return; @@ -635,21 +638,27 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush) if (flush) flush_workqueue(ipoib_workqueue); + spin_lock_irq(&priv->lock); if (priv->broadcast && priv->broadcast->query) { ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query); priv->broadcast->query = NULL; + spin_unlock_irq(&priv->lock); ipoib_dbg_mcast(priv, "waiting for bcast\n"); wait_for_completion(&priv->broadcast->done); - } + } else + spin_unlock_irq(&priv->lock); list_for_each_entry(mcast, &priv->multicast_list, list) { + spin_lock_irq(&priv->lock); if (mcast->query) { ib_sa_cancel_query(mcast->query_id, mcast->query); mcast->query = NULL; + spin_unlock_irq(&priv->lock); ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n", IPOIB_GID_ARG(mcast->mcmember.mgid)); wait_for_completion(&mcast->done); - } + } else + spin_unlock_irq(&priv->lock); } return 0; -- cgit v1.2.3-59-g8ed1b From 4546d31d84beafe74c56651173ac4fe197c7de8b Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Thu, 2 Mar 2006 11:22:28 -0800 Subject: IB: Fix modify QP checking of "current QP state" attribute According to the IB spec version 1.2, section 11.2.4.2, the current table has a couple of mistakes where it allows the current QP state (IB_QP_CUR_STATE) attribute. For the transitions: RTS -> RTS: IB_QP_CUR_STATE should be allowed for all transports SQD -> SQD: IB_QP_CUR_STATE should never be allowed Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/core/verbs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index c69334dc8012..cae0845f472a 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -366,10 +366,12 @@ static const struct { .opt_param = { [IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY), - [IB_QPT_UC] = (IB_QP_ACCESS_FLAGS | + [IB_QPT_UC] = (IB_QP_CUR_STATE | + IB_QP_ACCESS_FLAGS | IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE), - [IB_QPT_RC] = (IB_QP_ACCESS_FLAGS | + [IB_QPT_RC] = (IB_QP_CUR_STATE | + IB_QP_ACCESS_FLAGS | IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE | IB_QP_MIN_RNR_TIMER), @@ -419,7 +421,6 @@ static const struct { [IB_QPT_UD] = (IB_QP_PKEY_INDEX | IB_QP_QKEY), [IB_QPT_UC] = (IB_QP_AV | - IB_QP_CUR_STATE | IB_QP_ALT_PATH | IB_QP_ACCESS_FLAGS | IB_QP_PKEY_INDEX | @@ -431,7 +432,6 @@ static const struct { IB_QP_RNR_RETRY | IB_QP_MAX_QP_RD_ATOMIC | IB_QP_MAX_DEST_RD_ATOMIC | - IB_QP_CUR_STATE | IB_QP_ALT_PATH | IB_QP_ACCESS_FLAGS | IB_QP_PKEY_INDEX | -- cgit v1.2.3-59-g8ed1b From 27d56300647f6e76847bc2407d7abc782fe87495 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Thu, 2 Mar 2006 11:25:27 -0800 Subject: IB/uverbs: Fix query QP return of sq_sig_all The old code didn't convert from the kernel's enum correctly. Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index b157e5ff7dad..0e0dbc9421bf 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1084,7 +1084,7 @@ ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file, resp.max_send_sge = init_attr->cap.max_send_sge; resp.max_recv_sge = init_attr->cap.max_recv_sge; resp.max_inline_data = init_attr->cap.max_inline_data; - resp.sq_sig_all = !!init_attr->sq_sig_type; + resp.sq_sig_all = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR; if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) -- cgit v1.2.3-59-g8ed1b From 651eaac92894f8b6761c51b6637ea9cacea7fba2 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 2 Mar 2006 12:40:46 -0800 Subject: IB/mthca: Optimize large messages on Sinai HCAs Sinai (one-port PCI Express) HCAs get improved throughput for messages bigger than 80 KB in DDR mode if memory keys are formatted in a specific way. The enhancement only works if the memory key table is smaller than 2^24 entries. For larger tables, the enhancement is off and a warning is printed (to avoid silent performance loss). Signed-off-by: Eli Cohen Signed-off-by: Michael Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cmd.c | 12 ++++++++---- drivers/infiniband/hw/mthca/mthca_dev.h | 3 ++- drivers/infiniband/hw/mthca/mthca_main.c | 23 +++++++++++++---------- drivers/infiniband/hw/mthca/mthca_mr.c | 20 +++++++++++++++++++- drivers/infiniband/hw/mthca/mthca_profile.c | 10 +++++++++- 5 files changed, 51 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 948a2861cae3..343eca507870 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -1277,7 +1277,8 @@ int mthca_INIT_HCA(struct mthca_dev *dev, int err; #define INIT_HCA_IN_SIZE 0x200 -#define INIT_HCA_FLAGS_OFFSET 0x014 +#define INIT_HCA_FLAGS1_OFFSET 0x00c +#define INIT_HCA_FLAGS2_OFFSET 0x014 #define INIT_HCA_QPC_OFFSET 0x020 #define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10) #define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17) @@ -1320,15 +1321,18 @@ int mthca_INIT_HCA(struct mthca_dev *dev, memset(inbox, 0, INIT_HCA_IN_SIZE); + if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT) + MTHCA_PUT(inbox, 0x1, INIT_HCA_FLAGS1_OFFSET); + #if defined(__LITTLE_ENDIAN) - *(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1); + *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) &= ~cpu_to_be32(1 << 1); #elif defined(__BIG_ENDIAN) - *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 1); + *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1 << 1); #else #error Host endianness not defined #endif /* Check port for UD address vector: */ - *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1); + *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1); /* We leave wqe_quota, responder_exu, etc as 0 (default) */ diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index ea48c897c7ce..ad52edbefe98 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -64,7 +64,8 @@ enum { MTHCA_FLAG_NO_LAM = 1 << 5, MTHCA_FLAG_FMR = 1 << 6, MTHCA_FLAG_MEMFREE = 1 << 7, - MTHCA_FLAG_PCIE = 1 << 8 + MTHCA_FLAG_PCIE = 1 << 8, + MTHCA_FLAG_SINAI_OPT = 1 << 9 }; enum { diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 9c849d27b06e..d94837fbf162 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c @@ -935,13 +935,19 @@ enum { static struct { u64 latest_fw; - int is_memfree; - int is_pcie; + u32 flags; } mthca_hca_table[] = { - [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 3), .is_memfree = 0, .is_pcie = 0 }, - [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 0), .is_memfree = 0, .is_pcie = 1 }, - [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), .is_memfree = 1, .is_pcie = 1 }, - [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 1), .is_memfree = 1, .is_pcie = 1 } + [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 3), + .flags = 0 }, + [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 0), + .flags = MTHCA_FLAG_PCIE }, + [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), + .flags = MTHCA_FLAG_MEMFREE | + MTHCA_FLAG_PCIE }, + [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 1), + .flags = MTHCA_FLAG_MEMFREE | + MTHCA_FLAG_PCIE | + MTHCA_FLAG_SINAI_OPT } }; static int __devinit mthca_init_one(struct pci_dev *pdev, @@ -1031,12 +1037,9 @@ static int __devinit mthca_init_one(struct pci_dev *pdev, mdev->pdev = pdev; + mdev->mthca_flags = mthca_hca_table[id->driver_data].flags; if (ddr_hidden) mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN; - if (mthca_hca_table[id->driver_data].is_memfree) - mdev->mthca_flags |= MTHCA_FLAG_MEMFREE; - if (mthca_hca_table[id->driver_data].is_pcie) - mdev->mthca_flags |= MTHCA_FLAG_PCIE; /* * Now reset the HCA before we touch the PCI capabilities or diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 0b48048ad0f8..698b62125765 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -76,6 +76,8 @@ struct mthca_mpt_entry { #define MTHCA_MPT_STATUS_SW 0xF0 #define MTHCA_MPT_STATUS_HW 0x00 +#define SINAI_FMR_KEY_INC 0x1000000 + /* * Buddy allocator for MTT segments (currently not very efficient * since it doesn't keep a free list and just searches linearly @@ -330,6 +332,14 @@ static inline u32 key_to_hw_index(struct mthca_dev *dev, u32 key) return tavor_key_to_hw_index(key); } +static inline u32 adjust_key(struct mthca_dev *dev, u32 key) +{ + if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT) + return ((key << 20) & 0x800000) | (key & 0x7fffff); + else + return key; +} + int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift, u64 iova, u64 total_size, u32 access, struct mthca_mr *mr) { @@ -345,6 +355,7 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift, key = mthca_alloc(&dev->mr_table.mpt_alloc); if (key == -1) return -ENOMEM; + key = adjust_key(dev, key); mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key); if (mthca_is_memfree(dev)) { @@ -504,6 +515,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd, key = mthca_alloc(&dev->mr_table.mpt_alloc); if (key == -1) return -ENOMEM; + key = adjust_key(dev, key); idx = key & (dev->limits.num_mpts - 1); mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key); @@ -687,7 +699,10 @@ int mthca_arbel_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, ++fmr->maps; key = arbel_key_to_hw_index(fmr->ibmr.lkey); - key += dev->limits.num_mpts; + if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT) + key += SINAI_FMR_KEY_INC; + else + key += dev->limits.num_mpts; fmr->ibmr.lkey = fmr->ibmr.rkey = arbel_hw_index_to_key(key); *(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_SW; @@ -760,6 +775,9 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev) else dev->mthca_flags |= MTHCA_FLAG_FMR; + if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT) + mthca_dbg(dev, "Memory key throughput optimization activated.\n"); + err = mthca_buddy_init(&dev->mr_table.mtt_buddy, fls(dev->limits.num_mtt_segs - 1)); diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c index 08a909371b0a..58d44aa3c302 100644 --- a/drivers/infiniband/hw/mthca/mthca_profile.c +++ b/drivers/infiniband/hw/mthca/mthca_profile.c @@ -152,7 +152,7 @@ u64 mthca_make_profile(struct mthca_dev *dev, } if (total_size > mem_avail) { mthca_err(dev, "Profile requires 0x%llx bytes; " - "won't in 0x%llx bytes of context memory.\n", + "won't fit in 0x%llx bytes of context memory.\n", (unsigned long long) total_size, (unsigned long long) mem_avail); kfree(profile); @@ -262,6 +262,14 @@ u64 mthca_make_profile(struct mthca_dev *dev, */ dev->limits.num_pds = MTHCA_NUM_PDS; + if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT && + init_hca->log_mpt_sz > 23) { + mthca_warn(dev, "MPT table too large (requested size 2^%d >= 2^24)\n", + init_hca->log_mpt_sz); + mthca_warn(dev, "Disabling memory key throughput optimization.\n"); + dev->mthca_flags &= ~MTHCA_FLAG_SINAI_OPT; + } + /* * For Tavor, FMRs use ioremapped PCI memory. For 32 bit * systems it may use too much vmalloc space to map all MTT -- cgit v1.2.3-59-g8ed1b From 6226bb570184eb6c645e047d2aecbce8c0442e3e Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 2 Mar 2006 13:56:37 -0800 Subject: IB/mthca: Update firmware versions Update known firmware versions in driver's table to the latest releases. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index d94837fbf162..266f347c6707 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c @@ -937,14 +937,14 @@ static struct { u64 latest_fw; u32 flags; } mthca_hca_table[] = { - [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 3), + [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 4, 0), .flags = 0 }, - [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 0), + [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 400), .flags = MTHCA_FLAG_PCIE }, [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), .flags = MTHCA_FLAG_MEMFREE | MTHCA_FLAG_PCIE }, - [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 1), + [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 800), .flags = MTHCA_FLAG_MEMFREE | MTHCA_FLAG_PCIE | MTHCA_FLAG_SINAI_OPT } -- cgit v1.2.3-59-g8ed1b From 87fd1a11ae91ab42fac978467667c61fee9f01da Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Thu, 2 Mar 2006 16:50:37 -0800 Subject: IB/cm: Check cm_id state before handling a REP Move checking the state of a cm_id before modifying it when handling a REP. This fixes a bug seen under MPI scale-up testing, where a NULL timewait_info pointer is dereferenced if a request times out before a REP is received. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cm.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 2514de3480d8..7cfedb8d9bcd 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -121,7 +121,7 @@ struct cm_id_private { struct rb_node service_node; struct rb_node sidr_id_node; - spinlock_t lock; + spinlock_t lock; /* Do not acquire inside cm.lock */ wait_queue_head_t wait; atomic_t refcount; @@ -1547,40 +1547,46 @@ static int cm_rep_handler(struct cm_work *work) return -EINVAL; } + cm_format_rep_event(work); + + spin_lock_irqsave(&cm_id_priv->lock, flags); + switch (cm_id_priv->id.state) { + case IB_CM_REQ_SENT: + case IB_CM_MRA_REQ_RCVD: + break; + default: + spin_unlock_irqrestore(&cm_id_priv->lock, flags); + ret = -EINVAL; + goto error; + } + cm_id_priv->timewait_info->work.remote_id = rep_msg->local_comm_id; cm_id_priv->timewait_info->remote_ca_guid = rep_msg->local_ca_guid; cm_id_priv->timewait_info->remote_qpn = cm_rep_get_local_qpn(rep_msg); - spin_lock_irqsave(&cm.lock, flags); + spin_lock(&cm.lock); /* Check for duplicate REP. */ if (cm_insert_remote_id(cm_id_priv->timewait_info)) { - spin_unlock_irqrestore(&cm.lock, flags); + spin_unlock(&cm.lock); + spin_unlock_irqrestore(&cm_id_priv->lock, flags); ret = -EINVAL; goto error; } /* Check for a stale connection. */ if (cm_insert_remote_qpn(cm_id_priv->timewait_info)) { - spin_unlock_irqrestore(&cm.lock, flags); + rb_erase(&cm_id_priv->timewait_info->remote_id_node, + &cm.remote_id_table); + cm_id_priv->timewait_info->inserted_remote_id = 0; + spin_unlock(&cm.lock); + spin_unlock_irqrestore(&cm_id_priv->lock, flags); cm_issue_rej(work->port, work->mad_recv_wc, IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REP, NULL, 0); ret = -EINVAL; goto error; } - spin_unlock_irqrestore(&cm.lock, flags); - - cm_format_rep_event(work); + spin_unlock(&cm.lock); - spin_lock_irqsave(&cm_id_priv->lock, flags); - switch (cm_id_priv->id.state) { - case IB_CM_REQ_SENT: - case IB_CM_MRA_REQ_RCVD: - break; - default: - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - ret = -EINVAL; - goto error; - } cm_id_priv->id.state = IB_CM_REP_RCVD; cm_id_priv->id.remote_id = rep_msg->local_comm_id; cm_id_priv->remote_qpn = cm_rep_get_local_qpn(rep_msg); @@ -1603,7 +1609,7 @@ static int cm_rep_handler(struct cm_work *work) cm_deref_id(cm_id_priv); return 0; -error: cm_cleanup_timewait(cm_id_priv->timewait_info); +error: cm_deref_id(cm_id_priv); return ret; } -- cgit v1.2.3-59-g8ed1b From 6ecb0c849625e830ab96495d473bb704812c30e1 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 20 Mar 2006 10:08:23 -0800 Subject: IB/srp: Add SCSI host attributes to show target port Add SCSI host attributes in sysfs that show the ID extension, IOC GUID, service ID, P_Key and destination GID for each target port that the SRP initiator connects to. Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 84 ++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 960dae5c87d1..89ad29dc88d4 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1237,6 +1237,87 @@ static int srp_reset_host(struct scsi_cmnd *scmnd) return ret; } +static ssize_t show_id_ext(struct class_device *cdev, char *buf) +{ + struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + + if (target->state == SRP_TARGET_DEAD || + target->state == SRP_TARGET_REMOVED) + return -ENODEV; + + return sprintf(buf, "0x%016llx\n", + (unsigned long long) be64_to_cpu(target->id_ext)); +} + +static ssize_t show_ioc_guid(struct class_device *cdev, char *buf) +{ + struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + + if (target->state == SRP_TARGET_DEAD || + target->state == SRP_TARGET_REMOVED) + return -ENODEV; + + return sprintf(buf, "0x%016llx\n", + (unsigned long long) be64_to_cpu(target->ioc_guid)); +} + +static ssize_t show_service_id(struct class_device *cdev, char *buf) +{ + struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + + if (target->state == SRP_TARGET_DEAD || + target->state == SRP_TARGET_REMOVED) + return -ENODEV; + + return sprintf(buf, "0x%016llx\n", + (unsigned long long) be64_to_cpu(target->service_id)); +} + +static ssize_t show_pkey(struct class_device *cdev, char *buf) +{ + struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + + if (target->state == SRP_TARGET_DEAD || + target->state == SRP_TARGET_REMOVED) + return -ENODEV; + + return sprintf(buf, "0x%04x\n", be16_to_cpu(target->path.pkey)); +} + +static ssize_t show_dgid(struct class_device *cdev, char *buf) +{ + struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + + if (target->state == SRP_TARGET_DEAD || + target->state == SRP_TARGET_REMOVED) + return -ENODEV; + + return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + be16_to_cpu(((__be16 *) target->path.dgid.raw)[0]), + be16_to_cpu(((__be16 *) target->path.dgid.raw)[1]), + be16_to_cpu(((__be16 *) target->path.dgid.raw)[2]), + be16_to_cpu(((__be16 *) target->path.dgid.raw)[3]), + be16_to_cpu(((__be16 *) target->path.dgid.raw)[4]), + be16_to_cpu(((__be16 *) target->path.dgid.raw)[5]), + be16_to_cpu(((__be16 *) target->path.dgid.raw)[6]), + be16_to_cpu(((__be16 *) target->path.dgid.raw)[7])); +} + +static CLASS_DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL); +static CLASS_DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL); +static CLASS_DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL); +static CLASS_DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); +static CLASS_DEVICE_ATTR(dgid, S_IRUGO, show_dgid, NULL); + +static struct class_device_attribute *srp_host_attrs[] = { + &class_device_attr_id_ext, + &class_device_attr_ioc_guid, + &class_device_attr_service_id, + &class_device_attr_pkey, + &class_device_attr_dgid, + NULL +}; + static struct scsi_host_template srp_template = { .module = THIS_MODULE, .name = DRV_NAME, @@ -1249,7 +1330,8 @@ static struct scsi_host_template srp_template = { .this_id = -1, .sg_tablesize = SRP_MAX_INDIRECT, .cmd_per_lun = SRP_SQ_SIZE, - .use_clustering = ENABLE_CLUSTERING + .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = srp_host_attrs }; static int srp_add_target(struct srp_host *host, struct srp_target_port *target) -- cgit v1.2.3-59-g8ed1b From f36e1793e25513380cae5958a9164d4cc4458ad0 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Fri, 3 Mar 2006 21:54:13 -0800 Subject: IB/umad: Add support for large RMPP transfers Add support for sending and receiving large RMPP transfers. The old code supports transfers only as large as a single contiguous kernel memory allocation. This patch uses linked list of memory buffers when sending and receiving data to avoid needing contiguous pages for larger transfers. Receive side: copy the arriving MADs in chunks instead of coalescing to one large buffer in kernel space. Send side: split a multipacket MAD buffer to a list of segments, (multipacket_list) and send these using a gather list of size 2. Also, save pointer to last sent segment, and retrieve requested segments by walking list starting at last sent segment. Finally, save pointer to last-acked segment. When retrying, retrieve segments for resending relative to this pointer. When updating last ack, start at this pointer. Signed-off-by: Jack Morgenstein Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/mad.c | 166 ++++++++++++++++++++++----- drivers/infiniband/core/mad_priv.h | 16 ++- drivers/infiniband/core/mad_rmpp.c | 148 ++++++++---------------- drivers/infiniband/core/user_mad.c | 225 +++++++++++++++++++++++++------------ include/rdma/ib_mad.h | 48 +++++--- 5 files changed, 376 insertions(+), 227 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 445ad0dda213..16549add8e8f 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -31,7 +31,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id: mad.c 2817 2005-07-07 11:29:26Z halr $ + * $Id: mad.c 5596 2006-03-03 01:00:07Z sean.hefty $ */ #include @@ -765,18 +765,67 @@ out: return ret; } -static int get_buf_length(int hdr_len, int data_len) +static int get_pad_size(int hdr_len, int data_len) { int seg_size, pad; seg_size = sizeof(struct ib_mad) - hdr_len; if (data_len && seg_size) { pad = seg_size - data_len % seg_size; - if (pad == seg_size) - pad = 0; + return pad == seg_size ? 0 : pad; } else - pad = seg_size; - return hdr_len + data_len + pad; + return seg_size; +} + +static void free_send_rmpp_list(struct ib_mad_send_wr_private *mad_send_wr) +{ + struct ib_rmpp_segment *s, *t; + + list_for_each_entry_safe(s, t, &mad_send_wr->rmpp_list, list) { + list_del(&s->list); + kfree(s); + } +} + +static int alloc_send_rmpp_list(struct ib_mad_send_wr_private *send_wr, + gfp_t gfp_mask) +{ + struct ib_mad_send_buf *send_buf = &send_wr->send_buf; + struct ib_rmpp_mad *rmpp_mad = send_buf->mad; + struct ib_rmpp_segment *seg = NULL; + int left, seg_size, pad; + + send_buf->seg_size = sizeof (struct ib_mad) - send_buf->hdr_len; + seg_size = send_buf->seg_size; + pad = send_wr->pad; + + /* Allocate data segments. */ + for (left = send_buf->data_len + pad; left > 0; left -= seg_size) { + seg = kmalloc(sizeof (*seg) + seg_size, gfp_mask); + if (!seg) { + printk(KERN_ERR "alloc_send_rmpp_segs: RMPP mem " + "alloc failed for len %zd, gfp %#x\n", + sizeof (*seg) + seg_size, gfp_mask); + free_send_rmpp_list(send_wr); + return -ENOMEM; + } + seg->num = ++send_buf->seg_count; + list_add_tail(&seg->list, &send_wr->rmpp_list); + } + + /* Zero any padding */ + if (pad) + memset(seg->data + seg_size - pad, 0, pad); + + rmpp_mad->rmpp_hdr.rmpp_version = send_wr->mad_agent_priv-> + agent.rmpp_version; + rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA; + ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE); + + send_wr->cur_seg = container_of(send_wr->rmpp_list.next, + struct ib_rmpp_segment, list); + send_wr->last_ack_seg = send_wr->cur_seg; + return 0; } struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, @@ -787,32 +836,40 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, { struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_send_wr_private *mad_send_wr; - int buf_size; + int pad, message_size, ret, size; void *buf; mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private, agent); - buf_size = get_buf_length(hdr_len, data_len); + pad = get_pad_size(hdr_len, data_len); + message_size = hdr_len + data_len + pad; if ((!mad_agent->rmpp_version && - (rmpp_active || buf_size > sizeof(struct ib_mad))) || - (!rmpp_active && buf_size > sizeof(struct ib_mad))) + (rmpp_active || message_size > sizeof(struct ib_mad))) || + (!rmpp_active && message_size > sizeof(struct ib_mad))) return ERR_PTR(-EINVAL); - buf = kzalloc(sizeof *mad_send_wr + buf_size, gfp_mask); + size = rmpp_active ? hdr_len : sizeof(struct ib_mad); + buf = kzalloc(sizeof *mad_send_wr + size, gfp_mask); if (!buf) return ERR_PTR(-ENOMEM); - mad_send_wr = buf + buf_size; + mad_send_wr = buf + size; + INIT_LIST_HEAD(&mad_send_wr->rmpp_list); mad_send_wr->send_buf.mad = buf; + mad_send_wr->send_buf.hdr_len = hdr_len; + mad_send_wr->send_buf.data_len = data_len; + mad_send_wr->pad = pad; mad_send_wr->mad_agent_priv = mad_agent_priv; - mad_send_wr->sg_list[0].length = buf_size; + mad_send_wr->sg_list[0].length = hdr_len; mad_send_wr->sg_list[0].lkey = mad_agent->mr->lkey; + mad_send_wr->sg_list[1].length = sizeof(struct ib_mad) - hdr_len; + mad_send_wr->sg_list[1].lkey = mad_agent->mr->lkey; mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr; mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list; - mad_send_wr->send_wr.num_sge = 1; + mad_send_wr->send_wr.num_sge = 2; mad_send_wr->send_wr.opcode = IB_WR_SEND; mad_send_wr->send_wr.send_flags = IB_SEND_SIGNALED; mad_send_wr->send_wr.wr.ud.remote_qpn = remote_qpn; @@ -820,13 +877,11 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index; if (rmpp_active) { - struct ib_rmpp_mad *rmpp_mad = mad_send_wr->send_buf.mad; - rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(hdr_len - - IB_MGMT_RMPP_HDR + data_len); - rmpp_mad->rmpp_hdr.rmpp_version = mad_agent->rmpp_version; - rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA; - ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, - IB_MGMT_RMPP_FLAG_ACTIVE); + ret = alloc_send_rmpp_list(mad_send_wr, gfp_mask); + if (ret) { + kfree(buf); + return ERR_PTR(ret); + } } mad_send_wr->send_buf.mad_agent = mad_agent; @@ -835,14 +890,50 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, } EXPORT_SYMBOL(ib_create_send_mad); +void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num) +{ + struct ib_mad_send_wr_private *mad_send_wr; + struct list_head *list; + + mad_send_wr = container_of(send_buf, struct ib_mad_send_wr_private, + send_buf); + list = &mad_send_wr->cur_seg->list; + + if (mad_send_wr->cur_seg->num < seg_num) { + list_for_each_entry(mad_send_wr->cur_seg, list, list) + if (mad_send_wr->cur_seg->num == seg_num) + break; + } else if (mad_send_wr->cur_seg->num > seg_num) { + list_for_each_entry_reverse(mad_send_wr->cur_seg, list, list) + if (mad_send_wr->cur_seg->num == seg_num) + break; + } + return mad_send_wr->cur_seg->data; +} +EXPORT_SYMBOL(ib_get_rmpp_segment); + +static inline void *ib_get_payload(struct ib_mad_send_wr_private *mad_send_wr) +{ + if (mad_send_wr->send_buf.seg_count) + return ib_get_rmpp_segment(&mad_send_wr->send_buf, + mad_send_wr->seg_num); + else + return mad_send_wr->send_buf.mad + + mad_send_wr->send_buf.hdr_len; +} + void ib_free_send_mad(struct ib_mad_send_buf *send_buf) { struct ib_mad_agent_private *mad_agent_priv; + struct ib_mad_send_wr_private *mad_send_wr; mad_agent_priv = container_of(send_buf->mad_agent, struct ib_mad_agent_private, agent); - kfree(send_buf->mad); + mad_send_wr = container_of(send_buf, struct ib_mad_send_wr_private, + send_buf); + free_send_rmpp_list(mad_send_wr); + kfree(send_buf->mad); if (atomic_dec_and_test(&mad_agent_priv->refcount)) wake_up(&mad_agent_priv->wait); } @@ -865,10 +956,17 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr) mad_agent = mad_send_wr->send_buf.mad_agent; sge = mad_send_wr->sg_list; - sge->addr = dma_map_single(mad_agent->device->dma_device, - mad_send_wr->send_buf.mad, sge->length, - DMA_TO_DEVICE); - pci_unmap_addr_set(mad_send_wr, mapping, sge->addr); + sge[0].addr = dma_map_single(mad_agent->device->dma_device, + mad_send_wr->send_buf.mad, + sge[0].length, + DMA_TO_DEVICE); + pci_unmap_addr_set(mad_send_wr, header_mapping, sge[0].addr); + + sge[1].addr = dma_map_single(mad_agent->device->dma_device, + ib_get_payload(mad_send_wr), + sge[1].length, + DMA_TO_DEVICE); + pci_unmap_addr_set(mad_send_wr, payload_mapping, sge[1].addr); spin_lock_irqsave(&qp_info->send_queue.lock, flags); if (qp_info->send_queue.count < qp_info->send_queue.max_active) { @@ -885,11 +983,14 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr) list_add_tail(&mad_send_wr->mad_list.list, list); } spin_unlock_irqrestore(&qp_info->send_queue.lock, flags); - if (ret) + if (ret) { dma_unmap_single(mad_agent->device->dma_device, - pci_unmap_addr(mad_send_wr, mapping), - sge->length, DMA_TO_DEVICE); - + pci_unmap_addr(mad_send_wr, header_mapping), + sge[0].length, DMA_TO_DEVICE); + dma_unmap_single(mad_agent->device->dma_device, + pci_unmap_addr(mad_send_wr, payload_mapping), + sge[1].length, DMA_TO_DEVICE); + } return ret; } @@ -1860,8 +1961,11 @@ static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv, retry: dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device, - pci_unmap_addr(mad_send_wr, mapping), + pci_unmap_addr(mad_send_wr, header_mapping), mad_send_wr->sg_list[0].length, DMA_TO_DEVICE); + dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device, + pci_unmap_addr(mad_send_wr, payload_mapping), + mad_send_wr->sg_list[1].length, DMA_TO_DEVICE); queued_send_wr = NULL; spin_lock_irqsave(&send_queue->lock, flags); list_del(&mad_list->list); diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index 570f78682af3..a7125d4b5ccf 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h @@ -31,7 +31,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id: mad_priv.h 2730 2005-06-28 16:43:03Z sean.hefty $ + * $Id: mad_priv.h 5596 2006-03-03 01:00:07Z sean.hefty $ */ #ifndef __IB_MAD_PRIV_H__ @@ -85,6 +85,12 @@ struct ib_mad_private { } mad; } __attribute__ ((packed)); +struct ib_rmpp_segment { + struct list_head list; + u32 num; + u8 data[0]; +}; + struct ib_mad_agent_private { struct list_head agent_list; struct ib_mad_agent agent; @@ -119,7 +125,8 @@ struct ib_mad_send_wr_private { struct list_head agent_list; struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_send_buf send_buf; - DECLARE_PCI_UNMAP_ADDR(mapping) + DECLARE_PCI_UNMAP_ADDR(header_mapping) + DECLARE_PCI_UNMAP_ADDR(payload_mapping) struct ib_send_wr send_wr; struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG]; __be64 tid; @@ -130,11 +137,12 @@ struct ib_mad_send_wr_private { enum ib_wc_status status; /* RMPP control */ + struct list_head rmpp_list; + struct ib_rmpp_segment *last_ack_seg; + struct ib_rmpp_segment *cur_seg; int last_ack; int seg_num; int newwin; - int total_seg; - int data_offset; int pad; }; diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index 3249e1d8c07b..bacfdd5bddad 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -111,14 +111,14 @@ static int data_offset(u8 mgmt_class) return IB_MGMT_RMPP_HDR; } -static void format_ack(struct ib_rmpp_mad *ack, +static void format_ack(struct ib_mad_send_buf *msg, struct ib_rmpp_mad *data, struct mad_rmpp_recv *rmpp_recv) { + struct ib_rmpp_mad *ack = msg->mad; unsigned long flags; - memcpy(&ack->mad_hdr, &data->mad_hdr, - data_offset(data->mad_hdr.mgmt_class)); + memcpy(ack, &data->mad_hdr, msg->hdr_len); ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP; ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK; @@ -135,16 +135,16 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv, struct ib_mad_recv_wc *recv_wc) { struct ib_mad_send_buf *msg; - int ret; + int ret, hdr_len; + hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, - recv_wc->wc->pkey_index, 1, IB_MGMT_RMPP_HDR, - IB_MGMT_RMPP_DATA, GFP_KERNEL); + recv_wc->wc->pkey_index, 1, hdr_len, + 0, GFP_KERNEL); if (!msg) return; - format_ack(msg->mad, (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, - rmpp_recv); + format_ack(msg, (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv); msg->ah = rmpp_recv->ah; ret = ib_post_send_mad(msg, NULL); if (ret) @@ -156,16 +156,17 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent, { struct ib_mad_send_buf *msg; struct ib_ah *ah; + int hdr_len; ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc, recv_wc->recv_buf.grh, agent->port_num); if (IS_ERR(ah)) return (void *) ah; + hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); msg = ib_create_send_mad(agent, recv_wc->wc->src_qp, recv_wc->wc->pkey_index, 1, - IB_MGMT_RMPP_HDR, IB_MGMT_RMPP_DATA, - GFP_KERNEL); + hdr_len, 0, GFP_KERNEL); if (IS_ERR(msg)) ib_destroy_ah(ah); else @@ -195,8 +196,7 @@ static void nack_recv(struct ib_mad_agent_private *agent, return; rmpp_mad = msg->mad; - memcpy(rmpp_mad, recv_wc->recv_buf.mad, - data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class)); + memcpy(rmpp_mad, recv_wc->recv_buf.mad, msg->hdr_len); rmpp_mad->mad_hdr.method ^= IB_MGMT_METHOD_RESP; rmpp_mad->rmpp_hdr.rmpp_version = IB_MGMT_RMPP_VERSION; @@ -433,44 +433,6 @@ static struct ib_mad_recv_wc * complete_rmpp(struct mad_rmpp_recv *rmpp_recv) return rmpp_wc; } -void ib_coalesce_recv_mad(struct ib_mad_recv_wc *mad_recv_wc, void *buf) -{ - struct ib_mad_recv_buf *seg_buf; - struct ib_rmpp_mad *rmpp_mad; - void *data; - int size, len, offset; - u8 flags; - - len = mad_recv_wc->mad_len; - if (len <= sizeof(struct ib_mad)) { - memcpy(buf, mad_recv_wc->recv_buf.mad, len); - return; - } - - offset = data_offset(mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class); - - list_for_each_entry(seg_buf, &mad_recv_wc->rmpp_list, list) { - rmpp_mad = (struct ib_rmpp_mad *)seg_buf->mad; - flags = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr); - - if (flags & IB_MGMT_RMPP_FLAG_FIRST) { - data = rmpp_mad; - size = sizeof(*rmpp_mad); - } else { - data = (void *) rmpp_mad + offset; - if (flags & IB_MGMT_RMPP_FLAG_LAST) - size = len; - else - size = sizeof(*rmpp_mad) - offset; - } - - memcpy(buf, data, size); - len -= size; - buf += size; - } -} -EXPORT_SYMBOL(ib_coalesce_recv_mad); - static struct ib_mad_recv_wc * continue_rmpp(struct ib_mad_agent_private *agent, struct ib_mad_recv_wc *mad_recv_wc) @@ -570,50 +532,33 @@ start_rmpp(struct ib_mad_agent_private *agent, return mad_recv_wc; } -static inline u64 get_seg_addr(struct ib_mad_send_wr_private *mad_send_wr) -{ - return mad_send_wr->sg_list[0].addr + mad_send_wr->data_offset + - (sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset) * - (mad_send_wr->seg_num - 1); -} - static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) { struct ib_rmpp_mad *rmpp_mad; int timeout; - u32 paylen; + u32 paylen = 0; rmpp_mad = mad_send_wr->send_buf.mad; ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE); - rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(mad_send_wr->seg_num); + rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(++mad_send_wr->seg_num); if (mad_send_wr->seg_num == 1) { rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST; - paylen = mad_send_wr->total_seg * IB_MGMT_RMPP_DATA - + paylen = mad_send_wr->send_buf.seg_count * IB_MGMT_RMPP_DATA - mad_send_wr->pad; - rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); - mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad); - } else { - mad_send_wr->send_wr.num_sge = 2; - mad_send_wr->sg_list[0].length = mad_send_wr->data_offset; - mad_send_wr->sg_list[1].addr = get_seg_addr(mad_send_wr); - mad_send_wr->sg_list[1].length = sizeof(struct ib_rmpp_mad) - - mad_send_wr->data_offset; - mad_send_wr->sg_list[1].lkey = mad_send_wr->sg_list[0].lkey; - rmpp_mad->rmpp_hdr.paylen_newwin = 0; } - if (mad_send_wr->seg_num == mad_send_wr->total_seg) { + if (mad_send_wr->seg_num == mad_send_wr->send_buf.seg_count) { rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST; paylen = IB_MGMT_RMPP_DATA - mad_send_wr->pad; - rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); } + rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); /* 2 seconds for an ACK until we can find the packet lifetime */ timeout = mad_send_wr->send_buf.timeout_ms; if (!timeout || timeout > 2000) mad_send_wr->timeout = msecs_to_jiffies(2000); - mad_send_wr->seg_num++; + return ib_send_mad(mad_send_wr); } @@ -629,7 +574,7 @@ static void abort_send(struct ib_mad_agent_private *agent, __be64 tid, if (!mad_send_wr) goto out; /* Unmatched send */ - if ((mad_send_wr->last_ack == mad_send_wr->total_seg) || + if ((mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) || (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS)) goto out; /* Send is already done */ @@ -645,6 +590,18 @@ out: spin_unlock_irqrestore(&agent->lock, flags); } +static inline void adjust_last_ack(struct ib_mad_send_wr_private *wr, + int seg_num) +{ + struct list_head *list; + + wr->last_ack = seg_num; + list = &wr->last_ack_seg->list; + list_for_each_entry(wr->last_ack_seg, list, list) + if (wr->last_ack_seg->num == seg_num) + break; +} + static void process_rmpp_ack(struct ib_mad_agent_private *agent, struct ib_mad_recv_wc *mad_recv_wc) { @@ -675,11 +632,12 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, if (!mad_send_wr) goto out; /* Unmatched ACK */ - if ((mad_send_wr->last_ack == mad_send_wr->total_seg) || + if ((mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) || (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS)) goto out; /* Send is already done */ - if (seg_num > mad_send_wr->total_seg || seg_num > mad_send_wr->newwin) { + if (seg_num > mad_send_wr->send_buf.seg_count || + seg_num > mad_send_wr->newwin) { spin_unlock_irqrestore(&agent->lock, flags); abort_send(agent, rmpp_mad->mad_hdr.tid, IB_MGMT_RMPP_STATUS_S2B); @@ -691,11 +649,11 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, goto out; /* Old ACK */ if (seg_num > mad_send_wr->last_ack) { - mad_send_wr->last_ack = seg_num; + adjust_last_ack(mad_send_wr, seg_num); mad_send_wr->retries = mad_send_wr->send_buf.retries; } mad_send_wr->newwin = newwin; - if (mad_send_wr->last_ack == mad_send_wr->total_seg) { + if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) { /* If no response is expected, the ACK completes the send */ if (!mad_send_wr->send_buf.timeout_ms) { struct ib_mad_send_wc wc; @@ -714,7 +672,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, mad_send_wr->send_buf.timeout_ms); } else if (mad_send_wr->refcount == 1 && mad_send_wr->seg_num < mad_send_wr->newwin && - mad_send_wr->seg_num <= mad_send_wr->total_seg) { + mad_send_wr->seg_num < mad_send_wr->send_buf.seg_count) { /* Send failure will just result in a timeout/retry */ ret = send_next_seg(mad_send_wr); if (ret) @@ -838,31 +796,19 @@ out: int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr) { struct ib_rmpp_mad *rmpp_mad; - int i, total_len, ret; + int ret; rmpp_mad = mad_send_wr->send_buf.mad; if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE)) return IB_RMPP_RESULT_UNHANDLED; - if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) + if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) { + mad_send_wr->seg_num = 1; return IB_RMPP_RESULT_INTERNAL; + } - if (mad_send_wr->send_wr.num_sge > 1) - return -EINVAL; /* TODO: support num_sge > 1 */ - - mad_send_wr->seg_num = 1; mad_send_wr->newwin = 1; - mad_send_wr->data_offset = data_offset(rmpp_mad->mad_hdr.mgmt_class); - - total_len = 0; - for (i = 0; i < mad_send_wr->send_wr.num_sge; i++) - total_len += mad_send_wr->send_wr.sg_list[i].length; - - mad_send_wr->total_seg = (total_len - mad_send_wr->data_offset) / - (sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset); - mad_send_wr->pad = total_len - IB_MGMT_RMPP_HDR - - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); /* We need to wait for the final ACK even if there isn't a response */ mad_send_wr->refcount += (mad_send_wr->timeout == 0); @@ -893,14 +839,14 @@ int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr, if (!mad_send_wr->timeout) return IB_RMPP_RESULT_PROCESSED; /* Response received */ - if (mad_send_wr->last_ack == mad_send_wr->total_seg) { + if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) { mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms); return IB_RMPP_RESULT_PROCESSED; /* Send done */ } - if (mad_send_wr->seg_num > mad_send_wr->newwin || - mad_send_wr->seg_num > mad_send_wr->total_seg) + if (mad_send_wr->seg_num == mad_send_wr->newwin || + mad_send_wr->seg_num == mad_send_wr->send_buf.seg_count) return IB_RMPP_RESULT_PROCESSED; /* Wait for ACK */ ret = send_next_seg(mad_send_wr); @@ -921,10 +867,12 @@ int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr) IB_MGMT_RMPP_FLAG_ACTIVE)) return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */ - if (mad_send_wr->last_ack == mad_send_wr->total_seg) + if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) return IB_RMPP_RESULT_PROCESSED; - mad_send_wr->seg_num = mad_send_wr->last_ack + 1; + mad_send_wr->seg_num = mad_send_wr->last_ack; + mad_send_wr->cur_seg = mad_send_wr->last_ack_seg; + ret = send_next_seg(mad_send_wr); if (ret) return IB_RMPP_RESULT_PROCESSED; diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index c908de8db5a9..fb6cd42601f9 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -31,7 +31,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id: user_mad.c 4010 2005-11-09 23:11:56Z roland $ + * $Id: user_mad.c 5596 2006-03-03 01:00:07Z sean.hefty $ */ #include @@ -121,6 +121,7 @@ struct ib_umad_file { struct ib_umad_packet { struct ib_mad_send_buf *msg; + struct ib_mad_recv_wc *recv_wc; struct list_head list; int length; struct ib_user_mad mad; @@ -176,31 +177,32 @@ static int queue_packet(struct ib_umad_file *file, return ret; } +static int data_offset(u8 mgmt_class) +{ + if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) + return IB_MGMT_SA_HDR; + else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && + (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) + return IB_MGMT_VENDOR_HDR; + else + return IB_MGMT_RMPP_HDR; +} + static void send_handler(struct ib_mad_agent *agent, struct ib_mad_send_wc *send_wc) { struct ib_umad_file *file = agent->context; - struct ib_umad_packet *timeout; struct ib_umad_packet *packet = send_wc->send_buf->context[0]; ib_destroy_ah(packet->msg->ah); ib_free_send_mad(packet->msg); if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) { - timeout = kzalloc(sizeof *timeout + IB_MGMT_MAD_HDR, GFP_KERNEL); - if (!timeout) - goto out; - - timeout->length = IB_MGMT_MAD_HDR; - timeout->mad.hdr.id = packet->mad.hdr.id; - timeout->mad.hdr.status = ETIMEDOUT; - memcpy(timeout->mad.data, packet->mad.data, - sizeof (struct ib_mad_hdr)); - - if (queue_packet(file, agent, timeout)) - kfree(timeout); + packet->length = IB_MGMT_MAD_HDR; + packet->mad.hdr.status = ETIMEDOUT; + if (!queue_packet(file, agent, packet)) + return; } -out: kfree(packet); } @@ -209,22 +211,20 @@ static void recv_handler(struct ib_mad_agent *agent, { struct ib_umad_file *file = agent->context; struct ib_umad_packet *packet; - int length; if (mad_recv_wc->wc->status != IB_WC_SUCCESS) - goto out; + goto err1; - length = mad_recv_wc->mad_len; - packet = kzalloc(sizeof *packet + length, GFP_KERNEL); + packet = kzalloc(sizeof *packet, GFP_KERNEL); if (!packet) - goto out; + goto err1; - packet->length = length; - - ib_coalesce_recv_mad(mad_recv_wc, packet->mad.data); + packet->length = mad_recv_wc->mad_len; + packet->recv_wc = mad_recv_wc; packet->mad.hdr.status = 0; - packet->mad.hdr.length = length + sizeof (struct ib_user_mad); + packet->mad.hdr.length = sizeof (struct ib_user_mad) + + mad_recv_wc->mad_len; packet->mad.hdr.qpn = cpu_to_be32(mad_recv_wc->wc->src_qp); packet->mad.hdr.lid = cpu_to_be16(mad_recv_wc->wc->slid); packet->mad.hdr.sl = mad_recv_wc->wc->sl; @@ -240,12 +240,79 @@ static void recv_handler(struct ib_mad_agent *agent, } if (queue_packet(file, agent, packet)) - kfree(packet); + goto err2; + return; -out: +err2: + kfree(packet); +err1: ib_free_recv_mad(mad_recv_wc); } +static ssize_t copy_recv_mad(char __user *buf, struct ib_umad_packet *packet, + size_t count) +{ + struct ib_mad_recv_buf *recv_buf; + int left, seg_payload, offset, max_seg_payload; + + /* We need enough room to copy the first (or only) MAD segment. */ + recv_buf = &packet->recv_wc->recv_buf; + if ((packet->length <= sizeof (*recv_buf->mad) && + count < sizeof (packet->mad) + packet->length) || + (packet->length > sizeof (*recv_buf->mad) && + count < sizeof (packet->mad) + sizeof (*recv_buf->mad))) + return -EINVAL; + + if (copy_to_user(buf, &packet->mad, sizeof (packet->mad))) + return -EFAULT; + + buf += sizeof (packet->mad); + seg_payload = min_t(int, packet->length, sizeof (*recv_buf->mad)); + if (copy_to_user(buf, recv_buf->mad, seg_payload)) + return -EFAULT; + + if (seg_payload < packet->length) { + /* + * Multipacket RMPP MAD message. Copy remainder of message. + * Note that last segment may have a shorter payload. + */ + if (count < sizeof (packet->mad) + packet->length) { + /* + * The buffer is too small, return the first RMPP segment, + * which includes the RMPP message length. + */ + return -ENOSPC; + } + offset = data_offset(recv_buf->mad->mad_hdr.mgmt_class); + max_seg_payload = sizeof (struct ib_mad) - offset; + + for (left = packet->length - seg_payload, buf += seg_payload; + left; left -= seg_payload, buf += seg_payload) { + recv_buf = container_of(recv_buf->list.next, + struct ib_mad_recv_buf, list); + seg_payload = min(left, max_seg_payload); + if (copy_to_user(buf, ((void *) recv_buf->mad) + offset, + seg_payload)) + return -EFAULT; + } + } + return sizeof (packet->mad) + packet->length; +} + +static ssize_t copy_send_mad(char __user *buf, struct ib_umad_packet *packet, + size_t count) +{ + ssize_t size = sizeof (packet->mad) + packet->length; + + if (count < size) + return -EINVAL; + + if (copy_to_user(buf, &packet->mad, size)) + return -EFAULT; + + return size; +} + static ssize_t ib_umad_read(struct file *filp, char __user *buf, size_t count, loff_t *pos) { @@ -253,7 +320,7 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf, struct ib_umad_packet *packet; ssize_t ret; - if (count < sizeof (struct ib_user_mad) + sizeof (struct ib_mad)) + if (count < sizeof (struct ib_user_mad)) return -EINVAL; spin_lock_irq(&file->recv_lock); @@ -276,28 +343,44 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf, spin_unlock_irq(&file->recv_lock); - if (count < packet->length + sizeof (struct ib_user_mad)) { - /* Return length needed (and first RMPP segment) if too small */ - if (copy_to_user(buf, &packet->mad, - sizeof (struct ib_user_mad) + sizeof (struct ib_mad))) - ret = -EFAULT; - else - ret = -ENOSPC; - } else if (copy_to_user(buf, &packet->mad, - packet->length + sizeof (struct ib_user_mad))) - ret = -EFAULT; + if (packet->recv_wc) + ret = copy_recv_mad(buf, packet, count); else - ret = packet->length + sizeof (struct ib_user_mad); + ret = copy_send_mad(buf, packet, count); + if (ret < 0) { /* Requeue packet */ spin_lock_irq(&file->recv_lock); list_add(&packet->list, &file->recv_list); spin_unlock_irq(&file->recv_lock); - } else + } else { + if (packet->recv_wc) + ib_free_recv_mad(packet->recv_wc); kfree(packet); + } return ret; } +static int copy_rmpp_mad(struct ib_mad_send_buf *msg, const char __user *buf) +{ + int left, seg; + + /* Copy class specific header */ + if ((msg->hdr_len > IB_MGMT_RMPP_HDR) && + copy_from_user(msg->mad + IB_MGMT_RMPP_HDR, buf + IB_MGMT_RMPP_HDR, + msg->hdr_len - IB_MGMT_RMPP_HDR)) + return -EFAULT; + + /* All headers are in place. Copy data segments. */ + for (seg = 1, left = msg->data_len, buf += msg->hdr_len; left > 0; + seg++, left -= msg->seg_size, buf += msg->seg_size) { + if (copy_from_user(ib_get_rmpp_segment(msg, seg), buf, + min(left, msg->seg_size))) + return -EFAULT; + } + return 0; +} + static ssize_t ib_umad_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos) { @@ -309,14 +392,12 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, struct ib_rmpp_mad *rmpp_mad; u8 method; __be64 *tid; - int ret, length, hdr_len, copy_offset; - int rmpp_active, has_rmpp_header; + int ret, data_len, hdr_len, copy_offset, rmpp_active; if (count < sizeof (struct ib_user_mad) + IB_MGMT_RMPP_HDR) return -EINVAL; - length = count - sizeof (struct ib_user_mad); - packet = kmalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL); + packet = kzalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL); if (!packet) return -ENOMEM; @@ -363,35 +444,25 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { hdr_len = IB_MGMT_SA_HDR; copy_offset = IB_MGMT_RMPP_HDR; - has_rmpp_header = 1; + rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & + IB_MGMT_RMPP_FLAG_ACTIVE; } else if (rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START && rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END) { - hdr_len = IB_MGMT_VENDOR_HDR; - copy_offset = IB_MGMT_RMPP_HDR; - has_rmpp_header = 1; + hdr_len = IB_MGMT_VENDOR_HDR; + copy_offset = IB_MGMT_RMPP_HDR; + rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & + IB_MGMT_RMPP_FLAG_ACTIVE; } else { hdr_len = IB_MGMT_MAD_HDR; copy_offset = IB_MGMT_MAD_HDR; - has_rmpp_header = 0; - } - - if (has_rmpp_header) - rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & - IB_MGMT_RMPP_FLAG_ACTIVE; - else rmpp_active = 0; - - /* Validate that the management class can support RMPP */ - if (rmpp_active && !agent->rmpp_version) { - ret = -EINVAL; - goto err_ah; } + data_len = count - sizeof (struct ib_user_mad) - hdr_len; packet->msg = ib_create_send_mad(agent, be32_to_cpu(packet->mad.hdr.qpn), - 0, rmpp_active, - hdr_len, length - hdr_len, - GFP_KERNEL); + 0, rmpp_active, hdr_len, + data_len, GFP_KERNEL); if (IS_ERR(packet->msg)) { ret = PTR_ERR(packet->msg); goto err_ah; @@ -402,14 +473,21 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, packet->msg->retries = packet->mad.hdr.retries; packet->msg->context[0] = packet; - /* Copy MAD headers (RMPP header in place) */ + /* Copy MAD header. Any RMPP header is already in place. */ memcpy(packet->msg->mad, packet->mad.data, IB_MGMT_MAD_HDR); - /* Now, copy rest of message from user into send buffer */ - if (copy_from_user(packet->msg->mad + copy_offset, - buf + sizeof (struct ib_user_mad) + copy_offset, - length - copy_offset)) { - ret = -EFAULT; - goto err_msg; + buf += sizeof (struct ib_user_mad); + + if (!rmpp_active) { + if (copy_from_user(packet->msg->mad + copy_offset, + buf + copy_offset, + hdr_len + data_len - copy_offset)) { + ret = -EFAULT; + goto err_msg; + } + } else { + ret = copy_rmpp_mad(packet->msg, buf); + if (ret) + goto err_msg; } /* @@ -433,18 +511,14 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, goto err_msg; up_read(&file->port->mutex); - return count; err_msg: ib_free_send_mad(packet->msg); - err_ah: ib_destroy_ah(ah); - err_up: up_read(&file->port->mutex); - err: kfree(packet); return ret; @@ -627,8 +701,11 @@ static int ib_umad_close(struct inode *inode, struct file *filp) already_dead = file->agents_dead; file->agents_dead = 1; - list_for_each_entry_safe(packet, tmp, &file->recv_list, list) + list_for_each_entry_safe(packet, tmp, &file->recv_list, list) { + if (packet->recv_wc) + ib_free_recv_mad(packet->recv_wc); kfree(packet); + } list_del(&file->port_list); diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h index 2c133506742b..51ab8eddb295 100644 --- a/include/rdma/ib_mad.h +++ b/include/rdma/ib_mad.h @@ -33,7 +33,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id: ib_mad.h 2775 2005-07-02 13:42:12Z halr $ + * $Id: ib_mad.h 5596 2006-03-03 01:00:07Z sean.hefty $ */ #if !defined( IB_MAD_H ) @@ -208,15 +208,23 @@ struct ib_class_port_info /** * ib_mad_send_buf - MAD data buffer and work request for sends. * @next: A pointer used to chain together MADs for posting. - * @mad: References an allocated MAD data buffer. + * @mad: References an allocated MAD data buffer for MADs that do not have + * RMPP active. For MADs using RMPP, references the common and management + * class specific headers. * @mad_agent: MAD agent that allocated the buffer. * @ah: The address handle to use when sending the MAD. * @context: User-controlled context fields. + * @hdr_len: Indicates the size of the data header of the MAD. This length + * includes the common MAD, RMPP, and class specific headers. + * @data_len: Indicates the total size of user-transferred data. + * @seg_count: The number of RMPP segments allocated for this send. + * @seg_size: Size of each RMPP segment. * @timeout_ms: Time to wait for a response. * @retries: Number of times to retry a request for a response. * * Users are responsible for initializing the MAD buffer itself, with the - * exception of specifying the payload length field in any RMPP MAD. + * exception of any RMPP header. Additional segment buffer space allocated + * beyond data_len is padding. */ struct ib_mad_send_buf { struct ib_mad_send_buf *next; @@ -224,6 +232,10 @@ struct ib_mad_send_buf { struct ib_mad_agent *mad_agent; struct ib_ah *ah; void *context[2]; + int hdr_len; + int data_len; + int seg_count; + int seg_size; int timeout_ms; int retries; }; @@ -299,7 +311,7 @@ typedef void (*ib_mad_snoop_handler)(struct ib_mad_agent *mad_agent, * @mad_recv_wc: Received work completion information on the received MAD. * * MADs received in response to a send request operation will be handed to - * the user after the send operation completes. All data buffers given + * the user before the send operation completes. All data buffers given * to registered agents through this routine are owned by the receiving * client, except for snooping agents. Clients snooping MADs should not * modify the data referenced by @mad_recv_wc. @@ -485,17 +497,6 @@ int ib_unregister_mad_agent(struct ib_mad_agent *mad_agent); int ib_post_send_mad(struct ib_mad_send_buf *send_buf, struct ib_mad_send_buf **bad_send_buf); -/** - * ib_coalesce_recv_mad - Coalesces received MAD data into a single buffer. - * @mad_recv_wc: Work completion information for a received MAD. - * @buf: User-provided data buffer to receive the coalesced buffers. The - * referenced buffer should be at least the size of the mad_len specified - * by @mad_recv_wc. - * - * This call copies a chain of received MAD segments into a single data buffer, - * removing duplicated headers. - */ -void ib_coalesce_recv_mad(struct ib_mad_recv_wc *mad_recv_wc, void *buf); /** * ib_free_recv_mad - Returns data buffers used to receive a MAD. @@ -590,9 +591,10 @@ int ib_process_mad_wc(struct ib_mad_agent *mad_agent, * with an initialized work request structure. Users may modify the returned * MAD data buffer before posting the send. * - * The returned data buffer will be cleared. Users are responsible for - * initializing the common MAD and any class specific headers. If @rmpp_active - * is set, the RMPP header will be initialized for sending. + * The returned MAD header, class specific headers, and any padding will be + * cleared. Users are responsible for initializing the common MAD header, + * any class specific header, and MAD data area. + * If @rmpp_active is set, the RMPP header will be initialized for sending. */ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, u32 remote_qpn, u16 pkey_index, @@ -600,6 +602,16 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, int hdr_len, int data_len, gfp_t gfp_mask); +/** + * ib_get_rmpp_segment - returns the data buffer for a given RMPP segment. + * @send_buf: Previously allocated send data buffer. + * @seg_num: number of segment to return + * + * This routine returns a pointer to the data buffer of an RMPP MAD. + * Users must provide synchronization to @send_buf around this call. + */ +void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num); + /** * ib_free_send_mad - Returns data buffers used to send a MAD. * @send_buf: Previously allocated send data buffer. -- cgit v1.2.3-59-g8ed1b From 702b2aaccfbf0fa29c6ffb423a39a7a5573f793a Mon Sep 17 00:00:00 2001 From: Ami Perlmutter Date: Mon, 20 Mar 2006 10:08:24 -0800 Subject: IB/uverbs: Use correct alt_pkey_index in modify QP The old code incorrectly used the primary P_Key index as the alternate index too. Signed-off-by: Ami Perlmutter Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 0e0dbc9421bf..9f69bd48eb1b 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1131,7 +1131,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, attr->dest_qp_num = cmd.dest_qp_num; attr->qp_access_flags = cmd.qp_access_flags; attr->pkey_index = cmd.pkey_index; - attr->alt_pkey_index = cmd.pkey_index; + attr->alt_pkey_index = cmd.alt_pkey_index; attr->en_sqd_async_notify = cmd.en_sqd_async_notify; attr->max_rd_atomic = cmd.max_rd_atomic; attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic; -- cgit v1.2.3-59-g8ed1b From 8b9ab02b690e988f19c9d740ef642d7d833d23d5 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 7 Mar 2006 11:21:08 -0800 Subject: IPoIB: Fix build now that neighbour destructor is in neigh_params Fix the IPoIB build (which is broken in net-2.6.17 because of my screw-up, which left out this chunk in ipoib_multicast.c). The neighbour destructor is now in neigh_params, so we don't need to clear it in the ops structure. Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index fde442a1996d..93c462eaf4fd 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -115,7 +115,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) if (neigh->ah) ipoib_put_ah(neigh->ah); *to_ipoib_neigh(neigh->neighbour) = NULL; - neigh->neighbour->ops->destructor = NULL; kfree(neigh); } -- cgit v1.2.3-59-g8ed1b From 0b3ea0829cbcdaee6e018a83a2949ef458213f3b Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Mon, 20 Mar 2006 10:08:24 -0800 Subject: IPoIB: Move ipoib_ib_dev_flush() to ipoib workqueue Move ipoib_ib_dev_flush() to ipoib's workqueue. This keeps it ordered with respect to other work scheduled by the ipoib driver. This fixes problems with races, for example: - ipoib_ib_dev_flush() has started running because of an IB event - user does ifconfig ib0 down - ipoib_mcast_stop_thread() gets called twice and waits for the same completion twice Signed-off-by: Jack Morgenstein Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib.h | 2 +- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 9 +++++---- drivers/infiniband/ulp/ipoib/ipoib_main.c | 8 +++++++- drivers/infiniband/ulp/ipoib/ipoib_verbs.c | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 638eff745b2f..1251f86ec856 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -259,7 +259,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev); int ipoib_ib_dev_open(struct net_device *dev); int ipoib_ib_dev_up(struct net_device *dev); -int ipoib_ib_dev_down(struct net_device *dev); +int ipoib_ib_dev_down(struct net_device *dev, int flush); int ipoib_ib_dev_stop(struct net_device *dev); int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 5a5367d10875..a1f5a05f2f36 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -435,7 +435,7 @@ int ipoib_ib_dev_up(struct net_device *dev) return ipoib_mcast_start_thread(dev); } -int ipoib_ib_dev_down(struct net_device *dev) +int ipoib_ib_dev_down(struct net_device *dev, int flush) { struct ipoib_dev_priv *priv = netdev_priv(dev); @@ -450,10 +450,11 @@ int ipoib_ib_dev_down(struct net_device *dev) set_bit(IPOIB_PKEY_STOP, &priv->flags); cancel_delayed_work(&priv->pkey_task); mutex_unlock(&pkey_mutex); - flush_workqueue(ipoib_workqueue); + if (flush) + flush_workqueue(ipoib_workqueue); } - ipoib_mcast_stop_thread(dev, 1); + ipoib_mcast_stop_thread(dev, flush); ipoib_mcast_dev_flush(dev); ipoib_flush_paths(dev); @@ -591,7 +592,7 @@ void ipoib_ib_dev_flush(void *_dev) ipoib_dbg(priv, "flushing\n"); - ipoib_ib_dev_down(dev); + ipoib_ib_dev_down(dev, 0); /* * The device could have been brought down between the start and when diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index c3b5f79d1168..1633aadae421 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -133,7 +133,13 @@ static int ipoib_stop(struct net_device *dev) netif_stop_queue(dev); - ipoib_ib_dev_down(dev); + /* + * Now flush workqueue to make sure a scheduled task doesn't + * bring our internal state back up. + */ + flush_workqueue(ipoib_workqueue); + + ipoib_ib_dev_down(dev, 1); ipoib_ib_dev_stop(dev); if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index faaf10e5fc7b..18d2f53ec34c 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c @@ -255,6 +255,6 @@ void ipoib_event(struct ib_event_handler *handler, record->event == IB_EVENT_LID_CHANGE || record->event == IB_EVENT_SM_CHANGE) { ipoib_dbg(priv, "Port active event\n"); - schedule_work(&priv->flush_task); + queue_work(ipoib_workqueue, &priv->flush_task); } } -- cgit v1.2.3-59-g8ed1b From 048975ac580a771fc5bb96c6b454cba897ab1a73 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 20 Mar 2006 10:08:25 -0800 Subject: IB: Coverity fixes to sysfs.c Fix two bugs found by coverity: - Memory leak in error path of alloc_group_attrs() - Fencepost error in state_show(): the test should be < ARRAY_SIZE(), not <= ARRAY_SIZE(). Signed-off-by: Roland Dreier --- drivers/infiniband/core/sysfs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 49601bb8475b..15121cb5a1f6 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -112,7 +112,7 @@ static ssize_t state_show(struct ib_port *p, struct port_attribute *unused, return ret; return sprintf(buf, "%d: %s\n", attr.state, - attr.state >= 0 && attr.state <= ARRAY_SIZE(state_name) ? + attr.state >= 0 && attr.state < ARRAY_SIZE(state_name) ? state_name[attr.state] : "UNKNOWN"); } @@ -472,8 +472,10 @@ alloc_group_attrs(ssize_t (*show)(struct ib_port *, goto err; if (snprintf(element->name, sizeof(element->name), - "%d", i) >= sizeof(element->name)) + "%d", i) >= sizeof(element->name)) { + kfree(element); goto err; + } element->attr.attr.name = element->name; element->attr.attr.mode = S_IRUGO; -- cgit v1.2.3-59-g8ed1b From 6b63e3015a69dd8aa5534e23af9f132a021da02e Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 20 Mar 2006 10:08:25 -0800 Subject: IB/mthca: Coverity fix to mthca_init_eq_table() Fix bug found by coverity: the loop body never executed, because it was doing for (i = 0; i < MTHCA_EQ_CMD; ++i), but MTHCA_EQ_CMD is 0. The correct loop bound is MTHCA_NUM_EQ, to loop over all EQs. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_eq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index a44b12dd7952..cbdc348fb689 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -928,7 +928,7 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev) mthca_warn(dev, "MAP_EQ for cmd EQ %d returned status 0x%02x\n", dev->eq_table.eq[MTHCA_EQ_CMD].eqn, status); - for (i = 0; i < MTHCA_EQ_CMD; ++i) + for (i = 0; i < MTHCA_NUM_EQ; ++i) if (mthca_is_memfree(dev)) arbel_eq_req_not(dev, dev->eq_table.eq[i].eqn_mask); else -- cgit v1.2.3-59-g8ed1b From bf17c1c7cc9250d7c3c01b0ae898aefa1853535a Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 20 Mar 2006 10:08:25 -0800 Subject: IB/srp: Coverity fix to srp_parse_options() Fix leak found by Coverity: in the SRP_OPT_DGID case, srp_parse_options() didn't free the result of match_strdup(). Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 89ad29dc88d4..a13dcdf90a4f 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1448,6 +1448,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target) strlcpy(dgid, p + i * 2, 3); target->path.dgid.raw[i] = simple_strtoul(dgid, NULL, 16); } + kfree(p); break; case SRP_OPT_PKEY: -- cgit v1.2.3-59-g8ed1b From dc05980dd736bfbe5b2524b463e5f098e67a64e9 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 20 Mar 2006 10:08:25 -0800 Subject: IB/mad: Fix oopsable race on device removal Fix an oopsable race debugged by Eli Cohen : After removing the port from port_list, ib_mad_port_close flushes port_priv->wq before destroying the special QPs. This means that a completion event could arrive, and queue a new work in this work queue after flush. This patch also removes an unnecessary flush_workqueue(): destroy_workqueue() already includes a flush. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/core/mad.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 16549add8e8f..f7854b65fd55 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -2364,8 +2364,12 @@ static void timeout_sends(void *data) static void ib_mad_thread_completion_handler(struct ib_cq *cq, void *arg) { struct ib_mad_port_private *port_priv = cq->cq_context; + unsigned long flags; - queue_work(port_priv->wq, &port_priv->work); + spin_lock_irqsave(&ib_mad_port_list_lock, flags); + if (!list_empty(&port_priv->port_list)) + queue_work(port_priv->wq, &port_priv->work); + spin_unlock_irqrestore(&ib_mad_port_list_lock, flags); } /* @@ -2677,18 +2681,23 @@ static int ib_mad_port_open(struct ib_device *device, } INIT_WORK(&port_priv->work, ib_mad_completion_handler, port_priv); + spin_lock_irqsave(&ib_mad_port_list_lock, flags); + list_add_tail(&port_priv->port_list, &ib_mad_port_list); + spin_unlock_irqrestore(&ib_mad_port_list_lock, flags); + ret = ib_mad_port_start(port_priv); if (ret) { printk(KERN_ERR PFX "Couldn't start port\n"); goto error9; } - spin_lock_irqsave(&ib_mad_port_list_lock, flags); - list_add_tail(&port_priv->port_list, &ib_mad_port_list); - spin_unlock_irqrestore(&ib_mad_port_list_lock, flags); return 0; error9: + spin_lock_irqsave(&ib_mad_port_list_lock, flags); + list_del_init(&port_priv->port_list); + spin_unlock_irqrestore(&ib_mad_port_list_lock, flags); + destroy_workqueue(port_priv->wq); error8: destroy_mad_qp(&port_priv->qp_info[1]); @@ -2725,11 +2734,9 @@ static int ib_mad_port_close(struct ib_device *device, int port_num) printk(KERN_ERR PFX "Port %d not found\n", port_num); return -ENODEV; } - list_del(&port_priv->port_list); + list_del_init(&port_priv->port_list); spin_unlock_irqrestore(&ib_mad_port_list_lock, flags); - /* Stop processing completions. */ - flush_workqueue(port_priv->wq); destroy_workqueue(port_priv->wq); destroy_mad_qp(&port_priv->qp_info[1]); destroy_mad_qp(&port_priv->qp_info[0]); -- cgit v1.2.3-59-g8ed1b From e10e271bfd295bf805dc294460868e1deb938211 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Mon, 20 Mar 2006 10:08:26 -0800 Subject: IB/mthca: Correct reported SRQ size in MemFree case. MemFree devices need to reserve one shared receive queue (SRQ) work request for internal use, so the capacity returned from the create_srq and query_srq methods should be srq->max - 1. Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_srq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 209d2bae2256..96fcc64c61cd 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -271,7 +271,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, srq->first_free = 0; srq->last_free = srq->max - 1; - attr->max_wr = srq->max; + attr->max_wr = (mthca_is_memfree(dev)) ? srq->max - 1 : srq->max; attr->max_sge = srq->max_gs; return 0; @@ -386,7 +386,7 @@ int mthca_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr) } else srq_attr->srq_limit = 0; - srq_attr->max_wr = srq->max; + srq_attr->max_wr = (mthca_is_memfree(dev)) ? srq->max - 1 : srq->max; srq_attr->max_sge = srq->max_gs; out: -- cgit v1.2.3-59-g8ed1b From bfef73fa78ca1e56175dcbd33aa11de4764f85a5 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 20 Mar 2006 10:08:26 -0800 Subject: IPoIB: Get rid of useless test of queue length In neigh_add_path(), the queue of delayed packets can never be full, because the queue is always freshly created and cannot be found by any other code path. In fact, the test of the queue length is worse than useless: if somehow the test ever triggered and path_rec_start() also failed, then dev_kfree_skb_any() will be called twice on the same skb. Fix this by deleting the useless test. Pointed out by Michael S. Tsirkin . Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 1633aadae421..0ebacd558ff6 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -519,12 +519,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) be32_to_cpup((__be32 *) skb->dst->neighbour->ha)); } else { neigh->ah = NULL; - if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { - __skb_queue_tail(&neigh->queue, skb); - } else { - ++priv->stats.tx_dropped; - dev_kfree_skb_any(skb); - } + __skb_queue_tail(&neigh->queue, skb); if (!path->query && path_rec_start(dev, path)) goto err; -- cgit v1.2.3-59-g8ed1b From fd02e8038eb943755e8727a0ea193c037a51714f Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Mon, 13 Mar 2006 14:33:01 +0200 Subject: IB/mthca: Query SRQ srq_limit fixes Fix endianness handling of srq_limit: it is big-endian in the context structure, so we need to swab it before returning it. Also add support for srq_limit query for Tavor (non-MemFree) HCAs. Signed-off-by: Eli Cohen Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_srq.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 96fcc64c61cd..47a6a754a591 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -49,7 +49,8 @@ struct mthca_tavor_srq_context { __be32 state_pd; __be32 lkey; __be32 uar; - __be32 wqe_cnt; + __be16 limit_watermark; + __be16 wqe_cnt; u32 reserved[2]; }; @@ -369,6 +370,7 @@ int mthca_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr) struct mthca_srq *srq = to_msrq(ibsrq); struct mthca_mailbox *mailbox; struct mthca_arbel_srq_context *arbel_ctx; + struct mthca_tavor_srq_context *tavor_ctx; u8 status; int err; @@ -382,9 +384,11 @@ int mthca_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr) if (mthca_is_memfree(dev)) { arbel_ctx = mailbox->buf; - srq_attr->srq_limit = arbel_ctx->limit_watermark; - } else - srq_attr->srq_limit = 0; + srq_attr->srq_limit = be16_to_cpu(arbel_ctx->limit_watermark); + } else { + tavor_ctx = mailbox->buf; + srq_attr->srq_limit = be16_to_cpu(tavor_ctx->limit_watermark); + } srq_attr->max_wr = (mthca_is_memfree(dev)) ? srq->max - 1 : srq->max; srq_attr->max_sge = srq->max_gs; -- cgit v1.2.3-59-g8ed1b From 8075f21fc6dac8fb16372a7d4e28d9f21077cdda Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 20 Mar 2006 20:21:24 +0100 Subject: SCSI_AACRAID: add a help text Most of the text by Mark Salyzyn . Signed-off-by: Adrian Bunk Acked-by: Mark Salyzyn --- drivers/scsi/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 3c606cf8c8ca..5c94a5d4efc0 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -379,6 +379,14 @@ config SCSI_AHA1740 config SCSI_AACRAID tristate "Adaptec AACRAID support" depends on SCSI && PCI + help + This driver supports a variety of Dell, HP, Adaptec, IBM and + ICP storage products. For a list of supported products, refer + to . + + To compile this driver as a module, choose M here: the module + will be called aacraid. + source "drivers/scsi/aic7xxx/Kconfig.aic7xxx" -- cgit v1.2.3-59-g8ed1b From 7b9af3455b9edb3ca8efb251bd9d2d51ecb0066c Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 20 Mar 2006 20:23:13 +0100 Subject: remove dead Radeon URL This patch removes a dead Radeon URL from two Kconfig files. This isue was noted by Reto Gantenbein in Kernel Bugzilla #4446. Signed-off-by: Adrian Bunk --- drivers/char/drm/Kconfig | 4 ++-- drivers/video/Kconfig | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig index 56ace9d5e2ae..5278c388d3e7 100644 --- a/drivers/char/drm/Kconfig +++ b/drivers/char/drm/Kconfig @@ -37,8 +37,8 @@ config DRM_RADEON help Choose this option if you have an ATI Radeon graphics card. There are both PCI and AGP versions. You don't need to choose this to - run the Radeon in plain VGA mode. There is a product page at - . + run the Radeon in plain VGA mode. + If M is selected, the module will be called radeon. config DRM_I810 diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index f5079c78ba4e..fdebd60a3250 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -899,8 +899,6 @@ config FB_RADEON_OLD Choose this option if you want to use an ATI Radeon graphics card as a framebuffer device. There are both PCI and AGP versions. You don't need to choose this to run the Radeon in plain VGA mode. - There is a product page at - . config FB_RADEON tristate "ATI Radeon display support" -- cgit v1.2.3-59-g8ed1b From d358788f3f30113e49882187d794832905e42592 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Mar 2006 20:00:09 +0000 Subject: [SERIAL] kernel console should send CRLF not LFCR Glen Turner reported that writing LFCR rather than the more traditional CRLF causes issues with some terminals. Since this aflicts many serial drivers, extract the common code to a library function (uart_console_write) and arrange for each driver to supply a "putchar" function. Signed-off-by: Russell King --- drivers/serial/21285.c | 19 +++++++------------ drivers/serial/8250.c | 26 +++++++++----------------- drivers/serial/8250_early.c | 9 ++------- drivers/serial/amba-pl010.c | 24 ++++++++---------------- drivers/serial/amba-pl011.c | 20 +++++--------------- drivers/serial/at91_serial.c | 24 ++++++++---------------- drivers/serial/au1x00_uart.c | 26 +++++++++----------------- drivers/serial/clps711x.c | 24 ++++++++---------------- drivers/serial/dz.c | 12 +++++------- drivers/serial/imx.c | 26 +++++++++----------------- drivers/serial/ip22zilog.c | 11 +++-------- drivers/serial/m32r_sio.c | 26 +++++++++----------------- drivers/serial/mpc52xx_uart.c | 11 +++++------ drivers/serial/pmac_zilog.c | 23 +++++++++++------------ drivers/serial/pxa.c | 26 +++++++++----------------- drivers/serial/s3c2410.c | 26 ++++++++++---------------- drivers/serial/sa1100.c | 26 ++++++++++---------------- drivers/serial/serial_core.c | 21 +++++++++++++++++++++ drivers/serial/serial_lh7a40x.c | 17 +++++++---------- drivers/serial/serial_txx9.c | 26 +++++++++----------------- drivers/serial/sunsab.c | 10 +++------- drivers/serial/sunsu.c | 26 +++++++++----------------- drivers/serial/sunzilog.c | 13 ++++--------- drivers/serial/vr41xx_siu.c | 16 +++++++--------- include/linux/serial_core.h | 3 +++ 25 files changed, 190 insertions(+), 301 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 8c5c276c5577..7572665a8855 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -375,23 +375,18 @@ static void serial21285_setup_ports(void) } #ifdef CONFIG_SERIAL_21285_CONSOLE +static void serial21285_console_putchar(struct uart_port *port, int ch) +{ + while (*CSR_UARTFLG & 0x20) + barrier(); + *CSR_UARTDR = ch; +} static void serial21285_console_write(struct console *co, const char *s, unsigned int count) { - int i; - - for (i = 0; i < count; i++) { - while (*CSR_UARTFLG & 0x20) - barrier(); - *CSR_UARTDR = s[i]; - if (s[i] == '\n') { - while (*CSR_UARTFLG & 0x20) - barrier(); - *CSR_UARTDR = '\r'; - } - } + uart_console_write(&serial21285_port, s, count, serial21285_console_putchar); } static void __init diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 7aca22c9976d..5996d3cd0ed8 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2182,6 +2182,14 @@ static inline void wait_for_xmitr(struct uart_8250_port *up, int bits) } } +static void serial8250_console_putchar(struct uart_port *port, int ch) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + + wait_for_xmitr(up, UART_LSR_THRE); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -2193,7 +2201,6 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) { struct uart_8250_port *up = &serial8250_ports[co->index]; unsigned int ier; - int i; touch_nmi_watchdog(); @@ -2207,22 +2214,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) else serial_out(up, UART_IER, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up, UART_LSR_THRE); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up, UART_LSR_THRE); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, serial8250_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index 59ba5d993b4b..7e511199b4c5 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c @@ -74,7 +74,7 @@ static void __init wait_for_xmitr(struct uart_port *port) } } -static void __init putc(struct uart_port *port, unsigned char c) +static void __init putc(struct uart_port *port, int c) { wait_for_xmitr(port); serial_out(port, UART_TX, c); @@ -89,12 +89,7 @@ static void __init early_uart_write(struct console *console, const char *s, unsi ier = serial_in(port, UART_IER); serial_out(port, UART_IER, 0); - while (*s && count-- > 0) { - putc(port, *s); - if (*s == '\n') - putc(port, '\r'); - s++; - } + uart_console_write(port, s, count, putc); /* Wait for transmitter to become empty and restore the IER */ wait_for_xmitr(port); diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 321a3b3a5728..e04d5e82d9ae 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -591,12 +591,18 @@ static struct uart_amba_port amba_ports[UART_NR] = { #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE +static void pl010_console_putchar(struct uart_port *port, int ch) +{ + while (!UART_TX_READY(UART_GET_FR(port))) + barrier(); + UART_PUT_CHAR(port, ch); +} + static void pl010_console_write(struct console *co, const char *s, unsigned int count) { struct uart_port *port = &amba_ports[co->index].port; unsigned int status, old_cr; - int i; /* * First save the CR then disable the interrupts @@ -604,21 +610,7 @@ pl010_console_write(struct console *co, const char *s, unsigned int count) old_cr = UART_GET_CR(port); UART_PUT_CR(port, UART01x_CR_UARTEN); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_FR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_FR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, '\r'); - } - } + uart_console_write(port, s, count, pl010_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 034a029e356e..3d966cfc9a38 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -587,14 +587,12 @@ static struct uart_amba_port *amba_ports[UART_NR]; #ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE -static inline void -pl011_console_write_char(struct uart_amba_port *uap, char ch) +static void pl011_console_putchar(struct uart_port *port, int ch) { - unsigned int status; + struct uart_amba_port *uap = (struct uart_amba_port *)port; - do { - status = readw(uap->port.membase + UART01x_FR); - } while (status & UART01x_FR_TXFF); + while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) + barrier(); writew(ch, uap->port.membase + UART01x_DR); } @@ -603,7 +601,6 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) { struct uart_amba_port *uap = amba_ports[co->index]; unsigned int status, old_cr, new_cr; - int i; clk_enable(uap->clk); @@ -615,14 +612,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; writew(new_cr, uap->port.membase + UART011_CR); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - pl011_console_write_char(uap, s[i]); - if (s[i] == '\n') - pl011_console_write_char(uap, '\r'); - } + uart_console_write(&uap->port, s, count, pl011_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c index 2113feb75c39..6547fe0cef96 100644 --- a/drivers/serial/at91_serial.c +++ b/drivers/serial/at91_serial.c @@ -711,6 +711,12 @@ void __init at91_register_uart(int idx, int port) } #ifdef CONFIG_SERIAL_AT91_CONSOLE +static void at91_console_putchar(struct uart_port *port, int ch) +{ + while (!(UART_GET_CSR(port) & AT91_US_TXRDY)) + barrier(); + UART_PUT_CHAR(port, ch); +} /* * Interrupts are disabled on entering @@ -718,7 +724,7 @@ void __init at91_register_uart(int idx, int port) static void at91_console_write(struct console *co, const char *s, u_int count) { struct uart_port *port = at91_ports + co->index; - unsigned int status, i, imr; + unsigned int status, imr; /* * First, save IMR and then disable interrupts @@ -726,21 +732,7 @@ static void at91_console_write(struct console *co, const char *s, u_int count) imr = UART_GET_IMR(port); /* get interrupt mask */ UART_PUT_IDR(port, AT91_US_RXRDY | AT91_US_TXRDY); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_CSR(port); - } while (!(status & AT91_US_TXRDY)); - UART_PUT_CHAR(port, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_CSR(port); - } while (!(status & AT91_US_TXRDY)); - UART_PUT_CHAR(port, '\r'); - } - } + uart_console_write(port, s, count, at91_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index 344022fe53ef..29f94bbb79be 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c @@ -1121,6 +1121,14 @@ static inline void wait_for_xmitr(struct uart_8250_port *up) } } +static void au1x00_console_putchar(struct uart_port *port, int ch) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + + wait_for_xmitr(up); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1132,7 +1140,6 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) { struct uart_8250_port *up = &serial8250_ports[co->index]; unsigned int ier; - int i; /* * First save the UER then disable the interrupts @@ -1140,22 +1147,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) ier = serial_in(up, UART_IER); serial_out(up, UART_IER, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, au1x00_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index ce7b2e4ecd17..2691112c84ad 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -424,6 +424,13 @@ static struct uart_port clps711x_ports[UART_NR] = { }; #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE +static void clps711xuart_console_putchar(struct uart_port *port, int ch) +{ + while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF) + barrier(); + clps_writel(ch, UARTDR(port)); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -438,7 +445,6 @@ clps711xuart_console_write(struct console *co, const char *s, { struct uart_port *port = clps711x_ports + co->index; unsigned int status, syscon; - int i; /* * Ensure that the port is enabled. @@ -446,21 +452,7 @@ clps711xuart_console_write(struct console *co, const char *s, syscon = clps_readl(SYSCON(port)); clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = clps_readl(SYSFLG(port)); - } while (status & SYSFLG_UTXFF); - clps_writel(s[i], UARTDR(port)); - if (s[i] == '\n') { - do { - status = clps_readl(SYSFLG(port)); - } while (status & SYSFLG_UTXFF); - clps_writel('\r', UARTDR(port)); - } - } + uart_console_write(port, s, count, clps711xuart_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index ba5541de673b..bf71bad5c34f 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -674,11 +674,12 @@ static void dz_reset(struct dz_port *dport) } #ifdef CONFIG_SERIAL_DZ_CONSOLE -static void dz_console_put_char(struct dz_port *dport, unsigned char ch) +static void dz_console_putchar(struct uart_port *port, int ch) { + struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; int loops = 2500; - unsigned short tmp = ch; + unsigned short tmp = (unsigned char)ch; /* this code sends stuff out to serial device - spinning its wheels and waiting. */ @@ -694,6 +695,7 @@ static void dz_console_put_char(struct dz_port *dport, unsigned char ch) spin_unlock_irqrestore(&dport->port.lock, flags); } + /* * ------------------------------------------------------------------- * dz_console_print () @@ -710,11 +712,7 @@ static void dz_console_print(struct console *cons, #ifdef DEBUG_DZ prom_printf((char *) str); #endif - while (count--) { - if (*str == '\n') - dz_console_put_char(dport, '\r'); - dz_console_put_char(dport, *str++); - } + uart_console_write(&dport->port, str, count, dz_console_putchar); } static int __init dz_console_setup(struct console *co, char *options) diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 4d53fb5ca87b..c3b7a6673e9c 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -743,6 +743,13 @@ static void __init imx_init_ports(void) } #ifdef CONFIG_SERIAL_IMX_CONSOLE +static void imx_console_putchar(struct uart_port *port, int ch) +{ + struct imx_port *sport = (struct imx_port *)port; + while ((UTS((u32)sport->port.membase) & UTS_TXFULL)) + barrier(); + URTX0((u32)sport->port.membase) = ch; +} /* * Interrupts are disabled on entering @@ -751,7 +758,7 @@ static void imx_console_write(struct console *co, const char *s, unsigned int count) { struct imx_port *sport = &imx_ports[co->index]; - unsigned int old_ucr1, old_ucr2, i; + unsigned int old_ucr1, old_ucr2; /* * First, save UCR1/2 and then disable interrupts @@ -764,22 +771,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count) & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN; - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - - while ((UTS((u32)sport->port.membase) & UTS_TXFULL)) - barrier(); - - URTX0((u32)sport->port.membase) = s[i]; - - if (s[i] == '\n') { - while ((UTS((u32)sport->port.membase) & UTS_TXFULL)) - barrier(); - URTX0((u32)sport->port.membase) = '\r'; - } - } + uart_console_write(&sport->port, s, count, imx_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index 193722d680cf..651772474ac1 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -967,8 +967,9 @@ static struct zilog_layout * __init get_zs(int chip) #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ #ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE -static void ip22zilog_put_char(struct zilog_channel *channel, unsigned char ch) +static void ip22zilog_put_char(struct uart_port *port, int ch) { + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); int loops = ZS_PUT_CHAR_MAX_DELAY; /* This is a timed polling loop so do not switch the explicit @@ -992,16 +993,10 @@ static void ip22zilog_console_write(struct console *con, const char *s, unsigned int count) { struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index]; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); unsigned long flags; - int i; spin_lock_irqsave(&up->port.lock, flags); - for (i = 0; i < count; i++, s++) { - ip22zilog_put_char(channel, *s); - if (*s == 10) - ip22zilog_put_char(channel, 13); - } + uart_console_write(&up->port, s, count, ip22zilog_put_char); udelay(2); spin_unlock_irqrestore(&up->port.lock, flags); } diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 242a04104393..876bc5e027bb 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -1039,6 +1039,14 @@ static inline void wait_for_xmitr(struct uart_sio_port *up) } } +static void m32r_sio_console_putchar(struct uart_port *port, int ch) +{ + struct uart_sio_port *up = (struct uart_sio_port *)port; + + wait_for_xmitr(up); + sio_out(up, SIOTXB, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1058,23 +1066,7 @@ static void m32r_sio_console_write(struct console *co, const char *s, ier = sio_in(up, SIOTRCR); sio_out(up, SIOTRCR, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - sio_out(up, SIOTXB, *s); - - if (*s == 10) { - wait_for_xmitr(up); - sio_out(up, SIOTXB, 13); - } - } + uart_console_write(&up->port, s, count, m32r_sio_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 61dd17d7bace..928e6cf12dca 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -603,15 +603,14 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count) udelay(1); /* Write all the chars */ - for ( i=0 ; impc52xx_psc_buffer_8, *s); - + for (i = 0; i < count; i++, s++) { /* Line return handling */ - if ( *s++ == '\n' ) + if (*s == '\n') out_8(&psc->mpc52xx_psc_buffer_8, '\r'); + /* Send the char */ + out_8(&psc->mpc52xx_psc_buffer_8, *s); + /* Wait the TX buffer to be empty */ j = 20000; /* Maximum wait */ while (!(in_be16(&psc->mpc52xx_psc_status) & diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 9b7ed58cb53b..513ff8597707 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1916,6 +1916,16 @@ static void __exit exit_pmz(void) #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE +static void pmz_console_putchar(struct uart_port *port, int ch) +{ + struct uart_pmac_port *uap = (struct uart_pmac_port *)port; + + /* Wait for the transmit buffer to empty. */ + while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) + udelay(5); + write_zsdata(uap, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1924,7 +1934,6 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c { struct uart_pmac_port *uap = &pmz_ports[con->index]; unsigned long flags; - int i; if (ZS_IS_ASLEEP(uap)) return; @@ -1934,17 +1943,7 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB); write_zsreg(uap, R5, uap->curregs[5] | TxENABLE | RTS | DTR); - for (i = 0; i < count; i++) { - /* Wait for the transmit buffer to empty. */ - while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) - udelay(5); - write_zsdata(uap, s[i]); - if (s[i] == 10) { - while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) - udelay(5); - write_zsdata(uap, R13); - } - } + uart_console_write(&uap->port, s, count, pmz_console_putchar); /* Restore the values in the registers. */ write_zsreg(uap, R1, uap->curregs[1]); diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 10535f00301f..77d4568ccc3a 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -619,6 +619,14 @@ static inline void wait_for_xmitr(struct uart_pxa_port *up) } } +static void serial_pxa_console_putchar(struct uart_port *port, int ch) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + + wait_for_xmitr(up); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -630,7 +638,6 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) { struct uart_pxa_port *up = &serial_pxa_ports[co->index]; unsigned int ier; - int i; /* * First save the IER then disable the interrupts @@ -638,22 +645,7 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) ier = serial_in(up, UART_IER); serial_out(up, UART_IER, UART_IER_UUE); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, serial_pxa_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 7410e093a6b9..e4d701239702 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -1584,25 +1584,19 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) } static void -s3c24xx_serial_console_write(struct console *co, const char *s, - unsigned int count) +s3c24xx_serial_console_putchar(struct uart_port *port, int ch) { - int i; unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); + while (!s3c24xx_serial_console_txrdy(port, ufcon)) + barrier(); + wr_regb(cons_uart, S3C2410_UTXH, ch); +} - for (i = 0; i < count; i++) { - while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon)) - barrier(); - - wr_regb(cons_uart, S3C2410_UTXH, s[i]); - - if (s[i] == '\n') { - while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon)) - barrier(); - - wr_regb(cons_uart, S3C2410_UTXH, '\r'); - } - } +static void +s3c24xx_serial_console_write(struct console *co, const char *s, + unsigned int count) +{ + uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar); } static void __init diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 2c00b8625852..c2d9068b491d 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -689,6 +689,14 @@ void __init sa1100_register_uart(int idx, int port) #ifdef CONFIG_SERIAL_SA1100_CONSOLE +static void sa1100_console_putchar(struct uart_port *port, int ch) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + + while (!(UART_GET_UTSR1(sport) & UTSR1_TNF)) + barrier(); + UART_PUT_CHAR(sport, ch); +} /* * Interrupts are disabled on entering @@ -697,7 +705,7 @@ static void sa1100_console_write(struct console *co, const char *s, unsigned int count) { struct sa1100_port *sport = &sa1100_ports[co->index]; - unsigned int old_utcr3, status, i; + unsigned int old_utcr3, status; /* * First, save UTCR3 and then disable interrupts @@ -706,21 +714,7 @@ sa1100_console_write(struct console *co, const char *s, unsigned int count) UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) | UTCR3_TXE); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_UTSR1(sport); - } while (!(status & UTSR1_TNF)); - UART_PUT_CHAR(sport, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_UTSR1(sport); - } while (!(status & UTSR1_TNF)); - UART_PUT_CHAR(sport, '\r'); - } - } + uart_console_write(&sport->port, s, count, sa1100_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index cc1faa31d124..fcd7744c4253 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1754,6 +1754,27 @@ static int uart_read_proc(char *page, char **start, off_t off, #endif #ifdef CONFIG_SERIAL_CORE_CONSOLE +/* + * uart_console_write - write a console message to a serial port + * @port: the port to write the message + * @s: array of characters + * @count: number of characters in string to write + * @write: function to write character to port + */ +void uart_console_write(struct uart_port *port, const char *s, + unsigned int count, + void (*putchar)(struct uart_port *, int)) +{ + unsigned int i; + + for (i = 0; i < count; i++, s++) { + if (*s == '\n') + putchar(port, '\r'); + putchar(port, *s); + } +} +EXPORT_SYMBOL_GPL(uart_console_write); + /* * Check whether an invalid uart number has been specified, and * if so, search for the first available port that does have diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 04186eaae227..aa521b8e0d4e 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -543,6 +543,12 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { #else # define LH7A40X_CONSOLE &lh7a40x_console +static void lh7a40xuart_console_putchar(struct uart_port *port, int ch) +{ + while (UR(port, UART_R_STATUS) & nTxRdy) + ; + UR(port, UART_R_DATA) = ch; +} static void lh7a40xuart_console_write (struct console* co, const char* s, @@ -556,16 +562,7 @@ static void lh7a40xuart_console_write (struct console* co, UR (port, UART_R_INTEN) = 0; /* Disable all interrupts */ BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */ - for (; count-- > 0; ++s) { - while (UR (port, UART_R_STATUS) & nTxRdy) - ; - UR (port, UART_R_DATA) = *s; - if (*s == '\n') { - while ((UR (port, UART_R_STATUS) & TxBusy)) - ; - UR (port, UART_R_DATA) = '\r'; - } - } + uart_console_write(port, s, count, lh7a40xuart_console_putchar); /* Wait until all characters are sent */ while (UR (port, UART_R_STATUS) & TxBusy) diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index ee98a867bc6d..1a259cee1a98 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -854,6 +854,14 @@ static inline void wait_for_xmitr(struct uart_txx9_port *up) } } +static void serial_txx9_console_putchar(struct uart_port *port, int ch) +{ + struct uart_txx9_port *up = (struct uart_txx9_port *)port; + + wait_for_xmitr(up); + sio_out(up, TXX9_SITFIFO, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -865,7 +873,6 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count) { struct uart_txx9_port *up = &serial_txx9_ports[co->index]; unsigned int ier, flcr; - int i; /* * First save the UER then disable the interrupts @@ -879,22 +886,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count) if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES)) sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - sio_out(up, TXX9_SITFIFO, *s); - if (*s == 10) { - wait_for_xmitr(up); - sio_out(up, TXX9_SITFIFO, 13); - } - } + uart_console_write(&up->port, s, count, serial_txx9_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 85664228a0b6..be95eabd0394 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -861,8 +861,9 @@ static int num_channels; #ifdef CONFIG_SERIAL_SUNSAB_CONSOLE -static __inline__ void sunsab_console_putchar(struct uart_sunsab_port *up, char c) +static void sunsab_console_putchar(struct uart_port *port, int c) { + struct uart_sunsab_port *up = (struct uart_sunsab_port *)port; unsigned long flags; spin_lock_irqsave(&up->port.lock, flags); @@ -876,13 +877,8 @@ static __inline__ void sunsab_console_putchar(struct uart_sunsab_port *up, char static void sunsab_console_write(struct console *con, const char *s, unsigned n) { struct uart_sunsab_port *up = &sunsab_ports[con->index]; - int i; - for (i = 0; i < n; i++) { - if (*s == '\n') - sunsab_console_putchar(up, '\r'); - sunsab_console_putchar(up, *s++); - } + uart_console_write(&up->port, s, n, sunsab_console_putchar); sunsab_tec_wait(up); } diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 4e453fa966ae..9ca1d8b9364b 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1376,6 +1376,14 @@ static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up) } } +static void sunsu_console_putchar(struct uart_port *port, int ch) +{ + struct uart_sunsu_port *up = (struct uart_sunsu_port *)port; + + wait_for_xmitr(up); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1385,7 +1393,6 @@ static void sunsu_console_write(struct console *co, const char *s, { struct uart_sunsu_port *up = &sunsu_ports[co->index]; unsigned int ier; - int i; /* * First save the UER then disable the interrupts @@ -1393,22 +1400,7 @@ static void sunsu_console_write(struct console *co, const char *s, ier = serial_in(up, UART_IER); serial_out(up, UART_IER, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, sunsu_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 5cc4d4c2935c..b0c46b9a5930 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1252,8 +1252,9 @@ static struct zilog_layout __iomem * __init get_zs(int chip, int node) #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ -static void sunzilog_put_char(struct zilog_channel __iomem *channel, unsigned char ch) +static void sunzilog_putchar(struct uart_port *port, int ch) { + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); int loops = ZS_PUT_CHAR_MAX_DELAY; /* This is a timed polling loop so do not switch the explicit @@ -1284,7 +1285,7 @@ static int sunzilog_serio_write(struct serio *serio, unsigned char ch) spin_lock_irqsave(&sunzilog_serio_lock, flags); - sunzilog_put_char(ZILOG_CHANNEL_FROM_PORT(&up->port), ch); + sunzilog_putchar(&up->port, ch); spin_unlock_irqrestore(&sunzilog_serio_lock, flags); @@ -1325,16 +1326,10 @@ static void sunzilog_console_write(struct console *con, const char *s, unsigned int count) { struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); unsigned long flags; - int i; spin_lock_irqsave(&up->port.lock, flags); - for (i = 0; i < count; i++, s++) { - sunzilog_put_char(channel, *s); - if (*s == 10) - sunzilog_put_char(channel, 13); - } + uart_console_write(&up->port, s, count, sunzilog_putchar); udelay(2); spin_unlock_irqrestore(&up->port.lock, flags); } diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index d61494d185cd..3f88b8e81937 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -821,25 +821,23 @@ static void wait_for_xmitr(struct uart_port *port) } } +static void siu_console_putchar(struct uart_port *port, int ch) +{ + wait_for_xmitr(port); + siu_write(port, UART_TX, ch); +} + static void siu_console_write(struct console *con, const char *s, unsigned count) { struct uart_port *port; uint8_t ier; - unsigned i; port = &siu_uart_ports[con->index]; ier = siu_read(port, UART_IER); siu_write(port, UART_IER, 0); - for (i = 0; i < count && *s != '\0'; i++, s++) { - wait_for_xmitr(port); - siu_write(port, UART_TX, *s); - if (*s == '\n') { - wait_for_xmitr(port); - siu_write(port, UART_TX, '\r'); - } - } + uart_console_write(port, s, count, siu_console_putchar); wait_for_xmitr(port); siu_write(port, UART_IER, ier); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 4041122dabfc..f7434e5086f5 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -366,6 +366,9 @@ void uart_parse_options(char *options, int *baud, int *parity, int *bits, int uart_set_options(struct uart_port *port, struct console *co, int baud, int parity, int bits, int flow); struct tty_driver *uart_console_device(struct console *co, int *index); +void uart_console_write(struct uart_port *port, const char *s, + unsigned int count, + void (*putchar)(struct uart_port *, int)); /* * Port/driver registration/removal -- cgit v1.2.3-59-g8ed1b From 91bca4b3e2f1aaaf67e62a36914f33ca1e7d5a06 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 20 Mar 2006 20:08:22 +0000 Subject: [SERIAL] Merge avlab serial board entries in parport_serial As can be seen from this patch, the avlab_*_[68]50 table entries are identical to the plain avlab_* entries in every respect. Hence, there is no need to list them separately in the pciserial_board nor parport_pc_pci card tables - they can re-use the plain avlab_* entries. Signed-off-by: Russell King --- drivers/parport/parport_serial.c | 75 ++++++++++------------------------------ 1 file changed, 18 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index 10845253c9e0..d121644646b9 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c @@ -31,14 +31,8 @@ enum parport_pc_pci_cards { netmos_9xx5_combo, netmos_9855, avlab_1s1p, - avlab_1s1p_650, - avlab_1s1p_850, avlab_1s2p, - avlab_1s2p_650, - avlab_1s2p_850, avlab_2s1p, - avlab_2s1p_650, - avlab_2s1p_850, siig_1s1p_10x, siig_2s1p_10x, siig_2p1s_20x, @@ -85,14 +79,8 @@ static struct parport_pc_pci cards[] __devinitdata = { /* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init }, /* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init }, /* avlab_1s1p */ { 1, { { 1, 2}, } }, - /* avlab_1s1p_650 */ { 1, { { 1, 2}, } }, - /* avlab_1s1p_850 */ { 1, { { 1, 2}, } }, /* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} }, - /* avlab_1s2p_650 */ { 2, { { 1, 2}, { 3, 4 },} }, - /* avlab_1s2p_850 */ { 2, { { 1, 2}, { 3, 4 },} }, /* avlab_2s1p */ { 1, { { 2, 3}, } }, - /* avlab_2s1p_650 */ { 1, { { 2, 3}, } }, - /* avlab_2s1p_850 */ { 1, { { 2, 3}, } }, /* siig_1s1p_10x */ { 1, { { 3, 4 }, } }, /* siig_2s1p_10x */ { 1, { { 4, 5 }, } }, /* siig_2p1s_20x */ { 2, { { 1, 2 }, { 3, 4 }, } }, @@ -119,15 +107,24 @@ static struct pci_device_id parport_serial_pci_tbl[] = { { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855, PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 }, /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ - { 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p}, - { 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650}, - { 0x14db, 0x2112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_850}, - { 0x14db, 0x2140, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p}, - { 0x14db, 0x2141, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_650}, - { 0x14db, 0x2142, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_850}, - { 0x14db, 0x2160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p}, - { 0x14db, 0x2161, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_650}, - { 0x14db, 0x2162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_850}, + { PCI_VENDOR_ID_AFAVLAB, 0x2110, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2111, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2112, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2140, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2141, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2142, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2160, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2161, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2162, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650, @@ -201,54 +198,18 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = { .base_baud = 115200, .uart_offset = 8, }, - [avlab_1s1p_650] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 1, - .base_baud = 115200, - .uart_offset = 8, - }, - [avlab_1s1p_850] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 1, - .base_baud = 115200, - .uart_offset = 8, - }, [avlab_1s2p] = { /* n/t */ .flags = FL_BASE0 | FL_BASE_BARS, .num_ports = 1, .base_baud = 115200, .uart_offset = 8, }, - [avlab_1s2p_650] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 1, - .base_baud = 115200, - .uart_offset = 8, - }, - [avlab_1s2p_850] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 1, - .base_baud = 115200, - .uart_offset = 8, - }, [avlab_2s1p] = { /* n/t */ .flags = FL_BASE0 | FL_BASE_BARS, .num_ports = 2, .base_baud = 115200, .uart_offset = 8, }, - [avlab_2s1p_650] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 2, - .base_baud = 115200, - .uart_offset = 8, - }, - [avlab_2s1p_850] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 2, - .base_baud = 115200, - .uart_offset = 8, - }, [siig_1s1p_10x] = { .flags = FL_BASE2, .num_ports = 1, -- cgit v1.2.3-59-g8ed1b From 972de6c8bfd8b36618563be454df1e95a36dc379 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Mar 2006 13:17:13 -0800 Subject: [PATCH] Mark empty release functions as broken Come on people, this is just wrong... Signed-off-by: Greg Kroah-Hartman --- drivers/video/epson1355fb.c | 1 + drivers/video/vfb.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 3b0e71383448..082759447bf6 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -607,6 +607,7 @@ static void clearfb16(struct fb_info *info) static void epson1355fb_platform_release(struct device *device) { + dev_err(device, "This driver is broken, please bug the authors so they will fix it.\n"); } static int epson1355fb_remove(struct platform_device *dev) diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 53208cb58396..77eed1fd9943 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -401,6 +401,7 @@ static int __init vfb_setup(char *options) static void vfb_platform_release(struct device *device) { // This is called when the reference count goes to zero. + dev_err(device, "This driver is broken, please bug the authors so they will fix it.\n"); } static int __init vfb_probe(struct platform_device *dev) -- cgit v1.2.3-59-g8ed1b From 305b3228f9ff4d59f49e6d34a7034d44ee8ce2f0 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Thu, 19 Jan 2006 17:52:27 +0000 Subject: [PATCH] driver core: platform_get_irq*(): return -ENXIO on error platform_get_irq*() cannot return 0 on error as 0 is a valid IRQ on some platforms, return -ENXIO instead. Signed-off-by: David Vrabel Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 461554a02517..89b268321321 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -61,7 +61,7 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) { struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); - return r ? r->start : 0; + return r ? r->start : -ENXIO; } EXPORT_SYMBOL_GPL(platform_get_irq); @@ -98,7 +98,7 @@ int platform_get_irq_byname(struct platform_device *dev, char *name) { struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name); - return r ? r->start : 0; + return r ? r->start : -ENXIO; } EXPORT_SYMBOL_GPL(platform_get_irq_byname); -- cgit v1.2.3-59-g8ed1b From 489447380a2921ec0e9154f773c44ab3167ede4b Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Thu, 19 Jan 2006 17:56:29 +0000 Subject: [PATCH] handle errors returned by platform_get_irq*() platform_get_irq*() now returns on -ENXIO when the resource cannot be found. Ensure all users of platform_get_irq*() handle this error appropriately. Signed-off-by: David Vrabel Signed-off-by: Greg Kroah-Hartman --- arch/arm/common/locomo.c | 2 ++ arch/arm/common/sa1111.c | 2 ++ drivers/char/s3c2410-rtc.c | 4 ++-- drivers/char/watchdog/mpcore_wdt.c | 4 ++++ drivers/i2c/busses/i2c-iop3xx.c | 9 +++++++-- drivers/i2c/busses/i2c-mpc.c | 5 +++++ drivers/i2c/busses/i2c-mv64xxx.c | 4 ++++ drivers/ide/mips/au1xxx-ide.c | 5 +++++ drivers/mmc/pxamci.c | 2 +- drivers/net/arm/am79c961a.c | 4 +++- drivers/net/fs_enet/mac-fcc.c | 2 ++ drivers/net/fs_enet/mac-fec.c | 2 ++ drivers/net/fs_enet/mac-scc.c | 2 ++ drivers/net/gianfar.c | 4 ++++ drivers/net/smc91x.c | 4 ++++ drivers/pcmcia/omap_cf.c | 2 +- drivers/serial/s3c2410.c | 2 ++ drivers/usb/host/ohci-omap.c | 9 +++++++-- drivers/video/sa1100fb.c | 2 +- 19 files changed, 60 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index d31b1cb7eea0..23609400a8e2 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -788,6 +788,8 @@ static int locomo_probe(struct platform_device *dev) if (!mem) return -EINVAL; irq = platform_get_irq(dev, 0); + if (irq < 0) + return -ENXIO; return __locomo_probe(&dev->dev, mem, irq); } diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 1475089f9b42..93352f6097c1 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -943,6 +943,8 @@ static int sa1111_probe(struct platform_device *pdev) if (!mem) return -EINVAL; irq = platform_get_irq(pdev, 0); + if (irq < 0) + return -ENXIO; return __sa1111_probe(&pdev->dev, mem, irq); } diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c index 2e308657f6f6..b0038b19b505 100644 --- a/drivers/char/s3c2410-rtc.c +++ b/drivers/char/s3c2410-rtc.c @@ -448,13 +448,13 @@ static int s3c2410_rtc_probe(struct platform_device *pdev) /* find the IRQs */ s3c2410_rtc_tickno = platform_get_irq(pdev, 1); - if (s3c2410_rtc_tickno <= 0) { + if (s3c2410_rtc_tickno < 0) { dev_err(&pdev->dev, "no irq for rtc tick\n"); return -ENOENT; } s3c2410_rtc_alarmno = platform_get_irq(pdev, 0); - if (s3c2410_rtc_alarmno <= 0) { + if (s3c2410_rtc_alarmno < 0) { dev_err(&pdev->dev, "no irq for alarm\n"); return -ENOENT; } diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c index b4d843489881..2c2c51773200 100644 --- a/drivers/char/watchdog/mpcore_wdt.c +++ b/drivers/char/watchdog/mpcore_wdt.c @@ -338,6 +338,10 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) wdt->dev = &dev->dev; wdt->irq = platform_get_irq(dev, 0); + if (wdt->irq < 0) { + ret = -ENXIO; + goto err_free; + } wdt->base = ioremap(res->start, res->end - res->start + 1); if (!wdt->base) { ret = -ENOMEM; diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 1414851a17b8..d00a02fc23e4 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -434,7 +434,7 @@ static int iop3xx_i2c_probe(struct platform_device *pdev) { struct resource *res; - int ret; + int ret, irq; struct i2c_adapter *new_adapter; struct i2c_algo_iop3xx_data *adapter_data; @@ -470,7 +470,12 @@ iop3xx_i2c_probe(struct platform_device *pdev) goto release_region; } - ret = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0, + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + ret = -ENXIO; + goto unmap; + } + ret = request_irq(irq, iop3xx_i2c_irq_handler, 0, pdev->name, adapter_data); if (ret) { diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 5ccd338a9dc9..2721e4c8184a 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -302,6 +302,10 @@ static int fsl_i2c_probe(struct platform_device *pdev) } i2c->irq = platform_get_irq(pdev, 0); + if (i2c->irq < 0) { + result = -ENXIO; + goto fail_get_irq; + } i2c->flags = pdata->device_flags; init_waitqueue_head(&i2c->queue); @@ -340,6 +344,7 @@ static int fsl_i2c_probe(struct platform_device *pdev) fail_irq: iounmap(i2c->base); fail_map: + fail_get_irq: kfree(i2c); return result; }; diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 22781d84f79f..ac5cde1bbd2b 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -516,6 +516,10 @@ mv64xxx_i2c_probe(struct platform_device *pd) drv_data->freq_m = pdata->freq_m; drv_data->freq_n = pdata->freq_n; drv_data->irq = platform_get_irq(pd, 0); + if (drv_data->irq < 0) { + rc = -ENXIO; + goto exit_unmap_regs; + } drv_data->adapter.id = I2C_HW_MV64XXX; drv_data->adapter.algo = &mv64xxx_i2c_algo; drv_data->adapter.owner = THIS_MODULE; diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index 32431dcf5d8e..71f27e955d87 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -674,6 +674,11 @@ static int au_ide_probe(struct device *dev) ret = -ENODEV; goto out; } + if (ahwif->irq < 0) { + pr_debug("%s %d: no IRQ\n", DRV_NAME, pdev->id); + ret = -ENODEV; + goto out; + } if (!request_mem_region (res->start, res->end-res->start, pdev->name)) { pr_debug("%s: request_mem_region failed\n", DRV_NAME); diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index 285d7d068097..c32fad1ce51c 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -438,7 +438,7 @@ static int pxamci_probe(struct platform_device *pdev) r = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!r || irq == NO_IRQ) + if (!r || irq < 0) return -ENXIO; r = request_mem_region(r->start, SZ_4K, DRIVER_NAME); diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 53e3afc1b7b7..09d5c3f26985 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -696,7 +696,9 @@ static int __init am79c961_probe(struct platform_device *pdev) dev->base_addr = res->start; dev->irq = platform_get_irq(pdev, 0); - ret = -ENODEV; + ret = -ENODEV; + if (dev->irq < 0) + goto nodev; if (!request_region(dev->base_addr, 0x18, dev->name)) goto nodev; diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index e67b1d06611c..95e2bb8dd7b4 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -118,6 +118,8 @@ static int do_pd_setup(struct fs_enet_private *fep) /* Fill out IRQ field */ fep->interrupt = platform_get_irq(pdev, 0); + if (fep->interrupt < 0) + return -EINVAL; /* Attach the memory for the FCC Parameter RAM */ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram"); diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 2e8f44469699..3dad69dfdb2c 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -144,6 +144,8 @@ static int do_pd_setup(struct fs_enet_private *fep) /* Fill out IRQ field */ fep->interrupt = platform_get_irq_byname(pdev,"interrupt"); + if (fep->interrupt < 0) + return -EINVAL; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); fep->fec.fecp =(void*)r->start; diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index a3897fda71fa..a772b286f96d 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c @@ -118,6 +118,8 @@ static int do_pd_setup(struct fs_enet_private *fep) /* Fill out IRQ field */ fep->interrupt = platform_get_irq_byname(pdev, "interrupt"); + if (fep->interrupt < 0) + return -EINVAL; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); fep->scc.sccp = (void *)r->start; diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 0e8e3fcde9ff..771e25d8c417 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -193,8 +193,12 @@ static int gfar_probe(struct platform_device *pdev) priv->interruptTransmit = platform_get_irq_byname(pdev, "tx"); priv->interruptReceive = platform_get_irq_byname(pdev, "rx"); priv->interruptError = platform_get_irq_byname(pdev, "error"); + if (priv->interruptTransmit < 0 || priv->interruptReceive < 0 || priv->interruptError < 0) + goto regs_fail; } else { priv->interruptTransmit = platform_get_irq(pdev, 0); + if (priv->interruptTransmit < 0) + goto regs_fail; } /* get a pointer to the register memory */ diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 7ec08127c9d6..75e9b3b910cc 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -2221,6 +2221,10 @@ static int smc_drv_probe(struct platform_device *pdev) ndev->dma = (unsigned char)-1; ndev->irq = platform_get_irq(pdev, 0); + if (ndev->irq < 0) { + ret = -ENODEV; + goto out_free_netdev; + } ret = smc_request_attrib(pdev); if (ret) diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c index 47b5ade95bde..2c23d7584399 100644 --- a/drivers/pcmcia/omap_cf.c +++ b/drivers/pcmcia/omap_cf.c @@ -218,7 +218,7 @@ static int __init omap_cf_probe(struct device *dev) /* either CFLASH.IREQ (INT_1610_CF) or some GPIO */ irq = platform_get_irq(pdev, 0); - if (!irq) + if (irq < 0) return -EINVAL; cf = kcalloc(1, sizeof *cf, GFP_KERNEL); diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 7410e093a6b9..00d7c0ad8cbf 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -1066,6 +1066,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, port->mapbase = res->start; port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART); port->irq = platform_get_irq(platdev, 0); + if (port->irq < 0) + port->irq = 0; ourport->clk = clk_get(&platdev->dev, "uart"); diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 3785b3f7df1b..ca19abe01c53 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -286,7 +286,7 @@ void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *); int usb_hcd_omap_probe (const struct hc_driver *driver, struct platform_device *pdev) { - int retval; + int retval, irq; struct usb_hcd *hcd = 0; struct ohci_hcd *ohci; @@ -329,7 +329,12 @@ int usb_hcd_omap_probe (const struct hc_driver *driver, if (retval < 0) goto err2; - retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), SA_INTERRUPT); + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + retval = -ENXIO; + goto err2; + } + retval = usb_add_hcd(hcd, irq, SA_INTERRUPT); if (retval == 0) return retval; diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 8a893ce7040d..d9831fd42341 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -1457,7 +1457,7 @@ static int __init sa1100fb_probe(struct platform_device *pdev) int ret, irq; irq = platform_get_irq(pdev, 0); - if (irq <= 0) + if (irq < 0) return -EINVAL; if (!request_mem_region(0xb0100000, 0x10000, "LCD")) -- cgit v1.2.3-59-g8ed1b From 58383af629efb07e5a0694e445eda0c65b16e1de Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 6 Feb 2006 14:12:43 -0800 Subject: [PATCH] kobj_map semaphore to mutex conversion Convert the kobj_map code to use a mutex instead of a semaphore. It converts the single two users as well, genhd.c and char_dev.c. Signed-off-by: Jes Sorensen Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 31 ++++++++++++++++--------------- drivers/base/map.c | 21 +++++++++++---------- fs/char_dev.c | 17 +++++++++-------- include/linux/kobj_map.h | 4 ++-- 4 files changed, 38 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/block/genhd.c b/block/genhd.c index db57546a709d..64510fd88621 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -15,12 +15,13 @@ #include #include #include +#include #define MAX_PROBE_HASH 255 /* random */ static struct subsystem block_subsys; -static DECLARE_MUTEX(block_subsys_sem); +static DEFINE_MUTEX(block_subsys_lock); /* * Can be deleted altogether. Later. @@ -46,7 +47,7 @@ struct blkdev_info { /* * iterate over a list of blkdev_info structures. allows * the major_names array to be iterated over from outside this file - * must be called with the block_subsys_sem held + * must be called with the block_subsys_lock held */ void *get_next_blkdev(void *dev) { @@ -85,20 +86,20 @@ out: void *acquire_blkdev_list(void) { - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); return get_next_blkdev(NULL); } void release_blkdev_list(void *dev) { - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); kfree(dev); } /* * Count the number of records in the blkdev_list. - * must be called with the block_subsys_sem held + * must be called with the block_subsys_lock held */ int count_blkdev_list(void) { @@ -118,7 +119,7 @@ int count_blkdev_list(void) /* * extract the major and name values from a blkdev_info struct * passed in as a void to *dev. Must be called with - * block_subsys_sem held + * block_subsys_lock held */ int get_blkdev_info(void *dev, int *major, char **name) { @@ -138,7 +139,7 @@ int register_blkdev(unsigned int major, const char *name) struct blk_major_name **n, *p; int index, ret = 0; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); /* temporary */ if (major == 0) { @@ -183,7 +184,7 @@ int register_blkdev(unsigned int major, const char *name) kfree(p); } out: - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); return ret; } @@ -197,7 +198,7 @@ int unregister_blkdev(unsigned int major, const char *name) int index = major_to_index(major); int ret = 0; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); for (n = &major_names[index]; *n; n = &(*n)->next) if ((*n)->major == major) break; @@ -207,7 +208,7 @@ int unregister_blkdev(unsigned int major, const char *name) p = *n; *n = p->next; } - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); kfree(p); return ret; @@ -301,7 +302,7 @@ static void *part_start(struct seq_file *part, loff_t *pos) struct list_head *p; loff_t l = *pos; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); list_for_each(p, &block_subsys.kset.list) if (!l--) return list_entry(p, struct gendisk, kobj.entry); @@ -318,7 +319,7 @@ static void *part_next(struct seq_file *part, void *v, loff_t *pos) static void part_stop(struct seq_file *part, void *v) { - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); } static int show_partition(struct seq_file *part, void *v) @@ -377,7 +378,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data) static int __init genhd_device_init(void) { - bdev_map = kobj_map_init(base_probe, &block_subsys_sem); + bdev_map = kobj_map_init(base_probe, &block_subsys_lock); blk_dev_init(); subsystem_register(&block_subsys); return 0; @@ -611,7 +612,7 @@ static void *diskstats_start(struct seq_file *part, loff_t *pos) loff_t k = *pos; struct list_head *p; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); list_for_each(p, &block_subsys.kset.list) if (!k--) return list_entry(p, struct gendisk, kobj.entry); @@ -628,7 +629,7 @@ static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) static void diskstats_stop(struct seq_file *part, void *v) { - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); } static int diskstats_show(struct seq_file *s, void *v) diff --git a/drivers/base/map.c b/drivers/base/map.c index b449dae6f0d3..e87017f36853 100644 --- a/drivers/base/map.c +++ b/drivers/base/map.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -25,7 +26,7 @@ struct kobj_map { int (*lock)(dev_t, void *); void *data; } *probes[255]; - struct semaphore *sem; + struct mutex *lock; }; int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, @@ -53,7 +54,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, p->range = range; p->data = data; } - down(domain->sem); + mutex_lock(domain->lock); for (i = 0, p -= n; i < n; i++, p++, index++) { struct probe **s = &domain->probes[index % 255]; while (*s && (*s)->range < range) @@ -61,7 +62,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, p->next = *s; *s = p; } - up(domain->sem); + mutex_unlock(domain->lock); return 0; } @@ -75,7 +76,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range) if (n > 255) n = 255; - down(domain->sem); + mutex_lock(domain->lock); for (i = 0; i < n; i++, index++) { struct probe **s; for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) { @@ -88,7 +89,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range) } } } - up(domain->sem); + mutex_unlock(domain->lock); kfree(found); } @@ -99,7 +100,7 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index) unsigned long best = ~0UL; retry: - down(domain->sem); + mutex_lock(domain->lock); for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) { struct kobject *(*probe)(dev_t, int *, void *); struct module *owner; @@ -120,7 +121,7 @@ retry: module_put(owner); continue; } - up(domain->sem); + mutex_unlock(domain->lock); kobj = probe(dev, index, data); /* Currently ->owner protects _only_ ->probe() itself. */ module_put(owner); @@ -128,11 +129,11 @@ retry: return kobj; goto retry; } - up(domain->sem); + mutex_unlock(domain->lock); return NULL; } -struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem) +struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock) { struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL); struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL); @@ -149,6 +150,6 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem) base->get = base_probe; for (i = 0; i < 255; i++) p->probes[i] = base; - p->sem = sem; + p->lock = lock; return p; } diff --git a/fs/char_dev.c b/fs/char_dev.c index 21195c481637..5c36345c9bf7 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef CONFIG_KMOD #include @@ -28,7 +29,7 @@ static struct kobj_map *cdev_map; #define MAX_PROBE_HASH 255 /* random */ -static DECLARE_MUTEX(chrdevs_lock); +static DEFINE_MUTEX(chrdevs_lock); static struct char_device_struct { struct char_device_struct *next; @@ -88,13 +89,13 @@ out: void *acquire_chrdev_list(void) { - down(&chrdevs_lock); + mutex_lock(&chrdevs_lock); return get_next_chrdev(NULL); } void release_chrdev_list(void *dev) { - up(&chrdevs_lock); + mutex_unlock(&chrdevs_lock); kfree(dev); } @@ -151,7 +152,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, memset(cd, 0, sizeof(struct char_device_struct)); - down(&chrdevs_lock); + mutex_lock(&chrdevs_lock); /* temporary */ if (major == 0) { @@ -186,10 +187,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, } cd->next = *cp; *cp = cd; - up(&chrdevs_lock); + mutex_unlock(&chrdevs_lock); return cd; out: - up(&chrdevs_lock); + mutex_unlock(&chrdevs_lock); kfree(cd); return ERR_PTR(ret); } @@ -200,7 +201,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) struct char_device_struct *cd = NULL, **cp; int i = major_to_index(major); - down(&chrdevs_lock); + mutex_lock(&chrdevs_lock); for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) if ((*cp)->major == major && (*cp)->baseminor == baseminor && @@ -210,7 +211,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) cd = *cp; *cp = cd->next; } - up(&chrdevs_lock); + mutex_unlock(&chrdevs_lock); return cd; } diff --git a/include/linux/kobj_map.h b/include/linux/kobj_map.h index cbe7d8008042..bafe178a381f 100644 --- a/include/linux/kobj_map.h +++ b/include/linux/kobj_map.h @@ -1,6 +1,6 @@ #ifdef __KERNEL__ -#include +#include typedef struct kobject *kobj_probe_t(dev_t, int *, void *); struct kobj_map; @@ -9,6 +9,6 @@ int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *, kobj_probe_t *, int (*)(dev_t, void *), void *); void kobj_unmap(struct kobj_map *, dev_t, unsigned long); struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *); -struct kobj_map *kobj_map_init(kobj_probe_t *, struct semaphore *); +struct kobj_map *kobj_map_init(kobj_probe_t *, struct mutex *); #endif -- cgit v1.2.3-59-g8ed1b From b87ba0a33a634c9a8e3609702122a04034a0688d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Mar 2006 13:17:13 -0800 Subject: [PATCH] add EXPORT_SYMBOL_GPL_FUTURE() to USB subsystem The USB core symbols will be converted to GPL-only in a few years. Mark this as such and update the documentation explaining why, and provide a pointer for developers to receive help if they need it. Signed-off-by: Greg Kroah-Hartman --- Documentation/feature-removal-schedule.txt | 18 ++++++++++++++++++ drivers/usb/core/driver.c | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 28a31c5e2289..afeaf6218ea2 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -196,3 +196,21 @@ Why: Board specific code doesn't build anymore since ~2.6.0 and no users have complained indicating there is no more need for these boards. This should really be considered a last call. Who: Ralf Baechle + +--------------------------- + +What: USB driver API moves to EXPORT_SYMBOL_GPL +When: Febuary 2008 +Files: include/linux/usb.h, drivers/usb/core/driver.c +Why: The USB subsystem has changed a lot over time, and it has been + possible to create userspace USB drivers using usbfs/libusb/gadgetfs + that operate as fast as the USB bus allows. Because of this, the USB + subsystem will not be allowing closed source kernel drivers to + register with it, after this grace period is over. If anyone needs + any help in converting their closed source drivers over to use the + userspace filesystems, please contact the + linux-usb-devel@lists.sourceforge.net mailing list, and the developers + there will be glad to help you out. +Who: Greg Kroah-Hartman + +--------------------------- diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index dce9d987f0fc..c196f3845305 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -378,7 +378,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface, return NULL; } -EXPORT_SYMBOL(usb_match_id); +EXPORT_SYMBOL_GPL_FUTURE(usb_match_id); int usb_device_match(struct device *dev, struct device_driver *drv) { @@ -446,7 +446,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner) return retval; } -EXPORT_SYMBOL(usb_register_driver); +EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver); /** * usb_deregister - unregister a USB driver @@ -469,4 +469,4 @@ void usb_deregister(struct usb_driver *driver) usbfs_update_special(); } -EXPORT_SYMBOL(usb_deregister); +EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); -- cgit v1.2.3-59-g8ed1b From 30560ba6eda308c13a361d08eb5d4eaab94ab37e Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Mon, 13 Feb 2006 14:52:38 -0800 Subject: [PATCH] firmware: fix BUG: in fw_realloc_buffer The fw_realloc_buffer routine does not handle an increase in buffer size of more than 4k. It's not clear to me why it expects that it will only get an extra 4k of data. The attached patch modifies fw_realloc_buffer to vmalloc as much memory as is requested, instead of what we previously had + 4k. I've tested this on my laptop, which would crash occaisionally on boot without the patch. With the patch, it hasn't crashed, but I can't be certain that this code path is exercised. Signed-off-by: Jeff Moyer Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index e97e911ebf7a..472318205236 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -211,18 +211,20 @@ static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) { u8 *new_data; + int new_size = fw_priv->alloc_size; if (min_size <= fw_priv->alloc_size) return 0; - new_data = vmalloc(fw_priv->alloc_size + PAGE_SIZE); + new_size = ALIGN(min_size, PAGE_SIZE); + new_data = vmalloc(new_size); if (!new_data) { printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__); /* Make sure that we don't keep incomplete data */ fw_load_abort(fw_priv); return -ENOMEM; } - fw_priv->alloc_size += PAGE_SIZE; + fw_priv->alloc_size = new_size; if (fw_priv->fw->data) { memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size); vfree(fw_priv->fw->data); -- cgit v1.2.3-59-g8ed1b From a29d642a4aa99c5234314ab2523281139226c231 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 7 Mar 2006 23:53:25 -0800 Subject: [PATCH] get_cpu_sysdev() signedness fix Doing (int < NR_CPUS) doesn't dtrt if it's negative.. Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/cpu.c | 2 +- include/linux/cpu.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 07a7f97e1de9..29f3d7504da1 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -141,7 +141,7 @@ int __devinit register_cpu(struct cpu *cpu, int num, struct node *root) return error; } -struct sys_device *get_cpu_sysdev(int cpu) +struct sys_device *get_cpu_sysdev(unsigned cpu) { if (cpu < NR_CPUS) return cpu_sys_devices[cpu]; diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 0ed1d4853c69..d612b89dce33 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -32,7 +32,7 @@ struct cpu { }; extern int register_cpu(struct cpu *, int, struct node *); -extern struct sys_device *get_cpu_sysdev(int cpu); +extern struct sys_device *get_cpu_sysdev(unsigned cpu); #ifdef CONFIG_HOTPLUG_CPU extern void unregister_cpu(struct cpu *, struct node *); #endif -- cgit v1.2.3-59-g8ed1b From 60f780528f3ae603eb169a221628b93b6c6929f9 Mon Sep 17 00:00:00 2001 From: Luca Risolia Date: Mon, 6 Feb 2006 16:29:35 +0000 Subject: [PATCH] USB: Add ZC0301 Video4Linux2 driver This patch adds a Video4Linux2 driver for ZC0301 Image Processor and Control Chip. Signed-off-by: Luca Risolia Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/zc0301.txt | 250 +++++ MAINTAINERS | 8 + drivers/usb/Makefile | 1 + drivers/usb/media/Kconfig | 15 + drivers/usb/media/Makefile | 2 + drivers/usb/media/zc0301.h | 185 ++++ drivers/usb/media/zc0301_core.c | 2028 ++++++++++++++++++++++++++++++++++ drivers/usb/media/zc0301_pas202bcb.c | 353 ++++++ drivers/usb/media/zc0301_sensor.h | 98 ++ 9 files changed, 2940 insertions(+) create mode 100644 Documentation/usb/zc0301.txt create mode 100644 drivers/usb/media/zc0301.h create mode 100644 drivers/usb/media/zc0301_core.c create mode 100644 drivers/usb/media/zc0301_pas202bcb.c create mode 100644 drivers/usb/media/zc0301_sensor.h (limited to 'drivers') diff --git a/Documentation/usb/zc0301.txt b/Documentation/usb/zc0301.txt new file mode 100644 index 000000000000..10590bf625e4 --- /dev/null +++ b/Documentation/usb/zc0301.txt @@ -0,0 +1,250 @@ + + ZC0301 Image Processor and Control Chip + Driver for Linux + ======================================= + + - Documentation - + + +Index +===== +1. Copyright +2. Disclaimer +3. License +4. Overview and features +5. Module dependencies +6. Module loading +7. Module parameters +8. Supported devices +9. Notes for V4L2 application developers +10. Contact information +11. Credits + + +1. Copyright +============ +Copyright (C) 2006 by Luca Risolia + + +2. Disclaimer +============= +This software is not developed or sponsored by Z-Star Microelectronics Corp. +Trademarks are property of their respective owner. + + +3. License +========== +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. + + +4. Overview and features +======================== +This driver supports the video interface of the devices mounting the ZC0301 +Image Processor and Control Chip. + +The driver relies on the Video4Linux2 and USB core modules. It has been +designed to run properly on SMP systems as well. + +The latest version of the ZC0301 driver can be found at the following URL: +http://www.linux-projects.org/ + +Some of the features of the driver are: + +- full compliance with the Video4Linux2 API (see also "Notes for V4L2 + application developers" paragraph); +- available mmap or read/poll methods for video streaming through isochronous + data transfers; +- automatic detection of image sensor; +- video formats is standard JPEG in various compression qualities + (see also "Notes for V4L2 application developers" paragraph); +- full support for the capabilities of every possible image sensors that can + be connected to the ZC0301 bridges, including, for istance, red, green, + blue and global gain adjustments and exposure control (see "Supported + devices" paragraph for details); +- use of default color settings for sunlight conditions; +- dynamic driver control thanks to various module parameters (see "Module + parameters" paragraph); +- up to 64 cameras can be handled at the same time; they can be connected and + disconnected from the host many times without turning off the computer, if + the system supports hotplugging; + + +5. Module dependencies +====================== +For it to work properly, the driver needs kernel support for Video4Linux and +USB. + +The following options of the kernel configuration file must be enabled and +corresponding modules must be compiled: + + # Multimedia devices + # + CONFIG_VIDEO_DEV=m + + # USB support + # + CONFIG_USB=m + +In addition, depending on the hardware being used, the modules below are +necessary: + + # USB Host Controller Drivers + # + CONFIG_USB_EHCI_HCD=m + CONFIG_USB_UHCI_HCD=m + CONFIG_USB_OHCI_HCD=m + +The ZC0301 controller also provides a built-in microphone interface. It is +supported by the USB Audio driver thanks to the ALSA API: + + # Sound + # + CONFIG_SOUND=y + + # Advanced Linux Sound Architecture + # + CONFIG_SND=m + + # USB devices + # + CONFIG_SND_USB_AUDIO=m + +And finally: + + # USB Multimedia devices + # + CONFIG_USB_ZC0301=m + + +6. Module loading +================= +To use the driver, it is necessary to load the "zc0301" module into memory +after every other module required: "videodev", "usbcore" and, depending on +the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd". + +Loading can be done as shown below: + + [root@localhost home]# modprobe zc0301 + +At this point the devices should be recognized. You can invoke "dmesg" to +analyze kernel messages and verify that the loading process has gone well: + + [user@localhost home]$ dmesg + + +7. Module parameters +==================== +Module parameters are listed below: +------------------------------------------------------------------------------- +Name: video_nr +Type: short array (min = 0, max = 64) +Syntax: <-1|n[,...]> +Description: Specify V4L2 minor mode number: + -1 = use next available + n = use minor number n + You can specify up to 64 cameras this way. + For example: + video_nr=-1,2,-1 would assign minor number 2 to the second + registered camera and use auto for the first one and for every + other camera. +Default: -1 +------------------------------------------------------------------------------- +Name: force_munmap +Type: bool array (min = 0, max = 64) +Syntax: <0|1[,...]> +Description: Force the application to unmap previously mapped buffer memory + before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not + all the applications support this feature. This parameter is + specific for each detected camera. + 0 = do not force memory unmapping + 1 = force memory unmapping (save memory) +Default: 0 +------------------------------------------------------------------------------- +Name: debug +Type: ushort +Syntax: +Description: Debugging information level, from 0 to 3: + 0 = none (use carefully) + 1 = critical errors + 2 = significant informations + 3 = more verbose messages + Level 3 is useful for testing only, when only one device + is used at the same time. It also shows some more informations + about the hardware being detected. This module parameter can be + changed at runtime thanks to the /sys filesystem interface. +Default: 2 +------------------------------------------------------------------------------- + + +8. Supported devices +==================== +None of the names of the companies as well as their products will be mentioned +here. They have never collaborated with the author, so no advertising. + +From the point of view of a driver, what unambiguously identify a device are +its vendor and product USB identifiers. Below is a list of known identifiers of +devices mounting the ZC0301 Image Processor and Control Chips: + +Vendor ID Product ID +--------- ---------- +0x046d 0x08ae + +The following image sensors are supported: + +Model Manufacturer +----- ------------ +PAS202BCB PixArt Imaging, Inc. + +All the available control settings of each image sensor are supported through +the V4L2 interface. + + +9. Notes for V4L2 application developers +======================================== +This driver follows the V4L2 API specifications. In particular, it enforces two +rules: + +- exactly one I/O method, either "mmap" or "read", is associated with each +file descriptor. Once it is selected, the application must close and reopen the +device to switch to the other I/O method; + +- although it is not mandatory, previously mapped buffer memory should always +be unmapped before calling any "VIDIOC_S_CROP" or "VIDIOC_S_FMT" ioctl's. +The same number of buffers as before will be allocated again to match the size +of the new video frames, so you have to map the buffers again before any I/O +attempts on them. + +This driver supports the standard JPEG video format. The current compression +quality may vary from 0 to 3 and can be selected or queried thanks to the +VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. + + +10. Contact information +======================= +The author may be contacted by e-mail at . + +GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is +'FCE635A4'; the public 1024-bit key should be available at any keyserver; +the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'. + + +11. Credits +=========== +- Informations about the chip internals to enable the I2C protocol have been + taken from the documentation of the ZC030x Video4Linux1 driver written by + Andrew Birkett ; +- Initialization values of the ZC0301 connected to the PAS202BCB image sensor + have been taken from the SPCA5XX driver maintained by + Michel Xhaard diff --git a/MAINTAINERS b/MAINTAINERS index 8db5c339845d..ad0d77cbfbc3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2902,6 +2902,14 @@ L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained +USB ZC0301 DRIVER +P: Luca Risolia +M: luca.risolia@studio.unibo.it +L: linux-usb-devel@lists.sourceforge.net +L: video4linux-list@redhat.com +W: http://www.linux-projects.org +S: Maintained + USB ZD1201 DRIVER P: Jeroen Vreeken M: pe1rxq@amsat.org diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 36e476dd9123..bade87b62cf9 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_USB_SN9C102) += media/ obj-$(CONFIG_USB_STV680) += media/ obj-$(CONFIG_USB_VICAM) += media/ obj-$(CONFIG_USB_W9968CF) += media/ +obj-$(CONFIG_USB_ZC0301) += media/ obj-$(CONFIG_USB_CATC) += net/ obj-$(CONFIG_USB_KAWETH) += net/ diff --git a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig index 0d3d2cc5d7be..189d40f96be5 100644 --- a/drivers/usb/media/Kconfig +++ b/drivers/usb/media/Kconfig @@ -191,6 +191,21 @@ config USB_W9968CF To compile this driver as a module, choose M here: the module will be called w9968cf. +config USB_ZC0301 + tristate "USB ZC0301 Image Processor and Control Chip support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want support for cameras based on the ZC0301 + Image Processor and Control Chip. + + See for more informations. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" to use this driver. + + To compile this driver as a module, choose M here: the + module will be called zc0301. + config USB_PWC tristate "USB Philips Cameras" depends on USB && VIDEO_DEV diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile index 3957aa1be0f2..333bf09ca2d6 100644 --- a/drivers/usb/media/Makefile +++ b/drivers/usb/media/Makefile @@ -4,6 +4,7 @@ sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o +zc0301-objs := zc0301_core.o zc0301_pas202bcb.o obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_DSBR) += dsbr100.o @@ -16,4 +17,5 @@ obj-$(CONFIG_USB_SN9C102) += sn9c102.o obj-$(CONFIG_USB_STV680) += stv680.o obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o obj-$(CONFIG_USB_W9968CF) += w9968cf.o +obj-$(CONFIG_USB_ZC0301) += zc0301.o obj-$(CONFIG_USB_PWC) += pwc/ diff --git a/drivers/usb/media/zc0301.h b/drivers/usb/media/zc0301.h new file mode 100644 index 000000000000..6fa5075f1e3d --- /dev/null +++ b/drivers/usb/media/zc0301.h @@ -0,0 +1,185 @@ +/*************************************************************************** + * V4L2 driver for ZC0301 Image Processor and Control Chip * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * 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. * + ***************************************************************************/ + +#ifndef _ZC0301_H_ +#define _ZC0301_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zc0301_sensor.h" + +/*****************************************************************************/ + +#define ZC0301_DEBUG +#define ZC0301_DEBUG_LEVEL 2 +#define ZC0301_MAX_DEVICES 64 +#define ZC0301_FORCE_MUNMAP 0 +#define ZC0301_MAX_FRAMES 32 +#define ZC0301_COMPRESSION_QUALITY 2 +#define ZC0301_URBS 2 +#define ZC0301_ISO_PACKETS 7 +#define ZC0301_ALTERNATE_SETTING 7 +#define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS) +#define ZC0301_CTRL_TIMEOUT 100 +#define ZC0301_FRAME_TIMEOUT 2 * 1000 * msecs_to_jiffies(1) + +/*****************************************************************************/ + +ZC0301_ID_TABLE +ZC0301_SENSOR_TABLE + +enum zc0301_frame_state { + F_UNUSED, + F_QUEUED, + F_GRABBING, + F_DONE, + F_ERROR, +}; + +struct zc0301_frame_t { + void* bufmem; + struct v4l2_buffer buf; + enum zc0301_frame_state state; + struct list_head frame; + unsigned long vma_use_count; +}; + +enum zc0301_dev_state { + DEV_INITIALIZED = 0x01, + DEV_DISCONNECTED = 0x02, + DEV_MISCONFIGURED = 0x04, +}; + +enum zc0301_io_method { + IO_NONE, + IO_READ, + IO_MMAP, +}; + +enum zc0301_stream_state { + STREAM_OFF, + STREAM_INTERRUPT, + STREAM_ON, +}; + +struct zc0301_module_param { + u8 force_munmap; +}; + +static DECLARE_RWSEM(zc0301_disconnect); + +struct zc0301_device { + struct video_device* v4ldev; + + struct zc0301_sensor* sensor; + + struct usb_device* usbdev; + struct urb* urb[ZC0301_URBS]; + void* transfer_buffer[ZC0301_URBS]; + u8* control_buffer; + + struct zc0301_frame_t *frame_current, frame[ZC0301_MAX_FRAMES]; + struct list_head inqueue, outqueue; + u32 frame_count, nbuffers, nreadbuffers; + + enum zc0301_io_method io; + enum zc0301_stream_state stream; + + struct v4l2_jpegcompression compression; + + struct zc0301_module_param module_param; + + enum zc0301_dev_state state; + u8 users; + + struct mutex dev_mutex, fileop_mutex; + spinlock_t queue_lock; + wait_queue_head_t open, wait_frame, wait_stream; +}; + +/*****************************************************************************/ + +void +zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor) +{ + cam->sensor = sensor; + cam->sensor->usbdev = cam->usbdev; +} + +/*****************************************************************************/ + +#undef DBG +#undef KDBG +#ifdef ZC0301_DEBUG +# define DBG(level, fmt, args...) \ +do { \ + if (debug >= (level)) { \ + if ((level) == 1) \ + dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ + else if ((level) == 2) \ + dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ + else if ((level) >= 3) \ + dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args); \ + } \ +} while (0) +# define KDBG(level, fmt, args...) \ +do { \ + if (debug >= (level)) { \ + if ((level) == 1 || (level) == 2) \ + pr_info("zc0301: " fmt "\n", ## args); \ + else if ((level) == 3) \ + pr_debug("zc0301: [%s:%d] " fmt "\n", __FUNCTION__, \ + __LINE__ , ## args); \ + } \ +} while (0) +# define V4LDBG(level, name, cmd) \ +do { \ + if (debug >= (level)) \ + v4l_print_ioctl(name, cmd); \ +} while (0) +#else +# define DBG(level, fmt, args...) do {;} while(0) +# define KDBG(level, fmt, args...) do {;} while(0) +# define V4LDBG(level, name, cmd) do {;} while(0) +#endif + +#undef PDBG +#define PDBG(fmt, args...) \ +dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args) + +#undef PDBGG +#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ + +#endif /* _ZC0301_H_ */ diff --git a/drivers/usb/media/zc0301_core.c b/drivers/usb/media/zc0301_core.c new file mode 100644 index 000000000000..238f60f7f472 --- /dev/null +++ b/drivers/usb/media/zc0301_core.c @@ -0,0 +1,2028 @@ +/*************************************************************************** + * Video4Linux2 driver for ZC0301 Image Processor and Control Chip * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * Informations about the chip internals to enable the I2C protocol have * + * been taken from the documentation of the ZC030x Video4Linux1 driver * + * written by Andrew Birkett * + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zc0301.h" + +/*****************************************************************************/ + +#define ZC0301_MODULE_NAME "V4L2 driver for ZC0301 " \ + "Image Processor and Control Chip" +#define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" +#define ZC0301_AUTHOR_EMAIL "" +#define ZC0301_MODULE_LICENSE "GPL" +#define ZC0301_MODULE_VERSION "1:1.00" +#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 0) + +/*****************************************************************************/ + +MODULE_DEVICE_TABLE(usb, zc0301_id_table); + +MODULE_AUTHOR(ZC0301_MODULE_AUTHOR " " ZC0301_AUTHOR_EMAIL); +MODULE_DESCRIPTION(ZC0301_MODULE_NAME); +MODULE_VERSION(ZC0301_MODULE_VERSION); +MODULE_LICENSE(ZC0301_MODULE_LICENSE); + +static short video_nr[] = {[0 ... ZC0301_MAX_DEVICES-1] = -1}; +module_param_array(video_nr, short, NULL, 0444); +MODULE_PARM_DESC(video_nr, + "\n<-1|n[,...]> Specify V4L2 minor mode number." + "\n -1 = use next available (default)" + "\n n = use minor number n (integer >= 0)" + "\nYou can specify up to " + __MODULE_STRING(ZC0301_MAX_DEVICES) " cameras this way." + "\nFor example:" + "\nvideo_nr=-1,2,-1 would assign minor number 2 to" + "\nthe second registered camera and use auto for the first" + "\none and for every other camera." + "\n"); + +static short force_munmap[] = {[0 ... ZC0301_MAX_DEVICES-1] = + ZC0301_FORCE_MUNMAP}; +module_param_array(force_munmap, bool, NULL, 0444); +MODULE_PARM_DESC(force_munmap, + "\n<0|1[,...]> Force the application to unmap previously" + "\nmapped buffer memory before calling any VIDIOC_S_CROP or" + "\nVIDIOC_S_FMT ioctl's. Not all the applications support" + "\nthis feature. This parameter is specific for each" + "\ndetected camera." + "\n 0 = do not force memory unmapping" + "\n 1 = force memory unmapping (save memory)" + "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." + "\n"); + +#ifdef ZC0301_DEBUG +static unsigned short debug = ZC0301_DEBUG_LEVEL; +module_param(debug, ushort, 0644); +MODULE_PARM_DESC(debug, + "\n Debugging information level, from 0 to 3:" + "\n0 = none (use carefully)" + "\n1 = critical errors" + "\n2 = significant informations" + "\n3 = more verbose messages" + "\nLevel 3 is useful for testing only, when only " + "one device is used." + "\nDefault value is "__MODULE_STRING(ZC0301_DEBUG_LEVEL)"." + "\n"); +#endif + +/*****************************************************************************/ + +static u32 +zc0301_request_buffers(struct zc0301_device* cam, u32 count, + enum zc0301_io_method io) +{ + struct v4l2_pix_format* p = &(cam->sensor->pix_format); + struct v4l2_rect* r = &(cam->sensor->cropcap.bounds); + const size_t imagesize = cam->module_param.force_munmap || + io == IO_READ ? + (p->width * p->height * p->priv) / 8 : + (r->width * r->height * p->priv) / 8; + void* buff = NULL; + u32 i; + + if (count > ZC0301_MAX_FRAMES) + count = ZC0301_MAX_FRAMES; + + cam->nbuffers = count; + while (cam->nbuffers > 0) { + if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) + break; + cam->nbuffers--; + } + + for (i = 0; i < cam->nbuffers; i++) { + cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); + cam->frame[i].buf.index = i; + cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); + cam->frame[i].buf.length = imagesize; + cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cam->frame[i].buf.sequence = 0; + cam->frame[i].buf.field = V4L2_FIELD_NONE; + cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; + cam->frame[i].buf.flags = 0; + } + + return cam->nbuffers; +} + + +static void zc0301_release_buffers(struct zc0301_device* cam) +{ + if (cam->nbuffers) { + vfree(cam->frame[0].bufmem); + cam->nbuffers = 0; + } + cam->frame_current = NULL; +} + + +static void zc0301_empty_framequeues(struct zc0301_device* cam) +{ + u32 i; + + INIT_LIST_HEAD(&cam->inqueue); + INIT_LIST_HEAD(&cam->outqueue); + + for (i = 0; i < ZC0301_MAX_FRAMES; i++) { + cam->frame[i].state = F_UNUSED; + cam->frame[i].buf.bytesused = 0; + } +} + + +static void zc0301_requeue_outqueue(struct zc0301_device* cam) +{ + struct zc0301_frame_t *i; + + list_for_each_entry(i, &cam->outqueue, frame) { + i->state = F_QUEUED; + list_add(&i->frame, &cam->inqueue); + } + + INIT_LIST_HEAD(&cam->outqueue); +} + + +static void zc0301_queue_unusedframes(struct zc0301_device* cam) +{ + unsigned long lock_flags; + u32 i; + + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].state == F_UNUSED) { + cam->frame[i].state = F_QUEUED; + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_add_tail(&cam->frame[i].frame, &cam->inqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + } +} + +/*****************************************************************************/ + +int zc0301_write_reg(struct zc0301_device* cam, u16 index, u16 value) +{ + struct usb_device* udev = cam->usbdev; + int res; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0xa0, 0x40, + value, index, NULL, 0, ZC0301_CTRL_TIMEOUT); + if (res < 0) { + DBG(3, "Failed to write a register (index 0x%04X, " + "value 0x%02X, error %d)",index, value, res); + return -1; + } + + return 0; +} + + +int zc0301_read_reg(struct zc0301_device* cam, u16 index) +{ + struct usb_device* udev = cam->usbdev; + u8* buff = cam->control_buffer; + int res; + + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0xa1, 0xc0, + 0x0001, index, buff, 1, ZC0301_CTRL_TIMEOUT); + if (res < 0) + DBG(3, "Failed to read a register (index 0x%04X, error %d)", + index, res); + + PDBGG("Read: index 0x%04X, value: 0x%04X", index, (int)(*buff)); + + return (res >= 0) ? (int)(*buff) : -1; +} + + +int zc0301_i2c_read(struct zc0301_device* cam, u16 address, u8 length) +{ + int err = 0, res, r0, r1; + + err += zc0301_write_reg(cam, 0x0092, address); + err += zc0301_write_reg(cam, 0x0090, 0x02); + + msleep(1); + + res = zc0301_read_reg(cam, 0x0091); + if (res < 0) + err += res; + r0 = zc0301_read_reg(cam, 0x0095); + if (r0 < 0) + err += r0; + r1 = zc0301_read_reg(cam, 0x0096); + if (r1 < 0) + err += r1; + + res = (length <= 1) ? r0 : r0 | (r1 << 8); + + if (err) + DBG(3, "I2C read failed at address 0x%04X, value: 0x%04X", + address, res); + + + PDBGG("I2C read: address 0x%04X, value: 0x%04X", address, res); + + return err ? -1 : res; +} + + +int zc0301_i2c_write(struct zc0301_device* cam, u16 address, u16 value) +{ + int err = 0, res; + + err += zc0301_write_reg(cam, 0x0092, address); + err += zc0301_write_reg(cam, 0x0093, value & 0xff); + err += zc0301_write_reg(cam, 0x0094, value >> 8); + err += zc0301_write_reg(cam, 0x0090, 0x01); + + msleep(1); + + res = zc0301_read_reg(cam, 0x0091); + if (res < 0) + err += res; + + if (err) + DBG(3, "I2C write failed at address 0x%04X, value: 0x%04X", + address, value); + + PDBGG("I2C write: address 0x%04X, value: 0x%04X", address, value); + + return err ? -1 : 0; +} + +/*****************************************************************************/ + +static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs) +{ + struct zc0301_device* cam = urb->context; + struct zc0301_frame_t** f; + size_t imagesize; + u8 i; + int err = 0; + + if (urb->status == -ENOENT) + return; + + f = &cam->frame_current; + + if (cam->stream == STREAM_INTERRUPT) { + cam->stream = STREAM_OFF; + if ((*f)) + (*f)->state = F_QUEUED; + DBG(3, "Stream interrupted"); + wake_up_interruptible(&cam->wait_stream); + } + + if (cam->state & DEV_DISCONNECTED) + return; + + if (cam->state & DEV_MISCONFIGURED) { + wake_up_interruptible(&cam->wait_frame); + return; + } + + if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) + goto resubmit_urb; + + if (!(*f)) + (*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t, + frame); + + imagesize = (cam->sensor->pix_format.width * + cam->sensor->pix_format.height * + cam->sensor->pix_format.priv) / 8; + + for (i = 0; i < urb->number_of_packets; i++) { + unsigned int len, status; + void *pos; + u16* soi; + u8 sof; + + len = urb->iso_frame_desc[i].actual_length; + status = urb->iso_frame_desc[i].status; + pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; + + if (status) { + DBG(3, "Error in isochronous frame"); + (*f)->state = F_ERROR; + continue; + } + + sof = (*(soi = pos) == 0xd8ff); + + PDBGG("Isochrnous frame: length %u, #%u i,", len, i); + + if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) +start_of_frame: + if (sof) { + (*f)->state = F_GRABBING; + (*f)->buf.bytesused = 0; + do_gettimeofday(&(*f)->buf.timestamp); + DBG(3, "SOF detected: new video frame"); + } + + if ((*f)->state == F_GRABBING) { + if (sof && (*f)->buf.bytesused) + goto end_of_frame; + + if ((*f)->buf.bytesused + len > imagesize) { + DBG(3, "Video frame size exceeded"); + (*f)->state = F_ERROR; + continue; + } + + memcpy((*f)->bufmem+(*f)->buf.bytesused, pos, len); + (*f)->buf.bytesused += len; + + if ((*f)->buf.bytesused == imagesize) { + u32 b; +end_of_frame: + b = (*f)->buf.bytesused; + (*f)->state = F_DONE; + (*f)->buf.sequence= ++cam->frame_count; + spin_lock(&cam->queue_lock); + list_move_tail(&(*f)->frame, &cam->outqueue); + if (!list_empty(&cam->inqueue)) + (*f) = list_entry(cam->inqueue.next, + struct zc0301_frame_t, + frame); + else + (*f) = NULL; + spin_unlock(&cam->queue_lock); + DBG(3, "Video frame captured: : %lu bytes", + (unsigned long)(b)); + + if (!(*f)) + goto resubmit_urb; + + if (sof) + goto start_of_frame; + } + } + } + +resubmit_urb: + urb->dev = cam->usbdev; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0 && err != -EPERM) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "usb_submit_urb() failed"); + } + + wake_up_interruptible(&cam->wait_frame); +} + + +static int zc0301_start_transfer(struct zc0301_device* cam) +{ + struct usb_device *udev = cam->usbdev; + struct urb* urb; + const unsigned int wMaxPacketSize[] = {0, 128, 192, 256, 384, + 512, 768, 1023}; + const unsigned int psz = wMaxPacketSize[ZC0301_ALTERNATE_SETTING]; + s8 i, j; + int err = 0; + + for (i = 0; i < ZC0301_URBS; i++) { + cam->transfer_buffer[i] = kzalloc(ZC0301_ISO_PACKETS * psz, + GFP_KERNEL); + if (!cam->transfer_buffer[i]) { + err = -ENOMEM; + DBG(1, "Not enough memory"); + goto free_buffers; + } + } + + for (i = 0; i < ZC0301_URBS; i++) { + urb = usb_alloc_urb(ZC0301_ISO_PACKETS, GFP_KERNEL); + cam->urb[i] = urb; + if (!urb) { + err = -ENOMEM; + DBG(1, "usb_alloc_urb() failed"); + goto free_urbs; + } + urb->dev = udev; + urb->context = cam; + urb->pipe = usb_rcvisocpipe(udev, 1); + urb->transfer_flags = URB_ISO_ASAP; + urb->number_of_packets = ZC0301_ISO_PACKETS; + urb->complete = zc0301_urb_complete; + urb->transfer_buffer = cam->transfer_buffer[i]; + urb->transfer_buffer_length = psz * ZC0301_ISO_PACKETS; + urb->interval = 1; + for (j = 0; j < ZC0301_ISO_PACKETS; j++) { + urb->iso_frame_desc[j].offset = psz * j; + urb->iso_frame_desc[j].length = psz; + } + } + + err = usb_set_interface(udev, 0, ZC0301_ALTERNATE_SETTING); + if (err) { + DBG(1, "usb_set_interface() failed"); + goto free_urbs; + } + + cam->frame_current = NULL; + + for (i = 0; i < ZC0301_URBS; i++) { + err = usb_submit_urb(cam->urb[i], GFP_KERNEL); + if (err) { + for (j = i-1; j >= 0; j--) + usb_kill_urb(cam->urb[j]); + DBG(1, "usb_submit_urb() failed, error %d", err); + goto free_urbs; + } + } + + return 0; + +free_urbs: + for (i = 0; (i < ZC0301_URBS) && cam->urb[i]; i++) + usb_free_urb(cam->urb[i]); + +free_buffers: + for (i = 0; (i < ZC0301_URBS) && cam->transfer_buffer[i]; i++) + kfree(cam->transfer_buffer[i]); + + return err; +} + + +static int zc0301_stop_transfer(struct zc0301_device* cam) +{ + struct usb_device *udev = cam->usbdev; + s8 i; + int err = 0; + + if (cam->state & DEV_DISCONNECTED) + return 0; + + for (i = ZC0301_URBS-1; i >= 0; i--) { + usb_kill_urb(cam->urb[i]); + usb_free_urb(cam->urb[i]); + kfree(cam->transfer_buffer[i]); + } + + err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ + if (err) + DBG(3, "usb_set_interface() failed"); + + return err; +} + + +static int zc0301_stream_interrupt(struct zc0301_device* cam) +{ + long timeout; + + cam->stream = STREAM_INTERRUPT; + timeout = wait_event_timeout(cam->wait_stream, + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + ZC0301_URB_TIMEOUT); + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + else if (!timeout) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "URB timeout reached. The camera is misconfigured. To " + "use it, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + return 0; +} + +/*****************************************************************************/ + +static int +zc0301_set_compression(struct zc0301_device* cam, + struct v4l2_jpegcompression* compression) +{ + int r, err = 0; + + if ((r = zc0301_read_reg(cam, 0x0008)) < 0) + err += r; + err += zc0301_write_reg(cam, 0x0008, + r | 0x11 | (compression->quality >> 1)); + + return err ? -EIO : 0; +} + + +static int zc0301_init(struct zc0301_device* cam) +{ + struct zc0301_sensor* s = cam->sensor; + struct v4l2_control ctrl; + struct v4l2_queryctrl *qctrl; + struct v4l2_rect* rect; + u8 i = 0; + int err = 0; + + if (!(cam->state & DEV_INITIALIZED)) { + init_waitqueue_head(&cam->open); + qctrl = s->qctrl; + rect = &(s->cropcap.defrect); + cam->compression.quality = ZC0301_COMPRESSION_QUALITY; + } else { /* use current values */ + qctrl = s->_qctrl; + rect = &(s->_rect); + } + + if (s->init) { + err = s->init(cam); + if (err) { + DBG(3, "Sensor initialization failed"); + return err; + } + } + + if ((err = zc0301_set_compression(cam, &cam->compression))) { + DBG(3, "set_compression() failed"); + return err; + } + + if (s->set_crop) + if ((err = s->set_crop(cam, rect))) { + DBG(3, "set_crop() failed"); + return err; + } + + if (s->set_ctrl) { + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (s->qctrl[i].id != 0 && + !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { + ctrl.id = s->qctrl[i].id; + ctrl.value = qctrl[i].default_value; + err = s->set_ctrl(cam, &ctrl); + if (err) { + DBG(3, "Set %s control failed", + s->qctrl[i].name); + return err; + } + DBG(3, "Image sensor supports '%s' control", + s->qctrl[i].name); + } + } + + if (!(cam->state & DEV_INITIALIZED)) { + mutex_init(&cam->fileop_mutex); + spin_lock_init(&cam->queue_lock); + init_waitqueue_head(&cam->wait_frame); + init_waitqueue_head(&cam->wait_stream); + cam->nreadbuffers = 2; + memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); + memcpy(&(s->_rect), &(s->cropcap.defrect), + sizeof(struct v4l2_rect)); + cam->state |= DEV_INITIALIZED; + } + + DBG(2, "Initialization succeeded"); + return 0; +} + + +static void zc0301_release_resources(struct zc0301_device* cam) +{ + DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); + video_set_drvdata(cam->v4ldev, NULL); + video_unregister_device(cam->v4ldev); + kfree(cam->control_buffer); +} + +/*****************************************************************************/ + +static int zc0301_open(struct inode* inode, struct file* filp) +{ + struct zc0301_device* cam; + int err = 0; + + /* + This is the only safe way to prevent race conditions with + disconnect + */ + if (!down_read_trylock(&zc0301_disconnect)) + return -ERESTARTSYS; + + cam = video_get_drvdata(video_devdata(filp)); + + if (mutex_lock_interruptible(&cam->dev_mutex)) { + up_read(&zc0301_disconnect); + return -ERESTARTSYS; + } + + if (cam->users) { + DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); + if ((filp->f_flags & O_NONBLOCK) || + (filp->f_flags & O_NDELAY)) { + err = -EWOULDBLOCK; + goto out; + } + mutex_unlock(&cam->dev_mutex); + err = wait_event_interruptible_exclusive(cam->open, + cam->state & DEV_DISCONNECTED + || !cam->users); + if (err) { + up_read(&zc0301_disconnect); + return err; + } + if (cam->state & DEV_DISCONNECTED) { + up_read(&zc0301_disconnect); + return -ENODEV; + } + mutex_lock(&cam->dev_mutex); + } + + + if (cam->state & DEV_MISCONFIGURED) { + err = zc0301_init(cam); + if (err) { + DBG(1, "Initialization failed again. " + "I will retry on next open()."); + goto out; + } + cam->state &= ~DEV_MISCONFIGURED; + } + + if ((err = zc0301_start_transfer(cam))) + goto out; + + filp->private_data = cam; + cam->users++; + cam->io = IO_NONE; + cam->stream = STREAM_OFF; + cam->nbuffers = 0; + cam->frame_count = 0; + zc0301_empty_framequeues(cam); + + DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); + +out: + mutex_unlock(&cam->dev_mutex); + up_read(&zc0301_disconnect); + return err; +} + + +static int zc0301_release(struct inode* inode, struct file* filp) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + + mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ + + zc0301_stop_transfer(cam); + + zc0301_release_buffers(cam); + + if (cam->state & DEV_DISCONNECTED) { + zc0301_release_resources(cam); + mutex_unlock(&cam->dev_mutex); + kfree(cam); + return 0; + } + + cam->users--; + wake_up_interruptible_nr(&cam->open, 1); + + DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); + + mutex_unlock(&cam->dev_mutex); + + return 0; +} + + +static ssize_t +zc0301_read(struct file* filp, char __user * buf, + size_t count, loff_t* f_pos) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + struct zc0301_frame_t* f, * i; + unsigned long lock_flags; + long timeout; + int err = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + if (cam->io == IO_MMAP) { + DBG(3, "Close and open the device again to choose the read " + "method"); + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + if (cam->io == IO_NONE) { + if (!zc0301_request_buffers(cam, cam->nreadbuffers, IO_READ)) { + DBG(1, "read() failed, not enough memory"); + mutex_unlock(&cam->fileop_mutex); + return -ENOMEM; + } + cam->io = IO_READ; + cam->stream = STREAM_ON; + } + + if (list_empty(&cam->inqueue)) { + if (!list_empty(&cam->outqueue)) + zc0301_empty_framequeues(cam); + zc0301_queue_unusedframes(cam); + } + + if (!count) { + mutex_unlock(&cam->fileop_mutex); + return 0; + } + + if (list_empty(&cam->outqueue)) { + if (filp->f_flags & O_NONBLOCK) { + mutex_unlock(&cam->fileop_mutex); + return -EAGAIN; + } + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + ZC0301_FRAME_TIMEOUT ); + if (timeout < 0) { + mutex_unlock(&cam->fileop_mutex); + return timeout; + } + if (cam->state & DEV_DISCONNECTED) { + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + if (!timeout || (cam->state & DEV_MISCONFIGURED)) { + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + } + + f = list_entry(cam->outqueue.prev, struct zc0301_frame_t, frame); + + if (count > f->buf.bytesused) + count = f->buf.bytesused; + + if (copy_to_user(buf, f->bufmem, count)) { + err = -EFAULT; + goto exit; + } + *f_pos += count; + +exit: + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_for_each_entry(i, &cam->outqueue, frame) + i->state = F_UNUSED; + INIT_LIST_HEAD(&cam->outqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + zc0301_queue_unusedframes(cam); + + PDBGG("Frame #%lu, bytes read: %zu", + (unsigned long)f->buf.index, count); + + mutex_unlock(&cam->fileop_mutex); + + return err ? err : count; +} + + +static unsigned int zc0301_poll(struct file *filp, poll_table *wait) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + struct zc0301_frame_t* f; + unsigned long lock_flags; + unsigned int mask = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return POLLERR; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + goto error; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + goto error; + } + + if (cam->io == IO_NONE) { + if (!zc0301_request_buffers(cam, cam->nreadbuffers, IO_READ)) { + DBG(1, "poll() failed, not enough memory"); + goto error; + } + cam->io = IO_READ; + cam->stream = STREAM_ON; + } + + if (cam->io == IO_READ) { + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_for_each_entry(f, &cam->outqueue, frame) + f->state = F_UNUSED; + INIT_LIST_HEAD(&cam->outqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + zc0301_queue_unusedframes(cam); + } + + poll_wait(filp, &cam->wait_frame, wait); + + if (!list_empty(&cam->outqueue)) + mask |= POLLIN | POLLRDNORM; + + mutex_unlock(&cam->fileop_mutex); + + return mask; + +error: + mutex_unlock(&cam->fileop_mutex); + return POLLERR; +} + + +static void zc0301_vm_open(struct vm_area_struct* vma) +{ + struct zc0301_frame_t* f = vma->vm_private_data; + f->vma_use_count++; +} + + +static void zc0301_vm_close(struct vm_area_struct* vma) +{ + /* NOTE: buffers are not freed here */ + struct zc0301_frame_t* f = vma->vm_private_data; + f->vma_use_count--; +} + + +static struct vm_operations_struct zc0301_vm_ops = { + .open = zc0301_vm_open, + .close = zc0301_vm_close, +}; + + +static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + unsigned long size = vma->vm_end - vma->vm_start, + start = vma->vm_start; + void *pos; + u32 i; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || + size != PAGE_ALIGN(cam->frame[0].buf.length)) { + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + for (i = 0; i < cam->nbuffers; i++) { + if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) + break; + } + if (i == cam->nbuffers) { + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED; + + pos = cam->frame[i].bufmem; + while (size > 0) { /* size is page-aligned */ + if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { + mutex_unlock(&cam->fileop_mutex); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + size -= PAGE_SIZE; + } + + vma->vm_ops = &zc0301_vm_ops; + vma->vm_private_data = &cam->frame[i]; + + zc0301_vm_open(vma); + + mutex_unlock(&cam->fileop_mutex); + + return 0; +} + +/*****************************************************************************/ + +static int +zc0301_vidioc_querycap(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_capability cap = { + .driver = "zc0301", + .version = ZC0301_MODULE_VERSION_CODE, + .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING, + }; + + strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); + if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) + strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, + sizeof(cap.bus_info)); + + if (copy_to_user(arg, &cap, sizeof(cap))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_enuminput(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_input i; + + if (copy_from_user(&i, arg, sizeof(i))) + return -EFAULT; + + if (i.index) + return -EINVAL; + + memset(&i, 0, sizeof(i)); + strcpy(i.name, "Camera"); + + if (copy_to_user(arg, &i, sizeof(i))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_gs_input(struct zc0301_device* cam, void __user * arg) +{ + int index; + + if (copy_from_user(&index, arg, sizeof(index))) + return -EFAULT; + + if (index != 0) + return -EINVAL; + + return 0; +} + + +static int +zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg) +{ + struct zc0301_sensor* s = cam->sensor; + struct v4l2_queryctrl qc; + u8 i; + + if (copy_from_user(&qc, arg, sizeof(qc))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (qc.id && qc.id == s->qctrl[i].id) { + memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); + if (copy_to_user(arg, &qc, sizeof(qc))) + return -EFAULT; + return 0; + } + + return -EINVAL; +} + + +static int +zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg) +{ + struct zc0301_sensor* s = cam->sensor; + struct v4l2_control ctrl; + int err = 0; + u8 i; + + if (!s->get_ctrl && !s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + + if (!s->get_ctrl) { + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (ctrl.id == s->qctrl[i].id) { + ctrl.value = s->_qctrl[i].default_value; + goto exit; + } + return -EINVAL; + } else + err = s->get_ctrl(cam, &ctrl); + +exit: + if (copy_to_user(arg, &ctrl, sizeof(ctrl))) + return -EFAULT; + + return err; +} + + +static int +zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) +{ + struct zc0301_sensor* s = cam->sensor; + struct v4l2_control ctrl; + u8 i; + int err = 0; + + if (!s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (ctrl.id == s->qctrl[i].id) { + if (ctrl.value < s->qctrl[i].minimum || + ctrl.value > s->qctrl[i].maximum) + return -ERANGE; + ctrl.value -= ctrl.value % s->qctrl[i].step; + break; + } + + if ((err = s->set_ctrl(cam, &ctrl))) + return err; + + s->_qctrl[i].default_value = ctrl.value; + + return 0; +} + + +static int +zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_cropcap* cc = &(cam->sensor->cropcap); + + cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cc->pixelaspect.numerator = 1; + cc->pixelaspect.denominator = 1; + + if (copy_to_user(arg, cc, sizeof(*cc))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg) +{ + struct zc0301_sensor* s = cam->sensor; + struct v4l2_crop crop = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + }; + + memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); + + if (copy_to_user(arg, &crop, sizeof(crop))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) +{ + struct zc0301_sensor* s = cam->sensor; + struct v4l2_crop crop; + struct v4l2_rect* rect; + struct v4l2_rect* bounds = &(s->cropcap.bounds); + const enum zc0301_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; + + if (copy_from_user(&crop, arg, sizeof(crop))) + return -EFAULT; + + rect = &(crop.c); + + if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_CROP failed. " + "Unmap the buffers first."); + return -EINVAL; + } + + if (!s->set_crop) { + memcpy(rect, &(s->_rect), sizeof(*rect)); + if (copy_to_user(arg, &crop, sizeof(crop))) + return -EFAULT; + return 0; + } + + rect->left &= ~7L; + rect->top &= ~7L; + if (rect->width < 8) + rect->width = 8; + if (rect->height < 8) + rect->height = 8; + if (rect->width > bounds->width) + rect->width = bounds->width; + if (rect->height > bounds->height) + rect->height = bounds->height; + if (rect->left < bounds->left) + rect->left = bounds->left; + if (rect->top < bounds->top) + rect->top = bounds->top; + if (rect->left + rect->width > bounds->left + bounds->width) + rect->left = bounds->left+bounds->width - rect->width; + if (rect->top + rect->height > bounds->top + bounds->height) + rect->top = bounds->top+bounds->height - rect->height; + rect->width &= ~7L; + rect->height &= ~7L; + + if (cam->stream == STREAM_ON) + if ((err = zc0301_stream_interrupt(cam))) + return err; + + if (copy_to_user(arg, &crop, sizeof(crop))) { + cam->stream = stream; + return -EFAULT; + } + + if (cam->module_param.force_munmap || cam->io == IO_READ) + zc0301_release_buffers(cam); + + if (s->set_crop) + err += s->set_crop(cam, rect); + + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + s->pix_format.width = rect->width; + s->pix_format.height = rect->height; + memcpy(&(s->_rect), rect, sizeof(*rect)); + + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } + + if (cam->io == IO_READ) + zc0301_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + zc0301_requeue_outqueue(cam); + + cam->stream = stream; + + return 0; +} + + +static int +zc0301_vidioc_enum_fmt(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_fmtdesc fmtd; + + if (copy_from_user(&fmtd, arg, sizeof(fmtd))) + return -EFAULT; + + if (fmtd.index == 0) { + strcpy(fmtd.description, "JPEG"); + fmtd.pixelformat = V4L2_PIX_FMT_JPEG; + fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; + } else + return -EINVAL; + + fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); + + if (copy_to_user(arg, &fmtd, sizeof(fmtd))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_format format; + struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); + + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; + + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + pfmt->bytesperline = 0; + pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); + pfmt->field = V4L2_FIELD_NONE; + memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); + + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, + void __user * arg) +{ + struct zc0301_sensor* s = cam->sensor; + struct v4l2_format format; + struct v4l2_pix_format* pix; + struct v4l2_pix_format* pfmt = &(s->pix_format); + struct v4l2_rect* bounds = &(s->cropcap.bounds); + struct v4l2_rect rect; + const enum zc0301_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; + + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; + + pix = &(format.fmt.pix); + + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + memcpy(&rect, &(s->_rect), sizeof(rect)); + + if (!s->set_crop) { + pix->width = rect.width; + pix->height = rect.height; + } else { + rect.width = pix->width; + rect.height = pix->height; + } + + if (rect.width < 8) + rect.width = 8; + if (rect.height < 8) + rect.height = 8; + if (rect.width > bounds->left + bounds->width - rect.left) + rect.width = bounds->left + bounds->width - rect.left; + if (rect.height > bounds->top + bounds->height - rect.top) + rect.height = bounds->top + bounds->height - rect.top; + rect.width &= ~7L; + rect.height &= ~7L; + + pix->width = rect.width; + pix->height = rect.height; + pix->pixelformat = pfmt->pixelformat; + pix->priv = pfmt->priv; + pix->colorspace = pfmt->colorspace; + pix->bytesperline = 0; + pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); + pix->field = V4L2_FIELD_NONE; + + if (cmd == VIDIOC_TRY_FMT) { + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; + return 0; + } + + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_FMT failed. " + "Unmap the buffers first."); + return -EINVAL; + } + + if (cam->stream == STREAM_ON) + if ((err = zc0301_stream_interrupt(cam))) + return err; + + if (copy_to_user(arg, &format, sizeof(format))) { + cam->stream = stream; + return -EFAULT; + } + + if (cam->module_param.force_munmap || cam->io == IO_READ) + zc0301_release_buffers(cam); + + if (s->set_crop) + err += s->set_crop(cam, &rect); + + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + memcpy(pfmt, pix, sizeof(*pix)); + memcpy(&(s->_rect), &rect, sizeof(rect)); + + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } + + if (cam->io == IO_READ) + zc0301_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + zc0301_requeue_outqueue(cam); + + cam->stream = stream; + + return 0; +} + + +static int +zc0301_vidioc_g_jpegcomp(struct zc0301_device* cam, void __user * arg) +{ + if (copy_to_user(arg, &cam->compression, sizeof(cam->compression))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_jpegcompression jc; + const enum zc0301_stream_state stream = cam->stream; + int err = 0; + + if (copy_from_user(&jc, arg, sizeof(jc))) + return -EFAULT; + + if (jc.quality < 0 || jc.quality > 3) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = zc0301_stream_interrupt(cam))) + return err; + + err += zc0301_set_compression(cam, &jc); + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " + "problems. To use the camera, close and open " + "/dev/video%d again.", cam->v4ldev->minor); + return -EIO; + } + + cam->compression.quality = jc.quality; + + cam->stream = stream; + + return 0; +} + + +static int +zc0301_vidioc_reqbufs(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_requestbuffers rb; + u32 i; + int err; + + if (copy_from_user(&rb, arg, sizeof(rb))) + return -EFAULT; + + if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + rb.memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + if (cam->io == IO_READ) { + DBG(3, "Close and open the device again to choose the mmap " + "I/O method"); + return -EINVAL; + } + + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_REQBUFS failed. " + "Previous buffers are still mapped."); + return -EINVAL; + } + + if (cam->stream == STREAM_ON) + if ((err = zc0301_stream_interrupt(cam))) + return err; + + zc0301_empty_framequeues(cam); + + zc0301_release_buffers(cam); + if (rb.count) + rb.count = zc0301_request_buffers(cam, rb.count, IO_MMAP); + + if (copy_to_user(arg, &rb, sizeof(rb))) { + zc0301_release_buffers(cam); + cam->io = IO_NONE; + return -EFAULT; + } + + cam->io = rb.count ? IO_MMAP : IO_NONE; + + return 0; +} + + +static int +zc0301_vidioc_querybuf(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_buffer b; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; + + memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); + + if (cam->frame[b.index].vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; + + if (cam->frame[b.index].state == F_DONE) + b.flags |= V4L2_BUF_FLAG_DONE; + else if (cam->frame[b.index].state != F_UNUSED) + b.flags |= V4L2_BUF_FLAG_QUEUED; + + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_qbuf(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_buffer b; + unsigned long lock_flags; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; + + if (cam->frame[b.index].state != F_UNUSED) + return -EINVAL; + + cam->frame[b.index].state = F_QUEUED; + + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + PDBGG("Frame #%lu queued", (unsigned long)b.index); + + return 0; +} + + +static int +zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp, + void __user * arg) +{ + struct v4l2_buffer b; + struct zc0301_frame_t *f; + unsigned long lock_flags; + long timeout; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP) + return -EINVAL; + + if (list_empty(&cam->outqueue)) { + if (cam->stream == STREAM_OFF) + return -EINVAL; + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + ZC0301_FRAME_TIMEOUT ); + if (timeout < 0) + return timeout; + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + if (!timeout || (cam->state & DEV_MISCONFIGURED)) + return -EIO; + } + + spin_lock_irqsave(&cam->queue_lock, lock_flags); + f = list_entry(cam->outqueue.next, struct zc0301_frame_t, frame); + list_del(cam->outqueue.next); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + f->state = F_UNUSED; + + memcpy(&b, &f->buf, sizeof(b)); + if (f->vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; + + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + + PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); + + return 0; +} + + +static int +zc0301_vidioc_streamon(struct zc0301_device* cam, void __user * arg) +{ + int type; + + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (list_empty(&cam->inqueue)) + return -EINVAL; + + cam->stream = STREAM_ON; + + DBG(3, "Stream on"); + + return 0; +} + + +static int +zc0301_vidioc_streamoff(struct zc0301_device* cam, void __user * arg) +{ + int type, err; + + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = zc0301_stream_interrupt(cam))) + return err; + + zc0301_empty_framequeues(cam); + + DBG(3, "Stream off"); + + return 0; +} + + +static int +zc0301_vidioc_g_parm(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + + if (sp.parm.capture.readbuffers == 0) + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (sp.parm.capture.readbuffers > ZC0301_MAX_FRAMES) + sp.parm.capture.readbuffers = ZC0301_MAX_FRAMES; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + cam->nreadbuffers = sp.parm.capture.readbuffers; + + return 0; +} + + +static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, + unsigned int cmd, void __user * arg) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + + switch (cmd) { + + case VIDIOC_QUERYCAP: + return zc0301_vidioc_querycap(cam, arg); + + case VIDIOC_ENUMINPUT: + return zc0301_vidioc_enuminput(cam, arg); + + case VIDIOC_G_INPUT: + case VIDIOC_S_INPUT: + return zc0301_vidioc_gs_input(cam, arg); + + case VIDIOC_QUERYCTRL: + return zc0301_vidioc_query_ctrl(cam, arg); + + case VIDIOC_G_CTRL: + return zc0301_vidioc_g_ctrl(cam, arg); + + case VIDIOC_S_CTRL_OLD: + case VIDIOC_S_CTRL: + return zc0301_vidioc_s_ctrl(cam, arg); + + case VIDIOC_CROPCAP_OLD: + case VIDIOC_CROPCAP: + return zc0301_vidioc_cropcap(cam, arg); + + case VIDIOC_G_CROP: + return zc0301_vidioc_g_crop(cam, arg); + + case VIDIOC_S_CROP: + return zc0301_vidioc_s_crop(cam, arg); + + case VIDIOC_ENUM_FMT: + return zc0301_vidioc_enum_fmt(cam, arg); + + case VIDIOC_G_FMT: + return zc0301_vidioc_g_fmt(cam, arg); + + case VIDIOC_TRY_FMT: + case VIDIOC_S_FMT: + return zc0301_vidioc_try_s_fmt(cam, cmd, arg); + + case VIDIOC_G_JPEGCOMP: + return zc0301_vidioc_g_jpegcomp(cam, arg); + + case VIDIOC_S_JPEGCOMP: + return zc0301_vidioc_s_jpegcomp(cam, arg); + + case VIDIOC_REQBUFS: + return zc0301_vidioc_reqbufs(cam, arg); + + case VIDIOC_QUERYBUF: + return zc0301_vidioc_querybuf(cam, arg); + + case VIDIOC_QBUF: + return zc0301_vidioc_qbuf(cam, arg); + + case VIDIOC_DQBUF: + return zc0301_vidioc_dqbuf(cam, filp, arg); + + case VIDIOC_STREAMON: + return zc0301_vidioc_streamon(cam, arg); + + case VIDIOC_STREAMOFF: + return zc0301_vidioc_streamoff(cam, arg); + + case VIDIOC_G_PARM: + return zc0301_vidioc_g_parm(cam, arg); + + case VIDIOC_S_PARM_OLD: + case VIDIOC_S_PARM: + return zc0301_vidioc_s_parm(cam, arg); + + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case VIDIOC_QUERYSTD: + case VIDIOC_ENUMSTD: + case VIDIOC_QUERYMENU: + return -EINVAL; + + default: + return -EINVAL; + + } +} + + +static int zc0301_ioctl(struct inode* inode, struct file* filp, + unsigned int cmd, unsigned long arg) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + int err = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + V4LDBG(3, "zc0301", cmd); + + err = zc0301_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); + + mutex_unlock(&cam->fileop_mutex); + + return err; +} + + +static struct file_operations zc0301_fops = { + .owner = THIS_MODULE, + .open = zc0301_open, + .release = zc0301_release, + .ioctl = zc0301_ioctl, + .read = zc0301_read, + .poll = zc0301_poll, + .mmap = zc0301_mmap, + .llseek = no_llseek, +}; + +/*****************************************************************************/ + +static int +zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct zc0301_device* cam; + static unsigned int dev_nr = 0; + unsigned int i; + int err = 0; + + if (!(cam = kzalloc(sizeof(struct zc0301_device), GFP_KERNEL))) + return -ENOMEM; + + cam->usbdev = udev; + + if (!(cam->control_buffer = kzalloc(4, GFP_KERNEL))) { + DBG(1, "kmalloc() failed"); + err = -ENOMEM; + goto fail; + } + + if (!(cam->v4ldev = video_device_alloc())) { + DBG(1, "video_device_alloc() failed"); + err = -ENOMEM; + goto fail; + } + + mutex_init(&cam->dev_mutex); + + DBG(2, "ZC0301 Image Processor and Control Chip detected " + "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); + + for (i = 0; zc0301_sensor_table[i]; i++) { + err = zc0301_sensor_table[i](cam); + if (!err) + break; + } + + if (!err && cam->sensor) + DBG(2, "%s image sensor detected", cam->sensor->name); + else { + DBG(1, "No supported image sensor detected"); + err = -ENODEV; + goto fail; + } + + if (zc0301_init(cam)) { + DBG(1, "Initialization failed. I will retry on open()."); + cam->state |= DEV_MISCONFIGURED; + } + + strcpy(cam->v4ldev->name, "ZC0301 PC Camera"); + cam->v4ldev->owner = THIS_MODULE; + cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; + cam->v4ldev->hardware = 0; + cam->v4ldev->fops = &zc0301_fops; + cam->v4ldev->minor = video_nr[dev_nr]; + cam->v4ldev->release = video_device_release; + video_set_drvdata(cam->v4ldev, cam); + + mutex_lock(&cam->dev_mutex); + + err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, + video_nr[dev_nr]); + if (err) { + DBG(1, "V4L2 device registration failed"); + if (err == -ENFILE && video_nr[dev_nr] == -1) + DBG(1, "Free /dev/videoX node not found"); + video_nr[dev_nr] = -1; + dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; + mutex_unlock(&cam->dev_mutex); + goto fail; + } + + DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); + + cam->module_param.force_munmap = force_munmap[dev_nr]; + + dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; + + usb_set_intfdata(intf, cam); + + mutex_unlock(&cam->dev_mutex); + + return 0; + +fail: + if (cam) { + kfree(cam->control_buffer); + if (cam->v4ldev) + video_device_release(cam->v4ldev); + kfree(cam); + } + return err; +} + + +static void zc0301_usb_disconnect(struct usb_interface* intf) +{ + struct zc0301_device* cam = usb_get_intfdata(intf); + + if (!cam) + return; + + down_write(&zc0301_disconnect); + + mutex_lock(&cam->dev_mutex); + + DBG(2, "Disconnecting %s...", cam->v4ldev->name); + + wake_up_interruptible_all(&cam->open); + + if (cam->users) { + DBG(2, "Device /dev/video%d is open! Deregistration and " + "memory deallocation are deferred on close.", + cam->v4ldev->minor); + cam->state |= DEV_MISCONFIGURED; + zc0301_stop_transfer(cam); + cam->state |= DEV_DISCONNECTED; + wake_up_interruptible(&cam->wait_frame); + wake_up_interruptible(&cam->wait_stream); + } else { + cam->state |= DEV_DISCONNECTED; + zc0301_release_resources(cam); + } + + mutex_unlock(&cam->dev_mutex); + + if (!cam->users) + kfree(cam); + + up_write(&zc0301_disconnect); +} + + +static struct usb_driver zc0301_usb_driver = { + .name = "zc0301", + .id_table = zc0301_id_table, + .probe = zc0301_usb_probe, + .disconnect = zc0301_usb_disconnect, +}; + +/*****************************************************************************/ + +static int __init zc0301_module_init(void) +{ + int err = 0; + + KDBG(2, ZC0301_MODULE_NAME " v" ZC0301_MODULE_VERSION); + KDBG(3, ZC0301_MODULE_AUTHOR); + + if ((err = usb_register(&zc0301_usb_driver))) + KDBG(1, "usb_register() failed"); + + return err; +} + + +static void __exit zc0301_module_exit(void) +{ + usb_deregister(&zc0301_usb_driver); +} + + +module_init(zc0301_module_init); +module_exit(zc0301_module_exit); diff --git a/drivers/usb/media/zc0301_pas202bcb.c b/drivers/usb/media/zc0301_pas202bcb.c new file mode 100644 index 000000000000..83b45f1c0f4e --- /dev/null +++ b/drivers/usb/media/zc0301_pas202bcb.c @@ -0,0 +1,353 @@ +/*************************************************************************** + * Plug-in for PAS202BCB image sensor connected to the ZC030! Image * + * Processor and Control Chip * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * Initialization values of the ZC0301 have been taken from the SPCA5XX * + * driver maintained by Michel Xhaard * + * * + * 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 "zc0301_sensor.h" + + +static struct zc0301_sensor pas202bcb; + + +static int pas202bcb_init(struct zc0301_device* cam) +{ + int err = 0; + + err += zc0301_write_reg(cam, 0x0002, 0x00); + err += zc0301_write_reg(cam, 0x0003, 0x02); + err += zc0301_write_reg(cam, 0x0004, 0x80); + err += zc0301_write_reg(cam, 0x0005, 0x01); + err += zc0301_write_reg(cam, 0x0006, 0xE0); + err += zc0301_write_reg(cam, 0x0098, 0x00); + err += zc0301_write_reg(cam, 0x009A, 0x03); + err += zc0301_write_reg(cam, 0x011A, 0x00); + err += zc0301_write_reg(cam, 0x011C, 0x03); + err += zc0301_write_reg(cam, 0x009B, 0x01); + err += zc0301_write_reg(cam, 0x009C, 0xE6); + err += zc0301_write_reg(cam, 0x009D, 0x02); + err += zc0301_write_reg(cam, 0x009E, 0x86); + + err += zc0301_i2c_write(cam, 0x02, 0x02); + err += zc0301_i2c_write(cam, 0x0A, 0x01); + err += zc0301_i2c_write(cam, 0x0B, 0x01); + err += zc0301_i2c_write(cam, 0x0D, 0x00); + err += zc0301_i2c_write(cam, 0x12, 0x05); + err += zc0301_i2c_write(cam, 0x13, 0x63); + err += zc0301_i2c_write(cam, 0x15, 0x70); + + err += zc0301_write_reg(cam, 0x0101, 0xB7); + err += zc0301_write_reg(cam, 0x0100, 0x0D); + err += zc0301_write_reg(cam, 0x0189, 0x06); + err += zc0301_write_reg(cam, 0x01AD, 0x00); + err += zc0301_write_reg(cam, 0x01C5, 0x03); + err += zc0301_write_reg(cam, 0x01CB, 0x13); + err += zc0301_write_reg(cam, 0x0250, 0x08); + err += zc0301_write_reg(cam, 0x0301, 0x08); + err += zc0301_write_reg(cam, 0x018D, 0x70); + err += zc0301_write_reg(cam, 0x0008, 0x03); + err += zc0301_write_reg(cam, 0x01C6, 0x04); + err += zc0301_write_reg(cam, 0x01CB, 0x07); + err += zc0301_write_reg(cam, 0x0120, 0x11); + err += zc0301_write_reg(cam, 0x0121, 0x37); + err += zc0301_write_reg(cam, 0x0122, 0x58); + err += zc0301_write_reg(cam, 0x0123, 0x79); + err += zc0301_write_reg(cam, 0x0124, 0x91); + err += zc0301_write_reg(cam, 0x0125, 0xA6); + err += zc0301_write_reg(cam, 0x0126, 0xB8); + err += zc0301_write_reg(cam, 0x0127, 0xC7); + err += zc0301_write_reg(cam, 0x0128, 0xD3); + err += zc0301_write_reg(cam, 0x0129, 0xDE); + err += zc0301_write_reg(cam, 0x012A, 0xE6); + err += zc0301_write_reg(cam, 0x012B, 0xED); + err += zc0301_write_reg(cam, 0x012C, 0xF3); + err += zc0301_write_reg(cam, 0x012D, 0xF8); + err += zc0301_write_reg(cam, 0x012E, 0xFB); + err += zc0301_write_reg(cam, 0x012F, 0xFF); + err += zc0301_write_reg(cam, 0x0130, 0x26); + err += zc0301_write_reg(cam, 0x0131, 0x23); + err += zc0301_write_reg(cam, 0x0132, 0x20); + err += zc0301_write_reg(cam, 0x0133, 0x1C); + err += zc0301_write_reg(cam, 0x0134, 0x16); + err += zc0301_write_reg(cam, 0x0135, 0x13); + err += zc0301_write_reg(cam, 0x0136, 0x10); + err += zc0301_write_reg(cam, 0x0137, 0x0D); + err += zc0301_write_reg(cam, 0x0138, 0x0B); + err += zc0301_write_reg(cam, 0x0139, 0x09); + err += zc0301_write_reg(cam, 0x013A, 0x07); + err += zc0301_write_reg(cam, 0x013B, 0x06); + err += zc0301_write_reg(cam, 0x013C, 0x05); + err += zc0301_write_reg(cam, 0x013D, 0x04); + err += zc0301_write_reg(cam, 0x013E, 0x03); + err += zc0301_write_reg(cam, 0x013F, 0x02); + err += zc0301_write_reg(cam, 0x010A, 0x4C); + err += zc0301_write_reg(cam, 0x010B, 0xF5); + err += zc0301_write_reg(cam, 0x010C, 0xFF); + err += zc0301_write_reg(cam, 0x010D, 0xF9); + err += zc0301_write_reg(cam, 0x010E, 0x51); + err += zc0301_write_reg(cam, 0x010F, 0xF5); + err += zc0301_write_reg(cam, 0x0110, 0xFB); + err += zc0301_write_reg(cam, 0x0111, 0xED); + err += zc0301_write_reg(cam, 0x0112, 0x5F); + err += zc0301_write_reg(cam, 0x0180, 0x00); + err += zc0301_write_reg(cam, 0x0019, 0x00); + err += zc0301_write_reg(cam, 0x0087, 0x20); + err += zc0301_write_reg(cam, 0x0088, 0x21); + + err += zc0301_i2c_write(cam, 0x20, 0x02); + err += zc0301_i2c_write(cam, 0x21, 0x1B); + err += zc0301_i2c_write(cam, 0x03, 0x44); + err += zc0301_i2c_write(cam, 0x0E, 0x01); + err += zc0301_i2c_write(cam, 0x0F, 0x00); + + err += zc0301_write_reg(cam, 0x01A9, 0x14); + err += zc0301_write_reg(cam, 0x01AA, 0x24); + err += zc0301_write_reg(cam, 0x0190, 0x00); + err += zc0301_write_reg(cam, 0x0191, 0x02); + err += zc0301_write_reg(cam, 0x0192, 0x1B); + err += zc0301_write_reg(cam, 0x0195, 0x00); + err += zc0301_write_reg(cam, 0x0196, 0x00); + err += zc0301_write_reg(cam, 0x0197, 0x4D); + err += zc0301_write_reg(cam, 0x018C, 0x10); + err += zc0301_write_reg(cam, 0x018F, 0x20); + err += zc0301_write_reg(cam, 0x001D, 0x44); + err += zc0301_write_reg(cam, 0x001E, 0x6F); + err += zc0301_write_reg(cam, 0x001F, 0xAD); + err += zc0301_write_reg(cam, 0x0020, 0xEB); + err += zc0301_write_reg(cam, 0x0087, 0x0F); + err += zc0301_write_reg(cam, 0x0088, 0x0E); + err += zc0301_write_reg(cam, 0x0180, 0x40); + err += zc0301_write_reg(cam, 0x0192, 0x1B); + err += zc0301_write_reg(cam, 0x0191, 0x02); + err += zc0301_write_reg(cam, 0x0190, 0x00); + err += zc0301_write_reg(cam, 0x0116, 0x1D); + err += zc0301_write_reg(cam, 0x0117, 0x40); + err += zc0301_write_reg(cam, 0x0118, 0x99); + err += zc0301_write_reg(cam, 0x0180, 0x42); + err += zc0301_write_reg(cam, 0x0116, 0x1D); + err += zc0301_write_reg(cam, 0x0117, 0x40); + err += zc0301_write_reg(cam, 0x0118, 0x99); + err += zc0301_write_reg(cam, 0x0007, 0x00); + + err += zc0301_i2c_write(cam, 0x11, 0x01); + + msleep(100); + + return err; +} + + +static int pas202bcb_get_ctrl(struct zc0301_device* cam, + struct v4l2_control* ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + { + int r1 = zc0301_i2c_read(cam, 0x04, 1), + r2 = zc0301_i2c_read(cam, 0x05, 1); + if (r1 < 0 || r2 < 0) + return -EIO; + ctrl->value = (r1 << 6) | (r2 & 0x3f); + } + return 0; + case V4L2_CID_RED_BALANCE: + if ((ctrl->value = zc0301_i2c_read(cam, 0x09, 1)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case V4L2_CID_BLUE_BALANCE: + if ((ctrl->value = zc0301_i2c_read(cam, 0x07, 1)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case V4L2_CID_GAIN: + if ((ctrl->value = zc0301_i2c_read(cam, 0x10, 1)) < 0) + return -EIO; + ctrl->value &= 0x1f; + return 0; + case ZC0301_V4L2_CID_GREEN_BALANCE: + if ((ctrl->value = zc0301_i2c_read(cam, 0x08, 1)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case ZC0301_V4L2_CID_DAC_MAGNITUDE: + if ((ctrl->value = zc0301_i2c_read(cam, 0x0c, 1)) < 0) + return -EIO; + return 0; + default: + return -EINVAL; + } +} + + +static int pas202bcb_set_ctrl(struct zc0301_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += zc0301_i2c_write(cam, 0x04, ctrl->value >> 6); + err += zc0301_i2c_write(cam, 0x05, ctrl->value & 0x3f); + break; + case V4L2_CID_RED_BALANCE: + err += zc0301_i2c_write(cam, 0x09, ctrl->value); + break; + case V4L2_CID_BLUE_BALANCE: + err += zc0301_i2c_write(cam, 0x07, ctrl->value); + break; + case V4L2_CID_GAIN: + err += zc0301_i2c_write(cam, 0x10, ctrl->value); + break; + case ZC0301_V4L2_CID_GREEN_BALANCE: + err += zc0301_i2c_write(cam, 0x08, ctrl->value); + break; + case ZC0301_V4L2_CID_DAC_MAGNITUDE: + err += zc0301_i2c_write(cam, 0x0c, ctrl->value); + break; + default: + return -EINVAL; + } + err += zc0301_i2c_write(cam, 0x11, 0x01); + + return err ? -EIO : 0; +} + + +static struct zc0301_sensor pas202bcb = { + .name = "PAS202BCB", + .init = &pas202bcb_init, + .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x01e5, + .maximum = 0x3fff, + .step = 0x0001, + .default_value = 0x01e5, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x0c, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x01, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x05, + .flags = 0, + }, + { + .id = ZC0301_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = ZC0301_V4L2_CID_DAC_MAGNITUDE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "DAC magnitude", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = 0x04, + .flags = 0, + }, + }, + .get_ctrl = &pas202bcb_get_ctrl, + .set_ctrl = &pas202bcb_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_JPEG, + .priv = 16, + }, +}; + + +int zc0301_probe_pas202bcb(struct zc0301_device* cam) +{ + int r0 = 0, r1 = 0, err = 0; + unsigned int pid = 0; + + err += zc0301_write_reg(cam, 0x0000, 0x01); + err += zc0301_write_reg(cam, 0x0010, 0x0e); + err += zc0301_write_reg(cam, 0x0001, 0x01); + err += zc0301_write_reg(cam, 0x0012, 0x03); + err += zc0301_write_reg(cam, 0x0012, 0x01); + err += zc0301_write_reg(cam, 0x008d, 0x08); + + msleep(10); + + r0 = zc0301_i2c_read(cam, 0x00, 1); + r1 = zc0301_i2c_read(cam, 0x01, 1); + + if (r0 < 0 || r1 < 0 || err) + return -EIO; + + pid = (r0 << 4) | ((r1 & 0xf0) >> 4); + if (pid != 0x017) + return -ENODEV; + + zc0301_attach_sensor(cam, &pas202bcb); + + return 0; +} diff --git a/drivers/usb/media/zc0301_sensor.h b/drivers/usb/media/zc0301_sensor.h new file mode 100644 index 000000000000..8890e32405d4 --- /dev/null +++ b/drivers/usb/media/zc0301_sensor.h @@ -0,0 +1,98 @@ +/*************************************************************************** + * API for image sensors connected to the ZC030! Image Processor and * + * Control Chip * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * 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. * + ***************************************************************************/ + +#ifndef _ZC0301_SENSOR_H_ +#define _ZC0301_SENSOR_H_ + +#include +#include +#include +#include +#include +#include + +struct zc0301_device; +struct zc0301_sensor; + +/*****************************************************************************/ + +extern int zc0301_probe_pas202bcb(struct zc0301_device* cam); + +#define ZC0301_SENSOR_TABLE \ +/* Weak detections must go at the end of the list */ \ +static int (*zc0301_sensor_table[])(struct zc0301_device*) = { \ + &zc0301_probe_pas202bcb, \ + NULL, \ +}; + +extern void +zc0301_attach_sensor(struct zc0301_device* cam, + struct zc0301_sensor* sensor); + +#define ZC0301_USB_DEVICE(vend, prod, intclass) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ + USB_DEVICE_ID_MATCH_INT_CLASS, \ + .idVendor = (vend), \ + .idProduct = (prod), \ + .bInterfaceClass = (intclass) + +#define ZC0301_ID_TABLE \ +static const struct usb_device_id zc0301_id_table[] = { \ + { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \ + { } \ +}; + +/*****************************************************************************/ + +extern int zc0301_write_reg(struct zc0301_device*, u16 index, u16 value); +extern int zc0301_read_reg(struct zc0301_device*, u16 index); +extern int zc0301_i2c_write(struct zc0301_device*, u16 address, u16 value); +extern int zc0301_i2c_read(struct zc0301_device*, u16 address, u8 length); + +/*****************************************************************************/ + +#define ZC0301_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 +#define ZC0301_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE +#define ZC0301_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1 + +struct zc0301_sensor { + char name[32]; + + struct v4l2_queryctrl qctrl[ZC0301_MAX_CTRLS]; + struct v4l2_cropcap cropcap; + struct v4l2_pix_format pix_format; + + int (*init)(struct zc0301_device* cam); + int (*get_ctrl)(struct zc0301_device* cam, + struct v4l2_control* ctrl); + int (*set_ctrl)(struct zc0301_device* cam, + const struct v4l2_control* ctrl); + int (*set_crop)(struct zc0301_device* cam, + const struct v4l2_rect* rect); + + const struct usb_device* usbdev; + + /* Private */ + struct v4l2_queryctrl _qctrl[ZC0301_MAX_CTRLS]; + struct v4l2_rect _rect; +}; + +#endif /* _ZC0301_SENSOR_H_ */ -- cgit v1.2.3-59-g8ed1b From 8781ba0aa9d9dd2870b75dba8d9a47e0f5a3f96a Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 21:24:25 +0100 Subject: [PATCH] USB: optimise devio.c::usbdev_read this is a small optimisation. It is ridiculous to do a kmalloc for 18 bytes. This puts it onto the stack. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 2b68998fe4b3..d01bd77e7b14 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -134,26 +134,21 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l } if (pos < sizeof(struct usb_device_descriptor)) { - struct usb_device_descriptor *desc = kmalloc(sizeof(*desc), GFP_KERNEL); - if (!desc) { - ret = -ENOMEM; - goto err; - } - memcpy(desc, &dev->descriptor, sizeof(dev->descriptor)); - le16_to_cpus(&desc->bcdUSB); - le16_to_cpus(&desc->idVendor); - le16_to_cpus(&desc->idProduct); - le16_to_cpus(&desc->bcdDevice); + struct usb_device_descriptor temp_desc ; /* 18 bytes - fits on the stack */ + + memcpy(&temp_desc, &dev->descriptor, sizeof(dev->descriptor)); + le16_to_cpus(&temp_desc->bcdUSB); + le16_to_cpus(&temp_desc->idVendor); + le16_to_cpus(&temp_desc->idProduct); + le16_to_cpus(&temp_desc->bcdDevice); len = sizeof(struct usb_device_descriptor) - pos; if (len > nbytes) len = nbytes; - if (copy_to_user(buf, ((char *)desc) + pos, len)) { - kfree(desc); + if (copy_to_user(buf, ((char *)&temp_desc) + pos, len)) { ret = -EFAULT; goto err; } - kfree(desc); *ppos += len; buf += len; -- cgit v1.2.3-59-g8ed1b From 9fcd5c322ca2ee636e06e0c099cf8f1a692f832e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 18 Jan 2006 23:55:07 -0800 Subject: [PATCH] USB: optimise devio.c usbdev_read fix drivers/usb/core/devio.c: In function `usbdev_read': drivers/usb/core/devio.c:140: error: invalid type argument of `->' drivers/usb/core/devio.c:141: error: invalid type argument of `->' drivers/usb/core/devio.c:142: error: invalid type argument of `->' drivers/usb/core/devio.c:143: error: invalid type argument of `->' Cc: Oliver Neukum Cc: Pete Zaitcev Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index d01bd77e7b14..de6a7c07cf97 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -137,10 +137,10 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l struct usb_device_descriptor temp_desc ; /* 18 bytes - fits on the stack */ memcpy(&temp_desc, &dev->descriptor, sizeof(dev->descriptor)); - le16_to_cpus(&temp_desc->bcdUSB); - le16_to_cpus(&temp_desc->idVendor); - le16_to_cpus(&temp_desc->idProduct); - le16_to_cpus(&temp_desc->bcdDevice); + le16_to_cpus(&temp_desc.bcdUSB); + le16_to_cpus(&temp_desc.idVendor); + le16_to_cpus(&temp_desc.idProduct); + le16_to_cpus(&temp_desc.bcdDevice); len = sizeof(struct usb_device_descriptor) - pos; if (len > nbytes) -- cgit v1.2.3-59-g8ed1b From 9ff87d7326d9e4666721070040474f60a68ab467 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 20:45:11 +0100 Subject: [PATCH] USB: mdc800.c to kzalloc one more conversion to kzalloc. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/image/mdc800.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 049871145d63..4e3e4d048c14 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -978,13 +978,11 @@ static int __init usb_mdc800_init (void) { int retval = -ENODEV; /* Allocate Memory */ - mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL); + mdc800=kzalloc (sizeof (struct mdc800_data), GFP_KERNEL); if (!mdc800) goto cleanup_on_fail; - memset(mdc800, 0, sizeof(struct mdc800_data)); mdc800->dev = NULL; - mdc800->open=0; mdc800->state=NOT_CONNECTED; init_MUTEX (&mdc800->io_lock); -- cgit v1.2.3-59-g8ed1b From 887c2560b6ceb5fe7ac24704e85af507c6d960e5 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Sun, 8 Jan 2006 12:33:45 +0100 Subject: [PATCH] USB: kzalloc for storage another one for kzalloc. This covers the storage subdirectory. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/datafab.c | 3 +-- drivers/usb/storage/isd200.c | 8 +++----- drivers/usb/storage/jumpshot.c | 3 +-- drivers/usb/storage/sddr55.c | 3 +-- drivers/usb/storage/shuttle_usbat.c | 3 +-- 5 files changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 54e3e6c7ecd8..01d8971ad7db 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -512,13 +512,12 @@ int datafab_transport(struct scsi_cmnd * srb, struct us_data *us) }; if (!us->extra) { - us->extra = kmalloc(sizeof(struct datafab_info), GFP_NOIO); + us->extra = kzalloc(sizeof(struct datafab_info), GFP_NOIO); if (!us->extra) { US_DEBUGP("datafab_transport: Gah! " "Can't allocate storage for Datafab info struct!\n"); return USB_STOR_TRANSPORT_ERROR; } - memset(us->extra, 0, sizeof(struct datafab_info)); us->extra_destructor = datafab_info_destructor; ((struct datafab_info *)us->extra)->lun = -1; } diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index ecb328aa9ea1..7308e8cbe8f9 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -1361,21 +1361,19 @@ static int isd200_init_info(struct us_data *us) struct isd200_info *info; info = (struct isd200_info *) - kmalloc(sizeof(struct isd200_info), GFP_KERNEL); + kzalloc(sizeof(struct isd200_info), GFP_KERNEL); if (!info) retStatus = ISD200_ERROR; else { - memset(info, 0, sizeof(struct isd200_info)); info->id = (struct hd_driveid *) - kmalloc(sizeof(struct hd_driveid), GFP_KERNEL); + kzalloc(sizeof(struct hd_driveid), GFP_KERNEL); info->RegsBuf = (unsigned char *) kmalloc(sizeof(info->ATARegs), GFP_KERNEL); if (!info->id || !info->RegsBuf) { isd200_free_info_ptrs(info); kfree(info); retStatus = ISD200_ERROR; - } else - memset(info->id, 0, sizeof(struct hd_driveid)); + } } if (retStatus == ISD200_GOOD) { diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index aff9d51c327c..5031aa98f6a9 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -441,12 +441,11 @@ int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us) }; if (!us->extra) { - us->extra = kmalloc(sizeof(struct jumpshot_info), GFP_NOIO); + us->extra = kzalloc(sizeof(struct jumpshot_info), GFP_NOIO); if (!us->extra) { US_DEBUGP("jumpshot_transport: Gah! Can't allocate storage for jumpshot info struct!\n"); return USB_STOR_TRANSPORT_ERROR; } - memset(us->extra, 0, sizeof(struct jumpshot_info)); us->extra_destructor = jumpshot_info_destructor; } diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index 8451779f4269..0b1b5b59ca7b 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -751,11 +751,10 @@ int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) struct sddr55_card_info *info; if (!us->extra) { - us->extra = kmalloc( + us->extra = kzalloc( sizeof(struct sddr55_card_info), GFP_NOIO); if (!us->extra) return USB_STOR_TRANSPORT_ERROR; - memset(us->extra, 0, sizeof(struct sddr55_card_info)); us->extra_destructor = sddr55_card_info_destructor; } diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index fea176d7e79a..f2bc5c9e23d5 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -1318,12 +1318,11 @@ int init_usbat(struct us_data *us) unsigned char subcountL = USBAT_ATA_LBA_ME; unsigned char *status = us->iobuf; - us->extra = kmalloc(sizeof(struct usbat_info), GFP_NOIO); + us->extra = kzalloc(sizeof(struct usbat_info), GFP_NOIO); if (!us->extra) { US_DEBUGP("init_usbat: Gah! Can't allocate storage for usbat info struct!\n"); return 1; } - memset(us->extra, 0, sizeof(struct usbat_info)); info = (struct usbat_info *) (us->extra); /* Enable peripheral control signals */ -- cgit v1.2.3-59-g8ed1b From bbdb7dafb5b5a3c0197cbabd5055d8e9c093e3ea Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 20:54:29 +0100 Subject: [PATCH] USB: kzalloc for hid this uses kzalloc in hid. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 18 +++++------------- drivers/usb/input/hid-lgff.c | 6 ++---- drivers/usb/input/hid-tmff.c | 3 +-- drivers/usb/input/hiddev.c | 6 ++---- 4 files changed, 10 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 07a012f88772..f187a719f17e 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -66,9 +66,8 @@ static struct hid_report *hid_register_report(struct hid_device *device, unsigne if (report_enum->report_id_hash[id]) return report_enum->report_id_hash[id]; - if (!(report = kmalloc(sizeof(struct hid_report), GFP_KERNEL))) + if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL))) return NULL; - memset(report, 0, sizeof(struct hid_report)); if (id != 0) report_enum->numbered = 1; @@ -97,12 +96,9 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned return NULL; } - if (!(field = kmalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) + if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) + values * sizeof(unsigned), GFP_KERNEL))) return NULL; - memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage) - + values * sizeof(unsigned)); - field->index = report->maxfield++; report->field[field->index] = field; field->usage = (struct hid_usage *)(field + 1); @@ -651,17 +647,14 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size) hid_parser_reserved }; - if (!(device = kmalloc(sizeof(struct hid_device), GFP_KERNEL))) + if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL))) return NULL; - memset(device, 0, sizeof(struct hid_device)); - if (!(device->collection = kmalloc(sizeof(struct hid_collection) * + if (!(device->collection = kzalloc(sizeof(struct hid_collection) * HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) { kfree(device); return NULL; } - memset(device->collection, 0, sizeof(struct hid_collection) * - HID_DEFAULT_NUM_COLLECTIONS); device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; for (i = 0; i < HID_REPORT_TYPES; i++) @@ -675,13 +668,12 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size) memcpy(device->rdesc, start, size); device->rsize = size; - if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) { + if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) { kfree(device->rdesc); kfree(device->collection); kfree(device); return NULL; } - memset(parser, 0, sizeof(struct hid_parser)); parser->device = device; end = start + size; diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c index f82c9c9e5d51..f07d44357ff1 100644 --- a/drivers/usb/input/hid-lgff.c +++ b/drivers/usb/input/hid-lgff.c @@ -154,10 +154,9 @@ int hid_lgff_init(struct hid_device* hid) return -1; } - private = kmalloc(sizeof(struct lgff_device), GFP_KERNEL); + private = kzalloc(sizeof(struct lgff_device), GFP_KERNEL); if (!private) return -1; - memset(private, 0, sizeof(struct lgff_device)); hid->ff_private = private; /* Input init */ @@ -228,13 +227,12 @@ static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report) } *ret->field[0] = *report->field[0]; - ret->field[0]->value = kmalloc(sizeof(s32[8]), GFP_KERNEL); + ret->field[0]->value = kzalloc(sizeof(s32[8]), GFP_KERNEL); if (!ret->field[0]->value) { kfree(ret->field[0]); kfree(ret); return NULL; } - memset(ret->field[0]->value, 0, sizeof(s32[8])); return ret; } diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c index 023fd5ac31c8..534425c69c0a 100644 --- a/drivers/usb/input/hid-tmff.c +++ b/drivers/usb/input/hid-tmff.c @@ -113,11 +113,10 @@ int hid_tmff_init(struct hid_device *hid) struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); struct input_dev *input_dev = hidinput->input; - private = kmalloc(sizeof(struct tmff_device), GFP_KERNEL); + private = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); if (!private) return -ENOMEM; - memset(private, 0, sizeof(struct tmff_device)); hid->ff_private = private; /* Find the report to use */ diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 925f5aba06f5..6dd666696178 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -257,9 +257,8 @@ static int hiddev_open(struct inode * inode, struct file * file) { if (i >= HIDDEV_MINORS || !hiddev_table[i]) return -ENODEV; - if (!(list = kmalloc(sizeof(struct hiddev_list), GFP_KERNEL))) + if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) return -ENOMEM; - memset(list, 0, sizeof(struct hiddev_list)); list->hiddev = hiddev_table[i]; list->next = hiddev_table[i]->list; @@ -754,9 +753,8 @@ int hiddev_connect(struct hid_device *hid) if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) return -1; - if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) + if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) return -1; - memset(hiddev, 0, sizeof(struct hiddev)); retval = usb_register_dev(hid->intf, &hiddev_class); if (retval) { -- cgit v1.2.3-59-g8ed1b From d8e298dc9feed17f397be4bb2cd8c1dd47248c74 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 21:01:47 +0100 Subject: [PATCH] USB: kzalloc in dabusb kzalloc in dabusb. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/media/dabusb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c index 18d8eaf408d5..6f560fe9a519 100644 --- a/drivers/usb/media/dabusb.c +++ b/drivers/usb/media/dabusb.c @@ -217,12 +217,11 @@ static int dabusb_alloc_buffers (pdabusb_t s) pipesize, packets, transfer_buffer_length); while (buffers < (s->total_buffer_size << 10)) { - b = (pbuff_t) kmalloc (sizeof (buff_t), GFP_KERNEL); + b = (pbuff_t) kzalloc (sizeof (buff_t), GFP_KERNEL); if (!b) { - err("kmalloc(sizeof(buff_t))==NULL"); + err("kzalloc(sizeof(buff_t))==NULL"); goto err; } - memset (b, 0, sizeof (buff_t)); b->s = s; b->purb = usb_alloc_urb(packets, GFP_KERNEL); if (!b->purb) { -- cgit v1.2.3-59-g8ed1b From b10b4177881c50f22a79832558054f2e42be5cfa Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 21:28:40 +0100 Subject: [PATCH] USB: kzalloc in w9968cf another one for kzalloc. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/media/w9968cf.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c index 9937fc64c8bf..78cd1a577d26 100644 --- a/drivers/usb/media/w9968cf.c +++ b/drivers/usb/media/w9968cf.c @@ -695,13 +695,12 @@ static int w9968cf_allocate_memory(struct w9968cf_device* cam) /* Allocate memory for the isochronous transfer buffers */ for (i = 0; i < W9968CF_URBS; i++) { if (!(cam->transfer_buffer[i] = - kmalloc(W9968CF_ISO_PACKETS*p_size, GFP_KERNEL))) { + kzalloc(W9968CF_ISO_PACKETS*p_size, GFP_KERNEL))) { DBG(1, "Couldn't allocate memory for the isochronous " "transfer buffers (%u bytes)", p_size * W9968CF_ISO_PACKETS) return -ENOMEM; } - memset(cam->transfer_buffer[i], 0, W9968CF_ISO_PACKETS*p_size); } /* Allocate memory for the temporary frame buffer */ @@ -3499,12 +3498,10 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) return -ENODEV; cam = (struct w9968cf_device*) - kmalloc(sizeof(struct w9968cf_device), GFP_KERNEL); + kzalloc(sizeof(struct w9968cf_device), GFP_KERNEL); if (!cam) return -ENOMEM; - memset(cam, 0, sizeof(*cam)); - init_MUTEX(&cam->dev_sem); down(&cam->dev_sem); @@ -3532,21 +3529,19 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) /* Allocate 2 bytes of memory for camera control USB transfers */ - if (!(cam->control_buffer = kmalloc(2, GFP_KERNEL))) { + if (!(cam->control_buffer = kzalloc(2, GFP_KERNEL))) { DBG(1,"Couldn't allocate memory for camera control transfers") err = -ENOMEM; goto fail; } - memset(cam->control_buffer, 0, 2); /* Allocate 8 bytes of memory for USB data transfers to the FSB */ - if (!(cam->data_buffer = kmalloc(8, GFP_KERNEL))) { + if (!(cam->data_buffer = kzalloc(8, GFP_KERNEL))) { DBG(1, "Couldn't allocate memory for data " "transfers to the FSB") err = -ENOMEM; goto fail; } - memset(cam->data_buffer, 0, 8); /* Register the V4L device */ cam->v4ldev = video_device_alloc(); -- cgit v1.2.3-59-g8ed1b From 51b208ddf6e492c58609e07fa50bce98bb02cb27 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 21:35:08 +0100 Subject: [PATCH] USB: kzalloc in usbvideo another for kzalloc. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/media/usbvideo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c index 63a72e550a1b..63d279ec722b 100644 --- a/drivers/usb/media/usbvideo.c +++ b/drivers/usb/media/usbvideo.c @@ -690,14 +690,13 @@ int usbvideo_register( } base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo); - cams = (struct usbvideo *) kmalloc(base_size, GFP_KERNEL); + cams = (struct usbvideo *) kzalloc(base_size, GFP_KERNEL); if (cams == NULL) { err("Failed to allocate %d. bytes for usbvideo struct", base_size); return -ENOMEM; } dbg("%s: Allocated $%p (%d. bytes) for %d. cameras", __FUNCTION__, cams, base_size, num_cams); - memset(cams, 0, base_size); /* Copy callbacks, apply defaults for those that are not set */ memmove(&cams->cb, cbTbl, sizeof(cams->cb)); -- cgit v1.2.3-59-g8ed1b From 5f7481337cc803926b5c43aac44441f683ff91ed Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 22:24:56 +0100 Subject: [PATCH] USB: kzalloc in cytherm another one for kzalloc. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/cytherm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c index 6671317b495f..a04204292aa3 100644 --- a/drivers/usb/misc/cytherm.c +++ b/drivers/usb/misc/cytherm.c @@ -351,12 +351,11 @@ static int cytherm_probe(struct usb_interface *interface, struct usb_cytherm *dev = NULL; int retval = -ENOMEM; - dev = kmalloc (sizeof(struct usb_cytherm), GFP_KERNEL); + dev = kzalloc (sizeof(struct usb_cytherm), GFP_KERNEL); if (dev == NULL) { dev_err (&interface->dev, "Out of memory\n"); goto error; } - memset (dev, 0x00, sizeof (*dev)); dev->udev = usb_get_dev(udev); -- cgit v1.2.3-59-g8ed1b From 092e462a537ba60e5f78ff208c8a95e6fd071fa5 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 22:36:27 +0100 Subject: [PATCH] USB: kzalloc in idmouse another for kzalloc. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/idmouse.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index d8cde1017985..b3aca5124339 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -340,10 +340,9 @@ static int idmouse_probe(struct usb_interface *interface, return -ENODEV; /* allocate memory for our device state and initialize it */ - dev = kmalloc(sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) return -ENOMEM; - memset(dev, 0x00, sizeof(*dev)); init_MUTEX(&dev->sem); dev->udev = udev; -- cgit v1.2.3-59-g8ed1b From 1144cf7af2ff8e6816e360d03f867439f7efde40 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 22:40:02 +0100 Subject: [PATCH] USB: kzalloc in ldusb another one for kzalloc Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ldusb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index e2d1198623eb..f6bdaf08a80f 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -626,12 +626,11 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * /* allocate memory for our device state and intialize it */ - dev = kmalloc(sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { dev_err(&intf->dev, "Out of memory\n"); goto exit; } - memset(dev, 0x00, sizeof(*dev)); init_MUTEX(&dev->sem); dev->intf = intf; init_waitqueue_head(&dev->read_wait); -- cgit v1.2.3-59-g8ed1b From 17590840dc3c14cb059817466884ac9bd97c4a35 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 22:41:51 +0100 Subject: [PATCH] USB: kzalloc in PhidgetInterfaceKit another for kzalloc. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/phidgetkit.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 605a3c87e05c..997db5d8e35b 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -88,7 +88,7 @@ static int change_outputs(struct phidget_interfacekit *kit, int output_num, int int retval; int n; - buffer = kmalloc(4, GFP_KERNEL); + buffer = kzalloc(4, GFP_KERNEL); if (!buffer) { dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); @@ -96,7 +96,6 @@ static int change_outputs(struct phidget_interfacekit *kit, int output_num, int } kit->outputs[output_num] = enable; - memset(buffer, 0, 4); for (n=0; n<8; n++) { if (kit->outputs[n]) { buffer[0] |= 1 << n; @@ -192,7 +191,7 @@ static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, unsigned char *buffer; int retval = -ENOMEM; - buffer = kmalloc(8, GFP_KERNEL); + buffer = kzalloc(8, GFP_KERNEL); if (!buffer) { dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); goto exit; @@ -202,7 +201,6 @@ static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, retval = -EINVAL; goto exit; } - memset(buffer, 0x00, 8); if (enabled) buffer[0] = 0x01; buffer[7] = 0x11; @@ -406,12 +404,11 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - kit = kmalloc(sizeof(*kit), GFP_KERNEL); + kit = kzalloc(sizeof(*kit), GFP_KERNEL); if (kit == NULL) { dev_err(&intf->dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } - memset(kit, 0, sizeof(*kit)); kit->ifkit = ifkit; kit->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kit->data_dma); -- cgit v1.2.3-59-g8ed1b From d874a2bade6eec21abb30d4822d7b3e43cfbae95 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 22:43:32 +0100 Subject: [PATCH] USB: kzalloc in PhidgetServo another for kzalloc. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/phidgetservo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c index b3418d2bcc69..5a040c205eed 100644 --- a/drivers/usb/misc/phidgetservo.c +++ b/drivers/usb/misc/phidgetservo.c @@ -252,12 +252,11 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id) struct usb_device *udev = interface_to_usbdev(interface); struct phidget_servo *dev; - dev = kmalloc(sizeof (struct phidget_servo), GFP_KERNEL); + dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); if (dev == NULL) { dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } - memset(dev, 0x00, sizeof (*dev)); dev->udev = usb_get_dev(udev); dev->type = id->driver_info; -- cgit v1.2.3-59-g8ed1b From 06d694748b5173d972d7e4169173adad62ee67c0 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 22:44:52 +0100 Subject: [PATCH] USB: kzalloc in usbled another one for kzalloc. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbled.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index 877b081a3a6e..f441964132c0 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c @@ -106,12 +106,11 @@ static int led_probe(struct usb_interface *interface, const struct usb_device_id struct usb_led *dev = NULL; int retval = -ENOMEM; - dev = kmalloc(sizeof(struct usb_led), GFP_KERNEL); + dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL); if (dev == NULL) { dev_err(&interface->dev, "Out of memory\n"); goto error; } - memset (dev, 0x00, sizeof (*dev)); dev->udev = usb_get_dev(udev); -- cgit v1.2.3-59-g8ed1b From 9ee884cc89dc339276c719ab4ff53913ac03d083 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Jan 2006 23:27:17 +0100 Subject: [PATCH] USB: kzalloc in sisusbvga this does two things: - use kzalloc where appropriate - correct error return codes in ioctl Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 3260d595441f..196c8794a73c 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3188,7 +3188,7 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, break; default: - retval = -EINVAL; + retval = -ENOTTY; break; } @@ -3251,12 +3251,11 @@ static int sisusb_probe(struct usb_interface *intf, dev->devnum); /* Allocate memory for our private */ - if (!(sisusb = kmalloc(sizeof(*sisusb), GFP_KERNEL))) { + if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) { printk(KERN_ERR "sisusb: Failed to allocate memory for private data\n"); return -ENOMEM; } - memset(sisusb, 0, sizeof(*sisusb)); kref_init(&sisusb->kref); init_MUTEX(&(sisusb->lock)); -- cgit v1.2.3-59-g8ed1b From 29da7937a11a47bad64558c3be4d998c4ea5e823 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Mon, 13 Feb 2006 20:35:57 -0800 Subject: [PATCH] ub: use kzalloc Switch from kmalloc+memset to kzalloc. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/block/ub.c b/drivers/block/ub.c index f04d864770ad..3e7689494c66 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -2007,9 +2007,8 @@ static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun) init_completion(&compl); rc = -ENOMEM; - if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) + if ((cmd = kzalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) goto err_alloc; - memset(cmd, 0, ALLOC_SIZE); cmd->cdb[0] = TEST_UNIT_READY; cmd->cdb_len = 6; @@ -2062,9 +2061,8 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, init_completion(&compl); rc = -ENOMEM; - if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) + if ((cmd = kzalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) goto err_alloc; - memset(cmd, 0, ALLOC_SIZE); p = (char *)cmd + sizeof(struct ub_scsi_cmd); cmd->cdb[0] = 0x25; @@ -2405,9 +2403,8 @@ static int ub_probe(struct usb_interface *intf, return -ENXIO; rc = -ENOMEM; - if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL) + if ((sc = kzalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL) goto err_core; - memset(sc, 0, sizeof(struct ub_dev)); sc->lock = ub_next_lock(); INIT_LIST_HEAD(&sc->luns); usb_init_urb(&sc->work_urb); @@ -2524,9 +2521,8 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) int rc; rc = -ENOMEM; - if ((lun = kmalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL) + if ((lun = kzalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL) goto err_alloc; - memset(lun, 0, sizeof(struct ub_lun)); lun->num = lnum; rc = -ENOSR; -- cgit v1.2.3-59-g8ed1b From 9628416a542488230b53df48d90d4a967dea41c8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 5 Feb 2006 00:03:28 +0100 Subject: [PATCH] USB: remove OBSOLETE_OSS_USB_DRIVER drivers This patch removes the obsolete USB_MIDI and USB_AUDIO drivers. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Makefile | 2 - drivers/usb/class/Kconfig | 47 - drivers/usb/class/Makefile | 2 - drivers/usb/class/audio.c | 3869 ------------------------------------------ drivers/usb/class/audio.h | 110 -- drivers/usb/class/usb-midi.c | 2153 ----------------------- drivers/usb/class/usb-midi.h | 164 -- 7 files changed, 6347 deletions(-) delete mode 100644 drivers/usb/class/audio.c delete mode 100644 drivers/usb/class/audio.h delete mode 100644 drivers/usb/class/usb-midi.c delete mode 100644 drivers/usb/class/usb-midi.h (limited to 'drivers') diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index bade87b62cf9..7796ecfc0765 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -17,8 +17,6 @@ obj-$(CONFIG_USB_SL811_HCD) += host/ obj-$(CONFIG_ETRAX_USB_HOST) += host/ obj-$(CONFIG_USB_ACM) += class/ -obj-$(CONFIG_USB_AUDIO) += class/ -obj-$(CONFIG_USB_MIDI) += class/ obj-$(CONFIG_USB_PRINTER) += class/ obj-$(CONFIG_USB_STORAGE) += storage/ diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig index ef105a92a7bd..3a9102d2591b 100644 --- a/drivers/usb/class/Kconfig +++ b/drivers/usb/class/Kconfig @@ -4,53 +4,6 @@ comment "USB Device Class drivers" depends on USB -config OBSOLETE_OSS_USB_DRIVER - bool "Obsolete OSS USB drivers" - depends on USB && SOUND - help - This option enables support for the obsolete USB Audio and Midi - drivers that are scheduled for removal in the near future since - there are ALSA drivers for the same hardware. - - Please contact Adrian Bunk if you had to - say Y here because of missing support in the ALSA drivers. - - If unsure, say N. - -config USB_AUDIO - tristate "USB Audio support" - depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER - help - Say Y here if you want to connect USB audio equipment such as - speakers to your computer's USB port. You only need this if you use - the OSS sound driver; ALSA has its own option for usb audio support. - - To compile this driver as a module, choose M here: the - module will be called audio. - -config USB_MIDI - tristate "USB MIDI support" - depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER - ---help--- - Say Y here if you want to connect a USB MIDI device to your - computer's USB port. You only need this if you use the OSS - sound system; USB MIDI devices are supported by ALSA's USB - audio driver. This driver is for devices that comply with - 'Universal Serial Bus Device Class Definition for MIDI Device'. - - The following devices are known to work: - * Steinberg USB2MIDI - * Roland MPU64 - * Roland PC-300 - * Roland SC8850 - * Roland UM-1 - * Roland UM-2 - * Roland UA-100 - * Yamaha MU1000 - - To compile this driver as a module, choose M here: the - module will be called usb-midi. - config USB_ACM tristate "USB Modem (CDC ACM) support" depends on USB diff --git a/drivers/usb/class/Makefile b/drivers/usb/class/Makefile index 229471247751..cc391e6c2af8 100644 --- a/drivers/usb/class/Makefile +++ b/drivers/usb/class/Makefile @@ -4,6 +4,4 @@ # obj-$(CONFIG_USB_ACM) += cdc-acm.o -obj-$(CONFIG_USB_AUDIO) += audio.o -obj-$(CONFIG_USB_MIDI) += usb-midi.o obj-$(CONFIG_USB_PRINTER) += usblp.o diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c deleted file mode 100644 index 3ad9ee8b84a9..000000000000 --- a/drivers/usb/class/audio.c +++ /dev/null @@ -1,3869 +0,0 @@ -/*****************************************************************************/ - -/* - * audio.c -- USB Audio Class driver - * - * Copyright (C) 1999, 2000, 2001, 2003, 2004 - * Alan Cox (alan@lxorguk.ukuu.org.uk) - * Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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. - * - * Debugging: - * Use the 'lsusb' utility to dump the descriptors. - * - * 1999-09-07: Alan Cox - * Parsing Audio descriptor patch - * 1999-09-08: Thomas Sailer - * Added OSS compatible data io functions; both parts of the - * driver remain to be glued together - * 1999-09-10: Thomas Sailer - * Beautified the driver. Added sample format conversions. - * Still not properly glued with the parsing code. - * The parsing code seems to have its problems btw, - * Since it parses all available configs but doesn't - * store which iface/altsetting belongs to which config. - * 1999-09-20: Thomas Sailer - * Threw out Alan's parsing code and implemented my own one. - * You cannot reasonnably linearly parse audio descriptors, - * especially the AudioClass descriptors have to be considered - * pointer lists. Mixer parsing untested, due to lack of device. - * First stab at synch pipe implementation, the Dallas USB DAC - * wants to use an Asynch out pipe. usb_audio_state now basically - * only contains lists of mixer and wave devices. We can therefore - * now have multiple mixer/wave devices per USB device. - * 1999-10-28: Thomas Sailer - * Converted to URB API. Fixed a taskstate/wakeup semantics mistake - * that made the driver consume all available CPU cycles. - * Now runs stable on UHCI-Acher/Fliegl/Sailer. - * 1999-10-31: Thomas Sailer - * Audio can now be unloaded if it is not in use by any mixer - * or dsp client (formerly you had to disconnect the audio devices - * from the USB port) - * Finally, about three months after ordering, my "Maxxtro SPK222" - * speakers arrived, isn't disdata a great mail order company 8-) - * Parse class specific endpoint descriptor of the audiostreaming - * interfaces and take the endpoint attributes from there. - * Unbelievably, the Philips USB DAC has a sampling rate range - * of over a decade, yet does not support the sampling rate control! - * No wonder it sounds so bad, has very audible sampling rate - * conversion distortion. Don't try to listen to it using - * decent headphones! - * "Let's make things better" -> but please Philips start with your - * own stuff!!!! - * 1999-11-02: Thomas Sailer - * It takes the Philips boxes several seconds to acquire synchronisation - * that means they won't play short sounds. Should probably maintain - * the ISO datastream even if there's nothing to play. - * Fix counting the total_bytes counter, RealPlayer G2 depends on it. - * 1999-12-20: Thomas Sailer - * Fix bad bug in conversion to per interface probing. - * disconnect was called multiple times for the audio device, - * leading to a premature freeing of the audio structures - * 2000-05-13: Thomas Sailer - * I don't remember who changed the find_format routine, - * but the change was completely broken for the Dallas - * chip. Anyway taking sampling rate into account in find_format - * is bad and should not be done unless there are devices with - * completely broken audio descriptors. Unless someone shows - * me such a descriptor, I will not allow find_format to - * take the sampling rate into account. - * Also, the former find_format made: - * - mpg123 play mono instead of stereo - * - sox completely fail for wav's with sample rates < 44.1kHz - * for the Dallas chip. - * Also fix a rather long standing problem with applications that - * use "small" writes producing no sound at all. - * 2000-05-15: Thomas Sailer - * My fears came true, the Philips camera indeed has pretty stupid - * audio descriptors. - * 2000-05-17: Thomas Sailer - * Nemsoft spotted my stupid last minute change, thanks - * 2000-05-19: Thomas Sailer - * Fixed FEATURE_UNIT thinkos found thanks to the KC Technology - * Xtend device. Basically the driver treated FEATURE_UNIT's sourced - * by mono terminals as stereo. - * 2000-05-20: Thomas Sailer - * SELECTOR support (and thus selecting record channels from the mixer). - * Somewhat peculiar due to OSS interface limitations. Only works - * for channels where a "slider" is already in front of it (i.e. - * a MIXER unit or a FEATURE unit with volume capability). - * 2000-11-26: Thomas Sailer - * Workaround for Dallas DS4201. The DS4201 uses PCM8 as format tag for - * its 8 bit modes, but expects signed data (and should therefore have used PCM). - * 2001-03-10: Thomas Sailer - * provide abs function, prevent picking up a bogus kernel macro - * for abs. Bug report by Andrew Morton - * 2001-06-16: Bryce Nesbitt - * Fix SNDCTL_DSP_STEREO API violation - * 2003-04-08: Oliver Neukum (oliver@neukum.name): - * Setting a configuration is done by usbcore and must not be overridden - * 2004-02-27: Workaround for broken synch descriptors - * 2004-03-07: Alan Stern - * Add usb_ifnum_to_if() and usb_altnum_to_altsetting() support. - * Use the in-memory descriptors instead of reading them from the device. - * - */ - -/* - * Strategy: - * - * Alan Cox and Thomas Sailer are starting to dig at opposite ends and - * are hoping to meet in the middle, just like tunnel diggers :) - * Alan tackles the descriptor parsing, Thomas the actual data IO and the - * OSS compatible interface. - * - * Data IO implementation issues - * - * A mmap'able ring buffer per direction is implemented, because - * almost every OSS app expects it. It is however impractical to - * transmit/receive USB data directly into and out of the ring buffer, - * due to alignment and synchronisation issues. Instead, the ring buffer - * feeds a constant time delay line that handles the USB issues. - * - * Now we first try to find an alternate setting that exactly matches - * the sample format requested by the user. If we find one, we do not - * need to perform any sample rate conversions. If there is no matching - * altsetting, we choose the closest one and perform sample format - * conversions. We never do sample rate conversion; these are too - * expensive to be performed in the kernel. - * - * Current status: no known HCD-specific issues. - * - * Generally: Due to the brokenness of the Audio Class spec - * it seems generally impossible to write a generic Audio Class driver, - * so a reasonable driver should implement the features that are actually - * used. - * - * Parsing implementation issues - * - * One cannot reasonably parse the AudioClass descriptors linearly. - * Therefore the current implementation features routines to look - * for a specific descriptor in the descriptor list. - * - * How does the parsing work? First, all interfaces are searched - * for an AudioControl class interface. If found, the config descriptor - * that belongs to the current configuration is searched and - * the HEADER descriptor is found. It contains a list of - * all AudioStreaming and MIDIStreaming devices. This list is then walked, - * and all AudioStreaming interfaces are classified into input and output - * interfaces (according to the endpoint0 direction in altsetting1) (MIDIStreaming - * is currently not supported). The input & output list is then used - * to group inputs and outputs together and issued pairwise to the - * AudioStreaming class parser. Finally, all OUTPUT_TERMINAL descriptors - * are walked and issued to the mixer construction routine. - * - * The AudioStreaming parser simply enumerates all altsettings belonging - * to the specified interface. It looks for AS_GENERAL and FORMAT_TYPE - * class specific descriptors to extract the sample format/sample rate - * data. Only sample format types PCM and PCM8 are supported right now, and - * only FORMAT_TYPE_I is handled. The isochronous data endpoint needs to - * be the first endpoint of the interface, and the optional synchronisation - * isochronous endpoint the second one. - * - * Mixer construction works as follows: The various TERMINAL and UNIT - * descriptors span a tree from the root (OUTPUT_TERMINAL) through the - * intermediate nodes (UNITs) to the leaves (INPUT_TERMINAL). We walk - * that tree in a depth first manner. FEATURE_UNITs may contribute volume, - * bass and treble sliders to the mixer, MIXER_UNITs volume sliders. - * The terminal type encoded in the INPUT_TERMINALs feeds a heuristic - * to determine "meaningful" OSS slider numbers, however we will see - * how well this works in practice. Other features are not used at the - * moment, they seem less often used. Also, it seems difficult at least - * to construct recording source switches from SELECTOR_UNITs, but - * since there are not many USB ADC's available, we leave that for later. - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "audio.h" - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.0.0" -#define DRIVER_AUTHOR "Alan Cox , Thomas Sailer (sailer@ife.ee.ethz.ch)" -#define DRIVER_DESC "USB Audio Class driver" - -#define AUDIO_DEBUG 1 - -#define SND_DEV_DSP16 5 - -#define dprintk(x) - -/* --------------------------------------------------------------------- */ - -/* - * Linked list of all audio devices... - */ -static struct list_head audiodevs = LIST_HEAD_INIT(audiodevs); -static DECLARE_MUTEX(open_sem); - -/* - * wait queue for processes wanting to open an USB audio device - */ -static DECLARE_WAIT_QUEUE_HEAD(open_wait); - - -#define MAXFORMATS MAX_ALT -#define DMABUFSHIFT 17 /* 128k worth of DMA buffer */ -#define NRSGBUF (1U<<(DMABUFSHIFT-PAGE_SHIFT)) - -/* - * This influences: - * - Latency - * - Interrupt rate - * - Synchronisation behaviour - * Don't touch this if you don't understand all of the above. - */ -#define DESCFRAMES 5 -#define SYNCFRAMES DESCFRAMES - -#define MIXFLG_STEREOIN 1 -#define MIXFLG_STEREOOUT 2 - -struct mixerchannel { - __u16 value; - __u16 osschannel; /* number of the OSS channel */ - __s16 minval, maxval; - __u16 slctunitid; - __u8 unitid; - __u8 selector; - __u8 chnum; - __u8 flags; -}; - -struct audioformat { - unsigned int format; - unsigned int sratelo; - unsigned int sratehi; - unsigned char altsetting; - unsigned char attributes; -}; - -struct dmabuf { - /* buffer data format */ - unsigned int format; - unsigned int srate; - /* physical buffer */ - unsigned char *sgbuf[NRSGBUF]; - unsigned bufsize; - unsigned numfrag; - unsigned fragshift; - unsigned wrptr, rdptr; - unsigned total_bytes; - int count; - unsigned error; /* over/underrun */ - wait_queue_head_t wait; - /* redundant, but makes calculations easier */ - unsigned fragsize; - unsigned dmasize; - /* OSS stuff */ - unsigned mapped:1; - unsigned ready:1; - unsigned ossfragshift; - int ossmaxfrags; - unsigned subdivision; -}; - -struct usb_audio_state; - -#define FLG_URB0RUNNING 1 -#define FLG_URB1RUNNING 2 -#define FLG_SYNC0RUNNING 4 -#define FLG_SYNC1RUNNING 8 -#define FLG_RUNNING 16 -#define FLG_CONNECTED 32 - -struct my_data_urb { - struct urb *urb; -}; - -struct my_sync_urb { - struct urb *urb; -}; - - -struct usb_audiodev { - struct list_head list; - struct usb_audio_state *state; - - /* soundcore stuff */ - int dev_audio; - - /* wave stuff */ - mode_t open_mode; - spinlock_t lock; /* DMA buffer access spinlock */ - - struct usbin { - int interface; /* Interface number, -1 means not used */ - unsigned int format; /* USB data format */ - unsigned int datapipe; /* the data input pipe */ - unsigned int syncpipe; /* the synchronisation pipe - 0 for anything but adaptive IN mode */ - unsigned int syncinterval; /* P for adaptive IN mode, 0 otherwise */ - unsigned int freqn; /* nominal sampling rate in USB format, i.e. fs/1000 in Q10.14 */ - unsigned int freqmax; /* maximum sampling rate, used for buffer management */ - unsigned int phase; /* phase accumulator */ - unsigned int flags; /* see FLG_ defines */ - - struct my_data_urb durb[2]; /* ISO descriptors for the data endpoint */ - struct my_sync_urb surb[2]; /* ISO sync pipe descriptor if needed */ - - struct dmabuf dma; - } usbin; - - struct usbout { - int interface; /* Interface number, -1 means not used */ - unsigned int format; /* USB data format */ - unsigned int datapipe; /* the data input pipe */ - unsigned int syncpipe; /* the synchronisation pipe - 0 for anything but asynchronous OUT mode */ - unsigned int syncinterval; /* P for asynchronous OUT mode, 0 otherwise */ - unsigned int freqn; /* nominal sampling rate in USB format, i.e. fs/1000 in Q10.14 */ - unsigned int freqm; /* momentary sampling rate in USB format, i.e. fs/1000 in Q10.14 */ - unsigned int freqmax; /* maximum sampling rate, used for buffer management */ - unsigned int phase; /* phase accumulator */ - unsigned int flags; /* see FLG_ defines */ - - struct my_data_urb durb[2]; /* ISO descriptors for the data endpoint */ - struct my_sync_urb surb[2]; /* ISO sync pipe descriptor if needed */ - - struct dmabuf dma; - } usbout; - - - unsigned int numfmtin, numfmtout; - struct audioformat fmtin[MAXFORMATS]; - struct audioformat fmtout[MAXFORMATS]; -}; - -struct usb_mixerdev { - struct list_head list; - struct usb_audio_state *state; - - /* soundcore stuff */ - int dev_mixer; - - unsigned char iface; /* interface number of the AudioControl interface */ - - /* USB format descriptions */ - unsigned int numch, modcnt; - - /* mixch is last and gets allocated dynamically */ - struct mixerchannel ch[0]; -}; - -struct usb_audio_state { - struct list_head audiodev; - - /* USB device */ - struct usb_device *usbdev; - - struct list_head audiolist; - struct list_head mixerlist; - - unsigned count; /* usage counter; NOTE: the usb stack is also considered a user */ -}; - -/* private audio format extensions */ -#define AFMT_STEREO 0x80000000 -#define AFMT_ISSTEREO(x) ((x) & AFMT_STEREO) -#define AFMT_IS16BIT(x) ((x) & (AFMT_S16_LE|AFMT_S16_BE|AFMT_U16_LE|AFMT_U16_BE)) -#define AFMT_ISUNSIGNED(x) ((x) & (AFMT_U8|AFMT_U16_LE|AFMT_U16_BE)) -#define AFMT_BYTESSHIFT(x) ((AFMT_ISSTEREO(x) ? 1 : 0) + (AFMT_IS16BIT(x) ? 1 : 0)) -#define AFMT_BYTES(x) (1<= 0x10000) { - x >>= 16; - r += 16; - } - if (x >= 0x100) { - x >>= 8; - r += 8; - } - if (x >= 0x10) { - x >>= 4; - r += 4; - } - if (x >= 4) { - x >>= 2; - r += 2; - } - if (x >= 2) - r++; - return r; -} - -/* --------------------------------------------------------------------- */ - -/* - * OSS compatible ring buffer management. The ring buffer may be mmap'ed into - * an application address space. - * - * I first used the rvmalloc stuff copied from bttv. Alan Cox did not like it, so - * we now use an array of pointers to a single page each. This saves us the - * kernel page table manipulations, but we have to do a page table alike mechanism - * (though only one indirection) in software. - */ - -static void dmabuf_release(struct dmabuf *db) -{ - unsigned int nr; - void *p; - - for(nr = 0; nr < NRSGBUF; nr++) { - if (!(p = db->sgbuf[nr])) - continue; - ClearPageReserved(virt_to_page(p)); - free_page((unsigned long)p); - db->sgbuf[nr] = NULL; - } - db->mapped = db->ready = 0; -} - -static int dmabuf_init(struct dmabuf *db) -{ - unsigned int nr, bytepersec, bufs; - void *p; - - /* initialize some fields */ - db->rdptr = db->wrptr = db->total_bytes = db->count = db->error = 0; - /* calculate required buffer size */ - bytepersec = db->srate << AFMT_BYTESSHIFT(db->format); - bufs = 1U << DMABUFSHIFT; - if (db->ossfragshift) { - if ((1000 << db->ossfragshift) < bytepersec) - db->fragshift = ld2(bytepersec/1000); - else - db->fragshift = db->ossfragshift; - } else { - db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1)); - if (db->fragshift < 3) - db->fragshift = 3; - } - db->numfrag = bufs >> db->fragshift; - while (db->numfrag < 4 && db->fragshift > 3) { - db->fragshift--; - db->numfrag = bufs >> db->fragshift; - } - db->fragsize = 1 << db->fragshift; - if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag) - db->numfrag = db->ossmaxfrags; - db->dmasize = db->numfrag << db->fragshift; - for(nr = 0; nr < NRSGBUF; nr++) { - if (!db->sgbuf[nr]) { - p = (void *)get_zeroed_page(GFP_KERNEL); - if (!p) - return -ENOMEM; - db->sgbuf[nr] = p; - SetPageReserved(virt_to_page(p)); - } - memset(db->sgbuf[nr], AFMT_ISUNSIGNED(db->format) ? 0x80 : 0, PAGE_SIZE); - if ((nr << PAGE_SHIFT) >= db->dmasize) - break; - } - db->bufsize = nr << PAGE_SHIFT; - db->ready = 1; - dprintk((KERN_DEBUG "usbaudio: dmabuf_init bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d " - "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x srate %d\n", - bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift, db->fragsize, - db->numfrag, db->dmasize, db->bufsize, db->format, db->srate)); - return 0; -} - -static int dmabuf_mmap(struct vm_area_struct *vma, struct dmabuf *db, unsigned long start, unsigned long size, pgprot_t prot) -{ - unsigned int nr; - - if (!db->ready || db->mapped || (start | size) & (PAGE_SIZE-1) || size > db->bufsize) - return -EINVAL; - size >>= PAGE_SHIFT; - for(nr = 0; nr < size; nr++) - if (!db->sgbuf[nr]) - return -EINVAL; - db->mapped = 1; - for(nr = 0; nr < size; nr++) { - unsigned long pfn; - - pfn = virt_to_phys(db->sgbuf[nr]) >> PAGE_SHIFT; - if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, prot)) - return -EAGAIN; - start += PAGE_SIZE; - } - return 0; -} - -static void dmabuf_copyin(struct dmabuf *db, const void *buffer, unsigned int size) -{ - unsigned int pgrem, rem; - - db->total_bytes += size; - for (;;) { - if (size <= 0) - return; - pgrem = ((~db->wrptr) & (PAGE_SIZE-1)) + 1; - if (pgrem > size) - pgrem = size; - rem = db->dmasize - db->wrptr; - if (pgrem > rem) - pgrem = rem; - memcpy((db->sgbuf[db->wrptr >> PAGE_SHIFT]) + (db->wrptr & (PAGE_SIZE-1)), buffer, pgrem); - size -= pgrem; - buffer += pgrem; - db->wrptr += pgrem; - if (db->wrptr >= db->dmasize) - db->wrptr = 0; - } -} - -static void dmabuf_copyout(struct dmabuf *db, void *buffer, unsigned int size) -{ - unsigned int pgrem, rem; - - db->total_bytes += size; - for (;;) { - if (size <= 0) - return; - pgrem = ((~db->rdptr) & (PAGE_SIZE-1)) + 1; - if (pgrem > size) - pgrem = size; - rem = db->dmasize - db->rdptr; - if (pgrem > rem) - pgrem = rem; - memcpy(buffer, (db->sgbuf[db->rdptr >> PAGE_SHIFT]) + (db->rdptr & (PAGE_SIZE-1)), pgrem); - size -= pgrem; - buffer += pgrem; - db->rdptr += pgrem; - if (db->rdptr >= db->dmasize) - db->rdptr = 0; - } -} - -static int dmabuf_copyin_user(struct dmabuf *db, unsigned int ptr, const void __user *buffer, unsigned int size) -{ - unsigned int pgrem, rem; - - if (!db->ready || db->mapped) - return -EINVAL; - for (;;) { - if (size <= 0) - return 0; - pgrem = ((~ptr) & (PAGE_SIZE-1)) + 1; - if (pgrem > size) - pgrem = size; - rem = db->dmasize - ptr; - if (pgrem > rem) - pgrem = rem; - if (copy_from_user((db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), buffer, pgrem)) - return -EFAULT; - size -= pgrem; - buffer += pgrem; - ptr += pgrem; - if (ptr >= db->dmasize) - ptr = 0; - } -} - -static int dmabuf_copyout_user(struct dmabuf *db, unsigned int ptr, void __user *buffer, unsigned int size) -{ - unsigned int pgrem, rem; - - if (!db->ready || db->mapped) - return -EINVAL; - for (;;) { - if (size <= 0) - return 0; - pgrem = ((~ptr) & (PAGE_SIZE-1)) + 1; - if (pgrem > size) - pgrem = size; - rem = db->dmasize - ptr; - if (pgrem > rem) - pgrem = rem; - if (copy_to_user(buffer, (db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), pgrem)) - return -EFAULT; - size -= pgrem; - buffer += pgrem; - ptr += pgrem; - if (ptr >= db->dmasize) - ptr = 0; - } -} - -/* --------------------------------------------------------------------- */ -/* - * USB I/O code. We do sample format conversion if necessary - */ - -static void usbin_stop(struct usb_audiodev *as) -{ - struct usbin *u = &as->usbin; - unsigned long flags; - unsigned int i, notkilled = 1; - - spin_lock_irqsave(&as->lock, flags); - u->flags &= ~FLG_RUNNING; - i = u->flags; - spin_unlock_irqrestore(&as->lock, flags); - while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) { - if (notkilled) - schedule_timeout_interruptible(1); - else - schedule_timeout_uninterruptible(1); - spin_lock_irqsave(&as->lock, flags); - i = u->flags; - spin_unlock_irqrestore(&as->lock, flags); - if (notkilled && signal_pending(current)) { - if (i & FLG_URB0RUNNING) - usb_kill_urb(u->durb[0].urb); - if (i & FLG_URB1RUNNING) - usb_kill_urb(u->durb[1].urb); - if (i & FLG_SYNC0RUNNING) - usb_kill_urb(u->surb[0].urb); - if (i & FLG_SYNC1RUNNING) - usb_kill_urb(u->surb[1].urb); - notkilled = 0; - } - } - set_current_state(TASK_RUNNING); - kfree(u->durb[0].urb->transfer_buffer); - kfree(u->durb[1].urb->transfer_buffer); - kfree(u->surb[0].urb->transfer_buffer); - kfree(u->surb[1].urb->transfer_buffer); - u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer = - u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL; -} - -static inline void usbin_release(struct usb_audiodev *as) -{ - usbin_stop(as); -} - -static void usbin_disc(struct usb_audiodev *as) -{ - struct usbin *u = &as->usbin; - - unsigned long flags; - - spin_lock_irqsave(&as->lock, flags); - u->flags &= ~(FLG_RUNNING | FLG_CONNECTED); - spin_unlock_irqrestore(&as->lock, flags); - usbin_stop(as); -} - -static void conversion(const void *ibuf, unsigned int ifmt, void *obuf, unsigned int ofmt, void *tmp, unsigned int scnt) -{ - unsigned int cnt, i; - __s16 *sp, *sp2, s; - unsigned char *bp; - - cnt = scnt; - if (AFMT_ISSTEREO(ifmt)) - cnt <<= 1; - sp = ((__s16 *)tmp) + cnt; - switch (ifmt & ~AFMT_STEREO) { - case AFMT_U8: - for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) { - bp--; - sp--; - *sp = (*bp ^ 0x80) << 8; - } - break; - - case AFMT_S8: - for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) { - bp--; - sp--; - *sp = *bp << 8; - } - break; - - case AFMT_U16_LE: - for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = (bp[0] | (bp[1] << 8)) ^ 0x8000; - } - break; - - case AFMT_U16_BE: - for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = (bp[1] | (bp[0] << 8)) ^ 0x8000; - } - break; - - case AFMT_S16_LE: - for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = bp[0] | (bp[1] << 8); - } - break; - - case AFMT_S16_BE: - for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = bp[1] | (bp[0] << 8); - } - break; - } - if (!AFMT_ISSTEREO(ifmt) && AFMT_ISSTEREO(ofmt)) { - /* expand from mono to stereo */ - for (sp = ((__s16 *)tmp)+scnt, sp2 = ((__s16 *)tmp)+2*scnt, i = 0; i < scnt; i++) { - sp--; - sp2 -= 2; - sp2[0] = sp2[1] = sp[0]; - } - } - if (AFMT_ISSTEREO(ifmt) && !AFMT_ISSTEREO(ofmt)) { - /* contract from stereo to mono */ - for (sp = sp2 = ((__s16 *)tmp), i = 0; i < scnt; i++, sp++, sp2 += 2) - sp[0] = (sp2[0] + sp2[1]) >> 1; - } - cnt = scnt; - if (AFMT_ISSTEREO(ofmt)) - cnt <<= 1; - sp = ((__s16 *)tmp); - bp = ((unsigned char *)obuf); - switch (ofmt & ~AFMT_STEREO) { - case AFMT_U8: - for (i = 0; i < cnt; i++, sp++, bp++) - *bp = (*sp >> 8) ^ 0x80; - break; - - case AFMT_S8: - for (i = 0; i < cnt; i++, sp++, bp++) - *bp = *sp >> 8; - break; - - case AFMT_U16_LE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[0] = s; - bp[1] = (s >> 8) ^ 0x80; - } - break; - - case AFMT_U16_BE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[1] = s; - bp[0] = (s >> 8) ^ 0x80; - } - break; - - case AFMT_S16_LE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[0] = s; - bp[1] = s >> 8; - } - break; - - case AFMT_S16_BE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[1] = s; - bp[0] = s >> 8; - } - break; - } - -} - -static void usbin_convert(struct usbin *u, unsigned char *buffer, unsigned int samples) -{ - union { - __s16 s[64]; - unsigned char b[0]; - } tmp; - unsigned int scnt, maxs, ufmtsh, dfmtsh; - - ufmtsh = AFMT_BYTESSHIFT(u->format); - dfmtsh = AFMT_BYTESSHIFT(u->dma.format); - maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64; - while (samples > 0) { - scnt = samples; - if (scnt > maxs) - scnt = maxs; - conversion(buffer, u->format, tmp.b, u->dma.format, tmp.b, scnt); - dmabuf_copyin(&u->dma, tmp.b, scnt << dfmtsh); - buffer += scnt << ufmtsh; - samples -= scnt; - } -} - -static int usbin_prepare_desc(struct usbin *u, struct urb *urb) -{ - unsigned int i, maxsize, offs; - - maxsize = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); - //printk(KERN_DEBUG "usbin_prepare_desc: maxsize %d freq 0x%x format 0x%x\n", maxsize, u->freqn, u->format); - for (i = offs = 0; i < DESCFRAMES; i++, offs += maxsize) { - urb->iso_frame_desc[i].length = maxsize; - urb->iso_frame_desc[i].offset = offs; - } - urb->interval = 1; - return 0; -} - -/* - * return value: 0 if descriptor should be restarted, -1 otherwise - * convert sample format on the fly if necessary - */ -static int usbin_retire_desc(struct usbin *u, struct urb *urb) -{ - unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, dmafree; - unsigned char *cp; - - ufmtsh = AFMT_BYTESSHIFT(u->format); - dfmtsh = AFMT_BYTESSHIFT(u->dma.format); - for (i = 0; i < DESCFRAMES; i++) { - cp = ((unsigned char *)urb->transfer_buffer) + urb->iso_frame_desc[i].offset; - if (urb->iso_frame_desc[i].status) { - dprintk((KERN_DEBUG "usbin_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); - continue; - } - scnt = urb->iso_frame_desc[i].actual_length >> ufmtsh; - if (!scnt) - continue; - cnt = scnt << dfmtsh; - if (!u->dma.mapped) { - dmafree = u->dma.dmasize - u->dma.count; - if (cnt > dmafree) { - scnt = dmafree >> dfmtsh; - cnt = scnt << dfmtsh; - err++; - } - } - u->dma.count += cnt; - if (u->format == u->dma.format) { - /* we do not need format conversion */ - dprintk((KERN_DEBUG "usbaudio: no sample format conversion\n")); - dmabuf_copyin(&u->dma, cp, cnt); - } else { - /* we need sampling format conversion */ - dprintk((KERN_DEBUG "usbaudio: sample format conversion %x != %x\n", u->format, u->dma.format)); - usbin_convert(u, cp, scnt); - } - } - if (err) - u->dma.error++; - if (u->dma.count >= (signed)u->dma.fragsize) - wake_up(&u->dma.wait); - return err ? -1 : 0; -} - -static void usbin_completed(struct urb *urb, struct pt_regs *regs) -{ - struct usb_audiodev *as = (struct usb_audiodev *)urb->context; - struct usbin *u = &as->usbin; - unsigned long flags; - unsigned int mask; - int suret = 0; - -#if 0 - printk(KERN_DEBUG "usbin_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); -#endif - if (urb == u->durb[0].urb) - mask = FLG_URB0RUNNING; - else if (urb == u->durb[1].urb) - mask = FLG_URB1RUNNING; - else { - mask = 0; - printk(KERN_ERR "usbin_completed: panic: unknown URB\n"); - } - urb->dev = as->state->usbdev; - spin_lock_irqsave(&as->lock, flags); - if (!usbin_retire_desc(u, urb) && - u->flags & FLG_RUNNING && - !usbin_prepare_desc(u, urb) && - (suret = usb_submit_urb(urb, GFP_ATOMIC)) == 0) { - u->flags |= mask; - } else { - u->flags &= ~(mask | FLG_RUNNING); - wake_up(&u->dma.wait); - printk(KERN_DEBUG "usbin_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret); - } - spin_unlock_irqrestore(&as->lock, flags); -} - -/* - * we output sync data - */ -static int usbin_sync_prepare_desc(struct usbin *u, struct urb *urb) -{ - unsigned char *cp = urb->transfer_buffer; - unsigned int i, offs; - - for (i = offs = 0; i < SYNCFRAMES; i++, offs += 3, cp += 3) { - urb->iso_frame_desc[i].length = 3; - urb->iso_frame_desc[i].offset = offs; - cp[0] = u->freqn; - cp[1] = u->freqn >> 8; - cp[2] = u->freqn >> 16; - } - urb->interval = 1; - return 0; -} - -/* - * return value: 0 if descriptor should be restarted, -1 otherwise - */ -static int usbin_sync_retire_desc(struct usbin *u, struct urb *urb) -{ - unsigned int i; - - for (i = 0; i < SYNCFRAMES; i++) - if (urb->iso_frame_desc[0].status) - dprintk((KERN_DEBUG "usbin_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); - return 0; -} - -static void usbin_sync_completed(struct urb *urb, struct pt_regs *regs) -{ - struct usb_audiodev *as = (struct usb_audiodev *)urb->context; - struct usbin *u = &as->usbin; - unsigned long flags; - unsigned int mask; - int suret = 0; - -#if 0 - printk(KERN_DEBUG "usbin_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); -#endif - if (urb == u->surb[0].urb) - mask = FLG_SYNC0RUNNING; - else if (urb == u->surb[1].urb) - mask = FLG_SYNC1RUNNING; - else { - mask = 0; - printk(KERN_ERR "usbin_sync_completed: panic: unknown URB\n"); - } - urb->dev = as->state->usbdev; - spin_lock_irqsave(&as->lock, flags); - if (!usbin_sync_retire_desc(u, urb) && - u->flags & FLG_RUNNING && - !usbin_sync_prepare_desc(u, urb) && - (suret = usb_submit_urb(urb, GFP_ATOMIC)) == 0) { - u->flags |= mask; - } else { - u->flags &= ~(mask | FLG_RUNNING); - wake_up(&u->dma.wait); - dprintk((KERN_DEBUG "usbin_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret)); - } - spin_unlock_irqrestore(&as->lock, flags); -} - -static int usbin_start(struct usb_audiodev *as) -{ - struct usb_device *dev = as->state->usbdev; - struct usbin *u = &as->usbin; - struct urb *urb; - unsigned long flags; - unsigned int maxsze, bufsz; - -#if 0 - printk(KERN_DEBUG "usbin_start: device %d ufmt 0x%08x dfmt 0x%08x srate %d\n", - dev->devnum, u->format, u->dma.format, u->dma.srate); -#endif - /* allocate USB storage if not already done */ - spin_lock_irqsave(&as->lock, flags); - if (!(u->flags & FLG_CONNECTED)) { - spin_unlock_irqrestore(&as->lock, flags); - return -EIO; - } - if (!(u->flags & FLG_RUNNING)) { - spin_unlock_irqrestore(&as->lock, flags); - u->freqn = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */ - u->freqmax = u->freqn + (u->freqn >> 2); - u->phase = 0; - maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); - bufsz = DESCFRAMES * maxsze; - kfree(u->durb[0].urb->transfer_buffer); - u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); - u->durb[0].urb->transfer_buffer_length = bufsz; - kfree(u->durb[1].urb->transfer_buffer); - u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); - u->durb[1].urb->transfer_buffer_length = bufsz; - if (u->syncpipe) { - kfree(u->surb[0].urb->transfer_buffer); - u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); - u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES; - kfree(u->surb[1].urb->transfer_buffer); - u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); - u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES; - } - if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer || - (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) { - printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum); - return 0; - } - spin_lock_irqsave(&as->lock, flags); - } - if (u->dma.count >= u->dma.dmasize && !u->dma.mapped) { - spin_unlock_irqrestore(&as->lock, flags); - return 0; - } - u->flags |= FLG_RUNNING; - if (!(u->flags & FLG_URB0RUNNING)) { - urb = u->durb[0].urb; - urb->dev = dev; - urb->pipe = u->datapipe; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = DESCFRAMES; - urb->context = as; - urb->complete = usbin_completed; - if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL)) - u->flags |= FLG_URB0RUNNING; - else - u->flags &= ~FLG_RUNNING; - } - if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) { - urb = u->durb[1].urb; - urb->dev = dev; - urb->pipe = u->datapipe; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = DESCFRAMES; - urb->context = as; - urb->complete = usbin_completed; - if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL)) - u->flags |= FLG_URB1RUNNING; - else - u->flags &= ~FLG_RUNNING; - } - if (u->syncpipe) { - if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) { - urb = u->surb[0].urb; - urb->dev = dev; - urb->pipe = u->syncpipe; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = SYNCFRAMES; - urb->context = as; - urb->complete = usbin_sync_completed; - /* stride: u->syncinterval */ - if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL)) - u->flags |= FLG_SYNC0RUNNING; - else - u->flags &= ~FLG_RUNNING; - } - if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) { - urb = u->surb[1].urb; - urb->dev = dev; - urb->pipe = u->syncpipe; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = SYNCFRAMES; - urb->context = as; - urb->complete = usbin_sync_completed; - /* stride: u->syncinterval */ - if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL)) - u->flags |= FLG_SYNC1RUNNING; - else - u->flags &= ~FLG_RUNNING; - } - } - spin_unlock_irqrestore(&as->lock, flags); - return 0; -} - -static void usbout_stop(struct usb_audiodev *as) -{ - struct usbout *u = &as->usbout; - unsigned long flags; - unsigned int i, notkilled = 1; - - spin_lock_irqsave(&as->lock, flags); - u->flags &= ~FLG_RUNNING; - i = u->flags; - spin_unlock_irqrestore(&as->lock, flags); - while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) { - if (notkilled) - schedule_timeout_interruptible(1); - else - schedule_timeout_uninterruptible(1); - spin_lock_irqsave(&as->lock, flags); - i = u->flags; - spin_unlock_irqrestore(&as->lock, flags); - if (notkilled && signal_pending(current)) { - if (i & FLG_URB0RUNNING) - usb_kill_urb(u->durb[0].urb); - if (i & FLG_URB1RUNNING) - usb_kill_urb(u->durb[1].urb); - if (i & FLG_SYNC0RUNNING) - usb_kill_urb(u->surb[0].urb); - if (i & FLG_SYNC1RUNNING) - usb_kill_urb(u->surb[1].urb); - notkilled = 0; - } - } - set_current_state(TASK_RUNNING); - kfree(u->durb[0].urb->transfer_buffer); - kfree(u->durb[1].urb->transfer_buffer); - kfree(u->surb[0].urb->transfer_buffer); - kfree(u->surb[1].urb->transfer_buffer); - u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer = - u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL; -} - -static inline void usbout_release(struct usb_audiodev *as) -{ - usbout_stop(as); -} - -static void usbout_disc(struct usb_audiodev *as) -{ - struct usbout *u = &as->usbout; - unsigned long flags; - - spin_lock_irqsave(&as->lock, flags); - u->flags &= ~(FLG_RUNNING | FLG_CONNECTED); - spin_unlock_irqrestore(&as->lock, flags); - usbout_stop(as); -} - -static void usbout_convert(struct usbout *u, unsigned char *buffer, unsigned int samples) -{ - union { - __s16 s[64]; - unsigned char b[0]; - } tmp; - unsigned int scnt, maxs, ufmtsh, dfmtsh; - - ufmtsh = AFMT_BYTESSHIFT(u->format); - dfmtsh = AFMT_BYTESSHIFT(u->dma.format); - maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64; - while (samples > 0) { - scnt = samples; - if (scnt > maxs) - scnt = maxs; - dmabuf_copyout(&u->dma, tmp.b, scnt << dfmtsh); - conversion(tmp.b, u->dma.format, buffer, u->format, tmp.b, scnt); - buffer += scnt << ufmtsh; - samples -= scnt; - } -} - -static int usbout_prepare_desc(struct usbout *u, struct urb *urb) -{ - unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, offs; - unsigned char *cp = urb->transfer_buffer; - - ufmtsh = AFMT_BYTESSHIFT(u->format); - dfmtsh = AFMT_BYTESSHIFT(u->dma.format); - for (i = offs = 0; i < DESCFRAMES; i++) { - urb->iso_frame_desc[i].offset = offs; - u->phase = (u->phase & 0x3fff) + u->freqm; - scnt = u->phase >> 14; - if (!scnt) { - urb->iso_frame_desc[i].length = 0; - continue; - } - cnt = scnt << dfmtsh; - if (!u->dma.mapped) { - if (cnt > u->dma.count) { - scnt = u->dma.count >> dfmtsh; - cnt = scnt << dfmtsh; - err++; - } - u->dma.count -= cnt; - } else - u->dma.count += cnt; - if (u->format == u->dma.format) { - /* we do not need format conversion */ - dmabuf_copyout(&u->dma, cp, cnt); - } else { - /* we need sampling format conversion */ - usbout_convert(u, cp, scnt); - } - cnt = scnt << ufmtsh; - urb->iso_frame_desc[i].length = cnt; - offs += cnt; - cp += cnt; - } - urb->interval = 1; - if (err) - u->dma.error++; - if (u->dma.mapped) { - if (u->dma.count >= (signed)u->dma.fragsize) - wake_up(&u->dma.wait); - } else { - if ((signed)u->dma.dmasize >= u->dma.count + (signed)u->dma.fragsize) - wake_up(&u->dma.wait); - } - return err ? -1 : 0; -} - -/* - * return value: 0 if descriptor should be restarted, -1 otherwise - */ -static int usbout_retire_desc(struct usbout *u, struct urb *urb) -{ - unsigned int i; - - for (i = 0; i < DESCFRAMES; i++) { - if (urb->iso_frame_desc[i].status) { - dprintk((KERN_DEBUG "usbout_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); - continue; - } - } - return 0; -} - -static void usbout_completed(struct urb *urb, struct pt_regs *regs) -{ - struct usb_audiodev *as = (struct usb_audiodev *)urb->context; - struct usbout *u = &as->usbout; - unsigned long flags; - unsigned int mask; - int suret = 0; - -#if 0 - printk(KERN_DEBUG "usbout_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); -#endif - if (urb == u->durb[0].urb) - mask = FLG_URB0RUNNING; - else if (urb == u->durb[1].urb) - mask = FLG_URB1RUNNING; - else { - mask = 0; - printk(KERN_ERR "usbout_completed: panic: unknown URB\n"); - } - urb->dev = as->state->usbdev; - spin_lock_irqsave(&as->lock, flags); - if (!usbout_retire_desc(u, urb) && - u->flags & FLG_RUNNING && - !usbout_prepare_desc(u, urb) && - (suret = usb_submit_urb(urb, GFP_ATOMIC)) == 0) { - u->flags |= mask; - } else { - u->flags &= ~(mask | FLG_RUNNING); - wake_up(&u->dma.wait); - dprintk((KERN_DEBUG "usbout_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret)); - } - spin_unlock_irqrestore(&as->lock, flags); -} - -static int usbout_sync_prepare_desc(struct usbout *u, struct urb *urb) -{ - unsigned int i, offs; - - for (i = offs = 0; i < SYNCFRAMES; i++, offs += 3) { - urb->iso_frame_desc[i].length = 3; - urb->iso_frame_desc[i].offset = offs; - } - urb->interval = 1; - return 0; -} - -/* - * return value: 0 if descriptor should be restarted, -1 otherwise - */ -static int usbout_sync_retire_desc(struct usbout *u, struct urb *urb) -{ - unsigned char *cp = urb->transfer_buffer; - unsigned int f, i; - - for (i = 0; i < SYNCFRAMES; i++, cp += 3) { - if (urb->iso_frame_desc[i].status) { - dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); - continue; - } - if (urb->iso_frame_desc[i].actual_length < 3) { - dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u length %d\n", i, urb->iso_frame_desc[i].actual_length)); - continue; - } - f = cp[0] | (cp[1] << 8) | (cp[2] << 16); - if (abs(f - u->freqn) > (u->freqn >> 3) || f > u->freqmax) { - printk(KERN_WARNING "usbout_sync_retire_desc: requested frequency %u (nominal %u) out of range!\n", f, u->freqn); - continue; - } - u->freqm = f; - } - return 0; -} - -static void usbout_sync_completed(struct urb *urb, struct pt_regs *regs) -{ - struct usb_audiodev *as = (struct usb_audiodev *)urb->context; - struct usbout *u = &as->usbout; - unsigned long flags; - unsigned int mask; - int suret = 0; - -#if 0 - printk(KERN_DEBUG "usbout_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); -#endif - if (urb == u->surb[0].urb) - mask = FLG_SYNC0RUNNING; - else if (urb == u->surb[1].urb) - mask = FLG_SYNC1RUNNING; - else { - mask = 0; - printk(KERN_ERR "usbout_sync_completed: panic: unknown URB\n"); - } - urb->dev = as->state->usbdev; - spin_lock_irqsave(&as->lock, flags); - if (!usbout_sync_retire_desc(u, urb) && - u->flags & FLG_RUNNING && - !usbout_sync_prepare_desc(u, urb) && - (suret = usb_submit_urb(urb, GFP_ATOMIC)) == 0) { - u->flags |= mask; - } else { - u->flags &= ~(mask | FLG_RUNNING); - wake_up(&u->dma.wait); - dprintk((KERN_DEBUG "usbout_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret)); - } - spin_unlock_irqrestore(&as->lock, flags); -} - -static int usbout_start(struct usb_audiodev *as) -{ - struct usb_device *dev = as->state->usbdev; - struct usbout *u = &as->usbout; - struct urb *urb; - unsigned long flags; - unsigned int maxsze, bufsz; - -#if 0 - printk(KERN_DEBUG "usbout_start: device %d ufmt 0x%08x dfmt 0x%08x srate %d\n", - dev->devnum, u->format, u->dma.format, u->dma.srate); -#endif - /* allocate USB storage if not already done */ - spin_lock_irqsave(&as->lock, flags); - if (!(u->flags & FLG_CONNECTED)) { - spin_unlock_irqrestore(&as->lock, flags); - return -EIO; - } - if (!(u->flags & FLG_RUNNING)) { - spin_unlock_irqrestore(&as->lock, flags); - u->freqn = u->freqm = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */ - u->freqmax = u->freqn + (u->freqn >> 2); - u->phase = 0; - maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); - bufsz = DESCFRAMES * maxsze; - kfree(u->durb[0].urb->transfer_buffer); - u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); - u->durb[0].urb->transfer_buffer_length = bufsz; - kfree(u->durb[1].urb->transfer_buffer); - u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); - u->durb[1].urb->transfer_buffer_length = bufsz; - if (u->syncpipe) { - kfree(u->surb[0].urb->transfer_buffer); - u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); - u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES; - kfree(u->surb[1].urb->transfer_buffer); - u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); - u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES; - } - if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer || - (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) { - printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum); - return 0; - } - spin_lock_irqsave(&as->lock, flags); - } - if (u->dma.count <= 0 && !u->dma.mapped) { - spin_unlock_irqrestore(&as->lock, flags); - return 0; - } - u->flags |= FLG_RUNNING; - if (!(u->flags & FLG_URB0RUNNING)) { - urb = u->durb[0].urb; - urb->dev = dev; - urb->pipe = u->datapipe; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = DESCFRAMES; - urb->context = as; - urb->complete = usbout_completed; - if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_ATOMIC)) - u->flags |= FLG_URB0RUNNING; - else - u->flags &= ~FLG_RUNNING; - } - if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) { - urb = u->durb[1].urb; - urb->dev = dev; - urb->pipe = u->datapipe; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = DESCFRAMES; - urb->context = as; - urb->complete = usbout_completed; - if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_ATOMIC)) - u->flags |= FLG_URB1RUNNING; - else - u->flags &= ~FLG_RUNNING; - } - if (u->syncpipe) { - if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) { - urb = u->surb[0].urb; - urb->dev = dev; - urb->pipe = u->syncpipe; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = SYNCFRAMES; - urb->context = as; - urb->complete = usbout_sync_completed; - /* stride: u->syncinterval */ - if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_ATOMIC)) - u->flags |= FLG_SYNC0RUNNING; - else - u->flags &= ~FLG_RUNNING; - } - if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) { - urb = u->surb[1].urb; - urb->dev = dev; - urb->pipe = u->syncpipe; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = SYNCFRAMES; - urb->context = as; - urb->complete = usbout_sync_completed; - /* stride: u->syncinterval */ - if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_ATOMIC)) - u->flags |= FLG_SYNC1RUNNING; - else - u->flags &= ~FLG_RUNNING; - } - } - spin_unlock_irqrestore(&as->lock, flags); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static unsigned int format_goodness(struct audioformat *afp, unsigned int fmt, unsigned int srate) -{ - unsigned int g = 0; - - if (srate < afp->sratelo) - g += afp->sratelo - srate; - if (srate > afp->sratehi) - g += srate - afp->sratehi; - if (AFMT_ISSTEREO(afp->format) && !AFMT_ISSTEREO(fmt)) - g += 0x100000; - if (!AFMT_ISSTEREO(afp->format) && AFMT_ISSTEREO(fmt)) - g += 0x400000; - if (AFMT_IS16BIT(afp->format) && !AFMT_IS16BIT(fmt)) - g += 0x100000; - if (!AFMT_IS16BIT(afp->format) && AFMT_IS16BIT(fmt)) - g += 0x400000; - return g; -} - -static int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int srate) -{ - unsigned int i, g, gb = ~0; - int j = -1; /* default to failure */ - - /* find "best" format (according to format_goodness) */ - for (i = 0; i < nr; i++) { - g = format_goodness(&afp[i], fmt, srate); - if (g >= gb) - continue; - j = i; - gb = g; - } - return j; -} - -static int set_format_in(struct usb_audiodev *as) -{ - struct usb_device *dev = as->state->usbdev; - struct usb_host_interface *alts; - struct usb_interface *iface; - struct usbin *u = &as->usbin; - struct dmabuf *d = &u->dma; - struct audioformat *fmt; - unsigned int ep; - unsigned char data[3]; - int fmtnr, ret; - - iface = usb_ifnum_to_if(dev, u->interface); - if (!iface) - return 0; - - fmtnr = find_format(as->fmtin, as->numfmtin, d->format, d->srate); - if (fmtnr < 0) { - printk(KERN_ERR "usbaudio: set_format_in(): failed to find desired format/speed combination.\n"); - return -1; - } - - fmt = as->fmtin + fmtnr; - alts = usb_altnum_to_altsetting(iface, fmt->altsetting); - u->format = fmt->format; - u->datapipe = usb_rcvisocpipe(dev, alts->endpoint[0].desc.bEndpointAddress & 0xf); - u->syncpipe = u->syncinterval = 0; - if ((alts->endpoint[0].desc.bmAttributes & 0x0c) == 0x08) { - if (alts->desc.bNumEndpoints < 2 || - alts->endpoint[1].desc.bmAttributes != 0x01 || - alts->endpoint[1].desc.bSynchAddress != 0 || - alts->endpoint[1].desc.bEndpointAddress != (alts->endpoint[0].desc.bSynchAddress & 0x7f)) { - printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims adaptive in " - "but has invalid synch pipe; treating as asynchronous in\n", - dev->devnum, u->interface, fmt->altsetting); - } else { - u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf); - u->syncinterval = alts->endpoint[1].desc.bRefresh; - } - } - if (d->srate < fmt->sratelo) - d->srate = fmt->sratelo; - if (d->srate > fmt->sratehi) - d->srate = fmt->sratehi; - dprintk((KERN_DEBUG "usbaudio: set_format_in: usb_set_interface %u %u\n", - u->interface, fmt->altsetting)); - if (usb_set_interface(dev, alts->desc.bInterfaceNumber, fmt->altsetting) < 0) { - printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", - dev->devnum, u->interface, fmt->altsetting); - return -1; - } - if (fmt->sratelo == fmt->sratehi) - return 0; - ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN); - /* if endpoint has pitch control, enable it */ - if (fmt->attributes & 0x02) { - data[0] = 1; - if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, - PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) { - printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n", - ret, dev->devnum, u->interface, ep, d->srate); - return -1; - } - } - /* if endpoint has sampling rate control, set it */ - if (fmt->attributes & 0x01) { - data[0] = d->srate; - data[1] = d->srate >> 8; - data[2] = d->srate >> 16; - if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, - SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { - printk(KERN_ERR "usbaudio: failure (error %d) to set input sampling frequency device %d interface %u endpoint 0x%x to %u\n", - ret, dev->devnum, u->interface, ep, d->srate); - return -1; - } - if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, - SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { - printk(KERN_ERR "usbaudio: failure (error %d) to get input sampling frequency device %d interface %u endpoint 0x%x\n", - ret, dev->devnum, u->interface, ep); - return -1; - } - dprintk((KERN_DEBUG "usbaudio: set_format_in: device %d interface %d altsetting %d srate req: %u real %u\n", - dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16))); - d->srate = data[0] | (data[1] << 8) | (data[2] << 16); - } - dprintk((KERN_DEBUG "usbaudio: set_format_in: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate)); - return 0; -} - -static int set_format_out(struct usb_audiodev *as) -{ - struct usb_device *dev = as->state->usbdev; - struct usb_host_interface *alts; - struct usb_interface *iface; - struct usbout *u = &as->usbout; - struct dmabuf *d = &u->dma; - struct audioformat *fmt; - unsigned int ep; - unsigned char data[3]; - int fmtnr, ret; - - iface = usb_ifnum_to_if(dev, u->interface); - if (!iface) - return 0; - - fmtnr = find_format(as->fmtout, as->numfmtout, d->format, d->srate); - if (fmtnr < 0) { - printk(KERN_ERR "usbaudio: set_format_out(): failed to find desired format/speed combination.\n"); - return -1; - } - - fmt = as->fmtout + fmtnr; - u->format = fmt->format; - alts = usb_altnum_to_altsetting(iface, fmt->altsetting); - u->datapipe = usb_sndisocpipe(dev, alts->endpoint[0].desc.bEndpointAddress & 0xf); - u->syncpipe = u->syncinterval = 0; - if ((alts->endpoint[0].desc.bmAttributes & 0x0c) == 0x04) { -#if 0 - printk(KERN_DEBUG "bNumEndpoints 0x%02x endpoint[1].bmAttributes 0x%02x\n" - KERN_DEBUG "endpoint[1].bSynchAddress 0x%02x endpoint[1].bEndpointAddress 0x%02x\n" - KERN_DEBUG "endpoint[0].bSynchAddress 0x%02x\n", alts->bNumEndpoints, - alts->endpoint[1].bmAttributes, alts->endpoint[1].bSynchAddress, - alts->endpoint[1].bEndpointAddress, alts->endpoint[0].bSynchAddress); -#endif - if (alts->desc.bNumEndpoints < 2 || - alts->endpoint[1].desc.bmAttributes != 0x01 || - alts->endpoint[1].desc.bSynchAddress != 0 || - alts->endpoint[1].desc.bEndpointAddress != (alts->endpoint[0].desc.bSynchAddress | 0x80)) { - printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims asynch out " - "but has invalid synch pipe; treating as adaptive out\n", - dev->devnum, u->interface, fmt->altsetting); - } else { - u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf); - u->syncinterval = alts->endpoint[1].desc.bRefresh; - } - } - if (d->srate < fmt->sratelo) - d->srate = fmt->sratelo; - if (d->srate > fmt->sratehi) - d->srate = fmt->sratehi; - dprintk((KERN_DEBUG "usbaudio: set_format_out: usb_set_interface %u %u\n", - u->interface, fmt->altsetting)); - if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) { - printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", - dev->devnum, u->interface, fmt->altsetting); - return -1; - } - if (fmt->sratelo == fmt->sratehi) - return 0; - ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN); - /* if endpoint has pitch control, enable it */ - if (fmt->attributes & 0x02) { - data[0] = 1; - if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, - PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) { - printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n", - ret, dev->devnum, u->interface, ep, d->srate); - return -1; - } - } - /* if endpoint has sampling rate control, set it */ - if (fmt->attributes & 0x01) { - data[0] = d->srate; - data[1] = d->srate >> 8; - data[2] = d->srate >> 16; - if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, - SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { - printk(KERN_ERR "usbaudio: failure (error %d) to set output sampling frequency device %d interface %u endpoint 0x%x to %u\n", - ret, dev->devnum, u->interface, ep, d->srate); - return -1; - } - if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, - SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { - printk(KERN_ERR "usbaudio: failure (error %d) to get output sampling frequency device %d interface %u endpoint 0x%x\n", - ret, dev->devnum, u->interface, ep); - return -1; - } - dprintk((KERN_DEBUG "usbaudio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n", - dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16))); - d->srate = data[0] | (data[1] << 8) | (data[2] << 16); - } - dprintk((KERN_DEBUG "usbaudio: set_format_out: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate)); - return 0; -} - -static int set_format(struct usb_audiodev *s, unsigned int fmode, unsigned int fmt, unsigned int srate) -{ - int ret1 = 0, ret2 = 0; - - if (!(fmode & (FMODE_READ|FMODE_WRITE))) - return -EINVAL; - if (fmode & FMODE_READ) { - usbin_stop(s); - s->usbin.dma.ready = 0; - if (fmt == AFMT_QUERY) - fmt = s->usbin.dma.format; - else - s->usbin.dma.format = fmt; - if (!srate) - srate = s->usbin.dma.srate; - else - s->usbin.dma.srate = srate; - } - if (fmode & FMODE_WRITE) { - usbout_stop(s); - s->usbout.dma.ready = 0; - if (fmt == AFMT_QUERY) - fmt = s->usbout.dma.format; - else - s->usbout.dma.format = fmt; - if (!srate) - srate = s->usbout.dma.srate; - else - s->usbout.dma.srate = srate; - } - if (fmode & FMODE_READ) - ret1 = set_format_in(s); - if (fmode & FMODE_WRITE) - ret2 = set_format_out(s); - return ret1 ? ret1 : ret2; -} - -/* --------------------------------------------------------------------- */ - -static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value) -{ - struct usb_device *dev = ms->state->usbdev; - unsigned char data[2]; - struct mixerchannel *ch; - int v1, v2, v3; - - if (mixch >= ms->numch) - return -1; - ch = &ms->ch[mixch]; - v3 = ch->maxval - ch->minval; - v1 = value & 0xff; - v2 = (value >> 8) & 0xff; - if (v1 > 100) - v1 = 100; - if (v2 > 100) - v2 = 100; - if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) - v2 = v1; - ch->value = v1 | (v2 << 8); - v1 = (v1 * v3) / 100 + ch->minval; - v2 = (v2 * v3) / 100 + ch->minval; - switch (ch->selector) { - case 0: /* mixer unit request */ - data[0] = v1; - data[1] = v1 >> 8; - if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - (ch->chnum << 8) | 1, ms->iface | (ch->unitid << 8), data, 2, 1000) < 0) - goto err; - if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) - return 0; - data[0] = v2; - data[1] = v2 >> 8; - if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)), - ms->iface | (ch->unitid << 8), data, 2, 1000) < 0) - goto err; - return 0; - - /* various feature unit controls */ - case VOLUME_CONTROL: - data[0] = v1; - data[1] = v1 >> 8; - if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 2, 1000) < 0) - goto err; - if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) - return 0; - data[0] = v2; - data[1] = v2 >> 8; - if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, 1000) < 0) - goto err; - return 0; - - case BASS_CONTROL: - case MID_CONTROL: - case TREBLE_CONTROL: - data[0] = v1 >> 8; - if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 1, 1000) < 0) - goto err; - if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) - return 0; - data[0] = v2 >> 8; - if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, 1000) < 0) - goto err; - return 0; - - default: - return -1; - } - return 0; - - err: - printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", - dev->devnum, ms->iface, ch->unitid, ch->chnum, ch->selector); - return -1; -} - -static int get_rec_src(struct usb_mixerdev *ms) -{ - struct usb_device *dev = ms->state->usbdev; - unsigned int mask = 0, retmask = 0; - unsigned int i, j; - unsigned char buf; - int err = 0; - - for (i = 0; i < ms->numch; i++) { - if (!ms->ch[i].slctunitid || (mask & (1 << i))) - continue; - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - 0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, 1000) < 0) { - err = -EIO; - printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", - dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff); - continue; - } - for (j = i; j < ms->numch; j++) { - if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) - continue; - mask |= 1 << j; - if (buf == (ms->ch[j].slctunitid >> 8)) - retmask |= 1 << ms->ch[j].osschannel; - } - } - if (err) - return -EIO; - return retmask; -} - -static int set_rec_src(struct usb_mixerdev *ms, int srcmask) -{ - struct usb_device *dev = ms->state->usbdev; - unsigned int mask = 0, smask, bmask; - unsigned int i, j; - unsigned char buf; - int err = 0; - - for (i = 0; i < ms->numch; i++) { - if (!ms->ch[i].slctunitid || (mask & (1 << i))) - continue; - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - 0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, 1000) < 0) { - err = -EIO; - printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", - dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff); - continue; - } - /* first generate smask */ - smask = bmask = 0; - for (j = i; j < ms->numch; j++) { - if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) - continue; - smask |= 1 << ms->ch[j].osschannel; - if (buf == (ms->ch[j].slctunitid >> 8)) - bmask |= 1 << ms->ch[j].osschannel; - mask |= 1 << j; - } - /* check for multiple set sources */ - j = hweight32(srcmask & smask); - if (j == 0) - continue; - if (j > 1) - srcmask &= ~bmask; - for (j = i; j < ms->numch; j++) { - if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) - continue; - if (!(srcmask & (1 << ms->ch[j].osschannel))) - continue; - buf = ms->ch[j].slctunitid >> 8; - if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - 0, ms->iface | (ms->ch[j].slctunitid << 8), &buf, 1, 1000) < 0) { - err = -EIO; - printk(KERN_ERR "usbaudio: selector write request device %u if %u unit %u failed\n", - dev->devnum, ms->iface, ms->ch[j].slctunitid & 0xff); - continue; - } - } - } - return err ? -EIO : 0; -} - -/* --------------------------------------------------------------------- */ - -/* - * should be called with open_sem hold, so that no new processes - * look at the audio device to be destroyed - */ - -static void release(struct usb_audio_state *s) -{ - struct usb_audiodev *as; - struct usb_mixerdev *ms; - - s->count--; - if (s->count) { - up(&open_sem); - return; - } - up(&open_sem); - wake_up(&open_wait); - while (!list_empty(&s->audiolist)) { - as = list_entry(s->audiolist.next, struct usb_audiodev, list); - list_del(&as->list); - usbin_release(as); - usbout_release(as); - dmabuf_release(&as->usbin.dma); - dmabuf_release(&as->usbout.dma); - usb_free_urb(as->usbin.durb[0].urb); - usb_free_urb(as->usbin.durb[1].urb); - usb_free_urb(as->usbin.surb[0].urb); - usb_free_urb(as->usbin.surb[1].urb); - usb_free_urb(as->usbout.durb[0].urb); - usb_free_urb(as->usbout.durb[1].urb); - usb_free_urb(as->usbout.surb[0].urb); - usb_free_urb(as->usbout.surb[1].urb); - kfree(as); - } - while (!list_empty(&s->mixerlist)) { - ms = list_entry(s->mixerlist.next, struct usb_mixerdev, list); - list_del(&ms->list); - kfree(ms); - } - kfree(s); -} - -static inline int prog_dmabuf_in(struct usb_audiodev *as) -{ - usbin_stop(as); - return dmabuf_init(&as->usbin.dma); -} - -static inline int prog_dmabuf_out(struct usb_audiodev *as) -{ - usbout_stop(as); - return dmabuf_init(&as->usbout.dma); -} - -/* --------------------------------------------------------------------- */ - -static int usb_audio_open_mixdev(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode); - struct usb_mixerdev *ms; - struct usb_audio_state *s; - - down(&open_sem); - list_for_each_entry(s, &audiodevs, audiodev) { - list_for_each_entry(ms, &s->mixerlist, list) { - if (ms->dev_mixer == minor) - goto mixer_found; - } - } - up(&open_sem); - return -ENODEV; - - mixer_found: - if (!s->usbdev) { - up(&open_sem); - return -EIO; - } - file->private_data = ms; - s->count++; - - up(&open_sem); - return nonseekable_open(inode, file); -} - -static int usb_audio_release_mixdev(struct inode *inode, struct file *file) -{ - struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data; - struct usb_audio_state *s; - - lock_kernel(); - s = ms->state; - down(&open_sem); - release(s); - unlock_kernel(); - return 0; -} - -static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data; - int i, j, val; - int __user *user_arg = (int __user *)arg; - - if (!ms->state->usbdev) - return -ENODEV; - - if (cmd == SOUND_MIXER_INFO) { - mixer_info info; - - memset(&info, 0, sizeof(info)); - strncpy(info.id, "USB_AUDIO", sizeof(info.id)); - strncpy(info.name, "USB Audio Class Driver", sizeof(info.name)); - info.modify_counter = ms->modcnt; - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == SOUND_OLD_MIXER_INFO) { - _old_mixer_info info; - - memset(&info, 0, sizeof(info)); - strncpy(info.id, "USB_AUDIO", sizeof(info.id)); - strncpy(info.name, "USB Audio Class Driver", sizeof(info.name)); - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == OSS_GETVERSION) - return put_user(SOUND_VERSION, user_arg); - if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) - return -EINVAL; - if (_IOC_DIR(cmd) == _IOC_READ) { - switch (_IOC_NR(cmd)) { - case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ - val = get_rec_src(ms); - if (val < 0) - return val; - return put_user(val, user_arg); - - case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */ - for (val = i = 0; i < ms->numch; i++) - val |= 1 << ms->ch[i].osschannel; - return put_user(val, user_arg); - - case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ - for (val = i = 0; i < ms->numch; i++) - if (ms->ch[i].slctunitid) - val |= 1 << ms->ch[i].osschannel; - return put_user(val, user_arg); - - case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ - for (val = i = 0; i < ms->numch; i++) - if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) - val |= 1 << ms->ch[i].osschannel; - return put_user(val, user_arg); - - case SOUND_MIXER_CAPS: - return put_user(SOUND_CAP_EXCL_INPUT, user_arg); - - default: - i = _IOC_NR(cmd); - if (i >= SOUND_MIXER_NRDEVICES) - return -EINVAL; - for (j = 0; j < ms->numch; j++) { - if (ms->ch[j].osschannel == i) { - return put_user(ms->ch[j].value, user_arg); - } - } - return -EINVAL; - } - } - if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) - return -EINVAL; - ms->modcnt++; - switch (_IOC_NR(cmd)) { - case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ - if (get_user(val, user_arg)) - return -EFAULT; - return set_rec_src(ms, val); - - default: - i = _IOC_NR(cmd); - if (i >= SOUND_MIXER_NRDEVICES) - return -EINVAL; - for (j = 0; j < ms->numch && ms->ch[j].osschannel != i; j++); - if (j >= ms->numch) - return -EINVAL; - if (get_user(val, user_arg)) - return -EFAULT; - if (wrmixer(ms, j, val)) - return -EIO; - return put_user(ms->ch[j].value, user_arg); - } -} - -static /*const*/ struct file_operations usb_mixer_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .ioctl = usb_audio_ioctl_mixdev, - .open = usb_audio_open_mixdev, - .release = usb_audio_release_mixdev, -}; - -/* --------------------------------------------------------------------- */ - -static int drain_out(struct usb_audiodev *as, int nonblock) -{ - DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - int count, tmo; - - if (as->usbout.dma.mapped || !as->usbout.dma.ready) - return 0; - usbout_start(as); - add_wait_queue(&as->usbout.dma.wait, &wait); - for (;;) { - __set_current_state(TASK_INTERRUPTIBLE); - spin_lock_irqsave(&as->lock, flags); - count = as->usbout.dma.count; - spin_unlock_irqrestore(&as->lock, flags); - if (count <= 0) - break; - if (signal_pending(current)) - break; - if (nonblock) { - remove_wait_queue(&as->usbout.dma.wait, &wait); - set_current_state(TASK_RUNNING); - return -EBUSY; - } - tmo = 3 * HZ * count / as->usbout.dma.srate; - tmo >>= AFMT_BYTESSHIFT(as->usbout.dma.format); - if (!schedule_timeout(tmo + 1)) { - printk(KERN_DEBUG "usbaudio: dma timed out??\n"); - break; - } - } - remove_wait_queue(&as->usbout.dma.wait, &wait); - set_current_state(TASK_RUNNING); - if (signal_pending(current)) - return -ERESTARTSYS; - return 0; -} - -/* --------------------------------------------------------------------- */ - -static ssize_t usb_audio_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) -{ - struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; - DECLARE_WAITQUEUE(wait, current); - ssize_t ret = 0; - unsigned long flags; - unsigned int ptr; - int cnt, err; - - if (as->usbin.dma.mapped) - return -ENXIO; - if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as))) - return ret; - if (!access_ok(VERIFY_WRITE, buffer, count)) - return -EFAULT; - add_wait_queue(&as->usbin.dma.wait, &wait); - while (count > 0) { - spin_lock_irqsave(&as->lock, flags); - ptr = as->usbin.dma.rdptr; - cnt = as->usbin.dma.count; - /* set task state early to avoid wakeup races */ - if (cnt <= 0) - __set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&as->lock, flags); - if (cnt > count) - cnt = count; - if (cnt <= 0) { - if (usbin_start(as)) { - if (!ret) - ret = -ENODEV; - break; - } - if (file->f_flags & O_NONBLOCK) { - if (!ret) - ret = -EAGAIN; - break; - } - schedule(); - if (signal_pending(current)) { - if (!ret) - ret = -ERESTARTSYS; - break; - } - continue; - } - if ((err = dmabuf_copyout_user(&as->usbin.dma, ptr, buffer, cnt))) { - if (!ret) - ret = err; - break; - } - ptr += cnt; - if (ptr >= as->usbin.dma.dmasize) - ptr -= as->usbin.dma.dmasize; - spin_lock_irqsave(&as->lock, flags); - as->usbin.dma.rdptr = ptr; - as->usbin.dma.count -= cnt; - spin_unlock_irqrestore(&as->lock, flags); - count -= cnt; - buffer += cnt; - ret += cnt; - } - __set_current_state(TASK_RUNNING); - remove_wait_queue(&as->usbin.dma.wait, &wait); - return ret; -} - -static ssize_t usb_audio_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) -{ - struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; - DECLARE_WAITQUEUE(wait, current); - ssize_t ret = 0; - unsigned long flags; - unsigned int ptr; - unsigned int start_thr; - int cnt, err; - - if (as->usbout.dma.mapped) - return -ENXIO; - if (!as->usbout.dma.ready && (ret = prog_dmabuf_out(as))) - return ret; - if (!access_ok(VERIFY_READ, buffer, count)) - return -EFAULT; - start_thr = (as->usbout.dma.srate << AFMT_BYTESSHIFT(as->usbout.dma.format)) / (1000 / (3 * DESCFRAMES)); - add_wait_queue(&as->usbout.dma.wait, &wait); - while (count > 0) { -#if 0 - printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%lx\n", - count, as->usbout.dma.count, as->usbout.dma.rdptr, as->usbout.dma.wrptr, as->usbout.dma.dmasize, as->usbout.dma.fragsize, - as->usbout.flags, current->state); -#endif - spin_lock_irqsave(&as->lock, flags); - if (as->usbout.dma.count < 0) { - as->usbout.dma.count = 0; - as->usbout.dma.rdptr = as->usbout.dma.wrptr; - } - ptr = as->usbout.dma.wrptr; - cnt = as->usbout.dma.dmasize - as->usbout.dma.count; - /* set task state early to avoid wakeup races */ - if (cnt <= 0) - __set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&as->lock, flags); - if (cnt > count) - cnt = count; - if (cnt <= 0) { - if (usbout_start(as)) { - if (!ret) - ret = -ENODEV; - break; - } - if (file->f_flags & O_NONBLOCK) { - if (!ret) - ret = -EAGAIN; - break; - } - schedule(); - if (signal_pending(current)) { - if (!ret) - ret = -ERESTARTSYS; - break; - } - continue; - } - if ((err = dmabuf_copyin_user(&as->usbout.dma, ptr, buffer, cnt))) { - if (!ret) - ret = err; - break; - } - ptr += cnt; - if (ptr >= as->usbout.dma.dmasize) - ptr -= as->usbout.dma.dmasize; - spin_lock_irqsave(&as->lock, flags); - as->usbout.dma.wrptr = ptr; - as->usbout.dma.count += cnt; - spin_unlock_irqrestore(&as->lock, flags); - count -= cnt; - buffer += cnt; - ret += cnt; - if (as->usbout.dma.count >= start_thr && usbout_start(as)) { - if (!ret) - ret = -ENODEV; - break; - } - } - __set_current_state(TASK_RUNNING); - remove_wait_queue(&as->usbout.dma.wait, &wait); - return ret; -} - -/* Called without the kernel lock - fine */ -static unsigned int usb_audio_poll(struct file *file, struct poll_table_struct *wait) -{ - struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; - unsigned long flags; - unsigned int mask = 0; - - if (file->f_mode & FMODE_WRITE) { - if (!as->usbout.dma.ready) - prog_dmabuf_out(as); - poll_wait(file, &as->usbout.dma.wait, wait); - } - if (file->f_mode & FMODE_READ) { - if (!as->usbin.dma.ready) - prog_dmabuf_in(as); - poll_wait(file, &as->usbin.dma.wait, wait); - } - spin_lock_irqsave(&as->lock, flags); - if (file->f_mode & FMODE_READ) { - if (as->usbin.dma.count >= (signed)as->usbin.dma.fragsize) - mask |= POLLIN | POLLRDNORM; - } - if (file->f_mode & FMODE_WRITE) { - if (as->usbout.dma.mapped) { - if (as->usbout.dma.count >= (signed)as->usbout.dma.fragsize) - mask |= POLLOUT | POLLWRNORM; - } else { - if ((signed)as->usbout.dma.dmasize >= as->usbout.dma.count + (signed)as->usbout.dma.fragsize) - mask |= POLLOUT | POLLWRNORM; - } - } - spin_unlock_irqrestore(&as->lock, flags); - return mask; -} - -static int usb_audio_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; - struct dmabuf *db; - int ret = -EINVAL; - - lock_kernel(); - if (vma->vm_flags & VM_WRITE) { - if ((ret = prog_dmabuf_out(as)) != 0) - goto out; - db = &as->usbout.dma; - } else if (vma->vm_flags & VM_READ) { - if ((ret = prog_dmabuf_in(as)) != 0) - goto out; - db = &as->usbin.dma; - } else - goto out; - - ret = -EINVAL; - if (vma->vm_pgoff != 0) - goto out; - - ret = dmabuf_mmap(vma, db, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot); -out: - unlock_kernel(); - return ret; -} - -static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; - struct usb_audio_state *s = as->state; - int __user *user_arg = (int __user *)arg; - unsigned long flags; - audio_buf_info abinfo; - count_info cinfo; - int val = 0; - int val2, mapped, ret; - - if (!s->usbdev) - return -EIO; - mapped = ((file->f_mode & FMODE_WRITE) && as->usbout.dma.mapped) || - ((file->f_mode & FMODE_READ) && as->usbin.dma.mapped); -#if 0 - if (arg) - get_user(val, (int *)arg); - printk(KERN_DEBUG "usbaudio: usb_audio_ioctl cmd=%x arg=%lx *arg=%d\n", cmd, arg, val) -#endif - switch (cmd) { - case OSS_GETVERSION: - return put_user(SOUND_VERSION, user_arg); - - case SNDCTL_DSP_SYNC: - if (file->f_mode & FMODE_WRITE) - return drain_out(as, 0/*file->f_flags & O_NONBLOCK*/); - return 0; - - case SNDCTL_DSP_SETDUPLEX: - return 0; - - case SNDCTL_DSP_GETCAPS: - return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | - DSP_CAP_MMAP | DSP_CAP_BATCH, user_arg); - - case SNDCTL_DSP_RESET: - if (file->f_mode & FMODE_WRITE) { - usbout_stop(as); - as->usbout.dma.rdptr = as->usbout.dma.wrptr = as->usbout.dma.count = as->usbout.dma.total_bytes = 0; - } - if (file->f_mode & FMODE_READ) { - usbin_stop(as); - as->usbin.dma.rdptr = as->usbin.dma.wrptr = as->usbin.dma.count = as->usbin.dma.total_bytes = 0; - } - return 0; - - case SNDCTL_DSP_SPEED: - if (get_user(val, user_arg)) - return -EFAULT; - if (val >= 0) { - if (val < 4000) - val = 4000; - if (val > 100000) - val = 100000; - if (set_format(as, file->f_mode, AFMT_QUERY, val)) - return -EIO; - } - return put_user((file->f_mode & FMODE_READ) ? - as->usbin.dma.srate : as->usbout.dma.srate, - user_arg); - - case SNDCTL_DSP_STEREO: - if (get_user(val, user_arg)) - return -EFAULT; - val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - if (val) - val2 |= AFMT_STEREO; - else - val2 &= ~AFMT_STEREO; - if (set_format(as, file->f_mode, val2, 0)) - return -EIO; - return 0; - - case SNDCTL_DSP_CHANNELS: - if (get_user(val, user_arg)) - return -EFAULT; - if (val != 0) { - val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - if (val == 1) - val2 &= ~AFMT_STEREO; - else - val2 |= AFMT_STEREO; - if (set_format(as, file->f_mode, val2, 0)) - return -EIO; - } - val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, user_arg); - - case SNDCTL_DSP_GETFMTS: /* Returns a mask */ - return put_user(AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE | - AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, user_arg); - - case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - if (get_user(val, user_arg)) - return -EFAULT; - if (val != AFMT_QUERY) { - if (hweight32(val) != 1) - return -EINVAL; - if (!(val & (AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE | - AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE))) - return -EINVAL; - val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - val |= val2 & AFMT_STEREO; - if (set_format(as, file->f_mode, val, 0)) - return -EIO; - } - val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(val2 & ~AFMT_STEREO, user_arg); - - case SNDCTL_DSP_POST: - return 0; - - case SNDCTL_DSP_GETTRIGGER: - val = 0; - if (file->f_mode & FMODE_READ && as->usbin.flags & FLG_RUNNING) - val |= PCM_ENABLE_INPUT; - if (file->f_mode & FMODE_WRITE && as->usbout.flags & FLG_RUNNING) - val |= PCM_ENABLE_OUTPUT; - return put_user(val, user_arg); - - case SNDCTL_DSP_SETTRIGGER: - if (get_user(val, user_arg)) - return -EFAULT; - if (file->f_mode & FMODE_READ) { - if (val & PCM_ENABLE_INPUT) { - if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as))) - return ret; - if (usbin_start(as)) - return -ENODEV; - } else - usbin_stop(as); - } - if (file->f_mode & FMODE_WRITE) { - if (val & PCM_ENABLE_OUTPUT) { - if (!as->usbout.dma.ready && (ret = prog_dmabuf_out(as))) - return ret; - if (usbout_start(as)) - return -ENODEV; - } else - usbout_stop(as); - } - return 0; - - case SNDCTL_DSP_GETOSPACE: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - if (!(as->usbout.flags & FLG_RUNNING) && (val = prog_dmabuf_out(as)) != 0) - return val; - spin_lock_irqsave(&as->lock, flags); - abinfo.fragsize = as->usbout.dma.fragsize; - abinfo.bytes = as->usbout.dma.dmasize - as->usbout.dma.count; - abinfo.fragstotal = as->usbout.dma.numfrag; - abinfo.fragments = abinfo.bytes >> as->usbout.dma.fragshift; - spin_unlock_irqrestore(&as->lock, flags); - return copy_to_user((void __user *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; - - case SNDCTL_DSP_GETISPACE: - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - if (!(as->usbin.flags & FLG_RUNNING) && (val = prog_dmabuf_in(as)) != 0) - return val; - spin_lock_irqsave(&as->lock, flags); - abinfo.fragsize = as->usbin.dma.fragsize; - abinfo.bytes = as->usbin.dma.count; - abinfo.fragstotal = as->usbin.dma.numfrag; - abinfo.fragments = abinfo.bytes >> as->usbin.dma.fragshift; - spin_unlock_irqrestore(&as->lock, flags); - return copy_to_user((void __user *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; - - case SNDCTL_DSP_NONBLOCK: - file->f_flags |= O_NONBLOCK; - return 0; - - case SNDCTL_DSP_GETODELAY: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - spin_lock_irqsave(&as->lock, flags); - val = as->usbout.dma.count; - spin_unlock_irqrestore(&as->lock, flags); - return put_user(val, user_arg); - - case SNDCTL_DSP_GETIPTR: - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - spin_lock_irqsave(&as->lock, flags); - cinfo.bytes = as->usbin.dma.total_bytes; - cinfo.blocks = as->usbin.dma.count >> as->usbin.dma.fragshift; - cinfo.ptr = as->usbin.dma.wrptr; - if (as->usbin.dma.mapped) - as->usbin.dma.count &= as->usbin.dma.fragsize-1; - spin_unlock_irqrestore(&as->lock, flags); - if (copy_to_user((void __user *)arg, &cinfo, sizeof(cinfo))) - return -EFAULT; - return 0; - - case SNDCTL_DSP_GETOPTR: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - spin_lock_irqsave(&as->lock, flags); - cinfo.bytes = as->usbout.dma.total_bytes; - cinfo.blocks = as->usbout.dma.count >> as->usbout.dma.fragshift; - cinfo.ptr = as->usbout.dma.rdptr; - if (as->usbout.dma.mapped) - as->usbout.dma.count &= as->usbout.dma.fragsize-1; - spin_unlock_irqrestore(&as->lock, flags); - if (copy_to_user((void __user *)arg, &cinfo, sizeof(cinfo))) - return -EFAULT; - return 0; - - case SNDCTL_DSP_GETBLKSIZE: - if (file->f_mode & FMODE_WRITE) { - if ((val = prog_dmabuf_out(as))) - return val; - return put_user(as->usbout.dma.fragsize, user_arg); - } - if ((val = prog_dmabuf_in(as))) - return val; - return put_user(as->usbin.dma.fragsize, user_arg); - - case SNDCTL_DSP_SETFRAGMENT: - if (get_user(val, user_arg)) - return -EFAULT; - if (file->f_mode & FMODE_READ) { - as->usbin.dma.ossfragshift = val & 0xffff; - as->usbin.dma.ossmaxfrags = (val >> 16) & 0xffff; - if (as->usbin.dma.ossfragshift < 4) - as->usbin.dma.ossfragshift = 4; - if (as->usbin.dma.ossfragshift > 15) - as->usbin.dma.ossfragshift = 15; - if (as->usbin.dma.ossmaxfrags < 4) - as->usbin.dma.ossmaxfrags = 4; - } - if (file->f_mode & FMODE_WRITE) { - as->usbout.dma.ossfragshift = val & 0xffff; - as->usbout.dma.ossmaxfrags = (val >> 16) & 0xffff; - if (as->usbout.dma.ossfragshift < 4) - as->usbout.dma.ossfragshift = 4; - if (as->usbout.dma.ossfragshift > 15) - as->usbout.dma.ossfragshift = 15; - if (as->usbout.dma.ossmaxfrags < 4) - as->usbout.dma.ossmaxfrags = 4; - } - return 0; - - case SNDCTL_DSP_SUBDIVIDE: - if ((file->f_mode & FMODE_READ && as->usbin.dma.subdivision) || - (file->f_mode & FMODE_WRITE && as->usbout.dma.subdivision)) - return -EINVAL; - if (get_user(val, user_arg)) - return -EFAULT; - if (val != 1 && val != 2 && val != 4) - return -EINVAL; - if (file->f_mode & FMODE_READ) - as->usbin.dma.subdivision = val; - if (file->f_mode & FMODE_WRITE) - as->usbout.dma.subdivision = val; - return 0; - - case SOUND_PCM_READ_RATE: - return put_user((file->f_mode & FMODE_READ) ? - as->usbin.dma.srate : as->usbout.dma.srate, - user_arg); - - case SOUND_PCM_READ_CHANNELS: - val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, user_arg); - - case SOUND_PCM_READ_BITS: - val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(AFMT_IS16BIT(val2) ? 16 : 8, user_arg); - - case SOUND_PCM_WRITE_FILTER: - case SNDCTL_DSP_SETSYNCRO: - case SOUND_PCM_READ_FILTER: - return -EINVAL; - } - dprintk((KERN_DEBUG "usbaudio: usb_audio_ioctl - no command found\n")); - return -ENOIOCTLCMD; -} - -static int usb_audio_open(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode); - DECLARE_WAITQUEUE(wait, current); - struct usb_audiodev *as; - struct usb_audio_state *s; - - for (;;) { - down(&open_sem); - list_for_each_entry(s, &audiodevs, audiodev) { - list_for_each_entry(as, &s->audiolist, list) { - if (!((as->dev_audio ^ minor) & ~0xf)) - goto device_found; - } - } - up(&open_sem); - return -ENODEV; - - device_found: - if (!s->usbdev) { - up(&open_sem); - return -EIO; - } - /* wait for device to become free */ - if (!(as->open_mode & file->f_mode)) - break; - if (file->f_flags & O_NONBLOCK) { - up(&open_sem); - return -EBUSY; - } - __set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&open_wait, &wait); - up(&open_sem); - schedule(); - __set_current_state(TASK_RUNNING); - remove_wait_queue(&open_wait, &wait); - if (signal_pending(current)) - return -ERESTARTSYS; - } - if (file->f_mode & FMODE_READ) - as->usbin.dma.ossfragshift = as->usbin.dma.ossmaxfrags = as->usbin.dma.subdivision = 0; - if (file->f_mode & FMODE_WRITE) - as->usbout.dma.ossfragshift = as->usbout.dma.ossmaxfrags = as->usbout.dma.subdivision = 0; - if (set_format(as, file->f_mode, ((minor & 0xf) == SND_DEV_DSP16) ? AFMT_S16_LE : AFMT_U8 /* AFMT_ULAW */, 8000)) { - up(&open_sem); - return -EIO; - } - file->private_data = as; - as->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - s->count++; - up(&open_sem); - return nonseekable_open(inode, file); -} - -static int usb_audio_release(struct inode *inode, struct file *file) -{ - struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; - struct usb_audio_state *s; - struct usb_device *dev; - - lock_kernel(); - s = as->state; - dev = s->usbdev; - if (file->f_mode & FMODE_WRITE) - drain_out(as, file->f_flags & O_NONBLOCK); - down(&open_sem); - if (file->f_mode & FMODE_WRITE) { - usbout_stop(as); - if (dev && as->usbout.interface >= 0) - usb_set_interface(dev, as->usbout.interface, 0); - dmabuf_release(&as->usbout.dma); - usbout_release(as); - } - if (file->f_mode & FMODE_READ) { - usbin_stop(as); - if (dev && as->usbin.interface >= 0) - usb_set_interface(dev, as->usbin.interface, 0); - dmabuf_release(&as->usbin.dma); - usbin_release(as); - } - as->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); - release(s); - wake_up(&open_wait); - unlock_kernel(); - return 0; -} - -static /*const*/ struct file_operations usb_audio_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = usb_audio_read, - .write = usb_audio_write, - .poll = usb_audio_poll, - .ioctl = usb_audio_ioctl, - .mmap = usb_audio_mmap, - .open = usb_audio_open, - .release = usb_audio_release, -}; - -/* --------------------------------------------------------------------- */ - -static int usb_audio_probe(struct usb_interface *iface, - const struct usb_device_id *id); -static void usb_audio_disconnect(struct usb_interface *iface); - -static struct usb_device_id usb_audio_ids [] = { - { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS), - .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = 1}, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, usb_audio_ids); - -static struct usb_driver usb_audio_driver = { - .name = "audio", - .probe = usb_audio_probe, - .disconnect = usb_audio_disconnect, - .id_table = usb_audio_ids, -}; - -static void *find_descriptor(void *descstart, unsigned int desclen, void *after, - u8 dtype, int iface, int altsetting) -{ - u8 *p, *end, *next; - int ifc = -1, as = -1; - - p = descstart; - end = p + desclen; - for (; p < end;) { - if (p[0] < 2) - return NULL; - next = p + p[0]; - if (next > end) - return NULL; - if (p[1] == USB_DT_INTERFACE) { - /* minimum length of interface descriptor */ - if (p[0] < 9) - return NULL; - ifc = p[2]; - as = p[3]; - } - if (p[1] == dtype && (!after || (void *)p > after) && - (iface == -1 || iface == ifc) && (altsetting == -1 || altsetting == as)) { - return p; - } - p = next; - } - return NULL; -} - -static void *find_csinterface_descriptor(void *descstart, unsigned int desclen, void *after, u8 dsubtype, int iface, int altsetting) -{ - unsigned char *p; - - p = find_descriptor(descstart, desclen, after, USB_DT_CS_INTERFACE, iface, altsetting); - while (p) { - if (p[0] >= 3 && p[2] == dsubtype) - return p; - p = find_descriptor(descstart, desclen, p, USB_DT_CS_INTERFACE, iface, altsetting); - } - return NULL; -} - -static void *find_audiocontrol_unit(void *descstart, unsigned int desclen, void *after, u8 unit, int iface) -{ - unsigned char *p; - - p = find_descriptor(descstart, desclen, after, USB_DT_CS_INTERFACE, iface, -1); - while (p) { - if (p[0] >= 4 && p[2] >= INPUT_TERMINAL && p[2] <= EXTENSION_UNIT && p[3] == unit) - return p; - p = find_descriptor(descstart, desclen, p, USB_DT_CS_INTERFACE, iface, -1); - } - return NULL; -} - -static void usb_audio_parsestreaming(struct usb_audio_state *s, unsigned char *buffer, unsigned int buflen, int asifin, int asifout) -{ - struct usb_device *dev = s->usbdev; - struct usb_audiodev *as; - struct usb_host_interface *alts; - struct usb_interface *iface; - struct audioformat *fp; - unsigned char *fmt, *csep; - unsigned int i, j, k, format, idx; - - if (!(as = kmalloc(sizeof(struct usb_audiodev), GFP_KERNEL))) - return; - memset(as, 0, sizeof(struct usb_audiodev)); - init_waitqueue_head(&as->usbin.dma.wait); - init_waitqueue_head(&as->usbout.dma.wait); - spin_lock_init(&as->lock); - as->usbin.durb[0].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL); - as->usbin.durb[1].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL); - as->usbin.surb[0].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL); - as->usbin.surb[1].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL); - as->usbout.durb[0].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL); - as->usbout.durb[1].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL); - as->usbout.surb[0].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL); - as->usbout.surb[1].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL); - if ((!as->usbin.durb[0].urb) || - (!as->usbin.durb[1].urb) || - (!as->usbin.surb[0].urb) || - (!as->usbin.surb[1].urb) || - (!as->usbout.durb[0].urb) || - (!as->usbout.durb[1].urb) || - (!as->usbout.surb[0].urb) || - (!as->usbout.surb[1].urb)) { - usb_free_urb(as->usbin.durb[0].urb); - usb_free_urb(as->usbin.durb[1].urb); - usb_free_urb(as->usbin.surb[0].urb); - usb_free_urb(as->usbin.surb[1].urb); - usb_free_urb(as->usbout.durb[0].urb); - usb_free_urb(as->usbout.durb[1].urb); - usb_free_urb(as->usbout.surb[0].urb); - usb_free_urb(as->usbout.surb[1].urb); - kfree(as); - return; - } - as->state = s; - as->usbin.interface = asifin; - as->usbout.interface = asifout; - /* search for input formats */ - if (asifin >= 0) { - as->usbin.flags = FLG_CONNECTED; - iface = usb_ifnum_to_if(dev, asifin); - for (idx = 0; idx < iface->num_altsetting; idx++) { - alts = &iface->altsetting[idx]; - i = alts->desc.bAlternateSetting; - if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO || alts->desc.bInterfaceSubClass != 2) - continue; - if (alts->desc.bNumEndpoints < 1) { - if (i != 0) { /* altsetting 0 has no endpoints (Section B.3.4.1) */ - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", - dev->devnum, asifin, i); - } - continue; - } - if ((alts->endpoint[0].desc.bmAttributes & 0x03) != 0x01 || - !(alts->endpoint[0].desc.bEndpointAddress & 0x80)) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u first endpoint not isochronous in\n", - dev->devnum, asifin, i); - continue; - } - fmt = find_csinterface_descriptor(buffer, buflen, NULL, AS_GENERAL, asifin, i); - if (!fmt) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", - dev->devnum, asifin, i); - continue; - } - if (fmt[0] < 7 || fmt[6] != 0 || (fmt[5] != 1 && fmt[5] != 2)) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u format not supported\n", - dev->devnum, asifin, i); - continue; - } - format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8); - fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifin, i); - if (!fmt) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", - dev->devnum, asifin, i); - continue; - } - if (fmt[0] < 8+3*(fmt[7] ? fmt[7] : 2) || fmt[3] != 1) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", - dev->devnum, asifin, i); - continue; - } - if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", - dev->devnum, asifin, i, fmt[4], fmt[5]); - continue; - } - csep = find_descriptor(buffer, buflen, NULL, USB_DT_CS_ENDPOINT, asifin, i); - if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u no or invalid class specific endpoint descriptor\n", - dev->devnum, asifin, i); - continue; - } - if (as->numfmtin >= MAXFORMATS) - continue; - fp = &as->fmtin[as->numfmtin++]; - if (fmt[5] == 2) - format &= (AFMT_U16_LE | AFMT_S16_LE); - else - format &= (AFMT_U8 | AFMT_S8); - if (fmt[4] == 2) - format |= AFMT_STEREO; - fp->format = format; - fp->altsetting = i; - fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10] << 16); - printk(KERN_INFO "usbaudio: valid input sample rate %u\n", fp->sratelo); - for (j = fmt[7] ? (fmt[7]-1) : 1; j > 0; j--) { - k = fmt[8+3*j] | (fmt[9+3*j] << 8) | (fmt[10+3*j] << 16); - printk(KERN_INFO "usbaudio: valid input sample rate %u\n", k); - if (k > fp->sratehi) - fp->sratehi = k; - if (k < fp->sratelo) - fp->sratelo = k; - } - fp->attributes = csep[3]; - printk(KERN_INFO "usbaudio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u attributes 0x%02x\n", - dev->devnum, asifin, i, fp->format, fp->sratelo, fp->sratehi, fp->attributes); - } - } - /* search for output formats */ - if (asifout >= 0) { - as->usbout.flags = FLG_CONNECTED; - iface = usb_ifnum_to_if(dev, asifout); - for (idx = 0; idx < iface->num_altsetting; idx++) { - alts = &iface->altsetting[idx]; - i = alts->desc.bAlternateSetting; - if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO || alts->desc.bInterfaceSubClass != 2) - continue; - if (alts->desc.bNumEndpoints < 1) { - /* altsetting 0 should never have iso EPs */ - if (i != 0) - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", - dev->devnum, asifout, i); - continue; - } - if ((alts->endpoint[0].desc.bmAttributes & 0x03) != 0x01 || - (alts->endpoint[0].desc.bEndpointAddress & 0x80)) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u first endpoint not isochronous out\n", - dev->devnum, asifout, i); - continue; - } - /* See USB audio formats manual, section 2 */ - fmt = find_csinterface_descriptor(buffer, buflen, NULL, AS_GENERAL, asifout, i); - if (!fmt) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", - dev->devnum, asifout, i); - continue; - } - if (fmt[0] < 7 || fmt[6] != 0 || (fmt[5] != 1 && fmt[5] != 2)) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u format not supported\n", - dev->devnum, asifout, i); - continue; - } - format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8); - /* Dallas DS4201 workaround */ - if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa && - le16_to_cpu(dev->descriptor.idProduct) == 0x4201) - format = (AFMT_S16_LE | AFMT_S8); - fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifout, i); - if (!fmt) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", - dev->devnum, asifout, i); - continue; - } - if (fmt[0] < 8+3*(fmt[7] ? fmt[7] : 2) || fmt[3] != 1) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", - dev->devnum, asifout, i); - continue; - } - if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", - dev->devnum, asifout, i, fmt[4], fmt[5]); - continue; - } - csep = find_descriptor(buffer, buflen, NULL, USB_DT_CS_ENDPOINT, asifout, i); - if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) { - printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u no or invalid class specific endpoint descriptor\n", - dev->devnum, asifout, i); - continue; - } - if (as->numfmtout >= MAXFORMATS) - continue; - fp = &as->fmtout[as->numfmtout++]; - if (fmt[5] == 2) - format &= (AFMT_U16_LE | AFMT_S16_LE); - else - format &= (AFMT_U8 | AFMT_S8); - if (fmt[4] == 2) - format |= AFMT_STEREO; - fp->format = format; - fp->altsetting = i; - fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10] << 16); - printk(KERN_INFO "usbaudio: valid output sample rate %u\n", fp->sratelo); - for (j = fmt[7] ? (fmt[7]-1) : 1; j > 0; j--) { - k = fmt[8+3*j] | (fmt[9+3*j] << 8) | (fmt[10+3*j] << 16); - printk(KERN_INFO "usbaudio: valid output sample rate %u\n", k); - if (k > fp->sratehi) - fp->sratehi = k; - if (k < fp->sratelo) - fp->sratelo = k; - } - fp->attributes = csep[3]; - printk(KERN_INFO "usbaudio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u attributes 0x%02x\n", - dev->devnum, asifout, i, fp->format, fp->sratelo, fp->sratehi, fp->attributes); - } - } - if (as->numfmtin == 0 && as->numfmtout == 0) { - usb_free_urb(as->usbin.durb[0].urb); - usb_free_urb(as->usbin.durb[1].urb); - usb_free_urb(as->usbin.surb[0].urb); - usb_free_urb(as->usbin.surb[1].urb); - usb_free_urb(as->usbout.durb[0].urb); - usb_free_urb(as->usbout.durb[1].urb); - usb_free_urb(as->usbout.surb[0].urb); - usb_free_urb(as->usbout.surb[1].urb); - kfree(as); - return; - } - if ((as->dev_audio = register_sound_dsp(&usb_audio_fops, -1)) < 0) { - printk(KERN_ERR "usbaudio: cannot register dsp\n"); - usb_free_urb(as->usbin.durb[0].urb); - usb_free_urb(as->usbin.durb[1].urb); - usb_free_urb(as->usbin.surb[0].urb); - usb_free_urb(as->usbin.surb[1].urb); - usb_free_urb(as->usbout.durb[0].urb); - usb_free_urb(as->usbout.durb[1].urb); - usb_free_urb(as->usbout.surb[0].urb); - usb_free_urb(as->usbout.surb[1].urb); - kfree(as); - return; - } - printk(KERN_INFO "usbaudio: registered dsp 14,%d\n", as->dev_audio); - /* everything successful */ - list_add_tail(&as->list, &s->audiolist); -} - -struct consmixstate { - struct usb_audio_state *s; - unsigned char *buffer; - unsigned int buflen; - unsigned int ctrlif; - struct mixerchannel mixch[SOUND_MIXER_NRDEVICES]; - unsigned int nrmixch; - unsigned int mixchmask; - unsigned long unitbitmap[32/sizeof(unsigned long)]; - /* return values */ - unsigned int nrchannels; - unsigned int termtype; - unsigned int chconfig; -}; - -static struct mixerchannel *getmixchannel(struct consmixstate *state, unsigned int nr) -{ - struct mixerchannel *c; - - if (nr >= SOUND_MIXER_NRDEVICES) { - printk(KERN_ERR "usbaudio: invalid OSS mixer channel %u\n", nr); - return NULL; - } - if (!(state->mixchmask & (1 << nr))) { - printk(KERN_WARNING "usbaudio: OSS mixer channel %u already in use\n", nr); - return NULL; - } - c = &state->mixch[state->nrmixch++]; - c->osschannel = nr; - state->mixchmask &= ~(1 << nr); - return c; -} - -static unsigned int getvolchannel(struct consmixstate *state) -{ - unsigned int u; - - if ((state->termtype & 0xff00) == 0x0000 && (state->mixchmask & SOUND_MASK_VOLUME)) - return SOUND_MIXER_VOLUME; - if ((state->termtype & 0xff00) == 0x0100) { - if (state->mixchmask & SOUND_MASK_PCM) - return SOUND_MIXER_PCM; - if (state->mixchmask & SOUND_MASK_ALTPCM) - return SOUND_MIXER_ALTPCM; - } - if ((state->termtype & 0xff00) == 0x0200 && (state->mixchmask & SOUND_MASK_MIC)) - return SOUND_MIXER_MIC; - if ((state->termtype & 0xff00) == 0x0300 && (state->mixchmask & SOUND_MASK_SPEAKER)) - return SOUND_MIXER_SPEAKER; - if ((state->termtype & 0xff00) == 0x0500) { - if (state->mixchmask & SOUND_MASK_PHONEIN) - return SOUND_MIXER_PHONEIN; - if (state->mixchmask & SOUND_MASK_PHONEOUT) - return SOUND_MIXER_PHONEOUT; - } - if (state->termtype >= 0x710 && state->termtype <= 0x711 && (state->mixchmask & SOUND_MASK_RADIO)) - return SOUND_MIXER_RADIO; - if (state->termtype >= 0x709 && state->termtype <= 0x70f && (state->mixchmask & SOUND_MASK_VIDEO)) - return SOUND_MIXER_VIDEO; - u = ffs(state->mixchmask & (SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | SOUND_MASK_LINE3 | - SOUND_MASK_DIGITAL1 | SOUND_MASK_DIGITAL2 | SOUND_MASK_DIGITAL3)); - return u-1; -} - -static void prepmixch(struct consmixstate *state) -{ - struct usb_device *dev = state->s->usbdev; - struct mixerchannel *ch; - unsigned char *buf; - __s16 v1; - unsigned int v2, v3; - - if (!state->nrmixch || state->nrmixch > SOUND_MIXER_NRDEVICES) - return; - buf = kmalloc(sizeof(*buf) * 2, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "prepmixch: out of memory\n") ; - return; - } - - ch = &state->mixch[state->nrmixch-1]; - switch (ch->selector) { - case 0: /* mixer unit request */ - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) - goto err; - ch->minval = buf[0] | (buf[1] << 8); - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) - goto err; - ch->maxval = buf[0] | (buf[1] << 8); - v2 = ch->maxval - ch->minval; - if (!v2) - v2 = 1; - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) - goto err; - v1 = buf[0] | (buf[1] << 8); - v3 = v1 - ch->minval; - v3 = 100 * v3 / v2; - if (v3 > 100) - v3 = 100; - ch->value = v3; - if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) { - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)), - state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) - goto err; - v1 = buf[0] | (buf[1] << 8); - v3 = v1 - ch->minval; - v3 = 100 * v3 / v2; - if (v3 > 100) - v3 = 100; - } - ch->value |= v3 << 8; - break; - - /* various feature unit controls */ - case VOLUME_CONTROL: - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) - goto err; - ch->minval = buf[0] | (buf[1] << 8); - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) - goto err; - ch->maxval = buf[0] | (buf[1] << 8); - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) - goto err; - v1 = buf[0] | (buf[1] << 8); - v2 = ch->maxval - ch->minval; - v3 = v1 - ch->minval; - if (!v2) - v2 = 1; - v3 = 100 * v3 / v2; - if (v3 > 100) - v3 = 100; - ch->value = v3; - if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) { - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) - goto err; - v1 = buf[0] | (buf[1] << 8); - v3 = v1 - ch->minval; - v3 = 100 * v3 / v2; - if (v3 > 100) - v3 = 100; - } - ch->value |= v3 << 8; - break; - - case BASS_CONTROL: - case MID_CONTROL: - case TREBLE_CONTROL: - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0) - goto err; - ch->minval = buf[0] << 8; - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0) - goto err; - ch->maxval = buf[0] << 8; - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0) - goto err; - v1 = buf[0] << 8; - v2 = ch->maxval - ch->minval; - v3 = v1 - ch->minval; - if (!v2) - v2 = 1; - v3 = 100 * v3 / v2; - if (v3 > 100) - v3 = 100; - ch->value = v3; - if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) { - if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0) - goto err; - v1 = buf[0] << 8; - v3 = v1 - ch->minval; - v3 = 100 * v3 / v2; - if (v3 > 100) - v3 = 100; - } - ch->value |= v3 << 8; - break; - - default: - goto err; - } - - freebuf: - kfree(buf); - return; - err: - printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", - dev->devnum, state->ctrlif, ch->unitid, ch->chnum, ch->selector); - if (state->nrmixch) - state->nrmixch--; - goto freebuf; -} - - -static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid); - -static inline int checkmixbmap(unsigned char *bmap, unsigned char flg, unsigned int inidx, unsigned int numoch) -{ - unsigned int idx; - - idx = inidx*numoch; - if (!(bmap[-(idx >> 3)] & (0x80 >> (idx & 7)))) - return 0; - if (!(flg & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) - return 1; - idx = (inidx+!!(flg & MIXFLG_STEREOIN))*numoch+!!(flg & MIXFLG_STEREOOUT); - if (!(bmap[-(idx >> 3)] & (0x80 >> (idx & 7)))) - return 0; - return 1; -} - -static void usb_audio_mixerunit(struct consmixstate *state, unsigned char *mixer) -{ - unsigned int nroutch = mixer[5+mixer[4]]; - unsigned int chidx[SOUND_MIXER_NRDEVICES+1]; - unsigned int termt[SOUND_MIXER_NRDEVICES]; - unsigned char flg = (nroutch >= 2) ? MIXFLG_STEREOOUT : 0; - unsigned char *bmap = &mixer[9+mixer[4]]; - unsigned int bmapsize; - struct mixerchannel *ch; - unsigned int i; - - if (!mixer[4]) { - printk(KERN_ERR "usbaudio: unit %u invalid MIXER_UNIT descriptor\n", mixer[3]); - return; - } - if (mixer[4] > SOUND_MIXER_NRDEVICES) { - printk(KERN_ERR "usbaudio: mixer unit %u: too many input pins\n", mixer[3]); - return; - } - chidx[0] = 0; - for (i = 0; i < mixer[4]; i++) { - usb_audio_recurseunit(state, mixer[5+i]); - chidx[i+1] = chidx[i] + state->nrchannels; - termt[i] = state->termtype; - } - state->termtype = 0; - state->chconfig = mixer[6+mixer[4]] | (mixer[7+mixer[4]] << 8); - bmapsize = (nroutch * chidx[mixer[4]] + 7) >> 3; - bmap += bmapsize - 1; - if (mixer[0] < 10+mixer[4]+bmapsize) { - printk(KERN_ERR "usbaudio: unit %u invalid MIXER_UNIT descriptor (bitmap too small)\n", mixer[3]); - return; - } - for (i = 0; i < mixer[4]; i++) { - state->termtype = termt[i]; - if (chidx[i+1]-chidx[i] >= 2) { - flg |= MIXFLG_STEREOIN; - if (checkmixbmap(bmap, flg, chidx[i], nroutch)) { - ch = getmixchannel(state, getvolchannel(state)); - if (ch) { - ch->unitid = mixer[3]; - ch->selector = 0; - ch->chnum = chidx[i]+1; - ch->flags = flg; - prepmixch(state); - } - continue; - } - } - flg &= ~MIXFLG_STEREOIN; - if (checkmixbmap(bmap, flg, chidx[i], nroutch)) { - ch = getmixchannel(state, getvolchannel(state)); - if (ch) { - ch->unitid = mixer[3]; - ch->selector = 0; - ch->chnum = chidx[i]+1; - ch->flags = flg; - prepmixch(state); - } - } - } - state->termtype = 0; -} - -static struct mixerchannel *slctsrc_findunit(struct consmixstate *state, __u8 unitid) -{ - unsigned int i; - - for (i = 0; i < state->nrmixch; i++) - if (state->mixch[i].unitid == unitid) - return &state->mixch[i]; - return NULL; -} - -static void usb_audio_selectorunit(struct consmixstate *state, unsigned char *selector) -{ - unsigned int chnum, i, mixch; - struct mixerchannel *mch; - - if (!selector[4]) { - printk(KERN_ERR "usbaudio: unit %u invalid SELECTOR_UNIT descriptor\n", selector[3]); - return; - } - mixch = state->nrmixch; - usb_audio_recurseunit(state, selector[5]); - if (state->nrmixch != mixch) { - mch = &state->mixch[state->nrmixch-1]; - mch->slctunitid = selector[3] | (1 << 8); - } else if ((mch = slctsrc_findunit(state, selector[5]))) { - mch->slctunitid = selector[3] | (1 << 8); - } else { - printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel 1\n", selector[3]); - } - chnum = state->nrchannels; - for (i = 1; i < selector[4]; i++) { - mixch = state->nrmixch; - usb_audio_recurseunit(state, selector[5+i]); - if (chnum != state->nrchannels) { - printk(KERN_ERR "usbaudio: selector unit %u: input pins with varying channel numbers\n", selector[3]); - state->termtype = 0; - state->chconfig = 0; - state->nrchannels = 0; - return; - } - if (state->nrmixch != mixch) { - mch = &state->mixch[state->nrmixch-1]; - mch->slctunitid = selector[3] | ((i + 1) << 8); - } else if ((mch = slctsrc_findunit(state, selector[5+i]))) { - mch->slctunitid = selector[3] | ((i + 1) << 8); - } else { - printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel %u\n", selector[3], i+1); - } - } - state->termtype = 0; - state->chconfig = 0; -} - -/* in the future we might try to handle 3D etc. effect units */ - -static void usb_audio_processingunit(struct consmixstate *state, unsigned char *proc) -{ - unsigned int i; - - for (i = 0; i < proc[6]; i++) - usb_audio_recurseunit(state, proc[7+i]); - state->nrchannels = proc[7+proc[6]]; - state->termtype = 0; - state->chconfig = proc[8+proc[6]] | (proc[9+proc[6]] << 8); -} - - -/* See Audio Class Spec, section 4.3.2.5 */ -static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr) -{ - struct mixerchannel *ch; - unsigned short chftr, mchftr; -#if 0 - struct usb_device *dev = state->s->usbdev; - unsigned char data[1]; -#endif - unsigned char nr_logical_channels, i; - - usb_audio_recurseunit(state, ftr[4]); - - if (ftr[5] == 0 ) { - printk(KERN_ERR "usbaudio: wrong controls size in feature unit %u\n",ftr[3]); - return; - } - - if (state->nrchannels == 0) { - printk(KERN_ERR "usbaudio: feature unit %u source has no channels\n", ftr[3]); - return; - } - if (state->nrchannels > 2) - printk(KERN_WARNING "usbaudio: feature unit %u: OSS mixer interface does not support more than 2 channels\n", ftr[3]); - - nr_logical_channels=(ftr[0]-7)/ftr[5]-1; - - if (nr_logical_channels != state->nrchannels) { - printk(KERN_WARNING "usbaudio: warning: found %d of %d logical channels.\n", state->nrchannels,nr_logical_channels); - - if (state->nrchannels == 1 && nr_logical_channels==0) { - printk(KERN_INFO "usbaudio: assuming the channel found is the master channel (got a Philips camera?). Should be fine.\n"); - } else if (state->nrchannels == 1 && nr_logical_channels==2) { - printk(KERN_INFO "usbaudio: assuming that a stereo channel connected directly to a mixer is missing in search (got Labtec headset?). Should be fine.\n"); - state->nrchannels=nr_logical_channels; - } else { - printk(KERN_WARNING "usbaudio: no idea what's going on..., contact linux-usb-devel@lists.sourceforge.net\n"); - } - } - - /* There is always a master channel */ - mchftr = ftr[6]; - /* Binary AND over logical channels if they exist */ - if (nr_logical_channels) { - chftr = ftr[6+ftr[5]]; - for (i = 2; i <= nr_logical_channels; i++) - chftr &= ftr[6+i*ftr[5]]; - } else { - chftr = 0; - } - - /* volume control */ - if (chftr & 2) { - ch = getmixchannel(state, getvolchannel(state)); - if (ch) { - ch->unitid = ftr[3]; - ch->selector = VOLUME_CONTROL; - ch->chnum = 1; - ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0; - prepmixch(state); - } - } else if (mchftr & 2) { - ch = getmixchannel(state, getvolchannel(state)); - if (ch) { - ch->unitid = ftr[3]; - ch->selector = VOLUME_CONTROL; - ch->chnum = 0; - ch->flags = 0; - prepmixch(state); - } - } - /* bass control */ - if (chftr & 4) { - ch = getmixchannel(state, SOUND_MIXER_BASS); - if (ch) { - ch->unitid = ftr[3]; - ch->selector = BASS_CONTROL; - ch->chnum = 1; - ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0; - prepmixch(state); - } - } else if (mchftr & 4) { - ch = getmixchannel(state, SOUND_MIXER_BASS); - if (ch) { - ch->unitid = ftr[3]; - ch->selector = BASS_CONTROL; - ch->chnum = 0; - ch->flags = 0; - prepmixch(state); - } - } - /* treble control */ - if (chftr & 16) { - ch = getmixchannel(state, SOUND_MIXER_TREBLE); - if (ch) { - ch->unitid = ftr[3]; - ch->selector = TREBLE_CONTROL; - ch->chnum = 1; - ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0; - prepmixch(state); - } - } else if (mchftr & 16) { - ch = getmixchannel(state, SOUND_MIXER_TREBLE); - if (ch) { - ch->unitid = ftr[3]; - ch->selector = TREBLE_CONTROL; - ch->chnum = 0; - ch->flags = 0; - prepmixch(state); - } - } -#if 0 - /* if there are mute controls, unmute them */ - /* does not seem to be necessary, and the Dallas chip does not seem to support the "all" channel (255) */ - if ((chftr & 1) || (mchftr & 1)) { - printk(KERN_DEBUG "usbaudio: unmuting feature unit %u interface %u\n", ftr[3], state->ctrlif); - data[0] = 0; - if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - (MUTE_CONTROL << 8) | 0xff, state->ctrlif | (ftr[3] << 8), data, 1, 1000) < 0) - printk(KERN_WARNING "usbaudio: failure to unmute feature unit %u interface %u\n", ftr[3], state->ctrlif); - } -#endif -} - -static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid) -{ - unsigned char *p1; - unsigned int i, j; - - if (test_and_set_bit(unitid, state->unitbitmap)) { - printk(KERN_INFO "usbaudio: mixer path revisits unit %d\n", unitid); - return; - } - p1 = find_audiocontrol_unit(state->buffer, state->buflen, NULL, unitid, state->ctrlif); - if (!p1) { - printk(KERN_ERR "usbaudio: unit %d not found!\n", unitid); - return; - } - state->nrchannels = 0; - state->termtype = 0; - state->chconfig = 0; - switch (p1[2]) { - case INPUT_TERMINAL: - if (p1[0] < 12) { - printk(KERN_ERR "usbaudio: unit %u: invalid INPUT_TERMINAL descriptor\n", unitid); - return; - } - state->nrchannels = p1[7]; - state->termtype = p1[4] | (p1[5] << 8); - state->chconfig = p1[8] | (p1[9] << 8); - return; - - case MIXER_UNIT: - if (p1[0] < 10 || p1[0] < 10+p1[4]) { - printk(KERN_ERR "usbaudio: unit %u: invalid MIXER_UNIT descriptor\n", unitid); - return; - } - usb_audio_mixerunit(state, p1); - return; - - case SELECTOR_UNIT: - if (p1[0] < 6 || p1[0] < 6+p1[4]) { - printk(KERN_ERR "usbaudio: unit %u: invalid SELECTOR_UNIT descriptor\n", unitid); - return; - } - usb_audio_selectorunit(state, p1); - return; - - case FEATURE_UNIT: /* See USB Audio Class Spec 4.3.2.5 */ - if (p1[0] < 7 || p1[0] < 7+p1[5]) { - printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", unitid); - return; - } - usb_audio_featureunit(state, p1); - return; - - case PROCESSING_UNIT: - if (p1[0] < 13 || p1[0] < 13+p1[6] || p1[0] < 13+p1[6]+p1[11+p1[6]]) { - printk(KERN_ERR "usbaudio: unit %u: invalid PROCESSING_UNIT descriptor\n", unitid); - return; - } - usb_audio_processingunit(state, p1); - return; - - case EXTENSION_UNIT: - if (p1[0] < 13 || p1[0] < 13+p1[6] || p1[0] < 13+p1[6]+p1[11+p1[6]]) { - printk(KERN_ERR "usbaudio: unit %u: invalid EXTENSION_UNIT descriptor\n", unitid); - return; - } - for (j = i = 0; i < p1[6]; i++) { - usb_audio_recurseunit(state, p1[7+i]); - if (!i) - j = state->termtype; - else if (j != state->termtype) - j = 0; - } - state->nrchannels = p1[7+p1[6]]; - state->chconfig = p1[8+p1[6]] | (p1[9+p1[6]] << 8); - state->termtype = j; - return; - - default: - printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]); - return; - } -} - -static void usb_audio_constructmixer(struct usb_audio_state *s, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif, unsigned char *oterm) -{ - struct usb_mixerdev *ms; - struct consmixstate state; - - memset(&state, 0, sizeof(state)); - state.s = s; - state.nrmixch = 0; - state.mixchmask = ~0; - state.buffer = buffer; - state.buflen = buflen; - state.ctrlif = ctrlif; - set_bit(oterm[3], state.unitbitmap); /* mark terminal ID as visited */ - printk(KERN_DEBUG "usbaudio: constructing mixer for Terminal %u type 0x%04x\n", - oterm[3], oterm[4] | (oterm[5] << 8)); - usb_audio_recurseunit(&state, oterm[7]); - if (!state.nrmixch) { - printk(KERN_INFO "usbaudio: no mixer controls found for Terminal %u\n", oterm[3]); - return; - } - if (!(ms = kmalloc(sizeof(struct usb_mixerdev)+state.nrmixch*sizeof(struct mixerchannel), GFP_KERNEL))) - return; - memset(ms, 0, sizeof(struct usb_mixerdev)); - memcpy(&ms->ch, &state.mixch, state.nrmixch*sizeof(struct mixerchannel)); - ms->state = s; - ms->iface = ctrlif; - ms->numch = state.nrmixch; - if ((ms->dev_mixer = register_sound_mixer(&usb_mixer_fops, -1)) < 0) { - printk(KERN_ERR "usbaudio: cannot register mixer\n"); - kfree(ms); - return; - } - printk(KERN_INFO "usbaudio: registered mixer 14,%d\n", ms->dev_mixer); - list_add_tail(&ms->list, &s->mixerlist); -} - -/* arbitrary limit, we won't check more interfaces than this */ -#define USB_MAXINTERFACES 32 - -static struct usb_audio_state *usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif) -{ - struct usb_audio_state *s; - struct usb_interface *iface; - struct usb_host_interface *alt; - unsigned char ifin[USB_MAXINTERFACES], ifout[USB_MAXINTERFACES]; - unsigned char *p1; - unsigned int i, j, k, numifin = 0, numifout = 0; - - if (!(s = kmalloc(sizeof(struct usb_audio_state), GFP_KERNEL))) - return NULL; - memset(s, 0, sizeof(struct usb_audio_state)); - INIT_LIST_HEAD(&s->audiolist); - INIT_LIST_HEAD(&s->mixerlist); - s->usbdev = dev; - s->count = 1; - - /* find audiocontrol interface */ - if (!(p1 = find_csinterface_descriptor(buffer, buflen, NULL, HEADER, ctrlif, -1))) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u no HEADER found\n", - dev->devnum, ctrlif); - goto ret; - } - if (p1[0] < 8 + p1[7]) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u HEADER error\n", - dev->devnum, ctrlif); - goto ret; - } - if (!p1[7]) - printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u has no AudioStreaming and MidiStreaming interfaces\n", - dev->devnum, ctrlif); - for (i = 0; i < p1[7]; i++) { - j = p1[8+i]; - iface = usb_ifnum_to_if(dev, j); - if (!iface) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u does not exist\n", - dev->devnum, ctrlif, j); - continue; - } - if (iface->num_altsetting == 1) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has only 1 altsetting.\n", dev->devnum, ctrlif); - continue; - } - alt = usb_altnum_to_altsetting(iface, 0); - if (!alt) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no altsetting 0\n", - dev->devnum, ctrlif, j); - continue; - } - if (alt->desc.bInterfaceClass != USB_CLASS_AUDIO) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u is not an AudioClass interface\n", - dev->devnum, ctrlif, j); - continue; - } - if (alt->desc.bInterfaceSubClass == 3) { - printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u interface %u MIDIStreaming not supported\n", - dev->devnum, ctrlif, j); - continue; - } - if (alt->desc.bInterfaceSubClass != 2) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u invalid AudioClass subtype\n", - dev->devnum, ctrlif, j); - continue; - } - if (alt->desc.bNumEndpoints > 0) { - /* Check all endpoints; should they all have a bandwidth of 0 ? */ - for (k = 0; k < alt->desc.bNumEndpoints; k++) { - if (le16_to_cpu(alt->endpoint[k].desc.wMaxPacketSize) > 0) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u endpoint %d does not have 0 bandwidth at alt[0]\n", dev->devnum, ctrlif, k); - break; - } - } - if (k < alt->desc.bNumEndpoints) - continue; - } - - alt = usb_altnum_to_altsetting(iface, 1); - if (!alt) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no altsetting 1\n", - dev->devnum, ctrlif, j); - continue; - } - if (alt->desc.bNumEndpoints < 1) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no endpoint\n", - dev->devnum, ctrlif, j); - continue; - } - /* note: this requires the data endpoint to be ep0 and the optional sync - ep to be ep1, which seems to be the case */ - if (alt->endpoint[0].desc.bEndpointAddress & USB_DIR_IN) { - if (numifin < USB_MAXINTERFACES) { - ifin[numifin++] = j; - usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1); - } - } else { - if (numifout < USB_MAXINTERFACES) { - ifout[numifout++] = j; - usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1); - } - } - } - printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u has %u input and %u output AudioStreaming interfaces\n", - dev->devnum, ctrlif, numifin, numifout); - for (i = 0; i < numifin && i < numifout; i++) - usb_audio_parsestreaming(s, buffer, buflen, ifin[i], ifout[i]); - for (j = i; j < numifin; j++) - usb_audio_parsestreaming(s, buffer, buflen, ifin[i], -1); - for (j = i; j < numifout; j++) - usb_audio_parsestreaming(s, buffer, buflen, -1, ifout[i]); - /* now walk through all OUTPUT_TERMINAL descriptors to search for mixers */ - p1 = find_csinterface_descriptor(buffer, buflen, NULL, OUTPUT_TERMINAL, ctrlif, -1); - while (p1) { - if (p1[0] >= 9) - usb_audio_constructmixer(s, buffer, buflen, ctrlif, p1); - p1 = find_csinterface_descriptor(buffer, buflen, p1, OUTPUT_TERMINAL, ctrlif, -1); - } - -ret: - if (list_empty(&s->audiolist) && list_empty(&s->mixerlist)) { - kfree(s); - return NULL; - } - /* everything successful */ - down(&open_sem); - list_add_tail(&s->audiodev, &audiodevs); - up(&open_sem); - printk(KERN_DEBUG "usb_audio_parsecontrol: usb_audio_state at %p\n", s); - return s; -} - -/* we only care for the currently active configuration */ - -static int usb_audio_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev (intf); - struct usb_audio_state *s; - unsigned char *buffer; - unsigned int buflen; - -#if 0 - printk(KERN_DEBUG "usbaudio: Probing if %i: IC %x, ISC %x\n", ifnum, - config->interface[ifnum].altsetting[0].desc.bInterfaceClass, - config->interface[ifnum].altsetting[0].desc.bInterfaceSubClass); -#endif - - /* - * audiocontrol interface found - * find which configuration number is active - */ - buffer = dev->rawdescriptors[dev->actconfig - dev->config]; - buflen = le16_to_cpu(dev->actconfig->desc.wTotalLength); - s = usb_audio_parsecontrol(dev, buffer, buflen, intf->altsetting->desc.bInterfaceNumber); - if (s) { - usb_set_intfdata (intf, s); - return 0; - } - return -ENODEV; -} - - -/* a revoke facility would make things simpler */ - -static void usb_audio_disconnect(struct usb_interface *intf) -{ - struct usb_audio_state *s = usb_get_intfdata (intf); - struct usb_audiodev *as; - struct usb_mixerdev *ms; - - if (!s) - return; - - /* we get called with -1 for every audiostreaming interface registered */ - if (s == (struct usb_audio_state *)-1) { - dprintk((KERN_DEBUG "usbaudio: note, usb_audio_disconnect called with -1\n")); - return; - } - if (!s->usbdev) { - dprintk((KERN_DEBUG "usbaudio: error, usb_audio_disconnect already called for %p!\n", s)); - return; - } - down(&open_sem); - list_del_init(&s->audiodev); - s->usbdev = NULL; - usb_set_intfdata (intf, NULL); - - /* deregister all audio and mixer devices, so no new processes can open this device */ - list_for_each_entry(as, &s->audiolist, list) { - usbin_disc(as); - usbout_disc(as); - wake_up(&as->usbin.dma.wait); - wake_up(&as->usbout.dma.wait); - if (as->dev_audio >= 0) { - unregister_sound_dsp(as->dev_audio); - printk(KERN_INFO "usbaudio: unregister dsp 14,%d\n", as->dev_audio); - } - as->dev_audio = -1; - } - list_for_each_entry(ms, &s->mixerlist, list) { - if (ms->dev_mixer >= 0) { - unregister_sound_mixer(ms->dev_mixer); - printk(KERN_INFO "usbaudio: unregister mixer 14,%d\n", ms->dev_mixer); - } - ms->dev_mixer = -1; - } - release(s); - wake_up(&open_wait); -} - -static int __init usb_audio_init(void) -{ - int result = usb_register(&usb_audio_driver); - if (result == 0) - info(DRIVER_VERSION ":" DRIVER_DESC); - return result; -} - - -static void __exit usb_audio_cleanup(void) -{ - usb_deregister(&usb_audio_driver); -} - -module_init(usb_audio_init); -module_exit(usb_audio_cleanup); - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); - diff --git a/drivers/usb/class/audio.h b/drivers/usb/class/audio.h deleted file mode 100644 index 45916eb12103..000000000000 --- a/drivers/usb/class/audio.h +++ /dev/null @@ -1,110 +0,0 @@ -#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 -#define MIXER_UNIT 0x04 -#define SELECTOR_UNIT 0x05 -#define FEATURE_UNIT 0x06 -#define PROCESSING_UNIT 0x07 -#define EXTENSION_UNIT 0x08 - -#define AS_GENERAL 0x01 -#define FORMAT_TYPE 0x02 -#define FORMAT_SPECIFIC 0x03 - -#define EP_GENERAL 0x01 - -#define MAX_CHAN 9 -#define MAX_FREQ 16 -#define MAX_IFACE 8 -#define MAX_FORMAT 8 -#define MAX_ALT 32 /* Sorry, we need quite a few for the Philips webcams */ - -struct usb_audio_terminal -{ - u8 flags; - u8 assoc; - u16 type; /* Mic etc */ - u8 channels; - u8 source; - u16 chancfg; -}; - -struct usb_audio_format -{ - u8 type; - u8 channels; - u8 num_freq; - u8 sfz; - u8 bits; - u16 freq[MAX_FREQ]; -}; - -struct usb_audio_interface -{ - u8 terminal; - u8 delay; - u16 num_formats; - u16 format_type; - u8 flags; - u8 idleconf; /* Idle config */ -#define AU_IFACE_FOUND 1 - struct usb_audio_format format[MAX_FORMAT]; -}; - -struct usb_audio_device -{ - struct list_head list; - u8 mixer; - u8 selector; - void *irq_handle; - u8 num_channels; - u8 num_dsp_iface; - u8 channel_map[MAX_CHAN]; - struct usb_audio_terminal terminal[MAX_CHAN]; - struct usb_audio_interface interface[MAX_IFACE][MAX_ALT]; -}; - - - -/* Audio Class specific Request Codes */ - -#define SET_CUR 0x01 -#define GET_CUR 0x81 -#define SET_MIN 0x02 -#define GET_MIN 0x82 -#define SET_MAX 0x03 -#define GET_MAX 0x83 -#define SET_RES 0x04 -#define GET_RES 0x84 -#define SET_MEM 0x05 -#define GET_MEM 0x85 -#define GET_STAT 0xff - -/* Terminal Control Selectors */ - -#define COPY_PROTECT_CONTROL 0x01 - -/* Feature Unit Control Selectors */ - -#define MUTE_CONTROL 0x01 -#define VOLUME_CONTROL 0x02 -#define BASS_CONTROL 0x03 -#define MID_CONTROL 0x04 -#define TREBLE_CONTROL 0x05 -#define GRAPHIC_EQUALIZER_CONTROL 0x06 -#define AUTOMATIC_GAIN_CONTROL 0x07 -#define DELAY_CONTROL 0x08 -#define BASS_BOOST_CONTROL 0x09 -#define LOUDNESS_CONTROL 0x0a - -/* Endpoint Control Selectors */ - -#define SAMPLING_FREQ_CONTROL 0x01 -#define PITCH_CONTROL 0x02 diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c deleted file mode 100644 index f13f004d311f..000000000000 --- a/drivers/usb/class/usb-midi.c +++ /dev/null @@ -1,2153 +0,0 @@ -/* - usb-midi.c -- USB-MIDI driver - - Copyright (C) 2001 - NAGANO Daisuke - - 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; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - This driver is based on: - - 'Universal Serial Bus Device Class Definition for MIDI Device' - - linux/drivers/sound/es1371.c, linux/drivers/usb/audio.c - - alsa/lowlevel/pci/cs64xx.c - - umidi.c for NetBSD - */ - -/* ------------------------------------------------------------------------- */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "usb-midi.h" - -/* ------------------------------------------------------------------------- */ - -/* More verbose on syslog */ -#undef MIDI_DEBUG - -#define MIDI_IN_BUFSIZ 1024 - -#define HAVE_SUPPORT_USB_MIDI_CLASS - -#undef HAVE_SUPPORT_ALSA - -/* ------------------------------------------------------------------------- */ - -static int singlebyte = 0; -module_param(singlebyte, int, 0); -MODULE_PARM_DESC(singlebyte,"Enable sending MIDI messages with single message packet"); - -static int maxdevices = 4; -module_param(maxdevices, int, 0); -MODULE_PARM_DESC(maxdevices,"Max number of allocatable MIDI device"); - -static int uvendor = -1; -module_param(uvendor, int, 0); -MODULE_PARM_DESC(uvendor, "The USB Vendor ID of a semi-compliant interface"); - -static int uproduct = -1; -module_param(uproduct, int, 0); -MODULE_PARM_DESC(uproduct, "The USB Product ID of a semi-compliant interface"); - -static int uinterface = -1; -module_param(uinterface, int, 0); -MODULE_PARM_DESC(uinterface, "The Interface number of a semi-compliant interface"); - -static int ualt = -1; -module_param(ualt, int, 0); -MODULE_PARM_DESC(ualt, "The optional alternative setting of a semi-compliant interface"); - -static int umin = -1; -module_param(umin, int, 0); -MODULE_PARM_DESC(umin, "The input endpoint of a semi-compliant interface"); - -static int umout = -1; -module_param(umout, int, 0); -MODULE_PARM_DESC(umout, "The output endpoint of a semi-compliant interface"); - -static int ucable = -1; -module_param(ucable, int, 0); -MODULE_PARM_DESC(ucable, "The cable number used for a semi-compliant interface"); - -/** Note -- the usb_string() returns only Latin-1 characters. - * (unicode chars <= 255). To support Japanese, a unicode16LE-to-EUC or - * unicode16LE-to-JIS routine is needed to wrap around usb_get_string(). - **/ -static unsigned short ulangid = 0x0409; /** 0x0411 for Japanese **/ -module_param(ulangid, ushort, 0); -MODULE_PARM_DESC(ulangid, "The optional preferred USB Language ID for all devices"); - -MODULE_AUTHOR("NAGANO Daisuke "); -MODULE_DESCRIPTION("USB-MIDI driver"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------------------- */ - -/** MIDIStreaming Class-Specific Interface Descriptor Subtypes **/ - -#define MS_DESCRIPTOR_UNDEFINED 0 -#define MS_HEADER 1 -#define MIDI_IN_JACK 2 -#define MIDI_OUT_JACK 3 -/* Spec reads: ELEMENT */ -#define ELEMENT_DESCRIPTOR 4 - -#define MS_HEADER_LENGTH 7 - -/** MIDIStreaming Class-Specific Endpoint Descriptor Subtypes **/ - -#define DESCRIPTOR_UNDEFINED 0 -/* Spec reads: MS_GENERAL */ -#define MS_GENERAL_ENDPOINT 1 - -/** MIDIStreaming MIDI IN and OUT Jack Types **/ - -#define JACK_TYPE_UNDEFINED 0 -/* Spec reads: EMBEDDED */ -#define EMBEDDED_JACK 1 -/* Spec reads: EXTERNAL */ -#define EXTERNAL_JACK 2 - - -/* structure summary - - usb_midi_state usb_device - | | - *| *| per ep - in_ep out_ep - | | - *| *| per cable - min mout - | | (cable to device pairing magic) - | | - usb_midi_dev dev_id (major,minor) == file->private_data - -*/ - -/* usb_midi_state: corresponds to a USB-MIDI module */ -struct usb_midi_state { - struct list_head mididev; - - struct usb_device *usbdev; - - struct list_head midiDevList; - struct list_head inEndpointList; - struct list_head outEndpointList; - - spinlock_t lock; - - unsigned int count; /* usage counter */ -}; - -/* midi_out_endpoint: corresponds to an output endpoint */ -struct midi_out_endpoint { - struct list_head list; - - struct usb_device *usbdev; - int endpoint; - spinlock_t lock; - wait_queue_head_t wait; - - unsigned char *buf; - int bufWrPtr; - int bufSize; - - struct urb *urb; -}; - -/* midi_in_endpoint: corresponds to an input endpoint */ -struct midi_in_endpoint { - struct list_head list; - - struct usb_device *usbdev; - int endpoint; - spinlock_t lock; - wait_queue_head_t wait; - - struct usb_mididev *cables[16]; // cables open for read - int readers; // number of cables open for read - - struct urb *urb; - unsigned char *recvBuf; - int recvBufSize; - int urbSubmitted; //FIXME: == readers > 0 -}; - -/* usb_mididev: corresponds to a logical device */ -struct usb_mididev { - struct list_head list; - - struct usb_midi_state *midi; - int dev_midi; - mode_t open_mode; - - struct { - struct midi_in_endpoint *ep; - int cableId; - -// as we are pushing data from usb_bulk_read to usb_midi_read, -// we need a larger, cyclic buffer here. - unsigned char buf[MIDI_IN_BUFSIZ]; - int bufRdPtr; - int bufWrPtr; - int bufRemains; - } min; - - struct { - struct midi_out_endpoint *ep; - int cableId; - - unsigned char buf[3]; - int bufPtr; - int bufRemains; - - int isInExclusive; - unsigned char lastEvent; - } mout; - - int singlebyte; -}; - -/** Map the high nybble of MIDI voice messages to number of Message bytes. - * High nyble ranges from 0x8 to 0xe - */ - -static int remains_80e0[] = { - 3, /** 0x8X Note Off **/ - 3, /** 0x9X Note On **/ - 3, /** 0xAX Poly-key pressure **/ - 3, /** 0xBX Control Change **/ - 2, /** 0xCX Program Change **/ - 2, /** 0xDX Channel pressure **/ - 3 /** 0xEX PitchBend Change **/ -}; - -/** Map the messages to a number of Message bytes. - * - **/ -static int remains_f0f6[] = { - 0, /** 0xF0 **/ - 2, /** 0XF1 **/ - 3, /** 0XF2 **/ - 2, /** 0XF3 **/ - 2, /** 0XF4 (Undefined by MIDI Spec, and subject to change) **/ - 2, /** 0XF5 (Undefined by MIDI Spec, and subject to change) **/ - 1 /** 0XF6 **/ -}; - -/** Map the messages to a CIN (Code Index Number). - * - **/ -static int cin_f0ff[] = { - 4, /** 0xF0 System Exclusive Message Start (special cases may be 6 or 7) */ - 2, /** 0xF1 **/ - 3, /** 0xF2 **/ - 2, /** 0xF3 **/ - 2, /** 0xF4 **/ - 2, /** 0xF5 **/ - 5, /** 0xF6 **/ - 5, /** 0xF7 End of System Exclusive Message (May be 6 or 7) **/ - 5, /** 0xF8 **/ - 5, /** 0xF9 **/ - 5, /** 0xFA **/ - 5, /** 0xFB **/ - 5, /** 0xFC **/ - 5, /** 0xFD **/ - 5, /** 0xFE **/ - 5 /** 0xFF **/ -}; - -/** Map MIDIStreaming Event packet Code Index Number (low nybble of byte 0) - * to the number of bytes of valid MIDI data. - * - * CIN of 0 and 1 are NOT USED in MIDIStreaming 1.0. - * - **/ -static int cin_to_len[] = { - 0, 0, 2, 3, - 3, 1, 2, 3, - 3, 3, 3, 3, - 2, 2, 3, 1 -}; - - -/* ------------------------------------------------------------------------- */ - -static struct list_head mididevs = LIST_HEAD_INIT(mididevs); - -static DECLARE_MUTEX(open_sem); -static DECLARE_WAIT_QUEUE_HEAD(open_wait); - - -/* ------------------------------------------------------------------------- */ - -static void usb_write_callback(struct urb *urb, struct pt_regs *regs) -{ - struct midi_out_endpoint *ep = (struct midi_out_endpoint *)urb->context; - - if ( waitqueue_active( &ep->wait ) ) - wake_up_interruptible( &ep->wait ); -} - - -static int usb_write( struct midi_out_endpoint *ep, unsigned char *buf, int len ) -{ - struct usb_device *d; - int pipe; - int ret = 0; - int status; - int maxretry = 50; - - DECLARE_WAITQUEUE(wait,current); - init_waitqueue_head(&ep->wait); - - d = ep->usbdev; - pipe = usb_sndbulkpipe(d, ep->endpoint); - usb_fill_bulk_urb( ep->urb, d, pipe, (unsigned char*)buf, len, - usb_write_callback, ep ); - - status = usb_submit_urb(ep->urb, GFP_KERNEL); - - if (status) { - printk(KERN_ERR "usbmidi: Cannot submit urb (%d)\n",status); - ret = -EIO; - goto error; - } - - add_wait_queue( &ep->wait, &wait ); - set_current_state( TASK_INTERRUPTIBLE ); - - while( ep->urb->status == -EINPROGRESS ) { - if ( maxretry-- < 0 ) { - printk(KERN_ERR "usbmidi: usb_bulk_msg timed out\n"); - ret = -ETIME; - break; - } - interruptible_sleep_on_timeout( &ep->wait, 10 ); - } - set_current_state( TASK_RUNNING ); - remove_wait_queue( &ep->wait, &wait ); - -error: - return ret; -} - - -/** Copy data from URB to In endpoint buf. - * Discard if CIN == 0 or CIN = 1. - * - * - **/ - -static void usb_bulk_read(struct urb *urb, struct pt_regs *regs) -{ - struct midi_in_endpoint *ep = (struct midi_in_endpoint *)(urb->context); - unsigned char *data = urb->transfer_buffer; - int i, j, wake; - - if ( !ep->urbSubmitted ) { - return; - } - - if ( (urb->status == 0) && (urb->actual_length > 0) ) { - wake = 0; - spin_lock( &ep->lock ); - - for(j = 0; j < urb->actual_length; j += 4) { - int cin = (data[j]>>0)&0xf; - int cab = (data[j]>>4)&0xf; - struct usb_mididev *cable = ep->cables[cab]; - if ( cable ) { - int len = cin_to_len[cin]; /** length of MIDI data **/ - for (i = 0; i < len; i++) { - cable->min.buf[cable->min.bufWrPtr] = data[1+i+j]; - cable->min.bufWrPtr = (cable->min.bufWrPtr+1)%MIDI_IN_BUFSIZ; - if (cable->min.bufRemains < MIDI_IN_BUFSIZ) - cable->min.bufRemains += 1; - else /** need to drop data **/ - cable->min.bufRdPtr += (cable->min.bufRdPtr+1)%MIDI_IN_BUFSIZ; - wake = 1; - } - } - } - - spin_unlock ( &ep->lock ); - if ( wake ) { - wake_up( &ep->wait ); - } - } - - /* urb->dev must be reinitialized on 2.4.x kernels */ - urb->dev = ep->usbdev; - - urb->actual_length = 0; - usb_submit_urb(urb, GFP_ATOMIC); -} - - - -/* ------------------------------------------------------------------------- */ - -/* This routine must be called with spin_lock */ - -/** Wrapper around usb_write(). - * This routine must be called with spin_lock held on ep. - * Called by midiWrite(), putOneMidiEvent(), and usb_midi_write(); - **/ -static int flush_midi_buffer( struct midi_out_endpoint *ep ) -{ - int ret=0; - - if ( ep->bufWrPtr > 0 ) { - ret = usb_write( ep, ep->buf, ep->bufWrPtr ); - ep->bufWrPtr = 0; - } - - return ret; -} - - -/* ------------------------------------------------------------------------- */ - - -/** Given a MIDI Event, determine size of data to be attached to - * USB-MIDI packet. - * Returns 1, 2 or 3. - * Called by midiWrite(); - * Uses remains_80e0 and remains_f0f6; - **/ -static int get_remains(int event) -{ - int ret; - - if ( event < 0x80 ) { - ret = 1; - } else if ( event < 0xf0 ) { - ret = remains_80e0[((event-0x80)>>4)&0x0f]; - } else if ( event < 0xf7 ) { - ret = remains_f0f6[event-0xf0]; - } else { - ret = 1; - } - - return ret; -} - -/** Given the output MIDI data in the output buffer, computes a reasonable - * CIN. - * Called by putOneMidiEvent(). - **/ -static int get_CIN( struct usb_mididev *m ) -{ - int cin; - - if ( m->mout.buf[0] == 0xf7 ) { - cin = 5; - } - else if ( m->mout.buf[1] == 0xf7 ) { - cin = 6; - } - else if ( m->mout.buf[2] == 0xf7 ) { - cin = 7; - } - else { - if ( m->mout.isInExclusive == 1 ) { - cin = 4; - } else if ( m->mout.buf[0] < 0x80 ) { - /** One byte that we know nothing about. **/ - cin = 0xF; - } else if ( m->mout.buf[0] < 0xf0 ) { - /** MIDI Voice messages 0x8X to 0xEX map to cin 0x8 to 0xE. **/ - cin = (m->mout.buf[0]>>4)&0x0f; - } - else { - /** Special lookup table exists for real-time events. **/ - cin = cin_f0ff[m->mout.buf[0]-0xf0]; - } - } - - return cin; -} - - -/* ------------------------------------------------------------------------- */ - - - -/** Move data to USB endpoint buffer. - * - **/ -static int put_one_midi_event(struct usb_mididev *m) -{ - int cin; - unsigned long flags; - struct midi_out_endpoint *ep = m->mout.ep; - int ret=0; - - cin = get_CIN( m ); - if ( cin > 0x0f || cin < 0 ) { - return -EINVAL; - } - - spin_lock_irqsave( &ep->lock, flags ); - ep->buf[ep->bufWrPtr++] = (m->mout.cableId<<4) | cin; - ep->buf[ep->bufWrPtr++] = m->mout.buf[0]; - ep->buf[ep->bufWrPtr++] = m->mout.buf[1]; - ep->buf[ep->bufWrPtr++] = m->mout.buf[2]; - if ( ep->bufWrPtr >= ep->bufSize ) { - ret = flush_midi_buffer( ep ); - } - spin_unlock_irqrestore( &ep->lock, flags); - - m->mout.buf[0] = m->mout.buf[1] = m->mout.buf[2] = 0; - m->mout.bufPtr = 0; - - return ret; -} - -/** Write the MIDI message v on the midi device. - * Called by usb_midi_write(); - * Responsible for packaging a MIDI data stream into USB-MIDI packets. - **/ - -static int midi_write( struct usb_mididev *m, int v ) -{ - unsigned long flags; - struct midi_out_endpoint *ep = m->mout.ep; - int ret=0; - unsigned char c = (unsigned char)v; - unsigned char sysrt_buf[4]; - - if ( m->singlebyte != 0 ) { - /** Simple code to handle the single-byte USB-MIDI protocol. */ - spin_lock_irqsave( &ep->lock, flags ); - if ( ep->bufWrPtr+4 > ep->bufSize ) { - ret = flush_midi_buffer( ep ); - if ( !ret ) { - spin_unlock_irqrestore( &ep->lock, flags ); - return ret; - } - } - ep->buf[ep->bufWrPtr++] = (m->mout.cableId<<4) | 0x0f; /* single byte */ - ep->buf[ep->bufWrPtr++] = c; - ep->buf[ep->bufWrPtr++] = 0; - ep->buf[ep->bufWrPtr++] = 0; - if ( ep->bufWrPtr >= ep->bufSize ) { - ret = flush_midi_buffer( ep ); - } - spin_unlock_irqrestore( &ep->lock, flags ); - - return ret; - } - /** Normal USB-MIDI protocol begins here. */ - - if ( c > 0xf7 ) { /* system: Realtime messages */ - /** Realtime messages are written IMMEDIATELY. */ - sysrt_buf[0] = (m->mout.cableId<<4) | 0x0f; - sysrt_buf[1] = c; - sysrt_buf[2] = 0; - sysrt_buf[3] = 0; - spin_lock_irqsave( &ep->lock, flags ); - ret = usb_write( ep, sysrt_buf, 4 ); - spin_unlock_irqrestore( &ep->lock, flags ); - /* m->mout.lastEvent = 0; */ - - return ret; - } - - if ( c >= 0x80 ) { - if ( c < 0xf0 ) { - m->mout.lastEvent = c; - m->mout.isInExclusive = 0; - m->mout.bufRemains = get_remains(c); - } else if ( c == 0xf0 ) { - /* m->mout.lastEvent = 0; */ - m->mout.isInExclusive = 1; - m->mout.bufRemains = get_remains(c); - } else if ( c == 0xf7 && m->mout.isInExclusive == 1 ) { - /* m->mout.lastEvent = 0; */ - m->mout.isInExclusive = 0; - m->mout.bufRemains = 1; - } else if ( c > 0xf0 ) { - /* m->mout.lastEvent = 0; */ - m->mout.isInExclusive = 0; - m->mout.bufRemains = get_remains(c); - } - - } else if ( m->mout.bufRemains == 0 && m->mout.isInExclusive == 0 ) { - if ( m->mout.lastEvent == 0 ) { - return 0; /* discard, waiting for the first event */ - } - /** track status **/ - m->mout.buf[0] = m->mout.lastEvent; - m->mout.bufPtr = 1; - m->mout.bufRemains = get_remains(m->mout.lastEvent)-1; - } - - m->mout.buf[m->mout.bufPtr++] = c; - m->mout.bufRemains--; - if ( m->mout.bufRemains == 0 || m->mout.bufPtr >= 3) { - ret = put_one_midi_event(m); - } - - return ret; -} - - -/* ------------------------------------------------------------------------- */ - -/** Basic operation on /dev/midiXX as registered through struct file_operations. - * - * Basic contract: Used to change the current read/write position in a file. - * On success, the non-negative position is reported. - * On failure, the negative of an error code is reported. - * - * Because a MIDIStream is not a file, all seek operations are doomed to fail. - * - **/ -static loff_t usb_midi_llseek(struct file *file, loff_t offset, int origin) -{ - /** Tell user you cannot seek on a PIPE-like device. **/ - return -ESPIPE; -} - - -/** Basic operation on /dev/midiXX as registered through struct file_operations. - * - * Basic contract: Block until count bytes have been read or an error occurs. - * - **/ - -static ssize_t usb_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) -{ - struct usb_mididev *m = (struct usb_mididev *)file->private_data; - struct midi_in_endpoint *ep = m->min.ep; - ssize_t ret; - DECLARE_WAITQUEUE(wait, current); - - if ( !access_ok(VERIFY_READ, buffer, count) ) { - return -EFAULT; - } - if ( count == 0 ) { - return 0; - } - - add_wait_queue( &ep->wait, &wait ); - ret = 0; - while( count > 0 ) { - int cnt; - int d = (int)count; - - cnt = m->min.bufRemains; - if ( cnt > d ) { - cnt = d; - } - - if ( cnt <= 0 ) { - if ( file->f_flags & O_NONBLOCK ) { - if (!ret) - ret = -EAGAIN; - break; - } - __set_current_state(TASK_INTERRUPTIBLE); - schedule(); - if (signal_pending(current)) { - if(!ret) - ret=-ERESTARTSYS; - break; - } - continue; - } - - { - int i; - unsigned long flags; /* used to synchronize access to the endpoint */ - spin_lock_irqsave( &ep->lock, flags ); - for (i = 0; i < cnt; i++) { - if ( copy_to_user( buffer+i, m->min.buf+m->min.bufRdPtr, 1 ) ) { - if ( !ret ) - ret = -EFAULT; - break; - } - m->min.bufRdPtr = (m->min.bufRdPtr+1)%MIDI_IN_BUFSIZ; - m->min.bufRemains -= 1; - } - spin_unlock_irqrestore( &ep->lock, flags ); - } - - count-=cnt; - buffer+=cnt; - ret+=cnt; - - break; - } - - remove_wait_queue( &ep->wait, &wait ); - set_current_state(TASK_RUNNING); - - return ret; -} - - -/** Basic operation on /dev/midiXX as registered through struct file_operations. - * - * Basic Contract: Take MIDI data byte-by-byte and pass it to - * writeMidi() which packages MIDI data into USB-MIDI stream. - * Then flushMidiData() is called to ensure all bytes have been written - * in a timely fashion. - * - **/ - -static ssize_t usb_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) -{ - struct usb_mididev *m = (struct usb_mididev *)file->private_data; - ssize_t ret; - unsigned long int flags; - - if ( !access_ok(VERIFY_READ, buffer, count) ) { - return -EFAULT; - } - if ( count == 0 ) { - return 0; - } - - ret = 0; - while( count > 0 ) { - unsigned char c; - - if (copy_from_user((unsigned char *)&c, buffer, 1)) { - if ( ret == 0 ) - ret = -EFAULT; - break; - } - if( midi_write(m, (int)c) ) { - if ( ret == 0 ) - ret = -EFAULT; - break; - } - count--; - buffer++; - ret++; - } - - spin_lock_irqsave( &m->mout.ep->lock, flags ); - if ( flush_midi_buffer(m->mout.ep) < 0 ) { - ret = -EFAULT; - } - spin_unlock_irqrestore( &m->mout.ep->lock, flags ); - - return ret; -} - -/** Basic operation on /dev/midiXX as registered through struct file_operations. - * - * Basic contract: Wait (spin) until ready to read or write on the file. - * - **/ -static unsigned int usb_midi_poll(struct file *file, struct poll_table_struct *wait) -{ - struct usb_mididev *m = (struct usb_mididev *)file->private_data; - struct midi_in_endpoint *iep = m->min.ep; - struct midi_out_endpoint *oep = m->mout.ep; - unsigned long flags; - unsigned int mask = 0; - - if ( file->f_mode & FMODE_READ ) { - poll_wait( file, &iep->wait, wait ); - spin_lock_irqsave( &iep->lock, flags ); - if ( m->min.bufRemains > 0 ) - mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore( &iep->lock, flags ); - } - - if ( file->f_mode & FMODE_WRITE ) { - poll_wait( file, &oep->wait, wait ); - spin_lock_irqsave( &oep->lock, flags ); - if ( oep->bufWrPtr < oep->bufSize ) - mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore( &oep->lock, flags ); - } - - return mask; -} - - -/** Basic operation on /dev/midiXX as registered through struct file_operations. - * - * Basic contract: This is always the first operation performed on the - * device node. If no method is defined, the open succeeds without any - * notification given to the module. - * - **/ - -static int usb_midi_open(struct inode *inode, struct file *file) -{ - int minor = iminor(inode); - DECLARE_WAITQUEUE(wait, current); - struct usb_midi_state *s; - struct usb_mididev *m; - unsigned long flags; - int succeed = 0; - -#if 0 - printk(KERN_INFO "usb-midi: Open minor= %d.\n", minor); -#endif - - for(;;) { - down(&open_sem); - list_for_each_entry(s, &mididevs, mididev) { - list_for_each_entry(m, &s->midiDevList, list) { - if ( !((m->dev_midi ^ minor) & ~0xf) ) - goto device_found; - } - } - up(&open_sem); - return -ENODEV; - - device_found: - if ( !s->usbdev ) { - up(&open_sem); - return -EIO; - } - if ( !(m->open_mode & file->f_mode) ) { - break; - } - if ( file->f_flags & O_NONBLOCK ) { - up(&open_sem); - return -EBUSY; - } - __set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue( &open_wait, &wait ); - up(&open_sem); - schedule(); - remove_wait_queue( &open_wait, &wait ); - if ( signal_pending(current) ) { - return -ERESTARTSYS; - } - } - - file->private_data = m; - spin_lock_irqsave( &s->lock, flags ); - - if ( !(m->open_mode & (FMODE_READ | FMODE_WRITE)) ) { - //FIXME: intented semantics unclear here - m->min.bufRdPtr = 0; - m->min.bufWrPtr = 0; - m->min.bufRemains = 0; - spin_lock_init(&m->min.ep->lock); - - m->mout.bufPtr = 0; - m->mout.bufRemains = 0; - m->mout.isInExclusive = 0; - m->mout.lastEvent = 0; - spin_lock_init(&m->mout.ep->lock); - } - - if ( (file->f_mode & FMODE_READ) && m->min.ep != NULL ) { - unsigned long int flagsep; - spin_lock_irqsave( &m->min.ep->lock, flagsep ); - m->min.ep->cables[m->min.cableId] = m; - m->min.ep->readers += 1; - m->min.bufRdPtr = 0; - m->min.bufWrPtr = 0; - m->min.bufRemains = 0; - spin_unlock_irqrestore( &m->min.ep->lock, flagsep ); - - if ( !(m->min.ep->urbSubmitted)) { - - /* urb->dev must be reinitialized on 2.4.x kernels */ - m->min.ep->urb->dev = m->min.ep->usbdev; - - if ( usb_submit_urb(m->min.ep->urb, GFP_ATOMIC) ) { - printk(KERN_ERR "usbmidi: Cannot submit urb for MIDI-IN\n"); - } - m->min.ep->urbSubmitted = 1; - } - m->open_mode |= FMODE_READ; - succeed = 1; - } - - if ( (file->f_mode & FMODE_WRITE) && m->mout.ep != NULL ) { - m->mout.bufPtr = 0; - m->mout.bufRemains = 0; - m->mout.isInExclusive = 0; - m->mout.lastEvent = 0; - m->open_mode |= FMODE_WRITE; - succeed = 1; - } - - spin_unlock_irqrestore( &s->lock, flags ); - - s->count++; - up(&open_sem); - - /** Changed to prevent extra increments to USE_COUNT. **/ - if (!succeed) { - return -EBUSY; - } - -#if 0 - printk(KERN_INFO "usb-midi: Open Succeeded. minor= %d.\n", minor); -#endif - - return nonseekable_open(inode, file); /** Success. **/ -} - - -/** Basic operation on /dev/midiXX as registered through struct file_operations. - * - * Basic contract: Close an opened file and deallocate anything we allocated. - * Like open(), this can be missing. If open set file->private_data, - * release() must clear it. - * - **/ - -static int usb_midi_release(struct inode *inode, struct file *file) -{ - struct usb_mididev *m = (struct usb_mididev *)file->private_data; - struct usb_midi_state *s = (struct usb_midi_state *)m->midi; - -#if 0 - printk(KERN_INFO "usb-midi: Close.\n"); -#endif - - down(&open_sem); - - if ( m->open_mode & FMODE_WRITE ) { - m->open_mode &= ~FMODE_WRITE; - usb_kill_urb( m->mout.ep->urb ); - } - - if ( m->open_mode & FMODE_READ ) { - unsigned long int flagsep; - spin_lock_irqsave( &m->min.ep->lock, flagsep ); - m->min.ep->cables[m->min.cableId] = NULL; // discard cable - m->min.ep->readers -= 1; - m->open_mode &= ~FMODE_READ; - if ( m->min.ep->readers == 0 && - m->min.ep->urbSubmitted ) { - m->min.ep->urbSubmitted = 0; - usb_kill_urb(m->min.ep->urb); - } - spin_unlock_irqrestore( &m->min.ep->lock, flagsep ); - } - - s->count--; - - up(&open_sem); - wake_up(&open_wait); - - file->private_data = NULL; - return 0; -} - -static struct file_operations usb_midi_fops = { - .owner = THIS_MODULE, - .llseek = usb_midi_llseek, - .read = usb_midi_read, - .write = usb_midi_write, - .poll = usb_midi_poll, - .open = usb_midi_open, - .release = usb_midi_release, -}; - -/* ------------------------------------------------------------------------- */ - -/** Returns filled midi_in_endpoint structure or null on failure. - * - * Parameters: - * d - a usb_device - * endPoint - An usb endpoint in the range 0 to 15. - * Called by allocUsbMidiDev(); - * - **/ - -static struct midi_in_endpoint *alloc_midi_in_endpoint( struct usb_device *d, int endPoint ) -{ - struct midi_in_endpoint *ep; - int bufSize; - int pipe; - - endPoint &= 0x0f; /* Silently force endPoint to lie in range 0 to 15. */ - - pipe = usb_rcvbulkpipe( d, endPoint ); - bufSize = usb_maxpacket( d, pipe, 0 ); - /* usb_pipein() = ! usb_pipeout() = true for an in Endpoint */ - - ep = (struct midi_in_endpoint *)kmalloc(sizeof(struct midi_in_endpoint), GFP_KERNEL); - if ( !ep ) { - printk(KERN_ERR "usbmidi: no memory for midi in-endpoint\n"); - return NULL; - } - memset( ep, 0, sizeof(struct midi_in_endpoint) ); -// this sets cables[] and readers to 0, too. -// for (i=0; i<16; i++) ep->cables[i] = 0; // discard cable -// ep->readers = 0; - - ep->endpoint = endPoint; - - ep->recvBuf = (unsigned char *)kmalloc(sizeof(unsigned char)*(bufSize), GFP_KERNEL); - if ( !ep->recvBuf ) { - printk(KERN_ERR "usbmidi: no memory for midi in-endpoint buffer\n"); - kfree(ep); - return NULL; - } - - ep->urb = usb_alloc_urb(0, GFP_KERNEL); /* no ISO */ - if ( !ep->urb ) { - printk(KERN_ERR "usbmidi: no memory for midi in-endpoint urb\n"); - kfree(ep->recvBuf); - kfree(ep); - return NULL; - } - usb_fill_bulk_urb( ep->urb, d, - usb_rcvbulkpipe(d, endPoint), - (unsigned char *)ep->recvBuf, bufSize, - usb_bulk_read, ep ); - - /* ep->bufRdPtr = 0; */ - /* ep->bufWrPtr = 0; */ - /* ep->bufRemains = 0; */ - /* ep->urbSubmitted = 0; */ - ep->recvBufSize = bufSize; - - init_waitqueue_head(&ep->wait); - - return ep; -} - -static int remove_midi_in_endpoint( struct midi_in_endpoint *min ) -{ - usb_kill_urb( min->urb ); - usb_free_urb( min->urb ); - kfree( min->recvBuf ); - kfree( min ); - - return 0; -} - -/** Returns filled midi_out_endpoint structure or null on failure. - * - * Parameters: - * d - a usb_device - * endPoint - An usb endpoint in the range 0 to 15. - * Called by allocUsbMidiDev(); - * - **/ -static struct midi_out_endpoint *alloc_midi_out_endpoint( struct usb_device *d, int endPoint ) -{ - struct midi_out_endpoint *ep = NULL; - int pipe; - int bufSize; - - endPoint &= 0x0f; - pipe = usb_sndbulkpipe( d, endPoint ); - bufSize = usb_maxpacket( d, pipe, 1 ); - - ep = (struct midi_out_endpoint *)kmalloc(sizeof(struct midi_out_endpoint), GFP_KERNEL); - if ( !ep ) { - printk(KERN_ERR "usbmidi: no memory for midi out-endpoint\n"); - return NULL; - } - memset( ep, 0, sizeof(struct midi_out_endpoint) ); - - ep->endpoint = endPoint; - ep->buf = (unsigned char *)kmalloc(sizeof(unsigned char)*bufSize, GFP_KERNEL); - if ( !ep->buf ) { - printk(KERN_ERR "usbmidi: no memory for midi out-endpoint buffer\n"); - kfree(ep); - return NULL; - } - - ep->urb = usb_alloc_urb(0, GFP_KERNEL); /* no ISO */ - if ( !ep->urb ) { - printk(KERN_ERR "usbmidi: no memory for midi out-endpoint urb\n"); - kfree(ep->buf); - kfree(ep); - return NULL; - } - - ep->bufSize = bufSize; - /* ep->bufWrPtr = 0; */ - - init_waitqueue_head(&ep->wait); - - return ep; -} - - -static int remove_midi_out_endpoint( struct midi_out_endpoint *mout ) -{ - usb_kill_urb( mout->urb ); - usb_free_urb( mout->urb ); - kfree( mout->buf ); - kfree( mout ); - - return 0; -} - - -/** Returns a filled usb_mididev structure, registered as a Linux MIDI device. - * - * Returns null if memory is not available or the device cannot be registered. - * Called by allocUsbMidiDev(); - * - **/ -static struct usb_mididev *allocMidiDev( - struct usb_midi_state *s, - struct midi_in_endpoint *min, - struct midi_out_endpoint *mout, - int inCableId, - int outCableId ) -{ - struct usb_mididev *m; - - m = (struct usb_mididev *)kmalloc(sizeof(struct usb_mididev), GFP_KERNEL); - if (!m) { - printk(KERN_ERR "usbmidi: no memory for midi device\n"); - return NULL; - } - - memset(m, 0, sizeof(struct usb_mididev)); - - if ((m->dev_midi = register_sound_midi(&usb_midi_fops, -1)) < 0) { - printk(KERN_ERR "usbmidi: cannot register midi device\n"); - kfree(m); - return NULL; - } - - m->midi = s; - /* m->open_mode = 0; */ - - if ( min ) { - m->min.ep = min; - m->min.ep->usbdev = s->usbdev; - m->min.cableId = inCableId; - } - /* m->min.bufPtr = 0; */ - /* m->min.bufRemains = 0; */ - - if ( mout ) { - m->mout.ep = mout; - m->mout.ep->usbdev = s->usbdev; - m->mout.cableId = outCableId; - } - /* m->mout.bufPtr = 0; */ - /* m->mout.bufRemains = 0; */ - /* m->mout.isInExclusive = 0; */ - /* m->mout.lastEvent = 0; */ - - m->singlebyte = singlebyte; - - return m; -} - - -static void release_midi_device( struct usb_midi_state *s ) -{ - struct usb_mididev *m; - struct midi_in_endpoint *min; - struct midi_out_endpoint *mout; - - if ( s->count > 0 ) { - up(&open_sem); - return; - } - up( &open_sem ); - wake_up( &open_wait ); - - while(!list_empty(&s->inEndpointList)) { - min = list_entry(s->inEndpointList.next, struct midi_in_endpoint, list); - list_del(&min->list); - remove_midi_in_endpoint(min); - } - - while(!list_empty(&s->outEndpointList)) { - mout = list_entry(s->outEndpointList.next, struct midi_out_endpoint, list); - list_del(&mout->list); - remove_midi_out_endpoint(mout); - } - - while(!list_empty(&s->midiDevList)) { - m = list_entry(s->midiDevList.next, struct usb_mididev, list); - list_del(&m->list); - kfree(m); - } - - kfree(s); - - return; -} - - -/* ------------------------------------------------------------------------- */ - -/** Utility routine to find a descriptor in a dump of many descriptors. - * Returns start of descriptor or NULL if not found. - * descStart pointer to list of interfaces. - * descLength length (in bytes) of dump - * after (ignored if NULL) this routine returns only descriptors after "after" - * dtype (mandatory) The descriptor type. - * iface (ignored if -1) returns descriptor at/following given interface - * altSetting (ignored if -1) returns descriptor at/following given altSetting - * - * - * Called by parseDescriptor(), find_csinterface_descriptor(); - * - */ -static void *find_descriptor( void *descStart, unsigned int descLength, void *after, unsigned char dtype, int iface, int altSetting ) -{ - unsigned char *p, *end, *next; - int interfaceNumber = -1, altSet = -1; - - p = descStart; - end = p + descLength; - for( ; p < end; ) { - if ( p[0] < 2 ) - return NULL; - next = p + p[0]; - if ( next > end ) - return NULL; - if ( p[1] == USB_DT_INTERFACE ) { - if ( p[0] < USB_DT_INTERFACE_SIZE ) - return NULL; - interfaceNumber = p[2]; - altSet = p[3]; - } - if ( p[1] == dtype && - ( !after || ( p > (unsigned char *)after) ) && - ( ( iface == -1) || (iface == interfaceNumber) ) && - ( (altSetting == -1) || (altSetting == altSet) )) { - return p; - } - p = next; - } - return NULL; -} - -/** Utility to find a class-specific interface descriptor. - * dsubtype is a descriptor subtype - * Called by parseDescriptor(); - **/ -static void *find_csinterface_descriptor(void *descStart, unsigned int descLength, void *after, u8 dsubtype, int iface, int altSetting) -{ - unsigned char *p; - - p = find_descriptor( descStart, descLength, after, USB_DT_CS_INTERFACE, iface, altSetting ); - while ( p ) { - if ( p[0] >= 3 && p[2] == dsubtype ) - return p; - p = find_descriptor( descStart, descLength, p, USB_DT_CS_INTERFACE, - iface, altSetting ); - } - return NULL; -} - - -/** The magic of making a new usb_midi_device from config happens here. - * - * The caller is responsible for free-ing this return value (if not NULL). - * - **/ -static struct usb_midi_device *parse_descriptor( struct usb_device *d, unsigned char *buffer, int bufSize, unsigned int ifnum , unsigned int altSetting, int quirks) -{ - struct usb_midi_device *u; - unsigned char *p1; - unsigned char *p2; - unsigned char *next; - int iep, oep; - int length; - unsigned long longBits; - int pins, nbytes, offset, shift, jack; -#ifdef HAVE_JACK_STRINGS - /** Jacks can have associated names. **/ - unsigned char jack2string[256]; -#endif - - u = NULL; - /* find audiocontrol interface */ - p1 = find_csinterface_descriptor( buffer, bufSize, NULL, - MS_HEADER, ifnum, altSetting); - - if ( !p1 ) { - goto error_end; - } - - if ( p1[0] < MS_HEADER_LENGTH ) { - goto error_end; - } - - /* Assume success. Since the device corresponds to USB-MIDI spec, we assume - that the rest of the USB 2.0 spec is obeyed. */ - - u = (struct usb_midi_device *)kmalloc( sizeof(struct usb_midi_device), GFP_KERNEL ); - if ( !u ) { - return NULL; - } - u->deviceName = NULL; - u->idVendor = le16_to_cpu(d->descriptor.idVendor); - u->idProduct = le16_to_cpu(d->descriptor.idProduct); - u->interface = ifnum; - u->altSetting = altSetting; - u->in[0].endpoint = -1; - u->in[0].cableId = -1; - u->out[0].endpoint = -1; - u->out[0].cableId = -1; - - - printk(KERN_INFO "usb-midi: Found MIDIStreaming device corresponding to Release %d.%02d of spec.\n", - (p1[4] >> 4) * 10 + (p1[4] & 0x0f ), - (p1[3] >> 4) * 10 + (p1[3] & 0x0f ) - ); - - length = p1[5] | (p1[6] << 8); - -#ifdef HAVE_JACK_STRINGS - memset(jack2string, 0, sizeof(unsigned char) * 256); -#endif - - length -= p1[0]; - for (p2 = p1 + p1[0]; length > 0; p2 = next) { - next = p2 + p2[0]; - length -= p2[0]; - - if (p2[0] < 2 ) - break; - if (p2[1] != USB_DT_CS_INTERFACE) - break; - if (p2[2] == MIDI_IN_JACK && p2[0] >= 6 ) { - jack = p2[4]; -#ifdef HAVE_JACK_STRINGS - jack2string[jack] = p2[5]; -#endif - printk(KERN_INFO "usb-midi: Found IN Jack 0x%02x %s\n", - jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL" ); - } else if ( p2[2] == MIDI_OUT_JACK && p2[0] >= 6) { - pins = p2[5]; - if ( p2[0] < (6 + 2 * pins) ) - continue; - jack = p2[4]; -#ifdef HAVE_JACK_STRINGS - jack2string[jack] = p2[5 + 2 * pins]; -#endif - printk(KERN_INFO "usb-midi: Found OUT Jack 0x%02x %s, %d pins\n", - jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL", pins ); - } else if ( p2[2] == ELEMENT_DESCRIPTOR && p2[0] >= 10) { - pins = p2[4]; - if ( p2[0] < (9 + 2 * pins ) ) - continue; - nbytes = p2[8 + 2 * pins ]; - if ( p2[0] < (10 + 2 * pins + nbytes) ) - continue; - longBits = 0L; - for ( offset = 0, shift = 0; offset < nbytes && offset < 8; offset ++, shift += 8) { - longBits |= ((long)(p2[9 + 2 * pins + offset])) << shift; - } - jack = p2[3]; -#ifdef HAVE_JACK_STRINGS - jack2string[jack] = p2[9 + 2 * pins + nbytes]; -#endif - printk(KERN_INFO "usb-midi: Found ELEMENT 0x%02x, %d/%d pins in/out, bits: 0x%016lx\n", - jack, pins, (int)(p2[5 + 2 * pins]), (long)longBits ); - } else { - } - } - - iep=0; - oep=0; - - if (quirks==0) { - /* MIDISTREAM */ - p2 = NULL; - for (p1 = find_descriptor(buffer, bufSize, NULL, USB_DT_ENDPOINT, - ifnum, altSetting ); p1; p1 = next ) { - next = find_descriptor(buffer, bufSize, p1, USB_DT_ENDPOINT, - ifnum, altSetting ); - p2 = find_descriptor(buffer, bufSize, p1, USB_DT_CS_ENDPOINT, - ifnum, altSetting ); - - if ( p2 && next && ( p2 > next ) ) - p2 = NULL; - - if ( p1[0] < 9 || !p2 || p2[0] < 4 ) - continue; - - if ( (p1[2] & 0x80) == 0x80 ) { - if ( iep < 15 ) { - pins = p2[3]; /* not pins -- actually "cables" */ - if ( pins > 16 ) - pins = 16; - u->in[iep].endpoint = p1[2]; - u->in[iep].cableId = ( 1 << pins ) - 1; - if ( u->in[iep].cableId ) - iep ++; - if ( iep < 15 ) { - u->in[iep].endpoint = -1; - u->in[iep].cableId = -1; - } - } - } else { - if ( oep < 15 ) { - pins = p2[3]; /* not pins -- actually "cables" */ - if ( pins > 16 ) - pins = 16; - u->out[oep].endpoint = p1[2]; - u->out[oep].cableId = ( 1 << pins ) - 1; - if ( u->out[oep].cableId ) - oep ++; - if ( oep < 15 ) { - u->out[oep].endpoint = -1; - u->out[oep].cableId = -1; - } - } - } - - } - } else if (quirks==1) { - /* YAMAHA quirks */ - for (p1 = find_descriptor(buffer, bufSize, NULL, USB_DT_ENDPOINT, - ifnum, altSetting ); p1; p1 = next ) { - next = find_descriptor(buffer, bufSize, p1, USB_DT_ENDPOINT, - ifnum, altSetting ); - - if ( p1[0] < 7 ) - continue; - - if ( (p1[2] & 0x80) == 0x80 ) { - if ( iep < 15 ) { - pins = iep+1; - if ( pins > 16 ) - pins = 16; - u->in[iep].endpoint = p1[2]; - u->in[iep].cableId = ( 1 << pins ) - 1; - if ( u->in[iep].cableId ) - iep ++; - if ( iep < 15 ) { - u->in[iep].endpoint = -1; - u->in[iep].cableId = -1; - } - } - } else { - if ( oep < 15 ) { - pins = oep+1; - u->out[oep].endpoint = p1[2]; - u->out[oep].cableId = ( 1 << pins ) - 1; - if ( u->out[oep].cableId ) - oep ++; - if ( oep < 15 ) { - u->out[oep].endpoint = -1; - u->out[oep].cableId = -1; - } - } - } - - } - } - - if ( !iep && ! oep ) { - goto error_end; - } - - return u; - -error_end: - kfree(u); - return NULL; -} - -/* ------------------------------------------------------------------------- */ - -/** Returns number between 0 and 16. - * - **/ -static int on_bits( unsigned short v ) -{ - int i; - int ret=0; - - for ( i=0 ; i<16 ; i++ ) { - if ( v & (1<num_altsetting; - - for ( alt=0 ; altaltsetting[alt]; - epin = -1; - epout = -1; - - for ( i=0 ; idesc.bNumEndpoints ; i++ ) { - ep = &interface->endpoint[i].desc; - if ( (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ) { - continue; - } - if ( (ep->bEndpointAddress & USB_DIR_IN) && epin < 0 ) { - epin = i; - } else if ( epout < 0 ) { - epout = i; - } - if ( epin >= 0 && epout >= 0 ) { - return interface->desc.bAlternateSetting; - } - } - } - - return -ENODEV; -} - - -/* ------------------------------------------------------------------------- */ - - -/** Returns 0 if successful in allocating and registering internal structures. - * Returns negative on failure. - * Calls allocMidiDev which additionally registers /dev/midiXX devices. - * Writes messages on success to indicate which /dev/midiXX is which physical - * endpoint. - * - **/ -static int alloc_usb_midi_device( struct usb_device *d, struct usb_midi_state *s, struct usb_midi_device *u ) -{ - struct usb_mididev **mdevs=NULL; - struct midi_in_endpoint *mins[15], *min; - struct midi_out_endpoint *mouts[15], *mout; - int inDevs=0, outDevs=0; - int inEndpoints=0, outEndpoints=0; - int inEndpoint, outEndpoint; - int inCableId, outCableId; - int i; - int devices = 0; - int alt = 0; - - /* Obtain altSetting or die.. */ - alt = u->altSetting; - if ( alt < 0 ) { - alt = get_alt_setting( d, u->interface ); - } - if ( alt < 0 ) - return -ENXIO; - - /* Configure interface */ - if ( usb_set_interface( d, u->interface, alt ) < 0 ) { - return -ENXIO; - } - - for ( i = 0 ; i < 15 ; i++ ) { - mins[i] = NULL; - mouts[i] = NULL; - } - - /* Begin Allocation */ - while( inEndpoints < 15 - && inDevs < maxdevices - && u->in[inEndpoints].cableId >= 0 ) { - inDevs += on_bits((unsigned short)u->in[inEndpoints].cableId); - mins[inEndpoints] = alloc_midi_in_endpoint( d, u->in[inEndpoints].endpoint ); - if ( mins[inEndpoints] == NULL ) - goto error_end; - inEndpoints++; - } - - while( outEndpoints < 15 - && outDevs < maxdevices - && u->out[outEndpoints].cableId >= 0 ) { - outDevs += on_bits((unsigned short)u->out[outEndpoints].cableId); - mouts[outEndpoints] = alloc_midi_out_endpoint( d, u->out[outEndpoints].endpoint ); - if ( mouts[outEndpoints] == NULL ) - goto error_end; - outEndpoints++; - } - - devices = inDevs > outDevs ? inDevs : outDevs; - devices = maxdevices > devices ? devices : maxdevices; - - /* obtain space for device name (iProduct) if not known. */ - if ( ! u->deviceName ) { - mdevs = (struct usb_mididev **) - kmalloc(sizeof(struct usb_mididevs *)*devices - + sizeof(char) * 256, GFP_KERNEL); - } else { - mdevs = (struct usb_mididev **) - kmalloc(sizeof(struct usb_mididevs *)*devices, GFP_KERNEL); - } - - if ( !mdevs ) { - /* devices = 0; */ - /* mdevs = NULL; */ - goto error_end; - } - for ( i=0 ; ideviceName ) { - u->deviceName = (char *) (mdevs + devices); - if ( ! d->have_langid && d->descriptor.iProduct) { - alt = usb_get_string(d, 0, 0, u->deviceName, 250); - if (alt < 0) { - printk(KERN_INFO "error getting string descriptor 0 (error=%d)\n", alt); - } else if (u->deviceName[0] < 4) { - printk(KERN_INFO "string descriptor 0 too short (length = %d)\n", alt); - } else { - printk(KERN_INFO "string descriptor 0 found (length = %d)\n", alt); - for(; alt >= 4; alt -= 2) { - i = u->deviceName[alt-2] | (u->deviceName[alt-1]<< 8); - printk(KERN_INFO "usb-midi: langid(%d) 0x%04x\n", - (alt-4) >> 1, i); - if ( ( ( i ^ ulangid ) & 0xff ) == 0 ) { - d->have_langid = 1; - d->string_langid = i; - printk(KERN_INFO "usb-midi: langid(match) 0x%04x\n", i); - if ( i == ulangid ) - break; - } - } - } - } - u->deviceName[0] = (char) 0; - if (d->descriptor.iProduct) { - printk(KERN_INFO "usb-midi: fetchString(%d)\n", d->descriptor.iProduct); - alt = usb_string(d, d->descriptor.iProduct, u->deviceName, 255); - if( alt < 0 ) { - u->deviceName[0] = (char) 0; - } - printk(KERN_INFO "usb-midi: fetchString = %d\n", alt); - } - /* Failsafe */ - if ( !u->deviceName[0] ) { - if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_ROLAND ) { - strcpy(u->deviceName, "Unknown Roland"); - } else if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_STEINBERG ) { - strcpy(u->deviceName, "Unknown Steinberg"); - } else if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_YAMAHA ) { - strcpy(u->deviceName, "Unknown Yamaha"); - } else { - strcpy(u->deviceName, "Unknown"); - } - } - } - - inEndpoint = 0; inCableId = -1; - outEndpoint = 0; outCableId = -1; - - for ( i=0 ; iin[inEndpoint].cableId & (1<= 16 ) { - inEndpoint ++; - inCableId = 0; - } - } - min = mins[inEndpoint]; - for ( outCableId ++ ; - outEndpoint <15 - && mouts[outEndpoint] - && !(u->out[outEndpoint].cableId & (1<= 16 ) { - outEndpoint ++; - outCableId = 0; - } - } - mout = mouts[outEndpoint]; - - mdevs[i] = allocMidiDev( s, min, mout, inCableId, outCableId ); - if ( mdevs[i] == NULL ) - goto error_end; - - } - - /* Success! */ - for ( i=0 ; ilist, &s->midiDevList ); - } - for ( i=0 ; ilist, &s->inEndpointList ); - } - for ( i=0 ; ilist, &s->outEndpointList ); - } - - printk(KERN_INFO "usbmidi: found [ %s ] (0x%04x:0x%04x), attached:\n", u->deviceName, u->idVendor, u->idProduct ); - for ( i=0 ; idev_midi-2)>>4; - if ( mdevs[i]->mout.ep != NULL && mdevs[i]->min.ep != NULL ) { - printk(KERN_INFO "usbmidi: /dev/midi%02d: in (ep:%02x cid:%2d bufsiz:%2d) out (ep:%02x cid:%2d bufsiz:%2d)\n", - dm, - mdevs[i]->min.ep->endpoint|USB_DIR_IN, mdevs[i]->min.cableId, mdevs[i]->min.ep->recvBufSize, - mdevs[i]->mout.ep->endpoint, mdevs[i]->mout.cableId, mdevs[i]->mout.ep->bufSize); - } else if ( mdevs[i]->min.ep != NULL ) { - printk(KERN_INFO "usbmidi: /dev/midi%02d: in (ep:%02x cid:%2d bufsiz:%02d)\n", - dm, - mdevs[i]->min.ep->endpoint|USB_DIR_IN, mdevs[i]->min.cableId, mdevs[i]->min.ep->recvBufSize); - } else if ( mdevs[i]->mout.ep != NULL ) { - printk(KERN_INFO "usbmidi: /dev/midi%02d: out (ep:%02x cid:%2d bufsiz:%02d)\n", - dm, - mdevs[i]->mout.ep->endpoint, mdevs[i]->mout.cableId, mdevs[i]->mout.ep->bufSize); - } - } - - kfree(mdevs); - return 0; - - error_end: - if ( mdevs != NULL ) { - for ( i=0 ; idev_midi ); - kfree(mdevs[i]); - } - } - kfree(mdevs); - } - - for ( i=0 ; i<15 ; i++ ) { - if ( mins[i] != NULL ) { - remove_midi_in_endpoint( mins[i] ); - } - if ( mouts[i] != NULL ) { - remove_midi_out_endpoint( mouts[i] ); - } - } - - return -ENOMEM; -} - -/* ------------------------------------------------------------------------- */ - -/** Attempt to scan YAMAHA's device descriptor and detect correct values of - * them. - * Return 0 on succes, negative on failure. - * Called by usb_midi_probe(); - **/ - -static int detect_yamaha_device( struct usb_device *d, - struct usb_interface *iface, unsigned int ifnum, - struct usb_midi_state *s) -{ - struct usb_host_interface *interface; - struct usb_midi_device *u; - unsigned char *buffer; - int bufSize; - int i; - int alts=-1; - int ret; - - if (le16_to_cpu(d->descriptor.idVendor) != USB_VENDOR_ID_YAMAHA) { - return -EINVAL; - } - - for ( i=0 ; i < iface->num_altsetting; i++ ) { - interface = iface->altsetting + i; - - if ( interface->desc.bInterfaceClass != 255 || - interface->desc.bInterfaceSubClass != 0 ) - continue; - alts = interface->desc.bAlternateSetting; - } - if ( alts == -1 ) { - return -EINVAL; - } - - printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n", - le16_to_cpu(d->descriptor.idVendor), - le16_to_cpu(d->descriptor.idProduct), ifnum); - - i = d->actconfig - d->config; - buffer = d->rawdescriptors[i]; - bufSize = le16_to_cpu(d->actconfig->desc.wTotalLength); - - u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 1); - if ( u == NULL ) { - return -EINVAL; - } - - ret = alloc_usb_midi_device( d, s, u ); - - kfree(u); - - return ret; -} - - -/** Scan table of known devices which are only partially compliant with - * the MIDIStreaming specification. - * Called by usb_midi_probe(); - * - **/ - -static int detect_vendor_specific_device( struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s ) -{ - struct usb_midi_device *u; - int i; - int ret = -ENXIO; - - for ( i=0; idescriptor.idVendor) != u->idVendor || - le16_to_cpu(d->descriptor.idProduct) != u->idProduct || - ifnum != u->interface ) - continue; - - ret = alloc_usb_midi_device( d, s, u ); - break; - } - - return ret; -} - - -/** Attempt to match any config of an interface to a MIDISTREAMING interface. - * Returns 0 on success, negative on failure. - * Called by usb_midi_probe(); - **/ -static int detect_midi_subclass(struct usb_device *d, - struct usb_interface *iface, unsigned int ifnum, - struct usb_midi_state *s) -{ - struct usb_host_interface *interface; - struct usb_midi_device *u; - unsigned char *buffer; - int bufSize; - int i; - int alts=-1; - int ret; - - for ( i=0 ; i < iface->num_altsetting; i++ ) { - interface = iface->altsetting + i; - - if ( interface->desc.bInterfaceClass != USB_CLASS_AUDIO || - interface->desc.bInterfaceSubClass != USB_SUBCLASS_MIDISTREAMING ) - continue; - alts = interface->desc.bAlternateSetting; - } - if ( alts == -1 ) { - return -EINVAL; - } - - printk(KERN_INFO "usb-midi: Found MIDISTREAMING on dev %04x:%04x, iface %d\n", - le16_to_cpu(d->descriptor.idVendor), - le16_to_cpu(d->descriptor.idProduct), ifnum); - - - /* From USB Spec v2.0, Section 9.5. - If the class or vendor specific descriptors use the same format - as standard descriptors (e.g., start with a length byte and - followed by a type byte), they must be returned interleaved with - standard descriptors in the configuration information returned by - a GetDescriptor(Configuration) request. In this case, the class - or vendor-specific descriptors must follow a related standard - descriptor they modify or extend. - */ - - i = d->actconfig - d->config; - buffer = d->rawdescriptors[i]; - bufSize = le16_to_cpu(d->actconfig->desc.wTotalLength); - - u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 0); - if ( u == NULL ) { - return -EINVAL; - } - - ret = alloc_usb_midi_device( d, s, u ); - - kfree(u); - - return ret; -} - - -/** When user has requested a specific device, match it exactly. - * - * Uses uvendor, uproduct, uinterface, ualt, umin, umout and ucable. - * Called by usb_midi_probe(); - * - **/ -static int detect_by_hand(struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s) -{ - struct usb_midi_device u; - - if ( le16_to_cpu(d->descriptor.idVendor) != uvendor || - le16_to_cpu(d->descriptor.idProduct) != uproduct || - ifnum != uinterface ) { - return -EINVAL; - } - - if ( ualt < 0 ) - ualt = -1; - - if ( umin < 0 || umin > 15 ) - umin = 0x01 | USB_DIR_IN; - if ( umout < 0 || umout > 15 ) - umout = 0x01; - if ( ucable < 0 || ucable > 15 ) - ucable = 0; - - u.deviceName = NULL; /* A flag for alloc_usb_midi_device to get device - name from device. */ - u.idVendor = uvendor; - u.idProduct = uproduct; - u.interface = uinterface; - u.altSetting = ualt; - - u.in[0].endpoint = umin; - u.in[0].cableId = (1<cur_altsetting->desc.bInterfaceNumber; - - s = (struct usb_midi_state *)kmalloc(sizeof(struct usb_midi_state), GFP_KERNEL); - if ( !s ) - return -ENOMEM; - - memset( s, 0, sizeof(struct usb_midi_state) ); - INIT_LIST_HEAD(&s->midiDevList); - INIT_LIST_HEAD(&s->inEndpointList); - INIT_LIST_HEAD(&s->outEndpointList); - s->usbdev = dev; - s->count = 0; - spin_lock_init(&s->lock); - - if ( - detect_by_hand( dev, ifnum, s ) && - detect_midi_subclass( dev, intf, ifnum, s ) && - detect_vendor_specific_device( dev, ifnum, s ) && - detect_yamaha_device( dev, intf, ifnum, s) ) { - kfree(s); - return -EIO; - } - - down(&open_sem); - list_add_tail(&s->mididev, &mididevs); - up(&open_sem); - - usb_set_intfdata (intf, s); - return 0; -} - - -static void usb_midi_disconnect(struct usb_interface *intf) -{ - struct usb_midi_state *s = usb_get_intfdata (intf); - struct usb_mididev *m; - - if ( !s ) - return; - - if ( s == (struct usb_midi_state *)-1 ) { - return; - } - if ( !s->usbdev ) { - return; - } - down(&open_sem); - list_del(&s->mididev); - INIT_LIST_HEAD(&s->mididev); - s->usbdev = NULL; - usb_set_intfdata (intf, NULL); - - list_for_each_entry(m, &s->midiDevList, list) { - wake_up(&(m->min.ep->wait)); - wake_up(&(m->mout.ep->wait)); - if ( m->dev_midi >= 0 ) { - unregister_sound_midi(m->dev_midi); - } - m->dev_midi = -1; - } - release_midi_device(s); - wake_up(&open_wait); -} - -/* we want to look at all devices by hand */ -static struct usb_device_id id_table[] = { - {.driver_info = 42}, - {} -}; - -static struct usb_driver usb_midi_driver = { - .name = "midi", - .probe = usb_midi_probe, - .disconnect = usb_midi_disconnect, - .id_table = id_table, -}; - -/* ------------------------------------------------------------------------- */ - -static int __init usb_midi_init(void) -{ - return usb_register(&usb_midi_driver); -} - -static void __exit usb_midi_exit(void) -{ - usb_deregister(&usb_midi_driver); -} - -module_init(usb_midi_init) ; -module_exit(usb_midi_exit) ; - -#ifdef HAVE_ALSA_SUPPORT -#define SNDRV_MAIN_OBJECT_FILE -#include "../../include/driver.h" -#include "../../include/control.h" -#include "../../include/info.h" -#include "../../include/cs46xx.h" - -/* ------------------------------------------------------------------------- */ - -static int snd_usbmidi_input_close(snd_rawmidi_substream_t * substream) -{ - return 0; -} - -static int snd_usbmidi_input_open(snd_rawmidi_substream_t * substream ) -{ - return 0; -} - -static void snd_usbmidi_input_trigger(snd_rawmidi_substream_t * substream, int up) -{ - return 0; -} - - -/* ------------------------------------------------------------------------- */ - -static int snd_usbmidi_output_close(snd_rawmidi_substream_t * substream) -{ - return 0; -} - -static int snd_usbmidi_output_open(snd_rawmidi_substream_t * substream) -{ - return 0; -} - -static void snd_usb_midi_output_trigger(snd_rawmidi_substream_t * substream, - int up) -{ - return 0; -} - -/* ------------------------------------------------------------------------- */ - -static snd_rawmidi_ops_t snd_usbmidi_output = -{ - .open = snd_usbmidi_output_open, - .close = snd_usbmidi_output_close, - .trigger = snd_usbmidi_output_trigger, -}; -static snd_rawmidi_ops_t snd_usbmidi_input = -{ - .open = snd_usbmidi_input_open, - .close = snd_usbmidi_input_close, - .trigger = snd_usbmidi_input_trigger, -}; - -int snd_usbmidi_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rrawmidi) -{ - snd_rawmidi_t *rmidi; - int err; - - if (rrawmidi) - *rrawmidi = NULL; - if ((err = snd_rawmidi_new(chip->card, "USB-MIDI", device, 1, 1, &rmidi)) < 0) - return err; - strcpy(rmidi->name, "USB-MIDI"); - - snd_rawmidi_set_ops( rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output ); - snd_rawmidi_set_ops( rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_usbmidi_input ); - - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; - - rmidi->private_data = chip; - chip->rmidi = rmidi; - if (rrawmidi) - *rrawmidi = NULL; - - return 0; -} - -int snd_usbmidi_create( snd_card_t * card, - struct pci_dev * pci, - usbmidi_t ** rchip ) -{ - usbmidi_t *chip; - int err, idx; - snd_region_t *region; - static snd_device_opt_t ops = { - .dev_free = snd_usbmidi_dev_free, - }; - - *rchip = NULL; - chip = snd_magic_kcalloc( usbmidi_t, 0, GFP_KERNEL ); - if ( chip == NULL ) - return -ENOMEM; -} - -EXPORT_SYMBOL(snd_usbmidi_create); -EXPORT_SYMBOL(snd_usbmidi_midi); -#endif /* HAVE_ALSA_SUPPORT */ - diff --git a/drivers/usb/class/usb-midi.h b/drivers/usb/class/usb-midi.h deleted file mode 100644 index 358cdef8492e..000000000000 --- a/drivers/usb/class/usb-midi.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - usb-midi.h -- USB-MIDI driver - - Copyright (C) 2001 - NAGANO Daisuke - - 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; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* ------------------------------------------------------------------------- */ - -#ifndef _USB_MIDI_H_ -#define _USB_MIDI_H_ - -#ifndef USB_SUBCLASS_MIDISTREAMING -#define USB_SUBCLASS_MIDISTREAMING 3 -#endif - -/* ------------------------------------------------------------------------- */ -/* Roland MIDI Devices */ - -#define USB_VENDOR_ID_ROLAND 0x0582 -#define USBMIDI_ROLAND_UA100G 0x0000 -#define USBMIDI_ROLAND_MPU64 0x0002 -#define USBMIDI_ROLAND_SC8850 0x0003 -#define USBMIDI_ROLAND_SC8820 0x0007 -#define USBMIDI_ROLAND_UM2 0x0005 -#define USBMIDI_ROLAND_UM1 0x0009 -#define USBMIDI_ROLAND_PC300 0x0008 - -/* YAMAHA MIDI Devices */ -#define USB_VENDOR_ID_YAMAHA 0x0499 -#define USBMIDI_YAMAHA_MU1000 0x1001 - -/* Steinberg MIDI Devices */ -#define USB_VENDOR_ID_STEINBERG 0x0763 -#define USBMIDI_STEINBERG_USB2MIDI 0x1001 - -/* Mark of the Unicorn MIDI Devices */ -#define USB_VENDOR_ID_MOTU 0x07fd -#define USBMIDI_MOTU_FASTLANE 0x0001 - -/* ------------------------------------------------------------------------- */ -/* Supported devices */ - -struct usb_midi_endpoint { - int endpoint; - int cableId; /* if bit-n == 1 then cableId-n is enabled (n: 0 - 15) */ -}; - -struct usb_midi_device { - char *deviceName; - - u16 idVendor; - u16 idProduct; - int interface; - int altSetting; /* -1: auto detect */ - - struct usb_midi_endpoint in[15]; - struct usb_midi_endpoint out[15]; -}; - -static struct usb_midi_device usb_midi_devices[] = { - { /* Roland UM-1 */ - "Roland UM-1", - USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM1, 2, -1, - { { 0x81, 1 }, {-1, -1} }, - { { 0x01, 1,}, {-1, -1} }, - }, - - { /* Roland UM-2 */ - "Roland UM-2" , - USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM2, 2, -1, - { { 0x81, 3 }, {-1, -1} }, - { { 0x01, 3,}, {-1, -1} }, - }, - -/** Next entry courtesy research by Michael Minn **/ - { /* Roland UA-100 */ - "Roland UA-100", - USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G, 2, -1, - { { 0x82, 7 }, {-1, -1} }, /** cables 0,1 and 2 for SYSEX **/ - { { 0x02, 7 }, {-1, -1} }, - }, - -/** Next entry courtesy research by Michael Minn **/ - { /* Roland SC8850 */ - "Roland SC8850", - USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850, 2, -1, - { { 0x81, 0x3f }, {-1, -1} }, - { { 0x01, 0x3f }, {-1, -1} }, - }, - - { /* Roland SC8820 */ - "Roland SC8820", - USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1, - { { 0x81, 0x13 }, {-1, -1} }, - { { 0x01, 0x13 }, {-1, -1} }, - }, - - { /* Roland SC8820 */ - "Roland SC8820", - USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1, - { { 0x81, 17 }, {-1, -1} }, - { { 0x01, 17 }, {-1, -1} }, - }, - - { /* YAMAHA MU1000 */ - "YAMAHA MU1000", - USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000, 0, -1, - { { 0x81, 1 }, {-1, -1} }, - { { 0x01, 15 }, {-1, -1} }, - }, - { /* Roland PC-300 */ - "Roland PC-300", - USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300, 2, -1, - { { 0x81, 1 }, {-1, -1} }, - { { 0x01, 1 }, {-1, -1} }, - }, - { /* MOTU Fastlane USB */ - "MOTU Fastlane USB", - USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE, 1, 0, - { { 0x82, 3 }, {-1, -1} }, - { { 0x02, 3 }, {-1, -1} }, - } -}; - -#define VENDOR_SPECIFIC_USB_MIDI_DEVICES (sizeof(usb_midi_devices)/sizeof(struct usb_midi_device)) - -/* for Hot-Plugging */ - -static struct usb_device_id usb_midi_ids [] = { - { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS), - .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING}, - { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM1 ) }, - { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM2 ) }, - { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G ) }, - { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300 ) }, - { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850 ) }, - { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820 ) }, - { USB_DEVICE( USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000 ) }, - { USB_DEVICE( USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE ) }, -/* { USB_DEVICE( USB_VENDOR_ID_STEINBERG, USBMIDI_STEINBERG_USB2MIDI ) },*/ - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, usb_midi_ids); - -/* ------------------------------------------------------------------------- */ -#endif /* _USB_MIDI_H_ */ - - -- cgit v1.2.3-59-g8ed1b From e266a12492f7ca9142882710bff92e902b7c95c8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 8 Nov 2005 21:05:43 +0100 Subject: [PATCH] USB: drivers/usb/core/message.c: make usb_get_string() static After the removal of usb-midi.c, there's no longer any external user of usb_get_string(). Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 5 ++--- include/linux/usb.h | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 7135e542679d..2f6009b0cffc 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -631,8 +631,8 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char * Returns the number of bytes received on success, or else the status code * returned by the underlying usb_control_msg() call. */ -int usb_get_string(struct usb_device *dev, unsigned short langid, - unsigned char index, void *buf, int size) +static int usb_get_string(struct usb_device *dev, unsigned short langid, + unsigned char index, void *buf, int size) { int i; int result; @@ -1488,7 +1488,6 @@ EXPORT_SYMBOL(usb_sg_wait); // synchronous control message convenience routines EXPORT_SYMBOL(usb_get_descriptor); EXPORT_SYMBOL(usb_get_status); -EXPORT_SYMBOL(usb_get_string); EXPORT_SYMBOL(usb_string); // synchronous calls that also maintain usbcore state diff --git a/include/linux/usb.h b/include/linux/usb.h index 827cc6de5f5c..130d125fda12 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1018,8 +1018,6 @@ extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype, unsigned char descindex, void *buf, int size); extern int usb_get_status(struct usb_device *dev, int type, int target, void *data); -extern int usb_get_string(struct usb_device *dev, - unsigned short langid, unsigned char index, void *buf, int size); extern int usb_string(struct usb_device *dev, int index, char *buf, size_t size); -- cgit v1.2.3-59-g8ed1b From 35cce732d9d4d9af6b4ad4d26d8f8c0eddb573a2 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Thu, 12 Jan 2006 20:35:25 +0200 Subject: [PATCH] USB: remove LINUX_VERSION_CODE macro usage This patch removes unnecessary LINUX_VERSION_CODE macro usage from drivers/usb/. Signed-off-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- drivers/usb/media/pwc/pwc-ctrl.c | 1 - drivers/usb/media/pwc/pwc-if.c | 6 +----- drivers/usb/misc/sisusbvga/sisusb.h | 8 -------- 3 files changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c index 3ebb6e9cdf92..0398b812e0ce 100644 --- a/drivers/usb/media/pwc/pwc-ctrl.c +++ b/drivers/usb/media/pwc/pwc-ctrl.c @@ -41,7 +41,6 @@ #include #endif #include -#include #include "pwc.h" #include "pwc-ioctl.h" diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c index 4f9b0dc6fd7b..db6753dc5ba5 100644 --- a/drivers/usb/media/pwc/pwc-if.c +++ b/drivers/usb/media/pwc/pwc-if.c @@ -62,7 +62,6 @@ #include #include #include -#include #include #include "pwc.h" @@ -827,13 +826,10 @@ static int pwc_isoc_init(struct pwc_device *pdev) /* Get the current alternate interface, adjust packet size */ if (!udev->actconfig) return -EFAULT; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) - idesc = &udev->actconfig->interface[0]->altsetting[pdev->valternate]; -#else + intf = usb_ifnum_to_if(udev, 0); if (intf) idesc = usb_altnum_to_altsetting(intf, pdev->valternate); -#endif if (!idesc) return -EFAULT; diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h index 1d7a77cc7c4a..a716825d1f9b 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.h +++ b/drivers/usb/misc/sisusbvga/sisusb.h @@ -37,24 +37,16 @@ #ifndef _SISUSB_H_ #define _SISUSB_H_ -#include #ifdef CONFIG_COMPAT -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10) -#include -#define SISUSB_OLD_CONFIG_COMPAT -#else #define SISUSB_NEW_CONFIG_COMPAT #endif -#endif /* For older kernels, support for text consoles is by default * off. To ensable text console support, change the following: */ #if 0 -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13) #define CONFIG_USB_SISUSBVGA_CON #endif -#endif /* Version Information */ -- cgit v1.2.3-59-g8ed1b From 4186ecf8ad16dd05759a09594de6a87e48759ba6 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Wed, 11 Jan 2006 15:55:29 +0100 Subject: [PATCH] USB: convert a bunch of USB semaphores to mutexes the patch below converts a bunch of semaphores-used-as-mutex in the USB code to mutexes Signed-off-by: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 23 +++--- drivers/usb/class/usblp.c | 15 ++-- drivers/usb/core/devices.c | 7 +- drivers/usb/core/hcd.c | 25 ++++--- drivers/usb/core/hcd.h | 2 +- drivers/usb/core/hub.c | 7 +- drivers/usb/core/notify.c | 15 ++-- drivers/usb/core/usb.c | 5 +- drivers/usb/image/mdc800.c | 63 ++++++++-------- drivers/usb/input/ati_remote.c | 2 - drivers/usb/media/dabusb.c | 31 ++++---- drivers/usb/media/dabusb.h | 2 +- drivers/usb/media/ov511.c | 91 +++++++++++------------ drivers/usb/media/ov511.h | 11 ++- drivers/usb/media/se401.c | 12 +-- drivers/usb/media/se401.h | 3 +- drivers/usb/media/sn9c102.h | 5 +- drivers/usb/media/sn9c102_core.c | 156 +++++++++++++++++++-------------------- drivers/usb/media/stv680.c | 13 ++-- drivers/usb/media/stv680.h | 2 +- drivers/usb/media/usbvideo.c | 28 +++---- drivers/usb/media/usbvideo.h | 5 +- drivers/usb/media/vicam.c | 21 +++--- drivers/usb/media/w9968cf.c | 75 ++++++++++--------- drivers/usb/media/w9968cf.h | 14 +--- drivers/usb/misc/idmouse.c | 25 ++++--- drivers/usb/misc/ldusb.c | 11 +-- drivers/usb/misc/legousbtower.c | 11 +-- drivers/usb/mon/mon_main.c | 19 ++--- drivers/usb/mon/mon_text.c | 21 +++--- drivers/usb/mon/usb_mon.h | 2 +- drivers/usb/storage/scsiglue.c | 9 ++- drivers/usb/storage/usb.c | 25 ++++--- drivers/usb/storage/usb.h | 5 +- 34 files changed, 389 insertions(+), 372 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 97bdeb1c2181..6dd339f4c0fc 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -80,7 +81,7 @@ static struct usb_driver acm_driver; static struct tty_driver *acm_tty_driver; static struct acm *acm_table[ACM_TTY_MINORS]; -static DECLARE_MUTEX(open_sem); +static DEFINE_MUTEX(open_mutex); #define ACM_READY(acm) (acm && acm->dev && acm->used) @@ -431,8 +432,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) int rv = -EINVAL; int i; dbg("Entering acm_tty_open.\n"); - - down(&open_sem); + + mutex_lock(&open_mutex); acm = acm_table[tty->index]; if (!acm || !acm->dev) @@ -474,14 +475,14 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) done: err_out: - up(&open_sem); + mutex_unlock(&open_mutex); return rv; full_bailout: usb_kill_urb(acm->ctrlurb); bail_out: acm->used--; - up(&open_sem); + mutex_unlock(&open_mutex); return -EIO; } @@ -507,7 +508,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) if (!acm || !acm->used) return; - down(&open_sem); + mutex_lock(&open_mutex); if (!--acm->used) { if (acm->dev) { acm_set_control(acm, acm->ctrlout = 0); @@ -518,7 +519,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) } else acm_tty_unregister(acm); } - up(&open_sem); + mutex_unlock(&open_mutex); } static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) @@ -1013,9 +1014,9 @@ static void acm_disconnect(struct usb_interface *intf) return; } - down(&open_sem); + mutex_lock(&open_mutex); if (!usb_get_intfdata(intf)) { - up(&open_sem); + mutex_unlock(&open_mutex); return; } acm->dev = NULL; @@ -1045,11 +1046,11 @@ static void acm_disconnect(struct usb_interface *intf) if (!acm->used) { acm_tty_unregister(acm); - up(&open_sem); + mutex_unlock(&open_mutex); return; } - up(&open_sem); + mutex_unlock(&open_mutex); if (acm->tty) tty_hangup(acm->tty); diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index d34848ac30b0..48dee4b8d8e5 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -55,6 +55,7 @@ #include #include #include +#include #undef DEBUG #include @@ -223,7 +224,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp); /* forward reference to make our lives easier */ static struct usb_driver usblp_driver; -static DECLARE_MUTEX(usblp_sem); /* locks the existence of usblp's */ +static DEFINE_MUTEX(usblp_mutex); /* locks the existence of usblp's */ /* * Functions for usblp control messages. @@ -351,7 +352,7 @@ static int usblp_open(struct inode *inode, struct file *file) if (minor < 0) return -ENODEV; - down (&usblp_sem); + mutex_lock (&usblp_mutex); retval = -ENODEV; intf = usb_find_interface(&usblp_driver, minor); @@ -399,7 +400,7 @@ static int usblp_open(struct inode *inode, struct file *file) } } out: - up (&usblp_sem); + mutex_unlock (&usblp_mutex); return retval; } @@ -425,13 +426,13 @@ static int usblp_release(struct inode *inode, struct file *file) { struct usblp *usblp = file->private_data; - down (&usblp_sem); + mutex_lock (&usblp_mutex); usblp->used = 0; if (usblp->present) { usblp_unlink_urbs(usblp); } else /* finish cleanup from disconnect */ usblp_cleanup (usblp); - up (&usblp_sem); + mutex_unlock (&usblp_mutex); return 0; } @@ -1152,7 +1153,7 @@ static void usblp_disconnect(struct usb_interface *intf) device_remove_file(&intf->dev, &dev_attr_ieee1284_id); - down (&usblp_sem); + mutex_lock (&usblp_mutex); down (&usblp->sem); usblp->present = 0; usb_set_intfdata (intf, NULL); @@ -1166,7 +1167,7 @@ static void usblp_disconnect(struct usb_interface *intf) if (!usblp->used) usblp_cleanup (usblp); - up (&usblp_sem); + mutex_unlock (&usblp_mutex); } static struct usb_device_id usblp_ids [] = { diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 2684e15b813b..c0f37343a276 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include "usb.h" @@ -570,7 +571,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte if (!access_ok(VERIFY_WRITE, buf, nbytes)) return -EFAULT; - down (&usb_bus_list_lock); + mutex_lock(&usb_bus_list_lock); /* print devices for all busses */ list_for_each_entry(bus, &usb_bus_list, bus_list) { /* recurse through all children of the root hub */ @@ -580,12 +581,12 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0); usb_unlock_device(bus->root_hub); if (ret < 0) { - up(&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); return ret; } total_written += ret; } - up (&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); return total_written; } diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0018bbc4de34..9223f2869674 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -93,7 +94,7 @@ struct usb_busmap { static struct usb_busmap busmap; /* used when updating list of hcds */ -DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */ +DEFINE_MUTEX(usb_bus_list_lock); /* exported only for usbfs */ EXPORT_SYMBOL_GPL (usb_bus_list_lock); /* used for controlling access to virtual root hubs */ @@ -761,14 +762,14 @@ static int usb_register_bus(struct usb_bus *bus) { int busnum; - down (&usb_bus_list_lock); + mutex_lock(&usb_bus_list_lock); busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); if (busnum < USB_MAXBUS) { set_bit (busnum, busmap.busmap); bus->busnum = busnum; } else { printk (KERN_ERR "%s: too many buses\n", usbcore_name); - up(&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); return -E2BIG; } @@ -776,7 +777,7 @@ static int usb_register_bus(struct usb_bus *bus) bus->controller, "usb_host%d", busnum); if (IS_ERR(bus->class_dev)) { clear_bit(busnum, busmap.busmap); - up(&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); return PTR_ERR(bus->class_dev); } @@ -784,7 +785,7 @@ static int usb_register_bus(struct usb_bus *bus) /* Add it to the local list of buses */ list_add (&bus->bus_list, &usb_bus_list); - up (&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); usb_notify_add_bus(bus); @@ -809,9 +810,9 @@ static void usb_deregister_bus (struct usb_bus *bus) * controller code, as well as having it call this when cleaning * itself up */ - down (&usb_bus_list_lock); + mutex_lock(&usb_bus_list_lock); list_del (&bus->bus_list); - up (&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); usb_notify_remove_bus(bus); @@ -844,14 +845,14 @@ static int register_root_hub (struct usb_device *usb_dev, set_bit (devnum, usb_dev->bus->devmap.devicemap); usb_set_device_state(usb_dev, USB_STATE_ADDRESS); - down (&usb_bus_list_lock); + mutex_lock(&usb_bus_list_lock); usb_dev->bus->root_hub = usb_dev; usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); if (retval != sizeof usb_dev->descriptor) { usb_dev->bus->root_hub = NULL; - up (&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); dev_dbg (parent_dev, "can't read %s device descriptor %d\n", usb_dev->dev.bus_id, retval); return (retval < 0) ? retval : -EMSGSIZE; @@ -863,7 +864,7 @@ static int register_root_hub (struct usb_device *usb_dev, dev_err (parent_dev, "can't register root hub for %s, %d\n", usb_dev->dev.bus_id, retval); } - up (&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); if (retval == 0) { spin_lock_irq (&hcd_root_hub_lock); @@ -1891,9 +1892,9 @@ void usb_remove_hcd(struct usb_hcd *hcd) hcd->rh_registered = 0; spin_unlock_irq (&hcd_root_hub_lock); - down(&usb_bus_list_lock); + mutex_lock(&usb_bus_list_lock); usb_disconnect(&hcd->self.root_hub); - up(&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); hcd->poll_rh = 0; del_timer_sync(&hcd->rh_timer); diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 591b5aad1a18..f44a2fe62a9d 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -364,7 +364,7 @@ extern void usb_set_device_state(struct usb_device *udev, /* exported only within usbcore */ extern struct list_head usb_bus_list; -extern struct semaphore usb_bus_list_lock; +extern struct mutex usb_bus_list_lock; extern wait_queue_head_t usb_kill_urb_queue; extern struct usb_bus *usb_bus_get (struct usb_bus *bus); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 650d5ee5871b..867fa8130238 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -2162,7 +2163,7 @@ static int hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, int retry_counter) { - static DECLARE_MUTEX(usb_address0_sem); + static DEFINE_MUTEX(usb_address0_mutex); struct usb_device *hdev = hub->hdev; int i, j, retval; @@ -2183,7 +2184,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, if (oldspeed == USB_SPEED_LOW) delay = HUB_LONG_RESET_TIME; - down(&usb_address0_sem); + mutex_lock(&usb_address0_mutex); /* Reset the device; full speed may morph to high speed */ retval = hub_port_reset(hub, port1, udev, delay); @@ -2381,7 +2382,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, fail: if (retval) hub_port_disable(hub, port1, 0); - up(&usb_address0_sem); + mutex_unlock(&usb_address0_mutex); return retval; } diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index fbbebab52fbd..4b55285de9a0 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c @@ -13,16 +13,17 @@ #include #include #include +#include #include "usb.h" static struct notifier_block *usb_notifier_list; -static DECLARE_MUTEX(usb_notifier_lock); +static DEFINE_MUTEX(usb_notifier_lock); static void usb_notifier_chain_register(struct notifier_block **list, struct notifier_block *n) { - down(&usb_notifier_lock); + mutex_lock(&usb_notifier_lock); while (*list) { if (n->priority > (*list)->priority) break; @@ -30,13 +31,13 @@ static void usb_notifier_chain_register(struct notifier_block **list, } n->next = *list; *list = n; - up(&usb_notifier_lock); + mutex_unlock(&usb_notifier_lock); } static void usb_notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n) { - down(&usb_notifier_lock); + mutex_lock(&usb_notifier_lock); while ((*nl)!=NULL) { if ((*nl)==n) { *nl = n->next; @@ -45,7 +46,7 @@ static void usb_notifier_chain_unregister(struct notifier_block **nl, nl=&((*nl)->next); } exit: - up(&usb_notifier_lock); + mutex_unlock(&usb_notifier_lock); } static int usb_notifier_call_chain(struct notifier_block **n, @@ -54,7 +55,7 @@ static int usb_notifier_call_chain(struct notifier_block **n, int ret=NOTIFY_DONE; struct notifier_block *nb = *n; - down(&usb_notifier_lock); + mutex_lock(&usb_notifier_lock); while (nb) { ret = nb->notifier_call(nb,val,v); if (ret&NOTIFY_STOP_MASK) { @@ -63,7 +64,7 @@ static int usb_notifier_call_chain(struct notifier_block **n, nb = nb->next; } exit: - up(&usb_notifier_lock); + mutex_unlock(&usb_notifier_lock); return ret; } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 13d1d367f7f1..d7352aa73b5e 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -639,7 +640,7 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id) struct usb_bus *bus; struct usb_device *dev = NULL; - down(&usb_bus_list_lock); + mutex_lock(&usb_bus_list_lock); for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) { @@ -653,7 +654,7 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id) goto exit; } exit: - up(&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); return dev; } diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 4e3e4d048c14..08daf400f985 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -96,6 +96,7 @@ #include #include #include +#include #include #include @@ -169,7 +170,7 @@ struct mdc800_data int out_count; // Bytes in the buffer int open; // Camera device open ? - struct semaphore io_lock; // IO -lock + struct mutex io_lock; // IO -lock char in [8]; // Command Input Buffer int in_count; @@ -497,7 +498,7 @@ static int mdc800_usb_probe (struct usb_interface *intf, info ("Found Mustek MDC800 on USB."); - down (&mdc800->io_lock); + mutex_lock(&mdc800->io_lock); retval = usb_register_dev(intf, &mdc800_class); if (retval) { @@ -542,7 +543,7 @@ static int mdc800_usb_probe (struct usb_interface *intf, mdc800->state=READY; - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); usb_set_intfdata(intf, mdc800); return 0; @@ -620,7 +621,7 @@ static int mdc800_device_open (struct inode* inode, struct file *file) int retval=0; int errn=0; - down (&mdc800->io_lock); + mutex_lock(&mdc800->io_lock); if (mdc800->state == NOT_CONNECTED) { @@ -656,7 +657,7 @@ static int mdc800_device_open (struct inode* inode, struct file *file) dbg ("Mustek MDC800 device opened."); error_out: - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return errn; } @@ -669,7 +670,7 @@ static int mdc800_device_release (struct inode* inode, struct file *file) int retval=0; dbg ("Mustek MDC800 device closed."); - down (&mdc800->io_lock); + mutex_lock(&mdc800->io_lock); if (mdc800->open && (mdc800->state != NOT_CONNECTED)) { usb_kill_urb(mdc800->irq_urb); @@ -682,7 +683,7 @@ static int mdc800_device_release (struct inode* inode, struct file *file) retval=-EIO; } - up(&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return retval; } @@ -695,21 +696,21 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l size_t left=len, sts=len; /* single transfer size */ char __user *ptr = buf; - down (&mdc800->io_lock); + mutex_lock(&mdc800->io_lock); if (mdc800->state == NOT_CONNECTED) { - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EBUSY; } if (mdc800->state == WORKING) { warn ("Illegal State \"working\" reached during read ?!"); - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EBUSY; } if (!mdc800->open) { - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EBUSY; } @@ -717,7 +718,7 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l { if (signal_pending (current)) { - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EINTR; } @@ -736,7 +737,7 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL)) { err ("Can't submit download urb (status=%i)",mdc800->download_urb->status); - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return len-left; } wait_event_timeout(mdc800->download_wait, mdc800->downloaded, @@ -745,14 +746,14 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l if (mdc800->download_urb->status != 0) { err ("request download-bytes fails (status=%i)",mdc800->download_urb->status); - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return len-left; } } else { /* No more bytes -> that's an error*/ - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EIO; } } @@ -761,7 +762,7 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l /* Copy Bytes */ if (copy_to_user(ptr, &mdc800->out [mdc800->out_ptr], sts)) { - up(&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EFAULT; } ptr+=sts; @@ -770,7 +771,7 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l } } - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return len-left; } @@ -785,15 +786,15 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s { size_t i=0; - down (&mdc800->io_lock); + mutex_lock(&mdc800->io_lock); if (mdc800->state != READY) { - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EBUSY; } if (!mdc800->open ) { - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EBUSY; } @@ -802,13 +803,13 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s unsigned char c; if (signal_pending (current)) { - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EINTR; } if(get_user(c, buf+i)) { - up(&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EFAULT; } @@ -829,7 +830,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s } else { - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EIO; } @@ -841,7 +842,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s if (mdc800_usb_waitForIRQ (0,TO_GET_READY)) { err ("Camera didn't get ready.\n"); - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EIO; } @@ -853,7 +854,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL)) { err ("submitting write urb fails (status=%i)", mdc800->write_urb->status); - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EIO; } wait_event_timeout(mdc800->write_wait, mdc800->written, TO_WRITE_GET_READY*HZ/1000); @@ -861,7 +862,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s if (mdc800->state == WORKING) { usb_kill_urb(mdc800->write_urb); - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EIO; } @@ -873,7 +874,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s { err ("call 0x07 before 0x05,0x3e"); mdc800->state=READY; - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EIO; } mdc800->pic_len=-1; @@ -892,7 +893,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ)) { err ("requesting answer from irq fails"); - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EIO; } @@ -920,7 +921,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND)) { err ("Command Timeout."); - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return -EIO; } } @@ -930,7 +931,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s } i++; } - up (&mdc800->io_lock); + mutex_unlock(&mdc800->io_lock); return i; } @@ -984,7 +985,7 @@ static int __init usb_mdc800_init (void) mdc800->dev = NULL; mdc800->state=NOT_CONNECTED; - init_MUTEX (&mdc800->io_lock); + mutex_init (&mdc800->io_lock); init_waitqueue_head (&mdc800->irq_wait); init_waitqueue_head (&mdc800->write_wait); diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index f7bdc506e613..99f986cb6e95 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -159,8 +159,6 @@ static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; */ #define FILTER_TIME (HZ / 20) -static DECLARE_MUTEX(disconnect_sem); - struct ati_remote { struct input_dev *idev; struct usb_device *udev; diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c index 6f560fe9a519..1774ab7a40d2 100644 --- a/drivers/usb/media/dabusb.c +++ b/drivers/usb/media/dabusb.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "dabusb.h" #include "dabfirmware.h" @@ -570,7 +571,7 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l s->readptr = 0; } } - err: //up(&s->mutex); + err: //mutex_unlock(&s->mutex); return ret; } @@ -585,10 +586,10 @@ static int dabusb_open (struct inode *inode, struct file *file) s = &dabusb[devnum - DABUSB_MINOR]; dbg("dabusb_open"); - down (&s->mutex); + mutex_lock(&s->mutex); while (!s->usbdev || s->opened) { - up (&s->mutex); + mutex_unlock(&s->mutex); if (file->f_flags & O_NONBLOCK) { return -EBUSY; @@ -598,15 +599,15 @@ static int dabusb_open (struct inode *inode, struct file *file) if (signal_pending (current)) { return -EAGAIN; } - down (&s->mutex); + mutex_lock(&s->mutex); } if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { - up(&s->mutex); + mutex_unlock(&s->mutex); err("set_interface failed"); return -EINVAL; } s->opened = 1; - up (&s->mutex); + mutex_unlock(&s->mutex); file->f_pos = 0; file->private_data = s; @@ -620,10 +621,10 @@ static int dabusb_release (struct inode *inode, struct file *file) dbg("dabusb_release"); - down (&s->mutex); + mutex_lock(&s->mutex); dabusb_stop (s); dabusb_free_buffers (s); - up (&s->mutex); + mutex_unlock(&s->mutex); if (!s->remove_pending) { if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) @@ -648,10 +649,10 @@ static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cm if (s->remove_pending) return -EIO; - down (&s->mutex); + mutex_lock(&s->mutex); if (!s->usbdev) { - up (&s->mutex); + mutex_unlock(&s->mutex); return -EIO; } @@ -691,7 +692,7 @@ static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cm ret = -ENOIOCTLCMD; break; } - up (&s->mutex); + mutex_unlock(&s->mutex); return ret; } @@ -737,7 +738,7 @@ static int dabusb_probe (struct usb_interface *intf, s = &dabusb[intf->minor]; - down (&s->mutex); + mutex_lock(&s->mutex); s->remove_pending = 0; s->usbdev = usbdev; s->devnum = intf->minor; @@ -760,7 +761,7 @@ static int dabusb_probe (struct usb_interface *intf, } dbg("bound to interface: %d", intf->altsetting->desc.bInterfaceNumber); usb_set_intfdata (intf, s); - up (&s->mutex); + mutex_unlock(&s->mutex); retval = usb_register_dev(intf, &dabusb_class); if (retval) { @@ -771,7 +772,7 @@ static int dabusb_probe (struct usb_interface *intf, return 0; reject: - up (&s->mutex); + mutex_unlock(&s->mutex); s->usbdev = NULL; return -ENODEV; } @@ -828,7 +829,7 @@ static int __init dabusb_init (void) for (u = 0; u < NRDABUSB; u++) { pdabusb_t s = &dabusb[u]; memset (s, 0, sizeof (dabusb_t)); - init_MUTEX (&s->mutex); + mutex_init (&s->mutex); s->usbdev = NULL; s->total_buffer_size = buffers; init_waitqueue_head (&s->wait); diff --git a/drivers/usb/media/dabusb.h b/drivers/usb/media/dabusb.h index 10b666e43abc..96b03e4af8b9 100644 --- a/drivers/usb/media/dabusb.h +++ b/drivers/usb/media/dabusb.h @@ -18,7 +18,7 @@ typedef enum { _stopped=0, _started } driver_state_t; typedef struct { - struct semaphore mutex; + struct mutex mutex; struct usb_device *usbdev; wait_queue_head_t wait; wait_queue_head_t remove_ok; diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c index 51e9cc06f7e3..cfec8c61574e 100644 --- a/drivers/usb/media/ov511.c +++ b/drivers/usb/media/ov511.c @@ -365,14 +365,14 @@ reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value) PDEBUG(5, "0x%02X:0x%02X", reg, value); - down(&ov->cbuf_lock); + mutex_lock(&ov->cbuf_lock); ov->cbuf[0] = value; rc = usb_control_msg(ov->dev, usb_sndctrlpipe(ov->dev, 0), (ov->bclass == BCL_OV518)?1:2 /* REG_IO */, USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, (__u16)reg, &ov->cbuf[0], 1, 1000); - up(&ov->cbuf_lock); + mutex_unlock(&ov->cbuf_lock); if (rc < 0) err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc)); @@ -387,7 +387,7 @@ reg_r(struct usb_ov511 *ov, unsigned char reg) { int rc; - down(&ov->cbuf_lock); + mutex_lock(&ov->cbuf_lock); rc = usb_control_msg(ov->dev, usb_rcvctrlpipe(ov->dev, 0), (ov->bclass == BCL_OV518)?1:3 /* REG_IO */, @@ -401,7 +401,7 @@ reg_r(struct usb_ov511 *ov, unsigned char reg) PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]); } - up(&ov->cbuf_lock); + mutex_unlock(&ov->cbuf_lock); return rc; } @@ -444,7 +444,7 @@ ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n) PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n); - down(&ov->cbuf_lock); + mutex_lock(&ov->cbuf_lock); *((__le32 *)ov->cbuf) = __cpu_to_le32(val); @@ -453,7 +453,7 @@ ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n) 1 /* REG_IO */, USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, (__u16)reg, ov->cbuf, n, 1000); - up(&ov->cbuf_lock); + mutex_unlock(&ov->cbuf_lock); if (rc < 0) err("reg write multiple: error %d: %s", rc, @@ -768,14 +768,14 @@ i2c_r(struct usb_ov511 *ov, unsigned char reg) { int rc; - down(&ov->i2c_lock); + mutex_lock(&ov->i2c_lock); if (ov->bclass == BCL_OV518) rc = ov518_i2c_read_internal(ov, reg); else rc = ov511_i2c_read_internal(ov, reg); - up(&ov->i2c_lock); + mutex_unlock(&ov->i2c_lock); return rc; } @@ -785,14 +785,14 @@ i2c_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value) { int rc; - down(&ov->i2c_lock); + mutex_lock(&ov->i2c_lock); if (ov->bclass == BCL_OV518) rc = ov518_i2c_write_internal(ov, reg, value); else rc = ov511_i2c_write_internal(ov, reg, value); - up(&ov->i2c_lock); + mutex_unlock(&ov->i2c_lock); return rc; } @@ -842,9 +842,9 @@ i2c_w_mask(struct usb_ov511 *ov, { int rc; - down(&ov->i2c_lock); + mutex_lock(&ov->i2c_lock); rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask); - up(&ov->i2c_lock); + mutex_unlock(&ov->i2c_lock); return rc; } @@ -880,7 +880,7 @@ i2c_w_slave(struct usb_ov511 *ov, { int rc = 0; - down(&ov->i2c_lock); + mutex_lock(&ov->i2c_lock); /* Set new slave IDs */ rc = i2c_set_slave_internal(ov, slave); @@ -894,7 +894,7 @@ out: if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) err("Couldn't restore primary I2C slave"); - up(&ov->i2c_lock); + mutex_unlock(&ov->i2c_lock); return rc; } @@ -906,7 +906,7 @@ i2c_r_slave(struct usb_ov511 *ov, { int rc; - down(&ov->i2c_lock); + mutex_lock(&ov->i2c_lock); /* Set new slave IDs */ rc = i2c_set_slave_internal(ov, slave); @@ -923,7 +923,7 @@ out: if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) err("Couldn't restore primary I2C slave"); - up(&ov->i2c_lock); + mutex_unlock(&ov->i2c_lock); return rc; } @@ -933,7 +933,7 @@ ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid) { int rc; - down(&ov->i2c_lock); + mutex_lock(&ov->i2c_lock); rc = i2c_set_slave_internal(ov, sid); if (rc < 0) @@ -942,7 +942,7 @@ ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid) // FIXME: Is this actually necessary? rc = ov51x_reset(ov, OV511_RESET_NOREGS); out: - up(&ov->i2c_lock); + mutex_unlock(&ov->i2c_lock); return rc; } @@ -3832,7 +3832,7 @@ ov51x_alloc(struct usb_ov511 *ov) const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h); PDEBUG(4, "entered"); - down(&ov->buf_lock); + mutex_lock(&ov->buf_lock); if (ov->buf_state == BUF_ALLOCATED) goto out; @@ -3879,12 +3879,12 @@ ov51x_alloc(struct usb_ov511 *ov) ov->buf_state = BUF_ALLOCATED; out: - up(&ov->buf_lock); + mutex_unlock(&ov->buf_lock); PDEBUG(4, "leaving"); return 0; error: ov51x_do_dealloc(ov); - up(&ov->buf_lock); + mutex_unlock(&ov->buf_lock); PDEBUG(4, "errored"); return -ENOMEM; } @@ -3893,9 +3893,9 @@ static void ov51x_dealloc(struct usb_ov511 *ov) { PDEBUG(4, "entered"); - down(&ov->buf_lock); + mutex_lock(&ov->buf_lock); ov51x_do_dealloc(ov); - up(&ov->buf_lock); + mutex_unlock(&ov->buf_lock); PDEBUG(4, "leaving"); } @@ -3914,7 +3914,7 @@ ov51x_v4l1_open(struct inode *inode, struct file *file) PDEBUG(4, "opening"); - down(&ov->lock); + mutex_lock(&ov->lock); err = -EBUSY; if (ov->user) @@ -3958,7 +3958,7 @@ ov51x_v4l1_open(struct inode *inode, struct file *file) ov51x_led_control(ov, 1); out: - up(&ov->lock); + mutex_unlock(&ov->lock); return err; } @@ -3970,7 +3970,7 @@ ov51x_v4l1_close(struct inode *inode, struct file *file) PDEBUG(4, "ov511_close"); - down(&ov->lock); + mutex_lock(&ov->lock); ov->user--; ov51x_stop_isoc(ov); @@ -3981,15 +3981,15 @@ ov51x_v4l1_close(struct inode *inode, struct file *file) if (ov->dev) ov51x_dealloc(ov); - up(&ov->lock); + mutex_unlock(&ov->lock); /* Device unplugged while open. Only a minimum of unregistration is done * here; the disconnect callback already did the rest. */ if (!ov->dev) { - down(&ov->cbuf_lock); + mutex_lock(&ov->cbuf_lock); kfree(ov->cbuf); ov->cbuf = NULL; - up(&ov->cbuf_lock); + mutex_unlock(&ov->cbuf_lock); ov51x_dealloc(ov); kfree(ov); @@ -4449,12 +4449,12 @@ ov51x_v4l1_ioctl(struct inode *inode, struct file *file, struct usb_ov511 *ov = video_get_drvdata(vdev); int rc; - if (down_interruptible(&ov->lock)) + if (mutex_lock_interruptible(&ov->lock)) return -EINTR; rc = video_usercopy(inode, file, cmd, arg, ov51x_v4l1_ioctl_internal); - up(&ov->lock); + mutex_unlock(&ov->lock); return rc; } @@ -4468,7 +4468,7 @@ ov51x_v4l1_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos) int i, rc = 0, frmx = -1; struct ov511_frame *frame; - if (down_interruptible(&ov->lock)) + if (mutex_lock_interruptible(&ov->lock)) return -EINTR; PDEBUG(4, "%ld bytes, noblock=%d", count, noblock); @@ -4604,11 +4604,11 @@ restart: PDEBUG(4, "read finished, returning %ld (sweet)", count); - up(&ov->lock); + mutex_unlock(&ov->lock); return count; error: - up(&ov->lock); + mutex_unlock(&ov->lock); return rc; } @@ -4631,14 +4631,14 @@ ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))) return -EINVAL; - if (down_interruptible(&ov->lock)) + if (mutex_lock_interruptible(&ov->lock)) return -EINTR; pos = (unsigned long)ov->fbuf; while (size > 0) { page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - up(&ov->lock); + mutex_unlock(&ov->lock); return -EAGAIN; } start += PAGE_SIZE; @@ -4649,7 +4649,7 @@ ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma) size = 0; } - up(&ov->lock); + mutex_unlock(&ov->lock); return 0; } @@ -5738,11 +5738,10 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) init_waitqueue_head(&ov->wq); - init_MUTEX(&ov->lock); /* to 1 == available */ - init_MUTEX(&ov->buf_lock); - init_MUTEX(&ov->param_lock); - init_MUTEX(&ov->i2c_lock); - init_MUTEX(&ov->cbuf_lock); + mutex_init(&ov->lock); /* to 1 == available */ + mutex_init(&ov->buf_lock); + mutex_init(&ov->i2c_lock); + mutex_init(&ov->cbuf_lock); ov->buf_state = BUF_NOT_ALLOCATED; @@ -5833,10 +5832,10 @@ error: } if (ov->cbuf) { - down(&ov->cbuf_lock); + mutex_lock(&ov->cbuf_lock); kfree(ov->cbuf); ov->cbuf = NULL; - up(&ov->cbuf_lock); + mutex_unlock(&ov->cbuf_lock); } kfree(ov); @@ -5881,10 +5880,10 @@ ov51x_disconnect(struct usb_interface *intf) /* Free the memory */ if (ov && !ov->user) { - down(&ov->cbuf_lock); + mutex_lock(&ov->cbuf_lock); kfree(ov->cbuf); ov->cbuf = NULL; - up(&ov->cbuf_lock); + mutex_unlock(&ov->cbuf_lock); ov51x_dealloc(ov); kfree(ov); diff --git a/drivers/usb/media/ov511.h b/drivers/usb/media/ov511.h index 086509a137c6..bce9b3633889 100644 --- a/drivers/usb/media/ov511.h +++ b/drivers/usb/media/ov511.h @@ -5,6 +5,7 @@ #include #include #include +#include #define OV511_DEBUG /* Turn on debug messages */ @@ -435,7 +436,7 @@ struct usb_ov511 { int led_policy; /* LED: off|on|auto; OV511+ only */ - struct semaphore lock; /* Serializes user-accessible operations */ + struct mutex lock; /* Serializes user-accessible operations */ int user; /* user count for exclusive use */ int streaming; /* Are we streaming Isochronous? */ @@ -473,11 +474,9 @@ struct usb_ov511 { int packet_size; /* Frame size per isoc desc */ int packet_numbering; /* Is ISO frame numbering enabled? */ - struct semaphore param_lock; /* params lock for this camera */ - /* Framebuffer/sbuf management */ int buf_state; - struct semaphore buf_lock; + struct mutex buf_lock; struct ov51x_decomp_ops *decomp_ops; @@ -494,12 +493,12 @@ struct usb_ov511 { int pal; /* Device is designed for PAL resolution */ /* I2C interface */ - struct semaphore i2c_lock; /* Protect I2C controller regs */ + struct mutex i2c_lock; /* Protect I2C controller regs */ unsigned char primary_i2c_slave; /* I2C write id of sensor */ /* Control transaction stuff */ unsigned char *cbuf; /* Buffer for payload */ - struct semaphore cbuf_lock; + struct mutex cbuf_lock; }; /* Used to represent a list of values and their respective symbolic names */ diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c index 2ba562285fda..8c3b1ad8a8fd 100644 --- a/drivers/usb/media/se401.c +++ b/drivers/usb/media/se401.c @@ -1157,21 +1157,21 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma) unsigned long size = vma->vm_end-vma->vm_start; unsigned long page, pos; - down(&se401->lock); + mutex_lock(&se401->lock); if (se401->dev == NULL) { - up(&se401->lock); + mutex_unlock(&se401->lock); return -EIO; } if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { - up(&se401->lock); + mutex_unlock(&se401->lock); return -EINVAL; } pos = (unsigned long)se401->fbuf; while (size > 0) { page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - up(&se401->lock); + mutex_unlock(&se401->lock); return -EAGAIN; } start += PAGE_SIZE; @@ -1181,7 +1181,7 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma) else size = 0; } - up(&se401->lock); + mutex_unlock(&se401->lock); return 0; } @@ -1366,7 +1366,7 @@ static int se401_probe(struct usb_interface *intf, memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name)); init_waitqueue_head(&se401->wq); - init_MUTEX(&se401->lock); + mutex_init(&se401->lock); wmb(); if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { diff --git a/drivers/usb/media/se401.h b/drivers/usb/media/se401.h index 2e5846f1eb20..e88a40d4c86a 100644 --- a/drivers/usb/media/se401.h +++ b/drivers/usb/media/se401.h @@ -5,6 +5,7 @@ #include #include #include +#include #define se401_DEBUG /* Turn on debug messages */ @@ -189,7 +190,7 @@ struct usb_se401 { int maxframesize; int cframesize; /* current framesize */ - struct semaphore lock; + struct mutex lock; int user; /* user count for exclusive use */ int removed; /* device disconnected */ diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h index 17d60c1eea7e..59e44be27cb4 100644 --- a/drivers/usb/media/sn9c102.h +++ b/drivers/usb/media/sn9c102.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "sn9c102_sensor.h" @@ -109,7 +110,7 @@ struct sn9c102_module_param { u8 force_munmap; }; -static DECLARE_MUTEX(sn9c102_sysfs_lock); +static DEFINE_MUTEX(sn9c102_sysfs_lock); static DECLARE_RWSEM(sn9c102_disconnect); struct sn9c102_device { @@ -141,7 +142,7 @@ struct sn9c102_device { enum sn9c102_dev_state state; u8 users; - struct semaphore dev_sem, fileop_sem; + struct mutex dev_mutex, fileop_mutex; spinlock_t queue_lock; wait_queue_head_t open, wait_frame, wait_stream; }; diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c index c81397e4714b..30119080871b 100644 --- a/drivers/usb/media/sn9c102_core.c +++ b/drivers/usb/media/sn9c102_core.c @@ -866,18 +866,18 @@ static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf) struct sn9c102_device* cam; ssize_t count; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } count = sprintf(buf, "%u\n", cam->sysfs.reg); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -890,18 +890,18 @@ sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) u8 index; ssize_t count; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } index = sn9c102_strtou8(buf, len, &count); if (index > 0x1f || !count) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EINVAL; } @@ -910,7 +910,7 @@ sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg); DBG(3, "Written bytes: %zd", count); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -922,17 +922,17 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) ssize_t count; int val; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EIO; } @@ -940,7 +940,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) DBG(3, "Read bytes: %zd", count); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -954,24 +954,24 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) ssize_t count; int err; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } value = sn9c102_strtou8(buf, len, &count); if (!count) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EINVAL; } err = sn9c102_write_reg(cam, value, cam->sysfs.reg); if (err) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EIO; } @@ -979,7 +979,7 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) cam->sysfs.reg, value); DBG(3, "Written bytes: %zd", count); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -990,12 +990,12 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf) struct sn9c102_device* cam; ssize_t count; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } @@ -1003,7 +1003,7 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf) DBG(3, "Read bytes: %zd", count); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -1016,18 +1016,18 @@ sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) u8 index; ssize_t count; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } index = sn9c102_strtou8(buf, len, &count); if (!count) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EINVAL; } @@ -1036,7 +1036,7 @@ sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); DBG(3, "Written bytes: %zd", count); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -1048,22 +1048,22 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) ssize_t count; int val; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } if (!(cam->sensor->sysfs_ops & SN9C102_I2C_READ)) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENOSYS; } if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EIO; } @@ -1071,7 +1071,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) DBG(3, "Read bytes: %zd", count); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -1085,29 +1085,29 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) ssize_t count; int err; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } if (!(cam->sensor->sysfs_ops & SN9C102_I2C_WRITE)) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENOSYS; } value = sn9c102_strtou8(buf, len, &count); if (!count) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EINVAL; } err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value); if (err) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EIO; } @@ -1115,7 +1115,7 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) cam->sysfs.i2c_reg, value); DBG(3, "Written bytes: %zd", count); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -1130,18 +1130,18 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) u8 value; ssize_t count; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } bridge = cam->bridge; - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); value = sn9c102_strtou8(buf, len, &count); if (!count) @@ -1404,7 +1404,7 @@ static int sn9c102_init(struct sn9c102_device* cam) } if (!(cam->state & DEV_INITIALIZED)) { - init_MUTEX(&cam->fileop_sem); + mutex_init(&cam->fileop_mutex); spin_lock_init(&cam->queue_lock); init_waitqueue_head(&cam->wait_frame); init_waitqueue_head(&cam->wait_stream); @@ -1422,13 +1422,13 @@ static int sn9c102_init(struct sn9c102_device* cam) static void sn9c102_release_resources(struct sn9c102_device* cam) { - down(&sn9c102_sysfs_lock); + mutex_lock(&sn9c102_sysfs_lock); DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); kfree(cam->control_buffer); } @@ -1449,7 +1449,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) cam = video_get_drvdata(video_devdata(filp)); - if (down_interruptible(&cam->dev_sem)) { + if (mutex_lock_interruptible(&cam->dev_mutex)) { up_read(&sn9c102_disconnect); return -ERESTARTSYS; } @@ -1461,7 +1461,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) err = -EWOULDBLOCK; goto out; } - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); err = wait_event_interruptible_exclusive(cam->open, cam->state & DEV_DISCONNECTED || !cam->users); @@ -1473,7 +1473,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) up_read(&sn9c102_disconnect); return -ENODEV; } - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); } @@ -1501,7 +1501,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); out: - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); up_read(&sn9c102_disconnect); return err; } @@ -1511,7 +1511,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) { struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); - down(&cam->dev_sem); /* prevent disconnect() to be called */ + mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ sn9c102_stop_transfer(cam); @@ -1519,7 +1519,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) if (cam->state & DEV_DISCONNECTED) { sn9c102_release_resources(cam); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); kfree(cam); return 0; } @@ -1529,7 +1529,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); return 0; } @@ -1543,33 +1543,33 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) unsigned long lock_flags; int err = 0; - if (down_interruptible(&cam->fileop_sem)) + if (mutex_lock_interruptible(&cam->fileop_mutex)) return -ERESTARTSYS; if (cam->state & DEV_DISCONNECTED) { DBG(1, "Device not present"); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENODEV; } if (cam->state & DEV_MISCONFIGURED) { DBG(1, "The camera is misconfigured. Close and open it " "again."); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EIO; } if (cam->io == IO_MMAP) { DBG(3, "Close and open the device again to choose " "the read method"); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EINVAL; } if (cam->io == IO_NONE) { if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) { DBG(1, "read() failed, not enough memory"); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENOMEM; } cam->io = IO_READ; @@ -1583,13 +1583,13 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) } if (!count) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return 0; } if (list_empty(&cam->outqueue)) { if (filp->f_flags & O_NONBLOCK) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EAGAIN; } err = wait_event_interruptible @@ -1598,15 +1598,15 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) (cam->state & DEV_DISCONNECTED) || (cam->state & DEV_MISCONFIGURED) ); if (err) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return err; } if (cam->state & DEV_DISCONNECTED) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENODEV; } if (cam->state & DEV_MISCONFIGURED) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EIO; } } @@ -1634,7 +1634,7 @@ exit: PDBGG("Frame #%lu, bytes read: %zu", (unsigned long)f->buf.index, count); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return count; } @@ -1647,7 +1647,7 @@ static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) unsigned long lock_flags; unsigned int mask = 0; - if (down_interruptible(&cam->fileop_sem)) + if (mutex_lock_interruptible(&cam->fileop_mutex)) return POLLERR; if (cam->state & DEV_DISCONNECTED) { @@ -1685,12 +1685,12 @@ static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) if (!list_empty(&cam->outqueue)) mask |= POLLIN | POLLRDNORM; - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return mask; error: - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return POLLERR; } @@ -1724,25 +1724,25 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) void *pos; u32 i; - if (down_interruptible(&cam->fileop_sem)) + if (mutex_lock_interruptible(&cam->fileop_mutex)) return -ERESTARTSYS; if (cam->state & DEV_DISCONNECTED) { DBG(1, "Device not present"); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENODEV; } if (cam->state & DEV_MISCONFIGURED) { DBG(1, "The camera is misconfigured. Close and open it " "again."); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EIO; } if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || size != PAGE_ALIGN(cam->frame[0].buf.length)) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EINVAL; } @@ -1751,7 +1751,7 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) break; } if (i == cam->nbuffers) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EINVAL; } @@ -1761,7 +1761,7 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) pos = cam->frame[i].bufmem; while (size > 0) { /* size is page-aligned */ if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EAGAIN; } start += PAGE_SIZE; @@ -1774,7 +1774,7 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) sn9c102_vm_open(vma); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return 0; } @@ -2655,19 +2655,19 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp, struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); int err = 0; - if (down_interruptible(&cam->fileop_sem)) + if (mutex_lock_interruptible(&cam->fileop_mutex)) return -ERESTARTSYS; if (cam->state & DEV_DISCONNECTED) { DBG(1, "Device not present"); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENODEV; } if (cam->state & DEV_MISCONFIGURED) { DBG(1, "The camera is misconfigured. Close and open it " "again."); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EIO; } @@ -2675,7 +2675,7 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp, err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return err; } @@ -2722,7 +2722,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - init_MUTEX(&cam->dev_sem); + mutex_init(&cam->dev_mutex); r = sn9c102_read_reg(cam, 0x00); if (r < 0 || r != 0x10) { @@ -2776,7 +2776,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->v4ldev->release = video_device_release; video_set_drvdata(cam->v4ldev, cam); - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, video_nr[dev_nr]); @@ -2786,7 +2786,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) DBG(1, "Free /dev/videoX node not found"); video_nr[dev_nr] = -1; dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); goto fail; } @@ -2803,7 +2803,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) usb_set_intfdata(intf, cam); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); return 0; @@ -2827,7 +2827,7 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf) down_write(&sn9c102_disconnect); - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); DBG(2, "Disconnecting %s...", cam->v4ldev->name); @@ -2847,7 +2847,7 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf) sn9c102_release_resources(cam); } - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); if (!cam->users) kfree(cam); diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c index b497a6a0a206..b1a6be2958ed 100644 --- a/drivers/usb/media/stv680.c +++ b/drivers/usb/media/stv680.c @@ -67,6 +67,7 @@ #include #include #include +#include #include "stv680.h" @@ -1258,22 +1259,22 @@ static int stv680_mmap (struct file *file, struct vm_area_struct *vma) unsigned long size = vma->vm_end-vma->vm_start; unsigned long page, pos; - down (&stv680->lock); + mutex_lock(&stv680->lock); if (stv680->udev == NULL) { - up (&stv680->lock); + mutex_unlock(&stv680->lock); return -EIO; } if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { - up (&stv680->lock); + mutex_unlock(&stv680->lock); return -EINVAL; } pos = (unsigned long) stv680->fbuf; while (size > 0) { page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - up (&stv680->lock); + mutex_unlock(&stv680->lock); return -EAGAIN; } start += PAGE_SIZE; @@ -1283,7 +1284,7 @@ static int stv680_mmap (struct file *file, struct vm_area_struct *vma) else size = 0; } - up (&stv680->lock); + mutex_unlock(&stv680->lock); return 0; } @@ -1409,7 +1410,7 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id memcpy (stv680->vdev->name, stv680->camera_name, strlen (stv680->camera_name)); init_waitqueue_head (&stv680->wq); - init_MUTEX (&stv680->lock); + mutex_init (&stv680->lock); wmb (); if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { diff --git a/drivers/usb/media/stv680.h b/drivers/usb/media/stv680.h index b0551cdb280b..ea46e0001e6d 100644 --- a/drivers/usb/media/stv680.h +++ b/drivers/usb/media/stv680.h @@ -118,7 +118,7 @@ struct usb_stv { int origGain; int origMode; /* original camera mode */ - struct semaphore lock; /* to lock the structure */ + struct mutex lock; /* to lock the structure */ int user; /* user count for exclusive use */ int removed; /* device disconnected */ int streaming; /* Are we streaming video? */ diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c index 63d279ec722b..0b51fae720a9 100644 --- a/drivers/usb/media/usbvideo.c +++ b/drivers/usb/media/usbvideo.c @@ -714,7 +714,7 @@ int usbvideo_register( cams->md_module = md; if (cams->md_module == NULL) warn("%s: module == NULL!", __FUNCTION__); - init_MUTEX(&cams->lock); /* to 1 == available */ + mutex_init(&cams->lock); /* to 1 == available */ for (i = 0; i < num_cams; i++) { struct uvd *up = &cams->cam[i]; @@ -862,7 +862,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf) if (uvd->debug > 0) info("%s(%p.)", __FUNCTION__, intf); - down(&uvd->lock); + mutex_lock(&uvd->lock); uvd->remove_pending = 1; /* Now all ISO data will be ignored */ /* At this time we ask to cancel outstanding URBs */ @@ -882,7 +882,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf) info("%s: In use, disconnect pending.", __FUNCTION__); else usbvideo_CameraRelease(uvd); - up(&uvd->lock); + mutex_unlock(&uvd->lock); info("USB camera disconnected."); usbvideo_ClientDecModCount(uvd); @@ -929,19 +929,19 @@ static int usbvideo_find_struct(struct usbvideo *cams) err("No usbvideo handle?"); return -1; } - down(&cams->lock); + mutex_lock(&cams->lock); for (u = 0; u < cams->num_cameras; u++) { struct uvd *uvd = &cams->cam[u]; if (!uvd->uvd_used) /* This one is free */ { uvd->uvd_used = 1; /* In use now */ - init_MUTEX(&uvd->lock); /* to 1 == available */ + mutex_init(&uvd->lock); /* to 1 == available */ uvd->dev = NULL; rv = u; break; } } - up(&cams->lock); + mutex_unlock(&cams->lock); return rv; } @@ -983,7 +983,7 @@ struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams) /* Not relying upon caller we increase module counter ourselves */ usbvideo_ClientIncModCount(uvd); - down(&uvd->lock); + mutex_lock(&uvd->lock); for (i=0; i < USBVIDEO_NUMSBUF; i++) { uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); if (uvd->sbuf[i].urb == NULL) { @@ -1006,7 +1006,7 @@ struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams) * return control to the client's probe function right now. */ allocate_done: - up (&uvd->lock); + mutex_unlock(&uvd->lock); usbvideo_ClientDecModCount(uvd); return uvd; } @@ -1120,7 +1120,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) info("%s($%p)", __FUNCTION__, dev); usbvideo_ClientIncModCount(uvd); - down(&uvd->lock); + mutex_lock(&uvd->lock); if (uvd->user) { err("%s: Someone tried to open an already opened device!", __FUNCTION__); @@ -1201,7 +1201,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) } } } - up(&uvd->lock); + mutex_unlock(&uvd->lock); if (errCode != 0) usbvideo_ClientDecModCount(uvd); if (uvd->debug > 0) @@ -1230,7 +1230,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file) if (uvd->debug > 1) info("%s($%p)", __FUNCTION__, dev); - down(&uvd->lock); + mutex_lock(&uvd->lock); GET_CALLBACK(uvd, stopDataPump)(uvd); usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); uvd->fbuf = NULL; @@ -1251,7 +1251,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file) info("usbvideo_v4l_close: Final disconnect."); usbvideo_CameraRelease(uvd); } - up(&uvd->lock); + mutex_unlock(&uvd->lock); usbvideo_ClientDecModCount(uvd); if (uvd->debug > 1) @@ -1511,7 +1511,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, if (uvd->debug >= 1) info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock); - down(&uvd->lock); + mutex_lock(&uvd->lock); /* See if a frame is completed, then use it. */ for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { @@ -1643,7 +1643,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, } } read_done: - up(&uvd->lock); + mutex_unlock(&uvd->lock); return count; } diff --git a/drivers/usb/media/usbvideo.h b/drivers/usb/media/usbvideo.h index 6c390a1f981b..135433c2680a 100644 --- a/drivers/usb/media/usbvideo.h +++ b/drivers/usb/media/usbvideo.h @@ -19,6 +19,7 @@ #include #include #include +#include /* Most helpful debugging aid */ #define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__)))) @@ -213,7 +214,7 @@ struct uvd { unsigned long flags; /* FLAGS_USBVIDEO_xxx */ unsigned long paletteBits; /* Which palettes we accept? */ unsigned short defaultPalette; /* What palette to use for read() */ - struct semaphore lock; + struct mutex lock; int user; /* user count for exclusive use */ videosize_t videosize; /* Current setting */ @@ -272,7 +273,7 @@ struct usbvideo { int num_cameras; /* As allocated */ struct usb_driver usbdrv; /* Interface to the USB stack */ char drvName[80]; /* Driver name */ - struct semaphore lock; /* Mutex protecting camera structures */ + struct mutex lock; /* Mutex protecting camera structures */ struct usbvideo_cb cb; /* Table of callbacks (virtual methods) */ struct video_device vdt; /* Video device template */ struct uvd *cam; /* Array of camera structures */ diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c index 5df144073871..8cfc47b831fb 100644 --- a/drivers/usb/media/vicam.c +++ b/drivers/usb/media/vicam.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "usbvideo.h" // #define VICAM_DEBUG @@ -407,7 +408,7 @@ struct vicam_camera { struct usb_device *udev; // usb device /* guard against simultaneous accesses to the camera */ - struct semaphore cam_lock; + struct mutex cam_lock; int is_initialized; u8 open_count; @@ -461,12 +462,12 @@ static int send_control_msg(struct vicam_camera *cam, u16 size) { int status = -ENODEV; - down(&cam->cam_lock); + mutex_lock(&cam->cam_lock); if (cam->udev) { status = __send_control_msg(cam, request, value, index, cp, size); } - up(&cam->cam_lock); + mutex_unlock(&cam->cam_lock); return status; } static int @@ -831,13 +832,13 @@ vicam_close(struct inode *inode, struct file *file) rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); kfree(cam->cntrlbuf); - down(&cam->cam_lock); + mutex_lock(&cam->cam_lock); cam->open_count--; open_count = cam->open_count; udev = cam->udev; - up(&cam->cam_lock); + mutex_unlock(&cam->cam_lock); if (!open_count && !udev) { kfree(cam); @@ -960,7 +961,7 @@ read_frame(struct vicam_camera *cam, int framenum) request[8] = 0; // bytes 9-15 do not seem to affect exposure or image quality - down(&cam->cam_lock); + mutex_lock(&cam->cam_lock); if (!cam->udev) { goto done; @@ -985,7 +986,7 @@ read_frame(struct vicam_camera *cam, int framenum) } done: - up(&cam->cam_lock); + mutex_unlock(&cam->cam_lock); } static ssize_t @@ -1309,7 +1310,7 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) cam->shutter_speed = 15; - init_MUTEX(&cam->cam_lock); + mutex_init(&cam->cam_lock); memcpy(&cam->vdev, &vicam_template, sizeof (vicam_template)); @@ -1351,7 +1352,7 @@ vicam_disconnect(struct usb_interface *intf) /* stop the camera from being used */ - down(&cam->cam_lock); + mutex_lock(&cam->cam_lock); /* mark the camera as gone */ @@ -1368,7 +1369,7 @@ vicam_disconnect(struct usb_interface *intf) open_count = cam->open_count; - up(&cam->cam_lock); + mutex_unlock(&cam->cam_lock); if (!open_count) { kfree(cam); diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c index 78cd1a577d26..b57dec3782e0 100644 --- a/drivers/usb/media/w9968cf.c +++ b/drivers/usb/media/w9968cf.c @@ -47,6 +47,13 @@ #include "w9968cf.h" #include "w9968cf_decoder.h" +static struct w9968cf_vpp_t* w9968cf_vpp; +static DECLARE_WAIT_QUEUE_HEAD(w9968cf_vppmod_wait); + +static LIST_HEAD(w9968cf_dev_list); /* head of V4L registered cameras list */ +static DEFINE_MUTEX(w9968cf_devlist_mutex); /* semaphore for list traversal */ + +static DECLARE_RWSEM(w9968cf_disconnect); /* prevent races with open() */ /**************************************************************************** @@ -2418,7 +2425,7 @@ w9968cf_configure_camera(struct w9968cf_device* cam, enum w9968cf_model_id mod_id, const unsigned short dev_nr) { - init_MUTEX(&cam->fileop_sem); + mutex_init(&cam->fileop_mutex); init_waitqueue_head(&cam->open); spin_lock_init(&cam->urb_lock); spin_lock_init(&cam->flist_lock); @@ -2646,7 +2653,7 @@ static void w9968cf_adjust_configuration(struct w9968cf_device* cam) --------------------------------------------------------------------------*/ static void w9968cf_release_resources(struct w9968cf_device* cam) { - down(&w9968cf_devlist_sem); + mutex_lock(&w9968cf_devlist_mutex); DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->minor) @@ -2657,7 +2664,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam) kfree(cam->control_buffer); kfree(cam->data_buffer); - up(&w9968cf_devlist_sem); + mutex_unlock(&w9968cf_devlist_mutex); } @@ -2677,14 +2684,14 @@ static int w9968cf_open(struct inode* inode, struct file* filp) cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); if (cam->sensor == CC_UNKNOWN) { DBG(2, "No supported image sensor has been detected by the " "'ovcamchip' module for the %s (/dev/video%d). Make " "sure it is loaded *before* (re)connecting the camera.", symbolic(camlist, cam->id), cam->v4ldev->minor) - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); up_read(&w9968cf_disconnect); return -ENODEV; } @@ -2693,11 +2700,11 @@ static int w9968cf_open(struct inode* inode, struct file* filp) DBG(2, "%s (/dev/video%d) has been already occupied by '%s'", symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command) if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) { - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); up_read(&w9968cf_disconnect); return -EWOULDBLOCK; } - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); err = wait_event_interruptible_exclusive(cam->open, cam->disconnected || !cam->users); @@ -2709,7 +2716,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp) up_read(&w9968cf_disconnect); return -ENODEV; } - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); } DBG(5, "Opening '%s', /dev/video%d ...", @@ -2738,7 +2745,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp) DBG(5, "Video device is open") - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); up_read(&w9968cf_disconnect); return 0; @@ -2746,7 +2753,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp) deallocate_memory: w9968cf_deallocate_memory(cam); DBG(2, "Failed to open the video device") - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); up_read(&w9968cf_disconnect); return err; } @@ -2758,13 +2765,13 @@ static int w9968cf_release(struct inode* inode, struct file* filp) cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); - down(&cam->dev_sem); /* prevent disconnect() to be called */ + mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ w9968cf_stop_transfer(cam); if (cam->disconnected) { w9968cf_release_resources(cam); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); kfree(cam); return 0; } @@ -2774,7 +2781,7 @@ static int w9968cf_release(struct inode* inode, struct file* filp) wake_up_interruptible_nr(&cam->open, 1); DBG(5, "Video device closed") - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); return 0; } @@ -2791,18 +2798,18 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) if (filp->f_flags & O_NONBLOCK) return -EWOULDBLOCK; - if (down_interruptible(&cam->fileop_sem)) + if (mutex_lock_interruptible(&cam->fileop_mutex)) return -ERESTARTSYS; if (cam->disconnected) { DBG(2, "Device not present") - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENODEV; } if (cam->misconfigured) { DBG(2, "The camera is misconfigured. Close and open it again.") - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EIO; } @@ -2817,11 +2824,11 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) cam->frame[1].status == F_READY || cam->disconnected); if (err) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return err; } if (cam->disconnected) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENODEV; } @@ -2835,7 +2842,7 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) if (copy_to_user(buf, fr->buffer, count)) { fr->status = F_UNUSED; - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EFAULT; } *f_pos += count; @@ -2844,7 +2851,7 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) DBG(5, "%zu bytes read", count) - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return count; } @@ -2898,24 +2905,24 @@ w9968cf_ioctl(struct inode* inode, struct file* filp, cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); - if (down_interruptible(&cam->fileop_sem)) + if (mutex_lock_interruptible(&cam->fileop_mutex)) return -ERESTARTSYS; if (cam->disconnected) { DBG(2, "Device not present") - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENODEV; } if (cam->misconfigured) { DBG(2, "The camera is misconfigured. Close and open it again.") - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EIO; } err = w9968cf_v4l_ioctl(inode, filp, cmd, (void __user *)arg); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return err; } @@ -3502,8 +3509,8 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) if (!cam) return -ENOMEM; - init_MUTEX(&cam->dev_sem); - down(&cam->dev_sem); + mutex_init(&cam->dev_mutex); + mutex_lock(&cam->dev_mutex); cam->usbdev = udev; /* NOTE: a local copy is used to avoid possible race conditions */ @@ -3515,10 +3522,10 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) simcams = W9968CF_SIMCAMS; /* How many cameras are connected ? */ - down(&w9968cf_devlist_sem); + mutex_lock(&w9968cf_devlist_mutex); list_for_each(ptr, &w9968cf_dev_list) sc++; - up(&w9968cf_devlist_sem); + mutex_unlock(&w9968cf_devlist_mutex); if (sc >= simcams) { DBG(2, "Device rejected: too many connected cameras " @@ -3578,9 +3585,9 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) w9968cf_configure_camera(cam, udev, mod_id, dev_nr); /* Add a new entry into the list of V4L registered devices */ - down(&w9968cf_devlist_sem); + mutex_lock(&w9968cf_devlist_mutex); list_add(&cam->v4llist, &w9968cf_dev_list); - up(&w9968cf_devlist_sem); + mutex_unlock(&w9968cf_devlist_mutex); dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0; w9968cf_turn_on_led(cam); @@ -3588,7 +3595,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) w9968cf_i2c_init(cam); usb_set_intfdata(intf, cam); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); return 0; fail: /* Free unused memory */ @@ -3596,7 +3603,7 @@ fail: /* Free unused memory */ kfree(cam->data_buffer); if (cam->v4ldev) video_device_release(cam->v4ldev); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); kfree(cam); return err; } @@ -3611,7 +3618,7 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) if (cam) { /* Prevent concurrent accesses to data */ - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); cam->disconnected = 1; @@ -3630,7 +3637,7 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) } else w9968cf_release_resources(cam); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); if (!cam->users) kfree(cam); diff --git a/drivers/usb/media/w9968cf.h b/drivers/usb/media/w9968cf.h index 47a6ff794171..a87be719a281 100644 --- a/drivers/usb/media/w9968cf.h +++ b/drivers/usb/media/w9968cf.h @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include @@ -194,14 +194,6 @@ enum w9968cf_vpp_flag { VPP_UYVY_TO_RGBX = 0x08, }; -static struct w9968cf_vpp_t* w9968cf_vpp; -static DECLARE_WAIT_QUEUE_HEAD(w9968cf_vppmod_wait); - -static LIST_HEAD(w9968cf_dev_list); /* head of V4L registered cameras list */ -static DECLARE_MUTEX(w9968cf_devlist_sem); /* semaphore for list traversal */ - -static DECLARE_RWSEM(w9968cf_disconnect); /* prevent races with open() */ - /* Main device driver structure */ struct w9968cf_device { struct device dev; /* device structure */ @@ -277,8 +269,8 @@ struct w9968cf_device { struct i2c_client* sensor_client; /* Locks */ - struct semaphore dev_sem, /* for probe, disconnect,open and close */ - fileop_sem; /* for read and ioctl */ + struct mutex dev_mutex, /* for probe, disconnect,open and close */ + fileop_mutex; /* for read and ioctl */ spinlock_t urb_lock, /* for submit_urb() and unlink_urb() */ flist_lock; /* for requested frame list accesses */ wait_queue_head_t open, wait_queue; diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index b3aca5124339..d0b167256699 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -121,7 +122,7 @@ static struct usb_driver idmouse_driver = { }; /* prevent races between open() and disconnect() */ -static DECLARE_MUTEX(disconnect_sem); +static DEFINE_MUTEX(disconnect_mutex); static int idmouse_create_image(struct usb_idmouse *dev) { @@ -213,18 +214,18 @@ static int idmouse_open(struct inode *inode, struct file *file) int result = 0; /* prevent disconnects */ - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); /* get the interface from minor number and driver information */ interface = usb_find_interface (&idmouse_driver, iminor (inode)); if (!interface) { - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return -ENODEV; } /* get the device information block from the interface */ dev = usb_get_intfdata(interface); if (!dev) { - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return -ENODEV; } @@ -258,7 +259,7 @@ error: up(&dev->sem); /* unlock the disconnect semaphore */ - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return result; } @@ -267,12 +268,12 @@ static int idmouse_release(struct inode *inode, struct file *file) struct usb_idmouse *dev; /* prevent a race condition with open() */ - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); dev = (struct usb_idmouse *) file->private_data; if (dev == NULL) { - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return -ENODEV; } @@ -282,7 +283,7 @@ static int idmouse_release(struct inode *inode, struct file *file) /* are we really open? */ if (dev->open <= 0) { up(&dev->sem); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return -ENODEV; } @@ -292,12 +293,12 @@ static int idmouse_release(struct inode *inode, struct file *file) /* the device was unplugged before the file was released */ up(&dev->sem); idmouse_delete(dev); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return 0; } up(&dev->sem); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return 0; } @@ -399,7 +400,7 @@ static void idmouse_disconnect(struct usb_interface *interface) struct usb_idmouse *dev; /* prevent races with open() */ - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); /* get device structure */ dev = usb_get_intfdata(interface); @@ -421,7 +422,7 @@ static void idmouse_disconnect(struct usb_interface *interface) if (!dev->open) idmouse_delete(dev); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); info("%s disconnected", DRIVER_DESC); } diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index f6bdaf08a80f..966acb474f67 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -172,7 +173,7 @@ struct ld_usb { }; /* prevent races between open() and disconnect() */ -static DECLARE_MUTEX(disconnect_sem); +static DEFINE_MUTEX(disconnect_mutex); static struct usb_driver ld_usb_driver; @@ -293,7 +294,7 @@ static int ld_usb_open(struct inode *inode, struct file *file) nonseekable_open(inode, file); subminor = iminor(inode); - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); interface = usb_find_interface(&ld_usb_driver, subminor); @@ -355,7 +356,7 @@ unlock_exit: up(&dev->sem); unlock_disconnect_exit: - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return retval; } @@ -740,7 +741,7 @@ static void ld_usb_disconnect(struct usb_interface *intf) struct ld_usb *dev; int minor; - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); dev = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); @@ -761,7 +762,7 @@ static void ld_usb_disconnect(struct usb_interface *intf) up(&dev->sem); } - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); dev_info(&intf->dev, "LD USB Device #%d now disconnected\n", (minor - USB_LD_MINOR_BASE)); diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 1336745b8f55..779bcf0373ad 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -83,6 +83,7 @@ #include #include #include +#include #include #include #include @@ -256,7 +257,7 @@ static void tower_disconnect (struct usb_interface *interface); /* prevent races between open() and disconnect */ -static DECLARE_MUTEX (disconnect_sem); +static DEFINE_MUTEX (disconnect_mutex); /* file operations needed when we register this driver */ static struct file_operations tower_fops = { @@ -349,7 +350,7 @@ static int tower_open (struct inode *inode, struct file *file) nonseekable_open(inode, file); subminor = iminor(inode); - down (&disconnect_sem); + mutex_lock (&disconnect_mutex); interface = usb_find_interface (&tower_driver, subminor); @@ -427,7 +428,7 @@ unlock_exit: up (&dev->sem); unlock_disconnect_exit: - up (&disconnect_sem); + mutex_unlock (&disconnect_mutex); dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval); @@ -1005,7 +1006,7 @@ static void tower_disconnect (struct usb_interface *interface) dbg(2, "%s: enter", __FUNCTION__); - down (&disconnect_sem); + mutex_lock (&disconnect_mutex); dev = usb_get_intfdata (interface); usb_set_intfdata (interface, NULL); @@ -1027,7 +1028,7 @@ static void tower_disconnect (struct usb_interface *interface) up (&dev->sem); } - up (&disconnect_sem); + mutex_unlock (&disconnect_mutex); info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE)); diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index c34944c75047..b03e346e33f1 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "usb_mon.h" #include "../core/hcd.h" @@ -23,7 +24,7 @@ static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus); static void mon_bus_drop(struct kref *r); static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus); -DECLARE_MUTEX(mon_lock); +DEFINE_MUTEX(mon_lock); static struct dentry *mon_dir; /* /dbg/usbmon */ static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */ @@ -196,14 +197,14 @@ static void mon_bus_remove(struct usb_bus *ubus) { struct mon_bus *mbus = ubus->mon_bus; - down(&mon_lock); + mutex_lock(&mon_lock); list_del(&mbus->bus_link); debugfs_remove(mbus->dent_t); debugfs_remove(mbus->dent_s); mon_dissolve(mbus, ubus); kref_put(&mbus->ref, mon_bus_drop); - up(&mon_lock); + mutex_unlock(&mon_lock); } static int mon_notify(struct notifier_block *self, unsigned long action, @@ -307,9 +308,9 @@ static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus) goto err_create_s; mbus->dent_s = d; - down(&mon_lock); + mutex_lock(&mon_lock); list_add_tail(&mbus->bus_link, &mon_buses); - up(&mon_lock); + mutex_unlock(&mon_lock); return; err_create_s: @@ -347,11 +348,11 @@ static int __init mon_init(void) usb_register_notify(&mon_nb); - down(&usb_bus_list_lock); + mutex_lock(&usb_bus_list_lock); list_for_each_entry (ubus, &usb_bus_list, bus_list) { mon_bus_init(mondir, ubus); } - up(&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); return 0; } @@ -363,7 +364,7 @@ static void __exit mon_exit(void) usb_unregister_notify(&mon_nb); usb_mon_deregister(); - down(&mon_lock); + mutex_lock(&mon_lock); while (!list_empty(&mon_buses)) { p = mon_buses.next; mbus = list_entry(p, struct mon_bus, bus_link); @@ -387,7 +388,7 @@ static void __exit mon_exit(void) mon_dissolve(mbus, mbus->u_bus); kref_put(&mbus->ref, mon_bus_drop); } - up(&mon_lock); + mutex_unlock(&mon_lock); debugfs_remove(mon_dir); } diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 611612146ae9..59089e8b7e5e 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "usb_mon.h" @@ -54,7 +55,7 @@ struct mon_reader_text { wait_queue_head_t wait; int printf_size; char *printf_buf; - struct semaphore printf_lock; + struct mutex printf_lock; char slab_name[SLAB_NAME_SZ]; }; @@ -208,7 +209,7 @@ static int mon_text_open(struct inode *inode, struct file *file) struct mon_reader_text *rp; int rc; - down(&mon_lock); + mutex_lock(&mon_lock); mbus = inode->u.generic_ip; ubus = mbus->u_bus; @@ -220,7 +221,7 @@ static int mon_text_open(struct inode *inode, struct file *file) memset(rp, 0, sizeof(struct mon_reader_text)); INIT_LIST_HEAD(&rp->e_list); init_waitqueue_head(&rp->wait); - init_MUTEX(&rp->printf_lock); + mutex_init(&rp->printf_lock); rp->printf_size = PRINTF_DFL; rp->printf_buf = kmalloc(rp->printf_size, GFP_KERNEL); @@ -247,7 +248,7 @@ static int mon_text_open(struct inode *inode, struct file *file) mon_reader_add(mbus, &rp->r); file->private_data = rp; - up(&mon_lock); + mutex_unlock(&mon_lock); return 0; // err_busy: @@ -257,7 +258,7 @@ err_slab: err_alloc_pr: kfree(rp); err_alloc: - up(&mon_lock); + mutex_unlock(&mon_lock); return rc; } @@ -301,7 +302,7 @@ static ssize_t mon_text_read(struct file *file, char __user *buf, set_current_state(TASK_RUNNING); remove_wait_queue(&rp->wait, &waita); - down(&rp->printf_lock); + mutex_lock(&rp->printf_lock); cnt = 0; pbuf = rp->printf_buf; limit = rp->printf_size; @@ -358,7 +359,7 @@ static ssize_t mon_text_read(struct file *file, char __user *buf, if (copy_to_user(buf, rp->printf_buf, cnt)) cnt = -EFAULT; - up(&rp->printf_lock); + mutex_unlock(&rp->printf_lock); kmem_cache_free(rp->e_slab, ep); return cnt; } @@ -371,12 +372,12 @@ static int mon_text_release(struct inode *inode, struct file *file) struct list_head *p; struct mon_event_text *ep; - down(&mon_lock); + mutex_lock(&mon_lock); mbus = inode->u.generic_ip; if (mbus->nreaders <= 0) { printk(KERN_ERR TAG ": consistency error on close\n"); - up(&mon_lock); + mutex_unlock(&mon_lock); return 0; } mon_reader_del(mbus, &rp->r); @@ -402,7 +403,7 @@ static int mon_text_release(struct inode *inode, struct file *file) kfree(rp->printf_buf); kfree(rp); - up(&mon_lock); + mutex_unlock(&mon_lock); return 0; } diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h index 4be0f9346071..8e0613c350cc 100644 --- a/drivers/usb/mon/usb_mon.h +++ b/drivers/usb/mon/usb_mon.h @@ -49,7 +49,7 @@ void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r); */ extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len); -extern struct semaphore mon_lock; +extern struct mutex mon_lock; extern struct file_operations mon_fops_text; extern struct file_operations mon_fops_stat; diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 4ef5527028c5..5f11e19eaae3 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -47,6 +47,7 @@ #include #include +#include #include #include @@ -271,9 +272,9 @@ static int device_reset(struct scsi_cmnd *srb) US_DEBUGP("%s called\n", __FUNCTION__); /* lock the device pointers and do the reset */ - down(&(us->dev_semaphore)); + mutex_lock(&(us->dev_mutex)); result = us->transport_reset(us); - up(&(us->dev_semaphore)); + mutex_unlock(&us->dev_mutex); return result < 0 ? FAILED : SUCCESS; } @@ -286,9 +287,9 @@ static int bus_reset(struct scsi_cmnd *srb) US_DEBUGP("%s called\n", __FUNCTION__); - down(&(us->dev_semaphore)); + mutex_lock(&(us->dev_mutex)); result = usb_stor_port_reset(us); - up(&(us->dev_semaphore)); + mutex_unlock(&us->dev_mutex); return result < 0 ? FAILED : SUCCESS; } diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index dbcf23980ff1..dd108634348e 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -188,7 +189,7 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message) struct us_data *us = usb_get_intfdata(iface); /* Wait until no command is running */ - down(&us->dev_semaphore); + mutex_lock(&us->dev_mutex); US_DEBUGP("%s\n", __FUNCTION__); if (us->suspend_resume_hook) @@ -198,7 +199,7 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message) /* When runtime PM is working, we'll set a flag to indicate * whether we should autoresume when a SCSI request arrives. */ - up(&us->dev_semaphore); + mutex_unlock(&us->dev_mutex); return 0; } @@ -206,14 +207,14 @@ static int storage_resume(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); - down(&us->dev_semaphore); + mutex_lock(&us->dev_mutex); US_DEBUGP("%s\n", __FUNCTION__); if (us->suspend_resume_hook) (us->suspend_resume_hook)(us, US_RESUME); iface->dev.power.power_state.event = PM_EVENT_ON; - up(&us->dev_semaphore); + mutex_unlock(&us->dev_mutex); return 0; } @@ -276,12 +277,12 @@ static int usb_stor_control_thread(void * __us) US_DEBUGP("*** thread awakened.\n"); /* lock the device pointers */ - down(&(us->dev_semaphore)); + mutex_lock(&(us->dev_mutex)); /* if the device has disconnected, we are free to exit */ if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { US_DEBUGP("-- exiting\n"); - up(&(us->dev_semaphore)); + mutex_unlock(&us->dev_mutex); break; } @@ -370,7 +371,7 @@ SkipForAbort: scsi_unlock(host); /* unlock the device pointers */ - up(&(us->dev_semaphore)); + mutex_unlock(&us->dev_mutex); } /* for (;;) */ scsi_host_put(host); @@ -815,8 +816,8 @@ static void quiesce_and_remove_host(struct us_data *us) * The thread will exit when it sees the DISCONNECTING flag. */ /* Wait for the current command to finish, then remove the host */ - down(&us->dev_semaphore); - up(&us->dev_semaphore); + mutex_lock(&us->dev_mutex); + mutex_unlock(&us->dev_mutex); /* queuecommand won't accept any new commands and the control * thread won't execute a previously-queued command. If there @@ -870,9 +871,9 @@ retry: /* For bulk-only devices, determine the max LUN value */ if (us->protocol == US_PR_BULK && !(us->flags & US_FL_SINGLE_LUN)) { - down(&us->dev_semaphore); + mutex_lock(&us->dev_mutex); us->max_lun = usb_stor_Bulk_max_lun(us); - up(&us->dev_semaphore); + mutex_unlock(&us->dev_mutex); } scsi_scan_host(us_to_host(us)); printk(KERN_DEBUG "usb-storage: device scan complete\n"); @@ -912,7 +913,7 @@ static int storage_probe(struct usb_interface *intf, us = host_to_us(host); memset(us, 0, sizeof(struct us_data)); - init_MUTEX(&(us->dev_semaphore)); + mutex_init(&(us->dev_mutex)); init_MUTEX_LOCKED(&(us->sema)); init_completion(&(us->notify)); init_waitqueue_head(&us->delay_wait); diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 7259fd1f6b0d..009fb0953a56 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -49,6 +49,7 @@ #include #include #include +#include #include struct us_data; @@ -103,9 +104,9 @@ typedef void (*pm_hook)(struct us_data *, int); /* power management hook */ struct us_data { /* The device we're working with * It's important to note: - * (o) you must hold dev_semaphore to change pusb_dev + * (o) you must hold dev_mutex to change pusb_dev */ - struct semaphore dev_semaphore; /* protect pusb_dev */ + struct mutex dev_mutex; /* protect pusb_dev */ struct usb_device *pusb_dev; /* this usb_device */ struct usb_interface *pusb_intf; /* this interface */ struct us_unusual_dev *unusual_dev; /* device-filter entry */ -- cgit v1.2.3-59-g8ed1b From f8aeb3bb8657b207895aa10f75e63f2c48d08985 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 20 Jan 2006 13:55:14 -0800 Subject: [PATCH] USB: EHCI and NF2 quirk This teaches the EHCI driver about a quirk seen in older NForce2 chips, adding a workaround to ignore selective suspend requests. Bus-wide (so-called "global") suspend still works, as does USB wakeup of a root hub that's globally suspended. There's still a hole in this support though. Strictly speaking, this should _fail_ selective suspend requests, rather than ignoring them, since doing it this way means that devices which should be able to issue remote wakeup are not going to be able to do that. For now, we'll just live with that problem ... since usbcore expects to do selective suspend on the way towards a full bus suspend, and usbcore needs to be able to do full bus suspend. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 4 ++++ drivers/usb/host/ehci-pci.c | 25 ++++++++++++++++++++++++- drivers/usb/host/ehci.h | 3 ++- 3 files changed, 30 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 69b0b9be7a64..d03e3cad5ca8 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -359,6 +359,8 @@ static int ehci_hub_control ( case USB_PORT_FEAT_SUSPEND: if (temp & PORT_RESET) goto error; + if (ehci->no_selective_suspend) + break; if (temp & PORT_SUSPEND) { if ((temp & PORT_PE) == 0) goto error; @@ -514,6 +516,8 @@ static int ehci_hub_control ( temp &= ~PORT_RWC_BITS; switch (wValue) { case USB_PORT_FEAT_SUSPEND: + if (ehci->no_selective_suspend) + break; if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) goto error; diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 3a6687df5594..1e03f1a5a5fd 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -106,11 +106,11 @@ 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.) */ - switch (pdev->device) { case 0x003c: /* MCP04 */ case 0x005b: /* CK804 */ case 0x00d8: /* CK8 */ @@ -120,6 +120,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd) 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. + */ + case 0x0068: + pci_read_config_dword(pdev, PCI_REVISION_ID, &temp); + if ((temp & 0xff) < 0xa4) + ehci->no_selective_suspend = 1; + break; } break; } @@ -163,6 +171,21 @@ static int ehci_pci_setup(struct usb_hcd *hcd) device_init_wakeup(&pdev->dev, 1); } +#ifdef CONFIG_USB_SUSPEND + /* REVISIT: the controller works fine for wakeup iff the root hub + * itself is "globally" suspended, but usbcore currently doesn't + * understand such things. + * + * System suspend currently expects to be able to suspend the entire + * device tree, device-at-a-time. If we failed selective suspend + * reports, system suspend would fail; so the root hub code must claim + * success. That's lying to usbcore, and it matters for for runtime + * PM scenarios with selective suspend and remote wakeup... + */ + if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev)) + ehci_warn(ehci, "selective suspend/wakeup unavailable\n"); +#endif + retval = ehci_pci_reinit(ehci, pdev); done: return retval; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 18e257c2bdb5..86af41c41de1 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -89,6 +89,8 @@ struct ehci_hcd { /* one per controller */ u32 command; unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */ + unsigned no_selective_suspend:1; + u8 sbrn; /* packed release number */ /* irq statistics */ #ifdef EHCI_STATS @@ -97,7 +99,6 @@ struct ehci_hcd { /* one per controller */ #else # define COUNT(x) do {} while (0) #endif - u8 sbrn; /* packed release number */ }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ -- cgit v1.2.3-59-g8ed1b From 469d02293d494d30dba81895cd3d34b0a3a6d51a Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 20 Jan 2006 13:49:10 -0800 Subject: [PATCH] USB: EHCI full speed ISO bugfixes This patch replaces the split ISO raw_mask calculation code in the iso_stream_init() function that computed incorrect numbers of high speed transactions for both input and output transfers. In the output case, it added a superfluous start-split transaction for all maxmimum packet sizes that are a multiple of 188. In the input case, it forgot to add complete-split transactions for all microframes covered by the full speed transaction, and the additional complete-split transaction needed for the case when full speed data starts arriving near the end of a microframe. These changes don't affect the lack of full speed bandwidth, but at least it removes the MMF errors that the HC raised with some input streams. Signed-off-by: Clemens Ladisch Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index ebcca9700671..88419c6823a8 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -707,6 +707,7 @@ iso_stream_init ( } else { u32 addr; int think_time; + int hs_transfers; addr = dev->ttport << 24; if (!ehci_is_TDI(ehci) @@ -719,6 +720,7 @@ iso_stream_init ( think_time = dev->tt ? dev->tt->think_time : 0; stream->tt_usecs = NS_TO_US (think_time + usb_calc_bus_time ( dev->speed, is_input, 1, maxp)); + hs_transfers = max (1u, (maxp + 187) / 188); if (is_input) { u32 tmp; @@ -727,12 +729,11 @@ iso_stream_init ( stream->usecs = HS_USECS_ISO (1); stream->raw_mask = 1; - /* pessimistic c-mask */ - tmp = usb_calc_bus_time (USB_SPEED_FULL, 1, 0, maxp) - / (125 * 1000); - stream->raw_mask |= 3 << (tmp + 9); + /* c-mask as specified in USB 2.0 11.18.4 3.c */ + tmp = (1 << (hs_transfers + 2)) - 1; + stream->raw_mask |= tmp << (8 + 2); } else - stream->raw_mask = smask_out [maxp / 188]; + stream->raw_mask = smask_out [hs_transfers - 1]; bandwidth = stream->usecs + stream->c_usecs; bandwidth /= 1 << (interval + 2); -- cgit v1.2.3-59-g8ed1b From 80cb9aee01245b38325dd84f1359b14a3f01f10d Mon Sep 17 00:00:00 2001 From: Randy Vinson Date: Fri, 20 Jan 2006 13:53:38 -0800 Subject: [PATCH] USB: EHCI for Freescale 83xx Adding a Host Mode USB driver for the Freescale 83xx. This driver supports both the Dual-Role (DR) controller and the Multi-Port-Host (MPH) controller present in the Freescale MPC8349. It has been tested with the MPC8349CDS reference system. This driver depends on platform support code for setting up the pins on the device package in a manner appropriate for the board in use. Note that this patch requires selecting the EHCI controller option under the USB Host menu. Signed-off-by: Randy Vinson Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Kconfig | 1 + drivers/usb/host/Kconfig | 2 +- drivers/usb/host/ehci-fsl.c | 357 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci-fsl.h | 37 +++++ drivers/usb/host/ehci-hcd.c | 8 +- include/linux/fsl_devices.h | 27 ++++ 6 files changed, 430 insertions(+), 2 deletions(-) create mode 100644 drivers/usb/host/ehci-fsl.c create mode 100644 drivers/usb/host/ehci-fsl.h (limited to 'drivers') diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 85dacc92545a..7772e28a303f 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -11,6 +11,7 @@ config USB_ARCH_HAS_HCD boolean default y if USB_ARCH_HAS_OHCI default y if ARM # SL-811 + default y if PPC_83xx default PCI # many non-PCI SOC chips embed OHCI diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index be3fd9bce573..a45293673906 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -6,7 +6,7 @@ comment "USB Host Controller Drivers" config USB_EHCI_HCD tristate "EHCI HCD (USB 2.0) support" - depends on USB && PCI + depends on USB && (PCI || PPC_83xx) ---help--- The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c new file mode 100644 index 000000000000..c6012d6cd527 --- /dev/null +++ b/drivers/usb/host/ehci-fsl.c @@ -0,0 +1,357 @@ +/* + * (C) Copyright David Brownell 2000-2002 + * Copyright (c) 2005 MontaVista Software + * + * 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. + * + * Ported to 834x by Randy Vinson using code provided + * by Hunter Wu. + */ + +#include +#include + +#include "ehci-fsl.h" + +/* FIXME: Power Managment is un-ported so temporarily disable it */ +#undef CONFIG_PM + +/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */ + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + +/** + * usb_hcd_fsl_probe - initialize FSL-based HCDs + * @drvier: Driver to be used for this HCD + * @pdev: USB Host Controller being probed + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller. + * + */ +int usb_hcd_fsl_probe(const struct hc_driver *driver, + struct platform_device *pdev) +{ + struct fsl_usb2_platform_data *pdata; + struct usb_hcd *hcd; + struct resource *res; + int irq; + int retval; + unsigned int temp; + + pr_debug("initializing FSL-SOC USB Controller\n"); + + /* Need platform data for setup */ + pdata = (struct fsl_usb2_platform_data *)pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, + "No platform data for %s.\n", pdev->dev.bus_id); + return -ENODEV; + } + + /* + * This is a host mode driver, verify that we're supposed to be + * in host mode. + */ + if (!((pdata->operating_mode == FSL_USB2_DR_HOST) || + (pdata->operating_mode == FSL_USB2_MPH_HOST))) { + dev_err(&pdev->dev, + "Non Host Mode configured for %s. Wrong driver linked.\n", + pdev->dev.bus_id); + return -ENODEV; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, + "Found HC with no IRQ. Check %s setup!\n", + pdev->dev.bus_id); + return -ENODEV; + } + irq = res->start; + + hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id); + if (!hcd) { + retval = -ENOMEM; + goto err1; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, + "Found HC with no register addr. Check %s setup!\n", + pdev->dev.bus_id); + retval = -ENODEV; + goto err2; + } + hcd->rsrc_start = res->start; + hcd->rsrc_len = res->end - res->start + 1; + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, + driver->description)) { + dev_dbg(&pdev->dev, "controller already in use\n"); + retval = -EBUSY; + goto err2; + } + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + + if (hcd->regs == NULL) { + dev_dbg(&pdev->dev, "error mapping memory\n"); + retval = -EFAULT; + goto err3; + } + + /* Enable USB controller */ + temp = in_be32(hcd->regs + 0x500); + out_be32(hcd->regs + 0x500, temp | 0x4); + + /* Set to Host mode */ + temp = in_le32(hcd->regs + 0x1a8); + out_le32(hcd->regs + 0x1a8, temp | 0x3); + + retval = usb_add_hcd(hcd, irq, SA_SHIRQ); + if (retval != 0) + goto err4; + return retval; + + err4: + iounmap(hcd->regs); + err3: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + err2: + usb_put_hcd(hcd); + err1: + dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval); + return retval; +} + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * usb_hcd_fsl_remove - shutdown processing for FSL-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_hcd_fsl_probe(). + * + */ +void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct platform_device *pdev) +{ + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); +} + +static void mpc83xx_setup_phy(struct ehci_hcd *ehci, + enum fsl_usb2_phy_modes phy_mode, + unsigned int port_offset) +{ + u32 portsc = readl(&ehci->regs->port_status[port_offset]); + portsc &= ~PORT_PTS_MSK; + switch (phy_mode) { + case FSL_USB2_PHY_ULPI: + portsc |= PORT_PTS_ULPI; + break; + case FSL_USB2_PHY_SERIAL: + portsc |= PORT_PTS_SERIAL; + break; + case FSL_USB2_PHY_UTMI_WIDE: + portsc |= PORT_PTS_PTW; + /* fall through */ + case FSL_USB2_PHY_UTMI: + portsc |= PORT_PTS_UTMI; + break; + case FSL_USB2_PHY_NONE: + break; + } + writel(portsc, &ehci->regs->port_status[port_offset]); +} + +static void mpc83xx_usb_setup(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct fsl_usb2_platform_data *pdata; + void __iomem *non_ehci = hcd->regs; + + pdata = + (struct fsl_usb2_platform_data *)hcd->self.controller-> + platform_data; + /* Enable PHY interface in the control reg. */ + out_be32(non_ehci + FSL_SOC_USB_CTRL, 0x00000004); + out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); + + if (pdata->operating_mode == FSL_USB2_DR_HOST) + mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); + + if (pdata->operating_mode == FSL_USB2_MPH_HOST) { + if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) + mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); + if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) + mpc83xx_setup_phy(ehci, pdata->phy_mode, 1); + } + + /* put controller in host mode. */ + writel(0x00000003, non_ehci + FSL_SOC_USB_USBMODE); + out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); + out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); + out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); +} + +/* called after powerup, by probe or system-pm "wakeup" */ +static int ehci_fsl_reinit(struct ehci_hcd *ehci) +{ + mpc83xx_usb_setup(ehci_to_hcd(ehci)); + ehci_port_power(ehci, 0); + + return 0; +} + +/* called during probe() after chip reset completes */ +static int ehci_fsl_setup(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int retval; + + /* EHCI registers start at offset 0x100 */ + ehci->caps = hcd->regs + 0x100; + ehci->regs = hcd->regs + 0x100 + + HC_LENGTH(readl(&ehci->caps->hc_capbase)); + dbg_hcs_params(ehci, "reset"); + dbg_hcc_params(ehci, "reset"); + + /* cache this readonly data; minimize chip reads */ + ehci->hcs_params = readl(&ehci->caps->hcs_params); + + retval = ehci_halt(ehci); + if (retval) + return retval; + + /* data structure init */ + retval = ehci_init(hcd); + if (retval) + return retval; + + ehci->is_tdi_rh_tt = 1; + + ehci->sbrn = 0x20; + + ehci_reset(ehci); + + retval = ehci_fsl_reinit(ehci); + return retval; +} + +static const struct hc_driver ehci_fsl_hc_driver = { + .description = hcd_name, + .product_desc = "Freescale On-Chip EHCI Host Controller", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = ehci_fsl_setup, + .start = ehci_run, +#ifdef CONFIG_PM + .suspend = ehci_bus_suspend, + .resume = ehci_bus_resume, +#endif + .stop = ehci_stop, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, +}; + +static int ehci_fsl_drv_probe(struct platform_device *pdev) +{ + if (usb_disabled()) + return -ENODEV; + + return usb_hcd_fsl_probe(&ehci_fsl_hc_driver, pdev); +} + +static int ehci_fsl_drv_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + + usb_hcd_fsl_remove(hcd, 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", + }, +}; + +static struct platform_driver ehci_fsl_mph_driver = { + .probe = ehci_fsl_drv_probe, + .remove = ehci_fsl_drv_remove, + .driver = { + .name = "fsl-usb2-mph", + }, +}; + +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-fsl.h b/drivers/usb/host/ehci-fsl.h new file mode 100644 index 000000000000..caac0d1967d0 --- /dev/null +++ b/drivers/usb/host/ehci-fsl.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2005 freescale semiconductor + * Copyright (c) 2005 MontaVista Software + * + * 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. + */ +#ifndef _EHCI_FSL_H +#define _EHCI_FSL_H + +/* offsets for the non-ehci registers in the FSL SOC USB controller */ +#define FSL_SOC_USB_ULPIVP 0x170 +#define FSL_SOC_USB_PORTSC1 0x184 +#define PORT_PTS_MSK (3<<30) +#define PORT_PTS_UTMI (0<<30) +#define PORT_PTS_ULPI (2<<30) +#define PORT_PTS_SERIAL (3<<30) +#define PORT_PTS_PTW (1<<28) +#define FSL_SOC_USB_PORTSC2 0x188 +#define FSL_SOC_USB_USBMODE 0x1a8 +#define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */ +#define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */ +#define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */ +#define FSL_SOC_USB_SICTRL 0x40c /* NOTE: big-endian */ +#define FSL_SOC_USB_PRICTRL 0x410 /* NOTE: big-endian */ +#define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */ +#endif /* _EHCI_FSL_H */ diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 9dd3d14c64f3..8730babb5771 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -891,6 +891,12 @@ MODULE_LICENSE ("GPL"); #include "ehci-pci.c" #endif -#if !defined(CONFIG_PCI) +#ifdef CONFIG_PPC_83xx +#include "ehci-fsl.c" +#endif + +#if !(defined(CONFIG_PCI) || \ + defined(CONFIG_PPC_83xx) \ + ) #error "missing bus glue for ehci-hcd" #endif diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index a9f1cfd096ff..a3a0e078f79d 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -83,5 +83,32 @@ struct fsl_i2c_platform_data { #define FSL_I2C_DEV_SEPARATE_DFSRR 0x00000001 #define FSL_I2C_DEV_CLOCK_5200 0x00000002 + +enum fsl_usb2_operating_modes { + FSL_USB2_MPH_HOST, + FSL_USB2_DR_HOST, + FSL_USB2_DR_DEVICE, + FSL_USB2_DR_OTG, +}; + +enum fsl_usb2_phy_modes { + FSL_USB2_PHY_NONE, + FSL_USB2_PHY_ULPI, + FSL_USB2_PHY_UTMI, + FSL_USB2_PHY_UTMI_WIDE, + FSL_USB2_PHY_SERIAL, +}; + +struct fsl_usb2_platform_data { + /* board specific information */ + enum fsl_usb2_operating_modes operating_mode; + enum fsl_usb2_phy_modes phy_mode; + unsigned int port_enables; +}; + +/* Flags in fsl_usb2_mph_platform_data */ +#define FSL_USB2_PORT0_ENABLED 0x00000001 +#define FSL_USB2_PORT1_ENABLED 0x00000002 + #endif /* _FSL_DEVICE_H_ */ #endif /* __KERNEL__ */ -- cgit v1.2.3-59-g8ed1b From 8cd42e97bf451bbbb2f54dc571366ae5a72faaea Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 20 Jan 2006 13:57:52 -0800 Subject: [PATCH] USB: EHCI and Freescale 83xx quirk On the MPC834x processors the multiport host (MPH) EHCI controller has an erratum in which the port number in the queue head expects to be 0..N-1 instead of 1..N. If we are on one of these chips we subtract one from the port number before putting it into the queue head. Signed-off-by: Kumar Gala Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 10 ++++++++++ drivers/usb/host/ehci-q.c | 9 ++++++++- drivers/usb/host/ehci.h | 15 +++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index c6012d6cd527..59f90f76ee31 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -198,6 +198,16 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd) mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); if (pdata->operating_mode == FSL_USB2_MPH_HOST) { + unsigned int chip, rev, svr; + + svr = mfspr(SPRN_SVR); + chip = svr >> 16; + rev = (svr >> 4) & 0xf; + + /* Deal with USB Erratum #14 on MPC834x Rev 1.0 & 1.1 chips */ + if ((rev == 1) && (chip >= 0x8050) && (chip <= 0x8055)) + ehci->has_fsl_port_bug = 1; + if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 9b13bf2fa98d..6e28e593c044 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -721,7 +721,14 @@ qh_make ( info1 |= maxp << 16; info2 |= (EHCI_TUNE_MULT_TT << 30); - info2 |= urb->dev->ttport << 23; + + /* Some Freescale processors have an erratum in which the + * port number in the queue head was 0..N-1 instead of 1..N. + */ + if (ehci_has_fsl_portno_bug(ehci)) + info2 |= (urb->dev->ttport-1) << 23; + else + info2 |= urb->dev->ttport << 23; /* set the address of the TT; for TDI's integrated * root hub tt, leave it zeroed. diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 86af41c41de1..679c1cdcc915 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -88,8 +88,11 @@ struct ehci_hcd { /* one per controller */ unsigned long next_statechange; u32 command; + /* SILICON QUIRKS */ unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */ unsigned no_selective_suspend:1; + unsigned has_fsl_port_bug:1; /* FreeScale */ + u8 sbrn; /* packed release number */ /* irq statistics */ @@ -637,6 +640,18 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) #define ehci_port_speed(ehci, portsc) (1<has_fsl_port_bug) +#else +#define ehci_has_fsl_portno_bug(e) (0) +#endif + + /*-------------------------------------------------------------------------*/ #ifndef DEBUG -- cgit v1.2.3-59-g8ed1b From 76fa9a240de4294a097235c9ddd470c21eb3449e Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 20 Jan 2006 14:06:09 -0800 Subject: [PATCH] USB: EHCI for AU1200 ALCHEMY: Add EHCI support for AU1200 Updated by removing the OHCI support Signed-off-by: Jordan Crouse Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- arch/mips/au1000/common/cputable.c | 2 +- arch/mips/au1000/common/platform.c | 2 - drivers/usb/Kconfig | 9 +- drivers/usb/host/Kconfig | 2 +- drivers/usb/host/ehci-au1xxx.c | 297 +++++++++++++++++++++ drivers/usb/host/ehci-hcd.c | 11 +- include/asm-mips/mach-mips/cpu-feature-overrides.h | 4 + 7 files changed, 319 insertions(+), 8 deletions(-) create mode 100644 drivers/usb/host/ehci-au1xxx.c (limited to 'drivers') diff --git a/arch/mips/au1000/common/cputable.c b/arch/mips/au1000/common/cputable.c index 4dbde82c8215..d8df5fdb045f 100644 --- a/arch/mips/au1000/common/cputable.c +++ b/arch/mips/au1000/common/cputable.c @@ -38,7 +38,7 @@ struct cpu_spec cpu_specs[] = { { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 }, - { 0xffffffff, 0x04030201, "Au1200 AC", 0, 1 }, + { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0 }, { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, }; diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c index 48d3f54f88f8..1fb3dbdb93be 100644 --- a/arch/mips/au1000/common/platform.c +++ b/arch/mips/au1000/common/platform.c @@ -278,9 +278,7 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = { &au1100_lcd_device, #endif #ifdef CONFIG_SOC_AU1200 -#if 0 /* fixme */ &au1xxx_usb_ehci_device, -#endif &au1xxx_usb_gdt_device, &au1xxx_usb_otg_device, &au1200_lcd_device, diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 7772e28a303f..0e865975899f 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -10,8 +10,8 @@ menu "USB support" config USB_ARCH_HAS_HCD boolean default y if USB_ARCH_HAS_OHCI + default y if USB_ARCH_HAS_EHCI default y if ARM # SL-811 - default y if PPC_83xx default PCI # many non-PCI SOC chips embed OHCI @@ -31,6 +31,13 @@ config USB_ARCH_HAS_OHCI # more: default PCI +# some non-PCI hcds implement EHCI +config USB_ARCH_HAS_EHCI + boolean + default y if PPC_83xx + default y if SOC_AU1200 + default PCI + # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. config USB tristate "Support for Host-side USB" diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index a45293673906..e27b79a3c05f 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -6,7 +6,7 @@ comment "USB Host Controller Drivers" config USB_EHCI_HCD tristate "EHCI HCD (USB 2.0) support" - depends on USB && (PCI || PPC_83xx) + depends on USB && USB_ARCH_HAS_EHCI ---help--- The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c new file mode 100644 index 000000000000..63eadeec1324 --- /dev/null +++ b/drivers/usb/host/ehci-au1xxx.c @@ -0,0 +1,297 @@ +/* + * EHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 2000-2004 David Brownell + * + * Bus Glue for AMD Alchemy Au1xxx + * + * Based on "ohci-au1xxx.c" by Matt Porter + * + * Modified for AMD Alchemy Au1200 EHC + * by K.Boge + * + * This file is licenced under the GPL. + */ + +#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) +#define USB_MCFG_SSDEN (1<<23) +#define USB_MCFG_PHYPLLEN (1<<19) +#define USB_MCFG_EHCCLKEN (1<<17) +#define USB_MCFG_UCAM (1<<7) +#define USB_MCFG_EBMEN (1<<3) +#define USB_MCFG_EMEMEN (1<<2) + +#define USBH_ENABLE_CE (USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN) + +#ifdef CONFIG_DMA_COHERENT +#define USBH_ENABLE_INIT (USBH_ENABLE_CE \ + | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ + | USB_MCFG_SSDEN | USB_MCFG_UCAM \ + | USB_MCFG_EBMEN | USB_MCFG_EMEMEN) +#else +#define USBH_ENABLE_INIT (USBH_ENABLE_CE \ + | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ + | USB_MCFG_SSDEN \ + | USB_MCFG_EBMEN | USB_MCFG_EMEMEN) +#endif +#define USBH_DISABLE (USB_MCFG_EBMEN | USB_MCFG_EMEMEN) + +#endif /* Au1200 */ + +extern int usb_disabled(void); + +/*-------------------------------------------------------------------------*/ + +static void au1xxx_start_ehc(struct platform_device *dev) +{ + pr_debug(__FILE__ ": starting Au1xxx EHCI USB Controller\n"); + + /* write HW defaults again in case Yamon cleared them */ + if (au_readl(USB_HOST_CONFIG) == 0) { + au_writel(0x00d02000, USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); + udelay(1000); + } + /* enable host controller */ + au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); + udelay(1000); + au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG), + USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); + udelay(1000); + + pr_debug(__FILE__ ": Clock to USB host has been enabled\n"); +} + +static void au1xxx_stop_ehc(struct platform_device *dev) +{ + pr_debug(__FILE__ ": stopping Au1xxx EHCI USB Controller\n"); + + /* Disable mem */ + au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); + udelay(1000); + /* Disable clock */ + au_writel(~USB_MCFG_EHCCLKEN & au_readl(USB_HOST_CONFIG), + USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); +} + +/*-------------------------------------------------------------------------*/ + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + +/** + * usb_ehci_au1xxx_probe - initialize Au1xxx-based HCDs + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + * + */ +int usb_ehci_au1xxx_probe(const struct hc_driver *driver, + struct usb_hcd **hcd_out, struct platform_device *dev) +{ + int retval; + struct usb_hcd *hcd; + struct ehci_hcd *ehci; + +#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) + + /* Au1200 AB USB does not support coherent memory */ + if (!(read_c0_prid() & 0xff)) { + pr_info("%s: this is chip revision AB!\n", dev->dev.name); + pr_info("%s: update your board or re-configure the kernel\n", + dev->dev.name); + return -ENODEV; + } +#endif + + au1xxx_start_ehc(dev); + + if (dev->resource[1].flags != IORESOURCE_IRQ) { + pr_debug("resource[1] is not IORESOURCE_IRQ"); + retval = -ENOMEM; + } + hcd = usb_create_hcd(driver, &dev->dev, "Au1xxx"); + if (!hcd) + return -ENOMEM; + hcd->rsrc_start = dev->resource[0].start; + hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + pr_debug("request_mem_region failed"); + retval = -EBUSY; + goto err1; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + pr_debug("ioremap failed"); + retval = -ENOMEM; + goto err2; + } + + ehci = hcd_to_ehci(hcd); + ehci->caps = hcd->regs; + ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); + /* cache this readonly data; minimize chip reads */ + ehci->hcs_params = readl(&ehci->caps->hcs_params); + + /* ehci_hcd_init(hcd_to_ehci(hcd)); */ + + retval = + usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT | SA_SHIRQ); + if (retval == 0) + return retval; + + au1xxx_stop_ehc(dev); + iounmap(hcd->regs); +err2: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err1: + usb_put_hcd(hcd); + return retval; +} + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * usb_ehci_hcd_au1xxx_remove - shutdown processing for Au1xxx-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_ehci_hcd_au1xxx_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + * + */ +void usb_ehci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev) +{ + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); + au1xxx_stop_ehc(dev); +} + +/*-------------------------------------------------------------------------*/ + +static const struct hc_driver ehci_au1xxx_hc_driver = { + .description = hcd_name, + .product_desc = "Au1xxx EHCI", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = ehci_init, + .start = ehci_run, + .stop = ehci_stop, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, +#ifdef CONFIG_PM + .hub_suspend = ehci_hub_suspend, + .hub_resume = ehci_hub_resume, +#endif +}; + +/*-------------------------------------------------------------------------*/ + +static int ehci_hcd_au1xxx_drv_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = NULL; + int ret; + + pr_debug("In ehci_hcd_au1xxx_drv_probe\n"); + + if (usb_disabled()) + return -ENODEV; + + ret = usb_ehci_au1xxx_probe(&ehci_au1xxx_hc_driver, &hcd, pdev); + return ret; +} + +static int ehci_hcd_au1xxx_drv_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + + usb_ehci_au1xxx_remove(hcd, pdev); + return 0; +} + + /*TBD*/ +/*static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + + return 0; +} +static int ehci_hcd_au1xxx_drv_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + + return 0; +} +*/ +static struct device_driver ehci_hcd_au1xxx_driver = { + .name = "au1xxx-ehci", + .bus = &platform_bus_type, + .probe = ehci_hcd_au1xxx_drv_probe, + .remove = ehci_hcd_au1xxx_drv_remove, + /*.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-hcd.c b/drivers/usb/host/ehci-hcd.c index 8730babb5771..79f2d8b9bfb6 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -889,14 +889,19 @@ MODULE_LICENSE ("GPL"); #ifdef CONFIG_PCI #include "ehci-pci.c" +#define EHCI_BUS_GLUED #endif #ifdef CONFIG_PPC_83xx #include "ehci-fsl.c" +#define EHCI_BUS_GLUED #endif -#if !(defined(CONFIG_PCI) || \ - defined(CONFIG_PPC_83xx) \ - ) +#ifdef CONFIG_SOC_AU1X00 +#include "ehci-au1xxx.c" +#define EHCI_BUS_GLUED +#endif + +#ifndef EHCI_BUS_GLUED #error "missing bus glue for ehci-hcd" #endif diff --git a/include/asm-mips/mach-mips/cpu-feature-overrides.h b/include/asm-mips/mach-mips/cpu-feature-overrides.h index 9f92aed17754..e06af6c86f86 100644 --- a/include/asm-mips/mach-mips/cpu-feature-overrides.h +++ b/include/asm-mips/mach-mips/cpu-feature-overrides.h @@ -29,7 +29,11 @@ /* #define cpu_has_prefetch ? */ #define cpu_has_mcheck 1 /* #define cpu_has_ejtag ? */ +#ifdef CONFIG_CPU_HAS_LLSC #define cpu_has_llsc 1 +#else +#define cpu_has_llsc 0 +#endif /* #define cpu_has_vtag_icache ? */ /* #define cpu_has_dc_aliases ? */ /* #define cpu_has_ic_fills_f_dc ? */ -- cgit v1.2.3-59-g8ed1b From d5fb7f1b5b832946eaf450b2a695ec3e7fd2d351 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 20 Jan 2006 14:09:54 -0800 Subject: [PATCH] USB: OHCI for AU1200 ALCHEMY: Add OHCI support for AU1200 Updated by moving the OHCI support out of the EHCI patch. Signed-off-by: Jordan Crouse Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- arch/mips/au1000/common/platform.c | 2 +- drivers/usb/host/ohci-au1xxx.c | 102 +++++++++++++++++++++++++++++++------ 2 files changed, 88 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c index 1fb3dbdb93be..dbb4ee7ed42d 100644 --- a/arch/mips/au1000/common/platform.c +++ b/arch/mips/au1000/common/platform.c @@ -20,7 +20,7 @@ static struct resource au1xxx_usb_ohci_resources[] = { [0] = { .start = USB_OHCI_BASE, - .end = USB_OHCI_BASE + USB_OHCI_LEN, + .end = USB_OHCI_BASE + USB_OHCI_LEN - 1, .flags = IORESOURCE_MEM, }, [1] = { diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index db280ca7b7a0..a1c8b3b2fcc7 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c @@ -23,6 +23,8 @@ #include +#ifndef CONFIG_SOC_AU1200 + #define USBH_ENABLE_BE (1<<0) #define USBH_ENABLE_C (1<<1) #define USBH_ENABLE_E (1<<2) @@ -37,21 +39,68 @@ #error not byte order defined #endif +#else /* Au1200 */ + +#define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) +#define USB_MCFG_PFEN (1<<31) +#define USB_MCFG_RDCOMB (1<<30) +#define USB_MCFG_SSDEN (1<<23) +#define USB_MCFG_OHCCLKEN (1<<16) +#define USB_MCFG_UCAM (1<<7) +#define USB_MCFG_OBMEN (1<<1) +#define USB_MCFG_OMEMEN (1<<0) + +#define USBH_ENABLE_CE USB_MCFG_OHCCLKEN +#ifdef CONFIG_DMA_COHERENT +#define USBH_ENABLE_INIT (USB_MCFG_OHCCLKEN \ + | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ + | USB_MCFG_SSDEN | USB_MCFG_UCAM \ + | USB_MCFG_OBMEN | USB_MCFG_OMEMEN) +#else +#define USBH_ENABLE_INIT (USB_MCFG_OHCCLKEN \ + | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ + | USB_MCFG_SSDEN \ + | USB_MCFG_OBMEN | USB_MCFG_OMEMEN) +#endif +#define USBH_DISABLE (USB_MCFG_OBMEN | USB_MCFG_OMEMEN) + +#endif /* Au1200 */ + extern int usb_disabled(void); /*-------------------------------------------------------------------------*/ -static void au1xxx_start_hc(struct platform_device *dev) +static void au1xxx_start_ohc(struct platform_device *dev) { printk(KERN_DEBUG __FILE__ ": starting Au1xxx OHCI USB Controller\n"); /* enable host controller */ + +#ifndef CONFIG_SOC_AU1200 + au_writel(USBH_ENABLE_CE, USB_HOST_CONFIG); udelay(1000); au_writel(USBH_ENABLE_INIT, USB_HOST_CONFIG); udelay(1000); +#else /* Au1200 */ + + /* write HW defaults again in case Yamon cleared them */ + if (au_readl(USB_HOST_CONFIG) == 0) { + au_writel(0x00d02000, USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); + udelay(1000); + } + au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); + udelay(1000); + au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); + udelay(1000); + +#endif /* Au1200 */ + /* wait for reset complete (read register twice; see au1500 errata) */ while (au_readl(USB_HOST_CONFIG), !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD)) @@ -61,13 +110,25 @@ static void au1xxx_start_hc(struct platform_device *dev) ": Clock to USB host has been enabled \n"); } -static void au1xxx_stop_hc(struct platform_device *dev) +static void au1xxx_stop_ohc(struct platform_device *dev) { printk(KERN_DEBUG __FILE__ ": stopping Au1xxx OHCI USB Controller\n"); +#ifndef CONFIG_SOC_AU1200 + /* Disable clock */ au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); + +#else /* Au1200 */ + + /* Disable mem */ + au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); + udelay(1000); + /* Disable clock */ + au_writel(~USBH_ENABLE_CE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); + au_readl(USB_HOST_CONFIG); +#endif /* Au1200 */ } @@ -78,7 +139,7 @@ static void au1xxx_stop_hc(struct platform_device *dev) /** - * usb_hcd_au1xxx_probe - initialize Au1xxx-based HCDs + * usb_ohci_au1xxx_probe - initialize Au1xxx-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and @@ -86,14 +147,25 @@ static void au1xxx_stop_hc(struct platform_device *dev) * through the hotplug entry's driver_data. * */ -int usb_hcd_au1xxx_probe (const struct hc_driver *driver, +static int usb_ohci_au1xxx_probe(const struct hc_driver *driver, struct platform_device *dev) { int retval; struct usb_hcd *hcd; - if(dev->resource[1].flags != IORESOURCE_IRQ) { - pr_debug ("resource[1] is not IORESOURCE_IRQ"); +#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) + /* Au1200 AB USB does not support coherent memory */ + if (!(read_c0_prid() & 0xff)) { + pr_info("%s: this is chip revision AB !!\n", + dev->dev.name); + pr_info("%s: update your board or re-configure the kernel\n", + dev->dev.name); + return -ENODEV; + } +#endif + + if (dev->resource[1].flags != IORESOURCE_IRQ) { + pr_debug("resource[1] is not IORESOURCE_IRQ\n"); return -ENOMEM; } @@ -104,26 +176,26 @@ int usb_hcd_au1xxx_probe (const struct hc_driver *driver, hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("request_mem_region failed"); + pr_debug("request_mem_region failed\n"); retval = -EBUSY; goto err1; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { - pr_debug("ioremap failed"); + pr_debug("ioremap failed\n"); retval = -ENOMEM; goto err2; } - au1xxx_start_hc(dev); + au1xxx_start_ohc(dev); ohci_hcd_init(hcd_to_ohci(hcd)); - retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); + retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT | SA_SHIRQ); if (retval == 0) return retval; - au1xxx_stop_hc(dev); + au1xxx_stop_ohc(dev); iounmap(hcd->regs); err2: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); @@ -146,10 +218,10 @@ int usb_hcd_au1xxx_probe (const struct hc_driver *driver, * context, normally "rmmod", "apmd", or something similar. * */ -void usb_hcd_au1xxx_remove (struct usb_hcd *hcd, struct platform_device *dev) +static void usb_ohci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev) { usb_remove_hcd(hcd); - au1xxx_stop_hc(dev); + au1xxx_stop_ohc(dev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); @@ -235,7 +307,7 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) if (usb_disabled()) return -ENODEV; - ret = usb_hcd_au1xxx_probe(&ohci_au1xxx_hc_driver, pdev); + ret = usb_ohci_au1xxx_probe(&ohci_au1xxx_hc_driver, pdev); return ret; } @@ -243,7 +315,7 @@ static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); - usb_hcd_au1xxx_remove(hcd, pdev); + usb_ohci_au1xxx_remove(hcd, pdev); return 0; } /*TBD*/ -- cgit v1.2.3-59-g8ed1b From d0852299381326c5d8eb67771aa98108050e6901 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 20 Jan 2006 14:35:55 -0800 Subject: [PATCH] USB: EHCI unlink tweaks This patch modifies the behavior of the EHCI driver in an unlink path that seems to be causing various issues on some systems. Those problems have included issues with disconnection, driver unbinding, and similar cases where urb unlinking would just not work right. This patch should help avoid those problems by not turning off the async (control/bulk) schedule until it's not expecting an "async advance" IRQ, which comes from the processing passing the schedule head. Whether the driver attempts to do such things is dependent on system timings, so many folk would never have seen these problems. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 6e28e593c044..5ada7cd5698b 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1022,12 +1022,14 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) /* stop async schedule right now? */ if (unlikely (qh == ehci->async)) { /* can't get here without STS_ASS set */ - if (ehci_to_hcd(ehci)->state != HC_STATE_HALT) { + if (ehci_to_hcd(ehci)->state != HC_STATE_HALT + && !ehci->reclaim) { + /* ... and CMD_IAAD clear */ writel (cmd & ~CMD_ASE, &ehci->regs->command); wmb (); // handshake later, if we need to + timer_action_done (ehci, TIMER_ASYNC_OFF); } - timer_action_done (ehci, TIMER_ASYNC_OFF); return; } -- cgit v1.2.3-59-g8ed1b From 39a269c09f854d3d98cbb755b3568175f04efa10 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Sun, 22 Jan 2006 10:32:13 -0800 Subject: [PATCH] USB: add support for OCHI on AT91rm9200 This adds support for OHCI on AT91rm9200 based boards. Possibly of interest here is the way this uses to gate clocks on/off during system pm state transitions. That's typical for non-PCI systems. Some can go further; Mini-A host side connectors enable ID-pin sensing. From: Andrew Victor Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Kconfig | 1 + drivers/usb/Makefile | 1 + drivers/usb/host/ohci-at91.c | 306 +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ohci-hcd.c | 5 + 4 files changed, 313 insertions(+) create mode 100644 drivers/usb/host/ohci-at91.c (limited to 'drivers') diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 0e865975899f..b1222cd4aa46 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -23,6 +23,7 @@ config USB_ARCH_HAS_OHCI default y if ARCH_LH7A404 default y if ARCH_S3C2410 default y if PXA27x + default y if ARCH_AT91RM9200 # PPC: default y if STB03xxx default y if PPC_MPC52xx diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 7796ecfc0765..bb36a1c1dbb3 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_USB_OHCI_HCD) += host/ obj-$(CONFIG_USB_UHCI_HCD) += host/ obj-$(CONFIG_USB_SL811_HCD) += host/ obj-$(CONFIG_ETRAX_USB_HOST) += host/ +obj-$(CONFIG_USB_OHCI_AT91) += host/ obj-$(CONFIG_USB_ACM) += class/ obj-$(CONFIG_USB_PRINTER) += class/ diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c new file mode 100644 index 000000000000..980030d684d5 --- /dev/null +++ b/drivers/usb/host/ohci-at91.c @@ -0,0 +1,306 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * Copyright (C) 2004 SAN People (Pty) Ltd. + * Copyright (C) 2005 Thibaut VARENE + * + * AT91RM9200 Bus Glue + * + * Based on fragments of 2.4 driver by Rick Bronson. + * Based on ohci-omap.c + * + * This file is licenced under the GPL. + */ + +#include +#include + +#include +#include +#include + +#ifndef CONFIG_ARCH_AT91RM9200 +#error "This file is AT91RM9200 bus glue. CONFIG_ARCH_AT91RM9200 must be defined." +#endif + +/* interface and function clocks */ +static struct clk *iclk, *fclk; + +extern int usb_disabled(void); + +/*-------------------------------------------------------------------------*/ + +static void at91_start_hc(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ohci_regs __iomem *regs = hcd->regs; + + dev_dbg(&pdev->dev, "starting AT91RM9200 OHCI USB Controller\n"); + + /* + * Start the USB clocks. + */ + clk_enable(iclk); + clk_enable(fclk); + + /* + * The USB host controller must remain in reset. + */ + writel(0, ®s->control); +} + +static void at91_stop_hc(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ohci_regs __iomem *regs = hcd->regs; + + dev_dbg(&pdev->dev, "stopping AT91RM9200 OHCI USB Controller\n"); + + /* + * Put the USB host controller into reset. + */ + writel(0, ®s->control); + + /* + * Stop the USB clocks. + */ + clk_disable(fclk); + clk_disable(iclk); +} + + +/*-------------------------------------------------------------------------*/ + +static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + + +/** + * usb_hcd_at91_probe - initialize AT91RM9200-based HCDs + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + * + * Store this function in the HCD's struct pci_driver as probe(). + */ +int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev) +{ + int retval; + struct usb_hcd *hcd = NULL; + + if (pdev->num_resources != 2) { + pr_debug("hcd probe: invalid num_resources"); + return -ENODEV; + } + + if ((pdev->resource[0].flags != IORESOURCE_MEM) || (pdev->resource[1].flags != IORESOURCE_IRQ)) { + pr_debug("hcd probe: invalid resource type\n"); + return -ENODEV; + } + + hcd = usb_create_hcd(driver, &pdev->dev, "at91rm9200"); + if (!hcd) + return -ENOMEM; + hcd->rsrc_start = pdev->resource[0].start; + hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + pr_debug("request_mem_region failed\n"); + retval = -EBUSY; + goto err1; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + pr_debug("ioremap failed\n"); + retval = -EIO; + goto err2; + } + + iclk = clk_get(&pdev->dev, "ohci_clk"); + fclk = clk_get(&pdev->dev, "uhpck"); + + at91_start_hc(pdev); + ohci_hcd_init(hcd_to_ohci(hcd)); + + retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT); + if (retval == 0) + return retval; + + /* Error handling */ + at91_stop_hc(pdev); + + clk_put(fclk); + clk_put(iclk); + + iounmap(hcd->regs); + + err2: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + + err1: + usb_put_hcd(hcd); + return retval; +} + + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * usb_hcd_at91_remove - shutdown processing for AT91RM9200-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_hcd_at91_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + * + */ +static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pdev) +{ + usb_remove_hcd(hcd); + at91_stop_hc(pdev); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + + clk_put(fclk); + clk_put(iclk); + fclk = iclk = NULL; + + dev_set_drvdata(&pdev->dev, NULL); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static int __devinit +ohci_at91_start (struct usb_hcd *hcd) +{ +// struct at91_ohci_data *board = hcd->self.controller->platform_data; + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; + + if ((ret = ohci_init(ohci)) < 0) + return ret; + + if ((ret = ohci_run(ohci)) < 0) { + err("can't start %s", hcd->self.bus_name); + ohci_stop(hcd); + return ret; + } +// hcd->self.root_hub->maxchild = board->ports; + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static const struct hc_driver ohci_at91_hc_driver = { + .description = hcd_name, + .product_desc = "AT91RM9200 OHCI", + .hcd_priv_size = sizeof(struct ohci_hcd), + + /* + * generic hardware linkage + */ + .irq = ohci_irq, + .flags = HCD_USB11 | HCD_MEMORY, + + /* + * basic lifecycle operations + */ + .start = ohci_at91_start, + .stop = ohci_stop, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ohci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ohci_hub_status_data, + .hub_control = ohci_hub_control, + +#ifdef CONFIG_PM + .hub_suspend = ohci_hub_suspend, + .hub_resume = ohci_hub_resume, +#endif + .start_port_reset = ohci_start_port_reset, +}; + +/*-------------------------------------------------------------------------*/ + +static int ohci_hcd_at91_drv_probe(struct platform_device *dev) +{ + return usb_hcd_at91_probe(&ohci_at91_hc_driver, dev); +} + +static int ohci_hcd_at91_drv_remove(struct platform_device *dev) +{ + return usb_hcd_at91_remove(platform_get_drvdata(dev), dev); +} + +#ifdef CONFIG_PM +static int ohci_hcd_at91_drv_suspend(struct platform_device *dev, u32 state, u32 level) +{ + printk("%s(%s:%d): not implemented yet\n", + __func__, __FILE__, __LINE__); + + clk_disable(fclk); + + return 0; +} + +static int ohci_hcd_at91_drv_resume(struct platform_device *dev, u32 state) +{ + printk("%s(%s:%d): not implemented yet\n", + __func__, __FILE__, __LINE__); + + clk_enable(fclk); + + return 0; +} +#else +#define ohci_hcd_at91_drv_suspend NULL +#define ohci_hcd_at91_drv_resume NULL +#endif + +static struct platform_driver ohci_hcd_at91_driver = { + .probe = ohci_hcd_at91_drv_probe, + .remove = ohci_hcd_at91_drv_remove, + .suspend = ohci_hcd_at91_drv_suspend, + .resume = ohci_hcd_at91_drv_resume, + .driver = { + .name = "at91rm9200-ohci", + .owner = THIS_MODULE, + }, +}; + +static int __init ohci_hcd_at91_init (void) +{ + if (usb_disabled()) + return -ENODEV; + + return platform_driver_register(&ohci_hcd_at91_driver); +} + +static void __exit ohci_hcd_at91_cleanup (void) +{ + platform_driver_unregister(&ohci_hcd_at91_driver); +} + +module_init (ohci_hcd_at91_init); +module_exit (ohci_hcd_at91_cleanup); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index a4b12404ae08..2990be269000 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -905,6 +905,10 @@ MODULE_LICENSE ("GPL"); #include "ohci-ppc-soc.c" #endif +#ifdef CONFIG_ARCH_AT91RM9200 +#include "ohci-at91.c" +#endif + #if !(defined(CONFIG_PCI) \ || defined(CONFIG_SA1111) \ || defined(CONFIG_ARCH_S3C2410) \ @@ -913,6 +917,7 @@ MODULE_LICENSE ("GPL"); || defined (CONFIG_PXA27x) \ || defined (CONFIG_SOC_AU1X00) \ || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ + || defined (CONFIG_ARCH_AT91RM9200) \ ) #error "missing bus glue for ohci-hcd" #endif -- cgit v1.2.3-59-g8ed1b From bae4bd848dc0b7e6defc7a5d62834a35d1eed06d Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 22 Jan 2006 10:32:37 -0800 Subject: [PATCH] USB: add support for AT91 gadget This adds support for the USB peripheral controller on AT91 (rm9200, eventually also sam9261 or uClinux) platforms. More SOC support for Linux-USB ... an uncomplicated pure PIO driver. It'd be worth using this as a model, if you're starting a driver for some other peripheral controller. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 17 + drivers/usb/gadget/Makefile | 1 + drivers/usb/gadget/at91_udc.c | 1773 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/at91_udc.h | 181 +++++ 4 files changed, 1972 insertions(+) create mode 100644 drivers/usb/gadget/at91_udc.c create mode 100644 drivers/usb/gadget/at91_udc.h (limited to 'drivers') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index ff075a53c8d6..d80f71877d68 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -187,6 +187,23 @@ config USB_OTG Select this only if your OMAP board has a Mini-AB connector. +config USB_GADGET_AT91 + boolean "AT91 USB Device Port" + depends on ARCH_AT91RM9200 + select USB_GADGET_SELECTED + help + Many Atmel AT91 processors (such as the AT91RM2000) have a + full speed USB Device Port with support for five configurable + endpoints (plus endpoint zero). + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "at91_udc" and force all + gadget drivers to also be dynamically linked. + +config USB_AT91 + tristate + depends on USB_GADGET_AT91 + default USB_GADGET config USB_GADGET_DUMMY_HCD boolean "Dummy HCD (DEVELOPMENT)" diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index d5fd04d886e6..5a28e61392ec 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o obj-$(CONFIG_USB_GOKU) += goku_udc.o obj-$(CONFIG_USB_OMAP) += omap_udc.o obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o +obj-$(CONFIG_USB_AT91) += at91_udc.o # # USB gadget drivers diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c new file mode 100644 index 000000000000..865858cfd1c2 --- /dev/null +++ b/drivers/usb/gadget/at91_udc.c @@ -0,0 +1,1773 @@ +/* + * at91_udc -- driver for at91-series USB peripheral controller + * + * Copyright (C) 2004 by Thomas Rathbone + * Copyright (C) 2005 by HP Labs + * Copyright (C) 2005 by 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. + * + * 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. + */ + +#undef DEBUG +#undef VERBOSE +#undef PACKET_TRACE + +#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 "at91_udc.h" + + +/* + * This controller is simple and PIO-only. It's used in many AT91-series + * ARMv4T controllers, including the at91rm9200 (arm920T, with MMU), + * at91sam9261 (arm926ejs, with MMU), and several no-mmu versions. + * + * This driver expects the board has been wired with two GPIOs suppporting + * a VBUS sensing IRQ, and a D+ pullup. (They may be omitted, but the + * testing hasn't covered such cases.) The pullup is most important; it + * provides software control over whether the host enumerates the device. + * The VBUS sensing helps during enumeration, and allows both USB clocks + * (and the transceiver) to stay gated off until they're necessary, saving + * power. During USB suspend, the 48 MHz clock is gated off. + */ + +#define DRIVER_VERSION "8 March 2005" + +static const char driver_name [] = "at91_udc"; +static const char ep0name[] = "ep0"; + +/*-------------------------------------------------------------------------*/ + +/* + * Read from a UDP register. + */ +static inline unsigned long at91_udp_read(unsigned int reg) +{ + void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP; + + return __raw_readl(udp_base + reg); +} + +/* + * Write to a UDP register. + */ +static inline void at91_udp_write(unsigned int reg, unsigned long value) +{ + void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP; + + __raw_writel(value, udp_base + reg); +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + +#include + +static const char debug_filename[] = "driver/udc"; + +#define FOURBITS "%s%s%s%s" +#define EIGHTBITS FOURBITS FOURBITS + +static void proc_ep_show(struct seq_file *s, struct at91_ep *ep) +{ + static char *types[] = { + "control", "out-iso", "out-bulk", "out-int", + "BOGUS", "in-iso", "in-bulk", "in-int"}; + + u32 csr; + struct at91_request *req; + unsigned long flags; + + local_irq_save(flags); + + csr = __raw_readl(ep->creg); + + /* NOTE: not collecting per-endpoint irq statistics... */ + + seq_printf(s, "\n"); + seq_printf(s, "%s, maxpacket %d %s%s %s%s\n", + ep->ep.name, ep->ep.maxpacket, + ep->is_in ? "in" : "out", + ep->is_iso ? " iso" : "", + ep->is_pingpong + ? (ep->fifo_bank ? "pong" : "ping") + : "", + ep->stopped ? " stopped" : ""); + seq_printf(s, "csr %08x rxbytes=%d %s %s %s" EIGHTBITS "\n", + csr, + (csr & 0x07ff0000) >> 16, + (csr & (1 << 15)) ? "enabled" : "disabled", + (csr & (1 << 11)) ? "DATA1" : "DATA0", + types[(csr & 0x700) >> 8], + + /* iff type is control then print current direction */ + (!(csr & 0x700)) + ? ((csr & (1 << 7)) ? " IN" : " OUT") + : "", + (csr & (1 << 6)) ? " rxdatabk1" : "", + (csr & (1 << 5)) ? " forcestall" : "", + (csr & (1 << 4)) ? " txpktrdy" : "", + + (csr & (1 << 3)) ? " stallsent" : "", + (csr & (1 << 2)) ? " rxsetup" : "", + (csr & (1 << 1)) ? " rxdatabk0" : "", + (csr & (1 << 0)) ? " txcomp" : ""); + if (list_empty (&ep->queue)) + seq_printf(s, "\t(queue empty)\n"); + + else list_for_each_entry (req, &ep->queue, queue) { + unsigned length = req->req.actual; + + seq_printf(s, "\treq %p len %d/%d buf %p\n", + &req->req, length, + req->req.length, req->req.buf); + } + local_irq_restore(flags); +} + +static void proc_irq_show(struct seq_file *s, const char *label, u32 mask) +{ + int i; + + seq_printf(s, "%s %04x:%s%s" FOURBITS, label, mask, + (mask & (1 << 13)) ? " wakeup" : "", + (mask & (1 << 12)) ? " endbusres" : "", + + (mask & (1 << 11)) ? " sofint" : "", + (mask & (1 << 10)) ? " extrsm" : "", + (mask & (1 << 9)) ? " rxrsm" : "", + (mask & (1 << 8)) ? " rxsusp" : ""); + for (i = 0; i < 8; i++) { + if (mask & (1 << i)) + seq_printf(s, " ep%d", i); + } + seq_printf(s, "\n"); +} + +static int proc_udc_show(struct seq_file *s, void *unused) +{ + struct at91_udc *udc = s->private; + struct at91_ep *ep; + u32 tmp; + + seq_printf(s, "%s: version %s\n", driver_name, DRIVER_VERSION); + + seq_printf(s, "vbus %s, pullup %s, %s powered%s, gadget %s\n\n", + udc->vbus ? "present" : "off", + udc->enabled + ? (udc->vbus ? "active" : "enabled") + : "disabled", + udc->selfpowered ? "self" : "VBUS", + udc->suspended ? ", suspended" : "", + udc->driver ? udc->driver->driver.name : "(none)"); + + /* don't access registers when interface isn't clocked */ + if (!udc->clocked) { + seq_printf(s, "(not clocked)\n"); + return 0; + } + + tmp = at91_udp_read(AT91_UDP_FRM_NUM); + seq_printf(s, "frame %05x:%s%s frame=%d\n", tmp, + (tmp & AT91_UDP_FRM_OK) ? " ok" : "", + (tmp & AT91_UDP_FRM_ERR) ? " err" : "", + (tmp & AT91_UDP_NUM)); + + tmp = at91_udp_read(AT91_UDP_GLB_STAT); + seq_printf(s, "glbstate %02x:%s" FOURBITS "\n", tmp, + (tmp & AT91_UDP_RMWUPE) ? " rmwupe" : "", + (tmp & AT91_UDP_RSMINPR) ? " rsminpr" : "", + (tmp & AT91_UDP_ESR) ? " esr" : "", + (tmp & AT91_UDP_CONFG) ? " confg" : "", + (tmp & AT91_UDP_FADDEN) ? " fadden" : ""); + + tmp = at91_udp_read(AT91_UDP_FADDR); + seq_printf(s, "faddr %03x:%s fadd=%d\n", tmp, + (tmp & AT91_UDP_FEN) ? " fen" : "", + (tmp & AT91_UDP_FADD)); + + proc_irq_show(s, "imr ", at91_udp_read(AT91_UDP_IMR)); + proc_irq_show(s, "isr ", at91_udp_read(AT91_UDP_ISR)); + + if (udc->enabled && udc->vbus) { + proc_ep_show(s, &udc->ep[0]); + list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { + if (ep->desc) + proc_ep_show(s, ep); + } + } + return 0; +} + +static int proc_udc_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_udc_show, PDE(inode)->data); +} + +static struct file_operations proc_ops = { + .open = proc_udc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void create_debug_file(struct at91_udc *udc) +{ + struct proc_dir_entry *pde; + + pde = create_proc_entry (debug_filename, 0, NULL); + udc->pde = pde; + if (pde == NULL) + return; + + pde->proc_fops = &proc_ops; + pde->data = udc; +} + +static void remove_debug_file(struct at91_udc *udc) +{ + if (udc->pde) + remove_proc_entry(debug_filename, NULL); +} + +#else + +static inline void create_debug_file(struct at91_udc *udc) {} +static inline void remove_debug_file(struct at91_udc *udc) {} + +#endif + + +/*-------------------------------------------------------------------------*/ + +static void done(struct at91_ep *ep, struct at91_request *req, int status) +{ + unsigned stopped = ep->stopped; + + list_del_init(&req->queue); + if (req->req.status == -EINPROGRESS) + req->req.status = status; + else + status = req->req.status; + if (status && status != -ESHUTDOWN) + VDBG("%s done %p, status %d\n", ep->ep.name, req, status); + + ep->stopped = 1; + req->req.complete(&ep->ep, &req->req); + ep->stopped = stopped; + + /* ep0 is always ready; other endpoints need a non-empty queue */ + if (list_empty(&ep->queue) && ep->int_mask != (1 << 0)) + at91_udp_write(AT91_UDP_IDR, ep->int_mask); +} + +/*-------------------------------------------------------------------------*/ + +/* bits indicating OUT fifo has data ready */ +#define RX_DATA_READY (AT91_UDP_RX_DATA_BK0 | AT91_UDP_RX_DATA_BK1) + +/* + * Endpoint FIFO CSR bits have a mix of bits, making it unsafe to just write + * back most of the value you just read (because of side effects, including + * bits that may change after reading and before writing). + * + * Except when changing a specific bit, always write values which: + * - clear SET_FX bits (setting them could change something) + * - set CLR_FX bits (clearing them could change something) + * + * There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE + * that shouldn't normally be changed. + */ +#define SET_FX (AT91_UDP_TXPKTRDY) +#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP) + +/* pull OUT packet data from the endpoint's fifo */ +static int read_fifo (struct at91_ep *ep, struct at91_request *req) +{ + u32 __iomem *creg = ep->creg; + u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0)); + u32 csr; + u8 *buf; + unsigned int count, bufferspace, is_done; + + buf = req->req.buf + req->req.actual; + bufferspace = req->req.length - req->req.actual; + + /* + * there might be nothing to read if ep_queue() calls us, + * or if we already emptied both pingpong buffers + */ +rescan: + csr = __raw_readl(creg); + if ((csr & RX_DATA_READY) == 0) + return 0; + + count = (csr & AT91_UDP_RXBYTECNT) >> 16; + if (count > ep->ep.maxpacket) + count = ep->ep.maxpacket; + if (count > bufferspace) { + DBG("%s buffer overflow\n", ep->ep.name); + req->req.status = -EOVERFLOW; + count = bufferspace; + } + __raw_readsb(dreg, buf, count); + + /* release and swap pingpong mem bank */ + csr |= CLR_FX; + if (ep->is_pingpong) { + if (ep->fifo_bank == 0) { + csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0); + ep->fifo_bank = 1; + } else { + csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK1); + ep->fifo_bank = 0; + } + } else + csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0); + __raw_writel(csr, creg); + + req->req.actual += count; + is_done = (count < ep->ep.maxpacket); + if (count == bufferspace) + is_done = 1; + + PACKET("%s %p out/%d%s\n", ep->ep.name, &req->req, count, + is_done ? " (done)" : ""); + + /* + * avoid extra trips through IRQ logic for packets already in + * the fifo ... maybe preventing an extra (expensive) OUT-NAK + */ + if (is_done) + done(ep, req, 0); + else if (ep->is_pingpong) { + bufferspace -= count; + buf += count; + goto rescan; + } + + return is_done; +} + +/* load fifo for an IN packet */ +static int write_fifo(struct at91_ep *ep, struct at91_request *req) +{ + u32 __iomem *creg = ep->creg; + u32 csr = __raw_readl(creg); + u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0)); + unsigned total, count, is_last; + + /* + * TODO: allow for writing two packets to the fifo ... that'll + * reduce the amount of IN-NAKing, but probably won't affect + * throughput much. (Unlike preventing OUT-NAKing!) + */ + + /* + * If ep_queue() calls us, the queue is empty and possibly in + * odd states like TXCOMP not yet cleared (we do it, saving at + * least one IRQ) or the fifo not yet being free. Those aren't + * issues normally (IRQ handler fast path). + */ + if (unlikely(csr & (AT91_UDP_TXCOMP | AT91_UDP_TXPKTRDY))) { + if (csr & AT91_UDP_TXCOMP) { + csr |= CLR_FX; + csr &= ~(SET_FX | AT91_UDP_TXCOMP); + __raw_writel(csr, creg); + csr = __raw_readl(creg); + } + if (csr & AT91_UDP_TXPKTRDY) + return 0; + } + + total = req->req.length - req->req.actual; + if (ep->ep.maxpacket < total) { + count = ep->ep.maxpacket; + is_last = 0; + } else { + count = total; + is_last = (count < ep->ep.maxpacket) || !req->req.zero; + } + + /* + * Write the packet, maybe it's a ZLP. + * + * NOTE: incrementing req->actual before we receive the ACK means + * gadget driver IN bytecounts can be wrong in fault cases. That's + * fixable with PIO drivers like this one (save "count" here, and + * do the increment later on TX irq), but not for most DMA hardware. + * + * So all gadget drivers must accept that potential error. Some + * hardware supports precise fifo status reporting, letting them + * recover when the actual bytecount matters (e.g. for USB Test + * and Measurement Class devices). + */ + __raw_writesb(dreg, req->req.buf + req->req.actual, count); + csr &= ~SET_FX; + csr |= CLR_FX | AT91_UDP_TXPKTRDY; + __raw_writel(csr, creg); + req->req.actual += count; + + PACKET("%s %p in/%d%s\n", ep->ep.name, &req->req, count, + is_last ? " (done)" : ""); + if (is_last) + done(ep, req, 0); + return is_last; +} + +static void nuke(struct at91_ep *ep, int status) +{ + struct at91_request *req; + + // terminer chaque requete dans la queue + ep->stopped = 1; + if (list_empty(&ep->queue)) + return; + + VDBG("%s %s\n", __FUNCTION__, ep->ep.name); + while (!list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, struct at91_request, queue); + done(ep, req, status); + } +} + +/*-------------------------------------------------------------------------*/ + +static int at91_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) +{ + struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); + struct at91_udc *dev = ep->udc; + u16 maxpacket; + u32 tmp; + unsigned long flags; + + if (!_ep || !ep + || !desc || ep->desc + || _ep->name == ep0name + || desc->bDescriptorType != USB_DT_ENDPOINT + || (maxpacket = le16_to_cpu(desc->wMaxPacketSize)) == 0 + || maxpacket > ep->maxpacket) { + DBG("bad ep or descriptor\n"); + return -EINVAL; + } + + if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { + DBG("bogus device state\n"); + return -ESHUTDOWN; + } + + tmp = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + switch (tmp) { + case USB_ENDPOINT_XFER_CONTROL: + DBG("only one control endpoint\n"); + return -EINVAL; + case USB_ENDPOINT_XFER_INT: + if (maxpacket > 64) + goto bogus_max; + break; + case USB_ENDPOINT_XFER_BULK: + switch (maxpacket) { + case 8: + case 16: + case 32: + case 64: + goto ok; + } +bogus_max: + DBG("bogus maxpacket %d\n", maxpacket); + return -EINVAL; + case USB_ENDPOINT_XFER_ISOC: + if (!ep->is_pingpong) { + DBG("iso requires double buffering\n"); + return -EINVAL; + } + break; + } + +ok: + local_irq_save(flags); + + /* initialize endpoint to match this descriptor */ + ep->is_in = (desc->bEndpointAddress & USB_DIR_IN) != 0; + ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC); + ep->stopped = 0; + if (ep->is_in) + tmp |= 0x04; + tmp <<= 8; + tmp |= AT91_UDP_EPEDS; + __raw_writel(tmp, ep->creg); + + ep->desc = desc; + ep->ep.maxpacket = maxpacket; + + /* + * reset/init endpoint fifo. NOTE: leaves fifo_bank alone, + * since endpoint resets don't reset hw pingpong state. + */ + at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); + at91_udp_write(AT91_UDP_RST_EP, 0); + + local_irq_restore(flags); + return 0; +} + +static int at91_ep_disable (struct usb_ep * _ep) +{ + struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); + unsigned long flags; + + if (ep == &ep->udc->ep[0]) + return -EINVAL; + + local_irq_save(flags); + + nuke(ep, -ESHUTDOWN); + + /* restore the endpoint's pristine config */ + ep->desc = NULL; + ep->ep.maxpacket = ep->maxpacket; + + /* reset fifos and endpoint */ + if (ep->udc->clocked) { + at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); + at91_udp_write(AT91_UDP_RST_EP, 0); + __raw_writel(0, ep->creg); + } + + local_irq_restore(flags); + return 0; +} + +/* + * this is a PIO-only driver, so there's nothing + * interesting for request or buffer allocation. + */ + +static struct usb_request *at91_ep_alloc_request (struct usb_ep *_ep, unsigned int gfp_flags) +{ + struct at91_request *req; + + req = kcalloc(1, sizeof (struct at91_request), SLAB_KERNEL); + if (!req) + return NULL; + + INIT_LIST_HEAD(&req->queue); + return &req->req; +} + +static void at91_ep_free_request(struct usb_ep *_ep, struct usb_request *_req) +{ + struct at91_request *req; + + req = container_of(_req, struct at91_request, req); + BUG_ON(!list_empty(&req->queue)); + kfree(req); +} + +static void *at91_ep_alloc_buffer( + struct usb_ep *_ep, + unsigned bytes, + dma_addr_t *dma, + gfp_t gfp_flags) +{ + *dma = ~0; + return kmalloc(bytes, gfp_flags); +} + +static void at91_ep_free_buffer( + struct usb_ep *ep, + void *buf, + dma_addr_t dma, + unsigned bytes) +{ + kfree(buf); +} + +static int at91_ep_queue(struct usb_ep *_ep, + struct usb_request *_req, gfp_t gfp_flags) +{ + struct at91_request *req; + struct at91_ep *ep; + struct at91_udc *dev; + int status; + unsigned long flags; + + req = container_of(_req, struct at91_request, req); + ep = container_of(_ep, struct at91_ep, ep); + + if (!_req || !_req->complete + || !_req->buf || !list_empty(&req->queue)) { + DBG("invalid request\n"); + return -EINVAL; + } + + if (!_ep || (!ep->desc && ep->ep.name != ep0name)) { + DBG("invalid ep\n"); + return -EINVAL; + } + + dev = ep->udc; + + if (!dev || !dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { + DBG("invalid device\n"); + return -EINVAL; + } + + _req->status = -EINPROGRESS; + _req->actual = 0; + + local_irq_save(flags); + + /* try to kickstart any empty and idle queue */ + if (list_empty(&ep->queue) && !ep->stopped) { + int is_ep0; + + /* + * If this control request has a non-empty DATA stage, this + * will start that stage. It works just like a non-control + * request (until the status stage starts, maybe early). + * + * If the data stage is empty, then this starts a successful + * IN/STATUS stage. (Unsuccessful ones use set_halt.) + */ + is_ep0 = (ep->ep.name == ep0name); + if (is_ep0) { + u32 tmp; + + if (!dev->req_pending) { + status = -EINVAL; + goto done; + } + + /* + * defer changing CONFG until after the gadget driver + * reconfigures the endpoints. + */ + if (dev->wait_for_config_ack) { + tmp = at91_udp_read(AT91_UDP_GLB_STAT); + tmp ^= AT91_UDP_CONFG; + VDBG("toggle config\n"); + at91_udp_write(AT91_UDP_GLB_STAT, tmp); + } + if (req->req.length == 0) { +ep0_in_status: + PACKET("ep0 in/status\n"); + status = 0; + tmp = __raw_readl(ep->creg); + tmp &= ~SET_FX; + tmp |= CLR_FX | AT91_UDP_TXPKTRDY; + __raw_writel(tmp, ep->creg); + dev->req_pending = 0; + goto done; + } + } + + if (ep->is_in) + status = write_fifo(ep, req); + else { + status = read_fifo(ep, req); + + /* IN/STATUS stage is otherwise triggered by irq */ + if (status && is_ep0) + goto ep0_in_status; + } + } else + status = 0; + + if (req && !status) { + list_add_tail (&req->queue, &ep->queue); + at91_udp_write(AT91_UDP_IER, ep->int_mask); + } +done: + local_irq_restore(flags); + return (status < 0) ? status : 0; +} + +static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) +{ + struct at91_ep *ep; + struct at91_request *req; + + ep = container_of(_ep, struct at91_ep, ep); + if (!_ep || ep->ep.name == ep0name) + return -EINVAL; + + /* make sure it's actually queued on this endpoint */ + list_for_each_entry (req, &ep->queue, queue) { + if (&req->req == _req) + break; + } + if (&req->req != _req) + return -EINVAL; + + done(ep, req, -ECONNRESET); + return 0; +} + +static int at91_ep_set_halt(struct usb_ep *_ep, int value) +{ + struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); + u32 __iomem *creg; + u32 csr; + unsigned long flags; + int status = 0; + + if (!_ep || ep->is_iso || !ep->udc->clocked) + return -EINVAL; + + creg = ep->creg; + local_irq_save(flags); + + csr = __raw_readl(creg); + + /* + * fail with still-busy IN endpoints, ensuring correct sequencing + * of data tx then stall. note that the fifo rx bytecount isn't + * completely accurate as a tx bytecount. + */ + if (ep->is_in && (!list_empty(&ep->queue) || (csr >> 16) != 0)) + status = -EAGAIN; + else { + csr |= CLR_FX; + csr &= ~SET_FX; + if (value) { + csr |= AT91_UDP_FORCESTALL; + VDBG("halt %s\n", ep->ep.name); + } else { + at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); + at91_udp_write(AT91_UDP_RST_EP, 0); + csr &= ~AT91_UDP_FORCESTALL; + } + __raw_writel(csr, creg); + } + + local_irq_restore(flags); + return status; +} + +static struct usb_ep_ops at91_ep_ops = { + .enable = at91_ep_enable, + .disable = at91_ep_disable, + .alloc_request = at91_ep_alloc_request, + .free_request = at91_ep_free_request, + .alloc_buffer = at91_ep_alloc_buffer, + .free_buffer = at91_ep_free_buffer, + .queue = at91_ep_queue, + .dequeue = at91_ep_dequeue, + .set_halt = at91_ep_set_halt, + // there's only imprecise fifo status reporting +}; + +/*-------------------------------------------------------------------------*/ + +static int at91_get_frame(struct usb_gadget *gadget) +{ + if (!to_udc(gadget)->clocked) + return -EINVAL; + return at91_udp_read(AT91_UDP_FRM_NUM) & AT91_UDP_NUM; +} + +static int at91_wakeup(struct usb_gadget *gadget) +{ + struct at91_udc *udc = to_udc(gadget); + u32 glbstate; + int status = -EINVAL; + unsigned long flags; + + DBG("%s\n", __FUNCTION__ ); + local_irq_save(flags); + + if (!udc->clocked || !udc->suspended) + goto done; + + /* NOTE: some "early versions" handle ESR differently ... */ + + glbstate = at91_udp_read(AT91_UDP_GLB_STAT); + if (!(glbstate & AT91_UDP_ESR)) + goto done; + glbstate |= AT91_UDP_ESR; + at91_udp_write(AT91_UDP_GLB_STAT, glbstate); + +done: + local_irq_restore(flags); + return status; +} + +/* reinit == restore inital software state */ +static void udc_reinit(struct at91_udc *udc) +{ + u32 i; + + INIT_LIST_HEAD(&udc->gadget.ep_list); + INIT_LIST_HEAD(&udc->gadget.ep0->ep_list); + + for (i = 0; i < NUM_ENDPOINTS; i++) { + struct at91_ep *ep = &udc->ep[i]; + + if (i != 0) + list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); + ep->desc = NULL; + ep->stopped = 0; + ep->fifo_bank = 0; + ep->ep.maxpacket = ep->maxpacket; + // initialiser une queue par endpoint + INIT_LIST_HEAD(&ep->queue); + } +} + +static void stop_activity(struct at91_udc *udc) +{ + struct usb_gadget_driver *driver = udc->driver; + int i; + + if (udc->gadget.speed == USB_SPEED_UNKNOWN) + driver = NULL; + udc->gadget.speed = USB_SPEED_UNKNOWN; + + for (i = 0; i < NUM_ENDPOINTS; i++) { + struct at91_ep *ep = &udc->ep[i]; + ep->stopped = 1; + nuke(ep, -ESHUTDOWN); + } + if (driver) + driver->disconnect(&udc->gadget); + + udc_reinit(udc); +} + +static void clk_on(struct at91_udc *udc) +{ + if (udc->clocked) + return; + udc->clocked = 1; + clk_enable(udc->iclk); + clk_enable(udc->fclk); +} + +static void clk_off(struct at91_udc *udc) +{ + if (!udc->clocked) + return; + udc->clocked = 0; + udc->gadget.speed = USB_SPEED_UNKNOWN; + clk_disable(udc->iclk); + clk_disable(udc->fclk); +} + +/* + * activate/deactivate link with host; minimize power usage for + * inactive links by cutting clocks and transceiver power. + */ +static void pullup(struct at91_udc *udc, int is_on) +{ + if (!udc->enabled || !udc->vbus) + is_on = 0; + DBG("%sactive\n", is_on ? "" : "in"); + if (is_on) { + clk_on(udc); + at91_udp_write(AT91_UDP_TXVC, 0); + at91_set_gpio_value(udc->board.pullup_pin, 1); + } else { + stop_activity(udc); + at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); + at91_set_gpio_value(udc->board.pullup_pin, 0); + clk_off(udc); + + // REVISIT: with transceiver disabled, will D- float + // so that a host would falsely detect a device? + } +} + +/* vbus is here! turn everything on that's ready */ +static int at91_vbus_session(struct usb_gadget *gadget, int is_active) +{ + struct at91_udc *udc = to_udc(gadget); + unsigned long flags; + + // VDBG("vbus %s\n", is_active ? "on" : "off"); + local_irq_save(flags); + udc->vbus = (is_active != 0); + pullup(udc, is_active); + local_irq_restore(flags); + return 0; +} + +static int at91_pullup(struct usb_gadget *gadget, int is_on) +{ + struct at91_udc *udc = to_udc(gadget); + unsigned long flags; + + local_irq_save(flags); + udc->enabled = is_on = !!is_on; + pullup(udc, is_on); + local_irq_restore(flags); + return 0; +} + +static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on) +{ + struct at91_udc *udc = to_udc(gadget); + unsigned long flags; + + local_irq_save(flags); + udc->selfpowered = (is_on != 0); + local_irq_restore(flags); + return 0; +} + +static const struct usb_gadget_ops at91_udc_ops = { + .get_frame = at91_get_frame, + .wakeup = at91_wakeup, + .set_selfpowered = at91_set_selfpowered, + .vbus_session = at91_vbus_session, + .pullup = at91_pullup, + + /* + * VBUS-powered devices may also also want to support bigger + * power budgets after an appropriate SET_CONFIGURATION. + */ + // .vbus_power = at91_vbus_power, +}; + +/*-------------------------------------------------------------------------*/ + +static int handle_ep(struct at91_ep *ep) +{ + struct at91_request *req; + u32 __iomem *creg = ep->creg; + u32 csr = __raw_readl(creg); + + if (!list_empty(&ep->queue)) + req = list_entry(ep->queue.next, + struct at91_request, queue); + else + req = NULL; + + if (ep->is_in) { + if (csr & (AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)) { + csr |= CLR_FX; + csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP); + __raw_writel(csr, creg); + } + if (req) + return write_fifo(ep, req); + + } else { + if (csr & AT91_UDP_STALLSENT) { + /* STALLSENT bit == ISOERR */ + if (ep->is_iso && req) + req->req.status = -EILSEQ; + csr |= CLR_FX; + csr &= ~(SET_FX | AT91_UDP_STALLSENT); + __raw_writel(csr, creg); + csr = __raw_readl(creg); + } + if (req && (csr & RX_DATA_READY)) + return read_fifo(ep, req); + } + return 0; +} + +union setup { + u8 raw[8]; + struct usb_ctrlrequest r; +}; + +static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) +{ + u32 __iomem *creg = ep->creg; + u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0)); + unsigned rxcount, i = 0; + u32 tmp; + union setup pkt; + int status = 0; + + /* read and ack SETUP; hard-fail for bogus packets */ + rxcount = (csr & AT91_UDP_RXBYTECNT) >> 16; + if (likely(rxcount == 8)) { + while (rxcount--) + pkt.raw[i++] = __raw_readb(dreg); + if (pkt.r.bRequestType & USB_DIR_IN) { + csr |= AT91_UDP_DIR; + ep->is_in = 1; + } else { + csr &= ~AT91_UDP_DIR; + ep->is_in = 0; + } + } else { + // REVISIT this happens sometimes under load; why?? + ERR("SETUP len %d, csr %08x\n", rxcount, csr); + status = -EINVAL; + } + csr |= CLR_FX; + csr &= ~(SET_FX | AT91_UDP_RXSETUP); + __raw_writel(csr, creg); + udc->wait_for_addr_ack = 0; + udc->wait_for_config_ack = 0; + ep->stopped = 0; + if (unlikely(status != 0)) + goto stall; + +#define w_index le16_to_cpu(pkt.r.wIndex) +#define w_value le16_to_cpu(pkt.r.wValue) +#define w_length le16_to_cpu(pkt.r.wLength) + + VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n", + pkt.r.bRequestType, pkt.r.bRequest, + w_value, w_index, w_length); + + /* + * A few standard requests get handled here, ones that touch + * hardware ... notably for device and endpoint features. + */ + udc->req_pending = 1; + csr = __raw_readl(creg); + csr |= CLR_FX; + csr &= ~SET_FX; + switch ((pkt.r.bRequestType << 8) | pkt.r.bRequest) { + + case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) + | USB_REQ_SET_ADDRESS: + __raw_writel(csr | AT91_UDP_TXPKTRDY, creg); + udc->addr = w_value; + udc->wait_for_addr_ack = 1; + udc->req_pending = 0; + /* FADDR is set later, when we ack host STATUS */ + return; + + case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) + | USB_REQ_SET_CONFIGURATION: + tmp = at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_CONFG; + if (pkt.r.wValue) + udc->wait_for_config_ack = (tmp == 0); + else + udc->wait_for_config_ack = (tmp != 0); + if (udc->wait_for_config_ack) + VDBG("wait for config\n"); + /* CONFG is toggled later, if gadget driver succeeds */ + break; + + /* + * Hosts may set or clear remote wakeup status, and + * devices may report they're VBUS powered. + */ + case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) + | USB_REQ_GET_STATUS: + tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED); + if (at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_ESR) + tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP); + PACKET("get device status\n"); + __raw_writeb(tmp, dreg); + __raw_writeb(0, dreg); + goto write_in; + /* then STATUS starts later, automatically */ + case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) + | USB_REQ_SET_FEATURE: + if (w_value != USB_DEVICE_REMOTE_WAKEUP) + goto stall; + tmp = at91_udp_read(AT91_UDP_GLB_STAT); + tmp |= AT91_UDP_ESR; + at91_udp_write(AT91_UDP_GLB_STAT, tmp); + goto succeed; + case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) + | USB_REQ_CLEAR_FEATURE: + if (w_value != USB_DEVICE_REMOTE_WAKEUP) + goto stall; + tmp = at91_udp_read(AT91_UDP_GLB_STAT); + tmp &= ~AT91_UDP_ESR; + at91_udp_write(AT91_UDP_GLB_STAT, tmp); + goto succeed; + + /* + * Interfaces have no feature settings; this is pretty useless. + * we won't even insist the interface exists... + */ + case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8) + | USB_REQ_GET_STATUS: + PACKET("get interface status\n"); + __raw_writeb(0, dreg); + __raw_writeb(0, dreg); + goto write_in; + /* then STATUS starts later, automatically */ + case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8) + | USB_REQ_SET_FEATURE: + case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8) + | USB_REQ_CLEAR_FEATURE: + goto stall; + + /* + * Hosts may clear bulk/intr endpoint halt after the gadget + * driver sets it (not widely used); or set it (for testing) + */ + case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8) + | USB_REQ_GET_STATUS: + tmp = w_index & USB_ENDPOINT_NUMBER_MASK; + ep = &udc->ep[tmp]; + if (tmp > NUM_ENDPOINTS || (tmp && !ep->desc)) + goto stall; + + if (tmp) { + if ((w_index & USB_DIR_IN)) { + if (!ep->is_in) + goto stall; + } else if (ep->is_in) + goto stall; + } + PACKET("get %s status\n", ep->ep.name); + if (__raw_readl(ep->creg) & AT91_UDP_FORCESTALL) + tmp = (1 << USB_ENDPOINT_HALT); + else + tmp = 0; + __raw_writeb(tmp, dreg); + __raw_writeb(0, dreg); + goto write_in; + /* then STATUS starts later, automatically */ + case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8) + | USB_REQ_SET_FEATURE: + tmp = w_index & USB_ENDPOINT_NUMBER_MASK; + ep = &udc->ep[tmp]; + if (w_value != USB_ENDPOINT_HALT || tmp > NUM_ENDPOINTS) + goto stall; + if (!ep->desc || ep->is_iso) + goto stall; + if ((w_index & USB_DIR_IN)) { + if (!ep->is_in) + goto stall; + } else if (ep->is_in) + goto stall; + + tmp = __raw_readl(ep->creg); + tmp &= ~SET_FX; + tmp |= CLR_FX | AT91_UDP_FORCESTALL; + __raw_writel(tmp, ep->creg); + goto succeed; + case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8) + | USB_REQ_CLEAR_FEATURE: + tmp = w_index & USB_ENDPOINT_NUMBER_MASK; + ep = &udc->ep[tmp]; + if (w_value != USB_ENDPOINT_HALT || tmp > NUM_ENDPOINTS) + goto stall; + if (tmp == 0) + goto succeed; + if (!ep->desc || ep->is_iso) + goto stall; + if ((w_index & USB_DIR_IN)) { + if (!ep->is_in) + goto stall; + } else if (ep->is_in) + goto stall; + + at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); + at91_udp_write(AT91_UDP_RST_EP, 0); + tmp = __raw_readl(ep->creg); + tmp |= CLR_FX; + tmp &= ~(SET_FX | AT91_UDP_FORCESTALL); + __raw_writel(tmp, ep->creg); + if (!list_empty(&ep->queue)) + handle_ep(ep); + goto succeed; + } + +#undef w_value +#undef w_index +#undef w_length + + /* pass request up to the gadget driver */ + status = udc->driver->setup(&udc->gadget, &pkt.r); + if (status < 0) { +stall: + VDBG("req %02x.%02x protocol STALL; stat %d\n", + pkt.r.bRequestType, pkt.r.bRequest, status); + csr |= AT91_UDP_FORCESTALL; + __raw_writel(csr, creg); + udc->req_pending = 0; + } + return; + +succeed: + /* immediate successful (IN) STATUS after zero length DATA */ + PACKET("ep0 in/status\n"); +write_in: + csr |= AT91_UDP_TXPKTRDY; + __raw_writel(csr, creg); + udc->req_pending = 0; + return; +} + +static void handle_ep0(struct at91_udc *udc) +{ + struct at91_ep *ep0 = &udc->ep[0]; + u32 __iomem *creg = ep0->creg; + u32 csr = __raw_readl(creg); + struct at91_request *req; + + if (unlikely(csr & AT91_UDP_STALLSENT)) { + nuke(ep0, -EPROTO); + udc->req_pending = 0; + csr |= CLR_FX; + csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_FORCESTALL); + __raw_writel(csr, creg); + VDBG("ep0 stalled\n"); + csr = __raw_readl(creg); + } + if (csr & AT91_UDP_RXSETUP) { + nuke(ep0, 0); + udc->req_pending = 0; + handle_setup(udc, ep0, csr); + return; + } + + if (list_empty(&ep0->queue)) + req = NULL; + else + req = list_entry(ep0->queue.next, struct at91_request, queue); + + /* host ACKed an IN packet that we sent */ + if (csr & AT91_UDP_TXCOMP) { + csr |= CLR_FX; + csr &= ~(SET_FX | AT91_UDP_TXCOMP); + + /* write more IN DATA? */ + if (req && ep0->is_in) { + if (handle_ep(ep0)) + udc->req_pending = 0; + + /* + * Ack after: + * - last IN DATA packet (including GET_STATUS) + * - IN/STATUS for OUT DATA + * - IN/STATUS for any zero-length DATA stage + * except for the IN DATA case, the host should send + * an OUT status later, which we'll ack. + */ + } else { + udc->req_pending = 0; + __raw_writel(csr, creg); + + /* + * SET_ADDRESS takes effect only after the STATUS + * (to the original address) gets acked. + */ + if (udc->wait_for_addr_ack) { + u32 tmp; + + at91_udp_write(AT91_UDP_FADDR, AT91_UDP_FEN | udc->addr); + tmp = at91_udp_read(AT91_UDP_GLB_STAT); + tmp &= ~AT91_UDP_FADDEN; + if (udc->addr) + tmp |= AT91_UDP_FADDEN; + at91_udp_write(AT91_UDP_GLB_STAT, tmp); + + udc->wait_for_addr_ack = 0; + VDBG("address %d\n", udc->addr); + } + } + } + + /* OUT packet arrived ... */ + else if (csr & AT91_UDP_RX_DATA_BK0) { + csr |= CLR_FX; + csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0); + + /* OUT DATA stage */ + if (!ep0->is_in) { + if (req) { + if (handle_ep(ep0)) { + /* send IN/STATUS */ + PACKET("ep0 in/status\n"); + csr = __raw_readl(creg); + csr &= ~SET_FX; + csr |= CLR_FX | AT91_UDP_TXPKTRDY; + __raw_writel(csr, creg); + udc->req_pending = 0; + } + } else if (udc->req_pending) { + /* + * AT91 hardware has a hard time with this + * "deferred response" mode for control-OUT + * transfers. (For control-IN it's fine.) + * + * The normal solution leaves OUT data in the + * fifo until the gadget driver is ready. + * We couldn't do that here without disabling + * the IRQ that tells about SETUP packets, + * e.g. when the host gets impatient... + * + * Working around it by copying into a buffer + * would almost be a non-deferred response, + * except that it wouldn't permit reliable + * stalling of the request. Instead, demand + * that gadget drivers not use this mode. + */ + DBG("no control-OUT deferred responses!\n"); + __raw_writel(csr | AT91_UDP_FORCESTALL, creg); + udc->req_pending = 0; + } + + /* STATUS stage for control-IN; ack. */ + } else { + PACKET("ep0 out/status ACK\n"); + __raw_writel(csr, creg); + + /* "early" status stage */ + if (req) + done(ep0, req, 0); + } + } +} + +static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) +{ + struct at91_udc *udc = _udc; + u32 rescans = 5; + + while (rescans--) { + u32 status = at91_udp_read(AT91_UDP_ISR); + + status &= at91_udp_read(AT91_UDP_IMR); + if (!status) + break; + + /* USB reset irq: not maskable */ + if (status & AT91_UDP_ENDBUSRES) { + at91_udp_write(AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS); + at91_udp_write(AT91_UDP_IER, MINIMUS_INTERRUPTUS); + /* Atmel code clears this irq twice */ + at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES); + at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES); + VDBG("end bus reset\n"); + udc->addr = 0; + stop_activity(udc); + + /* enable ep0 */ + at91_udp_write(AT91_UDP_CSR(0), AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); + udc->gadget.speed = USB_SPEED_FULL; + udc->suspended = 0; + at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0)); + + /* + * NOTE: this driver keeps clocks off unless the + * USB host is present. That saves power, and also + * eliminates IRQs (reset, resume, suspend) that can + * otherwise flood from the controller. If your + * board doesn't support VBUS detection, suspend and + * resume irq logic may need more attention... + */ + + /* host initiated suspend (3+ms bus idle) */ + } else if (status & AT91_UDP_RXSUSP) { + at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXSUSP); + at91_udp_write(AT91_UDP_IER, AT91_UDP_RXRSM); + at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXSUSP); + // VDBG("bus suspend\n"); + if (udc->suspended) + continue; + udc->suspended = 1; + + /* + * NOTE: when suspending a VBUS-powered device, the + * gadget driver should switch into slow clock mode + * and then into standby to avoid drawing more than + * 500uA power (2500uA for some high-power configs). + */ + if (udc->driver && udc->driver->suspend) + udc->driver->suspend(&udc->gadget); + + /* host initiated resume */ + } else if (status & AT91_UDP_RXRSM) { + at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXRSM); + at91_udp_write(AT91_UDP_IER, AT91_UDP_RXSUSP); + at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXRSM); + // VDBG("bus resume\n"); + if (!udc->suspended) + continue; + udc->suspended = 0; + + /* + * NOTE: for a VBUS-powered device, the gadget driver + * would normally want to switch out of slow clock + * mode into normal mode. + */ + if (udc->driver && udc->driver->resume) + udc->driver->resume(&udc->gadget); + + /* endpoint IRQs are cleared by handling them */ + } else { + int i; + unsigned mask = 1; + struct at91_ep *ep = &udc->ep[1]; + + if (status & mask) + handle_ep0(udc); + for (i = 1; i < NUM_ENDPOINTS; i++) { + mask <<= 1; + if (status & mask) + handle_ep(ep); + ep++; + } + } + } + + return IRQ_HANDLED; +} + +/*-------------------------------------------------------------------------*/ + +static struct at91_udc controller = { + .gadget = { + .ops = &at91_udc_ops, + .ep0 = &controller.ep[0].ep, + .name = driver_name, + .dev = { + .bus_id = "gadget" + } + }, + .ep[0] = { + .ep = { + .name = ep0name, + .ops = &at91_ep_ops, + }, + .udc = &controller, + .maxpacket = 8, + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(0)), + .int_mask = 1 << 0, + }, + .ep[1] = { + .ep = { + .name = "ep1", + .ops = &at91_ep_ops, + }, + .udc = &controller, + .is_pingpong = 1, + .maxpacket = 64, + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(1)), + .int_mask = 1 << 1, + }, + .ep[2] = { + .ep = { + .name = "ep2", + .ops = &at91_ep_ops, + }, + .udc = &controller, + .is_pingpong = 1, + .maxpacket = 64, + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(2)), + .int_mask = 1 << 2, + }, + .ep[3] = { + .ep = { + /* could actually do bulk too */ + .name = "ep3-int", + .ops = &at91_ep_ops, + }, + .udc = &controller, + .maxpacket = 8, + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(3)), + .int_mask = 1 << 3, + }, + .ep[4] = { + .ep = { + .name = "ep4", + .ops = &at91_ep_ops, + }, + .udc = &controller, + .is_pingpong = 1, + .maxpacket = 256, + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(4)), + .int_mask = 1 << 4, + }, + .ep[5] = { + .ep = { + .name = "ep5", + .ops = &at91_ep_ops, + }, + .udc = &controller, + .is_pingpong = 1, + .maxpacket = 256, + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(5)), + .int_mask = 1 << 5, + }, + /* ep6 and ep7 are also reserved */ +}; + +static irqreturn_t at91_vbus_irq(int irq, void *_udc, struct pt_regs *r) +{ + struct at91_udc *udc = _udc; + unsigned value; + + /* vbus needs at least brief debouncing */ + udelay(10); + value = at91_get_gpio_value(udc->board.vbus_pin); + if (value != udc->vbus) + at91_vbus_session(&udc->gadget, value); + + return IRQ_HANDLED; +} + +int usb_gadget_register_driver (struct usb_gadget_driver *driver) +{ + struct at91_udc *udc = &controller; + int retval; + + if (!driver + || driver->speed != USB_SPEED_FULL + || !driver->bind + || !driver->unbind + || !driver->setup) { + DBG("bad parameter.\n"); + return -EINVAL; + } + + if (udc->driver) { + DBG("UDC already has a gadget driver\n"); + return -EBUSY; + } + + udc->driver = driver; + udc->gadget.dev.driver = &driver->driver; + udc->gadget.dev.driver_data = &driver->driver; + udc->enabled = 1; + udc->selfpowered = 1; + + retval = driver->bind(&udc->gadget); + if (retval) { + DBG("driver->bind() returned %d\n", retval); + udc->driver = NULL; + return retval; + } + + local_irq_disable(); + pullup(udc, 1); + local_irq_enable(); + + DBG("bound to %s\n", driver->driver.name); + return 0; +} +EXPORT_SYMBOL (usb_gadget_register_driver); + +int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) +{ + struct at91_udc *udc = &controller; + + if (!driver || driver != udc->driver) + return -EINVAL; + + local_irq_disable(); + udc->enabled = 0; + pullup(udc, 0); + local_irq_enable(); + + driver->unbind(&udc->gadget); + udc->driver = NULL; + + DBG("unbound from %s\n", driver->driver.name); + return 0; +} +EXPORT_SYMBOL (usb_gadget_unregister_driver); + +/*-------------------------------------------------------------------------*/ + +static void at91udc_shutdown(struct platform_device *dev) +{ + /* force disconnect on reboot */ + pullup(platform_get_drvdata(dev), 0); +} + +static int __devinit at91udc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct at91_udc *udc; + int retval; + + if (!dev->platform_data) { + /* small (so we copy it) but critical! */ + DBG("missing platform_data\n"); + return -ENODEV; + } + + if (!request_mem_region(AT91_BASE_UDP, SZ_16K, driver_name)) { + DBG("someone's using UDC memory\n"); + return -EBUSY; + } + + /* init software state */ + udc = &controller; + udc->gadget.dev.parent = dev; + udc->board = *(struct at91_udc_data *) dev->platform_data; + udc->pdev = pdev; + udc_reinit(udc); + udc->enabled = 0; + + /* get interface and function clocks */ + udc->iclk = clk_get(dev, "udc_clk"); + udc->fclk = clk_get(dev, "udpck"); + if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) { + DBG("clocks missing\n"); + return -ENODEV; + } + + retval = device_register(&udc->gadget.dev); + if (retval < 0) + goto fail0; + + /* disable everything until there's a gadget driver and vbus */ + pullup(udc, 0); + + /* request UDC and maybe VBUS irqs */ + if (request_irq(AT91_ID_UDP, at91_udc_irq, SA_INTERRUPT, driver_name, udc)) { + DBG("request irq %d failed\n", AT91_ID_UDP); + retval = -EBUSY; + goto fail1; + } + if (udc->board.vbus_pin > 0) { + if (request_irq(udc->board.vbus_pin, at91_vbus_irq, SA_INTERRUPT, driver_name, udc)) { + DBG("request vbus irq %d failed\n", udc->board.vbus_pin); + free_irq(AT91_ID_UDP, udc); + retval = -EBUSY; + goto fail1; + } + } else { + DBG("no VBUS detection, assuming always-on\n"); + udc->vbus = 1; + } + dev_set_drvdata(dev, udc); + create_debug_file(udc); + + INFO("%s version %s\n", driver_name, DRIVER_VERSION); + return 0; + +fail1: + device_unregister(&udc->gadget.dev); +fail0: + release_mem_region(AT91_VA_BASE_UDP, SZ_16K); + DBG("%s probe failed, %d\n", driver_name, retval); + return retval; +} + +static int __devexit at91udc_remove(struct platform_device *dev) +{ + struct at91_udc *udc = platform_get_drvdata(dev); + + DBG("remove\n"); + + pullup(udc, 0); + + if (udc->driver != 0) + usb_gadget_unregister_driver(udc->driver); + + remove_debug_file(udc); + if (udc->board.vbus_pin > 0) + free_irq(udc->board.vbus_pin, udc); + free_irq(AT91_ID_UDP, udc); + device_unregister(&udc->gadget.dev); + release_mem_region(AT91_BASE_UDP, SZ_16K); + + clk_put(udc->iclk); + clk_put(udc->fclk); + + return 0; +} + +#ifdef CONFIG_PM +static int at91udc_suspend(struct platform_device *dev, u32 state, u32 level) +{ + struct at91_udc *udc = platform_get_drvdata(dev); + + /* + * The "safe" suspend transitions are opportunistic ... e.g. when + * the USB link is suspended (48MHz clock autogated off), or when + * it's disconnected (programmatically gated off, elsewhere). + * Then we can suspend, and the chip can enter slow clock mode. + * + * The problem case is some component (user mode?) suspending this + * device while it's active, with the 48 MHz clock in use. There + * are two basic approaches: (a) veto suspend levels involving slow + * clock mode, (b) disconnect, so 48 MHz will no longer be in use + * and we can enter slow clock mode. This uses (b) for now, since + * it's simplest until AT91 PM exists and supports the other option. + */ + if (udc->vbus && !udc->suspended) + pullup(udc, 0); + return 0; +} + +static int at91udc_resume(struct platform_device *dev, u32 level) +{ + struct at91_udc *udc = platform_get_drvdata(dev); + + /* maybe reconnect to host; if so, clocks on */ + pullup(udc, 1); + return 0; +} +#else +#define at91udc_suspend NULL +#define at91udc_resume NULL +#endif + +static struct platform_driver at91_udc = { + .probe = at91udc_probe, + .remove = __devexit_p(at91udc_remove), + .shutdown = at91udc_shutdown, + .suspend = at91udc_suspend, + .resume = at91udc_resume, + .driver = { + .name = (char *) driver_name, + .owner = THIS_MODULE, + }, +}; + +static int __devinit udc_init_module(void) +{ + return platform_driver_register(&at91_udc); +} +module_init(udc_init_module); + +static void __devexit udc_exit_module(void) +{ + platform_driver_unregister(&at91_udc); +} +module_exit(udc_exit_module); + +MODULE_DESCRIPTION("AT91RM9200 udc driver"); +MODULE_AUTHOR("Thomas Rathbone, David Brownell"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h new file mode 100644 index 000000000000..5a4799cedd19 --- /dev/null +++ b/drivers/usb/gadget/at91_udc.h @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2004 by Thomas Rathbone, HP Labs + * Copyright (C) 2005 by Ivan Kokshaysky + * Copyright (C) 2006 by 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. + * + * 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 AT91_UDC_H +#define AT91_UDC_H + +/* + * USB Device Port (UDP) registers. + * Based on AT91RM9200 datasheet revision E. + */ + +#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 */ + + +/*-------------------------------------------------------------------------*/ + +/* + * controller driver data structures + */ + +#define NUM_ENDPOINTS 6 + +/* + * hardware won't disable bus reset, or resume while the controller + * is suspended ... watching suspend helps keep the logic symmetric. + */ +#define MINIMUS_INTERRUPTUS \ + (AT91_UDP_ENDBUSRES | AT91_UDP_RXRSM | AT91_UDP_RXSUSP) + +struct at91_ep { + struct usb_ep ep; + struct list_head queue; + struct at91_udc *udc; + void __iomem *creg; + + unsigned maxpacket:16; + u8 int_mask; + unsigned is_pingpong:1; + + unsigned stopped:1; + unsigned is_in:1; + unsigned is_iso:1; + unsigned fifo_bank:1; + + const struct usb_endpoint_descriptor + *desc; +}; + +/* + * driver is non-SMP, and just blocks IRQs whenever it needs + * access protection for chip registers or driver state + */ +struct at91_udc { + struct usb_gadget gadget; + struct at91_ep ep[NUM_ENDPOINTS]; + struct usb_gadget_driver *driver; + unsigned vbus:1; + unsigned enabled:1; + unsigned clocked:1; + unsigned suspended:1; + unsigned req_pending:1; + unsigned wait_for_addr_ack:1; + unsigned wait_for_config_ack:1; + unsigned selfpowered:1; + u8 addr; + struct at91_udc_data board; + struct clk *iclk, *fclk; + struct platform_device *pdev; + struct proc_dir_entry *pde; +}; + +static inline struct at91_udc *to_udc(struct usb_gadget *g) +{ + return container_of(g, struct at91_udc, gadget); +} + +struct at91_request { + struct usb_request req; + struct list_head queue; +}; + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +#define DBG(stuff...) printk(KERN_DEBUG "udc: " stuff) +#else +#define DBG(stuff...) do{}while(0) +#endif + +#ifdef VERBOSE +# define VDBG DBG +#else +# define VDBG(stuff...) do{}while(0) +#endif + +#ifdef PACKET_TRACE +# define PACKET VDBG +#else +# define PACKET(stuff...) do{}while(0) +#endif + +#define ERR(stuff...) printk(KERN_ERR "udc: " stuff) +#define WARN(stuff...) printk(KERN_WARNING "udc: " stuff) +#define INFO(stuff...) printk(KERN_INFO "udc: " stuff) + +#endif + -- cgit v1.2.3-59-g8ed1b From 7802ac5c29d135345db1b06f9167075cd9f2d675 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 22 Jan 2006 10:33:27 -0800 Subject: [PATCH] USB: minor gadget/rndis tweak Resove a minor FIXME: don't change MTU while RNDIS link is active, the other end won't expect such things... Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ether.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index afc84cfb61f9..04b9743c1c1f 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -1549,7 +1549,8 @@ static int eth_change_mtu (struct net_device *net, int new_mtu) { struct eth_dev *dev = netdev_priv(net); - // FIXME if rndis, don't change while link's live + if (dev->rndis) + return -EBUSY; if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN) return -ERANGE; -- cgit v1.2.3-59-g8ed1b From 1c05ad4447e4ecbd61647c102fb6f2f5a6634ff3 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 25 Jan 2006 08:45:59 -0800 Subject: [PATCH] recognize three more usb peripheral controllers This adds declarations for three USB peripheral controllers: - Two high speed USB cores that can be licensed from Mentor Graphics to be integrated into silicon: * "musbhsfc" is for peripherals only, as found in for example the IBM/AMCC 44EP processors. * "musbhdrc" is OTG-capable (dual role), and is found in various products including OMAP 2430 and the new DaVinci SOCs. The "musbh" standing for "Mentor USB Highspeed", the rest standing for "Function Controller" or "Dual Role Controller" (OTG-capable). - The full speed controller on the FreeScale MPC8272. Adding these definitions just allows gadget driver code to handle any controller-specific logic; controller drivers are quite separate. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ether.c | 8 ++++++++ drivers/usb/gadget/gadget_chips.h | 30 ++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 04b9743c1c1f..3d2603e31808 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -253,6 +253,14 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); #define DEV_CONFIG_CDC #endif +#ifdef CONFIG_USB_GADGET_MUSBHSFC +#define DEV_CONFIG_CDC +#endif + +#ifdef CONFIG_USB_GADGET_MUSBHDRC +#define DEV_CONFIG_CDC +#endif + /* For CDC-incapable hardware, choose the simple cdc subset. * Anything that talks bulk (without notable bugs) can do this. diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index 8cbae21d84b9..c4081407171f 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -3,9 +3,9 @@ * gadget drivers or other code that needs to deal with them, and which * autoconfigures instead of using early binding to the hardware. * - * This could eventually work like the ARM mach_is_*() stuff, driven by + * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by * some config file that gets updated as new hardware is supported. - * (And avoiding the runtime comparisons in typical one-choice cases.) + * (And avoiding all runtime comparisons in typical one-choice configs!) * * NOTE: some of these controller drivers may not be available yet. */ @@ -93,6 +93,26 @@ #define gadget_is_imx(g) 0 #endif +/* Mentor high speed function controller */ +#ifdef CONFIG_USB_GADGET_MUSBHSFC +#define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name) +#else +#define gadget_is_musbhsfc(g) 0 +#endif + +/* Mentor high speed "dual role" controller, peripheral mode */ +#ifdef CONFIG_USB_GADGET_MUSBHDRC +#define gadget_is_musbhdrc(g) !strcmp("musbhdrc_udc", (g)->name) +#else +#define gadget_is_musbhdrc(g) 0 +#endif + +#ifdef CONFIG_USB_GADGET_MPC8272 +#define gadget_is_mpc8272(g) !strcmp("mpc8272_udc", (g)->name) +#else +#define gadget_is_mpc8272(g) 0 +#endif + // CONFIG_USB_GADGET_SX2 // CONFIG_USB_GADGET_AU1X00 // ... @@ -143,5 +163,11 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x13; else if (gadget_is_imx(gadget)) return 0x14; + else if (gadget_is_musbhsfc(gadget)) + return 0x15; + else if (gadget_is_musbhdrc(gadget)) + return 0x16; + else if (gadget_is_mpc8272(gadget)) + return 0x17; return -ENOENT; } -- cgit v1.2.3-59-g8ed1b From b1e8f0a6a8805c971857cd10a65cf8caa4c1a672 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 23 Jan 2006 15:25:40 -0800 Subject: [PATCH] USB: usbcore sets up root hubs earlier Make the HCD initialization sequence more sane ... notably, setting up root hubs before HCDs are asked to do their one-time init. Among other things, that lets the HCDs do custom root hub init along with all the other one-time initialization done in the (now misnamed) reset() method. This also copies the controller wakeup flags into the root hub; it's done a bit later than would be ideal, but that'll be necessary until the PCI code initializes them correctly. (The PCI patch breaks on PPC due to how it sequences PCI initialization.) Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 104 ++++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 9223f2869674..6368562d73ca 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -823,18 +823,17 @@ static void usb_deregister_bus (struct usb_bus *bus) /** * register_root_hub - called by usb_add_hcd() to register a root hub - * @usb_dev: the usb root hub device to be registered. * @hcd: host controller for this root hub * * This function registers the root hub with the USB subsystem. It sets up - * the device properly in the device tree and stores the root_hub pointer - * in the bus structure, then calls usb_new_device() to register the usb - * device. It also assigns the root hub's USB address (always 1). + * the device properly in the device tree and then calls usb_new_device() + * to register the usb device. It also assigns the root hub's USB address + * (always 1). */ -static int register_root_hub (struct usb_device *usb_dev, - struct usb_hcd *hcd) +static int register_root_hub(struct usb_hcd *hcd) { struct device *parent_dev = hcd->self.controller; + struct usb_device *usb_dev = hcd->self.root_hub; const int devnum = 1; int retval; @@ -846,12 +845,10 @@ static int register_root_hub (struct usb_device *usb_dev, usb_set_device_state(usb_dev, USB_STATE_ADDRESS); mutex_lock(&usb_bus_list_lock); - usb_dev->bus->root_hub = usb_dev; usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); if (retval != sizeof usb_dev->descriptor) { - usb_dev->bus->root_hub = NULL; mutex_unlock(&usb_bus_list_lock); dev_dbg (parent_dev, "can't read %s device descriptor %d\n", usb_dev->dev.bus_id, retval); @@ -860,7 +857,6 @@ static int register_root_hub (struct usb_device *usb_dev, retval = usb_new_device (usb_dev); if (retval) { - usb_dev->bus->root_hub = NULL; dev_err (parent_dev, "can't register root hub for %s, %d\n", usb_dev->dev.bus_id, retval); } @@ -1772,12 +1768,10 @@ int usb_add_hcd(struct usb_hcd *hcd, set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - /* till now HC has been in an indeterminate state ... */ - if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { - dev_err(hcd->self.controller, "can't reset\n"); - return retval; - } - + /* HC is in reset state, but accessible. Now do the one-time init, + * bottom up so that hcds can customize the root hubs before khubd + * starts talking to them. (Note, bus id is assigned early too.) + */ if ((retval = hcd_buffer_create(hcd)) != 0) { dev_dbg(hcd->self.controller, "pool alloc failed\n"); return retval; @@ -1786,6 +1780,42 @@ int usb_add_hcd(struct usb_hcd *hcd, if ((retval = usb_register_bus(&hcd->self)) < 0) goto err_register_bus; + if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { + dev_err(hcd->self.controller, "unable to allocate root hub\n"); + retval = -ENOMEM; + goto err_allocate_root_hub; + } + rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH : + USB_SPEED_FULL; + hcd->self.root_hub = rhdev; + + /* "reset" is misnamed; its role is now one-time init. the controller + * should already have been reset (and boot firmware kicked off etc). + */ + if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { + dev_err(hcd->self.controller, "can't setup\n"); + goto err_hcd_driver_setup; + } + + /* wakeup flag init is in transition; for now we can't rely on PCI to + * initialize these bits properly, so we let reset() override it. + * This init should _precede_ the reset() once PCI behaves. + */ + device_init_wakeup(&rhdev->dev, + device_can_wakeup(hcd->self.controller)); + + // ... all these hcd->*_wakeup flags will vanish + hcd->can_wakeup = device_can_wakeup(hcd->self.controller); + + /* hcd->driver->reset() reported can_wakeup, probably with + * assistance from board's boot firmware. + * NOTE: normal devices won't enable wakeup by default. + */ + if (hcd->can_wakeup) + dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); + hcd->remote_wakeup = hcd->can_wakeup; + + /* enable irqs just before we start the controller */ if (hcd->driver->irq) { char buf[8], *bufp = buf; @@ -1817,56 +1847,32 @@ int usb_add_hcd(struct usb_hcd *hcd, (unsigned long long)hcd->rsrc_start); } - /* Allocate the root hub before calling hcd->driver->start(), - * but don't register it until afterward so that the hardware - * is running. - */ - if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { - dev_err(hcd->self.controller, "unable to allocate root hub\n"); - retval = -ENOMEM; - goto err_allocate_root_hub; - } - - /* Although in principle hcd->driver->start() might need to use rhdev, - * none of the current drivers do. - */ if ((retval = hcd->driver->start(hcd)) < 0) { dev_err(hcd->self.controller, "startup error %d\n", retval); goto err_hcd_driver_start; } - /* hcd->driver->start() reported can_wakeup, probably with - * assistance from board's boot firmware. - * NOTE: normal devices won't enable wakeup by default. - */ - if (hcd->can_wakeup) - dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); - hcd->remote_wakeup = hcd->can_wakeup; - - rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH : - USB_SPEED_FULL; + /* starting here, usbcore will pay attention to this root hub */ rhdev->bus_mA = min(500u, hcd->power_budget); - if ((retval = register_root_hub(rhdev, hcd)) != 0) + if ((retval = register_root_hub(hcd)) != 0) goto err_register_root_hub; if (hcd->uses_new_polling && hcd->poll_rh) usb_hcd_poll_rh_status(hcd); return retval; - err_register_root_hub: +err_register_root_hub: hcd->driver->stop(hcd); - - err_hcd_driver_start: - usb_put_dev(rhdev); - - err_allocate_root_hub: +err_hcd_driver_start: if (hcd->irq >= 0) free_irq(irqnum, hcd); - - err_request_irq: +err_request_irq: +err_hcd_driver_setup: + hcd->self.root_hub = NULL; + usb_put_dev(rhdev); +err_allocate_root_hub: usb_deregister_bus(&hcd->self); - - err_register_bus: +err_register_bus: hcd_buffer_destroy(hcd); return retval; } -- cgit v1.2.3-59-g8ed1b From 6a9062f393fa48125df23c5491543828a21e1ae0 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 23 Jan 2006 15:28:07 -0800 Subject: [PATCH] USB: ohci uses driver model wakeup flags This makes OHCI use the driver model wakeup control bits for its root hub (e.g. disable on amd756, because of chip erratum) and for the controller itself. It no longer uses the hcd glue bits with those roles, and depends on the previous patch making the root hub available earlier. Note that on most platforms (boot code properly setting the RWC bit) this gives a partial workaround for the way PCI isn't currently flagging devices that support PME# signals. (Because of odd PCI init sequencing on PPC.) That's because many OHCI controllers support "legacy PCI PM" ... without involving any PCI PM capability. USB wakeup from STR, if it works on your system, may still involve tweaking things by hand in /proc/acpi/wakeup. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 49 +++++++++++++++++++++++++-------------------- drivers/usb/host/ohci-hub.c | 12 +++++------ drivers/usb/host/ohci-pci.c | 15 ++++++++++++-- 3 files changed, 46 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 2990be269000..544f7589912f 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -443,11 +443,16 @@ ohci_reboot (struct notifier_block *block, unsigned long code, void *null) static int ohci_init (struct ohci_hcd *ohci) { int ret; + struct usb_hcd *hcd = ohci_to_hcd(ohci); disable (ohci); - ohci->regs = ohci_to_hcd(ohci)->regs; + ohci->regs = hcd->regs; ohci->next_statechange = jiffies; + /* REVISIT this BIOS handshake is now moved into PCI "quirks", and + * was never needed for most non-PCI systems ... remove the code? + */ + #ifndef IR_DISABLE /* SMM owns the HC? not for long! */ if (!no_handshake && ohci_readl (ohci, @@ -478,8 +483,10 @@ static int ohci_init (struct ohci_hcd *ohci) /* Disable HC interrupts */ ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); - // flush the writes - (void) ohci_readl (ohci, &ohci->regs->control); + + /* flush the writes, and save key bits like RWC */ + if (ohci_readl (ohci, &ohci->regs->control) & OHCI_CTRL_RWC) + ohci->hc_control |= OHCI_CTRL_RWC; /* Read the number of ports unless overridden */ if (ohci->num_ports == 0) @@ -488,16 +495,19 @@ static int ohci_init (struct ohci_hcd *ohci) if (ohci->hcca) return 0; - ohci->hcca = dma_alloc_coherent (ohci_to_hcd(ohci)->self.controller, + ohci->hcca = dma_alloc_coherent (hcd->self.controller, sizeof *ohci->hcca, &ohci->hcca_dma, 0); if (!ohci->hcca) return -ENOMEM; if ((ret = ohci_mem_init (ohci)) < 0) - ohci_stop (ohci_to_hcd(ohci)); + ohci_stop (hcd); + else { + register_reboot_notifier (&ohci->reboot_notifier); + create_debug_files (ohci); + } return ret; - } /*-------------------------------------------------------------------------*/ @@ -510,6 +520,7 @@ static int ohci_run (struct ohci_hcd *ohci) { u32 mask, temp; int first = ohci->fminterval == 0; + struct usb_hcd *hcd = ohci_to_hcd(ohci); disable (ohci); @@ -525,18 +536,17 @@ static int ohci_run (struct ohci_hcd *ohci) /* also: power/overcurrent flags in roothub.a */ } - /* Reset USB nearly "by the book". RemoteWakeupConnected - * saved if boot firmware (BIOS/SMM/...) told us it's connected - * (for OHCI integrated on mainboard, it normally is) + /* Reset USB nearly "by the book". RemoteWakeupConnected was + * saved if boot firmware (BIOS/SMM/...) told us it's connected, + * or if bus glue did the same (e.g. for PCI add-in cards with + * PCI PM support). */ - ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n", hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), - ohci->hc_control); - - if (ohci->hc_control & OHCI_CTRL_RWC - && !(ohci->flags & OHCI_QUIRK_AMD756)) - ohci_to_hcd(ohci)->can_wakeup = 1; + ohci_readl (ohci, &ohci->regs->control)); + if ((ohci->hc_control & OHCI_CTRL_RWC) != 0 + && !device_may_wakeup(hcd->self.controller)) + device_init_wakeup(hcd->self.controller, 1); switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_OPER: @@ -632,7 +642,7 @@ retry: ohci->hc_control &= OHCI_CTRL_RWC; ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); - ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; + hcd->state = HC_STATE_RUNNING; /* wake on ConnectStatusChange, matching external hubs */ ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status); @@ -667,15 +677,10 @@ retry: // POTPGT delay is bits 24-31, in 2 ms units. mdelay ((temp >> 23) & 0x1fe); - ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; + hcd->state = HC_STATE_RUNNING; ohci_dump (ohci, 1); - if (ohci_to_hcd(ohci)->self.root_hub == NULL) { - register_reboot_notifier (&ohci->reboot_notifier); - create_debug_files (ohci); - } - return 0; } diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 4b2226d77b34..0bb972b58336 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -107,7 +107,7 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) &ohci->regs->intrstatus); /* maybe resume can wake root hub */ - if (hcd->remote_wakeup) + if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev)) ohci->hc_control |= OHCI_CTRL_RWE; else ohci->hc_control &= ~OHCI_CTRL_RWE; @@ -246,9 +246,9 @@ static int ohci_bus_resume (struct usb_hcd *hcd) (void) ohci_readl (ohci, &ohci->regs->control); msleep (3); - temp = OHCI_CONTROL_INIT | OHCI_USB_OPER; - if (hcd->can_wakeup) - temp |= OHCI_CTRL_RWC; + temp = ohci->hc_control; + temp &= OHCI_CTRL_RWC; + temp |= OHCI_CONTROL_INIT | OHCI_USB_OPER; ohci->hc_control = temp; ohci_writel (ohci, temp, &ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control); @@ -302,7 +302,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int i, changed = 0, length = 1; - int can_suspend = hcd->can_wakeup; + int can_suspend = device_may_wakeup(&hcd->self.root_hub->dev); unsigned long flags; spin_lock_irqsave (&ohci->lock, flags); @@ -354,7 +354,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) */ if (!(status & RH_PS_CCS)) continue; - if ((status & RH_PS_PSS) && hcd->remote_wakeup) + if ((status & RH_PS_PSS) && can_suspend) continue; can_suspend = 0; } diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 1b09dde068e1..1bfe96f4d045 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -35,7 +35,10 @@ ohci_pci_start (struct usb_hcd *hcd) struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ret; - if(hcd->self.controller && hcd->self.controller->bus == &pci_bus_type) { + /* REVISIT this whole block should move to reset(), which handles + * all the other one-time init. + */ + if (hcd->self.controller) { struct pci_dev *pdev = to_pci_dev(hcd->self.controller); /* AMD 756, for most chips (early revs), corrupts register @@ -45,7 +48,8 @@ ohci_pci_start (struct usb_hcd *hcd) && pdev->device == 0x740c) { ohci->flags = OHCI_QUIRK_AMD756; ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); - // also somewhat erratum 10 (suspend/resume issues) + /* also erratum 10 (suspend/resume issues) */ + device_init_wakeup(&hcd->self.root_hub->dev, 0); } /* FIXME for some of the early AMD 760 southbridges, OHCI @@ -88,6 +92,13 @@ ohci_pci_start (struct usb_hcd *hcd) ohci_dbg (ohci, "enabled Compaq ZFMicro chipset quirk\n"); } + + /* RWC may not be set for add-in PCI cards, since boot + * firmware probably ignored them. This transfers PCI + * PM wakeup capabilities (once the PCI layer is fixed). + */ + if (device_may_wakeup(&pdev->dev)) + ohci->hc_control |= OHCI_CTRL_RWC; } /* NOTE: there may have already been a first reset, to -- cgit v1.2.3-59-g8ed1b From fb669cc01ed778c4926f395e44a9b61644597d38 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 24 Jan 2006 08:40:27 -0800 Subject: [PATCH] USB: remove usbcore-specific wakeup flags This makes usbcore use the driver model wakeup flags for host controllers and for their root hubs. Since previous patches have removed all users of the HCD flags they replace, this converts the last users of those flags. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd-pci.c | 11 ++++++++--- drivers/usb/core/hcd.c | 40 ++++++++++++++++++++++++++-------------- drivers/usb/core/hcd.h | 2 -- drivers/usb/core/hub.c | 22 ++++++++++++++-------- 4 files changed, 48 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 29b5b2a6e183..e0afb5ad29e5 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -264,14 +264,19 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) */ retval = pci_set_power_state (dev, PCI_D3hot); if (retval == 0) { - dev_dbg (hcd->self.controller, "--> PCI D3\n"); + int wake = device_can_wakeup(&hcd->self.root_hub->dev); + + wake = wake && device_may_wakeup(hcd->self.controller); + + dev_dbg (hcd->self.controller, "--> PCI D3%s\n", + wake ? "/wakeup" : ""); /* Ignore these return values. We rely on pci code to * reject requests the hardware can't implement, rather * than coding the same thing. */ - (void) pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup); - (void) pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup); + (void) pci_enable_wake (dev, PCI_D3hot, wake); + (void) pci_enable_wake (dev, PCI_D3cold, wake); } else { dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n", retval); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6368562d73ca..a98d978d76e2 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -367,21 +367,39 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) /* DEVICE REQUESTS */ + /* The root hub's remote wakeup enable bit is implemented using + * driver model wakeup flags. If this system supports wakeup + * through USB, userspace may change the default "allow wakeup" + * policy through sysfs or these calls. + * + * Most root hubs support wakeup from downstream devices, for + * runtime power management (disabling USB clocks and reducing + * VBUS power usage). However, not all of them do so; silicon, + * board, and BIOS bugs here are not uncommon, so these can't + * be treated quite like external hubs. + * + * Likewise, not all root hubs will pass wakeup events upstream, + * to wake up the whole system. So don't assume root hub and + * controller capabilities are identical. + */ + case DeviceRequest | USB_REQ_GET_STATUS: - tbuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP) + tbuf [0] = (device_may_wakeup(&hcd->self.root_hub->dev) + << USB_DEVICE_REMOTE_WAKEUP) | (1 << USB_DEVICE_SELF_POWERED); tbuf [1] = 0; len = 2; break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (wValue == USB_DEVICE_REMOTE_WAKEUP) - hcd->remote_wakeup = 0; + device_set_wakeup_enable(&hcd->self.root_hub->dev, 0); else goto error; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: - if (hcd->can_wakeup && wValue == USB_DEVICE_REMOTE_WAKEUP) - hcd->remote_wakeup = 1; + if (device_can_wakeup(&hcd->self.root_hub->dev) + && wValue == USB_DEVICE_REMOTE_WAKEUP) + device_set_wakeup_enable(&hcd->self.root_hub->dev, 1); else goto error; break; @@ -410,7 +428,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) bufp = fs_rh_config_descriptor; len = sizeof fs_rh_config_descriptor; } - if (hcd->can_wakeup) + if (device_can_wakeup(&hcd->self.root_hub->dev)) patch_wakeup = 1; break; case USB_DT_STRING << 8: @@ -1804,16 +1822,10 @@ int usb_add_hcd(struct usb_hcd *hcd, device_init_wakeup(&rhdev->dev, device_can_wakeup(hcd->self.controller)); - // ... all these hcd->*_wakeup flags will vanish - hcd->can_wakeup = device_can_wakeup(hcd->self.controller); - - /* hcd->driver->reset() reported can_wakeup, probably with - * assistance from board's boot firmware. - * NOTE: normal devices won't enable wakeup by default. - */ - if (hcd->can_wakeup) + /* NOTE: root hub and controller capabilities may not be the same */ + if (device_can_wakeup(hcd->self.controller) + && device_can_wakeup(&hcd->self.root_hub->dev)) dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); - hcd->remote_wakeup = hcd->can_wakeup; /* enable irqs just before we start the controller */ if (hcd->driver->irq) { diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index f44a2fe62a9d..7022aafb2ae8 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -78,8 +78,6 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ #define HCD_FLAG_HW_ACCESSIBLE 0x00000001 #define HCD_FLAG_SAW_IRQ 0x00000002 - unsigned can_wakeup:1; /* hw supports wakeup? */ - unsigned remote_wakeup:1;/* sw should use wakeup? */ unsigned rh_registered:1;/* is root hub registered? */ /* The next flag is a stopgap, to be removed when all the HCDs diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 867fa8130238..f1d64d4bbf5f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1006,12 +1006,18 @@ void usb_set_device_state(struct usb_device *udev, ; /* do nothing */ else if (new_state != USB_STATE_NOTATTACHED) { udev->state = new_state; - if (new_state == USB_STATE_CONFIGURED) - device_init_wakeup(&udev->dev, - (udev->actconfig->desc.bmAttributes - & USB_CONFIG_ATT_WAKEUP)); - else if (new_state != USB_STATE_SUSPENDED) - device_init_wakeup(&udev->dev, 0); + + /* root hub wakeup capabilities are managed out-of-band + * and may involve silicon errata ... ignore them here. + */ + if (udev->parent) { + if (new_state == USB_STATE_CONFIGURED) + device_init_wakeup(&udev->dev, + (udev->actconfig->desc.bmAttributes + & USB_CONFIG_ATT_WAKEUP)); + else if (new_state != USB_STATE_SUSPENDED) + device_init_wakeup(&udev->dev, 0); + } } else recursively_mark_NOTATTACHED(udev); spin_unlock_irqrestore(&device_state_lock, flags); @@ -1877,9 +1883,9 @@ int usb_resume_device(struct usb_device *udev) if (udev->state == USB_STATE_NOTATTACHED) return -ENODEV; -#ifdef CONFIG_USB_SUSPEND /* selective resume of one downstream hub-to-device port */ if (udev->parent) { +#ifdef CONFIG_USB_SUSPEND if (udev->state == USB_STATE_SUSPENDED) { // NOTE swsusp may bork us, device state being wrong... // NOTE this fails if parent is also suspended... @@ -1887,8 +1893,8 @@ int usb_resume_device(struct usb_device *udev) udev->portnum, udev); } else status = 0; - } else #endif + } else status = finish_device_resume(udev); if (status < 0) dev_dbg(&udev->dev, "can't resume, status %d\n", -- cgit v1.2.3-59-g8ed1b From aef4e266964bc15861b5835c1f5b9d2ebc155c2a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 31 Jan 2006 12:58:38 -0500 Subject: [PATCH] usbhid: add error handling This patch (as628c) adds error handling to the USB HID core. When an error is reported for an interrupt URB, the driver will do delayed retries, at increasing intervals, for up to one second. If that doesn't work, it will try to reset the device. Testing by users has shown that both the retries and the resets end up getting used. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 153 +++++++++++++++++++++++++++++++++++++------ drivers/usb/input/hid.h | 10 +++ 2 files changed, 142 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index f187a719f17e..6b8a51cad375 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -902,6 +902,99 @@ static int hid_input_report(int type, struct urb *urb, int interrupt, struct pt_ return 0; } +/* + * Input submission and I/O error handler. + */ + +static void hid_io_error(struct hid_device *hid); + +/* Start up the input URB */ +static int hid_start_in(struct hid_device *hid) +{ + unsigned long flags; + int rc = 0; + + spin_lock_irqsave(&hid->inlock, flags); + if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) && + !test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) { + rc = usb_submit_urb(hid->urbin, GFP_ATOMIC); + if (rc != 0) + clear_bit(HID_IN_RUNNING, &hid->iofl); + } + spin_unlock_irqrestore(&hid->inlock, flags); + return rc; +} + +/* I/O retry timer routine */ +static void hid_retry_timeout(unsigned long _hid) +{ + struct hid_device *hid = (struct hid_device *) _hid; + + dev_dbg(&hid->intf->dev, "retrying intr urb\n"); + if (hid_start_in(hid)) + hid_io_error(hid); +} + +/* Workqueue routine to reset the device */ +static void hid_reset(void *_hid) +{ + struct hid_device *hid = (struct hid_device *) _hid; + int rc_lock, rc; + + 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); + 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)) + hid_io_error(hid); + } else if (!(rc == -ENODEV || rc == -EHOSTUNREACH || rc == -EINTR)) + err("can't reset device, %s-%s/input%d, status %d", + hid->dev->bus->bus_name, + hid->dev->devpath, + hid->ifnum, rc); +} + +/* Main I/O error handler */ +static void hid_io_error(struct hid_device *hid) +{ + unsigned long flags; + + spin_lock_irqsave(&hid->inlock, flags); + + /* Stop when disconnected */ + if (usb_get_intfdata(hid->intf) == NULL) + goto done; + + /* When an error occurs, retry at increasing intervals */ + if (hid->retry_delay == 0) { + hid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ + hid->stop_retry = jiffies + msecs_to_jiffies(1000); + } else if (hid->retry_delay < 100) + hid->retry_delay *= 2; + + if (time_after(jiffies, hid->stop_retry)) { + + /* Retries failed, so do a port reset */ + if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) { + if (schedule_work(&hid->reset_work)) + goto done; + clear_bit(HID_RESET_PENDING, &hid->iofl); + } + } + + mod_timer(&hid->io_retry, + jiffies + msecs_to_jiffies(hid->retry_delay)); +done: + spin_unlock_irqrestore(&hid->inlock, flags); +} + /* * Input interrupt completion handler. */ @@ -913,25 +1006,35 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs) switch (urb->status) { case 0: /* success */ + hid->retry_delay = 0; hid_input_report(HID_INPUT_REPORT, urb, 1, regs); break; case -ECONNRESET: /* unlink */ case -ENOENT: - case -EPERM: case -ESHUTDOWN: /* unplug */ - case -EILSEQ: /* unplug timeout on uhci */ + clear_bit(HID_IN_RUNNING, &hid->iofl); return; + case -EILSEQ: /* protocol error or unplug */ + case -EPROTO: /* protocol error or unplug */ case -ETIMEDOUT: /* NAK */ - break; + clear_bit(HID_IN_RUNNING, &hid->iofl); + hid_io_error(hid); + return; default: /* error */ warn("input irq status %d received", urb->status); } status = usb_submit_urb(urb, SLAB_ATOMIC); - if (status) - err("can't resubmit intr, %s-%s/input%d, status %d", - hid->dev->bus->bus_name, hid->dev->devpath, - hid->ifnum, status); + if (status) { + clear_bit(HID_IN_RUNNING, &hid->iofl); + if (status != -EPERM) { + err("can't resubmit intr, %s-%s/input%d, status %d", + hid->dev->bus->bus_name, + hid->dev->devpath, + hid->ifnum, status); + hid_io_error(hid); + } + } } /* @@ -1093,8 +1196,9 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs) case 0: /* success */ break; case -ESHUTDOWN: /* unplug */ - case -EILSEQ: /* unplug timeout on uhci */ unplug = 1; + case -EILSEQ: /* protocol error or unplug */ + case -EPROTO: /* protocol error or unplug */ case -ECONNRESET: /* unlink */ case -ENOENT: break; @@ -1141,8 +1245,9 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs) hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs); break; case -ESHUTDOWN: /* unplug */ - case -EILSEQ: /* unplug timectrl on uhci */ unplug = 1; + case -EILSEQ: /* protocol error or unplug */ + case -EPROTO: /* protocol error or unplug */ case -ECONNRESET: /* unlink */ case -ENOENT: case -EPIPE: /* report not available */ @@ -1255,14 +1360,9 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, int hid_open(struct hid_device *hid) { - if (hid->open++) - return 0; - - hid->urbin->dev = hid->dev; - - if (usb_submit_urb(hid->urbin, GFP_KERNEL)) - return -EIO; - + ++hid->open; + if (hid_start_in(hid)) + hid_io_error(hid); return 0; } @@ -1787,6 +1887,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) init_waitqueue_head(&hid->wait); + INIT_WORK(&hid->reset_work, hid_reset, hid); + setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid); + + spin_lock_init(&hid->inlock); spin_lock_init(&hid->outlock); spin_lock_init(&hid->ctrllock); @@ -1855,11 +1959,16 @@ static void hid_disconnect(struct usb_interface *intf) if (!hid) return; + spin_lock_irq(&hid->inlock); /* Sync with error handler */ usb_set_intfdata(intf, NULL); + spin_unlock_irq(&hid->inlock); usb_kill_urb(hid->urbin); usb_kill_urb(hid->urbout); usb_kill_urb(hid->urbctrl); + del_timer_sync(&hid->io_retry); + flush_scheduled_work(); + if (hid->claimed & HID_CLAIMED_INPUT) hidinput_disconnect(hid); if (hid->claimed & HID_CLAIMED_HIDDEV) @@ -1934,6 +2043,10 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) { struct hid_device *hid = usb_get_intfdata (intf); + spin_lock_irq(&hid->inlock); /* Sync with error handler */ + set_bit(HID_SUSPENDED, &hid->iofl); + spin_unlock_irq(&hid->inlock); + del_timer(&hid->io_retry); usb_kill_urb(hid->urbin); dev_dbg(&intf->dev, "suspend\n"); return 0; @@ -1944,10 +2057,8 @@ static int hid_resume(struct usb_interface *intf) struct hid_device *hid = usb_get_intfdata (intf); int status; - if (hid->open) - status = usb_submit_urb(hid->urbin, GFP_NOIO); - else - status = 0; + clear_bit(HID_SUSPENDED, &hid->iofl); + status = hid_start_in(hid); dev_dbg(&intf->dev, "resume status %d\n", status); return status; } diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 8b0d4346ce9c..4e1b784fe527 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h @@ -31,6 +31,8 @@ #include #include #include +#include +#include /* * USB HID (Human Interface Device) interface class code @@ -370,6 +372,9 @@ struct hid_control_fifo { #define HID_CTRL_RUNNING 1 #define HID_OUT_RUNNING 2 +#define HID_IN_RUNNING 3 +#define HID_RESET_PENDING 4 +#define HID_SUSPENDED 5 struct hid_input { struct list_head list; @@ -393,12 +398,17 @@ struct hid_device { /* device report descriptor */ int ifnum; /* USB interface number */ unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ + struct timer_list io_retry; /* Retry timer */ + unsigned long stop_retry; /* Time to give up, in jiffies */ + unsigned int retry_delay; /* Delay length in ms */ + struct work_struct reset_work; /* Task context for resets */ unsigned int bufsize; /* URB buffer size */ struct urb *urbin; /* Input URB */ char *inbuf; /* Input buffer */ dma_addr_t inbuf_dma; /* Input buffer dma */ + spinlock_t inlock; /* Input fifo spinlock */ struct urb *urbctrl; /* Control URB */ struct usb_ctrlrequest *cr; /* Control request struct */ -- cgit v1.2.3-59-g8ed1b From efafe6fb72b2bbab40080a08f7946f1eadb9bad9 Mon Sep 17 00:00:00 2001 From: Malte Doersam Date: Sat, 28 Jan 2006 17:48:33 +0100 Subject: [PATCH] USB: Pegasus: Linksys USBVPN1 support + cleanup This patch adds a second linksys vendor-id (077b) and the product id of the pegasus based adapter USBVPN1 http://www1.linksys.com/Products/product.asp?prid=3D543&scid=3D30 Furthermore it replaces all LINKSYS_GPIO_RESET with DEFAULT_GPIO_RESET as both are declared like this: #define DEFAULT_GPIO_RESET 0x24 #define LINKSYS_GPIO_RESET 0x24 This is misleading and confusing. The check is now done via the VENDOR_ID in pegasus.c: if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS Signed-off-by: Malte Doersam Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/pegasus.c | 1 + drivers/usb/net/pegasus.h | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 156a2f1cb39a..5b6675684567 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -524,6 +524,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb) ret = set_registers(pegasus, EthCtrl0, 3, data); if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || + usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS2 || usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) { u16 auxmode; read_mii_word(pegasus, 0, 0x1b, &auxmode); diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h index 9fbd59b55cb6..a54752ce1493 100644 --- a/drivers/usb/net/pegasus.h +++ b/drivers/usb/net/pegasus.h @@ -25,7 +25,6 @@ #define PHY_READ 0x40 #define PHY_WRITE 0x20 #define DEFAULT_GPIO_RESET 0x24 -#define LINKSYS_GPIO_RESET 0x24 #define DEFAULT_GPIO_SET 0x26 #define PEGASUS_PRESENT 0x00000001 @@ -140,6 +139,7 @@ struct usb_eth_dev { #define VENDOR_KINGSTON 0x0951 #define VENDOR_LANEED 0x056e #define VENDOR_LINKSYS 0x066b +#define VENDOR_LINKSYS2 0x077b #define VENDOR_MELCO 0x0411 #define VENDOR_MICROSOFT 0x045e #define VENDOR_MOBILITY 0x1342 @@ -218,15 +218,15 @@ PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004, PEGASUS_DEV( "Corega FEter USB-TXS", VENDOR_COREGA, 0x000d, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001, - LINKSYS_GPIO_RESET ) + DEFAULT_GPIO_RESET ) PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4002, - LINKSYS_GPIO_RESET ) + DEFAULT_GPIO_RESET ) PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4102, - LINKSYS_GPIO_RESET | PEGASUS_II ) + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x400b, - LINKSYS_GPIO_RESET | PEGASUS_II ) + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x200c, - LINKSYS_GPIO_RESET | PEGASUS_II ) + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "D-Link DSB-650TX(PNA)", VENDOR_DLINK, 0x4003, DEFAULT_GPIO_RESET | HAS_HOME_PNA ) PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1, @@ -260,17 +260,19 @@ PEGASUS_DEV( "LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1, PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x200c, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x2202, - LINKSYS_GPIO_RESET ) + DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2203, - LINKSYS_GPIO_RESET ) + DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2204, - LINKSYS_GPIO_RESET | HAS_HOME_PNA ) + DEFAULT_GPIO_RESET | HAS_HOME_PNA ) PEGASUS_DEV( "Linksys USB10T Ethernet Adapter", VENDOR_LINKSYS, 0x2206, - LINKSYS_GPIO_RESET | PEGASUS_II) + DEFAULT_GPIO_RESET | PEGASUS_II) +PEGASUS_DEV( "Linksys USBVPN1", VENDOR_LINKSYS2, 0x08b4, + DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Linksys USB USB100TX", VENDOR_LINKSYS, 0x400b, - LINKSYS_GPIO_RESET | PEGASUS_II ) + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x200c, - LINKSYS_GPIO_RESET | PEGASUS_II ) + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005, -- cgit v1.2.3-59-g8ed1b From 0eb8c7cafe8d4fa9a90ea8680200e3ae3d57b1bd Mon Sep 17 00:00:00 2001 From: Franck Bui-Huu Date: Tue, 7 Feb 2006 09:06:17 +0100 Subject: [PATCH] USB: Zero driver: Removed duplicated code Signed-off-by: Franck Bui-Huu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/zero.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index ae7a1c0f5748..5e9fe8a70543 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -1224,12 +1224,6 @@ autoconf_fail: loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - if (gadget->is_otg) { - otg_descriptor.bmAttributes |= USB_OTG_HNP, - source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - } - usb_gadget_set_selfpowered (gadget); init_timer (&dev->resume); -- cgit v1.2.3-59-g8ed1b From 499003e815344304c7b0c93aad923ddf644d24e0 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 24 Jan 2006 08:11:27 -0800 Subject: [PATCH] USB: Fix masking bug initialization of Freescale EHCI controller In setting up the of PHY we masked off too many bits, instead just initialize PORTSC for the type of PHY we are using. Signed-off-by: Kumar Gala Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 59f90f76ee31..f985f121a245 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -160,8 +160,7 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci, enum fsl_usb2_phy_modes phy_mode, unsigned int port_offset) { - u32 portsc = readl(&ehci->regs->port_status[port_offset]); - portsc &= ~PORT_PTS_MSK; + u32 portsc = 0; switch (phy_mode) { case FSL_USB2_PHY_ULPI: portsc |= PORT_PTS_ULPI; -- cgit v1.2.3-59-g8ed1b From dccf4a48d47120a42382ba526f1a0848c13ba2a4 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Sat, 17 Dec 2005 17:58:46 -0500 Subject: [PATCH] UHCI: use one QH per endpoint, not per URB This patch (as623) changes the uhci-hcd driver to make it use one QH per device endpoint, instead of a QH per URB as it does now. Numerous areas of the code are affected by this. For example, the distinction between "queued" URBs and non-"queued" URBs no longer exists; all URBs belong to a queue and some just happen to be at the queue's head. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 320 ++++---------- drivers/usb/host/uhci-hcd.c | 65 ++- drivers/usb/host/uhci-hcd.h | 177 ++++---- drivers/usb/host/uhci-q.c | 985 +++++++++++++++++++----------------------- 4 files changed, 685 insertions(+), 862 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 5832953086f8..3faccbd68547 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -90,13 +90,60 @@ static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space) return out - buf; } -static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) +static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) { char *out = buf; - struct urb_priv *urbp; - struct list_head *head, *tmp; struct uhci_td *td; - int i = 0, checked = 0, prevactive = 0; + int i, nactive, ninactive; + + if (len < 200) + return 0; + + out += sprintf(out, "urb_priv [%p] ", urbp); + out += sprintf(out, "urb [%p] ", urbp->urb); + out += sprintf(out, "qh [%p] ", urbp->qh); + out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe)); + out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), + (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; + } + + out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : "")); + out += sprintf(out, "%s", (urbp->fsbr_timeout ? " FSBR_TO" : "")); + + if (urbp->urb->status != -EINPROGRESS) + out += sprintf(out, " Status=%d", urbp->urb->status); + out += sprintf(out, "\n"); + + i = nactive = ninactive = 0; + list_for_each_entry(td, &urbp->td_list, list) { + if (++i <= 10 || debug > 2) { + out += sprintf(out, "%*s%d: ", space + 2, "", i); + out += uhci_show_td(td, out, len - (out - buf), 0); + } else { + if (td_status(td) & TD_CTRL_ACTIVE) + ++nactive; + else + ++ninactive; + } + } + if (nactive + ninactive > 0) + out += sprintf(out, "%*s[skipped %d inactive and %d active " + "TDs]\n", + space, "", ninactive, nactive); + + return out - buf; +} + +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); /* Try to make sure there's enough memory */ @@ -118,86 +165,36 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) if (!(element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH))) out += sprintf(out, "%*s Element is NULL (bug?)\n", space, ""); - if (!qh->urbp) { - out += sprintf(out, "%*s urbp == NULL\n", space, ""); - goto out; - } - - urbp = qh->urbp; - - head = &urbp->td_list; - tmp = head->next; - - td = list_entry(tmp, struct uhci_td, list); - - if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS)) - out += sprintf(out, "%*s Element != First TD\n", space, ""); - - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - out += sprintf(out, "%*s%d: ", space + 2, "", i++); - out += uhci_show_td(td, out, len - (out - buf), 0); - - if (i > 10 && !checked && prevactive && tmp != head && - debug <= 2) { - struct list_head *ntmp = tmp; - struct uhci_td *ntd = td; - int active = 1, ni = i; - - checked = 1; - - while (ntmp != head && ntmp->next != head && active) { - ntd = list_entry(ntmp, struct uhci_td, list); - - ntmp = ntmp->next; - - active = td_status(ntd) & TD_CTRL_ACTIVE; - - ni++; - } - - if (active && ni > i) { - out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i); - tmp = ntmp; - td = ntd; - i = ni; - } + if (list_empty(&qh->queue)) { + out += sprintf(out, "%*s queue is empty\n", space, ""); + } else { + struct urb_priv *urbp = list_entry(qh->queue.next, + struct urb_priv, node); + struct uhci_td *td = list_entry(urbp->td_list.next, + struct uhci_td, list); + + if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS)) + out += sprintf(out, "%*s Element != First TD\n", + space, ""); + i = nurbs = 0; + list_for_each_entry(urbp, &qh->queue, node) { + if (++i <= 10) + out += uhci_show_urbp(urbp, out, + len - (out - buf), space + 2); + else + ++nurbs; } - - prevactive = td_status(td) & TD_CTRL_ACTIVE; - } - - if (list_empty(&urbp->queue_list) || urbp->queued) - goto out; - - out += sprintf(out, "%*sQueued QHs:\n", -space, "--"); - - head = &urbp->queue_list; - tmp = head->next; - - while (tmp != head) { - struct urb_priv *nurbp = list_entry(tmp, struct urb_priv, - queue_list); - tmp = tmp->next; - - out += uhci_show_qh(nurbp->qh, out, len - (out - buf), space); + if (nurbs > 0) + out += sprintf(out, "%*s Skipped %d URBs\n", + space, "", nurbs); } -out: return out - buf; } -#define show_frame_num() \ - if (!shown) { \ - shown = 1; \ - out += sprintf(out, "- Frame %d\n", i); \ - } - #ifdef CONFIG_PROC_FS static const char * const qh_names[] = { + "skel_unlink_qh", "skel_iso_qh", "skel_int128_qh", "skel_int64_qh", "skel_int32_qh", "skel_int16_qh", "skel_int8_qh", "skel_int4_qh", @@ -206,12 +203,6 @@ static const char * const qh_names[] = { "skel_bulk_qh", "skel_term_qh" }; -#define show_qh_name() \ - if (!shown) { \ - shown = 1; \ - out += sprintf(out, "- %s\n", qh_names[i]); \ - } - static int uhci_show_sc(int port, unsigned short status, char *buf, int len) { char *out = buf; @@ -321,139 +312,29 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) return out - buf; } -static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *buf, int len) -{ - struct list_head *tmp; - char *out = buf; - int count = 0; - - if (len < 200) - return 0; - - out += sprintf(out, "urb_priv [%p] ", urbp); - out += sprintf(out, "urb [%p] ", urbp->urb); - out += sprintf(out, "qh [%p] ", urbp->qh); - out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe)); - out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), (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; - } - - out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : "")); - out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " : "")); - - if (urbp->urb->status != -EINPROGRESS) - out += sprintf(out, "Status=%d ", urbp->urb->status); - //out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime); - - count = 0; - list_for_each(tmp, &urbp->td_list) - count++; - out += sprintf(out, "TDs=%d ",count); - - if (urbp->queued) - out += sprintf(out, "queued\n"); - else { - count = 0; - list_for_each(tmp, &urbp->queue_list) - count++; - out += sprintf(out, "queued URBs=%d\n", count); - } - - return out - buf; -} - -static int uhci_show_lists(struct uhci_hcd *uhci, char *buf, int len) -{ - char *out = buf; - struct list_head *head, *tmp; - int count; - - out += sprintf(out, "Main list URBs:"); - if (list_empty(&uhci->urb_list)) - out += sprintf(out, " Empty\n"); - else { - out += sprintf(out, "\n"); - count = 0; - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); - - out += sprintf(out, " %d: ", ++count); - out += uhci_show_urbp(uhci, urbp, out, len - (out - buf)); - tmp = tmp->next; - } - } - - out += sprintf(out, "Remove list URBs:"); - if (list_empty(&uhci->urb_remove_list)) - out += sprintf(out, " Empty\n"); - else { - out += sprintf(out, "\n"); - count = 0; - head = &uhci->urb_remove_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); - - out += sprintf(out, " %d: ", ++count); - out += uhci_show_urbp(uhci, urbp, out, len - (out - buf)); - tmp = tmp->next; - } - } - - out += sprintf(out, "Complete list URBs:"); - if (list_empty(&uhci->complete_list)) - out += sprintf(out, " Empty\n"); - else { - out += sprintf(out, "\n"); - count = 0; - head = &uhci->complete_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); - - out += sprintf(out, " %d: ", ++count); - out += uhci_show_urbp(uhci, urbp, out, len - (out - buf)); - tmp = tmp->next; - } - } - - return out - buf; -} - static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) { - unsigned long flags; char *out = buf; int i, j; struct uhci_qh *qh; struct uhci_td *td; struct list_head *tmp, *head; - spin_lock_irqsave(&uhci->lock, flags); - out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); out += sprintf(out, "HC status\n"); out += uhci_show_status(uhci, out, len - (out - buf)); + if (debug <= 1) + return out - buf; out += sprintf(out, "Frame List\n"); for (i = 0; i < UHCI_NUMFRAMES; ++i) { - int shown = 0; td = uhci->frame_cpu[i]; if (!td) continue; - if (td->dma_handle != (dma_addr_t)uhci->frame[i]) { - show_frame_num(); + out += sprintf(out, "- Frame %d\n", i); \ + if (td->dma_handle != (dma_addr_t)uhci->frame[i]) out += sprintf(out, " frame list does not match td->dma_handle!\n"); - } - show_frame_num(); head = &td->fl_list; tmp = head; @@ -467,14 +348,11 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) out += sprintf(out, "Skeleton QHs\n"); for (i = 0; i < UHCI_NUM_SKELQH; ++i) { - int shown = 0; + int cnt = 0; qh = uhci->skelqh[i]; - - if (debug > 1) { - show_qh_name(); - out += uhci_show_qh(qh, out, len - (out - buf), 4); - } + out += sprintf(out, "- %s\n", qh_names[i]); \ + out += uhci_show_qh(qh, out, len - (out - buf), 4); /* Last QH is the Terminating QH, it's different */ if (i == UHCI_NUM_SKELQH - 1) { @@ -487,44 +365,27 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) continue; } - j = (i < 7) ? 7 : i+1; /* Next skeleton */ - if (list_empty(&qh->list)) { - if (i < UHCI_NUM_SKELQH - 1) { - if (qh->link != - (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) { - show_qh_name(); - out += sprintf(out, " skeleton QH not linked to next skeleton QH!\n"); - } - } - - continue; - } - - show_qh_name(); - - head = &qh->list; + j = (i < 9) ? 9 : i+1; /* Next skeleton */ + head = &qh->node; tmp = head->next; while (tmp != head) { - qh = list_entry(tmp, struct uhci_qh, list); - + qh = list_entry(tmp, struct uhci_qh, node); tmp = tmp->next; - - out += uhci_show_qh(qh, out, len - (out - buf), 4); + if (++cnt <= 10) + out += uhci_show_qh(qh, out, + len - (out - buf), 4); } + if ((cnt -= 10) > 0) + out += sprintf(out, " Skipped %d QHs\n", cnt); - if (i < UHCI_NUM_SKELQH - 1) { + if (i > 1 && i < UHCI_NUM_SKELQH - 1) { if (qh->link != (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) out += sprintf(out, " last QH not linked to next skeleton!\n"); } } - if (debug > 2) - out += uhci_show_lists(uhci, out, len - (out - buf)); - - spin_unlock_irqrestore(&uhci->lock, flags); - return out - buf; } @@ -541,6 +402,7 @@ static int uhci_debug_open(struct inode *inode, struct file *file) struct uhci_hcd *uhci = inode->u.generic_ip; struct uhci_debug *up; int ret = -ENOMEM; + unsigned long flags; lock_kernel(); up = kmalloc(sizeof(*up), GFP_KERNEL); @@ -553,7 +415,9 @@ static int uhci_debug_open(struct inode *inode, struct file *file) goto out; } + spin_lock_irqsave(&uhci->lock, flags); up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); + spin_unlock_irqrestore(&uhci->lock, flags); file->private_data = up; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index dfe121d35887..1ff4b8806372 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -54,7 +54,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v2.3" +#define DRIVER_VERSION "v3.0" #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ Alan Stern" @@ -489,15 +489,11 @@ static int uhci_start(struct usb_hcd *hcd) uhci->fsbrtimeout = 0; spin_lock_init(&uhci->lock); - INIT_LIST_HEAD(&uhci->qh_remove_list); INIT_LIST_HEAD(&uhci->td_remove_list); - - INIT_LIST_HEAD(&uhci->urb_remove_list); - INIT_LIST_HEAD(&uhci->urb_list); - INIT_LIST_HEAD(&uhci->complete_list); + INIT_LIST_HEAD(&uhci->idle_qh_list); init_waitqueue_head(&uhci->waitqh); @@ -540,7 +536,7 @@ static int uhci_start(struct usb_hcd *hcd) } for (i = 0; i < UHCI_NUM_SKELQH; i++) { - uhci->skelqh[i] = uhci_alloc_qh(uhci); + uhci->skelqh[i] = uhci_alloc_qh(uhci, NULL, NULL); if (!uhci->skelqh[i]) { dev_err(uhci_dev(uhci), "unable to allocate QH\n"); goto err_alloc_skelqh; @@ -557,13 +553,17 @@ static int uhci_start(struct usb_hcd *hcd) uhci->skel_int16_qh->link = uhci->skel_int8_qh->link = uhci->skel_int4_qh->link = - uhci->skel_int2_qh->link = - cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int1_qh->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH; - - uhci->skel_ls_control_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_fs_control_qh->link = cpu_to_le32(uhci->skel_bulk_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH; + uhci->skel_int2_qh->link = UHCI_PTR_QH | + cpu_to_le32(uhci->skel_int1_qh->dma_handle); + + uhci->skel_int1_qh->link = UHCI_PTR_QH | + cpu_to_le32(uhci->skel_ls_control_qh->dma_handle); + uhci->skel_ls_control_qh->link = UHCI_PTR_QH | + cpu_to_le32(uhci->skel_fs_control_qh->dma_handle); + uhci->skel_fs_control_qh->link = UHCI_PTR_QH | + cpu_to_le32(uhci->skel_bulk_qh->dma_handle); + uhci->skel_bulk_qh->link = UHCI_PTR_QH | + cpu_to_le32(uhci->skel_term_qh->dma_handle); /* This dummy TD is to work around a bug in Intel PIIX controllers */ uhci_fill_td(uhci->term_td, 0, uhci_explen(0) | @@ -589,15 +589,15 @@ static int uhci_start(struct usb_hcd *hcd) /* * ffs (Find First bit Set) does exactly what we need: - * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[6], - * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[5], etc. - * ffs > 6 => not on any high-period queue, so use - * skel_int1_qh = skelqh[7]. + * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8], + * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc. + * ffs >= 7 => not on any high-period queue, so use + * skel_int1_qh = skelqh[9]. * Add UHCI_NUMFRAMES to insure at least one bit is set. */ - irq = 6 - (int) __ffs(i + UHCI_NUMFRAMES); - if (irq < 0) - irq = 7; + irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES); + if (irq <= 1) + irq = 9; /* Only place we don't use the frame list routines */ uhci->frame[i] = UHCI_PTR_QH | @@ -767,13 +767,30 @@ static int uhci_resume(struct usb_hcd *hcd) } #endif -/* Wait until all the URBs for a particular device/endpoint are gone */ +/* Wait until a particular device/endpoint's QH is idle, and free it */ static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd, - struct usb_host_endpoint *ep) + struct usb_host_endpoint *hep) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); + struct uhci_qh *qh; + + spin_lock_irq(&uhci->lock); + qh = (struct uhci_qh *) hep->hcpriv; + if (qh == NULL) + goto done; - wait_event_interruptible(uhci->waitqh, list_empty(&ep->urb_list)); + while (qh->state != QH_STATE_IDLE) { + ++uhci->num_waiting; + spin_unlock_irq(&uhci->lock); + wait_event_interruptible(uhci->waitqh, + qh->state == QH_STATE_IDLE); + spin_lock_irq(&uhci->lock); + --uhci->num_waiting; + } + + uhci_free_qh(uhci, qh); +done: + spin_unlock_irq(&uhci->lock); } static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 8b4b887a7d41..7a9481c09a05 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -28,8 +28,9 @@ #define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ #define USBSTS_ERROR 0x0002 /* Interrupt due to error */ #define USBSTS_RD 0x0004 /* Resume Detect */ -#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ -#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ +#define USBSTS_HSE 0x0008 /* Host System Error: PCI problems */ +#define USBSTS_HCPE 0x0010 /* Host Controller Process Error: + * the schedule is buggy */ #define USBSTS_HCH 0x0020 /* HC Halted */ /* Interrupt enable register */ @@ -47,7 +48,8 @@ /* USB port status and control registers */ #define USBPORTSC1 16 #define USBPORTSC2 18 -#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ +#define USBPORTSC_CCS 0x0001 /* Current Connect Status + * ("device present") */ #define USBPORTSC_CSC 0x0002 /* Connect Status Change */ #define USBPORTSC_PE 0x0004 /* Port Enable */ #define USBPORTSC_PEC 0x0008 /* Port Enable Change */ @@ -71,15 +73,16 @@ #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ -#define UHCI_PTR_BITS cpu_to_le32(0x000F) -#define UHCI_PTR_TERM cpu_to_le32(0x0001) -#define UHCI_PTR_QH cpu_to_le32(0x0002) -#define UHCI_PTR_DEPTH cpu_to_le32(0x0004) -#define UHCI_PTR_BREADTH cpu_to_le32(0x0000) +#define UHCI_PTR_BITS __constant_cpu_to_le32(0x000F) +#define UHCI_PTR_TERM __constant_cpu_to_le32(0x0001) +#define UHCI_PTR_QH __constant_cpu_to_le32(0x0002) +#define UHCI_PTR_DEPTH __constant_cpu_to_le32(0x0004) +#define UHCI_PTR_BREADTH __constant_cpu_to_le32(0x0000) #define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ -#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ +#define CAN_SCHEDULE_FRAMES 1000 /* how far in the future frames + * can be scheduled */ /* @@ -87,38 +90,54 @@ */ /* - * One role of a QH is to hold a queue of TDs for some endpoint. Each QH is - * used with one URB, and qh->element (updated by the HC) is either: - * - the next unprocessed TD for the URB, or - * - UHCI_PTR_TERM (when there's no more traffic for this endpoint), or - * - the QH for the next URB queued to the same endpoint. + * One role of a QH is to hold a queue of TDs for some endpoint. One QH goes + * with each endpoint, and qh->element (updated by the HC) is either: + * - the next unprocessed TD in the endpoint's queue, or + * - UHCI_PTR_TERM (when there's no more traffic for this endpoint). * * The other role of a QH is to serve as a "skeleton" framelist entry, so we * can easily splice a QH for some endpoint into the schedule at the right * place. Then qh->element is UHCI_PTR_TERM. * - * In the frame list, qh->link maintains a list of QHs seen by the HC: + * In the schedule, qh->link maintains a list of QHs seen by the HC: * skel1 --> ep1-qh --> ep2-qh --> ... --> skel2 --> ... + * + * qh->node is the software equivalent of qh->link. The differences + * are that the software list is doubly-linked and QHs in the UNLINKING + * state are on the software list but not the hardware schedule. + * + * For bookkeeping purposes we maintain QHs even for Isochronous endpoints, + * but they never get added to the hardware schedule. */ +#define QH_STATE_IDLE 1 /* QH is not being used */ +#define QH_STATE_UNLINKING 2 /* QH has been removed from the + * schedule but the hardware may + * still be using it */ +#define QH_STATE_ACTIVE 3 /* QH is on the schedule */ + struct uhci_qh { /* Hardware fields */ - __le32 link; /* Next queue */ - __le32 element; /* Queue element pointer */ + __le32 link; /* Next QH in the schedule */ + __le32 element; /* Queue element (TD) pointer */ /* Software fields */ dma_addr_t dma_handle; - struct urb_priv *urbp; + struct list_head node; /* Node in the list of QHs */ + struct usb_host_endpoint *hep; /* Endpoint information */ + struct usb_device *udev; + struct list_head queue; /* Queue of urbps for this QH */ + struct uhci_qh *skel; /* Skeleton for this QH */ - struct list_head list; - struct list_head remove_list; + unsigned int unlink_frame; /* When the QH was unlinked */ + int state; /* QH_STATE_xxx; see above */ } __attribute__((aligned(16))); /* * We need a special accessor for the element pointer because it is * subject to asynchronous updates by the controller. */ -static __le32 inline qh_element(struct uhci_qh *qh) { +static inline __le32 qh_element(struct uhci_qh *qh) { __le32 element = qh->element; barrier(); @@ -149,11 +168,13 @@ static __le32 inline qh_element(struct uhci_qh *qh) { #define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */ #define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ - TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) + TD_CTRL_BABBLE | TD_CTRL_CRCTIME | \ + TD_CTRL_BITSTUFF) #define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT) #define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xF60000) -#define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ +#define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & \ + TD_CTRL_ACTLEN_MASK) /* 1-based */ /* * for TD : (a.k.a. Token) @@ -163,7 +184,7 @@ static __le32 inline qh_element(struct uhci_qh *qh) { #define TD_TOKEN_TOGGLE_SHIFT 19 #define TD_TOKEN_TOGGLE (1 << 19) #define TD_TOKEN_EXPLEN_SHIFT 21 -#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n - 1 */ +#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n-1 */ #define TD_TOKEN_PID_MASK 0xFF #define uhci_explen(len) ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \ @@ -187,7 +208,7 @@ static __le32 inline qh_element(struct uhci_qh *qh) { * sw space after the TD entry. * * td->link points to either another TD (not necessarily for the same urb or - * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs). + * even the same endpoint), or nothing (PTR_TERM), or a QH. */ struct uhci_td { /* Hardware fields */ @@ -210,7 +231,7 @@ struct uhci_td { * We need a special accessor for the control/status word because it is * subject to asynchronous updates by the controller. */ -static u32 inline td_status(struct uhci_td *td) { +static inline u32 td_status(struct uhci_td *td) { __le32 status = td->status; barrier(); @@ -223,17 +244,14 @@ static u32 inline td_status(struct uhci_td *td) { */ /* - * The UHCI driver places Interrupt, Control and Bulk into QHs both - * to group together TDs for one transfer, and also to facilitate queuing - * of URBs. To make it easy to insert entries into the schedule, we have - * a skeleton of QHs for each predefined Interrupt latency, low-speed - * control, full-speed control and terminating QH (see explanation for - * the terminating QH below). + * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for + * automatic queuing. To make it easy to insert entries into the schedule, + * we have a skeleton of QHs for each predefined Interrupt latency, + * low-speed control, full-speed control, bulk, and terminating QH + * (see explanation for the terminating QH below). * * When we want to add a new QH, we add it to the end of the list for the - * skeleton QH. - * - * For instance, the queue can look like this: + * skeleton QH. For instance, the schedule list can look like this: * * skel int128 QH * dev 1 interrupt QH @@ -256,26 +274,31 @@ static u32 inline td_status(struct uhci_td *td) { * - To loop back to the full-speed control queue for full-speed bandwidth * reclamation. * - * Isochronous transfers are stored before the start of the skeleton - * schedule and don't use QHs. While the UHCI spec doesn't forbid the - * use of QHs for Isochronous, it doesn't use them either. And the spec - * says that queues never advance on an error completion status, which - * makes them totally unsuitable for Isochronous transfers. + * There's a special skeleton QH for Isochronous QHs. It never appears + * on the schedule, and Isochronous TDs go on the schedule before the + * the skeleton QHs. The hardware accesses them directly rather than + * through their QH, which is used only for bookkeeping purposes. + * While the UHCI spec doesn't forbid the use of QHs for Isochronous, + * it doesn't use them either. And the spec says that queues never + * advance on an error completion status, which makes them totally + * unsuitable for Isochronous transfers. */ -#define UHCI_NUM_SKELQH 12 -#define skel_int128_qh skelqh[0] -#define skel_int64_qh skelqh[1] -#define skel_int32_qh skelqh[2] -#define skel_int16_qh skelqh[3] -#define skel_int8_qh skelqh[4] -#define skel_int4_qh skelqh[5] -#define skel_int2_qh skelqh[6] -#define skel_int1_qh skelqh[7] -#define skel_ls_control_qh skelqh[8] -#define skel_fs_control_qh skelqh[9] -#define skel_bulk_qh skelqh[10] -#define skel_term_qh skelqh[11] +#define UHCI_NUM_SKELQH 14 +#define skel_unlink_qh skelqh[0] +#define skel_iso_qh skelqh[1] +#define skel_int128_qh skelqh[2] +#define skel_int64_qh skelqh[3] +#define skel_int32_qh skelqh[4] +#define skel_int16_qh skelqh[5] +#define skel_int8_qh skelqh[6] +#define skel_int4_qh skelqh[7] +#define skel_int2_qh skelqh[8] +#define skel_int1_qh skelqh[9] +#define skel_ls_control_qh skelqh[10] +#define skel_fs_control_qh skelqh[11] +#define skel_bulk_qh skelqh[12] +#define skel_term_qh skelqh[13] /* * Search tree for determining where fits in the skelqh[] @@ -293,21 +316,21 @@ static inline int __interval_to_skel(int interval) if (interval < 16) { if (interval < 4) { if (interval < 2) - return 7; /* int1 for 0-1 ms */ - return 6; /* int2 for 2-3 ms */ + return 9; /* int1 for 0-1 ms */ + return 8; /* int2 for 2-3 ms */ } if (interval < 8) - return 5; /* int4 for 4-7 ms */ - return 4; /* int8 for 8-15 ms */ + return 7; /* int4 for 4-7 ms */ + return 6; /* int8 for 8-15 ms */ } if (interval < 64) { if (interval < 32) - return 3; /* int16 for 16-31 ms */ - return 2; /* int32 for 32-63 ms */ + return 5; /* int16 for 16-31 ms */ + return 4; /* int32 for 32-63 ms */ } if (interval < 128) - return 1; /* int64 for 64-127 ms */ - return 0; /* int128 for 128-255 ms (Max.) */ + return 3; /* int64 for 64-127 ms */ + return 2; /* int128 for 128-255 ms (Max.) */ } @@ -363,12 +386,12 @@ struct uhci_hcd { spinlock_t lock; - dma_addr_t frame_dma_handle; /* Hardware frame list */ + dma_addr_t frame_dma_handle; /* Hardware frame list */ __le32 *frame; - void **frame_cpu; /* CPU's frame list */ + void **frame_cpu; /* CPU's frame list */ - int fsbr; /* Full-speed bandwidth reclamation */ - unsigned long fsbrtimeout; /* FSBR delay */ + int fsbr; /* Full-speed bandwidth reclamation */ + unsigned long fsbrtimeout; /* FSBR delay */ enum uhci_rh_state rh_state; unsigned long auto_stop_time; /* When to AUTO_STOP */ @@ -392,24 +415,19 @@ struct uhci_hcd { /* Main list of URBs currently controlled by this HC */ struct list_head urb_list; - /* List of QHs that are done, but waiting to be unlinked (race) */ - struct list_head qh_remove_list; - unsigned int qh_remove_age; /* Age in frames */ - /* 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 */ - /* List of asynchronously unlinked URBs */ - struct list_head urb_remove_list; - unsigned int urb_remove_age; /* Age in frames */ - /* List of URBs awaiting completion callback */ struct list_head complete_list; + struct list_head idle_qh_list; /* Where the idle QHs live */ + int rh_numports; /* Number of root-hub ports */ wait_queue_head_t waitqh; /* endpoint_disable waiters */ + int num_waiting; /* Number of waiters */ }; /* Convert between a usb_hcd pointer and the corresponding uhci_hcd */ @@ -430,22 +448,19 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci) */ struct urb_priv { struct list_head urb_list; + struct list_head node; /* Node in the QH's urbp list */ struct urb *urb; struct uhci_qh *qh; /* QH for this URB */ struct list_head td_list; - unsigned fsbr : 1; /* URB turned on FSBR */ - unsigned fsbr_timeout : 1; /* URB timed out on FSBR */ - unsigned queued : 1; /* QH was queued (not linked in) */ - unsigned short_control_packet : 1; /* If we get a short packet during */ - /* a control transfer, retrigger */ - /* the status phase */ - unsigned long fsbrtime; /* In jiffies */ - struct list_head queue_list; + unsigned fsbr : 1; /* URB turned on FSBR */ + unsigned fsbr_timeout : 1; /* URB timed out 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 782398045f9f..b1b551a3d14e 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -13,13 +13,9 @@ * (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 Alan Stern, stern@rowland.harvard.edu + * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu */ -static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb); -static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb); -static void uhci_remove_pending_urbps(struct uhci_hcd *uhci); -static void uhci_free_pending_qhs(struct uhci_hcd *uhci); static void uhci_free_pending_tds(struct uhci_hcd *uhci); /* @@ -30,7 +26,7 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci); * games with the FSBR code to make sure we get the correct order in all * the cases. I don't think it's worth the effort */ -static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) +static void uhci_set_next_interrupt(struct uhci_hcd *uhci) { if (uhci->is_stopped) mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); @@ -42,12 +38,6 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC); } -static inline void uhci_moveto_complete(struct uhci_hcd *uhci, - struct urb_priv *urbp) -{ - list_move_tail(&urbp->urb_list, &uhci->complete_list); -} - static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) { dma_addr_t dma_handle; @@ -71,6 +61,18 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) return td; } +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); + + dma_pool_free(uhci->td_pool, td, td->dma_handle); +} + static inline void uhci_fill_td(struct uhci_td *td, u32 status, u32 token, u32 buffer) { @@ -82,7 +84,8 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status, /* * We insert Isochronous URBs directly into the frame list at the beginning */ -static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum) +static inline void uhci_insert_td_in_frame_list(struct uhci_hcd *uhci, + struct uhci_td *td, unsigned framenum) { framenum &= (UHCI_NUMFRAMES - 1); @@ -108,7 +111,7 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, } } -static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci, +static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci, struct uhci_td *td) { /* If it's not inserted, don't remove it */ @@ -139,48 +142,68 @@ static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci, td->frame = -1; } -static void unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb) +/* + * Remove all the TDs for an Isochronous URB from the frame list + */ +static void uhci_unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb) { struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; struct uhci_td *td; list_for_each_entry(td, &urbp->td_list, list) - uhci_remove_td_frame_list(uhci, td); + uhci_remove_td_from_frame_list(uhci, td); wmb(); } /* - * Inserts a td list into qh. + * Remove an URB's TDs from the hardware schedule */ -static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth) +static void uhci_remove_tds_from_schedule(struct uhci_hcd *uhci, + struct urb *urb, int status) { - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td; - __le32 *plink; + struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - /* Ordering isn't important here yet since the QH hasn't been */ - /* inserted into the schedule yet */ - plink = &qh->element; - list_for_each_entry(td, &urbp->td_list, list) { - *plink = cpu_to_le32(td->dma_handle) | breadth; - plink = &td->link; + /* Isochronous TDs get unlinked directly from the frame list */ + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { + uhci_unlink_isochronous_tds(uhci, urb); + return; } - *plink = UHCI_PTR_TERM; -} -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); + /* If the URB isn't first on its queue, adjust the link pointer + * of the last TD in the previous URB. */ + if (urbp->node.prev != &urbp->qh->queue) { + struct urb_priv *purbp; + struct uhci_td *ptd, *ltd; + + if (status == -EINPROGRESS) + status = 0; + purbp = list_entry(urbp->node.prev, struct urb_priv, node); + 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; + } - dma_pool_free(uhci->td_pool, td, td->dma_handle); + /* If the URB completed with an error, then the QH element certainly + * points to one of the URB's TDs. If it completed normally then + * the QH element has certainly moved on to the next URB. And if + * the URB is still in progress then it must have been dequeued. + * The QH element either hasn't reached it yet or is somewhere in + * the middle. If the URB wasn't first we can assume that it + * hasn't started yet (see above): Otherwise all the preceding URBs + * would have completed and been removed from the queue, so this one + * _would_ be first. + * + * If the QH element is inside this URB, clear it. It will be + * set properly when the QH is activated. + */ + if (status < 0) + urbp->qh->element = UHCI_PTR_TERM; } -static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci) +static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, + struct usb_device *udev, struct usb_host_endpoint *hep) { dma_addr_t dma_handle; struct uhci_qh *qh; @@ -194,256 +217,120 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci) qh->element = UHCI_PTR_TERM; qh->link = UHCI_PTR_TERM; - qh->urbp = NULL; + INIT_LIST_HEAD(&qh->queue); + INIT_LIST_HEAD(&qh->node); - INIT_LIST_HEAD(&qh->list); - INIT_LIST_HEAD(&qh->remove_list); + if (udev) { /* Normal QH */ + qh->state = QH_STATE_IDLE; + qh->hep = hep; + qh->udev = udev; + hep->hcpriv = qh; + usb_get_dev(udev); + } else { /* Skeleton QH */ + qh->state = QH_STATE_ACTIVE; + qh->udev = NULL; + } return qh; } static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { - if (!list_empty(&qh->list)) + WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); + if (!list_empty(&qh->queue)) dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh); - if (!list_empty(&qh->remove_list)) - dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh); + list_del(&qh->node); + if (qh->udev) { + qh->hep->hcpriv = NULL; + usb_put_dev(qh->udev); + } dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); } /* - * Append this urb's qh after the last qh in skelqh->list - * - * Note that urb_priv.queue_list doesn't have a separate queue head; - * it's a ring with every element "live". + * Put a QH on the schedule in both hardware and software */ -static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb) +static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct urb_priv *turbp; - struct uhci_qh *lqh; + struct uhci_qh *pqh; - /* Grab the last QH */ - lqh = list_entry(skelqh->list.prev, struct uhci_qh, list); + WARN_ON(list_empty(&qh->queue)); - /* Point to the next skelqh */ - urbp->qh->link = lqh->link; - wmb(); /* Ordering is important */ + /* Set the element pointer if it isn't set already. + * This isn't needed for Isochronous queues, but it doesn't hurt. */ + if (qh_element(qh) == UHCI_PTR_TERM) { + struct urb_priv *urbp = list_entry(qh->queue.next, + struct urb_priv, node); + struct uhci_td *td = list_entry(urbp->td_list.next, + struct uhci_td, list); - /* - * Patch QHs for previous endpoint's queued URBs? HC goes - * here next, not to the next skelqh it now points to. - * - * lqh --> td ... --> qh ... --> td --> qh ... --> td - * | | | - * v v v - * +<----------------+-----------------+ - * v - * newqh --> td ... --> td - * | - * v - * ... - * - * The HC could see (and use!) any of these as we write them. - */ - lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; - if (lqh->urbp) { - list_for_each_entry(turbp, &lqh->urbp->queue_list, queue_list) - turbp->qh->link = lqh->link; + qh->element = cpu_to_le32(td->dma_handle); } - list_add_tail(&urbp->qh->list, &skelqh->list); + if (qh->state == QH_STATE_ACTIVE) + return; + qh->state = QH_STATE_ACTIVE; + + /* Move the QH from its old list to the end of the appropriate + * skeleton's list */ + list_move_tail(&qh->node, &qh->skel->node); + + /* Link it into the schedule */ + pqh = list_entry(qh->node.prev, struct uhci_qh, node); + qh->link = pqh->link; + wmb(); + pqh->link = UHCI_PTR_QH | cpu_to_le32(qh->dma_handle); } /* - * Start removal of QH from schedule; it finishes next frame. - * TDs should be unlinked before this is called. + * Take a QH off the hardware schedule */ -static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) +static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { struct uhci_qh *pqh; - __le32 newlink; - if (!qh) + if (qh->state == QH_STATE_UNLINKING) return; + WARN_ON(qh->state != QH_STATE_ACTIVE || !qh->udev); + qh->state = QH_STATE_UNLINKING; - /* - * Only go through the hoops if it's actually linked in - */ - if (!list_empty(&qh->list)) { - - /* If our queue is nonempty, make the next URB the head */ - if (!list_empty(&qh->urbp->queue_list)) { - struct urb_priv *nurbp; - - nurbp = list_entry(qh->urbp->queue_list.next, - struct urb_priv, queue_list); - nurbp->queued = 0; - list_add(&nurbp->qh->list, &qh->list); - newlink = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH; - } else - newlink = qh->link; - - /* Fix up the previous QH's queue to link to either - * the new head of this queue or the start of the - * next endpoint's queue. */ - pqh = list_entry(qh->list.prev, struct uhci_qh, list); - pqh->link = newlink; - if (pqh->urbp) { - struct urb_priv *turbp; - - list_for_each_entry(turbp, &pqh->urbp->queue_list, - queue_list) - turbp->qh->link = newlink; - } - wmb(); - - /* Leave qh->link in case the HC is on the QH now, it will */ - /* continue the rest of the schedule */ - qh->element = UHCI_PTR_TERM; - - list_del_init(&qh->list); - } - - list_del_init(&qh->urbp->queue_list); - qh->urbp = NULL; + /* Unlink the QH from the schedule and record when we did it */ + pqh = list_entry(qh->node.prev, struct uhci_qh, node); + pqh->link = qh->link; + mb(); uhci_get_current_frame_number(uhci); - if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) { - uhci_free_pending_qhs(uhci); - uhci->qh_remove_age = uhci->frame_number; - } + qh->unlink_frame = 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 QH */ - if (list_empty(&uhci->qh_remove_list)) + /* Force an interrupt so we know when the QH is fully unlinked */ + if (list_empty(&uhci->skel_unlink_qh->node)) uhci_set_next_interrupt(uhci); - list_add(&qh->remove_list, &uhci->qh_remove_list); + /* Move the QH from its old list to the end of the unlinking list */ + list_move_tail(&qh->node, &uhci->skel_unlink_qh->node); } -static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td; - - list_for_each_entry(td, &urbp->td_list, list) { - if (toggle) - td->token |= cpu_to_le32(TD_TOKEN_TOGGLE); - else - td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE); - - toggle ^= 1; - } - - return toggle; -} - -/* This function will append one URB's QH to another URB's QH. This is for */ -/* queuing interrupt, control or bulk transfers */ -static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb) -{ - struct urb_priv *eurbp, *urbp, *furbp, *lurbp; - struct uhci_td *lltd; - - eurbp = eurb->hcpriv; - urbp = urb->hcpriv; - - /* Find the first URB in the queue */ - furbp = eurbp; - if (eurbp->queued) { - list_for_each_entry(furbp, &eurbp->queue_list, queue_list) - if (!furbp->queued) - break; - } - - lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list); - - lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list); - - /* Control transfers always start with toggle 0 */ - if (!usb_pipecontrol(urb->pipe)) - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe), - uhci_fixup_toggle(urb, - uhci_toggle(td_token(lltd)) ^ 1)); - - /* All qhs in the queue need to link to the next queue */ - urbp->qh->link = eurbp->qh->link; - - wmb(); /* Make sure we flush everything */ - - lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; - - list_add_tail(&urbp->queue_list, &furbp->queue_list); - - urbp->queued = 1; -} - -static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb) +/* + * When we and the controller are through with a QH, it becomes IDLE. + * This happens when a QH has been off the schedule (on the unlinking + * list) for more than one frame, or when an error occurs while adding + * the first URB onto a new QH. + */ +static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh) { - struct urb_priv *urbp, *nurbp, *purbp, *turbp; - struct uhci_td *pltd; - unsigned int toggle; - - urbp = urb->hcpriv; - - if (list_empty(&urbp->queue_list)) - return; - - nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list); - - /* - * Fix up the toggle for the following URBs in the queue. - * Only needed for bulk and interrupt: control and isochronous - * endpoints don't propagate toggles between messages. - */ - if (usb_pipebulk(urb->pipe) || usb_pipeint(urb->pipe)) { - if (!urbp->queued) - /* We just set the toggle in uhci_unlink_generic */ - toggle = usb_gettoggle(urb->dev, - usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)); - else { - /* If we're in the middle of the queue, grab the */ - /* toggle from the TD previous to us */ - purbp = list_entry(urbp->queue_list.prev, - struct urb_priv, queue_list); - pltd = list_entry(purbp->td_list.prev, - struct uhci_td, list); - toggle = uhci_toggle(td_token(pltd)) ^ 1; - } - - list_for_each_entry(turbp, &urbp->queue_list, queue_list) { - if (!turbp->queued) - break; - toggle = uhci_fixup_toggle(turbp->urb, toggle); - } + WARN_ON(qh->state == QH_STATE_ACTIVE); - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe), toggle); - } - - if (urbp->queued) { - /* We're somewhere in the middle (or end). The case where - * we're at the head is handled in uhci_remove_qh(). */ - purbp = list_entry(urbp->queue_list.prev, struct urb_priv, - queue_list); - - pltd = list_entry(purbp->td_list.prev, struct uhci_td, list); - if (nurbp->queued) - pltd->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH; - else - /* The next URB happens to be the beginning, so */ - /* we're the last, end the chain */ - pltd->link = UHCI_PTR_TERM; - } + list_move(&qh->node, &uhci->idle_qh_list); + qh->state = QH_STATE_IDLE; - /* urbp->queue_list is handled in uhci_remove_qh() */ + /* If anyone is waiting for a QH to become idle, wake them up */ + if (uhci->num_waiting) + wake_up_all(&uhci->waitqh); } -static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *urb) +static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, + struct urb *urb) { struct urb_priv *urbp; @@ -453,17 +340,14 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u memset((void *)urbp, 0, sizeof(*urbp)); - urbp->fsbrtime = jiffies; urbp->urb = urb; + urb->hcpriv = urbp; + urbp->fsbrtime = jiffies; + INIT_LIST_HEAD(&urbp->node); INIT_LIST_HEAD(&urbp->td_list); - INIT_LIST_HEAD(&urbp->queue_list); INIT_LIST_HEAD(&urbp->urb_list); - list_add_tail(&urbp->urb_list, &uhci->urb_list); - - urb->hcpriv = urbp; - return urbp; } @@ -482,18 +366,17 @@ static void uhci_remove_td_from_urb(struct uhci_td *td) list_del_init(&td->list); } -static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) +static void uhci_free_urb_priv(struct uhci_hcd *uhci, + struct urb_priv *urbp) { struct uhci_td *td, *tmp; - struct urb_priv *urbp; - - urbp = (struct urb_priv *)urb->hcpriv; - if (!urbp) - return; if (!list_empty(&urbp->urb_list)) - dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list " - "or uhci->remove_list!\n", urb); + dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list!\n", + urbp->urb); + if (!list_empty(&urbp->node)) + 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) { @@ -502,7 +385,7 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) } /* Check to see if the remove list is empty. Set the IOC bit */ - /* to force an interrupt so we can remove the TDs*/ + /* to force an interrupt so we can remove the TDs. */ if (list_empty(&uhci->td_remove_list)) uhci_set_next_interrupt(uhci); @@ -511,7 +394,7 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) list_add(&td->remove_list, &uhci->td_remove_list); } - urb->hcpriv = NULL; + urbp->urb->hcpriv = NULL; kmem_cache_free(uhci_up_cachep, urbp); } @@ -567,18 +450,83 @@ static int uhci_map_status(int status, int dir_out) return 0; } +/* + * Fix up the data toggles for URBs in a queue, when one of them + * terminates early (short transfer, error, or dequeued). + */ +static void uhci_fixup_toggles(struct urb *urb) +{ + struct list_head *head; + struct uhci_td *td; + struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; + int prevactive = 0; + unsigned int toggle = 0; + struct urb_priv *turbp, *list_end; + + /* + * We need to find out what the last successful toggle was so + * we can update the data toggles for the following transfers. + * + * There are 2 ways the last successful completed TD is found: + * + * 1) The TD is NOT active and the actual length < expected length + * 2) The TD is NOT active and it's the last TD in the chain + * + * and a third way the first uncompleted TD is found: + * + * 3) The TD is active and the previous TD is NOT active + */ + head = &urbp->td_list; + list_for_each_entry(td, head, list) { + unsigned int ctrlstat = td_status(td); + + if (!(ctrlstat & TD_CTRL_ACTIVE) && + (uhci_actual_length(ctrlstat) < + uhci_expected_length(td_token(td)) || + td->list.next == head)) + toggle = uhci_toggle(td_token(td)) ^ 1; + else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive) + toggle = uhci_toggle(td_token(td)); + + prevactive = ctrlstat & TD_CTRL_ACTIVE; + } + + /* + * Fix up the toggle for the following URBs in the queue. + * + * We can stop as soon as we find an URB with toggles set correctly, + * because then all the following URBs will be correct also. + */ + list_end = list_entry(&urbp->qh->queue, struct urb_priv, node); + turbp = urbp; + while ((turbp = list_entry(turbp->node.next, struct urb_priv, node)) + != list_end) { + td = list_entry(turbp->td_list.next, struct uhci_td, list); + if (uhci_toggle(td_token(td)) == toggle) + return; + + list_for_each_entry(td, &turbp->td_list, list) { + td->token ^= __constant_cpu_to_le32(TD_TOKEN_TOGGLE); + toggle ^= 1; + } + } + + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe), toggle); +} + /* * Control transfers */ -static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) +static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, + struct uhci_qh *qh) { - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; struct uhci_td *td; - struct uhci_qh *qh, *skelqh; unsigned long destination, status; - int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); + int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); int len = urb->transfer_buffer_length; dma_addr_t data = urb->transfer_dma; + __le32 *plink; /* The "pipe" thing contains the destination in bits 8--18 */ destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; @@ -597,7 +545,8 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur uhci_add_td_to_urb(urb, td); uhci_fill_td(td, status, destination | uhci_explen(8), - urb->setup_dma); + urb->setup_dma); + plink = &td->link; /* * If direction is "send", change the packet ID from SETUP (0x2D) @@ -615,21 +564,20 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur * Build the DATA TDs */ while (len > 0) { - int pktsze = len; - - if (pktsze > maxsze) - pktsze = maxsze; + int pktsze = min(len, maxsze); td = uhci_alloc_td(uhci); if (!td) return -ENOMEM; + *plink = cpu_to_le32(td->dma_handle); /* Alternate Data0/1 (start with Data1) */ destination ^= TD_TOKEN_TOGGLE; uhci_add_td_to_urb(urb, td); uhci_fill_td(td, status, destination | uhci_explen(pktsze), - data); + data); + plink = &td->link; data += pktsze; len -= pktsze; @@ -641,6 +589,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur td = uhci_alloc_td(uhci); if (!td) return -ENOMEM; + *plink = cpu_to_le32(td->dma_handle); /* * It's IN if the pipe is an output pipe or we're not expecting @@ -658,16 +607,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur uhci_add_td_to_urb(urb, td); uhci_fill_td(td, status | TD_CTRL_IOC, - destination | uhci_explen(0), 0); - - qh = uhci_alloc_qh(uhci); - if (!qh) - return -ENOMEM; - - urbp->qh = qh; - qh->urbp = urbp; - - uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); + destination | uhci_explen(0), 0); /* Low-speed transfers get a different queue, and won't hog the bus. * Also, some devices enumerate better without FSBR; the easiest way @@ -675,18 +615,13 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur * isn't in the CONFIGURED state. */ if (urb->dev->speed == USB_SPEED_LOW || urb->dev->state != USB_STATE_CONFIGURED) - skelqh = uhci->skel_ls_control_qh; + qh->skel = uhci->skel_ls_control_qh; else { - skelqh = uhci->skel_fs_control_qh; + qh->skel = uhci->skel_fs_control_qh; uhci_inc_fsbr(uhci, urb); } - if (eurb) - uhci_append_queued_urb(uhci, eurb, urb); - else - uhci_insert_qh(uhci, skelqh, urb); - - return -EINPROGRESS; + return 0; } /* @@ -703,7 +638,7 @@ 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_control_packet = 1; + urbp->short_transfer = 1; td = list_entry(urbp->td_list.prev, struct uhci_td, list); urbp->qh->element = cpu_to_le32(td->dma_handle); @@ -720,16 +655,14 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) unsigned int status; int ret = 0; - if (list_empty(&urbp->td_list)) - return -EINVAL; - head = &urbp->td_list; - - if (urbp->short_control_packet) { + 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); @@ -742,8 +675,6 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) if (status) goto td_error; - urb->actual_length = 0; - /* The rest of the TDs (but the last) are data */ tmp = tmp->next; while (tmp != head && tmp->next != head) { @@ -770,10 +701,7 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) goto err; } - if (uhci_packetid(td_token(td)) == USB_PID_IN) - return usb_control_retrigger_status(uhci, urb); - else - return 0; + return usb_control_retrigger_status(uhci, urb); } } @@ -825,15 +753,15 @@ err: /* * Common submit for bulk and interrupt */ -static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb, struct uhci_qh *skelqh) +static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, + struct uhci_qh *qh) { struct uhci_td *td; - struct uhci_qh *qh; unsigned long destination, status; - int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); + int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); int len = urb->transfer_buffer_length; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; dma_addr_t data = urb->transfer_dma; + __le32 *plink, fake_link; if (len < 0) return -EINVAL; @@ -841,7 +769,8 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb /* The "pipe" thing contains the destination in bits 8--18 */ destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); - status = uhci_maxerr(3) | TD_CTRL_ACTIVE; + /* 3 errors */ + status = TD_CTRL_ACTIVE | uhci_maxerr(3); if (urb->dev->speed == USB_SPEED_LOW) status |= TD_CTRL_LS; if (usb_pipein(urb->pipe)) @@ -850,10 +779,11 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb /* * Build the DATA TDs */ + plink = &fake_link; do { /* Allow zero length packets */ int pktsze = maxsze; - if (pktsze >= len) { + if (len <= pktsze) { /* The last packet */ pktsze = len; if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) status &= ~TD_CTRL_SPD; @@ -862,12 +792,15 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb td = uhci_alloc_td(uhci); if (!td) return -ENOMEM; + *plink = cpu_to_le32(td->dma_handle); uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(pktsze) | + uhci_fill_td(td, status, + destination | uhci_explen(pktsze) | (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), data); + plink = &td->link; data += pktsze; len -= maxsze; @@ -883,11 +816,13 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb * however, if transfer_length == 0, the zero packet was already * prepared above. */ - if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) && - !len && urb->transfer_buffer_length) { + if ((urb->transfer_flags & URB_ZERO_PACKET) && + usb_pipeout(urb->pipe) && len == 0 && + urb->transfer_buffer_length > 0) { td = uhci_alloc_td(uhci); if (!td) return -ENOMEM; + *plink = cpu_to_le32(td->dma_handle); uhci_add_td_to_urb(urb, td); uhci_fill_td(td, status, destination | uhci_explen(0) | @@ -905,24 +840,9 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb * fast side but not enough to justify delaying an interrupt * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT * flag setting. */ - td->status |= cpu_to_le32(TD_CTRL_IOC); - - qh = uhci_alloc_qh(uhci); - if (!qh) - return -ENOMEM; - - urbp->qh = qh; - qh->urbp = urbp; + td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); - /* Always breadth first */ - uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); - - if (eurb) - uhci_append_queued_urb(uhci, eurb, urb); - else - uhci_insert_qh(uhci, skelqh, urb); - - return -EINPROGRESS; + return 0; } /* @@ -954,8 +874,24 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) if (urb->transfer_flags & URB_SHORT_NOT_OK) { ret = -EREMOTEIO; goto err; - } else - return 0; + } + + /* + * 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; + uhci_fixup_toggles(urb); + td = list_entry(urbp->td_list.prev, + struct uhci_td, list); + urbp->qh->element = td->link; + } + break; } } @@ -988,7 +924,8 @@ err: return ret; } -static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) +static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, + struct uhci_qh *qh) { int ret; @@ -996,21 +933,22 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struc if (urb->dev->speed == USB_SPEED_LOW) return -EINVAL; - ret = uhci_submit_common(uhci, urb, eurb, uhci->skel_bulk_qh); - if (ret == -EINPROGRESS) + qh->skel = uhci->skel_bulk_qh; + ret = uhci_submit_common(uhci, urb, qh); + if (ret == 0) uhci_inc_fsbr(uhci, urb); - return ret; } -static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) +static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, + struct uhci_qh *qh) { - /* USB 1.1 interrupt transfers only involve one packet per interval; - * that's the uhci_submit_common() "breadth first" policy. Drivers - * can submit urbs of any length, but longer ones might need many - * intervals to complete. + /* 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. */ - return uhci_submit_common(uhci, urb, eurb, uhci->skelqh[__interval_to_skel(urb->interval)]); + qh->skel = uhci->skelqh[__interval_to_skel(urb->interval)]; + return uhci_submit_common(uhci, urb, qh); } /* @@ -1072,11 +1010,12 @@ static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb) /* * Isochronous transfers */ -static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) +static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, + struct uhci_qh *qh) { - struct uhci_td *td; + struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */ int i, ret, frame; - int status, destination; + unsigned long destination, status; struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; status = TD_CTRL_ACTIVE | TD_CTRL_IOS; @@ -1092,20 +1031,25 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) return -ENOMEM; uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length), - urb->transfer_dma + urb->iso_frame_desc[i].offset); - - if (i + 1 >= urb->number_of_packets) - td->status |= cpu_to_le32(TD_CTRL_IOC); + uhci_fill_td(td, status, destination | + uhci_explen(urb->iso_frame_desc[i].length), + urb->transfer_dma + + urb->iso_frame_desc[i].offset); } + /* Set the interrupt-on-completion flag on the last packet. */ + td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); + + qh->skel = uhci->skel_iso_qh; + + /* Add the TDs to the frame list */ frame = urb->start_frame; list_for_each_entry(td, &urbp->td_list, list) { - uhci_insert_td_frame_list(uhci, td, frame); + uhci_insert_td_in_frame_list(uhci, td, frame); frame += urb->interval; } - return -EINPROGRESS; + return 0; } static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) @@ -1139,80 +1083,67 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) i++; } - unlink_isochronous_tds(uhci, urb); return ret; } -static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *up; - - /* We don't match Isoc transfers since they are special */ - if (usb_pipeisoc(urb->pipe)) - return NULL; - - list_for_each_entry(up, &uhci->urb_list, urb_list) { - struct urb *u = up->urb; - - if (u->dev == urb->dev && u->status == -EINPROGRESS) { - /* For control, ignore the direction */ - if (usb_pipecontrol(urb->pipe) && - (u->pipe & ~USB_DIR_IN) == (urb->pipe & ~USB_DIR_IN)) - return u; - else if (u->pipe == urb->pipe) - return u; - } - } - - return NULL; -} - static int uhci_urb_enqueue(struct usb_hcd *hcd, - struct usb_host_endpoint *ep, + struct usb_host_endpoint *hep, struct urb *urb, gfp_t mem_flags) { int ret; struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned long flags; - struct urb *eurb; + struct urb_priv *urbp; + struct uhci_qh *qh; int bustime; spin_lock_irqsave(&uhci->lock, flags); ret = urb->status; if (ret != -EINPROGRESS) /* URB already unlinked! */ - goto out; + goto done; - eurb = uhci_find_urb_ep(uhci, urb); + ret = -ENOMEM; + urbp = uhci_alloc_urb_priv(uhci, urb); + if (!urbp) + goto done; - if (!uhci_alloc_urb_priv(uhci, urb)) { - ret = -ENOMEM; - goto out; + if (hep->hcpriv) + qh = (struct uhci_qh *) hep->hcpriv; + else { + qh = uhci_alloc_qh(uhci, urb->dev, hep); + if (!qh) + goto err_no_qh; } + urbp->qh = qh; switch (usb_pipetype(urb->pipe)) { case PIPE_CONTROL: - ret = uhci_submit_control(uhci, urb, eurb); + ret = uhci_submit_control(uhci, urb, qh); + break; + case PIPE_BULK: + ret = uhci_submit_bulk(uhci, urb, qh); break; case PIPE_INTERRUPT: - if (!eurb) { + if (list_empty(&qh->queue)) { bustime = usb_check_bandwidth(urb->dev, urb); if (bustime < 0) ret = bustime; else { - ret = uhci_submit_interrupt(uhci, urb, eurb); - if (ret == -EINPROGRESS) + ret = uhci_submit_interrupt(uhci, urb, qh); + if (ret == 0) usb_claim_bandwidth(urb->dev, urb, bustime, 0); } } else { /* inherit from parent */ - urb->bandwidth = eurb->bandwidth; - ret = uhci_submit_interrupt(uhci, urb, eurb); + struct urb_priv *eurbp; + + eurbp = list_entry(qh->queue.prev, struct urb_priv, + node); + urb->bandwidth = eurbp->urb->bandwidth; + ret = uhci_submit_interrupt(uhci, urb, qh); } break; - case PIPE_BULK: - ret = uhci_submit_bulk(uhci, urb, eurb); - break; case PIPE_ISOCHRONOUS: bustime = usb_check_bandwidth(urb->dev, urb); if (bustime < 0) { @@ -1220,22 +1151,59 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, break; } - ret = uhci_submit_isochronous(uhci, urb); - if (ret == -EINPROGRESS) + ret = uhci_submit_isochronous(uhci, urb, qh); + if (ret == 0) usb_claim_bandwidth(urb->dev, urb, bustime, 1); break; } + if (ret != 0) + goto err_submit_failed; - if (ret != -EINPROGRESS) { - /* Submit failed, so delete it from the urb_list */ - struct urb_priv *urbp = urb->hcpriv; + /* Add this URB to the QH */ + urbp->qh = qh; + list_add_tail(&urbp->node, &qh->queue); + list_add_tail(&urbp->urb_list, &uhci->urb_list); - list_del_init(&urbp->urb_list); - uhci_destroy_urb_priv(uhci, urb); - } else - ret = 0; + /* 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) + uhci_activate_qh(uhci, qh); + + /* If the QH is already active, we have a race with the hardware. + * This won't get fixed until dummy TDs are added. */ + else if (qh->state == QH_STATE_ACTIVE) { + + /* If the URB isn't first on its queue, adjust the link pointer + * of the last TD in the previous URB. */ + if (urbp->node.prev != &urbp->qh->queue) { + struct urb_priv *purbp = list_entry(urbp->node.prev, + struct urb_priv, node); + struct uhci_td *ptd = list_entry(purbp->td_list.prev, + struct uhci_td, list); + struct uhci_td *td = list_entry(urbp->td_list.next, + struct uhci_td, list); + + ptd->link = cpu_to_le32(td->dma_handle); + + } + if (qh_element(qh) == UHCI_PTR_TERM) { + struct uhci_td *td = list_entry(urbp->td_list.next, + struct uhci_td, list); + + qh->element = cpu_to_le32(td->dma_handle); + } + } + goto done; + +err_submit_failed: + if (qh->state == QH_STATE_IDLE) + uhci_make_qh_idle(uhci, qh); /* Reclaim unused QH */ -out: +err_no_qh: + uhci_free_urb_priv(uhci, urbp); + +done: spin_unlock_irqrestore(&uhci->lock, flags); return ret; } @@ -1245,119 +1213,115 @@ out: */ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb) { - int ret = -EINPROGRESS; - struct urb_priv *urbp; - - spin_lock(&urb->lock); - - urbp = (struct urb_priv *)urb->hcpriv; - - if (urb->status != -EINPROGRESS) /* URB already dequeued */ - goto out; + int status; + int okay_to_giveback = 0; + struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; switch (usb_pipetype(urb->pipe)) { case PIPE_CONTROL: - ret = uhci_result_control(uhci, urb); - break; - case PIPE_BULK: - case PIPE_INTERRUPT: - ret = uhci_result_common(uhci, urb); + status = uhci_result_control(uhci, urb); break; case PIPE_ISOCHRONOUS: - ret = uhci_result_isochronous(uhci, urb); + status = uhci_result_isochronous(uhci, urb); + break; + default: /* PIPE_BULK or PIPE_INTERRUPT */ + status = uhci_result_common(uhci, urb); break; } - if (ret == -EINPROGRESS) - goto out; - urb->status = ret; + spin_lock(&urb->lock); + if (urb->status == -EINPROGRESS) { /* Not yet dequeued */ + if (status != -EINPROGRESS) { /* URB has completed */ + urb->status = status; + + /* If the URB got a real error (as opposed to + * simply being dequeued), we don't have to + * unlink the QH. Fix this later... */ + if (status < 0) + uhci_unlink_qh(uhci, urbp->qh); + else + okay_to_giveback = 1; + } + } else { /* Already dequeued */ + if (urbp->qh->state == QH_STATE_UNLINKING && + uhci->frame_number + uhci->is_stopped != + urbp->qh->unlink_frame) + okay_to_giveback = 1; + } + spin_unlock(&urb->lock); + if (!okay_to_giveback) + return; switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: - case PIPE_BULK: case PIPE_ISOCHRONOUS: /* Release bandwidth for Interrupt or Isoc. transfers */ if (urb->bandwidth) usb_release_bandwidth(urb->dev, urb, 1); - uhci_unlink_generic(uhci, urb); break; case PIPE_INTERRUPT: /* Release bandwidth for Interrupt or Isoc. transfers */ /* Make sure we don't release if we have a queued URB */ - if (list_empty(&urbp->queue_list) && urb->bandwidth) + if (list_empty(&urbp->qh->queue) && urb->bandwidth) usb_release_bandwidth(urb->dev, urb, 0); else /* bandwidth was passed on to queued URB, */ /* so don't let usb_unlink_urb() release it */ urb->bandwidth = 0; - uhci_unlink_generic(uhci, urb); + /* Falls through */ + case PIPE_BULK: + if (status < 0) + uhci_fixup_toggles(urb); + break; + default: /* PIPE_CONTROL */ break; - default: - dev_info(uhci_dev(uhci), "%s: unknown pipe type %d " - "for urb %p\n", - __FUNCTION__, usb_pipetype(urb->pipe), urb); } - /* Move it from uhci->urb_list to uhci->complete_list */ - uhci_moveto_complete(uhci, urbp); + /* Take the URB's TDs off the hardware schedule */ + uhci_remove_tds_from_schedule(uhci, urb, status); -out: - spin_unlock(&urb->lock); -} - -static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb) -{ - struct list_head *head; - struct uhci_td *td; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - int prevactive = 0; + /* Take the URB off the QH's queue and see if the QH is now unused */ + list_del_init(&urbp->node); + if (list_empty(&urbp->qh->queue)) + uhci_unlink_qh(uhci, urbp->qh); uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ - /* - * Now we need to find out what the last successful toggle was - * so we can update the local data toggle for the next transfer - * - * There are 2 ways the last successful completed TD is found: - * - * 1) The TD is NOT active and the actual length < expected length - * 2) The TD is NOT active and it's the last TD in the chain - * - * and a third way the first uncompleted TD is found: - * - * 3) The TD is active and the previous TD is NOT active - * - * Control and Isochronous ignore the toggle, so this is safe - * for all types - * - * FIXME: The toggle fixups won't be 100% reliable until we - * change over to using a single queue for each endpoint and - * stop the queue before unlinking. - */ - head = &urbp->td_list; - list_for_each_entry(td, head, list) { - unsigned int ctrlstat = td_status(td); + /* Queue it for giving back */ + list_move_tail(&urbp->urb_list, &uhci->complete_list); +} - if (!(ctrlstat & TD_CTRL_ACTIVE) && - (uhci_actual_length(ctrlstat) < - uhci_expected_length(td_token(td)) || - td->list.next == head)) - usb_settoggle(urb->dev, uhci_endpoint(td_token(td)), - uhci_packetout(td_token(td)), - uhci_toggle(td_token(td)) ^ 1); - else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive) - usb_settoggle(urb->dev, uhci_endpoint(td_token(td)), - uhci_packetout(td_token(td)), - uhci_toggle(td_token(td))); +/* + * Check out the QHs waiting to be fully unlinked + */ +static void uhci_scan_unlinking_qhs(struct uhci_hcd *uhci) +{ + struct uhci_qh *qh, *tmp; - prevactive = ctrlstat & TD_CTRL_ACTIVE; - } + list_for_each_entry_safe(qh, tmp, &uhci->skel_unlink_qh->node, node) { - uhci_delete_queued_urb(uhci, urb); + /* If the queue is empty and the QH is fully unlinked then + * it can become IDLE. */ + if (list_empty(&qh->queue)) { + if (uhci->frame_number + uhci->is_stopped != + qh->unlink_frame) + uhci_make_qh_idle(uhci, qh); - /* The interrupt loop will reclaim the QHs */ - uhci_remove_qh(uhci, urbp->qh); - urbp->qh = NULL; + /* If none of the QH's URBs have been dequeued then the QH + * should be re-activated. */ + } else { + struct urb_priv *urbp; + int any_dequeued = 0; + + list_for_each_entry(urbp, &qh->queue, node) { + if (urbp->urb->status != -EINPROGRESS) { + any_dequeued = 1; + break; + } + } + if (!any_dequeued) + uhci_activate_qh(uhci, qh); + } + } } static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) @@ -1370,22 +1334,11 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) urbp = urb->hcpriv; if (!urbp) /* URB was never linked! */ goto done; - list_del_init(&urbp->urb_list); + /* Remove Isochronous TDs from the frame list ASAP */ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) - unlink_isochronous_tds(uhci, urb); - uhci_unlink_generic(uhci, urb); - - uhci_get_current_frame_number(uhci); - if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) { - uhci_remove_pending_urbps(uhci); - uhci->urb_remove_age = uhci->frame_number; - } - - /* If we're the first, set the next interrupt bit */ - if (list_empty(&uhci->urb_remove_list)) - uhci_set_next_interrupt(uhci); - list_add_tail(&urbp->urb_list, &uhci->urb_remove_list); + uhci_unlink_isochronous_tds(uhci, urb); + uhci_unlink_qh(uhci, urbp->qh); done: spin_unlock_irqrestore(&uhci->lock, flags); @@ -1426,17 +1379,6 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb) return 0; } -static void uhci_free_pending_qhs(struct uhci_hcd *uhci) -{ - struct uhci_qh *qh, *tmp; - - list_for_each_entry_safe(qh, tmp, &uhci->qh_remove_list, remove_list) { - list_del_init(&qh->remove_list); - - uhci_free_qh(uhci, qh); - } -} - static void uhci_free_pending_tds(struct uhci_hcd *uhci) { struct uhci_td *td, *tmp; @@ -1455,7 +1397,7 @@ __acquires(uhci->lock) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - uhci_destroy_urb_priv(uhci, urb); + uhci_free_urb_priv(uhci, (struct urb_priv *) (urb->hcpriv)); spin_unlock(&uhci->lock); usb_hcd_giveback_urb(hcd, urb, regs); @@ -1474,13 +1416,6 @@ static void uhci_finish_completion(struct uhci_hcd *uhci, struct pt_regs *regs) } } -static void uhci_remove_pending_urbps(struct uhci_hcd *uhci) -{ - - /* Splice the urb_remove_list onto the end of the complete_list */ - list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev); -} - /* Process events in the schedule, but only in one thread at a time */ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) { @@ -1498,12 +1433,8 @@ 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->qh_remove_age) - uhci_free_pending_qhs(uhci); if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) uhci_free_pending_tds(uhci); - if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) - uhci_remove_pending_urbps(uhci); /* Walk the list of pending URBs to see which ones completed * (must be _safe because uhci_transfer_result() dequeues URBs) */ @@ -1516,25 +1447,21 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) uhci_finish_completion(uhci, regs); /* If the controller is stopped, we can finish these off right now */ - if (uhci->is_stopped) { - uhci_free_pending_qhs(uhci); + if (uhci->is_stopped) uhci_free_pending_tds(uhci); - uhci_remove_pending_urbps(uhci); - } if (uhci->need_rescan) goto rescan; uhci->scan_in_progress = 0; - if (list_empty(&uhci->urb_remove_list) && - list_empty(&uhci->td_remove_list) && - list_empty(&uhci->qh_remove_list)) + /* Check out the QHs waiting for unlinking */ + uhci_scan_unlinking_qhs(uhci); + + if (list_empty(&uhci->td_remove_list) && + list_empty(&uhci->skel_unlink_qh->node)) uhci_clear_next_interrupt(uhci); else uhci_set_next_interrupt(uhci); - - /* Wake up anyone waiting for an URB to complete */ - wake_up_all(&uhci->waitqh); } static void check_fsbr(struct uhci_hcd *uhci) -- cgit v1.2.3-59-g8ed1b From af0bb5998abe8ed28ee354dd4c71689cacdc91e9 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Sat, 17 Dec 2005 18:00:12 -0500 Subject: [PATCH] UHCI: use dummy TDs This patch (as624) fixes a hardware race in uhci-hcd by adding a dummy TD to the end of each endpoint's queue. Without the dummy the host controller will effectively turn off the queue when it reaches the end, which happens asynchronously. This leads to a potential problem when new transfer descriptors are added to the end of the queue; they may never get used. With a dummy TD present the controller never turns off the queue; instead it just stops at the dummy and leaves the queue on but inactive. When new TDs are added to the end of the queue, the first new one gets written over the dummy. Thus there's never any question about whether the queue is running or needs to be restarted. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 5 ++ drivers/usb/host/uhci-hcd.h | 1 + drivers/usb/host/uhci-q.c | 138 +++++++++++++++++++++++------------------- 3 files changed, 83 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 3faccbd68547..6814783adf91 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -189,6 +189,11 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) space, "", nurbs); } + if (qh->udev) { + out += sprintf(out, "%*s Dummy TD\n", space, ""); + out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0); + } + return out - buf; } diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 7a9481c09a05..c057956667b5 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -128,6 +128,7 @@ struct uhci_qh { struct usb_device *udev; 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 */ unsigned int unlink_frame; /* When the QH was unlinked */ int state; /* QH_STATE_xxx; see above */ diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index b1b551a3d14e..c4194182dcc4 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -48,10 +48,6 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) return NULL; td->dma_handle = dma_handle; - - td->link = UHCI_PTR_TERM; - td->buffer = 0; - td->frame = -1; INIT_LIST_HEAD(&td->list); @@ -221,6 +217,11 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, INIT_LIST_HEAD(&qh->node); if (udev) { /* Normal QH */ + qh->dummy_td = uhci_alloc_td(uhci); + if (!qh->dummy_td) { + dma_pool_free(uhci->qh_pool, qh, dma_handle); + return NULL; + } qh->state = QH_STATE_IDLE; qh->hep = hep; qh->udev = udev; @@ -244,6 +245,7 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) if (qh->udev) { qh->hep->hcpriv = NULL; usb_put_dev(qh->udev); + uhci_free_td(uhci, qh->dummy_td); } dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); } @@ -531,22 +533,20 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, /* The "pipe" thing contains the destination in bits 8--18 */ destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; - /* 3 errors */ - status = TD_CTRL_ACTIVE | uhci_maxerr(3); + /* 3 errors, dummy TD remains inactive */ + status = uhci_maxerr(3); if (urb->dev->speed == USB_SPEED_LOW) status |= TD_CTRL_LS; /* * Build the TD for the control request setup packet */ - td = uhci_alloc_td(uhci); - if (!td) - return -ENOMEM; - + td = qh->dummy_td; uhci_add_td_to_urb(urb, td); uhci_fill_td(td, status, destination | uhci_explen(8), urb->setup_dma); plink = &td->link; + status |= TD_CTRL_ACTIVE; /* * If direction is "send", change the packet ID from SETUP (0x2D) @@ -568,7 +568,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, td = uhci_alloc_td(uhci); if (!td) - return -ENOMEM; + goto nomem; *plink = cpu_to_le32(td->dma_handle); /* Alternate Data0/1 (start with Data1) */ @@ -588,7 +588,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, */ td = uhci_alloc_td(uhci); if (!td) - return -ENOMEM; + goto nomem; *plink = cpu_to_le32(td->dma_handle); /* @@ -608,6 +608,20 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, uhci_add_td_to_urb(urb, td); uhci_fill_td(td, status | TD_CTRL_IOC, destination | uhci_explen(0), 0); + plink = &td->link; + + /* + * Build the new dummy TD and activate the old one + */ + td = uhci_alloc_td(uhci); + if (!td) + goto nomem; + *plink = cpu_to_le32(td->dma_handle); + + uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); + wmb(); + qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); + qh->dummy_td = td; /* Low-speed transfers get a different queue, and won't hog the bus. * Also, some devices enumerate better without FSBR; the easiest way @@ -620,8 +634,12 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, qh->skel = uhci->skel_fs_control_qh; uhci_inc_fsbr(uhci, urb); } - return 0; + +nomem: + /* Remove the dummy TD from the td_list so it doesn't get freed */ + uhci_remove_td_from_urb(qh->dummy_td); + return -ENOMEM; } /* @@ -761,16 +779,19 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); int len = urb->transfer_buffer_length; dma_addr_t data = urb->transfer_dma; - __le32 *plink, fake_link; + __le32 *plink; + unsigned int toggle; if (len < 0) return -EINVAL; /* The "pipe" thing contains the destination in bits 8--18 */ destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); + toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe)); - /* 3 errors */ - status = TD_CTRL_ACTIVE | uhci_maxerr(3); + /* 3 errors, dummy TD remains inactive */ + status = uhci_maxerr(3); if (urb->dev->speed == USB_SPEED_LOW) status |= TD_CTRL_LS; if (usb_pipein(urb->pipe)) @@ -779,7 +800,8 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, /* * Build the DATA TDs */ - plink = &fake_link; + plink = NULL; + td = qh->dummy_td; do { /* Allow zero length packets */ int pktsze = maxsze; @@ -789,24 +811,23 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, status &= ~TD_CTRL_SPD; } - td = uhci_alloc_td(uhci); - if (!td) - return -ENOMEM; - *plink = cpu_to_le32(td->dma_handle); - + if (plink) { + td = uhci_alloc_td(uhci); + if (!td) + goto nomem; + *plink = cpu_to_le32(td->dma_handle); + } uhci_add_td_to_urb(urb, td); uhci_fill_td(td, status, - destination | uhci_explen(pktsze) | - (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), - data); + destination | uhci_explen(pktsze) | + (toggle << TD_TOKEN_TOGGLE_SHIFT), + data); plink = &td->link; + status |= TD_CTRL_ACTIVE; data += pktsze; len -= maxsze; - - usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)); + toggle ^= 1; } while (len > 0); /* @@ -821,17 +842,17 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, urb->transfer_buffer_length > 0) { td = uhci_alloc_td(uhci); if (!td) - return -ENOMEM; + goto nomem; *plink = cpu_to_le32(td->dma_handle); uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(0) | - (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), - data); + uhci_fill_td(td, status, + destination | uhci_explen(0) | + (toggle << TD_TOKEN_TOGGLE_SHIFT), + data); + plink = &td->link; - usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)); + toggle ^= 1; } /* Set the interrupt-on-completion flag on the last packet. @@ -842,7 +863,27 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, * flag setting. */ td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); + /* + * Build the new dummy TD and activate the old one + */ + td = uhci_alloc_td(uhci); + if (!td) + goto nomem; + *plink = cpu_to_le32(td->dma_handle); + + uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); + wmb(); + qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); + qh->dummy_td = td; + + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe), toggle); return 0; + +nomem: + /* Remove the dummy TD from the td_list so it doesn't get freed */ + uhci_remove_td_from_urb(qh->dummy_td); + return -ENOMEM; } /* @@ -1169,31 +1210,6 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, * become idle, so we can activate it right away. */ if (qh->queue.next == &urbp->node) uhci_activate_qh(uhci, qh); - - /* If the QH is already active, we have a race with the hardware. - * This won't get fixed until dummy TDs are added. */ - else if (qh->state == QH_STATE_ACTIVE) { - - /* If the URB isn't first on its queue, adjust the link pointer - * of the last TD in the previous URB. */ - if (urbp->node.prev != &urbp->qh->queue) { - struct urb_priv *purbp = list_entry(urbp->node.prev, - struct urb_priv, node); - struct uhci_td *ptd = list_entry(purbp->td_list.prev, - struct uhci_td, list); - struct uhci_td *td = list_entry(urbp->td_list.next, - struct uhci_td, list); - - ptd->link = cpu_to_le32(td->dma_handle); - - } - if (qh_element(qh) == UHCI_PTR_TERM) { - struct uhci_td *td = list_entry(urbp->td_list.next, - struct uhci_td, list); - - qh->element = cpu_to_le32(td->dma_handle); - } - } goto done; err_submit_failed: -- cgit v1.2.3-59-g8ed1b From 0ed8fee1c1d38a62e981025ba40b5eba30c4ce2a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Sat, 17 Dec 2005 18:02:38 -0500 Subject: [PATCH] UHCI: remove main list of URBs As part of reorienting uhci-hcd away from URBs and toward endpoint queues, this patch (as625) eliminates the driver's main list of URBs. The list wsa used mainly in checking for URB completions; now the driver goes through the list of active endpoints and checks the members of the queues. As a side effect, I had to remove the code that looks for FSBR timeouts. For now, FSBR will remain on so long as any URBs on a full-speed control or bulk queue request it, even if the queue isn't advancing. A later patch can add more intelligent handling. This isn't a huge drawback; it's pretty rare for an URB to get stuck for more than a fraction of a second. (And it will help the people trying to use those insane HP USB devices.) Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 1 - drivers/usb/host/uhci-hcd.c | 2 - drivers/usb/host/uhci-hcd.h | 15 +- drivers/usb/host/uhci-q.c | 631 ++++++++++++++++++------------------------ 4 files changed, 279 insertions(+), 370 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 6814783adf91..f2f5f8ce1715 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -114,7 +114,6 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) } out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : "")); - out += sprintf(out, "%s", (urbp->fsbr_timeout ? " FSBR_TO" : "")); if (urbp->urb->status != -EINPROGRESS) out += sprintf(out, " Status=%d", urbp->urb->status); diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 1ff4b8806372..9865f303d3fc 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -491,8 +491,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->urb_list); - INIT_LIST_HEAD(&uhci->complete_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 c057956667b5..7e96bef2e88f 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -132,6 +132,10 @@ struct uhci_qh { unsigned int unlink_frame; /* When the QH was unlinked */ int state; /* QH_STATE_xxx; see above */ + + 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 */ } __attribute__((aligned(16))); /* @@ -384,6 +388,7 @@ struct uhci_hcd { struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QHs */ + struct uhci_qh *next_qh; /* Next QH to scan */ spinlock_t lock; @@ -413,16 +418,10 @@ struct uhci_hcd { unsigned long resuming_ports; unsigned long ports_timeout; /* Time to stop signalling */ - /* Main list of URBs currently controlled by this HC */ - struct list_head urb_list; - /* 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 */ - /* List of URBs awaiting completion callback */ - struct list_head complete_list; - struct list_head idle_qh_list; /* Where the idle QHs live */ int rh_numports; /* Number of root-hub ports */ @@ -448,7 +447,6 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci) * Private per-URB data */ struct urb_priv { - struct list_head urb_list; struct list_head node; /* Node in the QH's urbp list */ struct urb *urb; @@ -456,10 +454,7 @@ struct urb_priv { struct uhci_qh *qh; /* QH for this URB */ struct list_head td_list; - unsigned long fsbrtime; /* In jiffies */ - unsigned fsbr : 1; /* URB turned on FSBR */ - unsigned fsbr_timeout : 1; /* URB timed out 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 c4194182dcc4..44bba9a6d196 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -151,53 +151,6 @@ static void uhci_unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb) wmb(); } -/* - * Remove an URB's TDs from the hardware schedule - */ -static void uhci_remove_tds_from_schedule(struct uhci_hcd *uhci, - struct urb *urb, int status) -{ - 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) { - uhci_unlink_isochronous_tds(uhci, urb); - return; - } - - /* If the URB isn't first on its queue, adjust the link pointer - * of the last TD in the previous URB. */ - if (urbp->node.prev != &urbp->qh->queue) { - struct urb_priv *purbp; - struct uhci_td *ptd, *ltd; - - if (status == -EINPROGRESS) - status = 0; - purbp = list_entry(urbp->node.prev, struct urb_priv, node); - 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; - } - - /* If the URB completed with an error, then the QH element certainly - * points to one of the URB's TDs. If it completed normally then - * the QH element has certainly moved on to the next URB. And if - * the URB is still in progress then it must have been dequeued. - * The QH element either hasn't reached it yet or is somewhere in - * the middle. If the URB wasn't first we can assume that it - * hasn't started yet (see above): Otherwise all the preceding URBs - * would have completed and been removed from the queue, so this one - * _would_ be first. - * - * If the QH element is inside this URB, clear it. It will be - * set properly when the QH is activated. - */ - if (status < 0) - urbp->qh->element = UHCI_PTR_TERM; -} - static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *udev, struct usb_host_endpoint *hep) { @@ -250,6 +203,90 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); } +/* + * When the currently executing URB is dequeued, save its current toggle value + */ +static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb) +{ + struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; + struct uhci_td *td; + + /* 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) + return; + 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)) + 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); +} + +/* + * Fix up the data toggles for URBs in a queue, when one of them + * terminates early (short transfer, error, or dequeued). + */ +static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first) +{ + struct urb_priv *urbp = NULL; + struct uhci_td *td; + unsigned int toggle = qh->initial_toggle; + unsigned int pipe; + + /* Fixups for a short transfer start with the second URB in the + * queue (the short URB is the first). */ + if (skip_first) + urbp = list_entry(qh->queue.next, struct urb_priv, node); + + /* When starting with the first URB, if the QH element pointer is + * still valid then we know the URB's toggles are okay. */ + else if (qh_element(qh) != UHCI_PTR_TERM) + toggle = 2; + + /* Fix up the toggle for the URBs in the queue. Normally this + * loop won't run more than once: When an error or short transfer + * occurs, the queue usually gets emptied. */ + list_prepare_entry(urbp, &qh->queue, node); + list_for_each_entry_continue(urbp, &qh->queue, node) { + + /* If the first TD has the right toggle value, we don't + * need to change any toggles in this URB */ + td = list_entry(urbp->td_list.next, struct uhci_td, list); + if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) { + td = list_entry(urbp->td_list.next, struct uhci_td, + list); + toggle = uhci_toggle(td_token(td)) ^ 1; + + /* Otherwise all the toggles in the URB have to be switched */ + } else { + list_for_each_entry(td, &urbp->td_list, list) { + td->token ^= __constant_cpu_to_le32( + TD_TOKEN_TOGGLE); + toggle ^= 1; + } + } + } + + wmb(); + pipe = list_entry(qh->queue.next, struct urb_priv, node)->urb->pipe; + usb_settoggle(qh->udev, usb_pipeendpoint(pipe), + usb_pipeout(pipe), toggle); + qh->needs_fixup = 0; +} + /* * Put a QH on the schedule in both hardware and software */ @@ -276,6 +313,9 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) /* Move the QH from its old list to the end of the appropriate * skeleton's list */ + if (qh == uhci->next_qh) + uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, + node); list_move_tail(&qh->node, &qh->skel->node); /* Link it into the schedule */ @@ -310,6 +350,9 @@ static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) uhci_set_next_interrupt(uhci); /* Move the QH from its old list to the end of the unlinking list */ + if (qh == uhci->next_qh) + uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, + node); list_move_tail(&qh->node, &uhci->skel_unlink_qh->node); } @@ -323,6 +366,9 @@ static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh) { WARN_ON(qh->state == QH_STATE_ACTIVE); + if (qh == uhci->next_qh) + uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, + node); list_move(&qh->node, &uhci->idle_qh_list); qh->state = QH_STATE_IDLE; @@ -344,11 +390,9 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, urbp->urb = urb; urb->hcpriv = urbp; - urbp->fsbrtime = jiffies; INIT_LIST_HEAD(&urbp->node); INIT_LIST_HEAD(&urbp->td_list); - INIT_LIST_HEAD(&urbp->urb_list); return urbp; } @@ -373,9 +417,6 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci, { struct uhci_td *td, *tmp; - if (!list_empty(&urbp->urb_list)) - dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list!\n", - urbp->urb); if (!list_empty(&urbp->node)) dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n", urbp->urb); @@ -452,71 +493,6 @@ static int uhci_map_status(int status, int dir_out) return 0; } -/* - * Fix up the data toggles for URBs in a queue, when one of them - * terminates early (short transfer, error, or dequeued). - */ -static void uhci_fixup_toggles(struct urb *urb) -{ - struct list_head *head; - struct uhci_td *td; - struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - int prevactive = 0; - unsigned int toggle = 0; - struct urb_priv *turbp, *list_end; - - /* - * We need to find out what the last successful toggle was so - * we can update the data toggles for the following transfers. - * - * There are 2 ways the last successful completed TD is found: - * - * 1) The TD is NOT active and the actual length < expected length - * 2) The TD is NOT active and it's the last TD in the chain - * - * and a third way the first uncompleted TD is found: - * - * 3) The TD is active and the previous TD is NOT active - */ - head = &urbp->td_list; - list_for_each_entry(td, head, list) { - unsigned int ctrlstat = td_status(td); - - if (!(ctrlstat & TD_CTRL_ACTIVE) && - (uhci_actual_length(ctrlstat) < - uhci_expected_length(td_token(td)) || - td->list.next == head)) - toggle = uhci_toggle(td_token(td)) ^ 1; - else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive) - toggle = uhci_toggle(td_token(td)); - - prevactive = ctrlstat & TD_CTRL_ACTIVE; - } - - /* - * Fix up the toggle for the following URBs in the queue. - * - * We can stop as soon as we find an URB with toggles set correctly, - * because then all the following URBs will be correct also. - */ - list_end = list_entry(&urbp->qh->queue, struct urb_priv, node); - turbp = urbp; - while ((turbp = list_entry(turbp->node.next, struct urb_priv, node)) - != list_end) { - td = list_entry(turbp->td_list.next, struct uhci_td, list); - if (uhci_toggle(td_token(td)) == toggle) - return; - - list_for_each_entry(td, &turbp->td_list, list) { - td->token ^= __constant_cpu_to_le32(TD_TOKEN_TOGGLE); - toggle ^= 1; - } - } - - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe), toggle); -} - /* * Control transfers */ @@ -765,6 +741,9 @@ err: } } + /* Note that the queue has stopped */ + urbp->qh->element = UHCI_PTR_TERM; + urbp->qh->is_stopped = 1; return ret; } @@ -927,7 +906,10 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) */ if (!urbp->short_transfer) { urbp->short_transfer = 1; - uhci_fixup_toggles(urb); + 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; @@ -962,6 +944,13 @@ err: } } #endif + + /* 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; } @@ -995,76 +984,39 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, /* * Isochronous transfers */ -static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end) -{ - struct urb *last_urb = NULL; - struct urb_priv *up; - int ret = 0; - - list_for_each_entry(up, &uhci->urb_list, urb_list) { - struct urb *u = up->urb; - - /* look for pending URBs with identical pipe handle */ - if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && - (u->status == -EINPROGRESS) && (u != urb)) { - if (!last_urb) - *start = u->start_frame; - last_urb = u; - } - } - - if (last_urb) { - *end = (last_urb->start_frame + last_urb->number_of_packets * - last_urb->interval) & (UHCI_NUMFRAMES-1); - ret = 0; - } else - ret = -1; /* no previous urb found */ - - return ret; -} - -static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb) +static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, + struct uhci_qh *qh) { - int limits; - unsigned int start = 0, end = 0; + struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */ + int i, frame; + unsigned long destination, status; + struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; if (urb->number_of_packets > 900) /* 900? Why? */ return -EFBIG; - limits = isochronous_find_limits(uhci, urb, &start, &end); + status = TD_CTRL_ACTIVE | TD_CTRL_IOS; + destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); + /* Figure out the starting frame number */ if (urb->transfer_flags & URB_ISO_ASAP) { - if (limits) { + if (list_empty(&qh->queue)) { uhci_get_current_frame_number(uhci); - urb->start_frame = (uhci->frame_number + 10) - & (UHCI_NUMFRAMES - 1); - } else - urb->start_frame = end; + urb->start_frame = (uhci->frame_number + 10); + + } else { /* Go right after the last one */ + struct urb *last_urb; + + last_urb = 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); + } } else { - urb->start_frame &= (UHCI_NUMFRAMES - 1); /* FIXME: Sanity check */ } - - return 0; -} - -/* - * Isochronous transfers - */ -static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, - struct uhci_qh *qh) -{ - struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */ - int i, ret, frame; - unsigned long destination, status; - struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - - status = TD_CTRL_ACTIVE | TD_CTRL_IOS; - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); - - ret = isochronous_find_start(uhci, urb); - if (ret) - return ret; + urb->start_frame &= (UHCI_NUMFRAMES - 1); for (i = 0; i < urb->number_of_packets; i++) { td = uhci_alloc_td(uhci); @@ -1203,7 +1155,6 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, /* Add this URB to the QH */ urbp->qh = qh; list_add_tail(&urbp->node, &qh->queue); - list_add_tail(&urbp->urb_list, &uhci->urb_list); /* 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 @@ -1224,49 +1175,66 @@ done: return ret; } +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; + + spin_lock_irqsave(&uhci->lock, flags); + urbp = urb->hcpriv; + if (!urbp) /* URB was never linked! */ + goto done; + + /* Remove Isochronous TDs from the frame list ASAP */ + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) + uhci_unlink_isochronous_tds(uhci, urb); + uhci_unlink_qh(uhci, urbp->qh); + +done: + spin_unlock_irqrestore(&uhci->lock, flags); + return 0; +} + /* - * Return the result of a transfer + * Finish unlinking an URB and give it back */ -static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb) +static void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh, + struct urb *urb, struct pt_regs *regs) +__releases(uhci->lock) +__acquires(uhci->lock) { - int status; - int okay_to_giveback = 0; struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: - status = uhci_result_control(uhci, urb); - break; - case PIPE_ISOCHRONOUS: - status = uhci_result_isochronous(uhci, urb); - break; - default: /* PIPE_BULK or PIPE_INTERRUPT */ - status = uhci_result_common(uhci, urb); - break; - } + /* Isochronous TDs get unlinked directly from the frame list */ + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) + uhci_unlink_isochronous_tds(uhci, urb); - spin_lock(&urb->lock); - if (urb->status == -EINPROGRESS) { /* Not yet dequeued */ - if (status != -EINPROGRESS) { /* URB has completed */ - urb->status = status; + /* 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; - /* If the URB got a real error (as opposed to - * simply being dequeued), we don't have to - * unlink the QH. Fix this later... */ - if (status < 0) - uhci_unlink_qh(uhci, urbp->qh); - else - okay_to_giveback = 1; - } - } else { /* Already dequeued */ - if (urbp->qh->state == QH_STATE_UNLINKING && - uhci->frame_number + uhci->is_stopped != - urbp->qh->unlink_frame) - okay_to_giveback = 1; + purbp = list_entry(urbp->node.prev, struct urb_priv, node); + 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; } - spin_unlock(&urb->lock); - if (!okay_to_giveback) - return; + + /* 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); + if (list_empty(&qh->queue) && qh->needs_fixup) { + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe), qh->initial_toggle); + qh->needs_fixup = 0; + } + + uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ + uhci_free_urb_priv(uhci, urbp); switch (usb_pipetype(urb->pipe)) { case PIPE_ISOCHRONOUS: @@ -1277,122 +1245,107 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb) case PIPE_INTERRUPT: /* Release bandwidth for Interrupt or Isoc. transfers */ /* Make sure we don't release if we have a queued URB */ - if (list_empty(&urbp->qh->queue) && urb->bandwidth) + if (list_empty(&qh->queue) && urb->bandwidth) usb_release_bandwidth(urb->dev, urb, 0); else /* bandwidth was passed on to queued URB, */ /* so don't let usb_unlink_urb() release it */ urb->bandwidth = 0; - /* Falls through */ - case PIPE_BULK: - if (status < 0) - uhci_fixup_toggles(urb); - break; - default: /* PIPE_CONTROL */ break; } - /* Take the URB's TDs off the hardware schedule */ - uhci_remove_tds_from_schedule(uhci, urb, status); - - /* Take the URB off the QH's queue and see if the QH is now unused */ - list_del_init(&urbp->node); - if (list_empty(&urbp->qh->queue)) - uhci_unlink_qh(uhci, urbp->qh); + spin_unlock(&uhci->lock); + usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb, regs); + spin_lock(&uhci->lock); - uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ + /* If the queue is now empty, we can unlink the QH and give up its + * reserved bandwidth. */ + if (list_empty(&qh->queue)) { + uhci_unlink_qh(uhci, qh); - /* Queue it for giving back */ - list_move_tail(&urbp->urb_list, &uhci->complete_list); + /* Bandwidth stuff not yet implemented */ + } } /* - * Check out the QHs waiting to be fully unlinked + * Scan the URBs in a QH's queue */ -static void uhci_scan_unlinking_qhs(struct uhci_hcd *uhci) -{ - struct uhci_qh *qh, *tmp; +#define QH_FINISHED_UNLINKING(qh) \ + (qh->state == QH_STATE_UNLINKING && \ + uhci->frame_number + uhci->is_stopped != qh->unlink_frame) - list_for_each_entry_safe(qh, tmp, &uhci->skel_unlink_qh->node, node) { - - /* If the queue is empty and the QH is fully unlinked then - * it can become IDLE. */ - if (list_empty(&qh->queue)) { - if (uhci->frame_number + uhci->is_stopped != - qh->unlink_frame) - uhci_make_qh_idle(uhci, qh); - - /* If none of the QH's URBs have been dequeued then the QH - * should be re-activated. */ - } else { - struct urb_priv *urbp; - int any_dequeued = 0; - - list_for_each_entry(urbp, &qh->queue, node) { - if (urbp->urb->status != -EINPROGRESS) { - any_dequeued = 1; - break; - } - } - if (!any_dequeued) - uhci_activate_qh(uhci, qh); - } - } -} - -static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) +static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, + struct pt_regs *regs) { - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - unsigned long flags; struct urb_priv *urbp; + struct urb *urb; + int status; - spin_lock_irqsave(&uhci->lock, flags); - urbp = urb->hcpriv; - if (!urbp) /* URB was never linked! */ - goto done; + while (!list_empty(&qh->queue)) { + urbp = list_entry(qh->queue.next, struct urb_priv, node); + urb = urbp->urb; - /* Remove Isochronous TDs from the frame list ASAP */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) - uhci_unlink_isochronous_tds(uhci, urb); - uhci_unlink_qh(uhci, urbp->qh); + switch (usb_pipetype(urb->pipe)) { + case PIPE_CONTROL: + status = uhci_result_control(uhci, urb); + break; + case PIPE_ISOCHRONOUS: + status = uhci_result_isochronous(uhci, urb); + break; + default: /* PIPE_BULK or PIPE_INTERRUPT */ + status = uhci_result_common(uhci, urb); + break; + } + if (status == -EINPROGRESS) + break; -done: - spin_unlock_irqrestore(&uhci->lock, flags); - return 0; -} + spin_lock(&urb->lock); + if (urb->status == -EINPROGRESS) /* Not dequeued */ + urb->status = status; + else + status = -ECONNRESET; + spin_unlock(&urb->lock); -static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct list_head *head; - struct uhci_td *td; - int count = 0; + /* 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; - uhci_dec_fsbr(uhci, urb); + uhci_giveback_urb(uhci, qh, urb, regs); + if (qh->is_stopped) + break; + } - urbp->fsbr_timeout = 1; + /* 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))) + return; - /* - * Ideally we would want to fix qh->element as well, but it's - * read/write by the HC, so that can introduce a race. It's not - * really worth the hassle - */ + /* Otherwise give back each of the dequeued URBs */ + list_for_each_entry(urbp, &qh->queue, node) { + urb = urbp->urb; + if (urb->status != -EINPROGRESS) { + uhci_save_toggle(qh, urb); + uhci_giveback_urb(uhci, qh, urb, regs); + goto restart; + } + } + qh->is_stopped = 0; - head = &urbp->td_list; - list_for_each_entry(td, head, list) { - /* - * Make sure we don't do the last one (since it'll have the - * TERM bit set) as well as we skip every so many TDs to - * make sure it doesn't hog the bandwidth - */ - if (td->list.next != head && (count % DEPTH_INTERVAL) == - (DEPTH_INTERVAL - 1)) - td->link |= UHCI_PTR_DEPTH; - - count++; + /* There are no more dequeued URBs. If there are still URBs on the + * queue, the QH can now be re-activated. */ + if (!list_empty(&qh->queue)) { + if (qh->needs_fixup) + uhci_fixup_toggles(qh, 0); + uhci_activate_qh(uhci, qh); } - return 0; + /* The queue is empty. The QH can become idle if it is fully + * unlinked. */ + else if (QH_FINISHED_UNLINKING(qh)) + uhci_make_qh_idle(uhci, qh); } static void uhci_free_pending_tds(struct uhci_hcd *uhci) @@ -1406,36 +1359,13 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci) } } -static void -uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) -__releases(uhci->lock) -__acquires(uhci->lock) -{ - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - - uhci_free_urb_priv(uhci, (struct urb_priv *) (urb->hcpriv)); - - spin_unlock(&uhci->lock); - usb_hcd_giveback_urb(hcd, urb, regs); - spin_lock(&uhci->lock); -} - -static void uhci_finish_completion(struct uhci_hcd *uhci, struct pt_regs *regs) -{ - struct urb_priv *urbp, *tmp; - - list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) { - struct urb *urb = urbp->urb; - - list_del_init(&urbp->urb_list); - uhci_finish_urb(uhci_to_hcd(uhci), urb, regs); - } -} - -/* Process events in the schedule, but only in one thread at a time */ +/* + * Process events in the schedule, but only in one thread at a time + */ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) { - struct urb_priv *urbp, *tmp; + int i; + struct uhci_qh *qh; /* Don't allow re-entrant calls */ if (uhci->scan_in_progress) { @@ -1452,26 +1382,24 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) uhci_free_pending_tds(uhci); - /* Walk the list of pending URBs to see which ones completed - * (must be _safe because uhci_transfer_result() dequeues URBs) */ - list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) { - struct urb *urb = urbp->urb; - - /* Checks the status and does all of the magic necessary */ - uhci_transfer_result(uhci, urb); + /* 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, + struct uhci_qh, node); + 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); + } } - uhci_finish_completion(uhci, regs); - - /* If the controller is stopped, we can finish these off right now */ - if (uhci->is_stopped) - uhci_free_pending_tds(uhci); if (uhci->need_rescan) goto rescan; uhci->scan_in_progress = 0; - /* Check out the QHs waiting for unlinking */ - uhci_scan_unlinking_qhs(uhci); + /* 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)) @@ -1482,19 +1410,8 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) static void check_fsbr(struct uhci_hcd *uhci) { - struct urb_priv *up; - - list_for_each_entry(up, &uhci->urb_list, urb_list) { - struct urb *u = up->urb; - - spin_lock(&u->lock); - - /* Check if the FSBR timed out */ - if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) - uhci_fsbr_timeout(uhci, u); - - spin_unlock(&u->lock); - } + /* 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)) { -- cgit v1.2.3-59-g8ed1b From 8d402e1ae03656c1ad215514f8885ef4793f0948 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Sat, 17 Dec 2005 18:03:37 -0500 Subject: [PATCH] UHCI: improve debugging code This patch (as626) makes some improvements to the debugging code in uhci-hcd. The main change is that now the code won't get compiled if CONFIG_USB_DEBUG isn't set. But there are other changes too, like adding a missing .owner field and printing a debugging dump if the controller dies. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 36 +++++++++++++++++++++----- drivers/usb/host/uhci-hcd.c | 60 ++++++++++++++++++++++++++++--------------- drivers/usb/host/uhci-hcd.h | 1 + drivers/usb/host/uhci-q.c | 12 +-------- 4 files changed, 70 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index f2f5f8ce1715..e1239319655c 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -17,10 +17,13 @@ #include "uhci-hcd.h" -static struct dentry *uhci_debugfs_root = NULL; +#define uhci_debug_operations (* (struct file_operations *) NULL) +static struct dentry *uhci_debugfs_root; + +#ifdef DEBUG /* Handle REALLY large printks so we don't overflow buffers */ -static inline void lprintk(char *buf) +static void lprintk(char *buf) { char *p; @@ -196,7 +199,6 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) return out - buf; } -#ifdef CONFIG_PROC_FS static const char * const qh_names[] = { "skel_unlink_qh", "skel_iso_qh", "skel_int128_qh", "skel_int64_qh", @@ -393,12 +395,13 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) return out - buf; } +#ifdef CONFIG_DEBUG_FS + #define MAX_OUTPUT (64 * 1024) struct uhci_debug { int size; char *data; - struct uhci_hcd *uhci; }; static int uhci_debug_open(struct inode *inode, struct file *file) @@ -419,8 +422,10 @@ static int uhci_debug_open(struct inode *inode, struct file *file) goto out; } + up->size = 0; spin_lock_irqsave(&uhci->lock, flags); - up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); + if (uhci->is_initialized) + up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); spin_unlock_irqrestore(&uhci->lock, flags); file->private_data = up; @@ -472,15 +477,32 @@ static int uhci_debug_release(struct inode *inode, struct file *file) return 0; } +#undef uhci_debug_operations static struct file_operations uhci_debug_operations = { + .owner = THIS_MODULE, .open = uhci_debug_open, .llseek = uhci_debug_lseek, .read = uhci_debug_read, .release = uhci_debug_release, }; -#else /* CONFIG_DEBUG_FS */ +#endif /* CONFIG_DEBUG_FS */ -#define uhci_debug_operations (* (struct file_operations *) NULL) +#else /* DEBUG */ + +static inline void lprintk(char *buf) +{} + +static inline int uhci_show_qh(struct uhci_qh *qh, char *buf, + int len, int space) +{ + return 0; +} + +static inline int uhci_sprint_schedule(struct uhci_hcd *uhci, + char *buf, int len) +{ + return 0; +} #endif diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 9865f303d3fc..4edb8330c440 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -68,12 +68,16 @@ Alan Stern" * debug = 3, show all TDs in URBs when dumping */ #ifdef DEBUG +#define DEBUG_CONFIGURED 1 static int debug = 1; -#else -static int debug = 0; -#endif module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug level"); + +#else +#define DEBUG_CONFIGURED 0 +#define debug 0 +#endif + static char *errbuf; #define ERRBUF_LEN (32 * 1024) @@ -338,6 +342,12 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) dev_err(uhci_dev(uhci), "host controller halted, " "very bad!\n"); + if (debug > 1 && errbuf) { + /* Print the schedule for debugging */ + uhci_sprint_schedule(uhci, + errbuf, ERRBUF_LEN); + lprintk(errbuf); + } hc_died(uhci); /* Force a callback in case there are @@ -376,6 +386,14 @@ static void release_uhci(struct uhci_hcd *uhci) { int i; + if (DEBUG_CONFIGURED) { + spin_lock_irq(&uhci->lock); + uhci->is_initialized = 0; + spin_unlock_irq(&uhci->lock); + + debugfs_remove(uhci->dentry); + } + for (i = 0; i < UHCI_NUM_SKELQH; i++) uhci_free_qh(uhci, uhci->skelqh[i]); @@ -390,8 +408,6 @@ static void release_uhci(struct uhci_hcd *uhci) dma_free_coherent(uhci_dev(uhci), UHCI_NUMFRAMES * sizeof(*uhci->frame), uhci->frame, uhci->frame_dma_handle); - - debugfs_remove(uhci->dentry); } static int uhci_reset(struct usb_hcd *hcd) @@ -474,17 +490,6 @@ static int uhci_start(struct usb_hcd *hcd) hcd->uses_new_polling = 1; - dentry = debugfs_create_file(hcd->self.bus_name, - S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, - &uhci_debug_operations); - if (!dentry) { - dev_err(uhci_dev(uhci), - "couldn't create uhci debugfs entry\n"); - retval = -ENOMEM; - goto err_create_debug_entry; - } - uhci->dentry = dentry; - uhci->fsbr = 0; uhci->fsbrtimeout = 0; @@ -495,6 +500,19 @@ static int uhci_start(struct usb_hcd *hcd) init_waitqueue_head(&uhci->waitqh); + if (DEBUG_CONFIGURED) { + dentry = debugfs_create_file(hcd->self.bus_name, + S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, + uhci, &uhci_debug_operations); + if (!dentry) { + dev_err(uhci_dev(uhci), "couldn't create uhci " + "debugfs entry\n"); + retval = -ENOMEM; + goto err_create_debug_entry; + } + uhci->dentry = dentry; + } + uhci->frame = dma_alloc_coherent(uhci_dev(uhci), UHCI_NUMFRAMES * sizeof(*uhci->frame), &uhci->frame_dma_handle, 0); @@ -609,6 +627,7 @@ static int uhci_start(struct usb_hcd *hcd) mb(); configure_hc(uhci); + uhci->is_initialized = 1; start_rh(uhci); return 0; @@ -872,16 +891,15 @@ static int __init uhci_hcd_init(void) if (usb_disabled()) return -ENODEV; - if (debug) { + if (DEBUG_CONFIGURED) { errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); if (!errbuf) goto errbuf_failed; + uhci_debugfs_root = debugfs_create_dir("uhci", NULL); + if (!uhci_debugfs_root) + goto debug_failed; } - uhci_debugfs_root = debugfs_create_dir("uhci", NULL); - if (!uhci_debugfs_root) - goto debug_failed; - uhci_up_cachep = kmem_cache_create("uhci_urb_priv", sizeof(struct urb_priv), 0, 0, NULL, NULL); if (!uhci_up_cachep) diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 7e96bef2e88f..4a69c7eb09bd 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -411,6 +411,7 @@ struct uhci_hcd { unsigned int hc_inaccessible:1; /* HC is suspended or dead */ unsigned int working_RD:1; /* Suspended root hub doesn't need to be polled */ + unsigned int is_initialized:1; /* Data structure is usable */ /* 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 44bba9a6d196..5d6c4f75d0d8 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -736,7 +736,6 @@ err: if (errbuf) { /* Print the chain for debugging purposes */ uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); - lprintk(errbuf); } } @@ -924,26 +923,17 @@ td_error: ret = uhci_map_status(status, uhci_packetout(td_token(td))); err: - /* - * Enable this chunk of code if you want to see some more debugging. - * But be careful, it has the tendancy to starve out khubd and prevent - * disconnects from happening successfully if you have a slow debug - * log interface (like a serial console. - */ -#if 0 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) { + if (debug > 1 && errbuf) { /* Print the chain for debugging purposes */ uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); - lprintk(errbuf); } } -#endif /* Note that the queue has stopped and save the next toggle value */ urbp->qh->element = UHCI_PTR_TERM; -- cgit v1.2.3-59-g8ed1b From dbf4fcad62467ce1bd6966292b6850fc7a210e0b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 20 Dec 2005 09:58:08 -0500 Subject: [PATCH] UHCI: Don't log short transfers Even when the URB_SHORT_NOT_OK flag is set, a short transfer shouldn't generate a debugging log message. Especially not one with the confusing claim that the transfer "failed with status 0". This patch (as627) fixes that behavior in uhci-hcd. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-q.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 5d6c4f75d0d8..0c1b12091c48 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -922,7 +922,6 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) 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", @@ -934,6 +933,7 @@ err: lprintk(errbuf); } } +err: /* Note that the queue has stopped and save the next toggle value */ urbp->qh->element = UHCI_PTR_TERM; -- cgit v1.2.3-59-g8ed1b From 1393adb2ebb00a2cd54b293cd7ee71e3376f4e9f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 31 Jan 2006 10:02:55 -0500 Subject: [PATCH] uhci-hcd: fix mistaken usage of list_prepare_entry A recent update to the uhci-hcd driver invoked the list_prepare_entry macro incorrectly. This patch (as646) corrects it. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-q.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 0c1b12091c48..5d2f9575ab4f 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -259,7 +259,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first) /* Fix up the toggle for the URBs in the queue. Normally this * loop won't run more than once: When an error or short transfer * occurs, the queue usually gets emptied. */ - list_prepare_entry(urbp, &qh->queue, node); + urbp = list_prepare_entry(urbp, &qh->queue, node); list_for_each_entry_continue(urbp, &qh->queue, node) { /* If the first TD has the right toggle value, we don't -- cgit v1.2.3-59-g8ed1b From 6a8e87b23ff4a979bde5451a242466a4b3f9fe7d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 19 Jan 2006 10:46:27 -0500 Subject: [PATCH] USB core and HCDs: don't put_device while atomic This patch (as640) removes several put_device and the corresponding get_device calls from the USB core and HCDs. Some of the puts were done in atomic contexts, and none of them are needed since the core now guarantees that every endpoint will be disabled and every URB completed before a USB device is released. Signed-off-by: Alan Stern Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 2 -- drivers/usb/host/ehci-mem.c | 1 - drivers/usb/host/ehci-q.c | 2 +- drivers/usb/host/ehci-sched.c | 6 ++---- drivers/usb/host/isp116x-hcd.c | 3 +-- drivers/usb/host/sl811-hcd.c | 3 +-- drivers/usb/host/uhci-q.c | 2 -- 7 files changed, 5 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index a98d978d76e2..fbd938d4ea58 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1105,7 +1105,6 @@ static void urb_unlink (struct urb *urb) spin_lock_irqsave (&hcd_data_lock, flags); list_del_init (&urb->urb_list); spin_unlock_irqrestore (&hcd_data_lock, flags); - usb_put_dev (urb->dev); } @@ -1145,7 +1144,6 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags) case HC_STATE_RUNNING: case HC_STATE_RESUMING: doit: - usb_get_dev (urb->dev); list_add_tail (&urb->urb_list, &ep->urb_list); status = 0; break; diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 91c2ab43cbcc..ec7eb3f4f867 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c @@ -75,7 +75,6 @@ static void qh_destroy (struct kref *kref) } if (qh->dummy) ehci_qtd_free (ehci, qh->dummy); - usb_put_dev (qh->dev); dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); } diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 5ada7cd5698b..e469221e7ec3 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -702,7 +702,7 @@ qh_make ( } /* support for tt scheduling, and access to toggles */ - qh->dev = usb_get_dev (urb->dev); + qh->dev = urb->dev; /* using TT? */ switch (urb->dev->speed) { diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 88419c6823a8..90d6900a37f4 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1399,7 +1399,7 @@ itd_complete ( */ /* give urb back to the driver ... can be out-of-order */ - dev = usb_get_dev (urb->dev); + dev = urb->dev; ehci_urb_done (ehci, urb, regs); urb = NULL; @@ -1418,7 +1418,6 @@ itd_complete ( (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); } iso_stream_put (ehci, stream); - usb_put_dev (dev); return 1; } @@ -1765,7 +1764,7 @@ sitd_complete ( */ /* give urb back to the driver */ - dev = usb_get_dev (urb->dev); + dev = urb->dev; ehci_urb_done (ehci, urb, regs); urb = NULL; @@ -1784,7 +1783,6 @@ sitd_complete ( (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); } iso_stream_put (ehci, stream); - usb_put_dev (dev); return 1; } diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 972ce04889f8..fea5dcbec7c4 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -724,7 +724,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, ep = hep->hcpriv; else { INIT_LIST_HEAD(&ep->schedule); - ep->udev = usb_get_dev(udev); + ep->udev = udev; ep->epnum = epnum; ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); usb_settoggle(udev, epnum, is_out, 0); @@ -891,7 +891,6 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd, if (!list_empty(&hep->urb_list)) WARN("ep %p not empty?\n", ep); - usb_put_dev(ep->udev); kfree(ep); hep->hcpriv = NULL; } diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 517360b77d8e..a92343052751 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -853,7 +853,7 @@ static int sl811h_urb_enqueue( } else { INIT_LIST_HEAD(&ep->schedule); - ep->udev = usb_get_dev(udev); + ep->udev = udev; ep->epnum = epnum; ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); ep->defctrl = SL11H_HCTLMASK_ARM | SL11H_HCTLMASK_ENABLE; @@ -1052,7 +1052,6 @@ sl811h_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) if (!list_empty(&hep->urb_list)) WARN("ep %p not empty?\n", ep); - usb_put_dev(ep->udev); kfree(ep); hep->hcpriv = NULL; } diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 5d2f9575ab4f..a06d84c19e13 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -179,7 +179,6 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, qh->hep = hep; qh->udev = udev; hep->hcpriv = qh; - usb_get_dev(udev); } else { /* Skeleton QH */ qh->state = QH_STATE_ACTIVE; @@ -197,7 +196,6 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) list_del(&qh->node); if (qh->udev) { qh->hep->hcpriv = NULL; - usb_put_dev(qh->udev); uhci_free_td(uhci, qh->dummy_td); } dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); -- cgit v1.2.3-59-g8ed1b From 43c5d5aaafef56618a6efbcab7f91615da1a8659 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 1 Feb 2006 10:47:11 -0500 Subject: [PATCH] usbcore: fix compile error with CONFIG_USB_SUSPEND=n This patch (as647) fixes a small error introduced by a recent change to the USB core suspend/resume code. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f1d64d4bbf5f..7dd28f8e1cea 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1892,8 +1892,8 @@ int usb_resume_device(struct usb_device *udev) status = hub_port_resume(hdev_to_hub(udev->parent), udev->portnum, udev); } else - status = 0; #endif + status = 0; } else status = finish_device_resume(udev); if (status < 0) -- cgit v1.2.3-59-g8ed1b From 329af28b141ab4ae847aff1362864c4cc332641f Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 18 Feb 2006 12:31:05 -0800 Subject: [PATCH] USB: gadget driver section fixups This adds __init section annotations to gadget driver bind() routines to remove calls from .text into .init sections (for endpoint autoconfig). Likewise it adds __exit section annotations to their unbind() routines. The specification of the gadget driver register/unregister functions is updated to explicitly allow use of those sections. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ether.c | 4 ++-- drivers/usb/gadget/file_storage.c | 4 ++-- drivers/usb/gadget/serial.c | 6 +++--- drivers/usb/gadget/zero.c | 6 +++--- include/linux/usb_gadget.h | 7 +++++-- 5 files changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 3d2603e31808..0d9d9bbb73f0 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -2125,7 +2125,7 @@ eth_req_free (struct usb_ep *ep, struct usb_request *req) } -static void +static void __exit eth_unbind (struct usb_gadget *gadget) { struct eth_dev *dev = get_gadget_data (gadget); @@ -2532,7 +2532,7 @@ static struct usb_gadget_driver eth_driver = { .function = (char *) driver_desc, .bind = eth_bind, - .unbind = eth_unbind, + .unbind = __exit_p(eth_unbind), .setup = eth_setup, .disconnect = eth_disconnect, diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index de59c58896d6..cf3be299e353 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3678,7 +3678,7 @@ static void lun_release(struct device *dev) kref_put(&fsg->ref, fsg_release); } -static void fsg_unbind(struct usb_gadget *gadget) +static void __exit fsg_unbind(struct usb_gadget *gadget) { struct fsg_dev *fsg = get_gadget_data(gadget); int i; @@ -4064,7 +4064,7 @@ static struct usb_gadget_driver fsg_driver = { #endif .function = (char *) longname, .bind = fsg_bind, - .unbind = fsg_unbind, + .unbind = __exit_p(fsg_unbind), .disconnect = fsg_disconnect, .setup = fsg_setup, .suspend = fsg_suspend, diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index ba9acd531024..548feaac4553 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -369,7 +369,7 @@ static struct usb_gadget_driver gs_gadget_driver = { #endif /* CONFIG_USB_GADGET_DUALSPEED */ .function = GS_LONG_NAME, .bind = gs_bind, - .unbind = gs_unbind, + .unbind = __exit_p(gs_unbind), .setup = gs_setup, .disconnect = gs_disconnect, .driver = { @@ -1413,7 +1413,7 @@ requeue: * Called on module load. Allocates and initializes the device * structure and a control request. */ -static int gs_bind(struct usb_gadget *gadget) +static int __init gs_bind(struct usb_gadget *gadget) { int ret; struct usb_ep *ep; @@ -1538,7 +1538,7 @@ autoconf_fail: * Called on module unload. Frees the control request and device * structure. */ -static void gs_unbind(struct usb_gadget *gadget) +static void __exit gs_unbind(struct usb_gadget *gadget) { struct gs_dev *dev = get_gadget_data(gadget); diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 5e9fe8a70543..44d8e5e77da7 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -1119,7 +1119,7 @@ zero_autoresume (unsigned long _dev) /*-------------------------------------------------------------------------*/ -static void +static void __exit zero_unbind (struct usb_gadget *gadget) { struct zero_dev *dev = get_gadget_data (gadget); @@ -1136,7 +1136,7 @@ zero_unbind (struct usb_gadget *gadget) set_gadget_data (gadget, NULL); } -static int +static int __init zero_bind (struct usb_gadget *gadget) { struct zero_dev *dev; @@ -1288,7 +1288,7 @@ static struct usb_gadget_driver zero_driver = { #endif .function = (char *) longname, .bind = zero_bind, - .unbind = zero_unbind, + .unbind = __exit_p(zero_unbind), .setup = zero_setup, .disconnect = zero_disconnect, diff --git a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h index ff81117eb733..1d78870ed8af 100644 --- a/include/linux/usb_gadget.h +++ b/include/linux/usb_gadget.h @@ -801,7 +801,9 @@ struct usb_gadget_driver { * Call this in your gadget driver's module initialization function, * to tell the underlying usb controller driver about your driver. * The driver's bind() function will be called to bind it to a - * gadget. This function must be called in a context that can sleep. + * gadget before this registration call returns. It's expected that + * the bind() functions will be in init sections. + * This function must be called in a context that can sleep. */ int usb_gadget_register_driver (struct usb_gadget_driver *driver); @@ -814,7 +816,8 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver); * going away. If the controller is connected to a USB host, * it will first disconnect(). The driver is also requested * to unbind() and clean up any device state, before this procedure - * finally returns. + * finally returns. It's expected that the unbind() functions + * will in in exit sections, so may not be linked in some kernels. * This function must be called in a context that can sleep. */ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver); -- cgit v1.2.3-59-g8ed1b From 1afc64a3d68174fe524f11d92e045a30eacc927e Mon Sep 17 00:00:00 2001 From: Aras Vaichas Date: Sat, 18 Feb 2006 12:31:23 -0800 Subject: [PATCH] USB: ethernet gadget driver section fixups This patch allows you to set the iSerialNumber field in the usb_device_descriptor structure for your USB ethernet gadget. It also changes the parameters shown through sysfs so they're no longer declared as __initdata, preventing potential oopses. That's most useful for the Ethernet addresses, which may in some cases be random "locally administered" addresses. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ether.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 0d9d9bbb73f0..c3d8e5c5bf28 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -182,33 +182,37 @@ struct eth_dev { * parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ -static ushort __initdata idVendor; +static ushort idVendor; module_param(idVendor, ushort, S_IRUGO); MODULE_PARM_DESC(idVendor, "USB Vendor ID"); -static ushort __initdata idProduct; +static ushort idProduct; module_param(idProduct, ushort, S_IRUGO); MODULE_PARM_DESC(idProduct, "USB Product ID"); -static ushort __initdata bcdDevice; +static ushort bcdDevice; module_param(bcdDevice, ushort, S_IRUGO); MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); -static char *__initdata iManufacturer; +static char *iManufacturer; module_param(iManufacturer, charp, S_IRUGO); MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); -static char *__initdata iProduct; +static char *iProduct; module_param(iProduct, charp, S_IRUGO); MODULE_PARM_DESC(iProduct, "USB Product string"); +static char *iSerialNumber; +module_param(iSerialNumber, charp, S_IRUGO); +MODULE_PARM_DESC(iSerialNumber, "SerialNumber"); + /* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */ -static char *__initdata dev_addr; +static char *dev_addr; module_param(dev_addr, charp, S_IRUGO); MODULE_PARM_DESC(dev_addr, "Device Ethernet Address"); /* this address is invisible to ifconfig */ -static char *__initdata host_addr; +static char *host_addr; module_param(host_addr, charp, S_IRUGO); MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); @@ -403,6 +407,7 @@ static inline int BITRATE(struct usb_gadget *g) #define STRING_CDC 7 #define STRING_SUBSET 8 #define STRING_RNDIS 9 +#define STRING_SERIALNUMBER 10 /* holds our biggest descriptor (or RNDIS response) */ #define USB_BUFSIZ 256 @@ -870,6 +875,7 @@ static inline void __init hs_subset_descriptors(void) static char manufacturer [50]; static char product_desc [40] = DRIVER_DESC; +static char serial_number [20]; #ifdef DEV_CONFIG_CDC /* address that the host will use ... usually assigned at random */ @@ -880,6 +886,7 @@ static char ethaddr [2 * ETH_ALEN + 1]; static struct usb_string strings [] = { { STRING_MANUFACTURER, manufacturer, }, { STRING_PRODUCT, product_desc, }, + { STRING_SERIALNUMBER, serial_number, }, { STRING_DATA, "Ethernet Data", }, #ifdef DEV_CONFIG_CDC { STRING_CDC, "CDC Ethernet", }, @@ -2162,7 +2169,7 @@ static u8 __init nibble (unsigned char c) return 0; } -static void __init get_ether_addr (const char *str, u8 *dev_addr) +static int __init get_ether_addr(const char *str, u8 *dev_addr) { if (str) { unsigned i; @@ -2177,9 +2184,10 @@ static void __init get_ether_addr (const char *str, u8 *dev_addr) dev_addr [i] = num; } if (is_valid_ether_addr (dev_addr)) - return; + return 0; } random_ether_addr(dev_addr); + return 1; } static int __init @@ -2277,6 +2285,10 @@ eth_bind (struct usb_gadget *gadget) strlcpy (manufacturer, iManufacturer, sizeof manufacturer); if (iProduct) strlcpy (product_desc, iProduct, sizeof product_desc); + if (iSerialNumber) { + device_desc.iSerialNumber = STRING_SERIALNUMBER, + strlcpy(serial_number, iSerialNumber, sizeof serial_number); + } /* all we really need is bulk IN/OUT */ usb_ep_autoconfig_reset (gadget); @@ -2386,9 +2398,13 @@ autoconf_fail: * The host side address is used with CDC and RNDIS, and commonly * ends up in a persistent config database. */ - get_ether_addr(dev_addr, net->dev_addr); + if (get_ether_addr(dev_addr, net->dev_addr)) + dev_warn(&gadget->dev, + "using random %s ethernet address\n", "self"); if (cdc || rndis) { - get_ether_addr(host_addr, dev->host_mac); + if (get_ether_addr(host_addr, dev->host_mac)) + dev_warn(&gadget->dev, + "using random %s ethernet address\n", "host"); #ifdef DEV_CONFIG_CDC snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X", dev->host_mac [0], dev->host_mac [1], -- cgit v1.2.3-59-g8ed1b From addf36fec058691f7ba4f95b5487d140f4a86f5a Mon Sep 17 00:00:00 2001 From: Matthew Martin Date: Wed, 15 Feb 2006 15:41:25 -0600 Subject: [PATCH] USB: Fix warning in drivers/usb/media/ov511.c Gcc 4.0.2 had the warning: drivers/usb/media/ov511.c: In function 'show_exposure': drivers/usb/media/ov511.c:5642: warning: 'exp' may be used uninitialized in this function Here is the patch to fix that warning. Signed-off-by: Matthew Martin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/media/ov511.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c index cfec8c61574e..1d887ec06080 100644 --- a/drivers/usb/media/ov511.c +++ b/drivers/usb/media/ov511.c @@ -5639,7 +5639,7 @@ static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); static ssize_t show_exposure(struct class_device *cd, char *buf) { struct usb_ov511 *ov = cd_to_ov(cd); - unsigned char exp; + unsigned char exp = 0; if (!ov->dev) return -ENODEV; -- cgit v1.2.3-59-g8ed1b From 9e47a52bf36fa4a24f56f878f4ca57eb885c78dd Mon Sep 17 00:00:00 2001 From: Luca Risolia Date: Wed, 8 Feb 2006 00:05:27 +0000 Subject: [PATCH] USB: ZC0301 driver updates "Cosmetic" driver updates for the ZC0301 driver: - Fix stream_interrupt() (and work around a possible kernel bug); - Fix vidioc_enum_input() and split vidioc_gs_input() in two parts; - Use wait_event_interruptible_timeout() instead of wait_event_interruptible() when waiting for video frames; - replace erroneous wake_up_interruptible(&wait_stream) with wake_up(&wait_stream); - Cosmetic cleanups in the documentation. Signed-off-by: Luca Risolia Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/zc0301.txt | 19 ++++++---------- drivers/usb/media/zc0301.h | 2 +- drivers/usb/media/zc0301_core.c | 43 +++++++++++++++++++++++------------- drivers/usb/media/zc0301_pas202bcb.c | 2 +- 4 files changed, 37 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/Documentation/usb/zc0301.txt b/Documentation/usb/zc0301.txt index 10590bf625e4..0889ae6ac7d8 100644 --- a/Documentation/usb/zc0301.txt +++ b/Documentation/usb/zc0301.txt @@ -67,8 +67,7 @@ Some of the features of the driver are: - available mmap or read/poll methods for video streaming through isochronous data transfers; - automatic detection of image sensor; -- video formats is standard JPEG in various compression qualities - (see also "Notes for V4L2 application developers" paragraph); +- video format is standard JPEG; - full support for the capabilities of every possible image sensors that can be connected to the ZC0301 bridges, including, for istance, red, green, blue and global gain adjustments and exposure control (see "Supported @@ -226,10 +225,6 @@ The same number of buffers as before will be allocated again to match the size of the new video frames, so you have to map the buffers again before any I/O attempts on them. -This driver supports the standard JPEG video format. The current compression -quality may vary from 0 to 3 and can be selected or queried thanks to the -VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. - 10. Contact information ======================= @@ -242,9 +237,9 @@ the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'. 11. Credits =========== -- Informations about the chip internals to enable the I2C protocol have been - taken from the documentation of the ZC030x Video4Linux1 driver written by - Andrew Birkett ; -- Initialization values of the ZC0301 connected to the PAS202BCB image sensor - have been taken from the SPCA5XX driver maintained by - Michel Xhaard +- Informations about the chip internals needed to enable the I2C protocol have + been taken from the documentation of the ZC030x Video4Linux1 driver written + by Andrew Birkett ; +- Initialization values of the ZC0301 controller connected to the PAS202BCB + image sensor have been taken from the SPCA5XX driver maintained by + Michel Xhaard . diff --git a/drivers/usb/media/zc0301.h b/drivers/usb/media/zc0301.h index 6fa5075f1e3d..cb1a0823bc63 100644 --- a/drivers/usb/media/zc0301.h +++ b/drivers/usb/media/zc0301.h @@ -45,7 +45,7 @@ #define ZC0301_MAX_DEVICES 64 #define ZC0301_FORCE_MUNMAP 0 #define ZC0301_MAX_FRAMES 32 -#define ZC0301_COMPRESSION_QUALITY 2 +#define ZC0301_COMPRESSION_QUALITY 0 #define ZC0301_URBS 2 #define ZC0301_ISO_PACKETS 7 #define ZC0301_ALTERNATE_SETTING 7 diff --git a/drivers/usb/media/zc0301_core.c b/drivers/usb/media/zc0301_core.c index 238f60f7f472..7e8b1676d144 100644 --- a/drivers/usb/media/zc0301_core.c +++ b/drivers/usb/media/zc0301_core.c @@ -3,9 +3,9 @@ * * * Copyright (C) 2006 by Luca Risolia * * * - * Informations about the chip internals to enable the I2C protocol have * - * been taken from the documentation of the ZC030x Video4Linux1 driver * - * written by Andrew Birkett * + * Informations about the chip internals needed to enable the I2C protocol * + * have been taken from the documentation of the ZC030x Video4Linux1 * + * driver written by Andrew Birkett * * * * 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 * @@ -54,8 +54,8 @@ #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" #define ZC0301_AUTHOR_EMAIL "" #define ZC0301_MODULE_LICENSE "GPL" -#define ZC0301_MODULE_VERSION "1:1.00" -#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 0) +#define ZC0301_MODULE_VERSION "1:1.01" +#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1) /*****************************************************************************/ @@ -314,7 +314,7 @@ static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs) if ((*f)) (*f)->state = F_QUEUED; DBG(3, "Stream interrupted"); - wake_up_interruptible(&cam->wait_stream); + wake_up(&cam->wait_stream); } if (cam->state & DEV_DISCONNECTED) @@ -526,7 +526,7 @@ static int zc0301_stream_interrupt(struct zc0301_device* cam) ZC0301_URB_TIMEOUT); if (cam->state & DEV_DISCONNECTED) return -ENODEV; - else if (!timeout) { + else if (cam->stream != STREAM_OFF) { cam->state |= DEV_MISCONFIGURED; DBG(1, "URB timeout reached. The camera is misconfigured. To " "use it, close and open /dev/video%d again.", @@ -547,8 +547,7 @@ zc0301_set_compression(struct zc0301_device* cam, if ((r = zc0301_read_reg(cam, 0x0008)) < 0) err += r; - err += zc0301_write_reg(cam, 0x0008, - r | 0x11 | (compression->quality >> 1)); + err += zc0301_write_reg(cam, 0x0008, r | 0x11 | compression->quality); return err ? -EIO : 0; } @@ -737,8 +736,7 @@ static int zc0301_release(struct inode* inode, struct file* filp) static ssize_t -zc0301_read(struct file* filp, char __user * buf, - size_t count, loff_t* f_pos) +zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) { struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); struct zc0301_frame_t* f, * i; @@ -1019,6 +1017,7 @@ zc0301_vidioc_enuminput(struct zc0301_device* cam, void __user * arg) memset(&i, 0, sizeof(i)); strcpy(i.name, "Camera"); + i.type = V4L2_INPUT_TYPE_CAMERA; if (copy_to_user(arg, &i, sizeof(i))) return -EFAULT; @@ -1028,7 +1027,19 @@ zc0301_vidioc_enuminput(struct zc0301_device* cam, void __user * arg) static int -zc0301_vidioc_gs_input(struct zc0301_device* cam, void __user * arg) +zc0301_vidioc_g_input(struct zc0301_device* cam, void __user * arg) +{ + int index = 0; + + if (copy_to_user(arg, &index, sizeof(index))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_s_input(struct zc0301_device* cam, void __user * arg) { int index; @@ -1446,7 +1457,7 @@ zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg) if (copy_from_user(&jc, arg, sizeof(jc))) return -EFAULT; - if (jc.quality < 0 || jc.quality > 3) + if (jc.quality != 0) return -EINVAL; if (cam->stream == STREAM_ON) @@ -1738,8 +1749,10 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, return zc0301_vidioc_enuminput(cam, arg); case VIDIOC_G_INPUT: + return zc0301_vidioc_g_input(cam, arg); + case VIDIOC_S_INPUT: - return zc0301_vidioc_gs_input(cam, arg); + return zc0301_vidioc_s_input(cam, arg); case VIDIOC_QUERYCTRL: return zc0301_vidioc_query_ctrl(cam, arg); @@ -1980,7 +1993,7 @@ static void zc0301_usb_disconnect(struct usb_interface* intf) zc0301_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; wake_up_interruptible(&cam->wait_frame); - wake_up_interruptible(&cam->wait_stream); + wake_up(&cam->wait_stream); } else { cam->state |= DEV_DISCONNECTED; zc0301_release_resources(cam); diff --git a/drivers/usb/media/zc0301_pas202bcb.c b/drivers/usb/media/zc0301_pas202bcb.c index 83b45f1c0f4e..32b9b9329cbf 100644 --- a/drivers/usb/media/zc0301_pas202bcb.c +++ b/drivers/usb/media/zc0301_pas202bcb.c @@ -318,7 +318,7 @@ static struct zc0301_sensor pas202bcb = { .width = 640, .height = 480, .pixelformat = V4L2_PIX_FMT_JPEG, - .priv = 16, + .priv = 8, }, }; -- cgit v1.2.3-59-g8ed1b From 80b6ca48321974a6566a1c9048ba34f60420bca6 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Mon, 27 Feb 2006 21:29:43 +0100 Subject: [PATCH] USB: kzalloc() conversion for rest of drivers/usb Signed-off-by: Eric Sesterhenn Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-mem.c | 10 +++------- drivers/usb/host/ehci-sched.c | 3 +-- drivers/usb/host/hc_crisv10.c | 12 ++++-------- drivers/usb/media/ov511.c | 4 +--- drivers/usb/media/pwc/pwc-if.c | 3 +-- drivers/usb/media/se401.c | 4 +--- drivers/usb/media/stv680.c | 7 ++----- drivers/usb/misc/auerswald.c | 6 ++---- drivers/usb/misc/usblcd.c | 3 +-- drivers/usb/misc/usbtest.c | 9 +++------ drivers/usb/mon/mon_main.c | 3 +-- drivers/usb/mon/mon_text.c | 3 +-- drivers/usb/net/zd1201.c | 9 +++------ drivers/usb/serial/cp2101.c | 4 +--- drivers/usb/serial/cypress_m8.c | 3 +-- drivers/usb/serial/ftdi_sio.c | 3 +-- drivers/usb/serial/garmin_gps.c | 3 +-- drivers/usb/serial/io_edgeport.c | 3 +-- drivers/usb/serial/io_ti.c | 6 ++---- drivers/usb/serial/ir-usb.c | 3 +-- drivers/usb/serial/keyspan.c | 6 ++---- drivers/usb/serial/kobil_sct.c | 16 +++++----------- drivers/usb/serial/mct_u232.c | 3 +-- drivers/usb/serial/option.c | 3 +-- drivers/usb/serial/pl2303.c | 6 ++---- drivers/usb/serial/ti_usb_3410_5052.c | 3 +-- drivers/usb/serial/usb-serial.c | 6 ++---- drivers/usb/serial/visor.c | 3 +-- drivers/usb/storage/isd200.c | 2 +- 29 files changed, 48 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index ec7eb3f4f867..766061e0260a 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c @@ -220,13 +220,9 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) ehci->periodic [i] = EHCI_LIST_END; /* software shadow of hardware table */ - ehci->pshadow = kmalloc (ehci->periodic_size * sizeof (void *), flags); - if (ehci->pshadow == NULL) { - goto fail; - } - memset (ehci->pshadow, 0, ehci->periodic_size * sizeof (void *)); - - return 0; + ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags); + if (ehci->pshadow != NULL) + return 0; fail: ehci_dbg (ehci, "couldn't init memory\n"); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 90d6900a37f4..5871944e6145 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -864,9 +864,8 @@ iso_sched_alloc (unsigned packets, gfp_t mem_flags) int size = sizeof *iso_sched; size += packets * sizeof (struct ehci_iso_packet); - iso_sched = kmalloc (size, mem_flags); + iso_sched = kzalloc(size, mem_flags); if (likely (iso_sched != NULL)) { - memset(iso_sched, 0, size); INIT_LIST_HEAD (&iso_sched->td_list); } return iso_sched; diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c index 641268d7e6f3..2fe7fd19437b 100644 --- a/drivers/usb/host/hc_crisv10.c +++ b/drivers/usb/host/hc_crisv10.c @@ -2137,10 +2137,9 @@ static int etrax_usb_submit_bulk_urb(struct urb *urb) urb->status = -EINPROGRESS; /* Setup the hcpriv data. */ - urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); + urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); assert(urb_priv != NULL); /* This sets rx_offset to 0. */ - memset(urb_priv, 0, sizeof(etrax_urb_priv_t)); urb_priv->urb_state = NOT_STARTED; urb->hcpriv = urb_priv; @@ -2475,10 +2474,9 @@ static int etrax_usb_submit_ctrl_urb(struct urb *urb) urb->status = -EINPROGRESS; /* Setup the hcpriv data. */ - urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); + urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); assert(urb_priv != NULL); /* This sets rx_offset to 0. */ - memset(urb_priv, 0, sizeof(etrax_urb_priv_t)); urb_priv->urb_state = NOT_STARTED; urb->hcpriv = urb_priv; @@ -2767,9 +2765,8 @@ static void etrax_usb_add_to_intr_sb_list(struct urb *urb, int epid) maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); interval = urb->interval; - urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); + urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); assert(urb_priv != NULL); - memset(urb_priv, 0, sizeof(etrax_urb_priv_t)); urb->hcpriv = urb_priv; first_ep = &TxIntrEPList[0]; @@ -2997,9 +2994,8 @@ static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid) prev_sb_desc = next_sb_desc = temp_sb_desc = NULL; - urb_priv = kmalloc(sizeof(etrax_urb_priv_t), GFP_ATOMIC); + urb_priv = kzalloc(sizeof(etrax_urb_priv_t), GFP_ATOMIC); assert(urb_priv != NULL); - memset(urb_priv, 0, sizeof(etrax_urb_priv_t)); urb->hcpriv = urb_priv; urb_priv->epid = epid; diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c index 1d887ec06080..da44579d6f29 100644 --- a/drivers/usb/media/ov511.c +++ b/drivers/usb/media/ov511.c @@ -5686,13 +5686,11 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) if (idesc->bInterfaceSubClass != 0x00) return -ENODEV; - if ((ov = kmalloc(sizeof(*ov), GFP_KERNEL)) == NULL) { + if ((ov = kzalloc(sizeof(*ov), GFP_KERNEL)) == NULL) { err("couldn't kmalloc ov struct"); goto error_out; } - memset(ov, 0, sizeof(*ov)); - ov->dev = dev; ov->iface = idesc->bInterfaceNumber; ov->led_policy = led; diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c index db6753dc5ba5..90eb26042817 100644 --- a/drivers/usb/media/pwc/pwc-if.c +++ b/drivers/usb/media/pwc/pwc-if.c @@ -1867,12 +1867,11 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id Info("Warning: more than 1 configuration available.\n"); /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */ - pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL); + pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL); if (pdev == NULL) { Err("Oops, could not allocate memory for pwc_device.\n"); return -ENOMEM; } - memset(pdev, 0, sizeof(struct pwc_device)); pdev->type = type_id; pdev->vsize = default_size; pdev->vframes = default_fps; diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c index 8c3b1ad8a8fd..f03ea7f89596 100644 --- a/drivers/usb/media/se401.c +++ b/drivers/usb/media/se401.c @@ -1345,13 +1345,11 @@ static int se401_probe(struct usb_interface *intf, /* We found one */ info("SE401 camera found: %s", camera_name); - if ((se401 = kmalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { + if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { err("couldn't kmalloc se401 struct"); return -ENOMEM; } - memset(se401, 0, sizeof(*se401)); - se401->dev = dev; se401->iface = interface->bInterfaceNumber; se401->camera_name = camera_name; diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c index b1a6be2958ed..9636da20748d 100644 --- a/drivers/usb/media/stv680.c +++ b/drivers/usb/media/stv680.c @@ -318,12 +318,11 @@ static int stv_init (struct usb_stv *stv680) unsigned char *buffer; unsigned long int bufsize; - buffer = kmalloc (40, GFP_KERNEL); + buffer = kzalloc (40, GFP_KERNEL); if (buffer == NULL) { PDEBUG (0, "STV(e): Out of (small buf) memory"); return -1; } - memset (buffer, 0, 40); udelay (100); /* set config 1, interface 0, alternate 0 */ @@ -1388,14 +1387,12 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id goto error; } /* We found one */ - if ((stv680 = kmalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) { + if ((stv680 = kzalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) { PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct."); retval = -ENOMEM; goto error; } - memset (stv680, 0, sizeof (*stv680)); - stv680->udev = dev; stv680->camera_name = camera_name; diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index ad2f4cccd388..1fef36e71c57 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -570,10 +570,9 @@ static int auerchain_setup (pauerchain_t acp, unsigned int numElements) /* fill the list of free elements */ for (;numElements; numElements--) { - acep = (pauerchainelement_t) kmalloc (sizeof (auerchainelement_t), GFP_KERNEL); + acep = kzalloc(sizeof(auerchainelement_t), GFP_KERNEL); if (!acep) goto ac_fail; - memset (acep, 0, sizeof (auerchainelement_t)); INIT_LIST_HEAD (&acep->list); list_add_tail (&acep->list, &acp->free_list); } @@ -761,10 +760,9 @@ static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned /* fill the list of free elements */ for (;numElements; numElements--) { - bep = (pauerbuf_t) kmalloc (sizeof (auerbuf_t), GFP_KERNEL); + bep = kzalloc(sizeof(auerbuf_t), GFP_KERNEL); if (!bep) goto bl_fail; - memset (bep, 0, sizeof (auerbuf_t)); bep->list = bcp; INIT_LIST_HEAD (&bep->buff_list); bep->bufp = kmalloc (bufsize, GFP_KERNEL); diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index cc3dae3f34e0..c82c402285a0 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -270,12 +270,11 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id int retval = -ENOMEM; /* allocate memory for our device state and initialize it */ - dev = kmalloc(sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { err("Out of memory"); goto error; } - memset(dev, 0x00, sizeof(*dev)); kref_init(&dev->kref); dev->udev = usb_get_dev(interface_to_usbdev(interface)); diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 84fa1728f052..9d59b901841c 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -382,12 +382,11 @@ alloc_sglist (int nents, int max, int vary) for (i = 0; i < nents; i++) { char *buf; - buf = kmalloc (size, SLAB_KERNEL); + buf = kzalloc (size, SLAB_KERNEL); if (!buf) { free_sglist (sg, i); return NULL; } - memset (buf, 0, size); /* kmalloc pages are always physically contiguous! */ sg_init_one(&sg[i], buf, size); @@ -842,10 +841,9 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) * as with bulk/intr sglists, sglen is the queue depth; it also * controls which subtests run (more tests than sglen) or rerun. */ - urb = kmalloc (param->sglen * sizeof (struct urb *), SLAB_KERNEL); + urb = kcalloc(param->sglen, sizeof(struct urb *), SLAB_KERNEL); if (!urb) return -ENOMEM; - memset (urb, 0, param->sglen * sizeof (struct urb *)); for (i = 0; i < param->sglen; i++) { int pipe = usb_rcvctrlpipe (udev, 0); unsigned len; @@ -1865,10 +1863,9 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) } #endif - dev = kmalloc (sizeof *dev, SLAB_KERNEL); + dev = kzalloc(sizeof(*dev), SLAB_KERNEL); if (!dev) return -ENOMEM; - memset (dev, 0, sizeof *dev); info = (struct usbtest_info *) id->driver_info; dev->info = info; init_MUTEX (&dev->sem); diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index b03e346e33f1..6ecc27302211 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -277,9 +277,8 @@ static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus) char name[NAMESZ]; int rc; - if ((mbus = kmalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL) + if ((mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL) goto err_alloc; - memset(mbus, 0, sizeof(struct mon_bus)); kref_init(&mbus->ref); spin_lock_init(&mbus->lock); INIT_LIST_HEAD(&mbus->r_list); diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 59089e8b7e5e..ac043ec2b8dc 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -213,12 +213,11 @@ static int mon_text_open(struct inode *inode, struct file *file) mbus = inode->u.generic_ip; ubus = mbus->u_bus; - rp = kmalloc(sizeof(struct mon_reader_text), GFP_KERNEL); + rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL); if (rp == NULL) { rc = -ENOMEM; goto err_alloc; } - memset(rp, 0, sizeof(struct mon_reader_text)); INIT_LIST_HEAD(&rp->e_list); init_waitqueue_head(&rp->wait); mutex_init(&rp->printf_lock); diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c index f3a8e2807c3b..fe9b60cd8d95 100644 --- a/drivers/usb/net/zd1201.c +++ b/drivers/usb/net/zd1201.c @@ -621,10 +621,9 @@ static int zd1201_drvr_start(struct zd1201 *zd) __le16 zdmax; unsigned char *buffer; - buffer = kmalloc(ZD1201_RXSIZE, GFP_KERNEL); + buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL); if (!buffer) return -ENOMEM; - memset(buffer, 0, ZD1201_RXSIZE); usb_fill_bulk_urb(zd->rx_urb, zd->usb, usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE, @@ -1750,11 +1749,9 @@ static int zd1201_probe(struct usb_interface *interface, usb = interface_to_usbdev(interface); - zd = kmalloc(sizeof(struct zd1201), GFP_KERNEL); - if (!zd) { + zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL); + if (!zd) return -ENOMEM; - } - memset(zd, 0, sizeof(struct zd1201)); zd->ap = ap; zd->usb = usb; zd->removed = 0; diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index dc7a069503e0..9ea7b4a4a22b 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -169,9 +169,7 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request, /* Number of integers required to contain the array */ length = (((size - 1) | 3) + 1)/4; - buf = kmalloc (length * sizeof(u32), GFP_KERNEL); - memset(buf, 0, length * sizeof(u32)); - + buf = kcalloc(length, sizeof(u32), GFP_KERNEL); if (!buf) { dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__); return -ENOMEM; diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 68067fe117a4..71af3bf5adb7 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -435,11 +435,10 @@ static int generic_startup (struct usb_serial *serial) dbg("%s - port %d", __FUNCTION__, serial->port[0]->number); - priv = kmalloc(sizeof (struct cypress_private), GFP_KERNEL); + priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL); if (!priv) return -ENOMEM; - memset(priv, 0x00, sizeof (struct cypress_private)); spin_lock_init(&priv->lock); priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE); if (priv->buf == NULL) { diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c145e1ed8429..ece52a6328b5 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1141,12 +1141,11 @@ static int ftdi_sio_attach (struct usb_serial *serial) dbg("%s",__FUNCTION__); - priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); + priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); if (!priv){ err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private)); return -ENOMEM; } - memset(priv, 0, sizeof(*priv)); spin_lock_init(&priv->rx_lock); init_waitqueue_head(&priv->delta_msr_wait); diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index d6f55e9dccae..5ec9bf5bac8d 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1422,12 +1422,11 @@ static int garmin_attach (struct usb_serial *serial) dbg("%s", __FUNCTION__); - garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL); + garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); if (garmin_data_p == NULL) { dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__); return -ENOMEM; } - memset (garmin_data_p, 0, sizeof(struct garmin_data)); init_timer(&garmin_data_p->timer); spin_lock_init(&garmin_data_p->lock); INIT_LIST_HEAD(&garmin_data_p->pktlist); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 3f29e6b0fd19..b606c5968102 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -2725,12 +2725,11 @@ static int edge_startup (struct usb_serial *serial) dev = serial->dev; /* create our private serial structure */ - edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL); + edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); if (edge_serial == NULL) { dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); return -ENOMEM; } - memset (edge_serial, 0, sizeof(struct edgeport_serial)); spin_lock_init(&edge_serial->es_lock); edge_serial->serial = serial; usb_set_serial_data(serial, edge_serial); diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index afc0f34b3a46..8e1e2253748b 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2727,12 +2727,11 @@ static int edge_startup (struct usb_serial *serial) dev = serial->dev; /* create our private serial structure */ - edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL); + edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); if (edge_serial == NULL) { dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); return -ENOMEM; } - memset (edge_serial, 0, sizeof(struct edgeport_serial)); sema_init(&edge_serial->es_sem, 1); edge_serial->serial = serial; usb_set_serial_data(serial, edge_serial); @@ -2745,12 +2744,11 @@ static int edge_startup (struct usb_serial *serial) /* set up our port private structures */ for (i = 0; i < serial->num_ports; ++i) { - edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); + edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); if (edge_port == NULL) { dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); goto cleanup; } - memset (edge_port, 0, sizeof(struct edgeport_port)); spin_lock_init(&edge_port->ep_lock); edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE); if (edge_port->ep_out_buf == NULL) { diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index a59010421444..426182ddc42a 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -184,10 +184,9 @@ static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, struct irda_class_desc *desc; int ret; - desc = kmalloc(sizeof (struct irda_class_desc), GFP_KERNEL); + desc = kzalloc(sizeof (struct irda_class_desc), GFP_KERNEL); if (desc == NULL) return NULL; - memset(desc, 0, sizeof(struct irda_class_desc)); ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0), IU_REQ_GET_CLASS_DESC, diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 3b958e60f5e8..052b735c4fbd 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -2250,12 +2250,11 @@ static int keyspan_startup (struct usb_serial *serial) } /* Setup private data for serial driver */ - s_priv = kmalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL); + s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL); if (!s_priv) { dbg("%s - kmalloc for keyspan_serial_private failed.", __FUNCTION__); return -ENOMEM; } - memset(s_priv, 0, sizeof(struct keyspan_serial_private)); s_priv->device_details = d_details; usb_set_serial_data(serial, s_priv); @@ -2263,12 +2262,11 @@ static int keyspan_startup (struct usb_serial *serial) /* Now setup per port private data */ for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; - p_priv = kmalloc(sizeof(struct keyspan_port_private), GFP_KERNEL); + p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL); if (!p_priv) { dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __FUNCTION__, i); return (1); } - memset(p_priv, 0, sizeof(struct keyspan_port_private)); p_priv->device_details = d_details; usb_set_serial_port_data(port, p_priv); } diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index b8b213185d0f..87dfcd89ffab 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -255,11 +255,9 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp) } // allocate memory for transfer buffer - transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); + transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); if (! transfer_buffer) { return -ENOMEM; - } else { - memset(transfer_buffer, 0, transfer_buffer_length); } // allocate write_urb @@ -383,11 +381,10 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs) // BEGIN DEBUG /* - dbg_data = (unsigned char *) kmalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); + dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); if (! dbg_data) { return; } - memset(dbg_data, 0, (3 * purb->actual_length + 10)); for (i = 0; i < purb->actual_length; i++) { sprintf(dbg_data +3*i, "%02X ", data[i]); } @@ -518,11 +515,10 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file) } // allocate memory for transfer buffer - transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); + transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); if (!transfer_buffer) { return -ENOMEM; } - memset(transfer_buffer, 0, transfer_buffer_length); result = usb_control_msg( port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0 ), @@ -564,11 +560,10 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file, } // allocate memory for transfer buffer - transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); + transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); if (! transfer_buffer) { return -ENOMEM; } - memset(transfer_buffer, 0, transfer_buffer_length); if (set & TIOCM_RTS) rts = 1; @@ -655,11 +650,10 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, (struct termios __user *)arg)) return -EFAULT; - settings = (unsigned char *) kmalloc(50, GFP_KERNEL); + settings = kzalloc(50, GFP_KERNEL); if (! settings) { return -ENOBUFS; } - memset(settings, 0, 50); switch (priv->internal_termios.c_cflag & CBAUD) { case B1200: diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index b6d6cab9c859..35bd29b6c408 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -348,10 +348,9 @@ static int mct_u232_startup (struct usb_serial *serial) struct mct_u232_private *priv; struct usb_serial_port *port, *rport; - priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL); + priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL); if (!priv) return -ENOMEM; - memset(priv, 0, sizeof(struct mct_u232_private)); spin_lock_init(&priv->lock); usb_set_serial_port_data(serial->port[0], priv); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 52bdf6fe46f2..a8455c9e79dd 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -631,13 +631,12 @@ static int option_startup(struct usb_serial *serial) /* Now setup per port private data */ for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; - portdata = kmalloc(sizeof(*portdata), GFP_KERNEL); + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); if (!portdata) { dbg("%s: kmalloc for option_port_private (%d) failed!.", __FUNCTION__, i); return (1); } - memset(portdata, 0, sizeof(struct option_port_private)); usb_set_serial_port_data(port, portdata); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 37c81c08faad..cf2213bae0e0 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -218,10 +218,9 @@ static int pl2303_startup (struct usb_serial *serial) dbg("device type: %d", type); for (i = 0; i < serial->num_ports; ++i) { - priv = kmalloc (sizeof (struct pl2303_private), GFP_KERNEL); + priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL); if (!priv) goto cleanup; - memset (priv, 0x00, sizeof (struct pl2303_private)); spin_lock_init(&priv->lock); priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE); if (priv->buf == NULL) { @@ -383,12 +382,11 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol } } - buf = kmalloc (7, GFP_KERNEL); + buf = kzalloc (7, GFP_KERNEL); if (!buf) { dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__); return; } - memset (buf, 0x00, 0x07); i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0), GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index c18db3257073..c3a2071b802d 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -416,12 +416,11 @@ static int ti_startup(struct usb_serial *serial) dev->actconfig->desc.bConfigurationValue); /* create device structure */ - tdev = kmalloc(sizeof(struct ti_device), GFP_KERNEL); + tdev = kzalloc(sizeof(struct ti_device), GFP_KERNEL); if (tdev == NULL) { dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } - memset(tdev, 0, sizeof(struct ti_device)); sema_init(&tdev->td_open_close_sem, 1); tdev->td_serial = serial; usb_set_serial_data(serial, tdev); diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index b5c96e74a903..097f4e8488fe 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -564,12 +564,11 @@ static struct usb_serial * create_serial (struct usb_device *dev, { struct usb_serial *serial; - serial = kmalloc (sizeof (*serial), GFP_KERNEL); + serial = kzalloc(sizeof(*serial), GFP_KERNEL); if (!serial) { dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__); return NULL; } - memset (serial, 0, sizeof(*serial)); serial->dev = usb_get_dev(dev); serial->type = driver; serial->interface = interface; @@ -778,10 +777,9 @@ int usb_serial_probe(struct usb_interface *interface, serial->num_port_pointers = max_endpoints; dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints); for (i = 0; i < max_endpoints; ++i) { - port = kmalloc(sizeof(struct usb_serial_port), GFP_KERNEL); + port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); if (!port) goto probe_error; - memset(port, 0x00, sizeof(struct usb_serial_port)); port->number = i + serial->minor; port->serial = serial; spin_lock_init(&port->lock); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 11a48d874752..f5c3841d4843 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -763,10 +763,9 @@ static int generic_startup(struct usb_serial *serial) int i; for (i = 0; i < serial->num_ports; ++i) { - priv = kmalloc (sizeof(*priv), GFP_KERNEL); + priv = kzalloc (sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - memset (priv, 0x00, sizeof(*priv)); spin_lock_init(&priv->lock); usb_set_serial_port_data(serial->port[i], priv); } diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 7308e8cbe8f9..6831dca93c1b 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -1382,7 +1382,7 @@ static int isd200_init_info(struct us_data *us) } else US_DEBUGP("ERROR - kmalloc failure\n"); - return(retStatus); + return retStatus; } /************************************************************************** -- cgit v1.2.3-59-g8ed1b From 7039f4224d4e40b06308d5c1a97427af1a142459 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Mon, 27 Feb 2006 13:34:10 -0800 Subject: [PATCH] USB: kzalloc() conversion in drivers/usb/gadget this patch converts drivers/usb to kzalloc usage. Compile tested with allyes config. I think there was a bug in drivers/usb/gadget/inode.c because it used sizeof(*data) for the kmalloc() and sizeof(data) for the memset(), since sizeof(data) just returns the size for a pointer. Signed-off-by: Eric Sesterhenn Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/dummy_hcd.c | 3 +-- drivers/usb/gadget/goku_udc.c | 3 +-- drivers/usb/gadget/inode.c | 6 ++---- drivers/usb/gadget/lh7a40x_udc.c | 3 +-- drivers/usb/gadget/net2280.c | 3 +-- drivers/usb/gadget/omap_udc.c | 6 ++---- drivers/usb/gadget/pxa2xx_udc.c | 3 +-- drivers/usb/gadget/serial.c | 3 +-- drivers/usb/gadget/zero.c | 3 +-- 9 files changed, 11 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 9734cb76dd6c..42ce41d71b7f 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -478,10 +478,9 @@ dummy_alloc_request (struct usb_ep *_ep, gfp_t mem_flags) return NULL; ep = usb_ep_to_dummy_ep (_ep); - req = kmalloc (sizeof *req, mem_flags); + req = kzalloc(sizeof(*req), mem_flags); if (!req) return NULL; - memset (req, 0, sizeof *req); INIT_LIST_HEAD (&req->queue); return &req->req; } diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index b0f3cd63e3b9..66b81bbf6bee 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -275,11 +275,10 @@ goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) if (!_ep) return NULL; - req = kmalloc(sizeof *req, gfp_flags); + req = kzalloc(sizeof *req, gfp_flags); if (!req) return NULL; - memset(req, 0, sizeof *req); req->req.dma = DMA_ADDR_INVALID; INIT_LIST_HEAD(&req->queue); return &req->req; diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 0aab7d24c768..b44cfda76b61 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -170,10 +170,9 @@ static struct dev_data *dev_new (void) { struct dev_data *dev; - dev = kmalloc (sizeof *dev, GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return NULL; - memset (dev, 0, sizeof *dev); dev->state = STATE_DEV_DISABLED; atomic_set (&dev->count, 1); spin_lock_init (&dev->lock); @@ -1592,10 +1591,9 @@ static int activate_ep_files (struct dev_data *dev) gadget_for_each_ep (ep, dev->gadget) { struct ep_data *data; - data = kmalloc (sizeof *data, GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) goto enomem; - memset (data, 0, sizeof data); data->state = STATE_EP_DISABLED; init_MUTEX (&data->lock); init_waitqueue_head (&data->wait); diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index 1a362c5e7f3d..0d3424eda038 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c @@ -1114,11 +1114,10 @@ static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, DEBUG("%s, %p\n", __FUNCTION__, ep); - req = kmalloc(sizeof *req, gfp_flags); + req = kzalloc(sizeof(*req), gfp_flags); if (!req) return 0; - memset(req, 0, sizeof *req); INIT_LIST_HEAD(&req->queue); return &req->req; diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 67b13ab2f3f5..fb73dc100535 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -386,11 +386,10 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) return NULL; ep = container_of (_ep, struct net2280_ep, ep); - req = kmalloc (sizeof *req, gfp_flags); + req = kzalloc(sizeof(*req), gfp_flags); if (!req) return NULL; - memset (req, 0, sizeof *req); req->req.dma = DMA_ADDR_INVALID; INIT_LIST_HEAD (&req->queue); diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index a8972d7c97be..fbea51448909 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -273,9 +273,8 @@ omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) { struct omap_req *req; - req = kmalloc(sizeof *req, gfp_flags); + req = kzalloc(sizeof(*req), gfp_flags); if (req) { - memset (req, 0, sizeof *req); req->req.dma = DMA_ADDR_INVALID; INIT_LIST_HEAD (&req->queue); } @@ -2586,11 +2585,10 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv) /* UDC_PULLUP_EN gates the chip clock */ // OTG_SYSCON_1_REG |= DEV_IDLE_EN; - udc = kmalloc (sizeof *udc, SLAB_KERNEL); + udc = kzalloc(sizeof(*udc), SLAB_KERNEL); if (!udc) return -ENOMEM; - memset(udc, 0, sizeof *udc); spin_lock_init (&udc->lock); udc->gadget.ops = &omap_gadget_ops; diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index bb028c5b8952..680f7fc5b171 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -335,11 +335,10 @@ pxa2xx_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) { struct pxa2xx_request *req; - req = kmalloc (sizeof *req, gfp_flags); + req = kzalloc(sizeof(*req), gfp_flags); if (!req) return NULL; - memset (req, 0, sizeof *req); INIT_LIST_HEAD (&req->queue); return &req->req; } diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 548feaac4553..b992546c394d 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -2178,10 +2178,9 @@ static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags) return -EIO; for (i=0; iport_dev = dev; port->port_num = i; port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE); diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 44d8e5e77da7..51424f66a765 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -1188,10 +1188,9 @@ autoconf_fail: /* ok, we made sense of the hardware ... */ - dev = kmalloc (sizeof *dev, SLAB_KERNEL); + dev = kzalloc(sizeof(*dev), SLAB_KERNEL); if (!dev) return -ENOMEM; - memset (dev, 0, sizeof *dev); spin_lock_init (&dev->lock); dev->gadget = gadget; set_gadget_data (gadget, dev); -- cgit v1.2.3-59-g8ed1b From 2ffab02fea5880da284dc5511479b25a796a8dee Mon Sep 17 00:00:00 2001 From: Luca Risolia Date: Sat, 25 Feb 2006 06:50:47 +0000 Subject: [PATCH] USB: SN9C10x driver updates SN9C10x driver updates. Changes: + new, - removed, * cleanup, @ bugfix @ Fix stream_interrupt() @ Fix vidioc_enum_input() and split vidioc_gs_input() @ Need usb_get|put_dev() when disconnecting, if the device is open * Use wait_event_interruptible_timeout() instead of wait_event_interruptible() when waiting for video frames * replace wake_up_interruptible(&wait_stream) with wake_up(&wait_stream) * Cleanups and updates in the documentation + Use per-device sensor structures + Add support for PAS202BCA image sensors + Add frame_timeout module parameter Signed-off-by: Luca Risolia Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/sn9c102.txt | 11 ++ drivers/usb/media/Makefile | 5 +- drivers/usb/media/sn9c102.h | 23 +++- drivers/usb/media/sn9c102_core.c | 170 +++++++++++++---------- drivers/usb/media/sn9c102_ov7630.c | 33 +++-- drivers/usb/media/sn9c102_pas202bca.c | 238 +++++++++++++++++++++++++++++++++ drivers/usb/media/sn9c102_pas202bcb.c | 2 +- drivers/usb/media/sn9c102_sensor.h | 15 ++- drivers/usb/media/sn9c102_tas5110c1b.c | 14 +- drivers/usb/media/sn9c102_tas5130d1b.c | 12 +- 10 files changed, 416 insertions(+), 107 deletions(-) create mode 100644 drivers/usb/media/sn9c102_pas202bca.c (limited to 'drivers') diff --git a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt index c6b76414172c..b957beae5607 100644 --- a/Documentation/usb/sn9c102.txt +++ b/Documentation/usb/sn9c102.txt @@ -196,6 +196,14 @@ Description: Force the application to unmap previously mapped buffer memory 1 = force memory unmapping (save memory) Default: 0 ------------------------------------------------------------------------------- +Name: frame_timeout +Type: uint array (min = 0, max = 64) +Syntax: +Description: Timeout for a video frame in seconds. This parameter is + specific for each detected camera. This parameter can be + changed at runtime thanks to the /sys filesystem interface. +Default: 2 +------------------------------------------------------------------------------- Name: debug Type: ushort Syntax: @@ -321,6 +329,7 @@ Vendor ID Product ID --------- ---------- 0x0c45 0x6001 0x0c45 0x6005 +0x0c45 0x6007 0x0c45 0x6009 0x0c45 0x600d 0x0c45 0x6024 @@ -370,6 +379,7 @@ HV7131D Hynix Semiconductor, Inc. MI-0343 Micron Technology, Inc. OV7630 OmniVision Technologies, Inc. PAS106B PixArt Imaging, Inc. +PAS202BCA PixArt Imaging, Inc. PAS202BCB PixArt Imaging, Inc. TAS5110C1B Taiwan Advanced Sensor Corporation TAS5130D1B Taiwan Advanced Sensor Corporation @@ -493,6 +503,7 @@ Many thanks to following persons for their contribute (listed in alphabetical order): - Luca Capello for the donation of a webcam; +- Philippe Coval for having helped testing the PAS202BCA image sensor; - Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the donation of a webcam; - Jon Hollstrom for the donation of a webcam; diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile index 333bf09ca2d6..50e89a33b85e 100644 --- a/drivers/usb/media/Makefile +++ b/drivers/usb/media/Makefile @@ -2,7 +2,10 @@ # Makefile for USB Media drivers # -sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o +sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ + sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \ + sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ + sn9c102_tas5130d1b.o et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o zc0301-objs := zc0301_core.o zc0301_pas202bcb.o diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h index 59e44be27cb4..1d70a62b9f23 100644 --- a/drivers/usb/media/sn9c102.h +++ b/drivers/usb/media/sn9c102.h @@ -34,7 +34,8 @@ #include #include #include -#include +#include +#include #include "sn9c102_sensor.h" @@ -51,6 +52,7 @@ #define SN9C102_ALTERNATE_SETTING 8 #define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS) #define SN9C102_CTRL_TIMEOUT 300 +#define SN9C102_FRAME_TIMEOUT 2 /*****************************************************************************/ @@ -108,6 +110,7 @@ struct sn9c102_sysfs_attr { struct sn9c102_module_param { u8 force_munmap; + u16 frame_timeout; }; static DEFINE_MUTEX(sn9c102_sysfs_lock); @@ -117,7 +120,7 @@ struct sn9c102_device { struct video_device* v4ldev; enum sn9c102_bridge bridge; - struct sn9c102_sensor* sensor; + struct sn9c102_sensor sensor; struct usb_device* usbdev; struct urb* urb[SN9C102_URBS]; @@ -149,12 +152,21 @@ struct sn9c102_device { /*****************************************************************************/ +struct sn9c102_device* +sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) +{ + if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) + return cam; + + return NULL; +} + + void sn9c102_attach_sensor(struct sn9c102_device* cam, struct sn9c102_sensor* sensor) { - cam->sensor = sensor; - cam->sensor->usbdev = cam->usbdev; + memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); } /*****************************************************************************/ @@ -197,7 +209,8 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args) +dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args) #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c index 30119080871b..4c6cc6395723 100644 --- a/drivers/usb/media/sn9c102_core.c +++ b/drivers/usb/media/sn9c102_core.c @@ -25,11 +25,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -49,8 +47,8 @@ #define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" #define SN9C102_AUTHOR_EMAIL "" #define SN9C102_MODULE_LICENSE "GPL" -#define SN9C102_MODULE_VERSION "1:1.26" -#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 26) +#define SN9C102_MODULE_VERSION "1:1.27" +#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 27) /*****************************************************************************/ @@ -89,6 +87,15 @@ MODULE_PARM_DESC(force_munmap, "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." "\n"); +static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = + SN9C102_FRAME_TIMEOUT}; +module_param_array(frame_timeout, uint, NULL, 0644); +MODULE_PARM_DESC(frame_timeout, + "\n Timeout for a video frame in seconds." + "\nThis parameter is specific for each detected camera." + "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." + "\n"); + #ifdef SN9C102_DEBUG static unsigned short debug = SN9C102_DEBUG_LEVEL; module_param(debug, ushort, 0644); @@ -128,8 +135,8 @@ static u32 sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, enum sn9c102_io_method io) { - struct v4l2_pix_format* p = &(cam->sensor->pix_format); - struct v4l2_rect* r = &(cam->sensor->cropcap.bounds); + struct v4l2_pix_format* p = &(cam->sensor.pix_format); + struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); const size_t imagesize = cam->module_param.force_munmap || io == IO_READ ? (p->width * p->height * p->priv) / 8 : @@ -449,19 +456,13 @@ sn9c102_i2c_try_write(struct sn9c102_device* cam, int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address) { - if (!cam->sensor) - return -1; - - return sn9c102_i2c_try_read(cam, cam->sensor, address); + return sn9c102_i2c_try_read(cam, &cam->sensor, address); } int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value) { - if (!cam->sensor) - return -1; - - return sn9c102_i2c_try_write(cam, cam->sensor, address, value); + return sn9c102_i2c_try_write(cam, &cam->sensor, address, value); } /*****************************************************************************/ @@ -505,7 +506,7 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) size_t eoflen = sizeof(sn9c102_eof_header_t), i; unsigned j, n = sizeof(sn9c102_eof_header) / eoflen; - if (cam->sensor->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) + if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) return NULL; /* EOF header does not exist in compressed data */ for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++) @@ -535,7 +536,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) if ((*f)) (*f)->state = F_QUEUED; DBG(3, "Stream interrupted"); - wake_up_interruptible(&cam->wait_stream); + wake_up(&cam->wait_stream); } if (cam->state & DEV_DISCONNECTED) @@ -553,9 +554,9 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t, frame); - imagesize = (cam->sensor->pix_format.width * - cam->sensor->pix_format.height * - cam->sensor->pix_format.priv) / 8; + imagesize = (cam->sensor.pix_format.width * + cam->sensor.pix_format.height * + cam->sensor.pix_format.priv) / 8; soflen = (cam->bridge) == BRIDGE_SN9C103 ? sizeof(sn9c103_sof_header_t) : @@ -579,7 +580,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) redo: sof = sn9c102_find_sof_header(cam, pos, len); - if (!sof) { + if (likely(!sof)) { eof = sn9c102_find_eof_header(cam, pos, len); if ((*f)->state == F_GRABBING) { end_of_frame: @@ -589,8 +590,9 @@ end_of_frame: img = (eof > pos) ? eof - pos - 1 : 0; if ((*f)->buf.bytesused+img > imagesize) { - u32 b = (*f)->buf.bytesused + img - - imagesize; + u32 b; + b = (*f)->buf.bytesused + img - + imagesize; img = imagesize - (*f)->buf.bytesused; DBG(3, "Expected EOF not found: " "video frame cut"); @@ -608,9 +610,10 @@ end_of_frame: (*f)->buf.bytesused += img; if ((*f)->buf.bytesused == imagesize || - (cam->sensor->pix_format.pixelformat == + (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X && eof)) { - u32 b = (*f)->buf.bytesused; + u32 b; + b = (*f)->buf.bytesused; (*f)->state = F_DONE; (*f)->buf.sequence= ++cam->frame_count; spin_lock(&cam->queue_lock); @@ -667,7 +670,7 @@ start_of_frame: if (eof && eof < sof) goto end_of_frame; /* (1) */ else { - if (cam->sensor->pix_format.pixelformat == + if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) { eof = sof - soflen; goto end_of_frame; @@ -808,20 +811,21 @@ static int sn9c102_stop_transfer(struct sn9c102_device* cam) static int sn9c102_stream_interrupt(struct sn9c102_device* cam) { - int err = 0; + long timeout; cam->stream = STREAM_INTERRUPT; - err = wait_event_timeout(cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED), - SN9C102_URB_TIMEOUT); + timeout = wait_event_timeout(cam->wait_stream, + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + SN9C102_URB_TIMEOUT); if (cam->state & DEV_DISCONNECTED) return -ENODEV; - else if (err) { + else if (cam->stream != STREAM_OFF) { cam->state |= DEV_MISCONFIGURED; - DBG(1, "The camera is misconfigured. To use it, close and " - "open /dev/video%d again.", cam->v4ldev->minor); - return err; + DBG(1, "URB timeout reached. The camera is misconfigured. " + "To use it, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; } return 0; @@ -1057,7 +1061,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) return -ENODEV; } - if (!(cam->sensor->sysfs_ops & SN9C102_I2C_READ)) { + if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) { mutex_unlock(&sn9c102_sysfs_lock); return -ENOSYS; } @@ -1094,7 +1098,7 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) return -ENODEV; } - if (!(cam->sensor->sysfs_ops & SN9C102_I2C_WRITE)) { + if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) { mutex_unlock(&sn9c102_sysfs_lock); return -ENOSYS; } @@ -1249,7 +1253,7 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam) video_device_create_file(v4ldev, &class_device_attr_blue); video_device_create_file(v4ldev, &class_device_attr_red); } - if (cam->sensor && cam->sensor->sysfs_ops) { + if (cam->sensor.sysfs_ops) { video_device_create_file(v4ldev, &class_device_attr_i2c_reg); video_device_create_file(v4ldev, &class_device_attr_i2c_val); } @@ -1312,7 +1316,7 @@ static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale) static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect) { - struct sn9c102_sensor* s = cam->sensor; + struct sn9c102_sensor* s = &cam->sensor; u8 h_start = (u8)(rect->left - s->cropcap.bounds.left), v_start = (u8)(rect->top - s->cropcap.bounds.top), h_size = (u8)(rect->width / 16), @@ -1335,7 +1339,7 @@ static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect) static int sn9c102_init(struct sn9c102_device* cam) { - struct sn9c102_sensor* s = cam->sensor; + struct sn9c102_sensor* s = &cam->sensor; struct v4l2_control ctrl; struct v4l2_queryctrl *qctrl; struct v4l2_rect* rect; @@ -1428,6 +1432,8 @@ static void sn9c102_release_resources(struct sn9c102_device* cam) video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); + usb_put_dev(cam->usbdev); + mutex_unlock(&sn9c102_sysfs_lock); kfree(cam->control_buffer); @@ -1541,6 +1547,7 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); struct sn9c102_frame_t* f, * i; unsigned long lock_flags; + long timeout; int err = 0; if (mutex_lock_interruptible(&cam->fileop_mutex)) @@ -1592,20 +1599,22 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) mutex_unlock(&cam->fileop_mutex); return -EAGAIN; } - err = wait_event_interruptible - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED) ); - if (err) { + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) { mutex_unlock(&cam->fileop_mutex); - return err; + return timeout; } if (cam->state & DEV_DISCONNECTED) { mutex_unlock(&cam->fileop_mutex); return -ENODEV; } - if (cam->state & DEV_MISCONFIGURED) { + if (!timeout || (cam->state & DEV_MISCONFIGURED)) { mutex_unlock(&cam->fileop_mutex); return -EIO; } @@ -1816,6 +1825,7 @@ sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg) memset(&i, 0, sizeof(i)); strcpy(i.name, "Camera"); + i.type = V4L2_INPUT_TYPE_CAMERA; if (copy_to_user(arg, &i, sizeof(i))) return -EFAULT; @@ -1825,7 +1835,19 @@ sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg) static int -sn9c102_vidioc_gs_input(struct sn9c102_device* cam, void __user * arg) +sn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg) +{ + int index = 0; + + if (copy_to_user(arg, &index, sizeof(index))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg) { int index; @@ -1842,7 +1864,7 @@ sn9c102_vidioc_gs_input(struct sn9c102_device* cam, void __user * arg) static int sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg) { - struct sn9c102_sensor* s = cam->sensor; + struct sn9c102_sensor* s = &cam->sensor; struct v4l2_queryctrl qc; u8 i; @@ -1864,7 +1886,7 @@ sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg) static int sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg) { - struct sn9c102_sensor* s = cam->sensor; + struct sn9c102_sensor* s = &cam->sensor; struct v4l2_control ctrl; int err = 0; u8 i; @@ -1896,7 +1918,7 @@ exit: static int sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) { - struct sn9c102_sensor* s = cam->sensor; + struct sn9c102_sensor* s = &cam->sensor; struct v4l2_control ctrl; u8 i; int err = 0; @@ -1909,6 +1931,8 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) if (ctrl.id == s->qctrl[i].id) { + if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) + return -EINVAL; if (ctrl.value < s->qctrl[i].minimum || ctrl.value > s->qctrl[i].maximum) return -ERANGE; @@ -1931,7 +1955,7 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) static int sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg) { - struct v4l2_cropcap* cc = &(cam->sensor->cropcap); + struct v4l2_cropcap* cc = &(cam->sensor.cropcap); cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; cc->pixelaspect.numerator = 1; @@ -1947,7 +1971,7 @@ sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg) static int sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg) { - struct sn9c102_sensor* s = cam->sensor; + struct sn9c102_sensor* s = &cam->sensor; struct v4l2_crop crop = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, }; @@ -1964,7 +1988,7 @@ sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg) static int sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) { - struct sn9c102_sensor* s = cam->sensor; + struct sn9c102_sensor* s = &cam->sensor; struct v4l2_crop crop; struct v4l2_rect* rect; struct v4l2_rect* bounds = &(s->cropcap.bounds); @@ -2105,7 +2129,7 @@ static int sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) { struct v4l2_format format; - struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); + struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); if (copy_from_user(&format, arg, sizeof(format))) return -EFAULT; @@ -2130,7 +2154,7 @@ static int sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, void __user * arg) { - struct sn9c102_sensor* s = cam->sensor; + struct sn9c102_sensor* s = &cam->sensor; struct v4l2_format format; struct v4l2_pix_format* pix; struct v4l2_pix_format* pfmt = &(s->pix_format); @@ -2417,7 +2441,7 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, struct v4l2_buffer b; struct sn9c102_frame_t *f; unsigned long lock_flags; - int err = 0; + long timeout; if (copy_from_user(&b, arg, sizeof(b))) return -EFAULT; @@ -2430,16 +2454,18 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, return -EINVAL; if (filp->f_flags & O_NONBLOCK) return -EAGAIN; - err = wait_event_interruptible - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED) ); - if (err) - return err; + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) + return timeout; if (cam->state & DEV_DISCONNECTED) return -ENODEV; - if (cam->state & DEV_MISCONFIGURED) + if (!timeout || (cam->state & DEV_MISCONFIGURED)) return -EIO; } @@ -2571,8 +2597,10 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, return sn9c102_vidioc_enuminput(cam, arg); case VIDIOC_G_INPUT: + return sn9c102_vidioc_g_input(cam, arg); + case VIDIOC_S_INPUT: - return sn9c102_vidioc_gs_input(cam, arg); + return sn9c102_vidioc_s_input(cam, arg); case VIDIOC_QUERYCTRL: return sn9c102_vidioc_query_ctrl(cam, arg); @@ -2752,10 +2780,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) break; } - if (!err && cam->sensor) { - DBG(2, "%s image sensor detected", cam->sensor->name); + if (!err) { + DBG(2, "%s image sensor detected", cam->sensor.name); DBG(3, "Support for %s maintained by %s", - cam->sensor->name, cam->sensor->maintainer); + cam->sensor.name, cam->sensor.maintainer); } else { DBG(1, "No supported image sensor detected"); err = -ENODEV; @@ -2793,6 +2821,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); cam->module_param.force_munmap = force_munmap[dev_nr]; + cam->module_param.frame_timeout = frame_timeout[dev_nr]; dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; @@ -2841,7 +2870,8 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf) sn9c102_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; wake_up_interruptible(&cam->wait_frame); - wake_up_interruptible(&cam->wait_stream); + wake_up(&cam->wait_stream); + usb_get_dev(cam->usbdev); } else { cam->state |= DEV_DISCONNECTED; sn9c102_release_resources(cam); diff --git a/drivers/usb/media/sn9c102_ov7630.c b/drivers/usb/media/sn9c102_ov7630.c index 4a36519b5af4..42852b7cb042 100644 --- a/drivers/usb/media/sn9c102_ov7630.c +++ b/drivers/usb/media/sn9c102_ov7630.c @@ -34,8 +34,8 @@ static int ov7630_init(struct sn9c102_device* cam) err += sn9c102_write_reg(cam, 0x0f, 0x18); err += sn9c102_write_reg(cam, 0x50, 0x19); - err += sn9c102_i2c_write(cam, 0x12, 0x8d); - err += sn9c102_i2c_write(cam, 0x11, 0x00); + err += sn9c102_i2c_write(cam, 0x12, 0x80); + err += sn9c102_i2c_write(cam, 0x11, 0x01); err += sn9c102_i2c_write(cam, 0x15, 0x34); err += sn9c102_i2c_write(cam, 0x16, 0x03); err += sn9c102_i2c_write(cam, 0x17, 0x1c); @@ -43,12 +43,14 @@ static int ov7630_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x19, 0x06); err += sn9c102_i2c_write(cam, 0x1a, 0xf6); err += sn9c102_i2c_write(cam, 0x1b, 0x04); - err += sn9c102_i2c_write(cam, 0x20, 0x44); + err += sn9c102_i2c_write(cam, 0x20, 0xf6); err += sn9c102_i2c_write(cam, 0x23, 0xee); err += sn9c102_i2c_write(cam, 0x26, 0xa0); err += sn9c102_i2c_write(cam, 0x27, 0x9a); - err += sn9c102_i2c_write(cam, 0x28, 0x20); + err += sn9c102_i2c_write(cam, 0x28, 0xa0); err += sn9c102_i2c_write(cam, 0x29, 0x30); + err += sn9c102_i2c_write(cam, 0x2a, 0xa0); + err += sn9c102_i2c_write(cam, 0x2b, 0x1f); err += sn9c102_i2c_write(cam, 0x2f, 0x3d); err += sn9c102_i2c_write(cam, 0x30, 0x24); err += sn9c102_i2c_write(cam, 0x32, 0x86); @@ -80,7 +82,7 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam, err += sn9c102_i2c_write(cam, 0x02, ctrl->value); break; case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x03, ctrl->value); + err += sn9c102_i2c_write(cam, 0x01, ctrl->value); break; case V4L2_CID_GAIN: err += sn9c102_i2c_write(cam, 0x00, ctrl->value); @@ -108,7 +110,7 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam, err += sn9c102_i2c_write(cam, 0x0d, ctrl->value); break; case V4L2_CID_AUTO_WHITE_BALANCE: - err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x09); + err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78); break; case V4L2_CID_AUTOGAIN: err += sn9c102_i2c_write(cam, 0x13, ctrl->value); @@ -371,26 +373,29 @@ static struct sn9c102_sensor ov7630 = { int sn9c102_probe_ov7630(struct sn9c102_device* cam) { + const struct usb_device_id ov7630_id_table[] = { + { USB_DEVICE(0x0c45, 0x602c), }, + { USB_DEVICE(0x0c45, 0x602d), }, + { USB_DEVICE(0x0c45, 0x608f), }, + { USB_DEVICE(0x0c45, 0x60b0), }, + { } + }; int err = 0; - sn9c102_attach_sensor(cam, &ov7630); - - if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c && - le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602d && - le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f && - le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x60b0) + if (!sn9c102_match_id(cam, ov7630_id_table)) return -ENODEV; err += sn9c102_write_reg(cam, 0x01, 0x01); err += sn9c102_write_reg(cam, 0x00, 0x01); err += sn9c102_write_reg(cam, 0x28, 0x17); - if (err) return -EIO; - err += sn9c102_i2c_write(cam, 0x0b, 0); + err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0); if (err) return -ENODEV; + sn9c102_attach_sensor(cam, &ov7630); + return 0; } diff --git a/drivers/usb/media/sn9c102_pas202bca.c b/drivers/usb/media/sn9c102_pas202bca.c new file mode 100644 index 000000000000..3453237055bb --- /dev/null +++ b/drivers/usb/media/sn9c102_pas202bca.c @@ -0,0 +1,238 @@ +/*************************************************************************** + * Plug-in for PAS202BCA image sensor connected to the SN9C10x PC Camera * + * Controllers * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * 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 "sn9c102_sensor.h" + + +static struct sn9c102_sensor pas202bca; + + +static int pas202bca_init(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x00, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x11); + err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x20, 0x17); + err += sn9c102_write_reg(cam, 0x30, 0x19); + err += sn9c102_write_reg(cam, 0x09, 0x18); + + err += sn9c102_i2c_write(cam, 0x02, 0x14); + err += sn9c102_i2c_write(cam, 0x03, 0x40); + err += sn9c102_i2c_write(cam, 0x0d, 0x2c); + err += sn9c102_i2c_write(cam, 0x0e, 0x01); + err += sn9c102_i2c_write(cam, 0x0f, 0xa9); + err += sn9c102_i2c_write(cam, 0x10, 0x08); + err += sn9c102_i2c_write(cam, 0x13, 0x63); + err += sn9c102_i2c_write(cam, 0x15, 0x70); + err += sn9c102_i2c_write(cam, 0x11, 0x01); + + msleep(400); + + return err; +} + + +static int pas202bca_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, 0x24, 0x17); + else + err += sn9c102_write_reg(cam, 0x20, 0x17); + + return err; +} + + +static int pas202bca_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); + err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); + break; + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_write(cam, 0x09, ctrl->value); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_write(cam, 0x07, ctrl->value); + break; + case V4L2_CID_GAIN: + err += sn9c102_i2c_write(cam, 0x10, ctrl->value); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_write(cam, 0x08, ctrl->value); + break; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); + break; + default: + return -EINVAL; + } + err += sn9c102_i2c_write(cam, 0x11, 0x01); + + return err ? -EIO : 0; +} + + +static int pas202bca_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = &pas202bca; + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + + +static struct sn9c102_sensor pas202bca = { + .name = "PAS202BCA", + .maintainer = "Luca Risolia ", + .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x40, + .init = &pas202bca_init, + .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x01e5, + .maximum = 0x3fff, + .step = 0x0001, + .default_value = 0x01e5, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x0c, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x01, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x05, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "DAC magnitude", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = 0x04, + .flags = 0, + }, + }, + .set_ctrl = &pas202bca_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .set_crop = &pas202bca_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &pas202bca_set_pix_format +}; + + +int sn9c102_probe_pas202bca(struct sn9c102_device* cam) +{ + const struct usb_device_id pas202bca_id_table[] = { + { USB_DEVICE(0x0c45, 0x60af), }, + { } + }; + int err = 0; + + if (!sn9c102_match_id(cam,pas202bca_id_table)) + return -ENODEV; + + err += sn9c102_write_reg(cam, 0x01, 0x01); + err += sn9c102_write_reg(cam, 0x40, 0x01); + err += sn9c102_write_reg(cam, 0x28, 0x17); + if (err) + return -EIO; + + if (sn9c102_i2c_try_write(cam, &pas202bca, 0x10, 0)) /* try to write */ + return -ENODEV; + + sn9c102_attach_sensor(cam, &pas202bca); + + return 0; +} diff --git a/drivers/usb/media/sn9c102_pas202bcb.c b/drivers/usb/media/sn9c102_pas202bcb.c index 5ca54c7daaf2..d068616ab337 100644 --- a/drivers/usb/media/sn9c102_pas202bcb.c +++ b/drivers/usb/media/sn9c102_pas202bcb.c @@ -263,7 +263,7 @@ static struct sn9c102_sensor pas202bcb = { int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) -{ +{ int r0 = 0, r1 = 0, err = 0; unsigned int pid = 0; diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h index 7d953b24f2f2..2afd9e9d09bb 100644 --- a/drivers/usb/media/sn9c102_sensor.h +++ b/drivers/usb/media/sn9c102_sensor.h @@ -66,6 +66,7 @@ extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); +extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam); extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); @@ -81,12 +82,17 @@ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { \ &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \ &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \ &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \ + &sn9c102_probe_pas202bca, /* detection mostly based on USB pid/vid */ \ &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \ &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \ &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \ NULL, \ }; +/* Device identification */ +extern struct sn9c102_device* +sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); + /* Attach a probed sensor to the camera. */ extern void sn9c102_attach_sensor(struct sn9c102_device* cam, @@ -108,6 +114,7 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, static const struct usb_device_id sn9c102_id_table[] = { \ { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \ { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \ + { USB_DEVICE(0x0c45, 0x6007), }, \ { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \ { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \ { USB_DEVICE(0x0c45, 0x6024), }, \ @@ -126,7 +133,7 @@ static const struct usb_device_id sn9c102_id_table[] = { \ { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \ { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \ { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131x */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */ \ { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \ { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \ { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \ @@ -359,12 +366,6 @@ struct sn9c102_sensor { error code without rolling back. */ - const struct usb_device* usbdev; - /* - Points to the usb_device struct after the sensor is attached. - Do not touch unless you know what you are doing. - */ - /* Do NOT write to the data below, it's READ ONLY. It is used by the core module to store successfully updated values of the above diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c index 32ddf236cafe..2e08c552f40a 100644 --- a/drivers/usb/media/sn9c102_tas5110c1b.c +++ b/drivers/usb/media/sn9c102_tas5110c1b.c @@ -142,14 +142,18 @@ static struct sn9c102_sensor tas5110c1b = { int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) { - /* This sensor has no identifiers, so let's attach it anyway */ - sn9c102_attach_sensor(cam, &tas5110c1b); + const struct usb_device_id tas5110c1b_id_table[] = { + { USB_DEVICE(0x0c45, 0x6001), }, + { USB_DEVICE(0x0c45, 0x6005), }, + { USB_DEVICE(0x0c45, 0x60ab), }, + { } + }; /* Sensor detection is based on USB pid/vid */ - if (le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x6001 && - le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x6005 && - le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x60ab) + if (!sn9c102_match_id(cam, tas5110c1b_id_table)) return -ENODEV; + sn9c102_attach_sensor(cam, &tas5110c1b); + return 0; } diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c index a0728f0ae00c..c7b339740bbf 100644 --- a/drivers/usb/media/sn9c102_tas5130d1b.c +++ b/drivers/usb/media/sn9c102_tas5130d1b.c @@ -153,13 +153,17 @@ static struct sn9c102_sensor tas5130d1b = { int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) { - /* This sensor has no identifiers, so let's attach it anyway */ - sn9c102_attach_sensor(cam, &tas5130d1b); + const struct usb_device_id tas5130d1b_id_table[] = { + { USB_DEVICE(0x0c45, 0x6025), }, + { USB_DEVICE(0x0c45, 0x60aa), }, + { } + }; /* Sensor detection is based on USB pid/vid */ - if (le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x6025 && - le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x60aa) + if (!sn9c102_match_id(cam, tas5130d1b_id_table)) return -ENODEV; + sn9c102_attach_sensor(cam, &tas5130d1b); + return 0; } -- cgit v1.2.3-59-g8ed1b From ccad7789d5e557644d1c866b018394872af0ec5b Mon Sep 17 00:00:00 2001 From: Luca Risolia Date: Sat, 25 Feb 2006 06:54:18 +0000 Subject: [PATCH] USB: ET61X[12]51 driver updates USB: ET61X[12]51 driver updates Changes: + new, - removed, * cleanup, @ bugfix @ Fix stream_interrupt() @ Fix vidioc_enum_input() and split vidioc_gs_input() @ Need usb_get|put_dev() when disconnecting, if the device is open * Use wait_event_interruptible_timeout() instead of wait_event_interruptible() when waiting for video frames * replace wake_up_interruptible(&wait_stream) with wake_up(&wait_stream) * Cleanups and updates in the documentation * Use mutexes instead of semaphores + Use per-device sensor structures + Add support for PAS202BCA image sensors + Add frame_timeout module parameter Signed-off-by: Luca Risolia Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/et61x251.txt | 10 +- drivers/usb/media/et61x251.h | 28 ++- drivers/usb/media/et61x251_core.c | 321 +++++++++++++++++--------------- drivers/usb/media/et61x251_sensor.h | 5 +- drivers/usb/media/et61x251_tas5130d1b.c | 10 +- 5 files changed, 213 insertions(+), 161 deletions(-) (limited to 'drivers') diff --git a/Documentation/usb/et61x251.txt b/Documentation/usb/et61x251.txt index b44dda407ce2..29340282ab5f 100644 --- a/Documentation/usb/et61x251.txt +++ b/Documentation/usb/et61x251.txt @@ -176,6 +176,14 @@ Description: Force the application to unmap previously mapped buffer memory 1 = force memory unmapping (save memory) Default: 0 ------------------------------------------------------------------------------- +Name: frame_timeout +Type: uint array (min = 0, max = 64) +Syntax: +Description: Timeout for a video frame in seconds. This parameter is + specific for each detected camera. This parameter can be + changed at runtime thanks to the /sys filesystem interface. +Default: 2 +------------------------------------------------------------------------------- Name: debug Type: ushort Syntax: @@ -266,7 +274,7 @@ the V4L2 interface. 10. Notes for V4L2 application developers -======================================== +========================================= This driver follows the V4L2 API specifications. In particular, it enforces two rules: diff --git a/drivers/usb/media/et61x251.h b/drivers/usb/media/et61x251.h index 652238f329f3..eee8afc9be72 100644 --- a/drivers/usb/media/et61x251.h +++ b/drivers/usb/media/et61x251.h @@ -33,7 +33,9 @@ #include #include #include -#include +#include +#include +#include #include "et61x251_sensor.h" @@ -51,6 +53,7 @@ #define ET61X251_ALTERNATE_SETTING 13 #define ET61X251_URB_TIMEOUT msecs_to_jiffies(2 * ET61X251_ISO_PACKETS) #define ET61X251_CTRL_TIMEOUT 100 +#define ET61X251_FRAME_TIMEOUT 2 /*****************************************************************************/ @@ -127,15 +130,16 @@ struct et61x251_sysfs_attr { struct et61x251_module_param { u8 force_munmap; + u16 frame_timeout; }; -static DECLARE_MUTEX(et61x251_sysfs_lock); +static DEFINE_MUTEX(et61x251_sysfs_lock); static DECLARE_RWSEM(et61x251_disconnect); struct et61x251_device { struct video_device* v4ldev; - struct et61x251_sensor* sensor; + struct et61x251_sensor sensor; struct usb_device* usbdev; struct urb* urb[ET61X251_URBS]; @@ -157,19 +161,28 @@ struct et61x251_device { enum et61x251_dev_state state; u8 users; - struct semaphore dev_sem, fileop_sem; + struct mutex dev_mutex, fileop_mutex; spinlock_t queue_lock; wait_queue_head_t open, wait_frame, wait_stream; }; /*****************************************************************************/ +struct et61x251_device* +et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) +{ + if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) + return cam; + + return NULL; +} + + void et61x251_attach_sensor(struct et61x251_device* cam, struct et61x251_sensor* sensor) { - cam->sensor = sensor; - cam->sensor->usbdev = cam->usbdev; + memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor)); } /*****************************************************************************/ @@ -212,7 +225,8 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args) +dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args) #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ diff --git a/drivers/usb/media/et61x251_core.c b/drivers/usb/media/et61x251_core.c index 2c0171a5ad62..7cc01b828b3d 100644 --- a/drivers/usb/media/et61x251_core.c +++ b/drivers/usb/media/et61x251_core.c @@ -25,11 +25,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -50,8 +48,8 @@ #define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" #define ET61X251_AUTHOR_EMAIL "" #define ET61X251_MODULE_LICENSE "GPL" -#define ET61X251_MODULE_VERSION "1:1.01" -#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1) +#define ET61X251_MODULE_VERSION "1:1.02" +#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2) /*****************************************************************************/ @@ -90,6 +88,16 @@ MODULE_PARM_DESC(force_munmap, "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." "\n"); +static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] = + ET61X251_FRAME_TIMEOUT}; +module_param_array(frame_timeout, uint, NULL, 0644); +MODULE_PARM_DESC(frame_timeout, + "\n Timeout for a video frame in seconds." + "\nThis parameter is specific for each detected camera." + "\nDefault value is " + __MODULE_STRING(ET61X251_FRAME_TIMEOUT)"." + "\n"); + #ifdef ET61X251_DEBUG static unsigned short debug = ET61X251_DEBUG_LEVEL; module_param(debug, ushort, 0644); @@ -111,8 +119,8 @@ static u32 et61x251_request_buffers(struct et61x251_device* cam, u32 count, enum et61x251_io_method io) { - struct v4l2_pix_format* p = &(cam->sensor->pix_format); - struct v4l2_rect* r = &(cam->sensor->cropcap.bounds); + struct v4l2_pix_format* p = &(cam->sensor.pix_format); + struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); const size_t imagesize = cam->module_param.force_munmap || io == IO_READ ? (p->width * p->height * p->priv) / 8 : @@ -268,8 +276,8 @@ et61x251_i2c_try_read(struct et61x251_device* cam, int err = 0, res; data[0] = address; - data[1] = cam->sensor->i2c_slave_id; - data[2] = cam->sensor->rsta | 0x10; + data[1] = cam->sensor.i2c_slave_id; + data[2] = cam->sensor.rsta | 0x10; data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02); res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); @@ -301,8 +309,8 @@ et61x251_i2c_try_write(struct et61x251_device* cam, int err = 0, res; data[0] = address; - data[1] = cam->sensor->i2c_slave_id; - data[2] = cam->sensor->rsta | 0x12; + data[1] = cam->sensor.i2c_slave_id; + data[2] = cam->sensor.rsta | 0x12; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); if (res < 0) @@ -334,9 +342,6 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, u8* data = cam->control_buffer; int err = 0, res; - if (!cam->sensor) - return -1; - data[0] = data2; data[1] = data3; data[2] = data4; @@ -350,8 +355,8 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, err += res; data[0] = address; - data[1] = cam->sensor->i2c_slave_id; - data[2] = cam->sensor->rsta | 0x02 | (n << 4); + data[1] = cam->sensor.i2c_slave_id; + data[2] = cam->sensor.rsta | 0x02 | (n << 4); res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); if (res < 0) @@ -364,11 +369,11 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, if (res < 0) err += res; - err += et61x251_i2c_wait(cam, cam->sensor); + err += et61x251_i2c_wait(cam, &cam->sensor); if (err) DBG(3, "I2C raw write failed for %s image sensor", - cam->sensor->name); + cam->sensor.name); PDBGG("I2C raw write: %u bytes, address = 0x%02X, data1 = 0x%02X, " "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X," @@ -382,19 +387,13 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, int et61x251_i2c_read(struct et61x251_device* cam, u8 address) { - if (!cam->sensor) - return -1; - - return et61x251_i2c_try_read(cam, cam->sensor, address); + return et61x251_i2c_try_read(cam, &cam->sensor, address); } int et61x251_i2c_write(struct et61x251_device* cam, u8 address, u8 value) { - if (!cam->sensor) - return -1; - - return et61x251_i2c_try_write(cam, cam->sensor, address, value); + return et61x251_i2c_try_write(cam, &cam->sensor, address, value); } /*****************************************************************************/ @@ -417,7 +416,7 @@ static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs) if ((*f)) (*f)->state = F_QUEUED; DBG(3, "Stream interrupted"); - wake_up_interruptible(&cam->wait_stream); + wake_up(&cam->wait_stream); } if (cam->state & DEV_DISCONNECTED) @@ -435,9 +434,9 @@ static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs) (*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t, frame); - imagesize = (cam->sensor->pix_format.width * - cam->sensor->pix_format.height * - cam->sensor->pix_format.priv) / 8; + imagesize = (cam->sensor.pix_format.width * + cam->sensor.pix_format.height * + cam->sensor.pix_format.priv) / 8; for (i = 0; i < urb->number_of_packets; i++) { unsigned int len, status; @@ -476,7 +475,7 @@ start_of_frame: if ((*f)->state == F_GRABBING) { if (sof && (*f)->buf.bytesused) { - if (cam->sensor->pix_format.pixelformat == + if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_ET61X251) goto end_of_frame; else { @@ -521,7 +520,7 @@ end_of_frame: goto resubmit_urb; if (sof && - cam->sensor->pix_format.pixelformat == + cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_ET61X251) goto start_of_frame; } @@ -650,21 +649,21 @@ static int et61x251_stop_transfer(struct et61x251_device* cam) static int et61x251_stream_interrupt(struct et61x251_device* cam) { - int err = 0; + long timeout; cam->stream = STREAM_INTERRUPT; - err = wait_event_timeout(cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED), - ET61X251_URB_TIMEOUT); + timeout = wait_event_timeout(cam->wait_stream, + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + ET61X251_URB_TIMEOUT); if (cam->state & DEV_DISCONNECTED) return -ENODEV; - else if (err) { + else if (cam->stream != STREAM_OFF) { cam->state |= DEV_MISCONFIGURED; DBG(1, "URB timeout reached. The camera is misconfigured. To " "use it, close and open /dev/video%d again.", cam->v4ldev->minor); - return err; + return -EIO; } return 0; @@ -709,18 +708,18 @@ static ssize_t et61x251_show_reg(struct class_device* cd, char* buf) struct et61x251_device* cam; ssize_t count; - if (down_interruptible(&et61x251_sysfs_lock)) + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } count = sprintf(buf, "%u\n", cam->sysfs.reg); - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return count; } @@ -733,18 +732,18 @@ et61x251_store_reg(struct class_device* cd, const char* buf, size_t len) u8 index; ssize_t count; - if (down_interruptible(&et61x251_sysfs_lock)) + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } index = et61x251_strtou8(buf, len, &count); if (index > 0x8e || !count) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -EINVAL; } @@ -753,7 +752,7 @@ et61x251_store_reg(struct class_device* cd, const char* buf, size_t len) DBG(2, "Moved ET61X[12]51 register index to 0x%02X", cam->sysfs.reg); DBG(3, "Written bytes: %zd", count); - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return count; } @@ -765,17 +764,17 @@ static ssize_t et61x251_show_val(struct class_device* cd, char* buf) ssize_t count; int val; - if (down_interruptible(&et61x251_sysfs_lock)) + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } if ((val = et61x251_read_reg(cam, cam->sysfs.reg)) < 0) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -EIO; } @@ -783,7 +782,7 @@ static ssize_t et61x251_show_val(struct class_device* cd, char* buf) DBG(3, "Read bytes: %zd", count); - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return count; } @@ -797,24 +796,24 @@ et61x251_store_val(struct class_device* cd, const char* buf, size_t len) ssize_t count; int err; - if (down_interruptible(&et61x251_sysfs_lock)) + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } value = et61x251_strtou8(buf, len, &count); if (!count) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -EINVAL; } err = et61x251_write_reg(cam, value, cam->sysfs.reg); if (err) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -EIO; } @@ -822,7 +821,7 @@ et61x251_store_val(struct class_device* cd, const char* buf, size_t len) cam->sysfs.reg, value); DBG(3, "Written bytes: %zd", count); - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return count; } @@ -833,12 +832,12 @@ static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf) struct et61x251_device* cam; ssize_t count; - if (down_interruptible(&et61x251_sysfs_lock)) + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } @@ -846,7 +845,7 @@ static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf) DBG(3, "Read bytes: %zd", count); - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return count; } @@ -859,18 +858,18 @@ et61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) u8 index; ssize_t count; - if (down_interruptible(&et61x251_sysfs_lock)) + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } index = et61x251_strtou8(buf, len, &count); if (!count) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -EINVAL; } @@ -879,7 +878,7 @@ et61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); DBG(3, "Written bytes: %zd", count); - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return count; } @@ -891,22 +890,22 @@ static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf) ssize_t count; int val; - if (down_interruptible(&et61x251_sysfs_lock)) + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } - if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) { - up(&et61x251_sysfs_lock); + if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) { + mutex_unlock(&et61x251_sysfs_lock); return -ENOSYS; } if ((val = et61x251_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -EIO; } @@ -914,7 +913,7 @@ static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf) DBG(3, "Read bytes: %zd", count); - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return count; } @@ -928,29 +927,29 @@ et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len) ssize_t count; int err; - if (down_interruptible(&et61x251_sysfs_lock)) + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } - if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) { - up(&et61x251_sysfs_lock); + if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) { + mutex_unlock(&et61x251_sysfs_lock); return -ENOSYS; } value = et61x251_strtou8(buf, len, &count); if (!count) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -EINVAL; } err = et61x251_i2c_write(cam, cam->sysfs.i2c_reg, value); if (err) { - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return -EIO; } @@ -958,7 +957,7 @@ et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len) cam->sysfs.i2c_reg, value); DBG(3, "Written bytes: %zd", count); - up(&et61x251_sysfs_lock); + mutex_unlock(&et61x251_sysfs_lock); return count; } @@ -980,7 +979,7 @@ static void et61x251_create_sysfs(struct et61x251_device* cam) video_device_create_file(v4ldev, &class_device_attr_reg); video_device_create_file(v4ldev, &class_device_attr_val); - if (cam->sensor && cam->sensor->sysfs_ops) { + if (cam->sensor.sysfs_ops) { video_device_create_file(v4ldev, &class_device_attr_i2c_reg); video_device_create_file(v4ldev, &class_device_attr_i2c_val); } @@ -1048,7 +1047,7 @@ static int et61x251_set_scale(struct et61x251_device* cam, u8 scale) static int et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect) { - struct et61x251_sensor* s = cam->sensor; + struct et61x251_sensor* s = &cam->sensor; u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left + s->active_pixel.left), fmw_sy = (u16)(rect->top - s->cropcap.bounds.top + @@ -1076,7 +1075,7 @@ et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect) static int et61x251_init(struct et61x251_device* cam) { - struct et61x251_sensor* s = cam->sensor; + struct et61x251_sensor* s = &cam->sensor; struct v4l2_control ctrl; struct v4l2_queryctrl *qctrl; struct v4l2_rect* rect; @@ -1143,7 +1142,7 @@ static int et61x251_init(struct et61x251_device* cam) } if (!(cam->state & DEV_INITIALIZED)) { - init_MUTEX(&cam->fileop_sem); + mutex_init(&cam->fileop_mutex); spin_lock_init(&cam->queue_lock); init_waitqueue_head(&cam->wait_frame); init_waitqueue_head(&cam->wait_stream); @@ -1161,13 +1160,15 @@ static int et61x251_init(struct et61x251_device* cam) static void et61x251_release_resources(struct et61x251_device* cam) { - down(&et61x251_sysfs_lock); + mutex_lock(&et61x251_sysfs_lock); DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); - up(&et61x251_sysfs_lock); + usb_put_dev(cam->usbdev); + + mutex_unlock(&et61x251_sysfs_lock); kfree(cam->control_buffer); } @@ -1188,7 +1189,7 @@ static int et61x251_open(struct inode* inode, struct file* filp) cam = video_get_drvdata(video_devdata(filp)); - if (down_interruptible(&cam->dev_sem)) { + if (mutex_lock_interruptible(&cam->dev_mutex)) { up_read(&et61x251_disconnect); return -ERESTARTSYS; } @@ -1200,7 +1201,7 @@ static int et61x251_open(struct inode* inode, struct file* filp) err = -EWOULDBLOCK; goto out; } - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); err = wait_event_interruptible_exclusive(cam->open, cam->state & DEV_DISCONNECTED || !cam->users); @@ -1212,7 +1213,7 @@ static int et61x251_open(struct inode* inode, struct file* filp) up_read(&et61x251_disconnect); return -ENODEV; } - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); } @@ -1240,7 +1241,7 @@ static int et61x251_open(struct inode* inode, struct file* filp) DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); out: - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); up_read(&et61x251_disconnect); return err; } @@ -1250,7 +1251,7 @@ static int et61x251_release(struct inode* inode, struct file* filp) { struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); - down(&cam->dev_sem); /* prevent disconnect() to be called */ + mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ et61x251_stop_transfer(cam); @@ -1258,7 +1259,7 @@ static int et61x251_release(struct inode* inode, struct file* filp) if (cam->state & DEV_DISCONNECTED) { et61x251_release_resources(cam); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); kfree(cam); return 0; } @@ -1268,7 +1269,7 @@ static int et61x251_release(struct inode* inode, struct file* filp) DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); return 0; } @@ -1281,28 +1282,29 @@ et61x251_read(struct file* filp, char __user * buf, struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); struct et61x251_frame_t* f, * i; unsigned long lock_flags; + long timeout; int err = 0; - if (down_interruptible(&cam->fileop_sem)) + if (mutex_lock_interruptible(&cam->fileop_mutex)) return -ERESTARTSYS; if (cam->state & DEV_DISCONNECTED) { DBG(1, "Device not present"); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENODEV; } if (cam->state & DEV_MISCONFIGURED) { DBG(1, "The camera is misconfigured. Close and open it " "again."); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EIO; } if (cam->io == IO_MMAP) { DBG(3, "Close and open the device again to choose the read " "method"); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EINVAL; } @@ -1310,7 +1312,7 @@ et61x251_read(struct file* filp, char __user * buf, if (!et61x251_request_buffers(cam, cam->nreadbuffers, IO_READ)) { DBG(1, "read() failed, not enough memory"); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENOMEM; } cam->io = IO_READ; @@ -1324,30 +1326,32 @@ et61x251_read(struct file* filp, char __user * buf, } if (!count) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return 0; } if (list_empty(&cam->outqueue)) { if (filp->f_flags & O_NONBLOCK) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EAGAIN; } - err = wait_event_interruptible - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED) ); - if (err) { - up(&cam->fileop_sem); - return err; + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) { + mutex_unlock(&cam->fileop_mutex); + return timeout; } if (cam->state & DEV_DISCONNECTED) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENODEV; } - if (cam->state & DEV_MISCONFIGURED) { - up(&cam->fileop_sem); + if (!timeout || (cam->state & DEV_MISCONFIGURED)) { + mutex_unlock(&cam->fileop_mutex); return -EIO; } } @@ -1375,7 +1379,7 @@ exit: PDBGG("Frame #%lu, bytes read: %zu", (unsigned long)f->buf.index, count); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return err ? err : count; } @@ -1388,7 +1392,7 @@ static unsigned int et61x251_poll(struct file *filp, poll_table *wait) unsigned long lock_flags; unsigned int mask = 0; - if (down_interruptible(&cam->fileop_sem)) + if (mutex_lock_interruptible(&cam->fileop_mutex)) return POLLERR; if (cam->state & DEV_DISCONNECTED) { @@ -1426,12 +1430,12 @@ static unsigned int et61x251_poll(struct file *filp, poll_table *wait) if (!list_empty(&cam->outqueue)) mask |= POLLIN | POLLRDNORM; - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return mask; error: - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return POLLERR; } @@ -1465,25 +1469,25 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) void *pos; u32 i; - if (down_interruptible(&cam->fileop_sem)) + if (mutex_lock_interruptible(&cam->fileop_mutex)) return -ERESTARTSYS; if (cam->state & DEV_DISCONNECTED) { DBG(1, "Device not present"); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENODEV; } if (cam->state & DEV_MISCONFIGURED) { DBG(1, "The camera is misconfigured. Close and open it " "again."); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EIO; } if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || size != PAGE_ALIGN(cam->frame[0].buf.length)) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EINVAL; } @@ -1492,7 +1496,7 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) break; } if (i == cam->nbuffers) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EINVAL; } @@ -1502,7 +1506,7 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) pos = cam->frame[i].bufmem; while (size > 0) { /* size is page-aligned */ if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EAGAIN; } start += PAGE_SIZE; @@ -1515,7 +1519,7 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) et61x251_vm_open(vma); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return 0; } @@ -1557,6 +1561,7 @@ et61x251_vidioc_enuminput(struct et61x251_device* cam, void __user * arg) memset(&i, 0, sizeof(i)); strcpy(i.name, "Camera"); + i.type = V4L2_INPUT_TYPE_CAMERA; if (copy_to_user(arg, &i, sizeof(i))) return -EFAULT; @@ -1566,7 +1571,19 @@ et61x251_vidioc_enuminput(struct et61x251_device* cam, void __user * arg) static int -et61x251_vidioc_gs_input(struct et61x251_device* cam, void __user * arg) +et61x251_vidioc_g_input(struct et61x251_device* cam, void __user * arg) +{ + int index = 0; + + if (copy_to_user(arg, &index, sizeof(index))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_s_input(struct et61x251_device* cam, void __user * arg) { int index; @@ -1583,7 +1600,7 @@ et61x251_vidioc_gs_input(struct et61x251_device* cam, void __user * arg) static int et61x251_vidioc_query_ctrl(struct et61x251_device* cam, void __user * arg) { - struct et61x251_sensor* s = cam->sensor; + struct et61x251_sensor* s = &cam->sensor; struct v4l2_queryctrl qc; u8 i; @@ -1605,7 +1622,7 @@ et61x251_vidioc_query_ctrl(struct et61x251_device* cam, void __user * arg) static int et61x251_vidioc_g_ctrl(struct et61x251_device* cam, void __user * arg) { - struct et61x251_sensor* s = cam->sensor; + struct et61x251_sensor* s = &cam->sensor; struct v4l2_control ctrl; int err = 0; u8 i; @@ -1637,7 +1654,7 @@ exit: static int et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg) { - struct et61x251_sensor* s = cam->sensor; + struct et61x251_sensor* s = &cam->sensor; struct v4l2_control ctrl; u8 i; int err = 0; @@ -1650,6 +1667,8 @@ et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg) for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) if (ctrl.id == s->qctrl[i].id) { + if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) + return -EINVAL; if (ctrl.value < s->qctrl[i].minimum || ctrl.value > s->qctrl[i].maximum) return -ERANGE; @@ -1669,7 +1688,7 @@ et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg) static int et61x251_vidioc_cropcap(struct et61x251_device* cam, void __user * arg) { - struct v4l2_cropcap* cc = &(cam->sensor->cropcap); + struct v4l2_cropcap* cc = &(cam->sensor.cropcap); cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; cc->pixelaspect.numerator = 1; @@ -1685,7 +1704,7 @@ et61x251_vidioc_cropcap(struct et61x251_device* cam, void __user * arg) static int et61x251_vidioc_g_crop(struct et61x251_device* cam, void __user * arg) { - struct et61x251_sensor* s = cam->sensor; + struct et61x251_sensor* s = &cam->sensor; struct v4l2_crop crop = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, }; @@ -1702,7 +1721,7 @@ et61x251_vidioc_g_crop(struct et61x251_device* cam, void __user * arg) static int et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) { - struct et61x251_sensor* s = cam->sensor; + struct et61x251_sensor* s = &cam->sensor; struct v4l2_crop crop; struct v4l2_rect* rect; struct v4l2_rect* bounds = &(s->cropcap.bounds); @@ -1843,7 +1862,7 @@ static int et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg) { struct v4l2_format format; - struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); + struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); if (copy_from_user(&format, arg, sizeof(format))) return -EFAULT; @@ -1868,7 +1887,7 @@ static int et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, void __user * arg) { - struct et61x251_sensor* s = cam->sensor; + struct et61x251_sensor* s = &cam->sensor; struct v4l2_format format; struct v4l2_pix_format* pix; struct v4l2_pix_format* pfmt = &(s->pix_format); @@ -2155,7 +2174,7 @@ et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp, struct v4l2_buffer b; struct et61x251_frame_t *f; unsigned long lock_flags; - int err = 0; + long timeout; if (copy_from_user(&b, arg, sizeof(b))) return -EFAULT; @@ -2168,16 +2187,18 @@ et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp, return -EINVAL; if (filp->f_flags & O_NONBLOCK) return -EAGAIN; - err = wait_event_interruptible - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED) ); - if (err) - return err; + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) + return timeout; if (cam->state & DEV_DISCONNECTED) return -ENODEV; - if (cam->state & DEV_MISCONFIGURED) + if (!timeout || (cam->state & DEV_MISCONFIGURED)) return -EIO; } @@ -2309,8 +2330,10 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, return et61x251_vidioc_enuminput(cam, arg); case VIDIOC_G_INPUT: + return et61x251_vidioc_g_input(cam, arg); + case VIDIOC_S_INPUT: - return et61x251_vidioc_gs_input(cam, arg); + return et61x251_vidioc_s_input(cam, arg); case VIDIOC_QUERYCTRL: return et61x251_vidioc_query_ctrl(cam, arg); @@ -2393,19 +2416,19 @@ static int et61x251_ioctl(struct inode* inode, struct file* filp, struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); int err = 0; - if (down_interruptible(&cam->fileop_sem)) + if (mutex_lock_interruptible(&cam->fileop_mutex)) return -ERESTARTSYS; if (cam->state & DEV_DISCONNECTED) { DBG(1, "Device not present"); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -ENODEV; } if (cam->state & DEV_MISCONFIGURED) { DBG(1, "The camera is misconfigured. Close and open it " "again."); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EIO; } @@ -2413,7 +2436,7 @@ static int et61x251_ioctl(struct inode* inode, struct file* filp, err = et61x251_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return err; } @@ -2459,7 +2482,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - init_MUTEX(&cam->dev_sem); + mutex_init(&cam->dev_mutex); DBG(2, "ET61X[12]51 PC Camera Controller detected " "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); @@ -2470,8 +2493,8 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) break; } - if (!err && cam->sensor) - DBG(2, "%s image sensor detected", cam->sensor->name); + if (!err) + DBG(2, "%s image sensor detected", cam->sensor.name); else { DBG(1, "No supported image sensor detected"); err = -ENODEV; @@ -2492,7 +2515,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->v4ldev->release = video_device_release; video_set_drvdata(cam->v4ldev, cam); - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, video_nr[dev_nr]); @@ -2502,13 +2525,14 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) DBG(1, "Free /dev/videoX node not found"); video_nr[dev_nr] = -1; dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); goto fail; } DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); cam->module_param.force_munmap = force_munmap[dev_nr]; + cam->module_param.frame_timeout = frame_timeout[dev_nr]; dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; @@ -2519,7 +2543,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) usb_set_intfdata(intf, cam); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); return 0; @@ -2543,7 +2567,7 @@ static void et61x251_usb_disconnect(struct usb_interface* intf) down_write(&et61x251_disconnect); - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); DBG(2, "Disconnecting %s...", cam->v4ldev->name); @@ -2557,13 +2581,14 @@ static void et61x251_usb_disconnect(struct usb_interface* intf) et61x251_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; wake_up_interruptible(&cam->wait_frame); - wake_up_interruptible(&cam->wait_stream); + wake_up(&cam->wait_stream); + usb_get_dev(cam->usbdev); } else { cam->state |= DEV_DISCONNECTED; et61x251_release_resources(cam); } - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); if (!cam->users) kfree(cam); diff --git a/drivers/usb/media/et61x251_sensor.h b/drivers/usb/media/et61x251_sensor.h index b9df91062fc0..56841ae8a207 100644 --- a/drivers/usb/media/et61x251_sensor.h +++ b/drivers/usb/media/et61x251_sensor.h @@ -42,6 +42,9 @@ static int (*et61x251_sensor_table[])(struct et61x251_device*) = { \ NULL, \ }; +extern struct et61x251_device* +et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id); + extern void et61x251_attach_sensor(struct et61x251_device* cam, struct et61x251_sensor* sensor); @@ -105,8 +108,6 @@ struct et61x251_sensor { int (*set_pix_format)(struct et61x251_device* cam, const struct v4l2_pix_format* pix); - const struct usb_device* usbdev; - /* Private */ struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS]; struct v4l2_rect _rect; diff --git a/drivers/usb/media/et61x251_tas5130d1b.c b/drivers/usb/media/et61x251_tas5130d1b.c index 65f1ae9cf2b3..3998d76a307a 100644 --- a/drivers/usb/media/et61x251_tas5130d1b.c +++ b/drivers/usb/media/et61x251_tas5130d1b.c @@ -126,12 +126,16 @@ static struct et61x251_sensor tas5130d1b = { int et61x251_probe_tas5130d1b(struct et61x251_device* cam) { - /* This sensor has no identifiers, so let's attach it anyway */ - et61x251_attach_sensor(cam, &tas5130d1b); + const struct usb_device_id tas5130d1b_id_table[] = { + { USB_DEVICE(0x102c, 0x6251), }, + { } + }; /* Sensor detection is based on USB pid/vid */ - if (le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x6251) + if (!et61x251_match_id(cam, tas5130d1b_id_table)) return -ENODEV; + et61x251_attach_sensor(cam, &tas5130d1b); + return 0; } -- cgit v1.2.3-59-g8ed1b From a847423905c6a8ccd6671d05f5877d893d10cd9f Mon Sep 17 00:00:00 2001 From: Luca Risolia Date: Sat, 25 Feb 2006 06:57:49 +0000 Subject: [PATCH] USB: ZC0301 driver updates ZC0301 driver updates. Changes: + new, - removed, * cleanup, @ bugfix @ Need usb_get|put_dev() when disconnecting, if the device is open * Cleanups and updates in the documentation + Use per-device sensor structures + Add frame_timeout module parameter Signed-off-by: Luca Risolia Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/zc0301.txt | 29 +++++++++++------- drivers/usb/media/zc0301.h | 20 +++++++++---- drivers/usb/media/zc0301_core.c | 58 ++++++++++++++++++++++-------------- drivers/usb/media/zc0301_pas202bcb.c | 38 +++++++++++++---------- drivers/usb/media/zc0301_sensor.h | 25 +++++++++------- 5 files changed, 108 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/Documentation/usb/zc0301.txt b/Documentation/usb/zc0301.txt index 0889ae6ac7d8..095838420e82 100644 --- a/Documentation/usb/zc0301.txt +++ b/Documentation/usb/zc0301.txt @@ -68,11 +68,6 @@ Some of the features of the driver are: data transfers; - automatic detection of image sensor; - video format is standard JPEG; -- full support for the capabilities of every possible image sensors that can - be connected to the ZC0301 bridges, including, for istance, red, green, - blue and global gain adjustments and exposure control (see "Supported - devices" paragraph for details); -- use of default color settings for sunlight conditions; - dynamic driver control thanks to various module parameters (see "Module parameters" paragraph); - up to 64 cameras can be handled at the same time; they can be connected and @@ -171,6 +166,14 @@ Description: Force the application to unmap previously mapped buffer memory 1 = force memory unmapping (save memory) Default: 0 ------------------------------------------------------------------------------- +Name: frame_timeout +Type: uint array (min = 0, max = 64) +Syntax: +Description: Timeout for a video frame in seconds. This parameter is + specific for each detected camera. This parameter can be + changed at runtime thanks to the /sys filesystem interface. +Default: 2 +------------------------------------------------------------------------------- Name: debug Type: ushort Syntax: @@ -198,17 +201,23 @@ devices mounting the ZC0301 Image Processor and Control Chips: Vendor ID Product ID --------- ---------- +0x10fd 0x8050 +0x041e 0x0417 +0x041e 0x041e +0x041e 0x081c +0x041e 0x0834 +0x041e 0x0835 0x046d 0x08ae +0x0ac8 0x0301 -The following image sensors are supported: +The list above does not imply that all those devices work with this driver: up +until now only the ones that mount the following image sensors are supported; +kernel messages will always tell you whether this is the case: Model Manufacturer ----- ------------ PAS202BCB PixArt Imaging, Inc. -All the available control settings of each image sensor are supported through -the V4L2 interface. - 9. Notes for V4L2 application developers ======================================== @@ -240,6 +249,6 @@ the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'. - Informations about the chip internals needed to enable the I2C protocol have been taken from the documentation of the ZC030x Video4Linux1 driver written by Andrew Birkett ; -- Initialization values of the ZC0301 controller connected to the PAS202BCB +- The initialization values of the ZC0301 controller connected to the PAS202BCB image sensor have been taken from the SPCA5XX driver maintained by Michel Xhaard . diff --git a/drivers/usb/media/zc0301.h b/drivers/usb/media/zc0301.h index cb1a0823bc63..9ba9135e824b 100644 --- a/drivers/usb/media/zc0301.h +++ b/drivers/usb/media/zc0301.h @@ -34,7 +34,8 @@ #include #include #include -#include +#include +#include #include "zc0301_sensor.h" @@ -51,7 +52,7 @@ #define ZC0301_ALTERNATE_SETTING 7 #define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS) #define ZC0301_CTRL_TIMEOUT 100 -#define ZC0301_FRAME_TIMEOUT 2 * 1000 * msecs_to_jiffies(1) +#define ZC0301_FRAME_TIMEOUT 2 /*****************************************************************************/ @@ -94,6 +95,7 @@ enum zc0301_stream_state { struct zc0301_module_param { u8 force_munmap; + u16 frame_timeout; }; static DECLARE_RWSEM(zc0301_disconnect); @@ -101,7 +103,7 @@ static DECLARE_RWSEM(zc0301_disconnect); struct zc0301_device { struct video_device* v4ldev; - struct zc0301_sensor* sensor; + struct zc0301_sensor sensor; struct usb_device* usbdev; struct urb* urb[ZC0301_URBS]; @@ -129,11 +131,19 @@ struct zc0301_device { /*****************************************************************************/ +struct zc0301_device* +zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id) +{ + if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) + return cam; + + return NULL; +} + void zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor) { - cam->sensor = sensor; - cam->sensor->usbdev = cam->usbdev; + memcpy(&cam->sensor, sensor, sizeof(struct zc0301_sensor)); } /*****************************************************************************/ diff --git a/drivers/usb/media/zc0301_core.c b/drivers/usb/media/zc0301_core.c index 7e8b1676d144..5773688d3dae 100644 --- a/drivers/usb/media/zc0301_core.c +++ b/drivers/usb/media/zc0301_core.c @@ -29,11 +29,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -54,8 +52,8 @@ #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" #define ZC0301_AUTHOR_EMAIL "" #define ZC0301_MODULE_LICENSE "GPL" -#define ZC0301_MODULE_VERSION "1:1.01" -#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1) +#define ZC0301_MODULE_VERSION "1:1.02" +#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2) /*****************************************************************************/ @@ -94,6 +92,15 @@ MODULE_PARM_DESC(force_munmap, "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." "\n"); +static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] = + ZC0301_FRAME_TIMEOUT}; +module_param_array(frame_timeout, uint, NULL, 0644); +MODULE_PARM_DESC(frame_timeout, + "\n Timeout for a video frame in seconds." + "\nThis parameter is specific for each detected camera." + "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"." + "\n"); + #ifdef ZC0301_DEBUG static unsigned short debug = ZC0301_DEBUG_LEVEL; module_param(debug, ushort, 0644); @@ -115,8 +122,8 @@ static u32 zc0301_request_buffers(struct zc0301_device* cam, u32 count, enum zc0301_io_method io) { - struct v4l2_pix_format* p = &(cam->sensor->pix_format); - struct v4l2_rect* r = &(cam->sensor->cropcap.bounds); + struct v4l2_pix_format* p = &(cam->sensor.pix_format); + struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); const size_t imagesize = cam->module_param.force_munmap || io == IO_READ ? (p->width * p->height * p->priv) / 8 : @@ -332,9 +339,9 @@ static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs) (*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t, frame); - imagesize = (cam->sensor->pix_format.width * - cam->sensor->pix_format.height * - cam->sensor->pix_format.priv) / 8; + imagesize = (cam->sensor.pix_format.width * + cam->sensor.pix_format.height * + cam->sensor.pix_format.priv) / 8; for (i = 0; i < urb->number_of_packets; i++) { unsigned int len, status; @@ -555,7 +562,7 @@ zc0301_set_compression(struct zc0301_device* cam, static int zc0301_init(struct zc0301_device* cam) { - struct zc0301_sensor* s = cam->sensor; + struct zc0301_sensor* s = &cam->sensor; struct v4l2_control ctrl; struct v4l2_queryctrl *qctrl; struct v4l2_rect* rect; @@ -630,6 +637,7 @@ static void zc0301_release_resources(struct zc0301_device* cam) DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); + usb_put_dev(cam->usbdev); kfree(cam->control_buffer); } @@ -798,7 +806,8 @@ zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) (!list_empty(&cam->outqueue)) || (cam->state & DEV_DISCONNECTED) || (cam->state & DEV_MISCONFIGURED), - ZC0301_FRAME_TIMEOUT ); + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); if (timeout < 0) { mutex_unlock(&cam->fileop_mutex); return timeout; @@ -1056,7 +1065,7 @@ zc0301_vidioc_s_input(struct zc0301_device* cam, void __user * arg) static int zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg) { - struct zc0301_sensor* s = cam->sensor; + struct zc0301_sensor* s = &cam->sensor; struct v4l2_queryctrl qc; u8 i; @@ -1078,7 +1087,7 @@ zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg) static int zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg) { - struct zc0301_sensor* s = cam->sensor; + struct zc0301_sensor* s = &cam->sensor; struct v4l2_control ctrl; int err = 0; u8 i; @@ -1110,7 +1119,7 @@ exit: static int zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) { - struct zc0301_sensor* s = cam->sensor; + struct zc0301_sensor* s = &cam->sensor; struct v4l2_control ctrl; u8 i; int err = 0; @@ -1123,6 +1132,8 @@ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) if (ctrl.id == s->qctrl[i].id) { + if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) + return -EINVAL; if (ctrl.value < s->qctrl[i].minimum || ctrl.value > s->qctrl[i].maximum) return -ERANGE; @@ -1142,7 +1153,7 @@ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) static int zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg) { - struct v4l2_cropcap* cc = &(cam->sensor->cropcap); + struct v4l2_cropcap* cc = &(cam->sensor.cropcap); cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; cc->pixelaspect.numerator = 1; @@ -1158,7 +1169,7 @@ zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg) static int zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg) { - struct zc0301_sensor* s = cam->sensor; + struct zc0301_sensor* s = &cam->sensor; struct v4l2_crop crop = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, }; @@ -1175,7 +1186,7 @@ zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg) static int zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) { - struct zc0301_sensor* s = cam->sensor; + struct zc0301_sensor* s = &cam->sensor; struct v4l2_crop crop; struct v4l2_rect* rect; struct v4l2_rect* bounds = &(s->cropcap.bounds); @@ -1304,7 +1315,7 @@ static int zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg) { struct v4l2_format format; - struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); + struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); if (copy_from_user(&format, arg, sizeof(format))) return -EFAULT; @@ -1328,7 +1339,7 @@ static int zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, void __user * arg) { - struct zc0301_sensor* s = cam->sensor; + struct zc0301_sensor* s = &cam->sensor; struct v4l2_format format; struct v4l2_pix_format* pix; struct v4l2_pix_format* pfmt = &(s->pix_format); @@ -1612,7 +1623,8 @@ zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp, (!list_empty(&cam->outqueue)) || (cam->state & DEV_DISCONNECTED) || (cam->state & DEV_MISCONFIGURED), - ZC0301_FRAME_TIMEOUT ); + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); if (timeout < 0) return timeout; if (cam->state & DEV_DISCONNECTED) @@ -1911,8 +1923,8 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) break; } - if (!err && cam->sensor) - DBG(2, "%s image sensor detected", cam->sensor->name); + if (!err) + DBG(2, "%s image sensor detected", cam->sensor.name); else { DBG(1, "No supported image sensor detected"); err = -ENODEV; @@ -1950,6 +1962,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); cam->module_param.force_munmap = force_munmap[dev_nr]; + cam->module_param.frame_timeout = frame_timeout[dev_nr]; dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; @@ -1994,6 +2007,7 @@ static void zc0301_usb_disconnect(struct usb_interface* intf) cam->state |= DEV_DISCONNECTED; wake_up_interruptible(&cam->wait_frame); wake_up(&cam->wait_stream); + usb_get_dev(cam->usbdev); } else { cam->state |= DEV_DISCONNECTED; zc0301_release_resources(cam); diff --git a/drivers/usb/media/zc0301_pas202bcb.c b/drivers/usb/media/zc0301_pas202bcb.c index 32b9b9329cbf..9d282a22c15f 100644 --- a/drivers/usb/media/zc0301_pas202bcb.c +++ b/drivers/usb/media/zc0301_pas202bcb.c @@ -22,6 +22,14 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ***************************************************************************/ +/* + NOTE: Sensor controls are disabled for now, becouse changing them while + streaming sometimes results in out-of-sync video frames. We'll use + the default initialization, until we know how to stop and start video + in the chip. However, the image quality still looks good under various + light conditions. +*/ + #include #include "zc0301_sensor.h" @@ -245,7 +253,7 @@ static struct zc0301_sensor pas202bcb = { .maximum = 0x3fff, .step = 0x0001, .default_value = 0x01e5, - .flags = 0, + .flags = V4L2_CTRL_FLAG_DISABLED, }, { .id = V4L2_CID_GAIN, @@ -255,7 +263,17 @@ static struct zc0301_sensor pas202bcb = { .maximum = 0x1f, .step = 0x01, .default_value = 0x0c, - .flags = 0, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = ZC0301_V4L2_CID_DAC_MAGNITUDE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "DAC magnitude", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = 0x00, + .flags = V4L2_CTRL_FLAG_DISABLED, }, { .id = V4L2_CID_RED_BALANCE, @@ -265,7 +283,7 @@ static struct zc0301_sensor pas202bcb = { .maximum = 0x0f, .step = 0x01, .default_value = 0x01, - .flags = 0, + .flags = V4L2_CTRL_FLAG_DISABLED, }, { .id = V4L2_CID_BLUE_BALANCE, @@ -275,7 +293,7 @@ static struct zc0301_sensor pas202bcb = { .maximum = 0x0f, .step = 0x01, .default_value = 0x05, - .flags = 0, + .flags = V4L2_CTRL_FLAG_DISABLED, }, { .id = ZC0301_V4L2_CID_GREEN_BALANCE, @@ -285,17 +303,7 @@ static struct zc0301_sensor pas202bcb = { .maximum = 0x0f, .step = 0x01, .default_value = 0x00, - .flags = 0, - }, - { - .id = ZC0301_V4L2_CID_DAC_MAGNITUDE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "DAC magnitude", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x04, - .flags = 0, + .flags = V4L2_CTRL_FLAG_DISABLED, }, }, .get_ctrl = &pas202bcb_get_ctrl, diff --git a/drivers/usb/media/zc0301_sensor.h b/drivers/usb/media/zc0301_sensor.h index 8890e32405d4..e3cb6cc920ca 100644 --- a/drivers/usb/media/zc0301_sensor.h +++ b/drivers/usb/media/zc0301_sensor.h @@ -43,9 +43,11 @@ static int (*zc0301_sensor_table[])(struct zc0301_device*) = { \ NULL, \ }; +extern struct zc0301_device* +zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id); + extern void -zc0301_attach_sensor(struct zc0301_device* cam, - struct zc0301_sensor* sensor); +zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); #define ZC0301_USB_DEVICE(vend, prod, intclass) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ @@ -56,7 +58,14 @@ zc0301_attach_sensor(struct zc0301_device* cam, #define ZC0301_ID_TABLE \ static const struct usb_device_id zc0301_id_table[] = { \ + { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \ + { ZC0301_USB_DEVICE(0x041e, 0x0417, 0xff), }, \ + { ZC0301_USB_DEVICE(0x041e, 0x041e, 0xff), }, /* HV7131B */ \ + { ZC0301_USB_DEVICE(0x041e, 0x081c, 0xff), }, /* PAS106 */ \ + { ZC0301_USB_DEVICE(0x041e, 0x0834, 0xff), }, /* PAS106 */ \ + { ZC0301_USB_DEVICE(0x041e, 0x0835, 0xff), }, /* PAS106 */ \ { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \ + { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \ { } \ }; @@ -80,15 +89,11 @@ struct zc0301_sensor { struct v4l2_cropcap cropcap; struct v4l2_pix_format pix_format; - int (*init)(struct zc0301_device* cam); - int (*get_ctrl)(struct zc0301_device* cam, - struct v4l2_control* ctrl); - int (*set_ctrl)(struct zc0301_device* cam, + int (*init)(struct zc0301_device*); + int (*get_ctrl)(struct zc0301_device*, struct v4l2_control* ctrl); + int (*set_ctrl)(struct zc0301_device*, const struct v4l2_control* ctrl); - int (*set_crop)(struct zc0301_device* cam, - const struct v4l2_rect* rect); - - const struct usb_device* usbdev; + int (*set_crop)(struct zc0301_device*, const struct v4l2_rect* rect); /* Private */ struct v4l2_queryctrl _qctrl[ZC0301_MAX_CTRLS]; -- cgit v1.2.3-59-g8ed1b From a5c44e29e5637b5e6fe59d225eb4f438688b3849 Mon Sep 17 00:00:00 2001 From: Lonnie Mendez Date: Wed, 1 Mar 2006 10:45:24 -0600 Subject: [PATCH] USB: cypress_m8: add support for the Nokia ca42-version 2 cable This patch adds support for the Nokia ca42 version 2 cable to the cypress_m8 driver. The device was tested by others with this patch and found to be compatible with the cypress_m8 driver. A special note should be taken that this cable seems to vary in the type of chipset used. This patch supports the cable with product id 0x4101. Signed-off-by: Lonnie Mendez Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cypress_m8.c | 70 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/serial/cypress_m8.h | 5 +++ 2 files changed, 75 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 71af3bf5adb7..7212fbe3b6f2 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -98,10 +98,16 @@ static struct usb_device_id id_table_cyphidcomrs232 [] = { { } /* Terminating entry */ }; +static struct usb_device_id id_table_nokiaca42v2 [] = { + { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) }, + { } /* Terminating entry */ +}; + static struct usb_device_id id_table_combined [] = { { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) }, { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) }, { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, + { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) }, { } /* Terminating entry */ }; @@ -149,6 +155,7 @@ struct cypress_buf { /* function prototypes for the Cypress USB to serial device */ static int cypress_earthmate_startup (struct usb_serial *serial); static int cypress_hidcom_startup (struct usb_serial *serial); +static int cypress_ca42v2_startup (struct usb_serial *serial); static void cypress_shutdown (struct usb_serial *serial); static int cypress_open (struct usb_serial_port *port, struct file *filp); static void cypress_close (struct usb_serial_port *port, struct file *filp); @@ -235,6 +242,34 @@ static struct usb_serial_driver cypress_hidcom_device = { .write_int_callback = cypress_write_int_callback, }; +static struct usb_serial_driver cypress_ca42v2_device = { + .driver = { + .owner = THIS_MODULE, + .name = "nokiaca42v2", + }, + .description = "Nokia CA-42 V2 Adapter", + .id_table = id_table_nokiaca42v2, + .num_interrupt_in = 1, + .num_interrupt_out = 1, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 1, + .attach = cypress_ca42v2_startup, + .shutdown = cypress_shutdown, + .open = cypress_open, + .close = cypress_close, + .write = cypress_write, + .write_room = cypress_write_room, + .ioctl = cypress_ioctl, + .set_termios = cypress_set_termios, + .tiocmget = cypress_tiocmget, + .tiocmset = cypress_tiocmset, + .chars_in_buffer = cypress_chars_in_buffer, + .throttle = cypress_throttle, + .unthrottle = cypress_unthrottle, + .read_int_callback = cypress_read_int_callback, + .write_int_callback = cypress_write_int_callback, +}; /***************************************************************************** * Cypress serial helper functions @@ -286,6 +321,12 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m __FUNCTION__); new_baudrate = priv->baud_rate; } + } else if (priv->chiptype == CT_CA42V2) { + if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) { + err("%s - failed setting baud rate, unsupported speed", + __FUNCTION__); + new_baudrate = priv->baud_rate; + } } else if (priv->chiptype == CT_GENERIC) { if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) { err("%s - failed setting baud rate, unsupported speed", @@ -499,6 +540,25 @@ static int cypress_hidcom_startup (struct usb_serial *serial) } /* cypress_hidcom_startup */ +static int cypress_ca42v2_startup (struct usb_serial *serial) +{ + struct cypress_private *priv; + + dbg("%s", __FUNCTION__); + + if (generic_startup(serial)) { + dbg("%s - Failed setting up port %d", __FUNCTION__, + serial->port[0]->number); + return 1; + } + + priv = usb_get_serial_port_data(serial->port[0]); + priv->chiptype = CT_CA42V2; + + return 0; +} /* cypress_ca42v2_startup */ + + static void cypress_shutdown (struct usb_serial *serial) { struct cypress_private *priv; @@ -943,6 +1003,10 @@ static void cypress_set_termios (struct usb_serial_port *port, *(tty->termios) = tty_std_termios; tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + } else if (priv->chiptype == CT_CA42V2) { + *(tty->termios) = tty_std_termios; + tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | + CLOCAL; } priv->termios_initialized = 1; } @@ -1541,6 +1605,9 @@ static int __init cypress_init(void) retval = usb_serial_register(&cypress_hidcom_device); if (retval) goto failed_hidcom_register; + retval = usb_serial_register(&cypress_ca42v2_device); + if (retval) + goto failed_ca42v2_register; retval = usb_register(&cypress_driver); if (retval) goto failed_usb_register; @@ -1549,6 +1616,8 @@ static int __init cypress_init(void) return 0; failed_usb_register: usb_deregister(&cypress_driver); +failed_ca42v2_register: + usb_serial_deregister(&cypress_ca42v2_device); failed_hidcom_register: usb_serial_deregister(&cypress_hidcom_device); failed_em_register: @@ -1565,6 +1634,7 @@ static void __exit cypress_exit (void) usb_deregister (&cypress_driver); usb_serial_deregister (&cypress_earthmate_device); usb_serial_deregister (&cypress_hidcom_device); + usb_serial_deregister (&cypress_ca42v2_device); } diff --git a/drivers/usb/serial/cypress_m8.h b/drivers/usb/serial/cypress_m8.h index 1fa119efe41a..e1c7c27e18b7 100644 --- a/drivers/usb/serial/cypress_m8.h +++ b/drivers/usb/serial/cypress_m8.h @@ -18,6 +18,10 @@ /* Cypress HID->COM RS232 Adapter */ #define VENDOR_ID_CYPRESS 0x04b4 #define PRODUCT_ID_CYPHIDCOM 0x5500 + +/* Nokia CA-42 USB to serial cable */ +#define VENDOR_ID_DAZZLE 0x07d0 +#define PRODUCT_ID_CA42 0x4101 /* End of device listing */ /* Used for setting / requesting serial line settings */ @@ -34,6 +38,7 @@ #define CT_EARTHMATE 0x01 #define CT_CYPHIDCOM 0x02 +#define CT_CA42V2 0x03 #define CT_GENERIC 0x0F /* End of chiptype definitions */ -- cgit v1.2.3-59-g8ed1b From 96050b11f690878c19c1cd39970ab7325d91e18b Mon Sep 17 00:00:00 2001 From: Julian Bradfield Date: Wed, 1 Mar 2006 10:19:44 +0000 Subject: [PATCH] USB: PL2303 and TIOCMIWAIT A while ago, I posted about TIOCMIWAIT not working with the PL2303 USB-serial adapter. After a brief exchange with Greg, I tracked this to a missing wake-up in the USB interrupt procedures. I got our systems staff to install the enclosed very simple patch to our 2.6.12 kernels, and it all works fine as expected. I guess this should also apply to the latest version and go into the mainstream. Apologies for the long delay in posting the result. The routine being patched is pl2303_update_line_status Signed-off-by: Julian Bradfield Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index cf2213bae0e0..fb3b6b7b9065 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -826,6 +826,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port, spin_lock_irqsave(&priv->lock, flags); priv->line_status = data[status_idx]; spin_unlock_irqrestore(&priv->lock, flags); + wake_up_interruptible (&priv->delta_msr_wait); exit: return; -- cgit v1.2.3-59-g8ed1b From 491b04ce1c9adfa0cd73f095086f3c37da81b667 Mon Sep 17 00:00:00 2001 From: Dick Streefland Date: Wed, 1 Mar 2006 00:53:33 -0800 Subject: [PATCH] USB: support for USB-to-serial cable from Speed Dragon Multimedia The USB data cable for my Samsung GSM phone contains the USB-to-serial converter chip MS3303H from Speed Dragon Multimedia, Inc. that appears to be compatible with the PL2303 chip. The following patch adds support for this chip to the pl2303 driver. Signed-off-by: Dick Streefland Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 1 + drivers/usb/serial/pl2303.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index fb3b6b7b9065..b3014fda645c 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -77,6 +77,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) }, { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) }, { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) }, + { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 9bc4755162ad..77901d143979 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -75,3 +75,7 @@ /* Leadtek GPS 9531 (ID 0413:2101) */ #define LEADTEK_VENDOR_ID 0x0413 #define LEADTEK_9531_PRODUCT_ID 0x2101 + +/* USB GSM cable from Speed Dragon Multimedia, Ltd */ +#define SPEEDDRAGON_VENDOR_ID 0x0e55 +#define SPEEDDRAGON_PRODUCT_ID 0x110b -- cgit v1.2.3-59-g8ed1b From ae55717584431761b70215d3d574c13fe97093f2 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 28 Feb 2006 10:16:12 -0500 Subject: [PATCH] USB: UHCI: Increase port-reset completion delay for HP controllers This patch (as657) increases the port-reset completion delay in uhci-hcd for HP's embedded controllers. Unlike other UHCI controllers, the HP chips can take as long as 250 us to carry out the processing associated with finishing a port reset. This fixes Novell bug #148761. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-hub.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index a71e48a66805..152971d16769 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -99,6 +99,21 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, } } +/* Wait for the UHCI controller in HP's iLO2 server management chip. + * It can take up to 250 us to finish a reset and set the CSC bit. + */ +static void wait_for_HP(unsigned long port_addr) +{ + int i; + + for (i = 10; i < 250; i += 10) { + if (inw(port_addr) & USBPORTSC_CSC) + return; + udelay(10); + } + /* Log a warning? */ +} + static void uhci_check_ports(struct uhci_hcd *uhci) { unsigned int port; @@ -113,6 +128,12 @@ static void uhci_check_ports(struct uhci_hcd *uhci) CLR_RH_PORTSTAT(USBPORTSC_PR); udelay(10); + /* HP's server management chip requires + * a longer delay. */ + if (to_pci_dev(uhci_dev(uhci))->vendor == + PCI_VENDOR_ID_HP) + wait_for_HP(port_addr); + /* If the port was enabled before, turning * reset on caused a port enable change. * Turning reset off causes a port connect -- cgit v1.2.3-59-g8ed1b From 4d69581929b8f8836f806bcc320b19ed886e9517 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Thu, 2 Mar 2006 16:36:09 -0800 Subject: [PATCH] USB: ub 01 remove first_open The first_open was long overdue for removal, but I wanted to keep this separate for other changes in case of regressions. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'drivers') diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 3e7689494c66..26aa96eba439 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -8,7 +8,6 @@ * and is not licensed separately. See file COPYING for details. * * TODO (sorted by decreasing priority) - * -- Kill first_open (Al Viro fixed the block layer now) * -- 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 @@ -334,7 +333,6 @@ struct ub_lun { int changed; /* Media was changed */ int removable; int readonly; - int first_open; /* Kludge. See ub_bd_open. */ struct ub_request urq; @@ -1849,26 +1847,6 @@ static int ub_bd_open(struct inode *inode, struct file *filp) sc->openc++; spin_unlock_irqrestore(&ub_lock, flags); - /* - * This is a workaround for a specific problem in our block layer. - * In 2.6.9, register_disk duplicates the code from rescan_partitions. - * However, if we do add_disk with a device which persistently reports - * a changed media, add_disk calls register_disk, which does do_open, - * which will call rescan_paritions for changed media. After that, - * register_disk attempts to do it all again and causes double kobject - * registration and a eventually an oops on module removal. - * - * The bottom line is, Al Viro says that we should not allow - * bdev->bd_invalidated to be set when doing add_disk no matter what. - */ - if (lun->first_open) { - lun->first_open = 0; - if (lun->changed) { - rc = -ENOMEDIUM; - goto err_open; - } - } - if (lun->removable || lun->readonly) check_disk_change(inode->i_bdev); @@ -2537,7 +2515,6 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) lun->removable = 1; /* XXX Query this from the device */ lun->changed = 1; /* ub_revalidate clears only */ - lun->first_open = 1; ub_revalidate(sc, lun); rc = -ENOMEM; -- cgit v1.2.3-59-g8ed1b From 952ba222962bf3fb1336f139f1049030153cae55 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Thu, 2 Mar 2006 16:42:59 -0800 Subject: [PATCH] USB: ub 02 remove diag Remove the "diag" file from the sysfs. The usbmon is good enough these days so I do not need this feature anymore. Also, sysfs is a pain. Al Viro caught a race in this, which I thought too bothersome to fix. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 197 ++--------------------------------------------------- 1 file changed, 4 insertions(+), 193 deletions(-) (limited to 'drivers') diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 26aa96eba439..21d0e075c928 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -180,6 +180,7 @@ 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')) @@ -195,24 +196,11 @@ enum ub_scsi_cmd_state { UB_CMDST_DONE /* Final state */ }; -static char *ub_scsi_cmd_stname[] = { - ". ", - "Cmd", - "dat", - "c2s", - "sts", - "clr", - "crs", - "Sen", - "fin" -}; - struct ub_scsi_cmd { unsigned char cdb[UB_MAX_CDB_SIZE]; unsigned char cdb_len; unsigned char dir; /* 0 - none, 1 - read, 3 - write. */ - unsigned char trace_index; enum ub_scsi_cmd_state state; unsigned int tag; struct ub_scsi_cmd *next; @@ -248,28 +236,6 @@ struct ub_capacity { unsigned int bshift; /* Shift between 512 and hard sects */ }; -/* - * The SCSI command tracing structure. - */ - -#define SCMD_ST_HIST_SZ 8 -#define SCMD_TRACE_SZ 63 /* Less than 4KB of 61-byte lines */ - -struct ub_scsi_cmd_trace { - int hcur; - unsigned int tag; - unsigned int req_size, act_size; - unsigned char op; - unsigned char dir; - unsigned char key, asc, ascq; - char st_hst[SCMD_ST_HIST_SZ]; -}; - -struct ub_scsi_trace { - int cur; - struct ub_scsi_cmd_trace vec[SCMD_TRACE_SZ]; -}; - /* * This is a direct take-off from linux/include/completion.h * The difference is that I do not wait on this thing, just poll. @@ -388,7 +354,6 @@ struct ub_dev { wait_queue_head_t reset_wait; int sg_stat[6]; - struct ub_scsi_trace tr; }; /* @@ -457,137 +422,6 @@ static int ub_qlock_next = 0; static DEFINE_SPINLOCK(ub_lock); /* Locks globals and ->openc */ -/* - * The SCSI command tracing procedures. - */ - -static void ub_cmdtr_new(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - int n; - struct ub_scsi_cmd_trace *t; - - if ((n = sc->tr.cur + 1) == SCMD_TRACE_SZ) n = 0; - t = &sc->tr.vec[n]; - - memset(t, 0, sizeof(struct ub_scsi_cmd_trace)); - t->tag = cmd->tag; - t->op = cmd->cdb[0]; - t->dir = cmd->dir; - t->req_size = cmd->len; - t->st_hst[0] = cmd->state; - - sc->tr.cur = n; - cmd->trace_index = n; -} - -static void ub_cmdtr_state(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - int n; - struct ub_scsi_cmd_trace *t; - - t = &sc->tr.vec[cmd->trace_index]; - if (t->tag == cmd->tag) { - if ((n = t->hcur + 1) == SCMD_ST_HIST_SZ) n = 0; - t->st_hst[n] = cmd->state; - t->hcur = n; - } -} - -static void ub_cmdtr_act_len(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - struct ub_scsi_cmd_trace *t; - - t = &sc->tr.vec[cmd->trace_index]; - if (t->tag == cmd->tag) - t->act_size = cmd->act_len; -} - -static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd, - unsigned char *sense) -{ - struct ub_scsi_cmd_trace *t; - - t = &sc->tr.vec[cmd->trace_index]; - if (t->tag == cmd->tag) { - t->key = sense[2] & 0x0F; - t->asc = sense[12]; - t->ascq = sense[13]; - } -} - -static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, - char *page) -{ - struct usb_interface *intf; - struct ub_dev *sc; - struct list_head *p; - struct ub_lun *lun; - int cnt; - unsigned long flags; - int nc, nh; - int i, j; - struct ub_scsi_cmd_trace *t; - - intf = to_usb_interface(dev); - sc = usb_get_intfdata(intf); - if (sc == NULL) - return 0; - - cnt = 0; - spin_lock_irqsave(sc->lock, flags); - - cnt += sprintf(page + cnt, - "poison %d reset %d\n", - atomic_read(&sc->poison), sc->reset); - cnt += sprintf(page + cnt, - "qlen %d qmax %d\n", - sc->cmd_queue.qlen, sc->cmd_queue.qmax); - cnt += sprintf(page + cnt, - "sg %d %d %d %d %d .. %d\n", - sc->sg_stat[0], - sc->sg_stat[1], - sc->sg_stat[2], - sc->sg_stat[3], - sc->sg_stat[4], - sc->sg_stat[5]); - - list_for_each (p, &sc->luns) { - lun = list_entry(p, struct ub_lun, link); - cnt += sprintf(page + cnt, - "lun %u changed %d removable %d readonly %d\n", - lun->num, lun->changed, lun->removable, lun->readonly); - } - - if ((nc = sc->tr.cur + 1) == SCMD_TRACE_SZ) nc = 0; - for (j = 0; j < SCMD_TRACE_SZ; j++) { - t = &sc->tr.vec[nc]; - - cnt += sprintf(page + cnt, "%08x %02x", t->tag, t->op); - if (t->op == REQUEST_SENSE) { - cnt += sprintf(page + cnt, " [sense %x %02x %02x]", - t->key, t->asc, t->ascq); - } else { - cnt += sprintf(page + cnt, " %c", UB_DIR_CHAR(t->dir)); - cnt += sprintf(page + cnt, " [%5d %5d]", - t->req_size, t->act_size); - } - if ((nh = t->hcur + 1) == SCMD_ST_HIST_SZ) nh = 0; - for (i = 0; i < SCMD_ST_HIST_SZ; i++) { - cnt += sprintf(page + cnt, " %s", - ub_scsi_cmd_stname[(int)t->st_hst[nh]]); - if (++nh == SCMD_ST_HIST_SZ) nh = 0; - } - cnt += sprintf(page + cnt, "\n"); - - if (++nc == SCMD_TRACE_SZ) nc = 0; - } - - spin_unlock_irqrestore(sc->lock, flags); - return cnt; -} - -static DEVICE_ATTR(diag, S_IRUGO, ub_diag_show, NULL); /* N.B. World readable */ - /* * The id allocator. * @@ -1090,7 +924,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) add_timer(&sc->work_timer); cmd->state = UB_CMDST_CMD; - ub_cmdtr_state(sc, cmd); return 0; } @@ -1143,12 +976,10 @@ static void ub_scsi_dispatch(struct ub_dev *sc) ub_cmdq_pop(sc); (*cmd->done)(sc, cmd); } else if (cmd->state == UB_CMDST_INIT) { - ub_cmdtr_new(sc, cmd); if ((rc = ub_scsi_cmd_start(sc, cmd)) == 0) break; cmd->error = rc; cmd->state = UB_CMDST_DONE; - ub_cmdtr_state(sc, cmd); } else { if (!ub_is_completed(&sc->work_done)) break; @@ -1245,7 +1076,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) return; } cmd->state = UB_CMDST_CLEAR; - ub_cmdtr_state(sc, cmd); return; case -ESHUTDOWN: /* unplug */ case -EILSEQ: /* unplug timeout on uhci */ @@ -1277,7 +1107,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) return; } cmd->state = UB_CMDST_CLR2STS; - ub_cmdtr_state(sc, cmd); return; } if (urb->status == -EOVERFLOW) { @@ -1302,7 +1131,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) if (urb->status != 0 || len != cmd->sgv[cmd->current_sg].length) { cmd->act_len += len; - ub_cmdtr_act_len(sc, cmd); cmd->error = -EIO; ub_state_stat(sc, cmd); @@ -1329,7 +1157,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) } cmd->act_len += urb->actual_length; - ub_cmdtr_act_len(sc, cmd); if (++cmd->current_sg < cmd->nsg) { ub_data_start(sc, cmd); @@ -1355,7 +1182,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) cmd->error = -EIO; /* A cheap trick... */ cmd->state = UB_CMDST_CLRRS; - ub_cmdtr_state(sc, cmd); return; } @@ -1439,7 +1265,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) return; } cmd->state = UB_CMDST_DONE; - ub_cmdtr_state(sc, cmd); ub_cmdq_pop(sc); (*cmd->done)(sc, cmd); @@ -1494,7 +1319,6 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) add_timer(&sc->work_timer); cmd->state = UB_CMDST_DATA; - ub_cmdtr_state(sc, cmd); } /* @@ -1506,7 +1330,6 @@ static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc) cmd->error = rc; cmd->state = UB_CMDST_DONE; - ub_cmdtr_state(sc, cmd); ub_cmdq_pop(sc); (*cmd->done)(sc, cmd); } @@ -1552,7 +1375,6 @@ static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) cmd->stat_count = 0; cmd->state = UB_CMDST_STAT; - ub_cmdtr_state(sc, cmd); } /* @@ -1571,7 +1393,6 @@ static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd) return; cmd->state = UB_CMDST_STAT; - ub_cmdtr_state(sc, cmd); } /* @@ -1609,7 +1430,6 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) scmd->tag = sc->tagcnt++; cmd->state = UB_CMDST_SENSE; - ub_cmdtr_state(sc, cmd); ub_cmdq_insert(sc, scmd); return; @@ -1665,11 +1485,6 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) unsigned char *sense = sc->top_sense; struct ub_scsi_cmd *cmd; - /* - * Ignoring scmd->act_len, because the buffer was pre-zeroed. - */ - ub_cmdtr_sense(sc, scmd, sense); - /* * Find the command which triggered the unit attention or a check, * save the sense into it, and advance its state machine. @@ -1691,6 +1506,9 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) return; } + /* + * Ignoring scmd->act_len, because the buffer was pre-zeroed. + */ cmd->key = sense[2] & 0x0F; cmd->asc = sense[12]; cmd->ascq = sense[13]; @@ -2413,9 +2231,6 @@ static int ub_probe(struct usb_interface *intf, if (ub_get_pipes(sc, sc->dev, intf) != 0) goto err_dev_desc; - if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0) - goto err_diag; - /* * At this point, all USB initialization is done, do upper layer. * We really hate halfway initialized structures, so from the @@ -2480,8 +2295,6 @@ static int ub_probe(struct usb_interface *intf, } return 0; - /* device_remove_file(&sc->intf->dev, &dev_attr_diag); */ -err_diag: err_dev_desc: usb_set_intfdata(intf, NULL); // usb_put_intf(sc->intf); @@ -2609,7 +2422,6 @@ static void ub_disconnect(struct usb_interface *intf) while ((cmd = ub_cmdq_peek(sc)) != NULL) { cmd->error = -ENOTCONN; cmd->state = UB_CMDST_DONE; - ub_cmdtr_state(sc, cmd); ub_cmdq_pop(sc); (*cmd->done)(sc, cmd); cnt++; @@ -2660,7 +2472,6 @@ static void ub_disconnect(struct usb_interface *intf) * and no URBs left in transit. */ - device_remove_file(&sc->intf->dev, &dev_attr_diag); usb_set_intfdata(intf, NULL); // usb_put_intf(sc->intf); sc->intf = NULL; -- cgit v1.2.3-59-g8ed1b From 11a223ae3b86b94391774512e5671600367a305c Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Thu, 2 Mar 2006 16:53:00 -0800 Subject: [PATCH] USB: ub 03 drop stall clearing Matt mentioned that a very old ZIP-100 actually does need this, but I am yet to see anyone who actually has one still working and uses ub with it. He/she must be a retrocomputing geek, who can easily bias it to usb-storage with libusual, if needed. Meanwhile, common folks have trouble with poorly designed USB keys and some el-cheapo European music players. I think we better drop this for now. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 21d0e075c928..f73446f580df 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -2270,19 +2270,8 @@ static int ub_probe(struct usb_interface *intf, nluns = 1; for (i = 0; i < 3; i++) { - if ((rc = ub_sync_getmaxlun(sc)) < 0) { - /* - * This segment is taken from usb-storage. They say - * that ZIP-100 needs this, but my own ZIP-100 works - * fine without this. - * Still, it does not seem to hurt anything. - */ - if (rc == -EPIPE) { - ub_probe_clear_stall(sc, sc->recv_bulk_pipe); - ub_probe_clear_stall(sc, sc->send_bulk_pipe); - } + if ((rc = ub_sync_getmaxlun(sc)) < 0) break; - } if (rc != 0) { nluns = rc; break; -- cgit v1.2.3-59-g8ed1b From 6aa35675bbc370e5f11baae7e01a9ab255d8030c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 8 Mar 2006 15:14:09 -0500 Subject: [PATCH] USB: usbcore: Don't assume a USB configuration includes any interfaces In a couple of places, usbcore assumes that a USB device configuration will have a nonzero number of interfaces. Having no interfaces may or may not be allowed by the USB spec; in any event we shouldn't die if we encounter such a thing. This patch (as662) removes the assumptions. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7dd28f8e1cea..8e65f7a237e4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1179,8 +1179,11 @@ static int choose_configuration(struct usb_device *udev) c = udev->config; num_configs = udev->descriptor.bNumConfigurations; for (i = 0; i < num_configs; (i++, c++)) { - struct usb_interface_descriptor *desc = - &c->intf_cache[0]->altsetting->desc; + struct usb_interface_descriptor *desc = NULL; + + /* It's possible that a config has no interfaces! */ + if (c->desc.bNumInterfaces > 0) + desc = &c->intf_cache[0]->altsetting->desc; /* * HP's USB bus-powered keyboard has only one configuration @@ -1215,7 +1218,8 @@ static int choose_configuration(struct usb_device *udev) /* If the first config's first interface is COMM/2/0xff * (MSFT RNDIS), rule it out unless Linux has host-side * RNDIS support. */ - if (i == 0 && desc->bInterfaceClass == USB_CLASS_COMM + if (i == 0 && desc + && desc->bInterfaceClass == USB_CLASS_COMM && desc->bInterfaceSubClass == 2 && desc->bInterfaceProtocol == 0xff) { #ifndef CONFIG_USB_NET_RNDIS @@ -1231,8 +1235,8 @@ static int choose_configuration(struct usb_device *udev) * than a vendor-specific driver. */ else if (udev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC && - desc->bInterfaceClass != - USB_CLASS_VENDOR_SPEC) { + (!desc || desc->bInterfaceClass != + USB_CLASS_VENDOR_SPEC)) { best = c; break; } @@ -3024,7 +3028,7 @@ 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 && + if (udev->actconfig && udev->actconfig->desc.bNumInterfaces > 0 && udev->actconfig->interface[0]->dev.driver == &hub_driver.driver && (hub = hdev_to_hub(udev)) != NULL) { -- cgit v1.2.3-59-g8ed1b From f48219db93eaee644e9fd9f22fb6421f38059cc5 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Thu, 9 Mar 2006 14:10:49 +0100 Subject: [PATCH] USB: usbcore: usb_set_configuration oops (NULL ptr dereference) When trying to deconfigure a device via usb_set_configuration(dev, 0), 2.6.16-rc kernels after 55c527187c9d78f840b284d596a0b298bc1493af oops with "Unable to handle NULL pointer dereference at...". This is due to an unchecked dereference of cp in the power budget part. Signed-off-by: Horst Schirmeier Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 2f6009b0cffc..08fb20f06f3e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1388,11 +1388,13 @@ free_interfaces: if (dev->state != USB_STATE_ADDRESS) usb_disable_device (dev, 1); // Skip ep0 - i = dev->bus_mA - cp->desc.bMaxPower * 2; - if (i < 0) - dev_warn(&dev->dev, "new config #%d exceeds power " - "limit by %dmA\n", - configuration, -i); + if (cp) { + i = dev->bus_mA - cp->desc.bMaxPower * 2; + if (i < 0) + dev_warn(&dev->dev, "new config #%d exceeds power " + "limit by %dmA\n", + configuration, -i); + } if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, -- cgit v1.2.3-59-g8ed1b From b712548c5d88f2e4672f8482c3904e8c5728dbf1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Mar 2006 17:40:08 -0800 Subject: [PATCH] USB: fix initdata issue in isp116x-hcd As found by Sam's scripts. Cc: Sam Ravnborg Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp116x-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index fea5dcbec7c4..e99210b7909b 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1552,7 +1552,7 @@ static struct hc_driver isp116x_hc_driver = { /*----------------------------------------------------------------*/ -static int __init_or_module isp116x_remove(struct platform_device *pdev) +static int isp116x_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct isp116x *isp116x; -- cgit v1.2.3-59-g8ed1b From 1e7a5a84e407dfa20813a7f55413be8193ee5380 Mon Sep 17 00:00:00 2001 From: Phil Dibowitz Date: Sun, 5 Mar 2006 21:36:51 -0800 Subject: [PATCH] USB: storage: sandisk unusual_devices entry The following adds an unusual_devs entry for the SanDisk ImageMate CompactFlash USB drive, for the US_FL_FIX_CAPACITY flag. Additionally, it removes trailing whitespace from the previous entry. It's based on the patch sent by Roman Hodek . Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 31ca92056c27..a0d355831204 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -760,12 +760,19 @@ UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), -UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, +/* Submitted by Roman Hodek */ +UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk", "ImageMate SDDR-05a", US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN ), +UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, + "SanDisk Corporation", + "ImageMate CompactFlash USB", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + #ifdef CONFIG_USB_STORAGE_USBAT UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, "Sandisk", -- cgit v1.2.3-59-g8ed1b From c713c973fb4bfdb22cce488cca4f9f8006ed58ce Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Sun, 5 Mar 2006 21:43:40 -0800 Subject: [PATCH] USB: storage: another unusual_devs.h entry Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index a0d355831204..5d78fb42cb04 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1080,6 +1080,16 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, 0), #endif +/* + * Pete Zaitcev , bz#164688. + * The device blatantly ignores LUN and returns 1 in GetMaxLUN. + */ +UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100, + "Unknown", + "Unknown", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + /* Submitted by Joris Struyve */ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, "Medion", -- cgit v1.2.3-59-g8ed1b From 23b7885d50c5f5fe6dca93d4b0913f6e7b878dad Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Sun, 5 Mar 2006 21:45:44 -0800 Subject: [PATCH] USB: storage: unusual_devs.h entry 0420:0001 Ref https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=176584 Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 5d78fb42cb04..8310e86d745d 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -120,6 +120,12 @@ UNUSUAL_DEV( 0x0419, 0xaaf6, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Pete Zaitcev , bz#176584 */ +UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, + "GENERIC", "MP3 PLAYER", /* MyMusix PD-205 on the outside. */ + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Reported by Olaf Hering from novell bug #105878 */ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, "SMSC", -- cgit v1.2.3-59-g8ed1b From 9d5847bc1a3977fbfb4057aad41458df89792309 Mon Sep 17 00:00:00 2001 From: Rodolfo Quesada Date: Mon, 6 Mar 2006 10:45:42 -0500 Subject: [PATCH] USB: storage: new unusual_devs.h entry: Mitsumi 7in1 Card Reader This patch (as661) adds an unusual_devs entry for the Mitsumi 7in1 Card Reader. From: Rodolfo Quesada Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 8310e86d745d..c4a9dcff5f2b 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -62,6 +62,13 @@ UNUSUAL_DEV( 0x03ee, 0x6901, 0x0000, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), +/* Reported by Rodolfo Quesada */ +UNUSUAL_DEV( 0x03ee, 0x6906, 0x0003, 0x0003, + "VIA Technologies Inc.", + "Mitsumi multi cardreader", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, "HP", "CD-Writer+", -- cgit v1.2.3-59-g8ed1b From 2e56222ed52cec40427fa89f23b228232e3e327e Mon Sep 17 00:00:00 2001 From: Wolfgang Rohdewald Date: Wed, 8 Mar 2006 16:59:44 +0100 Subject: [PATCH] USB: add support for Creativelabs Silvercrest USB keyboard Signed-off-by: Wolfgang Rohdewald Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 6b8a51cad375..58b59f6e9881 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1552,6 +1552,9 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_HP 0x03f0 #define USB_DEVICE_ID_HP_USBHUB_KB 0x020c +#define USB_VENDOR_ID_CREATIVELABS 0x062a +#define USB_DEVICE_ID_CREATIVELABS_SILVERCREST 0x0201 + /* * Alphabetically sorted blacklist by quirk type. */ @@ -1668,6 +1671,7 @@ static const struct hid_blacklist { { 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_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 }, -- cgit v1.2.3-59-g8ed1b From 6e0755a4b2a41a8cd5839db69532d07262294b41 Mon Sep 17 00:00:00 2001 From: Luca Risolia Date: Fri, 3 Mar 2006 09:58:39 +0000 Subject: [PATCH] USB: ZC0301 driver bugfix ZC0301 driver bugfix. Use correct PID/VID USB entries. Signed-off-by: Luca Risolia Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/zc0301.txt | 12 ++++++------ drivers/usb/media/zc0301.h | 5 +---- drivers/usb/media/zc0301_core.c | 6 +++--- drivers/usb/media/zc0301_sensor.h | 12 ++++++------ 4 files changed, 16 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/Documentation/usb/zc0301.txt b/Documentation/usb/zc0301.txt index 095838420e82..f55262c6733b 100644 --- a/Documentation/usb/zc0301.txt +++ b/Documentation/usb/zc0301.txt @@ -201,14 +201,14 @@ devices mounting the ZC0301 Image Processor and Control Chips: Vendor ID Product ID --------- ---------- -0x10fd 0x8050 -0x041e 0x0417 -0x041e 0x041e -0x041e 0x081c -0x041e 0x0834 -0x041e 0x0835 +0x041e 0x4017 +0x041e 0x401c +0x041e 0x401e +0x041e 0x4034 +0x041e 0x4035 0x046d 0x08ae 0x0ac8 0x0301 +0x10fd 0x8050 The list above does not imply that all those devices work with this driver: up until now only the ones that mount the following image sensors are supported; diff --git a/drivers/usb/media/zc0301.h b/drivers/usb/media/zc0301.h index 9ba9135e824b..8e0655140e60 100644 --- a/drivers/usb/media/zc0301.h +++ b/drivers/usb/media/zc0301.h @@ -134,10 +134,7 @@ struct zc0301_device { struct zc0301_device* zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id) { - if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) - return cam; - - return NULL; + return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; } void diff --git a/drivers/usb/media/zc0301_core.c b/drivers/usb/media/zc0301_core.c index 5773688d3dae..4036c6268bff 100644 --- a/drivers/usb/media/zc0301_core.c +++ b/drivers/usb/media/zc0301_core.c @@ -52,8 +52,8 @@ #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" #define ZC0301_AUTHOR_EMAIL "" #define ZC0301_MODULE_LICENSE "GPL" -#define ZC0301_MODULE_VERSION "1:1.02" -#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2) +#define ZC0301_MODULE_VERSION "1:1.03" +#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 3) /*****************************************************************************/ @@ -637,7 +637,6 @@ static void zc0301_release_resources(struct zc0301_device* cam) DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); - usb_put_dev(cam->usbdev); kfree(cam->control_buffer); } @@ -727,6 +726,7 @@ static int zc0301_release(struct inode* inode, struct file* filp) if (cam->state & DEV_DISCONNECTED) { zc0301_release_resources(cam); + usb_put_dev(cam->usbdev); mutex_unlock(&cam->dev_mutex); kfree(cam); return 0; diff --git a/drivers/usb/media/zc0301_sensor.h b/drivers/usb/media/zc0301_sensor.h index e3cb6cc920ca..cf0965a81d01 100644 --- a/drivers/usb/media/zc0301_sensor.h +++ b/drivers/usb/media/zc0301_sensor.h @@ -58,14 +58,14 @@ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); #define ZC0301_ID_TABLE \ static const struct usb_device_id zc0301_id_table[] = { \ - { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \ - { ZC0301_USB_DEVICE(0x041e, 0x0417, 0xff), }, \ - { ZC0301_USB_DEVICE(0x041e, 0x041e, 0xff), }, /* HV7131B */ \ - { ZC0301_USB_DEVICE(0x041e, 0x081c, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x0834, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x0835, 0xff), }, /* PAS106 */ \ + { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, \ + { ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */ \ + { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131B */ \ + { ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */ \ + { ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */ \ { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \ { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \ + { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \ { } \ }; -- cgit v1.2.3-59-g8ed1b From f88f8295d8a9229fc8b647baf4f15959384d7bb7 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 10 Mar 2006 23:25:06 +0100 Subject: [PATCH] USB: vicam.c: fix a NULL pointer dereference This patch fixes a NULL pointer dereference spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/media/vicam.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c index 8cfc47b831fb..1d06e53ec7c5 100644 --- a/drivers/usb/media/vicam.c +++ b/drivers/usb/media/vicam.c @@ -764,6 +764,7 @@ vicam_open(struct inode *inode, struct file *file) if (!cam) { printk(KERN_ERR "vicam video_device improperly initialized"); + return -EINVAL; } /* the videodev_lock held above us protects us from -- cgit v1.2.3-59-g8ed1b From 24f8b116c45e46779dec553f934c3d74f79c06fb Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sat, 11 Mar 2006 00:16:55 -0800 Subject: [PATCH] USB: fix check_ctrlrecip to allow control transfers in state ADDRESS check_ctrlrecip() disallows any control transfers if the device is deconfigured (in configuration 0, ie. state ADDRESS). This for example makes it impossible to read the device descriptors without configuring the device, although most standard device requests are allowed in this state by the spec. This patch allows control transfers for the ADDRESS state, too. Signed-off-by: Horst Schirmeier Cc: Alan Stern Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index de6a7c07cf97..545da37afca7 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -493,7 +493,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig { int ret = 0; - if (ps->dev->state != USB_STATE_CONFIGURED) + if (ps->dev->state != USB_STATE_ADDRESS + && ps->dev->state != USB_STATE_CONFIGURED) return -EHOSTUNREACH; if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) return 0; -- cgit v1.2.3-59-g8ed1b From 59224f5352542b968c41200954e56c26c4f0a075 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Sat, 11 Mar 2006 11:29:02 +0000 Subject: [PATCH] USB: cp2101: add new device IDs This patch adds a new device ID to the cp2101 driver Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 9ea7b4a4a22b..e0c2acdb3f06 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -32,7 +32,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.06" +#define DRIVER_VERSION "v0.07" #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" /* @@ -58,6 +58,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ { 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, 0x807A) }, /* Crumb128 board */ { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ -- cgit v1.2.3-59-g8ed1b From bf58fbd5e86a43466e638407ff8a4eb7766a3b68 Mon Sep 17 00:00:00 2001 From: "A. Maitland Bottoms" Date: Tue, 14 Mar 2006 18:44:23 -0500 Subject: [PATCH] USB: ftdi_sio: add Icom ID1 USB product and vendor ids The Icom ID-1 1.2 GHz band digital transceiver is a new radio that has a USB interface. With this patch, the ftdi_sio driver will report "Detected FT8U232AM" and provide a serial device interface. Signed-off-by: "A. Maitland Bottoms" Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 7 +++++++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ece52a6328b5..f3af81b4dd29 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -492,6 +492,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) }, { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, + { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index bdef3b8c731f..8da773c2744d 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -145,6 +145,13 @@ #define KOBIL_CONV_B1_PID 0x2020 /* KOBIL Konverter for B1 */ #define KOBIL_CONV_KAAN_PID 0x2021 /* KOBIL_Konverter for KAAN */ +/* + * Icom ID-1 digital transceiver + */ + +#define ICOM_ID1_VID 0x0C26 +#define ICOM_ID1_PID 0x0004 + /* * DSS-20 Sync Station for Sony Ericsson P800 */ -- cgit v1.2.3-59-g8ed1b From 09abfa8048de8e68eaa09eb07ac18f2d549dfe58 Mon Sep 17 00:00:00 2001 From: Petko Manolov Date: Wed, 15 Mar 2006 16:29:38 +0200 Subject: [PATCH] USB: rtl8150 small fix This one is about announcing the device registration after the last check has been made. From: Petko Manolov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/rtl8150.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index 8ca52be23976..1bbbae283c0b 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c @@ -880,7 +880,6 @@ static int rtl8150_probe(struct usb_interface *intf, } fill_skb_pool(dev); set_ethernet_addr(dev); - info("%s: rtl8150 is detected", netdev->name); usb_set_intfdata(intf, dev); SET_NETDEV_DEV(netdev, &intf->dev); @@ -888,6 +887,9 @@ static int rtl8150_probe(struct usb_interface *intf, err("couldn't register the device"); goto out2; } + + info("%s: rtl8150 is detected", netdev->name); + return 0; out2: -- cgit v1.2.3-59-g8ed1b From da81817fbd744ce70983f1d3c61841265003c7f4 Mon Sep 17 00:00:00 2001 From: Eugene Teo Date: Wed, 15 Mar 2006 14:57:19 -0800 Subject: [PATCH] USB: Fix irda-usb use after use Don't read from free'd memory after calling netif_rx(). docopy is used as a boolean (0 and 1) so unsigned int is sufficient. Coverity bug #928 Signed-off-by: Eugene Teo Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/net/irda/irda-usb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 8936058a3cce..6e2ec56cde0b 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -740,7 +740,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) struct sk_buff *newskb; struct sk_buff *dataskb; struct urb *next_urb; - int docopy; + unsigned int len, docopy; IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length); @@ -851,10 +851,11 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) dataskb->dev = self->netdev; dataskb->mac.raw = dataskb->data; dataskb->protocol = htons(ETH_P_IRDA); + len = dataskb->len; netif_rx(dataskb); /* Keep stats up to date */ - self->stats.rx_bytes += dataskb->len; + self->stats.rx_bytes += len; self->stats.rx_packets++; self->netdev->last_rx = jiffies; -- cgit v1.2.3-59-g8ed1b From e9a66c64bb7033cb0180d419b2008acf7a141adc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Mar 2006 17:40:08 -0800 Subject: [PATCH] USB serial: add navman driver Thanks to Warren Lewis for the information needed to write the driver and for testing it out. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 7 ++ drivers/usb/serial/Makefile | 1 + drivers/usb/serial/navman.c | 157 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 drivers/usb/serial/navman.c (limited to 'drivers') diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index be5dc80836c3..5a8a2c91c2b2 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -403,6 +403,13 @@ config USB_SERIAL_MCT_U232 To compile this driver as a module, choose M here: the module will be called mct_u232. +config USB_SERIAL_NAVMAN + tristate "USB Navman GPS device" + depends on USB_SERIAL + help + To compile this driver as a module, choose M here: the + module will be called navman. + config USB_SERIAL_PL2303 tristate "USB Prolific 2303 Single Port Serial Driver" depends on USB_SERIAL diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index f0b04420cea1..f7fe4172efed 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o +obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o obj-$(CONFIG_USB_SERIAL_OPTION) += option.o obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c new file mode 100644 index 000000000000..7f544081032e --- /dev/null +++ b/drivers/usb/serial/navman.c @@ -0,0 +1,157 @@ +/* + * Navman Serial USB driver + * + * Copyright (C) 2006 Greg Kroah-Hartman + * + * 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 +#include +#include +#include +#include "usb-serial.h" + +static int debug; + +static struct usb_device_id id_table [] = { + { USB_DEVICE(0x0a99, 0x0001) }, /* Talon Technology device */ + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver navman_driver = { + .name = "navman", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + +static void navman_read_int_callback(struct urb *urb, struct pt_regs *regs) +{ + struct usb_serial_port *port = urb->context; + unsigned char *data = urb->transfer_buffer; + struct tty_struct *tty; + int result; + + switch (urb->status) { + case 0: + /* success */ + break; + 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; + } + + usb_serial_debug_data(debug, &port->dev, __FUNCTION__, + urb->actual_length, data); + + tty = port->tty; + if (tty && urb->actual_length) { + tty_buffer_request_room(tty, urb->actual_length); + tty_insert_flip_string(tty, data, urb->actual_length); + tty_flip_buffer_push(tty); + } + +exit: + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) + dev_err(&urb->dev->dev, + "%s - Error %d submitting interrupt urb\n", + __FUNCTION__, result); +} + +static int navman_open(struct usb_serial_port *port, struct file *filp) +{ + int result = 0; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (port->interrupt_in_urb) { + dbg("%s - adding interrupt input for treo", __FUNCTION__); + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (result) + dev_err(&port->dev, + "%s - failed submitting interrupt urb, error %d\n", + __FUNCTION__, result); + } + return result; +} + +static void navman_close(struct usb_serial_port *port, struct file *filp) +{ + dbg("%s - port %d", __FUNCTION__, port->number); + + if (port->interrupt_in_urb) + usb_kill_urb(port->interrupt_in_urb); +} + +static int navman_write(struct usb_serial_port *port, + const unsigned char *buf, int count) +{ + dbg("%s - port %d", __FUNCTION__, port->number); + + /* + * This device can't write any data, only read from the device + * so we just silently eat all data sent to us and say it was + * successfully sent. + * Evil, I know, but do you have a better idea? + */ + + return count; +} + +static struct usb_serial_driver navman_device = { + .driver = { + .owner = THIS_MODULE, + .name = "navman", + }, + .id_table = id_table, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 1, + .open = navman_open, + .close = navman_close, + .write = navman_write, + .read_int_callback = navman_read_int_callback, +}; + +static int __init navman_init(void) +{ + int retval; + + retval = usb_serial_register(&navman_device); + if (retval) + return retval; + retval = usb_register(&navman_driver); + if (retval) + usb_serial_deregister(&navman_device); + return retval; +} + +static void __exit navman_exit(void) +{ + usb_deregister(&navman_driver); + usb_serial_deregister(&navman_device); +} + +module_init(navman_init); +module_exit(navman_exit); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v1.2.3-59-g8ed1b From 71a8924bee63d891f6256d560e32416a458440b3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Mar 2006 17:28:39 -0500 Subject: [PATCH] USB: omninet: fix up debugging comments Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/omninet.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 762d8ff9a1e4..4d40704dea2c 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -204,7 +204,7 @@ static void omninet_read_bulk_callback (struct urb *urb, struct pt_regs *regs) int i; int result; -// dbg("omninet_read_bulk_callback"); + dbg("%s - port %d", __FUNCTION__, port->number); if (urb->status) { dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); @@ -250,7 +250,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf int result; -// dbg("omninet_write port %d", port->number); + dbg("%s - port %d", __FUNCTION__, port->number); if (count == 0) { dbg("%s - write request of 0 bytes", __FUNCTION__); @@ -302,7 +302,7 @@ static int omninet_write_room (struct usb_serial_port *port) if (wport->write_urb_busy) room = wport->bulk_out_size - OMNINET_HEADERLEN; -// dbg("omninet_write_room returns %d", room); + dbg("%s - returns %d", __FUNCTION__, room); return (room); } @@ -312,7 +312,7 @@ static void omninet_write_bulk_callback (struct urb *urb, struct pt_regs *regs) /* struct omninet_header *header = (struct omninet_header *) urb->transfer_buffer; */ struct usb_serial_port *port = (struct usb_serial_port *) urb->context; -// dbg("omninet_write_bulk_callback, port %0x\n", port); + dbg("%s - port %0x\n", __FUNCTION__, port->number); port->write_urb_busy = 0; if (urb->status) { @@ -321,8 +321,6 @@ static void omninet_write_bulk_callback (struct urb *urb, struct pt_regs *regs) } schedule_work(&port->work); - -// dbg("omninet_write_bulk_callback, tty %0x\n", tty); } -- cgit v1.2.3-59-g8ed1b From cd85f6e2f58282186ad720fc18482be228f0b972 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 20 Mar 2006 19:49:54 -0500 Subject: [libata] sata_mv: fix irq port status usage Interrupt handler did not properly initialize a variable on a per-port basis, leading to incorrect behavior on ports other than port 0. Bug caught and fixed by Mark Lord. Signed-off-by: Jeff Garzik --- drivers/scsi/sata_mv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index aceaf56999a5..e561281967dd 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1353,7 +1353,6 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, u32 hc_irq_cause; int shift, port, port0, hard_port, handled; unsigned int err_mask; - u8 ata_status = 0; if (hc == 0) { port0 = 0; @@ -1371,6 +1370,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, hc,relevant,hc_irq_cause); for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { + u8 ata_status = 0; ap = host_set->ports[port]; hard_port = port & MV_PORT_MASK; /* range 0-3 */ handled = 0; /* ensure ata_status is set if handled++ */ -- cgit v1.2.3-59-g8ed1b From d4d2c558fd3e1f5e386b153f194aa8f0be496c77 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:47:20 -0800 Subject: [TG3]: Add support for 5714S and 5715S Add support for 5714S and 5715S. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 35 ++++++++++++++++++++++++++++++++++- include/linux/pci_ids.h | 2 ++ 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 6c6c5498899f..b0de6b2754cc 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -223,8 +223,12 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S, @@ -2680,6 +2684,12 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) err |= tg3_readphy(tp, MII_BMSR, &bmsr); err |= tg3_readphy(tp, MII_BMSR, &bmsr); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { + if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP) + bmsr |= BMSR_LSTATUS; + else + bmsr &= ~BMSR_LSTATUS; + } err |= tg3_readphy(tp, MII_BMCR, &bmcr); @@ -2748,6 +2758,13 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) bmcr = new_bmcr; err |= tg3_readphy(tp, MII_BMSR, &bmsr); err |= tg3_readphy(tp, MII_BMSR, &bmsr); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == + ASIC_REV_5714) { + if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP) + bmsr |= BMSR_LSTATUS; + else + bmsr &= ~BMSR_LSTATUS; + } tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; } } @@ -5585,6 +5602,9 @@ static int tg3_reset_hw(struct tg3 *tp) tg3_abort_hw(tp, 1); } + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + tg3_phy_reset(tp); + err = tg3_chip_reset(tp); if (err) return err; @@ -6097,6 +6117,17 @@ static int tg3_reset_hw(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG; } + if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) { + u32 tmp; + + tmp = tr32(SERDES_RX_CTRL); + tw32(SERDES_RX_CTRL, tmp | SERDES_RX_SIG_DETECT); + tp->grc_local_ctrl &= ~GRC_LCLCTRL_USE_EXT_SIG_DETECT; + tp->grc_local_ctrl |= GRC_LCLCTRL_USE_SIG_DETECT; + tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); + } + err = tg3_setup_phy(tp, 1); if (err) return err; @@ -6476,7 +6507,9 @@ static int tg3_open(struct net_device *dev) if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) && - (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX)) { + (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX) && + !((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) && + (tp->pdev_peer == tp->pdev))) { /* All MSI supporting chips should support tagged * status. Assert that this is the case. */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 751eea58bde8..a3a09cceb026 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1857,12 +1857,14 @@ #define PCI_DEVICE_ID_TIGON3_5705M 0x165d #define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e #define PCI_DEVICE_ID_TIGON3_5714 0x1668 +#define PCI_DEVICE_ID_TIGON3_5714S 0x1669 #define PCI_DEVICE_ID_TIGON3_5780 0x166a #define PCI_DEVICE_ID_TIGON3_5780S 0x166b #define PCI_DEVICE_ID_TIGON3_5705F 0x166e #define PCI_DEVICE_ID_TIGON3_5750 0x1676 #define PCI_DEVICE_ID_TIGON3_5751 0x1677 #define PCI_DEVICE_ID_TIGON3_5715 0x1678 +#define PCI_DEVICE_ID_TIGON3_5715S 0x1679 #define PCI_DEVICE_ID_TIGON3_5750M 0x167c #define PCI_DEVICE_ID_TIGON3_5751M 0x167d #define PCI_DEVICE_ID_TIGON3_5751F 0x167e -- cgit v1.2.3-59-g8ed1b From 4e3a7aaa28db952392814f889dfbd25672266d29 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:47:44 -0800 Subject: [TG3]: Enable TSO by default Enable TSO by default on newer chips that support TSO in hardware. Leave TSO off by default on older chips that do firmware TSO because performance is slightly lower. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b0de6b2754cc..7deebd74223e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10881,11 +10881,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; } - /* TSO is off by default, user can enable using ethtool. */ -#if 0 - if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) + /* TSO is on by default on chips that support hardware TSO. + * Firmware TSO on older chips gives lower performance, so it + * is off by default, but can be enabled using ethtool. + */ + if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) dev->features |= NETIF_F_TSO; -#endif #endif -- cgit v1.2.3-59-g8ed1b From bc1c756741b065cfebf850e4164c0e2aae9d527f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:48:03 -0800 Subject: [TG3]: Support shutdown WoL. Support WoL during shutdown by calling tg3_set_power_state(tp, PCI_D3hot) during tg3_close(). Change the power state parameter to pci_power_t type and use constants defined in pci.h. Certain ethtool operations cannot be performed after tg3_close() because the device will go to low power state. Add return -EAGAIN in such cases where appropriate. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 52 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7deebd74223e..01fed17d076f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1042,9 +1042,11 @@ static void tg3_frob_aux_power(struct tg3 *tp) struct net_device *dev_peer; dev_peer = pci_get_drvdata(tp->pdev_peer); + /* remove_one() may have been run on the peer. */ if (!dev_peer) - BUG(); - tp_peer = netdev_priv(dev_peer); + tp_peer = tp; + else + tp_peer = netdev_priv(dev_peer); } if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 || @@ -1135,7 +1137,7 @@ static int tg3_halt_cpu(struct tg3 *, u32); static int tg3_nvram_lock(struct tg3 *); static void tg3_nvram_unlock(struct tg3 *); -static int tg3_set_power_state(struct tg3 *tp, int state) +static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) { u32 misc_host_ctrl; u16 power_control, power_caps; @@ -1154,7 +1156,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state) power_control |= PCI_PM_CTRL_PME_STATUS; power_control &= ~(PCI_PM_CTRL_STATE_MASK); switch (state) { - case 0: + case PCI_D0: power_control |= 0; pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, @@ -1167,15 +1169,15 @@ static int tg3_set_power_state(struct tg3 *tp, int state) return 0; - case 1: + case PCI_D1: power_control |= 1; break; - case 2: + case PCI_D2: power_control |= 2; break; - case 3: + case PCI_D3hot: power_control |= 3; break; @@ -6206,7 +6208,7 @@ static int tg3_init_hw(struct tg3 *tp) int err; /* Force the chip into D0. */ - err = tg3_set_power_state(tp, 0); + err = tg3_set_power_state(tp, PCI_D0); if (err) goto out; @@ -6493,6 +6495,10 @@ static int tg3_open(struct net_device *dev) tg3_full_lock(tp, 0); + err = tg3_set_power_state(tp, PCI_D0); + if (err) + return err; + tg3_disable_ints(tp); tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; @@ -6872,7 +6878,6 @@ static int tg3_close(struct net_device *dev) tp->tg3_flags &= ~(TG3_FLAG_INIT_COMPLETE | TG3_FLAG_GOT_SERDES_FLOWCTL); - netif_carrier_off(tp->dev); tg3_full_unlock(tp); @@ -6889,6 +6894,10 @@ static int tg3_close(struct net_device *dev) tg3_free_consistent(tp); + tg3_set_power_state(tp, PCI_D3hot); + + netif_carrier_off(tp->dev); + return 0; } @@ -7207,6 +7216,9 @@ static void tg3_get_regs(struct net_device *dev, memset(p, 0, TG3_REGDUMP_LEN); + if (tp->link_config.phy_is_low_power) + return; + tg3_full_lock(tp, 0); #define __GET_REG32(reg) (*(p)++ = tr32(reg)) @@ -7281,6 +7293,9 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *pd; u32 i, offset, len, val, b_offset, b_count; + if (tp->link_config.phy_is_low_power) + return -EAGAIN; + offset = eeprom->offset; len = eeprom->len; eeprom->len = 0; @@ -7342,6 +7357,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u32 offset, len, b_offset, odd_len, start, end; u8 *buf; + if (tp->link_config.phy_is_low_power) + return -EAGAIN; + if (eeprom->magic != TG3_EEPROM_MAGIC) return -EINVAL; @@ -8262,6 +8280,9 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, { struct tg3 *tp = netdev_priv(dev); + if (tp->link_config.phy_is_low_power) + tg3_set_power_state(tp, PCI_D0); + memset(data, 0, sizeof(u64) * TG3_NUM_TEST); if (tg3_test_nvram(tp) != 0) { @@ -8319,6 +8340,9 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, tg3_full_unlock(tp); } + if (tp->link_config.phy_is_low_power) + tg3_set_power_state(tp, PCI_D3hot); + } static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) @@ -8338,6 +8362,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) break; /* We have no PHY */ + if (tp->link_config.phy_is_low_power) + return -EAGAIN; + spin_lock_bh(&tp->lock); err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval); spin_unlock_bh(&tp->lock); @@ -8354,6 +8381,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (tp->link_config.phy_is_low_power) + return -EAGAIN; + spin_lock_bh(&tp->lock); err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in); spin_unlock_bh(&tp->lock); @@ -9805,7 +9835,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; /* Force the chip into D0. */ - err = tg3_set_power_state(tp, 0); + err = tg3_set_power_state(tp, PCI_D0); if (err) { printk(KERN_ERR PFX "(%s) transition to D0 failed\n", pci_name(tp->pdev)); @@ -11078,7 +11108,7 @@ static int tg3_resume(struct pci_dev *pdev) pci_restore_state(tp->pdev); - err = tg3_set_power_state(tp, 0); + err = tg3_set_power_state(tp, PCI_D0); if (err) return err; -- cgit v1.2.3-59-g8ed1b From 2e2e4f5c996d577383c5cb584b153b39f4961155 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:48:18 -0800 Subject: [TG3]: Update version and reldate Update version to 3.50. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 01fed17d076f..994658d26b8e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.49" -#define DRV_MODULE_RELDATE "Feb 2, 2006" +#define DRV_MODULE_VERSION "3.50" +#define DRV_MODULE_RELDATE "Feb 4, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3-59-g8ed1b From 6b39777c5924b9db2406c5769a044da383782d0e Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:48:32 -0800 Subject: [BNX2]: Reduce register test size Eliminate some of the registers in ethtool register test to reduce driver size. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 254 ----------------------------------------------------- 1 file changed, 254 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index b787b6582e50..4be21b8501bf 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3506,74 +3506,9 @@ bnx2_test_registers(struct bnx2 *bp) { 0x0c00, 0, 0x00000000, 0x00000001 }, { 0x0c04, 0, 0x00000000, 0x03ff0001 }, { 0x0c08, 0, 0x0f0ff073, 0x00000000 }, - { 0x0c0c, 0, 0x00ffffff, 0x00000000 }, - { 0x0c30, 0, 0x00000000, 0xffffffff }, - { 0x0c34, 0, 0x00000000, 0xffffffff }, - { 0x0c38, 0, 0x00000000, 0xffffffff }, - { 0x0c3c, 0, 0x00000000, 0xffffffff }, - { 0x0c40, 0, 0x00000000, 0xffffffff }, - { 0x0c44, 0, 0x00000000, 0xffffffff }, - { 0x0c48, 0, 0x00000000, 0x0007ffff }, - { 0x0c4c, 0, 0x00000000, 0xffffffff }, - { 0x0c50, 0, 0x00000000, 0xffffffff }, - { 0x0c54, 0, 0x00000000, 0xffffffff }, - { 0x0c58, 0, 0x00000000, 0xffffffff }, - { 0x0c5c, 0, 0x00000000, 0xffffffff }, - { 0x0c60, 0, 0x00000000, 0xffffffff }, - { 0x0c64, 0, 0x00000000, 0xffffffff }, - { 0x0c68, 0, 0x00000000, 0xffffffff }, - { 0x0c6c, 0, 0x00000000, 0xffffffff }, - { 0x0c70, 0, 0x00000000, 0xffffffff }, - { 0x0c74, 0, 0x00000000, 0xffffffff }, - { 0x0c78, 0, 0x00000000, 0xffffffff }, - { 0x0c7c, 0, 0x00000000, 0xffffffff }, - { 0x0c80, 0, 0x00000000, 0xffffffff }, - { 0x0c84, 0, 0x00000000, 0xffffffff }, - { 0x0c88, 0, 0x00000000, 0xffffffff }, - { 0x0c8c, 0, 0x00000000, 0xffffffff }, - { 0x0c90, 0, 0x00000000, 0xffffffff }, - { 0x0c94, 0, 0x00000000, 0xffffffff }, - { 0x0c98, 0, 0x00000000, 0xffffffff }, - { 0x0c9c, 0, 0x00000000, 0xffffffff }, - { 0x0ca0, 0, 0x00000000, 0xffffffff }, - { 0x0ca4, 0, 0x00000000, 0xffffffff }, - { 0x0ca8, 0, 0x00000000, 0x0007ffff }, - { 0x0cac, 0, 0x00000000, 0xffffffff }, - { 0x0cb0, 0, 0x00000000, 0xffffffff }, - { 0x0cb4, 0, 0x00000000, 0xffffffff }, - { 0x0cb8, 0, 0x00000000, 0xffffffff }, - { 0x0cbc, 0, 0x00000000, 0xffffffff }, - { 0x0cc0, 0, 0x00000000, 0xffffffff }, - { 0x0cc4, 0, 0x00000000, 0xffffffff }, - { 0x0cc8, 0, 0x00000000, 0xffffffff }, - { 0x0ccc, 0, 0x00000000, 0xffffffff }, - { 0x0cd0, 0, 0x00000000, 0xffffffff }, - { 0x0cd4, 0, 0x00000000, 0xffffffff }, - { 0x0cd8, 0, 0x00000000, 0xffffffff }, - { 0x0cdc, 0, 0x00000000, 0xffffffff }, - { 0x0ce0, 0, 0x00000000, 0xffffffff }, - { 0x0ce4, 0, 0x00000000, 0xffffffff }, - { 0x0ce8, 0, 0x00000000, 0xffffffff }, - { 0x0cec, 0, 0x00000000, 0xffffffff }, - { 0x0cf0, 0, 0x00000000, 0xffffffff }, - { 0x0cf4, 0, 0x00000000, 0xffffffff }, - { 0x0cf8, 0, 0x00000000, 0xffffffff }, - { 0x0cfc, 0, 0x00000000, 0xffffffff }, - { 0x0d00, 0, 0x00000000, 0xffffffff }, - { 0x0d04, 0, 0x00000000, 0xffffffff }, { 0x1000, 0, 0x00000000, 0x00000001 }, { 0x1004, 0, 0x00000000, 0x000f0001 }, - { 0x1044, 0, 0x00000000, 0xffc003ff }, - { 0x1080, 0, 0x00000000, 0x0001ffff }, - { 0x1084, 0, 0x00000000, 0xffffffff }, - { 0x1088, 0, 0x00000000, 0xffffffff }, - { 0x108c, 0, 0x00000000, 0xffffffff }, - { 0x1090, 0, 0x00000000, 0xffffffff }, - { 0x1094, 0, 0x00000000, 0xffffffff }, - { 0x1098, 0, 0x00000000, 0xffffffff }, - { 0x109c, 0, 0x00000000, 0xffffffff }, - { 0x10a0, 0, 0x00000000, 0xffffffff }, { 0x1408, 0, 0x01c00800, 0x00000000 }, { 0x149c, 0, 0x8000ffff, 0x00000000 }, @@ -3585,111 +3520,9 @@ bnx2_test_registers(struct bnx2 *bp) { 0x14c4, 0, 0x00003fff, 0x00000000 }, { 0x14cc, 0, 0x00000000, 0x00000001 }, { 0x14d0, 0, 0xffffffff, 0x00000000 }, - { 0x1500, 0, 0x00000000, 0xffffffff }, - { 0x1504, 0, 0x00000000, 0xffffffff }, - { 0x1508, 0, 0x00000000, 0xffffffff }, - { 0x150c, 0, 0x00000000, 0xffffffff }, - { 0x1510, 0, 0x00000000, 0xffffffff }, - { 0x1514, 0, 0x00000000, 0xffffffff }, - { 0x1518, 0, 0x00000000, 0xffffffff }, - { 0x151c, 0, 0x00000000, 0xffffffff }, - { 0x1520, 0, 0x00000000, 0xffffffff }, - { 0x1524, 0, 0x00000000, 0xffffffff }, - { 0x1528, 0, 0x00000000, 0xffffffff }, - { 0x152c, 0, 0x00000000, 0xffffffff }, - { 0x1530, 0, 0x00000000, 0xffffffff }, - { 0x1534, 0, 0x00000000, 0xffffffff }, - { 0x1538, 0, 0x00000000, 0xffffffff }, - { 0x153c, 0, 0x00000000, 0xffffffff }, - { 0x1540, 0, 0x00000000, 0xffffffff }, - { 0x1544, 0, 0x00000000, 0xffffffff }, - { 0x1548, 0, 0x00000000, 0xffffffff }, - { 0x154c, 0, 0x00000000, 0xffffffff }, - { 0x1550, 0, 0x00000000, 0xffffffff }, - { 0x1554, 0, 0x00000000, 0xffffffff }, - { 0x1558, 0, 0x00000000, 0xffffffff }, - { 0x1600, 0, 0x00000000, 0xffffffff }, - { 0x1604, 0, 0x00000000, 0xffffffff }, - { 0x1608, 0, 0x00000000, 0xffffffff }, - { 0x160c, 0, 0x00000000, 0xffffffff }, - { 0x1610, 0, 0x00000000, 0xffffffff }, - { 0x1614, 0, 0x00000000, 0xffffffff }, - { 0x1618, 0, 0x00000000, 0xffffffff }, - { 0x161c, 0, 0x00000000, 0xffffffff }, - { 0x1620, 0, 0x00000000, 0xffffffff }, - { 0x1624, 0, 0x00000000, 0xffffffff }, - { 0x1628, 0, 0x00000000, 0xffffffff }, - { 0x162c, 0, 0x00000000, 0xffffffff }, - { 0x1630, 0, 0x00000000, 0xffffffff }, - { 0x1634, 0, 0x00000000, 0xffffffff }, - { 0x1638, 0, 0x00000000, 0xffffffff }, - { 0x163c, 0, 0x00000000, 0xffffffff }, - { 0x1640, 0, 0x00000000, 0xffffffff }, - { 0x1644, 0, 0x00000000, 0xffffffff }, - { 0x1648, 0, 0x00000000, 0xffffffff }, - { 0x164c, 0, 0x00000000, 0xffffffff }, - { 0x1650, 0, 0x00000000, 0xffffffff }, - { 0x1654, 0, 0x00000000, 0xffffffff }, { 0x1800, 0, 0x00000000, 0x00000001 }, { 0x1804, 0, 0x00000000, 0x00000003 }, - { 0x1840, 0, 0x00000000, 0xffffffff }, - { 0x1844, 0, 0x00000000, 0xffffffff }, - { 0x1848, 0, 0x00000000, 0xffffffff }, - { 0x184c, 0, 0x00000000, 0xffffffff }, - { 0x1850, 0, 0x00000000, 0xffffffff }, - { 0x1900, 0, 0x7ffbffff, 0x00000000 }, - { 0x1904, 0, 0xffffffff, 0x00000000 }, - { 0x190c, 0, 0xffffffff, 0x00000000 }, - { 0x1914, 0, 0xffffffff, 0x00000000 }, - { 0x191c, 0, 0xffffffff, 0x00000000 }, - { 0x1924, 0, 0xffffffff, 0x00000000 }, - { 0x192c, 0, 0xffffffff, 0x00000000 }, - { 0x1934, 0, 0xffffffff, 0x00000000 }, - { 0x193c, 0, 0xffffffff, 0x00000000 }, - { 0x1944, 0, 0xffffffff, 0x00000000 }, - { 0x194c, 0, 0xffffffff, 0x00000000 }, - { 0x1954, 0, 0xffffffff, 0x00000000 }, - { 0x195c, 0, 0xffffffff, 0x00000000 }, - { 0x1964, 0, 0xffffffff, 0x00000000 }, - { 0x196c, 0, 0xffffffff, 0x00000000 }, - { 0x1974, 0, 0xffffffff, 0x00000000 }, - { 0x197c, 0, 0xffffffff, 0x00000000 }, - { 0x1980, 0, 0x0700ffff, 0x00000000 }, - - { 0x1c00, 0, 0x00000000, 0x00000001 }, - { 0x1c04, 0, 0x00000000, 0x00000003 }, - { 0x1c08, 0, 0x0000000f, 0x00000000 }, - { 0x1c40, 0, 0x00000000, 0xffffffff }, - { 0x1c44, 0, 0x00000000, 0xffffffff }, - { 0x1c48, 0, 0x00000000, 0xffffffff }, - { 0x1c4c, 0, 0x00000000, 0xffffffff }, - { 0x1c50, 0, 0x00000000, 0xffffffff }, - { 0x1d00, 0, 0x7ffbffff, 0x00000000 }, - { 0x1d04, 0, 0xffffffff, 0x00000000 }, - { 0x1d0c, 0, 0xffffffff, 0x00000000 }, - { 0x1d14, 0, 0xffffffff, 0x00000000 }, - { 0x1d1c, 0, 0xffffffff, 0x00000000 }, - { 0x1d24, 0, 0xffffffff, 0x00000000 }, - { 0x1d2c, 0, 0xffffffff, 0x00000000 }, - { 0x1d34, 0, 0xffffffff, 0x00000000 }, - { 0x1d3c, 0, 0xffffffff, 0x00000000 }, - { 0x1d44, 0, 0xffffffff, 0x00000000 }, - { 0x1d4c, 0, 0xffffffff, 0x00000000 }, - { 0x1d54, 0, 0xffffffff, 0x00000000 }, - { 0x1d5c, 0, 0xffffffff, 0x00000000 }, - { 0x1d64, 0, 0xffffffff, 0x00000000 }, - { 0x1d6c, 0, 0xffffffff, 0x00000000 }, - { 0x1d74, 0, 0xffffffff, 0x00000000 }, - { 0x1d7c, 0, 0xffffffff, 0x00000000 }, - { 0x1d80, 0, 0x0700ffff, 0x00000000 }, - - { 0x2004, 0, 0x00000000, 0x0337000f }, - { 0x2008, 0, 0xffffffff, 0x00000000 }, - { 0x200c, 0, 0xffffffff, 0x00000000 }, - { 0x2010, 0, 0xffffffff, 0x00000000 }, - { 0x2014, 0, 0x801fff80, 0x00000000 }, - { 0x2018, 0, 0x000003ff, 0x00000000 }, { 0x2800, 0, 0x00000000, 0x00000001 }, { 0x2804, 0, 0x00000000, 0x00003f01 }, @@ -3707,16 +3540,6 @@ bnx2_test_registers(struct bnx2 *bp) { 0x2c00, 0, 0x00000000, 0x00000011 }, { 0x2c04, 0, 0x00000000, 0x00030007 }, - { 0x3000, 0, 0x00000000, 0x00000001 }, - { 0x3004, 0, 0x00000000, 0x007007ff }, - { 0x3008, 0, 0x00000003, 0x00000000 }, - { 0x300c, 0, 0xffffffff, 0x00000000 }, - { 0x3010, 0, 0xffffffff, 0x00000000 }, - { 0x3014, 0, 0xffffffff, 0x00000000 }, - { 0x3034, 0, 0xffffffff, 0x00000000 }, - { 0x3038, 0, 0xffffffff, 0x00000000 }, - { 0x3050, 0, 0x00000001, 0x00000000 }, - { 0x3c00, 0, 0x00000000, 0x00000001 }, { 0x3c04, 0, 0x00000000, 0x00070000 }, { 0x3c08, 0, 0x00007f71, 0x07f00000 }, @@ -3726,88 +3549,11 @@ bnx2_test_registers(struct bnx2 *bp) { 0x3c18, 0, 0x00000000, 0xffffffff }, { 0x3c1c, 0, 0xfffff000, 0x00000000 }, { 0x3c20, 0, 0xffffff00, 0x00000000 }, - { 0x3c24, 0, 0xffffffff, 0x00000000 }, - { 0x3c28, 0, 0xffffffff, 0x00000000 }, - { 0x3c2c, 0, 0xffffffff, 0x00000000 }, - { 0x3c30, 0, 0xffffffff, 0x00000000 }, - { 0x3c34, 0, 0xffffffff, 0x00000000 }, - { 0x3c38, 0, 0xffffffff, 0x00000000 }, - { 0x3c3c, 0, 0xffffffff, 0x00000000 }, - { 0x3c40, 0, 0xffffffff, 0x00000000 }, - { 0x3c44, 0, 0xffffffff, 0x00000000 }, - { 0x3c48, 0, 0xffffffff, 0x00000000 }, - { 0x3c4c, 0, 0xffffffff, 0x00000000 }, - { 0x3c50, 0, 0xffffffff, 0x00000000 }, - { 0x3c54, 0, 0xffffffff, 0x00000000 }, - { 0x3c58, 0, 0xffffffff, 0x00000000 }, - { 0x3c5c, 0, 0xffffffff, 0x00000000 }, - { 0x3c60, 0, 0xffffffff, 0x00000000 }, - { 0x3c64, 0, 0xffffffff, 0x00000000 }, - { 0x3c68, 0, 0xffffffff, 0x00000000 }, - { 0x3c6c, 0, 0xffffffff, 0x00000000 }, - { 0x3c70, 0, 0xffffffff, 0x00000000 }, - { 0x3c74, 0, 0x0000003f, 0x00000000 }, - { 0x3c78, 0, 0x00000000, 0x00000000 }, - { 0x3c7c, 0, 0x00000000, 0x00000000 }, - { 0x3c80, 0, 0x3fffffff, 0x00000000 }, - { 0x3c84, 0, 0x0000003f, 0x00000000 }, - { 0x3c88, 0, 0x00000000, 0xffffffff }, - { 0x3c8c, 0, 0x00000000, 0xffffffff }, - - { 0x4000, 0, 0x00000000, 0x00000001 }, - { 0x4004, 0, 0x00000000, 0x00030000 }, - { 0x4008, 0, 0x00000ff0, 0x00000000 }, - { 0x400c, 0, 0xffffffff, 0x00000000 }, - { 0x4088, 0, 0x00000000, 0x00070303 }, - - { 0x4400, 0, 0x00000000, 0x00000001 }, - { 0x4404, 0, 0x00000000, 0x00003f01 }, - { 0x4408, 0, 0x7fff00ff, 0x00000000 }, - { 0x440c, 0, 0xffffffff, 0x00000000 }, - { 0x4410, 0, 0xffff, 0x0000 }, - { 0x4414, 0, 0xffff, 0x0000 }, - { 0x4418, 0, 0xffff, 0x0000 }, - { 0x441c, 0, 0xffff, 0x0000 }, - { 0x4428, 0, 0xffffffff, 0x00000000 }, - { 0x442c, 0, 0xffffffff, 0x00000000 }, - { 0x4430, 0, 0xffffffff, 0x00000000 }, - { 0x4434, 0, 0xffffffff, 0x00000000 }, - { 0x4438, 0, 0xffffffff, 0x00000000 }, - { 0x443c, 0, 0xffffffff, 0x00000000 }, - { 0x4440, 0, 0xffffffff, 0x00000000 }, - { 0x4444, 0, 0xffffffff, 0x00000000 }, - - { 0x4c00, 0, 0x00000000, 0x00000001 }, - { 0x4c04, 0, 0x00000000, 0x0000003f }, - { 0x4c08, 0, 0xffffffff, 0x00000000 }, - { 0x4c0c, 0, 0x0007fc00, 0x00000000 }, - { 0x4c10, 0, 0x80003fe0, 0x00000000 }, - { 0x4c14, 0, 0xffffffff, 0x00000000 }, - { 0x4c44, 0, 0x00000000, 0x9fff9fff }, - { 0x4c48, 0, 0x00000000, 0xb3009fff }, - { 0x4c4c, 0, 0x00000000, 0x77f33b30 }, - { 0x4c50, 0, 0x00000000, 0xffffffff }, { 0x5004, 0, 0x00000000, 0x0000007f }, { 0x5008, 0, 0x0f0007ff, 0x00000000 }, { 0x500c, 0, 0xf800f800, 0x07ff07ff }, - { 0x5400, 0, 0x00000008, 0x00000001 }, - { 0x5404, 0, 0x00000000, 0x0000003f }, - { 0x5408, 0, 0x0000001f, 0x00000000 }, - { 0x540c, 0, 0xffffffff, 0x00000000 }, - { 0x5410, 0, 0xffffffff, 0x00000000 }, - { 0x5414, 0, 0x0000ffff, 0x00000000 }, - { 0x5418, 0, 0x0000ffff, 0x00000000 }, - { 0x541c, 0, 0x0000ffff, 0x00000000 }, - { 0x5420, 0, 0x0000ffff, 0x00000000 }, - { 0x5428, 0, 0x000000ff, 0x00000000 }, - { 0x542c, 0, 0xff00ffff, 0x00000000 }, - { 0x5430, 0, 0x001fff80, 0x00000000 }, - { 0x5438, 0, 0xffffffff, 0x00000000 }, - { 0x543c, 0, 0xffffffff, 0x00000000 }, - { 0x5440, 0, 0xf800f800, 0x07ff07ff }, - { 0x5c00, 0, 0x00000000, 0x00000001 }, { 0x5c04, 0, 0x00000000, 0x0003000f }, { 0x5c08, 0, 0x00000003, 0x00000000 }, -- cgit v1.2.3-59-g8ed1b From 244ac4f446ac6a19caf5eb692c4844f29e6478bf Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:48:46 -0800 Subject: [BNX2]: Add ethtool -d support Add ETHTOOL_GREGS support. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 4be21b8501bf..6fbb5486163d 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -4540,6 +4540,64 @@ bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) info->fw_version[5] = 0; } +#define BNX2_REGDUMP_LEN (32 * 1024) + +static int +bnx2_get_regs_len(struct net_device *dev) +{ + return BNX2_REGDUMP_LEN; +} + +static void +bnx2_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p) +{ + u32 *p = _p, i, offset; + u8 *orig_p = _p; + struct bnx2 *bp = netdev_priv(dev); + u32 reg_boundaries[] = { 0x0000, 0x0098, 0x0400, 0x045c, + 0x0800, 0x0880, 0x0c00, 0x0c10, + 0x0c30, 0x0d08, 0x1000, 0x101c, + 0x1040, 0x1048, 0x1080, 0x10a4, + 0x1400, 0x1490, 0x1498, 0x14f0, + 0x1500, 0x155c, 0x1580, 0x15dc, + 0x1600, 0x1658, 0x1680, 0x16d8, + 0x1800, 0x1820, 0x1840, 0x1854, + 0x1880, 0x1894, 0x1900, 0x1984, + 0x1c00, 0x1c0c, 0x1c40, 0x1c54, + 0x1c80, 0x1c94, 0x1d00, 0x1d84, + 0x2000, 0x2030, 0x23c0, 0x2400, + 0x2800, 0x2820, 0x2830, 0x2850, + 0x2b40, 0x2c10, 0x2fc0, 0x3058, + 0x3c00, 0x3c94, 0x4000, 0x4010, + 0x4080, 0x4090, 0x43c0, 0x4458, + 0x4c00, 0x4c18, 0x4c40, 0x4c54, + 0x4fc0, 0x5010, 0x53c0, 0x5444, + 0x5c00, 0x5c18, 0x5c80, 0x5c90, + 0x5fc0, 0x6000, 0x6400, 0x6428, + 0x6800, 0x6848, 0x684c, 0x6860, + 0x6888, 0x6910, 0x8000 }; + + regs->version = 0; + + memset(p, 0, BNX2_REGDUMP_LEN); + + if (!netif_running(bp->dev)) + return; + + i = 0; + offset = reg_boundaries[0]; + p += offset; + while (offset < BNX2_REGDUMP_LEN) { + *p++ = REG_RD(bp, offset); + offset += 4; + if (offset == reg_boundaries[i + 1]) { + offset = reg_boundaries[i + 2]; + p = (u32 *) (orig_p + offset); + i += 2; + } + } +} + static void bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { @@ -5106,6 +5164,8 @@ static struct ethtool_ops bnx2_ethtool_ops = { .get_settings = bnx2_get_settings, .set_settings = bnx2_set_settings, .get_drvinfo = bnx2_get_drvinfo, + .get_regs_len = bnx2_get_regs_len, + .get_regs = bnx2_get_regs, .get_wol = bnx2_get_wol, .set_wol = bnx2_set_wol, .nway_reset = bnx2_nway_reset, -- cgit v1.2.3-59-g8ed1b From 236b6394bb49ea58465c6f935a286d2342576f8d Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:49:02 -0800 Subject: [BNX2]: Fix bug when rx ring is full Fix the rx code path that does not handle the full rx ring correctly. When the rx ring is set to the max. size (i.e. 255), the consumer and producer indices will be the same when completing an rx packet. Fix the rx code to handle this condition properly. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 6fbb5486163d..0d592f7c3a99 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1656,23 +1656,30 @@ static inline void bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb, u16 cons, u16 prod) { - struct sw_bd *cons_rx_buf = &bp->rx_buf_ring[cons]; - struct sw_bd *prod_rx_buf = &bp->rx_buf_ring[prod]; - struct rx_bd *cons_bd = &bp->rx_desc_ring[cons]; - struct rx_bd *prod_bd = &bp->rx_desc_ring[prod]; + struct sw_bd *cons_rx_buf, *prod_rx_buf; + struct rx_bd *cons_bd, *prod_bd; + + cons_rx_buf = &bp->rx_buf_ring[cons]; + prod_rx_buf = &bp->rx_buf_ring[prod]; pci_dma_sync_single_for_device(bp->pdev, pci_unmap_addr(cons_rx_buf, mapping), bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE); - prod_rx_buf->skb = cons_rx_buf->skb; - pci_unmap_addr_set(prod_rx_buf, mapping, - pci_unmap_addr(cons_rx_buf, mapping)); + bp->rx_prod_bseq += bp->rx_buf_use_size; - memcpy(prod_bd, cons_bd, 8); + prod_rx_buf->skb = skb; - bp->rx_prod_bseq += bp->rx_buf_use_size; + if (cons == prod) + return; + pci_unmap_addr_set(prod_rx_buf, mapping, + pci_unmap_addr(cons_rx_buf, mapping)); + + cons_bd = &bp->rx_desc_ring[cons]; + prod_bd = &bp->rx_desc_ring[prod]; + prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi; + prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo; } static int @@ -1699,14 +1706,19 @@ bnx2_rx_int(struct bnx2 *bp, int budget) u32 status; struct sw_bd *rx_buf; struct sk_buff *skb; + dma_addr_t dma_addr; sw_ring_cons = RX_RING_IDX(sw_cons); sw_ring_prod = RX_RING_IDX(sw_prod); rx_buf = &bp->rx_buf_ring[sw_ring_cons]; skb = rx_buf->skb; - pci_dma_sync_single_for_cpu(bp->pdev, - pci_unmap_addr(rx_buf, mapping), + + rx_buf->skb = NULL; + + dma_addr = pci_unmap_addr(rx_buf, mapping); + + pci_dma_sync_single_for_cpu(bp->pdev, dma_addr, bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE); rx_hdr = (struct l2_fhdr *) skb->data; @@ -1747,8 +1759,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget) skb = new_skb; } else if (bnx2_alloc_rx_skb(bp, sw_ring_prod) == 0) { - pci_unmap_single(bp->pdev, - pci_unmap_addr(rx_buf, mapping), + pci_unmap_single(bp->pdev, dma_addr, bp->rx_buf_use_size, PCI_DMA_FROMDEVICE); skb_reserve(skb, bp->rx_offset); @@ -1794,8 +1805,6 @@ reuse_rx: rx_pkt++; next_rx: - rx_buf->skb = NULL; - sw_cons = NEXT_RX_BD(sw_cons); sw_prod = NEXT_RX_BD(sw_prod); @@ -3360,7 +3369,7 @@ bnx2_init_rx_ring(struct bnx2 *bp) val = (u64) bp->rx_desc_mapping & 0xffffffff; CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val); - for ( ;ring_prod < bp->rx_ring_size; ) { + for (i = 0; i < bp->rx_ring_size; i++) { if (bnx2_alloc_rx_skb(bp, ring_prod) < 0) { break; } -- cgit v1.2.3-59-g8ed1b From 13daffa2f2ba65674e7816a0e95e7b93246cb686 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:49:20 -0800 Subject: [BNX2]: Support larger rx ring sizes (part 1) Increase maximum receive ring size from 255 to 1020 by supporting up to 4 linked pages of receive descriptors. To accomodate the higher memory usage, each physical descriptor page is allocated separately and the software ring that keeps track of the SKBs and the DMA addresses is allocated using vmalloc. Some of the receive-related fields in the bp structure are re- organized a bit for better locality of reference. The max. was reduced to 1020 from 4080 after discussion with David Miller. This patch contains ring init code changes only. This next patch contains rx data path code changes. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 117 ++++++++++++++++++++++++++++++++++++++--------------- drivers/net/bnx2.h | 36 ++++++++++------- 2 files changed, 107 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 0d592f7c3a99..03c47cf04e90 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -360,6 +360,8 @@ bnx2_netif_start(struct bnx2 *bp) static void bnx2_free_mem(struct bnx2 *bp) { + int i; + if (bp->stats_blk) { pci_free_consistent(bp->pdev, sizeof(struct statistics_block), bp->stats_blk, bp->stats_blk_mapping); @@ -378,19 +380,23 @@ bnx2_free_mem(struct bnx2 *bp) } kfree(bp->tx_buf_ring); bp->tx_buf_ring = NULL; - if (bp->rx_desc_ring) { - pci_free_consistent(bp->pdev, - sizeof(struct rx_bd) * RX_DESC_CNT, - bp->rx_desc_ring, bp->rx_desc_mapping); - bp->rx_desc_ring = NULL; - } - kfree(bp->rx_buf_ring); + for (i = 0; i < bp->rx_max_ring; i++) { + if (bp->rx_desc_ring[i]) + pci_free_consistent(bp->pdev, + sizeof(struct rx_bd) * RX_DESC_CNT, + bp->rx_desc_ring[i], + bp->rx_desc_mapping[i]); + bp->rx_desc_ring[i] = NULL; + } + vfree(bp->rx_buf_ring); bp->rx_buf_ring = NULL; } static int bnx2_alloc_mem(struct bnx2 *bp) { + int i; + bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT, GFP_KERNEL); if (bp->tx_buf_ring == NULL) @@ -404,18 +410,23 @@ bnx2_alloc_mem(struct bnx2 *bp) if (bp->tx_desc_ring == NULL) goto alloc_mem_err; - bp->rx_buf_ring = kmalloc(sizeof(struct sw_bd) * RX_DESC_CNT, - GFP_KERNEL); + bp->rx_buf_ring = vmalloc(sizeof(struct sw_bd) * RX_DESC_CNT * + bp->rx_max_ring); if (bp->rx_buf_ring == NULL) goto alloc_mem_err; - memset(bp->rx_buf_ring, 0, sizeof(struct sw_bd) * RX_DESC_CNT); - bp->rx_desc_ring = pci_alloc_consistent(bp->pdev, - sizeof(struct rx_bd) * - RX_DESC_CNT, - &bp->rx_desc_mapping); - if (bp->rx_desc_ring == NULL) - goto alloc_mem_err; + memset(bp->rx_buf_ring, 0, sizeof(struct sw_bd) * RX_DESC_CNT * + bp->rx_max_ring); + + for (i = 0; i < bp->rx_max_ring; i++) { + bp->rx_desc_ring[i] = + pci_alloc_consistent(bp->pdev, + sizeof(struct rx_bd) * RX_DESC_CNT, + &bp->rx_desc_mapping[i]); + if (bp->rx_desc_ring[i] == NULL) + goto alloc_mem_err; + + } bp->status_blk = pci_alloc_consistent(bp->pdev, sizeof(struct status_block), @@ -1520,7 +1531,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) struct sk_buff *skb; struct sw_bd *rx_buf = &bp->rx_buf_ring[index]; dma_addr_t mapping; - struct rx_bd *rxbd = &bp->rx_desc_ring[index]; + struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)]; unsigned long align; skb = dev_alloc_skb(bp->rx_buf_size); @@ -3349,24 +3360,32 @@ bnx2_init_rx_ring(struct bnx2 *bp) bp->hw_rx_cons = 0; bp->rx_prod_bseq = 0; - rxbd = &bp->rx_desc_ring[0]; - for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) { - rxbd->rx_bd_len = bp->rx_buf_use_size; - rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END; - } + for (i = 0; i < bp->rx_max_ring; i++) { + int j; - rxbd->rx_bd_haddr_hi = (u64) bp->rx_desc_mapping >> 32; - rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping & 0xffffffff; + rxbd = &bp->rx_desc_ring[i][0]; + for (j = 0; j < MAX_RX_DESC_CNT; j++, rxbd++) { + rxbd->rx_bd_len = bp->rx_buf_use_size; + rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END; + } + if (i == (bp->rx_max_ring - 1)) + j = 0; + else + j = i + 1; + rxbd->rx_bd_haddr_hi = (u64) bp->rx_desc_mapping[j] >> 32; + rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping[j] & + 0xffffffff; + } val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE; val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2; val |= 0x02 << 8; CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val); - val = (u64) bp->rx_desc_mapping >> 32; + val = (u64) bp->rx_desc_mapping[0] >> 32; CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, val); - val = (u64) bp->rx_desc_mapping & 0xffffffff; + val = (u64) bp->rx_desc_mapping[0] & 0xffffffff; CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val); for (i = 0; i < bp->rx_ring_size; i++) { @@ -3383,6 +3402,29 @@ bnx2_init_rx_ring(struct bnx2 *bp) REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq); } +static void +bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size) +{ + u32 num_rings, max; + + bp->rx_ring_size = size; + num_rings = 1; + while (size > MAX_RX_DESC_CNT) { + size -= MAX_RX_DESC_CNT; + num_rings++; + } + /* round to next power of 2 */ + max = MAX_RX_RINGS; + while ((max & num_rings) == 0) + max >>= 1; + + if (num_rings != max) + max <<= 1; + + bp->rx_max_ring = max; + bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1; +} + static void bnx2_free_tx_skbs(struct bnx2 *bp) { @@ -3428,7 +3470,7 @@ bnx2_free_rx_skbs(struct bnx2 *bp) if (bp->rx_buf_ring == NULL) return; - for (i = 0; i < RX_DESC_CNT; i++) { + for (i = 0; i < bp->rx_max_ring_idx; i++) { struct sw_bd *rx_buf = &bp->rx_buf_ring[i]; struct sk_buff *skb = rx_buf->skb; @@ -4792,7 +4834,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { struct bnx2 *bp = netdev_priv(dev); - ering->rx_max_pending = MAX_RX_DESC_CNT; + ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT; ering->rx_mini_max_pending = 0; ering->rx_jumbo_max_pending = 0; @@ -4809,17 +4851,28 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { struct bnx2 *bp = netdev_priv(dev); - if ((ering->rx_pending > MAX_RX_DESC_CNT) || + if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) || (ering->tx_pending > MAX_TX_DESC_CNT) || (ering->tx_pending <= MAX_SKB_FRAGS)) { return -EINVAL; } - bp->rx_ring_size = ering->rx_pending; + if (netif_running(bp->dev)) { + bnx2_netif_stop(bp); + bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); + bnx2_free_skbs(bp); + bnx2_free_mem(bp); + } + + bnx2_set_rx_ring_size(bp, ering->rx_pending); bp->tx_ring_size = ering->tx_pending; if (netif_running(bp->dev)) { - bnx2_netif_stop(bp); + int rc; + + rc = bnx2_alloc_mem(bp); + if (rc) + return rc; bnx2_init_nic(bp); bnx2_netif_start(bp); } @@ -5493,7 +5546,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->mac_addr[5] = (u8) reg; bp->tx_ring_size = MAX_TX_DESC_CNT; - bp->rx_ring_size = 100; + bnx2_set_rx_ring_size(bp, 100); bp->rx_csum = 1; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 9f691cbd666b..beb2e8bcc659 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -3792,8 +3792,10 @@ struct l2_fhdr { #define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd)) #define MAX_TX_DESC_CNT (TX_DESC_CNT - 1) +#define MAX_RX_RINGS 4 #define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd)) #define MAX_RX_DESC_CNT (RX_DESC_CNT - 1) +#define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS) #define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \ (MAX_TX_DESC_CNT - 1)) ? \ @@ -3805,8 +3807,10 @@ struct l2_fhdr { (MAX_RX_DESC_CNT - 1)) ? \ (x) + 2 : (x) + 1 -#define RX_RING_IDX(x) ((x) & MAX_RX_DESC_CNT) +#define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx) +#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> 8) +#define RX_IDX(x) ((x) & MAX_RX_DESC_CNT) /* Context size. */ #define CTX_SHIFT 7 @@ -3903,6 +3907,15 @@ struct bnx2 { struct status_block *status_blk; u32 last_status_idx; + u32 flags; +#define PCIX_FLAG 1 +#define PCI_32BIT_FLAG 2 +#define ONE_TDMA_FLAG 4 /* no longer used */ +#define NO_WOL_FLAG 8 +#define USING_DAC_FLAG 0x10 +#define USING_MSI_FLAG 0x20 +#define ASF_ENABLE_FLAG 0x40 + struct tx_bd *tx_desc_ring; struct sw_bd *tx_buf_ring; u32 tx_prod_bseq; @@ -3920,19 +3933,22 @@ struct bnx2 { u32 rx_offset; u32 rx_buf_use_size; /* useable size */ u32 rx_buf_size; /* with alignment */ - struct rx_bd *rx_desc_ring; - struct sw_bd *rx_buf_ring; + u32 rx_max_ring_idx; + u32 rx_prod_bseq; u16 rx_prod; u16 rx_cons; u32 rx_csum; + struct sw_bd *rx_buf_ring; + struct rx_bd *rx_desc_ring[MAX_RX_RINGS]; + /* Only used to synchronize netif_stop_queue/wake_queue when tx */ /* ring is full */ spinlock_t tx_lock; - /* End of fileds used in the performance code paths. */ + /* End of fields used in the performance code paths. */ char *name; @@ -3945,15 +3961,6 @@ struct bnx2 { /* Used to synchronize phy accesses. */ spinlock_t phy_lock; - u32 flags; -#define PCIX_FLAG 1 -#define PCI_32BIT_FLAG 2 -#define ONE_TDMA_FLAG 4 /* no longer used */ -#define NO_WOL_FLAG 8 -#define USING_DAC_FLAG 0x10 -#define USING_MSI_FLAG 0x20 -#define ASF_ENABLE_FLAG 0x40 - u32 phy_flags; #define PHY_SERDES_FLAG 1 #define PHY_CRC_FIX_FLAG 2 @@ -4004,8 +4011,9 @@ struct bnx2 { dma_addr_t tx_desc_mapping; + int rx_max_ring; int rx_ring_size; - dma_addr_t rx_desc_mapping; + dma_addr_t rx_desc_mapping[MAX_RX_RINGS]; u16 tx_quick_cons_trip; u16 tx_quick_cons_trip_int; -- cgit v1.2.3-59-g8ed1b From 3fdfcc2c95ffc7ee04b480a4c1fd4809b5ff2f7c Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:49:49 -0800 Subject: [BNX2]: Support larger rx ring sizes (part 2) Support bigger rx ring sizes (up to 1020) in the rx fast path. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 03c47cf04e90..b36515e95376 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1687,8 +1687,8 @@ bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb, pci_unmap_addr_set(prod_rx_buf, mapping, pci_unmap_addr(cons_rx_buf, mapping)); - cons_bd = &bp->rx_desc_ring[cons]; - prod_bd = &bp->rx_desc_ring[prod]; + cons_bd = &bp->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)]; + prod_bd = &bp->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)]; prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi; prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo; } -- cgit v1.2.3-59-g8ed1b From 1d60290f27e7dc4bce2c43922d0bfa9abd246fc9 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:50:08 -0800 Subject: [BNX2]: Update version Update version to 1.4.37. Add missing flush_scheduled_work() in bnx2_suspend as noted by Jeff Garzik. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index b36515e95376..1f4b788245f1 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -14,8 +14,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.31" -#define DRV_MODULE_RELDATE "January 19, 2006" +#define DRV_MODULE_VERSION "1.4.37" +#define DRV_MODULE_RELDATE "February 1, 2006" #define RUN_AT(x) (jiffies + (x)) @@ -5765,6 +5765,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state) if (!netif_running(dev)) return 0; + flush_scheduled_work(); bnx2_netif_stop(bp); netif_device_detach(dev); del_timer_sync(&bp->timer); -- cgit v1.2.3-59-g8ed1b From 0d36f37bb1e1cbadca6dc90a840bb2bc9ab51c44 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 17:55:25 -0800 Subject: [BNX2]: include Include so that it compiles properly on all archs. Update version to 1.4.38. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 4 ++-- drivers/net/bnx2.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 1f4b788245f1..7d213707008a 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -14,8 +14,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.37" -#define DRV_MODULE_RELDATE "February 1, 2006" +#define DRV_MODULE_VERSION "1.4.38" +#define DRV_MODULE_RELDATE "February 10, 2006" #define RUN_AT(x) (jiffies + (x)) diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index beb2e8bcc659..fd4b7f2eb477 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3-59-g8ed1b From ec4f32d550b94b4b66c9c7689bc09c6b32c8e82e Mon Sep 17 00:00:00 2001 From: Jean Tourrilhes Date: Mon, 20 Mar 2006 18:54:03 -0800 Subject: [IRDA]: nsc-ircc: ISAPnP support This enables PnP support for the nsc-ircc chipset. Since we can't fetch the chipset cfg_base from the PnP layer, we just use the PnP information as one more hint when probing the chip. Signed-off-by: Jean Tourrilhes Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/nsc-ircc.c | 185 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 151 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index ee717d0e939e..282414ba22f0 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -12,6 +12,7 @@ * Copyright (c) 1998-2000 Dag Brattli * Copyright (c) 1998 Lichen Wang, * Copyright (c) 1998 Actisys Corp., www.actisys.com + * Copyright (c) 2000-2004 Jean Tourrilhes * All Rights Reserved * * This program is free software; you can redistribute it and/or @@ -53,6 +54,7 @@ #include #include #include +#include #include #include @@ -78,8 +80,8 @@ static int dongle_id; /* Use BIOS settions by default, but user may supply module parameters */ static unsigned int io[] = { ~0, ~0, ~0, ~0 }; -static unsigned int irq[] = { 0, 0, 0, 0, 0 }; -static unsigned int dma[] = { 0, 0, 0, 0, 0 }; +static unsigned int irq[] = { 0, 0, 0, 0 }; +static unsigned int dma[] = { 0, 0, 0, 0 }; static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info); static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info); @@ -87,6 +89,7 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info); static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info); static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info); static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info); +static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id); /* These are the known NSC chips */ static nsc_chip_t chips[] = { @@ -104,7 +107,6 @@ static nsc_chip_t chips[] = { { NULL } }; -/* Max 4 instances for now */ static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL }; static char *dongle_types[] = { @@ -126,8 +128,24 @@ static char *dongle_types[] = { "No dongle connected", }; +/* PNP probing */ +static chipio_t pnp_info; +static const struct pnp_device_id nsc_ircc_pnp_table[] = { + { .id = "NSC6001", .driver_data = 0 }, + { .id = "IBM0071", .driver_data = 0 }, + { } +}; + +MODULE_DEVICE_TABLE(pnp, nsc_ircc_pnp_table); + +static struct pnp_driver nsc_ircc_pnp_driver = { + .name = "nsc-ircc", + .id_table = nsc_ircc_pnp_table, + .probe = nsc_ircc_pnp_probe, +}; + /* Some prototypes */ -static int nsc_ircc_open(int i, chipio_t *info); +static int nsc_ircc_open(chipio_t *info); static int nsc_ircc_close(struct nsc_ircc_cb *self); static int nsc_ircc_setup(chipio_t *info); static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self); @@ -148,6 +166,10 @@ static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev); static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data); +/* Globals */ +static int pnp_registered; +static int pnp_succeeded; + /* * Function nsc_ircc_init () * @@ -158,28 +180,30 @@ static int __init nsc_ircc_init(void) { chipio_t info; nsc_chip_t *chip; - int ret = -ENODEV; + int ret; int cfg_base; int cfg, id; int reg; int i = 0; + /* Register with PnP subsystem to detect disable ports */ + ret = pnp_register_driver(&nsc_ircc_pnp_driver); + + if (ret >= 0) + pnp_registered = 1; + + ret = -ENODEV; + /* Probe for all the NSC chipsets we know about */ - for (chip=chips; chip->name ; chip++) { + for (chip = chips; chip->name ; chip++) { IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__, chip->name); /* Try all config registers for this chip */ - for (cfg=0; cfg<3; cfg++) { + for (cfg = 0; cfg < ARRAY_SIZE(chip->cfg); cfg++) { cfg_base = chip->cfg[cfg]; if (!cfg_base) continue; - - memset(&info, 0, sizeof(chipio_t)); - info.cfg_base = cfg_base; - info.fir_base = io[i]; - info.dma = dma[i]; - info.irq = irq[i]; /* Read index register */ reg = inb(cfg_base); @@ -194,24 +218,64 @@ static int __init nsc_ircc_init(void) if ((id & chip->cid_mask) == chip->cid_value) { IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n", __FUNCTION__, chip->name, id & ~chip->cid_mask); - /* - * If the user supplies the base address, then - * we init the chip, if not we probe the values - * set by the BIOS - */ - if (io[i] < 0x2000) { - chip->init(chip, &info); - } else - chip->probe(chip, &info); - if (nsc_ircc_open(i, &info) == 0) - ret = 0; + /* + * If we found a correct PnP setting, + * we first try it. + */ + if (pnp_succeeded) { + memset(&info, 0, sizeof(chipio_t)); + info.cfg_base = cfg_base; + info.fir_base = pnp_info.fir_base; + info.dma = pnp_info.dma; + info.irq = pnp_info.irq; + + if (info.fir_base < 0x2000) { + IRDA_MESSAGE("%s, chip->init\n", driver_name); + chip->init(chip, &info); + } else + chip->probe(chip, &info); + + if (nsc_ircc_open(&info) >= 0) + ret = 0; + } + + /* + * Opening based on PnP values failed. + * Let's fallback to user values, or probe + * the chip. + */ + if (ret) { + IRDA_DEBUG(2, "%s, PnP init failed\n", driver_name); + memset(&info, 0, sizeof(chipio_t)); + info.cfg_base = cfg_base; + info.fir_base = io[i]; + info.dma = dma[i]; + info.irq = irq[i]; + + /* + * If the user supplies the base address, then + * we init the chip, if not we probe the values + * set by the BIOS + */ + if (io[i] < 0x2000) { + chip->init(chip, &info); + } else + chip->probe(chip, &info); + + if (nsc_ircc_open(&info) >= 0) + ret = 0; + } i++; } else { IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __FUNCTION__, id); } } - + } + + if (ret) { + pnp_unregister_driver(&nsc_ircc_pnp_driver); + pnp_registered = 0; } return ret; @@ -229,10 +293,15 @@ static void __exit nsc_ircc_cleanup(void) pm_unregister_all(nsc_ircc_pmproc); - for (i=0; i < 4; i++) { + for (i = 0; i < ARRAY_SIZE(dev_self); i++) { if (dev_self[i]) nsc_ircc_close(dev_self[i]); } + + if (pnp_registered) + pnp_unregister_driver(&nsc_ircc_pnp_driver); + + pnp_registered = 0; } /* @@ -241,16 +310,27 @@ static void __exit nsc_ircc_cleanup(void) * Open driver instance * */ -static int __init nsc_ircc_open(int i, chipio_t *info) +static int __init nsc_ircc_open(chipio_t *info) { struct net_device *dev; struct nsc_ircc_cb *self; - struct pm_dev *pmdev; + struct pm_dev *pmdev; void *ret; - int err; + int err, chip_index; IRDA_DEBUG(2, "%s()\n", __FUNCTION__); + + for (chip_index = 0; chip_index < ARRAY_SIZE(dev_self); chip_index++) { + if (!dev_self[chip_index]) + break; + } + + if (chip_index == ARRAY_SIZE(dev_self)) { + IRDA_ERROR("%s(), maximum number of supported chips reached!\n", __FUNCTION__); + return -ENOMEM; + } + IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, info->cfg_base); @@ -271,8 +351,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info) spin_lock_init(&self->lock); /* Need to store self somewhere */ - dev_self[i] = self; - self->index = i; + dev_self[chip_index] = self; + self->index = chip_index; /* Initialize IO */ self->io.cfg_base = info->cfg_base; @@ -351,7 +431,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info) /* Check if user has supplied a valid dongle id or not */ if ((dongle_id <= 0) || - (dongle_id >= (sizeof(dongle_types) / sizeof(dongle_types[0]))) ) { + (dongle_id >= ARRAY_SIZE(dongle_types))) { dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name, @@ -368,7 +448,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info) if (pmdev) pmdev->data = self; - return 0; + return chip_index; out4: dma_free_coherent(NULL, self->tx_buff.truesize, self->tx_buff.head, self->tx_buff_dma); @@ -379,7 +459,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info) release_region(self->io.fir_base, self->io.fir_ext); out1: free_netdev(dev); - dev_self[i] = NULL; + dev_self[chip_index] = NULL; return err; } @@ -806,6 +886,43 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info) return 0; } +/* PNP probing */ +static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id) +{ + memset(&pnp_info, 0, sizeof(chipio_t)); + pnp_info.irq = -1; + pnp_info.dma = -1; + pnp_succeeded = 1; + + /* There don't seem to be any way to get the cfg_base. + * On my box, cfg_base is in the PnP descriptor of the + * motherboard. Oh well... Jean II */ + + if (pnp_port_valid(dev, 0) && + !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) + pnp_info.fir_base = pnp_port_start(dev, 0); + + if (pnp_irq_valid(dev, 0) && + !(pnp_irq_flags(dev, 0) & IORESOURCE_DISABLED)) + pnp_info.irq = pnp_irq(dev, 0); + + if (pnp_dma_valid(dev, 0) && + !(pnp_dma_flags(dev, 0) & IORESOURCE_DISABLED)) + pnp_info.dma = pnp_dma(dev, 0); + + IRDA_DEBUG(0, "%s() : From PnP, found firbase 0x%03X ; irq %d ; dma %d.\n", + __FUNCTION__, pnp_info.fir_base, pnp_info.irq, pnp_info.dma); + + if((pnp_info.fir_base == 0) || + (pnp_info.irq == -1) || (pnp_info.dma == -1)) { + /* Returning an error will disable the device. Yuck ! */ + //return -EINVAL; + pnp_succeeded = 0; + } + + return 0; +} + /* * Function nsc_ircc_setup (info) * -- cgit v1.2.3-59-g8ed1b From 3b99b93baba4cbf4fd3d206e65e81a070b21b560 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 20 Mar 2006 18:59:05 -0800 Subject: [IRDA]: nsc-ircc: PM update This patch brings the nsc-ircc code to a more up to date power management scheme, following the current device model. Signed-off-by: Dmitry Torokhov Signed-off-by: Rudolf Marek Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/nsc-ircc.c | 131 ++++++++++++++++++++++++++++++++------------ drivers/net/irda/nsc-ircc.h | 2 +- 2 files changed, 98 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 282414ba22f0..81a4ccf54c57 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -55,14 +55,12 @@ #include #include #include +#include #include #include #include -#include -#include - #include #include #include @@ -74,6 +72,19 @@ static char *driver_name = "nsc-ircc"; +/* Power Management */ +#define NSC_IRCC_DRIVER_NAME "nsc-ircc" +static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state); +static int nsc_ircc_resume(struct platform_device *dev); + +static struct platform_driver nsc_ircc_driver = { + .suspend = nsc_ircc_suspend, + .resume = nsc_ircc_resume, + .driver = { + .name = NSC_IRCC_DRIVER_NAME, + }, +}; + /* Module parameters */ static int qos_mtt_bits = 0x07; /* 1 ms or more */ static int dongle_id; @@ -164,7 +175,6 @@ static int nsc_ircc_net_open(struct net_device *dev); static int nsc_ircc_net_close(struct net_device *dev); static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev); -static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data); /* Globals */ static int pnp_registered; @@ -186,6 +196,12 @@ static int __init nsc_ircc_init(void) int reg; int i = 0; + ret = platform_driver_register(&nsc_ircc_driver); + if (ret) { + IRDA_ERROR("%s, Can't register driver!\n", driver_name); + return ret; + } + /* Register with PnP subsystem to detect disable ports */ ret = pnp_register_driver(&nsc_ircc_pnp_driver); @@ -274,6 +290,7 @@ static int __init nsc_ircc_init(void) } if (ret) { + platform_driver_unregister(&nsc_ircc_driver); pnp_unregister_driver(&nsc_ircc_pnp_driver); pnp_registered = 0; } @@ -291,13 +308,13 @@ static void __exit nsc_ircc_cleanup(void) { int i; - pm_unregister_all(nsc_ircc_pmproc); - for (i = 0; i < ARRAY_SIZE(dev_self); i++) { if (dev_self[i]) nsc_ircc_close(dev_self[i]); } + platform_driver_unregister(&nsc_ircc_driver); + if (pnp_registered) pnp_unregister_driver(&nsc_ircc_pnp_driver); @@ -314,7 +331,6 @@ static int __init nsc_ircc_open(chipio_t *info) { struct net_device *dev; struct nsc_ircc_cb *self; - struct pm_dev *pmdev; void *ret; int err, chip_index; @@ -444,11 +460,18 @@ static int __init nsc_ircc_open(chipio_t *info) self->io.dongle_id = dongle_id; nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id); - pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, nsc_ircc_pmproc); - if (pmdev) - pmdev->data = self; + self->pldev = platform_device_register_simple(NSC_IRCC_DRIVER_NAME, + self->index, NULL, 0); + if (IS_ERR(self->pldev)) { + err = PTR_ERR(self->pldev); + goto out5; + } + platform_set_drvdata(self->pldev, self); return chip_index; + + out5: + unregister_netdev(dev); out4: dma_free_coherent(NULL, self->tx_buff.truesize, self->tx_buff.head, self->tx_buff_dma); @@ -479,6 +502,8 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self) iobase = self->io.fir_base; + platform_device_unregister(self->pldev); + /* Remove netdevice */ unregister_netdev(self->netdev); @@ -2278,45 +2303,83 @@ static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev) return &self->stats; } -static void nsc_ircc_suspend(struct nsc_ircc_cb *self) +static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state) { - IRDA_MESSAGE("%s, Suspending\n", driver_name); + struct nsc_ircc_cb *self = platform_get_drvdata(dev); + int bank; + unsigned long flags; + int iobase = self->io.fir_base; if (self->io.suspended) - return; + return 0; - nsc_ircc_net_close(self->netdev); + IRDA_DEBUG(1, "%s, Suspending\n", driver_name); + rtnl_lock(); + if (netif_running(self->netdev)) { + netif_device_detach(self->netdev); + spin_lock_irqsave(&self->lock, flags); + /* Save current bank */ + bank = inb(iobase+BSR); + + /* Disable interrupts */ + switch_bank(iobase, BANK0); + outb(0, iobase+IER); + + /* Restore bank register */ + outb(bank, iobase+BSR); + + spin_unlock_irqrestore(&self->lock, flags); + free_irq(self->io.irq, self->netdev); + disable_dma(self->io.dma); + } self->io.suspended = 1; + rtnl_unlock(); + + return 0; } -static void nsc_ircc_wakeup(struct nsc_ircc_cb *self) +static int nsc_ircc_resume(struct platform_device *dev) { + struct nsc_ircc_cb *self = platform_get_drvdata(dev); + unsigned long flags; + if (!self->io.suspended) - return; + return 0; + IRDA_DEBUG(1, "%s, Waking up\n", driver_name); + + rtnl_lock(); nsc_ircc_setup(&self->io); - nsc_ircc_net_open(self->netdev); - - IRDA_MESSAGE("%s, Waking up\n", driver_name); + nsc_ircc_init_dongle_interface(self->io.fir_base, self->io.dongle_id); + if (netif_running(self->netdev)) { + if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, + self->netdev->name, self->netdev)) { + IRDA_WARNING("%s, unable to allocate irq=%d\n", + driver_name, self->io.irq); + + /* + * Don't fail resume process, just kill this + * network interface + */ + unregister_netdevice(self->netdev); + } else { + spin_lock_irqsave(&self->lock, flags); + nsc_ircc_change_speed(self, self->io.speed); + spin_unlock_irqrestore(&self->lock, flags); + netif_device_attach(self->netdev); + } + + } else { + spin_lock_irqsave(&self->lock, flags); + nsc_ircc_change_speed(self, 9600); + spin_unlock_irqrestore(&self->lock, flags); + } self->io.suspended = 0; -} + rtnl_unlock(); -static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) -{ - struct nsc_ircc_cb *self = (struct nsc_ircc_cb*) dev->data; - if (self) { - switch (rqst) { - case PM_SUSPEND: - nsc_ircc_suspend(self); - break; - case PM_RESUME: - nsc_ircc_wakeup(self); - break; - } - } - return 0; + return 0; } MODULE_AUTHOR("Dag Brattli "); diff --git a/drivers/net/irda/nsc-ircc.h b/drivers/net/irda/nsc-ircc.h index 6edf7e514624..dacf671abcd6 100644 --- a/drivers/net/irda/nsc-ircc.h +++ b/drivers/net/irda/nsc-ircc.h @@ -269,7 +269,7 @@ struct nsc_ircc_cb { __u32 new_speed; int index; /* Instance index */ - struct pm_dev *dev; + struct platform_device *pldev; }; static inline void switch_bank(int iobase, int bank) -- cgit v1.2.3-59-g8ed1b From 0ed79c9b7dea5cd9a55589a495cf96f00cd037d9 Mon Sep 17 00:00:00 2001 From: Jean Tourrilhes Date: Mon, 20 Mar 2006 18:59:40 -0800 Subject: [IRDA]: nsc-ircc: support for yet another Thinkpad IrDA chipset This patch simply adds support for a variation of the nsc-ircc PC8739x chipset, found in some IBM Thinkpad laptops. Signed-off-by: Jean Tourrilhes Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/nsc-ircc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 81a4ccf54c57..83141a3ff546 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -90,9 +90,9 @@ static int qos_mtt_bits = 0x07; /* 1 ms or more */ static int dongle_id; /* Use BIOS settions by default, but user may supply module parameters */ -static unsigned int io[] = { ~0, ~0, ~0, ~0 }; -static unsigned int irq[] = { 0, 0, 0, 0 }; -static unsigned int dma[] = { 0, 0, 0, 0 }; +static unsigned int io[] = { ~0, ~0, ~0, ~0, ~0 }; +static unsigned int irq[] = { 0, 0, 0, 0, 0 }; +static unsigned int dma[] = { 0, 0, 0, 0, 0 }; static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info); static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info); @@ -115,10 +115,12 @@ static nsc_chip_t chips[] = { /* Contributed by Jan Frey - IBM A30/A31 */ { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, nsc_ircc_probe_39x, nsc_ircc_init_39x }, + { "IBM", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff, + nsc_ircc_probe_39x, nsc_ircc_init_39x }, { NULL } }; -static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL }; +static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL }; static char *dongle_types[] = { "Differential serial interface", -- cgit v1.2.3-59-g8ed1b From 034888262eb8de1a91bc471d4e6d8173f6b3dbda Mon Sep 17 00:00:00 2001 From: David chosrova Date: Mon, 20 Mar 2006 19:00:04 -0800 Subject: [IRDA]: sti/cli removal from EP7211 IrDA driver This patch replaces the deprecated sti/cli routines with the corresponding spin_lock ones. Signed-off-by: David chosrova Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/ep7211_ir.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/ep7211_ir.c b/drivers/net/irda/ep7211_ir.c index 31896262d21c..4cba38f7e4a8 100644 --- a/drivers/net/irda/ep7211_ir.c +++ b/drivers/net/irda/ep7211_ir.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,8 @@ static void ep7211_ir_close(dongle_t *self); static int ep7211_ir_change_speed(struct irda_task *task); static int ep7211_ir_reset(struct irda_task *task); +static DEFINE_SPINLOCK(ep7211_lock); + static struct dongle_reg dongle = { .type = IRDA_EP7211_IR, .open = ep7211_ir_open, @@ -36,7 +39,7 @@ static void ep7211_ir_open(dongle_t *self, struct qos_info *qos) { unsigned int syscon1, flags; - save_flags(flags); cli(); + spin_lock_irqsave(&ep7211_lock, flags); /* Turn on the SIR encoder. */ syscon1 = clps_readl(SYSCON1); @@ -46,14 +49,14 @@ static void ep7211_ir_open(dongle_t *self, struct qos_info *qos) /* XXX: We should disable modem status interrupts on the first UART (interrupt #14). */ - restore_flags(flags); + spin_unlock_irqrestore(&ep7211_lock, flags); } static void ep7211_ir_close(dongle_t *self) { unsigned int syscon1, flags; - save_flags(flags); cli(); + spin_lock_irqsave(&ep7211_lock, flags); /* Turn off the SIR encoder. */ syscon1 = clps_readl(SYSCON1); @@ -63,7 +66,7 @@ static void ep7211_ir_close(dongle_t *self) /* XXX: If we've disabled the modem status interrupts, we should reset them back to their original state. */ - restore_flags(flags); + spin_unlock_irqrestore(&ep7211_lock, flags); } /* -- cgit v1.2.3-59-g8ed1b From a85d771e32f9724b61a68748cc667d1e11fe3478 Mon Sep 17 00:00:00 2001 From: Christophe Lucas Date: Mon, 20 Mar 2006 19:00:27 -0800 Subject: [IRDA]: pci_register_driver conversion This patch converts 2 IrDA drivers pci_module_init() calls to pci_register_driver(). Signed-off-by: Christophe Lucas Signed-off-by: Domen Puncer Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/donauboe.c | 2 +- drivers/net/irda/vlsi_ir.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index 3137592d60c0..910c0cab35b0 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c @@ -1778,7 +1778,7 @@ static struct pci_driver donauboe_pci_driver = { static int __init donauboe_init (void) { - return pci_module_init(&donauboe_pci_driver); + return pci_register_driver(&donauboe_pci_driver); } static void __exit diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index a9f49f058cfb..97a49e0be76b 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -1887,7 +1887,7 @@ static int __init vlsi_mod_init(void) vlsi_proc_root->owner = THIS_MODULE; } - ret = pci_module_init(&vlsi_irda_driver); + ret = pci_register_driver(&vlsi_irda_driver); if (ret && vlsi_proc_root) remove_proc_entry(PROC_DIR, NULL); -- cgit v1.2.3-59-g8ed1b From e75f7c900944aa90831f6d343ca40090a68b56dd Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 21:33:26 -0800 Subject: [TG3]: Add some missing netif_running() checks Add missing netif_running() checks in tg3's dev->set_multicast_list() and dev->set_mac_address(). If not netif_running(), these 2 calls can simply return 0 after storing the new settings if required. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 994658d26b8e..f7da3bf2fa09 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -5537,6 +5537,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + if (!netif_running(dev)) + return 0; + spin_lock_bh(&tp->lock); __tg3_set_mac_addr(tp); spin_unlock_bh(&tp->lock); @@ -7192,6 +7195,9 @@ static void tg3_set_rx_mode(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); + if (!netif_running(dev)) + return; + tg3_full_lock(tp, 0); __tg3_set_rx_mode(dev); tg3_full_unlock(tp); -- cgit v1.2.3-59-g8ed1b From 4f81c32b028aecd818634b1ef36aae3b2b3e66ce Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 21:33:42 -0800 Subject: [TG3]: Fix tg3_get_ringparam() Fix-up tg3_get_ringparam() to return the correct parameters. Set the jumbo rx ring parameter only if it is supported by the chip and currently in use. Add missing value for tx_max_pending, noticed by Rick Jones. Update version to 3.51. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f7da3bf2fa09..d4f5b58e1dd4 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.50" -#define DRV_MODULE_RELDATE "Feb 4, 2006" +#define DRV_MODULE_VERSION "3.51" +#define DRV_MODULE_RELDATE "Feb 21, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -7593,11 +7593,20 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam * ering->rx_max_pending = TG3_RX_RING_SIZE - 1; ering->rx_mini_max_pending = 0; - ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1; + if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) + ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1; + else + ering->rx_jumbo_max_pending = 0; + + ering->tx_max_pending = TG3_TX_RING_SIZE - 1; ering->rx_pending = tp->rx_pending; ering->rx_mini_pending = 0; - ering->rx_jumbo_pending = tp->rx_jumbo_pending; + if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) + ering->rx_jumbo_pending = tp->rx_jumbo_pending; + else + ering->rx_jumbo_pending = 0; + ering->tx_pending = tp->tx_pending; } -- cgit v1.2.3-59-g8ed1b From 0ac81ae34ec8898e7eb1388fe21e3cee7b626a88 Mon Sep 17 00:00:00 2001 From: David Basden Date: Mon, 20 Mar 2006 22:21:10 -0800 Subject: [IRDA]: TOIM3232 dongle support Here goes a patch for supporting TOIM3232 based serial IrDA dongles. The code is based on the tekram dongle code. It's been tested with a TOIM3232 based IRWave 320S dongle. It may work for TOIM4232 dongles, although it's not been tested. Signed-off-by: David Basden Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/Kconfig | 8 + drivers/net/irda/Makefile | 1 + drivers/net/irda/toim3232-sir.c | 375 ++++++++++++++++++++++++++++++++++++++++ include/linux/irda.h | 1 + 4 files changed, 385 insertions(+) create mode 100644 drivers/net/irda/toim3232-sir.c (limited to 'drivers') diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index c81fe1c382d5..5e6d00752990 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -64,6 +64,14 @@ config TEKRAM_DONGLE dongles you will have to start irattach like this: "irattach -d tekram". +config TOIM3232_DONGLE + tristate "TOIM3232 IrDa dongle" + depends on DONGLE && IRDA + help + Say Y here if you want to build support for the Vishay/Temic + TOIM3232 and TOIM4232 based dongles. + To compile it as a module, choose M here. + config LITELINK_DONGLE tristate "Parallax LiteLink dongle" depends on DONGLE && IRDA diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index 72cbfdc9cfcc..27ab75f20799 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_OLD_BELKIN_DONGLE) += old_belkin-sir.o obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o +obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o # The SIR helper module sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o diff --git a/drivers/net/irda/toim3232-sir.c b/drivers/net/irda/toim3232-sir.c new file mode 100644 index 000000000000..f6e5fed6a36d --- /dev/null +++ b/drivers/net/irda/toim3232-sir.c @@ -0,0 +1,375 @@ +/********************************************************************* + * + * Filename: toim3232-sir.c + * Version: 1.0 + * Description: Implementation of dongles based on the Vishay/Temic + * TOIM3232 SIR Endec chipset. Currently only the + * IRWave IR320ST-2 is tested, although it should work + * with any TOIM3232 or TOIM4232 chipset based RS232 + * dongle with minimal modification. + * Based heavily on the Tekram driver (tekram.c), + * with thanks to Dag Brattli and Martin Diehl. + * Status: Experimental. + * Author: David Basden + * Created at: Thu Feb 09 23:47:32 2006 + * + * Copyright (c) 2006 David Basden. + * Copyright (c) 1998-1999 Dag Brattli, + * Copyright (c) 2002 Martin Diehl, + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsø admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +/* + * This driver has currently only been tested on the IRWave IR320ST-2 + * + * PROTOCOL: + * + * The protocol for talking to the TOIM3232 is quite easy, and is + * designed to interface with RS232 with only level convertors. The + * BR/~D line on the chip is brought high to signal 'command mode', + * where a command byte is sent to select the baudrate of the RS232 + * interface and the pulse length of the IRDA output. When BR/~D + * is brought low, the dongle then changes to the selected baudrate, + * and the RS232 interface is used for data until BR/~D is brought + * high again. The initial speed for the TOIMx323 after RESET is + * 9600 baud. The baudrate for command-mode is the last selected + * baud-rate, or 9600 after a RESET. + * + * The dongle I have (below) adds some extra hardware on the front end, + * but this is mostly directed towards pariasitic power from the RS232 + * line rather than changing very much about how to communicate with + * the TOIM3232. + * + * The protocol to talk to the TOIM4232 chipset seems to be almost + * identical to the TOIM3232 (and the 4232 datasheet is more detailed) + * so this code will probably work on that as well, although I haven't + * tested it on that hardware. + * + * Target dongle variations that might be common: + * + * DTR and RTS function: + * The data sheet for the 4232 has a sample implementation that hooks the + * DTR and RTS lines to the RESET and BaudRate/~Data lines of the + * chip (through line-converters). Given both DTR and RTS would have to + * be held low in normal operation, and the TOIMx232 requires +5V to + * signal ground, most dongle designers would almost certainly choose + * an implementation that kept at least one of DTR or RTS high in + * normal operation to provide power to the dongle, but will likely + * vary between designs. + * + * User specified command bits: + * There are two user-controllable output lines from the TOIMx232 that + * can be set low or high by setting the appropriate bits in the + * high-nibble of the command byte (when setting speed and pulse length). + * These might be used to switch on and off added hardware or extra + * dongle features. + * + * + * Target hardware: IRWave IR320ST-2 + * + * The IRWave IR320ST-2 is a simple dongle based on the Vishay/Temic + * TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transciever. + * It uses a hex inverter and some discrete components to buffer and + * line convert the RS232 down to 5V. + * + * The dongle is powered through a voltage regulator, fed by a large + * capacitor. To switch the dongle on, DTR is brought high to charge + * the capacitor and drive the voltage regulator. DTR isn't associated + * with any control lines on the TOIM3232. Parisitic power is also taken + * from the RTS, TD and RD lines when brought high, but through resistors. + * When DTR is low, the circuit might lose power even with RTS high. + * + * RTS is inverted and attached to the BR/~D input pin. When RTS + * is high, BR/~D is low, and the TOIM3232 is in the normal 'data' mode. + * RTS is brought low, BR/~D is high, and the TOIM3232 is in 'command + * mode'. + * + * For some unknown reason, the RESET line isn't actually connected + * to anything. This means to reset the dongle to get it to a known + * state (9600 baud) you must drop DTR and RTS low, wait for the power + * capacitor to discharge, and then bring DTR (and RTS for data mode) + * high again, and wait for the capacitor to charge, the power supply + * to stabilise, and the oscillator clock to stabilise. + * + * Fortunately, if the current baudrate is known, the chipset can + * easily change speed by entering command mode without having to + * reset the dongle first. + * + * Major Components: + * + * - Vishay/Temic TOIM3232 SIR Endec to change RS232 pulse timings + * to IRDA pulse timings + * - 3.6864MHz crystal to drive TOIM3232 clock oscillator + * - DM74lS04M Inverting Hex line buffer for RS232 input buffering + * and level conversion + * - PJ2951AC 150mA voltage regulator + * - Vishay/Temic TFDS4500 SIR IRDA front-end transceiver + * + */ + +#include +#include +#include + +#include + +#include "sir-dev.h" + +MODULE_PARM(toim3232delay, "i"); +MODULE_PARM_DESC(toim3232delay, "toim3232 dongle write complete delay"); +static int toim3232delay = 150; /* default is 150 ms */ + +#if 0 +MODULE_PARM(toim3232flipdtr, "i"); +MODULE_PARM_DESC(toim3232flipdtr, "toim3232 dongle invert DTR (Reset)"); +static int toim3232flipdtr = 0; /* default is DTR high to reset */ + +MODULE_PARM(toim3232fliptrs, "i"); +MODULE_PARM_DESC(toim3232fliprts, "toim3232 dongle invert RTS (BR/D)"); +static int toim3232fliprts = 0; /* default is RTS high for baud change */ +#endif + +static int toim3232_open(struct sir_dev *); +static int toim3232_close(struct sir_dev *); +static int toim3232_change_speed(struct sir_dev *, unsigned); +static int toim3232_reset(struct sir_dev *); + +#define TOIM3232_115200 0x00 +#define TOIM3232_57600 0x01 +#define TOIM3232_38400 0x02 +#define TOIM3232_19200 0x03 +#define TOIM3232_9600 0x06 +#define TOIM3232_2400 0x0A + +#define TOIM3232_PW 0x10 /* Pulse select bit */ + +static struct dongle_driver toim3232 = { + .owner = THIS_MODULE, + .driver_name = "Vishay TOIM3232", + .type = IRDA_TOIM3232_DONGLE, + .open = toim3232_open, + .close = toim3232_close, + .reset = toim3232_reset, + .set_speed = toim3232_change_speed, +}; + +static int __init toim3232_sir_init(void) +{ + if (toim3232delay < 1 || toim3232delay > 500) + toim3232delay = 200; + IRDA_DEBUG(1, "%s - using %d ms delay\n", + toim3232.driver_name, toim3232delay); + return irda_register_dongle(&toim3232); +} + +static void __exit toim3232_sir_cleanup(void) +{ + irda_unregister_dongle(&toim3232); +} + +static int toim3232_open(struct sir_dev *dev) +{ + struct qos_info *qos = &dev->qos; + + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); + + /* Pull the lines high to start with. + * + * For the IR320ST-2, we need to charge the main supply capacitor to + * switch the device on. We keep DTR high throughout to do this. + * When RTS, TD and RD are high, they will also trickle-charge the + * cap. RTS is high for data transmission, and low for baud rate select. + * -- DGB + */ + sirdev_set_dtr_rts(dev, TRUE, TRUE); + + /* The TOI3232 supports many speeds between 1200bps and 115000bps. + * We really only care about those supported by the IRDA spec, but + * 38400 seems to be implemented in many places */ + qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; + + /* From the tekram driver. Not sure what a reasonable value is -- DGB */ + qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */ + irda_qos_bits_to_value(qos); + + /* irda thread waits 50 msec for power settling */ + + return 0; +} + +static int toim3232_close(struct sir_dev *dev) +{ + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); + + /* Power off dongle */ + sirdev_set_dtr_rts(dev, FALSE, FALSE); + + return 0; +} + +/* + * Function toim3232change_speed (dev, state, speed) + * + * Set the speed for the TOIM3232 based dongle. Warning, this + * function must be called with a process context! + * + * Algorithm + * 1. keep DTR high but clear RTS to bring into baud programming mode + * 2. wait at least 7us to enter programming mode + * 3. send control word to set baud rate and timing + * 4. wait at least 1us + * 5. bring RTS high to enter DATA mode (RS232 is passed through to transceiver) + * 6. should take effect immediately (although probably worth waiting) + */ + +#define TOIM3232_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1) + +static int toim3232_change_speed(struct sir_dev *dev, unsigned speed) +{ + unsigned state = dev->fsm.substate; + unsigned delay = 0; + u8 byte; + static int ret = 0; + + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); + + switch(state) { + case SIRDEV_STATE_DONGLE_SPEED: + + /* Figure out what we are going to send as a control byte */ + switch (speed) { + case 2400: + byte = TOIM3232_PW|TOIM3232_2400; + break; + default: + speed = 9600; + ret = -EINVAL; + /* fall thru */ + case 9600: + byte = TOIM3232_PW|TOIM3232_9600; + break; + case 19200: + byte = TOIM3232_PW|TOIM3232_19200; + break; + case 38400: + byte = TOIM3232_PW|TOIM3232_38400; + break; + case 57600: + byte = TOIM3232_PW|TOIM3232_57600; + break; + case 115200: + byte = TOIM3232_115200; + break; + } + + /* Set DTR, Clear RTS: Go into baud programming mode */ + sirdev_set_dtr_rts(dev, TRUE, FALSE); + + /* Wait at least 7us */ + udelay(14); + + /* Write control byte */ + sirdev_raw_write(dev, &byte, 1); + + dev->speed = speed; + + state = TOIM3232_STATE_WAIT_SPEED; + delay = toim3232delay; + break; + + case TOIM3232_STATE_WAIT_SPEED: + /* Have transmitted control byte * Wait for 'at least 1us' */ + udelay(14); + + /* Set DTR, Set RTS: Go into normal data mode */ + sirdev_set_dtr_rts(dev, TRUE, TRUE); + + /* Wait (TODO: check this is needed) */ + udelay(50); + break; + + default: + printk(KERN_ERR "%s - undefined state %d\n", __FUNCTION__, state); + ret = -EINVAL; + break; + } + + dev->fsm.substate = state; + return (delay > 0) ? delay : ret; +} + +/* + * Function toim3232reset (driver) + * + * This function resets the toim3232 dongle. Warning, this function + * must be called with a process context!! + * + * What we should do is: + * 0. Pull RESET high + * 1. Wait for at least 7us + * 2. Pull RESET low + * 3. Wait for at least 7us + * 4. Pull BR/~D high + * 5. Wait for at least 7us + * 6. Send control byte to set baud rate + * 7. Wait at least 1us after stop bit + * 8. Pull BR/~D low + * 9. Should then be in data mode + * + * Because the IR320ST-2 doesn't have the RESET line connected for some reason, + * we'll have to do something else. + * + * The default speed after a RESET is 9600, so lets try just bringing it up in + * data mode after switching it off, waiting for the supply capacitor to + * discharge, and then switch it back on. This isn't actually pulling RESET + * high, but it seems to have the same effect. + * + * This behaviour will probably work on dongles that have the RESET line connected, + * but if not, add a flag for the IR320ST-2, and implment the above-listed proper + * behaviour. + * + * RTS is inverted and then fed to BR/~D, so to put it in programming mode, we + * need to have pull RTS low + */ + +static int toim3232_reset(struct sir_dev *dev) +{ + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); + + /* Switch off both DTR and RTS to switch off dongle */ + sirdev_set_dtr_rts(dev, FALSE, FALSE); + + /* Should sleep a while. This might be evil doing it this way.*/ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(50)); + + /* Set DTR, Set RTS (data mode) */ + sirdev_set_dtr_rts(dev, TRUE, TRUE); + + /* Wait at least 10 ms for power to stabilize again */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(10)); + + /* Speed should now be 9600 */ + dev->speed = 9600; + + return 0; +} + +MODULE_AUTHOR("David Basden "); +MODULE_DESCRIPTION("Vishay/Temic TOIM3232 based dongle driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("irda-dongle-12"); /* IRDA_TOIM3232_DONGLE */ + +module_init(toim3232_sir_init); +module_exit(toim3232_sir_cleanup); diff --git a/include/linux/irda.h b/include/linux/irda.h index 95dee174cdc5..09d8f105a5a8 100644 --- a/include/linux/irda.h +++ b/include/linux/irda.h @@ -76,6 +76,7 @@ typedef enum { IRDA_MCP2120_DONGLE = 9, IRDA_ACT200L_DONGLE = 10, IRDA_MA600_DONGLE = 11, + IRDA_TOIM3232_DONGLE = 12, } IRDA_DONGLE; /* Protocol types to be used for SOCK_DGRAM */ -- cgit v1.2.3-59-g8ed1b From b191ba0d599928372be5a89f75486eb58efab48a Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Mon, 20 Mar 2006 22:21:40 -0800 Subject: [CONNECTOR]: Use netlink_has_listeners() to avoind unnecessary allocations. Return -ESRCH from cn_netlink_send() when there are not listeners, just as it could be done by netlink_broadcast(). Propagate netlink_broadcast() error back to the caller. Signed-off-by: Evgeniy Polyakov Signed-off-by: David S. Miller --- Documentation/connector/connector.txt | 5 +++-- drivers/connector/connector.c | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/Documentation/connector/connector.txt b/Documentation/connector/connector.txt index 57a314b14cf8..ad6e0ba7b38c 100644 --- a/Documentation/connector/connector.txt +++ b/Documentation/connector/connector.txt @@ -69,10 +69,11 @@ Unregisters new callback with connector core. struct cb_id *id - unique connector's user identifier. -void cn_netlink_send(struct cn_msg *msg, u32 __groups, int gfp_mask); +int cn_netlink_send(struct cn_msg *msg, u32 __groups, int gfp_mask); Sends message to the specified groups. It can be safely called from -any context, but may silently fail under strong memory pressure. +softirq context, but may silently fail under strong memory pressure. +If there are no listeners for given group -ESRCH can be returned. struct cn_msg * - message header(with attached data). u32 __group - destination group. diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index 505677fb3157..d7125f4d9113 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -97,6 +97,9 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask) group = __group; } + if (!netlink_has_listeners(dev->nls, group)) + return -ESRCH; + size = NLMSG_SPACE(sizeof(*msg) + msg->len); skb = alloc_skb(size, gfp_mask); @@ -111,9 +114,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask) NETLINK_CB(skb).dst_group = group; - netlink_broadcast(dev->nls, skb, 0, group, gfp_mask); - - return 0; + return netlink_broadcast(dev->nls, skb, 0, group, gfp_mask); nlmsg_failure: kfree_skb(skb); -- cgit v1.2.3-59-g8ed1b From 6756ae4b4e97aba48c042b4aa6b77a18f507d2cb Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 22:23:58 -0800 Subject: [NET]: Convert RTNL to mutex. This patch turns the RTNL from a semaphore to a new 2.6.16 mutex and gets rid of some of the leftover legacy. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/8139too.c | 2 +- include/linux/rtnetlink.h | 20 +++++++------------- net/core/dev.c | 8 ++++---- net/core/link_watch.c | 4 ++-- net/core/netpoll.c | 6 +++--- net/core/rtnetlink.c | 28 +++++++++++++++++----------- net/ipv4/igmp.c | 24 ++++++++++++------------ net/ipv4/ipconfig.c | 10 +++++----- 8 files changed, 51 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index e58d4c50c2e1..f5ee064ab6b2 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -1605,7 +1605,7 @@ static void rtl8139_thread (void *_data) if (tp->watchdog_fired) { tp->watchdog_fired = 0; rtl8139_tx_timeout_task(_data); - } else if (rtnl_shlock_nowait() == 0) { + } else if (rtnl_trylock()) { rtl8139_thread_iter (dev, tp, tp->mmio_addr); rtnl_unlock (); } else { diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index edccefb45188..d263853a8f1c 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -907,6 +907,7 @@ struct tcamsg #ifdef __KERNEL__ #include +#include extern size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size); static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str) @@ -1038,24 +1039,17 @@ __rta_reserve(struct sk_buff *skb, int attrtype, int attrlen) extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change); -extern struct semaphore rtnl_sem; - -#define rtnl_shlock() down(&rtnl_sem) -#define rtnl_shlock_nowait() down_trylock(&rtnl_sem) - -#define rtnl_shunlock() do { up(&rtnl_sem); \ - if (rtnl && rtnl->sk_receive_queue.qlen) \ - rtnl->sk_data_ready(rtnl, 0); \ - } while(0) - +/* RTNL is used as a global lock for all changes to network configuration */ extern void rtnl_lock(void); -extern int rtnl_lock_interruptible(void); extern void rtnl_unlock(void); +extern int rtnl_trylock(void); + extern void rtnetlink_init(void); +extern void __rtnl_unlock(void); #define ASSERT_RTNL() do { \ - if (unlikely(down_trylock(&rtnl_sem) == 0)) { \ - up(&rtnl_sem); \ + if (unlikely(rtnl_trylock())) { \ + rtnl_unlock(); \ printk(KERN_ERR "RTNL: assertion failed at %s (%d)\n", \ __FILE__, __LINE__); \ dump_stack(); \ diff --git a/net/core/dev.c b/net/core/dev.c index 8763c99fcb84..be1d896cc5b9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2466,9 +2466,9 @@ int dev_ioctl(unsigned int cmd, void __user *arg) */ if (cmd == SIOCGIFCONF) { - rtnl_shlock(); + rtnl_lock(); ret = dev_ifconf((char __user *) arg); - rtnl_shunlock(); + rtnl_unlock(); return ret; } if (cmd == SIOCGIFNAME) @@ -2877,7 +2877,7 @@ static void netdev_wait_allrefs(struct net_device *dev) rebroadcast_time = warning_time = jiffies; while (atomic_read(&dev->refcnt) != 0) { if (time_after(jiffies, rebroadcast_time + 1 * HZ)) { - rtnl_shlock(); + rtnl_lock(); /* Rebroadcast unregister notification */ notifier_call_chain(&netdev_chain, @@ -2894,7 +2894,7 @@ static void netdev_wait_allrefs(struct net_device *dev) linkwatch_run_queue(); } - rtnl_shunlock(); + __rtnl_unlock(); rebroadcast_time = jiffies; } diff --git a/net/core/link_watch.c b/net/core/link_watch.c index e82a451d330b..341de44c7ed1 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -139,9 +139,9 @@ static void linkwatch_event(void *dummy) linkwatch_nextevent = jiffies + HZ; clear_bit(LW_RUNNING, &linkwatch_flags); - rtnl_shlock(); + rtnl_lock(); linkwatch_run_queue(); - rtnl_shunlock(); + rtnl_unlock(); } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index ea51f8d02eb8..e8e05cebd95a 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -669,14 +669,14 @@ int netpoll_setup(struct netpoll *np) printk(KERN_INFO "%s: device %s not up yet, forcing it\n", np->name, np->dev_name); - rtnl_shlock(); + rtnl_lock(); if (dev_change_flags(ndev, ndev->flags | IFF_UP) < 0) { printk(KERN_ERR "%s: failed to open %s\n", np->name, np->dev_name); - rtnl_shunlock(); + rtnl_unlock(); goto release; } - rtnl_shunlock(); + rtnl_unlock(); atleast = jiffies + HZ/10; atmost = jiffies + 4*HZ; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1c15a907066f..ae10d3740faa 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -51,25 +52,31 @@ #include #include -DECLARE_MUTEX(rtnl_sem); +static DEFINE_MUTEX(rtnl_mutex); void rtnl_lock(void) { - rtnl_shlock(); + mutex_lock(&rtnl_mutex); } -int rtnl_lock_interruptible(void) +void __rtnl_unlock(void) { - return down_interruptible(&rtnl_sem); + mutex_unlock(&rtnl_mutex); } - + void rtnl_unlock(void) { - rtnl_shunlock(); - + mutex_unlock(&rtnl_mutex); + if (rtnl && rtnl->sk_receive_queue.qlen) + rtnl->sk_data_ready(rtnl, 0); netdev_run_todo(); } +int rtnl_trylock(void) +{ + return mutex_trylock(&rtnl_mutex); +} + int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len) { memset(tb, 0, sizeof(struct rtattr*)*maxattr); @@ -625,9 +632,9 @@ static void rtnetlink_rcv(struct sock *sk, int len) unsigned int qlen = 0; do { - rtnl_lock(); + mutex_lock(&rtnl_mutex); netlink_run_queue(sk, &qlen, &rtnetlink_rcv_msg); - up(&rtnl_sem); + mutex_unlock(&rtnl_mutex); netdev_run_todo(); } while (qlen); @@ -704,6 +711,5 @@ EXPORT_SYMBOL(rtnetlink_links); EXPORT_SYMBOL(rtnetlink_put_metrics); EXPORT_SYMBOL(rtnl); EXPORT_SYMBOL(rtnl_lock); -EXPORT_SYMBOL(rtnl_lock_interruptible); -EXPORT_SYMBOL(rtnl_sem); +EXPORT_SYMBOL(rtnl_trylock); EXPORT_SYMBOL(rtnl_unlock); diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 64ce52bf0485..3ec502f19da0 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1730,7 +1730,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr) if (!MULTICAST(addr)) return -EINVAL; - rtnl_shlock(); + rtnl_lock(); in_dev = ip_mc_find_dev(imr); @@ -1763,7 +1763,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr) ip_mc_inc_group(in_dev, addr); err = 0; done: - rtnl_shunlock(); + rtnl_unlock(); return err; } @@ -1837,7 +1837,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct if (!MULTICAST(addr)) return -EINVAL; - rtnl_shlock(); + rtnl_lock(); imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr; imr.imr_address.s_addr = mreqs->imr_interface; @@ -1947,7 +1947,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1, &mreqs->imr_sourceaddr, 1); done: - rtnl_shunlock(); + rtnl_unlock(); if (leavegroup) return ip_mc_leave_group(sk, &imr); return err; @@ -1970,7 +1970,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex) msf->imsf_fmode != MCAST_EXCLUDE) return -EINVAL; - rtnl_shlock(); + rtnl_lock(); imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; imr.imr_address.s_addr = msf->imsf_interface; @@ -2030,7 +2030,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex) pmc->sfmode = msf->imsf_fmode; err = 0; done: - rtnl_shunlock(); + rtnl_unlock(); if (leavegroup) err = ip_mc_leave_group(sk, &imr); return err; @@ -2050,7 +2050,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf, if (!MULTICAST(addr)) return -EINVAL; - rtnl_shlock(); + rtnl_lock(); imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; imr.imr_address.s_addr = msf->imsf_interface; @@ -2072,7 +2072,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf, goto done; msf->imsf_fmode = pmc->sfmode; psl = pmc->sflist; - rtnl_shunlock(); + rtnl_unlock(); if (!psl) { len = 0; count = 0; @@ -2091,7 +2091,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf, return -EFAULT; return 0; done: - rtnl_shunlock(); + rtnl_unlock(); return err; } @@ -2112,7 +2112,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf, if (!MULTICAST(addr)) return -EINVAL; - rtnl_shlock(); + rtnl_lock(); err = -EADDRNOTAVAIL; @@ -2125,7 +2125,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf, goto done; gsf->gf_fmode = pmc->sfmode; psl = pmc->sflist; - rtnl_shunlock(); + rtnl_unlock(); count = psl ? psl->sl_count : 0; copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; gsf->gf_numsrc = count; @@ -2146,7 +2146,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf, } return 0; done: - rtnl_shunlock(); + rtnl_unlock(); return err; } diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index bb3613ec448c..cb8a92f18ef6 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -186,7 +186,7 @@ static int __init ic_open_devs(void) unsigned short oflags; last = &ic_first_dev; - rtnl_shlock(); + rtnl_lock(); /* bring loopback device up first */ if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0) @@ -215,7 +215,7 @@ static int __init ic_open_devs(void) continue; } if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) { - rtnl_shunlock(); + rtnl_unlock(); return -1; } d->dev = dev; @@ -232,7 +232,7 @@ static int __init ic_open_devs(void) dev->name, able, d->xid)); } } - rtnl_shunlock(); + rtnl_unlock(); *last = NULL; @@ -251,7 +251,7 @@ static void __init ic_close_devs(void) struct ic_device *d, *next; struct net_device *dev; - rtnl_shlock(); + rtnl_lock(); next = ic_first_dev; while ((d = next)) { next = d->next; @@ -262,7 +262,7 @@ static void __init ic_close_devs(void) } kfree(d); } - rtnl_shunlock(); + rtnl_unlock(); } /* -- cgit v1.2.3-59-g8ed1b From c5ecd62c25400a3c6856e009f84257d5bd03f03b Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 20 Mar 2006 22:25:41 -0800 Subject: [NET]: Move destructor from neigh->ops to neigh_params struct neigh_ops currently has a destructor field, which no in-kernel drivers outside of infiniband use. The infiniband/ulp/ipoib in-tree driver stashes some info in the neighbour structure (the results of the second-stage lookup from ARP results to real link-level path), and it uses neigh->ops->destructor to get a callback so it can clean up this extra info when a neighbour is freed. We've run into problems with this: since the destructor is in an ops field that is shared between neighbours that may belong to different net devices, there's no way to set/clear it safely. The following patch moves this field to neigh_parms where it can be safely set, together with its twin neigh_setup. Two additional patches in the patch series update ipoib to use this new interface. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier Signed-off-by: David S. Miller --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 16 +--------------- include/net/neighbour.h | 2 +- net/core/neighbour.c | 4 ++-- 3 files changed, 4 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index c3b5f79d1168..9d9cecd4753b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -247,7 +247,6 @@ static void path_free(struct net_device *dev, struct ipoib_path *path) if (neigh->ah) ipoib_put_ah(neigh->ah); *to_ipoib_neigh(neigh->neighbour) = NULL; - neigh->neighbour->ops->destructor = NULL; kfree(neigh); } @@ -530,7 +529,6 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) err: *to_ipoib_neigh(skb->dst->neighbour) = NULL; list_del(&neigh->list); - neigh->neighbour->ops->destructor = NULL; kfree(neigh); ++priv->stats.tx_dropped; @@ -769,21 +767,9 @@ static void ipoib_neigh_destructor(struct neighbour *n) ipoib_put_ah(ah); } -static int ipoib_neigh_setup(struct neighbour *neigh) -{ - /* - * Is this kosher? I can't find anybody in the kernel that - * sets neigh->destructor, so we should be able to set it here - * without trouble. - */ - neigh->ops->destructor = ipoib_neigh_destructor; - - return 0; -} - static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms) { - parms->neigh_setup = ipoib_neigh_setup; + parms->neigh_destructor = ipoib_neigh_destructor; return 0; } diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 6fa9ae190741..b0666d66293f 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -68,6 +68,7 @@ struct neigh_parms struct net_device *dev; struct neigh_parms *next; int (*neigh_setup)(struct neighbour *); + void (*neigh_destructor)(struct neighbour *); struct neigh_table *tbl; void *sysctl_table; @@ -145,7 +146,6 @@ struct neighbour struct neigh_ops { int family; - void (*destructor)(struct neighbour *); void (*solicit)(struct neighbour *, struct sk_buff*); void (*error_report)(struct neighbour *, struct sk_buff*); int (*output)(struct sk_buff*); diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 6ba1cdea18e8..0c8666872d10 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -586,8 +586,8 @@ void neigh_destroy(struct neighbour *neigh) kfree(hh); } - if (neigh->ops && neigh->ops->destructor) - (neigh->ops->destructor)(neigh); + if (neigh->parms->neigh_destructor) + (neigh->parms->neigh_destructor)(neigh); skb_queue_purge(&neigh->arp_queue); -- cgit v1.2.3-59-g8ed1b From d9ab5ad12b0d865bdb1b750d81192d34465541e9 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 22:27:35 -0800 Subject: [TG3]: Add 5787 and 5754 basic support Add basic support for 2 new chips 5787 and 5754. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 27 +++++++++++++++++++++++++-- drivers/net/tg3.h | 6 +++++- include/linux/pci_ids.h | 4 ++++ 3 files changed, 34 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d4f5b58e1dd4..e6ed940d7714 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -221,6 +221,14 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S, @@ -4388,6 +4396,10 @@ static int tg3_chip_reset(struct tg3 *tp) tp->nvram_lock_cnt = 0; } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + tw32(GRC_FASTBOOT_PC, 0); + /* * We must avoid the readl() that normally takes place. * It locks machines, causes machine checks, and other @@ -6018,6 +6030,10 @@ static int tg3_reset_hw(struct tg3 *tp) } } + /* Enable host coalescing bug fix */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + val |= (1 << 29); + tw32_f(WDMAC_MODE, val); udelay(40); @@ -8326,6 +8342,9 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, if (!err) tg3_nvram_unlock(tp); + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + tg3_phy_reset(tp); + if (tg3_test_registers(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; data[2] = 1; @@ -9681,6 +9700,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; @@ -9693,7 +9713,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0) @@ -9903,7 +9924,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)) tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; tp->coalesce_mode = 0; @@ -10628,6 +10650,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5752: return "5752"; case PHY_ID_BCM5714: return "5714"; case PHY_ID_BCM5780: return "5780"; + case PHY_ID_BCM5787: return "5787"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 7e3b613afb29..8d32fbe0d303 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -138,6 +138,7 @@ #define ASIC_REV_5752 0x06 #define ASIC_REV_5780 0x08 #define ASIC_REV_5714 0x09 +#define ASIC_REV_5787 0x0b #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 #define CHIPREV_5700_BX 0x71 @@ -1393,6 +1394,7 @@ #define GRC_MDI_CTRL 0x00006844 #define GRC_SEEPROM_DELAY 0x00006848 /* 0x684c --> 0x6c00 unused */ +#define GRC_FASTBOOT_PC 0x00006894 /* 5752, 5755, 5787 */ /* 0x6c00 --> 0x7000 unused */ @@ -2247,6 +2249,7 @@ struct tg3 { #define PHY_ID_BCM5752 0x60008100 #define PHY_ID_BCM5714 0x60008340 #define PHY_ID_BCM5780 0x60008350 +#define PHY_ID_BCM5787 0xbc050ce0 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_INVALID 0xffffffff #define PHY_ID_REV_MASK 0x0000000f @@ -2271,7 +2274,8 @@ struct tg3 { (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \ - (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM8002) + (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \ + (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index a3a09cceb026..b9810ddf435a 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1861,14 +1861,18 @@ #define PCI_DEVICE_ID_TIGON3_5780 0x166a #define PCI_DEVICE_ID_TIGON3_5780S 0x166b #define PCI_DEVICE_ID_TIGON3_5705F 0x166e +#define PCI_DEVICE_ID_TIGON3_5754M 0x1672 #define PCI_DEVICE_ID_TIGON3_5750 0x1676 #define PCI_DEVICE_ID_TIGON3_5751 0x1677 #define PCI_DEVICE_ID_TIGON3_5715 0x1678 #define PCI_DEVICE_ID_TIGON3_5715S 0x1679 +#define PCI_DEVICE_ID_TIGON3_5754 0x167a #define PCI_DEVICE_ID_TIGON3_5750M 0x167c #define PCI_DEVICE_ID_TIGON3_5751M 0x167d #define PCI_DEVICE_ID_TIGON3_5751F 0x167e +#define PCI_DEVICE_ID_TIGON3_5787M 0x1693 #define PCI_DEVICE_ID_TIGON3_5782 0x1696 +#define PCI_DEVICE_ID_TIGON3_5787 0x169b #define PCI_DEVICE_ID_TIGON3_5788 0x169c #define PCI_DEVICE_ID_TIGON3_5789 0x169d #define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 -- cgit v1.2.3-59-g8ed1b From 1b27777a9b9b2b6d1c06000b7a31262d198b4238 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 22:27:48 -0800 Subject: [TG3]: Add 5787 nvram support Support additional nvrams and new nvram format for 5787 and 5754. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++-------- drivers/net/tg3.h | 7 +++ 2 files changed, 130 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e6ed940d7714..9cd8613625f8 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7816,29 +7816,53 @@ static void tg3_get_ethtool_stats (struct net_device *dev, } #define NVRAM_TEST_SIZE 0x100 +#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14 static int tg3_test_nvram(struct tg3 *tp) { - u32 *buf, csum; - int i, j, err = 0; + u32 *buf, csum, magic; + int i, j, err = 0, size; - buf = kmalloc(NVRAM_TEST_SIZE, GFP_KERNEL); + if (tg3_nvram_read(tp, 0, &magic) != 0) + return -EIO; + + magic = swab32(magic); + if (magic == TG3_EEPROM_MAGIC) + size = NVRAM_TEST_SIZE; + else if ((magic & 0xff000000) == 0xa5000000) { + if ((magic & 0xe00000) == 0x200000) + size = NVRAM_SELFBOOT_FORMAT1_SIZE; + else + return 0; + } else + return -EIO; + + buf = kmalloc(size, GFP_KERNEL); if (buf == NULL) return -ENOMEM; - for (i = 0, j = 0; i < NVRAM_TEST_SIZE; i += 4, j++) { + err = -EIO; + for (i = 0, j = 0; i < size; i += 4, j++) { u32 val; if ((err = tg3_nvram_read(tp, i, &val)) != 0) break; buf[j] = cpu_to_le32(val); } - if (i < NVRAM_TEST_SIZE) + if (i < size) goto out; - err = -EIO; - if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) - goto out; + /* Selfboot format */ + if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) { + u8 *buf8 = (u8 *) buf, csum8 = 0; + + for (i = 0; i < size; i++) + csum8 += buf8[i]; + + if (csum8 == 0) + return 0; + return -EIO; + } /* Bootstrap checksum at offset 0x10 */ csum = calc_crc((unsigned char *) buf, 0x10); @@ -8561,14 +8585,15 @@ static struct ethtool_ops tg3_ethtool_ops = { static void __devinit tg3_get_eeprom_size(struct tg3 *tp) { - u32 cursize, val; + u32 cursize, val, magic; tp->nvram_size = EEPROM_CHIP_SIZE; if (tg3_nvram_read(tp, 0, &val) != 0) return; - if (swab32(val) != TG3_EEPROM_MAGIC) + magic = swab32(val); + if ((magic != TG3_EEPROM_MAGIC) && ((magic & 0xff000000) != 0xa5000000)) return; /* @@ -8576,13 +8601,13 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp) * When we encounter our validation signature, we know the addressing * has wrapped around, and thus have our chip size. */ - cursize = 0x800; + cursize = 0x10; while (cursize < tp->nvram_size) { if (tg3_nvram_read(tp, cursize, &val) != 0) return; - if (swab32(val) == TG3_EEPROM_MAGIC) + if (swab32(val) == magic) break; cursize <<= 1; @@ -8595,6 +8620,15 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp) { u32 val; + if (tg3_nvram_read(tp, 0, &val) != 0) + return; + + /* Selfboot format */ + if (swab32(val) != TG3_EEPROM_MAGIC) { + tg3_get_eeprom_size(tp); + return; + } + if (tg3_nvram_read(tp, 0xf0, &val) == 0) { if (val != 0) { tp->nvram_size = (val >> 16) * 1024; @@ -8718,6 +8752,44 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) } } +static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) +{ + u32 nvcfg1; + + nvcfg1 = tr32(NVRAM_CFG1); + + switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { + case FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ: + case FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ: + case FLASH_5787VENDOR_MICRO_EEPROM_64KHZ: + case FLASH_5787VENDOR_MICRO_EEPROM_376KHZ: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; + + nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; + tw32(NVRAM_CFG1, nvcfg1); + break; + case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: + case FLASH_5755VENDOR_ATMEL_FLASH_1: + case FLASH_5755VENDOR_ATMEL_FLASH_2: + case FLASH_5755VENDOR_ATMEL_FLASH_3: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 264; + break; + case FLASH_5752VENDOR_ST_M45PE10: + case FLASH_5752VENDOR_ST_M45PE20: + case FLASH_5752VENDOR_ST_M45PE40: + tp->nvram_jedecnum = JEDEC_ST; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 256; + break; + } +} + /* Chips other than 5700/5701 use the NVRAM for fetching info. */ static void __devinit tg3_nvram_init(struct tg3 *tp) { @@ -8753,6 +8825,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) tg3_get_5752_nvram_info(tp); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + tg3_get_5787_nvram_info(tp); else tg3_get_nvram_info(tp); @@ -9041,6 +9115,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, nvram_cmd |= NVRAM_CMD_LAST; if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { @@ -9444,6 +9519,7 @@ static void __devinit tg3_read_partno(struct tg3 *tp) { unsigned char vpd_data[256]; int i; + u32 magic; if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { /* Sun decided not to put the necessary bits in the @@ -9453,16 +9529,43 @@ static void __devinit tg3_read_partno(struct tg3 *tp) return; } - for (i = 0; i < 256; i += 4) { - u32 tmp; + if (tg3_nvram_read(tp, 0x0, &magic)) + return; - if (tg3_nvram_read(tp, 0x100 + i, &tmp)) - goto out_not_found; + if (swab32(magic) == TG3_EEPROM_MAGIC) { + for (i = 0; i < 256; i += 4) { + u32 tmp; - vpd_data[i + 0] = ((tmp >> 0) & 0xff); - vpd_data[i + 1] = ((tmp >> 8) & 0xff); - vpd_data[i + 2] = ((tmp >> 16) & 0xff); - vpd_data[i + 3] = ((tmp >> 24) & 0xff); + if (tg3_nvram_read(tp, 0x100 + i, &tmp)) + goto out_not_found; + + vpd_data[i + 0] = ((tmp >> 0) & 0xff); + vpd_data[i + 1] = ((tmp >> 8) & 0xff); + vpd_data[i + 2] = ((tmp >> 16) & 0xff); + vpd_data[i + 3] = ((tmp >> 24) & 0xff); + } + } else { + int vpd_cap; + + vpd_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_VPD); + for (i = 0; i < 256; i += 4) { + u32 tmp, j = 0; + u16 tmp16; + + pci_write_config_word(tp->pdev, vpd_cap + PCI_VPD_ADDR, + i); + while (j++ < 100) { + pci_read_config_word(tp->pdev, vpd_cap + + PCI_VPD_ADDR, &tmp16); + if (tmp16 & 0x8000) + break; + msleep(1); + } + pci_read_config_dword(tp->pdev, vpd_cap + PCI_VPD_DATA, + &tmp); + tmp = cpu_to_le32(tmp); + memcpy(&vpd_data[i], &tmp, 4); + } } /* Now parse and find the part number. */ diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 8d32fbe0d303..6a0d2fa05740 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1438,6 +1438,13 @@ #define FLASH_5752VENDOR_ST_M45PE10 0x02400000 #define FLASH_5752VENDOR_ST_M45PE20 0x02400002 #define FLASH_5752VENDOR_ST_M45PE40 0x02400001 +#define FLASH_5755VENDOR_ATMEL_FLASH_1 0x03400001 +#define FLASH_5755VENDOR_ATMEL_FLASH_2 0x03400002 +#define FLASH_5755VENDOR_ATMEL_FLASH_3 0x03400000 +#define FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ 0x03000003 +#define FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ 0x03000002 +#define FLASH_5787VENDOR_MICRO_EEPROM_64KHZ 0x03000000 +#define FLASH_5787VENDOR_MICRO_EEPROM_376KHZ 0x02000000 #define NVRAM_CFG1_5752PAGE_SIZE_MASK 0x70000000 #define FLASH_5752PAGE_SIZE_256 0x00000000 #define FLASH_5752PAGE_SIZE_512 0x10000000 -- cgit v1.2.3-59-g8ed1b From 5a6f3074c2ea5a7b4ff5b18f0e1fd9b1257e1a29 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 22:28:05 -0800 Subject: [TG3]: Add new hard_start_xmit Support 5787 hardware TSO using a new flag TG3_FLG2_HW_TSO_2. Since the TSO interface is slightly different and these chips have finally fixed the 4GB DMA problem and do not have the 40-bit DMA problem, a new hard_start_xmit is used for these chips. All previous chips will use the old hard_start_xmit that is now renamed tg3_start_xmit_dma_bug(). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- drivers/net/tg3.h | 4 +- 2 files changed, 142 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 9cd8613625f8..d4035de6440e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3655,7 +3655,135 @@ static void tg3_set_txd(struct tg3 *tp, int entry, txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; } +/* hard_start_xmit for devices that don't have any bugs and + * support TG3_FLG2_HW_TSO_2 only. + */ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct tg3 *tp = netdev_priv(dev); + dma_addr_t mapping; + u32 len, entry, base_flags, mss; + + len = skb_headlen(skb); + + /* No BH disabling for tx_lock here. We are running in BH disabled + * context and TX reclaim runs via tp->poll inside of a software + * interrupt. Furthermore, IRQ processing runs lockless so we have + * no IRQ context deadlocks to worry about either. Rejoice! + */ + if (!spin_trylock(&tp->tx_lock)) + return NETDEV_TX_LOCKED; + + if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { + if (!netif_queue_stopped(dev)) { + netif_stop_queue(dev); + + /* This is a hard error, log it. */ + printk(KERN_ERR PFX "%s: BUG! Tx Ring full when " + "queue awake!\n", dev->name); + } + spin_unlock(&tp->tx_lock); + return NETDEV_TX_BUSY; + } + + entry = tp->tx_prod; + base_flags = 0; +#if TG3_TSO_SUPPORT != 0 + mss = 0; + if (skb->len > (tp->dev->mtu + ETH_HLEN) && + (mss = skb_shinfo(skb)->tso_size) != 0) { + int tcp_opt_len, ip_tcp_len; + + if (skb_header_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { + dev_kfree_skb(skb); + goto out_unlock; + } + + tcp_opt_len = ((skb->h.th->doff - 5) * 4); + ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); + + base_flags |= (TXD_FLAG_CPU_PRE_DMA | + TXD_FLAG_CPU_POST_DMA); + + skb->nh.iph->check = 0; + skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); + + skb->h.th->check = 0; + + mss |= (ip_tcp_len + tcp_opt_len) << 9; + } + else if (skb->ip_summed == CHECKSUM_HW) + base_flags |= TXD_FLAG_TCPUDP_CSUM; +#else + mss = 0; + if (skb->ip_summed == CHECKSUM_HW) + base_flags |= TXD_FLAG_TCPUDP_CSUM; +#endif +#if TG3_VLAN_TAG_USED + if (tp->vlgrp != NULL && vlan_tx_tag_present(skb)) + base_flags |= (TXD_FLAG_VLAN | + (vlan_tx_tag_get(skb) << 16)); +#endif + + /* Queue skb data, a.k.a. the main skb fragment. */ + mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE); + + tp->tx_buffers[entry].skb = skb; + pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); + + tg3_set_txd(tp, entry, mapping, len, base_flags, + (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); + + entry = NEXT_TX(entry); + + /* Now loop through additional data fragments, and queue them. */ + if (skb_shinfo(skb)->nr_frags > 0) { + unsigned int i, last; + + last = skb_shinfo(skb)->nr_frags - 1; + for (i = 0; i <= last; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + len = frag->size; + mapping = pci_map_page(tp->pdev, + frag->page, + frag->page_offset, + len, PCI_DMA_TODEVICE); + + tp->tx_buffers[entry].skb = NULL; + pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); + + tg3_set_txd(tp, entry, mapping, len, + base_flags, (i == last) | (mss << 1)); + + entry = NEXT_TX(entry); + } + } + + /* Packets are ready, update Tx producer idx local and on card. */ + tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); + + tp->tx_prod = entry; + if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) { + netif_stop_queue(dev); + if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH) + netif_wake_queue(tp->dev); + } + +out_unlock: + mmiowb(); + spin_unlock(&tp->tx_lock); + + dev->trans_start = jiffies; + + return NETDEV_TX_OK; +} + +/* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and + * support TG3_FLG2_HW_TSO_1 or firmware TSO only. + */ +static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); dma_addr_t mapping; @@ -9811,8 +9939,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)) tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; - if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) - tp->tg3_flags2 |= TG3_FLG2_HW_TSO; + if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; + else + tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1; + } if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && @@ -10163,10 +10295,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) else tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES; - /* It seems all chips can get confused if TX buffers + /* All chips before 5787 can get confused if TX buffers * straddle the 4GB address boundary in some cases. */ - tp->dev->hard_start_xmit = tg3_start_xmit; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + tp->dev->hard_start_xmit = tg3_start_xmit; + else + tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug; tp->rx_offset = 2; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 6a0d2fa05740..ba3466c8a96d 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2194,7 +2194,7 @@ struct tg3 { #define TG3_FLG2_PHY_SERDES 0x00002000 #define TG3_FLG2_CAPACITIVE_COUPLING 0x00004000 #define TG3_FLG2_FLASH 0x00008000 -#define TG3_FLG2_HW_TSO 0x00010000 +#define TG3_FLG2_HW_TSO_1 0x00010000 #define TG3_FLG2_SERDES_PREEMPHASIS 0x00020000 #define TG3_FLG2_5705_PLUS 0x00040000 #define TG3_FLG2_5750_PLUS 0x00080000 @@ -2207,6 +2207,8 @@ struct tg3 { #define TG3_FLG2_PARALLEL_DETECT 0x01000000 #define TG3_FLG2_ICH_WORKAROUND 0x02000000 #define TG3_FLG2_5780_CLASS 0x04000000 +#define TG3_FLG2_HW_TSO_2 0x08000000 +#define TG3_FLG2_HW_TSO (TG3_FLG2_HW_TSO_1 | TG3_FLG2_HW_TSO_2) u32 split_mode_max_reqs; #define SPLIT_MODE_5704_MAX_REQ 3 -- cgit v1.2.3-59-g8ed1b From 9c27dbdf64cba05d0cacc343118a7fd01d4b82f7 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 22:28:27 -0800 Subject: [TG3]: Add ipv6 checksum support Support ipv6 tx csum on 5787 by setting NETIF_F_HW_CSUM. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d4035de6440e..5182a3be7f21 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7871,10 +7871,10 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) return 0; } - if (data) - dev->features |= NETIF_F_IP_CSUM; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + ethtool_op_set_tx_hw_csum(dev, data); else - dev->features &= ~NETIF_F_IP_CSUM; + ethtool_op_set_tx_csum(dev, data); return 0; } @@ -11236,7 +11236,11 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * checksumming. */ if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + dev->features |= NETIF_F_HW_CSUM; + else + dev->features |= NETIF_F_IP_CSUM; + dev->features |= NETIF_F_SG; tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; } else tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; -- cgit v1.2.3-59-g8ed1b From fcfa0a32c767219c1bdad621ef4a3aff1904cbbd Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 22:28:41 -0800 Subject: [TG3]: Add new one-shot MSI handler Support one-shot MSI on 5787. This one-shot MSI idea is credited to David Miller. In this mode, MSI disables itself automatically after it is generated, saving the driver a register access to disable it for NAPI. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 85 +++++++++++++++++++++++++++++++++++-------------------- drivers/net/tg3.h | 1 + 2 files changed, 55 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 5182a3be7f21..40f52897cf9b 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -546,6 +546,9 @@ static void tg3_enable_ints(struct tg3 *tp) (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, (tp->last_tag << 24)); + if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) + tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, + (tp->last_tag << 24)); tg3_cond_int(tp); } @@ -3365,6 +3368,23 @@ static inline void tg3_full_unlock(struct tg3 *tp) spin_unlock_bh(&tp->lock); } +/* One-shot MSI handler - Chip automatically disables interrupt + * after sending MSI so driver doesn't have to do it. + */ +static irqreturn_t tg3_msi_1shot(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + struct tg3 *tp = netdev_priv(dev); + + prefetch(tp->hw_status); + prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); + + if (likely(!tg3_irq_sync(tp))) + netif_rx_schedule(dev); /* schedule NAPI poll */ + + return IRQ_HANDLED; +} + /* MSI ISR - No need to check for interrupt sharing and no need to * flush status block and interrupt mailbox. PCI ordering rules * guarantee that MSI will arrive after the status block. @@ -6511,6 +6531,26 @@ static void tg3_timer(unsigned long __opaque) add_timer(&tp->timer); } +int tg3_request_irq(struct tg3 *tp) +{ + irqreturn_t (*fn)(int, void *, struct pt_regs *); + unsigned long flags; + struct net_device *dev = tp->dev; + + if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { + fn = tg3_msi; + if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) + fn = tg3_msi_1shot; + flags = SA_SAMPLE_RANDOM; + } else { + fn = tg3_interrupt; + if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) + fn = tg3_interrupt_tagged; + flags = SA_SHIRQ | SA_SAMPLE_RANDOM; + } + return (request_irq(tp->pdev->irq, fn, flags, dev->name, dev)); +} + static int tg3_test_interrupt(struct tg3 *tp) { struct net_device *dev = tp->dev; @@ -6547,16 +6587,7 @@ static int tg3_test_interrupt(struct tg3 *tp) free_irq(tp->pdev->irq, dev); - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) - err = request_irq(tp->pdev->irq, tg3_msi, - SA_SAMPLE_RANDOM, dev->name, dev); - else { - irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt; - if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) - fn = tg3_interrupt_tagged; - err = request_irq(tp->pdev->irq, fn, - SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); - } + err = tg3_request_irq(tp); if (err) return err; @@ -6608,14 +6639,7 @@ static int tg3_test_msi(struct tg3 *tp) tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; - { - irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt; - if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) - fn = tg3_interrupt_tagged; - - err = request_irq(tp->pdev->irq, fn, - SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); - } + err = tg3_request_irq(tp); if (err) return err; @@ -6677,17 +6701,7 @@ static int tg3_open(struct net_device *dev) tp->tg3_flags2 |= TG3_FLG2_USING_MSI; } } - if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) - err = request_irq(tp->pdev->irq, tg3_msi, - SA_SAMPLE_RANDOM, dev->name, dev); - else { - irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt; - if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) - fn = tg3_interrupt_tagged; - - err = request_irq(tp->pdev->irq, fn, - SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); - } + err = tg3_request_irq(tp); if (err) { if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { @@ -6752,6 +6766,14 @@ static int tg3_open(struct net_device *dev) return err; } + + if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { + if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) { + u32 val = tr32(0x7c04); + + tw32(0x7c04, val | (1 << 29)); + } + } } tg3_full_lock(tp, 0); @@ -9940,9 +9962,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; - else + tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; + } else tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index ba3466c8a96d..6b05d5786cd7 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2209,6 +2209,7 @@ struct tg3 { #define TG3_FLG2_5780_CLASS 0x04000000 #define TG3_FLG2_HW_TSO_2 0x08000000 #define TG3_FLG2_HW_TSO (TG3_FLG2_HW_TSO_1 | TG3_FLG2_HW_TSO_2) +#define TG3_FLG2_1SHOT_MSI 0x10000000 u32 split_mode_max_reqs; #define SPLIT_MODE_5704_MAX_REQ 3 -- cgit v1.2.3-59-g8ed1b From 79f4d13a15774c2d442b619bad95a4c612eed4f3 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 22:28:57 -0800 Subject: [TG3]: Fixup memory test for 5787 Ethtool memory test on 5787 requires a new memory table. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 40f52897cf9b..fe5c565a5284 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8306,14 +8306,24 @@ static int tg3_test_memory(struct tg3 *tp) { 0x00008000, 0x02000}, { 0x00010000, 0x0e000}, { 0xffffffff, 0x00000} + }, mem_tbl_5755[] = { + { 0x00000200, 0x00008}, + { 0x00004000, 0x00800}, + { 0x00006000, 0x00800}, + { 0x00008000, 0x02000}, + { 0x00010000, 0x0c000}, + { 0xffffffff, 0x00000} }; struct mem_entry *mem_tbl; int err = 0; int i; - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) - mem_tbl = mem_tbl_5705; - else + if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + mem_tbl = mem_tbl_5755; + else + mem_tbl = mem_tbl_5705; + } else mem_tbl = mem_tbl_570x; for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) { -- cgit v1.2.3-59-g8ed1b From 1820180b0e59cc48019414018b180518059f50d3 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 22:29:15 -0800 Subject: [TG3]: nvram cleanup Some nvram related cleanup: 1. Add a tg3_nvram_read_swab() since swabing the data is frequently done. 2. Add a function to convert nvram address to physical address instead of doing it in 2 separate places. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 62 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index fe5c565a5284..602326b78ef9 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7457,6 +7457,7 @@ static int tg3_get_eeprom_len(struct net_device *dev) } static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val); +static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val); static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { @@ -7973,10 +7974,9 @@ static int tg3_test_nvram(struct tg3 *tp) u32 *buf, csum, magic; int i, j, err = 0, size; - if (tg3_nvram_read(tp, 0, &magic) != 0) + if (tg3_nvram_read_swab(tp, 0, &magic) != 0) return -EIO; - magic = swab32(magic); if (magic == TG3_EEPROM_MAGIC) size = NVRAM_TEST_SIZE; else if ((magic & 0xff000000) == 0xa5000000) { @@ -8749,10 +8749,9 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp) tp->nvram_size = EEPROM_CHIP_SIZE; - if (tg3_nvram_read(tp, 0, &val) != 0) + if (tg3_nvram_read_swab(tp, 0, &magic) != 0) return; - magic = swab32(val); if ((magic != TG3_EEPROM_MAGIC) && ((magic & 0xff000000) != 0xa5000000)) return; @@ -8764,10 +8763,10 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp) cursize = 0x10; while (cursize < tp->nvram_size) { - if (tg3_nvram_read(tp, cursize, &val) != 0) + if (tg3_nvram_read_swab(tp, cursize, &val) != 0) return; - if (swab32(val) == magic) + if (val == magic) break; cursize <<= 1; @@ -8780,11 +8779,11 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp) { u32 val; - if (tg3_nvram_read(tp, 0, &val) != 0) + if (tg3_nvram_read_swab(tp, 0, &val) != 0) return; /* Selfboot format */ - if (swab32(val) != TG3_EEPROM_MAGIC) { + if (val != TG3_EEPROM_MAGIC) { tg3_get_eeprom_size(tp); return; } @@ -9056,6 +9055,20 @@ static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd) return 0; } +static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr) +{ + if ((tp->tg3_flags & TG3_FLAG_NVRAM) && + (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && + (tp->tg3_flags2 & TG3_FLG2_FLASH) && + (tp->nvram_jedecnum == JEDEC_ATMEL)) + + addr = ((addr / tp->nvram_pagesize) << + ATMEL_AT45DB0X1B_PAGE_POS) + + (addr % tp->nvram_pagesize); + + return addr; +} + static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) { int ret; @@ -9068,14 +9081,7 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) return tg3_nvram_read_using_eeprom(tp, offset, val); - if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && - (tp->tg3_flags2 & TG3_FLG2_FLASH) && - (tp->nvram_jedecnum == JEDEC_ATMEL)) { - - offset = ((offset / tp->nvram_pagesize) << - ATMEL_AT45DB0X1B_PAGE_POS) + - (offset % tp->nvram_pagesize); - } + offset = tg3_nvram_phys_addr(tp, offset); if (offset > NVRAM_ADDR_MSK) return -EINVAL; @@ -9100,6 +9106,16 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) return ret; } +static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val) +{ + int err; + u32 tmp; + + err = tg3_nvram_read(tp, offset, &tmp); + *val = swab32(tmp); + return err; +} + static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, u32 offset, u32 len, u8 *buf) { @@ -9252,15 +9268,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, page_off = offset % tp->nvram_pagesize; - if ((tp->tg3_flags2 & TG3_FLG2_FLASH) && - (tp->nvram_jedecnum == JEDEC_ATMEL)) { - - phy_addr = ((offset / tp->nvram_pagesize) << - ATMEL_AT45DB0X1B_PAGE_POS) + page_off; - } - else { - phy_addr = offset; - } + phy_addr = tg3_nvram_phys_addr(tp, offset); tw32(NVRAM_ADDR, phy_addr); @@ -9689,10 +9697,10 @@ static void __devinit tg3_read_partno(struct tg3 *tp) return; } - if (tg3_nvram_read(tp, 0x0, &magic)) + if (tg3_nvram_read_swab(tp, 0x0, &magic)) return; - if (swab32(magic) == TG3_EEPROM_MAGIC) { + if (magic == TG3_EEPROM_MAGIC) { for (i = 0; i < 256; i += 4) { u32 tmp; -- cgit v1.2.3-59-g8ed1b From c4e6575c78b83928c470d81b271909084a2efd37 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 22:29:32 -0800 Subject: [TG3]: Add firmware version info Add fw_version information to ethtool -i. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/tg3.h | 1 + 2 files changed, 57 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 602326b78ef9..0a4e7b74c1fc 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7666,6 +7666,7 @@ static void tg3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info strcpy(info->driver, DRV_MODULE_NAME); strcpy(info->version, DRV_MODULE_VERSION); + strcpy(info->fw_version, tp->fw_ver); strcpy(info->bus_info, pci_name(tp->pdev)); } @@ -9069,6 +9070,20 @@ static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr) return addr; } +static u32 tg3_nvram_logical_addr(struct tg3 *tp, u32 addr) +{ + if ((tp->tg3_flags & TG3_FLAG_NVRAM) && + (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && + (tp->tg3_flags2 & TG3_FLG2_FLASH) && + (tp->nvram_jedecnum == JEDEC_ATMEL)) + + addr = ((addr >> ATMEL_AT45DB0X1B_PAGE_POS) * + tp->nvram_pagesize) + + (addr & ((1 << ATMEL_AT45DB0X1B_PAGE_POS) - 1)); + + return addr; +} + static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) { int ret; @@ -9780,6 +9795,46 @@ out_not_found: strcpy(tp->board_part_number, "none"); } +static void __devinit tg3_read_fw_ver(struct tg3 *tp) +{ + u32 val, offset, start; + + if (tg3_nvram_read_swab(tp, 0, &val)) + return; + + if (val != TG3_EEPROM_MAGIC) + return; + + if (tg3_nvram_read_swab(tp, 0xc, &offset) || + tg3_nvram_read_swab(tp, 0x4, &start)) + return; + + offset = tg3_nvram_logical_addr(tp, offset); + if (tg3_nvram_read_swab(tp, offset, &val)) + return; + + if ((val & 0xfc000000) == 0x0c000000) { + u32 ver_offset, addr; + int i; + + if (tg3_nvram_read_swab(tp, offset + 4, &val) || + tg3_nvram_read_swab(tp, offset + 8, &ver_offset)) + return; + + if (val != 0) + return; + + addr = offset + ver_offset - start; + for (i = 0; i < 16; i += 4) { + if (tg3_nvram_read(tp, addr + i, &val)) + return; + + val = cpu_to_le32(val); + memcpy(tp->fw_ver + i, &val, 4); + } + } +} + #ifdef CONFIG_SPARC64 static int __devinit tg3_is_sun_570X(struct tg3 *tp) { @@ -10301,6 +10356,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } tg3_read_partno(tp); + tg3_read_fw_ver(tp); if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 6b05d5786cd7..baa34c4721db 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2271,6 +2271,7 @@ struct tg3 { u32 led_ctrl; char board_part_number[24]; + char fw_ver[16]; u32 nic_sram_data_cfg; u32 pci_clock_ctrl; struct pci_dev *pdev_peer; -- cgit v1.2.3-59-g8ed1b From e9e678006ee865b0f7e53069b0e519141a710a6e Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 20 Mar 2006 22:29:52 -0800 Subject: [TG3]: update version and reldate Update version to 3.52. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0a4e7b74c1fc..e0691cf16456 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.51" -#define DRV_MODULE_RELDATE "Feb 21, 2006" +#define DRV_MODULE_VERSION "3.52" +#define DRV_MODULE_RELDATE "Mar 06, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3-59-g8ed1b From 153330618691694af64f39fb56c9de051862380e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 22:32:28 -0800 Subject: [NET]: dev_put/dev_hold cleanup Get rid of the old __dev_put macro that is just a hold over from pre 2.6 kernel. And turn dev_hold into an inline instead of a macro. Signed-off-by: Stephen Hemminger Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 2 +- include/linux/netdevice.h | 6 ++++-- net/ipv4/igmp.c | 2 +- net/ipv4/ipmr.c | 4 ++-- net/sched/sch_generic.c | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index f39de16e6b97..49cd096a3c3d 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -920,7 +920,7 @@ e1000_remove(struct pci_dev *pdev) unregister_netdev(netdev); #ifdef CONFIG_E1000_NAPI for (i = 0; i < adapter->num_rx_queues; i++) - __dev_put(&adapter->polling_netdev[i]); + dev_put(&adapter->polling_netdev[i]); #endif if (!e1000_check_phy_reset_block(&adapter->hw)) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b825be201bce..950dc55e5192 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -712,8 +712,10 @@ static inline void dev_put(struct net_device *dev) atomic_dec(&dev->refcnt); } -#define __dev_put(dev) atomic_dec(&(dev)->refcnt) -#define dev_hold(dev) atomic_inc(&(dev)->refcnt) +static inline void dev_hold(struct net_device *dev) +{ + atomic_inc(&dev->refcnt); +} /* Carrier loss detection, dial on demand. The functions netif_carrier_on * and _off may be called from IRQ context, but it is caller diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 3ec502f19da0..d512239a1473 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1382,7 +1382,7 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr) dev = ip_dev_find(imr->imr_address.s_addr); if (!dev) return NULL; - __dev_put(dev); + dev_put(dev); } if (!dev && !ip_route_output_key(&rt, &fl)) { diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 5c94c222e3f3..717ab7d6d7b6 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -415,10 +415,10 @@ static int vif_add(struct vifctl *vifc, int mrtsock) return -ENOBUFS; break; case 0: - dev=ip_dev_find(vifc->vifc_lcl_addr.s_addr); + dev = ip_dev_find(vifc->vifc_lcl_addr.s_addr); if (!dev) return -EADDRNOTAVAIL; - __dev_put(dev); + dev_put(dev); break; default: return -EINVAL; diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 99ceb91f0150..31eb83717c26 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -234,7 +234,7 @@ static void dev_watchdog_down(struct net_device *dev) { spin_lock_bh(&dev->xmit_lock); if (del_timer(&dev->watchdog_timer)) - __dev_put(dev); + dev_put(dev); spin_unlock_bh(&dev->xmit_lock); } -- cgit v1.2.3-59-g8ed1b From d4ccd08cdfa8d34f4d25b62041343c52fc79385f Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Mon, 20 Mar 2006 22:32:53 -0800 Subject: [IRDA] sem2mutex: drivers/net/irda 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: David S. Miller --- drivers/net/irda/irtty-sir.c | 19 ++++++++++--------- drivers/net/irda/sir_dongle.c | 19 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 101750bf210f..6a98b7ae4975 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -338,7 +339,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop) /*****************************************************************/ /* serialize ldisc open/close with sir_dev */ -static DECLARE_MUTEX(irtty_sem); +static DEFINE_MUTEX(irtty_mutex); /* notifier from sir_dev when irda% device gets opened (ifup) */ @@ -348,11 +349,11 @@ static int irtty_start_dev(struct sir_dev *dev) struct tty_struct *tty; /* serialize with ldisc open/close */ - down(&irtty_sem); + mutex_lock(&irtty_mutex); priv = dev->priv; if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { - up(&irtty_sem); + mutex_unlock(&irtty_mutex); return -ESTALE; } @@ -363,7 +364,7 @@ static int irtty_start_dev(struct sir_dev *dev) /* Make sure we can receive more data */ irtty_stop_receiver(tty, FALSE); - up(&irtty_sem); + mutex_unlock(&irtty_mutex); return 0; } @@ -375,11 +376,11 @@ static int irtty_stop_dev(struct sir_dev *dev) struct tty_struct *tty; /* serialize with ldisc open/close */ - down(&irtty_sem); + mutex_lock(&irtty_mutex); priv = dev->priv; if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { - up(&irtty_sem); + mutex_unlock(&irtty_mutex); return -ESTALE; } @@ -390,7 +391,7 @@ static int irtty_stop_dev(struct sir_dev *dev) if (tty->driver->stop) tty->driver->stop(tty); - up(&irtty_sem); + mutex_unlock(&irtty_mutex); return 0; } @@ -514,13 +515,13 @@ static int irtty_open(struct tty_struct *tty) priv->dev = dev; /* serialize with start_dev - in case we were racing with ifup */ - down(&irtty_sem); + mutex_lock(&irtty_mutex); dev->priv = priv; tty->disc_data = priv; tty->receive_room = 65536; - up(&irtty_sem); + mutex_unlock(&irtty_mutex); IRDA_DEBUG(0, "%s - %s: irda line discipline opened\n", __FUNCTION__, tty->name); diff --git a/drivers/net/irda/sir_dongle.c b/drivers/net/irda/sir_dongle.c index 8d225921ae7b..d7e32d9554fc 100644 --- a/drivers/net/irda/sir_dongle.c +++ b/drivers/net/irda/sir_dongle.c @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -28,7 +29,7 @@ */ static LIST_HEAD(dongle_list); /* list of registered dongle drivers */ -static DECLARE_MUTEX(dongle_list_lock); /* protects the list */ +static DEFINE_MUTEX(dongle_list_lock); /* protects the list */ int irda_register_dongle(struct dongle_driver *new) { @@ -38,25 +39,25 @@ int irda_register_dongle(struct dongle_driver *new) IRDA_DEBUG(0, "%s : registering dongle \"%s\" (%d).\n", __FUNCTION__, new->driver_name, new->type); - down(&dongle_list_lock); + mutex_lock(&dongle_list_lock); list_for_each(entry, &dongle_list) { drv = list_entry(entry, struct dongle_driver, dongle_list); if (new->type == drv->type) { - up(&dongle_list_lock); + mutex_unlock(&dongle_list_lock); return -EEXIST; } } list_add(&new->dongle_list, &dongle_list); - up(&dongle_list_lock); + mutex_unlock(&dongle_list_lock); return 0; } EXPORT_SYMBOL(irda_register_dongle); int irda_unregister_dongle(struct dongle_driver *drv) { - down(&dongle_list_lock); + mutex_lock(&dongle_list_lock); list_del(&drv->dongle_list); - up(&dongle_list_lock); + mutex_unlock(&dongle_list_lock); return 0; } EXPORT_SYMBOL(irda_unregister_dongle); @@ -75,7 +76,7 @@ int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type) return -EBUSY; /* serialize access to the list of registered dongles */ - down(&dongle_list_lock); + mutex_lock(&dongle_list_lock); list_for_each(entry, &dongle_list) { drv = list_entry(entry, struct dongle_driver, dongle_list); @@ -109,14 +110,14 @@ int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type) if (!drv->open || (err=drv->open(dev))!=0) goto out_reject; /* failed to open driver */ - up(&dongle_list_lock); + mutex_unlock(&dongle_list_lock); return 0; out_reject: dev->dongle_drv = NULL; module_put(drv->owner); out_unlock: - up(&dongle_list_lock); + mutex_unlock(&dongle_list_lock); return err; } -- cgit v1.2.3-59-g8ed1b From 73a6c6306876c83ed992f1b15069a0ee9b3fa73b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 20 Mar 2006 22:33:41 -0800 Subject: [IRDA]: remove MODULE_PARM() MODULE_PARM() is deprecated and is about to go away altogether. Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/irda/toim3232-sir.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/toim3232-sir.c b/drivers/net/irda/toim3232-sir.c index f6e5fed6a36d..aa1a9b0ed83e 100644 --- a/drivers/net/irda/toim3232-sir.c +++ b/drivers/net/irda/toim3232-sir.c @@ -125,18 +125,18 @@ #include "sir-dev.h" -MODULE_PARM(toim3232delay, "i"); -MODULE_PARM_DESC(toim3232delay, "toim3232 dongle write complete delay"); static int toim3232delay = 150; /* default is 150 ms */ +module_param(toim3232delay, int, 0); +MODULE_PARM_DESC(toim3232delay, "toim3232 dongle write complete delay"); #if 0 -MODULE_PARM(toim3232flipdtr, "i"); -MODULE_PARM_DESC(toim3232flipdtr, "toim3232 dongle invert DTR (Reset)"); static int toim3232flipdtr = 0; /* default is DTR high to reset */ +module_param(toim3232flipdtr, int, 0); +MODULE_PARM_DESC(toim3232flipdtr, "toim3232 dongle invert DTR (Reset)"); -MODULE_PARM(toim3232fliptrs, "i"); -MODULE_PARM_DESC(toim3232fliprts, "toim3232 dongle invert RTS (BR/D)"); static int toim3232fliprts = 0; /* default is RTS high for baud change */ +module_param(toim3232fliptrs, int, 0); +MODULE_PARM_DESC(toim3232fliprts, "toim3232 dongle invert RTS (BR/D)"); #endif static int toim3232_open(struct sir_dev *); -- cgit v1.2.3-59-g8ed1b From 758df69ee01f7be99c2df5562ef278bab05623dd Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 20 Mar 2006 22:34:09 -0800 Subject: [CASSINI]: sem2mutex Semaphore to mutexes 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: David S. Miller --- drivers/net/cassini.c | 40 ++++++++++++++++++++-------------------- drivers/net/cassini.h | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 6e295fce5c6f..8f1573e658a5 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -91,6 +91,7 @@ #include #include #include +#include #include @@ -3892,7 +3893,7 @@ static void cas_reset(struct cas *cp, int blkflag) spin_unlock(&cp->stat_lock[N_TX_RINGS]); } -/* Shut down the chip, must be called with pm_sem held. */ +/* Shut down the chip, must be called with pm_mutex held. */ static void cas_shutdown(struct cas *cp) { unsigned long flags; @@ -4311,11 +4312,11 @@ static int cas_open(struct net_device *dev) int hw_was_up, err; unsigned long flags; - down(&cp->pm_sem); + mutex_lock(&cp->pm_mutex); hw_was_up = cp->hw_running; - /* The power-management semaphore protects the hw_running + /* The power-management mutex protects the hw_running * etc. state so it is safe to do this bit without cp->lock */ if (!cp->hw_running) { @@ -4364,7 +4365,7 @@ static int cas_open(struct net_device *dev) cas_unlock_all_restore(cp, flags); netif_start_queue(dev); - up(&cp->pm_sem); + mutex_unlock(&cp->pm_mutex); return 0; err_spare: @@ -4372,7 +4373,7 @@ err_spare: cas_free_rxds(cp); err_tx_tiny: cas_tx_tiny_free(cp); - up(&cp->pm_sem); + mutex_unlock(&cp->pm_mutex); return err; } @@ -4382,7 +4383,7 @@ static int cas_close(struct net_device *dev) struct cas *cp = netdev_priv(dev); /* Make sure we don't get distracted by suspend/resume */ - down(&cp->pm_sem); + mutex_lock(&cp->pm_mutex); netif_stop_queue(dev); @@ -4399,7 +4400,7 @@ static int cas_close(struct net_device *dev) cas_spare_free(cp); cas_free_rxds(cp); cas_tx_tiny_free(cp); - up(&cp->pm_sem); + mutex_unlock(&cp->pm_mutex); return 0; } @@ -4834,10 +4835,10 @@ static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) unsigned long flags; int rc = -EOPNOTSUPP; - /* Hold the PM semaphore while doing ioctl's or we may collide + /* Hold the PM mutex while doing ioctl's or we may collide * with open/close and power management and oops. */ - down(&cp->pm_sem); + mutex_lock(&cp->pm_mutex); switch (cmd) { case SIOCGMIIPHY: /* Get address of MII PHY in use. */ data->phy_id = cp->phy_addr; @@ -4867,7 +4868,7 @@ static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; }; - up(&cp->pm_sem); + mutex_unlock(&cp->pm_mutex); return rc; } @@ -4994,7 +4995,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, spin_lock_init(&cp->tx_lock[i]); } spin_lock_init(&cp->stat_lock[N_TX_RINGS]); - init_MUTEX(&cp->pm_sem); + mutex_init(&cp->pm_mutex); init_timer(&cp->link_timer); cp->link_timer.function = cas_link_timer; @@ -5116,10 +5117,10 @@ err_out_free_consistent: cp->init_block, cp->block_dvma); err_out_iounmap: - down(&cp->pm_sem); + mutex_lock(&cp->pm_mutex); if (cp->hw_running) cas_shutdown(cp); - up(&cp->pm_sem); + mutex_unlock(&cp->pm_mutex); iounmap(cp->regs); @@ -5152,11 +5153,11 @@ static void __devexit cas_remove_one(struct pci_dev *pdev) cp = netdev_priv(dev); unregister_netdev(dev); - down(&cp->pm_sem); + mutex_lock(&cp->pm_mutex); flush_scheduled_work(); if (cp->hw_running) cas_shutdown(cp); - up(&cp->pm_sem); + mutex_unlock(&cp->pm_mutex); #if 1 if (cp->orig_cacheline_size) { @@ -5183,10 +5184,7 @@ static int cas_suspend(struct pci_dev *pdev, pm_message_t state) struct cas *cp = netdev_priv(dev); unsigned long flags; - /* We hold the PM semaphore during entire driver - * sleep time - */ - down(&cp->pm_sem); + mutex_lock(&cp->pm_mutex); /* If the driver is opened, we stop the DMA */ if (cp->opened) { @@ -5206,6 +5204,7 @@ static int cas_suspend(struct pci_dev *pdev, pm_message_t state) if (cp->hw_running) cas_shutdown(cp); + mutex_unlock(&cp->pm_mutex); return 0; } @@ -5217,6 +5216,7 @@ static int cas_resume(struct pci_dev *pdev) printk(KERN_INFO "%s: resuming\n", dev->name); + mutex_lock(&cp->pm_mutex); cas_hard_reset(cp); if (cp->opened) { unsigned long flags; @@ -5229,7 +5229,7 @@ static int cas_resume(struct pci_dev *pdev) netif_device_attach(dev); } - up(&cp->pm_sem); + mutex_unlock(&cp->pm_mutex); return 0; } #endif /* CONFIG_PM */ diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h index 88063ef16cf6..ab55c7ee1012 100644 --- a/drivers/net/cassini.h +++ b/drivers/net/cassini.h @@ -4284,7 +4284,7 @@ struct cas { * (ie. not power managed) */ int hw_running; int opened; - struct semaphore pm_sem; /* open/close/suspend/resume */ + struct mutex pm_mutex; /* open/close/suspend/resume */ struct cas_init_block *init_block; struct cas_tx_desc *init_txds[MAX_TX_RINGS]; -- cgit v1.2.3-59-g8ed1b From e3968fc0f3db58e4c448ec20f66ce6da49d9bc5f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 20 Mar 2006 22:34:25 -0800 Subject: [SUNGEM]: sem2mutex Semaphore to mutexes 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: David S. Miller --- drivers/net/sungem.c | 37 +++++++++++++++++++------------------ drivers/net/sungem.h | 6 +++--- 2 files changed, 22 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 28ce47a02408..38cd30cb7c75 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -2284,7 +2285,7 @@ static void gem_reset_task(void *data) { struct gem *gp = (struct gem *) data; - down(&gp->pm_sem); + mutex_lock(&gp->pm_mutex); netif_poll_disable(gp->dev); @@ -2311,7 +2312,7 @@ static void gem_reset_task(void *data) netif_poll_enable(gp->dev); - up(&gp->pm_sem); + mutex_unlock(&gp->pm_mutex); } @@ -2320,14 +2321,14 @@ static int gem_open(struct net_device *dev) struct gem *gp = dev->priv; int rc = 0; - down(&gp->pm_sem); + mutex_lock(&gp->pm_mutex); /* We need the cell enabled */ if (!gp->asleep) rc = gem_do_start(dev); gp->opened = (rc == 0); - up(&gp->pm_sem); + mutex_unlock(&gp->pm_mutex); return rc; } @@ -2340,13 +2341,13 @@ static int gem_close(struct net_device *dev) * our caller (dev_close) already did it for us */ - down(&gp->pm_sem); + mutex_lock(&gp->pm_mutex); gp->opened = 0; if (!gp->asleep) gem_do_stop(dev, 0); - up(&gp->pm_sem); + mutex_unlock(&gp->pm_mutex); return 0; } @@ -2358,7 +2359,7 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state) struct gem *gp = dev->priv; unsigned long flags; - down(&gp->pm_sem); + mutex_lock(&gp->pm_mutex); netif_poll_disable(dev); @@ -2391,11 +2392,11 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state) /* Stop the link timer */ del_timer_sync(&gp->link_timer); - /* Now we release the semaphore to not block the reset task who + /* Now we release the mutex to not block the reset task who * can take it too. We are marked asleep, so there will be no * conflict here */ - up(&gp->pm_sem); + mutex_unlock(&gp->pm_mutex); /* Wait for a pending reset task to complete */ while (gp->reset_task_pending) @@ -2424,7 +2425,7 @@ static int gem_resume(struct pci_dev *pdev) printk(KERN_INFO "%s: resuming\n", dev->name); - down(&gp->pm_sem); + mutex_lock(&gp->pm_mutex); /* Keep the cell enabled during the entire operation, no need to * take a lock here tho since nothing else can happen while we are @@ -2440,7 +2441,7 @@ static int gem_resume(struct pci_dev *pdev) * still asleep, a new sleep cycle may bring it back */ gem_put_cell(gp); - up(&gp->pm_sem); + mutex_unlock(&gp->pm_mutex); return 0; } pci_set_master(gp->pdev); @@ -2486,7 +2487,7 @@ static int gem_resume(struct pci_dev *pdev) netif_poll_enable(dev); - up(&gp->pm_sem); + mutex_unlock(&gp->pm_mutex); return 0; } @@ -2591,7 +2592,7 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu) return 0; } - down(&gp->pm_sem); + mutex_lock(&gp->pm_mutex); spin_lock_irq(&gp->lock); spin_lock(&gp->tx_lock); dev->mtu = new_mtu; @@ -2602,7 +2603,7 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu) } spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); - up(&gp->pm_sem); + mutex_unlock(&gp->pm_mutex); return 0; } @@ -2771,10 +2772,10 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) int rc = -EOPNOTSUPP; unsigned long flags; - /* Hold the PM semaphore while doing ioctl's or we may collide + /* Hold the PM mutex while doing ioctl's or we may collide * with power management. */ - down(&gp->pm_sem); + mutex_lock(&gp->pm_mutex); spin_lock_irqsave(&gp->lock, flags); gem_get_cell(gp); @@ -2812,7 +2813,7 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) gem_put_cell(gp); spin_unlock_irqrestore(&gp->lock, flags); - up(&gp->pm_sem); + mutex_unlock(&gp->pm_mutex); return rc; } @@ -3033,7 +3034,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, spin_lock_init(&gp->lock); spin_lock_init(&gp->tx_lock); - init_MUTEX(&gp->pm_sem); + mutex_init(&gp->pm_mutex); init_timer(&gp->link_timer); gp->link_timer.function = gem_link_timer; diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h index 13006d759ad8..89847215d006 100644 --- a/drivers/net/sungem.h +++ b/drivers/net/sungem.h @@ -980,15 +980,15 @@ struct gem { int tx_new, tx_old; unsigned int has_wol : 1; /* chip supports wake-on-lan */ - unsigned int asleep : 1; /* chip asleep, protected by pm_sem */ + unsigned int asleep : 1; /* chip asleep, protected by pm_mutex */ unsigned int asleep_wol : 1; /* was asleep with WOL enabled */ - unsigned int opened : 1; /* driver opened, protected by pm_sem */ + unsigned int opened : 1; /* driver opened, protected by pm_mutex */ unsigned int running : 1; /* chip running, protected by lock */ /* cell enable count, protected by lock */ int cell_enabled; - struct semaphore pm_sem; + struct mutex pm_mutex; u32 msg_enable; u32 status; -- cgit v1.2.3-59-g8ed1b From 471a24c0589cd192dcd2c6770ab6252cd42b1cff Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 20 Mar 2006 22:34:52 -0800 Subject: [WAN]: fix section mismatch warning in sbni In latest -mm sbni gives following warning: WARNING: drivers/net/wan/sbni.o - Section mismatch: reference to \ .init.data: from .text between 'init_module' (at offset 0x14ef) and \ 'cleanup_module' The warning is caused by init_module() calling a function declared __init. Declare init_module() __init too to fix warning. Signed-off-by: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/wan/sbni.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index db2c798ba89e..175ba13bce41 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -1495,8 +1495,7 @@ module_param(skip_pci_probe, bool, 0); MODULE_LICENSE("GPL"); -int -init_module( void ) +int __init init_module( void ) { struct net_device *dev; int err; -- cgit v1.2.3-59-g8ed1b From 6613f82dd293b23f582a649b287fadbf8d23e6cf Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 20 Mar 2006 22:35:16 -0800 Subject: [ATM] suni: cast arg properly in SONET_SETFRAMING Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/atm/suni.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c index 06817dec0c25..b1d063cc4fbe 100644 --- a/drivers/atm/suni.c +++ b/drivers/atm/suni.c @@ -188,7 +188,7 @@ static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) case SONET_GETDIAG: return get_diag(dev,arg); case SONET_SETFRAMING: - if (arg != SONET_FRAME_SONET) return -EINVAL; + if ((int)(unsigned long)arg != SONET_FRAME_SONET) return -EINVAL; return 0; case SONET_GETFRAMING: return put_user(SONET_FRAME_SONET,(int __user *)arg) ? -- cgit v1.2.3-59-g8ed1b From 59f1741e541bf4f6139599389610a70de49c3ad2 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Mon, 20 Mar 2006 22:39:21 -0800 Subject: [TG3]: netif_carrier_off runs too early; could still be queued when init fails Move the netif_carrier_off() call from tg3_init_one()-> tg3_init_link_config() to tg3_open() as is the convention for most other network drivers. I was getting a panic after a tg3 device failed to initialize due to DMA failure. The oops pointed to the link watch queue with spinlock debugging enabled. Without spinlock debugging, the Oops didn't occur. I suspect that the link event was getting queued but not executed until after the DMA test had failed and the device was freed. The link event was then operating on freed memory, which could contain anything. With this patch applied, the Oops no longer occurs. [ Based upon feedback from Michael Chan, we move netif_carrier_off() to the end of tg3_init_one() instead of moving it to tg3_open() -DaveM ] Signed-off-by: Jeff Mahoney Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/tg3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e0691cf16456..5104efe8ebfb 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10926,7 +10926,6 @@ static void __devinit tg3_init_link_config(struct tg3 *tp) tp->link_config.speed = SPEED_INVALID; tp->link_config.duplex = DUPLEX_INVALID; tp->link_config.autoneg = AUTONEG_ENABLE; - netif_carrier_off(tp->dev); tp->link_config.active_speed = SPEED_INVALID; tp->link_config.active_duplex = DUPLEX_INVALID; tp->link_config.phy_is_low_power = 0; @@ -11390,6 +11389,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, (pdev->dma_mask == DMA_32BIT_MASK) ? 32 : (((u64) pdev->dma_mask == DMA_40BIT_MASK) ? 40 : 64)); + netif_carrier_off(tp->dev); + return 0; err_out_iounmap: -- cgit v1.2.3-59-g8ed1b From cbb042f9e1292434e3cacb90e67d8d381aeac5a9 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 20 Mar 2006 22:43:56 -0800 Subject: [NET]: Replace skb_pull/skb_postpull_rcsum with skb_pull_rcsum We're now starting to have quite a number of places that do skb_pull followed immediately by an skb_postpull_rcsum. We can merge these two operations into one function with skb_pull_rcsum. This makes sense since most pull operations on receive skb's need to update the checksum. I've decided to make this out-of-line since it is fairly big and the fast path where hardware checksums are enabled need to call csum_partial anyway. Since this is a brand new function we get to add an extra check on the len argument. As it is most callers of skb_pull ignore its return value which essentially means that there is no check on the len argument. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 4 ++-- drivers/net/pppoe.c | 3 +-- include/linux/skbuff.h | 4 +++- net/802/psnap.c | 3 +-- net/8021q/vlan_dev.c | 6 ++---- net/bridge/br_netfilter.c | 6 ++---- net/core/skbuff.c | 21 +++++++++++++++++++++ 7 files changed, 32 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 0245e40b51a1..f608c12e3e8b 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1691,8 +1691,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) || ppp->npmode[npi] != NPMODE_PASS) { kfree_skb(skb); } else { - skb_pull(skb, 2); /* chop off protocol */ - skb_postpull_rcsum(skb, skb->data - 2, 2); + /* chop off protocol */ + skb_pull_rcsum(skb, 2); skb->dev = ppp->dev; skb->protocol = htons(npindex_to_ethertype[npi]); skb->mac.raw = skb->data; diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 9369f811075d..475dc930380f 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -337,8 +337,7 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) if (sk->sk_state & PPPOX_BOUND) { struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; int len = ntohs(ph->length); - skb_pull(skb, sizeof(struct pppoe_hdr)); - skb_postpull_rcsum(skb, ph, sizeof(*ph)); + skb_pull_rcsum(skb, sizeof(struct pppoe_hdr)); if (pskb_trim_rcsum(skb, len)) goto abort_kfree; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 75c963103b9f..613b9513f8b9 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1159,12 +1159,14 @@ static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp) */ static inline void skb_postpull_rcsum(struct sk_buff *skb, - const void *start, int len) + const void *start, unsigned int len) { if (skb->ip_summed == CHECKSUM_HW) skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); } +unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len); + /** * pskb_trim_rcsum - trim received skb and update checksum * @skb: buffer to trim diff --git a/net/802/psnap.c b/net/802/psnap.c index 34e42968b477..97c95eec79ed 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -61,8 +61,7 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, /* Pass the frame on. */ u8 *hdr = skb->data; skb->h.raw += 5; - skb_pull(skb, 5); - skb_postpull_rcsum(skb, hdr, 5); + skb_pull_rcsum(skb, 5); rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); } else { skb->sk = NULL; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 0f604d227da2..da9cfe927158 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -163,10 +163,8 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, stats->rx_packets++; stats->rx_bytes += skb->len; - skb_pull(skb, VLAN_HLEN); /* take off the VLAN header (4 bytes currently) */ - - /* Need to correct hardware checksum */ - skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); + /* Take off the VLAN header (4 bytes currently) */ + skb_pull_rcsum(skb, VLAN_HLEN); /* Ok, lets check to make sure the device (dev) we * came in on is what this VLAN is attached to. diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index e060aad8624d..6787bc5197f7 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -425,8 +425,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, if (skb->protocol == __constant_htons(ETH_P_8021Q)) { u8 *vhdr = skb->data; - skb_pull(skb, VLAN_HLEN); - skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); + skb_pull_rcsum(skb, VLAN_HLEN); skb->nh.raw += VLAN_HLEN; } return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); @@ -444,8 +443,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, if (skb->protocol == __constant_htons(ETH_P_8021Q)) { u8 *vhdr = skb->data; - skb_pull(skb, VLAN_HLEN); - skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); + skb_pull_rcsum(skb, VLAN_HLEN); skb->nh.raw += VLAN_HLEN; } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 01abf1e8990b..2960c8b82b23 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1795,6 +1795,27 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, return 0; } +/** + * skb_pull_rcsum - pull skb and update receive checksum + * @skb: buffer to update + * @start: start of data before pull + * @len: length of data pulled + * + * This function performs an skb_pull on the packet and updates + * update the CHECKSUM_HW checksum. It should be used on receive + * path processing instead of skb_pull unless you know that the + * checksum difference is zero (e.g., a valid IP header) or you + * are setting ip_summed to CHECKSUM_NONE. + */ +unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) +{ + BUG_ON(len > skb->len); + skb->len -= len; + BUG_ON(skb->len < skb->data_len); + skb_postpull_rcsum(skb, skb->data, len); + return skb->data += len; +} + void __init skb_init(void) { skbuff_head_cache = kmem_cache_create("skbuff_head_cache", -- cgit v1.2.3-59-g8ed1b From e35fc385655ac584902edd98dd07ac488e986aa1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 22:46:40 -0800 Subject: [INFINIBAND] ipoib: Remove leftover use of neigh_ops->destructor Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index a2408d7ec598..19fd17384d0a 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -115,7 +115,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) if (neigh->ah) ipoib_put_ah(neigh->ah); *to_ipoib_neigh(neigh->neighbour) = NULL; - neigh->neighbour->ops->destructor = NULL; kfree(neigh); } -- cgit v1.2.3-59-g8ed1b From 81789ef5c9a435fbf94224987efe6fbb97ffab09 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 20 Mar 2006 23:00:14 -0800 Subject: [TG3]: make drivers/net/tg3.c:tg3_request_irq() static This patch makes the needlessly global function tg3_request_irq() static. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 5104efe8ebfb..b1e8d0698fac 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6531,7 +6531,7 @@ static void tg3_timer(unsigned long __opaque) add_timer(&tp->timer); } -int tg3_request_irq(struct tg3 *tp) +static int tg3_request_irq(struct tg3 *tp) { irqreturn_t (*fn)(int, void *, struct pt_regs *); unsigned long flags; -- cgit v1.2.3-59-g8ed1b From 30ca3e376e82cc44488b1d377adfb10b5818548e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 20 Mar 2006 23:02:36 -0800 Subject: [TG3]: Don't mark tg3_test_registers() as returning const. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b1e8d0698fac..e03d1ae50c3e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8059,7 +8059,7 @@ static int tg3_test_link(struct tg3 *tp) } /* Only test the commonly used registers */ -static const int tg3_test_registers(struct tg3 *tp) +static int tg3_test_registers(struct tg3 *tp) { int i, is_5705; u32 offset, read_mask, write_mask, val, save_val, read_val; -- cgit v1.2.3-59-g8ed1b From f10b7897ee29649fa7f0ccdc8d859ccd6ce7dbfd Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 25 Jan 2006 22:34:01 +1100 Subject: [CRYPTO] api: Align tfm context as wide as possible Since tfm contexts can contain arbitrary types we should provide at least natural alignment (__attribute__ ((__aligned__))) for them. In particular, this is needed on the Xscale which is a 32-bit architecture with a u64 type that requires 64-bit alignment. This problem was reported by Ronen Shitrit. The crypto_tfm structure's size was 44 bytes on 32-bit architectures and 80 bytes on 64-bit architectures. So adding this requirement only means that we have to add an extra 4 bytes on 32-bit architectures. On i386 the natural alignment is 16 bytes which also benefits the VIA Padlock as it no longer has to manually align its context structure to 128 bits. Signed-off-by: Herbert Xu --- crypto/api.c | 2 +- drivers/crypto/padlock-aes.c | 6 +++++- include/linux/crypto.h | 10 +++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/crypto/api.c b/crypto/api.c index e26156f71839..34e02caffc2a 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -165,7 +165,7 @@ static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags) break; } - return len + alg->cra_alignmask; + return len + (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1)); } struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 0c08c58252be..5158a9db4bc5 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -284,7 +284,11 @@ aes_hw_extkey_available(uint8_t key_len) static inline struct aes_ctx *aes_ctx(void *ctx) { - return (struct aes_ctx *)ALIGN((unsigned long)ctx, PADLOCK_ALIGNMENT); + unsigned long align = PADLOCK_ALIGNMENT; + + if (align <= crypto_tfm_ctx_alignment()) + align = 1; + return (struct aes_ctx *)ALIGN((unsigned long)ctx, align); } static int diff --git a/include/linux/crypto.h b/include/linux/crypto.h index d88bf8aa8b47..0ab1bc1152ca 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -229,6 +229,8 @@ struct crypto_tfm { } crt_u; struct crypto_alg *__crt_alg; + + char __crt_ctx[] __attribute__ ((__aligned__)); }; /* @@ -301,7 +303,13 @@ static inline unsigned int crypto_tfm_alg_alignmask(struct crypto_tfm *tfm) static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) { - return (void *)&tfm[1]; + return tfm->__crt_ctx; +} + +static inline unsigned int crypto_tfm_ctx_alignment(void) +{ + struct crypto_tfm *tfm; + return __alignof__(tfm->__crt_ctx); } /* -- cgit v1.2.3-59-g8ed1b From efcf55cb5c21d7142aeb1a5a4c14e40960600bd6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 9 Mar 2006 11:17:43 -0300 Subject: V4L/DVB (3419): This patch fixes Tuner TNF5335 family Radio now works. Tuner now supports both PAL/D and STD/MN models Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 3 +++ drivers/media/video/tuner-types.c | 27 +++++++++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index aba0688d7c1c..5d7abed71674 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -364,6 +364,9 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) case TUNER_PHILIPS_FMD1216ME_MK3: buffer[3] = 0x19; break; + case TUNER_TNF_5335MF: + buffer[3] = 0x11; + break; case TUNER_PHILIPS_FM1256_IH3: div = (20 * freq) / 16000 + (int)(33.3 * 20); /* IF 33.3 MHz */ buffer[3] = 0x19; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index db8b9873029b..b72ef44e149a 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -950,12 +950,22 @@ static struct tuner_params tuner_tuv1236d_params[] = { }, }; -/* ------------ TUNER_TNF_5335MF - Philips NTSC ------------ */ +/* ------------ TUNER_TNF_xxx5 - Texas Instruments--------- */ +/* This is known to work with Tenna TVF58t5-MFF and TVF5835 MFF + * but it is expected to work also with other Tenna/Ymec + * models based on TI SN 761677 chip on both PAL and NTSC + */ + +static struct tuner_range tuner_tnf_5335_d_if_pal_ranges[] = { + { 16 * 168.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 471.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, +}; static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x8e, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 0x04, }, + { 16 * 169.25 /*MHz*/, 0x8e, 0x01, }, + { 16 * 469.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_params tuner_tnf_5335mf_params[] = { @@ -964,6 +974,11 @@ static struct tuner_params tuner_tnf_5335mf_params[] = { .ranges = tuner_tnf_5335mf_ntsc_ranges, .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges), }, + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_tnf_5335_d_if_pal_ranges, + .count = ARRAY_SIZE(tuner_tnf_5335_d_if_pal_ranges), + }, }; /* 70-79 */ @@ -1354,8 +1369,8 @@ struct tunertype tuners[] = { .params = tuner_tuv1236d_params, .count = ARRAY_SIZE(tuner_tuv1236d_params), }, - [TUNER_TNF_5335MF] = { /* Philips NTSC */ - .name = "Tena TNF 5335 MF", + [TUNER_TNF_5335MF] = { /* Tenna PAL/NTSC */ + .name = "Tena TNF 5335 and similar models", .params = tuner_tnf_5335mf_params, .count = ARRAY_SIZE(tuner_tnf_5335mf_params), }, -- cgit v1.2.3-59-g8ed1b From 99ca99915068806552d1f90ce50bed4c7387d65a Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Thu, 9 Mar 2006 11:20:14 -0300 Subject: V4L/DVB (3420): Nskips maybe used uninitialized in bttv_risc_overlay The Coverity checker (previously Stanford checker) noticed that the value of nskips could be read even if it was never written. Signed-off-by: Duncan Sands Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bttv-risc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index a60c211c9e31..5c746110df62 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -276,6 +276,8 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, if (line > maxy) btcx_calc_skips(line, ov->w.width, &maxy, skips, &nskips, ov->clips, ov->nclips); + else + nskips = 0; /* write out risc code */ for (start = 0, skip = 0; start < ov->w.width; start = end) { -- cgit v1.2.3-59-g8ed1b From cef4e7af71ec16aba13ae291e41262a8913a56d8 Mon Sep 17 00:00:00 2001 From: Ian Pickworth Date: Thu, 9 Mar 2006 12:03:40 -0300 Subject: V4L/DVB (3423): Fix cx88 error messages on balance change There is an error in the cx88 code that causes this message in the syslog when balance is changed at full volume: Mar 4 18:35:08 ian2 kernel: cx88[0]: irq pci [0x1] vid* Mar 4 18:35:39 ian2 last message repeated 348 times Mar 4 18:36:01 ian2 last message repeated 564 times ... and so on The attached patch cures this problem. Signed-off-by: Ian Pickworth Signed-off-by: Marcin Rudowski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 21738b664bc9..cfa8668784b4 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -63,7 +63,7 @@ /* need "shadow" registers for some write-only ones ... */ #define SHADOW_AUD_VOL_CTL 1 #define SHADOW_AUD_BAL_CTL 2 -#define SHADOW_MAX 2 +#define SHADOW_MAX 3 /* FM Radio deemphasis type */ enum cx88_deemph_type { -- cgit v1.2.3-59-g8ed1b From 7947a220e5fe1373f1830b41fb7376bef636f113 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 9 Mar 2006 16:09:20 -0300 Subject: V4L/DVB (3424): Updated CARDLIST.tuner with newer tenna string Also Removed whitespaces introduced by previous tena patch Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.tuner | 2 +- drivers/media/video/tuner-types.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 603f165376fe..44069338b531 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -67,7 +67,7 @@ tuner=65 - Ymec TVF66T5-B/DFF tuner=66 - LG NTSC (TALN mini series) tuner=67 - Philips TD1316 Hybrid Tuner tuner=68 - Philips TUV1236D ATSC/NTSC dual in -tuner=69 - Tena TNF 5335 MF +tuner=69 - Tena TNF 5335 and similar models tuner=70 - Samsung TCPN 2121P30A tuner=71 - Xceive xc3028 tuner=72 - Thomson FE6600 diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index b72ef44e149a..e75904dddb12 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -958,8 +958,8 @@ static struct tuner_params tuner_tuv1236d_params[] = { static struct tuner_range tuner_tnf_5335_d_if_pal_ranges[] = { { 16 * 168.25 /*MHz*/, 0x8e, 0x01, }, - { 16 * 471.25 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 0x08, }, + { 16 * 471.25 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, }; static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = { -- cgit v1.2.3-59-g8ed1b From 4aca4831aafad64a8622cd855c5f952228d75d72 Mon Sep 17 00:00:00 2001 From: Marcin Rudowski Date: Thu, 9 Mar 2006 16:09:51 -0300 Subject: V4L/DVB (3425): Correct gpio values for Aver 303 Studio in v4l-dvb tree Old values generally works in A2 mono, but new ones allows: - detect and use Nicam stereo - mute in tv - use radio FM Signed-off-by: Marcin Rudowski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index c0d1f0b12829..c8f91b1c2068 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -184,17 +184,18 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio1 = 0x309f, + .gpio1 = 0xe09f, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio1 = 0x305f, + .gpio1 = 0xe05f, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, - .gpio1 = 0x305f, + .gpio1 = 0xe05f, }}, .radio = { + .gpio1 = 0xe0df, .type = CX88_RADIO, }, }, -- cgit v1.2.3-59-g8ed1b From 09794a6f95cf970d76e8b1c0ddd2b20a89f3dd88 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Fri, 10 Mar 2006 15:21:28 -0300 Subject: V4L/DVB (3435): Remove 'pid' from struct dmxdev_filter The PID value is already stored in struct dmx_sct_filter_params which is a member of struct dmxdev_filter. Acked-by: Johannes Stezenbach Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dmxdev.c | 9 +++------ drivers/media/dvb/dvb-core/dmxdev.h | 2 -- 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 4c52c8521bd8..ab1aeb84c681 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -454,7 +454,7 @@ static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter) for (i=0; ifilternum; i++) if (dmxdev->filter[i].state>=DMXDEV_STATE_GO && dmxdev->filter[i].type==DMXDEV_TYPE_SEC && - dmxdev->filter[i].pid==pid) { + dmxdev->filter[i].params.sec.pid==pid) { dvb_dmxdev_feed_start(&dmxdev->filter[i]); return 0; } @@ -505,7 +505,6 @@ static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter) return 0; dmxdevfilter->type=DMXDEV_TYPE_NONE; - dmxdevfilter->pid=0xffff; dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); return 0; } @@ -546,8 +545,8 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) /* find active filter/feed with same PID */ for (i=0; ifilternum; i++) { if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && - dmxdev->filter[i].pid == para->pid && - dmxdev->filter[i].type == DMXDEV_TYPE_SEC) { + dmxdev->filter[i].type == DMXDEV_TYPE_SEC && + dmxdev->filter[i].params.sec.pid == para->pid) { *secfeed = dmxdev->filter[i].feed.sec; break; } @@ -756,7 +755,6 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev, dvb_dmxdev_filter_stop(dmxdevfilter); dmxdevfilter->type=DMXDEV_TYPE_SEC; - dmxdevfilter->pid=params->pid; memcpy(&dmxdevfilter->params.sec, params, sizeof(struct dmx_sct_filter_params)); invert_mode(&dmxdevfilter->params.sec.filter); @@ -778,7 +776,6 @@ static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev, return -EINVAL; dmxdevfilter->type=DMXDEV_TYPE_PES; - dmxdevfilter->pid=params->pid; memcpy(&dmxdevfilter->params, params, sizeof(struct dmx_pes_filter_params)); dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h index fafdf476b23a..4cb879435fdb 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.h +++ b/drivers/media/dvb/dvb-core/dmxdev.h @@ -89,8 +89,6 @@ struct dmxdev_filter { struct timer_list timer; int todo; u8 secheader[3]; - - u16 pid; }; -- cgit v1.2.3-59-g8ed1b From 6abe6bff6fc62832bc8cce3886b9670ba2542601 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Fri, 10 Mar 2006 15:21:43 -0300 Subject: V4L/DVB (3436): Remove 'dvbdev' from struct dmxdev_filter The member dvbdev gets initialized once but is never used after that. Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dmxdev.c | 1 - drivers/media/dvb/dvb-core/dmxdev.h | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index ab1aeb84c681..5cd2f98290ae 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -694,7 +694,6 @@ static int dvb_demux_open(struct inode *inode, struct file *file) dmxdevfilter=&dmxdev->filter[i]; mutex_init(&dmxdevfilter->mutex); - dmxdevfilter->dvbdev=dmxdev->dvbdev; file->private_data=dmxdevfilter; dvb_dmxdev_buffer_init(&dmxdevfilter->buffer); diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h index 4cb879435fdb..5d4d18a00a68 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.h +++ b/drivers/media/dvb/dvb-core/dmxdev.h @@ -62,8 +62,6 @@ struct dmxdev_buffer { }; struct dmxdev_filter { - struct dvb_device *dvbdev; - union { struct dmx_section_filter *sec; } filter; -- cgit v1.2.3-59-g8ed1b From bbad7dc5488a04fadebd7fa8aa051d81c2ae0080 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Fri, 10 Mar 2006 15:21:58 -0300 Subject: V4L/DVB (3437): Fix typo in enum name and use enum in struct dmxdev_filter Rename 'enum dmxdevype' to 'enum dmxdev_type' and use this enum instead of int for the member 'type' of struct dmxdev_filter. Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dmxdev.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h index 5d4d18a00a68..1b3e49bd9aa2 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.h +++ b/drivers/media/dvb/dvb-core/dmxdev.h @@ -37,7 +37,7 @@ #include "dvbdev.h" #include "demux.h" -enum dmxdevype { +enum dmxdev_type { DMXDEV_TYPE_NONE, DMXDEV_TYPE_SEC, DMXDEV_TYPE_PES, @@ -76,7 +76,7 @@ struct dmxdev_filter { struct dmx_pes_filter_params pes; } params; - int type; + enum dmxdev_type type; enum dmxdev_state state; struct dmxdev *dev; struct dmxdev_buffer buffer; -- cgit v1.2.3-59-g8ed1b From f705e6e4940c4e803240b77c6c63fb2d47a97b59 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Fri, 10 Mar 2006 15:22:31 -0300 Subject: V4L/DVB (3438): Optical cleanup for dmxdev.c Used Lindent, manually changed some line breaks. Removed invalid email addresses, useless casts and useless initialization of return values. Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dmxdev.c | 650 ++++++++++++++++++------------------ 1 file changed, 321 insertions(+), 329 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 5cd2f98290ae..f6932d6c62e3 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -1,9 +1,8 @@ /* * dmxdev.c - DVB demultiplexer device * - * Copyright (C) 2000 Ralph Metzler - * & Marcus Metzler - for convergence integrated media GmbH + * Copyright (C) 2000 Ralph Metzler & Marcus Metzler + * for convergence integrated media GmbH * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -32,7 +31,6 @@ #include #include #include - #include "dmxdev.h" static int debug; @@ -44,15 +42,16 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer) { - buffer->data=NULL; - buffer->size=8192; - buffer->pread=0; - buffer->pwrite=0; - buffer->error=0; + buffer->data = NULL; + buffer->size = 8192; + buffer->pread = 0; + buffer->pwrite = 0; + buffer->error = 0; init_waitqueue_head(&buffer->queue); } -static inline int dvb_dmxdev_buffer_write(struct dmxdev_buffer *buf, const u8 *src, int len) +static inline int dvb_dmxdev_buffer_write(struct dmxdev_buffer *buf, + const u8 *src, int len) { int split; int free; @@ -63,98 +62,99 @@ static inline int dvb_dmxdev_buffer_write(struct dmxdev_buffer *buf, const u8 *s if (!buf->data) return 0; - free=buf->pread-buf->pwrite; - split=0; - if (free<=0) { - free+=buf->size; - split=buf->size-buf->pwrite; + free = buf->pread - buf->pwrite; + split = 0; + if (free <= 0) { + free += buf->size; + split = buf->size - buf->pwrite; } - if (len>=free) { + if (len >= free) { dprintk("dmxdev: buffer overflow\n"); return -1; } - if (split>=len) - split=0; - todo=len; + if (split >= len) + split = 0; + todo = len; if (split) { memcpy(buf->data + buf->pwrite, src, split); - todo-=split; - buf->pwrite=0; + todo -= split; + buf->pwrite = 0; } - memcpy(buf->data + buf->pwrite, src+split, todo); - buf->pwrite=(buf->pwrite+todo)%buf->size; + memcpy(buf->data + buf->pwrite, src + split, todo); + buf->pwrite = (buf->pwrite + todo) % buf->size; return len; } static ssize_t dvb_dmxdev_buffer_read(struct dmxdev_buffer *src, - int non_blocking, char __user *buf, size_t count, loff_t *ppos) + int non_blocking, char __user *buf, + size_t count, loff_t *ppos) { - unsigned long todo=count; + unsigned long todo = count; int split, avail, error; if (!src->data) return 0; - if ((error=src->error)) { - src->pwrite=src->pread; - src->error=0; + if ((error = src->error)) { + src->pwrite = src->pread; + src->error = 0; return error; } - if (non_blocking && (src->pwrite==src->pread)) + if (non_blocking && (src->pwrite == src->pread)) return -EWOULDBLOCK; - while (todo>0) { - if (non_blocking && (src->pwrite==src->pread)) - return (count-todo) ? (count-todo) : -EWOULDBLOCK; + while (todo > 0) { + if (non_blocking && (src->pwrite == src->pread)) + return (count - todo) ? (count - todo) : -EWOULDBLOCK; if (wait_event_interruptible(src->queue, - (src->pread!=src->pwrite) || - (src->error))<0) - return count-todo; + (src->pread != src->pwrite) || + (src->error)) < 0) + return count - todo; - if ((error=src->error)) { - src->pwrite=src->pread; - src->error=0; + if ((error = src->error)) { + src->pwrite = src->pread; + src->error = 0; return error; } - split=src->size; - avail=src->pwrite - src->pread; - if (avail<0) { - avail+=src->size; - split=src->size - src->pread; + split = src->size; + avail = src->pwrite - src->pread; + if (avail < 0) { + avail += src->size; + split = src->size - src->pread; } - if (avail>todo) - avail=todo; - if (splitdata+src->pread, split)) - return -EFAULT; - buf+=split; - src->pread=0; - todo-=split; - avail-=split; + if (avail > todo) + avail = todo; + if (split < avail) { + if (copy_to_user(buf, src->data + src->pread, split)) + return -EFAULT; + buf += split; + src->pread = 0; + todo -= split; + avail -= split; } if (avail) { - if (copy_to_user(buf, src->data+src->pread, avail)) + if (copy_to_user(buf, src->data + src->pread, avail)) return -EFAULT; src->pread = (src->pread + avail) % src->size; - todo-=avail; - buf+=avail; + todo -= avail; + buf += avail; } } return count; } -static struct dmx_frontend * get_fe(struct dmx_demux *demux, int type) +static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type) { struct list_head *head, *pos; - head=demux->get_frontends(demux); + head = demux->get_frontends(demux); if (!head) return NULL; list_for_each(pos, head) - if (DMX_FE_ENTRY(pos)->source==type) + if (DMX_FE_ENTRY(pos)->source == type) return DMX_FE_ENTRY(pos); return NULL; @@ -166,37 +166,37 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) struct dmxdev *dmxdev = dvbdev->priv; struct dmx_frontend *front; - dprintk ("function : %s\n", __FUNCTION__); + dprintk("function : %s\n", __FUNCTION__); if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; - if ((file->f_flags&O_ACCMODE)==O_RDWR) { - if (!(dmxdev->capabilities&DMXDEV_CAP_DUPLEX)) { + if ((file->f_flags & O_ACCMODE) == O_RDWR) { + if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { mutex_unlock(&dmxdev->mutex); return -EOPNOTSUPP; } } - if ((file->f_flags&O_ACCMODE)==O_RDONLY) { - dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); - dmxdev->dvr_buffer.size=DVR_BUFFER_SIZE; - dmxdev->dvr_buffer.data=vmalloc(DVR_BUFFER_SIZE); - if (!dmxdev->dvr_buffer.data) { - mutex_unlock(&dmxdev->mutex); - return -ENOMEM; - } + if ((file->f_flags & O_ACCMODE) == O_RDONLY) { + dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); + dmxdev->dvr_buffer.size = DVR_BUFFER_SIZE; + dmxdev->dvr_buffer.data = vmalloc(DVR_BUFFER_SIZE); + if (!dmxdev->dvr_buffer.data) { + mutex_unlock(&dmxdev->mutex); + return -ENOMEM; + } } - if ((file->f_flags&O_ACCMODE)==O_WRONLY) { - dmxdev->dvr_orig_fe=dmxdev->demux->frontend; + if ((file->f_flags & O_ACCMODE) == O_WRONLY) { + dmxdev->dvr_orig_fe = dmxdev->demux->frontend; if (!dmxdev->demux->write) { mutex_unlock(&dmxdev->mutex); return -EOPNOTSUPP; } - front=get_fe(dmxdev->demux, DMX_MEMORY_FE); + front = get_fe(dmxdev->demux, DMX_MEMORY_FE); if (!front) { mutex_unlock(&dmxdev->mutex); @@ -217,17 +217,17 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; - if ((file->f_flags&O_ACCMODE)==O_WRONLY) { + if ((file->f_flags & O_ACCMODE) == O_WRONLY) { dmxdev->demux->disconnect_frontend(dmxdev->demux); dmxdev->demux->connect_frontend(dmxdev->demux, dmxdev->dvr_orig_fe); } - if ((file->f_flags&O_ACCMODE)==O_RDONLY) { + if ((file->f_flags & O_ACCMODE) == O_RDONLY) { if (dmxdev->dvr_buffer.data) { - void *mem=dmxdev->dvr_buffer.data; + void *mem = dmxdev->dvr_buffer.data; mb(); spin_lock_irq(&dmxdev->lock); - dmxdev->dvr_buffer.data=NULL; + dmxdev->dvr_buffer.data = NULL; spin_unlock_irq(&dmxdev->lock); vfree(mem); } @@ -237,7 +237,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) } static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { struct dvb_device *dvbdev = file->private_data; struct dmxdev *dmxdev = dvbdev->priv; @@ -245,60 +245,62 @@ static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, if (!dmxdev->demux->write) return -EOPNOTSUPP; - if ((file->f_flags&O_ACCMODE)!=O_WRONLY) + if ((file->f_flags & O_ACCMODE) != O_WRONLY) return -EINVAL; if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; - ret=dmxdev->demux->write(dmxdev->demux, buf, count); + ret = dmxdev->demux->write(dmxdev->demux, buf, count); mutex_unlock(&dmxdev->mutex); return ret; } static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) + loff_t *ppos) { struct dvb_device *dvbdev = file->private_data; struct dmxdev *dmxdev = dvbdev->priv; int ret; //mutex_lock(&dmxdev->mutex); - ret= dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, - file->f_flags&O_NONBLOCK, - buf, count, ppos); + ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, + file->f_flags & O_NONBLOCK, + buf, count, ppos); //mutex_unlock(&dmxdev->mutex); return ret; } -static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter *dmxdevfilter, int state) +static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter + *dmxdevfilter, int state) { spin_lock_irq(&dmxdevfilter->dev->lock); - dmxdevfilter->state=state; + dmxdevfilter->state = state; spin_unlock_irq(&dmxdevfilter->dev->lock); } -static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, unsigned long size) +static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, + unsigned long size) { - struct dmxdev_buffer *buf=&dmxdevfilter->buffer; + struct dmxdev_buffer *buf = &dmxdevfilter->buffer; void *mem; - if (buf->size==size) + if (buf->size == size) return 0; - if (dmxdevfilter->state>=DMXDEV_STATE_GO) + if (dmxdevfilter->state >= DMXDEV_STATE_GO) return -EBUSY; spin_lock_irq(&dmxdevfilter->dev->lock); - mem=buf->data; - buf->data=NULL; - buf->size=size; - buf->pwrite=buf->pread=0; + mem = buf->data; + buf->data = NULL; + buf->size = size; + buf->pwrite = buf->pread = 0; spin_unlock_irq(&dmxdevfilter->dev->lock); vfree(mem); if (buf->size) { - mem=vmalloc(dmxdevfilter->buffer.size); + mem = vmalloc(dmxdevfilter->buffer.size); if (!mem) return -ENOMEM; spin_lock_irq(&dmxdevfilter->dev->lock); - buf->data=mem; + buf->data = mem; spin_unlock_irq(&dmxdevfilter->dev->lock); } return 0; @@ -306,31 +308,33 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, unsign static void dvb_dmxdev_filter_timeout(unsigned long data) { - struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *)data; + struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data; - dmxdevfilter->buffer.error=-ETIMEDOUT; + dmxdevfilter->buffer.error = -ETIMEDOUT; spin_lock_irq(&dmxdevfilter->dev->lock); - dmxdevfilter->state=DMXDEV_STATE_TIMEDOUT; + dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT; spin_unlock_irq(&dmxdevfilter->dev->lock); wake_up(&dmxdevfilter->buffer.queue); } static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) { - struct dmx_sct_filter_params *para=&dmxdevfilter->params.sec; + struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec; del_timer(&dmxdevfilter->timer); if (para->timeout) { - dmxdevfilter->timer.function=dvb_dmxdev_filter_timeout; - dmxdevfilter->timer.data=(unsigned long) dmxdevfilter; - dmxdevfilter->timer.expires=jiffies+1+(HZ/2+HZ*para->timeout)/1000; + dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout; + dmxdevfilter->timer.data = (unsigned long)dmxdevfilter; + dmxdevfilter->timer.expires = + jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000; add_timer(&dmxdevfilter->timer); } } static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, - const u8 *buffer2, size_t buffer2_len, - struct dmx_section_filter *filter, enum dmx_success success) + const u8 *buffer2, size_t buffer2_len, + struct dmx_section_filter *filter, + enum dmx_success success) { struct dmxdev_filter *dmxdevfilter = filter->priv; int ret; @@ -340,68 +344,68 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, return 0; } spin_lock(&dmxdevfilter->dev->lock); - if (dmxdevfilter->state!=DMXDEV_STATE_GO) { + if (dmxdevfilter->state != DMXDEV_STATE_GO) { spin_unlock(&dmxdevfilter->dev->lock); return 0; } del_timer(&dmxdevfilter->timer); dprintk("dmxdev: section callback %02x %02x %02x %02x %02x %02x\n", buffer1[0], buffer1[1], - buffer1[2], buffer1[3], - buffer1[4], buffer1[5]); - ret=dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, buffer1_len); - if (ret==buffer1_len) { - ret=dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, buffer2_len); + buffer1[2], buffer1[3], buffer1[4], buffer1[5]); + ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, + buffer1_len); + if (ret == buffer1_len) { + ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, + buffer2_len); } - if (ret<0) { - dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread; - dmxdevfilter->buffer.error=-EOVERFLOW; + if (ret < 0) { + dmxdevfilter->buffer.pwrite = dmxdevfilter->buffer.pread; + dmxdevfilter->buffer.error = -EOVERFLOW; } - if (dmxdevfilter->params.sec.flags&DMX_ONESHOT) - dmxdevfilter->state=DMXDEV_STATE_DONE; + if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) + dmxdevfilter->state = DMXDEV_STATE_DONE; spin_unlock(&dmxdevfilter->dev->lock); wake_up(&dmxdevfilter->buffer.queue); return 0; } static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, - const u8 *buffer2, size_t buffer2_len, - struct dmx_ts_feed *feed, enum dmx_success success) + const u8 *buffer2, size_t buffer2_len, + struct dmx_ts_feed *feed, + enum dmx_success success) { struct dmxdev_filter *dmxdevfilter = feed->priv; struct dmxdev_buffer *buffer; int ret; spin_lock(&dmxdevfilter->dev->lock); - if (dmxdevfilter->params.pes.output==DMX_OUT_DECODER) { + if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { spin_unlock(&dmxdevfilter->dev->lock); return 0; } - if (dmxdevfilter->params.pes.output==DMX_OUT_TAP) - buffer=&dmxdevfilter->buffer; + if (dmxdevfilter->params.pes.output == DMX_OUT_TAP) + buffer = &dmxdevfilter->buffer; else - buffer=&dmxdevfilter->dev->dvr_buffer; + buffer = &dmxdevfilter->dev->dvr_buffer; if (buffer->error) { spin_unlock(&dmxdevfilter->dev->lock); wake_up(&buffer->queue); return 0; } - ret=dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); - if (ret==buffer1_len) - ret=dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); - if (ret<0) { - buffer->pwrite=buffer->pread; - buffer->error=-EOVERFLOW; + ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); + if (ret == buffer1_len) + ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); + if (ret < 0) { + buffer->pwrite = buffer->pread; + buffer->error = -EOVERFLOW; } spin_unlock(&dmxdevfilter->dev->lock); wake_up(&buffer->queue); return 0; } - /* stop feed but only mark the specified filter as stopped (state set) */ - static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) { dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); @@ -420,20 +424,16 @@ static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) return 0; } - /* start feed associated with the specified filter */ - static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter) { - dvb_dmxdev_filter_state_set (filter, DMXDEV_STATE_GO); + dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO); switch (filter->type) { case DMXDEV_TYPE_SEC: return filter->feed.sec->start_filtering(filter->feed.sec); - break; case DMXDEV_TYPE_PES: return filter->feed.ts->start_filtering(filter->feed.ts); - break; default: return -EINVAL; } @@ -441,32 +441,31 @@ static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter) return 0; } - /* restart section feed if it has filters left associated with it, otherwise release the feed */ - static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter) { int i; struct dmxdev *dmxdev = filter->dev; u16 pid = filter->params.sec.pid; - for (i=0; ifilternum; i++) - if (dmxdev->filter[i].state>=DMXDEV_STATE_GO && - dmxdev->filter[i].type==DMXDEV_TYPE_SEC && - dmxdev->filter[i].params.sec.pid==pid) { + for (i = 0; i < dmxdev->filternum; i++) + if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && + dmxdev->filter[i].type == DMXDEV_TYPE_SEC && + dmxdev->filter[i].params.sec.pid == pid) { dvb_dmxdev_feed_start(&dmxdev->filter[i]); return 0; } - filter->dev->demux->release_section_feed(dmxdev->demux, filter->feed.sec); + filter->dev->demux->release_section_feed(dmxdev->demux, + filter->feed.sec); return 0; } static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) { - if (dmxdevfilter->statestate < DMXDEV_STATE_GO) return 0; switch (dmxdevfilter->type) { @@ -476,35 +475,35 @@ static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) dvb_dmxdev_feed_stop(dmxdevfilter); if (dmxdevfilter->filter.sec) dmxdevfilter->feed.sec-> - release_filter(dmxdevfilter->feed.sec, - dmxdevfilter->filter.sec); + release_filter(dmxdevfilter->feed.sec, + dmxdevfilter->filter.sec); dvb_dmxdev_feed_restart(dmxdevfilter); - dmxdevfilter->feed.sec=NULL; + dmxdevfilter->feed.sec = NULL; break; case DMXDEV_TYPE_PES: if (!dmxdevfilter->feed.ts) break; dvb_dmxdev_feed_stop(dmxdevfilter); dmxdevfilter->dev->demux-> - release_ts_feed(dmxdevfilter->dev->demux, - dmxdevfilter->feed.ts); - dmxdevfilter->feed.ts=NULL; + release_ts_feed(dmxdevfilter->dev->demux, + dmxdevfilter->feed.ts); + dmxdevfilter->feed.ts = NULL; break; default: - if (dmxdevfilter->state==DMXDEV_STATE_ALLOCATED) + if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED) return 0; return -EINVAL; } - dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread=0; + dmxdevfilter->buffer.pwrite = dmxdevfilter->buffer.pread = 0; return 0; } static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter) { - if (dmxdevfilter->statestate < DMXDEV_STATE_SET) return 0; - dmxdevfilter->type=DMXDEV_TYPE_NONE; + dmxdevfilter->type = DMXDEV_TYPE_NONE; dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); return 0; } @@ -524,7 +523,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) if (!(mem = filter->buffer.data)) { mem = vmalloc(filter->buffer.size); spin_lock_irq(&filter->dev->lock); - filter->buffer.data=mem; + filter->buffer.data = mem; spin_unlock_irq(&filter->dev->lock); if (!filter->buffer.data) return -ENOMEM; @@ -535,15 +534,16 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) switch (filter->type) { case DMXDEV_TYPE_SEC: { - struct dmx_sct_filter_params *para=&filter->params.sec; - struct dmx_section_filter **secfilter=&filter->filter.sec; - struct dmx_section_feed **secfeed=&filter->feed.sec; + struct dmx_sct_filter_params *para = &filter->params.sec; + struct dmx_section_filter **secfilter = &filter->filter.sec; + struct dmx_section_feed **secfeed = &filter->feed.sec; + + *secfilter = NULL; + *secfeed = NULL; - *secfilter=NULL; - *secfeed=NULL; /* find active filter/feed with same PID */ - for (i=0; ifilternum; i++) { + for (i = 0; i < dmxdev->filternum; i++) { if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && dmxdev->filter[i].type == DMXDEV_TYPE_SEC && dmxdev->filter[i].params.sec.pid == para->pid) { @@ -554,21 +554,20 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) /* if no feed found, try to allocate new one */ if (!*secfeed) { - ret=dmxdev->demux->allocate_section_feed(dmxdev->demux, - secfeed, - dvb_dmxdev_section_callback); - if (ret<0) { - printk ("DVB (%s): could not alloc feed\n", - __FUNCTION__); + ret = dmxdev->demux->allocate_section_feed(dmxdev->demux, + secfeed, + dvb_dmxdev_section_callback); + if (ret < 0) { + printk("DVB (%s): could not alloc feed\n", + __FUNCTION__); return ret; } - ret=(*secfeed)->set(*secfeed, para->pid, 32768, - (para->flags & DMX_CHECK_CRC) ? 1 : 0); - - if (ret<0) { - printk ("DVB (%s): could not set feed\n", - __FUNCTION__); + ret = (*secfeed)->set(*secfeed, para->pid, 32768, + (para->flags & DMX_CHECK_CRC) ? 1 : 0); + if (ret < 0) { + printk("DVB (%s): could not set feed\n", + __FUNCTION__); dvb_dmxdev_feed_restart(filter); return ret; } @@ -576,41 +575,38 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) dvb_dmxdev_feed_stop(filter); } - ret=(*secfeed)->allocate_filter(*secfeed, secfilter); - + ret = (*secfeed)->allocate_filter(*secfeed, secfilter); if (ret < 0) { dvb_dmxdev_feed_restart(filter); filter->feed.sec->start_filtering(*secfeed); - dprintk ("could not get filter\n"); + dprintk("could not get filter\n"); return ret; } (*secfilter)->priv = filter; memcpy(&((*secfilter)->filter_value[3]), - &(para->filter.filter[1]), DMX_FILTER_SIZE-1); + &(para->filter.filter[1]), DMX_FILTER_SIZE - 1); memcpy(&(*secfilter)->filter_mask[3], - ¶->filter.mask[1], DMX_FILTER_SIZE-1); + ¶->filter.mask[1], DMX_FILTER_SIZE - 1); memcpy(&(*secfilter)->filter_mode[3], - ¶->filter.mode[1], DMX_FILTER_SIZE-1); + ¶->filter.mode[1], DMX_FILTER_SIZE - 1); - (*secfilter)->filter_value[0]=para->filter.filter[0]; - (*secfilter)->filter_mask[0]=para->filter.mask[0]; - (*secfilter)->filter_mode[0]=para->filter.mode[0]; - (*secfilter)->filter_mask[1]=0; - (*secfilter)->filter_mask[2]=0; + (*secfilter)->filter_value[0] = para->filter.filter[0]; + (*secfilter)->filter_mask[0] = para->filter.mask[0]; + (*secfilter)->filter_mode[0] = para->filter.mode[0]; + (*secfilter)->filter_mask[1] = 0; + (*secfilter)->filter_mask[2] = 0; filter->todo = 0; - ret = filter->feed.sec->start_filtering (filter->feed.sec); - + ret = filter->feed.sec->start_filtering(filter->feed.sec); if (ret < 0) return ret; dvb_dmxdev_filter_timer(filter); break; } - case DMXDEV_TYPE_PES: { struct timespec timeout = { 0 }; @@ -622,41 +618,41 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) struct dmx_ts_feed **tsfeed = &filter->feed.ts; filter->feed.ts = NULL; - otype=para->output; + otype = para->output; - ts_pes=(enum dmx_ts_pes) para->pes_type; + ts_pes = (enum dmx_ts_pes)para->pes_type; - if (ts_pesdemux->allocate_ts_feed(dmxdev->demux, - tsfeed, - dvb_dmxdev_ts_callback); - if (ret<0) + ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux, + tsfeed, + dvb_dmxdev_ts_callback); + if (ret < 0) return ret; - (*tsfeed)->priv = (void *) filter; + (*tsfeed)->priv = filter; ret = (*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes, 32768, timeout); - if (ret < 0) { - dmxdev->demux->release_ts_feed(dmxdev->demux, *tsfeed); + dmxdev->demux->release_ts_feed(dmxdev->demux, + *tsfeed); return ret; } ret = filter->feed.ts->start_filtering(filter->feed.ts); - if (ret < 0) { - dmxdev->demux->release_ts_feed(dmxdev->demux, *tsfeed); + dmxdev->demux->release_ts_feed(dmxdev->demux, + *tsfeed); return ret; } @@ -683,31 +679,31 @@ static int dvb_demux_open(struct inode *inode, struct file *file) if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; - for (i=0; ifilternum; i++) - if (dmxdev->filter[i].state==DMXDEV_STATE_FREE) + for (i = 0; i < dmxdev->filternum; i++) + if (dmxdev->filter[i].state == DMXDEV_STATE_FREE) break; - if (i==dmxdev->filternum) { + if (i == dmxdev->filternum) { mutex_unlock(&dmxdev->mutex); return -EMFILE; } - dmxdevfilter=&dmxdev->filter[i]; + dmxdevfilter = &dmxdev->filter[i]; mutex_init(&dmxdevfilter->mutex); - file->private_data=dmxdevfilter; + file->private_data = dmxdevfilter; dvb_dmxdev_buffer_init(&dmxdevfilter->buffer); - dmxdevfilter->type=DMXDEV_TYPE_NONE; + dmxdevfilter->type = DMXDEV_TYPE_NONE; dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); - dmxdevfilter->feed.ts=NULL; + dmxdevfilter->feed.ts = NULL; init_timer(&dmxdevfilter->timer); mutex_unlock(&dmxdev->mutex); return 0; } - -static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, struct dmxdev_filter *dmxdevfilter) +static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, + struct dmxdev_filter *dmxdevfilter) { if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; @@ -721,10 +717,10 @@ static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, struct dmxdev_filter *d dvb_dmxdev_filter_reset(dmxdevfilter); if (dmxdevfilter->buffer.data) { - void *mem=dmxdevfilter->buffer.data; + void *mem = dmxdevfilter->buffer.data; spin_lock_irq(&dmxdev->lock); - dmxdevfilter->buffer.data=NULL; + dmxdevfilter->buffer.data = NULL; spin_unlock_irq(&dmxdev->lock); vfree(mem); } @@ -740,118 +736,120 @@ static inline void invert_mode(dmx_filter_t *filter) { int i; - for (i=0; imode[i]^=0xff; + for (i = 0; i < DMX_FILTER_SIZE; i++) + filter->mode[i] ^= 0xff; } - static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev, - struct dmxdev_filter *dmxdevfilter, - struct dmx_sct_filter_params *params) + struct dmxdev_filter *dmxdevfilter, + struct dmx_sct_filter_params *params) { - dprintk ("function : %s\n", __FUNCTION__); + dprintk("function : %s\n", __FUNCTION__); dvb_dmxdev_filter_stop(dmxdevfilter); - dmxdevfilter->type=DMXDEV_TYPE_SEC; + dmxdevfilter->type = DMXDEV_TYPE_SEC; memcpy(&dmxdevfilter->params.sec, params, sizeof(struct dmx_sct_filter_params)); invert_mode(&dmxdevfilter->params.sec.filter); dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); - if (params->flags&DMX_IMMEDIATE_START) + if (params->flags & DMX_IMMEDIATE_START) return dvb_dmxdev_filter_start(dmxdevfilter); return 0; } static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev, - struct dmxdev_filter *dmxdevfilter, - struct dmx_pes_filter_params *params) + struct dmxdev_filter *dmxdevfilter, + struct dmx_pes_filter_params *params) { dvb_dmxdev_filter_stop(dmxdevfilter); - if (params->pes_type>DMX_PES_OTHER || params->pes_type<0) + if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0) return -EINVAL; - dmxdevfilter->type=DMXDEV_TYPE_PES; - memcpy(&dmxdevfilter->params, params, sizeof(struct dmx_pes_filter_params)); + dmxdevfilter->type = DMXDEV_TYPE_PES; + memcpy(&dmxdevfilter->params, params, + sizeof(struct dmx_pes_filter_params)); dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); - if (params->flags&DMX_IMMEDIATE_START) + if (params->flags & DMX_IMMEDIATE_START) return dvb_dmxdev_filter_start(dmxdevfilter); return 0; } static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil, - struct file *file, char __user *buf, size_t count, loff_t *ppos) + struct file *file, char __user *buf, + size_t count, loff_t *ppos) { int result, hcount; - int done=0; - - if (dfil->todo<=0) { - hcount=3+dfil->todo; - if (hcount>count) - hcount=count; - result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK, - buf, hcount, ppos); - if (result<0) { - dfil->todo=0; + int done = 0; + + if (dfil->todo <= 0) { + hcount = 3 + dfil->todo; + if (hcount > count) + hcount = count; + result = dvb_dmxdev_buffer_read(&dfil->buffer, + file->f_flags & O_NONBLOCK, + buf, hcount, ppos); + if (result < 0) { + dfil->todo = 0; return result; } - if (copy_from_user(dfil->secheader-dfil->todo, buf, result)) + if (copy_from_user(dfil->secheader - dfil->todo, buf, result)) return -EFAULT; - buf+=result; - done=result; - count-=result; - dfil->todo-=result; - if (dfil->todo>-3) + buf += result; + done = result; + count -= result; + dfil->todo -= result; + if (dfil->todo > -3) return done; - dfil->todo=((dfil->secheader[1]<<8)|dfil->secheader[2])&0xfff; + dfil->todo = ((dfil->secheader[1] << 8) | dfil->secheader[2]) & 0xfff; if (!count) return done; } - if (count>dfil->todo) - count=dfil->todo; - result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK, - buf, count, ppos); - if (result<0) + if (count > dfil->todo) + count = dfil->todo; + result = dvb_dmxdev_buffer_read(&dfil->buffer, + file->f_flags & O_NONBLOCK, + buf, count, ppos); + if (result < 0) return result; - dfil->todo-=result; - return (result+done); + dfil->todo -= result; + return (result + done); } - static ssize_t -dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +dvb_demux_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) { - struct dmxdev_filter *dmxdevfilter= file->private_data; - int ret=0; + struct dmxdev_filter *dmxdevfilter = file->private_data; + int ret; if (mutex_lock_interruptible(&dmxdevfilter->mutex)) return -ERESTARTSYS; - if (dmxdevfilter->type==DMXDEV_TYPE_SEC) - ret=dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos); + if (dmxdevfilter->type == DMXDEV_TYPE_SEC) + ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos); else - ret=dvb_dmxdev_buffer_read(&dmxdevfilter->buffer, - file->f_flags&O_NONBLOCK, - buf, count, ppos); + ret = dvb_dmxdev_buffer_read(&dmxdevfilter->buffer, + file->f_flags & O_NONBLOCK, + buf, count, ppos); mutex_unlock(&dmxdevfilter->mutex); return ret; } - static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { struct dmxdev_filter *dmxdevfilter = file->private_data; - struct dmxdev *dmxdev=dmxdevfilter->dev; - unsigned long arg=(unsigned long) parg; - int ret=0; + struct dmxdev *dmxdev = dmxdevfilter->dev; + unsigned long arg = (unsigned long)parg; + int ret = 0; if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; @@ -862,7 +860,7 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } - if (dmxdevfilter->statestate < DMXDEV_STATE_SET) ret = -EINVAL; else ret = dvb_dmxdev_filter_start(dmxdevfilter); @@ -874,7 +872,7 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } - ret=dvb_dmxdev_filter_stop(dmxdevfilter); + ret = dvb_dmxdev_filter_stop(dmxdevfilter); mutex_unlock(&dmxdevfilter->mutex); break; @@ -883,8 +881,7 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } - ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, - (struct dmx_sct_filter_params *)parg); + ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, parg); mutex_unlock(&dmxdevfilter->mutex); break; @@ -893,8 +890,7 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } - ret=dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, - (struct dmx_pes_filter_params *)parg); + ret = dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, parg); mutex_unlock(&dmxdevfilter->mutex); break; @@ -903,7 +899,7 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, mutex_unlock(&dmxdev->mutex); return -ERESTARTSYS; } - ret=dvb_dmxdev_set_buffer_size(dmxdevfilter, arg); + ret = dvb_dmxdev_set_buffer_size(dmxdevfilter, arg); mutex_unlock(&dmxdevfilter->mutex); break; @@ -912,10 +908,10 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, case DMX_GET_PES_PIDS: if (!dmxdev->demux->get_pes_pids) { - ret=-EINVAL; + ret = -EINVAL; break; } - dmxdev->demux->get_pes_pids(dmxdev->demux, (u16 *)parg); + dmxdev->demux->get_pes_pids(dmxdev->demux, parg); break; case DMX_GET_CAPS: @@ -936,17 +932,18 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, case DMX_GET_STC: if (!dmxdev->demux->get_stc) { - ret=-EINVAL; + ret = -EINVAL; break; } ret = dmxdev->demux->get_stc(dmxdev->demux, - ((struct dmx_stc *)parg)->num, - &((struct dmx_stc *)parg)->stc, - &((struct dmx_stc *)parg)->base); + ((struct dmx_stc *)parg)->num, + &((struct dmx_stc *)parg)->stc, + &((struct dmx_stc *)parg)->base); break; default: - ret=-EINVAL; + ret = -EINVAL; + break; } mutex_unlock(&dmxdev->mutex); return ret; @@ -958,8 +955,7 @@ static int dvb_demux_ioctl(struct inode *inode, struct file *file, return dvb_usercopy(inode, file, cmd, arg, dvb_demux_do_ioctl); } - -static unsigned int dvb_demux_poll (struct file *file, poll_table *wait) +static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) { struct dmxdev_filter *dmxdevfilter = file->private_data; unsigned int mask = 0; @@ -983,7 +979,6 @@ static unsigned int dvb_demux_poll (struct file *file, poll_table *wait) return mask; } - static int dvb_demux_release(struct inode *inode, struct file *file) { struct dmxdev_filter *dmxdevfilter = file->private_data; @@ -992,32 +987,28 @@ static int dvb_demux_release(struct inode *inode, struct file *file) return dvb_dmxdev_filter_free(dmxdev, dmxdevfilter); } - static struct file_operations dvb_demux_fops = { - .owner = THIS_MODULE, - .read = dvb_demux_read, - .ioctl = dvb_demux_ioctl, - .open = dvb_demux_open, - .release = dvb_demux_release, - .poll = dvb_demux_poll, + .owner = THIS_MODULE, + .read = dvb_demux_read, + .ioctl = dvb_demux_ioctl, + .open = dvb_demux_open, + .release = dvb_demux_release, + .poll = dvb_demux_poll, }; - static struct dvb_device dvbdev_demux = { - .priv = NULL, - .users = 1, - .writers = 1, - .fops = &dvb_demux_fops + .priv = NULL, + .users = 1, + .writers = 1, + .fops = &dvb_demux_fops }; - static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *parg) + unsigned int cmd, void *parg) { struct dvb_device *dvbdev = file->private_data; struct dmxdev *dmxdev = dvbdev->priv; - - int ret=0; + int ret; if (mutex_lock_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; @@ -1025,39 +1016,38 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file, switch (cmd) { case DMX_SET_BUFFER_SIZE: // FIXME: implement - ret=0; + ret = 0; break; default: - ret=-EINVAL; + ret = -EINVAL; + break; } mutex_unlock(&dmxdev->mutex); return ret; } - static int dvb_dvr_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { return dvb_usercopy(inode, file, cmd, arg, dvb_dvr_do_ioctl); } - -static unsigned int dvb_dvr_poll (struct file *file, poll_table *wait) +static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) { struct dvb_device *dvbdev = file->private_data; struct dmxdev *dmxdev = dvbdev->priv; unsigned int mask = 0; - dprintk ("function : %s\n", __FUNCTION__); + dprintk("function : %s\n", __FUNCTION__); poll_wait(file, &dmxdev->dvr_buffer.queue, wait); - if ((file->f_flags&O_ACCMODE) == O_RDONLY) { + if ((file->f_flags & O_ACCMODE) == O_RDONLY) { if (dmxdev->dvr_buffer.error) mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); - if (dmxdev->dvr_buffer.pread!=dmxdev->dvr_buffer.pwrite) + if (dmxdev->dvr_buffer.pread != dmxdev->dvr_buffer.pwrite) mask |= (POLLIN | POLLRDNORM | POLLPRI); } else mask |= (POLLOUT | POLLWRNORM | POLLPRI); @@ -1065,61 +1055,63 @@ static unsigned int dvb_dvr_poll (struct file *file, poll_table *wait) return mask; } - static struct file_operations dvb_dvr_fops = { - .owner = THIS_MODULE, - .read = dvb_dvr_read, - .write = dvb_dvr_write, - .ioctl = dvb_dvr_ioctl, - .open = dvb_dvr_open, - .release = dvb_dvr_release, - .poll = dvb_dvr_poll, + .owner = THIS_MODULE, + .read = dvb_dvr_read, + .write = dvb_dvr_write, + .ioctl = dvb_dvr_ioctl, + .open = dvb_dvr_open, + .release = dvb_dvr_release, + .poll = dvb_dvr_poll, }; static struct dvb_device dvbdev_dvr = { - .priv = NULL, - .users = 1, - .writers = 1, - .fops = &dvb_dvr_fops + .priv = NULL, + .users = 1, + .writers = 1, + .fops = &dvb_dvr_fops }; -int -dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) +int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) { int i; if (dmxdev->demux->open(dmxdev->demux) < 0) return -EUSERS; - dmxdev->filter = vmalloc(dmxdev->filternum*sizeof(struct dmxdev_filter)); + dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter)); if (!dmxdev->filter) return -ENOMEM; mutex_init(&dmxdev->mutex); spin_lock_init(&dmxdev->lock); - for (i=0; ifilternum; i++) { - dmxdev->filter[i].dev=dmxdev; - dmxdev->filter[i].buffer.data=NULL; - dvb_dmxdev_filter_state_set(&dmxdev->filter[i], DMXDEV_STATE_FREE); + for (i = 0; i < dmxdev->filternum; i++) { + dmxdev->filter[i].dev = dmxdev; + dmxdev->filter[i].buffer.data = NULL; + dvb_dmxdev_filter_state_set(&dmxdev->filter[i], + DMXDEV_STATE_FREE); } - dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, DVB_DEVICE_DEMUX); - dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, dmxdev, DVB_DEVICE_DVR); + dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, + DVB_DEVICE_DEMUX); + dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, + dmxdev, DVB_DEVICE_DVR); dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); return 0; } + EXPORT_SYMBOL(dvb_dmxdev_init); -void -dvb_dmxdev_release(struct dmxdev *dmxdev) +void dvb_dmxdev_release(struct dmxdev *dmxdev) { dvb_unregister_device(dmxdev->dvbdev); dvb_unregister_device(dmxdev->dvr_dvbdev); vfree(dmxdev->filter); - dmxdev->filter=NULL; + dmxdev->filter = NULL; dmxdev->demux->close(dmxdev->demux); } + EXPORT_SYMBOL(dvb_dmxdev_release); -- cgit v1.2.3-59-g8ed1b From 9050d942b7dc55cd8e6d9b2c1ce260656021f0fb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 10 Mar 2006 16:46:50 -0300 Subject: V4L/DVB (3439): Added no_overlay option and quirks to saa7134 Some chipsets have several problems when pci to pci transfers are activated on overlay mode. the option no_overlay allows disabling such feature of the driver, in favor of keeping the system stable. The default is to use pcipci_fail flag defined on drivers/pci/quirks.c. It also allows the user to override it by forcing disable overlay or forcing enable. Forcing enable may generate PCI transfer corruption, including disk mass corruption, so should be used with care. Added a text description to this option and make messages looks the same at both bttv and saa7134 drivers. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bttv-cards.c | 10 +++++++--- drivers/media/video/saa7134/saa7134-core.c | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 21ffe1c8dde4..abfa6ad857a0 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -137,6 +137,8 @@ MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a li MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)"); MODULE_PARM_DESC(tuner,"specify installed tuner type"); MODULE_PARM_DESC(autoload,"automatically load i2c modules like tuner.o, default is 1 (yes)"); +MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)" + " [some VIA/SIS chipsets are known to have problem with overlay]"); /* ----------------------------------------------------------------------- */ /* list of card IDs for bt878+ cards */ @@ -4944,12 +4946,14 @@ void __devinit bttv_check_chipset(void) if (vsfx) printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n"); if (pcipci_fail) { - printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n"); + printk(KERN_INFO "bttv: bttv and your chipset may not work " + "together.\n"); if (!no_overlay) { - printk(KERN_WARNING "bttv: overlay will be disabled.\n"); + printk(KERN_INFO "bttv: overlay will be disabled.\n"); no_overlay = 1; } else { - printk(KERN_WARNING "bttv: overlay forced. Use this option at your own risk.\n"); + printk(KERN_INFO "bttv: overlay forced. Use this " + "option at your own risk.\n"); } } if (UNSET != latency) diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index e7c30665739e..f5f2cf5d1507 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -66,6 +66,11 @@ static unsigned int latency = UNSET; module_param(latency, int, 0444); MODULE_PARM_DESC(latency,"pci latency timer"); +static int no_overlay=-1; +module_param(no_overlay, int, 0444); +MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)" + " [some VIA/SIS chipsets are known to have problem with overlay]"); + static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; @@ -835,6 +840,22 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, latency = 0x0A; } #endif + if (pci_pci_problems & PCIPCI_FAIL) { + printk(KERN_INFO "%s: quirk: this driver and your " + "chipset may not work together" + " in overlay mode.\n",dev->name); + if (!no_overlay) { + printk(KERN_INFO "%s: quirk: overlay " + "mode will be disabled.\n", + dev->name); + no_overlay = 1; + } else { + printk(KERN_INFO "%s: quirk: overlay " + "mode will be forced. Use this" + " option at your own risk.\n", + dev->name); + } + } } if (UNSET != latency) { printk(KERN_INFO "%s: setting pci latency timer to %d\n", -- cgit v1.2.3-59-g8ed1b From b1b168e62390b720e46271937355edba0a6e30bf Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 11 Mar 2006 16:12:35 -0300 Subject: V4L/DVB (3443): Thomson FE6600: add missing "count" array element - added missing "count" element in Thomson FE6600 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-types.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index e75904dddb12..ae6a2cf91c9b 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -1388,6 +1388,7 @@ struct tunertype tuners[] = { [TUNER_THOMSON_FE6600] = { /* Thomson PAL / DVB-T */ .name = "Thomson FE6600", .params = tuner_thomson_fe6600_params, + .count = ARRAY_SIZE(tuner_thomson_fe6600_params), }, }; -- cgit v1.2.3-59-g8ed1b From fd2f26771b14a321f4003366fdf99a2484fa6b2a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 11 Mar 2006 16:21:36 -0300 Subject: V4L/DVB (3444): Saa7134: small whitespace cleanup - matched indents on quotes within a printk Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 4071313cc45f..e9172e114974 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3368,9 +3368,9 @@ int saa7134_board_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_MD5044: printk("%s: seems there are two different versions of the MD5044\n" - "%s: (with the same ID) out there. If sound doesn't work for\n" - "%s: you try the audio_clock_override=0x200000 insmod option.\n", - dev->name,dev->name,dev->name); + "%s: (with the same ID) out there. If sound doesn't work for\n" + "%s: you try the audio_clock_override=0x200000 insmod option.\n", + dev->name,dev->name,dev->name); break; case SAA7134_BOARD_CINERGY400_CARDBUS: /* power-up tuner chip */ -- cgit v1.2.3-59-g8ed1b From f3629be8388a679590eb919919ee63e2715ec25e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 11 Mar 2006 17:02:01 -0300 Subject: V4L/DVB (3445): LG TALN series: add PAL / SECAM support - added tuner_lg_taln_pal_secam_ranges - renamed tuner 66 from TUNER_LG_NTSC_TALN_MINI to TUNER_LG_TALN - updated FlyTV mini Asus Digimatrix with new tuner Thanks-to: Rickard Osser Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.tuner | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 2 +- drivers/media/video/tuner-types.c | 26 ++++++++++++++++++-------- include/media/tuner.h | 2 +- 4 files changed, 21 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 44069338b531..1bcdac67dd8c 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -64,7 +64,7 @@ tuner=62 - Philips TEA5767HN FM Radio tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner tuner=64 - LG TDVS-H062F/TUA6034 tuner=65 - Ymec TVF66T5-B/DFF -tuner=66 - LG NTSC (TALN mini series) +tuner=66 - LG TALN series tuner=67 - Philips TD1316 Hybrid Tuner tuner=68 - Philips TUV1236D ATSC/NTSC dual in tuner=69 - Tena TNF 5335 and similar models diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index e9172e114974..f9265419ccb9 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2028,7 +2028,7 @@ struct saa7134_board saa7134_boards[] = { [SAA7134_BOARD_FLYTV_DIGIMATRIX] = { .name = "FlyTV mini Asus Digimatrix", .audio_clock = 0x00200000, - .tuner_type = TUNER_LG_NTSC_TALN_MINI, + .tuner_type = TUNER_LG_TALN, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index ae6a2cf91c9b..72e0f01db563 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -903,17 +903,27 @@ static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { /* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */ -static struct tuner_range tuner_lg_taln_mini_ntsc_ranges[] = { +static struct tuner_range tuner_lg_taln_ntsc_ranges[] = { { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, { 16 * 373.25 /*MHz*/, 0x8e, 0x02, }, { 16 * 999.99 , 0x8e, 0x08, }, }; -static struct tuner_params tuner_lg_taln_mini_params[] = { +static struct tuner_range tuner_lg_taln_pal_secam_ranges[] = { + { 16 * 150.00 /*MHz*/, 0x8e, 0x01, }, + { 16 * 425.00 /*MHz*/, 0x8e, 0x02, }, + { 16 * 999.99 , 0x8e, 0x08, }, +}; + +static struct tuner_params tuner_lg_taln_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_lg_taln_mini_ntsc_ranges, - .count = ARRAY_SIZE(tuner_lg_taln_mini_ntsc_ranges), + .ranges = tuner_lg_taln_ntsc_ranges, + .count = ARRAY_SIZE(tuner_lg_taln_ntsc_ranges), + },{ + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_taln_pal_secam_ranges, + .count = ARRAY_SIZE(tuner_lg_taln_pal_secam_ranges), }, }; @@ -1354,10 +1364,10 @@ struct tunertype tuners[] = { .params = tuner_ymec_tvf66t5_b_dff_params, .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_params), }, - [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */ - .name = "LG NTSC (TALN mini series)", - .params = tuner_lg_taln_mini_params, - .count = ARRAY_SIZE(tuner_lg_taln_mini_params), + [TUNER_LG_TALN] = { /* LGINNOTEK NTSC / PAL / SECAM */ + .name = "LG TALN series", + .params = tuner_lg_taln_params, + .count = ARRAY_SIZE(tuner_lg_taln_params), }, [TUNER_PHILIPS_TD1316] = { /* Philips PAL */ .name = "Philips TD1316 Hybrid Tuner", diff --git a/include/media/tuner.h b/include/media/tuner.h index 02d7d9a76fa2..017fed7d5e4d 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -110,7 +110,7 @@ #define TUNER_LG_TDVS_H062F 64 /* DViCO FusionHDTV 5 */ #define TUNER_YMEC_TVF66T5_B_DFF 65 /* Acorp Y878F */ -#define TUNER_LG_NTSC_TALN_MINI 66 +#define TUNER_LG_TALN 66 #define TUNER_PHILIPS_TD1316 67 #define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ -- cgit v1.2.3-59-g8ed1b From 68593af311aadb541b3b70acea175dea8e9cf7ca Mon Sep 17 00:00:00 2001 From: Rickard Osser Date: Sat, 11 Mar 2006 17:14:12 -0300 Subject: V4L/DVB (3446): Saa7134: add support for AVerMedia A169 Dual Analog tuner card - Added support for AVerMedia A169 Dual Analog tuner card (dual saa7134 decoders - only 1 working right now) - Added autodetection for both parts of the card. It shows up like 2 cards, B1 and B - Enabled tuner B1, SVIDEO on B1 and composite1 through SVIDEO, FIXME: B is more or less dead at this point and I suspect the FM-radio is on the B part of the board Signed-off-by: Rickard Osser Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 + drivers/media/video/saa7134/saa7134-cards.c | 59 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 2 + 3 files changed, 63 insertions(+) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 874ffc4b5cca..421a2427f50a 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -89,3 +89,5 @@ 88 -> Tevion/KWorld DVB-T 220RF [17de:7201] 89 -> ELSA EX-VISION 700TV [1048:226c] 90 -> Kworld ATSC110 [17de:7350] + 91 -> AVerMedia A169 B [1461:7360] + 92 -> AVerMedia A169 B1 [1461:6360] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index f9265419ccb9..f9a29c415c73 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2756,6 +2756,47 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }}, }, + [SAA7134_BOARD_AVERMEDIA_A169_B] = { + /* AVerMedia A169 */ + /* Rickard Osser */ + /* This card has two saa7134 chips on it, + but only one of them is currently working. */ + .name = "AVerMedia A169 B", + .audio_clock = 0x02187de7, + .tuner_type = TUNER_LG_TALN, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x0a60000, + }, + [SAA7134_BOARD_AVERMEDIA_A169_B1] = { + /* AVerMedia A169 */ + /* Rickard Osser */ + .name = "AVerMedia A169 B1", + .audio_clock = 0x02187de7, + .tuner_type = TUNER_LG_TALN, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0xca60000, + .inputs = {{ + .name = name_tv, + .vmux = 4, + .amux = TV, + .tv = 1, + .gpio = 0x04a61000, + },{ + .name = name_comp2, /* Composite SVIDEO (B/W if signal is carried with SVIDEO) */ + .vmux = 1, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 9, /* 9 is correct as S-VIDEO1 according to a169.inf! */ + .amux = LINE1, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3262,6 +3303,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x17de, .subdevice = 0x7350, .driver_data = SAA7134_BOARD_KWORLD_ATSC110, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1461, + .subdevice = 0x7360, + .driver_data = SAA7134_BOARD_AVERMEDIA_A169_B, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1461, + .subdevice = 0x6360, + .driver_data = SAA7134_BOARD_AVERMEDIA_A169_B1, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3417,6 +3470,12 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_UPMOST_PURPLE_TV: dev->has_remote = SAA7134_REMOTE_I2C; break; + case SAA7134_BOARD_AVERMEDIA_A169_B: + printk("%s: AVerMedia A169: dual saa7134 broadcast decoders\n" + "%s: Sorry, none of the inputs to this chip are supported yet.\n" + "%s: Dual decoder functionality is disabled for now, use the other chip.\n", + dev->name,dev->name,dev->name); + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f8c9b6760732..7d04ed330ec3 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -218,6 +218,8 @@ struct saa7134_format { #define SAA7134_BOARD_TEVION_DVBT_220RF 88 #define SAA7134_BOARD_ELSA_700TV 89 #define SAA7134_BOARD_KWORLD_ATSC110 90 +#define SAA7134_BOARD_AVERMEDIA_A169_B 91 +#define SAA7134_BOARD_AVERMEDIA_A169_B1 92 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3-59-g8ed1b From 49239c35f28e53f280b47efdbccfdf2cbd728993 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Sat, 11 Mar 2006 23:54:24 -0300 Subject: V4L/DVB (3447): Cx88-cards.c: fix values of gpio0 for card CX88_BOARD_PROLINK_PLAYTVPVR This patch changes the gpio0 values for the card CX88_BOARD_PROLINK_PLAYTVPVR to the ones observed using RegSpy from the dscaler project. Signed-off-by: Matheus Izvekov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index c8f91b1c2068..c91f30e11f22 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -323,19 +323,19 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0xff00, + .gpio0 = 0xbff0, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0xff03, + .gpio0 = 0xbff3, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, - .gpio0 = 0xff03, + .gpio0 = 0xbff3, }}, .radio = { .type = CX88_RADIO, - .gpio0 = 0xff00, + .gpio0 = 0xbff0, }, }, [CX88_BOARD_ASUS_PVR_416] = { -- cgit v1.2.3-59-g8ed1b From a5daecbaebda687d62c2ba1f46adaa96e4394282 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Sat, 11 Mar 2006 23:54:58 -0300 Subject: V4L/DVB (3448): Cx88-input.c: add IR remote control support to CX88_BOARD_PROLINK_PLAYTVPVR This patch adds support for the IR remote control found in the card CX88_BOARD_PROLINK_PLAYTVPVR. Signed-off-by: Matheus Izvekov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-input.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index f2fba57f955b..78a63b7dd380 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -186,6 +186,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->mask_keydown = 0x02; ir->polling = 5; /* ms */ break; + case CX88_BOARD_PROLINK_PLAYTVPVR: case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: ir_codes = ir_codes_pixelview; ir->gpio_addr = MO_GP1_IO; -- cgit v1.2.3-59-g8ed1b From 9f9c907fdc331fc6062d758f46f65cb0d2dd11be Mon Sep 17 00:00:00 2001 From: Marcin Rudowski Date: Sun, 12 Mar 2006 00:03:47 -0300 Subject: V4L/DVB (3449): Cx88 default picture controls values This patch fixes default values for some picture controls: - brightness set to 50% by default (now is 0%) - hue set to 50% by default (now is 0%) - sets saturation to datasheet value - volume set to 0dB (now is -32dB) and some left small fixes: - twice offset adding - balance didn't follow datasheet (bits[0:5] = attenuation; bit[6] = channel to provide attenuation) Signed-off-by: Marcin Rudowski Signed-off-by: Ian Pickworth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 7bbc81fb43b5..b1892dff0fe8 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -227,7 +227,7 @@ static struct cx88_ctrl cx8800_ctls[] = { .minimum = 0x00, .maximum = 0xff, .step = 1, - .default_value = 0, + .default_value = 0x7f, .type = V4L2_CTRL_TYPE_INTEGER, }, .off = 128, @@ -255,7 +255,7 @@ static struct cx88_ctrl cx8800_ctls[] = { .minimum = 0, .maximum = 0xff, .step = 1, - .default_value = 0, + .default_value = 0x7f, .type = V4L2_CTRL_TYPE_INTEGER, }, .off = 128, @@ -300,7 +300,7 @@ static struct cx88_ctrl cx8800_ctls[] = { .minimum = 0, .maximum = 0x3f, .step = 1, - .default_value = 0x1f, + .default_value = 0x3f, .type = V4L2_CTRL_TYPE_INTEGER, }, .reg = AUD_VOL_CTL, @@ -909,7 +909,8 @@ static int get_control(struct cx88_core *core, struct v4l2_control *ctl) value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg); switch (ctl->id) { case V4L2_CID_AUDIO_BALANCE: - ctl->value = (value & 0x40) ? (value & 0x3f) : (0x40 - (value & 0x3f)); + ctl->value = ((value & 0x7f) < 0x40) ? ((value & 0x7f) + 0x40) + : (0x7f - (value & 0x7f)); break; case V4L2_CID_AUDIO_VOLUME: ctl->value = 0x3f - (value & 0x3f); @@ -946,7 +947,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) mask=c->mask; switch (ctl->id) { case V4L2_CID_AUDIO_BALANCE: - value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value; + value = (ctl->value < 0x40) ? (0x7f - ctl->value) : (ctl->value - 0x40); break; case V4L2_CID_AUDIO_VOLUME: value = 0x3f - (ctl->value & 0x3f); @@ -987,8 +988,7 @@ static void init_controls(struct cx88_core *core) for (i = 0; i < CX8800_CTLS; i++) { ctrl.id=cx8800_ctls[i].v.id; - ctrl.value=cx8800_ctls[i].v.default_value - +cx8800_ctls[i].off; + ctrl.value=cx8800_ctls[i].v.default_value; set_control(core, &ctrl); } } -- cgit v1.2.3-59-g8ed1b From fc34f165317403444d254a27bc356dc5de0bbc3d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 13 Mar 2006 03:41:44 -0300 Subject: V4L/DVB (3479): Cleanup mangled whitespace Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index c91f30e11f22..c7042cf41231 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -323,19 +323,19 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0xbff0, + .gpio0 = 0xbff0, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0xbff3, + .gpio0 = 0xbff3, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, - .gpio0 = 0xbff3, + .gpio0 = 0xbff3, }}, .radio = { .type = CX88_RADIO, - .gpio0 = 0xbff0, + .gpio0 = 0xbff0, }, }, [CX88_BOARD_ASUS_PVR_416] = { -- cgit v1.2.3-59-g8ed1b From 9d9d6baeca6f9174b8e7fd219a62a8fa09d61cc7 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Mon, 13 Mar 2006 13:14:34 -0300 Subject: V4L/DVB (3484): Make dvb_ringbuffer compatible to dmxdev_buffer Added variable 'error' to struct dvb_ringbuffer, which is set to zero on init() and flush(). Also reset read an write pointers to zero on flush() to get less fragmented data. Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_ringbuffer.c | 4 +++- drivers/media/dvb/dvb-core/dvb_ringbuffer.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c index 77ad2410f4d3..f233248358c4 100644 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c @@ -45,6 +45,7 @@ void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len) rbuf->pread=rbuf->pwrite=0; rbuf->data=data; rbuf->size=len; + rbuf->error=0; init_waitqueue_head(&rbuf->queue); @@ -86,7 +87,8 @@ ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf) void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) { - rbuf->pread = rbuf->pwrite; + rbuf->pread = rbuf->pwrite = 0; + rbuf->error = 0; } diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h index 6d2560972771..d97714e75736 100644 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h @@ -35,6 +35,7 @@ struct dvb_ringbuffer { ssize_t size; ssize_t pread; ssize_t pwrite; + int error; wait_queue_head_t queue; spinlock_t lock; -- cgit v1.2.3-59-g8ed1b From ae24601b47c3f4a56545ef4cd4e7c821ac1db598 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Mon, 13 Mar 2006 13:17:11 -0300 Subject: V4L/DVB (3485): BUG_ON() Conversion in drivers/video/media Signed-off-by: Eric Sesterhenn Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_core.c | 3 +-- drivers/media/common/saa7146_fops.c | 6 ++---- drivers/media/dvb/ttpci/av7110.c | 6 ++---- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 3 +-- drivers/media/video/bttv-risc.c | 3 +-- drivers/media/video/cx88/cx88-core.c | 3 +-- drivers/media/video/cx88/cx88-video.c | 3 +-- drivers/media/video/saa7134/saa7134-alsa.c | 3 +-- drivers/media/video/saa7134/saa7134-core.c | 3 +-- drivers/media/video/saa7134/saa7134-oss.c | 6 ++---- drivers/media/video/saa7134/saa7134-video.c | 3 +-- drivers/media/video/video-buf.c | 3 +-- 12 files changed, 15 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index ee16c042ef6e..8cdd4d265ffa 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -116,8 +116,7 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) pg = vmalloc_to_page(virt); if (NULL == pg) goto err; - if (PageHighMem(pg)) - BUG(); + BUG_ON(PageHighMem(pg)); sglist[i].page = pg; sglist[i].length = PAGE_SIZE; } diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index dc7fb20f47b5..3870fa948cc0 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -37,8 +37,7 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; - if ((fh->resources & bits) != bits) - BUG(); + BUG_ON((fh->resources & bits) != bits); mutex_lock(&dev->lock); fh->resources &= ~bits; @@ -55,8 +54,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf) { DEB_EE(("dev:%p, buf:%p\n",dev,buf)); - if (in_interrupt()) - BUG(); + BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma); diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index aef4f58d712d..7497b1e8d883 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -1090,11 +1090,9 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num, struct av7110 *av7110; /* pointer casting paranoia... */ - if (!demux) - BUG(); + BUG_ON(!demux); dvbdemux = (struct dvb_demux *) demux->priv; - if (!dvbdemux) - BUG(); + BUG_ON(!dvbdemux); av7110 = (struct av7110 *) dvbdemux->priv; dprintk(4, "%p\n", av7110); diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index ecb15d4ecf81..248fdc7accfb 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -688,8 +688,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) memcpy(ttusb->muxpack + ttusb->muxpack_ptr, data, avail); ttusb->muxpack_ptr += avail; - if (ttusb->muxpack_ptr > 264) - BUG(); + BUG_ON(ttusb->muxpack_ptr > 264); data += avail; len -= avail; /* determine length */ diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index 5c746110df62..344f84e9af04 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -511,8 +511,7 @@ bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf) { - if (in_interrupt()) - BUG(); + BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); videobuf_dma_pci_unmap(btv->c.pci, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 25be3a976d09..c2cdbafdb77b 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -215,8 +215,7 @@ int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, void cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf) { - if (in_interrupt()) - BUG(); + BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); videobuf_dma_pci_unmap(pci, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index b1892dff0fe8..6c97aa740d27 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -366,8 +366,7 @@ static void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits) { struct cx88_core *core = dev->core; - if ((fh->resources & bits) != bits) - BUG(); + BUG_ON((fh->resources & bits) != bits); mutex_lock(&core->lock); fh->resources &= ~bits; diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 614f7b923403..64e2c108df34 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -308,8 +308,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev) static int dsp_buffer_free(struct saa7134_dev *dev) { - if (!dev->dmasound.blksize) - BUG(); + BUG_ON(!dev->dmasound.blksize); videobuf_dma_free(&dev->dmasound.dma); diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index f5f2cf5d1507..be85e0b0cbb0 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -256,8 +256,7 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt) void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf) { - if (in_interrupt()) - BUG(); + BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma); diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index 80e34a5fdcc5..d79d05f88705 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -84,8 +84,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev) { int err; - if (!dev->dmasound.bufsize) - BUG(); + BUG_ON(!dev->dmasound.bufsize); videobuf_dma_init(&dev->dmasound.dma); err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE, (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT); @@ -96,8 +95,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev) static int dsp_buffer_free(struct saa7134_dev *dev) { - if (!dev->dmasound.blksize) - BUG(); + BUG_ON(!dev->dmasound.blksize); videobuf_dma_free(&dev->dmasound.dma); dev->dmasound.blocks = 0; dev->dmasound.blksize = 0; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 72f389a51a13..600c3c7e3dca 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -489,8 +489,7 @@ int res_locked(struct saa7134_dev *dev, unsigned int bit) static void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits) { - if ((fh->resources & bits) != bits) - BUG(); + BUG_ON((fh->resources & bits) != bits); mutex_lock(&dev->lock); fh->resources &= ~bits; diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index cb1c228e29f8..a8918e839f65 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -59,8 +59,7 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) pg = vmalloc_to_page(virt); if (NULL == pg) goto err; - if (PageHighMem(pg)) - BUG(); + BUG_ON(PageHighMem(pg)); sglist[i].page = pg; sglist[i].length = PAGE_SIZE; } -- cgit v1.2.3-59-g8ed1b From 31dcbf994b9eda784c620c8caa3a9dc67a9d0045 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Tue, 14 Mar 2006 12:12:39 -0300 Subject: V4L/DVB (3488): Snd_cx88_create: don't dereference NULL core If the call to cx88_core_get returns a NULL value, it is dereferenced by cx88_reset, and perhaps by cx88_core_put. Spotted by the Coverity checker. Signed-off-by: Duncan Sands Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-alsa.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 2acccd6d49bc..bffef1decc8b 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -672,6 +672,11 @@ static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, chip = (snd_cx88_card_t *) card->private_data; core = cx88_core_get(pci); + if (NULL == core) { + err = -EINVAL; + kfree (chip); + return err; + } if (!pci_dma_supported(pci,0xffffffff)) { dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name); @@ -688,11 +693,6 @@ static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, spin_lock_init(&chip->reg_lock); cx88_reset(core); - if (NULL == core) { - err = -EINVAL; - kfree (chip); - return err; - } chip->core = core; /* get irq */ -- cgit v1.2.3-59-g8ed1b From f6fe8c6a429bb44d95091e67f8e39662cd4e6fc3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 14 Mar 2006 00:35:07 -0300 Subject: V4L/DVB (3495): Kconfig: select VIDEO_CX25840 to build cx25840 a/v decoder module The cx25840 module requires external firmware in order to function, so it must select FW_LOADER, but saa7115 and saa7129 do not require it. This patch creates VIDEO_CX25840, and alters VIDEO_DECODER to select it. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 3 +++ drivers/media/video/Makefile | 3 ++- drivers/media/video/cx25840/Kconfig | 9 +++++++++ drivers/media/video/cx25840/Makefile | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 drivers/media/video/cx25840/Kconfig (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index f6889f771053..a76036ff9a9c 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -359,8 +359,11 @@ config VIDEO_AUDIO_DECODER config VIDEO_DECODER tristate "Add support for additional video chipsets" depends on VIDEO_DEV && I2C && EXPERIMENTAL + select VIDEO_CX25840 ---help--- Say Y here to compile drivers for SAA7115, SAA7127 and CX25840 video decoders. +source "drivers/media/video/cx25840/Kconfig" + endmenu diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 87b1ce6e2050..c15f8490b365 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o -obj-$(CONFIG_VIDEO_DECODER) += saa7115.o cx25840/ saa7127.o +obj-$(CONFIG_VIDEO_DECODER) += saa7115.o saa7127.o +obj-$(CONFIG_VIDEO_CX25840) += cx25840/ EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core diff --git a/drivers/media/video/cx25840/Kconfig b/drivers/media/video/cx25840/Kconfig new file mode 100644 index 000000000000..854264e42ec0 --- /dev/null +++ b/drivers/media/video/cx25840/Kconfig @@ -0,0 +1,9 @@ +config VIDEO_CX25840 + tristate "Conexant CX2584x audio/video decoders" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + select FW_LOADER + ---help--- + Support for the Conexant CX2584x audio/video decoders. + + To compile this driver as a module, choose M here: the + module will be called cx25840 diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile index 543ebacdc9d7..32a896c23d1e 100644 --- a/drivers/media/video/cx25840/Makefile +++ b/drivers/media/video/cx25840/Makefile @@ -1,6 +1,6 @@ cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \ cx25840-vbi.o -obj-$(CONFIG_VIDEO_DECODER) += cx25840.o +obj-$(CONFIG_VIDEO_CX25840) += cx25840.o EXTRA_CFLAGS += -I$(src)/.. -- cgit v1.2.3-59-g8ed1b From 49444fe1239cc26882d1b1fdcc658b3bdf8df942 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 14 Mar 2006 00:52:20 -0300 Subject: V4L/DVB (3496): Cpia2: move Kconfig build logic into cpia2/Kconfig Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 10 +--------- drivers/media/video/cpia2/Kconfig | 9 +++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 drivers/media/video/cpia2/Kconfig (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index a76036ff9a9c..ee0eed441a64 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -142,15 +142,7 @@ config VIDEO_CPIA_USB otherwise say N. This will not work with the Creative Webcam III. It is also available as a module (cpia_usb). -config VIDEO_CPIA2 - tristate "CPiA2 Video For Linux" - depends on VIDEO_DEV - ---help--- - This is the video4linux driver for cameras based on Vision's CPiA2 - (Colour Processor Interface ASIC), such as the Digital Blue QX5 - Microscope. If you have one of these cameras, say Y here - - This driver is also available as a module (cpia2). +source "drivers/media/video/cpia2/Kconfig" config VIDEO_SAA5246A tristate "SAA5246A, SAA5281 Teletext processor" diff --git a/drivers/media/video/cpia2/Kconfig b/drivers/media/video/cpia2/Kconfig new file mode 100644 index 000000000000..1c09ef981226 --- /dev/null +++ b/drivers/media/video/cpia2/Kconfig @@ -0,0 +1,9 @@ +config VIDEO_CPIA2 + tristate "CPiA2 Video For Linux" + depends on VIDEO_DEV + ---help--- + This is the video4linux driver for cameras based on Vision's CPiA2 + (Colour Processor Interface ASIC), such as the Digital Blue QX5 + Microscope. If you have one of these cameras, say Y here + + This driver is also available as a module (cpia2). -- cgit v1.2.3-59-g8ed1b From 5e5890e16ea917ad489a7778f51631bdb14523a2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 14 Mar 2006 01:25:01 -0300 Subject: V4L/DVB (3497): Remove redundant makefile inclusion of tuner.o VIDEO_MXB selects VIDEO_TUNER, so we don't have to include tuner.o in the Makefile. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index c15f8490b365..51721574d9cf 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -48,7 +48,7 @@ obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ -obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o +obj-$(CONFIG_VIDEO_MXB) += saa7111.o tda9840.o tea6415c.o tea6420.o mxb.o obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o obj-$(CONFIG_VIDEO_DPC) += saa7111.o dpc7146.o -- cgit v1.2.3-59-g8ed1b From 19478843e4f8af7de9b297876519ee8b98c2f5ad Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Mar 2006 17:24:57 -0300 Subject: V4L/DVB (3499): Fix a bug when more than MAXBOARDS were plugged on em28xx Coverity reported a bug at checking max number of supported boards by em28xx init code. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index f56ae4852165..78f0f7a706ea 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1949,7 +1949,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, model=id->driver_info; - if (nr > EM28XX_MAXBOARDS) { + if (nr >= EM28XX_MAXBOARDS) { printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS); em28xx_devused&=~(1< Date: Tue, 14 Mar 2006 17:30:09 -0300 Subject: V4L/DVB (3500): Ringbuffer: don't reset pointers to zero Oliver Endriss spotted, that resetting read and write pointers on flush() requires additional locking and breaks the av7110 driver. Therefore this patch partially reverts the previous patch titled "make dvb_ringbuffer compatible to dmxdev_buffer". Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_ringbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c index f233248358c4..c972fe014c58 100644 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c @@ -87,7 +87,7 @@ ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf) void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) { - rbuf->pread = rbuf->pwrite = 0; + rbuf->pread = rbuf->pwrite; rbuf->error = 0; } -- cgit v1.2.3-59-g8ed1b From 34731df288a5ffe4b0c396caf8cd24c6a710a222 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Tue, 14 Mar 2006 17:31:01 -0300 Subject: V4L/DVB (3501): Dmxdev: use dvb_ringbuffer Use dvb_ringbuffer instead of an own buffer implementation in dmxdev.[ch]. Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dmxdev.c | 156 ++++++++++++++---------------------- drivers/media/dvb/dvb-core/dmxdev.h | 14 +--- 2 files changed, 62 insertions(+), 108 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index f6932d6c62e3..09e96e9ddbdf 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -40,110 +40,72 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); #define dprintk if (debug) printk -static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer) +static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, + const u8 *src, size_t len) { - buffer->data = NULL; - buffer->size = 8192; - buffer->pread = 0; - buffer->pwrite = 0; - buffer->error = 0; - init_waitqueue_head(&buffer->queue); -} - -static inline int dvb_dmxdev_buffer_write(struct dmxdev_buffer *buf, - const u8 *src, int len) -{ - int split; - int free; - int todo; + ssize_t free; if (!len) return 0; if (!buf->data) return 0; - free = buf->pread - buf->pwrite; - split = 0; - if (free <= 0) { - free += buf->size; - split = buf->size - buf->pwrite; - } - if (len >= free) { + free = dvb_ringbuffer_free(buf); + if (len > free) { dprintk("dmxdev: buffer overflow\n"); - return -1; - } - if (split >= len) - split = 0; - todo = len; - if (split) { - memcpy(buf->data + buf->pwrite, src, split); - todo -= split; - buf->pwrite = 0; + return -EOVERFLOW; } - memcpy(buf->data + buf->pwrite, src + split, todo); - buf->pwrite = (buf->pwrite + todo) % buf->size; - return len; + + return dvb_ringbuffer_write(buf, src, len); } -static ssize_t dvb_dmxdev_buffer_read(struct dmxdev_buffer *src, +static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, int non_blocking, char __user *buf, size_t count, loff_t *ppos) { - unsigned long todo = count; - int split, avail, error; + size_t todo; + ssize_t avail; + ssize_t ret = 0; if (!src->data) return 0; - if ((error = src->error)) { - src->pwrite = src->pread; - src->error = 0; - return error; + if (src->error) { + ret = src->error; + dvb_ringbuffer_flush(src); + return ret; } - if (non_blocking && (src->pwrite == src->pread)) - return -EWOULDBLOCK; - - while (todo > 0) { - if (non_blocking && (src->pwrite == src->pread)) - return (count - todo) ? (count - todo) : -EWOULDBLOCK; + for (todo = count; todo > 0; todo -= ret) { + if (non_blocking && dvb_ringbuffer_empty(src)) { + ret = -EWOULDBLOCK; + break; + } - if (wait_event_interruptible(src->queue, - (src->pread != src->pwrite) || - (src->error)) < 0) - return count - todo; + ret = wait_event_interruptible(src->queue, + !dvb_ringbuffer_empty(src) || + (src->error != 0)); + if (ret < 0) + break; - if ((error = src->error)) { - src->pwrite = src->pread; - src->error = 0; - return error; + if (src->error) { + ret = src->error; + dvb_ringbuffer_flush(src); + break; } - split = src->size; - avail = src->pwrite - src->pread; - if (avail < 0) { - avail += src->size; - split = src->size - src->pread; - } + avail = dvb_ringbuffer_avail(src); if (avail > todo) avail = todo; - if (split < avail) { - if (copy_to_user(buf, src->data + src->pread, split)) - return -EFAULT; - buf += split; - src->pread = 0; - todo -= split; - avail -= split; - } - if (avail) { - if (copy_to_user(buf, src->data + src->pread, avail)) - return -EFAULT; - src->pread = (src->pread + avail) % src->size; - todo -= avail; - buf += avail; - } + + ret = dvb_ringbuffer_read(src, buf, avail, 1); + if (ret < 0) + break; + + buf += ret; } - return count; + + return (count - todo) ? (count - todo) : ret; } static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type) @@ -179,13 +141,12 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) } if ((file->f_flags & O_ACCMODE) == O_RDONLY) { - dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); - dmxdev->dvr_buffer.size = DVR_BUFFER_SIZE; - dmxdev->dvr_buffer.data = vmalloc(DVR_BUFFER_SIZE); - if (!dmxdev->dvr_buffer.data) { + void *mem = vmalloc(DVR_BUFFER_SIZE); + if (!mem) { mutex_unlock(&dmxdev->mutex); return -ENOMEM; } + dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); } if ((file->f_flags & O_ACCMODE) == O_WRONLY) { @@ -280,7 +241,7 @@ static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, unsigned long size) { - struct dmxdev_buffer *buf = &dmxdevfilter->buffer; + struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; void *mem; if (buf->size == size) @@ -291,7 +252,7 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, mem = buf->data; buf->data = NULL; buf->size = size; - buf->pwrite = buf->pread = 0; + dvb_ringbuffer_flush(buf); spin_unlock_irq(&dmxdevfilter->dev->lock); vfree(mem); @@ -359,8 +320,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, buffer2_len); } if (ret < 0) { - dmxdevfilter->buffer.pwrite = dmxdevfilter->buffer.pread; - dmxdevfilter->buffer.error = -EOVERFLOW; + dvb_ringbuffer_flush(&dmxdevfilter->buffer); + dmxdevfilter->buffer.error = ret; } if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) dmxdevfilter->state = DMXDEV_STATE_DONE; @@ -375,7 +336,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, enum dmx_success success) { struct dmxdev_filter *dmxdevfilter = feed->priv; - struct dmxdev_buffer *buffer; + struct dvb_ringbuffer *buffer; int ret; spin_lock(&dmxdevfilter->dev->lock); @@ -397,8 +358,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, if (ret == buffer1_len) ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); if (ret < 0) { - buffer->pwrite = buffer->pread; - buffer->error = -EOVERFLOW; + dvb_ringbuffer_flush(buffer); + buffer->error = ret; } spin_unlock(&dmxdevfilter->dev->lock); wake_up(&buffer->queue); @@ -494,7 +455,8 @@ static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) return 0; return -EINVAL; } - dmxdevfilter->buffer.pwrite = dmxdevfilter->buffer.pread = 0; + + dvb_ringbuffer_flush(&dmxdevfilter->buffer); return 0; } @@ -520,16 +482,16 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) if (filter->state >= DMXDEV_STATE_GO) dvb_dmxdev_filter_stop(filter); - if (!(mem = filter->buffer.data)) { + if (!filter->buffer.data) { mem = vmalloc(filter->buffer.size); + if (!mem) + return -ENOMEM; spin_lock_irq(&filter->dev->lock); filter->buffer.data = mem; spin_unlock_irq(&filter->dev->lock); - if (!filter->buffer.data) - return -ENOMEM; } - filter->buffer.pwrite = filter->buffer.pread = 0; + dvb_ringbuffer_flush(&filter->buffer); switch (filter->type) { case DMXDEV_TYPE_SEC: @@ -692,7 +654,7 @@ static int dvb_demux_open(struct inode *inode, struct file *file) mutex_init(&dmxdevfilter->mutex); file->private_data = dmxdevfilter; - dvb_dmxdev_buffer_init(&dmxdevfilter->buffer); + dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); dmxdevfilter->type = DMXDEV_TYPE_NONE; dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); dmxdevfilter->feed.ts = NULL; @@ -973,7 +935,7 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) if (dmxdevfilter->buffer.error) mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); - if (dmxdevfilter->buffer.pread != dmxdevfilter->buffer.pwrite) + if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer)) mask |= (POLLIN | POLLRDNORM | POLLPRI); return mask; @@ -1047,7 +1009,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) if (dmxdev->dvr_buffer.error) mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); - if (dmxdev->dvr_buffer.pread != dmxdev->dvr_buffer.pwrite) + if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer)) mask |= (POLLIN | POLLRDNORM | POLLPRI); } else mask |= (POLLOUT | POLLWRNORM | POLLPRI); @@ -1097,7 +1059,7 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, dmxdev, DVB_DEVICE_DVR); - dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); + dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); return 0; } diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h index 1b3e49bd9aa2..d2bee9ffe43c 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.h +++ b/drivers/media/dvb/dvb-core/dmxdev.h @@ -36,6 +36,7 @@ #include "dvbdev.h" #include "demux.h" +#include "dvb_ringbuffer.h" enum dmxdev_type { DMXDEV_TYPE_NONE, @@ -52,15 +53,6 @@ enum dmxdev_state { DMXDEV_STATE_TIMEDOUT }; -struct dmxdev_buffer { - u8 *data; - int size; - int pread; - int pwrite; - wait_queue_head_t queue; - int error; -}; - struct dmxdev_filter { union { struct dmx_section_filter *sec; @@ -79,7 +71,7 @@ struct dmxdev_filter { enum dmxdev_type type; enum dmxdev_state state; struct dmxdev *dev; - struct dmxdev_buffer buffer; + struct dvb_ringbuffer buffer; struct mutex mutex; @@ -102,7 +94,7 @@ struct dmxdev { #define DMXDEV_CAP_DUPLEX 1 struct dmx_frontend *dvr_orig_fe; - struct dmxdev_buffer dvr_buffer; + struct dvb_ringbuffer dvr_buffer; #define DVR_BUFFER_SIZE (10*188*1024) struct mutex mutex; -- cgit v1.2.3-59-g8ed1b From 12a219da0a74d1d797475addbccaedf2343be571 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 14 Mar 2006 16:07:42 -0300 Subject: V4L/DVB (3502): Saa7134: make unsupported secondary decoder message generic There are already some supported devices that contain two saa713x chips on-board, where only one of these chips is currently functional in the driver. We are already printing a warning message for the second saa7134 decoder in SAA7134_BOARD_AVERMEDIA_A169_B. This patch alters that case to make it generic, so that other cards in the same situation can use it. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index f9a29c415c73..5e0251a33e8b 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3471,10 +3471,10 @@ int saa7134_board_init1(struct saa7134_dev *dev) dev->has_remote = SAA7134_REMOTE_I2C; break; case SAA7134_BOARD_AVERMEDIA_A169_B: - printk("%s: AVerMedia A169: dual saa7134 broadcast decoders\n" + printk("%s: %s: dual saa713x broadcast decoders\n" "%s: Sorry, none of the inputs to this chip are supported yet.\n" "%s: Dual decoder functionality is disabled for now, use the other chip.\n", - dev->name,dev->name,dev->name); + dev->name,card(dev).name,dev->name,dev->name); break; } return 0; -- cgit v1.2.3-59-g8ed1b From 67ac9a40f90db57b09f7d98f72d8d0344acefbac Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 14 Mar 2006 16:18:49 -0300 Subject: V4L/DVB (3503): Whitespace: fix incorrect indentation of curly bracket Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 5e0251a33e8b..3824fba7fb1c 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -536,7 +536,7 @@ struct saa7134_board saa7134_boards[] = { .radio = { .name = name_radio, .amux = LINE2, - }, + }, }, [SAA7134_BOARD_MD7134] = { .name = "Medion 7134", -- cgit v1.2.3-59-g8ed1b From ba3a5a81f79d16666e1b46ee9e4fe7f2bc8bd70f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 14 Mar 2006 19:02:12 -0300 Subject: V4L/DVB (3504): Medion 7134: Autodetect second bridge chip The device, Medion 7134, has two saa7134 chips on it, but only one of them is functional in the current saa7134 driver. This patch adds autodetection for the second, unsupported saa7134 chip, as SAA7134_BOARD_MD7134_BRIDGE_2, and displays a message to the user (in dmesg) indicating that the second chip isn't yet functional. This is useful for users, since two instances of the saa7134 driver will spawn. This patch will prevent confusion by warning the user that only one of the chips on the board are functional. There are other versions of the SAA7134_BOARD_MD7134 with only a single saa7134 bridge/decoder -- those devices will not be affected by this patch. Only devices containing the second chip will display the warning. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 18 ++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 20 insertions(+) (limited to 'drivers') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 421a2427f50a..8c7195455963 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -91,3 +91,4 @@ 90 -> Kworld ATSC110 [17de:7350] 91 -> AVerMedia A169 B [1461:7360] 92 -> AVerMedia A169 B1 [1461:6360] + 93 -> Medion 7134 Bridge #2 [16be:0005] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 3824fba7fb1c..fdd7f48f3b76 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2797,6 +2797,17 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }}, }, + [SAA7134_BOARD_MD7134_BRIDGE_2] = { + /* This card has two saa7134 chips on it, + but only one of them is currently working. + The programming for the primary decoder is + in SAA7134_BOARD_MD7134 */ + .name = "Medion 7134 Bridge #2", + .audio_clock = 0x00187de7, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3315,6 +3326,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1461, .subdevice = 0x6360, .driver_data = SAA7134_BOARD_AVERMEDIA_A169_B1, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x16be, + .subdevice = 0x0005, + .driver_data = SAA7134_BOARD_MD7134_BRIDGE_2, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3471,6 +3488,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) dev->has_remote = SAA7134_REMOTE_I2C; break; case SAA7134_BOARD_AVERMEDIA_A169_B: + case SAA7134_BOARD_MD7134_BRIDGE_2: printk("%s: %s: dual saa713x broadcast decoders\n" "%s: Sorry, none of the inputs to this chip are supported yet.\n" "%s: Dual decoder functionality is disabled for now, use the other chip.\n", diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 7d04ed330ec3..683e785c18bd 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -220,6 +220,7 @@ struct saa7134_format { #define SAA7134_BOARD_KWORLD_ATSC110 90 #define SAA7134_BOARD_AVERMEDIA_A169_B 91 #define SAA7134_BOARD_AVERMEDIA_A169_B1 92 +#define SAA7134_BOARD_MD7134_BRIDGE_2 93 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3-59-g8ed1b From 77cc5319900054662861cb147f300b1d1d22fcc5 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Wed, 15 Mar 2006 09:31:31 -0300 Subject: V4L/DVB (3506): Cinergy T2 dmx cleanup on disconnect Detaching the device didn't clean up several device files in /dev/dvb, after applying that patch all dvb devices disappeared as expected. Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/cinergyT2/cinergyT2.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 29b7be5271d4..71b575dc22bd 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -506,6 +506,9 @@ static int cinergyt2_open (struct inode *inode, struct file *file) static void cinergyt2_unregister(struct cinergyt2 *cinergyt2) { + dvb_net_release(&cinergyt2->dvbnet); + dvb_dmxdev_release(&cinergyt2->dmxdev); + dvb_dmx_release(&cinergyt2->demux); dvb_unregister_device(cinergyt2->fedev); dvb_unregister_adapter(&cinergyt2->adapter); @@ -938,6 +941,7 @@ static int cinergyt2_probe (struct usb_interface *intf, return 0; bailout: + dvb_net_release(&cinergyt2->dvbnet); dvb_dmxdev_release(&cinergyt2->dmxdev); dvb_dmx_release(&cinergyt2->demux); dvb_unregister_adapter(&cinergyt2->adapter); -- cgit v1.2.3-59-g8ed1b From c04e89b1f2c624fbb1e57874062491c2b987c7e2 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 15 Mar 2006 16:17:11 -0300 Subject: V4L/DVB (3509): Make a needlessly global function static. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/zl10353.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 23846c4452ad..d7d9f59d76d2 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -88,7 +88,7 @@ static int zl10353_read_register(struct zl10353_state *state, u8 reg) return b1[0]; } -void zl10353_dump_regs(struct dvb_frontend *fe) +static void zl10353_dump_regs(struct dvb_frontend *fe) { struct zl10353_state *state = fe->demodulator_priv; char buf[52], buf2[4]; -- cgit v1.2.3-59-g8ed1b From f5762e441d5022ecc5b66b5fe54e41e2ac5d02be Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 13 Mar 2006 13:31:31 -0300 Subject: V4L/DVB (3513): Remove saa711x driver Now, em28xx uses saa7115 instead of saa711x. saa7115 driver is capable of handling saa 7113, 7114 and 7115. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Makefile | 2 +- drivers/media/video/em28xx/em28xx-video.c | 218 ++---------------------------- drivers/media/video/saa7115.c | 76 +++++++++-- include/media/v4l2-common.h | 1 + 4 files changed, 78 insertions(+), 219 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 51721574d9cf..00080224f281 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -44,7 +44,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ -obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o +obj-$(CONFIG_VIDEO_EM28XX) += saa7115.o tvp5150.o obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 78f0f7a706ea..780342f7b239 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -101,23 +101,6 @@ static struct em28xx_tvnorm tvnorms[] = { } }; -static const unsigned char saa7114_i2c_init[] = { - 0x00,0x00,0x01,0x08,0x02,0xc4,0x03,0x30,0x04,0x90,0x05,0x90,0x06,0xeb,0x07,0xe0, - 0x08,0x88,0x09,0x40,0x0a,0x80,0x0b,0x44,0x0c,0x40,0x0d,0x00,0x0e,0x81,0x0f,0x2a, - 0x10,0x06,0x11,0x00,0x12,0xc8,0x13,0x80,0x14,0x00,0x15,0x11,0x16,0x01,0x17,0x42, - 0x18,0x40,0x19,0x80,0x40,0x00,0x41,0xff,0x42,0xff,0x43,0xff,0x44,0xff,0x45,0xff, - 0x46,0xff,0x47,0xff,0x48,0xff,0x49,0xff,0x4a,0xff,0x4b,0xff,0x4c,0xff,0x4d,0xff, - 0x4e,0xff,0x4f,0xff,0x50,0xff,0x51,0xff,0x52,0xff,0x53,0xff,0x54,0x5f,0x55,0xff, - 0x56,0xff,0x57,0xff,0x58,0x00,0x59,0x47,0x5a,0x03,0x5b,0x03,0x5d,0x3e,0x5e,0x00, - 0x80,0x1c,0x83,0x01,0x84,0xa5,0x85,0x10,0x86,0x45,0x87,0x41,0x88,0xf0,0x88,0x00, - 0x88,0xf0,0x90,0x00,0x91,0x08,0x92,0x00,0x93,0x80,0x94,0x08,0x95,0x00,0x96,0xc0, - 0x97,0x02,0x98,0x13,0x99,0x00,0x9a,0x38,0x9b,0x01,0x9c,0x80,0x9d,0x02,0x9e,0x06, - 0x9f,0x01,0xa0,0x01,0xa1,0x00,0xa2,0x00,0xa4,0x80,0xa5,0x36,0xa6,0x36,0xa8,0x67, - 0xa9,0x04,0xaa,0x00,0xac,0x33,0xad,0x02,0xae,0x00,0xb0,0xcd,0xb1,0x04,0xb2,0xcd, - 0xb3,0x04,0xb4,0x01,0xb8,0x00,0xb9,0x00,0xba,0x00,0xbb,0x00,0xbc,0x00,0xbd,0x00, - 0xbe,0x00,0xbf,0x00 -}; - #define TVNORMS ARRAY_SIZE(tvnorms) /* supported controls */ @@ -144,65 +127,6 @@ static struct v4l2_queryctrl em28xx_qctrl[] = { } }; -/* FIXME: These are specific to saa711x - should be moved to its code */ -static struct v4l2_queryctrl saa711x_qctrl[] = { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = -128, - .maximum = 127, - .step = 1, - .default_value = 0, - .flags = 0, - },{ - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0x0, - .maximum = 0x1f, - .step = 0x1, - .default_value = 0x10, - .flags = 0, - },{ - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0x0, - .maximum = 0x1f, - .step = 0x1, - .default_value = 0x10, - .flags = 0, - },{ - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Red chroma balance", - .minimum = -128, - .maximum = 127, - .step = 1, - .default_value = 0, - .flags = 0, - },{ - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Blue chroma balance", - .minimum = -128, - .maximum = 127, - .step = 1, - .default_value = 0, - .flags = 0, - },{ - .id = V4L2_CID_GAMMA, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gamma", - .minimum = 0x0, - .maximum = 0x3f, - .step = 0x1, - .default_value = 0x20, - .flags = 0, - } -}; - static struct usb_driver em28xx_usb_driver; static DEFINE_MUTEX(em28xx_sysfs_lock); @@ -245,22 +169,9 @@ static int em28xx_config(struct em28xx *dev) static void em28xx_config_i2c(struct em28xx *dev) { struct v4l2_frequency f; - struct video_decoder_init em28xx_vdi = {.data = NULL }; - - - /* configure decoder */ - if(dev->model == EM2820_BOARD_MSI_VOX_USB_2){ - em28xx_vdi.data=saa7114_i2c_init; - em28xx_vdi.len=sizeof(saa7114_i2c_init); - } - - - em28xx_i2c_call_clients(dev, DECODER_INIT, &em28xx_vdi); - em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &dev->ctl_input); -/* em28xx_i2c_call_clients(dev,DECODER_SET_PICTURE, &dev->vpic); */ -/* em28xx_i2c_call_clients(dev,DECODER_SET_NORM,&dev->tvnorm->id); */ -/* em28xx_i2c_call_clients(dev,DECODER_ENABLE_OUTPUT,&output); */ -/* em28xx_i2c_call_clients(dev,DECODER_DUMP, NULL); */ + em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL); + em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &dev->ctl_input); + em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); /* configure tuner */ f.tuner = 0; @@ -300,8 +211,7 @@ static void video_mux(struct em28xx *dev, int index) dev->ctl_input = index; dev->ctl_ainput = INPUT(index)->amux; - em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &input); - + em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &input); em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput); @@ -747,43 +657,6 @@ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) } } -/*FIXME: should be moved to saa711x */ -static int saa711x_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) -{ - s32 tmp; - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - if ((tmp = em28xx_brightness_get(dev)) < 0) - return -EIO; - ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ - return 0; - case V4L2_CID_CONTRAST: - if ((ctrl->value = em28xx_contrast_get(dev)) < 0) - return -EIO; - return 0; - case V4L2_CID_SATURATION: - if ((ctrl->value = em28xx_saturation_get(dev)) < 0) - return -EIO; - return 0; - case V4L2_CID_RED_BALANCE: - if ((tmp = em28xx_v_balance_get(dev)) < 0) - return -EIO; - ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ - return 0; - case V4L2_CID_BLUE_BALANCE: - if ((tmp = em28xx_u_balance_get(dev)) < 0) - return -EIO; - ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ - return 0; - case V4L2_CID_GAMMA: - if ((ctrl->value = em28xx_gamma_get(dev)) < 0) - return -EIO; - return 0; - default: - return -EINVAL; - } -} - /* * em28xx_set_ctrl() * mute or set new saturation, brightness or contrast @@ -806,27 +679,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) } } -/*FIXME: should be moved to saa711x */ -static int saa711x_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - return em28xx_brightness_set(dev, ctrl->value); - case V4L2_CID_CONTRAST: - return em28xx_contrast_set(dev, ctrl->value); - case V4L2_CID_SATURATION: - return em28xx_saturation_set(dev, ctrl->value); - case V4L2_CID_RED_BALANCE: - return em28xx_v_balance_set(dev, ctrl->value); - case V4L2_CID_BLUE_BALANCE: - return em28xx_u_balance_set(dev, ctrl->value); - case V4L2_CID_GAMMA: - return em28xx_gamma_set(dev, ctrl->value); - default: - return -EINVAL; - } -} - /* * em28xx_stream_interrupt() * stops streaming @@ -1130,8 +982,6 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, em28xx_set_norm(dev, dev->width, dev->height); - em28xx_i2c_call_clients(dev, DECODER_SET_NORM, - &tvnorms[i].mode); em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); @@ -1242,22 +1092,11 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, } } } - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,qc); - if (qc->type) - return 0; - else - return -EINVAL; - } - for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { - if (qc->id && qc->id == saa711x_qctrl[i].id) { - memcpy(qc, &(saa711x_qctrl[i]), - sizeof(*qc)); - return 0; - } - } - - return -EINVAL; + em28xx_i2c_call_clients(dev,cmd,qc); + if (qc->type) + return 0; + else + return -EINVAL; } case VIDIOC_G_CTRL: { @@ -1267,12 +1106,8 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, if (!dev->has_msp34xx) retval=em28xx_get_ctrl(dev, ctrl); if (retval==-EINVAL) { - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,arg); - return 0; - } - - return saa711x_get_ctrl(dev, ctrl); + em28xx_i2c_call_clients(dev,cmd,arg); + return 0; } else return retval; } case VIDIOC_S_CTRL: @@ -1293,33 +1128,8 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, } } - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,arg); - return 0; - } else if (!dev->has_msp34xx) { - for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { - if (ctrl->id == em28xx_qctrl[i].id) { - if (ctrl->value < - em28xx_qctrl[i].minimum - || ctrl->value > - em28xx_qctrl[i].maximum) - return -ERANGE; - return em28xx_set_ctrl(dev, ctrl); - } - } - for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { - if (ctrl->id == saa711x_qctrl[i].id) { - if (ctrl->value < - saa711x_qctrl[i].minimum - || ctrl->value > - saa711x_qctrl[i].maximum) - return -ERANGE; - return saa711x_set_ctrl(dev, ctrl); - } - } - } - - return -EINVAL; + em28xx_i2c_call_clients(dev,cmd,arg); + return 0; } /* --- tuner ioctls ------------------------------------------ */ case VIDIOC_G_TUNER: @@ -1772,7 +1582,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, #ifdef CONFIG_MODULES /* request some modules */ if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114) - request_module("saa711x"); + request_module("saa7115"); if (dev->decoder == EM28XX_TVP5150) request_module("tvp5150"); if (dev->has_tuner) diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index f0eb9851bf53..7050d81c0242 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1,4 +1,4 @@ -/* saa7115 - Philips SAA7114/SAA7115 video decoder driver +/* saa7115 - Philips SAA7113/SAA7114/SAA7115 video decoder driver * * Based on saa7114 driver by Maxim Yevtyushkin, which is based on * the saa7111 driver by Dave Perks. @@ -16,6 +16,7 @@ * (2/17/2003) * * VBI support (2004) and cleanups (2005) by Hans Verkuil + * SAA7113 support by Mauro Carvalho Chehab * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -42,8 +43,9 @@ #include #include -MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver"); -MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil"); +MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver"); +MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, " + "Hans Verkuil, Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); static int debug = 0; @@ -51,7 +53,10 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { + 0x4a >>1, 0x48 >>1, /* SAA7113 */ + 0x42 >> 1, 0x40 >> 1, /* SAA7114 and SAA7115 */ + I2C_CLIENT_END }; I2C_CLIENT_INSMOD; @@ -101,10 +106,12 @@ static inline int saa7115_read(struct i2c_client *client, u8 reg) Hauppauge driver sets. */ static const unsigned char saa7115_init_auto_input[] = { + /* Front-End Part */ 0x01, 0x48, /* white peak control disabled */ 0x03, 0x20, /* was 0x30. 0x20: long vertical blanking */ 0x04, 0x90, /* analog gain set to 0 */ 0x05, 0x90, /* analog gain set to 0 */ + /* Decoder Part */ 0x06, 0xeb, /* horiz sync begin = -21 */ 0x07, 0xe0, /* horiz sync stop = -17 */ 0x0a, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */ @@ -123,6 +130,8 @@ static const unsigned char saa7115_init_auto_input[] = { 0x1b, 0x42, /* misc chroma control 0x42 = recommended */ 0x1c, 0xa9, /* combfilter control 0xA9 = recommended */ 0x1d, 0x01, /* combfilter control 0x01 = recommended */ + + /* Power Device Control */ 0x88, 0xd0, /* reset device */ 0x88, 0xf0, /* set device programmed, all in operational mode */ 0x00, 0x00 @@ -338,6 +347,33 @@ static const unsigned char saa7115_cfg_vbi_off[] = { 0x00, 0x00 }; +static const unsigned char saa7113_init_auto_input[] = { + 0x01, 0x08, /* PH7113_INCREMENT_DELAY - (1) (1) (1) (1) IDEL3 IDEL2 IDELL1 IDEL0 */ + 0x02, 0xc2, /* PH7113_ANALOG_INPUT_CONTR_1 - FUSE1 FUSE0 GUDL1 GUDL0 MODE3 MODE2 MODE1 MODE0 */ + 0x03, 0x30, /* PH7113_ANALOG_INPUT_CONTR_2 - (1) HLNRS VBSL WPOFF HOLDG GAFIX GAI28 GAI18 */ + 0x04, 0x00, /* PH7113_ANALOG_INPUT_CONTR_3 - GAI17 GAI16 GAI15 GAI14 GAI13 GAI12 GAI11 GAI10 */ + 0x05, 0x00, /* PH7113_ANALOG_INPUT_CONTR_4 - GAI27 GAI26 GAI25 GAI24 GAI23 GAI22 GAI21 GAI20 */ + 0x06, 0x89, /* PH7113_HORIZONTAL_SYNC_START - HSB7 HSB6 HSB5 HSB4 HSB3 HSB2 HSB1 HSB0 */ + 0x07, 0x0d, /* PH7113_HORIZONTAL_SYNC_STOP - HSS7 HSS6 HSS5 HSS4 HSS3 HSS2 HSS1 HSS0 */ + 0x08, 0x88, /* PH7113_SYNC_CONTROL - AUFD FSEL FOET HTC1 HTC0 HPLL VNOI1 VNOI0 */ + 0x09, 0x01, /* PH7113_LUMINANCE_CONTROL - BYPS PREF BPSS1 BPSS0 VBLB UPTCV APER1 APER0 */ + 0x0a, 0x80, /* PH7113_LUMINANCE_BRIGHTNESS - BRIG7 BRIG6 BRIG5 BRIG4 BRIG3 BRIG2 BRIG1 BRIG0 */ + 0x0b, 0x47, /* PH7113_LUMINANCE_CONTRAST - CONT7 CONT6 CONT5 CONT4 CONT3 CONT2 CONT1 CONT0 */ + 0x0c, 0x40, /* PH7113_CHROMA_SATURATION - SATN7 SATN6 SATN5 SATN4 SATN3 SATN2 SATN1 SATN0 */ + 0x0d, 0x00, /* PH7113_CHROMA_HUE_CONTROL - HUEC7 HUEC6 HUEC5 HUEC4 HUEC3 HUEC2 HUEC1 HUEC0 */ + 0x0e, 0x01, /* PH7113_CHROMA_CONTROL - CDTO CSTD2 CSTD1 CSTD0 DCCF FCTC CHBW1 CHBW0 */ + 0x0f, 0x2a, /* PH7113_CHROMA_GAIN_CONTROL - ACGC CGAIN6 CGAIN5 CGAIN4 CGAIN3 CGAIN2 CGAIN1 CGAIN0 */ + 0x10, 0x08, /* PH7113_FORMAT_DELAY_CONTROL - OFTS1 OFTS0 HDEL1 HDEL0 VRLN YDEL2 YDEL1 YDEL0 */ + 0x11, 0x0c, /* PH7113_OUTPUT_CONTROL_1 - GPSW1 CM99 GPSW0 HLSEL OEYC OERT VIPB COLO */ + 0x12, 0x07, /* PH7113_OUTPUT_CONTROL_2 - RTSE13 RTSE12 RTSE11 RTSE10 RTSE03 RTSE02 RTSE01 RTSE00 */ + 0x13, 0x00, /* PH7113_OUTPUT_CONTROL_3 - ADLSB (1) (1) OLDSB FIDP (1) AOSL1 AOSL0 */ + 0x14, 0x00, /* RESERVED 14 - (1) (1) (1) (1) (1) (1) (1) (1) */ + 0x15, 0x00, /* PH7113_V_GATE1_START - VSTA7 VSTA6 VSTA5 VSTA4 VSTA3 VSTA2 VSTA1 VSTA0 */ + 0x16, 0x00, /* PH7113_V_GATE1_STOP - VSTO7 VSTO6 VSTO5 VSTO4 VSTO3 VSTO2 VSTO1 VSTO0 */ + 0x17, 0x00, /* PH7113_V_GATE1_MSB - (1) (1) (1) (1) (1) (1) VSTO8 VSTA8 */ + 0x00, 0x00 +}; + static const unsigned char saa7115_init_misc[] = { 0x38, 0x03, /* audio stuff */ 0x39, 0x10, @@ -680,7 +716,7 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) state->std = std; /* restart task B if needed */ - if (taskb && state->ident == V4L2_IDENT_SAA7114) { + if (taskb && state->ident != V4L2_IDENT_SAA7115) { saa7115_writeregs(client, saa7115_cfg_vbi_on); } @@ -703,7 +739,7 @@ static void saa7115_log_status(struct i2c_client *client) int vcr; v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq); - if (client->name[6] == '4') { + if (state->ident != V4L2_IDENT_SAA7115) { /* status for the saa7114 */ reg1f = saa7115_read(client, 0x1f); signalOk = (reg1f & 0xc1) == 0x81; @@ -751,8 +787,8 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo u8 lcr[24]; int i, x; - /* saa7114 doesn't yet support VBI */ - if (state->ident == V4L2_IDENT_SAA7114) + /* saa7113/71144 doesn't yet support VBI */ + if (state->ident != V4L2_IDENT_SAA7115) return; for (i = 0; i <= 23; i++) @@ -1261,14 +1297,12 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) saa7115_write(client, 0, 5); chip_id = saa7115_read(client, 0) & 0x0f; - if (chip_id != 4 && chip_id != 5) { + if (chip_id <3 && chip_id > 5) { v4l_dbg(1, debug, client, "saa7115 not found\n"); kfree(client); return 0; } - if (chip_id == 4) { - snprintf(client->name, sizeof(client->name) - 1, "saa7114"); - } + snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id); v4l_info(client, "saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name); state = kzalloc(sizeof(struct saa7115_state), GFP_KERNEL); @@ -1285,13 +1319,27 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) state->contrast = 64; state->hue = 0; state->sat = 64; - state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115; + switch (chip_id) { + case 3: + state->ident = V4L2_IDENT_SAA7113; + break; + case 4: + state->ident = V4L2_IDENT_SAA7114; + break; + default: + state->ident = V4L2_IDENT_SAA7115; + break; + } + state->audclk_freq = 48000; v4l_dbg(1, debug, client, "writing init values\n"); /* init to 60hz/48khz */ - saa7115_writeregs(client, saa7115_init_auto_input); + if (state->ident==V4L2_IDENT_SAA7113) + saa7115_writeregs(client, saa7113_init_auto_input); + else + saa7115_writeregs(client, saa7115_init_auto_input); saa7115_writeregs(client, saa7115_init_misc); saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index c44741e78f20..2360453e7496 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -103,6 +103,7 @@ enum v4l2_chip_ident { V4L2_IDENT_UNKNOWN = 0, /* module saa7115: reserved range 100-149 */ + V4L2_IDENT_SAA7113 = 103, V4L2_IDENT_SAA7114 = 104, V4L2_IDENT_SAA7115 = 105, -- cgit v1.2.3-59-g8ed1b From f89982a978974cc2fb74f512d7ec7438e0e851ea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Mar 2006 16:33:33 -0300 Subject: V4L/DVB (3514): SAA7113 doesn't have auto std chroma detection mode This patch makes chroma standard selection based at possible values, according with datasheet. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 7050d81c0242..498d9aaec1e5 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -713,6 +713,35 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) saa7115_writeregs(client, saa7115_cfg_50hz_video); } + /* Register 0E - Bits D6-D4 on NO-AUTO mode + (SAA7113 doesn't have auto mode) + 50 Hz / 625 lines 60 Hz / 525 lines + 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz) + 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz) + 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz) + 011 NTSC N (3.58MHz) PAL M (3.58MHz) + 100 reserved NTSC-Japan (3.58MHz) + */ + if (state->ident == V4L2_IDENT_SAA7113) { + u8 reg = saa7115_read(client, 0x0e) & 0x8f; + + if (std & V4L2_STD_PAL) { + if (std == V4L2_STD_PAL_M) { + reg|=0x30; + } else if (std == V4L2_STD_PAL_N) { + reg|=0x20; + } else if (std == V4L2_STD_PAL_60) { + reg|=0x10; + } + } else if (std & V4L2_STD_NTSC) { + if (std == V4L2_STD_NTSC_M_JP) { + reg|=0x40; + } + } + saa7115_write(client, 0x0e, reg); + } + + state->std = std; /* restart task B if needed */ -- cgit v1.2.3-59-g8ed1b From 9b89f2d301db6ad1fc716b70d9e26a38c958e7a5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 15 Mar 2006 17:52:14 -0300 Subject: V4L/DVB (3521): Avoid warnings at video-buf.c Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/video-buf.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index a8918e839f65..87e937581d5a 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -427,7 +427,7 @@ videobuf_queue_is_busy(struct videobuf_queue *q) void videobuf_queue_cancel(struct videobuf_queue *q) { - unsigned long flags; + unsigned long flags=0; int i; /* remove queued buffers from list */ @@ -588,7 +588,7 @@ videobuf_qbuf(struct videobuf_queue *q, { struct videobuf_buffer *buf; enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; int retval; mutex_lock(&q->lock); @@ -700,7 +700,7 @@ int videobuf_streamon(struct videobuf_queue *q) { struct videobuf_buffer *buf; struct list_head *list; - unsigned long flags; + unsigned long flags=0; int retval; mutex_lock(&q->lock); @@ -745,7 +745,7 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, size_t count, loff_t *ppos) { enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; int retval; /* setup stuff */ @@ -787,7 +787,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, int nonblocking) { enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; unsigned size, nbufs, bytes; int retval; @@ -866,7 +866,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, int videobuf_read_start(struct videobuf_queue *q) { enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; int count = 0, size = 0; int err, i; @@ -918,7 +918,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, { unsigned int *fc, bytes; int err, retval; - unsigned long flags; + unsigned long flags=0; dprintk(2,"%s\n",__FUNCTION__); mutex_lock(&q->lock); -- cgit v1.2.3-59-g8ed1b From 02c17224da6182d11cde34d57b27b93aaa7206cf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 16 Mar 2006 18:44:07 -0300 Subject: V4L/DVB (3522): Fixed a trouble with other PAL standards V4L2_STD_PAL define is not correct. It specifies only 50Hz PAL standards. This patch fixes saa7113 color config for other PAL video standards. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 498d9aaec1e5..b184fd00b4e7 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -725,18 +725,14 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) if (state->ident == V4L2_IDENT_SAA7113) { u8 reg = saa7115_read(client, 0x0e) & 0x8f; - if (std & V4L2_STD_PAL) { - if (std == V4L2_STD_PAL_M) { - reg|=0x30; - } else if (std == V4L2_STD_PAL_N) { - reg|=0x20; - } else if (std == V4L2_STD_PAL_60) { - reg|=0x10; - } - } else if (std & V4L2_STD_NTSC) { - if (std == V4L2_STD_NTSC_M_JP) { - reg|=0x40; - } + if (std == V4L2_STD_PAL_M) { + reg|=0x30; + } else if (std == V4L2_STD_PAL_N) { + reg|=0x20; + } else if (std == V4L2_STD_PAL_60) { + reg|=0x10; + } else if (std == V4L2_STD_NTSC_M_JP) { + reg|=0x40; } saa7115_write(client, 0x0e, reg); } -- cgit v1.2.3-59-g8ed1b From cfdd4ad0661e57db353ff36c2e8c57fc956cf6fb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 13 Mar 2006 23:44:31 -0300 Subject: V4L/DVB (3494): Kconfig: select VIDEO_MSP3400 to build msp3400.ko The msp3400 driver is currently only being built if the bttv driver is selected. There are new drivers that will be needing msp3400, so simply including msp3400 in the Makefile is no longer appropriate. This patch creates VIDEO_MSP3400, and alters VIDEO_BT848, VIDEO_PVRUSB2 and VIDEO_AUDIO_DECODER each to select VIDEO_MSP3400. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 15 +++++++++++++-- drivers/media/video/Makefile | 3 ++- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index ee0eed441a64..1a95a0eca7a9 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -26,6 +26,7 @@ config VIDEO_BT848 select VIDEO_IR select VIDEO_TUNER select VIDEO_TVEEPROM + select VIDEO_MSP3400 ---help--- Support for BT848 based frame grabber/overlay boards. This includes the Miro, Hauppauge and STB boards. Please read the material in @@ -344,9 +345,19 @@ config VIDEO_M32R_AR_M64278 config VIDEO_AUDIO_DECODER tristate "Add support for additional audio chipsets" depends on VIDEO_DEV && I2C && EXPERIMENTAL + select VIDEO_MSP3400 ---help--- - Say Y here to compile drivers for WM8775 and CS53L32A audio - decoders. + Say Y here to compile drivers for WM8775, CS53L32A and + MSP34xx audio decoders. + +config VIDEO_MSP3400 + tristate "Micronas MSP34xx audio decoders" + depends on VIDEO_DEV && I2C + ---help--- + Support for the Micronas MSP34xx series of audio decoders. + + To compile this driver as a module, choose M here: the + module will be called msp3400 config VIDEO_DECODER tristate "Add support for additional video chipsets" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 00080224f281..e42a25880781 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -15,7 +15,7 @@ msp3400-objs := msp3400-driver.o msp3400-kthreads.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o -obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \ +obj-$(CONFIG_VIDEO_BT848) += bttv.o tvaudio.o \ tda7432.o tda9875.o ir-kbd-i2c.o obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o @@ -45,6 +45,7 @@ obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ obj-$(CONFIG_VIDEO_EM28XX) += saa7115.o tvp5150.o +obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ -- cgit v1.2.3-59-g8ed1b From ac9ec9358e63878b105f48f5f094105dff7d9833 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 16 Mar 2006 02:53:14 -0300 Subject: V4L/DVB (3524): Kconfig: add menu items for saa7115 and saa7127 - created Kconfig menu item, VIDEO_SAA711X, for the saa7115 module, which supports SAA7113, SAA7114 and SAA7115 video decoders. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 20 ++++++++++++++++++++ drivers/media/video/Makefile | 5 +++-- drivers/media/video/em28xx/Kconfig | 1 + 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 1a95a0eca7a9..f50033e985e1 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -363,10 +363,30 @@ config VIDEO_DECODER tristate "Add support for additional video chipsets" depends on VIDEO_DEV && I2C && EXPERIMENTAL select VIDEO_CX25840 + select VIDEO_SAA711X + select VIDEO_SAA7127 ---help--- Say Y here to compile drivers for SAA7115, SAA7127 and CX25840 video decoders. source "drivers/media/video/cx25840/Kconfig" +config VIDEO_SAA711X + tristate "Philips SAA7113/4/5 video decoders" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + ---help--- + Support for the Philips SAA7113/4/5 video decoders. + + To compile this driver as a module, choose M here: the + module will be called saa7115 + +config VIDEO_SAA7127 + tristate "Philips SAA7127/9 digital video encoders" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + ---help--- + Support for the Philips SAA7127/9 digital video encoders. + + To compile this driver as a module, choose M here: the + module will be called saa7127 + endmenu diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index e42a25880781..67fc6d6bd81b 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -44,7 +44,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ -obj-$(CONFIG_VIDEO_EM28XX) += saa7115.o tvp5150.o +obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ @@ -63,7 +63,8 @@ obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o -obj-$(CONFIG_VIDEO_DECODER) += saa7115.o saa7127.o obj-$(CONFIG_VIDEO_CX25840) += cx25840/ +obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o +obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 885fd0170086..5a793ae7cc23 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -5,6 +5,7 @@ config VIDEO_EM28XX select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR + select VIDEO_SAA711X ---help--- This is a video4linux driver for Empia 28xx based TV cards. -- cgit v1.2.3-59-g8ed1b From baacb5bf47eb4066d5f715529d5e68b004ad574c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 16 Mar 2006 02:59:09 -0300 Subject: V4L/DVB (3525): Kconfig: remove VIDEO_DECODER - removed VIDEO_DECODER Kconfig menu item. VIDEO_CX25840, VIDEO_SAA711X and VIDEO_SAA7127 now each have their own menu items. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index f50033e985e1..2ae2c52718a7 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -359,16 +359,6 @@ config VIDEO_MSP3400 To compile this driver as a module, choose M here: the module will be called msp3400 -config VIDEO_DECODER - tristate "Add support for additional video chipsets" - depends on VIDEO_DEV && I2C && EXPERIMENTAL - select VIDEO_CX25840 - select VIDEO_SAA711X - select VIDEO_SAA7127 - ---help--- - Say Y here to compile drivers for SAA7115, SAA7127 and CX25840 - video decoders. - source "drivers/media/video/cx25840/Kconfig" config VIDEO_SAA711X -- cgit v1.2.3-59-g8ed1b From e690e14c9476aa46ec49ce8e24a591f786aa4766 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 16 Mar 2006 12:53:53 -0300 Subject: V4L/DVB (3527): VIDEO_CPIA2 must depend on USB CONFIG_VIDEO_CPIA2=y, CONFIG_USB=n results in the following compile <-- snip --> ... LD .tmp_vmlinux1 drivers/built-in.o: In function `set_alternate':cpia2_usb.c:(.text+0x443aa2): undefined reference to `usb_set_interface' drivers/built-in.o: In function `cpia2_usb_stream_resume': undefined reference to `usb_alloc_urb' drivers/built-in.o: In function `cpia2_usb_stream_resume': undefined reference to `usb_submit_urb' drivers/built-in.o: In function `cpia2_usb_stream_pause': undefined reference to `usb_kill_urb' drivers/built-in.o: In function `cpia2_usb_stream_pause': undefined reference to `usb_free_urb' drivers/built-in.o: In function `cpia2_usb_disconnect':cpia2_usb.c:(.text+0x443e14): undefined reference to `usb_driver_release_interface' drivers/built-in.o: In function `cpia2_usb_transfer_cmd': undefined reference to `usb_control_msg' drivers/built-in.o: In function `cpia2_usb_transfer_cmd': undefined reference to `usb_control_msg' drivers/built-in.o: In function `cpia2_usb_complete':cpia2_usb.c:(.text+0x444836): undefined reference to `usb_submit_urb' drivers/built-in.o: In function `cpia2_usb_cleanup': undefined reference to `usb_deregister' drivers/built-in.o: In function `cpia2_usb_init': undefined reference to `usb_register_driver' Signed-off-by: Adrian Bunk Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cpia2/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cpia2/Kconfig b/drivers/media/video/cpia2/Kconfig index 1c09ef981226..513cc0927389 100644 --- a/drivers/media/video/cpia2/Kconfig +++ b/drivers/media/video/cpia2/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CPIA2 tristate "CPiA2 Video For Linux" - depends on VIDEO_DEV + depends on VIDEO_DEV && USB ---help--- This is the video4linux driver for cameras based on Vision's CPiA2 (Colour Processor Interface ASIC), such as the Digital Blue QX5 -- cgit v1.2.3-59-g8ed1b From f5c08a2ee906381d85a6f0a3ca309fd56cf3b90f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 16 Mar 2006 13:18:25 -0300 Subject: V4L/DVB (3528): Kconfig: fix ATSC frontend menu item names by manufacturer - Corrected typo for NxtWave NXT200X - Added "Oren" manufacturer name to menu items for OR51132 and OR51211 - Removed "(pcHDTV HDx000 card)" from Oren frontends menu item names, This isn't necessary, as these frontends are selected by the card drivers, build configuration (DVB_BT8XX and VIDEO_CX88_DVB). Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index a1a894d81040..94233168d241 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -161,7 +161,7 @@ comment "ATSC (North American/Korean Terresterial DTV) frontends" depends on DVB_CORE config DVB_NXT200X - tristate "Nextwave NXT2002/NXT2004 based" + tristate "NxtWave Communications NXT2002/NXT2004 based" depends on DVB_CORE select FW_LOADER help @@ -175,14 +175,14 @@ config DVB_NXT200X or /lib/firmware (depending on configuration of firmware hotplug). config DVB_OR51211 - tristate "or51211 based (pcHDTV HD2000 card)" + tristate "Oren OR51211 based" depends on DVB_CORE select FW_LOADER help An ATSC 8VSB tuner module. Say Y when you want to support this frontend. config DVB_OR51132 - tristate "OR51132 based (pcHDTV HD3000 card)" + tristate "Oren OR51132 based" depends on DVB_CORE select FW_LOADER help -- cgit v1.2.3-59-g8ed1b From e273db7a99eabb4b2ba66dbaa90a63894cb2f2e3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 16 Mar 2006 14:48:38 -0300 Subject: V4L/DVB (3529): Kconfig: add menu items for cs53l32a and wm8775 A/D converters - created Kconfig item, VIDEO_CS53L32A, for the cs53l32a module which supports the Cirrus Logic CS53L32A Low Voltage Stereo A/D Converter. - created Kconfig item, VIDEO_WM8775, for the wm8775 module which supports the Wolfson Microelectronics WM8775 high performance stereo A/D Converter. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 22 ++++++++++++++++++++++ drivers/media/video/Makefile | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 2ae2c52718a7..9df669e70fd7 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -346,6 +346,8 @@ config VIDEO_AUDIO_DECODER tristate "Add support for additional audio chipsets" depends on VIDEO_DEV && I2C && EXPERIMENTAL select VIDEO_MSP3400 + select VIDEO_CS53L32A + select VIDEO_WM8775 ---help--- Say Y here to compile drivers for WM8775, CS53L32A and MSP34xx audio decoders. @@ -359,6 +361,26 @@ config VIDEO_MSP3400 To compile this driver as a module, choose M here: the module will be called msp3400 +config VIDEO_CS53L32A + tristate "Cirrus Logic CS53L32A audio ADC" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + ---help--- + Support for the Cirrus Logic CS53L32A low voltage + stereo A/D converter. + + To compile this driver as a module, choose M here: the + module will be called cs53l32a + +config VIDEO_WM8775 + tristate "Wolfson Microelectronics WM8775 audio ADC" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + ---help--- + Support for the Wolfson Microelectronics WM8775 + high performance stereo A/D Converter. + + To compile this driver as a module, choose M here: the + module will be called wm8775 + source "drivers/media/video/cx25840/Kconfig" config VIDEO_SAA711X diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 67fc6d6bd81b..f2bd4c0c4f10 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -46,7 +46,8 @@ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o -obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o +obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o +obj-$(CONFIG_VIDEO_WM8775) += wm8775.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ obj-$(CONFIG_VIDEO_MXB) += saa7111.o tda9840.o tea6415c.o tea6420.o mxb.o -- cgit v1.2.3-59-g8ed1b From ad5125913be0a723a2e17824ec688d4890bf978b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 16 Mar 2006 14:53:23 -0300 Subject: V4L/DVB (3530): Kconfig: remove VIDEO_AUDIO_DECODER - removed VIDEO_AUDIO_DECODER Kconfig menu item. VIDEO_MSP3400, VIDEO_CS53L32A and VIDEO_WM8775 now each have their own menu items. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 9df669e70fd7..c622a4da5663 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -342,16 +342,6 @@ config VIDEO_M32R_AR_M64278 Say Y here to use the Renesas M64278E-800 camera module, which supports VGA(640x480 pixcels) size of images. -config VIDEO_AUDIO_DECODER - tristate "Add support for additional audio chipsets" - depends on VIDEO_DEV && I2C && EXPERIMENTAL - select VIDEO_MSP3400 - select VIDEO_CS53L32A - select VIDEO_WM8775 - ---help--- - Say Y here to compile drivers for WM8775, CS53L32A and - MSP34xx audio decoders. - config VIDEO_MSP3400 tristate "Micronas MSP34xx audio decoders" depends on VIDEO_DEV && I2C -- cgit v1.2.3-59-g8ed1b From 265366e8fb8c31706711aea5f79d763816a968db Mon Sep 17 00:00:00 2001 From: Perceval Anichini Date: Thu, 16 Mar 2006 11:22:47 -0300 Subject: V4L/DVB (3532): Moved duplicated code of ALPS BSRU6 tuner to a standalone file. Moved duplicated code of ALPS BSRU6 tuner to a standalone file. Modified av7110 and budget drivers to include the new file. Signed-off-by: Perceval Anichini Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/bsru6.h | 140 +++++++++++++++++++++++++++++++++ drivers/media/dvb/ttpci/av7110.c | 104 +----------------------- drivers/media/dvb/ttpci/budget-ci.c | 118 +-------------------------- drivers/media/dvb/ttpci/budget-patch.c | 99 +---------------------- drivers/media/dvb/ttpci/budget.c | 98 +---------------------- 5 files changed, 145 insertions(+), 414 deletions(-) create mode 100644 drivers/media/dvb/frontends/bsru6.h (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/bsru6.h b/drivers/media/dvb/frontends/bsru6.h new file mode 100644 index 000000000000..2a5366ce79cc --- /dev/null +++ b/drivers/media/dvb/frontends/bsru6.h @@ -0,0 +1,140 @@ +/* + * bsru6.h - ALPS BSRU6 tuner support (moved from budget-ci.c) + * + * 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. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ + +#ifndef BSRU6_H +#define BSRU6_H + +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb9, + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; + +static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { + aclk = 0xb7; + bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; + bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; + bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; + bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; + bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; + bclk = 0x51; + } + + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, ratio & 0xf0); + + return 0; +} + +static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params) +{ + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + buf[3] = 0xC4; + + if (params->frequency > 1530000) + buf[3] = 0xc0; + + if (i2c_transfer(i2c, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct stv0299_config alps_bsru6_config = { + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; + +#endif diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 7497b1e8d883..5cf5b7d044ff 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -68,6 +68,7 @@ #include "bsbe1.h" #include "lnbp21.h" +#include "bsru6.h" #define TS_WIDTH 376 #define TS_HEIGHT 512 @@ -1570,109 +1571,6 @@ static struct ves1x93_config alps_bsrv2_config = { .pll_set = alps_bsrv2_pll_set, }; - -static u8 alps_bsru6_inittab[] = { - 0x01, 0x15, - 0x02, 0x30, - 0x03, 0x00, - 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ - 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ - 0x06, 0x40, /* DAC not used, set to high impendance mode */ - 0x07, 0x00, /* DAC LSB */ - 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ - 0x09, 0x00, /* FIFO */ - 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ - 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ - 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ - 0x10, 0x3f, // AGC2 0x3d - 0x11, 0x84, - 0x12, 0xb9, - 0x15, 0xc9, // lock detector threshold - 0x16, 0x00, - 0x17, 0x00, - 0x18, 0x00, - 0x19, 0x00, - 0x1a, 0x00, - 0x1f, 0x50, - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 - 0x29, 0x1e, // 1/2 threshold - 0x2a, 0x14, // 2/3 threshold - 0x2b, 0x0f, // 3/4 threshold - 0x2c, 0x09, // 5/6 threshold - 0x2d, 0x05, // 7/8 threshold - 0x2e, 0x01, - 0x31, 0x1f, // test all FECs - 0x32, 0x19, // viterbi and synchro search - 0x33, 0xfc, // rs control - 0x34, 0x93, // error control - 0x0f, 0x52, - 0xff, 0xff -}; - -static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) -{ - u8 aclk = 0; - u8 bclk = 0; - - if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } - else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } - else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } - else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } - else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } - else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } - - stv0299_writereg(fe, 0x13, aclk); - stv0299_writereg(fe, 0x14, bclk); - stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg(fe, 0x21, (ratio ) & 0xf0); - - return 0; -} - -static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) -{ - int ret; - u8 data[4]; - u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) - return -EINVAL; - - div = (params->frequency + (125 - 1)) / 125; // round correctly - data[0] = (div >> 8) & 0x7f; - data[1] = div & 0xff; - data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; - data[3] = 0xC4; - - if (params->frequency > 1530000) data[3] = 0xc0; - - ret = i2c_transfer(i2c, &msg, 1); - if (ret != 1) - return -EIO; - return 0; -} - -static struct stv0299_config alps_bsru6_config = { - - .demod_address = 0x68, - .inittab = alps_bsru6_inittab, - .mclk = 88000000UL, - .invert = 1, - .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, - .volt13_op0_op1 = STV0299_VOLT13_OP1, - .min_delay_ms = 100, - .set_symbol_rate = alps_bsru6_set_symbol_rate, - .pll_set = alps_bsru6_pll_set, -}; - - static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct av7110* av7110 = fe->dvb->priv; diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 09b972b9ffe3..5f91036f5b87 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -44,6 +44,7 @@ #include "tda1004x.h" #include "lnbp21.h" #include "bsbe1.h" +#include "bsru6.h" #define DEBIADDR_IR 0x1234 #define DEBIADDR_CICONTROL 0x0000 @@ -476,123 +477,6 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) tasklet_schedule(&budget_ci->ciintf_irq_tasklet); } - -static u8 alps_bsru6_inittab[] = { - 0x01, 0x15, - 0x02, 0x00, - 0x03, 0x00, - 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ - 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ - 0x06, 0x40, /* DAC not used, set to high impendance mode */ - 0x07, 0x00, /* DAC LSB */ - 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ - 0x09, 0x00, /* FIFO */ - 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ - 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ - 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ - 0x10, 0x3f, // AGC2 0x3d - 0x11, 0x84, - 0x12, 0xb9, - 0x15, 0xc9, // lock detector threshold - 0x16, 0x00, - 0x17, 0x00, - 0x18, 0x00, - 0x19, 0x00, - 0x1a, 0x00, - 0x1f, 0x50, - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 - 0x29, 0x1e, // 1/2 threshold - 0x2a, 0x14, // 2/3 threshold - 0x2b, 0x0f, // 3/4 threshold - 0x2c, 0x09, // 5/6 threshold - 0x2d, 0x05, // 7/8 threshold - 0x2e, 0x01, - 0x31, 0x1f, // test all FECs - 0x32, 0x19, // viterbi and synchro search - 0x33, 0xfc, // rs control - 0x34, 0x93, // error control - 0x0f, 0x52, - 0xff, 0xff -}; - -static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) -{ - u8 aclk = 0; - u8 bclk = 0; - - if (srate < 1500000) { - aclk = 0xb7; - bclk = 0x47; - } else if (srate < 3000000) { - aclk = 0xb7; - bclk = 0x4b; - } else if (srate < 7000000) { - aclk = 0xb7; - bclk = 0x4f; - } else if (srate < 14000000) { - aclk = 0xb7; - bclk = 0x53; - } else if (srate < 30000000) { - aclk = 0xb6; - bclk = 0x53; - } else if (srate < 45000000) { - aclk = 0xb4; - bclk = 0x51; - } - - stv0299_writereg(fe, 0x13, aclk); - stv0299_writereg(fe, 0x14, bclk); - stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg(fe, 0x21, (ratio) & 0xf0); - - return 0; -} - -static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params) -{ - u8 buf[4]; - u32 div; - struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) - return -EINVAL; - - div = (params->frequency + (125 - 1)) / 125; // round correctly - buf[0] = (div >> 8) & 0x7f; - buf[1] = div & 0xff; - buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; - buf[3] = 0xC4; - - if (params->frequency > 1530000) - buf[3] = 0xc0; - - if (i2c_transfer(i2c, &msg, 1) != 1) - return -EIO; - return 0; -} - -static struct stv0299_config alps_bsru6_config = { - - .demod_address = 0x68, - .inittab = alps_bsru6_inittab, - .mclk = 88000000UL, - .invert = 1, - .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, - .volt13_op0_op1 = STV0299_VOLT13_OP1, - .min_delay_ms = 100, - .set_symbol_rate = alps_bsru6_set_symbol_rate, - .pll_set = alps_bsru6_pll_set, -}; - - - - static u8 philips_su1278_tt_inittab[] = { 0x01, 0x0f, 0x02, 0x30, diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index fc416cf5253c..9fc9185a8426 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -37,6 +37,8 @@ #include "ves1x93.h" #include "tda8083.h" +#include "bsru6.h" + #define budget_patch budget static struct saa7146_extension budget_extension; @@ -290,103 +292,6 @@ static struct ves1x93_config alps_bsrv2_config = { .pll_set = alps_bsrv2_pll_set, }; -static u8 alps_bsru6_inittab[] = { - 0x01, 0x15, - 0x02, 0x00, - 0x03, 0x00, - 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ - 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ - 0x06, 0x40, /* DAC not used, set to high impendance mode */ - 0x07, 0x00, /* DAC LSB */ - 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ - 0x09, 0x00, /* FIFO */ - 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ - 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ - 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ - 0x10, 0x3f, // AGC2 0x3d - 0x11, 0x84, - 0x12, 0xb9, - 0x15, 0xc9, // lock detector threshold - 0x16, 0x00, - 0x17, 0x00, - 0x18, 0x00, - 0x19, 0x00, - 0x1a, 0x00, - 0x1f, 0x50, - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 - 0x29, 0x1e, // 1/2 threshold - 0x2a, 0x14, // 2/3 threshold - 0x2b, 0x0f, // 3/4 threshold - 0x2c, 0x09, // 5/6 threshold - 0x2d, 0x05, // 7/8 threshold - 0x2e, 0x01, - 0x31, 0x1f, // test all FECs - 0x32, 0x19, // viterbi and synchro search - 0x33, 0xfc, // rs control - 0x34, 0x93, // error control - 0x0f, 0x52, - 0xff, 0xff -}; - -static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) -{ - u8 aclk = 0; - u8 bclk = 0; - - if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } - else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } - else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } - else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } - else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } - else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } - - stv0299_writereg (fe, 0x13, aclk); - stv0299_writereg (fe, 0x14, bclk); - stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); - - return 0; -} - -static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) -{ - u8 data[4]; - u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; - - div = (params->frequency + (125 - 1)) / 125; // round correctly - data[0] = (div >> 8) & 0x7f; - data[1] = div & 0xff; - data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; - data[3] = 0xC4; - - if (params->frequency > 1530000) data[3] = 0xc0; - - if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO; - return 0; -} - -static struct stv0299_config alps_bsru6_config = { - - .demod_address = 0x68, - .inittab = alps_bsru6_inittab, - .mclk = 88000000UL, - .invert = 1, - .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, - .volt13_op0_op1 = STV0299_VOLT13_OP1, - .min_delay_ms = 100, - .set_symbol_rate = alps_bsru6_set_symbol_rate, - .pll_set = alps_bsru6_pll_set, -}; - static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index bfb80925019a..c23c02d95641 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -42,6 +42,7 @@ #include "tda8083.h" #include "s5h1420.h" #include "lnbp21.h" +#include "bsru6.h" static void Set22K (struct budget *budget, int state) { @@ -220,103 +221,6 @@ static struct ves1x93_config alps_bsrv2_config = .pll_set = alps_bsrv2_pll_set, }; -static u8 alps_bsru6_inittab[] = { - 0x01, 0x15, - 0x02, 0x00, - 0x03, 0x00, - 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ - 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ - 0x06, 0x40, /* DAC not used, set to high impendance mode */ - 0x07, 0x00, /* DAC LSB */ - 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ - 0x09, 0x00, /* FIFO */ - 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ - 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ - 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ - 0x10, 0x3f, // AGC2 0x3d - 0x11, 0x84, - 0x12, 0xb9, - 0x15, 0xc9, // lock detector threshold - 0x16, 0x00, - 0x17, 0x00, - 0x18, 0x00, - 0x19, 0x00, - 0x1a, 0x00, - 0x1f, 0x50, - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 - 0x29, 0x1e, // 1/2 threshold - 0x2a, 0x14, // 2/3 threshold - 0x2b, 0x0f, // 3/4 threshold - 0x2c, 0x09, // 5/6 threshold - 0x2d, 0x05, // 7/8 threshold - 0x2e, 0x01, - 0x31, 0x1f, // test all FECs - 0x32, 0x19, // viterbi and synchro search - 0x33, 0xfc, // rs control - 0x34, 0x93, // error control - 0x0f, 0x52, - 0xff, 0xff -}; - -static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) -{ - u8 aclk = 0; - u8 bclk = 0; - - if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } - else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } - else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } - else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } - else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } - else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } - - stv0299_writereg (fe, 0x13, aclk); - stv0299_writereg (fe, 0x14, bclk); - stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); - - return 0; -} - -static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) -{ - u8 data[4]; - u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; - - div = (params->frequency + (125 - 1)) / 125; // round correctly - data[0] = (div >> 8) & 0x7f; - data[1] = div & 0xff; - data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; - data[3] = 0xC4; - - if (params->frequency > 1530000) data[3] = 0xc0; - - if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO; - return 0; -} - -static struct stv0299_config alps_bsru6_config = { - - .demod_address = 0x68, - .inittab = alps_bsru6_inittab, - .mclk = 88000000UL, - .invert = 1, - .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, - .volt13_op0_op1 = STV0299_VOLT13_OP1, - .min_delay_ms = 100, - .set_symbol_rate = alps_bsru6_set_symbol_rate, - .pll_set = alps_bsru6_pll_set, -}; - static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; -- cgit v1.2.3-59-g8ed1b From 4caba4261f2649215710ac0298bd7814080000ad Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Fri, 17 Mar 2006 05:29:15 -0300 Subject: V4L/DVB (3533): Add WSS (wide screen signalling) module parameters Add wss_cfg_4_3 and wss_cfg_16_9 configuration options. Firmware 2623 or later required. Both parameters are bit masks: - bit 15: disable WSS - bit 14: send short WSS burst, then turn off WSS - bit 13..0: WSS bits as specified by the standard These parameters are useful if you own a broken tv set which does not handle wss correctly. Default settings: - wss_cfg_4_3: 0x4008 - wss_cfg_16_9: 0x0007 These should work with most devices. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110.c | 13 +++++++++++++ drivers/media/dvb/ttpci/av7110_v4l.c | 11 ++++------- 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 5cf5b7d044ff..840efec32cb6 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -85,6 +85,8 @@ static int hw_sections; static int rgb_on; static int volume = 255; static int budgetpatch; +static int wss_cfg_4_3 = 0x4008; +static int wss_cfg_16_9 = 0x0007; module_param_named(debug, av7110_debug, int, 0644); MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)"); @@ -103,6 +105,10 @@ module_param(volume, int, 0444); MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)"); module_param(budgetpatch, int, 0444); MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)"); +module_param(wss_cfg_4_3, int, 0444); +MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data"); +module_param(wss_cfg_16_9, int, 0444); +MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data"); static void restart_feeds(struct av7110 *av7110); @@ -128,6 +134,13 @@ static void init_av7110_av(struct av7110 *av7110) if (ret < 0) printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret); + ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3); + if (ret < 0) + printk("dvb-ttpci: unable to configure 4:3 wss\n"); + ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9); + if (ret < 0) + printk("dvb-ttpci: unable to configure 16:9 wss\n"); + ret = av7710_set_video_mode(av7110, vidmode); if (ret < 0) printk("dvb-ttpci:cannot set video mode:%d\n",ret); diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index 94cf38c7e8a8..2f23ceab8d44 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c @@ -579,14 +579,11 @@ static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size return -EFAULT; if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23) return -EINVAL; - if (d.id) { + if (d.id) av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0]; - rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, - 2, 1, av7110->wssData); - } else { - av7110->wssData = 0; - rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0); - } + else + av7110->wssData = 0x8000; + rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 1, av7110->wssData); return (rc < 0) ? rc : count; } -- cgit v1.2.3-59-g8ed1b From a8733ca5141c256322ab5ea9fd3074942a209bba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 17 Mar 2006 10:37:02 -0300 Subject: V4L/DVB (3537a): Whitespace cleanup Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/dpc7146.c | 58 +++++++------- drivers/media/video/hexium_gemini.c | 10 +-- drivers/media/video/hexium_orion.c | 18 ++--- drivers/media/video/mxb.c | 146 ++++++++++++++++++------------------ drivers/media/video/mxb.h | 2 +- drivers/media/video/tda9840.c | 3 +- drivers/media/video/tea6415c.c | 5 +- drivers/media/video/tea6420.c | 5 +- 8 files changed, 125 insertions(+), 122 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c index 2831bdd12057..0fcc935828f8 100644 --- a/drivers/media/video/dpc7146.c +++ b/drivers/media/video/dpc7146.c @@ -1,6 +1,6 @@ /* dpc7146.c - v4l2 driver for the dpc7146 demonstration board - + Copyright (C) 2000-2003 Michael Hunold This program is free software; you can redistribute it and/or modify @@ -52,7 +52,7 @@ #define SAA711X_DECODED_BYTES_OF_TS_2 0x1C #define SAA711X_STATUS_BYTE 0x1F -#define DPC_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) +#define DPC_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) static int debug = 0; module_param(debug, int, 0); @@ -81,16 +81,16 @@ struct dpc struct video_device *video_dev; struct video_device *vbi_dev; - struct i2c_adapter i2c_adapter; + struct i2c_adapter i2c_adapter; struct i2c_client *saa7111a; - + int cur_input; /* current input */ }; /* fixme: add vbi stuff here */ static int dpc_probe(struct saa7146_dev* dev) { - struct dpc* dpc = NULL; + struct dpc* dpc = NULL; struct i2c_client *client; struct list_head *item; @@ -118,20 +118,20 @@ static int dpc_probe(struct saa7146_dev* dev) /* loop through all i2c-devices on the bus and look who is there */ list_for_each(item,&dpc->i2c_adapter.clients) { client = list_entry(item, struct i2c_client, list); - if( I2C_SAA7111A == client->addr ) + if( I2C_SAA7111A == client->addr ) dpc->saa7111a = client; } /* check if all devices are present */ if( 0 == dpc->saa7111a ) { - DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n")); + DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n")); i2c_del_adapter(&dpc->i2c_adapter); kfree(dpc); return -ENODEV; } - - /* all devices are present, probe was successful */ - DEB_D(("dpc_v4l2.o: dpc_probe succeeded for this device.\n")); + + /* all devices are present, probe was successful */ + DEB_D(("dpc_v4l2.o: dpc_probe succeeded for this device.\n")); /* we store the pointer in our private data field */ dev->ext_priv = dpc; @@ -182,7 +182,7 @@ static struct saa7146_ext_vv vv_data; static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { struct dpc* dpc = (struct dpc*)dev->ext_priv; - + DEB_D(("dpc_v4l2.o: dpc_attach called.\n")); /* checking for i2c-devices can be omitted here, because we @@ -193,7 +193,7 @@ static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data ERR(("cannot register capture v4l2 device. skipping.\n")); return -1; } - + /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) { if( 0 != saa7146_register_device(&dpc->vbi_dev, dev, "dpc", VFL_TYPE_VBI)) { @@ -205,18 +205,18 @@ static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data printk("dpc: found 'dpc7146 demonstration board'-%d.\n",dpc_num); dpc_num++; - + /* the rest */ dpc->cur_input = 0; dpc_init_done(dev); - + return 0; } static int dpc_detach(struct saa7146_dev* dev) { struct dpc* dpc = (struct dpc*)dev->ext_priv; - + DEB_EE(("dev:%p\n",dev)); i2c_release_client(dpc->saa7111a); @@ -238,25 +238,25 @@ static int dpc_detach(struct saa7146_dev* dev) int dpc_vbi_bypass(struct saa7146_dev* dev) { struct dpc* dpc = (struct dpc*)dev->ext_priv; - + int i = 1; /* switch bypass in saa7111a */ if ( 0 != dpc->saa7111a->driver->command(dpc->saa7111a,SAA711X_VBI_BYPASS, &i)) { printk("dpc_v4l2.o: VBI_BYPASS: could not address saa7111a.\n"); return -1; - } + } return 0; } #endif -static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; struct dpc* dpc = (struct dpc*)dev->ext_priv; /* - struct saa7146_vv *vv = dev->vv_data; + struct saa7146_vv *vv = dev->vv_data; */ switch(cmd) { @@ -264,11 +264,11 @@ static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct v4l2_input *i = arg; DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); - + if( i->index < 0 || i->index >= DPC_INPUTS) { return -EINVAL; } - + memcpy(i, &dpc_inputs[i->index], sizeof(struct v4l2_input)); DEB_D(("dpc_v4l2.o: v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n",i->index)); @@ -289,13 +289,13 @@ static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) if (input < 0 || input >= DPC_INPUTS) { return -EINVAL; } - + dpc->cur_input = input; /* fixme: switch input here, switch audio, too! */ // saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); printk("dpc_v4l2.o: VIDIOC_S_INPUT: fixme switch input.\n"); - + return 0; } default: @@ -334,8 +334,8 @@ static struct saa7146_standard standard[] = { static struct saa7146_extension extension; static struct saa7146_pci_extension_data dpc = { - .ext_priv = "Multimedia eXtension Board", - .ext = &extension, + .ext_priv = "Multimedia eXtension Board", + .ext = &extension, }; static struct pci_device_id pci_tbl[] = { @@ -357,7 +357,7 @@ static struct saa7146_ext_vv vv_data = { .capabilities = V4L2_CAP_VBI_CAPTURE, .stds = &standard[0], .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), - .std_callback = &std_callback, + .std_callback = &std_callback, .ioctls = &ioctls[0], .ioctl = dpc_ioctl, }; @@ -365,7 +365,7 @@ static struct saa7146_ext_vv vv_data = { static struct saa7146_extension extension = { .name = "dpc7146 demonstration board", .flags = SAA7146_USE_I2C_IRQ, - + .pci_tbl = &pci_tbl[0], .module = THIS_MODULE, @@ -375,7 +375,7 @@ static struct saa7146_extension extension = { .irq_mask = 0, .irq_func = NULL, -}; +}; static int __init dpc_init_module(void) { @@ -383,7 +383,7 @@ static int __init dpc_init_module(void) DEB_S(("failed to register extension.\n")); return -ENODEV; } - + return 0; } diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index e7bbeb11553d..c7fed3405655 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -1,9 +1,9 @@ /* hexium_gemini.c - v4l2 driver for Hexium Gemini frame grabber cards - + Visit http://www.mihu.de/linux/saa7146/ and follow the link to "hexium" for further details about this card. - + Copyright (C) 2003 Michael Hunold This program is free software; you can redistribute it and/or modify @@ -81,7 +81,7 @@ struct hexium struct video_device *video_dev; struct i2c_adapter i2c_adapter; - + int cur_input; /* current input */ v4l2_std_id cur_std; /* current standard */ int cur_bw; /* current black/white status */ @@ -174,7 +174,7 @@ static struct saa7146_standard hexium_standards[] = { .h_offset = 1, .h_pixels = 720, .v_max_out = 576, .h_max_out = 768, } -}; +}; /* bring hardware to a sane state. this has to be done, just in case someone wants to capture from this device before it has been properly initialized. @@ -311,7 +311,7 @@ static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) struct saa7146_dev *dev = fh->dev; struct hexium *hexium = (struct hexium *) dev->ext_priv; /* - struct saa7146_vv *vv = dev->vv_data; + struct saa7146_vv *vv = dev->vv_data; */ switch (cmd) { case VIDIOC_ENUMINPUT: diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index aad4a18aafd6..137c4736da04 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -3,7 +3,7 @@ Visit http://www.mihu.de/linux/saa7146/ and follow the link to "hexium" for further details about this card. - + Copyright (C) 2003 Michael Hunold This program is free software; you can redistribute it and/or modify @@ -69,7 +69,7 @@ struct hexium { int type; struct video_device *video_dev; - struct i2c_adapter i2c_adapter; + struct i2c_adapter i2c_adapter; int cur_input; /* current input */ }; @@ -86,7 +86,7 @@ static u8 hexium_saa7110[53]={ }; static struct { - struct hexium_data data[8]; + struct hexium_data data[8]; } hexium_input_select[] = { { { /* cvbs 1 */ @@ -153,7 +153,7 @@ static struct { { 0x30, 0x60 }, { 0x31, 0xB5 }, // ?? { 0x21, 0x03 }, - } + } }, { { /* y/c 1 */ { 0x06, 0x80 }, @@ -187,7 +187,7 @@ static struct { { 0x31, 0x75 }, { 0x21, 0x21 }, } -} +} }; static struct saa7146_standard hexium_standards[] = { @@ -207,7 +207,7 @@ static struct saa7146_standard hexium_standards[] = { .h_offset = 1, .h_pixels = 720, .v_max_out = 576, .h_max_out = 768, } -}; +}; /* this is only called for old HV-PCI6/Orion cards without eeprom */ @@ -272,7 +272,7 @@ static int hexium_probe(struct saa7146_dev *dev) return 0; } - /* check if this is an old hexium Orion card by looking at + /* check if this is an old hexium Orion card by looking at a saa7110 at address 0x4e */ if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) { printk("hexium_orion: device is a Hexium HV-PCI6/Orion (old).\n"); @@ -314,7 +314,7 @@ static int hexium_set_input(struct hexium *hexium, int input) { union i2c_smbus_data data; int i = 0; - + DEB_D((".\n")); for (i = 0; i < 8; i++) { @@ -375,7 +375,7 @@ static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) struct saa7146_dev *dev = fh->dev; struct hexium *hexium = (struct hexium *) dev->ext_priv; /* - struct saa7146_vv *vv = dev->vv_data; + struct saa7146_vv *vv = dev->vv_data; */ switch (cmd) { case VIDIOC_ENUMINPUT: diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 2f154f415bca..eb3b31867494 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -1,11 +1,11 @@ /* mxb - v4l2 driver for the Multimedia eXtension Board - + Copyright (C) 1998-2006 Michael Hunold Visit http://www.mihu.de/linux/saa7146/mxb/ for further details about this card. - + 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 @@ -35,12 +35,12 @@ #define I2C_SAA7111 0x24 -#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) +#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) /* global variable */ static int mxb_num = 0; -/* initial frequence the tuner will be tuned to. +/* initial frequence the tuner will be tuned to. in verden (lower saxony, germany) 4148 is a channel called "phoenix" */ static int freq = 4148; @@ -55,7 +55,7 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); enum { TUNER, AUX1, AUX3, AUX3_YC }; static struct v4l2_input mxb_inputs[MXB_INPUTS] = { - { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, @@ -66,7 +66,7 @@ static struct v4l2_input mxb_inputs[MXB_INPUTS] = { static struct { int hps_source; int hps_sync; -} input_port_selection[MXB_INPUTS] = { +} input_port_selection[MXB_INPUTS] = { { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A }, { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A }, { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A }, @@ -81,7 +81,7 @@ static int video_audio_connect[MXB_INPUTS] = /* these are the necessary input-output-pins for bringing one audio source (see above) to the CD-output */ static struct tea6420_multiplex TEA6420_cd[MXB_AUDIOS+1][2] = - { + { {{1,1,0},{1,1,0}}, /* Tuner */ {{5,1,0},{6,1,0}}, /* AUX 1 */ {{4,1,0},{6,1,0}}, /* AUX 2 */ @@ -122,8 +122,8 @@ static struct saa7146_extension_ioctls ioctls[] = { { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE }, { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE }, { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE }, - { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */ - { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */ + { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */ + { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */ { 0, 0 } }; @@ -132,7 +132,7 @@ struct mxb struct video_device *video_dev; struct video_device *vbi_dev; - struct i2c_adapter i2c_adapter; + struct i2c_adapter i2c_adapter; struct i2c_client* saa7111a; struct i2c_client* tda9840; @@ -200,15 +200,15 @@ static int mxb_probe(struct saa7146_dev* dev) client = list_entry(item, struct i2c_client, list); if( I2C_TEA6420_1 == client->addr ) mxb->tea6420_1 = client; - if( I2C_TEA6420_2 == client->addr ) + if( I2C_TEA6420_2 == client->addr ) mxb->tea6420_2 = client; - if( I2C_TEA6415C_2 == client->addr ) + if( I2C_TEA6415C_2 == client->addr ) mxb->tea6415c = client; - if( I2C_TDA9840 == client->addr ) + if( I2C_TDA9840 == client->addr ) mxb->tda9840 = client; if( I2C_SAA7111 == client->addr ) mxb->saa7111a = client; - if( 0x60 == client->addr ) + if( 0x60 == client->addr ) mxb->tuner = client; } @@ -222,7 +222,7 @@ static int mxb_probe(struct saa7146_dev* dev) return -ENODEV; } - /* all devices are present, probe was successful */ + /* all devices are present, probe was successful */ /* we store the pointer in our private data field */ dev->ext_priv = mxb; @@ -230,7 +230,7 @@ static int mxb_probe(struct saa7146_dev* dev) return 0; } -/* some init data for the saa7740, the so-called 'sound arena module'. +/* some init data for the saa7740, the so-called 'sound arena module'. there are no specs available, so we simply use some init values */ static struct { int length; @@ -330,7 +330,7 @@ static int mxb_init_done(struct saa7146_dev* dev) v4l2_std_id std = V4L2_STD_PAL_BG; int i = 0, err = 0; - struct tea6415c_multiplex vm; + struct tea6415c_multiplex vm; /* select video mode in saa7111a */ i = VIDEO_MODE_PAL; @@ -380,16 +380,16 @@ static int mxb_init_done(struct saa7146_dev* dev) vm.in = 3; vm.out = 13; mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm); - + /* the rest for mxb */ mxb->cur_input = 0; mxb->cur_mute = 1; mxb->cur_mode = V4L2_TUNER_MODE_STEREO; mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode); - + /* check if the saa7740 (aka 'sound arena module') is present - on the mxb. if so, we must initialize it. due to lack of + on the mxb. if so, we must initialize it. due to lack of informations about the saa7740, the values were reverse engineered. */ msg.addr = 0x1b; @@ -409,7 +409,7 @@ static int mxb_init_done(struct saa7146_dev* dev) break; } - msg.len = mxb_saa7740_init[i].length; + msg.len = mxb_saa7740_init[i].length; msg.buf = &mxb_saa7740_init[i].data[0]; if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) { DEB_D(("failed to initialize 'sound arena module'.\n")); @@ -418,12 +418,12 @@ static int mxb_init_done(struct saa7146_dev* dev) } INFO(("'sound arena module' detected.\n")); } -err: +err: /* the rest for saa7146: you should definitely set some basic values for the input-port handling of the saa7146. */ /* ext->saa has been filled by the core driver */ - + /* some stuff is done via variables */ saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, input_port_selection[mxb->cur_input].hps_sync); @@ -431,7 +431,7 @@ err: /* this is ugly, but because of the fact that this is completely hardware dependend, it should be done directly... */ - saa7146_write(dev, DD1_STREAM_B, 0x00000000); + saa7146_write(dev, DD1_STREAM_B, 0x00000000); saa7146_write(dev, DD1_INIT, 0x02000200); saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); @@ -453,7 +453,7 @@ static struct saa7146_ext_vv vv_data; static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { struct mxb* mxb = (struct mxb*)dev->ext_priv; - + DEB_EE(("dev:%p\n",dev)); /* checking for i2c-devices can be omitted here, because we @@ -464,7 +464,7 @@ static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data ERR(("cannot register capture v4l2 device. skipping.\n")); return -1; } - + /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { @@ -513,17 +513,17 @@ static int mxb_detach(struct saa7146_dev* dev) return 0; } -static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; struct mxb* mxb = (struct mxb*)dev->ext_priv; - struct saa7146_vv *vv = dev->vv_data; - + struct saa7146_vv *vv = dev->vv_data; + switch(cmd) { case VIDIOC_ENUMINPUT: { struct v4l2_input *i = arg; - + DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); if( i->index < 0 || i->index >= MXB_INPUTS) { return -EINVAL; @@ -559,11 +559,11 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) break; } } - + if( i < 0 ) { return -EAGAIN; } - + switch (vc->id ) { case V4L2_CID_AUDIO_MUTE: { vc->value = mxb->cur_mute; @@ -571,7 +571,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) return 0; } } - + DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value)); return 0; } @@ -580,17 +580,17 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct v4l2_control *vc = arg; int i = 0; - + for (i = MAXCONTROLS - 1; i >= 0; i--) { if (mxb_controls[i].id == vc->id) { break; } } - + if( i < 0 ) { return -EAGAIN; } - + switch (vc->id ) { case V4L2_CID_AUDIO_MUTE: { mxb->cur_mute = vc->value; @@ -614,12 +614,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) *input = mxb->cur_input; DEB_EE(("VIDIOC_G_INPUT %d.\n",*input)); - return 0; - } + return 0; + } case VIDIOC_S_INPUT: { int input = *(int *)arg; - struct tea6415c_multiplex vm; + struct tea6415c_multiplex vm; int i = 0; DEB_EE(("VIDIOC_S_INPUT %d.\n",input)); @@ -627,34 +627,34 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) if (input < 0 || input >= MXB_INPUTS) { return -EINVAL; } - + /* fixme: locke das setzen des inputs mit hilfe des mutexes mutex_lock(&dev->lock); video_mux(dev,*i); mutex_unlock(&dev->lock); */ - + /* fixme: check if streaming capture if ( 0 != dev->streaming ) { DEB_D(("VIDIOC_S_INPUT illegal while streaming.\n")); return -EPERM; } */ - + mxb->cur_input = input; - + saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); - + /* prepare switching of tea6415c and saa7111a; have a look at the 'background'-file for further informations */ switch( input ) { - + case TUNER: { i = 0; vm.in = 3; vm.out = 17; - + if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) { printk("VIDIOC_S_INPUT: could not address tea6415c #1\n"); return -EFAULT; @@ -662,7 +662,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) /* connect tuner-output always to multicable */ vm.in = 3; vm.out = 13; - break; + break; } case AUX3_YC: { @@ -703,11 +703,11 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) break; } } - + /* switch video in saa7111a */ if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) { printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n"); - } + } /* switch the audio-source only if necessary */ if( 0 == mxb->cur_mute ) { @@ -738,11 +738,11 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */ /* FIXME: add the real signal strength here */ t->signal = 0xffff; - t->afc = 0; + t->afc = 0; mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, &byte); t->audmode = mxb->cur_mode; - + if( byte < 0 ) { t->rxsubchans = V4L2_TUNER_SUB_MONO; } else { @@ -777,12 +777,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) struct v4l2_tuner *t = arg; int result = 0; int byte = 0; - + if( 0 != t->index ) { DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index)); return -EINVAL; } - + switch(t->audmode) { case V4L2_TUNER_MODE_STEREO: { mxb->cur_mode = V4L2_TUNER_MODE_STEREO; @@ -813,7 +813,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) { printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte); } - + return 0; } case VIDIOC_G_FREQUENCY: @@ -839,7 +839,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) if (V4L2_TUNER_ANALOG_TV != f->type) return -EINVAL; - + if(0 != mxb->cur_input) { DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input)); return -EINVAL; @@ -848,7 +848,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) mxb->cur_freq = *f; DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency)); - /* tune in desired frequency */ + /* tune in desired frequency */ mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq); /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ @@ -861,12 +861,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) case MXB_S_AUDIO_CD: { int i = *(int*)arg; - + if( i < 0 || i >= MXB_AUDIOS ) { DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i)); return -EINVAL; } - + DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n",i)); mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[i][0]); @@ -877,12 +877,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) case MXB_S_AUDIO_LINE: { int i = *(int*)arg; - + if( i < 0 || i >= MXB_AUDIOS ) { DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i)); return -EINVAL; } - + DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n",i)); mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[i][0]); mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[i][1]); @@ -894,13 +894,13 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) struct v4l2_audio *a = arg; if( a->index < 0 || a->index > MXB_INPUTS ) { - DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index)); + DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index)); return -EINVAL; } - - DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index)); + + DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index)); memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio)); - + return 0; } case VIDIOC_S_AUDIO: @@ -908,7 +908,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) struct v4l2_audio *a = arg; DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index)); return 0; - } + } default: /* DEB2(printk("does not handle this ioctl.\n")); @@ -928,7 +928,7 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) v4l2_std_id std = V4L2_STD_PAL_I; DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ - saa7146_write(dev, GPIO_CTRL, 0x00404050); + saa7146_write(dev, GPIO_CTRL, 0x00404050); /* unset the 7111 gpio register -- I don't know what this does exactly */ mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero); mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); @@ -936,7 +936,7 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) v4l2_std_id std = V4L2_STD_PAL_BG; DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ - saa7146_write(dev, GPIO_CTRL, 0x00404050); + saa7146_write(dev, GPIO_CTRL, 0x00404050); /* set the 7111 gpio register -- I don't know what this does exactly */ mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one); mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); @@ -969,8 +969,8 @@ static struct saa7146_standard standard[] = { }; static struct saa7146_pci_extension_data mxb = { - .ext_priv = "Multimedia eXtension Board", - .ext = &extension, + .ext_priv = "Multimedia eXtension Board", + .ext = &extension, }; static struct pci_device_id pci_tbl[] = { @@ -992,7 +992,7 @@ static struct saa7146_ext_vv vv_data = { .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, .stds = &standard[0], .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), - .std_callback = &std_callback, + .std_callback = &std_callback, .ioctls = &ioctls[0], .ioctl = mxb_ioctl, }; @@ -1000,7 +1000,7 @@ static struct saa7146_ext_vv vv_data = { static struct saa7146_extension extension = { .name = MXB_IDENTIFIER, .flags = SAA7146_USE_I2C_IRQ, - + .pci_tbl = &pci_tbl[0], .module = THIS_MODULE, @@ -1010,7 +1010,7 @@ static struct saa7146_extension extension = { .irq_mask = 0, .irq_func = NULL, -}; +}; static int __init mxb_init_module(void) { @@ -1018,7 +1018,7 @@ static int __init mxb_init_module(void) DEB_S(("failed to register extension.\n")); return -ENODEV; } - + return 0; } diff --git a/drivers/media/video/mxb.h b/drivers/media/video/mxb.h index 2332ed5f7c6b..400a57ba62ec 100644 --- a/drivers/media/video/mxb.h +++ b/drivers/media/video/mxb.h @@ -38,5 +38,5 @@ static struct v4l2_audio mxb_audios[MXB_AUDIOS] = { .name = "CD-ROM (X10)", .capability = V4L2_AUDCAP_STEREO, } -}; +}; #endif diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index ed4c04119ccc..0243700f58ae 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include @@ -222,7 +223,7 @@ static int detach(struct i2c_client *client) static struct i2c_driver driver = { .driver = { - .name = "tda9840", + .name = "tda9840", }, .id = I2C_DRIVERID_TDA9840, .attach_adapter = attach, diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index bb35844e3842..774ed0dbc56d 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -26,6 +26,7 @@ Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA. */ + #include #include #include @@ -107,7 +108,7 @@ static int switch_matrix(struct i2c_client *client, int i, int o) { u8 byte = 0; int ret; - + dprintk("adr:0x%02x, i:%d, o:%d\n", client->addr, i, o); /* check if the pins are valid */ @@ -191,7 +192,7 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) static struct i2c_driver driver = { .driver = { - .name = "tea6415c", + .name = "tea6415c", }, .id = I2C_DRIVERID_TEA6415C, .attach_adapter = attach, diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index 4dcba5a4fff0..ad7d2872cfbf 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -26,6 +26,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include @@ -83,7 +84,7 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g) dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret); return -EIO; } - + return 0; } @@ -167,7 +168,7 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) static struct i2c_driver driver = { .driver = { - .name = "tea6420", + .name = "tea6420", }, .id = I2C_DRIVERID_TEA6420, .attach_adapter = attach, -- cgit v1.2.3-59-g8ed1b From 08f1d0b99f4e2203935d86640a7fec5c233b777c Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 17 Mar 2006 18:21:17 -0300 Subject: V4L/DVB (3543): Fix Makefile to adapt to bt8xx/ conversion Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile index d188e4c670b5..9d197efb481d 100644 --- a/drivers/media/dvb/bt8xx/Makefile +++ b/drivers/media/dvb/bt8xx/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o -EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends -- cgit v1.2.3-59-g8ed1b From ecb73774e5f5b5f635a70073086c3f57b4ca4ae6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 17 Mar 2006 20:54:32 -0300 Subject: V4L/DVB (3545): Fixed no_overlay option and quirks on saa7134 driver Some chipsets have several problems when pci to pci transfers are activated on overlay mode. the option no_overlay allows disabling such feature of the driver, in favor of keeping the system stable. The default is to use pcipci_fail flag defined on drivers/pci/quirks.c. It also allows the user to override it by forcing disable overlay or forcing enable. Forcing enable may generate PCI transfer corruption, including disk mass corruption, so should be used with care. Added a text description to this option and make messages looks the same at both bttv and saa7134 drivers. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 13 +++++++++---- drivers/media/video/saa7134/saa7134-video.c | 27 +++++++++++++++++++++++++-- drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 35 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index be85e0b0cbb0..58e568d7d2ee 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -66,8 +66,8 @@ static unsigned int latency = UNSET; module_param(latency, int, 0444); MODULE_PARM_DESC(latency,"pci latency timer"); -static int no_overlay=-1; -module_param(no_overlay, int, 0444); +int saa7134_no_overlay=-1; +module_param_named(no_overlay, saa7134_no_overlay, int, 0444); MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)" " [some VIA/SIS chipsets are known to have problem with overlay]"); @@ -843,11 +843,11 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, printk(KERN_INFO "%s: quirk: this driver and your " "chipset may not work together" " in overlay mode.\n",dev->name); - if (!no_overlay) { + if (!saa7134_no_overlay) { printk(KERN_INFO "%s: quirk: overlay " "mode will be disabled.\n", dev->name); - no_overlay = 1; + saa7134_no_overlay = 1; } else { printk(KERN_INFO "%s: quirk: overlay " "mode will be forced. Use this" @@ -957,6 +957,11 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, v4l2_prio_init(&dev->prio); /* register v4l devices */ + if (saa7134_no_overlay <= 0) { + saa7134_video_template.type |= VID_TYPE_OVERLAY; + } else { + printk("bttv: Overlay support disabled.\n"); + } dev->video_dev = vdev_init(dev,&saa7134_video_template,"video"); err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, video_nr[dev->nr]); diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 600c3c7e3dca..57a11e71d996 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1462,6 +1462,10 @@ static int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, f->fmt.pix.height * f->fmt.pix.bytesperline; return 0; case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (saa7134_no_overlay > 0) { + printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; + } f->fmt.win = fh->win; return 0; case V4L2_BUF_TYPE_VBI_CAPTURE: @@ -1526,6 +1530,10 @@ static int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, return 0; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (saa7134_no_overlay > 0) { + printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; + } err = verify_preview(dev,&f->fmt.win); if (0 != err) return err; @@ -1556,6 +1564,10 @@ static int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, fh->cap.field = f->fmt.pix.field; return 0; case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (saa7134_no_overlay > 0) { + printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; + } err = verify_preview(dev,&f->fmt.win); if (0 != err) return err; @@ -1715,11 +1727,13 @@ static int video_do_ioctl(struct inode *inode, struct file *file, cap->version = SAA7134_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_TUNER; + if (saa7134_no_overlay <= 0) { + cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; + } if ((tuner_type == TUNER_ABSENT) || (tuner_type == UNSET)) cap->capabilities &= ~V4L2_CAP_TUNER; @@ -1970,6 +1984,10 @@ static int video_do_ioctl(struct inode *inode, struct file *file, switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (saa7134_no_overlay > 0) { + printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; + } if (index >= FORMATS) return -EINVAL; if (f->type == V4L2_BUF_TYPE_VIDEO_OVERLAY && @@ -2030,6 +2048,11 @@ static int video_do_ioctl(struct inode *inode, struct file *file, int *on = arg; if (*on) { + if (saa7134_no_overlay > 0) { + printk ("no_overlay\n"); + return -EINVAL; + } + if (!res_get(dev,fh,RESOURCE_OVERLAY)) return -EBUSY; spin_lock_irqsave(&dev->slock,flags); @@ -2281,7 +2304,7 @@ static struct file_operations radio_fops = struct video_device saa7134_video_template = { .name = "saa7134-video", - .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| + .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = 0, .fops = &video_fops, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 683e785c18bd..17ba34f30760 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -557,6 +557,7 @@ struct saa7134_dev { /* saa7134-core.c */ extern struct list_head saa7134_devlist; +extern int saa7134_no_overlay; void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); -- cgit v1.2.3-59-g8ed1b From 30afc84cf7325e88fb9746340eba3c161080ff49 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 18 Mar 2006 18:40:14 +0900 Subject: [SCSI] libata: implement minimal transport template for ->eh_timed_out SCSI midlayer has moved hostt->eh_timed_out to transport template. As libata doesn't need full-blown transport support yet, implement minimal transport for libata. No transport class or whatsoever, just empty transport template with ->eh_timed_out hook. Signed-off-by: Tejun Heo Signed-off-by: James Bottomley --- drivers/scsi/ahci.c | 1 - drivers/scsi/ata_piix.c | 1 - drivers/scsi/libata-core.c | 3 ++- drivers/scsi/libata-scsi.c | 10 ++++++++++ drivers/scsi/libata.h | 2 ++ 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 - include/linux/libata.h | 1 - 19 files changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index e97ab3e6de4d..a1ddbba2cbdf 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -207,7 +207,6 @@ static struct scsi_host_template ahci_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 9327b62f97de..a74e23d39ba9 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -209,7 +209,6 @@ static struct scsi_host_template piix_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 714b42bad935..64dce00e9c46 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4653,6 +4653,8 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, if (!host) return NULL; + host->transportt = &ata_scsi_transport_template; + ap = (struct ata_port *) &host->hostdata[0]; ata_host_init(ap, host, host_set, ent, port_no); @@ -5084,7 +5086,6 @@ 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_timed_out); EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ccedb4536977..bd9f2176f79a 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ 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 @@ -92,6 +94,14 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { 0, 30 /* extended self test time, see 05-359r1 */ }; +/* + * libata transport template. libata doesn't do real transport stuff. + * It just needs the eh_timed_out hook. + */ +struct scsi_transport_template ata_scsi_transport_template = { + .eh_timed_out = ata_scsi_timed_out, +}; + static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index f4c48c91b63d..65f52beea884 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -57,6 +57,8 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); /* libata-scsi.c */ +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, diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 5f33cc932e70..b3dc5f85ae0b 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -143,7 +143,6 @@ static struct scsi_host_template adma_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index e561281967dd..874c5be0843c 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -378,7 +378,6 @@ static struct scsi_host_template mv_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = MV_USE_Q_DEPTH, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index caffadc2e0ae..e5b20c6afc18 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -229,7 +229,6 @@ static struct scsi_host_template nv_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 84cb3940ad88..cc928c68a479 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -111,7 +111,6 @@ static struct scsi_host_template pdc_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 9602f43a298e..9ffe1ef0d205 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -132,7 +132,6 @@ static struct scsi_host_template qs_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 4f2a67ed39d8..3e75d6733239 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -146,7 +146,6 @@ static struct scsi_host_template sil_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 9a53a5ed38c5..5d01e5ce5ac5 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -281,7 +281,6 @@ static struct scsi_host_template sil24_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 7fd45f86de99..acc8439dea23 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -87,7 +87,6 @@ static struct scsi_host_template sis_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 4aaccd53e736..051e47d975ca 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -288,7 +288,6 @@ static struct scsi_host_template k2_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 9f8a76815402..ae70f60c7c0d 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -182,7 +182,6 @@ static struct scsi_host_template pdc_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 37a487b7d655..8f5025733def 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -75,7 +75,6 @@ static struct scsi_host_template uli_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index ff65a0b0457f..791bf652ba63 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -94,7 +94,6 @@ static struct scsi_host_template svia_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index b574379a7a82..ee75b9b38ae8 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -251,7 +251,6 @@ static struct scsi_host_template vsc_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_timed_out = ata_scsi_timed_out, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, diff --git a/include/linux/libata.h b/include/linux/libata.h index 239408ecfddf..204c37a55f06 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -508,7 +508,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 enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); 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); -- cgit v1.2.3-59-g8ed1b From 00a6cae288138ce0444ab6f48a81da12afe557aa Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 21 Mar 2006 10:56:59 -0800 Subject: [PATCH] skge: use NAPI for tx cleanup. Cleanup transmit buffers using NAPI. This allows the transmit routine to leave interrupts enabled, and that improves performance. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 99 ++++++++++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 25e028b7ce48..1a30d5401c48 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2307,16 +2307,13 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) int i; u32 control, len; u64 map; - unsigned long flags; skb = skb_padto(skb, ETH_ZLEN); if (!skb) return NETDEV_TX_OK; - local_irq_save(flags); if (!spin_trylock(&skge->tx_lock)) { /* Collision - tell upper layer to requeue */ - local_irq_restore(flags); return NETDEV_TX_LOCKED; } @@ -2327,7 +2324,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) printk(KERN_WARNING PFX "%s: ring full when queue awake!\n", dev->name); } - spin_unlock_irqrestore(&skge->tx_lock, flags); + spin_unlock(&skge->tx_lock); return NETDEV_TX_BUSY; } @@ -2403,7 +2400,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) } dev->trans_start = jiffies; - spin_unlock_irqrestore(&skge->tx_lock, flags); + spin_unlock(&skge->tx_lock); return NETDEV_TX_OK; } @@ -2416,7 +2413,7 @@ static inline void skge_tx_free(struct skge_hw *hw, struct skge_element *e) pci_unmap_addr(e, mapaddr), pci_unmap_len(e, maplen), PCI_DMA_TODEVICE); - dev_kfree_skb_any(e->skb); + dev_kfree_skb(e->skb); e->skb = NULL; } else { pci_unmap_page(hw->pdev, @@ -2430,15 +2427,14 @@ static void skge_tx_clean(struct skge_port *skge) { struct skge_ring *ring = &skge->tx_ring; struct skge_element *e; - unsigned long flags; - spin_lock_irqsave(&skge->tx_lock, flags); + spin_lock_bh(&skge->tx_lock); for (e = ring->to_clean; e != ring->to_use; e = e->next) { ++skge->tx_avail; skge_tx_free(skge->hw, e); } ring->to_clean = e; - spin_unlock_irqrestore(&skge->tx_lock, flags); + spin_unlock_bh(&skge->tx_lock); } static void skge_tx_timeout(struct net_device *dev) @@ -2663,6 +2659,37 @@ resubmit: return NULL; } +static void skge_tx_done(struct skge_port *skge) +{ + struct skge_ring *ring = &skge->tx_ring; + struct skge_element *e; + + spin_lock(&skge->tx_lock); + for (e = ring->to_clean; prefetch(e->next), e != ring->to_use; e = e->next) { + struct skge_tx_desc *td = e->desc; + u32 control; + + rmb(); + control = td->control; + if (control & BMU_OWN) + break; + + if (unlikely(netif_msg_tx_done(skge))) + printk(KERN_DEBUG PFX "%s: tx done slot %td status 0x%x\n", + skge->netdev->name, e - ring->start, td->status); + + skge_tx_free(skge->hw, e); + e->skb = NULL; + ++skge->tx_avail; + } + ring->to_clean = e; + skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); + + if (skge->tx_avail > MAX_SKB_FRAGS + 1) + netif_wake_queue(skge->netdev); + + spin_unlock(&skge->tx_lock); +} static int skge_poll(struct net_device *dev, int *budget) { @@ -2670,8 +2697,10 @@ static int skge_poll(struct net_device *dev, int *budget) struct skge_hw *hw = skge->hw; struct skge_ring *ring = &skge->rx_ring; struct skge_element *e; - unsigned int to_do = min(dev->quota, *budget); - unsigned int work_done = 0; + int to_do = min(dev->quota, *budget); + int work_done = 0; + + skge_tx_done(skge); for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) { struct skge_rx_desc *rd = e->desc; @@ -2714,40 +2743,6 @@ static int skge_poll(struct net_device *dev, int *budget) return 0; } -static inline void skge_tx_intr(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - struct skge_ring *ring = &skge->tx_ring; - struct skge_element *e; - - spin_lock(&skge->tx_lock); - for (e = ring->to_clean; prefetch(e->next), e != ring->to_use; e = e->next) { - struct skge_tx_desc *td = e->desc; - u32 control; - - rmb(); - control = td->control; - if (control & BMU_OWN) - break; - - if (unlikely(netif_msg_tx_done(skge))) - printk(KERN_DEBUG PFX "%s: tx done slot %td status 0x%x\n", - dev->name, e - ring->start, td->status); - - skge_tx_free(hw, e); - e->skb = NULL; - ++skge->tx_avail; - } - ring->to_clean = e; - skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); - - if (skge->tx_avail > MAX_SKB_FRAGS + 1) - netif_wake_queue(dev); - - spin_unlock(&skge->tx_lock); -} - /* Parity errors seem to happen when Genesis is connected to a switch * with no other ports present. Heartbeat error?? */ @@ -2884,24 +2879,18 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) return IRQ_NONE; spin_lock(&hw->hw_lock); - if (status & IS_R1_F) { + if (status & (IS_R1_F|IS_XA1_F)) { skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F); - hw->intr_mask &= ~IS_R1_F; + hw->intr_mask &= ~(IS_R1_F|IS_XA1_F); netif_rx_schedule(hw->dev[0]); } - if (status & IS_R2_F) { + if (status & (IS_R2_F|IS_XA2_F)) { skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F); - hw->intr_mask &= ~IS_R2_F; + hw->intr_mask &= ~(IS_R2_F|IS_XA2_F); netif_rx_schedule(hw->dev[1]); } - if (status & IS_XA1_F) - skge_tx_intr(hw->dev[0]); - - if (status & IS_XA2_F) - skge_tx_intr(hw->dev[1]); - if (status & IS_PA_TO_RX1) { struct skge_port *skge = netdev_priv(hw->dev[0]); ++skge->net_stats.rx_over_errors; -- cgit v1.2.3-59-g8ed1b From cfc3ed796eda2c41fb20986d831ed56c0474279d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 21 Mar 2006 10:57:00 -0800 Subject: [PATCH] skge: use auto masking of irqs Improve performance of skge driver by not touching irq mask register as much. Since the interrupt source auto-masks, the driver can just leave it disabled until the end of the soft irq. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 54 +++++++++++++++++++++--------------------------------- drivers/net/skge.h | 1 - 2 files changed, 21 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 1a30d5401c48..4fc9333f0740 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -104,7 +104,6 @@ static const int txqaddr[] = { Q_XA1, Q_XA2 }; static const int rxqaddr[] = { Q_R1, Q_R2 }; static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F }; static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F }; -static const u32 portirqmask[] = { IS_PORT_1, IS_PORT_2 }; static int skge_get_regs_len(struct net_device *dev) { @@ -2184,12 +2183,6 @@ static int skge_up(struct net_device *dev) skge->tx_avail = skge->tx_ring.count - 1; - /* Enable IRQ from port */ - spin_lock_irq(&hw->hw_lock); - hw->intr_mask |= portirqmask[port]; - skge_write32(hw, B0_IMSK, hw->intr_mask); - spin_unlock_irq(&hw->hw_lock); - /* Initialize MAC */ spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) @@ -2246,11 +2239,6 @@ static int skge_down(struct net_device *dev) else yukon_stop(skge); - spin_lock_irq(&hw->hw_lock); - hw->intr_mask &= ~portirqmask[skge->port]; - skge_write32(hw, B0_IMSK, hw->intr_mask); - spin_unlock_irq(&hw->hw_lock); - /* Stop transmitter */ skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), @@ -2734,11 +2722,9 @@ static int skge_poll(struct net_device *dev, int *budget) if (work_done >= to_do) return 1; /* not done */ - spin_lock_irq(&hw->hw_lock); - __netif_rx_complete(dev); - hw->intr_mask |= portirqmask[skge->port]; + netif_rx_complete(dev); + hw->intr_mask |= skge->port == 0 ? (IS_R1_F|IS_XA1_F) : (IS_R2_F|IS_XA2_F); skge_write32(hw, B0_IMSK, hw->intr_mask); - spin_unlock_irq(&hw->hw_lock); return 0; } @@ -2850,12 +2836,11 @@ static void skge_extirq(unsigned long data) int port; spin_lock(&hw->phy_lock); - for (port = 0; port < 2; port++) { + for (port = 0; port < hw->ports; port++) { struct net_device *dev = hw->dev[port]; + struct skge_port *skge = netdev_priv(dev); - if (dev && netif_running(dev)) { - struct skge_port *skge = netdev_priv(dev); - + if (netif_running(dev)) { if (hw->chip_id != CHIP_ID_GENESIS) yukon_phy_intr(skge); else @@ -2864,21 +2849,25 @@ static void skge_extirq(unsigned long data) } spin_unlock(&hw->phy_lock); - spin_lock_irq(&hw->hw_lock); hw->intr_mask |= IS_EXT_REG; skge_write32(hw, B0_IMSK, hw->intr_mask); - spin_unlock_irq(&hw->hw_lock); } static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) { struct skge_hw *hw = dev_id; - u32 status = skge_read32(hw, B0_SP_ISRC); + u32 status; - if (status == 0 || status == ~0) /* hotplug or shared irq */ + /* Reading this register masks IRQ */ + status = skge_read32(hw, B0_SP_ISRC); + if (status == 0) return IRQ_NONE; - spin_lock(&hw->hw_lock); + if (status & IS_EXT_REG) { + hw->intr_mask &= ~IS_EXT_REG; + tasklet_schedule(&hw->ext_tasklet); + } + if (status & (IS_R1_F|IS_XA1_F)) { skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F); hw->intr_mask &= ~(IS_R1_F|IS_XA1_F); @@ -2891,6 +2880,9 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) netif_rx_schedule(hw->dev[1]); } + if (likely((status & hw->intr_mask) == 0)) + return IRQ_HANDLED; + if (status & IS_PA_TO_RX1) { struct skge_port *skge = netdev_priv(hw->dev[0]); ++skge->net_stats.rx_over_errors; @@ -2918,13 +2910,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) if (status & IS_HW_ERR) skge_error_irq(hw); - if (status & IS_EXT_REG) { - hw->intr_mask &= ~IS_EXT_REG; - tasklet_schedule(&hw->ext_tasklet); - } - skge_write32(hw, B0_IMSK, hw->intr_mask); - spin_unlock(&hw->hw_lock); return IRQ_HANDLED; } @@ -3070,7 +3056,10 @@ static int skge_reset(struct skge_hw *hw) else hw->ram_size = t8 * 4096; - hw->intr_mask = IS_HW_ERR | IS_EXT_REG; + hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1; + if (hw->ports > 1) + hw->intr_mask |= IS_PORT_2; + if (hw->chip_id == CHIP_ID_GENESIS) genesis_init(hw); else { @@ -3293,7 +3282,6 @@ static int __devinit skge_probe(struct pci_dev *pdev, hw->pdev = pdev; spin_lock_init(&hw->phy_lock); - spin_lock_init(&hw->hw_lock); tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw); hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 941f12a333b6..2efdacc290e5 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2402,7 +2402,6 @@ struct skge_hw { struct tasklet_struct ext_tasklet; spinlock_t phy_lock; - spinlock_t hw_lock; }; enum { -- cgit v1.2.3-59-g8ed1b From c3da14474063e71686039d961d14785a9c2971ae Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 21 Mar 2006 10:57:01 -0800 Subject: [PATCH] skge: check the allocation of ring buffer The SysKonnect Genesis and Yukon chip sets have restrictions on the possible control block area. The memory needs to not cross 4 Gig boundary, and it needs to be 8 byte aligned. This patch checks and fails to bring the device up if region is unacceptable. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 4fc9333f0740..deca5066a447 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -727,7 +727,7 @@ static struct ethtool_ops skge_ethtool_ops = { * Allocate ring elements and chain them together * One-to-one association of board descriptors with ring elements */ -static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base) +static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base) { struct skge_tx_desc *d; struct skge_element *e; @@ -2168,6 +2168,14 @@ static int skge_up(struct net_device *dev) if (!skge->mem) return -ENOMEM; + BUG_ON(skge->dma & 7); + + if ((u64)skge->dma >> 32 != ((u64) skge->dma + skge->mem_size) >> 32) { + printk(KERN_ERR PFX "pci_alloc_consistent region crosses 4G boundary\n"); + err = -EINVAL; + goto free_pci_mem; + } + memset(skge->mem, 0, skge->mem_size); if ((err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma))) -- cgit v1.2.3-59-g8ed1b From 93aea718c69d44ee492f233929686b15b5b3702d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 21 Mar 2006 10:57:02 -0800 Subject: [PATCH] skge: dma configuration cleanup Cleanup of the part of the code that sets up DMA configuration. Should cause no real change in operation, just clearer. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index deca5066a447..381669cc415f 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -3251,22 +3251,18 @@ static int __devinit skge_probe(struct pci_dev *pdev, pci_set_master(pdev); - if (sizeof(dma_addr_t) > sizeof(u32) && - !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { using_dac = 1; err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - if (err < 0) { - printk(KERN_ERR PFX "%s unable to obtain 64 bit DMA " - "for consistent allocations\n", pci_name(pdev)); - goto err_out_free_regions; - } - } else { - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (err) { - printk(KERN_ERR PFX "%s no usable DMA configuration\n", - pci_name(pdev)); - goto err_out_free_regions; - } + } else if (!(err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { + using_dac = 0; + err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + } + + if (err) { + printk(KERN_ERR PFX "%s no usable DMA configuration\n", + pci_name(pdev)); + goto err_out_free_regions; } #ifdef __BIG_ENDIAN -- cgit v1.2.3-59-g8ed1b From ff7907aede7962629c2eb50e08b870316c80518f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 21 Mar 2006 10:57:03 -0800 Subject: [PATCH] skge: use kcalloc Use kcalloc when allocating ring data structure. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 381669cc415f..5ece10034df9 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -733,13 +733,12 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base) struct skge_element *e; int i; - ring->start = kmalloc(sizeof(*e)*ring->count, GFP_KERNEL); + ring->start = kcalloc(sizeof(*e), ring->count, GFP_KERNEL); if (!ring->start) return -ENOMEM; for (i = 0, e = ring->start, d = vaddr; i < ring->count; i++, e++, d++) { e->desc = d; - e->skb = NULL; if (i == ring->count - 1) { e->next = ring->start; d->next_offset = base; -- cgit v1.2.3-59-g8ed1b From c68ce71a340ffb5c589db5d9f9af1ce4ef81baa9 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 21 Mar 2006 10:57:04 -0800 Subject: [PATCH] skge: use mmiowb Add mmio barriers at the appropriate places, don't have a platform that needs them, but this is where the documentation of the patch says to add them. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 5ece10034df9..8c674cdecd7b 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2394,9 +2394,11 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); } - dev->trans_start = jiffies; + mmiowb(); spin_unlock(&skge->tx_lock); + dev->trans_start = jiffies; + return NETDEV_TX_OK; } @@ -2730,6 +2732,8 @@ static int skge_poll(struct net_device *dev, int *budget) return 1; /* not done */ netif_rx_complete(dev); + mmiowb(); + hw->intr_mask |= skge->port == 0 ? (IS_R1_F|IS_XA1_F) : (IS_R2_F|IS_XA2_F); skge_write32(hw, B0_IMSK, hw->intr_mask); -- cgit v1.2.3-59-g8ed1b From 203babb650d0c99a8be08f479d4a05d420988d89 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 21 Mar 2006 10:57:05 -0800 Subject: [PATCH] skge: formmating and whitespace cleanup Reformat some code to make it easier to read. And whitespace fixes. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 8c674cdecd7b..7f8e8dd0fc6e 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2177,15 +2177,17 @@ static int skge_up(struct net_device *dev) memset(skge->mem, 0, skge->mem_size); - if ((err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma))) + err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma); + if (err) goto free_pci_mem; err = skge_rx_fill(skge); if (err) goto free_rx_ring; - if ((err = skge_ring_alloc(&skge->tx_ring, skge->mem + rx_size, - skge->dma + rx_size))) + err = skge_ring_alloc(&skge->tx_ring, skge->mem + rx_size, + skge->dma + rx_size); + if (err) goto free_rx_ring; skge->tx_avail = skge->tx_ring.count - 1; @@ -2308,9 +2310,9 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; if (!spin_trylock(&skge->tx_lock)) { - /* Collision - tell upper layer to requeue */ - return NETDEV_TX_LOCKED; - } + /* Collision - tell upper layer to requeue */ + return NETDEV_TX_LOCKED; + } if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) { if (!netif_queue_stopped(dev)) { @@ -2709,8 +2711,8 @@ static int skge_poll(struct net_device *dev, int *budget) if (control & BMU_OWN) break; - skb = skge_rx_get(skge, e, control, rd->status, - le16_to_cpu(rd->csum2)); + skb = skge_rx_get(skge, e, control, rd->status, + le16_to_cpu(rd->csum2)); if (likely(skb)) { dev->last_rx = jiffies; netif_receive_skb(skb); @@ -3240,13 +3242,15 @@ static int __devinit skge_probe(struct pci_dev *pdev, struct skge_hw *hw; int err, using_dac = 0; - if ((err = pci_enable_device(pdev))) { + err = pci_enable_device(pdev); + if (err) { printk(KERN_ERR PFX "%s cannot enable PCI device\n", pci_name(pdev)); goto err_out; } - if ((err = pci_request_regions(pdev, DRV_NAME))) { + err = pci_request_regions(pdev, DRV_NAME); + if (err) { printk(KERN_ERR PFX "%s cannot obtain PCI resources\n", pci_name(pdev)); goto err_out_disable_pdev; @@ -3298,7 +3302,8 @@ static int __devinit skge_probe(struct pci_dev *pdev, goto err_out_free_hw; } - if ((err = request_irq(pdev->irq, skge_intr, SA_SHIRQ, DRV_NAME, hw))) { + err = request_irq(pdev->irq, skge_intr, SA_SHIRQ, DRV_NAME, hw); + if (err) { printk(KERN_ERR PFX "%s: cannot assign irq %d\n", pci_name(pdev), pdev->irq); goto err_out_iounmap; @@ -3316,7 +3321,8 @@ static int __devinit skge_probe(struct pci_dev *pdev, if ((dev = skge_devinit(hw, 0, using_dac)) == NULL) goto err_out_led_off; - if ((err = register_netdev(dev))) { + err = register_netdev(dev); + if (err) { printk(KERN_ERR PFX "%s: cannot register net device\n", pci_name(pdev)); goto err_out_free_netdev; -- cgit v1.2.3-59-g8ed1b From b9d64acc82c104df9e4d6b74cbb1af05a77b5d44 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 21 Mar 2006 10:57:06 -0800 Subject: [PATCH] skge: handle pci errors better When a PCI error occurs, try and report more info. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 7f8e8dd0fc6e..0325fbceb358 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2764,17 +2764,6 @@ static void skge_mac_parity(struct skge_hw *hw, int port) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE); } -static void skge_pci_clear(struct skge_hw *hw) -{ - u16 status; - - pci_read_config_word(hw->pdev, PCI_STATUS, &status); - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - pci_write_config_word(hw->pdev, PCI_STATUS, - status | PCI_STATUS_ERROR_BITS); - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); -} - static void skge_mac_intr(struct skge_hw *hw, int port) { if (hw->chip_id == CHIP_ID_GENESIS) @@ -2816,23 +2805,39 @@ static void skge_error_irq(struct skge_hw *hw) if (hwstatus & IS_M2_PAR_ERR) skge_mac_parity(hw, 1); - if (hwstatus & IS_R1_PAR_ERR) + if (hwstatus & IS_R1_PAR_ERR) { + printk(KERN_ERR PFX "%s: receive queue parity error\n", + hw->dev[0]->name); skge_write32(hw, B0_R1_CSR, CSR_IRQ_CL_P); + } - if (hwstatus & IS_R2_PAR_ERR) + if (hwstatus & IS_R2_PAR_ERR) { + printk(KERN_ERR PFX "%s: receive queue parity error\n", + hw->dev[1]->name); skge_write32(hw, B0_R2_CSR, CSR_IRQ_CL_P); + } if (hwstatus & (IS_IRQ_MST_ERR|IS_IRQ_STAT)) { - printk(KERN_ERR PFX "hardware error detected (status 0x%x)\n", - hwstatus); + u16 pci_status, pci_cmd; + + pci_read_config_word(hw->pdev, PCI_COMMAND, &pci_cmd); + pci_read_config_word(hw->pdev, PCI_STATUS, &pci_status); - skge_pci_clear(hw); + printk(KERN_ERR PFX "%s: PCI error cmd=%#x status=%#x\n", + pci_name(hw->pdev), pci_cmd, pci_status); + + /* Write the error bits back to clear them. */ + pci_status &= PCI_STATUS_ERROR_BITS; + skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + pci_write_config_word(hw->pdev, PCI_COMMAND, + pci_cmd | PCI_COMMAND_SERR | PCI_COMMAND_PARITY); + pci_write_config_word(hw->pdev, PCI_STATUS, pci_status); + skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); /* if error still set then just ignore it */ hwstatus = skge_read32(hw, B0_HWE_ISRC); if (hwstatus & IS_IRQ_STAT) { - pr_debug("IRQ status %x: still set ignoring hardware errors\n", - hwstatus); + printk(KERN_INFO PFX "unable to clear error (so ignoring them)\n"); hw->intr_mask &= ~IS_HW_ERR; } } @@ -2998,7 +3003,7 @@ static const char *skge_board_name(const struct skge_hw *hw) static int skge_reset(struct skge_hw *hw) { u32 reg; - u16 ctst; + u16 ctst, pci_status; u8 t8, mac_cfg, pmd_type, phy_type; int i; @@ -3009,8 +3014,13 @@ static int skge_reset(struct skge_hw *hw) skge_write8(hw, B0_CTST, CS_RST_CLR); /* clear PCI errors, if any */ - skge_pci_clear(hw); + skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + skge_write8(hw, B2_TST_CTRL2, 0); + pci_read_config_word(hw->pdev, PCI_STATUS, &pci_status); + pci_write_config_word(hw->pdev, PCI_STATUS, + pci_status | PCI_STATUS_ERROR_BITS); + skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); skge_write8(hw, B0_CTST, CS_MRST_CLR); /* restore CLK_RUN bits (for Yukon-Lite) */ @@ -3377,7 +3387,6 @@ static void __devexit skge_remove(struct pci_dev *pdev) skge_write32(hw, B0_IMSK, 0); skge_write16(hw, B0_LED, LED_STAT_OFF); - skge_pci_clear(hw); skge_write8(hw, B0_CTST, CS_RST_SET); tasklet_kill(&hw->ext_tasklet); -- cgit v1.2.3-59-g8ed1b From 9362860fd1d9062ff9b3dca42aa3e1e68c2ddb67 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 21 Mar 2006 10:57:07 -0800 Subject: [PATCH] skge: version 1.4 Update version number Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 0325fbceb358..4eda81d41b10 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -44,7 +44,7 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.3" +#define DRV_VERSION "1.4" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 -- cgit v1.2.3-59-g8ed1b From 6f059c3e9042bc4eaa4f7a8dd651bbed9be144f2 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Tue, 21 Mar 2006 11:44:35 -0700 Subject: [PATCH] mv643xx_eth: Cache align skb->data if CONFIG_NOT_COHERENT_CACHE When I/O is non-cache-coherent, we need to ensure that the I/O buffers we use don't share cache lines with other data. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.h | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index 7754d1974b9e..4262c1da6d4a 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -42,13 +42,23 @@ #define MAX_DESCS_PER_SKB 1 #endif +/* + * The MV643XX HW requires 8-byte alignment. However, when I/O + * is non-cache-coherent, we need to ensure that the I/O buffers + * we use don't share cache lines with other data. + */ +#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_NOT_COHERENT_CACHE) +#define ETH_DMA_ALIGN L1_CACHE_BYTES +#else +#define ETH_DMA_ALIGN 8 +#endif + #define ETH_VLAN_HLEN 4 #define ETH_FCS_LEN 4 -#define ETH_DMA_ALIGN 8 /* hw requires 8-byte alignment */ -#define ETH_HW_IP_ALIGN 2 /* hw aligns IP header */ +#define ETH_HW_IP_ALIGN 2 /* hw aligns IP header */ #define ETH_WRAPPER_LEN (ETH_HW_IP_ALIGN + ETH_HLEN + \ - ETH_VLAN_HLEN + ETH_FCS_LEN) -#define ETH_RX_SKB_SIZE ((dev->mtu + ETH_WRAPPER_LEN + 7) & ~0x7) + ETH_VLAN_HLEN + ETH_FCS_LEN) +#define ETH_RX_SKB_SIZE (dev->mtu + ETH_WRAPPER_LEN + ETH_DMA_ALIGN) #define ETH_RX_QUEUES_ENABLED (1 << 0) /* use only Q0 for receive */ #define ETH_TX_QUEUES_ENABLED (1 << 0) /* use only Q0 for transmit */ -- cgit v1.2.3-59-g8ed1b From 290d4de5b71f60bb5853a7ef9f0e8c817cd26892 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 15:48:15 -0800 Subject: [PATCH] sky2: remove support for untested Yukon EC/rev 0 The Yukon EC/rev0 (A1) chipset requires a bunch of workarounds. I copied these from sk98lin. But since they never got tested and add more cruft to the code; any attempt at using driver as is on this version will probably fail. It looks like this was a early engineering sample chip revision, if it ever shows up on a real system. Produce an error message. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 93 +++++++++++++++++++----------------------------------- drivers/net/sky2.h | 2 -- 2 files changed, 32 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 73260364cba3..3086e52032a8 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -61,10 +61,6 @@ * a receive requires one (or two if using 64 bit dma). */ -#define is_ec_a1(hw) \ - unlikely((hw)->chip_id == CHIP_ID_YUKON_EC && \ - (hw)->chip_rev == CHIP_REV_YU_EC_A1) - #define RX_LE_SIZE 512 #define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) #define RX_MAX_PENDING (RX_LE_SIZE/2 - 2) @@ -725,37 +721,11 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2) return le; } -/* - * This is a workaround code taken from SysKonnect sk98lin driver - * to deal with chip bug on Yukon EC rev 0 in the wraparound case. - */ -static void sky2_put_idx(struct sky2_hw *hw, unsigned q, - u16 idx, u16 *last, u16 size) +/* Update chip's next pointer */ +static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx) { wmb(); - if (is_ec_a1(hw) && idx < *last) { - u16 hwget = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX)); - - if (hwget == 0) { - /* Start prefetching again */ - sky2_write8(hw, Y2_QADDR(q, PREF_UNIT_FIFO_WM), 0xe0); - goto setnew; - } - - if (hwget == size - 1) { - /* set watermark to one list element */ - sky2_write8(hw, Y2_QADDR(q, PREF_UNIT_FIFO_WM), 8); - - /* set put index to first list element */ - sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), 0); - } else /* have hardware go to end of list */ - sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), - size - 1); - } else { -setnew: - sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx); - } - *last = idx; + sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx); mmiowb(); } @@ -1001,7 +971,6 @@ static int sky2_rx_start(struct sky2_port *sky2) /* Tell chip about available buffers */ sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); - sky2->rx_last_put = sky2_read16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX)); return 0; nomem: sky2_rx_clean(sky2); @@ -1299,8 +1268,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); } - sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod, - &sky2->tx_last_put, TX_RING_SIZE); + sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod); out_unlock: spin_unlock(&sky2->tx_lock); @@ -1843,8 +1811,7 @@ resubmit: sky2_rx_add(sky2, re->mapaddr); /* Tell receiver about new buffers. */ - sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put, - &sky2->rx_last_put, RX_LE_SIZE); + sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put); return skb; @@ -2238,6 +2205,23 @@ static int sky2_reset(struct sky2_hw *hw) return -EOPNOTSUPP; } + hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; + + /* This rev is really old, and requires untested workarounds */ + if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) { + printk(KERN_ERR PFX "%s: unsupported revision Yukon-%s (0x%x) rev %d\n", + pci_name(hw->pdev), yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], + hw->chip_id, hw->chip_rev); + return -EOPNOTSUPP; + } + + /* This chip is new and not tested yet */ + if (hw->chip_id == CHIP_ID_YUKON_EC_U) { + pr_info(PFX "%s: is a version of Yukon 2 chipset that has not been tested yet.\n", + pci_name(hw->pdev)); + pr_info("Please report success/failure to maintainer \n"); + } + /* disable ASF */ if (hw->chip_id <= CHIP_ID_YUKON_EC) { sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); @@ -2271,7 +2255,6 @@ static int sky2_reset(struct sky2_hw *hw) if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC)) ++hw->ports; } - hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; sky2_set_power_state(hw, PCI_D0); @@ -2338,29 +2321,17 @@ static int sky2_reset(struct sky2_hw *hw) sky2_write16(hw, STAT_LAST_IDX, STATUS_RING_SIZE - 1); /* These status setup values are copied from SysKonnect's driver */ - if (is_ec_a1(hw)) { - /* WA for dev. #4.3 */ - sky2_write16(hw, STAT_TX_IDX_TH, 0xfff); /* Tx Threshold */ + sky2_write16(hw, STAT_TX_IDX_TH, 10); + sky2_write8(hw, STAT_FIFO_WM, 16); - /* set Status-FIFO watermark */ - sky2_write8(hw, STAT_FIFO_WM, 0x21); /* WA for dev. #4.18 */ - - /* set Status-FIFO ISR watermark */ - sky2_write8(hw, STAT_FIFO_ISR_WM, 0x07); /* WA for dev. #4.18 */ - sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 10000)); - } else { - sky2_write16(hw, STAT_TX_IDX_TH, 10); - sky2_write8(hw, STAT_FIFO_WM, 16); - - /* set Status-FIFO ISR watermark */ - if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0) - sky2_write8(hw, STAT_FIFO_ISR_WM, 4); - else - sky2_write8(hw, STAT_FIFO_ISR_WM, 16); + /* set Status-FIFO ISR watermark */ + if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0) + sky2_write8(hw, STAT_FIFO_ISR_WM, 4); + else + sky2_write8(hw, STAT_FIFO_ISR_WM, 16); - sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000)); - sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 7)); - } + sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000)); + sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 7)); /* enable status unit */ sky2_write32(hw, STAT_CTRL, SC_STAT_OP_ON); @@ -3091,7 +3062,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, INIT_WORK(&sky2->phy_task, sky2_phy_task, sky2); init_MUTEX(&sky2->phy_sema); sky2->tx_pending = TX_DEF_PENDING; - sky2->rx_pending = is_ec_a1(hw) ? 8 : RX_DEF_PENDING; + sky2->rx_pending = RX_DEF_PENDING; sky2->rx_bufsize = sky2_buf_size(ETH_DATA_LEN); hw->dev[port] = dev; diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index dce955c76f3c..e2bf1d37ed0e 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1840,7 +1840,6 @@ struct sky2_port { u16 tx_prod; /* next le to use */ u32 tx_addr64; u16 tx_pending; - u16 tx_last_put; u16 tx_last_mss; struct ring_info *rx_ring ____cacheline_aligned_in_smp; @@ -1849,7 +1848,6 @@ struct sky2_port { u16 rx_next; /* next re to check */ u16 rx_put; /* next le index to use */ u16 rx_pending; - u16 rx_last_put; u16 rx_bufsize; #ifdef SKY2_VLAN_TAG_USED u16 rx_tag; -- cgit v1.2.3-59-g8ed1b From c4b1580e8ad1aab13e0d8b97c7af3eebab8791ae Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 15:48:16 -0800 Subject: [PATCH] sky2: drop broken wake on lan support Remove wake on lan support for now. It doesn't work right, and I don't have a machine with working suspend/resume to test or fix it. It will be re-enabled later. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 36 ------------------------------------ drivers/net/sky2.h | 1 - 2 files changed, 37 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 3086e52032a8..3a6c796eb70e 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2777,38 +2777,6 @@ static int sky2_set_pauseparam(struct net_device *dev, return err; } -#ifdef CONFIG_PM -static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct sky2_port *sky2 = netdev_priv(dev); - - wol->supported = WAKE_MAGIC; - wol->wolopts = sky2->wol ? WAKE_MAGIC : 0; -} - -static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct sky2_port *sky2 = netdev_priv(dev); - struct sky2_hw *hw = sky2->hw; - - if (wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) - return -EOPNOTSUPP; - - sky2->wol = wol->wolopts == WAKE_MAGIC; - - if (sky2->wol) { - memcpy_toio(hw->regs + WOL_MAC_ADDR, dev->dev_addr, ETH_ALEN); - - sky2_write16(hw, WOL_CTRL_STAT, - WOL_CTL_ENA_PME_ON_MAGIC_PKT | - WOL_CTL_ENA_MAGIC_PKT_UNIT); - } else - sky2_write16(hw, WOL_CTRL_STAT, WOL_CTL_DEFAULT); - - return 0; -} -#endif - static int sky2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ecmd) { @@ -2996,10 +2964,6 @@ static struct ethtool_ops sky2_ethtool_ops = { .set_ringparam = sky2_set_ringparam, .get_pauseparam = sky2_get_pauseparam, .set_pauseparam = sky2_set_pauseparam, -#ifdef CONFIG_PM - .get_wol = sky2_get_wol, - .set_wol = sky2_set_wol, -#endif .phys_id = sky2_phys_id, .get_stats_count = sky2_get_stats_count, .get_ethtool_stats = sky2_get_ethtool_stats, diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index e2bf1d37ed0e..2a23f3ad6d9f 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1863,7 +1863,6 @@ struct sky2_port { u8 rx_pause; u8 tx_pause; u8 rx_csum; - u8 wol; struct net_device_stats net_stats; -- cgit v1.2.3-59-g8ed1b From e07b1aa8b3ebedd3c7e0e1b4b524f1b2d62707cf Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 15:48:17 -0800 Subject: [PATCH] sky2: rework of NAPI and IRQ management Redo the interupt handling of sky2 driver based on the IRQ mangement documentation. All interrupts are handled by the device0 NAPI poll routine. Don't need to adjust interrupt mask in IRQ context, done only when changing device under RTNL. Therefore don't need hwlock anymore. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 276 +++++++++++++++++++++-------------------------------- drivers/net/sky2.h | 15 +-- 2 files changed, 111 insertions(+), 180 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 3a6c796eb70e..41dbe588de30 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -500,9 +500,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) /* Force a renegotiation */ static void sky2_phy_reinit(struct sky2_port *sky2) { - down(&sky2->phy_sema); + spin_lock_bh(&sky2->phy_lock); sky2_phy_init(sky2->hw, sky2->port); - up(&sky2->phy_sema); + spin_unlock_bh(&sky2->phy_lock); } static void sky2_mac_init(struct sky2_hw *hw, unsigned port) @@ -567,9 +567,9 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); - down(&sky2->phy_sema); + spin_lock_bh(&sky2->phy_lock); sky2_phy_init(hw, port); - up(&sky2->phy_sema); + spin_unlock_bh(&sky2->phy_lock); /* MIB clear */ reg = gma_read16(hw, port, GM_PHY_ADDR); @@ -856,9 +856,9 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIREG: { u16 val = 0; - down(&sky2->phy_sema); + spin_lock_bh(&sky2->phy_lock); err = __gm_phy_read(hw, sky2->port, data->reg_num & 0x1f, &val); - up(&sky2->phy_sema); + spin_unlock_bh(&sky2->phy_lock); data->val_out = val; break; @@ -868,10 +868,10 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!capable(CAP_NET_ADMIN)) return -EPERM; - down(&sky2->phy_sema); + spin_lock_bh(&sky2->phy_lock); err = gm_phy_write(hw, sky2->port, data->reg_num & 0x1f, data->val_in); - up(&sky2->phy_sema); + spin_unlock_bh(&sky2->phy_lock); break; } return err; @@ -983,7 +983,7 @@ static int sky2_up(struct net_device *dev) struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; - u32 ramsize, rxspace; + u32 ramsize, rxspace, imask; int err = -ENOMEM; if (netif_msg_ifup(sky2)) @@ -1048,10 +1048,10 @@ static int sky2_up(struct net_device *dev) goto err_out; /* Enable interrupts from phy/mac for port */ - spin_lock_irq(&hw->hw_lock); - hw->intr_mask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; - sky2_write32(hw, B0_IMSK, hw->intr_mask); - spin_unlock_irq(&hw->hw_lock); + imask = sky2_read32(hw, B0_IMSK); + imask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; + sky2_write32(hw, B0_IMSK, imask); + return 0; err_out: @@ -1343,6 +1343,7 @@ static int sky2_down(struct net_device *dev) struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; u16 ctrl; + u32 imask; /* Never really got started! */ if (!sky2->tx_le) @@ -1354,14 +1355,6 @@ static int sky2_down(struct net_device *dev) /* Stop more packets from being queued */ netif_stop_queue(dev); - /* Disable port IRQ */ - spin_lock_irq(&hw->hw_lock); - hw->intr_mask &= ~((sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); - sky2_write32(hw, B0_IMSK, hw->intr_mask); - spin_unlock_irq(&hw->hw_lock); - - flush_scheduled_work(); - sky2_phy_reset(hw, port); /* Stop transmitter */ @@ -1405,6 +1398,11 @@ static int sky2_down(struct net_device *dev) sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); + /* Disable port IRQ */ + imask = sky2_read32(hw, B0_IMSK); + imask &= ~(sky2->port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; + sky2_write32(hw, B0_IMSK, imask); + /* turn off LED's */ sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); @@ -1599,20 +1597,19 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) return 0; } -/* - * Interrupt from PHY are handled outside of interrupt context - * because accessing phy registers requires spin wait which might - * cause excess interrupt latency. - */ -static void sky2_phy_task(void *arg) +/* Interrupt from PHY */ +static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) { - struct sky2_port *sky2 = arg; - struct sky2_hw *hw = sky2->hw; + struct net_device *dev = hw->dev[port]; + struct sky2_port *sky2 = netdev_priv(dev); u16 istatus, phystat; - down(&sky2->phy_sema); - istatus = gm_phy_read(hw, sky2->port, PHY_MARV_INT_STAT); - phystat = gm_phy_read(hw, sky2->port, PHY_MARV_PHY_STAT); + spin_lock(&sky2->phy_lock); + istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); + phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); + + if (!netif_running(dev)) + goto out; if (netif_msg_intr(sky2)) printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", @@ -1638,12 +1635,7 @@ static void sky2_phy_task(void *arg) sky2_link_down(sky2); } out: - up(&sky2->phy_sema); - - spin_lock_irq(&hw->hw_lock); - hw->intr_mask |= (sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2; - sky2_write32(hw, B0_IMSK, hw->intr_mask); - spin_unlock_irq(&hw->hw_lock); + spin_unlock(&sky2->phy_lock); } @@ -1655,20 +1647,6 @@ static void sky2_tx_timeout(struct net_device *dev) struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; unsigned txq = txqaddr[sky2->port]; - u16 ridx; - - /* Maybe we just missed an status interrupt */ - spin_lock(&sky2->tx_lock); - ridx = sky2_read16(hw, - sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX); - sky2_tx_complete(sky2, ridx); - spin_unlock(&sky2->tx_lock); - - if (!netif_queue_stopped(dev)) { - if (net_ratelimit()) - pr_info(PFX "transmit interrupt missed? recovered\n"); - return; - } if (netif_msg_timer(sky2)) printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); @@ -1698,6 +1676,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) struct sky2_hw *hw = sky2->hw; int err; u16 ctl, mode; + u32 imask; if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; @@ -1710,12 +1689,15 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) return 0; } + imask = sky2_read32(hw, B0_IMSK); sky2_write32(hw, B0_IMSK, 0); dev->trans_start = jiffies; /* prevent tx timeout */ netif_stop_queue(dev); netif_poll_disable(hw->dev[0]); + synchronize_irq(hw->pdev->irq); + ctl = gma_read16(hw, sky2->port, GM_GP_CTRL); gma_write16(hw, sky2->port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); sky2_rx_stop(sky2); @@ -1734,7 +1716,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD); err = sky2_rx_start(sky2); - sky2_write32(hw, B0_IMSK, hw->intr_mask); + sky2_write32(hw, B0_IMSK, imask); if (err) dev_close(dev); @@ -1838,76 +1820,51 @@ error: goto resubmit; } -/* - * Check for transmit complete - */ -#define TX_NO_STATUS 0xffff - -static void sky2_tx_check(struct sky2_hw *hw, int port, u16 last) +/* Transmit complete */ +static inline void sky2_tx_done(struct net_device *dev, u16 last) { - if (last != TX_NO_STATUS) { - struct net_device *dev = hw->dev[port]; - if (dev && netif_running(dev)) { - struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_port *sky2 = netdev_priv(dev); - spin_lock(&sky2->tx_lock); - sky2_tx_complete(sky2, last); - spin_unlock(&sky2->tx_lock); - } + if (netif_running(dev)) { + spin_lock(&sky2->tx_lock); + sky2_tx_complete(sky2, last); + spin_unlock(&sky2->tx_lock); } } -/* - * Both ports share the same status interrupt, therefore there is only - * one poll routine. - */ -static int sky2_poll(struct net_device *dev0, int *budget) +/* Process status response ring */ +static int sky2_status_intr(struct sky2_hw *hw, int to_do) { - struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; - unsigned int to_do = min(dev0->quota, *budget); - unsigned int work_done = 0; - u16 hwidx; - u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS }; - - sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); - - /* - * Kick the STAT_LEV_TIMER_CTRL timer. - * This fixes my hangs on Yukon-EC (0xb6) rev 1. - * The if clause is there to start the timer only if it has been - * configured correctly and not been disabled via ethtool. - */ - if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_START) { - sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP); - sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START); - } + int work_done = 0; - hwidx = sky2_read16(hw, STAT_PUT_IDX); - BUG_ON(hwidx >= STATUS_RING_SIZE); rmb(); - while (hwidx != hw->st_idx) { + for(;;) { struct sky2_status_le *le = hw->st_le + hw->st_idx; struct net_device *dev; struct sky2_port *sky2; struct sk_buff *skb; u32 status; u16 length; + u8 link, opcode; + + opcode = le->opcode; + if (!opcode) + break; + opcode &= ~HW_OWNER; - le = hw->st_le + hw->st_idx; hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE; - prefetch(hw->st_le + hw->st_idx); + le->opcode = 0; - BUG_ON(le->link >= 2); - dev = hw->dev[le->link]; - if (dev == NULL || !netif_running(dev)) - continue; + link = le->link; + BUG_ON(link >= 2); + dev = hw->dev[link]; sky2 = netdev_priv(dev); - status = le32_to_cpu(le->status); - length = le16_to_cpu(le->length); + length = le->length; + status = le->status; - switch (le->opcode & ~HW_OWNER) { + switch (opcode) { case OP_RXSTAT: skb = sky2_receive(sky2, length, status); if (!skb) @@ -1947,42 +1904,23 @@ static int sky2_poll(struct net_device *dev0, int *budget) case OP_TXINDEXLE: /* TX index reports status for both ports */ - tx_done[0] = status & 0xffff; - tx_done[1] = ((status >> 24) & 0xff) - | (u16)(length & 0xf) << 8; + sky2_tx_done(hw->dev[0], status & 0xffff); + if (hw->dev[1]) + sky2_tx_done(hw->dev[1], + ((status >> 24) & 0xff) + | (u16)(length & 0xf) << 8); break; default: if (net_ratelimit()) printk(KERN_WARNING PFX - "unknown status opcode 0x%x\n", le->opcode); + "unknown status opcode 0x%x\n", opcode); break; } } exit_loop: - sky2_tx_check(hw, 0, tx_done[0]); - sky2_tx_check(hw, 1, tx_done[1]); - - if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) { - sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); - sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); - } - - if (likely(work_done < to_do)) { - spin_lock_irq(&hw->hw_lock); - __netif_rx_complete(dev0); - - hw->intr_mask |= Y2_IS_STAT_BMU; - sky2_write32(hw, B0_IMSK, hw->intr_mask); - spin_unlock_irq(&hw->hw_lock); - - return 0; - } else { - *budget -= work_done; - dev0->quota -= work_done; - return 1; - } + return work_done; } static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) @@ -2101,42 +2039,17 @@ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) } } -static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) -{ - struct net_device *dev = hw->dev[port]; - struct sky2_port *sky2 = netdev_priv(dev); - - hw->intr_mask &= ~(port == 0 ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); - sky2_write32(hw, B0_IMSK, hw->intr_mask); - - schedule_work(&sky2->phy_task); -} -static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) +static int sky2_poll(struct net_device *dev0, int *budget) { - struct sky2_hw *hw = dev_id; - struct net_device *dev0 = hw->dev[0]; - u32 status; - - status = sky2_read32(hw, B0_Y2_SP_ISRC2); - if (status == 0 || status == ~0) - return IRQ_NONE; + struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; + int work_limit = min(dev0->quota, *budget); + int work_done = 0; + u32 status = sky2_read32(hw, B0_ISRC); - spin_lock(&hw->hw_lock); if (status & Y2_IS_HW_ERR) sky2_hw_intr(hw); - /* Do NAPI for Rx and Tx status */ - if (status & Y2_IS_STAT_BMU) { - hw->intr_mask &= ~Y2_IS_STAT_BMU; - sky2_write32(hw, B0_IMSK, hw->intr_mask); - - if (likely(__netif_rx_schedule_prep(dev0))) { - prefetch(&hw->st_le[hw->st_idx]); - __netif_rx_schedule(dev0); - } - } - if (status & Y2_IS_IRQ_PHY1) sky2_phy_intr(hw, 0); @@ -2149,9 +2062,38 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) if (status & Y2_IS_IRQ_MAC2) sky2_mac_intr(hw, 1); + if (status & Y2_IS_STAT_BMU) { + work_done = sky2_status_intr(hw, work_limit); + *budget -= work_done; + dev0->quota -= work_done; + + if (work_done >= work_limit) + return 1; + + sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); + } + + netif_rx_complete(dev0); + + /* Ack interrupt and re-enable */ sky2_write32(hw, B0_Y2_SP_ICR, 2); + return 0; +} + +static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct sky2_hw *hw = dev_id; + struct net_device *dev0 = hw->dev[0]; + u32 status; + + /* Reading this mask interrupts as side effect */ + status = sky2_read32(hw, B0_Y2_SP_ISRC2); + if (status == 0 || status == ~0) + return IRQ_NONE; - spin_unlock(&hw->hw_lock); + prefetch(&hw->st_le[hw->st_idx]); + if (likely(__netif_rx_schedule_prep(dev0))) + __netif_rx_schedule(dev0); return IRQ_HANDLED; } @@ -2320,7 +2262,6 @@ static int sky2_reset(struct sky2_hw *hw) /* Set the list last index */ sky2_write16(hw, STAT_LAST_IDX, STATUS_RING_SIZE - 1); - /* These status setup values are copied from SysKonnect's driver */ sky2_write16(hw, STAT_TX_IDX_TH, 10); sky2_write8(hw, STAT_FIFO_WM, 16); @@ -2714,7 +2655,7 @@ static int sky2_phys_id(struct net_device *dev, u32 data) ms = data * 1000; /* save initial values */ - down(&sky2->phy_sema); + spin_lock_bh(&sky2->phy_lock); if (hw->chip_id == CHIP_ID_YUKON_XL) { u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); @@ -2730,9 +2671,9 @@ static int sky2_phys_id(struct net_device *dev, u32 data) sky2_led(hw, port, onoff); onoff = !onoff; - up(&sky2->phy_sema); + spin_unlock_bh(&sky2->phy_lock); interrupted = msleep_interruptible(250); - down(&sky2->phy_sema); + spin_lock_bh(&sky2->phy_lock); ms -= 250; } @@ -2747,7 +2688,7 @@ static int sky2_phys_id(struct net_device *dev, u32 data) gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); } - up(&sky2->phy_sema); + spin_unlock_bh(&sky2->phy_lock); return 0; } @@ -3023,8 +2964,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, */ sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); - INIT_WORK(&sky2->phy_task, sky2_phy_task, sky2); - init_MUTEX(&sky2->phy_sema); + spin_lock_init(&sky2->phy_lock); sky2->tx_pending = TX_DEF_PENDING; sky2->rx_pending = RX_DEF_PENDING; sky2->rx_bufsize = sky2_buf_size(ETH_DATA_LEN); @@ -3136,7 +3076,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, goto err_out_free_hw; } hw->pm_cap = pm_cap; - spin_lock_init(&hw->hw_lock); #ifdef __BIG_ENDIAN /* byte swap descriptors in hardware */ @@ -3196,8 +3135,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, goto err_out_unregister; } - hw->intr_mask = Y2_IS_BASE; - sky2_write32(hw, B0_IMSK, hw->intr_mask); + sky2_write32(hw, B0_IMSK, Y2_IS_BASE); pci_set_drvdata(pdev, hw); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 2a23f3ad6d9f..db362b69b0bb 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -278,13 +278,9 @@ enum { Y2_IS_CHK_TXS1 = 1<<1, /* Descriptor error TXS 1 */ Y2_IS_CHK_TXA1 = 1<<0, /* Descriptor error TXA 1 */ - Y2_IS_BASE = Y2_IS_HW_ERR | Y2_IS_STAT_BMU | - Y2_IS_POLL_CHK | Y2_IS_TWSI_RDY | - Y2_IS_IRQ_SW | Y2_IS_TIMINT, - Y2_IS_PORT_1 = Y2_IS_IRQ_PHY1 | Y2_IS_IRQ_MAC1 | - Y2_IS_CHK_RX1 | Y2_IS_CHK_TXA1 | Y2_IS_CHK_TXS1, - Y2_IS_PORT_2 = Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2 | - Y2_IS_CHK_RX2 | Y2_IS_CHK_TXA2 | Y2_IS_CHK_TXS2, + Y2_IS_BASE = Y2_IS_HW_ERR | Y2_IS_STAT_BMU, + Y2_IS_PORT_1 = Y2_IS_IRQ_PHY1 | Y2_IS_IRQ_MAC1, + Y2_IS_PORT_2 = Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2, }; /* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ @@ -1832,6 +1828,7 @@ struct sky2_port { struct net_device *netdev; unsigned port; u32 msg_enable; + spinlock_t phy_lock; spinlock_t tx_lock ____cacheline_aligned_in_smp; struct tx_ring_info *tx_ring; @@ -1866,16 +1863,12 @@ struct sky2_port { struct net_device_stats net_stats; - struct work_struct phy_task; - struct semaphore phy_sema; }; struct sky2_hw { void __iomem *regs; struct pci_dev *pdev; struct net_device *dev[2]; - spinlock_t hw_lock; - u32 intr_mask; int pm_cap; u8 chip_id; -- cgit v1.2.3-59-g8ed1b From 77b3d6a2d56be5af87ffae5bb78a39c847d49f99 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 15:48:18 -0800 Subject: [PATCH] sky2: coalescing parameters Change default coalescing parameters slightly, and allow wider range of values. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 41dbe588de30..7e3353f55c38 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2272,7 +2272,8 @@ static int sky2_reset(struct sky2_hw *hw) sky2_write8(hw, STAT_FIFO_ISR_WM, 16); sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000)); - sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 7)); + sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 20)); + sky2_write32(hw, STAT_LEV_TIMER_INI, sky2_us2clk(hw, 100)); /* enable status unit */ sky2_write32(hw, STAT_CTRL, SC_STAT_OP_ON); @@ -2758,19 +2759,11 @@ static int sky2_set_coalesce(struct net_device *dev, { struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; - const u32 tmin = sky2_clk2us(hw, 1); - const u32 tmax = 5000; + const u32 tmax = sky2_clk2us(hw, 0x0ffffff); - if (ecmd->tx_coalesce_usecs != 0 && - (ecmd->tx_coalesce_usecs < tmin || ecmd->tx_coalesce_usecs > tmax)) - return -EINVAL; - - if (ecmd->rx_coalesce_usecs != 0 && - (ecmd->rx_coalesce_usecs < tmin || ecmd->rx_coalesce_usecs > tmax)) - return -EINVAL; - - if (ecmd->rx_coalesce_usecs_irq != 0 && - (ecmd->rx_coalesce_usecs_irq < tmin || ecmd->rx_coalesce_usecs_irq > tmax)) + if (ecmd->tx_coalesce_usecs > tmax || + ecmd->rx_coalesce_usecs > tmax || + ecmd->rx_coalesce_usecs_irq > tmax) return -EINVAL; if (ecmd->tx_max_coalesced_frames >= TX_RING_SIZE-1) -- cgit v1.2.3-59-g8ed1b From fb2690a9bfa330aff3de29cbdde526591ac90dce Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 15:48:19 -0800 Subject: [PATCH] sky2: add MSI support Add MSI support to sky2 driver. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++--- drivers/net/sky2.h | 2 ++ 2 files changed, 79 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 7e3353f55c38..2e29972b8d0b 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -92,6 +92,10 @@ static int copybreak __read_mostly = 256; module_param(copybreak, int, 0); MODULE_PARM_DESC(copybreak, "Receive copy threshold"); +static int disable_msi = 0; +module_param(disable_msi, int, 0); +MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); + static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, @@ -2045,7 +2049,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; int work_limit = min(dev0->quota, *budget); int work_done = 0; - u32 status = sky2_read32(hw, B0_ISRC); + u32 status = sky2_read32(hw, B0_Y2_SP_EISR); if (status & Y2_IS_HW_ERR) sky2_hw_intr(hw); @@ -2075,8 +2079,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) netif_rx_complete(dev0); - /* Ack interrupt and re-enable */ - sky2_write32(hw, B0_Y2_SP_ICR, 2); + status = sky2_read32(hw, B0_Y2_SP_LISR); return 0; } @@ -3001,6 +3004,66 @@ static void __devinit sky2_show_addr(struct net_device *dev) dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); } +/* Handle software interrupt used during MSI test */ +static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct sky2_hw *hw = dev_id; + u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2); + + if (status == 0) + return IRQ_NONE; + + if (status & Y2_IS_IRQ_SW) { + hw->msi_detected = 1; + wake_up(&hw->msi_wait); + sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); + } + sky2_write32(hw, B0_Y2_SP_ICR, 2); + + return IRQ_HANDLED; +} + +/* Test interrupt path by forcing a a software IRQ */ +static int __devinit sky2_test_msi(struct sky2_hw *hw) +{ + struct pci_dev *pdev = hw->pdev; + int err; + + sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); + + err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw); + if (err) { + printk(KERN_ERR PFX "%s: cannot assign irq %d\n", + pci_name(pdev), pdev->irq); + return err; + } + + init_waitqueue_head (&hw->msi_wait); + + sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); + wmb(); + + wait_event_timeout(hw->msi_wait, hw->msi_detected, HZ/10); + + if (!hw->msi_detected) { + /* MSI test failed, go back to INTx mode */ + printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, " + "switching to INTx mode. Please report this failure to " + "the PCI maintainer and include system chipset information.\n", + pci_name(pdev)); + + err = -EOPNOTSUPP; + sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); + } + + sky2_write32(hw, B0_IMSK, 0); + + free_irq(pdev->irq, hw); + + return err; +} + static int __devinit sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -3121,7 +3184,15 @@ static int __devinit sky2_probe(struct pci_dev *pdev, } } - err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw); + if (!disable_msi && pci_enable_msi(pdev) == 0) { + err = sky2_test_msi(hw); + if (err == -EOPNOTSUPP) + pci_disable_msi(pdev); + else if (err) + goto err_out_unregister; + } + + err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw); if (err) { printk(KERN_ERR PFX "%s: cannot assign irq %d\n", pci_name(pdev), pdev->irq); @@ -3135,6 +3206,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, return 0; err_out_unregister: + pci_disable_msi(pdev); if (dev1) { unregister_netdev(dev1); free_netdev(dev1); @@ -3177,6 +3249,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev) sky2_read8(hw, B0_CTST); free_irq(pdev->irq, hw); + pci_disable_msi(pdev); pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); pci_release_regions(pdev); pci_disable_device(pdev); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index db362b69b0bb..50e9f7d38bf3 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1879,6 +1879,8 @@ struct sky2_hw { struct sky2_status_le *st_le; u32 st_idx; dma_addr_t st_dma; + int msi_detected; + wait_queue_head_t msi_wait; }; /* Register accessor for memory mapped device */ -- cgit v1.2.3-59-g8ed1b From d89e1343959200a578465d50bb36c89733cf66a7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 15:48:20 -0800 Subject: [PATCH] sky2: whitespace fixes Small whitespace fixes. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 2e29972b8d0b..ffe3aa7e2ab2 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -852,7 +852,7 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!netif_running(dev)) return -ENODEV; /* Phy still in reset */ - switch(cmd) { + switch (cmd) { case SIOCGMIIPHY: data->phy_id = PHY_ADDR_MARV; @@ -1304,7 +1304,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) struct tx_ring_info *re = sky2->tx_ring + put; struct sk_buff *skb = re->skb; - nxt = re->idx; + nxt = re->idx; BUG_ON(nxt >= TX_RING_SIZE); prefetch(sky2->tx_ring + nxt); @@ -1320,7 +1320,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) struct tx_ring_info *fre; fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE; pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr), - skb_shinfo(skb)->frags[i].size, + skb_shinfo(skb)->frags[i].size, PCI_DMA_TODEVICE); } @@ -2187,7 +2187,7 @@ static int sky2_reset(struct sky2_hw *hw) sky2_write8(hw, B0_CTST, CS_MRST_CLR); /* clear any PEX errors */ - if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) + if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL); @@ -2954,7 +2954,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->speed = -1; sky2->advertising = sky2_supported_modes(hw); - /* Receive checksum disabled for Yukon XL + /* Receive checksum disabled for Yukon XL * because of observed problems with incorrect * values when multiple packets are received in one interrupt */ -- cgit v1.2.3-59-g8ed1b From 8f24664da64f8db094cd9d379b16fc1d8776d1df Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 15:48:21 -0800 Subject: [PATCH] sky2: transmit recovery This patch decodes state and revovers from any races in the transmit timeout and NAPI logic. It should never trigger, but if it does then do the right thing. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ffe3aa7e2ab2..ab36a7460a26 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1328,7 +1328,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) } sky2->tx_cons = put; - if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE) + if (tx_avail(sky2) > MAX_SKB_TX_LE) netif_wake_queue(dev); } @@ -1651,17 +1651,40 @@ static void sky2_tx_timeout(struct net_device *dev) struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; unsigned txq = txqaddr[sky2->port]; + u16 report, done; if (netif_msg_timer(sky2)) printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); - sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); - sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); + report = sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX); + done = sky2_read16(hw, Q_ADDR(txq, Q_DONE)); - sky2_tx_clean(sky2); + printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n", + dev->name, + sky2->tx_cons, sky2->tx_prod, report, done); + + if (report != done) { + printk(KERN_INFO PFX "status burst pending (irq moderation?)\n"); + + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); + } else if (report != sky2->tx_cons) { + printk(KERN_INFO PFX "status report lost?\n"); - sky2_qset(hw, txq); - sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1); + spin_lock_bh(&sky2->tx_lock); + sky2_tx_complete(sky2, report); + spin_unlock_bh(&sky2->tx_lock); + } else { + printk(KERN_INFO PFX "hardware hung? flushing\n"); + + sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); + sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); + + sky2_tx_clean(sky2); + + sky2_qset(hw, txq); + sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1); + } } @@ -2097,6 +2120,8 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) prefetch(&hw->st_le[hw->st_idx]); if (likely(__netif_rx_schedule_prep(dev0))) __netif_rx_schedule(dev0); + else + printk(KERN_DEBUG PFX "irq race detected\n"); return IRQ_HANDLED; } -- cgit v1.2.3-59-g8ed1b From d257924e85a81561a956f1791fa5a226e3a32ce1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 15:48:22 -0800 Subject: [PATCH] sky2: handle all error irqs The hardware has additional error trap interrupt bits. I have never seen them trigger, but if they do, it looks like this might be useful. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 55 ++++++++++++++++++++++++++++++++++++++++++++---------- drivers/net/sky2.h | 6 ++++-- 2 files changed, 49 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ab36a7460a26..380bb59f3517 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2066,6 +2066,27 @@ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) } } +/* This should never happen it is a fatal situation */ +static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, + const char *rxtx, u32 mask) +{ + struct net_device *dev = hw->dev[port]; + struct sky2_port *sky2 = netdev_priv(dev); + u32 imask; + + printk(KERN_ERR PFX "%s: %s descriptor error (hardware problem)\n", + dev ? dev->name : "", rxtx); + + imask = sky2_read32(hw, B0_IMSK); + imask &= ~mask; + sky2_write32(hw, B0_IMSK, imask); + + if (dev) { + spin_lock(&sky2->phy_lock); + sky2_link_down(sky2); + spin_unlock(&sky2->phy_lock); + } +} static int sky2_poll(struct net_device *dev0, int *budget) { @@ -2074,20 +2095,34 @@ static int sky2_poll(struct net_device *dev0, int *budget) int work_done = 0; u32 status = sky2_read32(hw, B0_Y2_SP_EISR); - if (status & Y2_IS_HW_ERR) - sky2_hw_intr(hw); + if (unlikely(status & ~Y2_IS_STAT_BMU)) { + if (status & Y2_IS_HW_ERR) + sky2_hw_intr(hw); + + if (status & Y2_IS_IRQ_PHY1) + sky2_phy_intr(hw, 0); - if (status & Y2_IS_IRQ_PHY1) - sky2_phy_intr(hw, 0); + if (status & Y2_IS_IRQ_PHY2) + sky2_phy_intr(hw, 1); - if (status & Y2_IS_IRQ_PHY2) - sky2_phy_intr(hw, 1); + if (status & Y2_IS_IRQ_MAC1) + sky2_mac_intr(hw, 0); - if (status & Y2_IS_IRQ_MAC1) - sky2_mac_intr(hw, 0); + if (status & Y2_IS_IRQ_MAC2) + sky2_mac_intr(hw, 1); - if (status & Y2_IS_IRQ_MAC2) - sky2_mac_intr(hw, 1); + if (status & Y2_IS_CHK_RX1) + sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); + + if (status & Y2_IS_CHK_RX2) + sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); + + if (status & Y2_IS_CHK_TXA1) + sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); + + if (status & Y2_IS_CHK_TXA2) + sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); + } if (status & Y2_IS_STAT_BMU) { work_done = sky2_status_intr(hw, work_limit); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 50e9f7d38bf3..d63cd5a1b71c 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -279,8 +279,10 @@ enum { Y2_IS_CHK_TXA1 = 1<<0, /* Descriptor error TXA 1 */ Y2_IS_BASE = Y2_IS_HW_ERR | Y2_IS_STAT_BMU, - Y2_IS_PORT_1 = Y2_IS_IRQ_PHY1 | Y2_IS_IRQ_MAC1, - Y2_IS_PORT_2 = Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2, + Y2_IS_PORT_1 = Y2_IS_IRQ_PHY1 | Y2_IS_IRQ_MAC1 + | Y2_IS_CHK_TXA1 | Y2_IS_CHK_RX1, + Y2_IS_PORT_2 = Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2 + | Y2_IS_CHK_TXA2 | Y2_IS_CHK_RX2, }; /* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ -- cgit v1.2.3-59-g8ed1b From 8368f31c8f51ef8ba61ce9fff7b94259777b6419 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 20 Mar 2006 15:48:23 -0800 Subject: [PATCH] sky2 version 1.1 Set version to 1.1 Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 380bb59f3517..f08fe6c884b2 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -51,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "0.15" +#define DRV_VERSION "1.1" #define PFX DRV_NAME " " /* -- cgit v1.2.3-59-g8ed1b From ac62ef043504d5c754357325cd514553ddabb046 Mon Sep 17 00:00:00 2001 From: Don Fry Date: Mon, 20 Mar 2006 15:26:03 -0800 Subject: [PATCH] pcnet32: support boards with multiple phys Boards with multiple PHYs were not being handled properly by the pcnet32 driver. This patch by Thomas Bogendoerfer with changes by me will allow Allied Telesyn 2700FTX and 2701FTX boards to use either the copper or the fiber interfaces. It has been tested on ia32 and ppc64 hardware. Philippe Seewer also tested and improved the patch. ethtool for pcnet32 already supports multiple phys. See also bugzilla bug 4219. Please apply to 2.6.16 Signed-off-by: Don Fry Signed-off-by: Jeff Garzik --- drivers/net/pcnet32.c | 236 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 212 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 7e900572eaf8..1bc3f5bffb95 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -22,8 +22,8 @@ *************************************************************************/ #define DRV_NAME "pcnet32" -#define DRV_VERSION "1.31c" -#define DRV_RELDATE "01.Nov.2005" +#define DRV_VERSION "1.32" +#define DRV_RELDATE "18.Mar.2006" #define PFX DRV_NAME ": " static const char * const version = @@ -133,7 +133,7 @@ static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = { }; #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN) -#define PCNET32_NUM_REGS 168 +#define PCNET32_NUM_REGS 136 #define MAX_UNITS 8 /* More are supported, limit only on options */ static int options[MAX_UNITS]; @@ -265,6 +265,9 @@ static int homepna[MAX_UNITS]; * v1.31c 01 Nov 2005 Don Fry Allied Telesyn 2700/2701 FX are 100Mbit only. * Force 100Mbit FD if Auto (ASEL) is selected. * See Bugzilla 2669 and 4551. + * v1.32 18 Mar2006 Thomas Bogendoerfer and Don Fry added Multi-Phy + * handling for supporting AT-270x FTX cards with FX and Tx PHYs. + * Philippe Seewer assisted with auto negotiation and testing. */ @@ -375,6 +378,7 @@ struct pcnet32_private { unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ struct net_device_stats stats; char tx_full; + char phycount; /* number of phys found */ int options; unsigned int shared_irq:1, /* shared irq possible */ dxsuflo:1, /* disable transmit stop on uflo */ @@ -384,6 +388,9 @@ struct pcnet32_private { struct timer_list watchdog_timer; struct timer_list blink_timer; u32 msg_enable; /* debug message level */ + + /* each bit indicates an available PHY */ + u32 phymask; }; static void pcnet32_probe_vlbus(void); @@ -415,6 +422,7 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, static void pcnet32_purge_tx_ring(struct net_device *dev); static int pcnet32_alloc_ring(struct net_device *dev, char *name); static void pcnet32_free_ring(struct net_device *dev); +static void pcnet32_check_media(struct net_device *dev, int verbose); enum pci_flags_bit { @@ -936,9 +944,14 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) return 0; } +#define PCNET32_REGS_PER_PHY 32 +#define PCNET32_MAX_PHYS 32 static int pcnet32_get_regs_len(struct net_device *dev) { - return(PCNET32_NUM_REGS * sizeof(u16)); + struct pcnet32_private *lp = dev->priv; + int j = lp->phycount * PCNET32_REGS_PER_PHY; + + return((PCNET32_NUM_REGS + j) * sizeof(u16)); } static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, @@ -998,9 +1011,14 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, /* read mii phy registers */ if (lp->mii) { - for (i=0; i<32; i++) { - lp->a.write_bcr(ioaddr, 33, ((lp->mii_if.phy_id) << 5) | i); - *buff++ = lp->a.read_bcr(ioaddr, 34); + int j; + for (j=0; jphymask & (1 << j)) { + for (i=0; ia.write_bcr(ioaddr, 33, (j << 5) | i); + *buff++ = lp->a.read_bcr(ioaddr, 34); + } + } } } @@ -1009,10 +1027,6 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, a->write_csr(ioaddr, 5, 0x0000); } - i = buff - (u16 *)ptr; - for (; i < PCNET32_NUM_REGS; i++) - *buff++ = 0; - spin_unlock_irqrestore(&lp->lock, flags); } @@ -1185,7 +1199,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) if (cards_found < MAX_UNITS && homepna[cards_found]) media |= 1; /* switch to home wiring mode */ if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_DEBUG PFX "media set to %sMbit mode.\n", + printk(KERN_DEBUG PFX "media set to %sMbit mode.\n", (media & 1) ? "1" : "10"); a->write_bcr(ioaddr, 49, media); break; @@ -1401,8 +1415,34 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) } /* Set the mii phy_id so that we can query the link state */ - if (lp->mii) + if (lp->mii) { + /* lp->phycount and lp->phymask are set to 0 by memset above */ + lp->mii_if.phy_id = ((lp->a.read_bcr (ioaddr, 33)) >> 5) & 0x1f; + /* scan for PHYs */ + for (i=0; iphycount++; + lp->phymask |= (1 << i); + lp->mii_if.phy_id = i; + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_INFO PFX "Found PHY %04x:%04x at address %d.\n", + id1, id2, i); + } + lp->a.write_bcr(ioaddr, 33, (lp->mii_if.phy_id) << 5); + if (lp->phycount > 1) { + lp->options |= PCNET32_PORT_MII; + } + } init_timer (&lp->watchdog_timer); lp->watchdog_timer.data = (unsigned long) dev; @@ -1625,7 +1665,7 @@ pcnet32_open(struct net_device *dev) dev->name); } } - { + if (lp->phycount < 2) { /* * 24 Jun 2004 according AMD, in order to change the PHY, * DANAS (or DISPM for 79C976) must be set; then select the speed, @@ -1651,6 +1691,62 @@ pcnet32_open(struct net_device *dev) lp->a.write_bcr(ioaddr, 32, val); } } + } else { + int first_phy = -1; + u16 bmcr; + u32 bcr9; + struct ethtool_cmd ecmd; + + /* + * There is really no good other way to handle multiple PHYs + * other than turning off all automatics + */ + val = lp->a.read_bcr(ioaddr, 2); + lp->a.write_bcr(ioaddr, 2, val & ~2); + val = lp->a.read_bcr(ioaddr, 32); + lp->a.write_bcr(ioaddr, 32, val & ~(1 << 7)); /* stop MII manager */ + + if (!(lp->options & PCNET32_PORT_ASEL)) { + /* setup ecmd */ + ecmd.port = PORT_MII; + ecmd.transceiver = XCVR_INTERNAL; + ecmd.autoneg = AUTONEG_DISABLE; + ecmd.speed = lp->options & PCNET32_PORT_100 ? SPEED_100 : SPEED_10; + bcr9 = lp->a.read_bcr(ioaddr, 9); + + if (lp->options & PCNET32_PORT_FD) { + ecmd.duplex = DUPLEX_FULL; + bcr9 |= (1 << 0); + } else { + ecmd.duplex = DUPLEX_HALF; + bcr9 |= ~(1 << 0); + } + lp->a.write_bcr(ioaddr, 9, bcr9); + } + + for (i=0; iphymask & (1 << i)) { + /* isolate all but the first PHY */ + bmcr = mdio_read(dev, i, MII_BMCR); + if (first_phy == -1) { + first_phy = i; + mdio_write(dev, i, MII_BMCR, bmcr & ~BMCR_ISOLATE); + } else { + mdio_write(dev, i, MII_BMCR, bmcr | BMCR_ISOLATE); + } + /* use mii_ethtool_sset to setup PHY */ + lp->mii_if.phy_id = i; + ecmd.phy_address = i; + if (lp->options & PCNET32_PORT_ASEL) { + mii_ethtool_gset(&lp->mii_if, &ecmd); + ecmd.autoneg = AUTONEG_ENABLE; + } + mii_ethtool_sset(&lp->mii_if, &ecmd); + } + } + lp->mii_if.phy_id = first_phy; + if (netif_msg_link(lp)) + printk(KERN_INFO "%s: Using PHY number %d.\n", dev->name, first_phy); } #ifdef DO_DXSUFLO @@ -1680,11 +1776,9 @@ pcnet32_open(struct net_device *dev) netif_start_queue(dev); - /* If we have mii, print the link status and start the watchdog */ - if (lp->mii) { - mii_check_media (&lp->mii_if, netif_msg_link(lp), 1); - mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); - } + /* Print the link status and start the watchdog */ + pcnet32_check_media (dev, 1); + mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); i = 0; while (i++ < 100) @@ -2430,17 +2524,111 @@ static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return rc; } +static int pcnet32_check_otherphy(struct net_device *dev) +{ + struct pcnet32_private *lp = dev->priv; + struct mii_if_info mii = lp->mii_if; + u16 bmcr; + int i; + + for (i = 0; i < PCNET32_MAX_PHYS; i++) { + if (i == lp->mii_if.phy_id) + continue; /* skip active phy */ + if (lp->phymask & (1 << i)) { + mii.phy_id = i; + if (mii_link_ok(&mii)) { + /* found PHY with active link */ + if (netif_msg_link(lp)) + printk(KERN_INFO "%s: Using PHY number %d.\n", dev->name, i); + + /* isolate inactive phy */ + bmcr = mdio_read(dev, lp->mii_if.phy_id, MII_BMCR); + mdio_write(dev, lp->mii_if.phy_id, MII_BMCR, bmcr | BMCR_ISOLATE); + + /* de-isolate new phy */ + bmcr = mdio_read(dev, i, MII_BMCR); + mdio_write(dev, i, MII_BMCR, bmcr & ~BMCR_ISOLATE); + + /* set new phy address */ + lp->mii_if.phy_id = i; + return 1; + } + } + } + return 0; +} + +/* + * Show the status of the media. Similar to mii_check_media however it + * correctly shows the link speed for all (tested) pcnet32 variants. + * Devices with no mii just report link state without speed. + * + * Caller is assumed to hold and release the lp->lock. + */ + +static void pcnet32_check_media(struct net_device *dev, int verbose) +{ + struct pcnet32_private *lp = dev->priv; + int curr_link; + int prev_link = netif_carrier_ok(dev) ? 1 : 0; + u32 bcr9; + + if (lp->mii) { + curr_link = mii_link_ok(&lp->mii_if); + } else { + ulong ioaddr = dev->base_addr; /* card base I/O address */ + curr_link = (lp->a.read_bcr(ioaddr, 4) != 0xc0); + } + if (!curr_link) { + if (prev_link || verbose) { + netif_carrier_off(dev); + if (netif_msg_link(lp)) + printk(KERN_INFO "%s: link down\n", dev->name); + } + if (lp->phycount > 1) { + curr_link = pcnet32_check_otherphy(dev); + prev_link = 0; + } + } else if (verbose || !prev_link) { + netif_carrier_on(dev); + if (lp->mii) { + if (netif_msg_link(lp)) { + struct ethtool_cmd ecmd; + mii_ethtool_gset(&lp->mii_if, &ecmd); + printk(KERN_INFO "%s: link up, %sMbps, %s-duplex\n", + dev->name, + (ecmd.speed == SPEED_100) ? "100" : "10", + (ecmd.duplex == DUPLEX_FULL) ? "full" : "half"); + } + bcr9 = lp->a.read_bcr(dev->base_addr, 9); + if ((bcr9 & (1 << 0)) != lp->mii_if.full_duplex) { + if (lp->mii_if.full_duplex) + bcr9 |= (1 << 0); + else + bcr9 &= ~(1 << 0); + lp->a.write_bcr(dev->base_addr, 9, bcr9); + } + } else { + if (netif_msg_link(lp)) + printk(KERN_INFO "%s: link up\n", dev->name); + } + } +} + +/* + * Check for loss of link and link establishment. + * Can not use mii_check_media because it does nothing if mode is forced. + */ + static void pcnet32_watchdog(struct net_device *dev) { struct pcnet32_private *lp = dev->priv; unsigned long flags; /* Print the link status if it has changed */ - if (lp->mii) { - spin_lock_irqsave(&lp->lock, flags); - mii_check_media (&lp->mii_if, netif_msg_link(lp), 0); - spin_unlock_irqrestore(&lp->lock, flags); - } + spin_lock_irqsave(&lp->lock, flags); + pcnet32_check_media(dev, 0); + spin_unlock_irqrestore(&lp->lock, flags); mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); } -- cgit v1.2.3-59-g8ed1b From 09779c6df2dbe95483269d194b327d41fe2cc57e Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 20 Mar 2006 11:54:27 -0500 Subject: [PATCH] smc91x: allow for dynamic bus access configs All accessor's different methods are now selected with C code and unused ones statically optimized away at compile time instead of being selected with #if's and #ifdef's. This has many advantages such as allowing the compiler to validate the syntax of the whole code, making it cleaner and easier to understand, and ultimately allowing people to define configuration symbols in terms of variables if they really want to dynamically support multiple bus configurations at the same time (with the unavoidable performance cost). Signed-off-by: Nicolas Pitre Signed-off-by: Jeff Garzik --- drivers/net/smc91x.c | 53 +++--- drivers/net/smc91x.h | 474 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 307 insertions(+), 220 deletions(-) (limited to 'drivers') diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 75e9b3b910cc..0e9833adf9fe 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -215,15 +215,12 @@ struct smc_local { spinlock_t lock; -#ifdef SMC_CAN_USE_DATACS - u32 __iomem *datacs; -#endif - #ifdef SMC_USE_PXA_DMA /* DMA needs the physical address of the chip */ u_long physaddr; #endif void __iomem *base; + void __iomem *datacs; }; #if SMC_DEBUG > 0 @@ -2104,9 +2101,8 @@ static int smc_enable_device(struct platform_device *pdev) * Set the appropriate byte/word mode. */ ecsr = readb(addr + (ECSR << SMC_IO_SHIFT)) & ~ECSR_IOIS8; -#ifndef SMC_CAN_USE_16BIT - ecsr |= ECSR_IOIS8; -#endif + if (!SMC_CAN_USE_16BIT) + ecsr |= ECSR_IOIS8; writeb(ecsr, addr + (ECSR << SMC_IO_SHIFT)); local_irq_restore(flags); @@ -2143,40 +2139,39 @@ static void smc_release_attrib(struct platform_device *pdev) release_mem_region(res->start, ATTRIB_SIZE); } -#ifdef SMC_CAN_USE_DATACS -static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) +static inline void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) { - struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32"); - struct smc_local *lp = netdev_priv(ndev); + if (SMC_CAN_USE_DATACS) { + struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32"); + struct smc_local *lp = netdev_priv(ndev); - if (!res) - return; + if (!res) + return; - if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) { - printk(KERN_INFO "%s: failed to request datacs memory region.\n", CARDNAME); - return; - } + if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) { + printk(KERN_INFO "%s: failed to request datacs memory region.\n", CARDNAME); + return; + } - lp->datacs = ioremap(res->start, SMC_DATA_EXTENT); + lp->datacs = ioremap(res->start, SMC_DATA_EXTENT); + } } static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev) { - struct smc_local *lp = netdev_priv(ndev); - struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32"); + if (SMC_CAN_USE_DATACS) { + struct smc_local *lp = netdev_priv(ndev); + struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32"); - if (lp->datacs) - iounmap(lp->datacs); + if (lp->datacs) + iounmap(lp->datacs); - lp->datacs = NULL; + lp->datacs = NULL; - if (res) - release_mem_region(res->start, SMC_DATA_EXTENT); + if (res) + release_mem_region(res->start, SMC_DATA_EXTENT); + } } -#else -static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) {} -static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev) {} -#endif /* * smc_init(void) diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index e0efd1964e72..e1be1af51201 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -275,7 +275,10 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_insw(a,r,p,l) readsw ((void*) ((a) + (r)), p, l) #define SMC_outw(v,a,r) ({ writew ((v), (a) + (r)); LPD7A40X_IOBARRIER; }) -static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) +#define SMC_outsw LPD7A40X_SMC_outsw + +static inline void LPD7A40X_SMC_outsw(unsigned long a, int r, + unsigned char* p, int l) { unsigned short* ps = (unsigned short*) p; while (l-- > 0) { @@ -342,10 +345,6 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) #endif -#ifndef SMC_IRQ_FLAGS -#define SMC_IRQ_FLAGS SA_TRIGGER_RISING -#endif - #ifdef SMC_USE_PXA_DMA /* * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is @@ -441,10 +440,85 @@ smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs) #endif /* SMC_USE_PXA_DMA */ -/* Because of bank switching, the LAN91x uses only 16 I/O ports */ +/* + * Everything a particular hardware setup needs should have been defined + * at this point. Add stubs for the undefined cases, mainly to avoid + * compilation warnings since they'll be optimized away, or to prevent buggy + * use of them. + */ + +#if ! SMC_CAN_USE_32BIT +#define SMC_inl(ioaddr, reg) ({ BUG(); 0; }) +#define SMC_outl(x, ioaddr, reg) BUG() +#define SMC_insl(a, r, p, l) BUG() +#define SMC_outsl(a, r, p, l) BUG() +#endif + +#if !defined(SMC_insl) || !defined(SMC_outsl) +#define SMC_insl(a, r, p, l) BUG() +#define SMC_outsl(a, r, p, l) BUG() +#endif + +#if ! SMC_CAN_USE_16BIT + +/* + * Any 16-bit access is performed with two 8-bit accesses if the hardware + * can't do it directly. Most registers are 16-bit so those are mandatory. + */ +#define SMC_outw(x, ioaddr, reg) \ + do { \ + unsigned int __val16 = (x); \ + SMC_outb( __val16, ioaddr, reg ); \ + SMC_outb( __val16 >> 8, ioaddr, reg + (1 << SMC_IO_SHIFT));\ + } while (0) +#define SMC_inw(ioaddr, reg) \ + ({ \ + unsigned int __val16; \ + __val16 = SMC_inb( ioaddr, reg ); \ + __val16 |= SMC_inb( ioaddr, reg + (1 << SMC_IO_SHIFT)) << 8; \ + __val16; \ + }) + +#define SMC_insw(a, r, p, l) BUG() +#define SMC_outsw(a, r, p, l) BUG() + +#endif + +#if !defined(SMC_insw) || !defined(SMC_outsw) +#define SMC_insw(a, r, p, l) BUG() +#define SMC_outsw(a, r, p, l) BUG() +#endif + +#if ! SMC_CAN_USE_8BIT +#define SMC_inb(ioaddr, reg) ({ BUG(); 0; }) +#define SMC_outb(x, ioaddr, reg) BUG() +#define SMC_insb(a, r, p, l) BUG() +#define SMC_outsb(a, r, p, l) BUG() +#endif + +#if !defined(SMC_insb) || !defined(SMC_outsb) +#define SMC_insb(a, r, p, l) BUG() +#define SMC_outsb(a, r, p, l) BUG() +#endif + +#ifndef SMC_CAN_USE_DATACS +#define SMC_CAN_USE_DATACS 0 +#endif + #ifndef SMC_IO_SHIFT #define SMC_IO_SHIFT 0 #endif + +#ifndef SMC_IRQ_FLAGS +#define SMC_IRQ_FLAGS SA_TRIGGER_RISING +#endif + +#ifndef SMC_INTERRUPT_PREAMBLE +#define SMC_INTERRUPT_PREAMBLE +#endif + + +/* Because of bank switching, the LAN91x uses only 16 I/O ports */ #define SMC_IO_EXTENT (16 << SMC_IO_SHIFT) #define SMC_DATA_EXTENT (4) @@ -817,6 +891,11 @@ static const char * chip_ids[ 16 ] = { * Note: the following macros do *not* select the bank -- this must * be done separately as needed in the main code. The SMC_REG() macro * only uses the bank argument for debugging purposes (when enabled). + * + * Note: despite inline functions being safer, everything leading to this + * should preferably be macros to let BUG() display the line number in + * the core source code since we're interested in the top call site + * not in any inline function location. */ #if SMC_DEBUG > 0 @@ -834,62 +913,142 @@ static const char * chip_ids[ 16 ] = { #define SMC_REG(reg, bank) (reg<> 8) -#define SMC_GET_TXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) & 0xFF) -#define SMC_GET_RXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) >> 8) -#define SMC_GET_INT() (SMC_inw( ioaddr, INT_REG ) & 0xFF) +/* + * Hack Alert: Some setups just can't write 8 or 16 bits reliably when not + * aligned to a 32 bit boundary. I tell you that does exist! + * Fortunately the affected register accesses can be easily worked around + * since we can write zeroes to the preceeding 16 bits without adverse + * effects and use a 32-bit access. + * + * Enforce it on any 32-bit capable setup for now. + */ +#define SMC_MUST_ALIGN_WRITE SMC_CAN_USE_32BIT + +#define SMC_GET_PN() \ + ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, PN_REG)) \ + : (SMC_inw(ioaddr, PN_REG) & 0xFF) ) + +#define SMC_SET_PN(x) \ + do { \ + if (SMC_MUST_ALIGN_WRITE) \ + SMC_outl((x)<<16, ioaddr, SMC_REG(0, 2)); \ + else if (SMC_CAN_USE_8BIT) \ + SMC_outb(x, ioaddr, PN_REG); \ + else \ + SMC_outw(x, ioaddr, PN_REG); \ + } while (0) + +#define SMC_GET_AR() \ + ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, AR_REG)) \ + : (SMC_inw(ioaddr, PN_REG) >> 8) ) + +#define SMC_GET_TXFIFO() \ + ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, TXFIFO_REG)) \ + : (SMC_inw(ioaddr, TXFIFO_REG) & 0xFF) ) + +#define SMC_GET_RXFIFO() \ + ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, RXFIFO_REG)) \ + : (SMC_inw(ioaddr, TXFIFO_REG) >> 8) ) + +#define SMC_GET_INT() \ + ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, INT_REG)) \ + : (SMC_inw(ioaddr, INT_REG) & 0xFF) ) + #define SMC_ACK_INT(x) \ do { \ - unsigned long __flags; \ - int __mask; \ - local_irq_save(__flags); \ - __mask = SMC_inw( ioaddr, INT_REG ) & ~0xff; \ - SMC_outw( __mask | (x), ioaddr, INT_REG ); \ - local_irq_restore(__flags); \ + if (SMC_CAN_USE_8BIT) \ + SMC_outb(x, ioaddr, INT_REG); \ + else { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_inw( ioaddr, INT_REG ) & ~0xff; \ + SMC_outw( __mask | (x), ioaddr, INT_REG ); \ + local_irq_restore(__flags); \ + } \ + } while (0) + +#define SMC_GET_INT_MASK() \ + ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, IM_REG)) \ + : (SMC_inw( ioaddr, INT_REG ) >> 8) ) + +#define SMC_SET_INT_MASK(x) \ + do { \ + if (SMC_CAN_USE_8BIT) \ + SMC_outb(x, ioaddr, IM_REG); \ + else \ + SMC_outw((x) << 8, ioaddr, INT_REG); \ + } while (0) + +#define SMC_CURRENT_BANK() SMC_inw(ioaddr, BANK_SELECT) + +#define SMC_SELECT_BANK(x) \ + do { \ + if (SMC_MUST_ALIGN_WRITE) \ + SMC_outl((x)<<16, ioaddr, 12<> 8) -#define SMC_SET_INT_MASK(x) SMC_outw( (x) << 8, ioaddr, INT_REG ) -#endif -#define SMC_CURRENT_BANK() SMC_inw( ioaddr, BANK_SELECT ) -#define SMC_SELECT_BANK(x) SMC_outw( x, ioaddr, BANK_SELECT ) -#define SMC_GET_BASE() SMC_inw( ioaddr, BASE_REG ) -#define SMC_SET_BASE(x) SMC_outw( x, ioaddr, BASE_REG ) -#define SMC_GET_CONFIG() SMC_inw( ioaddr, CONFIG_REG ) -#define SMC_SET_CONFIG(x) SMC_outw( x, ioaddr, CONFIG_REG ) -#define SMC_GET_COUNTER() SMC_inw( ioaddr, COUNTER_REG ) -#define SMC_GET_CTL() SMC_inw( ioaddr, CTL_REG ) -#define SMC_SET_CTL(x) SMC_outw( x, ioaddr, CTL_REG ) -#define SMC_GET_MII() SMC_inw( ioaddr, MII_REG ) -#define SMC_SET_MII(x) SMC_outw( x, ioaddr, MII_REG ) -#define SMC_GET_MIR() SMC_inw( ioaddr, MIR_REG ) -#define SMC_SET_MIR(x) SMC_outw( x, ioaddr, MIR_REG ) -#define SMC_GET_MMU_CMD() SMC_inw( ioaddr, MMU_CMD_REG ) -#define SMC_SET_MMU_CMD(x) SMC_outw( x, ioaddr, MMU_CMD_REG ) -#define SMC_GET_FIFO() SMC_inw( ioaddr, FIFO_REG ) -#define SMC_GET_PTR() SMC_inw( ioaddr, PTR_REG ) -#define SMC_SET_PTR(x) SMC_outw( x, ioaddr, PTR_REG ) -#define SMC_GET_EPH_STATUS() SMC_inw( ioaddr, EPH_STATUS_REG ) -#define SMC_GET_RCR() SMC_inw( ioaddr, RCR_REG ) -#define SMC_SET_RCR(x) SMC_outw( x, ioaddr, RCR_REG ) -#define SMC_GET_REV() SMC_inw( ioaddr, REV_REG ) -#define SMC_GET_RPC() SMC_inw( ioaddr, RPC_REG ) -#define SMC_SET_RPC(x) SMC_outw( x, ioaddr, RPC_REG ) -#define SMC_GET_TCR() SMC_inw( ioaddr, TCR_REG ) -#define SMC_SET_TCR(x) SMC_outw( x, ioaddr, TCR_REG ) +#define SMC_GET_EPH_STATUS() SMC_inw(ioaddr, EPH_STATUS_REG) + +#define SMC_GET_RCR() SMC_inw(ioaddr, RCR_REG) + +#define SMC_SET_RCR(x) SMC_outw(x, ioaddr, RCR_REG) + +#define SMC_GET_REV() SMC_inw(ioaddr, REV_REG) + +#define SMC_GET_RPC() SMC_inw(ioaddr, RPC_REG) + +#define SMC_SET_RPC(x) \ + do { \ + if (SMC_MUST_ALIGN_WRITE) \ + SMC_outl((x)<<16, ioaddr, SMC_REG(8, 0)); \ + else \ + SMC_outw(x, ioaddr, RPC_REG); \ + } while (0) + +#define SMC_GET_TCR() SMC_inw(ioaddr, TCR_REG) + +#define SMC_SET_TCR(x) SMC_outw(x, ioaddr, TCR_REG) #ifndef SMC_GET_MAC_ADDR #define SMC_GET_MAC_ADDR(addr) \ @@ -920,151 +1079,84 @@ static const char * chip_ids[ 16 ] = { SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 ); \ } while (0) -#if SMC_CAN_USE_32BIT -/* - * Some setups just can't write 8 or 16 bits reliably when not aligned - * to a 32 bit boundary. I tell you that exists! - * We re-do the ones here that can be easily worked around if they can have - * their low parts written to 0 without adverse effects. - */ -#undef SMC_SELECT_BANK -#define SMC_SELECT_BANK(x) SMC_outl( (x)<<16, ioaddr, 12<> 16; \ - } while (0) -#else #define SMC_PUT_PKT_HDR(status, length) \ do { \ - SMC_outw( status, ioaddr, DATA_REG ); \ - SMC_outw( length, ioaddr, DATA_REG ); \ - } while (0) -#define SMC_GET_PKT_HDR(status, length) \ - do { \ - (status) = SMC_inw( ioaddr, DATA_REG ); \ - (length) = SMC_inw( ioaddr, DATA_REG ); \ + if (SMC_CAN_USE_32BIT) \ + SMC_outl((status) | (length)<<16, ioaddr, DATA_REG); \ + else { \ + SMC_outw(status, ioaddr, DATA_REG); \ + SMC_outw(length, ioaddr, DATA_REG); \ + } \ } while (0) -#endif -#if SMC_CAN_USE_32BIT -#define _SMC_PUSH_DATA(p, l) \ +#define SMC_GET_PKT_HDR(status, length) \ do { \ - char *__ptr = (p); \ - int __len = (l); \ - if (__len >= 2 && (unsigned long)__ptr & 2) { \ - __len -= 2; \ - SMC_outw( *(u16 *)__ptr, ioaddr, DATA_REG ); \ - __ptr += 2; \ - } \ - SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2); \ - if (__len & 2) { \ - __ptr += (__len & ~3); \ - SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \ + if (SMC_CAN_USE_32BIT) { \ + unsigned int __val = SMC_inl(ioaddr, DATA_REG); \ + (status) = __val & 0xffff; \ + (length) = __val >> 16; \ + } else { \ + (status) = SMC_inw(ioaddr, DATA_REG); \ + (length) = SMC_inw(ioaddr, DATA_REG); \ } \ } while (0) -#define _SMC_PULL_DATA(p, l) \ - do { \ - char *__ptr = (p); \ - int __len = (l); \ - if ((unsigned long)__ptr & 2) { \ - /* \ - * We want 32bit alignment here. \ - * Since some buses perform a full 32bit \ - * fetch even for 16bit data we can't use \ - * SMC_inw() here. Back both source (on chip \ - * and destination) pointers of 2 bytes. \ - */ \ - __ptr -= 2; \ - __len += 2; \ - SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \ - } \ - __len += 2; \ - SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \ - } while (0) -#elif SMC_CAN_USE_16BIT -#define _SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 ) -#define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 ) -#elif SMC_CAN_USE_8BIT -#define _SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l ) -#define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l ) -#endif -#if ! SMC_CAN_USE_16BIT -#define SMC_outw(x, ioaddr, reg) \ +#define SMC_PUSH_DATA(p, l) \ do { \ - unsigned int __val16 = (x); \ - SMC_outb( __val16, ioaddr, reg ); \ - SMC_outb( __val16 >> 8, ioaddr, reg + (1 << SMC_IO_SHIFT));\ + if (SMC_CAN_USE_32BIT) { \ + void *__ptr = (p); \ + int __len = (l); \ + void *__ioaddr = ioaddr; \ + if (__len >= 2 && (unsigned long)__ptr & 2) { \ + __len -= 2; \ + SMC_outw(*(u16 *)__ptr, ioaddr, DATA_REG); \ + __ptr += 2; \ + } \ + if (SMC_CAN_USE_DATACS && lp->datacs) \ + __ioaddr = lp->datacs; \ + SMC_outsl(__ioaddr, DATA_REG, __ptr, __len>>2); \ + if (__len & 2) { \ + __ptr += (__len & ~3); \ + SMC_outw(*((u16 *)__ptr), ioaddr, DATA_REG); \ + } \ + } else if (SMC_CAN_USE_16BIT) \ + SMC_outsw(ioaddr, DATA_REG, p, (l) >> 1); \ + else if (SMC_CAN_USE_8BIT) \ + SMC_outsb(ioaddr, DATA_REG, p, l); \ } while (0) -#define SMC_inw(ioaddr, reg) \ - ({ \ - unsigned int __val16; \ - __val16 = SMC_inb( ioaddr, reg ); \ - __val16 |= SMC_inb( ioaddr, reg + (1 << SMC_IO_SHIFT)) << 8; \ - __val16; \ - }) -#endif - -#ifdef SMC_CAN_USE_DATACS -#define SMC_PUSH_DATA(p, l) \ - if ( lp->datacs ) { \ - unsigned char *__ptr = (p); \ - int __len = (l); \ - if (__len >= 2 && (unsigned long)__ptr & 2) { \ - __len -= 2; \ - SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \ - __ptr += 2; \ - } \ - outsl(lp->datacs, __ptr, __len >> 2); \ - if (__len & 2) { \ - __ptr += (__len & ~3); \ - SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \ - } \ - } else { \ - _SMC_PUSH_DATA(p, l); \ - } #define SMC_PULL_DATA(p, l) \ - if ( lp->datacs ) { \ - unsigned char *__ptr = (p); \ - int __len = (l); \ - if ((unsigned long)__ptr & 2) { \ - /* \ - * We want 32bit alignment here. \ - * Since some buses perform a full 32bit \ - * fetch even for 16bit data we can't use \ - * SMC_inw() here. Back both source (on chip \ - * and destination) pointers of 2 bytes. \ - */ \ - __ptr -= 2; \ + do { \ + if (SMC_CAN_USE_32BIT) { \ + void *__ptr = (p); \ + int __len = (l); \ + void *__ioaddr = ioaddr; \ + if ((unsigned long)__ptr & 2) { \ + /* \ + * We want 32bit alignment here. \ + * Since some buses perform a full \ + * 32bit fetch even for 16bit data \ + * we can't use SMC_inw() here. \ + * Back both source (on-chip) and \ + * destination pointers of 2 bytes. \ + * This is possible since the call to \ + * SMC_GET_PKT_HDR() already advanced \ + * the source pointer of 4 bytes, and \ + * the skb_reserve(skb, 2) advanced \ + * the destination pointer of 2 bytes. \ + */ \ + __ptr -= 2; \ + __len += 2; \ + SMC_SET_PTR(2|PTR_READ|PTR_RCV|PTR_AUTOINC); \ + } \ + if (SMC_CAN_USE_DATACS && lp->datacs) \ + __ioaddr = lp->datacs; \ __len += 2; \ - SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \ - } \ - __len += 2; \ - insl( lp->datacs, __ptr, __len >> 2); \ - } else { \ - _SMC_PULL_DATA(p, l); \ - } -#else -#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l) -#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l) -#endif - -#if !defined (SMC_INTERRUPT_PREAMBLE) -# define SMC_INTERRUPT_PREAMBLE -#endif + SMC_insl(__ioaddr, DATA_REG, __ptr, __len>>2); \ + } else if (SMC_CAN_USE_16BIT) \ + SMC_insw(ioaddr, DATA_REG, p, (l) >> 1); \ + else if (SMC_CAN_USE_8BIT) \ + SMC_insb(ioaddr, DATA_REG, p, l); \ + } while (0) #endif /* _SMC91X_H_ */ -- cgit v1.2.3-59-g8ed1b From 3d781a02313e9f22923ee919d99e1cf72fd1f468 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 16 Mar 2006 23:58:44 -0800 Subject: [PATCH] skfp warning fixes drivers/net/skfp/fplustm.c: In function `enable_formac': drivers/net/skfp/fplustm.c:552: warning: large integer implicitly truncated to unsigned type drivers/net/skfp/fplustm.c:555: warning: large integer implicitly truncated to unsigned type These arguments were changed to `const', so the compiler can now see that it's doing and outw(..., 0xffffnnnn). Cast the arg to ushort. Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/skfp/fplustm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c index a4b2b6975d6c..0784f558ca9a 100644 --- a/drivers/net/skfp/fplustm.c +++ b/drivers/net/skfp/fplustm.c @@ -549,12 +549,12 @@ void formac_tx_restart(struct s_smc *smc) static void enable_formac(struct s_smc *smc) { /* set formac IMSK : 0 enables irq */ - outpw(FM_A(FM_IMSK1U),~mac_imsk1u) ; - outpw(FM_A(FM_IMSK1L),~mac_imsk1l) ; - outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ; - outpw(FM_A(FM_IMSK2L),~mac_imsk2l) ; - outpw(FM_A(FM_IMSK3U),~mac_imsk3u) ; - outpw(FM_A(FM_IMSK3L),~mac_imsk3l) ; + outpw(FM_A(FM_IMSK1U),(unsigned short)~mac_imsk1u); + outpw(FM_A(FM_IMSK1L),(unsigned short)~mac_imsk1l); + outpw(FM_A(FM_IMSK2U),(unsigned short)~mac_imsk2u); + outpw(FM_A(FM_IMSK2L),(unsigned short)~mac_imsk2l); + outpw(FM_A(FM_IMSK3U),(unsigned short)~mac_imsk3u); + outpw(FM_A(FM_IMSK3L),(unsigned short)~mac_imsk3l); } #if 0 /* Removed because the driver should use the ASICs TX complete IRQ. */ -- cgit v1.2.3-59-g8ed1b From 4a5e8e296cfdeef18312c08199f25c00ec148f41 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 21 Mar 2006 16:15:44 -0500 Subject: [netdrvr] pcnet32: Lindent --- drivers/net/pcnet32.c | 4155 +++++++++++++++++++++++++------------------------ 1 file changed, 2156 insertions(+), 1999 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 1bc3f5bffb95..861361018640 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -26,8 +26,8 @@ #define DRV_RELDATE "18.Mar.2006" #define PFX DRV_NAME ": " -static const char * const version = -DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n"; +static const char *const version = + DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n"; #include #include @@ -58,18 +58,23 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n"; * PCI device identifiers for "new style" Linux PCI Device Drivers */ static struct pci_device_id pcnet32_pci_tbl[] = { - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* - * Adapters that were sold with IBM's RS/6000 or pSeries hardware have - * the incorrect vendor id. - */ - { PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0 }, - { 0, } + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + + /* + * Adapters that were sold with IBM's RS/6000 or pSeries hardware have + * the incorrect vendor id. + */ + { PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0}, + + { } /* terminate list */ }; -MODULE_DEVICE_TABLE (pci, pcnet32_pci_tbl); +MODULE_DEVICE_TABLE(pci, pcnet32_pci_tbl); static int cards_found; @@ -77,13 +82,11 @@ static int cards_found; * VLB I/O addresses */ static unsigned int pcnet32_portlist[] __initdata = - { 0x300, 0x320, 0x340, 0x360, 0 }; - - + { 0x300, 0x320, 0x340, 0x360, 0 }; static int pcnet32_debug = 0; -static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */ -static int pcnet32vlb; /* check for VLB cards ? */ +static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */ +static int pcnet32vlb; /* check for VLB cards ? */ static struct net_device *pcnet32_dev; @@ -110,32 +113,34 @@ static int rx_copybreak = 200; * to internal options */ static const unsigned char options_mapping[] = { - PCNET32_PORT_ASEL, /* 0 Auto-select */ - PCNET32_PORT_AUI, /* 1 BNC/AUI */ - PCNET32_PORT_AUI, /* 2 AUI/BNC */ - PCNET32_PORT_ASEL, /* 3 not supported */ - PCNET32_PORT_10BT | PCNET32_PORT_FD, /* 4 10baseT-FD */ - PCNET32_PORT_ASEL, /* 5 not supported */ - PCNET32_PORT_ASEL, /* 6 not supported */ - PCNET32_PORT_ASEL, /* 7 not supported */ - PCNET32_PORT_ASEL, /* 8 not supported */ - PCNET32_PORT_MII, /* 9 MII 10baseT */ - PCNET32_PORT_MII | PCNET32_PORT_FD, /* 10 MII 10baseT-FD */ - PCNET32_PORT_MII, /* 11 MII (autosel) */ - PCNET32_PORT_10BT, /* 12 10BaseT */ - PCNET32_PORT_MII | PCNET32_PORT_100, /* 13 MII 100BaseTx */ - PCNET32_PORT_MII | PCNET32_PORT_100 | PCNET32_PORT_FD, /* 14 MII 100BaseTx-FD */ - PCNET32_PORT_ASEL /* 15 not supported */ + PCNET32_PORT_ASEL, /* 0 Auto-select */ + PCNET32_PORT_AUI, /* 1 BNC/AUI */ + PCNET32_PORT_AUI, /* 2 AUI/BNC */ + PCNET32_PORT_ASEL, /* 3 not supported */ + PCNET32_PORT_10BT | PCNET32_PORT_FD, /* 4 10baseT-FD */ + PCNET32_PORT_ASEL, /* 5 not supported */ + PCNET32_PORT_ASEL, /* 6 not supported */ + PCNET32_PORT_ASEL, /* 7 not supported */ + PCNET32_PORT_ASEL, /* 8 not supported */ + PCNET32_PORT_MII, /* 9 MII 10baseT */ + PCNET32_PORT_MII | PCNET32_PORT_FD, /* 10 MII 10baseT-FD */ + PCNET32_PORT_MII, /* 11 MII (autosel) */ + PCNET32_PORT_10BT, /* 12 10BaseT */ + PCNET32_PORT_MII | PCNET32_PORT_100, /* 13 MII 100BaseTx */ + /* 14 MII 100BaseTx-FD */ + PCNET32_PORT_MII | PCNET32_PORT_100 | PCNET32_PORT_FD, + PCNET32_PORT_ASEL /* 15 not supported */ }; static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = { - "Loopback test (offline)" + "Loopback test (offline)" }; + #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN) #define PCNET32_NUM_REGS 136 -#define MAX_UNITS 8 /* More are supported, limit only on options */ +#define MAX_UNITS 8 /* More are supported, limit only on options */ static int options[MAX_UNITS]; static int full_duplex[MAX_UNITS]; static int homepna[MAX_UNITS]; @@ -270,7 +275,6 @@ static int homepna[MAX_UNITS]; * Philippe Seewer assisted with auto negotiation and testing. */ - /* * Set the number of Tx and Rx buffers, using Log_2(# buffers). * Reasonable default values are 4 Tx buffers, and 16 Rx buffers. @@ -306,42 +310,42 @@ static int homepna[MAX_UNITS]; /* The PCNET32 Rx and Tx ring descriptors. */ struct pcnet32_rx_head { - u32 base; - s16 buf_length; - s16 status; - u32 msg_length; - u32 reserved; + u32 base; + s16 buf_length; + s16 status; + u32 msg_length; + u32 reserved; }; struct pcnet32_tx_head { - u32 base; - s16 length; - s16 status; - u32 misc; - u32 reserved; + u32 base; + s16 length; + s16 status; + u32 misc; + u32 reserved; }; /* The PCNET32 32-Bit initialization block, described in databook. */ struct pcnet32_init_block { - u16 mode; - u16 tlen_rlen; - u8 phys_addr[6]; - u16 reserved; - u32 filter[2]; - /* Receive and transmit ring base, along with extra bits. */ - u32 rx_ring; - u32 tx_ring; + u16 mode; + u16 tlen_rlen; + u8 phys_addr[6]; + u16 reserved; + u32 filter[2]; + /* Receive and transmit ring base, along with extra bits. */ + u32 rx_ring; + u32 tx_ring; }; /* PCnet32 access functions */ struct pcnet32_access { - u16 (*read_csr)(unsigned long, int); - void (*write_csr)(unsigned long, int, u16); - u16 (*read_bcr)(unsigned long, int); - void (*write_bcr)(unsigned long, int, u16); - u16 (*read_rap)(unsigned long); - void (*write_rap)(unsigned long, u16); - void (*reset)(unsigned long); + u16 (*read_csr) (unsigned long, int); + void (*write_csr) (unsigned long, int, u16); + u16 (*read_bcr) (unsigned long, int); + void (*write_bcr) (unsigned long, int, u16); + u16 (*read_rap) (unsigned long); + void (*write_rap) (unsigned long, u16); + void (*reset) (unsigned long); }; /* @@ -349,771 +353,794 @@ struct pcnet32_access { * so the structure should be allocated using pci_alloc_consistent(). */ struct pcnet32_private { - struct pcnet32_init_block init_block; - /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */ - struct pcnet32_rx_head *rx_ring; - struct pcnet32_tx_head *tx_ring; - dma_addr_t dma_addr; /* DMA address of beginning of this - object, returned by - pci_alloc_consistent */ - struct pci_dev *pci_dev; /* Pointer to the associated pci device + struct pcnet32_init_block init_block; + /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */ + struct pcnet32_rx_head *rx_ring; + struct pcnet32_tx_head *tx_ring; + dma_addr_t dma_addr; /* DMA address of beginning of this + object, returned by + pci_alloc_consistent */ + struct pci_dev *pci_dev; /* Pointer to the associated pci device structure */ - const char *name; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct sk_buff **tx_skbuff; - struct sk_buff **rx_skbuff; - dma_addr_t *tx_dma_addr; - dma_addr_t *rx_dma_addr; - struct pcnet32_access a; - spinlock_t lock; /* Guard lock */ - unsigned int cur_rx, cur_tx; /* The next free ring entry */ - unsigned int rx_ring_size; /* current rx ring size */ - unsigned int tx_ring_size; /* current tx ring size */ - unsigned int rx_mod_mask; /* rx ring modular mask */ - unsigned int tx_mod_mask; /* tx ring modular mask */ - unsigned short rx_len_bits; - unsigned short tx_len_bits; - dma_addr_t rx_ring_dma_addr; - dma_addr_t tx_ring_dma_addr; - unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - struct net_device_stats stats; - char tx_full; - char phycount; /* number of phys found */ - int options; - unsigned int shared_irq:1, /* shared irq possible */ - dxsuflo:1, /* disable transmit stop on uflo */ - mii:1; /* mii port available */ - struct net_device *next; - struct mii_if_info mii_if; - struct timer_list watchdog_timer; - struct timer_list blink_timer; - u32 msg_enable; /* debug message level */ - - /* each bit indicates an available PHY */ - u32 phymask; + const char *name; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + struct sk_buff **tx_skbuff; + struct sk_buff **rx_skbuff; + dma_addr_t *tx_dma_addr; + dma_addr_t *rx_dma_addr; + struct pcnet32_access a; + spinlock_t lock; /* Guard lock */ + unsigned int cur_rx, cur_tx; /* The next free ring entry */ + unsigned int rx_ring_size; /* current rx ring size */ + unsigned int tx_ring_size; /* current tx ring size */ + unsigned int rx_mod_mask; /* rx ring modular mask */ + unsigned int tx_mod_mask; /* tx ring modular mask */ + unsigned short rx_len_bits; + unsigned short tx_len_bits; + dma_addr_t rx_ring_dma_addr; + dma_addr_t tx_ring_dma_addr; + unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + struct net_device_stats stats; + char tx_full; + char phycount; /* number of phys found */ + int options; + unsigned int shared_irq:1, /* shared irq possible */ + dxsuflo:1, /* disable transmit stop on uflo */ + mii:1; /* mii port available */ + struct net_device *next; + struct mii_if_info mii_if; + struct timer_list watchdog_timer; + struct timer_list blink_timer; + u32 msg_enable; /* debug message level */ + + /* each bit indicates an available PHY */ + u32 phymask; }; static void pcnet32_probe_vlbus(void); -static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); -static int pcnet32_probe1(unsigned long, int, struct pci_dev *); -static int pcnet32_open(struct net_device *); -static int pcnet32_init_ring(struct net_device *); -static int pcnet32_start_xmit(struct sk_buff *, struct net_device *); -static int pcnet32_rx(struct net_device *); -static void pcnet32_tx_timeout (struct net_device *dev); +static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); +static int pcnet32_probe1(unsigned long, int, struct pci_dev *); +static int pcnet32_open(struct net_device *); +static int pcnet32_init_ring(struct net_device *); +static int pcnet32_start_xmit(struct sk_buff *, struct net_device *); +static int pcnet32_rx(struct net_device *); +static void pcnet32_tx_timeout(struct net_device *dev); static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *); -static int pcnet32_close(struct net_device *); +static int pcnet32_close(struct net_device *); static struct net_device_stats *pcnet32_get_stats(struct net_device *); static void pcnet32_load_multicast(struct net_device *dev); static void pcnet32_set_multicast_list(struct net_device *); -static int pcnet32_ioctl(struct net_device *, struct ifreq *, int); +static int pcnet32_ioctl(struct net_device *, struct ifreq *, int); static void pcnet32_watchdog(struct net_device *); static int mdio_read(struct net_device *dev, int phy_id, int reg_num); -static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val); +static void mdio_write(struct net_device *dev, int phy_id, int reg_num, + int val); static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits); static void pcnet32_ethtool_test(struct net_device *dev, - struct ethtool_test *eth_test, u64 *data); -static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1); + struct ethtool_test *eth_test, u64 * data); +static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1); static int pcnet32_phys_id(struct net_device *dev, u32 data); static void pcnet32_led_blink_callback(struct net_device *dev); static int pcnet32_get_regs_len(struct net_device *dev); static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *ptr); + void *ptr); static void pcnet32_purge_tx_ring(struct net_device *dev); static int pcnet32_alloc_ring(struct net_device *dev, char *name); static void pcnet32_free_ring(struct net_device *dev); static void pcnet32_check_media(struct net_device *dev, int verbose); - enum pci_flags_bit { - PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, - PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, + PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4, + PCI_ADDR0 = 0x10 << 0, PCI_ADDR1 = 0x10 << 1, PCI_ADDR2 = + 0x10 << 2, PCI_ADDR3 = 0x10 << 3, }; - -static u16 pcnet32_wio_read_csr (unsigned long addr, int index) +static u16 pcnet32_wio_read_csr(unsigned long addr, int index) { - outw (index, addr+PCNET32_WIO_RAP); - return inw (addr+PCNET32_WIO_RDP); + outw(index, addr + PCNET32_WIO_RAP); + return inw(addr + PCNET32_WIO_RDP); } -static void pcnet32_wio_write_csr (unsigned long addr, int index, u16 val) +static void pcnet32_wio_write_csr(unsigned long addr, int index, u16 val) { - outw (index, addr+PCNET32_WIO_RAP); - outw (val, addr+PCNET32_WIO_RDP); + outw(index, addr + PCNET32_WIO_RAP); + outw(val, addr + PCNET32_WIO_RDP); } -static u16 pcnet32_wio_read_bcr (unsigned long addr, int index) +static u16 pcnet32_wio_read_bcr(unsigned long addr, int index) { - outw (index, addr+PCNET32_WIO_RAP); - return inw (addr+PCNET32_WIO_BDP); + outw(index, addr + PCNET32_WIO_RAP); + return inw(addr + PCNET32_WIO_BDP); } -static void pcnet32_wio_write_bcr (unsigned long addr, int index, u16 val) +static void pcnet32_wio_write_bcr(unsigned long addr, int index, u16 val) { - outw (index, addr+PCNET32_WIO_RAP); - outw (val, addr+PCNET32_WIO_BDP); + outw(index, addr + PCNET32_WIO_RAP); + outw(val, addr + PCNET32_WIO_BDP); } -static u16 pcnet32_wio_read_rap (unsigned long addr) +static u16 pcnet32_wio_read_rap(unsigned long addr) { - return inw (addr+PCNET32_WIO_RAP); + return inw(addr + PCNET32_WIO_RAP); } -static void pcnet32_wio_write_rap (unsigned long addr, u16 val) +static void pcnet32_wio_write_rap(unsigned long addr, u16 val) { - outw (val, addr+PCNET32_WIO_RAP); + outw(val, addr + PCNET32_WIO_RAP); } -static void pcnet32_wio_reset (unsigned long addr) +static void pcnet32_wio_reset(unsigned long addr) { - inw (addr+PCNET32_WIO_RESET); + inw(addr + PCNET32_WIO_RESET); } -static int pcnet32_wio_check (unsigned long addr) +static int pcnet32_wio_check(unsigned long addr) { - outw (88, addr+PCNET32_WIO_RAP); - return (inw (addr+PCNET32_WIO_RAP) == 88); + outw(88, addr + PCNET32_WIO_RAP); + return (inw(addr + PCNET32_WIO_RAP) == 88); } static struct pcnet32_access pcnet32_wio = { - .read_csr = pcnet32_wio_read_csr, - .write_csr = pcnet32_wio_write_csr, - .read_bcr = pcnet32_wio_read_bcr, - .write_bcr = pcnet32_wio_write_bcr, - .read_rap = pcnet32_wio_read_rap, - .write_rap = pcnet32_wio_write_rap, - .reset = pcnet32_wio_reset + .read_csr = pcnet32_wio_read_csr, + .write_csr = pcnet32_wio_write_csr, + .read_bcr = pcnet32_wio_read_bcr, + .write_bcr = pcnet32_wio_write_bcr, + .read_rap = pcnet32_wio_read_rap, + .write_rap = pcnet32_wio_write_rap, + .reset = pcnet32_wio_reset }; -static u16 pcnet32_dwio_read_csr (unsigned long addr, int index) +static u16 pcnet32_dwio_read_csr(unsigned long addr, int index) { - outl (index, addr+PCNET32_DWIO_RAP); - return (inl (addr+PCNET32_DWIO_RDP) & 0xffff); + outl(index, addr + PCNET32_DWIO_RAP); + return (inl(addr + PCNET32_DWIO_RDP) & 0xffff); } -static void pcnet32_dwio_write_csr (unsigned long addr, int index, u16 val) +static void pcnet32_dwio_write_csr(unsigned long addr, int index, u16 val) { - outl (index, addr+PCNET32_DWIO_RAP); - outl (val, addr+PCNET32_DWIO_RDP); + outl(index, addr + PCNET32_DWIO_RAP); + outl(val, addr + PCNET32_DWIO_RDP); } -static u16 pcnet32_dwio_read_bcr (unsigned long addr, int index) +static u16 pcnet32_dwio_read_bcr(unsigned long addr, int index) { - outl (index, addr+PCNET32_DWIO_RAP); - return (inl (addr+PCNET32_DWIO_BDP) & 0xffff); + outl(index, addr + PCNET32_DWIO_RAP); + return (inl(addr + PCNET32_DWIO_BDP) & 0xffff); } -static void pcnet32_dwio_write_bcr (unsigned long addr, int index, u16 val) +static void pcnet32_dwio_write_bcr(unsigned long addr, int index, u16 val) { - outl (index, addr+PCNET32_DWIO_RAP); - outl (val, addr+PCNET32_DWIO_BDP); + outl(index, addr + PCNET32_DWIO_RAP); + outl(val, addr + PCNET32_DWIO_BDP); } -static u16 pcnet32_dwio_read_rap (unsigned long addr) +static u16 pcnet32_dwio_read_rap(unsigned long addr) { - return (inl (addr+PCNET32_DWIO_RAP) & 0xffff); + return (inl(addr + PCNET32_DWIO_RAP) & 0xffff); } -static void pcnet32_dwio_write_rap (unsigned long addr, u16 val) +static void pcnet32_dwio_write_rap(unsigned long addr, u16 val) { - outl (val, addr+PCNET32_DWIO_RAP); + outl(val, addr + PCNET32_DWIO_RAP); } -static void pcnet32_dwio_reset (unsigned long addr) +static void pcnet32_dwio_reset(unsigned long addr) { - inl (addr+PCNET32_DWIO_RESET); + inl(addr + PCNET32_DWIO_RESET); } -static int pcnet32_dwio_check (unsigned long addr) +static int pcnet32_dwio_check(unsigned long addr) { - outl (88, addr+PCNET32_DWIO_RAP); - return ((inl (addr+PCNET32_DWIO_RAP) & 0xffff) == 88); + outl(88, addr + PCNET32_DWIO_RAP); + return ((inl(addr + PCNET32_DWIO_RAP) & 0xffff) == 88); } static struct pcnet32_access pcnet32_dwio = { - .read_csr = pcnet32_dwio_read_csr, - .write_csr = pcnet32_dwio_write_csr, - .read_bcr = pcnet32_dwio_read_bcr, - .write_bcr = pcnet32_dwio_write_bcr, - .read_rap = pcnet32_dwio_read_rap, - .write_rap = pcnet32_dwio_write_rap, - .reset = pcnet32_dwio_reset + .read_csr = pcnet32_dwio_read_csr, + .write_csr = pcnet32_dwio_write_csr, + .read_bcr = pcnet32_dwio_read_bcr, + .write_bcr = pcnet32_dwio_write_bcr, + .read_rap = pcnet32_dwio_read_rap, + .write_rap = pcnet32_dwio_write_rap, + .reset = pcnet32_dwio_reset }; #ifdef CONFIG_NET_POLL_CONTROLLER static void pcnet32_poll_controller(struct net_device *dev) { - disable_irq(dev->irq); - pcnet32_interrupt(0, dev, NULL); - enable_irq(dev->irq); + disable_irq(dev->irq); + pcnet32_interrupt(0, dev, NULL); + enable_irq(dev->irq); } #endif - static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct pcnet32_private *lp = dev->priv; - unsigned long flags; - int r = -EOPNOTSUPP; + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r = -EOPNOTSUPP; - if (lp->mii) { - spin_lock_irqsave(&lp->lock, flags); - mii_ethtool_gset(&lp->mii_if, cmd); - spin_unlock_irqrestore(&lp->lock, flags); - r = 0; - } - return r; + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); + mii_ethtool_gset(&lp->mii_if, cmd); + spin_unlock_irqrestore(&lp->lock, flags); + r = 0; + } + return r; } static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct pcnet32_private *lp = dev->priv; - unsigned long flags; - int r = -EOPNOTSUPP; + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r = -EOPNOTSUPP; - if (lp->mii) { - spin_lock_irqsave(&lp->lock, flags); - r = mii_ethtool_sset(&lp->mii_if, cmd); - spin_unlock_irqrestore(&lp->lock, flags); - } - return r; + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); + r = mii_ethtool_sset(&lp->mii_if, cmd); + spin_unlock_irqrestore(&lp->lock, flags); + } + return r; } -static void pcnet32_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +static void pcnet32_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) { - struct pcnet32_private *lp = dev->priv; - - strcpy (info->driver, DRV_NAME); - strcpy (info->version, DRV_VERSION); - if (lp->pci_dev) - strcpy (info->bus_info, pci_name(lp->pci_dev)); - else - sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr); + struct pcnet32_private *lp = dev->priv; + + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + if (lp->pci_dev) + strcpy(info->bus_info, pci_name(lp->pci_dev)); + else + sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr); } static u32 pcnet32_get_link(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - unsigned long flags; - int r; - - spin_lock_irqsave(&lp->lock, flags); - if (lp->mii) { - r = mii_link_ok(&lp->mii_if); - } else { - ulong ioaddr = dev->base_addr; /* card base I/O address */ - r = (lp->a.read_bcr(ioaddr, 4) != 0xc0); - } - spin_unlock_irqrestore(&lp->lock, flags); + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r; - return r; + spin_lock_irqsave(&lp->lock, flags); + if (lp->mii) { + r = mii_link_ok(&lp->mii_if); + } else { + ulong ioaddr = dev->base_addr; /* card base I/O address */ + r = (lp->a.read_bcr(ioaddr, 4) != 0xc0); + } + spin_unlock_irqrestore(&lp->lock, flags); + + return r; } static u32 pcnet32_get_msglevel(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - return lp->msg_enable; + struct pcnet32_private *lp = dev->priv; + return lp->msg_enable; } static void pcnet32_set_msglevel(struct net_device *dev, u32 value) { - struct pcnet32_private *lp = dev->priv; - lp->msg_enable = value; + struct pcnet32_private *lp = dev->priv; + lp->msg_enable = value; } static int pcnet32_nway_reset(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - unsigned long flags; - int r = -EOPNOTSUPP; + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r = -EOPNOTSUPP; - if (lp->mii) { - spin_lock_irqsave(&lp->lock, flags); - r = mii_nway_restart(&lp->mii_if); - spin_unlock_irqrestore(&lp->lock, flags); - } - return r; + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); + r = mii_nway_restart(&lp->mii_if); + spin_unlock_irqrestore(&lp->lock, flags); + } + return r; } -static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) +static void pcnet32_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = dev->priv; - ering->tx_max_pending = TX_MAX_RING_SIZE - 1; - ering->tx_pending = lp->tx_ring_size - 1; - ering->rx_max_pending = RX_MAX_RING_SIZE - 1; - ering->rx_pending = lp->rx_ring_size - 1; + ering->tx_max_pending = TX_MAX_RING_SIZE - 1; + ering->tx_pending = lp->tx_ring_size - 1; + ering->rx_max_pending = RX_MAX_RING_SIZE - 1; + ering->rx_pending = lp->rx_ring_size - 1; } -static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) +static int pcnet32_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) { - struct pcnet32_private *lp = dev->priv; - unsigned long flags; - int i; - - if (ering->rx_mini_pending || ering->rx_jumbo_pending) - return -EINVAL; - - if (netif_running(dev)) - pcnet32_close(dev); - - spin_lock_irqsave(&lp->lock, flags); - pcnet32_free_ring(dev); - lp->tx_ring_size = min(ering->tx_pending, (unsigned int) TX_MAX_RING_SIZE); - lp->rx_ring_size = min(ering->rx_pending, (unsigned int) RX_MAX_RING_SIZE); - - /* set the minimum ring size to 4, to allow the loopback test to work - * unchanged. - */ - for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) { - if (lp->tx_ring_size <= (1 << i)) - break; - } - lp->tx_ring_size = (1 << i); - lp->tx_mod_mask = lp->tx_ring_size - 1; - lp->tx_len_bits = (i << 12); - - for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) { - if (lp->rx_ring_size <= (1 << i)) - break; - } - lp->rx_ring_size = (1 << i); - lp->rx_mod_mask = lp->rx_ring_size - 1; - lp->rx_len_bits = (i << 4); - - if (pcnet32_alloc_ring(dev, dev->name)) { + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int i; + + if (ering->rx_mini_pending || ering->rx_jumbo_pending) + return -EINVAL; + + if (netif_running(dev)) + pcnet32_close(dev); + + spin_lock_irqsave(&lp->lock, flags); pcnet32_free_ring(dev); - spin_unlock_irqrestore(&lp->lock, flags); - return -ENOMEM; - } + lp->tx_ring_size = + min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE); + lp->rx_ring_size = + min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE); + + /* set the minimum ring size to 4, to allow the loopback test to work + * unchanged. + */ + for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) { + if (lp->tx_ring_size <= (1 << i)) + break; + } + lp->tx_ring_size = (1 << i); + lp->tx_mod_mask = lp->tx_ring_size - 1; + lp->tx_len_bits = (i << 12); - spin_unlock_irqrestore(&lp->lock, flags); + for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) { + if (lp->rx_ring_size <= (1 << i)) + break; + } + lp->rx_ring_size = (1 << i); + lp->rx_mod_mask = lp->rx_ring_size - 1; + lp->rx_len_bits = (i << 4); + + if (pcnet32_alloc_ring(dev, dev->name)) { + pcnet32_free_ring(dev); + spin_unlock_irqrestore(&lp->lock, flags); + return -ENOMEM; + } - if (pcnet32_debug & NETIF_MSG_DRV) - printk(KERN_INFO PFX "%s: Ring Param Settings: RX: %d, TX: %d\n", - dev->name, lp->rx_ring_size, lp->tx_ring_size); + spin_unlock_irqrestore(&lp->lock, flags); - if (netif_running(dev)) - pcnet32_open(dev); + if (pcnet32_debug & NETIF_MSG_DRV) + printk(KERN_INFO PFX + "%s: Ring Param Settings: RX: %d, TX: %d\n", dev->name, + lp->rx_ring_size, lp->tx_ring_size); - return 0; + if (netif_running(dev)) + pcnet32_open(dev); + + return 0; } -static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data) +static void pcnet32_get_strings(struct net_device *dev, u32 stringset, + u8 * data) { - memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test)); + memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test)); } static int pcnet32_self_test_count(struct net_device *dev) { - return PCNET32_TEST_LEN; + return PCNET32_TEST_LEN; } static void pcnet32_ethtool_test(struct net_device *dev, - struct ethtool_test *test, u64 *data) + struct ethtool_test *test, u64 * data) { - struct pcnet32_private *lp = dev->priv; - int rc; - - if (test->flags == ETH_TEST_FL_OFFLINE) { - rc = pcnet32_loopback_test(dev, data); - if (rc) { - if (netif_msg_hw(lp)) - printk(KERN_DEBUG "%s: Loopback test failed.\n", dev->name); - test->flags |= ETH_TEST_FL_FAILED; + struct pcnet32_private *lp = dev->priv; + int rc; + + if (test->flags == ETH_TEST_FL_OFFLINE) { + rc = pcnet32_loopback_test(dev, data); + if (rc) { + if (netif_msg_hw(lp)) + printk(KERN_DEBUG "%s: Loopback test failed.\n", + dev->name); + test->flags |= ETH_TEST_FL_FAILED; + } else if (netif_msg_hw(lp)) + printk(KERN_DEBUG "%s: Loopback test passed.\n", + dev->name); } else if (netif_msg_hw(lp)) - printk(KERN_DEBUG "%s: Loopback test passed.\n", dev->name); - } else if (netif_msg_hw(lp)) - printk(KERN_DEBUG "%s: No tests to run (specify 'Offline' on ethtool).", dev->name); -} /* end pcnet32_ethtool_test */ + printk(KERN_DEBUG + "%s: No tests to run (specify 'Offline' on ethtool).", + dev->name); +} /* end pcnet32_ethtool_test */ -static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1) +static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) { - struct pcnet32_private *lp = dev->priv; - struct pcnet32_access *a = &lp->a; /* access to registers */ - ulong ioaddr = dev->base_addr; /* card base I/O address */ - struct sk_buff *skb; /* sk buff */ - int x, i; /* counters */ - int numbuffs = 4; /* number of TX/RX buffers and descs */ - u16 status = 0x8300; /* TX ring status */ - u16 teststatus; /* test of ring status */ - int rc; /* return code */ - int size; /* size of packets */ - unsigned char *packet; /* source packet data */ - static const int data_len = 60; /* length of source packets */ - unsigned long flags; - unsigned long ticks; - - *data1 = 1; /* status of test, default to fail */ - rc = 1; /* default to fail */ - - if (netif_running(dev)) - pcnet32_close(dev); - - spin_lock_irqsave(&lp->lock, flags); - - /* Reset the PCNET32 */ - lp->a.reset (ioaddr); - - /* switch pcnet32 to 32bit mode */ - lp->a.write_bcr (ioaddr, 20, 2); - - lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); - lp->init_block.filter[0] = 0; - lp->init_block.filter[1] = 0; - - /* purge & init rings but don't actually restart */ - pcnet32_restart(dev, 0x0000); - - lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ - - /* Initialize Transmit buffers. */ - size = data_len + 15; - for (x=0; xname, __LINE__); - goto clean_up; - } else { - packet = skb->data; - skb_put(skb, size); /* create space for data */ - lp->tx_skbuff[x] = skb; - lp->tx_ring[x].length = le16_to_cpu(-skb->len); - lp->tx_ring[x].misc = 0; - - /* put DA and SA into the skb */ - for (i=0; i<6; i++) - *packet++ = dev->dev_addr[i]; - for (i=0; i<6; i++) - *packet++ = dev->dev_addr[i]; - /* type */ - *packet++ = 0x08; - *packet++ = 0x06; - /* packet number */ - *packet++ = x; - /* fill packet with data */ - for (i=0; itx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data, - skb->len, PCI_DMA_TODEVICE); - lp->tx_ring[x].base = (u32)le32_to_cpu(lp->tx_dma_addr[x]); - wmb(); /* Make sure owner changes after all others are visible */ - lp->tx_ring[x].status = le16_to_cpu(status); - } - } - - x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */ - x = x | 0x0002; - a->write_bcr(ioaddr, 32, x); - - lp->a.write_csr (ioaddr, 15, 0x0044); /* set int loopback in CSR15 */ - - teststatus = le16_to_cpu(0x8000); - lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */ - - /* Check status of descriptors */ - for (x=0; xrx_ring[x].status & teststatus) && (ticks < 200)) { - spin_unlock_irqrestore(&lp->lock, flags); - mdelay(1); - spin_lock_irqsave(&lp->lock, flags); - rmb(); - ticks++; - } - if (ticks == 200) { - if (netif_msg_hw(lp)) - printk("%s: Desc %d failed to reset!\n",dev->name,x); - break; - } - } - - lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ - wmb(); - if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) { - printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name); - - for (x=0; xname, x); - skb = lp->rx_skbuff[x]; - for (i=0; idata+i)); - } - printk("\n"); - } - } - - x = 0; - rc = 0; - while (xrx_skbuff[x]; - packet = lp->tx_skbuff[x]->data; - for (i=0; idata+i) != packet[i]) { - if (netif_msg_hw(lp)) - printk(KERN_DEBUG "%s: Error in compare! %2x - %02x %02x\n", - dev->name, i, *(skb->data+i), packet[i]); - rc = 1; - break; - } + struct pcnet32_private *lp = dev->priv; + struct pcnet32_access *a = &lp->a; /* access to registers */ + ulong ioaddr = dev->base_addr; /* card base I/O address */ + struct sk_buff *skb; /* sk buff */ + int x, i; /* counters */ + int numbuffs = 4; /* number of TX/RX buffers and descs */ + u16 status = 0x8300; /* TX ring status */ + u16 teststatus; /* test of ring status */ + int rc; /* return code */ + int size; /* size of packets */ + unsigned char *packet; /* source packet data */ + static const int data_len = 60; /* length of source packets */ + unsigned long flags; + unsigned long ticks; + + *data1 = 1; /* status of test, default to fail */ + rc = 1; /* default to fail */ + + if (netif_running(dev)) + pcnet32_close(dev); + + spin_lock_irqsave(&lp->lock, flags); + + /* Reset the PCNET32 */ + lp->a.reset(ioaddr); + + /* switch pcnet32 to 32bit mode */ + lp->a.write_bcr(ioaddr, 20, 2); + + lp->init_block.mode = + le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); + lp->init_block.filter[0] = 0; + lp->init_block.filter[1] = 0; + + /* purge & init rings but don't actually restart */ + pcnet32_restart(dev, 0x0000); + + lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ + + /* Initialize Transmit buffers. */ + size = data_len + 15; + for (x = 0; x < numbuffs; x++) { + if (!(skb = dev_alloc_skb(size))) { + if (netif_msg_hw(lp)) + printk(KERN_DEBUG + "%s: Cannot allocate skb at line: %d!\n", + dev->name, __LINE__); + goto clean_up; + } else { + packet = skb->data; + skb_put(skb, size); /* create space for data */ + lp->tx_skbuff[x] = skb; + lp->tx_ring[x].length = le16_to_cpu(-skb->len); + lp->tx_ring[x].misc = 0; + + /* put DA and SA into the skb */ + for (i = 0; i < 6; i++) + *packet++ = dev->dev_addr[i]; + for (i = 0; i < 6; i++) + *packet++ = dev->dev_addr[i]; + /* type */ + *packet++ = 0x08; + *packet++ = 0x06; + /* packet number */ + *packet++ = x; + /* fill packet with data */ + for (i = 0; i < data_len; i++) + *packet++ = i; + + lp->tx_dma_addr[x] = + pci_map_single(lp->pci_dev, skb->data, skb->len, + PCI_DMA_TODEVICE); + lp->tx_ring[x].base = + (u32) le32_to_cpu(lp->tx_dma_addr[x]); + wmb(); /* Make sure owner changes after all others are visible */ + lp->tx_ring[x].status = le16_to_cpu(status); + } } - x++; - } - if (!rc) { - *data1 = 0; - } -clean_up: - pcnet32_purge_tx_ring(dev); - x = a->read_csr(ioaddr, 15) & 0xFFFF; - a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */ + x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */ + x = x | 0x0002; + a->write_bcr(ioaddr, 32, x); + + lp->a.write_csr(ioaddr, 15, 0x0044); /* set int loopback in CSR15 */ + + teststatus = le16_to_cpu(0x8000); + lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */ + + /* Check status of descriptors */ + for (x = 0; x < numbuffs; x++) { + ticks = 0; + rmb(); + while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) { + spin_unlock_irqrestore(&lp->lock, flags); + mdelay(1); + spin_lock_irqsave(&lp->lock, flags); + rmb(); + ticks++; + } + if (ticks == 200) { + if (netif_msg_hw(lp)) + printk("%s: Desc %d failed to reset!\n", + dev->name, x); + break; + } + } + + lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ + wmb(); + if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) { + printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name); + + for (x = 0; x < numbuffs; x++) { + printk(KERN_DEBUG "%s: Packet %d:\n", dev->name, x); + skb = lp->rx_skbuff[x]; + for (i = 0; i < size; i++) { + printk("%02x ", *(skb->data + i)); + } + printk("\n"); + } + } - x = a->read_bcr(ioaddr, 32); /* reset internal loopback */ - x = x & ~0x0002; - a->write_bcr(ioaddr, 32, x); + x = 0; + rc = 0; + while (x < numbuffs && !rc) { + skb = lp->rx_skbuff[x]; + packet = lp->tx_skbuff[x]->data; + for (i = 0; i < size; i++) { + if (*(skb->data + i) != packet[i]) { + if (netif_msg_hw(lp)) + printk(KERN_DEBUG + "%s: Error in compare! %2x - %02x %02x\n", + dev->name, i, *(skb->data + i), + packet[i]); + rc = 1; + break; + } + } + x++; + } + if (!rc) { + *data1 = 0; + } - spin_unlock_irqrestore(&lp->lock, flags); + clean_up: + pcnet32_purge_tx_ring(dev); + x = a->read_csr(ioaddr, 15) & 0xFFFF; + a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */ - if (netif_running(dev)) { - pcnet32_open(dev); - } else { - lp->a.write_bcr (ioaddr, 20, 4); /* return to 16bit mode */ - } + x = a->read_bcr(ioaddr, 32); /* reset internal loopback */ + x = x & ~0x0002; + a->write_bcr(ioaddr, 32, x); - return(rc); -} /* end pcnet32_loopback_test */ + spin_unlock_irqrestore(&lp->lock, flags); + + if (netif_running(dev)) { + pcnet32_open(dev); + } else { + lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */ + } + + return (rc); +} /* end pcnet32_loopback_test */ static void pcnet32_led_blink_callback(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - struct pcnet32_access *a = &lp->a; - ulong ioaddr = dev->base_addr; - unsigned long flags; - int i; - - spin_lock_irqsave(&lp->lock, flags); - for (i=4; i<8; i++) { - a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000); - } - spin_unlock_irqrestore(&lp->lock, flags); - - mod_timer(&lp->blink_timer, PCNET32_BLINK_TIMEOUT); + struct pcnet32_private *lp = dev->priv; + struct pcnet32_access *a = &lp->a; + ulong ioaddr = dev->base_addr; + unsigned long flags; + int i; + + spin_lock_irqsave(&lp->lock, flags); + for (i = 4; i < 8; i++) { + a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000); + } + spin_unlock_irqrestore(&lp->lock, flags); + + mod_timer(&lp->blink_timer, PCNET32_BLINK_TIMEOUT); } static int pcnet32_phys_id(struct net_device *dev, u32 data) { - struct pcnet32_private *lp = dev->priv; - struct pcnet32_access *a = &lp->a; - ulong ioaddr = dev->base_addr; - unsigned long flags; - int i, regs[4]; - - if (!lp->blink_timer.function) { - init_timer(&lp->blink_timer); - lp->blink_timer.function = (void *) pcnet32_led_blink_callback; - lp->blink_timer.data = (unsigned long) dev; - } - - /* Save the current value of the bcrs */ - spin_lock_irqsave(&lp->lock, flags); - for (i=4; i<8; i++) { - regs[i-4] = a->read_bcr(ioaddr, i); - } - spin_unlock_irqrestore(&lp->lock, flags); - - mod_timer(&lp->blink_timer, jiffies); - set_current_state(TASK_INTERRUPTIBLE); - - if ((!data) || (data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - - msleep_interruptible(data * 1000); - del_timer_sync(&lp->blink_timer); - - /* Restore the original value of the bcrs */ - spin_lock_irqsave(&lp->lock, flags); - for (i=4; i<8; i++) { - a->write_bcr(ioaddr, i, regs[i-4]); - } - spin_unlock_irqrestore(&lp->lock, flags); - - return 0; + struct pcnet32_private *lp = dev->priv; + struct pcnet32_access *a = &lp->a; + ulong ioaddr = dev->base_addr; + unsigned long flags; + int i, regs[4]; + + if (!lp->blink_timer.function) { + init_timer(&lp->blink_timer); + lp->blink_timer.function = (void *)pcnet32_led_blink_callback; + lp->blink_timer.data = (unsigned long)dev; + } + + /* Save the current value of the bcrs */ + spin_lock_irqsave(&lp->lock, flags); + for (i = 4; i < 8; i++) { + regs[i - 4] = a->read_bcr(ioaddr, i); + } + spin_unlock_irqrestore(&lp->lock, flags); + + mod_timer(&lp->blink_timer, jiffies); + set_current_state(TASK_INTERRUPTIBLE); + + if ((!data) || (data > (u32) (MAX_SCHEDULE_TIMEOUT / HZ))) + data = (u32) (MAX_SCHEDULE_TIMEOUT / HZ); + + msleep_interruptible(data * 1000); + del_timer_sync(&lp->blink_timer); + + /* Restore the original value of the bcrs */ + spin_lock_irqsave(&lp->lock, flags); + for (i = 4; i < 8; i++) { + a->write_bcr(ioaddr, i, regs[i - 4]); + } + spin_unlock_irqrestore(&lp->lock, flags); + + return 0; } #define PCNET32_REGS_PER_PHY 32 #define PCNET32_MAX_PHYS 32 static int pcnet32_get_regs_len(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - int j = lp->phycount * PCNET32_REGS_PER_PHY; + struct pcnet32_private *lp = dev->priv; + int j = lp->phycount * PCNET32_REGS_PER_PHY; - return((PCNET32_NUM_REGS + j) * sizeof(u16)); + return ((PCNET32_NUM_REGS + j) * sizeof(u16)); } static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *ptr) + void *ptr) { - int i, csr0; - u16 *buff = ptr; - struct pcnet32_private *lp = dev->priv; - struct pcnet32_access *a = &lp->a; - ulong ioaddr = dev->base_addr; - int ticks; - unsigned long flags; - - spin_lock_irqsave(&lp->lock, flags); - - csr0 = a->read_csr(ioaddr, 0); - if (!(csr0 & 0x0004)) { /* If not stopped */ - /* set SUSPEND (SPND) - CSR5 bit 0 */ - a->write_csr(ioaddr, 5, 0x0001); - - /* poll waiting for bit to be set */ - ticks = 0; - while (!(a->read_csr(ioaddr, 5) & 0x0001)) { - spin_unlock_irqrestore(&lp->lock, flags); - mdelay(1); - spin_lock_irqsave(&lp->lock, flags); - ticks++; - if (ticks > 200) { - if (netif_msg_hw(lp)) - printk(KERN_DEBUG "%s: Error getting into suspend!\n", - dev->name); - break; - } - } - } - - /* read address PROM */ - for (i=0; i<16; i += 2) - *buff++ = inw(ioaddr + i); - - /* read control and status registers */ - for (i=0; i<90; i++) { - *buff++ = a->read_csr(ioaddr, i); - } - - *buff++ = a->read_csr(ioaddr, 112); - *buff++ = a->read_csr(ioaddr, 114); - - /* read bus configuration registers */ - for (i=0; i<30; i++) { - *buff++ = a->read_bcr(ioaddr, i); - } - *buff++ = 0; /* skip bcr30 so as not to hang 79C976 */ - for (i=31; i<36; i++) { - *buff++ = a->read_bcr(ioaddr, i); - } - - /* read mii phy registers */ - if (lp->mii) { - int j; - for (j=0; jphymask & (1 << j)) { - for (i=0; ia.write_bcr(ioaddr, 33, (j << 5) | i); - *buff++ = lp->a.read_bcr(ioaddr, 34); + int i, csr0; + u16 *buff = ptr; + struct pcnet32_private *lp = dev->priv; + struct pcnet32_access *a = &lp->a; + ulong ioaddr = dev->base_addr; + int ticks; + unsigned long flags; + + spin_lock_irqsave(&lp->lock, flags); + + csr0 = a->read_csr(ioaddr, 0); + if (!(csr0 & 0x0004)) { /* If not stopped */ + /* set SUSPEND (SPND) - CSR5 bit 0 */ + a->write_csr(ioaddr, 5, 0x0001); + + /* poll waiting for bit to be set */ + ticks = 0; + while (!(a->read_csr(ioaddr, 5) & 0x0001)) { + spin_unlock_irqrestore(&lp->lock, flags); + mdelay(1); + spin_lock_irqsave(&lp->lock, flags); + ticks++; + if (ticks > 200) { + if (netif_msg_hw(lp)) + printk(KERN_DEBUG + "%s: Error getting into suspend!\n", + dev->name); + break; + } } - } } - } - if (!(csr0 & 0x0004)) { /* If not stopped */ - /* clear SUSPEND (SPND) - CSR5 bit 0 */ - a->write_csr(ioaddr, 5, 0x0000); - } + /* read address PROM */ + for (i = 0; i < 16; i += 2) + *buff++ = inw(ioaddr + i); + + /* read control and status registers */ + for (i = 0; i < 90; i++) { + *buff++ = a->read_csr(ioaddr, i); + } + + *buff++ = a->read_csr(ioaddr, 112); + *buff++ = a->read_csr(ioaddr, 114); - spin_unlock_irqrestore(&lp->lock, flags); + /* read bus configuration registers */ + for (i = 0; i < 30; i++) { + *buff++ = a->read_bcr(ioaddr, i); + } + *buff++ = 0; /* skip bcr30 so as not to hang 79C976 */ + for (i = 31; i < 36; i++) { + *buff++ = a->read_bcr(ioaddr, i); + } + + /* read mii phy registers */ + if (lp->mii) { + int j; + for (j = 0; j < PCNET32_MAX_PHYS; j++) { + if (lp->phymask & (1 << j)) { + for (i = 0; i < PCNET32_REGS_PER_PHY; i++) { + lp->a.write_bcr(ioaddr, 33, + (j << 5) | i); + *buff++ = lp->a.read_bcr(ioaddr, 34); + } + } + } + } + + if (!(csr0 & 0x0004)) { /* If not stopped */ + /* clear SUSPEND (SPND) - CSR5 bit 0 */ + a->write_csr(ioaddr, 5, 0x0000); + } + + spin_unlock_irqrestore(&lp->lock, flags); } static struct ethtool_ops pcnet32_ethtool_ops = { - .get_settings = pcnet32_get_settings, - .set_settings = pcnet32_set_settings, - .get_drvinfo = pcnet32_get_drvinfo, - .get_msglevel = pcnet32_get_msglevel, - .set_msglevel = pcnet32_set_msglevel, - .nway_reset = pcnet32_nway_reset, - .get_link = pcnet32_get_link, - .get_ringparam = pcnet32_get_ringparam, - .set_ringparam = pcnet32_set_ringparam, - .get_tx_csum = ethtool_op_get_tx_csum, - .get_sg = ethtool_op_get_sg, - .get_tso = ethtool_op_get_tso, - .get_strings = pcnet32_get_strings, - .self_test_count = pcnet32_self_test_count, - .self_test = pcnet32_ethtool_test, - .phys_id = pcnet32_phys_id, - .get_regs_len = pcnet32_get_regs_len, - .get_regs = pcnet32_get_regs, - .get_perm_addr = ethtool_op_get_perm_addr, + .get_settings = pcnet32_get_settings, + .set_settings = pcnet32_set_settings, + .get_drvinfo = pcnet32_get_drvinfo, + .get_msglevel = pcnet32_get_msglevel, + .set_msglevel = pcnet32_set_msglevel, + .nway_reset = pcnet32_nway_reset, + .get_link = pcnet32_get_link, + .get_ringparam = pcnet32_get_ringparam, + .set_ringparam = pcnet32_set_ringparam, + .get_tx_csum = ethtool_op_get_tx_csum, + .get_sg = ethtool_op_get_sg, + .get_tso = ethtool_op_get_tso, + .get_strings = pcnet32_get_strings, + .self_test_count = pcnet32_self_test_count, + .self_test = pcnet32_ethtool_test, + .phys_id = pcnet32_phys_id, + .get_regs_len = pcnet32_get_regs_len, + .get_regs = pcnet32_get_regs, + .get_perm_addr = ethtool_op_get_perm_addr, }; /* only probes for non-PCI devices, the rest are handled by * pci_register_driver via pcnet32_probe_pci */ -static void __devinit -pcnet32_probe_vlbus(void) +static void __devinit pcnet32_probe_vlbus(void) { - unsigned int *port, ioaddr; - - /* search for PCnet32 VLB cards at known addresses */ - for (port = pcnet32_portlist; (ioaddr = *port); port++) { - if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_vlbus")) { - /* check if there is really a pcnet chip on that ioaddr */ - if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57)) { - pcnet32_probe1(ioaddr, 0, NULL); - } else { - release_region(ioaddr, PCNET32_TOTAL_SIZE); - } - } - } + unsigned int *port, ioaddr; + + /* search for PCnet32 VLB cards at known addresses */ + for (port = pcnet32_portlist; (ioaddr = *port); port++) { + if (request_region + (ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_vlbus")) { + /* check if there is really a pcnet chip on that ioaddr */ + if ((inb(ioaddr + 14) == 0x57) + && (inb(ioaddr + 15) == 0x57)) { + pcnet32_probe1(ioaddr, 0, NULL); + } else { + release_region(ioaddr, PCNET32_TOTAL_SIZE); + } + } + } } - static int __devinit pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) { - unsigned long ioaddr; - int err; - - err = pci_enable_device(pdev); - if (err < 0) { - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "failed to enable device -- err=%d\n", err); - return err; - } - pci_set_master(pdev); + unsigned long ioaddr; + int err; + + err = pci_enable_device(pdev); + if (err < 0) { + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_ERR PFX + "failed to enable device -- err=%d\n", err); + return err; + } + pci_set_master(pdev); + + ioaddr = pci_resource_start(pdev, 0); + if (!ioaddr) { + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_ERR PFX + "card has no PCI IO resources, aborting\n"); + return -ENODEV; + } - ioaddr = pci_resource_start (pdev, 0); - if (!ioaddr) { - if (pcnet32_debug & NETIF_MSG_PROBE) - printk (KERN_ERR PFX "card has no PCI IO resources, aborting\n"); - return -ENODEV; - } + if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) { + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_ERR PFX + "architecture does not support 32bit PCI busmaster DMA\n"); + return -ENODEV; + } + if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci") == + NULL) { + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_ERR PFX + "io address range already allocated\n"); + return -EBUSY; + } - if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) { - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "architecture does not support 32bit PCI busmaster DMA\n"); - return -ENODEV; - } - if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci") == NULL) { - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "io address range already allocated\n"); - return -EBUSY; - } - - err = pcnet32_probe1(ioaddr, 1, pdev); - if (err < 0) { - pci_disable_device(pdev); - } - return err; + err = pcnet32_probe1(ioaddr, 1, pdev); + if (err < 0) { + pci_disable_device(pdev); + } + return err; } - /* pcnet32_probe1 * Called from both pcnet32_probe_vlbus and pcnet_probe_pci. * pdev will be NULL when called from pcnet32_probe_vlbus. @@ -1121,710 +1148,764 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) static int __devinit pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) { - struct pcnet32_private *lp; - dma_addr_t lp_dma_addr; - int i, media; - int fdx, mii, fset, dxsuflo; - int chip_version; - char *chipname; - struct net_device *dev; - struct pcnet32_access *a = NULL; - u8 promaddr[6]; - int ret = -ENODEV; - - /* reset the chip */ - pcnet32_wio_reset(ioaddr); - - /* NOTE: 16-bit check is first, otherwise some older PCnet chips fail */ - if (pcnet32_wio_read_csr(ioaddr, 0) == 4 && pcnet32_wio_check(ioaddr)) { - a = &pcnet32_wio; - } else { - pcnet32_dwio_reset(ioaddr); - if (pcnet32_dwio_read_csr(ioaddr, 0) == 4 && pcnet32_dwio_check(ioaddr)) { - a = &pcnet32_dwio; - } else - goto err_release_region; - } - - chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16); - if ((pcnet32_debug & NETIF_MSG_PROBE) && (pcnet32_debug & NETIF_MSG_HW)) - printk(KERN_INFO " PCnet chip version is %#x.\n", chip_version); - if ((chip_version & 0xfff) != 0x003) { - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_INFO PFX "Unsupported chip version.\n"); - goto err_release_region; - } - - /* initialize variables */ - fdx = mii = fset = dxsuflo = 0; - chip_version = (chip_version >> 12) & 0xffff; - - switch (chip_version) { - case 0x2420: - chipname = "PCnet/PCI 79C970"; /* PCI */ - break; - case 0x2430: - if (shared) - chipname = "PCnet/PCI 79C970"; /* 970 gives the wrong chip id back */ - else - chipname = "PCnet/32 79C965"; /* 486/VL bus */ - break; - case 0x2621: - chipname = "PCnet/PCI II 79C970A"; /* PCI */ - fdx = 1; - break; - case 0x2623: - chipname = "PCnet/FAST 79C971"; /* PCI */ - fdx = 1; mii = 1; fset = 1; - break; - case 0x2624: - chipname = "PCnet/FAST+ 79C972"; /* PCI */ - fdx = 1; mii = 1; fset = 1; - break; - case 0x2625: - chipname = "PCnet/FAST III 79C973"; /* PCI */ - fdx = 1; mii = 1; - break; - case 0x2626: - chipname = "PCnet/Home 79C978"; /* PCI */ - fdx = 1; + struct pcnet32_private *lp; + dma_addr_t lp_dma_addr; + int i, media; + int fdx, mii, fset, dxsuflo; + int chip_version; + char *chipname; + struct net_device *dev; + struct pcnet32_access *a = NULL; + u8 promaddr[6]; + int ret = -ENODEV; + + /* reset the chip */ + pcnet32_wio_reset(ioaddr); + + /* NOTE: 16-bit check is first, otherwise some older PCnet chips fail */ + if (pcnet32_wio_read_csr(ioaddr, 0) == 4 && pcnet32_wio_check(ioaddr)) { + a = &pcnet32_wio; + } else { + pcnet32_dwio_reset(ioaddr); + if (pcnet32_dwio_read_csr(ioaddr, 0) == 4 + && pcnet32_dwio_check(ioaddr)) { + a = &pcnet32_dwio; + } else + goto err_release_region; + } + + chip_version = + a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr, 89) << 16); + if ((pcnet32_debug & NETIF_MSG_PROBE) && (pcnet32_debug & NETIF_MSG_HW)) + printk(KERN_INFO " PCnet chip version is %#x.\n", + chip_version); + if ((chip_version & 0xfff) != 0x003) { + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_INFO PFX "Unsupported chip version.\n"); + goto err_release_region; + } + + /* initialize variables */ + fdx = mii = fset = dxsuflo = 0; + chip_version = (chip_version >> 12) & 0xffff; + + switch (chip_version) { + case 0x2420: + chipname = "PCnet/PCI 79C970"; /* PCI */ + break; + case 0x2430: + if (shared) + chipname = "PCnet/PCI 79C970"; /* 970 gives the wrong chip id back */ + else + chipname = "PCnet/32 79C965"; /* 486/VL bus */ + break; + case 0x2621: + chipname = "PCnet/PCI II 79C970A"; /* PCI */ + fdx = 1; + break; + case 0x2623: + chipname = "PCnet/FAST 79C971"; /* PCI */ + fdx = 1; + mii = 1; + fset = 1; + break; + case 0x2624: + chipname = "PCnet/FAST+ 79C972"; /* PCI */ + fdx = 1; + mii = 1; + fset = 1; + break; + case 0x2625: + chipname = "PCnet/FAST III 79C973"; /* PCI */ + fdx = 1; + mii = 1; + break; + case 0x2626: + chipname = "PCnet/Home 79C978"; /* PCI */ + fdx = 1; + /* + * This is based on specs published at www.amd.com. This section + * assumes that a card with a 79C978 wants to go into standard + * ethernet mode. The 79C978 can also go into 1Mb HomePNA mode, + * and the module option homepna=1 can select this instead. + */ + media = a->read_bcr(ioaddr, 49); + media &= ~3; /* default to 10Mb ethernet */ + if (cards_found < MAX_UNITS && homepna[cards_found]) + media |= 1; /* switch to home wiring mode */ + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_DEBUG PFX "media set to %sMbit mode.\n", + (media & 1) ? "1" : "10"); + a->write_bcr(ioaddr, 49, media); + break; + case 0x2627: + chipname = "PCnet/FAST III 79C975"; /* PCI */ + fdx = 1; + mii = 1; + break; + case 0x2628: + chipname = "PCnet/PRO 79C976"; + fdx = 1; + mii = 1; + break; + default: + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_INFO PFX + "PCnet version %#x, no PCnet32 chip.\n", + chip_version); + goto err_release_region; + } + /* - * This is based on specs published at www.amd.com. This section - * assumes that a card with a 79C978 wants to go into standard - * ethernet mode. The 79C978 can also go into 1Mb HomePNA mode, - * and the module option homepna=1 can select this instead. + * On selected chips turn on the BCR18:NOUFLO bit. This stops transmit + * starting until the packet is loaded. Strike one for reliability, lose + * one for latency - although on PCI this isnt a big loss. Older chips + * have FIFO's smaller than a packet, so you can't do this. + * Turn on BCR18:BurstRdEn and BCR18:BurstWrEn. */ - media = a->read_bcr(ioaddr, 49); - media &= ~3; /* default to 10Mb ethernet */ - if (cards_found < MAX_UNITS && homepna[cards_found]) - media |= 1; /* switch to home wiring mode */ - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_DEBUG PFX "media set to %sMbit mode.\n", - (media & 1) ? "1" : "10"); - a->write_bcr(ioaddr, 49, media); - break; - case 0x2627: - chipname = "PCnet/FAST III 79C975"; /* PCI */ - fdx = 1; mii = 1; - break; - case 0x2628: - chipname = "PCnet/PRO 79C976"; - fdx = 1; mii = 1; - break; - default: - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_INFO PFX "PCnet version %#x, no PCnet32 chip.\n", - chip_version); - goto err_release_region; - } - - /* - * On selected chips turn on the BCR18:NOUFLO bit. This stops transmit - * starting until the packet is loaded. Strike one for reliability, lose - * one for latency - although on PCI this isnt a big loss. Older chips - * have FIFO's smaller than a packet, so you can't do this. - * Turn on BCR18:BurstRdEn and BCR18:BurstWrEn. - */ - - if (fset) { - a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0860)); - a->write_csr(ioaddr, 80, (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00); - dxsuflo = 1; - } - - dev = alloc_etherdev(0); - if (!dev) { + + if (fset) { + a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0860)); + a->write_csr(ioaddr, 80, + (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00); + dxsuflo = 1; + } + + dev = alloc_etherdev(0); + if (!dev) { + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_ERR PFX "Memory allocation failed.\n"); + ret = -ENOMEM; + goto err_release_region; + } + SET_NETDEV_DEV(dev, &pdev->dev); + if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Memory allocation failed.\n"); - ret = -ENOMEM; - goto err_release_region; - } - SET_NETDEV_DEV(dev, &pdev->dev); - - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr); - - /* In most chips, after a chip reset, the ethernet address is read from the - * station address PROM at the base address and programmed into the - * "Physical Address Registers" CSR12-14. - * As a precautionary measure, we read the PROM values and complain if - * they disagree with the CSRs. Either way, we use the CSR values, and - * double check that they are valid. - */ - for (i = 0; i < 3; i++) { - unsigned int val; - val = a->read_csr(ioaddr, i+12) & 0x0ffff; - /* There may be endianness issues here. */ - dev->dev_addr[2*i] = val & 0x0ff; - dev->dev_addr[2*i+1] = (val >> 8) & 0x0ff; - } - - /* read PROM address and compare with CSR address */ - for (i = 0; i < 6; i++) - promaddr[i] = inb(ioaddr + i); - - if (memcmp(promaddr, dev->dev_addr, 6) - || !is_valid_ether_addr(dev->dev_addr)) { - if (is_valid_ether_addr(promaddr)) { - if (pcnet32_debug & NETIF_MSG_PROBE) { - printk(" warning: CSR address invalid,\n"); - printk(KERN_INFO " using instead PROM address of"); - } - memcpy(dev->dev_addr, promaddr, 6); - } - } - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - /* if the ethernet address is not valid, force to 00:00:00:00:00:00 */ - if (!is_valid_ether_addr(dev->perm_addr)) - memset(dev->dev_addr, 0, sizeof(dev->dev_addr)); - - if (pcnet32_debug & NETIF_MSG_PROBE) { + printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr); + + /* In most chips, after a chip reset, the ethernet address is read from the + * station address PROM at the base address and programmed into the + * "Physical Address Registers" CSR12-14. + * As a precautionary measure, we read the PROM values and complain if + * they disagree with the CSRs. Either way, we use the CSR values, and + * double check that they are valid. + */ + for (i = 0; i < 3; i++) { + unsigned int val; + val = a->read_csr(ioaddr, i + 12) & 0x0ffff; + /* There may be endianness issues here. */ + dev->dev_addr[2 * i] = val & 0x0ff; + dev->dev_addr[2 * i + 1] = (val >> 8) & 0x0ff; + } + + /* read PROM address and compare with CSR address */ for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i]); - - /* Version 0x2623 and 0x2624 */ - if (((chip_version + 1) & 0xfffe) == 0x2624) { - i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ - printk("\n" KERN_INFO " tx_start_pt(0x%04x):",i); - switch(i>>10) { - case 0: printk(" 20 bytes,"); break; - case 1: printk(" 64 bytes,"); break; - case 2: printk(" 128 bytes,"); break; - case 3: printk("~220 bytes,"); break; - } - i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */ - printk(" BCR18(%x):",i&0xffff); - if (i & (1<<5)) printk("BurstWrEn "); - if (i & (1<<6)) printk("BurstRdEn "); - if (i & (1<<7)) printk("DWordIO "); - if (i & (1<<11)) printk("NoUFlow "); - i = a->read_bcr(ioaddr, 25); - printk("\n" KERN_INFO " SRAMSIZE=0x%04x,",i<<8); - i = a->read_bcr(ioaddr, 26); - printk(" SRAM_BND=0x%04x,",i<<8); - i = a->read_bcr(ioaddr, 27); - if (i & (1<<14)) printk("LowLatRx"); - } - } - - dev->base_addr = ioaddr; - /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ - if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) { - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Consistent memory allocation failed.\n"); - ret = -ENOMEM; - goto err_free_netdev; - } - - memset(lp, 0, sizeof(*lp)); - lp->dma_addr = lp_dma_addr; - lp->pci_dev = pdev; - - spin_lock_init(&lp->lock); - - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - dev->priv = lp; - lp->name = chipname; - lp->shared_irq = shared; - lp->tx_ring_size = TX_RING_SIZE; /* default tx ring size */ - lp->rx_ring_size = RX_RING_SIZE; /* default rx ring size */ - lp->tx_mod_mask = lp->tx_ring_size - 1; - lp->rx_mod_mask = lp->rx_ring_size - 1; - lp->tx_len_bits = (PCNET32_LOG_TX_BUFFERS << 12); - lp->rx_len_bits = (PCNET32_LOG_RX_BUFFERS << 4); - lp->mii_if.full_duplex = fdx; - lp->mii_if.phy_id_mask = 0x1f; - lp->mii_if.reg_num_mask = 0x1f; - lp->dxsuflo = dxsuflo; - lp->mii = mii; - lp->msg_enable = pcnet32_debug; - if ((cards_found >= MAX_UNITS) || (options[cards_found] > sizeof(options_mapping))) - lp->options = PCNET32_PORT_ASEL; - else - lp->options = options_mapping[options[cards_found]]; - lp->mii_if.dev = dev; - lp->mii_if.mdio_read = mdio_read; - lp->mii_if.mdio_write = mdio_write; - - if (fdx && !(lp->options & PCNET32_PORT_ASEL) && - ((cards_found>=MAX_UNITS) || full_duplex[cards_found])) - lp->options |= PCNET32_PORT_FD; - - if (!a) { - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "No access methods\n"); - ret = -ENODEV; - goto err_free_consistent; - } - lp->a = *a; - - /* prior to register_netdev, dev->name is not yet correct */ - if (pcnet32_alloc_ring(dev, pci_name(lp->pci_dev))) { - ret = -ENOMEM; - goto err_free_ring; - } - /* detect special T1/E1 WAN card by checking for MAC address */ - if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 + promaddr[i] = inb(ioaddr + i); + + if (memcmp(promaddr, dev->dev_addr, 6) + || !is_valid_ether_addr(dev->dev_addr)) { + if (is_valid_ether_addr(promaddr)) { + if (pcnet32_debug & NETIF_MSG_PROBE) { + printk(" warning: CSR address invalid,\n"); + printk(KERN_INFO + " using instead PROM address of"); + } + memcpy(dev->dev_addr, promaddr, 6); + } + } + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); + + /* if the ethernet address is not valid, force to 00:00:00:00:00:00 */ + if (!is_valid_ether_addr(dev->perm_addr)) + memset(dev->dev_addr, 0, sizeof(dev->dev_addr)); + + if (pcnet32_debug & NETIF_MSG_PROBE) { + for (i = 0; i < 6; i++) + printk(" %2.2x", dev->dev_addr[i]); + + /* Version 0x2623 and 0x2624 */ + if (((chip_version + 1) & 0xfffe) == 0x2624) { + i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ + printk("\n" KERN_INFO " tx_start_pt(0x%04x):", i); + switch (i >> 10) { + case 0: + printk(" 20 bytes,"); + break; + case 1: + printk(" 64 bytes,"); + break; + case 2: + printk(" 128 bytes,"); + break; + case 3: + printk("~220 bytes,"); + break; + } + i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */ + printk(" BCR18(%x):", i & 0xffff); + if (i & (1 << 5)) + printk("BurstWrEn "); + if (i & (1 << 6)) + printk("BurstRdEn "); + if (i & (1 << 7)) + printk("DWordIO "); + if (i & (1 << 11)) + printk("NoUFlow "); + i = a->read_bcr(ioaddr, 25); + printk("\n" KERN_INFO " SRAMSIZE=0x%04x,", i << 8); + i = a->read_bcr(ioaddr, 26); + printk(" SRAM_BND=0x%04x,", i << 8); + i = a->read_bcr(ioaddr, 27); + if (i & (1 << 14)) + printk("LowLatRx"); + } + } + + dev->base_addr = ioaddr; + /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ + if ((lp = + pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) { + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_ERR PFX + "Consistent memory allocation failed.\n"); + ret = -ENOMEM; + goto err_free_netdev; + } + + memset(lp, 0, sizeof(*lp)); + lp->dma_addr = lp_dma_addr; + lp->pci_dev = pdev; + + spin_lock_init(&lp->lock); + + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pdev->dev); + dev->priv = lp; + lp->name = chipname; + lp->shared_irq = shared; + lp->tx_ring_size = TX_RING_SIZE; /* default tx ring size */ + lp->rx_ring_size = RX_RING_SIZE; /* default rx ring size */ + lp->tx_mod_mask = lp->tx_ring_size - 1; + lp->rx_mod_mask = lp->rx_ring_size - 1; + lp->tx_len_bits = (PCNET32_LOG_TX_BUFFERS << 12); + lp->rx_len_bits = (PCNET32_LOG_RX_BUFFERS << 4); + lp->mii_if.full_duplex = fdx; + lp->mii_if.phy_id_mask = 0x1f; + lp->mii_if.reg_num_mask = 0x1f; + lp->dxsuflo = dxsuflo; + lp->mii = mii; + lp->msg_enable = pcnet32_debug; + if ((cards_found >= MAX_UNITS) + || (options[cards_found] > sizeof(options_mapping))) + lp->options = PCNET32_PORT_ASEL; + else + lp->options = options_mapping[options[cards_found]]; + lp->mii_if.dev = dev; + lp->mii_if.mdio_read = mdio_read; + lp->mii_if.mdio_write = mdio_write; + + if (fdx && !(lp->options & PCNET32_PORT_ASEL) && + ((cards_found >= MAX_UNITS) || full_duplex[cards_found])) + lp->options |= PCNET32_PORT_FD; + + if (!a) { + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_ERR PFX "No access methods\n"); + ret = -ENODEV; + goto err_free_consistent; + } + lp->a = *a; + + /* prior to register_netdev, dev->name is not yet correct */ + if (pcnet32_alloc_ring(dev, pci_name(lp->pci_dev))) { + ret = -ENOMEM; + goto err_free_ring; + } + /* detect special T1/E1 WAN card by checking for MAC address */ + if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 && dev->dev_addr[2] == 0x75) - lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI; - - lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */ - lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits); - for (i = 0; i < 6; i++) - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - lp->init_block.filter[0] = 0x00000000; - lp->init_block.filter[1] = 0x00000000; - lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr); - lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr); - - /* switch pcnet32 to 32bit mode */ - a->write_bcr(ioaddr, 20, 2); - - a->write_csr(ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, - init_block)) & 0xffff); - a->write_csr(ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, - init_block)) >> 16); - - if (pdev) { /* use the IRQ provided by PCI */ - dev->irq = pdev->irq; - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(" assigned IRQ %d.\n", dev->irq); - } else { - unsigned long irq_mask = probe_irq_on(); + lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI; - /* - * To auto-IRQ we enable the initialization-done and DMA error - * interrupts. For ISA boards we get a DMA error, but VLB and PCI - * boards will work. - */ - /* Trigger an initialization just for the interrupt. */ - a->write_csr (ioaddr, 0, 0x41); - mdelay (1); + lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */ + lp->init_block.tlen_rlen = + le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits); + for (i = 0; i < 6; i++) + lp->init_block.phys_addr[i] = dev->dev_addr[i]; + lp->init_block.filter[0] = 0x00000000; + lp->init_block.filter[1] = 0x00000000; + lp->init_block.rx_ring = (u32) le32_to_cpu(lp->rx_ring_dma_addr); + lp->init_block.tx_ring = (u32) le32_to_cpu(lp->tx_ring_dma_addr); + + /* switch pcnet32 to 32bit mode */ + a->write_bcr(ioaddr, 20, 2); + + a->write_csr(ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, + init_block)) & 0xffff); + a->write_csr(ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, + init_block)) >> 16); + + if (pdev) { /* use the IRQ provided by PCI */ + dev->irq = pdev->irq; + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(" assigned IRQ %d.\n", dev->irq); + } else { + unsigned long irq_mask = probe_irq_on(); + + /* + * To auto-IRQ we enable the initialization-done and DMA error + * interrupts. For ISA boards we get a DMA error, but VLB and PCI + * boards will work. + */ + /* Trigger an initialization just for the interrupt. */ + a->write_csr(ioaddr, 0, 0x41); + mdelay(1); + + dev->irq = probe_irq_off(irq_mask); + if (!dev->irq) { + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(", failed to detect IRQ line.\n"); + ret = -ENODEV; + goto err_free_ring; + } + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(", probed IRQ %d.\n", dev->irq); + } - dev->irq = probe_irq_off (irq_mask); - if (!dev->irq) { - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(", failed to detect IRQ line.\n"); - ret = -ENODEV; - goto err_free_ring; + /* Set the mii phy_id so that we can query the link state */ + if (lp->mii) { + /* lp->phycount and lp->phymask are set to 0 by memset above */ + + lp->mii_if.phy_id = ((lp->a.read_bcr(ioaddr, 33)) >> 5) & 0x1f; + /* scan for PHYs */ + for (i = 0; i < PCNET32_MAX_PHYS; i++) { + unsigned short id1, id2; + + id1 = mdio_read(dev, i, MII_PHYSID1); + if (id1 == 0xffff) + continue; + id2 = mdio_read(dev, i, MII_PHYSID2); + if (id2 == 0xffff) + continue; + if (i == 31 && ((chip_version + 1) & 0xfffe) == 0x2624) + continue; /* 79C971 & 79C972 have phantom phy at id 31 */ + lp->phycount++; + lp->phymask |= (1 << i); + lp->mii_if.phy_id = i; + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_INFO PFX + "Found PHY %04x:%04x at address %d.\n", + id1, id2, i); + } + lp->a.write_bcr(ioaddr, 33, (lp->mii_if.phy_id) << 5); + if (lp->phycount > 1) { + lp->options |= PCNET32_PORT_MII; + } } - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(", probed IRQ %d.\n", dev->irq); - } - - /* Set the mii phy_id so that we can query the link state */ - if (lp->mii) { - /* lp->phycount and lp->phymask are set to 0 by memset above */ - - lp->mii_if.phy_id = ((lp->a.read_bcr (ioaddr, 33)) >> 5) & 0x1f; - /* scan for PHYs */ - for (i=0; iphycount++; - lp->phymask |= (1 << i); - lp->mii_if.phy_id = i; - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_INFO PFX "Found PHY %04x:%04x at address %d.\n", - id1, id2, i); - } - lp->a.write_bcr(ioaddr, 33, (lp->mii_if.phy_id) << 5); - if (lp->phycount > 1) { - lp->options |= PCNET32_PORT_MII; - } - } - - init_timer (&lp->watchdog_timer); - lp->watchdog_timer.data = (unsigned long) dev; - lp->watchdog_timer.function = (void *) &pcnet32_watchdog; - - /* The PCNET32-specific entries in the device structure. */ - dev->open = &pcnet32_open; - dev->hard_start_xmit = &pcnet32_start_xmit; - dev->stop = &pcnet32_close; - dev->get_stats = &pcnet32_get_stats; - dev->set_multicast_list = &pcnet32_set_multicast_list; - dev->do_ioctl = &pcnet32_ioctl; - dev->ethtool_ops = &pcnet32_ethtool_ops; - dev->tx_timeout = pcnet32_tx_timeout; - dev->watchdog_timeo = (5*HZ); + + init_timer(&lp->watchdog_timer); + lp->watchdog_timer.data = (unsigned long)dev; + lp->watchdog_timer.function = (void *)&pcnet32_watchdog; + + /* The PCNET32-specific entries in the device structure. */ + dev->open = &pcnet32_open; + dev->hard_start_xmit = &pcnet32_start_xmit; + dev->stop = &pcnet32_close; + dev->get_stats = &pcnet32_get_stats; + dev->set_multicast_list = &pcnet32_set_multicast_list; + dev->do_ioctl = &pcnet32_ioctl; + dev->ethtool_ops = &pcnet32_ethtool_ops; + dev->tx_timeout = pcnet32_tx_timeout; + dev->watchdog_timeo = (5 * HZ); #ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = pcnet32_poll_controller; + dev->poll_controller = pcnet32_poll_controller; #endif - /* Fill in the generic fields of the device structure. */ - if (register_netdev(dev)) - goto err_free_ring; - - if (pdev) { - pci_set_drvdata(pdev, dev); - } else { - lp->next = pcnet32_dev; - pcnet32_dev = dev; - } - - if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_INFO "%s: registered as %s\n", dev->name, lp->name); - cards_found++; - - /* enable LED writes */ - a->write_bcr(ioaddr, 2, a->read_bcr(ioaddr, 2) | 0x1000); - - return 0; - -err_free_ring: - pcnet32_free_ring(dev); -err_free_consistent: - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); -err_free_netdev: - free_netdev(dev); -err_release_region: - release_region(ioaddr, PCNET32_TOTAL_SIZE); - return ret; -} + /* Fill in the generic fields of the device structure. */ + if (register_netdev(dev)) + goto err_free_ring; + + if (pdev) { + pci_set_drvdata(pdev, dev); + } else { + lp->next = pcnet32_dev; + pcnet32_dev = dev; + } + + if (pcnet32_debug & NETIF_MSG_PROBE) + printk(KERN_INFO "%s: registered as %s\n", dev->name, lp->name); + cards_found++; + + /* enable LED writes */ + a->write_bcr(ioaddr, 2, a->read_bcr(ioaddr, 2) | 0x1000); + return 0; + + err_free_ring: + pcnet32_free_ring(dev); + err_free_consistent: + pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); + err_free_netdev: + free_netdev(dev); + err_release_region: + release_region(ioaddr, PCNET32_TOTAL_SIZE); + return ret; +} /* if any allocation fails, caller must also call pcnet32_free_ring */ static int pcnet32_alloc_ring(struct net_device *dev, char *name) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = dev->priv; - lp->tx_ring = pci_alloc_consistent(lp->pci_dev, - sizeof(struct pcnet32_tx_head) * lp->tx_ring_size, - &lp->tx_ring_dma_addr); - if (lp->tx_ring == NULL) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX "%s: Consistent memory allocation failed.\n", - name); - return -ENOMEM; - } - - lp->rx_ring = pci_alloc_consistent(lp->pci_dev, - sizeof(struct pcnet32_rx_head) * lp->rx_ring_size, - &lp->rx_ring_dma_addr); - if (lp->rx_ring == NULL) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX "%s: Consistent memory allocation failed.\n", - name); - return -ENOMEM; - } - - lp->tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->tx_ring_size, - GFP_ATOMIC); - if (!lp->tx_dma_addr) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX "%s: Memory allocation failed.\n", name); - return -ENOMEM; - } - memset(lp->tx_dma_addr, 0, sizeof(dma_addr_t) * lp->tx_ring_size); - - lp->rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->rx_ring_size, - GFP_ATOMIC); - if (!lp->rx_dma_addr) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX "%s: Memory allocation failed.\n", name); - return -ENOMEM; - } - memset(lp->rx_dma_addr, 0, sizeof(dma_addr_t) * lp->rx_ring_size); - - lp->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->tx_ring_size, - GFP_ATOMIC); - if (!lp->tx_skbuff) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX "%s: Memory allocation failed.\n", name); - return -ENOMEM; - } - memset(lp->tx_skbuff, 0, sizeof(struct sk_buff *) * lp->tx_ring_size); - - lp->rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->rx_ring_size, - GFP_ATOMIC); - if (!lp->rx_skbuff) { - if (pcnet32_debug & NETIF_MSG_DRV) - printk("\n" KERN_ERR PFX "%s: Memory allocation failed.\n", name); - return -ENOMEM; - } - memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size); + lp->tx_ring = pci_alloc_consistent(lp->pci_dev, + sizeof(struct pcnet32_tx_head) * + lp->tx_ring_size, + &lp->tx_ring_dma_addr); + if (lp->tx_ring == NULL) { + if (pcnet32_debug & NETIF_MSG_DRV) + printk("\n" KERN_ERR PFX + "%s: Consistent memory allocation failed.\n", + name); + return -ENOMEM; + } - return 0; -} + lp->rx_ring = pci_alloc_consistent(lp->pci_dev, + sizeof(struct pcnet32_rx_head) * + lp->rx_ring_size, + &lp->rx_ring_dma_addr); + if (lp->rx_ring == NULL) { + if (pcnet32_debug & NETIF_MSG_DRV) + printk("\n" KERN_ERR PFX + "%s: Consistent memory allocation failed.\n", + name); + return -ENOMEM; + } + lp->tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->tx_ring_size, + GFP_ATOMIC); + if (!lp->tx_dma_addr) { + if (pcnet32_debug & NETIF_MSG_DRV) + printk("\n" KERN_ERR PFX + "%s: Memory allocation failed.\n", name); + return -ENOMEM; + } + memset(lp->tx_dma_addr, 0, sizeof(dma_addr_t) * lp->tx_ring_size); + + lp->rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->rx_ring_size, + GFP_ATOMIC); + if (!lp->rx_dma_addr) { + if (pcnet32_debug & NETIF_MSG_DRV) + printk("\n" KERN_ERR PFX + "%s: Memory allocation failed.\n", name); + return -ENOMEM; + } + memset(lp->rx_dma_addr, 0, sizeof(dma_addr_t) * lp->rx_ring_size); + + lp->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->tx_ring_size, + GFP_ATOMIC); + if (!lp->tx_skbuff) { + if (pcnet32_debug & NETIF_MSG_DRV) + printk("\n" KERN_ERR PFX + "%s: Memory allocation failed.\n", name); + return -ENOMEM; + } + memset(lp->tx_skbuff, 0, sizeof(struct sk_buff *) * lp->tx_ring_size); + + lp->rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->rx_ring_size, + GFP_ATOMIC); + if (!lp->rx_skbuff) { + if (pcnet32_debug & NETIF_MSG_DRV) + printk("\n" KERN_ERR PFX + "%s: Memory allocation failed.\n", name); + return -ENOMEM; + } + memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size); + + return 0; +} static void pcnet32_free_ring(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = dev->priv; - kfree(lp->tx_skbuff); - lp->tx_skbuff = NULL; + kfree(lp->tx_skbuff); + lp->tx_skbuff = NULL; - kfree(lp->rx_skbuff); - lp->rx_skbuff = NULL; + kfree(lp->rx_skbuff); + lp->rx_skbuff = NULL; - kfree(lp->tx_dma_addr); - lp->tx_dma_addr = NULL; + kfree(lp->tx_dma_addr); + lp->tx_dma_addr = NULL; - kfree(lp->rx_dma_addr); - lp->rx_dma_addr = NULL; + kfree(lp->rx_dma_addr); + lp->rx_dma_addr = NULL; - if (lp->tx_ring) { - pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size, - lp->tx_ring, lp->tx_ring_dma_addr); - lp->tx_ring = NULL; - } + if (lp->tx_ring) { + pci_free_consistent(lp->pci_dev, + sizeof(struct pcnet32_tx_head) * + lp->tx_ring_size, lp->tx_ring, + lp->tx_ring_dma_addr); + lp->tx_ring = NULL; + } - if (lp->rx_ring) { - pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size, - lp->rx_ring, lp->rx_ring_dma_addr); - lp->rx_ring = NULL; - } + if (lp->rx_ring) { + pci_free_consistent(lp->pci_dev, + sizeof(struct pcnet32_rx_head) * + lp->rx_ring_size, lp->rx_ring, + lp->rx_ring_dma_addr); + lp->rx_ring = NULL; + } } - -static int -pcnet32_open(struct net_device *dev) +static int pcnet32_open(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - u16 val; - int i; - int rc; - unsigned long flags; - - if (request_irq(dev->irq, &pcnet32_interrupt, - lp->shared_irq ? SA_SHIRQ : 0, dev->name, (void *)dev)) { - return -EAGAIN; - } - - spin_lock_irqsave(&lp->lock, flags); - /* Check for a valid station address */ - if (!is_valid_ether_addr(dev->dev_addr)) { - rc = -EINVAL; - goto err_free_irq; - } - - /* Reset the PCNET32 */ - lp->a.reset (ioaddr); - - /* switch pcnet32 to 32bit mode */ - lp->a.write_bcr (ioaddr, 20, 2); - - if (netif_msg_ifup(lp)) - printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n", - dev->name, dev->irq, - (u32) (lp->tx_ring_dma_addr), - (u32) (lp->rx_ring_dma_addr), - (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block))); - - /* set/reset autoselect bit */ - val = lp->a.read_bcr (ioaddr, 2) & ~2; - if (lp->options & PCNET32_PORT_ASEL) - val |= 2; - lp->a.write_bcr (ioaddr, 2, val); - - /* handle full duplex setting */ - if (lp->mii_if.full_duplex) { - val = lp->a.read_bcr (ioaddr, 9) & ~3; - if (lp->options & PCNET32_PORT_FD) { - val |= 1; - if (lp->options == (PCNET32_PORT_FD | PCNET32_PORT_AUI)) + struct pcnet32_private *lp = dev->priv; + unsigned long ioaddr = dev->base_addr; + u16 val; + int i; + int rc; + unsigned long flags; + + if (request_irq(dev->irq, &pcnet32_interrupt, + lp->shared_irq ? SA_SHIRQ : 0, dev->name, + (void *)dev)) { + return -EAGAIN; + } + + spin_lock_irqsave(&lp->lock, flags); + /* Check for a valid station address */ + if (!is_valid_ether_addr(dev->dev_addr)) { + rc = -EINVAL; + goto err_free_irq; + } + + /* Reset the PCNET32 */ + lp->a.reset(ioaddr); + + /* switch pcnet32 to 32bit mode */ + lp->a.write_bcr(ioaddr, 20, 2); + + if (netif_msg_ifup(lp)) + printk(KERN_DEBUG + "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n", + dev->name, dev->irq, (u32) (lp->tx_ring_dma_addr), + (u32) (lp->rx_ring_dma_addr), + (u32) (lp->dma_addr + + offsetof(struct pcnet32_private, init_block))); + + /* set/reset autoselect bit */ + val = lp->a.read_bcr(ioaddr, 2) & ~2; + if (lp->options & PCNET32_PORT_ASEL) val |= 2; - } else if (lp->options & PCNET32_PORT_ASEL) { - /* workaround of xSeries250, turn on for 79C975 only */ - i = ((lp->a.read_csr(ioaddr, 88) | - (lp->a.read_csr(ioaddr,89) << 16)) >> 12) & 0xffff; - if (i == 0x2627) - val |= 3; - } - lp->a.write_bcr (ioaddr, 9, val); - } - - /* set/reset GPSI bit in test register */ - val = lp->a.read_csr (ioaddr, 124) & ~0x10; - if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI) - val |= 0x10; - lp->a.write_csr (ioaddr, 124, val); - - /* Allied Telesyn AT 2700/2701 FX are 100Mbit only and do not negotiate */ - if (lp->pci_dev->subsystem_vendor == PCI_VENDOR_ID_AT && + lp->a.write_bcr(ioaddr, 2, val); + + /* handle full duplex setting */ + if (lp->mii_if.full_duplex) { + val = lp->a.read_bcr(ioaddr, 9) & ~3; + if (lp->options & PCNET32_PORT_FD) { + val |= 1; + if (lp->options == (PCNET32_PORT_FD | PCNET32_PORT_AUI)) + val |= 2; + } else if (lp->options & PCNET32_PORT_ASEL) { + /* workaround of xSeries250, turn on for 79C975 only */ + i = ((lp->a.read_csr(ioaddr, 88) | + (lp->a. + read_csr(ioaddr, 89) << 16)) >> 12) & 0xffff; + if (i == 0x2627) + val |= 3; + } + lp->a.write_bcr(ioaddr, 9, val); + } + + /* set/reset GPSI bit in test register */ + val = lp->a.read_csr(ioaddr, 124) & ~0x10; + if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI) + val |= 0x10; + lp->a.write_csr(ioaddr, 124, val); + + /* Allied Telesyn AT 2700/2701 FX are 100Mbit only and do not negotiate */ + if (lp->pci_dev->subsystem_vendor == PCI_VENDOR_ID_AT && (lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX || lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) { - if (lp->options & PCNET32_PORT_ASEL) { - lp->options = PCNET32_PORT_FD | PCNET32_PORT_100; - if (netif_msg_link(lp)) - printk(KERN_DEBUG "%s: Setting 100Mb-Full Duplex.\n", - dev->name); - } - } - if (lp->phycount < 2) { - /* - * 24 Jun 2004 according AMD, in order to change the PHY, - * DANAS (or DISPM for 79C976) must be set; then select the speed, - * duplex, and/or enable auto negotiation, and clear DANAS - */ - if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) { - lp->a.write_bcr(ioaddr, 32, - lp->a.read_bcr(ioaddr, 32) | 0x0080); - /* disable Auto Negotiation, set 10Mpbs, HD */ - val = lp->a.read_bcr(ioaddr, 32) & ~0xb8; - if (lp->options & PCNET32_PORT_FD) - val |= 0x10; - if (lp->options & PCNET32_PORT_100) - val |= 0x08; - lp->a.write_bcr (ioaddr, 32, val); - } else { - if (lp->options & PCNET32_PORT_ASEL) { - lp->a.write_bcr(ioaddr, 32, - lp->a.read_bcr(ioaddr, 32) | 0x0080); - /* enable auto negotiate, setup, disable fd */ - val = lp->a.read_bcr(ioaddr, 32) & ~0x98; - val |= 0x20; - lp->a.write_bcr(ioaddr, 32, val); - } - } - } else { - int first_phy = -1; - u16 bmcr; - u32 bcr9; - struct ethtool_cmd ecmd; - - /* - * There is really no good other way to handle multiple PHYs - * other than turning off all automatics - */ - val = lp->a.read_bcr(ioaddr, 2); - lp->a.write_bcr(ioaddr, 2, val & ~2); - val = lp->a.read_bcr(ioaddr, 32); - lp->a.write_bcr(ioaddr, 32, val & ~(1 << 7)); /* stop MII manager */ - - if (!(lp->options & PCNET32_PORT_ASEL)) { - /* setup ecmd */ - ecmd.port = PORT_MII; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.autoneg = AUTONEG_DISABLE; - ecmd.speed = lp->options & PCNET32_PORT_100 ? SPEED_100 : SPEED_10; - bcr9 = lp->a.read_bcr(ioaddr, 9); - - if (lp->options & PCNET32_PORT_FD) { - ecmd.duplex = DUPLEX_FULL; - bcr9 |= (1 << 0); - } else { - ecmd.duplex = DUPLEX_HALF; - bcr9 |= ~(1 << 0); - } - lp->a.write_bcr(ioaddr, 9, bcr9); - } - - for (i=0; iphymask & (1 << i)) { - /* isolate all but the first PHY */ - bmcr = mdio_read(dev, i, MII_BMCR); - if (first_phy == -1) { - first_phy = i; - mdio_write(dev, i, MII_BMCR, bmcr & ~BMCR_ISOLATE); - } else { - mdio_write(dev, i, MII_BMCR, bmcr | BMCR_ISOLATE); - } - /* use mii_ethtool_sset to setup PHY */ - lp->mii_if.phy_id = i; - ecmd.phy_address = i; if (lp->options & PCNET32_PORT_ASEL) { - mii_ethtool_gset(&lp->mii_if, &ecmd); - ecmd.autoneg = AUTONEG_ENABLE; + lp->options = PCNET32_PORT_FD | PCNET32_PORT_100; + if (netif_msg_link(lp)) + printk(KERN_DEBUG + "%s: Setting 100Mb-Full Duplex.\n", + dev->name); + } + } + if (lp->phycount < 2) { + /* + * 24 Jun 2004 according AMD, in order to change the PHY, + * DANAS (or DISPM for 79C976) must be set; then select the speed, + * duplex, and/or enable auto negotiation, and clear DANAS + */ + if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) { + lp->a.write_bcr(ioaddr, 32, + lp->a.read_bcr(ioaddr, 32) | 0x0080); + /* disable Auto Negotiation, set 10Mpbs, HD */ + val = lp->a.read_bcr(ioaddr, 32) & ~0xb8; + if (lp->options & PCNET32_PORT_FD) + val |= 0x10; + if (lp->options & PCNET32_PORT_100) + val |= 0x08; + lp->a.write_bcr(ioaddr, 32, val); + } else { + if (lp->options & PCNET32_PORT_ASEL) { + lp->a.write_bcr(ioaddr, 32, + lp->a.read_bcr(ioaddr, + 32) | 0x0080); + /* enable auto negotiate, setup, disable fd */ + val = lp->a.read_bcr(ioaddr, 32) & ~0x98; + val |= 0x20; + lp->a.write_bcr(ioaddr, 32, val); + } + } + } else { + int first_phy = -1; + u16 bmcr; + u32 bcr9; + struct ethtool_cmd ecmd; + + /* + * There is really no good other way to handle multiple PHYs + * other than turning off all automatics + */ + val = lp->a.read_bcr(ioaddr, 2); + lp->a.write_bcr(ioaddr, 2, val & ~2); + val = lp->a.read_bcr(ioaddr, 32); + lp->a.write_bcr(ioaddr, 32, val & ~(1 << 7)); /* stop MII manager */ + + if (!(lp->options & PCNET32_PORT_ASEL)) { + /* setup ecmd */ + ecmd.port = PORT_MII; + ecmd.transceiver = XCVR_INTERNAL; + ecmd.autoneg = AUTONEG_DISABLE; + ecmd.speed = + lp-> + options & PCNET32_PORT_100 ? SPEED_100 : SPEED_10; + bcr9 = lp->a.read_bcr(ioaddr, 9); + + if (lp->options & PCNET32_PORT_FD) { + ecmd.duplex = DUPLEX_FULL; + bcr9 |= (1 << 0); + } else { + ecmd.duplex = DUPLEX_HALF; + bcr9 |= ~(1 << 0); + } + lp->a.write_bcr(ioaddr, 9, bcr9); } - mii_ethtool_sset(&lp->mii_if, &ecmd); - } - } - lp->mii_if.phy_id = first_phy; - if (netif_msg_link(lp)) - printk(KERN_INFO "%s: Using PHY number %d.\n", dev->name, first_phy); - } + + for (i = 0; i < PCNET32_MAX_PHYS; i++) { + if (lp->phymask & (1 << i)) { + /* isolate all but the first PHY */ + bmcr = mdio_read(dev, i, MII_BMCR); + if (first_phy == -1) { + first_phy = i; + mdio_write(dev, i, MII_BMCR, + bmcr & ~BMCR_ISOLATE); + } else { + mdio_write(dev, i, MII_BMCR, + bmcr | BMCR_ISOLATE); + } + /* use mii_ethtool_sset to setup PHY */ + lp->mii_if.phy_id = i; + ecmd.phy_address = i; + if (lp->options & PCNET32_PORT_ASEL) { + mii_ethtool_gset(&lp->mii_if, &ecmd); + ecmd.autoneg = AUTONEG_ENABLE; + } + mii_ethtool_sset(&lp->mii_if, &ecmd); + } + } + lp->mii_if.phy_id = first_phy; + if (netif_msg_link(lp)) + printk(KERN_INFO "%s: Using PHY number %d.\n", + dev->name, first_phy); + } #ifdef DO_DXSUFLO - if (lp->dxsuflo) { /* Disable transmit stop on underflow */ - val = lp->a.read_csr (ioaddr, 3); - val |= 0x40; - lp->a.write_csr (ioaddr, 3, val); - } + if (lp->dxsuflo) { /* Disable transmit stop on underflow */ + val = lp->a.read_csr(ioaddr, 3); + val |= 0x40; + lp->a.write_csr(ioaddr, 3, val); + } #endif - lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); - pcnet32_load_multicast(dev); - - if (pcnet32_init_ring(dev)) { - rc = -ENOMEM; - goto err_free_ring; - } - - /* Re-initialize the PCNET32, and start it when done. */ - lp->a.write_csr (ioaddr, 1, (lp->dma_addr + - offsetof(struct pcnet32_private, init_block)) & 0xffff); - lp->a.write_csr (ioaddr, 2, (lp->dma_addr + - offsetof(struct pcnet32_private, init_block)) >> 16); - - lp->a.write_csr (ioaddr, 4, 0x0915); - lp->a.write_csr (ioaddr, 0, 0x0001); - - netif_start_queue(dev); - - /* Print the link status and start the watchdog */ - pcnet32_check_media (dev, 1); - mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); - - i = 0; - while (i++ < 100) - if (lp->a.read_csr (ioaddr, 0) & 0x0100) - break; - /* - * We used to clear the InitDone bit, 0x0100, here but Mark Stockton - * reports that doing so triggers a bug in the '974. - */ - lp->a.write_csr (ioaddr, 0, 0x0042); - - if (netif_msg_ifup(lp)) - printk(KERN_DEBUG "%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n", - dev->name, i, (u32) (lp->dma_addr + - offsetof(struct pcnet32_private, init_block)), - lp->a.read_csr(ioaddr, 0)); - - spin_unlock_irqrestore(&lp->lock, flags); - - return 0; /* Always succeed */ - -err_free_ring: - /* free any allocated skbuffs */ - for (i = 0; i < lp->rx_ring_size; i++) { - lp->rx_ring[i].status = 0; - if (lp->rx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(lp->rx_skbuff[i]); - } - lp->rx_skbuff[i] = NULL; - lp->rx_dma_addr[i] = 0; - } - - pcnet32_free_ring(dev); - - /* - * Switch back to 16bit mode to avoid problems with dumb - * DOS packet driver after a warm reboot - */ - lp->a.write_bcr (ioaddr, 20, 4); - -err_free_irq: - spin_unlock_irqrestore(&lp->lock, flags); - free_irq(dev->irq, dev); - return rc; + lp->init_block.mode = + le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); + pcnet32_load_multicast(dev); + + if (pcnet32_init_ring(dev)) { + rc = -ENOMEM; + goto err_free_ring; + } + + /* Re-initialize the PCNET32, and start it when done. */ + lp->a.write_csr(ioaddr, 1, (lp->dma_addr + + offsetof(struct pcnet32_private, + init_block)) & 0xffff); + lp->a.write_csr(ioaddr, 2, + (lp->dma_addr + + offsetof(struct pcnet32_private, init_block)) >> 16); + + lp->a.write_csr(ioaddr, 4, 0x0915); + lp->a.write_csr(ioaddr, 0, 0x0001); + + netif_start_queue(dev); + + /* Print the link status and start the watchdog */ + pcnet32_check_media(dev, 1); + mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); + + i = 0; + while (i++ < 100) + if (lp->a.read_csr(ioaddr, 0) & 0x0100) + break; + /* + * We used to clear the InitDone bit, 0x0100, here but Mark Stockton + * reports that doing so triggers a bug in the '974. + */ + lp->a.write_csr(ioaddr, 0, 0x0042); + + if (netif_msg_ifup(lp)) + printk(KERN_DEBUG + "%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n", + dev->name, i, + (u32) (lp->dma_addr + + offsetof(struct pcnet32_private, init_block)), + lp->a.read_csr(ioaddr, 0)); + + spin_unlock_irqrestore(&lp->lock, flags); + + return 0; /* Always succeed */ + + err_free_ring: + /* free any allocated skbuffs */ + for (i = 0; i < lp->rx_ring_size; i++) { + lp->rx_ring[i].status = 0; + if (lp->rx_skbuff[i]) { + pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], + PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); + dev_kfree_skb(lp->rx_skbuff[i]); + } + lp->rx_skbuff[i] = NULL; + lp->rx_dma_addr[i] = 0; + } + + pcnet32_free_ring(dev); + + /* + * Switch back to 16bit mode to avoid problems with dumb + * DOS packet driver after a warm reboot + */ + lp->a.write_bcr(ioaddr, 20, 4); + + err_free_irq: + spin_unlock_irqrestore(&lp->lock, flags); + free_irq(dev->irq, dev); + return rc; } /* @@ -1840,722 +1921,792 @@ err_free_irq: * restarting the chip, but I'm too lazy to do so right now. dplatt@3do.com */ -static void -pcnet32_purge_tx_ring(struct net_device *dev) +static void pcnet32_purge_tx_ring(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - int i; - - for (i = 0; i < lp->tx_ring_size; i++) { - lp->tx_ring[i].status = 0; /* CPU owns buffer */ - wmb(); /* Make sure adapter sees owner change */ - if (lp->tx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], - lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); - dev_kfree_skb_any(lp->tx_skbuff[i]); - } - lp->tx_skbuff[i] = NULL; - lp->tx_dma_addr[i] = 0; - } -} + struct pcnet32_private *lp = dev->priv; + int i; + for (i = 0; i < lp->tx_ring_size; i++) { + lp->tx_ring[i].status = 0; /* CPU owns buffer */ + wmb(); /* Make sure adapter sees owner change */ + if (lp->tx_skbuff[i]) { + pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], + lp->tx_skbuff[i]->len, + PCI_DMA_TODEVICE); + dev_kfree_skb_any(lp->tx_skbuff[i]); + } + lp->tx_skbuff[i] = NULL; + lp->tx_dma_addr[i] = 0; + } +} /* Initialize the PCNET32 Rx and Tx rings. */ -static int -pcnet32_init_ring(struct net_device *dev) +static int pcnet32_init_ring(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - int i; - - lp->tx_full = 0; - lp->cur_rx = lp->cur_tx = 0; - lp->dirty_rx = lp->dirty_tx = 0; - - for (i = 0; i < lp->rx_ring_size; i++) { - struct sk_buff *rx_skbuff = lp->rx_skbuff[i]; - if (rx_skbuff == NULL) { - if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) { - /* there is not much, we can do at this point */ - if (pcnet32_debug & NETIF_MSG_DRV) - printk(KERN_ERR "%s: pcnet32_init_ring dev_alloc_skb failed.\n", - dev->name); - return -1; - } - skb_reserve (rx_skbuff, 2); - } - - rmb(); - if (lp->rx_dma_addr[i] == 0) - lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->data, - PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); - lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]); - lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ); - wmb(); /* Make sure owner changes after all others are visible */ - lp->rx_ring[i].status = le16_to_cpu(0x8000); - } - /* The Tx buffer address is filled in as needed, but we do need to clear - * the upper ownership bit. */ - for (i = 0; i < lp->tx_ring_size; i++) { - lp->tx_ring[i].status = 0; /* CPU owns buffer */ - wmb(); /* Make sure adapter sees owner change */ - lp->tx_ring[i].base = 0; - lp->tx_dma_addr[i] = 0; - } - - lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits); - for (i = 0; i < 6; i++) - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr); - lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr); - wmb(); /* Make sure all changes are visible */ - return 0; + struct pcnet32_private *lp = dev->priv; + int i; + + lp->tx_full = 0; + lp->cur_rx = lp->cur_tx = 0; + lp->dirty_rx = lp->dirty_tx = 0; + + for (i = 0; i < lp->rx_ring_size; i++) { + struct sk_buff *rx_skbuff = lp->rx_skbuff[i]; + if (rx_skbuff == NULL) { + if (! + (rx_skbuff = lp->rx_skbuff[i] = + dev_alloc_skb(PKT_BUF_SZ))) { + /* there is not much, we can do at this point */ + if (pcnet32_debug & NETIF_MSG_DRV) + printk(KERN_ERR + "%s: pcnet32_init_ring dev_alloc_skb failed.\n", + dev->name); + return -1; + } + skb_reserve(rx_skbuff, 2); + } + + rmb(); + if (lp->rx_dma_addr[i] == 0) + lp->rx_dma_addr[i] = + pci_map_single(lp->pci_dev, rx_skbuff->data, + PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); + lp->rx_ring[i].base = (u32) le32_to_cpu(lp->rx_dma_addr[i]); + lp->rx_ring[i].buf_length = le16_to_cpu(2 - PKT_BUF_SZ); + wmb(); /* Make sure owner changes after all others are visible */ + lp->rx_ring[i].status = le16_to_cpu(0x8000); + } + /* The Tx buffer address is filled in as needed, but we do need to clear + * the upper ownership bit. */ + for (i = 0; i < lp->tx_ring_size; i++) { + lp->tx_ring[i].status = 0; /* CPU owns buffer */ + wmb(); /* Make sure adapter sees owner change */ + lp->tx_ring[i].base = 0; + lp->tx_dma_addr[i] = 0; + } + + lp->init_block.tlen_rlen = + le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits); + for (i = 0; i < 6; i++) + lp->init_block.phys_addr[i] = dev->dev_addr[i]; + lp->init_block.rx_ring = (u32) le32_to_cpu(lp->rx_ring_dma_addr); + lp->init_block.tx_ring = (u32) le32_to_cpu(lp->tx_ring_dma_addr); + wmb(); /* Make sure all changes are visible */ + return 0; } /* the pcnet32 has been issued a stop or reset. Wait for the stop bit * then flush the pending transmit operations, re-initialize the ring, * and tell the chip to initialize. */ -static void -pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) +static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) { - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - int i; + struct pcnet32_private *lp = dev->priv; + unsigned long ioaddr = dev->base_addr; + int i; - /* wait for stop */ - for (i=0; i<100; i++) - if (lp->a.read_csr(ioaddr, 0) & 0x0004) - break; + /* wait for stop */ + for (i = 0; i < 100; i++) + if (lp->a.read_csr(ioaddr, 0) & 0x0004) + break; - if (i >= 100 && netif_msg_drv(lp)) - printk(KERN_ERR "%s: pcnet32_restart timed out waiting for stop.\n", - dev->name); + if (i >= 100 && netif_msg_drv(lp)) + printk(KERN_ERR + "%s: pcnet32_restart timed out waiting for stop.\n", + dev->name); - pcnet32_purge_tx_ring(dev); - if (pcnet32_init_ring(dev)) - return; + pcnet32_purge_tx_ring(dev); + if (pcnet32_init_ring(dev)) + return; - /* ReInit Ring */ - lp->a.write_csr (ioaddr, 0, 1); - i = 0; - while (i++ < 1000) - if (lp->a.read_csr (ioaddr, 0) & 0x0100) - break; + /* ReInit Ring */ + lp->a.write_csr(ioaddr, 0, 1); + i = 0; + while (i++ < 1000) + if (lp->a.read_csr(ioaddr, 0) & 0x0100) + break; - lp->a.write_csr (ioaddr, 0, csr0_bits); + lp->a.write_csr(ioaddr, 0, csr0_bits); } - -static void -pcnet32_tx_timeout (struct net_device *dev) +static void pcnet32_tx_timeout(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr, flags; - - spin_lock_irqsave(&lp->lock, flags); - /* Transmitter timeout, serious problems. */ - if (pcnet32_debug & NETIF_MSG_DRV) - printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n", - dev->name, lp->a.read_csr(ioaddr, 0)); - lp->a.write_csr (ioaddr, 0, 0x0004); - lp->stats.tx_errors++; - if (netif_msg_tx_err(lp)) { - int i; - printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", - lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", - lp->cur_rx); - for (i = 0 ; i < lp->rx_ring_size; i++) - printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", - le32_to_cpu(lp->rx_ring[i].base), - (-le16_to_cpu(lp->rx_ring[i].buf_length)) & 0xffff, - le32_to_cpu(lp->rx_ring[i].msg_length), - le16_to_cpu(lp->rx_ring[i].status)); - for (i = 0 ; i < lp->tx_ring_size; i++) - printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", - le32_to_cpu(lp->tx_ring[i].base), - (-le16_to_cpu(lp->tx_ring[i].length)) & 0xffff, - le32_to_cpu(lp->tx_ring[i].misc), - le16_to_cpu(lp->tx_ring[i].status)); - printk("\n"); - } - pcnet32_restart(dev, 0x0042); - - dev->trans_start = jiffies; - netif_wake_queue(dev); - - spin_unlock_irqrestore(&lp->lock, flags); -} + struct pcnet32_private *lp = dev->priv; + unsigned long ioaddr = dev->base_addr, flags; + + spin_lock_irqsave(&lp->lock, flags); + /* Transmitter timeout, serious problems. */ + if (pcnet32_debug & NETIF_MSG_DRV) + printk(KERN_ERR + "%s: transmit timed out, status %4.4x, resetting.\n", + dev->name, lp->a.read_csr(ioaddr, 0)); + lp->a.write_csr(ioaddr, 0, 0x0004); + lp->stats.tx_errors++; + if (netif_msg_tx_err(lp)) { + int i; + printk(KERN_DEBUG + " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", + lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", + lp->cur_rx); + for (i = 0; i < lp->rx_ring_size; i++) + printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", + le32_to_cpu(lp->rx_ring[i].base), + (-le16_to_cpu(lp->rx_ring[i].buf_length)) & + 0xffff, le32_to_cpu(lp->rx_ring[i].msg_length), + le16_to_cpu(lp->rx_ring[i].status)); + for (i = 0; i < lp->tx_ring_size; i++) + printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", + le32_to_cpu(lp->tx_ring[i].base), + (-le16_to_cpu(lp->tx_ring[i].length)) & 0xffff, + le32_to_cpu(lp->tx_ring[i].misc), + le16_to_cpu(lp->tx_ring[i].status)); + printk("\n"); + } + pcnet32_restart(dev, 0x0042); + dev->trans_start = jiffies; + netif_wake_queue(dev); -static int -pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) + spin_unlock_irqrestore(&lp->lock, flags); +} + +static int pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - u16 status; - int entry; - unsigned long flags; + struct pcnet32_private *lp = dev->priv; + unsigned long ioaddr = dev->base_addr; + u16 status; + int entry; + unsigned long flags; - spin_lock_irqsave(&lp->lock, flags); + spin_lock_irqsave(&lp->lock, flags); - if (netif_msg_tx_queued(lp)) { - printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", - dev->name, lp->a.read_csr(ioaddr, 0)); - } + if (netif_msg_tx_queued(lp)) { + printk(KERN_DEBUG + "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", + dev->name, lp->a.read_csr(ioaddr, 0)); + } - /* Default status -- will not enable Successful-TxDone - * interrupt when that option is available to us. - */ - status = 0x8300; + /* Default status -- will not enable Successful-TxDone + * interrupt when that option is available to us. + */ + status = 0x8300; - /* Fill in a Tx ring entry */ + /* Fill in a Tx ring entry */ - /* Mask to ring buffer boundary. */ - entry = lp->cur_tx & lp->tx_mod_mask; + /* Mask to ring buffer boundary. */ + entry = lp->cur_tx & lp->tx_mod_mask; - /* Caution: the write order is important here, set the status - * with the "ownership" bits last. */ + /* Caution: the write order is important here, set the status + * with the "ownership" bits last. */ - lp->tx_ring[entry].length = le16_to_cpu(-skb->len); + lp->tx_ring[entry].length = le16_to_cpu(-skb->len); - lp->tx_ring[entry].misc = 0x00000000; + lp->tx_ring[entry].misc = 0x00000000; - lp->tx_skbuff[entry] = skb; - lp->tx_dma_addr[entry] = pci_map_single(lp->pci_dev, skb->data, skb->len, - PCI_DMA_TODEVICE); - lp->tx_ring[entry].base = (u32)le32_to_cpu(lp->tx_dma_addr[entry]); - wmb(); /* Make sure owner changes after all others are visible */ - lp->tx_ring[entry].status = le16_to_cpu(status); + lp->tx_skbuff[entry] = skb; + lp->tx_dma_addr[entry] = + pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); + lp->tx_ring[entry].base = (u32) le32_to_cpu(lp->tx_dma_addr[entry]); + wmb(); /* Make sure owner changes after all others are visible */ + lp->tx_ring[entry].status = le16_to_cpu(status); - lp->cur_tx++; - lp->stats.tx_bytes += skb->len; + lp->cur_tx++; + lp->stats.tx_bytes += skb->len; - /* Trigger an immediate send poll. */ - lp->a.write_csr (ioaddr, 0, 0x0048); + /* Trigger an immediate send poll. */ + lp->a.write_csr(ioaddr, 0, 0x0048); - dev->trans_start = jiffies; + dev->trans_start = jiffies; - if (lp->tx_ring[(entry+1) & lp->tx_mod_mask].base != 0) { - lp->tx_full = 1; - netif_stop_queue(dev); - } - spin_unlock_irqrestore(&lp->lock, flags); - return 0; + if (lp->tx_ring[(entry + 1) & lp->tx_mod_mask].base != 0) { + lp->tx_full = 1; + netif_stop_queue(dev); + } + spin_unlock_irqrestore(&lp->lock, flags); + return 0; } /* The PCNET32 interrupt handler. */ static irqreturn_t -pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) +pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct net_device *dev = dev_id; - struct pcnet32_private *lp; - unsigned long ioaddr; - u16 csr0,rap; - int boguscnt = max_interrupt_work; - int must_restart; - - if (!dev) { - if (pcnet32_debug & NETIF_MSG_INTR) - printk (KERN_DEBUG "%s(): irq %d for unknown device\n", - __FUNCTION__, irq); - return IRQ_NONE; - } - - ioaddr = dev->base_addr; - lp = dev->priv; - - spin_lock(&lp->lock); - - rap = lp->a.read_rap(ioaddr); - while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8f00 && --boguscnt >= 0) { - if (csr0 == 0xffff) { - break; /* PCMCIA remove happened */ + struct net_device *dev = dev_id; + struct pcnet32_private *lp; + unsigned long ioaddr; + u16 csr0, rap; + int boguscnt = max_interrupt_work; + int must_restart; + + if (!dev) { + if (pcnet32_debug & NETIF_MSG_INTR) + printk(KERN_DEBUG "%s(): irq %d for unknown device\n", + __FUNCTION__, irq); + return IRQ_NONE; } - /* Acknowledge all of the current interrupt sources ASAP. */ - lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f); - must_restart = 0; + ioaddr = dev->base_addr; + lp = dev->priv; - if (netif_msg_intr(lp)) - printk(KERN_DEBUG "%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", - dev->name, csr0, lp->a.read_csr (ioaddr, 0)); - - if (csr0 & 0x0400) /* Rx interrupt */ - pcnet32_rx(dev); - - if (csr0 & 0x0200) { /* Tx-done interrupt */ - unsigned int dirty_tx = lp->dirty_tx; - int delta; - - while (dirty_tx != lp->cur_tx) { - int entry = dirty_tx & lp->tx_mod_mask; - int status = (short)le16_to_cpu(lp->tx_ring[entry].status); - - if (status < 0) - break; /* It still hasn't been Txed */ - - lp->tx_ring[entry].base = 0; - - if (status & 0x4000) { - /* There was an major error, log it. */ - int err_status = le32_to_cpu(lp->tx_ring[entry].misc); - lp->stats.tx_errors++; - if (netif_msg_tx_err(lp)) - printk(KERN_ERR "%s: Tx error status=%04x err_status=%08x\n", - dev->name, status, err_status); - if (err_status & 0x04000000) lp->stats.tx_aborted_errors++; - if (err_status & 0x08000000) lp->stats.tx_carrier_errors++; - if (err_status & 0x10000000) lp->stats.tx_window_errors++; + spin_lock(&lp->lock); + + rap = lp->a.read_rap(ioaddr); + while ((csr0 = lp->a.read_csr(ioaddr, 0)) & 0x8f00 && --boguscnt >= 0) { + if (csr0 == 0xffff) { + break; /* PCMCIA remove happened */ + } + /* Acknowledge all of the current interrupt sources ASAP. */ + lp->a.write_csr(ioaddr, 0, csr0 & ~0x004f); + + must_restart = 0; + + if (netif_msg_intr(lp)) + printk(KERN_DEBUG + "%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", + dev->name, csr0, lp->a.read_csr(ioaddr, 0)); + + if (csr0 & 0x0400) /* Rx interrupt */ + pcnet32_rx(dev); + + if (csr0 & 0x0200) { /* Tx-done interrupt */ + unsigned int dirty_tx = lp->dirty_tx; + int delta; + + while (dirty_tx != lp->cur_tx) { + int entry = dirty_tx & lp->tx_mod_mask; + int status = + (short)le16_to_cpu(lp->tx_ring[entry]. + status); + + if (status < 0) + break; /* It still hasn't been Txed */ + + lp->tx_ring[entry].base = 0; + + if (status & 0x4000) { + /* There was an major error, log it. */ + int err_status = + le32_to_cpu(lp->tx_ring[entry]. + misc); + lp->stats.tx_errors++; + if (netif_msg_tx_err(lp)) + printk(KERN_ERR + "%s: Tx error status=%04x err_status=%08x\n", + dev->name, status, + err_status); + if (err_status & 0x04000000) + lp->stats.tx_aborted_errors++; + if (err_status & 0x08000000) + lp->stats.tx_carrier_errors++; + if (err_status & 0x10000000) + lp->stats.tx_window_errors++; #ifndef DO_DXSUFLO - if (err_status & 0x40000000) { - lp->stats.tx_fifo_errors++; - /* Ackk! On FIFO errors the Tx unit is turned off! */ - /* Remove this verbosity later! */ - if (netif_msg_tx_err(lp)) - printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n", - dev->name, csr0); - must_restart = 1; - } + if (err_status & 0x40000000) { + lp->stats.tx_fifo_errors++; + /* Ackk! On FIFO errors the Tx unit is turned off! */ + /* Remove this verbosity later! */ + if (netif_msg_tx_err(lp)) + printk(KERN_ERR + "%s: Tx FIFO error! CSR0=%4.4x\n", + dev->name, csr0); + must_restart = 1; + } #else - if (err_status & 0x40000000) { - lp->stats.tx_fifo_errors++; - if (! lp->dxsuflo) { /* If controller doesn't recover ... */ - /* Ackk! On FIFO errors the Tx unit is turned off! */ - /* Remove this verbosity later! */ - if (netif_msg_tx_err(lp)) - printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n", - dev->name, csr0); - must_restart = 1; - } - } + if (err_status & 0x40000000) { + lp->stats.tx_fifo_errors++; + if (!lp->dxsuflo) { /* If controller doesn't recover ... */ + /* Ackk! On FIFO errors the Tx unit is turned off! */ + /* Remove this verbosity later! */ + if (netif_msg_tx_err + (lp)) + printk(KERN_ERR + "%s: Tx FIFO error! CSR0=%4.4x\n", + dev-> + name, + csr0); + must_restart = 1; + } + } #endif - } else { - if (status & 0x1800) - lp->stats.collisions++; - lp->stats.tx_packets++; + } else { + if (status & 0x1800) + lp->stats.collisions++; + lp->stats.tx_packets++; + } + + /* We must free the original skb */ + if (lp->tx_skbuff[entry]) { + pci_unmap_single(lp->pci_dev, + lp->tx_dma_addr[entry], + lp->tx_skbuff[entry]-> + len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(lp->tx_skbuff[entry]); + lp->tx_skbuff[entry] = NULL; + lp->tx_dma_addr[entry] = 0; + } + dirty_tx++; + } + + delta = + (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + + lp->tx_ring_size); + if (delta > lp->tx_ring_size) { + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dev->name, dirty_tx, lp->cur_tx, + lp->tx_full); + dirty_tx += lp->tx_ring_size; + delta -= lp->tx_ring_size; + } + + if (lp->tx_full && + netif_queue_stopped(dev) && + delta < lp->tx_ring_size - 2) { + /* The ring is no longer full, clear tbusy. */ + lp->tx_full = 0; + netif_wake_queue(dev); + } + lp->dirty_tx = dirty_tx; + } + + /* Log misc errors. */ + if (csr0 & 0x4000) + lp->stats.tx_errors++; /* Tx babble. */ + if (csr0 & 0x1000) { + /* + * this happens when our receive ring is full. This shouldn't + * be a problem as we will see normal rx interrupts for the frames + * in the receive ring. But there are some PCI chipsets (I can + * reproduce this on SP3G with Intel saturn chipset) which have + * sometimes problems and will fill up the receive ring with + * error descriptors. In this situation we don't get a rx + * interrupt, but a missed frame interrupt sooner or later. + * So we try to clean up our receive ring here. + */ + pcnet32_rx(dev); + lp->stats.rx_errors++; /* Missed a Rx frame. */ + } + if (csr0 & 0x0800) { + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: Bus master arbitration failure, status %4.4x.\n", + dev->name, csr0); + /* unlike for the lance, there is no restart needed */ } - /* We must free the original skb */ - if (lp->tx_skbuff[entry]) { - pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[entry], - lp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(lp->tx_skbuff[entry]); - lp->tx_skbuff[entry] = NULL; - lp->tx_dma_addr[entry] = 0; + if (must_restart) { + /* reset the chip to clear the error condition, then restart */ + lp->a.reset(ioaddr); + lp->a.write_csr(ioaddr, 4, 0x0915); + pcnet32_restart(dev, 0x0002); + netif_wake_queue(dev); } - dirty_tx++; - } - - delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size); - if (delta > lp->tx_ring_size) { - if (netif_msg_drv(lp)) - printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, lp->cur_tx, lp->tx_full); - dirty_tx += lp->tx_ring_size; - delta -= lp->tx_ring_size; - } - - if (lp->tx_full && - netif_queue_stopped(dev) && - delta < lp->tx_ring_size - 2) { - /* The ring is no longer full, clear tbusy. */ - lp->tx_full = 0; - netif_wake_queue (dev); - } - lp->dirty_tx = dirty_tx; - } - - /* Log misc errors. */ - if (csr0 & 0x4000) lp->stats.tx_errors++; /* Tx babble. */ - if (csr0 & 0x1000) { - /* - * this happens when our receive ring is full. This shouldn't - * be a problem as we will see normal rx interrupts for the frames - * in the receive ring. But there are some PCI chipsets (I can - * reproduce this on SP3G with Intel saturn chipset) which have - * sometimes problems and will fill up the receive ring with - * error descriptors. In this situation we don't get a rx - * interrupt, but a missed frame interrupt sooner or later. - * So we try to clean up our receive ring here. - */ - pcnet32_rx(dev); - lp->stats.rx_errors++; /* Missed a Rx frame. */ - } - if (csr0 & 0x0800) { - if (netif_msg_drv(lp)) - printk(KERN_ERR "%s: Bus master arbitration failure, status %4.4x.\n", - dev->name, csr0); - /* unlike for the lance, there is no restart needed */ - } - - if (must_restart) { - /* reset the chip to clear the error condition, then restart */ - lp->a.reset(ioaddr); - lp->a.write_csr(ioaddr, 4, 0x0915); - pcnet32_restart(dev, 0x0002); - netif_wake_queue(dev); - } - } - - /* Set interrupt enable. */ - lp->a.write_csr (ioaddr, 0, 0x0040); - lp->a.write_rap (ioaddr,rap); - - if (netif_msg_intr(lp)) - printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n", - dev->name, lp->a.read_csr (ioaddr, 0)); - - spin_unlock(&lp->lock); - - return IRQ_HANDLED; + } + + /* Set interrupt enable. */ + lp->a.write_csr(ioaddr, 0, 0x0040); + lp->a.write_rap(ioaddr, rap); + + if (netif_msg_intr(lp)) + printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n", + dev->name, lp->a.read_csr(ioaddr, 0)); + + spin_unlock(&lp->lock); + + return IRQ_HANDLED; } -static int -pcnet32_rx(struct net_device *dev) +static int pcnet32_rx(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - int entry = lp->cur_rx & lp->rx_mod_mask; - int boguscnt = lp->rx_ring_size / 2; - - /* If we own the next entry, it's a new packet. Send it up. */ - while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) { - int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8; - - if (status != 0x03) { /* There was an error. */ - /* - * There is a tricky error noted by John Murphy, - * to Russ Nelson: Even with full-sized - * buffers it's possible for a jabber packet to use two - * buffers, with only the last correctly noting the error. - */ - if (status & 0x01) /* Only count a general error at the */ - lp->stats.rx_errors++; /* end of a packet.*/ - if (status & 0x20) lp->stats.rx_frame_errors++; - if (status & 0x10) lp->stats.rx_over_errors++; - if (status & 0x08) lp->stats.rx_crc_errors++; - if (status & 0x04) lp->stats.rx_fifo_errors++; - lp->rx_ring[entry].status &= le16_to_cpu(0x03ff); - } else { - /* Malloc up new buffer, compatible with net-2e. */ - short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4; - struct sk_buff *skb; - - /* Discard oversize frames. */ - if (unlikely(pkt_len > PKT_BUF_SZ - 2)) { - if (netif_msg_drv(lp)) - printk(KERN_ERR "%s: Impossible packet size %d!\n", - dev->name, pkt_len); - lp->stats.rx_errors++; - } else if (pkt_len < 60) { - if (netif_msg_rx_err(lp)) - printk(KERN_ERR "%s: Runt packet!\n", dev->name); - lp->stats.rx_errors++; - } else { - int rx_in_place = 0; - - if (pkt_len > rx_copybreak) { - struct sk_buff *newskb; - - if ((newskb = dev_alloc_skb(PKT_BUF_SZ))) { - skb_reserve (newskb, 2); - skb = lp->rx_skbuff[entry]; - pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry], - PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); - skb_put (skb, pkt_len); - lp->rx_skbuff[entry] = newskb; - newskb->dev = dev; - lp->rx_dma_addr[entry] = - pci_map_single(lp->pci_dev, newskb->data, - PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); - lp->rx_ring[entry].base = le32_to_cpu(lp->rx_dma_addr[entry]); - rx_in_place = 1; - } else - skb = NULL; + struct pcnet32_private *lp = dev->priv; + int entry = lp->cur_rx & lp->rx_mod_mask; + int boguscnt = lp->rx_ring_size / 2; + + /* If we own the next entry, it's a new packet. Send it up. */ + while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) { + int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8; + + if (status != 0x03) { /* There was an error. */ + /* + * There is a tricky error noted by John Murphy, + * to Russ Nelson: Even with full-sized + * buffers it's possible for a jabber packet to use two + * buffers, with only the last correctly noting the error. + */ + if (status & 0x01) /* Only count a general error at the */ + lp->stats.rx_errors++; /* end of a packet. */ + if (status & 0x20) + lp->stats.rx_frame_errors++; + if (status & 0x10) + lp->stats.rx_over_errors++; + if (status & 0x08) + lp->stats.rx_crc_errors++; + if (status & 0x04) + lp->stats.rx_fifo_errors++; + lp->rx_ring[entry].status &= le16_to_cpu(0x03ff); } else { - skb = dev_alloc_skb(pkt_len+2); - } - - if (skb == NULL) { - int i; - if (netif_msg_drv(lp)) - printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n", - dev->name); - for (i = 0; i < lp->rx_ring_size; i++) - if ((short)le16_to_cpu(lp->rx_ring[(entry+i) - & lp->rx_mod_mask].status) < 0) - break; - - if (i > lp->rx_ring_size -2) { - lp->stats.rx_dropped++; - lp->rx_ring[entry].status |= le16_to_cpu(0x8000); - wmb(); /* Make sure adapter sees owner change */ - lp->cur_rx++; - } - break; - } - skb->dev = dev; - if (!rx_in_place) { - skb_reserve(skb,2); /* 16 byte align */ - skb_put(skb,pkt_len); /* Make room */ - pci_dma_sync_single_for_cpu(lp->pci_dev, - lp->rx_dma_addr[entry], - PKT_BUF_SZ-2, - PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, - (unsigned char *)(lp->rx_skbuff[entry]->data), - pkt_len,0); - pci_dma_sync_single_for_device(lp->pci_dev, - lp->rx_dma_addr[entry], - PKT_BUF_SZ-2, - PCI_DMA_FROMDEVICE); + /* Malloc up new buffer, compatible with net-2e. */ + short pkt_len = + (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff) + - 4; + struct sk_buff *skb; + + /* Discard oversize frames. */ + if (unlikely(pkt_len > PKT_BUF_SZ - 2)) { + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: Impossible packet size %d!\n", + dev->name, pkt_len); + lp->stats.rx_errors++; + } else if (pkt_len < 60) { + if (netif_msg_rx_err(lp)) + printk(KERN_ERR "%s: Runt packet!\n", + dev->name); + lp->stats.rx_errors++; + } else { + int rx_in_place = 0; + + if (pkt_len > rx_copybreak) { + struct sk_buff *newskb; + + if ((newskb = + dev_alloc_skb(PKT_BUF_SZ))) { + skb_reserve(newskb, 2); + skb = lp->rx_skbuff[entry]; + pci_unmap_single(lp->pci_dev, + lp-> + rx_dma_addr + [entry], + PKT_BUF_SZ - 2, + PCI_DMA_FROMDEVICE); + skb_put(skb, pkt_len); + lp->rx_skbuff[entry] = newskb; + newskb->dev = dev; + lp->rx_dma_addr[entry] = + pci_map_single(lp->pci_dev, + newskb->data, + PKT_BUF_SZ - + 2, + PCI_DMA_FROMDEVICE); + lp->rx_ring[entry].base = + le32_to_cpu(lp-> + rx_dma_addr + [entry]); + rx_in_place = 1; + } else + skb = NULL; + } else { + skb = dev_alloc_skb(pkt_len + 2); + } + + if (skb == NULL) { + int i; + if (netif_msg_drv(lp)) + printk(KERN_ERR + "%s: Memory squeeze, deferring packet.\n", + dev->name); + for (i = 0; i < lp->rx_ring_size; i++) + if ((short) + le16_to_cpu(lp-> + rx_ring[(entry + + i) + & lp-> + rx_mod_mask]. + status) < 0) + break; + + if (i > lp->rx_ring_size - 2) { + lp->stats.rx_dropped++; + lp->rx_ring[entry].status |= + le16_to_cpu(0x8000); + wmb(); /* Make sure adapter sees owner change */ + lp->cur_rx++; + } + break; + } + skb->dev = dev; + if (!rx_in_place) { + skb_reserve(skb, 2); /* 16 byte align */ + skb_put(skb, pkt_len); /* Make room */ + pci_dma_sync_single_for_cpu(lp->pci_dev, + lp-> + rx_dma_addr + [entry], + PKT_BUF_SZ - + 2, + PCI_DMA_FROMDEVICE); + eth_copy_and_sum(skb, + (unsigned char *)(lp-> + rx_skbuff + [entry]-> + data), + pkt_len, 0); + pci_dma_sync_single_for_device(lp-> + pci_dev, + lp-> + rx_dma_addr + [entry], + PKT_BUF_SZ + - 2, + PCI_DMA_FROMDEVICE); + } + lp->stats.rx_bytes += skb->len; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->last_rx = jiffies; + lp->stats.rx_packets++; + } } - lp->stats.rx_bytes += skb->len; - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - dev->last_rx = jiffies; - lp->stats.rx_packets++; - } + /* + * The docs say that the buffer length isn't touched, but Andrew Boyd + * of QNX reports that some revs of the 79C965 clear it. + */ + lp->rx_ring[entry].buf_length = le16_to_cpu(2 - PKT_BUF_SZ); + wmb(); /* Make sure owner changes after all others are visible */ + lp->rx_ring[entry].status |= le16_to_cpu(0x8000); + entry = (++lp->cur_rx) & lp->rx_mod_mask; + if (--boguscnt <= 0) + break; /* don't stay in loop forever */ } - /* - * The docs say that the buffer length isn't touched, but Andrew Boyd - * of QNX reports that some revs of the 79C965 clear it. - */ - lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ); - wmb(); /* Make sure owner changes after all others are visible */ - lp->rx_ring[entry].status |= le16_to_cpu(0x8000); - entry = (++lp->cur_rx) & lp->rx_mod_mask; - if (--boguscnt <= 0) break; /* don't stay in loop forever */ - } - - return 0; + + return 0; } -static int -pcnet32_close(struct net_device *dev) +static int pcnet32_close(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr; - struct pcnet32_private *lp = dev->priv; - int i; - unsigned long flags; + unsigned long ioaddr = dev->base_addr; + struct pcnet32_private *lp = dev->priv; + int i; + unsigned long flags; - del_timer_sync(&lp->watchdog_timer); + del_timer_sync(&lp->watchdog_timer); - netif_stop_queue(dev); + netif_stop_queue(dev); - spin_lock_irqsave(&lp->lock, flags); + spin_lock_irqsave(&lp->lock, flags); - lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112); + lp->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112); - if (netif_msg_ifdown(lp)) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, lp->a.read_csr (ioaddr, 0)); + if (netif_msg_ifdown(lp)) + printk(KERN_DEBUG + "%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, lp->a.read_csr(ioaddr, 0)); - /* We stop the PCNET32 here -- it occasionally polls memory if we don't. */ - lp->a.write_csr (ioaddr, 0, 0x0004); + /* We stop the PCNET32 here -- it occasionally polls memory if we don't. */ + lp->a.write_csr(ioaddr, 0, 0x0004); - /* - * Switch back to 16bit mode to avoid problems with dumb - * DOS packet driver after a warm reboot - */ - lp->a.write_bcr (ioaddr, 20, 4); + /* + * Switch back to 16bit mode to avoid problems with dumb + * DOS packet driver after a warm reboot + */ + lp->a.write_bcr(ioaddr, 20, 4); - spin_unlock_irqrestore(&lp->lock, flags); + spin_unlock_irqrestore(&lp->lock, flags); - free_irq(dev->irq, dev); + free_irq(dev->irq, dev); - spin_lock_irqsave(&lp->lock, flags); + spin_lock_irqsave(&lp->lock, flags); - /* free all allocated skbuffs */ - for (i = 0; i < lp->rx_ring_size; i++) { - lp->rx_ring[i].status = 0; - wmb(); /* Make sure adapter sees owner change */ - if (lp->rx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(lp->rx_skbuff[i]); + /* free all allocated skbuffs */ + for (i = 0; i < lp->rx_ring_size; i++) { + lp->rx_ring[i].status = 0; + wmb(); /* Make sure adapter sees owner change */ + if (lp->rx_skbuff[i]) { + pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], + PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); + dev_kfree_skb(lp->rx_skbuff[i]); + } + lp->rx_skbuff[i] = NULL; + lp->rx_dma_addr[i] = 0; } - lp->rx_skbuff[i] = NULL; - lp->rx_dma_addr[i] = 0; - } - for (i = 0; i < lp->tx_ring_size; i++) { - lp->tx_ring[i].status = 0; /* CPU owns buffer */ - wmb(); /* Make sure adapter sees owner change */ - if (lp->tx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], - lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); - dev_kfree_skb(lp->tx_skbuff[i]); + for (i = 0; i < lp->tx_ring_size; i++) { + lp->tx_ring[i].status = 0; /* CPU owns buffer */ + wmb(); /* Make sure adapter sees owner change */ + if (lp->tx_skbuff[i]) { + pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], + lp->tx_skbuff[i]->len, + PCI_DMA_TODEVICE); + dev_kfree_skb(lp->tx_skbuff[i]); + } + lp->tx_skbuff[i] = NULL; + lp->tx_dma_addr[i] = 0; } - lp->tx_skbuff[i] = NULL; - lp->tx_dma_addr[i] = 0; - } - spin_unlock_irqrestore(&lp->lock, flags); + spin_unlock_irqrestore(&lp->lock, flags); - return 0; + return 0; } -static struct net_device_stats * -pcnet32_get_stats(struct net_device *dev) +static struct net_device_stats *pcnet32_get_stats(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - u16 saved_addr; - unsigned long flags; - - spin_lock_irqsave(&lp->lock, flags); - saved_addr = lp->a.read_rap(ioaddr); - lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112); - lp->a.write_rap(ioaddr, saved_addr); - spin_unlock_irqrestore(&lp->lock, flags); - - return &lp->stats; + struct pcnet32_private *lp = dev->priv; + unsigned long ioaddr = dev->base_addr; + u16 saved_addr; + unsigned long flags; + + spin_lock_irqsave(&lp->lock, flags); + saved_addr = lp->a.read_rap(ioaddr); + lp->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112); + lp->a.write_rap(ioaddr, saved_addr); + spin_unlock_irqrestore(&lp->lock, flags); + + return &lp->stats; } /* taken from the sunlance driver, which it took from the depca driver */ -static void pcnet32_load_multicast (struct net_device *dev) +static void pcnet32_load_multicast(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - volatile struct pcnet32_init_block *ib = &lp->init_block; - volatile u16 *mcast_table = (u16 *)&ib->filter; - struct dev_mc_list *dmi=dev->mc_list; - char *addrs; - int i; - u32 crc; - - /* set all multicast bits */ - if (dev->flags & IFF_ALLMULTI) { - ib->filter[0] = 0xffffffff; - ib->filter[1] = 0xffffffff; + struct pcnet32_private *lp = dev->priv; + volatile struct pcnet32_init_block *ib = &lp->init_block; + volatile u16 *mcast_table = (u16 *) & ib->filter; + struct dev_mc_list *dmi = dev->mc_list; + char *addrs; + int i; + u32 crc; + + /* set all multicast bits */ + if (dev->flags & IFF_ALLMULTI) { + ib->filter[0] = 0xffffffff; + ib->filter[1] = 0xffffffff; + return; + } + /* clear the multicast filter */ + ib->filter[0] = 0; + ib->filter[1] = 0; + + /* Add addresses */ + for (i = 0; i < dev->mc_count; i++) { + addrs = dmi->dmi_addr; + dmi = dmi->next; + + /* multicast address? */ + if (!(*addrs & 1)) + continue; + + crc = ether_crc_le(6, addrs); + crc = crc >> 26; + mcast_table[crc >> 4] = + le16_to_cpu(le16_to_cpu(mcast_table[crc >> 4]) | + (1 << (crc & 0xf))); + } return; - } - /* clear the multicast filter */ - ib->filter[0] = 0; - ib->filter[1] = 0; - - /* Add addresses */ - for (i = 0; i < dev->mc_count; i++) { - addrs = dmi->dmi_addr; - dmi = dmi->next; - - /* multicast address? */ - if (!(*addrs & 1)) - continue; - - crc = ether_crc_le(6, addrs); - crc = crc >> 26; - mcast_table [crc >> 4] = le16_to_cpu( - le16_to_cpu(mcast_table [crc >> 4]) | (1 << (crc & 0xf))); - } - return; } - /* * Set or clear the multicast filter for this adaptor. */ static void pcnet32_set_multicast_list(struct net_device *dev) { - unsigned long ioaddr = dev->base_addr, flags; - struct pcnet32_private *lp = dev->priv; - - spin_lock_irqsave(&lp->lock, flags); - if (dev->flags&IFF_PROMISC) { - /* Log any net taps. */ - if (netif_msg_hw(lp)) - printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name); - lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << 7); - } else { - lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); - pcnet32_load_multicast (dev); - } - - lp->a.write_csr (ioaddr, 0, 0x0004); /* Temporarily stop the lance. */ - pcnet32_restart(dev, 0x0042); /* Resume normal operation */ - netif_wake_queue(dev); - - spin_unlock_irqrestore(&lp->lock, flags); + unsigned long ioaddr = dev->base_addr, flags; + struct pcnet32_private *lp = dev->priv; + + spin_lock_irqsave(&lp->lock, flags); + if (dev->flags & IFF_PROMISC) { + /* Log any net taps. */ + if (netif_msg_hw(lp)) + printk(KERN_INFO "%s: Promiscuous mode enabled.\n", + dev->name); + lp->init_block.mode = + le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << + 7); + } else { + lp->init_block.mode = + le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); + pcnet32_load_multicast(dev); + } + + lp->a.write_csr(ioaddr, 0, 0x0004); /* Temporarily stop the lance. */ + pcnet32_restart(dev, 0x0042); /* Resume normal operation */ + netif_wake_queue(dev); + + spin_unlock_irqrestore(&lp->lock, flags); } /* This routine assumes that the lp->lock is held */ static int mdio_read(struct net_device *dev, int phy_id, int reg_num) { - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - u16 val_out; + struct pcnet32_private *lp = dev->priv; + unsigned long ioaddr = dev->base_addr; + u16 val_out; - if (!lp->mii) - return 0; + if (!lp->mii) + return 0; - lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f)); - val_out = lp->a.read_bcr(ioaddr, 34); + lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f)); + val_out = lp->a.read_bcr(ioaddr, 34); - return val_out; + return val_out; } /* This routine assumes that the lp->lock is held */ static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val) { - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; + struct pcnet32_private *lp = dev->priv; + unsigned long ioaddr = dev->base_addr; - if (!lp->mii) - return; + if (!lp->mii) + return; - lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f)); - lp->a.write_bcr(ioaddr, 34, val); + lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f)); + lp->a.write_bcr(ioaddr, 34, val); } static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct pcnet32_private *lp = dev->priv; - int rc; - unsigned long flags; + struct pcnet32_private *lp = dev->priv; + int rc; + unsigned long flags; - /* SIOC[GS]MIIxxx ioctls */ - if (lp->mii) { - spin_lock_irqsave(&lp->lock, flags); - rc = generic_mii_ioctl(&lp->mii_if, if_mii(rq), cmd, NULL); - spin_unlock_irqrestore(&lp->lock, flags); - } else { - rc = -EOPNOTSUPP; - } + /* SIOC[GS]MIIxxx ioctls */ + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); + rc = generic_mii_ioctl(&lp->mii_if, if_mii(rq), cmd, NULL); + spin_unlock_irqrestore(&lp->lock, flags); + } else { + rc = -EOPNOTSUPP; + } - return rc; + return rc; } static int pcnet32_check_otherphy(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - struct mii_if_info mii = lp->mii_if; - u16 bmcr; - int i; - - for (i = 0; i < PCNET32_MAX_PHYS; i++) { - if (i == lp->mii_if.phy_id) - continue; /* skip active phy */ - if (lp->phymask & (1 << i)) { - mii.phy_id = i; - if (mii_link_ok(&mii)) { - /* found PHY with active link */ - if (netif_msg_link(lp)) - printk(KERN_INFO "%s: Using PHY number %d.\n", dev->name, i); - - /* isolate inactive phy */ - bmcr = mdio_read(dev, lp->mii_if.phy_id, MII_BMCR); - mdio_write(dev, lp->mii_if.phy_id, MII_BMCR, bmcr | BMCR_ISOLATE); - - /* de-isolate new phy */ - bmcr = mdio_read(dev, i, MII_BMCR); - mdio_write(dev, i, MII_BMCR, bmcr & ~BMCR_ISOLATE); + struct pcnet32_private *lp = dev->priv; + struct mii_if_info mii = lp->mii_if; + u16 bmcr; + int i; - /* set new phy address */ - lp->mii_if.phy_id = i; - return 1; - } + for (i = 0; i < PCNET32_MAX_PHYS; i++) { + if (i == lp->mii_if.phy_id) + continue; /* skip active phy */ + if (lp->phymask & (1 << i)) { + mii.phy_id = i; + if (mii_link_ok(&mii)) { + /* found PHY with active link */ + if (netif_msg_link(lp)) + printk(KERN_INFO + "%s: Using PHY number %d.\n", + dev->name, i); + + /* isolate inactive phy */ + bmcr = + mdio_read(dev, lp->mii_if.phy_id, MII_BMCR); + mdio_write(dev, lp->mii_if.phy_id, MII_BMCR, + bmcr | BMCR_ISOLATE); + + /* de-isolate new phy */ + bmcr = mdio_read(dev, i, MII_BMCR); + mdio_write(dev, i, MII_BMCR, + bmcr & ~BMCR_ISOLATE); + + /* set new phy address */ + lp->mii_if.phy_id = i; + return 1; + } + } } - } - return 0; + return 0; } /* @@ -2568,51 +2719,53 @@ static int pcnet32_check_otherphy(struct net_device *dev) static void pcnet32_check_media(struct net_device *dev, int verbose) { - struct pcnet32_private *lp = dev->priv; - int curr_link; - int prev_link = netif_carrier_ok(dev) ? 1 : 0; - u32 bcr9; - - if (lp->mii) { - curr_link = mii_link_ok(&lp->mii_if); - } else { - ulong ioaddr = dev->base_addr; /* card base I/O address */ - curr_link = (lp->a.read_bcr(ioaddr, 4) != 0xc0); - } - if (!curr_link) { - if (prev_link || verbose) { - netif_carrier_off(dev); - if (netif_msg_link(lp)) - printk(KERN_INFO "%s: link down\n", dev->name); - } - if (lp->phycount > 1) { - curr_link = pcnet32_check_otherphy(dev); - prev_link = 0; - } - } else if (verbose || !prev_link) { - netif_carrier_on(dev); + struct pcnet32_private *lp = dev->priv; + int curr_link; + int prev_link = netif_carrier_ok(dev) ? 1 : 0; + u32 bcr9; + if (lp->mii) { - if (netif_msg_link(lp)) { - struct ethtool_cmd ecmd; - mii_ethtool_gset(&lp->mii_if, &ecmd); - printk(KERN_INFO "%s: link up, %sMbps, %s-duplex\n", - dev->name, - (ecmd.speed == SPEED_100) ? "100" : "10", - (ecmd.duplex == DUPLEX_FULL) ? "full" : "half"); - } - bcr9 = lp->a.read_bcr(dev->base_addr, 9); - if ((bcr9 & (1 << 0)) != lp->mii_if.full_duplex) { - if (lp->mii_if.full_duplex) - bcr9 |= (1 << 0); - else - bcr9 &= ~(1 << 0); - lp->a.write_bcr(dev->base_addr, 9, bcr9); - } + curr_link = mii_link_ok(&lp->mii_if); } else { - if (netif_msg_link(lp)) - printk(KERN_INFO "%s: link up\n", dev->name); + ulong ioaddr = dev->base_addr; /* card base I/O address */ + curr_link = (lp->a.read_bcr(ioaddr, 4) != 0xc0); + } + if (!curr_link) { + if (prev_link || verbose) { + netif_carrier_off(dev); + if (netif_msg_link(lp)) + printk(KERN_INFO "%s: link down\n", dev->name); + } + if (lp->phycount > 1) { + curr_link = pcnet32_check_otherphy(dev); + prev_link = 0; + } + } else if (verbose || !prev_link) { + netif_carrier_on(dev); + if (lp->mii) { + if (netif_msg_link(lp)) { + struct ethtool_cmd ecmd; + mii_ethtool_gset(&lp->mii_if, &ecmd); + printk(KERN_INFO + "%s: link up, %sMbps, %s-duplex\n", + dev->name, + (ecmd.speed == SPEED_100) ? "100" : "10", + (ecmd.duplex == + DUPLEX_FULL) ? "full" : "half"); + } + bcr9 = lp->a.read_bcr(dev->base_addr, 9); + if ((bcr9 & (1 << 0)) != lp->mii_if.full_duplex) { + if (lp->mii_if.full_duplex) + bcr9 |= (1 << 0); + else + bcr9 &= ~(1 << 0); + lp->a.write_bcr(dev->base_addr, 9, bcr9); + } + } else { + if (netif_msg_link(lp)) + printk(KERN_INFO "%s: link up\n", dev->name); + } } - } } /* @@ -2622,39 +2775,39 @@ static void pcnet32_check_media(struct net_device *dev, int verbose) static void pcnet32_watchdog(struct net_device *dev) { - struct pcnet32_private *lp = dev->priv; - unsigned long flags; + struct pcnet32_private *lp = dev->priv; + unsigned long flags; - /* Print the link status if it has changed */ - spin_lock_irqsave(&lp->lock, flags); - pcnet32_check_media(dev, 0); - spin_unlock_irqrestore(&lp->lock, flags); + /* Print the link status if it has changed */ + spin_lock_irqsave(&lp->lock, flags); + pcnet32_check_media(dev, 0); + spin_unlock_irqrestore(&lp->lock, flags); - mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); + mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); } static void __devexit pcnet32_remove_one(struct pci_dev *pdev) { - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev) { - struct pcnet32_private *lp = dev->priv; - - unregister_netdev(dev); - pcnet32_free_ring(dev); - release_region(dev->base_addr, PCNET32_TOTAL_SIZE); - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - free_netdev(dev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } + struct net_device *dev = pci_get_drvdata(pdev); + + if (dev) { + struct pcnet32_private *lp = dev->priv; + + unregister_netdev(dev); + pcnet32_free_ring(dev); + release_region(dev->base_addr, PCNET32_TOTAL_SIZE); + pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); + free_netdev(dev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + } } static struct pci_driver pcnet32_driver = { - .name = DRV_NAME, - .probe = pcnet32_probe_pci, - .remove = __devexit_p(pcnet32_remove_one), - .id_table = pcnet32_pci_tbl, + .name = DRV_NAME, + .probe = pcnet32_probe_pci, + .remove = __devexit_p(pcnet32_remove_one), + .id_table = pcnet32_pci_tbl, }; /* An additional parameter that may be passed in... */ @@ -2665,9 +2818,11 @@ static int pcnet32_have_pci; module_param(debug, int, 0); MODULE_PARM_DESC(debug, DRV_NAME " debug level"); module_param(max_interrupt_work, int, 0); -MODULE_PARM_DESC(max_interrupt_work, DRV_NAME " maximum events handled per interrupt"); +MODULE_PARM_DESC(max_interrupt_work, + DRV_NAME " maximum events handled per interrupt"); module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, DRV_NAME " copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(rx_copybreak, + DRV_NAME " copy breakpoint for copy-only-tiny-frames"); module_param(tx_start_pt, int, 0); MODULE_PARM_DESC(tx_start_pt, DRV_NAME " transmit start point (0-3)"); module_param(pcnet32vlb, int, 0); @@ -2678,7 +2833,9 @@ module_param_array(full_duplex, int, NULL, 0); MODULE_PARM_DESC(full_duplex, DRV_NAME " full duplex setting(s) (1)"); /* Module Parameter for HomePNA cards added by Patrick Simmons, 2004 */ module_param_array(homepna, int, NULL, 0); -MODULE_PARM_DESC(homepna, DRV_NAME " mode for 79C978 cards (1 for HomePNA, 0 for Ethernet, default Ethernet"); +MODULE_PARM_DESC(homepna, + DRV_NAME + " mode for 79C978 cards (1 for HomePNA, 0 for Ethernet, default Ethernet"); MODULE_AUTHOR("Thomas Bogendoerfer"); MODULE_DESCRIPTION("Driver for PCnet32 and PCnetPCI based ethercards"); @@ -2688,44 +2845,44 @@ MODULE_LICENSE("GPL"); static int __init pcnet32_init_module(void) { - printk(KERN_INFO "%s", version); + printk(KERN_INFO "%s", version); - pcnet32_debug = netif_msg_init(debug, PCNET32_MSG_DEFAULT); + pcnet32_debug = netif_msg_init(debug, PCNET32_MSG_DEFAULT); - if ((tx_start_pt >= 0) && (tx_start_pt <= 3)) - tx_start = tx_start_pt; + if ((tx_start_pt >= 0) && (tx_start_pt <= 3)) + tx_start = tx_start_pt; - /* find the PCI devices */ - if (!pci_module_init(&pcnet32_driver)) - pcnet32_have_pci = 1; + /* find the PCI devices */ + if (!pci_module_init(&pcnet32_driver)) + pcnet32_have_pci = 1; - /* should we find any remaining VLbus devices ? */ - if (pcnet32vlb) - pcnet32_probe_vlbus(); + /* should we find any remaining VLbus devices ? */ + if (pcnet32vlb) + pcnet32_probe_vlbus(); - if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE)) - printk(KERN_INFO PFX "%d cards_found.\n", cards_found); + if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE)) + printk(KERN_INFO PFX "%d cards_found.\n", cards_found); - return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV; + return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV; } static void __exit pcnet32_cleanup_module(void) { - struct net_device *next_dev; - - while (pcnet32_dev) { - struct pcnet32_private *lp = pcnet32_dev->priv; - next_dev = lp->next; - unregister_netdev(pcnet32_dev); - pcnet32_free_ring(pcnet32_dev); - release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE); - pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - free_netdev(pcnet32_dev); - pcnet32_dev = next_dev; - } + struct net_device *next_dev; + + while (pcnet32_dev) { + struct pcnet32_private *lp = pcnet32_dev->priv; + next_dev = lp->next; + unregister_netdev(pcnet32_dev); + pcnet32_free_ring(pcnet32_dev); + release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE); + pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); + free_netdev(pcnet32_dev); + pcnet32_dev = next_dev; + } - if (pcnet32_have_pci) - pci_unregister_driver(&pcnet32_driver); + if (pcnet32_have_pci) + pci_unregister_driver(&pcnet32_driver); } module_init(pcnet32_init_module); -- cgit v1.2.3-59-g8ed1b From 0b5bf225c06e62eb6066fc5b7ccf4f296356c503 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 21 Mar 2006 16:22:47 -0500 Subject: [netdrvr] pcnet32: other source formatting cleanups - undo some Lindent damage by indenting member names - remove history at top of .c file, this is stored in the kernel repo changelog (in greater detail, even). --- drivers/net/pcnet32.c | 228 ++++++++++++-------------------------------------- 1 file changed, 54 insertions(+), 174 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 861361018640..9595f74da93f 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -155,126 +155,6 @@ static int homepna[MAX_UNITS]; * 16MB limitation and we don't need bounce buffers. */ -/* - * History: - * v0.01: Initial version - * only tested on Alpha Noname Board - * v0.02: changed IRQ handling for new interrupt scheme (dev_id) - * tested on a ASUS SP3G - * v0.10: fixed an odd problem with the 79C974 in a Compaq Deskpro XL - * looks like the 974 doesn't like stopping and restarting in a - * short period of time; now we do a reinit of the lance; the - * bug was triggered by doing ifconfig eth0 broadcast - * and hangs the machine (thanks to Klaus Liedl for debugging) - * v0.12: by suggestion from Donald Becker: Renamed driver to pcnet32, - * made it standalone (no need for lance.c) - * v0.13: added additional PCI detecting for special PCI devices (Compaq) - * v0.14: stripped down additional PCI probe (thanks to David C Niemi - * and sveneric@xs4all.nl for testing this on their Compaq boxes) - * v0.15: added 79C965 (VLB) probe - * added interrupt sharing for PCI chips - * v0.16: fixed set_multicast_list on Alpha machines - * v0.17: removed hack from dev.c; now pcnet32 uses ethif_probe in Space.c - * v0.19: changed setting of autoselect bit - * v0.20: removed additional Compaq PCI probe; there is now a working one - * in arch/i386/bios32.c - * v0.21: added endian conversion for ppc, from work by cort@cs.nmt.edu - * v0.22: added printing of status to ring dump - * v0.23: changed enet_statistics to net_devive_stats - * v0.90: added multicast filter - * added module support - * changed irq probe to new style - * added PCnetFast chip id - * added fix for receive stalls with Intel saturn chipsets - * added in-place rx skbs like in the tulip driver - * minor cleanups - * v0.91: added PCnetFast+ chip id - * back port to 2.0.x - * v1.00: added some stuff from Donald Becker's 2.0.34 version - * added support for byte counters in net_dev_stats - * v1.01: do ring dumps, only when debugging the driver - * increased the transmit timeout - * v1.02: fixed memory leak in pcnet32_init_ring() - * v1.10: workaround for stopped transmitter - * added port selection for modules - * detect special T1/E1 WAN card and setup port selection - * v1.11: fixed wrong checking of Tx errors - * v1.20: added check of return value kmalloc (cpeterso@cs.washington.edu) - * added save original kmalloc addr for freeing (mcr@solidum.com) - * added support for PCnetHome chip (joe@MIT.EDU) - * rewritten PCI card detection - * added dwio mode to get driver working on some PPC machines - * v1.21: added mii selection and mii ioctl - * v1.22: changed pci scanning code to make PPC people happy - * fixed switching to 32bit mode in pcnet32_open() (thanks - * to Michael Richard for noticing this one) - * added sub vendor/device id matching (thanks again to - * Michael Richard ) - * added chip id for 79c973/975 (thanks to Zach Brown ) - * v1.23 fixed small bug, when manual selecting MII speed/duplex - * v1.24 Applied Thomas' patch to use TxStartPoint and thus decrease TxFIFO - * underflows. Added tx_start_pt module parameter. Increased - * TX_RING_SIZE from 16 to 32. Added #ifdef'd code to use DXSUFLO - * for FAST[+] chipsets. - * v1.24ac Added SMP spinlocking - Alan Cox - * v1.25kf Added No Interrupt on successful Tx for some Tx's - * v1.26 Converted to pci_alloc_consistent, Jamey Hicks / George France - * - * - Fixed a few bugs, related to running the controller in 32bit mode. - * 23 Oct, 2000. Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * v1.26p Fix oops on rmmod+insmod; plug i/o resource leak - Paul Gortmaker - * v1.27 improved CSR/PROM address detection, lots of cleanups, - * new pcnet32vlb module option, HP-PARISC support, - * added module parameter descriptions, - * initial ethtool support - Helge Deller - * v1.27a Sun Feb 10 2002 Go Taniguchi - * use alloc_etherdev and register_netdev - * fix pci probe not increment cards_found - * FD auto negotiate error workaround for xSeries250 - * clean up and using new mii module - * v1.27b Sep 30 2002 Kent Yoder - * Added timer for cable connection state changes. - * v1.28 20 Feb 2004 Don Fry - * Jon Mason , Chinmay Albal - * Now uses ethtool_ops, netif_msg_* and generic_mii_ioctl. - * Fixes bogus 'Bus master arbitration failure', pci_[un]map_single - * length errors, and transmit hangs. Cleans up after errors in open. - * Jim Lewis added ethernet loopback test. - * Thomas Munck Steenholdt non-mii ioctl corrections. - * v1.29 6 Apr 2004 Jim Lewis added physical - * identification code (blink led's) and register dump. - * Don Fry added timer for 971/972 so skbufs don't remain on tx ring - * forever. - * v1.30 18 May 2004 Don Fry removed timer and Last Transmit Interrupt - * (ltint) as they added complexity and didn't give good throughput. - * v1.30a 22 May 2004 Don Fry limit frames received during interrupt. - * v1.30b 24 May 2004 Don Fry fix bogus tx carrier errors with 79c973, - * assisted by Bruce Penrod . - * v1.30c 25 May 2004 Don Fry added netif_wake_queue after pcnet32_restart. - * v1.30d 01 Jun 2004 Don Fry discard oversize rx packets. - * v1.30e 11 Jun 2004 Don Fry recover after fifo error and rx hang. - * v1.30f 16 Jun 2004 Don Fry cleanup IRQ to allow 0 and 1 for PCI, - * expanding on suggestions from Ralf Baechle , - * and Brian Murphy . - * v1.30g 22 Jun 2004 Patrick Simmons added option - * homepna for selecting HomePNA mode for PCNet/Home 79C978. - * v1.30h 24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32. - * v1.30i 28 Jun 2004 Don Fry change to use module_param. - * v1.30j 29 Apr 2005 Don Fry fix skb/map leak with loopback test. - * v1.31 02 Sep 2005 Hubert WS Lin added set_ringparam(). - * v1.31a 12 Sep 2005 Hubert WS Lin set min ring size to 4 - * to allow loopback test to work unchanged. - * v1.31b 06 Oct 2005 Don Fry changed alloc_ring to show name of device - * if allocation fails - * v1.31c 01 Nov 2005 Don Fry Allied Telesyn 2700/2701 FX are 100Mbit only. - * Force 100Mbit FD if Auto (ASEL) is selected. - * See Bugzilla 2669 and 4551. - * v1.32 18 Mar2006 Thomas Bogendoerfer and Don Fry added Multi-Phy - * handling for supporting AT-270x FTX cards with FX and Tx PHYs. - * Philippe Seewer assisted with auto negotiation and testing. - */ - /* * Set the number of Tx and Rx buffers, using Log_2(# buffers). * Reasonable default values are 4 Tx buffers, and 16 Rx buffers. @@ -310,31 +190,31 @@ static int homepna[MAX_UNITS]; /* The PCNET32 Rx and Tx ring descriptors. */ struct pcnet32_rx_head { - u32 base; - s16 buf_length; - s16 status; - u32 msg_length; - u32 reserved; + u32 base; + s16 buf_length; + s16 status; + u32 msg_length; + u32 reserved; }; struct pcnet32_tx_head { - u32 base; - s16 length; - s16 status; - u32 misc; - u32 reserved; + u32 base; + s16 length; + s16 status; + u32 misc; + u32 reserved; }; /* The PCNET32 32-Bit initialization block, described in databook. */ struct pcnet32_init_block { - u16 mode; - u16 tlen_rlen; - u8 phys_addr[6]; - u16 reserved; - u32 filter[2]; + u16 mode; + u16 tlen_rlen; + u8 phys_addr[6]; + u16 reserved; + u32 filter[2]; /* Receive and transmit ring base, along with extra bits. */ - u32 rx_ring; - u32 tx_ring; + u32 rx_ring; + u32 tx_ring; }; /* PCnet32 access functions */ @@ -355,46 +235,46 @@ struct pcnet32_access { struct pcnet32_private { struct pcnet32_init_block init_block; /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */ - struct pcnet32_rx_head *rx_ring; - struct pcnet32_tx_head *tx_ring; - dma_addr_t dma_addr; /* DMA address of beginning of this - object, returned by - pci_alloc_consistent */ - struct pci_dev *pci_dev; /* Pointer to the associated pci device - structure */ - const char *name; + struct pcnet32_rx_head *rx_ring; + struct pcnet32_tx_head *tx_ring; + dma_addr_t dma_addr;/* DMA address of beginning of this + object, returned by pci_alloc_consistent */ + struct pci_dev *pci_dev; + const char *name; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct sk_buff **tx_skbuff; - struct sk_buff **rx_skbuff; - dma_addr_t *tx_dma_addr; - dma_addr_t *rx_dma_addr; - struct pcnet32_access a; - spinlock_t lock; /* Guard lock */ - unsigned int cur_rx, cur_tx; /* The next free ring entry */ - unsigned int rx_ring_size; /* current rx ring size */ - unsigned int tx_ring_size; /* current tx ring size */ - unsigned int rx_mod_mask; /* rx ring modular mask */ - unsigned int tx_mod_mask; /* tx ring modular mask */ - unsigned short rx_len_bits; - unsigned short tx_len_bits; - dma_addr_t rx_ring_dma_addr; - dma_addr_t tx_ring_dma_addr; - unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - struct net_device_stats stats; - char tx_full; - char phycount; /* number of phys found */ - int options; - unsigned int shared_irq:1, /* shared irq possible */ - dxsuflo:1, /* disable transmit stop on uflo */ - mii:1; /* mii port available */ - struct net_device *next; - struct mii_if_info mii_if; - struct timer_list watchdog_timer; - struct timer_list blink_timer; - u32 msg_enable; /* debug message level */ + struct sk_buff **tx_skbuff; + struct sk_buff **rx_skbuff; + dma_addr_t *tx_dma_addr; + dma_addr_t *rx_dma_addr; + struct pcnet32_access a; + spinlock_t lock; /* Guard lock */ + unsigned int cur_rx, cur_tx; /* The next free ring entry */ + unsigned int rx_ring_size; /* current rx ring size */ + unsigned int tx_ring_size; /* current tx ring size */ + unsigned int rx_mod_mask; /* rx ring modular mask */ + unsigned int tx_mod_mask; /* tx ring modular mask */ + unsigned short rx_len_bits; + unsigned short tx_len_bits; + dma_addr_t rx_ring_dma_addr; + dma_addr_t tx_ring_dma_addr; + unsigned int dirty_rx, /* ring entries to be freed. */ + dirty_tx; + + struct net_device_stats stats; + char tx_full; + char phycount; /* number of phys found */ + int options; + unsigned int shared_irq:1, /* shared irq possible */ + dxsuflo:1, /* disable transmit stop on uflo */ + mii:1; /* mii port available */ + struct net_device *next; + struct mii_if_info mii_if; + struct timer_list watchdog_timer; + struct timer_list blink_timer; + u32 msg_enable; /* debug message level */ /* each bit indicates an available PHY */ - u32 phymask; + u32 phymask; }; static void pcnet32_probe_vlbus(void); -- cgit v1.2.3-59-g8ed1b From 18ec5c731271939acb414614e964c15c8ef52156 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 20 Mar 2006 17:10:17 +0000 Subject: [ARM] 3373/1: move uengine loader to arch/arm/common Patch from Lennert Buytenhek Move the uengine loader from arch/arm/mach-ixp2000 to arch/arm/common so that ixp23xx can use it too. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/common/Makefile | 1 + arch/arm/common/uengine.c | 473 +++++++++++++++++++++++++++++++++ arch/arm/mach-ixp2000/Makefile | 2 +- arch/arm/mach-ixp2000/uengine.c | 473 --------------------------------- drivers/net/ixp2000/enp2611.c | 2 +- drivers/net/ixp2000/ixpdev.c | 2 +- include/asm-arm/arch-ixp2000/uengine.h | 62 ----- include/asm-arm/hardware/uengine.h | 62 +++++ 8 files changed, 539 insertions(+), 538 deletions(-) create mode 100644 arch/arm/common/uengine.c delete mode 100644 arch/arm/mach-ixp2000/uengine.c delete mode 100644 include/asm-arm/arch-ixp2000/uengine.h create mode 100644 include/asm-arm/hardware/uengine.h (limited to 'drivers') diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index c81a2ff6b5be..847e3e6356c6 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_SHARP_LOCOMO) += locomo.o 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 diff --git a/arch/arm/common/uengine.c b/arch/arm/common/uengine.c new file mode 100644 index 000000000000..a1310b71004e --- /dev/null +++ b/arch/arm/common/uengine.c @@ -0,0 +1,473 @@ +/* + * Generic library functions for the microengines found on the Intel + * IXP2000 series of network processors. + * + * Copyright (C) 2004, 2005 Lennert Buytenhek + * Dedicated to Marija Kulikova. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USTORE_ADDRESS 0x000 +#define USTORE_DATA_LOWER 0x004 +#define USTORE_DATA_UPPER 0x008 +#define CTX_ENABLES 0x018 +#define CC_ENABLE 0x01c +#define CSR_CTX_POINTER 0x020 +#define INDIRECT_CTX_STS 0x040 +#define ACTIVE_CTX_STS 0x044 +#define INDIRECT_CTX_SIG_EVENTS 0x048 +#define INDIRECT_CTX_WAKEUP_EVENTS 0x050 +#define NN_PUT 0x080 +#define NN_GET 0x084 +#define TIMESTAMP_LOW 0x0c0 +#define TIMESTAMP_HIGH 0x0c4 +#define T_INDEX_BYTE_INDEX 0x0f4 +#define LOCAL_CSR_STATUS 0x180 + +u32 ixp2000_uengine_mask; + +static void *ixp2000_uengine_csr_area(int uengine) +{ + return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10); +} + +/* + * LOCAL_CSR_STATUS=1 after a read or write to a microengine's CSR + * space means that the microengine we tried to access was also trying + * to access its own CSR space on the same clock cycle as we did. When + * this happens, we lose the arbitration process by default, and the + * read or write we tried to do was not actually performed, so we try + * again until it succeeds. + */ +u32 ixp2000_uengine_csr_read(int uengine, int offset) +{ + void *uebase; + u32 *local_csr_status; + u32 *reg; + u32 value; + + uebase = ixp2000_uengine_csr_area(uengine); + + local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); + reg = (u32 *)(uebase + offset); + do { + value = ixp2000_reg_read(reg); + } while (ixp2000_reg_read(local_csr_status) & 1); + + return value; +} +EXPORT_SYMBOL(ixp2000_uengine_csr_read); + +void ixp2000_uengine_csr_write(int uengine, int offset, u32 value) +{ + void *uebase; + u32 *local_csr_status; + u32 *reg; + + uebase = ixp2000_uengine_csr_area(uengine); + + local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); + reg = (u32 *)(uebase + offset); + do { + ixp2000_reg_write(reg, value); + } while (ixp2000_reg_read(local_csr_status) & 1); +} +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); +} +EXPORT_SYMBOL(ixp2000_uengine_reset); + +void ixp2000_uengine_set_mode(int uengine, u32 mode) +{ + /* + * CTL_STR_PAR_EN: unconditionally enable parity checking on + * control store. + */ + mode |= 0x10000000; + ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mode); + + /* + * Enable updating of condition codes. + */ + ixp2000_uengine_csr_write(uengine, CC_ENABLE, 0x00002000); + + /* + * Initialise other per-microengine registers. + */ + ixp2000_uengine_csr_write(uengine, NN_PUT, 0x00); + ixp2000_uengine_csr_write(uengine, NN_GET, 0x00); + ixp2000_uengine_csr_write(uengine, T_INDEX_BYTE_INDEX, 0); +} +EXPORT_SYMBOL(ixp2000_uengine_set_mode); + +static int make_even_parity(u32 x) +{ + return hweight32(x) & 1; +} + +static void ustore_write(int uengine, u64 insn) +{ + /* + * Generate even parity for top and bottom 20 bits. + */ + insn |= (u64)make_even_parity((insn >> 20) & 0x000fffff) << 41; + insn |= (u64)make_even_parity(insn & 0x000fffff) << 40; + + /* + * Write to microstore. The second write auto-increments + * the USTORE_ADDRESS index register. + */ + ixp2000_uengine_csr_write(uengine, USTORE_DATA_LOWER, (u32)insn); + ixp2000_uengine_csr_write(uengine, USTORE_DATA_UPPER, (u32)(insn >> 32)); +} + +void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns) +{ + int i; + + /* + * Start writing to microstore at address 0. + */ + ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x80000000); + for (i = 0; i < insns; i++) { + u64 insn; + + insn = (((u64)ucode[0]) << 32) | + (((u64)ucode[1]) << 24) | + (((u64)ucode[2]) << 16) | + (((u64)ucode[3]) << 8) | + ((u64)ucode[4]); + ucode += 5; + + ustore_write(uengine, insn); + } + + /* + * Pad with a few NOPs at the end (to avoid the microengine + * aborting as it prefetches beyond the last instruction), unless + * we run off the end of the instruction store first, at which + * point the address register will wrap back to zero. + */ + for (i = 0; i < 4; i++) { + u32 addr; + + addr = ixp2000_uengine_csr_read(uengine, USTORE_ADDRESS); + if (addr == 0x80000000) + break; + ustore_write(uengine, 0xf0000c0300ULL); + } + + /* + * End programming. + */ + ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x00000000); +} +EXPORT_SYMBOL(ixp2000_uengine_load_microcode); + +void ixp2000_uengine_init_context(int uengine, int context, int pc) +{ + /* + * Select the right context for indirect access. + */ + ixp2000_uengine_csr_write(uengine, CSR_CTX_POINTER, context); + + /* + * Initialise signal masks to immediately go to Ready state. + */ + ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_SIG_EVENTS, 1); + ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_WAKEUP_EVENTS, 1); + + /* + * Set program counter. + */ + ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_STS, pc); +} +EXPORT_SYMBOL(ixp2000_uengine_init_context); + +void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask) +{ + u32 mask; + + /* + * Enable the specified context to go to Executing state. + */ + mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); + mask |= ctx_mask << 8; + ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); +} +EXPORT_SYMBOL(ixp2000_uengine_start_contexts); + +void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask) +{ + u32 mask; + + /* + * Disable the Ready->Executing transition. Note that this + * does not stop the context until it voluntarily yields. + */ + mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); + mask &= ~(ctx_mask << 8); + ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); +} +EXPORT_SYMBOL(ixp2000_uengine_stop_contexts); + +static int check_ixp_type(struct ixp2000_uengine_code *c) +{ + u32 product_id; + u32 rev; + + product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID); + if (((product_id >> 16) & 0x1f) != 0) + return 0; + + switch ((product_id >> 8) & 0xff) { + case 0: /* IXP2800 */ + if (!(c->cpu_model_bitmask & 4)) + return 0; + break; + + case 1: /* IXP2850 */ + if (!(c->cpu_model_bitmask & 8)) + return 0; + break; + + case 2: /* IXP2400 */ + if (!(c->cpu_model_bitmask & 2)) + return 0; + break; + + default: + return 0; + } + + rev = product_id & 0xff; + if (rev < c->cpu_min_revision || rev > c->cpu_max_revision) + return 0; + + return 1; +} + +static void generate_ucode(u8 *ucode, u32 *gpr_a, u32 *gpr_b) +{ + int offset; + int i; + + offset = 0; + + for (i = 0; i < 128; i++) { + u8 b3; + u8 b2; + u8 b1; + u8 b0; + + b3 = (gpr_a[i] >> 24) & 0xff; + b2 = (gpr_a[i] >> 16) & 0xff; + b1 = (gpr_a[i] >> 8) & 0xff; + b0 = gpr_a[i] & 0xff; + + // immed[@ai, (b1 << 8) | b0] + // 11110000 0000VVVV VVVV11VV VVVVVV00 1IIIIIII + ucode[offset++] = 0xf0; + ucode[offset++] = (b1 >> 4); + ucode[offset++] = (b1 << 4) | 0x0c | (b0 >> 6); + ucode[offset++] = (b0 << 2); + ucode[offset++] = 0x80 | i; + + // immed_w1[@ai, (b3 << 8) | b2] + // 11110100 0100VVVV VVVV11VV VVVVVV00 1IIIIIII + ucode[offset++] = 0xf4; + ucode[offset++] = 0x40 | (b3 >> 4); + ucode[offset++] = (b3 << 4) | 0x0c | (b2 >> 6); + ucode[offset++] = (b2 << 2); + ucode[offset++] = 0x80 | i; + } + + for (i = 0; i < 128; i++) { + u8 b3; + u8 b2; + u8 b1; + u8 b0; + + b3 = (gpr_b[i] >> 24) & 0xff; + b2 = (gpr_b[i] >> 16) & 0xff; + b1 = (gpr_b[i] >> 8) & 0xff; + b0 = gpr_b[i] & 0xff; + + // immed[@bi, (b1 << 8) | b0] + // 11110000 0000VVVV VVVV001I IIIIII11 VVVVVVVV + ucode[offset++] = 0xf0; + ucode[offset++] = (b1 >> 4); + ucode[offset++] = (b1 << 4) | 0x02 | (i >> 6); + ucode[offset++] = (i << 2) | 0x03; + ucode[offset++] = b0; + + // immed_w1[@bi, (b3 << 8) | b2] + // 11110100 0100VVVV VVVV001I IIIIII11 VVVVVVVV + ucode[offset++] = 0xf4; + ucode[offset++] = 0x40 | (b3 >> 4); + ucode[offset++] = (b3 << 4) | 0x02 | (i >> 6); + ucode[offset++] = (i << 2) | 0x03; + ucode[offset++] = b2; + } + + // ctx_arb[kill] + ucode[offset++] = 0xe0; + ucode[offset++] = 0x00; + ucode[offset++] = 0x01; + ucode[offset++] = 0x00; + ucode[offset++] = 0x00; +} + +static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c) +{ + int per_ctx_regs; + u32 *gpr_a; + u32 *gpr_b; + u8 *ucode; + int i; + + gpr_a = kmalloc(128 * sizeof(u32), GFP_KERNEL); + gpr_b = kmalloc(128 * sizeof(u32), GFP_KERNEL); + ucode = kmalloc(513 * 5, GFP_KERNEL); + if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) { + kfree(ucode); + kfree(gpr_b); + kfree(gpr_a); + return 1; + } + + per_ctx_regs = 16; + if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS) + per_ctx_regs = 32; + + memset(gpr_a, 0, sizeof(gpr_a)); + memset(gpr_b, 0, sizeof(gpr_b)); + for (i = 0; i < 256; i++) { + struct ixp2000_reg_value *r = c->initial_reg_values + i; + u32 *bank; + int inc; + int j; + + if (r->reg == -1) + break; + + bank = (r->reg & 0x400) ? gpr_b : gpr_a; + inc = (r->reg & 0x80) ? 128 : per_ctx_regs; + + j = r->reg & 0x7f; + while (j < 128) { + bank[j] = r->value; + j += inc; + } + } + + generate_ucode(ucode, gpr_a, gpr_b); + ixp2000_uengine_load_microcode(uengine, ucode, 513); + ixp2000_uengine_init_context(uengine, 0, 0); + ixp2000_uengine_start_contexts(uengine, 0x01); + for (i = 0; i < 100; i++) { + u32 status; + + status = ixp2000_uengine_csr_read(uengine, ACTIVE_CTX_STS); + if (!(status & 0x80000000)) + break; + } + ixp2000_uengine_stop_contexts(uengine, 0x01); + + kfree(ucode); + kfree(gpr_b); + kfree(gpr_a); + + return !!(i == 100); +} + +int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c) +{ + int ctx; + + if (!check_ixp_type(c)) + return 1; + + if (!(ixp2000_uengine_mask & (1 << uengine))) + return 1; + + ixp2000_uengine_reset(1 << uengine); + ixp2000_uengine_set_mode(uengine, c->uengine_parameters); + if (set_initial_registers(uengine, c)) + return 1; + ixp2000_uengine_load_microcode(uengine, c->insns, c->num_insns); + + for (ctx = 0; ctx < 8; ctx++) + ixp2000_uengine_init_context(uengine, ctx, 0); + + return 0; +} +EXPORT_SYMBOL(ixp2000_uengine_load); + + +static int __init ixp2000_uengine_init(void) +{ + int uengine; + u32 value; + + /* + * Determine number of microengines present. + */ + switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) { + case 0: /* IXP2800 */ + case 1: /* IXP2850 */ + ixp2000_uengine_mask = 0x00ff00ff; + break; + + case 2: /* IXP2400 */ + ixp2000_uengine_mask = 0x000f000f; + break; + + default: + printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n", + (unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID)); + ixp2000_uengine_mask = 0x00000000; + break; + } + + /* + * Reset microengines. + */ + ixp2000_uengine_reset(ixp2000_uengine_mask); + + /* + * Synchronise timestamp counters across all microengines. + */ + value = ixp2000_reg_read(IXP2000_MISC_CONTROL); + ixp2000_reg_wrb(IXP2000_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); + + return 0; +} + +subsys_initcall(ixp2000_uengine_init); diff --git a/arch/arm/mach-ixp2000/Makefile b/arch/arm/mach-ixp2000/Makefile index 9621aeb61f46..1e6139d42a92 100644 --- a/arch/arm/mach-ixp2000/Makefile +++ b/arch/arm/mach-ixp2000/Makefile @@ -1,7 +1,7 @@ # # Makefile for the linux kernel. # -obj-y := core.o pci.o uengine.o +obj-y := core.o pci.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-ixp2000/uengine.c b/arch/arm/mach-ixp2000/uengine.c deleted file mode 100644 index ec4e007a22ef..000000000000 --- a/arch/arm/mach-ixp2000/uengine.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Generic library functions for the microengines found on the Intel - * IXP2000 series of network processors. - * - * Copyright (C) 2004, 2005 Lennert Buytenhek - * Dedicated to Marija Kulikova. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of the - * License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define USTORE_ADDRESS 0x000 -#define USTORE_DATA_LOWER 0x004 -#define USTORE_DATA_UPPER 0x008 -#define CTX_ENABLES 0x018 -#define CC_ENABLE 0x01c -#define CSR_CTX_POINTER 0x020 -#define INDIRECT_CTX_STS 0x040 -#define ACTIVE_CTX_STS 0x044 -#define INDIRECT_CTX_SIG_EVENTS 0x048 -#define INDIRECT_CTX_WAKEUP_EVENTS 0x050 -#define NN_PUT 0x080 -#define NN_GET 0x084 -#define TIMESTAMP_LOW 0x0c0 -#define TIMESTAMP_HIGH 0x0c4 -#define T_INDEX_BYTE_INDEX 0x0f4 -#define LOCAL_CSR_STATUS 0x180 - -u32 ixp2000_uengine_mask; - -static void *ixp2000_uengine_csr_area(int uengine) -{ - return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10); -} - -/* - * LOCAL_CSR_STATUS=1 after a read or write to a microengine's CSR - * space means that the microengine we tried to access was also trying - * to access its own CSR space on the same clock cycle as we did. When - * this happens, we lose the arbitration process by default, and the - * read or write we tried to do was not actually performed, so we try - * again until it succeeds. - */ -u32 ixp2000_uengine_csr_read(int uengine, int offset) -{ - void *uebase; - u32 *local_csr_status; - u32 *reg; - u32 value; - - uebase = ixp2000_uengine_csr_area(uengine); - - local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); - reg = (u32 *)(uebase + offset); - do { - value = ixp2000_reg_read(reg); - } while (ixp2000_reg_read(local_csr_status) & 1); - - return value; -} -EXPORT_SYMBOL(ixp2000_uengine_csr_read); - -void ixp2000_uengine_csr_write(int uengine, int offset, u32 value) -{ - void *uebase; - u32 *local_csr_status; - u32 *reg; - - uebase = ixp2000_uengine_csr_area(uengine); - - local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); - reg = (u32 *)(uebase + offset); - do { - ixp2000_reg_write(reg, value); - } while (ixp2000_reg_read(local_csr_status) & 1); -} -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); -} -EXPORT_SYMBOL(ixp2000_uengine_reset); - -void ixp2000_uengine_set_mode(int uengine, u32 mode) -{ - /* - * CTL_STR_PAR_EN: unconditionally enable parity checking on - * control store. - */ - mode |= 0x10000000; - ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mode); - - /* - * Enable updating of condition codes. - */ - ixp2000_uengine_csr_write(uengine, CC_ENABLE, 0x00002000); - - /* - * Initialise other per-microengine registers. - */ - ixp2000_uengine_csr_write(uengine, NN_PUT, 0x00); - ixp2000_uengine_csr_write(uengine, NN_GET, 0x00); - ixp2000_uengine_csr_write(uengine, T_INDEX_BYTE_INDEX, 0); -} -EXPORT_SYMBOL(ixp2000_uengine_set_mode); - -static int make_even_parity(u32 x) -{ - return hweight32(x) & 1; -} - -static void ustore_write(int uengine, u64 insn) -{ - /* - * Generate even parity for top and bottom 20 bits. - */ - insn |= (u64)make_even_parity((insn >> 20) & 0x000fffff) << 41; - insn |= (u64)make_even_parity(insn & 0x000fffff) << 40; - - /* - * Write to microstore. The second write auto-increments - * the USTORE_ADDRESS index register. - */ - ixp2000_uengine_csr_write(uengine, USTORE_DATA_LOWER, (u32)insn); - ixp2000_uengine_csr_write(uengine, USTORE_DATA_UPPER, (u32)(insn >> 32)); -} - -void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns) -{ - int i; - - /* - * Start writing to microstore at address 0. - */ - ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x80000000); - for (i = 0; i < insns; i++) { - u64 insn; - - insn = (((u64)ucode[0]) << 32) | - (((u64)ucode[1]) << 24) | - (((u64)ucode[2]) << 16) | - (((u64)ucode[3]) << 8) | - ((u64)ucode[4]); - ucode += 5; - - ustore_write(uengine, insn); - } - - /* - * Pad with a few NOPs at the end (to avoid the microengine - * aborting as it prefetches beyond the last instruction), unless - * we run off the end of the instruction store first, at which - * point the address register will wrap back to zero. - */ - for (i = 0; i < 4; i++) { - u32 addr; - - addr = ixp2000_uengine_csr_read(uengine, USTORE_ADDRESS); - if (addr == 0x80000000) - break; - ustore_write(uengine, 0xf0000c0300ULL); - } - - /* - * End programming. - */ - ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x00000000); -} -EXPORT_SYMBOL(ixp2000_uengine_load_microcode); - -void ixp2000_uengine_init_context(int uengine, int context, int pc) -{ - /* - * Select the right context for indirect access. - */ - ixp2000_uengine_csr_write(uengine, CSR_CTX_POINTER, context); - - /* - * Initialise signal masks to immediately go to Ready state. - */ - ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_SIG_EVENTS, 1); - ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_WAKEUP_EVENTS, 1); - - /* - * Set program counter. - */ - ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_STS, pc); -} -EXPORT_SYMBOL(ixp2000_uengine_init_context); - -void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask) -{ - u32 mask; - - /* - * Enable the specified context to go to Executing state. - */ - mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); - mask |= ctx_mask << 8; - ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); -} -EXPORT_SYMBOL(ixp2000_uengine_start_contexts); - -void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask) -{ - u32 mask; - - /* - * Disable the Ready->Executing transition. Note that this - * does not stop the context until it voluntarily yields. - */ - mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); - mask &= ~(ctx_mask << 8); - ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); -} -EXPORT_SYMBOL(ixp2000_uengine_stop_contexts); - -static int check_ixp_type(struct ixp2000_uengine_code *c) -{ - u32 product_id; - u32 rev; - - product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID); - if (((product_id >> 16) & 0x1f) != 0) - return 0; - - switch ((product_id >> 8) & 0xff) { - case 0: /* IXP2800 */ - if (!(c->cpu_model_bitmask & 4)) - return 0; - break; - - case 1: /* IXP2850 */ - if (!(c->cpu_model_bitmask & 8)) - return 0; - break; - - case 2: /* IXP2400 */ - if (!(c->cpu_model_bitmask & 2)) - return 0; - break; - - default: - return 0; - } - - rev = product_id & 0xff; - if (rev < c->cpu_min_revision || rev > c->cpu_max_revision) - return 0; - - return 1; -} - -static void generate_ucode(u8 *ucode, u32 *gpr_a, u32 *gpr_b) -{ - int offset; - int i; - - offset = 0; - - for (i = 0; i < 128; i++) { - u8 b3; - u8 b2; - u8 b1; - u8 b0; - - b3 = (gpr_a[i] >> 24) & 0xff; - b2 = (gpr_a[i] >> 16) & 0xff; - b1 = (gpr_a[i] >> 8) & 0xff; - b0 = gpr_a[i] & 0xff; - - // immed[@ai, (b1 << 8) | b0] - // 11110000 0000VVVV VVVV11VV VVVVVV00 1IIIIIII - ucode[offset++] = 0xf0; - ucode[offset++] = (b1 >> 4); - ucode[offset++] = (b1 << 4) | 0x0c | (b0 >> 6); - ucode[offset++] = (b0 << 2); - ucode[offset++] = 0x80 | i; - - // immed_w1[@ai, (b3 << 8) | b2] - // 11110100 0100VVVV VVVV11VV VVVVVV00 1IIIIIII - ucode[offset++] = 0xf4; - ucode[offset++] = 0x40 | (b3 >> 4); - ucode[offset++] = (b3 << 4) | 0x0c | (b2 >> 6); - ucode[offset++] = (b2 << 2); - ucode[offset++] = 0x80 | i; - } - - for (i = 0; i < 128; i++) { - u8 b3; - u8 b2; - u8 b1; - u8 b0; - - b3 = (gpr_b[i] >> 24) & 0xff; - b2 = (gpr_b[i] >> 16) & 0xff; - b1 = (gpr_b[i] >> 8) & 0xff; - b0 = gpr_b[i] & 0xff; - - // immed[@bi, (b1 << 8) | b0] - // 11110000 0000VVVV VVVV001I IIIIII11 VVVVVVVV - ucode[offset++] = 0xf0; - ucode[offset++] = (b1 >> 4); - ucode[offset++] = (b1 << 4) | 0x02 | (i >> 6); - ucode[offset++] = (i << 2) | 0x03; - ucode[offset++] = b0; - - // immed_w1[@bi, (b3 << 8) | b2] - // 11110100 0100VVVV VVVV001I IIIIII11 VVVVVVVV - ucode[offset++] = 0xf4; - ucode[offset++] = 0x40 | (b3 >> 4); - ucode[offset++] = (b3 << 4) | 0x02 | (i >> 6); - ucode[offset++] = (i << 2) | 0x03; - ucode[offset++] = b2; - } - - // ctx_arb[kill] - ucode[offset++] = 0xe0; - ucode[offset++] = 0x00; - ucode[offset++] = 0x01; - ucode[offset++] = 0x00; - ucode[offset++] = 0x00; -} - -static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c) -{ - int per_ctx_regs; - u32 *gpr_a; - u32 *gpr_b; - u8 *ucode; - int i; - - gpr_a = kmalloc(128 * sizeof(u32), GFP_KERNEL); - gpr_b = kmalloc(128 * sizeof(u32), GFP_KERNEL); - ucode = kmalloc(513 * 5, GFP_KERNEL); - if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) { - kfree(ucode); - kfree(gpr_b); - kfree(gpr_a); - return 1; - } - - per_ctx_regs = 16; - if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS) - per_ctx_regs = 32; - - memset(gpr_a, 0, sizeof(gpr_a)); - memset(gpr_b, 0, sizeof(gpr_b)); - for (i = 0; i < 256; i++) { - struct ixp2000_reg_value *r = c->initial_reg_values + i; - u32 *bank; - int inc; - int j; - - if (r->reg == -1) - break; - - bank = (r->reg & 0x400) ? gpr_b : gpr_a; - inc = (r->reg & 0x80) ? 128 : per_ctx_regs; - - j = r->reg & 0x7f; - while (j < 128) { - bank[j] = r->value; - j += inc; - } - } - - generate_ucode(ucode, gpr_a, gpr_b); - ixp2000_uengine_load_microcode(uengine, ucode, 513); - ixp2000_uengine_init_context(uengine, 0, 0); - ixp2000_uengine_start_contexts(uengine, 0x01); - for (i = 0; i < 100; i++) { - u32 status; - - status = ixp2000_uengine_csr_read(uengine, ACTIVE_CTX_STS); - if (!(status & 0x80000000)) - break; - } - ixp2000_uengine_stop_contexts(uengine, 0x01); - - kfree(ucode); - kfree(gpr_b); - kfree(gpr_a); - - return !!(i == 100); -} - -int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c) -{ - int ctx; - - if (!check_ixp_type(c)) - return 1; - - if (!(ixp2000_uengine_mask & (1 << uengine))) - return 1; - - ixp2000_uengine_reset(1 << uengine); - ixp2000_uengine_set_mode(uengine, c->uengine_parameters); - if (set_initial_registers(uengine, c)) - return 1; - ixp2000_uengine_load_microcode(uengine, c->insns, c->num_insns); - - for (ctx = 0; ctx < 8; ctx++) - ixp2000_uengine_init_context(uengine, ctx, 0); - - return 0; -} -EXPORT_SYMBOL(ixp2000_uengine_load); - - -static int __init ixp2000_uengine_init(void) -{ - int uengine; - u32 value; - - /* - * Determine number of microengines present. - */ - switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) { - case 0: /* IXP2800 */ - case 1: /* IXP2850 */ - ixp2000_uengine_mask = 0x00ff00ff; - break; - - case 2: /* IXP2400 */ - ixp2000_uengine_mask = 0x000f000f; - break; - - default: - printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n", - (unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID)); - ixp2000_uengine_mask = 0x00000000; - break; - } - - /* - * Reset microengines. - */ - ixp2000_uengine_reset(ixp2000_uengine_mask); - - /* - * Synchronise timestamp counters across all microengines. - */ - value = ixp2000_reg_read(IXP2000_MISC_CONTROL); - ixp2000_reg_wrb(IXP2000_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); - - return 0; -} - -subsys_initcall(ixp2000_uengine_init); diff --git a/drivers/net/ixp2000/enp2611.c b/drivers/net/ixp2000/enp2611.c index d82651a97bae..6f7dce8eba51 100644 --- a/drivers/net/ixp2000/enp2611.c +++ b/drivers/net/ixp2000/enp2611.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include "ixpdev.h" diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index 09f03f493bea..77f104a005f3 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include "ixp2400_rx.ucode" diff --git a/include/asm-arm/arch-ixp2000/uengine.h b/include/asm-arm/arch-ixp2000/uengine.h deleted file mode 100644 index b442d65c6593..000000000000 --- a/include/asm-arm/arch-ixp2000/uengine.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Generic library functions for the microengines found on the Intel - * IXP2000 series of network processors. - * - * Copyright (C) 2004, 2005 Lennert Buytenhek - * Dedicated to Marija Kulikova. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of the - * License, or (at your option) any later version. - */ - -#ifndef __IXP2000_UENGINE_H -#define __IXP2000_UENGINE_H - -extern u32 ixp2000_uengine_mask; - -struct ixp2000_uengine_code -{ - u32 cpu_model_bitmask; - u8 cpu_min_revision; - u8 cpu_max_revision; - - u32 uengine_parameters; - - struct ixp2000_reg_value { - int reg; - u32 value; - } *initial_reg_values; - - int num_insns; - u8 *insns; -}; - -u32 ixp2000_uengine_csr_read(int uengine, int offset); -void ixp2000_uengine_csr_write(int uengine, int offset, u32 value); -void ixp2000_uengine_reset(u32 uengine_mask); -void ixp2000_uengine_set_mode(int uengine, u32 mode); -void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns); -void ixp2000_uengine_init_context(int uengine, int context, int pc); -void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask); -void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask); -int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c); - -#define IXP2000_UENGINE_8_CONTEXTS 0x00000000 -#define IXP2000_UENGINE_4_CONTEXTS 0x80000000 -#define IXP2000_UENGINE_PRN_UPDATE_EVERY 0x40000000 -#define IXP2000_UENGINE_PRN_UPDATE_ON_ACCESS 0x00000000 -#define IXP2000_UENGINE_NN_FROM_SELF 0x00100000 -#define IXP2000_UENGINE_NN_FROM_PREVIOUS 0x00000000 -#define IXP2000_UENGINE_ASSERT_EMPTY_AT_3 0x000c0000 -#define IXP2000_UENGINE_ASSERT_EMPTY_AT_2 0x00080000 -#define IXP2000_UENGINE_ASSERT_EMPTY_AT_1 0x00040000 -#define IXP2000_UENGINE_ASSERT_EMPTY_AT_0 0x00000000 -#define IXP2000_UENGINE_LM_ADDR1_GLOBAL 0x00020000 -#define IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT 0x00000000 -#define IXP2000_UENGINE_LM_ADDR0_GLOBAL 0x00010000 -#define IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT 0x00000000 - - -#endif diff --git a/include/asm-arm/hardware/uengine.h b/include/asm-arm/hardware/uengine.h new file mode 100644 index 000000000000..b442d65c6593 --- /dev/null +++ b/include/asm-arm/hardware/uengine.h @@ -0,0 +1,62 @@ +/* + * Generic library functions for the microengines found on the Intel + * IXP2000 series of network processors. + * + * Copyright (C) 2004, 2005 Lennert Buytenhek + * Dedicated to Marija Kulikova. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + */ + +#ifndef __IXP2000_UENGINE_H +#define __IXP2000_UENGINE_H + +extern u32 ixp2000_uengine_mask; + +struct ixp2000_uengine_code +{ + u32 cpu_model_bitmask; + u8 cpu_min_revision; + u8 cpu_max_revision; + + u32 uengine_parameters; + + struct ixp2000_reg_value { + int reg; + u32 value; + } *initial_reg_values; + + int num_insns; + u8 *insns; +}; + +u32 ixp2000_uengine_csr_read(int uengine, int offset); +void ixp2000_uengine_csr_write(int uengine, int offset, u32 value); +void ixp2000_uengine_reset(u32 uengine_mask); +void ixp2000_uengine_set_mode(int uengine, u32 mode); +void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns); +void ixp2000_uengine_init_context(int uengine, int context, int pc); +void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask); +void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask); +int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c); + +#define IXP2000_UENGINE_8_CONTEXTS 0x00000000 +#define IXP2000_UENGINE_4_CONTEXTS 0x80000000 +#define IXP2000_UENGINE_PRN_UPDATE_EVERY 0x40000000 +#define IXP2000_UENGINE_PRN_UPDATE_ON_ACCESS 0x00000000 +#define IXP2000_UENGINE_NN_FROM_SELF 0x00100000 +#define IXP2000_UENGINE_NN_FROM_PREVIOUS 0x00000000 +#define IXP2000_UENGINE_ASSERT_EMPTY_AT_3 0x000c0000 +#define IXP2000_UENGINE_ASSERT_EMPTY_AT_2 0x00080000 +#define IXP2000_UENGINE_ASSERT_EMPTY_AT_1 0x00040000 +#define IXP2000_UENGINE_ASSERT_EMPTY_AT_0 0x00000000 +#define IXP2000_UENGINE_LM_ADDR1_GLOBAL 0x00020000 +#define IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT 0x00000000 +#define IXP2000_UENGINE_LM_ADDR0_GLOBAL 0x00010000 +#define IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT 0x00000000 + + +#endif -- cgit v1.2.3-59-g8ed1b From e0f4ab8a1741193891f096aa63df9ac8672af54c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 21 Mar 2006 14:51:37 -0800 Subject: Revert "V4L/DVB (3543): Fix Makefile to adapt to bt8xx/ conversion" This reverts commit 08f1d0b99f4e2203935d86640a7fec5c233b777c The "bt8xx/ conversion" for drivers/video/ hasn't actually percolated all the way to this tree, so the Makefile change escaped too soon. Build breakage noticed by Jeff Garzik Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile index 9d197efb481d..d188e4c670b5 100644 --- a/drivers/media/dvb/bt8xx/Makefile +++ b/drivers/media/dvb/bt8xx/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o -EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends -- cgit v1.2.3-59-g8ed1b From 80682fa9f70932950c913fd10411c004c4c2e8b0 Mon Sep 17 00:00:00 2001 From: Uwe Zeisberger Date: Wed, 22 Mar 2006 00:21:33 +0100 Subject: Fix "frist", "fisrt", typos Signed-off-by: Uwe Zeisberger Signed-off-by: Adrian Bunk --- drivers/base/platform.c | 2 +- drivers/block/cciss.c | 2 +- drivers/s390/net/claw.c | 2 +- drivers/scsi/megaraid/megaraid_sas.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 89b268321321..83f5c5984d1a 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -326,7 +326,7 @@ EXPORT_SYMBOL_GPL(platform_device_register); * platform_device_unregister - unregister a platform-level device * @pdev: platform device we're unregistering * - * Unregistration is done in 2 steps. Fisrt we release all resources + * Unregistration is done in 2 steps. First we release all resources * and remove it from the subsystem, then we drop reference count by * calling platform_device_put(). */ diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 0d65394707db..62b6f9da60b2 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2137,7 +2137,7 @@ static void start_io( ctlr_info_t *h) break; } - /* Get the frist entry from the Request Q */ + /* Get the first entry from the Request Q */ removeQ(&(h->reqQ), c); h->Qdepth--; diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index a86436a7a606..acd2a3f005f1 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -1404,7 +1404,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first, if ( privptr-> p_read_active_first ==NULL ) { #ifdef DEBUGMSG - printk(KERN_INFO "%s:%s p_read_active_frist == NULL \n", + printk(KERN_INFO "%s:%s p_read_active_first == NULL \n", dev->name,__FUNCTION__); printk(KERN_INFO "%s:%s Read active first/last changed \n", dev->name,__FUNCTION__); diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 4f39dd01936d..84c379ffa2a8 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -915,7 +915,7 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) int ret; /* - * Frist wait for all commands to complete + * First wait for all commands to complete */ ret = megasas_generic_reset(scmd); -- cgit v1.2.3-59-g8ed1b From 9e6b48732d53bd986178bca3bce18d2329e4b0ca Mon Sep 17 00:00:00 2001 From: James Ring Date: Wed, 22 Mar 2006 00:51:11 +0100 Subject: Fix spelling in E1000_DISABLE_PACKET_SPLIT Kconfig description Signed-off-by: Adrian Bunk --- drivers/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e0b11095b9da..00993e8ba589 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1914,7 +1914,7 @@ config E1000_DISABLE_PACKET_SPLIT depends on E1000 help Say Y here if you want to use the legacy receive path for PCI express - hadware. + hardware. If in doubt, say N. -- cgit v1.2.3-59-g8ed1b From b142eb6594003d3f82fd552a9b2ad73d774465d2 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 21 Mar 2006 20:37:47 -0500 Subject: [libata] SCSI VPD page 0x83 fixes Original patch (and description) by Douglas Gilbert, with minor fixes and API updates from me. Changelog: - make existing libata VPD device identification page (0x83) supply the ATA serial number in the libata "vendor specific" designator (from Chris Paulson-Ellis) - add a "t10 vendor id based" designator as defined in SAT rev 08 (section 10.3.4.2.3) that supplies ATA model and serial numbers - make the libata VPD page 0x83 more extensible (for adding more designators in the future). - rename EVPD to VPD in various places. Enable Vital Product Data (EVPD) is a bit in the INQUIRY cdb. Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 59 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index ccedb4536977..3aaa74cbef1d 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1542,7 +1542,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, * @buflen: Response buffer length. * * Returns standard device identification data associated - * with non-EVPD INQUIRY command output. + * with non-VPD INQUIRY command output. * * LOCKING: * spin_lock_irqsave(host_set lock) @@ -1593,12 +1593,12 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, } /** - * ata_scsiop_inq_00 - Simulate INQUIRY EVPD page 0, list of pages + * ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * - * Returns list of inquiry EVPD pages available. + * Returns list of inquiry VPD pages available. * * LOCKING: * spin_lock_irqsave(host_set lock) @@ -1612,7 +1612,7 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf, 0x80, /* page 0x80, unit serial no page */ 0x83 /* page 0x83, device ident page */ }; - rbuf[3] = sizeof(pages); /* number of supported EVPD pages */ + rbuf[3] = sizeof(pages); /* number of supported VPD pages */ if (buflen > 6) memcpy(rbuf + 4, pages, sizeof(pages)); @@ -1621,7 +1621,7 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf, } /** - * ata_scsiop_inq_80 - Simulate INQUIRY EVPD page 80, device serial number + * ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. @@ -1650,16 +1650,16 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf, return 0; } -static const char * const inq_83_str = "Linux ATA-SCSI simulator"; - /** - * ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity + * ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * - * Returns device identification. Currently hardcoded to - * return "Linux ATA-SCSI simulator". + * Yields two logical unit device identification designators: + * - vendor specific ASCII containing the ATA serial number + * - SAT defined "t10 vendor id based" containing ASCII vendor + * name ("ATA "), model and serial numbers. * * LOCKING: * spin_lock_irqsave(host_set lock) @@ -1668,16 +1668,39 @@ static const char * const inq_83_str = "Linux ATA-SCSI simulator"; unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen) { - rbuf[1] = 0x83; /* this page code */ - rbuf[3] = 4 + strlen(inq_83_str); /* page len */ + int num; + const int sat_model_serial_desc_len = 68; + const int ata_model_byte_len = 40; - /* our one and only identification descriptor (vendor-specific) */ - if (buflen > (strlen(inq_83_str) + 4 + 4 - 1)) { - rbuf[4 + 0] = 2; /* code set: ASCII */ - rbuf[4 + 3] = strlen(inq_83_str); - memcpy(rbuf + 4 + 4, inq_83_str, strlen(inq_83_str)); + rbuf[1] = 0x83; /* this page code */ + num = 4; + + if (buflen > (ATA_SERNO_LEN + num + 3)) { + /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */ + rbuf[num + 0] = 2; + rbuf[num + 3] = ATA_SERNO_LEN; + num += 4; + ata_id_string(args->id, (unsigned char *) rbuf + num, + ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + num += ATA_SERNO_LEN; } - + if (buflen > (sat_model_serial_desc_len + num + 3)) { + /* SAT defined lu model and serial numbers descriptor */ + /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */ + rbuf[num + 0] = 2; + rbuf[num + 1] = 1; + rbuf[num + 3] = sat_model_serial_desc_len; + num += 4; + memcpy(rbuf + num, "ATA ", 8); + num += 8; + ata_id_string(args->id, (unsigned char *) rbuf + num, + ATA_ID_PROD_OFS, ata_model_byte_len); + num += ata_model_byte_len; + ata_id_string(args->id, (unsigned char *) rbuf + num, + ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + num += ATA_SERNO_LEN; + } + rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */ return 0; } -- cgit v1.2.3-59-g8ed1b From 41ade50c4eff9477e6aef6b15e84673c6758ec0d Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Tue, 14 Mar 2006 11:19:04 +0800 Subject: [PATCH] libata-dev: add flush task to ata_exec_internal() Add ata_port_flush_task() to ata_exec_internal(). Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 714b42bad935..a28569d0081d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -962,6 +962,8 @@ ata_exec_internal(struct ata_port *ap, 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); + spin_lock_irqsave(&ap->host_set->lock, flags); /* We're racing with irq here. If we lose, the -- cgit v1.2.3-59-g8ed1b From f59b0cf8a3a39b75e580066c6a9aeabd97ec2743 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Thu, 16 Mar 2006 17:59:22 +0800 Subject: [PATCH] libata-dev: Remove ATA_PROT_PIO_MULT Remove the ATA_PROT_PIO_MULT protocol. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 1 - drivers/scsi/libata-scsi.c | 7 ++++--- include/linux/ata.h | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a28569d0081d..7a5392c8ec6f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3909,7 +3909,6 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc) case ATA_PROT_ATAPI: case ATA_PROT_PIO: - case ATA_PROT_PIO_MULT: if (ap->flags & ATA_FLAG_PIO_DMA) return 1; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 3aaa74cbef1d..cebf9b31b516 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2379,9 +2379,6 @@ ata_scsi_map_proto(u8 byte1) case 4: /* PIO Data-in */ case 5: /* PIO Data-out */ - if (byte1 & 0xe0) { - return ATA_PROT_PIO_MULT; - } return ATA_PROT_PIO; case 10: /* Device Reset */ @@ -2420,6 +2417,10 @@ 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; + if (scsicmd[1] & 0xe0) + /* PIO multi not supported yet */ + goto invalid_fld; + /* * 12 and 16 byte CDBs use different offsets to * provide the various register values. diff --git a/include/linux/ata.h b/include/linux/ata.h index b02a16c435e7..6b188b3b61dd 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -204,7 +204,6 @@ enum ata_tf_protocols { ATA_PROT_UNKNOWN, /* unknown/invalid */ ATA_PROT_NODATA, /* no data */ ATA_PROT_PIO, /* PIO single sector */ - ATA_PROT_PIO_MULT, /* PIO multiple sector */ ATA_PROT_DMA, /* DMA */ ATA_PROT_ATAPI, /* packet command, PIO data xfer*/ ATA_PROT_ATAPI_NODATA, /* packet command, no data */ -- cgit v1.2.3-59-g8ed1b From e46834cd2ddb1e2941806cb8fec60fb6bdd2ec29 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 17 Mar 2006 17:04:03 -0600 Subject: [PATCH] libata: Add some dummy noop functions Add some dummy noop functions for use by libata clients that do not need to do anything. Future SAS patches will utilize these functions. Signed-off-by: Brian King Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 3 +++ include/linux/libata.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 7a5392c8ec6f..8c86ae8d79b5 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2865,6 +2865,8 @@ void ata_qc_prep(struct ata_queued_cmd *qc) ata_fill_sg(qc); } +void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } + /** * ata_sg_init_one - Associate command with memory buffer * @qc: Command to be associated @@ -5063,6 +5065,7 @@ EXPORT_SYMBOL_GPL(ata_port_stop); EXPORT_SYMBOL_GPL(ata_host_stop); EXPORT_SYMBOL_GPL(ata_interrupt); EXPORT_SYMBOL_GPL(ata_qc_prep); +EXPORT_SYMBOL_GPL(ata_noop_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup); EXPORT_SYMBOL_GPL(ata_bmdma_start); EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); diff --git a/include/linux/libata.h b/include/linux/libata.h index 239408ecfddf..17e5a719c72b 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -543,6 +543,7 @@ 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_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); extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen); -- cgit v1.2.3-59-g8ed1b From a6cce2a79deefb33354561a064f0609a3b342829 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 17 Mar 2006 17:04:15 -0600 Subject: [PATCH] libata: ata_scsi_slave_config cleanup Encapsulate some of ata_scsi_slave_config so that parts can be reused in future SAS patches. Signed-off-by: Brian King Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 62 +++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index cebf9b31b516..fc547ca295fa 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -662,6 +662,41 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) } } +static void ata_scsi_sdev_config(struct scsi_device *sdev) +{ + sdev->use_10_for_rw = 1; + sdev->use_10_for_ms = 1; +} + +static void ata_scsi_dev_config(struct scsi_device *sdev, + struct ata_device *dev) +{ + unsigned int max_sectors; + + /* TODO: 2048 is an arbitrary number, not the + * hardware maximum. This should be increased to + * 65534 when Jens Axboe's patch for dynamically + * determining max_sectors is merged. + */ + max_sectors = ATA_MAX_SECTORS; + if (dev->flags & ATA_DFLAG_LBA48) + max_sectors = 2048; + if (dev->max_sectors) + max_sectors = dev->max_sectors; + + blk_queue_max_sectors(sdev->request_queue, max_sectors); + + /* + * SATA DMA transfers must be multiples of 4 byte, so + * we need to pad ATAPI transfers using an extra sg. + * Decrement max hw segments accordingly. + */ + if (dev->class == ATA_DEV_ATAPI) { + request_queue_t *q = sdev->request_queue; + blk_queue_max_hw_segments(q, q->max_hw_segments - 1); + } +} + /** * ata_scsi_slave_config - Set SCSI device attributes * @sdev: SCSI device to examine @@ -676,41 +711,18 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) int ata_scsi_slave_config(struct scsi_device *sdev) { - sdev->use_10_for_rw = 1; - sdev->use_10_for_ms = 1; + 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; - unsigned int max_sectors; ap = (struct ata_port *) &sdev->host->hostdata[0]; dev = &ap->device[sdev->id]; - /* TODO: 2048 is an arbitrary number, not the - * hardware maximum. This should be increased to - * 65534 when Jens Axboe's patch for dynamically - * determining max_sectors is merged. - */ - max_sectors = ATA_MAX_SECTORS; - if (dev->flags & ATA_DFLAG_LBA48) - max_sectors = 2048; - if (dev->max_sectors) - max_sectors = dev->max_sectors; - - blk_queue_max_sectors(sdev->request_queue, max_sectors); - - /* - * SATA DMA transfers must be multiples of 4 byte, so - * we need to pad ATAPI transfers using an extra sg. - * Decrement max hw segments accordingly. - */ - if (dev->class == ATA_DEV_ATAPI) { - request_queue_t *q = sdev->request_queue; - blk_queue_max_hw_segments(q, q->max_hw_segments - 1); - } + ata_scsi_dev_config(sdev, dev); } return 0; /* scsi layer doesn't check return value, sigh */ -- cgit v1.2.3-59-g8ed1b From 806a6e7a9904d4a1dfd3fd79d373bf31d71d34cb Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Tue, 21 Mar 2006 21:11:53 -0500 Subject: [libata] sata_mv: off-by-1 fix This patch addresses a number of weird behaviours observed for the sata_mv driver, by fixing an "off by one" bug in processing of the EDMA response queue. Basically, sata_mv was looking in the wrong place for command results, and this produced a lot of unpredictable behaviour. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/scsi/sata_mv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index e561281967dd..eed67ae2dc08 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1263,6 +1263,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap) void __iomem *port_mmio = mv_ap_base(ap); struct mv_port_priv *pp = ap->private_data; u32 out_ptr; + u8 ata_status; out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); @@ -1270,6 +1271,8 @@ static u8 mv_get_crpb_status(struct ata_port *ap) WARN_ON(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != pp->rsp_consumer); + ata_status = pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT; + /* increment our consumer index... */ pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer); @@ -1284,7 +1287,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap) writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); /* Return ATA status register for completed CRPB */ - return (pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT); + return ata_status; } /** -- cgit v1.2.3-59-g8ed1b From 2d2020242d14dc8caf83d7682d91368cff64290c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 21 Mar 2006 15:53:46 +0000 Subject: [PATCH] libata: pick a less confusion "um dunno" error Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index fc547ca295fa..dd954a23b357 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -511,13 +511,11 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", id, drv_stat); - /* For our last chance pick, use medium read error because - * it's much more common than an ATA drive telling you a write - * has failed. - */ - *sk = MEDIUM_ERROR; - *asc = 0x11; /* "unrecovered read error" */ - *ascq = 0x04; /* "auto-reallocation failed" */ + /* 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 */ + *sk = ABORTED_COMMAND; + *asc = 0x00; + *ascq = 0x00; translate_done: printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to " -- cgit v1.2.3-59-g8ed1b From db7f44d96e0b605906abc38aaf34841a93885884 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 21 Mar 2006 15:54:24 +0000 Subject: [PATCH] libata: make code actually compile with debugging on Signed-off-by: Jeff Garzik --- drivers/scsi/pdc_adma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 5f33cc932e70..b7b2300f6768 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -322,7 +322,7 @@ static int adma_fill_sg(struct ata_queued_cmd *qc) = (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4); i += 4; - VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", nelem, + VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", i/4, (unsigned long)addr, len); } return i; -- cgit v1.2.3-59-g8ed1b From 41bbc8bf1ab0e3e7cda1a0334176a9aa3986cd30 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 21 Mar 2006 15:57:00 +0000 Subject: [PATCH] libata: Note weakness in our PCI handling that one day wants fixing Signed-off-by: Jeff Garzik --- drivers/scsi/libata-bmdma.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index a93336adcd23..a89e44b21f4d 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -648,6 +648,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, goto err_out_regions; } + /* FIXME: If we get no DMA mask we should fall back to PIO */ rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) goto err_out_regions; -- cgit v1.2.3-59-g8ed1b From d33d44facc8673388979297c9836b4bf590f7388 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 21 Mar 2006 15:59:57 +0000 Subject: [PATCH] libata: two new PCI helpers The first performs the simplex clearing relevant to some chipsets that report simplex by default but can in fact do more if poked. The second is used to strip DMA modes from a PCI control with no BAR4 allocation. Signed-off-by: Jeff Garzik --- drivers/scsi/libata-bmdma.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index a89e44b21f4d..999725ca8d09 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -700,5 +700,41 @@ err_out: return rc; } +/** + * ata_pci_clear_simplex - attempt to kick device out of simplex + * @pdev: PCI device + * + * Some PCI ATA devices report simplex mode but in fact can be told to + * enter non simplex mode. This implements the neccessary logic to + * perform the task on such devices. Calling it on other devices will + * have -undefined- behaviour. + */ + +int ata_pci_clear_simplex(struct pci_dev *pdev) +{ + unsigned long bmdma = pci_resource_start(pdev, 4); + u8 simplex; + + if (bmdma == 0) + return -ENOENT; + + simplex = inb(bmdma + 0x02); + outb(simplex & 0x60, bmdma + 0x02); + simplex = inb(bmdma + 0x02); + if (simplex & 0x80) + return -EOPNOTSUPP; + return 0; +} + +unsigned long ata_pci_default_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long xfer_mask) +{ + /* Filter out DMA modes if the device has been configured by + the BIOS as PIO only */ + + if (ap->ioaddr.bmdma_addr == 0) + xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + return xfer_mask; +} + #endif /* CONFIG_PCI */ -- cgit v1.2.3-59-g8ed1b From 88f93a31dcd950fa6b27a5721428de7e01369c06 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 21 Mar 2006 16:04:12 +0000 Subject: [PATCH] libata: report which drive is causing mode problems Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 8c86ae8d79b5..d6b8d8e6364b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1739,7 +1739,7 @@ static int ata_host_set_pio(struct ata_port *ap) continue; if (!dev->pio_mode) { - printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); + printk(KERN_WARNING "ata%u: no PIO support for device %d.\n", ap->id, i); return -1; } -- cgit v1.2.3-59-g8ed1b From 23cfce8924f1e7ff1d14b8f1afd7550182026d16 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 21 Mar 2006 16:06:53 +0000 Subject: [PATCH] libata: make irqtrap mode compile Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d6b8d8e6364b..673ddf611d0e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4340,9 +4340,9 @@ idle_irq: #ifdef ATA_IRQ_TRAP if ((ap->stats.idle_irq % 1000) == 0) { - handled = 1; ata_irq_ack(ap, 0); /* debug trap */ printk(KERN_WARNING "ata%d: irq trap\n", ap->id); + return 1; } #endif return 0; /* irq not handled */ -- cgit v1.2.3-59-g8ed1b From 4d4681f6b994baf93dff0e4f59ab4fe38b49ef13 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 21 Mar 2006 21:31:22 -0500 Subject: [libata] fix oops on non-DMA bmdma hardware Alan noted: "bmdma may be zero but the bmdma_irq_clear function gets called even in this case during pure PIO operation. Check we have a bmdma before we use it." I fixed this by adding a check for zero. While was I there, I fixed the non-standard indentation of the small function's code. Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 673ddf611d0e..c8d2201b126f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4202,14 +4202,17 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc) void ata_bmdma_irq_clear(struct ata_port *ap) { - if (ap->flags & ATA_FLAG_MMIO) { - void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; - writeb(readb(mmio), mmio); - } else { - unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; - outb(inb(addr), addr); - } + if (!ap->ioaddr.bmdma_addr) + return; + if (ap->flags & ATA_FLAG_MMIO) { + void __iomem *mmio = + ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; + writeb(readb(mmio), mmio); + } else { + unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; + outb(inb(addr), addr); + } } -- cgit v1.2.3-59-g8ed1b From c962990a38167aacac91738501815deffa3afbd6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 21 Mar 2006 22:07:13 -0500 Subject: [libata] sata_vsc: fix inconsistent NULL checking Also, cleanup interrupt mask content and note in Kconfig that this driver supports the Intel 31244. Signed-off-by: Jeff Garzik --- drivers/scsi/Kconfig | 4 ++-- drivers/scsi/sata_vsc.c | 51 +++++++++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 5c94a5d4efc0..4035920ce3d8 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -595,10 +595,10 @@ config SCSI_SATA_VIA If unsure, say N. config SCSI_SATA_VITESSE - tristate "VITESSE VSC-7174 SATA support" + tristate "VITESSE VSC-7174 / INTEL 31244 SATA support" depends on SCSI_SATA && PCI help - This option enables support for Vitesse VSC7174 Serial ATA. + This option enables support for Vitesse VSC7174 and Intel 31244 Serial ATA. If unsure, say N. diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index b574379a7a82..b7b6c807346d 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -82,17 +82,20 @@ #define VSC_SATA_PORT_OFFSET 0x200 /* Error interrupt status bit offsets */ -#define VSC_SATA_INT_ERROR_E_OFFSET 2 -#define VSC_SATA_INT_ERROR_P_OFFSET 4 -#define VSC_SATA_INT_ERROR_T_OFFSET 5 -#define VSC_SATA_INT_ERROR_M_OFFSET 1 +#define VSC_SATA_INT_ERROR_CRC 0x40 +#define VSC_SATA_INT_ERROR_T 0x20 +#define VSC_SATA_INT_ERROR_P 0x10 +#define VSC_SATA_INT_ERROR_R 0x8 +#define VSC_SATA_INT_ERROR_E 0x4 +#define VSC_SATA_INT_ERROR_M 0x2 +#define VSC_SATA_INT_PHY_CHANGE 0x1 +#define VSC_SATA_INT_ERROR (VSC_SATA_INT_ERROR_CRC | VSC_SATA_INT_ERROR_T | \ + VSC_SATA_INT_ERROR_P | VSC_SATA_INT_ERROR_R | \ + VSC_SATA_INT_ERROR_E | VSC_SATA_INT_ERROR_M | \ + VSC_SATA_INT_PHY_CHANGE) + #define is_vsc_sata_int_err(port_idx, int_status) \ - (int_status & ((1 << (VSC_SATA_INT_ERROR_E_OFFSET + (8 * port_idx))) | \ - (1 << (VSC_SATA_INT_ERROR_P_OFFSET + (8 * port_idx))) | \ - (1 << (VSC_SATA_INT_ERROR_T_OFFSET + (8 * port_idx))) | \ - (1 << (VSC_SATA_INT_ERROR_M_OFFSET + (8 * port_idx))) \ - )\ - ) + (int_status & (VSC_SATA_INT_ERROR << (8 * port_idx))) static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) @@ -215,14 +218,6 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, ap = host_set->ports[i]; - if (is_vsc_sata_int_err(i, int_status)) { - u32 err_status; - printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__); - err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0; - vsc_sata_scr_write(ap, SCR_ERROR, err_status); - handled++; - } - if (ap && !(ap->flags & (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; @@ -230,12 +225,26 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.ctl & ATA_NIEN))) { handled += ata_host_intr(ap, qc); - } else { - printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__); + } 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 + * time (phy state changes). Clearing the SCR + * error register is not required, but it prevents + * the phy state change interrupts from recurring + * later. + */ + u32 err_status; + err_status = vsc_sata_scr_read(ap, SCR_ERROR); + printk(KERN_DEBUG "%s: clearing interrupt, " + "status %x; sata err status %x\n", + __FUNCTION__, + int_status, err_status); + vsc_sata_scr_write(ap, SCR_ERROR, err_status); + /* Clear interrupt status */ ata_chk_status(ap); handled++; } - } } } -- cgit v1.2.3-59-g8ed1b From 55cca65e1995ad604ee87e22c76c17d5cbceb9d0 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 21 Mar 2006 22:14:17 -0500 Subject: [libata sata_vsc, sata_svw] Convert #define'd constants to enums Also, bump sata_vsc version. --- drivers/scsi/sata_svw.c | 56 +++++++++++++++-------------- drivers/scsi/sata_vsc.c | 95 +++++++++++++++++++++++++------------------------ 2 files changed, 78 insertions(+), 73 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 4aaccd53e736..b023b6958487 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -56,33 +56,35 @@ #define DRV_NAME "sata_svw" #define DRV_VERSION "1.07" -/* Taskfile registers offsets */ -#define K2_SATA_TF_CMD_OFFSET 0x00 -#define K2_SATA_TF_DATA_OFFSET 0x00 -#define K2_SATA_TF_ERROR_OFFSET 0x04 -#define K2_SATA_TF_NSECT_OFFSET 0x08 -#define K2_SATA_TF_LBAL_OFFSET 0x0c -#define K2_SATA_TF_LBAM_OFFSET 0x10 -#define K2_SATA_TF_LBAH_OFFSET 0x14 -#define K2_SATA_TF_DEVICE_OFFSET 0x18 -#define K2_SATA_TF_CMDSTAT_OFFSET 0x1c -#define K2_SATA_TF_CTL_OFFSET 0x20 - -/* DMA base */ -#define K2_SATA_DMA_CMD_OFFSET 0x30 - -/* SCRs base */ -#define K2_SATA_SCR_STATUS_OFFSET 0x40 -#define K2_SATA_SCR_ERROR_OFFSET 0x44 -#define K2_SATA_SCR_CONTROL_OFFSET 0x48 - -/* Others */ -#define K2_SATA_SICR1_OFFSET 0x80 -#define K2_SATA_SICR2_OFFSET 0x84 -#define K2_SATA_SIM_OFFSET 0x88 - -/* Port stride */ -#define K2_SATA_PORT_OFFSET 0x100 +enum { + /* Taskfile registers offsets */ + K2_SATA_TF_CMD_OFFSET = 0x00, + K2_SATA_TF_DATA_OFFSET = 0x00, + K2_SATA_TF_ERROR_OFFSET = 0x04, + K2_SATA_TF_NSECT_OFFSET = 0x08, + K2_SATA_TF_LBAL_OFFSET = 0x0c, + K2_SATA_TF_LBAM_OFFSET = 0x10, + K2_SATA_TF_LBAH_OFFSET = 0x14, + K2_SATA_TF_DEVICE_OFFSET = 0x18, + K2_SATA_TF_CMDSTAT_OFFSET = 0x1c, + K2_SATA_TF_CTL_OFFSET = 0x20, + + /* DMA base */ + K2_SATA_DMA_CMD_OFFSET = 0x30, + + /* SCRs base */ + K2_SATA_SCR_STATUS_OFFSET = 0x40, + K2_SATA_SCR_ERROR_OFFSET = 0x44, + K2_SATA_SCR_CONTROL_OFFSET = 0x48, + + /* Others */ + K2_SATA_SICR1_OFFSET = 0x80, + K2_SATA_SICR2_OFFSET = 0x84, + K2_SATA_SIM_OFFSET = 0x88, + + /* Port stride */ + K2_SATA_PORT_OFFSET = 0x100, +}; static u8 k2_stat_check_status(struct ata_port *ap); diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index b7b6c807346d..fbf0713f9aba 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -47,52 +47,55 @@ #include #define DRV_NAME "sata_vsc" -#define DRV_VERSION "1.1" - -/* Interrupt register offsets (from chip base address) */ -#define VSC_SATA_INT_STAT_OFFSET 0x00 -#define VSC_SATA_INT_MASK_OFFSET 0x04 - -/* Taskfile registers offsets */ -#define VSC_SATA_TF_CMD_OFFSET 0x00 -#define VSC_SATA_TF_DATA_OFFSET 0x00 -#define VSC_SATA_TF_ERROR_OFFSET 0x04 -#define VSC_SATA_TF_FEATURE_OFFSET 0x06 -#define VSC_SATA_TF_NSECT_OFFSET 0x08 -#define VSC_SATA_TF_LBAL_OFFSET 0x0c -#define VSC_SATA_TF_LBAM_OFFSET 0x10 -#define VSC_SATA_TF_LBAH_OFFSET 0x14 -#define VSC_SATA_TF_DEVICE_OFFSET 0x18 -#define VSC_SATA_TF_STATUS_OFFSET 0x1c -#define VSC_SATA_TF_COMMAND_OFFSET 0x1d -#define VSC_SATA_TF_ALTSTATUS_OFFSET 0x28 -#define VSC_SATA_TF_CTL_OFFSET 0x29 - -/* DMA base */ -#define VSC_SATA_UP_DESCRIPTOR_OFFSET 0x64 -#define VSC_SATA_UP_DATA_BUFFER_OFFSET 0x6C -#define VSC_SATA_DMA_CMD_OFFSET 0x70 - -/* SCRs base */ -#define VSC_SATA_SCR_STATUS_OFFSET 0x100 -#define VSC_SATA_SCR_ERROR_OFFSET 0x104 -#define VSC_SATA_SCR_CONTROL_OFFSET 0x108 - -/* Port stride */ -#define VSC_SATA_PORT_OFFSET 0x200 - -/* Error interrupt status bit offsets */ -#define VSC_SATA_INT_ERROR_CRC 0x40 -#define VSC_SATA_INT_ERROR_T 0x20 -#define VSC_SATA_INT_ERROR_P 0x10 -#define VSC_SATA_INT_ERROR_R 0x8 -#define VSC_SATA_INT_ERROR_E 0x4 -#define VSC_SATA_INT_ERROR_M 0x2 -#define VSC_SATA_INT_PHY_CHANGE 0x1 -#define VSC_SATA_INT_ERROR (VSC_SATA_INT_ERROR_CRC | VSC_SATA_INT_ERROR_T | \ - VSC_SATA_INT_ERROR_P | VSC_SATA_INT_ERROR_R | \ - VSC_SATA_INT_ERROR_E | VSC_SATA_INT_ERROR_M | \ - VSC_SATA_INT_PHY_CHANGE) +#define DRV_VERSION "1.2" + +enum { + /* Interrupt register offsets (from chip base address) */ + VSC_SATA_INT_STAT_OFFSET = 0x00, + VSC_SATA_INT_MASK_OFFSET = 0x04, + + /* Taskfile registers offsets */ + VSC_SATA_TF_CMD_OFFSET = 0x00, + VSC_SATA_TF_DATA_OFFSET = 0x00, + VSC_SATA_TF_ERROR_OFFSET = 0x04, + VSC_SATA_TF_FEATURE_OFFSET = 0x06, + VSC_SATA_TF_NSECT_OFFSET = 0x08, + VSC_SATA_TF_LBAL_OFFSET = 0x0c, + VSC_SATA_TF_LBAM_OFFSET = 0x10, + VSC_SATA_TF_LBAH_OFFSET = 0x14, + VSC_SATA_TF_DEVICE_OFFSET = 0x18, + VSC_SATA_TF_STATUS_OFFSET = 0x1c, + VSC_SATA_TF_COMMAND_OFFSET = 0x1d, + VSC_SATA_TF_ALTSTATUS_OFFSET = 0x28, + VSC_SATA_TF_CTL_OFFSET = 0x29, + + /* DMA base */ + VSC_SATA_UP_DESCRIPTOR_OFFSET = 0x64, + VSC_SATA_UP_DATA_BUFFER_OFFSET = 0x6C, + VSC_SATA_DMA_CMD_OFFSET = 0x70, + + /* SCRs base */ + VSC_SATA_SCR_STATUS_OFFSET = 0x100, + VSC_SATA_SCR_ERROR_OFFSET = 0x104, + VSC_SATA_SCR_CONTROL_OFFSET = 0x108, + + /* Port stride */ + VSC_SATA_PORT_OFFSET = 0x200, + + /* Error interrupt status bit offsets */ + VSC_SATA_INT_ERROR_CRC = 0x40, + VSC_SATA_INT_ERROR_T = 0x20, + VSC_SATA_INT_ERROR_P = 0x10, + VSC_SATA_INT_ERROR_R = 0x8, + VSC_SATA_INT_ERROR_E = 0x4, + VSC_SATA_INT_ERROR_M = 0x2, + VSC_SATA_INT_PHY_CHANGE = 0x1, + VSC_SATA_INT_ERROR = (VSC_SATA_INT_ERROR_CRC | VSC_SATA_INT_ERROR_T | \ + VSC_SATA_INT_ERROR_P | VSC_SATA_INT_ERROR_R | \ + VSC_SATA_INT_ERROR_E | VSC_SATA_INT_ERROR_M | \ + VSC_SATA_INT_PHY_CHANGE), +}; + #define is_vsc_sata_int_err(port_idx, int_status) \ (int_status & (VSC_SATA_INT_ERROR << (8 * port_idx))) -- cgit v1.2.3-59-g8ed1b From caf636c760b33c72ebf018ff03c1b0d79ea6656a Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 22 Mar 2006 01:05:31 -0800 Subject: [TG3]: Fix SRAM access during tg3_init_one() 5700 and 5701 will not return correct SRAM data when the chip is in D3hot power state. tg3_get_eeprom_hw_cfg() must first put the device in D0 before reading SRAM. Thanks to Thomas Chenault at Dell for noticing this problem. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e03d1ae50c3e..cb687fcaae1f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9436,12 +9436,18 @@ static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp) return NULL; } -/* Since this function may be called in D3-hot power state during - * tg3_init_one(), only config cycles are allowed. - */ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) { u32 val; + u16 pmcsr; + + /* On some early chips the SRAM cannot be accessed in D3hot state, + * so need make sure we're in D0. + */ + pci_read_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, &pmcsr); + pmcsr &= ~PCI_PM_CTRL_STATE_MASK; + pci_write_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, pmcsr); + msleep(1); /* Make sure register accesses (indirect or otherwise) * will function correctly. -- cgit v1.2.3-59-g8ed1b From 15c3b696101992c4d69962325f0e91647164427f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 22 Mar 2006 01:06:52 -0800 Subject: [TG3]: Skip phy power down on some devices Some PHYs should not be powered down in tg3_set_power_state() because of bugs or other hardware limitations. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index cb687fcaae1f..f1d9a07bb888 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1148,6 +1148,19 @@ static int tg3_halt_cpu(struct tg3 *, u32); static int tg3_nvram_lock(struct tg3 *); static void tg3_nvram_unlock(struct tg3 *); +static void tg3_power_down_phy(struct tg3 *tp) +{ + /* The PHY should not be powered down on some chips because + * of bugs. + */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 && + (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) + return; + tg3_writephy(tp, MII_BMCR, BMCR_PDOWN); +} + static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) { u32 misc_host_ctrl; @@ -1327,8 +1340,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_FORCE_LED_OFF); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) - tg3_writephy(tp, MII_BMCR, BMCR_PDOWN); + tg3_power_down_phy(tp); } } -- cgit v1.2.3-59-g8ed1b From 056755f4d73d49b4adcbb8ecdaf75138cf166bd3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 22 Mar 2006 01:07:53 -0800 Subject: [TG3]: Bump driver version and reldate. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f1d9a07bb888..88829eb9568e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.52" -#define DRV_MODULE_RELDATE "Mar 06, 2006" +#define DRV_MODULE_VERSION "3.53" +#define DRV_MODULE_RELDATE "Mar 22, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3-59-g8ed1b From 14778d9072e53d2171f66ffd9657daff41acfaed Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 21 Mar 2006 02:29:39 -0800 Subject: [SPARC]: Respect vm_page_prot in io_remap_page_range(). Make sure the callers do a pgprot_noncached() on vma->vm_page_prot. Pointed out by Hugh Dickens. Signed-off-by: David S. Miller --- arch/sparc/mm/generic.c | 1 - arch/sparc/mm/loadmmu.c | 2 -- arch/sparc/mm/srmmu.c | 9 ++++++++- arch/sparc/mm/sun4c.c | 15 ++++++++++++--- arch/sparc64/kernel/pci.c | 2 +- arch/sparc64/mm/generic.c | 1 - drivers/char/drm/drm_vm.c | 1 + drivers/sbus/char/flash.c | 3 +-- drivers/video/fbmem.c | 8 +------- drivers/video/sbuslib.c | 2 ++ include/asm-sparc/pgtable.h | 6 +++--- 11 files changed, 29 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/arch/sparc/mm/generic.c b/arch/sparc/mm/generic.c index 2cb0728cee05..1ef7fa03fefe 100644 --- a/arch/sparc/mm/generic.c +++ b/arch/sparc/mm/generic.c @@ -76,7 +76,6 @@ int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, vma->vm_pgoff = (offset >> PAGE_SHIFT) | ((unsigned long)space << 28UL); - prot = __pgprot(pg_iobits); offset -= from; dir = pgd_offset(mm, from); flush_cache_range(vma, beg, end); diff --git a/arch/sparc/mm/loadmmu.c b/arch/sparc/mm/loadmmu.c index e9f9571601ba..36b4d24988f8 100644 --- a/arch/sparc/mm/loadmmu.c +++ b/arch/sparc/mm/loadmmu.c @@ -22,8 +22,6 @@ struct ctx_list *ctx_list_pool; struct ctx_list ctx_free; struct ctx_list ctx_used; -unsigned int pg_iobits; - extern void ld_mmu_sun4c(void); extern void ld_mmu_srmmu(void); diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index c664b962987c..27b0e0ba8581 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -2130,6 +2130,13 @@ static unsigned long srmmu_pte_to_pgoff(pte_t pte) return pte_val(pte) >> SRMMU_PTE_FILE_SHIFT; } +static pgprot_t srmmu_pgprot_noncached(pgprot_t prot) +{ + prot &= ~__pgprot(SRMMU_CACHE); + + return prot; +} + /* Load up routines and constants for sun4m and sun4d mmu */ void __init ld_mmu_srmmu(void) { @@ -2150,9 +2157,9 @@ void __init ld_mmu_srmmu(void) BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY)); BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL)); page_kernel = pgprot_val(SRMMU_PAGE_KERNEL); - pg_iobits = SRMMU_VALID | SRMMU_WRITE | SRMMU_REF; /* Functions */ + BTFIXUPSET_CALL(pgprot_noncached, srmmu_pgprot_noncached, BTFIXUPCALL_NORM); #ifndef CONFIG_SMP BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4md, BTFIXUPCALL_SWAPG1G2); #endif diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 731f19603cad..49f28c1bdc6d 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1589,7 +1589,10 @@ static void sun4c_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) static inline void sun4c_mapioaddr(unsigned long physaddr, unsigned long virt_addr) { - unsigned long page_entry; + unsigned long page_entry, pg_iobits; + + pg_iobits = _SUN4C_PAGE_PRESENT | _SUN4C_READABLE | _SUN4C_WRITEABLE | + _SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE; page_entry = ((physaddr >> PAGE_SHIFT) & SUN4C_PFN_MASK); page_entry |= ((pg_iobits | _SUN4C_PAGE_PRIV) & ~(_SUN4C_PAGE_PRESENT)); @@ -2134,6 +2137,13 @@ void __init sun4c_paging_init(void) printk("SUN4C: %d mmu entries for the kernel\n", cnt); } +static pgprot_t sun4c_pgprot_noncached(pgprot_t prot) +{ + prot |= __pgprot(_SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE); + + return prot; +} + /* Load up routines and constants for sun4c mmu */ void __init ld_mmu_sun4c(void) { @@ -2156,10 +2166,9 @@ void __init ld_mmu_sun4c(void) BTFIXUPSET_INT(page_readonly, pgprot_val(SUN4C_PAGE_READONLY)); BTFIXUPSET_INT(page_kernel, pgprot_val(SUN4C_PAGE_KERNEL)); page_kernel = pgprot_val(SUN4C_PAGE_KERNEL); - pg_iobits = _SUN4C_PAGE_PRESENT | _SUN4C_READABLE | _SUN4C_WRITEABLE | - _SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE; /* Functions */ + BTFIXUPSET_CALL(pgprot_noncached, sun4c_pgprot_noncached, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4c, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(do_check_pgt_cache, sun4c_check_pgt_cache, BTFIXUPCALL_NORM); diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 95ffa9418620..dfccff29e182 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -656,6 +656,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, __pci_mmap_set_flags(dev, vma, mmap_state); __pci_mmap_set_pgprot(dev, vma, mmap_state); + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, @@ -663,7 +664,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, if (ret) return ret; - vma->vm_flags |= VM_IO; return 0; } diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c index 5fc5c579e35e..8cb06205d265 100644 --- a/arch/sparc64/mm/generic.c +++ b/arch/sparc64/mm/generic.c @@ -140,7 +140,6 @@ int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; vma->vm_pgoff = phys_base >> PAGE_SHIFT; - prot = __pgprot(pg_iobits); offset -= from; dir = pgd_offset(mm, from); flush_cache_range(vma, beg, end); diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index 0291cd62c69f..ffd0800ed601 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c @@ -619,6 +619,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) #endif offset = dev->driver->get_reg_ofs(dev); #ifdef __sparc__ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, (map->offset + offset) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 6bdd768b731d..2beb3dded087 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -71,9 +71,8 @@ flash_mmap(struct file *file, struct vm_area_struct *vma) if (vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)) > size) size = vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)); - pgprot_val(vma->vm_page_prot) &= ~(_PAGE_CACHE); - pgprot_val(vma->vm_page_prot) |= _PAGE_E; vma->vm_flags |= (VM_SHM | VM_LOCKED); + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); if (io_remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot)) return -EAGAIN; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 996c7b58564e..07d882b14396 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1169,11 +1169,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) vma->vm_pgoff = off >> PAGE_SHIFT; /* This is an IO map - tell maydump to skip this VMA */ vma->vm_flags |= VM_IO | VM_RESERVED; -#if defined(__sparc_v9__) - if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) - return -EAGAIN; -#else #if defined(__mc68000__) #if defined(CONFIG_SUN3) pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE; @@ -1195,7 +1190,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) #elif defined(__i386__) || defined(__x86_64__) if (boot_cpu_data.x86 > 3) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; -#elif defined(__mips__) +#elif defined(__mips__) || defined(__sparc_v9__) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); #elif defined(__hppa__) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; @@ -1212,7 +1207,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; -#endif /* !__sparc_v9__ */ return 0; #endif /* !sparc32 */ } diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index a4d7cc51ce0b..34ef859ee414 100644 --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c @@ -58,6 +58,8 @@ int sbusfb_mmap_helper(struct sbus_mmap_map *map, /* To stop the swapper from even considering these pages */ vma->vm_flags |= (VM_IO | VM_RESERVED); + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + /* Each page, see which map applies */ for (page = 0; page < size; ){ map_size = 0; diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h index b33c35411e82..9eea8f4d41f0 100644 --- a/include/asm-sparc/pgtable.h +++ b/include/asm-sparc/pgtable.h @@ -269,11 +269,14 @@ BTFIXUPDEF_CALL_CONST(pte_t, mk_pte, struct page *, pgprot_t) BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_phys, unsigned long, pgprot_t) BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_io, unsigned long, pgprot_t, int) +BTFIXUPDEF_CALL_CONST(pgprot_t, pgprot_noncached, pgprot_t) #define mk_pte(page,pgprot) BTFIXUP_CALL(mk_pte)(page,pgprot) #define mk_pte_phys(page,pgprot) BTFIXUP_CALL(mk_pte_phys)(page,pgprot) #define mk_pte_io(page,pgprot,space) BTFIXUP_CALL(mk_pte_io)(page,pgprot,space) +#define pgprot_noncached(pgprot) BTFIXUP_CALL(pgprot_noncached)(pgprot) + BTFIXUPDEF_INT(pte_modify_mask) static pte_t pte_modify(pte_t pte, pgprot_t newprot) __attribute_const__; @@ -309,9 +312,6 @@ BTFIXUPDEF_CALL(pte_t *, pte_offset_kernel, pmd_t *, unsigned long) #define pte_unmap(pte) do{}while(0) #define pte_unmap_nested(pte) do{}while(0) -/* The permissions for pgprot_val to make a page mapped on the obio space */ -extern unsigned int pg_iobits; - /* Certain architectures need to do special things when pte's * within a page table are directly modified. Thus, the following * hook is made available. -- cgit v1.2.3-59-g8ed1b From f7cbb7fcd3bae5264a079e06411b35366da9bd4d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 13 Jan 2006 18:48:06 +0100 Subject: [ALSA] Fix snd_xxx_t typedefs Modules: PXA Mainstone driver,CX88 driver,SAA7134 driver Replace snd_xxx_t typedefs with explicit structs. Signed-off-by: Takashi Iwai --- arch/arm/mach-pxa/mainstone.c | 4 +- drivers/media/video/cx88/cx88-alsa.c | 54 +++++++++++++------------ drivers/media/video/saa7134/saa7134-alsa.c | 65 +++++++++++++++++------------- drivers/media/video/saa7134/saa7134.h | 2 +- include/asm-arm/arch-pxa/audio.h | 4 +- 5 files changed, 70 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index d5bda60209ec..98356f810007 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -157,14 +157,14 @@ static struct platform_device smc91x_device = { .resource = smc91x_resources, }; -static int mst_audio_startup(snd_pcm_substream_t *substream, void *priv) +static int mst_audio_startup(struct snd_pcm_substream *substream, void *priv) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) MST_MSCWR2 &= ~MST_MSCWR2_AC97_SPKROFF; return 0; } -static void mst_audio_shutdown(snd_pcm_substream_t *substream, void *priv) +static void mst_audio_shutdown(struct snd_pcm_substream *substream, void *priv) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF; diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 2acccd6d49bc..c841914c0244 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -63,7 +63,7 @@ struct cx88_audio_dev { /* audio controls */ int irq; - snd_card_t *card; + struct snd_card *card; spinlock_t reg_lock; @@ -82,7 +82,7 @@ struct cx88_audio_dev { struct cx88_buffer *buf; long opened; - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; }; typedef struct cx88_audio_dev snd_cx88_card_t; @@ -96,7 +96,7 @@ typedef struct cx88_audio_dev snd_cx88_card_t; 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)] = 1}; -static snd_card_t *snd_cx88_cards[SNDRV_CARDS]; +static struct snd_card *snd_cx88_cards[SNDRV_CARDS]; module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); @@ -320,7 +320,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) /* * Digital hardware definition */ -static snd_pcm_hardware_t snd_cx88_digital_hw = { +static struct snd_pcm_hardware snd_cx88_digital_hw = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -342,16 +342,16 @@ static snd_pcm_hardware_t snd_cx88_digital_hw = { /* * audio pcm capture runtime free */ -static void snd_card_cx88_runtime_free(snd_pcm_runtime_t *runtime) +static void snd_card_cx88_runtime_free(struct snd_pcm_runtime *runtime) { } /* * audio pcm capture open callback */ -static int snd_cx88_pcm_open(snd_pcm_substream_t *substream) +static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; int err; if (test_and_set_bit(0, &chip->opened)) @@ -380,7 +380,7 @@ _error: /* * audio close callback */ -static int snd_cx88_close(snd_pcm_substream_t *substream) +static int snd_cx88_close(struct snd_pcm_substream *substream) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); @@ -393,8 +393,8 @@ static int snd_cx88_close(snd_pcm_substream_t *substream) /* * hw_params callback */ -static int snd_cx88_hw_params(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * hw_params) +static int snd_cx88_hw_params(struct snd_pcm_substream * substream, + struct snd_pcm_hw_params * hw_params) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); struct cx88_buffer *buf; @@ -453,7 +453,7 @@ static int snd_cx88_hw_params(snd_pcm_substream_t * substream, /* * hw free callback */ -static int snd_cx88_hw_free(snd_pcm_substream_t * substream) +static int snd_cx88_hw_free(struct snd_pcm_substream * substream) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); @@ -469,7 +469,7 @@ static int snd_cx88_hw_free(snd_pcm_substream_t * substream) /* * prepare callback */ -static int snd_cx88_prepare(snd_pcm_substream_t *substream) +static int snd_cx88_prepare(struct snd_pcm_substream *substream) { return 0; } @@ -478,7 +478,7 @@ static int snd_cx88_prepare(snd_pcm_substream_t *substream) /* * trigger callback */ -static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd) +static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); int err; @@ -505,10 +505,10 @@ static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd) /* * pointer callback */ -static snd_pcm_uframes_t snd_cx88_pointer(snd_pcm_substream_t *substream) +static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; if (chip->read_count) { chip->read_count -= snd_pcm_lib_period_bytes(substream); @@ -525,7 +525,7 @@ static snd_pcm_uframes_t snd_cx88_pointer(snd_pcm_substream_t *substream) /* * operators */ -static snd_pcm_ops_t snd_cx88_pcm_ops = { +static struct snd_pcm_ops snd_cx88_pcm_ops = { .open = snd_cx88_pcm_open, .close = snd_cx88_close, .ioctl = snd_pcm_lib_ioctl, @@ -542,7 +542,7 @@ static snd_pcm_ops_t snd_cx88_pcm_ops = { static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name) { int err; - snd_pcm_t *pcm; + struct snd_pcm *pcm; err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); if (err < 0) @@ -557,7 +557,8 @@ static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name) /**************************************************************************** CONTROL INTERFACE ****************************************************************************/ -static int snd_cx88_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info) +static int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) { info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; info->count = 1; @@ -568,7 +569,8 @@ static int snd_cx88_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_i } /* OK - TODO: test it */ -static int snd_cx88_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) +static int snd_cx88_capture_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *value) { snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); struct cx88_core *core=chip->core; @@ -579,7 +581,8 @@ static int snd_cx88_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_va } /* OK - TODO: test it */ -static int snd_cx88_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) +static int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *value) { snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); struct cx88_core *core=chip->core; @@ -595,7 +598,7 @@ static int snd_cx88_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va return v != old_control; } -static snd_kcontrol_new_t snd_cx88_capture_volume = { +static struct snd_kcontrol_new snd_cx88_capture_volume = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Volume", .info = snd_cx88_capture_volume_info, @@ -641,7 +644,7 @@ static int snd_cx88_free(snd_cx88_card_t *chip) /* * Component Destructor */ -static void snd_cx88_dev_free(snd_card_t * card) +static void snd_cx88_dev_free(struct snd_card * card) { snd_cx88_card_t *chip = card->private_data; @@ -654,8 +657,9 @@ static void snd_cx88_dev_free(snd_card_t * card) */ static int devno; -static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, - snd_cx88_card_t **rchip) +static int __devinit snd_cx88_create(struct snd_card *card, + struct pci_dev *pci, + snd_cx88_card_t **rchip) { snd_cx88_card_t *chip; struct cx88_core *core; @@ -726,7 +730,7 @@ static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, static int __devinit cx88_audio_initdev(struct pci_dev *pci, const struct pci_device_id *pci_id) { - snd_card_t *card; + struct snd_card *card; snd_cx88_card_t *chip; int err; diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 7df5e0826e12..e02e6ee31b78 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -71,7 +71,7 @@ MODULE_PARM_DESC(enable, "Enable (or not) the SAA7134 capture interface(s)."); */ typedef struct snd_card_saa7134 { - snd_card_t *card; + struct snd_card *card; spinlock_t mixer_lock; int mixer_volume[MIXER_ADDR_LAST+1][2]; int capture_source[MIXER_ADDR_LAST+1][2]; @@ -95,10 +95,10 @@ typedef struct snd_card_saa7134_pcm { spinlock_t lock; - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; } snd_card_saa7134_pcm_t; -static snd_card_t *snd_saa7134_cards[SNDRV_CARDS]; +static struct snd_card *snd_saa7134_cards[SNDRV_CARDS]; /* @@ -251,10 +251,10 @@ out: * */ -static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, +static int snd_card_saa7134_capture_trigger(struct snd_pcm_substream * substream, int cmd) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; snd_card_saa7134_pcm_t *pcm = runtime->private_data; struct saa7134_dev *dev=pcm->dev; int err = 0; @@ -333,9 +333,9 @@ static int dsp_buffer_free(struct saa7134_dev *dev) * */ -static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) +static int snd_card_saa7134_capture_prepare(struct snd_pcm_substream * substream) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; int bswap, sign; u32 fmt, control; snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); @@ -422,9 +422,10 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) * */ -static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) +static snd_pcm_uframes_t +snd_card_saa7134_capture_pointer(struct snd_pcm_substream * substream) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; snd_card_saa7134_pcm_t *pcm = runtime->private_data; struct saa7134_dev *dev=pcm->dev; @@ -442,7 +443,7 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * * ALSA hardware capabilities definition */ -static snd_pcm_hardware_t snd_card_saa7134_capture = +static struct snd_pcm_hardware snd_card_saa7134_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -465,7 +466,7 @@ static snd_pcm_hardware_t snd_card_saa7134_capture = .periods_max = 1024, }; -static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) +static void snd_card_saa7134_runtime_free(struct snd_pcm_runtime *runtime) { snd_card_saa7134_pcm_t *pcm = runtime->private_data; @@ -482,8 +483,8 @@ static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) * */ -static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * hw_params) +static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, + struct snd_pcm_hw_params * hw_params) { snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); struct saa7134_dev *dev; @@ -562,7 +563,7 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, * */ -static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) +static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream) { snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); struct saa7134_dev *dev; @@ -588,7 +589,7 @@ static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) * */ -static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) +static int snd_card_saa7134_capture_close(struct snd_pcm_substream * substream) { return 0; } @@ -603,9 +604,9 @@ static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) * */ -static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) +static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; snd_card_saa7134_pcm_t *pcm; snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); struct saa7134_dev *dev = saa7134->dev; @@ -641,7 +642,7 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) * ALSA capture callbacks definition */ -static snd_pcm_ops_t snd_card_saa7134_capture_ops = { +static struct snd_pcm_ops snd_card_saa7134_capture_ops = { .open = snd_card_saa7134_capture_open, .close = snd_card_saa7134_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -662,7 +663,7 @@ static snd_pcm_ops_t snd_card_saa7134_capture_ops = { static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device) { - snd_pcm_t *pcm; + struct snd_pcm *pcm; int err; if ((err = snd_pcm_new(saa7134->card, "SAA7134 PCM", device, 0, 1, &pcm)) < 0) @@ -680,7 +681,8 @@ static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device) .get = snd_saa7134_volume_get, .put = snd_saa7134_volume_put, \ .private_value = addr } -static int snd_saa7134_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) +static int snd_saa7134_volume_info(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_info * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; @@ -689,7 +691,8 @@ static int snd_saa7134_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_ return 0; } -static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_saa7134_volume_get(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) { snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); int addr = kcontrol->private_value; @@ -699,7 +702,8 @@ static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ return 0; } -static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) { snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); int change, addr = kcontrol->private_value; @@ -730,7 +734,8 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ .get = snd_saa7134_capsrc_get, .put = snd_saa7134_capsrc_put, \ .private_value = addr } -static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) +static int snd_saa7134_capsrc_info(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_info * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 2; @@ -739,7 +744,8 @@ static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_ return 0; } -static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_saa7134_capsrc_get(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) { snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); int addr = kcontrol->private_value; @@ -752,7 +758,8 @@ static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ return 0; } -static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_saa7134_capsrc_put(struct snd_kcontrol * kcontrol, + struct snd_ctl_elem_value * ucontrol) { snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); int change, addr = kcontrol->private_value; @@ -829,7 +836,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ return change; } -static snd_kcontrol_new_t snd_saa7134_controls[] = { +static struct snd_kcontrol_new snd_saa7134_controls[] = { SAA713x_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER), SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER), SAA713x_VOLUME("Line Volume", 1, MIXER_ADDR_LINE1), @@ -848,7 +855,7 @@ SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2), static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) { - snd_card_t *card = chip->card; + struct snd_card *card = chip->card; unsigned int idx; int err; @@ -862,7 +869,7 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) return 0; } -static void snd_saa7134_free(snd_card_t * card) +static void snd_saa7134_free(struct snd_card * card) { snd_card_saa7134_t *chip = card->private_data; @@ -889,7 +896,7 @@ static void snd_saa7134_free(snd_card_t * card) static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) { - snd_card_t *card; + struct snd_card *card; snd_card_saa7134_t *chip; int err; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 3261d8bebdd1..6873d9a85ef1 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -386,7 +386,7 @@ struct saa7134_dmasound { unsigned int read_offset; unsigned int read_count; void * priv_data; - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; }; /* IR input */ diff --git a/include/asm-arm/arch-pxa/audio.h b/include/asm-arm/arch-pxa/audio.h index 60976f830e3f..17eccd720136 100644 --- a/include/asm-arm/arch-pxa/audio.h +++ b/include/asm-arm/arch-pxa/audio.h @@ -6,8 +6,8 @@ #include typedef struct { - int (*startup)(snd_pcm_substream_t *, void *); - void (*shutdown)(snd_pcm_substream_t *, void *); + int (*startup)(struct snd_pcm_substream *, void *); + void (*shutdown)(struct snd_pcm_substream *, void *); void (*suspend)(void *); void (*resume)(void *); void *priv; -- cgit v1.2.3-59-g8ed1b From 8a2cda007068e838ac6494cde74c37534f04f8dc Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Wed, 22 Mar 2006 00:07:36 -0800 Subject: [PATCH] i810fb_cursor(): use GFP_ATOMIC The console cursor can be called in atomic context. Change memory allocation to use the GFP_ATOMIC flag in i810fb_cursor(). Signed-off-by: Antonino Daplas Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/i810/i810_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index d8467c03b49f..788297e9d59e 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -1508,7 +1508,7 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor) int size = ((cursor->image.width + 7) >> 3) * cursor->image.height; int i; - u8 *data = kmalloc(64 * 8, GFP_KERNEL); + u8 *data = kmalloc(64 * 8, GFP_ATOMIC); if (data == NULL) return -ENOMEM; -- cgit v1.2.3-59-g8ed1b From d2044a94e80b61f68ee7456f82d9b443e9ff6ac7 Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Wed, 22 Mar 2006 00:07:42 -0800 Subject: [PATCH] dm: bio split bvec fix The code that handles bios that span table target boundaries by breaking them up into smaller bios will not split an individual struct bio_vec into more than two pieces. Sometimes more than that are required. This patch adds a loop to break the second piece up into as many pieces as are necessary. Cc: "Abhishek Gupta" Cc: Dan Smith Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 88d60202b9db..26b08ee425c7 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -533,30 +533,35 @@ static void __clone_and_map(struct clone_info *ci) } else { /* - * Create two copy bios to deal with io that has - * been split across a target. + * Handle a bvec that must be split between two or more targets. */ struct bio_vec *bv = bio->bi_io_vec + ci->idx; + sector_t remaining = to_sector(bv->bv_len); + unsigned int offset = 0; - clone = split_bvec(bio, ci->sector, ci->idx, - bv->bv_offset, max); - __map_bio(ti, clone, tio); + do { + if (offset) { + ti = dm_table_find_target(ci->map, ci->sector); + max = max_io_len(ci->md, ci->sector, ti); - ci->sector += max; - ci->sector_count -= max; - ti = dm_table_find_target(ci->map, ci->sector); - - len = to_sector(bv->bv_len) - max; - clone = split_bvec(bio, ci->sector, ci->idx, - bv->bv_offset + to_bytes(max), len); - tio = alloc_tio(ci->md); - tio->io = ci->io; - tio->ti = ti; - memset(&tio->info, 0, sizeof(tio->info)); - __map_bio(ti, clone, tio); + tio = alloc_tio(ci->md); + tio->io = ci->io; + tio->ti = ti; + memset(&tio->info, 0, sizeof(tio->info)); + } + + len = min(remaining, max); + + clone = split_bvec(bio, ci->sector, ci->idx, + bv->bv_offset + offset, len); + + __map_bio(ti, clone, tio); + + ci->sector += len; + ci->sector_count -= len; + offset += to_bytes(len); + } while (remaining -= len); - ci->sector += len; - ci->sector_count -= len; ci->idx++; } } -- cgit v1.2.3-59-g8ed1b From 83485f826bea154a0ab41e9b8689105531dd7cb2 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Wed, 22 Mar 2006 00:07:45 -0800 Subject: [PATCH] serial: serial_txx9 driver update Update the serial_txx9 driver. * More strict check in verify_port. Cleanup. * Do not insert a char caused previous overrun. * Fix some spin_locks. * Do not call uart_add_one_port for absent ports. Also, this patch removes a BROKEN tag from Kconfig. This driver has been marked as BROKEN by removal of uart_register_port, but it has been solved already on Sep 2005. Signed-off-by: Atsushi Nemoto Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/Kconfig | 2 +- drivers/serial/serial_txx9.c | 77 +++++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 89e5413cc2a3..c66ef96c71b4 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -866,7 +866,7 @@ config SERIAL_M32R_PLDSIO config SERIAL_TXX9 bool "TMPTX39XX/49XX SIO support" - depends HAS_TXX9_SERIAL && BROKEN + depends HAS_TXX9_SERIAL select SERIAL_CORE default y diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index ee98a867bc6d..141173efd463 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -33,6 +33,10 @@ * 1.02 Cleanup. (import 8250.c changes) * 1.03 Fix low-latency mode. (import 8250.c changes) * 1.04 Remove usage of deprecated functions, cleanup. + * 1.05 More strict check in verify_port. Cleanup. + * 1.06 Do not insert a char caused previous overrun. + * Fix some spin_locks. + * Do not call uart_add_one_port for absent ports. */ #include @@ -57,7 +61,7 @@ #include #include -static char *serial_version = "1.04"; +static char *serial_version = "1.06"; static char *serial_name = "TX39/49 Serial driver"; #define PASS_LIMIT 256 @@ -94,6 +98,8 @@ static char *serial_name = "TX39/49 Serial driver"; #define UART_NR 4 #endif +#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) + struct uart_txx9_port { struct uart_port port; @@ -210,7 +216,7 @@ static inline unsigned int sio_in(struct uart_txx9_port *up, int offset) { switch (up->port.iotype) { default: - return *(volatile u32 *)(up->port.membase + offset); + return __raw_readl(up->port.membase + offset); case UPIO_PORT: return inl(up->port.iobase + offset); } @@ -221,7 +227,7 @@ sio_out(struct uart_txx9_port *up, int offset, int value) { switch (up->port.iotype) { default: - *(volatile u32 *)(up->port.membase + offset) = value; + __raw_writel(value, up->port.membase + offset); break; case UPIO_PORT: outl(value, up->port.iobase + offset); @@ -259,34 +265,19 @@ sio_quot_set(struct uart_txx9_port *up, int quot) static void serial_txx9_stop_tx(struct uart_port *port) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; - unsigned long flags; - - spin_lock_irqsave(&up->port.lock, flags); sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_TIE); - spin_unlock_irqrestore(&up->port.lock, flags); } static void serial_txx9_start_tx(struct uart_port *port) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; - unsigned long flags; - - spin_lock_irqsave(&up->port.lock, flags); sio_set(up, TXX9_SIDICR, TXX9_SIDICR_TIE); - spin_unlock_irqrestore(&up->port.lock, flags); } static void serial_txx9_stop_rx(struct uart_port *port) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; - unsigned long flags; - - spin_lock_irqsave(&up->port.lock, flags); up->port.read_status_mask &= ~TXX9_SIDISR_RDIS; -#if 0 - sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_RIE); -#endif - spin_unlock_irqrestore(&up->port.lock, flags); } static void serial_txx9_enable_ms(struct uart_port *port) @@ -302,12 +293,16 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r unsigned int disr = *status; int max_count = 256; char flag; + unsigned int next_ignore_status_mask; do { ch = sio_in(up, TXX9_SIRFIFO); flag = TTY_NORMAL; up->port.icount.rx++; + /* mask out RFDN_MASK bit added by previous overrun */ + next_ignore_status_mask = + up->port.ignore_status_mask & ~TXX9_SIDISR_RFDN_MASK; if (unlikely(disr & (TXX9_SIDISR_UBRK | TXX9_SIDISR_UPER | TXX9_SIDISR_UFER | TXX9_SIDISR_UOER))) { /* @@ -328,8 +323,17 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r up->port.icount.parity++; else if (disr & TXX9_SIDISR_UFER) up->port.icount.frame++; - if (disr & TXX9_SIDISR_UOER) + if (disr & TXX9_SIDISR_UOER) { up->port.icount.overrun++; + /* + * The receiver read buffer still hold + * a char which caused overrun. + * Ignore next char by adding RFDN_MASK + * to ignore_status_mask temporarily. + */ + next_ignore_status_mask |= + TXX9_SIDISR_RFDN_MASK; + } /* * Mask off conditions which should be ingored. @@ -349,6 +353,7 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag); ignore_char: + up->port.ignore_status_mask = next_ignore_status_mask; disr = sio_in(up, TXX9_SIDISR); } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0)); spin_unlock(&up->port.lock); @@ -450,14 +455,11 @@ static unsigned int serial_txx9_get_mctrl(struct uart_port *port) static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; - unsigned long flags; - spin_lock_irqsave(&up->port.lock, flags); if (mctrl & TIOCM_RTS) sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC); else sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC); - spin_unlock_irqrestore(&up->port.lock, flags); } static void serial_txx9_break_ctl(struct uart_port *port, int break_state) @@ -784,8 +786,14 @@ static void serial_txx9_config_port(struct uart_port *port, int uflags) static int serial_txx9_verify_port(struct uart_port *port, struct serial_struct *ser) { - if (ser->irq < 0 || - ser->baud_base < 9600 || ser->type != PORT_TXX9) + unsigned long new_port = ser->port; + if (HIGH_BITS_OFFSET) + new_port += (unsigned long)ser->port_high << HIGH_BITS_OFFSET; + if (ser->type != port->type || + ser->irq != port->irq || + ser->io_type != port->iotype || + new_port != port->iobase || + (unsigned long)ser->iomem_base != port->mapbase) return -EINVAL; return 0; } @@ -827,7 +835,8 @@ static void __init serial_txx9_register_ports(struct uart_driver *drv) up->port.line = i; up->port.ops = &serial_txx9_pops; - uart_add_one_port(drv, &up->port); + if (up->port.iobase || up->port.mapbase) + uart_add_one_port(drv, &up->port); } } @@ -926,11 +935,6 @@ static int serial_txx9_console_setup(struct console *co, char *options) if (!port->ops) return -ENODEV; - /* - * Temporary fix. - */ - spin_lock_init(&port->lock); - /* * Disable UART interrupts, set DTR and RTS high * and set speed. @@ -1041,11 +1045,10 @@ static int __devinit serial_txx9_register_port(struct uart_port *port) mutex_lock(&serial_txx9_mutex); for (i = 0; i < UART_NR; i++) { uart = &serial_txx9_ports[i]; - if (uart->port.type == PORT_UNKNOWN) + if (!(uart->port.iobase || uart->port.mapbase)) break; } if (i < UART_NR) { - uart_remove_one_port(&serial_txx9_reg, &uart->port); uart->port.iobase = port->iobase; uart->port.membase = port->membase; uart->port.irq = port->irq; @@ -1080,9 +1083,8 @@ static void __devexit serial_txx9_unregister_port(int line) uart->port.type = PORT_UNKNOWN; uart->port.iobase = 0; uart->port.mapbase = 0; - uart->port.membase = 0; + uart->port.membase = NULL; uart->port.dev = NULL; - uart_add_one_port(&serial_txx9_reg, &uart->port); mutex_unlock(&serial_txx9_mutex); } @@ -1198,8 +1200,11 @@ static void __exit serial_txx9_exit(void) #ifdef ENABLE_SERIAL_TXX9_PCI pci_unregister_driver(&serial_txx9_pci_driver); #endif - for (i = 0; i < UART_NR; i++) - uart_remove_one_port(&serial_txx9_reg, &serial_txx9_ports[i].port); + for (i = 0; i < UART_NR; i++) { + struct uart_txx9_port *up = &serial_txx9_ports[i]; + if (up->port.iobase || up->port.mapbase) + uart_remove_one_port(&serial_txx9_reg, &up->port); + } uart_unregister_driver(&serial_txx9_reg); } -- cgit v1.2.3-59-g8ed1b From d39b6cfe664079ca79ae1cfebac4725a877fd61d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 22 Mar 2006 00:07:53 -0800 Subject: [PATCH] vr41xx: convert to the new platform device interface The patch does the following for v441xx seris drivers: - stop using platform_device_register_simple() as it is going away - mark ->probe() and ->remove() methods as __devinit and __devexit respectively - initialize "owner" field in driver structure so there is a link from /sys/modules to the driver - mark *_init() and *_exit() functions as __init and __exit Signed-off-by: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/vr41xx_giu.c | 19 +++++++++++++------ drivers/char/vr41xx_rtc.c | 30 ++++++++++++++++++++---------- drivers/serial/vr41xx_siu.c | 24 +++++++++++++++--------- 3 files changed, 48 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index 2267c7b81799..05e6e814d86f 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c @@ -613,7 +613,7 @@ static struct file_operations gpio_fops = { .release = gpio_release, }; -static int giu_probe(struct platform_device *dev) +static int __devinit giu_probe(struct platform_device *dev) { unsigned long start, size, flags = 0; unsigned int nr_pins = 0; @@ -697,7 +697,7 @@ static int giu_probe(struct platform_device *dev) return cascade_irq(GIUINT_IRQ, giu_get_irq); } -static int giu_remove(struct platform_device *dev) +static int __devexit giu_remove(struct platform_device *dev) { iounmap(giu_base); @@ -712,9 +712,10 @@ static struct platform_device *giu_platform_device; static struct platform_driver giu_device_driver = { .probe = giu_probe, - .remove = giu_remove, + .remove = __devexit_p(giu_remove), .driver = { .name = "GIU", + .owner = THIS_MODULE, }, }; @@ -722,9 +723,15 @@ static int __init vr41xx_giu_init(void) { int retval; - giu_platform_device = platform_device_register_simple("GIU", -1, NULL, 0); - if (IS_ERR(giu_platform_device)) - return PTR_ERR(giu_platform_device); + giu_platform_device = platform_device_alloc("GIU", -1); + if (!giu_platform_device) + return -ENOMEM; + + retval = platform_device_add(giu_platform_device); + if (retval < 0) { + platform_device_put(giu_platform_device); + return retval; + } retval = platform_driver_register(&giu_device_driver); if (retval < 0) diff --git a/drivers/char/vr41xx_rtc.c b/drivers/char/vr41xx_rtc.c index bc1b4a15212c..b109d9a502d6 100644 --- a/drivers/char/vr41xx_rtc.c +++ b/drivers/char/vr41xx_rtc.c @@ -558,7 +558,7 @@ static struct miscdevice rtc_miscdevice = { .fops = &rtc_fops, }; -static int rtc_probe(struct platform_device *pdev) +static int __devinit rtc_probe(struct platform_device *pdev) { unsigned int irq; int retval; @@ -631,7 +631,7 @@ static int rtc_probe(struct platform_device *pdev) return 0; } -static int rtc_remove(struct platform_device *dev) +static int __devexit rtc_remove(struct platform_device *dev) { int retval; @@ -653,13 +653,14 @@ static struct platform_device *rtc_platform_device; static struct platform_driver rtc_device_driver = { .probe = rtc_probe, - .remove = rtc_remove, + .remove = __devexit_p(rtc_remove), .driver = { .name = rtc_name, + .owner = THIS_MODULE, }, }; -static int __devinit vr41xx_rtc_init(void) +static int __init vr41xx_rtc_init(void) { int retval; @@ -684,10 +685,20 @@ static int __devinit vr41xx_rtc_init(void) break; } - rtc_platform_device = platform_device_register_simple("RTC", -1, - rtc_resource, ARRAY_SIZE(rtc_resource)); - if (IS_ERR(rtc_platform_device)) - return PTR_ERR(rtc_platform_device); + rtc_platform_device = platform_device_alloc("RTC", -1); + if (!rtc_platform_device) + return -ENOMEM; + + retval = platform_device_add_resources(rtc_platform_device, + rtc_resource, ARRAY_SIZE(rtc_resource)); + + if (retval == 0) + retval = platform_device_add(rtc_platform_device); + + if (retval < 0) { + platform_device_put(rtc_platform_device); + return retval; + } retval = platform_driver_register(&rtc_device_driver); if (retval < 0) @@ -696,10 +707,9 @@ static int __devinit vr41xx_rtc_init(void) return retval; } -static void __devexit vr41xx_rtc_exit(void) +static void __exit vr41xx_rtc_exit(void) { platform_driver_unregister(&rtc_device_driver); - platform_device_unregister(rtc_platform_device); } diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index d61494d185cd..bd6294132c18 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -919,7 +919,7 @@ static struct uart_driver siu_uart_driver = { .cons = SERIAL_VR41XX_CONSOLE, }; -static int siu_probe(struct platform_device *dev) +static int __devinit siu_probe(struct platform_device *dev) { struct uart_port *port; int num, i, retval; @@ -953,7 +953,7 @@ static int siu_probe(struct platform_device *dev) return 0; } -static int siu_remove(struct platform_device *dev) +static int __devexit siu_remove(struct platform_device *dev) { struct uart_port *port; int i; @@ -1006,21 +1006,28 @@ static struct platform_device *siu_platform_device; static struct platform_driver siu_device_driver = { .probe = siu_probe, - .remove = siu_remove, + .remove = __devexit_p(siu_remove), .suspend = siu_suspend, .resume = siu_resume, .driver = { .name = "SIU", + .owner = THIS_MODULE, }, }; -static int __devinit vr41xx_siu_init(void) +static int __init vr41xx_siu_init(void) { int retval; - siu_platform_device = platform_device_register_simple("SIU", -1, NULL, 0); - if (IS_ERR(siu_platform_device)) - return PTR_ERR(siu_platform_device); + siu_platform_device = platform_device_alloc("SIU", -1); + if (!siu_platform_device) + return -ENOMEM; + + retval = platform_device_add(siu_platform_device); + if (retval < 0) { + platform_device_put(siu_platform_device); + return retval; + } retval = platform_driver_register(&siu_device_driver); if (retval < 0) @@ -1029,10 +1036,9 @@ static int __devinit vr41xx_siu_init(void) return retval; } -static void __devexit vr41xx_siu_exit(void) +static void __exit vr41xx_siu_exit(void) { platform_driver_unregister(&siu_device_driver); - platform_device_unregister(siu_platform_device); } -- cgit v1.2.3-59-g8ed1b From eee8ab75c609fa0c452246f69237ff577b931243 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 22 Mar 2006 00:07:54 -0800 Subject: [PATCH] mv64x600_wdt: convert to the new platform device interface mv64x600_wdt: convert to the new platform device interface Do not use platform_device_register_simple() as it is going away. Signed-off-by: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/watchdog/mv64x60_wdt.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c index 00d9ef04a369..f1b9cf89f153 100644 --- a/drivers/char/watchdog/mv64x60_wdt.c +++ b/drivers/char/watchdog/mv64x60_wdt.c @@ -228,15 +228,25 @@ static int __init mv64x60_wdt_init(void) printk(KERN_INFO "MV64x60 watchdog driver\n"); - mv64x60_wdt_dev = platform_device_register_simple(MV64x60_WDT_NAME, - -1, NULL, 0); - if (IS_ERR(mv64x60_wdt_dev)) { - ret = PTR_ERR(mv64x60_wdt_dev); + mv64x60_wdt_dev = platform_device_alloc(MV64x60_WDT_NAME, -1); + if (!mv64x60_wdt_dev) { + ret = -ENOMEM; + goto out; + } + + ret = platform_device_add(mv64x60_wdt_dev); + if (ret) { + platform_device_put(mv64x60_wdt_dev); goto out; } ret = platform_driver_register(&mv64x60_wdt_driver); - out: + if (ret) { + platform_device_unregister(mv64x60_wdt_dev); + goto out; + } + + out: return ret; } -- cgit v1.2.3-59-g8ed1b From d0497614e0bd54f113041966532035edba463f8e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 22 Mar 2006 00:07:55 -0800 Subject: [PATCH] tb0219: convert to the new platform device interface Do not use platform_device_register_simple() as it is going away. Signed-off-by: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tb0219.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c index ac2a297ce37c..a80c83210872 100644 --- a/drivers/char/tb0219.c +++ b/drivers/char/tb0219.c @@ -283,7 +283,7 @@ static void tb0219_pci_irq_init(void) vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, IRQ_LEVEL_LOW); } -static int tb0219_probe(struct platform_device *dev) +static int __devinit tb0219_probe(struct platform_device *dev) { int retval; @@ -319,7 +319,7 @@ static int tb0219_probe(struct platform_device *dev) return 0; } -static int tb0219_remove(struct platform_device *dev) +static int __devexit tb0219_remove(struct platform_device *dev) { _machine_restart = old_machine_restart; @@ -335,19 +335,26 @@ static struct platform_device *tb0219_platform_device; static struct platform_driver tb0219_device_driver = { .probe = tb0219_probe, - .remove = tb0219_remove, + .remove = __devexit_p(tb0219_remove), .driver = { .name = "TB0219", + .owner = THIS_MODULE, }, }; -static int __devinit tanbac_tb0219_init(void) +static int __init tanbac_tb0219_init(void) { int retval; - tb0219_platform_device = platform_device_register_simple("TB0219", -1, NULL, 0); - if (IS_ERR(tb0219_platform_device)) - return PTR_ERR(tb0219_platform_device); + tb0219_platform_device = platform_device_alloc("TB0219", -1); + if (!tb0219_platform_device) + return -ENOMEM; + + retval = platform_device_add(tb0219_platform_device); + if (retval < 0) { + platform_device_put(tb0219_platform_device); + return retval; + } retval = platform_driver_register(&tb0219_device_driver); if (retval < 0) @@ -356,10 +363,9 @@ static int __devinit tanbac_tb0219_init(void) return retval; } -static void __devexit tanbac_tb0219_exit(void) +static void __exit tanbac_tb0219_exit(void) { platform_driver_unregister(&tb0219_device_driver); - platform_device_unregister(tb0219_platform_device); } -- cgit v1.2.3-59-g8ed1b From a7f3ea728b36aff520dff1611b3ce10cff46d8fe Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 22 Mar 2006 00:07:56 -0800 Subject: [PATCH] dcdbas: convert to the new platform device interface Do not use platform_device_register_simple() as it is going away, define dcdbas_driver and implement ->probe() and ->remove() functions so manual binding and unbinding will work with this driver. Also switch to using attribute_group when creating sysfs attributes and make sure to check and handle errors; explicitely remove attributes when detaching driver. Signed-off-by: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/firmware/dcdbas.c | 110 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 88 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 4652512f7d1a..3a4e5c5b4e1f 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -530,30 +530,27 @@ static DCDBAS_DEV_ATTR_RW(host_control_action); static DCDBAS_DEV_ATTR_RW(host_control_smi_type); static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown); -static struct device_attribute *dcdbas_dev_attrs[] = { - &dev_attr_smi_data_buf_size, - &dev_attr_smi_data_buf_phys_addr, - &dev_attr_smi_request, - &dev_attr_host_control_action, - &dev_attr_host_control_smi_type, - &dev_attr_host_control_on_shutdown, +static struct attribute *dcdbas_dev_attrs[] = { + &dev_attr_smi_data_buf_size.attr, + &dev_attr_smi_data_buf_phys_addr.attr, + &dev_attr_smi_request.attr, + &dev_attr_host_control_action.attr, + &dev_attr_host_control_smi_type.attr, + &dev_attr_host_control_on_shutdown.attr, NULL }; -/** - * dcdbas_init: initialize driver - */ -static int __init dcdbas_init(void) +static struct attribute_group dcdbas_attr_group = { + .attrs = dcdbas_dev_attrs, +}; + +static int __devinit dcdbas_probe(struct platform_device *dev) { - int i; + int i, error; host_control_action = HC_ACTION_NONE; host_control_smi_type = HC_SMITYPE_NONE; - dcdbas_pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); - if (IS_ERR(dcdbas_pdev)) - return PTR_ERR(dcdbas_pdev); - /* * BIOS SMI calls require buffer addresses be in 32-bit address space. * This is done by setting the DMA mask below. @@ -561,19 +558,79 @@ static int __init dcdbas_init(void) dcdbas_pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask; + error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group); + if (error) + return error; + + for (i = 0; dcdbas_bin_attrs[i]; i++) { + error = sysfs_create_bin_file(&dev->dev.kobj, + dcdbas_bin_attrs[i]); + if (error) { + while (--i >= 0) + sysfs_remove_bin_file(&dev->dev.kobj, + dcdbas_bin_attrs[i]); + sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group); + return error; + } + } + register_reboot_notifier(&dcdbas_reboot_nb); + dev_info(&dev->dev, "%s (version %s)\n", + DRIVER_DESCRIPTION, DRIVER_VERSION); + + return 0; +} + +static int __devexit dcdbas_remove(struct platform_device *dev) +{ + int i; + + unregister_reboot_notifier(&dcdbas_reboot_nb); for (i = 0; dcdbas_bin_attrs[i]; i++) - sysfs_create_bin_file(&dcdbas_pdev->dev.kobj, - dcdbas_bin_attrs[i]); + sysfs_remove_bin_file(&dev->dev.kobj, dcdbas_bin_attrs[i]); + sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group); - for (i = 0; dcdbas_dev_attrs[i]; i++) - device_create_file(&dcdbas_pdev->dev, dcdbas_dev_attrs[i]); + return 0; +} - dev_info(&dcdbas_pdev->dev, "%s (version %s)\n", - DRIVER_DESCRIPTION, DRIVER_VERSION); +static struct platform_driver dcdbas_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .probe = dcdbas_probe, + .remove = __devexit_p(dcdbas_remove), +}; + +/** + * dcdbas_init: initialize driver + */ +static int __init dcdbas_init(void) +{ + int error; + + error = platform_driver_register(&dcdbas_driver); + if (error) + return error; + + dcdbas_pdev = platform_device_alloc(DRIVER_NAME, -1); + if (!dcdbas_pdev) { + error = -ENOMEM; + goto err_unregister_driver; + } + + error = platform_device_add(dcdbas_pdev); + if (error) + goto err_free_device; return 0; + + err_free_device: + platform_device_put(dcdbas_pdev); + err_unregister_driver: + platform_driver_unregister(&dcdbas_driver); + return error; } /** @@ -588,6 +645,15 @@ static void __exit dcdbas_exit(void) unregister_reboot_notifier(&dcdbas_reboot_nb); smi_data_buf_free(); platform_device_unregister(dcdbas_pdev); + platform_driver_unregister(&dcdbas_driver); + + /* + * We have to free the buffer here instead of dcdbas_remove + * because only in module exit function we can be sure that + * all sysfs attributes belonging to this module have been + * released. + */ + smi_data_buf_free(); } module_init(dcdbas_init); -- cgit v1.2.3-59-g8ed1b From ac2b898ca6fb06196a26869c23b66afe7944e52e Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 22 Mar 2006 00:08:15 -0800 Subject: [PATCH] slab: Remove SLAB_NO_REAP option SLAB_NO_REAP is documented as an option that will cause this slab not to be reaped under memory pressure. However, that is not what happens. The only thing that SLAB_NO_REAP controls at the moment is the reclaim of the unused slab elements that were allocated in batch in cache_reap(). Cache_reap() is run every few seconds independently of memory pressure. Could we remove the whole thing? Its only used by three slabs anyways and I cannot find a reason for having this option. There is an additional problem with SLAB_NO_REAP. If set then the recovery of objects from alien caches is switched off. Objects not freed on the same node where they were initially allocated will only be reused if a certain amount of objects accumulates from one alien node (not very likely) or if the cache is explicitly shrunk. (Strangely __cache_shrink does not check for SLAB_NO_REAP) Getting rid of SLAB_NO_REAP fixes the problems with alien cache freeing. Signed-off-by: Christoph Lameter Cc: Pekka Enberg Cc: Manfred Spraul Cc: Mark Fasheh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/iscsi_tcp.c | 2 +- fs/ocfs2/super.c | 2 +- include/linux/slab.h | 1 - mm/slab.c | 13 ++----------- 4 files changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index ff79e68b347c..7b82ff090d42 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -3639,7 +3639,7 @@ iscsi_tcp_init(void) taskcache = kmem_cache_create("iscsi_taskcache", sizeof(struct iscsi_data_task), 0, - SLAB_HWCACHE_ALIGN | SLAB_NO_REAP, NULL, NULL); + SLAB_HWCACHE_ALIGN, NULL, NULL); if (!taskcache) return -ENOMEM; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 8dd3aafec499..09e1c57a86a0 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -959,7 +959,7 @@ static int ocfs2_initialize_mem_caches(void) ocfs2_lock_cache = kmem_cache_create("ocfs2_lock", sizeof(struct ocfs2_journal_lock), 0, - SLAB_NO_REAP|SLAB_HWCACHE_ALIGN, + SLAB_HWCACHE_ALIGN, NULL, NULL); if (!ocfs2_lock_cache) return -ENOMEM; diff --git a/include/linux/slab.h b/include/linux/slab.h index 38bed95dda7a..2b28c849d75a 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -38,7 +38,6 @@ typedef struct kmem_cache kmem_cache_t; #define SLAB_DEBUG_INITIAL 0x00000200UL /* Call constructor (as verifier) */ #define SLAB_RED_ZONE 0x00000400UL /* Red zone objs in a cache */ #define SLAB_POISON 0x00000800UL /* Poison objects */ -#define SLAB_NO_REAP 0x00001000UL /* never reap from the cache */ #define SLAB_HWCACHE_ALIGN 0x00002000UL /* align objs on a h/w cache lines */ #define SLAB_CACHE_DMA 0x00004000UL /* use GFP_DMA memory */ #define SLAB_MUST_HWCACHE_ALIGN 0x00008000UL /* force alignment */ diff --git a/mm/slab.c b/mm/slab.c index 5c2574989834..24235506b2a0 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -170,12 +170,12 @@ #if DEBUG # define CREATE_MASK (SLAB_DEBUG_INITIAL | SLAB_RED_ZONE | \ SLAB_POISON | SLAB_HWCACHE_ALIGN | \ - SLAB_NO_REAP | SLAB_CACHE_DMA | \ + SLAB_CACHE_DMA | \ SLAB_MUST_HWCACHE_ALIGN | SLAB_STORE_USER | \ SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ SLAB_DESTROY_BY_RCU) #else -# define CREATE_MASK (SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \ +# define CREATE_MASK (SLAB_HWCACHE_ALIGN | \ SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN | \ SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ SLAB_DESTROY_BY_RCU) @@ -662,7 +662,6 @@ static struct kmem_cache cache_cache = { .limit = BOOT_CPUCACHE_ENTRIES, .shared = 1, .buffer_size = sizeof(struct kmem_cache), - .flags = SLAB_NO_REAP, .name = "kmem_cache", #if DEBUG .obj_size = sizeof(struct kmem_cache), @@ -1848,9 +1847,6 @@ static void setup_cpu_cache(struct kmem_cache *cachep) * %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check * for buffer overruns. * - * %SLAB_NO_REAP - Don't automatically reap this cache when we're under - * memory pressure. - * * %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware * cacheline. This can be beneficial if you're counting cycles as closely * as davem. @@ -3584,10 +3580,6 @@ static void cache_reap(void *unused) struct slab *slabp; searchp = list_entry(walk, struct kmem_cache, next); - - if (searchp->flags & SLAB_NO_REAP) - goto next; - check_irq_on(); l3 = searchp->nodelists[numa_node_id()]; @@ -3635,7 +3627,6 @@ static void cache_reap(void *unused) } while (--tofree > 0); next_unlock: spin_unlock_irq(&l3->list_lock); -next: cond_resched(); } check_irq_on(); -- cgit v1.2.3-59-g8ed1b From f9aed0e2537174b95908f48b6052ae37196c9390 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:30 -0800 Subject: [PATCH] sg: use compound pages sg increments the refcount of constituent pages in its higher order memory allocations when they are about to be mapped by userspace. This is done so the subsequent get_page/put_page when doing the mapping and unmapping does not free the page. Move over to the preferred way, that is, using compound pages instead. This fixes a whole class of possible obscure bugs where a get_user_pages on a constituent page may outlast the user mappings or even the driver. Signed-off-by: Nick Piggin Cc: Hugh Dickins Cc: Douglas Gilbert Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/sg.c | 37 +++---------------------------------- 1 file changed, 3 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 5a0a19322d01..0e0ca8fc7318 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1140,32 +1140,6 @@ sg_fasync(int fd, struct file *filp, int mode) return (retval < 0) ? retval : 0; } -/* When startFinish==1 increments page counts for pages other than the - first of scatter gather elements obtained from alloc_pages(). - When startFinish==0 decrements ... */ -static void -sg_rb_correct4mmap(Sg_scatter_hold * rsv_schp, int startFinish) -{ - struct scatterlist *sg = rsv_schp->buffer; - struct page *page; - int k, m; - - SCSI_LOG_TIMEOUT(3, printk("sg_rb_correct4mmap: startFinish=%d, scatg=%d\n", - startFinish, rsv_schp->k_use_sg)); - /* N.B. correction _not_ applied to base page of each allocation */ - for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sg) { - for (m = PAGE_SIZE; m < sg->length; m += PAGE_SIZE) { - page = sg->page; - if (startFinish) - get_page(page); - else { - if (page_count(page) > 0) - __put_page(page); - } - } - } -} - static struct page * sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type) { @@ -1237,10 +1211,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) sa += len; } - if (0 == sfp->mmap_called) { - sg_rb_correct4mmap(rsv_schp, 1); /* do only once per fd lifetime */ - sfp->mmap_called = 1; - } + sfp->mmap_called = 1; vma->vm_flags |= VM_RESERVED; vma->vm_private_data = sfp; vma->vm_ops = &sg_mmap_vm_ops; @@ -2395,8 +2366,6 @@ __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) SCSI_LOG_TIMEOUT(6, printk("__sg_remove_sfp: bufflen=%d, k_use_sg=%d\n", (int) sfp->reserve.bufflen, (int) sfp->reserve.k_use_sg)); - if (sfp->mmap_called) - sg_rb_correct4mmap(&sfp->reserve, 0); /* undo correction */ sg_remove_scat(&sfp->reserve); } sfp->parentdp = NULL; @@ -2478,9 +2447,9 @@ sg_page_malloc(int rqSz, int lowDma, int *retSzp) return resp; if (lowDma) - page_mask = GFP_ATOMIC | GFP_DMA | __GFP_NOWARN; + page_mask = GFP_ATOMIC | GFP_DMA | __GFP_COMP | __GFP_NOWARN; else - page_mask = GFP_ATOMIC | __GFP_NOWARN; + page_mask = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN; for (order = 0, a_size = PAGE_SIZE; a_size < rqSz; order++, a_size <<= 1) ; -- cgit v1.2.3-59-g8ed1b From 7835e98b2e3c66dba79cb0ff8ebb90a2fe030c29 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:40 -0800 Subject: [PATCH] remove set_page_count() outside mm/ set_page_count usage outside mm/ is limited to setting the refcount to 1. Remove set_page_count from outside mm/, and replace those users with init_page_count() and set_page_refcounted(). This allows more debug checking, and tighter control on how code is allowed to play around with page->_count. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/mm/init.c | 2 +- arch/arm/mm/init.c | 2 +- arch/arm26/mm/init.c | 2 +- arch/cris/mm/init.c | 2 +- arch/frv/mm/init.c | 6 +++--- arch/h8300/mm/init.c | 4 ++-- arch/i386/mm/init.c | 6 +++--- arch/ia64/mm/init.c | 6 +++--- arch/m32r/mm/init.c | 4 ++-- arch/m68k/mm/init.c | 2 +- arch/m68k/mm/memory.c | 2 +- arch/m68k/mm/motorola.c | 2 +- arch/m68knommu/mm/init.c | 4 ++-- arch/mips/arc/memory.c | 2 +- arch/mips/dec/prom/memory.c | 2 +- arch/mips/mips-boards/generic/memory.c | 2 +- arch/mips/mips-boards/sim/sim_mem.c | 2 +- arch/mips/mm/init.c | 6 +++--- arch/mips/sgi-ip27/ip27-memory.c | 2 +- arch/parisc/mm/init.c | 4 ++-- arch/powerpc/mm/init_32.c | 4 ++-- arch/powerpc/mm/init_64.c | 4 ++-- arch/powerpc/mm/mem.c | 4 ++-- arch/powerpc/platforms/cell/setup.c | 2 +- arch/ppc/mm/init.c | 6 +++--- arch/s390/mm/init.c | 4 ++-- arch/sh/mm/init.c | 4 ++-- arch/sh64/mm/init.c | 4 ++-- arch/sparc/kernel/sun4d_smp.c | 6 +++--- arch/sparc/kernel/sun4m_smp.c | 6 +++--- arch/sparc/mm/init.c | 6 +++--- arch/sparc64/mm/init.c | 4 ++-- arch/um/kernel/mem.c | 4 ++-- arch/x86_64/mm/init.c | 6 +++--- arch/xtensa/mm/init.c | 2 +- drivers/video/acornfb.c | 2 +- include/linux/mm.h | 11 +++++++++-- mm/hugetlb.c | 5 +++-- mm/internal.h | 13 ++++++++++++- mm/page_alloc.c | 14 ++++++-------- 40 files changed, 96 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index 486d7945583d..544ac5dc09eb 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -357,7 +357,7 @@ free_reserved_mem(void *start, void *end) void *__start = start; for (; __start < end; __start += PAGE_SIZE) { ClearPageReserved(virt_to_page(__start)); - set_page_count(virt_to_page(__start), 1); + init_page_count(virt_to_page(__start)); free_page((long)__start); totalram_pages++; } diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 8b276ee38acf..b0321e943b76 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -531,7 +531,7 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s) for (; addr < end; addr += PAGE_SIZE) { struct page *page = virt_to_page(addr); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); free_page(addr); totalram_pages++; } diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c index 1f09a9d0fb83..e3ecaa453747 100644 --- a/arch/arm26/mm/init.c +++ b/arch/arm26/mm/init.c @@ -324,7 +324,7 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s) for (; addr < end; addr += PAGE_SIZE) { struct page *page = virt_to_page(addr); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); free_page(addr); totalram_pages++; } diff --git a/arch/cris/mm/init.c b/arch/cris/mm/init.c index 31a0018b525a..b7842ff213a6 100644 --- a/arch/cris/mm/init.c +++ b/arch/cris/mm/init.c @@ -216,7 +216,7 @@ free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c index 765088ea8a50..8899aa1a4f06 100644 --- a/arch/frv/mm/init.c +++ b/arch/frv/mm/init.c @@ -169,7 +169,7 @@ void __init mem_init(void) struct page *page = &mem_map[pfn]; ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalram_pages++; } @@ -210,7 +210,7 @@ void __init free_initmem(void) /* next to check that the page we free is not a partial page */ for (addr = start; addr < end; addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -230,7 +230,7 @@ void __init free_initrd_mem(unsigned long start, unsigned long end) int pages = 0; for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; pages++; diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c index 1e0929ddc8c4..09efc4b1f038 100644 --- a/arch/h8300/mm/init.c +++ b/arch/h8300/mm/init.c @@ -196,7 +196,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) int pages = 0; for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; pages++; @@ -219,7 +219,7 @@ free_initmem() /* next to check that the page we free is not a partial page */ for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 2700f01994ba..7ba55a6e2dbc 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -270,7 +270,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) static void __meminit free_new_highpage(struct page *page) { - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalhigh_pages++; } @@ -727,7 +727,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); memset((void *)addr, 0xcc, PAGE_SIZE); free_page(addr); totalram_pages++; @@ -766,7 +766,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index b38b6d213c15..08d94e6bfa18 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -197,7 +197,7 @@ free_initmem (void) eaddr = (unsigned long) ia64_imva(__init_end); while (addr < eaddr) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); ++totalram_pages; addr += PAGE_SIZE; @@ -252,7 +252,7 @@ free_initrd_mem (unsigned long start, unsigned long end) continue; page = virt_to_page(start); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); free_page(start); ++totalram_pages; } @@ -640,7 +640,7 @@ mem_init (void) void online_page(struct page *page) { ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalram_pages++; num_physpages++; diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c index 6facf15b04f3..c9e7dad860b7 100644 --- a/arch/m32r/mm/init.c +++ b/arch/m32r/mm/init.c @@ -226,7 +226,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -244,7 +244,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) unsigned long p; for (p = start; p < end; p += PAGE_SIZE) { ClearPageReserved(virt_to_page(p)); - set_page_count(virt_to_page(p), 1); + init_page_count(virt_to_page(p)); free_page(p); totalram_pages++; } diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c index c45beb955943..a190e39c907a 100644 --- a/arch/m68k/mm/init.c +++ b/arch/m68k/mm/init.c @@ -137,7 +137,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) int pages = 0; for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; pages++; diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c index 559942ce0e1e..d6d582a5abb0 100644 --- a/arch/m68k/mm/memory.c +++ b/arch/m68k/mm/memory.c @@ -54,7 +54,7 @@ void __init init_pointer_table(unsigned long ptable) /* unreserve the page so it's possible to free that page */ PD_PAGE(dp)->flags &= ~(1 << PG_reserved); - set_page_count(PD_PAGE(dp), 1); + init_page_count(PD_PAGE(dp)); return; } diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c index d855fec26317..afb57eeafdcb 100644 --- a/arch/m68k/mm/motorola.c +++ b/arch/m68k/mm/motorola.c @@ -276,7 +276,7 @@ void free_initmem(void) addr = (unsigned long)&__init_begin; for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) { virt_to_page(addr)->flags &= ~(1 << PG_reserved); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } diff --git a/arch/m68knommu/mm/init.c b/arch/m68knommu/mm/init.c index 89f0b554ffb7..d79503fe6e42 100644 --- a/arch/m68knommu/mm/init.c +++ b/arch/m68knommu/mm/init.c @@ -195,7 +195,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) int pages = 0; for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; pages++; @@ -218,7 +218,7 @@ free_initmem() /* next to check that the page we free is not a partial page */ for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } diff --git a/arch/mips/arc/memory.c b/arch/mips/arc/memory.c index 958d2eb78862..8a9ef58cc399 100644 --- a/arch/mips/arc/memory.c +++ b/arch/mips/arc/memory.c @@ -158,7 +158,7 @@ unsigned long __init prom_free_prom_memory(void) while (addr < boot_mem_map.map[i].addr + boot_mem_map.map[i].size) { ClearPageReserved(virt_to_page(__va(addr))); - set_page_count(virt_to_page(__va(addr)), 1); + init_page_count(virt_to_page(__va(addr))); free_page((unsigned long)__va(addr)); addr += PAGE_SIZE; freed += PAGE_SIZE; diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c index 81cb5a76cfb7..1edaf3074ee9 100644 --- a/arch/mips/dec/prom/memory.c +++ b/arch/mips/dec/prom/memory.c @@ -118,7 +118,7 @@ unsigned long __init prom_free_prom_memory(void) addr = PAGE_SIZE; while (addr < end) { ClearPageReserved(virt_to_page(__va(addr))); - set_page_count(virt_to_page(__va(addr)), 1); + init_page_count(virt_to_page(__va(addr))); free_page((unsigned long)__va(addr)); addr += PAGE_SIZE; } diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c index 2c8afd77a20b..ee5e70c95cf3 100644 --- a/arch/mips/mips-boards/generic/memory.c +++ b/arch/mips/mips-boards/generic/memory.c @@ -174,7 +174,7 @@ unsigned long __init prom_free_prom_memory(void) while (addr < boot_mem_map.map[i].addr + boot_mem_map.map[i].size) { ClearPageReserved(virt_to_page(__va(addr))); - set_page_count(virt_to_page(__va(addr)), 1); + init_page_count(virt_to_page(__va(addr))); free_page((unsigned long)__va(addr)); addr += PAGE_SIZE; freed += PAGE_SIZE; diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c index 0dbd7435bb2a..1ec4e75656bd 100644 --- a/arch/mips/mips-boards/sim/sim_mem.c +++ b/arch/mips/mips-boards/sim/sim_mem.c @@ -117,7 +117,7 @@ unsigned long __init prom_free_prom_memory(void) while (addr < boot_mem_map.map[i].addr + boot_mem_map.map[i].size) { ClearPageReserved(virt_to_page(__va(addr))); - set_page_count(virt_to_page(__va(addr)), 1); + init_page_count(virt_to_page(__va(addr))); free_page((unsigned long)__va(addr)); addr += PAGE_SIZE; freed += PAGE_SIZE; diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index a140da9732db..52f7d59fe612 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -245,7 +245,7 @@ void __init mem_init(void) #ifdef CONFIG_LIMITED_DMA set_page_address(page, lowmem_page_address(page)); #endif - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalhigh_pages++; } @@ -292,7 +292,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } @@ -315,7 +315,7 @@ void free_initmem(void) page = addr; #endif ClearPageReserved(virt_to_page(page)); - set_page_count(virt_to_page(page), 1); + init_page_count(virt_to_page(page)); free_page(page); totalram_pages++; freed += PAGE_SIZE; diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index ed93a9792959..e0d095daa5ed 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -559,7 +559,7 @@ void __init mem_init(void) /* if (!page_is_ram(pgnr)) continue; */ /* commented out until page_is_ram works */ ClearPageReserved(p); - set_page_count(p, 1); + init_page_count(p); __free_page(p); totalram_pages++; } diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 7847ca13d6c2..852eda3953dc 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -398,7 +398,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); num_physpages++; totalram_pages++; @@ -1018,7 +1018,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); num_physpages++; totalram_pages++; diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 7d0d75c11848..b57fb3a2b7bb 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c @@ -216,7 +216,7 @@ static void free_sec(unsigned long start, unsigned long end, const char *name) while (start < end) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); cnt++; start += PAGE_SIZE; @@ -248,7 +248,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 81cfb0c2ec58..bacb71c89811 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -140,7 +140,7 @@ void free_initmem(void) for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) { memset((void *)addr, 0xcc, PAGE_SIZE); ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -155,7 +155,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 6ae5c130d0db..454cac01d8cc 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -108,7 +108,7 @@ EXPORT_SYMBOL(phys_mem_access_prot); void online_page(struct page *page) { ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalram_pages++; num_physpages++; @@ -376,7 +376,7 @@ void __init mem_init(void) struct page *page = pfn_to_page(pfn); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalhigh_pages++; } diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index b33a4443f5a9..fec8e65b36ea 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -115,7 +115,7 @@ static void __init cell_spuprop_present(struct device_node *spe, for (pfn = start_pfn; pfn < end_pfn; pfn++) { struct page *page = pfn_to_page(pfn); set_page_links(page, ZONE_DMA, node_id, pfn); - set_page_count(page, 1); + init_page_count(page); reset_page_mapcount(page); SetPageReserved(page); INIT_LIST_HEAD(&page->lru); diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 134db5c04203..cb1c294fb932 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -140,7 +140,7 @@ static void free_sec(unsigned long start, unsigned long end, const char *name) while (start < end) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); cnt++; start += PAGE_SIZE; @@ -172,7 +172,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } @@ -441,7 +441,7 @@ void __init mem_init(void) struct page *page = mem_map + pfn; ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalhigh_pages++; } diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index df953383724d..a055894f3bd8 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -292,7 +292,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -307,7 +307,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index e342565f75fb..77b4a838fe10 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -273,7 +273,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -286,7 +286,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) unsigned long p; for (p = start; p < end; p += PAGE_SIZE) { ClearPageReserved(virt_to_page(p)); - set_page_count(virt_to_page(p), 1); + init_page_count(virt_to_page(p)); free_page(p); totalram_pages++; } diff --git a/arch/sh64/mm/init.c b/arch/sh64/mm/init.c index a65e8bb2c3cc..1169757fb38b 100644 --- a/arch/sh64/mm/init.c +++ b/arch/sh64/mm/init.c @@ -173,7 +173,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -186,7 +186,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) unsigned long p; for (p = start; p < end; p += PAGE_SIZE) { ClearPageReserved(virt_to_page(p)); - set_page_count(virt_to_page(p), 1); + init_page_count(virt_to_page(p)); free_page(p); totalram_pages++; } diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 40d426cce824..4219dd2ce3a2 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -266,19 +266,19 @@ void __init smp4d_boot_cpus(void) /* Free unneeded trap tables */ ClearPageReserved(virt_to_page(trapbase_cpu1)); - set_page_count(virt_to_page(trapbase_cpu1), 1); + init_page_count(virt_to_page(trapbase_cpu1)); free_page((unsigned long)trapbase_cpu1); totalram_pages++; num_physpages++; ClearPageReserved(virt_to_page(trapbase_cpu2)); - set_page_count(virt_to_page(trapbase_cpu2), 1); + init_page_count(virt_to_page(trapbase_cpu2)); free_page((unsigned long)trapbase_cpu2); totalram_pages++; num_physpages++; ClearPageReserved(virt_to_page(trapbase_cpu3)); - set_page_count(virt_to_page(trapbase_cpu3), 1); + init_page_count(virt_to_page(trapbase_cpu3)); free_page((unsigned long)trapbase_cpu3); totalram_pages++; num_physpages++; diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index a21f27d10e55..fbbd8a474c4c 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -233,21 +233,21 @@ void __init smp4m_boot_cpus(void) /* Free unneeded trap tables */ if (!cpu_isset(i, cpu_present_map)) { ClearPageReserved(virt_to_page(trapbase_cpu1)); - set_page_count(virt_to_page(trapbase_cpu1), 1); + init_page_count(virt_to_page(trapbase_cpu1)); free_page((unsigned long)trapbase_cpu1); totalram_pages++; num_physpages++; } if (!cpu_isset(2, cpu_present_map)) { ClearPageReserved(virt_to_page(trapbase_cpu2)); - set_page_count(virt_to_page(trapbase_cpu2), 1); + init_page_count(virt_to_page(trapbase_cpu2)); free_page((unsigned long)trapbase_cpu2); totalram_pages++; num_physpages++; } if (!cpu_isset(3, cpu_present_map)) { ClearPageReserved(virt_to_page(trapbase_cpu3)); - set_page_count(virt_to_page(trapbase_cpu3), 1); + init_page_count(virt_to_page(trapbase_cpu3)); free_page((unsigned long)trapbase_cpu3); totalram_pages++; num_physpages++; diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c index c03babaa0498..898669732466 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init.c @@ -383,7 +383,7 @@ void map_high_region(unsigned long start_pfn, unsigned long end_pfn) struct page *page = pfn_to_page(tmp); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalhigh_pages++; } @@ -480,7 +480,7 @@ void free_initmem (void) p = virt_to_page(addr); ClearPageReserved(p); - set_page_count(p, 1); + init_page_count(p); __free_page(p); totalram_pages++; num_physpages++; @@ -497,7 +497,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) struct page *p = virt_to_page(start); ClearPageReserved(p); - set_page_count(p, 1); + init_page_count(p); __free_page(p); num_physpages++; } diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index c2b556106fc1..2ae143ba50d8 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1461,7 +1461,7 @@ void free_initmem(void) p = virt_to_page(page); ClearPageReserved(p); - set_page_count(p, 1); + init_page_count(p); __free_page(p); num_physpages++; totalram_pages++; @@ -1477,7 +1477,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) struct page *p = virt_to_page(start); ClearPageReserved(p); - set_page_count(p, 1); + init_page_count(p); __free_page(p); num_physpages++; totalram_pages++; diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index fa4f915be5c5..92cce96b5e24 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -57,7 +57,7 @@ static void setup_highmem(unsigned long highmem_start, for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){ page = &mem_map[highmem_pfn + i]; ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); } } @@ -296,7 +296,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index 7af1742aa958..40ed13d263cd 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -486,7 +486,7 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size) void online_page(struct page *page) { ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalram_pages++; num_physpages++; @@ -592,7 +592,7 @@ void free_initmem(void) addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE); free_page(addr); totalram_pages++; @@ -632,7 +632,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index 5a91d6c9e66d..e1be4235f367 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c @@ -272,7 +272,7 @@ free_reserved_mem(void *start, void *end) { for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page((unsigned long)start); totalram_pages++; } diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index b058273527bb..76448d6ae896 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -1269,7 +1269,7 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end) */ page = virt_to_page(virtual_start); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); free_page(virtual_start); virtual_start += PAGE_SIZE; diff --git a/include/linux/mm.h b/include/linux/mm.h index 3d84b7a35e0d..7d8c127daad7 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -307,8 +307,6 @@ static inline int get_page_unless_zero(struct page *page) return atomic_inc_not_zero(&page->_count); } -#define set_page_count(p,v) atomic_set(&(p)->_count, (v)) - extern void FASTCALL(__page_cache_release(struct page *)); static inline int page_count(struct page *page) @@ -325,6 +323,15 @@ static inline void get_page(struct page *page) atomic_inc(&page->_count); } +/* + * Setup the page count before being freed into the page allocator for + * the first time (boot or memory hotplug) + */ +static inline void init_page_count(struct page *page) +{ + atomic_set(&page->_count, 1); +} + void put_page(struct page *page); void split_page(struct page *page, unsigned int order); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 39d49ecea8e8..20117a4b8ab6 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -18,6 +18,7 @@ #include #include +#include "internal.h" const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL; static unsigned long nr_huge_pages, free_huge_pages; @@ -106,7 +107,7 @@ struct page *alloc_huge_page(struct vm_area_struct *vma, unsigned long addr) return NULL; } spin_unlock(&hugetlb_lock); - set_page_count(page, 1); + set_page_refcounted(page); for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); ++i) clear_user_highpage(&page[i], addr); return page; @@ -152,7 +153,7 @@ static void update_and_free_page(struct page *page) 1 << PG_private | 1<< PG_writeback); } page[1].lru.next = NULL; - set_page_count(page, 1); + set_page_refcounted(page); __free_pages(page, HUGETLB_PAGE_ORDER); } diff --git a/mm/internal.h b/mm/internal.h index 7bb339779818..d20e3cc4aef0 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -13,8 +13,19 @@ #include -static inline void set_page_refs(struct page *page, int order) +static inline void set_page_count(struct page *page, int v) { + atomic_set(&page->_count, v); +} + +/* + * Turn a non-refcounted page (->_count == 0) into refcounted with + * a count of one. + */ +static inline void set_page_refcounted(struct page *page) +{ + BUG_ON(PageCompound(page) && page_private(page) != (unsigned long)page); + BUG_ON(atomic_read(&page->_count)); set_page_count(page, 1); } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e197818a7cf6..7f65b5a63bb3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -442,7 +442,7 @@ void fastcall __init __free_pages_bootmem(struct page *page, unsigned int order) if (order == 0) { __ClearPageReserved(page); set_page_count(page, 0); - set_page_refs(page, 0); + set_page_refcounted(page); __free_page(page); } else { int loop; @@ -457,7 +457,7 @@ void fastcall __init __free_pages_bootmem(struct page *page, unsigned int order) set_page_count(p, 0); } - set_page_refs(page, order); + set_page_refcounted(page); __free_pages(page, order); } } @@ -525,7 +525,7 @@ static int prep_new_page(struct page *page, int order) 1 << PG_referenced | 1 << PG_arch_1 | 1 << PG_checked | 1 << PG_mappedtodisk); set_page_private(page, 0); - set_page_refs(page, order); + set_page_refcounted(page); kernel_map_pages(page, 1 << order, 1); return 0; } @@ -755,10 +755,8 @@ void split_page(struct page *page, unsigned int order) BUG_ON(PageCompound(page)); BUG_ON(!page_count(page)); - for (i = 1; i < (1 << order); i++) { - BUG_ON(page_count(page + i)); - set_page_count(page + i, 1); - } + for (i = 1; i < (1 << order); i++) + set_page_refcounted(page + i); } /* @@ -1771,7 +1769,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, continue; page = pfn_to_page(pfn); set_page_links(page, zone, nid, pfn); - set_page_count(page, 1); + init_page_count(page); reset_page_mapcount(page); SetPageReserved(page); INIT_LIST_HEAD(&page->lru); -- cgit v1.2.3-59-g8ed1b From 7c74ffd072fbe44b6039223982f2dc76840ac4f5 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 22 Mar 2006 15:47:34 +0000 Subject: [PATCH] libata: note missing posting in mmio cmd write Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-bmdma.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 999725ca8d09..96b4d2160df8 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -214,6 +214,8 @@ static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile * Issues MMIO write to ATA command register, with proper * synchronization with interrupt handler / other threads. * + * FIXME: missing write posting for 400nS delay enforcement + * * LOCKING: * spin_lock_irqsave(host_set lock) */ -- cgit v1.2.3-59-g8ed1b From 09c7ad79dc62c499bb03d1ee92f838db2fc776c5 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 22 Mar 2006 15:52:40 +0000 Subject: [PATCH] libata: Fix a drive detection problem The current code follows the spec but uses an overlong delay. This would be great if the hardware did. Several vendors however forget the D7 pulldown. Fortunately 0xFF isnt a sane reset state so we can use it to skip detection as is done in drivers/ide. (ie this is a tested solution over a long time) Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5d00bb721e23..477afb4a9255 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2001,9 +2001,19 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, * status is checked. Because waiting for "a while" before * checking status is fine, post SRST, we perform this magic * delay here as well. + * + * Old drivers/ide uses the 2mS rule and then waits for ready */ msleep(150); + + /* Before we perform post reset processing we want to see if + the bus shows 0xFF because the odd clown forgets the D7 pulldown + resistor */ + + if (ata_check_status(ap) == 0xFF) + return 1; /* Positive is failure for some reason */ + ata_bus_post_reset(ap, devmask); return 0; -- cgit v1.2.3-59-g8ed1b From f4b15fefb38fb4942d85247854660bc8e02641a7 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 22 Mar 2006 15:54:04 +0000 Subject: [PATCH] Update libata DMA blacklist to cover versions, and resync with IDE layer Not much to say here except that some drives have fixed and bad firmware Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 94 +++++++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 477afb4a9255..c6600ac965f0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2563,48 +2563,72 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, } static const char * const ata_dma_blacklist [] = { - "WDC AC11000H", - "WDC AC22100H", - "WDC AC32500H", - "WDC AC33100H", - "WDC AC31600H", - "WDC AC32100H", - "WDC AC23200L", - "Compaq CRD-8241B", - "CRD-8400B", - "CRD-8480B", - "CRD-8482B", - "CRD-84", - "SanDisk SDP3B", - "SanDisk SDP3B-64", - "SANYO CD-ROM CRD", - "HITACHI CDR-8", - "HITACHI CDR-8335", - "HITACHI CDR-8435", - "Toshiba CD-ROM XM-6202B", - "TOSHIBA CD-ROM XM-1702BC", - "CD-532E-A", - "E-IDE CD-ROM CR-840", - "CD-ROM Drive/F5A", - "WPI CDD-820", - "SAMSUNG CD-ROM SC-148C", - "SAMSUNG CD-ROM SC", - "SanDisk SDP3B-64", - "ATAPI CD-ROM DRIVE 40X MAXIMUM", - "_NEC DV5800A", + "WDC AC11000H", NULL, + "WDC AC22100H", NULL, + "WDC AC32500H", NULL, + "WDC AC33100H", NULL, + "WDC AC31600H", NULL, + "WDC AC32100H", "24.09P07", + "WDC AC23200L", "21.10N21", + "Compaq CRD-8241B", NULL, + "CRD-8400B", NULL, + "CRD-8480B", NULL, + "CRD-8482B", NULL, + "CRD-84", NULL, + "SanDisk SDP3B", NULL, + "SanDisk SDP3B-64", NULL, + "SANYO CD-ROM CRD", NULL, + "HITACHI CDR-8", NULL, + "HITACHI CDR-8335", NULL, + "HITACHI CDR-8435", NULL, + "Toshiba CD-ROM XM-6202B", NULL, + "TOSHIBA CD-ROM XM-1702BC", NULL, + "CD-532E-A", NULL, + "E-IDE CD-ROM CR-840", NULL, + "CD-ROM Drive/F5A", NULL, + "WPI CDD-820", NULL, + "SAMSUNG CD-ROM SC-148C", NULL, + "SAMSUNG CD-ROM SC", NULL, + "SanDisk SDP3B-64", NULL, + "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL, + "_NEC DV5800A", NULL, + "SAMSUNG CD-ROM SN-124", "N001" }; + +static int ata_strim(char *s, size_t len) +{ + len = strnlen(s, len); + + /* ATAPI specifies that empty space is blank-filled; remove blanks */ + while ((len > 0) && (s[len - 1] == ' ')) { + len--; + s[len] = 0; + } + return len; +} static int ata_dma_blacklisted(const struct ata_device *dev) { - unsigned char model_num[41]; + unsigned char model_num[40]; + unsigned char model_rev[16]; + unsigned int nlen, rlen; int i; - ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); - - for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++) - if (!strcmp(ata_dma_blacklist[i], model_num)) - 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, + sizeof(model_rev)); + nlen = ata_strim(model_num, sizeof(model_num)); + rlen = ata_strim(model_rev, sizeof(model_rev)); + for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) { + if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) { + if (ata_dma_blacklist[i+1] == NULL) + return 1; + if (!strncmp(ata_dma_blacklist[i], model_rev, rlen)) + return 1; + } + } return 0; } -- cgit v1.2.3-59-g8ed1b From 67951aded31a1a736c1f0f6e8317677ea6c21ee1 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 22 Mar 2006 15:55:54 +0000 Subject: [PATCH] libata: Symbol exports Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c6600ac965f0..f4e307104b7b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5150,6 +5150,8 @@ EXPORT_SYMBOL_GPL(ata_pci_init_one); EXPORT_SYMBOL_GPL(ata_pci_remove_one); EXPORT_SYMBOL_GPL(ata_pci_device_suspend); EXPORT_SYMBOL_GPL(ata_pci_device_resume); +EXPORT_SYMBOL_GPL(ata_pci_default_filter); +EXPORT_SYMBOL_GPL(ata_pci_clear_simplex); #endif /* CONFIG_PCI */ EXPORT_SYMBOL_GPL(ata_device_suspend); -- cgit v1.2.3-59-g8ed1b From f0c8bbfa154f4481623a4478b0ae94a6ceeaa026 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 22 Mar 2006 20:48:18 +0900 Subject: [PATCH] libata: do not ignore PIO-only devices As libata now can do PIO, don't ignore PIO-only devices. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f4e307104b7b..0314abd97f2d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1221,13 +1221,6 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, * common ATA, ATAPI feature tests */ - /* we require DMA support (bits 8 of word 49) */ - if (!ata_id_has_dma(id)) { - printk(KERN_DEBUG "ata%u: no dma\n", ap->id); - rc = -EINVAL; - goto err_out_nosup; - } - /* find max transfer mode; for printk only */ xfer_mask = ata_id_xfermask(id); -- cgit v1.2.3-59-g8ed1b From 4658f79bec0b51222e769e328c2923f39f3bda77 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 22 Mar 2006 21:07:03 +0900 Subject: [PATCH] ahci: add softreset Now that libata is smart enought to handle both soft and hard resets, add softreset method. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index a1ddbba2cbdf..ffba65656a83 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -513,6 +513,138 @@ 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, int verbose, unsigned int *class) +{ + struct ahci_host_priv *hpriv = ap->host_set->private_data; + 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); + const u32 cmd_fis_len = 5; /* five dwords */ + const char *reason = NULL; + struct ata_taskfile tf; + u8 *fis; + int rc; + + DPRINTK("ENTER\n"); + + /* prepare for SRST (AHCI-1.1 10.4.1) */ + rc = ahci_stop_engine(ap); + if (rc) { + reason = "failed to stop engine"; + goto fail_restart; + } + + /* 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"; + goto fail_restart; + } + + 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)) { + rc = -EIO; + reason = "CLO failed"; + goto fail_restart; + } + } + + /* restart engine */ + ahci_start_engine(ap); + + ata_tf_init(ap, &tf, 0); + 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); + + tf.ctl |= ATA_SRST; + ata_tf_to_fis(&tf, fis, 0); + 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)) { + rc = -EIO; + reason = "1st FIS failed"; + goto fail; + } + + /* spec says at least 5us, but be generous and sleep for 1ms */ + msleep(1); + + /* issue the second D2H Register FIS */ + ahci_fill_cmd_slot(pp, cmd_fis_len); + + tf.ctl &= ~ATA_SRST; + ata_tf_to_fis(&tf, fis, 0); + fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ + + writel(1, port_mmio + PORT_CMD_ISSUE); + readl(port_mmio + PORT_CMD_ISSUE); /* flush */ + + /* spec mandates ">= 2ms" before checking status. + * We wait 150ms, because that was the magic delay used for + * ATAPI devices in Hale Landis's ATADRVR, for the period of time + * between when the ATA command register is written, and then + * status is checked. Because waiting for "a while" before + * checking status is fine, post SRST, we perform this magic + * delay here as well. + */ + msleep(150); + + *class = ATA_DEV_NONE; + if (sata_dev_present(ap)) { + if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { + rc = -EIO; + reason = "device not ready"; + goto fail; + } + *class = ahci_dev_classify(ap); + } + + DPRINTK("EXIT, class=%u\n", *class); + return 0; + + 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); + return rc; +} + static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) { int rc; @@ -553,7 +685,8 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class) static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes) { - return ata_drive_probe_reset(ap, NULL, NULL, ahci_hardreset, + return ata_drive_probe_reset(ap, ata_std_probeinit, + ahci_softreset, ahci_hardreset, ahci_postreset, classes); } -- cgit v1.2.3-59-g8ed1b From d97381702d3a2f917cfe935fbca1e850a37b984b Mon Sep 17 00:00:00 2001 From: Jens Osterkamp Date: Tue, 21 Mar 2006 22:53:47 -0800 Subject: [PATCH] fix spidernet build issue Signed-off-by: Jens Osterkamp Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 00e72b12fb92..b90468aea077 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -58,8 +58,8 @@ obj-$(CONFIG_STNIC) += stnic.o 8390.o obj-$(CONFIG_FEALNX) += fealnx.o obj-$(CONFIG_TIGON3) += tg3.o obj-$(CONFIG_BNX2) += bnx2.o -spidernet-y += spider_net.o spider_net_ethtool.o sungem_phy.o -obj-$(CONFIG_SPIDER_NET) += spidernet.o +spidernet-y += spider_net.o spider_net_ethtool.o +obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o obj-$(CONFIG_TC35815) += tc35815.o obj-$(CONFIG_SKGE) += skge.o obj-$(CONFIG_SKY2) += sky2.o -- cgit v1.2.3-59-g8ed1b From c2d3d4b938d1a8df4fd4db73427009dfb9e8b225 Mon Sep 17 00:00:00 2001 From: Sergei Shtylylov Date: Tue, 21 Mar 2006 22:53:52 -0800 Subject: [PATCH] AMD Au1xx0: fix Ethernet TX stats With Au1xx0 Ethernet driver, TX bytes/packets always remain zero. The problem seems to be that when packet has been transmitted, the length word in DMA buffer is zero. The patch updates the TX stats when a buffer is fed to DMA. The initial 2.4 patch was posted to linux-mips@linux-mips.org by Thomas Lange 21 Jan 2005. Signed-off-by: Thomas Lange Signed-off-by: Sergei Shtylyov Cc: Jordan Crouse Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/au1000_eth.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index cd0b1dccfb61..1363083b4d83 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -90,8 +90,6 @@ static void au1000_tx_timeout(struct net_device *); static int au1000_set_config(struct net_device *dev, struct ifmap *map); static void set_rx_mode(struct net_device *); static struct net_device_stats *au1000_get_stats(struct net_device *); -static inline void update_tx_stats(struct net_device *, u32, u32); -static inline void update_rx_stats(struct net_device *, u32); static void au1000_timer(unsigned long); static int au1000_ioctl(struct net_device *, struct ifreq *, int); static int mdio_read(struct net_device *, int, int); @@ -1825,16 +1823,11 @@ static void __exit au1000_cleanup_module(void) } } - -static inline void -update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len) +static void update_tx_stats(struct net_device *dev, u32 status) { struct au1000_private *aup = (struct au1000_private *) dev->priv; struct net_device_stats *ps = &aup->stats; - ps->tx_packets++; - ps->tx_bytes += pkt_len; - if (status & TX_FRAME_ABORTED) { if (dev->if_port == IF_PORT_100BASEFX) { if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) { @@ -1867,7 +1860,7 @@ static void au1000_tx_ack(struct net_device *dev) ptxd = aup->tx_dma_ring[aup->tx_tail]; while (ptxd->buff_stat & TX_T_DONE) { - update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff); + update_tx_stats(dev, ptxd->status); ptxd->buff_stat &= ~TX_T_DONE; ptxd->len = 0; au_sync(); @@ -1889,6 +1882,7 @@ static void au1000_tx_ack(struct net_device *dev) static int au1000_tx(struct sk_buff *skb, struct net_device *dev) { struct au1000_private *aup = (struct au1000_private *) dev->priv; + struct net_device_stats *ps = &aup->stats; volatile tx_dma_t *ptxd; u32 buff_stat; db_dest_t *pDB; @@ -1908,7 +1902,7 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev) return 1; } else if (buff_stat & TX_T_DONE) { - update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff); + update_tx_stats(dev, ptxd->status); ptxd->len = 0; } @@ -1928,6 +1922,9 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev) else ptxd->len = skb->len; + ps->tx_packets++; + ps->tx_bytes += ptxd->len; + ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE; au_sync(); dev_kfree_skb(skb); @@ -1936,7 +1933,6 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev) return 0; } - static inline void update_rx_stats(struct net_device *dev, u32 status) { struct au1000_private *aup = (struct au1000_private *) dev->priv; -- cgit v1.2.3-59-g8ed1b From 95f6b5a1e38e26dc313e283e1e6058d3ffff517d Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Wed, 22 Mar 2006 16:03:39 +0100 Subject: [PATCH] s390: qeth driver statistics fixes [patch 2/6] s390: qeth driver statistics fixes From: Ursula Braun - display "unsigned int" values in /proc/qeth_perf with %u instead of %i - omit qdio header length when increasing card->stats.tx_bytes Signed-off-by: Frank Pavlic diffstat: qeth_main.c | 3 ++- qeth_proc.c | 38 +++++++++++++++++++------------------- 2 files changed, 21 insertions(+), 20 deletions(-) Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_main.c | 3 ++- drivers/s390/net/qeth_proc.c | 38 +++++++++++++++++++------------------- 2 files changed, 21 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index dba7f7f02e79..634c3958f426 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -4419,6 +4419,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) int elements_needed = 0; enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; struct qeth_eddp_context *ctx = NULL; + int tx_bytes = skb->len; int rc; QETH_DBF_TEXT(trace, 6, "sendpkt"); @@ -4499,7 +4500,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) elements_needed, ctx); if (!rc){ card->stats.tx_packets++; - card->stats.tx_bytes += skb->len; + card->stats.tx_bytes += tx_bytes; #ifdef CONFIG_QETH_PERF_STATS if (skb_shinfo(skb)->tso_size && !(large_send == QETH_LARGE_SEND_NO)) { diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index 3c6339df879d..1304641545df 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c @@ -192,27 +192,27 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) CARD_DDEV_ID(card), QETH_CARD_IFNAME(card) ); - seq_printf(s, " Skb's/buffers received : %li/%i\n" - " Skb's/buffers sent : %li/%i\n\n", + seq_printf(s, " Skb's/buffers received : %lu/%u\n" + " Skb's/buffers sent : %lu/%u\n\n", card->stats.rx_packets, card->perf_stats.bufs_rec, card->stats.tx_packets, card->perf_stats.bufs_sent ); - seq_printf(s, " Skb's/buffers sent without packing : %li/%i\n" - " Skb's/buffers sent with packing : %i/%i\n\n", + seq_printf(s, " Skb's/buffers sent without packing : %lu/%u\n" + " Skb's/buffers sent with packing : %u/%u\n\n", card->stats.tx_packets - card->perf_stats.skbs_sent_pack, card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack, card->perf_stats.skbs_sent_pack, card->perf_stats.bufs_sent_pack ); - seq_printf(s, " Skbs sent in SG mode : %i\n" - " Skb fragments sent in SG mode : %i\n\n", + seq_printf(s, " Skbs sent in SG mode : %u\n" + " Skb fragments sent in SG mode : %u\n\n", card->perf_stats.sg_skbs_sent, card->perf_stats.sg_frags_sent); - seq_printf(s, " large_send tx (in Kbytes) : %i\n" - " large_send count : %i\n\n", + seq_printf(s, " large_send tx (in Kbytes) : %u\n" + " large_send count : %u\n\n", card->perf_stats.large_send_bytes >> 10, card->perf_stats.large_send_cnt); - seq_printf(s, " Packing state changes no pkg.->packing : %i/%i\n" + seq_printf(s, " Packing state changes no pkg.->packing : %u/%u\n" " Watermarks L/H : %i/%i\n" " Current buffer usage (outbound q's) : " "%i/%i/%i/%i\n\n", @@ -229,16 +229,16 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0 ); - seq_printf(s, " Inbound handler time (in us) : %i\n" - " Inbound handler count : %i\n" - " Inbound do_QDIO time (in us) : %i\n" - " Inbound do_QDIO count : %i\n\n" - " Outbound handler time (in us) : %i\n" - " Outbound handler count : %i\n\n" - " Outbound time (in us, incl QDIO) : %i\n" - " Outbound count : %i\n" - " Outbound do_QDIO time (in us) : %i\n" - " Outbound do_QDIO count : %i\n\n", + seq_printf(s, " Inbound handler time (in us) : %u\n" + " Inbound handler count : %u\n" + " Inbound do_QDIO time (in us) : %u\n" + " Inbound do_QDIO count : %u\n\n" + " Outbound handler time (in us) : %u\n" + " Outbound handler count : %u\n\n" + " Outbound time (in us, incl QDIO) : %u\n" + " Outbound count : %u\n" + " Outbound do_QDIO time (in us) : %u\n" + " Outbound do_QDIO count : %u\n\n", card->perf_stats.inbound_time, card->perf_stats.inbound_cnt, card->perf_stats.inbound_do_qdio_time, -- cgit v1.2.3-59-g8ed1b From 1380fee2b553fbde1a094476685f43ec5625aec2 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Wed, 22 Mar 2006 16:03:41 +0100 Subject: [PATCH] s390: qeth driver cleanups [patch 3/6] s390: qeth driver cleanups From: Ursula Braun - code analyzing tool BEAM has found some unreachable and unnecessary statements and also conditions which are always true. - removed some useless MII code since OSA card will never allow to set such values. Signed-off-by: Frank Pavlic diffstat: qeth_main.c | 49 ++++--------------------------------------------- qeth_proc.c | 18 +++++++++--------- qeth_sys.c | 2 +- 3 files changed, 14 insertions(+), 55 deletions(-) Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_main.c | 49 ++++---------------------------------------- drivers/s390/net/qeth_proc.c | 18 ++++++++-------- drivers/s390/net/qeth_sys.c | 2 +- 3 files changed, 14 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 634c3958f426..69329ea61e2b 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1364,7 +1364,7 @@ qeth_wait_for_buffer(struct qeth_channel *channel) static void qeth_clear_cmd_buffers(struct qeth_channel *channel) { - int cnt = 0; + int cnt; for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++) qeth_release_buffer(channel,&channel->iob[cnt]); @@ -2814,11 +2814,11 @@ qeth_handle_send_error(struct qeth_card *card, QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card)); return QETH_SEND_ERROR_LINK_FAILURE; case 3: + default: QETH_DBF_TEXT(trace, 1, "SIGAcc3"); QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card)); return QETH_SEND_ERROR_KICK_IT; } - return QETH_SEND_ERROR_LINK_FAILURE; } void @@ -3865,6 +3865,7 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) if ((hdr_mac == QETH_TR_MAC_NC) || (hdr_mac == QETH_TR_MAC_C)) return RTN_MULTICAST; + break; /* eth or so multicast? */ default: if ((hdr_mac == QETH_ETH_MAC_V4) || @@ -4586,38 +4587,11 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum) case MII_NCONFIG: /* network interface config */ break; default: - rc = 0; break; } return rc; } -static void -qeth_mdio_write(struct net_device *dev, int phy_id, int regnum, int value) -{ - switch(regnum){ - case MII_BMCR: /* Basic mode control register */ - case MII_BMSR: /* Basic mode status register */ - case MII_PHYSID1: /* PHYS ID 1 */ - case MII_PHYSID2: /* PHYS ID 2 */ - case MII_ADVERTISE: /* Advertisement control reg */ - case MII_LPA: /* Link partner ability reg */ - case MII_EXPANSION: /* Expansion register */ - case MII_DCOUNTER: /* disconnect counter */ - case MII_FCSCOUNTER: /* false carrier counter */ - case MII_NWAYTEST: /* N-way auto-neg test register */ - case MII_RERRCOUNTER: /* rx error counter */ - case MII_SREVISION: /* silicon revision */ - case MII_RESV1: /* reserved 1 */ - case MII_LBRERROR: /* loopback, rx, bypass error */ - case MII_PHYADDR: /* physical address */ - case MII_RESV2: /* reserved 2 */ - case MII_TPISTATUS: /* TPI status for 10mbps */ - case MII_NCONFIG: /* network interface config */ - default: - break; - } -} static inline const char * qeth_arp_get_error_cause(int *rc) @@ -5237,21 +5211,6 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) mii_data->val_out = qeth_mdio_read(dev,mii_data->phy_id, mii_data->reg_num); break; - case SIOCSMIIREG: - rc = -EOPNOTSUPP; - break; - /* TODO: remove return if qeth_mdio_write does something */ - if (!capable(CAP_NET_ADMIN)){ - rc = -EPERM; - break; - } - mii_data = if_mii(rq); - if (mii_data->phy_id != 0) - rc = -EINVAL; - else - qeth_mdio_write(dev, mii_data->phy_id, mii_data->reg_num, - mii_data->val_in); - break; default: rc = -EOPNOTSUPP; } @@ -6901,7 +6860,7 @@ qeth_send_setassparms(struct qeth_card *card, struct qeth_cmd_buffer *iob, cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); if (len <= sizeof(__u32)) cmd->data.setassparms.data.flags_32bit = (__u32) data; - else if (len > sizeof(__u32)) + else /* (len > sizeof(__u32)) */ memcpy(&cmd->data.setassparms.data, (void *) data, len); rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param); diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index 1304641545df..360d782c7ada 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c @@ -74,7 +74,7 @@ qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) static inline const char * qeth_get_router_str(struct qeth_card *card, int ipv) { - int routing_type = 0; + enum qeth_routing_types routing_type = NO_ROUTER; if (ipv == 4) { routing_type = card->options.route4.type; @@ -86,26 +86,26 @@ qeth_get_router_str(struct qeth_card *card, int ipv) #endif /* CONFIG_QETH_IPV6 */ } - if (routing_type == PRIMARY_ROUTER) + switch (routing_type){ + case PRIMARY_ROUTER: return "pri"; - else if (routing_type == SECONDARY_ROUTER) + case SECONDARY_ROUTER: return "sec"; - else if (routing_type == MULTICAST_ROUTER) { + case MULTICAST_ROUTER: if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) return "mc+"; return "mc"; - } else if (routing_type == PRIMARY_CONNECTOR) { + case PRIMARY_CONNECTOR: if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) return "p+c"; return "p.c"; - } else if (routing_type == SECONDARY_CONNECTOR) { + case SECONDARY_CONNECTOR: if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) return "s+c"; return "s.c"; - } else if (routing_type == NO_ROUTER) + default: /* NO_ROUTER */ return "no"; - else - return "unk"; + } } static int diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index c1831f572585..f2a076a2b2f1 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -115,7 +115,7 @@ qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const c return -EPERM; portno = simple_strtoul(buf, &tmp, 16); - if ((portno < 0) || (portno > MAX_PORTNO)){ + if (portno > MAX_PORTNO){ PRINT_WARN("portno 0x%X is out of range\n", portno); return -EINVAL; } -- cgit v1.2.3-59-g8ed1b From def720e6166f49027c45286088d1e22743666ca3 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Wed, 22 Mar 2006 16:03:44 +0100 Subject: [PATCH] s390: qeth :allow setting of attribute "route6" to "no_router". [patch 4/6] s390: qeth :allow setting of attribute "route6" to "no_router". From: Ursula Braun when setting route6 attribute back to no_router qeth does not issue an IP ASSIST command to reset router value to no_router. Once primary_router is set device stays in this mode. Issue an IP ASSIST command when no_router is set in route6. Device will be reset and thus will not longer run as a primary router. Signed-off-by: Frank Pavlic diffstat: qeth_main.c | 5 ----- 1 files changed, 5 deletions(-) Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_main.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 69329ea61e2b..021cd5d08c61 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -7339,11 +7339,6 @@ qeth_setrouting_v6(struct qeth_card *card) qeth_correct_routing_type(card, &card->options.route6.type, QETH_PROT_IPV6); - if ((card->options.route6.type == NO_ROUTER) || - ((card->info.type == QETH_CARD_TYPE_OSAE) && - (card->options.route6.type == MULTICAST_ROUTER) && - !qeth_is_supported6(card,IPA_OSA_MC_ROUTER))) - return 0; rc = qeth_send_setrouting(card, card->options.route6.type, QETH_PROT_IPV6); if (rc) { -- cgit v1.2.3-59-g8ed1b From eadfa7ddca98b0430b8b666e0344ab1d559389c8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 22 Mar 2006 10:38:45 -0800 Subject: [PATCH] sky2: more ethtool stats Expose all the available hardware statistics via ethtool. And cleanup some of the statistics definitions. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 27 +++++++++++++++++---- drivers/net/sky2.h | 71 +++++++++++++++++++++++++++--------------------------- 2 files changed, 57 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index f08fe6c884b2..36db93811ac7 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2478,17 +2478,34 @@ static const struct sky2_stat { { "rx_unicast", GM_RXF_UC_OK }, { "tx_mac_pause", GM_TXF_MPAUSE }, { "rx_mac_pause", GM_RXF_MPAUSE }, - { "collisions", GM_TXF_SNG_COL }, + { "collisions", GM_TXF_COL }, { "late_collision",GM_TXF_LAT_COL }, { "aborted", GM_TXF_ABO_COL }, + { "single_collisions", GM_TXF_SNG_COL }, { "multi_collisions", GM_TXF_MUL_COL }, - { "fifo_underrun", GM_TXE_FIFO_UR }, - { "fifo_overflow", GM_RXE_FIFO_OV }, - { "rx_toolong", GM_RXF_LNG_ERR }, - { "rx_jabber", GM_RXF_JAB_PKT }, + + { "rx_short", GM_RXE_SHT }, { "rx_runt", GM_RXE_FRAG }, + { "rx_64_byte_packets", GM_RXF_64B }, + { "rx_65_to_127_byte_packets", GM_RXF_127B }, + { "rx_128_to_255_byte_packets", GM_RXF_255B }, + { "rx_256_to_511_byte_packets", GM_RXF_511B }, + { "rx_512_to_1023_byte_packets", GM_RXF_1023B }, + { "rx_1024_to_1518_byte_packets", GM_RXF_1518B }, + { "rx_1518_to_max_byte_packets", GM_RXF_MAX_SZ }, { "rx_too_long", GM_RXF_LNG_ERR }, + { "rx_fifo_overflow", GM_RXE_FIFO_OV }, + { "rx_jabber", GM_RXF_JAB_PKT }, { "rx_fcs_error", GM_RXF_FCS_ERR }, + + { "tx_64_byte_packets", GM_TXF_64B }, + { "tx_65_to_127_byte_packets", GM_TXF_127B }, + { "tx_128_to_255_byte_packets", GM_TXF_255B }, + { "tx_256_to_511_byte_packets", GM_TXF_511B }, + { "tx_512_to_1023_byte_packets", GM_TXF_1023B }, + { "tx_1024_to_1518_byte_packets", GM_TXF_1518B }, + { "tx_1519_to_max_byte_packets", GM_TXF_MAX_SZ }, + { "tx_fifo_underrun", GM_TXE_FIFO_UR }, }; static u32 sky2_get_rx_csum(struct net_device *dev) diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index d63cd5a1b71c..2838f661b393 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1373,23 +1373,23 @@ enum { GM_SMI_CTRL = 0x0080, /* 16 bit r/w SMI Control Register */ GM_SMI_DATA = 0x0084, /* 16 bit r/w SMI Data Register */ GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */ +/* MIB Counters */ + GM_MIB_CNT_BASE = 0x0100, /* Base Address of MIB Counters */ + GM_MIB_CNT_SIZE = 256, }; -/* MIB Counters */ -#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */ -#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */ /* * MIB Counters base address definitions (low word) - * use offset 4 for access to high word (32 bit r/o) */ enum { - GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */ + GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */ GM_RXF_BC_OK = GM_MIB_CNT_BASE + 8, /* Broadcast Frames Received OK */ GM_RXF_MPAUSE = GM_MIB_CNT_BASE + 16, /* Pause MAC Ctrl Frames Received */ GM_RXF_MC_OK = GM_MIB_CNT_BASE + 24, /* Multicast Frames Received OK */ GM_RXF_FCS_ERR = GM_MIB_CNT_BASE + 32, /* Rx Frame Check Seq. Error */ - /* GM_MIB_CNT_BASE + 40: reserved */ + GM_RXO_OK_LO = GM_MIB_CNT_BASE + 48, /* Octets Received OK Low */ GM_RXO_OK_HI = GM_MIB_CNT_BASE + 56, /* Octets Received OK High */ GM_RXO_ERR_LO = GM_MIB_CNT_BASE + 64, /* Octets Received Invalid Low */ @@ -1397,37 +1397,36 @@ enum { GM_RXF_SHT = GM_MIB_CNT_BASE + 80, /* Frames <64 Byte Received OK */ GM_RXE_FRAG = GM_MIB_CNT_BASE + 88, /* Frames <64 Byte Received with FCS Err */ GM_RXF_64B = GM_MIB_CNT_BASE + 96, /* 64 Byte Rx Frame */ - GM_RXF_127B = GM_MIB_CNT_BASE + 104, /* 65-127 Byte Rx Frame */ - GM_RXF_255B = GM_MIB_CNT_BASE + 112, /* 128-255 Byte Rx Frame */ - GM_RXF_511B = GM_MIB_CNT_BASE + 120, /* 256-511 Byte Rx Frame */ - GM_RXF_1023B = GM_MIB_CNT_BASE + 128, /* 512-1023 Byte Rx Frame */ - GM_RXF_1518B = GM_MIB_CNT_BASE + 136, /* 1024-1518 Byte Rx Frame */ - GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144, /* 1519-MaxSize Byte Rx Frame */ - GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152, /* Rx Frame too Long Error */ - GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160, /* Rx Jabber Packet Frame */ - /* GM_MIB_CNT_BASE + 168: reserved */ - GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176, /* Rx FIFO overflow Event */ - /* GM_MIB_CNT_BASE + 184: reserved */ - GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192, /* Unicast Frames Xmitted OK */ - GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200, /* Broadcast Frames Xmitted OK */ - GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208, /* Pause MAC Ctrl Frames Xmitted */ - GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216, /* Multicast Frames Xmitted OK */ - GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224, /* Octets Transmitted OK Low */ - GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232, /* Octets Transmitted OK High */ - GM_TXF_64B = GM_MIB_CNT_BASE + 240, /* 64 Byte Tx Frame */ - GM_TXF_127B = GM_MIB_CNT_BASE + 248, /* 65-127 Byte Tx Frame */ - GM_TXF_255B = GM_MIB_CNT_BASE + 256, /* 128-255 Byte Tx Frame */ - GM_TXF_511B = GM_MIB_CNT_BASE + 264, /* 256-511 Byte Tx Frame */ - GM_TXF_1023B = GM_MIB_CNT_BASE + 272, /* 512-1023 Byte Tx Frame */ - GM_TXF_1518B = GM_MIB_CNT_BASE + 280, /* 1024-1518 Byte Tx Frame */ - GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288, /* 1519-MaxSize Byte Tx Frame */ - - GM_TXF_COL = GM_MIB_CNT_BASE + 304, /* Tx Collision */ - GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312, /* Tx Late Collision */ - GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320, /* Tx aborted due to Exces. Col. */ - GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328, /* Tx Multiple Collision */ - GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336, /* Tx Single Collision */ - GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344, /* Tx FIFO Underrun Event */ + GM_RXF_127B = GM_MIB_CNT_BASE + 104,/* 65-127 Byte Rx Frame */ + GM_RXF_255B = GM_MIB_CNT_BASE + 112,/* 128-255 Byte Rx Frame */ + GM_RXF_511B = GM_MIB_CNT_BASE + 120,/* 256-511 Byte Rx Frame */ + GM_RXF_1023B = GM_MIB_CNT_BASE + 128,/* 512-1023 Byte Rx Frame */ + GM_RXF_1518B = GM_MIB_CNT_BASE + 136,/* 1024-1518 Byte Rx Frame */ + GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144,/* 1519-MaxSize Byte Rx Frame */ + GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152,/* Rx Frame too Long Error */ + GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160,/* Rx Jabber Packet Frame */ + + GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176,/* Rx FIFO overflow Event */ + GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192,/* Unicast Frames Xmitted OK */ + GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200,/* Broadcast Frames Xmitted OK */ + GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208,/* Pause MAC Ctrl Frames Xmitted */ + GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216,/* Multicast Frames Xmitted OK */ + GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224,/* Octets Transmitted OK Low */ + GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232,/* Octets Transmitted OK High */ + GM_TXF_64B = GM_MIB_CNT_BASE + 240,/* 64 Byte Tx Frame */ + GM_TXF_127B = GM_MIB_CNT_BASE + 248,/* 65-127 Byte Tx Frame */ + GM_TXF_255B = GM_MIB_CNT_BASE + 256,/* 128-255 Byte Tx Frame */ + GM_TXF_511B = GM_MIB_CNT_BASE + 264,/* 256-511 Byte Tx Frame */ + GM_TXF_1023B = GM_MIB_CNT_BASE + 272,/* 512-1023 Byte Tx Frame */ + GM_TXF_1518B = GM_MIB_CNT_BASE + 280,/* 1024-1518 Byte Tx Frame */ + GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288,/* 1519-MaxSize Byte Tx Frame */ + + GM_TXF_COL = GM_MIB_CNT_BASE + 304,/* Tx Collision */ + GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312,/* Tx Late Collision */ + GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320,/* Tx aborted due to Exces. Col. */ + GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328,/* Tx Multiple Collision */ + GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336,/* Tx Single Collision */ + GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344,/* Tx FIFO Underrun Event */ }; /* GMAC Bit Definitions */ -- cgit v1.2.3-59-g8ed1b From 494aced2cda34c186083f7d53c419426eea3d584 Mon Sep 17 00:00:00 2001 From: Artur Skawina Date: Tue, 21 Mar 2006 22:04:36 +0100 Subject: [PATCH] sis900 adm7001 PHY support this patch is required to get a SIS964 based motherboard ethernet working (FSC D1875) (picking the #1 transceiver, instead of the last one, in case no known ones were found might be a better default, and would have worked in this case too) Signed-off-by: Artur Skawina Signed-off-by: Jeff Garzik --- drivers/net/sis900.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index a1cb07cdb60f..253440a98022 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -128,6 +128,7 @@ static const struct mii_chip_info { { "SiS 900 Internal MII PHY", 0x001d, 0x8000, LAN }, { "SiS 7014 Physical Layer Solution", 0x0016, 0xf830, LAN }, { "Altimata AC101LF PHY", 0x0022, 0x5520, LAN }, + { "ADM 7001 LAN PHY", 0x002e, 0xcc60, LAN }, { "AMD 79C901 10BASE-T PHY", 0x0000, 0x6B70, LAN }, { "AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, HOME}, { "ICS LAN PHY", 0x0015, 0xF440, LAN }, -- cgit v1.2.3-59-g8ed1b From 5185c7c20a4b88892f868ad8d92d1b640b1edba9 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Wed, 22 Mar 2006 22:30:34 +0100 Subject: [PATCH] Use after free in net/tulip/de2104x.c hi, this fixes coverity bug #912, where skb is freed first, and dereferenced a few lines later with skb->len. Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik --- drivers/net/tulip/de2104x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 6299e186c73f..e3dd144d326b 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -1327,11 +1327,11 @@ static void de_clean_rings (struct de_private *de) struct sk_buff *skb = de->tx_skb[i].skb; if ((skb) && (skb != DE_DUMMY_SKB)) { if (skb != DE_SETUP_SKB) { - dev_kfree_skb(skb); de->net_stats.tx_dropped++; pci_unmap_single(de->pdev, de->tx_skb[i].mapping, skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb(skb); } else { pci_unmap_single(de->pdev, de->tx_skb[i].mapping, -- cgit v1.2.3-59-g8ed1b From 6a6bbd29a0284c1b9d33c324ba85f3ebb5509589 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Wed, 22 Mar 2006 22:49:48 +0100 Subject: [PATCH] Use of uninitialized variable in drivers/net/depca.c hi, this fixes coverity bug #888, where the variable dev is used uninitialized. I assume the programmer meant to use mdev, which is initialized. Compile tested only. Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik --- drivers/net/depca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 03804cc38be0..0941d40f046f 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1412,7 +1412,7 @@ static int __init depca_mca_probe(struct device *device) irq = 11; break; default: - printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where); + printk("%s: mca_probe IRQ error. You should never get here (%d).\n", mdev->name, where); return -EINVAL; } -- cgit v1.2.3-59-g8ed1b From 0caab23e11c015559af81a4c0f4759ca05a5446a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 22 Mar 2006 17:39:38 -0800 Subject: scsi: link in the debug driver last If the debug driver is built-in, link it in last, so that any real drivers will probe first, rather than having the debug driver pick the first scsi slots.. Signed-off-by: Douglas Gilbert Signed-off-by: Randy Dunlap Acked-by: James Bottomley Signed-off-by: Linus Torvalds --- drivers/scsi/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 15dc2e00e1b2..e513c3158ad9 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -117,7 +117,6 @@ obj-$(CONFIG_SCSI_PPA) += ppa.o obj-$(CONFIG_SCSI_IMM) += imm.o obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.o jazz_esp.o obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o -obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o obj-$(CONFIG_SCSI_FCAL) += fcal.o obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o @@ -148,6 +147,9 @@ obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o obj-$(CONFIG_CHR_DEV_SG) += sg.o obj-$(CONFIG_CHR_DEV_SCH) += ch.o +# This goes last, so that "real" scsi devices probe earlier +obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o + scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_error.o scsi_lib.o \ scsi_scan.o scsi_sysfs.o \ -- cgit v1.2.3-59-g8ed1b From 3bea63136fd9b1398de77f76b7b9e3b28249ecca Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Tue, 21 Mar 2006 23:00:05 -0800 Subject: [PATCH] powerpc: make powerbook_sleep_grackle static powerbook_sleep_grackle is only called inside via-pmu, from pmu_ioctl() Signed-off-by: Olaf Hering Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- drivers/macintosh/via-pmu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 4a478eb0e27d..8a8fffa339f0 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -2201,8 +2201,7 @@ pmac_wakeup_devices(void) #define GRACKLE_NAP (1<<4) #define GRACKLE_SLEEP (1<<3) -int -powerbook_sleep_grackle(void) +static int powerbook_sleep_grackle(void) { unsigned long save_l2cr; unsigned short pmcr1; -- cgit v1.2.3-59-g8ed1b From 8ac4fc53fef6b4ff942a66be1b503b24d32bcf83 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 21 Mar 2006 23:00:06 -0800 Subject: [PATCH] powerpc: dont allow old RTC to be selected Now powerpc uses the generic RTC stuff we should not enable the old RTC. Doing so will result in hangs at boot. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- drivers/char/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 05ba410682a3..b524f5ba78a9 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -695,7 +695,7 @@ config NVRAM config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV + depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you -- cgit v1.2.3-59-g8ed1b From 3e52174ec8fd9d8671b69b8e7decb465aaf519c0 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 21 Mar 2006 23:20:26 -0800 Subject: [PATCH] macintosh: cleanup the use of i2c headers Cleanup the use of i2c headers in macintosh drivers. Signed-off-by: Jean Delvare Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- drivers/macintosh/therm_pm72.c | 2 -- drivers/macintosh/windfarm_lm75_sensor.c | 1 - drivers/macintosh/windfarm_max6690_sensor.c | 1 - drivers/macintosh/windfarm_smu_sat.c | 1 - 4 files changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index 4f50ee5767a2..231146f439dd 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -104,7 +104,6 @@ #include #include #include -#include #include #include #include @@ -113,7 +112,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index 423bfa2432c0..3f7967feaf5b 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c index 8e99d408fddd..eae1189d6c41 100644 --- a/drivers/macintosh/windfarm_max6690_sensor.c +++ b/drivers/macintosh/windfarm_max6690_sensor.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index 24e51d5e97fc..e295a07a1ebc 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3-59-g8ed1b From 57ae595f6bf8bde42de199ff9fe68b873080fde2 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 21 Mar 2006 23:20:27 -0800 Subject: [PATCH] powerpc: via-pmu warning fix drivers/macintosh/via-pmu.c:164: warning: `sleep_in_progress' defined but not used Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- drivers/macintosh/via-pmu.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 8a8fffa339f0..4f5f3abc9cb3 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -161,7 +161,9 @@ static int drop_interrupts; #if defined(CONFIG_PM) && defined(CONFIG_PPC32) static int option_lid_wakeup = 1; #endif /* CONFIG_PM && CONFIG_PPC32 */ +#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT) static int sleep_in_progress; +#endif static unsigned long async_req_locks; static unsigned int pmu_irq_stats[11]; -- cgit v1.2.3-59-g8ed1b From 6ea671a12f66b9d4d0f35fce957a71a6849295f2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 21 Mar 2006 23:20:27 -0800 Subject: [PATCH] powerpc: tidy-up of_register_driver()/driver_register() return values Remove the assumption that driver_register() returns the number of devices bound to the driver. In fact, it returns zero for success or a negative error value. Nobody uses the return value of of_register_driver() anyway. Signed-off-by: Bjorn Helgaas Acked-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/of_device.c | 5 +---- drivers/macintosh/smu.c | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 22d83d4d1af5..9feeeef5a875 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -147,15 +147,12 @@ postcore_initcall(of_bus_driver_init); int of_register_driver(struct of_platform_driver *drv) { - int count = 0; - /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &of_platform_bus_type; /* register with core */ - count = driver_register(&drv->driver); - return count ? count : 1; + return driver_register(&drv->driver); } void of_unregister_driver(struct of_platform_driver *drv) diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index db2ae71d07ef..4eb05d7143d8 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -629,8 +629,6 @@ static struct of_platform_driver smu_of_platform_driver = static int __init smu_init_sysfs(void) { - int rc; - /* * Due to sysfs bogosity, a sysdev is not a real device, so * we should in fact create both if we want sysdev semantics @@ -639,7 +637,7 @@ static int __init smu_init_sysfs(void) * I'm a bit too far from figuring out how that works with those * new chipsets, but that will come back and bite us */ - rc = of_register_driver(&smu_of_platform_driver); + of_register_driver(&smu_of_platform_driver); return 0; } -- cgit v1.2.3-59-g8ed1b From d56a3e380085bf45cc2adba80c4e6490ba644231 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 21 Mar 2006 23:20:28 -0800 Subject: [PATCH] macintosh: tidy-up driver_register() return values Remove the assumption that driver_register() returns the number of devices bound to the driver. In fact, it returns zero for success or a negative error value. All callers of macio_register_driver() either ignore the return value or return it as the return value of a module_init() function. Signed-off-by: Bjorn Helgaas Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- drivers/macintosh/macio_asic.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 69596f6438e9..431bd37225a1 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -550,15 +550,12 @@ static void macio_pci_add_devices(struct macio_chip *chip) */ int macio_register_driver(struct macio_driver *drv) { - int count = 0; - /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &macio_bus_type; /* register with core */ - count = driver_register(&drv->driver); - return count ? count : 1; + return driver_register(&drv->driver); } /** -- cgit v1.2.3-59-g8ed1b From 142877b07fe1ef1816513b20f65a51c6ffcadb8b Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 22 Mar 2006 23:30:34 -0500 Subject: [libata sata_sil24] cleanups: use pci_iomap(), kzalloc() * libata will soon move to iomap, so we should use pci_iomap() and pci_iounmap(). * Use kzalloc() where appropriate. --- drivers/scsi/sata_sil24.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 5d01e5ce5ac5..3efebea211f2 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -842,9 +842,10 @@ static void sil24_port_stop(struct ata_port *ap) static void sil24_host_stop(struct ata_host_set *host_set) { struct sil24_host_priv *hpriv = host_set->private_data; + struct pci_dev *pdev = to_pci_dev(host_set->dev); - iounmap(hpriv->host_base); - iounmap(hpriv->port_base); + pci_iounmap(pdev, hpriv->host_base); + pci_iounmap(pdev, hpriv->port_base); kfree(hpriv); } @@ -871,26 +872,23 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_disable; rc = -ENOMEM; - /* ioremap mmio registers */ - host_base = ioremap(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + /* map mmio registers */ + host_base = pci_iomap(pdev, 0, 0); if (!host_base) goto out_free; - port_base = ioremap(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); + port_base = pci_iomap(pdev, 2, 0); if (!port_base) goto out_free; /* allocate & init probe_ent and hpriv */ - probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); if (!probe_ent) goto out_free; - hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL); + hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL); if (!hpriv) goto out_free; - memset(probe_ent, 0, sizeof(*probe_ent)); probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); @@ -907,7 +905,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->mmio_base = port_base; probe_ent->private_data = hpriv; - memset(hpriv, 0, sizeof(*hpriv)); hpriv->host_base = host_base; hpriv->port_base = port_base; @@ -1011,9 +1008,9 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) out_free: if (host_base) - iounmap(host_base); + pci_iounmap(pdev, host_base); if (port_base) - iounmap(port_base); + pci_iounmap(pdev, port_base); kfree(probe_ent); kfree(hpriv); pci_release_regions(pdev); -- cgit v1.2.3-59-g8ed1b From 10ad05df14fb5b6ac1fcdaa312a9c13e77627a97 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 22 Mar 2006 23:50:50 -0500 Subject: [libata sata_nv] cleanups: convert #defines to enums; remove in-file history --- drivers/scsi/sata_nv.c | 124 +++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index e5b20c6afc18..834003eb36a7 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -29,34 +29,6 @@ * NV-specific details such as register offsets, SATA phy location, * hotplug info, etc. * - * 0.10 - * - Fixed spurious interrupts issue seen with the Maxtor 6H500F0 500GB - * drive. Also made the check_hotplug() callbacks return whether there - * was a hotplug interrupt or not. This was not the source of the - * spurious interrupts, but is the right thing to do anyway. - * - * 0.09 - * - Fixed bug introduced by 0.08's MCP51 and MCP55 support. - * - * 0.08 - * - Added support for MCP51 and MCP55. - * - * 0.07 - * - Added support for RAID class code. - * - * 0.06 - * - Added generic SATA support by using a pci_device_id that filters on - * the IDE storage class code. - * - * 0.03 - * - Fixed a bug where the hotplug handlers for non-CK804/MCP04 were using - * mmio_base, which is only set for the CK804/MCP04 case. - * - * 0.02 - * - Added support for CK804 SATA controller. - * - * 0.01 - * - Initial revision. */ #include @@ -74,53 +46,55 @@ #define DRV_NAME "sata_nv" #define DRV_VERSION "0.8" -#define NV_PORTS 2 -#define NV_PIO_MASK 0x1f -#define NV_MWDMA_MASK 0x07 -#define NV_UDMA_MASK 0x7f -#define NV_PORT0_SCR_REG_OFFSET 0x00 -#define NV_PORT1_SCR_REG_OFFSET 0x40 - -#define NV_INT_STATUS 0x10 -#define NV_INT_STATUS_CK804 0x440 -#define NV_INT_STATUS_PDEV_INT 0x01 -#define NV_INT_STATUS_PDEV_PM 0x02 -#define NV_INT_STATUS_PDEV_ADDED 0x04 -#define NV_INT_STATUS_PDEV_REMOVED 0x08 -#define NV_INT_STATUS_SDEV_INT 0x10 -#define NV_INT_STATUS_SDEV_PM 0x20 -#define NV_INT_STATUS_SDEV_ADDED 0x40 -#define NV_INT_STATUS_SDEV_REMOVED 0x80 -#define NV_INT_STATUS_PDEV_HOTPLUG (NV_INT_STATUS_PDEV_ADDED | \ - NV_INT_STATUS_PDEV_REMOVED) -#define NV_INT_STATUS_SDEV_HOTPLUG (NV_INT_STATUS_SDEV_ADDED | \ - NV_INT_STATUS_SDEV_REMOVED) -#define NV_INT_STATUS_HOTPLUG (NV_INT_STATUS_PDEV_HOTPLUG | \ - NV_INT_STATUS_SDEV_HOTPLUG) - -#define NV_INT_ENABLE 0x11 -#define NV_INT_ENABLE_CK804 0x441 -#define NV_INT_ENABLE_PDEV_MASK 0x01 -#define NV_INT_ENABLE_PDEV_PM 0x02 -#define NV_INT_ENABLE_PDEV_ADDED 0x04 -#define NV_INT_ENABLE_PDEV_REMOVED 0x08 -#define NV_INT_ENABLE_SDEV_MASK 0x10 -#define NV_INT_ENABLE_SDEV_PM 0x20 -#define NV_INT_ENABLE_SDEV_ADDED 0x40 -#define NV_INT_ENABLE_SDEV_REMOVED 0x80 -#define NV_INT_ENABLE_PDEV_HOTPLUG (NV_INT_ENABLE_PDEV_ADDED | \ - NV_INT_ENABLE_PDEV_REMOVED) -#define NV_INT_ENABLE_SDEV_HOTPLUG (NV_INT_ENABLE_SDEV_ADDED | \ - NV_INT_ENABLE_SDEV_REMOVED) -#define NV_INT_ENABLE_HOTPLUG (NV_INT_ENABLE_PDEV_HOTPLUG | \ - NV_INT_ENABLE_SDEV_HOTPLUG) - -#define NV_INT_CONFIG 0x12 -#define NV_INT_CONFIG_METHD 0x01 // 0 = INT, 1 = SMI - -// For PCI config register 20 -#define NV_MCP_SATA_CFG_20 0x50 -#define NV_MCP_SATA_CFG_20_SATA_SPACE_EN 0x04 +enum { + NV_PORTS = 2, + NV_PIO_MASK = 0x1f, + NV_MWDMA_MASK = 0x07, + NV_UDMA_MASK = 0x7f, + NV_PORT0_SCR_REG_OFFSET = 0x00, + NV_PORT1_SCR_REG_OFFSET = 0x40, + + 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_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, + 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, + 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 + + // For PCI config register 20 + NV_MCP_SATA_CFG_20 = 0x50, + NV_MCP_SATA_CFG_20_SATA_SPACE_EN = 0x04, +}; 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, -- cgit v1.2.3-59-g8ed1b From 02cbd926e9acdc03574d26803050cd2664f59ada Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 22 Mar 2006 23:59:46 -0500 Subject: [libata sata_nv] eliminate duplicate codepaths with iomap eliminate a bunch of if (mmio) writel() else outl() code with the pci_iomap() and io{read,write}{8,16,32}() interface. --- drivers/scsi/sata_nv.c | 57 ++++++++++++-------------------------------------- 1 file changed, 13 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 834003eb36a7..f77bf183dfab 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -149,8 +149,6 @@ static const struct pci_device_id nv_pci_tbl[] = { { 0, } /* terminate list */ }; -#define NV_HOST_FLAGS_SCR_MMIO 0x00000001 - struct nv_host_desc { enum nv_host_type host_type; @@ -306,36 +304,23 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg) { - struct ata_host_set *host_set = ap->host_set; - struct nv_host *host = host_set->private_data; - if (sc_reg > SCR_CONTROL) return 0xffffffffU; - if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) - return readl((void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); - else - return inl(ap->ioaddr.scr_addr + (sc_reg * 4)); + return ioread32((void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); } static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) { - struct ata_host_set *host_set = ap->host_set; - struct nv_host *host = host_set->private_data; - if (sc_reg > SCR_CONTROL) return; - if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) - writel(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); - else - outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)); + 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; - struct pci_dev *pdev = to_pci_dev(host_set->dev); // Disable hotplug event interrupts. if (host->host_desc->disable_hotplug) @@ -343,8 +328,7 @@ static void nv_host_stop (struct ata_host_set *host_set) kfree(host); - if (host_set->mmio_base) - pci_iounmap(pdev, host_set->mmio_base); + ata_pci_host_stop(host_set); } static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -356,6 +340,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) int pci_dev_busy = 0; int rc; u32 bar; + unsigned long base; // Make sure this is a SATA controller by counting the number of bars // (NVIDIA SATA controllers will always have six bars). Otherwise, @@ -400,31 +385,16 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->private_data = host; - if (pci_resource_flags(pdev, 5) & IORESOURCE_MEM) - host->host_flags |= NV_HOST_FLAGS_SCR_MMIO; - - if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) { - unsigned long base; - - probe_ent->mmio_base = pci_iomap(pdev, 5, 0); - if (probe_ent->mmio_base == NULL) { - rc = -EIO; - goto err_out_free_host; - } - - base = (unsigned long)probe_ent->mmio_base; + probe_ent->mmio_base = pci_iomap(pdev, 5, 0); + if (!probe_ent->mmio_base) { + rc = -EIO; + goto err_out_free_host; + } - probe_ent->port[0].scr_addr = - base + NV_PORT0_SCR_REG_OFFSET; - probe_ent->port[1].scr_addr = - base + NV_PORT1_SCR_REG_OFFSET; - } else { + base = (unsigned long)probe_ent->mmio_base; - probe_ent->port[0].scr_addr = - pci_resource_start(pdev, 5) | NV_PORT0_SCR_REG_OFFSET; - probe_ent->port[1].scr_addr = - pci_resource_start(pdev, 5) | NV_PORT1_SCR_REG_OFFSET; - } + probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET; + probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET; pci_set_master(pdev); @@ -441,8 +411,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) return 0; err_out_iounmap: - if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) - pci_iounmap(pdev, probe_ent->mmio_base); + pci_iounmap(pdev, probe_ent->mmio_base); err_out_free_host: kfree(host); err_out_free_ent: -- cgit v1.2.3-59-g8ed1b From 50106c5a0366c9e02bf872e85c672732aa517fb4 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 23 Mar 2006 00:14:36 -0500 Subject: [libata sata_uli] kill scr_addr abuse sata_uli was storing PCI config addresses in a variable intended for port addresses, a variable soon to become void __iomem *. Update the driver to store the SCR address, found in PCI config space, in the driver-private data area. --- drivers/scsi/sata_uli.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 8f5025733def..7ac5a5f5a905 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -44,6 +44,8 @@ enum { uli_5287 = 1, uli_5281 = 2, + uli_max_ports = 4, + /* PCI configuration registers */ ULI5287_BASE = 0x90, /* sata0 phy SCR registers */ ULI5287_OFFS = 0x10, /* offset from sata0->sata1 phy regs */ @@ -51,6 +53,10 @@ enum { ULI5281_OFFS = 0x60, /* offset from sata0->sata1 phy regs */ }; +struct uli_priv { + unsigned int scr_cfg_addr[uli_max_ports]; +}; + static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static u32 uli_scr_read (struct ata_port *ap, unsigned int sc_reg); static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); @@ -137,7 +143,8 @@ MODULE_VERSION(DRV_VERSION); static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg) { - return ap->ioaddr.scr_addr + (4 * sc_reg); + struct uli_priv *hpriv = ap->host_set->private_data; + return hpriv->scr_cfg_addr[ap->port_no] + (4 * sc_reg); } static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) @@ -182,6 +189,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) int rc; unsigned int board_idx = (unsigned int) ent->driver_data; int pci_dev_busy = 0; + struct uli_priv *hpriv; if (!printed_version++) dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); @@ -210,10 +218,18 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_regions; } + hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL); + if (!hpriv) { + rc = -ENOMEM; + goto err_out_probe_ent; + } + + probe_ent->private_data = hpriv; + switch (board_idx) { case uli_5287: - probe_ent->port[0].scr_addr = ULI5287_BASE; - probe_ent->port[1].scr_addr = ULI5287_BASE + ULI5287_OFFS; + hpriv->scr_cfg_addr[0] = ULI5287_BASE; + hpriv->scr_cfg_addr[1] = ULI5287_BASE + ULI5287_OFFS; probe_ent->n_ports = 4; probe_ent->port[2].cmd_addr = pci_resource_start(pdev, 0) + 8; @@ -221,27 +237,27 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->port[2].ctl_addr = (pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS) + 4; probe_ent->port[2].bmdma_addr = pci_resource_start(pdev, 4) + 16; - probe_ent->port[2].scr_addr = ULI5287_BASE + ULI5287_OFFS*4; + hpriv->scr_cfg_addr[2] = ULI5287_BASE + ULI5287_OFFS*4; probe_ent->port[3].cmd_addr = pci_resource_start(pdev, 2) + 8; probe_ent->port[3].altstatus_addr = probe_ent->port[3].ctl_addr = (pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS) + 4; probe_ent->port[3].bmdma_addr = pci_resource_start(pdev, 4) + 24; - probe_ent->port[3].scr_addr = ULI5287_BASE + ULI5287_OFFS*5; + hpriv->scr_cfg_addr[3] = ULI5287_BASE + ULI5287_OFFS*5; ata_std_ports(&probe_ent->port[2]); ata_std_ports(&probe_ent->port[3]); break; case uli_5289: - probe_ent->port[0].scr_addr = ULI5287_BASE; - probe_ent->port[1].scr_addr = ULI5287_BASE + ULI5287_OFFS; + hpriv->scr_cfg_addr[0] = ULI5287_BASE; + hpriv->scr_cfg_addr[1] = ULI5287_BASE + ULI5287_OFFS; break; case uli_5281: - probe_ent->port[0].scr_addr = ULI5281_BASE; - probe_ent->port[1].scr_addr = ULI5281_BASE + ULI5281_OFFS; + hpriv->scr_cfg_addr[0] = ULI5281_BASE; + hpriv->scr_cfg_addr[1] = ULI5281_BASE + ULI5281_OFFS; break; default: @@ -258,9 +274,10 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) return 0; +err_out_probe_ent: + kfree(probe_ent); err_out_regions: pci_release_regions(pdev); - err_out: if (!pci_dev_busy) pci_disable_device(pdev); -- cgit v1.2.3-59-g8ed1b From 2cc432eed0491df66e14b578139bba2c75fb3f9a Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 23 Mar 2006 00:32:03 -0500 Subject: [libata] Move some bmdma-specific code to libata-bmdma.c No code changes, just moving code between files. --- drivers/scsi/libata-bmdma.c | 234 ++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata-core.c | 234 -------------------------------------------- 2 files changed, 234 insertions(+), 234 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 96b4d2160df8..a00a78b30836 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -418,6 +418,240 @@ u8 ata_altstatus(struct ata_port *ap) return inb(ap->ioaddr.altstatus_addr); } +/** + * ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction + * @qc: Info associated with this ATA transaction. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); + u8 dmactl; + void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; + + /* load PRD table addr. */ + mb(); /* make sure PRD table writes are visible to controller */ + writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS); + + /* specify data direction, triple-check start bit is clear */ + dmactl = readb(mmio + ATA_DMA_CMD); + dmactl &= ~(ATA_DMA_WR | ATA_DMA_START); + if (!rw) + dmactl |= ATA_DMA_WR; + writeb(dmactl, mmio + ATA_DMA_CMD); + + /* issue r/w command */ + ap->ops->exec_command(ap, &qc->tf); +} + +/** + * ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction + * @qc: Info associated with this ATA transaction. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; + u8 dmactl; + + /* start host DMA transaction */ + dmactl = readb(mmio + ATA_DMA_CMD); + writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD); + + /* Strictly, one may wish to issue a readb() here, to + * flush the mmio write. However, control also passes + * to the hardware at this point, and it will interrupt + * us when we are to resume control. So, in effect, + * we don't care when the mmio write flushes. + * Further, a read of the DMA status register _immediately_ + * following the write may not be what certain flaky hardware + * is expected, so I think it is best to not add a readb() + * without first all the MMIO ATA cards/mobos. + * Or maybe I'm just being paranoid. + */ +} + +/** + * ata_bmdma_setup_pio - Set up PCI IDE BMDMA transaction (PIO) + * @qc: Info associated with this ATA transaction. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); + u8 dmactl; + + /* load PRD table addr. */ + outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); + + /* specify data direction, triple-check start bit is clear */ + dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + dmactl &= ~(ATA_DMA_WR | ATA_DMA_START); + if (!rw) + dmactl |= ATA_DMA_WR; + outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + + /* issue r/w command */ + ap->ops->exec_command(ap, &qc->tf); +} + +/** + * ata_bmdma_start_pio - Start a PCI IDE BMDMA transaction (PIO) + * @qc: Info associated with this ATA transaction. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +static void ata_bmdma_start_pio (struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + u8 dmactl; + + /* start host DMA transaction */ + dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + outb(dmactl | ATA_DMA_START, + ap->ioaddr.bmdma_addr + ATA_DMA_CMD); +} + + +/** + * ata_bmdma_start - Start a PCI IDE BMDMA transaction + * @qc: Info associated with this ATA transaction. + * + * Writes the ATA_DMA_START flag to the DMA command register. + * + * May be used as the bmdma_start() entry in ata_port_operations. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_bmdma_start(struct ata_queued_cmd *qc) +{ + if (qc->ap->flags & ATA_FLAG_MMIO) + ata_bmdma_start_mmio(qc); + else + ata_bmdma_start_pio(qc); +} + + +/** + * ata_bmdma_setup - Set up PCI IDE BMDMA transaction + * @qc: Info associated with this ATA transaction. + * + * Writes address of PRD table to device's PRD Table Address + * register, sets the DMA control register, and calls + * ops->exec_command() to start the transfer. + * + * May be used as the bmdma_setup() entry in ata_port_operations. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_bmdma_setup(struct ata_queued_cmd *qc) +{ + if (qc->ap->flags & ATA_FLAG_MMIO) + ata_bmdma_setup_mmio(qc); + else + ata_bmdma_setup_pio(qc); +} + + +/** + * ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt. + * @ap: Port associated with this ATA transaction. + * + * Clear interrupt and error flags in DMA status register. + * + * May be used as the irq_clear() entry in ata_port_operations. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void ata_bmdma_irq_clear(struct ata_port *ap) +{ + if (!ap->ioaddr.bmdma_addr) + return; + + if (ap->flags & ATA_FLAG_MMIO) { + void __iomem *mmio = + ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; + writeb(readb(mmio), mmio); + } else { + unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; + outb(inb(addr), addr); + } +} + + +/** + * ata_bmdma_status - Read PCI IDE BMDMA status + * @ap: Port associated with this ATA transaction. + * + * Read and return BMDMA status register. + * + * May be used as the bmdma_status() entry in ata_port_operations. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +u8 ata_bmdma_status(struct ata_port *ap) +{ + u8 host_stat; + if (ap->flags & ATA_FLAG_MMIO) { + void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; + host_stat = readb(mmio + ATA_DMA_STATUS); + } else + host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + return host_stat; +} + + +/** + * ata_bmdma_stop - Stop PCI IDE BMDMA transfer + * @qc: Command we are ending DMA for + * + * Clears the ATA_DMA_START flag in the dma control register + * + * May be used as the bmdma_stop() entry in ata_port_operations. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void ata_bmdma_stop(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + if (ap->flags & ATA_FLAG_MMIO) { + void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; + + /* clear start/stop bit */ + writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START, + mmio + ATA_DMA_CMD); + } else { + /* clear start/stop bit */ + outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, + ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + } + + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_altstatus(ap); /* dummy read */ +} + #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 0314abd97f2d..f3c115b55681 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4064,240 +4064,6 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) return 0; } -/** - * ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction - * @qc: Info associated with this ATA transaction. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); - u8 dmactl; - void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; - - /* load PRD table addr. */ - mb(); /* make sure PRD table writes are visible to controller */ - writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS); - - /* specify data direction, triple-check start bit is clear */ - dmactl = readb(mmio + ATA_DMA_CMD); - dmactl &= ~(ATA_DMA_WR | ATA_DMA_START); - if (!rw) - dmactl |= ATA_DMA_WR; - writeb(dmactl, mmio + ATA_DMA_CMD); - - /* issue r/w command */ - ap->ops->exec_command(ap, &qc->tf); -} - -/** - * ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction - * @qc: Info associated with this ATA transaction. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; - u8 dmactl; - - /* start host DMA transaction */ - dmactl = readb(mmio + ATA_DMA_CMD); - writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD); - - /* Strictly, one may wish to issue a readb() here, to - * flush the mmio write. However, control also passes - * to the hardware at this point, and it will interrupt - * us when we are to resume control. So, in effect, - * we don't care when the mmio write flushes. - * Further, a read of the DMA status register _immediately_ - * following the write may not be what certain flaky hardware - * is expected, so I think it is best to not add a readb() - * without first all the MMIO ATA cards/mobos. - * Or maybe I'm just being paranoid. - */ -} - -/** - * ata_bmdma_setup_pio - Set up PCI IDE BMDMA transaction (PIO) - * @qc: Info associated with this ATA transaction. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); - u8 dmactl; - - /* load PRD table addr. */ - outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); - - /* specify data direction, triple-check start bit is clear */ - dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - dmactl &= ~(ATA_DMA_WR | ATA_DMA_START); - if (!rw) - dmactl |= ATA_DMA_WR; - outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - - /* issue r/w command */ - ap->ops->exec_command(ap, &qc->tf); -} - -/** - * ata_bmdma_start_pio - Start a PCI IDE BMDMA transaction (PIO) - * @qc: Info associated with this ATA transaction. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -static void ata_bmdma_start_pio (struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - u8 dmactl; - - /* start host DMA transaction */ - dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - outb(dmactl | ATA_DMA_START, - ap->ioaddr.bmdma_addr + ATA_DMA_CMD); -} - - -/** - * ata_bmdma_start - Start a PCI IDE BMDMA transaction - * @qc: Info associated with this ATA transaction. - * - * Writes the ATA_DMA_START flag to the DMA command register. - * - * May be used as the bmdma_start() entry in ata_port_operations. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ -void ata_bmdma_start(struct ata_queued_cmd *qc) -{ - if (qc->ap->flags & ATA_FLAG_MMIO) - ata_bmdma_start_mmio(qc); - else - ata_bmdma_start_pio(qc); -} - - -/** - * ata_bmdma_setup - Set up PCI IDE BMDMA transaction - * @qc: Info associated with this ATA transaction. - * - * Writes address of PRD table to device's PRD Table Address - * register, sets the DMA control register, and calls - * ops->exec_command() to start the transfer. - * - * May be used as the bmdma_setup() entry in ata_port_operations. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ -void ata_bmdma_setup(struct ata_queued_cmd *qc) -{ - if (qc->ap->flags & ATA_FLAG_MMIO) - ata_bmdma_setup_mmio(qc); - else - ata_bmdma_setup_pio(qc); -} - - -/** - * ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt. - * @ap: Port associated with this ATA transaction. - * - * Clear interrupt and error flags in DMA status register. - * - * May be used as the irq_clear() entry in ata_port_operations. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -void ata_bmdma_irq_clear(struct ata_port *ap) -{ - if (!ap->ioaddr.bmdma_addr) - return; - - if (ap->flags & ATA_FLAG_MMIO) { - void __iomem *mmio = - ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; - writeb(readb(mmio), mmio); - } else { - unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; - outb(inb(addr), addr); - } -} - - -/** - * ata_bmdma_status - Read PCI IDE BMDMA status - * @ap: Port associated with this ATA transaction. - * - * Read and return BMDMA status register. - * - * May be used as the bmdma_status() entry in ata_port_operations. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -u8 ata_bmdma_status(struct ata_port *ap) -{ - u8 host_stat; - if (ap->flags & ATA_FLAG_MMIO) { - void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; - host_stat = readb(mmio + ATA_DMA_STATUS); - } else - host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - return host_stat; -} - - -/** - * ata_bmdma_stop - Stop PCI IDE BMDMA transfer - * @qc: Command we are ending DMA for - * - * Clears the ATA_DMA_START flag in the dma control register - * - * May be used as the bmdma_stop() entry in ata_port_operations. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -void ata_bmdma_stop(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - if (ap->flags & ATA_FLAG_MMIO) { - void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; - - /* clear start/stop bit */ - writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START, - mmio + ATA_DMA_CMD); - } else { - /* clear start/stop bit */ - outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, - ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - } - - /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ - ata_altstatus(ap); /* dummy read */ -} - /** * ata_host_intr - Handle host interrupt for given (port, task) * @ap: Port on which interrupt arrived (possibly...) -- cgit v1.2.3-59-g8ed1b From bf5295bba804a6aead9bc1c0d5970173a9d4e08e Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 23 Mar 2006 01:11:56 -0800 Subject: [BNX2]: Fix link change handling Fix some link-related problems by doing a coalesce_now after link change interrupt to flush out the transient link status. To facilitate this, the host coalesce cmd register value is cached in the device structure. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 29 +++++++++++++++++------------ drivers/net/bnx2.h | 1 + 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 7d213707008a..c56888e66351 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -313,8 +313,6 @@ bnx2_disable_int(struct bnx2 *bp) static void bnx2_enable_int(struct bnx2 *bp) { - u32 val; - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | BNX2_PCICFG_INT_ACK_CMD_MASK_INT | bp->last_status_idx); @@ -322,8 +320,7 @@ bnx2_enable_int(struct bnx2 *bp) REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx); - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW); + REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); } static void @@ -1926,6 +1923,13 @@ bnx2_poll(struct net_device *dev, int *budget) spin_lock(&bp->phy_lock); bnx2_phy_int(bp); spin_unlock(&bp->phy_lock); + + /* This is needed to take care of transient status + * during link changes. + */ + REG_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_RD(bp, BNX2_HC_COMMAND); } if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) @@ -3307,6 +3311,8 @@ bnx2_init_chip(struct bnx2 *bp) udelay(20); + bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND); + return rc; } @@ -3746,7 +3752,6 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) struct sk_buff *skb, *rx_skb; unsigned char *packet; u16 rx_start_idx, rx_idx; - u32 val; dma_addr_t map; struct tx_bd *txbd; struct sw_bd *rx_buf; @@ -3777,8 +3782,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) map = pci_map_single(bp->pdev, skb->data, pkt_size, PCI_DMA_TODEVICE); - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_RD(bp, BNX2_HC_COMMAND); udelay(5); @@ -3802,8 +3808,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) udelay(100); - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_RD(bp, BNX2_HC_COMMAND); udelay(5); @@ -3939,7 +3946,6 @@ static int bnx2_test_intr(struct bnx2 *bp) { int i; - u32 val; u16 status_idx; if (!netif_running(bp->dev)) @@ -3948,8 +3954,7 @@ bnx2_test_intr(struct bnx2 *bp) status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff; /* This register is not touched during run-time. */ - val = REG_RD(bp, BNX2_HC_COMMAND); - REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW); + REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); REG_RD(bp, BNX2_HC_COMMAND); for (i = 0; i < 10; i++) { diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index fd4b7f2eb477..18bc0919cc9e 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -4038,6 +4038,7 @@ struct bnx2 { struct statistics_block *stats_blk; dma_addr_t stats_blk_mapping; + u32 hc_cmd; u32 rx_mode; u16 req_line_speed; -- cgit v1.2.3-59-g8ed1b From 0f31f99446270e66c6f18c7d87aadd7db1dad214 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 23 Mar 2006 01:12:38 -0800 Subject: [BNX2]: Combine small mem allocations Combine two small (56 byte and 320 byte) pci consistent memory allocations into one allocation. Jeff Garzik suggested to store the combined size in the bp structure for later use when freeing the memory. Use kzalloc() instead of kmalloc() + memset(). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 34 +++++++++++++++------------------- drivers/net/bnx2.h | 2 ++ 2 files changed, 17 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index c56888e66351..8ce5ae84c832 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -359,15 +359,11 @@ bnx2_free_mem(struct bnx2 *bp) { int i; - if (bp->stats_blk) { - pci_free_consistent(bp->pdev, sizeof(struct statistics_block), - bp->stats_blk, bp->stats_blk_mapping); - bp->stats_blk = NULL; - } if (bp->status_blk) { - pci_free_consistent(bp->pdev, sizeof(struct status_block), + pci_free_consistent(bp->pdev, bp->status_stats_size, bp->status_blk, bp->status_blk_mapping); bp->status_blk = NULL; + bp->stats_blk = NULL; } if (bp->tx_desc_ring) { pci_free_consistent(bp->pdev, @@ -392,14 +388,13 @@ bnx2_free_mem(struct bnx2 *bp) static int bnx2_alloc_mem(struct bnx2 *bp) { - int i; + int i, status_blk_size; - bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT, - GFP_KERNEL); + bp->tx_buf_ring = kzalloc(sizeof(struct sw_bd) * TX_DESC_CNT, + GFP_KERNEL); if (bp->tx_buf_ring == NULL) return -ENOMEM; - memset(bp->tx_buf_ring, 0, sizeof(struct sw_bd) * TX_DESC_CNT); bp->tx_desc_ring = pci_alloc_consistent(bp->pdev, sizeof(struct tx_bd) * TX_DESC_CNT, @@ -425,21 +420,22 @@ bnx2_alloc_mem(struct bnx2 *bp) } - bp->status_blk = pci_alloc_consistent(bp->pdev, - sizeof(struct status_block), + /* Combine status and statistics blocks into one allocation. */ + status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block)); + bp->status_stats_size = status_blk_size + + sizeof(struct statistics_block); + + bp->status_blk = pci_alloc_consistent(bp->pdev, bp->status_stats_size, &bp->status_blk_mapping); if (bp->status_blk == NULL) goto alloc_mem_err; - memset(bp->status_blk, 0, sizeof(struct status_block)); + memset(bp->status_blk, 0, bp->status_stats_size); - bp->stats_blk = pci_alloc_consistent(bp->pdev, - sizeof(struct statistics_block), - &bp->stats_blk_mapping); - if (bp->stats_blk == NULL) - goto alloc_mem_err; + bp->stats_blk = (void *) ((unsigned long) bp->status_blk + + status_blk_size); - memset(bp->stats_blk, 0, sizeof(struct statistics_block)); + bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size; return 0; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 18bc0919cc9e..5d132b00e8fd 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -4083,6 +4083,8 @@ struct bnx2 { struct flash_spec *flash_info; u32 flash_size; + + int status_stats_size; }; static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset); -- cgit v1.2.3-59-g8ed1b From f2a4f05216e95f3b8c06b858abc0fe9a77500816 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 23 Mar 2006 01:13:12 -0800 Subject: [BNX2]: Move .h files to bnx2.c Move all #include <> from bnx2.h to bnx2.c. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/net/bnx2.h | 40 ---------------------------------------- 2 files changed, 40 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 8ce5ae84c832..3f2eaf52d197 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -9,6 +9,46 @@ * Written by: Michael Chan (mchan@broadcom.com) */ +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef NETIF_F_HW_VLAN_TX +#include +#define BCM_VLAN 1 +#endif +#ifdef NETIF_F_TSO +#include +#include +#include +#define BCM_TSO 1 +#endif +#include +#include +#include + #include "bnx2.h" #include "bnx2_fw.h" diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 5d132b00e8fd..60598849acd4 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -13,46 +13,6 @@ #ifndef BNX2_H #define BNX2_H -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef NETIF_F_HW_VLAN_TX -#include -#define BCM_VLAN 1 -#endif -#ifdef NETIF_F_TSO -#include -#include -#include -#define BCM_TSO 1 -#endif -#include -#include -#include - /* Hardware data structures and register definitions automatically * generated from RTL code. Do not modify. */ -- cgit v1.2.3-59-g8ed1b From 29b12174ac14f110225d6d9ebb66c30df5023baf Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 23 Mar 2006 01:13:43 -0800 Subject: [BNX2]: Separate tx producer and consumer fields Put the tx producer and consumer fields in separate cache lines in the device structure, similar to the VJ net channel queue structure. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 1 + drivers/net/bnx2.h | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 3f2eaf52d197..6ccacb5f2545 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "bnx2.h" #include "bnx2_fw.h" diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 60598849acd4..b87925f6a228 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -3877,15 +3877,17 @@ struct bnx2 { #define USING_MSI_FLAG 0x20 #define ASF_ENABLE_FLAG 0x40 - struct tx_bd *tx_desc_ring; - struct sw_bd *tx_buf_ring; - u32 tx_prod_bseq; - u16 tx_prod; - u16 tx_cons; - int tx_ring_size; - - u16 hw_tx_cons; - u16 hw_rx_cons; + /* Put tx producer and consumer fields in separate cache lines. */ + + u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES))); + u16 tx_prod; + + struct tx_bd *tx_desc_ring; + struct sw_bd *tx_buf_ring; + int tx_ring_size; + + u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES))); + u16 hw_tx_cons; #ifdef BCM_VLAN struct vlan_group *vlgrp; @@ -3899,6 +3901,7 @@ struct bnx2 { u32 rx_prod_bseq; u16 rx_prod; u16 rx_cons; + u16 hw_rx_cons; u32 rx_csum; -- cgit v1.2.3-59-g8ed1b From 5e2e71141ca93a3e2543966ced6a6077d4fb8fd8 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 23 Mar 2006 01:14:09 -0800 Subject: [BNX2]: Update version and reldate Update version to 1.4.39. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 6ccacb5f2545..2671da20a496 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -55,8 +55,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.38" -#define DRV_MODULE_RELDATE "February 10, 2006" +#define DRV_MODULE_VERSION "1.4.39" +#define DRV_MODULE_RELDATE "March 22, 2006" #define RUN_AT(x) (jiffies + (x)) -- cgit v1.2.3-59-g8ed1b From af36e6b6d7f4ad7a5ccfd14dfa71ec941255f93d Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 23 Mar 2006 01:28:06 -0800 Subject: [TG3]: Add 5755 support Add support for new chip 5755 which is very similar to 5787. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 37 +++++++++++++++++++++++++++++++------ drivers/net/tg3.h | 6 +++++- include/linux/pci_ids.h | 2 ++ 3 files changed, 38 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 88829eb9568e..c69c8df088d0 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -225,6 +225,10 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M, @@ -4557,6 +4561,7 @@ static int tg3_chip_reset(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tw32(GRC_FASTBOOT_PC, 0); @@ -6152,6 +6157,9 @@ static int tg3_reset_hw(struct tg3 *tp) gpio_mask |= GRC_LCLCTRL_GPIO_OE3 | GRC_LCLCTRL_GPIO_OUTPUT3; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL; + tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask; /* GPIO1 must be driven high for eeprom write protect */ @@ -6191,7 +6199,8 @@ static int tg3_reset_hw(struct tg3 *tp) } /* Enable host coalescing bug fix */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) val |= (1 << 29); tw32_f(WDMAC_MODE, val); @@ -6249,6 +6258,9 @@ static int tg3_reset_hw(struct tg3 *tp) udelay(100); tp->rx_mode = RX_MODE_ENABLE; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE; + tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); @@ -7907,7 +7919,8 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) return 0; } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) ethtool_op_set_tx_hw_csum(dev, data); else ethtool_op_set_tx_csum(dev, data); @@ -8332,7 +8345,8 @@ static int tg3_test_memory(struct tg3 *tp) int i; if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) mem_tbl = mem_tbl_5755; else mem_tbl = mem_tbl_5705; @@ -9310,6 +9324,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, nvram_cmd |= NVRAM_CMD_LAST; if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) && (tp->nvram_jedecnum == JEDEC_ST) && (nvram_cmd & NVRAM_CMD_FIRST)) { @@ -10044,6 +10059,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 || (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; @@ -10053,7 +10069,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_5705_PLUS; if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2; tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; } else @@ -10063,6 +10080,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; @@ -10219,6 +10237,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; + /* Force the chip into D0. */ err = tg3_set_power_state(tp, PCI_D0); if (err) { @@ -10274,6 +10295,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)) tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; @@ -10413,7 +10435,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* All chips before 5787 can get confused if TX buffers * straddle the 4GB address boundary in some cases. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tp->dev->hard_start_xmit = tg3_start_xmit; else tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug; @@ -11002,6 +11025,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5752: return "5752"; case PHY_ID_BCM5714: return "5714"; case PHY_ID_BCM5780: return "5780"; + case PHY_ID_BCM5755: return "5755"; case PHY_ID_BCM5787: return "5787"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; @@ -11350,7 +11374,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * checksumming. */ if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) dev->features |= NETIF_F_HW_CSUM; else dev->features |= NETIF_F_IP_CSUM; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index baa34c4721db..672f375ef711 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -138,6 +138,7 @@ #define ASIC_REV_5752 0x06 #define ASIC_REV_5780 0x08 #define ASIC_REV_5714 0x09 +#define ASIC_REV_5755 0x0a #define ASIC_REV_5787 0x0b #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 @@ -456,6 +457,7 @@ #define RX_MODE_PROMISC 0x00000100 #define RX_MODE_NO_CRC_CHECK 0x00000200 #define RX_MODE_KEEP_VLAN_TAG 0x00000400 +#define RX_MODE_IPV6_CSUM_ENABLE 0x01000000 #define MAC_RX_STATUS 0x0000046c #define RX_STATUS_REMOTE_TX_XOFFED 0x00000001 #define RX_STATUS_XOFF_RCVD 0x00000002 @@ -1340,6 +1342,7 @@ #define GRC_LCLCTRL_CLEARINT 0x00000002 #define GRC_LCLCTRL_SETINT 0x00000004 #define GRC_LCLCTRL_INT_ON_ATTN 0x00000008 +#define GRC_LCLCTRL_GPIO_UART_SEL 0x00000010 /* 5755 only */ #define GRC_LCLCTRL_USE_SIG_DETECT 0x00000010 /* 5714/5780 only */ #define GRC_LCLCTRL_USE_EXT_SIG_DETECT 0x00000020 /* 5714/5780 only */ #define GRC_LCLCTRL_GPIO_INPUT3 0x00000020 @@ -2259,6 +2262,7 @@ struct tg3 { #define PHY_ID_BCM5752 0x60008100 #define PHY_ID_BCM5714 0x60008340 #define PHY_ID_BCM5780 0x60008350 +#define PHY_ID_BCM5755 0xbc050cc0 #define PHY_ID_BCM5787 0xbc050ce0 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_INVALID 0xffffffff @@ -2286,7 +2290,7 @@ struct tg3 { (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \ (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \ - (X) == PHY_ID_BCM8002) + (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ec3c32932620..989a9d00dec1 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1864,11 +1864,13 @@ #define PCI_DEVICE_ID_TIGON3_5780S 0x166b #define PCI_DEVICE_ID_TIGON3_5705F 0x166e #define PCI_DEVICE_ID_TIGON3_5754M 0x1672 +#define PCI_DEVICE_ID_TIGON3_5755M 0x1673 #define PCI_DEVICE_ID_TIGON3_5750 0x1676 #define PCI_DEVICE_ID_TIGON3_5751 0x1677 #define PCI_DEVICE_ID_TIGON3_5715 0x1678 #define PCI_DEVICE_ID_TIGON3_5715S 0x1679 #define PCI_DEVICE_ID_TIGON3_5754 0x167a +#define PCI_DEVICE_ID_TIGON3_5755 0x167b #define PCI_DEVICE_ID_TIGON3_5750M 0x167c #define PCI_DEVICE_ID_TIGON3_5751M 0x167d #define PCI_DEVICE_ID_TIGON3_5751F 0x167e -- cgit v1.2.3-59-g8ed1b From d3c7b886978bef42f5ea487dec376c482d3cd7e3 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 23 Mar 2006 01:28:25 -0800 Subject: [TG3]: Add 5755 nvram support Add 5755 nvram support. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 43 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/tg3.h | 3 +++ 2 files changed, 46 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c69c8df088d0..b4c5bab2bb40 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8938,6 +8938,47 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) } } +static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) +{ + u32 nvcfg1; + + nvcfg1 = tr32(NVRAM_CFG1); + + /* NVRAM protection for TPM */ + if (nvcfg1 & (1 << 27)) + tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM; + + switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) { + case FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ: + case FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; + + nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; + tw32(NVRAM_CFG1, nvcfg1); + break; + case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED: + case FLASH_5755VENDOR_ATMEL_FLASH_1: + case FLASH_5755VENDOR_ATMEL_FLASH_2: + case FLASH_5755VENDOR_ATMEL_FLASH_3: + case FLASH_5755VENDOR_ATMEL_FLASH_4: + tp->nvram_jedecnum = JEDEC_ATMEL; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 264; + break; + case FLASH_5752VENDOR_ST_M45PE10: + case FLASH_5752VENDOR_ST_M45PE20: + case FLASH_5752VENDOR_ST_M45PE40: + tp->nvram_jedecnum = JEDEC_ST; + tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; + tp->tg3_flags2 |= TG3_FLG2_FLASH; + tp->nvram_pagesize = 256; + break; + } +} + static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -9011,6 +9052,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) tg3_get_5752_nvram_info(tp); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) + tg3_get_5755_nvram_info(tp); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tg3_get_5787_nvram_info(tp); else diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 672f375ef711..c43cc3264202 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1444,6 +1444,9 @@ #define FLASH_5755VENDOR_ATMEL_FLASH_1 0x03400001 #define FLASH_5755VENDOR_ATMEL_FLASH_2 0x03400002 #define FLASH_5755VENDOR_ATMEL_FLASH_3 0x03400000 +#define FLASH_5755VENDOR_ATMEL_FLASH_4 0x00000003 +#define FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ 0x03c00003 +#define FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ 0x03c00002 #define FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ 0x03000003 #define FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ 0x03000002 #define FLASH_5787VENDOR_MICRO_EEPROM_64KHZ 0x03000000 -- cgit v1.2.3-59-g8ed1b From 95381c893dd71a534ab56f09b12a4e2118aa0f32 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 23 Mar 2006 01:29:06 -0800 Subject: [TG3]: Update driver version and reldate. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b4c5bab2bb40..b5473325bff4 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.53" -#define DRV_MODULE_RELDATE "Mar 22, 2006" +#define DRV_MODULE_VERSION "3.54" +#define DRV_MODULE_RELDATE "Mar 23, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3-59-g8ed1b From 711e2c33ac9221a419a9e28d05dd78a6a9c5fd4d Mon Sep 17 00:00:00 2001 From: Jean Tourrilhes Date: Wed, 22 Feb 2006 15:10:56 -0800 Subject: [PATCH] WE-20 for kernel 2.6.16 This is version 20 of the Wireless Extensions. This is the completion of the RtNetlink work I started early 2004, it enables the full Wireless Extension API over RtNetlink. Few comments on the patch : o totally driver transparent, no change in drivers needed. o iwevent were already RtNetlink based since they were created (around 2.5.7). This adds all the regular SET and GET requests over RtNetlink, using the exact same mechanism and data format as iwevents. o This is a Kconfig option, as currently most people have no need for it. Surprisingly, patch is actually small and well encapsulated. o Tested on SMP, attention as been paid to make it 64 bits clean. o Code do probably too many checks and could be further optimised, but better safe than sorry. o RtNetlink based version of the Wireless Tools available on my web page for people inclined to try out this stuff. I would also like to thank Alexey Kuznetsov for his helpful suggestions to make this patch better. Signed-off-by: Jean Tourrilhes Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 9 + include/linux/wireless.h | 10 +- include/net/iw_handler.h | 12 +- net/core/rtnetlink.c | 98 ++++- net/core/wireless.c | 911 ++++++++++++++++++++++++++++++++++++++----- 5 files changed, 947 insertions(+), 93 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 5b0a19a5058d..6a1033ec06cf 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -25,6 +25,15 @@ config NET_RADIO the tools from . +config NET_WIRELESS_RTNETLINK + bool "Wireless Extension API over RtNetlink" + ---help--- + Support the Wireless Extension API over the RtNetlink socket + in addition to the traditional ioctl interface (selected above). + + For now, few tools use this facility, but it might grow in the + future. The only downside is that it adds 4.5 kB to your kernel. + # Note : the cards are obsolete (can't buy them anymore), but the drivers # are not, as people are still using them... comment "Obsolete Wireless cards support (pre-802.11)" diff --git a/include/linux/wireless.h b/include/linux/wireless.h index a555a0f7a7b4..13588564b42b 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -1,10 +1,10 @@ /* * This file define a set of standard wireless extensions * - * Version : 19 18.3.05 + * Version : 20 17.2.06 * * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H @@ -80,7 +80,7 @@ * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ -#define WIRELESS_EXT 19 +#define WIRELESS_EXT 20 /* * Changes : @@ -204,6 +204,10 @@ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros + * + * V19 to V20 + * ---------- + * - RtNetlink requests support (SET/GET) */ /**************************** CONSTANTS ****************************/ diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index a2c5e0b88422..10559e937d27 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h @@ -4,7 +4,7 @@ * Version : 7 18.3.05 * * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 2001-2005 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 2001-2006 Jean Tourrilhes, All Rights Reserved. */ #ifndef _IW_HANDLER_H @@ -436,6 +436,16 @@ extern int dev_get_wireless_info(char * buffer, char **start, off_t offset, /* Handle IOCTLs, called in net/core/dev.c */ extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd); +/* Handle RtNetlink requests, called in net/core/rtnetlink.c */ +extern int wireless_rtnetlink_set(struct net_device * dev, + char * data, + int len); +extern int wireless_rtnetlink_get(struct net_device * dev, + char * data, + int len, + char ** p_buf, + int * p_len); + /* Second : functions that may be called by driver modules */ /* Send a single event to user space */ diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index ae10d3740faa..3fcfa9c59e1f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -51,6 +51,10 @@ #include #include #include +#ifdef CONFIG_NET_WIRELESS_RTNETLINK +#include +#include +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ static DEFINE_MUTEX(rtnl_mutex); @@ -467,6 +471,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) goto out; } +#ifdef CONFIG_NET_WIRELESS_RTNETLINK + if (ida[IFLA_WIRELESS - 1]) { + + /* Call Wireless Extensions. + * Various stuff checked in there... */ + err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len); + if (err) + goto out; + } +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + err = 0; out: @@ -477,6 +492,83 @@ out: return err; } +#ifdef CONFIG_NET_WIRELESS_RTNETLINK +static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg) +{ + struct ifinfomsg *ifm = NLMSG_DATA(in_nlh); + struct rtattr **ida = arg; + struct net_device *dev; + struct ifinfomsg *r; + struct nlmsghdr *nlh; + int err = -ENOBUFS; + struct sk_buff *skb; + unsigned char *b; + char *iw_buf = NULL; + int iw_buf_len = 0; + + if (ifm->ifi_index >= 0) + dev = dev_get_by_index(ifm->ifi_index); + else + return -EINVAL; + if (!dev) + return -ENODEV; + +#ifdef CONFIG_NET_WIRELESS_RTNETLINK + if (ida[IFLA_WIRELESS - 1]) { + + /* Call Wireless Extensions. We need to know the size before + * we can alloc. Various stuff checked in there... */ + err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len); + if (err) + goto out; + } +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + + /* Create a skb big enough to include all the data. + * Some requests are way bigger than 4k... Jean II */ + skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)), + GFP_KERNEL); + if (!skb) + goto out; + b = skb->tail; + + /* Put in the message the usual good stuff */ + nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq, + RTM_NEWLINK, sizeof(*r)); + r = NLMSG_DATA(nlh); + r->ifi_family = AF_UNSPEC; + r->__ifi_pad = 0; + r->ifi_type = dev->type; + r->ifi_index = dev->ifindex; + r->ifi_flags = dev->flags; + r->ifi_change = 0; + + /* Put the wireless payload if it exist */ + if(iw_buf != NULL) + RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len, + iw_buf + IW_EV_POINT_OFF); + + nlh->nlmsg_len = skb->tail - b; + + /* Needed ? */ + NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; + + err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); + if (err > 0) + err = 0; +out: + if(iw_buf != NULL) + kfree(iw_buf); + dev_put(dev); + return err; + +rtattr_failure: +nlmsg_failure: + kfree_skb(skb); + goto out; +} +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb) { int idx; @@ -642,7 +734,11 @@ static void rtnetlink_rcv(struct sock *sk, int len) static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] = { - [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo }, + [RTM_GETLINK - RTM_BASE] = { +#ifdef CONFIG_NET_WIRELESS_RTNETLINK + .doit = do_getlink, +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + .dumpit = rtnetlink_dump_ifinfo }, [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink }, [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, diff --git a/net/core/wireless.c b/net/core/wireless.c index 2add7ed609e9..81d6995fcfdb 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c @@ -2,7 +2,7 @@ * This file implement the Wireless Extensions APIs. * * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved. * * (As all part of the Linux kernel, this file is GPL) */ @@ -65,6 +65,9 @@ * o Start deprecating dev->get_wireless_stats, output a warning * o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless * o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats) + * + * v8 - 17.02.06 - Jean II + * o RtNetlink requests support (SET/GET) */ /***************************** INCLUDES *****************************/ @@ -89,11 +92,13 @@ /* Debugging stuff */ #undef WE_IOCTL_DEBUG /* Debug IOCTL API */ +#undef WE_RTNETLINK_DEBUG /* Debug RtNetlink API */ #undef WE_EVENT_DEBUG /* Debug Event dispatcher */ #undef WE_SPY_DEBUG /* Debug enhanced spy support */ /* Options */ -#define WE_EVENT_NETLINK /* Propagate events using rtnetlink */ +//CONFIG_NET_WIRELESS_RTNETLINK /* Wireless requests over RtNetlink */ +#define WE_EVENT_RTNETLINK /* Propagate events using RtNetlink */ #define WE_SET_EVENT /* Generate an event on some set commands */ /************************* GLOBAL VARIABLES *************************/ @@ -156,13 +161,18 @@ static const struct iw_ioctl_description standard_ioctl[] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */ - .header_type = IW_HEADER_TYPE_NULL, + .header_type = IW_HEADER_TYPE_POINT, + .token_size = sizeof(struct iw_priv_args), + .max_tokens = 16, + .flags = IW_DESCR_FLAG_NOMAX, }, [SIOCSIWSTATS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */ - .header_type = IW_HEADER_TYPE_NULL, + .header_type = IW_HEADER_TYPE_POINT, + .token_size = 1, + .max_tokens = sizeof(struct iw_statistics), .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWSPY - SIOCIWFIRST] = { @@ -529,6 +539,70 @@ static inline int adjust_priv_size(__u16 args, return num * iw_priv_type_size[type]; } +/* ---------------------------------------------------------------- */ +/* + * Standard Wireless Handler : get wireless stats + * Allow programatic access to /proc/net/wireless even if /proc + * doesn't exist... Also more efficient... + */ +static int iw_handler_get_iwstats(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) +{ + /* Get stats from the driver */ + struct iw_statistics *stats; + + stats = get_wireless_stats(dev); + if (stats != (struct iw_statistics *) NULL) { + + /* Copy statistics to extra */ + memcpy(extra, stats, sizeof(struct iw_statistics)); + wrqu->data.length = sizeof(struct iw_statistics); + + /* Check if we need to clear the updated flag */ + if(wrqu->data.flags != 0) + stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; + return 0; + } else + return -EOPNOTSUPP; +} + +/* ---------------------------------------------------------------- */ +/* + * Standard Wireless Handler : get iwpriv definitions + * Export the driver private handler definition + * They will be picked up by tools like iwpriv... + */ +static int iw_handler_get_private(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) +{ + /* Check if the driver has something to export */ + if((dev->wireless_handlers->num_private_args == 0) || + (dev->wireless_handlers->private_args == NULL)) + return -EOPNOTSUPP; + + /* Check if there is enough buffer up there */ + if(wrqu->data.length < dev->wireless_handlers->num_private_args) { + /* User space can't know in advance how large the buffer + * needs to be. Give it a hint, so that we can support + * any size buffer we want somewhat efficiently... */ + wrqu->data.length = dev->wireless_handlers->num_private_args; + return -E2BIG; + } + + /* Set the number of available ioctls. */ + wrqu->data.length = dev->wireless_handlers->num_private_args; + + /* Copy structure to the user buffer. */ + memcpy(extra, dev->wireless_handlers->private_args, + sizeof(struct iw_priv_args) * wrqu->data.length); + + return 0; +} + /******************** /proc/net/wireless SUPPORT ********************/ /* @@ -628,83 +702,16 @@ int __init wireless_proc_init(void) * or just call the driver ioctl handler. */ -/* ---------------------------------------------------------------- */ -/* - * Allow programatic access to /proc/net/wireless even if /proc - * doesn't exist... Also more efficient... - */ -static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr) -{ - /* Get stats from the driver */ - struct iw_statistics *stats; - - stats = get_wireless_stats(dev); - if (stats != (struct iw_statistics *) NULL) { - struct iwreq * wrq = (struct iwreq *)ifr; - - /* Copy statistics to the user buffer */ - if(copy_to_user(wrq->u.data.pointer, stats, - sizeof(struct iw_statistics))) - return -EFAULT; - - /* Check if we need to clear the updated flag */ - if(wrq->u.data.flags != 0) - stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; - return 0; - } else - return -EOPNOTSUPP; -} - -/* ---------------------------------------------------------------- */ -/* - * Export the driver private handler definition - * They will be picked up by tools like iwpriv... - */ -static inline int ioctl_export_private(struct net_device * dev, - struct ifreq * ifr) -{ - struct iwreq * iwr = (struct iwreq *) ifr; - - /* Check if the driver has something to export */ - if((dev->wireless_handlers->num_private_args == 0) || - (dev->wireless_handlers->private_args == NULL)) - return -EOPNOTSUPP; - - /* Check NULL pointer */ - if(iwr->u.data.pointer == NULL) - return -EFAULT; - - /* Check if there is enough buffer up there */ - if(iwr->u.data.length < dev->wireless_handlers->num_private_args) { - /* User space can't know in advance how large the buffer - * needs to be. Give it a hint, so that we can support - * any size buffer we want somewhat efficiently... */ - iwr->u.data.length = dev->wireless_handlers->num_private_args; - return -E2BIG; - } - - /* Set the number of available ioctls. */ - iwr->u.data.length = dev->wireless_handlers->num_private_args; - - /* Copy structure to the user buffer. */ - if (copy_to_user(iwr->u.data.pointer, - dev->wireless_handlers->private_args, - sizeof(struct iw_priv_args) * iwr->u.data.length)) - return -EFAULT; - - return 0; -} - /* ---------------------------------------------------------------- */ /* * Wrapper to call a standard Wireless Extension handler. * We do various checks and also take care of moving data between * user space and kernel space. */ -static inline int ioctl_standard_call(struct net_device * dev, - struct ifreq * ifr, - unsigned int cmd, - iw_handler handler) +static int ioctl_standard_call(struct net_device * dev, + struct ifreq * ifr, + unsigned int cmd, + iw_handler handler) { struct iwreq * iwr = (struct iwreq *) ifr; const struct iw_ioctl_description * descr; @@ -1048,14 +1055,20 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd) { case SIOCGIWSTATS: /* Get Wireless Stats */ - return dev_iwstats(dev, ifr); + return ioctl_standard_call(dev, + ifr, + cmd, + &iw_handler_get_iwstats); case SIOCGIWPRIV: /* Check if we have some wireless handlers defined */ if(dev->wireless_handlers != NULL) { /* We export to user space the definition of * the private handler ourselves */ - return ioctl_export_private(dev, ifr); + return ioctl_standard_call(dev, + ifr, + cmd, + &iw_handler_get_private); } // ## Fall-through for old API ## default: @@ -1088,16 +1101,739 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd) return -EINVAL; } +/********************** RTNETLINK REQUEST API **********************/ +/* + * The alternate user space API to configure all those Wireless Extensions + * is through RtNetlink. + * This API support only the new driver API (iw_handler). + * + * This RtNetlink API use the same query/reply model as the ioctl API. + * Maximum effort has been done to fit in the RtNetlink model, and + * we support both RtNetlink Set and RtNelink Get operations. + * On the other hand, we don't offer Dump operations because of the + * following reasons : + * o Large number of parameters, most optional + * o Large size of some parameters (> 100 bytes) + * o Each parameters need to be extracted from hardware + * o Scan requests can take seconds and disable network activity. + * Because of this high cost/overhead, we want to return only the + * parameters the user application is really interested in. + * We could offer partial Dump using the IW_DESCR_FLAG_DUMP flag. + * + * The API uses the standard RtNetlink socket. When the RtNetlink code + * find a IFLA_WIRELESS field in a RtNetlink SET_LINK request, + * it calls here. + */ + +#ifdef CONFIG_NET_WIRELESS_RTNETLINK +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a standard Wireless Extension GET handler. + * We do various checks and call the handler with the proper args. + */ +static int rtnetlink_standard_get(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler, + char ** p_buf, + int * p_len) +{ + const struct iw_ioctl_description * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + int hdr_len; + struct iw_request_info info; + char * buffer = NULL; + int buffer_size = 0; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + if((cmd - SIOCIWFIRST) >= standard_ioctl_num) + return -EOPNOTSUPP; + descr = &(standard_ioctl[cmd - SIOCIWFIRST]); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found standard handler for 0x%04X\n", + dev->name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Check if wrqu is complete */ + hdr_len = event_type_size[descr->header_type]; + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have extra data in the reply or not */ + if(descr->header_type != IW_HEADER_TYPE_POINT) { + + /* Create the kernel buffer that we will return. + * It's at an offset to match the TYPE_POINT case... */ + buffer_size = request_len + IW_EV_POINT_OFF; + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + /* Copy event data */ + memcpy(buffer + IW_EV_POINT_OFF, request, request_len); + /* Use our own copy of wrqu */ + wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF + + IW_EV_LCP_LEN); + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, NULL); + + } else { + union iwreq_data wrqu_point; + char * extra = NULL; + int extra_size = 0; + + /* Get a temp copy of wrqu (skip pointer) */ + memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, + ((char *) request) + IW_EV_LCP_LEN, + IW_EV_POINT_LEN - IW_EV_LCP_LEN); + + /* Calculate space needed by arguments. Always allocate + * for max space. Easier, and won't last long... */ + extra_size = descr->max_tokens * descr->token_size; + /* Support for very large requests */ + if((descr->flags & IW_DESCR_FLAG_NOMAX) && + (wrqu_point.data.length > descr->max_tokens)) + extra_size = (wrqu_point.data.length + * descr->token_size); + buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", + dev->name, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Create the kernel buffer that we will return */ + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + + /* Put wrqu in the right place (just before extra). + * Leave space for IWE header and dummy pointer... + * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... + */ + memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, + ((char *) &wrqu_point) + IW_EV_POINT_OFF, + IW_EV_POINT_LEN - IW_EV_LCP_LEN); + wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); + + /* Extra comes logically after that. Offset +12 bytes. */ + extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; + + /* Call the handler */ + ret = handler(dev, &info, wrqu, extra); + + /* Calculate real returned length */ + extra_size = (wrqu->data.length * descr->token_size); + /* Re-adjust reply size */ + request->len = extra_size + IW_EV_POINT_LEN; + + /* Put the iwe header where it should, i.e. scrap the + * dummy pointer. */ + memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Check if there is enough buffer up there */ + if(wrqu_point.data.length < wrqu->data.length) + ret = -E2BIG; + } + + /* Return the buffer to the caller */ + if (!ret) { + *p_buf = buffer; + *p_len = request->len; + } else { + /* Cleanup */ + if(buffer) + kfree(buffer); + } + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a standard Wireless Extension SET handler. + * We do various checks and call the handler with the proper args. + */ +static inline int rtnetlink_standard_set(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler) +{ + const struct iw_ioctl_description * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + union iwreq_data wrqu_point; + int hdr_len; + char * extra = NULL; + int extra_size = 0; + struct iw_request_info info; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + if((cmd - SIOCIWFIRST) >= standard_ioctl_num) + return -EOPNOTSUPP; + descr = &(standard_ioctl[cmd - SIOCIWFIRST]); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found standard SET handler for 0x%04X\n", + dev->name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Extract fixed header from request. This is properly aligned. */ + wrqu = &request->u; + + /* Check if wrqu is complete */ + hdr_len = event_type_size[descr->header_type]; + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have extra data in the request or not */ + if(descr->header_type != IW_HEADER_TYPE_POINT) { + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, NULL); + + } else { + int extra_len; + + /* Put wrqu in the right place (skip pointer) */ + memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, + wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); + /* Don't forget about the event code... */ + wrqu = &wrqu_point; + + /* Check if number of token fits within bounds */ + if(wrqu_point.data.length > descr->max_tokens) + return -E2BIG; + if(wrqu_point.data.length < descr->min_tokens) + return -EINVAL; + + /* Real length of payload */ + extra_len = wrqu_point.data.length * descr->token_size; + + /* Check if request is self consistent */ + if((request_len - hdr_len) < extra_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Always allocate for max space. Easier, and won't last + * long... */ + extra_size = descr->max_tokens * descr->token_size; + extra = kmalloc(extra_size, GFP_KERNEL); + if (extra == NULL) + return -ENOMEM; + + /* Copy extra in aligned buffer */ + memcpy(extra, ((char *) request) + hdr_len, extra_len); + + /* Call the handler */ + ret = handler(dev, &info, &wrqu_point, extra); + } + +#ifdef WE_SET_EVENT + /* Generate an event to notify listeners of the change */ + if((descr->flags & IW_DESCR_FLAG_EVENT) && + ((ret == 0) || (ret == -EIWCOMMIT))) { + if(descr->flags & IW_DESCR_FLAG_RESTRICT) + /* If the event is restricted, don't + * export the payload */ + wireless_send_event(dev, cmd, wrqu, NULL); + else + wireless_send_event(dev, cmd, wrqu, extra); + } +#endif /* WE_SET_EVENT */ + + /* Cleanup - I told you it wasn't that long ;-) */ + if(extra) + kfree(extra); + + /* Call commit handler if needed and defined */ + if(ret == -EIWCOMMIT) + ret = call_commit_handler(dev); + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a private Wireless Extension GET handler. + * Same as above... + * It's not as nice and slimline as the standard wrapper. The cause + * is struct iw_priv_args, which was not really designed for the + * job we are going here. + * + * IMPORTANT : This function prevent to set and get data on the same + * IOCTL and enforce the SET/GET convention. Not doing it would be + * far too hairy... + * If you need to set and get data at the same time, please don't use + * a iw_handler but process it in your ioctl handler (i.e. use the + * old driver API). + */ +static inline int rtnetlink_private_get(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler, + char ** p_buf, + int * p_len) +{ + const struct iw_priv_args * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + int hdr_len; + struct iw_request_info info; + int extra_size = 0; + int i; + char * buffer = NULL; + int buffer_size = 0; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + for(i = 0; i < dev->wireless_handlers->num_private_args; i++) + if(cmd == dev->wireless_handlers->private_args[i].cmd) { + descr = &(dev->wireless_handlers->private_args[i]); + break; + } + if(descr == NULL) + return -EOPNOTSUPP; + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n", + dev->name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n", + dev->name, descr->name, descr->set_args, descr->get_args); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Compute the max size of the get arguments */ + extra_size = get_priv_size(descr->get_args); + + /* Does it fits in wrqu ? */ + if((descr->get_args & IW_PRIV_SIZE_FIXED) && + (extra_size <= IFNAMSIZ)) { + hdr_len = extra_size; + extra_size = 0; + } else { + hdr_len = IW_EV_POINT_LEN; + } + + /* Check if wrqu is complete */ + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have a pointer to user space data or not. */ + if(extra_size == 0) { + + /* Create the kernel buffer that we will return. + * It's at an offset to match the TYPE_POINT case... */ + buffer_size = request_len + IW_EV_POINT_OFF; + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + /* Copy event data */ + memcpy(buffer + IW_EV_POINT_OFF, request, request_len); + /* Use our own copy of wrqu */ + wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF + + IW_EV_LCP_LEN); + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, (char *) wrqu); + + } else { + char * extra; + + /* Buffer for full reply */ + buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", + dev->name, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Create the kernel buffer that we will return */ + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (buffer == NULL) { + return -ENOMEM; + } + + /* Put wrqu in the right place (just before extra). + * Leave space for IWE header and dummy pointer... + * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... + */ + memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, + ((char *) request) + IW_EV_LCP_LEN, + IW_EV_POINT_LEN - IW_EV_LCP_LEN); + wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); + + /* Extra comes logically after that. Offset +12 bytes. */ + extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; + + /* Call the handler */ + ret = handler(dev, &info, wrqu, extra); + + /* Adjust for the actual length if it's variable, + * avoid leaking kernel bits outside. */ + if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) + extra_size = adjust_priv_size(descr->get_args, wrqu); + /* Re-adjust reply size */ + request->len = extra_size + IW_EV_POINT_LEN; + + /* Put the iwe header where it should, i.e. scrap the + * dummy pointer. */ + memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); +#endif /* WE_RTNETLINK_DEBUG */ + } + + /* Return the buffer to the caller */ + if (!ret) { + *p_buf = buffer; + *p_len = request->len; + } else { + /* Cleanup */ + if(buffer) + kfree(buffer); + } + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Wrapper to call a private Wireless Extension SET handler. + * Same as above... + * It's not as nice and slimline as the standard wrapper. The cause + * is struct iw_priv_args, which was not really designed for the + * job we are going here. + * + * IMPORTANT : This function prevent to set and get data on the same + * IOCTL and enforce the SET/GET convention. Not doing it would be + * far too hairy... + * If you need to set and get data at the same time, please don't use + * a iw_handler but process it in your ioctl handler (i.e. use the + * old driver API). + */ +static inline int rtnetlink_private_set(struct net_device * dev, + struct iw_event * request, + int request_len, + iw_handler handler) +{ + const struct iw_priv_args * descr = NULL; + unsigned int cmd; + union iwreq_data * wrqu; + union iwreq_data wrqu_point; + int hdr_len; + char * extra = NULL; + int extra_size = 0; + int offset = 0; /* For sub-ioctls */ + struct iw_request_info info; + int i; + int ret = -EINVAL; + + /* Get the description of the Request */ + cmd = request->cmd; + for(i = 0; i < dev->wireless_handlers->num_private_args; i++) + if(cmd == dev->wireless_handlers->private_args[i].cmd) { + descr = &(dev->wireless_handlers->private_args[i]); + break; + } + if(descr == NULL) + return -EOPNOTSUPP; + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n", + ifr->ifr_name, cmd); + printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n", + dev->name, descr->name, descr->set_args, descr->get_args); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Compute the size of the set arguments */ + /* Check for sub-ioctl handler */ + if(descr->name[0] == '\0') + /* Reserve one int for sub-ioctl index */ + offset = sizeof(__u32); + + /* Size of set arguments */ + extra_size = get_priv_size(descr->set_args); + + /* Does it fits in wrqu ? */ + if((descr->set_args & IW_PRIV_SIZE_FIXED) && + (extra_size <= IFNAMSIZ)) { + hdr_len = IW_EV_LCP_LEN + extra_size; + extra_size = 0; + } else { + hdr_len = IW_EV_POINT_LEN; + } + + /* Extract fixed header from request. This is properly aligned. */ + wrqu = &request->u; + + /* Check if wrqu is complete */ + if(request_len < hdr_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG + "%s (WE.r) : Wireless request too short (%d)\n", + dev->name, request_len); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + + /* Check if we have a pointer to user space data or not. */ + if(extra_size == 0) { + + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, wrqu, (char *) wrqu); + + } else { + int extra_len; + + /* Put wrqu in the right place (skip pointer) */ + memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, + wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); + + /* Does it fits within bounds ? */ + if(wrqu_point.data.length > (descr->set_args & + IW_PRIV_SIZE_MASK)) + return -E2BIG; + + /* Real length of payload */ + extra_len = adjust_priv_size(descr->set_args, &wrqu_point); + + /* Check if request is self consistent */ + if((request_len - hdr_len) < extra_len) { +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + return -EINVAL; + } + +#ifdef WE_RTNETLINK_DEBUG + printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n", + dev->name, extra_size); +#endif /* WE_RTNETLINK_DEBUG */ + + /* Always allocate for max space. Easier, and won't last + * long... */ + extra = kmalloc(extra_size, GFP_KERNEL); + if (extra == NULL) + return -ENOMEM; + + /* Copy extra in aligned buffer */ + memcpy(extra, ((char *) request) + hdr_len, extra_len); + + /* Call the handler */ + ret = handler(dev, &info, &wrqu_point, extra); + + /* Cleanup - I told you it wasn't that long ;-) */ + kfree(extra); + } + + /* Call commit handler if needed and defined */ + if(ret == -EIWCOMMIT) + ret = call_commit_handler(dev); + + return ret; +} + +/* ---------------------------------------------------------------- */ +/* + * Main RtNetlink dispatcher. Called from the main networking code + * (do_getlink() in net/core/rtnetlink.c). + * Check the type of Request and call the appropriate wrapper... + */ +int wireless_rtnetlink_get(struct net_device * dev, + char * data, + int len, + char ** p_buf, + int * p_len) +{ + struct iw_event * request = (struct iw_event *) data; + iw_handler handler; + + /* Check length */ + if(len < IW_EV_LCP_LEN) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", + dev->name, len); + return -EINVAL; + } + + /* ReCheck length (len may have padding) */ + if(request->len > len) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n", + dev->name, request->len, len); + return -EINVAL; + } + + /* Only accept GET requests in here */ + if(!IW_IS_GET(request->cmd)) + return -EOPNOTSUPP; + + /* Special cases */ + if(request->cmd == SIOCGIWSTATS) + /* Get Wireless Stats */ + return rtnetlink_standard_get(dev, + request, + request->len, + &iw_handler_get_iwstats, + p_buf, p_len); + if(request->cmd == SIOCGIWPRIV) { + /* Check if we have some wireless handlers defined */ + if(dev->wireless_handlers == NULL) + return -EOPNOTSUPP; + /* Get Wireless Stats */ + return rtnetlink_standard_get(dev, + request, + request->len, + &iw_handler_get_private, + p_buf, p_len); + } + + /* Basic check */ + if (!netif_device_present(dev)) + return -ENODEV; + + /* Try to find the handler */ + handler = get_handler(dev, request->cmd); + if(handler != NULL) { + /* Standard and private are not the same */ + if(request->cmd < SIOCIWFIRSTPRIV) + return rtnetlink_standard_get(dev, + request, + request->len, + handler, + p_buf, p_len); + else + return rtnetlink_private_get(dev, + request, + request->len, + handler, + p_buf, p_len); + } + + return -EOPNOTSUPP; +} + +/* ---------------------------------------------------------------- */ +/* + * Main RtNetlink dispatcher. Called from the main networking code + * (do_setlink() in net/core/rtnetlink.c). + * Check the type of Request and call the appropriate wrapper... + */ +int wireless_rtnetlink_set(struct net_device * dev, + char * data, + int len) +{ + struct iw_event * request = (struct iw_event *) data; + iw_handler handler; + + /* Check length */ + if(len < IW_EV_LCP_LEN) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", + dev->name, len); + return -EINVAL; + } + + /* ReCheck length (len may have padding) */ + if(request->len > len) { + printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n", + dev->name, request->len, len); + return -EINVAL; + } + + /* Only accept SET requests in here */ + if(!IW_IS_SET(request->cmd)) + return -EOPNOTSUPP; + + /* Basic check */ + if (!netif_device_present(dev)) + return -ENODEV; + + /* New driver API : try to find the handler */ + handler = get_handler(dev, request->cmd); + if(handler != NULL) { + /* Standard and private are not the same */ + if(request->cmd < SIOCIWFIRSTPRIV) + return rtnetlink_standard_set(dev, + request, + request->len, + handler); + else + return rtnetlink_private_set(dev, + request, + request->len, + handler); + } + + return -EOPNOTSUPP; +} +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + + /************************* EVENT PROCESSING *************************/ /* * Process events generated by the wireless layer or the driver. * Most often, the event will be propagated through rtnetlink */ -#ifdef WE_EVENT_NETLINK -/* "rtnl" is defined in net/core/rtnetlink.c, but we need it here. - * It is declared in */ - +#ifdef WE_EVENT_RTNETLINK /* ---------------------------------------------------------------- */ /* * Fill a rtnetlink message with our event data. @@ -1121,12 +1857,11 @@ static inline int rtnetlink_fill_iwinfo(struct sk_buff * skb, r->__ifi_pad = 0; r->ifi_type = dev->type; r->ifi_index = dev->ifindex; - r->ifi_flags = dev->flags; + r->ifi_flags = dev_get_flags(dev); r->ifi_change = 0; /* Wireless changes don't affect those flags */ /* Add the wireless events in the netlink packet */ - RTA_PUT(skb, IFLA_WIRELESS, - event_len, event); + RTA_PUT(skb, IFLA_WIRELESS, event_len, event); nlh->nlmsg_len = skb->tail - b; return skb->len; @@ -1163,7 +1898,7 @@ static inline void rtmsg_iwinfo(struct net_device * dev, NETLINK_CB(skb).dst_group = RTNLGRP_LINK; netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); } -#endif /* WE_EVENT_NETLINK */ +#endif /* WE_EVENT_RTNETLINK */ /* ---------------------------------------------------------------- */ /* @@ -1255,10 +1990,10 @@ void wireless_send_event(struct net_device * dev, if(extra != NULL) memcpy(((char *) event) + hdr_len, extra, extra_len); -#ifdef WE_EVENT_NETLINK - /* rtnetlink event channel */ +#ifdef WE_EVENT_RTNETLINK + /* Send via the RtNetlink event channel */ rtmsg_iwinfo(dev, (char *) event, event_len); -#endif /* WE_EVENT_NETLINK */ +#endif /* WE_EVENT_RTNETLINK */ /* Cleanup */ kfree(event); -- cgit v1.2.3-59-g8ed1b From 6254312352dfd1c996245cb3bc74be901dc165cc Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 22 Mar 2006 03:48:33 -0300 Subject: V4L/DVB (3568a): saa7114: Fix i2c block write Fix the i2c block write mode of the saa7114 driver. A previous code change accidentally commented out a local variable increment, which should have been kept, causing the register writes over the I2C bus to never be batched, replacing any attempted block write by slower, individual write transactions. Also drop the commented out code, as it only adds to confusion. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7114.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index fd0a4b4ef014..1c29d05307a5 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c @@ -139,9 +139,6 @@ saa7114_write (struct i2c_client *client, u8 reg, u8 value) { - /*struct saa7114 *decoder = i2c_get_clientdata(client);*/ - - /*decoder->reg[reg] = value;*/ return i2c_smbus_write_byte_data(client, reg, value); } @@ -157,7 +154,6 @@ saa7114_write_block (struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - /*struct saa7114 *decoder = i2c_get_clientdata(client);*/ struct i2c_msg msg; u8 block_data[32]; @@ -168,8 +164,8 @@ saa7114_write_block (struct i2c_client *client, msg.len = 0; block_data[msg.len++] = reg = data[0]; do { - block_data[msg.len++] = - /*decoder->reg[reg++] =*/ data[1]; + block_data[msg.len++] = data[1]; + reg++; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && -- cgit v1.2.3-59-g8ed1b From 6eb5d9ca9f1496108cb86f2d9bfc2db5d9c796fe Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 22 Mar 2006 03:48:32 -0300 Subject: V4L/DVB (3568b): saa7111: Prevent array overrun Explicitely state the number of registers the SAA7111 has, and use that defined value where relevant. This should prevent any future array overrun like the one I just fixed in the saa7110 driver. This patch also saves 8 bytes of memory as a side effect, as the register cache was larger than needed. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7111.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index 8c06592b37ff..a2e1ccb79e49 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -70,8 +70,10 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ +#define SAA7111_NR_REG 0x18 + struct saa7111 { - unsigned char reg[32]; + unsigned char reg[SAA7111_NR_REG]; int norm; int input; @@ -227,11 +229,11 @@ saa7111_command (struct i2c_client *client, { int i; - for (i = 0; i < 32; i += 16) { + for (i = 0; i < SAA7111_NR_REG; i += 16) { int j; printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); - for (j = 0; j < 16; ++j) { + for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) { printk(" %02x", saa7111_read(client, i + j)); } -- cgit v1.2.3-59-g8ed1b From daf72f408c66aee4ac939f614293a78841aa7717 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 22 Mar 2006 03:48:37 -0300 Subject: V4L/DVB (3568c): zoran: Init cleanups Cleanups to the zr36057 initialization: * Drop intermediate local variables. * Single error path. Also drop a needless cast on kfree. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran_card.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index 246e67cd8b51..a2e528ccf28a 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c @@ -995,10 +995,7 @@ test_interrupts (struct zoran *zr) static int __devinit zr36057_init (struct zoran *zr) { - u32 *mem; - void *vdev; - unsigned mem_needed; - int j; + int j, err; int two = 2; int zero = 0; @@ -1049,19 +1046,16 @@ zr36057_init (struct zoran *zr) /* allocate memory *before* doing anything to the hardware * in case allocation fails */ - mem_needed = BUZ_NUM_STAT_COM * 4; - mem = kzalloc(mem_needed, GFP_KERNEL); - vdev = (void *) kmalloc(sizeof(struct video_device), GFP_KERNEL); - if (!mem || !vdev) { + zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL); + zr->video_dev = kmalloc(sizeof(struct video_device), GFP_KERNEL); + if (!zr->stat_com || !zr->video_dev) { dprintk(1, KERN_ERR "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", ZR_DEVNAME(zr)); - kfree(vdev); - kfree(mem); - return -ENOMEM; + err = -ENOMEM; + goto exit_free; } - zr->stat_com = mem; for (j = 0; j < BUZ_NUM_STAT_COM; j++) { zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */ } @@ -1069,16 +1063,11 @@ zr36057_init (struct zoran *zr) /* * Now add the template and register the device unit. */ - zr->video_dev = vdev; memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); - if (video_register_device(zr->video_dev, VFL_TYPE_GRABBER, - video_nr) < 0) { - zoran_unregister_i2c(zr); - kfree((void *) zr->stat_com); - kfree(vdev); - return -1; - } + err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr); + if (err < 0) + goto exit_unregister; zoran_init_hardware(zr); if (*zr_debug > 2) @@ -1092,6 +1081,13 @@ zr36057_init (struct zoran *zr) zr->zoran_proc = NULL; zr->initialized = 1; return 0; + +exit_unregister: + zoran_unregister_i2c(zr); +exit_free: + kfree(zr->stat_com); + kfree(zr->video_dev); + return err; } static void @@ -1121,7 +1117,7 @@ zoran_release (struct zoran *zr) btwrite(0, ZR36057_SPGPPCR); free_irq(zr->pci_dev->irq, zr); /* unmap and free memory */ - kfree((void *) zr->stat_com); + kfree(zr->stat_com); zoran_proc_cleanup(zr); iounmap(zr->zr36057_mem); pci_disable_device(zr->pci_dev); -- cgit v1.2.3-59-g8ed1b From 58a0b84c92e62c2cc42036259a4b51e0bcaf8fa5 Mon Sep 17 00:00:00 2001 From: Martin Samuelsson Date: Wed, 22 Mar 2006 03:48:38 -0300 Subject: V4L/DVB (3568d): saa7111.c fix When grabbing composite video with Iomega Buz, the stock driver will prevent grabbing from the same input twice in a row, forcing the user to switch inputs before anything useful can be grabbed again. It is caused by some optimization code in the input selection parts, and triggered by the saa7111_command() executing cmd 0. The attached patch will remedy this by disabling cmd 0 altogether; a fix that has no found negative effects on the rest of the code. In fact, saa7110.c does the exact same thing. Acked-by: Ronald S. Bultje Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7111.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index a2e1ccb79e49..6bd1789c8f78 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -212,6 +212,7 @@ saa7111_command (struct i2c_client *client, switch (cmd) { case 0: + break; case DECODER_INIT: { struct video_decoder_init *init = arg; -- cgit v1.2.3-59-g8ed1b From f49a5eaea6d7b3ed3d01ca9388eac9e7e5bf6025 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 22 Mar 2006 03:48:36 -0300 Subject: V4L/DVB (3568e): bt856: Spare memory The bt856 driver has a register cache much larger than needed. We really only write to 3 registers, so a 32-byte cache is a bit too much. We can be just as efficient with a 6-byte cache. We could even do with a 3-byte cache, but at the cost of additional arithmetics arguably not worth the spared 3 bytes. Also, 4 of the 6 other members of the bt856 data structure were not used anywhere, so we can as well drop them for an additional 16 bytes of memory spared. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt856.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 909b593530ed..7c68937853b0 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -71,17 +71,14 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ -#define REG_OFFSET 0xCE +#define REG_OFFSET 0xDA +#define BT856_NR_REG 6 struct bt856 { - unsigned char reg[32]; + unsigned char reg[BT856_NR_REG]; int norm; int enable; - int bright; - int contrast; - int hue; - int sat; }; #define I2C_BT856 0x88 @@ -120,8 +117,8 @@ bt856_dump (struct i2c_client *client) struct bt856 *encoder = i2c_get_clientdata(client); printk(KERN_INFO "%s: register dump:", I2C_NAME(client)); - for (i = 0xd6; i <= 0xde; i += 2) - printk(" %02x", encoder->reg[i - REG_OFFSET]); + for (i = 0; i < BT856_NR_REG; i += 2) + printk(" %02x", encoder->reg[i]); printk("\n"); } -- cgit v1.2.3-59-g8ed1b From 6201573cc9bfe1e0bdec229bed8e95b0dc88a587 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 22 Mar 2006 03:48:30 -0300 Subject: V4L/DVB (3568f): saa7110: Fix array overrun Fix a (probably harmless) array overrun in the DECODER_DUMP command of the saa7110 driver. No big deal as this command is not used anywhere anyway. Also reformat the dump so that it displays nicely. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7110.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 7bb85a7b326e..20cad9fc99ef 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -432,15 +432,13 @@ saa7110_command (struct i2c_client *client, break; case DECODER_DUMP: - for (v = 0; v < 0x34; v += 16) { + for (v = 0; v < SAA7110_NR_REG; v += 16) { int j; - dprintk(1, KERN_INFO "%s: %03x\n", I2C_NAME(client), + dprintk(1, KERN_DEBUG "%s: %02x:", I2C_NAME(client), v); - for (j = 0; j < 16; j++) { - dprintk(1, KERN_INFO " %02x", - decoder->reg[v + j]); - } - dprintk(1, KERN_INFO "\n"); + for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++) + dprintk(1, " %02x", decoder->reg[v + j]); + dprintk(1, "\n"); } break; -- cgit v1.2.3-59-g8ed1b From 384c36893f94e0e2145832cf2f20684ae372aee5 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 22 Mar 2006 03:54:16 -0300 Subject: V4L/DVB (3568g): sem2mutex: zoran Semaphore to mutexes 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: Mauro Carvalho Chehab --- drivers/media/video/zoran.h | 2 +- drivers/media/video/zoran_card.c | 11 +- drivers/media/video/zoran_driver.c | 227 +++++++++++++++++++------------------ 3 files changed, 121 insertions(+), 119 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index 9fe6ad3b6352..ad04a129499d 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran.h @@ -395,7 +395,7 @@ struct zoran { struct videocodec *codec; /* video codec */ struct videocodec *vfe; /* video front end */ - struct semaphore resource_lock; /* prevent evil stuff */ + struct mutex resource_lock; /* prevent evil stuff */ u8 initialized; /* flag if zoran has been correctly initalized */ int user; /* number of current users */ diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index a2e528ccf28a..b22dbb6d18f6 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c @@ -47,6 +47,7 @@ #include #include #include +#include #include @@ -673,7 +674,7 @@ zoran_i2c_client_register (struct i2c_client *client) KERN_DEBUG "%s: i2c_client_register() - driver id = %d\n", ZR_DEVNAME(zr), client->driver->id); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (zr->user > 0) { /* we're already busy, so we keep a reference to @@ -694,7 +695,7 @@ zoran_i2c_client_register (struct i2c_client *client) } clientreg_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -707,7 +708,7 @@ zoran_i2c_client_unregister (struct i2c_client *client) dprintk(2, KERN_DEBUG "%s: i2c_client_unregister()\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (zr->user > 0) { res = -EBUSY; @@ -722,7 +723,7 @@ zoran_i2c_client_unregister (struct i2c_client *client) snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%d]", zr->id); } clientunreg_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -1202,7 +1203,7 @@ find_zr36057 (void) zr->id = zoran_num; snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id); spin_lock_init(&zr->spinlock); - init_MUTEX(&zr->resource_lock); + mutex_init(&zr->resource_lock); if (pci_enable_device(dev)) continue; zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0); diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 485553be190b..b2c6e01e3923 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -81,6 +81,7 @@ #include #include +#include #include "zoran.h" #include "zoran_device.h" #include "zoran_card.h" @@ -1292,7 +1293,7 @@ zoran_open (struct inode *inode, /* see fs/device.c - the kernel already locks during open(), * so locking ourselves only causes deadlocks */ - /*down(&zr->resource_lock);*/ + /*mutex_lock(&zr->resource_lock);*/ if (!zr->decoder) { dprintk(1, @@ -1371,7 +1372,7 @@ zoran_open (struct inode *inode, if (zr->user++ == 0) first_open = 1; - /*up(&zr->resource_lock);*/ + /*mutex_unlock(&zr->resource_lock);*/ /* default setup - TODO: look at flags */ if (first_open) { /* First device open */ @@ -1401,7 +1402,7 @@ open_unlock_and_return: /* if there's no device found, we didn't obtain the lock either */ if (zr) { - /*up(&zr->resource_lock);*/ + /*mutex_unlock(&zr->resource_lock);*/ } return res; @@ -1419,7 +1420,7 @@ zoran_close (struct inode *inode, /* kernel locks (fs/device.c), so don't do that ourselves * (prevents deadlocks) */ - /*down(&zr->resource_lock);*/ + /*mutex_lock(&zr->resource_lock);*/ zoran_close_end_session(file); @@ -1466,7 +1467,7 @@ zoran_close (struct inode *inode, } module_put(THIS_MODULE); - /*up(&zr->resource_lock);*/ + /*mutex_unlock(&zr->resource_lock);*/ dprintk(4, KERN_INFO "%s: zoran_close() done\n", ZR_DEVNAME(zr)); @@ -2027,14 +2028,14 @@ zoran_do_ioctl (struct inode *inode, * but moving the free code outside the munmap() handler fixes * all this... If someone knows why, please explain me (Ronald) */ - if (!down_trylock(&zr->resource_lock)) { + if (!!mutex_trylock(&zr->resource_lock)) { /* we obtained it! Let's try to free some things */ if (fh->jpg_buffers.ready_to_be_freed) jpg_fbuffer_free(file); if (fh->v4l_buffers.ready_to_be_freed) v4l_fbuffer_free(file); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); } switch (cmd) { @@ -2051,12 +2052,12 @@ zoran_do_ioctl (struct inode *inode, vcap->channels = zr->card.inputs; vcap->audios = 0; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); vcap->maxwidth = BUZ_MAX_WIDTH; vcap->maxheight = BUZ_MAX_HEIGHT; vcap->minwidth = BUZ_MIN_WIDTH; vcap->minheight = BUZ_MIN_HEIGHT; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -2084,9 +2085,9 @@ zoran_do_ioctl (struct inode *inode, vchan->tuners = 0; vchan->flags = 0; vchan->type = VIDEO_TYPE_CAMERA; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); vchan->norm = zr->norm; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); vchan->channel = channel; return 0; @@ -2113,7 +2114,7 @@ zoran_do_ioctl (struct inode *inode, "%s: VIDIOCSCHAN - channel=%d, norm=%d\n", ZR_DEVNAME(zr), vchan->channel, vchan->norm); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if ((res = zoran_set_input(zr, vchan->channel))) goto schan_unlock_and_return; if ((res = zoran_set_norm(zr, vchan->norm))) @@ -2122,7 +2123,7 @@ zoran_do_ioctl (struct inode *inode, /* Make sure the changes come into effect */ res = wait_grab_pending(zr); schan_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -2134,7 +2135,7 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOCGPICT\n", ZR_DEVNAME(zr)); memset(vpict, 0, sizeof(struct video_picture)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); vpict->hue = zr->hue; vpict->brightness = zr->brightness; vpict->contrast = zr->contrast; @@ -2145,7 +2146,7 @@ zoran_do_ioctl (struct inode *inode, } else { vpict->depth = 0; } - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -2180,7 +2181,7 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); decoder_command(zr, DECODER_SET_PICTURE, vpict); @@ -2191,7 +2192,7 @@ zoran_do_ioctl (struct inode *inode, fh->overlay_settings.format = &zoran_formats[i]; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -2204,9 +2205,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOCCAPTURE - on=%d\n", ZR_DEVNAME(zr), *on); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_overlay(file, *on); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2219,12 +2220,12 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOCGWIN\n", ZR_DEVNAME(zr)); memset(vwin, 0, sizeof(struct video_window)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); vwin->x = fh->overlay_settings.x; vwin->y = fh->overlay_settings.y; vwin->width = fh->overlay_settings.width; vwin->height = fh->overlay_settings.height; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); vwin->clipcount = 0; return 0; } @@ -2241,12 +2242,12 @@ zoran_do_ioctl (struct inode *inode, ZR_DEVNAME(zr), vwin->x, vwin->y, vwin->width, vwin->height, vwin->clipcount); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_window(file, vwin->x, vwin->y, vwin->width, vwin->height, vwin->clips, vwin->clipcount, NULL); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2258,9 +2259,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOCGFBUF\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); *vbuf = zr->buffer; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } break; @@ -2287,12 +2288,12 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_fbuffer(file, vbuf->base, &zoran_formats[i], vbuf->width, vbuf->height, vbuf->bytesperline); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2305,9 +2306,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOCSYNC - frame=%d\n", ZR_DEVNAME(zr), *frame); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = v4l_sync(file, *frame); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); if (!res) zr->v4l_sync_tail++; return res; @@ -2325,9 +2326,9 @@ zoran_do_ioctl (struct inode *inode, ZR_DEVNAME(zr), vmap->frame, vmap->width, vmap->height, vmap->format); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = v4l_grab(file, vmap); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -2348,7 +2349,7 @@ zoran_do_ioctl (struct inode *inode, i * fh->v4l_buffers.buffer_size; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { dprintk(1, @@ -2367,7 +2368,7 @@ zoran_do_ioctl (struct inode *inode, /* The next mmap will map the V4L buffers */ fh->map_mode = ZORAN_MAP_MODE_RAW; v4l1reqbuf_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2421,7 +2422,7 @@ zoran_do_ioctl (struct inode *inode, bparams->major_version = MAJOR_VERSION; bparams->minor_version = MINOR_VERSION; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); bparams->norm = zr->norm; bparams->input = zr->input; @@ -2450,7 +2451,7 @@ zoran_do_ioctl (struct inode *inode, bparams->jpeg_markers = fh->jpg_settings.jpg_comp.jpeg_markers; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); bparams->VFIFO_FB = 0; @@ -2486,7 +2487,7 @@ zoran_do_ioctl (struct inode *inode, sizeof(bparams->COM_data)); settings.jpg_comp.jpeg_markers = bparams->jpeg_markers; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (zr->codec_mode != BUZ_MODE_IDLE) { dprintk(1, @@ -2506,7 +2507,7 @@ zoran_do_ioctl (struct inode *inode, fh->jpg_settings = settings; sparams_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2538,7 +2539,7 @@ zoran_do_ioctl (struct inode *inode, breq->size > MAX_KMALLOC_MEM) breq->size = MAX_KMALLOC_MEM; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { dprintk(1, @@ -2561,7 +2562,7 @@ zoran_do_ioctl (struct inode *inode, * also be *_PLAY, but it doesn't matter here */ fh->map_mode = ZORAN_MAP_MODE_JPG_REC; jpgreqbuf_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2574,9 +2575,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_CAPT - frame=%d\n", ZR_DEVNAME(zr), *frame); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_COMPRESS); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2589,9 +2590,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_PLAY - frame=%d\n", ZR_DEVNAME(zr), *frame); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_DECOMPRESS); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2604,9 +2605,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: BUZIOC_SYNC\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = jpg_sync(file, bsync); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -2630,7 +2631,7 @@ zoran_do_ioctl (struct inode *inode, input = zr->card.input[bstat->input].muxsel; norm = VIDEO_MODE_AUTO; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (zr->codec_mode != BUZ_MODE_IDLE) { dprintk(1, @@ -2655,7 +2656,7 @@ zoran_do_ioctl (struct inode *inode, decoder_command(zr, DECODER_SET_INPUT, &input); decoder_command(zr, DECODER_SET_NORM, &zr->norm); gstat_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); if (!res) { bstat->signal = @@ -2763,7 +2764,7 @@ zoran_do_ioctl (struct inode *inode, switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_OVERLAY: - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); fmt->fmt.win.w.left = fh->overlay_settings.x; fmt->fmt.win.w.top = fh->overlay_settings.y; @@ -2776,14 +2777,14 @@ zoran_do_ioctl (struct inode *inode, else fmt->fmt.win.field = V4L2_FIELD_TOP; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); break; case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && fh->map_mode == ZORAN_MAP_MODE_RAW) { @@ -2837,7 +2838,7 @@ zoran_do_ioctl (struct inode *inode, V4L2_COLORSPACE_SMPTE170M; } - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); break; @@ -2870,7 +2871,7 @@ zoran_do_ioctl (struct inode *inode, fmt->fmt.win.w.height, fmt->fmt.win.clipcount, fmt->fmt.win.bitmap); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_window(file, fmt->fmt.win.w.left, fmt->fmt.win.w.top, @@ -2880,7 +2881,7 @@ zoran_do_ioctl (struct inode *inode, fmt->fmt.win.clips, fmt->fmt.win.clipcount, fmt->fmt.win.bitmap); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; break; @@ -2917,7 +2918,7 @@ zoran_do_ioctl (struct inode *inode, } if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) { - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); settings = fh->jpg_settings; @@ -2995,7 +2996,7 @@ zoran_do_ioctl (struct inode *inode, ZORAN_MAP_MODE_JPG_REC : ZORAN_MAP_MODE_JPG_PLAY; sfmtjpg_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); } else { for (i = 0; i < zoran_num_formats; i++) if (fmt->fmt.pix.pixelformat == @@ -3010,7 +3011,7 @@ zoran_do_ioctl (struct inode *inode, (char *) &printformat); return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.allocated || (fh->v4l_buffers.allocated && fh->v4l_buffers.active != @@ -3052,7 +3053,7 @@ zoran_do_ioctl (struct inode *inode, fh->map_mode = ZORAN_MAP_MODE_RAW; sfmtv4l_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); } break; @@ -3077,7 +3078,7 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_G_FBUF\n", ZR_DEVNAME(zr)); memset(fb, 0, sizeof(*fb)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); fb->base = zr->buffer.base; fb->fmt.width = zr->buffer.width; fb->fmt.height = zr->buffer.height; @@ -3086,7 +3087,7 @@ zoran_do_ioctl (struct inode *inode, fh->overlay_settings.format->fourcc; } fb->fmt.bytesperline = zr->buffer.bytesperline; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); fb->fmt.colorspace = V4L2_COLORSPACE_SRGB; fb->fmt.field = V4L2_FIELD_INTERLACED; fb->flags = V4L2_FBUF_FLAG_OVERLAY; @@ -3121,12 +3122,12 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_fbuffer(file, fb->base, &zoran_formats[i], fb->fmt.width, fb->fmt.height, fb->fmt.bytesperline); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3139,9 +3140,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_PREVIEW - on=%d\n", ZR_DEVNAME(zr), *on); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = setup_overlay(file, *on); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3163,7 +3164,7 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { dprintk(1, @@ -3224,7 +3225,7 @@ zoran_do_ioctl (struct inode *inode, goto v4l2reqbuf_unlock_and_return; } v4l2reqbuf_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -3245,9 +3246,9 @@ zoran_do_ioctl (struct inode *inode, buf->type = type; buf->index = index; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); res = zoran_v4l2_buffer_status(file, buf, buf->index); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3262,7 +3263,7 @@ zoran_do_ioctl (struct inode *inode, KERN_DEBUG "%s: VIDIOC_QBUF - type=%d, index=%d\n", ZR_DEVNAME(zr), buf->type, buf->index); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: @@ -3322,7 +3323,7 @@ zoran_do_ioctl (struct inode *inode, goto qbuf_unlock_and_return; } qbuf_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3336,7 +3337,7 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_DQBUF - type=%d\n", ZR_DEVNAME(zr), buf->type); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: @@ -3410,7 +3411,7 @@ zoran_do_ioctl (struct inode *inode, goto dqbuf_unlock_and_return; } dqbuf_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3422,7 +3423,7 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMON\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: /* raw capture */ @@ -3470,7 +3471,7 @@ zoran_do_ioctl (struct inode *inode, goto strmon_unlock_and_return; } strmon_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3482,7 +3483,7 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMOFF\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: /* raw capture */ @@ -3540,7 +3541,7 @@ zoran_do_ioctl (struct inode *inode, goto strmoff_unlock_and_return; } strmoff_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3600,7 +3601,7 @@ zoran_do_ioctl (struct inode *inode, ctrl->id > V4L2_CID_HUE) return -EINVAL; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: ctrl->value = zr->brightness; @@ -3615,7 +3616,7 @@ zoran_do_ioctl (struct inode *inode, ctrl->value = zr->hue; break; } - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -3642,7 +3643,7 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: zr->brightness = ctrl->value; @@ -3664,7 +3665,7 @@ zoran_do_ioctl (struct inode *inode, decoder_command(zr, DECODER_SET_PICTURE, &pict); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -3732,9 +3733,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_G_STD\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); norm = zr->norm; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); switch (norm) { case VIDEO_MODE_PAL: @@ -3776,13 +3777,13 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if ((res = zoran_set_norm(zr, norm))) goto sstd_unlock_and_return; res = wait_grab_pending(zr); sstd_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -3809,9 +3810,9 @@ zoran_do_ioctl (struct inode *inode, inp->std = V4L2_STD_ALL; /* Get status of video decoder */ - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); decoder_command(zr, DECODER_GET_STATUS, &status); - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); if (!(status & DECODER_STATUS_GOOD)) { inp->status |= V4L2_IN_ST_NO_POWER; @@ -3830,9 +3831,9 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_G_INPUT\n", ZR_DEVNAME(zr)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); *input = zr->input; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -3845,14 +3846,14 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_S_INPUT - input=%d\n", ZR_DEVNAME(zr), *input); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if ((res = zoran_set_input(zr, *input))) goto sinput_unlock_and_return; /* Make sure the changes come into effect */ res = wait_grab_pending(zr); sinput_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -3914,7 +3915,7 @@ zoran_do_ioctl (struct inode *inode, memset(cropcap, 0, sizeof(*cropcap)); cropcap->type = type; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || @@ -3934,7 +3935,7 @@ zoran_do_ioctl (struct inode *inode, cropcap->defrect.width = BUZ_MIN_WIDTH; cropcap->defrect.height = BUZ_MIN_HEIGHT; cropcap_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -3950,7 +3951,7 @@ zoran_do_ioctl (struct inode *inode, memset(crop, 0, sizeof(*crop)); crop->type = type; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || @@ -3969,7 +3970,7 @@ zoran_do_ioctl (struct inode *inode, crop->c.height = fh->jpg_settings.img_height; gcrop_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -3988,7 +3989,7 @@ zoran_do_ioctl (struct inode *inode, ZR_DEVNAME(zr), crop->type, crop->c.left, crop->c.top, crop->c.width, crop->c.height); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { dprintk(1, @@ -4024,7 +4025,7 @@ zoran_do_ioctl (struct inode *inode, fh->jpg_settings = settings; scrop_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } break; @@ -4038,7 +4039,7 @@ zoran_do_ioctl (struct inode *inode, memset(params, 0, sizeof(*params)); - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); params->quality = fh->jpg_settings.jpg_comp.quality; params->APPn = fh->jpg_settings.jpg_comp.APPn; @@ -4053,7 +4054,7 @@ zoran_do_ioctl (struct inode *inode, params->jpeg_markers = fh->jpg_settings.jpg_comp.jpeg_markers; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -4074,7 +4075,7 @@ zoran_do_ioctl (struct inode *inode, settings.jpg_comp = *params; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->v4l_buffers.active != ZORAN_FREE || fh->jpg_buffers.active != ZORAN_FREE) { @@ -4093,7 +4094,7 @@ zoran_do_ioctl (struct inode *inode, zoran_v4l2_calc_bufsize(&fh->jpg_settings); fh->jpg_settings.jpg_comp = *params = settings.jpg_comp; sjpegc_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return 0; } @@ -4127,7 +4128,7 @@ zoran_do_ioctl (struct inode *inode, switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_OVERLAY: - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH) fmt->fmt.win.w.width = BUZ_MAX_WIDTH; @@ -4138,7 +4139,7 @@ zoran_do_ioctl (struct inode *inode, if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT) fmt->fmt.win.w.height = BUZ_MIN_HEIGHT; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); break; case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -4146,7 +4147,7 @@ zoran_do_ioctl (struct inode *inode, if (fmt->fmt.pix.bytesperline > 0) return -EINVAL; - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) { settings = fh->jpg_settings; @@ -4229,7 +4230,7 @@ zoran_do_ioctl (struct inode *inode, goto tryfmt_unlock_and_return; } tryfmt_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; break; @@ -4280,7 +4281,7 @@ zoran_poll (struct file *file, * if no buffers queued or so, return POLLNVAL */ - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: @@ -4329,7 +4330,7 @@ zoran_poll (struct file *file, } poll_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); return res; } @@ -4385,7 +4386,7 @@ zoran_vm_close (struct vm_area_struct *vma) if (fh->jpg_buffers.buffer[i].map) break; if (i == fh->jpg_buffers.num_buffers) { - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.active != ZORAN_FREE) { jpg_qbuf(file, -1, zr->codec_mode); @@ -4398,7 +4399,7 @@ zoran_vm_close (struct vm_area_struct *vma) fh->jpg_buffers.allocated = 0; fh->jpg_buffers.ready_to_be_freed = 1; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); } break; @@ -4421,7 +4422,7 @@ zoran_vm_close (struct vm_area_struct *vma) if (fh->v4l_buffers.buffer[i].map) break; if (i == fh->v4l_buffers.num_buffers) { - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); if (fh->v4l_buffers.active != ZORAN_FREE) { zr36057_set_memgrab(zr, 0); @@ -4434,7 +4435,7 @@ zoran_vm_close (struct vm_area_struct *vma) fh->v4l_buffers.allocated = 0; fh->v4l_buffers.ready_to_be_freed = 1; - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); } break; @@ -4489,7 +4490,7 @@ zoran_mmap (struct file *file, case ZORAN_MAP_MODE_JPG_PLAY: /* lock */ - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); /* Map the MJPEG buffers */ if (!fh->jpg_buffers.allocated) { @@ -4579,13 +4580,13 @@ zoran_mmap (struct file *file, } jpg_mmap_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); break; case ZORAN_MAP_MODE_RAW: - down(&zr->resource_lock); + mutex_lock(&zr->resource_lock); /* Map the V4L buffers */ if (!fh->v4l_buffers.allocated) { @@ -4657,7 +4658,7 @@ zoran_mmap (struct file *file, break; } v4l_mmap_unlock_and_return: - up(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); break; -- cgit v1.2.3-59-g8ed1b From 2f8de1a10697efe7bee08e51b587208706b44e97 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 21 Mar 2006 14:53:22 -0300 Subject: V4L/DVB (3568h): cpia: correct email address Correct email address typo (erdfeld -> erdfelt). Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cpia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index d93a561e6b80..3cebfa91ca14 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -58,7 +58,7 @@ static int video_nr = -1; #ifdef MODULE module_param(video_nr, int, 0); -MODULE_AUTHOR("Scott J. Bertin & Peter Pregler & Johannes Erdfelt "); +MODULE_AUTHOR("Scott J. Bertin & Peter Pregler & Johannes Erdfelt "); MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("video"); -- cgit v1.2.3-59-g8ed1b From 2467a670ee24631b05e91971286730e71f6a6af0 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 22 Mar 2006 03:48:34 -0300 Subject: V4L/DVB (3568i): adv7175: Drop unused register cache Drop the adv7175 register cache, as it is only written to and never read back from. This saves 128 bytes of memory and slightly speeds up the register writes. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7175.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 4e218f22b214..245f94265758 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -68,8 +68,6 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ struct adv7175 { - unsigned char reg[128]; - int norm; int input; int enable; @@ -95,9 +93,6 @@ adv7175_write (struct i2c_client *client, u8 reg, u8 value) { - struct adv7175 *encoder = i2c_get_clientdata(client); - - encoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } @@ -120,7 +115,6 @@ adv7175_write_block (struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - struct adv7175 *encoder = i2c_get_clientdata(client); struct i2c_msg msg; u8 block_data[32]; @@ -131,8 +125,8 @@ adv7175_write_block (struct i2c_client *client, msg.len = 0; block_data[msg.len++] = reg = data[0]; do { - block_data[msg.len++] = - encoder->reg[reg++] = data[1]; + block_data[msg.len++] = data[1]; + reg++; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && -- cgit v1.2.3-59-g8ed1b From 5a313c59bcc5062fc56088d5ff9289828c4b6626 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 22 Mar 2006 03:48:34 -0300 Subject: V4L/DVB (3568j): adv7175: Drop unused encoder dump command Drop support for the ENCODER_DUMP command in the adv7175 driver. ENCODER_DUMP was never actually defined as far as I can see, so the code was ifdef'd out, and I suspect it was never used, not even once, as it includes an obvious array overrun. The register values of this specific chip can be dumped in a generic way using the i2c-dev driver and the "i2cdump" user-space tool if it is ever really needed. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7175.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 245f94265758..ca86de0c2805 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -165,24 +165,6 @@ set_subcarrier_freq (struct i2c_client *client, adv7175_write(client, 0x05, 0x25); } -#ifdef ENCODER_DUMP -static void -dump (struct i2c_client *client) -{ - struct adv7175 *encoder = i2c_get_clientdata(client); - int i, j; - - printk(KERN_INFO "%s: registry dump\n", I2C_NAME(client)); - for (i = 0; i < 182 / 8; i++) { - printk("%s: 0x%02x -", I2C_NAME(client), i * 8); - for (j = 0; j < 8; j++) { - printk(" 0x%02x", encoder->reg[i * 8 + j]); - } - printk("\n"); - } -} -#endif - /* ----------------------------------------------------------------------- */ // Output filter: S-Video Composite @@ -401,14 +383,6 @@ adv7175_command (struct i2c_client *client, } break; -#ifdef ENCODER_DUMP - case ENCODER_DUMP: - { - dump(client); - } - break; -#endif - default: return -EINVAL; } -- cgit v1.2.3-59-g8ed1b From 9aa45e34d2948f360f8c0e63d10f49015ca51edd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 22 Mar 2006 03:48:35 -0300 Subject: V4L/DVB (3568k): zoran: Use i2c_master_send when possible Change all the Zoran (ZR36050/ZR36060) drivers to use i2c_master_send instead of i2c_transfer when possible. This simplifies the code by a few lines in each driver. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7170.c | 17 +++++++---------- drivers/media/video/adv7175.c | 17 +++++++---------- drivers/media/video/bt819.c | 17 +++++++---------- drivers/media/video/saa7110.c | 7 +------ drivers/media/video/saa7111.c | 17 +++++++---------- drivers/media/video/saa7114.c | 17 +++++++---------- drivers/media/video/saa7185.c | 17 +++++++---------- 7 files changed, 43 insertions(+), 66 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 4ce07ae62dac..d18bf9097dc9 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -125,24 +125,21 @@ adv7170_write_block (struct i2c_client *client, if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ struct adv7170 *encoder = i2c_get_clientdata(client); - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = + block_data[block_len++] = encoder->reg[reg++] = data[1]; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index ca86de0c2805..1a2b111897d5 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -115,24 +115,21 @@ adv7175_write_block (struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = data[1]; + block_data[block_len++] = data[1]; reg++; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index d6447791d0e5..c2c450fbf683 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -141,24 +141,21 @@ bt819_write_block (struct i2c_client *client, if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ struct bt819 *decoder = i2c_get_clientdata(client); - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = + block_data[block_len++] = decoder->reg[reg++] = data[1]; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 20cad9fc99ef..36123fa0b63f 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -108,13 +108,8 @@ saa7110_write_block (struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { struct saa7110 *decoder = i2c_get_clientdata(client); - struct i2c_msg msg; - msg.len = len; - msg.buf = (char *) data; - msg.addr = client->addr; - msg.flags = 0; - ret = i2c_transfer(client->adapter, &msg, 1); + ret = i2c_master_send(client, data, len); /* Cache the written data */ memcpy(decoder->reg + reg, data + 1, len - 1); diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index 6bd1789c8f78..cb27917c376a 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -112,24 +112,21 @@ saa7111_write_block (struct i2c_client *client, if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ struct saa7111 *decoder = i2c_get_clientdata(client); - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = + block_data[block_len++] = decoder->reg[reg++] = data[1]; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index 1c29d05307a5..849b54cd5c24 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c @@ -154,24 +154,21 @@ saa7114_write_block (struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = data[1]; + block_data[block_len++] = data[1]; reg++; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 3ed0edb870a4..67dfa7186453 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -113,24 +113,21 @@ saa7185_write_block (struct i2c_client *client, if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ struct saa7185 *encoder = i2c_get_clientdata(client); - struct i2c_msg msg; u8 block_data[32]; + int block_len; - msg.addr = client->addr; - msg.flags = 0; while (len >= 2) { - msg.buf = (char *) block_data; - msg.len = 0; - block_data[msg.len++] = reg = data[0]; + block_len = 0; + block_data[block_len++] = reg = data[0]; do { - block_data[msg.len++] = + block_data[block_len++] = encoder->reg[reg++] = data[1]; len -= 2; data += 2; } while (len >= 2 && data[0] == reg && - msg.len < 32); - if ((ret = i2c_transfer(client->adapter, - &msg, 1)) < 0) + block_len < 32); + if ((ret = i2c_master_send(client, block_data, + block_len)) < 0) break; } } else { -- cgit v1.2.3-59-g8ed1b From 61808c2bbba127ecd9786401c55ea4c394aa0240 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 23 Mar 2006 02:59:24 -0800 Subject: [PATCH] cciss: fix use-after-free in cciss_init_one free_hba() sets hba[i] to NULL, the dereference afterwards results in this crash. Setting busy_initializing to 0 actually looks unnecessary, but I'm not entirely sure, which is why I left it in. cciss: controller appears to be disabled Unable to handle kernel NULL pointer dereference at virtual address 00000370 printing eip: c1114d53 *pde = 00000000 Oops: 0002 [#1] Modules linked in: CPU: 0 EIP: 0060:[] Not tainted VLI EFLAGS: 00010286 (2.6.16 #1) EIP is at cciss_init_one+0x4e9/0x4fe eax: 00000000 ebx: c132cd60 ecx: c13154e4 edx: c27d3c00 esi: 00000000 edi: c2748800 ebp: c2536ee4 esp: c2536eb8 ds: 007b es: 007b ss: 0068 Process swapper (pid: 1, threadinfo=c2536000 task=c2535a30) Stack: <0>00000000 00000000 00000000 c13fdba0 c2536ee8 c13159c0 c2536f38 f7c74740 c132cd60 c132cd60 ffffffed c2536ef0 c10c1d51 c2748800 c2536f04 c10c1d85 c132cd60 c2748800 c132cd8c c2536f14 c10c1db8 c2748848 00000000 c2536f28 Call Trace: [] show_stack_log_lvl+0xa8/0xb0 [] show_registers+0x102/0x16a [] die+0xc1/0x13c [] do_page_fault+0x38a/0x525 [] error_code+0x4f/0x54 [] pci_call_probe+0xd/0x10 [] __pci_device_probe+0x31/0x43 [] pci_device_probe+0x21/0x34 [] driver_probe_device+0x44/0x99 [] __driver_attach+0x39/0x5d [] bus_for_each_dev+0x35/0x5a [] driver_attach+0x14/0x16 [] bus_add_driver+0x5c/0x8f [] driver_register+0x73/0x78 [] __pci_register_driver+0x5f/0x71 [] cciss_init+0x1a/0x1c [] do_initcalls+0x4c/0x96 [] do_basic_setup+0x1c/0x1e [] init+0x35/0x118 [] kernel_thread_helper+0x5/0xb Code: 04 b5 e0 de 40 c1 8d 50 04 8b 40 34 e8 3f b7 f9 ff 8b 04 b5 e0 de 40 c1 e8 aa f3 ff ff 89 f0 e8 e8 fa ff ff 8b 04 b5 e0 de 40 c1 80 70 03 00 00 00 00 00 00 83 c8 ff 8d 65 f4 5b 5e 5f 5d c3 <0>Kernel panic - not syncing: Attempted to kill init! Signed-off-by: Patrick McHardy Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/cciss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index cf39cf9aac25..e29b8926f80e 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3268,8 +3268,8 @@ clean2: unregister_blkdev(hba[i]->major, hba[i]->devname); clean1: release_io_mem(hba[i]); - free_hba(i); hba[i]->busy_initializing = 0; + free_hba(i); return(-1); } -- cgit v1.2.3-59-g8ed1b From ff4da2e262d2509fe1bacff70dd00934be569c66 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 23 Mar 2006 03:00:07 -0800 Subject: [PATCH] swsusp: add check for suspension of X-controlled devices It is unsafe to suspend devices if the hardware is controlled by X. Add an extra check to prevent this from happening. Signed-off-by: Rafael J. Wysocki Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/power/suspend.c | 5 ++++- drivers/char/vt.c | 8 ++++++++ include/linux/vt_kern.h | 5 +++++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 8660779fb288..bdb60663f2ef 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -8,6 +8,7 @@ * */ +#include #include #include "../base.h" #include "power.h" @@ -62,7 +63,6 @@ int suspend_device(struct device * dev, pm_message_t state) return error; } - /** * device_suspend - Save state and stop all devices in system. * @state: Power state to put each device in. @@ -82,6 +82,9 @@ int device_suspend(pm_message_t state) { int error = 0; + if (!is_console_suspend_safe()) + return -EINVAL; + down(&dpm_sem); down(&dpm_list_sem); while (!list_empty(&dpm_active) && error == 0) { diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 0900d1dbee59..86b31b87eb85 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -3234,6 +3234,14 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org) } } +int is_console_suspend_safe(void) +{ + /* It is unsafe to suspend devices while X has control of the + * hardware. Make sure we are running on a kernel-controlled console. + */ + return vc_cons[fg_console].d->vc_mode == KD_TEXT; +} + /* * Visible symbols for modules */ diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index fab5aed8ca31..530ae3f4248c 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -73,6 +73,11 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc); int vt_waitactive(int vt); void change_console(struct vc_data *new_vc); void reset_vc(struct vc_data *vc); +#ifdef CONFIG_VT +int is_console_suspend_safe(void); +#else +static inline int is_console_suspend_safe(void) { return 1; } +#endif /* * vc_screen.c shares this temporary buffer with the console write code so that -- cgit v1.2.3-59-g8ed1b From d2c5d4fc07a41a6048b01d3b2930aeff1235fda5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 23 Mar 2006 03:00:14 -0800 Subject: [PATCH] cleanup cdrom_ioctl Add a small helper for each ioctl to cut down cdrom_ioctl to a readable size. Signed-off-by: Christoph Hellwig Cc: Acked-by: Jens Axboe Signed-off-by: Benoit Boissinot Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cdrom/cdrom.c | 877 +++++++++++++++++++++++++++++++------------------- 1 file changed, 537 insertions(+), 340 deletions(-) (limited to 'drivers') diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 879bbc26ce96..d6653fc03b92 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2196,395 +2196,592 @@ retry: return cdrom_read_cdda_old(cdi, ubuf, lba, nframes); } -/* Just about every imaginable ioctl is supported in the Uniform layer - * these days. ATAPI / SCSI specific code now mainly resides in - * mmc_ioct(). - */ -int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi, - struct inode *ip, unsigned int cmd, unsigned long arg) +static int cdrom_ioctl_multisession(struct cdrom_device_info *cdi, + void __user *argp) { - struct cdrom_device_ops *cdo = cdi->ops; + struct cdrom_multisession ms_info; + u8 requested_format; int ret; - /* Try the generic SCSI command ioctl's first.. */ - ret = scsi_cmd_ioctl(file, ip->i_bdev->bd_disk, cmd, (void __user *)arg); - if (ret != -ENOTTY) + cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); + + if (!(cdi->ops->capability & CDC_MULTI_SESSION)) + return -ENOSYS; + + if (copy_from_user(&ms_info, argp, sizeof(ms_info))) + return -EFAULT; + + requested_format = ms_info.addr_format; + if (requested_format != CDROM_MSF && requested_format != CDROM_LBA) + return -EINVAL; + ms_info.addr_format = CDROM_LBA; + + ret = cdi->ops->get_last_session(cdi, &ms_info); + if (ret) return ret; - /* the first few commands do not deal with audio drive_info, but - only with routines in cdrom device operations. */ - switch (cmd) { - case CDROMMULTISESSION: { - struct cdrom_multisession ms_info; - u_char requested_format; - cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); - if (!(cdo->capability & CDC_MULTI_SESSION)) - return -ENOSYS; - IOCTL_IN(arg, struct cdrom_multisession, ms_info); - requested_format = ms_info.addr_format; - if (!((requested_format == CDROM_MSF) || - (requested_format == CDROM_LBA))) - return -EINVAL; - ms_info.addr_format = CDROM_LBA; - if ((ret=cdo->get_last_session(cdi, &ms_info))) + sanitize_format(&ms_info.addr, &ms_info.addr_format, requested_format); + + if (copy_to_user(argp, &ms_info, sizeof(ms_info))) + return -EFAULT; + + cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n"); + return 0; +} + +static int cdrom_ioctl_eject(struct cdrom_device_info *cdi) +{ + cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n"); + + if (!CDROM_CAN(CDC_OPEN_TRAY)) + return -ENOSYS; + if (cdi->use_count != 1 || keeplocked) + return -EBUSY; + if (CDROM_CAN(CDC_LOCK)) { + int ret = cdi->ops->lock_door(cdi, 0); + if (ret) return ret; - sanitize_format(&ms_info.addr, &ms_info.addr_format, - requested_format); - IOCTL_OUT(arg, struct cdrom_multisession, ms_info); - cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n"); - return 0; - } + } - case CDROMEJECT: { - cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n"); - if (!CDROM_CAN(CDC_OPEN_TRAY)) - return -ENOSYS; - if (cdi->use_count != 1 || keeplocked) - return -EBUSY; - if (CDROM_CAN(CDC_LOCK)) - if ((ret=cdo->lock_door(cdi, 0))) - return ret; + return cdi->ops->tray_move(cdi, 1); +} - return cdo->tray_move(cdi, 1); - } +static int cdrom_ioctl_closetray(struct cdrom_device_info *cdi) +{ + cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n"); - case CDROMCLOSETRAY: { - cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n"); - if (!CDROM_CAN(CDC_CLOSE_TRAY)) - return -ENOSYS; - return cdo->tray_move(cdi, 0); - } + if (!CDROM_CAN(CDC_CLOSE_TRAY)) + return -ENOSYS; + return cdi->ops->tray_move(cdi, 0); +} - case CDROMEJECT_SW: { - cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n"); - if (!CDROM_CAN(CDC_OPEN_TRAY)) - return -ENOSYS; - if (keeplocked) - return -EBUSY; - cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT); - if (arg) - cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT; - return 0; - } +static int cdrom_ioctl_eject_sw(struct cdrom_device_info *cdi, + unsigned long arg) +{ + cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n"); - case CDROM_MEDIA_CHANGED: { - struct cdrom_changer_info *info; - int changed; + if (!CDROM_CAN(CDC_OPEN_TRAY)) + return -ENOSYS; + if (keeplocked) + return -EBUSY; - cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); - if (!CDROM_CAN(CDC_MEDIA_CHANGED)) - return -ENOSYS; + cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT); + if (arg) + cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT; + return 0; +} - /* cannot select disc or select current disc */ - if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT) - return media_changed(cdi, 1); +static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi, + unsigned long arg) +{ + struct cdrom_changer_info *info; + int ret; - if ((unsigned int)arg >= cdi->capacity) - return -EINVAL; + cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; + if (!CDROM_CAN(CDC_MEDIA_CHANGED)) + return -ENOSYS; - if ((ret = cdrom_read_mech_status(cdi, info))) { - kfree(info); - return ret; - } + /* cannot select disc or select current disc */ + if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT) + return media_changed(cdi, 1); - changed = info->slots[arg].change; - kfree(info); - return changed; - } + if ((unsigned int)arg >= cdi->capacity) + return -EINVAL; - case CDROM_SET_OPTIONS: { - cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n"); - /* options need to be in sync with capability. too late for - that, so we have to check each one separately... */ - switch (arg) { - case CDO_USE_FFLAGS: - case CDO_CHECK_TYPE: - break; - case CDO_LOCK: - if (!CDROM_CAN(CDC_LOCK)) - return -ENOSYS; - break; - case 0: - return cdi->options; - /* default is basically CDO_[AUTO_CLOSE|AUTO_EJECT] */ - default: - if (!CDROM_CAN(arg)) - return -ENOSYS; - } - cdi->options |= (int) arg; - return cdi->options; - } + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; - case CDROM_CLEAR_OPTIONS: { - cdinfo(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n"); - cdi->options &= ~(int) arg; - return cdi->options; - } + ret = cdrom_read_mech_status(cdi, info); + if (!ret) + ret = info->slots[arg].change; + kfree(info); + return ret; +} - case CDROM_SELECT_SPEED: { - cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n"); - if (!CDROM_CAN(CDC_SELECT_SPEED)) - return -ENOSYS; - return cdo->select_speed(cdi, arg); - } +static int cdrom_ioctl_set_options(struct cdrom_device_info *cdi, + unsigned long arg) +{ + cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n"); - case CDROM_SELECT_DISC: { - cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n"); - if (!CDROM_CAN(CDC_SELECT_DISC)) + /* + * Options need to be in sync with capability. + * Too late for that, so we have to check each one separately. + */ + switch (arg) { + case CDO_USE_FFLAGS: + case CDO_CHECK_TYPE: + break; + case CDO_LOCK: + if (!CDROM_CAN(CDC_LOCK)) + return -ENOSYS; + break; + case 0: + return cdi->options; + /* default is basically CDO_[AUTO_CLOSE|AUTO_EJECT] */ + default: + if (!CDROM_CAN(arg)) return -ENOSYS; + } + cdi->options |= (int) arg; + return cdi->options; +} - if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE)) - if ((int)arg >= cdi->capacity) - return -EINVAL; - - /* cdo->select_disc is a hook to allow a driver-specific - * way of seleting disc. However, since there is no - * equiv hook for cdrom_slot_status this may not - * actually be useful... - */ - if (cdo->select_disc != NULL) - return cdo->select_disc(cdi, arg); - - /* no driver specific select_disc(), call our own */ - cdinfo(CD_CHANGER, "Using generic cdrom_select_disc()\n"); - return cdrom_select_disc(cdi, arg); - } +static int cdrom_ioctl_clear_options(struct cdrom_device_info *cdi, + unsigned long arg) +{ + cdinfo(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n"); - case CDROMRESET: { - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n"); - if (!CDROM_CAN(CDC_RESET)) - return -ENOSYS; - invalidate_bdev(ip->i_bdev, 0); - return cdo->reset(cdi); - } + cdi->options &= ~(int) arg; + return cdi->options; +} - case CDROM_LOCKDOOR: { - cdinfo(CD_DO_IOCTL, "%socking door.\n", arg ? "L" : "Unl"); - if (!CDROM_CAN(CDC_LOCK)) - return -EDRIVE_CANT_DO_THIS; - keeplocked = arg ? 1 : 0; - /* don't unlock the door on multiple opens,but allow root - * to do so */ - if ((cdi->use_count != 1) && !arg && !capable(CAP_SYS_ADMIN)) - return -EBUSY; - return cdo->lock_door(cdi, arg); - } +static int cdrom_ioctl_select_speed(struct cdrom_device_info *cdi, + unsigned long arg) +{ + cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n"); - case CDROM_DEBUG: { - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - cdinfo(CD_DO_IOCTL, "%sabling debug.\n", arg ? "En" : "Dis"); - debug = arg ? 1 : 0; - return debug; - } + if (!CDROM_CAN(CDC_SELECT_SPEED)) + return -ENOSYS; + return cdi->ops->select_speed(cdi, arg); +} - case CDROM_GET_CAPABILITY: { - cdinfo(CD_DO_IOCTL, "entering CDROM_GET_CAPABILITY\n"); - return (cdo->capability & ~cdi->mask); - } +static int cdrom_ioctl_select_disc(struct cdrom_device_info *cdi, + unsigned long arg) +{ + cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n"); + + if (!CDROM_CAN(CDC_SELECT_DISC)) + return -ENOSYS; + + if (arg != CDSL_CURRENT && arg != CDSL_NONE) { + if ((int)arg >= cdi->capacity) + return -EINVAL; + } + + /* + * ->select_disc is a hook to allow a driver-specific way of + * seleting disc. However, since there is no equivalent hook for + * cdrom_slot_status this may not actually be useful... + */ + if (cdi->ops->select_disc) + return cdi->ops->select_disc(cdi, arg); + + cdinfo(CD_CHANGER, "Using generic cdrom_select_disc()\n"); + return cdrom_select_disc(cdi, arg); +} + +static int cdrom_ioctl_reset(struct cdrom_device_info *cdi, + struct block_device *bdev) +{ + cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n"); + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (!CDROM_CAN(CDC_RESET)) + return -ENOSYS; + invalidate_bdev(bdev, 0); + return cdi->ops->reset(cdi); +} + +static int cdrom_ioctl_lock_door(struct cdrom_device_info *cdi, + unsigned long arg) +{ + cdinfo(CD_DO_IOCTL, "%socking door.\n", arg ? "L" : "Unl"); + + if (!CDROM_CAN(CDC_LOCK)) + return -EDRIVE_CANT_DO_THIS; + + keeplocked = arg ? 1 : 0; + + /* + * Don't unlock the door on multiple opens by default, but allow + * root to do so. + */ + if (cdi->use_count != 1 && !arg && !capable(CAP_SYS_ADMIN)) + return -EBUSY; + return cdi->ops->lock_door(cdi, arg); +} + +static int cdrom_ioctl_debug(struct cdrom_device_info *cdi, + unsigned long arg) +{ + cdinfo(CD_DO_IOCTL, "%sabling debug.\n", arg ? "En" : "Dis"); + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + debug = arg ? 1 : 0; + return debug; +} -/* The following function is implemented, although very few audio +static int cdrom_ioctl_get_capability(struct cdrom_device_info *cdi) +{ + cdinfo(CD_DO_IOCTL, "entering CDROM_GET_CAPABILITY\n"); + return (cdi->ops->capability & ~cdi->mask); +} + +/* + * The following function is implemented, although very few audio * discs give Universal Product Code information, which should just be * the Medium Catalog Number on the box. Note, that the way the code * is written on the CD is /not/ uniform across all discs! */ - case CDROM_GET_MCN: { - struct cdrom_mcn mcn; - cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCN\n"); - if (!(cdo->capability & CDC_MCN)) - return -ENOSYS; - if ((ret=cdo->get_mcn(cdi, &mcn))) - return ret; - IOCTL_OUT(arg, struct cdrom_mcn, mcn); - cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n"); - return 0; - } +static int cdrom_ioctl_get_mcn(struct cdrom_device_info *cdi, + void __user *argp) +{ + struct cdrom_mcn mcn; + int ret; - case CDROM_DRIVE_STATUS: { - cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n"); - if (!(cdo->capability & CDC_DRIVE_STATUS)) - return -ENOSYS; - if (!CDROM_CAN(CDC_SELECT_DISC)) - return cdo->drive_status(cdi, CDSL_CURRENT); - if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE)) - return cdo->drive_status(cdi, CDSL_CURRENT); - if (((int)arg >= cdi->capacity)) - return -EINVAL; - return cdrom_slot_status(cdi, arg); - } + cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCN\n"); - /* Ok, this is where problems start. The current interface for the - CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption - that CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunatly, - while this is often the case, it is also very common for CDs to - have some tracks with data, and some tracks with audio. Just - because I feel like it, I declare the following to be the best - way to cope. If the CD has ANY data tracks on it, it will be - returned as a data CD. If it has any XA tracks, I will return - it as that. Now I could simplify this interface by combining these - returns with the above, but this more clearly demonstrates - the problem with the current interface. Too bad this wasn't - designed to use bitmasks... -Erik - - Well, now we have the option CDS_MIXED: a mixed-type CD. - User level programmers might feel the ioctl is not very useful. - ---david - */ - case CDROM_DISC_STATUS: { - tracktype tracks; - cdinfo(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n"); - cdrom_count_tracks(cdi, &tracks); - if (tracks.error) - return(tracks.error); - - /* Policy mode on */ - if (tracks.audio > 0) { - if (tracks.data==0 && tracks.cdi==0 && tracks.xa==0) - return CDS_AUDIO; - else - return CDS_MIXED; - } - if (tracks.cdi > 0) return CDS_XA_2_2; - if (tracks.xa > 0) return CDS_XA_2_1; - if (tracks.data > 0) return CDS_DATA_1; - /* Policy mode off */ + if (!(cdi->ops->capability & CDC_MCN)) + return -ENOSYS; + ret = cdi->ops->get_mcn(cdi, &mcn); + if (ret) + return ret; - cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognize!\n"); - return CDS_NO_INFO; - } + if (copy_to_user(argp, &mcn, sizeof(mcn))) + return -EFAULT; + cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n"); + return 0; +} - case CDROM_CHANGER_NSLOTS: { - cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n"); - return cdi->capacity; - } +static int cdrom_ioctl_drive_status(struct cdrom_device_info *cdi, + unsigned long arg) +{ + cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n"); + + if (!(cdi->ops->capability & CDC_DRIVE_STATUS)) + return -ENOSYS; + if (!CDROM_CAN(CDC_SELECT_DISC) || + (arg == CDSL_CURRENT || arg == CDSL_NONE)) + return cdi->ops->drive_status(cdi, CDSL_CURRENT); + if (((int)arg >= cdi->capacity)) + return -EINVAL; + return cdrom_slot_status(cdi, arg); +} + +/* + * Ok, this is where problems start. The current interface for the + * CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption that + * CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunatly, while this + * is often the case, it is also very common for CDs to have some tracks + * with data, and some tracks with audio. Just because I feel like it, + * I declare the following to be the best way to cope. If the CD has ANY + * data tracks on it, it will be returned as a data CD. If it has any XA + * tracks, I will return it as that. Now I could simplify this interface + * by combining these returns with the above, but this more clearly + * demonstrates the problem with the current interface. Too bad this + * wasn't designed to use bitmasks... -Erik + * + * Well, now we have the option CDS_MIXED: a mixed-type CD. + * User level programmers might feel the ioctl is not very useful. + * ---david + */ +static int cdrom_ioctl_disc_status(struct cdrom_device_info *cdi) +{ + tracktype tracks; + + cdinfo(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n"); + + cdrom_count_tracks(cdi, &tracks); + if (tracks.error) + return tracks.error; + + /* Policy mode on */ + if (tracks.audio > 0) { + if (!tracks.data && !tracks.cdi && !tracks.xa) + return CDS_AUDIO; + else + return CDS_MIXED; + } + + if (tracks.cdi > 0) + return CDS_XA_2_2; + if (tracks.xa > 0) + return CDS_XA_2_1; + if (tracks.data > 0) + return CDS_DATA_1; + /* Policy mode off */ + + cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognize!\n"); + return CDS_NO_INFO; +} + +static int cdrom_ioctl_changer_nslots(struct cdrom_device_info *cdi) +{ + cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n"); + return cdi->capacity; +} + +static int cdrom_ioctl_get_subchnl(struct cdrom_device_info *cdi, + void __user *argp) +{ + struct cdrom_subchnl q; + u8 requested, back; + int ret; + + /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/ + + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + if (copy_from_user(&q, argp, sizeof(q))) + return -EFAULT; + + requested = q.cdsc_format; + if (requested != CDROM_MSF && requested != CDROM_LBA) + return -EINVAL; + q.cdsc_format = CDROM_MSF; + + ret = cdi->ops->audio_ioctl(cdi, CDROMSUBCHNL, &q); + if (ret) + return ret; + + back = q.cdsc_format; /* local copy */ + sanitize_format(&q.cdsc_absaddr, &back, requested); + sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); + + if (copy_to_user(argp, &q, sizeof(q))) + return -EFAULT; + /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ + return 0; +} + +static int cdrom_ioctl_read_tochdr(struct cdrom_device_info *cdi, + void __user *argp) +{ + struct cdrom_tochdr header; + int ret; + + /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */ + + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + if (copy_from_user(&header, argp, sizeof(header))) + return -EFAULT; + + ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header); + if (ret) + return ret; + + if (copy_to_user(argp, &header, sizeof(header))) + return -EFAULT; + /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */ + return 0; +} + +static int cdrom_ioctl_read_tocentry(struct cdrom_device_info *cdi, + void __user *argp) +{ + struct cdrom_tocentry entry; + u8 requested_format; + int ret; + + /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */ + + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + if (copy_from_user(&entry, argp, sizeof(entry))) + return -EFAULT; + + requested_format = entry.cdte_format; + if (requested_format != CDROM_MSF && requested_format != CDROM_LBA) + return -EINVAL; + /* make interface to low-level uniform */ + entry.cdte_format = CDROM_MSF; + ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry); + if (ret) + return ret; + sanitize_format(&entry.cdte_addr, &entry.cdte_format, requested_format); + + if (copy_to_user(argp, &entry, sizeof(entry))) + return -EFAULT; + /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */ + return 0; +} + +static int cdrom_ioctl_play_msf(struct cdrom_device_info *cdi, + void __user *argp) +{ + struct cdrom_msf msf; + + cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); + + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + if (copy_from_user(&msf, argp, sizeof(msf))) + return -EFAULT; + return cdi->ops->audio_ioctl(cdi, CDROMPLAYMSF, &msf); +} + +static int cdrom_ioctl_play_trkind(struct cdrom_device_info *cdi, + void __user *argp) +{ + struct cdrom_ti ti; + int ret; + + cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); + + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + if (copy_from_user(&ti, argp, sizeof(ti))) + return -EFAULT; + + ret = check_for_audio_disc(cdi, cdi->ops); + if (ret) + return ret; + return cdi->ops->audio_ioctl(cdi, CDROMPLAYTRKIND, &ti); +} +static int cdrom_ioctl_volctrl(struct cdrom_device_info *cdi, + void __user *argp) +{ + struct cdrom_volctrl volume; + + cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n"); + + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + if (copy_from_user(&volume, argp, sizeof(volume))) + return -EFAULT; + return cdi->ops->audio_ioctl(cdi, CDROMVOLCTRL, &volume); +} + +static int cdrom_ioctl_volread(struct cdrom_device_info *cdi, + void __user *argp) +{ + struct cdrom_volctrl volume; + int ret; + + cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n"); + + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + + ret = cdi->ops->audio_ioctl(cdi, CDROMVOLREAD, &volume); + if (ret) + return ret; + + if (copy_to_user(argp, &volume, sizeof(volume))) + return -EFAULT; + return 0; +} + +static int cdrom_ioctl_audioctl(struct cdrom_device_info *cdi, + unsigned int cmd) +{ + int ret; + + cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n"); + + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + ret = check_for_audio_disc(cdi, cdi->ops); + if (ret) + return ret; + return cdi->ops->audio_ioctl(cdi, cmd, NULL); +} + +/* + * Just about every imaginable ioctl is supported in the Uniform layer + * these days. + * ATAPI / SCSI specific code now mainly resides in mmc_ioctl(). + */ +int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi, + struct inode *ip, unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int ret; + + /* + * Try the generic SCSI command ioctl's first. + */ + ret = scsi_cmd_ioctl(file, ip->i_bdev->bd_disk, cmd, argp); + if (ret != -ENOTTY) + return ret; + + switch (cmd) { + case CDROMMULTISESSION: + return cdrom_ioctl_multisession(cdi, argp); + case CDROMEJECT: + return cdrom_ioctl_eject(cdi); + case CDROMCLOSETRAY: + return cdrom_ioctl_closetray(cdi); + case CDROMEJECT_SW: + return cdrom_ioctl_eject_sw(cdi, arg); + case CDROM_MEDIA_CHANGED: + return cdrom_ioctl_media_changed(cdi, arg); + case CDROM_SET_OPTIONS: + return cdrom_ioctl_set_options(cdi, arg); + case CDROM_CLEAR_OPTIONS: + return cdrom_ioctl_clear_options(cdi, arg); + case CDROM_SELECT_SPEED: + return cdrom_ioctl_select_speed(cdi, arg); + case CDROM_SELECT_DISC: + return cdrom_ioctl_select_disc(cdi, arg); + case CDROMRESET: + return cdrom_ioctl_reset(cdi, ip->i_bdev); + case CDROM_LOCKDOOR: + return cdrom_ioctl_lock_door(cdi, arg); + case CDROM_DEBUG: + return cdrom_ioctl_debug(cdi, arg); + case CDROM_GET_CAPABILITY: + return cdrom_ioctl_get_capability(cdi); + case CDROM_GET_MCN: + return cdrom_ioctl_get_mcn(cdi, argp); + case CDROM_DRIVE_STATUS: + return cdrom_ioctl_drive_status(cdi, arg); + case CDROM_DISC_STATUS: + return cdrom_ioctl_disc_status(cdi); + case CDROM_CHANGER_NSLOTS: + return cdrom_ioctl_changer_nslots(cdi); } - /* use the ioctls that are implemented through the generic_packet() - interface. this may look at bit funny, but if -ENOTTY is - returned that particular ioctl is not implemented and we - let it go through the device specific ones. */ + /* + * Use the ioctls that are implemented through the generic_packet() + * interface. this may look at bit funny, but if -ENOTTY is + * returned that particular ioctl is not implemented and we + * let it go through the device specific ones. + */ if (CDROM_CAN(CDC_GENERIC_PACKET)) { ret = mmc_ioctl(cdi, cmd, arg); - if (ret != -ENOTTY) { + if (ret != -ENOTTY) return ret; - } } - /* note: most of the cdinfo() calls are commented out here, - because they fill up the sys log when CD players poll - the drive. */ + /* + * Note: most of the cdinfo() calls are commented out here, + * because they fill up the sys log when CD players poll + * the drive. + */ switch (cmd) { - case CDROMSUBCHNL: { - struct cdrom_subchnl q; - u_char requested, back; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/ - IOCTL_IN(arg, struct cdrom_subchnl, q); - requested = q.cdsc_format; - if (!((requested == CDROM_MSF) || - (requested == CDROM_LBA))) - return -EINVAL; - q.cdsc_format = CDROM_MSF; - if ((ret=cdo->audio_ioctl(cdi, cmd, &q))) - return ret; - back = q.cdsc_format; /* local copy */ - sanitize_format(&q.cdsc_absaddr, &back, requested); - sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); - IOCTL_OUT(arg, struct cdrom_subchnl, q); - /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ - return 0; - } - case CDROMREADTOCHDR: { - struct cdrom_tochdr header; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */ - IOCTL_IN(arg, struct cdrom_tochdr, header); - if ((ret=cdo->audio_ioctl(cdi, cmd, &header))) - return ret; - IOCTL_OUT(arg, struct cdrom_tochdr, header); - /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */ - return 0; - } - case CDROMREADTOCENTRY: { - struct cdrom_tocentry entry; - u_char requested_format; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */ - IOCTL_IN(arg, struct cdrom_tocentry, entry); - requested_format = entry.cdte_format; - if (!((requested_format == CDROM_MSF) || - (requested_format == CDROM_LBA))) - return -EINVAL; - /* make interface to low-level uniform */ - entry.cdte_format = CDROM_MSF; - if ((ret=cdo->audio_ioctl(cdi, cmd, &entry))) - return ret; - sanitize_format(&entry.cdte_addr, - &entry.cdte_format, requested_format); - IOCTL_OUT(arg, struct cdrom_tocentry, entry); - /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */ - return 0; - } - case CDROMPLAYMSF: { - struct cdrom_msf msf; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); - IOCTL_IN(arg, struct cdrom_msf, msf); - return cdo->audio_ioctl(cdi, cmd, &msf); - } - case CDROMPLAYTRKIND: { - struct cdrom_ti ti; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); - IOCTL_IN(arg, struct cdrom_ti, ti); - CHECKAUDIO; - return cdo->audio_ioctl(cdi, cmd, &ti); - } - case CDROMVOLCTRL: { - struct cdrom_volctrl volume; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n"); - IOCTL_IN(arg, struct cdrom_volctrl, volume); - return cdo->audio_ioctl(cdi, cmd, &volume); - } - case CDROMVOLREAD: { - struct cdrom_volctrl volume; - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n"); - if ((ret=cdo->audio_ioctl(cdi, cmd, &volume))) - return ret; - IOCTL_OUT(arg, struct cdrom_volctrl, volume); - return 0; - } + case CDROMSUBCHNL: + return cdrom_ioctl_get_subchnl(cdi, argp); + case CDROMREADTOCHDR: + return cdrom_ioctl_read_tochdr(cdi, argp); + case CDROMREADTOCENTRY: + return cdrom_ioctl_read_tocentry(cdi, argp); + case CDROMPLAYMSF: + return cdrom_ioctl_play_msf(cdi, argp); + case CDROMPLAYTRKIND: + return cdrom_ioctl_play_trkind(cdi, argp); + case CDROMVOLCTRL: + return cdrom_ioctl_volctrl(cdi, argp); + case CDROMVOLREAD: + return cdrom_ioctl_volread(cdi, argp); case CDROMSTART: case CDROMSTOP: case CDROMPAUSE: - case CDROMRESUME: { - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n"); - CHECKAUDIO; - return cdo->audio_ioctl(cdi, cmd, NULL); - } - } /* switch */ + case CDROMRESUME: + return cdrom_ioctl_audioctl(cdi, cmd); + } - /* do the device specific ioctls */ + /* + * Finally, do the device specific ioctls + */ if (CDROM_CAN(CDC_IOCTLS)) - return cdo->dev_ioctl(cdi, cmd, arg); - + return cdi->ops->dev_ioctl(cdi, cmd, arg); + return -ENOSYS; } -- cgit v1.2.3-59-g8ed1b From 6a2900b67652421b51fe25e4b86ecfec742b1f30 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 23 Mar 2006 03:00:15 -0800 Subject: [PATCH] kill cdrom ->dev_ioctl method Since early 2.4.x all cdrom drivers implement the block_device methods themselves, so they can handle additional ioctls directly instead of going through the cdrom layer. Signed-off-by: Christoph Hellwig Acked-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cdrom/cdrom.c | 7 - drivers/cdrom/cdu31a.c | 8 +- drivers/cdrom/cm206.c | 44 +- drivers/cdrom/sbpcd.c | 1890 +++++++++++++++++++++++------------------------ drivers/cdrom/viocd.c | 2 +- drivers/ide/ide-cd.c | 99 +-- drivers/scsi/sr.c | 37 +- drivers/scsi/sr.h | 1 - drivers/scsi/sr_ioctl.c | 19 - include/linux/cdrom.h | 5 +- 10 files changed, 1040 insertions(+), 1072 deletions(-) (limited to 'drivers') diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index d6653fc03b92..a59876a0bfa1 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -407,7 +407,6 @@ int register_cdrom(struct cdrom_device_info *cdi) ENSURE(get_mcn, CDC_MCN); ENSURE(reset, CDC_RESET); ENSURE(audio_ioctl, CDC_PLAY_AUDIO); - ENSURE(dev_ioctl, CDC_IOCTLS); ENSURE(generic_packet, CDC_GENERIC_PACKET); cdi->mc_flags = 0; cdo->n_minors = 0; @@ -2776,12 +2775,6 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi, return cdrom_ioctl_audioctl(cdi, cmd); } - /* - * Finally, do the device specific ioctls - */ - if (CDROM_CAN(CDC_IOCTLS)) - return cdi->ops->dev_ioctl(cdi, cmd, arg); - return -ENOSYS; } diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index 378e88d20757..72ffd64e8b1e 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -2668,7 +2668,7 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi, return retval; } -static int scd_dev_ioctl(struct cdrom_device_info *cdi, +static int scd_read_audio(struct cdrom_device_info *cdi, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; @@ -2894,11 +2894,10 @@ static struct cdrom_device_ops scd_dops = { .get_mcn = scd_get_mcn, .reset = scd_reset, .audio_ioctl = scd_audio_ioctl, - .dev_ioctl = scd_dev_ioctl, .capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | - CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, + CDC_RESET | CDC_DRIVE_STATUS, .n_minors = 1, }; @@ -2936,6 +2935,9 @@ static int scd_block_ioctl(struct inode *inode, struct file *file, case CDROMCLOSETRAY: retval = scd_tray_move(&scd_info, 0); break; + case CDROMREADAUDIO: + retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg); + break; default: retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg); } diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c index ce127f7ec0f6..fad27a87ce35 100644 --- a/drivers/cdrom/cm206.c +++ b/drivers/cdrom/cm206.c @@ -1157,32 +1157,6 @@ static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, } } -/* Ioctl. These ioctls are specific to the cm206 driver. I have made - some driver statistics accessible through ioctl calls. - */ - -static int cm206_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, - unsigned long arg) -{ - switch (cmd) { -#ifdef STATISTICS - case CM206CTL_GET_STAT: - if (arg >= NR_STATS) - return -EINVAL; - else - return cd->stats[arg]; - case CM206CTL_GET_LAST_STAT: - if (arg >= NR_STATS) - return -EINVAL; - else - return cd->last_stat[arg]; -#endif - default: - debug(("Unknown ioctl call 0x%x\n", cmd)); - return -EINVAL; - } -} - static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr) { if (cd != NULL) { @@ -1321,11 +1295,10 @@ static struct cdrom_device_ops cm206_dops = { .get_mcn = cm206_get_upc, .reset = cm206_reset, .audio_ioctl = cm206_audio_ioctl, - .dev_ioctl = cm206_ioctl, .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED | - CDC_IOCTLS | CDC_DRIVE_STATUS, + CDC_DRIVE_STATUS, .n_minors = 1, }; @@ -1350,6 +1323,21 @@ static int cm206_block_release(struct inode *inode, struct file *file) static int cm206_block_ioctl(struct inode *inode, struct file *file, unsigned cmd, unsigned long arg) { + switch (cmd) { +#ifdef STATISTICS + case CM206CTL_GET_STAT: + if (arg >= NR_STATS) + return -EINVAL; + return cd->stats[arg]; + case CM206CTL_GET_LAST_STAT: + if (arg >= NR_STATS) + return -EINVAL; + return cd->last_stat[arg]; +#endif + default: + break; + } + return cdrom_ioctl(file, &cm206_info, inode, cmd, arg); } diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 466e9c2974bd..4760f515f591 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -4160,18 +4160,13 @@ static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_mu return 0; } -/*==========================================================================*/ -/*==========================================================================*/ -/* - * ioctl support - */ -static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, - u_long arg) +static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, + void * arg) { struct sbpcd_drive *p = cdi->handle; - int i; + int i, st, j; - msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg); + msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg); if (p->drv_id==-1) { msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); return (-ENXIO); /* no such drive */ @@ -4183,484 +4178,163 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); switch (cmd) /* Sun-compatible */ { - case DDIOCSDBG: /* DDI Debug */ - if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM); - i=sbpcd_dbg_ioctl(arg,1); - RETURN_UP(i); - case CDROMRESET: /* hard reset the drive */ - msg(DBG_IOC,"ioctl: CDROMRESET entered.\n"); - i=DriveReset(); - current_drive->audio_state=0; - RETURN_UP(i); - case CDROMREADMODE1: - msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); + case CDROMPAUSE: /* Pause the drive */ + msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n"); + /* pause the drive unit when it is currently in PLAY mode, */ + /* or reset the starting and ending locations when in PAUSED mode. */ + /* If applicable, at the next stopping point it reaches */ + /* the drive will discontinue playing. */ + switch (current_drive->audio_state) + { + case audio_playing: + if (famL_drive) i=cc_ReadSubQ(); + else i=cc_Pause_Resume(1); + if (i<0) RETURN_UP(-EIO); + if (famL_drive) i=cc_Pause_Resume(1); + else i=cc_ReadSubQ(); + if (i<0) RETURN_UP(-EIO); + current_drive->pos_audio_start=current_drive->SubQ_run_tot; + current_drive->audio_state=audio_pausing; + RETURN_UP(0); + case audio_pausing: + i=cc_Seek(current_drive->pos_audio_start,1); + if (i<0) RETURN_UP(-EIO); + RETURN_UP(0); + default: + RETURN_UP(-EINVAL); + } + + case CDROMRESUME: /* resume paused audio play */ + msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n"); + /* resume playing audio tracks when a previous PLAY AUDIO call has */ + /* been paused with a PAUSE command. */ + /* It will resume playing from the location saved in SubQ_run_tot. */ + if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL); + if (famL_drive) + i=cc_PlayAudio(current_drive->pos_audio_start, + current_drive->pos_audio_end); + else i=cc_Pause_Resume(3); + if (i<0) RETURN_UP(-EIO); + current_drive->audio_state=audio_playing; + RETURN_UP(0); + + case CDROMPLAYMSF: + msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); #ifdef SAFE_MIXED if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ - cc_ModeSelect(CD_FRAMESIZE); - cc_ModeSense(); - current_drive->mode=READ_M1; + if (current_drive->audio_state==audio_playing) + { + i=cc_Pause_Resume(1); + if (i<0) RETURN_UP(-EIO); + i=cc_ReadSubQ(); + if (i<0) RETURN_UP(-EIO); + current_drive->pos_audio_start=current_drive->SubQ_run_tot; + i=cc_Seek(current_drive->pos_audio_start,1); + } + memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf)); + /* values come as msf-bin */ + current_drive->pos_audio_start = (msf.cdmsf_min0<<16) | + (msf.cdmsf_sec0<<8) | + msf.cdmsf_frame0; + current_drive->pos_audio_end = (msf.cdmsf_min1<<16) | + (msf.cdmsf_sec1<<8) | + msf.cdmsf_frame1; + msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n", + current_drive->pos_audio_start,current_drive->pos_audio_end); + i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); + if (i<0) + { + msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); + DriveReset(); + current_drive->audio_state=0; + RETURN_UP(-EIO); + } + current_drive->audio_state=audio_playing; RETURN_UP(0); - case CDROMREADMODE2: /* not usable at the moment */ - msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); + case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ + msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); #ifdef SAFE_MIXED if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ - cc_ModeSelect(CD_FRAMESIZE_RAW1); - cc_ModeSense(); - current_drive->mode=READ_M2; + if (current_drive->audio_state==audio_playing) + { + msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); +#if 1 + RETURN_UP(0); /* just let us play on */ +#else + RETURN_UP(-EINVAL); /* play on, but say "error" */ +#endif + } + memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti)); + msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n", + ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1); + if (ti.cdti_trk0n_first_track) RETURN_UP(-EINVAL); + if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL); + if (ti.cdti_trk1current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track; + current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address; + current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address; + i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); + if (i<0) + { + msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); + DriveReset(); + current_drive->audio_state=0; + RETURN_UP(-EIO); + } + current_drive->audio_state=audio_playing; RETURN_UP(0); - case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */ - msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n"); - if (current_drive->sbp_audsiz>0) - vfree(current_drive->aud_buf); - current_drive->aud_buf=NULL; - current_drive->sbp_audsiz=arg; + case CDROMREADTOCHDR: /* Read the table of contents header */ + msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n"); + tochdr.cdth_trk0=current_drive->n_first_track; + tochdr.cdth_trk1=current_drive->n_last_track; + memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr)); + RETURN_UP(0); - if (current_drive->sbp_audsiz>16) - { - current_drive->sbp_audsiz = 0; - RETURN_UP(current_drive->sbp_audsiz); - } - - if (current_drive->sbp_audsiz>0) + case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ + msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n"); + memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); + i=tocentry.cdte_track; + if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1; + else if (in_first_track||i>current_drive->n_last_track) + RETURN_UP(-EINVAL); + tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F; + tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F; + tocentry.cdte_datamode=current_drive->TocBuffer[i].format; + if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */ { - current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW); - if (current_drive->aud_buf==NULL) - { - msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz); - current_drive->sbp_audsiz=0; - } - else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz); + tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF; + tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF; + tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF; } - RETURN_UP(current_drive->sbp_audsiz); - - case CDROMREADAUDIO: - { /* start of CDROMREADAUDIO */ - int i=0, j=0, frame, block=0; - u_int try=0; - u_long timeout; - u_char *p; - u_int data_tries = 0; - u_int data_waits = 0; - u_int data_retrying = 0; - int status_tries; - int error_flag; + else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ + tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address); + else RETURN_UP(-EINVAL); + memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); + RETURN_UP(0); - msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n"); - if (fam0_drive) RETURN_UP(-EINVAL); - if (famL_drive) RETURN_UP(-EINVAL); - if (famV_drive) RETURN_UP(-EINVAL); - if (famT_drive) RETURN_UP(-EINVAL); + case CDROMSTOP: /* Spin down the drive */ + msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n"); #ifdef SAFE_MIXED if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ - if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL); - if (copy_from_user(&read_audio, (void __user *)arg, - sizeof(struct cdrom_read_audio))) - RETURN_UP(-EFAULT); - if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL); - if (!access_ok(VERIFY_WRITE, read_audio.buf, - read_audio.nframes*CD_FRAMESIZE_RAW)) - RETURN_UP(-EFAULT); - - if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */ - block=msf2lba(&read_audio.addr.msf.minute); - else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */ - block=read_audio.addr.lba; - else RETURN_UP(-EINVAL); -#if 000 - i=cc_SetSpeed(speed_150,0,0); - if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i); -#endif - msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n", - block, blk2msf(block)); - msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n"); -#if OLD_BUSY - while (busy_data) sbp_sleep(HZ/10); /* wait a bit */ - busy_audio=1; -#endif /* OLD_BUSY */ - error_flag=0; - for (data_tries=5; data_tries>0; data_tries--) - { - msg(DBG_AUD,"data_tries=%d ...\n", data_tries); - current_drive->mode=READ_AU; - cc_ModeSelect(CD_FRAMESIZE_RAW); - cc_ModeSense(); - for (status_tries=3; status_tries > 0; status_tries--) - { - flags_cmd_out |= f_respo3; - cc_ReadStatus(); - if (sbp_status() != 0) break; - if (st_check) cc_ReadError(); - sbp_sleep(1); /* wait a bit, try again */ - } - if (status_tries == 0) - { - msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__); - continue; - } - msg(DBG_AUD,"read_audio: sbp_status: ok.\n"); - - flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; - if (fam0L_drive) - { - flags_cmd_out |= f_lopsta | f_getsta | f_bit1; - cmd_type=READ_M2; - drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ - drvcmd[1]=(block>>16)&0x000000ff; - drvcmd[2]=(block>>8)&0x000000ff; - drvcmd[3]=block&0x000000ff; - drvcmd[4]=0; - drvcmd[5]=read_audio.nframes; /* # of frames */ - drvcmd[6]=0; - } - else if (fam1_drive) - { - drvcmd[0]=CMD1_READ; /* "read frames", new drives */ - lba2msf(block,&drvcmd[1]); /* msf-bin format required */ - drvcmd[4]=0; - drvcmd[5]=0; - drvcmd[6]=read_audio.nframes; /* # of frames */ - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_READ_XA2; - lba2msf(block,&drvcmd[1]); /* msf-bin format required */ - drvcmd[4]=0; - drvcmd[5]=read_audio.nframes; /* # of frames */ - drvcmd[6]=0x11; /* raw mode */ - } - else if (famT_drive) /* CD-55A: not tested yet */ - { - } - msg(DBG_AUD,"read_audio: before giving \"read\" command.\n"); - flags_cmd_out=f_putcmd; - response_count=0; - i=cmd_out(); - if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i); - sbp_sleep(0); - msg(DBG_AUD,"read_audio: after giving \"read\" command.\n"); - for (frame=1;frame<2 && !error_flag; frame++) - { - try=maxtim_data; - for (timeout=jiffies+9*HZ; ; ) - { - for ( ; try!=0;try--) - { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) break; - if (!(j&s_not_result_ready)) break; - if (fam0L_drive) if (j&s_attention) break; - } - if (try != 0 || time_after_eq(jiffies, timeout)) break; - if (data_retrying == 0) data_waits++; - data_retrying = 1; - sbp_sleep(1); - try = 1; - } - if (try==0) - { - msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n"); - error_flag++; - break; - } - msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n"); - if (j&s_not_data_ready) - { - msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n"); - error_flag++; - break; - } - msg(DBG_AUD,"read_audio: before reading data.\n"); - error_flag=0; - p = current_drive->aud_buf; - if (sbpro_type==1) OUT(CDo_sel_i_d,1); - if (do_16bit) - { - u_short *p2 = (u_short *) p; - - for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) - { - if ((inb_p(CDi_status)&s_not_data_ready)) continue; - - /* get one sample */ - *p2++ = inw_p(CDi_data); - *p2++ = inw_p(CDi_data); - } - } else { - for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) - { - if ((inb_p(CDi_status)&s_not_data_ready)) continue; - - /* get one sample */ - *p++ = inb_p(CDi_data); - *p++ = inb_p(CDi_data); - *p++ = inb_p(CDi_data); - *p++ = inb_p(CDi_data); - } - } - if (sbpro_type==1) OUT(CDo_sel_i_d,0); - data_retrying = 0; - } - msg(DBG_AUD,"read_audio: after reading data.\n"); - if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ - { - msg(DBG_AUD,"read_audio: read aborted by drive\n"); -#if 0000 - i=cc_DriveReset(); /* ugly fix to prevent a hang */ -#else - i=cc_ReadError(); -#endif - continue; - } - if (fam0L_drive) - { - i=maxtim_data; - for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--) - { - for ( ;i!=0;i--) - { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) break; - if (!(j&s_not_result_ready)) break; - if (j&s_attention) break; - } - if (i != 0 || time_after_eq(jiffies, timeout)) break; - sbp_sleep(0); - i = 1; - } - if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ"); - if (!(j&s_attention)) - { - msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n"); - i=cc_DriveReset(); /* ugly fix to prevent a hang */ - continue; - } - } - do - { - if (fam0L_drive) cc_ReadStatus(); - i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ - if (i<0) { msg(DBG_AUD, - "read_audio: cc_ReadStatus error after read: %02X\n", - current_drive->status_bits); - continue; /* FIXME */ - } - } - while ((fam0L_drive)&&(!st_check)&&(!(i&p_success))); - if (st_check) - { - i=cc_ReadError(); - msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i); - continue; - } - if (copy_to_user(read_audio.buf, - current_drive->aud_buf, - read_audio.nframes * CD_FRAMESIZE_RAW)) - RETURN_UP(-EFAULT); - msg(DBG_AUD,"read_audio: copy_to_user done.\n"); - break; - } - cc_ModeSelect(CD_FRAMESIZE); - cc_ModeSense(); - current_drive->mode=READ_M1; -#if OLD_BUSY - busy_audio=0; -#endif /* OLD_BUSY */ - if (data_tries == 0) - { - msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__); - RETURN_UP(-EIO); - } - msg(DBG_AUD,"read_audio: successful return.\n"); - RETURN_UP(0); - } /* end of CDROMREADAUDIO */ - - default: - msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); - RETURN_UP(-EINVAL); - } /* end switch(cmd) */ -} - -static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, - void * arg) -{ - struct sbpcd_drive *p = cdi->handle; - int i, st, j; - - msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg); - if (p->drv_id==-1) { - msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); - return (-ENXIO); /* no such drive */ - } - down(&ioctl_read_sem); - if (p != current_drive) - switch_drive(p); - - msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); - switch (cmd) /* Sun-compatible */ - { - - case CDROMPAUSE: /* Pause the drive */ - msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n"); - /* pause the drive unit when it is currently in PLAY mode, */ - /* or reset the starting and ending locations when in PAUSED mode. */ - /* If applicable, at the next stopping point it reaches */ - /* the drive will discontinue playing. */ - switch (current_drive->audio_state) - { - case audio_playing: - if (famL_drive) i=cc_ReadSubQ(); - else i=cc_Pause_Resume(1); - if (i<0) RETURN_UP(-EIO); - if (famL_drive) i=cc_Pause_Resume(1); - else i=cc_ReadSubQ(); - if (i<0) RETURN_UP(-EIO); - current_drive->pos_audio_start=current_drive->SubQ_run_tot; - current_drive->audio_state=audio_pausing; - RETURN_UP(0); - case audio_pausing: - i=cc_Seek(current_drive->pos_audio_start,1); - if (i<0) RETURN_UP(-EIO); - RETURN_UP(0); - default: - RETURN_UP(-EINVAL); - } - - case CDROMRESUME: /* resume paused audio play */ - msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n"); - /* resume playing audio tracks when a previous PLAY AUDIO call has */ - /* been paused with a PAUSE command. */ - /* It will resume playing from the location saved in SubQ_run_tot. */ - if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL); - if (famL_drive) - i=cc_PlayAudio(current_drive->pos_audio_start, - current_drive->pos_audio_end); - else i=cc_Pause_Resume(3); - if (i<0) RETURN_UP(-EIO); - current_drive->audio_state=audio_playing; - RETURN_UP(0); - - case CDROMPLAYMSF: - msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); -#ifdef SAFE_MIXED - if (current_drive->has_data>1) RETURN_UP(-EBUSY); -#endif /* SAFE_MIXED */ - if (current_drive->audio_state==audio_playing) - { - i=cc_Pause_Resume(1); - if (i<0) RETURN_UP(-EIO); - i=cc_ReadSubQ(); - if (i<0) RETURN_UP(-EIO); - current_drive->pos_audio_start=current_drive->SubQ_run_tot; - i=cc_Seek(current_drive->pos_audio_start,1); - } - memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf)); - /* values come as msf-bin */ - current_drive->pos_audio_start = (msf.cdmsf_min0<<16) | - (msf.cdmsf_sec0<<8) | - msf.cdmsf_frame0; - current_drive->pos_audio_end = (msf.cdmsf_min1<<16) | - (msf.cdmsf_sec1<<8) | - msf.cdmsf_frame1; - msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n", - current_drive->pos_audio_start,current_drive->pos_audio_end); - i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); - if (i<0) - { - msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); - DriveReset(); - current_drive->audio_state=0; - RETURN_UP(-EIO); - } - current_drive->audio_state=audio_playing; - RETURN_UP(0); - - case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ - msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); -#ifdef SAFE_MIXED - if (current_drive->has_data>1) RETURN_UP(-EBUSY); -#endif /* SAFE_MIXED */ - if (current_drive->audio_state==audio_playing) - { - msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); -#if 1 - RETURN_UP(0); /* just let us play on */ -#else - RETURN_UP(-EINVAL); /* play on, but say "error" */ -#endif - } - memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti)); - msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n", - ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1); - if (ti.cdti_trk0n_first_track) RETURN_UP(-EINVAL); - if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL); - if (ti.cdti_trk1current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track; - current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address; - current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address; - i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); - if (i<0) - { - msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); - DriveReset(); - current_drive->audio_state=0; - RETURN_UP(-EIO); - } - current_drive->audio_state=audio_playing; - RETURN_UP(0); - - case CDROMREADTOCHDR: /* Read the table of contents header */ - msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n"); - tochdr.cdth_trk0=current_drive->n_first_track; - tochdr.cdth_trk1=current_drive->n_last_track; - memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr)); - RETURN_UP(0); - - case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ - msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n"); - memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); - i=tocentry.cdte_track; - if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1; - else if (in_first_track||i>current_drive->n_last_track) - RETURN_UP(-EINVAL); - tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F; - tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F; - tocentry.cdte_datamode=current_drive->TocBuffer[i].format; - if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */ - { - tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF; - tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF; - tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF; - } - else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ - tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address); - else RETURN_UP(-EINVAL); - memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); - RETURN_UP(0); - - case CDROMSTOP: /* Spin down the drive */ - msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n"); -#ifdef SAFE_MIXED - if (current_drive->has_data>1) RETURN_UP(-EBUSY); -#endif /* SAFE_MIXED */ - i=cc_Pause_Resume(1); - current_drive->audio_state=0; -#if 0 - cc_DriveReset(); + i=cc_Pause_Resume(1); + current_drive->audio_state=0; +#if 0 + cc_DriveReset(); #endif RETURN_UP(i); - + case CDROMSTART: /* Spin up the drive */ msg(DBG_IOC,"ioctl: CDROMSTART entered.\n"); cc_SpinUp(); current_drive->audio_state=0; RETURN_UP(0); - + case CDROMVOLCTRL: /* Volume control */ msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n"); memcpy(&volctrl,(char *) arg,sizeof(volctrl)); @@ -4670,7 +4344,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, current_drive->vol_ctrl1=volctrl.channel1; i=cc_SetVolume(); RETURN_UP(0); - + case CDROMVOLREAD: /* read Volume settings from drive */ msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); st=cc_GetVolume(); @@ -4694,7 +4368,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, if (i<0) { j=cc_ReadError(); /* clear out error status from drive */ current_drive->audio_state=CDROM_AUDIO_NO_STATUS; - /* get and set the disk state here, + /* get and set the disk state here, probably not the right place, but who cares! It makes it work properly! --AJK */ if (current_drive->CD_changed==0xFF) { @@ -4715,8 +4389,8 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, } } memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); - /* - This virtual crap is very bogus! + /* + This virtual crap is very bogus! It doesn't detect when the cd is done playing audio! Lets do this right with proper hardware register reading! */ @@ -4775,7 +4449,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, SC.cdsc_trk,SC.cdsc_ind, SC.cdsc_absaddr,SC.cdsc_reladdr); RETURN_UP(0); - + default: msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); RETURN_UP(-EINVAL); @@ -4788,7 +4462,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, static void sbp_transfer(struct request *req) { long offs; - + while ( (req->nr_sectors > 0) && (req->sector/4 >= current_drive->sbp_first_frame) && (req->sector/4 <= current_drive->sbp_last_frame) ) @@ -4807,11 +4481,11 @@ static void sbp_transfer(struct request *req) * * This is a kludge so we don't need to modify end_request. * We put the req we take out after INIT_REQUEST in the requests list, - * so that end_request will discard it. + * so that end_request will discard it. * * The bug could be present in other block devices, perhaps we * should modify INIT_REQUEST and end_request instead, and - * change every block device.. + * change every block device.. * * Could be a race here?? Could e.g. a timer interrupt schedule() us? * If so, we should copy end_request here, and do it right.. (or @@ -4831,546 +4505,865 @@ static void sbp_transfer(struct request *req) /*==========================================================================*/ /* - * I/O request routine, called from Linux kernel. + * I/O request routine, called from Linux kernel. + */ +static void do_sbpcd_request(request_queue_t * q) +{ + u_int block; + u_int nsect; + int status_tries, data_tries; + struct request *req; + struct sbpcd_drive *p; +#ifdef DEBUG_GTL + static int xx_nr=0; + int xnr; +#endif + + request_loop: +#ifdef DEBUG_GTL + xnr=++xx_nr; + + req = elv_next_request(q); + + if (!req) + { + printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n", + xnr, current->pid, jiffies); + printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n", + xnr, jiffies); + return; + } + + printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n", + xnr, req, req->sector, req->nr_sectors, current->pid, jiffies); +#endif + + req = elv_next_request(q); /* take out our request so no other */ + if (!req) + return; + + if (req -> sector == -1) + end_request(req, 0); + spin_unlock_irq(q->queue_lock); + + down(&ioctl_read_sem); + if (rq_data_dir(elv_next_request(q)) != READ) + { + msg(DBG_INF, "bad cmd %d\n", req->cmd[0]); + goto err_done; + } + p = req->rq_disk->private_data; +#if OLD_BUSY + while (busy_audio) sbp_sleep(HZ); /* wait a bit */ + busy_data=1; +#endif /* OLD_BUSY */ + + if (p->audio_state==audio_playing) goto err_done; + if (p != current_drive) + switch_drive(p); + + block = req->sector; /* always numbered as 512-byte-pieces */ + nsect = req->nr_sectors; /* always counted as 512-byte-pieces */ + + msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect); +#if 0 + msg(DBG_MUL,"read LBA %d\n", block/4); +#endif + + sbp_transfer(req); + /* if we satisfied the request from the buffer, we're done. */ + if (req->nr_sectors == 0) + { +#ifdef DEBUG_GTL + printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n", + xnr, req, req->sector, req->nr_sectors, jiffies); +#endif + up(&ioctl_read_sem); + spin_lock_irq(q->queue_lock); + end_request(req, 1); + goto request_loop; + } + +#ifdef FUTURE + i=prepare(0,0); /* at moment not really a hassle check, but ... */ + if (i!=0) + msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i); +#endif /* FUTURE */ + + if (!st_spinning) cc_SpinUp(); + + for (data_tries=n_retries; data_tries > 0; data_tries--) + { + for (status_tries=3; status_tries > 0; status_tries--) + { + flags_cmd_out |= f_respo3; + cc_ReadStatus(); + if (sbp_status() != 0) break; + if (st_check) cc_ReadError(); + sbp_sleep(1); /* wait a bit, try again */ + } + if (status_tries == 0) + { + msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__); + break; + } + + sbp_read_cmd(req); + sbp_sleep(0); + if (sbp_data(req) != 0) + { +#ifdef SAFE_MIXED + current_drive->has_data=2; /* is really a data disk */ +#endif /* SAFE_MIXED */ +#ifdef DEBUG_GTL + printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n", + xnr, req, req->sector, req->nr_sectors, jiffies); +#endif + up(&ioctl_read_sem); + spin_lock_irq(q->queue_lock); + end_request(req, 1); + goto request_loop; + } + } + + err_done: +#if OLD_BUSY + busy_data=0; +#endif /* OLD_BUSY */ +#ifdef DEBUG_GTL + printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n", + xnr, req, req->sector, req->nr_sectors, jiffies); +#endif + up(&ioctl_read_sem); + sbp_sleep(0); /* wait a bit, try again */ + spin_lock_irq(q->queue_lock); + end_request(req, 0); + goto request_loop; +} +/*==========================================================================*/ +/* + * build and send the READ command. + */ +static void sbp_read_cmd(struct request *req) +{ +#undef OLD + + int i; + int block; + + current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ + current_drive->sbp_current = 0; + block=req->sector/4; + if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm) + current_drive->sbp_read_frames = current_drive->sbp_bufsiz; + else + { + current_drive->sbp_read_frames=current_drive->CDsize_frm-block; + /* avoid reading past end of data */ + if (current_drive->sbp_read_frames < 1) + { + msg(DBG_INF,"requested frame %d, CD size %d ???\n", + block, current_drive->CDsize_frm); + current_drive->sbp_read_frames=1; + } + } + + flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; + clr_cmdbuf(); + if (famV_drive) + { + drvcmd[0]=CMDV_READ; + lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ + bin2bcdx(&drvcmd[1]); + bin2bcdx(&drvcmd[2]); + bin2bcdx(&drvcmd[3]); + drvcmd[4]=current_drive->sbp_read_frames>>8; + drvcmd[5]=current_drive->sbp_read_frames&0xff; + drvcmd[6]=0x02; /* flag "msf-bcd" */ + } + else if (fam0L_drive) + { + flags_cmd_out |= f_lopsta | f_getsta | f_bit1; + if (current_drive->xa_byte==0x20) + { + cmd_type=READ_M2; + drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ + drvcmd[1]=(block>>16)&0x0ff; + drvcmd[2]=(block>>8)&0x0ff; + drvcmd[3]=block&0x0ff; + drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[5]=current_drive->sbp_read_frames&0x0ff; + } + else + { + drvcmd[0]=CMD0_READ; /* "read frames", old drives */ + if (current_drive->drv_type>=drv_201) + { + lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ + bin2bcdx(&drvcmd[1]); + bin2bcdx(&drvcmd[2]); + bin2bcdx(&drvcmd[3]); + } + else + { + drvcmd[1]=(block>>16)&0x0ff; + drvcmd[2]=(block>>8)&0x0ff; + drvcmd[3]=block&0x0ff; + } + drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[5]=current_drive->sbp_read_frames&0x0ff; + drvcmd[6]=(current_drive->drv_typesbp_read_frames>>8)&0x0ff; + drvcmd[6]=current_drive->sbp_read_frames&0x0ff; + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_READ; + lba2msf(block,&drvcmd[1]); /* msf-bin format required */ + drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[5]=current_drive->sbp_read_frames&0x0ff; + drvcmd[6]=0x02; + } + else if (famT_drive) + { + drvcmd[0]=CMDT_READ; + drvcmd[2]=(block>>24)&0x0ff; + drvcmd[3]=(block>>16)&0x0ff; + drvcmd[4]=(block>>8)&0x0ff; + drvcmd[5]=block&0x0ff; + drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[8]=current_drive->sbp_read_frames&0x0ff; + } + flags_cmd_out=f_putcmd; + response_count=0; + i=cmd_out(); + if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i); + return; +} +/*==========================================================================*/ +/* + * Check the completion of the read-data command. On success, read + * the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer. */ -static void do_sbpcd_request(request_queue_t * q) +static int sbp_data(struct request *req) { - u_int block; - u_int nsect; - int status_tries, data_tries; - struct request *req; - struct sbpcd_drive *p; -#ifdef DEBUG_GTL - static int xx_nr=0; - int xnr; -#endif - - request_loop: -#ifdef DEBUG_GTL - xnr=++xx_nr; - - req = elv_next_request(q); - - if (!req) - { - printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n", - xnr, current->pid, jiffies); - printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n", - xnr, jiffies); - return; - } + int i=0, j=0, l, frame; + u_int try=0; + u_long timeout; + u_char *p; + u_int data_tries = 0; + u_int data_waits = 0; + u_int data_retrying = 0; + int error_flag; + int xa_count; + int max_latency; + int success; + int wait; + int duration; - printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n", - xnr, req, req->sector, req->nr_sectors, current->pid, jiffies); + error_flag=0; + success=0; +#if LONG_TIMING + max_latency=9*HZ; +#else + if (current_drive->f_multisession) max_latency=15*HZ; + else max_latency=5*HZ; #endif + duration=jiffies; + for (frame=0;framesbp_read_frames&&!error_flag; frame++) + { + SBPCD_CLI; - req = elv_next_request(q); /* take out our request so no other */ - if (!req) - return; + del_timer(&data_timer); + data_timer.expires=jiffies+max_latency; + timed_out_data=0; + add_timer(&data_timer); + while (!timed_out_data) + { + if (current_drive->f_multisession) try=maxtim_data*4; + else try=maxtim_data; + msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try); + for ( ; try!=0;try--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) break; + if (!(j&s_not_result_ready)) break; + if (fam0LV_drive) if (j&s_attention) break; + } + if (!(j&s_not_data_ready)) goto data_ready; + if (try==0) + { + if (data_retrying == 0) data_waits++; + data_retrying = 1; + msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n"); + sbp_sleep(1); + try = 1; + } + } + msg(DBG_INF,"sbp_data: CDi_status loop expired.\n"); + data_ready: + del_timer(&data_timer); - if (req -> sector == -1) - end_request(req, 0); - spin_unlock_irq(q->queue_lock); + if (timed_out_data) + { + msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j); + error_flag++; + } + if (try==0) + { + msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j); + error_flag++; + } + if (!(j&s_not_result_ready)) + { + msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j); + response_count=20; + j=ResponseInfo(); + j=inb(CDi_status); + } + if (j&s_not_data_ready) + { + if ((current_drive->ored_ctl_adr&0x40)==0) + msg(DBG_INF, "CD contains no data tracks.\n"); + else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j); + error_flag++; + } + SBPCD_STI; + if (error_flag) break; - down(&ioctl_read_sem); - if (rq_data_dir(elv_next_request(q)) != READ) - { - msg(DBG_INF, "bad cmd %d\n", req->cmd[0]); - goto err_done; + msg(DBG_000, "sbp_data: beginning to read.\n"); + p = current_drive->sbp_buf + frame * CD_FRAMESIZE; + if (sbpro_type==1) OUT(CDo_sel_i_d,1); + if (cmd_type==READ_M2) { + if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1); + else insb(CDi_data, xa_head_buf, CD_XA_HEAD); + } + if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1); + else insb(CDi_data, p, CD_FRAMESIZE); + if (cmd_type==READ_M2) { + if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1); + else insb(CDi_data, xa_tail_buf, CD_XA_TAIL); + } + current_drive->sbp_current++; + if (sbpro_type==1) OUT(CDo_sel_i_d,0); + if (cmd_type==READ_M2) + { + for (xa_count=0;xa_count= 1000) + { + msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries); + data_waits = data_tries = 0; + } } - p = req->rq_disk->private_data; -#if OLD_BUSY - while (busy_audio) sbp_sleep(HZ); /* wait a bit */ - busy_data=1; -#endif /* OLD_BUSY */ - - if (p->audio_state==audio_playing) goto err_done; - if (p != current_drive) - switch_drive(p); - - block = req->sector; /* always numbered as 512-byte-pieces */ - nsect = req->nr_sectors; /* always counted as 512-byte-pieces */ - - msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect); + duration=jiffies-duration; + msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration); + if (famT_drive) + { + wait=8; + do + { + if (teac==2) + { + if ((i=CDi_stat_loop_T()) == -1) break; + } + else + { + sbp_sleep(1); + OUT(CDo_sel_i_d,0); + i=inb(CDi_status); + } + if (!(i&s_not_data_ready)) + { + OUT(CDo_sel_i_d,1); + j=0; + do + { + if (do_16bit) i=inw(CDi_data); + else i=inb(CDi_data); + j++; + i=inb(CDi_status); + } + while (!(i&s_not_data_ready)); + msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j); + } + if (!(i&s_not_result_ready)) + { + OUT(CDo_sel_i_d,0); + l=0; + do + { + infobuf[l++]=inb(CDi_info); + i=inb(CDi_status); + } + while (!(i&s_not_result_ready)); + if (infobuf[0]==0x00) success=1; +#if 1 + for (j=0;j1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion); + else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n"); + clr_cmdbuf(); + drvcmd[0]=CMDT_READ_ERR; + j=cmd_out_T(); /* !!! recursive here !!! */ + --recursion; + sbp_sleep(1); + } + while (j<0); + current_drive->error_state=infobuf[2]; + current_drive->b3=infobuf[3]; + current_drive->b4=infobuf[4]; + } + break; + } + else + { #if 0 - msg(DBG_MUL,"read LBA %d\n", block/4); + msg(DBG_TEA, "============= waiting for result=================.\n"); + sbp_sleep(1); #endif - - sbp_transfer(req); - /* if we satisfied the request from the buffer, we're done. */ - if (req->nr_sectors == 0) + } + } + while (wait--); + } + + if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ { -#ifdef DEBUG_GTL - printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n", - xnr, req, req->sector, req->nr_sectors, jiffies); + msg(DBG_TEA, "================error flag: %d=================.\n", error_flag); + msg(DBG_INF,"sbp_data: read aborted by drive.\n"); +#if 1 + i=cc_DriveReset(); /* ugly fix to prevent a hang */ +#else + i=cc_ReadError(); #endif - up(&ioctl_read_sem); - spin_lock_irq(q->queue_lock); - end_request(req, 1); - goto request_loop; + return (0); } - -#ifdef FUTURE - i=prepare(0,0); /* at moment not really a hassle check, but ... */ - if (i!=0) - msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i); -#endif /* FUTURE */ - - if (!st_spinning) cc_SpinUp(); - for (data_tries=n_retries; data_tries > 0; data_tries--) + if (fam0LV_drive) { - for (status_tries=3; status_tries > 0; status_tries--) + SBPCD_CLI; + i=maxtim_data; + for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--) { - flags_cmd_out |= f_respo3; - cc_ReadStatus(); - if (sbp_status() != 0) break; - if (st_check) cc_ReadError(); - sbp_sleep(1); /* wait a bit, try again */ + for ( ;i!=0;i--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) break; + if (!(j&s_not_result_ready)) break; + if (j&s_attention) break; + } + if (i != 0 || time_after_eq(jiffies, timeout)) break; + sbp_sleep(0); + i = 1; } - if (status_tries == 0) + if (i==0) msg(DBG_INF,"status timeout after READ.\n"); + if (!(j&s_attention)) { - msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__); - break; + msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n"); + i=cc_DriveReset(); /* ugly fix to prevent a hang */ + SBPCD_STI; + return (0); } - - sbp_read_cmd(req); - sbp_sleep(0); - if (sbp_data(req) != 0) + SBPCD_STI; + } + +#if 0 + if (!success) +#endif + do { -#ifdef SAFE_MIXED - current_drive->has_data=2; /* is really a data disk */ -#endif /* SAFE_MIXED */ -#ifdef DEBUG_GTL - printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n", - xnr, req, req->sector, req->nr_sectors, jiffies); + if (fam0LV_drive) cc_ReadStatus(); +#if 1 + if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i); #endif - up(&ioctl_read_sem); - spin_lock_irq(q->queue_lock); - end_request(req, 1); - goto request_loop; + i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ +#if 1 + if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i); +#endif + if (i<0) + { + msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits); + return (0); + } } + while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success))); + if (st_check) + { + i=cc_ReadError(); + msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i); + return (0); + } + if (fatal_err) + { + fatal_err=0; + current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ + current_drive->sbp_current = 0; + msg(DBG_INF,"sbp_data: fatal_err - retrying.\n"); + return (0); } - err_done: -#if OLD_BUSY - busy_data=0; -#endif /* OLD_BUSY */ -#ifdef DEBUG_GTL - printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n", - xnr, req, req->sector, req->nr_sectors, jiffies); -#endif - up(&ioctl_read_sem); - sbp_sleep(0); /* wait a bit, try again */ - spin_lock_irq(q->queue_lock); - end_request(req, 0); - goto request_loop; + current_drive->sbp_first_frame = req -> sector / 4; + current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1; + sbp_transfer(req); + return (1); } /*==========================================================================*/ -/* - * build and send the READ command. - */ -static void sbp_read_cmd(struct request *req) + +static int sbpcd_block_open(struct inode *inode, struct file *file) { -#undef OLD + struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; + return cdrom_open(p->sbpcd_infop, inode, file); +} - int i; - int block; +static int sbpcd_block_release(struct inode *inode, struct file *file) +{ + struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; + return cdrom_release(p->sbpcd_infop, file); +} + +static int sbpcd_block_ioctl(struct inode *inode, struct file *file, + unsigned cmd, unsigned long arg) +{ + struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; + struct cdrom_device_info *cdi = p->sbpcd_infop; + int ret, i; + + ret = cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg); + if (ret != -ENOSYS) + return ret; + + msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg); + if (p->drv_id==-1) { + msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); + return (-ENXIO); /* no such drive */ + } + down(&ioctl_read_sem); + if (p != current_drive) + switch_drive(p); - current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ - current_drive->sbp_current = 0; - block=req->sector/4; - if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm) - current_drive->sbp_read_frames = current_drive->sbp_bufsiz; - else + msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); + switch (cmd) /* Sun-compatible */ { - current_drive->sbp_read_frames=current_drive->CDsize_frm-block; - /* avoid reading past end of data */ - if (current_drive->sbp_read_frames < 1) + case DDIOCSDBG: /* DDI Debug */ + if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM); + i=sbpcd_dbg_ioctl(arg,1); + RETURN_UP(i); + case CDROMRESET: /* hard reset the drive */ + msg(DBG_IOC,"ioctl: CDROMRESET entered.\n"); + i=DriveReset(); + current_drive->audio_state=0; + RETURN_UP(i); + + case CDROMREADMODE1: + msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); +#ifdef SAFE_MIXED + if (current_drive->has_data>1) RETURN_UP(-EBUSY); +#endif /* SAFE_MIXED */ + cc_ModeSelect(CD_FRAMESIZE); + cc_ModeSense(); + current_drive->mode=READ_M1; + RETURN_UP(0); + + case CDROMREADMODE2: /* not usable at the moment */ + msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); +#ifdef SAFE_MIXED + if (current_drive->has_data>1) RETURN_UP(-EBUSY); +#endif /* SAFE_MIXED */ + cc_ModeSelect(CD_FRAMESIZE_RAW1); + cc_ModeSense(); + current_drive->mode=READ_M2; + RETURN_UP(0); + + case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */ + msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n"); + if (current_drive->sbp_audsiz>0) + vfree(current_drive->aud_buf); + current_drive->aud_buf=NULL; + current_drive->sbp_audsiz=arg; + + if (current_drive->sbp_audsiz>16) { - msg(DBG_INF,"requested frame %d, CD size %d ???\n", - block, current_drive->CDsize_frm); - current_drive->sbp_read_frames=1; + current_drive->sbp_audsiz = 0; + RETURN_UP(current_drive->sbp_audsiz); } - } - flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; - clr_cmdbuf(); - if (famV_drive) - { - drvcmd[0]=CMDV_READ; - lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ - bin2bcdx(&drvcmd[1]); - bin2bcdx(&drvcmd[2]); - bin2bcdx(&drvcmd[3]); - drvcmd[4]=current_drive->sbp_read_frames>>8; - drvcmd[5]=current_drive->sbp_read_frames&0xff; - drvcmd[6]=0x02; /* flag "msf-bcd" */ - } - else if (fam0L_drive) - { - flags_cmd_out |= f_lopsta | f_getsta | f_bit1; - if (current_drive->xa_byte==0x20) + if (current_drive->sbp_audsiz>0) { - cmd_type=READ_M2; - drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ - drvcmd[1]=(block>>16)&0x0ff; - drvcmd[2]=(block>>8)&0x0ff; - drvcmd[3]=block&0x0ff; - drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; - drvcmd[5]=current_drive->sbp_read_frames&0x0ff; + current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW); + if (current_drive->aud_buf==NULL) + { + msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz); + current_drive->sbp_audsiz=0; + } + else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz); } - else + RETURN_UP(current_drive->sbp_audsiz); + + case CDROMREADAUDIO: + { /* start of CDROMREADAUDIO */ + int i=0, j=0, frame, block=0; + u_int try=0; + u_long timeout; + u_char *p; + u_int data_tries = 0; + u_int data_waits = 0; + u_int data_retrying = 0; + int status_tries; + int error_flag; + + msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n"); + if (fam0_drive) RETURN_UP(-EINVAL); + if (famL_drive) RETURN_UP(-EINVAL); + if (famV_drive) RETURN_UP(-EINVAL); + if (famT_drive) RETURN_UP(-EINVAL); +#ifdef SAFE_MIXED + if (current_drive->has_data>1) RETURN_UP(-EBUSY); +#endif /* SAFE_MIXED */ + if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL); + if (copy_from_user(&read_audio, (void __user *)arg, + sizeof(struct cdrom_read_audio))) + RETURN_UP(-EFAULT); + if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL); + if (!access_ok(VERIFY_WRITE, read_audio.buf, + read_audio.nframes*CD_FRAMESIZE_RAW)) + RETURN_UP(-EFAULT); + + if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */ + block=msf2lba(&read_audio.addr.msf.minute); + else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */ + block=read_audio.addr.lba; + else RETURN_UP(-EINVAL); +#if 000 + i=cc_SetSpeed(speed_150,0,0); + if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i); +#endif + msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n", + block, blk2msf(block)); + msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n"); +#if OLD_BUSY + while (busy_data) sbp_sleep(HZ/10); /* wait a bit */ + busy_audio=1; +#endif /* OLD_BUSY */ + error_flag=0; + for (data_tries=5; data_tries>0; data_tries--) { - drvcmd[0]=CMD0_READ; /* "read frames", old drives */ - if (current_drive->drv_type>=drv_201) + msg(DBG_AUD,"data_tries=%d ...\n", data_tries); + current_drive->mode=READ_AU; + cc_ModeSelect(CD_FRAMESIZE_RAW); + cc_ModeSense(); + for (status_tries=3; status_tries > 0; status_tries--) { - lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ - bin2bcdx(&drvcmd[1]); - bin2bcdx(&drvcmd[2]); - bin2bcdx(&drvcmd[3]); + flags_cmd_out |= f_respo3; + cc_ReadStatus(); + if (sbp_status() != 0) break; + if (st_check) cc_ReadError(); + sbp_sleep(1); /* wait a bit, try again */ } - else + if (status_tries == 0) { - drvcmd[1]=(block>>16)&0x0ff; - drvcmd[2]=(block>>8)&0x0ff; - drvcmd[3]=block&0x0ff; + msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__); + continue; } - drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; - drvcmd[5]=current_drive->sbp_read_frames&0x0ff; - drvcmd[6]=(current_drive->drv_typesbp_read_frames>>8)&0x0ff; - drvcmd[6]=current_drive->sbp_read_frames&0x0ff; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_READ; - lba2msf(block,&drvcmd[1]); /* msf-bin format required */ - drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; - drvcmd[5]=current_drive->sbp_read_frames&0x0ff; - drvcmd[6]=0x02; - } - else if (famT_drive) - { - drvcmd[0]=CMDT_READ; - drvcmd[2]=(block>>24)&0x0ff; - drvcmd[3]=(block>>16)&0x0ff; - drvcmd[4]=(block>>8)&0x0ff; - drvcmd[5]=block&0x0ff; - drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff; - drvcmd[8]=current_drive->sbp_read_frames&0x0ff; - } - flags_cmd_out=f_putcmd; - response_count=0; - i=cmd_out(); - if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i); - return; -} -/*==========================================================================*/ -/* - * Check the completion of the read-data command. On success, read - * the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer. - */ -static int sbp_data(struct request *req) -{ - int i=0, j=0, l, frame; - u_int try=0; - u_long timeout; - u_char *p; - u_int data_tries = 0; - u_int data_waits = 0; - u_int data_retrying = 0; - int error_flag; - int xa_count; - int max_latency; - int success; - int wait; - int duration; - - error_flag=0; - success=0; -#if LONG_TIMING - max_latency=9*HZ; -#else - if (current_drive->f_multisession) max_latency=15*HZ; - else max_latency=5*HZ; -#endif - duration=jiffies; - for (frame=0;framesbp_read_frames&&!error_flag; frame++) - { - SBPCD_CLI; - - del_timer(&data_timer); - data_timer.expires=jiffies+max_latency; - timed_out_data=0; - add_timer(&data_timer); - while (!timed_out_data) - { - if (current_drive->f_multisession) try=maxtim_data*4; - else try=maxtim_data; - msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try); - for ( ; try!=0;try--) + msg(DBG_AUD,"read_audio: sbp_status: ok.\n"); + + flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; + if (fam0L_drive) { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) break; - if (!(j&s_not_result_ready)) break; - if (fam0LV_drive) if (j&s_attention) break; + flags_cmd_out |= f_lopsta | f_getsta | f_bit1; + cmd_type=READ_M2; + drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ + drvcmd[1]=(block>>16)&0x000000ff; + drvcmd[2]=(block>>8)&0x000000ff; + drvcmd[3]=block&0x000000ff; + drvcmd[4]=0; + drvcmd[5]=read_audio.nframes; /* # of frames */ + drvcmd[6]=0; } - if (!(j&s_not_data_ready)) goto data_ready; - if (try==0) + else if (fam1_drive) { - if (data_retrying == 0) data_waits++; - data_retrying = 1; - msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n"); - sbp_sleep(1); - try = 1; + drvcmd[0]=CMD1_READ; /* "read frames", new drives */ + lba2msf(block,&drvcmd[1]); /* msf-bin format required */ + drvcmd[4]=0; + drvcmd[5]=0; + drvcmd[6]=read_audio.nframes; /* # of frames */ } - } - msg(DBG_INF,"sbp_data: CDi_status loop expired.\n"); - data_ready: - del_timer(&data_timer); - - if (timed_out_data) - { - msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j); - error_flag++; - } - if (try==0) - { - msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j); - error_flag++; - } - if (!(j&s_not_result_ready)) - { - msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j); - response_count=20; - j=ResponseInfo(); - j=inb(CDi_status); - } - if (j&s_not_data_ready) - { - if ((current_drive->ored_ctl_adr&0x40)==0) - msg(DBG_INF, "CD contains no data tracks.\n"); - else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j); - error_flag++; - } - SBPCD_STI; - if (error_flag) break; - - msg(DBG_000, "sbp_data: beginning to read.\n"); - p = current_drive->sbp_buf + frame * CD_FRAMESIZE; - if (sbpro_type==1) OUT(CDo_sel_i_d,1); - if (cmd_type==READ_M2) { - if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1); - else insb(CDi_data, xa_head_buf, CD_XA_HEAD); - } - if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1); - else insb(CDi_data, p, CD_FRAMESIZE); - if (cmd_type==READ_M2) { - if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1); - else insb(CDi_data, xa_tail_buf, CD_XA_TAIL); - } - current_drive->sbp_current++; - if (sbpro_type==1) OUT(CDo_sel_i_d,0); - if (cmd_type==READ_M2) - { - for (xa_count=0;xa_count= 1000) - { - msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries); - data_waits = data_tries = 0; - } - } - duration=jiffies-duration; - msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration); - if (famT_drive) - { - wait=8; - do - { - if (teac==2) - { - if ((i=CDi_stat_loop_T()) == -1) break; - } - else - { - sbp_sleep(1); - OUT(CDo_sel_i_d,0); - i=inb(CDi_status); - } - if (!(i&s_not_data_ready)) + else if (fam2_drive) { - OUT(CDo_sel_i_d,1); - j=0; - do + drvcmd[0]=CMD2_READ_XA2; + lba2msf(block,&drvcmd[1]); /* msf-bin format required */ + drvcmd[4]=0; + drvcmd[5]=read_audio.nframes; /* # of frames */ + drvcmd[6]=0x11; /* raw mode */ + } + else if (famT_drive) /* CD-55A: not tested yet */ + { + } + msg(DBG_AUD,"read_audio: before giving \"read\" command.\n"); + flags_cmd_out=f_putcmd; + response_count=0; + i=cmd_out(); + if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i); + sbp_sleep(0); + msg(DBG_AUD,"read_audio: after giving \"read\" command.\n"); + for (frame=1;frame<2 && !error_flag; frame++) + { + try=maxtim_data; + for (timeout=jiffies+9*HZ; ; ) { - if (do_16bit) i=inw(CDi_data); - else i=inb(CDi_data); - j++; - i=inb(CDi_status); + for ( ; try!=0;try--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) break; + if (!(j&s_not_result_ready)) break; + if (fam0L_drive) if (j&s_attention) break; + } + if (try != 0 || time_after_eq(jiffies, timeout)) break; + if (data_retrying == 0) data_waits++; + data_retrying = 1; + sbp_sleep(1); + try = 1; } - while (!(i&s_not_data_ready)); - msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j); - } - if (!(i&s_not_result_ready)) - { - OUT(CDo_sel_i_d,0); - l=0; - do + if (try==0) { - infobuf[l++]=inb(CDi_info); - i=inb(CDi_status); + msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n"); + error_flag++; + break; } - while (!(i&s_not_result_ready)); - if (infobuf[0]==0x00) success=1; -#if 1 - for (j=0;j1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion); - else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n"); - clr_cmdbuf(); - drvcmd[0]=CMDT_READ_ERR; - j=cmd_out_T(); /* !!! recursive here !!! */ - --recursion; - sbp_sleep(1); + break; + } + msg(DBG_AUD,"read_audio: before reading data.\n"); + error_flag=0; + p = current_drive->aud_buf; + if (sbpro_type==1) OUT(CDo_sel_i_d,1); + if (do_16bit) + { + u_short *p2 = (u_short *) p; + + for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) + { + if ((inb_p(CDi_status)&s_not_data_ready)) continue; + + /* get one sample */ + *p2++ = inw_p(CDi_data); + *p2++ = inw_p(CDi_data); + } + } else { + for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) + { + if ((inb_p(CDi_status)&s_not_data_ready)) continue; + + /* get one sample */ + *p++ = inb_p(CDi_data); + *p++ = inb_p(CDi_data); + *p++ = inb_p(CDi_data); + *p++ = inb_p(CDi_data); } - while (j<0); - current_drive->error_state=infobuf[2]; - current_drive->b3=infobuf[3]; - current_drive->b4=infobuf[4]; } - break; + if (sbpro_type==1) OUT(CDo_sel_i_d,0); + data_retrying = 0; } - else + msg(DBG_AUD,"read_audio: after reading data.\n"); + if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ { -#if 0 - msg(DBG_TEA, "============= waiting for result=================.\n"); - sbp_sleep(1); -#endif - } - } - while (wait--); - } - - if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ - { - msg(DBG_TEA, "================error flag: %d=================.\n", error_flag); - msg(DBG_INF,"sbp_data: read aborted by drive.\n"); -#if 1 - i=cc_DriveReset(); /* ugly fix to prevent a hang */ + msg(DBG_AUD,"read_audio: read aborted by drive\n"); +#if 0000 + i=cc_DriveReset(); /* ugly fix to prevent a hang */ #else - i=cc_ReadError(); + i=cc_ReadError(); #endif - return (0); - } - - if (fam0LV_drive) - { - SBPCD_CLI; - i=maxtim_data; - for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--) - { - for ( ;i!=0;i--) + continue; + } + if (fam0L_drive) { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) break; - if (!(j&s_not_result_ready)) break; - if (j&s_attention) break; + i=maxtim_data; + for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--) + { + for ( ;i!=0;i--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) break; + if (!(j&s_not_result_ready)) break; + if (j&s_attention) break; + } + if (i != 0 || time_after_eq(jiffies, timeout)) break; + sbp_sleep(0); + i = 1; + } + if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ"); + if (!(j&s_attention)) + { + msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n"); + i=cc_DriveReset(); /* ugly fix to prevent a hang */ + continue; + } } - if (i != 0 || time_after_eq(jiffies, timeout)) break; - sbp_sleep(0); - i = 1; - } - if (i==0) msg(DBG_INF,"status timeout after READ.\n"); - if (!(j&s_attention)) - { - msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n"); - i=cc_DriveReset(); /* ugly fix to prevent a hang */ - SBPCD_STI; - return (0); - } - SBPCD_STI; - } - -#if 0 - if (!success) -#endif - do - { - if (fam0LV_drive) cc_ReadStatus(); -#if 1 - if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i); -#endif - i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ -#if 1 - if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i); -#endif - if (i<0) + do { - msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits); - return (0); + if (fam0L_drive) cc_ReadStatus(); + i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ + if (i<0) { msg(DBG_AUD, + "read_audio: cc_ReadStatus error after read: %02X\n", + current_drive->status_bits); + continue; /* FIXME */ + } + } + while ((fam0L_drive)&&(!st_check)&&(!(i&p_success))); + if (st_check) + { + i=cc_ReadError(); + msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i); + continue; } + if (copy_to_user(read_audio.buf, + current_drive->aud_buf, + read_audio.nframes * CD_FRAMESIZE_RAW)) + RETURN_UP(-EFAULT); + msg(DBG_AUD,"read_audio: copy_to_user done.\n"); + break; } - while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success))); - if (st_check) - { - i=cc_ReadError(); - msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i); - return (0); - } - if (fatal_err) - { - fatal_err=0; - current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ - current_drive->sbp_current = 0; - msg(DBG_INF,"sbp_data: fatal_err - retrying.\n"); - return (0); - } - - current_drive->sbp_first_frame = req -> sector / 4; - current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1; - sbp_transfer(req); - return (1); -} -/*==========================================================================*/ - -static int sbpcd_block_open(struct inode *inode, struct file *file) -{ - struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; - return cdrom_open(p->sbpcd_infop, inode, file); -} - -static int sbpcd_block_release(struct inode *inode, struct file *file) -{ - struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; - return cdrom_release(p->sbpcd_infop, file); -} + cc_ModeSelect(CD_FRAMESIZE); + cc_ModeSense(); + current_drive->mode=READ_M1; +#if OLD_BUSY + busy_audio=0; +#endif /* OLD_BUSY */ + if (data_tries == 0) + { + msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__); + RETURN_UP(-EIO); + } + msg(DBG_AUD,"read_audio: successful return.\n"); + RETURN_UP(0); + } /* end of CDROMREADAUDIO */ -static int sbpcd_block_ioctl(struct inode *inode, struct file *file, - unsigned cmd, unsigned long arg) -{ - struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; - return cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg); + default: + msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); + RETURN_UP(-EINVAL); + } /* end switch(cmd) */ } static int sbpcd_block_media_changed(struct gendisk *disk) @@ -5478,10 +5471,9 @@ static struct cdrom_device_ops sbpcd_dops = { .get_mcn = sbpcd_get_mcn, .reset = sbpcd_reset, .audio_ioctl = sbpcd_audio_ioctl, - .dev_ioctl = sbpcd_dev_ioctl, .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | - CDC_MCN | CDC_PLAY_AUDIO | CDC_IOCTLS, + CDC_MCN | CDC_PLAY_AUDIO, .n_minors = 1, }; diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index e27617259552..c0f817ba7adb 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -627,7 +627,7 @@ static struct cdrom_device_ops viocd_dops = { .media_changed = viocd_media_changed, .lock_door = viocd_lock_door, .generic_packet = viocd_packet, - .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM + .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM }; static int __init find_capability(const char *type) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 3325660f7248..430d8af35cb1 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -2470,52 +2470,6 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi, return cgc->stat; } -static -int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi, - unsigned int cmd, unsigned long arg) -{ - struct packet_command cgc; - char buffer[16]; - int stat; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN); - - /* These will be moved into the Uniform layer shortly... */ - switch (cmd) { - case CDROMSETSPINDOWN: { - char spindown; - - if (copy_from_user(&spindown, (void __user *) arg, sizeof(char))) - return -EFAULT; - - if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0))) - return stat; - - buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f); - - return cdrom_mode_select(cdi, &cgc); - } - - case CDROMGETSPINDOWN: { - char spindown; - - if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0))) - return stat; - - spindown = buffer[11] & 0x0f; - - if (copy_to_user((void __user *) arg, &spindown, sizeof (char))) - return -EFAULT; - - return 0; - } - - default: - return -EINVAL; - } - -} - static int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, unsigned int cmd, void *arg) @@ -2852,12 +2806,11 @@ static struct cdrom_device_ops ide_cdrom_dops = { .get_mcn = ide_cdrom_get_mcn, .reset = ide_cdrom_reset, .audio_ioctl = ide_cdrom_audio_ioctl, - .dev_ioctl = ide_cdrom_dev_ioctl, .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | - CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R | + CDC_DRIVE_STATUS | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM | CDC_GENERIC_PACKET | CDC_MO_DRIVE | CDC_MRW | CDC_MRW_W | CDC_RAM, @@ -3367,6 +3320,45 @@ static int idecd_release(struct inode * inode, struct file * file) return 0; } +static int idecd_set_spindown(struct cdrom_device_info *cdi, unsigned long arg) +{ + struct packet_command cgc; + char buffer[16]; + int stat; + char spindown; + + if (copy_from_user(&spindown, (void __user *)arg, sizeof(char))) + return -EFAULT; + + init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN); + + stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0); + if (stat) + return stat; + + buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f); + return cdrom_mode_select(cdi, &cgc); +} + +static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg) +{ + struct packet_command cgc; + char buffer[16]; + int stat; + char spindown; + + init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN); + + stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0); + if (stat) + return stat; + + spindown = buffer[11] & 0x0f; + if (copy_to_user((void __user *)arg, &spindown, sizeof (char))) + return -EFAULT; + return 0; +} + static int idecd_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -3374,7 +3366,16 @@ static int idecd_ioctl (struct inode *inode, struct file *file, struct cdrom_info *info = ide_cd_g(bdev->bd_disk); int err; - err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg); + switch (cmd) { + case CDROMSETSPINDOWN: + return idecd_set_spindown(&info->devinfo, arg); + case CDROMGETSPINDOWN: + return idecd_get_spindown(&info->devinfo, arg); + default: + break; + } + + err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg); if (err == -EINVAL) err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index f9c1192dc15e..7c80711e18ed 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -71,7 +71,7 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR); #define SR_CAPABILITIES \ (CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK|CDC_SELECT_SPEED| \ CDC_SELECT_DISC|CDC_MULTI_SESSION|CDC_MCN|CDC_MEDIA_CHANGED| \ - CDC_PLAY_AUDIO|CDC_RESET|CDC_IOCTLS|CDC_DRIVE_STATUS| \ + CDC_PLAY_AUDIO|CDC_RESET|CDC_DRIVE_STATUS| \ CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \ CDC_MRW|CDC_MRW_W|CDC_RAM) @@ -118,7 +118,6 @@ static struct cdrom_device_ops sr_dops = { .get_mcn = sr_get_mcn, .reset = sr_reset, .audio_ioctl = sr_audio_ioctl, - .dev_ioctl = sr_dev_ioctl, .capability = SR_CAPABILITIES, .generic_packet = sr_packet, }; @@ -456,17 +455,33 @@ static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd, { struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk); struct scsi_device *sdev = cd->device; + void __user *argp = (void __user *)arg; + int ret; - /* - * Send SCSI addressing ioctls directly to mid level, send other - * ioctls to cdrom/block level. - */ - switch (cmd) { - case SCSI_IOCTL_GET_IDLUN: - case SCSI_IOCTL_GET_BUS_NUMBER: - return scsi_ioctl(sdev, cmd, (void __user *)arg); + /* + * Send SCSI addressing ioctls directly to mid level, send other + * ioctls to cdrom/block level. + */ + switch (cmd) { + case SCSI_IOCTL_GET_IDLUN: + case SCSI_IOCTL_GET_BUS_NUMBER: + return scsi_ioctl(sdev, cmd, argp); } - return cdrom_ioctl(file, &cd->cdi, inode, cmd, arg); + + ret = cdrom_ioctl(file, &cd->cdi, inode, cmd, arg); + if (ret != ENOSYS) + return ret; + + /* + * ENODEV means that we didn't recognise the ioctl, or that we + * cannot execute it in the current device state. In either + * case fall through to scsi_ioctl, which will return ENDOEV again + * if it doesn't recognise the ioctl + */ + ret = scsi_nonblockable_ioctl(sdev, cmd, argp, NULL); + if (ret != -ENODEV) + return ret; + return scsi_ioctl(sdev, cmd, argp); } static int sr_block_media_changed(struct gendisk *disk) diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h index d2bcd99c272f..d65de9621b27 100644 --- a/drivers/scsi/sr.h +++ b/drivers/scsi/sr.h @@ -55,7 +55,6 @@ int sr_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *); int sr_reset(struct cdrom_device_info *); int sr_select_speed(struct cdrom_device_info *cdi, int speed); int sr_audio_ioctl(struct cdrom_device_info *, unsigned int, void *); -int sr_dev_ioctl(struct cdrom_device_info *, unsigned int, unsigned long); int sr_is_xa(Scsi_CD *); diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index b65462f76484..d1268cb46837 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -562,22 +562,3 @@ int sr_is_xa(Scsi_CD *cd) #endif return is_xa; } - -int sr_dev_ioctl(struct cdrom_device_info *cdi, - unsigned int cmd, unsigned long arg) -{ - Scsi_CD *cd = cdi->handle; - int ret; - - ret = scsi_nonblockable_ioctl(cd->device, cmd, - (void __user *)arg, NULL); - /* - * ENODEV means that we didn't recognise the ioctl, or that we - * cannot execute it in the current device state. In either - * case fall through to scsi_ioctl, which will return ENDOEV again - * if it doesn't recognise the ioctl - */ - if (ret != -ENODEV) - return ret; - return scsi_ioctl(cd->device, cmd, (void __user *)arg); -} diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h index b68fdf1f3156..3c9b0bc05123 100644 --- a/include/linux/cdrom.h +++ b/include/linux/cdrom.h @@ -378,7 +378,6 @@ struct cdrom_generic_command #define CDC_MEDIA_CHANGED 0x80 /* media changed */ #define CDC_PLAY_AUDIO 0x100 /* audio functions */ #define CDC_RESET 0x200 /* hard reset device */ -#define CDC_IOCTLS 0x400 /* driver has non-standard ioctls */ #define CDC_DRIVE_STATUS 0x800 /* driver implements drive status */ #define CDC_GENERIC_PACKET 0x1000 /* driver implements generic packets */ #define CDC_CD_R 0x2000 /* drive is a CD-R */ @@ -974,9 +973,7 @@ struct cdrom_device_ops { int (*reset) (struct cdrom_device_info *); /* play stuff */ int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *); - /* dev-specific */ - int (*dev_ioctl) (struct cdrom_device_info *, - unsigned int, unsigned long); + /* driver specifications */ const int capability; /* capability flags */ int n_minors; /* number of active minor devices */ -- cgit v1.2.3-59-g8ed1b From 9cdf18279d1f4a2d075ebe924d74e6e4547f6e1b Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 23 Mar 2006 03:00:21 -0800 Subject: [PATCH] sem2mutex: kcapi.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 Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/capi/kcapi.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index feec40cf5900..8c4fcb9027b3 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -32,6 +32,7 @@ #ifdef CONFIG_AVMB1_COMPAT #include #endif +#include static char *revision = "$Revision: 1.1.2.8 $"; @@ -66,7 +67,7 @@ LIST_HEAD(capi_drivers); DEFINE_RWLOCK(capi_drivers_list_lock); static DEFINE_RWLOCK(application_lock); -static DECLARE_MUTEX(controller_sem); +static DEFINE_MUTEX(controller_mutex); struct capi20_appl *capi_applications[CAPI_MAXAPPL]; struct capi_ctr *capi_cards[CAPI_MAXCONTR]; @@ -395,20 +396,20 @@ attach_capi_ctr(struct capi_ctr *card) { int i; - down(&controller_sem); + mutex_lock(&controller_mutex); for (i = 0; i < CAPI_MAXCONTR; i++) { if (capi_cards[i] == NULL) break; } if (i == CAPI_MAXCONTR) { - up(&controller_sem); + mutex_unlock(&controller_mutex); printk(KERN_ERR "kcapi: out of controller slots\n"); return -EBUSY; } capi_cards[i] = card; - up(&controller_sem); + mutex_unlock(&controller_mutex); card->nrecvctlpkt = 0; card->nrecvdatapkt = 0; @@ -531,13 +532,13 @@ u16 capi20_register(struct capi20_appl *ap) write_unlock_irqrestore(&application_lock, flags); - down(&controller_sem); + mutex_lock(&controller_mutex); for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING) continue; register_appl(capi_cards[i], applid, &ap->rparam); } - up(&controller_sem); + mutex_unlock(&controller_mutex); if (showcapimsgs & 1) { printk(KERN_DEBUG "kcapi: appl %d up\n", applid); @@ -560,13 +561,13 @@ u16 capi20_release(struct capi20_appl *ap) capi_applications[ap->applid - 1] = NULL; write_unlock_irqrestore(&application_lock, flags); - down(&controller_sem); + mutex_lock(&controller_mutex); for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING) continue; release_appl(capi_cards[i], ap->applid); } - up(&controller_sem); + mutex_unlock(&controller_mutex); flush_scheduled_work(); skb_queue_purge(&ap->recv_queue); -- cgit v1.2.3-59-g8ed1b From 8ed965d612d9e9bc08805c75123f063cf6966311 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 23 Mar 2006 03:00:21 -0800 Subject: [PATCH] sem2mutex: drivers: raw, connector, dcdbas, ppp_generic 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: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/raw.c | 23 ++++++++++++----------- drivers/connector/connector.c | 15 ++++++++------- drivers/firmware/dcdbas.c | 23 ++++++++++++----------- drivers/net/ppp_generic.c | 25 +++++++++++++------------ 4 files changed, 45 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 30e4cbe16bb0..15a7b4086524 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -29,7 +30,7 @@ struct raw_device_data { static struct class *raw_class; static struct raw_device_data raw_devices[MAX_RAW_MINORS]; -static DECLARE_MUTEX(raw_mutex); +static DEFINE_MUTEX(raw_mutex); static struct file_operations raw_ctl_fops; /* forward declaration */ /* @@ -53,7 +54,7 @@ static int raw_open(struct inode *inode, struct file *filp) return 0; } - down(&raw_mutex); + mutex_lock(&raw_mutex); /* * All we need to do on open is check that the device is bound. @@ -78,7 +79,7 @@ static int raw_open(struct inode *inode, struct file *filp) filp->f_dentry->d_inode->i_mapping = bdev->bd_inode->i_mapping; filp->private_data = bdev; - up(&raw_mutex); + mutex_unlock(&raw_mutex); return 0; out2: @@ -86,7 +87,7 @@ out2: out1: blkdev_put(bdev); out: - up(&raw_mutex); + mutex_unlock(&raw_mutex); return err; } @@ -99,14 +100,14 @@ static int raw_release(struct inode *inode, struct file *filp) const int minor= iminor(inode); struct block_device *bdev; - down(&raw_mutex); + mutex_lock(&raw_mutex); bdev = raw_devices[minor].binding; if (--raw_devices[minor].inuse == 0) { /* Here inode->i_mapping == bdev->bd_inode->i_mapping */ inode->i_mapping = &inode->i_data; inode->i_mapping->backing_dev_info = &default_backing_dev_info; } - up(&raw_mutex); + mutex_unlock(&raw_mutex); bd_release(bdev); blkdev_put(bdev); @@ -187,9 +188,9 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp, goto out; } - down(&raw_mutex); + mutex_lock(&raw_mutex); if (rawdev->inuse) { - up(&raw_mutex); + mutex_unlock(&raw_mutex); err = -EBUSY; goto out; } @@ -211,11 +212,11 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp, bind_device(&rq); } } - up(&raw_mutex); + mutex_unlock(&raw_mutex); } else { struct block_device *bdev; - down(&raw_mutex); + mutex_lock(&raw_mutex); bdev = rawdev->binding; if (bdev) { rq.block_major = MAJOR(bdev->bd_dev); @@ -223,7 +224,7 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp, } else { rq.block_major = rq.block_minor = 0; } - up(&raw_mutex); + mutex_unlock(&raw_mutex); if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) { err = -EFAULT; goto out; diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index d7125f4d9113..35897079a78d 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -41,7 +42,7 @@ module_param(cn_val, uint, 0); MODULE_PARM_DESC(cn_idx, "Connector's main device idx."); MODULE_PARM_DESC(cn_val, "Connector's main device val."); -static DECLARE_MUTEX(notify_lock); +static DEFINE_MUTEX(notify_lock); static LIST_HEAD(notify_list); static struct cn_dev cdev; @@ -260,7 +261,7 @@ static void cn_notify(struct cb_id *id, u32 notify_event) { struct cn_ctl_entry *ent; - down(¬ify_lock); + mutex_lock(¬ify_lock); list_for_each_entry(ent, ¬ify_list, notify_entry) { int i; struct cn_notify_req *req; @@ -293,7 +294,7 @@ static void cn_notify(struct cb_id *id, u32 notify_event) cn_netlink_send(&m, ctl->group, GFP_KERNEL); } } - up(¬ify_lock); + mutex_unlock(¬ify_lock); } /* @@ -407,14 +408,14 @@ static void cn_callback(void *data) if (ctl->group == 0) { struct cn_ctl_entry *n; - down(¬ify_lock); + mutex_lock(¬ify_lock); list_for_each_entry_safe(ent, n, ¬ify_list, notify_entry) { if (cn_ctl_msg_equals(ent->msg, ctl)) { list_del(&ent->notify_entry); kfree(ent); } } - up(¬ify_lock); + mutex_unlock(¬ify_lock); return; } @@ -429,9 +430,9 @@ static void cn_callback(void *data) memcpy(ent->msg, ctl, size - sizeof(*ent)); - down(¬ify_lock); + mutex_lock(¬ify_lock); list_add(&ent->notify_entry, ¬ify_list); - up(¬ify_lock); + mutex_unlock(¬ify_lock); } static int __init cn_init(void) diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 3a4e5c5b4e1f..d6543fc4a923 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -48,7 +49,7 @@ static u8 *smi_data_buf; static dma_addr_t smi_data_buf_handle; static unsigned long smi_data_buf_size; static u32 smi_data_buf_phys_addr; -static DECLARE_MUTEX(smi_data_lock); +static DEFINE_MUTEX(smi_data_lock); static unsigned int host_control_action; static unsigned int host_control_smi_type; @@ -139,9 +140,9 @@ static ssize_t smi_data_buf_size_store(struct device *dev, buf_size = simple_strtoul(buf, NULL, 10); /* make sure SMI data buffer is at least buf_size */ - down(&smi_data_lock); + mutex_lock(&smi_data_lock); ret = smi_data_buf_realloc(buf_size); - up(&smi_data_lock); + mutex_unlock(&smi_data_lock); if (ret) return ret; @@ -154,7 +155,7 @@ static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos, size_t max_read; ssize_t ret; - down(&smi_data_lock); + mutex_lock(&smi_data_lock); if (pos >= smi_data_buf_size) { ret = 0; @@ -165,7 +166,7 @@ static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos, ret = min(max_read, count); memcpy(buf, smi_data_buf + pos, ret); out: - up(&smi_data_lock); + mutex_unlock(&smi_data_lock); return ret; } @@ -174,7 +175,7 @@ static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos, { ssize_t ret; - down(&smi_data_lock); + mutex_lock(&smi_data_lock); ret = smi_data_buf_realloc(pos + count); if (ret) @@ -183,7 +184,7 @@ static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos, memcpy(smi_data_buf + pos, buf, count); ret = count; out: - up(&smi_data_lock); + mutex_unlock(&smi_data_lock); return ret; } @@ -201,9 +202,9 @@ static ssize_t host_control_action_store(struct device *dev, ssize_t ret; /* make sure buffer is available for host control command */ - down(&smi_data_lock); + mutex_lock(&smi_data_lock); ret = smi_data_buf_realloc(sizeof(struct apm_cmd)); - up(&smi_data_lock); + mutex_unlock(&smi_data_lock); if (ret) return ret; @@ -302,7 +303,7 @@ static ssize_t smi_request_store(struct device *dev, unsigned long val = simple_strtoul(buf, NULL, 10); ssize_t ret; - down(&smi_data_lock); + mutex_lock(&smi_data_lock); if (smi_data_buf_size < sizeof(struct smi_cmd)) { ret = -ENODEV; @@ -334,7 +335,7 @@ static ssize_t smi_request_store(struct device *dev, } out: - up(&smi_data_lock); + mutex_unlock(&smi_data_lock); return ret; } diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index f608c12e3e8b..b2073fce8216 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -198,11 +199,11 @@ static unsigned int cardmap_find_first_free(struct cardmap *map); static void cardmap_destroy(struct cardmap **map); /* - * all_ppp_sem protects the all_ppp_units mapping. + * all_ppp_mutex protects the all_ppp_units mapping. * It also ensures that finding a ppp unit in the all_ppp_units map * and updating its file.refcnt field is atomic. */ -static DECLARE_MUTEX(all_ppp_sem); +static DEFINE_MUTEX(all_ppp_mutex); static struct cardmap *all_ppp_units; static atomic_t ppp_unit_count = ATOMIC_INIT(0); @@ -804,7 +805,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, /* Attach to an existing ppp unit */ if (get_user(unit, p)) break; - down(&all_ppp_sem); + mutex_lock(&all_ppp_mutex); err = -ENXIO; ppp = ppp_find_unit(unit); if (ppp != 0) { @@ -812,7 +813,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, file->private_data = &ppp->file; err = 0; } - up(&all_ppp_sem); + mutex_unlock(&all_ppp_mutex); break; case PPPIOCATTCHAN: @@ -2446,7 +2447,7 @@ ppp_create_interface(int unit, int *retp) dev->do_ioctl = ppp_net_ioctl; ret = -EEXIST; - down(&all_ppp_sem); + mutex_lock(&all_ppp_mutex); if (unit < 0) unit = cardmap_find_first_free(all_ppp_units); else if (cardmap_get(all_ppp_units, unit) != NULL) @@ -2465,12 +2466,12 @@ ppp_create_interface(int unit, int *retp) atomic_inc(&ppp_unit_count); cardmap_set(&all_ppp_units, unit, ppp); - up(&all_ppp_sem); + mutex_unlock(&all_ppp_mutex); *retp = 0; return ppp; out2: - up(&all_ppp_sem); + mutex_unlock(&all_ppp_mutex); free_netdev(dev); out1: kfree(ppp); @@ -2500,7 +2501,7 @@ static void ppp_shutdown_interface(struct ppp *ppp) { struct net_device *dev; - down(&all_ppp_sem); + mutex_lock(&all_ppp_mutex); ppp_lock(ppp); dev = ppp->dev; ppp->dev = NULL; @@ -2514,7 +2515,7 @@ static void ppp_shutdown_interface(struct ppp *ppp) ppp->file.dead = 1; ppp->owner = NULL; wake_up_interruptible(&ppp->file.rwait); - up(&all_ppp_sem); + mutex_unlock(&all_ppp_mutex); } /* @@ -2556,7 +2557,7 @@ static void ppp_destroy_interface(struct ppp *ppp) /* * Locate an existing ppp unit. - * The caller should have locked the all_ppp_sem. + * The caller should have locked the all_ppp_mutex. */ static struct ppp * ppp_find_unit(int unit) @@ -2601,7 +2602,7 @@ ppp_connect_channel(struct channel *pch, int unit) int ret = -ENXIO; int hdrlen; - down(&all_ppp_sem); + mutex_lock(&all_ppp_mutex); ppp = ppp_find_unit(unit); if (ppp == 0) goto out; @@ -2626,7 +2627,7 @@ ppp_connect_channel(struct channel *pch, int unit) outl: write_unlock_bh(&pch->upl); out: - up(&all_ppp_sem); + mutex_unlock(&all_ppp_mutex); return ret; } -- cgit v1.2.3-59-g8ed1b From e723ccd805857a46d3b63fbd20edea8579c6c541 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 23 Mar 2006 03:00:22 -0800 Subject: [PATCH] sem2mutex: drivers/scsi/ide-scsi.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: Ingo Molnar Cc: Jens Axboe Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/ide-scsi.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 0cf0e4c7ac0c..39b760a24241 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -109,7 +110,7 @@ typedef struct ide_scsi_obj { unsigned long log; /* log flags */ } idescsi_scsi_t; -static DECLARE_MUTEX(idescsi_ref_sem); +static DEFINE_MUTEX(idescsi_ref_mutex); #define ide_scsi_g(disk) \ container_of((disk)->private_data, struct ide_scsi_obj, driver) @@ -118,19 +119,19 @@ static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk) { struct ide_scsi_obj *scsi = NULL; - down(&idescsi_ref_sem); + mutex_lock(&idescsi_ref_mutex); scsi = ide_scsi_g(disk); if (scsi) scsi_host_get(scsi->host); - up(&idescsi_ref_sem); + mutex_unlock(&idescsi_ref_mutex); return scsi; } static void ide_scsi_put(struct ide_scsi_obj *scsi) { - down(&idescsi_ref_sem); + mutex_lock(&idescsi_ref_mutex); scsi_host_put(scsi->host); - up(&idescsi_ref_sem); + mutex_unlock(&idescsi_ref_mutex); } static inline idescsi_scsi_t *scsihost_to_idescsi(struct Scsi_Host *host) -- cgit v1.2.3-59-g8ed1b From 1657f824e880a9bd239a3436b820d1a2986f763d Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 23 Mar 2006 03:00:25 -0800 Subject: [PATCH] sem2mutex: drivers/block/pktcdvd.c Convert to use mutex from a semaphore Signed-off-by: Jes Sorensen Signed-off-by: Ingo Molnar Cc: Peter Osterlund Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/pktcdvd.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 476a5b553f34..1d261f985f31 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -81,7 +82,7 @@ static struct pktcdvd_device *pkt_devs[MAX_WRITERS]; static struct proc_dir_entry *pkt_proc; static int pkt_major; -static struct semaphore ctl_mutex; /* Serialize open/close/setup/teardown */ +static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */ static mempool_t *psd_pool; @@ -2018,7 +2019,7 @@ static int pkt_open(struct inode *inode, struct file *file) VPRINTK("pktcdvd: entering open\n"); - down(&ctl_mutex); + mutex_lock(&ctl_mutex); pd = pkt_find_dev_from_minor(iminor(inode)); if (!pd) { ret = -ENODEV; @@ -2044,14 +2045,14 @@ static int pkt_open(struct inode *inode, struct file *file) set_blocksize(inode->i_bdev, CD_FRAMESIZE); } - up(&ctl_mutex); + mutex_unlock(&ctl_mutex); return 0; out_dec: pd->refcnt--; out: VPRINTK("pktcdvd: failed open (%d)\n", ret); - up(&ctl_mutex); + mutex_unlock(&ctl_mutex); return ret; } @@ -2060,14 +2061,14 @@ static int pkt_close(struct inode *inode, struct file *file) struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data; int ret = 0; - down(&ctl_mutex); + mutex_lock(&ctl_mutex); pd->refcnt--; BUG_ON(pd->refcnt < 0); if (pd->refcnt == 0) { int flush = test_bit(PACKET_WRITABLE, &pd->flags); pkt_release_dev(pd, flush); } - up(&ctl_mutex); + mutex_unlock(&ctl_mutex); return ret; } @@ -2596,21 +2597,21 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm case PKT_CTRL_CMD_SETUP: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - down(&ctl_mutex); + mutex_lock(&ctl_mutex); ret = pkt_setup_dev(&ctrl_cmd); - up(&ctl_mutex); + mutex_unlock(&ctl_mutex); break; case PKT_CTRL_CMD_TEARDOWN: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - down(&ctl_mutex); + mutex_lock(&ctl_mutex); ret = pkt_remove_dev(&ctrl_cmd); - up(&ctl_mutex); + mutex_unlock(&ctl_mutex); break; case PKT_CTRL_CMD_STATUS: - down(&ctl_mutex); + mutex_lock(&ctl_mutex); pkt_get_status(&ctrl_cmd); - up(&ctl_mutex); + mutex_unlock(&ctl_mutex); break; default: return -ENOTTY; @@ -2656,7 +2657,7 @@ static int __init pkt_init(void) goto out; } - init_MUTEX(&ctl_mutex); + mutex_init(&ctl_mutex); pkt_proc = proc_mkdir("pktcdvd", proc_root_driver); -- cgit v1.2.3-59-g8ed1b From b1c82b5c55851bf309f4019994610789f7042757 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 23 Mar 2006 03:00:26 -0800 Subject: [PATCH] sem2mutex: drivers/block/floppy.c Convert from semaphore to mutex. Untested as I have no access to a floppy drive at the moment. Signed-off-by: Jes Sorensen Signed-off-by: Ingo Molnar Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/floppy.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index d23b54332d7e..fb2d0be7cdeb 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -179,6 +179,7 @@ static int print_unex = 1; #include #include #include /* for invalidate_buffers() */ +#include /* * PS/2 floppies have much slower step rates than regular floppies. @@ -413,7 +414,7 @@ static struct floppy_write_errors write_errors[N_DRIVE]; static struct timer_list motor_off_timer[N_DRIVE]; static struct gendisk *disks[N_DRIVE]; static struct block_device *opened_bdev[N_DRIVE]; -static DECLARE_MUTEX(open_lock); +static DEFINE_MUTEX(open_lock); static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; /* @@ -3333,7 +3334,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, if (type) { if (!capable(CAP_SYS_ADMIN)) return -EPERM; - down(&open_lock); + mutex_lock(&open_lock); LOCK_FDC(drive, 1); floppy_type[type] = *g; floppy_type[type].name = "user format"; @@ -3347,7 +3348,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, continue; __invalidate_device(bdev); } - up(&open_lock); + mutex_unlock(&open_lock); } else { int oldStretch; LOCK_FDC(drive, 1); @@ -3674,7 +3675,7 @@ static int floppy_release(struct inode *inode, struct file *filp) { int drive = (long)inode->i_bdev->bd_disk->private_data; - down(&open_lock); + mutex_lock(&open_lock); if (UDRS->fd_ref < 0) UDRS->fd_ref = 0; else if (!UDRS->fd_ref--) { @@ -3684,7 +3685,7 @@ static int floppy_release(struct inode *inode, struct file *filp) if (!UDRS->fd_ref) opened_bdev[drive] = NULL; floppy_release_irq_and_dma(); - up(&open_lock); + mutex_unlock(&open_lock); return 0; } @@ -3702,7 +3703,7 @@ static int floppy_open(struct inode *inode, struct file *filp) char *tmp; filp->private_data = (void *)0; - down(&open_lock); + mutex_lock(&open_lock); old_dev = UDRS->fd_device; if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev) goto out2; @@ -3785,7 +3786,7 @@ static int floppy_open(struct inode *inode, struct file *filp) if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE))) goto out; } - up(&open_lock); + mutex_unlock(&open_lock); return 0; out: if (UDRS->fd_ref < 0) @@ -3796,7 +3797,7 @@ out: opened_bdev[drive] = NULL; floppy_release_irq_and_dma(); out2: - up(&open_lock); + mutex_unlock(&open_lock); return res; } -- cgit v1.2.3-59-g8ed1b From 6f87f0deebaff2716a3ce9232f948d702690562a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:27 -0800 Subject: [PATCH] sem2mutex: drivers/char/ 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 Cc: Russell King Cc: Wim Van Sebroeck Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/istallion.c | 1 - drivers/char/nwflash.c | 11 ++++++----- drivers/char/stallion.c | 1 - drivers/char/watchdog/pcwd_usb.c | 7 ++++--- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 28c5a3193b81..ede128356af2 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -181,7 +181,6 @@ static struct tty_driver *stli_serial; * is already swapping a shared buffer won't make things any worse. */ static char *stli_tmpwritebuf; -static DECLARE_MUTEX(stli_tmpwritesem); #define STLI_TXBUFSIZE 4096 diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index ca41d62b1d9d..8865387d3448 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -56,7 +57,7 @@ static int gbWriteEnable; static int gbWriteBase64Enable; static volatile unsigned char *FLASH_BASE; static int gbFlashSize = KFLASH_SIZE; -static DECLARE_MUTEX(nwflash_sem); +static DEFINE_MUTEX(nwflash_mutex); extern spinlock_t gpio_lock; @@ -140,7 +141,7 @@ static ssize_t flash_read(struct file *file, char __user *buf, size_t size, /* * We now lock against reads and writes. --rmk */ - if (down_interruptible(&nwflash_sem)) + if (mutex_lock_interruptible(&nwflash_mutex)) return -ERESTARTSYS; ret = copy_to_user(buf, (void *)(FLASH_BASE + p), count); @@ -149,7 +150,7 @@ static ssize_t flash_read(struct file *file, char __user *buf, size_t size, *ppos += count; } else ret = -EFAULT; - up(&nwflash_sem); + mutex_unlock(&nwflash_mutex); } return ret; } @@ -188,7 +189,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf, /* * We now lock against reads and writes. --rmk */ - if (down_interruptible(&nwflash_sem)) + if (mutex_lock_interruptible(&nwflash_mutex)) return -ERESTARTSYS; written = 0; @@ -277,7 +278,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf, */ leds_event(led_release); - up(&nwflash_sem); + mutex_unlock(&nwflash_mutex); return written; } diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index bdaab6992109..3f5d6077f39c 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -148,7 +148,6 @@ static struct tty_driver *stl_serial; * is already swapping a shared buffer won't make things any worse. */ static char *stl_tmpwritebuf; -static DECLARE_MUTEX(stl_tmpwritesem); /* * Define a local default termios struct. All ports will be created diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c index 1533f56baa42..2700c5c45b8a 100644 --- a/drivers/char/watchdog/pcwd_usb.c +++ b/drivers/char/watchdog/pcwd_usb.c @@ -42,6 +42,7 @@ #include #include #include +#include #ifdef CONFIG_USB_DEBUG @@ -143,7 +144,7 @@ struct usb_pcwd_private { static struct usb_pcwd_private *usb_pcwd_device; /* prevent races between open() and disconnect() */ -static DECLARE_MUTEX (disconnect_sem); +static DEFINE_MUTEX(disconnect_mutex); /* local function prototypes */ static int usb_pcwd_probe (struct usb_interface *interface, const struct usb_device_id *id); @@ -723,7 +724,7 @@ static void usb_pcwd_disconnect(struct usb_interface *interface) struct usb_pcwd_private *usb_pcwd; /* prevent races with open() */ - down (&disconnect_sem); + mutex_lock(&disconnect_mutex); usb_pcwd = usb_get_intfdata (interface); usb_set_intfdata (interface, NULL); @@ -749,7 +750,7 @@ static void usb_pcwd_disconnect(struct usb_interface *interface) cards_found--; - up (&disconnect_sem); + mutex_unlock(&disconnect_mutex); printk(KERN_INFO PFX "USB PC Watchdog disconnected\n"); } -- cgit v1.2.3-59-g8ed1b From c039e3134ae62863bbc8e8429b29e3c43cf21b2a Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 23 Mar 2006 03:00:28 -0800 Subject: [PATCH] sem2mutex: blockdev #2 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 Acked-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/ioctl.c | 22 +++++++++++----------- drivers/block/rd.c | 4 ++-- drivers/s390/block/dasd_ioctl.c | 8 ++++---- fs/block_dev.c | 28 ++++++++++++++-------------- fs/buffer.c | 6 +++--- fs/super.c | 4 ++-- include/linux/fs.h | 4 ++-- 7 files changed, 38 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/block/ioctl.c b/block/ioctl.c index e1109491c234..35fdb7dc6512 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -42,9 +42,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user return -EINVAL; } /* partition number in use? */ - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); if (disk->part[part - 1]) { - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return -EBUSY; } /* overlap? */ @@ -55,13 +55,13 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user continue; if (!(start+length <= s->start_sect || start >= s->start_sect + s->nr_sects)) { - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return -EBUSY; } } /* all seems OK */ add_partition(disk, part, start, length); - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return 0; case BLKPG_DEL_PARTITION: if (!disk->part[part-1]) @@ -71,9 +71,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user bdevp = bdget_disk(disk, part); if (!bdevp) return -ENOMEM; - down(&bdevp->bd_sem); + mutex_lock(&bdevp->bd_mutex); if (bdevp->bd_openers) { - up(&bdevp->bd_sem); + mutex_unlock(&bdevp->bd_mutex); bdput(bdevp); return -EBUSY; } @@ -81,10 +81,10 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user fsync_bdev(bdevp); invalidate_bdev(bdevp, 0); - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); delete_partition(disk, part); - up(&bdev->bd_sem); - up(&bdevp->bd_sem); + mutex_unlock(&bdev->bd_mutex); + mutex_unlock(&bdevp->bd_mutex); bdput(bdevp); return 0; @@ -102,10 +102,10 @@ static int blkdev_reread_part(struct block_device *bdev) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (down_trylock(&bdev->bd_sem)) + if (!mutex_trylock(&bdev->bd_mutex)) return -EBUSY; res = rescan_partitions(disk, bdev); - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return res; } diff --git a/drivers/block/rd.c b/drivers/block/rd.c index ffd6abd6d5a0..1c54f46d3f70 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -310,12 +310,12 @@ static int rd_ioctl(struct inode *inode, struct file *file, * cache */ error = -EBUSY; - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); if (bdev->bd_openers <= 2) { truncate_inode_pages(bdev->bd_inode->i_mapping, 0); error = 0; } - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return error; } diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index fafeeae52675..f9930552ab54 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -151,9 +151,9 @@ dasd_ioctl_enable(struct block_device *bdev, int no, long args) return -ENODEV; dasd_enable_device(device); /* Formatting the dasd device can change the capacity. */ - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); i_size_write(bdev->bd_inode, (loff_t)get_capacity(device->gdp) << 9); - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return 0; } @@ -184,9 +184,9 @@ dasd_ioctl_disable(struct block_device *bdev, int no, long args) * Set i_size to zero, since read, write, etc. check against this * value. */ - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); i_size_write(bdev->bd_inode, 0); - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); return 0; } diff --git a/fs/block_dev.c b/fs/block_dev.c index 6e50346fb1ee..44d05e6e34db 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -265,8 +265,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) SLAB_CTOR_CONSTRUCTOR) { memset(bdev, 0, sizeof(*bdev)); - sema_init(&bdev->bd_sem, 1); - sema_init(&bdev->bd_mount_sem, 1); + mutex_init(&bdev->bd_mutex); + mutex_init(&bdev->bd_mount_mutex); INIT_LIST_HEAD(&bdev->bd_inodes); INIT_LIST_HEAD(&bdev->bd_list); inode_init_once(&ei->vfs_inode); @@ -574,7 +574,7 @@ static int do_open(struct block_device *bdev, struct file *file) } owner = disk->fops->owner; - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); if (!bdev->bd_openers) { bdev->bd_disk = disk; bdev->bd_contains = bdev; @@ -605,21 +605,21 @@ static int do_open(struct block_device *bdev, struct file *file) if (ret) goto out_first; bdev->bd_contains = whole; - down(&whole->bd_sem); + mutex_lock(&whole->bd_mutex); whole->bd_part_count++; p = disk->part[part - 1]; bdev->bd_inode->i_data.backing_dev_info = whole->bd_inode->i_data.backing_dev_info; if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) { whole->bd_part_count--; - up(&whole->bd_sem); + mutex_unlock(&whole->bd_mutex); ret = -ENXIO; goto out_first; } kobject_get(&p->kobj); bdev->bd_part = p; bd_set_size(bdev, (loff_t) p->nr_sects << 9); - up(&whole->bd_sem); + mutex_unlock(&whole->bd_mutex); } } else { put_disk(disk); @@ -633,13 +633,13 @@ static int do_open(struct block_device *bdev, struct file *file) if (bdev->bd_invalidated) rescan_partitions(bdev->bd_disk, bdev); } else { - down(&bdev->bd_contains->bd_sem); + mutex_lock(&bdev->bd_contains->bd_mutex); bdev->bd_contains->bd_part_count++; - up(&bdev->bd_contains->bd_sem); + mutex_unlock(&bdev->bd_contains->bd_mutex); } } bdev->bd_openers++; - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); unlock_kernel(); return 0; @@ -652,7 +652,7 @@ out_first: put_disk(disk); module_put(owner); out: - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); unlock_kernel(); if (ret) bdput(bdev); @@ -714,7 +714,7 @@ int blkdev_put(struct block_device *bdev) struct inode *bd_inode = bdev->bd_inode; struct gendisk *disk = bdev->bd_disk; - down(&bdev->bd_sem); + mutex_lock(&bdev->bd_mutex); lock_kernel(); if (!--bdev->bd_openers) { sync_blockdev(bdev); @@ -724,9 +724,9 @@ int blkdev_put(struct block_device *bdev) if (disk->fops->release) ret = disk->fops->release(bd_inode, NULL); } else { - down(&bdev->bd_contains->bd_sem); + mutex_lock(&bdev->bd_contains->bd_mutex); bdev->bd_contains->bd_part_count--; - up(&bdev->bd_contains->bd_sem); + mutex_unlock(&bdev->bd_contains->bd_mutex); } if (!bdev->bd_openers) { struct module *owner = disk->fops->owner; @@ -746,7 +746,7 @@ int blkdev_put(struct block_device *bdev) bdev->bd_contains = NULL; } unlock_kernel(); - up(&bdev->bd_sem); + mutex_unlock(&bdev->bd_mutex); bdput(bdev); return ret; } diff --git a/fs/buffer.c b/fs/buffer.c index 1d3683d496f8..0d6ca7bac6c8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -201,7 +201,7 @@ int fsync_bdev(struct block_device *bdev) * freeze_bdev -- lock a filesystem and force it into a consistent state * @bdev: blockdevice to lock * - * This takes the block device bd_mount_sem to make sure no new mounts + * This takes the block device bd_mount_mutex to make sure no new mounts * happen on bdev until thaw_bdev() is called. * If a superblock is found on this device, we take the s_umount semaphore * on it to make sure nobody unmounts until the snapshot creation is done. @@ -210,7 +210,7 @@ struct super_block *freeze_bdev(struct block_device *bdev) { struct super_block *sb; - down(&bdev->bd_mount_sem); + mutex_lock(&bdev->bd_mount_mutex); sb = get_super(bdev); if (sb && !(sb->s_flags & MS_RDONLY)) { sb->s_frozen = SB_FREEZE_WRITE; @@ -264,7 +264,7 @@ void thaw_bdev(struct block_device *bdev, struct super_block *sb) drop_super(sb); } - up(&bdev->bd_mount_sem); + mutex_unlock(&bdev->bd_mount_mutex); } EXPORT_SYMBOL(thaw_bdev); diff --git a/fs/super.c b/fs/super.c index e20b5580afd5..8f9c9b3af70c 100644 --- a/fs/super.c +++ b/fs/super.c @@ -693,9 +693,9 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, * will protect the lockfs code from trying to start a snapshot * while we are mounting */ - down(&bdev->bd_mount_sem); + mutex_lock(&bdev->bd_mount_mutex); s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); - up(&bdev->bd_mount_sem); + mutex_unlock(&bdev->bd_mount_mutex); if (IS_ERR(s)) goto out; diff --git a/include/linux/fs.h b/include/linux/fs.h index 128d0082522c..009ac96053fe 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -397,8 +397,8 @@ struct block_device { dev_t bd_dev; /* not a kdev_t - it's a search key */ struct inode * bd_inode; /* will die */ int bd_openers; - struct semaphore bd_sem; /* open/close mutex */ - struct semaphore bd_mount_sem; /* mount mutex */ + struct mutex bd_mutex; /* open/close mutex */ + struct mutex bd_mount_mutex; /* mount mutex */ struct list_head bd_inodes; void * bd_holder; int bd_holders; -- cgit v1.2.3-59-g8ed1b From 70522e121a521aa09bd0f4e62e1aa68708b798e1 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:31 -0800 Subject: [PATCH] sem2mutex: tty 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 Cc: Alan Cox Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/n_tty.c | 10 +++++----- drivers/char/tty_io.c | 50 +++++++++++++++++++++++++------------------------- drivers/char/vt.c | 14 +++++++------- include/linux/tty.h | 8 ++++---- kernel/exit.c | 4 ++-- kernel/sys.c | 4 ++-- 6 files changed, 45 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index ccad7ae94541..ede365d05387 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -132,7 +132,7 @@ static void put_tty_queue(unsigned char c, struct tty_struct *tty) * We test the TTY_THROTTLED bit first so that it always * indicates the current state. The decision about whether * it is worth allowing more input has been taken by the caller. - * Can sleep, may be called under the atomic_read semaphore but + * Can sleep, may be called under the atomic_read_lock mutex but * this is not guaranteed. */ @@ -1132,7 +1132,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt) * buffer, and once to drain the space from the (physical) beginning of * the buffer to head pointer. * - * Called under the tty->atomic_read sem and with TTY_DONT_FLIP set + * Called under the tty->atomic_read_lock sem and with TTY_DONT_FLIP set * */ @@ -1262,11 +1262,11 @@ do_it_again: * Internal serialization of reads. */ if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&tty->atomic_read)) + if (!mutex_trylock(&tty->atomic_read_lock)) return -EAGAIN; } else { - if (down_interruptible(&tty->atomic_read)) + if (mutex_lock_interruptible(&tty->atomic_read_lock)) return -ERESTARTSYS; } @@ -1393,7 +1393,7 @@ do_it_again: timeout = time; } clear_bit(TTY_DONT_FLIP, &tty->flags); - up(&tty->atomic_read); + mutex_unlock(&tty->atomic_read_lock); remove_wait_queue(&tty->read_wait, &wait); if (!waitqueue_active(&tty->read_wait)) diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 53d3d066554e..76592ee1fb38 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -130,7 +130,7 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ /* Semaphore to protect creating and releasing a tty. This is shared with vt.c for deeply disgusting hack reasons */ -DECLARE_MUTEX(tty_sem); +DEFINE_MUTEX(tty_mutex); #ifdef CONFIG_UNIX98_PTYS extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ @@ -1188,11 +1188,11 @@ void disassociate_ctty(int on_exit) lock_kernel(); - down(&tty_sem); + mutex_lock(&tty_mutex); tty = current->signal->tty; if (tty) { tty_pgrp = tty->pgrp; - up(&tty_sem); + mutex_unlock(&tty_mutex); if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); } else { @@ -1200,7 +1200,7 @@ void disassociate_ctty(int on_exit) kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit); kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); } - up(&tty_sem); + mutex_unlock(&tty_mutex); unlock_kernel(); return; } @@ -1211,7 +1211,7 @@ void disassociate_ctty(int on_exit) } /* Must lock changes to tty_old_pgrp */ - down(&tty_sem); + mutex_lock(&tty_mutex); current->signal->tty_old_pgrp = 0; tty->session = 0; tty->pgrp = -1; @@ -1222,7 +1222,7 @@ void disassociate_ctty(int on_exit) p->signal->tty = NULL; } while_each_task_pid(current->signal->session, PIDTYPE_SID, p); read_unlock(&tasklist_lock); - up(&tty_sem); + mutex_unlock(&tty_mutex); unlock_kernel(); } @@ -1306,7 +1306,7 @@ static inline ssize_t do_tty_write( ssize_t ret = 0, written = 0; unsigned int chunk; - if (down_interruptible(&tty->atomic_write)) { + if (mutex_lock_interruptible(&tty->atomic_write_lock)) { return -ERESTARTSYS; } @@ -1329,7 +1329,7 @@ static inline ssize_t do_tty_write( if (count < chunk) chunk = count; - /* write_buf/write_cnt is protected by the atomic_write semaphore */ + /* write_buf/write_cnt is protected by the atomic_write_lock mutex */ if (tty->write_cnt < chunk) { unsigned char *buf; @@ -1338,7 +1338,7 @@ static inline ssize_t do_tty_write( buf = kmalloc(chunk, GFP_KERNEL); if (!buf) { - up(&tty->atomic_write); + mutex_unlock(&tty->atomic_write_lock); return -ENOMEM; } kfree(tty->write_buf); @@ -1374,7 +1374,7 @@ static inline ssize_t do_tty_write( inode->i_mtime = current_fs_time(inode->i_sb); ret = written; } - up(&tty->atomic_write); + mutex_unlock(&tty->atomic_write_lock); return ret; } @@ -1442,8 +1442,8 @@ static inline void tty_line_name(struct tty_driver *driver, int index, char *p) /* * WSH 06/09/97: Rewritten to remove races and properly clean up after a - * failed open. The new code protects the open with a semaphore, so it's - * really quite straightforward. The semaphore locking can probably be + * failed open. The new code protects the open with a mutex, so it's + * really quite straightforward. The mutex locking can probably be * relaxed for the (most common) case of reopening a tty. */ static int init_dev(struct tty_driver *driver, int idx, @@ -1640,7 +1640,7 @@ fast_track: success: *ret_tty = tty; - /* All paths come through here to release the semaphore */ + /* All paths come through here to release the mutex */ end_init: return retval; @@ -1837,7 +1837,7 @@ static void release_dev(struct file * filp) /* Guard against races with tty->count changes elsewhere and opens on /dev/tty */ - down(&tty_sem); + mutex_lock(&tty_mutex); tty_closing = tty->count <= 1; o_tty_closing = o_tty && (o_tty->count <= (pty_master ? 1 : 0)); @@ -1868,7 +1868,7 @@ static void release_dev(struct file * filp) printk(KERN_WARNING "release_dev: %s: read/write wait queue " "active!\n", tty_name(tty, buf)); - up(&tty_sem); + mutex_unlock(&tty_mutex); schedule(); } @@ -1934,7 +1934,7 @@ static void release_dev(struct file * filp) read_unlock(&tasklist_lock); } - up(&tty_sem); + mutex_unlock(&tty_mutex); /* check whether both sides are closing ... */ if (!tty_closing || (o_tty && !o_tty_closing)) @@ -2040,11 +2040,11 @@ retry_open: index = -1; retval = 0; - down(&tty_sem); + mutex_lock(&tty_mutex); if (device == MKDEV(TTYAUX_MAJOR,0)) { if (!current->signal->tty) { - up(&tty_sem); + mutex_unlock(&tty_mutex); return -ENXIO; } driver = current->signal->tty->driver; @@ -2070,18 +2070,18 @@ retry_open: noctty = 1; goto got_driver; } - up(&tty_sem); + mutex_unlock(&tty_mutex); return -ENODEV; } driver = get_tty_driver(device, &index); if (!driver) { - up(&tty_sem); + mutex_unlock(&tty_mutex); return -ENODEV; } got_driver: retval = init_dev(driver, index, &tty); - up(&tty_sem); + mutex_unlock(&tty_mutex); if (retval) return retval; @@ -2167,9 +2167,9 @@ static int ptmx_open(struct inode * inode, struct file * filp) } up(&allocated_ptys_lock); - down(&tty_sem); + mutex_lock(&tty_mutex); retval = init_dev(ptm_driver, index, &tty); - up(&tty_sem); + mutex_unlock(&tty_mutex); if (retval) goto out; @@ -2915,8 +2915,8 @@ static void initialize_tty_struct(struct tty_struct *tty) init_waitqueue_head(&tty->write_wait); init_waitqueue_head(&tty->read_wait); INIT_WORK(&tty->hangup_work, do_tty_hangup, tty); - sema_init(&tty->atomic_read, 1); - sema_init(&tty->atomic_write, 1); + mutex_init(&tty->atomic_read_lock); + mutex_init(&tty->atomic_write_lock); spin_lock_init(&tty->read_lock); INIT_LIST_HEAD(&tty->tty_files); INIT_WORK(&tty->SAK_work, NULL, NULL); diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 86b31b87eb85..ca4844c527da 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2489,7 +2489,7 @@ static int con_open(struct tty_struct *tty, struct file *filp) } /* - * We take tty_sem in here to prevent another thread from coming in via init_dev + * We take tty_mutex in here to prevent another thread from coming in via init_dev * and taking a ref against the tty while we're in the process of forgetting * about it and cleaning things up. * @@ -2497,7 +2497,7 @@ static int con_open(struct tty_struct *tty, struct file *filp) */ static void con_close(struct tty_struct *tty, struct file *filp) { - down(&tty_sem); + mutex_lock(&tty_mutex); acquire_console_sem(); if (tty && tty->count == 1) { struct vc_data *vc = tty->driver_data; @@ -2507,15 +2507,15 @@ static void con_close(struct tty_struct *tty, struct file *filp) tty->driver_data = NULL; release_console_sem(); vcs_remove_devfs(tty); - up(&tty_sem); + mutex_unlock(&tty_mutex); /* - * tty_sem is released, but we still hold BKL, so there is + * tty_mutex is released, but we still hold BKL, so there is * still exclusion against init_dev() */ return; } release_console_sem(); - up(&tty_sem); + mutex_unlock(&tty_mutex); } static void vc_init(struct vc_data *vc, unsigned int rows, @@ -2869,9 +2869,9 @@ void unblank_screen(void) } /* - * We defer the timer blanking to work queue so it can take the console semaphore + * We defer the timer blanking to work queue so it can take the console mutex * (console operations can still happen at irq time, but only from printk which - * has the console semaphore. Not perfect yet, but better than no locking + * has the console mutex. Not perfect yet, but better than no locking */ static void blank_screen_t(unsigned long dummy) { diff --git a/include/linux/tty.h b/include/linux/tty.h index f45cd74e6f24..f13f49afe198 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -231,8 +232,8 @@ struct tty_struct { int canon_data; unsigned long canon_head; unsigned int canon_column; - struct semaphore atomic_read; - struct semaphore atomic_write; + struct mutex atomic_read_lock; + struct mutex atomic_write_lock; unsigned char *write_buf; int write_cnt; spinlock_t read_lock; @@ -319,8 +320,7 @@ extern void tty_ldisc_put(int); extern void tty_wakeup(struct tty_struct *tty); extern void tty_ldisc_flush(struct tty_struct *tty); -struct semaphore; -extern struct semaphore tty_sem; +extern struct mutex tty_mutex; /* n_tty.c */ extern struct tty_ldisc tty_ldisc_N_TTY; diff --git a/kernel/exit.c b/kernel/exit.c index d1e8d500a7e1..8037405e136e 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -345,9 +345,9 @@ void daemonize(const char *name, ...) exit_mm(current); set_special_pids(1, 1); - down(&tty_sem); + mutex_lock(&tty_mutex); current->signal->tty = NULL; - up(&tty_sem); + mutex_unlock(&tty_mutex); /* Block and flush all signals */ sigfillset(&blocked); diff --git a/kernel/sys.c b/kernel/sys.c index 4941b9b14b97..c0fcad9f826c 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1227,7 +1227,7 @@ asmlinkage long sys_setsid(void) struct pid *pid; int err = -EPERM; - down(&tty_sem); + mutex_lock(&tty_mutex); write_lock_irq(&tasklist_lock); pid = find_pid(PIDTYPE_PGID, group_leader->pid); @@ -1241,7 +1241,7 @@ asmlinkage long sys_setsid(void) err = process_group(group_leader); out: write_unlock_irq(&tasklist_lock); - up(&tty_sem); + mutex_unlock(&tty_mutex); return err; } -- cgit v1.2.3-59-g8ed1b From f85221dd74f2708b78a2aa54de59944e44206d0e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:38 -0800 Subject: [PATCH] sem2mutex: drivers/block/loop.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: Ingo Molnar Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/loop.c | 18 +++++++++--------- include/linux/loop.h | 3 ++- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 0010704739e3..74bf0255e98f 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1144,7 +1144,7 @@ static int lo_ioctl(struct inode * inode, struct file * file, struct loop_device *lo = inode->i_bdev->bd_disk->private_data; int err; - down(&lo->lo_ctl_mutex); + mutex_lock(&lo->lo_ctl_mutex); switch (cmd) { case LOOP_SET_FD: err = loop_set_fd(lo, file, inode->i_bdev, arg); @@ -1170,7 +1170,7 @@ static int lo_ioctl(struct inode * inode, struct file * file, default: err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; } - up(&lo->lo_ctl_mutex); + mutex_unlock(&lo->lo_ctl_mutex); return err; } @@ -1178,9 +1178,9 @@ static int lo_open(struct inode *inode, struct file *file) { struct loop_device *lo = inode->i_bdev->bd_disk->private_data; - down(&lo->lo_ctl_mutex); + mutex_lock(&lo->lo_ctl_mutex); lo->lo_refcnt++; - up(&lo->lo_ctl_mutex); + mutex_unlock(&lo->lo_ctl_mutex); return 0; } @@ -1189,9 +1189,9 @@ static int lo_release(struct inode *inode, struct file *file) { struct loop_device *lo = inode->i_bdev->bd_disk->private_data; - down(&lo->lo_ctl_mutex); + mutex_lock(&lo->lo_ctl_mutex); --lo->lo_refcnt; - up(&lo->lo_ctl_mutex); + mutex_unlock(&lo->lo_ctl_mutex); return 0; } @@ -1233,12 +1233,12 @@ int loop_unregister_transfer(int number) xfer_funcs[n] = NULL; for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { - down(&lo->lo_ctl_mutex); + mutex_lock(&lo->lo_ctl_mutex); if (lo->lo_encryption == xfer) loop_release_xfer(lo); - up(&lo->lo_ctl_mutex); + mutex_unlock(&lo->lo_ctl_mutex); } return 0; @@ -1285,7 +1285,7 @@ static int __init loop_init(void) lo->lo_queue = blk_alloc_queue(GFP_KERNEL); if (!lo->lo_queue) goto out_mem4; - init_MUTEX(&lo->lo_ctl_mutex); + mutex_init(&lo->lo_ctl_mutex); init_completion(&lo->lo_done); init_completion(&lo->lo_bh_done); lo->lo_number = i; diff --git a/include/linux/loop.h b/include/linux/loop.h index f96506782ebe..e76c7611d6cc 100644 --- a/include/linux/loop.h +++ b/include/linux/loop.h @@ -17,6 +17,7 @@ #include #include #include +#include /* Possible states of device */ enum { @@ -60,7 +61,7 @@ struct loop_device { int lo_state; struct completion lo_done; struct completion lo_bh_done; - struct semaphore lo_ctl_mutex; + struct mutex lo_ctl_mutex; int lo_pending; request_queue_t *lo_queue; -- cgit v1.2.3-59-g8ed1b From 82d4dc5adb0055393248ad4ab8de392fac708a12 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:38 -0800 Subject: [PATCH] sem2mutex: drivers/block/nbd.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: Ingo Molnar Cc: Paul Clements Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/nbd.c | 16 ++++++++-------- include/linux/nbd.h | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 6997d8e6bfb5..a9bde30dadad 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -459,9 +459,9 @@ static void do_nbd_request(request_queue_t * q) req->errors = 0; spin_unlock_irq(q->queue_lock); - down(&lo->tx_lock); + mutex_lock(&lo->tx_lock); if (unlikely(!lo->sock)) { - up(&lo->tx_lock); + mutex_unlock(&lo->tx_lock); printk(KERN_ERR "%s: Attempted send on closed socket\n", lo->disk->disk_name); req->errors++; @@ -484,7 +484,7 @@ static void do_nbd_request(request_queue_t * q) } lo->active_req = NULL; - up(&lo->tx_lock); + mutex_unlock(&lo->tx_lock); wake_up_all(&lo->active_wq); spin_lock_irq(q->queue_lock); @@ -534,9 +534,9 @@ static int nbd_ioctl(struct inode *inode, struct file *file, case NBD_CLEAR_SOCK: error = 0; - down(&lo->tx_lock); + mutex_lock(&lo->tx_lock); lo->sock = NULL; - up(&lo->tx_lock); + mutex_unlock(&lo->tx_lock); file = lo->file; lo->file = NULL; nbd_clear_que(lo); @@ -590,7 +590,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, * FIXME: This code is duplicated from sys_shutdown, but * there should be a more generic interface rather than * calling socket ops directly here */ - down(&lo->tx_lock); + mutex_lock(&lo->tx_lock); if (lo->sock) { printk(KERN_WARNING "%s: shutting down socket\n", lo->disk->disk_name); @@ -598,7 +598,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, SEND_SHUTDOWN|RCV_SHUTDOWN); lo->sock = NULL; } - up(&lo->tx_lock); + mutex_unlock(&lo->tx_lock); file = lo->file; lo->file = NULL; nbd_clear_que(lo); @@ -683,7 +683,7 @@ static int __init nbd_init(void) nbd_dev[i].flags = 0; spin_lock_init(&nbd_dev[i].queue_lock); INIT_LIST_HEAD(&nbd_dev[i].queue_head); - init_MUTEX(&nbd_dev[i].tx_lock); + mutex_init(&nbd_dev[i].tx_lock); init_waitqueue_head(&nbd_dev[i].active_wq); nbd_dev[i].blksize = 1024; nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */ diff --git a/include/linux/nbd.h b/include/linux/nbd.h index f95d51fae733..a6ce409ec6fc 100644 --- a/include/linux/nbd.h +++ b/include/linux/nbd.h @@ -38,6 +38,7 @@ enum { #ifdef __KERNEL__ #include +#include /* values for flags field */ #define NBD_READ_ONLY 0x0001 @@ -57,7 +58,7 @@ struct nbd_device { struct request *active_req; wait_queue_head_t active_wq; - struct semaphore tx_lock; + struct mutex tx_lock; struct gendisk *disk; int blksize; u64 bytesize; -- cgit v1.2.3-59-g8ed1b From 81861d78c9edf9a9b03a9ba1f5b242d658f16832 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:44 -0800 Subject: [PATCH] sem2mutex: serial ->port_write_mutex 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: Linus Torvalds --- drivers/char/generic_serial.c | 14 +++++++------- drivers/char/ser_a2232.c | 4 ++-- drivers/char/sx.c | 2 +- drivers/char/vme_scc.c | 2 +- include/linux/generic_serial.h | 4 +++- 5 files changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index e38a5f0e07bb..5e59c0b42731 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -48,8 +48,8 @@ static int gs_debug; #define NEW_WRITE_LOCKING 1 #if NEW_WRITE_LOCKING #define DECL /* Nothing */ -#define LOCKIT down (& port->port_write_sem); -#define RELEASEIT up (&port->port_write_sem); +#define LOCKIT mutex_lock(& port->port_write_mutex); +#define RELEASEIT mutex_unlock(&port->port_write_mutex); #else #define DECL unsigned long flags; #define LOCKIT save_flags (flags);cli () @@ -124,14 +124,14 @@ int gs_write(struct tty_struct * tty, /* get exclusive "write" access to this port (problem 3) */ /* This is not a spinlock because we can have a disk access (page fault) in copy_from_user */ - down (& port->port_write_sem); + mutex_lock(& port->port_write_mutex); while (1) { c = count; /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_sem. */ + change the "head": we own the port_write_mutex. */ /* Don't overrun the end of the buffer */ t = SERIAL_XMIT_SIZE - port->xmit_head; if (t < c) c = t; @@ -153,7 +153,7 @@ int gs_write(struct tty_struct * tty, count -= c; total += c; } - up (& port->port_write_sem); + mutex_unlock(& port->port_write_mutex); gs_dprintk (GS_DEBUG_WRITE, "write: interrupts are %s\n", (port->flags & GS_TX_INTEN)?"enabled": "disabled"); @@ -214,7 +214,7 @@ int gs_write(struct tty_struct * tty, c = count; /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_sem. */ + change the "head": we own the port_write_mutex. */ /* Don't overrun the end of the buffer */ t = SERIAL_XMIT_SIZE - port->xmit_head; if (t < c) c = t; @@ -888,7 +888,7 @@ int gs_init_port(struct gs_port *port) spin_lock_irqsave (&port->driver_lock, flags); if (port->tty) clear_bit(TTY_IO_ERROR, &port->tty->flags); - init_MUTEX(&port->port_write_sem); + mutex_init(&port->port_write_mutex); port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; spin_unlock_irqrestore(&port->driver_lock, flags); gs_set_termios(port->tty, NULL); diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index fee68cc895f8..510bd3e0e88b 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c @@ -97,7 +97,7 @@ #include #include #include -#include +#include #include @@ -654,7 +654,7 @@ static void a2232_init_portstructs(void) port->gs.closing_wait = 30 * HZ; port->gs.rd = &a2232_real_driver; #ifdef NEW_WRITE_LOCKING - init_MUTEX(&(port->gs.port_write_sem)); + init_MUTEX(&(port->gs.port_write_mutex)); #endif init_waitqueue_head(&port->gs.open_wait); init_waitqueue_head(&port->gs.close_wait); diff --git a/drivers/char/sx.c b/drivers/char/sx.c index a6b4f02bdceb..3b4747230270 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -2318,7 +2318,7 @@ static int sx_init_portstructs (int nboards, int nports) port->board = board; port->gs.rd = &sx_real_driver; #ifdef NEW_WRITE_LOCKING - port->gs.port_write_sem = MUTEX; + port->gs.port_write_mutex = MUTEX; #endif port->gs.driver_lock = SPIN_LOCK_UNLOCKED; /* diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index d9325281e482..fd00822ac145 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c @@ -184,7 +184,7 @@ static void scc_init_portstructs(void) port->gs.closing_wait = 30 * HZ; port->gs.rd = &scc_real_driver; #ifdef NEW_WRITE_LOCKING - port->gs.port_write_sem = MUTEX; + port->gs.port_write_mutex = MUTEX; #endif init_waitqueue_head(&port->gs.open_wait); init_waitqueue_head(&port->gs.close_wait); diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h index 0abe9d9a0069..652611a4bdcd 100644 --- a/include/linux/generic_serial.h +++ b/include/linux/generic_serial.h @@ -12,6 +12,8 @@ #ifndef GENERIC_SERIAL_H #define GENERIC_SERIAL_H +#include + struct real_driver { void (*disable_tx_interrupts) (void *); void (*enable_tx_interrupts) (void *); @@ -34,7 +36,7 @@ struct gs_port { int xmit_head; int xmit_tail; int xmit_cnt; - struct semaphore port_write_sem; + struct mutex port_write_mutex; int flags; wait_queue_head_t open_wait; wait_queue_head_t close_wait; -- cgit v1.2.3-59-g8ed1b From cf8b8975c3c35d1269bf6f1c6f2ae4efb6909607 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 23 Mar 2006 03:00:45 -0800 Subject: [PATCH] sem2mutex: drivers/ide 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 Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-cd.c | 11 ++++++----- drivers/ide/ide-disk.c | 11 ++++++----- drivers/ide/ide-floppy.c | 11 ++++++----- drivers/ide/ide-tape.c | 19 ++++++++++--------- 4 files changed, 28 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 430d8af35cb1..c7671e188017 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -313,6 +313,7 @@ #include #include #include +#include #include /* For SCSI -> ATAPI command conversion */ @@ -324,7 +325,7 @@ #include "ide-cd.h" -static DECLARE_MUTEX(idecd_ref_sem); +static DEFINE_MUTEX(idecd_ref_mutex); #define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref) @@ -335,11 +336,11 @@ static struct cdrom_info *ide_cd_get(struct gendisk *disk) { struct cdrom_info *cd = NULL; - down(&idecd_ref_sem); + mutex_lock(&idecd_ref_mutex); cd = ide_cd_g(disk); if (cd) kref_get(&cd->kref); - up(&idecd_ref_sem); + mutex_unlock(&idecd_ref_mutex); return cd; } @@ -347,9 +348,9 @@ static void ide_cd_release(struct kref *); static void ide_cd_put(struct cdrom_info *cd) { - down(&idecd_ref_sem); + mutex_lock(&idecd_ref_mutex); kref_put(&cd->kref, ide_cd_release); - up(&idecd_ref_sem); + mutex_unlock(&idecd_ref_mutex); } /**************************************************************************** diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 09086b8b6486..e238b7da824b 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -60,6 +60,7 @@ #include #include #include +#include #define _IDE_DISK @@ -78,7 +79,7 @@ struct ide_disk_obj { struct kref kref; }; -static DECLARE_MUTEX(idedisk_ref_sem); +static DEFINE_MUTEX(idedisk_ref_mutex); #define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref) @@ -89,11 +90,11 @@ static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) { struct ide_disk_obj *idkp = NULL; - down(&idedisk_ref_sem); + mutex_lock(&idedisk_ref_mutex); idkp = ide_disk_g(disk); if (idkp) kref_get(&idkp->kref); - up(&idedisk_ref_sem); + mutex_unlock(&idedisk_ref_mutex); return idkp; } @@ -101,9 +102,9 @@ static void ide_disk_release(struct kref *); static void ide_disk_put(struct ide_disk_obj *idkp) { - down(&idedisk_ref_sem); + mutex_lock(&idedisk_ref_mutex); kref_put(&idkp->kref, ide_disk_release); - up(&idedisk_ref_sem); + mutex_unlock(&idedisk_ref_mutex); } /* diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 1f8db9ac05d1..a53e3ce4a142 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -98,6 +98,7 @@ #include #include #include +#include #include #include @@ -517,7 +518,7 @@ typedef struct { u8 reserved[4]; } idefloppy_mode_parameter_header_t; -static DECLARE_MUTEX(idefloppy_ref_sem); +static DEFINE_MUTEX(idefloppy_ref_mutex); #define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref) @@ -528,11 +529,11 @@ static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk) { struct ide_floppy_obj *floppy = NULL; - down(&idefloppy_ref_sem); + mutex_lock(&idefloppy_ref_mutex); floppy = ide_floppy_g(disk); if (floppy) kref_get(&floppy->kref); - up(&idefloppy_ref_sem); + mutex_unlock(&idefloppy_ref_mutex); return floppy; } @@ -540,9 +541,9 @@ static void ide_floppy_release(struct kref *); static void ide_floppy_put(struct ide_floppy_obj *floppy) { - down(&idefloppy_ref_sem); + mutex_lock(&idefloppy_ref_mutex); kref_put(&floppy->kref, ide_floppy_release); - up(&idefloppy_ref_sem); + mutex_unlock(&idefloppy_ref_mutex); } /* diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 0101d0def7c5..ebc59064b475 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -443,6 +443,7 @@ #include #include #include +#include #include #include @@ -1011,7 +1012,7 @@ typedef struct ide_tape_obj { int debug_level; } idetape_tape_t; -static DECLARE_MUTEX(idetape_ref_sem); +static DEFINE_MUTEX(idetape_ref_mutex); static struct class *idetape_sysfs_class; @@ -1024,11 +1025,11 @@ static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) { struct ide_tape_obj *tape = NULL; - down(&idetape_ref_sem); + mutex_lock(&idetape_ref_mutex); tape = ide_tape_g(disk); if (tape) kref_get(&tape->kref); - up(&idetape_ref_sem); + mutex_unlock(&idetape_ref_mutex); return tape; } @@ -1036,9 +1037,9 @@ static void ide_tape_release(struct kref *); static void ide_tape_put(struct ide_tape_obj *tape) { - down(&idetape_ref_sem); + mutex_lock(&idetape_ref_mutex); kref_put(&tape->kref, ide_tape_release); - up(&idetape_ref_sem); + mutex_unlock(&idetape_ref_mutex); } /* @@ -1290,11 +1291,11 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) { struct ide_tape_obj *tape = NULL; - down(&idetape_ref_sem); + mutex_lock(&idetape_ref_mutex); tape = idetape_devs[i]; if (tape) kref_get(&tape->kref); - up(&idetape_ref_sem); + mutex_unlock(&idetape_ref_mutex); return tape; } @@ -4870,11 +4871,11 @@ static int ide_tape_probe(ide_drive_t *drive) drive->driver_data = tape; - down(&idetape_ref_sem); + mutex_lock(&idetape_ref_mutex); for (minor = 0; idetape_devs[minor]; minor++) ; idetape_devs[minor] = tape; - up(&idetape_ref_sem); + mutex_unlock(&idetape_ref_mutex); idetape_setup(drive, tape, minor); -- cgit v1.2.3-59-g8ed1b From 40953ed87dd68742de0dd1bdecdcdfebfe1d69ae Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 23 Mar 2006 03:00:49 -0800 Subject: [PATCH] snsc kmalloc2kzalloc Change driver to use kzalloc rather than kmalloc+memset Signed-off-by: Jes Sorensen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/snsc.c | 8 +++----- drivers/char/snsc_event.c | 5 +---- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index 0e7d216e7eb0..b543821d8cb4 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2004, 2006 Silicon Graphics, Inc. All rights reserved. */ /* @@ -77,7 +77,7 @@ scdrv_open(struct inode *inode, struct file *file) scd = container_of(inode->i_cdev, struct sysctl_data_s, scd_cdev); /* allocate memory for subchannel data */ - sd = kmalloc(sizeof (struct subch_data_s), GFP_KERNEL); + sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL); if (sd == NULL) { printk("%s: couldn't allocate subchannel data\n", __FUNCTION__); @@ -85,7 +85,6 @@ scdrv_open(struct inode *inode, struct file *file) } /* initialize subch_data_s fields */ - memset(sd, 0, sizeof (struct subch_data_s)); sd->sd_nasid = scd->scd_nasid; sd->sd_subch = ia64_sn_irtr_open(scd->scd_nasid); @@ -394,7 +393,7 @@ scdrv_init(void) sprintf(devnamep, "#%d", geo_slab(geoid)); /* allocate sysctl device data */ - scd = kmalloc(sizeof (struct sysctl_data_s), + scd = kzalloc(sizeof (struct sysctl_data_s), GFP_KERNEL); if (!scd) { printk("%s: failed to allocate device info" @@ -402,7 +401,6 @@ scdrv_init(void) SYSCTL_BASENAME, devname); continue; } - memset(scd, 0, sizeof (struct sysctl_data_s)); /* initialize sysctl device data fields */ scd->scd_nasid = cnodeid_to_nasid(cnode); diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c index a4fa507eed9e..e234d50e142a 100644 --- a/drivers/char/snsc_event.c +++ b/drivers/char/snsc_event.c @@ -287,7 +287,7 @@ scdrv_event_init(struct sysctl_data_s *scd) { int rv; - event_sd = kmalloc(sizeof (struct subch_data_s), GFP_KERNEL); + event_sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL); if (event_sd == NULL) { printk(KERN_WARNING "%s: couldn't allocate subchannel info" " for event monitoring\n", __FUNCTION__); @@ -295,7 +295,6 @@ scdrv_event_init(struct sysctl_data_s *scd) } /* initialize subch_data_s fields */ - memset(event_sd, 0, sizeof (struct subch_data_s)); event_sd->sd_nasid = scd->scd_nasid; spin_lock_init(&event_sd->sd_rlock); @@ -321,5 +320,3 @@ scdrv_event_init(struct sysctl_data_s *scd) return; } } - - -- cgit v1.2.3-59-g8ed1b From 41c28ff1635e71af072c4711ff5fadd5855d48e7 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 23 Mar 2006 03:00:56 -0800 Subject: [PATCH] kill _INLINE_ This patch removes all occurances of _INLINE_ in the kernel. With the exception of tty_flip.h, I've simply removed the inline's since gcc should know best which functions to be inlined. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/hp/sim/simserial.c | 7 +--- arch/xtensa/platform-iss/console.c | 4 --- drivers/char/amiserial.c | 18 ++++------ drivers/isdn/hisax/config.c | 1 - drivers/isdn/hisax/elsa.c | 1 - drivers/serial/68328serial.c | 9 +++-- drivers/serial/au1x00_uart.c | 11 +++--- drivers/serial/crisv10.c | 68 ++++++++++++-------------------------- drivers/serial/m32r_sio.c | 15 ++++----- drivers/serial/sunsu.c | 13 +++----- drivers/tc/zs.c | 9 ++--- include/linux/tty_flip.h | 12 ++----- 12 files changed, 56 insertions(+), 112 deletions(-) (limited to 'drivers') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 626cdc83668b..0e5c6ae50228 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -46,11 +46,6 @@ #define KEYBOARD_INTR 3 /* must match with simulator! */ #define NR_PORTS 1 /* only one port for now */ -#define SERIAL_INLINE 1 - -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#endif #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) @@ -237,7 +232,7 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch) local_irq_restore(flags); } -static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) +static void transmit_chars(struct async_struct *info, int *intr_done) { int count; unsigned long flags; diff --git a/arch/xtensa/platform-iss/console.c b/arch/xtensa/platform-iss/console.c index 94fdfe474ac1..2a580efb58ec 100644 --- a/arch/xtensa/platform-iss/console.c +++ b/arch/xtensa/platform-iss/console.c @@ -31,10 +31,6 @@ #include #include -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#endif - #define SERIAL_MAX_NUM_LINES 1 #define SERIAL_TIMER_VALUE (20 * HZ) diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 7ac365b5d9ec..6602b3156df5 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -46,8 +46,6 @@ /* Sanity checks */ -#define SERIAL_INLINE - #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) #define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s) @@ -95,10 +93,6 @@ static char *serial_version = "4.30"; #include #include -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#endif - #define custom amiga_custom static char *serial_name = "Amiga-builtin serial driver"; @@ -253,14 +247,14 @@ static void rs_start(struct tty_struct *tty) * This routine is used by the interrupt handler to schedule * processing in the software interrupt portion of the driver. */ -static _INLINE_ void rs_sched_event(struct async_struct *info, - int event) +static void rs_sched_event(struct async_struct *info, + int event) { info->event |= 1 << event; tasklet_schedule(&info->tlet); } -static _INLINE_ void receive_chars(struct async_struct *info) +static void receive_chars(struct async_struct *info) { int status; int serdatr; @@ -349,7 +343,7 @@ out: return; } -static _INLINE_ void transmit_chars(struct async_struct *info) +static void transmit_chars(struct async_struct *info) { custom.intreq = IF_TBE; mb(); @@ -389,7 +383,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info) } } -static _INLINE_ void check_modem_status(struct async_struct *info) +static void check_modem_status(struct async_struct *info) { unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR); unsigned char dstatus; @@ -1959,7 +1953,7 @@ done: * number, and identifies which options were configured into this * driver. */ -static _INLINE_ void show_serial_version(void) +static void show_serial_version(void) { printk(KERN_INFO "%s version %s\n", serial_name, serial_version); } diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index df9d65201819..27332506f9f7 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -25,7 +25,6 @@ #include #include #define HISAX_STATUS_BUFSIZE 4096 -#define INCLUDE_INLINE_FUNCS /* * This structure array contains one entry per card. An entry looks diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index 110e9fd669c5..f8ca4b323331 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -108,7 +108,6 @@ static const char *ITACVer[] = #define ELSA_ASSIGN 4 #define RS_ISR_PASS_LIMIT 256 -#define _INLINE_ inline #define FLG_MODEM_ACTIVE 1 /* IPAC AUX */ #define ELSA_IPAC_LINE_LED 0x40 /* Bit 6 Gelbe LED */ diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 7f0f35a05dca..b88a7c1158af 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -101,8 +101,6 @@ struct tty_driver *serial_driver; #define RS_ISR_PASS_LIMIT 256 -#define _INLINE_ inline - static void change_speed(struct m68k_serial *info); /* @@ -262,7 +260,7 @@ static void batten_down_hatches(void) /* Drop into the debugger */ } -static _INLINE_ void status_handle(struct m68k_serial *info, unsigned short status) +static void status_handle(struct m68k_serial *info, unsigned short status) { #if 0 if(status & DCD) { @@ -289,7 +287,8 @@ static _INLINE_ void status_handle(struct m68k_serial *info, unsigned short stat return; } -static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *regs, unsigned short rx) +static void receive_chars(struct m68k_serial *info, struct pt_regs *regs, + unsigned short rx) { struct tty_struct *tty = info->tty; m68328_uart *uart = &uart_addr[info->line]; @@ -359,7 +358,7 @@ clear_and_exit: return; } -static _INLINE_ void transmit_chars(struct m68k_serial *info) +static void transmit_chars(struct m68k_serial *info) { m68328_uart *uart = &uart_addr[info->line]; diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index 29f94bbb79be..948880ac5878 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c @@ -133,13 +133,12 @@ static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = { { "AU1X00_UART",16, UART_CLEAR_FIFO | UART_USE_FIFO }, }; -static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) +static unsigned int serial_in(struct uart_8250_port *up, int offset) { return au_readl((unsigned long)up->port.membase + offset); } -static _INLINE_ void -serial_out(struct uart_8250_port *up, int offset, int value) +static void serial_out(struct uart_8250_port *up, int offset, int value) { au_writel(value, (unsigned long)up->port.membase + offset); } @@ -237,7 +236,7 @@ static void serial8250_enable_ms(struct uart_port *port) serial_out(up, UART_IER, up->ier); } -static _INLINE_ void +static void receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) { struct tty_struct *tty = up->port.info->tty; @@ -312,7 +311,7 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) spin_lock(&up->port.lock); } -static _INLINE_ void transmit_chars(struct uart_8250_port *up) +static void transmit_chars(struct uart_8250_port *up) { struct circ_buf *xmit = &up->port.info->xmit; int count; @@ -346,7 +345,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up) serial8250_stop_tx(&up->port); } -static _INLINE_ void check_modem_status(struct uart_8250_port *up) +static void check_modem_status(struct uart_8250_port *up) { int status; diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index be12623d8544..89700141f87e 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -481,8 +481,6 @@ static char *serial_version = "$Revision: 1.25 $"; #include "serial_compat.h" #endif -#define _INLINE_ inline - struct tty_driver *serial_driver; /* serial subtype definitions */ @@ -591,8 +589,6 @@ static void rs_throttle(struct tty_struct * tty); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); static int rs_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count); -extern _INLINE_ int rs_raw_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count); #ifdef CONFIG_ETRAX_RS485 static int e100_write_rs485(struct tty_struct * tty, int from_user, const unsigned char *buf, int count); @@ -1538,8 +1534,7 @@ e100_enable_rxdma_irq(struct e100_serial *info) /* the tx DMA uses only dma_descr interrupt */ -static _INLINE_ void -e100_disable_txdma_irq(struct e100_serial *info) +static void e100_disable_txdma_irq(struct e100_serial *info) { #ifdef SERIAL_DEBUG_INTR printk("txdma_irq(%d): 0\n",info->line); @@ -1548,8 +1543,7 @@ e100_disable_txdma_irq(struct e100_serial *info) *R_IRQ_MASK2_CLR = info->irq; } -static _INLINE_ void -e100_enable_txdma_irq(struct e100_serial *info) +static void e100_enable_txdma_irq(struct e100_serial *info) { #ifdef SERIAL_DEBUG_INTR printk("txdma_irq(%d): 1\n",info->line); @@ -1558,8 +1552,7 @@ e100_enable_txdma_irq(struct e100_serial *info) *R_IRQ_MASK2_SET = info->irq; } -static _INLINE_ void -e100_disable_txdma_channel(struct e100_serial *info) +static void e100_disable_txdma_channel(struct e100_serial *info) { unsigned long flags; @@ -1599,8 +1592,7 @@ e100_disable_txdma_channel(struct e100_serial *info) } -static _INLINE_ void -e100_enable_txdma_channel(struct e100_serial *info) +static void e100_enable_txdma_channel(struct e100_serial *info) { unsigned long flags; @@ -1625,8 +1617,7 @@ e100_enable_txdma_channel(struct e100_serial *info) restore_flags(flags); } -static _INLINE_ void -e100_disable_rxdma_channel(struct e100_serial *info) +static void e100_disable_rxdma_channel(struct e100_serial *info) { unsigned long flags; @@ -1665,8 +1656,7 @@ e100_disable_rxdma_channel(struct e100_serial *info) } -static _INLINE_ void -e100_enable_rxdma_channel(struct e100_serial *info) +static void e100_enable_rxdma_channel(struct e100_serial *info) { unsigned long flags; @@ -1913,9 +1903,7 @@ rs_start(struct tty_struct *tty) * This routine is used by the interrupt handler to schedule * processing in the software interrupt portion of the driver. */ -static _INLINE_ void -rs_sched_event(struct e100_serial *info, - int event) +static void rs_sched_event(struct e100_serial *info, int event) { if (info->event & (1 << event)) return; @@ -2155,8 +2143,9 @@ add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char fl return 1; } -extern _INLINE_ unsigned int -handle_descr_data(struct e100_serial *info, struct etrax_dma_descr *descr, unsigned int recvl) +static unsigned int handle_descr_data(struct e100_serial *info, + struct etrax_dma_descr *descr, + unsigned int recvl) { struct etrax_recv_buffer *buffer = phys_to_virt(descr->buf) - sizeof *buffer; @@ -2182,8 +2171,7 @@ handle_descr_data(struct e100_serial *info, struct etrax_dma_descr *descr, unsig return recvl; } -static _INLINE_ unsigned int -handle_all_descr_data(struct e100_serial *info) +static unsigned int handle_all_descr_data(struct e100_serial *info) { struct etrax_dma_descr *descr; unsigned int recvl; @@ -2230,8 +2218,7 @@ handle_all_descr_data(struct e100_serial *info) return ret; } -static _INLINE_ void -receive_chars_dma(struct e100_serial *info) +static void receive_chars_dma(struct e100_serial *info) { struct tty_struct *tty; unsigned char rstat; @@ -2292,8 +2279,7 @@ receive_chars_dma(struct e100_serial *info) *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart); } -static _INLINE_ int -start_recv_dma(struct e100_serial *info) +static int start_recv_dma(struct e100_serial *info) { struct etrax_dma_descr *descr = info->rec_descr; struct etrax_recv_buffer *buffer; @@ -2348,11 +2334,6 @@ start_receive(struct e100_serial *info) } -static _INLINE_ void -status_handle(struct e100_serial *info, unsigned short status) -{ -} - /* the bits in the MASK2 register are laid out like this: DMAI_EOP DMAI_DESCR DMAO_EOP DMAO_DESCR where I is the input channel and O is the output channel for the port. @@ -2454,8 +2435,7 @@ rec_interrupt(int irq, void *dev_id, struct pt_regs * regs) return IRQ_RETVAL(handled); } /* rec_interrupt */ -static _INLINE_ int -force_eop_if_needed(struct e100_serial *info) +static int force_eop_if_needed(struct e100_serial *info) { /* We check data_avail bit to determine if data has * arrived since last time @@ -2499,8 +2479,7 @@ force_eop_if_needed(struct e100_serial *info) return 1; } -extern _INLINE_ void -flush_to_flip_buffer(struct e100_serial *info) +static void flush_to_flip_buffer(struct e100_serial *info) { struct tty_struct *tty; struct etrax_recv_buffer *buffer; @@ -2611,8 +2590,7 @@ flush_to_flip_buffer(struct e100_serial *info) tty_flip_buffer_push(tty); } -static _INLINE_ void -check_flush_timeout(struct e100_serial *info) +static void check_flush_timeout(struct e100_serial *info) { /* Flip what we've got (if we can) */ flush_to_flip_buffer(info); @@ -2741,7 +2719,7 @@ TODO: The break will be delayed until an F or V character is received. */ -extern _INLINE_ +static struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) { unsigned long data_read; @@ -2875,8 +2853,7 @@ more_data: return info; } -extern _INLINE_ -struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) +static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) { unsigned char rstat; @@ -2995,7 +2972,7 @@ struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) return info; } /* handle_ser_rx_interrupt */ -extern _INLINE_ void handle_ser_tx_interrupt(struct e100_serial *info) +static void handle_ser_tx_interrupt(struct e100_serial *info) { unsigned long flags; @@ -3621,9 +3598,8 @@ rs_flush_chars(struct tty_struct *tty) restore_flags(flags); } -extern _INLINE_ int -rs_raw_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) +static int rs_raw_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) { int c, ret = 0; struct e100_serial *info = (struct e100_serial *)tty->driver_data; @@ -4710,7 +4686,7 @@ rs_open(struct tty_struct *tty, struct file * filp) * /proc fs routines.... */ -extern _INLINE_ int line_info(char *buf, struct e100_serial *info) +static int line_info(char *buf, struct e100_serial *info) { char stat_buf[30]; int ret; diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 876bc5e027bb..e9c10c0a30fc 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -248,17 +248,17 @@ static void sio_error(int *status) #endif /* CONFIG_SERIAL_M32R_PLDSIO */ -static _INLINE_ unsigned int sio_in(struct uart_sio_port *up, int offset) +static unsigned int sio_in(struct uart_sio_port *up, int offset) { return __sio_in(up->port.iobase + offset); } -static _INLINE_ void sio_out(struct uart_sio_port *up, int offset, int value) +static void sio_out(struct uart_sio_port *up, int offset, int value) { __sio_out(value, up->port.iobase + offset); } -static _INLINE_ unsigned int serial_in(struct uart_sio_port *up, int offset) +static unsigned int serial_in(struct uart_sio_port *up, int offset) { if (!offset) return 0; @@ -266,8 +266,7 @@ static _INLINE_ unsigned int serial_in(struct uart_sio_port *up, int offset) return __sio_in(offset); } -static _INLINE_ void -serial_out(struct uart_sio_port *up, int offset, int value) +static void serial_out(struct uart_sio_port *up, int offset, int value) { if (!offset) return; @@ -326,8 +325,8 @@ static void m32r_sio_enable_ms(struct uart_port *port) serial_out(up, UART_IER, up->ier); } -static _INLINE_ void receive_chars(struct uart_sio_port *up, int *status, - struct pt_regs *regs) +static void receive_chars(struct uart_sio_port *up, int *status, + struct pt_regs *regs) { struct tty_struct *tty = up->port.info->tty; unsigned char ch; @@ -400,7 +399,7 @@ static _INLINE_ void receive_chars(struct uart_sio_port *up, int *status, tty_flip_buffer_push(tty); } -static _INLINE_ void transmit_chars(struct uart_sio_port *up) +static void transmit_chars(struct uart_sio_port *up) { struct circ_buf *xmit = &up->port.info->xmit; int count; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 7fc3d3b41d18..9fe2283d91e5 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -102,9 +102,7 @@ struct uart_sunsu_port { #endif }; -#define _INLINE_ - -static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset) +static unsigned int serial_in(struct uart_sunsu_port *up, int offset) { offset <<= up->port.regshift; @@ -121,8 +119,7 @@ static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset) } } -static _INLINE_ void -serial_out(struct uart_sunsu_port *up, int offset, int value) +static void serial_out(struct uart_sunsu_port *up, int offset, int value) { #ifndef CONFIG_SPARC64 /* @@ -316,7 +313,7 @@ static void sunsu_enable_ms(struct uart_port *port) spin_unlock_irqrestore(&up->port.lock, flags); } -static _INLINE_ struct tty_struct * +static struct tty_struct * receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs) { struct tty_struct *tty = up->port.info->tty; @@ -395,7 +392,7 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs return tty; } -static _INLINE_ void transmit_chars(struct uart_sunsu_port *up) +static void transmit_chars(struct uart_sunsu_port *up) { struct circ_buf *xmit = &up->port.info->xmit; int count; @@ -431,7 +428,7 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up) __stop_tx(up); } -static _INLINE_ void check_modem_status(struct uart_sunsu_port *up) +static void check_modem_status(struct uart_sunsu_port *up) { int status; diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index 6756d0fab6fe..2dffa8e303b2 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c @@ -186,8 +186,6 @@ static struct tty_driver *serial_driver; #define RS_STROBE_TIME 10 #define RS_ISR_PASS_LIMIT 256 -#define _INLINE_ inline - static void probe_sccs(void); static void change_speed(struct dec_serial *info); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); @@ -344,14 +342,13 @@ static inline void rs_recv_clear(struct dec_zschannel *zsc) * This routine is used by the interrupt handler to schedule * processing in the software interrupt portion of the driver. */ -static _INLINE_ void rs_sched_event(struct dec_serial *info, int event) +static void rs_sched_event(struct dec_serial *info, int event) { info->event |= 1 << event; tasklet_schedule(&info->tlet); } -static _INLINE_ void receive_chars(struct dec_serial *info, - struct pt_regs *regs) +static void receive_chars(struct dec_serial *info, struct pt_regs *regs) { struct tty_struct *tty = info->tty; unsigned char ch, stat, flag; @@ -441,7 +438,7 @@ static void transmit_chars(struct dec_serial *info) rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); } -static _INLINE_ void status_handle(struct dec_serial *info) +static void status_handle(struct dec_serial *info) { unsigned char stat; diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 222faf97d5f9..0c6169fff366 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -7,14 +7,8 @@ extern int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *c extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size); extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size); -#ifdef INCLUDE_INLINE_FUNCS -#define _INLINE_ extern -#else -#define _INLINE_ static __inline__ -#endif - -_INLINE_ int tty_insert_flip_char(struct tty_struct *tty, - unsigned char ch, char flag) +static inline int tty_insert_flip_char(struct tty_struct *tty, + unsigned char ch, char flag) { struct tty_buffer *tb = tty->buf.tail; if (tb && tb->active && tb->used < tb->size) { @@ -25,7 +19,7 @@ _INLINE_ int tty_insert_flip_char(struct tty_struct *tty, return tty_insert_flip_string_flags(tty, &ch, &flag, 1); } -_INLINE_ void tty_schedule_flip(struct tty_struct *tty) +static inline void tty_schedule_flip(struct tty_struct *tty) { unsigned long flags; spin_lock_irqsave(&tty->buf.lock, flags); -- cgit v1.2.3-59-g8ed1b From eb8782ef72758b8700963ef8b949f5c812e6d630 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Thu, 23 Mar 2006 03:00:57 -0800 Subject: [PATCH] PnPBIOS: Missing SMALL_TAG_ENDDEP tag Without the attached, the kernel complains about my BIOS' PNP tables. It was ACKed before, but never merged: http://marc.theaimsgroup.com/?l=linux-kernel&m=110237794007900&w=2 Cc: Adam Belay Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pnp/pnpbios/rsparser.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 5e38cd7335f7..c89c98a2cca8 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -448,11 +448,7 @@ pnpbios_parse_resource_option_data(unsigned char * p, unsigned char * end, struc break; case SMALL_TAG_END: - if (option_independent != option) - printk(KERN_WARNING "PnPBIOS: Missing SMALL_TAG_ENDDEP tag\n"); - p = p + 2; - return (unsigned char *)p; - break; + return p + 2; default: /* an unkown tag */ len_err: -- cgit v1.2.3-59-g8ed1b From 394e3902c55e667945f6f1c2bdbc59842cce70f7 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 23 Mar 2006 03:01:05 -0800 Subject: [PATCH] more for_each_cpu() conversions When we stop allocating percpu memory for not-possible CPUs we must not touch the percpu data for not-possible CPUs at all. The correct way of doing this is to test cpu_possible() or to use for_each_cpu(). This patch is a kernel-wide sweep of all instances of NR_CPUS. I found very few instances of this bug, if any. But the patch converts lots of open-coded test to use the preferred helper macros. Cc: Mikael Starvik Cc: David Howells Acked-by: Kyle McMartin Cc: Anton Blanchard Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: Paul Mundt Cc: "David S. Miller" Cc: William Lee Irwin III Cc: Andi Kleen Cc: Christian Zankel Cc: Philippe Elie Cc: Nathan Scott Cc: Jens Axboe Cc: Eric Dumazet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/cris/kernel/irq.c | 10 ++++------ arch/frv/kernel/irq.c | 10 ++++------ arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 4 +--- arch/i386/kernel/io_apic.c | 22 +++++++++------------- arch/i386/kernel/nmi.c | 4 ++-- arch/i386/oprofile/nmi_int.c | 7 ++----- arch/m32r/kernel/irq.c | 10 ++++------ arch/mips/kernel/irq.c | 10 ++++------ arch/mips/kernel/smp.c | 4 ++-- arch/mips/sgi-ip27/ip27-irq.c | 5 +---- arch/parisc/kernel/smp.c | 25 ++++++++++--------------- arch/powerpc/kernel/irq.c | 5 ++--- arch/powerpc/kernel/setup-common.c | 5 ++--- arch/powerpc/kernel/setup_32.c | 5 ++--- arch/powerpc/platforms/powermac/smp.c | 4 +--- arch/ppc/kernel/setup.c | 10 ++++------ arch/s390/kernel/smp.c | 4 +--- arch/sh/kernel/irq.c | 5 ++--- arch/sh/kernel/setup.c | 5 ++--- arch/sh64/kernel/irq.c | 5 ++--- arch/sparc/kernel/irq.c | 5 ++--- arch/sparc/kernel/smp.c | 24 ++++++++++-------------- arch/sparc/kernel/sun4d_irq.c | 8 +++----- arch/sparc/kernel/sun4d_smp.c | 8 +++----- arch/sparc/kernel/sun4m_smp.c | 6 ++---- arch/sparc64/kernel/irq.c | 4 +--- arch/sparc64/kernel/smp.c | 30 ++++++++++++------------------ arch/x86_64/kernel/irq.c | 21 ++++++++------------- arch/x86_64/kernel/nmi.c | 4 +--- arch/xtensa/kernel/irq.c | 15 ++++++--------- drivers/net/loopback.c | 4 +--- drivers/oprofile/cpu_buffer.c | 3 +-- fs/xfs/linux-2.6/xfs_stats.c | 7 ++----- fs/xfs/linux-2.6/xfs_sysctl.c | 3 +-- include/asm-alpha/mmu_context.h | 5 ++--- include/asm-alpha/topology.h | 4 ++-- include/asm-generic/percpu.h | 7 +++---- include/asm-powerpc/percpu.h | 7 +++---- include/asm-s390/percpu.h | 7 +++---- include/asm-sparc64/percpu.h | 7 +++---- include/asm-x86_64/percpu.h | 7 +++---- include/linux/genhd.h | 14 ++++---------- 42 files changed, 137 insertions(+), 222 deletions(-) (limited to 'drivers') diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c index 30deaf1b728a..b504def3e346 100644 --- a/arch/cris/kernel/irq.c +++ b/arch/cris/kernel/irq.c @@ -52,9 +52,8 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for (j=0; jtypename); seq_printf(p, " %s", action->name); diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c index 27ab4c30aac6..11fa326a8f62 100644 --- a/arch/frv/kernel/irq.c +++ b/arch/frv/kernel/irq.c @@ -75,9 +75,8 @@ int show_interrupts(struct seq_file *p, void *v) switch (i) { case 0: seq_printf(p, " "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "CPU%d ",j); + for_each_online_cpu(j) + seq_printf(p, "CPU%d ",j); seq_putc(p, '\n'); break; @@ -100,9 +99,8 @@ int show_interrupts(struct seq_file *p, void *v) #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); #else - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i - 1]); + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_cpu(j).irqs[i - 1]); #endif level = group->sources[ix]->level - frv_irq_levels; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index e11a09207ec8..3d5110b65cc3 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -1145,9 +1145,7 @@ static int __cpuinit powernowk8_init(void) { unsigned int i, supported_cpus = 0; - for (i=0; i CPU_IRQ(i)) { @@ -441,9 +439,7 @@ tryanothercpu: */ tmp_cpu_irq = 0; tmp_loaded = -1; - for (i = 0; i < NR_CPUS; i++) { - if (!cpu_online(i)) - continue; + for_each_online_cpu(i) { if (i != CPU_TO_PACKAGEINDEX(i)) continue; if (max_cpu_irq <= CPU_IRQ(i)) @@ -619,9 +615,7 @@ static int __init balanced_irq_init(void) if (smp_num_siblings > 1 && !cpus_empty(tmp)) physical_balance = 1; - for (i = 0; i < NR_CPUS; i++) { - if (!cpu_online(i)) - continue; + for_each_online_cpu(i) { irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL); irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL); if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) { @@ -638,9 +632,11 @@ static int __init balanced_irq_init(void) else printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq"); failed: - for (i = 0; i < NR_CPUS; i++) { + for_each_cpu(i) { kfree(irq_cpu_data[i].irq_delta); + irq_cpu_data[i].irq_delta = NULL; kfree(irq_cpu_data[i].last_irq); + irq_cpu_data[i].last_irq = NULL; } return 0; } diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 1db34effdd8d..9074818b9473 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -143,7 +143,7 @@ static int __init check_nmi_watchdog(void) local_irq_enable(); mdelay((10*1000)/nmi_hz); // wait 10 ticks - for (cpu = 0; cpu < NR_CPUS; cpu++) { + for_each_cpu(cpu) { #ifdef CONFIG_SMP /* Check cpu_callin_map here because that is set after the timer is started. */ @@ -510,7 +510,7 @@ void touch_nmi_watchdog (void) * Just reset the alert counters, (other CPUs might be * spinning on locks we hold): */ - for (i = 0; i < NR_CPUS; i++) + for_each_cpu(i) alert_counter[i] = 0; /* diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c index 0493e8b8ec49..1accce50c2c7 100644 --- a/arch/i386/oprofile/nmi_int.c +++ b/arch/i386/oprofile/nmi_int.c @@ -122,7 +122,7 @@ static void nmi_save_registers(void * dummy) static void free_msrs(void) { int i; - for (i = 0; i < NR_CPUS; ++i) { + for_each_cpu(i) { kfree(cpu_msrs[i].counters); cpu_msrs[i].counters = NULL; kfree(cpu_msrs[i].controls); @@ -138,10 +138,7 @@ static int allocate_msrs(void) size_t counters_size = sizeof(struct op_msr) * model->num_counters; int i; - for (i = 0; i < NR_CPUS; ++i) { - if (!cpu_online(i)) - continue; - + for_each_online_cpu(i) { cpu_msrs[i].counters = kmalloc(counters_size, GFP_KERNEL); if (!cpu_msrs[i].counters) { success = 0; diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c index 1ce63926a3c0..a4634b06f675 100644 --- a/arch/m32r/kernel/irq.c +++ b/arch/m32r/kernel/irq.c @@ -37,9 +37,8 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for (j=0; jtypename); seq_printf(p, " %s", action->name); diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 7d93992e462c..3dd76b3d2967 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -68,9 +68,8 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for (j=0; jtypename); seq_printf(p, " %s", action->name); diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 06ed90752424..78d171bfa331 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -167,8 +167,8 @@ int smp_call_function (void (*func) (void *info), void *info, int retry, mb(); /* Send a message to all other CPUs and wait for them to respond */ - for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i) && i != cpu) + for_each_online_cpu(i) + if (i != cpu) core_send_ipi(i, SMP_CALL_FUNCTION); /* Wait for response */ diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 73e5e52781d8..2854ac4c9be1 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -88,12 +88,9 @@ static inline int find_level(cpuid_t *cpunum, int irq) { int cpu, i; - for (cpu = 0; cpu <= NR_CPUS; cpu++) { + for_each_online_cpu(cpu) { struct slice_data *si = cpu_data[cpu].data; - if (!cpu_online(cpu)) - continue; - for (i = BASE_PCI_IRQ; i < LEVELS_PER_SLICE; i++) if (si->level_to_irq[i] == irq) { *cpunum = cpu; diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 25564b7ca6bb..d6ac1c60a471 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -298,8 +298,8 @@ send_IPI_allbutself(enum ipi_message_type op) { int i; - for (i = 0; i < NR_CPUS; i++) { - if (cpu_online(i) && i != smp_processor_id()) + for_each_online_cpu(i) { + if (i != smp_processor_id()) send_IPI_single(i, op); } } @@ -643,14 +643,13 @@ int sys_cpus(int argc, char **argv) if ( argc == 1 ){ #ifdef DUMP_MORE_STATE - for(i=0; iflags & SA_INTERRUPT) ? '+' : ' ', diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 4219dd2ce3a2..41bb9596be48 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -249,11 +249,9 @@ void __init smp4d_boot_cpus(void) } else { unsigned long bogosum = 0; - for(i = 0; i < NR_CPUS; i++) { - if (cpu_isset(i, cpu_present_map)) { - bogosum += cpu_data(i).udelay_val; - smp_highest_cpu = i; - } + for_each_present_cpu(i) { + bogosum += cpu_data(i).udelay_val; + smp_highest_cpu = i; } SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100)); printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index fbbd8a474c4c..1dde312eebda 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -218,10 +218,8 @@ void __init smp4m_boot_cpus(void) cpu_present_map = cpumask_of_cpu(smp_processor_id()); } else { unsigned long bogosum = 0; - for(i = 0; i < NR_CPUS; i++) { - if (cpu_isset(i, cpu_present_map)) - bogosum += cpu_data(i).udelay_val; - } + for_each_present_cpu(i) + bogosum += cpu_data(i).udelay_val; printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 8c93ba655b33..e505a4125e35 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -117,9 +117,7 @@ int show_interrupts(struct seq_file *p, void *v) #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); #else - for (j = 0; j < NR_CPUS; j++) { - if (!cpu_online(j)) - continue; + for_each_online_cpu(j) { seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); } diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 373a701c90a5..1b6e2ade1008 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -57,25 +57,21 @@ void smp_info(struct seq_file *m) int i; seq_printf(m, "State:\n"); - for (i = 0; i < NR_CPUS; i++) { - if (cpu_online(i)) - seq_printf(m, - "CPU%d:\t\tonline\n", i); - } + for_each_online_cpu(i) + seq_printf(m, "CPU%d:\t\tonline\n", i); } void smp_bogo(struct seq_file *m) { int i; - for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i)) - seq_printf(m, - "Cpu%dBogo\t: %lu.%02lu\n" - "Cpu%dClkTck\t: %016lx\n", - i, cpu_data(i).udelay_val / (500000/HZ), - (cpu_data(i).udelay_val / (5000/HZ)) % 100, - i, cpu_data(i).clock_tick); + for_each_online_cpu(i) + seq_printf(m, + "Cpu%dBogo\t: %lu.%02lu\n" + "Cpu%dClkTck\t: %016lx\n", + i, cpu_data(i).udelay_val / (500000/HZ), + (cpu_data(i).udelay_val / (5000/HZ)) % 100, + i, cpu_data(i).clock_tick); } void __init smp_store_cpu_info(int id) @@ -1282,7 +1278,7 @@ int setup_profiling_timer(unsigned int multiplier) return -EINVAL; spin_lock_irqsave(&prof_setup_lock, flags); - for (i = 0; i < NR_CPUS; i++) + for_each_cpu(i) prof_multiplier(i) = multiplier; current_tick_offset = (timer_tick_offset / multiplier); spin_unlock_irqrestore(&prof_setup_lock, flags); @@ -1384,10 +1380,8 @@ void __init smp_cpus_done(unsigned int max_cpus) unsigned long bogosum = 0; int i; - for (i = 0; i < NR_CPUS; i++) { - if (cpu_online(i)) - bogosum += cpu_data(i).udelay_val; - } + for_each_online_cpu(i) + bogosum += cpu_data(i).udelay_val; printk("Total of %ld processors activated " "(%lu.%02lu BogoMIPS).\n", (long) num_online_cpus(), diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c index 30d2a1e545fe..d8bd0b345b1e 100644 --- a/arch/x86_64/kernel/irq.c +++ b/arch/x86_64/kernel/irq.c @@ -38,9 +38,8 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for (j=0; jtypename); @@ -68,15 +65,13 @@ skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } else if (i == NR_IRQS) { seq_printf(p, "NMI: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count); + for_each_online_cpu(j) + seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count); seq_putc(p, '\n'); #ifdef CONFIG_X86_LOCAL_APIC seq_printf(p, "LOC: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs); + for_each_online_cpu(j) + seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs); seq_putc(p, '\n'); #endif seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 5bf17e41cd2d..66c009e10bac 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -162,9 +162,7 @@ int __init check_nmi_watchdog (void) local_irq_enable(); mdelay((10*1000)/nmi_hz); // wait 10 ticks - for (cpu = 0; cpu < NR_CPUS; cpu++) { - if (!cpu_online(cpu)) - continue; + for_each_online_cpu(cpu) { if (cpu_pda(cpu)->__nmi_count - counts[cpu] <= 5) { endflag = 1; printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n", diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index 4cbf6d91571f..51f9bed455fa 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c @@ -83,9 +83,8 @@ int show_interrupts(struct seq_file *p, void *v) if (i == 0) { seq_printf(p, " "); - for (j=0; jtypename); seq_printf(p, " %s", action->name); @@ -113,9 +111,8 @@ skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } else if (i == NR_IRQS) { seq_printf(p, "NMI: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", nmi_count(j)); + for_each_online_cpu(j) + seq_printf(p, "%10u ", nmi_count(j)); seq_putc(p, '\n'); seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); } diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 690a1aae0b34..0c13795dca38 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -172,11 +172,9 @@ static struct net_device_stats *get_stats(struct net_device *dev) memset(stats, 0, sizeof(struct net_device_stats)); - for (i=0; i < NR_CPUS; i++) { + for_each_cpu(i) { struct net_device_stats *lb_stats; - if (!cpu_possible(i)) - continue; lb_stats = &per_cpu(loopback_stats, i); stats->rx_bytes += lb_stats->rx_bytes; stats->tx_bytes += lb_stats->tx_bytes; diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 78193e4bbdb5..330d3869b41e 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -38,9 +38,8 @@ void free_cpu_buffers(void) { int i; - for_each_online_cpu(i) { + for_each_online_cpu(i) vfree(cpu_buffer[i].buffer); - } } int alloc_cpu_buffers(void) diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c index 8955720a2c6b..713e6a7505d0 100644 --- a/fs/xfs/linux-2.6/xfs_stats.c +++ b/fs/xfs/linux-2.6/xfs_stats.c @@ -62,18 +62,15 @@ xfs_read_xfsstats( while (j < xstats[i].endpoint) { val = 0; /* sum over all cpus */ - for (c = 0; c < NR_CPUS; c++) { - if (!cpu_possible(c)) continue; + for_each_cpu(c) val += *(((__u32*)&per_cpu(xfsstats, c) + j)); - } len += sprintf(buffer + len, " %u", val); j++; } buffer[len++] = '\n'; } /* extra precision counters */ - for (i = 0; i < NR_CPUS; i++) { - if (!cpu_possible(i)) continue; + for_each_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 a02564972420..7079cc837210 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/linux-2.6/xfs_sysctl.c @@ -38,8 +38,7 @@ xfs_stats_clear_proc_handler( if (!ret && write && *valp) { printk("XFS Clearing xfsstats\n"); - for (c = 0; c < NR_CPUS; c++) { - if (!cpu_possible(c)) continue; + for_each_cpu(c) { preempt_disable(); /* save vn_active, it's a universal truth! */ vn_active = per_cpu(xfsstats, c).vn_active; diff --git a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h index 6f92482cc96c..0c017fc181c1 100644 --- a/include/asm-alpha/mmu_context.h +++ b/include/asm-alpha/mmu_context.h @@ -231,9 +231,8 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm) { int i; - for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i)) - mm->context[i] = 0; + for_each_online_cpu(i) + mm->context[i] = 0; if (tsk != current) task_thread_info(tsk)->pcb.ptbr = ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT; diff --git a/include/asm-alpha/topology.h b/include/asm-alpha/topology.h index eb740e280d9c..420ccde6b916 100644 --- a/include/asm-alpha/topology.h +++ b/include/asm-alpha/topology.h @@ -27,8 +27,8 @@ static inline cpumask_t node_to_cpumask(int node) cpumask_t node_cpu_mask = CPU_MASK_NONE; int cpu; - for(cpu = 0; cpu < NR_CPUS; cpu++) { - if (cpu_online(cpu) && (cpu_to_node(cpu) == node)) + for_each_online_cpu(cpu) { + if (cpu_to_node(cpu) == node) cpu_set(cpu, node_cpu_mask); } diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h index 9044aeb37828..78cf45547e31 100644 --- a/include/asm-generic/percpu.h +++ b/include/asm-generic/percpu.h @@ -19,10 +19,9 @@ extern unsigned long __per_cpu_offset[NR_CPUS]; #define percpu_modcopy(pcpudst, src, size) \ do { \ unsigned int __i; \ - for (__i = 0; __i < NR_CPUS; __i++) \ - if (cpu_possible(__i)) \ - memcpy((pcpudst)+__per_cpu_offset[__i], \ - (src), (size)); \ + for_each_cpu(__i) \ + memcpy((pcpudst)+__per_cpu_offset[__i], \ + (src), (size)); \ } while (0) #else /* ! SMP */ diff --git a/include/asm-powerpc/percpu.h b/include/asm-powerpc/percpu.h index e31922c50e53..464301cd0d03 100644 --- a/include/asm-powerpc/percpu.h +++ b/include/asm-powerpc/percpu.h @@ -27,10 +27,9 @@ #define percpu_modcopy(pcpudst, src, size) \ do { \ unsigned int __i; \ - for (__i = 0; __i < NR_CPUS; __i++) \ - if (cpu_possible(__i)) \ - memcpy((pcpudst)+__per_cpu_offset(__i), \ - (src), (size)); \ + for_each_cpu(__i) \ + memcpy((pcpudst)+__per_cpu_offset(__i), \ + (src), (size)); \ } while (0) extern void setup_per_cpu_areas(void); diff --git a/include/asm-s390/percpu.h b/include/asm-s390/percpu.h index 123fcaca295e..e10ed87094f0 100644 --- a/include/asm-s390/percpu.h +++ b/include/asm-s390/percpu.h @@ -46,10 +46,9 @@ extern unsigned long __per_cpu_offset[NR_CPUS]; #define percpu_modcopy(pcpudst, src, size) \ do { \ unsigned int __i; \ - for (__i = 0; __i < NR_CPUS; __i++) \ - if (cpu_possible(__i)) \ - memcpy((pcpudst)+__per_cpu_offset[__i], \ - (src), (size)); \ + for_each_cpu(__i) \ + memcpy((pcpudst)+__per_cpu_offset[__i], \ + (src), (size)); \ } while (0) #else /* ! SMP */ diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h index aea4e51e7cd1..82032e159a76 100644 --- a/include/asm-sparc64/percpu.h +++ b/include/asm-sparc64/percpu.h @@ -26,10 +26,9 @@ register unsigned long __local_per_cpu_offset asm("g5"); #define percpu_modcopy(pcpudst, src, size) \ do { \ unsigned int __i; \ - for (__i = 0; __i < NR_CPUS; __i++) \ - if (cpu_possible(__i)) \ - memcpy((pcpudst)+__per_cpu_offset(__i), \ - (src), (size)); \ + for_each_cpu(__i) \ + memcpy((pcpudst)+__per_cpu_offset(__i), \ + (src), (size)); \ } while (0) #else /* ! SMP */ diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h index 29a6b0408f75..4405b4adeaba 100644 --- a/include/asm-x86_64/percpu.h +++ b/include/asm-x86_64/percpu.h @@ -26,10 +26,9 @@ #define percpu_modcopy(pcpudst, src, size) \ do { \ unsigned int __i; \ - for (__i = 0; __i < NR_CPUS; __i++) \ - if (cpu_possible(__i)) \ - memcpy((pcpudst)+__per_cpu_offset(__i), \ - (src), (size)); \ + for_each_cpu(__i) \ + memcpy((pcpudst)+__per_cpu_offset(__i), \ + (src), (size)); \ } while (0) extern void setup_per_cpu_areas(void); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index eef5ccdcd731..fd647fde5ec1 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -149,22 +149,16 @@ struct disk_attribute { ({ \ typeof(gendiskp->dkstats->field) res = 0; \ int i; \ - for (i=0; i < NR_CPUS; i++) { \ - if (!cpu_possible(i)) \ - continue; \ + for_each_cpu(i) \ res += per_cpu_ptr(gendiskp->dkstats, i)->field; \ - } \ res; \ }) static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { int i; - for (i=0; i < NR_CPUS; i++) { - if (cpu_possible(i)) { - memset(per_cpu_ptr(gendiskp->dkstats, i), value, - sizeof (struct disk_stats)); - } - } + for_each_cpu(i) + memset(per_cpu_ptr(gendiskp->dkstats, i), value, + sizeof (struct disk_stats)); } #else -- cgit v1.2.3-59-g8ed1b From 2056a782f8e7e65fd4bfd027506b4ce1c5e9ccd4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 23 Mar 2006 20:00:26 +0100 Subject: [PATCH] Block queue IO tracing support (blktrace) as of 2006-03-23 Signed-off-by: Jens Axboe --- block/Kconfig | 12 + block/Makefile | 2 + block/blktrace.c | 538 +++++++++++++++++++++++++++++++++++++++++++ block/elevator.c | 4 + block/ioctl.c | 6 + block/ll_rw_blk.c | 44 +++- drivers/block/cciss.c | 2 + drivers/md/dm.c | 13 +- fs/bio.c | 4 + fs/compat_ioctl.c | 1 + include/linux/blkdev.h | 3 + include/linux/blktrace_api.h | 277 ++++++++++++++++++++++ include/linux/compat_ioctl.h | 4 + include/linux/fs.h | 4 + include/linux/sched.h | 1 + kernel/fork.c | 1 + mm/highmem.c | 3 + 17 files changed, 916 insertions(+), 3 deletions(-) create mode 100644 block/blktrace.c create mode 100644 include/linux/blktrace_api.h (limited to 'drivers') diff --git a/block/Kconfig b/block/Kconfig index 377f6dd20e17..96783645092d 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -11,4 +11,16 @@ config LBD your machine, or if you want to have a raid or loopback device bigger than 2TB. Otherwise say N. +config BLK_DEV_IO_TRACE + bool "Support for tracing block io actions" + select RELAY + select DEBUG_FS + help + Say Y here, if you want to be able to trace the block layer actions + on a given queue. Tracing allows you to see any traffic happening + on a block device queue. For more information (and the user space + support tools needed), fetch the blktrace app from: + + git://brick.kernel.dk/data/git/blktrace.git + source block/Kconfig.iosched diff --git a/block/Makefile b/block/Makefile index 7e4f93e2b44e..c05de0e0037f 100644 --- a/block/Makefile +++ b/block/Makefile @@ -8,3 +8,5 @@ obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o obj-$(CONFIG_IOSCHED_AS) += as-iosched.o obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o + +obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o diff --git a/block/blktrace.c b/block/blktrace.c new file mode 100644 index 000000000000..36f3a172275f --- /dev/null +++ b/block/blktrace.c @@ -0,0 +1,538 @@ +/* + * Copyright (C) 2006 Jens Axboe + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_PER_CPU(unsigned long long, blk_trace_cpu_offset) = { 0, }; +static unsigned int blktrace_seq __read_mostly = 1; + +/* + * Send out a notify for this process, if we haven't done so since a trace + * started + */ +static void trace_note_tsk(struct blk_trace *bt, struct task_struct *tsk) +{ + struct blk_io_trace *t; + + t = relay_reserve(bt->rchan, sizeof(*t) + sizeof(tsk->comm)); + if (t) { + t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; + t->device = bt->dev; + t->action = BLK_TC_ACT(BLK_TC_NOTIFY); + t->pid = tsk->pid; + t->cpu = smp_processor_id(); + t->pdu_len = sizeof(tsk->comm); + memcpy((void *) t + sizeof(*t), tsk->comm, t->pdu_len); + tsk->btrace_seq = blktrace_seq; + } +} + +static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector, + pid_t pid) +{ + if (((bt->act_mask << BLK_TC_SHIFT) & what) == 0) + return 1; + if (sector < bt->start_lba || sector > bt->end_lba) + return 1; + if (bt->pid && pid != bt->pid) + return 1; + + return 0; +} + +/* + * Data direction bit lookup + */ +static u32 ddir_act[2] __read_mostly = { BLK_TC_ACT(BLK_TC_READ), BLK_TC_ACT(BLK_TC_WRITE) }; + +/* + * Bio action bits of interest + */ +static u32 bio_act[3] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_ACT(BLK_TC_SYNC) }; + +/* + * More could be added as needed, taking care to increment the decrementer + * to get correct indexing + */ +#define trace_barrier_bit(rw) \ + (((rw) & (1 << BIO_RW_BARRIER)) >> (BIO_RW_BARRIER - 0)) +#define trace_sync_bit(rw) \ + (((rw) & (1 << BIO_RW_SYNC)) >> (BIO_RW_SYNC - 1)) + +/* + * The worker for the various blk_add_trace*() types. Fills out a + * blk_io_trace structure and places it in a per-cpu subbuffer. + */ +void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, + int rw, u32 what, int error, int pdu_len, void *pdu_data) +{ + struct task_struct *tsk = current; + struct blk_io_trace *t; + unsigned long flags; + unsigned long *sequence; + pid_t pid; + int cpu; + + if (unlikely(bt->trace_state != Blktrace_running)) + return; + + what |= ddir_act[rw & WRITE]; + what |= bio_act[trace_barrier_bit(rw)]; + what |= bio_act[trace_sync_bit(rw)]; + + pid = tsk->pid; + if (unlikely(act_log_check(bt, what, sector, pid))) + return; + + /* + * A word about the locking here - we disable interrupts to reserve + * some space in the relay per-cpu buffer, to prevent an irq + * from coming in and stepping on our toes. Once reserved, it's + * enough to get preemption disabled to prevent read of this data + * before we are through filling it. get_cpu()/put_cpu() does this + * for us + */ + local_irq_save(flags); + + if (unlikely(tsk->btrace_seq != blktrace_seq)) + trace_note_tsk(bt, tsk); + + t = relay_reserve(bt->rchan, sizeof(*t) + pdu_len); + if (t) { + cpu = smp_processor_id(); + sequence = per_cpu_ptr(bt->sequence, cpu); + + t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; + t->sequence = ++(*sequence); + t->time = sched_clock() - per_cpu(blk_trace_cpu_offset, cpu); + t->sector = sector; + t->bytes = bytes; + t->action = what; + t->pid = pid; + t->device = bt->dev; + t->cpu = cpu; + t->error = error; + t->pdu_len = pdu_len; + + if (pdu_len) + memcpy((void *) t + sizeof(*t), pdu_data, pdu_len); + } + + local_irq_restore(flags); +} + +EXPORT_SYMBOL_GPL(__blk_add_trace); + +static struct dentry *blk_tree_root; +static struct mutex blk_tree_mutex; +static unsigned int root_users; + +static inline void blk_remove_root(void) +{ + if (blk_tree_root) { + debugfs_remove(blk_tree_root); + blk_tree_root = NULL; + } +} + +static void blk_remove_tree(struct dentry *dir) +{ + mutex_lock(&blk_tree_mutex); + debugfs_remove(dir); + if (--root_users == 0) + blk_remove_root(); + mutex_unlock(&blk_tree_mutex); +} + +static struct dentry *blk_create_tree(const char *blk_name) +{ + struct dentry *dir = NULL; + + mutex_lock(&blk_tree_mutex); + + if (!blk_tree_root) { + blk_tree_root = debugfs_create_dir("block", NULL); + if (!blk_tree_root) + goto err; + } + + dir = debugfs_create_dir(blk_name, blk_tree_root); + if (dir) + root_users++; + else + blk_remove_root(); + +err: + mutex_unlock(&blk_tree_mutex); + return dir; +} + +static void blk_trace_cleanup(struct blk_trace *bt) +{ + relay_close(bt->rchan); + debugfs_remove(bt->dropped_file); + blk_remove_tree(bt->dir); + free_percpu(bt->sequence); + kfree(bt); +} + +static int blk_trace_remove(request_queue_t *q) +{ + struct blk_trace *bt; + + bt = xchg(&q->blk_trace, NULL); + if (!bt) + return -EINVAL; + + if (bt->trace_state == Blktrace_setup || + bt->trace_state == Blktrace_stopped) + blk_trace_cleanup(bt); + + return 0; +} + +static int blk_dropped_open(struct inode *inode, struct file *filp) +{ + filp->private_data = inode->u.generic_ip; + + return 0; +} + +static ssize_t blk_dropped_read(struct file *filp, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct blk_trace *bt = filp->private_data; + char buf[16]; + + snprintf(buf, sizeof(buf), "%u\n", atomic_read(&bt->dropped)); + + return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); +} + +static struct file_operations blk_dropped_fops = { + .owner = THIS_MODULE, + .open = blk_dropped_open, + .read = blk_dropped_read, +}; + +/* + * Keep track of how many times we encountered a full subbuffer, to aid + * the user space app in telling how many lost events there were. + */ +static int blk_subbuf_start_callback(struct rchan_buf *buf, void *subbuf, + void *prev_subbuf, size_t prev_padding) +{ + struct blk_trace *bt; + + if (!relay_buf_full(buf)) + return 1; + + bt = buf->chan->private_data; + atomic_inc(&bt->dropped); + return 0; +} + +static int blk_remove_buf_file_callback(struct dentry *dentry) +{ + debugfs_remove(dentry); + return 0; +} + +static struct dentry *blk_create_buf_file_callback(const char *filename, + struct dentry *parent, + int mode, + struct rchan_buf *buf, + int *is_global) +{ + return debugfs_create_file(filename, mode, parent, buf, + &relay_file_operations); +} + +static struct rchan_callbacks blk_relay_callbacks = { + .subbuf_start = blk_subbuf_start_callback, + .create_buf_file = blk_create_buf_file_callback, + .remove_buf_file = blk_remove_buf_file_callback, +}; + +/* + * Setup everything required to start tracing + */ +static int blk_trace_setup(request_queue_t *q, struct block_device *bdev, + char __user *arg) +{ + struct blk_user_trace_setup buts; + struct blk_trace *old_bt, *bt = NULL; + struct dentry *dir = NULL; + char b[BDEVNAME_SIZE]; + int ret, i; + + if (copy_from_user(&buts, arg, sizeof(buts))) + return -EFAULT; + + if (!buts.buf_size || !buts.buf_nr) + return -EINVAL; + + strcpy(buts.name, bdevname(bdev, b)); + + /* + * some device names have larger paths - convert the slashes + * to underscores for this to work as expected + */ + for (i = 0; i < strlen(buts.name); i++) + if (buts.name[i] == '/') + buts.name[i] = '_'; + + if (copy_to_user(arg, &buts, sizeof(buts))) + return -EFAULT; + + ret = -ENOMEM; + bt = kzalloc(sizeof(*bt), GFP_KERNEL); + if (!bt) + goto err; + + bt->sequence = alloc_percpu(unsigned long); + if (!bt->sequence) + goto err; + + ret = -ENOENT; + dir = blk_create_tree(buts.name); + if (!dir) + goto err; + + bt->dir = dir; + bt->dev = bdev->bd_dev; + atomic_set(&bt->dropped, 0); + + ret = -EIO; + bt->dropped_file = debugfs_create_file("dropped", 0444, dir, bt, &blk_dropped_fops); + if (!bt->dropped_file) + goto err; + + bt->rchan = relay_open("trace", dir, buts.buf_size, buts.buf_nr, &blk_relay_callbacks); + if (!bt->rchan) + goto err; + bt->rchan->private_data = bt; + + bt->act_mask = buts.act_mask; + if (!bt->act_mask) + bt->act_mask = (u16) -1; + + bt->start_lba = buts.start_lba; + bt->end_lba = buts.end_lba; + if (!bt->end_lba) + bt->end_lba = -1ULL; + + bt->pid = buts.pid; + bt->trace_state = Blktrace_setup; + + ret = -EBUSY; + old_bt = xchg(&q->blk_trace, bt); + if (old_bt) { + (void) xchg(&q->blk_trace, old_bt); + goto err; + } + + return 0; +err: + if (dir) + blk_remove_tree(dir); + if (bt) { + if (bt->dropped_file) + debugfs_remove(bt->dropped_file); + if (bt->sequence) + free_percpu(bt->sequence); + if (bt->rchan) + relay_close(bt->rchan); + kfree(bt); + } + return ret; +} + +static int blk_trace_startstop(request_queue_t *q, int start) +{ + struct blk_trace *bt; + int ret; + + if ((bt = q->blk_trace) == NULL) + return -EINVAL; + + /* + * For starting a trace, we can transition from a setup or stopped + * trace. For stopping a trace, the state must be running + */ + ret = -EINVAL; + if (start) { + if (bt->trace_state == Blktrace_setup || + bt->trace_state == Blktrace_stopped) { + blktrace_seq++; + smp_mb(); + bt->trace_state = Blktrace_running; + ret = 0; + } + } else { + if (bt->trace_state == Blktrace_running) { + bt->trace_state = Blktrace_stopped; + relay_flush(bt->rchan); + ret = 0; + } + } + + return ret; +} + +/** + * blk_trace_ioctl: - handle the ioctls associated with tracing + * @bdev: the block device + * @cmd: the ioctl cmd + * @arg: the argument data, if any + * + **/ +int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) +{ + request_queue_t *q; + int ret, start = 0; + + q = bdev_get_queue(bdev); + if (!q) + return -ENXIO; + + mutex_lock(&bdev->bd_mutex); + + switch (cmd) { + case BLKTRACESETUP: + ret = blk_trace_setup(q, bdev, arg); + break; + case BLKTRACESTART: + start = 1; + case BLKTRACESTOP: + ret = blk_trace_startstop(q, start); + break; + case BLKTRACETEARDOWN: + ret = blk_trace_remove(q); + break; + default: + ret = -ENOTTY; + break; + } + + mutex_unlock(&bdev->bd_mutex); + return ret; +} + +/** + * blk_trace_shutdown: - stop and cleanup trace structures + * @q: the request queue associated with the device + * + **/ +void blk_trace_shutdown(request_queue_t *q) +{ + blk_trace_startstop(q, 0); + blk_trace_remove(q); +} + +/* + * Average offset over two calls to sched_clock() with a gettimeofday() + * in the middle + */ +static void blk_check_time(unsigned long long *t) +{ + unsigned long long a, b; + struct timeval tv; + + a = sched_clock(); + do_gettimeofday(&tv); + b = sched_clock(); + + *t = tv.tv_sec * 1000000000 + tv.tv_usec * 1000; + *t -= (a + b) / 2; +} + +static void blk_trace_check_cpu_time(void *data) +{ + unsigned long long *t; + int cpu = get_cpu(); + + t = &per_cpu(blk_trace_cpu_offset, cpu); + + /* + * Just call it twice, hopefully the second call will be cache hot + * and a little more precise + */ + blk_check_time(t); + blk_check_time(t); + + put_cpu(); +} + +/* + * Call blk_trace_check_cpu_time() on each CPU to calibrate our inter-CPU + * timings + */ +static void blk_trace_calibrate_offsets(void) +{ + unsigned long flags; + + smp_call_function(blk_trace_check_cpu_time, NULL, 1, 1); + local_irq_save(flags); + blk_trace_check_cpu_time(NULL); + local_irq_restore(flags); +} + +static void blk_trace_set_ht_offsets(void) +{ +#if defined(CONFIG_SCHED_SMT) + int cpu, i; + + /* + * now make sure HT siblings have the same time offset + */ + preempt_disable(); + for_each_online_cpu(cpu) { + unsigned long long *cpu_off, *sibling_off; + + for_each_cpu_mask(i, cpu_sibling_map[cpu]) { + if (i == cpu) + continue; + + cpu_off = &per_cpu(blk_trace_cpu_offset, cpu); + sibling_off = &per_cpu(blk_trace_cpu_offset, i); + *sibling_off = *cpu_off; + } + } + preempt_enable(); +#endif +} + +static __init int blk_trace_init(void) +{ + mutex_init(&blk_tree_mutex); + blk_trace_calibrate_offsets(); + blk_trace_set_ht_offsets(); + + return 0; +} + +module_init(blk_trace_init); + diff --git a/block/elevator.c b/block/elevator.c index db3d0d8296a0..5e558c4689a4 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -333,6 +334,8 @@ void elv_insert(request_queue_t *q, struct request *rq, int where) struct list_head *pos; unsigned ordseq; + blk_add_trace_rq(q, rq, BLK_TA_INSERT); + rq->q = q; switch (where) { @@ -499,6 +502,7 @@ struct request *elv_next_request(request_queue_t *q) * not be passed by new incoming requests */ rq->flags |= REQ_STARTED; + blk_add_trace_rq(q, rq, BLK_TA_ISSUE); } if (!q->boundary_rq || q->boundary_rq == rq) { diff --git a/block/ioctl.c b/block/ioctl.c index 35fdb7dc6512..9cfa2e1ecb24 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -5,6 +5,7 @@ #include #include #include +#include #include static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg) @@ -189,6 +190,11 @@ static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, return put_ulong(arg, bdev->bd_inode->i_size >> 9); case BLKGETSIZE64: return put_u64(arg, bdev->bd_inode->i_size); + case BLKTRACESTART: + case BLKTRACESTOP: + case BLKTRACESETUP: + case BLKTRACETEARDOWN: + return blk_trace_ioctl(bdev, cmd, (char __user *) arg); } return -ENOIOCTLCMD; } diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 6c793b196aa9..062067fa7ead 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -28,6 +28,7 @@ #include #include #include +#include /* * for max sense size @@ -1556,8 +1557,10 @@ void blk_plug_device(request_queue_t *q) if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)) return; - if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) + if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) { mod_timer(&q->unplug_timer, jiffies + q->unplug_delay); + blk_add_trace_generic(q, NULL, 0, BLK_TA_PLUG); + } } EXPORT_SYMBOL(blk_plug_device); @@ -1621,14 +1624,21 @@ static void blk_backing_dev_unplug(struct backing_dev_info *bdi, /* * devices don't necessarily have an ->unplug_fn defined */ - if (q->unplug_fn) + if (q->unplug_fn) { + blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL, + q->rq.count[READ] + q->rq.count[WRITE]); + q->unplug_fn(q); + } } static void blk_unplug_work(void *data) { request_queue_t *q = data; + blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL, + q->rq.count[READ] + q->rq.count[WRITE]); + q->unplug_fn(q); } @@ -1636,6 +1646,9 @@ static void blk_unplug_timeout(unsigned long data) { request_queue_t *q = (request_queue_t *)data; + blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_TIMER, NULL, + q->rq.count[READ] + q->rq.count[WRITE]); + kblockd_schedule_work(&q->unplug_work); } @@ -1753,6 +1766,9 @@ static void blk_release_queue(struct kobject *kobj) if (q->queue_tags) __blk_queue_free_tags(q); + if (q->blk_trace) + blk_trace_shutdown(q); + kmem_cache_free(requestq_cachep, q); } @@ -2129,6 +2145,8 @@ rq_starved: rq_init(q, rq); rq->rl = rl; + + blk_add_trace_generic(q, bio, rw, BLK_TA_GETRQ); out: return rq; } @@ -2157,6 +2175,8 @@ static struct request *get_request_wait(request_queue_t *q, int rw, if (!rq) { struct io_context *ioc; + blk_add_trace_generic(q, bio, rw, BLK_TA_SLEEPRQ); + __generic_unplug_device(q); spin_unlock_irq(q->queue_lock); io_schedule(); @@ -2210,6 +2230,8 @@ EXPORT_SYMBOL(blk_get_request); */ void blk_requeue_request(request_queue_t *q, struct request *rq) { + blk_add_trace_rq(q, rq, BLK_TA_REQUEUE); + if (blk_rq_tagged(rq)) blk_queue_end_tag(q, rq); @@ -2844,6 +2866,8 @@ static int __make_request(request_queue_t *q, struct bio *bio) if (!q->back_merge_fn(q, req, bio)) break; + blk_add_trace_bio(q, bio, BLK_TA_BACKMERGE); + req->biotail->bi_next = bio; req->biotail = bio; req->nr_sectors = req->hard_nr_sectors += nr_sectors; @@ -2859,6 +2883,8 @@ static int __make_request(request_queue_t *q, struct bio *bio) if (!q->front_merge_fn(q, req, bio)) break; + blk_add_trace_bio(q, bio, BLK_TA_FRONTMERGE); + bio->bi_next = req->bio; req->bio = bio; @@ -2976,6 +3002,7 @@ void generic_make_request(struct bio *bio) request_queue_t *q; sector_t maxsector; int ret, nr_sectors = bio_sectors(bio); + dev_t old_dev; might_sleep(); /* Test device or partition size, when known. */ @@ -3002,6 +3029,8 @@ void generic_make_request(struct bio *bio) * NOTE: we don't repeat the blk_size check for each new device. * Stacking drivers are expected to know what they are doing. */ + maxsector = -1; + old_dev = 0; do { char b[BDEVNAME_SIZE]; @@ -3034,6 +3063,15 @@ end_io: */ blk_partition_remap(bio); + if (maxsector != -1) + blk_add_trace_remap(q, bio, old_dev, bio->bi_sector, + maxsector); + + blk_add_trace_bio(q, bio, BLK_TA_QUEUE); + + maxsector = bio->bi_sector; + old_dev = bio->bi_bdev->bd_dev; + ret = q->make_request_fn(q, bio); } while (ret); } @@ -3153,6 +3191,8 @@ static int __end_that_request_first(struct request *req, int uptodate, int total_bytes, bio_nbytes, error, next_idx = 0; struct bio *bio; + blk_add_trace_rq(req->q, req, BLK_TA_COMPLETE); + /* * extend uptodate bool to allow < 0 value to be direct io error */ diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index e29b8926f80e..1f2890989b56 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -2331,6 +2332,7 @@ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, cmd->rq->completion_data = cmd; cmd->rq->errors = status; + blk_add_trace_rq(cmd->rq->q, cmd->rq, BLK_TA_COMPLETE); blk_complete_request(cmd->rq); } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 26b08ee425c7..8c82373f7ff3 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -17,6 +17,7 @@ #include #include #include +#include static const char *_name = DM_NAME; @@ -334,6 +335,8 @@ static void dec_pending(struct dm_io *io, int error) /* nudge anyone waiting on suspend queue */ wake_up(&io->md->wait); + blk_add_trace_bio(io->md->queue, io->bio, BLK_TA_COMPLETE); + bio_endio(io->bio, io->bio->bi_size, io->error); free_io(io->md, io); } @@ -392,6 +395,7 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, struct target_io *tio) { int r; + sector_t sector; /* * Sanity checks. @@ -407,10 +411,17 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, * this io. */ atomic_inc(&tio->io->io_count); + sector = clone->bi_sector; r = ti->type->map(ti, clone, &tio->info); - if (r > 0) + if (r > 0) { /* the bio has been remapped so dispatch it */ + + blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone, + tio->io->bio->bi_bdev->bd_dev, sector, + clone->bi_sector); + generic_make_request(clone); + } else if (r < 0) { /* error the io and bail out */ diff --git a/fs/bio.c b/fs/bio.c index 8f1d2e815c96..0a8c59cb68f5 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -25,6 +25,7 @@ #include #include #include +#include #include /* for struct sg_iovec */ #define BIO_POOL_SIZE 256 @@ -1095,6 +1096,9 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) if (!bp) return bp; + blk_add_trace_pdu_int(bdev_get_queue(bi->bi_bdev), BLK_TA_SPLIT, bi, + bi->bi_sector + first_sectors); + BUG_ON(bi->bi_vcnt != 1); BUG_ON(bi->bi_idx != 0); atomic_set(&bp->cnt, 3); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index c666769a875d..7c031f00fd79 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -72,6 +72,7 @@ #include #include #include +#include #include /* siocdevprivate_ioctl */ #include diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 56bb6a4e15f3..c179966f1a2f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -22,6 +22,7 @@ typedef struct request_queue request_queue_t; struct elevator_queue; typedef struct elevator_queue elevator_t; struct request_pm_state; +struct blk_trace; #define BLKDEV_MIN_RQ 4 #define BLKDEV_MAX_RQ 128 /* Default maximum */ @@ -416,6 +417,8 @@ struct request_queue unsigned int sg_reserved_size; int node; + struct blk_trace *blk_trace; + /* * reserved for flush operations */ diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h new file mode 100644 index 000000000000..b34d3e73d5ea --- /dev/null +++ b/include/linux/blktrace_api.h @@ -0,0 +1,277 @@ +#ifndef BLKTRACE_H +#define BLKTRACE_H + +#include +#include +#include + +/* + * Trace categories + */ +enum blktrace_cat { + BLK_TC_READ = 1 << 0, /* reads */ + BLK_TC_WRITE = 1 << 1, /* writes */ + BLK_TC_BARRIER = 1 << 2, /* barrier */ + BLK_TC_SYNC = 1 << 3, /* barrier */ + BLK_TC_QUEUE = 1 << 4, /* queueing/merging */ + BLK_TC_REQUEUE = 1 << 5, /* requeueing */ + BLK_TC_ISSUE = 1 << 6, /* issue */ + BLK_TC_COMPLETE = 1 << 7, /* completions */ + BLK_TC_FS = 1 << 8, /* fs requests */ + BLK_TC_PC = 1 << 9, /* pc requests */ + BLK_TC_NOTIFY = 1 << 10, /* special message */ + + BLK_TC_END = 1 << 15, /* only 16-bits, reminder */ +}; + +#define BLK_TC_SHIFT (16) +#define BLK_TC_ACT(act) ((act) << BLK_TC_SHIFT) + +/* + * Basic trace actions + */ +enum blktrace_act { + __BLK_TA_QUEUE = 1, /* queued */ + __BLK_TA_BACKMERGE, /* back merged to existing rq */ + __BLK_TA_FRONTMERGE, /* front merge to existing rq */ + __BLK_TA_GETRQ, /* allocated new request */ + __BLK_TA_SLEEPRQ, /* sleeping on rq allocation */ + __BLK_TA_REQUEUE, /* request requeued */ + __BLK_TA_ISSUE, /* sent to driver */ + __BLK_TA_COMPLETE, /* completed by driver */ + __BLK_TA_PLUG, /* queue was plugged */ + __BLK_TA_UNPLUG_IO, /* queue was unplugged by io */ + __BLK_TA_UNPLUG_TIMER, /* queue was unplugged by timer */ + __BLK_TA_INSERT, /* insert request */ + __BLK_TA_SPLIT, /* bio was split */ + __BLK_TA_BOUNCE, /* bio was bounced */ + __BLK_TA_REMAP, /* bio was remapped */ +}; + +/* + * Trace actions in full. Additionally, read or write is masked + */ +#define BLK_TA_QUEUE (__BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_BACKMERGE (__BLK_TA_BACKMERGE | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_FRONTMERGE (__BLK_TA_FRONTMERGE | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_GETRQ (__BLK_TA_GETRQ | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_SLEEPRQ (__BLK_TA_SLEEPRQ | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_REQUEUE (__BLK_TA_REQUEUE | BLK_TC_ACT(BLK_TC_REQUEUE)) +#define BLK_TA_ISSUE (__BLK_TA_ISSUE | BLK_TC_ACT(BLK_TC_ISSUE)) +#define BLK_TA_COMPLETE (__BLK_TA_COMPLETE| BLK_TC_ACT(BLK_TC_COMPLETE)) +#define BLK_TA_PLUG (__BLK_TA_PLUG | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_UNPLUG_IO (__BLK_TA_UNPLUG_IO | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_UNPLUG_TIMER (__BLK_TA_UNPLUG_TIMER | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_INSERT (__BLK_TA_INSERT | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_SPLIT (__BLK_TA_SPLIT) +#define BLK_TA_BOUNCE (__BLK_TA_BOUNCE) +#define BLK_TA_REMAP (__BLK_TA_REMAP | BLK_TC_ACT(BLK_TC_QUEUE)) + +#define BLK_IO_TRACE_MAGIC 0x65617400 +#define BLK_IO_TRACE_VERSION 0x07 + +/* + * The trace itself + */ +struct blk_io_trace { + u32 magic; /* MAGIC << 8 | version */ + u32 sequence; /* event number */ + u64 time; /* in microseconds */ + u64 sector; /* disk offset */ + u32 bytes; /* transfer length */ + u32 action; /* what happened */ + u32 pid; /* who did it */ + u32 device; /* device number */ + u32 cpu; /* on what cpu did it happen */ + u16 error; /* completion error */ + u16 pdu_len; /* length of data after this trace */ +}; + +/* + * The remap event + */ +struct blk_io_trace_remap { + u32 device; + u32 __pad; + u64 sector; +}; + +enum { + Blktrace_setup = 1, + Blktrace_running, + Blktrace_stopped, +}; + +struct blk_trace { + int trace_state; + struct rchan *rchan; + unsigned long *sequence; + u16 act_mask; + u64 start_lba; + u64 end_lba; + u32 pid; + u32 dev; + struct dentry *dir; + struct dentry *dropped_file; + atomic_t dropped; +}; + +/* + * User setup structure passed with BLKTRACESTART + */ +struct blk_user_trace_setup { + char name[BDEVNAME_SIZE]; /* output */ + u16 act_mask; /* input */ + u32 buf_size; /* input */ + u32 buf_nr; /* input */ + u64 start_lba; + u64 end_lba; + u32 pid; +}; + +#if defined(CONFIG_BLK_DEV_IO_TRACE) +extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); +extern void blk_trace_shutdown(request_queue_t *); +extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); + +/** + * blk_add_trace_rq - Add a trace for a request oriented action + * @q: queue the io is for + * @rq: the source request + * @what: the action + * + * Description: + * Records an action against a request. Will log the bio offset + size. + * + **/ +static inline void blk_add_trace_rq(struct request_queue *q, struct request *rq, + u32 what) +{ + struct blk_trace *bt = q->blk_trace; + int rw = rq->flags & 0x07; + + if (likely(!bt)) + return; + + if (blk_pc_request(rq)) { + what |= BLK_TC_ACT(BLK_TC_PC); + __blk_add_trace(bt, 0, rq->data_len, rw, what, rq->errors, sizeof(rq->cmd), rq->cmd); + } else { + what |= BLK_TC_ACT(BLK_TC_FS); + __blk_add_trace(bt, rq->hard_sector, rq->hard_nr_sectors << 9, rw, what, rq->errors, 0, NULL); + } +} + +/** + * blk_add_trace_bio - Add a trace for a bio oriented action + * @q: queue the io is for + * @bio: the source bio + * @what: the action + * + * Description: + * Records an action against a bio. Will log the bio offset + size. + * + **/ +static inline void blk_add_trace_bio(struct request_queue *q, struct bio *bio, + u32 what) +{ + struct blk_trace *bt = q->blk_trace; + + if (likely(!bt)) + return; + + __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, what, !bio_flagged(bio, BIO_UPTODATE), 0, NULL); +} + +/** + * blk_add_trace_generic - Add a trace for a generic action + * @q: queue the io is for + * @bio: the source bio + * @rw: the data direction + * @what: the action + * + * Description: + * Records a simple trace + * + **/ +static inline void blk_add_trace_generic(struct request_queue *q, + struct bio *bio, int rw, u32 what) +{ + struct blk_trace *bt = q->blk_trace; + + if (likely(!bt)) + return; + + if (bio) + blk_add_trace_bio(q, bio, what); + else + __blk_add_trace(bt, 0, 0, rw, what, 0, 0, NULL); +} + +/** + * blk_add_trace_pdu_int - Add a trace for a bio with an integer payload + * @q: queue the io is for + * @what: the action + * @bio: the source bio + * @pdu: the integer payload + * + * Description: + * Adds a trace with some integer payload. This might be an unplug + * option given as the action, with the depth at unplug time given + * as the payload + * + **/ +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); + + if (likely(!bt)) + return; + + if (bio) + __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, what, !bio_flagged(bio, BIO_UPTODATE), sizeof(rpdu), &rpdu); + else + __blk_add_trace(bt, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu); +} + +/** + * blk_add_trace_remap - Add a trace for a remap operation + * @q: queue the io is for + * @bio: the source bio + * @dev: target device + * @from: source sector + * @to: target sector + * + * Description: + * Device mapper or raid target sometimes need to split a bio because + * it spans a stripe (or similar). Add a trace for that action. + * + **/ +static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio, + dev_t dev, sector_t from, sector_t to) +{ + struct blk_trace *bt = q->blk_trace; + struct blk_io_trace_remap r; + + if (likely(!bt)) + return; + + r.device = cpu_to_be32(dev); + r.sector = cpu_to_be64(to); + + __blk_add_trace(bt, from, bio->bi_size, bio->bi_rw, BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r); +} + +#else /* !CONFIG_BLK_DEV_IO_TRACE */ +#define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY) +#define blk_trace_shutdown(q) do { } while (0) +#define blk_add_trace_rq(q, rq, what) do { } while (0) +#define blk_add_trace_bio(q, rq, what) do { } while (0) +#define blk_add_trace_generic(q, rq, rw, what) do { } while (0) +#define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) +#define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) +#endif /* CONFIG_BLK_DEV_IO_TRACE */ + +#endif diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index ae7dfb790df3..efb518f16bb3 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -97,6 +97,10 @@ COMPATIBLE_IOCTL(BLKRRPART) COMPATIBLE_IOCTL(BLKFLSBUF) COMPATIBLE_IOCTL(BLKSECTSET) COMPATIBLE_IOCTL(BLKSSZGET) +COMPATIBLE_IOCTL(BLKTRACESTART) +COMPATIBLE_IOCTL(BLKTRACESTOP) +COMPATIBLE_IOCTL(BLKTRACESETUP) +COMPATIBLE_IOCTL(BLKTRACETEARDOWN) ULONG_IOCTL(BLKRASET) ULONG_IOCTL(BLKFRASET) /* RAID */ diff --git a/include/linux/fs.h b/include/linux/fs.h index f9c9dea636d0..9b34a1b03455 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -197,6 +197,10 @@ extern int dir_notify_enable; #define BLKBSZGET _IOR(0x12,112,size_t) #define BLKBSZSET _IOW(0x12,113,size_t) #define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ +#define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup) +#define BLKTRACESTART _IO(0x12,116) +#define BLKTRACESTOP _IO(0x12,117) +#define BLKTRACETEARDOWN _IO(0x12,118) #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ #define FIBMAP _IO(0x00,1) /* bmap access */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 62e6314382f0..e60a91d5b369 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -706,6 +706,7 @@ struct task_struct { prio_array_t *array; unsigned short ioprio; + unsigned int btrace_seq; unsigned long sleep_avg; unsigned long long timestamp, last_ran; diff --git a/kernel/fork.c b/kernel/fork.c index c79ae0b19a49..c21bae8c93b9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -181,6 +181,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) /* One for us, one for whoever does the "release_task()" (usually parent) */ atomic_set(&tsk->usage,2); atomic_set(&tsk->fs_excl, 0); + tsk->btrace_seq = 0; return tsk; } diff --git a/mm/highmem.c b/mm/highmem.c index ce2e7e8bbfa7..d0ea1eec6a9a 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -26,6 +26,7 @@ #include #include #include +#include #include static mempool_t *page_pool, *isa_page_pool; @@ -483,6 +484,8 @@ void blk_queue_bounce(request_queue_t *q, struct bio **bio_orig) pool = isa_page_pool; } + blk_add_trace_bio(q, *bio_orig, BLK_TA_BOUNCE); + /* * slow path */ -- cgit v1.2.3-59-g8ed1b From 934d8bf142541ea013bc4002e200fa0e6815bf38 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 16 Mar 2006 13:46:23 -0500 Subject: [PATCH] wireless/airo: clean up printk usage to print device name Show the specific device that driver messages are about. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 191 ++++++++++++++++++++++++-------------------- 1 file changed, 105 insertions(+), 86 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 864937a409e5..8a0abb668ed4 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1216,6 +1216,22 @@ static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime); static int flashputbuf(struct airo_info *ai); static int flashrestart(struct airo_info *ai,struct net_device *dev); +#define airo_print(type, name, fmt, args...) \ + { printk(type "airo(%s): " fmt "\n", name, ##args); } + +#define airo_print_info(name, fmt, args...) \ + airo_print(KERN_INFO, name, fmt, ##args) + +#define airo_print_dbg(name, fmt, args...) \ + airo_print(KERN_DEBUG, name, fmt, ##args) + +#define airo_print_warn(name, fmt, args...) \ + airo_print(KERN_WARNING, name, fmt, ##args) + +#define airo_print_err(name, fmt, args...) \ + airo_print(KERN_ERR, name, fmt, ##args) + + /*********************************************************************** * MIC ROUTINES * *********************************************************************** @@ -1294,7 +1310,7 @@ static int micsetup(struct airo_info *ai) { ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP); if (ai->tfm == NULL) { - printk(KERN_ERR "airo: failed to load transform for AES\n"); + airo_print_err(ai->dev->name, "failed to load transform for AES"); return ERROR; } @@ -1726,11 +1742,11 @@ static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lo wkr.kindex = cpu_to_le16(wkr.kindex); wkr.klen = cpu_to_le16(wkr.klen); rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock); - if (rc!=SUCCESS) printk(KERN_ERR "airo: WEP_TEMP set %x\n", rc); + if (rc!=SUCCESS) airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc); if (perm) { rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock); if (rc!=SUCCESS) { - printk(KERN_ERR "airo: WEP_PERM set %x\n", rc); + airo_print_err(ai->dev->name, "WEP_PERM set %x", rc); } } return rc; @@ -1909,7 +1925,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct airo_info *ai = dev->priv; if (!skb) { - printk(KERN_ERR "airo: %s: skb==NULL\n",__FUNCTION__); + airo_print_err(dev->name, "%s: skb == NULL!",__FUNCTION__); return 0; } npacks = skb_queue_len (&ai->txq); @@ -1955,8 +1971,8 @@ static int mpi_send_packet (struct net_device *dev) /* get a packet to send */ if ((skb = skb_dequeue(&ai->txq)) == 0) { - printk (KERN_ERR - "airo: %s: Dequeue'd zero in send_packet()\n", + airo_print_err(dev->name, + "%s: Dequeue'd zero in send_packet()", __FUNCTION__); return 0; } @@ -2108,7 +2124,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { u32 *fids = priv->fids; if ( skb == NULL ) { - printk( KERN_ERR "airo: skb == NULL!!!\n" ); + airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__); return 0; } @@ -2179,7 +2195,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { } if ( skb == NULL ) { - printk( KERN_ERR "airo: skb == NULL!!!\n" ); + airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__); return 0; } @@ -2434,7 +2450,7 @@ static int mpi_init_descriptors (struct airo_info *ai) cmd.parm2 = MPI_MAX_FIDS; rc=issuecommand(ai, &cmd, &rsp); if (rc != SUCCESS) { - printk(KERN_ERR "airo: Couldn't allocate RX FID\n"); + airo_print_err(ai->dev->name, "Couldn't allocate RX FID"); return rc; } @@ -2462,7 +2478,7 @@ static int mpi_init_descriptors (struct airo_info *ai) rc=issuecommand(ai, &cmd, &rsp); if (rc != SUCCESS) { - printk(KERN_ERR "airo: Couldn't allocate TX FID\n"); + airo_print_err(ai->dev->name, "Couldn't allocate TX FID"); return rc; } @@ -2476,7 +2492,7 @@ static int mpi_init_descriptors (struct airo_info *ai) cmd.parm2 = 1; /* Magic number... */ rc=issuecommand(ai, &cmd, &rsp); if (rc != SUCCESS) { - printk(KERN_ERR "airo: Couldn't allocate RID\n"); + airo_print_err(ai->dev->name, "Couldn't allocate RID"); return rc; } @@ -2508,25 +2524,25 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci, aux_len = AUXMEMSIZE; if (!request_mem_region(mem_start, mem_len, name)) { - printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s", (int)mem_start, (int)mem_len, name); goto out; } if (!request_mem_region(aux_start, aux_len, name)) { - printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s", (int)aux_start, (int)aux_len, name); goto free_region1; } ai->pcimem = ioremap(mem_start, mem_len); if (!ai->pcimem) { - printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s", (int)mem_start, (int)mem_len, name); goto free_region2; } ai->pciaux = ioremap(aux_start, aux_len); if (!ai->pciaux) { - printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n", + airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s", (int)aux_start, (int)aux_len, name); goto free_memmap; } @@ -2534,7 +2550,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci, /* Reserve PKTSIZE for each fid and 2K for the Rids */ ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma); if (!ai->shared) { - printk(KERN_ERR "airo: Couldn't alloc_consistent %d\n", + airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d", PCI_SHARED_LEN); goto free_auxmap; } @@ -2681,22 +2697,22 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, /* Create the network device object. */ dev = alloc_etherdev(sizeof(*ai)); if (!dev) { - printk(KERN_ERR "airo: Couldn't alloc_etherdev\n"); + airo_print_err("", "Couldn't alloc_etherdev"); return NULL; } if (dev_alloc_name(dev, dev->name) < 0) { - printk(KERN_ERR "airo: Couldn't get name!\n"); + airo_print_err("", "Couldn't get name!"); goto err_out_free; } ai = dev->priv; ai->wifidev = NULL; ai->flags = 0; + ai->dev = dev; if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) { - printk(KERN_DEBUG "airo: Found an MPI350 card\n"); + airo_print_dbg(dev->name, "Found an MPI350 card"); set_bit(FLAG_MPI, &ai->flags); } - ai->dev = dev; spin_lock_init(&ai->aux_lock); sema_init(&ai->sem, 1); ai->config.len = 0; @@ -2738,27 +2754,28 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, rc = request_irq( dev->irq, airo_interrupt, SA_SHIRQ, dev->name, dev ); if (rc) { - printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc ); + airo_print_err(dev->name, "register interrupt %d failed, rc %d", + irq, rc); goto err_out_unlink; } if (!is_pcmcia) { if (!request_region( dev->base_addr, 64, dev->name )) { rc = -EBUSY; - printk(KERN_ERR "airo: Couldn't request region\n"); + airo_print_err(dev->name, "Couldn't request region"); goto err_out_irq; } } if (test_bit(FLAG_MPI,&ai->flags)) { if (mpi_map_card(ai, pci, dev->name)) { - printk(KERN_ERR "airo: Could not map memory\n"); + airo_print_err(dev->name, "Could not map memory"); goto err_out_res; } } if (probe) { if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) { - printk( KERN_ERR "airo: MAC could not be enabled\n" ); + airo_print_err(dev->name, "MAC could not be enabled" ); rc = -EIO; goto err_out_map; } @@ -2769,14 +2786,13 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, rc = register_netdev(dev); if (rc) { - printk(KERN_ERR "airo: Couldn't register_netdev\n"); + airo_print_err(dev->name, "Couldn't register_netdev"); goto err_out_map; } ai->wifidev = init_wifidev(ai, dev); set_bit(FLAG_REGISTERED,&ai->flags); - printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", - dev->name, + airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x", dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] ); @@ -2840,10 +2856,10 @@ int reset_airo_card( struct net_device *dev ) return -1; if ( setup_card(ai, dev->dev_addr, 1 ) != SUCCESS ) { - printk( KERN_ERR "airo: MAC could not be enabled\n" ); + airo_print_err(dev->name, "MAC could not be enabled"); return -1; } - printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", dev->name, + airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x", dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); /* Allocate the transmit buffers if needed */ @@ -3118,7 +3134,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) len = le16_to_cpu(hdr.len); if (len > 2312) { - printk( KERN_ERR "airo: Bad size %d\n", len ); + airo_print_err(apriv->dev->name, "Bad size %d", len); goto badrx; } if (len == 0) @@ -3161,10 +3177,12 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) bap_read (apriv, &gap, sizeof(gap), BAP0); gap = le16_to_cpu(gap); if (gap) { - if (gap <= 8) + if (gap <= 8) { bap_read (apriv, tmpbuf, gap, BAP0); - else - printk(KERN_ERR "airo: gaplen too big. Problems will follow...\n"); + } else { + airo_print_err(apriv->dev->name, "gaplen too " + "big. Problems will follow..."); + } } bap_read (apriv, buffer + hdrlen/2, len, BAP0); } else { @@ -3281,12 +3299,13 @@ exitrx: } } else { OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); - printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" ); + airo_print_err(apriv->dev->name, "Unallocated FID was " + "used to xmit" ); } } exittx: if ( status & ~STATUS_INTS & ~IGNORE_INTS ) - printk( KERN_WARNING "airo: Got weird status %x\n", + airo_print_warn(apriv->dev->name, "Got weird status %x", status & ~STATUS_INTS & ~IGNORE_INTS ); } @@ -3359,8 +3378,8 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) { up(&ai->sem); if (rc) - printk(KERN_ERR "%s: Cannot enable MAC, err=%d\n", - __FUNCTION__,rc); + airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d", + __FUNCTION__, rc); return rc; } @@ -3490,7 +3509,7 @@ void mpi_receive_802_11 (struct airo_info *ai) hdr.len = 0; len = le16_to_cpu(hdr.len); if (len > 2312) { - printk( KERN_ERR "airo: Bad size %d\n", len ); + airo_print_err(ai->dev->name, "Bad size %d", len); goto badrx; } if (len == 0) @@ -3531,8 +3550,8 @@ void mpi_receive_802_11 (struct airo_info *ai) if (gap <= 8) ptr += gap; else - printk(KERN_ERR - "airo: gaplen too big. Problems will follow...\n"); + airo_print_err(ai->dev->name, + "gaplen too big. Problems will follow..."); } memcpy ((char *)buffer + hdrlen, ptr, len); ptr += len; @@ -3604,15 +3623,15 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) if (issuecommand(ai, &cmd, &rsp) != SUCCESS) { if (lock) up(&ai->sem); - printk(KERN_ERR "airo: Error checking for AUX port\n"); + airo_print_err(ai->dev->name, "Error checking for AUX port"); return ERROR; } if (!aux_bap || rsp.status & 0xff00) { ai->bap_read = fast_bap_read; - printk(KERN_DEBUG "airo: Doing fast bap_reads\n"); + airo_print_dbg(ai->dev->name, "Doing fast bap_reads"); } else { ai->bap_read = aux_bap_read; - printk(KERN_DEBUG "airo: Doing AUX bap_reads\n"); + airo_print_dbg(ai->dev->name, "Doing AUX bap_reads"); } } if (lock) @@ -3643,7 +3662,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) if (cap_rid.softCap & 8) ai->config.rmode |= RXMODE_NORMALIZED_RSSI; else - printk(KERN_WARNING "airo: unknown received signal level scale\n"); + airo_print_warn(ai->dev->name, "unknown received signal " + "level scale"); } ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; ai->config.authType = AUTH_OPEN; @@ -3706,7 +3726,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) status = enable_MAC(ai, &rsp, lock); if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) { - printk( KERN_ERR "airo: Bad MAC enable reason = %x, rid = %x, offset = %d\n", rsp.rsp0, rsp.rsp1, rsp.rsp2 ); + airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x," + " offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 ); return ERROR; } @@ -3749,8 +3770,8 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { } if ( max_tries == -1 ) { - printk( KERN_ERR - "airo: Max tries exceeded when issueing command\n" ); + airo_print_err(ai->dev->name, + "Max tries exceeded when issueing command"); if (IN4500(ai, COMMAND) & COMMAND_BUSY) OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); return ERROR; @@ -3762,11 +3783,11 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { pRsp->rsp1 = IN4500(ai, RESP1); pRsp->rsp2 = IN4500(ai, RESP2); if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) { - printk (KERN_ERR "airo: cmd= %x\n", pCmd->cmd); - printk (KERN_ERR "airo: status= %x\n", pRsp->status); - printk (KERN_ERR "airo: Rsp0= %x\n", pRsp->rsp0); - printk (KERN_ERR "airo: Rsp1= %x\n", pRsp->rsp1); - printk (KERN_ERR "airo: Rsp2= %x\n", pRsp->rsp2); + airo_print_err(ai->dev->name, "cmd= %x\n", pCmd->cmd); + airo_print_err(ai->dev->name, "status= %x\n", pRsp->status); + airo_print_err(ai->dev->name, "Rsp0= %x\n", pRsp->rsp0); + airo_print_err(ai->dev->name, "Rsp1= %x\n", pRsp->rsp1); + airo_print_err(ai->dev->name, "Rsp2= %x\n", pRsp->rsp2); } // clear stuck command busy if necessary @@ -3799,15 +3820,15 @@ static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap ) } } else if ( status & BAP_ERR ) { /* invalid rid or offset */ - printk( KERN_ERR "airo: BAP error %x %d\n", + airo_print_err(ai->dev->name, "BAP error %x %d", status, whichbap ); return ERROR; } else if (status & BAP_DONE) { // success return SUCCESS; } if ( !(max_tries--) ) { - printk( KERN_ERR - "airo: BAP setup error too many retries\n" ); + airo_print_err(ai->dev->name, + "airo: BAP setup error too many retries\n"); return ERROR; } // -- PC4500 missed it, try again @@ -3962,8 +3983,8 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in len = min(len, (int)le16_to_cpu(*(u16*)pBuf)) - 2; if ( len <= 2 ) { - printk( KERN_ERR - "airo: Rid %x has a length of %d which is too short\n", + airo_print_err(ai->dev->name, + "Rid %x has a length of %d which is too short", (int)rid, (int)len ); rc = ERROR; goto done; @@ -3996,8 +4017,8 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, Resp rsp; if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid)) - printk(KERN_ERR - "%s: MAC should be disabled (rid=%04x)\n", + airo_print_err(ai->dev->name, + "%s: MAC should be disabled (rid=%04x)", __FUNCTION__, rid); memset(&cmd, 0, sizeof(cmd)); memset(&rsp, 0, sizeof(rsp)); @@ -4013,7 +4034,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, &ai->config_desc.rid_desc, sizeof(Rid)); if (len < 4 || len > 2047) { - printk(KERN_ERR "%s: len=%d\n",__FUNCTION__,len); + airo_print_err(ai->dev->name, "%s: len=%d", __FUNCTION__, len); rc = -1; } else { memcpy((char *)ai->config_desc.virtual_host_addr, @@ -4021,10 +4042,10 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, rc = issuecommand(ai, &cmd, &rsp); if ((rc & 0xff00) != 0) { - printk(KERN_ERR "%s: Write rid Error %d\n", - __FUNCTION__,rc); - printk(KERN_ERR "%s: Cmd=%04x\n", - __FUNCTION__,cmd.cmd); + airo_print_err(ai->dev->name, "%s: Write rid Error %d", + __FUNCTION__, rc); + airo_print_err(ai->dev->name, "%s: Cmd=%04x", + __FUNCTION__, cmd.cmd); } if ((rsp.status & 0x7f00)) @@ -4123,7 +4144,7 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket) len >>= 16; if (len <= ETH_ALEN * 2) { - printk( KERN_WARNING "Short packet %d\n", len ); + airo_print_warn(ai->dev->name, "Short packet %d", len); return ERROR; } len -= ETH_ALEN * 2; @@ -4187,7 +4208,7 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket) } if (len < hdrlen) { - printk( KERN_WARNING "Short packet %d\n", len ); + airo_print_warn(ai->dev->name, "Short packet %d", len); return ERROR; } @@ -4584,15 +4605,14 @@ static int proc_stats_rid_open( struct inode *inode, i*44096) { - printk(KERN_WARNING - "airo: Potentially disasterous buffer overflow averted!\n"); + airo_print_warn(apriv->dev->name, + "Potentially disasterous buffer overflow averted!"); break; } j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], vals[i]); } if (i*4>=stats.len){ - printk(KERN_WARNING - "airo: Got a short rid\n"); + airo_print_warn(apriv->dev->name, "Got a short rid"); } data->readlen = j; return 0; @@ -4798,8 +4818,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { case 'd': ai->config.modulation=MOD_DEFAULT; set_bit(FLAG_COMMIT, &ai->flags); break; case 'c': ai->config.modulation=MOD_CCK; set_bit(FLAG_COMMIT, &ai->flags); break; case 'm': ai->config.modulation=MOD_MOK; set_bit(FLAG_COMMIT, &ai->flags); break; - default: - printk( KERN_WARNING "airo: Unknown modulation\n" ); + default: airo_print_warn(ai->dev->name, "Unknown modulation"); } } else if (!strncmp(line, "Preamble: ", 10)) { line += 10; @@ -4807,10 +4826,10 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { case 'a': ai->config.preamble=PREAMBLE_AUTO; set_bit(FLAG_COMMIT, &ai->flags); break; case 'l': ai->config.preamble=PREAMBLE_LONG; set_bit(FLAG_COMMIT, &ai->flags); break; case 's': ai->config.preamble=PREAMBLE_SHORT; set_bit(FLAG_COMMIT, &ai->flags); break; - default: printk(KERN_WARNING "airo: Unknown preamble\n"); + default: airo_print_warn(ai->dev->name, "Unknown preamble"); } } else { - printk( KERN_WARNING "Couldn't figure out %s\n", line ); + airo_print_warn(ai->dev->name, "Couldn't figure out %s", line); } while( line[0] && line[0] != '\n' ) line++; if ( line[0] ) line++; @@ -5076,7 +5095,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { } j = 2; } else { - printk(KERN_ERR "airo: WepKey passed invalid key index\n"); + airo_print_err(ai->dev->name, "WepKey passed invalid key index"); return; } @@ -5489,17 +5508,16 @@ static int __init airo_init_module( void ) airo_entry->gid = proc_gid; for( i = 0; i < 4 && io[i] && irq[i]; i++ ) { - printk( KERN_INFO - "airo: Trying to configure ISA adapter at irq=%d io=0x%x\n", - irq[i], io[i] ); + airo_print_info("", "Trying to configure ISA adapter at irq=%d " + "io=0x%x", irq[i], io[i] ); if (init_airo_card( irq[i], io[i], 0, NULL )) have_isa_dev = 1; } #ifdef CONFIG_PCI - printk( KERN_INFO "airo: Probing for PCI adapters\n" ); + airo_print_info("", "Probing for PCI adapters"); pci_register_driver(&airo_driver); - printk( KERN_INFO "airo: Finished probing for PCI adapters\n" ); + airo_print_info("", "Finished probing for PCI adapters"); #endif /* Always exit with success, as we are a library module @@ -5511,7 +5529,7 @@ static int __init airo_init_module( void ) static void __exit airo_cleanup_module( void ) { while( airo_devices ) { - printk( KERN_INFO "airo: Unregistering %s\n", airo_devices->dev->name ); + airo_print_info(airo_devices->dev->name, "Unregistering...\n"); stop_airo_card( airo_devices->dev, 1 ); } #ifdef CONFIG_PCI @@ -5622,7 +5640,8 @@ static int airo_set_freq(struct net_device *dev, /* We should do a better check than that, * based on the card capability !!! */ if((channel < 1) || (channel > 14)) { - printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, fwrq->m); + airo_print_dbg(dev->name, "New channel value of %d is invalid!", + fwrq->m); rc = -EINVAL; } else { readConfigRid(local, 1); @@ -7711,7 +7730,7 @@ static int cmdreset(struct airo_info *ai) { disable_MAC(ai, 1); if(!waitbusy (ai)){ - printk(KERN_INFO "Waitbusy hang before RESET\n"); + airo_print_info(ai->dev->name, "Waitbusy hang before RESET"); return -EBUSY; } @@ -7720,7 +7739,7 @@ static int cmdreset(struct airo_info *ai) { ssleep(1); /* WAS 600 12/7/00 */ if(!waitbusy (ai)){ - printk(KERN_INFO "Waitbusy hang AFTER RESET\n"); + airo_print_info(ai->dev->name, "Waitbusy hang AFTER RESET"); return -EBUSY; } return 0; @@ -7748,7 +7767,7 @@ static int setflashmode (struct airo_info *ai) { if(!waitbusy(ai)) { clear_bit (FLAG_FLASHING, &ai->flags); - printk(KERN_INFO "Waitbusy hang after setflash mode\n"); + airo_print_info(ai->dev->name, "Waitbusy hang after setflash mode"); return -EIO; } return 0; @@ -7777,7 +7796,7 @@ static int flashpchar(struct airo_info *ai,int byte,int dwelltime) { /* timeout for busy clear wait */ if(waittime <= 0 ){ - printk(KERN_INFO "flash putchar busywait timeout! \n"); + airo_print_info(ai->dev->name, "flash putchar busywait timeout!"); return -EBUSY; } -- cgit v1.2.3-59-g8ed1b From 15db2763202b9479f3d30ea61a283be4fc48559d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 16 Mar 2006 13:46:27 -0500 Subject: [PATCH] wireless/airo: define default MTU The number 2312 was used all over the place to refer to the card's default MTU. Make it a #define and use that everywhere rather than the number. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 8a0abb668ed4..6f591abacfdc 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -902,6 +902,7 @@ static char swversion[] = "2.1"; #define NUM_MODULES 2 #define MIC_MSGLEN_MAX 2400 #define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX +#define AIRO_DEF_MTU 2312 typedef struct { u32 size; // size @@ -2642,7 +2643,7 @@ static void wifi_setup(struct net_device *dev) dev->type = ARPHRD_IEEE80211; dev->hard_header_len = ETH_HLEN; - dev->mtu = 2312; + dev->mtu = AIRO_DEF_MTU; dev->addr_len = ETH_ALEN; dev->tx_queue_len = 100; @@ -2799,7 +2800,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, /* Allocate the transmit buffers */ if (probe && !test_bit(FLAG_MPI,&ai->flags)) for( i = 0; i < MAX_FIDS; i++ ) - ai->fids[i] = transmit_allocate(ai,2312,i>=MAX_FIDS/2); + ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2); setup_proc_entry( dev, dev->priv ); /* XXX check for failure */ netif_start_queue(dev); @@ -2865,7 +2866,7 @@ int reset_airo_card( struct net_device *dev ) /* Allocate the transmit buffers if needed */ if (!test_bit(FLAG_MPI,&ai->flags)) for( i = 0; i < MAX_FIDS; i++ ) - ai->fids[i] = transmit_allocate (ai,2312,i>=MAX_FIDS/2); + ai->fids[i] = transmit_allocate (ai,AIRO_DEF_MTU,i>=MAX_FIDS/2); enable_interrupts( ai ); netif_wake_queue(dev); @@ -3133,7 +3134,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) } len = le16_to_cpu(hdr.len); - if (len > 2312) { + if (len > AIRO_DEF_MTU) { airo_print_err(apriv->dev->name, "Bad size %d", len); goto badrx; } @@ -3508,7 +3509,7 @@ void mpi_receive_802_11 (struct airo_info *ai) if (ai->wifidev == NULL) hdr.len = 0; len = le16_to_cpu(hdr.len); - if (len > 2312) { + if (len > AIRO_DEF_MTU) { airo_print_err(ai->dev->name, "Bad size %d", len); goto badrx; } @@ -4774,7 +4775,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 14; v = get_dec_u16(line, &i, 4); - v = (v<0) ? 0 : ((v>2312) ? 2312 : v); + v = (v<0) ? 0 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v); ai->config.rtsThres = (u16)v; set_bit (FLAG_COMMIT, &ai->flags); } else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) { @@ -4808,7 +4809,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { line += 15; v = get_dec_u16(line, &i, 4); - v = (v<256) ? 256 : ((v>2312) ? 2312 : v); + v = (v<256) ? 256 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v); v = v & 0xfffe; /* Make sure its even */ ai->config.fragThresh = (u16)v; set_bit (FLAG_COMMIT, &ai->flags); @@ -5965,8 +5966,8 @@ static int airo_set_rts(struct net_device *dev, int rthr = vwrq->value; if(vwrq->disabled) - rthr = 2312; - if((rthr < 0) || (rthr > 2312)) { + rthr = AIRO_DEF_MTU; + if((rthr < 0) || (rthr > AIRO_DEF_MTU)) { return -EINVAL; } readConfigRid(local, 1); @@ -5989,7 +5990,7 @@ static int airo_get_rts(struct net_device *dev, readConfigRid(local, 1); vwrq->value = local->config.rtsThres; - vwrq->disabled = (vwrq->value >= 2312); + vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU); vwrq->fixed = 1; return 0; @@ -6008,8 +6009,8 @@ static int airo_set_frag(struct net_device *dev, int fthr = vwrq->value; if(vwrq->disabled) - fthr = 2312; - if((fthr < 256) || (fthr > 2312)) { + fthr = AIRO_DEF_MTU; + if((fthr < 256) || (fthr > AIRO_DEF_MTU)) { return -EINVAL; } fthr &= ~0x1; /* Get an even value - is it really needed ??? */ @@ -6033,7 +6034,7 @@ static int airo_get_frag(struct net_device *dev, readConfigRid(local, 1); vwrq->value = local->config.fragThresh; - vwrq->disabled = (vwrq->value >= 2312); + vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU); vwrq->fixed = 1; return 0; @@ -6728,9 +6729,9 @@ static int airo_get_range(struct net_device *dev, range->throughput = 1500 * 1000; range->min_rts = 0; - range->max_rts = 2312; + range->max_rts = AIRO_DEF_MTU; range->min_frag = 256; - range->max_frag = 2312; + range->max_frag = AIRO_DEF_MTU; if(cap_rid.softCap & 2) { // WEP: RC4 40 bits @@ -7885,7 +7886,7 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev){ if (!test_bit(FLAG_MPI,&ai->flags)) for( i = 0; i < MAX_FIDS; i++ ) { ai->fids[i] = transmit_allocate - ( ai, 2312, i >= MAX_FIDS / 2 ); + ( ai, AIRO_DEF_MTU, i >= MAX_FIDS / 2 ); } ssleep(1); /* Added 12/7/00 */ -- cgit v1.2.3-59-g8ed1b From 9e75af30d529d54fc650586776c100d0665c0c93 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 16 Mar 2006 13:46:29 -0500 Subject: [PATCH] wireless/airo: cache wireless scans Observed problems when multiple processes request scans and subsequently scan results. This causes a scan result request to hit card registers before the scan is complete, returning an incomplete scan list and possibly making the card very angry. Instead, cache the results of a wireless scan and serve result requests from the cache, rather than hitting the hardware for them. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 231 +++++++++++++++++++++++++++++++++----------- 1 file changed, 172 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 6f591abacfdc..108d9fed8f07 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -769,6 +769,11 @@ typedef struct { u16 atimWindow; } BSSListRid; +typedef struct { + BSSListRid bss; + struct list_head list; +} BSSListElement; + typedef struct { u8 rssipct; u8 rssidBm; @@ -1120,6 +1125,8 @@ static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi); static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm); +static void airo_networks_free(struct airo_info *ai); + struct airo_info { struct net_device_stats stats; struct net_device *dev; @@ -1151,7 +1158,7 @@ struct airo_info { #define FLAG_COMMIT 13 #define FLAG_RESET 14 #define FLAG_FLASHING 15 -#define JOB_MASK 0x1ff0000 +#define JOB_MASK 0x2ff0000 #define JOB_DIE 16 #define JOB_XMIT 17 #define JOB_XMIT11 18 @@ -1161,6 +1168,7 @@ struct airo_info { #define JOB_EVENT 22 #define JOB_AUTOWEP 23 #define JOB_WSTATS 24 +#define JOB_SCAN_RESULTS 25 int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap); unsigned short *flash; @@ -1177,7 +1185,7 @@ struct airo_info { } xmit, xmit11; struct net_device *wifidev; struct iw_statistics wstats; // wireless stats - unsigned long scan_timestamp; /* Time started to scan */ + unsigned long scan_timeout; /* Time scan should be read */ struct iw_spy_data spy_data; struct iw_public_data wireless_data; /* MIC stuff */ @@ -1199,6 +1207,10 @@ struct airo_info { APListRid *APList; #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE char proc_name[IFNAMSIZ]; + + struct list_head network_list; + struct list_head network_free_list; + BSSListElement *networks; }; static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen, @@ -2381,6 +2393,8 @@ void stop_airo_card( struct net_device *dev, int freeres ) dev_kfree_skb(skb); } + airo_networks_free (ai); + kfree(ai->flash); kfree(ai->rssi); kfree(ai->APList); @@ -2687,6 +2701,42 @@ static int reset_card( struct net_device *dev , int lock) { return 0; } +#define MAX_NETWORK_COUNT 64 +static int airo_networks_allocate(struct airo_info *ai) +{ + if (ai->networks) + return 0; + + ai->networks = + kzalloc(MAX_NETWORK_COUNT * sizeof(BSSListElement), + GFP_KERNEL); + if (!ai->networks) { + airo_print_warn(ai->dev->name, "Out of memory allocating beacons"); + return -ENOMEM; + } + + return 0; +} + +static void airo_networks_free(struct airo_info *ai) +{ + if (!ai->networks) + return; + kfree(ai->networks); + ai->networks = NULL; +} + +static void airo_networks_initialize(struct airo_info *ai) +{ + int i; + + INIT_LIST_HEAD(&ai->network_free_list); + INIT_LIST_HEAD(&ai->network_list); + for (i = 0; i < MAX_NETWORK_COUNT; i++) + list_add_tail(&ai->networks[i].list, + &ai->network_free_list); +} + static struct net_device *_init_airo_card( unsigned short irq, int port, int is_pcmcia, struct pci_dev *pci, struct device *dmdev ) @@ -2728,6 +2778,10 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, if (rc) goto err_out_thr; + if (airo_networks_allocate (ai)) + goto err_out_unlink; + airo_networks_initialize (ai); + /* The Airo-specific entries in the device structure. */ if (test_bit(FLAG_MPI,&ai->flags)) { skb_queue_head_init (&ai->txq); @@ -2749,7 +2803,6 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, SET_NETDEV_DEV(dev, dmdev); - reset_card (dev, 1); msleep(400); @@ -2892,6 +2945,65 @@ static void airo_send_event(struct net_device *dev) { wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); } +static void airo_process_scan_results (struct airo_info *ai) { + union iwreq_data wrqu; + BSSListRid BSSList; + int rc; + BSSListElement * loop_net; + BSSListElement * tmp_net; + + /* Blow away current list of scan results */ + list_for_each_entry_safe (loop_net, tmp_net, &ai->network_list, list) { + list_move_tail (&loop_net->list, &ai->network_free_list); + /* Don't blow away ->list, just BSS data */ + memset (loop_net, 0, sizeof (loop_net->bss)); + } + + /* Try to read the first entry of the scan result */ + rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 0); + if((rc) || (BSSList.index == 0xffff)) { + /* No scan results */ + goto out; + } + + /* Read and parse all entries */ + tmp_net = NULL; + while((!rc) && (BSSList.index != 0xffff)) { + /* Grab a network off the free list */ + if (!list_empty(&ai->network_free_list)) { + tmp_net = list_entry(ai->network_free_list.next, + BSSListElement, list); + list_del(ai->network_free_list.next); + } + + if (tmp_net != NULL) { + memcpy(tmp_net, &BSSList, sizeof(tmp_net->bss)); + list_add_tail(&tmp_net->list, &ai->network_list); + tmp_net = NULL; + } + + /* Read next entry */ + rc = PC4500_readrid(ai, RID_BSSLISTNEXT, + &BSSList, sizeof(BSSList), 0); + } + +out: + ai->scan_timeout = 0; + clear_bit(JOB_SCAN_RESULTS, &ai->flags); + up(&ai->sem); + + /* Send an empty event to user space. + * We don't send the received data on + * the event because it would require + * us to do complex transcoding, and + * we want to minimise the work done in + * the irq handler. Use a request to + * extract the data - Jean II */ + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(ai->dev, SIOCGIWSCAN, &wrqu, NULL); +} + static int airo_thread(void *data) { struct net_device *dev = data; struct airo_info *ai = dev->priv; @@ -2921,13 +3033,26 @@ static int airo_thread(void *data) { set_current_state(TASK_INTERRUPTIBLE); if (ai->flags & JOB_MASK) break; - if (ai->expires) { - if (time_after_eq(jiffies,ai->expires)){ + if (ai->expires || ai->scan_timeout) { + if (ai->scan_timeout && + time_after_eq(jiffies,ai->scan_timeout)){ + set_bit(JOB_SCAN_RESULTS,&ai->flags); + break; + } else if (ai->expires && + time_after_eq(jiffies,ai->expires)){ set_bit(JOB_AUTOWEP,&ai->flags); break; } if (!signal_pending(current)) { - schedule_timeout(ai->expires - jiffies); + unsigned long wake_at; + if (!ai->expires || !ai->scan_timeout) { + wake_at = max(ai->expires, + ai->scan_timeout); + } else { + wake_at = min(ai->expires, + ai->scan_timeout); + } + schedule_timeout(wake_at - jiffies); continue; } } else if (!signal_pending(current)) { @@ -2970,6 +3095,10 @@ static int airo_thread(void *data) { airo_send_event(dev); else if (test_bit(JOB_AUTOWEP, &ai->flags)) timer_func(dev); + else if (test_bit(JOB_SCAN_RESULTS, &ai->flags)) + airo_process_scan_results(ai); + else /* Shouldn't get here, but we make sure to unlock */ + up(&ai->sem); } complete_and_exit (&ai->thr_exited, 0); } @@ -3064,19 +3193,15 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) * and reassociations as valid status * Jean II */ if(newStatus == ASSOCIATED) { - if (apriv->scan_timestamp) { - /* Send an empty event to user space. - * We don't send the received data on - * the event because it would require - * us to do complex transcoding, and - * we want to minimise the work done in - * the irq handler. Use a request to - * extract the data - Jean II */ - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); - apriv->scan_timestamp = 0; +#if 0 + /* FIXME: Grabbing scan results here + * seems to be too early??? Just wait for + * timeout instead. */ + if (apriv->scan_timeout > 0) { + set_bit(JOB_SCAN_RESULTS, &apriv->flags); + wake_up_interruptible(&apriv->thr_wait); } +#endif if (down_trylock(&apriv->sem) != 0) { set_bit(JOB_EVENT, &apriv->flags); wake_up_interruptible(&apriv->thr_wait); @@ -6992,6 +7117,7 @@ static int airo_set_scan(struct net_device *dev, struct airo_info *ai = dev->priv; Cmd cmd; Resp rsp; + int wake = 0; /* Note : you may have realised that, as this is a SET operation, * this is privileged and therefore a normal user can't @@ -7001,17 +7127,25 @@ static int airo_set_scan(struct net_device *dev, * Jean II */ if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN; + if (down_interruptible(&ai->sem)) + return -ERESTARTSYS; + + /* If there's already a scan in progress, don't + * trigger another one. */ + if (ai->scan_timeout > 0) + goto out; + /* Initiate a scan command */ memset(&cmd, 0, sizeof(cmd)); cmd.cmd=CMD_LISTBSS; - if (down_interruptible(&ai->sem)) - return -ERESTARTSYS; issuecommand(ai, &cmd, &rsp); - ai->scan_timestamp = jiffies; - up(&ai->sem); - - /* At this point, just return to the user. */ + ai->scan_timeout = RUN_AT(3*HZ); + wake = 1; +out: + up(&ai->sem); + if (wake) + wake_up_interruptible(&ai->thr_wait); return 0; } @@ -7131,59 +7265,38 @@ static int airo_get_scan(struct net_device *dev, char *extra) { struct airo_info *ai = dev->priv; - BSSListRid BSSList; - int rc; + BSSListElement *net; + int err = 0; char *current_ev = extra; - /* When we are associated again, the scan has surely finished. - * Just in case, let's make sure enough time has elapsed since - * we started the scan. - Javier */ - if(ai->scan_timestamp && time_before(jiffies,ai->scan_timestamp+3*HZ)) { - /* Important note : we don't want to block the caller - * until results are ready for various reasons. - * First, managing wait queues is complex and racy - * (there may be multiple simultaneous callers). - * Second, we grab some rtnetlink lock before comming - * here (in dev_ioctl()). - * Third, the caller can wait on the Wireless Event - * - Jean II */ + /* If a scan is in-progress, return -EAGAIN */ + if (ai->scan_timeout > 0) return -EAGAIN; - } - ai->scan_timestamp = 0; - - /* There's only a race with proc_BSSList_open(), but its - * consequences are begnign. So I don't bother fixing it - Javier */ - /* Try to read the first entry of the scan result */ - rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 1); - if((rc) || (BSSList.index == 0xffff)) { - /* Client error, no scan results... - * The caller need to restart the scan. */ - return -ENODATA; - } + if (down_interruptible(&ai->sem)) + return -EAGAIN; - /* Read and parse all entries */ - while((!rc) && (BSSList.index != 0xffff)) { + list_for_each_entry (net, &ai->network_list, list) { /* Translate to WE format this entry */ current_ev = airo_translate_scan(dev, current_ev, extra + dwrq->length, - &BSSList); + &net->bss); /* Check if there is space for one more entry */ if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) { /* Ask user space to try again with a bigger buffer */ - return -E2BIG; + err = -E2BIG; + goto out; } - - /* Read next entry */ - rc = PC4500_readrid(ai, RID_BSSLISTNEXT, - &BSSList, sizeof(BSSList), 1); } + /* Length of data */ dwrq->length = (current_ev - extra); dwrq->flags = 0; /* todo */ - return 0; +out: + up(&ai->sem); + return err; } /*------------------------------------------------------------------*/ -- cgit v1.2.3-59-g8ed1b From 971d1e69229f3dfc6dd233b8f4b82df2c35eedd8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 19 Mar 2006 19:21:44 -0800 Subject: [PATCH] hostap: Fix hw reset after CMDCODE_ACCESS_WRITE timeout The Coverity checker (CID: 59) noted that the call to prism2_hw_reset() was dead code. Move prism2_hw_reset() call to a place where it is actually executed. Signed-off-by: Adrian Bunk Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_hw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index b1f142d9e232..328e9a1d13b5 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -928,15 +928,15 @@ static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len) res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS_WRITE, rid, NULL, NULL); up(&local->rid_bap_sem); + if (res) { printk(KERN_DEBUG "%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE " "failed (res=%d, rid=%04x, len=%d)\n", dev->name, res, rid, len); - return res; - } - if (res == -ETIMEDOUT) - prism2_hw_reset(dev); + if (res == -ETIMEDOUT) + prism2_hw_reset(dev); + } return res; } -- cgit v1.2.3-59-g8ed1b From 54b85f489bdfafc9306dfcc21e0d2687c34c3b34 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 19 Mar 2006 19:21:45 -0800 Subject: [PATCH] hostap: Fix ap_add_sta() return value verification The Coverity checker (CID: 273) spotted this inconsequent NULL checking (unconditionally dereferencing directly after checking for NULL isn't a good idea). Return immediately to avoid this. Signed-off-by: Adrian Bunk Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_ap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 753a1de6664b..06c3fa32b310 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -3141,7 +3141,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr) if (ret == 1) { sta = ap_add_sta(ap, sta_addr); if (!sta) - ret = -1; + return -1; sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; sta->ap = 1; memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); -- cgit v1.2.3-59-g8ed1b From 8abceaf1cf44b9d95bcc366fa277b33e292141c4 Mon Sep 17 00:00:00 2001 From: Eugene Teo Date: Sun, 19 Mar 2006 19:21:46 -0800 Subject: [PATCH] hostap: Fix double free in prism2_config() error path The Coverity checker (CID: 930) spotted this double free on error path (allocation failure). Do not free these here since generic error path will take care of this. Signed-off-by: Eugene Teo Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_cs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index f8f4503475f9..d335b250923a 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -585,8 +585,6 @@ static int prism2_config(dev_link_t *link) parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL); if (parse == NULL || hw_priv == NULL) { - kfree(parse); - kfree(hw_priv); ret = -ENOMEM; goto failed; } -- cgit v1.2.3-59-g8ed1b From 3a1c42ad98fddab63e62b400ae98e6f609485efc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Mar 2006 19:21:47 -0800 Subject: [PATCH] hostap: Fix unlikely read overrun in CIS parsing The Coverity checker (CID: 452, 453, 454, 455, 456) spotted this unlikely read overrun of CIS buffer. Abort if CISTPL_CONFIG or CISTPL_MANFID would not fit in buffer. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_plx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index 94fe2449f099..e258517ac85d 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -368,7 +368,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, switch (cis[pos]) { case CISTPL_CONFIG: - if (cis[pos + 1] < 1) + if (cis[pos + 1] < 2) goto cis_error; rmsz = (cis[pos + 2] & 0x3c) >> 2; rasz = cis[pos + 2] & 0x03; @@ -390,7 +390,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, break; case CISTPL_MANFID: - if (cis[pos + 1] < 4) + if (cis[pos + 1] < 5) goto cis_error; manfid1 = cis[pos + 2] + (cis[pos + 3] << 8); manfid2 = cis[pos + 4] + (cis[pos + 5] << 8); -- cgit v1.2.3-59-g8ed1b From 4f7ecdf0b1b8125fe190247beb0df652829e13cb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Mar 2006 19:21:48 -0800 Subject: [PATCH] hostap: Remove dead code (duplicated idx != 0) The Coverity checker (CID: 58) spotted this duplicated idx != 0 validation for unicast keys in prism2_ioctl_siwencodeext(). Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_ioctl.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index f3e0ce1ee037..8b37e824dfcb 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c @@ -3358,10 +3358,6 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { if (!sta_ptr) local->tx_keyidx = i; - else if (i) { - ret = -EINVAL; - goto done; - } } -- cgit v1.2.3-59-g8ed1b From 9320199957cebc39ccef372fa1fccf5ba3d3fd7d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Mar 2006 19:21:49 -0800 Subject: [PATCH] hostap: Fix memory leak on PCI probe error path The Coverity checker (CID: 659, 660) spotted this resource leak on PCI probe error path. Free private data structure if pci_enable_device() fails. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_pci.c | 4 +++- drivers/net/wireless/hostap/hostap_plx.c | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index 2e85bdced2dd..194f07097581 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -307,7 +307,7 @@ static int prism2_pci_probe(struct pci_dev *pdev, memset(hw_priv, 0, sizeof(*hw_priv)); if (pci_enable_device(pdev)) - return -EIO; + goto err_out_free; phymem = pci_resource_start(pdev, 0); @@ -368,6 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev, err_out_disable: pci_disable_device(pdev); prism2_free_local_data(dev); + + err_out_free: kfree(hw_priv); return -ENODEV; diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index e258517ac85d..edaaa943eb8f 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -452,7 +452,7 @@ static int prism2_plx_probe(struct pci_dev *pdev, memset(hw_priv, 0, sizeof(*hw_priv)); if (pci_enable_device(pdev)) - return -EIO; + goto err_out_free; /* National Datacomm NCP130 based on TMD7160, not PLX9052. */ tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131); @@ -567,9 +567,6 @@ static int prism2_plx_probe(struct pci_dev *pdev, return hostap_hw_ready(dev); fail: - prism2_free_local_data(dev); - kfree(hw_priv); - if (irq_registered && dev) free_irq(dev->irq, dev); @@ -577,6 +574,10 @@ static int prism2_plx_probe(struct pci_dev *pdev, iounmap(attr_mem); pci_disable_device(pdev); + prism2_free_local_data(dev); + + err_out_free: + kfree(hw_priv); return -ENODEV; } -- cgit v1.2.3-59-g8ed1b From d26045404c8925eadf252aeb6b5b8055fc01e9de Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 23 Mar 2006 08:51:36 -0800 Subject: [PATCH] sky2: typo in last stats patch Typo in last stats patch. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 36db93811ac7..78c210facaa8 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2484,7 +2484,7 @@ static const struct sky2_stat { { "single_collisions", GM_TXF_SNG_COL }, { "multi_collisions", GM_TXF_MUL_COL }, - { "rx_short", GM_RXE_SHT }, + { "rx_short", GM_RXF_SHT }, { "rx_runt", GM_RXE_FRAG }, { "rx_64_byte_packets", GM_RXF_64B }, { "rx_65_to_127_byte_packets", GM_RXF_127B }, -- cgit v1.2.3-59-g8ed1b From 050ff18016979b98e3cadb930d6e29bfd5530469 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 23 Mar 2006 08:51:37 -0800 Subject: [PATCH] sky2: Fix RX stats Unicast packets are shown as multicast, real multicast packets are missing. Signed-off-by: Patrick McHardy Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 78c210facaa8..f3f70b07576d 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2607,7 +2607,7 @@ static struct net_device_stats *sky2_get_stats(struct net_device *dev) sky2->net_stats.rx_bytes = data[1]; sky2->net_stats.tx_packets = data[2] + data[4] + data[6]; sky2->net_stats.rx_packets = data[3] + data[5] + data[7]; - sky2->net_stats.multicast = data[5] + data[7]; + sky2->net_stats.multicast = data[3] + data[5]; sky2->net_stats.collisions = data[10]; sky2->net_stats.tx_aborted_errors = data[12]; -- cgit v1.2.3-59-g8ed1b From 15240072ac3ffb67050acd0b71b477c3bb977670 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 23 Mar 2006 08:51:38 -0800 Subject: [PATCH] sky2: dont need to use dev_kfree_skb_any Transmit buffers are always freed with interrupts enabled (softirq), so we can just call dev_kfree_skb. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index f3f70b07576d..68f9c206a620 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1175,7 +1175,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) /* just drop the packet if non-linear expansion fails */ if (skb_header_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { - dev_kfree_skb_any(skb); + dev_kfree_skb(skb); goto out_unlock; } @@ -1324,7 +1324,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) PCI_DMA_TODEVICE); } - dev_kfree_skb_any(skb); + dev_kfree_skb(skb); } sky2->tx_cons = put; -- cgit v1.2.3-59-g8ed1b From 901ccefb2dd7fe6a9e750a68f990f2a7d76b78d2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 23 Mar 2006 11:07:23 -0800 Subject: [PATCH] skge: align receive buffers The skge driver aligns the header on the initial receive buffers, but but doesn't on followon receive buffer allocations. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 4eda81d41b10..89a6252ac7cc 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2155,7 +2155,7 @@ static int skge_up(struct net_device *dev) printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); if (dev->mtu > RX_BUF_SIZE) - skge->rx_buf_size = dev->mtu + ETH_HLEN + NET_IP_ALIGN; + skge->rx_buf_size = dev->mtu + ETH_HLEN; else skge->rx_buf_size = RX_BUF_SIZE; @@ -2611,6 +2611,7 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, if (!nskb) goto resubmit; + skb_reserve(nskb, NET_IP_ALIGN); pci_unmap_single(skge->hw->pdev, pci_unmap_addr(e, mapaddr), pci_unmap_len(e, maplen), -- cgit v1.2.3-59-g8ed1b From b5d56ddc3f839e94e97a3eb8afb4d0d64a9f2ef8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 23 Mar 2006 11:07:24 -0800 Subject: [PATCH] skge: dont use dev_alloc_skb for rx buffs The skge driver was using dev_alloc_skb which reserves space for the Ethernet header. This unnecessary and it should just use alloc_skb, also by using GFP_KERNEL during startup it won't run into problems when a user asks for a huge ring size or mtu and potentially drains the reserved atomic pool. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 89a6252ac7cc..b0aa150bbd8a 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -829,7 +829,7 @@ static int skge_rx_fill(struct skge_port *skge) do { struct sk_buff *skb; - skb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN); + skb = alloc_skb(skge->rx_buf_size + NET_IP_ALIGN, GFP_KERNEL); if (!skb) return -ENOMEM; @@ -2592,7 +2592,7 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, goto error; if (len < RX_COPY_THRESHOLD) { - skb = dev_alloc_skb(len + 2); + skb = alloc_skb(len + 2, GFP_ATOMIC); if (!skb) goto resubmit; @@ -2607,7 +2607,7 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, skge_rx_reuse(e, skge->rx_buf_size); } else { struct sk_buff *nskb; - nskb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN); + nskb = alloc_skb(skge->rx_buf_size + NET_IP_ALIGN, GFP_ATOMIC); if (!nskb) goto resubmit; -- cgit v1.2.3-59-g8ed1b From 5a01144717ee9dacd45e1b0861a2c593796bcead Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 23 Mar 2006 11:07:25 -0800 Subject: [PATCH] skge: rx_reuse called twice In the error case we call skge_rx_reuse twice. This is harmless but unnecessary. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index b0aa150bbd8a..72148f0fbfcc 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -781,7 +781,7 @@ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, * Note: DMA address is not changed by chip. * MTU not changed while receiver active. */ -static void skge_rx_reuse(struct skge_element *e, unsigned int size) +static inline void skge_rx_reuse(struct skge_element *e, unsigned int size) { struct skge_rx_desc *rd = e->desc; @@ -2719,8 +2719,7 @@ static int skge_poll(struct net_device *dev, int *budget) netif_receive_skb(skb); ++work_done; - } else - skge_rx_reuse(e, skge->rx_buf_size); + } } ring->to_clean = e; -- cgit v1.2.3-59-g8ed1b From 4c180fc424550217344db6fe8960732dbd7feb0c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 23 Mar 2006 11:07:26 -0800 Subject: [PATCH] skge: multicast statistics fix Fix count of multicast packets. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 72148f0fbfcc..e15cbefcb6e3 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -357,7 +357,7 @@ static struct net_device_stats *skge_get_stats(struct net_device *dev) skge->net_stats.rx_bytes = data[1]; skge->net_stats.tx_packets = data[2] + data[4] + data[6]; skge->net_stats.rx_packets = data[3] + data[5] + data[7]; - skge->net_stats.multicast = data[5] + data[7]; + skge->net_stats.multicast = data[3] + data[5]; skge->net_stats.collisions = data[10]; skge->net_stats.tx_aborted_errors = data[12]; -- cgit v1.2.3-59-g8ed1b From 866b4f3e94a7568a1cb0018c061e19e120de6922 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 23 Mar 2006 11:07:27 -0800 Subject: [PATCH] skge: dont free skb until multi-part transmit complete Don't free transmit buffers until the whole set of transmit descriptors has been marked as done. Otherwise, we risk freeing a skb before the whole transmit is done. This changes the transmit completion handling from incremental to a two pass algorithm. First pass scans and records the start of the last done descriptor, second cleans up until that point. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 73 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index e15cbefcb6e3..a261766bc052 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2404,35 +2404,39 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static inline void skge_tx_free(struct skge_hw *hw, struct skge_element *e) -{ - /* This ring element can be skb or fragment */ - if (e->skb) { - pci_unmap_single(hw->pdev, - pci_unmap_addr(e, mapaddr), - pci_unmap_len(e, maplen), - PCI_DMA_TODEVICE); - dev_kfree_skb(e->skb); +static void skge_tx_complete(struct skge_port *skge, struct skge_element *last) +{ + struct pci_dev *pdev = skge->hw->pdev; + struct skge_element *e; + + for (e = skge->tx_ring.to_clean; e != last; e = e->next) { + struct sk_buff *skb = e->skb; + int i; + e->skb = NULL; - } else { - pci_unmap_page(hw->pdev, - pci_unmap_addr(e, mapaddr), - pci_unmap_len(e, maplen), - PCI_DMA_TODEVICE); + pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr), + skb_headlen(skb), PCI_DMA_TODEVICE); + ++skge->tx_avail; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + e = e->next; + pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr), + skb_shinfo(skb)->frags[i].size, + PCI_DMA_TODEVICE); + ++skge->tx_avail; + } + + dev_kfree_skb(skb); } + skge->tx_ring.to_clean = e; } static void skge_tx_clean(struct skge_port *skge) { - struct skge_ring *ring = &skge->tx_ring; - struct skge_element *e; spin_lock_bh(&skge->tx_lock); - for (e = ring->to_clean; e != ring->to_use; e = e->next) { - ++skge->tx_avail; - skge_tx_free(skge->hw, e); - } - ring->to_clean = e; + skge_tx_complete(skge, skge->tx_ring.to_use); + netif_wake_queue(skge->netdev); spin_unlock_bh(&skge->tx_lock); } @@ -2662,27 +2666,26 @@ resubmit: static void skge_tx_done(struct skge_port *skge) { struct skge_ring *ring = &skge->tx_ring; - struct skge_element *e; + struct skge_element *e, *last; spin_lock(&skge->tx_lock); - for (e = ring->to_clean; prefetch(e->next), e != ring->to_use; e = e->next) { + last = ring->to_clean; + for (e = ring->to_clean; e != ring->to_use; e = e->next) { struct skge_tx_desc *td = e->desc; - u32 control; - rmb(); - control = td->control; - if (control & BMU_OWN) + if (td->control & BMU_OWN) break; - if (unlikely(netif_msg_tx_done(skge))) - printk(KERN_DEBUG PFX "%s: tx done slot %td status 0x%x\n", - skge->netdev->name, e - ring->start, td->status); - - skge_tx_free(skge->hw, e); - e->skb = NULL; - ++skge->tx_avail; + if (td->control & BMU_EOF) { + last = e->next; + if (unlikely(netif_msg_tx_done(skge))) + printk(KERN_DEBUG PFX "%s: tx done slot %td\n", + skge->netdev->name, e - ring->start); + } } - ring->to_clean = e; + + skge_tx_complete(skge, last); + skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); if (skge->tx_avail > MAX_SKB_FRAGS + 1) -- cgit v1.2.3-59-g8ed1b From 29b4e886cbba5e0b0e4379fea7fc313e7808b5c2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 23 Mar 2006 11:07:28 -0800 Subject: [PATCH] skge: compute available ring buffers Don't need to keep track of available buffers, it is simpler to just compute the value (ala e1000). Don't need tes on link up because should always have available buffers then. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 20 ++++++++++---------- drivers/net/skge.h | 1 - 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index a261766bc052..a6f42fc85738 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -847,8 +847,7 @@ static void skge_link_up(struct skge_port *skge) LED_BLK_OFF|LED_SYNC_OFF|LED_ON); netif_carrier_on(skge->netdev); - if (skge->tx_avail > MAX_SKB_FRAGS + 1) - netif_wake_queue(skge->netdev); + netif_wake_queue(skge->netdev); if (netif_msg_link(skge)) printk(KERN_INFO PFX @@ -2190,8 +2189,6 @@ static int skge_up(struct net_device *dev) if (err) goto free_rx_ring; - skge->tx_avail = skge->tx_ring.count - 1; - /* Initialize MAC */ spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) @@ -2294,6 +2291,12 @@ static int skge_down(struct net_device *dev) return 0; } +static inline int skge_avail(const struct skge_ring *ring) +{ + return ((ring->to_clean > ring->to_use) ? 0 : ring->count) + + (ring->to_clean - ring->to_use) - 1; +} + static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) { struct skge_port *skge = netdev_priv(dev); @@ -2314,7 +2317,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_LOCKED; } - if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) { + if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -2390,8 +2393,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) dev->name, e - ring->start, skb->len); ring->to_use = e->next; - skge->tx_avail -= skb_shinfo(skb)->nr_frags + 1; - if (skge->tx_avail <= MAX_SKB_FRAGS + 1) { + if (skge_avail(&skge->tx_ring) <= MAX_SKB_FRAGS + 1) { pr_debug("%s: transmit queue full\n", dev->name); netif_stop_queue(dev); } @@ -2416,14 +2418,12 @@ static void skge_tx_complete(struct skge_port *skge, struct skge_element *last) e->skb = NULL; pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr), skb_headlen(skb), PCI_DMA_TODEVICE); - ++skge->tx_avail; for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { e = e->next; pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr), skb_shinfo(skb)->frags[i].size, PCI_DMA_TODEVICE); - ++skge->tx_avail; } dev_kfree_skb(skb); @@ -2688,7 +2688,7 @@ static void skge_tx_done(struct skge_port *skge) skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); - if (skge->tx_avail > MAX_SKB_FRAGS + 1) + if (skge_avail(&skge->tx_ring) > MAX_SKB_FRAGS + 1) netif_wake_queue(skge->netdev); spin_unlock(&skge->tx_lock); diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 2efdacc290e5..1f1ce88c8186 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2418,7 +2418,6 @@ struct skge_port { int port; spinlock_t tx_lock; - u32 tx_avail; struct skge_ring tx_ring; struct skge_ring rx_ring; -- cgit v1.2.3-59-g8ed1b From eff4b1fe0aa8002cbf414576e8cc102967bd9d5d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 23 Mar 2006 11:07:29 -0800 Subject: [PATCH] skge: version 1.5 Update version to allow tracking of complaints. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index a6f42fc85738..35dbf05c7f06 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -44,7 +44,7 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.4" +#define DRV_VERSION "1.5" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 -- cgit v1.2.3-59-g8ed1b From dedc6a7803d9c9795b504ffd8530a4ba7b3fd9ed Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Mon, 9 Jan 2006 23:24:41 +0100 Subject: [PATCH] hwmon: Use attribute arrays in pc87360 Convert individual sensors to sensor-attr arrays by each sensor type, and initialize them in loops instead of long blocks of individual calls. Signed-off-by: Jim Cromie Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/pc87360.c | 408 ++++++++++++++++++++++++------------------------ 1 file changed, 201 insertions(+), 207 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index f161e88e3bb6..2de69322f525 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -305,18 +305,26 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, return count; } -#define show_and_set_fan(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan_input, NULL, offset-1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \ - show_fan_min, set_fan_min, offset-1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO, \ - show_fan_div, NULL, offset-1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_status, S_IRUGO, \ - show_fan_status, NULL, offset-1); -show_and_set_fan(1) -show_and_set_fan(2) -show_and_set_fan(3) +static struct sensor_device_attribute fan_input[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1), + SENSOR_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2), +}; +static struct sensor_device_attribute fan_status[] = { + SENSOR_ATTR(fan1_status, S_IRUGO, show_fan_status, NULL, 0), + SENSOR_ATTR(fan2_status, S_IRUGO, show_fan_status, NULL, 1), + SENSOR_ATTR(fan3_status, S_IRUGO, show_fan_status, NULL, 2), +}; +static struct sensor_device_attribute fan_div[] = { + SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), + SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), + SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), +}; +static struct sensor_device_attribute fan_min[] = { + SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 0), + SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 1), + SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2), +}; static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -344,12 +352,11 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, con return count; } -#define show_and_set_pwm(offset) \ -static SENSOR_DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \ - show_pwm, set_pwm, offset-1); -show_and_set_pwm(1) -show_and_set_pwm(2) -show_and_set_pwm(3) +static struct sensor_device_attribute pwm[] = { + SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0), + SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1), + SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2), +}; static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -410,26 +417,58 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, return count; } -#define show_and_set_in(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in_input, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \ - show_in_max, set_in_max, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_status, S_IRUGO, \ - show_in_status, NULL, offset); -show_and_set_in(0) -show_and_set_in(1) -show_and_set_in(2) -show_and_set_in(3) -show_and_set_in(4) -show_and_set_in(5) -show_and_set_in(6) -show_and_set_in(7) -show_and_set_in(8) -show_and_set_in(9) -show_and_set_in(10) +static struct sensor_device_attribute in_input[] = { + SENSOR_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0), + SENSOR_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2), + SENSOR_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3), + SENSOR_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4), + SENSOR_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5), + SENSOR_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6), + SENSOR_ATTR(in7_input, S_IRUGO, show_in_input, NULL, 7), + SENSOR_ATTR(in8_input, S_IRUGO, show_in_input, NULL, 8), + SENSOR_ATTR(in9_input, S_IRUGO, show_in_input, NULL, 9), + SENSOR_ATTR(in10_input, S_IRUGO, show_in_input, NULL, 10), +}; +static struct sensor_device_attribute in_status[] = { + SENSOR_ATTR(in0_status, S_IRUGO, show_in_status, NULL, 0), + SENSOR_ATTR(in1_status, S_IRUGO, show_in_status, NULL, 1), + SENSOR_ATTR(in2_status, S_IRUGO, show_in_status, NULL, 2), + SENSOR_ATTR(in3_status, S_IRUGO, show_in_status, NULL, 3), + SENSOR_ATTR(in4_status, S_IRUGO, show_in_status, NULL, 4), + SENSOR_ATTR(in5_status, S_IRUGO, show_in_status, NULL, 5), + SENSOR_ATTR(in6_status, S_IRUGO, show_in_status, NULL, 6), + SENSOR_ATTR(in7_status, S_IRUGO, show_in_status, NULL, 7), + SENSOR_ATTR(in8_status, S_IRUGO, show_in_status, NULL, 8), + SENSOR_ATTR(in9_status, S_IRUGO, show_in_status, NULL, 9), + SENSOR_ATTR(in10_status, S_IRUGO, show_in_status, NULL, 10), +}; +static struct sensor_device_attribute in_min[] = { + SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 0), + SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 1), + SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 2), + SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 3), + SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 4), + SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 5), + SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 6), + SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 7), + SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 8), + SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 9), + SENSOR_ATTR(in10_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 10), +}; +static struct sensor_device_attribute in_max[] = { + SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 0), + SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 1), + SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 2), + SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 3), + SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 4), + SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 5), + SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 6), + SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 7), + SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 8), + SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 9), + SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10), +}; static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -511,20 +550,43 @@ static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devat return count; } -#define show_and_set_therm(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_therm_input, NULL, 11+offset-4); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ - show_therm_min, set_therm_min, 11+offset-4); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ - show_therm_max, set_therm_max, 11+offset-4); \ -static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \ - show_therm_crit, set_therm_crit, 11+offset-4); \ -static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \ - show_therm_status, NULL, 11+offset-4); -show_and_set_therm(4) -show_and_set_therm(5) -show_and_set_therm(6) +/* the +11 term below reflects the fact that VLM units 11,12,13 are + used in the chip to measure voltage across the thermistors +*/ +static struct sensor_device_attribute therm_input[] = { + SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0+11), + SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1+11), + SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2+11), +}; +static struct sensor_device_attribute therm_status[] = { + SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0+11), + SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1+11), + SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2+11), +}; +static struct sensor_device_attribute therm_min[] = { + SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR, + show_therm_min, set_therm_min, 0+11), + SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR, + show_therm_min, set_therm_min, 1+11), + SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR, + show_therm_min, set_therm_min, 2+11), +}; +static struct sensor_device_attribute therm_max[] = { + SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, + show_therm_max, set_therm_max, 0+11), + SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, + show_therm_max, set_therm_max, 1+11), + SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, + show_therm_max, set_therm_max, 2+11), +}; +static struct sensor_device_attribute therm_crit[] = { + SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR, + show_therm_crit, set_therm_crit, 0+11), + SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR, + show_therm_crit, set_therm_crit, 1+11), + SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR, + show_therm_crit, set_therm_crit, 2+11), +}; static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) { @@ -630,20 +692,40 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devatt return count; } -#define show_and_set_temp(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp_input, NULL, offset-1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ - show_temp_min, set_temp_min, offset-1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ - show_temp_max, set_temp_max, offset-1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \ - show_temp_crit, set_temp_crit, offset-1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \ - show_temp_status, NULL, offset-1); -show_and_set_temp(1) -show_and_set_temp(2) -show_and_set_temp(3) +static struct sensor_device_attribute temp_input[] = { + SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0), + SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1), + SENSOR_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2), +}; +static struct sensor_device_attribute temp_status[] = { + SENSOR_ATTR(temp1_status, S_IRUGO, show_temp_status, NULL, 0), + SENSOR_ATTR(temp2_status, S_IRUGO, show_temp_status, NULL, 1), + SENSOR_ATTR(temp3_status, S_IRUGO, show_temp_status, NULL, 2), +}; +static struct sensor_device_attribute temp_min[] = { + SENSOR_ATTR(temp1_min, S_IRUGO | S_IWUSR, + show_temp_min, set_temp_min, 0), + SENSOR_ATTR(temp2_min, S_IRUGO | S_IWUSR, + show_temp_min, set_temp_min, 1), + SENSOR_ATTR(temp3_min, S_IRUGO | S_IWUSR, + show_temp_min, set_temp_min, 2), +}; +static struct sensor_device_attribute temp_max[] = { + SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 0), + SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 1), + SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 2), +}; +static struct sensor_device_attribute temp_crit[] = { + SENSOR_ATTR(temp1_crit, S_IRUGO | S_IWUSR, + show_temp_crit, set_temp_crit, 0), + SENSOR_ATTR(temp2_crit, S_IRUGO | S_IWUSR, + show_temp_crit, set_temp_crit, 1), + SENSOR_ATTR(temp3_crit, S_IRUGO | S_IWUSR, + show_temp_crit, set_temp_crit, 2), +}; static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf) { @@ -749,22 +831,24 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses static int pc87360_detect(struct i2c_adapter *adapter) { int i; - struct i2c_client *new_client; + struct i2c_client *client; struct pc87360_data *data; int err = 0; const char *name = "pc87360"; int use_thermistors = 0; + struct device *dev; if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL))) return -ENOMEM; - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; init_MUTEX(&data->lock); - new_client->adapter = adapter; - new_client->driver = &pc87360_driver; - new_client->flags = 0; + client->adapter = adapter; + client->driver = &pc87360_driver; + client->flags = 0; data->fannr = 2; data->innr = 0; @@ -792,7 +876,7 @@ static int pc87360_detect(struct i2c_adapter *adapter) break; } - strcpy(new_client->name, name); + strlcpy(client->name, name, sizeof(client->name)); data->valid = 0; init_MUTEX(&data->update_lock); @@ -800,7 +884,7 @@ static int pc87360_detect(struct i2c_adapter *adapter) if (((data->address[i] = extra_isa[i])) && !request_region(extra_isa[i], PC87360_EXTENT, pc87360_driver.driver.name)) { - dev_err(&new_client->dev, "Region 0x%x-0x%x already " + dev_err(&client->dev, "Region 0x%x-0x%x already " "in use!\n", extra_isa[i], extra_isa[i]+PC87360_EXTENT-1); for (i--; i >= 0; i--) @@ -814,7 +898,7 @@ static int pc87360_detect(struct i2c_adapter *adapter) if (data->fannr) data->fan_conf = confreg[0] | (confreg[1] << 8); - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto ERROR2; /* Use the correct reference voltage @@ -828,7 +912,7 @@ static int pc87360_detect(struct i2c_adapter *adapter) PC87365_REG_TEMP_CONFIG); } data->in_vref = (i&0x02) ? 3025 : 2966; - dev_dbg(&new_client->dev, "Using %s reference voltage\n", + dev_dbg(&client->dev, "Using %s reference voltage\n", (i&0x02) ? "external" : "internal"); data->vid_conf = confreg[3]; @@ -847,154 +931,64 @@ static int pc87360_detect(struct i2c_adapter *adapter) if (devid == 0xe9 && data->address[1]) /* PC87366 */ use_thermistors = confreg[2] & 0x40; - pc87360_init_client(new_client, use_thermistors); + pc87360_init_client(client, use_thermistors); } /* Register sysfs hooks */ - data->class_dev = hwmon_device_register(&new_client->dev); + data->class_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto ERROR3; } if (data->innr) { - device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in0_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in1_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in2_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in3_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in4_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in5_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in6_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in7_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in8_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in9_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_in10_status.dev_attr); - - device_create_file(&new_client->dev, &dev_attr_cpu0_vid); - device_create_file(&new_client->dev, &dev_attr_vrm); - device_create_file(&new_client->dev, &dev_attr_alarms_in); + for (i = 0; i < 11; i++) { + device_create_file(dev, &in_input[i].dev_attr); + device_create_file(dev, &in_min[i].dev_attr); + device_create_file(dev, &in_max[i].dev_attr); + device_create_file(dev, &in_status[i].dev_attr); + } + device_create_file(dev, &dev_attr_cpu0_vid); + device_create_file(dev, &dev_attr_vrm); + device_create_file(dev, &dev_attr_alarms_in); } if (data->tempnr) { - 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_temp1_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.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_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_temp1_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp2_status.dev_attr); - - device_create_file(&new_client->dev, &dev_attr_alarms_temp); - } - if (data->tempnr == 3) { - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_status.dev_attr); - } - if (data->innr == 14) { - device_create_file(&new_client->dev, &sensor_dev_attr_temp4_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp5_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp6_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp4_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp5_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp6_min.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp4_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp5_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp6_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp4_crit.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp5_crit.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp6_crit.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp4_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp5_status.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp6_status.dev_attr); - } - - if (data->fannr) { - if (FAN_CONFIG_MONITOR(data->fan_conf, 0)) { - device_create_file(&new_client->dev, - &sensor_dev_attr_fan1_input.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan1_min.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan1_div.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan1_status.dev_attr); + for (i = 0; i < data->tempnr; i++) { + device_create_file(dev, &temp_input[i].dev_attr); + device_create_file(dev, &temp_min[i].dev_attr); + device_create_file(dev, &temp_max[i].dev_attr); + device_create_file(dev, &temp_crit[i].dev_attr); + device_create_file(dev, &temp_status[i].dev_attr); } + device_create_file(dev, &dev_attr_alarms_temp); + } - if (FAN_CONFIG_MONITOR(data->fan_conf, 1)) { - device_create_file(&new_client->dev, - &sensor_dev_attr_fan2_input.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan2_min.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan2_div.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan2_status.dev_attr); + if (data->innr == 14) { + for (i = 0; i < 3; i++) { + device_create_file(dev, &therm_input[i].dev_attr); + device_create_file(dev, &therm_min[i].dev_attr); + device_create_file(dev, &therm_max[i].dev_attr); + device_create_file(dev, &therm_crit[i].dev_attr); + device_create_file(dev, &therm_status[i].dev_attr); } - - if (FAN_CONFIG_CONTROL(data->fan_conf, 0)) - device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr); - if (FAN_CONFIG_CONTROL(data->fan_conf, 1)) - device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr); } - if (data->fannr == 3) { - if (FAN_CONFIG_MONITOR(data->fan_conf, 2)) { - device_create_file(&new_client->dev, - &sensor_dev_attr_fan3_input.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan3_min.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan3_div.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan3_status.dev_attr); - } - if (FAN_CONFIG_CONTROL(data->fan_conf, 2)) - device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr); + for (i = 0; i < data->fannr; i++) { + if (FAN_CONFIG_MONITOR(data->fan_conf, i)) { + device_create_file(dev, &fan_input[i].dev_attr); + device_create_file(dev, &fan_min[i].dev_attr); + device_create_file(dev, &fan_div[i].dev_attr); + device_create_file(dev, &fan_status[i].dev_attr); + } + if (FAN_CONFIG_CONTROL(data->fan_conf, i)) + device_create_file(dev, &pwm[i].dev_attr); } return 0; ERROR3: - i2c_detach_client(new_client); + i2c_detach_client(client); ERROR2: for (i = 0; i < 3; i++) { if (data->address[i]) { @@ -1071,7 +1065,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) } nr = data->innr < 11 ? data->innr : 11; - for (i=0; i= init_in[i]) { /* Forcibly enable voltage channel */ reg = pc87360_read_value(data, LD_IN, i, @@ -1088,14 +1082,14 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) /* We can't blindly trust the Super-I/O space configuration bit, most BIOS won't set it properly */ - for (i=11; iinnr; i++) { + for (i = 11; i < data->innr; i++) { reg = pc87360_read_value(data, LD_IN, i, PC87365_REG_TEMP_STATUS); use_thermistors = use_thermistors || (reg & 0x01); } i = use_thermistors ? 2 : 0; - for (; itempnr; i++) { + for (; i < data->tempnr; i++) { if (init >= init_temp[i]) { /* Forcibly enable temperature channel */ reg = pc87360_read_value(data, LD_TEMP, i, @@ -1111,7 +1105,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) } if (use_thermistors) { - for (i=11; iinnr; i++) { + for (i = 11; i < data->innr; i++) { if (init >= init_in[i]) { /* The pin may already be used by thermal diodes */ -- cgit v1.2.3-59-g8ed1b From 2488a39d233a758d41ab7de70a220bc956f3c96c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 9 Jan 2006 23:29:11 +0100 Subject: [PATCH] hwmon: Use attribute arrays in f71805f Convert the f71805f driver to use arrays of attributes. This shrinks the compiled module from 12.0 kB to 9.6 kB. We certainly should do the same for as many hardware monitoring drivers as possible. This, together with a nice chip design by Fintek, makes this driver very small, both in terms of number of lines of code and memory consumption. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/f71805f.c | 218 +++++++++++++++++++++++------------------------- 1 file changed, 103 insertions(+), 115 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index e029e0a94ecc..8e810f05d0ae 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -384,10 +384,6 @@ static ssize_t set_in0_min(struct device *dev, struct device_attribute return count; } -static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL); -static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max); -static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min); - static ssize_t show_in(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -450,23 +446,6 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute return count; } -#define sysfs_in(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset) - -sysfs_in(1); -sysfs_in(2); -sysfs_in(3); -sysfs_in(4); -sysfs_in(5); -sysfs_in(6); -sysfs_in(7); -sysfs_in(8); - static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -503,16 +482,6 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute return count; } -#define sysfs_fan(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1) - -sysfs_fan(1); -sysfs_fan(2); -sysfs_fan(3); - static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -586,20 +555,6 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute return count; } -#define sysfs_temp(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_max, set_temp_max, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp_hyst, set_temp_hyst, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \ - show_temp_type, NULL, offset - 1) - -sysfs_temp(1); -sysfs_temp(2); -sysfs_temp(3); - static ssize_t show_alarms_in(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -625,10 +580,6 @@ static ssize_t show_alarms_temp(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07); } -static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL); -static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL); -static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL); - static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -637,7 +588,89 @@ static ssize_t show_name(struct device *dev, struct device_attribute return sprintf(buf, "%s\n", data->name); } -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); +static struct device_attribute f71805f_dev_attr[] = { + __ATTR(in0_input, S_IRUGO, show_in0, NULL), + __ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max), + __ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min), + __ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL), + __ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL), + __ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL), + __ATTR(name, S_IRUGO, show_name, NULL), +}; + +static struct sensor_device_attribute f71805f_sensor_attr[] = { + SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), + SENSOR_ATTR(in1_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 1), + SENSOR_ATTR(in1_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), + SENSOR_ATTR(in2_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 2), + SENSOR_ATTR(in2_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 2), + SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), + SENSOR_ATTR(in3_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 3), + SENSOR_ATTR(in3_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 3), + SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), + SENSOR_ATTR(in4_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 4), + SENSOR_ATTR(in4_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 4), + SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), + SENSOR_ATTR(in5_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 5), + SENSOR_ATTR(in5_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 5), + SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), + SENSOR_ATTR(in6_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 6), + SENSOR_ATTR(in6_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 6), + SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), + SENSOR_ATTR(in7_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 7), + SENSOR_ATTR(in7_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 7), + SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), + SENSOR_ATTR(in8_max, S_IRUGO | S_IWUSR, + show_in_max, set_in_max, 8), + SENSOR_ATTR(in8_min, S_IRUGO | S_IWUSR, + show_in_min, set_in_min, 8), + + SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0), + SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 0), + SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, + show_temp_hyst, set_temp_hyst, 0), + SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), + SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1), + SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 1), + SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, + show_temp_hyst, set_temp_hyst, 1), + SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), + SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2), + SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, + show_temp_max, set_temp_max, 2), + SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, + show_temp_hyst, set_temp_hyst, 2), + SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), +}; + +static struct sensor_device_attribute f71805f_fan_attr[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), + SENSOR_ATTR(fan1_min, S_IRUGO | S_IWUSR, + show_fan_min, set_fan_min, 0), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), + SENSOR_ATTR(fan2_min, S_IRUGO | S_IWUSR, + show_fan_min, set_fan_min, 1), + SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), + SENSOR_ATTR(fan3_min, S_IRUGO | S_IWUSR, + show_fan_min, set_fan_min, 2), +}; /* * Device registration and initialization @@ -668,7 +701,7 @@ static int __devinit f71805f_probe(struct platform_device *pdev) { struct f71805f_data *data; struct resource *res; - int err; + int i, err; if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) { err = -ENOMEM; @@ -695,76 +728,31 @@ static int __devinit f71805f_probe(struct platform_device *pdev) f71805f_init_device(data); /* Register sysfs interface files */ - device_create_file(&pdev->dev, &dev_attr_in0_input); - device_create_file(&pdev->dev, &dev_attr_in0_max); - device_create_file(&pdev->dev, &dev_attr_in0_min); - device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr); - if (data->fan_enabled & (1 << 0)) { - device_create_file(&pdev->dev, - &sensor_dev_attr_fan1_input.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_fan1_min.dev_attr); + for (i = 0; i < ARRAY_SIZE(f71805f_dev_attr); i++) { + err = device_create_file(&pdev->dev, &f71805f_dev_attr[i]); + if (err) + goto exit_class; } - if (data->fan_enabled & (1 << 1)) { - device_create_file(&pdev->dev, - &sensor_dev_attr_fan2_input.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_fan2_min.dev_attr); + for (i = 0; i < ARRAY_SIZE(f71805f_sensor_attr); i++) { + err = device_create_file(&pdev->dev, + &f71805f_sensor_attr[i].dev_attr); + if (err) + goto exit_class; } - if (data->fan_enabled & (1 << 2)) { - device_create_file(&pdev->dev, - &sensor_dev_attr_fan3_input.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_fan3_min.dev_attr); + for (i = 0; i < ARRAY_SIZE(f71805f_fan_attr); i++) { + if (!(data->fan_enabled & (1 << (i / 2)))) + continue; + err = device_create_file(&pdev->dev, + &f71805f_fan_attr[i].dev_attr); + if (err) + goto exit_class; } - device_create_file(&pdev->dev, - &sensor_dev_attr_temp1_input.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_temp2_input.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_temp3_input.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_temp1_max_hyst.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_temp2_max_hyst.dev_attr); - device_create_file(&pdev->dev, - &sensor_dev_attr_temp3_max_hyst.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr); - device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr); - device_create_file(&pdev->dev, &dev_attr_alarms_in); - device_create_file(&pdev->dev, &dev_attr_alarms_fan); - device_create_file(&pdev->dev, &dev_attr_alarms_temp); - device_create_file(&pdev->dev, &dev_attr_name); return 0; +exit_class: + dev_err(&pdev->dev, "Sysfs interface creation failed\n"); + hwmon_device_unregister(data->class_dev); exit_free: kfree(data); exit: -- cgit v1.2.3-59-g8ed1b From b3585e4f5b3e4ddb4d82ae50d0b844f619c6d821 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Wed, 11 Jan 2006 10:50:26 +0100 Subject: [PATCH] I2C: Convert i2c to mutexes The patch below converts a few i2c semaphores to mutexes Signed-off-by: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-ali1535.c | 7 ++++--- drivers/i2c/chips/ds1374.c | 11 ++++++----- drivers/i2c/chips/m41t00.c | 11 ++++++----- drivers/i2c/i2c-core.c | 23 ++++++++++++----------- 4 files changed, 28 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 3eb47890db40..26cf891762b8 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -136,7 +137,7 @@ static struct pci_driver ali1535_driver; static unsigned short ali1535_smba; -static DECLARE_MUTEX(i2c_ali1535_sem); +static DEFINE_MUTEX(i2c_ali1535_mutex); /* Detect whether a ALI1535 can be found, and initialize it, where necessary. Note the differences between kernels with the old PCI BIOS interface and @@ -345,7 +346,7 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, int timeout; s32 result = 0; - down(&i2c_ali1535_sem); + mutex_lock(&i2c_ali1535_mutex); /* make sure SMBus is idle */ temp = inb_p(SMBHSTSTS); for (timeout = 0; @@ -460,7 +461,7 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, break; } EXIT: - up(&i2c_ali1535_sem); + mutex_unlock(&i2c_ali1535_mutex); return result; } diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c index 0710b9da9d54..03d09ed5ec2c 100644 --- a/drivers/i2c/chips/ds1374.c +++ b/drivers/i2c/chips/ds1374.c @@ -26,6 +26,7 @@ #include #include #include +#include #define DS1374_REG_TOD0 0x00 #define DS1374_REG_TOD1 0x01 @@ -41,7 +42,7 @@ #define DS1374_DRV_NAME "ds1374" -static DECLARE_MUTEX(ds1374_mutex); +static DEFINE_MUTEX(ds1374_mutex); static struct i2c_driver ds1374_driver; static struct i2c_client *save_client; @@ -114,7 +115,7 @@ ulong ds1374_get_rtc_time(void) ulong t1, t2; int limit = 10; /* arbitrary retry limit */ - down(&ds1374_mutex); + mutex_lock(&ds1374_mutex); /* * Since the reads are being performed one byte at a time using @@ -127,7 +128,7 @@ ulong ds1374_get_rtc_time(void) t2 = ds1374_read_rtc(); } while (t1 != t2 && limit--); - up(&ds1374_mutex); + mutex_unlock(&ds1374_mutex); if (t1 != t2) { dev_warn(&save_client->dev, @@ -145,7 +146,7 @@ static void ds1374_set_tlet(ulong arg) t1 = *(ulong *) arg; - down(&ds1374_mutex); + mutex_lock(&ds1374_mutex); /* * Since the writes are being performed one byte at a time using @@ -158,7 +159,7 @@ static void ds1374_set_tlet(ulong arg) t2 = ds1374_read_rtc(); } while (t1 != t2 && limit--); - up(&ds1374_mutex); + mutex_unlock(&ds1374_mutex); if (t1 != t2) dev_warn(&save_client->dev, diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c index 2dc3d48375fc..b5aabe7cf792 100644 --- a/drivers/i2c/chips/m41t00.c +++ b/drivers/i2c/chips/m41t00.c @@ -24,13 +24,14 @@ #include #include #include +#include #include #include #define M41T00_DRV_NAME "m41t00" -static DECLARE_MUTEX(m41t00_mutex); +static DEFINE_MUTEX(m41t00_mutex); static struct i2c_driver m41t00_driver; static struct i2c_client *save_client; @@ -54,7 +55,7 @@ m41t00_get_rtc_time(void) sec = min = hour = day = mon = year = 0; sec1 = min1 = hour1 = day1 = mon1 = year1 = 0; - down(&m41t00_mutex); + 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)) @@ -80,7 +81,7 @@ m41t00_get_rtc_time(void) mon1 = mon; year1 = year; } while (--limit > 0); - up(&m41t00_mutex); + mutex_unlock(&m41t00_mutex); if (limit == 0) { dev_warn(&save_client->dev, @@ -125,7 +126,7 @@ m41t00_set_tlet(ulong arg) BIN_TO_BCD(tm.tm_mday); BIN_TO_BCD(tm.tm_year); - down(&m41t00_mutex); + 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) @@ -140,7 +141,7 @@ m41t00_set_tlet(ulong arg) dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n"); - up(&m41t00_mutex); + mutex_unlock(&m41t00_mutex); return; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 1a2c9ab5d9e3..97334433e534 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -31,12 +31,13 @@ #include #include #include +#include #include static LIST_HEAD(adapters); static LIST_HEAD(drivers); -static DECLARE_MUTEX(core_lists); +static DEFINE_MUTEX(core_lists); static DEFINE_IDR(i2c_adapter_idr); /* match always succeeds, as we want the probe() to tell if we really accept this match */ @@ -153,7 +154,7 @@ int i2c_add_adapter(struct i2c_adapter *adap) struct list_head *item; struct i2c_driver *driver; - down(&core_lists); + mutex_lock(&core_lists); if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) { res = -ENOMEM; @@ -203,7 +204,7 @@ int i2c_add_adapter(struct i2c_adapter *adap) } out_unlock: - up(&core_lists); + mutex_unlock(&core_lists); return res; } @@ -216,7 +217,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) struct i2c_client *client; int res = 0; - down(&core_lists); + mutex_lock(&core_lists); /* First make sure that this adapter was ever added */ list_for_each_entry(adap_from_list, &adapters, list) { @@ -272,7 +273,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); out_unlock: - up(&core_lists); + mutex_unlock(&core_lists); return res; } @@ -289,7 +290,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) struct i2c_adapter *adapter; int res = 0; - down(&core_lists); + mutex_lock(&core_lists); /* add the driver to the list of i2c drivers in the driver core */ driver->driver.owner = owner; @@ -311,7 +312,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) } out_unlock: - up(&core_lists); + mutex_unlock(&core_lists); return res; } EXPORT_SYMBOL(i2c_register_driver); @@ -324,7 +325,7 @@ int i2c_del_driver(struct i2c_driver *driver) int res = 0; - down(&core_lists); + mutex_lock(&core_lists); /* Have a look at each adapter, if clients of this driver are still * attached. If so, detach them to be able to kill the driver @@ -363,7 +364,7 @@ int i2c_del_driver(struct i2c_driver *driver) pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); out_unlock: - up(&core_lists); + mutex_unlock(&core_lists); return 0; } @@ -779,12 +780,12 @@ struct i2c_adapter* i2c_get_adapter(int id) { struct i2c_adapter *adapter; - down(&core_lists); + mutex_lock(&core_lists); adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); if (adapter && !try_module_get(adapter->owner)) adapter = NULL; - up(&core_lists); + mutex_unlock(&core_lists); return adapter; } -- cgit v1.2.3-59-g8ed1b From 99c3adb4d5a2d0727d656f32d5de885581d3feec Mon Sep 17 00:00:00 2001 From: Ben Gardner Date: Wed, 18 Jan 2006 22:41:50 +0100 Subject: [PATCH] i2c: scx200_acb whitespace and comment cleanup scx200_acb: Whitespace and comment cleanup Signed-off-by: Ben Gardner Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/scx200_acb.c | 90 ++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index d3478e084522..f45779b76908 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -1,27 +1,25 @@ -/* linux/drivers/i2c/scx200_acb.c - +/* Copyright (c) 2001,2002 Christer Weinigel National Semiconductor SCx200 ACCESS.bus support - + Based on i2c-keywest.c which is: Copyright (c) 2001 Benjamin Herrenschmidt Copyright (c) 2000 Philip Edelbrock - + 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 @@ -79,8 +77,7 @@ static const char *scx200_acb_state_name[] = { }; /* Physical interface */ -struct scx200_acb_iface -{ +struct scx200_acb_iface { struct scx200_acb_iface *next; struct i2c_adapter adapter; unsigned base; @@ -100,7 +97,7 @@ struct scx200_acb_iface #define ACBSDA (iface->base + 0) #define ACBST (iface->base + 1) #define ACBST_SDAST 0x40 /* SDA Status */ -#define ACBST_BER 0x20 +#define ACBST_BER 0x20 #define ACBST_NEGACK 0x10 /* Negative Acknowledge */ #define ACBST_STASTR 0x08 /* Stall After Start */ #define ACBST_MASTER 0x02 @@ -109,9 +106,9 @@ struct scx200_acb_iface #define ACBCTL1 (iface->base + 3) #define ACBCTL1_STASTRE 0x80 #define ACBCTL1_NMINTE 0x40 -#define ACBCTL1_ACK 0x10 -#define ACBCTL1_STOP 0x02 -#define ACBCTL1_START 0x01 +#define ACBCTL1_ACK 0x10 +#define ACBCTL1_STOP 0x02 +#define ACBCTL1_START 0x01 #define ACBADDR (iface->base + 4) #define ACBCTL2 (iface->base + 5) #define ACBCTL2_ENABLE 0x01 @@ -122,7 +119,7 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) { const char *errmsg; - DBG("state %s, status = 0x%02x\n", + DBG("state %s, status = 0x%02x\n", scx200_acb_state_name[iface->state], status); if (status & ACBST_BER) { @@ -160,10 +157,10 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) case state_repeat_start: outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); /* fallthrough */ - + case state_quick: if (iface->address_byte & 1) { - if (iface->len == 1) + if (iface->len == 1) outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); else outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); @@ -202,17 +199,17 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); break; } - + outb(*iface->ptr++, ACBSDA); --iface->len; - + break; } return; negack: - DBG("negative acknowledge in state %s\n", + DBG("negative acknowledge in state %s\n", scx200_acb_state_name[iface->state]); iface->state = state_idle; @@ -231,7 +228,7 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) iface->needs_reset = 1; } -static void scx200_acb_timeout(struct scx200_acb_iface *iface) +static void scx200_acb_timeout(struct scx200_acb_iface *iface) { dev_err(&iface->adapter.dev, "timeout in state %s\n", scx200_acb_state_name[iface->state]); @@ -264,7 +261,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) static void scx200_acb_reset(struct scx200_acb_iface *iface) { /* Disable the ACCESS.bus device and Configure the SCL - frequency: 16 clock cycles */ + frequency: 16 clock cycles */ outb(0x70, ACBCTL2); /* Polling mode */ outb(0, ACBCTL1); @@ -283,9 +280,9 @@ static void scx200_acb_reset(struct scx200_acb_iface *iface) } static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, - u16 address, unsigned short flags, - char rw, u8 command, int size, - union i2c_smbus_data *data) + u16 address, unsigned short flags, + char rw, u8 command, int size, + union i2c_smbus_data *data) { struct scx200_acb_iface *iface = i2c_get_adapdata(adapter); int len; @@ -295,9 +292,10 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, switch (size) { case I2C_SMBUS_QUICK: - len = 0; - buffer = NULL; - break; + len = 0; + buffer = NULL; + break; + case I2C_SMBUS_BYTE: if (rw == I2C_SMBUS_READ) { len = 1; @@ -306,22 +304,26 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, len = 1; buffer = &command; } - break; + break; + case I2C_SMBUS_BYTE_DATA: - len = 1; - buffer = &data->byte; - break; + len = 1; + buffer = &data->byte; + break; + case I2C_SMBUS_WORD_DATA: len = 2; - cur_word = cpu_to_le16(data->word); - buffer = (u8 *)&cur_word; + cur_word = cpu_to_le16(data->word); + buffer = (u8 *)&cur_word; break; + case I2C_SMBUS_BLOCK_DATA: - len = data->block[0]; - buffer = &data->block[1]; + len = data->block[0]; + buffer = &data->block[1]; break; + default: - return -EINVAL; + return -EINVAL; } DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", @@ -370,7 +372,7 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, up(&iface->sem); if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ) - data->word = le16_to_cpu(cur_word); + data->word = le16_to_cpu(cur_word); #ifdef DEBUG DBG(": transfer done, result: %d", rc); @@ -406,7 +408,7 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface) u8 val; /* Disable the ACCESS.bus device and Configure the SCL - frequency: 16 clock cycles */ + frequency: 16 clock cycles */ outb(0x70, ACBCTL2); if (inb(ACBCTL2) != 0x70) { @@ -459,7 +461,8 @@ static int __init scx200_acb_create(int base, int index) init_MUTEX(&iface->sem); - snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); + snprintf(description, sizeof(description), + "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); if (request_region(base, 8, description) == 0) { dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n", base, base + 8-1); @@ -528,6 +531,7 @@ static int __init scx200_acb_init(void) static void __exit scx200_acb_cleanup(void) { struct scx200_acb_iface *iface; + lock_kernel(); while ((iface = scx200_acb_list) != NULL) { scx200_acb_list = iface->next; @@ -543,11 +547,3 @@ static void __exit scx200_acb_cleanup(void) module_init(scx200_acb_init); module_exit(scx200_acb_cleanup); - -/* - Local variables: - compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" - c-basic-offset: 8 - End: -*/ - -- cgit v1.2.3-59-g8ed1b From ef4d9275e2949976cb43c8bd0c11cb77b9b017e9 Mon Sep 17 00:00:00 2001 From: Ben Gardner Date: Wed, 18 Jan 2006 22:43:10 +0100 Subject: [PATCH] i2c: scx200_acb debug log cleanup scx200_acb: debug log cleanup Signed-off-by: Ben Gardner Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/scx200_acb.c | 42 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index f45779b76908..bfa243d5a8f2 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -45,12 +45,6 @@ static int base[MAX_DEVICES] = { 0x820, 0x840 }; module_param_array(base, int, NULL, 0); MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); -#ifdef DEBUG -#define DBG(x...) printk(KERN_DEBUG NAME ": " x) -#else -#define DBG(x...) -#endif - /* The hardware supports interrupt driven mode too, but I haven't implemented that. */ #define POLLED_MODE 1 @@ -119,8 +113,8 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) { const char *errmsg; - DBG("state %s, status = 0x%02x\n", - scx200_acb_state_name[iface->state], status); + dev_dbg(&iface->adapter.dev, "state %s, status = 0x%02x\n", + scx200_acb_state_name[iface->state], status); if (status & ACBST_BER) { errmsg = "bus error"; @@ -209,8 +203,8 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) return; negack: - DBG("negative acknowledge in state %s\n", - scx200_acb_state_name[iface->state]); + dev_dbg(&iface->adapter.dev, "negative ack in state %s\n", + scx200_acb_state_name[iface->state]); iface->state = state_idle; iface->result = -ENXIO; @@ -326,19 +320,15 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, return -EINVAL; } - DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", - size, address, command, len, rw == I2C_SMBUS_READ); + dev_dbg(&adapter->dev, + "size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", + size, address, command, len, rw); if (!len && rw == I2C_SMBUS_READ) { - dev_warn(&adapter->dev, "zero length read\n"); + dev_dbg(&adapter->dev, "zero length read\n"); return -EINVAL; } - if (len && !buffer) { - dev_warn(&adapter->dev, "nonzero length but no buffer\n"); - return -EFAULT; - } - down(&iface->sem); iface->address_byte = address<<1; @@ -375,7 +365,7 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, data->word = le16_to_cpu(cur_word); #ifdef DEBUG - DBG(": transfer done, result: %d", rc); + dev_dbg(&adapter->dev, "transfer done, result: %d", rc); if (buffer) { int i; printk(" data:"); @@ -412,7 +402,7 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface) outb(0x70, ACBCTL2); if (inb(ACBCTL2) != 0x70) { - DBG("ACBCTL2 readback failed\n"); + pr_debug(NAME ": ACBCTL2 readback failed\n"); return -ENXIO; } @@ -420,7 +410,8 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface) val = inb(ACBCTL1); if (val) { - DBG("disabled, but ACBCTL1=0x%02x\n", val); + pr_debug(NAME ": disabled, but ACBCTL1=0x%02x\n", + val); return -ENXIO; } @@ -430,7 +421,8 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface) val = inb(ACBCTL1); if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) { - DBG("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n", val); + pr_debug(NAME ": enabled, but NMINTE won't be set, " + "ACBCTL1=0x%02x\n", val); return -ENXIO; } @@ -464,7 +456,7 @@ static int __init scx200_acb_create(int base, int index) snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); if (request_region(base, 8, description) == 0) { - dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n", + printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n", base, base + 8-1); rc = -EBUSY; goto errout; @@ -473,14 +465,14 @@ static int __init scx200_acb_create(int base, int index) rc = scx200_acb_probe(iface); if (rc) { - dev_warn(&adapter->dev, "probe failed\n"); + printk(KERN_WARNING NAME ": probe failed\n"); goto errout; } scx200_acb_reset(iface); if (i2c_add_adapter(adapter) < 0) { - dev_err(&adapter->dev, "failed to register\n"); + printk(KERN_ERR NAME ": failed to register\n"); rc = -ENODEV; goto errout; } -- cgit v1.2.3-59-g8ed1b From 9b7b6d3b2b46c5c336a441ed12b504ee192e63b3 Mon Sep 17 00:00:00 2001 From: Ben Gardner Date: Wed, 18 Jan 2006 22:44:04 +0100 Subject: [PATCH] i2c: scx200_acb refactor/simplify code scx200_acb: refactor/simplify code (no functional changes) Signed-off-by: Ben Gardner Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/scx200_acb.c | 73 ++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index bfa243d5a8f2..517a050625f1 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -124,8 +124,17 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) errmsg = "not master"; goto error; } - if (status & ACBST_NEGACK) - goto negack; + if (status & ACBST_NEGACK) { + dev_dbg(&iface->adapter.dev, "negative ack in state %s\n", + scx200_acb_state_name[iface->state]); + + iface->state = state_idle; + iface->result = -ENXIO; + + outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); + outb(ACBST_STASTR | ACBST_NEGACK, ACBST); + return; + } switch (iface->state) { case state_idle: @@ -202,17 +211,6 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) return; - negack: - dev_dbg(&iface->adapter.dev, "negative ack in state %s\n", - scx200_acb_state_name[iface->state]); - - iface->state = state_idle; - iface->result = -ENXIO; - - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - outb(ACBST_STASTR | ACBST_NEGACK, ACBST); - return; - error: dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg, scx200_acb_state_name[iface->state]); @@ -222,20 +220,10 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) iface->needs_reset = 1; } -static void scx200_acb_timeout(struct scx200_acb_iface *iface) -{ - dev_err(&iface->adapter.dev, "timeout in state %s\n", - scx200_acb_state_name[iface->state]); - - iface->state = state_idle; - iface->result = -EIO; - iface->needs_reset = 1; -} - #ifdef POLLED_MODE static void scx200_acb_poll(struct scx200_acb_iface *iface) { - u8 status = 0; + u8 status; unsigned long timeout; timeout = jiffies + POLL_TIMEOUT; @@ -248,7 +236,12 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) msleep(10); } - scx200_acb_timeout(iface); + dev_err(&iface->adapter.dev, "timeout in state %s\n", + scx200_acb_state_name[iface->state]); + + iface->state = state_idle; + iface->result = -EIO; + iface->needs_reset = 1; } #endif /* POLLED_MODE */ @@ -291,13 +284,8 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, break; case I2C_SMBUS_BYTE: - if (rw == I2C_SMBUS_READ) { - len = 1; - buffer = &data->byte; - } else { - len = 1; - buffer = &command; - } + len = 1; + buffer = rw ? &data->byte : &command; break; case I2C_SMBUS_BYTE_DATA: @@ -331,9 +319,7 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, down(&iface->sem); - iface->address_byte = address<<1; - if (rw == I2C_SMBUS_READ) - iface->address_byte |= 1; + iface->address_byte = (address << 1) | rw; iface->command = command; iface->ptr = buffer; iface->len = len; @@ -433,7 +419,7 @@ static int __init scx200_acb_create(int base, int index) { struct scx200_acb_iface *iface; struct i2c_adapter *adapter; - int rc = 0; + int rc; char description[64]; iface = kzalloc(sizeof(*iface), GFP_KERNEL); @@ -459,14 +445,14 @@ static int __init scx200_acb_create(int base, int index) printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n", base, base + 8-1); rc = -EBUSY; - goto errout; + goto errout_free; } iface->base = base; rc = scx200_acb_probe(iface); if (rc) { printk(KERN_WARNING NAME ": probe failed\n"); - goto errout; + goto errout_release; } scx200_acb_reset(iface); @@ -474,7 +460,7 @@ static int __init scx200_acb_create(int base, int index) if (i2c_add_adapter(adapter) < 0) { printk(KERN_ERR NAME ": failed to register\n"); rc = -ENODEV; - goto errout; + goto errout_release; } lock_kernel(); @@ -484,12 +470,11 @@ static int __init scx200_acb_create(int base, int index) return 0; + errout_release: + release_region(iface->base, 8); + errout_free: + kfree(iface); errout: - if (iface) { - if (iface->base) - release_region(iface->base, 8); - kfree(iface); - } return rc; } -- cgit v1.2.3-59-g8ed1b From 8a05940d742174a87427a3fe746712d49d4b8c4b Mon Sep 17 00:00:00 2001 From: Ben Gardner Date: Wed, 18 Jan 2006 22:46:26 +0100 Subject: [PATCH] i2c: scx200_acb remove use of lock_kernel scx200_acb: remove use of lock_kernel() Signed-off-by: Ben Gardner Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/scx200_acb.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 517a050625f1..02150bb25d43 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -378,6 +378,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) { @@ -463,10 +464,10 @@ static int __init scx200_acb_create(int base, int index) goto errout_release; } - lock_kernel(); + down(&scx200_acb_list_mutex); iface->next = scx200_acb_list; scx200_acb_list = iface; - unlock_kernel(); + up(&scx200_acb_list_mutex); return 0; @@ -509,17 +510,17 @@ static void __exit scx200_acb_cleanup(void) { struct scx200_acb_iface *iface; - lock_kernel(); + down(&scx200_acb_list_mutex); while ((iface = scx200_acb_list) != NULL) { scx200_acb_list = iface->next; - unlock_kernel(); + up(&scx200_acb_list_mutex); i2c_del_adapter(&iface->adapter); release_region(iface->base, 8); kfree(iface); - lock_kernel(); + down(&scx200_acb_list_mutex); } - unlock_kernel(); + up(&scx200_acb_list_mutex); } module_init(scx200_acb_init); -- cgit v1.2.3-59-g8ed1b From 16ffc5c99554bc1630bc3939e0950a75b2b1c811 Mon Sep 17 00:00:00 2001 From: Ben Gardner Date: Wed, 18 Jan 2006 22:48:26 +0100 Subject: [PATCH] i2c: scx200_acb add support for the CS5535/CS5536 scx200_acb: Add support for the CS5535/CS5536 Signed-off-by: Ben Gardner Signed-off-by: Jean Delvare --- drivers/i2c/busses/scx200_acb.c | 57 +++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 02150bb25d43..0ae77f84ffe8 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -2,6 +2,7 @@ Copyright (c) 2001,2002 Christer Weinigel National Semiconductor SCx200 ACCESS.bus support + Also supports the AMD CS5535 and AMD CS5536 Based on i2c-keywest.c which is: Copyright (c) 2001 Benjamin Herrenschmidt @@ -31,6 +32,7 @@ #include #include #include +#include #include @@ -416,7 +418,7 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface) return 0; } -static int __init scx200_acb_create(int base, int index) +static int __init scx200_acb_create(const char *text, int base, int index) { struct scx200_acb_iface *iface; struct i2c_adapter *adapter; @@ -432,7 +434,7 @@ static int __init scx200_acb_create(int base, int index) adapter = &iface->adapter; i2c_set_adapdata(adapter, iface); - snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index); + snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index); adapter->owner = THIS_MODULE; adapter->id = I2C_HW_SMBUS_SCX200; adapter->algo = &scx200_acb_algorithm; @@ -440,8 +442,9 @@ static int __init scx200_acb_create(int base, int index) init_MUTEX(&iface->sem); - snprintf(description, sizeof(description), - "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); + snprintf(description, sizeof(description), "%s ACCESS.bus [%s]", + text, adapter->name); + if (request_region(base, 8, description) == 0) { printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n", base, base + 8-1); @@ -485,24 +488,50 @@ static struct pci_device_id scx200[] = { { }, }; +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 */ +}; + +#define MSR_LBAR_SMB 0x5140000B + +static int scx200_add_cs553x(void) +{ + u32 low, hi; + u32 smb_base; + + /* Grab & reserve the SMB I/O range */ + rdmsr(MSR_LBAR_SMB, low, hi); + + /* Check the IO mask and whether SMB is enabled */ + if (hi != 0x0000F001) { + printk(KERN_WARNING NAME ": SMBus not enabled\n"); + return -ENODEV; + } + + /* SMBus IO size is 8 bytes */ + smb_base = low & 0x0000FFF8; + + return scx200_acb_create("CS5535", smb_base, 0); +} + static int __init scx200_acb_init(void) { int i; - int rc; + int rc = -ENODEV; pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); /* Verify that this really is a SCx200 processor */ - if (pci_dev_present(scx200) == 0) - return -ENODEV; + 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 = -ENXIO; - for (i = 0; i < MAX_DEVICES; ++i) { - if (base[i] > 0) - rc = scx200_acb_create(base[i], i); - } - if (scx200_acb_list) - return 0; return rc; } -- cgit v1.2.3-59-g8ed1b From f933ff504f5b3f0f94b98d69d48fc8d3c1e92267 Mon Sep 17 00:00:00 2001 From: Ben Gardner Date: Wed, 18 Jan 2006 22:52:06 +0100 Subject: [PATCH] i2c: scx200_acb fix and speed up the poll loop scx200_acb: Fix and speed up the poll loop Signed-off-by: Ben Gardner Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/scx200_acb.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 0ae77f84ffe8..8e646bdb556c 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -47,10 +47,7 @@ static int base[MAX_DEVICES] = { 0x820, 0x840 }; module_param_array(base, int, NULL, 0); MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); -/* The hardware supports interrupt driven mode too, but I haven't - implemented that. */ -#define POLLED_MODE 1 -#define POLL_TIMEOUT (HZ) +#define POLL_TIMEOUT (HZ/5) enum scx200_acb_state { state_idle, @@ -222,7 +219,6 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) iface->needs_reset = 1; } -#ifdef POLLED_MODE static void scx200_acb_poll(struct scx200_acb_iface *iface) { u8 status; @@ -235,7 +231,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) scx200_acb_machine(iface, status); return; } - msleep(10); + yield(); } dev_err(&iface->adapter.dev, "timeout in state %s\n", @@ -245,7 +241,6 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) iface->result = -EIO; iface->needs_reset = 1; } -#endif /* POLLED_MODE */ static void scx200_acb_reset(struct scx200_acb_iface *iface) { @@ -335,12 +330,8 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, else iface->state = state_address; -#ifdef POLLED_MODE while (iface->state != state_idle) scx200_acb_poll(iface); -#else /* POLLED_MODE */ -#error Interrupt driven mode not implemented -#endif /* POLLED_MODE */ if (iface->needs_reset) scx200_acb_reset(iface); -- cgit v1.2.3-59-g8ed1b From a417bbd33b2ed7a3b2bc78cbadb820079d453328 Mon Sep 17 00:00:00 2001 From: Ben Gardner Date: Wed, 18 Jan 2006 22:53:09 +0100 Subject: [PATCH] i2c: scx200_acb minimal documentation update scx200_acb: Minimal documentation update Signed-off-by: Ben Gardner Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/scx200_acb | 5 +++-- drivers/i2c/busses/Kconfig | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/Documentation/i2c/busses/scx200_acb b/Documentation/i2c/busses/scx200_acb index 08c8cd1df60c..f50e69981ec6 100644 --- a/Documentation/i2c/busses/scx200_acb +++ b/Documentation/i2c/busses/scx200_acb @@ -6,9 +6,10 @@ Module Parameters ----------------- * base: int - Base addresses for the ACCESS.bus controllers + Base addresses for the ACCESS.bus controllers on SCx200 and SC1100 devices Description ----------- -Enable the use of the ACCESS.bus controllers of a SCx200 processor. +Enable the use of the ACCESS.bus controller on the Geode SCx200 and +SC1100 processors and the CS5535 and CS5536 Geode companion devices. diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index ff92735c7c85..1a3bf42351b3 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -389,10 +389,11 @@ config SCx200_I2C_SDA also be specified with a module parameter. config SCx200_ACB - tristate "NatSemi SCx200 ACCESS.bus" + tristate "Geode ACCESS.bus support" depends on I2C && PCI help - Enable the use of the ACCESS.bus controllers of a SCx200 processor. + Enable the use of the ACCESS.bus controllers on the Geode SCx200 and + SC1100 processors and the CS5535 and CS5536 Geode companion devices. If you don't know what to do here, say N. -- cgit v1.2.3-59-g8ed1b From cdf263f1c59cad9b1567e759890b9be044972856 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 22 Jan 2006 12:28:57 +0100 Subject: [PATCH] I2C: fix sx200_acb build on other arches scx200_acb is only useful on a few Geode-based systems, and won't compile on non-x86 systems due to the lack of asm/msr.h, as reported by Andrew Morton. Thus, we should make that driver depend on X86. Signed-off-by: Jean Delvare --- drivers/i2c/busses/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 1a3bf42351b3..7d2705a68e09 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -390,7 +390,7 @@ config SCx200_I2C_SDA config SCx200_ACB tristate "Geode ACCESS.bus support" - depends on I2C && PCI + depends on X86_32 && I2C && PCI help Enable the use of the ACCESS.bus controllers on the Geode SCx200 and SC1100 processors and the CS5535 and CS5536 Geode companion devices. -- cgit v1.2.3-59-g8ed1b From 1f8dae31fe8d7b1dbeaa2110e063d876be91ed60 Mon Sep 17 00:00:00 2001 From: Yuan Mu Date: Wed, 18 Jan 2006 23:11:55 +0100 Subject: [PATCH] hwmon: w83792d use arrays of attributes Use arrays of attributes in the w83792d driver. Signed-off-by: Jim Cromie Signed-off-by: Yuan Mu Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83792d.c | 525 ++++++++++++++++++++++-------------------------- 1 file changed, 241 insertions(+), 284 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index a2f6bb676235..c5b57c7a4a75 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -382,30 +382,40 @@ static ssize_t store_in_##reg (struct device *dev, \ store_in_reg(MIN, min); store_in_reg(MAX, max); -#define sysfs_in_reg(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, store_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, store_in_max, offset); - -sysfs_in_reg(0); -sysfs_in_reg(1); -sysfs_in_reg(2); -sysfs_in_reg(3); -sysfs_in_reg(4); -sysfs_in_reg(5); -sysfs_in_reg(6); -sysfs_in_reg(7); -sysfs_in_reg(8); - -#define device_create_file_in(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_in##offset##_input.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_in##offset##_max.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_in##offset##_min.dev_attr); \ -} while (0) +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), +}; +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), +}; +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), +}; + #define show_fan_reg(reg) \ static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ @@ -486,28 +496,33 @@ store_fan_div(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_fan(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \ - offset); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_div, store_fan_div, offset); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, store_fan_min, offset); - -sysfs_fan(1); -sysfs_fan(2); -sysfs_fan(3); -sysfs_fan(4); -sysfs_fan(5); -sysfs_fan(6); -sysfs_fan(7); - -#define device_create_file_fan(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_input.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_div.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_min.dev_attr); \ -} while (0) +static struct sensor_device_attribute sda_fan_input[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2), + SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3), + SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4), + SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5), + SENSOR_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6), + SENSOR_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7), +}; +static struct sensor_device_attribute sda_fan_min[] = { + SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 1), + SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 2), + SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 3), + SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 4), + SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 5), + SENSOR_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 6), + SENSOR_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 7), +}; +static struct sensor_device_attribute sda_fan_div[] = { + SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 1), + SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 2), + SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 3), + SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 4), + SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 5), + SENSOR_ATTR(fan6_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 6), + SENSOR_ATTR(fan7_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 7), +}; /* read/write the temperature1, includes measured value and limits */ @@ -539,21 +554,6 @@ static ssize_t store_temp1(struct device *dev, struct device_attribute *attr, return count; } - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1, - store_temp1, 1); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, - store_temp1, 2); - -#define device_create_file_temp1(client) \ -do { \ -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_max_hyst.dev_attr); \ -} while (0) - - /* read/write the temperature2-3, includes measured value and limits */ static ssize_t show_temp23(struct device *dev, struct device_attribute *attr, @@ -590,25 +590,23 @@ static ssize_t store_temp23(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_temp23(name,idx) \ -static SENSOR_DEVICE_ATTR_2(name##_input, S_IRUGO, show_temp23, NULL, \ - idx, 0); \ -static SENSOR_DEVICE_ATTR_2(name##_max, S_IRUGO | S_IWUSR, \ - show_temp23, store_temp23, idx, 2); \ -static SENSOR_DEVICE_ATTR_2(name##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp23, store_temp23, idx, 4); - -sysfs_temp23(temp2,0) -sysfs_temp23(temp3,1) +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), +}; -#define device_create_file_temp_add(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_input.dev_attr); \ -device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_max.dev_attr); \ -device_create_file(&client->dev, \ -&sensor_dev_attr_temp##offset##_max_hyst.dev_attr); \ -} while (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, 2), + SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 2), +}; +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, 4), + SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 4), +}; /* get reatime status of all sensors items: voltage, temp, fan */ static ssize_t @@ -620,8 +618,8 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); -#define device_create_file_alarms(client) \ -device_create_file(&client->dev, &dev_attr_alarms); +#define device_create_file_alarms() \ +device_create_file(dev, &dev_attr_alarms); @@ -711,26 +709,19 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_pwm(offset) \ -static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ - show_pwm, store_pwm, offset); \ -static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ - show_pwmenable, store_pwmenable, offset); \ - -sysfs_pwm(1); -sysfs_pwm(2); -sysfs_pwm(3); - - -#define device_create_file_pwm(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_pwm##offset.dev_attr); \ -} while (0) - -#define device_create_file_pwmenable(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_enable.dev_attr); \ -} while (0) +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), +}; +static struct sensor_device_attribute sda_pwm_enable[] = { + SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, + show_pwmenable, store_pwmenable, 1), + SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, + show_pwmenable, store_pwmenable, 2), + SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, + show_pwmenable, store_pwmenable, 3), +}; static ssize_t @@ -764,18 +755,14 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_pwm_mode(offset) \ -static SENSOR_DEVICE_ATTR(pwm##offset##_mode, S_IRUGO | S_IWUSR, \ - show_pwm_mode, store_pwm_mode, offset); - -sysfs_pwm_mode(1); -sysfs_pwm_mode(2); -sysfs_pwm_mode(3); - -#define device_create_file_pwm_mode(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_mode.dev_attr); \ -} while (0) +static struct sensor_device_attribute sda_pwm_mode[] = { + SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, + show_pwm_mode, store_pwm_mode, 1), + SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, + show_pwm_mode, store_pwm_mode, 2), + SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, + show_pwm_mode, store_pwm_mode, 3), +}; static ssize_t @@ -788,9 +775,9 @@ show_regs_chassis(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); -#define device_create_file_chassis(client) \ +#define device_create_file_chassis() \ do { \ -device_create_file(&client->dev, &dev_attr_chassis); \ +device_create_file(dev, &dev_attr_chassis); \ } while (0) @@ -824,9 +811,9 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, show_chassis_clear, store_chassis_clear); -#define device_create_file_chassis_clear(client) \ +#define device_create_file_chassis_clear() \ do { \ -device_create_file(&client->dev, &dev_attr_chassis_clear); \ +device_create_file(dev, &dev_attr_chassis_clear); \ } while (0) @@ -864,20 +851,14 @@ store_thermal_cruise(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_thermal_cruise(offset) \ -static SENSOR_DEVICE_ATTR(thermal_cruise##offset, S_IRUGO | S_IWUSR, \ - show_thermal_cruise, store_thermal_cruise, offset); - -sysfs_thermal_cruise(1); -sysfs_thermal_cruise(2); -sysfs_thermal_cruise(3); - -#define device_create_file_thermal_cruise(client, offset) \ -do { \ -device_create_file(&client->dev, \ -&sensor_dev_attr_thermal_cruise##offset.dev_attr); \ -} while (0) - +static struct sensor_device_attribute sda_thermal_cruise[] = { + SENSOR_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO, + show_thermal_cruise, store_thermal_cruise, 1), + SENSOR_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO, + show_thermal_cruise, store_thermal_cruise, 2), + SENSOR_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO, + show_thermal_cruise, store_thermal_cruise, 3), +}; /* For Smart Fan I/Thermal Cruise and Smart Fan II */ static ssize_t @@ -916,19 +897,14 @@ store_tolerance(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_tolerance(offset) \ -static SENSOR_DEVICE_ATTR(tolerance##offset, S_IRUGO | S_IWUSR, \ - show_tolerance, store_tolerance, offset); - -sysfs_tolerance(1); -sysfs_tolerance(2); -sysfs_tolerance(3); - -#define device_create_file_tolerance(client, offset) \ -do { \ -device_create_file(&client->dev, &sensor_dev_attr_tolerance##offset.dev_attr); \ -} while (0) - +static struct sensor_device_attribute sda_tolerance[] = { + SENSOR_ATTR(tolerance1, S_IWUSR | S_IRUGO, + show_tolerance, store_tolerance, 1), + SENSOR_ATTR(tolerance2, S_IWUSR | S_IRUGO, + show_tolerance, store_tolerance, 2), + SENSOR_ATTR(tolerance3, S_IWUSR | S_IRUGO, + show_tolerance, store_tolerance, 3), +}; /* For Smart Fan II */ static ssize_t @@ -964,28 +940,34 @@ store_sf2_point(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_sf2_point(offset, index) \ -static SENSOR_DEVICE_ATTR_2(sf2_point##offset##_fan##index, S_IRUGO | S_IWUSR, \ - show_sf2_point, store_sf2_point, offset, index); - -sysfs_sf2_point(1, 1); /* Fan1 */ -sysfs_sf2_point(2, 1); /* Fan1 */ -sysfs_sf2_point(3, 1); /* Fan1 */ -sysfs_sf2_point(4, 1); /* Fan1 */ -sysfs_sf2_point(1, 2); /* Fan2 */ -sysfs_sf2_point(2, 2); /* Fan2 */ -sysfs_sf2_point(3, 2); /* Fan2 */ -sysfs_sf2_point(4, 2); /* Fan2 */ -sysfs_sf2_point(1, 3); /* Fan3 */ -sysfs_sf2_point(2, 3); /* Fan3 */ -sysfs_sf2_point(3, 3); /* Fan3 */ -sysfs_sf2_point(4, 3); /* Fan3 */ - -#define device_create_file_sf2_point(client, offset, index) \ -do { \ -device_create_file(&client->dev, \ -&sensor_dev_attr_sf2_point##offset##_fan##index.dev_attr); \ -} while (0) +static struct sensor_device_attribute_2 sda_sf2_point[] = { + SENSOR_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 1, 1), + SENSOR_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 2, 1), + SENSOR_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 3, 1), + SENSOR_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 4, 1), + + SENSOR_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 1, 2), + SENSOR_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 2, 2), + SENSOR_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 3, 2), + SENSOR_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 4, 2), + + SENSOR_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 1, 3), + SENSOR_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 2, 3), + SENSOR_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 3, 3), + SENSOR_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR, + show_sf2_point, store_sf2_point, 4, 3), +}; static ssize_t @@ -1026,26 +1008,28 @@ store_sf2_level(struct device *dev, struct device_attribute *attr, return count; } -#define sysfs_sf2_level(offset, index) \ -static SENSOR_DEVICE_ATTR_2(sf2_level##offset##_fan##index, S_IRUGO | S_IWUSR, \ - show_sf2_level, store_sf2_level, offset, index); - -sysfs_sf2_level(1, 1); /* Fan1 */ -sysfs_sf2_level(2, 1); /* Fan1 */ -sysfs_sf2_level(3, 1); /* Fan1 */ -sysfs_sf2_level(1, 2); /* Fan2 */ -sysfs_sf2_level(2, 2); /* Fan2 */ -sysfs_sf2_level(3, 2); /* Fan2 */ -sysfs_sf2_level(1, 3); /* Fan3 */ -sysfs_sf2_level(2, 3); /* Fan3 */ -sysfs_sf2_level(3, 3); /* Fan3 */ - -#define device_create_file_sf2_level(client, offset, index) \ -do { \ -device_create_file(&client->dev, \ -&sensor_dev_attr_sf2_level##offset##_fan##index.dev_attr); \ -} while (0) - +static struct sensor_device_attribute_2 sda_sf2_level[] = { + SENSOR_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 1, 1), + SENSOR_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 2, 1), + SENSOR_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 3, 1), + + SENSOR_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 1, 2), + SENSOR_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 2, 2), + SENSOR_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 3, 2), + + SENSOR_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 1, 3), + SENSOR_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 2, 3), + SENSOR_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR, + show_sf2_level, store_sf2_level, 3, 3), +}; /* This function is called when: * w83792d_driver is inserted (when this module is loaded), for each @@ -1147,12 +1131,19 @@ ERROR_SC_0: return err; } +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_div[i].dev_attr); + device_create_file(dev, &sda_fan_min[i].dev_attr); +} static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind) { int i = 0, val1 = 0, val2; - struct i2c_client *new_client; + struct i2c_client *client; + struct device *dev; struct w83792d_data *data; int err = 0; const char *client_name = ""; @@ -1170,12 +1161,13 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) goto ERROR0; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &w83792d_driver; - new_client->flags = 0; + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &w83792d_driver; + client->flags = 0; /* Now, we do the remaining detection. */ @@ -1184,13 +1176,12 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) force_*=... parameter, and the Winbond will be reset to the right bank. */ if (kind < 0) { - if (w83792d_read_value(new_client, W83792D_REG_CONFIG) & 0x80) { - dev_warn(&new_client->dev, "Detection failed at step " - "3\n"); + if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) { + dev_warn(dev, "Detection failed at step 3\n"); goto ERROR1; } - val1 = w83792d_read_value(new_client, W83792D_REG_BANK); - val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN); + val1 = w83792d_read_value(client, W83792D_REG_BANK); + val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); /* Check for Winbond ID if in bank 0 */ if (!(val1 & 0x07)) { /* is Bank0 */ if (((!(val1 & 0x80)) && (val2 != 0xa3)) || @@ -1200,34 +1191,33 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) } /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR should match */ - if (w83792d_read_value(new_client, + if (w83792d_read_value(client, W83792D_REG_I2C_ADDR) != address) { - dev_warn(&new_client->dev, "Detection failed " - "at step 5\n"); + dev_warn(dev, "Detection failed at step 5\n"); goto ERROR1; } } /* We have either had a force parameter, or we have already detected the Winbond. Put it now into bank 0 and Vendor ID High Byte */ - w83792d_write_value(new_client, + w83792d_write_value(client, W83792D_REG_BANK, - (w83792d_read_value(new_client, + (w83792d_read_value(client, W83792D_REG_BANK) & 0x78) | 0x80); /* Determine the chip type. */ if (kind <= 0) { /* get vendor ID */ - val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN); + val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); if (val2 != 0x5c) { /* the vendor is NOT Winbond */ goto ERROR1; } - val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID); + val1 = w83792d_read_value(client, W83792D_REG_WCHIPID); if (val1 == 0x7a) { kind = w83792d; } else { if (kind == 0) - dev_warn(&new_client->dev, + dev_warn(dev, "w83792d: Ignoring 'force' parameter for" " unknown chip at adapter %d, address" " 0x%02x\n", i2c_adapter_id(adapter), @@ -1239,120 +1229,87 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) if (kind == w83792d) { client_name = "w83792d"; } else { - dev_err(&new_client->dev, "w83792d: Internal error: unknown" + dev_err(dev, "w83792d: Internal error: unknown" " kind (%d)?!?", kind); goto ERROR1; } /* Fill in the remaining client fields and put into the global list */ - strlcpy(new_client->name, client_name, I2C_NAME_SIZE); + strlcpy(client->name, client_name, I2C_NAME_SIZE); data->type = kind; data->valid = 0; init_MUTEX(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto ERROR1; if ((err = w83792d_detect_subclients(adapter, address, - kind, new_client))) + kind, client))) goto ERROR2; /* Initialize the chip */ - w83792d_init_client(new_client); + w83792d_init_client(client); /* A few vars need to be filled upon startup */ for (i = 0; i < 7; i++) { - data->fan_min[i] = w83792d_read_value(new_client, + data->fan_min[i] = w83792d_read_value(client, W83792D_REG_FAN_MIN[i]); } /* Register sysfs hooks */ - data->class_dev = hwmon_device_register(&new_client->dev); + data->class_dev = hwmon_device_register(dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto ERROR3; } - device_create_file_in(new_client, 0); - device_create_file_in(new_client, 1); - device_create_file_in(new_client, 2); - device_create_file_in(new_client, 3); - device_create_file_in(new_client, 4); - device_create_file_in(new_client, 5); - device_create_file_in(new_client, 6); - device_create_file_in(new_client, 7); - device_create_file_in(new_client, 8); - - device_create_file_fan(new_client, 1); - device_create_file_fan(new_client, 2); - device_create_file_fan(new_client, 3); + for (i = 0; i < 9; i++) { + device_create_file(dev, &sda_in_input[i].dev_attr); + device_create_file(dev, &sda_in_max[i].dev_attr); + device_create_file(dev, &sda_in_min[i].dev_attr); + } + for (i = 0; i < 3; i++) + device_create_file_fan(dev, i); /* Read GPIO enable register to check if pins for fan 4,5 are used as GPIO */ - val1 = w83792d_read_value(new_client, W83792D_REG_GPIO_EN); + val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN); if (!(val1 & 0x40)) - device_create_file_fan(new_client, 4); + device_create_file_fan(dev, 3); if (!(val1 & 0x20)) - device_create_file_fan(new_client, 5); + device_create_file_fan(dev, 4); - val1 = w83792d_read_value(new_client, W83792D_REG_PIN); + val1 = w83792d_read_value(client, W83792D_REG_PIN); if (val1 & 0x40) - device_create_file_fan(new_client, 6); + device_create_file_fan(dev, 5); if (val1 & 0x04) - device_create_file_fan(new_client, 7); - - device_create_file_temp1(new_client); /* Temp1 */ - device_create_file_temp_add(new_client, 2); /* Temp2 */ - device_create_file_temp_add(new_client, 3); /* Temp3 */ - - device_create_file_alarms(new_client); - - device_create_file_pwm(new_client, 1); - device_create_file_pwm(new_client, 2); - device_create_file_pwm(new_client, 3); - - device_create_file_pwmenable(new_client, 1); - device_create_file_pwmenable(new_client, 2); - device_create_file_pwmenable(new_client, 3); - - device_create_file_pwm_mode(new_client, 1); - device_create_file_pwm_mode(new_client, 2); - device_create_file_pwm_mode(new_client, 3); - - device_create_file_chassis(new_client); - device_create_file_chassis_clear(new_client); - - device_create_file_thermal_cruise(new_client, 1); - device_create_file_thermal_cruise(new_client, 2); - device_create_file_thermal_cruise(new_client, 3); - - device_create_file_tolerance(new_client, 1); - device_create_file_tolerance(new_client, 2); - device_create_file_tolerance(new_client, 3); - - device_create_file_sf2_point(new_client, 1, 1); /* Fan1 */ - device_create_file_sf2_point(new_client, 2, 1); /* Fan1 */ - device_create_file_sf2_point(new_client, 3, 1); /* Fan1 */ - device_create_file_sf2_point(new_client, 4, 1); /* Fan1 */ - device_create_file_sf2_point(new_client, 1, 2); /* Fan2 */ - device_create_file_sf2_point(new_client, 2, 2); /* Fan2 */ - device_create_file_sf2_point(new_client, 3, 2); /* Fan2 */ - device_create_file_sf2_point(new_client, 4, 2); /* Fan2 */ - device_create_file_sf2_point(new_client, 1, 3); /* Fan3 */ - device_create_file_sf2_point(new_client, 2, 3); /* Fan3 */ - device_create_file_sf2_point(new_client, 3, 3); /* Fan3 */ - device_create_file_sf2_point(new_client, 4, 3); /* Fan3 */ - - device_create_file_sf2_level(new_client, 1, 1); /* Fan1 */ - device_create_file_sf2_level(new_client, 2, 1); /* Fan1 */ - device_create_file_sf2_level(new_client, 3, 1); /* Fan1 */ - device_create_file_sf2_level(new_client, 1, 2); /* Fan2 */ - device_create_file_sf2_level(new_client, 2, 2); /* Fan2 */ - device_create_file_sf2_level(new_client, 3, 2); /* Fan2 */ - device_create_file_sf2_level(new_client, 1, 3); /* Fan3 */ - device_create_file_sf2_level(new_client, 2, 3); /* Fan3 */ - device_create_file_sf2_level(new_client, 3, 3); /* Fan3 */ + device_create_file_fan(dev, 6); + + for (i = 0; i < 3; 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, &sda_thermal_cruise[i].dev_attr); + device_create_file(dev, &sda_tolerance[i].dev_attr); + } + + device_create_file_alarms(); + + for (i = 0; i < ARRAY_SIZE(sda_pwm); i++) { + device_create_file(dev, &sda_pwm[i].dev_attr); + device_create_file(dev, &sda_pwm_enable[i].dev_attr); + device_create_file(dev, &sda_pwm_mode[i].dev_attr); + } + + device_create_file_chassis(); + device_create_file_chassis_clear(); + + for (i = 0; i < ARRAY_SIZE(sda_sf2_point); i++) + device_create_file(dev, &sda_sf2_point[i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(sda_sf2_level); i++) + device_create_file(dev, &sda_sf2_level[i].dev_attr); return 0; @@ -1366,7 +1323,7 @@ ERROR3: kfree(data->lm75[1]); } ERROR2: - i2c_detach_client(new_client); + i2c_detach_client(client); ERROR1: kfree(data); ERROR0: -- cgit v1.2.3-59-g8ed1b From 93766d2de6a3f7eead3fda57fd4638b90d6691fa Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 18 Jan 2006 23:13:09 +0100 Subject: [PATCH] hwmon: w83792d drop useless macros Drop 3 useless macros in the w83792d hardware monitoring driver. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83792d.c | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index c5b57c7a4a75..2e86e188b27a 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -618,10 +618,6 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); -#define device_create_file_alarms() \ -device_create_file(dev, &dev_attr_alarms); - - static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, @@ -775,12 +771,6 @@ show_regs_chassis(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); -#define device_create_file_chassis() \ -do { \ -device_create_file(dev, &dev_attr_chassis); \ -} while (0) - - static ssize_t show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) { @@ -811,13 +801,6 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, show_chassis_clear, store_chassis_clear); -#define device_create_file_chassis_clear() \ -do { \ -device_create_file(dev, &dev_attr_chassis_clear); \ -} while (0) - - - /* For Smart Fan I / Thermal Cruise */ static ssize_t show_thermal_cruise(struct device *dev, struct device_attribute *attr, @@ -1294,16 +1277,15 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) device_create_file(dev, &sda_tolerance[i].dev_attr); } - device_create_file_alarms(); - for (i = 0; i < ARRAY_SIZE(sda_pwm); i++) { device_create_file(dev, &sda_pwm[i].dev_attr); device_create_file(dev, &sda_pwm_enable[i].dev_attr); device_create_file(dev, &sda_pwm_mode[i].dev_attr); } - device_create_file_chassis(); - device_create_file_chassis_clear(); + device_create_file(dev, &dev_attr_alarms); + device_create_file(dev, &dev_attr_chassis); + device_create_file(dev, &dev_attr_chassis_clear); for (i = 0; i < ARRAY_SIZE(sda_sf2_point); i++) device_create_file(dev, &sda_sf2_point[i].dev_attr); -- cgit v1.2.3-59-g8ed1b From 7656032b904b936eca65a41afa1f2b3603195657 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 18 Jan 2006 23:14:55 +0100 Subject: [PATCH] i2c: Speed up block transfers Speed up i2c_smbus_write_block_data and i2c_smbus_read_i2c_block_data a bit by using memcpy instead of an explicit loop. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/i2c-core.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 97334433e534..2b0c555aa011 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -920,12 +920,11 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values) { union i2c_smbus_data data; - int i; + if (length > I2C_SMBUS_BLOCK_MAX) length = I2C_SMBUS_BLOCK_MAX; - for (i = 1; i <= length; i++) - data.block[i] = values[i-1]; data.block[0] = length; + memcpy(&data.block[1], values, length); return i2c_smbus_xfer(client->adapter,client->addr,client->flags, I2C_SMBUS_WRITE,command, I2C_SMBUS_BLOCK_DATA,&data); @@ -935,16 +934,14 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) { union i2c_smbus_data data; - int i; + if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, I2C_SMBUS_READ,command, I2C_SMBUS_I2C_BLOCK_DATA,&data)) return -1; - else { - for (i = 1; i <= data.block[0]; i++) - values[i-1] = data.block[i]; - return data.block[0]; - } + + memcpy(values, &data.block[1], data.block[0]); + return data.block[0]; } s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, -- cgit v1.2.3-59-g8ed1b From 5c085d369c2c4f18942ec8951466e186366d5c78 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 18 Jan 2006 23:16:04 +0100 Subject: [PATCH] i2c: Semaphore to mutex conversions, part 2 semaphore to mutex conversion. the conversion was generated via scripts, and the result was validated automatically via a script as well. build tested. Signed-off-by: Ingo Molnar Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-amd756-s4882.c | 13 +++++----- drivers/i2c/busses/i2c-isa.c | 2 +- drivers/i2c/chips/eeprom.c | 9 +++---- drivers/i2c/chips/max6875.c | 10 ++++---- drivers/i2c/chips/pcf8591.c | 13 +++++----- drivers/i2c/chips/tps65010.c | 45 ++++++++++++++++++----------------- drivers/i2c/i2c-core.c | 34 +++++++++++++------------- include/linux/i2c.h | 6 ++--- 8 files changed, 68 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index 56c7d987590f..f7b4cb4e9c75 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c @@ -38,6 +38,7 @@ #include #include #include +#include extern struct i2c_adapter amd756_smbus; @@ -45,7 +46,7 @@ static struct i2c_adapter *s4882_adapter; static struct i2c_algorithm *s4882_algo; /* Wrapper access functions for multiplexed SMBus */ -static struct semaphore amd756_lock; +static struct mutex amd756_lock; static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, @@ -59,12 +60,12 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, || addr == 0x18) return -1; - down(&amd756_lock); + mutex_lock(&amd756_lock); error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, command, size, data); - up(&amd756_lock); + mutex_unlock(&amd756_lock); return error; } @@ -87,7 +88,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) return -1; - down(&amd756_lock); + mutex_lock(&amd756_lock); if (last_channels != channels) { union i2c_smbus_data mplxdata; @@ -105,7 +106,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, command, size, data); UNLOCK: - up(&amd756_lock); + mutex_unlock(&amd756_lock); return error; } @@ -166,7 +167,7 @@ static int __init amd756_s4882_init(void) } printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); - init_MUTEX(&amd756_lock); + mutex_init(&amd756_lock); /* Define the 5 virtual adapters and algorithms structures */ if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter), diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c index 4344ae6b1fcb..c3e1d3e888d7 100644 --- a/drivers/i2c/busses/i2c-isa.c +++ b/drivers/i2c/busses/i2c-isa.c @@ -125,7 +125,7 @@ int i2c_isa_del_driver(struct i2c_driver *driver) static int __init i2c_isa_init(void) { - init_MUTEX(&isa_adapter.clist_lock); + mutex_init(&isa_adapter.clist_lock); INIT_LIST_HEAD(&isa_adapter.clients); isa_adapter.nr = ANY_I2C_ISA_BUS; diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 41116b7947f6..13c108269a6d 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -33,6 +33,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, @@ -54,7 +55,7 @@ enum eeprom_nature { /* Each client has this additional data */ struct eeprom_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; u8 valid; /* bitfield, bit!=0 if slice is valid */ unsigned long last_updated[8]; /* In jiffies, 8 slices */ u8 data[EEPROM_SIZE]; /* Register values */ @@ -81,7 +82,7 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice) struct eeprom_data *data = i2c_get_clientdata(client); int i, j; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (!(data->valid & (1 << slice)) || time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { @@ -107,7 +108,7 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice) data->valid |= (1 << slice); } exit: - up(&data->update_lock); + mutex_unlock(&data->update_lock); } static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count) @@ -187,7 +188,7 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields */ strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); data->nature = UNKNOWN; /* Tell the I2C layer a new client has arrived */ diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c index 6d3ff584155e..88d2ddee4490 100644 --- a/drivers/i2c/chips/max6875.c +++ b/drivers/i2c/chips/max6875.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include /* Do not scan - the MAX6875 access method will write to some EEPROM chips */ static unsigned short normal_i2c[] = {I2C_CLIENT_END}; @@ -54,7 +54,7 @@ I2C_CLIENT_INSMOD_1(max6875); /* Each client has this additional data */ struct max6875_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; u32 valid; u8 data[USER_EEPROM_SIZE]; @@ -83,7 +83,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice) if (slice >= USER_EEPROM_SLICES) return; - down(&data->update_lock); + mutex_lock(&data->update_lock); buf = &data->data[slice << SLICE_BITS]; @@ -122,7 +122,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice) data->valid |= (1 << slice); } exit_up: - up(&data->update_lock); + mutex_unlock(&data->update_lock); } static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, @@ -196,7 +196,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) real_client->driver = &max6875_driver; real_client->flags = 0; strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Init fake client data */ /* set the client data to the i2c_client so that it will get freed */ diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c index 36cff09c678d..925a6b371fd2 100644 --- a/drivers/i2c/chips/pcf8591.c +++ b/drivers/i2c/chips/pcf8591.c @@ -24,6 +24,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, @@ -74,7 +75,7 @@ MODULE_PARM_DESC(input_mode, struct pcf8591_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; u8 control; u8 aout; @@ -144,13 +145,13 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr struct pcf8591_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (val) data->control |= PCF8591_CONTROL_AOEF; else data->control &= ~PCF8591_CONTROL_AOEF; i2c_smbus_write_byte(client, data->control); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -200,7 +201,7 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields and put it into the global list */ strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -265,7 +266,7 @@ static int pcf8591_read_channel(struct device *dev, int channel) struct i2c_client *client = to_i2c_client(dev); struct pcf8591_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) { data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK) @@ -278,7 +279,7 @@ static int pcf8591_read_channel(struct device *dev, int channel) } value = i2c_smbus_read_byte(client); - up(&data->update_lock); + mutex_unlock(&data->update_lock); if ((channel == 2 && input_mode == 2) || (channel != 3 && (input_mode == 1 || input_mode == 3))) diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c index 1af3dfbb8086..179b1e022d80 100644 --- a/drivers/i2c/chips/tps65010.c +++ b/drivers/i2c/chips/tps65010.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -81,7 +82,7 @@ enum tps_model { struct tps65010 { struct i2c_client client; - struct semaphore lock; + struct mutex lock; int irq; struct work_struct work; struct dentry *file; @@ -218,7 +219,7 @@ static int dbg_show(struct seq_file *s, void *_) seq_printf(s, "driver %s\nversion %s\nchip %s\n\n", DRIVER_NAME, DRIVER_VERSION, chip); - down(&tps->lock); + mutex_lock(&tps->lock); /* FIXME how can we tell whether a battery is present? * likely involves a charge gauging chip (like BQ26501). @@ -300,7 +301,7 @@ static int dbg_show(struct seq_file *s, void *_) (v2 & (1 << (4 + i))) ? "rising" : "falling"); } - up(&tps->lock); + mutex_unlock(&tps->lock); return 0; } @@ -416,7 +417,7 @@ static void tps65010_work(void *_tps) { struct tps65010 *tps = _tps; - down(&tps->lock); + mutex_lock(&tps->lock); tps65010_interrupt(tps); @@ -444,7 +445,7 @@ static void tps65010_work(void *_tps) if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags)) enable_irq(tps->irq); - up(&tps->lock); + mutex_unlock(&tps->lock); } static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs) @@ -505,7 +506,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) if (!tps) return 0; - init_MUTEX(&tps->lock); + mutex_init(&tps->lock); INIT_WORK(&tps->work, tps65010_work, tps); tps->irq = -1; tps->client.addr = address; @@ -695,7 +696,7 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value) if ((gpio < GPIO1) || (gpio > GPIO4)) return -EINVAL; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO); @@ -720,7 +721,7 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value) gpio, value ? "high" : "low", i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } EXPORT_SYMBOL(tps65010_set_gpio_out_value); @@ -745,7 +746,7 @@ int tps65010_set_led(unsigned led, unsigned mode) led = LED2; } - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led, i2c_smbus_read_byte_data(&the_tps->client, @@ -771,7 +772,7 @@ int tps65010_set_led(unsigned led, unsigned mode) default: printk(KERN_ERR "%s: Wrong mode parameter for set_led()\n", DRIVER_NAME); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return -EINVAL; } @@ -781,7 +782,7 @@ int tps65010_set_led(unsigned led, unsigned mode) if (status != 0) { printk(KERN_ERR "%s: Failed to write led%i_on register\n", DRIVER_NAME, led); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -794,7 +795,7 @@ int tps65010_set_led(unsigned led, unsigned mode) if (status != 0) { printk(KERN_ERR "%s: Failed to write led%i_per register\n", DRIVER_NAME, led); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -802,7 +803,7 @@ int tps65010_set_led(unsigned led, unsigned mode) i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_PER + offs)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -820,7 +821,7 @@ int tps65010_set_vib(unsigned value) if (!the_tps) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); vdcdc2 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC2); vdcdc2 &= ~(1 << 1); @@ -831,7 +832,7 @@ int tps65010_set_vib(unsigned value) pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off"); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } EXPORT_SYMBOL(tps65010_set_vib); @@ -848,7 +849,7 @@ int tps65010_set_low_pwr(unsigned mode) if (!the_tps) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME, mode ? "enable" : "disable", @@ -876,7 +877,7 @@ int tps65010_set_low_pwr(unsigned mode) pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -894,7 +895,7 @@ int tps65010_config_vregs1(unsigned value) if (!the_tps) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); @@ -909,7 +910,7 @@ int tps65010_config_vregs1(unsigned value) pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -931,7 +932,7 @@ int tps65013_set_low_pwr(unsigned mode) if (!the_tps || the_tps->por) return -ENODEV; - down(&the_tps->lock); + mutex_lock(&the_tps->lock); pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n", DRIVER_NAME, @@ -959,7 +960,7 @@ int tps65013_set_low_pwr(unsigned mode) if (status != 0) { printk(KERN_ERR "%s: Failed to write chconfig register\n", DRIVER_NAME); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } @@ -977,7 +978,7 @@ int tps65013_set_low_pwr(unsigned mode) pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); - up(&the_tps->lock); + mutex_unlock(&the_tps->lock); return status; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 2b0c555aa011..975cb647da10 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -169,8 +169,8 @@ int i2c_add_adapter(struct i2c_adapter *adap) } adap->nr = id & MAX_ID_MASK; - init_MUTEX(&adap->bus_lock); - init_MUTEX(&adap->clist_lock); + mutex_init(&adap->bus_lock); + mutex_init(&adap->clist_lock); list_add_tail(&adap->list,&adapters); INIT_LIST_HEAD(&adap->clients); @@ -385,9 +385,9 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr) { int rval; - down(&adapter->clist_lock); + mutex_lock(&adapter->clist_lock); rval = __i2c_check_addr(adapter, addr); - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); return rval; } @@ -396,13 +396,13 @@ int i2c_attach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - down(&adapter->clist_lock); + mutex_lock(&adapter->clist_lock); if (__i2c_check_addr(client->adapter, client->addr)) { - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); return -EBUSY; } list_add_tail(&client->list,&adapter->clients); - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); if (adapter->client_register) { if (adapter->client_register(client)) { @@ -451,12 +451,12 @@ int i2c_detach_client(struct i2c_client *client) } } - down(&adapter->clist_lock); + mutex_lock(&adapter->clist_lock); list_del(&client->list); init_completion(&client->released); device_remove_file(&client->dev, &dev_attr_client_name); device_unregister(&client->dev); - up(&adapter->clist_lock); + mutex_unlock(&adapter->clist_lock); wait_for_completion(&client->released); out: @@ -514,19 +514,19 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) struct list_head *item; struct i2c_client *client; - down(&adap->clist_lock); + mutex_lock(&adap->clist_lock); list_for_each(item,&adap->clients) { client = list_entry(item, struct i2c_client, list); if (!try_module_get(client->driver->driver.owner)) continue; if (NULL != client->driver->command) { - up(&adap->clist_lock); + mutex_unlock(&adap->clist_lock); client->driver->command(client,cmd,arg); - down(&adap->clist_lock); + mutex_lock(&adap->clist_lock); } module_put(client->driver->driver.owner); } - up(&adap->clist_lock); + mutex_unlock(&adap->clist_lock); } static int __init i2c_init(void) @@ -570,9 +570,9 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) } #endif - down(&adap->bus_lock); + mutex_lock(&adap->bus_lock); ret = adap->algo->master_xfer(adap,msgs,num); - up(&adap->bus_lock); + mutex_unlock(&adap->bus_lock); return ret; } else { @@ -1116,10 +1116,10 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, flags &= I2C_M_TEN | I2C_CLIENT_PEC; if (adapter->algo->smbus_xfer) { - down(&adapter->bus_lock); + mutex_lock(&adapter->bus_lock); res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, command,size,data); - up(&adapter->bus_lock); + mutex_unlock(&adapter->bus_lock); } else res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, command,size,data); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 63f1d63cc1d8..1635ee25918f 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -32,7 +32,7 @@ #include #include /* for struct device */ #include /* for completion */ -#include +#include /* --- For i2c-isa ---------------------------------------------------- */ @@ -225,8 +225,8 @@ struct i2c_adapter { int (*client_unregister)(struct i2c_client *); /* data fields that are valid for all devices */ - struct semaphore bus_lock; - struct semaphore clist_lock; + struct mutex bus_lock; + struct mutex clist_lock; int timeout; int retries; -- cgit v1.2.3-59-g8ed1b From 3fb9a65529615944138d527b70174840c95c637a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 18 Jan 2006 23:17:01 +0100 Subject: [PATCH] i2c: Semaphore to mutex conversions, part 3 Cleanup after the semaphores to mutexes conversions in the i2c subsystem. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-ali1535.c | 1 - drivers/i2c/busses/i2c-pxa.c | 2 +- drivers/i2c/busses/scx200_acb.c | 9 +++++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 26cf891762b8..115a7312948e 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -64,7 +64,6 @@ #include #include #include -#include /* ALI1535 SMBus address offsets */ diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 7579f4b256a8..5155010b455e 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -647,7 +647,7 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c) } /* - * We are protected by the adapter bus semaphore. + * We are protected by the adapter bus mutex. */ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) { diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 8e646bdb556c..8bd305e47f0d 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -74,7 +75,7 @@ struct scx200_acb_iface { struct scx200_acb_iface *next; struct i2c_adapter adapter; unsigned base; - struct semaphore sem; + struct mutex mutex; /* State machine data */ enum scx200_acb_state state; @@ -314,7 +315,7 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, return -EINVAL; } - down(&iface->sem); + mutex_lock(&iface->mutex); iface->address_byte = (address << 1) | rw; iface->command = command; @@ -338,7 +339,7 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, rc = iface->result; - up(&iface->sem); + mutex_unlock(&iface->mutex); if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ) data->word = le16_to_cpu(cur_word); @@ -431,7 +432,7 @@ static int __init scx200_acb_create(const char *text, int base, int index) adapter->algo = &scx200_acb_algorithm; adapter->class = I2C_CLASS_HWMON; - init_MUTEX(&iface->sem); + mutex_init(&iface->mutex); snprintf(description, sizeof(description), "%s ACCESS.bus [%s]", text, adapter->name); -- cgit v1.2.3-59-g8ed1b From 9a61bf6300533d3b64d7ff29adfec00e596de67d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 18 Jan 2006 23:19:26 +0100 Subject: [PATCH] hwmon: Semaphore to mutex conversions convert drivers/hwmon/*.c semaphore use to mutexes. the conversion was generated via scripts, and the result was validated automatically via a script as well. all affected hwmon drivers were build-tested. Signed-off-by: Ingo Molnar Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/adm1021.c | 13 +++---- drivers/hwmon/adm1025.c | 25 ++++++------- drivers/hwmon/adm1026.c | 87 +++++++++++++++++++++++----------------------- drivers/hwmon/adm1031.c | 49 +++++++++++++------------- drivers/hwmon/adm9240.c | 29 ++++++++-------- drivers/hwmon/asb100.c | 45 ++++++++++++------------ drivers/hwmon/atxp1.c | 9 ++--- drivers/hwmon/ds1621.c | 13 +++---- drivers/hwmon/fscher.c | 41 +++++++++++----------- drivers/hwmon/fscpos.c | 29 ++++++++-------- drivers/hwmon/gl518sm.c | 25 ++++++------- drivers/hwmon/gl520sm.c | 45 ++++++++++++------------ drivers/hwmon/hdaps.c | 37 ++++++++++---------- drivers/hwmon/it87.c | 61 ++++++++++++++++---------------- drivers/hwmon/lm63.c | 29 ++++++++-------- drivers/hwmon/lm75.c | 13 +++---- drivers/hwmon/lm77.c | 21 +++++------ drivers/hwmon/lm78.c | 47 +++++++++++++------------ drivers/hwmon/lm80.c | 27 +++++++------- drivers/hwmon/lm83.c | 13 +++---- drivers/hwmon/lm85.c | 67 +++++++++++++++++------------------ drivers/hwmon/lm87.c | 39 +++++++++++---------- drivers/hwmon/lm90.c | 21 +++++------ drivers/hwmon/lm92.c | 17 ++++----- drivers/hwmon/max1619.c | 13 +++---- drivers/hwmon/pc87360.c | 61 ++++++++++++++++---------------- drivers/hwmon/sis5595.c | 47 +++++++++++++------------ drivers/hwmon/smsc47b397.c | 17 ++++----- drivers/hwmon/smsc47m1.c | 41 +++++++++++----------- drivers/hwmon/via686a.c | 33 +++++++++--------- drivers/hwmon/vt8231.c | 51 ++++++++++++++------------- drivers/hwmon/w83627ehf.c | 33 +++++++++--------- drivers/hwmon/w83627hf.c | 57 +++++++++++++++--------------- drivers/hwmon/w83781d.c | 55 +++++++++++++++-------------- drivers/hwmon/w83792d.c | 9 ++--- drivers/hwmon/w83l785ts.c | 9 ++--- 36 files changed, 632 insertions(+), 596 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index 665612729cb9..2b6e74dd4a82 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -26,6 +26,7 @@ #include #include #include +#include /* Addresses to scan */ @@ -92,7 +93,7 @@ struct adm1021_data { struct class_device *class_dev; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -162,10 +163,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co struct adm1021_data *data = i2c_get_clientdata(client); \ int temp = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = TEMP_TO_REG(temp); \ adm1021_write_value(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } set(temp_max, ADM1021_REG_TOS_W); @@ -275,7 +276,7 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, type_name, I2C_NAME_SIZE); data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -351,7 +352,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct adm1021_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -375,7 +376,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index 9331c56d2ba6..a4c859c9fbf8 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -53,6 +53,7 @@ #include #include #include +#include /* * Addresses to scan @@ -133,7 +134,7 @@ static struct i2c_driver adm1025_driver = { struct adm1025_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -207,11 +208,11 @@ static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute struct adm1025_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->in_min[offset] = IN_TO_REG(val, in_scale[offset]); \ i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(offset), \ data->in_min[offset]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } \ static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ @@ -221,11 +222,11 @@ static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute struct adm1025_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->in_max[offset] = IN_TO_REG(val, in_scale[offset]); \ i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(offset), \ data->in_max[offset]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } \ static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ @@ -247,11 +248,11 @@ static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribut struct adm1025_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->temp_min[offset-1] = TEMP_TO_REG(val); \ i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(offset-1), \ data->temp_min[offset-1]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } \ static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ @@ -261,11 +262,11 @@ static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribut struct adm1025_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->temp_max[offset-1] = TEMP_TO_REG(val); \ i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(offset-1), \ data->temp_max[offset-1]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } \ static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ @@ -404,7 +405,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) /* We can fill in the remaining client fields */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -523,7 +524,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct adm1025_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { int i; @@ -558,7 +559,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index fefe6e74fd02..8646ec1e9667 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -32,6 +32,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; @@ -260,10 +261,10 @@ struct pwm_data { struct adm1026_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; int valid; /* !=0 if following fields are valid */ unsigned long last_reading; /* In jiffies */ unsigned long last_config; /* In jiffies */ @@ -575,7 +576,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev) int i; long value, alarms, gpio; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (!data->valid || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) { /* Things that change quickly */ @@ -710,7 +711,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev) dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n"); data->vid = (data->gpio >> 11) & 0x1f; data->valid = 1; - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -739,10 +740,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = INS_TO_REG(nr, val); adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, @@ -762,10 +763,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = INS_TO_REG(nr, val); adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -813,10 +814,10 @@ static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, c struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET); adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf) @@ -831,10 +832,10 @@ static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, c struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET); adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -874,11 +875,11 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]); adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -939,7 +940,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, if (new_div == 0) { return -EINVAL; } - down(&data->update_lock); + mutex_lock(&data->update_lock); orig_div = data->fan_div[nr]; data->fan_div[nr] = DIV_FROM_REG(new_div); @@ -958,7 +959,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, if (data->fan_div[nr] != orig_div) { fixup_fan_min(dev,nr,orig_div); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1001,11 +1002,11 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[nr] = TEMP_TO_REG(val); adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr], data->temp_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, @@ -1025,11 +1026,11 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[nr] = TEMP_TO_REG(val); adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr], data->temp_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1064,11 +1065,11 @@ static ssize_t set_temp_offset(struct device *dev, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_offset[nr] = TEMP_TO_REG(val); adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr], data->temp_offset[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1115,11 +1116,11 @@ static ssize_t set_temp_auto_point1_temp(struct device *dev, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_tmin[nr] = TEMP_TO_REG(val); adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr], data->temp_tmin[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1150,11 +1151,11 @@ static ssize_t set_temp_crit_enable(struct device *dev, int val = simple_strtol(buf, NULL, 10); if ((val == 1) || (val==0)) { - down(&data->update_lock); + mutex_lock(&data->update_lock); data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4); adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } return count; } @@ -1184,11 +1185,11 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_crit[nr] = TEMP_TO_REG(val); adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr], data->temp_crit[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1212,10 +1213,10 @@ static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *a struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->analog_out = DAC_TO_REG(val); adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1267,7 +1268,7 @@ static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, int val = simple_strtol(buf, NULL, 10); unsigned long mask; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->alarm_mask = val & 0x7fffffff; mask = data->alarm_mask | (data->gpio_mask & 0x10000 ? 0x80000000 : 0); @@ -1282,7 +1283,7 @@ static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, mask >>= 8; adm1026_write_value(client, ADM1026_REG_MASK4, mask & 0xff); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1303,7 +1304,7 @@ static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const int val = simple_strtol(buf, NULL, 10); long gpio; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->gpio = val & 0x1ffff; gpio = data->gpio; adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7,gpio & 0xff); @@ -1311,7 +1312,7 @@ static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15,gpio & 0xff); gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f); adm1026_write_value(client, ADM1026_REG_STATUS4,gpio & 0xff); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1331,7 +1332,7 @@ static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, int val = simple_strtol(buf, NULL, 10); long mask; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->gpio_mask = val & 0x1ffff; mask = data->gpio_mask; adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7,mask & 0xff); @@ -1339,7 +1340,7 @@ static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15,mask & 0xff); mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f); adm1026_write_value(client, ADM1026_REG_MASK1,mask & 0xff); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1359,10 +1360,10 @@ static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, co if (data->pwm1.enable == 1) { int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm1.pwm = PWM_TO_REG(val); adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } return count; } @@ -1378,14 +1379,14 @@ static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *att struct adm1026_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm1.auto_pwm_min = SENSORS_LIMIT(val,0,255); if (data->pwm1.enable == 2) { /* apply immediately */ data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf) @@ -1406,7 +1407,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, int old_enable; if ((val >= 0) && (val < 3)) { - down(&data->update_lock); + mutex_lock(&data->update_lock); old_enable = data->pwm1.enable; data->pwm1.enable = val; data->config1 = (data->config1 & ~CFG1_PWM_AFC) @@ -1424,7 +1425,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); } return count; } @@ -1541,7 +1542,7 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, /* Fill in the remaining client fields */ data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index d06397966081..3bf2da621aed 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -28,6 +28,7 @@ #include #include #include +#include /* Following macros takes channel parameter starting from 0 to 2 */ #define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) @@ -70,7 +71,7 @@ typedef u8 auto_chan_table_t[8][2]; struct adm1031_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; int chip_type; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -262,10 +263,10 @@ set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr) old_fan_mode = data->conf1; - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, ®))) { - up(&data->update_lock); + mutex_unlock(&data->update_lock); return ret; } if (((data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1)) & ADM1031_CONF1_AUTO_MODE) ^ @@ -288,7 +289,7 @@ set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr) } data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -329,11 +330,11 @@ set_auto_temp_min(struct device *dev, const char *buf, size_t count, int nr) struct adm1031_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]); adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), data->auto_temp[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_auto_temp_max(struct device *dev, char *buf, int nr) @@ -349,11 +350,11 @@ set_auto_temp_max(struct device *dev, const char *buf, size_t count, int nr) struct adm1031_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]); adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), data->temp_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -405,11 +406,11 @@ set_pwm(struct device *dev, const char *buf, size_t count, int nr) int val = simple_strtol(buf, NULL, 10); int reg; - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && (((val>>4) & 0xf) != 5)) { /* In automatic mode, the only PWM accepted is 33% */ - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } data->pwm[nr] = PWM_TO_REG(val); @@ -417,7 +418,7 @@ set_pwm(struct device *dev, const char *buf, size_t count, int nr) adm1031_write_value(client, ADM1031_REG_PWM, nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf) : (data->pwm[nr] & 0xf) | (reg & 0xf0)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -511,7 +512,7 @@ set_fan_min(struct device *dev, const char *buf, size_t count, int nr) struct adm1031_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (val) { data->fan_min[nr] = FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); @@ -519,7 +520,7 @@ set_fan_min(struct device *dev, const char *buf, size_t count, int nr) data->fan_min[nr] = 0xff; } adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t @@ -540,7 +541,7 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr) if (tmp == 0xff) return -EINVAL; - down(&data->update_lock); + mutex_lock(&data->update_lock); old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); data->fan_div[nr] = (tmp & 0xC0) | (0x3f & data->fan_div[nr]); new_min = data->fan_min[nr] * old_div / @@ -553,7 +554,7 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr) data->fan_div[nr]); adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -627,11 +628,11 @@ set_temp_min(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtol(buf, NULL, 10); val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[nr] = TEMP_TO_REG(val); adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr), data->temp_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t @@ -643,11 +644,11 @@ set_temp_max(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtol(buf, NULL, 10); val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[nr] = TEMP_TO_REG(val); adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr), data->temp_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t @@ -659,11 +660,11 @@ set_temp_crit(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtol(buf, NULL, 10); val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_crit[nr] = TEMP_TO_REG(val); adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr), data->temp_crit[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -778,7 +779,7 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -891,7 +892,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) struct adm1031_data *data = i2c_get_clientdata(client); int chan; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -965,7 +966,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 5ddc22fea4a3..43f6991b588c 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -49,6 +49,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, @@ -150,7 +151,7 @@ struct adm9240_data { enum chips type; struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; unsigned long last_updated_measure; unsigned long last_updated_config; @@ -195,11 +196,11 @@ static ssize_t set_max(struct device *dev, struct device_attribute *devattr, struct adm9240_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[attr->index] = TEMP_TO_REG(val); i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index), data->temp_max[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -246,11 +247,11 @@ static ssize_t set_in_min(struct device *dev, struct adm9240_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[attr->index] = IN_TO_REG(val, attr->index); i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index), data->in_min[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -263,11 +264,11 @@ static ssize_t set_in_max(struct device *dev, struct adm9240_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[attr->index] = IN_TO_REG(val, attr->index); i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index), data->in_max[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -350,7 +351,7 @@ static ssize_t set_fan_min(struct device *dev, int nr = attr->index; u8 new_div; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (!val) { data->fan_min[nr] = 255; @@ -390,7 +391,7 @@ static ssize_t set_fan_min(struct device *dev, i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -439,10 +440,10 @@ static ssize_t set_aout(struct device *dev, struct adm9240_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->aout = AOUT_TO_REG(val); i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); @@ -539,7 +540,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) /* fill in the remaining client fields and attach */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->type = kind; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); if ((err = i2c_attach_client(new_client))) goto exit_free; @@ -691,7 +692,7 @@ static struct adm9240_data *adm9240_update_device(struct device *dev) struct adm9240_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); /* minimum measurement cycle: 1.75 seconds */ if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4)) @@ -771,7 +772,7 @@ static struct adm9240_data *adm9240_update_device(struct device *dev) data->last_updated_config = jiffies; data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index ae9de63cf2e0..65b2709f750c 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "lm75.h" /* @@ -182,10 +183,10 @@ static u8 DIV_TO_REG(long val) struct asb100_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; unsigned long last_updated; /* In jiffies */ /* array of 2 pointers to subclients */ @@ -245,11 +246,11 @@ static ssize_t set_in_##reg(struct device *dev, const char *buf, \ struct asb100_data *data = i2c_get_clientdata(client); \ unsigned long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->in_##reg[nr] = IN_TO_REG(val); \ asb100_write_value(client, ASB100_REG_IN_##REG(nr), \ data->in_##reg[nr]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -331,10 +332,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct asb100_data *data = i2c_get_clientdata(client); u32 val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -351,7 +352,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, unsigned long val = simple_strtoul(buf, NULL, 10); int reg; - down(&data->update_lock); + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); @@ -381,7 +382,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -461,7 +462,7 @@ static ssize_t set_##reg(struct device *dev, const char *buf, \ struct asb100_data *data = i2c_get_clientdata(client); \ unsigned long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ switch (nr) { \ case 1: case 2: \ data->reg[nr] = LM75_TEMP_TO_REG(val); \ @@ -472,7 +473,7 @@ static ssize_t set_##reg(struct device *dev, const char *buf, \ } \ asb100_write_value(client, ASB100_REG_TEMP_##REG(nr+1), \ data->reg[nr]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -574,11 +575,11 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const struct asb100_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm &= 0x80; /* keep the enable bit */ data->pwm |= (0x0f & ASB100_PWM_TO_REG(val)); asb100_write_value(client, ASB100_REG_PWM1, data->pwm); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -595,11 +596,11 @@ static ssize_t set_pwm_enable1(struct device *dev, struct device_attribute *attr struct asb100_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm &= 0x0f; /* keep the duty cycle bits */ data->pwm |= (val ? 0x80 : 0x00); asb100_write_value(client, ASB100_REG_PWM1, data->pwm); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -729,7 +730,7 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) } new_client = &data->client; - init_MUTEX(&data->lock); + mutex_init(&data->lock); i2c_set_clientdata(new_client, data); new_client->addr = address; new_client->adapter = adapter; @@ -789,7 +790,7 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -885,7 +886,7 @@ static int asb100_read_value(struct i2c_client *client, u16 reg) struct i2c_client *cl; int res, bank; - down(&data->lock); + mutex_lock(&data->lock); bank = (reg >> 8) & 0x0f; if (bank > 2) @@ -919,7 +920,7 @@ static int asb100_read_value(struct i2c_client *client, u16 reg) if (bank > 2) i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); - up(&data->lock); + mutex_unlock(&data->lock); return res; } @@ -930,7 +931,7 @@ static void asb100_write_value(struct i2c_client *client, u16 reg, u16 value) struct i2c_client *cl; int bank; - down(&data->lock); + mutex_lock(&data->lock); bank = (reg >> 8) & 0x0f; if (bank > 2) @@ -960,7 +961,7 @@ static void asb100_write_value(struct i2c_client *client, u16 reg, u16 value) if (bank > 2) i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); - up(&data->lock); + mutex_unlock(&data->lock); } static void asb100_init_client(struct i2c_client *client) @@ -984,7 +985,7 @@ static struct asb100_data *asb100_update_device(struct device *dev) struct asb100_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -1042,7 +1043,7 @@ static struct asb100_data *asb100_update_device(struct device *dev) dev_dbg(&client->dev, "... device update complete\n"); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index b0c490073c8e..728a1e8b9190 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -26,6 +26,7 @@ #include #include #include +#include MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); @@ -60,7 +61,7 @@ static struct i2c_driver atxp1_driver = { struct atxp1_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; unsigned long last_updated; u8 valid; struct { @@ -80,7 +81,7 @@ static struct atxp1_data * atxp1_update_device(struct device *dev) client = to_i2c_client(dev); data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { @@ -93,7 +94,7 @@ static struct atxp1_data * atxp1_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return(data); } @@ -309,7 +310,7 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); err = i2c_attach_client(new_client); diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index 203f9c7abb20..478eb4bb8570 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "lm75.h" /* Addresses to scan */ @@ -72,7 +73,7 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low") struct ds1621_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -156,10 +157,10 @@ static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *at struct ds1621_data *data = ds1621_update_client(dev); \ u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = val; \ ds1621_write_value(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -242,7 +243,7 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address, /* Fill in remaining client fields and put it into the global list */ strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -297,7 +298,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev) struct ds1621_data *data = i2c_get_clientdata(client); u8 new_conf; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -327,7 +328,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c index 25409181d1eb..6bc76b407636 100644 --- a/drivers/hwmon/fscher.c +++ b/drivers/hwmon/fscher.c @@ -33,6 +33,7 @@ #include #include #include +#include /* * Addresses to scan @@ -133,7 +134,7 @@ static struct i2c_driver fscher_driver = { struct fscher_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -332,7 +333,7 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) * global list */ strlcpy(new_client->name, "fscher", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -417,7 +418,7 @@ static struct fscher_data *fscher_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct fscher_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { @@ -457,7 +458,7 @@ static struct fscher_data *fscher_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -472,10 +473,10 @@ static ssize_t set_fan_status(struct i2c_client *client, struct fscher_data *dat /* bits 0..1, 3..7 reserved => mask with 0x04 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v; fscher_write_value(client, reg, v); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -490,10 +491,10 @@ static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data, { unsigned long v = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v; fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -518,14 +519,14 @@ static ssize_t set_fan_div(struct i2c_client *client, struct fscher_data *data, return -EINVAL; } - down(&data->update_lock); + mutex_lock(&data->update_lock); /* bits 2..7 reserved => mask with 0x03 */ data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03; data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v; fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -552,10 +553,10 @@ static ssize_t set_temp_status(struct i2c_client *client, struct fscher_data *da /* bits 2..7 reserved, 0 read only => mask with 0x02 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v; fscher_write_value(client, reg, v); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -609,10 +610,10 @@ static ssize_t set_control(struct i2c_client *client, struct fscher_data *data, /* bits 1..7 reserved => mask with 0x01 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->global_control &= ~v; fscher_write_value(client, reg, v); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -631,11 +632,11 @@ static ssize_t set_watchdog_control(struct i2c_client *client, struct /* bits 0..3 reserved => mask with 0xf0 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->watchdog[2] &= ~0xf0; data->watchdog[2] |= v; fscher_write_value(client, reg, data->watchdog[2]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -651,10 +652,10 @@ static ssize_t set_watchdog_status(struct i2c_client *client, struct fscher_data /* bits 0, 2..7 reserved => mask with 0x02 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->watchdog[1] &= ~v; fscher_write_value(client, reg, v); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -669,10 +670,10 @@ static ssize_t set_watchdog_preset(struct i2c_client *client, struct fscher_data { unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->watchdog[0] = v; fscher_write_value(client, reg, data->watchdog[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c index 6d0146b57020..758978e1bfe0 100644 --- a/drivers/hwmon/fscpos.c +++ b/drivers/hwmon/fscpos.c @@ -37,6 +37,7 @@ #include #include #include +#include /* * Addresses to scan @@ -114,7 +115,7 @@ static struct i2c_driver fscpos_driver = { struct fscpos_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* 0 until following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -208,13 +209,13 @@ static ssize_t set_fan_ripple(struct i2c_client *client, struct fscpos_data return -EINVAL; } - down(&data->update_lock); + mutex_lock(&data->update_lock); /* bits 2..7 reserved => mask with 0x03 */ data->fan_ripple[nr - 1] &= ~0x03; data->fan_ripple[nr - 1] |= v; fscpos_write_value(client, reg, data->fan_ripple[nr - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -232,10 +233,10 @@ static ssize_t set_pwm(struct i2c_client *client, struct fscpos_data *data, if (v < 0) v = 0; if (v > 255) v = 255; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[nr - 1] = v; fscpos_write_value(client, reg, data->pwm[nr - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -278,11 +279,11 @@ static ssize_t set_wdog_control(struct i2c_client *client, struct fscpos_data /* bits 0..3 reserved => mask with 0xf0 */ unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->wdog_control &= ~0xf0; data->wdog_control |= v; fscpos_write_value(client, reg, data->wdog_control); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -304,10 +305,10 @@ static ssize_t set_wdog_state(struct i2c_client *client, struct fscpos_data return -EINVAL; } - down(&data->update_lock); + mutex_lock(&data->update_lock); data->wdog_state &= ~v; fscpos_write_value(client, reg, v); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -321,10 +322,10 @@ static ssize_t set_wdog_preset(struct i2c_client *client, struct fscpos_data { unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->wdog_preset = v; fscpos_write_value(client, reg, data->wdog_preset); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -483,7 +484,7 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -579,7 +580,7 @@ static struct fscpos_data *fscpos_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct fscpos_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { int i; @@ -625,7 +626,7 @@ static struct fscpos_data *fscpos_update_device(struct device *dev) data->last_updated = jiffies; data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 9e685e3a3bc9..6606aabdb49d 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -43,6 +43,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; @@ -120,7 +121,7 @@ struct gl518_data { struct class_device *class_dev; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -212,10 +213,10 @@ static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, c struct gl518_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = type##_TO_REG(val); \ gl518_write_value(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -228,12 +229,12 @@ static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, c int regvalue; \ unsigned long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ regvalue = gl518_read_value(client, reg); \ data->value = type##_TO_REG(val); \ regvalue = (regvalue & ~mask) | (data->value << shift); \ gl518_write_value(client, reg, regvalue); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -265,7 +266,7 @@ static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, c int regvalue; unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); data->fan_min[0] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[0])); @@ -280,7 +281,7 @@ static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, c data->beep_mask &= data->alarm_mask; gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -291,7 +292,7 @@ static ssize_t set_fan_min2(struct device *dev, struct device_attribute *attr, c int regvalue; unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); data->fan_min[1] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[1])); @@ -306,7 +307,7 @@ static ssize_t set_fan_min2(struct device *dev, struct device_attribute *attr, c data->beep_mask &= data->alarm_mask; gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -407,7 +408,7 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, "gl518sm", I2C_NAME_SIZE); data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -525,7 +526,7 @@ static struct gl518_data *gl518_update_device(struct device *dev) struct gl518_data *data = i2c_get_clientdata(client); int val; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -586,7 +587,7 @@ static struct gl518_data *gl518_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index baee60e44b52..47b4d49f75c6 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -29,6 +29,7 @@ #include #include #include +#include /* Type of the extra sensor */ static unsigned short extra_sensor_type; @@ -121,7 +122,7 @@ static struct i2c_driver gl520_driver = { struct gl520_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until the following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -303,7 +304,7 @@ static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, co long v = simple_strtol(buf, NULL, 10); u8 r; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (n == 0) r = VDD_TO_REG(v); @@ -317,7 +318,7 @@ static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, co else gl520_write_value(client, reg, r); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -331,7 +332,7 @@ static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, co else r = IN_TO_REG(v); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[n] = r; @@ -340,7 +341,7 @@ static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, co else gl520_write_value(client, reg, r); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -373,7 +374,7 @@ static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, c unsigned long v = simple_strtoul(buf, NULL, 10); u8 r; - down(&data->update_lock); + mutex_lock(&data->update_lock); r = FAN_TO_REG(v, data->fan_div[n - 1]); data->fan_min[n - 1] = r; @@ -390,7 +391,7 @@ static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, c data->beep_mask &= data->alarm_mask; gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -409,7 +410,7 @@ static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, c return -EINVAL; } - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_div[n - 1] = r; if (n == 1) @@ -417,7 +418,7 @@ static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, c else gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -425,10 +426,10 @@ static ssize_t set_fan_off(struct i2c_client *client, struct gl520_data *data, c { u8 r = simple_strtoul(buf, NULL, 10)?1:0; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_off = r; gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -454,10 +455,10 @@ static ssize_t set_temp_max(struct i2c_client *client, struct gl520_data *data, { long v = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[n - 1] = TEMP_TO_REG(v);; gl520_write_value(client, reg, data->temp_max[n - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -465,10 +466,10 @@ static ssize_t set_temp_max_hyst(struct i2c_client *client, struct gl520_data *d { long v = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max_hyst[n - 1] = TEMP_TO_REG(v); gl520_write_value(client, reg, data->temp_max_hyst[n - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -491,10 +492,10 @@ static ssize_t set_beep_enable(struct i2c_client *client, struct gl520_data *dat { u8 r = simple_strtoul(buf, NULL, 10)?0:1; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->beep_enable = !r; gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -502,11 +503,11 @@ static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data, { u8 r = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); r &= data->alarm_mask; data->beep_mask = r; gl520_write_value(client, reg, r); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -561,7 +562,7 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields */ strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -685,7 +686,7 @@ static struct gl520_data *gl520_update_device(struct device *dev) struct gl520_data *data = i2c_get_clientdata(client); int val; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { @@ -750,7 +751,7 @@ static struct gl520_data *gl520_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 23a9e1ea8e32..7636c1a58f9c 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ @@ -70,10 +71,10 @@ static u8 km_activity; static int rest_x; static int rest_y; -static DECLARE_MUTEX(hdaps_sem); +static DEFINE_MUTEX(hdaps_mutex); /* - * __get_latch - Get the value from a given port. Callers must hold hdaps_sem. + * __get_latch - Get the value from a given port. Callers must hold hdaps_mutex. */ static inline u8 __get_latch(u16 port) { @@ -82,7 +83,7 @@ static inline u8 __get_latch(u16 port) /* * __check_latch - Check a port latch for a given value. Returns zero if the - * port contains the given value. Callers must hold hdaps_sem. + * port contains the given value. Callers must hold hdaps_mutex. */ static inline int __check_latch(u16 port, u8 val) { @@ -93,7 +94,7 @@ static inline int __check_latch(u16 port, u8 val) /* * __wait_latch - Wait up to 100us for a port latch to get a certain value, - * returning zero if the value is obtained. Callers must hold hdaps_sem. + * returning zero if the value is obtained. Callers must hold hdaps_mutex. */ static int __wait_latch(u16 port, u8 val) { @@ -110,7 +111,7 @@ static int __wait_latch(u16 port, u8 val) /* * __device_refresh - request a refresh from the accelerometer. Does not wait - * for refresh to complete. Callers must hold hdaps_sem. + * for refresh to complete. Callers must hold hdaps_mutex. */ static void __device_refresh(void) { @@ -124,7 +125,7 @@ static void __device_refresh(void) /* * __device_refresh_sync - request a synchronous refresh from the * accelerometer. We wait for the refresh to complete. Returns zero if - * successful and nonzero on error. Callers must hold hdaps_sem. + * successful and nonzero on error. Callers must hold hdaps_mutex. */ static int __device_refresh_sync(void) { @@ -134,7 +135,7 @@ static int __device_refresh_sync(void) /* * __device_complete - indicate to the accelerometer that we are done reading - * data, and then initiate an async refresh. Callers must hold hdaps_sem. + * data, and then initiate an async refresh. Callers must hold hdaps_mutex. */ static inline void __device_complete(void) { @@ -152,7 +153,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val) { int ret; - down(&hdaps_sem); + mutex_lock(&hdaps_mutex); /* do a sync refresh -- we need to be sure that we read fresh data */ ret = __device_refresh_sync(); @@ -163,7 +164,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val) __device_complete(); out: - up(&hdaps_sem); + mutex_unlock(&hdaps_mutex); return ret; } @@ -198,9 +199,9 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2, { int ret; - down(&hdaps_sem); + mutex_lock(&hdaps_mutex); ret = __hdaps_read_pair(port1, port2, val1, val2); - up(&hdaps_sem); + mutex_unlock(&hdaps_mutex); return ret; } @@ -213,7 +214,7 @@ static int hdaps_device_init(void) { int total, ret = -ENXIO; - down(&hdaps_sem); + mutex_lock(&hdaps_mutex); outb(0x13, 0x1610); outb(0x01, 0x161f); @@ -279,7 +280,7 @@ static int hdaps_device_init(void) } out: - up(&hdaps_sem); + mutex_unlock(&hdaps_mutex); return ret; } @@ -313,7 +314,7 @@ static struct platform_driver hdaps_driver = { }; /* - * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem. + * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_mutex. */ static void hdaps_calibrate(void) { @@ -325,7 +326,7 @@ static void hdaps_mousedev_poll(unsigned long unused) int x, y; /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ - if (down_trylock(&hdaps_sem)) { + if (!mutex_trylock(&hdaps_mutex)) { mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); return; } @@ -340,7 +341,7 @@ static void hdaps_mousedev_poll(unsigned long unused) mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); out: - up(&hdaps_sem); + mutex_unlock(&hdaps_mutex); } @@ -420,9 +421,9 @@ static ssize_t hdaps_calibrate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - down(&hdaps_sem); + mutex_lock(&hdaps_mutex); hdaps_calibrate(); - up(&hdaps_sem); + mutex_unlock(&hdaps_mutex); return count; } diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index d7a9401600bb..122ff9cd75cb 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -194,10 +195,10 @@ static int DIV_TO_REG(int val) struct it87_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -290,11 +291,11 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, struct it87_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val); it87_write_value(client, IT87_REG_VIN_MIN(nr), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, @@ -307,11 +308,11 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, struct it87_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val); it87_write_value(client, IT87_REG_VIN_MAX(nr), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -381,10 +382,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_high[nr] = TEMP_TO_REG(val); it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, @@ -397,10 +398,10 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_low[nr] = TEMP_TO_REG(val); it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_temp_offset(offset) \ @@ -440,7 +441,7 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->sensor &= ~(1 << nr); data->sensor &= ~(8 << nr); @@ -450,11 +451,11 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, else if (val == 2) data->sensor |= 8 << nr; else if (val != 0) { - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_sensor_offset(offset) \ @@ -524,7 +525,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, int val = simple_strtol(buf, NULL, 10); u8 reg = it87_read_value(client, IT87_REG_FAN_DIV); - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (nr) { case 0: data->fan_div[nr] = reg & 0x07; break; case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; @@ -533,7 +534,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, @@ -548,7 +549,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, int i, min[3]; u8 old; - down(&data->update_lock); + mutex_lock(&data->update_lock); old = it87_read_value(client, IT87_REG_FAN_DIV); for (i = 0; i < 3; i++) @@ -576,7 +577,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i])); it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_pwm_enable(struct device *dev, @@ -589,7 +590,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (val == 0) { int tmp; @@ -606,11 +607,11 @@ static ssize_t set_pwm_enable(struct device *dev, /* set saved pwm value, clear FAN_CTLX PWM mode bit */ it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); } else { - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, @@ -626,11 +627,11 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, if (val < 0 || val > 255) return -EINVAL; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->manual_pwm_ctl[nr] = val; if (data->fan_main_ctrl & (1 << nr)) it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -776,7 +777,7 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) new_client = &data->client; if (is_isa) - init_MUTEX(&data->lock); + mutex_init(&data->lock); i2c_set_clientdata(new_client, data); new_client->addr = address; new_client->adapter = adapter; @@ -823,7 +824,7 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, name, I2C_NAME_SIZE); data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -950,10 +951,10 @@ static int it87_read_value(struct i2c_client *client, u8 reg) int res; if (i2c_is_isa_client(client)) { - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); res = inb_p(client->addr + IT87_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return res; } else return i2c_smbus_read_byte_data(client, reg); @@ -969,10 +970,10 @@ static int it87_write_value(struct i2c_client *client, u8 reg, u8 value) struct it87_data *data = i2c_get_clientdata(client); if (i2c_is_isa_client(client)) { - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); outb_p(value, client->addr + IT87_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return 0; } else return i2c_smbus_write_byte_data(client, reg, value); @@ -1098,7 +1099,7 @@ static struct it87_data *it87_update_device(struct device *dev) struct it87_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -1160,7 +1161,7 @@ static struct it87_data *it87_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 6b1aa7ef552e..071f0fc6adec 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -45,6 +45,7 @@ #include #include #include +#include /* * Addresses to scan @@ -153,7 +154,7 @@ static struct i2c_driver lm63_driver = { struct lm63_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -192,13 +193,13 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *dummy, struct lm63_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan[1] = FAN_TO_REG(val); i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB, data->fan[1] & 0xFF); i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB, data->fan[1] >> 8); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -222,12 +223,12 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy, return -EPERM; val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm1_value = val <= 0 ? 0 : val >= 255 ? 2 * data->pwm1_freq : (val * data->pwm1_freq * 2 + 127) / 255; i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -253,10 +254,10 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *dummy, struct lm63_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp8[1] = TEMP8_TO_REG(val); i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -284,13 +285,13 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, long val = simple_strtol(buf, NULL, 10); int nr = attr->index; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp11[nr] = TEMP11_TO_REG(val); i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], data->temp11[nr] >> 8); i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], data->temp11[nr] & 0xff); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -314,11 +315,11 @@ static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute * long val = simple_strtol(buf, NULL, 10); long hyst; - down(&data->update_lock); + mutex_lock(&data->update_lock); hyst = TEMP8_FROM_REG(data->temp8[2]) - val; i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, HYST_TO_REG(hyst)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -427,7 +428,7 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, "lm63", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -530,7 +531,7 @@ static struct lm63_data *lm63_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm63_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { if (data->config & 0x04) { /* tachometer enabled */ @@ -582,7 +583,7 @@ static struct lm63_data *lm63_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 74ca2c8c61c3..fc25b90ec24a 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "lm75.h" @@ -47,7 +48,7 @@ I2C_CLIENT_INSMOD_1(lm75); struct lm75_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ u16 temp_input; /* Register values */ @@ -91,10 +92,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co struct lm75_data *data = i2c_get_clientdata(client); \ int temp = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = LM75_TEMP_TO_REG(temp); \ lm75_write_value(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } set(temp_max, LM75_REG_TEMP_OS); @@ -188,7 +189,7 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields and put it into the global list */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -264,7 +265,7 @@ static struct lm75_data *lm75_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm75_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -277,7 +278,7 @@ static struct lm75_data *lm75_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index df9e02aaa70a..459cc977380a 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -32,6 +32,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END }; @@ -51,7 +52,7 @@ I2C_CLIENT_INSMOD_1(lm77); struct lm77_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; unsigned long last_updated; /* In jiffies */ int temp_input; /* Temperatures */ @@ -139,10 +140,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co struct lm77_data *data = i2c_get_clientdata(client); \ long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = val; \ lm77_write_value(client, reg, LM77_TEMP_TO_REG(data->value)); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -157,11 +158,11 @@ static ssize_t set_temp_crit_hyst(struct device *dev, struct device_attribute *a struct lm77_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_hyst = data->temp_crit - val; lm77_write_value(client, LM77_REG_TEMP_HYST, LM77_TEMP_TO_REG(data->temp_hyst)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -173,7 +174,7 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, long val = simple_strtoul(buf, NULL, 10); int oldcrithyst; - down(&data->update_lock); + mutex_lock(&data->update_lock); oldcrithyst = data->temp_crit - data->temp_hyst; data->temp_crit = val; data->temp_hyst = data->temp_crit - oldcrithyst; @@ -181,7 +182,7 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, LM77_TEMP_TO_REG(data->temp_crit)); lm77_write_value(client, LM77_REG_TEMP_HYST, LM77_TEMP_TO_REG(data->temp_hyst)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -306,7 +307,7 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields and put it into the global list */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -380,7 +381,7 @@ static struct lm77_data *lm77_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm77_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -406,7 +407,7 @@ static struct lm77_data *lm77_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index e404001e20da..36d1192ebe2a 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -27,6 +27,7 @@ #include #include #include +#include #include /* Addresses to scan */ @@ -131,10 +132,10 @@ static inline int TEMP_FROM_REG(s8 val) struct lm78_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -207,10 +208,10 @@ static ssize_t set_in_min(struct device *dev, const char *buf, struct lm78_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val); lm78_write_value(client, LM78_REG_IN_MIN(nr), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -221,10 +222,10 @@ static ssize_t set_in_max(struct device *dev, const char *buf, struct lm78_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val); lm78_write_value(client, LM78_REG_IN_MAX(nr), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -288,10 +289,10 @@ static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, struct lm78_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_over = TEMP_TO_REG(val); lm78_write_value(client, LM78_REG_TEMP_OVER, data->temp_over); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -307,10 +308,10 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, struct lm78_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_hyst = TEMP_TO_REG(val); lm78_write_value(client, LM78_REG_TEMP_HYST, data->temp_hyst); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -342,10 +343,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct lm78_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -368,7 +369,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, unsigned long min; u8 reg; - down(&data->update_lock); + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); @@ -380,7 +381,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, default: dev_err(&client->dev, "fan_div value %ld not " "supported. Choose one of 1, 2, 4 or 8!\n", val); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -398,7 +399,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -548,7 +549,7 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) new_client = &data->client; if (is_isa) - init_MUTEX(&data->lock); + mutex_init(&data->lock); i2c_set_clientdata(new_client, data); new_client->addr = address; new_client->adapter = adapter; @@ -598,7 +599,7 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -697,10 +698,10 @@ static int lm78_read_value(struct i2c_client *client, u8 reg) int res; if (i2c_is_isa_client(client)) { struct lm78_data *data = i2c_get_clientdata(client); - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); res = inb_p(client->addr + LM78_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return res; } else return i2c_smbus_read_byte_data(client, reg); @@ -717,10 +718,10 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value) { if (i2c_is_isa_client(client)) { struct lm78_data *data = i2c_get_clientdata(client); - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); outb_p(value, client->addr + LM78_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return 0; } else return i2c_smbus_write_byte_data(client, reg, value); @@ -742,7 +743,7 @@ static struct lm78_data *lm78_update_device(struct device *dev) struct lm78_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -786,7 +787,7 @@ static struct lm78_data *lm78_update_device(struct device *dev) data->fan_div[2] = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index c9a7cdea7bd7..f72120d08c4c 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -28,6 +28,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, @@ -108,7 +109,7 @@ static inline long TEMP_FROM_REG(u16 temp) struct lm80_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -191,10 +192,10 @@ static ssize_t set_in_##suffix(struct device *dev, struct device_attribute *attr struct lm80_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock);\ + mutex_lock(&data->update_lock);\ data->value = IN_TO_REG(val); \ lm80_write_value(client, reg, data->value); \ - up(&data->update_lock);\ + mutex_unlock(&data->update_lock);\ return count; \ } set_in(min0, in_min[0], LM80_REG_IN_MIN(0)); @@ -241,10 +242,10 @@ static ssize_t set_fan_##suffix(struct device *dev, struct device_attribute *att struct lm80_data *data = i2c_get_clientdata(client); \ long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock);\ + mutex_lock(&data->update_lock);\ data->value = FAN_TO_REG(val, DIV_FROM_REG(data->div)); \ lm80_write_value(client, reg, data->value); \ - up(&data->update_lock);\ + mutex_unlock(&data->update_lock);\ return count; \ } set_fan(min1, fan_min[0], LM80_REG_FAN_MIN(1), fan_div[0]); @@ -263,7 +264,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, u8 reg; /* Save fan_min */ - down(&data->update_lock); + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); @@ -275,7 +276,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, default: dev_err(&client->dev, "fan_div value %ld not " "supported. Choose one of 1, 2, 4 or 8!\n", val); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -286,7 +287,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, /* Restore fan_min */ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -325,10 +326,10 @@ static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *at struct lm80_data *data = i2c_get_clientdata(client); \ long val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = TEMP_LIMIT_TO_REG(val); \ lm80_write_value(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } set_temp(hot_max, temp_hot_max, LM80_REG_TEMP_HOT_MAX); @@ -437,7 +438,7 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields and put it into the global list */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -545,7 +546,7 @@ static struct lm80_data *lm80_update_device(struct device *dev) struct lm80_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { dev_dbg(&client->dev, "Starting lm80 update\n"); @@ -585,7 +586,7 @@ static struct lm80_data *lm80_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index 26dfa9e216c2..aac4ec2bf694 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c @@ -35,6 +35,7 @@ #include #include #include +#include /* * Addresses to scan @@ -139,7 +140,7 @@ static struct i2c_driver lm83_driver = { struct lm83_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -171,11 +172,11 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, long val = simple_strtol(buf, NULL, 10); int nr = attr->index; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp[nr] = TEMP_TO_REG(val); i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4], data->temp[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -300,7 +301,7 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) /* We can fill in the remaining client fields */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -373,7 +374,7 @@ static struct lm83_data *lm83_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm83_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { int nr; @@ -393,7 +394,7 @@ static struct lm83_data *lm83_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 7389a0127547..095e58ac2ceb 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -31,6 +31,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; @@ -331,10 +332,10 @@ struct lm85_autofan { struct lm85_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; int valid; /* !=0 if following fields are valid */ unsigned long last_reading; /* In jiffies */ unsigned long last_config; /* In jiffies */ @@ -407,10 +408,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val); lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -499,10 +500,10 @@ static ssize_t set_pwm(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[nr] = PWM_TO_REG(val); lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr) @@ -559,10 +560,10 @@ static ssize_t set_in_min(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = INS_TO_REG(nr, val); lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_in_max(struct device *dev, char *buf, int nr) @@ -577,10 +578,10 @@ static ssize_t set_in_max(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = INS_TO_REG(nr, val); lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_in_reg(offset) \ @@ -640,10 +641,10 @@ static ssize_t set_temp_min(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[nr] = TEMP_TO_REG(val); lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_temp_max(struct device *dev, char *buf, int nr) @@ -658,10 +659,10 @@ static ssize_t set_temp_max(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[nr] = TEMP_TO_REG(val); lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_temp_reg(offset) \ @@ -713,12 +714,12 @@ static ssize_t set_pwm_auto_channels(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->autofan[nr].config = (data->autofan[nr].config & (~0xe0)) | ZONE_TO_REG(val) ; lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr), data->autofan[nr].config); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_pwm_auto_pwm_min(struct device *dev, char *buf, int nr) @@ -733,11 +734,11 @@ static ssize_t set_pwm_auto_pwm_min(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->autofan[nr].min_pwm = PWM_TO_REG(val); lm85_write_value(client, LM85_REG_AFAN_MINPWM(nr), data->autofan[nr].min_pwm); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_pwm_auto_pwm_minctl(struct device *dev, char *buf, int nr) @@ -752,7 +753,7 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->autofan[nr].min_off = val; lm85_write_value(client, LM85_REG_AFAN_SPIKE1, data->smooth[0] | data->syncpwm3 @@ -760,7 +761,7 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, const char *buf, | (data->autofan[1].min_off ? 0x40 : 0) | (data->autofan[2].min_off ? 0x80 : 0) ); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_pwm_auto_pwm_freq(struct device *dev, char *buf, int nr) @@ -775,13 +776,13 @@ static ssize_t set_pwm_auto_pwm_freq(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->autofan[nr].freq = FREQ_TO_REG(val); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), (data->zone[nr].range << 4) | data->autofan[nr].freq ); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define pwm_auto(offset) \ @@ -857,7 +858,7 @@ static ssize_t set_temp_auto_temp_off(struct device *dev, const char *buf, int min; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); min = TEMP_FROM_REG(data->zone[nr].limit); data->zone[nr].off_desired = TEMP_TO_REG(val); data->zone[nr].hyst = HYST_TO_REG(min - val); @@ -871,7 +872,7 @@ static ssize_t set_temp_auto_temp_off(struct device *dev, const char *buf, (data->zone[2].hyst << 4) ); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_temp_auto_temp_min(struct device *dev, char *buf, int nr) @@ -886,7 +887,7 @@ static ssize_t set_temp_auto_temp_min(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->zone[nr].limit = TEMP_TO_REG(val); lm85_write_value(client, LM85_REG_AFAN_LIMIT(nr), data->zone[nr].limit); @@ -913,7 +914,7 @@ static ssize_t set_temp_auto_temp_min(struct device *dev, const char *buf, (data->zone[2].hyst << 4) ); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_temp_auto_temp_max(struct device *dev, char *buf, int nr) @@ -930,7 +931,7 @@ static ssize_t set_temp_auto_temp_max(struct device *dev, const char *buf, int min; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); min = TEMP_FROM_REG(data->zone[nr].limit); data->zone[nr].max_desired = TEMP_TO_REG(val); data->zone[nr].range = RANGE_TO_REG( @@ -938,7 +939,7 @@ static ssize_t set_temp_auto_temp_max(struct device *dev, const char *buf, lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), ((data->zone[nr].range & 0x0f) << 4) | (data->autofan[nr].freq & 0x07)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t show_temp_auto_temp_crit(struct device *dev, char *buf, int nr) @@ -953,11 +954,11 @@ static ssize_t set_temp_auto_temp_crit(struct device *dev, const char *buf, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->zone[nr].critical = TEMP_TO_REG(val); lm85_write_value(client, LM85_REG_AFAN_CRITICAL(nr), data->zone[nr].critical); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define temp_auto(offset) \ @@ -1149,7 +1150,7 @@ static int lm85_detect(struct i2c_adapter *adapter, int address, /* Fill in the remaining client fields */ data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -1368,7 +1369,7 @@ static struct lm85_data *lm85_update_device(struct device *dev) struct lm85_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if ( !data->valid || time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL) ) { @@ -1571,7 +1572,7 @@ static struct lm85_data *lm85_update_device(struct device *dev) data->valid = 1; - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 6ba34c302d8d..e229daf666de 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -60,6 +60,7 @@ #include #include #include +#include /* * Addresses to scan @@ -176,7 +177,7 @@ static struct i2c_driver lm87_driver = { struct lm87_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -253,11 +254,11 @@ static void set_in_min(struct device *dev, const char *buf, int nr) struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val, data->in_scale[nr]); lm87_write_value(client, nr<6 ? LM87_REG_IN_MIN(nr) : LM87_REG_AIN_MIN(nr-6), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } static void set_in_max(struct device *dev, const char *buf, int nr) @@ -266,11 +267,11 @@ static void set_in_max(struct device *dev, const char *buf, int nr) struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val, data->in_scale[nr]); lm87_write_value(client, nr<6 ? LM87_REG_IN_MAX(nr) : LM87_REG_AIN_MAX(nr-6), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } #define set_in(offset) \ @@ -327,10 +328,10 @@ static void set_temp_low(struct device *dev, const char *buf, int nr) struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_low[nr] = TEMP_TO_REG(val); lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } static void set_temp_high(struct device *dev, const char *buf, int nr) @@ -339,10 +340,10 @@ static void set_temp_high(struct device *dev, const char *buf, int nr) struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_high[nr] = TEMP_TO_REG(val); lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } #define set_temp(offset) \ @@ -411,11 +412,11 @@ static void set_fan_min(struct device *dev, const char *buf, int nr) struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); } /* Note: we save and restore the fan minimum here, because its value is @@ -431,7 +432,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, unsigned long min; u8 reg; - down(&data->update_lock); + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], FAN_DIV_FROM_REG(data->fan_div[nr])); @@ -441,7 +442,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, case 4: data->fan_div[nr] = 2; break; case 8: data->fan_div[nr] = 3; break; default: - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -459,7 +460,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, data->fan_min[nr] = FAN_TO_REG(min, val); lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -522,10 +523,10 @@ static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->aout = AOUT_TO_REG(val); lm87_write_value(client, LM87_REG_AOUT, data->aout); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); @@ -589,7 +590,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) /* We can fill in the remaining client fields */ strlcpy(new_client->name, "lm87", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -744,7 +745,7 @@ static struct lm87_data *lm87_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm87_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { int i, j; @@ -813,7 +814,7 @@ static struct lm87_data *lm87_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 5679464447cc..d9eeaf7585bd 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -78,6 +78,7 @@ #include #include #include +#include /* * Addresses to scan @@ -201,7 +202,7 @@ static struct i2c_driver lm90_driver = { struct lm90_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ int kind; @@ -247,13 +248,13 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, long val = simple_strtol(buf, NULL, 10); int nr = attr->index; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (data->kind == adt7461) data->temp8[nr] = TEMP1_TO_REG_ADT7461(val); else data->temp8[nr] = TEMP1_TO_REG(val); i2c_smbus_write_byte_data(client, reg[nr - 1], data->temp8[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -281,7 +282,7 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, long val = simple_strtol(buf, NULL, 10); int nr = attr->index; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (data->kind == adt7461) data->temp11[nr] = TEMP2_TO_REG_ADT7461(val); else @@ -290,7 +291,7 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, data->temp11[nr] >> 8); i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], data->temp11[nr] & 0xff); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -311,11 +312,11 @@ static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy, long val = simple_strtol(buf, NULL, 10); long hyst; - down(&data->update_lock); + mutex_lock(&data->update_lock); hyst = TEMP1_FROM_REG(data->temp8[3]) - val; i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST, HYST_TO_REG(hyst)); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -558,7 +559,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; data->kind = kind; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -646,7 +647,7 @@ static struct lm90_data *lm90_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm90_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { u8 oldh, newh, l; @@ -692,7 +693,7 @@ static struct lm90_data *lm90_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index b0c4cb730a7e..197f77226dc4 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c @@ -46,6 +46,7 @@ #include #include #include +#include /* The LM92 and MAX6635 have 2 two-state pins for address selection, resulting in 4 possible addresses. */ @@ -96,7 +97,7 @@ static struct i2c_driver lm92_driver; struct lm92_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -114,7 +115,7 @@ static struct lm92_data *lm92_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct lm92_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { @@ -134,7 +135,7 @@ static struct lm92_data *lm92_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -158,10 +159,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co struct lm92_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = TEMP_TO_REG(val); \ i2c_smbus_write_word_data(client, reg, swab16(data->value)); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } set_temp(temp1_crit, LM92_REG_TEMP_CRIT); @@ -194,11 +195,11 @@ static ssize_t set_temp1_crit_hyst(struct device *dev, struct device_attribute * struct lm92_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val; i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST, swab16(TEMP_TO_REG(data->temp1_hyst))); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -348,7 +349,7 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) /* Fill in the remaining client fields */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the i2c subsystem a new client has arrived */ if ((err = i2c_attach_client(new_client))) diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index 3abe330b22ce..b4135b5971f4 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c @@ -33,6 +33,7 @@ #include #include #include +#include static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, @@ -104,7 +105,7 @@ static struct i2c_driver max1619_driver = { struct max1619_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -141,10 +142,10 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co struct max1619_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->value = TEMP_TO_REG(val); \ i2c_smbus_write_byte_data(client, reg, data->value); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } @@ -262,7 +263,7 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) /* We can fill in the remaining client fields */ strlcpy(new_client->name, name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -330,7 +331,7 @@ static struct max1619_data *max1619_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct max1619_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { dev_dbg(&client->dev, "Updating max1619 data.\n"); @@ -353,7 +354,7 @@ static struct max1619_data *max1619_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 2de69322f525..ae05e483a778 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -43,6 +43,7 @@ #include #include #include +#include #include static u8 devid; @@ -183,8 +184,8 @@ static inline u8 PWM_TO_REG(int val, int inv) struct pc87360_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; - struct semaphore update_lock; + struct mutex lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -283,7 +284,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, struct pc87360_data *data = i2c_get_clientdata(client); long fan_min = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index])); /* If it wouldn't fit, change clock divisor */ @@ -300,7 +301,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, /* Write new divider, preserve alarm bits */ pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index), data->fan_status[attr->index] & 0xF9); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -343,12 +344,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, con struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[attr->index] = PWM_TO_REG(val, FAN_CONFIG_INVERT(data->fan_conf, attr->index)); pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index), data->pwm[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -393,11 +394,11 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN, data->in_min[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf, @@ -408,12 +409,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[attr->index] = IN_TO_REG(val, data->in_vref); pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX, data->in_max[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -512,11 +513,11 @@ static ssize_t set_therm_min(struct device *dev, struct device_attribute *devatt struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN, data->in_min[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf, @@ -527,11 +528,11 @@ static ssize_t set_therm_max(struct device *dev, struct device_attribute *devatt struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[attr->index] = IN_TO_REG(val, data->in_vref); pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX, data->in_max[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf, @@ -542,11 +543,11 @@ static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devat struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref); pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT, data->in_crit[attr->index-11]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -654,11 +655,11 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[attr->index] = TEMP_TO_REG(val); pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN, data->temp_min[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf, @@ -669,11 +670,11 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[attr->index] = TEMP_TO_REG(val); pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX, data->temp_max[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf, @@ -684,11 +685,11 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devatt struct pc87360_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_crit[attr->index] = TEMP_TO_REG(val); pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT, data->temp_crit[attr->index]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -845,7 +846,7 @@ static int pc87360_detect(struct i2c_adapter *adapter) dev = &client->dev; i2c_set_clientdata(client, data); client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); client->adapter = adapter; client->driver = &pc87360_driver; client->flags = 0; @@ -878,7 +879,7 @@ static int pc87360_detect(struct i2c_adapter *adapter) strlcpy(client->name, name, sizeof(client->name)); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); for (i = 0; i < 3; i++) { if (((data->address[i] = extra_isa[i])) @@ -1027,11 +1028,11 @@ static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, { int res; - down(&(data->lock)); + mutex_lock(&(data->lock)); if (bank != NO_BANK) outb_p(bank, data->address[ldi] + PC87365_REG_BANK); res = inb_p(data->address[ldi] + reg); - up(&(data->lock)); + mutex_unlock(&(data->lock)); return res; } @@ -1039,11 +1040,11 @@ static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, u8 reg, u8 value) { - down(&(data->lock)); + mutex_lock(&(data->lock)); if (bank != NO_BANK) outb_p(bank, data->address[ldi] + PC87365_REG_BANK); outb_p(value, data->address[ldi] + reg); - up(&(data->lock)); + mutex_unlock(&(data->lock)); } static void pc87360_init_client(struct i2c_client *client, int use_thermistors) @@ -1215,7 +1216,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) struct pc87360_data *data = i2c_get_clientdata(client); u8 i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { dev_dbg(&client->dev, "Data update\n"); @@ -1315,7 +1316,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 8be5189d9bd9..4db0dd871eee 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -60,6 +60,7 @@ #include #include #include +#include #include @@ -167,9 +168,9 @@ static inline u8 DIV_TO_REG(int val) struct sis5595_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ char maxins; /* == 3 if temp enabled, otherwise == 4 */ @@ -231,10 +232,10 @@ static ssize_t set_in_min(struct device *dev, const char *buf, struct sis5595_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val); sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -245,10 +246,10 @@ static ssize_t set_in_max(struct device *dev, const char *buf, struct sis5595_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val); sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -310,10 +311,10 @@ static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, struct sis5595_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_over = TEMP_TO_REG(val); sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -329,10 +330,10 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, struct sis5595_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_hyst = TEMP_TO_REG(val); sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -364,10 +365,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct sis5595_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -390,7 +391,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, unsigned long val = simple_strtoul(buf, NULL, 10); int reg; - down(&data->update_lock); + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); reg = sis5595_read_value(client, SIS5595_REG_FANDIV); @@ -403,7 +404,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, default: dev_err(&client->dev, "fan_div value %ld not " "supported. Choose one of 1, 2, 4 or 8!\n", val); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -419,7 +420,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -527,7 +528,7 @@ static int sis5595_detect(struct i2c_adapter *adapter) new_client = &data->client; new_client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); i2c_set_clientdata(new_client, data); new_client->adapter = adapter; new_client->driver = &sis5595_driver; @@ -548,7 +549,7 @@ static int sis5595_detect(struct i2c_adapter *adapter) strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -635,20 +636,20 @@ static int sis5595_read_value(struct i2c_client *client, u8 reg) int res; struct sis5595_data *data = i2c_get_clientdata(client); - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return res; } static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value) { struct sis5595_data *data = i2c_get_clientdata(client); - down(&data->lock); + mutex_lock(&data->lock); outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return 0; } @@ -667,7 +668,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev) struct sis5595_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -707,7 +708,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index 8663bbbe97f5..b6086186d225 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -35,6 +35,7 @@ #include #include #include +#include #include /* Address is autodetected, there is no default value */ @@ -92,9 +93,9 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80}; struct smsc47b397_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; - struct semaphore update_lock; + struct mutex update_lock; unsigned long last_updated; /* in jiffies */ int valid; @@ -108,10 +109,10 @@ static int smsc47b397_read_value(struct i2c_client *client, u8 reg) struct smsc47b397_data *data = i2c_get_clientdata(client); int res; - down(&data->lock); + mutex_lock(&data->lock); outb(reg, client->addr); res = inb_p(client->addr + 1); - up(&data->lock); + mutex_unlock(&data->lock); return res; } @@ -121,7 +122,7 @@ static struct smsc47b397_data *smsc47b397_update_device(struct device *dev) struct smsc47b397_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { dev_dbg(&client->dev, "starting device update...\n"); @@ -144,7 +145,7 @@ static struct smsc47b397_data *smsc47b397_update_device(struct device *dev) dev_dbg(&client->dev, "... device update complete\n"); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -254,14 +255,14 @@ static int smsc47b397_detect(struct i2c_adapter *adapter) new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); new_client->adapter = adapter; new_client->driver = &smsc47b397_driver; new_client->flags = 0; strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); if ((err = i2c_attach_client(new_client))) goto error_free; diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index d1e3ec0fe4df..7732aec54594 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -34,6 +34,7 @@ #include #include #include +#include #include /* Address is autodetected, there is no default value */ @@ -102,9 +103,9 @@ superio_exit(void) struct smsc47m1_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; - struct semaphore update_lock; + struct mutex update_lock; unsigned long last_updated; /* In jiffies */ u8 fan[2]; /* Register value */ @@ -188,18 +189,18 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct smsc47m1_data *data = i2c_get_clientdata(client); long rpmdiv, val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]); if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040) { - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv); smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), data->fan_preload[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -220,14 +221,14 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, if (new_div == old_div) /* No change */ return count; - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (new_div) { case 1: data->fan_div[nr] = 0; break; case 2: data->fan_div[nr] = 1; break; case 4: data->fan_div[nr] = 2; break; case 8: data->fan_div[nr] = 3; break; default: - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -241,7 +242,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191); smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), data->fan_preload[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -257,12 +258,12 @@ static ssize_t set_pwm(struct device *dev, const char *buf, if (val < 0 || val > 255) return -EINVAL; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[nr] &= 0x81; /* Preserve additional bits */ data->pwm[nr] |= PWM_TO_REG(val); smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), data->pwm[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -278,12 +279,12 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf, if (val != 0 && val != 1) return -EINVAL; - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[nr] &= 0xFE; /* preserve the other bits */ data->pwm[nr] |= !val; smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), data->pwm[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -408,13 +409,13 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); new_client->adapter = adapter; new_client->driver = &smsc47m1_driver; new_client->flags = 0; strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* If no function is properly configured, there's no point in actually registering the chip. */ @@ -512,17 +513,17 @@ static int smsc47m1_read_value(struct i2c_client *client, u8 reg) { int res; - down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); res = inb_p(client->addr + reg); - up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); return res; } static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value) { - down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); outb_p(value, client->addr + reg); - up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); } static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, @@ -531,7 +532,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct smsc47m1_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { int i; @@ -558,7 +559,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, data->last_updated = jiffies; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index cb01848729b5..166298f1f190 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -296,7 +297,7 @@ static inline long TEMP_FROM_REG10(u16 val) struct via686a_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -355,11 +356,11 @@ static ssize_t set_in_min(struct device *dev, const char *buf, struct via686a_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val, nr); via686a_write_value(client, VIA686A_REG_IN_MIN(nr), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_in_max(struct device *dev, const char *buf, @@ -368,11 +369,11 @@ static ssize_t set_in_max(struct device *dev, const char *buf, struct via686a_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val, nr); via686a_write_value(client, VIA686A_REG_IN_MAX(nr), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_in_offset(offset) \ @@ -432,11 +433,11 @@ static ssize_t set_temp_over(struct device *dev, const char *buf, struct via686a_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_over[nr] = TEMP_TO_REG(val); via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr], data->temp_over[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp_hyst(struct device *dev, const char *buf, @@ -445,11 +446,11 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf, struct via686a_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_hyst[nr] = TEMP_TO_REG(val); via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr], data->temp_hyst[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } #define show_temp_offset(offset) \ @@ -508,10 +509,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, struct via686a_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); via686a_write_value(client, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_fan_div(struct device *dev, const char *buf, @@ -521,12 +522,12 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, int val = simple_strtol(buf, NULL, 10); int old; - down(&data->update_lock); + mutex_lock(&data->update_lock); old = via686a_read_value(client, VIA686A_REG_FANDIV); data->fan_div[nr] = DIV_TO_REG(val); old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); via686a_write_value(client, VIA686A_REG_FANDIV, old); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -639,7 +640,7 @@ static int via686a_detect(struct i2c_adapter *adapter) strlcpy(new_client->name, client_name, I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) goto exit_free; @@ -733,7 +734,7 @@ static struct via686a_data *via686a_update_device(struct device *dev) struct via686a_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -788,7 +789,7 @@ static struct via686a_data *via686a_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 271e9cb9532c..686f3deb3093 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -35,6 +35,7 @@ #include #include #include +#include #include static int force_addr; @@ -148,7 +149,7 @@ static inline u8 FAN_TO_REG(long rpm, int div) struct vt8231_data { struct i2c_client client; - struct semaphore update_lock; + struct mutex update_lock; struct class_device *class_dev; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -223,10 +224,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); vt8231_write_value(client, regvoltmin[nr], data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -239,10 +240,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); vt8231_write_value(client, regvoltmax[nr], data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -281,11 +282,11 @@ static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, 0, 255); vt8231_write_value(client, regvoltmin[5], data->in_min[5]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -296,11 +297,11 @@ static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, 0, 255); vt8231_write_value(client, regvoltmax[5], data->in_max[5]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -351,10 +352,10 @@ static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); vt8231_write_value(client, regtempmax[0], data->temp_max[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr, @@ -364,10 +365,10 @@ static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); vt8231_write_value(client, regtempmin[0], data->temp_min[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -407,10 +408,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); vt8231_write_value(client, regtempmax[nr], data->temp_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, @@ -422,10 +423,10 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); vt8231_write_value(client, regtempmin[nr], data->temp_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -520,10 +521,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = i2c_get_clientdata(client); int val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -539,7 +540,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, long min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (val) { case 1: data->fan_div[nr] = 0; break; case 2: data->fan_div[nr] = 1; break; @@ -548,7 +549,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, default: dev_err(&client->dev, "fan_div value %ld not supported." "Choose one of 1, 2, 4 or 8!\n", val); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -558,7 +559,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); vt8231_write_value(client, VT8231_REG_FANDIV, old); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -660,7 +661,7 @@ int vt8231_detect(struct i2c_adapter *adapter) /* Fill in the remaining client fields and put into the global list */ strlcpy(client->name, "vt8231", I2C_NAME_SIZE); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(client))) @@ -745,7 +746,7 @@ static struct vt8231_data *vt8231_update_device(struct device *dev) int i; u16 low; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -804,7 +805,7 @@ static struct vt8231_data *vt8231_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 12d79f5e4900..1affaf15beda 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "lm75.h" @@ -177,9 +178,9 @@ temp1_to_reg(int temp) struct w83627ehf_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -230,7 +231,7 @@ static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg) struct w83627ehf_data *data = i2c_get_clientdata(client); int res, word_sized = is_word_sized(reg); - down(&data->lock); + mutex_lock(&data->lock); w83627ehf_set_bank(client, reg); outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); @@ -242,7 +243,7 @@ static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg) } w83627ehf_reset_bank(client, reg); - up(&data->lock); + mutex_unlock(&data->lock); return res; } @@ -252,7 +253,7 @@ static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value) struct w83627ehf_data *data = i2c_get_clientdata(client); int word_sized = is_word_sized(reg); - down(&data->lock); + mutex_lock(&data->lock); w83627ehf_set_bank(client, reg); outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); @@ -264,7 +265,7 @@ static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value) outb_p(value & 0xff, client->addr + DATA_REG_OFFSET); w83627ehf_reset_bank(client, reg); - up(&data->lock); + mutex_unlock(&data->lock); return 0; } @@ -322,7 +323,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) struct w83627ehf_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { @@ -397,7 +398,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -434,7 +435,7 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) unsigned int reg; u8 new_div; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (!val) { /* No min limit, alarm disabled */ data->fan_min[nr] = 255; @@ -482,7 +483,7 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) } w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr], data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -561,11 +562,11 @@ store_temp1_##reg(struct device *dev, struct device_attribute *attr, \ struct w83627ehf_data *data = i2c_get_clientdata(client); \ u32 val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->temp1_##reg = temp1_to_reg(val); \ w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \ data->temp1_##reg); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_temp1_reg(OVER, max); @@ -597,11 +598,11 @@ store_##reg (struct device *dev, const char *buf, size_t count, int nr) \ struct w83627ehf_data *data = i2c_get_clientdata(client); \ u32 val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->reg[nr] = LM75_TEMP_TO_REG(val); \ w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \ data->reg[nr]); \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_temp_reg(OVER, temp_max); @@ -689,14 +690,14 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) client = &data->client; i2c_set_clientdata(client, data); client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); client->adapter = adapter; client->driver = &w83627ehf_driver; client->flags = 0; strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the i2c layer a new client has arrived */ if ((err = i2c_attach_client(client))) diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 7ea441d4da63..3d4888c178c9 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include "lm75.h" @@ -285,10 +286,10 @@ static inline u8 DIV_TO_REG(long val) struct w83627hf_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -360,12 +361,12 @@ store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ \ val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->in_##reg[nr] = IN_TO_REG(val); \ w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \ data->in_##reg[nr]); \ \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_in_reg(MIN, min) @@ -451,7 +452,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((data->vrm_ovt & 0x01) && (w83627thf == data->type || w83637hf == data->type)) @@ -465,7 +466,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a data->in_min[0] = IN_TO_REG(val); w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -478,7 +479,7 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if ((data->vrm_ovt & 0x01) && (w83627thf == data->type || w83637hf == data->type)) @@ -492,7 +493,7 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a data->in_max[0] = IN_TO_REG(val); w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -529,13 +530,13 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr - 1] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr), data->fan_min[nr - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -597,7 +598,7 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ \ val = simple_strtoul(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ \ if (nr >= 2) { /* TEMP2 and TEMP3 */ \ data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ @@ -609,7 +610,7 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ data->temp_##reg); \ } \ \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_temp_reg(OVER, max); @@ -718,7 +719,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count, val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ data->beep_mask = BEEP_MASK_TO_REG(val); @@ -736,7 +737,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count, w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, val2 | data->beep_enable << 7); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -783,7 +784,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) u8 reg; unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); /* Save fan_min */ min = FAN_FROM_REG(data->fan_min[nr], @@ -805,7 +806,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -848,7 +849,7 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (data->type == w83627thf) { /* bits 0-3 are reserved in 627THF */ @@ -865,7 +866,7 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) data->pwm[nr - 1]); } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -907,7 +908,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (val) { case 1: /* PII/Celeron diode */ @@ -941,7 +942,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) break; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1057,7 +1058,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter) new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); new_client->adapter = adapter; new_client->driver = &w83627hf_driver; new_client->flags = 0; @@ -1077,7 +1078,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter) strlcpy(new_client->name, client_name, I2C_NAME_SIZE); data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -1187,7 +1188,7 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg) struct w83627hf_data *data = i2c_get_clientdata(client); int res, word_sized; - down(&data->lock); + mutex_lock(&data->lock); word_sized = (((reg & 0xff00) == 0x100) || ((reg & 0xff00) == 0x200)) && (((reg & 0x00ff) == 0x50) @@ -1213,7 +1214,7 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg) client->addr + W83781D_ADDR_REG_OFFSET); outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); } - up(&data->lock); + mutex_unlock(&data->lock); return res; } @@ -1252,7 +1253,7 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) struct w83627hf_data *data = i2c_get_clientdata(client); int word_sized; - down(&data->lock); + mutex_lock(&data->lock); word_sized = (((reg & 0xff00) == 0x100) || ((reg & 0xff00) == 0x200)) && (((reg & 0x00ff) == 0x53) @@ -1277,7 +1278,7 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) client->addr + W83781D_ADDR_REG_OFFSET); outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); } - up(&data->lock); + mutex_unlock(&data->lock); return 0; } @@ -1387,7 +1388,7 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) struct w83627hf_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -1470,7 +1471,7 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 64c1f8af5bb2..782117817526 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "lm75.h" @@ -226,10 +227,10 @@ DIV_TO_REG(long val, enum chips type) struct w83781d_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore lock; + struct mutex lock; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -311,11 +312,11 @@ static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count \ val = simple_strtoul(buf, NULL, 10) / 10; \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ data->in_##reg[nr] = IN_TO_REG(val); \ w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \ \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_in_reg(MIN, min); @@ -381,13 +382,13 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_min[nr - 1] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); w83781d_write_value(client, W83781D_REG_FAN_MIN(nr), data->fan_min[nr - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -446,7 +447,7 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou \ val = simple_strtol(buf, NULL, 10); \ \ - down(&data->update_lock); \ + mutex_lock(&data->update_lock); \ \ if (nr >= 2) { /* TEMP2 and TEMP3 */ \ data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ @@ -458,7 +459,7 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou data->temp_##reg); \ } \ \ - up(&data->update_lock); \ + mutex_unlock(&data->update_lock); \ return count; \ } store_temp_reg(OVER, max); @@ -571,7 +572,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count, val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ data->beep_mask = BEEP_MASK_TO_REG(val, data->type); @@ -592,7 +593,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count, w83781d_write_value(client, W83781D_REG_BEEP_INTS2, val2 | data->beep_enable << 7); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -637,7 +638,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) u8 reg; unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); /* Save fan_min */ min = FAN_FROM_REG(data->fan_min[nr], @@ -662,7 +663,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -709,10 +710,10 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->pwm[nr - 1] = PWM_TO_REG(val); w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -725,7 +726,7 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (val) { case 0: @@ -742,11 +743,11 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) break; default: - up(&data->update_lock); + mutex_unlock(&data->update_lock); return -EINVAL; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -808,7 +809,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); switch (val) { case 1: /* PII/Celeron diode */ @@ -841,7 +842,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) break; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -1073,7 +1074,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; - init_MUTEX(&data->lock); + mutex_init(&data->lock); new_client->adapter = adapter; new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver; new_client->flags = 0; @@ -1178,7 +1179,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) @@ -1325,7 +1326,7 @@ w83781d_read_value(struct i2c_client *client, u16 reg) int res, word_sized, bank; struct i2c_client *cl; - down(&data->lock); + mutex_lock(&data->lock); if (i2c_is_isa_client(client)) { word_sized = (((reg & 0xff00) == 0x100) || ((reg & 0xff00) == 0x200)) @@ -1383,7 +1384,7 @@ w83781d_read_value(struct i2c_client *client, u16 reg) if (bank > 2) i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); } - up(&data->lock); + mutex_unlock(&data->lock); return res; } @@ -1394,7 +1395,7 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) int word_sized, bank; struct i2c_client *cl; - down(&data->lock); + mutex_lock(&data->lock); if (i2c_is_isa_client(client)) { word_sized = (((reg & 0xff00) == 0x100) || ((reg & 0xff00) == 0x200)) @@ -1447,7 +1448,7 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) if (bank > 2) i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); } - up(&data->lock); + mutex_unlock(&data->lock); return 0; } @@ -1533,7 +1534,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) struct w83781d_data *data = i2c_get_clientdata(client); int i; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -1641,7 +1642,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 2e86e188b27a..6865c64d8a51 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -43,6 +43,7 @@ #include #include #include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; @@ -271,7 +272,7 @@ struct w83792d_data { struct class_device *class_dev; enum chips type; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -1222,7 +1223,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) data->type = kind; data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(client))) @@ -1373,7 +1374,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) int i, j; u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after (jiffies - data->last_updated, (unsigned long) (HZ * 3)) @@ -1484,7 +1485,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); #ifdef DEBUG w83792d_print_debug(data, dev); diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c index f66c0cfdeda7..3f2bac125fb1 100644 --- a/drivers/hwmon/w83l785ts.c +++ b/drivers/hwmon/w83l785ts.c @@ -39,6 +39,7 @@ #include #include #include +#include /* How many retries on register read error */ #define MAX_RETRIES 5 @@ -107,7 +108,7 @@ static struct i2c_driver w83l785ts_driver = { struct w83l785ts_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -221,7 +222,7 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind) /* We can fill in the remaining client fields. */ strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE); data->valid = 0; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Default values in case the first read fails (unlikely). */ data->temp[1] = data->temp[0] = 0; @@ -299,7 +300,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct w83l785ts_data *data = i2c_get_clientdata(client); - down(&data->update_lock); + mutex_lock(&data->update_lock); if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) { dev_dbg(&client->dev, "Updating w83l785ts data.\n"); @@ -312,7 +313,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } -- cgit v1.2.3-59-g8ed1b From f08191849e42e67ab6ad556d9c2e8cbed1ddf303 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 18 Jan 2006 23:20:53 +0100 Subject: [PATCH] hwmon: f71805f semaphore to mutex conversions Convert the new f71805f hardware monitoring driver to use mutexes instead of semaphores. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/f71805f.c | 57 +++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 8e810f05d0ae..885465df6e6a 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -30,6 +30,7 @@ #include #include #include +#include #include static struct platform_device *pdev; @@ -131,10 +132,10 @@ static struct resource f71805f_resource __initdata = { struct f71805f_data { unsigned short addr; const char *name; - struct semaphore lock; + struct mutex lock; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ unsigned long last_limits; /* In jiffies */ @@ -224,20 +225,20 @@ static u8 f71805f_read8(struct f71805f_data *data, u8 reg) { u8 val; - down(&data->lock); + mutex_lock(&data->lock); outb(reg, data->addr + ADDR_REG_OFFSET); val = inb(data->addr + DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return val; } static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val) { - down(&data->lock); + mutex_lock(&data->lock); outb(reg, data->addr + ADDR_REG_OFFSET); outb(val, data->addr + DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); } /* It is important to read the MSB first, because doing so latches the @@ -246,24 +247,24 @@ static u16 f71805f_read16(struct f71805f_data *data, u8 reg) { u16 val; - down(&data->lock); + mutex_lock(&data->lock); outb(reg, data->addr + ADDR_REG_OFFSET); val = inb(data->addr + DATA_REG_OFFSET) << 8; outb(++reg, data->addr + ADDR_REG_OFFSET); val |= inb(data->addr + DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); return val; } static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) { - down(&data->lock); + mutex_lock(&data->lock); outb(reg, data->addr + ADDR_REG_OFFSET); outb(val >> 8, data->addr + DATA_REG_OFFSET); outb(++reg, data->addr + ADDR_REG_OFFSET); outb(val & 0xff, data->addr + DATA_REG_OFFSET); - up(&data->lock); + mutex_unlock(&data->lock); } static struct f71805f_data *f71805f_update_device(struct device *dev) @@ -271,7 +272,7 @@ static struct f71805f_data *f71805f_update_device(struct device *dev) struct f71805f_data *data = dev_get_drvdata(dev); int nr; - down(&data->update_lock); + mutex_lock(&data->update_lock); /* Limit registers cache is refreshed after 60 seconds */ if (time_after(jiffies, data->last_updated + 60 * HZ) @@ -323,7 +324,7 @@ static struct f71805f_data *f71805f_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } @@ -362,10 +363,10 @@ static ssize_t set_in0_max(struct device *dev, struct device_attribute struct f71805f_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_high[0] = in0_to_reg(val); f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -376,10 +377,10 @@ static ssize_t set_in0_min(struct device *dev, struct device_attribute struct f71805f_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_low[0] = in0_to_reg(val); f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -422,10 +423,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute int nr = attr->index; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_high[nr] = in_to_reg(val); f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -438,10 +439,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute int nr = attr->index; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_low[nr] = in_to_reg(val); f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -474,10 +475,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute int nr = attr->index; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->fan_low[nr] = fan_to_reg(val); f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -531,10 +532,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute int nr = attr->index; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_high[nr] = temp_to_reg(val); f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -547,10 +548,10 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute int nr = attr->index; long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_hyst[nr] = temp_to_reg(val); f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -711,9 +712,9 @@ static int __devinit f71805f_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_IO, 0); data->addr = res->start; - init_MUTEX(&data->lock); + mutex_init(&data->lock); data->name = "f71805f"; - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); platform_set_drvdata(pdev, data); -- cgit v1.2.3-59-g8ed1b From c2db6ce14a743ac5f8973124272cf425c4f86b90 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 18 Jan 2006 23:22:12 +0100 Subject: [PATCH] hwmon: Add support for the Winbond W83687THF Add support for the Winbond W83687THF chip to the w83627hf hardware monitoring driver. This new chip is almost similar to the already supported W83627THF chip, except for VID and a few other minor changes. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/w83627hf | 4 +++ drivers/hwmon/Kconfig | 7 +++-- drivers/hwmon/w83627hf.c | 72 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 66 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/Documentation/hwmon/w83627hf b/Documentation/hwmon/w83627hf index bbeaba680443..792231921241 100644 --- a/Documentation/hwmon/w83627hf +++ b/Documentation/hwmon/w83627hf @@ -18,6 +18,10 @@ Supported chips: Prefix: 'w83637hf' Addresses scanned: ISA address retrieved from Super I/O registers Datasheet: http://www.winbond.com/PDF/sheet/w83637hf.pdf + * Winbond W83687THF + Prefix: 'w83687thf' + Addresses scanned: ISA address retrieved from Super I/O registers + Datasheet: Provided by Winbond on request Authors: Frodo Looijaard , diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 7230d4e08196..99cdc612d2c6 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -406,13 +406,14 @@ config SENSORS_W83L785TS will be called w83l785ts. config SENSORS_W83627HF - tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF" - depends on HWMON && I2C && EXPERIMENTAL + tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" + depends on HWMON && I2C select I2C_ISA select HWMON_VID help If you say yes here you get support for the Winbond W836X7 series - of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF + of sensor chips: the W83627HF, W83627THF, W83637HF, W83687THF and + W83697HF. This driver can also be built as a module. If so, the module will be called w83627hf. diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 3d4888c178c9..992e34402705 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -28,6 +28,7 @@ w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) + w83687thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC) For other winbond chips, and for i2c support in the above chips, @@ -63,7 +64,7 @@ MODULE_PARM_DESC(force_i2c, static unsigned short address; /* Insmod parameters */ -enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf }; +enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; static int reset; module_param(reset, bool, 0); @@ -101,6 +102,10 @@ static int VAL; /* The value to read/write */ #define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */ #define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */ +#define W83687THF_VID_EN 0x29 /* w83687thf only */ +#define W83687THF_VID_CFG 0xF0 /* w83687thf only */ +#define W83687THF_VID_DATA 0xF1 /* w83687thf only */ + static inline void superio_outb(int reg, int val) { @@ -139,6 +144,7 @@ superio_exit(void) #define W627THF_DEVID 0x82 #define W697_DEVID 0x60 #define W637_DEVID 0x70 +#define W687THF_DEVID 0x85 #define WINB_ACT_REG 0x30 #define WINB_BASE_REG 0x60 /* Constants specified below */ @@ -202,11 +208,11 @@ superio_exit(void) #define W83627HF_REG_PWM1 0x5A #define W83627HF_REG_PWM2 0x5B -#define W83627THF_REG_PWM1 0x01 /* 697HF and 637HF too */ -#define W83627THF_REG_PWM2 0x03 /* 697HF and 637HF too */ -#define W83627THF_REG_PWM3 0x11 /* 637HF too */ +#define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */ +#define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */ +#define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */ -#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF too */ +#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF/687THF too */ static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 }; static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2, @@ -319,7 +325,7 @@ struct w83627hf_data { Default = 3435. Other Betas unimplemented */ u8 vrm; - u8 vrm_ovt; /* Register value, 627thf & 637hf only */ + u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ }; @@ -414,7 +420,8 @@ static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg) long in0; if ((data->vrm_ovt & 0x01) && - (w83627thf == data->type || w83637hf == data->type)) + (w83627thf == data->type || w83637hf == data->type + || w83687thf == data->type)) /* use VRM9 calculation */ in0 = (long)((reg * 488 + 70000 + 50) / 100); @@ -455,7 +462,8 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a mutex_lock(&data->update_lock); if ((data->vrm_ovt & 0x01) && - (w83627thf == data->type || w83637hf == data->type)) + (w83627thf == data->type || w83637hf == data->type + || w83687thf == data->type)) /* use VRM9 calculation */ data->in_min[0] = @@ -482,7 +490,8 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a mutex_lock(&data->update_lock); if ((data->vrm_ovt & 0x01) && - (w83627thf == data->type || w83637hf == data->type)) + (w83627thf == data->type || w83637hf == data->type + || w83687thf == data->type)) /* use VRM9 calculation */ data->in_max[0] = @@ -981,7 +990,8 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr) if(val != W627_DEVID && val != W627THF_DEVID && val != W697_DEVID && - val != W637_DEVID) { + val != W637_DEVID && + val != W687THF_DEVID) { superio_exit(); return -ENODEV; } @@ -1035,6 +1045,8 @@ static int w83627hf_detect(struct i2c_adapter *adapter) kind = w83627thf; else if(val == W637_DEVID) kind = w83637hf; + else if (val == W687THF_DEVID) + kind = w83687thf; else { dev_info(&adapter->dev, "Unsupported chip (dev_id=0x%02X).\n", val); @@ -1072,6 +1084,8 @@ static int w83627hf_detect(struct i2c_adapter *adapter) client_name = "w83697hf"; } else if (kind == w83637hf) { client_name = "w83637hf"; + } else if (kind == w83687thf) { + client_name = "w83687thf"; } /* Fill in the remaining client fields and put into the global list */ @@ -1107,7 +1121,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter) device_create_file_in(new_client, 2); device_create_file_in(new_client, 3); device_create_file_in(new_client, 4); - if (kind != w83627thf && kind != w83637hf) { + if (kind == w83627hf || kind == w83697hf) { device_create_file_in(new_client, 5); device_create_file_in(new_client, 6); } @@ -1140,7 +1154,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter) device_create_file_pwm(new_client, 1); device_create_file_pwm(new_client, 2); - if (kind == w83627thf || kind == w83637hf) + if (kind == w83627thf || kind == w83637hf || kind == w83687thf) device_create_file_pwm(new_client, 3); device_create_file_sensor(new_client, 1); @@ -1248,6 +1262,33 @@ exit: return res; } +static int w83687thf_read_vid(struct i2c_client *client) +{ + int res = 0xff; + + superio_enter(); + superio_select(W83627HF_LD_HWM); + + /* Make sure these GPIO pins are enabled */ + if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) { + dev_dbg(&client->dev, "VID disabled, no VID function\n"); + goto exit; + } + + /* Make sure the pins are configured for input */ + if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) { + dev_dbg(&client->dev, "VID configured as output, " + "no VID function\n"); + goto exit; + } + + res = superio_inb(W83687THF_VID_DATA) & 0x3f; + +exit: + superio_exit(); + return res; +} + static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) { struct w83627hf_data *data = i2c_get_clientdata(client); @@ -1325,10 +1366,13 @@ static void w83627hf_init_client(struct i2c_client *client) data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); } else if (w83627thf == data->type) { data->vid = w83627thf_read_gpio5(client); + } else if (w83687thf == data->type) { + data->vid = w83687thf_read_vid(client); } /* Read VRM & OVT Config only once */ - if (w83627thf == data->type || w83637hf == data->type) { + if (w83627thf == data->type || w83637hf == data->type + || w83687thf == data->type) { data->vrm_ovt = w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); } @@ -1395,7 +1439,7 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) for (i = 0; i <= 8; i++) { /* skip missing sensors */ if (((data->type == w83697hf) && (i == 1)) || - ((data->type == w83627thf || data->type == w83637hf) + ((data->type != w83627hf && data->type != w83697hf) && (i == 5 || i == 6))) continue; data->in[i] = -- cgit v1.2.3-59-g8ed1b From 4c537fb287e68b84df685f4730348e83a163367b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 5 Feb 2006 23:21:05 +0100 Subject: [PATCH] hwmon: Support the Pentium M VID code Add support for the Intel Pentium M series to the hwmon-vid driver. Signed-off-by: Jean Delvare Cc: Rudolf Marek Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/hwmon-vid.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index e497274916ce..a74a44f16f51 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c @@ -54,6 +54,10 @@ (IMVP-II). You can find more information in the datasheet of Max1718 http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452 + The 13 specification corresponds to the Intel Pentium M series. There + 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 */ /* vrm is the VRM/VRD document version multiplied by 10. @@ -100,6 +104,8 @@ int vid_from_reg(int val, u8 vrm) case 17: /* Intel IMVP-II */ return(val & 0x10 ? 975 - (val & 0xF) * 25 : 1750 - val * 50); + case 13: + return(1708 - (val & 0x3f) * 16); default: /* report 0 for unknown */ printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n"); return 0; @@ -129,8 +135,9 @@ struct vrm_model { static struct vrm_model vrm_models[] = { {X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */ {X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */ - {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 85}, /* 0.13um too */ + {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, 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-59-g8ed1b From 412fec8216bb71ecbe255af702b0daf7ad55a7c4 Mon Sep 17 00:00:00 2001 From: Yuan Mu Date: Sun, 5 Feb 2006 23:24:16 +0100 Subject: [PATCH] w83627ehf: Refactor the sysfs interface Use dynamic sysfs callbacks and array of attributes to reduce the w83627ehf driver size. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83627ehf.c | 206 ++++++++++++++++++---------------------------- 1 file changed, 80 insertions(+), 126 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 1affaf15beda..b6bd5685fd38 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -408,9 +409,12 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) #define show_fan_reg(reg) \ static ssize_t \ -show_##reg(struct device *dev, char *buf, int nr) \ +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, "%d\n", \ fan_from_reg(data->reg[nr], \ div_from_reg(data->fan_div[nr]))); \ @@ -419,18 +423,23 @@ show_fan_reg(fan); show_fan_reg(fan_min); static ssize_t -show_fan_div(struct device *dev, char *buf, int nr) +show_fan_div(struct device *dev, struct device_attribute *attr, + char *buf) { struct w83627ehf_data *data = w83627ehf_update_device(dev); - return sprintf(buf, "%u\n", - div_from_reg(data->fan_div[nr])); + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr])); } static ssize_t -store_fan_min(struct device *dev, const char *buf, size_t count, int nr) +store_fan_min(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; unsigned int val = simple_strtoul(buf, NULL, 10); unsigned int reg; u8 new_div; @@ -488,58 +497,41 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) return count; } -#define sysfs_fan_offset(offset) \ -static ssize_t \ -show_reg_fan_##offset(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_fan(dev, buf, offset-1); \ -} \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_reg_fan_##offset, NULL); +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), +}; -#define sysfs_fan_min_offset(offset) \ -static ssize_t \ -show_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_fan_min(dev, buf, offset-1); \ -} \ -static ssize_t \ -store_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return store_fan_min(dev, buf, count, offset-1); \ -} \ -static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_reg_fan##offset##_min, \ - store_reg_fan##offset##_min); +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), +}; -#define sysfs_fan_div_offset(offset) \ -static ssize_t \ -show_reg_fan##offset##_div(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_fan_div(dev, buf, offset - 1); \ -} \ -static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \ - show_reg_fan##offset##_div, NULL); - -sysfs_fan_offset(1); -sysfs_fan_min_offset(1); -sysfs_fan_div_offset(1); -sysfs_fan_offset(2); -sysfs_fan_min_offset(2); -sysfs_fan_div_offset(2); -sysfs_fan_offset(3); -sysfs_fan_min_offset(3); -sysfs_fan_div_offset(3); -sysfs_fan_offset(4); -sysfs_fan_min_offset(4); -sysfs_fan_div_offset(4); -sysfs_fan_offset(5); -sysfs_fan_min_offset(5); -sysfs_fan_div_offset(5); +static struct sensor_device_attribute sda_fan_div[] = { + SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), + SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), + SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), + SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3), + SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4), +}; + +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_div[i].dev_attr); + device_create_file(dev, &sda_fan_min[i].dev_attr); +} #define show_temp1_reg(reg) \ static ssize_t \ @@ -572,17 +564,14 @@ store_temp1_##reg(struct device *dev, struct device_attribute *attr, \ store_temp1_reg(OVER, max); store_temp1_reg(HYST, max_hyst); -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL); -static DEVICE_ATTR(temp1_max, S_IRUGO| S_IWUSR, - show_temp1_max, store_temp1_max); -static DEVICE_ATTR(temp1_max_hyst, S_IRUGO| S_IWUSR, - show_temp1_max_hyst, store_temp1_max_hyst); - #define show_temp_reg(reg) \ static ssize_t \ -show_##reg (struct device *dev, char *buf, int nr) \ +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, "%d\n", \ LM75_TEMP_FROM_REG(data->reg[nr])); \ } @@ -592,10 +581,13 @@ show_temp_reg(temp_max_hyst); #define store_temp_reg(REG, reg) \ static ssize_t \ -store_##reg (struct device *dev, const char *buf, size_t count, int nr) \ +store_##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); \ @@ -608,39 +600,23 @@ store_##reg (struct device *dev, const char *buf, size_t count, int nr) \ store_temp_reg(OVER, temp_max); store_temp_reg(HYST, temp_max_hyst); -#define sysfs_temp_offset(offset) \ -static ssize_t \ -show_reg_temp##offset (struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_temp(dev, buf, offset - 2); \ -} \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_reg_temp##offset, NULL); - -#define sysfs_temp_reg_offset(reg, offset) \ -static ssize_t \ -show_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_temp_##reg(dev, buf, offset - 2); \ -} \ -static ssize_t \ -store_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return store_temp_##reg(dev, buf, count, offset - 2); \ -} \ -static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \ - show_reg_temp##offset##_##reg, \ - store_reg_temp##offset##_##reg); - -sysfs_temp_offset(2); -sysfs_temp_reg_offset(max, 2); -sysfs_temp_reg_offset(max_hyst, 2); -sysfs_temp_offset(3); -sysfs_temp_reg_offset(max, 3); -sysfs_temp_reg_offset(max_hyst, 3); +static struct sensor_device_attribute sda_temp[] = { + SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0), + SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0), + SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1), + SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max, + store_temp1_max, 0), + SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max, + store_temp_max, 0), + SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max, + store_temp_max, 1), + SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst, + store_temp1_max_hyst, 0), + SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, + store_temp_max_hyst, 0), + SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, + store_temp_max_hyst, 1), +}; /* * Driver and client management @@ -674,6 +650,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) { struct i2c_client *client; struct w83627ehf_data *data; + struct device *dev; int i, err = 0; if (!request_region(address + REGION_OFFSET, REGION_LENGTH, @@ -694,6 +671,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) client->adapter = adapter; client->driver = &w83627ehf_driver; client->flags = 0; + dev = &client->dev; strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE); data->valid = 0; @@ -721,42 +699,18 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) data->has_fan |= (1 << 4); /* Register sysfs hooks */ - data->class_dev = hwmon_device_register(&client->dev); + data->class_dev = hwmon_device_register(dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto exit_detach; } - device_create_file(&client->dev, &dev_attr_fan1_input); - device_create_file(&client->dev, &dev_attr_fan1_min); - device_create_file(&client->dev, &dev_attr_fan1_div); - device_create_file(&client->dev, &dev_attr_fan2_input); - device_create_file(&client->dev, &dev_attr_fan2_min); - device_create_file(&client->dev, &dev_attr_fan2_div); - device_create_file(&client->dev, &dev_attr_fan3_input); - device_create_file(&client->dev, &dev_attr_fan3_min); - device_create_file(&client->dev, &dev_attr_fan3_div); - - if (data->has_fan & (1 << 3)) { - device_create_file(&client->dev, &dev_attr_fan4_input); - device_create_file(&client->dev, &dev_attr_fan4_min); - device_create_file(&client->dev, &dev_attr_fan4_div); - } - if (data->has_fan & (1 << 4)) { - device_create_file(&client->dev, &dev_attr_fan5_input); - device_create_file(&client->dev, &dev_attr_fan5_min); - device_create_file(&client->dev, &dev_attr_fan5_div); + for (i = 0; i < 5; i++) { + if (data->has_fan & (1 << i)) + device_create_file_fan(dev, i); } - - device_create_file(&client->dev, &dev_attr_temp1_input); - device_create_file(&client->dev, &dev_attr_temp1_max); - device_create_file(&client->dev, &dev_attr_temp1_max_hyst); - device_create_file(&client->dev, &dev_attr_temp2_input); - device_create_file(&client->dev, &dev_attr_temp2_max); - device_create_file(&client->dev, &dev_attr_temp2_max_hyst); - device_create_file(&client->dev, &dev_attr_temp3_input); - device_create_file(&client->dev, &dev_attr_temp3_max); - device_create_file(&client->dev, &dev_attr_temp3_max_hyst); + for (i = 0; i < ARRAY_SIZE(sda_temp); i++) + device_create_file(dev, &sda_temp[i].dev_attr); return 0; -- cgit v1.2.3-59-g8ed1b From fabddcd49d8b4fca40ce346f701853888d98b5d2 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 5 Feb 2006 23:26:51 +0100 Subject: [PATCH] w83781d: Don't reset the chip by default Stop resetting the chip on load by default, so as to preserve the BIOS initializations. Same was done in the w83627hf driver some times ago for the same reasons. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/w83781d | 5 +++++ drivers/hwmon/w83781d.c | 22 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/hwmon/w83781d b/Documentation/hwmon/w83781d index ac155d8b0fef..b1e9f80098ee 100644 --- a/Documentation/hwmon/w83781d +++ b/Documentation/hwmon/w83781d @@ -36,6 +36,11 @@ Module parameters Use 'init=0' to bypass initializing the chip. Try this if your computer crashes when you load the module. +* reset int + (default 0) + The driver used to reset the chip on load, but does no more. Use + 'reset=1' to restore the old behavior. Report if you need to do this. + force_subclients=bus,caddr,saddr,saddr This is used to force the i2c addresses for subclients of a certain chip. Typical usage is `force_subclients=0,0x2d,0x4a,0x4b' diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 782117817526..8b17132f6b94 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -57,6 +57,10 @@ I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f); 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 reset chip on load"); + static int init = 1; module_param(init, bool, 0); MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); @@ -1460,8 +1464,17 @@ w83781d_init_client(struct i2c_client *client) int type = data->type; u8 tmp; - if (init && type != as99127f) { /* this resets registers we don't have + if (reset && type != as99127f) { /* this resets registers we don't have documentation for on the as99127f */ + /* Resetting the chip has been the default for a long time, + but it causes the BIOS initializations (fan clock dividers, + thermal sensor types...) to be lost, so it is now optional. + It might even go away if nobody reports it as being useful, + as I see very little reason why this would be needed at + all. */ + dev_info(&client->dev, "If reset=1 solved a problem you were " + "having, please report!\n"); + /* save these registers */ i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); p = w83781d_read_value(client, W83781D_REG_PWMCLK12); @@ -1478,6 +1491,13 @@ w83781d_init_client(struct i2c_client *client) w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0); } + /* Disable power-on abnormal beep, as advised by the datasheet. + Already done if reset=1. */ + if (init && !reset && type != as99127f) { + i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); + w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); + } + data->vrm = vid_which_vrm(); if ((type != w83781d) && (type != as99127f)) { -- cgit v1.2.3-59-g8ed1b From 7eebcb7c0f4d45168265bdca79cc3e609d68d436 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 5 Feb 2006 23:28:21 +0100 Subject: [PATCH] i2c: Optimize core_lists mutex usage Stop holding the core_lists mutex when we don't actually need it. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/i2c-core.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 975cb647da10..45e2cdf54736 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -288,9 +288,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) { struct list_head *item; struct i2c_adapter *adapter; - int res = 0; - - mutex_lock(&core_lists); + int res; /* add the driver to the list of i2c drivers in the driver core */ driver->driver.owner = owner; @@ -298,8 +296,10 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) res = driver_register(&driver->driver); if (res) - goto out_unlock; + return res; + mutex_lock(&core_lists); + list_add_tail(&driver->list,&drivers); pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); @@ -311,9 +311,8 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) } } - out_unlock: mutex_unlock(&core_lists); - return res; + return 0; } EXPORT_SYMBOL(i2c_register_driver); -- cgit v1.2.3-59-g8ed1b From 2f27f46c49c096d86e7e63acd43cad3bc42f2383 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 5 Feb 2006 23:29:18 +0100 Subject: [PATCH] i2c: Drop the i2c-frodo bus driver Drop the i2c-frodo bus driver. It isn't referenced by the build system, and depends on code which was never included in 2.6 kernels. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-frodo.c | 85 ------------------------------------------ include/linux/i2c-id.h | 1 - 2 files changed, 86 deletions(-) delete mode 100644 drivers/i2c/busses/i2c-frodo.c (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-frodo.c b/drivers/i2c/busses/i2c-frodo.c deleted file mode 100644 index b6f52f5a4138..000000000000 --- a/drivers/i2c/busses/i2c-frodo.c +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * linux/drivers/i2c/i2c-frodo.c - * - * Author: Abraham van der Merwe - * - * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110 - * Development board (Frodo). - * - * This source code 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 -#include -#include -#include -#include - - -static void frodo_setsda (void *data,int state) -{ - if (state) - FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT; - else - FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT; -} - -static void frodo_setscl (void *data,int state) -{ - if (state) - FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT; - else - FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT; -} - -static int frodo_getsda (void *data) -{ - return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0); -} - -static int frodo_getscl (void *data) -{ - return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0); -} - -static struct i2c_algo_bit_data bit_frodo_data = { - .setsda = frodo_setsda, - .setscl = frodo_setscl, - .getsda = frodo_getsda, - .getscl = frodo_getscl, - .udelay = 80, - .mdelay = 80, - .timeout = HZ -}; - -static struct i2c_adapter frodo_ops = { - .owner = THIS_MODULE, - .id = I2C_HW_B_FRODO, - .algo_data = &bit_frodo_data, - .dev = { - .name = "Frodo adapter driver", - }, -}; - -static int __init i2c_frodo_init (void) -{ - return i2c_bit_add_bus(&frodo_ops); -} - -static void __exit i2c_frodo_exit (void) -{ - i2c_bit_del_bus(&frodo_ops); -} - -MODULE_AUTHOR ("Abraham van der Merwe "); -MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo"); -MODULE_LICENSE ("GPL"); - -module_init (i2c_frodo_init); -module_exit (i2c_frodo_exit); - diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 474c8f4f5d4f..ec311bc89439 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -172,7 +172,6 @@ #define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */ #define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */ #define I2C_HW_B_TSUNA 0x010012 /* DEC Tsunami chipset */ -#define I2C_HW_B_FRODO 0x010013 /* 2d3D SA-1110 Development Board */ #define I2C_HW_B_OMAHA 0x010014 /* Omaha I2C interface (ARM) */ #define I2C_HW_B_GUIDE 0x010015 /* Guide bit-basher */ #define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */ -- cgit v1.2.3-59-g8ed1b From f8d6d9f52b4977f5427e2cb782521611a823c108 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 5 Feb 2006 23:30:26 +0100 Subject: [PATCH] i2c: Fix i2c-ite name initialization Properly set the name member of the i2c_adapter structure of the ite i2c adapter driver. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-ite.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c index 5f5d2944808b..d82e6dae8407 100644 --- a/drivers/i2c/busses/i2c-ite.c +++ b/drivers/i2c/busses/i2c-ite.c @@ -200,9 +200,7 @@ static struct i2c_adapter iic_ite_ops = { .owner = THIS_MODULE, .id = I2C_HW_I_IIC, .algo_data = &iic_ite_data, - .dev = { - .name = "ITE IIC adapter", - }, + .name = "ITE IIC adapter", }; /* Called when the module is loaded. This function starts the -- cgit v1.2.3-59-g8ed1b From c006705e0f6a195d122be8d5344a4257c269f559 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 5 Feb 2006 23:31:25 +0100 Subject: [PATCH] i2c: Cleanup isp1301_omap Drop unused rogue i2c driver ID and nonsensical i2c class. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/isp1301_omap.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index 1251c7fc18d5..e6f1ab7b913c 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c @@ -1635,8 +1635,6 @@ static struct i2c_driver isp1301_driver = { .driver = { .name = "isp1301_omap", }, - .id = 1301, /* FIXME "official", i2c-ids.h */ - .class = I2C_CLASS_HWMON, .attach_adapter = isp1301_scan_bus, .detach_client = isp1301_detach_client, }; -- cgit v1.2.3-59-g8ed1b From 0cbcb4d39a83d4df7e45c13b5ebd9fe73e025237 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 27 Feb 2006 23:08:18 +0100 Subject: [PATCH] I2C: i2c-ali1535: Drop redundant mutex Drop a redundant mutex in driver i2c-ali1535. The struct i2c_adapter includes a mutex for the same purpose, operated by i2c-core. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-ali1535.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 115a7312948e..d3ef46aeeb3c 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -62,7 +62,6 @@ #include #include #include -#include #include @@ -136,7 +135,6 @@ static struct pci_driver ali1535_driver; static unsigned short ali1535_smba; -static DEFINE_MUTEX(i2c_ali1535_mutex); /* Detect whether a ALI1535 can be found, and initialize it, where necessary. Note the differences between kernels with the old PCI BIOS interface and @@ -345,7 +343,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, int timeout; s32 result = 0; - mutex_lock(&i2c_ali1535_mutex); /* make sure SMBus is idle */ temp = inb_p(SMBHSTSTS); for (timeout = 0; @@ -460,7 +457,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, break; } EXIT: - mutex_unlock(&i2c_ali1535_mutex); return result; } -- cgit v1.2.3-59-g8ed1b From d7d2fe384703f3f57dac94e8e6303a9f0d9a6239 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 27 Feb 2006 23:09:22 +0100 Subject: [PATCH] I2C: i2c-amd756-s4882: Improve static mutex initialization Static mutexes can be initialized at declaration time. Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-amd756-s4882.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index f7b4cb4e9c75..08e915730caf 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c @@ -46,7 +46,7 @@ static struct i2c_adapter *s4882_adapter; static struct i2c_algorithm *s4882_algo; /* Wrapper access functions for multiplexed SMBus */ -static struct mutex amd756_lock; +static DEFINE_MUTEX(amd756_lock); static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, @@ -167,8 +167,6 @@ static int __init amd756_s4882_init(void) } printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); - mutex_init(&amd756_lock); - /* Define the 5 virtual adapters and algorithms structures */ if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter), GFP_KERNEL))) { -- cgit v1.2.3-59-g8ed1b From 5f7ea3c58c9aa571617a9d77dd2fbd4bd81cc50a Mon Sep 17 00:00:00 2001 From: Martin Devera Date: Mon, 27 Feb 2006 23:11:45 +0100 Subject: [PATCH] I2C: i2c-piix4: Add Broadcom HT-1000 support Add Broadcom HT-1000 south bridge's PCI ID to i2c-piix driver. Note that at least on Supermicro H8SSL it uses non-standard SMBHSTCFG = 3 and standard values like 0 or 9 causes hangup. Signed-off-by: Martin Devera Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-piix4 | 2 +- drivers/i2c/busses/Kconfig | 4 +++- drivers/i2c/busses/i2c-piix4.c | 4 +++- include/linux/pci_ids.h | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index 856b4b8b962c..a1c8f581afed 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -4,7 +4,7 @@ Supported adapters: * Intel 82371AB PIIX4 and PIIX4E * Intel 82443MX (440MX) Datasheet: Publicly available at the Intel website - * ServerWorks OSB4, CSB5 and CSB6 southbridges + * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges Datasheet: Only available via NDA from ServerWorks * 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 7d2705a68e09..089c6f5b24de 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -168,12 +168,14 @@ config I2C_PIIX4 help If you say yes to this option, support will be included for the Intel PIIX4 family of mainboard I2C interfaces. Specifically, the following - versions of the chipset are supported: + versions of the chipset are supported (note that Serverworks is part + of Broadcom): Intel PIIX4 Intel 440MX Serverworks OSB4 Serverworks CSB5 Serverworks CSB6 + Serverworks HT-1000 SMSC Victory66 This driver can also be built as a module. If so, the module diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 692f47345481..d9c7c00e71f9 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -22,7 +22,7 @@ /* Supports: Intel PIIX4, 440MX - Serverworks OSB4, CSB5, CSB6 + Serverworks OSB4, CSB5, CSB6, HT-1000 SMSC Victory66 Note: we assume there can only be one device, with one SMBus interface. @@ -419,6 +419,8 @@ static struct pci_device_id piix4_ids[] = { .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6), .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB), + .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3), .driver_data = 3 }, { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3), diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ec3c32932620..f5a724fbf094 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1371,6 +1371,7 @@ #define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 #define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 #define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 +#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205 #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 #define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213 -- cgit v1.2.3-59-g8ed1b From 7cd30b26eb779b787e00e05f3e9797a97de33968 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Feb 2006 23:12:58 +0100 Subject: [PATCH] I2C: i2c-ixp4xx: Add hwmon class This patch adds I2C_CLASS_HWMON to the ixp4xx bus driver. Signed-off-by: Alessandro Zummo Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-ixp4xx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c index e422d8b2d4d6..2ed07112d683 100644 --- a/drivers/i2c/busses/i2c-ixp4xx.c +++ b/drivers/i2c/busses/i2c-ixp4xx.c @@ -126,6 +126,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev) drv_data->algo_data.timeout = 100; drv_data->adapter.id = I2C_HW_B_IXP4XX; + drv_data->adapter.class = I2C_CLASS_HWMON; strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, I2C_NAME_SIZE); drv_data->adapter.algo_data = &drv_data->algo_data; -- cgit v1.2.3-59-g8ed1b From 279a022d4a12598b58aee47a73faf2d8cc72c91f Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 27 Feb 2006 23:13:53 +0100 Subject: [PATCH] I2C: Drop unneeded i2c-dev.h includes Several media/video and sound drivers include i2c-dev.h while they don't need it at all. Clean it up. This header file is really only needed by i2c-dev.c and compat_ioctl.c, other drivers should never need it. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/adv7170.c | 1 - drivers/media/video/adv7175.c | 1 - drivers/media/video/bt819.c | 1 - drivers/media/video/bt856.c | 1 - drivers/media/video/saa7110.c | 1 - drivers/media/video/saa7111.c | 1 - drivers/media/video/saa7114.c | 1 - drivers/media/video/saa711x.c | 1 - drivers/media/video/saa7185.c | 1 - drivers/media/video/vpx3220.c | 1 - sound/oss/dmasound/dmasound_awacs.c | 2 -- sound/ppc/daca.c | 1 - sound/ppc/keywest.c | 1 - sound/ppc/toonie.c | 1 - sound/ppc/tumbler.c | 1 - 15 files changed, 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 4ce07ae62dac..6e2004cdec1f 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -53,7 +53,6 @@ MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); #include -#include #define I2C_NAME(x) (x)->name diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 4e218f22b214..6b17247adf87 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -49,7 +49,6 @@ MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); #include -#include #define I2C_NAME(s) (s)->name diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index d6447791d0e5..2bf63e7ab4e6 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -53,7 +53,6 @@ MODULE_AUTHOR("Mike Bernson & Dave Perks"); MODULE_LICENSE("GPL"); #include -#include #define I2C_NAME(s) (s)->name diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 909b593530ed..da3be00ae2fb 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -53,7 +53,6 @@ MODULE_AUTHOR("Mike Bernson & Dave Perks"); MODULE_LICENSE("GPL"); #include -#include #define I2C_NAME(s) (s)->name diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 7bb85a7b326e..dff06895171b 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -39,7 +39,6 @@ MODULE_AUTHOR("Pauline Middelink"); MODULE_LICENSE("GPL"); #include -#include #define I2C_NAME(s) (s)->name diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index 8c06592b37ff..5e06cc98442d 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -52,7 +52,6 @@ MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); #include -#include #define I2C_NAME(s) (s)->name diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index fd0a4b4ef014..ce5a740e923e 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c @@ -55,7 +55,6 @@ MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); #include -#include #define I2C_NAME(x) (x)->name diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 6c161f2f5e2c..708fae51e8ee 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -45,7 +45,6 @@ MODULE_AUTHOR("Dave Perks, Jose Ignacio Gijon, Joerg Heckenbach, Mark McClelland MODULE_LICENSE("GPL"); #include -#include #define I2C_NAME(s) (s)->name diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 3ed0edb870a4..e1718e85f6c4 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -49,7 +49,6 @@ MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); #include -#include #define I2C_NAME(s) (s)->name diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index d0a1e72ea8c4..4cd579967487 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -30,7 +30,6 @@ #include #include -#include #define I2C_NAME(x) (x)->name diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c index a17375141c3a..6ba8d6f45fe8 100644 --- a/sound/oss/dmasound/dmasound_awacs.c +++ b/sound/oss/dmasound/dmasound_awacs.c @@ -88,8 +88,6 @@ #include #endif -#include - #include #include #include diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c index 08cde51177d7..aa09ebd9ffb8 100644 --- a/sound/ppc/daca.c +++ b/sound/ppc/daca.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 6058c2dd1b7f..fb05938dcbd9 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include "pmac.h" diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c index 053b8f24e4dc..210be20dc27e 100644 --- a/sound/ppc/toonie.c +++ b/sound/ppc/toonie.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 838fc113c441..1146dd882bb1 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3-59-g8ed1b From f6c27fc17c5e575c5471fb344bdbd5f5f6072136 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Mon, 27 Feb 2006 23:14:58 +0100 Subject: [PATCH] I2C: hwmon: Rename register parameters "register" is a reserved keyword so using it as a parameter name can confuse some compilers, most notably ICC. The patch below just renames all occurences to reg which fits the actual function declarations. Signed-off-by: Darren Jenkins Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/adm1026.c | 5 ++--- drivers/hwmon/fscpos.c | 4 ++-- drivers/hwmon/it87.c | 5 ++--- drivers/hwmon/lm78.c | 4 ++-- drivers/hwmon/lm85.c | 4 ++-- drivers/hwmon/sis5595.c | 4 ++-- drivers/hwmon/w83627hf.c | 5 ++--- drivers/hwmon/w83781d.c | 5 ++--- 8 files changed, 16 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 8646ec1e9667..6d4f8b8d358e 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -299,9 +299,8 @@ static int adm1026_attach_adapter(struct i2c_adapter *adapter); static int adm1026_detect(struct i2c_adapter *adapter, int address, int kind); static int adm1026_detach_client(struct i2c_client *client); -static int adm1026_read_value(struct i2c_client *client, u8 register); -static int adm1026_write_value(struct i2c_client *client, u8 register, - int value); +static int adm1026_read_value(struct i2c_client *client, u8 reg); +static int adm1026_write_value(struct i2c_client *client, u8 reg, int value); static void adm1026_print_gpio(struct i2c_client *client); static void adm1026_fixup_gpio(struct i2c_client *client); static struct adm1026_data *adm1026_update_device(struct device *dev); diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c index 758978e1bfe0..6dc4846b9eeb 100644 --- a/drivers/hwmon/fscpos.c +++ b/drivers/hwmon/fscpos.c @@ -90,8 +90,8 @@ static int fscpos_attach_adapter(struct i2c_adapter *adapter); static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind); static int fscpos_detach_client(struct i2c_client *client); -static int fscpos_read_value(struct i2c_client *client, u8 register); -static int fscpos_write_value(struct i2c_client *client, u8 register, u8 value); +static int fscpos_read_value(struct i2c_client *client, u8 reg); +static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value); static struct fscpos_data *fscpos_update_device(struct device *dev); static void fscpos_init_client(struct i2c_client *client); diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 122ff9cd75cb..06df92b3ee49 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -225,9 +225,8 @@ static int it87_isa_attach_adapter(struct i2c_adapter *adapter); static int it87_detect(struct i2c_adapter *adapter, int address, int kind); static int it87_detach_client(struct i2c_client *client); -static int it87_read_value(struct i2c_client *client, u8 register); -static int it87_write_value(struct i2c_client *client, u8 register, - u8 value); +static int it87_read_value(struct i2c_client *client, u8 reg); +static int it87_write_value(struct i2c_client *client, u8 reg, u8 value); static struct it87_data *it87_update_device(struct device *dev); static int it87_check_pwm(struct i2c_client *client); static void it87_init_client(struct i2c_client *client, struct it87_data *data); diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 36d1192ebe2a..94be3d797e61 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -158,8 +158,8 @@ static int lm78_isa_attach_adapter(struct i2c_adapter *adapter); static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); static int lm78_detach_client(struct i2c_client *client); -static int lm78_read_value(struct i2c_client *client, u8 register); -static int lm78_write_value(struct i2c_client *client, u8 register, u8 value); +static int lm78_read_value(struct i2c_client *client, u8 reg); +static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value); static struct lm78_data *lm78_update_device(struct device *dev); static void lm78_init_client(struct i2c_client *client); diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 095e58ac2ceb..342e9663119d 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -374,8 +374,8 @@ static int lm85_detect(struct i2c_adapter *adapter, int address, int kind); static int lm85_detach_client(struct i2c_client *client); -static int lm85_read_value(struct i2c_client *client, u8 register); -static int lm85_write_value(struct i2c_client *client, u8 register, int value); +static int lm85_read_value(struct i2c_client *client, u8 reg); +static int lm85_write_value(struct i2c_client *client, u8 reg, int value); static struct lm85_data *lm85_update_device(struct device *dev); static void lm85_init_client(struct i2c_client *client); diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 4db0dd871eee..6f3fda73f70c 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -193,8 +193,8 @@ static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */ static int sis5595_detect(struct i2c_adapter *adapter); static int sis5595_detach_client(struct i2c_client *client); -static int sis5595_read_value(struct i2c_client *client, u8 register); -static int sis5595_write_value(struct i2c_client *client, u8 register, u8 value); +static int sis5595_read_value(struct i2c_client *client, u8 reg); +static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value); static struct sis5595_data *sis5595_update_device(struct device *dev); static void sis5595_init_client(struct i2c_client *client); diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 992e34402705..71fb7f1af8f5 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -332,9 +332,8 @@ struct w83627hf_data { static int w83627hf_detect(struct i2c_adapter *adapter); static int w83627hf_detach_client(struct i2c_client *client); -static int w83627hf_read_value(struct i2c_client *client, u16 register); -static int w83627hf_write_value(struct i2c_client *client, u16 register, - u16 value); +static int w83627hf_read_value(struct i2c_client *client, u16 reg); +static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value); static struct w83627hf_data *w83627hf_update_device(struct device *dev); static void w83627hf_init_client(struct i2c_client *client); diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 8b17132f6b94..e4c700356c44 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -272,9 +272,8 @@ static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter); static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); static int w83781d_detach_client(struct i2c_client *client); -static int w83781d_read_value(struct i2c_client *client, u16 register); -static int w83781d_write_value(struct i2c_client *client, u16 register, - u16 value); +static int w83781d_read_value(struct i2c_client *client, u16 reg); +static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value); static struct w83781d_data *w83781d_update_device(struct device *dev); static void w83781d_init_client(struct i2c_client *client); -- cgit v1.2.3-59-g8ed1b From ded2b66615613093eeb83b81499bc270de8fc499 Mon Sep 17 00:00:00 2001 From: "Mark M. Hoffman" Date: Sun, 5 Mar 2006 23:13:47 +0100 Subject: [PATCH] hwmon: add required idr locking Add required locking around idr_ routines, retry the idr_pre_get/idr_get_new pair properly, and sprinkle in some likely/unlikely for good measure. (Lack of idr locking didn't hurt when all callers were I2C clients, as the i2c-core serialized for us anyway. Now that we have non I2C hwmon drivers, this is truly necessary.) Signed-off-by: Mark M. Hoffman Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/hwmon.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index dddd3eb9b387..106fa01cdb60 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -17,6 +17,7 @@ #include #include #include +#include #define HWMON_ID_PREFIX "hwmon" #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" @@ -24,6 +25,7 @@ static struct class *hwmon_class; static DEFINE_IDR(hwmon_idr); +static DEFINE_SPINLOCK(idr_lock); /** * hwmon_device_register - register w/ hwmon sysfs class @@ -37,20 +39,30 @@ static DEFINE_IDR(hwmon_idr); struct class_device *hwmon_device_register(struct device *dev) { struct class_device *cdev; - int id; + int id, err; - if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0) +again: + if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0)) return ERR_PTR(-ENOMEM); - if (idr_get_new(&hwmon_idr, NULL, &id) < 0) - return ERR_PTR(-ENOMEM); + spin_lock(&idr_lock); + err = idr_get_new(&hwmon_idr, NULL, &id); + spin_unlock(&idr_lock); + + if (unlikely(err == -EAGAIN)) + goto again; + else if (unlikely(err)) + return ERR_PTR(err); id = id & MAX_ID_MASK; cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev, HWMON_ID_FORMAT, id); - if (IS_ERR(cdev)) + if (IS_ERR(cdev)) { + spin_lock(&idr_lock); idr_remove(&hwmon_idr, id); + spin_unlock(&idr_lock); + } return cdev; } @@ -64,9 +76,11 @@ void hwmon_device_unregister(struct class_device *cdev) { int id; - if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) { + if (likely(sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1)) { class_device_unregister(cdev); + spin_lock(&idr_lock); idr_remove(&hwmon_idr, id); + spin_unlock(&idr_lock); } else dev_dbg(cdev->dev, "hwmon_device_unregister() failed: bad class ID!\n"); -- cgit v1.2.3-59-g8ed1b From b64c05e7de6071694dd6840eac9724a006ee19f8 Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Sat, 14 Jan 2006 00:34:53 -0700 Subject: [PATCH] PCI: clean up msi.c a bit Clean up: move assignments outside of if() statements. AFAICT, no functional change. Easier to read/understand. Depends on "[PATCH 1/3] msi vector targeting abstractions" by Mark Maule . I expect one hunk to fail if applied against 2.6.15. This is essentially Joe Perches' patch. I've cleaned up the one instance added by Mark's patch. Signed-off-by: Grant Grundler Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 55 +++++++++++++++++++++++++++++++++++-------------------- drivers/pci/pci.c | 5 ++--- 2 files changed, 37 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 48723d6fa60f..d5a67c1bcb98 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -103,9 +103,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) switch (entry->msi_attrib.type) { case PCI_CAP_ID_MSI: { - int pos; + int pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI); - if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI))) + if (!pos) return; pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), @@ -347,9 +347,9 @@ static int assign_msi_vector(void) static int get_new_vector(void) { - int vector; + int vector = assign_msi_vector(); - if ((vector = assign_msi_vector()) > 0) + if (vector > 0) set_intr_gate(vector, interrupt[vector]); return vector; @@ -369,7 +369,8 @@ static int msi_init(void) return status; } - if ((status = msi_cache_init()) < 0) { + status = msi_cache_init(); + if (status < 0) { pci_msi_enable = 0; printk(KERN_WARNING "PCI: MSI cache init failed\n"); return status; @@ -523,10 +524,12 @@ static int msi_capability_init(struct pci_dev *dev) pos = pci_find_capability(dev, PCI_CAP_ID_MSI); pci_read_config_word(dev, msi_control_reg(pos), &control); /* MSI Entry Initialization */ - if (!(entry = alloc_msi_entry())) + entry = alloc_msi_entry(); + if (!entry) return -ENOMEM; - if ((vector = get_msi_vector(dev)) < 0) { + vector = get_msi_vector(dev); + if (vector < 0) { kmem_cache_free(msi_cachep, entry); return -EBUSY; } @@ -620,7 +623,8 @@ static int msix_capability_init(struct pci_dev *dev, entry = alloc_msi_entry(); if (!entry) break; - if ((vector = get_msi_vector(dev)) < 0) + vector = get_msi_vector(dev); + if (vector < 0) break; j = entries[i].entry; @@ -701,10 +705,12 @@ int pci_enable_msi(struct pci_dev* dev) temp = dev->irq; - if ((status = msi_init()) < 0) + status = msi_init(); + if (status < 0) return status; - if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSI))) + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (!pos) return -EINVAL; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -728,8 +734,8 @@ int pci_enable_msi(struct pci_dev* dev) dev->irq = temp; } /* Check whether driver already requested for MSI-X vectors */ - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 && - !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { printk(KERN_INFO "PCI: %s: Can't enable MSI. " "Device already has MSI-X vectors assigned\n", pci_name(dev)); @@ -755,7 +761,10 @@ void pci_disable_msi(struct pci_dev* dev) u16 control; unsigned long flags; - if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSI))) + if (!dev) + return; + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (!pos) return; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -924,10 +933,12 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) if (!pci_msi_enable || !dev || !entries) return -EINVAL; - if ((status = msi_init()) < 0) + status = msi_init(); + if (status < 0) return status; - if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX))) + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (!pos) return -EINVAL; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -1006,7 +1017,11 @@ void pci_disable_msix(struct pci_dev* dev) int pos, temp; u16 control; - if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX))) + if (!dev) + return; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (!pos) return; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -1066,8 +1081,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) return; temp = dev->irq; /* Save IOAPIC IRQ */ - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) > 0 && - !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { spin_lock_irqsave(&msi_lock, flags); state = msi_desc[dev->irq]->msi_attrib.state; spin_unlock_irqrestore(&msi_lock, flags); @@ -1080,8 +1095,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) msi_free_vector(dev, dev->irq, 0); dev->irq = temp; /* Restore IOAPIC IRQ */ } - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 && - !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { int vector, head, tail = 0, warning = 0; void __iomem *base = NULL; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d2d187916643..e17cd49d6244 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -495,9 +495,8 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) int pci_enable_device(struct pci_dev *dev) { - int err; - - if ((err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1))) + int err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); + if (err) return err; pci_fixup_device(pci_fixup_enable, dev); dev->is_enabled = 1; -- cgit v1.2.3-59-g8ed1b From b82db5cedf78bfeb4a1c8a28ae284dc671d26eb3 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Tue, 17 Jan 2006 16:56:56 -0800 Subject: [PATCH] PCI: return max reserved busnr Change the semantics of this call to return the max reserved bus number instead of just the max assigned bus number. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 5 +++-- include/linux/pci.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e17cd49d6244..0bf6d254426b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -19,7 +19,6 @@ #include /* isa_dma_bridge_buggy */ #include "pci.h" -#if 0 /** * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children @@ -34,7 +33,7 @@ pci_bus_max_busnr(struct pci_bus* bus) struct list_head *tmp; unsigned char max, n; - max = bus->number; + max = bus->subordinate; list_for_each(tmp, &bus->children) { n = pci_bus_max_busnr(pci_bus_b(tmp)); if(n > max) @@ -42,7 +41,9 @@ pci_bus_max_busnr(struct pci_bus* bus) } return max; } +EXPORT_SYMBOL_GPL(pci_bus_max_busnr); +#if 0 /** * pci_max_busnr - returns maximum PCI bus number * diff --git a/include/linux/pci.h b/include/linux/pci.h index fe1a2b02fc55..2039da1f3672 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -516,6 +516,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), void *userdata); int pci_cfg_space_size(struct pci_dev *dev); +unsigned char pci_bus_max_busnr(struct pci_bus* bus); /* kmem_cache style wrapper around pci_alloc_consistent() */ -- cgit v1.2.3-59-g8ed1b From e3ac86d8b3f5cee1afaa3e9e6984d0321149b948 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Tue, 17 Jan 2006 16:57:01 -0800 Subject: [PATCH] PCI: really fix parent's subordinate busnr After you find the maximum value of the subordinate buses below the child bus, you must fix the parent's subordinate bus number again, otherwise it may be too small. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/probe.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index adfad4fd6a13..63751a283817 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -537,6 +537,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max pci_fixup_parent_subordinate_busnr(child, max); /* Now we can scan all subordinate buses... */ max = pci_scan_child_bus(child); + /* + * now fix it up again since we have found + * the real value of max. + */ + pci_fixup_parent_subordinate_busnr(child, max); } else { /* * For CardBus bridges, we leave 4 bus numbers -- cgit v1.2.3-59-g8ed1b From c408a3794d6222ab43ab26648385f850a82f0803 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Tue, 17 Jan 2006 16:57:04 -0800 Subject: [PATCH] PCI: quirk for IBM Dock II cardbus controllers The IBM Dock II cardbus bridges require some extra configuration before Yenta is loaded in order to setup the Interrupts to be routed properly. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index dda6099903c1..7ec9fc9a9a42 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1242,6 +1242,33 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_pc DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_pcie_pxh); +/* + * Fixup the cardbus bridges on the IBM Dock II docking station + */ +static void __devinit quirk_ibm_dock2_cardbus(struct pci_dev *dev) +{ + u32 val; + + /* + * tie the 2 interrupt pins to INTA, and configure the + * multifunction routing register to handle this. + */ + if ((dev->subsystem_vendor == PCI_VENDOR_ID_IBM) && + (dev->subsystem_device == 0x0148)) { + printk(KERN_INFO "PCI: Found IBM Dock II Cardbus Bridge " + "applying quirk\n"); + pci_read_config_dword(dev, 0x8c, &val); + val = ((val & 0xffffff00) | 0x1002); + pci_write_config_dword(dev, 0x8c, val); + pci_read_config_dword(dev, 0x80, &val); + val = ((val & 0x00ffff00) | 0x2864c077); + pci_write_config_dword(dev, 0x80, val); + } +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, + quirk_ibm_dock2_cardbus); + static void __devinit quirk_netmos(struct pci_dev *dev) { unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; -- cgit v1.2.3-59-g8ed1b From 6aa4cdd07139ba4d5b89139b0070d795cc4dea88 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 13 Jan 2006 16:02:15 +0100 Subject: [PATCH] PCI hotplug: convert semaphores to mutex semaphore to mutex conversion. the conversion was generated via scripts, and the result was validated automatically via a script as well. build tested with allyesconfig. Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp.h | 3 +- drivers/pci/hotplug/acpiphp_glue.c | 12 ++--- drivers/pci/hotplug/cpqphp.h | 3 +- drivers/pci/hotplug/cpqphp_core.c | 14 +++--- drivers/pci/hotplug/cpqphp_ctrl.c | 56 +++++++++++----------- drivers/pci/hotplug/ibmphp_hpc.c | 10 ++-- drivers/pci/hotplug/pciehp.h | 3 +- drivers/pci/hotplug/pciehp_core.c | 6 +-- drivers/pci/hotplug/pciehp_ctrl.c | 68 +++++++++++++------------- drivers/pci/hotplug/pciehp_hpc.c | 2 +- drivers/pci/hotplug/shpchp.h | 3 +- drivers/pci/hotplug/shpchp_ctrl.c | 98 +++++++++++++++++++------------------- drivers/pci/hotplug/shpchp_hpc.c | 2 +- 13 files changed, 143 insertions(+), 137 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 293603e1b7c3..6a91cfb0f688 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -37,6 +37,7 @@ #include #include /* for KOBJ_NAME_LEN */ +#include #include "pci_hotplug.h" #define dbg(format, arg...) \ @@ -118,7 +119,7 @@ struct acpiphp_slot { struct acpiphp_bridge *bridge; /* parent */ struct list_head funcs; /* one slot may have different objects (i.e. for each function) */ - struct semaphore crit_sect; + struct mutex crit_sect; u32 id; /* slot id (serial #) for hotplug core */ u8 device; /* pci device# */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 509a5b3ae998..4e25d9c7cc39 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include "../pci.h" #include "pci_hotplug.h" @@ -188,7 +188,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) slot->device = device; slot->sun = sun; INIT_LIST_HEAD(&slot->funcs); - init_MUTEX(&slot->crit_sect); + mutex_init(&slot->crit_sect); slot->next = bridge->slots; bridge->slots = slot; @@ -1401,7 +1401,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) { int retval; - down(&slot->crit_sect); + mutex_lock(&slot->crit_sect); /* wake up all functions */ retval = power_on_slot(slot); @@ -1413,7 +1413,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) retval = enable_device(slot); err_exit: - up(&slot->crit_sect); + mutex_unlock(&slot->crit_sect); return retval; } @@ -1424,7 +1424,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) { int retval = 0; - down(&slot->crit_sect); + mutex_lock(&slot->crit_sect); /* unconfigure all functions */ retval = disable_device(slot); @@ -1437,7 +1437,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) goto err_exit; err_exit: - up(&slot->crit_sect); + mutex_unlock(&slot->crit_sect); return retval; } diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index cb88404c89fe..c74e9e37e76b 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h @@ -32,6 +32,7 @@ #include #include /* for read? and write? functions */ #include /* for delays */ +#include #define MY_NAME "cpqphp" @@ -286,7 +287,7 @@ struct event_info { struct controller { struct controller *next; u32 ctrl_int_comp; - struct semaphore crit_sect; /* critical section semaphore */ + struct mutex crit_sect; /* critical section mutex */ void __iomem *hpc_reg; /* cookie for our pci controller location */ struct pci_resource *mem_head; struct pci_resource *p_mem_head; diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index b3659ffccac9..8626901daeb8 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -599,7 +599,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, hp_slot = func->device - ctrl->slot_device_offset; // Wait for exclusive access to hardware - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (status == 1) { amber_LED_on (ctrl, hp_slot); @@ -607,7 +607,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, amber_LED_off (ctrl, hp_slot); } else { // Done with exclusive hardware access - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return(1); } @@ -617,7 +617,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, wait_for_ctrl_irq (ctrl); // Done with exclusive hardware access - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return(0); } @@ -1084,7 +1084,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev); - init_MUTEX(&ctrl->crit_sect); + mutex_init(&ctrl->crit_sect); init_waitqueue_head(&ctrl->queue); /* initialize our threads if they haven't already been started up */ @@ -1223,7 +1223,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) // turn off empty slots here unless command line option "ON" set // Wait for exclusive access to hardware - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; @@ -1270,12 +1270,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = init_SERR(ctrl); if (rc) { err("init_SERR failed\n"); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); goto err_free_irq; } // Done with exclusive hardware access - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); cpqhp_create_debugfs_files(ctrl); diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 771ed34b1819..72eb8e2d2065 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -1299,7 +1299,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) **********************************/ rc = CARD_FUNCTIONING; } else { - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn on board without attaching to the bus */ enable_slot_power (ctrl, hp_slot); @@ -1333,12 +1333,12 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if (rc) return rc; - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); slot_enable (ctrl, hp_slot); green_LED_blink (ctrl, hp_slot); @@ -1350,7 +1350,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); /* Wait for ~1 second because of hot plug spec */ long_delay(1*HZ); @@ -1375,7 +1375,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) * called for the "base" bus/dev/func of an * adapter. */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1386,7 +1386,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if (rc) return rc; @@ -1410,7 +1410,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) * called for the "base" bus/dev/func of an * adapter. */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1421,13 +1421,13 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } /* Done configuring so turn LED on full time */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); green_LED_on (ctrl, hp_slot); @@ -1436,7 +1436,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); rc = 0; } else { /* Something is wrong @@ -1445,7 +1445,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) * in this case it will always be called for the "base" * bus/dev/func of an adapter. */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1456,7 +1456,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } } @@ -1488,7 +1488,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn on board without attaching to the bus */ enable_slot_power(ctrl, hp_slot); @@ -1522,7 +1522,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq(ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if (rc) return rc; @@ -1532,7 +1532,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* turn on board and blink green LED */ dbg("%s: before down\n", __FUNCTION__); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); dbg("%s: after down\n", __FUNCTION__); dbg("%s: before slot_enable\n", __FUNCTION__); @@ -1553,7 +1553,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__); dbg("%s: before up\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); dbg("%s: after up\n", __FUNCTION__); /* Wait for ~1 second because of hot plug spec */ @@ -1607,7 +1607,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); if (rc) { - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1618,7 +1618,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } else { cpqhp_save_slot_config(ctrl, func); @@ -1640,7 +1640,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) } } while (new_slot); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); green_LED_on (ctrl, hp_slot); @@ -1649,9 +1649,9 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } else { - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1662,7 +1662,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -1721,7 +1721,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control func->status = 0x01; func->configured = 0; - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); green_LED_off (ctrl, hp_slot); slot_disable (ctrl, hp_slot); @@ -1736,7 +1736,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if (!replace_flag && ctrl->add_support) { while (func) { @@ -1899,7 +1899,7 @@ static void interrupt_event_handler(struct controller *ctrl) dbg("button cancel\n"); del_timer(&p_slot->task_event); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (p_slot->state == BLINKINGOFF_STATE) { /* slot is on */ @@ -1922,7 +1922,7 @@ static void interrupt_event_handler(struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } /*** button Released (No action on press...) */ else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) { @@ -1937,7 +1937,7 @@ static void interrupt_event_handler(struct controller *ctrl) p_slot->state = BLINKINGON_STATE; info(msg_button_on, p_slot->number); } - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); dbg("blink green LED and turn off amber\n"); @@ -1949,7 +1949,7 @@ static void interrupt_event_handler(struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); init_timer(&p_slot->task_event); p_slot->hp_slot = hp_slot; p_slot->ctrl = ctrl; diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index 1a3eb8d3d4cb..d680bb472c7b 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c @@ -34,6 +34,8 @@ #include #include #include +#include + #include "ibmphp.h" static int to_debug = FALSE; @@ -101,7 +103,7 @@ static int to_debug = FALSE; //---------------------------------------------------------------------------- static int ibmphp_shutdown; static int tid_poll; -static struct semaphore sem_hpcaccess; // lock access to HPC +static struct mutex sem_hpcaccess; // lock access to HPC static struct semaphore semOperations; // lock all operations and // access to data structures static struct semaphore sem_exit; // make sure polling thread goes away @@ -131,7 +133,7 @@ void __init ibmphp_hpc_initvars (void) { debug ("%s - Entry\n", __FUNCTION__); - init_MUTEX (&sem_hpcaccess); + mutex_init(&sem_hpcaccess); init_MUTEX (&semOperations); init_MUTEX_LOCKED (&sem_exit); to_debug = FALSE; @@ -778,7 +780,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) *---------------------------------------------------------------------*/ static void get_hpc_access (void) { - down (&sem_hpcaccess); + mutex_lock(&sem_hpcaccess); } /*---------------------------------------------------------------------- @@ -786,7 +788,7 @@ static void get_hpc_access (void) *---------------------------------------------------------------------*/ void free_hpc_access (void) { - up (&sem_hpcaccess); + mutex_unlock(&sem_hpcaccess); } /*---------------------------------------------------------------------- diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 0aac6a61337d..e0adf4bc89e8 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -34,6 +34,7 @@ #include #include /* signal_pending() */ #include +#include #include "pci_hotplug.h" #define MY_NAME "pciehp" @@ -96,7 +97,7 @@ struct php_ctlr_state_s { #define MAX_EVENTS 10 struct controller { struct controller *next; - struct semaphore crit_sect; /* critical section semaphore */ + struct mutex crit_sect; /* critical section mutex */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 4fb569018a24..1e8506e0fd87 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -439,7 +439,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ } /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ @@ -447,7 +447,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ if (rc) { /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); goto err_out_free_ctrl_slot; } else /* Wait for the command to complete */ @@ -455,7 +455,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return 0; diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 83c4b865718a..33d198768356 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -229,13 +229,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) static void set_slot_off(struct controller *ctrl, struct slot * pslot) { /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ if (POWER_CTRL(ctrl->ctrlcap)) { if (pslot->hpc_ops->power_off_slot(pslot)) { err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return; } wait_for_ctrl_irq (ctrl); @@ -249,14 +249,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) if (ATTN_LED(ctrl->ctrlcap)) { if (pslot->hpc_ops->set_attention_status(pslot, 1)) { err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return; } wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } /** @@ -279,13 +279,13 @@ static int board_added(struct slot *p_slot) ctrl->slot_device_offset, hp_slot); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (POWER_CTRL(ctrl->ctrlcap)) { /* Power on slot */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return -1; } @@ -301,7 +301,7 @@ static int board_added(struct slot *p_slot) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); /* Wait for ~1 second */ wait_for_ctrl_irq (ctrl); @@ -335,7 +335,7 @@ static int board_added(struct slot *p_slot) pci_fixup_device(pci_fixup_final, ctrl->pci_dev); if (PWR_LED(ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_on(p_slot); @@ -343,7 +343,7 @@ static int board_added(struct slot *p_slot) wait_for_ctrl_irq (ctrl); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } return 0; @@ -375,14 +375,14 @@ static int remove_board(struct slot *p_slot) dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (POWER_CTRL(ctrl->ctrlcap)) { /* power off slot */ rc = p_slot->hpc_ops->power_off_slot(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } /* Wait for the command to complete */ @@ -398,7 +398,7 @@ static int remove_board(struct slot *p_slot) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return 0; } @@ -445,7 +445,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); @@ -453,7 +453,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) wait_for_ctrl_irq (p_slot->ctrl); /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); } p_slot->state = STATIC_STATE; } @@ -495,7 +495,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); @@ -503,7 +503,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) wait_for_ctrl_irq (p_slot->ctrl); /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); } p_slot->state = STATIC_STATE; } @@ -616,7 +616,7 @@ static void interrupt_event_handler(struct controller *ctrl) switch (p_slot->state) { case BLINKINGOFF_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_on(p_slot); @@ -630,11 +630,11 @@ static void interrupt_event_handler(struct controller *ctrl) wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; case BLINKINGON_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_off(p_slot); @@ -647,7 +647,7 @@ static void interrupt_event_handler(struct controller *ctrl) wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; default: @@ -676,7 +676,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* blink green LED and turn off amber */ if (PWR_LED(ctrl->ctrlcap)) { @@ -693,7 +693,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); init_timer(&p_slot->task_event); p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ @@ -708,7 +708,7 @@ static void interrupt_event_handler(struct controller *ctrl) if (POWER_CTRL(ctrl->ctrlcap)) { dbg("power fault\n"); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (ATTN_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->set_attention_status(p_slot, 1); @@ -721,7 +721,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } } /***********SURPRISE REMOVAL********************/ @@ -756,19 +756,19 @@ int pciehp_enable_slot(struct slot *p_slot) int rc; /* Check to see if (latch closed, card present, power off) */ - down(&p_slot->ctrl->crit_sect); + 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); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } if (MRL_SENS(p_slot->ctrl->ctrlcap)) { 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); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } @@ -777,11 +777,11 @@ int pciehp_enable_slot(struct slot *p_slot) 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); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); @@ -806,13 +806,13 @@ int pciehp_disable_slot(struct slot *p_slot) return 1; /* Check to see if (latch closed, card present, power on) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } @@ -821,7 +821,7 @@ int pciehp_disable_slot(struct slot *p_slot) ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } @@ -830,12 +830,12 @@ int pciehp_disable_slot(struct slot *p_slot) ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); ret = remove_board(p_slot); update_slot_info(p_slot); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 77e530321de2..2427b0862cbf 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1334,7 +1334,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) if (pci_enable_device(pdev)) goto abort_free_ctlr; - init_MUTEX(&ctrl->crit_sect); + mutex_init(&ctrl->crit_sect); /* setup wait queue */ init_waitqueue_head(&ctrl->queue); diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 7d6f521d02ea..5a22a43cc387 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -33,6 +33,7 @@ #include #include #include /* signal_pending(), struct timer_list */ +#include #include "pci_hotplug.h" @@ -79,7 +80,7 @@ struct event_info { struct controller { struct controller *next; - struct semaphore crit_sect; /* critical section semaphore */ + struct mutex crit_sect; /* critical section mutex */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 643252d9bf3b..65e69252e2f9 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -242,10 +242,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, int rc = 0; dbg("%s: change to speed %d\n", __FUNCTION__, speed); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -253,10 +253,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", __FUNCTION__); err("%s: Error code (%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -319,14 +319,14 @@ static int board_added(struct slot *p_slot) ctrl->slot_device_offset, hp_slot); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* Power on slot without connecting to bus */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { err("%s: Failed to power on slot\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return -1; } @@ -334,7 +334,7 @@ static int board_added(struct slot *p_slot) if (rc) { err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return -1; } @@ -345,7 +345,7 @@ static int board_added(struct slot *p_slot) if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -353,19 +353,19 @@ static int board_added(struct slot *p_slot) err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", __FUNCTION__); err("%s: Error code (%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } } @@ -380,7 +380,7 @@ static int board_added(struct slot *p_slot) if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -388,7 +388,7 @@ static int board_added(struct slot *p_slot) if (rc || bus_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get bus operation speed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -399,7 +399,7 @@ static int board_added(struct slot *p_slot) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); @@ -481,21 +481,21 @@ static int board_added(struct slot *p_slot) return rc; } - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); /* Wait for ~1 second */ wait_for_ctrl_irq (ctrl); @@ -521,25 +521,25 @@ static int board_added(struct slot *p_slot) p_slot->pwr_save = 1; /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_on(p_slot); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return 0; err_exit: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -547,12 +547,12 @@ err_exit: if (rc) { err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return(rc); } @@ -581,14 +581,14 @@ static int remove_board(struct slot *p_slot) p_slot->status = 0x01; /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -596,7 +596,7 @@ static int remove_board(struct slot *p_slot) if (rc) { err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -604,12 +604,12 @@ static int remove_board(struct slot *p_slot) if (rc) { err("%s: Issue of Set Attention command failed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); p_slot->pwr_save = 0; p_slot->is_a_board = 0; @@ -656,12 +656,12 @@ static void shpchp_pushbutton_thread (unsigned long slot) if (shpchp_enable_slot(p_slot)) { /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); } p_slot->state = STATIC_STATE; } @@ -768,25 +768,25 @@ static void interrupt_event_handler(struct controller *ctrl) switch (p_slot->state) { case BLINKINGOFF_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_on(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; case BLINKINGON_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; default: @@ -813,7 +813,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* blink green LED and turn off amber */ p_slot->hpc_ops->green_led_blink(p_slot); @@ -821,7 +821,7 @@ static void interrupt_event_handler(struct controller *ctrl) p_slot->hpc_ops->set_attention_status(p_slot, 0); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); init_timer(&p_slot->task_event); p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ @@ -834,14 +834,14 @@ static void interrupt_event_handler(struct controller *ctrl) /***********POWER FAULT********************/ dbg("%s: power fault\n", __FUNCTION__); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->set_attention_status(p_slot, 1); p_slot->hpc_ops->green_led_off(p_slot); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } else { /* refresh notification */ if (p_slot) @@ -865,26 +865,26 @@ int shpchp_enable_slot (struct slot *p_slot) int rc; /* Check to see if (latch closed, card present, power off) */ - down(&p_slot->ctrl->crit_sect); + 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); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } 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); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } 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); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); p_slot->is_a_board = 1; @@ -925,27 +925,27 @@ int shpchp_disable_slot (struct slot *p_slot) return -ENODEV; /* Check to see if (latch closed, card present, power on) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); ret = remove_board(p_slot); update_slot_info(p_slot); diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index b4226ff3a854..ae81427e42b1 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -1454,7 +1454,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) } dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); - init_MUTEX(&ctrl->crit_sect); + mutex_init(&ctrl->crit_sect); /* Setup wait queue */ init_waitqueue_head(&ctrl->queue); -- cgit v1.2.3-59-g8ed1b From 926030f6af856d5681af7940239da2b0269cd755 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:55:35 +0900 Subject: [PATCH] shpchp - cleanup init_slots() This patch cleanups init_slots() function of SHPCHP driver based on pcihp_skelton.c. This patch has no functional change. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 7 --- drivers/pci/hotplug/shpchp_core.c | 120 ++++++++++++++++++++------------------ 2 files changed, 63 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 5a22a43cc387..e03ee0826700 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -428,13 +428,6 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot) pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp); } -#define SLOT_NAME_SIZE 10 - -static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) -{ - snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number); -} - enum php_ctlr_type { PCI, ISA, diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index a2b3f0010cec..29261b8824c8 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -99,89 +99,95 @@ static void release_slot(struct hotplug_slot *hotplug_slot) kfree(slot); } +#define SLOT_NAME_SIZE 10 +static void make_slot_name(struct slot *slot) +{ + snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", + slot->bus, slot->number); +} + static int init_slots(struct controller *ctrl) { - struct slot *new_slot; - u8 number_of_slots; - u8 slot_device; - u32 slot_number, sun; - int result = -ENOMEM; - - number_of_slots = ctrl->num_slots; - slot_device = ctrl->slot_device_offset; - slot_number = ctrl->first_slot; - - while (number_of_slots) { - new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL); - if (!new_slot) + struct slot *slot; + struct hotplug_slot *hotplug_slot; + struct hotplug_slot_info *info; + char *name; + int retval = -ENOMEM; + int i; + u32 sun; + + for (i = 0; i < ctrl->num_slots; i++) { + slot = kmalloc(sizeof(struct slot), GFP_KERNEL); + if (!slot) goto error; + memset(slot, 0, sizeof(struct slot)); - memset(new_slot, 0, sizeof(struct slot)); - new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); - if (!new_slot->hotplug_slot) + hotplug_slot = kmalloc(sizeof(struct hotplug_slot), + GFP_KERNEL); + if (!hotplug_slot) goto error_slot; - memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); + memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); + slot->hotplug_slot = hotplug_slot; - new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); - if (!new_slot->hotplug_slot->info) + info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + if (!info) goto error_hpslot; - memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); - new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); - if (!new_slot->hotplug_slot->name) + memset(info, 0, sizeof (struct hotplug_slot_info)); + hotplug_slot->info = info; + + name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); + if (!name) goto error_info; + hotplug_slot->name = name; - new_slot->magic = SLOT_MAGIC; - new_slot->ctrl = ctrl; - new_slot->bus = ctrl->slot_bus; - new_slot->device = slot_device; - new_slot->hpc_ops = ctrl->hpc_ops; + slot->hp_slot = i; + slot->magic = SLOT_MAGIC; + slot->ctrl = ctrl; + slot->bus = ctrl->slot_bus; + slot->device = ctrl->slot_device_offset + i; + slot->hpc_ops = ctrl->hpc_ops; if (shpchprm_get_physical_slot_number(ctrl, &sun, - new_slot->bus, new_slot->device)) + slot->bus, slot->device)) goto error_name; - new_slot->number = sun; - new_slot->hp_slot = slot_device - ctrl->slot_device_offset; + slot->number = sun; /* register this slot with the hotplug pci core */ - new_slot->hotplug_slot->private = new_slot; - new_slot->hotplug_slot->release = &release_slot; - make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); - new_slot->hotplug_slot->ops = &shpchp_hotplug_slot_ops; - - new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status)); - new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status)); - new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status)); - new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status)); - - dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", new_slot->bus, - new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset); - result = pci_hp_register (new_slot->hotplug_slot); - if (result) { - err ("pci_hp_register failed with error %d\n", result); + hotplug_slot->private = slot; + hotplug_slot->release = &release_slot; + make_slot_name(slot); + hotplug_slot->ops = &shpchp_hotplug_slot_ops; + + get_power_status(hotplug_slot, &info->power_status); + get_attention_status(hotplug_slot, &info->attention_status); + get_latch_status(hotplug_slot, &info->latch_status); + get_adapter_status(hotplug_slot, &info->adapter_status); + + dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " + "slot_device_offset=%x\n", slot->bus, slot->device, + slot->hp_slot, slot->number, ctrl->slot_device_offset); + retval = pci_hp_register(slot->hotplug_slot); + if (retval) { + err("pci_hp_register failed with error %d\n", retval); goto error_name; } - new_slot->next = ctrl->slot; - ctrl->slot = new_slot; - - number_of_slots--; - slot_device++; - slot_number += ctrl->slot_num_inc; + slot->next = ctrl->slot; + ctrl->slot = slot; } return 0; - error_name: - kfree(new_slot->hotplug_slot->name); + kfree(name); error_info: - kfree(new_slot->hotplug_slot->info); + kfree(info); error_hpslot: - kfree(new_slot->hotplug_slot); + kfree(hotplug_slot); error_slot: - kfree(new_slot); + kfree(slot); error: - return result; + return retval; } static void cleanup_slots(struct controller *ctrl) -- cgit v1.2.3-59-g8ed1b From dfcd5f68ec916414532e88583d1557b6ac0197f5 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:56:53 +0900 Subject: [PATCH] shpchp - cleanup shpchp_core.c This patch cleanups some codes in shpchp_core.c. This patch has no functional changes. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_core.c | 84 +++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 29261b8824c8..7f2e775534eb 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -213,9 +213,12 @@ static int get_ctlr_slot_config(struct controller *ctrl) int rc; int flags; - rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); + rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, + &first_device_num, &physical_slot_num, + &updown, &flags); if (rc) { - err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); + err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", + __FUNCTION__, ctrl->bus, ctrl->device); return -1; } @@ -224,19 +227,19 @@ static int get_ctlr_slot_config(struct controller *ctrl) ctrl->first_slot = physical_slot_num; ctrl->slot_num_inc = updown; /* either -1 or 1 */ - dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", - __FUNCTION__, num_ctlr_slots, first_device_num, physical_slot_num, updown, ctrl->bus, ctrl->device); + dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d " + "(%x:%x)\n", __FUNCTION__, num_ctlr_slots, first_device_num, + physical_slot_num, updown, ctrl->bus, ctrl->device); return 0; } - /* * set_attention_status - Turns the Amber LED for a slot on, off or blink */ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -246,20 +249,18 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) return 0; } - static int enable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); return shpchp_enable_slot(slot); } - static int disable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -268,7 +269,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot) static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -282,7 +283,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -296,7 +297,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -310,7 +311,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -324,7 +325,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -336,11 +337,11 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - + retval = slot->hpc_ops->get_max_bus_speed(slot, value); if (retval < 0) *value = PCI_SPEED_UNKNOWN; @@ -350,11 +351,11 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - + retval = slot->hpc_ops->get_cur_bus_speed(slot, value); if (retval < 0) *value = PCI_SPEED_UNKNOWN; @@ -378,13 +379,13 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int rc; struct controller *ctrl; struct slot *t_slot; - int first_device_num; /* first PCI device number supported by this SHPC */ - int num_ctlr_slots; /* number of slots supported by this SHPC */ + int first_device_num; /* first PCI device number */ + int num_ctlr_slots; /* number of slots implemented */ if (!is_shpc_capable(pdev)) return -ENODEV; - ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); + ctrl = kmalloc(sizeof(struct controller), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); goto err_out_none; @@ -393,31 +394,32 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = shpc_init(ctrl, pdev); if (rc) { - dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME); + dbg("%s: controller initialization failed\n", + SHPC_MODULE_NAME); goto err_out_free_ctrl; } pci_set_drvdata(pdev, ctrl); - ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); + ctrl->pci_bus = kmalloc(sizeof (*ctrl->pci_bus), GFP_KERNEL); if (!ctrl->pci_bus) { err("out of memory\n"); rc = -ENOMEM; goto err_out_unmap_mmio_region; } - + memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); ctrl->bus = pdev->bus->number; ctrl->slot_bus = pdev->subordinate->number; - ctrl->device = PCI_SLOT(pdev->devfn); ctrl->function = PCI_FUNC(pdev->devfn); - dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", ctrl->bus, ctrl->device, ctrl->function, pdev->irq); + + dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", + ctrl->bus, ctrl->device, ctrl->function, pdev->irq); /* - * Save configuration headers for this and subordinate PCI buses + * Save configuration headers for this and subordinate PCI buses */ - rc = get_ctlr_slot_config(ctrl); if (rc) { err(msg_initialization_err, rc); @@ -427,7 +429,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) num_ctlr_slots = ctrl->num_slots; ctrl->add_support = 1; - + /* Setup the slot information structures */ rc = init_slots(ctrl); if (rc) { @@ -443,7 +445,8 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot); if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) { - err(SHPC_MODULE_NAME ": Can't get current bus speed. Set to 33MHz PCI.\n"); + err(SHPC_MODULE_NAME ": Can't get current bus speed. " + "Set to 33MHz PCI.\n"); ctrl->speed = PCI_SPEED_33MHz; } @@ -474,11 +477,10 @@ err_out_none: return -ENODEV; } - static int shpc_start_thread(void) { int retval = 0; - + dbg("Initialize + Start the notification/polling mechanism \n"); retval = shpchp_event_start_thread(); @@ -515,24 +517,12 @@ static void __exit unload_shpchpd(void) } - static struct pci_device_id shpcd_pci_tbl[] = { - { - .class = ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), - .class_mask = ~0, - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - + {PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0)}, { /* end: all zeroes */ } }; - MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl); - - static struct pci_driver shpc_driver = { .name = SHPC_MODULE_NAME, .id_table = shpcd_pci_tbl, @@ -540,8 +530,6 @@ static struct pci_driver shpc_driver = { /* remove: shpc_remove_one, */ }; - - static int __init shpcd_init(void) { int retval = 0; -- cgit v1.2.3-59-g8ed1b From 5b1a960d180e9660a87b0c661a754efabc1b1d3a Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:57:40 +0900 Subject: [PATCH] shpchp - cleanup slot list This patch changes SHPCHP driver to use list_head structure for managing slot list. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 21 ++++++++------------- drivers/pci/hotplug/shpchp_core.c | 19 +++++++++---------- 2 files changed, 17 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index e03ee0826700..c0be7a1c3ff7 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -56,7 +56,6 @@ extern int shpchp_debug; #define SLOT_MAGIC 0x67267321 struct slot { u32 magic; - struct slot *next; u8 bus; u8 device; u16 status; @@ -87,7 +86,7 @@ struct controller { struct pci_dev *pci_dev; struct pci_bus *pci_bus; struct event_info event_queue[10]; - struct slot *slot; + struct list_head slot_list; struct hpc_ops *hpc_ops; wait_queue_head_t queue; /* sleep & wake process */ u8 next_event; @@ -315,23 +314,19 @@ static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const ch static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device) { - struct slot *p_slot, *tmp_slot = NULL; + struct slot *slot; if (!ctrl) return NULL; - p_slot = ctrl->slot; - - while (p_slot && (p_slot->device != device)) { - tmp_slot = p_slot; - p_slot = p_slot->next; - } - if (p_slot == NULL) { - err("ERROR: shpchp_find_slot device=0x%x\n", device); - p_slot = tmp_slot; + list_for_each_entry(slot, &ctrl->slot_list, slot_list) { + if (slot->device == device) + return slot; } - return (p_slot); + err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device); + + return NULL; } static inline int wait_for_ctrl_irq (struct controller *ctrl) diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 7f2e775534eb..547bf5d6fcca 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -173,8 +173,7 @@ static int init_slots(struct controller *ctrl) goto error_name; } - slot->next = ctrl->slot; - ctrl->slot = slot; + list_add(&slot->slot_list, &ctrl->slot_list); } return 0; @@ -192,15 +191,14 @@ error: static void cleanup_slots(struct controller *ctrl) { - struct slot *old_slot, *next_slot; - - old_slot = ctrl->slot; - ctrl->slot = NULL; + struct list_head *tmp; + struct list_head *next; + struct slot *slot; - while (old_slot) { - next_slot = old_slot->next; - pci_hp_deregister(old_slot->hotplug_slot); - old_slot = next_slot; + list_for_each_safe(tmp, next, &ctrl->slot_list) { + slot = list_entry(tmp, struct slot, slot_list); + list_del(&slot->slot_list); + pci_hp_deregister(slot->hotplug_slot); } } @@ -391,6 +389,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_none; } memset(ctrl, 0, sizeof(struct controller)); + INIT_LIST_HEAD(&ctrl->slot_list); rc = shpc_init(ctrl, pdev); if (rc) { -- cgit v1.2.3-59-g8ed1b From a4534560815ffc525bfbe465a290ce048aab4c01 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:58:30 +0900 Subject: [PATCH] shpchp - cleanup controller list This patch changes SHPCHP driver to use list_head structure for managing controller list. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 4 ++-- drivers/pci/hotplug/shpchp_core.c | 25 +++++++------------------ drivers/pci/hotplug/shpchp_ctrl.c | 2 +- 3 files changed, 10 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index c0be7a1c3ff7..f6d606dde691 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -78,7 +78,7 @@ struct event_info { }; struct controller { - struct controller *next; + struct list_head ctrl_list; struct mutex crit_sect; /* critical section mutex */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ @@ -204,7 +204,7 @@ extern void shpchp_remove_ctrl_files(struct controller *ctrl); /* Global variables */ -extern struct controller *shpchp_ctrl_list; +extern struct list_head shpchp_ctrl_list; struct ctrl_reg { volatile u32 base_offset; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 547bf5d6fcca..0dd0642e691b 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -38,7 +38,7 @@ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; -struct controller *shpchp_ctrl_list; /* = NULL */ +LIST_HEAD(shpchp_ctrl_list); #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " @@ -452,13 +452,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Finish setting up the hot plug ctrl device */ ctrl->next_event = 0; - if (!shpchp_ctrl_list) { - shpchp_ctrl_list = ctrl; - ctrl->next = NULL; - } else { - ctrl->next = shpchp_ctrl_list; - shpchp_ctrl_list = ctrl; - } + list_add(&ctrl->ctrl_list, &shpchp_ctrl_list); shpchp_create_ctrl_files(ctrl); @@ -493,22 +487,17 @@ static int shpc_start_thread(void) static void __exit unload_shpchpd(void) { + struct list_head *tmp; + struct list_head *next; struct controller *ctrl; - struct controller *tctrl; - - ctrl = shpchp_ctrl_list; - while (ctrl) { + list_for_each_safe(tmp, next, &shpchp_ctrl_list) { + ctrl = list_entry(tmp, struct controller, ctrl_list); shpchp_remove_ctrl_files(ctrl); cleanup_slots(ctrl); - kfree (ctrl->pci_bus); ctrl->hpc_ops->release_ctlr(ctrl); - - tctrl = ctrl; - ctrl = ctrl->next; - - kfree(tctrl); + kfree(ctrl); } /* Stop the notification mechanism */ diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 65e69252e2f9..3a8e733aead5 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -688,7 +688,7 @@ static int event_thread(void* data) if (pushbutton_pending) shpchp_pushbutton_thread(pushbutton_pending); else - for (ctrl = shpchp_ctrl_list; ctrl; ctrl=ctrl->next) + list_for_each_entry(ctrl, &shpchp_ctrl_list, ctrl_list) interrupt_event_handler(ctrl); } dbg("event_thread signals exit\n"); -- cgit v1.2.3-59-g8ed1b From d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccf Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:59:24 +0900 Subject: [PATCH] shpchp - cleanup check command status This patch cleanups codes that check the command status. For this, it introduces a new semaphore "cmd_sem" for each controller. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 1 + drivers/pci/hotplug/shpchp_ctrl.c | 120 +------------------------------------- drivers/pci/hotplug/shpchp_hpc.c | 25 ++++++-- 3 files changed, 23 insertions(+), 123 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index f6d606dde691..b1e2a7705835 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -80,6 +80,7 @@ struct event_info { struct controller { struct list_head ctrl_list; struct mutex crit_sect; /* critical section mutex */ + struct mutex cmd_lock; /* command lock */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 3a8e733aead5..802c4c48d186 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -242,21 +242,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, int rc = 0; dbg("%s: change to speed %d\n", __FUNCTION__, speed); - mutex_lock(&ctrl->crit_sect); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } - mutex_unlock(&ctrl->crit_sect); return rc; } @@ -330,15 +319,6 @@ static int board_added(struct slot *p_slot) return -1; } - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return -1; - } - - if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { if (slots_not_empty) return WRONG_BUS_FREQUENCY; @@ -349,25 +329,12 @@ static int board_added(struct slot *p_slot) return WRONG_BUS_FREQUENCY; } - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); mutex_unlock(&ctrl->crit_sect); return rc; } - - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); - return rc; - } } rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); @@ -481,22 +448,12 @@ static int board_added(struct slot *p_slot) return rc; } - mutex_lock(&ctrl->crit_sect); /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); return rc; } - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); - return rc; - } - - mutex_unlock(&ctrl->crit_sect); - /* Wait for ~1 second */ wait_for_ctrl_irq (ctrl); @@ -520,40 +477,18 @@ static int board_added(struct slot *p_slot) p_slot->is_a_board = 0x01; p_slot->pwr_save = 1; - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - p_slot->hpc_ops->green_led_on(p_slot); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return 0; err_exit: - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return rc; } - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return rc; - } - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return(rc); } @@ -580,37 +515,19 @@ static int remove_board(struct slot *p_slot) if (p_slot->is_a_board) p_slot->status = 0x01; - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return rc; } - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return rc; - } rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); if (rc) { err("%s: Issue of Set Attention command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return rc; } - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - p_slot->pwr_save = 0; p_slot->is_a_board = 0; @@ -654,15 +571,9 @@ static void shpchp_pushbutton_thread (unsigned long slot) } else { p_slot->state = POWERON_STATE; - if (shpchp_enable_slot(p_slot)) { - /* Wait for exclusive access to hardware */ - mutex_lock(&p_slot->ctrl->crit_sect); - + if (shpchp_enable_slot(p_slot)) p_slot->hpc_ops->green_led_off(p_slot); - /* Done with exclusive hardware access */ - mutex_unlock(&p_slot->ctrl->crit_sect); - } p_slot->state = STATIC_STATE; } @@ -767,27 +678,12 @@ static void interrupt_event_handler(struct controller *ctrl) switch (p_slot->state) { case BLINKINGOFF_STATE: - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - p_slot->hpc_ops->green_led_on(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); break; case BLINKINGON_STATE: - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - p_slot->hpc_ops->green_led_off(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - break; default: warn("Not a valid state\n"); @@ -812,17 +708,10 @@ static void interrupt_event_handler(struct controller *ctrl) info(msg_button_on, p_slot->number); } - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* blink green LED and turn off amber */ p_slot->hpc_ops->green_led_blink(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - init_timer(&p_slot->task_event); p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; @@ -833,15 +722,8 @@ static void interrupt_event_handler(struct controller *ctrl) } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { /***********POWER FAULT********************/ dbg("%s: power fault\n", __FUNCTION__); - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - p_slot->hpc_ops->set_attention_status(p_slot, 1); - p_slot->hpc_ops->green_led_off(p_slot); - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); } else { /* refresh notification */ if (p_slot) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index ae81427e42b1..c32a1b16704f 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -231,6 +231,7 @@ static spinlock_t list_lock; 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); /* This is the interrupt polling timeout function. */ static void int_poll_timeout(unsigned long lphp_ctlr) @@ -303,10 +304,13 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) int i; DBG_ENTER_ROUTINE - + + mutex_lock(&slot->ctrl->cmd_lock); + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; + retval = -EINVAL; + goto out; } for (i = 0; i < 10; i++) { @@ -323,7 +327,8 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) if (cmd_status & 0x1) { /* After 1 sec and and the controller is still busy */ err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); - return -1; + retval = -EBUSY; + goto out; } ++t_slot; @@ -340,6 +345,17 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) * Wait for command completion. */ retval = shpc_wait_cmd(slot->ctrl); + if (retval) + goto out; + + cmd_status = hpc_check_cmd_status(slot->ctrl); + if (cmd_status) { + err("%s: Failed to issued command 0x%x (error code = %d)\n", + __FUNCTION__, cmd, cmd_status); + retval = -EIO; + } + out: + mutex_unlock(&slot->ctrl->cmd_lock); DBG_LEAVE_ROUTINE return retval; @@ -1343,7 +1359,6 @@ static struct hpc_ops shpchp_hpc_ops = { .green_led_blink = hpc_set_green_led_blink, .release_ctlr = hpc_release_ctlr, - .check_cmd_status = hpc_check_cmd_status, }; inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, @@ -1455,6 +1470,8 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); mutex_init(&ctrl->crit_sect); + mutex_init(&ctrl->cmd_lock); + /* Setup wait queue */ init_waitqueue_head(&ctrl->queue); -- cgit v1.2.3-59-g8ed1b From ef3be54777901e570185089f21fbe4498453f67e Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:00:33 +0900 Subject: [PATCH] shpchp - bugfix: add missing serialization Current shpchp driver might cause system panic because of lack of serialization. It can be reproduced very easily by the following operation. # cd /sys/bus/pci/slots/ # while true; do echo 0 > power ; echo 1 > power ; done & # while true; do echo 0 > power ; echo 1 > power ; done & This patch fixes this issue by changing shpchp to get appropreate semaphore for hot-plug operation. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_ctrl.c | 66 ++++++++++++++------------------------- 1 file changed, 24 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 802c4c48d186..1a7003d4ba96 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -307,15 +307,10 @@ static int board_added(struct slot *p_slot) __FUNCTION__, p_slot->device, ctrl->slot_device_offset, hp_slot); - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* Power on slot without connecting to bus */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { err("%s: Failed to power on slot\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return -1; } @@ -325,14 +320,12 @@ static int board_added(struct slot *p_slot) if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); return rc; } } @@ -346,16 +339,12 @@ static int board_added(struct slot *p_slot) if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); if (rc || bus_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get bus operation speed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -365,9 +354,6 @@ static int board_added(struct slot *p_slot) max_bus_speed = bus_speed; } - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); pi = 1; @@ -744,29 +730,25 @@ static void interrupt_event_handler(struct controller *ctrl) int shpchp_enable_slot (struct slot *p_slot) { u8 getstatus = 0; - int rc; + int rc, retval = -ENODEV; /* Check to see if (latch closed, card present, power off) */ 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); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + 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); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + 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); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - mutex_unlock(&p_slot->ctrl->crit_sect); p_slot->is_a_board = 1; @@ -781,27 +763,29 @@ int shpchp_enable_slot (struct slot *p_slot) && p_slot->ctrl->num_slots == 1) { /* handle amd pogo errata; this must be done before enable */ amd_pogo_errata_save_misc_reg(p_slot); - rc = board_added(p_slot); + retval = board_added(p_slot); /* handle amd pogo errata; this must be done after enable */ amd_pogo_errata_restore_misc_reg(p_slot); } else - rc = board_added(p_slot); + retval = board_added(p_slot); - if (rc) { + if (retval) { p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); } update_slot_info(p_slot); - return rc; + out: + mutex_unlock(&p_slot->ctrl->crit_sect); + return retval; } int shpchp_disable_slot (struct slot *p_slot) { u8 getstatus = 0; - int ret = 0; + int rc, retval = -ENODEV; if (!p_slot->ctrl) return -ENODEV; @@ -809,28 +793,26 @@ int shpchp_disable_slot (struct slot *p_slot) /* Check to see if (latch closed, card present, power on) */ mutex_lock(&p_slot->ctrl->crit_sect); - ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); - if (ret || !getstatus) { + 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); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - if (ret || getstatus) { + 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); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (ret || !getstatus) { + 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); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - mutex_unlock(&p_slot->ctrl->crit_sect); - ret = remove_board(p_slot); + retval = remove_board(p_slot); update_slot_info(p_slot); - return ret; + out: + mutex_unlock(&p_slot->ctrl->crit_sect); + return retval; } -- cgit v1.2.3-59-g8ed1b From 287588b3537d0ce56a83f54d0e6ffcd60e54b569 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:01:35 +0900 Subject: [PATCH] pcihp_skeleton.c cleanup This patch cleans up pcihp_skelton.c as follows. o Move slot name area into struct slot. o Replace kmalloc with kzalloc and clean up the arg of sizeof() o Fix the wrong use of get_*_status() functions. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pcihp_skeleton.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index 3194d51c6ec9..0a46f549676a 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c @@ -37,10 +37,12 @@ #include #include "pci_hotplug.h" +#define SLOT_NAME_SIZE 10 struct slot { u8 number; struct hotplug_slot *hotplug_slot; struct list_head slot_list; + char name[SLOT_NAME_SIZE]; }; static LIST_HEAD(slot_list); @@ -233,12 +235,10 @@ static void release_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } -#define SLOT_NAME_SIZE 10 static void make_slot_name(struct slot *slot) { /* @@ -257,7 +257,6 @@ static int __init init_slots(void) struct slot *slot; struct hotplug_slot *hotplug_slot; struct hotplug_slot_info *info; - char *name; int retval = -ENOMEM; int i; @@ -266,31 +265,23 @@ static int __init init_slots(void) * with the pci_hotplug subsystem. */ for (i = 0; i < num_slots; ++i) { - slot = kmalloc(sizeof(struct slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(struct slot)); - hotplug_slot = kmalloc(sizeof(struct hotplug_slot), - GFP_KERNEL); + hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); if (!hotplug_slot) goto error_slot; - memset(hotplug_slot, 0, sizeof (struct hotplug_slot)); slot->hotplug_slot = hotplug_slot; - info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) goto error_hpslot; - memset(info, 0, sizeof (struct hotplug_slot_info)); hotplug_slot->info = info; - name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!name) - goto error_info; - hotplug_slot->name = name; - slot->number = i; + hotplug_slot->name = slot->name; hotplug_slot->private = slot; hotplug_slot->release = &release_slot; make_slot_name(slot); @@ -300,16 +291,16 @@ static int __init init_slots(void) * Initialize the slot info structure with some known * good values. */ - info->power_status = get_power_status(slot); - info->attention_status = get_attention_status(slot); - info->latch_status = get_latch_status(slot); - info->adapter_status = get_adapter_status(slot); + get_power_status(hotplug_slot, &info->power_status); + get_attention_status(hotplug_slot, &info->attention_status); + get_latch_status(hotplug_slot, &info->latch_status); + get_adapter_status(hotplug_slot, &info->adapter_status); dbg("registering slot %d\n", i); retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); - goto error_name; + goto error_info; } /* add slot to our internal list */ @@ -317,8 +308,6 @@ static int __init init_slots(void) } return 0; -error_name: - kfree(name); error_info: kfree(info); error_hpslot: -- cgit v1.2.3-59-g8ed1b From 57c95c0d1c9ec83877dfea2f62bebf31059bc93c Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:02:41 +0900 Subject: [PATCH] shpchp - replace kmalloc() with kzalloc() and cleanup arg of sizeof() This patch replaces kmalloc() and memset() pair with kzalloc() and cleans up the arg of sizeof() in SHPCHP driver. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_core.c | 15 +++++---------- drivers/pci/hotplug/shpchp_hpc.c | 4 +--- 2 files changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 0dd0642e691b..08be8c1f5dcc 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -117,22 +117,18 @@ static int init_slots(struct controller *ctrl) u32 sun; for (i = 0; i < ctrl->num_slots; i++) { - slot = kmalloc(sizeof(struct slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(struct slot)); - hotplug_slot = kmalloc(sizeof(struct hotplug_slot), - GFP_KERNEL); + hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); if (!hotplug_slot) goto error_slot; - memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); slot->hotplug_slot = hotplug_slot; - info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) goto error_hpslot; - memset(info, 0, sizeof (struct hotplug_slot_info)); hotplug_slot->info = info; name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); @@ -383,12 +379,11 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (!is_shpc_capable(pdev)) return -ENODEV; - ctrl = kmalloc(sizeof(struct controller), GFP_KERNEL); + ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); goto err_out_none; } - memset(ctrl, 0, sizeof(struct controller)); INIT_LIST_HEAD(&ctrl->slot_list); rc = shpc_init(ctrl, pdev); @@ -400,7 +395,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, ctrl); - ctrl->pci_bus = kmalloc(sizeof (*ctrl->pci_bus), GFP_KERNEL); + ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); if (!ctrl->pci_bus) { err("out of memory\n"); rc = -ENOMEM; diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index c32a1b16704f..1a6b5448f81d 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -1390,15 +1390,13 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ spin_lock_init(&list_lock); - php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); + php_ctlr = kzalloc(sizeof(*php_ctlr), GFP_KERNEL); if (!php_ctlr) { /* allocate controller state data */ err("%s: HPC controller memory allocation error!\n", __FUNCTION__); goto abort; } - memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s)); - php_ctlr->pci_dev = pdev; /* save pci_dev in context */ if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == -- cgit v1.2.3-59-g8ed1b From 8abebe13f9df5b93be521eeefbf349236ddcd4eb Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:03:40 +0900 Subject: [PATCH] shpchp - removed unncessary 'magic' member from slot This patch removes unnecessary 'magic' member from struct slot of SHPCHP driver. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 6 ------ drivers/pci/hotplug/shpchp_core.c | 1 - 2 files changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index b1e2a7705835..1e6d354fff38 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -53,9 +53,7 @@ extern int shpchp_debug; #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 SLOT_MAGIC 0x67267321 struct slot { - u32 magic; u8 bus; u8 device; u16 status; @@ -287,10 +285,6 @@ static inline int slot_paranoia_check (struct slot *slot, const char *function) dbg("%s - slot == NULL", function); return -1; } - if (slot->magic != SLOT_MAGIC) { - dbg("%s - bad magic number for slot", function); - return -1; - } if (!slot->hotplug_slot) { dbg("%s - slot->hotplug_slot == NULL!", function); return -1; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 08be8c1f5dcc..4161da4bf4ba 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -137,7 +137,6 @@ static int init_slots(struct controller *ctrl) hotplug_slot->name = name; slot->hp_slot = i; - slot->magic = SLOT_MAGIC; slot->ctrl = ctrl; slot->bus = ctrl->slot_bus; slot->device = ctrl->slot_device_offset + i; -- cgit v1.2.3-59-g8ed1b From bbe779db9f97e1c99b3c7ce1ebb26bbaecbdb2a9 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:04:56 +0900 Subject: [PATCH] shpchp - move slot name into struct slot This patch moves slot name area into struct slot. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 2 ++ drivers/pci/hotplug/shpchp_core.c | 14 +++----------- 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 1e6d354fff38..dc12b0dbb9b2 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -53,6 +53,7 @@ extern int shpchp_debug; #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 SLOT_NAME_SIZE 10 struct slot { u8 bus; u8 device; @@ -68,6 +69,7 @@ struct slot { struct hpc_ops *hpc_ops; struct hotplug_slot *hotplug_slot; struct list_head slot_list; + char name[SLOT_NAME_SIZE]; }; struct event_info { diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 4161da4bf4ba..cb4ac43ea95c 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -94,12 +94,10 @@ static void release_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } -#define SLOT_NAME_SIZE 10 static void make_slot_name(struct slot *slot) { snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", @@ -111,7 +109,6 @@ static int init_slots(struct controller *ctrl) struct slot *slot; struct hotplug_slot *hotplug_slot; struct hotplug_slot_info *info; - char *name; int retval = -ENOMEM; int i; u32 sun; @@ -131,10 +128,7 @@ static int init_slots(struct controller *ctrl) goto error_hpslot; hotplug_slot->info = info; - name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!name) - goto error_info; - hotplug_slot->name = name; + hotplug_slot->name = slot->name; slot->hp_slot = i; slot->ctrl = ctrl; @@ -144,7 +138,7 @@ static int init_slots(struct controller *ctrl) if (shpchprm_get_physical_slot_number(ctrl, &sun, slot->bus, slot->device)) - goto error_name; + goto error_info; slot->number = sun; @@ -165,15 +159,13 @@ static int init_slots(struct controller *ctrl) retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); - goto error_name; + goto error_info; } list_add(&slot->slot_list, &ctrl->slot_list); } return 0; -error_name: - kfree(name); error_info: kfree(info); error_hpslot: -- cgit v1.2.3-59-g8ed1b From e4e73041ecc4a3559c42ed9489f58531c2a8646b Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:05:57 +0900 Subject: [PATCH] shpchp - Fix incorrect return value of interrupt handler Current SHPCHP driver has a bug in its interrupt handler which cause "IRQ #: nobody cared" oops. This problem can be reproduced easily by the following operation. # cd /sys/bus/pci/slots/ # while true; do echo 1 > attention ; done & The reason is that when command complete interrupt is raised, current SHPCHP driver's interrupt handler returns IRQ_NONE regardless of if the interrupt is handled or not. This patch fixes this issue. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 1a6b5448f81d..943ed2b4dabe 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -1109,14 +1109,8 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) wake_up_interruptible(&ctrl->queue); } - if ((intr_loc = (intr_loc >> 1)) == 0) { - /* Unmask Global Interrupt Mask */ - temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); - temp_dword &= 0xfffffffe; - writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); - - return IRQ_NONE; - } + if ((intr_loc = (intr_loc >> 1)) == 0) + goto out; for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { /* To find out which slot has interrupt pending */ @@ -1146,6 +1140,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) 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); -- cgit v1.2.3-59-g8ed1b From bbe8f9a3e76c551973ee739de10b26581d78b45f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 14 Feb 2006 16:23:57 +0000 Subject: [PATCH] PCI: Avoid leaving MASTER_ABORT disabled permanently when returning from pci_scan_bridge. > On Mon, Feb 13, 2006 at 05:13:21PM -0800, David S. Miller wrote: > > > > In drivers/pci/probe.c:pci_scan_bridge(), if this is not the first > > pass (pass != 0) we don't restore the PCI_BRIDGE_CONTROL_REGISTER and > > thus leave PCI_BRIDGE_CTL_MASTER_ABORT off: > > > > int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass) > > { > > ... > > /* Disable MasterAbortMode during probing to avoid reporting > > of bus errors (in some architectures) */ > > pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bctl); > > pci_write_config_word(dev, PCI_BRIDGE_CONTROL, > > bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); > > ... > > if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) { > > unsigned int cmax, busnr; > > /* > > * Bus already configured by firmware, process it in the first > > * pass and just note the configuration. > > */ > > if (pass) > > return max; > > ... > > } > > > > pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); > > ... > > > > This doesn't seem intentional. Agreed, looks like an accident. The patch [1] originally came from Kip Walker (Broadcom back then) between 2.6.0-test3 and 2.6.0-test4. As I recall it was supposed to fix an issue with with PCI aborts being signalled by the PCI bridge of the Broadcom BCM1250 family of SOCs when probing behind pci_scan_bridge. It is undeseriable to disable PCI_BRIDGE_CTL_MASTER_ABORT in pci_{read,write)_config_* and the behaviour wasn't considered a bug in need of a workaround, so this was put in probe.c. I don't have an affected system at hand, so can't really test but I propose something like the below patch. [1] http://www.linux-mips.org/git?p=linux.git;a=commit;h=599457e0cb702a31a3247ea6a5d9c6c99c4cf195 [PCI] Avoid leaving MASTER_ABORT disabled permanently when returning from pci_scan_bridge. Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- drivers/pci/probe.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 63751a283817..3bc0fcd71d03 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -456,7 +456,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max * pass and just note the configuration. */ if (pass) - return max; + goto out; busnr = (buses >> 8) & 0xFF; /* @@ -466,12 +466,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max if (pci_find_bus(pci_domain_nr(bus), busnr)) { printk(KERN_INFO "PCI: Bus %04x:%02x already known\n", pci_domain_nr(bus), busnr); - return max; + goto out; } child = pci_add_new_bus(bus, dev, busnr); if (!child) - return max; + goto out; child->primary = buses & 0xFF; child->subordinate = (buses >> 16) & 0xFF; child->bridge_ctl = bctl; @@ -496,7 +496,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max bus ranges. */ pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses & ~0xffffff); - return max; + goto out; } /* Clear errors */ @@ -505,7 +505,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max /* Prevent assigning a bus number that already exists. * This can happen when a bridge is hot-plugged */ if (pci_find_bus(pci_domain_nr(bus), max+1)) - return max; + goto out; child = pci_add_new_bus(bus, dev, ++max); buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) @@ -581,8 +581,6 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max); } - pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); - sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number); while (bus->parent) { @@ -601,6 +599,9 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max bus = bus->parent; } +out: + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); + return max; } -- cgit v1.2.3-59-g8ed1b From 09e1218eccf58f6174fa68360a7c8dcfe457fe9b Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:38 -0800 Subject: [PATCH] shpchp: Remove unused pci_bus member from controller structure This patch removes unused 'pci_bus' member from controller structure. This patch have no functional change. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 1 - drivers/pci/hotplug/shpchp_core.c | 13 +------------ 2 files changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index dc12b0dbb9b2..ce792b3cf9de 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -85,7 +85,6 @@ struct controller { int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ struct pci_dev *pci_dev; - struct pci_bus *pci_bus; struct event_info event_queue[10]; struct list_head slot_list; struct hpc_ops *hpc_ops; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index cb4ac43ea95c..8b21fc206712 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -386,14 +386,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, ctrl); - ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); - if (!ctrl->pci_bus) { - err("out of memory\n"); - rc = -ENOMEM; - goto err_out_unmap_mmio_region; - } - - memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); ctrl->bus = pdev->bus->number; ctrl->slot_bus = pdev->subordinate->number; ctrl->device = PCI_SLOT(pdev->devfn); @@ -408,7 +400,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = get_ctlr_slot_config(ctrl); if (rc) { err(msg_initialization_err, rc); - goto err_out_free_ctrl_bus; + goto err_out_unmap_mmio_region; } first_device_num = ctrl->slot_device_offset; num_ctlr_slots = ctrl->num_slots; @@ -446,8 +438,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err_out_free_ctrl_slot: cleanup_slots(ctrl); -err_out_free_ctrl_bus: - kfree(ctrl->pci_bus); err_out_unmap_mmio_region: ctrl->hpc_ops->release_ctlr(ctrl); err_out_free_ctrl: @@ -481,7 +471,6 @@ static void __exit unload_shpchpd(void) ctrl = list_entry(tmp, struct controller, ctrl_list); shpchp_remove_ctrl_files(ctrl); cleanup_slots(ctrl); - kfree (ctrl->pci_bus); ctrl->hpc_ops->release_ctlr(ctrl); kfree(ctrl); } -- cgit v1.2.3-59-g8ed1b From 68c0b671491088d79611fa965bbf94b3bc0024a4 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:42 -0800 Subject: [PATCH] shpchp: Remove unused wait_for_ctrl_irq The wait_for_ctrl_irq() function in SHPCHP driver is no longer needed. This patch removes that. This patch has no functional change. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 21 --------------------- drivers/pci/hotplug/shpchp_ctrl.c | 2 +- 2 files changed, 1 insertion(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index ce792b3cf9de..6e1fb1bdc243 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -325,27 +325,6 @@ static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device) return NULL; } -static inline int wait_for_ctrl_irq (struct controller *ctrl) -{ - DECLARE_WAITQUEUE(wait, current); - int retval = 0; - - add_wait_queue(&ctrl->queue, &wait); - - if (!shpchp_poll_mode) { - /* Sleep for up to 1 second */ - msleep_interruptible(1000); - } else { - /* Sleep for up to 2 seconds */ - msleep_interruptible(2000); - } - remove_wait_queue(&ctrl->queue, &wait); - if (signal_pending(current)) - retval = -EINTR; - - return retval; -} - static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot) { u32 pcix_misc2_temp; diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 1a7003d4ba96..b709328a4145 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -441,7 +441,7 @@ static int board_added(struct slot *p_slot) } /* Wait for ~1 second */ - wait_for_ctrl_irq (ctrl); + msleep(1000); dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); /* Check for a power fault */ -- cgit v1.2.3-59-g8ed1b From f7391f5325ea744f0632f7ef39a90085162743ac Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:45 -0800 Subject: [PATCH] shpchp: event handling rework The event handler of SHPCHP driver is unnecessarily very complex. In addition, current event handler can only a fixed number of events at the same time, and some of events would be lost if several number of events happened at the same time. This patch simplify the event handler by using 'work queue', and it also fix the above-mentioned issue. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 13 +- drivers/pci/hotplug/shpchp_core.c | 49 ++---- drivers/pci/hotplug/shpchp_ctrl.c | 313 +++++++++++--------------------------- drivers/pci/hotplug/shpchp_hpc.c | 10 ++ 4 files changed, 119 insertions(+), 266 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 6e1fb1bdc243..87db07cfebdf 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -46,6 +46,7 @@ extern int shpchp_poll_mode; extern int shpchp_poll_time; extern int shpchp_debug; +extern struct workqueue_struct *shpchp_wq; /*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ #define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) @@ -70,11 +71,13 @@ struct slot { struct hotplug_slot *hotplug_slot; struct list_head slot_list; char name[SLOT_NAME_SIZE]; + struct work_struct work; /* work for button event */ }; struct event_info { u32 event_type; - u8 hp_slot; + struct slot *p_slot; + struct work_struct work; }; struct controller { @@ -85,11 +88,9 @@ struct controller { int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ struct pci_dev *pci_dev; - struct event_info event_queue[10]; struct list_head slot_list; struct hpc_ops *hpc_ops; wait_queue_head_t queue; /* sleep & wake process */ - u8 next_event; u8 bus; u8 device; u8 function; @@ -180,9 +181,6 @@ struct hotplug_params { /* sysfs functions for the hotplug controller info */ extern void shpchp_create_ctrl_files (struct controller *ctrl); -/* controller functions */ -extern int shpchp_event_start_thread(void); -extern void shpchp_event_stop_thread(void); extern int shpchp_enable_slot(struct slot *slot); extern int shpchp_disable_slot(struct slot *slot); @@ -201,7 +199,8 @@ extern void get_hp_params_from_firmware(struct pci_dev *dev, extern int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum); extern void shpchp_remove_ctrl_files(struct controller *ctrl); - +extern void cleanup_slots(struct controller *ctrl); +extern void shpchp_pushbutton_thread(void *data); /* Global variables */ extern struct list_head shpchp_ctrl_list; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 8b21fc206712..5de659d23d1a 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "shpchp.h" /* Global variables */ @@ -39,6 +40,7 @@ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; LIST_HEAD(shpchp_ctrl_list); +struct workqueue_struct *shpchp_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " @@ -57,7 +59,6 @@ MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); #define SHPC_MODULE_NAME "shpchp" -static int shpc_start_thread (void); static int set_attention_status (struct hotplug_slot *slot, u8 value); static int enable_slot (struct hotplug_slot *slot); static int disable_slot (struct hotplug_slot *slot); @@ -141,6 +142,7 @@ static int init_slots(struct controller *ctrl) goto error_info; slot->number = sun; + INIT_WORK(&slot->work, shpchp_pushbutton_thread, slot); /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; @@ -176,7 +178,7 @@ error: return retval; } -static void cleanup_slots(struct controller *ctrl) +void cleanup_slots(struct controller *ctrl) { struct list_head *tmp; struct list_head *next; @@ -185,6 +187,8 @@ static void cleanup_slots(struct controller *ctrl) list_for_each_safe(tmp, next, &ctrl->slot_list) { slot = list_entry(tmp, struct slot, slot_list); list_del(&slot->slot_list); + cancel_delayed_work(&slot->work); + flush_workqueue(shpchp_wq); pci_hp_deregister(slot->hotplug_slot); } } @@ -400,7 +404,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = get_ctlr_slot_config(ctrl); if (rc) { err(msg_initialization_err, rc); - goto err_out_unmap_mmio_region; + goto err_out_release_ctlr; } first_device_num = ctrl->slot_device_offset; num_ctlr_slots = ctrl->num_slots; @@ -411,7 +415,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = init_slots(ctrl); if (rc) { err(msg_initialization_err, 6); - goto err_out_free_ctrl_slot; + goto err_out_release_ctlr; } /* Now hpc_functions (slot->hpc_ops->functions) are ready */ @@ -427,18 +431,13 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ctrl->speed = PCI_SPEED_33MHz; } - /* Finish setting up the hot plug ctrl device */ - ctrl->next_event = 0; - list_add(&ctrl->ctrl_list, &shpchp_ctrl_list); shpchp_create_ctrl_files(ctrl); return 0; -err_out_free_ctrl_slot: - cleanup_slots(ctrl); -err_out_unmap_mmio_region: +err_out_release_ctlr: ctrl->hpc_ops->release_ctlr(ctrl); err_out_free_ctrl: kfree(ctrl); @@ -446,21 +445,6 @@ err_out_none: return -ENODEV; } -static int shpc_start_thread(void) -{ - int retval = 0; - - dbg("Initialize + Start the notification/polling mechanism \n"); - - retval = shpchp_event_start_thread(); - if (retval) { - dbg("shpchp_event_start_thread() failed\n"); - return retval; - } - - return retval; -} - static void __exit unload_shpchpd(void) { struct list_head *tmp; @@ -470,14 +454,11 @@ static void __exit unload_shpchpd(void) list_for_each_safe(tmp, next, &shpchp_ctrl_list) { ctrl = list_entry(tmp, struct controller, ctrl_list); shpchp_remove_ctrl_files(ctrl); - cleanup_slots(ctrl); ctrl->hpc_ops->release_ctlr(ctrl); kfree(ctrl); } - /* Stop the notification mechanism */ - shpchp_event_stop_thread(); - + destroy_workqueue(shpchp_wq); } static struct pci_device_id shpcd_pci_tbl[] = { @@ -501,17 +482,15 @@ static int __init shpcd_init(void) shpchp_poll_mode = 1; #endif - retval = shpc_start_thread(); - if (retval) - goto error_hpc_init; + 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"); - -error_hpc_init: if (retval) { - shpchp_event_stop_thread(); + destroy_workqueue(shpchp_wq); } return retval; } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b709328a4145..2411f3bd08da 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -32,44 +32,46 @@ #include #include #include +#include #include "../pci.h" #include "shpchp.h" -static void interrupt_event_handler(struct controller *ctrl); +static void interrupt_event_handler(void *data); -static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ -static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ -static int event_finished; -static unsigned long pushbutton_pending; /* = 0 */ +static int queue_interrupt_event(struct slot *p_slot, u32 event_type) +{ + struct event_info *info; + + info = kmalloc(sizeof(*info), GFP_ATOMIC); + if (!info) + return -ENOMEM; + + info->event_type = event_type; + info->p_slot = p_slot; + INIT_WORK(&info->work, interrupt_event_handler, info); + + queue_work(shpchp_wq, &info->work); + + return 0; +} u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - u8 getstatus; - struct event_info *taskInfo; + u32 event_type; /* Attention Button Change */ dbg("shpchp: Attention button interrupt received.\n"); - /* This is the structure that tells the worker thread what to do */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); - p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; /* * Button pressed - See if need to TAKE ACTION!!! */ info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_BUTTON_PRESS; + event_type = INT_BUTTON_PRESS; if ((p_slot->state == BLINKINGON_STATE) || (p_slot->state == BLINKINGOFF_STATE)) { @@ -77,7 +79,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) * attention again before the 5 sec. limit expires to cancel hot-add * or hot-remove */ - taskInfo->event_type = INT_BUTTON_CANCEL; + event_type = INT_BUTTON_CANCEL; info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); } else if ((p_slot->state == POWERON_STATE) || (p_slot->state == POWEROFF_STATE)) { @@ -85,12 +87,11 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) * means that the previous attention button action to hot-add or * hot-remove is undergoing */ - taskInfo->event_type = INT_BUTTON_IGNORE; + event_type = INT_BUTTON_IGNORE; info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); return 0; @@ -100,21 +101,12 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; u8 getstatus; - struct event_info *taskInfo; + u32 event_type; /* Switch Change */ dbg("shpchp: Switch interrupt received.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); @@ -126,9 +118,9 @@ 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); - taskInfo->event_type = INT_SWITCH_OPEN; + event_type = INT_SWITCH_OPEN; if (p_slot->pwr_save && p_slot->presence_save) { - taskInfo->event_type = INT_POWER_FAULT; + event_type = INT_POWER_FAULT; err("Surprise Removal of card\n"); } } else { @@ -136,34 +128,23 @@ 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); - taskInfo->event_type = INT_SWITCH_CLOSE; + event_type = INT_SWITCH_CLOSE; } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); - return rc; + return 1; } u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - /*u8 temp_byte;*/ - struct event_info *taskInfo; + u32 event_type; /* Presence Change */ dbg("shpchp: Presence/Notify input change.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); /* @@ -175,39 +156,29 @@ 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); - taskInfo->event_type = INT_PRESENCE_ON; + event_type = INT_PRESENCE_ON; } else { /* * Not Present */ info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_PRESENCE_OFF; + event_type = INT_PRESENCE_OFF; } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); - return rc; + return 1; } u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - struct event_info *taskInfo; + u32 event_type; /* Power fault */ dbg("shpchp: Power fault interrupt received.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { @@ -216,21 +187,21 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) */ info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); p_slot->status = 0x00; - taskInfo->event_type = INT_POWER_FAULT_CLEAR; + event_type = INT_POWER_FAULT_CLEAR; } else { /* * Power fault */ info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_POWER_FAULT; + event_type = INT_POWER_FAULT; /* set power fault status for this board */ p_slot->status = 0xFF; info("power fault bit %x set\n", hp_slot); } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ - return rc; + queue_interrupt_event(p_slot, event_type); + + return 1; } /* The following routines constitute the bulk of the @@ -521,14 +492,6 @@ static int remove_board(struct slot *p_slot) } -static void pushbutton_helper_thread (unsigned long data) -{ - pushbutton_pending = data; - - up(&event_semaphore); -} - - /** * shpchp_pushbutton_thread * @@ -536,90 +499,24 @@ static void pushbutton_helper_thread (unsigned long data) * Handles all pending events and exits. * */ -static void shpchp_pushbutton_thread (unsigned long slot) +void shpchp_pushbutton_thread(void *data) { - struct slot *p_slot = (struct slot *) slot; + struct slot *p_slot = data; u8 getstatus; - - pushbutton_pending = 0; - - if (!p_slot) { - dbg("%s: Error! slot NULL\n", __FUNCTION__); - return; - } p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (getstatus) { p_slot->state = POWEROFF_STATE; - shpchp_disable_slot(p_slot); p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; - if (shpchp_enable_slot(p_slot)) p_slot->hpc_ops->green_led_off(p_slot); - p_slot->state = STATIC_STATE; } - - return; -} - - -/* this is the main worker thread */ -static int event_thread(void* data) -{ - struct controller *ctrl; - lock_kernel(); - daemonize("shpchpd_event"); - unlock_kernel(); - - while (1) { - dbg("!!!!event_thread sleeping\n"); - down_interruptible (&event_semaphore); - dbg("event_thread woken finished = %d\n", event_finished); - if (event_finished || signal_pending(current)) - break; - /* Do stuff here */ - if (pushbutton_pending) - shpchp_pushbutton_thread(pushbutton_pending); - else - list_for_each_entry(ctrl, &shpchp_ctrl_list, ctrl_list) - interrupt_event_handler(ctrl); - } - dbg("event_thread signals exit\n"); - up(&event_exit); - return 0; -} - -int shpchp_event_start_thread (void) -{ - int pid; - - /* initialize our semaphores */ - init_MUTEX_LOCKED(&event_exit); - event_finished=0; - - init_MUTEX_LOCKED(&event_semaphore); - pid = kernel_thread(event_thread, NULL, 0); - - if (pid < 0) { - err ("Can't start up our event thread\n"); - return -1; - } - return 0; -} - - -void shpchp_event_stop_thread (void) -{ - event_finished = 1; - up(&event_semaphore); - down(&event_exit); } - static int update_slot_info (struct slot *slot) { struct hotplug_slot_info *info; @@ -639,91 +536,59 @@ static int update_slot_info (struct slot *slot) return result; } -static void interrupt_event_handler(struct controller *ctrl) +static void interrupt_event_handler(void *data) { - int loop = 0; - int change = 1; - u8 hp_slot; + struct event_info *info = data; + struct slot *p_slot = info->p_slot; u8 getstatus; - struct slot *p_slot; - while (change) { - change = 0; - - for (loop = 0; loop < 10; loop++) { - if (ctrl->event_queue[loop].event_type != 0) { - dbg("%s:loop %x event_type %x\n", __FUNCTION__, loop, - ctrl->event_queue[loop].event_type); - hp_slot = ctrl->event_queue[loop].hp_slot; - - p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - - if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { - dbg("%s: button cancel\n", __FUNCTION__); - del_timer(&p_slot->task_event); - - switch (p_slot->state) { - case BLINKINGOFF_STATE: - p_slot->hpc_ops->green_led_on(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - case BLINKINGON_STATE: - p_slot->hpc_ops->green_led_off(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - default: - warn("Not a valid state\n"); - return; - } - info(msg_button_cancel, p_slot->number); - p_slot->state = STATIC_STATE; - } else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { - /* Button Pressed (No action on 1st press...) */ - dbg("%s: Button pressed\n", __FUNCTION__); - - p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (getstatus) { - /* slot is on */ - dbg("%s: slot is on\n", __FUNCTION__); - p_slot->state = BLINKINGOFF_STATE; - info(msg_button_off, p_slot->number); - } else { - /* slot is off */ - dbg("%s: slot is off\n", __FUNCTION__); - p_slot->state = BLINKINGON_STATE; - info(msg_button_on, p_slot->number); - } - - /* blink green LED and turn off amber */ - p_slot->hpc_ops->green_led_blink(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - init_timer(&p_slot->task_event); - p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ - p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; - p_slot->task_event.data = (unsigned long) p_slot; - - dbg("%s: add_timer p_slot = %p\n", __FUNCTION__,(void *) p_slot); - add_timer(&p_slot->task_event); - } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { - /***********POWER FAULT********************/ - dbg("%s: power fault\n", __FUNCTION__); - p_slot->hpc_ops->set_attention_status(p_slot, 1); - p_slot->hpc_ops->green_led_off(p_slot); - } else { - /* refresh notification */ - if (p_slot) - update_slot_info(p_slot); - } - - ctrl->event_queue[loop].event_type = 0; + switch (info->event_type) { + case INT_BUTTON_CANCEL: + dbg("%s: button cancel\n", __FUNCTION__); + cancel_delayed_work(&p_slot->work); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + p_slot->hpc_ops->green_led_on(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + break; + case BLINKINGON_STATE: + p_slot->hpc_ops->green_led_off(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + break; + default: + warn("Not a valid state\n"); + return; + } + info(msg_button_cancel, p_slot->number); + p_slot->state = STATIC_STATE; + break; + case INT_BUTTON_PRESS: + dbg("%s: Button pressed\n", __FUNCTION__); + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (getstatus) { + p_slot->state = BLINKINGOFF_STATE; + info(msg_button_off, p_slot->number); + } else { + p_slot->state = BLINKINGON_STATE; + info(msg_button_on, p_slot->number); + } + /* blink green LED and turn off amber */ + p_slot->hpc_ops->green_led_blink(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); - change = 1; - } - } /* End of FOR loop */ + queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); + break; + case INT_POWER_FAULT: + dbg("%s: power fault\n", __FUNCTION__); + p_slot->hpc_ops->set_attention_status(p_slot, 1); + p_slot->hpc_ops->green_led_off(p_slot); + break; + default: + update_slot_info(p_slot); + break; } - return; + kfree(info); } diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 943ed2b4dabe..b392606a905a 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -813,6 +813,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; DBG_ENTER_ROUTINE @@ -821,6 +822,14 @@ static void hpc_release_ctlr(struct controller *ctrl) return ; } + /* + * Mask all slot event interrupts + */ + for (i = 0; i < ctrl->num_slots; i++) + writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i)); + + cleanup_slots(ctrl); + if (shpchp_poll_mode) { del_timer(&php_ctlr->int_poll_timer); } else { @@ -830,6 +839,7 @@ static void hpc_release_ctlr(struct controller *ctrl) pci_disable_msi(php_ctlr->pci_dev); } } + if (php_ctlr->pci_dev) { iounmap(php_ctlr->creg); release_mem_region(ctrl->mmio_base, ctrl->mmio_size); -- cgit v1.2.3-59-g8ed1b From a246fa4e9f0f1b5096a1cad0659d22fb10fb3732 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:48 -0800 Subject: [PATCH] shpchp: Fix slot state handling Current SHPCHP driver doesn't care about the confliction between hotplug operation via sysfs and hotplug operation via attention button. So if those ware conflicted, slot could be an unexpected state. This patch changes SHPCHP driver to handle slot state properly. With this patch, slot events are handled according to the current slot state as shown at the Table below. Table. Slot States and Event Handling ========================================================================= Slot State Event and Action ========================================================================= STATIC - Go to POWERON state if user initiates (Slot enabled, insertion request via sysfs Slot disabled) - Go to POWEROFF state if user initiates removal request via sysfs - Go to BLINKINGON state if user presses attention button when the slot is disabled - Go to BLINKINGOFF state if user presses attention button when the slot is enabled --- drivers/pci/hotplug/shpchp.h | 7 +- drivers/pci/hotplug/shpchp_core.c | 8 +- drivers/pci/hotplug/shpchp_ctrl.c | 227 +++++++++++++++++++++++++++++--------- 3 files changed, 181 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 87db07cfebdf..dd449512cf68 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -72,6 +72,7 @@ struct slot { struct list_head slot_list; char name[SLOT_NAME_SIZE]; struct work_struct work; /* work for button event */ + struct mutex lock; }; struct event_info { @@ -181,8 +182,8 @@ struct hotplug_params { /* sysfs functions for the hotplug controller info */ extern void shpchp_create_ctrl_files (struct controller *ctrl); -extern int shpchp_enable_slot(struct slot *slot); -extern int shpchp_disable_slot(struct slot *slot); +extern int shpchp_sysfs_enable_slot(struct slot *slot); +extern int shpchp_sysfs_disable_slot(struct slot *slot); extern u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id); extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id); @@ -200,7 +201,7 @@ extern int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum); extern void shpchp_remove_ctrl_files(struct controller *ctrl); extern void cleanup_slots(struct controller *ctrl); -extern void shpchp_pushbutton_thread(void *data); +extern void queue_pushbutton_work(void *data); /* Global variables */ extern struct list_head shpchp_ctrl_list; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 5de659d23d1a..fa60ae47d91d 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -136,13 +136,14 @@ static int init_slots(struct controller *ctrl) slot->bus = ctrl->slot_bus; slot->device = ctrl->slot_device_offset + i; slot->hpc_ops = ctrl->hpc_ops; + mutex_init(&slot->lock); if (shpchprm_get_physical_slot_number(ctrl, &sun, slot->bus, slot->device)) goto error_info; slot->number = sun; - INIT_WORK(&slot->work, shpchp_pushbutton_thread, slot); + INIT_WORK(&slot->work, queue_pushbutton_work, slot); /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; @@ -188,6 +189,7 @@ void cleanup_slots(struct controller *ctrl) slot = list_entry(tmp, struct slot, slot_list); list_del(&slot->slot_list); cancel_delayed_work(&slot->work); + flush_scheduled_work(); flush_workqueue(shpchp_wq); pci_hp_deregister(slot->hotplug_slot); } @@ -244,7 +246,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - return shpchp_enable_slot(slot); + return shpchp_sysfs_enable_slot(slot); } static int disable_slot (struct hotplug_slot *hotplug_slot) @@ -253,7 +255,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - return shpchp_disable_slot(slot); + return shpchp_sysfs_disable_slot(slot); } static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 2411f3bd08da..10f3257b18a7 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -37,6 +37,8 @@ #include "shpchp.h" static void interrupt_event_handler(void *data); +static int shpchp_enable_slot(struct slot *p_slot); +static int shpchp_disable_slot(struct slot *p_slot); static int queue_interrupt_event(struct slot *p_slot, u32 event_type) { @@ -50,7 +52,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->p_slot = p_slot; INIT_WORK(&info->work, interrupt_event_handler, info); - queue_work(shpchp_wq, &info->work); + schedule_work(&info->work); return 0; } @@ -73,24 +75,6 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); event_type = INT_BUTTON_PRESS; - if ((p_slot->state == BLINKINGON_STATE) - || (p_slot->state == BLINKINGOFF_STATE)) { - /* Cancel if we are still blinking; this means that we press the - * attention again before the 5 sec. limit expires to cancel hot-add - * or hot-remove - */ - event_type = INT_BUTTON_CANCEL; - info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); - } else if ((p_slot->state == POWERON_STATE) - || (p_slot->state == POWEROFF_STATE)) { - /* Ignore if the slot is on power-on or power-off state; this - * means that the previous attention button action to hot-add or - * hot-remove is undergoing - */ - event_type = INT_BUTTON_IGNORE; - info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); - } - queue_interrupt_event(p_slot, event_type); return 0; @@ -492,6 +476,11 @@ static int remove_board(struct slot *p_slot) } +struct pushbutton_work_info { + struct slot *p_slot; + struct work_struct work; +}; + /** * shpchp_pushbutton_thread * @@ -499,22 +488,61 @@ static int remove_board(struct slot *p_slot) * Handles all pending events and exits. * */ -void shpchp_pushbutton_thread(void *data) +static void shpchp_pushbutton_thread(void *data) { - struct slot *p_slot = data; - u8 getstatus; + struct pushbutton_work_info *info = data; + struct slot *p_slot = info->p_slot; - p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (getstatus) { - p_slot->state = POWEROFF_STATE; + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case POWEROFF_STATE: + mutex_unlock(&p_slot->lock); shpchp_disable_slot(p_slot); + mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; - } else { - p_slot->state = POWERON_STATE; + break; + case POWERON_STATE: + mutex_unlock(&p_slot->lock); if (shpchp_enable_slot(p_slot)) p_slot->hpc_ops->green_led_off(p_slot); + mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; + break; + default: + break; + } + mutex_unlock(&p_slot->lock); + + kfree(info); +} + +void queue_pushbutton_work(void *data) +{ + struct slot *p_slot = data; + struct pushbutton_work_info *info; + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + err("%s: Cannot allocate memory\n", __FUNCTION__); + return; + } + info->p_slot = p_slot; + INIT_WORK(&info->work, shpchp_pushbutton_thread, info); + + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + p_slot->state = POWEROFF_STATE; + break; + case BLINKINGON_STATE: + p_slot->state = POWERON_STATE; + break; + default: + goto out; } + queue_work(shpchp_wq, &info->work); + out: + mutex_unlock(&p_slot->lock); } static int update_slot_info (struct slot *slot) @@ -536,34 +564,15 @@ static int update_slot_info (struct slot *slot) return result; } -static void interrupt_event_handler(void *data) +/* + * Note: This function must be called with slot->lock held + */ +static void handle_button_press_event(struct slot *p_slot) { - struct event_info *info = data; - struct slot *p_slot = info->p_slot; u8 getstatus; - switch (info->event_type) { - case INT_BUTTON_CANCEL: - dbg("%s: button cancel\n", __FUNCTION__); - cancel_delayed_work(&p_slot->work); - switch (p_slot->state) { - case BLINKINGOFF_STATE: - p_slot->hpc_ops->green_led_on(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - case BLINKINGON_STATE: - p_slot->hpc_ops->green_led_off(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - default: - warn("Not a valid state\n"); - return; - } - info(msg_button_cancel, p_slot->number); - p_slot->state = STATIC_STATE; - break; - case INT_BUTTON_PRESS: - dbg("%s: Button pressed\n", __FUNCTION__); + switch (p_slot->state) { + case STATIC_STATE: p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (getstatus) { p_slot->state = BLINKINGOFF_STATE; @@ -576,7 +585,51 @@ static void interrupt_event_handler(void *data) p_slot->hpc_ops->green_led_blink(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); - queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); + schedule_delayed_work(&p_slot->work, 5*HZ); + break; + case BLINKINGOFF_STATE: + case BLINKINGON_STATE: + /* + * Cancel if we are still blinking; this means that we + * press the attention again before the 5 sec. limit + * expires to cancel hot-add or hot-remove + */ + info("Button cancel on Slot(%s)\n", p_slot->name); + dbg("%s: button cancel\n", __FUNCTION__); + cancel_delayed_work(&p_slot->work); + if (p_slot->state == BLINKINGOFF_STATE) + p_slot->hpc_ops->green_led_on(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); + p_slot->state = STATIC_STATE; + break; + case POWEROFF_STATE: + case POWERON_STATE: + /* + * Ignore if the slot is on power-on or power-off state; + * this means that the previous attention button action + * to hot-add or hot-remove is undergoing + */ + info("Button ignore on Slot(%s)\n", p_slot->name); + update_slot_info(p_slot); + break; + default: + warn("Not a valid state\n"); + break; + } +} + +static void interrupt_event_handler(void *data) +{ + struct event_info *info = data; + struct slot *p_slot = info->p_slot; + + mutex_lock(&p_slot->lock); + switch (info->event_type) { + case INT_BUTTON_PRESS: + handle_button_press_event(p_slot); break; case INT_POWER_FAULT: dbg("%s: power fault\n", __FUNCTION__); @@ -587,12 +640,13 @@ static void interrupt_event_handler(void *data) update_slot_info(p_slot); break; } + mutex_unlock(&p_slot->lock); kfree(info); } -int shpchp_enable_slot (struct slot *p_slot) +static int shpchp_enable_slot (struct slot *p_slot) { u8 getstatus = 0; int rc, retval = -ENODEV; @@ -647,7 +701,7 @@ int shpchp_enable_slot (struct slot *p_slot) } -int shpchp_disable_slot (struct slot *p_slot) +static int shpchp_disable_slot (struct slot *p_slot) { u8 getstatus = 0; int rc, retval = -ENODEV; @@ -681,3 +735,66 @@ int shpchp_disable_slot (struct slot *p_slot) return retval; } +int shpchp_sysfs_enable_slot(struct slot *p_slot) +{ + int retval = -ENODEV; + + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGON_STATE: + cancel_delayed_work(&p_slot->work); + case STATIC_STATE: + p_slot->state = POWERON_STATE; + mutex_unlock(&p_slot->lock); + retval = shpchp_enable_slot(p_slot); + mutex_lock(&p_slot->lock); + p_slot->state = STATIC_STATE; + break; + case POWERON_STATE: + info("Slot %s is already in powering on state\n", + p_slot->name); + break; + case BLINKINGOFF_STATE: + case POWEROFF_STATE: + info("Already enabled on slot %s\n", p_slot->name); + break; + default: + err("Not a valid state on slot %s\n", p_slot->name); + break; + } + mutex_unlock(&p_slot->lock); + + return retval; +} + +int shpchp_sysfs_disable_slot(struct slot *p_slot) +{ + int retval = -ENODEV; + + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + cancel_delayed_work(&p_slot->work); + case STATIC_STATE: + p_slot->state = POWEROFF_STATE; + mutex_unlock(&p_slot->lock); + retval = shpchp_disable_slot(p_slot); + mutex_lock(&p_slot->lock); + p_slot->state = STATIC_STATE; + break; + case POWEROFF_STATE: + info("Slot %s is already in powering off state\n", + p_slot->name); + break; + case BLINKINGON_STATE: + case POWERON_STATE: + info("Already disabled on slot %s\n", p_slot->name); + break; + default: + err("Not a valid state on slot %s\n", p_slot->name); + break; + } + mutex_unlock(&p_slot->lock); + + return retval; +} -- cgit v1.2.3-59-g8ed1b From e6b82b13c4066ca091a4919620d6403c8a269bc3 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:50 -0800 Subject: [PATCH] shpchp: adapt to pci driver model This patch adapts SHPCHP driver to the PCI device driver model. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 4 ---- drivers/pci/hotplug/shpchp_core.c | 26 +++++++------------------- 2 files changed, 7 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index dd449512cf68..f10f1ba877af 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -82,7 +82,6 @@ struct event_info { }; struct controller { - struct list_head ctrl_list; struct mutex crit_sect; /* critical section mutex */ struct mutex cmd_lock; /* command lock */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ @@ -203,9 +202,6 @@ extern void shpchp_remove_ctrl_files(struct controller *ctrl); extern void cleanup_slots(struct controller *ctrl); extern void queue_pushbutton_work(void *data); -/* Global variables */ -extern struct list_head shpchp_ctrl_list; - struct ctrl_reg { volatile u32 base_offset; volatile u32 slot_avail1; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index fa60ae47d91d..0e83c5fbc9df 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -39,7 +39,6 @@ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; -LIST_HEAD(shpchp_ctrl_list); struct workqueue_struct *shpchp_wq; #define DRIVER_VERSION "0.4" @@ -433,8 +432,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ctrl->speed = PCI_SPEED_33MHz; } - list_add(&ctrl->ctrl_list, &shpchp_ctrl_list); - shpchp_create_ctrl_files(ctrl); return 0; @@ -447,20 +444,13 @@ err_out_none: return -ENODEV; } -static void __exit unload_shpchpd(void) +static void shpc_remove(struct pci_dev *dev) { - struct list_head *tmp; - struct list_head *next; - struct controller *ctrl; - - list_for_each_safe(tmp, next, &shpchp_ctrl_list) { - ctrl = list_entry(tmp, struct controller, ctrl_list); - shpchp_remove_ctrl_files(ctrl); - ctrl->hpc_ops->release_ctlr(ctrl); - kfree(ctrl); - } + struct controller *ctrl = pci_get_drvdata(dev); - destroy_workqueue(shpchp_wq); + shpchp_remove_ctrl_files(ctrl); + ctrl->hpc_ops->release_ctlr(ctrl); + kfree(ctrl); } static struct pci_device_id shpcd_pci_tbl[] = { @@ -473,7 +463,7 @@ static struct pci_driver shpc_driver = { .name = SHPC_MODULE_NAME, .id_table = shpcd_pci_tbl, .probe = shpc_probe, - /* remove: shpc_remove_one, */ + .remove = shpc_remove, }; static int __init shpcd_init(void) @@ -500,10 +490,8 @@ static int __init shpcd_init(void) static void __exit shpcd_cleanup(void) { dbg("unload_shpchpd()\n"); - unload_shpchpd(); - pci_unregister_driver(&shpc_driver); - + destroy_workqueue(shpchp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } -- cgit v1.2.3-59-g8ed1b From 50defa1ccaffc197a133d92acb48d696d5ea3539 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Sun, 19 Feb 2006 16:05:52 -0500 Subject: [PATCH] PCI: Add pci_device_shutdown to pci_bus_type The extra compatability code is not necessary. Any code still using the old shutdown method will trigger the warning in driver_register() instead. Signed-off-by: Brian Gerst Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 0aa14c92b570..eb5b50c8770c 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -380,14 +380,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner) /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &pci_bus_type; - /* FIXME, once all of the existing PCI drivers have been fixed to set - * the pci shutdown function, this test can go away. */ - if (!drv->driver.shutdown) - drv->driver.shutdown = pci_device_shutdown; - else - printk(KERN_WARNING "Warning: PCI driver %s has a struct " - "device_driver shutdown method, please update!\n", - drv->name); drv->driver.owner = owner; drv->driver.kobj.ktype = &pci_driver_kobj_type; @@ -514,6 +506,7 @@ struct bus_type pci_bus_type = { .probe = pci_device_probe, .remove = pci_device_remove, .suspend = pci_device_suspend, + .shutdown = pci_device_shutdown, .resume = pci_device_resume, .dev_attrs = pci_dev_attrs, }; -- cgit v1.2.3-59-g8ed1b From 3c0a654e390d00fef9d8faed758f5e1e8078adb5 Mon Sep 17 00:00:00 2001 From: "tomek@koprowski.org" Date: Sun, 19 Feb 2006 18:03:24 +0100 Subject: [PATCH] PCI: SMBus unhide on HP Compaq nx6110 I attach a trivial patch for 2.6.15.4 that unhides SMBus controller on an HP Compaq nx6110 notebook. Signed-off-by: Tomasz Koprowski Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 7ec9fc9a9a42..af4bc8e2cf83 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -934,6 +934,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x12bd: /* HP D530 */ asus_hides_smbus = 1; } + if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) { + switch (dev->subsystem_device) { + case 0x099c: /* HP Compaq nx6110 */ + asus_hides_smbus = 1; + } + } } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) { if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) switch(dev->subsystem_device) { -- cgit v1.2.3-59-g8ed1b From e5548e960f38557825e50806b52cb24c9e730aa2 Mon Sep 17 00:00:00 2001 From: Bauke Jan Douma Date: Tue, 28 Feb 2006 21:44:36 +0100 Subject: [PATCH] PCI: quirk for asus a8v and a8v delux motherboards On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller and MC97 modem controller are deactivated when a second PCI soundcard is present. This patch enables them. Signed-off-by: Bauke Jan Douma Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index af4bc8e2cf83..d71c31df7fdf 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1074,6 +1074,37 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); +/* + * On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller + * and MC97 modem controller are disabled when a second PCI soundcard is + * present. This patch, tweaking the VT8237 ISA bridge, enables them. + * -- bjd + */ +static void __init asus_hides_ac97_lpc(struct pci_dev *dev) +{ + u8 val; + int asus_hides_ac97 = 0; + + if (likely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) { + if (dev->device == PCI_DEVICE_ID_VIA_8237) + asus_hides_ac97 = 1; + } + + if (!asus_hides_ac97) + return; + + pci_read_config_byte(dev, 0x50, &val); + if (val & 0xc0) { + pci_write_config_byte(dev, 0x50, val & (~0xc0)); + pci_read_config_byte(dev, 0x50, &val); + if (val & 0xc0) + printk(KERN_INFO "PCI: onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val); + else + printk(KERN_INFO "PCI: enabled onboard AC97/MC97 devices\n"); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc ); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); -- cgit v1.2.3-59-g8ed1b From 6e325a62a0a228cd0222783802b53cce04551776 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 14 Feb 2006 18:52:22 +0200 Subject: [PATCH] PCI: make MSI quirk inheritable from the pci bus It turns out AMD 8131 quirk only affects MSI for devices behind the 8131 bridge. Handle this by adding a flags field in pci_bus, inherited from parent to child. Signed-off-by: Michael S. Tsirkin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 3 +++ drivers/pci/probe.c | 1 + drivers/pci/quirks.c | 7 +++++-- include/linux/pci.h | 7 ++++++- 4 files changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d5a67c1bcb98..4de1c17ee573 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -703,6 +703,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; + temp = dev->irq; status = msi_init(); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 3bc0fcd71d03..542e7dfb371b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -347,6 +347,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr) child->parent = parent; child->ops = parent->ops; child->sysdata = parent->sysdata; + child->bus_flags = parent->bus_flags; child->bridge = get_device(&bridge->dev); child->class_dev.class = &pcibus_class; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d71c31df7fdf..4970f47be72c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -575,8 +575,11 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) { unsigned char revid, tmp; - pci_msi_quirk = 1; - printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n"); + if (dev->subordinate) { + printk(KERN_WARNING "PCI: MSI quirk detected. " + "PCI_BUS_FLAGS_NO_MSI set for subordinate bus.\n"); + dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; + } if (nr_ioapics == 0) return; diff --git a/include/linux/pci.h b/include/linux/pci.h index 2039da1f3672..d4d533fa5d30 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -95,6 +95,11 @@ enum pci_channel_state { pci_channel_io_perm_failure = (__force pci_channel_state_t) 3, }; +typedef unsigned short __bitwise pci_bus_flags_t; +enum pci_bus_flags { + PCI_BUS_FLAGS_NO_MSI = (pci_bus_flags_t) 1, +}; + /* * The pci_dev structure is used to describe PCI devices. */ @@ -203,7 +208,7 @@ struct pci_bus { char name[48]; unsigned short bridge_ctl; /* manage NO_ISA/FBB/et al behaviors */ - unsigned short pad2; + pci_bus_flags_t bus_flags; /* Inherited by child busses */ struct device *bridge; struct class_device class_dev; struct bin_attribute *legacy_io; /* legacy I/O for this bus */ -- cgit v1.2.3-59-g8ed1b From 75cde0e25787c1af341a128b350c36df24e5397d Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 8 Feb 2006 17:11:40 +0800 Subject: [PATCH] PCI: remove msi save/restore code in specific driver Remove pcie port driver's msi save/restore code. Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pcie/portdrv.h | 1 - drivers/pci/pcie/portdrv_pci.c | 66 +++--------------------------------------- 2 files changed, 4 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index a63bd8f72601..1d317d22ee89 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -29,7 +29,6 @@ struct pcie_port_device_ext { int interrupt_mode; /* [0:INTx | 1:MSI | 2:MSI-X] */ - unsigned int saved_msi_config_space[5]; }; extern struct bus_type pcie_port_bus_type; diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 02260141dc81..50bfc1b2f3bf 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -30,75 +30,16 @@ MODULE_LICENSE("GPL"); /* global data */ static const char device_name[] = "pcieport-driver"; -static void pci_save_msi_state(struct pci_dev *dev) +static int pcie_portdrv_save_config(struct pci_dev *dev) { - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); - int i = 0, pos; - u16 control; - - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0) - return; - - pci_read_config_dword(dev, pos, &p_ext->saved_msi_config_space[i++]); - control = p_ext->saved_msi_config_space[0] >> 16; - pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, - &p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_64BIT) { - pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, - &p_ext->saved_msi_config_space[i++]); - pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, - &p_ext->saved_msi_config_space[i++]); - } else - pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, - &p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_MASKBIT) - pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, - &p_ext->saved_msi_config_space[i++]); -} - -static void pci_restore_msi_state(struct pci_dev *dev) -{ - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); - int i = 0, pos; - u16 control; - - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0) - return; - - control = p_ext->saved_msi_config_space[i++] >> 16; - pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); - pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, - p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_64BIT) { - pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, - p_ext->saved_msi_config_space[i++]); - pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, - p_ext->saved_msi_config_space[i++]); - } else - pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, - p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_MASKBIT) - pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, - p_ext->saved_msi_config_space[i++]); -} - -static void pcie_portdrv_save_config(struct pci_dev *dev) -{ - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); - - pci_save_state(dev); - if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE) - pci_save_msi_state(dev); + return pci_save_state(dev); } static int pcie_portdrv_restore_config(struct pci_dev *dev) { - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); int retval; pci_restore_state(dev); - if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE) - pci_restore_msi_state(dev); retval = pci_enable_device(dev); if (retval) return retval; @@ -149,7 +90,8 @@ static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state) { int ret = pcie_port_device_suspend(dev, state); - pcie_portdrv_save_config(dev); + if (!ret) + ret = pcie_portdrv_save_config(dev); return ret; } -- cgit v1.2.3-59-g8ed1b From a0454b40ee8fac03194bb71f01730266506e75e1 Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Thu, 16 Feb 2006 23:58:29 -0800 Subject: [PATCH] PCI: fix problems with MSI-X on ia64 Use "unsigned long" when dealing with PCI resources. The BAR Indicator Register (BIR) can be a 64-bit value or the resource could be a 64-bit host physical address. Enables ib_mthca and cciss drivers to use MSI-X on ia64 HW. Problem showed up now because of new system firmware on one platform. Symptom will either be memory corruption or MCA. Second part of this patch deals with "useless" code. We walk through the steps to find the phys_addr and then don't use the result. I suspect the intent was to zero out the respective MSI-X entry but I'm not sure at the moment. Delete the code inside the #if 0/#endif if it's really not needed. Signed-off-by: Grant Grundler Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 4de1c17ee573..aea8b258b9b8 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -600,7 +600,8 @@ static int msix_capability_init(struct pci_dev *dev, struct msg_address address; struct msg_data data; int vector, pos, i, j, nr_entries, temp = 0; - u32 phys_addr, table_offset; + unsigned long phys_addr; + u32 table_offset; u16 control; u8 bir; void __iomem *base; @@ -609,11 +610,11 @@ static int msix_capability_init(struct pci_dev *dev, /* Request & Map MSI-X table region */ 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); + + pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - phys_addr = pci_resource_start (dev, bir); - phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK); + table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; + phys_addr = pci_resource_start (dev, bir) + table_offset; base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); if (base == NULL) return -ENOMEM; @@ -838,8 +839,10 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) * Detect last MSI-X vector to be released. * Release the MSI-X memory-mapped table. */ +#if 0 int pos, nr_entries; - u32 phys_addr, table_offset; + unsigned long phys_addr; + u32 table_offset; u16 control; u8 bir; @@ -850,9 +853,12 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - phys_addr = pci_resource_start (dev, bir); - phys_addr += (u32)(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); } } @@ -1119,7 +1125,9 @@ 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 */ - u32 phys_addr, table_offset; +#if 0 + unsigned long phys_addr; + u32 table_offset; u16 control; u8 bir; @@ -1128,9 +1136,12 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - phys_addr = pci_resource_start (dev, bir); - phys_addr += (u32)(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-59-g8ed1b From 8c4b2cf9af9b4ecc29d4f0ec4ecc8e94dc4432d7 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sat, 18 Feb 2006 01:36:55 -0800 Subject: [PATCH] PCI: PCI/Cardbus cards hidden, needs pci=assign-busses to fix "In some cases, especially on modern laptops with a lot of PCI and cardbus bridges, we're unable to assign correct secondary/subordinate bus numbers to all cardbus bridges due to BIOS limitations unless we are using "pci=assign-busses" boot option." -- Ivan Kokshaysky (from a patch comment) Without it, Cardbus cards inserted are never seen by PCI because the parent PCI-PCI Bridge of the Cardbus bridge will not pass and translate Type 1 PCI configuration cycles correctly and the system will fail to find and initialise the PCI devices in the system. Reference: PCI-PCI Bridges: PCI Configuration Cycles and PCI Bus Numbering: http://www.science.unitn.it/~fiorella/guidelinux/tlk/node72.html The reason for this is that: ``All PCI busses located behind a PCI-PCI bridge must reside between the secondary bus number and the subordinate bus number (inclusive).'' "pci=assign-busses" makes pcibios_assign_all_busses return 1 and this turns on PCI renumbering during PCI probing. Alan suggested to use DMI automatically set assign-busses on problem systems. The only question for me was where to put it. I put it directly before scanning PCI bus into pcibios_scan_root() because it's called from legacy, acpi and numa and so it can be one place for all systems and configurations which may need it. AMD64 Laptops are also affected and fixed by assign-busses, and the code is also incuded from arch/x86_64/pci/ that place will also work for x86_64 kernels, I only ifdef'-ed the x86-only Laptop in this example. Affected and known or assumed to be fixed with it are (found by googling): * ASUS Z71V and L3s * Samsung X20 * Compaq R3140us and all Compaq R3000 series laptops with TI1620 Controller, also Compaq R4000 series (from a kernel.org bugreport) * HP zv5000z (AMD64 3700+, known that fixup_parent_subordinate_busnr fixes it) * HP zv5200z * IBM ThinkPad 240 * An IBM ThinkPad (1.8 GHz Pentium M) debugged by Pavel Machek gives the correspondig message which detects the possible problem. * MSI S260 / Medion SIM 2100 MD 95600 The patch also expands the "try pci=assign-busses" warning so testers will help us to update the DMI table. Cc: Ivan Kokshaysky Cc: Alan Cox Cc: Dominik Brodowski Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- arch/i386/pci/common.c | 32 ++++++++++++++++++++++++++++++++ drivers/pci/probe.c | 4 +++- 2 files changed, 35 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index f6bc48da4d2a..dbece776c5b2 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -120,11 +121,42 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b) pci_read_bridge_bases(b); } +/* + * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) + */ +#ifdef __i386__ +static int __devinit assign_all_busses(struct dmi_system_id *d) +{ + pci_probe |= PCI_ASSIGN_ALL_BUSSES; + printk(KERN_INFO "%s detected: enabling PCI bus# renumbering" + " (pci=assign-busses)\n", d->ident); + return 0; +} +#endif + +/* + * Laptops which need pci=assign-busses to see Cardbus cards + */ +static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { +#ifdef __i386__ + { + .callback = assign_all_busses, + .ident = "Samsung X20 Laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"), + DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"), + }, + }, +#endif /* __i386__ */ + {} +}; struct pci_bus * __devinit pcibios_scan_root(int busnum) { struct pci_bus *bus = NULL; + dmi_check_system(pciprobe_dmi_table); + while ((bus = pci_find_next_bus(bus)) != NULL) { if (bus->number == busnum) { /* Already scanned */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 542e7dfb371b..e3dc3063e05b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -589,13 +589,15 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max (child->number > bus->subordinate) || (child->number < bus->number) || (child->subordinate < bus->number)) { - printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) may be " + printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) is " "hidden behind%s bridge #%02x (-#%02x)%s\n", child->number, child->subordinate, bus->self->transparent ? " transparent" : " ", bus->number, bus->subordinate, pcibios_assign_all_busses() ? " " : " (try 'pci=assign-busses')"); + printk(KERN_WARNING "Please report the result to " + "linux-kernel to fix this permanently\n"); } bus = bus->parent; } -- cgit v1.2.3-59-g8ed1b From b89b7ea05a8f71426bd36ed12e6cd73179d0f720 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2006 17:12:51 -0500 Subject: [PATCH] PCI: Move pci_dev_put outside a spinlock This patch (as659) fixes a might_sleep problem in the PCI core, by moving a call to pci_dev_put() outside the scope of a spinlock. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/pci/search.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 05fa91a31c62..ce7dd6e7be60 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -246,9 +246,9 @@ pci_get_subsys(unsigned int vendor, unsigned int device, } dev = NULL; exit: - pci_dev_put(from); dev = pci_dev_get(dev); spin_unlock(&pci_bus_lock); + pci_dev_put(from); return dev; } @@ -339,9 +339,9 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) } dev = NULL; exit: - pci_dev_put(from); dev = pci_dev_get(dev); spin_unlock(&pci_bus_lock); + pci_dev_put(from); return dev; } -- cgit v1.2.3-59-g8ed1b From 15a1ae74879925d0d3f71ebc3f56d0a2c5db393a Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Thu, 23 Feb 2006 17:55:58 -0800 Subject: [PATCH] acpiphp: add new bus to acpi If we add a new bridge with subordinate busses, we should call make sure that acpi is notified so that the PRT (if present) can be read and drivers who have registered on this bus will be notified when it is started. Also make sure to use the max reserved bus number for the starting the bus scan. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 111 ++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 4e25d9c7cc39..fe0a6b7662f7 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -751,6 +751,106 @@ static int power_off_slot(struct acpiphp_slot *slot) } + +/** + * acpiphp_max_busnr - return the highest reserved bus number under + * the given bus. + * @bus: bus to start search with + * + */ +static unsigned char acpiphp_max_busnr(struct pci_bus *bus) +{ + struct list_head *tmp; + unsigned char max, n; + + /* + * pci_bus_max_busnr will return the highest + * reserved busnr for all these children. + * that is equivalent to the bus->subordinate + * value. We don't want to use the parent's + * bus->subordinate value because it could have + * padding in it. + */ + max = bus->secondary; + + list_for_each(tmp, &bus->children) { + n = pci_bus_max_busnr(pci_bus_b(tmp)); + if (n > max) + max = n; + } + return max; +} + + + +/** + * 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 + * + */ +static int acpiphp_bus_add(struct acpiphp_func *func) +{ + acpi_handle phandle; + struct acpi_device *device, *pdevice; + int ret_val; + + acpi_get_parent(func->handle, &phandle); + if (acpi_bus_get_device(phandle, &pdevice)) { + dbg("no parent device, assuming NULL\n"); + pdevice = NULL; + } + if (acpi_bus_get_device(func->handle, &device)) { + ret_val = acpi_bus_add(&device, pdevice, func->handle, + ACPI_BUS_TYPE_DEVICE); + if (ret_val) { + dbg("error adding bus, %x\n", + -ret_val); + goto acpiphp_bus_add_out; + } + } + /* + * try to start anyway. We could have failed to add + * simply because this bus had previously been added + * on another add. Don't bother with the return value + * we just keep going. + */ + ret_val = acpi_bus_start(device); + +acpiphp_bus_add_out: + return ret_val; +} + + + /** * enable_device - enable, configure a slot * @slot: slot to be enabled @@ -788,7 +888,7 @@ static int enable_device(struct acpiphp_slot *slot) goto err_exit; } - max = bus->secondary; + max = acpiphp_max_busnr(bus); for (pass = 0; pass < 2; pass++) { list_for_each_entry(dev, &bus->devices, bus_list) { if (PCI_SLOT(dev->devfn) != slot->device) @@ -796,8 +896,15 @@ 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); + } + } } } } -- cgit v1.2.3-59-g8ed1b From ceaba663055e38226a070a9668eac5881d65a2cc Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Thu, 23 Feb 2006 17:56:01 -0800 Subject: [PATCH] acpi: export acpi_bus_trim Export the acpi_bus_trim function so that the pci hotplug driver can use it. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/scan.c | 5 +++-- include/acpi/acpi_bus.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 9271e5209ac1..a0ab828b2cc5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -23,7 +23,6 @@ static LIST_HEAD(acpi_device_list); DEFINE_SPINLOCK(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); -static int acpi_bus_trim(struct acpi_device *start, int rmdevice); static void acpi_device_release(struct kobject *kobj) { @@ -1284,7 +1283,7 @@ int acpi_bus_start(struct acpi_device *device) EXPORT_SYMBOL(acpi_bus_start); -static int acpi_bus_trim(struct acpi_device *start, int rmdevice) +int acpi_bus_trim(struct acpi_device *start, int rmdevice) { acpi_status status; struct acpi_device *parent, *child; @@ -1337,6 +1336,8 @@ static int acpi_bus_trim(struct acpi_device *start, int rmdevice) } return err; } +EXPORT_SYMBOL_GPL(acpi_bus_trim); + static int acpi_bus_scan_fixed(struct acpi_device *root) { diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 0b54e9a4a8a1..e496fac860ac 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -330,6 +330,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver); int 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); int acpi_bus_start(struct acpi_device *device); int acpi_match_ids(struct acpi_device *device, char *ids); -- cgit v1.2.3-59-g8ed1b From 20416ea54087c25502d6fb973b8e119973e16341 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Thu, 23 Feb 2006 17:56:03 -0800 Subject: [PATCH] acpiphp: add dock event handling These patches add generic dock event handling to acpiphp. If there are pci devices that need to be inserted/removed after the dock event, the event notification will be handed down to the normal pci hotplug event handler in acpiphp so that new bridges/devices can be enumerated. Because some dock stations do not have pci bridges or pci devices that need to be inserted after a dock, acpiphp will remain loaded to handle dock events even if no hotpluggable pci slots are discovered. You probably need to have the pci=assign-busses kernel parameter enabled to use these patches, and you may not allow ibm_acpi to handle docking notifications and use this patch. This patch incorporates feedback provided by many. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/Makefile | 3 +- drivers/pci/hotplug/acpiphp.h | 36 +++ drivers/pci/hotplug/acpiphp_core.c | 7 +- drivers/pci/hotplug/acpiphp_dock.c | 438 +++++++++++++++++++++++++++++++++++++ drivers/pci/hotplug/acpiphp_glue.c | 85 +++++-- 5 files changed, 545 insertions(+), 24 deletions(-) create mode 100644 drivers/pci/hotplug/acpiphp_dock.c (limited to 'drivers') diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 3c71e3077ff1..1c0ed377ed91 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -37,7 +37,8 @@ ibmphp-objs := ibmphp_core.o \ ibmphp_hpc.o acpiphp-objs := acpiphp_core.o \ - acpiphp_glue.o + acpiphp_glue.o \ + acpiphp_dock.o rpaphp-objs := rpaphp_core.o \ rpaphp_pci.o \ diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 6a91cfb0f688..885838a2e93f 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -161,6 +161,25 @@ struct acpiphp_attention_info struct module *owner; }; + +struct dependent_device { + struct list_head device_list; + struct list_head pci_list; + acpi_handle handle; + struct acpiphp_func *func; +}; + + +struct acpiphp_dock_station { + acpi_handle handle; + u32 last_dock_time; + u32 flags; + struct acpiphp_func *dock_bridge; + struct list_head dependent_devices; + struct list_head pci_dependent_devices; +}; + + /* PCI bus bridge HID */ #define ACPI_PCI_HOST_HID "PNP0A03" @@ -198,6 +217,12 @@ struct acpiphp_attention_info #define FUNC_HAS_PS1 (0x00000020) #define FUNC_HAS_PS2 (0x00000040) #define FUNC_HAS_PS3 (0x00000080) +#define FUNC_HAS_DCK (0x00000100) +#define FUNC_IS_DD (0x00000200) + +/* dock station flags */ +#define DOCK_DOCKING (0x00000001) +#define DOCK_HAS_BRIDGE (0x00000002) /* function prototypes */ @@ -211,6 +236,7 @@ extern void acpiphp_glue_exit (void); extern int acpiphp_get_num_slots (void); extern struct acpiphp_slot *get_slot_from_id (int id); typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); +void handle_hotplug_event_func(acpi_handle, u32, void*); extern int acpiphp_enable_slot (struct acpiphp_slot *slot); extern int acpiphp_disable_slot (struct acpiphp_slot *slot); @@ -220,6 +246,16 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); extern u32 acpiphp_get_address (struct acpiphp_slot *slot); +/* acpiphp_dock.c */ +extern int find_dock_station(void); +extern void remove_dock_station(void); +extern void add_dependent_device(struct dependent_device *new_dd); +extern void add_pci_dependent_device(struct dependent_device *new_dd); +extern struct dependent_device *get_dependent_device(acpi_handle handle); +extern int is_dependent_device(acpi_handle handle); +extern int detect_dependent_devices(acpi_handle *bridge_handle); +extern struct dependent_device *alloc_dependent_device(acpi_handle handle); + /* variables */ extern int acpiphp_debug; diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 60c4c38047a3..bce71c933478 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -429,14 +429,17 @@ static void __exit cleanup_slots (void) static int __init acpiphp_init(void) { int retval; + int docking_station; info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); acpiphp_debug = debug; + docking_station = find_dock_station(); + /* read all the ACPI info from the system */ retval = init_acpi(); - if (retval) + if (retval && !(docking_station)) return retval; return init_slots(); @@ -448,6 +451,8 @@ static void __exit acpiphp_exit(void) cleanup_slots(); /* deallocate internal data structures etc. */ acpiphp_glue_exit(); + + remove_dock_station(); } module_init(acpiphp_init); diff --git a/drivers/pci/hotplug/acpiphp_dock.c b/drivers/pci/hotplug/acpiphp_dock.c new file mode 100644 index 000000000000..4f1aaf128312 --- /dev/null +++ b/drivers/pci/hotplug/acpiphp_dock.c @@ -0,0 +1,438 @@ +/* + * ACPI PCI HotPlug dock functions to ACPI CA subsystem + * + * Copyright (C) 2006 Kristen Carlson Accardi (kristen.c.accardi@intel.com) + * Copyright (C) 2006 Intel Corporation + * + * 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; 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Send feedback to + * + */ +#include +#include + +#include +#include +#include +#include + +#include "../pci.h" +#include "pci_hotplug.h" +#include "acpiphp.h" + +static struct acpiphp_dock_station *ds; +#define MY_NAME "acpiphp_dock" + + +int is_dependent_device(acpi_handle handle) +{ + return (get_dependent_device(handle) ? 1 : 0); +} + + +static acpi_status +find_dependent_device(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + int *count = (int *)context; + + if (is_dependent_device(handle)) { + (*count)++; + return AE_CTRL_TERMINATE; + } else { + return AE_OK; + } +} + + + + +void add_dependent_device(struct dependent_device *new_dd) +{ + list_add_tail(&new_dd->device_list, &ds->dependent_devices); +} + + +void add_pci_dependent_device(struct dependent_device *new_dd) +{ + list_add_tail(&new_dd->pci_list, &ds->pci_dependent_devices); +} + + + +struct dependent_device * get_dependent_device(acpi_handle handle) +{ + struct dependent_device *dd; + + if (!ds) + return NULL; + + list_for_each_entry(dd, &ds->dependent_devices, device_list) { + if (handle == dd->handle) + return dd; + } + return NULL; +} + + + +struct dependent_device *alloc_dependent_device(acpi_handle handle) +{ + struct dependent_device *dd; + + dd = kzalloc(sizeof(*dd), GFP_KERNEL); + if (dd) { + INIT_LIST_HEAD(&dd->pci_list); + INIT_LIST_HEAD(&dd->device_list); + dd->handle = handle; + } + return dd; +} + + + +static int is_dock(acpi_handle handle) +{ + acpi_status status; + acpi_handle tmp; + + status = acpi_get_handle(handle, "_DCK", &tmp); + if (ACPI_FAILURE(status)) { + return 0; + } + return 1; +} + + + +static int dock_present(void) +{ + unsigned long sta; + acpi_status status; + + if (ds) { + status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta); + if (ACPI_SUCCESS(status) && sta) + return 1; + } + return 0; +} + + + +static void eject_dock(void) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 1; + + if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0", + &arg_list, NULL)) || dock_present()) + warn("%s: failed to eject dock!\n", __FUNCTION__); + + return; +} + + + + +static acpi_status handle_dock(int dock) +{ + acpi_status status; + struct acpi_object_list arg_list; + union acpi_object arg; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + + dbg("%s: %s\n", __FUNCTION__, dock ? "docking" : "undocking"); + + /* _DCK method has one argument */ + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = dock; + status = acpi_evaluate_object(ds->handle, "_DCK", + &arg_list, &buffer); + if (ACPI_FAILURE(status)) + err("%s: failed to execute _DCK\n", __FUNCTION__); + acpi_os_free(buffer.pointer); + + return status; +} + + + +static inline void dock(void) +{ + handle_dock(1); +} + + + +static inline void undock(void) +{ + handle_dock(0); +} + + + +/* + * the _DCK method can do funny things... and sometimes not + * hah-hah funny. + * + * TBD - figure out a way to only call fixups for + * systems that require them. + */ +static void post_dock_fixups(void) +{ + struct pci_bus *bus; + u32 buses; + struct dependent_device *dd; + + list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list) { + bus = dd->func->slot->bridge->pci_bus; + + /* fixup bad _DCK function that rewrites + * secondary bridge on slot + */ + pci_read_config_dword(bus->self, + PCI_PRIMARY_BUS, + &buses); + + if (((buses >> 8) & 0xff) != bus->secondary) { + buses = (buses & 0xff000000) + | ((unsigned int)(bus->primary) << 0) + | ((unsigned int)(bus->secondary) << 8) + | ((unsigned int)(bus->subordinate) << 16); + pci_write_config_dword(bus->self, + PCI_PRIMARY_BUS, + buses); + } + } +} + + + +static void hotplug_pci(u32 type) +{ + struct dependent_device *dd; + + list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list) + handle_hotplug_event_func(dd->handle, type, dd->func); +} + + + +static inline void begin_dock(void) +{ + ds->flags |= DOCK_DOCKING; +} + + +static inline void complete_dock(void) +{ + ds->flags &= ~(DOCK_DOCKING); + ds->last_dock_time = jiffies; +} + + +static int dock_in_progress(void) +{ + if (ds->flags & DOCK_DOCKING || + ds->last_dock_time == jiffies) { + dbg("dock in progress\n"); + return 1; + } + return 0; +} + + + +static void +handle_hotplug_event_dock(acpi_handle handle, u32 type, void *context) +{ + dbg("%s: enter\n", __FUNCTION__); + + switch (type) { + case ACPI_NOTIFY_BUS_CHECK: + dbg("BUS Check\n"); + if (!dock_in_progress() && dock_present()) { + begin_dock(); + dock(); + if (!dock_present()) { + err("Unable to dock!\n"); + break; + } + post_dock_fixups(); + hotplug_pci(type); + complete_dock(); + } + break; + case ACPI_NOTIFY_EJECT_REQUEST: + dbg("EJECT request\n"); + if (!dock_in_progress() && dock_present()) { + hotplug_pci(type); + undock(); + eject_dock(); + if (dock_present()) + err("Unable to undock!\n"); + } + break; + } +} + + + + +static acpi_status +find_dock_ejd(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + acpi_status status; + acpi_handle tmp; + acpi_handle dck_handle = (acpi_handle) context; + char objname[64]; + struct acpi_buffer buffer = { .length = sizeof(objname), + .pointer = objname }; + struct acpi_buffer ejd_buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *ejd_obj; + + status = acpi_get_handle(handle, "_EJD", &tmp); + if (ACPI_FAILURE(status)) + return AE_OK; + + /* make sure we are dependent on the dock device, + * by executing the _EJD method, then getting a handle + * to the device referenced by that name. If that + * device handle is the same handle as the dock station + * handle, then we are a device dependent on the dock station + */ + acpi_get_name(dck_handle, ACPI_FULL_PATHNAME, &buffer); + status = acpi_evaluate_object(handle, "_EJD", NULL, &ejd_buffer); + if (ACPI_FAILURE(status)) { + err("Unable to execute _EJD!\n"); + goto find_ejd_out; + } + ejd_obj = ejd_buffer.pointer; + status = acpi_get_handle(NULL, ejd_obj->string.pointer, &tmp); + if (ACPI_FAILURE(status)) + goto find_ejd_out; + + if (tmp == dck_handle) { + struct dependent_device *dd; + dbg("%s: found device dependent on dock\n", __FUNCTION__); + dd = alloc_dependent_device(handle); + if (!dd) { + err("Can't allocate memory for dependent device!\n"); + goto find_ejd_out; + } + add_dependent_device(dd); + } + +find_ejd_out: + acpi_os_free(ejd_buffer.pointer); + return AE_OK; +} + + + +int detect_dependent_devices(acpi_handle *bridge_handle) +{ + acpi_status status; + int count; + + count = 0; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, + (u32)1, find_dependent_device, + (void *)&count, NULL); + + return count; +} + + + + + +static acpi_status +find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + int *count = (int *)context; + + if (is_dock(handle)) { + dbg("%s: found dock\n", __FUNCTION__); + ds = kzalloc(sizeof(*ds), GFP_KERNEL); + ds->handle = handle; + INIT_LIST_HEAD(&ds->dependent_devices); + INIT_LIST_HEAD(&ds->pci_dependent_devices); + + /* look for devices dependent on dock station */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_dock_ejd, handle, NULL); + + acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_dock, ds); + (*count)++; + } + + return AE_OK; +} + + + + +int find_dock_station(void) +{ + int num = 0; + + ds = NULL; + + /* start from the root object, because some laptops define + * _DCK methods outside the scope of PCI (IBM x-series laptop) + */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_dock, &num, NULL); + + return num; +} + + + +void remove_dock_station(void) +{ + struct dependent_device *dd, *tmp; + if (ds) { + if (ACPI_FAILURE(acpi_remove_notify_handler(ds->handle, + ACPI_SYSTEM_NOTIFY, handle_hotplug_event_dock))) + err("failed to remove dock notify handler\n"); + + /* free all dependent devices */ + list_for_each_entry_safe(dd, tmp, &ds->dependent_devices, + device_list) + kfree(dd); + + /* no need to touch the pci_dependent_device list, + * cause all memory was freed above + */ + kfree(ds); + } +} + + diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index fe0a6b7662f7..22d0f1cf1362 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -57,7 +57,6 @@ static LIST_HEAD(bridge_list); #define MY_NAME "acpiphp_glue" static void handle_hotplug_event_bridge (acpi_handle, u32, void *); -static void handle_hotplug_event_func (acpi_handle, u32, void *); static void acpiphp_sanitize_bus(struct pci_bus *bus); static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); @@ -125,6 +124,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; struct acpiphp_slot *slot; struct acpiphp_func *newfunc; + struct dependent_device *dd; acpi_handle tmp; acpi_status status = AE_OK; unsigned long adr, sun; @@ -138,7 +138,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status) && !(is_dependent_device(handle))) return AE_OK; device = (adr >> 16) & 0xffff; @@ -152,7 +152,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) INIT_LIST_HEAD(&newfunc->sibling); newfunc->handle = handle; newfunc->function = function; - newfunc->flags = FUNC_HAS_EJ0; + if (ACPI_SUCCESS(status)) + newfunc->flags = FUNC_HAS_EJ0; if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) newfunc->flags |= FUNC_HAS_STA; @@ -163,6 +164,19 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) newfunc->flags |= FUNC_HAS_PS3; + if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp))) { + newfunc->flags |= FUNC_HAS_DCK; + /* add to devices dependent on dock station, + * because this may actually be the dock bridge + */ + dd = alloc_dependent_device(handle); + if (!dd) + err("Can't allocate memory for " + "new dependent device!\n"); + else + add_dependent_device(dd); + } + status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); if (ACPI_FAILURE(status)) sun = -1; @@ -210,18 +224,35 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); } + /* if this is a device dependent on a dock station, + * associate the acpiphp_func to the dependent_device + * struct. + */ + if ((dd = get_dependent_device(handle))) { + newfunc->flags |= FUNC_IS_DD; + /* + * we don't want any devices which is dependent + * on the dock to have it's _EJ0 method executed. + * because we need to run _DCK first. + */ + newfunc->flags &= ~FUNC_HAS_EJ0; + dd->func = newfunc; + add_pci_dependent_device(dd); + } + /* install notify handler */ - status = acpi_install_notify_handler(handle, + if (!(newfunc->flags & FUNC_HAS_DCK)) { + status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_func, newfunc); - if (ACPI_FAILURE(status)) { - err("failed to register interrupt notify handler\n"); - return status; - } + if (ACPI_FAILURE(status)) + err("failed to register interrupt notify handler\n"); + } else + status = AE_OK; - return AE_OK; + return status; } @@ -410,7 +441,8 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) goto out; /* check if this bridge has ejectable slots */ - if (detect_ejectable_slots(handle) > 0) { + if ((detect_ejectable_slots(handle) > 0) || + (detect_dependent_devices(handle) > 0)) { dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); add_p2p_bridge(handle, dev); } @@ -512,11 +544,13 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) list_for_each_safe (list, tmp, &slot->funcs) { struct acpiphp_func *func; func = list_entry(list, struct acpiphp_func, sibling); - status = acpi_remove_notify_handler(func->handle, + if (!(func->flags & FUNC_HAS_DCK)) { + status = acpi_remove_notify_handler(func->handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_func); - if (ACPI_FAILURE(status)) - err("failed to remove notify handler\n"); + if (ACPI_FAILURE(status)) + err("failed to remove notify handler\n"); + } pci_dev_put(func->pci_dev); list_del(list); kfree(func); @@ -828,14 +862,21 @@ static int acpiphp_bus_add(struct acpiphp_func *func) dbg("no parent device, assuming NULL\n"); pdevice = NULL; } - if (acpi_bus_get_device(func->handle, &device)) { - ret_val = acpi_bus_add(&device, pdevice, func->handle, - ACPI_BUS_TYPE_DEVICE); - if (ret_val) { - dbg("error adding bus, %x\n", - -ret_val); - goto acpiphp_bus_add_out; - } + if (!acpi_bus_get_device(func->handle, &device)) { + dbg("bus exists... trim\n"); + /* this shouldn't be in here, so remove + * the bus then re-add it... + */ + ret_val = acpi_bus_trim(device, 1); + dbg("acpi_bus_trim return %x\n", ret_val); + } + + ret_val = acpi_bus_add(&device, pdevice, func->handle, + ACPI_BUS_TYPE_DEVICE); + if (ret_val) { + dbg("error adding bus, %x\n", + -ret_val); + goto acpiphp_bus_add_out; } /* * try to start anyway. We could have failed to add @@ -1307,7 +1348,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont * handles ACPI event notification on slots * */ -static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) +void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) { struct acpiphp_func *func; char objname[64]; -- cgit v1.2.3-59-g8ed1b From 63e5f248c4b748690b5180aa1b4b10eac51bb0e1 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Thu, 23 Feb 2006 17:56:06 -0800 Subject: [PATCH] acpi: remove dock event handling from ibm_acpi Remove dock station support from ibm_acpi by default. This support has been put into acpiphp instead. Allow ibm_acpi to continue to provide docking station support via config option for laptops/docking stations that are not supported by acpiphp. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/Kconfig | 12 ++++++++++++ drivers/acpi/ibm_acpi.c | 13 ++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 33e2ca847a26..82710ae39228 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -205,6 +205,18 @@ config ACPI_IBM If you have an IBM ThinkPad laptop, say Y or M here. +config ACPI_IBM_DOCK + bool "Legacy Docking Station Support" + depends on ACPI_IBM + default n + ---help--- + Allows the ibm_acpi driver to handle docking station events. + This support is obsoleted by CONFIG_HOTPLUG_PCI_ACPI. It will + allow locking and removing the laptop from the docking station, + but will not properly connect PCI devices. + + If you are not sure, say N here. + config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" depends on X86 diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 5cc090326ddc..262b1f41335a 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -160,13 +160,13 @@ IBM_HANDLE(cmos, root, "\\UCMS", /* R50, R50e, R50p, R51, T4x, X31, X40 */ "\\CMOS", /* A3x, G4x, R32, T23, T30, X22-24, X30 */ "\\CMS", /* R40, R40e */ ); /* all others */ - +#ifdef CONFIG_ACPI_IBM_DOCK IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */ "\\_SB.PCI0.PCI1.DOCK", /* all others */ "\\_SB.PCI.ISA.SLCE", /* 570 */ ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */ - +#endif IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */ "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */ "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */ @@ -844,7 +844,7 @@ static int _sta(acpi_handle handle) return status; } - +#ifdef CONFIG_ACPI_IBM_DOCK #define dock_docked() (_sta(dock_handle) & 1) static int dock_read(char *p) @@ -907,6 +907,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event) acpi_bus_generate_event(ibm->device, event, 0); /* unknown */ } } +#endif static int bay_status_supported; static int bay_status2_supported; @@ -1574,6 +1575,7 @@ static struct ibm_struct ibms[] = { .read = light_read, .write = light_write, }, +#ifdef CONFIG_ACPI_IBM_DOCK { .name = "dock", .read = dock_read, @@ -1589,6 +1591,7 @@ static struct ibm_struct ibms[] = { .handle = &pci_handle, .type = ACPI_SYSTEM_NOTIFY, }, +#endif { .name = "bay", .init = bay_init, @@ -1880,7 +1883,9 @@ IBM_PARAM(hotkey); IBM_PARAM(bluetooth); IBM_PARAM(video); IBM_PARAM(light); +#ifdef CONFIG_ACPI_IBM_DOCK IBM_PARAM(dock); +#endif IBM_PARAM(bay); IBM_PARAM(cmos); IBM_PARAM(led); @@ -1927,7 +1932,9 @@ static int __init acpi_ibm_init(void) IBM_HANDLE_INIT(hkey); IBM_HANDLE_INIT(lght); IBM_HANDLE_INIT(cmos); +#ifdef CONFIG_ACPI_IBM_DOCK IBM_HANDLE_INIT(dock); +#endif IBM_HANDLE_INIT(pci); IBM_HANDLE_INIT(bay); if (bay_handle) -- cgit v1.2.3-59-g8ed1b From e27da3814170385a4d2797397d706e554635812d Mon Sep 17 00:00:00 2001 From: MUNEDA Takahiro Date: Thu, 23 Feb 2006 17:56:08 -0800 Subject: [PATCH] acpiphp - slot management fix - V4 o This patch removes IDs (for slots management). o This patch removes the slot register/unregister processes from the init/exit phases. Instead, adds these processes in the bridge add/cleanup phases. o Currently, this change doesn't have any meanings. But these changes are needed to support p2p bridge(with hotplug slot) Signed-off-by: MUNEDA Takahiro Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp.h | 8 +-- drivers/pci/hotplug/acpiphp_core.c | 129 ++++++++++++++++++------------------- drivers/pci/hotplug/acpiphp_glue.c | 48 +++++++------- 3 files changed, 87 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 885838a2e93f..de9df80ffb50 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -60,10 +60,7 @@ struct acpiphp_slot; * struct slot - slot information for each *physical* slot */ struct slot { - u8 number; struct hotplug_slot *hotplug_slot; - struct list_head slot_list; - struct acpiphp_slot *acpi_slot; }; @@ -119,9 +116,9 @@ struct acpiphp_slot { struct acpiphp_bridge *bridge; /* parent */ struct list_head funcs; /* one slot may have different objects (i.e. for each function) */ + struct slot *slot; struct mutex crit_sect; - u32 id; /* slot id (serial #) for hotplug core */ u8 device; /* pci device# */ u32 sun; /* ACPI _SUN (slot unique number) */ @@ -229,12 +226,13 @@ struct acpiphp_dock_station { /* acpiphp_core.c */ extern int acpiphp_register_attention(struct acpiphp_attention_info*info); extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info); +extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); +extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); /* acpiphp_glue.c */ extern int acpiphp_glue_init (void); extern void acpiphp_glue_exit (void); extern int acpiphp_get_num_slots (void); -extern struct acpiphp_slot *get_slot_from_id (int id); typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); void handle_hotplug_event_func(acpi_handle, u32, void*); diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index bce71c933478..4f1b0da8e47e 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -44,8 +44,6 @@ #include "pci_hotplug.h" #include "acpiphp.h" -static LIST_HEAD(slot_list); - #define MY_NAME "acpiphp" static int debug; @@ -341,62 +339,53 @@ static void release_slot(struct hotplug_slot *hotplug_slot) kfree(slot); } -/** - * init_slots - initialize 'struct slot' structures for each slot - * - */ -static int __init init_slots(void) +/* callback routine to initialize 'struct slot' for each slot */ +int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) { struct slot *slot; + struct hotplug_slot *hotplug_slot; + struct hotplug_slot_info *hotplug_slot_info; int retval = -ENOMEM; - int i; - - for (i = 0; i < num_slots; ++i) { - slot = kmalloc(sizeof(struct slot), GFP_KERNEL); - if (!slot) - goto error; - memset(slot, 0, sizeof(struct slot)); - - slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); - if (!slot->hotplug_slot) - goto error_slot; - memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); - - slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); - if (!slot->hotplug_slot->info) - goto error_hpslot; - memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info)); - - slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!slot->hotplug_slot->name) - goto error_info; - - slot->number = i; - - slot->hotplug_slot->private = slot; - slot->hotplug_slot->release = &release_slot; - slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; - - slot->acpi_slot = get_slot_from_id(i); - slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); - slot->hotplug_slot->info->attention_status = 0; - slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); - slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); - slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; - slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; - - make_slot_name(slot); - - retval = pci_hp_register(slot->hotplug_slot); - if (retval) { - err("pci_hp_register failed with error %d\n", retval); - goto error_name; - } - - /* add slot to our internal list */ - list_add(&slot->slot_list, &slot_list); - info("Slot [%s] registered\n", slot->hotplug_slot->name); - } + + slot = kzalloc(sizeof(*slot), GFP_KERNEL); + if (!slot) + goto error; + + slot->hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); + if (!slot->hotplug_slot) + goto error_slot; + + slot->hotplug_slot->info = kzalloc(sizeof(*hotplug_slot_info), + GFP_KERNEL); + if (!slot->hotplug_slot->info) + goto error_hpslot; + + slot->hotplug_slot->name = kzalloc(SLOT_NAME_SIZE, GFP_KERNEL); + if (!slot->hotplug_slot->name) + goto error_info; + + slot->hotplug_slot->private = slot; + slot->hotplug_slot->release = &release_slot; + slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; + + slot->acpi_slot = acpiphp_slot; + slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); + slot->hotplug_slot->info->attention_status = 0; + slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); + slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); + slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; + slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; + + acpiphp_slot->slot = slot; + make_slot_name(slot); + + retval = pci_hp_register(slot->hotplug_slot); + if (retval) { + err("pci_hp_register failed with error %d\n", retval); + goto error_name; + } + + info("Slot [%s] registered\n", slot->hotplug_slot->name); return 0; error_name: @@ -412,17 +401,16 @@ error: } -static void __exit cleanup_slots (void) +void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) { - struct list_head *tmp, *n; - struct slot *slot; + struct slot *slot = acpiphp_slot->slot; + int retval = 0; - list_for_each_safe (tmp, n, &slot_list) { - /* memory will be freed in release_slot callback */ - slot = list_entry(tmp, struct slot, slot_list); - list_del(&slot->slot_list); - pci_hp_deregister(slot->hotplug_slot); - } + info ("Slot [%s] unregistered\n", slot->hotplug_slot->name); + + retval = pci_hp_deregister(slot->hotplug_slot); + if (retval) + err("pci_hp_deregister failed with error %d\n", retval); } @@ -439,16 +427,21 @@ static int __init acpiphp_init(void) /* read all the ACPI info from the system */ retval = init_acpi(); - if (retval && !(docking_station)) - return retval; - return init_slots(); + /* if we have found a docking station, we should + * go ahead and load even if init_acpi has found + * no slots. This handles the case when the _DCK + * method not defined under the actual dock bridge + */ + if (docking_station) + return 0; + else + return retval; } static void __exit acpiphp_exit(void) { - cleanup_slots(); /* deallocate internal data structures etc. */ acpiphp_glue_exit(); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 22d0f1cf1362..dbfdac63cb49 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -128,8 +128,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) acpi_handle tmp; acpi_status status = AE_OK; unsigned long adr, sun; - int device, function; - static int num_slots = 0; /* XXX if we support I/O node hotplug... */ + int device, function, retval; status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); @@ -198,7 +197,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) memset(slot, 0, sizeof(struct acpiphp_slot)); slot->bridge = bridge; - slot->id = num_slots++; slot->device = device; slot->sun = sun; INIT_LIST_HEAD(&slot->funcs); @@ -212,6 +210,11 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", slot->sun, pci_domain_nr(bridge->pci_bus), bridge->pci_bus->number, slot->device); + retval = acpiphp_register_hotplug_slot(slot); + if (retval) { + warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval); + goto err_exit; + } } newfunc->slot = slot; @@ -253,6 +256,14 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) status = AE_OK; return status; + + err_exit: + bridge->nr_slots--; + bridge->slots = slot->next; + kfree(slot); + kfree(newfunc); + + return AE_OK; } @@ -335,9 +346,16 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) /* decode ACPI 2.0 _HPP (hot plug parameters) */ decode_hpp(bridge); + /* must be added to the list prior to calling register_slot */ + list_add(&bridge->list, &bridge_list); + /* register all slot objects under this bridge */ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, register_slot, bridge, NULL); + if (ACPI_FAILURE(status)) { + list_del(&bridge->list); + return; + } /* install notify handler */ if (bridge->type != BRIDGE_TYPE_HOST) { @@ -350,8 +368,6 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) err("failed to register interrupt notify handler\n"); } } - - list_add(&bridge->list, &bridge_list); } @@ -555,6 +571,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) list_del(list); kfree(func); } + acpiphp_unregister_hotplug_slot(slot); + list_del(&slot->funcs); kfree(slot); slot = next; } @@ -1521,26 +1539,6 @@ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) } #endif -/* search matching slot from id */ -struct acpiphp_slot *get_slot_from_id(int id) -{ - struct list_head *node; - struct acpiphp_bridge *bridge; - struct acpiphp_slot *slot; - - list_for_each (node, &bridge_list) { - bridge = (struct acpiphp_bridge *)node; - for (slot = bridge->slots; slot; slot = slot->next) - if (slot->id == id) - return slot; - } - - /* should never happen! */ - err("%s: no object for id %d\n", __FUNCTION__, id); - WARN_ON(1); - return NULL; -} - /** * acpiphp_enable_slot - power on slot -- cgit v1.2.3-59-g8ed1b From 0cccd0c20677e8a9da40018632f1b6c487ba2bd5 Mon Sep 17 00:00:00 2001 From: MUNEDA Takahiro Date: Fri, 24 Feb 2006 17:46:04 +0900 Subject: [PATCH] acpiphp: fix bridge handle When hotplug slot is under the host bridge, DEVICE_ACPI_HANDLE(&bus->self->dev) fails since '&bus->self' was not set. This patch fixes it. This patch is based on kristen's latest patches. I tested this patch on my Tiger4. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index dbfdac63cb49..21fa13e84470 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -972,8 +972,8 @@ static int enable_device(struct acpiphp_slot *slot) acpiphp_sanitize_bus(bus); pci_enable_bridges(bus); pci_bus_add_devices(bus); - acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus); - acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev)); + acpiphp_set_hpp_values(slot->bridge->handle, bus); + acpiphp_configure_ioapics(slot->bridge->handle); /* associate pci_dev to our representation */ list_for_each (l, &slot->funcs) { -- cgit v1.2.3-59-g8ed1b From 1305e9184a3de84f78dca102b293d21007bb6c49 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 26 Feb 2006 22:16:51 +0100 Subject: [PATCH] PCI: cpqphp_ctrl.c: board_replaced(): remove dead code The Coverity checker correctly noted, that in function board_replaced in drivers/pci/hotplug/cpqphp_ctrl.c, the variable src always has the value 8, and therefore much code after the ... if (rc || src) { ... if (rc) return rc; else return 1; } ... can never be called. This patch removes the unreachable code in this function fixing kernel Bugzilla #6073. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/cpqphp_ctrl.c | 76 ++++++++------------------------------- 1 file changed, 14 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 72eb8e2d2065..55d2dc7e39ca 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -1282,9 +1282,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) u8 hp_slot; u8 temp_byte; u8 adapter_speed; - u32 index; u32 rc = 0; - u32 src = 8; hp_slot = func->device - ctrl->slot_device_offset; @@ -1368,68 +1366,17 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) rc = cpqhp_configure_board(ctrl, func); - if (rc || src) { - /* If configuration fails, turn it off - * Get slot won't work for devices behind - * bridges, but in this case it will always be - * called for the "base" bus/dev/func of an - * adapter. */ - - mutex_lock(&ctrl->crit_sect); - - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); - - set_SOGO(ctrl); - - /* Wait for SOBS to be unset */ - wait_for_ctrl_irq (ctrl); - - mutex_unlock(&ctrl->crit_sect); - - if (rc) - return rc; - else - return 1; - } - - func->status = 0; - func->switch_save = 0x10; - - index = 1; - while (((func = cpqhp_slot_find(func->bus, func->device, index)) != NULL) && !rc) { - rc |= cpqhp_configure_board(ctrl, func); - index++; - } - - if (rc) { - /* If configuration fails, turn it off - * Get slot won't work for devices behind - * bridges, but in this case it will always be - * called for the "base" bus/dev/func of an - * adapter. */ - - mutex_lock(&ctrl->crit_sect); - - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); - - set_SOGO(ctrl); - - /* Wait for SOBS to be unset */ - wait_for_ctrl_irq (ctrl); - - mutex_unlock(&ctrl->crit_sect); - - return rc; - } - /* Done configuring so turn LED on full time */ + /* If configuration fails, turn it off + * Get slot won't work for devices behind + * bridges, but in this case it will always be + * called for the "base" bus/dev/func of an + * adapter. */ mutex_lock(&ctrl->crit_sect); - green_LED_on (ctrl, hp_slot); + amber_LED_on (ctrl, hp_slot); + green_LED_off (ctrl, hp_slot); + slot_disable (ctrl, hp_slot); set_SOGO(ctrl); @@ -1437,7 +1384,12 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) wait_for_ctrl_irq (ctrl); mutex_unlock(&ctrl->crit_sect); - rc = 0; + + if (rc) + return rc; + else + return 1; + } else { /* Something is wrong -- cgit v1.2.3-59-g8ed1b From 5eeca8e688b6affba4cd85262152fdd1b274ad33 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 5 Mar 2006 16:49:48 +0100 Subject: [PATCH] PCI: the scheduled removal of PCI_LEGACY_PROC This patch contains the scheduled removal of PCI_LEGACY_PROC. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- Documentation/feature-removal-schedule.txt | 7 -- drivers/pci/Kconfig | 17 ---- drivers/pci/proc.c | 126 ----------------------------- 3 files changed, 150 deletions(-) (limited to 'drivers') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index afeaf6218ea2..c7a4d0faab22 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -158,13 +158,6 @@ Who: Adrian Bunk --------------------------- -What: Legacy /proc/pci interface (PCI_LEGACY_PROC) -When: March 2006 -Why: deprecated since 2.5.53 in favor of lspci(8) -Who: Adrian Bunk - ---------------------------- - What: pci_module_init(driver) When: January 2007 Why: Is replaced by pci_register_driver(pci_driver). diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index f187fd8aeed6..d3dcce815d15 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -13,23 +13,6 @@ config PCI_MSI If you don't know what to do here, say N. -config PCI_LEGACY_PROC - bool "Legacy /proc/pci interface" - depends on PCI - ---help--- - This feature enables a procfs file -- /proc/pci -- that provides a - summary of PCI devices in the system. - - This feature has been deprecated as of v2.5.53, in favor of using the - tool lspci(8). This feature may be removed at a future date. - - lspci can provide the same data, as well as much more. lspci is a part of - the pci-utils package, which should be installed by your distribution. - See for information on where to get the latest - version. - - When in doubt, say N. - config PCI_DEBUG bool "PCI Debugging" depends on PCI && DEBUG_KERNEL diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 92a885760832..54b2ebc9c91a 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -458,131 +458,6 @@ int pci_proc_detach_bus(struct pci_bus* bus) return 0; } -#ifdef CONFIG_PCI_LEGACY_PROC - -/* - * Backward compatible /proc/pci interface. - */ - -/* - * Convert some of the configuration space registers of the device at - * address (bus,devfn) into a string (possibly several lines each). - * The configuration string is stored starting at buf[len]. If the - * string would exceed the size of the buffer (SIZE), 0 is returned. - */ -static int show_dev_config(struct seq_file *m, void *v) -{ - struct pci_dev *dev = v; - struct pci_dev *first_dev; - struct pci_driver *drv; - u32 class_rev; - unsigned char latency, min_gnt, max_lat; - int reg; - - first_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev == first_dev) - seq_puts(m, "PCI devices found:\n"); - pci_dev_put(first_dev); - - drv = pci_dev_driver(dev); - - pci_user_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - pci_user_read_config_byte (dev, PCI_LATENCY_TIMER, &latency); - pci_user_read_config_byte (dev, PCI_MIN_GNT, &min_gnt); - pci_user_read_config_byte (dev, PCI_MAX_LAT, &max_lat); - seq_printf(m, " Bus %2d, device %3d, function %2d:\n", - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); - seq_printf(m, " Class %04x", class_rev >> 16); - seq_printf(m, ": PCI device %04x:%04x", dev->vendor, dev->device); - seq_printf(m, " (rev %d).\n", class_rev & 0xff); - - if (dev->irq) - seq_printf(m, " IRQ %d.\n", dev->irq); - - if (latency || min_gnt || max_lat) { - seq_printf(m, " Master Capable. "); - if (latency) - seq_printf(m, "Latency=%d. ", latency); - else - seq_puts(m, "No bursts. "); - if (min_gnt) - seq_printf(m, "Min Gnt=%d.", min_gnt); - if (max_lat) - seq_printf(m, "Max Lat=%d.", max_lat); - seq_putc(m, '\n'); - } - - for (reg = 0; reg < 6; reg++) { - struct resource *res = dev->resource + reg; - unsigned long base, end, flags; - - base = res->start; - end = res->end; - flags = res->flags; - if (!end) - continue; - - if (flags & PCI_BASE_ADDRESS_SPACE_IO) { - seq_printf(m, " I/O at 0x%lx [0x%lx].\n", - base, end); - } else { - const char *pref, *type = "unknown"; - - if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) - pref = "P"; - else - pref = "Non-p"; - switch (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { - case PCI_BASE_ADDRESS_MEM_TYPE_32: - type = "32 bit"; break; - case PCI_BASE_ADDRESS_MEM_TYPE_1M: - type = "20 bit"; break; - case PCI_BASE_ADDRESS_MEM_TYPE_64: - type = "64 bit"; break; - } - seq_printf(m, " %srefetchable %s memory at " - "0x%lx [0x%lx].\n", pref, type, - base, - end); - } - } - return 0; -} - -static struct seq_operations proc_pci_op = { - .start = pci_seq_start, - .next = pci_seq_next, - .stop = pci_seq_stop, - .show = show_dev_config -}; - -static int proc_pci_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &proc_pci_op); -} -static struct file_operations proc_pci_operations = { - .open = proc_pci_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static void legacy_proc_init(void) -{ - struct proc_dir_entry * entry = create_proc_entry("pci", 0, NULL); - if (entry) - entry->proc_fops = &proc_pci_operations; -} - -#else - -static void legacy_proc_init(void) -{ - -} - -#endif /* CONFIG_PCI_LEGACY_PROC */ - static int proc_bus_pci_dev_open(struct inode *inode, struct file *file) { return seq_open(file, &proc_bus_pci_devices_op); @@ -606,7 +481,6 @@ static int __init pci_proc_init(void) while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { pci_proc_attach_device(dev); } - legacy_proc_init(); return 0; } -- cgit v1.2.3-59-g8ed1b From 309e57df7b766172ba137a8cbd909f88dd76e8e9 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 5 Mar 2006 22:33:34 -0700 Subject: [PATCH] PCI: Provide a boot parameter to disable MSI Several drivers are starting to grow options to disable MSI. However, it's often a host chipset issue, not something which individual drivers should handle. So we add the pci=nomsi kernel parameter to allow the user to disable MSI modes for systems we haven't added to the quirk list yet. Signed-off-by: Matthew Wilcox Signed-off-by: Randy Dunlap Acked-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 4 ++++ drivers/pci/Kconfig | 4 ++++ drivers/pci/msi.c | 10 ++++++++++ drivers/pci/pci.c | 8 ++++++-- drivers/pci/pci.h | 2 ++ 5 files changed, 26 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 7b7382d0f758..44a25f3f51d1 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -49,6 +49,7 @@ restrictions referred to are that the relevant option is valid if: MCA MCA bus support is enabled. MDA MDA console support is enabled. MOUSE Appropriate mouse support is enabled. + MSI Message Signaled Interrupts (PCI). MTD MTD support is enabled. NET Appropriate network support is enabled. NUMA NUMA support is enabled. @@ -1152,6 +1153,9 @@ running once the system is up. Mechanism 2. nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI Configuration + nomsi [MSI] If the PCI_MSI kernel config parameter is + enabled, this kernel boot option can be used to + disable the use of MSI interrupts system-wide. nosort [IA-32] Don't sort PCI devices according to order given by the PCI BIOS. This sorting is done to get a device order compatible with diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index d3dcce815d15..4d762fc4878c 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -11,6 +11,10 @@ config PCI_MSI generate an interrupt using an inbound Memory Write on its PCI bus instead of asserting a device IRQ pin. + Use of PCI MSI interrupts can be disabled at kernel boot time + by using the 'pci=nomsi' option. This disables MSI for the + entire system. + If you don't know what to do here, say N. config PCI_DEBUG diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index aea8b258b9b8..a77e79c8c82e 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -765,8 +765,11 @@ void pci_disable_msi(struct pci_dev* dev) u16 control; unsigned long flags; + if (!pci_msi_enable) + return; if (!dev) return; + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); if (!pos) return; @@ -1026,6 +1029,8 @@ void pci_disable_msix(struct pci_dev* dev) int pos, temp; u16 control; + if (!pci_msi_enable) + return; if (!dev) return; @@ -1152,6 +1157,11 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) } } +void pci_no_msi(void) +{ + pci_msi_enable = 0; +} + EXPORT_SYMBOL(pci_enable_msi); EXPORT_SYMBOL(pci_disable_msi); EXPORT_SYMBOL(pci_enable_msix); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 0bf6d254426b..03af23238939 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -900,8 +900,12 @@ static int __devinit pci_setup(char *str) if (k) *k++ = 0; if (*str && (str = pcibios_setup(str)) && *str) { - /* PCI layer options should be handled here */ - printk(KERN_ERR "PCI: Unknown option `%s'\n", str); + if (!strcmp(str, "nomsi")) { + pci_no_msi(); + } else { + printk(KERN_ERR "PCI: Unknown option `%s'\n", + str); + } } str = k; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index a6dfee2f6d2b..8f3fb47ea671 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -50,8 +50,10 @@ extern int pci_msi_quirk; #ifdef CONFIG_PCI_MSI void disable_msi_mode(struct pci_dev *dev, int pos, int type); +void pci_no_msi(void); #else static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { } +static inline void pci_no_msi(void) { } #endif extern int pcie_mch_quirk; -- cgit v1.2.3-59-g8ed1b From 3c990e9219ea0b0aee588473ce6c8a66cdee3ff5 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 4 Mar 2006 21:52:42 -0500 Subject: [PATCH] PCI: fix pci_request_region[s] arg Add missing 'const' to pci_request_region[s] 'res_name' arg, since we pass it directly to __request_region(), whose 'name' arg is also const. Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 4 ++-- include/linux/pci.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 03af23238939..bea1ad1ad5ba 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -639,7 +639,7 @@ void pci_release_region(struct pci_dev *pdev, int bar) * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. */ -int pci_request_region(struct pci_dev *pdev, int bar, char *res_name) +int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) { if (pci_resource_len(pdev, bar) == 0) return 0; @@ -697,7 +697,7 @@ void pci_release_regions(struct pci_dev *pdev) * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. */ -int pci_request_regions(struct pci_dev *pdev, char *res_name) +int pci_request_regions(struct pci_dev *pdev, const char *res_name) { int i; diff --git a/include/linux/pci.h b/include/linux/pci.h index d4d533fa5d30..0aad5a378e95 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -490,9 +490,9 @@ void pdev_sort_resources(struct pci_dev *, struct resource_list *); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), int (*)(struct pci_dev *, u8, u8)); #define HAVE_PCI_REQ_REGIONS 2 -int pci_request_regions(struct pci_dev *, char *); +int pci_request_regions(struct pci_dev *, const char *); void pci_release_regions(struct pci_dev *); -int pci_request_region(struct pci_dev *, int, char *); +int pci_request_region(struct pci_dev *, int, const char *); void pci_release_region(struct pci_dev *, int); /* drivers/pci/bus.c */ -- cgit v1.2.3-59-g8ed1b From 0afabe906539b4e8b9e895f19ea31aabdf12f30b Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Wed, 1 Mar 2006 14:55:11 +0900 Subject: [PATCH] shpchp: cleanup bus speed handling The code related to handling bus speed in SHPCHP driver is unnecessarily complex. This patch cleans up and simplify that. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_ctrl.c | 152 +++---------- drivers/pci/hotplug/shpchp_hpc.c | 466 +++++++++++++------------------------- 2 files changed, 189 insertions(+), 429 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 10f3257b18a7..4e6381481c55 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -198,7 +198,8 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, dbg("%s: change to speed %d\n", __FUNCTION__, speed); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + err("%s: Issue of set bus speed mode command failed\n", + __FUNCTION__); return WRONG_BUS_FREQUENCY; } return rc; @@ -209,33 +210,26 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, enum pci_bus_speed msp) { int rc = 0; - - if (flag != 0) { /* Other slots on the same bus are occupied */ - if ( asp < bsp ) { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bsp, asp); - return WRONG_BUS_FREQUENCY; + + /* + * If other slots on the same bus are occupied, we cannot + * change the bus speed. + */ + if (flag) { + if (asp < bsp) { + err("%s: speed of bus %x and adapter %x mismatch\n", + __FUNCTION__, bsp, asp); + rc = WRONG_BUS_FREQUENCY; } + return rc; + } + + if (asp < msp) { + if (bsp != asp) + rc = change_bus_speed(ctrl, pslot, asp); } else { - /* Other slots on the same bus are empty */ - if (msp == bsp) { - /* if adapter_speed >= bus_speed, do nothing */ - if (asp < bsp) { - /* - * Try to lower bus speed to accommodate the adapter if other slots - * on the same controller are empty - */ - if ((rc = change_bus_speed(ctrl, pslot, asp))) - return rc; - } - } else { - if (asp < msp) { - if ((rc = change_bus_speed(ctrl, pslot, asp))) - return rc; - } else { - if ((rc = change_bus_speed(ctrl, pslot, msp))) - return rc; - } - } + if (bsp != msp) + rc = change_bus_speed(ctrl, pslot, msp); } return rc; } @@ -252,8 +246,7 @@ static int board_added(struct slot *p_slot) u8 hp_slot; u8 slots_not_empty = 0; int rc = 0; - enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; - u8 pi, mode; + enum pci_bus_speed asp, bsp, msp; struct controller *ctrl = p_slot->ctrl; hp_slot = p_slot->device - ctrl->slot_device_offset; @@ -285,109 +278,36 @@ static int board_added(struct slot *p_slot) } } - rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); - /* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */ - /* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC, 0xa = PCI-X 133 Mhz 266, */ - /* 0xd = PCI-X 133 Mhz 533 */ - /* This encoding is different from the one used in cur_bus_speed & */ - /* max_bus_speed */ - - if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { - err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); + rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); + if (rc) { + err("%s: Can't get adapter speed or bus mode mismatch\n", + __FUNCTION__); return WRONG_BUS_FREQUENCY; } - rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); - if (rc || bus_speed == PCI_SPEED_UNKNOWN) { + rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp); + if (rc) { err("%s: Can't get bus operation speed\n", __FUNCTION__); return WRONG_BUS_FREQUENCY; } - rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed); - if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) { + rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp); + if (rc) { err("%s: Can't get max bus operation speed\n", __FUNCTION__); - max_bus_speed = bus_speed; - } - - if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { - err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); - pi = 1; + msp = bsp; } /* Check if there are other slots or devices on the same bus */ if (!list_empty(&ctrl->pci_dev->subordinate->devices)) slots_not_empty = 1; - dbg("%s: slots_not_empty %d, pi %d\n", __FUNCTION__, - slots_not_empty, pi); - dbg("adapter_speed %d, bus_speed %d, max_bus_speed %d\n", - adapter_speed, bus_speed, max_bus_speed); - - if (pi == 2) { - dbg("%s: In PI = %d\n", __FUNCTION__, pi); - if ((rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode))) { - err("%s: Can't get Mode1_ECC, set mode to 0\n", __FUNCTION__); - mode = 0; - } + dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, " + "max_bus_speed %d\n", __FUNCTION__, slots_not_empty, asp, + bsp, msp); - switch (adapter_speed) { - case PCI_SPEED_133MHz_PCIX_533: - case PCI_SPEED_133MHz_PCIX_266: - if ((bus_speed != adapter_speed) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - break; - case PCI_SPEED_133MHz_PCIX_ECC: - case PCI_SPEED_133MHz_PCIX: - if (mode) { /* Bus - Mode 1 ECC */ - if ((bus_speed != 0x7) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } else { - if ((bus_speed != 0x4) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } - break; - case PCI_SPEED_66MHz_PCIX_ECC: - case PCI_SPEED_66MHz_PCIX: - if (mode) { /* Bus - Mode 1 ECC */ - if ((bus_speed != 0x5) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } else { - if ((bus_speed != 0x2) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } - break; - case PCI_SPEED_66MHz: - if ((bus_speed != 0x1) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - break; - case PCI_SPEED_33MHz: - if (bus_speed > 0x0) { - if (slots_not_empty == 0) { - if ((rc = change_bus_speed(ctrl, p_slot, adapter_speed))) - return rc; - } else { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - } - break; - default: - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - } else { - /* If adpater_speed == bus_speed, nothing to do here */ - dbg("%s: In PI = %d\n", __FUNCTION__, pi); - if ((adapter_speed != bus_speed) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } + rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp); + if (rc) + return rc; /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index b392606a905a..66123cf4deaa 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -82,31 +82,6 @@ #define SLOT_100MHZ_PCIX_533 0x0f000000 #define SLOT_133MHZ_PCIX_533 0xf0000000 - -/* Secondary Bus Configuration Register */ -/* For PI = 1, Bits 0 to 2 have been encoded as follows to show current bus speed/mode */ -#define PCI_33MHZ 0x0 -#define PCI_66MHZ 0x1 -#define PCIX_66MHZ 0x2 -#define PCIX_100MHZ 0x3 -#define PCIX_133MHZ 0x4 - -/* For PI = 2, Bits 0 to 3 have been encoded as follows to show current bus speed/mode */ -#define PCI_33MHZ 0x0 -#define PCI_66MHZ 0x1 -#define PCIX_66MHZ 0x2 -#define PCIX_100MHZ 0x3 -#define PCIX_133MHZ 0x4 -#define PCIX_66MHZ_ECC 0x5 -#define PCIX_100MHZ_ECC 0x6 -#define PCIX_133MHZ_ECC 0x7 -#define PCIX_66MHZ_266 0x9 -#define PCIX_100MHZ_266 0xa -#define PCIX_133MHZ_266 0xb -#define PCIX_66MHZ_533 0x11 -#define PCIX_100MHZ_533 0x12 -#define PCIX_133MHZ_533 0x13 - /* Slot Configuration */ #define SLOT_NUM 0x0000001F #define FIRST_DEV_NUM 0x00001F00 @@ -548,81 +523,41 @@ 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) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u32 slot_reg; - u16 slot_status, sec_bus_status; - u8 m66_cap, pcix_cap, pi; 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); + u8 pcix_cap = (slot_reg >> 12) & 7; + u8 m66_cap = (slot_reg >> 9) & 1; 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; - } - - pi = readb(php_ctlr->creg + PROG_INTERFACE); - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); - dbg("%s: pi = %d, slot_reg = %x\n", __FUNCTION__, pi, slot_reg); - slot_status = (u16) slot_reg; - dbg("%s: slot_status = %x\n", __FUNCTION__, slot_status); - sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); - - pcix_cap = (u8) ((slot_status & 0x3000) >> 12); - dbg("%s: pcix_cap = %x\n", __FUNCTION__, pcix_cap); - m66_cap = (u8) ((slot_status & 0x0200) >> 9); - dbg("%s: m66_cap = %x\n", __FUNCTION__, m66_cap); + dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", + __FUNCTION__, slot_reg, pcix_cap, m66_cap); - - if (pi == 2) { - switch (pcix_cap) { - case 0: - *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; - break; - case 1: - *value = PCI_SPEED_66MHz_PCIX; - break; - case 3: - *value = PCI_SPEED_133MHz_PCIX; - break; - case 4: - *value = PCI_SPEED_133MHz_PCIX_266; - break; - case 5: - *value = PCI_SPEED_133MHz_PCIX_533; - break; - case 2: /* Reserved */ - default: - *value = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - break; - } - } else { - switch (pcix_cap) { - case 0: - *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; - break; - case 1: - *value = PCI_SPEED_66MHz_PCIX; - break; - case 3: - *value = PCI_SPEED_133MHz_PCIX; - break; - case 2: /* Reserved */ - default: - *value = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - break; - } + switch (pcix_cap) { + case 0x0: + *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; + break; + case 0x1: + *value = PCI_SPEED_66MHz_PCIX; + break; + case 0x3: + *value = PCI_SPEED_133MHz_PCIX; + break; + case 0x4: + *value = PCI_SPEED_133MHz_PCIX_266; + break; + case 0x5: + *value = PCI_SPEED_133MHz_PCIX_533; + break; + case 0x2: + default: + *value = PCI_SPEED_UNKNOWN; + retval = -ENODEV; + break; } dbg("Adapter speed = %d\n", *value); - DBG_LEAVE_ROUTINE return retval; } @@ -965,98 +900,66 @@ static int hpc_slot_disable(struct slot * slot) static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) { - u8 slot_cmd; - u8 pi; - int retval = 0; + int retval; struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + u8 pi, cmd; DBG_ENTER_ROUTINE - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } pi = readb(php_ctlr->creg + PROG_INTERFACE); - - if (pi == 1) { - switch (value) { - case 0: - slot_cmd = SETA_PCI_33MHZ; - break; - case 1: - slot_cmd = SETA_PCI_66MHZ; - break; - case 2: - slot_cmd = SETA_PCIX_66MHZ; - break; - case 3: - slot_cmd = SETA_PCIX_100MHZ; - break; - case 4: - slot_cmd = SETA_PCIX_133MHZ; - break; - default: - slot_cmd = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - return retval; - } - } else { - switch (value) { - case 0: - slot_cmd = SETB_PCI_33MHZ; - break; - case 1: - slot_cmd = SETB_PCI_66MHZ; - break; - case 2: - slot_cmd = SETB_PCIX_66MHZ_PM; - break; - case 3: - slot_cmd = SETB_PCIX_100MHZ_PM; - break; - case 4: - slot_cmd = SETB_PCIX_133MHZ_PM; - break; - case 5: - slot_cmd = SETB_PCIX_66MHZ_EM; - break; - case 6: - slot_cmd = SETB_PCIX_100MHZ_EM; - break; - case 7: - slot_cmd = SETB_PCIX_133MHZ_EM; - break; - case 8: - slot_cmd = SETB_PCIX_66MHZ_266; - break; - case 0x9: - slot_cmd = SETB_PCIX_100MHZ_266; - break; - case 0xa: - slot_cmd = SETB_PCIX_133MHZ_266; - break; - case 0xb: - slot_cmd = SETB_PCIX_66MHZ_533; - break; - case 0xc: - slot_cmd = SETB_PCIX_100MHZ_533; - break; - case 0xd: - slot_cmd = SETB_PCIX_133MHZ_533; - break; - default: - slot_cmd = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - return retval; - } + if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) + return -EINVAL; + switch (value) { + case PCI_SPEED_33MHz: + cmd = SETA_PCI_33MHZ; + break; + case PCI_SPEED_66MHz: + cmd = SETA_PCI_66MHZ; + break; + case PCI_SPEED_66MHz_PCIX: + cmd = SETA_PCIX_66MHZ; + break; + case PCI_SPEED_100MHz_PCIX: + cmd = SETA_PCIX_100MHZ; + break; + case PCI_SPEED_133MHz_PCIX: + cmd = SETA_PCIX_133MHZ; + break; + case PCI_SPEED_66MHz_PCIX_ECC: + cmd = SETB_PCIX_66MHZ_EM; + break; + case PCI_SPEED_100MHz_PCIX_ECC: + cmd = SETB_PCIX_100MHZ_EM; + break; + case PCI_SPEED_133MHz_PCIX_ECC: + cmd = SETB_PCIX_133MHZ_EM; + break; + case PCI_SPEED_66MHz_PCIX_266: + cmd = SETB_PCIX_66MHZ_266; + break; + case PCI_SPEED_100MHz_PCIX_266: + cmd = SETB_PCIX_100MHZ_266; + break; + case PCI_SPEED_133MHz_PCIX_266: + cmd = SETB_PCIX_133MHZ_266; + break; + case PCI_SPEED_66MHz_PCIX_533: + cmd = SETB_PCIX_66MHZ_533; + break; + case PCI_SPEED_100MHz_PCIX_533: + cmd = SETB_PCIX_100MHZ_533; + break; + case PCI_SPEED_133MHz_PCIX_533: + cmd = SETB_PCIX_133MHZ_533; + break; + default: + return -EINVAL; } - retval = shpc_write_cmd(slot, 0, slot_cmd); - if (retval) { + + retval = shpc_write_cmd(slot, 0, cmd); + if (retval) err("%s: Write command failed!\n", __FUNCTION__); - return -1; - } DBG_LEAVE_ROUTINE return retval; @@ -1163,64 +1066,43 @@ 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; enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; - int retval = 0; - u8 pi; - u32 slot_avail1, slot_avail2; + 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); 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; - } - - pi = readb(php_ctlr->creg + PROG_INTERFACE); - slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); - slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); - if (pi == 2) { if (slot_avail2 & SLOT_133MHZ_PCIX_533) - bus_speed = PCIX_133MHZ_533; + bus_speed = PCI_SPEED_133MHz_PCIX_533; else if (slot_avail2 & SLOT_100MHZ_PCIX_533) - bus_speed = PCIX_100MHZ_533; + bus_speed = PCI_SPEED_100MHz_PCIX_533; else if (slot_avail2 & SLOT_66MHZ_PCIX_533) - bus_speed = PCIX_66MHZ_533; + bus_speed = PCI_SPEED_66MHz_PCIX_533; else if (slot_avail2 & SLOT_133MHZ_PCIX_266) - bus_speed = PCIX_133MHZ_266; + bus_speed = PCI_SPEED_133MHz_PCIX_266; else if (slot_avail2 & SLOT_100MHZ_PCIX_266) - bus_speed = PCIX_100MHZ_266; + bus_speed = PCI_SPEED_100MHz_PCIX_266; else if (slot_avail2 & SLOT_66MHZ_PCIX_266) - bus_speed = PCIX_66MHZ_266; - else if (slot_avail1 & SLOT_133MHZ_PCIX) - bus_speed = PCIX_133MHZ; - else if (slot_avail1 & SLOT_100MHZ_PCIX) - bus_speed = PCIX_100MHZ; - else if (slot_avail1 & SLOT_66MHZ_PCIX) - bus_speed = PCIX_66MHZ; - else if (slot_avail2 & SLOT_66MHZ) - bus_speed = PCI_66MHZ; - else if (slot_avail1 & SLOT_33MHZ) - bus_speed = PCI_33MHZ; - else bus_speed = PCI_SPEED_UNKNOWN; - } else { + bus_speed = PCI_SPEED_66MHz_PCIX_266; + } + + if (bus_speed == PCI_SPEED_UNKNOWN) { if (slot_avail1 & SLOT_133MHZ_PCIX) - bus_speed = PCIX_133MHZ; + bus_speed = PCI_SPEED_133MHz_PCIX; else if (slot_avail1 & SLOT_100MHZ_PCIX) - bus_speed = PCIX_100MHZ; + bus_speed = PCI_SPEED_100MHz_PCIX; else if (slot_avail1 & SLOT_66MHZ_PCIX) - bus_speed = PCIX_66MHZ; + bus_speed = PCI_SPEED_66MHz_PCIX; else if (slot_avail2 & SLOT_66MHZ) - bus_speed = PCI_66MHZ; + bus_speed = PCI_SPEED_66MHz; else if (slot_avail1 & SLOT_33MHZ) - bus_speed = PCI_33MHZ; - else bus_speed = PCI_SPEED_UNKNOWN; + bus_speed = PCI_SPEED_33MHz; + else + retval = -ENODEV; } *value = bus_speed; @@ -1231,111 +1113,69 @@ 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; enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; - u16 sec_bus_status; - int retval = 0; - u8 pi; + u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG); + u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); + u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); 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; + if ((pi == 1) && (speed_mode > 4)) { + *value = PCI_SPEED_UNKNOWN; + return -ENODEV; } - pi = readb(php_ctlr->creg + PROG_INTERFACE); - sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); - - if (pi == 2) { - switch (sec_bus_status & 0x000f) { - case 0: - bus_speed = PCI_SPEED_33MHz; - break; - case 1: - bus_speed = PCI_SPEED_66MHz; - break; - case 2: - bus_speed = PCI_SPEED_66MHz_PCIX; - break; - case 3: - bus_speed = PCI_SPEED_100MHz_PCIX; - break; - case 4: - bus_speed = PCI_SPEED_133MHz_PCIX; - break; - case 5: - bus_speed = PCI_SPEED_66MHz_PCIX_ECC; - break; - case 6: - bus_speed = PCI_SPEED_100MHz_PCIX_ECC; - break; - case 7: - bus_speed = PCI_SPEED_133MHz_PCIX_ECC; - break; - case 8: - bus_speed = PCI_SPEED_66MHz_PCIX_266; - break; - case 9: - bus_speed = PCI_SPEED_100MHz_PCIX_266; - break; - case 0xa: - bus_speed = PCI_SPEED_133MHz_PCIX_266; - break; - case 0xb: - bus_speed = PCI_SPEED_66MHz_PCIX_533; - break; - case 0xc: - bus_speed = PCI_SPEED_100MHz_PCIX_533; - break; - case 0xd: - bus_speed = PCI_SPEED_133MHz_PCIX_533; - break; - case 0xe: - case 0xf: - default: - bus_speed = PCI_SPEED_UNKNOWN; - break; - } - } else { - /* In the case where pi is undefined, default it to 1 */ - switch (sec_bus_status & 0x0007) { - case 0: - bus_speed = PCI_SPEED_33MHz; - break; - case 1: - bus_speed = PCI_SPEED_66MHz; - break; - case 2: - bus_speed = PCI_SPEED_66MHz_PCIX; - break; - case 3: - bus_speed = PCI_SPEED_100MHz_PCIX; - break; - case 4: - bus_speed = PCI_SPEED_133MHz_PCIX; - break; - case 5: - bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ - break; - case 6: - bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ - break; - case 7: - bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ - break; - default: - bus_speed = PCI_SPEED_UNKNOWN; - break; - } + switch (speed_mode) { + case 0x0: + *value = PCI_SPEED_33MHz; + break; + case 0x1: + *value = PCI_SPEED_66MHz; + break; + case 0x2: + *value = PCI_SPEED_66MHz_PCIX; + break; + case 0x3: + *value = PCI_SPEED_100MHz_PCIX; + break; + case 0x4: + *value = PCI_SPEED_133MHz_PCIX; + break; + case 0x5: + *value = PCI_SPEED_66MHz_PCIX_ECC; + break; + case 0x6: + *value = PCI_SPEED_100MHz_PCIX_ECC; + break; + case 0x7: + *value = PCI_SPEED_133MHz_PCIX_ECC; + break; + case 0x8: + *value = PCI_SPEED_66MHz_PCIX_266; + break; + case 0x9: + *value = PCI_SPEED_100MHz_PCIX_266; + break; + case 0xa: + *value = PCI_SPEED_133MHz_PCIX_266; + break; + case 0xb: + *value = PCI_SPEED_66MHz_PCIX_533; + break; + case 0xc: + *value = PCI_SPEED_100MHz_PCIX_533; + break; + case 0xd: + *value = PCI_SPEED_133MHz_PCIX_533; + break; + default: + *value = PCI_SPEED_UNKNOWN; + retval = -ENODEV; + break; } - *value = bus_speed; dbg("Current bus speed = %d\n", bus_speed); DBG_LEAVE_ROUTINE return retval; -- cgit v1.2.3-59-g8ed1b From 8e77af6a9a9b1eefdb538894b20ed41f65b65ab7 Mon Sep 17 00:00:00 2001 From: John Keller Date: Wed, 8 Mar 2006 13:21:34 -0600 Subject: [PATCH] PCI Hotplug: SN: Fix cleanup on hotplug removal of PPB When doing a hotplug removal of a PPB, sn_bus_store_sysdata() needs to be called for the PPB and all of its children. Acked-by: Prarit Bhargava Signed-off-by: John Keller Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/sgi_hotplug.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index a32ae82e5922..c402da8e78ae 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2005-2006 Silicon Graphics, Inc. All rights reserved. * * This work was based on the 2.4/2.6 kernel development by Dick Reigner. * Work to add BIOS PROM support was completed by Mike Habeck. @@ -230,6 +230,13 @@ static void sn_bus_free_data(struct pci_dev *dev) list_for_each_entry(child, &subordinate_bus->devices, bus_list) sn_bus_free_data(child); } + /* + * Some drivers may use dma accesses during the + * driver remove function. We release the sysdata + * areas after the driver remove functions have + * been called. + */ + sn_bus_store_sysdata(dev); sn_pci_unfixup_slot(dev); } @@ -429,13 +436,6 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) PCI_DEVFN(slot->device_num + 1, PCI_FUNC(func))); if (dev) { - /* - * Some drivers may use dma accesses during the - * driver remove function. We release the sysdata - * areas after the driver remove functions have - * been called. - */ - sn_bus_store_sysdata(dev); sn_bus_free_data(dev); pci_remove_bus_device(dev); pci_dev_put(dev); -- cgit v1.2.3-59-g8ed1b From 7c8f25da12a3dda46fb730699582895d5fc51287 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Mon, 27 Feb 2006 22:15:49 +0900 Subject: [PATCH] acpiphp: Scan slots under the nested P2P bridge Current ACPIPHP driver scans only slots under the top level PCI-to-PCI bridge. So hotplug PCI slots under the nested PCI-to-PCI bridge would not be detected. For example, if the system has the ACPI namespace like below, hotplug slots woule not be detected. Device (PCI0) { /* Root bridge */ Name (_HID, "PNP0A03") Device (P2PA) { /* PCI-to-PCI bridge */ Name (_ADR, ...) Device (P2PB) { /* PCI-to-PCI bridge */ Name (_ADR, ...) Device (S0F0) { /* hotplug slot */ Name (_ADR, ...) Name (_SUN, ...) Method (_EJ0, ...) { ... } } ... Device (S0F7) { /* hotplug slot */ Name (_ADR, ...) Name (_SUN, ...) Method (_EJ0, ...) { ... } } Device (S1F0) { /* hotplug slot */ Name (_ADR, ...) Name (_SUN, ...) Method (_EJ0, ...) { ... } } ... } } } This patch fixes this issue. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 21fa13e84470..cbd5893d198e 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -463,6 +463,12 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) add_p2p_bridge(handle, dev); } + /* search P2P bridges under this p2p bridge */ + 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); + out: pci_dev_put(dev); return AE_OK; @@ -603,7 +609,8 @@ static void remove_bridge(acpi_handle handle) } else { /* clean-up p2p bridges under this host bridge */ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - (u32)1, cleanup_p2p_bridge, NULL, NULL); + ACPI_UINT32_MAX, cleanup_p2p_bridge, + NULL, NULL); } } -- cgit v1.2.3-59-g8ed1b From f5afe8064f3087bead8fea7e32547c2a3ada5fd0 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Tue, 28 Feb 2006 15:34:49 +0100 Subject: [PATCH] PCI: kzalloc() conversion in drivers/pci this patch converts drivers/pci to kzalloc usage. Compile tested with allyes config. Signed-off-by: Eric Sesterhenn Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 14 +++----- drivers/pci/hotplug/cpci_hotplug_core.c | 9 ++--- drivers/pci/hotplug/cpqphp_core.c | 13 +++---- drivers/pci/hotplug/fakephp.c | 9 ++--- drivers/pci/hotplug/ibmphp_core.c | 6 ++-- drivers/pci/hotplug/ibmphp_ebda.c | 57 ++++++++--------------------- drivers/pci/hotplug/ibmphp_pci.c | 63 +++++++++++---------------------- drivers/pci/hotplug/ibmphp_res.c | 33 ++++++----------- drivers/pci/hotplug/pciehp_core.c | 13 +++---- drivers/pci/hotplug/rpaphp_slot.c | 9 ++--- drivers/pci/pci-driver.c | 3 +- drivers/pci/pci-sysfs.c | 3 +- drivers/pci/pcie/portdrv_core.c | 3 +- drivers/pci/probe.c | 9 ++--- 14 files changed, 75 insertions(+), 169 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index cbd5893d198e..c7e6387983df 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -143,10 +143,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) device = (adr >> 16) & 0xffff; function = adr & 0xffff; - newfunc = kmalloc(sizeof(struct acpiphp_func), GFP_KERNEL); + newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); if (!newfunc) return AE_NO_MEMORY; - memset(newfunc, 0, sizeof(struct acpiphp_func)); INIT_LIST_HEAD(&newfunc->sibling); newfunc->handle = handle; @@ -189,13 +188,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) } if (!slot) { - slot = kmalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); + slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); if (!slot) { kfree(newfunc); return AE_NO_MEMORY; } - memset(slot, 0, sizeof(struct acpiphp_slot)); slot->bridge = bridge; slot->device = device; slot->sun = sun; @@ -376,12 +374,10 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) { struct acpiphp_bridge *bridge; - bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); + bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); if (bridge == NULL) return; - memset(bridge, 0, sizeof(struct acpiphp_bridge)); - bridge->type = BRIDGE_TYPE_HOST; bridge->handle = handle; @@ -398,14 +394,12 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) { struct acpiphp_bridge *bridge; - bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); + bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); if (bridge == NULL) { err("out of memory\n"); return; } - memset(bridge, 0, sizeof(struct acpiphp_bridge)); - bridge->type = BRIDGE_TYPE_P2P; bridge->handle = handle; diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 30af105271a2..037ce4c91687 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c @@ -248,22 +248,19 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) * with the pci_hotplug subsystem. */ for (i = first; i <= last; ++i) { - slot = kmalloc(sizeof (struct slot), GFP_KERNEL); + slot = kzalloc(sizeof (struct slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof (struct slot)); hotplug_slot = - kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL); + kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL); if (!hotplug_slot) goto error_slot; - memset(hotplug_slot, 0, sizeof (struct hotplug_slot)); slot->hotplug_slot = hotplug_slot; - info = kmalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); + info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); if (!info) goto error_hpslot; - memset(info, 0, sizeof (struct hotplug_slot_info)); hotplug_slot->info = info; name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 8626901daeb8..9bc1deb8df52 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -347,26 +347,22 @@ static int ctrl_slot_setup(struct controller *ctrl, slot_number = ctrl->first_slot; while (number_of_slots) { - slot = kmalloc(sizeof(*slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(struct slot)); - slot->hotplug_slot = kmalloc(sizeof(*(slot->hotplug_slot)), + slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)), GFP_KERNEL); if (!slot->hotplug_slot) goto error_slot; hotplug_slot = slot->hotplug_slot; - memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); hotplug_slot->info = - kmalloc(sizeof(*(hotplug_slot->info)), + kzalloc(sizeof(*(hotplug_slot->info)), GFP_KERNEL); if (!hotplug_slot->info) goto error_hpslot; hotplug_slot_info = hotplug_slot->info; - memset(hotplug_slot_info, 0, - sizeof(struct hotplug_slot_info)); hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); if (!hotplug_slot->name) @@ -854,13 +850,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_disable_device; } - ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); + ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); rc = -ENOMEM; goto err_disable_device; } - memset(ctrl, 0, sizeof(struct controller)); rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); if (rc) { diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 060d74775d7b..71b80c23e8ce 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -95,15 +95,13 @@ static int add_slot(struct pci_dev *dev) struct hotplug_slot *slot; int retval = -ENOMEM; - slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); + slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(*slot)); - slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + slot->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!slot->info) goto error_slot; - memset(slot->info, 0, sizeof(struct hotplug_slot_info)); slot->info->power_status = 1; slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; @@ -227,11 +225,10 @@ static void pci_rescan_bus(const struct pci_bus *bus) { unsigned int devfn; struct pci_dev *dev; - dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return; - memset(dev, 0, sizeof(dev)); dev->bus = (struct pci_bus*)bus; dev->sysdata = bus->sysdata; for (devfn = 0; devfn < 0x100; devfn += 8) { diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index dc59da675c08..45e2a0d9b596 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -1141,7 +1141,7 @@ static int enable_slot(struct hotplug_slot *hs) goto error_power; } - slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL); + slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL); if (!slot_cur->func) { /* We cannot do update_slot_info here, since no memory for * kmalloc n.e.ways, and update_slot_info allocates some */ @@ -1149,7 +1149,6 @@ static int enable_slot(struct hotplug_slot *hs) rc = -ENOMEM; goto error_power; } - memset(slot_cur->func, 0, sizeof(struct pci_func)); slot_cur->func->busno = slot_cur->bus; slot_cur->func->device = slot_cur->device; for (i = 0; i < 4; i++) @@ -1252,13 +1251,12 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) if (slot_cur->func == NULL) { /* We need this for fncs's that were there on bootup */ - slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL); + slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL); if (!slot_cur->func) { err("out of system memory\n"); rc = -ENOMEM; goto error; } - memset(slot_cur->func, 0, sizeof(struct pci_func)); slot_cur->func->busno = slot_cur->bus; slot_cur->func->device = slot_cur->device; } diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index aea1187c73ad..ba12034c5d3a 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c @@ -72,13 +72,7 @@ static int ebda_rio_table (void); static struct ebda_hpc_list * __init alloc_ebda_hpc_list (void) { - struct ebda_hpc_list *list; - - list = kmalloc (sizeof (struct ebda_hpc_list), GFP_KERNEL); - if (!list) - return NULL; - memset (list, 0, sizeof (*list)); - return list; + return kzalloc(sizeof(struct ebda_hpc_list), GFP_KERNEL); } static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count) @@ -87,21 +81,18 @@ static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count) struct ebda_hpc_slot *slots; struct ebda_hpc_bus *buses; - controller = kmalloc (sizeof (struct controller), GFP_KERNEL); + controller = kzalloc(sizeof(struct controller), GFP_KERNEL); if (!controller) goto error; - memset (controller, 0, sizeof (*controller)); - slots = kmalloc (sizeof (struct ebda_hpc_slot) * slot_count, GFP_KERNEL); + slots = kcalloc(slot_count, sizeof(struct ebda_hpc_slot), GFP_KERNEL); if (!slots) goto error_contr; - memset (slots, 0, sizeof (*slots) * slot_count); controller->slots = slots; - buses = kmalloc (sizeof (struct ebda_hpc_bus) * bus_count, GFP_KERNEL); + buses = kcalloc(bus_count, sizeof(struct ebda_hpc_bus), GFP_KERNEL); if (!buses) goto error_slots; - memset (buses, 0, sizeof (*buses) * bus_count); controller->buses = buses; return controller; @@ -122,24 +113,12 @@ static void free_ebda_hpc (struct controller *controller) static struct ebda_rsrc_list * __init alloc_ebda_rsrc_list (void) { - struct ebda_rsrc_list *list; - - list = kmalloc (sizeof (struct ebda_rsrc_list), GFP_KERNEL); - if (!list) - return NULL; - memset (list, 0, sizeof (*list)); - return list; + return kzalloc(sizeof(struct ebda_rsrc_list), GFP_KERNEL); } static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void) { - struct ebda_pci_rsrc *resource; - - resource = kmalloc (sizeof (struct ebda_pci_rsrc), GFP_KERNEL); - if (!resource) - return NULL; - memset (resource, 0, sizeof (*resource)); - return resource; + return kzalloc(sizeof(struct ebda_pci_rsrc), GFP_KERNEL); } static void __init print_bus_info (void) @@ -390,10 +369,9 @@ int __init ibmphp_access_ebda (void) debug ("now enter io table ---\n"); debug ("rio blk id: %x\n", blk_id); - rio_table_ptr = kmalloc (sizeof (struct rio_table_hdr), GFP_KERNEL); + rio_table_ptr = kzalloc(sizeof(struct rio_table_hdr), GFP_KERNEL); if (!rio_table_ptr) return -ENOMEM; - memset (rio_table_ptr, 0, sizeof (struct rio_table_hdr) ); rio_table_ptr->ver_num = readb (io_mem + offset); rio_table_ptr->scal_count = readb (io_mem + offset + 1); rio_table_ptr->riodev_count = readb (io_mem + offset + 2); @@ -445,10 +423,9 @@ static int __init ebda_rio_table (void) // we do concern about rio details for (i = 0; i < rio_table_ptr->riodev_count; i++) { - rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL); + rio_detail_ptr = kzalloc(sizeof(struct rio_detail), GFP_KERNEL); if (!rio_detail_ptr) return -ENOMEM; - memset (rio_detail_ptr, 0, sizeof (struct rio_detail)); rio_detail_ptr->rio_node_id = readb (io_mem + offset); rio_detail_ptr->bbar = readl (io_mem + offset + 1); rio_detail_ptr->rio_type = readb (io_mem + offset + 5); @@ -503,10 +480,9 @@ static int __init combine_wpg_for_chassis (void) rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num); if (!opt_rio_ptr) { - opt_rio_ptr = (struct opt_rio *) kmalloc (sizeof (struct opt_rio), GFP_KERNEL); + opt_rio_ptr = kzalloc(sizeof(struct opt_rio), GFP_KERNEL); if (!opt_rio_ptr) return -ENOMEM; - memset (opt_rio_ptr, 0, sizeof (struct opt_rio)); opt_rio_ptr->rio_type = rio_detail_ptr->rio_type; opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num; opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num; @@ -546,10 +522,9 @@ static int combine_wpg_for_expansion (void) rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num); if (!opt_rio_lo_ptr) { - opt_rio_lo_ptr = (struct opt_rio_lo *) kmalloc (sizeof (struct opt_rio_lo), GFP_KERNEL); + opt_rio_lo_ptr = kzalloc(sizeof(struct opt_rio_lo), GFP_KERNEL); if (!opt_rio_lo_ptr) return -ENOMEM; - memset (opt_rio_lo_ptr, 0, sizeof (struct opt_rio_lo)); opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type; opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num; opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num; @@ -842,12 +817,11 @@ static int __init ebda_rsrc_controller (void) bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num); if (!bus_info_ptr2) { - bus_info_ptr1 = (struct bus_info *) kmalloc (sizeof (struct bus_info), GFP_KERNEL); + bus_info_ptr1 = kzalloc(sizeof(struct bus_info), GFP_KERNEL); if (!bus_info_ptr1) { rc = -ENOMEM; goto error_no_hp_slot; } - memset (bus_info_ptr1, 0, sizeof (struct bus_info)); bus_info_ptr1->slot_min = slot_ptr->slot_num; bus_info_ptr1->slot_max = slot_ptr->slot_num; bus_info_ptr1->slot_count += 1; @@ -946,19 +920,17 @@ static int __init ebda_rsrc_controller (void) // register slots with hpc core as well as create linked list of ibm slot for (index = 0; index < hpc_ptr->slot_count; index++) { - hp_slot_ptr = kmalloc(sizeof(*hp_slot_ptr), GFP_KERNEL); + hp_slot_ptr = kzalloc(sizeof(*hp_slot_ptr), GFP_KERNEL); if (!hp_slot_ptr) { rc = -ENOMEM; goto error_no_hp_slot; } - memset(hp_slot_ptr, 0, sizeof(*hp_slot_ptr)); - hp_slot_ptr->info = kmalloc (sizeof(struct hotplug_slot_info), GFP_KERNEL); + hp_slot_ptr->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!hp_slot_ptr->info) { rc = -ENOMEM; goto error_no_hp_info; } - memset(hp_slot_ptr->info, 0, sizeof(struct hotplug_slot_info)); hp_slot_ptr->name = kmalloc(30, GFP_KERNEL); if (!hp_slot_ptr->name) { @@ -966,12 +938,11 @@ static int __init ebda_rsrc_controller (void) goto error_no_hp_name; } - tmp_slot = kmalloc(sizeof(*tmp_slot), GFP_KERNEL); + tmp_slot = kzalloc(sizeof(*tmp_slot), GFP_KERNEL); if (!tmp_slot) { rc = -ENOMEM; goto error_no_slot; } - memset(tmp_slot, 0, sizeof(*tmp_slot)); tmp_slot->flag = TRUE; diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 155133fe5c12..97753ddcd856 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c @@ -164,12 +164,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cleanup_count = 6; goto error; } - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err ("out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = cur_func->busno; newfunc->device = device; cur_func->next = newfunc; @@ -203,12 +202,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) flag = FALSE; for (i = 0; i < 32; i++) { if (func->devices[i]) { - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err ("out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = sec_number; newfunc->device = (u8) i; for (j = 0; j < 4; j++) @@ -232,12 +230,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) } } - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err ("out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = cur_func->busno; newfunc->device = device; for (j = 0; j < 4; j++) @@ -279,12 +276,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) for (i = 0; i < 32; i++) { if (func->devices[i]) { debug ("inside for loop, device is %x\n", i); - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err (" out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = sec_number; newfunc->device = (u8) i; for (j = 0; j < 4; j++) @@ -405,13 +401,12 @@ static int configure_device (struct pci_func *func) debug ("len[count] in IO %x, count %d\n", len[count], count); - io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!io[count]) { err ("out of system memory\n"); return -ENOMEM; } - memset (io[count], 0, sizeof (struct resource_node)); io[count]->type = IO; io[count]->busno = func->busno; io[count]->devfunc = PCI_DEVFN(func->device, func->function); @@ -444,12 +439,11 @@ static int configure_device (struct pci_func *func) debug ("len[count] in PFMEM %x, count %d\n", len[count], count); - pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!pfmem[count]) { err ("out of system memory\n"); return -ENOMEM; } - memset (pfmem[count], 0, sizeof (struct resource_node)); pfmem[count]->type = PFMEM; pfmem[count]->busno = func->busno; pfmem[count]->devfunc = PCI_DEVFN(func->device, @@ -460,13 +454,12 @@ static int configure_device (struct pci_func *func) ibmphp_add_resource (pfmem[count]); func->pfmem[count] = pfmem[count]; } else { - mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); + mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { err ("out of system memory\n"); kfree (pfmem[count]); return -ENOMEM; } - memset (mem_tmp, 0, sizeof (struct resource_node)); mem_tmp->type = MEM; mem_tmp->busno = pfmem[count]->busno; mem_tmp->devfunc = pfmem[count]->devfunc; @@ -512,12 +505,11 @@ static int configure_device (struct pci_func *func) debug ("len[count] in Mem %x, count %d\n", len[count], count); - mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!mem[count]) { err ("out of system memory\n"); return -ENOMEM; } - memset (mem[count], 0, sizeof (struct resource_node)); mem[count]->type = MEM; mem[count]->busno = func->busno; mem[count]->devfunc = PCI_DEVFN(func->device, @@ -677,14 +669,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) debug ("len[count] in IO = %x\n", len[count]); - bus_io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + bus_io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_io[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus_io[count], 0, sizeof (struct resource_node)); bus_io[count]->type = IO; bus_io[count]->busno = func->busno; bus_io[count]->devfunc = PCI_DEVFN(func->device, @@ -711,13 +702,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) debug ("len[count] in PFMEM = %x\n", len[count]); - bus_pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + bus_pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_pfmem[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus_pfmem[count], 0, sizeof (struct resource_node)); bus_pfmem[count]->type = PFMEM; bus_pfmem[count]->busno = func->busno; bus_pfmem[count]->devfunc = PCI_DEVFN(func->device, @@ -728,13 +718,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) ibmphp_add_resource (bus_pfmem[count]); func->pfmem[count] = bus_pfmem[count]; } else { - mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); + mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (mem_tmp, 0, sizeof (struct resource_node)); mem_tmp->type = MEM; mem_tmp->busno = bus_pfmem[count]->busno; mem_tmp->devfunc = bus_pfmem[count]->devfunc; @@ -770,13 +759,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) debug ("len[count] in Memory is %x\n", len[count]); - bus_mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + bus_mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_mem[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus_mem[count], 0, sizeof (struct resource_node)); bus_mem[count]->type = MEM; bus_mem[count]->busno = func->busno; bus_mem[count]->devfunc = PCI_DEVFN(func->device, @@ -841,14 +829,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) flag_io = TRUE; } else { debug ("it wants %x IO behind the bridge\n", amount_needed->io); - io = kmalloc(sizeof(*io), GFP_KERNEL); + io = kzalloc(sizeof(*io), GFP_KERNEL); if (!io) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (io, 0, sizeof (struct resource_node)); io->type = IO; io->busno = func->busno; io->devfunc = PCI_DEVFN(func->device, func->function); @@ -865,13 +852,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) flag_mem = TRUE; } else { debug ("it wants %x memory behind the bridge\n", amount_needed->mem); - mem = kmalloc(sizeof(*mem), GFP_KERNEL); + mem = kzalloc(sizeof(*mem), GFP_KERNEL); if (!mem) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (mem, 0, sizeof (struct resource_node)); mem->type = MEM; mem->busno = func->busno; mem->devfunc = PCI_DEVFN(func->device, func->function); @@ -888,13 +874,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) flag_pfmem = TRUE; } else { debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem); - pfmem = kmalloc(sizeof(*pfmem), GFP_KERNEL); + pfmem = kzalloc(sizeof(*pfmem), GFP_KERNEL); if (!pfmem) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (pfmem, 0, sizeof (struct resource_node)); pfmem->type = PFMEM; pfmem->busno = func->busno; pfmem->devfunc = PCI_DEVFN(func->device, func->function); @@ -904,13 +889,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) ibmphp_add_resource (pfmem); flag_pfmem = TRUE; } else { - mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); + mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (mem_tmp, 0, sizeof (struct resource_node)); mem_tmp->type = MEM; mem_tmp->busno = pfmem->busno; mem_tmp->devfunc = pfmem->devfunc; @@ -936,13 +920,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) */ bus = ibmphp_find_res_bus (sec_number); if (!bus) { - bus = kmalloc(sizeof(*bus), GFP_KERNEL); + bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (!bus) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus, 0, sizeof (struct bus_node)); bus->busno = sec_number; debug ("b4 adding new bus\n"); rc = add_new_bus (bus, io, mem, pfmem, func->busno); @@ -1111,10 +1094,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) }; struct res_needed *amount; - amount = kmalloc(sizeof(*amount), GFP_KERNEL); + amount = kzalloc(sizeof(*amount), GFP_KERNEL); if (amount == NULL) return NULL; - memset (amount, 0, sizeof (struct res_needed)); ibmphp_pci_bus->number = busno; @@ -1672,12 +1654,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r list_add (&bus->bus_list, &cur_bus->bus_list); } if (io) { - io_range = kmalloc(sizeof(*io_range), GFP_KERNEL); + io_range = kzalloc(sizeof(*io_range), GFP_KERNEL); if (!io_range) { err ("out of system memory\n"); return -ENOMEM; } - memset (io_range, 0, sizeof (struct range_node)); io_range->start = io->start; io_range->end = io->end; io_range->rangeno = 1; @@ -1685,12 +1666,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r bus->rangeIO = io_range; } if (mem) { - mem_range = kmalloc(sizeof(*mem_range), GFP_KERNEL); + mem_range = kzalloc(sizeof(*mem_range), GFP_KERNEL); if (!mem_range) { err ("out of system memory\n"); return -ENOMEM; } - memset (mem_range, 0, sizeof (struct range_node)); mem_range->start = mem->start; mem_range->end = mem->end; mem_range->rangeno = 1; @@ -1698,12 +1678,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r bus->rangeMem = mem_range; } if (pfmem) { - pfmem_range = kmalloc(sizeof(*pfmem_range), GFP_KERNEL); + pfmem_range = kzalloc(sizeof(*pfmem_range), GFP_KERNEL); if (!pfmem_range) { err ("out of system memory\n"); return -ENOMEM; } - memset (pfmem_range, 0, sizeof (struct range_node)); pfmem_range->start = pfmem->start; pfmem_range->end = pfmem->end; pfmem_range->rangeno = 1; diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c index 9c224c94d698..852a98bf07d3 100644 --- a/drivers/pci/hotplug/ibmphp_res.c +++ b/drivers/pci/hotplug/ibmphp_res.c @@ -55,13 +55,12 @@ static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8 return NULL; } - newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); + newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL); if (!newbus) { err ("out of system memory\n"); return NULL; } - memset (newbus, 0, sizeof (struct bus_node)); if (flag) newbus->busno = busno; else @@ -79,12 +78,11 @@ static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * cur return NULL; } - rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + rs = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!rs) { err ("out of system memory\n"); return NULL; } - memset (rs, 0, sizeof (struct resource_node)); rs->busno = curr->bus_num; rs->devfunc = curr->dev_fun; rs->start = curr->start_addr; @@ -100,12 +98,11 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node u8 num_ranges = 0; if (first_bus) { - newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); + newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL); if (!newbus) { err ("out of system memory.\n"); return -ENOMEM; } - memset (newbus, 0, sizeof (struct bus_node)); newbus->busno = curr->bus_num; } else { newbus = *new_bus; @@ -122,14 +119,13 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node } } - newrange = kmalloc (sizeof (struct range_node), GFP_KERNEL); + newrange = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!newrange) { if (first_bus) kfree (newbus); err ("out of system memory\n"); return -ENOMEM; } - memset (newrange, 0, sizeof (struct range_node)); newrange->start = curr->start_addr; newrange->end = curr->end_addr; @@ -1705,12 +1701,11 @@ static int __init once_over (void) bus_cur->firstPFMemFromMem = pfmem_cur; - mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!mem) { err ("out of system memory\n"); return -ENOMEM; } - memset (mem, 0, sizeof (struct resource_node)); mem->type = MEM; mem->busno = pfmem_cur->busno; mem->devfunc = pfmem_cur->devfunc; @@ -1994,12 +1989,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) end_address |= (upper_io_end << 16); if ((start_address) && (start_address <= end_address)) { - range = kmalloc (sizeof (struct range_node), GFP_KERNEL); + range = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!range) { err ("out of system memory\n"); return -ENOMEM; } - memset (range, 0, sizeof (struct range_node)); range->start = start_address; range->end = end_address + 0xfff; @@ -2020,13 +2014,12 @@ static int __init update_bridge_ranges (struct bus_node **bus) fix_resources (bus_sec); if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) { - io = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + io = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!io) { kfree (range); err ("out of system memory\n"); return -ENOMEM; } - memset (io, 0, sizeof (struct resource_node)); io->type = IO; io->busno = bus_cur->busno; io->devfunc = ((device << 3) | (function & 0x7)); @@ -2045,12 +2038,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) if ((start_address) && (start_address <= end_address)) { - range = kmalloc (sizeof (struct range_node), GFP_KERNEL); + range = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!range) { err ("out of system memory\n"); return -ENOMEM; } - memset (range, 0, sizeof (struct range_node)); range->start = start_address; range->end = end_address + 0xfffff; @@ -2072,13 +2064,12 @@ static int __init update_bridge_ranges (struct bus_node **bus) fix_resources (bus_sec); if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) { - mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!mem) { kfree (range); err ("out of system memory\n"); return -ENOMEM; } - memset (mem, 0, sizeof (struct resource_node)); mem->type = MEM; mem->busno = bus_cur->busno; mem->devfunc = ((device << 3) | (function & 0x7)); @@ -2101,12 +2092,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) if ((start_address) && (start_address <= end_address)) { - range = kmalloc (sizeof (struct range_node), GFP_KERNEL); + range = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!range) { err ("out of system memory\n"); return -ENOMEM; } - memset (range, 0, sizeof (struct range_node)); range->start = start_address; range->end = end_address + 0xfffff; @@ -2127,13 +2117,12 @@ static int __init update_bridge_ranges (struct bus_node **bus) fix_resources (bus_sec); if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) { - pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + pfmem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!pfmem) { kfree (range); err ("out of system memory\n"); return -ENOMEM; } - memset (pfmem, 0, sizeof (struct resource_node)); pfmem->type = PFMEM; pfmem->busno = bus_cur->busno; pfmem->devfunc = ((device << 3) | (function & 0x7)); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 1e8506e0fd87..601cf9045b20 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -117,27 +117,23 @@ static int init_slots(struct controller *ctrl) slot_number = ctrl->first_slot; while (number_of_slots) { - slot = kmalloc(sizeof(*slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(struct slot)); slot->hotplug_slot = - kmalloc(sizeof(*(slot->hotplug_slot)), + kzalloc(sizeof(*(slot->hotplug_slot)), GFP_KERNEL); if (!slot->hotplug_slot) goto error_slot; hotplug_slot = slot->hotplug_slot; - memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); hotplug_slot->info = - kmalloc(sizeof(*(hotplug_slot->info)), + kzalloc(sizeof(*(hotplug_slot->info)), GFP_KERNEL); if (!hotplug_slot->info) goto error_hpslot; hotplug_slot_info = hotplug_slot->info; - memset(hotplug_slot_info, 0, - sizeof(struct hotplug_slot_info)); hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); if (!hotplug_slot->name) goto error_info; @@ -373,12 +369,11 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ u8 value; struct pci_dev *pdev; - ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL); + ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); goto err_out_none; } - memset(ctrl, 0, sizeof(struct controller)); pdev = dev->port; ctrl->pci_dev = pdev; diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 78943e064b59..b771196a654e 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -84,19 +84,16 @@ struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_ { struct slot *slot; - slot = kmalloc(sizeof (struct slot), GFP_KERNEL); + slot = kzalloc(sizeof(struct slot), GFP_KERNEL); if (!slot) goto error_nomem; - memset(slot, 0, sizeof (struct slot)); - slot->hotplug_slot = kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL); + slot->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); if (!slot->hotplug_slot) goto error_slot; - memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); - slot->hotplug_slot->info = kmalloc(sizeof (struct hotplug_slot_info), + slot->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!slot->hotplug_slot->info) goto error_hpslot; - memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL); if (!slot->hotplug_slot->name) goto error_info; diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index eb5b50c8770c..f22f69ac6445 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -53,11 +53,10 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) if (fields < 0) return -EINVAL; - dynid = kmalloc(sizeof(*dynid), GFP_KERNEL); + dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); if (!dynid) return -ENOMEM; - memset(dynid, 0, sizeof(*dynid)); INIT_LIST_HEAD(&dynid->node); dynid->id.vendor = vendor; dynid->id.device = device; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 965a5934623a..56ac2bc003c7 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -501,9 +501,8 @@ int pci_create_sysfs_dev_files (struct pci_dev *pdev) if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { struct bin_attribute *rom_attr; - rom_attr = kmalloc(sizeof(*rom_attr), GFP_ATOMIC); + rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); if (rom_attr) { - memset(rom_attr, 0x00, sizeof(*rom_attr)); pdev->rom_attr = rom_attr; rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); rom_attr->attr.name = "rom"; diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index e4e5f1e8d816..55c662267868 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -248,11 +248,10 @@ static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, { struct pcie_device *device; - device = kmalloc(sizeof(struct pcie_device), GFP_KERNEL); + device = kzalloc(sizeof(struct pcie_device), GFP_KERNEL); if (!device) return NULL; - memset(device, 0, sizeof(struct pcie_device)); pcie_device_init(parent, device, port_type, service_type, irq,irq_mode); printk(KERN_DEBUG "Allocate Port Service[%s]\n", device->device.bus_id); return device; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e3dc3063e05b..a10ed9dab2c2 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -33,10 +33,9 @@ LIST_HEAD(pci_devices); */ static void pci_create_legacy_files(struct pci_bus *b) { - b->legacy_io = kmalloc(sizeof(struct bin_attribute) * 2, + b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2, GFP_ATOMIC); if (b->legacy_io) { - memset(b->legacy_io, 0, sizeof(struct bin_attribute) * 2); b->legacy_io->attr.name = "legacy_io"; b->legacy_io->size = 0xffff; b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; @@ -320,9 +319,8 @@ static struct pci_bus * __devinit pci_alloc_bus(void) { struct pci_bus *b; - b = kmalloc(sizeof(*b), GFP_KERNEL); + b = kzalloc(sizeof(*b), GFP_KERNEL); if (b) { - memset(b, 0, sizeof(*b)); INIT_LIST_HEAD(&b->node); INIT_LIST_HEAD(&b->children); INIT_LIST_HEAD(&b->devices); @@ -797,11 +795,10 @@ pci_scan_device(struct pci_bus *bus, int devfn) if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type)) return NULL; - dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return NULL; - memset(dev, 0, sizeof(struct pci_dev)); dev->bus = bus; dev->sysdata = bus->sysdata; dev->dev.parent = bus->bridge; -- cgit v1.2.3-59-g8ed1b From 783c49fc506d9afe4784390b556fa25ede5d6d1f Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Fri, 3 Mar 2006 10:16:05 -0800 Subject: [PATCH] PCI Hotplug: add common acpi functions to core shpchprm_acpi.c and pciehprm_acpi.c are nearly identical. In addition, there are functions in both these files that are also in acpiphp_glue.c. This patch will remove duplicate functions from shpchp, pciehp, and acpiphp and move this functionality to pci_hotplug, as it is not hardware specific. Get rid of shpchprm* and pciehprm* files since they are no longer needed. shpchprm_nonacpi.c and pciehprm_nonacpi.c are identical, as well as shpchprm_legacy.c and can be replaced with a macro. This patch also changes acpiphp to use the common hpp code. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/Makefile | 17 +-- drivers/pci/hotplug/acpi_pcihp.c | 227 +++++++++++++++++++++++++++++ drivers/pci/hotplug/acpiphp.h | 15 +- drivers/pci/hotplug/acpiphp_glue.c | 91 ++---------- drivers/pci/hotplug/pci_hotplug.h | 17 +++ drivers/pci/hotplug/pciehp.h | 24 +-- drivers/pci/hotplug/pciehp_hpc.c | 74 +++++++++- drivers/pci/hotplug/pciehprm_acpi.c | 257 --------------------------------- drivers/pci/hotplug/pciehprm_nonacpi.c | 47 ------ drivers/pci/hotplug/shpchp.h | 30 ++-- drivers/pci/hotplug/shpchp_core.c | 17 +++ drivers/pci/hotplug/shpchp_pci.c | 10 +- drivers/pci/hotplug/shpchprm_acpi.c | 186 ------------------------ drivers/pci/hotplug/shpchprm_legacy.c | 54 ------- drivers/pci/hotplug/shpchprm_nonacpi.c | 57 -------- 15 files changed, 393 insertions(+), 730 deletions(-) create mode 100644 drivers/pci/hotplug/acpi_pcihp.c delete mode 100644 drivers/pci/hotplug/pciehprm_acpi.c delete mode 100644 drivers/pci/hotplug/pciehprm_nonacpi.c delete mode 100644 drivers/pci/hotplug/shpchprm_acpi.c delete mode 100644 drivers/pci/hotplug/shpchprm_legacy.c delete mode 100644 drivers/pci/hotplug/shpchprm_nonacpi.c (limited to 'drivers') diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 1c0ed377ed91..421cfffb1756 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -22,6 +22,9 @@ ifdef CONFIG_HOTPLUG_PCI_CPCI pci_hotplug-objs += cpci_hotplug_core.o \ cpci_hotplug_pci.o endif +ifdef CONFIG_ACPI +pci_hotplug-objs += acpi_pcihp.o +endif cpqphp-objs := cpqphp_core.o \ cpqphp_ctrl.o \ @@ -51,23 +54,9 @@ pciehp-objs := pciehp_core.o \ pciehp_ctrl.o \ pciehp_pci.o \ pciehp_hpc.o -ifdef CONFIG_ACPI - pciehp-objs += pciehprm_acpi.o -else - pciehp-objs += pciehprm_nonacpi.o -endif shpchp-objs := shpchp_core.o \ shpchp_ctrl.o \ shpchp_pci.o \ shpchp_sysfs.o \ shpchp_hpc.o -ifdef CONFIG_ACPI - shpchp-objs += shpchprm_acpi.o -else - ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY - shpchp-objs += shpchprm_legacy.o - else - shpchp-objs += shpchprm_nonacpi.o - endif -endif diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c new file mode 100644 index 000000000000..0f7135317542 --- /dev/null +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -0,0 +1,227 @@ +/* + * Common ACPI functions for hot plug platforms + * + * Copyright (C) 2006 Intel Corporation + * + * 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; 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Send feedback to + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "pci_hotplug.h" + +#define METHOD_NAME__SUN "_SUN" +#define METHOD_NAME__HPP "_HPP" +#define METHOD_NAME_OSHP "OSHP" + +/* acpi_path_name + * + * @handle - the acpi_handle of the object who's name you want. + * + * Caller must free buffer. + */ +u8 * acpi_path_name(acpi_handle handle) +{ + acpi_status status; + struct acpi_buffer ret_buf = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *obj; + + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); + if (ACPI_FAILURE(status)) { + return NULL; + } + obj = ret_buf.pointer; + return obj->string.pointer; +} +EXPORT_SYMBOL_GPL(acpi_path_name); + + + +static acpi_status +acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) +{ + acpi_status status; + u8 nui[4]; + struct acpi_buffer ret_buf = { 0, NULL}; + union acpi_object *ext_obj, *package; + u8 *path_name = acpi_path_name(handle); + int i, len = 0; + + /* get _hpp */ + status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); + switch (status) { + case AE_BUFFER_OVERFLOW: + ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); + if (!ret_buf.pointer) { + printk(KERN_ERR "%s:%s alloc for _HPP fail\n", + __FUNCTION__, path_name); + acpi_os_free(path_name); + return AE_NO_MEMORY; + } + status = acpi_evaluate_object(handle, METHOD_NAME__HPP, + NULL, &ret_buf); + if (ACPI_SUCCESS(status)) + break; + default: + if (ACPI_FAILURE(status)) { + pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__, + path_name, status); + acpi_os_free(path_name); + return status; + } + } + + ext_obj = (union acpi_object *) ret_buf.pointer; + if (ext_obj->type != ACPI_TYPE_PACKAGE) { + printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__, + path_name); + status = AE_ERROR; + goto free_and_return; + } + + len = ext_obj->package.count; + package = (union acpi_object *) ret_buf.pointer; + for ( i = 0; (i < len) || (i < 4); i++) { + ext_obj = (union acpi_object *) &package->package.elements[i]; + switch (ext_obj->type) { + case ACPI_TYPE_INTEGER: + nui[i] = (u8)ext_obj->integer.value; + break; + default: + printk(KERN_ERR "%s:%s _HPP obj type incorrect\n", + __FUNCTION__, path_name); + status = AE_ERROR; + goto free_and_return; + } + } + + hpp->cache_line_size = nui[0]; + hpp->latency_timer = nui[1]; + hpp->enable_serr = nui[2]; + hpp->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); + +free_and_return: + acpi_os_free(path_name); + kfree(ret_buf.pointer); + return status; +} + + + +/* acpi_run_oshp - get control of hotplug from the firmware + * + * @handle - the handle of the hotplug controller. + */ +acpi_status acpi_run_oshp(acpi_handle handle) +{ + acpi_status status; + u8 *path_name = acpi_path_name(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__, + path_name, status); + else + pr_debug("%s:%s OSHP passes\n", __FUNCTION__, path_name); + acpi_os_free(path_name); + return status; +} +EXPORT_SYMBOL_GPL(acpi_run_oshp); + + + +/* acpi_get_hp_params_from_firmware + * + * @dev - the pci_dev of the newly added device + * @hpp - allocated by the caller + */ +acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp) +{ + acpi_status status = AE_NOT_FOUND; + struct pci_dev *pdev = dev; + + /* + * _HPP settings apply to all child buses, until another _HPP is + * encountered. If we don't find an _HPP for the input pci 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; + status = acpi_run_hpp(handle, hpp); + if (!(pdev->bus->parent)) + break; + /* Check if a parent object supports _HPP */ + pdev = pdev->bus->parent->self; + } + return status; +} +EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); + + +/* acpi_root_bridge - check to see if this acpi object is a root bridge + * + * @handle - the acpi object in question. + */ +int acpi_root_bridge(acpi_handle handle) +{ + acpi_status status; + struct acpi_device_info *info; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + int i; + + status = acpi_get_object_info(handle, &buffer); + if (ACPI_SUCCESS(status)) { + info = buffer.pointer; + if ((info->valid & ACPI_VALID_HID) && + !strcmp(PCI_ROOT_HID_STRING, + info->hardware_id.value)) { + acpi_os_free(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); + return 1; + } + } + } + acpi_os_free(buffer.pointer); + } + return 0; +} +EXPORT_SYMBOL_GPL(acpi_root_bridge); diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index de9df80ffb50..467ac70a46ff 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -64,19 +64,6 @@ struct slot { struct acpiphp_slot *acpi_slot; }; -/** - * struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters - * @cache_line_size in DWORD - * @latency_timer in PCI clock - * @enable_SERR 0 or 1 - * @enable_PERR 0 or 1 - */ -struct hpp_param { - u8 cache_line_size; - u8 latency_timer; - u8 enable_SERR; - u8 enable_PERR; -}; /** @@ -100,7 +87,7 @@ struct acpiphp_bridge { struct pci_dev *pci_dev; /* ACPI 2.0 _HPP parameters */ - struct hpp_param hpp; + struct hotplug_params hpp; spinlock_t res_lock; }; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index c7e6387983df..053ee843863c 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -285,57 +285,19 @@ static int detect_ejectable_slots(acpi_handle *bridge_handle) static void decode_hpp(struct acpiphp_bridge *bridge) { acpi_status status; - struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER, - .pointer = NULL}; - union acpi_object *package; - int i; - - /* default numbers */ - bridge->hpp.cache_line_size = 0x10; - bridge->hpp.latency_timer = 0x40; - bridge->hpp.enable_SERR = 0; - bridge->hpp.enable_PERR = 0; - - status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer); + status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp); if (ACPI_FAILURE(status)) { - dbg("_HPP evaluation failed\n"); - return; - } - - package = (union acpi_object *) buffer.pointer; - - if (!package || package->type != ACPI_TYPE_PACKAGE || - package->package.count != 4 || !package->package.elements) { - err("invalid _HPP object; ignoring\n"); - goto err_exit; + /* use default numbers */ + bridge->hpp.cache_line_size = 0x10; + bridge->hpp.latency_timer = 0x40; + bridge->hpp.enable_serr = 0; + bridge->hpp.enable_perr = 0; } - - for (i = 0; i < 4; i++) { - if (package->package.elements[i].type != ACPI_TYPE_INTEGER) { - err("invalid _HPP parameter type; ignoring\n"); - goto err_exit; - } - } - - bridge->hpp.cache_line_size = package->package.elements[0].integer.value; - bridge->hpp.latency_timer = package->package.elements[1].integer.value; - bridge->hpp.enable_SERR = package->package.elements[2].integer.value; - bridge->hpp.enable_PERR = package->package.elements[3].integer.value; - - dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n", - bridge->hpp.cache_line_size, - bridge->hpp.latency_timer, - bridge->hpp.enable_SERR, - bridge->hpp.enable_PERR); - - bridge->flags |= BRIDGE_HAS_HPP; - - err_exit: - kfree(buffer.pointer); } + /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ static void init_bridge_misc(struct acpiphp_bridge *bridge) { @@ -1154,11 +1116,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) pci_write_config_byte(dev, PCI_LATENCY_TIMER, bridge->hpp.latency_timer); pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); - if (bridge->hpp.enable_SERR) + if (bridge->hpp.enable_serr) pci_cmd |= PCI_COMMAND_SERR; else pci_cmd &= ~PCI_COMMAND_SERR; - if (bridge->hpp.enable_PERR) + if (bridge->hpp.enable_perr) pci_cmd |= PCI_COMMAND_PARITY; else pci_cmd &= ~PCI_COMMAND_PARITY; @@ -1169,11 +1131,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, bridge->hpp.latency_timer); pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); - if (bridge->hpp.enable_SERR) + if (bridge->hpp.enable_serr) pci_bctl |= PCI_BRIDGE_CTL_SERR; else pci_bctl &= ~PCI_BRIDGE_CTL_SERR; - if (bridge->hpp.enable_PERR) + if (bridge->hpp.enable_perr) pci_bctl |= PCI_BRIDGE_CTL_PARITY; else pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; @@ -1193,6 +1155,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus) memset(&bridge, 0, sizeof(bridge)); bridge.handle = handle; + bridge.pci_dev = bus->self; decode_hpp(&bridge); list_for_each_entry(dev, &bus->devices, bus_list) program_hpp(dev, &bridge); @@ -1409,41 +1372,13 @@ void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) } } -static int is_root_bridge(acpi_handle handle) -{ - acpi_status status; - struct acpi_device_info *info; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - int i; - - status = acpi_get_object_info(handle, &buffer); - if (ACPI_SUCCESS(status)) { - info = buffer.pointer; - if ((info->valid & ACPI_VALID_HID) && - !strcmp(PCI_ROOT_HID_STRING, - info->hardware_id.value)) { - acpi_os_free(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); - return 1; - } - } - } - } - return 0; -} static acpi_status find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) { int *count = (int *)context; - if (is_root_bridge(handle)) { + if (acpi_root_bridge(handle)) { acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_bridge, NULL); (*count)++; diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index 88d44f7fef29..e476ed033384 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h @@ -176,5 +176,22 @@ extern int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info *info); extern struct subsystem pci_hotplug_slots_subsys; +struct hotplug_params { + u8 cache_line_size; + u8 latency_timer; + u8 enable_serr; + u8 enable_perr; +}; + +#ifdef CONFIG_ACPI +#include +#include +#include +extern acpi_status acpi_run_oshp(acpi_handle handle); +extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp); +extern u8 * acpi_path_name(acpi_handle handle); +int acpi_root_bridge(acpi_handle handle); +#endif #endif diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e0adf4bc89e8..92c1f0f1e1ad 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -50,12 +50,6 @@ extern int pciehp_force; #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) -struct hotplug_params { - u8 cache_line_size; - u8 latency_timer; - u8 enable_serr; - u8 enable_perr; -}; struct slot { struct slot *next; @@ -192,9 +186,6 @@ extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); /* pci functions */ extern int pciehp_configure_device (struct slot *p_slot); extern int pciehp_unconfigure_device (struct slot *p_slot); -extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev); -extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp); @@ -286,4 +277,19 @@ struct hpc_ops { int (*check_lnk_status) (struct controller *ctrl); }; + +#ifdef CONFIG_ACPI +#define pciehp_get_hp_hw_control_from_firmware(dev) \ + pciehp_acpi_get_hp_hw_control_from_firmware(dev) +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))) + return -ENODEV; + return 0; +} +#else +#define pciehp_get_hp_hw_control_from_firmware(dev) 0 +#define pciehp_get_hp_params_from_firmware(dev, hpp) (-ENODEV) +#endif /* CONFIG_ACPI */ #endif /* _PCIEHP_H */ diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 2427b0862cbf..22dcd12e4c1c 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -38,7 +38,10 @@ #include "../pci.h" #include "pciehp.h" - +#include +#include +#include +#include #ifdef DEBUG #define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ #define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ @@ -1236,6 +1239,75 @@ static struct hpc_ops pciehp_hpc_ops = { .check_lnk_status = hpc_check_lnk_status, }; +#ifdef CONFIG_ACPI +int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) +{ + acpi_status status; + acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); + struct pci_dev *pdev = dev; + struct pci_bus *parent; + u8 *path_name = NULL; + + /* + * Per PCI firmware specification, we should run the ACPI _OSC + * method to get control of hotplug hardware before using it. + * If an _OSC is missing, we look for an OSHP to do the same thing. + * To handle different BIOS behavior, we look for _OSC and OSHP + * within the scope of the hotplug controller and its parents, upto + * the host bridge under which this controller exists. + */ + while (!handle) { + /* + * This hotplug controller was not listed in the ACPI name + * space at all. Try to get acpi handle of parent pci bus. + */ + if (!pdev || !pdev->bus->parent) + break; + parent = pdev->bus->parent; + dbg("Could not find %s in acpi namespace, trying parent\n", + pci_name(pdev)); + if (!parent->self) + /* Parent must be a host bridge */ + handle = acpi_get_pci_rootbridge_handle( + pci_domain_nr(parent), + parent->number); + else + handle = DEVICE_ACPI_HANDLE( + &(parent->self->dev)); + pdev = parent->self; + } + + while (handle) { + path_name = acpi_path_name(handle); + dbg("Trying to get hotplug control for %s \n", path_name); + status = pci_osc_control_set(handle, + OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); + if (status == AE_NOT_FOUND) + status = acpi_run_oshp(handle); + if (ACPI_SUCCESS(status)) { + dbg("Gained control for hotplug HW for pci %s (%s)\n", + pci_name(dev), path_name); + acpi_os_free(path_name); + return 0; + } + if (acpi_root_bridge(handle)) + break; + chandle = handle; + status = acpi_get_parent(chandle, &handle); + if (ACPI_FAILURE(status)) + break; + } + + err("Cannot get control of hotplug hardware for pci %s\n", + pci_name(dev)); + if (path_name) + acpi_os_free(path_name); + return -1; +} +#endif + + + int pcie_init(struct controller * ctrl, struct pcie_device *dev) { struct php_ctlr_state_s *php_ctlr, *p; diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c deleted file mode 100644 index 2bdb30f68bf8..000000000000 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * PCIEHPRM ACPI: PHP Resource Manager for ACPI platform - * - * Copyright (C) 2003-2004 Intel Corporation - * - * 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; 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, GOOD TITLE or - * NON INFRINGEMENT. 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. - * - * Send feedback to - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "pciehp.h" - -#define METHOD_NAME__SUN "_SUN" -#define METHOD_NAME__HPP "_HPP" -#define METHOD_NAME_OSHP "OSHP" - -static u8 * acpi_path_name( acpi_handle handle) -{ - acpi_status status; - static u8 path_name[ACPI_PATHNAME_MAX]; - struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name }; - - memset(path_name, 0, sizeof (path_name)); - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); - - if (ACPI_FAILURE(status)) - return NULL; - else - return path_name; -} - -static acpi_status -acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) -{ - acpi_status status; - u8 nui[4]; - struct acpi_buffer ret_buf = { 0, NULL}; - union acpi_object *ext_obj, *package; - u8 *path_name = acpi_path_name(handle); - int i, len = 0; - - /* get _hpp */ - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); - switch (status) { - case AE_BUFFER_OVERFLOW: - ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); - if (!ret_buf.pointer) { - err ("%s:%s alloc for _HPP fail\n", __FUNCTION__, - path_name); - return AE_NO_MEMORY; - } - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, - NULL, &ret_buf); - if (ACPI_SUCCESS(status)) - break; - default: - if (ACPI_FAILURE(status)) { - dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__, - path_name, status); - return status; - } - } - - ext_obj = (union acpi_object *) ret_buf.pointer; - if (ext_obj->type != ACPI_TYPE_PACKAGE) { - err ("%s:%s _HPP obj not a package\n", __FUNCTION__, - path_name); - status = AE_ERROR; - goto free_and_return; - } - - len = ext_obj->package.count; - package = (union acpi_object *) ret_buf.pointer; - for ( i = 0; (i < len) || (i < 4); i++) { - ext_obj = (union acpi_object *) &package->package.elements[i]; - switch (ext_obj->type) { - case ACPI_TYPE_INTEGER: - nui[i] = (u8)ext_obj->integer.value; - break; - default: - err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__, - path_name); - status = AE_ERROR; - goto free_and_return; - } - } - - hpp->cache_line_size = nui[0]; - hpp->latency_timer = nui[1]; - hpp->enable_serr = nui[2]; - hpp->enable_perr = nui[3]; - - dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); - dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer); - dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); - dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); - -free_and_return: - kfree(ret_buf.pointer); - return status; -} - -static acpi_status acpi_run_oshp(acpi_handle handle) -{ - acpi_status status; - u8 *path_name = acpi_path_name(handle); - - /* run OSHP */ - status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); - if (ACPI_FAILURE(status)) { - dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, - status); - } else { - dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); - } - return status; -} - -static int is_root_bridge(acpi_handle handle) -{ - acpi_status status; - struct acpi_device_info *info; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - int i; - - status = acpi_get_object_info(handle, &buffer); - if (ACPI_SUCCESS(status)) { - info = buffer.pointer; - if ((info->valid & ACPI_VALID_HID) && - !strcmp(PCI_ROOT_HID_STRING, - info->hardware_id.value)) { - acpi_os_free(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); - return 1; - } - } - } - } - return 0; -} - -int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - acpi_status status; - acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); - struct pci_dev *pdev = dev; - struct pci_bus *parent; - u8 *path_name; - - /* - * Per PCI firmware specification, we should run the ACPI _OSC - * method to get control of hotplug hardware before using it. - * If an _OSC is missing, we look for an OSHP to do the same thing. - * To handle different BIOS behavior, we look for _OSC and OSHP - * within the scope of the hotplug controller and its parents, upto - * the host bridge under which this controller exists. - */ - while (!handle) { - /* - * This hotplug controller was not listed in the ACPI name - * space at all. Try to get acpi handle of parent pci bus. - */ - if (!pdev || !pdev->bus->parent) - break; - parent = pdev->bus->parent; - dbg("Could not find %s in acpi namespace, trying parent\n", - pci_name(pdev)); - if (!parent->self) - /* Parent must be a host bridge */ - handle = acpi_get_pci_rootbridge_handle( - pci_domain_nr(parent), - parent->number); - else - handle = DEVICE_ACPI_HANDLE( - &(parent->self->dev)); - pdev = parent->self; - } - - while (handle) { - path_name = acpi_path_name(handle); - dbg("Trying to get hotplug control for %s \n", path_name); - status = pci_osc_control_set(handle, - OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); - if (status == AE_NOT_FOUND) - status = acpi_run_oshp(handle); - if (ACPI_SUCCESS(status)) { - dbg("Gained control for hotplug HW for pci %s (%s)\n", - pci_name(dev), path_name); - return 0; - } - if (is_root_bridge(handle)) - break; - chandle = handle; - status = acpi_get_parent(chandle, &handle); - if (ACPI_FAILURE(status)) - break; - } - - err("Cannot get control of hotplug hardware for pci %s\n", - pci_name(dev)); - return -1; -} - -void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - acpi_status status = AE_NOT_FOUND; - struct pci_dev *pdev = dev; - - /* - * _HPP settings apply to all child buses, until another _HPP is - * encountered. If we don't find an _HPP for the input pci 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; - status = acpi_run_hpp(handle, hpp); - if (!(pdev->bus->parent)) - break; - /* Check if a parent object supports _HPP */ - pdev = pdev->bus->parent->self; - } -} - diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c deleted file mode 100644 index 29180dfe8493..000000000000 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * Copyright (C) 2003-2004 Intel Corporation - * - * 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; 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, GOOD TITLE or - * NON INFRINGEMENT. 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. - * - * Send feedback to , - * - */ - -#include -#include -#include -#include -#include -#include -#include "pciehp.h" - -void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - return; -} - -int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - return 0; -} diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index f10f1ba877af..5c70f43908c4 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -106,12 +106,6 @@ struct controller { volatile int cmd_busy; }; -struct hotplug_params { - u8 cache_line_size; - u8 latency_timer; - u8 enable_serr; - u8 enable_perr; -}; /* Define AMD SHPC ID */ #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 @@ -193,15 +187,29 @@ extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id); extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); extern int shpchp_configure_device(struct slot *p_slot); extern int shpchp_unconfigure_device(struct slot *p_slot); -extern void get_hp_hw_control_from_firmware(struct pci_dev *dev); -extern void get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp); -extern int shpchprm_get_physical_slot_number(struct controller *ctrl, - u32 *sun, u8 busnum, u8 devnum); extern void shpchp_remove_ctrl_files(struct controller *ctrl); extern void cleanup_slots(struct controller *ctrl); extern void queue_pushbutton_work(void *data); + +#ifdef CONFIG_ACPI +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))) + return -ENODEV; + return 0; +} +#define get_hp_hw_control_from_firmware(pdev) \ + do { \ + if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \ + acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \ + } while (0) +#else +#define get_hp_params_from_firmware(dev, hpp) (-ENODEV) +#define get_hp_hw_control_from_firmware(dev) do { } while (0) +#endif + struct ctrl_reg { volatile u32 base_offset; volatile u32 slot_avail1; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 0e83c5fbc9df..3be4d492ccc2 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -104,6 +104,23 @@ static void make_slot_name(struct slot *slot) slot->bus, slot->number); } + + + +static int +shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, + u8 busnum, u8 devnum) +{ + int offset = devnum - ctrl->slot_device_offset; + + dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, + ctrl->slot_num_inc, offset); + *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset); + return 0; +} + + + static int init_slots(struct controller *ctrl) { struct slot *slot; diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 19e1a5e1e30b..257adc233996 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -38,7 +38,7 @@ static void program_fw_provided_values(struct pci_dev *dev) { u16 pci_cmd, pci_bctl; struct pci_dev *cdev; - struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */ + struct hotplug_params hpp; /* Program hpp values for this device */ if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || @@ -46,7 +46,13 @@ static void program_fw_provided_values(struct pci_dev *dev) (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) return; - get_hp_params_from_firmware(dev, &hpp); + /* 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; + } pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size); pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer); diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c deleted file mode 100644 index 17145e52223a..000000000000 --- a/drivers/pci/hotplug/shpchprm_acpi.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * SHPCHPRM ACPI: PHP Resource Manager for ACPI platform - * - * Copyright (C) 2003-2004 Intel Corporation - * - * 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; 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, GOOD TITLE or - * NON INFRINGEMENT. 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. - * - * Send feedback to - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "shpchp.h" - -#define METHOD_NAME__SUN "_SUN" -#define METHOD_NAME__HPP "_HPP" -#define METHOD_NAME_OSHP "OSHP" - -static u8 * acpi_path_name( acpi_handle handle) -{ - acpi_status status; - static u8 path_name[ACPI_PATHNAME_MAX]; - struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name }; - - memset(path_name, 0, sizeof (path_name)); - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); - - if (ACPI_FAILURE(status)) - return NULL; - else - return path_name; -} - -static acpi_status -acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) -{ - acpi_status status; - u8 nui[4]; - struct acpi_buffer ret_buf = { 0, NULL}; - union acpi_object *ext_obj, *package; - u8 *path_name = acpi_path_name(handle); - int i, len = 0; - - /* get _hpp */ - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); - switch (status) { - case AE_BUFFER_OVERFLOW: - ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); - if (!ret_buf.pointer) { - err ("%s:%s alloc for _HPP fail\n", __FUNCTION__, - path_name); - return AE_NO_MEMORY; - } - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, - NULL, &ret_buf); - if (ACPI_SUCCESS(status)) - break; - default: - if (ACPI_FAILURE(status)) { - dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__, - path_name, status); - return status; - } - } - - ext_obj = (union acpi_object *) ret_buf.pointer; - if (ext_obj->type != ACPI_TYPE_PACKAGE) { - err ("%s:%s _HPP obj not a package\n", __FUNCTION__, - path_name); - status = AE_ERROR; - goto free_and_return; - } - - len = ext_obj->package.count; - package = (union acpi_object *) ret_buf.pointer; - for ( i = 0; (i < len) || (i < 4); i++) { - ext_obj = (union acpi_object *) &package->package.elements[i]; - switch (ext_obj->type) { - case ACPI_TYPE_INTEGER: - nui[i] = (u8)ext_obj->integer.value; - break; - default: - err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__, - path_name); - status = AE_ERROR; - goto free_and_return; - } - } - - hpp->cache_line_size = nui[0]; - hpp->latency_timer = nui[1]; - hpp->enable_serr = nui[2]; - hpp->enable_perr = nui[3]; - - dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); - dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer); - dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); - dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); - -free_and_return: - kfree(ret_buf.pointer); - return status; -} - -static void acpi_run_oshp(acpi_handle handle) -{ - acpi_status status; - u8 *path_name = acpi_path_name(handle); - - /* run OSHP */ - status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); - if (ACPI_FAILURE(status)) { - err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, - status); - } else { - dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); - } -} - -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) -{ - int offset = devnum - ctrl->slot_device_offset; - - dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset); - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset); - return 0; -} - -void get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - /* - * OSHP is an optional ACPI firmware control method. If present, - * we need to run it to inform BIOS that we will control SHPC - * hardware from now on. - */ - acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev)); - if (!handle) - return; - acpi_run_oshp(handle); -} - -void get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - acpi_status status = AE_NOT_FOUND; - struct pci_dev *pdev = dev; - - /* - * _HPP settings apply to all child buses, until another _HPP is - * encountered. If we don't find an _HPP for the input pci 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; - status = acpi_run_hpp(handle, hpp); - if (!(pdev->bus->parent)) - break; - /* Check if a parent object supports _HPP */ - pdev = pdev->bus->parent->self; - } -} - diff --git a/drivers/pci/hotplug/shpchprm_legacy.c b/drivers/pci/hotplug/shpchprm_legacy.c deleted file mode 100644 index ed6c1254bf6f..000000000000 --- a/drivers/pci/hotplug/shpchprm_legacy.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * Copyright (C) 2003-2004 Intel Corporation - * - * 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; 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, GOOD TITLE or - * NON INFRINGEMENT. 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. - * - * Send feedback to , - * - */ - -#include -#include -#include -#include -#include "shpchp.h" - -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) -{ - int offset = devnum - ctrl->slot_device_offset; - - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset); - return 0; -} - -void get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - return; -} - -void get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - return; -} - diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.c b/drivers/pci/hotplug/shpchprm_nonacpi.c deleted file mode 100644 index c6b40998eeb3..000000000000 --- a/drivers/pci/hotplug/shpchprm_nonacpi.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * Copyright (C) 2003-2004 Intel Corporation - * - * 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; 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, GOOD TITLE or - * NON INFRINGEMENT. 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. - * - * Send feedback to , - * - */ - -#include -#include -#include -#include -#include -#include - -#include "shpchp.h" - -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) -{ - int offset = devnum - ctrl->slot_device_offset; - - dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset); - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset); - return 0; -} - -void get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - return; -} - -void get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - return; -} -- cgit v1.2.3-59-g8ed1b From dc6712d1261ee4585771724320d28580888818eb Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Tue, 14 Mar 2006 16:24:47 -0800 Subject: [PATCH] ibmphp: remove TRUE and FALSE This patch removes the defines TRUE and FALSE and just uses 0 or 1. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/ibmphp.h | 2 -- drivers/pci/hotplug/ibmphp_core.c | 4 +-- drivers/pci/hotplug/ibmphp_ebda.c | 2 +- drivers/pci/hotplug/ibmphp_hpc.c | 54 ++++++++++++++++++------------------ drivers/pci/hotplug/ibmphp_pci.c | 58 +++++++++++++++++++-------------------- drivers/pci/hotplug/ibmphp_res.c | 48 ++++++++++++++++---------------- 6 files changed, 83 insertions(+), 85 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index c22e0284d7b1..dba6d8ca9bda 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h @@ -406,8 +406,6 @@ extern void ibmphp_hpc_stop_poll_thread (void); //---------------------------------------------------------------------------- // HPC return codes //---------------------------------------------------------------------------- -#define FALSE 0x00 -#define TRUE 0x01 #define HPC_ERROR 0xFF //----------------------------------------------------------------------------- diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 45e2a0d9b596..e13d5b87241a 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -1239,9 +1239,9 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) } flag = slot_cur->flag; - slot_cur->flag = TRUE; + slot_cur->flag = 1; - if (flag == TRUE) { + if (flag == 1) { rc = validate(slot_cur, DISABLE); /* checking if powered off already & valid slot # */ if (rc) diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index ba12034c5d3a..05e4f5a1927a 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c @@ -944,7 +944,7 @@ static int __init ebda_rsrc_controller (void) goto error_no_slot; } - tmp_slot->flag = TRUE; + tmp_slot->flag = 1; tmp_slot->capabilities = hpc_ptr->slots[index].slot_cap; if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX) diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index d680bb472c7b..c3ac98a0a6a6 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c @@ -38,7 +38,7 @@ #include "ibmphp.h" -static int to_debug = FALSE; +static int to_debug = 0; #define debug_polling(fmt, arg...) do { if (to_debug) debug (fmt, arg); } while (0) //---------------------------------------------------------------------------- @@ -95,8 +95,8 @@ static int to_debug = FALSE; //---------------------------------------------------------------------------- // macro utilities //---------------------------------------------------------------------------- -// if bits 20,22,25,26,27,29,30 are OFF return TRUE -#define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? FALSE : TRUE)) +// if bits 20,22,25,26,27,29,30 are OFF return 1 +#define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? 0 : 1)) //---------------------------------------------------------------------------- // global variables @@ -136,8 +136,8 @@ void __init ibmphp_hpc_initvars (void) mutex_init(&sem_hpcaccess); init_MUTEX (&semOperations); init_MUTEX_LOCKED (&sem_exit); - to_debug = FALSE; - ibmphp_shutdown = FALSE; + to_debug = 0; + ibmphp_shutdown = 0; tid_poll = 0; debug ("%s - Exit\n", __FUNCTION__); @@ -739,21 +739,21 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) // check controller is still not working on the command //-------------------------------------------------------------------- timeout = CMD_COMPLETE_TOUT_SEC; - done = FALSE; + done = 0; while (!done) { rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status); if (!rc) { if (NEEDTOCHECK_CMDSTATUS (cmd)) { if (CTLR_FINISHED (status) == HPC_CTLR_FINISHED_YES) - done = TRUE; + done = 1; } else - done = TRUE; + done = 1; } if (!done) { msleep(1000); if (timeout < 1) { - done = TRUE; + done = 1; err ("%s - Error command complete timeout\n", __FUNCTION__); rc = -EFAULT; } else @@ -799,7 +799,7 @@ void free_hpc_access (void) void ibmphp_lock_operations (void) { down (&semOperations); - to_debug = TRUE; + to_debug = 1; } /*---------------------------------------------------------------------- @@ -809,7 +809,7 @@ void ibmphp_unlock_operations (void) { debug ("%s - Entry\n", __FUNCTION__); up (&semOperations); - to_debug = FALSE; + to_debug = 0; debug ("%s - Exit\n", __FUNCTION__); } @@ -937,40 +937,40 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) { u8 status; int rc = 0; - u8 disable = FALSE; - u8 update = FALSE; + u8 disable = 0; + u8 update = 0; debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot); // bit 0 - HPC_SLOT_POWER if ((pslot->status & 0x01) != (poldslot->status & 0x01)) - update = TRUE; + update = 1; // bit 1 - HPC_SLOT_CONNECT // ignore // bit 2 - HPC_SLOT_ATTN if ((pslot->status & 0x04) != (poldslot->status & 0x04)) - update = TRUE; + update = 1; // bit 3 - HPC_SLOT_PRSNT2 // bit 4 - HPC_SLOT_PRSNT1 if (((pslot->status & 0x08) != (poldslot->status & 0x08)) || ((pslot->status & 0x10) != (poldslot->status & 0x10))) - update = TRUE; + update = 1; // bit 5 - HPC_SLOT_PWRGD if ((pslot->status & 0x20) != (poldslot->status & 0x20)) // OFF -> ON: ignore, ON -> OFF: disable slot if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) - disable = TRUE; + disable = 1; // bit 6 - HPC_SLOT_BUS_SPEED // ignore // bit 7 - HPC_SLOT_LATCH if ((pslot->status & 0x80) != (poldslot->status & 0x80)) { - update = TRUE; + update = 1; // OPEN -> CLOSE if (pslot->status & 0x80) { if (SLOT_PWRGD (pslot->status)) { @@ -979,7 +979,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) msleep(1000); rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status); if (SLOT_PWRGD (status)) - update = TRUE; + update = 1; else // overwrite power in pslot to OFF pslot->status &= ~HPC_SLOT_POWER; } @@ -987,17 +987,17 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) // CLOSE -> OPEN else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) { - disable = TRUE; + disable = 1; } // else - ignore } // bit 4 - HPC_SLOT_BLINK_ATTN if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08)) - update = TRUE; + update = 1; if (disable) { debug ("process_changeinstatus - disable slot\n"); - pslot->flag = FALSE; + pslot->flag = 0; rc = ibmphp_do_disable_slot (pslot); } @@ -1102,7 +1102,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void) { debug ("%s - Entry\n", __FUNCTION__); - ibmphp_shutdown = TRUE; + ibmphp_shutdown = 1; debug ("before locking operations \n"); ibmphp_lock_operations (); debug ("after locking operations \n"); @@ -1136,7 +1136,7 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v u8 * pstatus) { int rc = 0; - u8 done = FALSE; + u8 done = 0; debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout); @@ -1144,14 +1144,14 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v *pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX); if (*pstatus == HPC_ERROR) { rc = HPC_ERROR; - done = TRUE; + done = 1; } if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO) - done = TRUE; + done = 1; if (!done) { msleep(1000); if (timeout < 1) { - done = TRUE; + done = 1; err ("HPCreadslot - Error ctlr timeout\n"); rc = HPC_ERROR; } else diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 97753ddcd856..d87a9e3eaeeb 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c @@ -199,7 +199,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) } pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); - flag = FALSE; + flag = 0; for (i = 0; i < 32; i++) { if (func->devices[i]) { newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); @@ -226,7 +226,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cleanup_count = 2; goto error; } - flag = TRUE; + flag = 1; } } @@ -272,7 +272,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cur_func->busno, device, function); pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); debug ("after configuring bridge..., sec_number = %x\n", sec_number); - flag = FALSE; + flag = 0; for (i = 0; i < 32; i++) { if (func->devices[i]) { debug ("inside for loop, device is %x\n", i); @@ -301,7 +301,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cleanup_count = 2; goto error; } - flag = TRUE; + flag = 1; } } @@ -449,7 +449,7 @@ static int configure_device (struct pci_func *func) pfmem[count]->devfunc = PCI_DEVFN(func->device, func->function); pfmem[count]->len = len[count]; - pfmem[count]->fromMem = FALSE; + pfmem[count]->fromMem = 0; if (ibmphp_check_resource (pfmem[count], 0) == 0) { ibmphp_add_resource (pfmem[count]); func->pfmem[count] = pfmem[count]; @@ -467,7 +467,7 @@ static int configure_device (struct pci_func *func) debug ("there's no pfmem... going into mem.\n"); if (ibmphp_check_resource (mem_tmp, 0) == 0) { ibmphp_add_resource (mem_tmp); - pfmem[count]->fromMem = TRUE; + pfmem[count]->fromMem = 1; pfmem[count]->rangeno = mem_tmp->rangeno; pfmem[count]->start = mem_tmp->start; pfmem[count]->end = mem_tmp->end; @@ -571,11 +571,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) u16 pfmem_base; u32 bar[2]; u32 len[2]; - u8 flag_io = FALSE; - u8 flag_mem = FALSE; - u8 flag_pfmem = FALSE; - u8 need_io_upper = FALSE; - u8 need_pfmem_upper = FALSE; + u8 flag_io = 0; + u8 flag_mem = 0; + u8 flag_pfmem = 0; + u8 need_io_upper = 0; + u8 need_pfmem_upper = 0; struct res_needed *amount_needed = NULL; struct resource_node *io = NULL; struct resource_node *bus_io[2] = {NULL, NULL}; @@ -713,7 +713,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) bus_pfmem[count]->devfunc = PCI_DEVFN(func->device, func->function); bus_pfmem[count]->len = len[count]; - bus_pfmem[count]->fromMem = FALSE; + bus_pfmem[count]->fromMem = 0; if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) { ibmphp_add_resource (bus_pfmem[count]); func->pfmem[count] = bus_pfmem[count]; @@ -730,7 +730,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) mem_tmp->len = bus_pfmem[count]->len; if (ibmphp_check_resource (mem_tmp, 0) == 0) { ibmphp_add_resource (mem_tmp); - bus_pfmem[count]->fromMem = TRUE; + bus_pfmem[count]->fromMem = 1; bus_pfmem[count]->rangeno = mem_tmp->rangeno; ibmphp_add_pfmem_from_mem (bus_pfmem[count]); func->pfmem[count] = bus_pfmem[count]; @@ -826,7 +826,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) if (!amount_needed->io) { debug ("it doesn't want IO?\n"); - flag_io = TRUE; + flag_io = 1; } else { debug ("it wants %x IO behind the bridge\n", amount_needed->io); io = kzalloc(sizeof(*io), GFP_KERNEL); @@ -843,13 +843,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) if (ibmphp_check_resource (io, 1) == 0) { debug ("were we able to add io\n"); ibmphp_add_resource (io); - flag_io = TRUE; + flag_io = 1; } } if (!amount_needed->mem) { debug ("it doesn't want n.e.memory?\n"); - flag_mem = TRUE; + flag_mem = 1; } else { debug ("it wants %x memory behind the bridge\n", amount_needed->mem); mem = kzalloc(sizeof(*mem), GFP_KERNEL); @@ -864,14 +864,14 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) mem->len = amount_needed->mem; if (ibmphp_check_resource (mem, 1) == 0) { ibmphp_add_resource (mem); - flag_mem = TRUE; + flag_mem = 1; debug ("were we able to add mem\n"); } } if (!amount_needed->pfmem) { debug ("it doesn't want n.e.pfmem mem?\n"); - flag_pfmem = TRUE; + flag_pfmem = 1; } else { debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem); pfmem = kzalloc(sizeof(*pfmem), GFP_KERNEL); @@ -884,10 +884,10 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) pfmem->busno = func->busno; pfmem->devfunc = PCI_DEVFN(func->device, func->function); pfmem->len = amount_needed->pfmem; - pfmem->fromMem = FALSE; + pfmem->fromMem = 0; if (ibmphp_check_resource (pfmem, 1) == 0) { ibmphp_add_resource (pfmem); - flag_pfmem = TRUE; + flag_pfmem = 1; } else { mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { @@ -901,10 +901,10 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) mem_tmp->len = pfmem->len; if (ibmphp_check_resource (mem_tmp, 1) == 0) { ibmphp_add_resource (mem_tmp); - pfmem->fromMem = TRUE; + pfmem->fromMem = 1; pfmem->rangeno = mem_tmp->rangeno; ibmphp_add_pfmem_from_mem (pfmem); - flag_pfmem = TRUE; + flag_pfmem = 1; } } } @@ -950,11 +950,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { debug ("io 32\n"); - need_io_upper = TRUE; + need_io_upper = 1; } if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { debug ("pfmem 64\n"); - need_pfmem_upper = TRUE; + need_pfmem_upper = 1; } if (bus->noIORanges) { @@ -1119,7 +1119,7 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) debug ("hdr_type behind the bridge is %x\n", hdr_type); if (hdr_type & PCI_HEADER_TYPE_BRIDGE) { err ("embedded bridges not supported for hot-plugging.\n"); - amount->not_correct = TRUE; + amount->not_correct = 1; return amount; } @@ -1127,12 +1127,12 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) if (class == PCI_CLASS_NOT_DEFINED_VGA) { err ("The device %x is VGA compatible and as is not supported for hot plugging. " "Please choose another device.\n", device); - amount->not_correct = TRUE; + amount->not_correct = 1; return amount; } else if (class == PCI_CLASS_DISPLAY_VGA) { err ("The device %x is not supported for hot plugging. " "Please choose another device.\n", device); - amount->not_correct = TRUE; + amount->not_correct = 1; return amount; } @@ -1192,9 +1192,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) } /* end for */ if (!howmany) - amount->not_correct = TRUE; + amount->not_correct = 1; else - amount->not_correct = FALSE; + amount->not_correct = 0; if ((amount->io) && (amount->io < IOBRIDGE)) amount->io = IOBRIDGE; if ((amount->mem) && (amount->mem < MEMBRIDGE)) diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c index 852a98bf07d3..5636b1ac2a2e 100644 --- a/drivers/pci/hotplug/ibmphp_res.c +++ b/drivers/pci/hotplug/ibmphp_res.c @@ -325,7 +325,7 @@ int __init ibmphp_rsrc_init (void) if (!new_pfmem) return -ENOMEM; new_pfmem->type = PFMEM; - new_pfmem->fromMem = FALSE; + new_pfmem->fromMem = 0; if (ibmphp_add_resource (new_pfmem) < 0) { newbus = alloc_error_bus (curr, 0, 0); if (!newbus) @@ -462,7 +462,7 @@ static int add_range (int type, struct range_node *range, struct bus_node *bus_c static void update_resources (struct bus_node *bus_cur, int type, int rangeno) { struct resource_node *res = NULL; - u8 eol = FALSE; /* end of list indicator */ + u8 eol = 0; /* end of list indicator */ switch (type) { case MEM: @@ -488,7 +488,7 @@ static void update_resources (struct bus_node *bus_cur, int type, int rangeno) else if (res->nextRange) res = res->nextRange; else { - eol = TRUE; + eol = 1; break; } } @@ -979,7 +979,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) int noranges = 0; u32 tmp_start; /* this is to make sure start address is divisible by the length needed */ u32 tmp_divide; - u8 flag = FALSE; + u8 flag = 0; if (!res) return -EINVAL; @@ -1046,17 +1046,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((range->start % tmp_divide) == 0) { /* just perfect, starting address is divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1085,17 +1085,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if (((res_cur->end + 1) % tmp_divide) == 0) { /* just perfect, starting address is divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = res_cur->end + 1; } else { /* Needs adjusting */ tmp_start = res_cur->end + 1; - flag = FALSE; + flag = 0; while ((len_tmp = range->end - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1123,17 +1123,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if ((range->start % tmp_divide) == 0) { /* just perfect, starting address is divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1158,17 +1158,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if (((res_prev->end + 1) % tmp_divide) == 0) { /* just perfect, starting address's divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = res_prev->end + 1; } else { /* Needs adjusting */ tmp_start = res_prev->end + 1; - flag = FALSE; + flag = 0; while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1217,17 +1217,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if ((range->start % tmp_divide) == 0) { /* just perfect, starting address's divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = range->end - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1281,17 +1281,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if ((range->start % tmp_divide) == 0) { /* just perfect, starting address's divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = range->end - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1684,7 +1684,7 @@ static int __init once_over (void) bus_cur = list_entry (tmp, struct bus_node, bus_list); if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) { for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) { - pfmem_cur->fromMem = TRUE; + pfmem_cur->fromMem = 1; if (pfmem_prev) pfmem_prev->next = pfmem_cur->next; else @@ -2129,7 +2129,7 @@ static int __init update_bridge_ranges (struct bus_node **bus) pfmem->start = start_address; pfmem->end = end_address + 0xfffff; pfmem->len = pfmem->end - pfmem->start + 1; - pfmem->fromMem = FALSE; + pfmem->fromMem = 0; ibmphp_add_resource (pfmem); } -- cgit v1.2.3-59-g8ed1b From b2e6e3ba7deb525f180df64f32f3fcb214538bea Mon Sep 17 00:00:00 2001 From: MUNEDA Takahiro Date: Fri, 17 Mar 2006 09:18:39 +0900 Subject: [PATCH] acpiphp: fix acpi_path_name I encountered the problem that the insmod of the acpiphp fails because of the mis-freeing of the memory. I tested this patch on my tiger4 box. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpi_pcihp.c | 54 ++++++++++++++------------------------- drivers/pci/hotplug/pci_hotplug.h | 1 - drivers/pci/hotplug/pciehp_hpc.c | 15 ++++++----- 3 files changed, 27 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 0f7135317542..39af9c325f35 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -37,28 +37,6 @@ #define METHOD_NAME__HPP "_HPP" #define METHOD_NAME_OSHP "OSHP" -/* acpi_path_name - * - * @handle - the acpi_handle of the object who's name you want. - * - * Caller must free buffer. - */ -u8 * acpi_path_name(acpi_handle handle) -{ - acpi_status status; - struct acpi_buffer ret_buf = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *obj; - - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); - if (ACPI_FAILURE(status)) { - return NULL; - } - obj = ret_buf.pointer; - return obj->string.pointer; -} -EXPORT_SYMBOL_GPL(acpi_path_name); - - static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) @@ -66,10 +44,12 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) acpi_status status; u8 nui[4]; struct acpi_buffer ret_buf = { 0, NULL}; + struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *ext_obj, *package; - u8 *path_name = acpi_path_name(handle); int i, len = 0; + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + /* get _hpp */ status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); switch (status) { @@ -77,8 +57,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); if (!ret_buf.pointer) { printk(KERN_ERR "%s:%s alloc for _HPP fail\n", - __FUNCTION__, path_name); - acpi_os_free(path_name); + __FUNCTION__, (char *)string.pointer); + acpi_os_free(string.pointer); return AE_NO_MEMORY; } status = acpi_evaluate_object(handle, METHOD_NAME__HPP, @@ -88,8 +68,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) default: if (ACPI_FAILURE(status)) { pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__, - path_name, status); - acpi_os_free(path_name); + (char *)string.pointer, status); + acpi_os_free(string.pointer); return status; } } @@ -97,7 +77,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) ext_obj = (union acpi_object *) ret_buf.pointer; if (ext_obj->type != ACPI_TYPE_PACKAGE) { printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__, - path_name); + (char *)string.pointer); status = AE_ERROR; goto free_and_return; } @@ -112,7 +92,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) break; default: printk(KERN_ERR "%s:%s _HPP obj type incorrect\n", - __FUNCTION__, path_name); + __FUNCTION__, (char *)string.pointer); status = AE_ERROR; goto free_and_return; } @@ -129,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(path_name); - kfree(ret_buf.pointer); + acpi_os_free(string.pointer); + acpi_os_free(ret_buf.pointer); return status; } @@ -143,16 +123,20 @@ free_and_return: acpi_status acpi_run_oshp(acpi_handle handle) { acpi_status status; - u8 *path_name = acpi_path_name(handle); + struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); /* 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__, - path_name, status); + (char *)string.pointer, status); else - pr_debug("%s:%s OSHP passes\n", __FUNCTION__, path_name); - acpi_os_free(path_name); + pr_debug("%s:%s OSHP passes\n", __FUNCTION__, + (char *)string.pointer); + + acpi_os_free(string.pointer); return status; } EXPORT_SYMBOL_GPL(acpi_run_oshp); diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index e476ed033384..eb0d01d47236 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h @@ -190,7 +190,6 @@ struct hotplug_params { extern acpi_status acpi_run_oshp(acpi_handle handle); extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp); -extern u8 * acpi_path_name(acpi_handle handle); int acpi_root_bridge(acpi_handle handle); #endif #endif diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 22dcd12e4c1c..6c14d9e46b2e 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1246,7 +1246,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); struct pci_dev *pdev = dev; struct pci_bus *parent; - u8 *path_name = NULL; + struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; /* * Per PCI firmware specification, we should run the ACPI _OSC @@ -1278,16 +1278,17 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) } while (handle) { - path_name = acpi_path_name(handle); - dbg("Trying to get hotplug control for %s \n", path_name); + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + dbg("Trying to get hotplug control for %s \n", + (char *)string.pointer); status = pci_osc_control_set(handle, OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); if (status == AE_NOT_FOUND) status = acpi_run_oshp(handle); if (ACPI_SUCCESS(status)) { dbg("Gained control for hotplug HW for pci %s (%s)\n", - pci_name(dev), path_name); - acpi_os_free(path_name); + pci_name(dev), (char *)string.pointer); + acpi_os_free(string.pointer); return 0; } if (acpi_root_bridge(handle)) @@ -1300,8 +1301,8 @@ 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)); - if (path_name) - acpi_os_free(path_name); + + acpi_os_free(string.pointer); return -1; } #endif -- cgit v1.2.3-59-g8ed1b From ccd6994000fb6d08ee1be8a7fa20c8d602a2267d Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Tue, 6 Dec 2005 13:38:27 +0300 Subject: [PATCH] W1: Change the type 'unsigned long' member of 'struct w1_bus_master' to 'void *'. Signed-off-by: Ben Gardner Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/ds_w1_bridge.c | 34 +++++++++++++++++----------------- drivers/w1/matrox_w1.c | 14 +++++++------- drivers/w1/w1.c | 8 ++++---- drivers/w1/w1.h | 24 ++++++++++++------------ 4 files changed, 40 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/w1/ds_w1_bridge.c b/drivers/w1/ds_w1_bridge.c index a79d16d5666f..29e01d57c6be 100644 --- a/drivers/w1/ds_w1_bridge.c +++ b/drivers/w1/ds_w1_bridge.c @@ -29,10 +29,10 @@ static struct ds_device *ds_dev; static struct w1_bus_master *ds_bus_master; -static u8 ds9490r_touch_bit(unsigned long data, u8 bit) +static u8 ds9490r_touch_bit(void *data, u8 bit) { u8 ret; - struct ds_device *dev = (struct ds_device *)data; + struct ds_device *dev = data; if (ds_touch_bit(dev, bit, &ret)) return 0; @@ -40,23 +40,23 @@ static u8 ds9490r_touch_bit(unsigned long data, u8 bit) return ret; } -static void ds9490r_write_bit(unsigned long data, u8 bit) +static void ds9490r_write_bit(void *data, u8 bit) { - struct ds_device *dev = (struct ds_device *)data; + struct ds_device *dev = data; ds_write_bit(dev, bit); } -static void ds9490r_write_byte(unsigned long data, u8 byte) +static void ds9490r_write_byte(void *data, u8 byte) { - struct ds_device *dev = (struct ds_device *)data; + struct ds_device *dev = data; ds_write_byte(dev, byte); } -static u8 ds9490r_read_bit(unsigned long data) +static u8 ds9490r_read_bit(void *data) { - struct ds_device *dev = (struct ds_device *)data; + struct ds_device *dev = data; int err; u8 bit = 0; @@ -70,9 +70,9 @@ static u8 ds9490r_read_bit(unsigned long data) return bit & 1; } -static u8 ds9490r_read_byte(unsigned long data) +static u8 ds9490r_read_byte(void *data) { - struct ds_device *dev = (struct ds_device *)data; + struct ds_device *dev = data; int err; u8 byte = 0; @@ -83,16 +83,16 @@ static u8 ds9490r_read_byte(unsigned long data) return byte; } -static void ds9490r_write_block(unsigned long data, const u8 *buf, int len) +static void ds9490r_write_block(void *data, const u8 *buf, int len) { - struct ds_device *dev = (struct ds_device *)data; + struct ds_device *dev = data; ds_write_block(dev, (u8 *)buf, len); } -static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len) +static u8 ds9490r_read_block(void *data, u8 *buf, int len) { - struct ds_device *dev = (struct ds_device *)data; + struct ds_device *dev = data; int err; err = ds_read_block(dev, buf, len); @@ -102,9 +102,9 @@ static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len) return len; } -static u8 ds9490r_reset(unsigned long data) +static u8 ds9490r_reset(void *data) { - struct ds_device *dev = (struct ds_device *)data; + struct ds_device *dev = data; struct ds_status st; int err; @@ -136,7 +136,7 @@ static int __devinit ds_w1_init(void) memset(ds_bus_master, 0, sizeof(*ds_bus_master)); - ds_bus_master->data = (unsigned long)ds_dev; + 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; diff --git a/drivers/w1/matrox_w1.c b/drivers/w1/matrox_w1.c index 0b03f8f93f63..750a1aacf6f5 100644 --- a/drivers/w1/matrox_w1.c +++ b/drivers/w1/matrox_w1.c @@ -90,8 +90,8 @@ struct matrox_device struct w1_bus_master *bus_master; }; -static u8 matrox_w1_read_ddc_bit(unsigned long); -static void matrox_w1_write_ddc_bit(unsigned long, u8); +static u8 matrox_w1_read_ddc_bit(void *); +static void matrox_w1_write_ddc_bit(void *, u8); /* * These functions read and write DDC Data bit. @@ -122,10 +122,10 @@ static __inline__ void matrox_w1_write_reg(struct matrox_device *dev, u8 reg, u8 wmb(); } -static void matrox_w1_write_ddc_bit(unsigned long data, u8 bit) +static void matrox_w1_write_ddc_bit(void *data, u8 bit) { u8 ret; - struct matrox_device *dev = (struct matrox_device *) data; + struct matrox_device *dev = data; if (bit) bit = 0; @@ -137,10 +137,10 @@ static void matrox_w1_write_ddc_bit(unsigned long data, u8 bit) matrox_w1_write_reg(dev, MATROX_GET_DATA, 0x00); } -static u8 matrox_w1_read_ddc_bit(unsigned long data) +static u8 matrox_w1_read_ddc_bit(void *data) { u8 ret; - struct matrox_device *dev = (struct matrox_device *) data; + struct matrox_device *dev = data; ret = matrox_w1_read_reg(dev, MATROX_GET_DATA); @@ -198,7 +198,7 @@ static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_devi matrox_w1_hw_init(dev); - dev->bus_master->data = (unsigned long) dev; + dev->bus_master->data = dev; dev->bus_master->read_bit = &matrox_w1_read_ddc_bit; dev->bus_master->write_bit = &matrox_w1_write_ddc_bit; diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 024206c4a0e4..f0b47fe4ed25 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -552,7 +552,7 @@ static void w1_slave_detach(struct w1_slave *sl) kfree(sl); } -static struct w1_master *w1_search_master(unsigned long data) +static struct w1_master *w1_search_master(void *data) { struct w1_master *dev; int found = 0; @@ -583,7 +583,7 @@ void w1_reconnect_slaves(struct w1_family *f) spin_unlock_bh(&w1_mlock); } -static void w1_slave_found(unsigned long data, u64 rn) +static void w1_slave_found(void *data, u64 rn) { int slave_count; struct w1_slave *sl; @@ -595,8 +595,8 @@ static void w1_slave_found(unsigned long data, u64 rn) dev = w1_search_master(data); if (!dev) { - printk(KERN_ERR "Failed to find w1 master device for data %08lx, it is impossible.\n", - data); + printk(KERN_ERR "Failed to find w1 master device for data %p, " + "it is impossible.\n", data); return; } diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index d8900780c3bf..b62e771e5709 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -80,7 +80,7 @@ struct w1_slave struct completion released; }; -typedef void (* w1_slave_found_callback)(unsigned long, u64); +typedef void (* w1_slave_found_callback)(void *, u64); /** @@ -93,16 +93,16 @@ typedef void (* w1_slave_found_callback)(unsigned long, u64); struct w1_bus_master { /** the first parameter in all the functions below */ - unsigned long data; + void *data; /** * Sample the line level * @return the level read (0 or 1) */ - u8 (*read_bit)(unsigned long); + u8 (*read_bit)(void *); /** Sets the line level */ - void (*write_bit)(unsigned long, u8); + void (*write_bit)(void *, u8); /** * touch_bit is the lowest-level function for devices that really @@ -111,42 +111,42 @@ struct w1_bus_master * touch_bit(1) = write-1 / read cycle * @return the bit read (0 or 1) */ - u8 (*touch_bit)(unsigned long, u8); + u8 (*touch_bit)(void *, u8); /** * Reads a bytes. Same as 8 touch_bit(1) calls. * @return the byte read */ - u8 (*read_byte)(unsigned long); + u8 (*read_byte)(void *); /** * Writes a byte. Same as 8 touch_bit(x) calls. */ - void (*write_byte)(unsigned long, u8); + void (*write_byte)(void *, u8); /** * Same as a series of read_byte() calls * @return the number of bytes read */ - u8 (*read_block)(unsigned long, u8 *, int); + u8 (*read_block)(void *, u8 *, int); /** Same as a series of write_byte() calls */ - void (*write_block)(unsigned long, const u8 *, int); + void (*write_block)(void *, const u8 *, int); /** * Combines two reads and a smart write for ROM searches * @return bit0=Id bit1=comp_id bit2=dir_taken */ - u8 (*triplet)(unsigned long, u8); + u8 (*triplet)(void *, u8); /** * long write-0 with a read for the presence pulse detection * @return -1=Error, 0=Device present, 1=No device present */ - u8 (*reset_bus)(unsigned long); + u8 (*reset_bus)(void *); /** Really nice hardware can handles the ROM searches */ - void (*search)(unsigned long, w1_slave_found_callback); + void (*search)(void *, w1_slave_found_callback); }; #define W1_MASTER_NEED_EXIT 0 -- cgit v1.2.3-59-g8ed1b From bd529cfb40c427d5b5aae0d315afb9f0a1da5e76 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Tue, 6 Dec 2005 13:38:28 +0300 Subject: [PATCH] W1: Move w1 bus master code into 'w1/masters' and move w1 slave code into 'w1/slaves' Signed-off-by: Ben Gardner Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/Kconfig | 60 +-- drivers/w1/Makefile | 10 +- drivers/w1/ds_w1_bridge.c | 174 --------- drivers/w1/dscore.c | 795 -------------------------------------- drivers/w1/dscore.h | 166 -------- drivers/w1/masters/Kconfig | 38 ++ drivers/w1/masters/Makefile | 11 + drivers/w1/masters/ds_w1_bridge.c | 174 +++++++++ drivers/w1/masters/dscore.c | 795 ++++++++++++++++++++++++++++++++++++++ drivers/w1/masters/dscore.h | 166 ++++++++ drivers/w1/masters/matrox_w1.c | 247 ++++++++++++ drivers/w1/matrox_w1.c | 247 ------------ drivers/w1/slaves/Kconfig | 38 ++ drivers/w1/slaves/Makefile | 12 + drivers/w1/slaves/w1_ds2433.c | 329 ++++++++++++++++ drivers/w1/slaves/w1_smem.c | 71 ++++ drivers/w1/slaves/w1_therm.c | 268 +++++++++++++ drivers/w1/w1_ds2433.c | 329 ---------------- drivers/w1/w1_smem.c | 71 ---- drivers/w1/w1_therm.c | 268 ------------- 20 files changed, 2152 insertions(+), 2117 deletions(-) delete mode 100644 drivers/w1/ds_w1_bridge.c delete mode 100644 drivers/w1/dscore.c delete mode 100644 drivers/w1/dscore.h create mode 100644 drivers/w1/masters/Kconfig create mode 100644 drivers/w1/masters/Makefile create mode 100644 drivers/w1/masters/ds_w1_bridge.c create mode 100644 drivers/w1/masters/dscore.c create mode 100644 drivers/w1/masters/dscore.h create mode 100644 drivers/w1/masters/matrox_w1.c delete mode 100644 drivers/w1/matrox_w1.c create mode 100644 drivers/w1/slaves/Kconfig create mode 100644 drivers/w1/slaves/Makefile create mode 100644 drivers/w1/slaves/w1_ds2433.c create mode 100644 drivers/w1/slaves/w1_smem.c create mode 100644 drivers/w1/slaves/w1_therm.c delete mode 100644 drivers/w1/w1_ds2433.c delete mode 100644 drivers/w1/w1_smem.c delete mode 100644 drivers/w1/w1_therm.c (limited to 'drivers') diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig index 4baf61a22327..5e61ed59a41e 100644 --- a/drivers/w1/Kconfig +++ b/drivers/w1/Kconfig @@ -11,63 +11,7 @@ config W1 This W1 support can also be built as a module. If so, the module will be called wire.ko. -config W1_MATROX - tristate "Matrox G400 transport layer for 1-wire" - depends on W1 && PCI - help - Say Y here if you want to communicate with your 1-wire devices - using Matrox's G400 GPIO pins. - - This support is also available as a module. If so, the module - will be called matrox_w1.ko. - -config W1_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_DS9490_BRIDGE - tristate "DS9490R USB <-> W1 transport layer for 1-wire" - depends on W1_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_THERM - tristate "Thermal family implementation" - depends on W1 - help - Say Y here if you want to connect 1-wire thermal sensors to you - wire. - -config W1_SMEM - tristate "Simple 64bit memory family implementation" - depends on W1 - help - Say Y here if you want to connect 1-wire - simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire. - -config W1_DS2433 - tristate "4kb EEPROM family support (DS2433)" - depends on W1 - help - Say Y here if you want to use a 1-wire - 4kb EEPROM family device (DS2433). - -config W1_DS2433_CRC - bool "Protect DS2433 data with a CRC16" - depends on W1_DS2433 - select CRC16 - help - Say Y here to protect DS2433 data with a CRC16. - Each block has 30 bytes of data and a two byte CRC16. - Full block writes are only allowed if the CRC is valid. +source drivers/w1/masters/Kconfig +source drivers/w1/slaves/Kconfig endmenu diff --git a/drivers/w1/Makefile b/drivers/w1/Makefile index 01fb54391470..0c2aa22d8c04 100644 --- a/drivers/w1/Makefile +++ b/drivers/w1/Makefile @@ -13,13 +13,5 @@ endif obj-$(CONFIG_W1) += wire.o wire-objs := w1.o w1_int.o w1_family.o w1_netlink.o w1_io.o -obj-$(CONFIG_W1_MATROX) += matrox_w1.o -obj-$(CONFIG_W1_THERM) += w1_therm.o -obj-$(CONFIG_W1_SMEM) += w1_smem.o +obj-y += masters/ slaves/ -obj-$(CONFIG_W1_DS9490) += ds9490r.o -ds9490r-objs := dscore.o - -obj-$(CONFIG_W1_DS9490_BRIDGE) += ds_w1_bridge.o - -obj-$(CONFIG_W1_DS2433) += w1_ds2433.o diff --git a/drivers/w1/ds_w1_bridge.c b/drivers/w1/ds_w1_bridge.c deleted file mode 100644 index 29e01d57c6be..000000000000 --- a/drivers/w1/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/w1.h" -#include "../w1/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/dscore.c b/drivers/w1/dscore.c deleted file mode 100644 index b9146306df49..000000000000 --- a/drivers/w1/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/dscore.h b/drivers/w1/dscore.h deleted file mode 100644 index 6cf5671d6ebe..000000000000 --- a/drivers/w1/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 */ - diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig new file mode 100644 index 000000000000..51bd64d0e54d --- /dev/null +++ b/drivers/w1/masters/Kconfig @@ -0,0 +1,38 @@ +# +# 1-wire bus master configuration +# + +menu "1-wire Bus Masters" + depends on W1 + +config W1_MASTER_MATROX + tristate "Matrox G400 transport layer for 1-wire" + depends on W1 && PCI + help + Say Y here if you want to communicate with your 1-wire devices + using Matrox's G400 GPIO pins. + + 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_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. + +endmenu + diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile new file mode 100644 index 000000000000..d9b84e522d6c --- /dev/null +++ b/drivers/w1/masters/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for 1-wire bus master drivers. +# + +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 + diff --git a/drivers/w1/masters/ds_w1_bridge.c b/drivers/w1/masters/ds_w1_bridge.c new file mode 100644 index 000000000000..5d30783a3eb6 --- /dev/null +++ b/drivers/w1/masters/ds_w1_bridge.c @@ -0,0 +1,174 @@ +/* + * 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 new file mode 100644 index 000000000000..2cf7776a7080 --- /dev/null +++ b/drivers/w1/masters/dscore.c @@ -0,0 +1,795 @@ +/* + * 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 new file mode 100644 index 000000000000..6cf5671d6ebe --- /dev/null +++ b/drivers/w1/masters/dscore.h @@ -0,0 +1,166 @@ +/* + * 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 */ + diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c new file mode 100644 index 000000000000..591809cbbb97 --- /dev/null +++ b/drivers/w1/masters/matrox_w1.c @@ -0,0 +1,247 @@ +/* + * matrox_w1.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../w1.h" +#include "../w1_int.h" +#include "../w1_log.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Evgeniy Polyakov "); +MODULE_DESCRIPTION("Driver for transport(Dallas 1-wire prtocol) over VGA DDC(matrox gpio)."); + +static struct pci_device_id matrox_w1_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400) }, + { }, +}; +MODULE_DEVICE_TABLE(pci, matrox_w1_tbl); + +static int __devinit matrox_w1_probe(struct pci_dev *, const struct pci_device_id *); +static void __devexit matrox_w1_remove(struct pci_dev *); + +static struct pci_driver matrox_w1_pci_driver = { + .name = "matrox_w1", + .id_table = matrox_w1_tbl, + .probe = matrox_w1_probe, + .remove = __devexit_p(matrox_w1_remove), +}; + +/* + * Matrox G400 DDC registers. + */ + +#define MATROX_G400_DDC_CLK (1<<4) +#define MATROX_G400_DDC_DATA (1<<1) + +#define MATROX_BASE 0x3C00 +#define MATROX_STATUS 0x1e14 + +#define MATROX_PORT_INDEX_OFFSET 0x00 +#define MATROX_PORT_DATA_OFFSET 0x0A + +#define MATROX_GET_CONTROL 0x2A +#define MATROX_GET_DATA 0x2B +#define MATROX_CURSOR_CTL 0x06 + +struct matrox_device +{ + void __iomem *base_addr; + void __iomem *port_index; + void __iomem *port_data; + u8 data_mask; + + unsigned long phys_addr; + void __iomem *virt_addr; + unsigned long found; + + struct w1_bus_master *bus_master; +}; + +static u8 matrox_w1_read_ddc_bit(void *); +static void matrox_w1_write_ddc_bit(void *, u8); + +/* + * These functions read and write DDC Data bit. + * + * Using tristate pins, since i can't find any open-drain pin in whole motherboard. + * Unfortunately we can't connect to Intel's 82801xx IO controller + * since we don't know motherboard schema, wich has pretty unused(may be not) GPIO. + * + * I've heard that PIIX also has open drain pin. + * + * Port mapping. + */ +static __inline__ u8 matrox_w1_read_reg(struct matrox_device *dev, u8 reg) +{ + u8 ret; + + writeb(reg, dev->port_index); + ret = readb(dev->port_data); + barrier(); + + return ret; +} + +static __inline__ void matrox_w1_write_reg(struct matrox_device *dev, u8 reg, u8 val) +{ + writeb(reg, dev->port_index); + writeb(val, dev->port_data); + wmb(); +} + +static void matrox_w1_write_ddc_bit(void *data, u8 bit) +{ + u8 ret; + struct matrox_device *dev = data; + + if (bit) + bit = 0; + else + bit = dev->data_mask; + + ret = matrox_w1_read_reg(dev, MATROX_GET_CONTROL); + matrox_w1_write_reg(dev, MATROX_GET_CONTROL, ((ret & ~dev->data_mask) | bit)); + matrox_w1_write_reg(dev, MATROX_GET_DATA, 0x00); +} + +static u8 matrox_w1_read_ddc_bit(void *data) +{ + u8 ret; + struct matrox_device *dev = data; + + ret = matrox_w1_read_reg(dev, MATROX_GET_DATA); + + return ret; +} + +static void matrox_w1_hw_init(struct matrox_device *dev) +{ + matrox_w1_write_reg(dev, MATROX_GET_DATA, 0xFF); + matrox_w1_write_reg(dev, MATROX_GET_CONTROL, 0x00); +} + +static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct matrox_device *dev; + int err; + + assert(pdev != NULL); + assert(ent != NULL); + + if (pdev->vendor != PCI_VENDOR_ID_MATROX || pdev->device != PCI_DEVICE_ID_MATROX_G400) + return -ENODEV; + + dev = kmalloc(sizeof(struct matrox_device) + + sizeof(struct w1_bus_master), GFP_KERNEL); + if (!dev) { + dev_err(&pdev->dev, + "%s: Failed to create new matrox_device object.\n", + __func__); + return -ENOMEM; + } + + memset(dev, 0, sizeof(struct matrox_device) + sizeof(struct w1_bus_master)); + + dev->bus_master = (struct w1_bus_master *)(dev + 1); + + /* + * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c + */ + + dev->phys_addr = pci_resource_start(pdev, 1); + + dev->virt_addr = ioremap_nocache(dev->phys_addr, 16384); + if (!dev->virt_addr) { + dev_err(&pdev->dev, "%s: failed to ioremap(0x%lx, %d).\n", + __func__, dev->phys_addr, 16384); + err = -EIO; + goto err_out_free_device; + } + + dev->base_addr = dev->virt_addr + MATROX_BASE; + dev->port_index = dev->base_addr + MATROX_PORT_INDEX_OFFSET; + dev->port_data = dev->base_addr + MATROX_PORT_DATA_OFFSET; + dev->data_mask = (MATROX_G400_DDC_DATA); + + matrox_w1_hw_init(dev); + + dev->bus_master->data = dev; + dev->bus_master->read_bit = &matrox_w1_read_ddc_bit; + dev->bus_master->write_bit = &matrox_w1_write_ddc_bit; + + err = w1_add_master_device(dev->bus_master); + if (err) + goto err_out_free_device; + + pci_set_drvdata(pdev, dev); + + dev->found = 1; + + dev_info(&pdev->dev, "Matrox G400 GPIO transport layer for 1-wire.\n"); + + return 0; + +err_out_free_device: + kfree(dev); + + return err; +} + +static void __devexit matrox_w1_remove(struct pci_dev *pdev) +{ + struct matrox_device *dev = pci_get_drvdata(pdev); + + assert(dev != NULL); + + if (dev->found) { + w1_remove_master_device(dev->bus_master); + iounmap(dev->virt_addr); + } + kfree(dev); +} + +static int __init matrox_w1_init(void) +{ + return pci_register_driver(&matrox_w1_pci_driver); +} + +static void __exit matrox_w1_fini(void) +{ + pci_unregister_driver(&matrox_w1_pci_driver); +} + +module_init(matrox_w1_init); +module_exit(matrox_w1_fini); diff --git a/drivers/w1/matrox_w1.c b/drivers/w1/matrox_w1.c deleted file mode 100644 index 750a1aacf6f5..000000000000 --- a/drivers/w1/matrox_w1.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * matrox_w1.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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "w1.h" -#include "w1_int.h" -#include "w1_log.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov "); -MODULE_DESCRIPTION("Driver for transport(Dallas 1-wire prtocol) over VGA DDC(matrox gpio)."); - -static struct pci_device_id matrox_w1_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400) }, - { }, -}; -MODULE_DEVICE_TABLE(pci, matrox_w1_tbl); - -static int __devinit matrox_w1_probe(struct pci_dev *, const struct pci_device_id *); -static void __devexit matrox_w1_remove(struct pci_dev *); - -static struct pci_driver matrox_w1_pci_driver = { - .name = "matrox_w1", - .id_table = matrox_w1_tbl, - .probe = matrox_w1_probe, - .remove = __devexit_p(matrox_w1_remove), -}; - -/* - * Matrox G400 DDC registers. - */ - -#define MATROX_G400_DDC_CLK (1<<4) -#define MATROX_G400_DDC_DATA (1<<1) - -#define MATROX_BASE 0x3C00 -#define MATROX_STATUS 0x1e14 - -#define MATROX_PORT_INDEX_OFFSET 0x00 -#define MATROX_PORT_DATA_OFFSET 0x0A - -#define MATROX_GET_CONTROL 0x2A -#define MATROX_GET_DATA 0x2B -#define MATROX_CURSOR_CTL 0x06 - -struct matrox_device -{ - void __iomem *base_addr; - void __iomem *port_index; - void __iomem *port_data; - u8 data_mask; - - unsigned long phys_addr; - void __iomem *virt_addr; - unsigned long found; - - struct w1_bus_master *bus_master; -}; - -static u8 matrox_w1_read_ddc_bit(void *); -static void matrox_w1_write_ddc_bit(void *, u8); - -/* - * These functions read and write DDC Data bit. - * - * Using tristate pins, since i can't find any open-drain pin in whole motherboard. - * Unfortunately we can't connect to Intel's 82801xx IO controller - * since we don't know motherboard schema, wich has pretty unused(may be not) GPIO. - * - * I've heard that PIIX also has open drain pin. - * - * Port mapping. - */ -static __inline__ u8 matrox_w1_read_reg(struct matrox_device *dev, u8 reg) -{ - u8 ret; - - writeb(reg, dev->port_index); - ret = readb(dev->port_data); - barrier(); - - return ret; -} - -static __inline__ void matrox_w1_write_reg(struct matrox_device *dev, u8 reg, u8 val) -{ - writeb(reg, dev->port_index); - writeb(val, dev->port_data); - wmb(); -} - -static void matrox_w1_write_ddc_bit(void *data, u8 bit) -{ - u8 ret; - struct matrox_device *dev = data; - - if (bit) - bit = 0; - else - bit = dev->data_mask; - - ret = matrox_w1_read_reg(dev, MATROX_GET_CONTROL); - matrox_w1_write_reg(dev, MATROX_GET_CONTROL, ((ret & ~dev->data_mask) | bit)); - matrox_w1_write_reg(dev, MATROX_GET_DATA, 0x00); -} - -static u8 matrox_w1_read_ddc_bit(void *data) -{ - u8 ret; - struct matrox_device *dev = data; - - ret = matrox_w1_read_reg(dev, MATROX_GET_DATA); - - return ret; -} - -static void matrox_w1_hw_init(struct matrox_device *dev) -{ - matrox_w1_write_reg(dev, MATROX_GET_DATA, 0xFF); - matrox_w1_write_reg(dev, MATROX_GET_CONTROL, 0x00); -} - -static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct matrox_device *dev; - int err; - - assert(pdev != NULL); - assert(ent != NULL); - - if (pdev->vendor != PCI_VENDOR_ID_MATROX || pdev->device != PCI_DEVICE_ID_MATROX_G400) - return -ENODEV; - - dev = kmalloc(sizeof(struct matrox_device) + - sizeof(struct w1_bus_master), GFP_KERNEL); - if (!dev) { - dev_err(&pdev->dev, - "%s: Failed to create new matrox_device object.\n", - __func__); - return -ENOMEM; - } - - memset(dev, 0, sizeof(struct matrox_device) + sizeof(struct w1_bus_master)); - - dev->bus_master = (struct w1_bus_master *)(dev + 1); - - /* - * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c - */ - - dev->phys_addr = pci_resource_start(pdev, 1); - - dev->virt_addr = ioremap_nocache(dev->phys_addr, 16384); - if (!dev->virt_addr) { - dev_err(&pdev->dev, "%s: failed to ioremap(0x%lx, %d).\n", - __func__, dev->phys_addr, 16384); - err = -EIO; - goto err_out_free_device; - } - - dev->base_addr = dev->virt_addr + MATROX_BASE; - dev->port_index = dev->base_addr + MATROX_PORT_INDEX_OFFSET; - dev->port_data = dev->base_addr + MATROX_PORT_DATA_OFFSET; - dev->data_mask = (MATROX_G400_DDC_DATA); - - matrox_w1_hw_init(dev); - - dev->bus_master->data = dev; - dev->bus_master->read_bit = &matrox_w1_read_ddc_bit; - dev->bus_master->write_bit = &matrox_w1_write_ddc_bit; - - err = w1_add_master_device(dev->bus_master); - if (err) - goto err_out_free_device; - - pci_set_drvdata(pdev, dev); - - dev->found = 1; - - dev_info(&pdev->dev, "Matrox G400 GPIO transport layer for 1-wire.\n"); - - return 0; - -err_out_free_device: - kfree(dev); - - return err; -} - -static void __devexit matrox_w1_remove(struct pci_dev *pdev) -{ - struct matrox_device *dev = pci_get_drvdata(pdev); - - assert(dev != NULL); - - if (dev->found) { - w1_remove_master_device(dev->bus_master); - iounmap(dev->virt_addr); - } - kfree(dev); -} - -static int __init matrox_w1_init(void) -{ - return pci_register_driver(&matrox_w1_pci_driver); -} - -static void __exit matrox_w1_fini(void) -{ - pci_unregister_driver(&matrox_w1_pci_driver); -} - -module_init(matrox_w1_init); -module_exit(matrox_w1_fini); diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig new file mode 100644 index 000000000000..f9d4c91fc533 --- /dev/null +++ b/drivers/w1/slaves/Kconfig @@ -0,0 +1,38 @@ +# +# 1-wire slaves configuration +# + +menu "1-wire Slaves" + depends on W1 + +config W1_SLAVE_THERM + tristate "Thermal family implementation" + depends on W1 + help + Say Y here if you want to connect 1-wire thermal sensors to you + wire. + +config W1_SLAVE_SMEM + tristate "Simple 64bit memory family implementation" + depends on W1 + help + Say Y here if you want to connect 1-wire + simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire. + +config W1_SLAVE_DS2433 + tristate "4kb EEPROM family support (DS2433)" + depends on W1 + help + Say Y here if you want to use a 1-wire + 4kb EEPROM family device (DS2433). + +config W1_SLAVE_DS2433_CRC + bool "Protect DS2433 data with a CRC16" + depends on W1_DS2433 + select CRC16 + help + Say Y here to protect DS2433 data with a CRC16. + Each block has 30 bytes of data and a two byte CRC16. + Full block writes are only allowed if the CRC is valid. + +endmenu diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile new file mode 100644 index 000000000000..70e21e2d70c3 --- /dev/null +++ b/drivers/w1/slaves/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for the Dallas's 1-wire slaves. +# + +ifeq ($(CONFIG_W1_SLAVE_DS2433_CRC), y) +EXTRA_CFLAGS += -DCONFIG_W1_F23_CRC +endif + +obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o +obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o +obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o + diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c new file mode 100644 index 000000000000..fb118be789ea --- /dev/null +++ b/drivers/w1/slaves/w1_ds2433.c @@ -0,0 +1,329 @@ +/* + * w1_ds2433.c - w1 family 23 (DS2433) driver + * + * Copyright (c) 2005 Ben Gardner + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_W1_F23_CRC +#include + +#define CRC16_INIT 0 +#define CRC16_VALID 0xb001 + +#endif + +#include "../w1.h" +#include "../w1_io.h" +#include "../w1_int.h" +#include "../w1_family.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ben Gardner "); +MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM"); + +#define W1_EEPROM_SIZE 512 +#define W1_PAGE_COUNT 16 +#define W1_PAGE_SIZE 32 +#define W1_PAGE_BITS 5 +#define W1_PAGE_MASK 0x1F + +#define W1_F23_TIME 300 + +#define W1_F23_READ_EEPROM 0xF0 +#define W1_F23_WRITE_SCRATCH 0x0F +#define W1_F23_READ_SCRATCH 0xAA +#define W1_F23_COPY_SCRATCH 0x55 + +struct w1_f23_data { + u8 memory[W1_EEPROM_SIZE]; + u32 validcrc; +}; + +/** + * Check the file size bounds and adjusts count as needed. + * This would not be needed if the file size didn't reset to 0 after a write. + */ +static inline size_t w1_f23_fix_count(loff_t off, size_t count, size_t size) +{ + if (off > size) + return 0; + + if ((off + count) > size) + return (size - off); + + return count; +} + +#ifdef CONFIG_W1_F23_CRC +static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data, + int block) +{ + u8 wrbuf[3]; + int off = block * W1_PAGE_SIZE; + + if (data->validcrc & (1 << block)) + return 0; + + if (w1_reset_select_slave(sl)) { + data->validcrc = 0; + return -EIO; + } + + wrbuf[0] = W1_F23_READ_EEPROM; + wrbuf[1] = off & 0xff; + wrbuf[2] = off >> 8; + w1_write_block(sl->master, wrbuf, 3); + w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE); + + /* cache the block if the CRC is valid */ + if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID) + data->validcrc |= (1 << block); + + return 0; +} +#endif /* CONFIG_W1_F23_CRC */ + +static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off, + size_t count) +{ + struct w1_slave *sl = kobj_to_w1_slave(kobj); +#ifdef CONFIG_W1_F23_CRC + struct w1_f23_data *data = sl->family_data; + int i, min_page, max_page; +#else + u8 wrbuf[3]; +#endif + + 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; + } + +#ifdef CONFIG_W1_F23_CRC + + min_page = (off >> W1_PAGE_BITS); + max_page = (off + count - 1) >> W1_PAGE_BITS; + for (i = min_page; i <= max_page; i++) { + if (w1_f23_refresh_block(sl, data, i)) { + count = -EIO; + goto out_up; + } + } + memcpy(buf, &data->memory[off], count); + +#else /* CONFIG_W1_F23_CRC */ + + /* read directly from the EEPROM */ + if (w1_reset_select_slave(sl)) { + count = -EIO; + goto out_up; + } + + wrbuf[0] = W1_F23_READ_EEPROM; + wrbuf[1] = off & 0xff; + wrbuf[2] = off >> 8; + w1_write_block(sl->master, wrbuf, 3); + w1_read_block(sl->master, buf, count); + +#endif /* CONFIG_W1_F23_CRC */ + +out_up: + up(&sl->master->mutex); +out_dec: + atomic_dec(&sl->refcnt); + + return count; +} + +/** + * Writes to the scratchpad and reads it back for verification. + * Then copies the scratchpad to EEPROM. + * The data must be on one page. + * The master must be locked. + * + * @param sl The slave structure + * @param addr Address for the write + * @param len length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK)) + * @param data The data to write + * @return 0=Success -1=failure + */ +static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data) +{ + u8 wrbuf[4]; + u8 rdbuf[W1_PAGE_SIZE + 3]; + u8 es = (addr + len - 1) & 0x1f; + + /* Write the data to the scratchpad */ + if (w1_reset_select_slave(sl)) + return -1; + + wrbuf[0] = W1_F23_WRITE_SCRATCH; + wrbuf[1] = addr & 0xff; + wrbuf[2] = addr >> 8; + + w1_write_block(sl->master, wrbuf, 3); + w1_write_block(sl->master, data, len); + + /* Read the scratchpad and verify */ + if (w1_reset_select_slave(sl)) + return -1; + + w1_write_8(sl->master, W1_F23_READ_SCRATCH); + w1_read_block(sl->master, rdbuf, len + 3); + + /* Compare what was read against the data written */ + if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) || + (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0)) + return -1; + + /* Copy the scratchpad to EEPROM */ + if (w1_reset_select_slave(sl)) + return -1; + + wrbuf[0] = W1_F23_COPY_SCRATCH; + wrbuf[3] = es; + w1_write_block(sl->master, wrbuf, 4); + + /* Sleep for 5 ms to wait for the write to complete */ + msleep(5); + + /* Reset the bus to wake up the EEPROM (this may not be needed) */ + w1_reset_bus(sl->master); + + return 0; +} + +static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off, + size_t count) +{ + struct w1_slave *sl = kobj_to_w1_slave(kobj); + int addr, len, idx; + + if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0) + return 0; + +#ifdef CONFIG_W1_F23_CRC + /* can only write full blocks in cached mode */ + if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) { + dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n", + (int)off, count); + return -EINVAL; + } + + /* make sure the block CRCs are valid */ + for (idx = 0; idx < count; idx += W1_PAGE_SIZE) { + if (crc16(CRC16_INIT, &buf[idx], W1_PAGE_SIZE) != CRC16_VALID) { + dev_err(&sl->dev, "bad CRC at offset %d\n", (int)off); + return -EINVAL; + } + } +#endif /* CONFIG_W1_F23_CRC */ + + atomic_inc(&sl->refcnt); + if (down_interruptible(&sl->master->mutex)) { + count = 0; + goto out_dec; + } + + /* Can only write data to one page at a time */ + idx = 0; + while (idx < count) { + addr = off + idx; + len = W1_PAGE_SIZE - (addr & W1_PAGE_MASK); + if (len > (count - idx)) + len = count - idx; + + if (w1_f23_write(sl, addr, len, &buf[idx]) < 0) { + count = -EIO; + goto out_up; + } + idx += len; + } + +out_up: + up(&sl->master->mutex); +out_dec: + atomic_dec(&sl->refcnt); + + return count; +} + +static struct bin_attribute w1_f23_bin_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUSR, + .owner = THIS_MODULE, + }, + .size = W1_EEPROM_SIZE, + .read = w1_f23_read_bin, + .write = w1_f23_write_bin, +}; + +static int w1_f23_add_slave(struct w1_slave *sl) +{ + int err; +#ifdef CONFIG_W1_F23_CRC + struct w1_f23_data *data; + + data = kmalloc(sizeof(struct w1_f23_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + memset(data, 0, sizeof(struct w1_f23_data)); + sl->family_data = data; + +#endif /* CONFIG_W1_F23_CRC */ + + err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f23_bin_attr); + +#ifdef CONFIG_W1_F23_CRC + if (err) + kfree(data); +#endif /* CONFIG_W1_F23_CRC */ + + return err; +} + +static void w1_f23_remove_slave(struct w1_slave *sl) +{ +#ifdef CONFIG_W1_F23_CRC + kfree(sl->family_data); + sl->family_data = NULL; +#endif /* CONFIG_W1_F23_CRC */ + sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr); +} + +static struct w1_family_ops w1_f23_fops = { + .add_slave = w1_f23_add_slave, + .remove_slave = w1_f23_remove_slave, +}; + +static struct w1_family w1_family_23 = { + .fid = W1_EEPROM_DS2433, + .fops = &w1_f23_fops, +}; + +static int __init w1_f23_init(void) +{ + return w1_register_family(&w1_family_23); +} + +static void __exit w1_f23_fini(void) +{ + w1_unregister_family(&w1_family_23); +} + +module_init(w1_f23_init); +module_exit(w1_f23_fini); diff --git a/drivers/w1/slaves/w1_smem.c b/drivers/w1/slaves/w1_smem.c new file mode 100644 index 000000000000..c6d3be54f94c --- /dev/null +++ b/drivers/w1/slaves/w1_smem.c @@ -0,0 +1,71 @@ +/* + * w1_smem.c + * + * Copyright (c) 2004 Evgeniy Polyakov + * + * + * This program is free software; you can redistribute it and/or modify + * it under the smems 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 "../w1.h" +#include "../w1_io.h" +#include "../w1_int.h" +#include "../w1_family.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Evgeniy Polyakov "); +MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family."); + +static struct w1_family w1_smem_family_01 = { + .fid = W1_FAMILY_SMEM_01, +}; + +static struct w1_family w1_smem_family_81 = { + .fid = W1_FAMILY_SMEM_81, +}; + +static int __init w1_smem_init(void) +{ + int err; + + err = w1_register_family(&w1_smem_family_01); + if (err) + return err; + + err = w1_register_family(&w1_smem_family_81); + if (err) { + w1_unregister_family(&w1_smem_family_01); + return err; + } + + return 0; +} + +static void __exit w1_smem_fini(void) +{ + w1_unregister_family(&w1_smem_family_01); + w1_unregister_family(&w1_smem_family_81); +} + +module_init(w1_smem_init); +module_exit(w1_smem_fini); diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c new file mode 100644 index 000000000000..536d16d78de7 --- /dev/null +++ b/drivers/w1/slaves/w1_therm.c @@ -0,0 +1,268 @@ +/* + * w1_therm.c + * + * Copyright (c) 2004 Evgeniy Polyakov + * + * + * This program is free software; you can redistribute it and/or modify + * it under the therms 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 "../w1.h" +#include "../w1_io.h" +#include "../w1_int.h" +#include "../w1_family.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Evgeniy Polyakov "); +MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family."); + +static u8 bad_roms[][9] = { + {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87}, + {} + }; + +static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t); + +static struct bin_attribute w1_therm_bin_attr = { + .attr = { + .name = "w1_slave", + .mode = S_IRUGO, + .owner = THIS_MODULE, + }, + .size = W1_SLAVE_DATA_SIZE, + .read = w1_therm_read_bin, +}; + +static int w1_therm_add_slave(struct w1_slave *sl) +{ + return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr); +} + +static void w1_therm_remove_slave(struct w1_slave *sl) +{ + sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr); +} + +static struct w1_family_ops w1_therm_fops = { + .add_slave = w1_therm_add_slave, + .remove_slave = w1_therm_remove_slave, +}; + +static struct w1_family w1_therm_family_DS18S20 = { + .fid = W1_THERM_DS18S20, + .fops = &w1_therm_fops, +}; + +static struct w1_family w1_therm_family_DS18B20 = { + .fid = W1_THERM_DS18B20, + .fops = &w1_therm_fops, +}; + +static struct w1_family w1_therm_family_DS1822 = { + .fid = W1_THERM_DS1822, + .fops = &w1_therm_fops, +}; + +struct w1_therm_family_converter +{ + u8 broken; + u16 reserved; + struct w1_family *f; + int (*convert)(u8 rom[9]); +}; + +static inline int w1_DS18B20_convert_temp(u8 rom[9]); +static inline int w1_DS18S20_convert_temp(u8 rom[9]); + +static struct w1_therm_family_converter w1_therm_families[] = { + { + .f = &w1_therm_family_DS18S20, + .convert = w1_DS18S20_convert_temp + }, + { + .f = &w1_therm_family_DS1822, + .convert = w1_DS18B20_convert_temp + }, + { + .f = &w1_therm_family_DS18B20, + .convert = w1_DS18B20_convert_temp + }, +}; + +static inline int w1_DS18B20_convert_temp(u8 rom[9]) +{ + int t = (rom[1] << 8) | rom[0]; + t /= 16; + return t; +} + +static inline int w1_DS18S20_convert_temp(u8 rom[9]) +{ + int t, h; + + if (!rom[7]) + return 0; + + if (rom[1] == 0) + t = ((s32)rom[0] >> 1)*1000; + else + t = 1000*(-1*(s32)(0x100-rom[0]) >> 1); + + t -= 250; + h = 1000*((s32)rom[7] - (s32)rom[6]); + h /= (s32)rom[7]; + t += h; + + return t; +} + +static inline int w1_convert_temp(u8 rom[9], u8 fid) +{ + int i; + + for (i=0; ifid == fid) + return w1_therm_families[i].convert(rom); + + return 0; +} + +static int w1_therm_check_rom(u8 rom[9]) +{ + int i; + + for (i=0; imaster; + 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; + } + + if (off > W1_SLAVE_DATA_SIZE) { + count = 0; + goto out; + } + if (off + count > W1_SLAVE_DATA_SIZE) { + count = 0; + goto out; + } + + memset(buf, 0, count); + memset(rom, 0, sizeof(rom)); + + count = 0; + verdict = 0; + crc = 0; + + while (max_trying--) { + if (!w1_reset_select_slave(sl)) { + int count = 0; + unsigned int tm = 750; + + w1_write_8(dev, W1_CONVERT_TEMP); + + while (tm) { + tm = msleep_interruptible(tm); + if (signal_pending(current)) + flush_signals(current); + } + + if (!w1_reset_select_slave(sl)) { + + w1_write_8(dev, W1_READ_SCRATCHPAD); + if ((count = w1_read_block(dev, rom, 9)) != 9) { + dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count); + } + + crc = w1_calc_crc8(rom, 8); + + if (rom[8] == crc && rom[0]) + verdict = 1; + } + } + + if (!w1_therm_check_rom(rom)) + break; + } + + for (i = 0; i < 9; ++i) + count += sprintf(buf + count, "%02x ", rom[i]); + count += sprintf(buf + count, ": crc=%02x %s\n", + crc, (verdict) ? "YES" : "NO"); + if (verdict) + memcpy(sl->rom, rom, sizeof(sl->rom)); + else + dev_warn(&dev->dev, "18S20 doesn't respond to CONVERT_TEMP.\n"); + + for (i = 0; i < 9; ++i) + count += sprintf(buf + count, "%02x ", sl->rom[i]); + + 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); + + return count; +} + +static int __init w1_therm_init(void) +{ + int err, i; + + for (i=0; i - * - * This source code is licensed under the GNU General Public License, - * Version 2. See the file COPYING for more details. - */ - -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_W1_F23_CRC -#include - -#define CRC16_INIT 0 -#define CRC16_VALID 0xb001 - -#endif - -#include "w1.h" -#include "w1_io.h" -#include "w1_int.h" -#include "w1_family.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ben Gardner "); -MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM"); - -#define W1_EEPROM_SIZE 512 -#define W1_PAGE_COUNT 16 -#define W1_PAGE_SIZE 32 -#define W1_PAGE_BITS 5 -#define W1_PAGE_MASK 0x1F - -#define W1_F23_TIME 300 - -#define W1_F23_READ_EEPROM 0xF0 -#define W1_F23_WRITE_SCRATCH 0x0F -#define W1_F23_READ_SCRATCH 0xAA -#define W1_F23_COPY_SCRATCH 0x55 - -struct w1_f23_data { - u8 memory[W1_EEPROM_SIZE]; - u32 validcrc; -}; - -/** - * Check the file size bounds and adjusts count as needed. - * This would not be needed if the file size didn't reset to 0 after a write. - */ -static inline size_t w1_f23_fix_count(loff_t off, size_t count, size_t size) -{ - if (off > size) - return 0; - - if ((off + count) > size) - return (size - off); - - return count; -} - -#ifdef CONFIG_W1_F23_CRC -static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data, - int block) -{ - u8 wrbuf[3]; - int off = block * W1_PAGE_SIZE; - - if (data->validcrc & (1 << block)) - return 0; - - if (w1_reset_select_slave(sl)) { - data->validcrc = 0; - return -EIO; - } - - wrbuf[0] = W1_F23_READ_EEPROM; - wrbuf[1] = off & 0xff; - wrbuf[2] = off >> 8; - w1_write_block(sl->master, wrbuf, 3); - w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE); - - /* cache the block if the CRC is valid */ - if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID) - data->validcrc |= (1 << block); - - return 0; -} -#endif /* CONFIG_W1_F23_CRC */ - -static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off, - size_t count) -{ - struct w1_slave *sl = kobj_to_w1_slave(kobj); -#ifdef CONFIG_W1_F23_CRC - struct w1_f23_data *data = sl->family_data; - int i, min_page, max_page; -#else - u8 wrbuf[3]; -#endif - - 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; - } - -#ifdef CONFIG_W1_F23_CRC - - min_page = (off >> W1_PAGE_BITS); - max_page = (off + count - 1) >> W1_PAGE_BITS; - for (i = min_page; i <= max_page; i++) { - if (w1_f23_refresh_block(sl, data, i)) { - count = -EIO; - goto out_up; - } - } - memcpy(buf, &data->memory[off], count); - -#else /* CONFIG_W1_F23_CRC */ - - /* read directly from the EEPROM */ - if (w1_reset_select_slave(sl)) { - count = -EIO; - goto out_up; - } - - wrbuf[0] = W1_F23_READ_EEPROM; - wrbuf[1] = off & 0xff; - wrbuf[2] = off >> 8; - w1_write_block(sl->master, wrbuf, 3); - w1_read_block(sl->master, buf, count); - -#endif /* CONFIG_W1_F23_CRC */ - -out_up: - up(&sl->master->mutex); -out_dec: - atomic_dec(&sl->refcnt); - - return count; -} - -/** - * Writes to the scratchpad and reads it back for verification. - * Then copies the scratchpad to EEPROM. - * The data must be on one page. - * The master must be locked. - * - * @param sl The slave structure - * @param addr Address for the write - * @param len length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK)) - * @param data The data to write - * @return 0=Success -1=failure - */ -static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data) -{ - u8 wrbuf[4]; - u8 rdbuf[W1_PAGE_SIZE + 3]; - u8 es = (addr + len - 1) & 0x1f; - - /* Write the data to the scratchpad */ - if (w1_reset_select_slave(sl)) - return -1; - - wrbuf[0] = W1_F23_WRITE_SCRATCH; - wrbuf[1] = addr & 0xff; - wrbuf[2] = addr >> 8; - - w1_write_block(sl->master, wrbuf, 3); - w1_write_block(sl->master, data, len); - - /* Read the scratchpad and verify */ - if (w1_reset_select_slave(sl)) - return -1; - - w1_write_8(sl->master, W1_F23_READ_SCRATCH); - w1_read_block(sl->master, rdbuf, len + 3); - - /* Compare what was read against the data written */ - if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) || - (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0)) - return -1; - - /* Copy the scratchpad to EEPROM */ - if (w1_reset_select_slave(sl)) - return -1; - - wrbuf[0] = W1_F23_COPY_SCRATCH; - wrbuf[3] = es; - w1_write_block(sl->master, wrbuf, 4); - - /* Sleep for 5 ms to wait for the write to complete */ - msleep(5); - - /* Reset the bus to wake up the EEPROM (this may not be needed) */ - w1_reset_bus(sl->master); - - return 0; -} - -static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off, - size_t count) -{ - struct w1_slave *sl = kobj_to_w1_slave(kobj); - int addr, len, idx; - - if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0) - return 0; - -#ifdef CONFIG_W1_F23_CRC - /* can only write full blocks in cached mode */ - if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) { - dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n", - (int)off, count); - return -EINVAL; - } - - /* make sure the block CRCs are valid */ - for (idx = 0; idx < count; idx += W1_PAGE_SIZE) { - if (crc16(CRC16_INIT, &buf[idx], W1_PAGE_SIZE) != CRC16_VALID) { - dev_err(&sl->dev, "bad CRC at offset %d\n", (int)off); - return -EINVAL; - } - } -#endif /* CONFIG_W1_F23_CRC */ - - atomic_inc(&sl->refcnt); - if (down_interruptible(&sl->master->mutex)) { - count = 0; - goto out_dec; - } - - /* Can only write data to one page at a time */ - idx = 0; - while (idx < count) { - addr = off + idx; - len = W1_PAGE_SIZE - (addr & W1_PAGE_MASK); - if (len > (count - idx)) - len = count - idx; - - if (w1_f23_write(sl, addr, len, &buf[idx]) < 0) { - count = -EIO; - goto out_up; - } - idx += len; - } - -out_up: - up(&sl->master->mutex); -out_dec: - atomic_dec(&sl->refcnt); - - return count; -} - -static struct bin_attribute w1_f23_bin_attr = { - .attr = { - .name = "eeprom", - .mode = S_IRUGO | S_IWUSR, - .owner = THIS_MODULE, - }, - .size = W1_EEPROM_SIZE, - .read = w1_f23_read_bin, - .write = w1_f23_write_bin, -}; - -static int w1_f23_add_slave(struct w1_slave *sl) -{ - int err; -#ifdef CONFIG_W1_F23_CRC - struct w1_f23_data *data; - - data = kmalloc(sizeof(struct w1_f23_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - memset(data, 0, sizeof(struct w1_f23_data)); - sl->family_data = data; - -#endif /* CONFIG_W1_F23_CRC */ - - err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f23_bin_attr); - -#ifdef CONFIG_W1_F23_CRC - if (err) - kfree(data); -#endif /* CONFIG_W1_F23_CRC */ - - return err; -} - -static void w1_f23_remove_slave(struct w1_slave *sl) -{ -#ifdef CONFIG_W1_F23_CRC - kfree(sl->family_data); - sl->family_data = NULL; -#endif /* CONFIG_W1_F23_CRC */ - sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr); -} - -static struct w1_family_ops w1_f23_fops = { - .add_slave = w1_f23_add_slave, - .remove_slave = w1_f23_remove_slave, -}; - -static struct w1_family w1_family_23 = { - .fid = W1_EEPROM_DS2433, - .fops = &w1_f23_fops, -}; - -static int __init w1_f23_init(void) -{ - return w1_register_family(&w1_family_23); -} - -static void __exit w1_f23_fini(void) -{ - w1_unregister_family(&w1_family_23); -} - -module_init(w1_f23_init); -module_exit(w1_f23_fini); diff --git a/drivers/w1/w1_smem.c b/drivers/w1/w1_smem.c deleted file mode 100644 index e3209d0aca9b..000000000000 --- a/drivers/w1/w1_smem.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * w1_smem.c - * - * Copyright (c) 2004 Evgeniy Polyakov - * - * - * This program is free software; you can redistribute it and/or modify - * it under the smems 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 "w1.h" -#include "w1_io.h" -#include "w1_int.h" -#include "w1_family.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov "); -MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family."); - -static struct w1_family w1_smem_family_01 = { - .fid = W1_FAMILY_SMEM_01, -}; - -static struct w1_family w1_smem_family_81 = { - .fid = W1_FAMILY_SMEM_81, -}; - -static int __init w1_smem_init(void) -{ - int err; - - err = w1_register_family(&w1_smem_family_01); - if (err) - return err; - - err = w1_register_family(&w1_smem_family_81); - if (err) { - w1_unregister_family(&w1_smem_family_01); - return err; - } - - return 0; -} - -static void __exit w1_smem_fini(void) -{ - w1_unregister_family(&w1_smem_family_01); - w1_unregister_family(&w1_smem_family_81); -} - -module_init(w1_smem_init); -module_exit(w1_smem_fini); diff --git a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c deleted file mode 100644 index 4577df3cfc48..000000000000 --- a/drivers/w1/w1_therm.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * w1_therm.c - * - * Copyright (c) 2004 Evgeniy Polyakov - * - * - * This program is free software; you can redistribute it and/or modify - * it under the therms 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 "w1.h" -#include "w1_io.h" -#include "w1_int.h" -#include "w1_family.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov "); -MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family."); - -static u8 bad_roms[][9] = { - {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87}, - {} - }; - -static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t); - -static struct bin_attribute w1_therm_bin_attr = { - .attr = { - .name = "w1_slave", - .mode = S_IRUGO, - .owner = THIS_MODULE, - }, - .size = W1_SLAVE_DATA_SIZE, - .read = w1_therm_read_bin, -}; - -static int w1_therm_add_slave(struct w1_slave *sl) -{ - return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr); -} - -static void w1_therm_remove_slave(struct w1_slave *sl) -{ - sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr); -} - -static struct w1_family_ops w1_therm_fops = { - .add_slave = w1_therm_add_slave, - .remove_slave = w1_therm_remove_slave, -}; - -static struct w1_family w1_therm_family_DS18S20 = { - .fid = W1_THERM_DS18S20, - .fops = &w1_therm_fops, -}; - -static struct w1_family w1_therm_family_DS18B20 = { - .fid = W1_THERM_DS18B20, - .fops = &w1_therm_fops, -}; - -static struct w1_family w1_therm_family_DS1822 = { - .fid = W1_THERM_DS1822, - .fops = &w1_therm_fops, -}; - -struct w1_therm_family_converter -{ - u8 broken; - u16 reserved; - struct w1_family *f; - int (*convert)(u8 rom[9]); -}; - -static inline int w1_DS18B20_convert_temp(u8 rom[9]); -static inline int w1_DS18S20_convert_temp(u8 rom[9]); - -static struct w1_therm_family_converter w1_therm_families[] = { - { - .f = &w1_therm_family_DS18S20, - .convert = w1_DS18S20_convert_temp - }, - { - .f = &w1_therm_family_DS1822, - .convert = w1_DS18B20_convert_temp - }, - { - .f = &w1_therm_family_DS18B20, - .convert = w1_DS18B20_convert_temp - }, -}; - -static inline int w1_DS18B20_convert_temp(u8 rom[9]) -{ - int t = (rom[1] << 8) | rom[0]; - t /= 16; - return t; -} - -static inline int w1_DS18S20_convert_temp(u8 rom[9]) -{ - int t, h; - - if (!rom[7]) - return 0; - - if (rom[1] == 0) - t = ((s32)rom[0] >> 1)*1000; - else - t = 1000*(-1*(s32)(0x100-rom[0]) >> 1); - - t -= 250; - h = 1000*((s32)rom[7] - (s32)rom[6]); - h /= (s32)rom[7]; - t += h; - - return t; -} - -static inline int w1_convert_temp(u8 rom[9], u8 fid) -{ - int i; - - for (i=0; ifid == fid) - return w1_therm_families[i].convert(rom); - - return 0; -} - -static int w1_therm_check_rom(u8 rom[9]) -{ - int i; - - for (i=0; imaster; - 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; - } - - if (off > W1_SLAVE_DATA_SIZE) { - count = 0; - goto out; - } - if (off + count > W1_SLAVE_DATA_SIZE) { - count = 0; - goto out; - } - - memset(buf, 0, count); - memset(rom, 0, sizeof(rom)); - - count = 0; - verdict = 0; - crc = 0; - - while (max_trying--) { - if (!w1_reset_select_slave(sl)) { - int count = 0; - unsigned int tm = 750; - - w1_write_8(dev, W1_CONVERT_TEMP); - - while (tm) { - tm = msleep_interruptible(tm); - if (signal_pending(current)) - flush_signals(current); - } - - if (!w1_reset_select_slave(sl)) { - - w1_write_8(dev, W1_READ_SCRATCHPAD); - if ((count = w1_read_block(dev, rom, 9)) != 9) { - dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count); - } - - crc = w1_calc_crc8(rom, 8); - - if (rom[8] == crc && rom[0]) - verdict = 1; - } - } - - if (!w1_therm_check_rom(rom)) - break; - } - - for (i = 0; i < 9; ++i) - count += sprintf(buf + count, "%02x ", rom[i]); - count += sprintf(buf + count, ": crc=%02x %s\n", - crc, (verdict) ? "YES" : "NO"); - if (verdict) - memcpy(sl->rom, rom, sizeof(sl->rom)); - else - dev_warn(&dev->dev, "18S20 doesn't respond to CONVERT_TEMP.\n"); - - for (i = 0; i < 9; ++i) - count += sprintf(buf + count, "%02x ", sl->rom[i]); - - 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); - - return count; -} - -static int __init w1_therm_init(void) -{ - int err, i; - - for (i=0; i Date: Tue, 6 Dec 2005 13:38:28 +0300 Subject: [PATCH] W1: Add the DS2482 I2C-to-w1 bridge driver. Signed-off-by: Ben Gardner Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- Documentation/w1/masters/ds2482 | 31 +++ drivers/w1/masters/Kconfig | 10 + drivers/w1/masters/Makefile | 2 + drivers/w1/masters/ds2482.c | 564 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 607 insertions(+) create mode 100644 Documentation/w1/masters/ds2482 create mode 100644 drivers/w1/masters/ds2482.c (limited to 'drivers') diff --git a/Documentation/w1/masters/ds2482 b/Documentation/w1/masters/ds2482 new file mode 100644 index 000000000000..c5d5478d90b2 --- /dev/null +++ b/Documentation/w1/masters/ds2482 @@ -0,0 +1,31 @@ +Kernel driver ds2482 +==================== + +Supported chips: + * Maxim DS2482-100, Maxim DS2482-800 + Prefix: 'ds2482' + Addresses scanned: None + Datasheets: + http://pdfserv.maxim-ic.com/en/ds/DS2482-100-DS2482S-100.pdf + http://pdfserv.maxim-ic.com/en/ds/DS2482-800-DS2482S-800.pdf + +Author: Ben Gardner + + +Description +----------- + +The Maixm/Dallas Semiconductor DS2482 is a I2C device that provides +one (DS2482-100) or eight (DS2482-800) 1-wire busses. + + +General Remarks +--------------- + +Valid addresses are 0x18, 0x19, 0x1a, and 0x1b. +However, the device cannot be detected without writing to the i2c bus, so no +detection is done. +You should force the device address. + +$ modprobe ds2482 force=0,0x18 + diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 51bd64d0e54d..1ff11b5a3ad2 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -34,5 +34,15 @@ config W1_MASTER_DS9490_BRIDGE This support is also available as a module. If so, the module will be called ds_w1_bridge.ko. +config W1_MASTER_DS2482 + tristate "Maxim DS2482 I2C to 1-Wire bridge" + depends on I2C && W1 && EXPERIMENTAL + help + If you say yes here you get support for the Maxim DS2482 + I2C to 1-Wire bridge. + + This driver can also be built as a module. If so, the module + will be called ds2482. + endmenu diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index d9b84e522d6c..1f3c8b983dc1 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -9,3 +9,5 @@ ds9490r-objs := dscore.o obj-$(CONFIG_W1_MASTER_DS9490_BRIDGE) += ds_w1_bridge.o +obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o + diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c new file mode 100644 index 000000000000..d1cacd23576b --- /dev/null +++ b/drivers/w1/masters/ds2482.c @@ -0,0 +1,564 @@ +/** + * ds2482.c - provides i2c to w1-master bridge(s) + * Copyright (C) 2005 Ben Gardner + * + * The DS2482 is a sensor chip made by Dallas Semiconductor (Maxim). + * It is a I2C to 1-wire bridge. + * There are two variations: -100 and -800, which have 1 or 8 1-wire ports. + * The complete datasheet can be obtained from MAXIM's website at: + * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/4382 + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#include "../w1.h" +#include "../w1_int.h" + +/** + * Address is selected using 2 pins, resulting in 4 possible addresses. + * 0x18, 0x19, 0x1a, 0x1b + * However, the chip cannot be detected without doing an i2c write, + * so use the force module parameter. + */ +static unsigned short normal_i2c[] = {I2C_CLIENT_END}; + +/** + * Insmod parameters + */ +I2C_CLIENT_INSMOD_1(ds2482); + +/** + * The DS2482 registers - there are 3 registers that are addressed by a read + * pointer. The read pointer is set by the last command executed. + * + * To read the data, issue a register read for any address + */ +#define DS2482_CMD_RESET 0xF0 /* No param */ +#define DS2482_CMD_SET_READ_PTR 0xE1 /* Param: DS2482_PTR_CODE_xxx */ +#define DS2482_CMD_CHANNEL_SELECT 0xC3 /* Param: Channel byte - DS2482-800 only */ +#define DS2482_CMD_WRITE_CONFIG 0xD2 /* Param: Config byte */ +#define DS2482_CMD_1WIRE_RESET 0xB4 /* Param: None */ +#define DS2482_CMD_1WIRE_SINGLE_BIT 0x87 /* Param: Bit byte (bit7) */ +#define DS2482_CMD_1WIRE_WRITE_BYTE 0xA5 /* Param: Data byte */ +#define DS2482_CMD_1WIRE_READ_BYTE 0x96 /* Param: None */ +/* Note to read the byte, Set the ReadPtr to Data then read (any addr) */ +#define DS2482_CMD_1WIRE_TRIPLET 0x78 /* Param: Dir byte (bit7) */ + +/* Values for DS2482_CMD_SET_READ_PTR */ +#define DS2482_PTR_CODE_STATUS 0xF0 +#define DS2482_PTR_CODE_DATA 0xE1 +#define DS2482_PTR_CODE_CHANNEL 0xD2 /* DS2482-800 only */ +#define DS2482_PTR_CODE_CONFIG 0xC3 + +/** + * Configure Register bit definitions + * The top 4 bits always read 0. + * To write, the top nibble must be the 1's compl. of the low nibble. + */ +#define DS2482_REG_CFG_1WS 0x08 +#define DS2482_REG_CFG_SPU 0x04 +#define DS2482_REG_CFG_PPM 0x02 +#define DS2482_REG_CFG_APU 0x01 + + +/** + * Write and verify codes for the CHANNEL_SELECT command (DS2482-800 only). + * To set the channel, write the value at the index of the channel. + * Read and compare against the corresponding value to verify the change. + */ +static const u8 ds2482_chan_wr[8] = + { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 }; +static const u8 ds2482_chan_rd[8] = + { 0xB8, 0xB1, 0xAA, 0xA3, 0x9C, 0x95, 0x8E, 0x87 }; + + +/** + * Status Register bit definitions (read only) + */ +#define DS2482_REG_STS_DIR 0x80 +#define DS2482_REG_STS_TSB 0x40 +#define DS2482_REG_STS_SBR 0x20 +#define DS2482_REG_STS_RST 0x10 +#define DS2482_REG_STS_LL 0x08 +#define DS2482_REG_STS_SD 0x04 +#define DS2482_REG_STS_PPD 0x02 +#define DS2482_REG_STS_1WB 0x01 + + +static int ds2482_attach_adapter(struct i2c_adapter *adapter); +static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind); +static int ds2482_detach_client(struct i2c_client *client); + + +/** + * Driver data (common to all clients) + */ +static struct i2c_driver ds2482_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "ds2482", + }, + .attach_adapter = ds2482_attach_adapter, + .detach_client = ds2482_detach_client, +}; + +/* + * Client data (each client gets its own) + */ + +struct ds2482_data; + +struct ds2482_w1_chan { + struct ds2482_data *pdev; + u8 channel; + struct w1_bus_master w1_bm; +}; + +struct ds2482_data { + struct i2c_client client; + struct semaphore access_lock; + + /* 1-wire interface(s) */ + int w1_count; /* 1 or 8 */ + struct ds2482_w1_chan w1_ch[8]; + + /* per-device values */ + u8 channel; + u8 read_prt; /* see DS2482_PTR_CODE_xxx */ + u8 reg_config; +}; + + +/** + * Sets the read pointer. + * @param pdev The ds2482 client pointer + * @param read_ptr see DS2482_PTR_CODE_xxx above + * @return -1 on failure, 0 on success + */ +static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr) +{ + if (pdev->read_prt != read_ptr) { + if (i2c_smbus_write_byte_data(&pdev->client, + DS2482_CMD_SET_READ_PTR, + read_ptr) < 0) + return -1; + + pdev->read_prt = read_ptr; + } + return 0; +} + +/** + * Sends a command without a parameter + * @param pdev The ds2482 client pointer + * @param cmd DS2482_CMD_RESET, + * DS2482_CMD_1WIRE_RESET, + * DS2482_CMD_1WIRE_READ_BYTE + * @return -1 on failure, 0 on success + */ +static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd) +{ + if (i2c_smbus_write_byte(&pdev->client, cmd) < 0) + return -1; + + pdev->read_prt = DS2482_PTR_CODE_STATUS; + return 0; +} + +/** + * Sends a command with a parameter + * @param pdev The ds2482 client pointer + * @param cmd DS2482_CMD_WRITE_CONFIG, + * DS2482_CMD_1WIRE_SINGLE_BIT, + * DS2482_CMD_1WIRE_WRITE_BYTE, + * DS2482_CMD_1WIRE_TRIPLET + * @param byte The data to send + * @return -1 on failure, 0 on success + */ +static inline int ds2482_send_cmd_data(struct ds2482_data *pdev, + u8 cmd, u8 byte) +{ + if (i2c_smbus_write_byte_data(&pdev->client, cmd, byte) < 0) + return -1; + + /* all cmds leave in STATUS, except CONFIG */ + pdev->read_prt = (cmd != DS2482_CMD_WRITE_CONFIG) ? + DS2482_PTR_CODE_STATUS : DS2482_PTR_CODE_CONFIG; + return 0; +} + + +/* + * 1-Wire interface code + */ + +#define DS2482_WAIT_IDLE_TIMEOUT 100 + +/** + * Waits until the 1-wire interface is idle (not busy) + * + * @param pdev Pointer to the device structure + * @return the last value read from status or -1 (failure) + */ +static int ds2482_wait_1wire_idle(struct ds2482_data *pdev) +{ + int temp = -1; + int retries = 0; + + if (!ds2482_select_register(pdev, DS2482_PTR_CODE_STATUS)) { + do { + temp = i2c_smbus_read_byte(&pdev->client); + } while ((temp >= 0) && (temp & DS2482_REG_STS_1WB) && + (++retries > DS2482_WAIT_IDLE_TIMEOUT)); + } + + if (retries > DS2482_WAIT_IDLE_TIMEOUT) + printk(KERN_ERR "%s: timeout on channel %d\n", + __func__, pdev->channel); + + return temp; +} + +/** + * Selects a w1 channel. + * The 1-wire interface must be idle before calling this function. + * + * @param pdev The ds2482 client pointer + * @param channel 0-7 + * @return -1 (failure) or 0 (success) + */ +static int ds2482_set_channel(struct ds2482_data *pdev, u8 channel) +{ + if (i2c_smbus_write_byte_data(&pdev->client, DS2482_CMD_CHANNEL_SELECT, + ds2482_chan_wr[channel]) < 0) + return -1; + + pdev->read_prt = DS2482_PTR_CODE_CHANNEL; + pdev->channel = -1; + if (i2c_smbus_read_byte(&pdev->client) == ds2482_chan_rd[channel]) { + pdev->channel = channel; + return 0; + } + return -1; +} + + +/** + * Performs the touch-bit function, which writes a 0 or 1 and reads the level. + * + * @param data The ds2482 channel pointer + * @param bit The level to write: 0 or non-zero + * @return The level read: 0 or 1 + */ +static u8 ds2482_w1_touch_bit(void *data, u8 bit) +{ + struct ds2482_w1_chan *pchan = data; + struct ds2482_data *pdev = pchan->pdev; + int status = -1; + + down(&pdev->access_lock); + + /* Select the channel */ + ds2482_wait_1wire_idle(pdev); + if (pdev->w1_count > 1) + ds2482_set_channel(pdev, pchan->channel); + + /* Send the touch command, wait until 1WB == 0, return the status */ + if (!ds2482_send_cmd_data(pdev, DS2482_CMD_1WIRE_SINGLE_BIT, + bit ? 0xFF : 0)) + status = ds2482_wait_1wire_idle(pdev); + + up(&pdev->access_lock); + + return (status & DS2482_REG_STS_SBR) ? 1 : 0; +} + +/** + * Performs the triplet function, which reads two bits and writes a bit. + * The bit written is determined by the two reads: + * 00 => dbit, 01 => 0, 10 => 1 + * + * @param data The ds2482 channel pointer + * @param dbit The direction to choose if both branches are valid + * @return b0=read1 b1=read2 b3=bit written + */ +static u8 ds2482_w1_triplet(void *data, u8 dbit) +{ + struct ds2482_w1_chan *pchan = data; + struct ds2482_data *pdev = pchan->pdev; + int status = (3 << 5); + + down(&pdev->access_lock); + + /* Select the channel */ + ds2482_wait_1wire_idle(pdev); + if (pdev->w1_count > 1) + ds2482_set_channel(pdev, pchan->channel); + + /* Send the triplet command, wait until 1WB == 0, return the status */ + if (!ds2482_send_cmd_data(pdev, DS2482_CMD_1WIRE_TRIPLET, + dbit ? 0xFF : 0)) + status = ds2482_wait_1wire_idle(pdev); + + up(&pdev->access_lock); + + /* Decode the status */ + return (status >> 5); +} + +/** + * Performs the write byte function. + * + * @param data The ds2482 channel pointer + * @param byte The value to write + */ +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); + + /* Select the channel */ + ds2482_wait_1wire_idle(pdev); + if (pdev->w1_count > 1) + ds2482_set_channel(pdev, pchan->channel); + + /* Send the write byte command */ + ds2482_send_cmd_data(pdev, DS2482_CMD_1WIRE_WRITE_BYTE, byte); + + up(&pdev->access_lock); +} + +/** + * Performs the read byte function. + * + * @param data The ds2482 channel pointer + * @return The value read + */ +static u8 ds2482_w1_read_byte(void *data) +{ + struct ds2482_w1_chan *pchan = data; + struct ds2482_data *pdev = pchan->pdev; + int result; + + down(&pdev->access_lock); + + /* Select the channel */ + ds2482_wait_1wire_idle(pdev); + if (pdev->w1_count > 1) + ds2482_set_channel(pdev, pchan->channel); + + /* Send the read byte command */ + ds2482_send_cmd(pdev, DS2482_CMD_1WIRE_READ_BYTE); + + /* Wait until 1WB == 0 */ + ds2482_wait_1wire_idle(pdev); + + /* Select the data register */ + ds2482_select_register(pdev, DS2482_PTR_CODE_DATA); + + /* Read the data byte */ + result = i2c_smbus_read_byte(&pdev->client); + + up(&pdev->access_lock); + + return result; +} + + +/** + * Sends a reset on the 1-wire interface + * + * @param data The ds2482 channel pointer + * @return 0=Device present, 1=No device present or error + */ +static u8 ds2482_w1_reset_bus(void *data) +{ + struct ds2482_w1_chan *pchan = data; + struct ds2482_data *pdev = pchan->pdev; + int err; + u8 retval = 1; + + down(&pdev->access_lock); + + /* Select the channel */ + ds2482_wait_1wire_idle(pdev); + if (pdev->w1_count > 1) + ds2482_set_channel(pdev, pchan->channel); + + /* Send the reset command */ + err = ds2482_send_cmd(pdev, DS2482_CMD_1WIRE_RESET); + if (err >= 0) { + /* Wait until the reset is complete */ + err = ds2482_wait_1wire_idle(pdev); + retval = !(err & DS2482_REG_STS_PPD); + + /* If the chip did reset since detect, re-config it */ + if (err & DS2482_REG_STS_RST) + ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG, + 0xF0); + } + + up(&pdev->access_lock); + + return retval; +} + + +/** + * Called to see if the device exists on an i2c bus. + */ +static int ds2482_attach_adapter(struct i2c_adapter *adapter) +{ + return i2c_probe(adapter, &addr_data, ds2482_detect); +} + + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct ds2482_data *data; + struct i2c_client *new_client; + int err = 0; + int temp1; + int idx; + + if (!i2c_check_functionality(adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA | + I2C_FUNC_SMBUS_BYTE)) + goto exit; + + if (!(data = kzalloc(sizeof(struct ds2482_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->driver = &ds2482_driver; + new_client->adapter = adapter; + + /* Reset the device (sets the read_ptr to status) */ + if (ds2482_send_cmd(data, DS2482_CMD_RESET) < 0) { + dev_dbg(&adapter->dev, "DS2482 reset failed at 0x%02x.\n", + address); + goto exit_free; + } + + /* Sleep at least 525ns to allow the reset to complete */ + ndelay(525); + + /* Read the status byte - only reset bit and line should be set */ + temp1 = i2c_smbus_read_byte(new_client); + if (temp1 != (DS2482_REG_STS_LL | DS2482_REG_STS_RST)) { + dev_dbg(&adapter->dev, "DS2482 (0x%02x) reset status " + "0x%02X - not a DS2482\n", address, temp1); + goto exit_free; + } + + /* Detect the 8-port version */ + data->w1_count = 1; + if (ds2482_set_channel(data, 7) == 0) + data->w1_count = 8; + + /* Set all config items to 0 (off) */ + ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, 0xF0); + + /* We can fill in the remaining client fields */ + snprintf(new_client->name, sizeof(new_client->name), "ds2482-%d00", + data->w1_count); + + init_MUTEX(&data->access_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + + /* Register 1-wire interface(s) */ + for (idx = 0; idx < data->w1_count; idx++) { + data->w1_ch[idx].pdev = data; + data->w1_ch[idx].channel = idx; + + /* Populate all the w1 bus master stuff */ + data->w1_ch[idx].w1_bm.data = &data->w1_ch[idx]; + data->w1_ch[idx].w1_bm.read_byte = ds2482_w1_read_byte; + data->w1_ch[idx].w1_bm.write_byte = ds2482_w1_write_byte; + data->w1_ch[idx].w1_bm.touch_bit = ds2482_w1_touch_bit; + data->w1_ch[idx].w1_bm.triplet = ds2482_w1_triplet; + data->w1_ch[idx].w1_bm.reset_bus = ds2482_w1_reset_bus; + + err = w1_add_master_device(&data->w1_ch[idx].w1_bm); + if (err) { + data->w1_ch[idx].pdev = NULL; + goto exit_w1_remove; + } + } + + return 0; + +exit_w1_remove: + i2c_detach_client(new_client); + + for (idx = 0; idx < data->w1_count; idx++) { + if (data->w1_ch[idx].pdev != NULL) + w1_remove_master_device(&data->w1_ch[idx].w1_bm); + } +exit_free: + kfree(data); +exit: + return err; +} + +static int ds2482_detach_client(struct i2c_client *client) +{ + struct ds2482_data *data = i2c_get_clientdata(client); + int err, idx; + + /* Unregister the 1-wire bridge(s) */ + for (idx = 0; idx < data->w1_count; idx++) { + if (data->w1_ch[idx].pdev != NULL) + w1_remove_master_device(&data->w1_ch[idx].w1_bm); + } + + /* Detach the i2c device */ + if ((err = i2c_detach_client(client))) { + dev_err(&client->dev, + "Deregistration failed, client not detached.\n"); + return err; + } + + /* Free the memory */ + kfree(data); + return 0; +} + +static int __init sensors_ds2482_init(void) +{ + return i2c_add_driver(&ds2482_driver); +} + +static void __exit sensors_ds2482_exit(void) +{ + i2c_del_driver(&ds2482_driver); +} + +MODULE_AUTHOR("Ben Gardner "); +MODULE_DESCRIPTION("DS2482 driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_ds2482_init); +module_exit(sensors_ds2482_exit); -- cgit v1.2.3-59-g8ed1b From a9fb1c7b950bed4afe208c9d67e20f086bb6abbb Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 13 Dec 2005 14:04:33 -0800 Subject: [PATCH] w1: misc cleanups This patch contains the following cleanups: - make needlessly global code static - declarations for global code belong into header files - w1.c: #if 0 the unused struct w1_slave_device Signed-off-by: Adrian Bunk Acked-by: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 6 ++++-- drivers/w1/w1.h | 10 ++++++++++ drivers/w1/w1_family.c | 2 +- drivers/w1/w1_int.c | 13 ++----------- drivers/w1/w1_io.c | 2 +- 5 files changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index f0b47fe4ed25..5def7fb903ac 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -164,11 +164,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, @@ -176,6 +177,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) { @@ -355,7 +357,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 b62e771e5709..5f09213512bf 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -203,6 +203,16 @@ 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.c b/drivers/w1/w1_family.c index 9e293e139a0e..0e32c114f906 100644 --- a/drivers/w1/w1_family.c +++ b/drivers/w1/w1_family.c @@ -25,10 +25,10 @@ #include #include "w1_family.h" +#include "w1.h" DEFINE_SPINLOCK(w1_flock); static LIST_HEAD(w1_families); -extern void w1_reconnect_slaves(struct w1_family *f); int w1_register_family(struct w1_family *newf) { diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index c3f67eafc7ec..4724693ad51d 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -26,19 +26,10 @@ #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 spinlock_t 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) @@ -103,7 +94,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); } diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index e2a043354ddf..f7f7e8bec30e 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c @@ -28,7 +28,7 @@ #include "w1_log.h" #include "w1_io.h" -int w1_delay_parm = 1; +static int w1_delay_parm = 1; module_param_named(delay_coef, w1_delay_parm, int, 0); static u8 w1_crc8_table[] = { -- cgit v1.2.3-59-g8ed1b From ec068072f0e8499cfe7b71749b4a63c503e7d328 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 6 Jan 2006 18:41:01 +0100 Subject: [PATCH] fix W1_MASTER_DS9490_BRIDGE dependencies W1_DS9490 was renamed to W1_MASTER_DS9490, but the entry in the dependencies of W1_MASTER_DS9490_BRIDGE was forgotten. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 1ff11b5a3ad2..c6bad4dbdc64 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -26,7 +26,7 @@ config W1_MASTER_DS9490 config W1_MASTER_DS9490_BRIDGE tristate "DS9490R USB <-> W1 transport layer for 1-wire" - depends on W1_DS9490 + depends on W1_MASTER_DS9490 help Say Y here if you want to communicate with your 1-wire devices using DS9490R USB bridge. -- cgit v1.2.3-59-g8ed1b From ecd5136c85cb4531a51f65241e7b3cd58420f3ed Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 8 Jan 2006 00:44:15 +0100 Subject: [PATCH] W1: Remove incorrect MODULE_ALIAS The w1 netlink socket is created by a hardware specific driver calling w1_add_master_device, so there is no point in including a module alias for netlink autoloading in the core. Signed-off-by: Patrick McHardy Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1_int.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 4724693ad51d..a2f9065e1928 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -208,5 +208,3 @@ void w1_remove_master_device(struct w1_bus_master *bm) EXPORT_SYMBOL(w1_add_master_device); EXPORT_SYMBOL(w1_remove_master_device); - -MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_W1); -- cgit v1.2.3-59-g8ed1b From f73b5e7949945486a649e40821cd351e2f60bf02 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 14 Jan 2006 00:05:59 -0800 Subject: [PATCH] W1: u64 is not long long You don't know what type a u64 is, hence you cannot print it without a cast. Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 5def7fb903ac..d640c1e1f8cd 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -388,11 +388,14 @@ 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", (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; -- cgit v1.2.3-59-g8ed1b From 674a396c6d2ba0341ebdd7c1c9950f32f018e2dd Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Mon, 20 Feb 2006 11:15:37 +0300 Subject: [PATCH] w1: use kthread api. This patch removes old-style kernel thread initialization and changes w1 to use kthread api. It is based on Christoph Hellwig work. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 56 +++++++++++++++-------------------------------------- drivers/w1/w1.h | 3 +-- drivers/w1/w1_int.c | 34 +++++++++++--------------------- 3 files changed, 28 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index d640c1e1f8cd..a698b517e863 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -57,9 +58,7 @@ module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); DEFINE_SPINLOCK(w1_mlock); LIST_HEAD(w1_masters); -static pid_t control_thread; -static int control_needs_exit; -static DECLARE_COMPLETION(w1_control_complete); +static struct task_struct *w1_control_thread; static int w1_master_match(struct device *dev, struct device_driver *drv) { @@ -717,22 +716,16 @@ static int w1_control(void *data) { struct w1_slave *sl, *sln; struct w1_master *dev, *n; - int err, have_to_wait = 0; + int have_to_wait = 0; - daemonize("w1_control"); - allow_signal(SIGTERM); - - while (!control_needs_exit || have_to_wait) { + while (!kthread_should_stop() || have_to_wait) { have_to_wait = 0; try_to_freeze(); msleep_interruptible(w1_control_timeout * 1000); - if (signal_pending(current)) - flush_signals(current); - list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) { - if (!control_needs_exit && !dev->flags) + if (!kthread_should_stop() && !dev->flags) continue; /* * Little race: we can create thread but not set the flag. @@ -743,21 +736,12 @@ static int w1_control(void *data) continue; } - if (control_needs_exit) { + if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { set_bit(W1_MASTER_NEED_EXIT, &dev->flags); - err = kill_proc(dev->kpid, SIGTERM, 1); - if (err) - dev_err(&dev->dev, - "Failed to send signal to w1 kernel thread %d.\n", - dev->kpid); - } - - if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { - wait_for_completion(&dev->dev_exited); - spin_lock_bh(&w1_mlock); + spin_lock(&w1_mlock); list_del(&dev->w1_master_entry); - spin_unlock_bh(&w1_mlock); + spin_unlock(&w1_mlock); down(&dev->mutex); list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { @@ -789,7 +773,7 @@ static int w1_control(void *data) } } - complete_and_exit(&w1_control_complete, 0); + return 0; } int w1_process(void *data) @@ -797,17 +781,11 @@ int w1_process(void *data) struct w1_master *dev = (struct w1_master *) data; struct w1_slave *sl, *sln; - daemonize("%s", dev->name); - allow_signal(SIGTERM); - - while (!test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { + while (!kthread_should_stop() && !test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) { try_to_freeze(); msleep_interruptible(w1_timeout * 1000); - if (signal_pending(current)) - flush_signals(current); - - if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) + if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) break; if (!dev->initialized) @@ -840,7 +818,6 @@ int w1_process(void *data) } atomic_dec(&dev->refcnt); - complete_and_exit(&dev->dev_exited, 0); return 0; } @@ -873,11 +850,11 @@ static int w1_init(void) goto err_out_master_unregister; } - control_thread = kernel_thread(&w1_control, NULL, 0); - if (control_thread < 0) { + w1_control_thread = kthread_run(w1_control, NULL, "w1_control"); + if (IS_ERR(w1_control_thread)) { + retval = PTR_ERR(w1_control_thread); printk(KERN_ERR "Failed to create control thread. err=%d\n", - control_thread); - retval = control_thread; + retval); goto err_out_slave_unregister; } @@ -903,8 +880,7 @@ static void w1_fini(void) list_for_each_entry(dev, &w1_masters, w1_master_entry) __w1_remove_master_device(dev); - control_needs_exit = 1; - wait_for_completion(&w1_control_complete); + kthread_stop(w1_control_thread); driver_unregister(&w1_slave_driver); driver_unregister(&w1_master_driver); diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 5f09213512bf..56980505e6c4 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -172,12 +172,11 @@ struct w1_master long flags; - pid_t kpid; + struct task_struct *thread; struct semaphore mutex; struct device_driver *driver; struct device dev; - struct completion dev_exited; struct w1_bus_master *bus_master; diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index a2f9065e1928..68565aacec7b 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "w1.h" #include "w1_log.h" @@ -56,7 +57,6 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, dev->max_slave_count = slave_count; dev->slave_count = 0; dev->attempts = 0; - dev->kpid = -1; dev->initialized = 0; dev->id = id; dev->slave_ttl = slave_ttl; @@ -67,8 +67,6 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, INIT_LIST_HEAD(&dev->slist); init_MUTEX(&dev->mutex); - init_completion(&dev->dev_exited); - memcpy(&dev->dev, device, sizeof(struct device)); snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), "w1_bus_master%u", dev->id); @@ -116,12 +114,12 @@ int w1_add_master_device(struct w1_bus_master *master) if (!dev) return -ENOMEM; - dev->kpid = kernel_thread(&w1_process, dev, 0); - if (dev->kpid < 0) { + dev->thread = kthread_run(&w1_process, dev, "%s", dev->name); + if (IS_ERR(dev->thread)) { + retval = PTR_ERR(dev->thread); dev_err(&dev->dev, "Failed to create new kernel thread. err=%d\n", - dev->kpid); - retval = dev->kpid; + retval); goto err_out_free_dev; } @@ -138,20 +136,14 @@ int w1_add_master_device(struct w1_bus_master *master) spin_unlock(&w1_mlock); msg.id.mst.id = dev->id; - msg.id.mst.pid = dev->kpid; + msg.id.mst.pid = dev->thread->pid; msg.type = W1_MASTER_ADD; w1_netlink_send(dev, &msg); return 0; err_out_kill_thread: - set_bit(W1_MASTER_NEED_EXIT, &dev->flags); - if (kill_proc(dev->kpid, SIGTERM, 1)) - dev_err(&dev->dev, - "Failed to send signal to w1 kernel thread %d.\n", - dev->kpid); - wait_for_completion(&dev->dev_exited); - + kthread_stop(dev->thread); err_out_free_dev: w1_free_dev(dev); @@ -160,18 +152,14 @@ err_out_free_dev: void __w1_remove_master_device(struct w1_master *dev) { - int err; struct w1_netlink_msg msg; + pid_t pid = dev->thread->pid; set_bit(W1_MASTER_NEED_EXIT, &dev->flags); - err = kill_proc(dev->kpid, SIGTERM, 1); - if (err) - dev_err(&dev->dev, - "%s: Failed to send signal to w1 kernel thread %d.\n", - __func__, dev->kpid); + kthread_stop(dev->thread); while (atomic_read(&dev->refcnt)) { - dev_dbg(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n", + dev_info(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n", dev->name, atomic_read(&dev->refcnt)); if (msleep_interruptible(1000)) @@ -179,7 +167,7 @@ void __w1_remove_master_device(struct w1_master *dev) } msg.id.mst.id = dev->id; - msg.id.mst.pid = dev->kpid; + msg.id.mst.pid = pid; msg.type = W1_MASTER_REMOVE; w1_netlink_send(dev, &msg); -- cgit v1.2.3-59-g8ed1b From 50bba752ca0a740a6ba9eb96d61ef7bbdfe405cf Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Thu, 19 Jan 2006 12:37:24 -0500 Subject: [PATCH] aoe [1/8]: zero packet data after skb allocation Zero the data in new socket buffers to prevent leaking information. Signed-off-by: "Ed L. Cashin" Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoecmd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 326ca3876b68..4ab01ce5cf36 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -28,6 +28,7 @@ new_skb(struct net_device *if_dev, ulong len) skb->protocol = __constant_htons(ETH_P_AOE); skb->priority = 0; skb_put(skb, len); + memset(skb->head, 0, len); skb->next = skb->prev = NULL; /* tell the network layer not to perform IP checksums -- cgit v1.2.3-59-g8ed1b From 3ae1c24e395b2b65326439622223d88d92bfa03a Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Thu, 19 Jan 2006 13:46:19 -0500 Subject: [PATCH] aoe [2/8]: support dynamic resizing of AoE devices Allow the driver to recognize AoE devices that have changed size. Devices not in use are updated automatically, and devices that are in use are updated at user request. Signed-off-by: "Ed L. Cashin" Signed-off-by: Greg Kroah-Hartman --- Documentation/aoe/mkdevs.sh | 2 + Documentation/aoe/udev.txt | 1 + drivers/block/aoe/aoe.h | 12 +-- drivers/block/aoe/aoeblk.c | 22 +++--- drivers/block/aoe/aoechr.c | 37 +++++++++ drivers/block/aoe/aoecmd.c | 177 +++++++++++++++++++++++++++++--------------- drivers/block/aoe/aoedev.c | 69 +++++++++++------ 7 files changed, 223 insertions(+), 97 deletions(-) (limited to 'drivers') diff --git a/Documentation/aoe/mkdevs.sh b/Documentation/aoe/mkdevs.sh index ec5a6de1cd7b..97374aacacb2 100644 --- a/Documentation/aoe/mkdevs.sh +++ b/Documentation/aoe/mkdevs.sh @@ -27,6 +27,8 @@ rm -f $dir/discover mknod -m 0200 $dir/discover c $MAJOR 3 rm -f $dir/interfaces mknod -m 0200 $dir/interfaces c $MAJOR 4 +rm -f $dir/revalidate +mknod -m 0200 $dir/revalidate c $MAJOR 5 export n_partitions mkshelf=`echo $0 | sed 's!mkdevs!mkshelf!'` diff --git a/Documentation/aoe/udev.txt b/Documentation/aoe/udev.txt index ab39d8bb634c..a7ed1dc4f331 100644 --- a/Documentation/aoe/udev.txt +++ b/Documentation/aoe/udev.txt @@ -18,6 +18,7 @@ SUBSYSTEM="aoe", KERNEL="discover", NAME="etherd/%k", GROUP="disk", MODE="0220" SUBSYSTEM="aoe", KERNEL="err", NAME="etherd/%k", GROUP="disk", MODE="0440" SUBSYSTEM="aoe", KERNEL="interfaces", NAME="etherd/%k", GROUP="disk", MODE="0220" +SUBSYSTEM="aoe", KERNEL="revalidate", NAME="etherd/%k", GROUP="disk", MODE="0220" # aoe block devices KERNEL="etherd*", NAME="%k", GROUP="disk" diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 881c48d941b7..bb7dd91e5d48 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -75,8 +75,9 @@ enum { DEVFL_TKILL = (1<<1), /* flag for timer to know when to kill self */ DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ DEVFL_CLOSEWAIT = (1<<3), /* device is waiting for all closes to revalidate */ - DEVFL_WC_UPDATE = (1<<4), /* this device needs to update write cache status */ - DEVFL_WORKON = (1<<4), + DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */ + DEVFL_PAUSE = (1<<5), + DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ BUFFL_FAIL = 1, }; @@ -152,16 +153,17 @@ void aoechr_exit(void); void aoechr_error(char *); void aoecmd_work(struct aoedev *d); -void aoecmd_cfg(ushort, unsigned char); +void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); void aoecmd_ata_rsp(struct sk_buff *); void aoecmd_cfg_rsp(struct sk_buff *); +void aoecmd_sleepwork(void *vp); int aoedev_init(void); void aoedev_exit(void); struct aoedev *aoedev_by_aoeaddr(int maj, int min); +struct aoedev *aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt); void aoedev_downdev(struct aoedev *d); -struct aoedev *aoedev_set(ulong, unsigned char *, struct net_device *, ulong); -int aoedev_busy(void); +int aoedev_isbusy(struct aoedev *d); int aoenet_init(void); void aoenet_exit(void); diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index c05ee8bffd97..039c0911fa8f 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -22,7 +22,9 @@ static ssize_t aoedisk_show_state(struct gendisk * disk, char *page) return snprintf(page, PAGE_SIZE, "%s%s\n", (d->flags & DEVFL_UP) ? "up" : "down", - (d->flags & DEVFL_CLOSEWAIT) ? ",closewait" : ""); + (d->flags & DEVFL_PAUSE) ? ",paused" : + (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : ""); + /* I'd rather see nopen exported so we can ditch closewait */ } static ssize_t aoedisk_show_mac(struct gendisk * disk, char *page) { @@ -107,8 +109,7 @@ aoeblk_release(struct inode *inode, struct file *filp) spin_lock_irqsave(&d->lock, flags); - if (--d->nopen == 0 && (d->flags & DEVFL_CLOSEWAIT)) { - d->flags &= ~DEVFL_CLOSEWAIT; + if (--d->nopen == 0 && !(d->flags & DEVFL_UP)) { spin_unlock_irqrestore(&d->lock, flags); aoecmd_cfg(d->aoemajor, d->aoeminor); return 0; @@ -158,14 +159,14 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) } list_add_tail(&buf->bufs, &d->bufq); - aoecmd_work(d); + aoecmd_work(d); sl = d->sendq_hd; d->sendq_hd = d->sendq_tl = NULL; spin_unlock_irqrestore(&d->lock, flags); - aoenet_xmit(sl); + return 0; } @@ -205,7 +206,7 @@ aoeblk_gdalloc(void *vp) printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate disk " "structure for %ld.%ld\n", d->aoemajor, d->aoeminor); spin_lock_irqsave(&d->lock, flags); - d->flags &= ~DEVFL_WORKON; + d->flags &= ~DEVFL_GDALLOC; spin_unlock_irqrestore(&d->lock, flags); return; } @@ -218,7 +219,7 @@ aoeblk_gdalloc(void *vp) "for %ld.%ld\n", d->aoemajor, d->aoeminor); put_disk(gd); spin_lock_irqsave(&d->lock, flags); - d->flags &= ~DEVFL_WORKON; + d->flags &= ~DEVFL_GDALLOC; spin_unlock_irqrestore(&d->lock, flags); return; } @@ -235,18 +236,13 @@ aoeblk_gdalloc(void *vp) gd->queue = &d->blkq; d->gd = gd; - d->flags &= ~DEVFL_WORKON; + d->flags &= ~DEVFL_GDALLOC; d->flags |= DEVFL_UP; spin_unlock_irqrestore(&d->lock, flags); add_disk(gd); aoedisk_add_sysfs(d); - - printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu " - "sectors\n", (unsigned long long)mac_addr(d->addr), - d->aoemajor, d->aoeminor, - d->fw_ver, (long long)d->ssize); } void diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 41ae0ede619a..5327f553b4f5 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -13,6 +13,7 @@ enum { MINOR_ERR = 2, MINOR_DISCOVER, MINOR_INTERFACES, + MINOR_REVALIDATE, MSGSZ = 2048, NARGS = 10, NMSG = 100, /* message backlog to retain */ @@ -41,6 +42,7 @@ static struct aoe_chardev chardevs[] = { { MINOR_ERR, "err" }, { MINOR_DISCOVER, "discover" }, { MINOR_INTERFACES, "interfaces" }, + { MINOR_REVALIDATE, "revalidate" }, }; static int @@ -62,6 +64,39 @@ interfaces(const char __user *str, size_t size) return 0; } +static int +revalidate(const char __user *str, size_t size) +{ + int major, minor, n; + ulong flags; + struct aoedev *d; + char buf[16]; + + if (size >= sizeof buf) + return -EINVAL; + buf[sizeof buf - 1] = '\0'; + if (copy_from_user(buf, str, size)) + return -EFAULT; + + /* should be e%d.%d format */ + n = sscanf(buf, "e%d.%d", &major, &minor); + if (n != 2) { + printk(KERN_ERR "aoe: %s: invalid device specification\n", + __FUNCTION__); + return -EINVAL; + } + d = aoedev_by_aoeaddr(major, minor); + if (!d) + return -EINVAL; + + spin_lock_irqsave(&d->lock, flags); + d->flags |= DEVFL_PAUSE; + spin_unlock_irqrestore(&d->lock, flags); + aoecmd_cfg(major, minor); + + return 0; +} + void aoechr_error(char *msg) { @@ -114,6 +149,8 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp case MINOR_INTERFACES: ret = interfaces(buf, cnt); break; + case MINOR_REVALIDATE: + ret = revalidate(buf, cnt); } if (ret == 0) ret = cnt; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 4ab01ce5cf36..150eb78cd5a9 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "aoe.h" @@ -189,12 +190,67 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) } } +/* some callers cannot sleep, and they can call this function, + * transmitting the packets later, when interrupts are on + */ +static struct sk_buff * +aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) +{ + struct aoe_hdr *h; + struct aoe_cfghdr *ch; + struct sk_buff *skb, *sl, *sl_tail; + struct net_device *ifp; + + sl = sl_tail = NULL; + + read_lock(&dev_base_lock); + for (ifp = dev_base; ifp; dev_put(ifp), ifp = ifp->next) { + dev_hold(ifp); + if (!is_aoe_netif(ifp)) + continue; + + skb = new_skb(ifp, sizeof *h + sizeof *ch); + if (skb == NULL) { + printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n"); + continue; + } + if (sl_tail == NULL) + sl_tail = skb; + h = (struct aoe_hdr *) skb->mac.raw; + memset(h, 0, sizeof *h + sizeof *ch); + + memset(h->dst, 0xff, sizeof h->dst); + memcpy(h->src, ifp->dev_addr, sizeof h->src); + h->type = __constant_cpu_to_be16(ETH_P_AOE); + h->verfl = AOE_HVER; + h->major = cpu_to_be16(aoemajor); + h->minor = aoeminor; + h->cmd = AOECMD_CFG; + + skb->next = sl; + sl = skb; + } + read_unlock(&dev_base_lock); + + if (tail != NULL) + *tail = sl_tail; + return sl; +} + /* enters with d->lock held */ void aoecmd_work(struct aoedev *d) { struct frame *f; struct buf *buf; + + if (d->flags & DEVFL_PAUSE) { + if (!aoedev_isbusy(d)) + d->sendq_hd = aoecmd_cfg_pkts(d->aoemajor, + d->aoeminor, &d->sendq_tl); + return; + } + loop: f = getframe(d, FREETAG); if (f == NULL) @@ -306,6 +362,37 @@ tdie: spin_unlock_irqrestore(&d->lock, flags); aoenet_xmit(sl); } +/* this function performs work that has been deferred until sleeping is OK + */ +void +aoecmd_sleepwork(void *vp) +{ + struct aoedev *d = (struct aoedev *) vp; + + if (d->flags & DEVFL_GDALLOC) + aoeblk_gdalloc(d); + + if (d->flags & DEVFL_NEWSIZE) { + struct block_device *bd; + unsigned long flags; + u64 ssize; + + ssize = d->gd->capacity; + bd = bdget_disk(d->gd, 0); + + if (bd) { + mutex_lock(&bd->bd_inode->i_mutex); + i_size_write(bd->bd_inode, (loff_t)ssize<<9); + mutex_unlock(&bd->bd_inode->i_mutex); + bdput(bd); + } + spin_lock_irqsave(&d->lock, flags); + d->flags |= DEVFL_UP; + d->flags &= ~DEVFL_NEWSIZE; + spin_unlock_irqrestore(&d->lock, flags); + } +} + static void ataid_complete(struct aoedev *d, unsigned char *id) { @@ -340,21 +427,29 @@ ataid_complete(struct aoedev *d, unsigned char *id) d->geo.heads = le16_to_cpu(get_unaligned((__le16 *) &id[55<<1])); d->geo.sectors = le16_to_cpu(get_unaligned((__le16 *) &id[56<<1])); } + + if (d->ssize != ssize) + printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu " + "sectors\n", (unsigned long long)mac_addr(d->addr), + d->aoemajor, d->aoeminor, + d->fw_ver, (long long)ssize); d->ssize = ssize; d->geo.start = 0; if (d->gd != NULL) { d->gd->capacity = ssize; - d->flags |= DEVFL_UP; - return; - } - if (d->flags & DEVFL_WORKON) { - printk(KERN_INFO "aoe: ataid_complete: can't schedule work, it's already on! " - "(This really shouldn't happen).\n"); - return; + d->flags |= DEVFL_NEWSIZE; + } else { + if (d->flags & DEVFL_GDALLOC) { + printk(KERN_INFO "aoe: %s: %s e%lu.%lu, %s\n", + __FUNCTION__, + "can't schedule work for", + d->aoemajor, d->aoeminor, + "it's already on! (This really shouldn't happen).\n"); + return; + } + d->flags |= DEVFL_GDALLOC; } - INIT_WORK(&d->work, aoeblk_gdalloc, d); schedule_work(&d->work); - d->flags |= DEVFL_WORKON; } static void @@ -452,7 +547,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) return; } ataid_complete(d, (char *) (ahin+1)); - /* d->flags |= DEVFL_WC_UPDATE; */ + d->flags &= ~DEVFL_PAUSE; break; default: printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized " @@ -485,51 +580,19 @@ aoecmd_ata_rsp(struct sk_buff *skb) f->tag = FREETAG; aoecmd_work(d); - sl = d->sendq_hd; d->sendq_hd = d->sendq_tl = NULL; spin_unlock_irqrestore(&d->lock, flags); - aoenet_xmit(sl); } void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor) { - struct aoe_hdr *h; - struct aoe_cfghdr *ch; - struct sk_buff *skb, *sl; - struct net_device *ifp; - - sl = NULL; - - read_lock(&dev_base_lock); - for (ifp = dev_base; ifp; dev_put(ifp), ifp = ifp->next) { - dev_hold(ifp); - if (!is_aoe_netif(ifp)) - continue; - - skb = new_skb(ifp, sizeof *h + sizeof *ch); - if (skb == NULL) { - printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n"); - continue; - } - h = (struct aoe_hdr *) skb->mac.raw; - memset(h, 0, sizeof *h + sizeof *ch); - - memset(h->dst, 0xff, sizeof h->dst); - memcpy(h->src, ifp->dev_addr, sizeof h->src); - h->type = __constant_cpu_to_be16(ETH_P_AOE); - h->verfl = AOE_HVER; - h->major = cpu_to_be16(aoemajor); - h->minor = aoeminor; - h->cmd = AOECMD_CFG; + struct sk_buff *sl; - skb->next = sl; - sl = skb; - } - read_unlock(&dev_base_lock); + sl = aoecmd_cfg_pkts(aoemajor, aoeminor, NULL); aoenet_xmit(sl); } @@ -562,9 +625,6 @@ aoecmd_ata_id(struct aoedev *d) f->waited = 0; f->writedatalen = 0; - /* this message initializes the device, so we reset the rttavg */ - d->rttavg = MAXTIMER; - /* set up ata header */ ah->scnt = 1; ah->cmdstat = WIN_IDENTIFY; @@ -572,12 +632,8 @@ aoecmd_ata_id(struct aoedev *d) skb = skb_prepare(d, f); - /* we now want to start the rexmit tracking */ - d->flags &= ~DEVFL_TKILL; - d->timer.data = (ulong) d; + d->rttavg = MAXTIMER; d->timer.function = rexmit_timer; - d->timer.expires = jiffies + TIMERTICK; - add_timer(&d->timer); return skb; } @@ -619,23 +675,28 @@ aoecmd_cfg_rsp(struct sk_buff *skb) if (bufcnt > MAXFRAMES) /* keep it reasonable */ bufcnt = MAXFRAMES; - d = aoedev_set(sysminor, h->src, skb->dev, bufcnt); + d = aoedev_by_sysminor_m(sysminor, bufcnt); if (d == NULL) { - printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device set failure\n"); + printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n"); return; } spin_lock_irqsave(&d->lock, flags); - if (d->flags & (DEVFL_UP | DEVFL_CLOSEWAIT)) { + /* permit device to migrate mac and network interface */ + d->ifp = skb->dev; + memcpy(d->addr, h->src, sizeof d->addr); + + /* don't change users' perspective */ + if (d->nopen && !(d->flags & DEVFL_PAUSE)) { spin_unlock_irqrestore(&d->lock, flags); return; } - + d->flags |= DEVFL_PAUSE; /* force pause */ d->fw_ver = be16_to_cpu(ch->fwver); - /* we get here only if the device is new */ - sl = aoecmd_ata_id(d); + /* check for already outstanding ataid */ + sl = aoedev_isbusy(d) == 0 ? aoecmd_ata_id(d) : NULL; spin_unlock_irqrestore(&d->lock, flags); diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index ded33ba31acc..ed4258a62df5 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -12,6 +12,24 @@ static struct aoedev *devlist; static spinlock_t devlist_lock; +int +aoedev_isbusy(struct aoedev *d) +{ + struct frame *f, *e; + + f = d->frames; + e = f + d->nframes; + do { + if (f->tag != FREETAG) { + printk(KERN_DEBUG "aoe: %ld.%ld isbusy\n", + d->aoemajor, d->aoeminor); + return 1; + } + } while (++f < e); + + return 0; +} + struct aoedev * aoedev_by_aoeaddr(int maj, int min) { @@ -28,6 +46,18 @@ aoedev_by_aoeaddr(int maj, int min) return d; } +static void +dummy_timer(ulong vp) +{ + struct aoedev *d; + + d = (struct aoedev *)vp; + if (d->flags & DEVFL_TKILL) + return; + d->timer.expires = jiffies + HZ; + add_timer(&d->timer); +} + /* called with devlist lock held */ static struct aoedev * aoedev_newdev(ulong nframes) @@ -44,6 +74,8 @@ aoedev_newdev(ulong nframes) return NULL; } + INIT_WORK(&d->work, aoecmd_sleepwork, d); + d->nframes = nframes; d->frames = f; e = f + nframes; @@ -52,6 +84,10 @@ aoedev_newdev(ulong nframes) spin_lock_init(&d->lock); init_timer(&d->timer); + d->timer.data = (ulong) d; + d->timer.function = dummy_timer; + d->timer.expires = jiffies + HZ; + add_timer(&d->timer); d->bufpool = NULL; /* defer to aoeblk_gdalloc */ INIT_LIST_HEAD(&d->bufq); d->next = devlist; @@ -67,9 +103,6 @@ aoedev_downdev(struct aoedev *d) struct buf *buf; struct bio *bio; - d->flags |= DEVFL_TKILL; - del_timer(&d->timer); - f = d->frames; e = f + d->nframes; for (; ftag = FREETAG, f->buf = NULL, f++) { @@ -92,16 +125,15 @@ aoedev_downdev(struct aoedev *d) bio_endio(bio, bio->bi_size, -EIO); } - if (d->nopen) - d->flags |= DEVFL_CLOSEWAIT; if (d->gd) d->gd->capacity = 0; - d->flags &= ~DEVFL_UP; + d->flags &= ~(DEVFL_UP | DEVFL_PAUSE); } +/* find it or malloc it */ struct aoedev * -aoedev_set(ulong sysminor, unsigned char *addr, struct net_device *ifp, ulong bufcnt) +aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) { struct aoedev *d; ulong flags; @@ -112,25 +144,19 @@ aoedev_set(ulong sysminor, unsigned char *addr, struct net_device *ifp, ulong bu if (d->sysminor == sysminor) break; - if (d == NULL && (d = aoedev_newdev(bufcnt)) == NULL) { - spin_unlock_irqrestore(&devlist_lock, flags); - printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n"); - return NULL; - } /* if newdev, (d->flags & DEVFL_UP) == 0 for below */ - - spin_unlock_irqrestore(&devlist_lock, flags); - spin_lock_irqsave(&d->lock, flags); - - d->ifp = ifp; - memcpy(d->addr, addr, sizeof d->addr); - if ((d->flags & DEVFL_UP) == 0) { - aoedev_downdev(d); /* flushes outstanding frames */ + if (d == NULL) { + d = aoedev_newdev(bufcnt); + if (d == NULL) { + spin_unlock_irqrestore(&devlist_lock, flags); + printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n"); + return NULL; + } d->sysminor = sysminor; d->aoemajor = AOEMAJOR(sysminor); d->aoeminor = AOEMINOR(sysminor); } - spin_unlock_irqrestore(&d->lock, flags); + spin_unlock_irqrestore(&devlist_lock, flags); return d; } @@ -161,6 +187,7 @@ aoedev_exit(void) spin_lock_irqsave(&d->lock, flags); aoedev_downdev(d); + d->flags |= DEVFL_TKILL; spin_unlock_irqrestore(&d->lock, flags); del_timer_sync(&d->timer); -- cgit v1.2.3-59-g8ed1b From eaf0a3cbe5d0713eca3278b3b18f08dba4fb914b Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Thu, 19 Jan 2006 13:46:20 -0500 Subject: [PATCH] aoe [3/8]: increase allowed outstanding packets Increase the number of AoE packets per device that can be outstanding at one time, increasing performance. Signed-off-by: "Ed L. Cashin" Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoecmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 150eb78cd5a9..34b8c8c13f9a 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -647,7 +647,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) ulong flags, sysminor, aoemajor; u16 bufcnt; struct sk_buff *sl; - enum { MAXFRAMES = 8 }; + enum { MAXFRAMES = 16 }; h = (struct aoe_hdr *) skb->mac.raw; ch = (struct aoe_cfghdr *) (h+1); -- cgit v1.2.3-59-g8ed1b From c42b24cae5c9fe1ae1f9bb9dea020e1a788fab4d Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Thu, 19 Jan 2006 13:46:22 -0500 Subject: [PATCH] aoe [4/8]: use less confusing driver name Users were confused by the driver being called "aoe-2.6-$version". This form looks less like a Linux kernel version number. Signed-off-by: "Ed L. Cashin" Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoemain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index 387588a3f4ba..f39d5bae14ab 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c @@ -89,7 +89,7 @@ aoe_init(void) } printk(KERN_INFO - "aoe: aoe_init: AoE v2.6-%s initialised.\n", + "aoe: aoe_init: AoE v%s initialised.\n", VERSION); discover_timer(TINIT); return 0; -- cgit v1.2.3-59-g8ed1b From 2dd5e42269b6f71db8ca519e401ef1e6615b3705 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Thu, 19 Jan 2006 13:46:25 -0500 Subject: [PATCH] aoe [5/8]: allow network interface migration on packet retransmit Retransmit to the current network interface for an AoE device. Signed-off-by: "Ed L. Cashin" --- drivers/block/aoe/aoecmd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 34b8c8c13f9a..22bebf87945c 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -286,6 +286,8 @@ rexmit(struct aoedev *d, struct frame *f) h = (struct aoe_hdr *) f->data; f->tag = n; h->tag = cpu_to_be32(n); + memcpy(h->dst, d->addr, sizeof h->dst); + memcpy(h->src, d->ifp->dev_addr, sizeof h->src); skb = skb_prepare(d, f); if (skb) { -- cgit v1.2.3-59-g8ed1b From 5f7702fd737d14de3ed06a94a1655be9d43f7e35 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Thu, 19 Jan 2006 13:46:27 -0500 Subject: [PATCH] aoe [6/8]: update device information on last close Instead of making the user wait or do it manually, refresh device information on its last close by issuing a config query to the device. Signed-off-by: "Ed L. Cashin" Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoeblk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 039c0911fa8f..32fea55fac48 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -109,7 +109,7 @@ aoeblk_release(struct inode *inode, struct file *filp) spin_lock_irqsave(&d->lock, flags); - if (--d->nopen == 0 && !(d->flags & DEVFL_UP)) { + if (--d->nopen == 0) { spin_unlock_irqrestore(&d->lock, flags); aoecmd_cfg(d->aoemajor, d->aoeminor); return 0; -- cgit v1.2.3-59-g8ed1b From 02edb05e6310d3acbb26ffb038f0eb819274e6d0 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Thu, 19 Jan 2006 13:46:29 -0500 Subject: [PATCH] aoe [7/8]: update driver compatibility string The aoe driver is not compatible with 2.6 kernels older than 2.6.2. Signed-off-by: "Ed L. Cashin" Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoemain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index f39d5bae14ab..de08491ebe66 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c @@ -11,7 +11,7 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sam Hopkins "); -MODULE_DESCRIPTION("AoE block/char driver for 2.6.[0-9]+"); +MODULE_DESCRIPTION("AoE block/char driver for 2.6.2 and newer 2.6 kernels"); MODULE_VERSION(VERSION); enum { TINIT, TRUN, TKILL }; -- cgit v1.2.3-59-g8ed1b From a712c0efbffb09f7b837577e29d0efb043fea0ea Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Thu, 19 Jan 2006 13:46:31 -0500 Subject: [PATCH] aoe [8/8]: update driver version number Update aoe driver version number. Signed-off-by: "Ed L. Cashin" Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index bb7dd91e5d48..7ff5f9470f55 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -1,5 +1,5 @@ /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ -#define VERSION "14" +#define VERSION "21" #define AOE_MAJOR 152 #define DEVICE_NAME "aoe" -- cgit v1.2.3-59-g8ed1b From 1c6f3fcac03a16c901ee5acd58100bff963add6d Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 25 Jan 2006 13:54:44 -0500 Subject: [PATCH] aoe: do not stop retransmit timer when device goes down This patch is a bugfix that follows and depends on the eight aoe driver patches sent January 19th. Signed-off-by: "Ed L. Cashin" Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoecmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 22bebf87945c..207aabcd1f4e 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -331,7 +331,7 @@ rexmit_timer(ulong vp) spin_lock_irqsave(&d->lock, flags); if (d->flags & DEVFL_TKILL) { -tdie: spin_unlock_irqrestore(&d->lock, flags); + spin_unlock_irqrestore(&d->lock, flags); return; } f = d->frames; @@ -342,7 +342,7 @@ tdie: spin_unlock_irqrestore(&d->lock, flags); n /= HZ; if (n > MAXWAIT) { /* waited too long. device failure. */ aoedev_downdev(d); - goto tdie; + break; } rexmit(d, f); } -- cgit v1.2.3-59-g8ed1b From 5dc401ee74c5d6a24867acd8302c55da9ae4f0ce Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Tue, 7 Feb 2006 11:26:39 -0500 Subject: [PATCH] aoe [1/3]: support multiple AoE listeners Always clone incoming skbs, allowing other AoE listeners to exist in the kernel. Signed-off-by: "Ed L. Cashin" Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoenet.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 4be976940f69..fdff774b8ab9 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -92,18 +92,6 @@ mac_addr(char addr[6]) return __be64_to_cpu(n); } -static struct sk_buff * -skb_check(struct sk_buff *skb) -{ - if (skb_is_nonlinear(skb)) - if ((skb = skb_share_check(skb, GFP_ATOMIC))) - if (skb_linearize(skb, GFP_ATOMIC) < 0) { - dev_kfree_skb(skb); - return NULL; - } - return skb; -} - void aoenet_xmit(struct sk_buff *sl) { @@ -125,14 +113,14 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct aoe_hdr *h; u32 n; - skb = skb_check(skb); - if (!skb) + skb = skb_share_check(skb, GFP_ATOMIC); + if (skb == NULL) return 0; - + if (skb_is_nonlinear(skb)) + if (skb_linearize(skb, GFP_ATOMIC) < 0) + goto exit; if (!is_aoe_netif(ifp)) goto exit; - - //skb->len += ETH_HLEN; /* (1) */ skb_push(skb, ETH_HLEN); /* (1) */ h = (struct aoe_hdr *) skb->mac.raw; -- cgit v1.2.3-59-g8ed1b From 9d41965b783474dba9fcf3eb02e5eb60540e6ff6 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Tue, 7 Feb 2006 11:37:24 -0500 Subject: [PATCH] aoe [2/3]: don't request ATA device ID on ATA error On an ATA error response, take the device down instead of sending another ATA device identify command. Signed-off-by: "Ed L. Cashin" --- drivers/block/aoe/aoecmd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 207aabcd1f4e..39da28d344fe 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -517,6 +517,8 @@ aoecmd_ata_rsp(struct sk_buff *skb) ahout = (struct aoe_atahdr *) (f->data + sizeof(struct aoe_hdr)); buf = f->buf; + if (ahout->cmdstat == WIN_IDENTIFY) + d->flags &= ~DEVFL_PAUSE; if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh " "stat=%2.2Xh from e%ld.%ld\n", @@ -549,7 +551,6 @@ aoecmd_ata_rsp(struct sk_buff *skb) return; } ataid_complete(d, (char *) (ahin+1)); - d->flags &= ~DEVFL_PAUSE; break; default: printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized " -- cgit v1.2.3-59-g8ed1b From 0fdf109676d1eda4ff8199a9a3ee3f11c555c1b3 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Tue, 7 Feb 2006 11:37:36 -0500 Subject: [PATCH] aoe [3/3]: update version to 22 Increase version number to 22. Signed-off-by: "Ed L. Cashin" --- drivers/block/aoe/aoe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 7ff5f9470f55..6eebcb7be97e 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -1,5 +1,5 @@ /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ -#define VERSION "21" +#define VERSION "22" #define AOE_MAJOR 152 #define DEVICE_NAME "aoe" -- cgit v1.2.3-59-g8ed1b From c0489e4efcad44aeb16c55760daf3b487183e9f0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Mar 2006 14:07:49 +0900 Subject: [PATCH] libata: implement ata_unpack_xfermask() Implement ata_unpack_xfermask(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f3c115b55681..1514cb5e35f7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -252,6 +252,29 @@ static unsigned int ata_pack_xfermask(unsigned int pio_mask, ((udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA); } +/** + * ata_unpack_xfermask - Unpack xfer_mask into pio, mwdma and udma masks + * @xfer_mask: xfer_mask to unpack + * @pio_mask: resulting pio_mask + * @mwdma_mask: resulting mwdma_mask + * @udma_mask: resulting udma_mask + * + * Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask. + * Any NULL distination masks will be ignored. + */ +static void ata_unpack_xfermask(unsigned int xfer_mask, + unsigned int *pio_mask, + unsigned int *mwdma_mask, + unsigned int *udma_mask) +{ + if (pio_mask) + *pio_mask = (xfer_mask & ATA_MASK_PIO) >> ATA_SHIFT_PIO; + if (mwdma_mask) + *mwdma_mask = (xfer_mask & ATA_MASK_MWDMA) >> ATA_SHIFT_MWDMA; + if (udma_mask) + *udma_mask = (xfer_mask & ATA_MASK_UDMA) >> ATA_SHIFT_UDMA; +} + static const struct ata_xfer_ent { unsigned int shift, bits; u8 base; -- cgit v1.2.3-59-g8ed1b From acf356b12d13c8b43c486e53e8ee12f1f435ecc8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Mar 2006 14:07:50 +0900 Subject: [PATCH] libata: add per-dev pio/mwdma/udma_mask Add per-dev pio/mwdma/udma_mask. All transfer mode limits used to be applied to ap->*_mask which unnecessarily restricted other devices sharing the port. This change will also benefit later EH speed down and hotplug. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 43 +++++++++++++++++++++++++------------------ include/linux/libata.h | 5 +++++ 2 files changed, 30 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1514cb5e35f7..a87748ba579c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -65,8 +65,7 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); static void ata_set_mode(struct ata_port *ap); static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); -static unsigned int ata_dev_xfermask(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_unique_id = 1; static struct workqueue_struct *ata_wq; @@ -1801,16 +1800,19 @@ static void ata_set_mode(struct ata_port *ap) /* step 1: calculate xfer_mask */ for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; - unsigned int xfer_mask; + unsigned int pio_mask, dma_mask; if (!ata_dev_present(dev)) continue; - xfer_mask = ata_dev_xfermask(ap, dev); + ata_dev_xfermask(ap, dev); - dev->pio_mode = ata_xfer_mask2mode(xfer_mask & ATA_MASK_PIO); - dev->dma_mode = ata_xfer_mask2mode(xfer_mask & (ATA_MASK_MWDMA | - ATA_MASK_UDMA)); + /* 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); + dev->dma_mode = ata_xfer_mask2mode(dma_mask); } /* step 2: always set host PIO timings */ @@ -2653,18 +2655,15 @@ static int ata_dma_blacklisted(const struct ata_device *dev) * @ap: Port on which the device to compute xfermask for resides * @dev: Device to compute xfermask for * - * Compute supported xfermask of @dev. This function is - * responsible for applying all known limits including host - * controller limits, device blacklist, etc... + * Compute supported xfermask of @dev and store it in + * dev->*_mask. This function is responsible for applying all + * known limits including host controller limits, device + * blacklist, etc... * * LOCKING: * None. - * - * RETURNS: - * Computed xfermask. */ -static unsigned int ata_dev_xfermask(struct ata_port *ap, - struct ata_device *dev) +static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) { unsigned long xfer_mask; int i; @@ -2677,6 +2676,8 @@ static unsigned int ata_dev_xfermask(struct ata_port *ap, struct ata_device *d = &ap->device[i]; if (!ata_dev_present(d)) continue; + 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); @@ -2686,7 +2687,8 @@ static unsigned int ata_dev_xfermask(struct ata_port *ap, printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " "disabling DMA\n", ap->id, dev->devno); - return xfer_mask; + ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, + &dev->udma_mask); } /** @@ -4436,8 +4438,13 @@ 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); - for (i = 0; i < ATA_MAX_DEVICES; i++) - ap->device[i].devno = i; + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + dev->devno = i; + dev->pio_mask = UINT_MAX; + dev->mwdma_mask = UINT_MAX; + dev->udma_mask = UINT_MAX; + } #ifdef ATA_IRQ_TRAP ap->stats.unhandled_irq = 1; diff --git a/include/linux/libata.h b/include/linux/libata.h index 7a54244d30aa..fbe8ba212598 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -358,6 +358,11 @@ struct ata_device { unsigned int max_sectors; /* per-device max sectors */ unsigned int cdb_len; + /* per-dev xfer mask */ + unsigned int pio_mask; + unsigned int mwdma_mask; + unsigned int udma_mask; + /* for CHS addressing */ u16 cylinders; /* Number of cylinders */ u16 heads; /* Number of heads */ -- cgit v1.2.3-59-g8ed1b From 5a529139554f12cb265715117a2153c936286294 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Mar 2006 14:07:50 +0900 Subject: [PATCH] libata: make per-dev transfer mode limits per-dev Now that each ata_device has xfer masks, per-dev limits can be made per-dev instead of per-port. Make per-dev limits per-dev. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- drivers/scsi/sata_sil.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a87748ba579c..1063928e3824 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1327,7 +1327,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, if (print_info) printk(KERN_INFO "ata%u(%u): applying bridge limits\n", ap->id, dev->devno); - ap->udma_mask &= ATA_UDMA5; + dev->udma_mask &= ATA_UDMA5; dev->max_sectors = ATA_MAX_SECTORS; } diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 3e75d6733239..18c296c56899 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -371,7 +371,7 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) if (quirks & SIL_QUIRK_UDMA5MAX) { printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n", ap->id, dev->devno, model_num); - ap->udma_mask &= ATA_UDMA5; + dev->udma_mask &= ATA_UDMA5; return; } } -- cgit v1.2.3-59-g8ed1b From 1f7dd3e9d62b25c7b79f913f37c2242a61295de4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Mar 2006 15:25:30 +0900 Subject: [PATCH] libata: check if port is disabled after internal command libata core is being changed to disallow port/device disable on lower layers. However, some LLDDs (sata_mv) directly disable port on command failure. This patch makes ata_exec_internal() check whether a port got disabled after an internal command. If it is, AC_ERR_SYSTEM is added to err_mask and the port gets re-enabled. As internal command failure results in device disable for drivers which don't implement newer reset/EH callbacks, this change results in no behavior change for single device per port controllers. For slave-possible LLDDs which disable port on command failure, (1) such drivers don't exist currently, (2) issuing command to the other device of once-disabled port shouldn't result in catastrophe even if such driver exists. So, this should be enough as a temporary measure. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1063928e3824..9cd9053e78fe 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1009,6 +1009,22 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, ata_qc_free(qc); + /* XXX - Some LLDDs (sata_mv) disable port on command failure. + * Until those drivers are fixed, we detect the condition + * here, fail the command with AC_ERR_SYSTEM and reenable the + * port. + * + * Note that this doesn't change any behavior as internal + * command failure results in disabling the device in the + * higher layer for LLDDs without new reset/EH callbacks. + * + * Kill the following code as soon as those drivers are fixed. + */ + if (ap->flags & ATA_FLAG_PORT_DISABLED) { + err_mask |= AC_ERR_SYSTEM; + ata_port_probe(ap); + } + return err_mask; } -- cgit v1.2.3-59-g8ed1b From 0b8efb0a16a1915c507db5a9b9fb5ede082a68a2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Mar 2006 15:25:31 +0900 Subject: [PATCH] libata: implement ata_dev_disable() This patch implements ata_dev_disable() which prints a warning message and takes @dev offline. Currently, this is done by explicitly incrementing dev->class with case-by-case warning messages. Giving user clear indication when libata gives up will be more important as libata will be doing more retries. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9cd9053e78fe..d1530b9fd8e7 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -394,6 +394,15 @@ static const char *ata_mode_string(unsigned int xfer_mask) return ""; } +static void ata_dev_disable(struct ata_port *ap, struct ata_device *dev) +{ + if (ata_dev_present(dev)) { + printk(KERN_WARNING "ata%u: dev %u disabled\n", + ap->id, dev->devno); + dev->class++; + } +} + /** * ata_pio_devchk - PATA device presence detection * @ap: ATA channel to examine -- cgit v1.2.3-59-g8ed1b From fcef978f9d4bd6ec43f89031442ee205987a912a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Mar 2006 15:25:31 +0900 Subject: [PATCH] libata: use ata_dev_disable() in ata_bus_probe() We may or may not disable a device after ata_dev_configure() fails. Kill 'not supported, ignoring' message in ata_dev_configure() and use ata_dev_disable() in ata_bus_probe(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d1530b9fd8e7..b08e79ffd769 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1363,8 +1363,6 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, return 0; err_out_nosup: - printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n", - ap->id, dev->devno); DPRINTK("EXIT, err\n"); return rc; } @@ -1431,7 +1429,7 @@ static int ata_bus_probe(struct ata_port *ap) } if (ata_dev_configure(ap, dev, 1)) { - dev->class++; /* disable device */ + ata_dev_disable(ap, dev); continue; } -- cgit v1.2.3-59-g8ed1b From 83206a2903fd2ddb1761d906b2b3b3de17ef87f1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 24 Mar 2006 15:25:31 +0900 Subject: [PATCH] libata: make ata_set_mode() responsible for failure handling Make ata_set_mode() responsible for determining whether to take port or device offline on failure. ata_dev_set_xfermode() and ata_dev_set_mode() indicate error to the caller instead of disabling port directly on failure. Also, for consistency, ata_dev_present() check is done in ata_set_mode() instead of ata_dev_set_mode(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 56 +++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b08e79ffd769..6970f6867334 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -64,7 +64,8 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); static void ata_set_mode(struct ata_port *ap); -static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *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); static unsigned int ata_unique_id = 1; @@ -1742,20 +1743,28 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, return 0; } -static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) +static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) { - if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) - return; + unsigned int err_mask; + int rc; if (dev->xfer_shift == ATA_SHIFT_PIO) dev->flags |= ATA_DFLAG_PIO; - ata_dev_set_xfermode(ap, dev); + err_mask = ata_dev_set_xfermode(ap, dev); + if (err_mask) { + printk(KERN_ERR + "ata%u: failed to set xfermode (err_mask=0x%x)\n", + ap->id, err_mask); + return -EIO; + } - if (ata_dev_revalidate(ap, dev, 0)) { - printk(KERN_ERR "ata%u: failed to revalidate after set " - "xfermode, disabled\n", ap->id); - ata_port_disable(ap); + rc = ata_dev_revalidate(ap, dev, 0); + if (rc) { + printk(KERN_ERR + "ata%u: failed to revalidate after set xfermode\n", + ap->id); + return rc; } DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n", @@ -1764,6 +1773,7 @@ static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) printk(KERN_INFO "ata%u: dev %u configured for %s\n", ap->id, dev->devno, ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode))); + return 0; } static int ata_host_set_pio(struct ata_port *ap) @@ -1847,11 +1857,15 @@ static void ata_set_mode(struct ata_port *ap) ata_host_set_dma(ap); /* step 4: update devices' xfer mode */ - for (i = 0; i < ATA_MAX_DEVICES; i++) - ata_dev_set_mode(ap, &ap->device[i]); + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; - if (ap->flags & ATA_FLAG_PORT_DISABLED) - return; + if (!ata_dev_present(dev)) + continue; + + if (ata_dev_set_mode(ap, dev)) + goto err_out; + } if (ap->ops->post_set_mode) ap->ops->post_set_mode(ap); @@ -2724,11 +2738,16 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) * * LOCKING: * PCI/etc. bus probe sem. + * + * RETURNS: + * 0 on success, AC_ERR_* mask otherwise. */ -static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) +static unsigned int ata_dev_set_xfermode(struct ata_port *ap, + struct ata_device *dev) { struct ata_taskfile tf; + unsigned int err_mask; /* set up set-features taskfile */ DPRINTK("set features - xfer mode\n"); @@ -2740,13 +2759,10 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) tf.protocol = ATA_PROT_NODATA; tf.nsect = dev->xfer_mode; - if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) { - printk(KERN_ERR "ata%u: failed to set xfermode, disabled\n", - ap->id); - ata_port_disable(ap); - } + err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); - DPRINTK("EXIT\n"); + DPRINTK("EXIT, err_mask=%x\n", err_mask); + return err_mask; } /** -- cgit v1.2.3-59-g8ed1b From 082776e4be791736c32baf818e50f501a7f83819 Mon Sep 17 00:00:00 2001 From: Nigel Cunningham Date: Thu, 23 Mar 2006 23:22:16 +1000 Subject: [PATCH] Make libata not powerdown drivers on PM_EVENT_FREEZE. At the moment libata doesn't pass pm_message_t down ata_device_suspend. This causes drives to be powered down when we just want a freeze, causing unnecessary wear and tear. This patch gets pm_message_t passed down so that it can be used to determine whether to power down the drive. Signed-off-by: Nigel Cunningham drivers/scsi/libata-core.c | 5 +++-- drivers/scsi/libata-scsi.c | 4 ++-- drivers/scsi/scsi_sysfs.c | 2 +- include/linux/libata.h | 4 ++-- include/scsi/scsi_host.h | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 5 +++-- drivers/scsi/libata-scsi.c | 4 ++-- drivers/scsi/scsi_sysfs.c | 2 +- include/linux/libata.h | 4 ++-- include/scsi/scsi_host.h | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 6970f6867334..d8f77f2a5af1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4336,14 +4336,15 @@ int ata_device_resume(struct ata_port *ap, struct ata_device *dev) * 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) +int ata_device_suspend(struct ata_port *ap, struct ata_device *dev, pm_message_t state) { if (!ata_dev_present(dev)) return 0; if (dev->class == ATA_DEV_ATA) ata_flush_cache(ap, dev); - ata_standby_drive(ap, dev); + if (state.event != PM_EVENT_FREEZE) + ata_standby_drive(ap, dev); ap->flags |= ATA_FLAG_SUSPENDED; return 0; } diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index a1259b242b8e..1fd3826da97e 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -414,12 +414,12 @@ int ata_scsi_device_resume(struct scsi_device *sdev) return ata_device_resume(ap, dev); } -int ata_scsi_device_suspend(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_device *dev = &ap->device[sdev->id]; - return ata_device_suspend(ap, dev); + return ata_device_suspend(ap, dev, state); } /** diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 89055494dfee..a6fde52946d6 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -286,7 +286,7 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state) return err; if (sht->suspend) - err = sht->suspend(sdev); + err = sht->suspend(sdev, state); return err; } diff --git a/include/linux/libata.h b/include/linux/libata.h index fbe8ba212598..c52f13498556 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -520,9 +520,9 @@ 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 *); -extern int ata_scsi_device_suspend(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 *); +extern int ata_device_suspend(struct ata_port *, 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, diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index a6cf3e535c0b..dc6862d09e53 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -286,7 +286,7 @@ struct scsi_host_template { * suspend support */ int (*resume)(struct scsi_device *); - int (*suspend)(struct scsi_device *); + int (*suspend)(struct scsi_device *, pm_message_t state); /* * Name of proc directory -- cgit v1.2.3-59-g8ed1b From ebdfca6eb1b755d3bfe9a81339ecdafd92038c1a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 23 Mar 2006 15:38:34 +0000 Subject: [PATCH] libata: add ata_dev_pair helper Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 17 +++++++++++++++++ include/linux/libata.h | 2 ++ 2 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d8f77f2a5af1..909568f7a72a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1575,6 +1575,23 @@ void sata_phy_reset(struct ata_port *ap) ata_bus_reset(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 *pair = &ap->device[1 - adev->devno]; + if (!ata_dev_present(pair)) + return NULL; + return pair; +} + /** * ata_port_disable - Disable port. * @ap: Port to be disabled. diff --git a/include/linux/libata.h b/include/linux/libata.h index c52f13498556..80c2339da67d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -573,6 +573,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 struct ata_device *ata_dev_pair(struct ata_port *ap, + struct ata_device *adev); /* * Timing helpers -- cgit v1.2.3-59-g8ed1b From 2e9edbf815e42f93dd29a9981f27bd421acc47df Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 24 Mar 2006 09:56:57 -0500 Subject: [libata] export ata_dev_pair; trim trailing whitespace Mostly, trim trailing whitespace. Also: * export ata_dev_pair * move ata_dev_classify export closer to ata_dev_pair export --- drivers/scsi/ata_piix.c | 6 +++--- drivers/scsi/libata-bmdma.c | 4 ++-- drivers/scsi/libata-core.c | 49 +++++++++++++++++++++++---------------------- drivers/scsi/libata-scsi.c | 30 +++++++++++++-------------- drivers/scsi/sata_sil24.c | 2 +- drivers/scsi/sata_vsc.c | 4 ++-- 6 files changed, 48 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index a74e23d39ba9..2d5be84d8bd4 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -742,7 +742,7 @@ static int piix_disable_ahci(struct pci_dev *pdev) /** * piix_check_450nx_errata - Check for problem 450NX setup * @ata_dev: the PCI device to check - * + * * Check for the present of 450NX errata #19 and errata #25. If * they are found return an error code so we can turn off DMA */ @@ -753,7 +753,7 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) u16 cfg; u8 rev; int no_piix_dma = 0; - + while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL) { /* Look for 450NX PXB. Check for problem configurations @@ -772,7 +772,7 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) if(no_piix_dma == 2) dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n"); return no_piix_dma; -} +} static void __devinit piix_init_sata_map(struct pci_dev *pdev, struct ata_port_info *pinfo) diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index a00a78b30836..95d81d86d8b7 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -941,7 +941,7 @@ err_out: * @pdev: PCI device * * Some PCI ATA devices report simplex mode but in fact can be told to - * enter non simplex mode. This implements the neccessary logic to + * enter non simplex mode. This implements the neccessary logic to * perform the task on such devices. Calling it on other devices will * have -undefined- behaviour. */ @@ -966,7 +966,7 @@ unsigned long ata_pci_default_filter(const struct ata_port *ap, struct ata_devic { /* Filter out DMA modes if the device has been configured by the BIOS as PIO only */ - + if (ap->ioaddr.bmdma_addr == 0) xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); return xfer_mask; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 909568f7a72a..94ad4acf8a59 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -190,7 +190,7 @@ static const u8 ata_rw_cmds[] = { * ata_rwcmd_protocol - set taskfile r/w commands and protocol * @qc: command to examine and configure * - * Examine the device configuration and tf->flags to calculate + * Examine the device configuration and tf->flags to calculate * the proper read/write commands and protocol to use. * * LOCKING: @@ -203,7 +203,7 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc) u8 cmd; int index, fua, lba48, write; - + fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0; lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0; write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0; @@ -1055,7 +1055,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) return 0; if (speed > 2) return 1; - + /* If we have no drive specific rule, then PIO 2 is non IORDY */ if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE */ @@ -1583,7 +1583,7 @@ void sata_phy_reset(struct ata_port *ap) * 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 *pair = &ap->device[1 - adev->devno]; @@ -1620,7 +1620,7 @@ void ata_port_disable(struct ata_port *ap) * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds). * These were taken from ATA/ATAPI-6 standard, rev 0a, except * for PIO 5, which is a nonstandard extension and UDMA6, which - * is currently supported only by Maxtor drives. + * is currently supported only by Maxtor drives. */ static const struct ata_timing ata_timing[] = { @@ -1635,11 +1635,11 @@ static const struct ata_timing ata_timing[] = { { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 }, /* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 150 }, */ - + { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 }, { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 }, { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 }, - + { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 }, { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 }, { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 }, @@ -1692,7 +1692,7 @@ static const struct ata_timing* ata_timing_find_mode(unsigned short speed) for (t = ata_timing; t->mode != speed; t++) if (t->mode == 0xFF) return NULL; - return t; + return t; } int ata_timing_compute(struct ata_device *adev, unsigned short speed, @@ -1702,7 +1702,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, struct ata_timing p; /* - * Find the mode. + * Find the mode. */ if (!(s = ata_timing_find_mode(speed))) @@ -2078,11 +2078,11 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, */ msleep(150); - - /* Before we perform post reset processing we want to see if + + /* Before we perform post reset processing we want to see if the bus shows 0xFF because the odd clown forgets the D7 pulldown resistor */ - + if (ata_check_status(ap) == 0xFF) return 1; /* Positive is failure for some reason */ @@ -2651,22 +2651,22 @@ static const char * const ata_dma_blacklist [] = { "SanDisk SDP3B-64", NULL, "SANYO CD-ROM CRD", NULL, "HITACHI CDR-8", NULL, - "HITACHI CDR-8335", NULL, + "HITACHI CDR-8335", NULL, "HITACHI CDR-8435", NULL, - "Toshiba CD-ROM XM-6202B", NULL, - "TOSHIBA CD-ROM XM-1702BC", NULL, - "CD-532E-A", NULL, - "E-IDE CD-ROM CR-840", NULL, - "CD-ROM Drive/F5A", NULL, - "WPI CDD-820", NULL, + "Toshiba CD-ROM XM-6202B", NULL, + "TOSHIBA CD-ROM XM-1702BC", NULL, + "CD-532E-A", NULL, + "E-IDE CD-ROM CR-840", NULL, + "CD-ROM Drive/F5A", NULL, + "WPI CDD-820", NULL, "SAMSUNG CD-ROM SC-148C", NULL, - "SAMSUNG CD-ROM SC", NULL, + "SAMSUNG CD-ROM SC", NULL, "SanDisk SDP3B-64", NULL, "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL, "_NEC DV5800A", NULL, "SAMSUNG CD-ROM SN-124", "N001" }; - + static int ata_strim(char *s, size_t len) { len = strnlen(s, len); @@ -3697,7 +3697,7 @@ static void ata_pio_error(struct ata_port *ap) 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 + /* make sure qc->err_mask is available to * know what's wrong and recover */ WARN_ON(qc->err_mask == 0); @@ -4695,7 +4695,7 @@ err_free_ret: * ata_host_set_remove - PCI layer callback for device removal * @host_set: ATA host set that was removed * - * Unregister all objects associated with this host set. Free those + * Unregister all objects associated with this host set. Free those * objects. * * LOCKING: @@ -4967,6 +4967,8 @@ 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); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_busy_sleep); @@ -4977,7 +4979,6 @@ 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_dev_classify); EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_c_string); EXPORT_SYMBOL_GPL(ata_scsi_simulate); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 1fd3826da97e..b7df37ed4393 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -256,7 +256,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) scsi_cmd[14] = args[0]; /* Good values for timeout and retries? Values below - from scsi_ioctl_send_command() for default case... */ + from scsi_ioctl_send_command() for default case... */ if (scsi_execute_req(scsidev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr, (10*HZ), 5)) rc = -EIO; @@ -438,7 +438,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) * LOCKING: * spin_lock_irqsave(host_set lock) */ -void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, +void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, u8 *ascq) { int i; @@ -495,7 +495,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, /* Look for drv_err */ for (i = 0; sense_table[i][0] != 0xFF; i++) { /* Look for best matches first */ - if ((sense_table[i][0] & drv_err) == + if ((sense_table[i][0] & drv_err) == sense_table[i][0]) { *sk = sense_table[i][1]; *asc = sense_table[i][2]; @@ -518,7 +518,7 @@ 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", + 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 @@ -1150,14 +1150,14 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc DPRINTK("block %u track %u cyl %u head %u sect %u\n", (u32)block, track, cyl, head, sect); - - /* Check whether the converted CHS can fit. - Cylinder: 0-65535 + + /* Check whether the converted CHS can fit. + Cylinder: 0-65535 Head: 0-15 Sector: 1-255*/ - if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) + if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) goto out_of_range; - + tf->command = ATA_CMD_VERIFY; tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */ tf->lbal = sect; @@ -1289,7 +1289,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm tf->lbal = block & 0xff; tf->device |= ATA_LBA; - } else { + } else { /* CHS */ u32 sect, head, cyl, track; @@ -1309,8 +1309,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm DPRINTK("block %u track %u cyl %u head %u sect %u\n", (u32)block, track, cyl, head, sect); - /* Check whether the converted CHS can fit. - Cylinder: 0-65535 + /* Check whether the converted CHS can fit. + Cylinder: 0-65535 Head: 0-15 Sector: 1-255*/ if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) @@ -1697,7 +1697,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, if (buflen > (ATA_SERNO_LEN + num + 3)) { /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */ - rbuf[num + 0] = 2; + rbuf[num + 0] = 2; rbuf[num + 3] = ATA_SERNO_LEN; num += 4; ata_id_string(args->id, (unsigned char *) rbuf + num, @@ -1707,8 +1707,8 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, if (buflen > (sat_model_serial_desc_len + num + 3)) { /* SAT defined lu model and serial numbers descriptor */ /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */ - rbuf[num + 0] = 2; - rbuf[num + 1] = 1; + rbuf[num + 0] = 2; + rbuf[num + 1] = 1; rbuf[num + 3] = sat_model_serial_desc_len; num += 4; memcpy(rbuf + num, "ATA ", 8); diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 3efebea211f2..068c98a4111b 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -342,7 +342,7 @@ static struct ata_port_info sil24_port_info[] = { .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil24_ops, }, - /* sil_3132 */ + /* sil_3132 */ { .sht = &sil24_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 9701a806539d..836bbbb26ff2 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -230,11 +230,11 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, handled += ata_host_intr(ap, qc); } else if (is_vsc_sata_int_err(i, int_status)) { /* - * On some chips (i.e. Intel 31244), an error + * On some chips (i.e. Intel 31244), an error * interrupt will sneak in at initialization * time (phy state changes). Clearing the SCR * error register is not required, but it prevents - * the phy state change interrupts from recurring + * the phy state change interrupts from recurring * later. */ u32 err_status; -- cgit v1.2.3-59-g8ed1b From eb3f0f9c6c3416016565c8b91644d7386889e565 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 23 Mar 2006 17:30:02 -0600 Subject: [PATCH] libata: ata_scsi_queuecmd cleanup Encapsulate part of ata_scsi_queuecmd so that it can be reused by future SAS patches. Signed-off-by: Brian King Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index b7df37ed4393..8192ddd62974 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -2597,6 +2597,21 @@ 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) +{ + 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); + else + ata_scsi_simulate(ap, dev, cmd, done); + } else + ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); +} + /** * ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device * @cmd: SCSI command to be sent @@ -2631,24 +2646,13 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) ata_scsi_dump_cdb(ap, cmd); dev = ata_scsi_find_dev(ap, scsidev); - if (unlikely(!dev)) { + if (likely(dev)) + __ata_scsi_queuecmd(cmd, done, ap, dev); + else { cmd->result = (DID_BAD_TARGET << 16); done(cmd); - goto out_unlock; } - 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); - else - ata_scsi_simulate(ap, dev, cmd, done); - } else - ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); - -out_unlock: spin_unlock(&ap->host_set->lock); spin_lock(shost->host_lock); return 0; -- cgit v1.2.3-59-g8ed1b From 2af10a818de1658f818601c7098056d65a772bc5 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 23 Mar 2006 17:30:08 -0600 Subject: [PATCH] libata: ata_scsi_ioctl cleanup In preparation for SAS, kill some unnecessary code in ata_scsi_ioctl to find the ATA port and device given the scsi_device. Neither local is used in the function. Signed-off-by: Brian King Signed-off-by: Jeff Garzik --- drivers/scsi/libata-scsi.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 8192ddd62974..628191bfd990 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -267,20 +267,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) { - struct ata_port *ap; - struct ata_device *dev; int val = -EINVAL, rc = -EINVAL; - ap = (struct ata_port *) &scsidev->host->hostdata[0]; - if (!ap) - goto out; - - dev = ata_scsi_find_dev(ap, scsidev); - if (!dev) { - rc = -ENODEV; - goto out; - } - switch (cmd) { case ATA_IOC_GET_IO32: val = 0; @@ -309,7 +297,6 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) break; } -out: return rc; } -- cgit v1.2.3-59-g8ed1b From 2f1f610b62bce36d6d50857859091b8989c70267 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 23 Mar 2006 17:30:15 -0600 Subject: [PATCH] libata: Remove dependence on host_set->dev for SAS Remove some of the dependence on the host_set struct in preparation for supporting SAS HBAs. Adds a struct device pointer to the ata_port struct. Signed-off-by: Brian King Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 13 +++++++------ include/linux/libata.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 94ad4acf8a59..d279666dcb38 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2856,7 +2856,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) if (qc->flags & ATA_QCFLAG_SG) { if (qc->n_elem) - dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir); + dma_unmap_sg(ap->dev, sg, qc->n_elem, dir); /* restore last sg */ sg[qc->orig_n_elem - 1].length += qc->pad_len; if (pad_buf) { @@ -2867,7 +2867,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) } } else { if (qc->n_elem) - dma_unmap_single(ap->host_set->dev, + dma_unmap_single(ap->dev, sg_dma_address(&sg[0]), sg_dma_len(&sg[0]), dir); /* restore sg */ @@ -3078,7 +3078,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) goto skip_map; } - dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt, + dma_address = dma_map_single(ap->dev, qc->buf_virt, sg->length, dir); if (dma_mapping_error(dma_address)) { /* restore sg */ @@ -3166,7 +3166,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) } dir = qc->dma_dir; - n_elem = dma_map_sg(ap->host_set->dev, sg, pre_n_elem, dir); + n_elem = dma_map_sg(ap->dev, sg, pre_n_elem, dir); if (n_elem < 1) { /* restore last sg */ lsg->length += qc->pad_len; @@ -4381,7 +4381,7 @@ int ata_device_suspend(struct ata_port *ap, struct ata_device *dev, pm_message_t int ata_port_start (struct ata_port *ap) { - struct device *dev = ap->host_set->dev; + struct device *dev = ap->dev; int rc; ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL); @@ -4414,7 +4414,7 @@ int ata_port_start (struct ata_port *ap) void ata_port_stop (struct ata_port *ap) { - struct device *dev = ap->host_set->dev; + struct device *dev = ap->dev; dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); ata_pad_free(ap, dev); @@ -4480,6 +4480,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->host = host; ap->ctl = ATA_DEVCTL_OBS; ap->host_set = host_set; + ap->dev = ent->dev; ap->port_no = port_no; ap->hard_port_no = ent->legacy_mode ? ent->hard_port_no : port_no; diff --git a/include/linux/libata.h b/include/linux/libata.h index 80c2339da67d..047192253c3a 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -400,6 +400,7 @@ struct ata_port { struct ata_host_stats stats; struct ata_host_set *host_set; + struct device *dev; struct work_struct port_task; -- cgit v1.2.3-59-g8ed1b From 3ba1998e90239ed0d7af918998bc866fa77303eb Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 24 Mar 2006 03:15:12 -0800 Subject: [PATCH] s390: wrong interrupt delivered for hsch() or csch() When cio waits for the interrupt for a basic sense, interrupts for hsch() or csch() issued in the meantime are wrongly counted as interrupts for the basic sense and the accumulated irb is passed to the device driver. In ccw_device_w4sense(), check for clear or halt function in the irb and pass the irb for the csch() or hsch() to the device driver. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/device_fsm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index b302779e7cff..180b3bf8b90d 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -827,6 +827,17 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) } return; } + /* + * Check if a halt or clear has been issued in the meanwhile. If yes, + * only deliver the halt/clear interrupt to the device driver as if it + * had killed the original request. + */ + if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) { + cdev->private->flags.dosense = 0; + memset(&cdev->private->irb, 0, sizeof(struct irb)); + ccw_device_accumulate_irb(cdev, irb); + goto call_handler; + } /* Add basic sense info to irb. */ ccw_device_accumulate_basic_sense(cdev, irb); if (cdev->private->flags.dosense) { @@ -834,6 +845,7 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) ccw_device_do_sense(cdev, irb); return; } +call_handler: cdev->private->state = DEV_STATE_ONLINE; /* Call the handler. */ if (ccw_device_call_handler(cdev) && cdev->private->flags.doverify) -- cgit v1.2.3-59-g8ed1b From 495a5b45ac33b8fe2c49780fdbcc8014cb6d6ddc Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 24 Mar 2006 03:15:14 -0800 Subject: [PATCH] s390: channel path measurements Gather extended measurements for channel paths from the channel subsystem and expose them to userspace via a sysfs attribute. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/chsc.c | 454 +++++++++++++++++++++++++++++++++++++++++++++--- drivers/s390/cio/chsc.h | 22 ++- drivers/s390/cio/css.c | 41 +++++ drivers/s390/cio/css.h | 6 + 4 files changed, 500 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index f4183d660258..8b57fe62a9f9 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -98,10 +98,8 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page) ssd_area = page; - ssd_area->request = (struct chsc_header) { - .length = 0x0010, - .code = 0x0004, - }; + ssd_area->request.length = 0x0010; + ssd_area->request.code = 0x0004; ssd_area->ssid = sch->schid.ssid; ssd_area->f_sch = sch->schid.sch_no; @@ -517,10 +515,8 @@ chsc_process_crw(void) struct device *dev; memset(sei_area, 0, sizeof(*sei_area)); memset(&res_data, 0, sizeof(struct res_acc_data)); - sei_area->request = (struct chsc_header) { - .length = 0x0010, - .code = 0x000e, - }; + sei_area->request.length = 0x0010; + sei_area->request.code = 0x000e; ccode = chsc(sei_area); if (ccode > 0) @@ -874,6 +870,264 @@ s390_vary_chpid( __u8 chpid, int on) return 0; } +/* + * Channel measurement related functions + */ +static ssize_t +chp_measurement_chars_read(struct kobject *kobj, char *buf, loff_t off, + size_t count) +{ + struct channel_path *chp; + unsigned int size; + + chp = to_channelpath(container_of(kobj, struct device, kobj)); + if (!chp->cmg_chars) + return 0; + + size = sizeof(struct cmg_chars); + + if (off > size) + return 0; + if (off + count > size) + count = size - off; + memcpy(buf, chp->cmg_chars + off, count); + return count; +} + +static struct bin_attribute chp_measurement_chars_attr = { + .attr = { + .name = "measurement_chars", + .mode = S_IRUSR, + .owner = THIS_MODULE, + }, + .size = sizeof(struct cmg_chars), + .read = chp_measurement_chars_read, +}; + +static void +chp_measurement_copy_block(struct cmg_entry *buf, + struct channel_subsystem *css, int chpid) +{ + void *area; + struct cmg_entry *entry, reference_buf; + int idx; + + if (chpid < 128) { + area = css->cub_addr1; + idx = chpid; + } else { + area = css->cub_addr2; + idx = chpid - 128; + } + entry = area + (idx * sizeof(struct cmg_entry)); + do { + memcpy(buf, entry, sizeof(*entry)); + memcpy(&reference_buf, entry, sizeof(*entry)); + } while (reference_buf.values[0] != buf->values[0]); +} + +static ssize_t +chp_measurement_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct channel_path *chp; + struct channel_subsystem *css; + unsigned int size; + + chp = to_channelpath(container_of(kobj, struct device, kobj)); + css = to_css(chp->dev.parent); + + size = sizeof(struct cmg_chars); + + /* Only allow single reads. */ + if (off || count < size) + return 0; + chp_measurement_copy_block((struct cmg_entry *)buf, css, chp->id); + return count; +} + +static struct bin_attribute chp_measurement_attr = { + .attr = { + .name = "measurement", + .mode = S_IRUSR, + .owner = THIS_MODULE, + }, + .size = sizeof(struct cmg_entry), + .read = chp_measurement_read, +}; + +static void +chsc_remove_chp_cmg_attr(struct channel_path *chp) +{ + sysfs_remove_bin_file(&chp->dev.kobj, &chp_measurement_chars_attr); + sysfs_remove_bin_file(&chp->dev.kobj, &chp_measurement_attr); +} + +static int +chsc_add_chp_cmg_attr(struct channel_path *chp) +{ + int ret; + + ret = sysfs_create_bin_file(&chp->dev.kobj, + &chp_measurement_chars_attr); + if (ret) + return ret; + ret = sysfs_create_bin_file(&chp->dev.kobj, &chp_measurement_attr); + if (ret) + sysfs_remove_bin_file(&chp->dev.kobj, + &chp_measurement_chars_attr); + return ret; +} + +static void +chsc_remove_cmg_attr(struct channel_subsystem *css) +{ + int i; + + for (i = 0; i <= __MAX_CHPID; i++) { + if (!css->chps[i]) + continue; + chsc_remove_chp_cmg_attr(css->chps[i]); + } +} + +static int +chsc_add_cmg_attr(struct channel_subsystem *css) +{ + int i, ret; + + ret = 0; + for (i = 0; i <= __MAX_CHPID; i++) { + if (!css->chps[i]) + continue; + ret = chsc_add_chp_cmg_attr(css->chps[i]); + if (ret) + goto cleanup; + } + return ret; +cleanup: + for (--i; i >= 0; i--) { + if (!css->chps[i]) + continue; + chsc_remove_chp_cmg_attr(css->chps[i]); + } + return ret; +} + + +static int +__chsc_do_secm(struct channel_subsystem *css, int enable, void *page) +{ + struct { + struct chsc_header request; + u32 operation_code : 2; + u32 : 30; + u32 key : 4; + u32 : 28; + u32 zeroes1; + u32 cub_addr1; + u32 zeroes2; + u32 cub_addr2; + u32 reserved[13]; + struct chsc_header response; + u32 status : 8; + u32 : 4; + u32 fmt : 4; + u32 : 16; + } *secm_area; + int ret, ccode; + + secm_area = page; + secm_area->request.length = 0x0050; + secm_area->request.code = 0x0016; + + secm_area->key = PAGE_DEFAULT_KEY; + secm_area->cub_addr1 = (u64)(unsigned long)css->cub_addr1; + secm_area->cub_addr2 = (u64)(unsigned long)css->cub_addr2; + + secm_area->operation_code = enable ? 0 : 1; + + ccode = chsc(secm_area); + if (ccode > 0) + return (ccode == 3) ? -ENODEV : -EBUSY; + + switch (secm_area->response.code) { + case 0x0001: /* Success. */ + ret = 0; + break; + case 0x0003: /* Invalid block. */ + case 0x0007: /* Invalid format. */ + case 0x0008: /* Other invalid block. */ + CIO_CRW_EVENT(2, "Error in chsc request block!\n"); + ret = -EINVAL; + break; + case 0x0004: /* Command not provided in model. */ + CIO_CRW_EVENT(2, "Model does not provide secm\n"); + ret = -EOPNOTSUPP; + break; + case 0x0102: /* cub adresses incorrect */ + CIO_CRW_EVENT(2, "Invalid addresses in chsc request block\n"); + ret = -EINVAL; + break; + case 0x0103: /* key error */ + CIO_CRW_EVENT(2, "Access key error in secm\n"); + ret = -EINVAL; + break; + case 0x0105: /* error while starting */ + CIO_CRW_EVENT(2, "Error while starting channel measurement\n"); + ret = -EIO; + break; + default: + CIO_CRW_EVENT(2, "Unknown CHSC response %d\n", + secm_area->response.code); + ret = -EIO; + } + return ret; +} + +int +chsc_secm(struct channel_subsystem *css, int enable) +{ + void *secm_area; + int ret; + + secm_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!secm_area) + return -ENOMEM; + + mutex_lock(&css->mutex); + if (enable && !css->cm_enabled) { + css->cub_addr1 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); + css->cub_addr2 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!css->cub_addr1 || !css->cub_addr2) { + free_page((unsigned long)css->cub_addr1); + free_page((unsigned long)css->cub_addr2); + free_page((unsigned long)secm_area); + mutex_unlock(&css->mutex); + return -ENOMEM; + } + } + ret = __chsc_do_secm(css, enable, secm_area); + if (!ret) { + css->cm_enabled = enable; + if (css->cm_enabled) { + ret = chsc_add_cmg_attr(css); + if (ret) { + memset(secm_area, 0, PAGE_SIZE); + __chsc_do_secm(css, 0, secm_area); + css->cm_enabled = 0; + } + } else + chsc_remove_cmg_attr(css); + } + if (enable && !css->cm_enabled) { + free_page((unsigned long)css->cub_addr1); + free_page((unsigned long)css->cub_addr2); + } + mutex_unlock(&css->mutex); + free_page((unsigned long)secm_area); + return ret; +} + /* * Files for the channel path entries. */ @@ -925,9 +1179,39 @@ chp_type_show(struct device *dev, struct device_attribute *attr, char *buf) static DEVICE_ATTR(type, 0444, chp_type_show, NULL); +static ssize_t +chp_cmg_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct channel_path *chp = to_channelpath(dev); + + if (!chp) + return 0; + if (chp->cmg == -1) /* channel measurements not available */ + return sprintf(buf, "unknown\n"); + return sprintf(buf, "%x\n", chp->cmg); +} + +static DEVICE_ATTR(cmg, 0444, chp_cmg_show, NULL); + +static ssize_t +chp_shared_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct channel_path *chp = to_channelpath(dev); + + if (!chp) + return 0; + if (chp->shared == -1) /* channel measurements not available */ + return sprintf(buf, "unknown\n"); + return sprintf(buf, "%x\n", chp->shared); +} + +static DEVICE_ATTR(shared, 0444, chp_shared_show, NULL); + static struct attribute * chp_attrs[] = { &dev_attr_status.attr, &dev_attr_type.attr, + &dev_attr_cmg.attr, + &dev_attr_shared.attr, NULL, }; @@ -966,10 +1250,8 @@ chsc_determine_channel_path_description(int chpid, if (!scpd_area) return -ENOMEM; - scpd_area->request = (struct chsc_header) { - .length = 0x0010, - .code = 0x0002, - }; + scpd_area->request.length = 0x0010; + scpd_area->request.code = 0x0002; scpd_area->first_chpid = chpid; scpd_area->last_chpid = chpid; @@ -1006,6 +1288,111 @@ out: return ret; } +static void +chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv, + struct cmg_chars *chars) +{ + switch (chp->cmg) { + case 2: + case 3: + chp->cmg_chars = kmalloc(sizeof(struct cmg_chars), + GFP_KERNEL); + if (chp->cmg_chars) { + int i, mask; + struct cmg_chars *cmg_chars; + + cmg_chars = chp->cmg_chars; + for (i = 0; i < NR_MEASUREMENT_CHARS; i++) { + mask = 0x80 >> (i + 3); + if (cmcv & mask) + cmg_chars->values[i] = chars->values[i]; + else + cmg_chars->values[i] = 0; + } + } + break; + default: + /* No cmg-dependent data. */ + break; + } +} + +static int +chsc_get_channel_measurement_chars(struct channel_path *chp) +{ + int ccode, ret; + + struct { + struct chsc_header request; + u32 : 24; + u32 first_chpid : 8; + u32 : 24; + u32 last_chpid : 8; + u32 zeroes1; + struct chsc_header response; + u32 zeroes2; + u32 not_valid : 1; + u32 shared : 1; + u32 : 22; + u32 chpid : 8; + u32 cmcv : 5; + u32 : 11; + u32 cmgq : 8; + u32 cmg : 8; + u32 zeroes3; + u32 data[NR_MEASUREMENT_CHARS]; + } *scmc_area; + + scmc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!scmc_area) + return -ENOMEM; + + scmc_area->request.length = 0x0010; + scmc_area->request.code = 0x0022; + + scmc_area->first_chpid = chp->id; + scmc_area->last_chpid = chp->id; + + ccode = chsc(scmc_area); + if (ccode > 0) { + ret = (ccode == 3) ? -ENODEV : -EBUSY; + goto out; + } + + switch (scmc_area->response.code) { + case 0x0001: /* Success. */ + if (!scmc_area->not_valid) { + chp->cmg = scmc_area->cmg; + chp->shared = scmc_area->shared; + chsc_initialize_cmg_chars(chp, scmc_area->cmcv, + (struct cmg_chars *) + &scmc_area->data); + } else { + chp->cmg = -1; + chp->shared = -1; + } + ret = 0; + break; + case 0x0003: /* Invalid block. */ + case 0x0007: /* Invalid format. */ + case 0x0008: /* Invalid bit combination. */ + CIO_CRW_EVENT(2, "Error in chsc request block!\n"); + ret = -EINVAL; + break; + case 0x0004: /* Command not provided. */ + CIO_CRW_EVENT(2, "Model does not provide scmc\n"); + ret = -EOPNOTSUPP; + break; + default: + CIO_CRW_EVENT(2, "Unknown CHSC response %d\n", + scmc_area->response.code); + ret = -EIO; + } +out: + free_page((unsigned long)scmc_area); + return ret; +} + /* * Entries for chpids on the system bus. * This replaces /proc/chpids. @@ -1034,6 +1421,22 @@ new_channel_path(int chpid) ret = chsc_determine_channel_path_description(chpid, &chp->desc); if (ret) goto out_free; + /* Get channel-measurement characteristics. */ + if (css_characteristics_avail && css_chsc_characteristics.scmc + && css_chsc_characteristics.secm) { + ret = chsc_get_channel_measurement_chars(chp); + if (ret) + goto out_free; + } else { + static int msg_done; + + if (!msg_done) { + printk(KERN_WARNING "cio: Channel measurements not " + "available, continuing.\n"); + msg_done = 1; + } + chp->cmg = -1; + } /* make it known to the system */ ret = device_register(&chp->dev); @@ -1046,8 +1449,19 @@ new_channel_path(int chpid) if (ret) { device_unregister(&chp->dev); goto out_free; - } else - css[0]->chps[chpid] = chp; + } + mutex_lock(&css[0]->mutex); + if (css[0]->cm_enabled) { + ret = chsc_add_chp_cmg_attr(chp); + if (ret) { + sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); + device_unregister(&chp->dev); + mutex_unlock(&css[0]->mutex); + goto out_free; + } + } + css[0]->chps[chpid] = chp; + mutex_unlock(&css[0]->mutex); return ret; out_free: kfree(chp); @@ -1103,10 +1517,8 @@ chsc_enable_facility(int operation_code) sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA); if (!sda_area) return -ENOMEM; - sda_area->request = (struct chsc_header) { - .length = 0x0400, - .code = 0x0031, - }; + sda_area->request.length = 0x0400; + sda_area->request.code = 0x0031; sda_area->operation_code = operation_code; ret = chsc(sda_area); @@ -1161,10 +1573,8 @@ chsc_determine_css_characteristics(void) return -ENOMEM; } - scsc_area->request = (struct chsc_header) { - .length = 0x0010, - .code = 0x0010, - }; + scsc_area->request.length = 0x0010; + scsc_area->request.code = 0x0010; result = chsc(scsc_area); if (result) { diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 3e75095f35d0..a259245780ae 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h @@ -12,6 +12,16 @@ struct chsc_header { u16 code; }; +#define NR_MEASUREMENT_CHARS 5 +struct cmg_chars { + u32 values[NR_MEASUREMENT_CHARS]; +}; + +#define NR_MEASUREMENT_ENTRIES 8 +struct cmg_entry { + u32 values[NR_MEASUREMENT_ENTRIES]; +}; + struct channel_path_desc { u8 flags; u8 lsn; @@ -27,6 +37,10 @@ struct channel_path { int id; int state; struct channel_path_desc desc; + /* Channel-measurement related stuff: */ + int cmg; + int shared; + void *cmg_chars; struct device dev; }; @@ -52,7 +66,11 @@ struct css_general_char { struct css_chsc_char { u64 res; - u64 : 43; + u64 : 20; + u32 secm : 1; /* bit 84 */ + u32 : 1; + u32 scmc : 1; /* bit 86 */ + u32 : 20; u32 scssc : 1; /* bit 107 */ u32 scsscf : 1; /* bit 108 */ u32 : 19; @@ -67,6 +85,8 @@ extern int css_characteristics_avail; extern void *chsc_get_chp_desc(struct subchannel*, int); extern int chsc_enable_facility(int); +struct channel_subsystem; +extern int chsc_secm(struct channel_subsystem *, int); #define to_channelpath(device) container_of(device, struct channel_path, dev) diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 3c77d65960db..5b304dbacaeb 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -452,15 +452,50 @@ channel_subsystem_release(struct device *dev) struct channel_subsystem *css; css = to_css(dev); + mutex_destroy(&css->mutex); kfree(css); } +static ssize_t +css_cm_enable_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct channel_subsystem *css = to_css(dev); + + if (!css) + return 0; + return sprintf(buf, "%x\n", css->cm_enabled); +} + +static ssize_t +css_cm_enable_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct channel_subsystem *css = to_css(dev); + int ret; + + switch (buf[0]) { + case '0': + ret = css->cm_enabled ? chsc_secm(css, 0) : 0; + break; + case '1': + ret = css->cm_enabled ? 0 : chsc_secm(css, 1); + break; + default: + ret = -EINVAL; + } + return ret < 0 ? ret : count; +} + +static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store); + static inline void __init setup_css(int nr) { u32 tod_high; memset(css[nr], 0, sizeof(struct channel_subsystem)); + mutex_init(&css[nr]->mutex); css[nr]->valid = 1; css[nr]->cssid = nr; sprintf(css[nr]->device.bus_id, "css%x", nr); @@ -507,6 +542,9 @@ init_channel_subsystem (void) ret = device_register(&css[i]->device); if (ret) goto out_free; + if (css_characteristics_avail && css_chsc_characteristics.secm) + device_create_file(&css[i]->device, + &dev_attr_cm_enable); } css_init_done = 1; @@ -519,6 +557,9 @@ out_free: out_unregister: while (i > 0) { i--; + if (css_characteristics_avail && css_chsc_characteristics.secm) + device_remove_file(&css[i]->device, + &dev_attr_cm_enable); device_unregister(&css[i]->device); } out_bus: diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index b6375861cb37..74a257b23383 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h @@ -1,6 +1,7 @@ #ifndef _CSS_H #define _CSS_H +#include #include #include @@ -150,6 +151,11 @@ struct channel_subsystem { struct channel_path *chps[__MAX_CHPID + 1]; struct device device; struct pgid global_pgid; + struct mutex mutex; + /* channel measurement related */ + int cm_enabled; + void *cub_addr1; + void *cub_addr2; }; #define to_css(dev) container_of(dev, struct channel_subsystem, device) -- cgit v1.2.3-59-g8ed1b From 13c6204facb01d425320411c17febff666875518 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 24 Mar 2006 03:15:19 -0800 Subject: [PATCH] s390: use normal switch statement for ioctls in dasd_ioctlc Handle ioctls implemented in dasd_ioctl through the normal switch statement that most drivers use instead of the awkward dasd_ioctl_no_register routine. This avoids searching a linear list on every call to dasd_ioctl(), and allows to give the various ioctl implementation functions sane prototypes, aswell as moving the check for bdev->bd_disk->private_data from the individual functions to dasd_ioctl. (I think it can't actually every be NULL, but let's keep that for later) Signed-off-by: Christoph Hellwig Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd.c | 4 - drivers/s390/block/dasd_int.h | 2 - drivers/s390/block/dasd_ioctl.c | 241 ++++++++++++++-------------------------- 3 files changed, 86 insertions(+), 161 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 33157c84d1d3..9e0b371ebe69 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1807,7 +1807,6 @@ dasd_exit(void) #ifdef CONFIG_PROC_FS dasd_proc_exit(); #endif - dasd_ioctl_exit(); if (dasd_page_cache != NULL) { kmem_cache_destroy(dasd_page_cache); dasd_page_cache = NULL; @@ -2093,9 +2092,6 @@ dasd_init(void) rc = dasd_parse(); if (rc) goto failed; - rc = dasd_ioctl_init(); - if (rc) - goto failed; #ifdef CONFIG_PROC_FS rc = dasd_proc_init(); if (rc) diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 7cb0b9e78a6a..6010ecf76b4c 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -523,8 +523,6 @@ int dasd_scan_partitions(struct dasd_device *); void dasd_destroy_partitions(struct dasd_device *); /* externals in dasd_ioctl.c */ -int dasd_ioctl_init(void); -void dasd_ioctl_exit(void); int dasd_ioctl_no_register(struct module *, int, dasd_ioctl_fn_t); int dasd_ioctl_no_unregister(struct module *, int, dasd_ioctl_fn_t); int dasd_ioctl(struct inode *, struct file *, unsigned int, unsigned long); diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index f9930552ab54..e3ad34686444 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -77,62 +77,11 @@ dasd_ioctl_no_unregister(struct module *owner, int no, dasd_ioctl_fn_t handler) return 0; } -int -dasd_ioctl(struct inode *inp, struct file *filp, - unsigned int no, unsigned long data) -{ - struct block_device *bdev = inp->i_bdev; - struct dasd_device *device = bdev->bd_disk->private_data; - struct dasd_ioctl *ioctl; - const char *dir; - int rc; - - if ((_IOC_DIR(no) != _IOC_NONE) && (data == 0)) { - PRINT_DEBUG("empty data ptr"); - return -EINVAL; - } - dir = _IOC_DIR (no) == _IOC_NONE ? "0" : - _IOC_DIR (no) == _IOC_READ ? "r" : - _IOC_DIR (no) == _IOC_WRITE ? "w" : - _IOC_DIR (no) == (_IOC_READ | _IOC_WRITE) ? "rw" : "u"; - DBF_DEV_EVENT(DBF_DEBUG, device, - "ioctl 0x%08x %s'0x%x'%d(%d) with data %8lx", no, - dir, _IOC_TYPE(no), _IOC_NR(no), _IOC_SIZE(no), data); - /* Search for ioctl no in the ioctl list. */ - list_for_each_entry(ioctl, &dasd_ioctl_list, list) { - if (ioctl->no == no) { - /* Found a matching ioctl. Call it. */ - if (!try_module_get(ioctl->owner)) - continue; - rc = ioctl->handler(bdev, no, data); - module_put(ioctl->owner); - return rc; - } - } - /* No ioctl with number no. */ - DBF_DEV_EVENT(DBF_INFO, device, - "unknown ioctl 0x%08x=%s'0x%x'%d(%d) data %8lx", no, - dir, _IOC_TYPE(no), _IOC_NR(no), _IOC_SIZE(no), data); - return -EINVAL; -} - -long -dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - int rval; - - lock_kernel(); - rval = dasd_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); - unlock_kernel(); - - return (rval == -EINVAL) ? -ENOIOCTLCMD : rval; -} - static int -dasd_ioctl_api_version(struct block_device *bdev, int no, long args) +dasd_ioctl_api_version(void __user *argp) { int ver = DASD_API_VERSION; - return put_user(ver, (int __user *) args); + return put_user(ver, (int *)argp); } /* @@ -140,15 +89,13 @@ dasd_ioctl_api_version(struct block_device *bdev, int no, long args) * used by dasdfmt after BIODASDDISABLE to retrigger blocksize detection */ static int -dasd_ioctl_enable(struct block_device *bdev, int no, long args) +dasd_ioctl_enable(struct block_device *bdev) { - struct dasd_device *device; + struct dasd_device *device = bdev->bd_disk->private_data; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; + dasd_enable_device(device); /* Formatting the dasd device can change the capacity. */ mutex_lock(&bdev->bd_mutex); @@ -162,15 +109,13 @@ dasd_ioctl_enable(struct block_device *bdev, int no, long args) * Used by dasdfmt. Disable I/O operations but allow ioctls. */ static int -dasd_ioctl_disable(struct block_device *bdev, int no, long args) +dasd_ioctl_disable(struct block_device *bdev) { - struct dasd_device *device; + struct dasd_device *device = bdev->bd_disk->private_data; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; + /* * Man this is sick. We don't do a real disable but only downgrade * the device to DASD_STATE_BASIC. The reason is that dasdfmt uses @@ -194,18 +139,13 @@ dasd_ioctl_disable(struct block_device *bdev, int no, long args) * Quiesce device. */ static int -dasd_ioctl_quiesce(struct block_device *bdev, int no, long args) +dasd_ioctl_quiesce(struct dasd_device *device) { - struct dasd_device *device; unsigned long flags; if (!capable (CAP_SYS_ADMIN)) return -EACCES; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - DEV_MESSAGE (KERN_DEBUG, device, "%s", "Quiesce IO on device"); spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); @@ -219,18 +159,13 @@ dasd_ioctl_quiesce(struct block_device *bdev, int no, long args) * Quiesce device. */ static int -dasd_ioctl_resume(struct block_device *bdev, int no, long args) +dasd_ioctl_resume(struct dasd_device *device) { - struct dasd_device *device; unsigned long flags; if (!capable (CAP_SYS_ADMIN)) return -EACCES; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - DEV_MESSAGE (KERN_DEBUG, device, "%s", "resume IO on device"); @@ -302,25 +237,19 @@ dasd_format(struct dasd_device * device, struct format_data_t * fdata) * Format device. */ static int -dasd_ioctl_format(struct block_device *bdev, int no, long args) +dasd_ioctl_format(struct block_device *bdev, void __user *argp) { - struct dasd_device *device; + struct dasd_device *device = bdev->bd_disk->private_data; struct format_data_t fdata; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (!args) + if (!argp) return -EINVAL; - /* fdata == NULL is no longer a valid arg to dasd_format ! */ - device = bdev->bd_disk->private_data; - - if (device == NULL) - return -ENODEV; if (device->features & DASD_FEATURE_READONLY) return -EROFS; - if (copy_from_user(&fdata, (void __user *) args, - sizeof (struct format_data_t))) + if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) return -EFAULT; if (bdev != bdev->bd_contains) { DEV_MESSAGE(KERN_WARNING, device, "%s", @@ -335,17 +264,8 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args) * Reset device profile information */ static int -dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args) +dasd_ioctl_reset_profile(struct dasd_device *device) { - struct dasd_device *device; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - memset(&device->profile, 0, sizeof (struct dasd_profile_info_t)); return 0; } @@ -354,31 +274,24 @@ dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args) * Return device profile information */ static int -dasd_ioctl_read_profile(struct block_device *bdev, int no, long args) +dasd_ioctl_read_profile(struct dasd_device *device, void __user *argp) { - struct dasd_device *device; - - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - if (dasd_profile_level == DASD_PROFILE_OFF) return -EIO; - - if (copy_to_user((long __user *) args, (long *) &device->profile, + if (copy_to_user(argp, &device->profile, sizeof (struct dasd_profile_info_t))) return -EFAULT; return 0; } #else static int -dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args) +dasd_ioctl_reset_profile(struct dasd_device *device) { return -ENOSYS; } static int -dasd_ioctl_read_profile(struct block_device *bdev, int no, long args) +dasd_ioctl_read_profile(struct dasd_device *device, void __user *argp) { return -ENOSYS; } @@ -388,18 +301,14 @@ dasd_ioctl_read_profile(struct block_device *bdev, int no, long args) * Return dasd information. Used for BIODASDINFO and BIODASDINFO2. */ static int -dasd_ioctl_information(struct block_device *bdev, int no, long args) +dasd_ioctl_information(struct dasd_device *device, + unsigned int cmd, void __user *argp) { - struct dasd_device *device; struct dasd_information2_t *dasd_info; unsigned long flags; int rc; struct ccw_device *cdev; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - if (!device->discipline->fill_info) return -EINVAL; @@ -467,8 +376,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) } rc = 0; - if (copy_to_user((long __user *) args, (long *) dasd_info, - ((no == (unsigned int) BIODASDINFO2) ? + if (copy_to_user(argp, dasd_info, + ((cmd == (unsigned int) BIODASDINFO2) ? sizeof (struct dasd_information2_t) : sizeof (struct dasd_information_t)))) rc = -EFAULT; @@ -480,68 +389,90 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) * Set read only */ static int -dasd_ioctl_set_ro(struct block_device *bdev, int no, long args) +dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp) { - struct dasd_device *device; - int intval, rc; + struct dasd_device *device = bdev->bd_disk->private_data; + int intval; if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (bdev != bdev->bd_contains) // ro setting is not allowed for partitions return -EINVAL; - if (get_user(intval, (int __user *) args)) + if (get_user(intval, (int *)argp)) return -EFAULT; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; set_disk_ro(bdev->bd_disk, intval); - rc = dasd_set_feature(device->cdev, DASD_FEATURE_READONLY, intval); - - return rc; + return dasd_set_feature(device->cdev, DASD_FEATURE_READONLY, intval); } -/* - * List of static ioctls. - */ -static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] = -{ - { BIODASDDISABLE, dasd_ioctl_disable }, - { BIODASDENABLE, dasd_ioctl_enable }, - { BIODASDQUIESCE, dasd_ioctl_quiesce }, - { BIODASDRESUME, dasd_ioctl_resume }, - { BIODASDFMT, dasd_ioctl_format }, - { BIODASDINFO, dasd_ioctl_information }, - { BIODASDINFO2, dasd_ioctl_information }, - { BIODASDPRRD, dasd_ioctl_read_profile }, - { BIODASDPRRST, dasd_ioctl_reset_profile }, - { BLKROSET, dasd_ioctl_set_ro }, - { DASDAPIVER, dasd_ioctl_api_version }, - { -1, NULL } -}; - int -dasd_ioctl_init(void) +dasd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { - int i; + struct block_device *bdev = inode->i_bdev; + struct dasd_device *device = bdev->bd_disk->private_data; + void __user *argp = (void __user *)arg; + struct dasd_ioctl *ioctl; + int rc; - for (i = 0; dasd_ioctls[i].no != -1; i++) - dasd_ioctl_no_register(NULL, dasd_ioctls[i].no, - dasd_ioctls[i].fn); - return 0; + if (!device) + return -ENODEV; + + if ((_IOC_DIR(cmd) != _IOC_NONE) && !arg) { + PRINT_DEBUG("empty data ptr"); + return -EINVAL; + } + switch (cmd) { + case BIODASDDISABLE: + return dasd_ioctl_disable(bdev); + case BIODASDENABLE: + return dasd_ioctl_enable(bdev); + case BIODASDQUIESCE: + return dasd_ioctl_quiesce(device); + case BIODASDRESUME: + return dasd_ioctl_resume(device); + case BIODASDFMT: + return dasd_ioctl_format(bdev, argp); + case BIODASDINFO: + return dasd_ioctl_information(device, cmd, argp); + case BIODASDINFO2: + return dasd_ioctl_information(device, cmd, argp); + case BIODASDPRRD: + return dasd_ioctl_read_profile(device, argp); + case BIODASDPRRST: + return dasd_ioctl_reset_profile(device); + case BLKROSET: + return dasd_ioctl_set_ro(bdev, argp); + case DASDAPIVER: + return dasd_ioctl_api_version(argp); + default: + /* resort to the deprecated dynamic ioctl list */ + list_for_each_entry(ioctl, &dasd_ioctl_list, list) { + if (ioctl->no == cmd) { + /* Found a matching ioctl. Call it. */ + if (!try_module_get(ioctl->owner)) + continue; + rc = ioctl->handler(bdev, cmd, arg); + module_put(ioctl->owner); + return rc; + } + } + return -EINVAL; + } } -void -dasd_ioctl_exit(void) +long +dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - int i; + int rval; - for (i = 0; dasd_ioctls[i].no != -1; i++) - dasd_ioctl_no_unregister(NULL, dasd_ioctls[i].no, - dasd_ioctls[i].fn); + lock_kernel(); + rval = dasd_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + unlock_kernel(); + return (rval == -EINVAL) ? -ENOIOCTLCMD : rval; } EXPORT_SYMBOL(dasd_ioctl_no_register); -- cgit v1.2.3-59-g8ed1b From 1107ccfbdef280fedc677af3bdbc405611ba554a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 24 Mar 2006 03:15:20 -0800 Subject: [PATCH] s390: use normal switch statement for ioctls in dasd_ioctlc Add an ->ioctl method to the dasd_discipline structure. This allows to apply the same kind of cleanups the last patch applied to dasd_ioctl.c to dasd_eckd.c (the only dasd discipline with special ioctls) aswell. Again lots of code removed. During auditing the ioctls I found two fishy return value propagations from copy_{from,to}_user, maintainers please check those, I've marked them with XXX comments. Signed-off-by: Christoph Hellwig Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd_eckd.c | 142 +++++++++++++--------------------------- drivers/s390/block/dasd_int.h | 1 + drivers/s390/block/dasd_ioctl.c | 9 ++- 3 files changed, 55 insertions(+), 97 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 822e2a265578..ee09ef33d08d 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1227,19 +1227,14 @@ dasd_eckd_fill_info(struct dasd_device * device, * (see dasd_eckd_reserve) device. */ static int -dasd_eckd_release(struct block_device *bdev, int no, long args) +dasd_eckd_release(struct dasd_device *device) { - struct dasd_device *device; struct dasd_ccw_req *cqr; int rc; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - cqr = dasd_smalloc_request(dasd_eckd_discipline.name, 1, 32, device); if (IS_ERR(cqr)) { @@ -1272,19 +1267,14 @@ dasd_eckd_release(struct block_device *bdev, int no, long args) * the interrupt is outstanding for a certain time. */ static int -dasd_eckd_reserve(struct block_device *bdev, int no, long args) +dasd_eckd_reserve(struct dasd_device *device) { - struct dasd_device *device; struct dasd_ccw_req *cqr; int rc; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - cqr = dasd_smalloc_request(dasd_eckd_discipline.name, 1, 32, device); if (IS_ERR(cqr)) { @@ -1316,19 +1306,14 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args) * (unconditional reserve) */ static int -dasd_eckd_steal_lock(struct block_device *bdev, int no, long args) +dasd_eckd_steal_lock(struct dasd_device *device) { - struct dasd_device *device; struct dasd_ccw_req *cqr; int rc; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - cqr = dasd_smalloc_request(dasd_eckd_discipline.name, 1, 32, device); if (IS_ERR(cqr)) { @@ -1358,19 +1343,14 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args) * Read performance statistics */ static int -dasd_eckd_performance(struct block_device *bdev, int no, long args) +dasd_eckd_performance(struct dasd_device *device, void __user *argp) { - struct dasd_device *device; struct dasd_psf_prssd_data *prssdp; struct dasd_rssd_perf_stats_t *stats; struct dasd_ccw_req *cqr; struct ccw1 *ccw; int rc; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - cqr = dasd_smalloc_request(dasd_eckd_discipline.name, 1 /* PSF */ + 1 /* RSSD */ , (sizeof (struct dasd_psf_prssd_data) + @@ -1414,8 +1394,9 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args) /* Prepare for Read Subsystem Data */ prssdp = (struct dasd_psf_prssd_data *) cqr->data; stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1); - rc = copy_to_user((long __user *) args, (long *) stats, - sizeof(struct dasd_rssd_perf_stats_t)); + if (copy_to_user(argp, stats, + sizeof(struct dasd_rssd_perf_stats_t))) + rc = -EFAULT; } dasd_sfree_request(cqr, cqr->device); return rc; @@ -1426,27 +1407,22 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args) * Returnes the cache attributes used in Define Extend (DE). */ static int -dasd_eckd_get_attrib (struct block_device *bdev, int no, long args) +dasd_eckd_get_attrib(struct dasd_device *device, void __user *argp) { - struct dasd_device *device; - struct dasd_eckd_private *private; - struct attrib_data_t attrib; + struct dasd_eckd_private *private = + (struct dasd_eckd_private *)device->private; + struct attrib_data_t attrib = private->attrib; int rc; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (!args) + if (!argp) return -EINVAL; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - - private = (struct dasd_eckd_private *) device->private; - attrib = private->attrib; - - rc = copy_to_user((long __user *) args, (long *) &attrib, - sizeof (struct attrib_data_t)); + rc = 0; + if (copy_to_user(argp, (long *) &attrib, + sizeof (struct attrib_data_t))) + rc = -EFAULT; return rc; } @@ -1456,26 +1432,19 @@ dasd_eckd_get_attrib (struct block_device *bdev, int no, long args) * Stores the attributes for cache operation to be used in Define Extend (DE). */ static int -dasd_eckd_set_attrib(struct block_device *bdev, int no, long args) +dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp) { - struct dasd_device *device; - struct dasd_eckd_private *private; + struct dasd_eckd_private *private = + (struct dasd_eckd_private *)device->private; struct attrib_data_t attrib; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (!args) + if (!argp) return -EINVAL; - device = bdev->bd_disk->private_data; - if (device == NULL) - return -ENODEV; - - if (copy_from_user(&attrib, (void __user *) args, - sizeof (struct attrib_data_t))) { + if (copy_from_user(&attrib, argp, sizeof(struct attrib_data_t))) return -EFAULT; - } - private = (struct dasd_eckd_private *) device->private; private->attrib = attrib; DEV_MESSAGE(KERN_INFO, device, @@ -1484,6 +1453,27 @@ dasd_eckd_set_attrib(struct block_device *bdev, int no, long args) return 0; } +static int +dasd_eckd_ioctl(struct dasd_device *device, unsigned int cmd, void __user *argp) +{ + switch (cmd) { + case BIODASDGATTR: + return dasd_eckd_get_attrib(device, argp); + case BIODASDSATTR: + return dasd_eckd_set_attrib(device, argp); + case BIODASDPSRD: + return dasd_eckd_performance(device, argp); + case BIODASDRLSE: + return dasd_eckd_release(device); + case BIODASDRSRV: + return dasd_eckd_reserve(device); + case BIODASDSLCK: + return dasd_eckd_steal_lock(device); + default: + return -ENOIOCTLCMD; + } +} + /* * Print sense data and related channel program. * Parts are printed because printk buffer is only 1024 bytes. @@ -1642,6 +1632,7 @@ static struct dasd_discipline dasd_eckd_discipline = { .free_cp = dasd_eckd_free_cp, .dump_sense = dasd_eckd_dump_sense, .fill_info = dasd_eckd_fill_info, + .ioctl = dasd_eckd_ioctl, }; static int __init @@ -1649,59 +1640,18 @@ dasd_eckd_init(void) { int ret; - dasd_ioctl_no_register(THIS_MODULE, BIODASDGATTR, - dasd_eckd_get_attrib); - dasd_ioctl_no_register(THIS_MODULE, BIODASDSATTR, - dasd_eckd_set_attrib); - dasd_ioctl_no_register(THIS_MODULE, BIODASDPSRD, - dasd_eckd_performance); - dasd_ioctl_no_register(THIS_MODULE, BIODASDRLSE, - dasd_eckd_release); - dasd_ioctl_no_register(THIS_MODULE, BIODASDRSRV, - dasd_eckd_reserve); - dasd_ioctl_no_register(THIS_MODULE, BIODASDSLCK, - dasd_eckd_steal_lock); - ASCEBC(dasd_eckd_discipline.ebcname, 4); ret = ccw_driver_register(&dasd_eckd_driver); - if (ret) { - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDGATTR, - dasd_eckd_get_attrib); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSATTR, - dasd_eckd_set_attrib); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDPSRD, - dasd_eckd_performance); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRLSE, - dasd_eckd_release); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRSRV, - dasd_eckd_reserve); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSLCK, - dasd_eckd_steal_lock); - return ret; - } - - dasd_generic_auto_online(&dasd_eckd_driver); - return 0; + if (!ret) + dasd_generic_auto_online(&dasd_eckd_driver); + return ret; } static void __exit dasd_eckd_cleanup(void) { ccw_driver_unregister(&dasd_eckd_driver); - - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDGATTR, - dasd_eckd_get_attrib); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSATTR, - dasd_eckd_set_attrib); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDPSRD, - dasd_eckd_performance); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRLSE, - dasd_eckd_release); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRSRV, - dasd_eckd_reserve); - dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSLCK, - dasd_eckd_steal_lock); } module_init(dasd_eckd_init); diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 6010ecf76b4c..e9485559e22e 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -272,6 +272,7 @@ struct dasd_discipline { /* i/o control functions. */ int (*fill_geometry) (struct dasd_device *, struct hd_geometry *); int (*fill_info) (struct dasd_device *, struct dasd_information2_t *); + int (*ioctl) (struct dasd_device *, unsigned int, void __user *); }; extern struct dasd_discipline *dasd_diag_discipline_pointer; diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index e3ad34686444..bb6caf46bbd9 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -448,7 +448,14 @@ dasd_ioctl(struct inode *inode, struct file *file, case DASDAPIVER: return dasd_ioctl_api_version(argp); default: - /* resort to the deprecated dynamic ioctl list */ + /* if the discipline has an ioctl method try it. */ + if (device->discipline->ioctl) { + int rval = device->discipline->ioctl(device, cmd, argp); + if (rval != -ENOIOCTLCMD) + return rval; + } + + /* else resort to the deprecated dynamic ioctl list */ list_for_each_entry(ioctl, &dasd_ioctl_list, list) { if (ioctl->no == cmd) { /* Found a matching ioctl. Call it. */ -- cgit v1.2.3-59-g8ed1b From 8b2eb664ce9dcba8b54ececf5e057470c47e57f7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 24 Mar 2006 03:15:21 -0800 Subject: [PATCH] s390: merge cmb into dasdc dasd_cmd just implements three ioctls which are wrappers around functionality in the core kernel or other modules. When merging those into dasd_mod they just add 22 lines of code which is far less than the amount of code removed in the last two patches, and which doesn't spill into another 4k pages when build modular, while removing a 128lines module. Signed-off-by: Christoph Hellwig Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/Kconfig | 10 ---- drivers/s390/block/Makefile | 1 - drivers/s390/block/dasd_cmb.c | 128 ---------------------------------------- drivers/s390/block/dasd_ioctl.c | 22 +++++++ 4 files changed, 22 insertions(+), 139 deletions(-) delete mode 100644 drivers/s390/block/dasd_cmb.c (limited to 'drivers') diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig index 6f50cc9323d9..baf9cc3ebae3 100644 --- a/drivers/s390/block/Kconfig +++ b/drivers/s390/block/Kconfig @@ -55,14 +55,4 @@ config DASD_DIAG Disks under VM. If you are not running under VM or unsure what it is, say "N". -config DASD_CMB - tristate "Compatibility interface for DASD channel measurement blocks" - depends on DASD - help - This driver provides an additional interface to the channel measurement - facility, which is normally accessed though sysfs, with a set of - ioctl functions specific to the dasd driver. - This is only needed if you want to use applications written for - linux-2.4 dasd channel measurement facility interface. - endif diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile index 58c6780134f7..163e97554f50 100644 --- a/drivers/s390/block/Makefile +++ b/drivers/s390/block/Makefile @@ -12,6 +12,5 @@ obj-$(CONFIG_DASD) += dasd_mod.o obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o -obj-$(CONFIG_DASD_CMB) += dasd_cmb.o obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o obj-$(CONFIG_DCSSBLK) += dcssblk.o diff --git a/drivers/s390/block/dasd_cmb.c b/drivers/s390/block/dasd_cmb.c deleted file mode 100644 index e88f73ee72ce..000000000000 --- a/drivers/s390/block/dasd_cmb.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Linux on zSeries Channel Measurement Facility support - * (dasd device driver interface) - * - * Copyright 2000,2003 IBM Corporation - * - * Author: Arnd Bergmann - * - * 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; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include - -#include "dasd_int.h" - -static int -dasd_ioctl_cmf_enable(struct block_device *bdev, int no, long args) -{ - struct dasd_device *device; - - device = bdev->bd_disk->private_data; - if (!device) - return -EINVAL; - - return enable_cmf(device->cdev); -} - -static int -dasd_ioctl_cmf_disable(struct block_device *bdev, int no, long args) -{ - struct dasd_device *device; - - device = bdev->bd_disk->private_data; - if (!device) - return -EINVAL; - - return disable_cmf(device->cdev); -} - -static int -dasd_ioctl_readall_cmb(struct block_device *bdev, int no, long args) -{ - struct dasd_device *device; - struct cmbdata __user *udata; - struct cmbdata data; - size_t size; - int ret; - - device = bdev->bd_disk->private_data; - if (!device) - return -EINVAL; - udata = (void __user *) args; - size = _IOC_SIZE(no); - - if (!access_ok(VERIFY_WRITE, udata, size)) - return -EFAULT; - ret = cmf_readall(device->cdev, &data); - if (ret) - return ret; - if (copy_to_user(udata, &data, min(size, sizeof(*udata)))) - return -EFAULT; - return 0; -} - -/* module initialization below here. dasd already provides a mechanism - * to dynamically register ioctl functions, so we simply use this. */ -static inline int -ioctl_reg(unsigned int no, dasd_ioctl_fn_t handler) -{ - return dasd_ioctl_no_register(THIS_MODULE, no, handler); -} - -static inline void -ioctl_unreg(unsigned int no, dasd_ioctl_fn_t handler) -{ - dasd_ioctl_no_unregister(THIS_MODULE, no, handler); -} - -static void -dasd_cmf_exit(void) -{ - ioctl_unreg(BIODASDCMFENABLE, dasd_ioctl_cmf_enable); - ioctl_unreg(BIODASDCMFDISABLE, dasd_ioctl_cmf_disable); - ioctl_unreg(BIODASDREADALLCMB, dasd_ioctl_readall_cmb); -} - -static int __init -dasd_cmf_init(void) -{ - int ret; - ret = ioctl_reg (BIODASDCMFENABLE, dasd_ioctl_cmf_enable); - if (ret) - goto err; - ret = ioctl_reg (BIODASDCMFDISABLE, dasd_ioctl_cmf_disable); - if (ret) - goto err; - ret = ioctl_reg (BIODASDREADALLCMB, dasd_ioctl_readall_cmb); - if (ret) - goto err; - - return 0; -err: - dasd_cmf_exit(); - - return ret; -} - -module_init(dasd_cmf_init); -module_exit(dasd_cmf_exit); - -MODULE_AUTHOR("Arnd Bergmann "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("channel measurement facility interface for dasd\n" - "Copyright 2003 IBM Corporation\n"); diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index bb6caf46bbd9..c8319bef2730 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -16,6 +16,7 @@ #include #include +#include #include /* This is ugly... */ @@ -406,6 +407,21 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp) return dasd_set_feature(device->cdev, DASD_FEATURE_READONLY, intval); } +static int +dasd_ioctl_readall_cmb(struct dasd_device *device, unsigned int cmd, + unsigned long arg) +{ + struct cmbdata __user *argp = (void __user *) arg; + size_t size = _IOC_SIZE(cmd); + struct cmbdata data; + int ret; + + ret = cmf_readall(device->cdev, &data); + if (!ret && copy_to_user(argp, &data, min(size, sizeof(*argp)))) + return -EFAULT; + return ret; +} + int dasd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -447,6 +463,12 @@ dasd_ioctl(struct inode *inode, struct file *file, return dasd_ioctl_set_ro(bdev, argp); case DASDAPIVER: return dasd_ioctl_api_version(argp); + case BIODASDCMFENABLE: + return enable_cmf(device->cdev); + case BIODASDCMFDISABLE: + return disable_cmf(device->cdev); + case BIODASDREADALLCMB: + return dasd_ioctl_readall_cmb(device, cmd, arg); default: /* if the discipline has an ioctl method try it. */ if (device->discipline->ioctl) { -- cgit v1.2.3-59-g8ed1b From 82814dbafdeef53e13e07134eb3b7be3c975fd21 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 24 Mar 2006 03:15:22 -0800 Subject: [PATCH] s390: remove dynamic dasd ioctls Now that there are no more users of the awkward dynamic ioctl hack we can remove the code to support it. Signed-off-by: Christoph Hellwig Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd_int.h | 11 ------- drivers/s390/block/dasd_ioctl.c | 69 ----------------------------------------- 2 files changed, 80 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index e9485559e22e..6d7fa30fa0b8 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -69,15 +69,6 @@ */ struct dasd_device; -typedef int (*dasd_ioctl_fn_t) (struct block_device *bdev, int no, long args); - -struct dasd_ioctl { - struct list_head list; - struct module *owner; - int no; - dasd_ioctl_fn_t handler; -}; - typedef enum { dasd_era_fatal = -1, /* no chance to recover */ dasd_era_none = 0, /* don't recover, everything alright */ @@ -524,8 +515,6 @@ int dasd_scan_partitions(struct dasd_device *); void dasd_destroy_partitions(struct dasd_device *); /* externals in dasd_ioctl.c */ -int dasd_ioctl_no_register(struct module *, int, dasd_ioctl_fn_t); -int dasd_ioctl_no_unregister(struct module *, int, dasd_ioctl_fn_t); int dasd_ioctl(struct inode *, struct file *, unsigned int, unsigned long); long dasd_compat_ioctl(struct file *, unsigned int, unsigned long); diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index c8319bef2730..e1dc0ffee027 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -24,59 +24,6 @@ #include "dasd_int.h" -/* - * SECTION: ioctl functions. - */ -static struct list_head dasd_ioctl_list = LIST_HEAD_INIT(dasd_ioctl_list); - -/* - * Find the ioctl with number no. - */ -static struct dasd_ioctl * -dasd_find_ioctl(int no) -{ - struct dasd_ioctl *ioctl; - - list_for_each_entry (ioctl, &dasd_ioctl_list, list) - if (ioctl->no == no) - return ioctl; - return NULL; -} - -/* - * Register ioctl with number no. - */ -int -dasd_ioctl_no_register(struct module *owner, int no, dasd_ioctl_fn_t handler) -{ - struct dasd_ioctl *new; - if (dasd_find_ioctl(no)) - return -EBUSY; - new = kmalloc(sizeof (struct dasd_ioctl), GFP_KERNEL); - if (new == NULL) - return -ENOMEM; - new->owner = owner; - new->no = no; - new->handler = handler; - list_add(&new->list, &dasd_ioctl_list); - return 0; -} - -/* - * Deregister ioctl with number no. - */ -int -dasd_ioctl_no_unregister(struct module *owner, int no, dasd_ioctl_fn_t handler) -{ - struct dasd_ioctl *old = dasd_find_ioctl(no); - if (old == NULL) - return -ENOENT; - if (old->no != no || old->handler != handler || owner != old->owner) - return -EINVAL; - list_del(&old->list); - kfree(old); - return 0; -} static int dasd_ioctl_api_version(void __user *argp) @@ -429,8 +376,6 @@ dasd_ioctl(struct inode *inode, struct file *file, struct block_device *bdev = inode->i_bdev; struct dasd_device *device = bdev->bd_disk->private_data; void __user *argp = (void __user *)arg; - struct dasd_ioctl *ioctl; - int rc; if (!device) return -ENODEV; @@ -477,17 +422,6 @@ dasd_ioctl(struct inode *inode, struct file *file, return rval; } - /* else resort to the deprecated dynamic ioctl list */ - list_for_each_entry(ioctl, &dasd_ioctl_list, list) { - if (ioctl->no == cmd) { - /* Found a matching ioctl. Call it. */ - if (!try_module_get(ioctl->owner)) - continue; - rc = ioctl->handler(bdev, cmd, arg); - module_put(ioctl->owner); - return rc; - } - } return -EINVAL; } } @@ -503,6 +437,3 @@ dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return (rval == -EINVAL) ? -ENOIOCTLCMD : rval; } - -EXPORT_SYMBOL(dasd_ioctl_no_register); -EXPORT_SYMBOL(dasd_ioctl_no_unregister); -- cgit v1.2.3-59-g8ed1b From d0b2eaa374afd10960a507a3f2ce2f24b85826e4 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 24 Mar 2006 03:15:24 -0800 Subject: [PATCH] s390: remove experimental flag from dasd diag The dasd diag discipline has been tested on 64 bit and is no longer experimental. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig index baf9cc3ebae3..08b3f240197f 100644 --- a/drivers/s390/block/Kconfig +++ b/drivers/s390/block/Kconfig @@ -49,7 +49,7 @@ config DASD_FBA config DASD_DIAG tristate "Support for DIAG access to Disks" - depends on DASD && ( 64BIT = 'n' || EXPERIMENTAL) + depends on DASD help Select this option if you want to use Diagnose250 command to access Disks under VM. If you are not running under VM or unsure what it is, -- cgit v1.2.3-59-g8ed1b From 554a826e0a29f1a88e5a5332f0718c059885ec17 Mon Sep 17 00:00:00 2001 From: Horst Hummel Date: Fri, 24 Mar 2006 03:15:24 -0800 Subject: [PATCH] s390: random values in result of BIODASDINFO2 Use kzalloc to get a zeroed buffer for the structure returned to user space by the BIODASDINFO2 ioctl. Not all fields are set up, e.g. the read_devno is missing. Signed-off-by: Horst Hummel Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd_ioctl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index e1dc0ffee027..d0c2d732dcff 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -260,7 +260,7 @@ dasd_ioctl_information(struct dasd_device *device, if (!device->discipline->fill_info) return -EINVAL; - dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL); + dasd_info = kzalloc(sizeof(struct dasd_information2_t), GFP_KERNEL); if (dasd_info == NULL) return -ENOMEM; @@ -303,8 +303,7 @@ dasd_ioctl_information(struct dasd_device *device, memcpy(dasd_info->type, device->discipline->name, 4); else memcpy(dasd_info->type, "none", 4); - dasd_info->req_queue_len = 0; - dasd_info->chanq_len = 0; + if (device->request_queue->request_fn) { struct list_head *l; #ifdef DASD_EXTENDED_PROFILING -- cgit v1.2.3-59-g8ed1b From 20c644680af1ef9a6b36c0873f59498c98b07ab1 Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Fri, 24 Mar 2006 03:15:25 -0800 Subject: [PATCH] s390: dasd extended error reporting The DASD extended error reporting is a facility that allows to get detailed information about certain problems in the DASD I/O. This information can be used to implement fail-over applications that can recover these problems. Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/Kconfig | 8 + drivers/s390/block/Makefile | 3 + drivers/s390/block/dasd.c | 29 +- drivers/s390/block/dasd_3990_erp.c | 3 + drivers/s390/block/dasd_devmap.c | 41 +++ drivers/s390/block/dasd_eckd.h | 1 + drivers/s390/block/dasd_eer.c | 682 +++++++++++++++++++++++++++++++++++++ drivers/s390/block/dasd_int.h | 46 +++ 8 files changed, 812 insertions(+), 1 deletion(-) create mode 100644 drivers/s390/block/dasd_eer.c (limited to 'drivers') diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig index 08b3f240197f..929d6fff6152 100644 --- a/drivers/s390/block/Kconfig +++ b/drivers/s390/block/Kconfig @@ -55,4 +55,12 @@ config DASD_DIAG Disks under VM. If you are not running under VM or unsure what it is, say "N". +config DASD_EER + bool "Extended error reporting (EER)" + depends on DASD + help + This driver provides a character device interface to the + DASD extended error reporting. This is only needed if you want to + use applications written for the EER facility. + endif diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile index 163e97554f50..be9f22d52fd8 100644 --- a/drivers/s390/block/Makefile +++ b/drivers/s390/block/Makefile @@ -7,6 +7,9 @@ dasd_fba_mod-objs := dasd_fba.o dasd_3370_erp.o dasd_9336_erp.o dasd_diag_mod-objs := dasd_diag.o dasd_mod-objs := dasd.o dasd_ioctl.o dasd_proc.o dasd_devmap.o \ dasd_genhd.o dasd_erp.o +ifdef CONFIG_DASD_EER +dasd_mod-objs += dasd_eer.o +endif obj-$(CONFIG_DASD) += dasd_mod.o obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 9e0b371ebe69..f32f7447588b 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -151,6 +151,8 @@ dasd_state_new_to_known(struct dasd_device *device) static inline void dasd_state_known_to_new(struct dasd_device * device) { + /* Disable extended error reporting for this device. */ + dasd_eer_disable(device); /* Forget the discipline information. */ if (device->discipline) module_put(device->discipline->owner); @@ -892,6 +894,9 @@ dasd_handle_state_change_pending(struct dasd_device *device) struct dasd_ccw_req *cqr; struct list_head *l, *n; + /* First of all start sense subsystem status request. */ + dasd_eer_snss(device); + device->stopped &= ~DASD_STOPPED_PENDING; /* restart all 'running' IO on queue */ @@ -1111,6 +1116,19 @@ restart: } goto restart; } + + /* First of all call extended error reporting. */ + if (dasd_eer_enabled(device) && + cqr->status == DASD_CQR_FAILED) { + dasd_eer_write(device, cqr, DASD_EER_FATALERROR); + + /* restart request */ + cqr->status = DASD_CQR_QUEUED; + cqr->retries = 255; + device->stopped |= DASD_STOPPED_QUIESCE; + goto restart; + } + /* Process finished ERP request. */ if (cqr->refers) { __dasd_process_erp(device, cqr); @@ -1248,7 +1266,8 @@ __dasd_start_head(struct dasd_device * device) cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); /* check FAILFAST */ if (device->stopped & ~DASD_STOPPED_PENDING && - test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) { + test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && + (!dasd_eer_enabled(device))) { cqr->status = DASD_CQR_FAILED; dasd_schedule_bh(device); } @@ -1807,6 +1826,7 @@ dasd_exit(void) #ifdef CONFIG_PROC_FS dasd_proc_exit(); #endif + dasd_eer_exit(); if (dasd_page_cache != NULL) { kmem_cache_destroy(dasd_page_cache); dasd_page_cache = NULL; @@ -2003,6 +2023,9 @@ dasd_generic_notify(struct ccw_device *cdev, int event) switch (event) { case CIO_GONE: case CIO_NO_PATH: + /* First of all call extended error reporting. */ + dasd_eer_write(device, NULL, DASD_EER_NOPATH); + if (device->state < DASD_STATE_BASIC) break; /* Device is active. We want to keep it. */ @@ -2060,6 +2083,7 @@ dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver) put_driver(drv); } + static int __init dasd_init(void) { @@ -2092,6 +2116,9 @@ dasd_init(void) rc = dasd_parse(); if (rc) goto failed; + rc = dasd_eer_init(); + if (rc) + goto failed; #ifdef CONFIG_PROC_FS rc = dasd_proc_init(); if (rc) diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 4ee0f934e325..2ed51562319e 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -1108,6 +1108,9 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) case 0x0B: DEV_MESSAGE(KERN_WARNING, device, "%s", "FORMAT F - Volume is suspended duplex"); + /* call extended error reporting (EER) */ + dasd_eer_write(device, erp->refers, + DASD_EER_PPRCSUSPEND); break; case 0x0C: DEV_MESSAGE(KERN_WARNING, device, "%s", diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 1629b27c48ab..f576f243cd93 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -715,10 +715,51 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *bu static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL); +/* + * extended error-reporting + */ +static ssize_t +dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct dasd_devmap *devmap; + int eer_flag; + + devmap = dasd_find_busid(dev->bus_id); + if (!IS_ERR(devmap) && devmap->device) + eer_flag = dasd_eer_enabled(devmap->device); + else + eer_flag = 0; + return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n"); +} + +static ssize_t +dasd_eer_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct dasd_devmap *devmap; + int rc; + + devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); + if (IS_ERR(devmap)) + return PTR_ERR(devmap); + if (!devmap->device) + return count; + if (buf[0] == '1') { + rc = dasd_eer_enable(devmap->device); + if (rc) + return rc; + } else + dasd_eer_disable(devmap->device); + return count; +} + +static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store); + static struct attribute * dasd_attrs[] = { &dev_attr_readonly.attr, &dev_attr_discipline.attr, &dev_attr_use_diag.attr, + &dev_attr_eer_enabled.attr, NULL, }; diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index bc3823d35223..ad8524bb7bb3 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -29,6 +29,7 @@ #define DASD_ECKD_CCW_PSF 0x27 #define DASD_ECKD_CCW_RSSD 0x3e #define DASD_ECKD_CCW_LOCATE_RECORD 0x47 +#define DASD_ECKD_CCW_SNSS 0x54 #define DASD_ECKD_CCW_DEFINE_EXTENT 0x63 #define DASD_ECKD_CCW_WRITE_MT 0x85 #define DASD_ECKD_CCW_READ_MT 0x86 diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c new file mode 100644 index 000000000000..2d946b6ca074 --- /dev/null +++ b/drivers/s390/block/dasd_eer.c @@ -0,0 +1,682 @@ +/* + * Character device driver for extended error reporting. + * + * Copyright (C) 2005 IBM Corporation + * extended error reporting for DASD ECKD devices + * Author(s): Stefan Weinhuber + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dasd_int.h" +#include "dasd_eckd.h" + +#ifdef PRINTK_HEADER +#undef PRINTK_HEADER +#endif /* PRINTK_HEADER */ +#define PRINTK_HEADER "dasd(eer):" + +/* + * SECTION: the internal buffer + */ + +/* + * The internal buffer is meant to store obaque blobs of data, so it does + * not know of higher level concepts like triggers. + * It consists of a number of pages that are used as a ringbuffer. Each data + * blob is stored in a simple record that consists of an integer, which + * contains the size of the following data, and the data bytes themselfes. + * + * To allow for multiple independent readers we create one internal buffer + * each time the device is opened and destroy the buffer when the file is + * closed again. The number of pages used for this buffer is determined by + * the module parmeter eer_pages. + * + * One record can be written to a buffer by using the functions + * - dasd_eer_start_record (one time per record to write the size to the + * buffer and reserve the space for the data) + * - dasd_eer_write_buffer (one or more times per record to write the data) + * The data can be written in several steps but you will have to compute + * the total size up front for the invocation of dasd_eer_start_record. + * If the ringbuffer is full, dasd_eer_start_record will remove the required + * number of old records. + * + * A record is typically read in two steps, first read the integer that + * specifies the size of the following data, then read the data. + * Both can be done by + * - dasd_eer_read_buffer + * + * For all mentioned functions you need to get the bufferlock first and keep + * it until a complete record is written or read. + * + * All information necessary to keep track of an internal buffer is kept in + * a struct eerbuffer. The buffer specific to a file pointer is strored in + * the private_data field of that file. To be able to write data to all + * existing buffers, each buffer is also added to the bufferlist. + * If the user does not want to read a complete record in one go, we have to + * keep track of the rest of the record. residual stores the number of bytes + * that are still to deliver. If the rest of the record is invalidated between + * two reads then residual will be set to -1 so that the next read will fail. + * All entries in the eerbuffer structure are protected with the bufferlock. + * To avoid races between writing to a buffer on the one side and creating + * and destroying buffers on the other side, the bufferlock must also be used + * to protect the bufferlist. + */ + +static int eer_pages = 5; +module_param(eer_pages, int, S_IRUGO|S_IWUSR); + +struct eerbuffer { + struct list_head list; + char **buffer; + int buffersize; + int buffer_page_count; + int head; + int tail; + int residual; +}; + +static LIST_HEAD(bufferlist); +static spinlock_t bufferlock = SPIN_LOCK_UNLOCKED; +static DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue); + +/* + * How many free bytes are available on the buffer. + * Needs to be called with bufferlock held. + */ +static int dasd_eer_get_free_bytes(struct eerbuffer *eerb) +{ + if (eerb->head < eerb->tail) + return eerb->tail - eerb->head - 1; + return eerb->buffersize - eerb->head + eerb->tail -1; +} + +/* + * How many bytes of buffer space are used. + * Needs to be called with bufferlock held. + */ +static int dasd_eer_get_filled_bytes(struct eerbuffer *eerb) +{ + + if (eerb->head >= eerb->tail) + return eerb->head - eerb->tail; + return eerb->buffersize - eerb->tail + eerb->head; +} + +/* + * The dasd_eer_write_buffer function just copies count bytes of data + * to the buffer. Make sure to call dasd_eer_start_record first, to + * make sure that enough free space is available. + * Needs to be called with bufferlock held. + */ +static void dasd_eer_write_buffer(struct eerbuffer *eerb, + char *data, int count) +{ + + unsigned long headindex,localhead; + unsigned long rest, len; + char *nextdata; + + nextdata = data; + rest = count; + while (rest > 0) { + headindex = eerb->head / PAGE_SIZE; + localhead = eerb->head % PAGE_SIZE; + len = min(rest, PAGE_SIZE - localhead); + memcpy(eerb->buffer[headindex]+localhead, nextdata, len); + nextdata += len; + rest -= len; + eerb->head += len; + if (eerb->head == eerb->buffersize) + eerb->head = 0; /* wrap around */ + BUG_ON(eerb->head > eerb->buffersize); + } +} + +/* + * Needs to be called with bufferlock held. + */ +static int dasd_eer_read_buffer(struct eerbuffer *eerb, char *data, int count) +{ + + unsigned long tailindex,localtail; + unsigned long rest, len, finalcount; + char *nextdata; + + finalcount = min(count, dasd_eer_get_filled_bytes(eerb)); + nextdata = data; + rest = finalcount; + while (rest > 0) { + tailindex = eerb->tail / PAGE_SIZE; + localtail = eerb->tail % PAGE_SIZE; + len = min(rest, PAGE_SIZE - localtail); + memcpy(nextdata, eerb->buffer[tailindex] + localtail, len); + nextdata += len; + rest -= len; + eerb->tail += len; + if (eerb->tail == eerb->buffersize) + eerb->tail = 0; /* wrap around */ + BUG_ON(eerb->tail > eerb->buffersize); + } + return finalcount; +} + +/* + * Whenever you want to write a blob of data to the internal buffer you + * have to start by using this function first. It will write the number + * of bytes that will be written to the buffer. If necessary it will remove + * old records to make room for the new one. + * Needs to be called with bufferlock held. + */ +static int dasd_eer_start_record(struct eerbuffer *eerb, int count) +{ + int tailcount; + + if (count + sizeof(count) > eerb->buffersize) + return -ENOMEM; + while (dasd_eer_get_free_bytes(eerb) < count + sizeof(count)) { + if (eerb->residual > 0) { + eerb->tail += eerb->residual; + if (eerb->tail >= eerb->buffersize) + eerb->tail -= eerb->buffersize; + eerb->residual = -1; + } + dasd_eer_read_buffer(eerb, (char *) &tailcount, + sizeof(tailcount)); + eerb->tail += tailcount; + if (eerb->tail >= eerb->buffersize) + eerb->tail -= eerb->buffersize; + } + dasd_eer_write_buffer(eerb, (char*) &count, sizeof(count)); + + return 0; +}; + +/* + * Release pages that are not used anymore. + */ +static void dasd_eer_free_buffer_pages(char **buf, int no_pages) +{ + int i; + + for (i = 0; i < no_pages; i++) + free_page((unsigned long) buf[i]); +} + +/* + * Allocate a new set of memory pages. + */ +static int dasd_eer_allocate_buffer_pages(char **buf, int no_pages) +{ + int i; + + for (i = 0; i < no_pages; i++) { + buf[i] = (char *) get_zeroed_page(GFP_KERNEL); + if (!buf[i]) { + dasd_eer_free_buffer_pages(buf, i); + return -ENOMEM; + } + } + return 0; +} + +/* + * SECTION: The extended error reporting functionality + */ + +/* + * When a DASD device driver wants to report an error, it calls the + * function dasd_eer_write and gives the respective trigger ID as + * parameter. Currently there are four kinds of triggers: + * + * DASD_EER_FATALERROR: all kinds of unrecoverable I/O problems + * DASD_EER_PPRCSUSPEND: PPRC was suspended + * DASD_EER_NOPATH: There is no path to the device left. + * DASD_EER_STATECHANGE: The state of the device has changed. + * + * For the first three triggers all required information can be supplied by + * the caller. For these triggers a record is written by the function + * dasd_eer_write_standard_trigger. + * + * The DASD_EER_STATECHANGE trigger is special since a sense subsystem + * status ccw need to be executed to gather the necessary sense data first. + * The dasd_eer_snss function will queue the SNSS request and the request + * callback will then call dasd_eer_write with the DASD_EER_STATCHANGE + * trigger. + * + * To avoid memory allocations at runtime, the necessary memory is allocated + * when the extended error reporting is enabled for a device (by + * dasd_eer_probe). There is one sense subsystem status request for each + * eer enabled DASD device. The presence of the cqr in device->eer_cqr + * indicates that eer is enable for the device. The use of the snss request + * is protected by the DASD_FLAG_EER_IN_USE bit. When this flag indicates + * that the cqr is currently in use, dasd_eer_snss cannot start a second + * request but sets the DASD_FLAG_EER_SNSS flag instead. The callback of + * the SNSS request will check the bit and call dasd_eer_snss again. + */ + +#define SNSS_DATA_SIZE 44 + +#define DASD_EER_BUSID_SIZE 10 +struct dasd_eer_header { + __u32 total_size; + __u32 trigger; + __u64 tv_sec; + __u64 tv_usec; + char busid[DASD_EER_BUSID_SIZE]; +}; + +/* + * The following function can be used for those triggers that have + * all necessary data available when the function is called. + * If the parameter cqr is not NULL, the chain of requests will be searched + * for valid sense data, and all valid sense data sets will be added to + * the triggers data. + */ +static void dasd_eer_write_standard_trigger(struct dasd_device *device, + struct dasd_ccw_req *cqr, + int trigger) +{ + struct dasd_ccw_req *temp_cqr; + int data_size; + struct timeval tv; + struct dasd_eer_header header; + unsigned long flags; + struct eerbuffer *eerb; + + /* go through cqr chain and count the valid sense data sets */ + data_size = 0; + for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) + if (temp_cqr->irb.esw.esw0.erw.cons) + data_size += 32; + + header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ + header.trigger = trigger; + do_gettimeofday(&tv); + header.tv_sec = tv.tv_sec; + header.tv_usec = tv.tv_usec; + strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); + + spin_lock_irqsave(&bufferlock, flags); + list_for_each_entry(eerb, &bufferlist, list) { + dasd_eer_start_record(eerb, header.total_size); + dasd_eer_write_buffer(eerb, (char *) &header, sizeof(header)); + for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) + if (temp_cqr->irb.esw.esw0.erw.cons) + dasd_eer_write_buffer(eerb, cqr->irb.ecw, 32); + dasd_eer_write_buffer(eerb, "EOR", 4); + } + spin_unlock_irqrestore(&bufferlock, flags); + wake_up_interruptible(&dasd_eer_read_wait_queue); +} + +/* + * This function writes a DASD_EER_STATECHANGE trigger. + */ +static void dasd_eer_write_snss_trigger(struct dasd_device *device, + struct dasd_ccw_req *cqr, + int trigger) +{ + int data_size; + int snss_rc; + struct timeval tv; + struct dasd_eer_header header; + unsigned long flags; + struct eerbuffer *eerb; + + snss_rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; + if (snss_rc) + data_size = 0; + else + data_size = SNSS_DATA_SIZE; + + header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ + header.trigger = DASD_EER_STATECHANGE; + do_gettimeofday(&tv); + header.tv_sec = tv.tv_sec; + header.tv_usec = tv.tv_usec; + strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); + + spin_lock_irqsave(&bufferlock, flags); + list_for_each_entry(eerb, &bufferlist, list) { + dasd_eer_start_record(eerb, header.total_size); + dasd_eer_write_buffer(eerb, (char *) &header , sizeof(header)); + if (!snss_rc) + dasd_eer_write_buffer(eerb, cqr->data, SNSS_DATA_SIZE); + dasd_eer_write_buffer(eerb, "EOR", 4); + } + spin_unlock_irqrestore(&bufferlock, flags); + wake_up_interruptible(&dasd_eer_read_wait_queue); +} + +/* + * This function is called for all triggers. It calls the appropriate + * function that writes the actual trigger records. + */ +void dasd_eer_write(struct dasd_device *device, struct dasd_ccw_req *cqr, + unsigned int id) +{ + if (!device->eer_cqr) + return; + switch (id) { + case DASD_EER_FATALERROR: + case DASD_EER_PPRCSUSPEND: + dasd_eer_write_standard_trigger(device, cqr, id); + break; + case DASD_EER_NOPATH: + dasd_eer_write_standard_trigger(device, NULL, id); + break; + case DASD_EER_STATECHANGE: + dasd_eer_write_snss_trigger(device, cqr, id); + break; + default: /* unknown trigger, so we write it without any sense data */ + dasd_eer_write_standard_trigger(device, NULL, id); + break; + } +} +EXPORT_SYMBOL(dasd_eer_write); + +/* + * Start a sense subsystem status request. + * Needs to be called with the device held. + */ +void dasd_eer_snss(struct dasd_device *device) +{ + struct dasd_ccw_req *cqr; + + cqr = device->eer_cqr; + if (!cqr) /* Device not eer enabled. */ + return; + if (test_and_set_bit(DASD_FLAG_EER_IN_USE, &device->flags)) { + /* Sense subsystem status request in use. */ + set_bit(DASD_FLAG_EER_SNSS, &device->flags); + return; + } + clear_bit(DASD_FLAG_EER_SNSS, &device->flags); + cqr->status = DASD_CQR_QUEUED; + list_add(&cqr->list, &device->ccw_queue); + dasd_schedule_bh(device); +} + +/* + * Callback function for use with sense subsystem status request. + */ +static void dasd_eer_snss_cb(struct dasd_ccw_req *cqr, void *data) +{ + struct dasd_device *device = cqr->device; + unsigned long flags; + + dasd_eer_write(device, cqr, DASD_EER_STATECHANGE); + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + if (device->eer_cqr == cqr) { + clear_bit(DASD_FLAG_EER_IN_USE, &device->flags); + if (test_bit(DASD_FLAG_EER_SNSS, &device->flags)) + /* Another SNSS has been requested in the meantime. */ + dasd_eer_snss(device); + cqr = NULL; + } + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + if (cqr) + /* + * Extended error recovery has been switched off while + * the SNSS request was running. It could even have + * been switched off and on again in which case there + * is a new ccw in device->eer_cqr. Free the "old" + * snss request now. + */ + dasd_kfree_request(cqr, device); +} + +/* + * Enable error reporting on a given device. + */ +int dasd_eer_enable(struct dasd_device *device) +{ + struct dasd_ccw_req *cqr; + unsigned long flags; + + if (device->eer_cqr) + return 0; + + if (!device->discipline || strcmp(device->discipline->name, "ECKD")) + return -EPERM; /* FIXME: -EMEDIUMTYPE ? */ + + cqr = dasd_kmalloc_request("ECKD", 1 /* SNSS */, + SNSS_DATA_SIZE, device); + if (!cqr) + return -ENOMEM; + + cqr->device = device; + cqr->retries = 255; + cqr->expires = 10 * HZ; + + cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SNSS; + cqr->cpaddr->count = SNSS_DATA_SIZE; + cqr->cpaddr->flags = 0; + cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; + + cqr->buildclk = get_clock(); + cqr->status = DASD_CQR_FILLED; + cqr->callback = dasd_eer_snss_cb; + + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + if (!device->eer_cqr) { + device->eer_cqr = cqr; + cqr = NULL; + } + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + if (cqr) + dasd_kfree_request(cqr, device); + return 0; +} + +/* + * Disable error reporting on a given device. + */ +void dasd_eer_disable(struct dasd_device *device) +{ + struct dasd_ccw_req *cqr; + unsigned long flags; + int in_use; + + if (!device->eer_cqr) + return; + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + cqr = device->eer_cqr; + device->eer_cqr = NULL; + clear_bit(DASD_FLAG_EER_SNSS, &device->flags); + in_use = test_and_clear_bit(DASD_FLAG_EER_IN_USE, &device->flags); + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + if (cqr && !in_use) + dasd_kfree_request(cqr, device); +} + +/* + * SECTION: the device operations + */ + +/* + * On the one side we need a lock to access our internal buffer, on the + * other side a copy_to_user can sleep. So we need to copy the data we have + * to transfer in a readbuffer, which is protected by the readbuffer_mutex. + */ +static char readbuffer[PAGE_SIZE]; +static DECLARE_MUTEX(readbuffer_mutex); + +static int dasd_eer_open(struct inode *inp, struct file *filp) +{ + struct eerbuffer *eerb; + unsigned long flags; + + eerb = kzalloc(sizeof(struct eerbuffer), GFP_KERNEL); + eerb->buffer_page_count = eer_pages; + if (eerb->buffer_page_count < 1 || + eerb->buffer_page_count > INT_MAX / PAGE_SIZE) { + kfree(eerb); + MESSAGE(KERN_WARNING, "can't open device since module " + "parameter eer_pages is smaller then 1 or" + " bigger then %d", (int)(INT_MAX / PAGE_SIZE)); + return -EINVAL; + } + eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE; + eerb->buffer = kmalloc(eerb->buffer_page_count * sizeof(char *), + GFP_KERNEL); + if (!eerb->buffer) { + kfree(eerb); + return -ENOMEM; + } + if (dasd_eer_allocate_buffer_pages(eerb->buffer, + eerb->buffer_page_count)) { + kfree(eerb->buffer); + kfree(eerb); + return -ENOMEM; + } + filp->private_data = eerb; + spin_lock_irqsave(&bufferlock, flags); + list_add(&eerb->list, &bufferlist); + spin_unlock_irqrestore(&bufferlock, flags); + + return nonseekable_open(inp,filp); +} + +static int dasd_eer_close(struct inode *inp, struct file *filp) +{ + struct eerbuffer *eerb; + unsigned long flags; + + eerb = (struct eerbuffer *) filp->private_data; + spin_lock_irqsave(&bufferlock, flags); + list_del(&eerb->list); + spin_unlock_irqrestore(&bufferlock, flags); + dasd_eer_free_buffer_pages(eerb->buffer, eerb->buffer_page_count); + kfree(eerb->buffer); + kfree(eerb); + + return 0; +} + +static ssize_t dasd_eer_read(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + int tc,rc; + int tailcount,effective_count; + unsigned long flags; + struct eerbuffer *eerb; + + eerb = (struct eerbuffer *) filp->private_data; + if (down_interruptible(&readbuffer_mutex)) + return -ERESTARTSYS; + + spin_lock_irqsave(&bufferlock, flags); + + if (eerb->residual < 0) { /* the remainder of this record */ + /* has been deleted */ + eerb->residual = 0; + spin_unlock_irqrestore(&bufferlock, flags); + up(&readbuffer_mutex); + return -EIO; + } else if (eerb->residual > 0) { + /* OK we still have a second half of a record to deliver */ + effective_count = min(eerb->residual, (int) count); + eerb->residual -= effective_count; + } else { + tc = 0; + while (!tc) { + tc = dasd_eer_read_buffer(eerb, (char *) &tailcount, + sizeof(tailcount)); + if (!tc) { + /* no data available */ + spin_unlock_irqrestore(&bufferlock, flags); + up(&readbuffer_mutex); + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + rc = wait_event_interruptible( + dasd_eer_read_wait_queue, + eerb->head != eerb->tail); + if (rc) + return rc; + if (down_interruptible(&readbuffer_mutex)) + return -ERESTARTSYS; + spin_lock_irqsave(&bufferlock, flags); + } + } + WARN_ON(tc != sizeof(tailcount)); + effective_count = min(tailcount,(int)count); + eerb->residual = tailcount - effective_count; + } + + tc = dasd_eer_read_buffer(eerb, readbuffer, effective_count); + WARN_ON(tc != effective_count); + + spin_unlock_irqrestore(&bufferlock, flags); + + if (copy_to_user(buf, readbuffer, effective_count)) { + up(&readbuffer_mutex); + return -EFAULT; + } + + up(&readbuffer_mutex); + return effective_count; +} + +static unsigned int dasd_eer_poll(struct file *filp, poll_table *ptable) +{ + unsigned int mask; + unsigned long flags; + struct eerbuffer *eerb; + + eerb = (struct eerbuffer *) filp->private_data; + poll_wait(filp, &dasd_eer_read_wait_queue, ptable); + spin_lock_irqsave(&bufferlock, flags); + if (eerb->head != eerb->tail) + mask = POLLIN | POLLRDNORM ; + else + mask = 0; + spin_unlock_irqrestore(&bufferlock, flags); + return mask; +} + +static struct file_operations dasd_eer_fops = { + .open = &dasd_eer_open, + .release = &dasd_eer_close, + .read = &dasd_eer_read, + .poll = &dasd_eer_poll, + .owner = THIS_MODULE, +}; + +static struct miscdevice dasd_eer_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "dasd_eer", + .fops = &dasd_eer_fops, +}; + +int __init dasd_eer_init(void) +{ + int rc; + + rc = misc_register(&dasd_eer_dev); + if (rc) { + MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " + "register misc device"); + return rc; + } + + return 0; +} + +void __exit dasd_eer_exit(void) +{ + WARN_ON(misc_deregister(&dasd_eer_dev) != 0); +} diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 6d7fa30fa0b8..4293ba827523 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -268,6 +268,23 @@ struct dasd_discipline { extern struct dasd_discipline *dasd_diag_discipline_pointer; + +/* + * Notification numbers for extended error reporting notifications: + * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's + * eer pointer) is freed. The error reporting module needs to do all necessary + * cleanup steps. + * The DASD_EER_TRIGGER notification sends the actual error reports (triggers). + */ +#define DASD_EER_DISABLE 0 +#define DASD_EER_TRIGGER 1 + +/* Trigger IDs for extended error reporting DASD_EER_TRIGGER notification */ +#define DASD_EER_FATALERROR 1 +#define DASD_EER_NOPATH 2 +#define DASD_EER_STATECHANGE 3 +#define DASD_EER_PPRCSUSPEND 4 + struct dasd_device { /* Block device stuff. */ struct gendisk *gdp; @@ -281,6 +298,9 @@ struct dasd_device { unsigned long flags; /* per device flags */ unsigned short features; /* copy of devmap-features (read-only!) */ + /* extended error reporting stuff (eer) */ + struct dasd_ccw_req *eer_cqr; + /* Device discipline stuff. */ struct dasd_discipline *discipline; struct dasd_discipline *base_discipline; @@ -326,6 +346,8 @@ struct dasd_device { /* per device flags */ #define DASD_FLAG_DSC_ERROR 2 /* return -EIO when disconnected */ #define DASD_FLAG_OFFLINE 3 /* device is in offline processing */ +#define DASD_FLAG_EER_SNSS 4 /* A SNSS is required */ +#define DASD_FLAG_EER_IN_USE 5 /* A SNSS request is running */ void dasd_put_device_wake(struct dasd_device *); @@ -545,6 +567,30 @@ dasd_era_t dasd_9336_erp_examine(struct dasd_ccw_req *, struct irb *); dasd_era_t dasd_9343_erp_examine(struct dasd_ccw_req *, struct irb *); struct dasd_ccw_req *dasd_9343_erp_action(struct dasd_ccw_req *); +/* externals in dasd_eer.c */ +#ifdef CONFIG_DASD_EER +int dasd_eer_init(void); +void dasd_eer_exit(void); +int dasd_eer_enable(struct dasd_device *); +void dasd_eer_disable(struct dasd_device *); +void dasd_eer_write(struct dasd_device *, struct dasd_ccw_req *cqr, + unsigned int id); +void dasd_eer_snss(struct dasd_device *); + +static inline int dasd_eer_enabled(struct dasd_device *device) +{ + return device->eer_cqr != NULL; +} +#else +#define dasd_eer_init() (0) +#define dasd_eer_exit() do { } while (0) +#define dasd_eer_enable(d) (0) +#define dasd_eer_disable(d) do { } while (0) +#define dasd_eer_write(d,c,i) do { } while (0) +#define dasd_eer_snss(d) do { } while (0) +#define dasd_eer_enabled(d) (0) +#endif /* CONFIG_DASD_ERR */ + #endif /* __KERNEL__ */ #endif /* DASD_H */ -- cgit v1.2.3-59-g8ed1b From 842d3fba94ed94cc5de7b712e0f4218ce6e4fd73 Mon Sep 17 00:00:00 2001 From: Stefan Bader Date: Fri, 24 Mar 2006 03:15:26 -0800 Subject: [PATCH] s390: tape retry flooding by deferred CC in interrupt If a deferred CC happens there will be lots of messages, because the retry is done immediatly in the interrupt handler which can be too fast. To avoid this requeue the request and schedule the queue to be processed. Signed-off-by: Stefan Bader Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/char/tape_core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 4ea438c749c9..c42f5e25024e 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -1064,15 +1064,16 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) /* * If the condition code is not zero and the start function bit is * still set, this is an deferred error and the last start I/O did - * not succeed. Restart the request now. + * not succeed. At this point the condition that caused the deferred + * error might still apply. So we just schedule the request to be + * started later. */ if (irb->scsw.cc != 0 && (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) { PRINT_WARN("(%s): deferred cc=%i. restaring\n", cdev->dev.bus_id, irb->scsw.cc); - rc = __tape_start_io(device, request); - if (rc) - __tape_end_request(device, request, rc); + request->status = TAPE_REQUEST_QUEUED; + schedule_work(&device->tape_dnr); return; } -- cgit v1.2.3-59-g8ed1b From 4cd190a736a97e302c038bd91357d636369d4c6b Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Fri, 24 Mar 2006 03:15:27 -0800 Subject: [PATCH] s390: tape operation abortion leads to panic When a request is aborted because of a signal, we currently stop the request via csh, but we do not wait for the interrupt of csh in any case. We free the request structure and therefore when the interrupt for the csh operation is presented, the request object is no longer valid and an invalid callback pointer is used. To fix this wait until the interrupt for csh arrives and until wait_event_interruptible() does not return -ERESTARTSYS. Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/char/tape_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index c42f5e25024e..5d17149a6529 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -1015,7 +1015,7 @@ tape_do_io_interruptible(struct tape_device *device, wq, (request->callback == NULL) ); - } while (rc != -ERESTARTSYS); + } while (rc == -ERESTARTSYS); DBF_EVENT(3, "IO stopped on %08x\n", device->cdev_id); rc = -ERESTARTSYS; -- cgit v1.2.3-59-g8ed1b From 5f38433885245dce82aa53c20a6b2efbe81ae350 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Fri, 24 Mar 2006 03:15:28 -0800 Subject: [PATCH] s390: fix endless retry loop in tape driver If a tape device is assigned to another host, the interrupt for the assign operation comes back with deferred condition code 1. Under some conditions this can lead to an endless loop of retries. Check if the current request is still in IO in deferred condition code handling and prevent retries when the request has already been cancelled. Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/char/tape.h | 1 + drivers/s390/char/tape_core.c | 32 +++++++++++++++++++++++++++----- drivers/s390/char/tape_std.c | 15 +++++++-------- 3 files changed, 35 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h index 01d865d93791..cd51ace8b610 100644 --- a/drivers/s390/char/tape.h +++ b/drivers/s390/char/tape.h @@ -250,6 +250,7 @@ extern void tape_free_request(struct tape_request *); extern int tape_do_io(struct tape_device *, struct tape_request *); extern int tape_do_io_async(struct tape_device *, struct tape_request *); extern int tape_do_io_interruptible(struct tape_device *, struct tape_request *); +extern int tape_cancel_io(struct tape_device *, struct tape_request *); void tape_hotplug_event(struct tape_device *, int major, int action); static inline int diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 5d17149a6529..c6fab5dbdd44 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -761,6 +761,13 @@ __tape_start_next_request(struct tape_device *device) */ if (request->status == TAPE_REQUEST_IN_IO) return; + /* + * Request has already been stopped. We have to wait until + * the request is removed from the queue in the interrupt + * handling. + */ + if (request->status == TAPE_REQUEST_DONE) + return; /* * We wanted to cancel the request but the common I/O layer @@ -1023,6 +1030,20 @@ tape_do_io_interruptible(struct tape_device *device, return rc; } +/* + * Stop running ccw. + */ +int +tape_cancel_io(struct tape_device *device, struct tape_request *request) +{ + int rc; + + spin_lock_irq(get_ccwdev_lock(device->cdev)); + rc = __tape_cancel_io(device, request); + spin_unlock_irq(get_ccwdev_lock(device->cdev)); + return rc; +} + /* * Tape interrupt routine, called from the ccw_device layer */ @@ -1068,12 +1089,12 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) * error might still apply. So we just schedule the request to be * started later. */ - if (irb->scsw.cc != 0 && (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) { - PRINT_WARN("(%s): deferred cc=%i. restaring\n", - cdev->dev.bus_id, - irb->scsw.cc); + if (irb->scsw.cc != 0 && (irb->scsw.fctl & SCSW_FCTL_START_FUNC) && + (request->status == TAPE_REQUEST_IN_IO)) { + DBF_EVENT(3,"(%08x): deferred cc=%i, fctl=%i. restarting\n", + device->cdev_id, irb->scsw.cc, irb->scsw.fctl); request->status = TAPE_REQUEST_QUEUED; - schedule_work(&device->tape_dnr); + schedule_delayed_work(&device->tape_dnr, HZ); return; } @@ -1287,4 +1308,5 @@ EXPORT_SYMBOL(tape_dump_sense_dbf); EXPORT_SYMBOL(tape_do_io); EXPORT_SYMBOL(tape_do_io_async); EXPORT_SYMBOL(tape_do_io_interruptible); +EXPORT_SYMBOL(tape_cancel_io); EXPORT_SYMBOL(tape_mtop); diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index 2f9fe30989a7..99cf881f41db 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c @@ -37,20 +37,19 @@ tape_std_assign_timeout(unsigned long data) { struct tape_request * request; struct tape_device * device; + int rc; request = (struct tape_request *) data; if ((device = request->device) == NULL) BUG(); - spin_lock_irq(get_ccwdev_lock(device->cdev)); - if (request->callback != NULL) { - DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n", + DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n", device->cdev_id); - PRINT_ERR("%s: Assignment timeout. Device busy.\n", - device->cdev->dev.bus_id); - ccw_device_clear(device->cdev, (long) request); - } - spin_unlock_irq(get_ccwdev_lock(device->cdev)); + rc = tape_cancel_io(device, request); + if(rc) + PRINT_ERR("(%s): Assign timeout: Cancel failed with rc = %i\n", + device->cdev->dev.bus_id, rc); + } int -- cgit v1.2.3-59-g8ed1b From b6cba4ee31e7376fa363c4b89ca502ac5e17eac1 Mon Sep 17 00:00:00 2001 From: Stefan Bader Date: Fri, 24 Mar 2006 03:15:29 -0800 Subject: [PATCH] s390: 3590 tape driver Michael Holzheu , Martin Schwidefsky Signed-off-by: Stefan Bader Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/Kconfig | 8 +- drivers/s390/char/Makefile | 1 + drivers/s390/char/tape_34xx.c | 8 +- drivers/s390/char/tape_3590.c | 1301 +++++++++++++++++++++++++++++++++++++++++ drivers/s390/char/tape_3590.h | 124 ++++ drivers/s390/char/tape_std.h | 12 +- 6 files changed, 1443 insertions(+), 11 deletions(-) create mode 100644 drivers/s390/char/tape_3590.c create mode 100644 drivers/s390/char/tape_3590.h (limited to 'drivers') diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig index 721787cc5a1c..4d36208ff8de 100644 --- a/drivers/s390/Kconfig +++ b/drivers/s390/Kconfig @@ -183,7 +183,13 @@ config S390_TAPE_34XX tape subsystems and 100% compatibles. It is safe to say "Y" here. - +config S390_TAPE_3590 + tristate "Support for 3590 tape hardware" + depends on S390_TAPE + help + Select this option if you want to access IBM 3590 magnetic + tape subsystems and 100% compatibles. + It is safe to say "Y" here. config VMLOGRDR tristate "Support for the z/VM recording system services (VM only)" diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index 6377a96735df..0c0162ff6c0c 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile @@ -26,4 +26,5 @@ tape-$(CONFIG_PROC_FS) += tape_proc.o tape-objs := tape_core.o tape_std.o tape_char.o $(tape-y) obj-$(CONFIG_S390_TAPE) += tape.o tape_class.o obj-$(CONFIG_S390_TAPE_34XX) += tape_34xx.o +obj-$(CONFIG_S390_TAPE_3590) += tape_3590.o obj-$(CONFIG_MONREADER) += monreader.o diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 682039cac15b..d4f2da738078 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -2,8 +2,7 @@ * drivers/s390/char/tape_34xx.c * tape device discipline for 3480/3490 tapes. * - * S390 and zSeries version - * Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) IBM Corp. 2001,2006 * Author(s): Carsten Otte * Tuan Ngo-Anh * Martin Schwidefsky @@ -28,11 +27,6 @@ debug_info_t *TAPE_DBF_AREA = NULL; EXPORT_SYMBOL(TAPE_DBF_AREA); -enum tape_34xx_type { - tape_3480, - tape_3490, -}; - #define TAPE34XX_FMT_3480 0 #define TAPE34XX_FMT_3480_2_XF 1 #define TAPE34XX_FMT_3480_XF 2 diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c new file mode 100644 index 000000000000..c3915f60a3aa --- /dev/null +++ b/drivers/s390/char/tape_3590.c @@ -0,0 +1,1301 @@ +/* + * drivers/s390/char/tape_3590.c + * tape device discipline for 3590 tapes. + * + * Copyright (C) IBM Corp. 2001,2006 + * Author(s): Stefan Bader + * Michael Holzheu + * Martin Schwidefsky + */ + +#include +#include +#include +#include + +#define TAPE_DBF_AREA tape_3590_dbf + +#include "tape.h" +#include "tape_std.h" +#include "tape_3590.h" + +/* + * Pointer to debug area. + */ +debug_info_t *TAPE_DBF_AREA = NULL; +EXPORT_SYMBOL(TAPE_DBF_AREA); + +/******************************************************************* + * Error Recovery fuctions: + * - Read Opposite: implemented + * - Read Device (buffered) log: BRA + * - Read Library log: BRA + * - Swap Devices: BRA + * - Long Busy: BRA + * - Special Intercept: BRA + * - Read Alternate: implemented + *******************************************************************/ + +#define PRINTK_HEADER "TAPE_3590: " + +static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = { + [0x00] = "", + [0x10] = "Lost Sense", + [0x11] = "Assigned Elsewhere", + [0x12] = "Allegiance Reset", + [0x13] = "Shared Access Violation", + [0x20] = "Command Reject", + [0x21] = "Configuration Error", + [0x22] = "Protection Exception", + [0x23] = "Write Protect", + [0x24] = "Write Length", + [0x25] = "Read-Only Format", + [0x31] = "Beginning of Partition", + [0x33] = "End of Partition", + [0x34] = "End of Data", + [0x35] = "Block not found", + [0x40] = "Device Intervention", + [0x41] = "Loader Intervention", + [0x42] = "Library Intervention", + [0x50] = "Write Error", + [0x51] = "Erase Error", + [0x52] = "Formatting Error", + [0x53] = "Read Error", + [0x54] = "Unsupported Format", + [0x55] = "No Formatting", + [0x56] = "Positioning lost", + [0x57] = "Read Length", + [0x60] = "Unsupported Medium", + [0x61] = "Medium Length Error", + [0x62] = "Medium removed", + [0x64] = "Load Check", + [0x65] = "Unload Check", + [0x70] = "Equipment Check", + [0x71] = "Bus out Check", + [0x72] = "Protocol Error", + [0x73] = "Interface Error", + [0x74] = "Overrun", + [0x75] = "Halt Signal", + [0x90] = "Device fenced", + [0x91] = "Device Path fenced", + [0xa0] = "Volume misplaced", + [0xa1] = "Volume inaccessible", + [0xa2] = "Volume in input", + [0xa3] = "Volume ejected", + [0xa4] = "All categories reserved", + [0xa5] = "Duplicate Volume", + [0xa6] = "Library Manager Offline", + [0xa7] = "Library Output Station full", + [0xa8] = "Vision System non-operational", + [0xa9] = "Library Manager Equipment Check", + [0xaa] = "Library Equipment Check", + [0xab] = "All Library Cells full", + [0xac] = "No Cleaner Volumes in Library", + [0xad] = "I/O Station door open", + [0xae] = "Subsystem environmental alert", +}; + +/* + * 3590 IOCTL Overload + */ +static int +tape_3590_ioctl(struct tape_device *device, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case TAPE390_DISPLAY: { + struct display_struct disp; + + if (copy_from_user(&disp, (char __user *) arg, sizeof(disp))) + return -EFAULT; + + return tape_std_display(device, &disp); + } + default: + return -EINVAL; /* no additional ioctls */ + } +} + +/* + * SENSE Medium: Get Sense data about medium state + */ +static int +tape_3590_sense_medium(struct tape_device *device) +{ + struct tape_request *request; + + request = tape_alloc_request(1, 128); + if (IS_ERR(request)) + return PTR_ERR(request); + request->op = TO_MSEN; + tape_ccw_end(request->cpaddr, MEDIUM_SENSE, 128, request->cpdata); + return tape_do_io_free(device, request); +} + +/* + * MTTELL: Tell block. Return the number of block relative to current file. + */ +static int +tape_3590_mttell(struct tape_device *device, int mt_count) +{ + __u64 block_id; + int rc; + + rc = tape_std_read_block_id(device, &block_id); + if (rc) + return rc; + return block_id >> 32; +} + +/* + * MTSEEK: seek to the specified block. + */ +static int +tape_3590_mtseek(struct tape_device *device, int count) +{ + struct tape_request *request; + + DBF_EVENT(6, "xsee id: %x\n", count); + request = tape_alloc_request(3, 4); + if (IS_ERR(request)) + return PTR_ERR(request); + request->op = TO_LBL; + tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); + *(__u32 *) request->cpdata = count; + tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata); + tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL); + return tape_do_io_free(device, request); +} + +/* + * Read Opposite Error Recovery Function: + * Used, when Read Forward does not work + */ +static void +tape_3590_read_opposite(struct tape_device *device, + struct tape_request *request) +{ + struct tape_3590_disc_data *data; + + /* + * We have allocated 4 ccws in tape_std_read, so we can now + * transform the request to a read backward, followed by a + * forward space block. + */ + request->op = TO_RBA; + tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); + data = device->discdata; + tape_ccw_cc_idal(request->cpaddr + 1, data->read_back_op, + device->char_data.idal_buf); + tape_ccw_cc(request->cpaddr + 2, FORSPACEBLOCK, 0, NULL); + tape_ccw_end(request->cpaddr + 3, NOP, 0, NULL); + DBF_EVENT(6, "xrop ccwg\n"); +} + +/* + * Read Attention Msg + * This should be done after an interrupt with attention bit (0x80) + * in device state. + * + * After a "read attention message" request there are two possible + * results: + * + * 1. A unit check is presented, when attention sense is present (e.g. when + * a medium has been unloaded). The attention sense comes then + * together with the unit check. The recovery action is either "retry" + * (in case there is an attention message pending) or "permanent error". + * + * 2. The attention msg is written to the "read subsystem data" buffer. + * In this case we probably should print it to the console. + */ +static int +tape_3590_read_attmsg(struct tape_device *device) +{ + struct tape_request *request; + char *buf; + + request = tape_alloc_request(3, 4096); + if (IS_ERR(request)) + return PTR_ERR(request); + request->op = TO_READ_ATTMSG; + buf = request->cpdata; + buf[0] = PREP_RD_SS_DATA; + buf[6] = RD_ATTMSG; /* read att msg */ + tape_ccw_cc(request->cpaddr, PERFORM_SS_FUNC, 12, buf); + tape_ccw_cc(request->cpaddr + 1, READ_SS_DATA, 4096 - 12, buf + 12); + tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL); + return tape_do_io_free(device, request); +} + +/* + * These functions are used to schedule follow-up actions from within an + * interrupt context (like unsolicited interrupts). + */ +static void +tape_3590_work_handler(void *data) +{ + struct { + struct tape_device *device; + enum tape_op op; + struct work_struct work; + } *p = data; + + switch (p->op) { + case TO_MSEN: + tape_3590_sense_medium(p->device); + break; + case TO_READ_ATTMSG: + tape_3590_read_attmsg(p->device); + break; + default: + DBF_EVENT(3, "T3590: work handler undefined for " + "operation 0x%02x\n", p->op); + } + tape_put_device(p->device); + kfree(p); +} + +static int +tape_3590_schedule_work(struct tape_device *device, enum tape_op op) +{ + struct { + struct tape_device *device; + enum tape_op op; + struct work_struct work; + } *p; + + if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL) + return -ENOMEM; + + INIT_WORK(&p->work, tape_3590_work_handler, p); + + p->device = tape_get_device_reference(device); + p->op = op; + + schedule_work(&p->work); + return 0; +} + +#ifdef CONFIG_S390_TAPE_BLOCK +/* + * Tape Block READ + */ +static struct tape_request * +tape_3590_bread(struct tape_device *device, struct request *req) +{ + struct tape_request *request; + struct ccw1 *ccw; + int count = 0, start_block, i; + unsigned off; + char *dst; + struct bio_vec *bv; + struct bio *bio; + + DBF_EVENT(6, "xBREDid:"); + start_block = req->sector >> TAPEBLOCK_HSEC_S2B; + DBF_EVENT(6, "start_block = %i\n", start_block); + + rq_for_each_bio(bio, req) { + bio_for_each_segment(bv, bio, i) { + count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9); + } + } + request = tape_alloc_request(2 + count + 1, 4); + if (IS_ERR(request)) + return request; + request->op = TO_BLOCK; + *(__u32 *) request->cpdata = start_block; + ccw = request->cpaddr; + ccw = tape_ccw_cc(ccw, MODE_SET_DB, 1, device->modeset_byte); + + /* + * We always setup a nop after the mode set ccw. This slot is + * used in tape_std_check_locate to insert a locate ccw if the + * current tape position doesn't match the start block to be read. + */ + ccw = tape_ccw_cc(ccw, NOP, 0, NULL); + + rq_for_each_bio(bio, req) { + bio_for_each_segment(bv, bio, i) { + dst = kmap(bv->bv_page) + bv->bv_offset; + for (off = 0; off < bv->bv_len; + off += TAPEBLOCK_HSEC_SIZE) { + ccw->flags = CCW_FLAG_CC; + ccw->cmd_code = READ_FORWARD; + ccw->count = TAPEBLOCK_HSEC_SIZE; + set_normalized_cda(ccw, (void *) __pa(dst)); + ccw++; + dst += TAPEBLOCK_HSEC_SIZE; + } + if (off > bv->bv_len) + BUG(); + } + } + ccw = tape_ccw_end(ccw, NOP, 0, NULL); + DBF_EVENT(6, "xBREDccwg\n"); + return request; +} + +static void +tape_3590_free_bread(struct tape_request *request) +{ + struct ccw1 *ccw; + + /* Last ccw is a nop and doesn't need clear_normalized_cda */ + for (ccw = request->cpaddr; ccw->flags & CCW_FLAG_CC; ccw++) + if (ccw->cmd_code == READ_FORWARD) + clear_normalized_cda(ccw); + tape_free_request(request); +} + +/* + * check_locate is called just before the tape request is passed to + * the common io layer for execution. It has to check the current + * tape position and insert a locate ccw if it doesn't match the + * start block for the request. + */ +static void +tape_3590_check_locate(struct tape_device *device, struct tape_request *request) +{ + __u32 *start_block; + + start_block = (__u32 *) request->cpdata; + if (*start_block != device->blk_data.block_position) { + /* Add the start offset of the file to get the real block. */ + *start_block += device->bof; + tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata); + } +} +#endif + +/* + * The done handler is called at device/channel end and wakes up the sleeping + * process + */ +static int +tape_3590_done(struct tape_device *device, struct tape_request *request) +{ + struct tape_3590_med_sense *sense; + + DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]); + + switch (request->op) { + case TO_BSB: + case TO_BSF: + case TO_DSE: + case TO_FSB: + case TO_FSF: + case TO_LBL: + case TO_RFO: + case TO_RBA: + case TO_REW: + case TO_WRI: + case TO_WTM: + case TO_BLOCK: + case TO_LOAD: + tape_med_state_set(device, MS_LOADED); + break; + case TO_RUN: + tape_med_state_set(device, MS_UNLOADED); + break; + case TO_MSEN: + sense = (struct tape_3590_med_sense *) request->cpdata; + if (sense->masst == MSENSE_UNASSOCIATED) + tape_med_state_set(device, MS_UNLOADED); + if (sense->masst == MSENSE_ASSOCIATED_MOUNT) + tape_med_state_set(device, MS_LOADED); + break; + case TO_RBI: /* RBI seems to succeed even without medium loaded. */ + case TO_NOP: /* Same to NOP. */ + case TO_READ_CONFIG: + case TO_READ_ATTMSG: + case TO_DIS: + case TO_ASSIGN: + case TO_UNASSIGN: + break; + case TO_SIZE: + break; + } + return TAPE_IO_SUCCESS; +} + +/* + * This fuction is called, when error recovery was successfull + */ +static inline int +tape_3590_erp_succeded(struct tape_device *device, struct tape_request *request) +{ + DBF_EVENT(3, "Error Recovery successfull for %s\n", + tape_op_verbose[request->op]); + return tape_3590_done(device, request); +} + +/* + * This fuction is called, when error recovery was not successfull + */ +static inline int +tape_3590_erp_failed(struct tape_device *device, struct tape_request *request, + struct irb *irb, int rc) +{ + DBF_EVENT(3, "Error Recovery failed for %s\n", + tape_op_verbose[request->op]); + tape_dump_sense_dbf(device, request, irb); + return rc; +} + +/* + * Error Recovery do retry + */ +static inline int +tape_3590_erp_retry(struct tape_device *device, struct tape_request *request, + struct irb *irb) +{ + DBF_EVENT(2, "Retry: %s\n", tape_op_verbose[request->op]); + tape_dump_sense_dbf(device, request, irb); + return TAPE_IO_RETRY; +} + +/* + * Handle unsolicited interrupts + */ +static int +tape_3590_unsolicited_irq(struct tape_device *device, struct irb *irb) +{ + if (irb->scsw.dstat == DEV_STAT_CHN_END) + /* Probably result of halt ssch */ + return TAPE_IO_PENDING; + else if (irb->scsw.dstat == 0x85) + /* Device Ready -> check medium state */ + tape_3590_schedule_work(device, TO_MSEN); + else if (irb->scsw.dstat & DEV_STAT_ATTENTION) + tape_3590_schedule_work(device, TO_READ_ATTMSG); + else { + DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); + PRINT_WARN("Unsolicited IRQ (Device End) caught.\n"); + tape_dump_sense(device, NULL, irb); + } + return TAPE_IO_SUCCESS; +} + +/* + * Basic Recovery routine + */ +static int +tape_3590_erp_basic(struct tape_device *device, struct tape_request *request, + struct irb *irb, int rc) +{ + struct tape_3590_sense *sense; + + sense = (struct tape_3590_sense *) irb->ecw; + + switch (sense->bra) { + case SENSE_BRA_PER: + return tape_3590_erp_failed(device, request, irb, rc); + case SENSE_BRA_CONT: + return tape_3590_erp_succeded(device, request); + case SENSE_BRA_RE: + return tape_3590_erp_retry(device, request, irb); + case SENSE_BRA_DRE: + return tape_3590_erp_failed(device, request, irb, rc); + default: + PRINT_ERR("Unknown BRA %x - This should not happen!\n", + sense->bra); + BUG(); + return TAPE_IO_STOP; + } +} + +/* + * RDL: Read Device (buffered) log + */ +static int +tape_3590_erp_read_buf_log(struct tape_device *device, + struct tape_request *request, struct irb *irb) +{ + /* + * We just do the basic error recovery at the moment (retry). + * Perhaps in the future, we read the log and dump it somewhere... + */ + return tape_3590_erp_basic(device, request, irb, -EIO); +} + +/* + * SWAP: Swap Devices + */ +static int +tape_3590_erp_swap(struct tape_device *device, struct tape_request *request, + struct irb *irb) +{ + /* + * This error recovery should swap the tapes + * if the original has a problem. The operation + * should proceed with the new tape... this + * should probably be done in user space! + */ + PRINT_WARN("(%s): Swap Tape Device!\n", device->cdev->dev.bus_id); + return tape_3590_erp_basic(device, request, irb, -EIO); +} + +/* + * LBY: Long Busy + */ +static int +tape_3590_erp_long_busy(struct tape_device *device, + struct tape_request *request, struct irb *irb) +{ + /* FIXME: how about WAITING for a minute ? */ + PRINT_WARN("(%s): Device is busy! Please wait a minute!\n", + device->cdev->dev.bus_id); + return tape_3590_erp_basic(device, request, irb, -EBUSY); +} + +/* + * SPI: Special Intercept + */ +static int +tape_3590_erp_special_interrupt(struct tape_device *device, + struct tape_request *request, struct irb *irb) +{ + return tape_3590_erp_basic(device, request, irb, -EIO); +} + +/* + * RDA: Read Alternate + */ +static int +tape_3590_erp_read_alternate(struct tape_device *device, + struct tape_request *request, struct irb *irb) +{ + struct tape_3590_disc_data *data; + + /* + * The issued Read Backward or Read Previous command is not + * supported by the device + * The recovery action should be to issue another command: + * Read Revious: if Read Backward is not supported + * Read Backward: if Read Previous is not supported + */ + data = device->discdata; + if (data->read_back_op == READ_PREVIOUS) { + DBF_EVENT(2, "(%08x): No support for READ_PREVIOUS command\n", + device->cdev_id); + data->read_back_op = READ_BACKWARD; + } else { + DBF_EVENT(2, "(%08x): No support for READ_BACKWARD command\n", + device->cdev_id); + data->read_back_op = READ_PREVIOUS; + } + tape_3590_read_opposite(device, request); + return tape_3590_erp_retry(device, request, irb); +} + +/* + * Error Recovery read opposite + */ +static int +tape_3590_erp_read_opposite(struct tape_device *device, + struct tape_request *request, struct irb *irb) +{ + switch (request->op) { + case TO_RFO: + /* + * We did read forward, but the data could not be read. + * We will read backward and then skip forward again. + */ + tape_3590_read_opposite(device, request); + return tape_3590_erp_retry(device, request, irb); + case TO_RBA: + /* We tried to read forward and backward, but hat no success */ + return tape_3590_erp_failed(device, request, irb, -EIO); + break; + default: + PRINT_WARN("read_opposite_recovery_called_with_op: %s\n", + tape_op_verbose[request->op]); + return tape_3590_erp_failed(device, request, irb, -EIO); + } +} + +/* + * Print an MIM (Media Information Message) (message code f0) + */ +static void +tape_3590_print_mim_msg_f0(struct tape_device *device, struct irb *irb) +{ + struct tape_3590_sense *sense; + + sense = (struct tape_3590_sense *) irb->ecw; + /* Exception Message */ + switch (sense->fmt.f70.emc) { + case 0x02: + PRINT_WARN("(%s): Data degraded\n", device->cdev->dev.bus_id); + break; + case 0x03: + PRINT_WARN("(%s): Data degraded in partion %i\n", + device->cdev->dev.bus_id, sense->fmt.f70.mp); + break; + case 0x04: + PRINT_WARN("(%s): Medium degraded\n", device->cdev->dev.bus_id); + break; + case 0x05: + PRINT_WARN("(%s): Medium degraded in partition %i\n", + device->cdev->dev.bus_id, sense->fmt.f70.mp); + break; + case 0x06: + PRINT_WARN("(%s): Block 0 Error\n", device->cdev->dev.bus_id); + break; + case 0x07: + PRINT_WARN("(%s): Medium Exception 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f70.md); + break; + default: + PRINT_WARN("(%s): MIM ExMsg: 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f70.emc); + break; + } + /* Service Message */ + switch (sense->fmt.f70.smc) { + case 0x02: + PRINT_WARN("(%s): Reference Media maintenance procedure %i\n", + device->cdev->dev.bus_id, sense->fmt.f70.md); + break; + default: + PRINT_WARN("(%s): MIM ServiceMsg: 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f70.smc); + break; + } +} + +/* + * Print an I/O Subsystem Service Information Message (message code f1) + */ +static void +tape_3590_print_io_sim_msg_f1(struct tape_device *device, struct irb *irb) +{ + struct tape_3590_sense *sense; + + sense = (struct tape_3590_sense *) irb->ecw; + /* Exception Message */ + switch (sense->fmt.f71.emc) { + case 0x01: + PRINT_WARN("(%s): Effect of failure is unknown\n", + device->cdev->dev.bus_id); + break; + case 0x02: + PRINT_WARN("(%s): CU Exception - no performance impact\n", + device->cdev->dev.bus_id); + break; + case 0x03: + PRINT_WARN("(%s): CU Exception on channel interface 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + break; + case 0x04: + PRINT_WARN("(%s): CU Exception on device path 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + break; + case 0x05: + PRINT_WARN("(%s): CU Exception on library path 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + break; + case 0x06: + PRINT_WARN("(%s): CU Exception on node 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + break; + case 0x07: + PRINT_WARN("(%s): CU Exception on partition 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + break; + default: + PRINT_WARN("(%s): SIM ExMsg: 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.emc); + } + /* Service Message */ + switch (sense->fmt.f71.smc) { + case 0x01: + PRINT_WARN("(%s): Repair impact is unknown\n", + device->cdev->dev.bus_id); + break; + case 0x02: + PRINT_WARN("(%s): Repair will not impact cu performance\n", + device->cdev->dev.bus_id); + break; + case 0x03: + if (sense->fmt.f71.mdf == 0) + PRINT_WARN("(%s): Repair will disable node " + "0x%x on CU\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1]); + else + PRINT_WARN("(%s): Repair will disable nodes " + "(0x%x-0x%x) on CU\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + break; + case 0x04: + if (sense->fmt.f71.mdf == 0) + PRINT_WARN("(%s): Repair will disable cannel path " + "0x%x on CU\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1]); + else + PRINT_WARN("(%s): Repair will disable cannel paths " + "(0x%x-0x%x) on CU\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + break; + case 0x05: + if (sense->fmt.f71.mdf == 0) + PRINT_WARN("(%s): Repair will disable device path " + "0x%x on CU\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1]); + else + PRINT_WARN("(%s): Repair will disable device paths " + "(0x%x-0x%x) on CU\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + break; + case 0x06: + if (sense->fmt.f71.mdf == 0) + PRINT_WARN("(%s): Repair will disable library path " + "0x%x on CU\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1]); + else + PRINT_WARN("(%s): Repair will disable library paths " + "(0x%x-0x%x) on CU\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + break; + case 0x07: + PRINT_WARN("(%s): Repair will disable access to CU\n", + device->cdev->dev.bus_id); + break; + default: + PRINT_WARN("(%s): SIM ServiceMsg: 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.smc); + } +} + +/* + * Print an Device Subsystem Service Information Message (message code f2) + */ +static void +tape_3590_print_dev_sim_msg_f2(struct tape_device *device, struct irb *irb) +{ + struct tape_3590_sense *sense; + + sense = (struct tape_3590_sense *) irb->ecw; + /* Exception Message */ + switch (sense->fmt.f71.emc) { + case 0x01: + PRINT_WARN("(%s): Effect of failure is unknown\n", + device->cdev->dev.bus_id); + break; + case 0x02: + PRINT_WARN("(%s): DV Exception - no performance impact\n", + device->cdev->dev.bus_id); + break; + case 0x03: + PRINT_WARN("(%s): DV Exception on channel interface 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + break; + case 0x04: + PRINT_WARN("(%s): DV Exception on loader 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + break; + case 0x05: + PRINT_WARN("(%s): DV Exception on message display 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.md[0]); + break; + case 0x06: + PRINT_WARN("(%s): DV Exception in tape path\n", + device->cdev->dev.bus_id); + break; + case 0x07: + PRINT_WARN("(%s): DV Exception in drive\n", + device->cdev->dev.bus_id); + break; + default: + PRINT_WARN("(%s): DSIM ExMsg: 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.emc); + } + /* Service Message */ + switch (sense->fmt.f71.smc) { + case 0x01: + PRINT_WARN("(%s): Repair impact is unknown\n", + device->cdev->dev.bus_id); + break; + case 0x02: + PRINT_WARN("(%s): Repair will not impact device performance\n", + device->cdev->dev.bus_id); + break; + case 0x03: + if (sense->fmt.f71.mdf == 0) + PRINT_WARN("(%s): Repair will disable channel path " + "0x%x on DV\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1]); + else + PRINT_WARN("(%s): Repair will disable channel path " + "(0x%x-0x%x) on DV\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + break; + case 0x04: + if (sense->fmt.f71.mdf == 0) + PRINT_WARN("(%s): Repair will disable interface 0x%x " + "on DV\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1]); + else + PRINT_WARN("(%s): Repair will disable interfaces " + "(0x%x-0x%x) on DV\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + break; + case 0x05: + if (sense->fmt.f71.mdf == 0) + PRINT_WARN("(%s): Repair will disable loader 0x%x " + "on DV\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1]); + else + PRINT_WARN("(%s): Repair will disable loader " + "(0x%x-0x%x) on DV\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + break; + case 0x07: + PRINT_WARN("(%s): Repair will disable access to DV\n", + device->cdev->dev.bus_id); + break; + case 0x08: + if (sense->fmt.f71.mdf == 0) + PRINT_WARN("(%s): Repair will disable message " + "display 0x%x on DV\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1]); + else + PRINT_WARN("(%s): Repair will disable message " + "displays (0x%x-0x%x) on DV\n", + device->cdev->dev.bus_id, + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + break; + case 0x09: + PRINT_WARN("(%s): Clean DV\n", device->cdev->dev.bus_id); + break; + default: + PRINT_WARN("(%s): DSIM ServiceMsg: 0x%02x\n", + device->cdev->dev.bus_id, sense->fmt.f71.smc); + } +} + +/* + * Print standard ERA Message + */ +static void +tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) +{ + struct tape_3590_sense *sense; + + sense = (struct tape_3590_sense *) irb->ecw; + if (sense->mc == 0) + return; + if ((sense->mc > 0) && (sense->mc < TAPE_3590_MAX_MSG)) { + if (tape_3590_msg[sense->mc] != NULL) + PRINT_WARN("(%s): %s\n", device->cdev->dev.bus_id, + tape_3590_msg[sense->mc]); + else { + PRINT_WARN("(%s): Message Code 0x%x\n", + device->cdev->dev.bus_id, sense->mc); + } + return; + } + if (sense->mc == 0xf0) { + /* Standard Media Information Message */ + PRINT_WARN("(%s): MIM SEV=%i, MC=%02x, ES=%x/%x, " + "RC=%02x-%04x-%02x\n", device->cdev->dev.bus_id, + sense->fmt.f70.sev, sense->mc, + sense->fmt.f70.emc, sense->fmt.f70.smc, + sense->fmt.f70.refcode, sense->fmt.f70.mid, + sense->fmt.f70.fid); + tape_3590_print_mim_msg_f0(device, irb); + return; + } + if (sense->mc == 0xf1) { + /* Standard I/O Subsystem Service Information Message */ + PRINT_WARN("(%s): IOSIM SEV=%i, DEVTYPE=3590/%02x, " + "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", + device->cdev->dev.bus_id, sense->fmt.f71.sev, + device->cdev->id.dev_model, + sense->mc, sense->fmt.f71.emc, + sense->fmt.f71.smc, sense->fmt.f71.refcode1, + sense->fmt.f71.refcode2, sense->fmt.f71.refcode3); + tape_3590_print_io_sim_msg_f1(device, irb); + return; + } + if (sense->mc == 0xf2) { + /* Standard Device Service Information Message */ + PRINT_WARN("(%s): DEVSIM SEV=%i, DEVTYPE=3590/%02x, " + "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", + device->cdev->dev.bus_id, sense->fmt.f71.sev, + device->cdev->id.dev_model, + sense->mc, sense->fmt.f71.emc, + sense->fmt.f71.smc, sense->fmt.f71.refcode1, + sense->fmt.f71.refcode2, sense->fmt.f71.refcode3); + tape_3590_print_dev_sim_msg_f2(device, irb); + return; + } + if (sense->mc == 0xf3) { + /* Standard Library Service Information Message */ + return; + } + PRINT_WARN("(%s): Device Message(%x)\n", + device->cdev->dev.bus_id, sense->mc); +} + +/* + * 3590 error Recovery routine: + * If possible, it tries to recover from the error. If this is not possible, + * inform the user about the problem. + */ +static int +tape_3590_unit_check(struct tape_device *device, struct tape_request *request, + struct irb *irb) +{ + struct tape_3590_sense *sense; + int rc; + +#ifdef CONFIG_S390_TAPE_BLOCK + if (request->op == TO_BLOCK) { + /* + * Recovery for block device requests. Set the block_position + * to something invalid and retry. + */ + device->blk_data.block_position = -1; + if (request->retries-- <= 0) + return tape_3590_erp_failed(device, request, irb, -EIO); + else + return tape_3590_erp_retry(device, request, irb); + } +#endif + + sense = (struct tape_3590_sense *) irb->ecw; + + /* + * First check all RC-QRCs where we want to do something special + * - "break": basic error recovery is done + * - "goto out:": just print error message if available + */ + rc = -EIO; + switch (sense->rc_rqc) { + + case 0x1110: + tape_3590_print_era_msg(device, irb); + return tape_3590_erp_read_buf_log(device, request, irb); + + case 0x2011: + tape_3590_print_era_msg(device, irb); + return tape_3590_erp_read_alternate(device, request, irb); + + case 0x2230: + case 0x2231: + tape_3590_print_era_msg(device, irb); + return tape_3590_erp_special_interrupt(device, request, irb); + + case 0x3010: + DBF_EVENT(2, "(%08x): Backward at Beginning of Partition\n", + device->cdev_id); + return tape_3590_erp_basic(device, request, irb, -ENOSPC); + case 0x3012: + DBF_EVENT(2, "(%08x): Forward at End of Partition\n", + device->cdev_id); + return tape_3590_erp_basic(device, request, irb, -ENOSPC); + case 0x3020: + DBF_EVENT(2, "(%08x): End of Data Mark\n", device->cdev_id); + return tape_3590_erp_basic(device, request, irb, -ENOSPC); + + case 0x3122: + DBF_EVENT(2, "(%08x): Rewind Unload initiated\n", + device->cdev_id); + return tape_3590_erp_basic(device, request, irb, -EIO); + case 0x3123: + DBF_EVENT(2, "(%08x): Rewind Unload complete\n", + device->cdev_id); + tape_med_state_set(device, MS_UNLOADED); + return tape_3590_erp_basic(device, request, irb, 0); + + case 0x4010: + /* + * print additional msg since default msg + * "device intervention" is not very meaningfull + */ + PRINT_WARN("(%s): Tape operation when medium not loaded\n", + device->cdev->dev.bus_id); + tape_med_state_set(device, MS_UNLOADED); + return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); + case 0x4012: /* Device Long Busy */ + tape_3590_print_era_msg(device, irb); + return tape_3590_erp_long_busy(device, request, irb); + + case 0x5010: + if (sense->rac == 0xd0) { + /* Swap */ + tape_3590_print_era_msg(device, irb); + return tape_3590_erp_swap(device, request, irb); + } + if (sense->rac == 0x26) { + /* Read Opposite */ + tape_3590_print_era_msg(device, irb); + return tape_3590_erp_read_opposite(device, request, + irb); + } + return tape_3590_erp_basic(device, request, irb, -EIO); + case 0x5020: + case 0x5021: + case 0x5022: + case 0x5040: + case 0x5041: + case 0x5042: + tape_3590_print_era_msg(device, irb); + return tape_3590_erp_swap(device, request, irb); + + case 0x5110: + case 0x5111: + return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE); + + case 0x5120: + case 0x1120: + tape_med_state_set(device, MS_UNLOADED); + return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); + + case 0x6020: + PRINT_WARN("(%s): Cartridge of wrong type ?\n", + device->cdev->dev.bus_id); + return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE); + + case 0x8011: + PRINT_WARN("(%s): Another host has reserved the tape device\n", + device->cdev->dev.bus_id); + return tape_3590_erp_basic(device, request, irb, -EPERM); + case 0x8013: + PRINT_WARN("(%s): Another host has priviliged access to the " + "tape device\n", device->cdev->dev.bus_id); + PRINT_WARN("(%s): To solve the problem unload the current " + "cartridge!\n", device->cdev->dev.bus_id); + return tape_3590_erp_basic(device, request, irb, -EPERM); + default: + return tape_3590_erp_basic(device, request, irb, -EIO); + } +} + +/* + * 3590 interrupt handler: + */ +static int +tape_3590_irq(struct tape_device *device, struct tape_request *request, + struct irb *irb) +{ + if (request == NULL) + return tape_3590_unsolicited_irq(device, irb); + + if ((irb->scsw.dstat & DEV_STAT_UNIT_EXCEP) && + (irb->scsw.dstat & DEV_STAT_DEV_END) && (request->op == TO_WRI)) { + /* Write at end of volume */ + DBF_EVENT(2, "End of volume\n"); + return tape_3590_erp_failed(device, request, irb, -ENOSPC); + } + + if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) + return tape_3590_unit_check(device, request, irb); + + if (irb->scsw.dstat & DEV_STAT_DEV_END) { + if (irb->scsw.dstat == DEV_STAT_UNIT_EXCEP) { + if (request->op == TO_FSB || request->op == TO_BSB) + request->rescnt++; + else + DBF_EVENT(5, "Unit Exception!\n"); + } + + return tape_3590_done(device, request); + } + + if (irb->scsw.dstat & DEV_STAT_CHN_END) { + DBF_EVENT(2, "cannel end\n"); + return TAPE_IO_PENDING; + } + + if (irb->scsw.dstat & DEV_STAT_ATTENTION) { + DBF_EVENT(2, "Unit Attention when busy..\n"); + return TAPE_IO_PENDING; + } + + DBF_EVENT(6, "xunknownirq\n"); + PRINT_ERR("Unexpected interrupt.\n"); + PRINT_ERR("Current op is: %s", tape_op_verbose[request->op]); + tape_dump_sense(device, request, irb); + return TAPE_IO_STOP; +} + +/* + * Setup device function + */ +static int +tape_3590_setup_device(struct tape_device *device) +{ + int rc; + struct tape_3590_disc_data *data; + + DBF_EVENT(6, "3590 device setup\n"); + data = kmalloc(sizeof(struct tape_3590_disc_data), + GFP_KERNEL | GFP_DMA); + if (data == NULL) + return -ENOMEM; + data->read_back_op = READ_PREVIOUS; + device->discdata = data; + + if ((rc = tape_std_assign(device)) == 0) { + /* Try to find out if medium is loaded */ + if ((rc = tape_3590_sense_medium(device)) != 0) + DBF_LH(3, "3590 medium sense returned %d\n", rc); + } + + return rc; +} + +/* + * Cleanup device function + */ +static void +tape_3590_cleanup_device(struct tape_device *device) +{ + tape_std_unassign(device); + + kfree(device->discdata); + device->discdata = NULL; +} + +/* + * List of 3590 magnetic tape commands. + */ +static tape_mtop_fn tape_3590_mtop[TAPE_NR_MTOPS] = { + [MTRESET] = tape_std_mtreset, + [MTFSF] = tape_std_mtfsf, + [MTBSF] = tape_std_mtbsf, + [MTFSR] = tape_std_mtfsr, + [MTBSR] = tape_std_mtbsr, + [MTWEOF] = tape_std_mtweof, + [MTREW] = tape_std_mtrew, + [MTOFFL] = tape_std_mtoffl, + [MTNOP] = tape_std_mtnop, + [MTRETEN] = tape_std_mtreten, + [MTBSFM] = tape_std_mtbsfm, + [MTFSFM] = tape_std_mtfsfm, + [MTEOM] = tape_std_mteom, + [MTERASE] = tape_std_mterase, + [MTRAS1] = NULL, + [MTRAS2] = NULL, + [MTRAS3] = NULL, + [MTSETBLK] = tape_std_mtsetblk, + [MTSETDENSITY] = NULL, + [MTSEEK] = tape_3590_mtseek, + [MTTELL] = tape_3590_mttell, + [MTSETDRVBUFFER] = NULL, + [MTFSS] = NULL, + [MTBSS] = NULL, + [MTWSM] = NULL, + [MTLOCK] = NULL, + [MTUNLOCK] = NULL, + [MTLOAD] = tape_std_mtload, + [MTUNLOAD] = tape_std_mtunload, + [MTCOMPRESSION] = tape_std_mtcompression, + [MTSETPART] = NULL, + [MTMKPART] = NULL +}; + +/* + * Tape discipline structure for 3590. + */ +static struct tape_discipline tape_discipline_3590 = { + .owner = THIS_MODULE, + .setup_device = tape_3590_setup_device, + .cleanup_device = tape_3590_cleanup_device, + .process_eov = tape_std_process_eov, + .irq = tape_3590_irq, + .read_block = tape_std_read_block, + .write_block = tape_std_write_block, +#ifdef CONFIG_S390_TAPE_BLOCK + .bread = tape_3590_bread, + .free_bread = tape_3590_free_bread, + .check_locate = tape_3590_check_locate, +#endif + .ioctl_fn = tape_3590_ioctl, + .mtop_array = tape_3590_mtop +}; + +static struct ccw_device_id tape_3590_ids[] = { + {CCW_DEVICE_DEVTYPE(0x3590, 0, 0x3590, 0), .driver_info = tape_3590}, + { /* end of list */ } +}; + +static int +tape_3590_online(struct ccw_device *cdev) +{ + return tape_generic_online(cdev->dev.driver_data, + &tape_discipline_3590); +} + +static int +tape_3590_offline(struct ccw_device *cdev) +{ + return tape_generic_offline(cdev->dev.driver_data); +} + +static struct ccw_driver tape_3590_driver = { + .name = "tape_3590", + .owner = THIS_MODULE, + .ids = tape_3590_ids, + .probe = tape_generic_probe, + .remove = tape_generic_remove, + .set_offline = tape_3590_offline, + .set_online = tape_3590_online, +}; + +/* + * Setup discipline structure. + */ +static int +tape_3590_init(void) +{ + int rc; + + TAPE_DBF_AREA = debug_register("tape_3590", 2, 2, 4 * sizeof(long)); + debug_register_view(TAPE_DBF_AREA, &debug_sprintf_view); +#ifdef DBF_LIKE_HELL + debug_set_level(TAPE_DBF_AREA, 6); +#endif + + DBF_EVENT(3, "3590 init\n"); + /* Register driver for 3590 tapes. */ + rc = ccw_driver_register(&tape_3590_driver); + if (rc) + DBF_EVENT(3, "3590 init failed\n"); + else + DBF_EVENT(3, "3590 registered\n"); + return rc; +} + +static void +tape_3590_exit(void) +{ + ccw_driver_unregister(&tape_3590_driver); + + debug_unregister(TAPE_DBF_AREA); +} + +MODULE_DEVICE_TABLE(ccw, tape_3590_ids); +MODULE_AUTHOR("(C) 2001,2006 IBM Corporation"); +MODULE_DESCRIPTION("Linux on zSeries channel attached 3590 tape device driver"); +MODULE_LICENSE("GPL"); + +module_init(tape_3590_init); +module_exit(tape_3590_exit); diff --git a/drivers/s390/char/tape_3590.h b/drivers/s390/char/tape_3590.h new file mode 100644 index 000000000000..cf274b9445a6 --- /dev/null +++ b/drivers/s390/char/tape_3590.h @@ -0,0 +1,124 @@ +/* + * drivers/s390/char/tape_3590.h + * tape device discipline for 3590 tapes. + * + * Copyright (C) IBM Corp. 2001,2006 + * Author(s): Stefan Bader + * Michael Holzheu + * Martin Schwidefsky + */ + +#ifndef _TAPE_3590_H +#define _TAPE_3590_H + +#define MEDIUM_SENSE 0xc2 +#define READ_PREVIOUS 0x0a +#define MODE_SENSE 0xcf +#define PERFORM_SS_FUNC 0x77 +#define READ_SS_DATA 0x3e + +#define PREP_RD_SS_DATA 0x18 +#define RD_ATTMSG 0x3 + +#define SENSE_BRA_PER 0 +#define SENSE_BRA_CONT 1 +#define SENSE_BRA_RE 2 +#define SENSE_BRA_DRE 3 + +#define SENSE_FMT_LIBRARY 0x23 +#define SENSE_FMT_UNSOLICITED 0x40 +#define SENSE_FMT_COMMAND_REJ 0x41 +#define SENSE_FMT_COMMAND_EXEC0 0x50 +#define SENSE_FMT_COMMAND_EXEC1 0x51 +#define SENSE_FMT_EVENT0 0x60 +#define SENSE_FMT_EVENT1 0x61 +#define SENSE_FMT_MIM 0x70 +#define SENSE_FMT_SIM 0x71 + +#define MSENSE_UNASSOCIATED 0x00 +#define MSENSE_ASSOCIATED_MOUNT 0x01 +#define MSENSE_ASSOCIATED_UMOUNT 0x02 + +#define TAPE_3590_MAX_MSG 0xb0 + +/* Datatypes */ + +struct tape_3590_disc_data { + unsigned char modeset_byte; + int read_back_op; +}; + +struct tape_3590_sense { + + unsigned int command_rej:1; + unsigned int interv_req:1; + unsigned int bus_out_check:1; + unsigned int eq_check:1; + unsigned int data_check:1; + unsigned int overrun:1; + unsigned int def_unit_check:1; + unsigned int assgnd_elsew:1; + + unsigned int locate_fail:1; + unsigned int inst_online:1; + unsigned int reserved:1; + unsigned int blk_seq_err:1; + unsigned int begin_part:1; + unsigned int wr_mode:1; + unsigned int wr_prot:1; + unsigned int not_cap:1; + + unsigned int bra:2; + unsigned int lc:3; + unsigned int vlf_active:1; + unsigned int stm:1; + unsigned int med_pos:1; + + unsigned int rac:8; + + unsigned int rc_rqc:16; + + unsigned int mc:8; + + unsigned int sense_fmt:8; + + union { + struct { + unsigned int emc:4; + unsigned int smc:4; + unsigned int sev:2; + unsigned int reserved:6; + unsigned int md:8; + unsigned int refcode:8; + unsigned int mid:16; + unsigned int mp:16; + unsigned char volid[6]; + unsigned int fid:8; + } f70; + struct { + unsigned int emc:4; + unsigned int smc:4; + unsigned int sev:2; + unsigned int reserved1:5; + unsigned int mdf:1; + unsigned char md[3]; + unsigned int simid:8; + unsigned int uid:16; + unsigned int refcode1:16; + unsigned int refcode2:16; + unsigned int refcode3:16; + unsigned int reserved2:8; + } f71; + unsigned char data[14]; + } fmt; + unsigned char pad[10]; + +} __attribute__ ((packed)); + +struct tape_3590_med_sense { + unsigned int macst:4; + unsigned int masst:4; + char pad[127]; +} __attribute__ ((packed)); + +#endif /* _TAPE_3590_H */ diff --git a/drivers/s390/char/tape_std.h b/drivers/s390/char/tape_std.h index 3ab6aafb7343..2d311798edf4 100644 --- a/drivers/s390/char/tape_std.h +++ b/drivers/s390/char/tape_std.h @@ -1,9 +1,8 @@ /* - * drivers/s390/char/tape_34xx.h + * drivers/s390/char/tape_std.h * standard tape device functions for ibm tapes. * - * S390 and zSeries version - * Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) IBM Corp. 2001,2006 * Author(s): Carsten Otte * Tuan Ngo-Anh * Martin Schwidefsky @@ -149,4 +148,11 @@ void tape_std_error_recovery_do_retry(struct tape_device *); void tape_std_error_recovery_read_opposite(struct tape_device *); void tape_std_error_recovery_HWBUG(struct tape_device *, int condno); +/* S390 tape types */ +enum s390_tape_type { + tape_3480, + tape_3490, + tape_3590, +}; + #endif // _TAPE_STD_H -- cgit v1.2.3-59-g8ed1b From 96641ee1e4a5154943774639478eb997f4ffb97e Mon Sep 17 00:00:00 2001 From: Eric Rossman Date: Fri, 24 Mar 2006 03:15:30 -0800 Subject: [PATCH] s390: CEX2A crt message length Undetected edge case for CRT messages to CEX2A caused length to be too short, thus truncating the message. The solution was to check a different variable which actually determines which key type is being used. Increment version number in z90main.c to correct level of 1.3.3, fix copyright year and add comment about bitlength limit of CEX2A. Signed-off-by: Eric Rossman Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/crypto/z90hardware.c | 10 +++++++++- drivers/s390/crypto/z90main.c | 5 +++-- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c index 4141919da805..be60795f4a74 100644 --- a/drivers/s390/crypto/z90hardware.c +++ b/drivers/s390/crypto/z90hardware.c @@ -2214,7 +2214,7 @@ ICACRT_msg_to_type50CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, long_len = 128; } - tmp_size = ((mod_len <= 128) ? TYPE50_CRB1_LEN : TYPE50_CRB2_LEN) + + tmp_size = ((long_len <= 64) ? TYPE50_CRB1_LEN : TYPE50_CRB2_LEN) + CALLER_HEADER; memset(z90cMsg_p, 0, tmp_size); @@ -2479,8 +2479,16 @@ convert_response(unsigned char *response, unsigned char *buffer, if (reply_code) switch (reply_code) { + case REP82_ERROR_MACHINE_FAILURE: + if (errh_p->type == TYPE82_RSP_CODE) + PRINTKW("Machine check failure\n"); + else + PRINTKW("Module failure\n"); + return REC_HARDWAR_ERR; case REP82_ERROR_OPERAND_INVALID: + return REC_OPERAND_INV; case REP88_ERROR_MESSAGE_MALFORMD: + PRINTKW("Message malformed\n"); return REC_OPERAND_INV; case REP82_ERROR_OPERAND_SIZE: return REC_OPERAND_SIZE; diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 7d6f19030ef9..977ecd9ba6bd 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c @@ -1,9 +1,9 @@ /* * linux/drivers/s390/crypto/z90main.c * - * z90crypt 1.3.2 + * z90crypt 1.3.3 * - * Copyright (C) 2001, 2004 IBM Corporation + * Copyright (C) 2001, 2005 IBM Corporation * Author(s): Robert Burroughs (burrough@us.ibm.com) * Eric Rossman (edrossma@us.ibm.com) * @@ -991,6 +991,7 @@ remove_device(struct device *device_p) * PCIXCC_MCL2 512-2048 ----- (applying any GA LIC will make an MCL3 card) * PCIXCC_MCL3 ----- 128-2048 * CEX2C 512-2048 128-2048 + * CEX2A ??-2048 same (the lower limit is less than 128 bit...) * * ext_bitlens (extended bitlengths) is a global, since you should not apply an * MCL to just one card in a machine. We assume, at first, that all cards have -- cgit v1.2.3-59-g8ed1b From 88abaab4f9b08381e30e737980a1c49d6b524dfc Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 24 Mar 2006 03:15:31 -0800 Subject: [PATCH] s390: kzalloc() conversion in drivers/s390 Convert all kmalloc + memset sequences in drivers/s390 to kzalloc usage. Signed-off-by: Eric Sesterhenn Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd.c | 12 ++++-------- drivers/s390/block/dcssblk.c | 3 +-- drivers/s390/char/fs3270.c | 3 +-- drivers/s390/char/keyboard.c | 12 ++++-------- drivers/s390/char/monreader.c | 6 ++---- drivers/s390/char/raw3270.c | 3 +-- drivers/s390/char/tape_class.c | 3 +-- drivers/s390/char/tape_core.c | 16 +++++----------- drivers/s390/char/tty3270.c | 9 +++------ drivers/s390/char/vmlogrdr.c | 3 +-- drivers/s390/cio/ccwgroup.c | 3 +-- drivers/s390/cio/chsc.c | 3 +-- drivers/s390/cio/css.c | 3 +-- drivers/s390/cio/device.c | 6 ++---- drivers/s390/cio/device_ops.c | 9 +++------ drivers/s390/cio/qdio.c | 20 +++++++------------- drivers/s390/crypto/z90main.c | 10 +++------- drivers/s390/net/claw.c | 3 +-- drivers/s390/net/fsm.c | 10 +++------- drivers/s390/net/iucv.c | 11 ++++------- drivers/s390/net/lcs.c | 11 ++++------- drivers/s390/net/netiucv.c | 7 ++----- drivers/s390/net/qeth_eddp.c | 13 ++++--------- drivers/s390/net/qeth_main.c | 20 ++++++-------------- drivers/s390/net/qeth_sys.c | 3 +-- drivers/s390/s390_rdev.c | 3 +-- 26 files changed, 67 insertions(+), 138 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index f32f7447588b..dfe542b206cc 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -71,10 +71,9 @@ dasd_alloc_device(void) { struct dasd_device *device; - device = kmalloc(sizeof (struct dasd_device), GFP_ATOMIC); + device = kzalloc(sizeof (struct dasd_device), GFP_ATOMIC); if (device == NULL) return ERR_PTR(-ENOMEM); - memset(device, 0, sizeof (struct dasd_device)); /* open_count = 0 means device online but not in use */ atomic_set(&device->open_count, -1); @@ -547,29 +546,26 @@ dasd_kmalloc_request(char *magic, int cplength, int datasize, (cplength*sizeof(struct ccw1)) > PAGE_SIZE) BUG(); - cqr = kmalloc(sizeof(struct dasd_ccw_req), GFP_ATOMIC); + cqr = kzalloc(sizeof(struct dasd_ccw_req), GFP_ATOMIC); if (cqr == NULL) return ERR_PTR(-ENOMEM); - memset(cqr, 0, sizeof(struct dasd_ccw_req)); cqr->cpaddr = NULL; if (cplength > 0) { - cqr->cpaddr = kmalloc(cplength*sizeof(struct ccw1), + cqr->cpaddr = kcalloc(cplength, sizeof(struct ccw1), GFP_ATOMIC | GFP_DMA); if (cqr->cpaddr == NULL) { kfree(cqr); return ERR_PTR(-ENOMEM); } - memset(cqr->cpaddr, 0, cplength*sizeof(struct ccw1)); } cqr->data = NULL; if (datasize > 0) { - cqr->data = kmalloc(datasize, GFP_ATOMIC | GFP_DMA); + cqr->data = kzalloc(datasize, GFP_ATOMIC | GFP_DMA); if (cqr->data == NULL) { kfree(cqr->cpaddr); kfree(cqr); return ERR_PTR(-ENOMEM); } - memset(cqr->data, 0, datasize); } strncpy((char *) &cqr->magic, magic, 4); ASCEBC((char *) &cqr->magic, 4); diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 44133250da2e..be9b05347b4f 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -388,12 +388,11 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char /* * get a struct dcssblk_dev_info */ - dev_info = kmalloc(sizeof(struct dcssblk_dev_info), GFP_KERNEL); + dev_info = kzalloc(sizeof(struct dcssblk_dev_info), GFP_KERNEL); if (dev_info == NULL) { rc = -ENOMEM; goto out; } - memset(dev_info, 0, sizeof(struct dcssblk_dev_info)); strcpy(dev_info->segment_name, local_buf); strlcpy(dev_info->dev.bus_id, local_buf, BUS_ID_SIZE); diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 5f6fa4c67843..a6415377bc73 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c @@ -368,10 +368,9 @@ fs3270_alloc_view(void) { struct fs3270 *fp; - fp = (struct fs3270 *) kmalloc(sizeof(struct fs3270),GFP_KERNEL); + fp = kzalloc(sizeof(struct fs3270),GFP_KERNEL); if (!fp) return ERR_PTR(-ENOMEM); - memset(fp, 0, sizeof(struct fs3270)); fp->init = raw3270_request_alloc(0); if (IS_ERR(fp->init)) { kfree(fp); diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index a317a123daba..6badd8403409 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -50,14 +50,12 @@ kbd_alloc(void) { struct kbd_data *kbd; int i, len; - kbd = kmalloc(sizeof(struct kbd_data), GFP_KERNEL); + kbd = kzalloc(sizeof(struct kbd_data), GFP_KERNEL); if (!kbd) goto out; - memset(kbd, 0, sizeof(struct kbd_data)); - kbd->key_maps = kmalloc(sizeof(key_maps), GFP_KERNEL); + kbd->key_maps = kzalloc(sizeof(key_maps), GFP_KERNEL); if (!key_maps) goto out_kbd; - memset(kbd->key_maps, 0, sizeof(key_maps)); for (i = 0; i < ARRAY_SIZE(key_maps); i++) { if (key_maps[i]) { kbd->key_maps[i] = @@ -68,10 +66,9 @@ kbd_alloc(void) { sizeof(u_short)*NR_KEYS); } } - kbd->func_table = kmalloc(sizeof(func_table), GFP_KERNEL); + kbd->func_table = kzalloc(sizeof(func_table), GFP_KERNEL); if (!kbd->func_table) goto out_maps; - memset(kbd->func_table, 0, sizeof(func_table)); for (i = 0; i < ARRAY_SIZE(func_table); i++) { if (func_table[i]) { len = strlen(func_table[i]) + 1; @@ -82,10 +79,9 @@ kbd_alloc(void) { } } kbd->fn_handler = - kmalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL); + kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL); if (!kbd->fn_handler) goto out_func; - memset(kbd->fn_handler, 0, sizeof(fn_handler_fn *) * NR_FN_HANDLER); kbd->accent_table = kmalloc(sizeof(struct kbdiacr)*MAX_DIACR, GFP_KERNEL); if (!kbd->accent_table) diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 5fd3ad867386..fb7bc9e5eebc 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c @@ -257,14 +257,13 @@ mon_alloc_mem(void) int i,j; struct mon_private *monpriv; - monpriv = kmalloc(sizeof(struct mon_private), GFP_KERNEL); + monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); if (!monpriv) { P_ERROR("no memory for monpriv\n"); return NULL; } - memset(monpriv, 0, sizeof(struct mon_private)); for (i = 0; i < MON_MSGLIM; i++) { - monpriv->msg_array[i] = kmalloc(sizeof(struct mon_msg), + monpriv->msg_array[i] = kzalloc(sizeof(struct mon_msg), GFP_KERNEL); if (!monpriv->msg_array[i]) { P_ERROR("open, no memory for msg_array\n"); @@ -272,7 +271,6 @@ mon_alloc_mem(void) kfree(monpriv->msg_array[j]); return NULL; } - memset(monpriv->msg_array[i], 0, sizeof(struct mon_msg)); } return monpriv; } diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 1026f2bc3185..bd06607a5dcc 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -115,10 +115,9 @@ raw3270_request_alloc(size_t size) struct raw3270_request *rq; /* Allocate request structure */ - rq = kmalloc(sizeof(struct raw3270_request), GFP_KERNEL | GFP_DMA); + rq = kzalloc(sizeof(struct raw3270_request), GFP_KERNEL | GFP_DMA); if (!rq) return ERR_PTR(-ENOMEM); - memset(rq, 0, sizeof(struct raw3270_request)); /* alloc output buffer. */ if (size > 0) { diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c index b3569c82bb16..a5c68e60fcf4 100644 --- a/drivers/s390/char/tape_class.c +++ b/drivers/s390/char/tape_class.c @@ -44,11 +44,10 @@ struct tape_class_device *register_tape_dev( int rc; char * s; - tcd = kmalloc(sizeof(struct tape_class_device), GFP_KERNEL); + tcd = kzalloc(sizeof(struct tape_class_device), GFP_KERNEL); if (!tcd) return ERR_PTR(-ENOMEM); - memset(tcd, 0, sizeof(struct tape_class_device)); strncpy(tcd->device_name, device_name, TAPECLASS_NAME_LEN); for (s = strchr(tcd->device_name, '/'); s; s = strchr(s, '/')) *s = '!'; diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index c6fab5dbdd44..389ee2c0f443 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -453,16 +453,14 @@ tape_alloc_device(void) { struct tape_device *device; - device = (struct tape_device *) - kmalloc(sizeof(struct tape_device), GFP_KERNEL); + device = kzalloc(sizeof(struct tape_device), GFP_KERNEL); if (device == NULL) { DBF_EXCEPTION(2, "ti:no mem\n"); PRINT_INFO ("can't allocate memory for " "tape info structure\n"); return ERR_PTR(-ENOMEM); } - memset(device, 0, sizeof(struct tape_device)); - device->modeset_byte = (char *) kmalloc(1, GFP_KERNEL | GFP_DMA); + device->modeset_byte = kmalloc(1, GFP_KERNEL | GFP_DMA); if (device->modeset_byte == NULL) { DBF_EXCEPTION(2, "ti:no mem\n"); PRINT_INFO("can't allocate memory for modeset byte\n"); @@ -659,34 +657,30 @@ tape_alloc_request(int cplength, int datasize) DBF_LH(6, "tape_alloc_request(%d, %d)\n", cplength, datasize); - request = (struct tape_request *) kmalloc(sizeof(struct tape_request), - GFP_KERNEL); + request = kzalloc(sizeof(struct tape_request), GFP_KERNEL); if (request == NULL) { DBF_EXCEPTION(1, "cqra nomem\n"); return ERR_PTR(-ENOMEM); } - memset(request, 0, sizeof(struct tape_request)); /* allocate channel program */ if (cplength > 0) { - request->cpaddr = kmalloc(cplength*sizeof(struct ccw1), + request->cpaddr = kcalloc(cplength, sizeof(struct ccw1), GFP_ATOMIC | GFP_DMA); if (request->cpaddr == NULL) { DBF_EXCEPTION(1, "cqra nomem\n"); kfree(request); return ERR_PTR(-ENOMEM); } - memset(request->cpaddr, 0, cplength*sizeof(struct ccw1)); } /* alloc small kernel buffer */ if (datasize > 0) { - request->cpdata = kmalloc(datasize, GFP_KERNEL | GFP_DMA); + request->cpdata = kzalloc(datasize, GFP_KERNEL | GFP_DMA); if (request->cpdata == NULL) { DBF_EXCEPTION(1, "cqra nomem\n"); kfree(request->cpaddr); kfree(request); return ERR_PTR(-ENOMEM); } - memset(request->cpdata, 0, datasize); } DBF_LH(6, "New request %p(%p/%p)\n", request, request->cpaddr, request->cpdata); diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 4b9069370388..9a141776873f 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -691,10 +691,9 @@ tty3270_alloc_view(void) struct tty3270 *tp; int pages; - tp = kmalloc(sizeof(struct tty3270),GFP_KERNEL); + tp = kzalloc(sizeof(struct tty3270), GFP_KERNEL); if (!tp) goto out_err; - memset(tp, 0, sizeof(struct tty3270)); tp->freemem_pages = kmalloc(sizeof(void *) * TTY3270_STRING_PAGES, GFP_KERNEL); if (!tp->freemem_pages) @@ -767,16 +766,14 @@ tty3270_alloc_screen(struct tty3270 *tp) int lines; size = sizeof(struct tty3270_line) * (tp->view.rows - 2); - tp->screen = kmalloc(size, GFP_KERNEL); + tp->screen = kzalloc(size, GFP_KERNEL); if (!tp->screen) goto out_err; - memset(tp->screen, 0, size); for (lines = 0; lines < tp->view.rows - 2; lines++) { size = sizeof(struct tty3270_cell) * tp->view.cols; - tp->screen[lines].cells = kmalloc(size, GFP_KERNEL); + tp->screen[lines].cells = kzalloc(size, GFP_KERNEL); if (!tp->screen[lines].cells) goto out_screen; - memset(tp->screen[lines].cells, 0, size); } return 0; out_screen: diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index b2d75de144c6..c625b69ebd19 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -759,9 +759,8 @@ vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) { struct device *dev; int ret; - dev = kmalloc(sizeof(struct device), GFP_KERNEL); + dev = kzalloc(sizeof(struct device), GFP_KERNEL); if (dev) { - memset(dev, 0, sizeof(struct device)); snprintf(dev->bus_id, BUS_ID_SIZE, "%s", priv->internal_name); dev->bus = &iucv_bus; diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 8013c8eb76fe..bdfee7fbaa2e 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -157,11 +157,10 @@ ccwgroup_create(struct device *root, if (argc > 256) /* disallow dumb users */ return -EINVAL; - gdev = kmalloc(sizeof(*gdev) + argc*sizeof(gdev->cdev[0]), GFP_KERNEL); + gdev = kzalloc(sizeof(*gdev) + argc*sizeof(gdev->cdev[0]), GFP_KERNEL); if (!gdev) return -ENOMEM; - memset(gdev, 0, sizeof(*gdev) + argc*sizeof(gdev->cdev[0])); atomic_set(&gdev->onoff, 0); del_drvdata = 0; diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 8b57fe62a9f9..6412b2c3edd3 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -1403,10 +1403,9 @@ new_channel_path(int chpid) struct channel_path *chp; int ret; - chp = kmalloc(sizeof(struct channel_path), GFP_KERNEL); + chp = kzalloc(sizeof(struct channel_path), GFP_KERNEL); if (!chp) return -ENOMEM; - memset(chp, 0, sizeof(struct channel_path)); /* fill in status, etc. */ chp->id = chpid; diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 5b304dbacaeb..74ea8aac4b7d 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -630,10 +630,9 @@ css_enqueue_subchannel_slow(struct subchannel_id schid) struct slow_subchannel *new_slow_sch; unsigned long flags; - new_slow_sch = kmalloc(sizeof(struct slow_subchannel), GFP_ATOMIC); + new_slow_sch = kzalloc(sizeof(struct slow_subchannel), GFP_ATOMIC); if (!new_slow_sch) return -ENOMEM; - memset(new_slow_sch, 0, sizeof(struct slow_subchannel)); new_slow_sch->schid = schid; spin_lock_irqsave(&slow_subchannel_lock, flags); list_add_tail(&new_slow_sch->slow_list, &slow_subchannels_head); diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index afc4e88551ad..8e3053c2a451 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -826,17 +826,15 @@ io_subchannel_probe (struct subchannel *sch) get_device(&cdev->dev); return 0; } - cdev = kmalloc (sizeof(*cdev), GFP_KERNEL); + cdev = kzalloc (sizeof(*cdev), GFP_KERNEL); if (!cdev) return -ENOMEM; - memset(cdev, 0, sizeof(struct ccw_device)); - cdev->private = kmalloc(sizeof(struct ccw_device_private), + cdev->private = kzalloc(sizeof(struct ccw_device_private), GFP_KERNEL | GFP_DMA); if (!cdev->private) { kfree(cdev); return -ENOMEM; } - memset(cdev->private, 0, sizeof(struct ccw_device_private)); atomic_set(&cdev->private->onoff, 0); cdev->dev = (struct device) { .parent = &sch->dev, diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 3a50b1903287..795abb5a65ba 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -359,10 +359,9 @@ read_dev_chars (struct ccw_device *cdev, void **buffer, int length) CIO_TRACE_EVENT (4, "rddevch"); CIO_TRACE_EVENT (4, sch->dev.bus_id); - rdc_ccw = kmalloc(sizeof(struct ccw1), GFP_KERNEL | GFP_DMA); + rdc_ccw = kzalloc(sizeof(struct ccw1), GFP_KERNEL | GFP_DMA); if (!rdc_ccw) return -ENOMEM; - memset(rdc_ccw, 0, sizeof(struct ccw1)); rdc_ccw->cmd_code = CCW_CMD_RDC; rdc_ccw->count = length; rdc_ccw->flags = CCW_FLAG_SLI; @@ -426,16 +425,14 @@ read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lp if (!ciw || ciw->cmd == 0) return -EOPNOTSUPP; - rcd_ccw = kmalloc(sizeof(struct ccw1), GFP_KERNEL | GFP_DMA); + rcd_ccw = kzalloc(sizeof(struct ccw1), GFP_KERNEL | GFP_DMA); if (!rcd_ccw) return -ENOMEM; - memset(rcd_ccw, 0, sizeof(struct ccw1)); - rcd_buf = kmalloc(ciw->count, GFP_KERNEL | GFP_DMA); + rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA); if (!rcd_buf) { kfree(rcd_ccw); return -ENOMEM; } - memset (rcd_buf, 0, ciw->count); rcd_ccw->cmd_code = ciw->cmd; rcd_ccw->cda = (__u32) __pa (rcd_buf); rcd_ccw->count = ciw->count; diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 9ed37dc9a1b0..814f9258ce00 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -1686,16 +1686,14 @@ qdio_alloc_qs(struct qdio_irq *irq_ptr, int result=-ENOMEM; for (i=0;islib=kmalloc(PAGE_SIZE,GFP_KERNEL); + q->slib = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!q->slib) { QDIO_PRINT_ERR("kmalloc of slib failed!\n"); goto out; @@ -1705,14 +1703,12 @@ qdio_alloc_qs(struct qdio_irq *irq_ptr, } for (i=0;islib=kmalloc(PAGE_SIZE,GFP_KERNEL); if (!q->slib) { QDIO_PRINT_ERR("kmalloc of slib failed!\n"); @@ -2984,7 +2980,7 @@ qdio_allocate(struct qdio_initialize *init_data) qdio_allocate_do_dbf(init_data); /* create irq */ - irq_ptr=kmalloc(sizeof(struct qdio_irq), GFP_KERNEL | GFP_DMA); + irq_ptr = kzalloc(sizeof(struct qdio_irq), GFP_KERNEL | GFP_DMA); QDIO_DBF_TEXT0(0,setup,"irq_ptr:"); QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*)); @@ -2994,8 +2990,6 @@ qdio_allocate(struct qdio_initialize *init_data) return -ENOMEM; } - memset(irq_ptr,0,sizeof(struct qdio_irq)); - init_MUTEX(&irq_ptr->setting_up_sema); /* QDR must be in DMA area since CCW data address is only 32 bit */ @@ -3686,10 +3680,10 @@ qdio_get_qdio_memory(void) for (i=1;istatus = STAT_OPEN; private_data_p->opener_pid = PID(); filp->private_data = private_data_p; @@ -2737,13 +2736,11 @@ create_z90crypt(int *cdx_p) z90crypt.max_count = Z90CRYPT_NUM_DEVS; z90crypt.cdx = *cdx_p; - hdware_blk_p = (struct hdware_block *) - kmalloc(sizeof(struct hdware_block), GFP_ATOMIC); + hdware_blk_p = kzalloc(sizeof(struct hdware_block), GFP_ATOMIC); if (!hdware_blk_p) { PDEBUG("kmalloc for hardware block failed\n"); return ENOMEM; } - memset(hdware_blk_p, 0x00, sizeof(struct hdware_block)); z90crypt.hdware_info = hdware_blk_p; return 0; @@ -2978,12 +2975,11 @@ create_crypto_device(int index) total_size = sizeof(struct device) + z90crypt.q_depth_array[index] * sizeof(int); - dev_ptr = (struct device *) kmalloc(total_size, GFP_ATOMIC); + dev_ptr = kzalloc(total_size, GFP_ATOMIC); if (!dev_ptr) { PRINTK("kmalloc device %d failed\n", index); return ENOMEM; } - memset(dev_ptr, 0, total_size); dev_ptr->dev_resp_p = kmalloc(MAX_RESPONSE_SIZE, GFP_ATOMIC); if (!dev_ptr->dev_resp_p) { kfree(dev_ptr); diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index acd2a3f005f1..23d53bf9daf1 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -310,7 +310,7 @@ claw_probe(struct ccwgroup_device *cgdev) printk(KERN_INFO "claw: variable cgdev =\n"); dumpit((char *)cgdev, sizeof(struct ccwgroup_device)); #endif - privptr = kmalloc(sizeof(struct claw_privbk), GFP_KERNEL); + privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL); if (privptr == NULL) { probe_error(cgdev); put_device(&cgdev->dev); @@ -319,7 +319,6 @@ claw_probe(struct ccwgroup_device *cgdev) CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM); return -ENOMEM; } - memset(privptr,0x00,sizeof(struct claw_privbk)); privptr->p_mtc_envelope= kmalloc( MAX_ENVELOPE_SIZE, GFP_KERNEL); privptr->p_env = kmalloc(sizeof(struct claw_env), GFP_KERNEL); if ((privptr->p_mtc_envelope==NULL) || (privptr->p_env==NULL)) { diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c index 6caf5fa6a3b5..7145e2134cf0 100644 --- a/drivers/s390/net/fsm.c +++ b/drivers/s390/net/fsm.c @@ -21,38 +21,34 @@ init_fsm(char *name, const char **state_names, const char **event_names, int nr_ fsm_function_t *m; fsm *f; - this = (fsm_instance *)kmalloc(sizeof(fsm_instance), order); + this = kzalloc(sizeof(fsm_instance), order); if (this == NULL) { printk(KERN_WARNING "fsm(%s): init_fsm: Couldn't alloc instance\n", name); return NULL; } - memset(this, 0, sizeof(fsm_instance)); strlcpy(this->name, name, sizeof(this->name)); - f = (fsm *)kmalloc(sizeof(fsm), order); + f = kzalloc(sizeof(fsm), order); if (f == NULL) { printk(KERN_WARNING "fsm(%s): init_fsm: Couldn't alloc fsm\n", name); kfree_fsm(this); return NULL; } - memset(f, 0, sizeof(fsm)); f->nr_events = nr_events; f->nr_states = nr_states; f->event_names = event_names; f->state_names = state_names; this->f = f; - m = (fsm_function_t *)kmalloc( - sizeof(fsm_function_t) * nr_states * nr_events, order); + m = kcalloc(nr_states*nr_events, sizeof(fsm_function_t), order); if (m == NULL) { printk(KERN_WARNING "fsm(%s): init_fsm: Couldn't alloc jumptable\n", name); kfree_fsm(this); return NULL; } - memset(m, 0, sizeof(fsm_function_t) * f->nr_states * f->nr_events); f->jumpmatrix = m; for (i = 0; i < tmpl_len; i++) { diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c index 760e77ec5a11..6190be9dca99 100644 --- a/drivers/s390/net/iucv.c +++ b/drivers/s390/net/iucv.c @@ -386,7 +386,7 @@ iucv_init(void) } /* Note: GFP_DMA used used to get memory below 2G */ - iucv_external_int_buffer = kmalloc(sizeof(iucv_GeneralInterrupt), + iucv_external_int_buffer = kzalloc(sizeof(iucv_GeneralInterrupt), GFP_KERNEL|GFP_DMA); if (!iucv_external_int_buffer) { printk(KERN_WARNING @@ -396,10 +396,9 @@ iucv_init(void) bus_unregister(&iucv_bus); return -ENOMEM; } - memset(iucv_external_int_buffer, 0, sizeof(iucv_GeneralInterrupt)); /* Initialize parameter pool */ - iucv_param_pool = kmalloc(sizeof(iucv_param) * PARAM_POOL_SIZE, + iucv_param_pool = kzalloc(sizeof(iucv_param) * PARAM_POOL_SIZE, GFP_KERNEL|GFP_DMA); if (!iucv_param_pool) { printk(KERN_WARNING "%s: Could not allocate param pool\n", @@ -410,7 +409,6 @@ iucv_init(void) bus_unregister(&iucv_bus); return -ENOMEM; } - memset(iucv_param_pool, 0, sizeof(iucv_param) * PARAM_POOL_SIZE); /* Initialize irq queue */ INIT_LIST_HEAD(&iucv_irq_queue); @@ -793,15 +791,14 @@ iucv_register_program (__u8 pgmname[16], } max_connections = iucv_query_maxconn(); - iucv_pathid_table = kmalloc(max_connections * sizeof(handler *), - GFP_ATOMIC); + iucv_pathid_table = kcalloc(max_connections, sizeof(handler *), + GFP_ATOMIC); if (iucv_pathid_table == NULL) { printk(KERN_WARNING "%s: iucv_pathid_table storage " "allocation failed\n", __FUNCTION__); kfree(new_handler); return NULL; } - memset (iucv_pathid_table, 0, max_connections * sizeof(handler *)); } memset(new_handler, 0, sizeof (handler)); memcpy(new_handler->id.user_data, pgmname, diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 9cf88d7201d3..edcf05d5d568 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -115,11 +115,10 @@ lcs_alloc_channel(struct lcs_channel *channel) LCS_DBF_TEXT(2, setup, "ichalloc"); for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) { /* alloc memory fo iobuffer */ - channel->iob[cnt].data = (void *) - kmalloc(LCS_IOBUFFERSIZE, GFP_DMA | GFP_KERNEL); + channel->iob[cnt].data = + kzalloc(LCS_IOBUFFERSIZE, GFP_DMA | GFP_KERNEL); if (channel->iob[cnt].data == NULL) break; - memset(channel->iob[cnt].data, 0, LCS_IOBUFFERSIZE); channel->iob[cnt].state = BUF_STATE_EMPTY; } if (cnt < LCS_NUM_BUFFS) { @@ -182,10 +181,9 @@ lcs_alloc_card(void) LCS_DBF_TEXT(2, setup, "alloclcs"); - card = kmalloc(sizeof(struct lcs_card), GFP_KERNEL | GFP_DMA); + card = kzalloc(sizeof(struct lcs_card), GFP_KERNEL | GFP_DMA); if (card == NULL) return NULL; - memset(card, 0, sizeof(struct lcs_card)); card->lan_type = LCS_FRAME_TYPE_AUTO; card->pkt_seq = 0; card->lancmd_timeout = LCS_LANCMD_TIMEOUT_DEFAULT; @@ -793,10 +791,9 @@ lcs_alloc_reply(struct lcs_cmd *cmd) LCS_DBF_TEXT(4, trace, "getreply"); - reply = kmalloc(sizeof(struct lcs_reply), GFP_ATOMIC); + reply = kzalloc(sizeof(struct lcs_reply), GFP_ATOMIC); if (!reply) return NULL; - memset(reply,0,sizeof(struct lcs_reply)); atomic_set(&reply->refcnt,1); reply->sequence_no = cmd->sequence_no; reply->received = 0; diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 71d3853e8682..260a93c8c442 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1728,14 +1728,13 @@ static int netiucv_register_device(struct net_device *ndev) { struct netiucv_priv *priv = ndev->priv; - struct device *dev = kmalloc(sizeof(struct device), GFP_KERNEL); + struct device *dev = kzalloc(sizeof(struct device), GFP_KERNEL); int ret; IUCV_DBF_TEXT(trace, 3, __FUNCTION__); if (dev) { - memset(dev, 0, sizeof(struct device)); snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name); dev->bus = &iucv_bus; dev->parent = iucv_root; @@ -1784,11 +1783,9 @@ netiucv_new_connection(struct net_device *dev, char *username) { struct iucv_connection **clist = &iucv_connections; struct iucv_connection *conn = - (struct iucv_connection *) - kmalloc(sizeof(struct iucv_connection), GFP_KERNEL); + kzalloc(sizeof(struct iucv_connection), GFP_KERNEL); if (conn) { - memset(conn, 0, sizeof(struct iucv_connection)); skb_queue_head_init(&conn->collect_queue); skb_queue_head_init(&conn->commit_queue); conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT; diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 82cb4af2f0e7..44e226f211e7 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -389,9 +389,8 @@ qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl) struct qeth_eddp_data *eddp; QETH_DBF_TEXT(trace, 5, "eddpcrda"); - eddp = kmalloc(sizeof(struct qeth_eddp_data), GFP_ATOMIC); + eddp = kzalloc(sizeof(struct qeth_eddp_data), GFP_ATOMIC); if (eddp){ - memset(eddp, 0, sizeof(struct qeth_eddp_data)); eddp->nhl = nhl; eddp->thl = thl; memcpy(&eddp->qh, qh, sizeof(struct qeth_hdr)); @@ -542,12 +541,11 @@ qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb, QETH_DBF_TEXT(trace, 5, "creddpcg"); /* create the context and allocate pages */ - ctx = kmalloc(sizeof(struct qeth_eddp_context), GFP_ATOMIC); + ctx = kzalloc(sizeof(struct qeth_eddp_context), GFP_ATOMIC); if (ctx == NULL){ QETH_DBF_TEXT(trace, 2, "ceddpcn1"); return NULL; } - memset(ctx, 0, sizeof(struct qeth_eddp_context)); ctx->type = QETH_LARGE_SEND_EDDP; qeth_eddp_calc_num_pages(ctx, skb, hdr_len); if (ctx->elements_per_skb > QETH_MAX_BUFFER_ELEMENTS(card)){ @@ -555,13 +553,12 @@ qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb, kfree(ctx); return NULL; } - ctx->pages = kmalloc(ctx->num_pages * sizeof(u8 *), GFP_ATOMIC); + ctx->pages = kcalloc(ctx->num_pages, sizeof(u8 *), GFP_ATOMIC); if (ctx->pages == NULL){ QETH_DBF_TEXT(trace, 2, "ceddpcn2"); kfree(ctx); return NULL; } - memset(ctx->pages, 0, ctx->num_pages * sizeof(u8 *)); for (i = 0; i < ctx->num_pages; ++i){ addr = (u8 *)__get_free_page(GFP_ATOMIC); if (addr == NULL){ @@ -573,15 +570,13 @@ qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb, memset(addr, 0, PAGE_SIZE); ctx->pages[i] = addr; } - ctx->elements = kmalloc(ctx->num_elements * + ctx->elements = kcalloc(ctx->num_elements, sizeof(struct qeth_eddp_element), GFP_ATOMIC); if (ctx->elements == NULL){ QETH_DBF_TEXT(trace, 2, "ceddpcn4"); qeth_eddp_free_context(ctx); return NULL; } - memset(ctx->elements, 0, - ctx->num_elements * sizeof(struct qeth_eddp_element)); /* reset num_elements; will be incremented again in fill_buffer to * reflect number of actually used elements */ ctx->num_elements = 0; diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 021cd5d08c61..b3c6e7907790 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -297,12 +297,10 @@ qeth_alloc_card(void) struct qeth_card *card; QETH_DBF_TEXT(setup, 2, "alloccrd"); - card = (struct qeth_card *) kmalloc(sizeof(struct qeth_card), - GFP_DMA|GFP_KERNEL); + card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL); if (!card) return NULL; QETH_DBF_HEX(setup, 2, &card, sizeof(void *)); - memset(card, 0, sizeof(struct qeth_card)); if (qeth_setup_channel(&card->read)) { kfree(card); return NULL; @@ -1632,9 +1630,8 @@ qeth_alloc_reply(struct qeth_card *card) { struct qeth_reply *reply; - reply = kmalloc(sizeof(struct qeth_reply), GFP_ATOMIC); + reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC); if (reply){ - memset(reply, 0, sizeof(struct qeth_reply)); atomic_set(&reply->refcnt, 1); reply->card = card; }; @@ -3348,13 +3345,11 @@ qeth_qdio_establish(struct qeth_card *card) QETH_DBF_TEXT(setup, 2, "qdioest"); - qib_param_field = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char), + qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char), GFP_KERNEL); if (!qib_param_field) return -ENOMEM; - memset(qib_param_field, 0, QDIO_MAX_BUFFERS_PER_Q * sizeof(char)); - qeth_create_qib_param_field(card, qib_param_field); qeth_create_qib_param_field_blkt(card, qib_param_field); @@ -4819,9 +4814,8 @@ qeth_arp_query(struct qeth_card *card, char *udata) /* get size of userspace buffer and mask_bits -> 6 bytes */ if (copy_from_user(&qinfo, udata, 6)) return -EFAULT; - if (!(qinfo.udata = kmalloc(qinfo.udata_len, GFP_KERNEL))) + if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL))) return -ENOMEM; - memset(qinfo.udata, 0, qinfo.udata_len); qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET; iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, IPA_CMD_ASS_ARP_QUERY_INFO, @@ -4969,11 +4963,10 @@ qeth_snmp_command(struct qeth_card *card, char *udata) return -EFAULT; } qinfo.udata_len = ureq->hdr.data_len; - if (!(qinfo.udata = kmalloc(qinfo.udata_len, GFP_KERNEL))){ + if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL))){ kfree(ureq); return -ENOMEM; } - memset(qinfo.udata, 0, qinfo.udata_len); qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr); iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL, @@ -5564,12 +5557,11 @@ qeth_get_addr_buffer(enum qeth_prot_versions prot) { struct qeth_ipaddr *addr; - addr = kmalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC); + addr = kzalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC); if (addr == NULL) { PRINT_WARN("Not enough memory to add address\n"); return NULL; } - memset(addr,0,sizeof(struct qeth_ipaddr)); addr->type = QETH_IP_TYPE_NORMAL; addr->proto = prot; return addr; diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index f2a076a2b2f1..882d419e4160 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -1145,11 +1145,10 @@ qeth_dev_ipato_add_store(const char *buf, size_t count, if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits))) return rc; - if (!(ipatoe = kmalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL))){ + if (!(ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL))){ PRINT_WARN("No memory to allocate ipato entry\n"); return -ENOMEM; } - memset(ipatoe, 0, sizeof(struct qeth_ipato_entry)); ipatoe->proto = proto; memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16); ipatoe->mask_bits = mask_bits; diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c index e3f647169827..3c7145d9f9a1 100644 --- a/drivers/s390/s390_rdev.c +++ b/drivers/s390/s390_rdev.c @@ -27,10 +27,9 @@ s390_root_dev_register(const char *name) if (!strlen(name)) return ERR_PTR(-EINVAL); - dev = kmalloc(sizeof(struct device), GFP_KERNEL); + dev = kzalloc(sizeof(struct device), GFP_KERNEL); if (!dev) return ERR_PTR(-ENOMEM); - memset(dev, 0, sizeof(struct device)); strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE)); dev->release = s390_root_dev_release; ret = device_register(dev); -- cgit v1.2.3-59-g8ed1b From b5029622ac86bb441dc5e641226fb1152fca02d7 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Fri, 24 Mar 2006 03:15:32 -0800 Subject: [PATCH] dasd: "cleanup dasd_ioctl" fix Cast the argument correctly. Cc: Christoph Hellwig Cc: Martin Schwidefsky Cc: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index d0c2d732dcff..b8c80d28df41 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -29,7 +29,7 @@ static int dasd_ioctl_api_version(void __user *argp) { int ver = DASD_API_VERSION; - return put_user(ver, (int *)argp); + return put_user(ver, (int __user *)argp); } /* -- cgit v1.2.3-59-g8ed1b From ef5a4c8b04867fa8ed9eaf311c4ed0c57c589b6d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 24 Mar 2006 03:15:36 -0800 Subject: [PATCH] remove ISA legacy functions: drivers/char/toshiba.c switch from isa_read...() to ioremap() and read...() Signed-off-by: Al Viro Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/toshiba.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c index 0c6f521abd0e..e2fb234dee40 100644 --- a/drivers/char/toshiba.c +++ b/drivers/char/toshiba.c @@ -355,14 +355,14 @@ static void tosh_set_fn_port(void) /* * Get the machine identification number of the current model */ -static int tosh_get_machine_id(void) +static int tosh_get_machine_id(void __iomem *bios) { int id; SMMRegisters regs; unsigned short bx,cx; unsigned long address; - id = (0x100*(int) isa_readb(0xffffe))+((int) isa_readb(0xffffa)); + id = (0x100*(int) readb(bios+0xfffe))+((int) readb(bios+0xfffa)); /* do we have a SCTTable machine identication number on our hands */ @@ -388,12 +388,12 @@ static int tosh_get_machine_id(void) /* now twiddle with our pointer a bit */ - address = 0x000f0000+bx; - cx = isa_readw(address); - address = 0x000f0009+bx+cx; - cx = isa_readw(address); - address = 0x000f000a+cx; - cx = isa_readw(address); + address = bx; + cx = readw(bios + address); + address = 9+bx+cx; + cx = readw(bios + address); + address = 0xa+cx; + cx = readw(bios + address); /* now construct our machine identification number */ @@ -416,13 +416,18 @@ static int tosh_probe(void) int i,major,minor,day,year,month,flag; unsigned char signature[7] = { 0x54,0x4f,0x53,0x48,0x49,0x42,0x41 }; SMMRegisters regs; + void __iomem *bios = ioremap(0xf0000, 0x10000); + + if (!bios) + return -ENOMEM; /* extra sanity check for the string "TOSHIBA" in the BIOS because some machines that are not Toshiba's pass the next test */ for (i=0;i<7;i++) { - if (isa_readb(0xfe010+i)!=signature[i]) { + if (readb(bios+0xe010+i)!=signature[i]) { printk("toshiba: not a supported Toshiba laptop\n"); + iounmap(bios); return -ENODEV; } } @@ -438,6 +443,7 @@ static int tosh_probe(void) if ((flag==1) || ((regs.eax & 0xff00)==0x8600)) { printk("toshiba: not a supported Toshiba laptop\n"); + iounmap(bios); return -ENODEV; } @@ -447,19 +453,19 @@ static int tosh_probe(void) /* next get the machine ID of the current laptop */ - tosh_id = tosh_get_machine_id(); + tosh_id = tosh_get_machine_id(bios); /* get the BIOS version */ - major = isa_readb(0xfe009)-'0'; - minor = ((isa_readb(0xfe00b)-'0')*10)+(isa_readb(0xfe00c)-'0'); + major = readb(bios+0xe009)-'0'; + minor = ((readb(bios+0xe00b)-'0')*10)+(readb(bios+0xe00c)-'0'); tosh_bios = (major*0x100)+minor; /* get the BIOS date */ - day = ((isa_readb(0xffff5)-'0')*10)+(isa_readb(0xffff6)-'0'); - month = ((isa_readb(0xffff8)-'0')*10)+(isa_readb(0xffff9)-'0'); - year = ((isa_readb(0xffffb)-'0')*10)+(isa_readb(0xffffc)-'0'); + day = ((readb(bios+0xfff5)-'0')*10)+(readb(bios+0xfff6)-'0'); + month = ((readb(bios+0xfff8)-'0')*10)+(readb(bios+0xfff9)-'0'); + year = ((readb(bios+0xfffb)-'0')*10)+(readb(bios+0xfffc)-'0'); tosh_date = (((year-90) & 0x1f)<<10) | ((month & 0xf)<<6) | ((day & 0x1f)<<1); @@ -476,6 +482,8 @@ static int tosh_probe(void) if ((tosh_id==0xfccb) || (tosh_id==0xfccc)) tosh_fan = 1; + iounmap(bios); + return 0; } -- cgit v1.2.3-59-g8ed1b From c818cb6406815716ab210ae15655ed94a973b15f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 24 Mar 2006 03:15:37 -0800 Subject: [PATCH] remove ISA legacy functions: drivers/scsi/g_NCR5380.c switched CONFIG_SCSI_G_NCR5380_MEM code in g_NCR5380 to ioremap(); massaged g_NCR5380.h accordingly. Signed-off-by: Al Viro Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/g_NCR5380.c | 28 +++++++++++++++++++++------- drivers/scsi/g_NCR5380.h | 23 +++++++++++++++++------ 2 files changed, 38 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 45756fa90777..e6bcfe949340 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -127,7 +127,7 @@ static int ncr_53c400a = NCR_NOT_SET; static int dtc_3181e = NCR_NOT_SET; static struct override { - NCR5380_implementation_fields; + NCR5380_map_type NCR5380_map_name; int irq; int dma; int board; /* Use NCR53c400, Ricoh, etc. extensions ? */ @@ -299,6 +299,10 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) }; int flags = 0; struct Scsi_Host *instance; +#ifdef CONFIG_SCSI_G_NCR5380_MEM + unsigned long base; + void __iomem *iomem; +#endif if (ncr_irq != NCR_NOT_SET) overrides[0].irq = ncr_irq; @@ -424,15 +428,22 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) region_size = NCR5380_region_size; } #else - if(!request_mem_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size, "ncr5380")) + base = overrides[current_override].NCR5380_map_name; + if (!request_mem_region(base, NCR5380_region_size, "ncr5380")) + continue; + iomem = ioremap(base, NCR5380_region_size); + if (!iomem) { + release_mem_region(base, NCR5380_region_size); continue; + } #endif instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); if (instance == NULL) { #ifndef CONFIG_SCSI_G_NCR5380_MEM release_region(overrides[current_override].NCR5380_map_name, region_size); #else - release_mem_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size); + iounmap(iomem); + release_mem_region(base, NCR5380_region_size); #endif continue; } @@ -440,6 +451,8 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name; #ifndef CONFIG_SCSI_G_NCR5380_MEM instance->n_io_port = region_size; +#else + ((struct NCR5380_hostdata *)instance->hostdata).iomem = iomem; #endif NCR5380_init(instance, flags); @@ -509,6 +522,7 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance) #ifndef CONFIG_SCSI_G_NCR5380_MEM release_region(instance->NCR5380_instance_name, instance->n_io_port); #else + iounmap(((struct NCR5380_hostdata *)instance->hostdata).iomem); release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size); #endif @@ -586,7 +600,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, } #else /* implies CONFIG_SCSI_G_NCR5380_MEM */ - isa_memcpy_fromio(dst + start, NCR53C400_host_buffer + NCR5380_map_name, 128); + memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); #endif start += 128; blocks--; @@ -606,7 +620,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, } #else /* implies CONFIG_SCSI_G_NCR5380_MEM */ - isa_memcpy_fromio(dst + start, NCR53C400_host_buffer + NCR5380_map_name, 128); + memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); #endif start += 128; blocks--; @@ -671,7 +685,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, } #else /* implies CONFIG_SCSI_G_NCR5380_MEM */ - isa_memcpy_toio(NCR53C400_host_buffer + NCR5380_map_name, src + start, 128); + memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); #endif start += 128; blocks--; @@ -687,7 +701,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, } #else /* implies CONFIG_SCSI_G_NCR5380_MEM */ - isa_memcpy_toio(NCR53C400_host_buffer + NCR5380_map_name, src + start, 128); + memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); #endif start += 128; blocks--; diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 656fbe2f91f6..d60a89cb8052 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -82,6 +82,15 @@ static const char* generic_NCR5380_info(struct Scsi_Host *); #define NCR5380_read(reg) (inb(NCR5380_map_name + (reg))) #define NCR5380_write(reg, value) (outb((value), (NCR5380_map_name + (reg)))) +#define NCR5380_implementation_fields \ + NCR5380_map_type NCR5380_map_name + +#define NCR5380_local_declare() \ + register NCR5380_implementation_fields + +#define NCR5380_setup(instance) \ + NCR5380_map_name = (NCR5380_map_type)((instance)->NCR5380_instance_name) + #else /* therefore CONFIG_SCSI_G_NCR5380_MEM */ @@ -95,18 +104,20 @@ static const char* generic_NCR5380_info(struct Scsi_Host *); #define NCR53C400_host_buffer 0x3900 #define NCR5380_region_size 0x3a00 -#define NCR5380_read(reg) isa_readb(NCR5380_map_name + NCR53C400_mem_base + (reg)) -#define NCR5380_write(reg, value) isa_writeb(value, NCR5380_map_name + NCR53C400_mem_base + (reg)) -#endif +#define NCR5380_read(reg) readb(iomem + NCR53C400_mem_base + (reg)) +#define NCR5380_write(reg, value) writeb(value, iomem + NCR53C400_mem_base + (reg)) #define NCR5380_implementation_fields \ - NCR5380_map_type NCR5380_map_name + NCR5380_map_type NCR5380_map_name; \ + void __iomem *iomem; #define NCR5380_local_declare() \ - register NCR5380_implementation_fields + register void __iomem *iomem #define NCR5380_setup(instance) \ - NCR5380_map_name = (NCR5380_map_type)((instance)->NCR5380_instance_name) + iomem = (((struct NCR5380_hostdata *)(instance)->hostdata).iomem) + +#endif #define NCR5380_intr generic_NCR5380_intr #define NCR5380_queue_command generic_NCR5380_queue_command -- cgit v1.2.3-59-g8ed1b From 22bc685f4b93f4a0ce28e5829eaf754cb4f7c040 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 24 Mar 2006 03:15:38 -0800 Subject: [PATCH] remove ISA legacy functions: drivers/scsi/in2000.c switched to ioremap(), cleaned the probing up a bit. Signed-off-by: Al Viro Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/in2000.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index 34daa3e068de..9c519876f8a0 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c @@ -1898,6 +1898,21 @@ static int int_tab[] in2000__INITDATA = { 10 }; +static int probe_bios(u32 addr, u32 *s1, uchar *switches) +{ + void __iomem *p = ioremap(addr, 0x34); + if (!p) + return 0; + *s1 = readl(p + 0x10); + if (*s1 == 0x41564f4e || readl(p + 0x30) == 0x61776c41) { + /* Read the switch image that's mapped into EPROM space */ + *switches = ~readb(p + 0x20); + iounmap(p); + return 1; + } + iounmap(p); + return 0; +} static int __init in2000_detect(struct scsi_host_template * tpnt) { @@ -1930,6 +1945,7 @@ static int __init in2000_detect(struct scsi_host_template * tpnt) detect_count = 0; for (bios = 0; bios_tab[bios]; bios++) { + u32 s1 = 0; if (check_setup_args("ioport", &val, buf)) { base = val; switches = ~inb(base + IO_SWITCHES) & 0xff; @@ -1941,13 +1957,9 @@ static int __init in2000_detect(struct scsi_host_template * tpnt) * for the obvious ID strings. We look for the 2 most common ones and * hope that they cover all the cases... */ - else if (isa_readl(bios_tab[bios] + 0x10) == 0x41564f4e || isa_readl(bios_tab[bios] + 0x30) == 0x61776c41) { + else if (probe_bios(bios_tab[bios], &s1, &switches)) { printk("Found IN2000 BIOS at 0x%x ", (unsigned int) bios_tab[bios]); -/* Read the switch image that's mapped into EPROM space */ - - switches = ~((isa_readb(bios_tab[bios] + 0x20) & 0xff)); - /* Find out where the IO space is */ x = switches & (SW_ADDR0 | SW_ADDR1); @@ -2037,7 +2049,7 @@ static int __init in2000_detect(struct scsi_host_template * tpnt) /* Older BIOS's had a 'sync on/off' switch - use its setting */ - if (isa_readl(bios_tab[bios] + 0x10) == 0x41564f4e && (switches & SW_SYNC_DOS5)) + if (s1 == 0x41564f4e && (switches & SW_SYNC_DOS5)) hostdata->sync_off = 0x00; /* sync defaults to on */ else hostdata->sync_off = 0xff; /* sync defaults to off */ -- cgit v1.2.3-59-g8ed1b From b336cea307839f97684d314071ef683821c571ed Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 24 Mar 2006 03:15:40 -0800 Subject: [PATCH] remove ISA legacy functions: drivers/net/hp-plus.c switch to ioremap() Adrian Bunk: The order of the hunks in the patch was slightly rearranged due to an unrelated change in the driver. Signed-off-by: Al Viro Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/hp-plus.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index 74e167e7dea7..0d7a6250e346 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c @@ -250,6 +250,12 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr) ei_status.block_output = &hpp_mem_block_output; ei_status.get_8390_hdr = &hpp_mem_get_8390_hdr; dev->mem_start = mem_start; + ei_status.mem = ioremap(mem_start, + (HP_STOP_PG - HP_START_PG)*256); + if (!ei_status.mem) { + retval = -ENOMEM; + goto out; + } ei_status.rmem_start = dev->mem_start + TX_PAGES/2*256; dev->mem_end = ei_status.rmem_end = dev->mem_start + (HP_STOP_PG - HP_START_PG)*256; @@ -262,8 +268,10 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr) retval = register_netdev(dev); if (retval) - goto out; + goto out1; return 0; +out1: + iounmap(ei_status.mem); out: release_region(ioaddr, HP_IO_EXTENT); return retval; @@ -372,7 +380,7 @@ hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring outw((ring_page<<8), ioaddr + HPP_IN_ADDR); outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION); - isa_memcpy_fromio(hdr, dev->mem_start, sizeof(struct e8390_pkt_hdr)); + memcpy_fromio(hdr, ei_status.mem, sizeof(struct e8390_pkt_hdr)); outw(option_reg, ioaddr + HPP_OPTION); hdr->count = (le16_to_cpu(hdr->count) + 3) & ~3; /* Round up allocation. */ } @@ -391,7 +399,7 @@ hpp_mem_block_input(struct net_device *dev, int count, struct sk_buff *skb, int Also note that we *can't* use eth_io_copy_and_sum() because it will not always copy "count" bytes (e.g. padded IP). */ - isa_memcpy_fromio(skb->data, dev->mem_start, count); + memcpy_fromio(skb->data, ei_status.mem, count); outw(option_reg, ioaddr + HPP_OPTION); } @@ -416,7 +424,7 @@ hpp_mem_block_output(struct net_device *dev, int count, outw(start_page << 8, ioaddr + HPP_OUT_ADDR); outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION); - isa_memcpy_toio(dev->mem_start, buf, (count + 3) & ~3); + memcpy_toio(ei_status.mem, buf, (count + 3) & ~3); outw(option_reg, ioaddr + HPP_OPTION); return; @@ -470,6 +478,7 @@ init_module(void) static void cleanup_card(struct net_device *dev) { /* NB: hpp_close() handles free_irq */ + iounmap(ei_status.mem); release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); } -- cgit v1.2.3-59-g8ed1b From c44fec118b62baad3fc70e2ef3447729a1d9b194 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 24 Mar 2006 03:15:41 -0800 Subject: [PATCH] remove ISA legacy functions: drivers/net/lance.c switch to ioremap() Signed-off-by: Al Viro Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/lance.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/lance.c b/drivers/net/lance.c index d1d714faa6ce..bb5ad479210b 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -464,20 +464,25 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int static int did_version; /* Already printed version info. */ unsigned long flags; int err = -ENOMEM; + void __iomem *bios; /* First we look for special cases. Check for HP's on-board ethernet by looking for 'HP' in the BIOS. There are two HP versions, check the BIOS for the configuration port. This method provided by L. Julliard, Laurent_Julliard@grenoble.hp.com. */ - if (isa_readw(0x000f0102) == 0x5048) { + bios = ioremap(0xf00f0, 0x14); + if (!bios) + return -ENOMEM; + if (readw(bios + 0x12) == 0x5048) { static const short ioaddr_table[] = { 0x300, 0x320, 0x340, 0x360}; - int hp_port = (isa_readl(0x000f00f1) & 1) ? 0x499 : 0x99; + int hp_port = (readl(bios + 1) & 1) ? 0x499 : 0x99; /* We can have boards other than the built-in! Verify this is on-board. */ if ((inb(hp_port) & 0xc0) == 0x80 && ioaddr_table[inb(hp_port) & 3] == ioaddr) hp_builtin = hp_port; } + iounmap(bios); /* We also recognize the HP Vectra on-board here, but check below. */ hpJ2405A = (inb(ioaddr) == 0x08 && inb(ioaddr+1) == 0x00 && inb(ioaddr+2) == 0x09); -- cgit v1.2.3-59-g8ed1b From 53b3531bbbf70ac7551b32d1acc229d94de52658 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 24 Mar 2006 03:16:13 -0800 Subject: [PATCH] s/;;/;/g Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-pxa/leds-mainstone.c | 6 +++--- arch/arm/mach-s3c2410/cpu.c | 2 +- arch/frv/kernel/gdb-stub.c | 2 +- arch/ia64/sn/kernel/bte.c | 2 +- arch/ia64/sn/pci/tioca_provider.c | 2 +- arch/mips/mm/dma-ip32.c | 6 +++--- arch/ppc/syslib/ppc85xx_setup.c | 2 +- arch/sparc64/kernel/irq.c | 2 +- drivers/char/pcmcia/synclink_cs.c | 2 +- drivers/char/synclink.c | 2 +- drivers/char/synclink_gt.c | 2 +- drivers/char/synclinkmp.c | 2 +- drivers/hwmon/gl520sm.c | 2 +- drivers/i2c/chips/rtc8564.c | 2 +- drivers/ide/ide-dma.c | 2 +- drivers/net/sk98lin/skge.c | 2 +- drivers/net/sky2.h | 2 +- drivers/net/wireless/prism54/oid_mgt.c | 4 ++-- drivers/net/wireless/spectrum_cs.c | 2 +- drivers/scsi/megaraid/megaraid_mbox.c | 2 +- drivers/usb/image/microtek.c | 2 +- drivers/usb/input/hid-core.c | 2 +- drivers/video/aty/radeon_pm.c | 2 +- fs/cifs/cifssmb.c | 2 +- fs/pnode.c | 2 +- include/acpi/acpi_bus.h | 2 +- include/asm-ia64/sn/sn_sal.h | 2 +- net/ipv4/inet_hashtables.c | 2 +- net/ipv4/netfilter/ip_nat_standalone.c | 2 +- net/tipc/link.c | 2 +- sound/ppc/toonie.c | 4 ++-- 31 files changed, 37 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-pxa/leds-mainstone.c b/arch/arm/mach-pxa/leds-mainstone.c index bbd3f87a9fc2..c06d3d7a8dd4 100644 --- a/arch/arm/mach-pxa/leds-mainstone.c +++ b/arch/arm/mach-pxa/leds-mainstone.c @@ -85,7 +85,7 @@ void mainstone_leds_event(led_event_t evt) break; case led_green_on: - hw_led_state |= D21;; + hw_led_state |= D21; break; case led_green_off: @@ -93,7 +93,7 @@ void mainstone_leds_event(led_event_t evt) break; case led_amber_on: - hw_led_state |= D22;; + hw_led_state |= D22; break; case led_amber_off: @@ -101,7 +101,7 @@ void mainstone_leds_event(led_event_t evt) break; case led_red_on: - hw_led_state |= D23;; + hw_led_state |= D23; break; case led_red_off: diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c index 00a379334b60..70c34fcf7858 100644 --- a/arch/arm/mach-s3c2410/cpu.c +++ b/arch/arm/mach-s3c2410/cpu.c @@ -146,7 +146,7 @@ void s3c24xx_set_board(struct s3c24xx_board *b) board = b; if (b->clocks_count != 0) { - struct clk **ptr = b->clocks;; + struct clk **ptr = b->clocks; for (i = b->clocks_count; i > 0; i--, ptr++) s3c24xx_register_clock(*ptr); diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c index 8f860d9c4947..508601fad079 100644 --- a/arch/frv/kernel/gdb-stub.c +++ b/arch/frv/kernel/gdb-stub.c @@ -1406,7 +1406,7 @@ void gdbstub(int sigval) __debug_frame->psr |= PSR_S; __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12; __debug_regs->brr |= BRR_EB; - sigval = SIGXCPU;; + sigval = SIGXCPU; } LEDS(0x5002); diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c index 1f11db470d90..e952ef4f6d91 100644 --- a/arch/ia64/sn/kernel/bte.c +++ b/arch/ia64/sn/kernel/bte.c @@ -36,7 +36,7 @@ static struct bteinfo_s *bte_if_on_node(nasid_t nasid, int interface) nodepda_t *tmp_nodepda; if (nasid_to_cnodeid(nasid) == -1) - return (struct bteinfo_s *)NULL;; + return (struct bteinfo_s *)NULL; tmp_nodepda = NODEPDA(nasid_to_cnodeid(nasid)); return &tmp_nodepda->bte_if[interface]; diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 7571a4025529..be0176912968 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -377,7 +377,7 @@ tioca_dma_mapped(struct pci_dev *pdev, u64 paddr, size_t req_size) struct tioca_dmamap *ca_dmamap; void *map; unsigned long flags; - struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);; + struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev); tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info; tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private; diff --git a/arch/mips/mm/dma-ip32.c b/arch/mips/mm/dma-ip32.c index a7e3072ff78d..ec54ed0d26ff 100644 --- a/arch/mips/mm/dma-ip32.c +++ b/arch/mips/mm/dma-ip32.c @@ -138,7 +138,7 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, BUG(); } - addr = virt_to_phys(ptr)&RAM_OFFSET_MASK;; + addr = virt_to_phys(ptr)&RAM_OFFSET_MASK; if(dev == NULL) addr+=CRIME_HI_MEM_BASE; return (dma_addr_t)addr; @@ -179,7 +179,7 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, addr = (unsigned long) page_address(sg->page)+sg->offset; if (addr) __dma_sync(addr, sg->length, direction); - addr = __pa(addr)&RAM_OFFSET_MASK;; + addr = __pa(addr)&RAM_OFFSET_MASK; if(dev == NULL) addr += CRIME_HI_MEM_BASE; sg->dma_address = (dma_addr_t)addr; @@ -199,7 +199,7 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page, addr = (unsigned long) page_address(page) + offset; dma_cache_wback_inv(addr, size); - addr = __pa(addr)&RAM_OFFSET_MASK;; + addr = __pa(addr)&RAM_OFFSET_MASK; if(dev == NULL) addr += CRIME_HI_MEM_BASE; diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c index e70b34ee6275..79b7089d7500 100644 --- a/arch/ppc/syslib/ppc85xx_setup.c +++ b/arch/ppc/syslib/ppc85xx_setup.c @@ -235,7 +235,7 @@ mpc85xx_setup_pci2(struct pci_controller *hose) (__ilog2(MPC85XX_PCI2_UPPER_MEM - MPC85XX_PCI2_LOWER_MEM + 1) - 1); /* Setup outbound IO windows @ MPC85XX_PCI2_IO_BASE */ - pci->potar2 = (MPC85XX_PCI2_LOWER_IO >> 12) & 0x000fffff;; + pci->potar2 = (MPC85XX_PCI2_LOWER_IO >> 12) & 0x000fffff; pci->potear2 = 0x00000000; pci->powbar2 = (MPC85XX_PCI2_IO_BASE >> 12) & 0x000fffff; /* Enable, IO R/W */ diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index e505a4125e35..11e645c9ec50 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -727,7 +727,7 @@ void handler_irq(int irq, struct pt_regs *regs) } #ifdef CONFIG_BLK_DEV_FD -extern irqreturn_t floppy_interrupt(int, void *, struct pt_regs *);; +extern irqreturn_t floppy_interrupt(int, void *, struct pt_regs *); /* XXX No easy way to include asm/floppy.h XXX */ extern unsigned char *pdma_vaddr; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 8a8ca32822ba..e6b714b6390d 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -4181,7 +4181,7 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, } info->params.encoding = new_encoding; - info->params.crc_type = new_crctype;; + info->params.crc_type = new_crctype; /* if network interface up, reprogram hardware */ if (info->netcount) diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index ede688a4e141..d68be61f0a49 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -7770,7 +7770,7 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, } info->params.encoding = new_encoding; - info->params.crc_type = new_crctype;; + info->params.crc_type = new_crctype; /* if network interface up, reprogram hardware */ if (info->netcount) diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index b046390cd256..738ec2f4e563 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -1365,7 +1365,7 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, } info->params.encoding = new_encoding; - info->params.crc_type = new_crctype;; + info->params.crc_type = new_crctype; /* if network interface up, reprogram hardware */ if (info->netcount) diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 960adb256fbb..858740131115 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -1650,7 +1650,7 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, } info->params.encoding = new_encoding; - info->params.crc_type = new_crctype;; + info->params.crc_type = new_crctype; /* if network interface up, reprogram hardware */ if (info->netcount) diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 47b4d49f75c6..14e810f3c2c0 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -456,7 +456,7 @@ static ssize_t set_temp_max(struct i2c_client *client, struct gl520_data *data, long v = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); - data->temp_max[n - 1] = TEMP_TO_REG(v);; + data->temp_max[n - 1] = TEMP_TO_REG(v); gl520_write_value(client, reg, data->temp_max[n - 1]); mutex_unlock(&data->update_lock); return count; diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c index ceaa6b0bdfd6..0d8699b3f488 100644 --- a/drivers/i2c/chips/rtc8564.c +++ b/drivers/i2c/chips/rtc8564.c @@ -53,7 +53,7 @@ static inline u8 _rtc8564_ctrl2(struct i2c_client *client) #define CTRL1(c) _rtc8564_ctrl1(c) #define CTRL2(c) _rtc8564_ctrl2(c) -static int debug;; +static int debug; module_param(debug, int, S_IRUGO | S_IWUSR); static struct i2c_driver rtc8564_driver; diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 0523da77425a..c481be8b807f 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -175,7 +175,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive) if (rq->rq_disk) { ide_driver_t *drv; - drv = *(ide_driver_t **)rq->rq_disk->private_data;; + drv = *(ide_driver_t **)rq->rq_disk->private_data; drv->end_request(drive, 1, rq->nr_sectors); } else ide_end_request(drive, 1, rq->nr_sectors); diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index a5f2b1ee0752..38a26df4095f 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -1727,7 +1727,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); pTxd->pMBuf = pMessage; - pTxd->TBControl = Control | BMU_OWN | sk_frag->size;; + pTxd->TBControl = Control | BMU_OWN | sk_frag->size; /* ** Do we have the last fragment? diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 2838f661b393..62532b4e45c5 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1804,7 +1804,7 @@ struct sky2_rx_le { __le16 length; u8 ctrl; u8 opcode; -} __attribute((packed));; +} __attribute((packed)); struct sky2_status_le { __le32 status; /* also checksum */ diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index eea2f04c8c6d..ebb238785839 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c @@ -332,7 +332,7 @@ mgt_le_to_cpu(int type, void *data) case OID_TYPE_ATTACH:{ struct obj_attachment *attach = data; attach->id = le16_to_cpu(attach->id); - attach->size = le16_to_cpu(attach->size);; + attach->size = le16_to_cpu(attach->size); break; } case OID_TYPE_SSID: @@ -401,7 +401,7 @@ mgt_cpu_to_le(int type, void *data) case OID_TYPE_ATTACH:{ struct obj_attachment *attach = data; attach->id = cpu_to_le16(attach->id); - attach->size = cpu_to_le16(attach->size);; + attach->size = cpu_to_le16(attach->size); break; } case OID_TYPE_SSID: diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index fee4be1ce810..5fa6fbe35bb9 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -147,7 +147,7 @@ struct pdi { __le16 _len; /* length of ID and data, in words */ __le16 _id; /* record ID */ char data[0]; /* plug data */ -} __attribute__ ((packed));; +} __attribute__ ((packed)); /* Functions for access to little-endian data */ diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index bf9f7f7ba354..c11e5ce6865e 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -2797,7 +2797,7 @@ mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[]) // available within 1 second, assume FW is initializing and wait // for an extended amount of time if (mbox->numstatus == 0xFF) { // status not yet available - udelay(25);; + udelay(25); for (i = 0; mbox->numstatus == 0xFF && i < 1000; i++) { rmb(); diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 28538db9eaf3..2a0e18a48748 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -360,7 +360,7 @@ static int mts_scsi_host_reset (Scsi_Cmnd *srb) rc = usb_lock_device_for_reset(desc->usb_dev, desc->usb_intf); if (rc < 0) return FAILED; - result = usb_reset_device(desc->usb_dev);; + result = usb_reset_device(desc->usb_dev); if (rc) usb_unlock_device(desc->usb_dev); return result ? FAILED : SUCCESS; diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 58b59f6e9881..d4bf1701046b 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1215,7 +1215,7 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs) if (hid->outhead != hid->outtail) { if (hid_submit_out(hid)) { - clear_bit(HID_OUT_RUNNING, &hid->iofl);; + clear_bit(HID_OUT_RUNNING, &hid->iofl); wake_up(&hid->wait); } spin_unlock_irqrestore(&hid->outlock, flags); diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 1f8d805c61e5..5886a2f1323e 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2080,7 +2080,7 @@ static void radeon_reinitialize_M9P(struct radeonfb_info *rinfo) OUTREG(0x2ec, 0x6332a3f0); mdelay(17); - OUTPLL(pllPPLL_REF_DIV, rinfo->pll.ref_div);; + OUTPLL(pllPPLL_REF_DIV, rinfo->pll.ref_div); OUTPLL(pllPPLL_DIV_0, rinfo->save_regs[92]); mdelay(40); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b41e8b379652..a243fe2792d5 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -4908,7 +4908,7 @@ SetEARetry: parm_data->list_len = cpu_to_le32(count); parm_data->list[0].EA_flags = 0; /* we checked above that name len is less than 255 */ - parm_data->list[0].name_len = (__u8)name_len;; + parm_data->list[0].name_len = (__u8)name_len; /* EA names are always ASCII */ if(ea_name) strncpy(parm_data->list[0].name,ea_name,name_len); diff --git a/fs/pnode.c b/fs/pnode.c index f1871f773f64..37b568ed0e05 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -130,7 +130,7 @@ static struct vfsmount *get_source(struct vfsmount *dest, { struct vfsmount *p_last_src = NULL; struct vfsmount *p_last_dest = NULL; - *type = CL_PROPAGATION;; + *type = CL_PROPAGATION; if (IS_MNT_SHARED(dest)) *type |= CL_MAKE_SHARED; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e496fac860ac..6dca3d542080 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -269,7 +269,7 @@ struct acpi_device_wakeup_state { struct acpi_device_wakeup { acpi_handle gpe_device; - acpi_integer gpe_number;; + acpi_integer gpe_number; acpi_integer sleep_state; struct acpi_handle_list resources; struct acpi_device_wakeup_state state; diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index e77f0c9b7d3d..b546de2fdce5 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -1037,7 +1037,7 @@ ia64_sn_get_sn_info(int fc, u8 *shubtype, u16 *nasid_bitmask, u8 *nasid_shift, /***** BEGIN HACK - temp til old proms no longer supported ********/ if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) { - int nasid = get_sapicid() & 0xfff;; + int nasid = get_sapicid() & 0xfff; #define SH_SHUB_ID_NODES_PER_BIT_MASK 0x001f000000000000UL #define SH_SHUB_ID_NODES_PER_BIT_SHFT 48 if (shubtype) *shubtype = 0; diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 33228115cda4..ef7366fc132f 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -315,7 +315,7 @@ ok: spin_unlock(&head->lock); if (tw) { - inet_twsk_deschedule(tw, death_row);; + inet_twsk_deschedule(tw, death_row); inet_twsk_put(tw); } diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index ab1f88fa21ec..380aef3d7865 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -394,7 +394,7 @@ static int init_or_cleanup(int init) ret = nf_register_hook(&ip_nat_local_out_ops); if (ret < 0) { printk("ip_nat_init: can't register local out hook.\n"); - goto cleanup_adjustout_ops;; + goto cleanup_adjustout_ops; } ret = nf_register_hook(&ip_nat_local_in_ops); if (ret < 0) { diff --git a/net/tipc/link.c b/net/tipc/link.c index 910b37e5083d..784b24b6d102 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1629,7 +1629,7 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, tipc_msg_print(TIPC_CONS, buf_msg(buf), ">RETR>"); info("...Retransmitted %u times\n", l_ptr->stale_count); - link_print(l_ptr, TIPC_CONS, "Resetting Link\n");; + link_print(l_ptr, TIPC_CONS, "Resetting Link\n"); tipc_link_reset(l_ptr); break; } diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c index 210be20dc27e..4e595172e423 100644 --- a/sound/ppc/toonie.c +++ b/sound/ppc/toonie.c @@ -117,7 +117,7 @@ static int toonie_get_mute_switch(struct snd_kcontrol *kcontrol, gp = &mix->amp_mute_gpio; break; default: - return -EINVAL;; + return -EINVAL; } ucontrol->value.integer.value[0] = !check_audio_gpio(gp); return 0; @@ -145,7 +145,7 @@ static int toonie_put_mute_switch(struct snd_kcontrol *kcontrol, gp = &mix->amp_mute_gpio; break; default: - return -EINVAL;; + return -EINVAL; } val = ! check_audio_gpio(gp); if (val != ucontrol->value.integer.value[0]) { -- cgit v1.2.3-59-g8ed1b From e933b6d6511dc80c63ab36fd584715371ae293c7 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 24 Mar 2006 03:16:15 -0800 Subject: [PATCH] remove ipmi pm_power_off redefinition Use the global define of pm_power_off Signed-off-by: Olaf Hering Cc: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_poweroff.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 49c09ae004bf..e8ed26b77d4c 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -37,15 +37,13 @@ #include #include #include +#include #include #include #include #define PFX "IPMI poweroff: " -/* Where to we insert our poweroff function? */ -extern void (*pm_power_off)(void); - /* Definitions for controlling power off (if the system supports it). It * conveniently matches the IPMI chassis control values. */ #define IPMI_CHASSIS_POWER_DOWN 0 /* power down, the default. */ -- cgit v1.2.3-59-g8ed1b From 453ae9337aa3a7da12db723223998c7f75a026c0 Mon Sep 17 00:00:00 2001 From: Arthur Othieno Date: Fri, 24 Mar 2006 03:18:07 -0800 Subject: [PATCH] block: floppy98 removal, really. floppy98 went out together with the rest of PC98 subarch. Remove stale Makefile entry that remained. Signed-off-by: Arthur Othieno Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/Makefile | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 3ec1f8df87b1..410f259a8031 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o obj-$(CONFIG_BLK_DEV_FD) += floppy.o -obj-$(CONFIG_BLK_DEV_FD98) += floppy98.o obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o obj-$(CONFIG_BLK_DEV_SWIM_IOP) += swim_iop.o -- cgit v1.2.3-59-g8ed1b From 4741c9fd36b3bcadd37238321c469049da94a4b9 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 24 Mar 2006 03:18:11 -0800 Subject: [PATCH] set_page_dirty() return value fixes We need set_page_dirty() to return true if it actually transitioned the page from a clean to dirty state. This wasn't right in a couple of places. Do a kernel-wide audit, fix things up. This leaves open the possibility of returning a negative errno from set_page_dirty() sometime in the future. But we don't do that at present. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/cris/arch-v32/drivers/cryptocop.c | 2 +- drivers/block/rd.c | 3 ++- fs/buffer.c | 2 +- include/linux/fs.h | 2 +- mm/page-writeback.c | 11 ++++++----- 5 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c index 501fa52d8d3a..c59ee28a35f4 100644 --- a/arch/cris/arch-v32/drivers/cryptocop.c +++ b/arch/cris/arch-v32/drivers/cryptocop.c @@ -2944,7 +2944,7 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig int spdl_err; /* Mark output pages dirty. */ spdl_err = set_page_dirty_lock(outpages[i]); - DEBUG(if (spdl_err)printk("cryptocop_ioctl_process: set_page_dirty_lock returned %d\n", spdl_err)); + DEBUG(if (spdl_err < 0)printk("cryptocop_ioctl_process: set_page_dirty_lock returned %d\n", spdl_err)); } for (i = 0; i < nooutpages; i++){ put_page(outpages[i]); diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 1c54f46d3f70..940bfd7951e5 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -186,7 +186,8 @@ static int ramdisk_writepages(struct address_space *mapping, */ static int ramdisk_set_page_dirty(struct page *page) { - SetPageDirty(page); + if (!TestSetPageDirty(page)) + return 1; return 0; } diff --git a/fs/buffer.c b/fs/buffer.c index 11ca6eb46a33..24262ea8cc50 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -865,8 +865,8 @@ int __set_page_dirty_buffers(struct page *page) } write_unlock_irq(&mapping->tree_lock); __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); + return 1; } - return 0; } EXPORT_SYMBOL(__set_page_dirty_buffers); diff --git a/include/linux/fs.h b/include/linux/fs.h index 0ad70c1e5e55..092cfaee0cd2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -350,7 +350,7 @@ struct address_space_operations { /* Write back some dirty pages from this mapping. */ int (*writepages)(struct address_space *, struct writeback_control *); - /* Set a page dirty */ + /* Set a page dirty. Return true if this dirtied it */ int (*set_page_dirty)(struct page *page); int (*readpages)(struct file *filp, struct address_space *mapping, diff --git a/mm/page-writeback.c b/mm/page-writeback.c index c67ddc464721..893d7677579e 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -628,8 +628,6 @@ EXPORT_SYMBOL(write_one_page); */ int __set_page_dirty_nobuffers(struct page *page) { - int ret = 0; - if (!TestSetPageDirty(page)) { struct address_space *mapping = page_mapping(page); struct address_space *mapping2; @@ -651,8 +649,9 @@ int __set_page_dirty_nobuffers(struct page *page) I_DIRTY_PAGES); } } + return 1; } - return ret; + return 0; } EXPORT_SYMBOL(__set_page_dirty_nobuffers); @@ -682,8 +681,10 @@ int fastcall set_page_dirty(struct page *page) return (*spd)(page); return __set_page_dirty_buffers(page); } - if (!PageDirty(page)) - SetPageDirty(page); + if (!PageDirty(page)) { + if (!TestSetPageDirty(page)) + return 1; + } return 0; } EXPORT_SYMBOL(set_page_dirty); -- cgit v1.2.3-59-g8ed1b From d129bceb1d44ed3c23b99164849193703372bab4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Mar 2006 03:18:17 -0800 Subject: [PATCH] mmc: Secure Digital Host Controller Interface driver Driver for the Secure Digital Host Controller Interface specification. Signed-off-by: Pierre Ossman Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 7 + drivers/mmc/Kconfig | 11 + drivers/mmc/Makefile | 1 + drivers/mmc/sdhci.c | 1265 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/mmc/sdhci.h | 185 ++++++++ 5 files changed, 1469 insertions(+) create mode 100644 drivers/mmc/sdhci.c create mode 100644 drivers/mmc/sdhci.h (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index bfd7fbfe90ab..5b6a0145505d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2488,6 +2488,13 @@ M: kristen.c.accardi@intel.com L: pcihpd-discuss@lists.sourceforge.net S: Maintained +SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER +P: Pierre Ossman +M: drzeus-sdhci@drzeus.cx +L: sdhci-devel@list.drzeus.cx +W: http://mmc.drzeus.cx/wiki/Linux/Drivers/sdhci +S: Maintained + SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS P: Stephen Hemminger M: shemminger@osdl.org diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 5d397b7a5497..3f5d77f633fa 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -49,6 +49,17 @@ config MMC_PXA If unsure, say N. +config MMC_SDHCI + tristate "Secure Digital Host Controller Interface support (EXPERIMENTAL)" + depends on PCI && MMC && EXPERIMENTAL + help + This select the generic Secure Digital Host Controller Interface. + It is used by manufacturers such as Texas Instruments(R), Ricoh(R) + and Toshiba(R). Most controllers found in laptops are of this type. + If you have a controller with this interface, say Y or M here. + + If unsure, say N. + config MMC_WBSD tristate "Winbond W83L51xD SD/MMC Card Interface support" depends on MMC && ISA_DMA_API diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index e351e71146e9..769d545284a4 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_MMC_BLOCK) += mmc_block.o # obj-$(CONFIG_MMC_ARMMMCI) += mmci.o obj-$(CONFIG_MMC_PXA) += pxamci.o +obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_WBSD) += wbsd.o obj-$(CONFIG_MMC_AU1X) += au1xmmc.o diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c new file mode 100644 index 000000000000..8b811d94371c --- /dev/null +++ b/drivers/mmc/sdhci.c @@ -0,0 +1,1265 @@ +/* + * linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver + * + * Copyright (C) 2005-2006 Pierre Ossman, 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 version 2 as + * published by the Free Software Foundation. + */ + + /* + * Note that PIO transfer is rather crappy atm. The buffer full/empty + * interrupts aren't reliable so we currently transfer the entire buffer + * directly. Patches to solve the problem are welcome. + */ + +#include +#include +#include +#include + +#include +#include + +#include + +#include "sdhci.h" + +#define DRIVER_NAME "sdhci" +#define DRIVER_VERSION "0.11" + +#define BUGMAIL "" + +#ifdef CONFIG_MMC_DEBUG +#define DBG(f, x...) \ + printk(KERN_DEBUG DRIVER_NAME " [%s()]: " f, __func__,## x) +#else +#define DBG(f, x...) do { } while (0) +#endif + +static const struct pci_device_id pci_ids[] __devinitdata = { + /* handle any SD host controller */ + {PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)}, + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(pci, pci_ids); + +static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *); +static void sdhci_finish_data(struct sdhci_host *); + +static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); +static void sdhci_finish_command(struct sdhci_host *); + +static void sdhci_dumpregs(struct sdhci_host *host) +{ + printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n"); + + printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", + readl(host->ioaddr + SDHCI_DMA_ADDRESS), + readw(host->ioaddr + SDHCI_HOST_VERSION)); + printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", + readw(host->ioaddr + SDHCI_BLOCK_SIZE), + readw(host->ioaddr + SDHCI_BLOCK_COUNT)); + printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", + readl(host->ioaddr + SDHCI_ARGUMENT), + readw(host->ioaddr + SDHCI_TRANSFER_MODE)); + printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", + readl(host->ioaddr + SDHCI_PRESENT_STATE), + readb(host->ioaddr + SDHCI_HOST_CONTROL)); + printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", + readb(host->ioaddr + SDHCI_POWER_CONTROL), + readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL)); + printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", + readb(host->ioaddr + SDHCI_WALK_UP_CONTROL), + readw(host->ioaddr + SDHCI_CLOCK_CONTROL)); + printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", + readb(host->ioaddr + SDHCI_TIMEOUT_CONTROL), + readl(host->ioaddr + SDHCI_INT_STATUS)); + printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", + readl(host->ioaddr + SDHCI_INT_ENABLE), + readl(host->ioaddr + SDHCI_SIGNAL_ENABLE)); + printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", + readw(host->ioaddr + SDHCI_ACMD12_ERR), + readw(host->ioaddr + SDHCI_SLOT_INT_STATUS)); + printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n", + readl(host->ioaddr + SDHCI_CAPABILITIES), + readl(host->ioaddr + SDHCI_MAX_CURRENT)); + + printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n"); +} + +/*****************************************************************************\ + * * + * Low level functions * + * * +\*****************************************************************************/ + +static void sdhci_reset(struct sdhci_host *host, u8 mask) +{ + writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET); + + if (mask & SDHCI_RESET_ALL) { + host->clock = 0; + + mdelay(50); + } +} + +static void sdhci_init(struct sdhci_host *host) +{ + u32 intmask; + + sdhci_reset(host, SDHCI_RESET_ALL); + + intmask = ~(SDHCI_INT_CARD_INT | SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL); + + writel(intmask, host->ioaddr + SDHCI_INT_ENABLE); + writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE); + + /* This is unknown magic. */ + writeb(0xE, host->ioaddr + SDHCI_TIMEOUT_CONTROL); +} + +static void sdhci_activate_led(struct sdhci_host *host) +{ + u8 ctrl; + + ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); + ctrl |= SDHCI_CTRL_LED; + writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); +} + +static void sdhci_deactivate_led(struct sdhci_host *host) +{ + u8 ctrl; + + ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); + ctrl &= ~SDHCI_CTRL_LED; + writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); +} + +/*****************************************************************************\ + * * + * Core functions * + * * +\*****************************************************************************/ + +static inline char* sdhci_kmap_sg(struct sdhci_host* host) +{ + host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ); + return host->mapped_sg + host->cur_sg->offset; +} + +static inline void sdhci_kunmap_sg(struct sdhci_host* host) +{ + kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ); +} + +static inline int sdhci_next_sg(struct sdhci_host* host) +{ + /* + * Skip to next SG entry. + */ + host->cur_sg++; + host->num_sg--; + + /* + * Any entries left? + */ + if (host->num_sg > 0) { + host->offset = 0; + host->remain = host->cur_sg->length; + } + + return host->num_sg; +} + +static void sdhci_transfer_pio(struct sdhci_host *host) +{ + char *buffer; + u32 mask; + int bytes, size; + unsigned long max_jiffies; + + BUG_ON(!host->data); + + if (host->num_sg == 0) + return; + + bytes = 0; + if (host->data->flags & MMC_DATA_READ) + mask = SDHCI_DATA_AVAILABLE; + else + mask = SDHCI_SPACE_AVAILABLE; + + buffer = sdhci_kmap_sg(host) + host->offset; + + /* Transfer shouldn't take more than 5 s */ + max_jiffies = jiffies + HZ * 5; + + while (host->size > 0) { + if (time_after(jiffies, max_jiffies)) { + printk(KERN_ERR "%s: PIO transfer stalled. " + "Please report this to " + BUGMAIL ".\n", mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + + sdhci_kunmap_sg(host); + + host->data->error = MMC_ERR_FAILED; + sdhci_finish_data(host); + return; + } + + if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask)) + continue; + + size = min(host->size, host->remain); + + if (size >= 4) { + if (host->data->flags & MMC_DATA_READ) + *(u32*)buffer = readl(host->ioaddr + SDHCI_BUFFER); + else + writel(*(u32*)buffer, host->ioaddr + SDHCI_BUFFER); + size = 4; + } else if (size >= 2) { + if (host->data->flags & MMC_DATA_READ) + *(u16*)buffer = readw(host->ioaddr + SDHCI_BUFFER); + else + writew(*(u16*)buffer, host->ioaddr + SDHCI_BUFFER); + size = 2; + } else { + if (host->data->flags & MMC_DATA_READ) + *(u8*)buffer = readb(host->ioaddr + SDHCI_BUFFER); + else + writeb(*(u8*)buffer, host->ioaddr + SDHCI_BUFFER); + size = 1; + } + + buffer += size; + host->offset += size; + host->remain -= size; + + bytes += size; + host->size -= size; + + if (host->remain == 0) { + sdhci_kunmap_sg(host); + if (sdhci_next_sg(host) == 0) { + DBG("PIO transfer: %d bytes\n", bytes); + return; + } + buffer = sdhci_kmap_sg(host); + } + } + + sdhci_kunmap_sg(host); + + DBG("PIO transfer: %d bytes\n", bytes); +} + +static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) +{ + u16 mode; + + WARN_ON(host->data); + + if (data == NULL) { + writew(0, host->ioaddr + SDHCI_TRANSFER_MODE); + return; + } + + DBG("blksz %04x blks %04x flags %08x\n", + 1 << data->blksz_bits, data->blocks, data->flags); + DBG("tsac %d ms nsac %d clk\n", + data->timeout_ns / 1000000, data->timeout_clks); + + mode = SDHCI_TRNS_BLK_CNT_EN; + if (data->blocks > 1) + mode |= SDHCI_TRNS_MULTI; + if (data->flags & MMC_DATA_READ) + mode |= SDHCI_TRNS_READ; + if (host->flags & SDHCI_USE_DMA) + mode |= SDHCI_TRNS_DMA; + + writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE); + + writew(1 << data->blksz_bits, host->ioaddr + SDHCI_BLOCK_SIZE); + writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT); + + if (host->flags & SDHCI_USE_DMA) { + int count; + + count = pci_map_sg(host->chip->pdev, data->sg, data->sg_len, + (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE); + BUG_ON(count != 1); + + writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS); + } else { + host->size = (1 << data->blksz_bits) * data->blocks; + + host->cur_sg = data->sg; + host->num_sg = data->sg_len; + + host->offset = 0; + host->remain = host->cur_sg->length; + } +} + +static void sdhci_finish_data(struct sdhci_host *host) +{ + struct mmc_data *data; + u32 intmask; + u16 blocks; + + BUG_ON(!host->data); + + data = host->data; + host->data = NULL; + + if (host->flags & SDHCI_USE_DMA) { + pci_unmap_sg(host->chip->pdev, data->sg, data->sg_len, + (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE); + } else { + intmask = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE); + intmask &= ~(SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL); + writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE); + + intmask = readl(host->ioaddr + SDHCI_INT_ENABLE); + intmask &= ~(SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL); + writel(intmask, host->ioaddr + SDHCI_INT_ENABLE); + } + + /* + * Controller doesn't count down when in single block mode. + */ + if ((data->blocks == 1) && (data->error == MMC_ERR_NONE)) + blocks = 0; + else + blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT); + data->bytes_xfered = (1 << data->blksz_bits) * (data->blocks - blocks); + + if ((data->error == MMC_ERR_NONE) && blocks) { + printk(KERN_ERR "%s: Controller signalled completion even " + "though there were blocks left. Please report this " + "to " BUGMAIL ".\n", mmc_hostname(host->mmc)); + data->error = MMC_ERR_FAILED; + } + + if (host->size != 0) { + printk(KERN_ERR "%s: %d bytes were left untransferred. " + "Please report this to " BUGMAIL ".\n", + mmc_hostname(host->mmc), host->size); + data->error = MMC_ERR_FAILED; + } + + DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered); + + if (data->stop) { + /* + * The controller needs a reset of internal state machines + * upon error conditions. + */ + if (data->error != MMC_ERR_NONE) { + sdhci_reset(host, SDHCI_RESET_CMD); + sdhci_reset(host, SDHCI_RESET_DATA); + } + + sdhci_send_command(host, data->stop); + } else + tasklet_schedule(&host->finish_tasklet); +} + +static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) +{ + int flags; + u32 present; + unsigned long max_jiffies; + + WARN_ON(host->cmd); + + DBG("Sending cmd (%x)\n", cmd->opcode); + + /* Wait max 10 ms */ + max_jiffies = jiffies + (HZ + 99)/100; + do { + if (time_after(jiffies, max_jiffies)) { + printk(KERN_ERR "%s: Controller never released " + "inhibit bits. Please report this to " + BUGMAIL ".\n", mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + cmd->error = MMC_ERR_FAILED; + tasklet_schedule(&host->finish_tasklet); + return; + } + present = readl(host->ioaddr + SDHCI_PRESENT_STATE); + } while (present & (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)); + + mod_timer(&host->timer, jiffies + 10 * HZ); + + host->cmd = cmd; + + sdhci_prepare_data(host, cmd->data); + + writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT); + + if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { + printk(KERN_ERR "%s: Unsupported response type! " + "Please report this to " BUGMAIL ".\n", + mmc_hostname(host->mmc)); + cmd->error = MMC_ERR_INVALID; + tasklet_schedule(&host->finish_tasklet); + return; + } + + if (!(cmd->flags & MMC_RSP_PRESENT)) + flags = SDHCI_CMD_RESP_NONE; + else if (cmd->flags & MMC_RSP_136) + flags = SDHCI_CMD_RESP_LONG; + else if (cmd->flags & MMC_RSP_BUSY) + flags = SDHCI_CMD_RESP_SHORT_BUSY; + else + flags = SDHCI_CMD_RESP_SHORT; + + if (cmd->flags & MMC_RSP_CRC) + flags |= SDHCI_CMD_CRC; + if (cmd->flags & MMC_RSP_OPCODE) + flags |= SDHCI_CMD_INDEX; + if (cmd->data) + flags |= SDHCI_CMD_DATA; + + writel(SDHCI_MAKE_CMD(cmd->opcode, flags), + host->ioaddr + SDHCI_COMMAND); +} + +static void sdhci_finish_command(struct sdhci_host *host) +{ + int i; + + BUG_ON(host->cmd == NULL); + + if (host->cmd->flags & MMC_RSP_PRESENT) { + if (host->cmd->flags & MMC_RSP_136) { + /* CRC is stripped so we need to do some shifting. */ + for (i = 0;i < 4;i++) { + host->cmd->resp[i] = readl(host->ioaddr + + SDHCI_RESPONSE + (3-i)*4) << 8; + if (i != 3) + host->cmd->resp[i] |= + readb(host->ioaddr + + SDHCI_RESPONSE + (3-i)*4-1); + } + } else { + host->cmd->resp[0] = readl(host->ioaddr + SDHCI_RESPONSE); + } + } + + host->cmd->error = MMC_ERR_NONE; + + DBG("Ending cmd (%x)\n", host->cmd->opcode); + + if (host->cmd->data) { + u32 intmask; + + host->data = host->cmd->data; + + if (!(host->flags & SDHCI_USE_DMA)) { + /* + * Don't enable the interrupts until now to make sure we + * get stable handling of the FIFO. + */ + intmask = readl(host->ioaddr + SDHCI_INT_ENABLE); + intmask |= SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL; + writel(intmask, host->ioaddr + SDHCI_INT_ENABLE); + + intmask = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE); + intmask |= SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL; + writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE); + + /* + * The buffer interrupts are to unreliable so we + * start the transfer immediatly. + */ + sdhci_transfer_pio(host); + } + } else + tasklet_schedule(&host->finish_tasklet); + + host->cmd = NULL; +} + +static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) +{ + int div; + u16 clk; + unsigned long max_jiffies; + + if (clock == host->clock) + return; + + writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); + + if (clock == 0) + goto out; + + for (div = 1;div < 256;div *= 2) { + if ((host->max_clk / div) <= clock) + break; + } + div >>= 1; + + clk = div << SDHCI_DIVIDER_SHIFT; + clk |= SDHCI_CLOCK_INT_EN; + writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); + + /* Wait max 10 ms */ + max_jiffies = jiffies + (HZ + 99)/100; + do { + if (time_after(jiffies, max_jiffies)) { + printk(KERN_ERR "%s: Internal clock never stabilised. " + "Please report this to " BUGMAIL ".\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + return; + } + clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL); + } while (!(clk & SDHCI_CLOCK_INT_STABLE)); + + clk |= SDHCI_CLOCK_CARD_EN; + writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); + +out: + host->clock = clock; +} + +/*****************************************************************************\ + * * + * MMC callbacks * + * * +\*****************************************************************************/ + +static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct sdhci_host *host; + unsigned long flags; + + host = mmc_priv(mmc); + + spin_lock_irqsave(&host->lock, flags); + + WARN_ON(host->mrq != NULL); + + sdhci_activate_led(host); + + host->mrq = mrq; + + if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { + host->mrq->cmd->error = MMC_ERR_TIMEOUT; + tasklet_schedule(&host->finish_tasklet); + } else + sdhci_send_command(host, mrq->cmd); + + spin_unlock_irqrestore(&host->lock, flags); +} + +static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct sdhci_host *host; + unsigned long flags; + u8 ctrl; + + host = mmc_priv(mmc); + + spin_lock_irqsave(&host->lock, flags); + + DBG("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n", + ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, + ios->vdd, ios->bus_width); + + /* + * Reset the chip on each power off. + * Should clear out any weird states. + */ + if (ios->power_mode == MMC_POWER_OFF) { + writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE); + spin_unlock_irqrestore(&host->lock, flags); + sdhci_init(host); + spin_lock_irqsave(&host->lock, flags); + } + + sdhci_set_clock(host, ios->clock); + + if (ios->power_mode == MMC_POWER_OFF) + writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); + else + writeb(0xFF, host->ioaddr + SDHCI_POWER_CONTROL); + + ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); + if (ios->bus_width == MMC_BUS_WIDTH_4) + ctrl |= SDHCI_CTRL_4BITBUS; + else + ctrl &= ~SDHCI_CTRL_4BITBUS; + writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); + + spin_unlock_irqrestore(&host->lock, flags); +} + +static int sdhci_get_ro(struct mmc_host *mmc) +{ + struct sdhci_host *host; + unsigned long flags; + int present; + + host = mmc_priv(mmc); + + spin_lock_irqsave(&host->lock, flags); + + present = readl(host->ioaddr + SDHCI_PRESENT_STATE); + + spin_unlock_irqrestore(&host->lock, flags); + + return !(present & SDHCI_WRITE_PROTECT); +} + +static struct mmc_host_ops sdhci_ops = { + .request = sdhci_request, + .set_ios = sdhci_set_ios, + .get_ro = sdhci_get_ro, +}; + +/*****************************************************************************\ + * * + * Tasklets * + * * +\*****************************************************************************/ + +static void sdhci_tasklet_card(unsigned long param) +{ + struct sdhci_host *host; + unsigned long flags; + + host = (struct sdhci_host*)param; + + spin_lock_irqsave(&host->lock, flags); + + if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { + if (host->mrq) { + printk(KERN_ERR "%s: Card removed during transfer!\n", + mmc_hostname(host->mmc)); + printk(KERN_ERR "%s: Resetting controller.\n", + mmc_hostname(host->mmc)); + + sdhci_reset(host, SDHCI_RESET_CMD); + sdhci_reset(host, SDHCI_RESET_DATA); + + host->mrq->cmd->error = MMC_ERR_FAILED; + tasklet_schedule(&host->finish_tasklet); + } + } + + spin_unlock_irqrestore(&host->lock, flags); + + mmc_detect_change(host->mmc, msecs_to_jiffies(500)); +} + +static void sdhci_tasklet_finish(unsigned long param) +{ + struct sdhci_host *host; + unsigned long flags; + struct mmc_request *mrq; + + host = (struct sdhci_host*)param; + + spin_lock_irqsave(&host->lock, flags); + + del_timer(&host->timer); + + mrq = host->mrq; + + DBG("Ending request, cmd (%x)\n", mrq->cmd->opcode); + + /* + * The controller needs a reset of internal state machines + * upon error conditions. + */ + if ((mrq->cmd->error != MMC_ERR_NONE) || + (mrq->data && ((mrq->data->error != MMC_ERR_NONE) || + (mrq->data->stop && (mrq->data->stop->error != MMC_ERR_NONE))))) { + sdhci_reset(host, SDHCI_RESET_CMD); + sdhci_reset(host, SDHCI_RESET_DATA); + } + + host->mrq = NULL; + host->cmd = NULL; + host->data = NULL; + + sdhci_deactivate_led(host); + + spin_unlock_irqrestore(&host->lock, flags); + + mmc_request_done(host->mmc, mrq); +} + +static void sdhci_timeout_timer(unsigned long data) +{ + struct sdhci_host *host; + unsigned long flags; + + host = (struct sdhci_host*)data; + + spin_lock_irqsave(&host->lock, flags); + + if (host->mrq) { + printk(KERN_ERR "%s: Timeout waiting for hardware interrupt. " + "Please report this to " BUGMAIL ".\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + + if (host->data) { + host->data->error = MMC_ERR_TIMEOUT; + sdhci_finish_data(host); + } else { + if (host->cmd) + host->cmd->error = MMC_ERR_TIMEOUT; + else + host->mrq->cmd->error = MMC_ERR_TIMEOUT; + + tasklet_schedule(&host->finish_tasklet); + } + } + + spin_unlock_irqrestore(&host->lock, flags); +} + +/*****************************************************************************\ + * * + * Interrupt handling * + * * +\*****************************************************************************/ + +static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) +{ + BUG_ON(intmask == 0); + + if (!host->cmd) { + printk(KERN_ERR "%s: Got command interrupt even though no " + "command operation was in progress.\n", + mmc_hostname(host->mmc)); + printk(KERN_ERR "%s: Please report this to " BUGMAIL ".\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + return; + } + + if (intmask & SDHCI_INT_RESPONSE) + sdhci_finish_command(host); + else { + if (intmask & SDHCI_INT_TIMEOUT) + host->cmd->error = MMC_ERR_TIMEOUT; + else if (intmask & SDHCI_INT_CRC) + host->cmd->error = MMC_ERR_BADCRC; + else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) + host->cmd->error = MMC_ERR_FAILED; + else + host->cmd->error = MMC_ERR_INVALID; + + tasklet_schedule(&host->finish_tasklet); + } +} + +static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) +{ + BUG_ON(intmask == 0); + + if (!host->data) { + /* + * A data end interrupt is sent together with the response + * for the stop command. + */ + if (intmask & SDHCI_INT_DATA_END) + return; + + printk(KERN_ERR "%s: Got data interrupt even though no " + "data operation was in progress.\n", + mmc_hostname(host->mmc)); + printk(KERN_ERR "%s: Please report this to " BUGMAIL ".\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + + return; + } + + if (intmask & SDHCI_INT_DATA_TIMEOUT) + host->data->error = MMC_ERR_TIMEOUT; + else if (intmask & SDHCI_INT_DATA_CRC) + host->data->error = MMC_ERR_BADCRC; + else if (intmask & SDHCI_INT_DATA_END_BIT) + host->data->error = MMC_ERR_FAILED; + + if (host->data->error != MMC_ERR_NONE) + sdhci_finish_data(host); + else { + if (intmask & (SDHCI_INT_BUF_FULL | SDHCI_INT_BUF_EMPTY)) + sdhci_transfer_pio(host); + + if (intmask & SDHCI_INT_DATA_END) + sdhci_finish_data(host); + } +} + +static irqreturn_t sdhci_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + irqreturn_t result; + struct sdhci_host* host = dev_id; + u32 intmask; + + spin_lock(&host->lock); + + intmask = readl(host->ioaddr + SDHCI_INT_STATUS); + + if (!intmask) { + result = IRQ_NONE; + goto out; + } + + DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask); + + if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) + tasklet_schedule(&host->card_tasklet); + + if (intmask & SDHCI_INT_CMD_MASK) { + sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); + + writel(intmask & SDHCI_INT_CMD_MASK, + host->ioaddr + SDHCI_INT_STATUS); + } + + if (intmask & SDHCI_INT_DATA_MASK) { + sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); + + writel(intmask & SDHCI_INT_DATA_MASK, + host->ioaddr + SDHCI_INT_STATUS); + } + + intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); + + if (intmask & SDHCI_INT_CARD_INT) { + printk(KERN_ERR "%s: Unexpected card interrupt. Please " + "report this to " BUGMAIL ".\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + } + + if (intmask & SDHCI_INT_BUS_POWER) { + printk(KERN_ERR "%s: Unexpected bus power interrupt. Please " + "report this to " BUGMAIL ".\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + } + + if (intmask & SDHCI_INT_ACMD12ERR) { + printk(KERN_ERR "%s: Unexpected auto CMD12 error. Please " + "report this to " BUGMAIL ".\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + + writew(~0, host->ioaddr + SDHCI_ACMD12_ERR); + } + + if (intmask) + writel(intmask, host->ioaddr + SDHCI_INT_STATUS); + + result = IRQ_HANDLED; + +out: + spin_unlock(&host->lock); + + return result; +} + +/*****************************************************************************\ + * * + * Suspend/resume * + * * +\*****************************************************************************/ + +#ifdef CONFIG_PM + +static int sdhci_suspend (struct pci_dev *pdev, pm_message_t state) +{ + struct sdhci_chip *chip; + int i, ret; + + chip = pci_get_drvdata(pdev); + if (!chip) + return 0; + + DBG("Suspending...\n"); + + for (i = 0;i < chip->num_slots;i++) { + if (!chip->hosts[i]) + continue; + ret = mmc_suspend_host(chip->hosts[i]->mmc, state); + if (ret) { + for (i--;i >= 0;i--) + mmc_resume_host(chip->hosts[i]->mmc); + return ret; + } + } + + pci_save_state(pdev); + pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int sdhci_resume (struct pci_dev *pdev) +{ + struct sdhci_chip *chip; + int i, ret; + + chip = pci_get_drvdata(pdev); + if (!chip) + return 0; + + DBG("Resuming...\n"); + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_device(pdev); + + for (i = 0;i < chip->num_slots;i++) { + if (!chip->hosts[i]) + continue; + if (chip->hosts[i]->flags & SDHCI_USE_DMA) + pci_set_master(pdev); + sdhci_init(chip->hosts[i]); + ret = mmc_resume_host(chip->hosts[i]->mmc); + if (ret) + return ret; + } + + return 0; +} + +#else /* CONFIG_PM */ + +#define sdhci_suspend NULL +#define sdhci_resume NULL + +#endif /* CONFIG_PM */ + +/*****************************************************************************\ + * * + * Device probing/removal * + * * +\*****************************************************************************/ + +static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) +{ + int ret; + struct sdhci_chip *chip; + struct mmc_host *mmc; + struct sdhci_host *host; + + u8 first_bar; + unsigned int caps; + + chip = pci_get_drvdata(pdev); + BUG_ON(!chip); + + ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar); + if (ret) + return ret; + + first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK; + + if (first_bar > 5) { + printk(KERN_ERR DRIVER_NAME ": Invalid first BAR. Aborting.\n"); + return -ENODEV; + } + + if (!(pci_resource_flags(pdev, first_bar + slot) & IORESOURCE_MEM)) { + printk(KERN_ERR DRIVER_NAME ": BAR is not iomem. Aborting.\n"); + return -ENODEV; + } + + if (pci_resource_len(pdev, first_bar + slot) != 0x100) { + printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. Aborting.\n"); + return -ENODEV; + } + + mmc = mmc_alloc_host(sizeof(struct sdhci_host), &pdev->dev); + if (!mmc) + return -ENOMEM; + + host = mmc_priv(mmc); + host->mmc = mmc; + + host->bar = first_bar + slot; + + host->addr = pci_resource_start(pdev, host->bar); + host->irq = pdev->irq; + + DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq); + + snprintf(host->slot_descr, 20, "sdhci:slot%d", slot); + + ret = pci_request_region(pdev, host->bar, host->slot_descr); + if (ret) + goto free; + + host->ioaddr = ioremap_nocache(host->addr, + pci_resource_len(pdev, host->bar)); + if (!host->ioaddr) { + ret = -ENOMEM; + goto release; + } + + caps = readl(host->ioaddr + SDHCI_CAPABILITIES); + + if ((caps & SDHCI_CAN_DO_DMA) && ((pdev->class & 0x0000FF) == 0x01)) + host->flags |= SDHCI_USE_DMA; + + if (host->flags & SDHCI_USE_DMA) { + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { + printk(KERN_WARNING "%s: No suitable DMA available. " + "Falling back to PIO.\n", host->slot_descr); + host->flags &= ~SDHCI_USE_DMA; + } + } + + if (host->flags & SDHCI_USE_DMA) + pci_set_master(pdev); + else /* XXX: Hack to get MMC layer to avoid highmem */ + pdev->dma_mask = 0; + + host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; + host->max_clk *= 1000000; + + /* + * Set host parameters. + */ + mmc->ops = &sdhci_ops; + mmc->f_min = host->max_clk / 256; + mmc->f_max = host->max_clk; + mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; + mmc->caps = MMC_CAP_4_BIT_DATA; + + spin_lock_init(&host->lock); + + /* + * Maximum number of segments. Hardware cannot do scatter lists. + */ + if (host->flags & SDHCI_USE_DMA) + mmc->max_hw_segs = 1; + else + mmc->max_hw_segs = 16; + mmc->max_phys_segs = 16; + + /* + * Maximum number of sectors in one transfer. Limited by sector + * count register. + */ + mmc->max_sectors = 0x3FFF; + + /* + * Maximum segment size. Could be one segment with the maximum number + * of sectors. + */ + mmc->max_seg_size = mmc->max_sectors * 512; + + /* + * Init tasklets. + */ + tasklet_init(&host->card_tasklet, + sdhci_tasklet_card, (unsigned long)host); + tasklet_init(&host->finish_tasklet, + sdhci_tasklet_finish, (unsigned long)host); + + setup_timer(&host->timer, sdhci_timeout_timer, (int)host); + + ret = request_irq(host->irq, sdhci_irq, SA_SHIRQ, + host->slot_descr, host); + if (ret) + goto unmap; + + sdhci_init(host); + +#ifdef CONFIG_MMC_DEBUG + sdhci_dumpregs(host); +#endif + + host->chip = chip; + chip->hosts[slot] = host; + + mmc_add_host(mmc); + + printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n", mmc_hostname(mmc), + host->addr, host->irq, + (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); + + return 0; + +unmap: + tasklet_kill(&host->card_tasklet); + tasklet_kill(&host->finish_tasklet); + + iounmap(host->ioaddr); +release: + pci_release_region(pdev, host->bar); +free: + mmc_free_host(mmc); + + return ret; +} + +static void sdhci_remove_slot(struct pci_dev *pdev, int slot) +{ + struct sdhci_chip *chip; + struct mmc_host *mmc; + struct sdhci_host *host; + + chip = pci_get_drvdata(pdev); + host = chip->hosts[slot]; + mmc = host->mmc; + + chip->hosts[slot] = NULL; + + mmc_remove_host(mmc); + + sdhci_reset(host, SDHCI_RESET_ALL); + + free_irq(host->irq, host); + + del_timer_sync(&host->timer); + + tasklet_kill(&host->card_tasklet); + tasklet_kill(&host->finish_tasklet); + + iounmap(host->ioaddr); + + pci_release_region(pdev, host->bar); + + mmc_free_host(mmc); +} + +static int __devinit sdhci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int ret, i; + u8 slots; + struct sdhci_chip *chip; + + BUG_ON(pdev == NULL); + BUG_ON(ent == NULL); + + DBG("found at %s\n", pci_name(pdev)); + + ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots); + if (ret) + return ret; + + slots = PCI_SLOT_INFO_SLOTS(slots) + 1; + DBG("found %d slot(s)\n", slots); + if (slots == 0) + return -ENODEV; + + ret = pci_enable_device(pdev); + if (ret) + return ret; + + chip = kzalloc(sizeof(struct sdhci_chip) + + sizeof(struct sdhci_host*) * slots, GFP_KERNEL); + if (!chip) { + ret = -ENOMEM; + goto err; + } + + chip->pdev = pdev; + + chip->num_slots = slots; + pci_set_drvdata(pdev, chip); + + for (i = 0;i < slots;i++) { + ret = sdhci_probe_slot(pdev, i); + if (ret) { + for (i--;i >= 0;i--) + sdhci_remove_slot(pdev, i); + goto free; + } + } + + return 0; + +free: + pci_set_drvdata(pdev, NULL); + kfree(chip); + +err: + pci_disable_device(pdev); + return ret; +} + +static void __devexit sdhci_remove(struct pci_dev *pdev) +{ + int i; + struct sdhci_chip *chip; + + chip = pci_get_drvdata(pdev); + + if (chip) { + for (i = 0;i < chip->num_slots;i++) + sdhci_remove_slot(pdev, i); + + pci_set_drvdata(pdev, NULL); + + kfree(chip); + } + + pci_disable_device(pdev); +} + +static struct pci_driver sdhci_driver = { + .name = DRIVER_NAME, + .id_table = pci_ids, + .probe = sdhci_probe, + .remove = __devexit_p(sdhci_remove), + .suspend = sdhci_suspend, + .resume = sdhci_resume, +}; + +/*****************************************************************************\ + * * + * Driver init/exit * + * * +\*****************************************************************************/ + +static int __init sdhci_drv_init(void) +{ + printk(KERN_INFO DRIVER_NAME + ": Secure Digital Host Controller Interface driver, " + DRIVER_VERSION "\n"); + printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); + + return pci_register_driver(&sdhci_driver); +} + +static void __exit sdhci_drv_exit(void) +{ + DBG("Exiting\n"); + + pci_unregister_driver(&sdhci_driver); +} + +module_init(sdhci_drv_init); +module_exit(sdhci_drv_exit); + +MODULE_AUTHOR("Pierre Ossman "); +MODULE_DESCRIPTION("Secure Digital Host Controller Interface driver"); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h new file mode 100644 index 000000000000..3b270ef486b4 --- /dev/null +++ b/drivers/mmc/sdhci.h @@ -0,0 +1,185 @@ +/* + * linux/drivers/mmc/sdhci.h - Secure Digital Host Controller Interface driver + * + * Copyright (C) 2005 Pierre Ossman, 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 version 2 as + * published by the Free Software Foundation. + */ + +/* + * PCI registers + */ + +#define PCI_SLOT_INFO 0x40 /* 8 bits */ +#define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) +#define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 + +/* + * Controller registers + */ + +#define SDHCI_DMA_ADDRESS 0x00 + +#define SDHCI_BLOCK_SIZE 0x04 + +#define SDHCI_BLOCK_COUNT 0x06 + +#define SDHCI_ARGUMENT 0x08 + +#define SDHCI_TRANSFER_MODE 0x0C +#define SDHCI_TRNS_DMA 0x01 +#define SDHCI_TRNS_BLK_CNT_EN 0x02 +#define SDHCI_TRNS_ACMD12 0x04 +#define SDHCI_TRNS_READ 0x10 +#define SDHCI_TRNS_MULTI 0x20 + +#define SDHCI_COMMAND 0x0E +#define SDHCI_CMD_RESP_MASK 0x03 +#define SDHCI_CMD_CRC 0x08 +#define SDHCI_CMD_INDEX 0x10 +#define SDHCI_CMD_DATA 0x20 + +#define SDHCI_CMD_RESP_NONE 0x00 +#define SDHCI_CMD_RESP_LONG 0x01 +#define SDHCI_CMD_RESP_SHORT 0x02 +#define SDHCI_CMD_RESP_SHORT_BUSY 0x03 + +#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff)) + +#define SDHCI_RESPONSE 0x10 + +#define SDHCI_BUFFER 0x20 + +#define SDHCI_PRESENT_STATE 0x24 +#define SDHCI_CMD_INHIBIT 0x00000001 +#define SDHCI_DATA_INHIBIT 0x00000002 +#define SDHCI_DOING_WRITE 0x00000100 +#define SDHCI_DOING_READ 0x00000200 +#define SDHCI_SPACE_AVAILABLE 0x00000400 +#define SDHCI_DATA_AVAILABLE 0x00000800 +#define SDHCI_CARD_PRESENT 0x00010000 +#define SDHCI_WRITE_PROTECT 0x00080000 + +#define SDHCI_HOST_CONTROL 0x28 +#define SDHCI_CTRL_LED 0x01 +#define SDHCI_CTRL_4BITBUS 0x02 + +#define SDHCI_POWER_CONTROL 0x29 + +#define SDHCI_BLOCK_GAP_CONTROL 0x2A + +#define SDHCI_WALK_UP_CONTROL 0x2B + +#define SDHCI_CLOCK_CONTROL 0x2C +#define SDHCI_DIVIDER_SHIFT 8 +#define SDHCI_CLOCK_CARD_EN 0x0004 +#define SDHCI_CLOCK_INT_STABLE 0x0002 +#define SDHCI_CLOCK_INT_EN 0x0001 + +#define SDHCI_TIMEOUT_CONTROL 0x2E + +#define SDHCI_SOFTWARE_RESET 0x2F +#define SDHCI_RESET_ALL 0x01 +#define SDHCI_RESET_CMD 0x02 +#define SDHCI_RESET_DATA 0x04 + +#define SDHCI_INT_STATUS 0x30 +#define SDHCI_INT_ENABLE 0x34 +#define SDHCI_SIGNAL_ENABLE 0x38 +#define SDHCI_INT_RESPONSE 0x00000001 +#define SDHCI_INT_DATA_END 0x00000002 +#define SDHCI_INT_DMA_END 0x00000008 +#define SDHCI_INT_BUF_EMPTY 0x00000010 +#define SDHCI_INT_BUF_FULL 0x00000020 +#define SDHCI_INT_CARD_INSERT 0x00000040 +#define SDHCI_INT_CARD_REMOVE 0x00000080 +#define SDHCI_INT_CARD_INT 0x00000100 +#define SDHCI_INT_TIMEOUT 0x00010000 +#define SDHCI_INT_CRC 0x00020000 +#define SDHCI_INT_END_BIT 0x00040000 +#define SDHCI_INT_INDEX 0x00080000 +#define SDHCI_INT_DATA_TIMEOUT 0x00100000 +#define SDHCI_INT_DATA_CRC 0x00200000 +#define SDHCI_INT_DATA_END_BIT 0x00400000 +#define SDHCI_INT_BUS_POWER 0x00800000 +#define SDHCI_INT_ACMD12ERR 0x01000000 + +#define SDHCI_INT_NORMAL_MASK 0x00007FFF +#define SDHCI_INT_ERROR_MASK 0xFFFF8000 + +#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \ + SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX) +#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ + SDHCI_INT_BUF_EMPTY | SDHCI_INT_BUF_FULL | \ + SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ + SDHCI_INT_DATA_END_BIT) + +#define SDHCI_ACMD12_ERR 0x3C + +/* 3E-3F reserved */ + +#define SDHCI_CAPABILITIES 0x40 +#define SDHCI_CAN_DO_DMA 0x00400000 +#define SDHCI_CLOCK_BASE_MASK 0x00003F00 +#define SDHCI_CLOCK_BASE_SHIFT 8 + +/* 44-47 reserved for more caps */ + +#define SDHCI_MAX_CURRENT 0x48 + +/* 4C-4F reserved for more max current */ + +/* 50-FB reserved */ + +#define SDHCI_SLOT_INT_STATUS 0xFC + +#define SDHCI_HOST_VERSION 0xFE + +struct sdhci_chip; + +struct sdhci_host { + struct sdhci_chip *chip; + struct mmc_host *mmc; /* MMC structure */ + + spinlock_t lock; /* Mutex */ + + int flags; /* Host attributes */ +#define SDHCI_USE_DMA (1<<0) + + unsigned int max_clk; /* Max possible freq (MHz) */ + + unsigned int clock; /* Current clock (MHz) */ + + struct mmc_request *mrq; /* Current request */ + struct mmc_command *cmd; /* Current command */ + struct mmc_data *data; /* Current data request */ + + struct scatterlist *cur_sg; /* We're working on this */ + char *mapped_sg; /* This is where it's mapped */ + int num_sg; /* Entries left */ + int offset; /* Offset into current sg */ + int remain; /* Bytes left in current */ + + int size; /* Remaining bytes in transfer */ + + char slot_descr[20]; /* Name for reservations */ + + int irq; /* Device IRQ */ + int bar; /* PCI BAR index */ + unsigned long addr; /* Bus address */ + void __iomem * ioaddr; /* Mapped address */ + + struct tasklet_struct card_tasklet; /* Tasklet structures */ + struct tasklet_struct finish_tasklet; + + struct timer_list timer; /* Timer for timeouts */ +}; + +struct sdhci_chip { + struct pci_dev *pdev; + + int num_slots; /* Slots on controller */ + struct sdhci_host *hosts[0]; /* Pointers to hosts */ +}; -- cgit v1.2.3-59-g8ed1b From f751d50f6dea1446797c9a31f5c183002e5780a8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 24 Mar 2006 03:18:21 -0800 Subject: [PATCH] show MCP menu only on ARCH_SA1100 On architectures like i386, the "Multimedia Capabilities Port drivers" menu is visible, but it can't be visited since it contains nothing usable for !ARCH_SA1100. This patch therefore shows this menu only on ARCH_SA1100. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mfd/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 550f29744812..fc3c8854f430 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -3,6 +3,7 @@ # menu "Multimedia Capabilities Port drivers" + depends on ARCH_SA1100 config MCP tristate -- cgit v1.2.3-59-g8ed1b From 208a08f7cc2a8932ed76162d9844f9ae7d7fc015 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 24 Mar 2006 03:18:21 -0800 Subject: [PATCH] ide: Allow IDE interface to specify its not capable of 32-bit operations In some embedded systems the IDE hardware interface may only support 16-bit or smaller accesses. Allow the interface to specify if this is the case and don't allow the drive or user to override the setting. Signed-off-by: Kumar Gala Acked-by: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-disk.c | 2 -- drivers/ide/ide-probe.c | 9 +++++++++ include/linux/ide.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index e238b7da824b..ccf528d733bf 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -978,8 +978,6 @@ static void idedisk_setup (ide_drive_t *drive) ide_dma_verbose(drive); printk("\n"); - drive->no_io_32bit = id->dword_io ? 1 : 0; - /* write cache enabled? */ if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5))) drive->wcache = 1; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 427d1c204174..1b7b4c531bc2 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -858,6 +858,15 @@ static void probe_hwif(ide_hwif_t *hwif) } } } + + for (unit = 0; unit < MAX_DRIVES; ++unit) { + ide_drive_t *drive = &hwif->drives[unit]; + + if (hwif->no_io_32bit) + drive->no_io_32bit = 1; + else + drive->no_io_32bit = drive->id->dword_io ? 1 : 0; + } } static int hwif_init(ide_hwif_t *hwif); diff --git a/include/linux/ide.h b/include/linux/ide.h index a7fc4cc79b23..8d2db412ba9c 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -792,6 +792,7 @@ typedef struct hwif_s { unsigned no_dsc : 1; /* 0 default, 1 dsc_overlap disabled */ unsigned auto_poll : 1; /* supports nop auto-poll */ unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */ + unsigned no_io_32bit : 1; /* 1 = can not do 32-bit IO ops */ struct device gendev; struct completion gendev_rel_comp; /* To deal with device release() */ -- cgit v1.2.3-59-g8ed1b From 10e705f83c3e796893a70fb872895ba604901166 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 24 Mar 2006 03:18:23 -0800 Subject: [PATCH] Fix "value computed not used" warnings Fixes for annoying gcc-4.1 compile warnings "value computed not used". Simply cast to void. (akpm: Linus will go ballistic...) Signed-off-by: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/paride/comm.c | 16 ++++++++-------- drivers/block/paride/on26.c | 2 +- drivers/net/8139too.c | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/block/paride/comm.c b/drivers/block/paride/comm.c index d842956edf76..43d61359d8ec 100644 --- a/drivers/block/paride/comm.c +++ b/drivers/block/paride/comm.c @@ -60,7 +60,7 @@ static int comm_read_regr( PIA *pi, int cont, int regr ) case 2: case 3: - case 4: w3(r+0x20); r1(); + case 4: w3(r+0x20); (void)r1(); w2(0x24); h = r4(); w2(4); return h; @@ -82,7 +82,7 @@ static void comm_write_regr( PIA *pi, int cont, int regr, int val ) case 2: case 3: - case 4: w3(r); r1(); w4(val); + case 4: w3(r); (void)r1(); w4(val); break; } } @@ -126,17 +126,17 @@ static void comm_read_block( PIA *pi, char * buf, int count ) w2(4); break; - case 2: w3(0x68); r1(); w2(0x24); + case 2: w3(0x68); (void)r1(); w2(0x24); for (i=0;i Date: Fri, 24 Mar 2006 03:18:24 -0800 Subject: [PATCH] rio: more header cleanup Strip some of the typedef mess out Remove a small subset of unused defines and the like. Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/rio/board.h | 58 +++++------ drivers/char/rio/cmdpkt.h | 46 ++++---- drivers/char/rio/link.h | 106 +++++-------------- drivers/char/rio/parmmap.h | 54 +++++----- drivers/char/rio/phb.h | 37 +++---- drivers/char/rio/pkt.h | 24 ++--- drivers/char/rio/port.h | 248 +++++++++++++++++--------------------------- drivers/char/rio/riotypes.h | 34 +++--- drivers/char/rio/rup.h | 21 ++-- drivers/char/rio/typdef.h | 15 +-- 10 files changed, 243 insertions(+), 400 deletions(-) (limited to 'drivers') diff --git a/drivers/char/rio/board.h b/drivers/char/rio/board.h index 29c980204098..bdea633a9076 100644 --- a/drivers/char/rio/board.h +++ b/drivers/char/rio/board.h @@ -33,10 +33,6 @@ #ifndef __rio_board_h__ #define __rio_board_h__ -#ifdef SCCS_LABELS -static char *_board_h_sccs_ = "@(#)board.h 1.2"; -#endif - /* ** board.h contains the definitions for the *hardware* of the host cards. ** It describes the memory overlay for the dual port RAM area. @@ -53,29 +49,29 @@ static char *_board_h_sccs_ = "@(#)board.h 1.2"; ** The shape of the Host Control area, at offset 0x7C00, Write Only */ struct s_Ctrl { - BYTE DpCtl; /* 7C00 */ - BYTE Dp_Unused2_[127]; - BYTE DpIntSet; /* 7C80 */ - BYTE Dp_Unused3_[127]; - BYTE DpTpuReset; /* 7D00 */ - BYTE Dp_Unused4_[127]; - BYTE DpIntReset; /* 7D80 */ - BYTE Dp_Unused5_[127]; + u8 DpCtl; /* 7C00 */ + u8 Dp_Unused2_[127]; + u8 DpIntSet; /* 7C80 */ + u8 Dp_Unused3_[127]; + u8 DpTpuReset; /* 7D00 */ + u8 Dp_Unused4_[127]; + u8 DpIntReset; /* 7D80 */ + u8 Dp_Unused5_[127]; }; /* ** The PROM data area on the host (0x7C00), Read Only */ struct s_Prom { - WORD DpSlxCode[2]; - WORD DpRev; - WORD Dp_Unused6_; - WORD DpUniq[4]; - WORD DpJahre; - WORD DpWoche; - WORD DpHwFeature[5]; - WORD DpOemId; - WORD DpSiggy[16]; + u16 DpSlxCode[2]; + u16 DpRev; + u16 Dp_Unused6_; + u16 DpUniq[4]; + u16 DpJahre; + u16 DpWoche; + u16 DpHwFeature[5]; + u16 DpOemId; + u16 DpSiggy[16]; }; /* @@ -90,19 +86,19 @@ union u_CtrlProm { /* This is the control/PROM area (0x7C00) */ ** The top end of memory! */ struct s_ParmMapS { /* Area containing Parm Map Pointer */ - BYTE Dp_Unused8_[DP_PARMMAP_ADDR]; - WORD DpParmMapAd; + u8 Dp_Unused8_[DP_PARMMAP_ADDR]; + u16 DpParmMapAd; }; struct s_StartUpS { - BYTE Dp_Unused9_[DP_STARTUP_ADDR]; - BYTE Dp_LongJump[0x4]; - BYTE Dp_Unused10_[2]; - BYTE Dp_ShortJump[0x2]; + u8 Dp_Unused9_[DP_STARTUP_ADDR]; + u8 Dp_LongJump[0x4]; + u8 Dp_Unused10_[2]; + u8 Dp_ShortJump[0x2]; }; union u_Sram2ParmMap { /* This is the top of memory (0x7E00-0x7FFF) */ - BYTE DpSramMem[DP_SRAM2_SIZE]; + u8 DpSramMem[DP_SRAM2_SIZE]; struct s_ParmMapS DpParmMapS; struct s_StartUpS DpStartUpS; }; @@ -111,11 +107,11 @@ union u_Sram2ParmMap { /* This is the top of memory (0x7E00-0x7FFF) */ ** This is the DP RAM overlay. */ struct DpRam { - BYTE DpSram1[DP_SRAM1_SIZE]; /* 0000 - 7BFF */ + u8 DpSram1[DP_SRAM1_SIZE]; /* 0000 - 7BFF */ union u_CtrlProm DpCtrlProm; /* 7C00 - 7DFF */ union u_Sram2ParmMap DpSram2ParmMap; /* 7E00 - 7FFF */ - BYTE DpScratch[DP_SCRATCH_SIZE]; /* 8000 - 8FFF */ - BYTE DpSram3[DP_SRAM3_SIZE]; /* 9000 - FFFF */ + u8 DpScratch[DP_SCRATCH_SIZE]; /* 8000 - 8FFF */ + u8 DpSram3[DP_SRAM3_SIZE]; /* 9000 - FFFF */ }; #define DpControl DpCtrlProm.DpCtrl.DpCtl diff --git a/drivers/char/rio/cmdpkt.h b/drivers/char/rio/cmdpkt.h index 77cee8df68ef..b6445d3f1416 100644 --- a/drivers/char/rio/cmdpkt.h +++ b/drivers/char/rio/cmdpkt.h @@ -55,24 +55,24 @@ static char *_cmdpkt_h_sccs_ = "@(#)cmdpkt.h 1.2"; ** at Data[2] in the actual pkt! */ struct BootSequence { - WORD NumPackets; - WORD LoadBase; - WORD CodeSize; + u16 NumPackets; + u16 LoadBase; + u16 CodeSize; }; #define BOOT_SEQUENCE_LEN 8 struct SamTop { - BYTE Unit; - BYTE Link; + u8 Unit; + u8 Link; }; struct CmdHdr { - BYTE PcCommand; + u8 PcCommand; union { - BYTE PcPhbNum; - BYTE PcLinkNum; - BYTE PcIDNum; + u8 PcPhbNum; + u8 PcLinkNum; + u8 PcIDNum; } U0; }; @@ -84,28 +84,28 @@ struct PktCmd { struct BootSequence PcBootSequence; } S1; struct { - WORD PcSequence; - BYTE PcBootData[RTA_BOOT_DATA_SIZE]; + u16 PcSequence; + u8 PcBootData[RTA_BOOT_DATA_SIZE]; } S2; struct { - WORD __crud__; - BYTE PcUniqNum[4]; /* this is really a uint. */ - BYTE PcModuleTypes; /* what modules are fitted */ + u16 __crud__; + u8 PcUniqNum[4]; /* this is really a uint. */ + u8 PcModuleTypes; /* what modules are fitted */ } S3; struct { struct CmdHdr CmdHdr; - BYTE __undefined__; - BYTE PcModemStatus; - BYTE PcPortStatus; - BYTE PcSubCommand; /* commands like mem or register dump */ - WORD PcSubAddr; /* Address for command */ - BYTE PcSubData[64]; /* Date area for command */ + u8 __undefined__; + u8 PcModemStatus; + u8 PcPortStatus; + u8 PcSubCommand; /* commands like mem or register dump */ + u16 PcSubAddr; /* Address for command */ + u8 PcSubData[64]; /* Date area for command */ } S4; struct { struct CmdHdr CmdHdr; - BYTE PcCommandText[1]; - BYTE __crud__[20]; - BYTE PcIDNum2; /* It had to go somewhere! */ + u8 PcCommandText[1]; + u8 __crud__[20]; + u8 PcIDNum2; /* It had to go somewhere! */ } S5; struct { struct CmdHdr CmdHdr; diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h index 48d68ca7f825..6a64b5a5b3d0 100644 --- a/drivers/char/rio/link.h +++ b/drivers/char/rio/link.h @@ -37,38 +37,9 @@ #ifndef _link_h #define _link_h 1 -#ifndef lint -#ifdef SCCS_LABELS -/* static char *_rio_link_h_sccs = "@(#)link.h 1.15"; */ -#endif -#endif - - - /************************************************* * Define the Link Status stuff ************************************************/ -#define LRT_ACTIVE ((ushort) 0x01) -#define LRT_SPARE1 ((ushort) 0x02) -#define INTRO_RCVD ((ushort) 0x04) -#define FORCED_DISCONNECT ((ushort) 0x08) -#define LRT_SPARE2 ((ushort) 0x80) - -#define TOP_OF_RTA_RAM ((ushort) 0x7000) -#define HOST_SERIAL_POINTER (unsigned char **) (TOP_OF_RTA_RAM - 2 * sizeof (ushort)) - -/* Flags for ltt_status */ -#define WAITING_ACK (ushort) 0x0001 -#define DATA_SENT (ushort) 0x0002 -#define WAITING_RUP (ushort) 0x0004 -#define WAITING_RETRY (ushort) 0x0008 -#define WAITING_TOPOLOGY (ushort) 0x0010 -#define SEND_SYNC (ushort) 0x0020 -#define FOAD_THIS_LINK (ushort) 0x0040 -#define REQUEST_SYNC (ushort) 0x0080 -#define REMOTE_DYING (ushort) 0x0100 -#define DIE_NOW (ushort) 0x0200 - /* Boot request stuff */ #define BOOT_REQUEST ((ushort) 0) /* Request for a boot */ #define BOOT_ABORT ((ushort) 1) /* Abort a boot */ @@ -76,56 +47,27 @@ and load address */ #define BOOT_COMPLETED ((ushort) 3) /* Boot completed */ -/* States that a link can be in */ -#define LINK_DISCONNECTED ((ushort) 0) /* Disconnected */ -#define LINK_BOOT1 ((ushort) 1) /* Trying to send 1st stage boot */ -#define LINK_BOOT2 ((ushort) 2) /* Trying to send 2nd stage boot */ -#define LINK_BOOT2WAIT ((ushort) 3) /* Waiting for selftest results */ -#define LINK_BOOT3 ((ushort) 4) /* Trying to send 3rd stage boots */ -#define LINK_SYNC ((ushort) 5) /* Syncing */ - -#define LINK_INTRO ((ushort) 10) /* Introductory packet */ -#define LINK_SUPPLYID ((ushort) 11) /* Trying to supply an ID */ -#define LINK_TOPOLOGY ((ushort) 12) /* Send a topology update */ -#define LINK_REQUESTID ((ushort) 13) /* Waiting for an ID */ -#define LINK_CONNECTED ((ushort) 14) /* Connected */ - -#define LINK_INTERCONNECT ((ushort) 20) /* Subnets interconnected */ - -#define LINK_SPARE ((ushort) 40) - -/* -** Set the default timeout for link communications. -*/ -#define LINKTIMEOUT (400 * MILLISECOND) - -/* -** LED stuff -*/ -#define LED_SET_COLOUR(colour) -#define LED_OR_COLOUR(colour) -#define LED_TIMEOUT(time) struct LPB { - WORD link_number; /* Link Number */ + u16 link_number; /* Link Number */ Channel_ptr in_ch; /* Link In Channel */ Channel_ptr out_ch; /* Link Out Channel */ - BYTE attached_serial[4]; /* Attached serial number */ - BYTE attached_host_serial[4]; + u8 attached_serial[4]; /* Attached serial number */ + u8 attached_host_serial[4]; /* Serial number of Host who booted the other end */ - WORD descheduled; /* Currently Descheduled */ - WORD state; /* Current state */ - WORD send_poll; /* Send a Poll Packet */ + u16 descheduled; /* Currently Descheduled */ + u16 state; /* Current state */ + u16 send_poll; /* Send a Poll Packet */ Process_ptr ltt_p; /* Process Descriptor */ Process_ptr lrt_p; /* Process Descriptor */ - WORD lrt_status; /* Current lrt status */ - WORD ltt_status; /* Current ltt status */ - WORD timeout; /* Timeout value */ - WORD topology; /* Topology bits */ - WORD mon_ltt; - WORD mon_lrt; - WORD WaitNoBoot; /* Secs to hold off booting */ + u16 lrt_status; /* Current lrt status */ + u16 ltt_status; /* Current ltt status */ + u16 timeout; /* Timeout value */ + u16 topology; /* Topology bits */ + u16 mon_ltt; + u16 mon_lrt; + u16 WaitNoBoot; /* Secs to hold off booting */ PKT_ptr add_packet_list; /* Add packets to here */ PKT_ptr remove_packet_list; /* Send packets from here */ @@ -136,17 +78,17 @@ struct LPB { struct RUP rup; struct RUP link_rup; /* RUP for the link (POLL, topology etc.) */ - WORD attached_link; /* Number of attached link */ - WORD csum_errors; /* csum errors */ - WORD num_disconnects; /* number of disconnects */ - WORD num_sync_rcvd; /* # sync's received */ - WORD num_sync_rqst; /* # sync requests */ - WORD num_tx; /* Num pkts sent */ - WORD num_rx; /* Num pkts received */ - WORD module_attached; /* Module tpyes of attached */ - WORD led_timeout; /* LED timeout */ - WORD first_port; /* First port to service */ - WORD last_port; /* Last port to service */ + u16 attached_link; /* Number of attached link */ + u16 csum_errors; /* csum errors */ + u16 num_disconnects; /* number of disconnects */ + u16 num_sync_rcvd; /* # sync's received */ + u16 num_sync_rqst; /* # sync requests */ + u16 num_tx; /* Num pkts sent */ + u16 num_rx; /* Num pkts received */ + u16 module_attached; /* Module tpyes of attached */ + u16 led_timeout; /* LED timeout */ + u16 first_port; /* First port to service */ + u16 last_port; /* Last port to service */ }; #endif diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h index e24acc1d1844..c4085fbf9ec6 100644 --- a/drivers/char/rio/parmmap.h +++ b/drivers/char/rio/parmmap.h @@ -48,39 +48,39 @@ typedef struct PARM_MAP PARM_MAP; struct PARM_MAP { PHB_ptr phb_ptr; /* Pointer to the PHB array */ - WORD_ptr phb_num_ptr; /* Ptr to Number of PHB's */ + u16 phb_num_ptr; /* Ptr to Number of PHB's */ FREE_LIST_ptr free_list; /* Free List pointer */ FREE_LIST_ptr free_list_end; /* Free List End pointer */ Q_BUF_ptr_ptr q_free_list_ptr; /* Ptr to Q_BUF variable */ - BYTE_ptr unit_id_ptr; /* Unit Id */ + u16 unit_id_ptr; /* Unit Id */ LPB_ptr link_str_ptr; /* Link Structure Array */ - BYTE_ptr bootloader_1; /* 1st Stage Boot Loader */ - BYTE_ptr bootloader_2; /* 2nd Stage Boot Loader */ - WORD_ptr port_route_map_ptr; /* Port Route Map */ + u16 bootloader_1; /* 1st Stage Boot Loader */ + u16 bootloader_2; /* 2nd Stage Boot Loader */ + u16 port_route_map_ptr; /* Port Route Map */ ROUTE_STR_ptr route_ptr; /* Unit Route Map */ - NUMBER_ptr map_present; /* Route Map present */ - NUMBER pkt_num; /* Total number of packets */ - NUMBER q_num; /* Total number of Q packets */ - WORD buffers_per_port; /* Number of buffers per port */ - WORD heap_size; /* Initial size of heap */ - WORD heap_left; /* Current Heap left */ - WORD error; /* Error code */ - WORD tx_max; /* Max number of tx pkts per phb */ - WORD rx_max; /* Max number of rx pkts per phb */ - WORD rx_limit; /* For high / low watermarks */ - NUMBER links; /* Links to use */ - NUMBER timer; /* Interrupts per second */ + u16 map_present; /* Route Map present */ + s16 pkt_num; /* Total number of packets */ + s16 q_num; /* Total number of Q packets */ + u16 buffers_per_port; /* Number of buffers per port */ + u16 heap_size; /* Initial size of heap */ + u16 heap_left; /* Current Heap left */ + u16 error; /* Error code */ + u16 tx_max; /* Max number of tx pkts per phb */ + u16 rx_max; /* Max number of rx pkts per phb */ + u16 rx_limit; /* For high / low watermarks */ + s16 links; /* Links to use */ + s16 timer; /* Interrupts per second */ RUP_ptr rups; /* Pointer to the RUPs */ - WORD max_phb; /* Mostly for debugging */ - WORD living; /* Just increments!! */ - WORD init_done; /* Initialisation over */ - WORD booting_link; - WORD idle_count; /* Idle time counter */ - WORD busy_count; /* Busy counter */ - WORD idle_control; /* Control Idle Process */ - WORD tx_intr; /* TX interrupt pending */ - WORD rx_intr; /* RX interrupt pending */ - WORD rup_intr; /* RUP interrupt pending */ + u16 max_phb; /* Mostly for debugging */ + u16 living; /* Just increments!! */ + u16 init_done; /* Initialisation over */ + u16 booting_link; + u16 idle_count; /* Idle time counter */ + u16 busy_count; /* Busy counter */ + u16 idle_control; /* Control Idle Process */ + u16 tx_intr; /* TX interrupt pending */ + u16 rx_intr; /* RX interrupt pending */ + u16 rup_intr; /* RUP interrupt pending */ }; #endif diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h index 2663ca0306e2..05d59f4b9fb0 100644 --- a/drivers/char/rio/phb.h +++ b/drivers/char/rio/phb.h @@ -37,13 +37,6 @@ #ifndef _phb_h #define _phb_h 1 -#ifdef SCCS_LABELS -#ifndef lint -/* static char *_rio_phb_h_sccs = "@(#)phb.h 1.12"; */ -#endif -#endif - - /************************************************* * Handshake asserted. Deasserted by the LTT(s) ************************************************/ @@ -126,21 +119,21 @@ *************************************************************************/ typedef struct PHB PHB; struct PHB { - WORD source; - WORD handshake; - WORD status; - NUMBER timeout; /* Maximum of 1.9 seconds */ - WORD link; /* Send down this link */ - WORD destination; - PKT_ptr_ptr tx_start; - PKT_ptr_ptr tx_end; - PKT_ptr_ptr tx_add; - PKT_ptr_ptr tx_remove; - - PKT_ptr_ptr rx_start; - PKT_ptr_ptr rx_end; - PKT_ptr_ptr rx_add; - PKT_ptr_ptr rx_remove; + u8 source; + u8 handshake; + u8 status; + u16 timeout; /* Maximum of 1.9 seconds */ + u8 link; /* Send down this link */ + u8 destination; + u16 tx_start; + u16 tx_end; + u16 tx_add; + u16 tx_remove; + + u16 rx_start; + u16 rx_end; + u16 rx_add; + u16 rx_remove; }; diff --git a/drivers/char/rio/pkt.h b/drivers/char/rio/pkt.h index 7011e52e82db..a9458164f02f 100644 --- a/drivers/char/rio/pkt.h +++ b/drivers/char/rio/pkt.h @@ -37,14 +37,6 @@ #ifndef _pkt_h #define _pkt_h 1 - -#ifdef SCCS_LABELS -#ifndef lint -/* static char *_rio_pkt_h_sccs = "@(#)pkt.h 1.8"; */ -#endif -#endif - -#define MAX_TTL 0xf #define PKT_CMD_BIT ((ushort) 0x080) #define PKT_CMD_DATA ((ushort) 0x080) @@ -70,15 +62,15 @@ #define CONTROL_DATA_WNDW (DATA_WNDW << 8) struct PKT { - BYTE dest_unit; /* Destination Unit Id */ - BYTE dest_port; /* Destination POrt */ - BYTE src_unit; /* Source Unit Id */ - BYTE src_port; /* Source POrt */ - BYTE len; - BYTE control; - BYTE data[PKT_MAX_DATA_LEN]; + u8 dest_unit; /* Destination Unit Id */ + u8 dest_port; /* Destination POrt */ + u8 src_unit; /* Source Unit Id */ + u8 src_port; /* Source POrt */ + u8 len; + u8 control; + u8 data[PKT_MAX_DATA_LEN]; /* Actual data :-) */ - WORD csum; /* C-SUM */ + u16 csum; /* C-SUM */ }; #endif diff --git a/drivers/char/rio/port.h b/drivers/char/rio/port.h index c99b1e70fdc8..4f1108fe9b1a 100644 --- a/drivers/char/rio/port.h +++ b/drivers/char/rio/port.h @@ -33,91 +33,37 @@ #ifndef __rio_port_h__ #define __rio_port_h__ -#ifdef SCCS_LABELS -static char *_port_h_sccs_ = "@(#)port.h 1.3"; -#endif - - -#undef VPIX - - -/* -** the port data structure - one per port in the system -*/ - -#ifdef STATS -struct RIOStats { - /* - ** interrupt statistics - */ - uint BreakIntCnt; - uint ModemOffCnt; - uint ModemOnCnt; - uint RxIntCnt; - uint TxIntCnt; - /* - ** throughput statistics - */ - uint RxCharCnt; - uint RxPktCnt; - uint RxSaveCnt; - uint TxCharCnt; - uint TxPktCnt; - /* - ** driver entry statistics - */ - uint CloseCnt; - uint IoctlCnt; - uint OpenCnt; - uint ReadCnt; - uint WriteCnt; - /* - ** proc statistics - */ - uint BlockCnt; - uint OutputCnt; - uint ResumeCnt; - uint RflushCnt; - uint SuspendCnt; - uint TbreakCnt; - uint TimeoutCnt; - uint UnblockCnt; - uint WflushCnt; - uint WFBodgeCnt; -}; -#endif - /* ** Port data structure */ struct Port { struct gs_port gs; - int PortNum; /* RIO port no., 0-511 */ + int PortNum; /* RIO port no., 0-511 */ struct Host *HostP; volatile caddr_t Caddr; - ushort HostPort; /* Port number on host card */ - uchar RupNum; /* Number of RUP for port */ - uchar ID2; /* Second ID of RTA for port */ - ulong State; /* FLAGS for open & xopen */ -#define RIO_LOPEN 0x00001 /* Local open */ -#define RIO_MOPEN 0x00002 /* Modem open */ -#define RIO_WOPEN 0x00004 /* Waiting for open */ -#define RIO_CLOSING 0x00008 /* The port is being close */ -#define RIO_XPBUSY 0x00010 /* Transparent printer busy */ -#define RIO_BREAKING 0x00020 /* Break in progress */ -#define RIO_DIRECT 0x00040 /* Doing Direct output */ -#define RIO_EXCLUSIVE 0x00080 /* Stream open for exclusive use */ -#define RIO_NDELAY 0x00100 /* Stream is open FNDELAY */ -#define RIO_CARR_ON 0x00200 /* Stream has carrier present */ -#define RIO_XPWANTR 0x00400 /* Stream wanted by Xprint */ -#define RIO_RBLK 0x00800 /* Stream is read-blocked */ -#define RIO_BUSY 0x01000 /* Stream is BUSY for write */ -#define RIO_TIMEOUT 0x02000 /* Stream timeout in progress */ -#define RIO_TXSTOP 0x04000 /* Stream output is stopped */ -#define RIO_WAITFLUSH 0x08000 /* Stream waiting for flush */ -#define RIO_DYNOROD 0x10000 /* Drain failed */ -#define RIO_DELETED 0x20000 /* RTA has been deleted */ -#define RIO_ISSCANCODE 0x40000 /* This line is in scancode mode */ + unsigned short HostPort; /* Port number on host card */ + unsigned char RupNum; /* Number of RUP for port */ + unsigned char ID2; /* Second ID of RTA for port */ + unsigned long State; /* FLAGS for open & xopen */ +#define RIO_LOPEN 0x00001 /* Local open */ +#define RIO_MOPEN 0x00002 /* Modem open */ +#define RIO_WOPEN 0x00004 /* Waiting for open */ +#define RIO_CLOSING 0x00008 /* The port is being close */ +#define RIO_XPBUSY 0x00010 /* Transparent printer busy */ +#define RIO_BREAKING 0x00020 /* Break in progress */ +#define RIO_DIRECT 0x00040 /* Doing Direct output */ +#define RIO_EXCLUSIVE 0x00080 /* Stream open for exclusive use */ +#define RIO_NDELAY 0x00100 /* Stream is open FNDELAY */ +#define RIO_CARR_ON 0x00200 /* Stream has carrier present */ +#define RIO_XPWANTR 0x00400 /* Stream wanted by Xprint */ +#define RIO_RBLK 0x00800 /* Stream is read-blocked */ +#define RIO_BUSY 0x01000 /* Stream is BUSY for write */ +#define RIO_TIMEOUT 0x02000 /* Stream timeout in progress */ +#define RIO_TXSTOP 0x04000 /* Stream output is stopped */ +#define RIO_WAITFLUSH 0x08000 /* Stream waiting for flush */ +#define RIO_DYNOROD 0x10000 /* Drain failed */ +#define RIO_DELETED 0x20000 /* RTA has been deleted */ +#define RIO_ISSCANCODE 0x40000 /* This line is in scancode mode */ #define RIO_USING_EUC 0x100000 /* Using extended Unix chars */ #define RIO_CAN_COOK 0x200000 /* This line can do cooking */ #define RIO_TRIAD_MODE 0x400000 /* Enable TRIAD special ops. */ @@ -125,15 +71,15 @@ struct Port { #define RIO_TRIAD_FUNC 0x1000000 /* Seen a function key coming in */ #define RIO_THROTTLE_RX 0x2000000 /* RX needs to be throttled. */ - ulong Config; /* FLAGS for NOREAD.... */ -#define RIO_NOREAD 0x0001 /* Are not allowed to read port */ -#define RIO_NOWRITE 0x0002 /* Are not allowed to write port */ -#define RIO_NOXPRINT 0x0004 /* Are not allowed to xprint port */ -#define RIO_NOMASK 0x0007 /* All not allowed things */ -#define RIO_IXANY 0x0008 /* Port is allowed ixany */ -#define RIO_MODEM 0x0010 /* Stream is a modem device */ -#define RIO_IXON 0x0020 /* Port is allowed ixon */ -#define RIO_WAITDRAIN 0x0040 /* Wait for port to completely drain */ + unsigned long Config; /* FLAGS for NOREAD.... */ +#define RIO_NOREAD 0x0001 /* Are not allowed to read port */ +#define RIO_NOWRITE 0x0002 /* Are not allowed to write port */ +#define RIO_NOXPRINT 0x0004 /* Are not allowed to xprint port */ +#define RIO_NOMASK 0x0007 /* All not allowed things */ +#define RIO_IXANY 0x0008 /* Port is allowed ixany */ +#define RIO_MODEM 0x0010 /* Stream is a modem device */ +#define RIO_IXON 0x0020 /* Port is allowed ixon */ +#define RIO_WAITDRAIN 0x0040 /* Wait for port to completely drain */ #define RIO_MAP_50_TO_50 0x0080 /* Map 50 baud to 50 baud */ #define RIO_MAP_110_TO_110 0x0100 /* Map 110 baud to 110 baud */ @@ -142,36 +88,36 @@ struct Port { ** As LynxOS does not appear to support Hardware Flow Control ..... ** Define our own flow control flags in 'Config'. */ -#define RIO_CTSFLOW 0x0200 /* RIO's own CTSFLOW flag */ -#define RIO_RTSFLOW 0x0400 /* RIO's own RTSFLOW flag */ +#define RIO_CTSFLOW 0x0200 /* RIO's own CTSFLOW flag */ +#define RIO_RTSFLOW 0x0400 /* RIO's own RTSFLOW flag */ - struct PHB *PhbP; /* pointer to PHB for port */ - WORD *TxAdd; /* Add packets here */ - WORD *TxStart; /* Start of add array */ - WORD *TxEnd; /* End of add array */ - WORD *RxRemove; /* Remove packets here */ - WORD *RxStart; /* Start of remove array */ - WORD *RxEnd; /* End of remove array */ - uint RtaUniqueNum; /* Unique number of RTA */ - ushort PortState; /* status of port */ - ushort ModemState; /* status of modem lines */ - ulong ModemLines; /* Modem bits sent to RTA */ - uchar CookMode; /* who expands CR/LF? */ - uchar ParamSem; /* Prevent write during param */ - uchar Mapped; /* if port mapped onto host */ - uchar SecondBlock; /* if port belongs to 2nd block - of 16 port RTA */ - uchar InUse; /* how many pre-emptive cmds */ - uchar Lock; /* if params locked */ - uchar Store; /* if params stored across closes */ - uchar FirstOpen; /* TRUE if first time port opened */ - uchar FlushCmdBodge; /* if doing a (non)flush */ - uchar MagicFlags; /* require intr processing */ -#define MAGIC_FLUSH 0x01 /* mirror of WflushFlag */ -#define MAGIC_REBOOT 0x02 /* RTA re-booted, re-open ports */ -#define MORE_OUTPUT_EYGOR 0x04 /* riotproc failed to empty clists */ - uchar WflushFlag; /* 1 How many WFLUSHs active */ + struct PHB *PhbP; /* pointer to PHB for port */ + u16 *TxAdd; /* Add packets here */ + u16 *TxStart; /* Start of add array */ + u16 *TxEnd; /* End of add array */ + u16 *RxRemove; /* Remove packets here */ + u16 *RxStart; /* Start of remove array */ + u16 *RxEnd; /* End of remove array */ + unsigned int RtaUniqueNum; /* Unique number of RTA */ + unsigned short PortState; /* status of port */ + unsigned short ModemState; /* status of modem lines */ + unsigned long ModemLines; /* Modem bits sent to RTA */ + unsigned char CookMode; /* who expands CR/LF? */ + unsigned char ParamSem; /* Prevent write during param */ + unsigned char Mapped; /* if port mapped onto host */ + unsigned char SecondBlock; /* if port belongs to 2nd block + of 16 port RTA */ + unsigned char InUse; /* how many pre-emptive cmds */ + unsigned char Lock; /* if params locked */ + unsigned char Store; /* if params stored across closes */ + unsigned char FirstOpen; /* TRUE if first time port opened */ + unsigned char FlushCmdBodge; /* if doing a (non)flush */ + unsigned char MagicFlags; /* require intr processing */ +#define MAGIC_FLUSH 0x01 /* mirror of WflushFlag */ +#define MAGIC_REBOOT 0x02 /* RTA re-booted, re-open ports */ +#define MORE_OUTPUT_EYGOR 0x04 /* riotproc failed to empty clists */ + unsigned char WflushFlag; /* 1 How many WFLUSHs active */ /* ** Transparent print stuff */ @@ -179,63 +125,55 @@ struct Port { #ifndef MAX_XP_CTRL_LEN #define MAX_XP_CTRL_LEN 16 /* ALSO IN DAEMON.H */ #endif - uint XpCps; + unsigned int XpCps; char XpOn[MAX_XP_CTRL_LEN]; char XpOff[MAX_XP_CTRL_LEN]; - ushort XpLen; /* strlen(XpOn)+strlen(XpOff) */ - uchar XpActive; - uchar XpLastTickOk; /* TRUE if we can process */ + unsigned short XpLen; /* strlen(XpOn)+strlen(XpOff) */ + unsigned char XpActive; + unsigned char XpLastTickOk; /* TRUE if we can process */ #define XP_OPEN 00001 #define XP_RUNABLE 00002 struct ttystatics *XttyP; } Xprint; -#ifdef VPIX - v86_t *StashP; - uint IntMask; - struct termss VpixSs; - uchar ModemStatusReg; /* Modem status register */ -#endif - uchar RxDataStart; - uchar Cor2Copy; /* copy of COR2 */ - char *Name; /* points to the Rta's name */ -#ifdef STATS - struct RIOStats Stat; /* ports statistics */ -#endif + unsigned char RxDataStart; + unsigned char Cor2Copy; /* copy of COR2 */ + char *Name; /* points to the Rta's name */ char *TxRingBuffer; - ushort TxBufferIn; /* New data arrives here */ - ushort TxBufferOut; /* Intr removes data here */ - ushort OldTxBufferOut; /* Indicates if draining */ - int TimeoutId; /* Timeout ID */ - uint Debug; - uchar WaitUntilBooted; /* True if open should block */ - uint statsGather; /* True if gathering stats */ - ulong txchars; /* Chars transmitted */ - ulong rxchars; /* Chars received */ - ulong opens; /* port open count */ - ulong closes; /* port close count */ - ulong ioctls; /* ioctl count */ - uchar LastRxTgl; /* Last state of rx toggle bit */ - spinlock_t portSem; /* Lock using this sem */ - int MonitorTstate; /* Monitoring ? */ - int timeout_id; /* For calling 100 ms delays */ - int timeout_sem; /* For calling 100 ms delays */ - int firstOpen; /* First time open ? */ - char *p; /* save the global struc here .. */ + unsigned short TxBufferIn; /* New data arrives here */ + unsigned short TxBufferOut; /* Intr removes data here */ + unsigned short OldTxBufferOut; /* Indicates if draining */ + int TimeoutId; /* Timeout ID */ + unsigned int Debug; + unsigned char WaitUntilBooted; /* True if open should block */ + unsigned int statsGather; /* True if gathering stats */ + unsigned long txchars; /* Chars transmitted */ + unsigned long rxchars; /* Chars received */ + unsigned long opens; /* port open count */ + unsigned long closes; /* port close count */ + unsigned long ioctls; /* ioctl count */ + unsigned char LastRxTgl; /* Last state of rx toggle bit */ + spinlock_t portSem; /* Lock using this sem */ + int MonitorTstate; /* Monitoring ? */ + int timeout_id; /* For calling 100 ms delays */ + int timeout_sem; /* For calling 100 ms delays */ + int firstOpen; /* First time open ? */ + char *p; /* save the global struc here .. */ }; struct ModuleInfo { char *Name; - uint Flags[4]; /* one per port on a module */ + unsigned int Flags[4]; /* one per port on a module */ }; -#endif /* ** This struct is required because trying to grab an entire Port structure ** runs into problems with differing struct sizes between driver and config. */ struct PortParams { - uint Port; - ulong Config; - ulong State; + unsigned int Port; + unsigned long Config; + unsigned long State; struct ttystatics *TtyP; }; + +#endif diff --git a/drivers/char/rio/riotypes.h b/drivers/char/rio/riotypes.h index 46084d5c7e98..d07bd0aab5a2 100644 --- a/drivers/char/rio/riotypes.h +++ b/drivers/char/rio/riotypes.h @@ -43,25 +43,21 @@ #endif #endif -typedef unsigned short NUMBER_ptr; -typedef unsigned short WORD_ptr; -typedef unsigned short BYTE_ptr; -typedef unsigned short char_ptr; -typedef unsigned short Channel_ptr; -typedef unsigned short FREE_LIST_ptr_ptr; -typedef unsigned short FREE_LIST_ptr; -typedef unsigned short LPB_ptr; -typedef unsigned short Process_ptr; -typedef unsigned short PHB_ptr; -typedef unsigned short PKT_ptr; -typedef unsigned short PKT_ptr_ptr; -typedef unsigned short Q_BUF_ptr; -typedef unsigned short Q_BUF_ptr_ptr; -typedef unsigned short ROUTE_STR_ptr; -typedef unsigned short RUP_ptr; -typedef unsigned short short_ptr; -typedef unsigned short u_short_ptr; -typedef unsigned short ushort_ptr; +typedef u16 char_ptr; +typedef u16 Channel_ptr; +typedef u16 FREE_LIST_ptr_ptr; +typedef u16 FREE_LIST_ptr; +typedef u16 LPB_ptr; +typedef u16 Process_ptr; +typedef u16 PHB_ptr; +typedef u16 PKT_ptr; +typedef u16 Q_BUF_ptr; +typedef u16 Q_BUF_ptr_ptr; +typedef u16 ROUTE_STR_ptr; +typedef u16 RUP_ptr; +typedef u16 short_ptr; +typedef u16 u_short_ptr; +typedef u16 ushort_ptr; #endif /* __riotypes__ */ diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h index f74f67c6f702..40c617436bd1 100644 --- a/drivers/char/rio/rup.h +++ b/drivers/char/rio/rup.h @@ -37,14 +37,7 @@ #ifndef _rup_h #define _rup_h 1 -#ifdef SCCS_LABELS -#ifndef lint -/* static char *_rio_rup_h_sccs = "@(#)rup.h 1.5"; */ -#endif -#endif - #define MAX_RUP ((short) 16) - #define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */ /************************************************* @@ -62,13 +55,13 @@ struct RUP { PKT_ptr txpkt; /* Outgoing packet */ PKT_ptr rxpkt; /* Incoming packet */ - WORD link; /* Which link to send down? */ - BYTE rup_dest_unit[2]; /* Destination unit */ - WORD handshake; /* For handshaking */ - WORD timeout; /* Timeout */ - WORD status; /* Status */ - WORD txcontrol; /* Transmit control */ - WORD rxcontrol; /* Receive control */ + u16 link; /* Which link to send down? */ + u8 rup_dest_unit[2]; /* Destination unit */ + u16 handshake; /* For handshaking */ + u16 timeout; /* Timeout */ + u16 status; /* Status */ + u16 txcontrol; /* Transmit control */ + u16 rxcontrol; /* Receive control */ }; #endif diff --git a/drivers/char/rio/typdef.h b/drivers/char/rio/typdef.h index 185b889e1510..840c2498a59d 100644 --- a/drivers/char/rio/typdef.h +++ b/drivers/char/rio/typdef.h @@ -33,23 +33,16 @@ #ifndef __rio_typdef_h__ #define __rio_typdef_h__ -#ifdef SCCS_LABELS -static char *_typdef_h_sccs_ = "@(#)typdef.h 1.2"; -#endif - -#undef VPIX - /* ** IT IS REALLY, REALLY, IMPORTANT THAT BYTES ARE UNSIGNED! ** ** These types are ONLY to be used for refering to data structures ** on the RIO Host card! */ -typedef volatile unsigned char BYTE; -typedef volatile unsigned short WORD; -typedef volatile unsigned int DWORD; -typedef volatile unsigned short RIOP; -typedef volatile short NUMBER; +typedef volatile u8 BYTE; +typedef volatile u16 WORD; +typedef volatile u32 DWORD; +typedef volatile u16 RIOP; /* -- cgit v1.2.3-59-g8ed1b From 3b8e3f1e44326115f2a28a63ede62b1f5c53e46e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 24 Mar 2006 03:18:24 -0800 Subject: [PATCH] rioboot: lindent This is the result of indent -kr -i8 -bri0 -l255 Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/rio/rioboot.c | 1515 ++++++++++++++++++++------------------------ 1 file changed, 704 insertions(+), 811 deletions(-) (limited to 'drivers') diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c index 92df43552f15..9a96fc644e52 100644 --- a/drivers/char/rio/rioboot.c +++ b/drivers/char/rio/rioboot.c @@ -80,149 +80,141 @@ static char *_rioboot_c_sccs_ = "@(#)rioboot.c 1.3"; #include "cmdblk.h" #include "route.h" -static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP ); - -static uchar -RIOAtVec2Ctrl[] = -{ - /* 0 */ INTERRUPT_DISABLE, - /* 1 */ INTERRUPT_DISABLE, - /* 2 */ INTERRUPT_DISABLE, - /* 3 */ INTERRUPT_DISABLE, - /* 4 */ INTERRUPT_DISABLE, - /* 5 */ INTERRUPT_DISABLE, - /* 6 */ INTERRUPT_DISABLE, - /* 7 */ INTERRUPT_DISABLE, - /* 8 */ INTERRUPT_DISABLE, - /* 9 */ IRQ_9|INTERRUPT_ENABLE, +static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP); + +static uchar RIOAtVec2Ctrl[] = { + /* 0 */ INTERRUPT_DISABLE, + /* 1 */ INTERRUPT_DISABLE, + /* 2 */ INTERRUPT_DISABLE, + /* 3 */ INTERRUPT_DISABLE, + /* 4 */ INTERRUPT_DISABLE, + /* 5 */ INTERRUPT_DISABLE, + /* 6 */ INTERRUPT_DISABLE, + /* 7 */ INTERRUPT_DISABLE, + /* 8 */ INTERRUPT_DISABLE, + /* 9 */ IRQ_9 | INTERRUPT_ENABLE, /* 10 */ INTERRUPT_DISABLE, - /* 11 */ IRQ_11|INTERRUPT_ENABLE, - /* 12 */ IRQ_12|INTERRUPT_ENABLE, + /* 11 */ IRQ_11 | INTERRUPT_ENABLE, + /* 12 */ IRQ_12 | INTERRUPT_ENABLE, /* 13 */ INTERRUPT_DISABLE, /* 14 */ INTERRUPT_DISABLE, - /* 15 */ IRQ_15|INTERRUPT_ENABLE + /* 15 */ IRQ_15 | INTERRUPT_ENABLE }; /* ** Load in the RTA boot code. */ -int -RIOBootCodeRTA(p, rbp) -struct rio_info * p; -struct DownLoad * rbp; +int RIOBootCodeRTA(p, rbp) +struct rio_info *p; +struct DownLoad *rbp; { int offset; - func_enter (); + func_enter(); /* Linux doesn't allow you to disable interrupts during a "copyin". (Crash when a pagefault occurs). */ /* disable(oldspl); */ - - rio_dprintk (RIO_DEBUG_BOOT, "Data at user address 0x%x\n",(int)rbp->DataP); + + rio_dprintk(RIO_DEBUG_BOOT, "Data at user address 0x%x\n", (int) rbp->DataP); /* - ** Check that we have set asside enough memory for this - */ - if ( rbp->Count > SIXTY_FOUR_K ) { - rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n"); + ** Check that we have set asside enough memory for this + */ + if (rbp->Count > SIXTY_FOUR_K) { + rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n"); p->RIOError.Error = HOST_FILE_TOO_LARGE; /* restore(oldspl); */ - func_exit (); + func_exit(); return -ENOMEM; } - if ( p->RIOBooting ) { - rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n"); + if (p->RIOBooting) { + rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n"); p->RIOError.Error = BOOT_IN_PROGRESS; /* restore(oldspl); */ - func_exit (); + func_exit(); return -EBUSY; } /* - ** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary, - ** so calculate how far we have to move the data up the buffer - ** to achieve this. - */ - offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % - RTA_BOOT_DATA_SIZE; + ** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary, + ** so calculate how far we have to move the data up the buffer + ** to achieve this. + */ + offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % RTA_BOOT_DATA_SIZE; /* - ** Be clean, and clear the 'unused' portion of the boot buffer, - ** because it will (eventually) be part of the Rta run time environment - ** and so should be zeroed. - */ - bzero( (caddr_t)p->RIOBootPackets, offset ); + ** Be clean, and clear the 'unused' portion of the boot buffer, + ** because it will (eventually) be part of the Rta run time environment + ** and so should be zeroed. + */ + bzero((caddr_t) p->RIOBootPackets, offset); /* - ** Copy the data from user space. - */ + ** Copy the data from user space. + */ - if ( copyin((int)rbp->DataP,((caddr_t)(p->RIOBootPackets))+offset, - rbp->Count) ==COPYFAIL ) { - rio_dprintk (RIO_DEBUG_BOOT, "Bad data copy from user space\n"); + if (copyin((int) rbp->DataP, ((caddr_t) (p->RIOBootPackets)) + offset, rbp->Count) == COPYFAIL) { + rio_dprintk(RIO_DEBUG_BOOT, "Bad data copy from user space\n"); p->RIOError.Error = COPYIN_FAILED; /* restore(oldspl); */ - func_exit (); + func_exit(); return -EFAULT; } /* - ** Make sure that our copy of the size includes that offset we discussed - ** earlier. - */ - p->RIONumBootPkts = (rbp->Count+offset)/RTA_BOOT_DATA_SIZE; - p->RIOBootCount = rbp->Count; + ** Make sure that our copy of the size includes that offset we discussed + ** earlier. + */ + p->RIONumBootPkts = (rbp->Count + offset) / RTA_BOOT_DATA_SIZE; + p->RIOBootCount = rbp->Count; /* restore(oldspl); */ func_exit(); return 0; } -void rio_start_card_running (struct Host * HostP) +void rio_start_card_running(struct Host *HostP) { - func_enter (); + func_enter(); - switch ( HostP->Type ) { + switch (HostP->Type) { case RIO_AT: - rio_dprintk (RIO_DEBUG_BOOT, "Start ISA card running\n"); - WBYTE(HostP->Control, - BOOT_FROM_RAM | EXTERNAL_BUS_ON - | HostP->Mode - | RIOAtVec2Ctrl[HostP->Ivec & 0xF] ); + rio_dprintk(RIO_DEBUG_BOOT, "Start ISA card running\n"); + WBYTE(HostP->Control, BOOT_FROM_RAM | EXTERNAL_BUS_ON | HostP->Mode | RIOAtVec2Ctrl[HostP->Ivec & 0xF]); break; - + #ifdef FUTURE_RELEASE case RIO_MCA: - /* - ** MCA handles IRQ vectors differently, so we don't write - ** them to this register. - */ - rio_dprintk (RIO_DEBUG_BOOT, "Start MCA card running\n"); + /* + ** MCA handles IRQ vectors differently, so we don't write + ** them to this register. + */ + rio_dprintk(RIO_DEBUG_BOOT, "Start MCA card running\n"); WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode); break; case RIO_EISA: - /* - ** EISA is totally different and expects OUTBZs to turn it on. - */ - rio_dprintk (RIO_DEBUG_BOOT, "Start EISA card running\n"); - OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM ); + /* + ** EISA is totally different and expects OUTBZs to turn it on. + */ + rio_dprintk(RIO_DEBUG_BOOT, "Start EISA card running\n"); + OUTBZ(HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM); break; #endif case RIO_PCI: - /* - ** PCI is much the same as MCA. Everything is once again memory - ** mapped, so we are writing to memory registers instead of io - ** ports. - */ - rio_dprintk (RIO_DEBUG_BOOT, "Start PCI card running\n"); + /* + ** PCI is much the same as MCA. Everything is once again memory + ** mapped, so we are writing to memory registers instead of io + ** ports. + */ + rio_dprintk(RIO_DEBUG_BOOT, "Start PCI card running\n"); WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode); break; default: - rio_dprintk (RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type); + rio_dprintk(RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type); break; } /* @@ -239,9 +231,8 @@ void rio_start_card_running (struct Host * HostP) ** Put your rubber pants on before messing with this code - even the magic ** numbers have trouble understanding what they are doing here. */ -int -RIOBootCodeHOST(p, rbp) -struct rio_info * p; +int RIOBootCodeHOST(p, rbp) +struct rio_info *p; register struct DownLoad *rbp; { register struct Host *HostP; @@ -254,355 +245,346 @@ register struct DownLoad *rbp; BYTE *DestP; int wait_count; ushort OldParmMap; - ushort offset; /* It is very important that this is a ushort */ + ushort offset; /* It is very important that this is a ushort */ /* uint byte; */ caddr_t DownCode = NULL; unsigned long flags; - HostP = NULL; /* Assure the compiler we've initialized it */ - for ( host=0; hostRIONumHosts; host++ ) { - rio_dprintk (RIO_DEBUG_BOOT, "Attempt to boot host %d\n",host); + HostP = NULL; /* Assure the compiler we've initialized it */ + for (host = 0; host < p->RIONumHosts; host++) { + rio_dprintk(RIO_DEBUG_BOOT, "Attempt to boot host %d\n", host); HostP = &p->RIOHosts[host]; - - rio_dprintk (RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", - HostP->Type, HostP->Mode, HostP->Ivec); + rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec); - if ( (HostP->Flags & RUN_STATE) != RC_WAITING ) { - rio_dprintk (RIO_DEBUG_BOOT, "%s %d already running\n","Host",host); + + if ((HostP->Flags & RUN_STATE) != RC_WAITING) { + rio_dprintk(RIO_DEBUG_BOOT, "%s %d already running\n", "Host", host); continue; } /* - ** Grab a 32 bit pointer to the card. - */ + ** Grab a 32 bit pointer to the card. + */ Cad = HostP->Caddr; /* - ** We are going to (try) and load in rbp->Count bytes. - ** The last byte will reside at p->RIOConf.HostLoadBase-1; - ** Therefore, we need to start copying at address - ** (caddr+p->RIOConf.HostLoadBase-rbp->Count) - */ - StartP = (caddr_t)&Cad[p->RIOConf.HostLoadBase-rbp->Count]; - - rio_dprintk (RIO_DEBUG_BOOT, "kernel virtual address for host is 0x%x\n", (int)Cad ); - rio_dprintk (RIO_DEBUG_BOOT, "kernel virtual address for download is 0x%x\n", (int)StartP); - rio_dprintk (RIO_DEBUG_BOOT, "host loadbase is 0x%x\n",p->RIOConf.HostLoadBase); - rio_dprintk (RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count); - - if ( p->RIOConf.HostLoadBase < rbp->Count ) { - rio_dprintk (RIO_DEBUG_BOOT, "Bin too large\n"); + ** We are going to (try) and load in rbp->Count bytes. + ** The last byte will reside at p->RIOConf.HostLoadBase-1; + ** Therefore, we need to start copying at address + ** (caddr+p->RIOConf.HostLoadBase-rbp->Count) + */ + StartP = (caddr_t) & Cad[p->RIOConf.HostLoadBase - rbp->Count]; + + rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for host is 0x%x\n", (int) Cad); + rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for download is 0x%x\n", (int) StartP); + rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase); + rio_dprintk(RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count); + + if (p->RIOConf.HostLoadBase < rbp->Count) { + rio_dprintk(RIO_DEBUG_BOOT, "Bin too large\n"); p->RIOError.Error = HOST_FILE_TOO_LARGE; - func_exit (); + func_exit(); return -EFBIG; } /* - ** Ensure that the host really is stopped. - ** Disable it's external bus & twang its reset line. - */ - RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot ); + ** Ensure that the host really is stopped. + ** Disable it's external bus & twang its reset line. + */ + RIOHostReset(HostP->Type, (struct DpRam *) HostP->CardP, HostP->Slot); /* - ** Copy the data directly from user space to the SRAM. - ** This ain't going to be none too clever if the download - ** code is bigger than this segment. - */ - rio_dprintk (RIO_DEBUG_BOOT, "Copy in code\n"); + ** Copy the data directly from user space to the SRAM. + ** This ain't going to be none too clever if the download + ** code is bigger than this segment. + */ + rio_dprintk(RIO_DEBUG_BOOT, "Copy in code\n"); /* - ** PCI hostcard can't cope with 32 bit accesses and so need to copy - ** data to a local buffer, and then dripfeed the card. - */ - if ( HostP->Type == RIO_PCI ) { - /* int offset; */ + ** PCI hostcard can't cope with 32 bit accesses and so need to copy + ** data to a local buffer, and then dripfeed the card. + */ + if (HostP->Type == RIO_PCI) { + /* int offset; */ DownCode = sysbrk(rbp->Count); - if ( !DownCode ) { - rio_dprintk (RIO_DEBUG_BOOT, "No system memory available\n"); + if (!DownCode) { + rio_dprintk(RIO_DEBUG_BOOT, "No system memory available\n"); p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY; - func_exit (); + func_exit(); return -ENOMEM; } bzero(DownCode, rbp->Count); - if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) { - rio_dprintk (RIO_DEBUG_BOOT, "Bad copyin of host data\n"); - sysfree( DownCode, rbp->Count ); + if (copyin((int) rbp->DataP, DownCode, rbp->Count) == COPYFAIL) { + rio_dprintk(RIO_DEBUG_BOOT, "Bad copyin of host data\n"); + sysfree(DownCode, rbp->Count); p->RIOError.Error = COPYIN_FAILED; - func_exit (); + func_exit(); return -EFAULT; } - HostP->Copy( DownCode, StartP, rbp->Count ); + HostP->Copy(DownCode, StartP, rbp->Count); - sysfree( DownCode, rbp->Count ); - } - else if ( copyin((int)rbp->DataP,StartP,rbp->Count)==COPYFAIL ) { - rio_dprintk (RIO_DEBUG_BOOT, "Bad copyin of host data\n"); + sysfree(DownCode, rbp->Count); + } else if (copyin((int) rbp->DataP, StartP, rbp->Count) == COPYFAIL) { + rio_dprintk(RIO_DEBUG_BOOT, "Bad copyin of host data\n"); p->RIOError.Error = COPYIN_FAILED; - func_exit (); + func_exit(); return -EFAULT; } - rio_dprintk (RIO_DEBUG_BOOT, "Copy completed\n"); + rio_dprintk(RIO_DEBUG_BOOT, "Copy completed\n"); /* - ** S T O P ! - ** - ** Upto this point the code has been fairly rational, and possibly - ** even straight forward. What follows is a pile of crud that will - ** magically turn into six bytes of transputer assembler. Normally - ** you would expect an array or something, but, being me, I have - ** chosen [been told] to use a technique whereby the startup code - ** will be correct if we change the loadbase for the code. Which - ** brings us onto another issue - the loadbase is the *end* of the - ** code, not the start. - ** - ** If I were you I wouldn't start from here. - */ + ** S T O P ! + ** + ** Upto this point the code has been fairly rational, and possibly + ** even straight forward. What follows is a pile of crud that will + ** magically turn into six bytes of transputer assembler. Normally + ** you would expect an array or something, but, being me, I have + ** chosen [been told] to use a technique whereby the startup code + ** will be correct if we change the loadbase for the code. Which + ** brings us onto another issue - the loadbase is the *end* of the + ** code, not the start. + ** + ** If I were you I wouldn't start from here. + */ /* - ** We now need to insert a short boot section into - ** the memory at the end of Sram2. This is normally (de)composed - ** of the last eight bytes of the download code. The - ** download has been assembled/compiled to expect to be - ** loaded from 0x7FFF downwards. We have loaded it - ** at some other address. The startup code goes into the small - ** ram window at Sram2, in the last 8 bytes, which are really - ** at addresses 0x7FF8-0x7FFF. - ** - ** If the loadbase is, say, 0x7C00, then we need to branch to - ** address 0x7BFE to run the host.bin startup code. We assemble - ** this jump manually. - ** - ** The two byte sequence 60 08 is loaded into memory at address - ** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0, - ** which adds '0' to the .O register, complements .O, and then shifts - ** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will - ** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new - ** location. Now, the branch starts from the value of .PC (or .IP or - ** whatever the bloody register is called on this chip), and the .PC - ** will be pointing to the location AFTER the branch, in this case - ** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8. - ** - ** A long branch is coded at 0x7FF8. This consists of loading a four - ** byte offset into .O using nfix (as above) and pfix operators. The - ** pfix operates in exactly the same way as the nfix operator, but - ** without the complement operation. The offset, of course, must be - ** relative to the address of the byte AFTER the branch instruction, - ** which will be (urm) 0x7FFC, so, our final destination of the branch - ** (loadbase-2), has to be reached from here. Imagine that the loadbase - ** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which - ** is the first byte of the initial two byte short local branch of the - ** download code). - ** - ** To code a jump from 0x7FFC (which is where the branch will start - ** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)= - ** 0x7BFE. - ** This will be coded as four bytes: - ** 60 2C 20 02 - ** being nfix .O+0 - ** pfix .O+C - ** pfix .O+0 - ** jump .O+2 - ** - ** The nfix operator is used, so that the startup code will be - ** compatible with the whole Tp family. (lies, damn lies, it'll never - ** work in a month of Sundays). - ** - ** The nfix nyble is the 1s complement of the nyble value you - ** want to load - in this case we wanted 'F' so we nfix loaded '0'. - */ + ** We now need to insert a short boot section into + ** the memory at the end of Sram2. This is normally (de)composed + ** of the last eight bytes of the download code. The + ** download has been assembled/compiled to expect to be + ** loaded from 0x7FFF downwards. We have loaded it + ** at some other address. The startup code goes into the small + ** ram window at Sram2, in the last 8 bytes, which are really + ** at addresses 0x7FF8-0x7FFF. + ** + ** If the loadbase is, say, 0x7C00, then we need to branch to + ** address 0x7BFE to run the host.bin startup code. We assemble + ** this jump manually. + ** + ** The two byte sequence 60 08 is loaded into memory at address + ** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0, + ** which adds '0' to the .O register, complements .O, and then shifts + ** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will + ** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new + ** location. Now, the branch starts from the value of .PC (or .IP or + ** whatever the bloody register is called on this chip), and the .PC + ** will be pointing to the location AFTER the branch, in this case + ** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8. + ** + ** A long branch is coded at 0x7FF8. This consists of loading a four + ** byte offset into .O using nfix (as above) and pfix operators. The + ** pfix operates in exactly the same way as the nfix operator, but + ** without the complement operation. The offset, of course, must be + ** relative to the address of the byte AFTER the branch instruction, + ** which will be (urm) 0x7FFC, so, our final destination of the branch + ** (loadbase-2), has to be reached from here. Imagine that the loadbase + ** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which + ** is the first byte of the initial two byte short local branch of the + ** download code). + ** + ** To code a jump from 0x7FFC (which is where the branch will start + ** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)= + ** 0x7BFE. + ** This will be coded as four bytes: + ** 60 2C 20 02 + ** being nfix .O+0 + ** pfix .O+C + ** pfix .O+0 + ** jump .O+2 + ** + ** The nfix operator is used, so that the startup code will be + ** compatible with the whole Tp family. (lies, damn lies, it'll never + ** work in a month of Sundays). + ** + ** The nfix nyble is the 1s complement of the nyble value you + ** want to load - in this case we wanted 'F' so we nfix loaded '0'. + */ /* - ** Dest points to the top 8 bytes of Sram2. The Tp jumps - ** to 0x7FFE at reset time, and starts executing. This is - ** a short branch to 0x7FF8, where a long branch is coded. - */ + ** Dest points to the top 8 bytes of Sram2. The Tp jumps + ** to 0x7FFE at reset time, and starts executing. This is + ** a short branch to 0x7FF8, where a long branch is coded. + */ - DestP = (BYTE *)&Cad[0x7FF8]; /* <<<---- READ THE ABOVE COMMENTS */ + DestP = (BYTE *) & Cad[0x7FF8]; /* <<<---- READ THE ABOVE COMMENTS */ #define NFIX(N) (0x60 | (N)) /* .O = (~(.O + N))<<4 */ #define PFIX(N) (0x20 | (N)) /* .O = (.O + N)<<4 */ -#define JUMP(N) (0x00 | (N)) /* .PC = .PC + .O */ +#define JUMP(N) (0x00 | (N)) /* .PC = .PC + .O */ /* - ** 0x7FFC is the address of the location following the last byte of - ** the four byte jump instruction. - ** READ THE ABOVE COMMENTS - ** - ** offset is (TO-FROM) % MEMSIZE, but with compound buggering about. - ** Memsize is 64K for this range of Tp, so offset is a short (unsigned, - ** cos I don't understand 2's complement). - */ - offset = (p->RIOConf.HostLoadBase-2)-0x7FFC; - WBYTE( DestP[0] , NFIX(((ushort)(~offset) >> (ushort)12) & 0xF) ); - WBYTE( DestP[1] , PFIX(( offset >> 8) & 0xF) ); - WBYTE( DestP[2] , PFIX(( offset >> 4) & 0xF) ); - WBYTE( DestP[3] , JUMP( offset & 0xF) ); - - WBYTE( DestP[6] , NFIX(0) ); - WBYTE( DestP[7] , JUMP(8) ); - - rio_dprintk (RIO_DEBUG_BOOT, "host loadbase is 0x%x\n",p->RIOConf.HostLoadBase); - rio_dprintk (RIO_DEBUG_BOOT, "startup offset is 0x%x\n",offset); + ** 0x7FFC is the address of the location following the last byte of + ** the four byte jump instruction. + ** READ THE ABOVE COMMENTS + ** + ** offset is (TO-FROM) % MEMSIZE, but with compound buggering about. + ** Memsize is 64K for this range of Tp, so offset is a short (unsigned, + ** cos I don't understand 2's complement). + */ + offset = (p->RIOConf.HostLoadBase - 2) - 0x7FFC; + WBYTE(DestP[0], NFIX(((ushort) (~offset) >> (ushort) 12) & 0xF)); + WBYTE(DestP[1], PFIX((offset >> 8) & 0xF)); + WBYTE(DestP[2], PFIX((offset >> 4) & 0xF)); + WBYTE(DestP[3], JUMP(offset & 0xF)); + + WBYTE(DestP[6], NFIX(0)); + WBYTE(DestP[7], JUMP(8)); + + rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase); + rio_dprintk(RIO_DEBUG_BOOT, "startup offset is 0x%x\n", offset); /* - ** Flag what is going on - */ + ** Flag what is going on + */ HostP->Flags &= ~RUN_STATE; HostP->Flags |= RC_STARTUP; /* - ** Grab a copy of the current ParmMap pointer, so we - ** can tell when it has changed. - */ + ** Grab a copy of the current ParmMap pointer, so we + ** can tell when it has changed. + */ OldParmMap = RWORD(HostP->__ParmMapR); - rio_dprintk (RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n",OldParmMap); + rio_dprintk(RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n", OldParmMap); /* - ** And start it running (I hope). - ** As there is nothing dodgy or obscure about the - ** above code, this is guaranteed to work every time. - */ - rio_dprintk (RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", - HostP->Type, HostP->Mode, HostP->Ivec); + ** And start it running (I hope). + ** As there is nothing dodgy or obscure about the + ** above code, this is guaranteed to work every time. + */ + rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec); rio_start_card_running(HostP); - rio_dprintk (RIO_DEBUG_BOOT, "Set control port\n"); + rio_dprintk(RIO_DEBUG_BOOT, "Set control port\n"); /* - ** Now, wait for upto five seconds for the Tp to setup the parmmap - ** pointer: - */ - for ( wait_count=0; (wait_countRIOConf.StartupTime)&& - (RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) { - rio_dprintk (RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n",wait_count,RWORD(HostP->__ParmMapR)); + ** Now, wait for upto five seconds for the Tp to setup the parmmap + ** pointer: + */ + for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && (RWORD(HostP->__ParmMapR) == OldParmMap); wait_count++) { + rio_dprintk(RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n", wait_count, RWORD(HostP->__ParmMapR)); delay(HostP, HUNDRED_MS); } /* - ** If the parmmap pointer is unchanged, then the host code - ** has crashed & burned in a really spectacular way - */ - if ( RWORD(HostP->__ParmMapR) == OldParmMap ) { - rio_dprintk (RIO_DEBUG_BOOT, "parmmap 0x%x\n", RWORD(HostP->__ParmMapR)); - rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n"); - -#define HOST_DISABLE \ - HostP->Flags &= ~RUN_STATE; \ - HostP->Flags |= RC_STUFFED; \ - RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );\ - continue - - HOST_DISABLE; - } - - rio_dprintk (RIO_DEBUG_BOOT, "Running 0x%x\n", RWORD(HostP->__ParmMapR)); + ** If the parmmap pointer is unchanged, then the host code + ** has crashed & burned in a really spectacular way + */ + if (RWORD(HostP->__ParmMapR) == OldParmMap) { + rio_dprintk(RIO_DEBUG_BOOT, "parmmap 0x%x\n", RWORD(HostP->__ParmMapR)); + rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n"); + HostP->Flags &= ~RUN_STATE; + HostP->Flags |= RC_STUFFED; + RIOHostReset(HostP->Type, (struct DpRam *) HostP->CardP, HostP->Slot); + continue} + + rio_dprintk(RIO_DEBUG_BOOT, "Running 0x%x\n", RWORD(HostP->__ParmMapR)); /* - ** Well, the board thought it was OK, and setup its parmmap - ** pointer. For the time being, we will pretend that this - ** board is running, and check out what the error flag says. - */ + ** Well, the board thought it was OK, and setup its parmmap + ** pointer. For the time being, we will pretend that this + ** board is running, and check out what the error flag says. + */ /* - ** Grab a 32 bit pointer to the parmmap structure - */ - ParmMapP = (PARM_MAP *)RIO_PTR(Cad,RWORD(HostP->__ParmMapR)); - rio_dprintk (RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int)ParmMapP); - ParmMapP = (PARM_MAP *)((unsigned long)Cad + - (unsigned long)((RWORD((HostP->__ParmMapR))) & 0xFFFF)); - rio_dprintk (RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int)ParmMapP); + ** Grab a 32 bit pointer to the parmmap structure + */ + ParmMapP = (PARM_MAP *) RIO_PTR(Cad, RWORD(HostP->__ParmMapR)); + rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int) ParmMapP); + ParmMapP = (PARM_MAP *) ((unsigned long) Cad + (unsigned long) ((RWORD((HostP->__ParmMapR))) & 0xFFFF)); + rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int) ParmMapP); /* - ** The links entry should be 0xFFFF; we set it up - ** with a mask to say how many PHBs to use, and - ** which links to use. - */ - if ( (RWORD(ParmMapP->links) & 0xFFFF) != 0xFFFF ) { - rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); - rio_dprintk (RIO_DEBUG_BOOT, "Links = 0x%x\n",RWORD(ParmMapP->links)); - HOST_DISABLE; - } - - WWORD(ParmMapP->links , RIO_LINK_ENABLE); + ** The links entry should be 0xFFFF; we set it up + ** with a mask to say how many PHBs to use, and + ** which links to use. + */ + if ((RWORD(ParmMapP->links) & 0xFFFF) != 0xFFFF) { + rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); + rio_dprintk(RIO_DEBUG_BOOT, "Links = 0x%x\n", RWORD(ParmMapP->links)); + HostP->Flags &= ~RUN_STATE; + HostP->Flags |= RC_STUFFED; + RIOHostReset(HostP->Type, (struct DpRam *) HostP->CardP, HostP->Slot); + continue} + + WWORD(ParmMapP->links, RIO_LINK_ENABLE); /* - ** now wait for the card to set all the parmmap->XXX stuff - ** this is a wait of upto two seconds.... - */ - rio_dprintk (RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n",p->RIOConf.StartupTime); + ** now wait for the card to set all the parmmap->XXX stuff + ** this is a wait of upto two seconds.... + */ + rio_dprintk(RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n", p->RIOConf.StartupTime); HostP->timeout_id = 0; - for ( wait_count=0; (wait_countRIOConf.StartupTime) && - !RWORD(ParmMapP->init_done); wait_count++ ) { - rio_dprintk (RIO_DEBUG_BOOT, "Waiting for init_done\n"); + for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && !RWORD(ParmMapP->init_done); wait_count++) { + rio_dprintk(RIO_DEBUG_BOOT, "Waiting for init_done\n"); delay(HostP, HUNDRED_MS); } - rio_dprintk (RIO_DEBUG_BOOT, "OK! init_done!\n"); + rio_dprintk(RIO_DEBUG_BOOT, "OK! init_done!\n"); - if (RWORD(ParmMapP->error) != E_NO_ERROR || - !RWORD(ParmMapP->init_done) ) { - rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); - rio_dprintk (RIO_DEBUG_BOOT, "Timedout waiting for init_done\n"); - HOST_DISABLE; - } + if (RWORD(ParmMapP->error) != E_NO_ERROR || !RWORD(ParmMapP->init_done)) { + rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); + rio_dprintk(RIO_DEBUG_BOOT, "Timedout waiting for init_done\n"); + HostP->Flags &= ~RUN_STATE; + HostP->Flags |= RC_STUFFED; + RIOHostReset(HostP->Type, (struct DpRam *) HostP->CardP, HostP->Slot); + continue} - rio_dprintk (RIO_DEBUG_BOOT, "Got init_done\n"); + rio_dprintk(RIO_DEBUG_BOOT, "Got init_done\n"); /* - ** It runs! It runs! - */ - rio_dprintk (RIO_DEBUG_BOOT, "Host ID %x Running\n",HostP->UniqueNum); + ** It runs! It runs! + */ + rio_dprintk(RIO_DEBUG_BOOT, "Host ID %x Running\n", HostP->UniqueNum); /* - ** set the time period between interrupts. - */ - WWORD(ParmMapP->timer, (short)p->RIOConf.Timer ); + ** set the time period between interrupts. + */ + WWORD(ParmMapP->timer, (short) p->RIOConf.Timer); /* - ** Translate all the 16 bit pointers in the __ParmMapR into - ** 32 bit pointers for the driver. - */ - HostP->ParmMapP = ParmMapP; - HostP->PhbP = (PHB*)RIO_PTR(Cad,RWORD(ParmMapP->phb_ptr)); - HostP->RupP = (RUP*)RIO_PTR(Cad,RWORD(ParmMapP->rups)); - HostP->PhbNumP = (ushort*)RIO_PTR(Cad,RWORD(ParmMapP->phb_num_ptr)); - HostP->LinkStrP = (LPB*)RIO_PTR(Cad,RWORD(ParmMapP->link_str_ptr)); + ** Translate all the 16 bit pointers in the __ParmMapR into + ** 32 bit pointers for the driver. + */ + HostP->ParmMapP = ParmMapP; + HostP->PhbP = (PHB *) RIO_PTR(Cad, RWORD(ParmMapP->phb_ptr)); + HostP->RupP = (RUP *) RIO_PTR(Cad, RWORD(ParmMapP->rups)); + HostP->PhbNumP = (ushort *) RIO_PTR(Cad, RWORD(ParmMapP->phb_num_ptr)); + HostP->LinkStrP = (LPB *) RIO_PTR(Cad, RWORD(ParmMapP->link_str_ptr)); /* - ** point the UnixRups at the real Rups - */ - for ( RupN = 0; RupNUnixRups[RupN].RupP = &HostP->RupP[RupN]; - HostP->UnixRups[RupN].Id = RupN+1; + ** point the UnixRups at the real Rups + */ + for (RupN = 0; RupN < MAX_RUP; RupN++) { + HostP->UnixRups[RupN].RupP = &HostP->RupP[RupN]; + HostP->UnixRups[RupN].Id = RupN + 1; HostP->UnixRups[RupN].BaseSysPort = NO_PORT; spin_lock_init(&HostP->UnixRups[RupN].RupLock); } - for ( RupN = 0; RupNUnixRups[RupN+MAX_RUP].RupP = &HostP->LinkStrP[RupN].rup; - HostP->UnixRups[RupN+MAX_RUP].Id = 0; - HostP->UnixRups[RupN+MAX_RUP].BaseSysPort = NO_PORT; - spin_lock_init(&HostP->UnixRups[RupN+MAX_RUP].RupLock); + for (RupN = 0; RupN < LINKS_PER_UNIT; RupN++) { + HostP->UnixRups[RupN + MAX_RUP].RupP = &HostP->LinkStrP[RupN].rup; + HostP->UnixRups[RupN + MAX_RUP].Id = 0; + HostP->UnixRups[RupN + MAX_RUP].BaseSysPort = NO_PORT; + spin_lock_init(&HostP->UnixRups[RupN + MAX_RUP].RupLock); } /* - ** point the PortP->Phbs at the real Phbs - */ - for ( PortN=p->RIOFirstPortsMapped; - PortNRIOLastPortsMapped+PORTS_PER_RTA; PortN++ ) { - if ( p->RIOPortp[PortN]->HostP == HostP ) { + ** point the PortP->Phbs at the real Phbs + */ + for (PortN = p->RIOFirstPortsMapped; PortN < p->RIOLastPortsMapped + PORTS_PER_RTA; PortN++) { + if (p->RIOPortp[PortN]->HostP == HostP) { struct Port *PortP = p->RIOPortp[PortN]; struct PHB *PhbP; /* int oldspl; */ - if ( !PortP->Mapped ) + if (!PortP->Mapped) continue; PhbP = &HostP->PhbP[PortP->HostPort]; @@ -610,40 +592,40 @@ register struct DownLoad *rbp; PortP->PhbP = PhbP; - PortP->TxAdd = (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_add)); - PortP->TxStart = (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_start)); - PortP->TxEnd = (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_end)); - PortP->RxRemove = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_remove)); - PortP->RxStart = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_start)); - PortP->RxEnd = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_end)); + PortP->TxAdd = (WORD *) RIO_PTR(Cad, RWORD(PhbP->tx_add)); + PortP->TxStart = (WORD *) RIO_PTR(Cad, RWORD(PhbP->tx_start)); + PortP->TxEnd = (WORD *) RIO_PTR(Cad, RWORD(PhbP->tx_end)); + PortP->RxRemove = (WORD *) RIO_PTR(Cad, RWORD(PhbP->rx_remove)); + PortP->RxStart = (WORD *) RIO_PTR(Cad, RWORD(PhbP->rx_start)); + PortP->RxEnd = (WORD *) RIO_PTR(Cad, RWORD(PhbP->rx_end)); rio_spin_unlock_irqrestore(&PortP->portSem, flags); /* - ** point the UnixRup at the base SysPort - */ - if ( !(PortN % PORTS_PER_RTA) ) + ** point the UnixRup at the base SysPort + */ + if (!(PortN % PORTS_PER_RTA)) HostP->UnixRups[PortP->RupNum].BaseSysPort = PortN; } } - rio_dprintk (RIO_DEBUG_BOOT, "Set the card running... \n"); + rio_dprintk(RIO_DEBUG_BOOT, "Set the card running... \n"); /* - ** last thing - show the world that everything is in place - */ + ** last thing - show the world that everything is in place + */ HostP->Flags &= ~RUN_STATE; HostP->Flags |= RC_RUNNING; } /* - ** MPX always uses a poller. This is actually patched into the system - ** configuration and called directly from each clock tick. - ** - */ + ** MPX always uses a poller. This is actually patched into the system + ** configuration and called directly from each clock tick. + ** + */ p->RIOPolling = 1; p->RIOSystemUp++; - - rio_dprintk (RIO_DEBUG_BOOT, "Done everything %x\n", HostP->Ivec); - func_exit (); + + rio_dprintk(RIO_DEBUG_BOOT, "Done everything %x\n", HostP->Ivec); + func_exit(); return 0; } @@ -653,23 +635,22 @@ register struct DownLoad *rbp; ** Boot an RTA. If we have successfully processed this boot, then ** return 1. If we havent, then return 0. */ -int -RIOBootRup( p, Rup, HostP, PacketP) -struct rio_info * p; +int RIOBootRup(p, Rup, HostP, PacketP) +struct rio_info *p; uint Rup; struct Host *HostP; -struct PKT *PacketP; +struct PKT *PacketP; { - struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data; + struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data; struct PktCmd_M *PktReplyP; struct CmdBlk *CmdBlkP; uint sequence; /* - ** If we haven't been told what to boot, we can't boot it. - */ - if ( p->RIONumBootPkts == 0 ) { - rio_dprintk (RIO_DEBUG_BOOT, "No RTA code to download yet\n"); + ** If we haven't been told what to boot, we can't boot it. + */ + if (p->RIONumBootPkts == 0) { + rio_dprintk(RIO_DEBUG_BOOT, "No RTA code to download yet\n"); return 0; } @@ -677,117 +658,111 @@ struct PKT *PacketP; /* ShowPacket( DBG_BOOT, PacketP ); */ /* - ** Special case of boot completed - if we get one of these then we - ** don't need a command block. For all other cases we do, so handle - ** this first and then get a command block, then handle every other - ** case, relinquishing the command block if disaster strikes! - */ - if ( (RBYTE(PacketP->len) & PKT_CMD_BIT) && - (RBYTE(PktCmdP->Command)==BOOT_COMPLETED) ) - return RIOBootComplete(p, HostP, Rup, PktCmdP ); + ** Special case of boot completed - if we get one of these then we + ** don't need a command block. For all other cases we do, so handle + ** this first and then get a command block, then handle every other + ** case, relinquishing the command block if disaster strikes! + */ + if ((RBYTE(PacketP->len) & PKT_CMD_BIT) && (RBYTE(PktCmdP->Command) == BOOT_COMPLETED)) + return RIOBootComplete(p, HostP, Rup, PktCmdP); /* - ** try to unhook a command block from the command free list. - */ - if ( !(CmdBlkP = RIOGetCmdBlk()) ) { - rio_dprintk (RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n"); + ** try to unhook a command block from the command free list. + */ + if (!(CmdBlkP = RIOGetCmdBlk())) { + rio_dprintk(RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n"); return 0; } /* - ** Fill in the default info on the command block - */ - CmdBlkP->Packet.dest_unit = Rup < (ushort)MAX_RUP ? Rup : 0; + ** Fill in the default info on the command block + */ + CmdBlkP->Packet.dest_unit = Rup < (ushort) MAX_RUP ? Rup : 0; CmdBlkP->Packet.dest_port = BOOT_RUP; - CmdBlkP->Packet.src_unit = 0; - CmdBlkP->Packet.src_port = BOOT_RUP; + CmdBlkP->Packet.src_unit = 0; + CmdBlkP->Packet.src_port = BOOT_RUP; CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL; - PktReplyP = (struct PktCmd_M *)CmdBlkP->Packet.data; + PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data; /* - ** process COMMANDS on the boot rup! - */ - if ( RBYTE(PacketP->len) & PKT_CMD_BIT ) { + ** process COMMANDS on the boot rup! + */ + if (RBYTE(PacketP->len) & PKT_CMD_BIT) { /* - ** We only expect one type of command - a BOOT_REQUEST! - */ - if ( RBYTE(PktCmdP->Command) != BOOT_REQUEST ) { - rio_dprintk (RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %d\n", - PktCmdP->Command,Rup,HostP-p->RIOHosts); - ShowPacket( DBG_BOOT, PacketP ); - RIOFreeCmdBlk( CmdBlkP ); + ** We only expect one type of command - a BOOT_REQUEST! + */ + if (RBYTE(PktCmdP->Command) != BOOT_REQUEST) { + rio_dprintk(RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %d\n", PktCmdP->Command, Rup, HostP - p->RIOHosts); + ShowPacket(DBG_BOOT, PacketP); + RIOFreeCmdBlk(CmdBlkP); return 1; } /* - ** Build a Boot Sequence command block - ** - ** 02.03.1999 ARG - ESIL 0820 fix - ** We no longer need to use "Boot Mode", we'll always allow - ** boot requests - the boot will not complete if the device - ** appears in the bindings table. - ** So, this conditional is not required ... - ** - if (p->RIOBootMode == RC_BOOT_NONE) - ** - ** If the system is in slave mode, and a boot request is - ** received, set command to BOOT_ABORT so that the boot - ** will not complete. - ** - PktReplyP->Command = BOOT_ABORT; - else - ** - ** We'll just (always) set the command field in packet reply - ** to allow an attempted boot sequence : - */ + ** Build a Boot Sequence command block + ** + ** 02.03.1999 ARG - ESIL 0820 fix + ** We no longer need to use "Boot Mode", we'll always allow + ** boot requests - the boot will not complete if the device + ** appears in the bindings table. + ** So, this conditional is not required ... + ** + if (p->RIOBootMode == RC_BOOT_NONE) + ** + ** If the system is in slave mode, and a boot request is + ** received, set command to BOOT_ABORT so that the boot + ** will not complete. + ** + PktReplyP->Command = BOOT_ABORT; + else + ** + ** We'll just (always) set the command field in packet reply + ** to allow an attempted boot sequence : + */ PktReplyP->Command = BOOT_SEQUENCE; PktReplyP->BootSequence.NumPackets = p->RIONumBootPkts; - PktReplyP->BootSequence.LoadBase = p->RIOConf.RtaLoadBase; - PktReplyP->BootSequence.CodeSize = p->RIOBootCount; + PktReplyP->BootSequence.LoadBase = p->RIOConf.RtaLoadBase; + PktReplyP->BootSequence.CodeSize = p->RIOBootCount; - CmdBlkP->Packet.len = BOOT_SEQUENCE_LEN | PKT_CMD_BIT; + CmdBlkP->Packet.len = BOOT_SEQUENCE_LEN | PKT_CMD_BIT; - bcopy("BOOT",(void *)&CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN],4); + bcopy("BOOT", (void *) &CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN], 4); - rio_dprintk (RIO_DEBUG_BOOT, "Boot RTA on Host %d Rup %d - %d (0x%x) packets to 0x%x\n", - HostP-p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, - p->RIOConf.RtaLoadBase); + rio_dprintk(RIO_DEBUG_BOOT, "Boot RTA on Host %d Rup %d - %d (0x%x) packets to 0x%x\n", HostP - p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, p->RIOConf.RtaLoadBase); /* - ** If this host is in slave mode, send the RTA an invalid boot - ** sequence command block to force it to kill the boot. We wait - ** for half a second before sending this packet to prevent the RTA - ** attempting to boot too often. The master host should then grab - ** the RTA and make it its own. - */ + ** If this host is in slave mode, send the RTA an invalid boot + ** sequence command block to force it to kill the boot. We wait + ** for half a second before sending this packet to prevent the RTA + ** attempting to boot too often. The master host should then grab + ** the RTA and make it its own. + */ p->RIOBooting++; - RIOQueueCmdBlk( HostP, Rup, CmdBlkP ); + RIOQueueCmdBlk(HostP, Rup, CmdBlkP); return 1; } /* - ** It is a request for boot data. - */ + ** It is a request for boot data. + */ sequence = RWORD(PktCmdP->Sequence); - rio_dprintk (RIO_DEBUG_BOOT, "Boot block %d on Host %d Rup%d\n",sequence,HostP-p->RIOHosts,Rup); + rio_dprintk(RIO_DEBUG_BOOT, "Boot block %d on Host %d Rup%d\n", sequence, HostP - p->RIOHosts, Rup); - if ( sequence >= p->RIONumBootPkts ) { - rio_dprintk (RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, - p->RIONumBootPkts); - ShowPacket( DBG_BOOT, PacketP ); + if (sequence >= p->RIONumBootPkts) { + rio_dprintk(RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, p->RIONumBootPkts); + ShowPacket(DBG_BOOT, PacketP); } PktReplyP->Sequence = sequence; - bcopy( p->RIOBootPackets[ p->RIONumBootPkts - sequence - 1 ], - PktReplyP->BootData, RTA_BOOT_DATA_SIZE ); + bcopy(p->RIOBootPackets[p->RIONumBootPkts - sequence - 1], PktReplyP->BootData, RTA_BOOT_DATA_SIZE); CmdBlkP->Packet.len = PKT_MAX_DATA_LEN; - ShowPacket( DBG_BOOT, &CmdBlkP->Packet ); - RIOQueueCmdBlk( HostP, Rup, CmdBlkP ); + ShowPacket(DBG_BOOT, &CmdBlkP->Packet); + RIOQueueCmdBlk(HostP, Rup, CmdBlkP); return 1; } @@ -797,422 +772,348 @@ struct PKT *PacketP; ** If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA. ** RtaUniq is the booted RTA. */ -static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP ) +static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP) { - struct Map *MapP = NULL; - struct Map *MapP2 = NULL; - int Flag; - int found; - int host, rta; - int EmptySlot = -1; - int entry, entry2; - char *MyType, *MyName; - uint MyLink; - ushort RtaType; - uint RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) + - (RBYTE(PktCmdP->UniqNum[1]) << 8) + - (RBYTE(PktCmdP->UniqNum[2]) << 16) + - (RBYTE(PktCmdP->UniqNum[3]) << 24); + struct Map *MapP = NULL; + struct Map *MapP2 = NULL; + int Flag; + int found; + int host, rta; + int EmptySlot = -1; + int entry, entry2; + char *MyType, *MyName; + uint MyLink; + ushort RtaType; + uint RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) + (RBYTE(PktCmdP->UniqNum[1]) << 8) + (RBYTE(PktCmdP->UniqNum[2]) << 16) + (RBYTE(PktCmdP->UniqNum[3]) << 24); /* Was RIOBooting-- . That's bad. If an RTA sends two of them, the driver will never think that the RTA has booted... -- REW */ p->RIOBooting = 0; - rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting); + rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting); /* - ** Determine type of unit (16/8 port RTA). - */ + ** Determine type of unit (16/8 port RTA). + */ RtaType = GetUnitType(RtaUniq); - if ( Rup >= (ushort)MAX_RUP ) { - rio_dprintk (RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", - HostP->Name, 8 * RtaType, RBYTE(PktCmdP->LinkNum)+'A'); + if (Rup >= (ushort) MAX_RUP) { + rio_dprintk(RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", HostP->Name, 8 * RtaType, RBYTE(PktCmdP->LinkNum) + 'A'); } else { - rio_dprintk (RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", - HostP->Mapping[Rup].Name, 8 * RtaType, - RBYTE(PktCmdP->LinkNum)+'A'); + rio_dprintk(RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", HostP->Mapping[Rup].Name, 8 * RtaType, RBYTE(PktCmdP->LinkNum) + 'A'); } - rio_dprintk (RIO_DEBUG_BOOT, "UniqNum is 0x%x\n",RtaUniq); + rio_dprintk(RIO_DEBUG_BOOT, "UniqNum is 0x%x\n", RtaUniq); - if ( ( RtaUniq == 0x00000000 ) || ( RtaUniq == 0xffffffff ) ) - { - rio_dprintk (RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n"); - return TRUE; + if ((RtaUniq == 0x00000000) || (RtaUniq == 0xffffffff)) { + rio_dprintk(RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n"); + return TRUE; } /* - ** If this RTA has just booted an RTA which doesn't belong to this - ** system, or the system is in slave mode, do not attempt to create - ** a new table entry for it. - */ - if (!RIOBootOk(p, HostP, RtaUniq)) - { - MyLink = RBYTE(PktCmdP->LinkNum); - if (Rup < (ushort) MAX_RUP) - { - /* - ** RtaUniq was clone booted (by this RTA). Instruct this RTA - ** to hold off further attempts to boot on this link for 30 - ** seconds. - */ - if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink)) - { - rio_dprintk (RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n", - 'A' + MyLink); + ** If this RTA has just booted an RTA which doesn't belong to this + ** system, or the system is in slave mode, do not attempt to create + ** a new table entry for it. + */ + if (!RIOBootOk(p, HostP, RtaUniq)) { + MyLink = RBYTE(PktCmdP->LinkNum); + if (Rup < (ushort) MAX_RUP) { + /* + ** RtaUniq was clone booted (by this RTA). Instruct this RTA + ** to hold off further attempts to boot on this link for 30 + ** seconds. + */ + if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink)) { + rio_dprintk(RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n", 'A' + MyLink); + } + } else { + /* + ** RtaUniq was booted by this host. Set the booting link + ** to hold off for 30 seconds to give another unit a + ** chance to boot it. + */ + WWORD(HostP->LinkStrP[MyLink].WaitNoBoot, 30); } - } - else - { - /* - ** RtaUniq was booted by this host. Set the booting link - ** to hold off for 30 seconds to give another unit a - ** chance to boot it. - */ - WWORD(HostP->LinkStrP[MyLink].WaitNoBoot, 30); - } - rio_dprintk (RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", - RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum); - return TRUE; + rio_dprintk(RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum); + return TRUE; } /* - ** Check for a SLOT_IN_USE entry for this RTA attached to the - ** current host card in the driver table. - ** - ** If it exists, make a note that we have booted it. Other parts of - ** the driver are interested in this information at a later date, - ** in particular when the booting RTA asks for an ID for this unit, - ** we must have set the BOOTED flag, and the NEWBOOT flag is used - ** to force an open on any ports that where previously open on this - ** unit. - */ - for ( entry=0; entryMapping[entry].Flags & SLOT_IN_USE) && - (HostP->Mapping[entry].RtaUniqueNum==RtaUniq)) - { - HostP->Mapping[entry].Flags |= RTA_BOOTED|RTA_NEWBOOT; + ** Check for a SLOT_IN_USE entry for this RTA attached to the + ** current host card in the driver table. + ** + ** If it exists, make a note that we have booted it. Other parts of + ** the driver are interested in this information at a later date, + ** in particular when the booting RTA asks for an ID for this unit, + ** we must have set the BOOTED flag, and the NEWBOOT flag is used + ** to force an open on any ports that where previously open on this + ** unit. + */ + for (entry = 0; entry < MAX_RUP; entry++) { + uint sysport; + + if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) { + HostP->Mapping[entry].Flags |= RTA_BOOTED | RTA_NEWBOOT; #ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry]); + RIO_SV_BROADCAST(HostP->svFlags[entry]); #endif - if ( (sysport=HostP->Mapping[entry].SysPort) != NO_PORT ) - { - if ( sysport < p->RIOFirstPortsBooted ) - p->RIOFirstPortsBooted = sysport; - if ( sysport > p->RIOLastPortsBooted ) - p->RIOLastPortsBooted = sysport; - /* - ** For a 16 port RTA, check the second bank of 8 ports - */ - if (RtaType == TYPE_RTA16) - { - entry2 = HostP->Mapping[entry].ID2 - 1; - HostP->Mapping[entry2].Flags |= RTA_BOOTED|RTA_NEWBOOT; + if ((sysport = HostP->Mapping[entry].SysPort) != NO_PORT) { + if (sysport < p->RIOFirstPortsBooted) + p->RIOFirstPortsBooted = sysport; + if (sysport > p->RIOLastPortsBooted) + p->RIOLastPortsBooted = sysport; + /* + ** For a 16 port RTA, check the second bank of 8 ports + */ + if (RtaType == TYPE_RTA16) { + entry2 = HostP->Mapping[entry].ID2 - 1; + HostP->Mapping[entry2].Flags |= RTA_BOOTED | RTA_NEWBOOT; #ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry2]); + RIO_SV_BROADCAST(HostP->svFlags[entry2]); #endif - sysport = HostP->Mapping[entry2].SysPort; - if ( sysport < p->RIOFirstPortsBooted ) - p->RIOFirstPortsBooted = sysport; - if ( sysport > p->RIOLastPortsBooted ) - p->RIOLastPortsBooted = sysport; - } - } - if (RtaType == TYPE_RTA16) { - rio_dprintk (RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", - entry+1, entry2+1); - } else { - rio_dprintk (RIO_DEBUG_BOOT, "RTA will be given ID %d\n",entry+1); + sysport = HostP->Mapping[entry2].SysPort; + if (sysport < p->RIOFirstPortsBooted) + p->RIOFirstPortsBooted = sysport; + if (sysport > p->RIOLastPortsBooted) + p->RIOLastPortsBooted = sysport; + } + } + if (RtaType == TYPE_RTA16) { + rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", entry + 1, entry2 + 1); + } else { + rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given ID %d\n", entry + 1); + } + return TRUE; } - return TRUE; - } } - rio_dprintk (RIO_DEBUG_BOOT, "RTA not configured for this host\n"); + rio_dprintk(RIO_DEBUG_BOOT, "RTA not configured for this host\n"); - if ( Rup >= (ushort)MAX_RUP ) - { - /* - ** It was a host that did the booting - */ - MyType = "Host"; - MyName = HostP->Name; - } - else - { - /* - ** It was an RTA that did the booting - */ - MyType = "RTA"; - MyName = HostP->Mapping[Rup].Name; + if (Rup >= (ushort) MAX_RUP) { + /* + ** It was a host that did the booting + */ + MyType = "Host"; + MyName = HostP->Name; + } else { + /* + ** It was an RTA that did the booting + */ + MyType = "RTA"; + MyName = HostP->Mapping[Rup].Name; } MyLink = RBYTE(PktCmdP->LinkNum); /* - ** There is no SLOT_IN_USE entry for this RTA attached to the current - ** host card in the driver table. - ** - ** Check for a SLOT_TENTATIVE entry for this RTA attached to the - ** current host card in the driver table. - ** - ** If we find one, then we re-use that slot. - */ - for ( entry=0; entryMapping[entry].Flags & SLOT_TENTATIVE) && - (HostP->Mapping[entry].RtaUniqueNum == RtaUniq) ) - { - if (RtaType == TYPE_RTA16) - { - entry2 = HostP->Mapping[entry].ID2 - 1; - if ( (HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) && - (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq) ) - rio_dprintk (RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)\n", - entry, entry2); - else - continue; + ** There is no SLOT_IN_USE entry for this RTA attached to the current + ** host card in the driver table. + ** + ** Check for a SLOT_TENTATIVE entry for this RTA attached to the + ** current host card in the driver table. + ** + ** If we find one, then we re-use that slot. + */ + for (entry = 0; entry < MAX_RUP; entry++) { + if ((HostP->Mapping[entry].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) { + if (RtaType == TYPE_RTA16) { + entry2 = HostP->Mapping[entry].ID2 - 1; + if ((HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq)) + rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)\n", entry, entry2); + else + continue; + } else + rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n", entry); + if (!p->RIONoMessage) + cprintf("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); + return TRUE; } - else - rio_dprintk (RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n",entry); - if (! p->RIONoMessage) - cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType,MyName,MyLink+'A'); - return TRUE; - } } /* - ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA - ** attached to the current host card in the driver table. - ** - ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another - ** host for this RTA in the driver table. - ** - ** For a SLOT_IN_USE entry on another host, we need to delete the RTA - ** entry from the other host and add it to this host (using some of - ** the functions from table.c which do this). - ** For a SLOT_TENTATIVE entry on another host, we must cope with the - ** following scenario: - ** - ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry - ** in table) - ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE - ** entries) - ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE) - ** + Unplug RTA and plug back into host A. - ** + Configure RTA on host A. We now have the same RTA configured - ** with different ports on two different hosts. - */ - rio_dprintk (RIO_DEBUG_BOOT, "Have we seen RTA %x before?\n", RtaUniq ); + ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA + ** attached to the current host card in the driver table. + ** + ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another + ** host for this RTA in the driver table. + ** + ** For a SLOT_IN_USE entry on another host, we need to delete the RTA + ** entry from the other host and add it to this host (using some of + ** the functions from table.c which do this). + ** For a SLOT_TENTATIVE entry on another host, we must cope with the + ** following scenario: + ** + ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry + ** in table) + ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE + ** entries) + ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE) + ** + Unplug RTA and plug back into host A. + ** + Configure RTA on host A. We now have the same RTA configured + ** with different ports on two different hosts. + */ + rio_dprintk(RIO_DEBUG_BOOT, "Have we seen RTA %x before?\n", RtaUniq); found = 0; - Flag = 0; /* Convince the compiler this variable is initialized */ - for ( host = 0; !found && (host < p->RIONumHosts); host++ ) - { - for ( rta=0; rtaRIOHosts[host].Mapping[rta].Flags & - (SLOT_IN_USE | SLOT_TENTATIVE)) && - (p->RIOHosts[host].Mapping[rta].RtaUniqueNum==RtaUniq)) - { - Flag = p->RIOHosts[host].Mapping[rta].Flags; - MapP = &p->RIOHosts[host].Mapping[rta]; - if (RtaType == TYPE_RTA16) - { - MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1]; - rio_dprintk (RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %s\n", - rta+1, MapP->ID2, p->RIOHosts[host].Name); - } - else - rio_dprintk (RIO_DEBUG_BOOT, "This RTA is unit %d from host %s\n", - rta+1, p->RIOHosts[host].Name); - found = 1; - break; + Flag = 0; /* Convince the compiler this variable is initialized */ + for (host = 0; !found && (host < p->RIONumHosts); host++) { + for (rta = 0; rta < MAX_RUP; rta++) { + if ((p->RIOHosts[host].Mapping[rta].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (p->RIOHosts[host].Mapping[rta].RtaUniqueNum == RtaUniq)) { + Flag = p->RIOHosts[host].Mapping[rta].Flags; + MapP = &p->RIOHosts[host].Mapping[rta]; + if (RtaType == TYPE_RTA16) { + MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1]; + rio_dprintk(RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %s\n", rta + 1, MapP->ID2, p->RIOHosts[host].Name); + } else + rio_dprintk(RIO_DEBUG_BOOT, "This RTA is unit %d from host %s\n", rta + 1, p->RIOHosts[host].Name); + found = 1; + break; + } } - } } /* - ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA - ** attached to the current host card in the driver table. - ** - ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on - ** another host for this RTA in the driver table... - ** - ** Check for a SLOT_IN_USE entry for this RTA in the config table. - */ - if ( !MapP ) - { - rio_dprintk (RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTable\n",RtaUniq); - for ( rta=0; rta < TOTAL_MAP_ENTRIES; rta++ ) - { - rio_dprintk (RIO_DEBUG_BOOT, "Check table entry %d (%x)", - rta, - p->RIOSavedTable[rta].RtaUniqueNum); - - if ( (p->RIOSavedTable[rta].Flags & SLOT_IN_USE) && - (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq) ) - { - MapP = &p->RIOSavedTable[rta]; - Flag = p->RIOSavedTable[rta].Flags; - if (RtaType == TYPE_RTA16) - { - for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES; - entry2++) - { - if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq) - break; - } - MapP2 = &p->RIOSavedTable[entry2]; - rio_dprintk (RIO_DEBUG_BOOT, "This RTA is from table entries %d+%d\n", - rta, entry2); - } - else - rio_dprintk (RIO_DEBUG_BOOT, "This RTA is from table entry %d\n", rta); - break; + ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA + ** attached to the current host card in the driver table. + ** + ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on + ** another host for this RTA in the driver table... + ** + ** Check for a SLOT_IN_USE entry for this RTA in the config table. + */ + if (!MapP) { + rio_dprintk(RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTable\n", RtaUniq); + for (rta = 0; rta < TOTAL_MAP_ENTRIES; rta++) { + rio_dprintk(RIO_DEBUG_BOOT, "Check table entry %d (%x)", rta, p->RIOSavedTable[rta].RtaUniqueNum); + + if ((p->RIOSavedTable[rta].Flags & SLOT_IN_USE) && (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq)) { + MapP = &p->RIOSavedTable[rta]; + Flag = p->RIOSavedTable[rta].Flags; + if (RtaType == TYPE_RTA16) { + for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES; entry2++) { + if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq) + break; + } + MapP2 = &p->RIOSavedTable[entry2]; + rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entries %d+%d\n", rta, entry2); + } else + rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entry %d\n", rta); + break; + } } - } } /* - ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA - ** attached to the current host card in the driver table. - ** - ** We may have found a SLOT_IN_USE entry on another host for this - ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry - ** on another host for this RTA in the driver table. - ** - ** Check the driver table for room to fit this newly discovered RTA. - ** RIOFindFreeID() first looks for free slots and if it does not - ** find any free slots it will then attempt to oust any - ** tentative entry in the table. - */ + ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA + ** attached to the current host card in the driver table. + ** + ** We may have found a SLOT_IN_USE entry on another host for this + ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry + ** on another host for this RTA in the driver table. + ** + ** Check the driver table for room to fit this newly discovered RTA. + ** RIOFindFreeID() first looks for free slots and if it does not + ** find any free slots it will then attempt to oust any + ** tentative entry in the table. + */ EmptySlot = 1; - if (RtaType == TYPE_RTA16) - { - if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0) - { - RIODefaultName(p, HostP, entry); - FillSlot(entry, entry2, RtaUniq, HostP); - EmptySlot = 0; - } - } - else - { - if (RIOFindFreeID(p, HostP, &entry, NULL) == 0) - { - RIODefaultName(p, HostP, entry); - FillSlot(entry, 0, RtaUniq, HostP); - EmptySlot = 0; - } + if (RtaType == TYPE_RTA16) { + if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0) { + RIODefaultName(p, HostP, entry); + FillSlot(entry, entry2, RtaUniq, HostP); + EmptySlot = 0; + } + } else { + if (RIOFindFreeID(p, HostP, &entry, NULL) == 0) { + RIODefaultName(p, HostP, entry); + FillSlot(entry, 0, RtaUniq, HostP); + EmptySlot = 0; + } } /* - ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA - ** attached to the current host card in the driver table. - ** - ** If we found a SLOT_IN_USE entry on another host for this - ** RTA in the config or driver table, and there are enough free - ** slots in the driver table, then we need to move it over and - ** delete it from the other host. - ** If we found a SLOT_TENTATIVE entry on another host for this - ** RTA in the driver table, just delete the other host entry. - */ - if (EmptySlot == 0) - { - if ( MapP ) - { - if (Flag & SLOT_IN_USE) - { - rio_dprintk (RIO_DEBUG_BOOT, - "This RTA configured on another host - move entry to current host (1)\n"); - HostP->Mapping[entry].SysPort = MapP->SysPort; - CCOPY( MapP->Name, HostP->Mapping[entry].Name, MAX_NAME_LEN ); - HostP->Mapping[entry].Flags = - SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT; + ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA + ** attached to the current host card in the driver table. + ** + ** If we found a SLOT_IN_USE entry on another host for this + ** RTA in the config or driver table, and there are enough free + ** slots in the driver table, then we need to move it over and + ** delete it from the other host. + ** If we found a SLOT_TENTATIVE entry on another host for this + ** RTA in the driver table, just delete the other host entry. + */ + if (EmptySlot == 0) { + if (MapP) { + if (Flag & SLOT_IN_USE) { + rio_dprintk(RIO_DEBUG_BOOT, "This RTA configured on another host - move entry to current host (1)\n"); + HostP->Mapping[entry].SysPort = MapP->SysPort; + CCOPY(MapP->Name, HostP->Mapping[entry].Name, MAX_NAME_LEN); + HostP->Mapping[entry].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT; #ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry]); + RIO_SV_BROADCAST(HostP->svFlags[entry]); #endif - RIOReMapPorts( p, HostP, &HostP->Mapping[entry] ); - if ( HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted ) - p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort; - if ( HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted ) - p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort; - rio_dprintk (RIO_DEBUG_BOOT, "SysPort %d, Name %s\n",(int)MapP->SysPort,MapP->Name); - } - else - { - rio_dprintk (RIO_DEBUG_BOOT, - "This RTA has a tentative entry on another host - delete that entry (1)\n"); - HostP->Mapping[entry].Flags = - SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT; + RIOReMapPorts(p, HostP, &HostP->Mapping[entry]); + if (HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted) + p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort; + if (HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted) + p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort; + rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) MapP->SysPort, MapP->Name); + } else { + rio_dprintk(RIO_DEBUG_BOOT, "This RTA has a tentative entry on another host - delete that entry (1)\n"); + HostP->Mapping[entry].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT; #ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry]); + RIO_SV_BROADCAST(HostP->svFlags[entry]); #endif - } - if (RtaType == TYPE_RTA16) - { - if (Flag & SLOT_IN_USE) - { - HostP->Mapping[entry2].Flags = SLOT_IN_USE | - RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; + } + if (RtaType == TYPE_RTA16) { + if (Flag & SLOT_IN_USE) { + HostP->Mapping[entry2].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; #ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry2]); + RIO_SV_BROADCAST(HostP->svFlags[entry2]); #endif - HostP->Mapping[entry2].SysPort = MapP2->SysPort; - /* - ** Map second block of ttys for 16 port RTA - */ - RIOReMapPorts( p, HostP, &HostP->Mapping[entry2] ); - if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted) - p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort; - if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted) - p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort; - rio_dprintk (RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", - (int)HostP->Mapping[entry2].SysPort, - HostP->Mapping[entry].Name); - } - else - HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | - RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; + HostP->Mapping[entry2].SysPort = MapP2->SysPort; + /* + ** Map second block of ttys for 16 port RTA + */ + RIOReMapPorts(p, HostP, &HostP->Mapping[entry2]); + if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted) + p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort; + if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted) + p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort; + rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) HostP->Mapping[entry2].SysPort, HostP->Mapping[entry].Name); + } else + HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; #ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry2]); + RIO_SV_BROADCAST(HostP->svFlags[entry2]); #endif - bzero( (caddr_t)MapP2, sizeof(struct Map) ); - } - bzero( (caddr_t)MapP, sizeof(struct Map) ); - if (! p->RIONoMessage) - cprintf("An orphaned RTA has been adopted by %s '%s' (%c).\n",MyType,MyName,MyLink+'A'); - } - else if (! p->RIONoMessage) - cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType,MyName,MyLink+'A'); - RIOSetChange(p); - return TRUE; + bzero((caddr_t) MapP2, sizeof(struct Map)); + } + bzero((caddr_t) MapP, sizeof(struct Map)); + if (!p->RIONoMessage) + cprintf("An orphaned RTA has been adopted by %s '%s' (%c).\n", MyType, MyName, MyLink + 'A'); + } else if (!p->RIONoMessage) + cprintf("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); + RIOSetChange(p); + return TRUE; } /* - ** There is no room in the driver table to make an entry for the - ** booted RTA. Keep a note of its Uniq Num in the overflow table, - ** so we can ignore it's ID requests. - */ - if (! p->RIONoMessage) - cprintf("The RTA connected to %s '%s' (%c) cannot be configured. You cannot configure more than 128 ports to one host card.\n",MyType,MyName,MyLink+'A'); - for ( entry=0; entryNumExtraBooted; entry++ ) - { - if ( HostP->ExtraUnits[entry] == RtaUniq ) - { - /* - ** already got it! - */ - return TRUE; - } + ** There is no room in the driver table to make an entry for the + ** booted RTA. Keep a note of its Uniq Num in the overflow table, + ** so we can ignore it's ID requests. + */ + if (!p->RIONoMessage) + cprintf("The RTA connected to %s '%s' (%c) cannot be configured. You cannot configure more than 128 ports to one host card.\n", MyType, MyName, MyLink + 'A'); + for (entry = 0; entry < HostP->NumExtraBooted; entry++) { + if (HostP->ExtraUnits[entry] == RtaUniq) { + /* + ** already got it! + */ + return TRUE; + } } /* - ** If there is room, add the unit to the list of extras - */ - if ( HostP->NumExtraBooted < MAX_EXTRA_UNITS ) - HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq; + ** If there is room, add the unit to the list of extras + */ + if (HostP->NumExtraBooted < MAX_EXTRA_UNITS) + HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq; return TRUE; } @@ -1226,25 +1127,20 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st ** We no longer support the RIOBootMode variable. It is all done from the ** "boot/noboot" field in the rio.cf file. */ -int -RIOBootOk(p, HostP, RtaUniq) -struct rio_info * p; -struct Host * HostP; +int RIOBootOk(p, HostP, RtaUniq) +struct rio_info *p; +struct Host *HostP; ulong RtaUniq; { - int Entry; - uint HostUniq = HostP->UniqueNum; + int Entry; + uint HostUniq = HostP->UniqueNum; /* - ** Search bindings table for RTA or its parent. - ** If it exists, return 0, else 1. - */ - for (Entry = 0; - ( Entry < MAX_RTA_BINDINGS ) && ( p->RIOBindTab[Entry] != 0 ); - Entry++) - { - if ( (p->RIOBindTab[Entry] == HostUniq) || - (p->RIOBindTab[Entry] == RtaUniq) ) + ** Search bindings table for RTA or its parent. + ** If it exists, return 0, else 1. + */ + for (Entry = 0; (Entry < MAX_RTA_BINDINGS) && (p->RIOBindTab[Entry] != 0); Entry++) { + if ((p->RIOBindTab[Entry] == HostUniq) || (p->RIOBindTab[Entry] == RtaUniq)) return 0; } return 1; @@ -1255,16 +1151,15 @@ ulong RtaUniq; ** slots tentative, and the second one RTA_SECOND_SLOT as well. */ -void -FillSlot(entry, entry2, RtaUniq, HostP) +void FillSlot(entry, entry2, RtaUniq, HostP) int entry; int entry2; uint RtaUniq; struct Host *HostP; { - int link; + int link; - rio_dprintk (RIO_DEBUG_BOOT, "FillSlot(%d, %d, 0x%x...)\n", entry, entry2, RtaUniq); + rio_dprintk(RIO_DEBUG_BOOT, "FillSlot(%d, %d, 0x%x...)\n", entry, entry2, RtaUniq); HostP->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE); HostP->Mapping[entry].SysPort = NO_PORT; @@ -1273,8 +1168,7 @@ struct Host *HostP; HostP->Mapping[entry].ID = entry + 1; HostP->Mapping[entry].ID2 = 0; if (entry2) { - HostP->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | - SLOT_TENTATIVE | RTA16_SECOND_SLOT); + HostP->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE | RTA16_SECOND_SLOT); HostP->Mapping[entry2].SysPort = NO_PORT; HostP->Mapping[entry2].RtaUniqueNum = RtaUniq; HostP->Mapping[entry2].HostUniqueNum = HostP->UniqueNum; @@ -1284,10 +1178,10 @@ struct Host *HostP; HostP->Mapping[entry].ID2 = entry2 + 1; } /* - ** Must set these up, so that utilities show - ** topology of 16 port RTAs correctly - */ - for ( link=0; linkMapping[entry].Topology[link].Unit = ROUTE_DISCONNECT; HostP->Mapping[entry].Topology[link].Link = NO_LINK; if (entry2) { @@ -1296,4 +1190,3 @@ struct Host *HostP; } } } - -- cgit v1.2.3-59-g8ed1b From b6c6b6021ec735bd105e130ac1ee1606575f74c3 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 24 Mar 2006 03:18:26 -0800 Subject: [PATCH] rioboot: post-Lindent After the indent we can now clean up unused code, and fix all myriad cases that don't use readb/writeb properly. Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/rio/rioboot.c | 429 +++++++++++++++++++-------------------------- 1 file changed, 177 insertions(+), 252 deletions(-) (limited to 'drivers') diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c index 9a96fc644e52..e1542e8dfb43 100644 --- a/drivers/char/rio/rioboot.c +++ b/drivers/char/rio/rioboot.c @@ -30,25 +30,19 @@ ** ----------------------------------------------------------------------------- */ -#ifdef SCCS_LABELS -static char *_rioboot_c_sccs_ = "@(#)rioboot.c 1.3"; -#endif - #include #include +#include +#include +#include +#include #include #include +#include #include #include #include -#include - - -#include -#include - -#include - +#include #include "linux_compat.h" @@ -80,9 +74,9 @@ static char *_rioboot_c_sccs_ = "@(#)rioboot.c 1.3"; #include "cmdblk.h" #include "route.h" -static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP); +static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd *PktCmdP); -static uchar RIOAtVec2Ctrl[] = { +static const unsigned char RIOAtVec2Ctrl[] = { /* 0 */ INTERRUPT_DISABLE, /* 1 */ INTERRUPT_DISABLE, /* 2 */ INTERRUPT_DISABLE, @@ -101,22 +95,22 @@ static uchar RIOAtVec2Ctrl[] = { /* 15 */ IRQ_15 | INTERRUPT_ENABLE }; -/* -** Load in the RTA boot code. -*/ -int RIOBootCodeRTA(p, rbp) -struct rio_info *p; -struct DownLoad *rbp; +/** + * RIOBootCodeRTA - Load RTA boot code + * @p: RIO to load + * @rbp: Download descriptor + * + * Called when the user process initiates booting of the card firmware. + * Lads the firmware + */ + +int RIOBootCodeRTA(struct rio_info *p, struct DownLoad * rbp) { int offset; func_enter(); - /* Linux doesn't allow you to disable interrupts during a - "copyin". (Crash when a pagefault occurs). */ - /* disable(oldspl); */ - - rio_dprintk(RIO_DEBUG_BOOT, "Data at user address 0x%x\n", (int) rbp->DataP); + rio_dprintk(RIO_DEBUG_BOOT, "Data at user address %p\n", rbp->DataP); /* ** Check that we have set asside enough memory for this @@ -124,7 +118,6 @@ struct DownLoad *rbp; if (rbp->Count > SIXTY_FOUR_K) { rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n"); p->RIOError.Error = HOST_FILE_TOO_LARGE; - /* restore(oldspl); */ func_exit(); return -ENOMEM; } @@ -132,7 +125,6 @@ struct DownLoad *rbp; if (p->RIOBooting) { rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n"); p->RIOError.Error = BOOT_IN_PROGRESS; - /* restore(oldspl); */ func_exit(); return -EBUSY; } @@ -149,16 +141,15 @@ struct DownLoad *rbp; ** because it will (eventually) be part of the Rta run time environment ** and so should be zeroed. */ - bzero((caddr_t) p->RIOBootPackets, offset); + memset(p->RIOBootPackets, 0, offset); /* - ** Copy the data from user space. + ** Copy the data from user space into the array */ - if (copyin((int) rbp->DataP, ((caddr_t) (p->RIOBootPackets)) + offset, rbp->Count) == COPYFAIL) { + if (copy_from_user(((u8 *)p->RIOBootPackets) + offset, rbp->DataP, rbp->Count)) { rio_dprintk(RIO_DEBUG_BOOT, "Bad data copy from user space\n"); p->RIOError.Error = COPYIN_FAILED; - /* restore(oldspl); */ func_exit(); return -EFAULT; } @@ -170,40 +161,25 @@ struct DownLoad *rbp; p->RIONumBootPkts = (rbp->Count + offset) / RTA_BOOT_DATA_SIZE; p->RIOBootCount = rbp->Count; - /* restore(oldspl); */ func_exit(); return 0; } +/** + * rio_start_card_running - host card start + * @HostP: The RIO to kick off + * + * Start a RIO processor unit running. Encapsulates the knowledge + * of the card type. + */ + void rio_start_card_running(struct Host *HostP) { - func_enter(); - switch (HostP->Type) { case RIO_AT: rio_dprintk(RIO_DEBUG_BOOT, "Start ISA card running\n"); - WBYTE(HostP->Control, BOOT_FROM_RAM | EXTERNAL_BUS_ON | HostP->Mode | RIOAtVec2Ctrl[HostP->Ivec & 0xF]); - break; - -#ifdef FUTURE_RELEASE - case RIO_MCA: - /* - ** MCA handles IRQ vectors differently, so we don't write - ** them to this register. - */ - rio_dprintk(RIO_DEBUG_BOOT, "Start MCA card running\n"); - WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode); - break; - - case RIO_EISA: - /* - ** EISA is totally different and expects OUTBZs to turn it on. - */ - rio_dprintk(RIO_DEBUG_BOOT, "Start EISA card running\n"); - OUTBZ(HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM); + writeb(BOOT_FROM_RAM | EXTERNAL_BUS_ON | HostP->Mode | RIOAtVec2Ctrl[HostP->Ivec & 0xF], &HostP->Control); break; -#endif - case RIO_PCI: /* ** PCI is much the same as MCA. Everything is once again memory @@ -211,16 +187,12 @@ void rio_start_card_running(struct Host *HostP) ** ports. */ rio_dprintk(RIO_DEBUG_BOOT, "Start PCI card running\n"); - WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode); + writeb(PCITpBootFromRam | PCITpBusEnable | HostP->Mode, &HostP->Control); break; default: rio_dprintk(RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type); break; } -/* - printk (KERN_INFO "Done with starting the card\n"); - func_exit (); -*/ return; } @@ -231,40 +203,41 @@ void rio_start_card_running(struct Host *HostP) ** Put your rubber pants on before messing with this code - even the magic ** numbers have trouble understanding what they are doing here. */ -int RIOBootCodeHOST(p, rbp) -struct rio_info *p; -register struct DownLoad *rbp; + +int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp) { - register struct Host *HostP; - register caddr_t Cad; - register PARM_MAP *ParmMapP; - register int RupN; + struct Host *HostP; + u8 *Cad; + PARM_MAP *ParmMapP; + int RupN; int PortN; - uint host; - caddr_t StartP; - BYTE *DestP; + unsigned int host; + u8 *StartP; + u8 *DestP; int wait_count; - ushort OldParmMap; - ushort offset; /* It is very important that this is a ushort */ - /* uint byte; */ - caddr_t DownCode = NULL; + u16 OldParmMap; + u16 offset; /* It is very important that this is a u16 */ + u8 *DownCode = NULL; unsigned long flags; HostP = NULL; /* Assure the compiler we've initialized it */ + + + /* Walk the hosts */ for (host = 0; host < p->RIONumHosts; host++) { rio_dprintk(RIO_DEBUG_BOOT, "Attempt to boot host %d\n", host); HostP = &p->RIOHosts[host]; rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec); - + /* Don't boot hosts already running */ if ((HostP->Flags & RUN_STATE) != RC_WAITING) { rio_dprintk(RIO_DEBUG_BOOT, "%s %d already running\n", "Host", host); continue; } /* - ** Grab a 32 bit pointer to the card. + ** Grab a pointer to the card (ioremapped) */ Cad = HostP->Caddr; @@ -274,13 +247,14 @@ register struct DownLoad *rbp; ** Therefore, we need to start copying at address ** (caddr+p->RIOConf.HostLoadBase-rbp->Count) */ - StartP = (caddr_t) & Cad[p->RIOConf.HostLoadBase - rbp->Count]; + StartP = &Cad[p->RIOConf.HostLoadBase - rbp->Count]; - rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for host is 0x%x\n", (int) Cad); - rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for download is 0x%x\n", (int) StartP); + rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for host is %p\n", Cad); + rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for download is %p\n", StartP); rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase); rio_dprintk(RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count); + /* Make sure it fits */ if (p->RIOConf.HostLoadBase < rbp->Count) { rio_dprintk(RIO_DEBUG_BOOT, "Bin too large\n"); p->RIOError.Error = HOST_FILE_TOO_LARGE; @@ -300,39 +274,23 @@ register struct DownLoad *rbp; */ rio_dprintk(RIO_DEBUG_BOOT, "Copy in code\n"); - /* - ** PCI hostcard can't cope with 32 bit accesses and so need to copy - ** data to a local buffer, and then dripfeed the card. - */ - if (HostP->Type == RIO_PCI) { - /* int offset; */ - - DownCode = sysbrk(rbp->Count); - if (!DownCode) { - rio_dprintk(RIO_DEBUG_BOOT, "No system memory available\n"); - p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY; - func_exit(); - return -ENOMEM; - } - bzero(DownCode, rbp->Count); - - if (copyin((int) rbp->DataP, DownCode, rbp->Count) == COPYFAIL) { - rio_dprintk(RIO_DEBUG_BOOT, "Bad copyin of host data\n"); - sysfree(DownCode, rbp->Count); - p->RIOError.Error = COPYIN_FAILED; - func_exit(); - return -EFAULT; - } - - HostP->Copy(DownCode, StartP, rbp->Count); + /* Buffer to local memory as we want to use I/O space and + some cards only do 8 or 16 bit I/O */ - sysfree(DownCode, rbp->Count); - } else if (copyin((int) rbp->DataP, StartP, rbp->Count) == COPYFAIL) { - rio_dprintk(RIO_DEBUG_BOOT, "Bad copyin of host data\n"); + DownCode = vmalloc(rbp->Count); + if (!DownCode) { + p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY; + func_exit(); + return -ENOMEM; + } + if (copy_from_user(rbp->DataP, DownCode, rbp->Count)) { + kfree(DownCode); p->RIOError.Error = COPYIN_FAILED; func_exit(); return -EFAULT; } + HostP->Copy(DownCode, StartP, rbp->Count); + vfree(DownCode); rio_dprintk(RIO_DEBUG_BOOT, "Copy completed\n"); @@ -411,7 +369,7 @@ register struct DownLoad *rbp; ** a short branch to 0x7FF8, where a long branch is coded. */ - DestP = (BYTE *) & Cad[0x7FF8]; /* <<<---- READ THE ABOVE COMMENTS */ + DestP = (u8 *) &Cad[0x7FF8]; /* <<<---- READ THE ABOVE COMMENTS */ #define NFIX(N) (0x60 | (N)) /* .O = (~(.O + N))<<4 */ #define PFIX(N) (0x20 | (N)) /* .O = (.O + N)<<4 */ @@ -427,13 +385,14 @@ register struct DownLoad *rbp; ** cos I don't understand 2's complement). */ offset = (p->RIOConf.HostLoadBase - 2) - 0x7FFC; - WBYTE(DestP[0], NFIX(((ushort) (~offset) >> (ushort) 12) & 0xF)); - WBYTE(DestP[1], PFIX((offset >> 8) & 0xF)); - WBYTE(DestP[2], PFIX((offset >> 4) & 0xF)); - WBYTE(DestP[3], JUMP(offset & 0xF)); - WBYTE(DestP[6], NFIX(0)); - WBYTE(DestP[7], JUMP(8)); + writeb(NFIX(((ushort) (~offset) >> (ushort) 12) & 0xF), DestP); + writeb(PFIX((offset >> 8) & 0xF), DestP + 1); + writeb(PFIX((offset >> 4) & 0xF), DestP + 2); + writeb(JUMP(offset & 0xF), DestP + 3); + + writeb(NFIX(0), DestP + 6); + writeb(JUMP(8), DestP + 7); rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase); rio_dprintk(RIO_DEBUG_BOOT, "startup offset is 0x%x\n", offset); @@ -448,7 +407,7 @@ register struct DownLoad *rbp; ** Grab a copy of the current ParmMap pointer, so we ** can tell when it has changed. */ - OldParmMap = RWORD(HostP->__ParmMapR); + OldParmMap = readw(&HostP->__ParmMapR); rio_dprintk(RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n", OldParmMap); @@ -467,9 +426,9 @@ register struct DownLoad *rbp; ** Now, wait for upto five seconds for the Tp to setup the parmmap ** pointer: */ - for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && (RWORD(HostP->__ParmMapR) == OldParmMap); wait_count++) { - rio_dprintk(RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n", wait_count, RWORD(HostP->__ParmMapR)); - delay(HostP, HUNDRED_MS); + for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && (readw(&HostP->__ParmMapR) == OldParmMap); wait_count++) { + rio_dprintk(RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n", wait_count, readw(&HostP->__ParmMapR)); + mdelay(100); } @@ -477,15 +436,16 @@ register struct DownLoad *rbp; ** If the parmmap pointer is unchanged, then the host code ** has crashed & burned in a really spectacular way */ - if (RWORD(HostP->__ParmMapR) == OldParmMap) { - rio_dprintk(RIO_DEBUG_BOOT, "parmmap 0x%x\n", RWORD(HostP->__ParmMapR)); + if (readw(&HostP->__ParmMapR) == OldParmMap) { + rio_dprintk(RIO_DEBUG_BOOT, "parmmap 0x%x\n", readw(&HostP->__ParmMapR)); rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n"); HostP->Flags &= ~RUN_STATE; HostP->Flags |= RC_STUFFED; - RIOHostReset(HostP->Type, (struct DpRam *) HostP->CardP, HostP->Slot); - continue} + RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot ); + continue; + } - rio_dprintk(RIO_DEBUG_BOOT, "Running 0x%x\n", RWORD(HostP->__ParmMapR)); + rio_dprintk(RIO_DEBUG_BOOT, "Running 0x%x\n", readw(&HostP->__ParmMapR)); /* ** Well, the board thought it was OK, and setup its parmmap @@ -496,25 +456,26 @@ register struct DownLoad *rbp; /* ** Grab a 32 bit pointer to the parmmap structure */ - ParmMapP = (PARM_MAP *) RIO_PTR(Cad, RWORD(HostP->__ParmMapR)); - rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int) ParmMapP); - ParmMapP = (PARM_MAP *) ((unsigned long) Cad + (unsigned long) ((RWORD((HostP->__ParmMapR))) & 0xFFFF)); - rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int) ParmMapP); + ParmMapP = (PARM_MAP *) RIO_PTR(Cad, readw(&HostP->__ParmMapR)); + rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP); + ParmMapP = (PARM_MAP *) ((unsigned long) Cad + readw(&HostP->__ParmMapR)); + rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP); /* ** The links entry should be 0xFFFF; we set it up ** with a mask to say how many PHBs to use, and ** which links to use. */ - if ((RWORD(ParmMapP->links) & 0xFFFF) != 0xFFFF) { + if (readw(&ParmMapP->links) != 0xFFFF) { rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); - rio_dprintk(RIO_DEBUG_BOOT, "Links = 0x%x\n", RWORD(ParmMapP->links)); + rio_dprintk(RIO_DEBUG_BOOT, "Links = 0x%x\n", readw(&ParmMapP->links)); HostP->Flags &= ~RUN_STATE; HostP->Flags |= RC_STUFFED; - RIOHostReset(HostP->Type, (struct DpRam *) HostP->CardP, HostP->Slot); - continue} + RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot ); + continue; + } - WWORD(ParmMapP->links, RIO_LINK_ENABLE); + writew(RIO_LINK_ENABLE, &ParmMapP->links); /* ** now wait for the card to set all the parmmap->XXX stuff @@ -522,19 +483,20 @@ register struct DownLoad *rbp; */ rio_dprintk(RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n", p->RIOConf.StartupTime); HostP->timeout_id = 0; - for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && !RWORD(ParmMapP->init_done); wait_count++) { + for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && !readw(&ParmMapP->init_done); wait_count++) { rio_dprintk(RIO_DEBUG_BOOT, "Waiting for init_done\n"); - delay(HostP, HUNDRED_MS); + mdelay(100); } rio_dprintk(RIO_DEBUG_BOOT, "OK! init_done!\n"); - if (RWORD(ParmMapP->error) != E_NO_ERROR || !RWORD(ParmMapP->init_done)) { + if (readw(&ParmMapP->error) != E_NO_ERROR || !readw(&ParmMapP->init_done)) { rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); rio_dprintk(RIO_DEBUG_BOOT, "Timedout waiting for init_done\n"); HostP->Flags &= ~RUN_STATE; HostP->Flags |= RC_STUFFED; - RIOHostReset(HostP->Type, (struct DpRam *) HostP->CardP, HostP->Slot); - continue} + RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot ); + continue; + } rio_dprintk(RIO_DEBUG_BOOT, "Got init_done\n"); @@ -546,17 +508,17 @@ register struct DownLoad *rbp; /* ** set the time period between interrupts. */ - WWORD(ParmMapP->timer, (short) p->RIOConf.Timer); + writew(p->RIOConf.Timer, &ParmMapP->timer); /* ** Translate all the 16 bit pointers in the __ParmMapR into - ** 32 bit pointers for the driver. + ** 32 bit pointers for the driver in ioremap space. */ HostP->ParmMapP = ParmMapP; - HostP->PhbP = (PHB *) RIO_PTR(Cad, RWORD(ParmMapP->phb_ptr)); - HostP->RupP = (RUP *) RIO_PTR(Cad, RWORD(ParmMapP->rups)); - HostP->PhbNumP = (ushort *) RIO_PTR(Cad, RWORD(ParmMapP->phb_num_ptr)); - HostP->LinkStrP = (LPB *) RIO_PTR(Cad, RWORD(ParmMapP->link_str_ptr)); + HostP->PhbP = (PHB *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr)); + HostP->RupP = (RUP *) RIO_PTR(Cad, readw(&ParmMapP->rups)); + HostP->PhbNumP = (ushort *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr)); + HostP->LinkStrP = (LPB *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr)); /* ** point the UnixRups at the real Rups @@ -592,12 +554,12 @@ register struct DownLoad *rbp; PortP->PhbP = PhbP; - PortP->TxAdd = (WORD *) RIO_PTR(Cad, RWORD(PhbP->tx_add)); - PortP->TxStart = (WORD *) RIO_PTR(Cad, RWORD(PhbP->tx_start)); - PortP->TxEnd = (WORD *) RIO_PTR(Cad, RWORD(PhbP->tx_end)); - PortP->RxRemove = (WORD *) RIO_PTR(Cad, RWORD(PhbP->rx_remove)); - PortP->RxStart = (WORD *) RIO_PTR(Cad, RWORD(PhbP->rx_start)); - PortP->RxEnd = (WORD *) RIO_PTR(Cad, RWORD(PhbP->rx_end)); + PortP->TxAdd = (u16 *) RIO_PTR(Cad, readw(&PhbP->tx_add)); + PortP->TxStart = (u16 *) RIO_PTR(Cad, readw(&PhbP->tx_start)); + PortP->TxEnd = (u16 *) RIO_PTR(Cad, readw(&PhbP->tx_end)); + PortP->RxRemove = (u16 *) RIO_PTR(Cad, readw(&PhbP->rx_remove)); + PortP->RxStart = (u16 *) RIO_PTR(Cad, readw(&PhbP->rx_start)); + PortP->RxEnd = (u16 *) RIO_PTR(Cad, readw(&PhbP->rx_end)); rio_spin_unlock_irqrestore(&PortP->portSem, flags); /* @@ -631,20 +593,23 @@ register struct DownLoad *rbp; -/* -** Boot an RTA. If we have successfully processed this boot, then -** return 1. If we havent, then return 0. -*/ -int RIOBootRup(p, Rup, HostP, PacketP) -struct rio_info *p; -uint Rup; -struct Host *HostP; -struct PKT *PacketP; +/** + * RIOBootRup - Boot an RTA + * @p: rio we are working with + * @Rup: Rup number + * @HostP: host object + * @PacketP: packet to use + * + * If we have successfully processed this boot, then + * return 1. If we havent, then return 0. + */ + +int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT *PacketP) { struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data; struct PktCmd_M *PktReplyP; struct CmdBlk *CmdBlkP; - uint sequence; + unsigned int sequence; /* ** If we haven't been told what to boot, we can't boot it. @@ -654,20 +619,17 @@ struct PKT *PacketP; return 0; } - /* rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_BOOT,"Incoming command packet\n"); */ - /* ShowPacket( DBG_BOOT, PacketP ); */ - /* ** Special case of boot completed - if we get one of these then we ** don't need a command block. For all other cases we do, so handle ** this first and then get a command block, then handle every other ** case, relinquishing the command block if disaster strikes! */ - if ((RBYTE(PacketP->len) & PKT_CMD_BIT) && (RBYTE(PktCmdP->Command) == BOOT_COMPLETED)) + if ((readb(&PacketP->len) & PKT_CMD_BIT) && (readb(&PktCmdP->Command) == BOOT_COMPLETED)) return RIOBootComplete(p, HostP, Rup, PktCmdP); /* - ** try to unhook a command block from the command free list. + ** Try to allocate a command block. This is in kernel space */ if (!(CmdBlkP = RIOGetCmdBlk())) { rio_dprintk(RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n"); @@ -688,13 +650,12 @@ struct PKT *PacketP; /* ** process COMMANDS on the boot rup! */ - if (RBYTE(PacketP->len) & PKT_CMD_BIT) { + if (readb(&PacketP->len) & PKT_CMD_BIT) { /* ** We only expect one type of command - a BOOT_REQUEST! */ - if (RBYTE(PktCmdP->Command) != BOOT_REQUEST) { - rio_dprintk(RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %d\n", PktCmdP->Command, Rup, HostP - p->RIOHosts); - ShowPacket(DBG_BOOT, PacketP); + if (readb(&PktCmdP->Command) != BOOT_REQUEST) { + rio_dprintk(RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %Zd\n", readb(&PktCmdP->Command), Rup, HostP - p->RIOHosts); RIOFreeCmdBlk(CmdBlkP); return 1; } @@ -702,20 +663,9 @@ struct PKT *PacketP; /* ** Build a Boot Sequence command block ** - ** 02.03.1999 ARG - ESIL 0820 fix ** We no longer need to use "Boot Mode", we'll always allow ** boot requests - the boot will not complete if the device ** appears in the bindings table. - ** So, this conditional is not required ... - ** - if (p->RIOBootMode == RC_BOOT_NONE) - ** - ** If the system is in slave mode, and a boot request is - ** received, set command to BOOT_ABORT so that the boot - ** will not complete. - ** - PktReplyP->Command = BOOT_ABORT; - else ** ** We'll just (always) set the command field in packet reply ** to allow an attempted boot sequence : @@ -728,9 +678,9 @@ struct PKT *PacketP; CmdBlkP->Packet.len = BOOT_SEQUENCE_LEN | PKT_CMD_BIT; - bcopy("BOOT", (void *) &CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN], 4); + memcpy((void *) &CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN], "BOOT", 4); - rio_dprintk(RIO_DEBUG_BOOT, "Boot RTA on Host %d Rup %d - %d (0x%x) packets to 0x%x\n", HostP - p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, p->RIOConf.RtaLoadBase); + rio_dprintk(RIO_DEBUG_BOOT, "Boot RTA on Host %Zd Rup %d - %d (0x%x) packets to 0x%x\n", HostP - p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, p->RIOConf.RtaLoadBase); /* ** If this host is in slave mode, send the RTA an invalid boot @@ -747,32 +697,35 @@ struct PKT *PacketP; /* ** It is a request for boot data. */ - sequence = RWORD(PktCmdP->Sequence); + sequence = readw(&PktCmdP->Sequence); - rio_dprintk(RIO_DEBUG_BOOT, "Boot block %d on Host %d Rup%d\n", sequence, HostP - p->RIOHosts, Rup); + rio_dprintk(RIO_DEBUG_BOOT, "Boot block %d on Host %Zd Rup%d\n", sequence, HostP - p->RIOHosts, Rup); if (sequence >= p->RIONumBootPkts) { rio_dprintk(RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, p->RIONumBootPkts); - ShowPacket(DBG_BOOT, PacketP); } PktReplyP->Sequence = sequence; - - bcopy(p->RIOBootPackets[p->RIONumBootPkts - sequence - 1], PktReplyP->BootData, RTA_BOOT_DATA_SIZE); - + memcpy(PktReplyP->BootData, p->RIOBootPackets[p->RIONumBootPkts - sequence - 1], RTA_BOOT_DATA_SIZE); CmdBlkP->Packet.len = PKT_MAX_DATA_LEN; - ShowPacket(DBG_BOOT, &CmdBlkP->Packet); RIOQueueCmdBlk(HostP, Rup, CmdBlkP); return 1; } -/* -** This function is called when an RTA been booted. -** If booted by a host, HostP->HostUniqueNum is the booting host. -** If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA. -** RtaUniq is the booted RTA. -*/ -static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP) +/** + * RIOBootComplete - RTA boot is done + * @p: RIO we are working with + * @HostP: Host structure + * @Rup: RUP being used + * @PktCmdP: Packet command that was used + * + * This function is called when an RTA been booted. + * If booted by a host, HostP->HostUniqueNum is the booting host. + * If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA. + * RtaUniq is the booted RTA. + */ + +static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd *PktCmdP) { struct Map *MapP = NULL; struct Map *MapP2 = NULL; @@ -782,12 +735,10 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str int EmptySlot = -1; int entry, entry2; char *MyType, *MyName; - uint MyLink; - ushort RtaType; - uint RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) + (RBYTE(PktCmdP->UniqNum[1]) << 8) + (RBYTE(PktCmdP->UniqNum[2]) << 16) + (RBYTE(PktCmdP->UniqNum[3]) << 24); + unsigned int MyLink; + unsigned short RtaType; + u32 RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24); - /* Was RIOBooting-- . That's bad. If an RTA sends two of them, the - driver will never think that the RTA has booted... -- REW */ p->RIOBooting = 0; rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting); @@ -795,16 +746,16 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str /* ** Determine type of unit (16/8 port RTA). */ + RtaType = GetUnitType(RtaUniq); - if (Rup >= (ushort) MAX_RUP) { - rio_dprintk(RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", HostP->Name, 8 * RtaType, RBYTE(PktCmdP->LinkNum) + 'A'); - } else { - rio_dprintk(RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", HostP->Mapping[Rup].Name, 8 * RtaType, RBYTE(PktCmdP->LinkNum) + 'A'); - } + if (Rup >= (ushort) MAX_RUP) + rio_dprintk(RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", HostP->Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A'); + else + rio_dprintk(RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", HostP->Mapping[Rup].Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A'); rio_dprintk(RIO_DEBUG_BOOT, "UniqNum is 0x%x\n", RtaUniq); - if ((RtaUniq == 0x00000000) || (RtaUniq == 0xffffffff)) { + if (RtaUniq == 0x00000000 || RtaUniq == 0xffffffff) { rio_dprintk(RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n"); return TRUE; } @@ -814,9 +765,10 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str ** system, or the system is in slave mode, do not attempt to create ** a new table entry for it. */ + if (!RIOBootOk(p, HostP, RtaUniq)) { - MyLink = RBYTE(PktCmdP->LinkNum); - if (Rup < (ushort) MAX_RUP) { + MyLink = readb(&PktCmdP->LinkNum); + if (Rup < (unsigned short) MAX_RUP) { /* ** RtaUniq was clone booted (by this RTA). Instruct this RTA ** to hold off further attempts to boot on this link for 30 @@ -825,14 +777,13 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink)) { rio_dprintk(RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n", 'A' + MyLink); } - } else { + } else /* ** RtaUniq was booted by this host. Set the booting link ** to hold off for 30 seconds to give another unit a ** chance to boot it. */ - WWORD(HostP->LinkStrP[MyLink].WaitNoBoot, 30); - } + writew(30, &HostP->LinkStrP[MyLink].WaitNoBoot); rio_dprintk(RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum); return TRUE; } @@ -849,13 +800,10 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str ** unit. */ for (entry = 0; entry < MAX_RUP; entry++) { - uint sysport; + unsigned int sysport; if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) { HostP->Mapping[entry].Flags |= RTA_BOOTED | RTA_NEWBOOT; -#ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry]); -#endif if ((sysport = HostP->Mapping[entry].SysPort) != NO_PORT) { if (sysport < p->RIOFirstPortsBooted) p->RIOFirstPortsBooted = sysport; @@ -867,9 +815,6 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str if (RtaType == TYPE_RTA16) { entry2 = HostP->Mapping[entry].ID2 - 1; HostP->Mapping[entry2].Flags |= RTA_BOOTED | RTA_NEWBOOT; -#ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry2]); -#endif sysport = HostP->Mapping[entry2].SysPort; if (sysport < p->RIOFirstPortsBooted) p->RIOFirstPortsBooted = sysport; @@ -877,18 +822,17 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str p->RIOLastPortsBooted = sysport; } } - if (RtaType == TYPE_RTA16) { + if (RtaType == TYPE_RTA16) rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", entry + 1, entry2 + 1); - } else { + else rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given ID %d\n", entry + 1); - } return TRUE; } } rio_dprintk(RIO_DEBUG_BOOT, "RTA not configured for this host\n"); - if (Rup >= (ushort) MAX_RUP) { + if (Rup >= (unsigned short) MAX_RUP) { /* ** It was a host that did the booting */ @@ -901,7 +845,7 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str MyType = "RTA"; MyName = HostP->Mapping[Rup].Name; } - MyLink = RBYTE(PktCmdP->LinkNum); + MyLink = readb(&PktCmdP->LinkNum); /* ** There is no SLOT_IN_USE entry for this RTA attached to the current @@ -923,7 +867,7 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str } else rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n", entry); if (!p->RIONoMessage) - cprintf("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); + printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); return TRUE; } } @@ -1044,11 +988,8 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str if (Flag & SLOT_IN_USE) { rio_dprintk(RIO_DEBUG_BOOT, "This RTA configured on another host - move entry to current host (1)\n"); HostP->Mapping[entry].SysPort = MapP->SysPort; - CCOPY(MapP->Name, HostP->Mapping[entry].Name, MAX_NAME_LEN); + memcpy(HostP->Mapping[entry].Name, MapP->Name, MAX_NAME_LEN); HostP->Mapping[entry].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT; -#ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry]); -#endif RIOReMapPorts(p, HostP, &HostP->Mapping[entry]); if (HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted) p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort; @@ -1058,16 +999,10 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str } else { rio_dprintk(RIO_DEBUG_BOOT, "This RTA has a tentative entry on another host - delete that entry (1)\n"); HostP->Mapping[entry].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT; -#ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry]); -#endif } if (RtaType == TYPE_RTA16) { if (Flag & SLOT_IN_USE) { HostP->Mapping[entry2].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; -#ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry2]); -#endif HostP->Mapping[entry2].SysPort = MapP2->SysPort; /* ** Map second block of ttys for 16 port RTA @@ -1080,16 +1015,13 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) HostP->Mapping[entry2].SysPort, HostP->Mapping[entry].Name); } else HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; -#ifdef NEED_TO_FIX - RIO_SV_BROADCAST(HostP->svFlags[entry2]); -#endif - bzero((caddr_t) MapP2, sizeof(struct Map)); + memset(MapP2, 0, sizeof(struct Map)); } - bzero((caddr_t) MapP, sizeof(struct Map)); + memset(MapP, 0, sizeof(struct Map)); if (!p->RIONoMessage) - cprintf("An orphaned RTA has been adopted by %s '%s' (%c).\n", MyType, MyName, MyLink + 'A'); + printk("An orphaned RTA has been adopted by %s '%s' (%c).\n", MyType, MyName, MyLink + 'A'); } else if (!p->RIONoMessage) - cprintf("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); + printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); RIOSetChange(p); return TRUE; } @@ -1100,7 +1032,7 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str ** so we can ignore it's ID requests. */ if (!p->RIONoMessage) - cprintf("The RTA connected to %s '%s' (%c) cannot be configured. You cannot configure more than 128 ports to one host card.\n", MyType, MyName, MyLink + 'A'); + printk("The RTA connected to %s '%s' (%c) cannot be configured. You cannot configure more than 128 ports to one host card.\n", MyType, MyName, MyLink + 'A'); for (entry = 0; entry < HostP->NumExtraBooted; entry++) { if (HostP->ExtraUnits[entry] == RtaUniq) { /* @@ -1127,13 +1059,10 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, uint Rup, str ** We no longer support the RIOBootMode variable. It is all done from the ** "boot/noboot" field in the rio.cf file. */ -int RIOBootOk(p, HostP, RtaUniq) -struct rio_info *p; -struct Host *HostP; -ulong RtaUniq; +int RIOBootOk(struct rio_info *p, struct Host *HostP, unsigned long RtaUniq) { int Entry; - uint HostUniq = HostP->UniqueNum; + unsigned int HostUniq = HostP->UniqueNum; /* ** Search bindings table for RTA or its parent. @@ -1151,11 +1080,7 @@ ulong RtaUniq; ** slots tentative, and the second one RTA_SECOND_SLOT as well. */ -void FillSlot(entry, entry2, RtaUniq, HostP) -int entry; -int entry2; -uint RtaUniq; -struct Host *HostP; +void FillSlot(int entry, int entry2, unsigned int RtaUniq, struct Host *HostP) { int link; -- cgit v1.2.3-59-g8ed1b From 27c6e526f34760a9c48a90112242b7165064fa85 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 24 Mar 2006 03:18:26 -0800 Subject: [PATCH] rio driver rework continued #1 More header cleanups, strip out typedefs and remove cruft. There are a lot of magic macros that can go and also a great deal of abuse of volatile that is not needed any more as this patch set cleans up the misuse of pointer access to ISA and PCI space. It now builds cleanly on 64bit, although there is more work left to do Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/rio/cmdpkt.h | 48 ++++++++++++++--------------- drivers/char/rio/daemon.h | 67 +++++++++++++++++++---------------------- drivers/char/rio/host.h | 56 +++++++++++++++++----------------- drivers/char/rio/link.h | 4 +-- drivers/char/rio/linux_compat.h | 41 +------------------------ drivers/char/rio/port.h | 2 +- drivers/char/rio/riodrvr.h | 48 ++++++++++++++--------------- drivers/char/rio/rup.h | 4 +-- drivers/char/rio/top.h | 4 +-- drivers/char/rio/typdef.h | 11 +++---- 10 files changed, 118 insertions(+), 167 deletions(-) (limited to 'drivers') diff --git a/drivers/char/rio/cmdpkt.h b/drivers/char/rio/cmdpkt.h index b6445d3f1416..357ae5722436 100644 --- a/drivers/char/rio/cmdpkt.h +++ b/drivers/char/rio/cmdpkt.h @@ -118,45 +118,45 @@ struct PktCmd_M { union { struct { struct { - uchar PcCommand; + u8 PcCommand; union { - uchar PcPhbNum; - uchar PcLinkNum; - uchar PcIDNum; + u8 PcPhbNum; + u8 PcLinkNum; + u8 PcIDNum; } U0; } CmdHdr; struct { - ushort NumPackets; - ushort LoadBase; - ushort CodeSize; + u16 NumPackets; + u16 LoadBase; + u16 CodeSize; } PcBootSequence; } S1; struct { - ushort PcSequence; - uchar PcBootData[RTA_BOOT_DATA_SIZE]; + u16 PcSequence; + u8 PcBootData[RTA_BOOT_DATA_SIZE]; } S2; struct { - ushort __crud__; - uchar PcUniqNum[4]; /* this is really a uint. */ - uchar PcModuleTypes; /* what modules are fitted */ + u16 __crud__; + u8 PcUniqNum[4]; /* this is really a uint. */ + u8 PcModuleTypes; /* what modules are fitted */ } S3; struct { - ushort __cmd_hdr__; - uchar __undefined__; - uchar PcModemStatus; - uchar PcPortStatus; - uchar PcSubCommand; - ushort PcSubAddr; - uchar PcSubData[64]; + u16 __cmd_hdr__; + u8 __undefined__; + u8 PcModemStatus; + u8 PcPortStatus; + u8 PcSubCommand; + u16 PcSubAddr; + u8 PcSubData[64]; } S4; struct { - ushort __cmd_hdr__; - uchar PcCommandText[1]; - uchar __crud__[20]; - uchar PcIDNum2; /* Tacked on end */ + u16 __cmd_hdr__; + u8 PcCommandText[1]; + u8 __crud__[20]; + u8 PcIDNum2; /* Tacked on end */ } S5; struct { - ushort __cmd_hdr__; + u16 __cmd_hdr__; struct Top Topology[LINKS_PER_UNIT]; } S6; } U1; diff --git a/drivers/char/rio/daemon.h b/drivers/char/rio/daemon.h index 28a991bd4fe6..5818a8aa46e0 100644 --- a/drivers/char/rio/daemon.h +++ b/drivers/char/rio/daemon.h @@ -45,15 +45,15 @@ static char *_daemon_h_sccs_ = "@(#)daemon.h 1.3"; */ struct Error { - uint Error; - uint Entry; - uint Other; + unsigned int Error; + unsigned int Entry; + unsigned int Other; }; struct DownLoad { char *DataP; - uint Count; - uint ProductCode; + unsigned int Count; + unsigned int ProductCode; }; /* @@ -68,69 +68,64 @@ struct DownLoad { #endif struct PortSetup { - uint From; /* Set/Clear XP & IXANY Control from this port.... */ - uint To; /* .... to this port */ - uint XpCps; /* at this speed */ + unsigned int From; /* Set/Clear XP & IXANY Control from this port.... */ + unsigned int To; /* .... to this port */ + unsigned int XpCps; /* at this speed */ char XpOn[MAX_XP_CTRL_LEN]; /* this is the start string */ char XpOff[MAX_XP_CTRL_LEN]; /* this is the stop string */ - uchar IxAny; /* enable/disable IXANY */ - uchar IxOn; /* enable/disable IXON */ - uchar Lock; /* lock port params */ - uchar Store; /* store params across closes */ - uchar Drain; /* close only when drained */ + u8 IxAny; /* enable/disable IXANY */ + u8 IxOn; /* enable/disable IXON */ + u8 Lock; /* lock port params */ + u8 Store; /* store params across closes */ + u8 Drain; /* close only when drained */ }; struct LpbReq { - uint Host; - uint Link; + unsigned int Host; + unsigned int Link; struct LPB *LpbP; }; struct RupReq { - uint HostNum; - uint RupNum; + unsigned int HostNum; + unsigned int RupNum; struct RUP *RupP; }; struct PortReq { - uint SysPort; + unsigned int SysPort; struct Port *PortP; }; struct StreamInfo { - uint SysPort; -#if 0 - queue_t RQueue; - queue_t WQueue; -#else + unsigned int SysPort; int RQueue; int WQueue; -#endif }; struct HostReq { - uint HostNum; + unsigned int HostNum; struct Host *HostP; }; struct HostDpRam { - uint HostNum; + unsigned int HostNum; struct DpRam *DpRamP; }; struct DebugCtrl { - uint SysPort; - uint Debug; - uint Wait; + unsigned int SysPort; + unsigned int Debug; + unsigned int Wait; }; struct MapInfo { - uint FirstPort; /* 8 ports, starting from this (tty) number */ - uint RtaUnique; /* reside on this RTA (unique number) */ + unsigned int FirstPort; /* 8 ports, starting from this (tty) number */ + unsigned int RtaUnique; /* reside on this RTA (unique number) */ }; struct MapIn { - uint NumEntries; /* How many port sets are we mapping? */ + unsigned int NumEntries; /* How many port sets are we mapping? */ struct MapInfo *MapInfoP; /* Pointer to (user space) info */ }; @@ -147,13 +142,13 @@ struct SpecialRupCmd { }; struct IdentifyRta { - ulong RtaUnique; - uchar ID; + unsigned long RtaUnique; + u8 ID; }; struct KillNeighbour { - ulong UniqueNum; - uchar Link; + unsigned long UniqueNum; + u8 Link; }; struct rioVersion { diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h index f7dfcedf7d45..79a55301f06b 100644 --- a/drivers/char/rio/host.h +++ b/drivers/char/rio/host.h @@ -50,22 +50,20 @@ static char *_host_h_sccs_ = "@(#)host.h 1.2"; ** the host. */ struct Host { - uchar Type; /* RIO_EISA, RIO_MCA, ... */ - uchar Ivec; /* POLLED or ivec number */ - uchar Mode; /* Control stuff */ - uchar Slot; /* Slot */ - volatile caddr_t Caddr; /* KV address of DPRAM */ - volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */ - paddr_t PaddrP; /* Phys. address of DPRAM */ + unsigned char Type; /* RIO_EISA, RIO_MCA, ... */ + unsigned char Ivec; /* POLLED or ivec number */ + unsigned char Mode; /* Control stuff */ + unsigned char Slot; /* Slot */ + caddr_t Caddr; /* KV address of DPRAM */ + struct DpRam *CardP; /* KV address of DPRAM, with overlay */ + paddr_t PaddrP; /* Phys. address of DPRAM */ char Name[MAX_NAME_LEN]; /* The name of the host */ - uint UniqueNum; /* host unique number */ + unsigned int UniqueNum; /* host unique number */ spinlock_t HostLock; /* Lock structure for MPX */ - /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */ - /*struct lockb HostLock; *//* Lock structure for MPX */ - uint WorkToBeDone; /* set to true each interrupt */ - uint InIntr; /* Being serviced? */ - uint IntSrvDone; /* host's interrupt has been serviced */ - int (*Copy) (caddr_t, caddr_t, int); /* copy func */ + unsigned int WorkToBeDone; /* set to true each interrupt */ + unsigned int InIntr; /* Being serviced? */ + unsigned int IntSrvDone; /* host's interrupt has been serviced */ + void (*Copy) (void *, void *, int); /* copy func */ struct timer_list timer; /* ** I M P O R T A N T ! @@ -74,7 +72,7 @@ struct Host { ** a RIO_HOST_FOAD command. */ - ulong Flags; /* Whats going down */ + unsigned long Flags; /* Whats going down */ #define RC_WAITING 0 #define RC_STARTUP 1 #define RC_RUNNING 2 @@ -88,28 +86,28 @@ struct Host { ** Boot mode applies to the way in which hosts in this system will ** boot RTAs */ -#define RC_BOOT_ALL 0x8 /* Boot all RTAs attached */ -#define RC_BOOT_OWN 0x10 /* Only boot RTAs bound to this system */ -#define RC_BOOT_NONE 0x20 /* Don't boot any RTAs (slave mode) */ +#define RC_BOOT_ALL 0x8 /* Boot all RTAs attached */ +#define RC_BOOT_OWN 0x10 /* Only boot RTAs bound to this system */ +#define RC_BOOT_NONE 0x20 /* Don't boot any RTAs (slave mode) */ struct Top Topology[LINKS_PER_UNIT]; /* one per link */ - struct Map Mapping[MAX_RUP]; /* Mappings for host */ - struct PHB *PhbP; /* Pointer to the PHB array */ - ushort *PhbNumP; /* Ptr to Number of PHB's */ - struct LPB *LinkStrP; /* Link Structure Array */ - struct RUP *RupP; /* Sixteen real rups here */ - struct PARM_MAP *ParmMapP; /* points to the parmmap */ - uint ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */ - uint NumExtraBooted; /* how many of the above */ + struct Map Mapping[MAX_RUP]; /* Mappings for host */ + struct PHB *PhbP; /* Pointer to the PHB array */ + unsigned short *PhbNumP; /* Ptr to Number of PHB's */ + struct LPB *LinkStrP; /* Link Structure Array */ + struct RUP *RupP; /* Sixteen real rups here */ + struct PARM_MAP *ParmMapP; /* points to the parmmap */ + unsigned int ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */ + unsigned int NumExtraBooted; /* how many of the above */ /* ** Twenty logical rups. ** The first sixteen are the real Rup entries (above), the last four ** are the link RUPs. */ struct UnixRup UnixRups[MAX_RUP + LINKS_PER_UNIT]; - int timeout_id; /* For calling 100 ms delays */ - int timeout_sem; /* For calling 100 ms delays */ - long locks; /* long req'd for set_bit --RR */ + int timeout_id; /* For calling 100 ms delays */ + int timeout_sem; /* For calling 100 ms delays */ + long locks; /* long req'd for set_bit --RR */ char ____end_marker____; }; #define Control CardP->DpControl diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h index 6a64b5a5b3d0..87a87b1ec01d 100644 --- a/drivers/char/rio/link.h +++ b/drivers/char/rio/link.h @@ -68,8 +68,8 @@ struct LPB { u16 mon_ltt; u16 mon_lrt; u16 WaitNoBoot; /* Secs to hold off booting */ - PKT_ptr add_packet_list; /* Add packets to here */ - PKT_ptr remove_packet_list; /* Send packets from here */ + u16 add_packet_list; /* Add packets to here */ + u16 remove_packet_list; /* Send packets from here */ Channel_ptr lrt_fail_chan; /* Lrt's failure channel */ Channel_ptr ltt_fail_chan; /* Ltt's failure channel */ diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h index 17a14c4a3420..ebbe3ea873e8 100644 --- a/drivers/char/rio/linux_compat.h +++ b/drivers/char/rio/linux_compat.h @@ -19,56 +19,16 @@ #include -#define disable(oldspl) save_flags (oldspl) -#define restore(oldspl) restore_flags (oldspl) - -#define sysbrk(x) kmalloc ((x),in_interrupt()? GFP_ATOMIC : GFP_KERNEL) -#define sysfree(p,size) kfree ((p)) - -#define WBYTE(p,v) writeb(v, &p) -#define RBYTE(p) readb (&p) -#define WWORD(p,v) writew(v, &p) -#define RWORD(p) readw(&p) -#define WINDW(p,v) writew(v, p) -#define RINDW(p) readw(p) - #define DEBUG_ALL -#define cprintf printk - -#ifdef __KERNEL__ -#define INKERNEL -#endif - struct ttystatics { struct termios tm; }; -#define bzero(d, n) memset((d), 0, (n)) #define bcopy(src, dest, n) memcpy ((dest), (src), (n)) #define SEM_SIGIGNORE 0x1234 -#ifdef DEBUG_SEM -#define swait(a,b) printk ("waiting: " __FILE__ " line %d\n", __LINE__) -#define ssignal(sem) printk ("signalling: " __FILE__ " line %d\n", __LINE__) - -#define sreset(sem) printk ("sreset: " __FILE__ "\n") -#define sem_init(sem,v) printk ("sreset: " __FILE__ "\n") -#endif - - -#define getpid() (current->pid) - -#define QSIZE SERIAL_XMIT_SIZE - -#define pseterr(errno) return (- errno) - -#define V_CBAUD CBAUD - -/* For one reason or another rioboot.c uses delay instead of RIODelay. */ -#define delay(x,y) RIODelay(NULL, y) - extern int rio_debug; #define RIO_DEBUG_INIT 0x000001 @@ -91,6 +51,7 @@ extern int rio_debug; #define RIO_DEBUG_DELAY 0x020000 #define RIO_DEBUG_MOD_COUNT 0x040000 + /* Copied over from riowinif.h . This is ugly. The winif file declares also much other stuff which is incompatible with the headers from the older driver. The older driver includes "brates.h" which shadows diff --git a/drivers/char/rio/port.h b/drivers/char/rio/port.h index 4f1108fe9b1a..9b5fa3eb0402 100644 --- a/drivers/char/rio/port.h +++ b/drivers/char/rio/port.h @@ -40,7 +40,7 @@ struct Port { struct gs_port gs; int PortNum; /* RIO port no., 0-511 */ struct Host *HostP; - volatile caddr_t Caddr; + caddr_t Caddr; unsigned short HostPort; /* Port number on host card */ unsigned char RupNum; /* Number of RUP for port */ unsigned char ID2; /* Second ID of RTA for port */ diff --git a/drivers/char/rio/riodrvr.h b/drivers/char/rio/riodrvr.h index 663ee0914ed7..3cffe275f216 100644 --- a/drivers/char/rio/riodrvr.h +++ b/drivers/char/rio/riodrvr.h @@ -72,42 +72,42 @@ struct rio_info { */ int RIOHalted; /* halted ? */ int RIORtaDisCons; /* RTA connections/disconnections */ - uint RIOReadCheck; /* Rio read check */ - uint RIONoMessage; /* To display message or not */ - uint RIONumBootPkts; /* how many packets for an RTA */ - uint RIOBootCount; /* size of RTA code */ - uint RIOBooting; /* count of outstanding boots */ - uint RIOSystemUp; /* Booted ?? */ - uint RIOCounting; /* for counting interrupts */ - uint RIOIntCount; /* # of intr since last check */ - uint RIOTxCount; /* number of xmit intrs */ - uint RIORxCount; /* number of rx intrs */ - uint RIORupCount; /* number of rup intrs */ + unsigned int RIOReadCheck; /* Rio read check */ + unsigned int RIONoMessage; /* To display message or not */ + unsigned int RIONumBootPkts; /* how many packets for an RTA */ + unsigned int RIOBootCount; /* size of RTA code */ + unsigned int RIOBooting; /* count of outstanding boots */ + unsigned int RIOSystemUp; /* Booted ?? */ + unsigned int RIOCounting; /* for counting interrupts */ + unsigned int RIOIntCount; /* # of intr since last check */ + unsigned int RIOTxCount; /* number of xmit intrs */ + unsigned int RIORxCount; /* number of rx intrs */ + unsigned int RIORupCount; /* number of rup intrs */ int RIXTimer; int RIOBufferSize; /* Buffersize */ int RIOBufferMask; /* Buffersize */ int RIOFirstMajor; /* First host card's major no */ - uint RIOLastPortsMapped; /* highest port number known */ - uint RIOFirstPortsMapped; /* lowest port number known */ + unsigned int RIOLastPortsMapped; /* highest port number known */ + unsigned int RIOFirstPortsMapped; /* lowest port number known */ - uint RIOLastPortsBooted; /* highest port number running */ - uint RIOFirstPortsBooted; /* lowest port number running */ + unsigned int RIOLastPortsBooted; /* highest port number running */ + unsigned int RIOFirstPortsBooted; /* lowest port number running */ - uint RIOLastPortsOpened; /* highest port number running */ - uint RIOFirstPortsOpened; /* lowest port number running */ + unsigned int RIOLastPortsOpened; /* highest port number running */ + unsigned int RIOFirstPortsOpened; /* lowest port number running */ /* Flag to say that the topology information has been changed. */ - uint RIOQuickCheck; - uint CdRegister; /* ??? */ + unsigned int RIOQuickCheck; + unsigned int CdRegister; /* ??? */ int RIOSignalProcess; /* Signalling process */ int rio_debug; /* To debug ... */ int RIODebugWait; /* For what ??? */ int tpri; /* Thread prio */ int tid; /* Thread id */ - uint _RIO_Polled; /* Counter for polling */ - uint _RIO_Interrupted; /* Counter for interrupt */ + unsigned int _RIO_Polled; /* Counter for polling */ + unsigned int _RIO_Interrupted; /* Counter for interrupt */ int intr_tid; /* iointset return value */ int TxEnSem; /* TxEnable Semaphore */ @@ -121,9 +121,9 @@ struct rio_info { struct Map RIOSavedTable[TOTAL_MAP_ENTRIES]; /* RTA to host binding table for master/slave operation */ - ulong RIOBindTab[MAX_RTA_BINDINGS]; + unsigned long RIOBindTab[MAX_RTA_BINDINGS]; /* RTA memory dump variable */ - uchar RIOMemDump[MEMDUMP_SIZE]; + unsigned char RIOMemDump[MEMDUMP_SIZE]; struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES]; }; @@ -138,7 +138,5 @@ struct rio_info { #define RIO_RESET_INT 0x7d80 -#define WRBYTE(x,y) *(volatile unsigned char *)((x)) = \ - (unsigned char)(y) #endif /* __riodrvr.h */ diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h index 40c617436bd1..4ae90cb207a9 100644 --- a/drivers/char/rio/rup.h +++ b/drivers/char/rio/rup.h @@ -53,8 +53,8 @@ #define RUP_NO_OWNER 0xff /* RUP not owned by any process */ struct RUP { - PKT_ptr txpkt; /* Outgoing packet */ - PKT_ptr rxpkt; /* Incoming packet */ + u16 txpkt; /* Outgoing packet */ + u16 rxpkt; /* Incoming packet */ u16 link; /* Which link to send down? */ u8 rup_dest_unit[2]; /* Destination unit */ u16 handshake; /* For handshaking */ diff --git a/drivers/char/rio/top.h b/drivers/char/rio/top.h index d15a11dc4f73..fe60430cf099 100644 --- a/drivers/char/rio/top.h +++ b/drivers/char/rio/top.h @@ -41,8 +41,8 @@ static char *_top_h_sccs_ = "@(#)top.h 1.2"; ** Topology information */ struct Top { - uchar Unit; - uchar Link; + u8 Unit; + u8 Link; }; #endif /* __rio_top_h__ */ diff --git a/drivers/char/rio/typdef.h b/drivers/char/rio/typdef.h index 840c2498a59d..f40c1df7db1f 100644 --- a/drivers/char/rio/typdef.h +++ b/drivers/char/rio/typdef.h @@ -39,10 +39,10 @@ ** These types are ONLY to be used for refering to data structures ** on the RIO Host card! */ -typedef volatile u8 BYTE; -typedef volatile u16 WORD; -typedef volatile u32 DWORD; -typedef volatile u16 RIOP; +typedef u8 BYTE; +typedef u16 WORD; +typedef u32 DWORD; +typedef u16 RIOP; /* @@ -57,8 +57,7 @@ typedef unsigned short ushort_t; typedef unsigned char uchar_t; typedef unsigned char queue_t; typedef unsigned char mblk_t; -typedef unsigned int paddr_t; -typedef unsigned char uchar; +typedef unsigned long paddr_t; #define TPNULL ((ushort)(0x8000)) -- cgit v1.2.3-59-g8ed1b From e2b3afd676ad3e15ca2efca3b3605c7d817ec6e3 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 24 Mar 2006 03:18:27 -0800 Subject: [PATCH] rio driver rework continued #2 First large chunk of code cleanup. The split between this and #3 and #4 is fairly arbitary and due to the message length limit on the list. These patches continue the process of ripping out macros and typedefs while cleaning up lots of 32bit assumptions. Several inlines for compatibility also get removed and that causes a lot of noise. Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/rio/rioparam.c | 108 ++++++++++++++++++-------------------------- drivers/char/rio/rioroute.c | 62 ++++++++++++------------- drivers/char/rio/riotable.c | 76 ++++++++++++++----------------- drivers/char/rio/riotty.c | 23 +++------- 4 files changed, 115 insertions(+), 154 deletions(-) (limited to 'drivers') diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c index c622f46d6d77..af25d2084f47 100644 --- a/drivers/char/rio/rioparam.c +++ b/drivers/char/rio/rioparam.c @@ -157,20 +157,16 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3"; ** NB. for MPX ** tty lock must NOT have been previously acquired. */ -int RIOParam(PortP, cmd, Modem, SleepFlag) -struct Port *PortP; -int cmd; -int Modem; -int SleepFlag; +int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag) { - register struct tty_struct *TtyP; + struct tty_struct *TtyP; int retval; - register struct phb_param *phb_param_ptr; + struct phb_param *phb_param_ptr; PKT *PacketP; int res; - uchar Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0; - uchar TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0; - uchar LNext = 0, TxBaud = 0, RxBaud = 0; + u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0; + u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0; + u8 LNext = 0, TxBaud = 0, RxBaud = 0; int retries = 0xff; unsigned long flags; @@ -226,15 +222,12 @@ int SleepFlag; if (retval == RIO_FAIL) { rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n"); rio_spin_unlock_irqrestore(&PortP->portSem, flags); - pseterr(EINTR); func_exit(); - - return RIO_FAIL; + return -EINTR; } if (PortP->State & RIO_DELETED) { rio_spin_unlock_irqrestore(&PortP->portSem, flags); func_exit(); - return RIO_SUCCESS; } } @@ -247,7 +240,7 @@ int SleepFlag; } rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res); - rio_dprintk(RIO_DEBUG_PARAM, "Packet is 0x%x\n", (int) PacketP); + rio_dprintk(RIO_DEBUG_PARAM, "Packet is 0x%p\n", PacketP); phb_param_ptr = (struct phb_param *) PacketP->data; @@ -474,9 +467,6 @@ int SleepFlag; e(115200); /* e(230400);e(460800); e(921600); */ } - /* XXX MIssing conversion table. XXX */ - /* (TtyP->termios->c_cflag & V_CBAUD); */ - rio_dprintk(RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud); @@ -552,23 +542,23 @@ int SleepFlag; /* ** Actually write the info into the packet to be sent */ - WBYTE(phb_param_ptr->Cmd, cmd); - WBYTE(phb_param_ptr->Cor1, Cor1); - WBYTE(phb_param_ptr->Cor2, Cor2); - WBYTE(phb_param_ptr->Cor4, Cor4); - WBYTE(phb_param_ptr->Cor5, Cor5); - WBYTE(phb_param_ptr->TxXon, TxXon); - WBYTE(phb_param_ptr->RxXon, RxXon); - WBYTE(phb_param_ptr->TxXoff, TxXoff); - WBYTE(phb_param_ptr->RxXoff, RxXoff); - WBYTE(phb_param_ptr->LNext, LNext); - WBYTE(phb_param_ptr->TxBaud, TxBaud); - WBYTE(phb_param_ptr->RxBaud, RxBaud); + writeb(cmd, &phb_param_ptr->Cmd); + writeb(Cor1, &phb_param_ptr->Cor1); + writeb(Cor2, &phb_param_ptr->Cor2); + writeb(Cor4, &phb_param_ptr->Cor4); + writeb(Cor5, &phb_param_ptr->Cor5); + writeb(TxXon, &phb_param_ptr->TxXon); + writeb(RxXon, &phb_param_ptr->RxXon); + writeb(TxXoff, &phb_param_ptr->TxXoff); + writeb(RxXoff, &phb_param_ptr->RxXoff); + writeb(LNext, &phb_param_ptr->LNext); + writeb(TxBaud, &phb_param_ptr->TxBaud); + writeb(RxBaud, &phb_param_ptr->RxBaud); /* ** Set the length/command field */ - WBYTE(PacketP->len, 12 | PKT_CMD_BIT); + writeb(12 | PKT_CMD_BIT, &PacketP->len); /* ** The packet is formed - now, whack it off @@ -597,15 +587,13 @@ int SleepFlag; ** We can add another packet to a transmit queue if the packet pointer pointed ** to by the TxAdd pointer has PKT_IN_USE clear in its address. */ -int can_add_transmit(PktP, PortP) -PKT **PktP; -struct Port *PortP; +int can_add_transmit(PKT **PktP, struct Port *PortP) { - register PKT *tp; + PKT *tp; - *PktP = tp = (PKT *) RIO_PTR(PortP->Caddr, RWORD(*PortP->TxAdd)); + *PktP = tp = (PKT *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd)); - return !((uint) tp & PKT_IN_USE); + return !((unsigned long) tp & PKT_IN_USE); } /* @@ -613,24 +601,21 @@ struct Port *PortP; ** and then move the TxAdd pointer along one position to point to the next ** packet pointer. You must wrap the pointer from the end back to the start. */ -void add_transmit(PortP) -struct Port *PortP; +void add_transmit(struct Port *PortP) { - if (RWORD(*PortP->TxAdd) & PKT_IN_USE) { + if (readw(PortP->TxAdd) & PKT_IN_USE) { rio_dprintk(RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!"); } - WWORD(*(ushort *) PortP->TxAdd, RWORD(*PortP->TxAdd) | PKT_IN_USE); + writew(readw(PortP->TxAdd) | PKT_IN_USE, PortP->TxAdd); PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : PortP->TxAdd + 1; - WWORD(PortP->PhbP->tx_add, RIO_OFF(PortP->Caddr, PortP->TxAdd)); + writew(RIO_OFF(PortP->Caddr, PortP->TxAdd), &PortP->PhbP->tx_add); } /**************************************** * Put a packet onto the end of the * free list ****************************************/ -void put_free_end(HostP, PktP) -struct Host *HostP; -PKT *PktP; +void put_free_end(struct Host *HostP, PKT *PktP) { FREE_LIST *tmp_pointer; ushort old_end, new_end; @@ -643,21 +628,21 @@ PKT *PktP; * ************************************************/ - rio_dprintk(RIO_DEBUG_PFE, "put_free_end(PktP=%x)\n", (int) PktP); + rio_dprintk(RIO_DEBUG_PFE, "put_free_end(PktP=%p)\n", PktP); - if ((old_end = RWORD(HostP->ParmMapP->free_list_end)) != TPNULL) { + if ((old_end = readw(&HostP->ParmMapP->free_list_end)) != TPNULL) { new_end = RIO_OFF(HostP->Caddr, PktP); tmp_pointer = (FREE_LIST *) RIO_PTR(HostP->Caddr, old_end); - WWORD(tmp_pointer->next, new_end); - WWORD(((FREE_LIST *) PktP)->prev, old_end); - WWORD(((FREE_LIST *) PktP)->next, TPNULL); - WWORD(HostP->ParmMapP->free_list_end, new_end); + writew(new_end, &tmp_pointer->next); + writew(old_end, &((FREE_LIST *) PktP)->prev); + writew(TPNULL, &((FREE_LIST *) PktP)->next); + writew(new_end, &HostP->ParmMapP->free_list_end); } else { /* First packet on the free list this should never happen! */ rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n"); - WWORD(HostP->ParmMapP->free_list_end, RIO_OFF(HostP->Caddr, PktP)); + writew(RIO_OFF(HostP->Caddr, PktP), &HostP->ParmMapP->free_list_end); tmp_pointer = (FREE_LIST *) PktP; - WWORD(tmp_pointer->prev, TPNULL); - WWORD(tmp_pointer->next, TPNULL); + writew(TPNULL, &tmp_pointer->prev); + writew(TPNULL, &tmp_pointer->next); } rio_dprintk(RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock); rio_spin_unlock_irqrestore(&HostP->HostLock, flags); @@ -669,12 +654,10 @@ PKT *PktP; ** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear, ** then can_remove_receive() returns 0. */ -int can_remove_receive(PktP, PortP) -PKT **PktP; -struct Port *PortP; +int can_remove_receive(PKT **PktP, struct Port *PortP) { - if (RWORD(*PortP->RxRemove) & PKT_IN_USE) { - *PktP = (PKT *) RIO_PTR(PortP->Caddr, RWORD(*PortP->RxRemove) & ~PKT_IN_USE); + if (readw(PortP->RxRemove) & PKT_IN_USE) { + *PktP = (PKT *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE); return 1; } return 0; @@ -685,10 +668,9 @@ struct Port *PortP; ** and then bump the pointers. Once the pointers get to the end, they must ** be wrapped back to the start. */ -void remove_receive(PortP) -struct Port *PortP; +void remove_receive(struct Port *PortP) { - WWORD(*PortP->RxRemove, RWORD(*PortP->RxRemove) & ~PKT_IN_USE); + writew(readw(PortP->RxRemove) & ~PKT_IN_USE, PortP->RxRemove); PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : PortP->RxRemove + 1; - WWORD(PortP->PhbP->rx_remove, RIO_OFF(PortP->Caddr, PortP->RxRemove)); + writew(RIO_OFF(PortP->Caddr, PortP->RxRemove), &PortP->PhbP->rx_remove); } diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c index f98888f52659..874ac7462388 100644 --- a/drivers/char/rio/rioroute.c +++ b/drivers/char/rio/rioroute.c @@ -115,7 +115,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) /* ** Is this unit telling us it's current link topology? */ - if (RBYTE(PktCmdP->Command) == ROUTE_TOPOLOGY) { + if (readb(&PktCmdP->Command) == ROUTE_TOPOLOGY) { MapP = HostP->Mapping; /* @@ -151,11 +151,11 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) ** it won't lie about network interconnect, total disconnects ** and no-IDs. (or at least, it doesn't *matter* if it does) */ - if (RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) > (ushort) MAX_RUP) + if (readb(&PktCmdP->RouteTopology[ThisLink].Unit) > (ushort) MAX_RUP) continue; for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) { - if ((RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) == RBYTE(PktCmdP->RouteTopology[NewLink].Unit)) && (RBYTE(PktCmdP->RouteTopology[ThisLink].Link) == RBYTE(PktCmdP->RouteTopology[NewLink].Link))) { + if ((readb(&PktCmdP->RouteTopology[ThisLink].Unit) == readb(&PktCmdP->RouteTopology[NewLink].Unit)) && (readb(&PktCmdP->RouteTopology[ThisLink].Link) == readb(&PktCmdP->RouteTopology[NewLink].Link))) { Lies++; } } @@ -164,10 +164,10 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) if (Lies) { rio_dprintk(RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n", Lies); rio_dprintk(RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n", - RBYTE(PktCmdP->RouteTopology[0].Unit), - 'A' + RBYTE(PktCmdP->RouteTopology[0].Link), - RBYTE(PktCmdP->RouteTopology[1].Unit), - 'A' + RBYTE(PktCmdP->RouteTopology[1].Link), RBYTE(PktCmdP->RouteTopology[2].Unit), 'A' + RBYTE(PktCmdP->RouteTopology[2].Link), RBYTE(PktCmdP->RouteTopology[3].Unit), 'A' + RBYTE(PktCmdP->RouteTopology[3].Link)); + readb(&PktCmdP->RouteTopology[0].Unit), + 'A' + readb(&PktCmdP->RouteTopology[0].Link), + readb(&PktCmdP->RouteTopology[1].Unit), + 'A' + readb(&PktCmdP->RouteTopology[1].Link), readb(&PktCmdP->RouteTopology[2].Unit), 'A' + readb(&PktCmdP->RouteTopology[2].Link), readb(&PktCmdP->RouteTopology[3].Unit), 'A' + readb(&PktCmdP->RouteTopology[3].Link)); return TRUE; } @@ -184,8 +184,8 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) /* ** this is what it is now connected to */ - NewUnit = RBYTE(PktCmdP->RouteTopology[ThisLink].Unit); - NewLink = RBYTE(PktCmdP->RouteTopology[ThisLink].Link); + NewUnit = readb(&PktCmdP->RouteTopology[ThisLink].Unit); + NewLink = readb(&PktCmdP->RouteTopology[ThisLink].Link); if (OldUnit != NewUnit || OldLink != NewLink) { /* @@ -219,7 +219,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) if (NewUnit == ROUTE_INTERCONNECT) { if (!p->RIONoMessage) - cprintf("%s '%s' (%c) is connected to another network.\n", MyType, MyName, 'A' + ThisLink); + printk(KERN_DEBUG "rio: %s '%s' (%c) is connected to another network.\n", MyType, MyName, 'A' + ThisLink); } /* @@ -264,12 +264,12 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) /* ** The only other command we recognise is a route_request command */ - if (RBYTE(PktCmdP->Command) != ROUTE_REQUEST) { - rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %d ROUTE_RUP\n", RBYTE(PktCmdP->Command), Rup, (int) HostP); + if (readb(&PktCmdP->Command) != ROUTE_REQUEST) { + rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %p ROUTE_RUP\n", readb(&PktCmdP->Command), Rup, HostP); return TRUE; } - RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) + (RBYTE(PktCmdP->UniqNum[1]) << 8) + (RBYTE(PktCmdP->UniqNum[2]) << 16) + (RBYTE(PktCmdP->UniqNum[3]) << 24); + RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24); /* ** Determine if 8 or 16 port RTA @@ -278,7 +278,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) rio_dprintk(RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq); - Mod = RBYTE(PktCmdP->ModuleTypes); + Mod = readb(&PktCmdP->ModuleTypes); Mod1 = LONYBLE(Mod); if (RtaType == TYPE_RTA16) { /* @@ -348,7 +348,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) if ((HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED)) { if (!(HostP->Mapping[ThisUnit].Flags & MSG_DONE)) { if (!p->RIONoMessage) - cprintf("RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name); + printk(KERN_DEBUG "rio: RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name); HostP->Mapping[ThisUnit].Flags |= MSG_DONE; } PktReplyP->Command = ROUTE_FOAD; @@ -475,7 +475,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) if (!UnknownMesgDone) { if (!p->RIONoMessage) - cprintf("One or more unknown RTAs are being updated.\n"); + printk(KERN_DEBUG "rio: One or more unknown RTAs are being updated.\n"); UnknownMesgDone = 1; } @@ -527,7 +527,7 @@ uint unit; */ PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort]; - link = RWORD(PortP->PhbP->link); + link = readw(&PortP->PhbP->link); for (port = 0; port < PORTS_PER_RTA; port++, PortN++) { ushort dest_port = port + 8; @@ -569,18 +569,18 @@ uint unit; ** card. This needs to be translated into a 32 bit pointer ** so it can be accessed from the driver. */ - Pkt = (PKT *) RIO_PTR(HostP->Caddr, RINDW(TxPktP)); + Pkt = (PKT *) RIO_PTR(HostP->Caddr, readw(TxPktP)); /* ** If the packet is used, reset it. */ - Pkt = (PKT *) ((uint) Pkt & ~PKT_IN_USE); - WBYTE(Pkt->dest_unit, dest_unit); - WBYTE(Pkt->dest_port, dest_port); + Pkt = (PKT *) ((unsigned long) Pkt & ~PKT_IN_USE); + writeb(dest_unit, &Pkt->dest_unit); + writeb(dest_port, &Pkt->dest_port); } - rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", RWORD(PortP->PhbP->destination) & 0xff, (RWORD(PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port); - WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8)); - WWORD(PortP->PhbP->link, link); + rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", readw(&PortP->PhbP->destination) & 0xff, (readw(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port); + writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination); + writew(link, &PortP->PhbP->link); rio_spin_unlock_irqrestore(&PortP->portSem, flags); } @@ -590,9 +590,9 @@ uint unit; */ if (link > 3) return; - if (((unit * 8) + 7) > RWORD(HostP->LinkStrP[link].last_port)) { + if (((unit * 8) + 7) > readw(&HostP->LinkStrP[link].last_port)) { rio_dprintk(RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7); - WWORD(HostP->LinkStrP[link].last_port, (unit * 8) + 7); + writew((unit * 8) + 7, &HostP->LinkStrP[link].last_port); } } } @@ -818,7 +818,7 @@ int Change; ToType = ToId ? "RTA" : "HOST"; rio_dprintk(RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected"); - cprintf("Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected"); + printk(KERN_DEBUG "rio: Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected"); } /* @@ -838,7 +838,7 @@ static int RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap) */ for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) { if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum) { - bzero((caddr_t) & p->RIOSavedTable[entry], sizeof(struct Map)); + memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map)); } } return 0; @@ -898,7 +898,7 @@ static int RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit) int nOther = (HostP->Mapping[unit].ID2) - 1; rio_dprintk(RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther); - bzero((caddr_t) & HostP->Mapping[nOther], sizeof(struct Map)); + memset(&HostP->Mapping[nOther], 0, sizeof(struct Map)); } RIORemoveFromSavedTable(p, &HostP->Mapping[unit]); @@ -997,7 +997,7 @@ int RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint * pID1, uint * pI /* ** Clear out this slot now that we intend to use it. */ - bzero(&HostP->Mapping[unit], sizeof(struct Map)); + memset(&HostP->Mapping[unit], 0, sizeof(struct Map)); /* ** If the second ID is not needed then we can return @@ -1015,7 +1015,7 @@ int RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint * pID1, uint * pI /* ** Clear out this slot now that we intend to use it. */ - bzero(&HostP->Mapping[unit], sizeof(struct Map)); + memset(&HostP->Mapping[unit], 0, sizeof(struct Map)); /* At this point under the right(wrong?) conditions ** we may have a first unit ID being higher than the diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c index a86b216ab653..f1d50142b91d 100644 --- a/drivers/char/rio/riotable.c +++ b/drivers/char/rio/riotable.c @@ -91,8 +91,7 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2"; ** A configuration table has been loaded. It is now up to us ** to sort it out and use the information contained therein. */ -int RIONewTable(p) -struct rio_info *p; +int RIONewTable(struct rio_info *p) { int Host, Host1, Host2, NameIsUnique, Entry, SubEnt; struct Map *MapP; @@ -298,9 +297,9 @@ struct rio_info *p; */ for (Host = 0; Host < RIO_HOSTS; Host++) { for (Entry = 0; Entry < MAX_RUP; Entry++) { - bzero((caddr_t) & p->RIOHosts[Host].Mapping[Entry], sizeof(struct Map)); + memset(&p->RIOHosts[Host].Mapping[Entry], 0, sizeof(struct Map)); } - bzero((caddr_t) & p->RIOHosts[Host].Name[0], sizeof(p->RIOHosts[Host].Name)); + memset(&p->RIOHosts[Host].Name[0], 0, sizeof(p->RIOHosts[Host].Name)); } /* @@ -409,9 +408,10 @@ struct rio_info *p; /* ** User process needs the config table - build it from first ** principles. +** +* FIXME: SMP locking */ -int RIOApel(p) -struct rio_info *p; +int RIOApel(struct rio_info *p) { int Host; int link; @@ -419,17 +419,17 @@ struct rio_info *p; int Next = 0; struct Map *MapP; struct Host *HostP; - long oldspl; - - disable(oldspl); /* strange but true! */ + unsigned long flags; rio_dprintk(RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n"); - bzero((caddr_t) & p->RIOConnectTable[0], sizeof(struct Map) * TOTAL_MAP_ENTRIES); + memset(&p->RIOConnectTable[0], 0, sizeof(struct Map) * TOTAL_MAP_ENTRIES); for (Host = 0; Host < RIO_HOSTS; Host++) { rio_dprintk(RIO_DEBUG_TABLE, "Processing host %d\n", Host); HostP = &p->RIOHosts[Host]; + rio_spin_lock_irqsave(&HostP->HostLock, flags); + MapP = &p->RIOConnectTable[Next++]; MapP->HostUniqueNum = HostP->UniqueNum; if ((HostP->Flags & RUN_STATE) != RC_RUNNING) @@ -453,8 +453,8 @@ struct rio_info *p; Next++; } } + rio_spin_unlock_irqrestore(&HostP->HostLock, flags); } - restore(oldspl); return 0; } @@ -463,9 +463,7 @@ struct rio_info *p; ** if the entry is suitably inactive, then we can gob on it and remove ** it from the table. */ -int RIODeleteRta(p, MapP) -struct rio_info *p; -struct Map *MapP; +int RIODeleteRta(struct rio_info *p, struct Map *MapP) { int host, entry, port, link; int SysPort; @@ -543,7 +541,7 @@ struct Map *MapP; if (PortP->SecondBlock) { ushort dest_unit = HostMapP->ID; ushort dest_port = port - SysPort; - WORD *TxPktP; + u16 *TxPktP; PKT *Pkt; for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) { @@ -554,19 +552,19 @@ struct Map *MapP; ** a 32 bit pointer so it can be ** accessed from the driver. */ - Pkt = (PKT *) RIO_PTR(HostP->Caddr, RWORD(*TxPktP)); + Pkt = (PKT *) RIO_PTR(HostP->Caddr, readw(&*TxPktP)); rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", *TxPktP, Pkt->dest_unit, Pkt->dest_port, dest_unit, dest_port); - WWORD(Pkt->dest_unit, dest_unit); - WWORD(Pkt->dest_port, dest_port); + writew(dest_unit, &Pkt->dest_unit); + writew(dest_port, &Pkt->dest_port); } rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, PortP->PhbP->destination & 0xff, (PortP->PhbP->destination >> 8) & 0xff, dest_unit, dest_port); - WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8)); + writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination); } rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags); } } rio_dprintk(RIO_DEBUG_TABLE, "Entry nulled.\n"); - bzero((char *) HostMapP, sizeof(struct Map)); + memset(HostMapP, 0, sizeof(struct Map)); work_done++; } } @@ -576,11 +574,11 @@ struct Map *MapP; /* XXXXX lock me up */ for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) { if (p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) { - bzero((char *) &p->RIOSavedTable[entry], sizeof(struct Map)); + memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map)); work_done++; } if (p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) { - bzero((char *) &p->RIOConnectTable[entry], sizeof(struct Map)); + memset(&p->RIOConnectTable[entry], 0, sizeof(struct Map)); work_done++; } } @@ -742,12 +740,9 @@ int RIOAssignRta(struct rio_info *p, struct Map *MapP) } -int RIOReMapPorts(p, HostP, HostMapP) -struct rio_info *p; -struct Host *HostP; -struct Map *HostMapP; +int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP) { - register struct Port *PortP; + struct Port *PortP; uint SubEnt; uint HostPort; uint SysPort; @@ -794,12 +789,12 @@ struct Map *HostMapP; */ if ((HostP->Flags & RUN_STATE) == RC_RUNNING) { struct PHB *PhbP = PortP->PhbP = &HostP->PhbP[HostPort]; - PortP->TxAdd = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->tx_add)); - PortP->TxStart = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->tx_start)); - PortP->TxEnd = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->tx_end)); - PortP->RxRemove = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->rx_remove)); - PortP->RxStart = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->rx_start)); - PortP->RxEnd = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->rx_end)); + PortP->TxAdd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add)); + PortP->TxStart = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start)); + PortP->TxEnd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end)); + PortP->RxRemove = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove)); + PortP->RxStart = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start)); + PortP->RxEnd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end)); } else PortP->PhbP = NULL; @@ -866,9 +861,6 @@ struct Map *HostMapP; PortP->RxDataStart = 0; PortP->Cor2Copy = 0; PortP->Name = &HostMapP->Name[0]; -#ifdef STATS - bzero((caddr_t) & PortP->Stat, sizeof(struct RIOStats)); -#endif PortP->statsGather = 0; PortP->txchars = 0; PortP->rxchars = 0; @@ -876,10 +868,10 @@ struct Map *HostMapP; PortP->closes = 0; PortP->ioctls = 0; if (PortP->TxRingBuffer) - bzero(PortP->TxRingBuffer, p->RIOBufferSize); + memset(PortP->TxRingBuffer, 0, p->RIOBufferSize); else if (p->RIOBufferSize) { - PortP->TxRingBuffer = sysbrk(p->RIOBufferSize); - bzero(PortP->TxRingBuffer, p->RIOBufferSize); + PortP->TxRingBuffer = kmalloc(p->RIOBufferSize, GFP_KERNEL); + memset(PortP->TxRingBuffer, 0, p->RIOBufferSize); } PortP->TxBufferOut = 0; PortP->TxBufferIn = 0; @@ -890,7 +882,7 @@ struct Map *HostMapP; ** If the same, we have received the same rx pkt from the RTA ** twice. Initialise to a value not equal to PHB_RX_TGL or 0. */ - PortP->LastRxTgl = ~(uchar) PHB_RX_TGL; + PortP->LastRxTgl = ~(u8) PHB_RX_TGL; /* ** and mark the port as usable @@ -906,9 +898,7 @@ struct Map *HostMapP; return 0; } -int RIOChangeName(p, MapP) -struct rio_info *p; -struct Map *MapP; +int RIOChangeName(struct rio_info *p, struct Map *MapP) { int host; struct Map *HostMapP; diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c index 6379816ed173..0ca431b4c474 100644 --- a/drivers/char/rio/riotty.c +++ b/drivers/char/rio/riotty.c @@ -136,7 +136,7 @@ extern struct rio_info *p; int riotopen(struct tty_struct *tty, struct file *filp) { - register uint SysPort; + unsigned int SysPort; int Modem; int repeat_this = 250; struct Port *PortP; /* pointer to the port structure */ @@ -155,7 +155,6 @@ int riotopen(struct tty_struct *tty, struct file *filp) if (p->RIOFailed) { rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n"); - pseterr(ENXIO); func_exit(); return -ENXIO; } @@ -170,7 +169,6 @@ int riotopen(struct tty_struct *tty, struct file *filp) */ if (SysPort >= RIO_PORTS) { /* out of range ? */ rio_dprintk(RIO_DEBUG_TTY, "Illegal port number %d\n", SysPort); - pseterr(ENXIO); func_exit(); return -ENXIO; } @@ -187,7 +185,6 @@ int riotopen(struct tty_struct *tty, struct file *filp) */ rio_dprintk(RIO_DEBUG_TTY, "port not mapped into system\n"); func_exit(); - pseterr(ENXIO); return -ENXIO; } @@ -209,7 +206,6 @@ int riotopen(struct tty_struct *tty, struct file *filp) */ if ((PortP->HostP->Flags & RUN_STATE) != RC_RUNNING) { rio_dprintk(RIO_DEBUG_TTY, "Host not running\n"); - pseterr(ENXIO); func_exit(); return -ENXIO; } @@ -429,9 +425,6 @@ int riotopen(struct tty_struct *tty, struct file *filp) rio_dprintk(RIO_DEBUG_TTY, "high level open done\n"); -#ifdef STATS - PortP->Stat.OpenCnt++; -#endif /* ** Count opens for port statistics reporting */ @@ -466,10 +459,10 @@ int riotclose(void *ptr) rio_dprintk(RIO_DEBUG_TTY, "port close SysPort %d\n", PortP->PortNum); /* PortP = p->RIOPortp[SysPort]; */ - rio_dprintk(RIO_DEBUG_TTY, "Port is at address 0x%x\n", (int) PortP); + rio_dprintk(RIO_DEBUG_TTY, "Port is at address 0x%p\n", PortP); /* tp = PortP->TtyP; *//* Get tty */ tty = PortP->gs.tty; - rio_dprintk(RIO_DEBUG_TTY, "TTY is at address 0x%x\n", (int) tty); + rio_dprintk(RIO_DEBUG_TTY, "TTY is at address 0x%p\n", tty); if (PortP->gs.closing_wait) end_time = jiffies + PortP->gs.closing_wait; @@ -536,7 +529,6 @@ int riotclose(void *ptr) if (!deleted) while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut)) { - cprintf("Need to flush the ttyport\n"); if (repeat_this-- <= 0) { rv = -EINTR; rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n"); @@ -615,9 +607,6 @@ int riotclose(void *ptr) */ PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW); -#ifdef STATS - PortP->Stat.CloseCnt++; -#endif /* ** Count opens for port statistics reporting */ @@ -722,15 +711,15 @@ int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len /* ** set the command byte and the argument byte */ - WBYTE(PacketP->data[0], command); + writeb(command, &PacketP->data[0]); if (len == 2) - WBYTE(PacketP->data[1], arg); + writeb(arg, &PacketP->data[1]); /* ** set the length of the packet and set the command bit. */ - WBYTE(PacketP->len, PKT_CMD_BIT | len); + writeb(PKT_CMD_BIT | len, &PacketP->len); add_transmit(PortP); /* -- cgit v1.2.3-59-g8ed1b From 00d83a54aa824b11ebc8c66c4a879cfeb5029a22 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 24 Mar 2006 03:18:28 -0800 Subject: [PATCH] rio driver rework continued #3 Second large chunk of code cleanup. The split between this and #3 and #4 is fairly arbitary and due to the message length limit on the list. These patches continue the process of ripping out macros and typedefs while cleaning up lots of 32bit assumptions. Several inlines for compatibility also get removed and that causes a lot of noise. Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/rio/cmdblk.h | 4 +- drivers/char/rio/func.h | 51 ++++--- drivers/char/rio/rio.h | 4 +- drivers/char/rio/rio_linux.c | 69 ++++------ drivers/char/rio/riocmd.c | 142 ++++++++++---------- drivers/char/rio/rioinit.c | 186 +++++++++++--------------- drivers/char/rio/riointr.c | 311 +++++-------------------------------------- 7 files changed, 232 insertions(+), 535 deletions(-) (limited to 'drivers') diff --git a/drivers/char/rio/cmdblk.h b/drivers/char/rio/cmdblk.h index a9a8c45631d7..c46b2fdb6626 100644 --- a/drivers/char/rio/cmdblk.h +++ b/drivers/char/rio/cmdblk.h @@ -48,10 +48,10 @@ struct CmdBlk { struct CmdBlk *NextP; /* Pointer to next command block */ struct PKT Packet; /* A packet, to copy to the rup */ /* The func to call to check if OK */ - int (*PreFuncP) (int, struct CmdBlk *); + int (*PreFuncP) (unsigned long, struct CmdBlk *); int PreArg; /* The arg for the func */ /* The func to call when completed */ - int (*PostFuncP) (int, struct CmdBlk *); + int (*PostFuncP) (unsigned long, struct CmdBlk *); int PostArg; /* The arg for the func */ }; diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h index b4778410ec6e..8967772d833d 100644 --- a/drivers/char/rio/func.h +++ b/drivers/char/rio/func.h @@ -43,35 +43,34 @@ static char *_func_h_sccs_ = "@(#)func.h 1.3"; /* rioboot.c */ int RIOBootCodeRTA(struct rio_info *, struct DownLoad *); -int RIOBootCodeHOST(struct rio_info *, register struct DownLoad *); +int RIOBootCodeHOST(struct rio_info *, struct DownLoad *); int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *); void msec_timeout(struct Host *); -int RIOBootRup(struct rio_info *, uint, struct Host *, struct PKT *); -int RIOBootOk(struct rio_info *, struct Host *, ulong); -int RIORtaBound(struct rio_info *, uint); -void FillSlot(int, int, uint, struct Host *); +int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT *); +int RIOBootOk(struct rio_info *, struct Host *, unsigned long); +int RIORtaBound(struct rio_info *, unsigned int); +void FillSlot(int, int, unsigned int, struct Host *); /* riocmd.c */ int RIOFoadRta(struct Host *, struct Map *); int RIOZombieRta(struct Host *, struct Map *); -int RIOCommandRta(struct rio_info *, uint, int (*func) (struct Host *, struct Map *)); -int RIOIdentifyRta(struct rio_info *, caddr_t); -int RIOKillNeighbour(struct rio_info *, caddr_t); +int RIOCommandRta(struct rio_info *, unsigned long, int (*func) (struct Host *, struct Map *)); +int RIOIdentifyRta(struct rio_info *, void *); +int RIOKillNeighbour(struct rio_info *, void *); int RIOSuspendBootRta(struct Host *, int, int); int RIOFoadWakeup(struct rio_info *); struct CmdBlk *RIOGetCmdBlk(void); void RIOFreeCmdBlk(struct CmdBlk *); -int RIOQueueCmdBlk(struct Host *, uint, struct CmdBlk *); +int RIOQueueCmdBlk(struct Host *, unsigned int, struct CmdBlk *); void RIOPollHostCommands(struct rio_info *, struct Host *); -int RIOWFlushMark(int, struct CmdBlk *); -int RIORFlushEnable(int, struct CmdBlk *); -int RIOUnUse(int, struct CmdBlk *); -void ShowPacket(uint, struct PKT *); +int RIOWFlushMark(unsigned long, struct CmdBlk *); +int RIORFlushEnable(unsigned long, struct CmdBlk *); +int RIOUnUse(unsigned long, struct CmdBlk *); +void ShowPacket(unsigned int, struct PKT *); /* rioctrl.c */ -int copyin(int, caddr_t, int); int riocontrol(struct rio_info *, dev_t, int, caddr_t, int); -int RIOPreemptiveCmd(struct rio_info *, struct Port *, uchar); +int RIOPreemptiveCmd(struct rio_info *, struct Port *, unsigned char); /* rioinit.c */ void rioinit(struct rio_info *, struct RioHostInfo *); @@ -80,19 +79,19 @@ void RIOISAinit(struct rio_info *, int); int RIODoAT(struct rio_info *, int, int); caddr_t RIOCheckForATCard(int); int RIOAssignAT(struct rio_info *, int, caddr_t, int); -int RIOBoardTest(paddr_t, caddr_t, uchar, int); +int RIOBoardTest(paddr_t, caddr_t, unsigned char, int); void RIOAllocDataStructs(struct rio_info *); void RIOSetupDataStructs(struct rio_info *); -int RIODefaultName(struct rio_info *, struct Host *, uint); +int RIODefaultName(struct rio_info *, struct Host *, unsigned int); struct rioVersion *RIOVersid(void); int RIOMapin(paddr_t, int, caddr_t *); void RIOMapout(paddr_t, long, caddr_t); -void RIOHostReset(uint, volatile struct DpRam *, uint); +void RIOHostReset(unsigned int, struct DpRam *, unsigned int); /* riointr.c */ void RIOTxEnable(char *); void RIOServiceHost(struct rio_info *, struct Host *, int); -int riotproc(struct rio_info *, register struct ttystatics *, int, int); +int riotproc(struct rio_info *, struct ttystatics *, int, int); /* rioparam.c */ int RIOParam(struct Port *, int, int, int); @@ -106,18 +105,18 @@ int can_remove_receive(struct PKT **, struct Port *); void remove_receive(struct Port *); /* rioroute.c */ -int RIORouteRup(struct rio_info *, uint, struct Host *, struct PKT *); -void RIOFixPhbs(struct rio_info *, struct Host *, uint); -uint GetUnitType(uint); +int RIORouteRup(struct rio_info *, unsigned int, struct Host *, struct PKT *); +void RIOFixPhbs(struct rio_info *, struct Host *, unsigned int); +unsigned int GetUnitType(unsigned int); int RIOSetChange(struct rio_info *); -int RIOFindFreeID(struct rio_info *, struct Host *, uint *, uint *); +int RIOFindFreeID(struct rio_info *, struct Host *, unsigned int *, unsigned int *); /* riotty.c */ int riotopen(struct tty_struct *tty, struct file *filp); int riotclose(void *ptr); -int riotioctl(struct rio_info *, struct tty_struct *, register int, register caddr_t); +int riotioctl(struct rio_info *, struct tty_struct *, int, caddr_t); void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg); /* riotable.c */ @@ -131,7 +130,7 @@ int RIOChangeName(struct rio_info *, struct Map *); #if 0 /* riodrvr.c */ struct rio_info *rio_install(struct RioHostInfo *); -int rio_uninstall(register struct rio_info *); +int rio_uninstall(struct rio_info *); int rio_open(struct rio_info *, int, struct file *); int rio_close(struct rio_info *, struct file *); int rio_read(struct rio_info *, struct file *, char *, int); @@ -143,7 +142,7 @@ int rio_isr_thread(char *); struct rio_info *rio_info_store(int cmd, struct rio_info *p); #endif -extern int rio_pcicopy(char *src, char *dst, int n); +extern void rio_copy_to_card(void *to, void *from, int len); extern int rio_minor(struct tty_struct *tty); extern int rio_ismodem(struct tty_struct *tty); diff --git a/drivers/char/rio/rio.h b/drivers/char/rio/rio.h index 7f45e1ab5332..2d466ffe112d 100644 --- a/drivers/char/rio/rio.h +++ b/drivers/char/rio/rio.h @@ -186,8 +186,8 @@ static char *_rio_h_sccs_ = "@(#)rio.h 1.3"; ** RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and ** returns the offset into the DP RAM area. */ -#define RIO_PTR(C,O) (((caddr_t)(C))+(0xFFFF&(O))) -#define RIO_OFF(C,O) ((int)(O)-(int)(C)) +#define RIO_PTR(C,O) (((unsigned char *)(C))+(0xFFFF&(O))) +#define RIO_OFF(C,O) ((long)(O)-(long)(C)) /* ** How to convert from various different device number formats: diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index c9af283a811d..f1e9e9a20c85 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -297,7 +297,7 @@ static void my_hd(void *ad, int len) unsigned char *addr = ad; for (i = 0; i < len; i += 16) { - rio_dprintk(RIO_DEBUG_PARAM, "%08x ", (int) addr + i); + rio_dprintk(RIO_DEBUG_PARAM, "%08lx ", (unsigned long) addr + i); for (j = 0; j < 16; j++) { rio_dprintk(RIO_DEBUG_PARAM, "%02x %s", addr[j + i], (j == 7) ? " " : ""); } @@ -340,13 +340,16 @@ int RIODelay_ni(struct Port *PortP, int njiffies) return !RIO_FAIL; } +void rio_copy_to_card(void *to, void *from, int len) +{ + rio_memcpy_toio(NULL, to, from, len); +} int rio_minor(struct tty_struct *tty) { return tty->index + (tty->driver == rio_driver) ? 0 : 256; } - int rio_ismodem(struct tty_struct *tty) { return 1; @@ -379,7 +382,7 @@ static void rio_reset_interrupt(struct Host *HostP) case RIO_AT: case RIO_MCA: case RIO_PCI: - WBYTE(HostP->ResetInt, 0xff); + writeb(0xFF, &HostP->ResetInt); } func_exit(); @@ -397,9 +400,6 @@ static irqreturn_t rio_interrupt(int irq, void *ptr, struct pt_regs *regs) /* AAargh! The order in which to do these things is essential and not trivial. - - Rate limit goes before "recursive". Otherwise a series of - recursive calls will hang the machine in the interrupt routine. - - hardware twiddling goes before "recursive". Otherwise when we poll the card, and a recursive interrupt happens, we won't ack the card, so it might keep on interrupting us. (especially @@ -414,26 +414,6 @@ static irqreturn_t rio_interrupt(int irq, void *ptr, struct pt_regs *regs) - The initialized test goes before recursive. */ - - -#ifdef IRQ_RATE_LIMIT - /* Aaargh! I'm ashamed. This costs more lines-of-code than the - actual interrupt routine!. (Well, used to when I wrote that comment) */ - { - static int lastjif; - static int nintr = 0; - - if (lastjif == jiffies) { - if (++nintr > IRQ_RATE_LIMIT) { - free_irq(HostP->Ivec, ptr); - printk(KERN_ERR "rio: Too many interrupts. Turning off interrupt %d.\n", HostP->Ivec); - } - } else { - lastjif = jiffies; - nintr = 0; - } - } -#endif rio_dprintk(RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n"); if (HostP->Ivec == irq) { /* Tell the card we've noticed the interrupt. */ @@ -444,13 +424,13 @@ static irqreturn_t rio_interrupt(int irq, void *ptr, struct pt_regs *regs) return IRQ_HANDLED; if (test_and_set_bit(RIO_BOARD_INTR_LOCK, &HostP->locks)) { - printk(KERN_ERR "Recursive interrupt! (host %d/irq%d)\n", (int) ptr, HostP->Ivec); + printk(KERN_ERR "Recursive interrupt! (host %p/irq%d)\n", ptr, HostP->Ivec); return IRQ_HANDLED; } RIOServiceHost(p, HostP, irq); - rio_dprintk(RIO_DEBUG_IFLOW, "riointr() doing host %d type %d\n", (int) ptr, HostP->Type); + rio_dprintk(RIO_DEBUG_IFLOW, "riointr() doing host %p type %d\n", ptr, HostP->Type); clear_bit(RIO_BOARD_INTR_LOCK, &HostP->locks); rio_dprintk(RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", irq, HostP->Ivec); @@ -873,7 +853,7 @@ static int rio_init_datastructures(void) #define HOST_SZ sizeof(struct Host) #define PORT_SZ sizeof(struct Port *) #define TMIO_SZ sizeof(struct termios *) - rio_dprintk(RIO_DEBUG_INIT, "getting : %d %d %d %d %d bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ); + rio_dprintk(RIO_DEBUG_INIT, "getting : %Zd %Zd %Zd %Zd %Zd bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ); if (!(p = ckmalloc(RI_SZ))) goto free0; @@ -963,22 +943,21 @@ static void __exit rio_release_drivers(void) static void fix_rio_pci(struct pci_dev *pdev) { - unsigned int hwbase; - unsigned long rebase; + unsigned long hwbase; + unsigned char *rebase; unsigned int t; #define CNTRL_REG_OFFSET 0x50 #define CNTRL_REG_GOODVALUE 0x18260000 - pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase); - hwbase &= PCI_BASE_ADDRESS_MEM_MASK; - rebase = (ulong) ioremap(hwbase, 0x80); + hwbase = pci_resource_start(pdev, 0); + rebase = ioremap(hwbase, 0x80); t = readl(rebase + CNTRL_REG_OFFSET); if (t != CNTRL_REG_GOODVALUE) { printk(KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE); writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); } - iounmap((char *) rebase); + iounmap(rebase); } #endif @@ -1049,7 +1028,7 @@ static int __init rio_init(void) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->CardP = (struct DpRam *) hp->Caddr; hp->Type = RIO_PCI; - hp->Copy = rio_pcicopy; + hp->Copy = rio_copy_to_card; hp->Mode = RIO_PCI_BOOT_FROM_RAM; spin_lock_init(&hp->HostLock); rio_reset_interrupt(hp); @@ -1058,10 +1037,10 @@ static int __init rio_init(void) rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == RIO_SUCCESS) { rio_dprintk(RIO_DEBUG_INIT, "Done RIOBoardTest\n"); - WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); + writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); p->RIOHosts[p->RIONumHosts].UniqueNum = - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) | - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) | + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); fix_rio_pci(pdev); @@ -1099,7 +1078,7 @@ static int __init rio_init(void) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->CardP = (struct DpRam *) hp->Caddr; hp->Type = RIO_PCI; - hp->Copy = rio_pcicopy; + hp->Copy = rio_copy_to_card; hp->Mode = RIO_PCI_BOOT_FROM_RAM; spin_lock_init(&hp->HostLock); @@ -1110,10 +1089,10 @@ static int __init rio_init(void) rio_start_card_running(hp); rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == RIO_SUCCESS) { - WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); + writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); p->RIOHosts[p->RIONumHosts].UniqueNum = - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) | - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) | + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); p->RIOLastPCISearch = RIO_SUCCESS; @@ -1137,8 +1116,8 @@ static int __init rio_init(void) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->CardP = (struct DpRam *) hp->Caddr; hp->Type = RIO_AT; - hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL - * -- YES! this is now a normal copy. Only the + hp->Copy = rio_copy_to_card; /* AT card PCI???? - PVDL + * -- YES! this is now a normal copy. Only the * old PCI card uses the special PCI copy. * Moreover, the ISA card will work with the * special PCI copy anyway. -- REW */ diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index 694bfb9d9378..08fcac1f12de 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c @@ -42,6 +42,7 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2"; #include #include #include +#include #include #include @@ -143,17 +144,17 @@ int RIOZombieRta(struct Host *HostP, struct Map *MapP) return 0; } -int RIOCommandRta(struct rio_info *p, uint RtaUnique, int (*func) (struct Host * HostP, struct Map * MapP)) +int RIOCommandRta(struct rio_info *p, unsigned long RtaUnique, int (*func) (struct Host * HostP, struct Map * MapP)) { - uint Host; + unsigned int Host; - rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%x func 0x%x\n", RtaUnique, (int) func); + rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%lx func 0x%p\n", RtaUnique, func); if (!RtaUnique) return (0); for (Host = 0; Host < p->RIONumHosts; Host++) { - uint Rta; + unsigned int Rta; struct Host *HostP = &p->RIOHosts[Host]; for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) { @@ -170,7 +171,7 @@ int RIOCommandRta(struct rio_info *p, uint RtaUnique, int (*func) (struct Host * ** any connections, we can get to it. */ for (Link = 0; Link < LINKS_PER_UNIT; Link++) { - if (MapP->Topology[Link].Unit <= (uchar) MAX_RUP) { + if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) { /* ** Its worth trying the operation... */ @@ -184,18 +185,18 @@ int RIOCommandRta(struct rio_info *p, uint RtaUnique, int (*func) (struct Host * } -int RIOIdentifyRta(struct rio_info *p, caddr_t arg) +int RIOIdentifyRta(struct rio_info *p, void * arg) { - uint Host; + unsigned int Host; - if (copyin((int) arg, (caddr_t) & IdRta, sizeof(IdRta)) == COPYFAIL) { + if (copy_from_user(&IdRta, arg, sizeof(IdRta))) { rio_dprintk(RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } for (Host = 0; Host < p->RIONumHosts; Host++) { - uint Rta; + unsigned int Rta; struct Host *HostP = &p->RIOHosts[Host]; for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) { @@ -211,7 +212,7 @@ int RIOIdentifyRta(struct rio_info *p, caddr_t arg) ** any connections, we can get to it. */ for (Link = 0; Link < LINKS_PER_UNIT; Link++) { - if (MapP->Topology[Link].Unit <= (uchar) MAX_RUP) { + if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) { /* ** Its worth trying the operation... */ @@ -249,7 +250,7 @@ int RIOIdentifyRta(struct rio_info *p, caddr_t arg) } -int RIOKillNeighbour(struct rio_info *p, caddr_t arg) +int RIOKillNeighbour(struct rio_info *p, void * arg) { uint Host; uint ID; @@ -258,7 +259,7 @@ int RIOKillNeighbour(struct rio_info *p, caddr_t arg) rio_dprintk(RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n"); - if (copyin((int) arg, (caddr_t) & KillUnit, sizeof(KillUnit)) == COPYFAIL) { + if (copy_from_user(&KillUnit, arg, sizeof(KillUnit))) { rio_dprintk(RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -344,7 +345,7 @@ int RIOSuspendBootRta(struct Host *HostP, int ID, int Link) int RIOFoadWakeup(struct rio_info *p) { int port; - register struct Port *PortP; + struct Port *PortP; unsigned long flags; for (port = 0; port < RIO_PORTS; port++) { @@ -379,10 +380,10 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data; struct Port *PortP; struct UnixRup *UnixRupP; - ushort SysPort; - ushort ReportedModemStatus; - ushort rup; - ushort subCommand; + unsigned short SysPort; + unsigned short ReportedModemStatus; + unsigned short rup; + unsigned short subCommand; unsigned long flags; func_enter(); @@ -395,18 +396,18 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * ** we can use PhbNum to get the rup number for the appropriate 8 port ** block (for the first block, this should be equal to 'Rup'). */ - rup = RBYTE(PktCmdP->PhbNum) / (ushort) PORTS_PER_RTA; + rup = readb(&PktCmdP->PhbNum) / (unsigned short) PORTS_PER_RTA; UnixRupP = &HostP->UnixRups[rup]; - SysPort = UnixRupP->BaseSysPort + (RBYTE(PktCmdP->PhbNum) % (ushort) PORTS_PER_RTA); + SysPort = UnixRupP->BaseSysPort + (readb(&PktCmdP->PhbNum) % (unsigned short) PORTS_PER_RTA); rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort); if (UnixRupP->BaseSysPort == NO_PORT) { rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n"); rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n"); - rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %d, name ``%s''\n", HostP - p->RIOHosts, HostP->Name); + rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name); rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup); - if (Rup >= (ushort) MAX_RUP) { + if (Rup >= (unsigned short) MAX_RUP) { rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name); } else rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name); @@ -421,7 +422,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * } PortP = p->RIOPortp[SysPort]; rio_spin_lock_irqsave(&PortP->portSem, flags); - switch (RBYTE(PktCmdP->Command)) { + switch (readb(&PktCmdP->Command)) { case BREAK_RECEIVED: rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n"); /* If the current line disc. is not multi-threading and @@ -434,15 +435,15 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * break; case COMPLETE: - rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %d\n", RBYTE(PktCmdP->PhbNum), HostP - p->RIOHosts); + rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %Zd\n", readb(&PktCmdP->PhbNum), HostP - p->RIOHosts); subCommand = 1; - switch (RBYTE(PktCmdP->SubCommand)) { + switch (readb(&PktCmdP->SubCommand)) { case MEMDUMP: - rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr)); + rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", readb(&PktCmdP->SubCommand), readw(&PktCmdP->SubAddr)); break; case READ_REGISTER: - rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", RWORD(PktCmdP->SubAddr)); - p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST); + rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", readw(&PktCmdP->SubAddr)); + p->CdRegister = (readb(&PktCmdP->ModemStatus) & MSVR1_HOST); break; default: subCommand = 0; @@ -450,10 +451,10 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * } if (subCommand) break; - rio_dprintk(RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", RBYTE(PktCmdP->PortStatus), PortP->PortState); - if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) { + rio_dprintk(RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", readb(&PktCmdP->PortStatus), PortP->PortState); + if (PortP->PortState != readb(&PktCmdP->PortStatus)) { rio_dprintk(RIO_DEBUG_CMD, "Mark status & wakeup\n"); - PortP->PortState = RBYTE(PktCmdP->PortStatus); + PortP->PortState = readb(&PktCmdP->PortStatus); /* What should we do here ... wakeup( &PortP->PortState ); */ @@ -467,7 +468,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * ** to the check for modem status change (they're just there because ** it's a convenient place to put them!). */ - ReportedModemStatus = RBYTE(PktCmdP->ModemStatus); + ReportedModemStatus = readb(&PktCmdP->ModemStatus); if ((PortP->ModemState & MSVR1_HOST) == (ReportedModemStatus & MSVR1_HOST)) { rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState); /* @@ -514,9 +515,6 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * */ if (PortP->State & (PORT_ISOPEN | RIO_WOPEN)) wake_up_interruptible(&PortP->gs.open_wait); -#ifdef STATS - PortP->Stat.ModemOnCnt++; -#endif } } else { /* @@ -527,9 +525,6 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * tty_hangup(PortP->gs.tty); PortP->State &= ~RIO_CARR_ON; rio_dprintk(RIO_DEBUG_CMD, "Carrirer just went down\n"); -#ifdef STATS - PortP->Stat.ModemOffCnt++; -#endif } } } @@ -539,7 +534,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * break; default: - rio_dprintk(RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %d\n", RBYTE(PktCmdP->Command), HostP - p->RIOHosts); + rio_dprintk(RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %Zd\n", readb(&PktCmdP->Command), HostP - p->RIOHosts); break; } rio_spin_unlock_irqrestore(&PortP->portSem, flags); @@ -566,10 +561,9 @@ struct CmdBlk *RIOGetCmdBlk(void) { struct CmdBlk *CmdBlkP; - CmdBlkP = (struct CmdBlk *) sysbrk(sizeof(struct CmdBlk)); + CmdBlkP = (struct CmdBlk *)kmalloc(sizeof(struct CmdBlk), GFP_ATOMIC); if (CmdBlkP) - bzero(CmdBlkP, sizeof(struct CmdBlk)); - + memset(CmdBlkP, 0, sizeof(struct CmdBlk)); return CmdBlkP; } @@ -578,7 +572,7 @@ struct CmdBlk *RIOGetCmdBlk(void) */ void RIOFreeCmdBlk(struct CmdBlk *CmdBlkP) { - sysfree((void *) CmdBlkP, sizeof(struct CmdBlk)); + kfree(CmdBlkP); } /* @@ -591,7 +585,7 @@ int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) struct UnixRup *UnixRupP; unsigned long flags; - if (Rup >= (ushort) (MAX_RUP + LINKS_PER_UNIT)) { + if (Rup >= (unsigned short) (MAX_RUP + LINKS_PER_UNIT)) { rio_dprintk(RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n", Rup); RIOFreeCmdBlk(CmdBlkP); return RIO_FAIL; @@ -605,7 +599,7 @@ int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) ** If the RUP is currently inactive, then put the request ** straight on the RUP.... */ - if ((UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) + if ((UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : TRUE)) { rio_dprintk(RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", CmdBlkP->Packet.data[0]); @@ -622,7 +616,7 @@ int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) /* ** set the command register */ - WWORD(UnixRupP->RupP->txcontrol, TX_PACKET_READY); + writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol); rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); @@ -634,20 +628,20 @@ int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) rio_dprintk(RIO_DEBUG_CMD, "Rup active - command waiting\n"); if (UnixRupP->CmdPendingP != NULL) rio_dprintk(RIO_DEBUG_CMD, "Rup active - command pending\n"); - if (RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE) + if (readw(&UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE) rio_dprintk(RIO_DEBUG_CMD, "Rup active - command rup not ready\n"); Base = &UnixRupP->CmdsWaitingP; - rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk 0x%x at 0x%x\n", (int) CmdBlkP, (int) Base); + rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk 0x%p at 0x%p\n", CmdBlkP, Base); while (*Base) { - rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk 0x%x here\n", (int) (*Base)); + rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk 0x%p here\n", *Base); Base = &((*Base)->NextP); - rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk 0x%x at 0x%x\n", (int) CmdBlkP, (int) Base); + rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk 0x%p at 0x%p\n", CmdBlkP, Base); } - rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk 0x%x at 0x%x\n", (int) CmdBlkP, (int) Base); + rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk 0x%p at 0x%p\n", CmdBlkP, Base); *Base = CmdBlkP; @@ -664,10 +658,10 @@ int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) */ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) { - register struct CmdBlk *CmdBlkP; - register struct UnixRup *UnixRupP; + struct CmdBlk *CmdBlkP; + struct UnixRup *UnixRupP; struct PKT *PacketP; - ushort Rup; + unsigned short Rup; unsigned long flags; @@ -684,16 +678,16 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) /* ** First check for incoming commands: */ - if (RWORD(UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) { + if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) { int FreeMe; - PacketP = (PKT *) RIO_PTR(HostP->Caddr, RWORD(UnixRupP->RupP->rxpkt)); + PacketP = (PKT *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt)); ShowPacket(DBG_CMD, PacketP); - switch (RBYTE(PacketP->dest_port)) { + switch (readb(&PacketP->dest_port)) { case BOOT_RUP: - rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", RBYTE(PacketP->len) & 0x80 ? "Command" : "Data", RBYTE(PacketP->data[0])); + rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", readb(&PacketP->len) & 0x80 ? "Command" : "Data", readb(&PacketP->data[0])); rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); FreeMe = RIOBootRup(p, Rup, HostP, PacketP); rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); @@ -708,7 +702,7 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); FreeMe = RIOCommandRup(p, Rup, HostP, PacketP); if (PacketP->data[5] == MEMDUMP) { - rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", *(ushort *) & (PacketP->data[6])); + rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", *(unsigned short *) & (PacketP->data[6])); HostP->Copy((caddr_t) & (PacketP->data[8]), (caddr_t) p->RIOMemDump, 32); } rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); @@ -721,7 +715,7 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) break; default: - rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", RBYTE(PacketP->dest_port)); + rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", readb(&PacketP->dest_port)); FreeMe = 1; break; } @@ -730,11 +724,11 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) rio_dprintk(RIO_DEBUG_CMD, "Free processed incoming command packet\n"); put_free_end(HostP, PacketP); - WWORD(UnixRupP->RupP->rxcontrol, RX_RUP_INACTIVE); + writew(RX_RUP_INACTIVE, &UnixRupP->RupP->rxcontrol); - if (RWORD(UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) { + if (readw(&UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) { rio_dprintk(RIO_DEBUG_CMD, "Handshake rup %d\n", Rup); - WWORD(UnixRupP->RupP->handshake, PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET); + writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &UnixRupP->RupP->handshake); } } } @@ -744,7 +738,7 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) ** and it has completed, then tidy it up. */ if ((CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */ - (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { + (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { /* ** we are idle. ** there is a command in pending. @@ -755,7 +749,7 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) if (CmdBlkP->Packet.dest_port == BOOT_RUP) rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]); - rio_dprintk(RIO_DEBUG_CMD, "Command 0x%x completed\n", (int) CmdBlkP); + rio_dprintk(RIO_DEBUG_CMD, "Command 0x%p completed\n", CmdBlkP); /* ** Clear the Rup lock to prevent mutual exclusion. @@ -782,16 +776,16 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) ** is idle, then process the command */ if ((CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */ - (UnixRupP->CmdPendingP == NULL) && (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { + (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { /* ** if the pre-function is non-zero, call it. ** If it returns RIO_FAIL then don't ** send this command yet! */ if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : TRUE)) { - rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command 0x%x\n", (int) CmdBlkP); + rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command 0x%p\n", CmdBlkP); } else { - rio_dprintk(RIO_DEBUG_CMD, "Start new command 0x%x Cmd byte is 0x%x\n", (int) CmdBlkP, CmdBlkP->Packet.data[0]); + rio_dprintk(RIO_DEBUG_CMD, "Start new command 0x%p Cmd byte is 0x%x\n", CmdBlkP, CmdBlkP->Packet.data[0]); /* ** Whammy! blat that pack! */ @@ -810,7 +804,7 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) /* ** set the command register */ - WWORD(UnixRupP->RupP->txcontrol, TX_PACKET_READY); + writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol); /* ** the command block will be freed @@ -822,7 +816,7 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) } while (Rup); } -int RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP) +int RIOWFlushMark(unsigned long iPortP, struct CmdBlk *CmdBlkP) { struct Port *PortP = (struct Port *) iPortP; unsigned long flags; @@ -834,7 +828,7 @@ int RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP) return RIOUnUse(iPortP, CmdBlkP); } -int RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP) +int RIORFlushEnable(unsigned long iPortP, struct CmdBlk *CmdBlkP) { struct Port *PortP = (struct Port *) iPortP; PKT *PacketP; @@ -848,19 +842,19 @@ int RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP) put_free_end(PortP->HostP, PacketP); } - if (RWORD(PortP->PhbP->handshake) == PHB_HANDSHAKE_SET) { + if (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET) { /* ** MAGIC! (Basically, handshake the RX buffer, so that ** the RTAs upstream can be re-enabled.) */ rio_dprintk(RIO_DEBUG_CMD, "Util: Set RX handshake bit\n"); - WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET); + writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake); } rio_spin_unlock_irqrestore(&PortP->portSem, flags); return RIOUnUse(iPortP, CmdBlkP); } -int RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP) +int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP) { struct Port *PortP = (struct Port *) iPortP; unsigned long flags; @@ -890,7 +884,7 @@ int RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP) ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data ** hanging around in the transmit buffer is sent immediately. */ - WWORD(PortP->HostP->ParmMapP->tx_intr, 1); + writew(1, &PortP->HostP->ParmMapP->tx_intr); /* What to do here .. wakeup( (caddr_t)&(PortP->InUse) ); */ diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c index 0d44ef464e6b..1d73c4646bbd 100644 --- a/drivers/char/rio/rioinit.c +++ b/drivers/char/rio/rioinit.c @@ -82,9 +82,6 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3"; #include "rioioctl.h" #include "rio_linux.h" -#undef bcopy -#define bcopy rio_pcicopy - int RIOPCIinit(struct rio_info *p, int Mode); static int RIOScrub(int, BYTE *, int); @@ -99,12 +96,8 @@ static int RIOScrub(int, BYTE *, int); ** bits < 0 indicates 8 bit operation requested, ** bits > 0 indicates 16 bit operation. */ -int -RIOAssignAT(p, Base, virtAddr, mode) -struct rio_info * p; -int Base; -caddr_t virtAddr; -int mode; + +int RIOAssignAT(struct rio_info *p, int Base, caddr_t virtAddr, int mode) { int bits; struct DpRam *cardp = (struct DpRam *)virtAddr; @@ -124,29 +117,25 @@ int mode; /* ** Revision 01 AT host cards don't support WORD operations, */ - if ( RBYTE(cardp->DpRevision) == 01 ) + if (readb(&cardp->DpRevision) == 01) bits = BYTE_OPERATION; p->RIOHosts[p->RIONumHosts].Type = RIO_AT; - p->RIOHosts[p->RIONumHosts].Copy = bcopy; + p->RIOHosts[p->RIONumHosts].Copy = rio_copy_to_card; /* set this later */ p->RIOHosts[p->RIONumHosts].Slot = -1; p->RIOHosts[p->RIONumHosts].Mode = SLOW_LINKS | SLOW_AT_BUS | bits; - WBYTE(p->RIOHosts[p->RIONumHosts].Control, - BOOT_FROM_RAM | EXTERNAL_BUS_OFF | - p->RIOHosts[p->RIONumHosts].Mode | - INTERRUPT_DISABLE ); - WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff); - WBYTE(p->RIOHosts[p->RIONumHosts].Control, - BOOT_FROM_RAM | EXTERNAL_BUS_OFF | - p->RIOHosts[p->RIONumHosts].Mode | - INTERRUPT_DISABLE ); - WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff); + writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE , + &p->RIOHosts[p->RIONumHosts].Control); + writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); + writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE, + &p->RIOHosts[p->RIONumHosts].Control); + writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); p->RIOHosts[p->RIONumHosts].UniqueNum = - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24); + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)| + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)| + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)| + ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24); rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum); p->RIONumHosts++; @@ -154,7 +143,7 @@ int mode; return(1); } -static uchar val[] = { +static u8 val[] = { #ifdef VERY_LONG_TEST 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xa5, 0xff, 0x5a, 0x00, 0xff, 0xc9, 0x36, @@ -167,12 +156,7 @@ static uchar val[] = { ** RAM test a board. ** Nothing too complicated, just enough to check it out. */ -int -RIOBoardTest(paddr, caddr, type, slot) -paddr_t paddr; -caddr_t caddr; -uchar type; -int slot; +int RIOBoardTest(paddr_t paddr, caddr_t caddr, unsigned char type, int slot) { struct DpRam *DpRam = (struct DpRam *)caddr; char *ram[4]; @@ -180,8 +164,8 @@ int slot; int op, bank; int nbanks; - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=0x%x, slot=%d\n", - type,(int)DpRam, slot); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=0x%p, slot=%d\n", + type, DpRam, slot); RIOHostReset(type, DpRam, slot); @@ -209,12 +193,11 @@ int slot; if (nbanks == 3) { - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n", - (int)ram[0], size[0], (int)ram[1], size[1], (int)ram[2], size[2]); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: 0x%p(0x%x), 0x%p(0x%x), 0x%p(0x%x)\n", + ram[0], size[0], ram[1], size[1], ram[2], size[2]); } else { - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n", - (int)ram[0], size[0], (int)ram[1], size[1], (int)ram[2], size[2], (int)ram[3], - size[3]); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: 0x%p(0x%x), 0x%p(0x%x), 0x%p(0x%x), 0x%p(0x%x)\n", + ram[0], size[0], ram[1], size[1], ram[2], size[2], ram[3], size[3]); } /* @@ -248,13 +231,10 @@ int slot; ** Call with op not zero, and the RAM will be read and compated with val[op-1] ** to check that the data from the previous phase was retained. */ -static int -RIOScrub(op, ram, size) -int op; -BYTE * ram; -int size; + +static int RIOScrub(int op, BYTE *ram, int size) { - int off; + int off; unsigned char oldbyte; unsigned char newbyte; unsigned char invbyte; @@ -279,15 +259,15 @@ int size; */ if (op) { for (off=0; offMapping[UnitId].Name,17); + memcpy(HostP->Mapping[UnitId].Name, "UNKNOWN RTA X-XX", 17); HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts); if ((UnitId+1) > 9) { HostP->Mapping[UnitId].Name[14]='0'+((UnitId+1)/10); @@ -412,8 +388,7 @@ uint UnitId; static struct rioVersion stVersion; -struct rioVersion * -RIOVersid(void) +struct rioVersion *RIOVersid(void) { strlcpy(stVersion.version, "RIO driver for linux V1.0", sizeof(stVersion.version)); @@ -423,40 +398,31 @@ RIOVersid(void) return &stVersion; } -void -RIOHostReset(Type, DpRamP, Slot) -uint Type; -volatile struct DpRam *DpRamP; -uint Slot; +void RIOHostReset(unsigned int Type, struct DpRam *DpRamP, unsigned int Slot) { /* ** Reset the Tpu */ rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: type 0x%x", Type); switch ( Type ) { - case RIO_AT: - rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n"); - WBYTE(DpRamP->DpControl, BOOT_FROM_RAM | EXTERNAL_BUS_OFF | - INTERRUPT_DISABLE | BYTE_OPERATION | - SLOW_LINKS | SLOW_AT_BUS); - WBYTE(DpRamP->DpResetTpu, 0xFF); - udelay(3); - + case RIO_AT: + rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n"); + writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | BYTE_OPERATION | + SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl); + writeb(0xFF, &DpRamP->DpResetTpu); + udelay(3); rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: Don't know if it worked. Try reset again\n"); - WBYTE(DpRamP->DpControl, BOOT_FROM_RAM | EXTERNAL_BUS_OFF | - INTERRUPT_DISABLE | BYTE_OPERATION | - SLOW_LINKS | SLOW_AT_BUS); - WBYTE(DpRamP->DpResetTpu, 0xFF); - udelay(3); - break; + writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | + BYTE_OPERATION | SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl); + writeb(0xFF, &DpRamP->DpResetTpu); + udelay(3); + break; case RIO_PCI: rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n"); - DpRamP->DpControl = RIO_PCI_BOOT_FROM_RAM; - DpRamP->DpResetInt = 0xFF; - DpRamP->DpResetTpu = 0xFF; + writeb(RIO_PCI_BOOT_FROM_RAM, &DpRamP->DpControl); + writeb(0xFF, &DpRamP->DpResetInt); + writeb(0xFF, &DpRamP->DpResetTpu); udelay(100); - /* for (i=0; i<6000; i++); */ - /* suspend( 3 ); */ break; default: rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n"); diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c index 34d8787557a1..ec415ccbc4f0 100644 --- a/drivers/char/rio/riointr.c +++ b/drivers/char/rio/riointr.c @@ -101,8 +101,7 @@ static char *firstchars(char *p, int nch) #define INCR( P, I ) ((P) = (((P)+(I)) & p->RIOBufferMask)) /* Enable and start the transmission of packets */ -void RIOTxEnable(en) -char *en; +void RIOTxEnable(char *en) { struct Port *PortP; struct rio_info *p; @@ -186,10 +185,8 @@ char *en; static int RupIntr; static int RxIntr; static int TxIntr; -void RIOServiceHost(p, HostP, From) -struct rio_info *p; -struct Host *HostP; -int From; + +void RIOServiceHost(struct rio_info *p, struct Host *HostP, int From) { rio_spin_lock(&HostP->HostLock); if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { @@ -201,22 +198,22 @@ int From; } rio_spin_unlock(&HostP->HostLock); - if (RWORD(HostP->ParmMapP->rup_intr)) { - WWORD(HostP->ParmMapP->rup_intr, 0); + if (readw(&HostP->ParmMapP->rup_intr)) { + writew(0, &HostP->ParmMapP->rup_intr); p->RIORupCount++; RupIntr++; - rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %d\n", HostP - p->RIOHosts); + rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %Zd\n", HostP - p->RIOHosts); RIOPollHostCommands(p, HostP); } - if (RWORD(HostP->ParmMapP->rx_intr)) { + if (readw(&HostP->ParmMapP->rx_intr)) { int port; - WWORD(HostP->ParmMapP->rx_intr, 0); + writew(0, &HostP->ParmMapP->rx_intr); p->RIORxCount++; RxIntr++; - rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %d\n", HostP - p->RIOHosts); + rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %Zd\n", HostP - p->RIOHosts); /* ** Loop through every port. If the port is mapped into ** the system ( i.e. has /dev/ttyXXXX associated ) then it is @@ -277,26 +274,26 @@ int From; ** it's handshake bit is set, then we must clear the handshake, ** so that that downstream RTA is re-enabled. */ - if (!can_remove_receive(&PacketP, PortP) && (RWORD(PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) { + if (!can_remove_receive(&PacketP, PortP) && (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) { /* ** MAGIC! ( Basically, handshake the RX buffer, so that ** the RTAs upstream can be re-enabled. ) */ rio_dprintk(RIO_DEBUG_INTR, "Set RX handshake bit\n"); - WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET); + writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake); } rio_spin_unlock(&PortP->portSem); } } - if (RWORD(HostP->ParmMapP->tx_intr)) { + if (readw(&HostP->ParmMapP->tx_intr)) { int port; - WWORD(HostP->ParmMapP->tx_intr, 0); + writew(0, &HostP->ParmMapP->tx_intr); p->RIOTxCount++; TxIntr++; - rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %d\n", HostP - p->RIOHosts); + rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %Zd\n", HostP - p->RIOHosts); /* ** Loop through every port. @@ -445,9 +442,9 @@ int From; */ PktCmdP = (struct PktCmd *) &PacketP->data[0]; - WBYTE(PktCmdP->Command, WFLUSH); + writeb(WFLUSH, &PktCmdP->Command); - p = PortP->HostPort % (ushort) PORTS_PER_RTA; + p = PortP->HostPort % (u16) PORTS_PER_RTA; /* ** If second block of ports for 16 port RTA, add 8 @@ -456,27 +453,27 @@ int From; if (PortP->SecondBlock) p += PORTS_PER_RTA; - WBYTE(PktCmdP->PhbNum, p); + writeb(p, &PktCmdP->PhbNum); /* ** to make debuggery easier */ - WBYTE(PacketP->data[2], 'W'); - WBYTE(PacketP->data[3], 'F'); - WBYTE(PacketP->data[4], 'L'); - WBYTE(PacketP->data[5], 'U'); - WBYTE(PacketP->data[6], 'S'); - WBYTE(PacketP->data[7], 'H'); - WBYTE(PacketP->data[8], ' '); - WBYTE(PacketP->data[9], '0' + PortP->WflushFlag); - WBYTE(PacketP->data[10], ' '); - WBYTE(PacketP->data[11], ' '); - WBYTE(PacketP->data[12], '\0'); + writeb('W', &PacketP->data[2]); + writeb('F', &PacketP->data[3]); + writeb('L', &PacketP->data[4]); + writeb('U', &PacketP->data[5]); + writeb('S', &PacketP->data[6]); + writeb('H', &PacketP->data[7]); + writeb(' ', &PacketP->data[8]); + writeb('0' + PortP->WflushFlag, &PacketP->data[9]); + writeb(' ', &PacketP->data[10]); + writeb(' ', &PacketP->data[11]); + writeb('\0', &PacketP->data[12]); /* ** its two bytes long! */ - WBYTE(PacketP->len, PKT_CMD_BIT | 2); + writeb(PKT_CMD_BIT | 2, &PacketP->len); /* ** queue it! @@ -529,19 +526,15 @@ int From; } /* -** Routine for handling received data for clist drivers. -** NB: Called with the tty locked. The spl from the lockb( ) is passed. -** we return the ttySpl level that we re-locked at. +** Routine for handling received data for tty drivers */ -static void RIOReceive(p, PortP) -struct rio_info *p; -struct Port *PortP; +static void RIOReceive(struct rio_info *p, struct Port *PortP) { struct tty_struct *TtyP; - register ushort transCount; + unsigned short transCount; struct PKT *PacketP; - register uint DataCnt; - uchar *ptr; + register unsigned int DataCnt; + unsigned char *ptr; unsigned char *buf; int copied = 0; @@ -594,9 +587,6 @@ struct Port *PortP; transCount = 1; while (can_remove_receive(&PacketP, PortP) && transCount) { -#ifdef STATS - PortP->Stat.RxIntCnt++; -#endif /* STATS */ RxIntCnt++; /* @@ -642,28 +632,15 @@ struct Port *PortP; ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the ** driver). */ -#undef ___DEBUG_IT___ -#ifdef ___DEBUG_IT___ - kkprintf("I:%d R:%d P:%d Q:%d C:%d F:%x ", intCount, RxIntCnt, PortP->PortNum, TtyP->rxqueue.count, transCount, TtyP->flags); -#endif - ptr = (uchar *) PacketP->data + PortP->RxDataStart; + ptr = (unsigned char *) PacketP->data + PortP->RxDataStart; tty_prepare_flip_string(TtyP, &buf, transCount); rio_memcpy_fromio(buf, ptr, transCount); -#ifdef STATS - /* - ** keep a count for statistical purposes - */ - PortP->Stat.RxCharCnt += transCount; -#endif PortP->RxDataStart += transCount; PacketP->len -= transCount; copied += transCount; -#ifdef ___DEBUG_IT___ - kkprintf("T:%d L:%d\n", DataCnt, PacketP->len); -#endif if (PacketP->len == 0) { /* @@ -674,12 +651,6 @@ struct Port *PortP; remove_receive(PortP); put_free_end(PortP->HostP, PacketP); PortP->RxDataStart = 0; -#ifdef STATS - /* - ** more lies ( oops, I mean statistics ) - */ - PortP->Stat.RxPktCnt++; -#endif /* STATS */ } } } @@ -691,215 +662,3 @@ struct Port *PortP; return; } -#ifdef FUTURE_RELEASE -/* -** The proc routine called by the line discipline to do the work for it. -** The proc routine works hand in hand with the interrupt routine. -*/ -int riotproc(p, tp, cmd, port) -struct rio_info *p; -register struct ttystatics *tp; -int cmd; -int port; -{ - register struct Port *PortP; - int SysPort; - struct PKT *PacketP; - - SysPort = port; /* Believe me, it works. */ - - if (SysPort < 0 || SysPort >= RIO_PORTS) { - rio_dprintk(RIO_DEBUG_INTR, "Illegal port %d derived from TTY in riotproc()\n", SysPort); - return 0; - } - PortP = p->RIOPortp[SysPort]; - - if ((uint) PortP->PhbP < (uint) PortP->Caddr || (uint) PortP->PhbP >= (uint) PortP->Caddr + SIXTY_FOUR_K) { - rio_dprintk(RIO_DEBUG_INTR, "RIO: NULL or BAD PhbP on sys port %d in proc routine\n", SysPort); - rio_dprintk(RIO_DEBUG_INTR, " PortP = 0x%x\n", PortP); - rio_dprintk(RIO_DEBUG_INTR, " PortP->PhbP = 0x%x\n", PortP->PhbP); - rio_dprintk(RIO_DEBUG_INTR, " PortP->Caddr = 0x%x\n", PortP->PhbP); - rio_dprintk(RIO_DEBUG_INTR, " PortP->HostPort = 0x%x\n", PortP->HostPort); - return 0; - } - - switch (cmd) { - case T_WFLUSH: - rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH\n"); - /* - ** Because of the spooky way the RIO works, we don't need - ** to issue a flush command on any of the SET*F commands, - ** as that causes trouble with getty and login, which issue - ** these commands to incur a READ flush, and rely on the fact - ** that the line discipline does a wait for drain for them. - ** As the rio doesn't wait for drain, the write flush would - ** destroy the Password: prompt. This isn't very friendly, so - ** here we only issue a WFLUSH command if we are in the interrupt - ** routine, or we aren't executing a SET*F command. - */ - if (PortP->HostP->InIntr || !PortP->FlushCmdBodge) { - /* - ** form a wflush packet - 1 byte long, no data - */ - if (PortP->State & RIO_DELETED) { - rio_dprintk(RIO_DEBUG_INTR, "WFLUSH on deleted RTA\n"); - } else { - if (RIOPreemptiveCmd(p, PortP, WFLUSH) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH Command failed\n"); - } else - rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH Command\n"); - } - /* - ** WFLUSH operation - flush the data! - */ - PortP->TxBufferIn = PortP->TxBufferOut = 0; - } else { - rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH Command ignored\n"); - } - /* - ** sort out the line discipline - */ - if (PortP->CookMode == COOK_WELL) - goto start; - break; - - case T_RESUME: - rio_dprintk(RIO_DEBUG_INTR, "T_RESUME\n"); - /* - ** send pre-emptive resume packet - */ - if (PortP->State & RIO_DELETED) { - rio_dprintk(RIO_DEBUG_INTR, "RESUME on deleted RTA\n"); - } else { - if (RIOPreemptiveCmd(p, PortP, RESUME) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_INTR, "T_RESUME Command failed\n"); - } - } - /* - ** and re-start the sender software! - */ - if (PortP->CookMode == COOK_WELL) - goto start; - break; - - case T_TIME: - rio_dprintk(RIO_DEBUG_INTR, "T_TIME\n"); - /* - ** T_TIME is called when xDLY is set in oflags and - ** the line discipline timeout has expired. It's - ** function in life is to clear the TIMEOUT flag - ** and to re-start output to the port. - */ - /* - ** Fall through and re-start output - */ - case T_OUTPUT: - start: - if (PortP->MagicFlags & MAGIC_FLUSH) { - PortP->MagicFlags |= MORE_OUTPUT_EYGOR; - return 0; - } - RIOTxEnable((char *) PortP); - PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR; - /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"T_OUTPUT finished\n"); */ - break; - - case T_SUSPEND: - rio_dprintk(RIO_DEBUG_INTR, "T_SUSPEND\n"); - /* - ** send a suspend pre-emptive packet. - */ - if (PortP->State & RIO_DELETED) { - rio_dprintk(RIO_DEBUG_INTR, "SUSPEND deleted RTA\n"); - } else { - if (RIOPreemptiveCmd(p, PortP, SUSPEND) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_INTR, "T_SUSPEND Command failed\n"); - } - } - /* - ** done! - */ - break; - - case T_BLOCK: - rio_dprintk(RIO_DEBUG_INTR, "T_BLOCK\n"); - break; - - case T_RFLUSH: - rio_dprintk(RIO_DEBUG_INTR, "T_RFLUSH\n"); - if (PortP->State & RIO_DELETED) { - rio_dprintk(RIO_DEBUG_INTR, "RFLUSH on deleted RTA\n"); - PortP->RxDataStart = 0; - } else { - if (RIOPreemptiveCmd(p, PortP, RFLUSH) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_INTR, "T_RFLUSH Command failed\n"); - return 0; - } - PortP->RxDataStart = 0; - while (can_remove_receive(&PacketP, PortP)) { - remove_receive(PortP); - ShowPacket(DBG_PROC, PacketP); - put_free_end(PortP->HostP, PacketP); - } - if (PortP->PhbP->handshake == PHB_HANDSHAKE_SET) { - /* - ** MAGIC! - */ - rio_dprintk(RIO_DEBUG_INTR, "Set receive handshake bit\n"); - PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET; - } - } - break; - /* FALLTHROUGH */ - case T_UNBLOCK: - rio_dprintk(RIO_DEBUG_INTR, "T_UNBLOCK\n"); - /* - ** If there is any data to receive set a timeout to service it. - */ - RIOReceive(p, PortP); - break; - - case T_BREAK: - rio_dprintk(RIO_DEBUG_INTR, "T_BREAK\n"); - /* - ** Send a break command. For Sys V - ** this is a timed break, so we - ** send a SBREAK[time] packet - */ - /* - ** Build a BREAK command - */ - if (PortP->State & RIO_DELETED) { - rio_dprintk(RIO_DEBUG_INTR, "BREAK on deleted RTA\n"); - } else { - if (RIOShortCommand(PortP, SBREAK, 2, p->RIOConf.BreakInterval) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n"); - } - } - - /* - ** done! - */ - break; - - case T_INPUT: - rio_dprintk(RIO_DEBUG_INTR, "Proc T_INPUT called - I don't know what to do!\n"); - break; - case T_PARM: - rio_dprintk(RIO_DEBUG_INTR, "Proc T_PARM called - I don't know what to do!\n"); - break; - - case T_SWTCH: - rio_dprintk(RIO_DEBUG_INTR, "Proc T_SWTCH called - I don't know what to do!\n"); - break; - - default: - rio_dprintk(RIO_DEBUG_INTR, "Proc UNKNOWN command %d\n", cmd); - } - /* - ** T_OUTPUT returns without passing through this point! - */ - /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"riotproc done\n"); */ - return (0); -} -#endif -- cgit v1.2.3-59-g8ed1b From 3d336aa257ba382c3ad7883ee000cbacb761e411 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 24 Mar 2006 03:18:29 -0800 Subject: [PATCH] rio driver rework continued #4 Third large chunk of code cleanup. The split between this and #3 and #4 is fairly arbitary and due to the message length limit on the list. These patches continue the process of ripping out macros and typedefs while cleaning up lots of 32bit assumptions. Several inlines for compatibility also get removed and that causes a lot of noise. Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/rio/rioctrl.c | 390 ++++++++++++++------------------------------- 1 file changed, 118 insertions(+), 272 deletions(-) (limited to 'drivers') diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c index fcf18a061228..f6a19aae1044 100644 --- a/drivers/char/rio/rioctrl.c +++ b/drivers/char/rio/rioctrl.c @@ -131,30 +131,6 @@ static int #define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff)) -int copyin(int arg, caddr_t dp, int siz) -{ - int rv; - - rio_dprintk(RIO_DEBUG_CTRL, "Copying %d bytes from user %p to %p.\n", siz, (void *) arg, dp); - rv = copy_from_user(dp, (void *) arg, siz); - if (rv) - return COPYFAIL; - else - return rv; -} - -static int copyout(caddr_t dp, int arg, int siz) -{ - int rv; - - rio_dprintk(RIO_DEBUG_CTRL, "Copying %d bytes to user %p from %p.\n", siz, (void *) arg, dp); - rv = copy_to_user((void *) arg, dp, siz); - if (rv) - return COPYFAIL; - else - return rv; -} - int riocontrol(p, dev, cmd, arg, su) struct rio_info *p; dev_t dev; @@ -178,7 +154,7 @@ int su; Host = 0; PortP = NULL; - rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: 0x%x\n", cmd, (int) arg); + rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: 0x%p\n", cmd, arg); switch (cmd) { /* @@ -189,90 +165,34 @@ int su; ** otherwise just the specified host card will be changed. */ case RIO_SET_TIMER: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %dms\n", (uint) arg); + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", (unsigned long)arg); { int host, value; - host = (uint) arg >> 16; - value = (uint) arg & 0x0000ffff; + host = ((unsigned long) arg >> 16) & 0x0000FFFF; + value = (unsigned long) arg & 0x0000ffff; if (host == -1) { for (host = 0; host < p->RIONumHosts; host++) { if (p->RIOHosts[host].Flags == RC_RUNNING) { - WWORD(p->RIOHosts[host].ParmMapP->timer, value); + writew(value, &p->RIOHosts[host].ParmMapP->timer); } } } else if (host >= p->RIONumHosts) { return -EINVAL; } else { if (p->RIOHosts[host].Flags == RC_RUNNING) { - WWORD(p->RIOHosts[host].ParmMapP->timer, value); + writew(value, &p->RIOHosts[host].ParmMapP->timer); } } } return 0; - case RIO_IDENTIFY_DRIVER: - /* - ** 15.10.1998 ARG - ESIL 0760 part fix - ** Added driver ident string output. - ** - #ifndef __THIS_RELEASE__ - #warning Driver Version string not defined ! - #endif - cprintf("%s %s %s %s\n", - RIO_DRV_STR, - __THIS_RELEASE__, - __DATE__, __TIME__ ); - - return 0; - - case RIO_DISPLAY_HOST_CFG: - ** - ** 15.10.1998 ARG - ESIL 0760 part fix - ** Added driver host card ident string output. - ** - ** Note that the only types currently supported - ** are ISA and PCI. Also this driver does not - ** (yet) distinguish between the Old PCI card - ** and the Jet PCI card. In fact I think this - ** driver only supports JET PCI ! - ** - - for (Host = 0; Host < p->RIONumHosts; Host++) - { - HostP = &(p->RIOHosts[Host]); - - switch ( HostP->Type ) - { - case RIO_AT : - strcpy( host_type, RIO_AT_HOST_STR ); - break; - - case RIO_PCI : - strcpy( host_type, RIO_PCI_HOST_STR ); - break; - - default : - strcpy( host_type, "Unknown" ); - break; - } - - cprintf( - "RIO Host %d - Type:%s Addr:%X IRQ:%d\n", - Host, host_type, - (uint)HostP->PaddrP, - (int)HostP->Ivec - 32 ); - } - return 0; - ** - */ - case RIO_FOAD_RTA: rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n"); - return RIOCommandRta(p, (uint) arg, RIOFoadRta); + return RIOCommandRta(p, (unsigned long)arg, RIOFoadRta); case RIO_ZOMBIE_RTA: rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n"); - return RIOCommandRta(p, (uint) arg, RIOZombieRta); + return RIOCommandRta(p, (unsigned long)arg, RIOZombieRta); case RIO_IDENTIFY_RTA: rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n"); @@ -287,7 +207,7 @@ int su; struct CmdBlk *CmdBlkP; rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n"); - if (copyin((int) arg, (caddr_t) & SpecialRupCmd, sizeof(SpecialRupCmd)) == COPYFAIL) { + if (copy_from_user(&SpecialRupCmd, arg, sizeof(SpecialRupCmd))) { rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -302,7 +222,7 @@ int su; SpecialRupCmd.Host = 0; rio_dprintk(RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", SpecialRupCmd.Host, SpecialRupCmd.RupNum); if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) { - cprintf("FAILED TO QUEUE SPECIAL RUP COMMAND\n"); + printk(KERN_WARNING "rio: FAILED TO QUEUE SPECIAL RUP COMMAND\n"); } return 0; } @@ -324,7 +244,7 @@ int su; if ((retval = RIOApel(p)) != 0) return retval; - if (copyout((caddr_t) p->RIOConnectTable, (int) arg, TOTAL_MAP_ENTRIES * sizeof(struct Map)) == COPYFAIL) { + if (copy_to_user(arg, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -369,7 +289,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copyin((int) arg, (caddr_t) & p->RIOConnectTable[0], TOTAL_MAP_ENTRIES * sizeof(struct Map)) == COPYFAIL) { + if (copy_from_user(&p->RIOConnectTable[0], arg, TOTAL_MAP_ENTRIES * sizeof(struct Map))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -415,7 +335,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copyout((caddr_t) p->RIOBindTab, (int) arg, (sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL) { + if (copy_to_user(arg, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -434,7 +354,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copyin((int) arg, (caddr_t) & p->RIOBindTab[0], (sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL) { + if (copy_from_user(&p->RIOBindTab[0], arg, (sizeof(ulong) * MAX_RTA_BINDINGS))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -458,12 +378,12 @@ int su; for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) { if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L)) EmptySlot = Entry; - else if (p->RIOBindTab[Entry] == (int) arg) { + else if (p->RIOBindTab[Entry] == (long)arg) { /* ** Already exists - delete */ p->RIOBindTab[Entry] = 0L; - rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %x from p->RIOBindTab\n", (int) arg); + rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", (unsigned long)arg); return 0; } } @@ -471,10 +391,10 @@ int su; ** Dosen't exist - add */ if (EmptySlot != -1) { - p->RIOBindTab[EmptySlot] = (int) arg; - rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %x to p->RIOBindTab\n", (int) arg); + p->RIOBindTab[EmptySlot] = (unsigned long)arg; + rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", (unsigned long) arg); } else { - rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %x not added\n", (int) arg); + rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", (unsigned long) arg); return -ENOMEM; } return 0; @@ -482,7 +402,7 @@ int su; case RIO_RESUME: rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n"); - port = (uint) arg; + port = (unsigned long) arg; if ((port < 0) || (port > 511)) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port); p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; @@ -518,8 +438,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copyin((int) arg, (caddr_t) & MapEnt, sizeof(MapEnt)) - == COPYFAIL) { + if (copy_from_user(&MapEnt, arg, sizeof(MapEnt))) { rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -533,8 +452,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copyin((int) arg, (caddr_t) & MapEnt, sizeof(MapEnt)) - == COPYFAIL) { + if (copy_from_user(&MapEnt, arg, sizeof(MapEnt))) { rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -548,8 +466,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copyin((int) arg, (caddr_t) & MapEnt, sizeof(MapEnt)) - == COPYFAIL) { + if (copy_from_user(&MapEnt, arg, sizeof(MapEnt))) { rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -557,30 +474,14 @@ int su; return RIODeleteRta(p, &MapEnt); case RIO_QUICK_CHECK: - /* - ** 09.12.1998 ARG - ESIL 0776 part fix - ** A customer was using this to get the RTAs - ** connect/disconnect status. - ** RIOConCon() had been botched use RIOHalted - ** to keep track of RTA connections and - ** disconnections. That has been changed and - ** RIORtaDisCons in the rio_info struct now - ** does the job. So we need to return the value - ** of RIORtaCons instead of RIOHalted. - ** - if (copyout((caddr_t)&p->RIOHalted,(int)arg, - sizeof(uint))==COPYFAIL) { - ** - */ - - if (copyout((caddr_t) & p->RIORtaDisCons, (int) arg, sizeof(uint)) == COPYFAIL) { + if (copy_to_user(arg, &p->RIORtaDisCons, sizeof(unsigned int))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } return 0; case RIO_LAST_ERROR: - if (copyout((caddr_t) & p->RIOError, (int) arg, sizeof(struct Error)) == COPYFAIL) + if (copy_to_user(arg, &p->RIOError, sizeof(struct Error))) return -EFAULT; return 0; @@ -589,7 +490,7 @@ int su; return -EINVAL; case RIO_GET_MODTYPE: - if (copyin((int) arg, (caddr_t) & port, sizeof(uint)) == COPYFAIL) { + if (copy_from_user(&port, arg, sizeof(unsigned int))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -609,36 +510,11 @@ int su; ** Return module type of port */ port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes; - if (copyout((caddr_t) & port, (int) arg, sizeof(uint)) == COPYFAIL) { + if (copy_to_user(arg, &port, sizeof(unsigned int))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } return (0); - /* - ** 02.03.1999 ARG - ESIL 0820 fix - ** We are no longer using "Boot Mode", so these ioctls - ** are not required : - ** - case RIO_GET_BOOT_MODE : - rio_dprint(RIO_DEBUG_CTRL, ("Get boot mode - %x\n", p->RIOBootMode)); - ** - ** Return boot state of system - BOOT_ALL, BOOT_OWN or BOOT_NONE - ** - if (copyout((caddr_t)&p->RIOBootMode, (int)arg, - sizeof(p->RIOBootMode)) == COPYFAIL) { - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return(0); - - case RIO_SET_BOOT_MODE : - p->RIOBootMode = (uint) arg; - rio_dprint(RIO_DEBUG_CTRL, ("Set boot mode to 0x%x\n", p->RIOBootMode)); - return(0); - ** - ** End ESIL 0820 fix - */ - case RIO_BLOCK_OPENS: rio_dprintk(RIO_DEBUG_CTRL, "Opens block until booted\n"); for (Entry = 0; Entry < RIO_PORTS; Entry++) { @@ -650,8 +526,7 @@ int su; case RIO_SETUP_PORTS: rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n"); - if (copyin((int) arg, (caddr_t) & PortSetup, sizeof(PortSetup)) - == COPYFAIL) { + if (copy_from_user(&PortSetup, arg, sizeof(PortSetup))) { p->RIOError.Error = COPYIN_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "EFAULT"); return -EFAULT; @@ -667,7 +542,7 @@ int su; return -EINVAL; } if (!p->RIOPortp) { - cprintf("No p->RIOPortp array!\n"); + printk(KERN_ERR "rio: No p->RIOPortp array!\n"); rio_dprintk(RIO_DEBUG_CTRL, "No p->RIOPortp array!\n"); return -EIO; } @@ -681,8 +556,7 @@ int su; case RIO_GET_PORT_SETUP: rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n"); - if (copyin((int) arg, (caddr_t) & PortSetup, sizeof(PortSetup)) - == COPYFAIL) { + if (copy_from_user(&PortSetup, arg, sizeof(PortSetup))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -703,8 +577,7 @@ int su; PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0'; PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0'; - if (copyout((caddr_t) & PortSetup, (int) arg, sizeof(PortSetup)) - == COPYFAIL) { + if (copy_to_user(arg, &PortSetup, sizeof(PortSetup))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } @@ -712,7 +585,7 @@ int su; case RIO_GET_PORT_PARAMS: rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n"); - if (copyin((int) arg, (caddr_t) & PortParams, sizeof(struct PortParams)) == COPYFAIL) { + if (copy_from_user(&PortParams, arg, sizeof(struct PortParams))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -725,7 +598,7 @@ int su; PortParams.State = PortP->State; rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port); - if (copyout((caddr_t) & PortParams, (int) arg, sizeof(struct PortParams)) == COPYFAIL) { + if (copy_to_user(arg, &PortParams, sizeof(struct PortParams))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } @@ -733,8 +606,7 @@ int su; case RIO_GET_PORT_TTY: rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n"); - if (copyin((int) arg, (caddr_t) & PortTty, sizeof(struct PortTty)) - == COPYFAIL) { + if (copy_from_user(&PortTty, arg, sizeof(struct PortTty))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -745,14 +617,14 @@ int su; rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port); PortP = (p->RIOPortp[PortTty.port]); - if (copyout((caddr_t) & PortTty, (int) arg, sizeof(struct PortTty)) == COPYFAIL) { + if (copy_to_user(arg, &PortTty, sizeof(struct PortTty))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } return retval; case RIO_SET_PORT_TTY: - if (copyin((int) arg, (caddr_t) & PortTty, sizeof(struct PortTty)) == COPYFAIL) { + if (copy_from_user(&PortTty, arg, sizeof(struct PortTty))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -767,8 +639,7 @@ int su; case RIO_SET_PORT_PARAMS: rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n"); - if (copyin((int) arg, (caddr_t) & PortParams, sizeof(PortParams)) - == COPYFAIL) { + if (copy_from_user(&PortParams, arg, sizeof(PortParams))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -784,7 +655,7 @@ int su; case RIO_GET_PORT_STATS: rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n"); - if (copyin((int) arg, (caddr_t) & portStats, sizeof(struct portStats)) == COPYFAIL) { + if (copy_from_user(&portStats, arg, sizeof(struct portStats))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -799,14 +670,14 @@ int su; portStats.opens = PortP->opens; portStats.closes = PortP->closes; portStats.ioctls = PortP->ioctls; - if (copyout((caddr_t) & portStats, (int) arg, sizeof(struct portStats)) == COPYFAIL) { + if (copy_to_user(arg, &portStats, sizeof(struct portStats))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } return retval; case RIO_RESET_PORT_STATS: - port = (uint) arg; + port = (unsigned long) arg; rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n"); if (port >= RIO_PORTS) { p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; @@ -824,7 +695,7 @@ int su; case RIO_GATHER_PORT_STATS: rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n"); - if (copyin((int) arg, (caddr_t) & portStats, sizeof(struct portStats)) == COPYFAIL) { + if (copy_from_user(&portStats, arg, sizeof(struct portStats))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -840,7 +711,7 @@ int su; case RIO_READ_CONFIG: rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n"); - if (copyout((caddr_t) & p->RIOConf, (int) arg, sizeof(struct Conf)) == COPYFAIL) { + if (copy_to_user(arg, &p->RIOConf, sizeof(struct Conf))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } @@ -852,8 +723,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copyin((int) arg, (caddr_t) & p->RIOConf, sizeof(struct Conf)) - == COPYFAIL) { + if (copy_from_user(&p->RIOConf, arg, sizeof(struct Conf))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -862,7 +732,7 @@ int su; */ for (Host = 0; Host < p->RIONumHosts; Host++) if ((p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING) - WWORD(p->RIOHosts[Host].ParmMapP->timer, p->RIOConf.Timer); + writew(p->RIOConf.Timer, &p->RIOHosts[Host].ParmMapP->timer); return retval; case RIO_START_POLLER: @@ -881,8 +751,7 @@ int su; case RIO_SETDEBUG: case RIO_GETDEBUG: rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n"); - if (copyin((int) arg, (caddr_t) & DebugCtrl, sizeof(DebugCtrl)) - == COPYFAIL) { + if (copy_from_user(&DebugCtrl, arg, sizeof(DebugCtrl))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -899,7 +768,7 @@ int su; rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait); DebugCtrl.Debug = p->rio_debug; DebugCtrl.Wait = p->RIODebugWait; - if (copyout((caddr_t) & DebugCtrl, (int) arg, sizeof(DebugCtrl)) == COPYFAIL) { + if (copy_to_user(arg, &DebugCtrl, sizeof(DebugCtrl))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -921,7 +790,7 @@ int su; } else { rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug); DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug; - if (copyout((caddr_t) & DebugCtrl, (int) arg, sizeof(DebugCtrl)) == COPYFAIL) { + if (copy_to_user(arg, &DebugCtrl, sizeof(DebugCtrl))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -936,43 +805,20 @@ int su; ** textual null terminated string. */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n"); - if (copyout((caddr_t) RIOVersid(), (int) arg, sizeof(struct rioVersion)) == COPYFAIL) { + if (copy_to_user(arg, RIOVersid(), sizeof(struct rioVersion))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } return retval; - /* - ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - ** !! commented out previous 'RIO_VERSID' functionality !! - ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - ** - case RIO_VERSID: - ** - ** Enquire about the release and version. - ** We return MAX_VERSION_LEN bytes, being a textual null - ** terminated string. - ** - rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID\n")); - if (copyout((caddr_t)RIOVersid(), - (int)arg, MAX_VERSION_LEN ) == COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID: Bad copy to user space\n",Host)); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - return retval; - ** - ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - */ - case RIO_NUM_HOSTS: /* ** Enquire as to the number of hosts located ** at init time. */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n"); - if (copyout((caddr_t) & p->RIONumHosts, (int) arg, sizeof(p->RIONumHosts)) == COPYFAIL) { + if (copy_to_user(arg, &p->RIONumHosts, sizeof(p->RIONumHosts))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -983,7 +829,7 @@ int su; /* ** Kill host. This may not be in the final version... */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %d\n", (int) arg); + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", (unsigned long) arg); if (!su) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n"); p->RIOError.Error = NOT_SUPER_USER; @@ -994,7 +840,7 @@ int su; for (Host = 0; Host < p->RIONumHosts; Host++) { (void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot); - bzero((caddr_t) & p->RIOHosts[Host].Flags, ((int) &p->RIOHosts[Host].____end_marker____) - ((int) &p->RIOHosts[Host].Flags)); + memset(&p->RIOHosts[Host].Flags, 0, ((char *) &p->RIOHosts[Host].____end_marker____) - ((char *) &p->RIOHosts[Host].Flags)); p->RIOHosts[Host].Flags = RC_WAITING; } RIOFoadWakeup(p); @@ -1017,7 +863,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copyin((int) arg, (caddr_t) & DownLoad, sizeof(DownLoad)) == COPYFAIL) { + if (copy_from_user(&DownLoad, arg, sizeof(DownLoad))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1045,9 +891,9 @@ int su; case RIO_PARMS: { - uint host; + unsigned int host; - if (copyin((int) arg, (caddr_t) & host, sizeof(host)) == COPYFAIL) { + if (copy_from_user(&host, arg, sizeof(host))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1056,7 +902,7 @@ int su; ** Fetch the parmmap */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n"); - if (copyout((caddr_t) p->RIOHosts[host].ParmMapP, (int) arg, sizeof(PARM_MAP)) == COPYFAIL) { + if (copy_to_user(arg, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) { p->RIOError.Error = COPYOUT_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n"); return -EFAULT; @@ -1066,7 +912,7 @@ int su; case RIO_HOST_REQ: rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n"); - if (copyin((int) arg, (caddr_t) & HostReq, sizeof(HostReq)) == COPYFAIL) { + if (copy_from_user(&HostReq, arg, sizeof(HostReq))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1078,7 +924,7 @@ int su; } rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum); - if (copyout((caddr_t) & p->RIOHosts[HostReq.HostNum], (int) HostReq.HostP, sizeof(struct Host)) == COPYFAIL) { + if (copy_to_user(HostReq.HostP, &p->RIOHosts[HostReq.HostNum], sizeof(struct Host))) { p->RIOError.Error = COPYOUT_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n"); return -EFAULT; @@ -1087,7 +933,7 @@ int su; case RIO_HOST_DPRAM: rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n"); - if (copyin((int) arg, (caddr_t) & HostDpRam, sizeof(HostDpRam)) == COPYFAIL) { + if (copy_from_user(&HostDpRam, arg, sizeof(HostDpRam))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1104,13 +950,13 @@ int su; /* It's hardware like this that really gets on my tits. */ static unsigned char copy[sizeof(struct DpRam)]; for (off = 0; off < sizeof(struct DpRam); off++) - copy[off] = p->RIOHosts[HostDpRam.HostNum].Caddr[off]; - if (copyout((caddr_t) copy, (int) HostDpRam.DpRamP, sizeof(struct DpRam)) == COPYFAIL) { + copy[off] = readb(&p->RIOHosts[HostDpRam.HostNum].Caddr[off]); + if (copy_to_user(HostDpRam.DpRamP, copy, sizeof(struct DpRam))) { p->RIOError.Error = COPYOUT_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); return -EFAULT; } - } else if (copyout((caddr_t) p->RIOHosts[HostDpRam.HostNum].Caddr, (int) HostDpRam.DpRamP, sizeof(struct DpRam)) == COPYFAIL) { + } else if (copy_to_user(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) { p->RIOError.Error = COPYOUT_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); return -EFAULT; @@ -1119,13 +965,13 @@ int su; case RIO_SET_BUSY: rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n"); - if ((int) arg < 0 || (int) arg > 511) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %d\n", (int) arg); + if ((unsigned long) arg > 511) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", (unsigned long) arg); p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; return -EINVAL; } rio_spin_lock_irqsave(&PortP->portSem, flags); - p->RIOPortp[(int) arg]->State |= RIO_BUSY; + p->RIOPortp[(unsigned long) arg]->State |= RIO_BUSY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return retval; @@ -1135,7 +981,7 @@ int su; ** (probably for debug reasons) */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n"); - if (copyin((int) arg, (caddr_t) & PortReq, sizeof(PortReq)) == COPYFAIL) { + if (copy_from_user(&PortReq, arg, sizeof(PortReq))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1147,7 +993,7 @@ int su; return -ENXIO; } rio_dprintk(RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort); - if (copyout((caddr_t) p->RIOPortp[PortReq.SysPort], (int) PortReq.PortP, sizeof(struct Port)) == COPYFAIL) { + if (copy_to_user(PortReq.PortP, p->RIOPortp[PortReq.SysPort], sizeof(struct Port))) { p->RIOError.Error = COPYOUT_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n"); return -EFAULT; @@ -1160,7 +1006,7 @@ int su; ** (probably for debug reasons) */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n"); - if (copyin((int) arg, (caddr_t) & RupReq, sizeof(RupReq)) == COPYFAIL) { + if (copy_from_user(&RupReq, arg, sizeof(RupReq))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1184,7 +1030,7 @@ int su; } rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum); - if (copyout((caddr_t) HostP->UnixRups[RupReq.RupNum].RupP, (int) RupReq.RupP, sizeof(struct RUP)) == COPYFAIL) { + if (copy_to_user(HostP->UnixRups[RupReq.RupNum].RupP, RupReq.RupP, sizeof(struct RUP))) { p->RIOError.Error = COPYOUT_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n"); return -EFAULT; @@ -1197,7 +1043,7 @@ int su; ** (probably for debug reasons) */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n"); - if (copyin((int) arg, (caddr_t) & LpbReq, sizeof(LpbReq)) == COPYFAIL) { + if (copy_from_user(&LpbReq, arg, sizeof(LpbReq))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1221,7 +1067,7 @@ int su; } rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host); - if (copyout((caddr_t) & HostP->LinkStrP[LpbReq.Link], (int) LpbReq.LpbP, sizeof(struct LPB)) == COPYFAIL) { + if (copy_to_user(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -1252,12 +1098,13 @@ int su; p->RIOError.Error = SIGNALS_ALREADY_SET; return -EBUSY; } - p->RIOSignalProcess = getpid(); + /* FIXME: PID tracking */ + p->RIOSignalProcess = current->pid; p->RIOPrintDisabled = DONT_PRINT; return retval; case RIO_SIGNALS_OFF: - if (p->RIOSignalProcess != getpid()) { + if (p->RIOSignalProcess != current->pid) { p->RIOError.Error = NOT_RECEIVING_PROCESS; return -EPERM; } @@ -1294,7 +1141,7 @@ int su; case RIO_MAP_B110_TO_110: case RIO_MAP_B110_TO_115200: rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n"); - port = (uint) arg; + port = (unsigned long) arg; if (port < 0 || port > 511) { rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port); p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; @@ -1324,7 +1171,7 @@ int su; case RIO_SEND_PACKET: rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n"); - if (copyin((int) arg, (caddr_t) & SendPack, sizeof(SendPack)) == COPYFAIL) { + if (copy_from_user(&SendPack, arg, sizeof(SendPack))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1344,9 +1191,9 @@ int su; } for (loop = 0; loop < (ushort) (SendPack.Len & 127); loop++) - WBYTE(PacketP->data[loop], SendPack.Data[loop]); + writeb(SendPack.Data[loop], &PacketP->data[loop]); - WBYTE(PacketP->len, SendPack.Len); + writeb(SendPack.Len, &PacketP->len); add_transmit(PortP); /* @@ -1368,7 +1215,7 @@ int su; return su ? 0 : -EPERM; case RIO_WHAT_MESG: - if (copyout((caddr_t) & p->RIONoMessage, (int) arg, sizeof(p->RIONoMessage)) == COPYFAIL) { + if (copy_to_user(arg, &p->RIONoMessage, sizeof(p->RIONoMessage))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -1376,7 +1223,7 @@ int su; return 0; case RIO_MEM_DUMP: - if (copyin((int) arg, (caddr_t) & SubCmd, sizeof(struct SubCmdStruct)) == COPYFAIL) { + if (copy_from_user(&SubCmd, arg, sizeof(struct SubCmdStruct))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -1406,7 +1253,7 @@ int su; PortP->State |= RIO_BUSY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (copyout((caddr_t) p->RIOMemDump, (int) arg, MEMDUMP_SIZE) == COPYFAIL) { + if (copy_to_user(arg, p->RIOMemDump, MEMDUMP_SIZE)) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -1414,30 +1261,30 @@ int su; return 0; case RIO_TICK: - if ((int) arg < 0 || (int) arg >= p->RIONumHosts) + if ((unsigned long) arg >= p->RIONumHosts) return -EINVAL; - rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %d\n", (int) arg); - WBYTE(p->RIOHosts[(int) arg].SetInt, 0xff); + rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", (unsigned long) arg); + writeb(0xFF, &p->RIOHosts[(unsigned long) arg].SetInt); return 0; case RIO_TOCK: - if ((int) arg < 0 || (int) arg >= p->RIONumHosts) + if ((unsigned long) arg >= p->RIONumHosts) return -EINVAL; - rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %d\n", (int) arg); - WBYTE((p->RIOHosts[(int) arg].ResetInt), 0xff); + rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", (unsigned long) arg); + writeb(0xFF, &p->RIOHosts[(unsigned long) arg].ResetInt); return 0; case RIO_READ_CHECK: /* Check reads for pkts with data[0] the same */ p->RIOReadCheck = !p->RIOReadCheck; - if (copyout((caddr_t) & p->RIOReadCheck, (int) arg, sizeof(uint)) == COPYFAIL) { + if (copy_to_user(arg, &p->RIOReadCheck, sizeof(unsigned int))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } return 0; case RIO_READ_REGISTER: - if (copyin((int) arg, (caddr_t) & SubCmd, sizeof(struct SubCmdStruct)) == COPYFAIL) { + if (copy_from_user(&SubCmd, arg, sizeof(struct SubCmdStruct))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -1472,7 +1319,7 @@ int su; PortP->State |= RIO_BUSY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (copyout((caddr_t) & p->CdRegister, (int) arg, sizeof(uint)) == COPYFAIL) { + if (copy_to_user(arg, &p->CdRegister, sizeof(unsigned int))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -1485,21 +1332,22 @@ int su; */ case RIO_MAKE_DEV: { - uint port = (uint) arg & RIO_MODEM_MASK; + unsigned int port = (unsigned long) arg & RIO_MODEM_MASK; + unsigned int ret; - switch ((uint) arg & RIO_DEV_MASK) { + switch ((unsigned long) arg & RIO_DEV_MASK) { case RIO_DEV_DIRECT: - arg = (caddr_t) drv_makedev(MAJOR(dev), port); - rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, (int) arg); - return (int) arg; + ret = drv_makedev(MAJOR(dev), port); + rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, ret); + return ret; case RIO_DEV_MODEM: - arg = (caddr_t) drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT)); - rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, (int) arg); - return (int) arg; + ret = drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT)); + rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, ret); + return ret; case RIO_DEV_XPRINT: - arg = (caddr_t) drv_makedev(MAJOR(dev), port); - rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, (int) arg); - return (int) arg; + ret = drv_makedev(MAJOR(dev), port); + rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, ret); + return ret; } rio_dprintk(RIO_DEBUG_CTRL, "MAKE Device is called\n"); return -EINVAL; @@ -1513,18 +1361,19 @@ int su; { dev_t dv; int mino; + unsigned long ret; - dv = (dev_t) ((int) arg); + dv = (dev_t) ((unsigned long) arg); mino = RIO_UNMODEM(dv); if (RIO_ISMODEM(dv)) { rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino); - arg = (caddr_t) (mino | RIO_DEV_MODEM); + ret = mino | RIO_DEV_MODEM; } else { rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino); - arg = (caddr_t) (mino | RIO_DEV_DIRECT); + ret = mino | RIO_DEV_DIRECT; } - return (int) arg; + return ret; } } rio_dprintk(RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n", cmd); @@ -1537,10 +1386,7 @@ int su; /* ** Pre-emptive commands go on RUPs and are only one byte long. */ -int RIOPreemptiveCmd(p, PortP, Cmd) -struct rio_info *p; -struct Port *PortP; -uchar Cmd; +int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd) { struct CmdBlk *CmdBlkP; struct PktCmd_M *PktCmdP; @@ -1558,7 +1404,7 @@ uchar Cmd; return RIO_FAIL; } - rio_dprintk(RIO_DEBUG_CTRL, "Command blk 0x%x - InUse now %d\n", (int) CmdBlkP, PortP->InUse); + rio_dprintk(RIO_DEBUG_CTRL, "Command blk 0x%p - InUse now %d\n", CmdBlkP, PortP->InUse); PktCmdP = (struct PktCmd_M *) &CmdBlkP->Packet.data[0]; @@ -1572,7 +1418,7 @@ uchar Cmd; CmdBlkP->Packet.dest_port = COMMAND_RUP; CmdBlkP->Packet.len = PKT_CMD_BIT | 2; CmdBlkP->PostFuncP = RIOUnUse; - CmdBlkP->PostArg = (int) PortP; + CmdBlkP->PostArg = (unsigned long) PortP; PktCmdP->Command = Cmd; port = PortP->HostPort % (ushort) PORTS_PER_RTA; /* @@ -1584,38 +1430,38 @@ uchar Cmd; switch (Cmd) { case MEMDUMP: - rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk 0x%x (addr 0x%x)\n", (int) CmdBlkP, (int) SubCmd.Addr); + rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk 0x%p (addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr); PktCmdP->SubCommand = MEMDUMP; PktCmdP->SubAddr = SubCmd.Addr; break; case FCLOSE: - rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk 0x%x\n", (int) CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk 0x%p\n", CmdBlkP); break; case READ_REGISTER: - rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk 0x%x\n", (int) SubCmd.Addr, (int) CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk 0x%p\n", (int) SubCmd.Addr, CmdBlkP); PktCmdP->SubCommand = READ_REGISTER; PktCmdP->SubAddr = SubCmd.Addr; break; case RESUME: - rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk 0x%x\n", (int) CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk 0x%p\n", CmdBlkP); break; case RFLUSH: - rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk 0x%x\n", (int) CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk 0x%p\n", CmdBlkP); CmdBlkP->PostFuncP = RIORFlushEnable; break; case SUSPEND: - rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk 0x%x\n", (int) CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk 0x%p\n", CmdBlkP); break; case MGET: - rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk 0x%x\n", (int) CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk 0x%p\n", CmdBlkP); break; case MSET: case MBIC: case MBIS: CmdBlkP->Packet.data[4] = (char) PortP->ModemLines; - rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk 0x%x\n", (int) CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk 0x%p\n", CmdBlkP); break; case WFLUSH: @@ -1629,7 +1475,7 @@ uchar Cmd; RIOFreeCmdBlk(CmdBlkP); return (RIO_FAIL); } else { - rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command blk 0x%x\n", (int) CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command blk 0x%p\n", CmdBlkP); CmdBlkP->PostFuncP = RIOWFlushMark; } break; -- cgit v1.2.3-59-g8ed1b From db3185242a9a369d5ef13cd2baf196507925009e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 24 Mar 2006 03:18:30 -0800 Subject: [PATCH] rio driver rework continued #5 Final polish. There is no more save_flags/cli type locking left. We also no longer use the pcicopy function and file so they can go. Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/Kconfig | 2 +- drivers/char/rio/Makefile | 2 +- drivers/char/rio/riopcicopy.c | 8 -------- 3 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 drivers/char/rio/riopcicopy.c (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index b524f5ba78a9..5980f3e886fc 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -290,7 +290,7 @@ config SX config RIO tristate "Specialix RIO system support" - depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && !64BIT + depends on SERIAL_NONSTANDARD && !64BIT help This is a driver for the Specialix RIO, a smart serial card which drives an outboard box that can support up to 128 ports. Product diff --git a/drivers/char/rio/Makefile b/drivers/char/rio/Makefile index bce2bd1204ed..2d1c5a7cba7d 100644 --- a/drivers/char/rio/Makefile +++ b/drivers/char/rio/Makefile @@ -9,4 +9,4 @@ obj-$(CONFIG_RIO) += rio.o rio-objs := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \ - rioparam.o riopcicopy.o rioroute.o riotable.o riotty.o + rioparam.o rioroute.o riotable.o riotty.o diff --git a/drivers/char/rio/riopcicopy.c b/drivers/char/rio/riopcicopy.c deleted file mode 100644 index 535afaa51ca5..000000000000 --- a/drivers/char/rio/riopcicopy.c +++ /dev/null @@ -1,8 +0,0 @@ - -/* Yeah. We have copyright on this one. Sure. */ - -void rio_pcicopy(char *from, char *to, int amount) -{ - while (amount--) - *to++ = *from++; -} -- cgit v1.2.3-59-g8ed1b From 57c2d60e1e3db506cdcecbf60f939593125db7f8 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 24 Mar 2006 03:18:31 -0800 Subject: [PATCH] Yet more rio cleaning (1 of 2) - Remove more unused headers - Remove various typedefs - Correct type of PaddrP (physical addresses should be ulong) - Kill use of bcopy - More printk cleanups - Kill true/false - Clean up direct access to pci BARs Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/rio/bootpkt.h | 61 ---------------------- drivers/char/rio/cirrus.h | 110 +--------------------------------------- drivers/char/rio/control.h | 61 ---------------------- drivers/char/rio/defaults.h | 51 ------------------- drivers/char/rio/error.h | 82 ------------------------------ drivers/char/rio/func.h | 7 +-- drivers/char/rio/host.h | 2 +- drivers/char/rio/link.h | 12 ++--- drivers/char/rio/linux_compat.h | 4 -- drivers/char/rio/list.h | 56 -------------------- drivers/char/rio/map.h | 12 ++--- drivers/char/rio/param.h | 24 ++++----- drivers/char/rio/parmmap.h | 14 ++--- drivers/char/rio/phb.h | 2 +- drivers/char/rio/qbuf.h | 62 ---------------------- 15 files changed, 36 insertions(+), 524 deletions(-) delete mode 100644 drivers/char/rio/bootpkt.h delete mode 100644 drivers/char/rio/control.h delete mode 100644 drivers/char/rio/defaults.h delete mode 100644 drivers/char/rio/error.h delete mode 100644 drivers/char/rio/list.h delete mode 100644 drivers/char/rio/qbuf.h (limited to 'drivers') diff --git a/drivers/char/rio/bootpkt.h b/drivers/char/rio/bootpkt.h deleted file mode 100644 index 602266e0c085..000000000000 --- a/drivers/char/rio/bootpkt.h +++ /dev/null @@ -1,61 +0,0 @@ - - -/**************************************************************************** - ******* ******* - ******* B O O T P A C K E T H E A D E R F I L E - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _pkt_h -#define _pkt_h 1 - -#ifndef lint -#ifdef SCCS -static char *_rio_bootpkt_h_sccs = "@(#)bootpkt.h 1.1"; -#endif -#endif - - /************************************************* - * Overlayed onto the Data fields of a regular - * Packet - ************************************************/ -typedef struct BOOT_PKT BOOT_PKT; -struct BOOT_PKT { - short seq_num; - char data[10]; -}; - - -#endif - -/*********** end of file ***********/ diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h index 89bd94eb45be..f4f837f86829 100644 --- a/drivers/char/rio/cirrus.h +++ b/drivers/char/rio/cirrus.h @@ -40,73 +40,7 @@ #endif #define _cirrus_h 1 - - -/* Bit fields for particular registers */ - -/* GCR */ -#define GCR_SERIAL 0x00 /* Configure as serial channel */ -#define GCR_PARALLEL 0x80 /* Configure as parallel channel */ - -/* RDSR - when status read from FIFO */ -#define RDSR_BREAK 0x08 /* Break received */ -#define RDSR_TIMEOUT 0x80 /* No new data timeout */ -#define RDSR_SC1 0x10 /* Special char 1 (tx XON) matched */ -#define RDSR_SC2 0x20 /* Special char 2 (tx XOFF) matched */ -#define RDSR_SC12_MASK 0x30 /* Mask for special chars 1 and 2 */ - -/* PPR */ -#define PPR_DEFAULT 0x31 /* Default value - for a 25Mhz clock gives - a timeout period of 1ms */ - -/* LIVR */ -#define LIVR_EXCEPTION 0x07 /* Receive exception interrupt */ - -/* CCR */ -#define CCR_RESET 0x80 /* Reset channel */ -#define CCR_CHANGE 0x4e /* COR's have changed - NB always change all - COR's */ -#define CCR_WFLUSH 0x82 /* Flush transmit FIFO and TSR / THR */ - -#define CCR_SENDSC1 0x21 /* Send special character one */ -#define CCR_SENDSC2 0x22 /* Send special character two */ -#define CCR_SENDSC3 0x23 /* Send special character three */ -#define CCR_SENDSC4 0x24 /* Send special character four */ - -#define CCR_TENABLE 0x18 /* Enable transmitter */ -#define CCR_TDISABLE 0x14 /* Disable transmitter */ -#define CCR_RENABLE 0x12 /* Enable receiver */ -#define CCR_RDISABLE 0x11 /* Disable receiver */ - -#define CCR_READY 0x00 /* CCR is ready for another command */ - -/* CCSR */ -#define CCSR_TXENABLE 0x08 /* Transmitter enable */ -#define CCSR_RXENABLE 0x80 /* Receiver enable */ -#define CCSR_TXFLOWOFF 0x04 /* Transmit flow off */ -#define CCSR_TXFLOWON 0x02 /* Transmit flow on */ - -/* SVRR */ -#define SVRR_RECEIVE 0x01 /* Receive interrupt pending */ -#define SVRR_TRANSMIT 0x02 /* Transmit interrupt pending */ -#define SVRR_MODEM 0x04 /* Modem interrupt pending */ - -/* CAR */ -#define CAR_PORTS 0x03 /* Bit fields for ports */ - -/* IER */ -#define IER_MODEM 0x80 /* Change in modem status */ -#define IER_RECEIVE 0x10 /* Good data / data exception */ -#define IER_TRANSMITR 0x04 /* Transmit ready (FIFO empty) */ -#define IER_TRANSMITE 0x02 /* Transmit empty */ -#define IER_TIMEOUT 0x01 /* Timeout on no data */ - -#define IER_DEFAULT 0x94 /* Default values */ -#define IER_PARALLEL 0x84 /* Default for Parallel */ -#define IER_EMPTY 0x92 /* Transmitter empty rather than ready */ - -/* COR1 - Driver only */ -#define COR1_INPCK 0x10 /* Check parity of received characters */ +/* Bit fields for particular registers shared with driver */ /* COR1 - driver and RTA */ #define COR1_ODD 0x80 /* Odd parity */ @@ -222,35 +156,6 @@ #define MSVR1_HOST 0xf3 /* The bits the host wants */ -/* MSVR2 */ -#define MSVR2_DSR 0x02 /* DSR output pin (DTR on Cirrus) */ - -/* MCOR */ -#define MCOR_CD 0x80 /* CD (DSR on Cirrus) */ -#define MCOR_RTS 0x40 /* RTS (CTS on Cirrus) */ -#define MCOR_RI 0x20 /* RI */ -#define MCOR_DTR 0x10 /* DTR (CD on Cirrus) */ - -#define MCOR_DEFAULT (MCOR_CD | MCOR_RTS | MCOR_RI | MCOR_DTR) -#define MCOR_FULLMODEM MCOR_DEFAULT -#define MCOR_RJ45 (MCOR_CD | MCOR_RTS | MCOR_DTR) -#define MCOR_RESTRICTED (MCOR_CD | MCOR_RTS) - -/* More MCOR - H/W Handshake (flowcontrol) stuff */ -#define MCOR_THRESH8 0x08 /* eight characters then we stop */ -#define MCOR_THRESH9 0x09 /* nine characters then we stop */ -#define MCOR_THRESH10 0x0A /* ten characters then we stop */ -#define MCOR_THRESH11 0x0B /* eleven characters then we stop */ - -#define MCOR_THRESHBITS 0x0F /* mask for ANDing out the above */ - -#define MCOR_THRESHOLD MCOR_THRESH9 /* MUST BE GREATER THAN COR3_THRESHOLD */ - - -/* RTPR */ -#define RTPR_DEFAULT 0x02 /* Default */ - - /* Defines for the subscripts of a CONFIG packet */ #define CONFIG_COR1 1 /* Option register 1 */ #define CONFIG_COR2 2 /* Option register 2 */ @@ -264,19 +169,6 @@ #define CONFIG_TXBAUD 10 /* Tx baud rate */ #define CONFIG_RXBAUD 11 /* Rx baud rate */ -/* Port status stuff */ -#define IDLE_CLOSED 0 /* Closed */ -#define IDLE_OPEN 1 /* Idle open */ -#define IDLE_BREAK 2 /* Idle on break */ - -/* Subscript of MODEM STATUS packet */ -#define MODEM_VALUE 3 /* Current values of handshake pins */ -/* Subscript of SBREAK packet */ -#define BREAK_LENGTH 1 /* Length of a break in slices of 0.01 seconds - 0 = stay on break until an EBREAK command - is sent */ - - #define PRE_EMPTIVE 0x80 /* Pre-emptive bit in command field */ /* Packet types going from Host to remote - with the exception of OPEN, MOPEN, diff --git a/drivers/char/rio/control.h b/drivers/char/rio/control.h deleted file mode 100644 index 6853d03304a3..000000000000 --- a/drivers/char/rio/control.h +++ /dev/null @@ -1,61 +0,0 @@ - - -/**************************************************************************** - ******* ******* - ******* C O N T R O L P A C K E T H E A D E R S - ******* ******* - **************************************************************************** - - Author : Jon Brawn - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - - -#ifndef _control_h -#define _control_h - -#ifndef lint -/* static char *_rio_control_h_sccs = "@(#)control.h 1.4"; */ -#endif - -#define CONTROL '^' -#define IFOAD ( CONTROL + 1 ) -#define IDENTIFY ( CONTROL + 2 ) -#define ZOMBIE ( CONTROL + 3 ) -#define UFOAD ( CONTROL + 4 ) -#define IWAIT ( CONTROL + 5 ) - -#define IFOAD_MAGIC 0xF0AD /* of course */ -#define ZOMBIE_MAGIC (~0xDEAD) /* not dead -> zombie */ -#define UFOAD_MAGIC 0xD1E /* kill-your-neighbour */ -#define IWAIT_MAGIC 0xB1DE /* Bide your time */ - -#endif - -/*********** end of file ***********/ diff --git a/drivers/char/rio/defaults.h b/drivers/char/rio/defaults.h deleted file mode 100644 index d55c2f6a9877..000000000000 --- a/drivers/char/rio/defaults.h +++ /dev/null @@ -1,51 +0,0 @@ - -/**************************************************************************** - ******* ******* - ******* D E F A U L T S - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef lint -#ifdef SCCS -static char *_rio_defaults_h_sccs = "@(#)defaults.h 1.1"; -#endif -#endif - - -#define MILLISECOND (int) (1000/64) /* 15.625 low ticks */ -#define SECOND (int) 15625 /* Low priority ticks */ - -#define LINK_TIMEOUT (int) (POLL_PERIOD / 2) - - -/*********** end of file ***********/ diff --git a/drivers/char/rio/error.h b/drivers/char/rio/error.h deleted file mode 100644 index f20f0789db8f..000000000000 --- a/drivers/char/rio/error.h +++ /dev/null @@ -1,82 +0,0 @@ - -/**************************************************************************** - ******* ******* - ******* E R R O R H E A D E R F I L E - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef lint -/* static char *_rio_error_h_sccs = "@(#)error.h 1.3"; */ -#endif - -#define E_NO_ERROR ((ushort) 0) -#define E_PROCESS_NOT_INIT ((ushort) 1) -#define E_LINK_TIMEOUT ((ushort) 2) -#define E_NO_ROUTE ((ushort) 3) -#define E_CONFUSED ((ushort) 4) -#define E_HOME ((ushort) 5) -#define E_CSUM_FAIL ((ushort) 6) -#define E_DISCONNECTED ((ushort) 7) -#define E_BAD_RUP ((ushort) 8) -#define E_NO_VIRGIN ((ushort) 9) -#define E_BOOT_RUP_BUSY ((ushort) 10) - - - - /************************************************* - * Parsed to mem_halt() - ************************************************/ -#define E_CHANALLOC ((ushort) 0x80) -#define E_POLL_ALLOC ((ushort) 0x81) -#define E_LTTWAKE ((ushort) 0x82) -#define E_LTT_ALLOC ((ushort) 0x83) -#define E_LRT_ALLOC ((ushort) 0x84) -#define E_CIRRUS ((ushort) 0x85) -#define E_MONITOR ((ushort) 0x86) -#define E_PHB_ALLOC ((ushort) 0x87) -#define E_ARRAY_ALLOC ((ushort) 0x88) -#define E_QBUF_ALLOC ((ushort) 0x89) -#define E_PKT_ALLOC ((ushort) 0x8a) -#define E_GET_TX_Q_BUF ((ushort) 0x8b) -#define E_GET_RX_Q_BUF ((ushort) 0x8c) -#define E_MEM_OUT ((ushort) 0x8d) -#define E_MMU_INIT ((ushort) 0x8e) -#define E_LTT_INIT ((ushort) 0x8f) -#define E_LRT_INIT ((ushort) 0x90) -#define E_LINK_RUN ((ushort) 0x91) -#define E_MONITOR_ALLOC ((ushort) 0x92) -#define E_MONITOR_INIT ((ushort) 0x93) -#define E_POLL_INIT ((ushort) 0x94) - - -/*********** end of file ***********/ diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h index 8967772d833d..e64fe9912394 100644 --- a/drivers/char/rio/func.h +++ b/drivers/char/rio/func.h @@ -49,7 +49,7 @@ void msec_timeout(struct Host *); int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT *); int RIOBootOk(struct rio_info *, struct Host *, unsigned long); int RIORtaBound(struct rio_info *, unsigned int); -void FillSlot(int, int, unsigned int, struct Host *); +void rio_fill_host_slot(int, int, unsigned int, struct Host *); /* riocmd.c */ int RIOFoadRta(struct Host *, struct Map *); @@ -66,7 +66,6 @@ void RIOPollHostCommands(struct rio_info *, struct Host *); int RIOWFlushMark(unsigned long, struct CmdBlk *); int RIORFlushEnable(unsigned long, struct CmdBlk *); int RIOUnUse(unsigned long, struct CmdBlk *); -void ShowPacket(unsigned int, struct PKT *); /* rioctrl.c */ int riocontrol(struct rio_info *, dev_t, int, caddr_t, int); @@ -79,13 +78,11 @@ void RIOISAinit(struct rio_info *, int); int RIODoAT(struct rio_info *, int, int); caddr_t RIOCheckForATCard(int); int RIOAssignAT(struct rio_info *, int, caddr_t, int); -int RIOBoardTest(paddr_t, caddr_t, unsigned char, int); +int RIOBoardTest(unsigned long, caddr_t, unsigned char, int); void RIOAllocDataStructs(struct rio_info *); void RIOSetupDataStructs(struct rio_info *); int RIODefaultName(struct rio_info *, struct Host *, unsigned int); struct rioVersion *RIOVersid(void); -int RIOMapin(paddr_t, int, caddr_t *); -void RIOMapout(paddr_t, long, caddr_t); void RIOHostReset(unsigned int, struct DpRam *, unsigned int); /* riointr.c */ diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h index 79a55301f06b..3ec73d1a279a 100644 --- a/drivers/char/rio/host.h +++ b/drivers/char/rio/host.h @@ -56,7 +56,7 @@ struct Host { unsigned char Slot; /* Slot */ caddr_t Caddr; /* KV address of DPRAM */ struct DpRam *CardP; /* KV address of DPRAM, with overlay */ - paddr_t PaddrP; /* Phys. address of DPRAM */ + unsigned long PaddrP; /* Phys. address of DPRAM */ char Name[MAX_NAME_LEN]; /* The name of the host */ unsigned int UniqueNum; /* host unique number */ spinlock_t HostLock; /* Lock structure for MPX */ diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h index 87a87b1ec01d..f3bf11a04d41 100644 --- a/drivers/char/rio/link.h +++ b/drivers/char/rio/link.h @@ -50,8 +50,8 @@ struct LPB { u16 link_number; /* Link Number */ - Channel_ptr in_ch; /* Link In Channel */ - Channel_ptr out_ch; /* Link Out Channel */ + u16 in_ch; /* Link In Channel */ + u16 out_ch; /* Link Out Channel */ u8 attached_serial[4]; /* Attached serial number */ u8 attached_host_serial[4]; /* Serial number of Host who @@ -59,8 +59,8 @@ struct LPB { u16 descheduled; /* Currently Descheduled */ u16 state; /* Current state */ u16 send_poll; /* Send a Poll Packet */ - Process_ptr ltt_p; /* Process Descriptor */ - Process_ptr lrt_p; /* Process Descriptor */ + u16 ltt_p; /* Process Descriptor */ + u16 lrt_p; /* Process Descriptor */ u16 lrt_status; /* Current lrt status */ u16 ltt_status; /* Current ltt status */ u16 timeout; /* Timeout value */ @@ -71,8 +71,8 @@ struct LPB { u16 add_packet_list; /* Add packets to here */ u16 remove_packet_list; /* Send packets from here */ - Channel_ptr lrt_fail_chan; /* Lrt's failure channel */ - Channel_ptr ltt_fail_chan; /* Ltt's failure channel */ + u16 lrt_fail_chan; /* Lrt's failure channel */ + u16 ltt_fail_chan; /* Ltt's failure channel */ /* RUP structure for HOST to driver communications */ struct RUP rup; diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h index ebbe3ea873e8..34c0d2899ef1 100644 --- a/drivers/char/rio/linux_compat.h +++ b/drivers/char/rio/linux_compat.h @@ -25,10 +25,6 @@ struct ttystatics { struct termios tm; }; -#define bcopy(src, dest, n) memcpy ((dest), (src), (n)) - -#define SEM_SIGIGNORE 0x1234 - extern int rio_debug; #define RIO_DEBUG_INIT 0x000001 diff --git a/drivers/char/rio/list.h b/drivers/char/rio/list.h deleted file mode 100644 index 79b853140ae5..000000000000 --- a/drivers/char/rio/list.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* L I S T ******* - ******* ******* - **************************************************************************** - - Author : Jeremy Rolls. - Date : 04-Nov-1990 - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - ***************************************************************************/ - -#ifndef _list_h -#define _list_h 1 - -#ifdef SCCS_LABELS -#ifndef lint -static char *_rio_list_h_sccs = "@(#)list.h 1.9"; -#endif -#endif - -#define PKT_IN_USE 0x1 - -#define ZERO_PTR (ushort) 0x8000 -#define CaD PortP->Caddr - -/* -** We can add another packet to a transmit queue if the packet pointer pointed -** to by the TxAdd pointer has PKT_IN_USE clear in its address. -*/ - -#endif /* ifndef _list.h */ -/*********** end of file ***********/ diff --git a/drivers/char/rio/map.h b/drivers/char/rio/map.h index 97fe287aab2a..bdbcd09c8b81 100644 --- a/drivers/char/rio/map.h +++ b/drivers/char/rio/map.h @@ -47,17 +47,17 @@ static char *_map_h_sccs_ = "@(#)map.h 1.2"; #define MAX_NAME_LEN 32 struct Map { - uint HostUniqueNum; /* Supporting hosts unique number */ - uint RtaUniqueNum; /* Unique number */ + unsigned int HostUniqueNum; /* Supporting hosts unique number */ + unsigned int RtaUniqueNum; /* Unique number */ /* ** The next two IDs must be swapped on big-endian architectures ** when using a v2.04 /etc/rio/config with a v3.00 driver (when ** upgrading for example). */ - ushort ID; /* ID used in the subnet */ - ushort ID2; /* ID of 2nd block of 8 for 16 port */ - ulong Flags; /* Booted, ID Given, Disconnected */ - ulong SysPort; /* First tty mapped to this port */ + unsigned short ID; /* ID used in the subnet */ + unsigned short ID2; /* ID of 2nd block of 8 for 16 port */ + unsigned long Flags; /* Booted, ID Given, Disconnected */ + unsigned long SysPort; /* First tty mapped to this port */ struct Top Topology[LINKS_PER_UNIT]; /* ID connected to each link */ char Name[MAX_NAME_LEN]; /* Cute name by which RTA is known */ }; diff --git a/drivers/char/rio/param.h b/drivers/char/rio/param.h index de7e57180c91..675c200b2459 100644 --- a/drivers/char/rio/param.h +++ b/drivers/char/rio/param.h @@ -43,18 +43,18 @@ static char *_param_h_sccs_ = "@(#)param.h 1.2"; */ struct phb_param { - BYTE Cmd; /* It is very important that these line up */ - BYTE Cor1; /* with what is expected at the other end. */ - BYTE Cor2; /* to confirm that you've got it right, */ - BYTE Cor4; /* check with cirrus/cirrus.h */ - BYTE Cor5; - BYTE TxXon; /* Transmit X-On character */ - BYTE TxXoff; /* Transmit X-Off character */ - BYTE RxXon; /* Receive X-On character */ - BYTE RxXoff; /* Receive X-Off character */ - BYTE LNext; /* Literal-next character */ - BYTE TxBaud; /* Transmit baudrate */ - BYTE RxBaud; /* Receive baudrate */ + u8 Cmd; /* It is very important that these line up */ + u8 Cor1; /* with what is expected at the other end. */ + u8 Cor2; /* to confirm that you've got it right, */ + u8 Cor4; /* check with cirrus/cirrus.h */ + u8 Cor5; + u8 TxXon; /* Transmit X-On character */ + u8 TxXoff; /* Transmit X-Off character */ + u8 RxXon; /* Receive X-On character */ + u8 RxXoff; /* Receive X-Off character */ + u8 LNext; /* Literal-next character */ + u8 TxBaud; /* Transmit baudrate */ + u8 RxBaud; /* Receive baudrate */ }; #endif diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h index c4085fbf9ec6..9764ef85c5a6 100644 --- a/drivers/char/rio/parmmap.h +++ b/drivers/char/rio/parmmap.h @@ -47,17 +47,17 @@ typedef struct PARM_MAP PARM_MAP; struct PARM_MAP { - PHB_ptr phb_ptr; /* Pointer to the PHB array */ + u16 phb_ptr; /* Pointer to the PHB array */ u16 phb_num_ptr; /* Ptr to Number of PHB's */ - FREE_LIST_ptr free_list; /* Free List pointer */ - FREE_LIST_ptr free_list_end; /* Free List End pointer */ - Q_BUF_ptr_ptr q_free_list_ptr; /* Ptr to Q_BUF variable */ + u16 free_list; /* Free List pointer */ + u16 free_list_end; /* Free List End pointer */ + u16 q_free_list_ptr; /* Ptr to Q_BUF variable */ u16 unit_id_ptr; /* Unit Id */ - LPB_ptr link_str_ptr; /* Link Structure Array */ + u16 link_str_ptr; /* Link Structure Array */ u16 bootloader_1; /* 1st Stage Boot Loader */ u16 bootloader_2; /* 2nd Stage Boot Loader */ u16 port_route_map_ptr; /* Port Route Map */ - ROUTE_STR_ptr route_ptr; /* Unit Route Map */ + u16 route_ptr; /* Unit Route Map */ u16 map_present; /* Route Map present */ s16 pkt_num; /* Total number of packets */ s16 q_num; /* Total number of Q packets */ @@ -70,7 +70,7 @@ struct PARM_MAP { u16 rx_limit; /* For high / low watermarks */ s16 links; /* Links to use */ s16 timer; /* Interrupts per second */ - RUP_ptr rups; /* Pointer to the RUPs */ + u16 rups; /* Pointer to the RUPs */ u16 max_phb; /* Mostly for debugging */ u16 living; /* Just increments!! */ u16 init_done; /* Initialisation over */ diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h index 05d59f4b9fb0..a4c48ae4e365 100644 --- a/drivers/char/rio/phb.h +++ b/drivers/char/rio/phb.h @@ -117,7 +117,7 @@ * the start. The pointer tx_add points to a SPACE to put a Packet. * The pointer tx_remove points to the next Packet to remove *************************************************************************/ -typedef struct PHB PHB; + struct PHB { u8 source; u8 handshake; diff --git a/drivers/char/rio/qbuf.h b/drivers/char/rio/qbuf.h deleted file mode 100644 index 391ffc335535..000000000000 --- a/drivers/char/rio/qbuf.h +++ /dev/null @@ -1,62 +0,0 @@ - -/**************************************************************************** - ******* ******* - ******* Q U E U E B U F F E R S T R U C T U R E S - ******* ******* - **************************************************************************** - - Author : Ian Nandhra / Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _qbuf_h -#define _qbuf_h 1 - -#ifndef lint -#ifdef SCCS_LABELS -static char *_rio_qbuf_h_sccs = "@(#)qbuf.h 1.1"; -#endif -#endif - - - -#define PKTS_PER_BUFFER (220 / PKT_LENGTH) - -typedef struct Q_BUF Q_BUF; -struct Q_BUF { - Q_BUF_ptr next; - Q_BUF_ptr prev; - PKT_ptr buf[PKTS_PER_BUFFER]; -}; - - -#endif - - -/*********** end of file ***********/ -- cgit v1.2.3-59-g8ed1b From 554b7c801e379e8c0072533b4da89a3a003cbfac Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 24 Mar 2006 03:18:32 -0800 Subject: [PATCH] Yet more rio cleaning (2 of 2) - Remove more unused headers - Remove various typedefs - Correct type of PaddrP (physical addresses should be ulong) - Kill use of bcopy - More printk cleanups - Kill true/false - Clean up direct access to pci BARs Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/rio/rio.h | 169 ++++++++++------------------------------ drivers/char/rio/rio_linux.c | 70 +++-------------- drivers/char/rio/rioboot.c | 78 +++++++++---------- drivers/char/rio/riocmd.c | 52 +++++-------- drivers/char/rio/rioctrl.c | 33 ++++---- drivers/char/rio/rioinit.c | 23 +++--- drivers/char/rio/riointr.c | 9 +-- drivers/char/rio/rioparam.c | 39 ++++------ drivers/char/rio/rioroute.c | 110 +++++++++++--------------- drivers/char/rio/riotable.c | 49 +++++------- drivers/char/rio/riotty.c | 179 ++++++++++++------------------------------- drivers/char/rio/riotypes.h | 64 ---------------- drivers/char/rio/rom.h | 62 --------------- drivers/char/rio/sam.h | 67 ---------------- drivers/char/rio/space.h | 45 ----------- drivers/char/rio/top.h | 48 ------------ drivers/char/rio/typdef.h | 74 ------------------ drivers/char/rio/unixrup.h | 6 +- 18 files changed, 265 insertions(+), 912 deletions(-) delete mode 100644 drivers/char/rio/riotypes.h delete mode 100644 drivers/char/rio/rom.h delete mode 100644 drivers/char/rio/sam.h delete mode 100644 drivers/char/rio/space.h delete mode 100644 drivers/char/rio/top.h delete mode 100644 drivers/char/rio/typdef.h (limited to 'drivers') diff --git a/drivers/char/rio/rio.h b/drivers/char/rio/rio.h index 2d466ffe112d..b4c91871ba28 100644 --- a/drivers/char/rio/rio.h +++ b/drivers/char/rio/rio.h @@ -33,38 +33,6 @@ #ifndef __rio_rio_h__ #define __rio_rio_h__ -#ifdef SCCS_LABELS -static char *_rio_h_sccs_ = "@(#)rio.h 1.3"; -#endif - -/* -** 30.09.1998 ARG - -** Introduced driver version and host card type strings -*/ -#define RIO_DRV_STR "Specialix RIO Driver" -#define RIO_AT_HOST_STR "ISA" -#define RIO_PCI_HOST_STR "PCI" - - -/* -** rio_info_store() commands (arbitary values) : -*/ -#define RIO_INFO_PUT 0xA4B3C2D1 -#define RIO_INFO_GET 0xF1E2D3C4 - - -/* -** anything that I couldn't cram in somewhere else -*/ -/* -#ifndef RIODEBUG -#define debug -#else -#define debug rioprint -#endif -*/ - - /* ** Maximum numbers of things */ @@ -101,9 +69,8 @@ static char *_rio_h_sccs_ = "@(#)rio.h 1.3"; /* ** Flag values returned by functions */ + #define RIO_FAIL -1 -#define RIO_SUCCESS 0 -#define COPYFAIL -1 /* copy[in|out] failed */ /* ** SysPort value for something that hasn't any ports @@ -142,30 +109,8 @@ static char *_rio_h_sccs_ = "@(#)rio.h 1.3"; /* ** Generally useful constants */ -#define HALF_A_SECOND ((HZ)>>1) -#define A_SECOND (HZ) -#define HUNDRED_HZ ((HZ/100)?(HZ/100):1) -#define FIFTY_HZ ((HZ/50)?(HZ/50):1) -#define TWENTY_HZ ((HZ/20)?(HZ/20):1) -#define TEN_HZ ((HZ/10)?(HZ/10):1) -#define FIVE_HZ ((HZ/5)?(HZ/5):1) -#define HUNDRED_MS TEN_HZ -#define FIFTY_MS TWENTY_HZ -#define TWENTY_MS FIFTY_HZ -#define TEN_MS HUNDRED_HZ -#define TWO_SECONDS ((A_SECOND)*2) -#define FIVE_SECONDS ((A_SECOND)*5) -#define TEN_SECONDS ((A_SECOND)*10) -#define FIFTEEN_SECONDS ((A_SECOND)*15) -#define TWENTY_SECONDS ((A_SECOND)*20) -#define HALF_A_MINUTE (A_MINUTE>>1) -#define A_MINUTE (A_SECOND*60) -#define FIVE_MINUTES (A_MINUTE*5) -#define QUARTER_HOUR (A_MINUTE*15) -#define HALF_HOUR (A_MINUTE*30) -#define HOUR (A_MINUTE*60) - -#define SIXTEEN_MEG 0x1000000 + +#define HUNDRED_MS ((HZ/10)?(HZ/10):1) #define ONE_MEG 0x100000 #define SIXTY_FOUR_K 0x10000 @@ -173,8 +118,6 @@ static char *_rio_h_sccs_ = "@(#)rio.h 1.3"; #define RIO_EISA_MEM_SIZE SIXTY_FOUR_K #define RIO_MCA_MEM_SIZE SIXTY_FOUR_K -#define POLL_VECTOR 0x100 - #define COOK_WELL 0 #define COOK_MEDIUM 1 #define COOK_RAW 2 @@ -193,62 +136,19 @@ static char *_rio_h_sccs_ = "@(#)rio.h 1.3"; ** How to convert from various different device number formats: ** DEV is a dev number, as passed to open, close etc - NOT a minor ** number! -** -** Note: LynxOS only gives us 8 bits for the device minor number, -** so all this crap here to deal with 'modem' bits etc. is -** just a load of irrelevant old bunkum! -** This however does not stop us needing to define a value -** for RIO_MODEMOFFSET which is required by the 'riomkdev' -** utility in the New Config Utilities suite. -*/ -/* 0-511: direct 512-1023: modem */ -#define RIO_MODEMOFFSET 0x200 /* doesn't mean anything */ +**/ + #define RIO_MODEM_MASK 0x1FF #define RIO_MODEM_BIT 0x200 #define RIO_UNMODEM(DEV) (MINOR(DEV) & RIO_MODEM_MASK) #define RIO_ISMODEM(DEV) (MINOR(DEV) & RIO_MODEM_BIT) #define RIO_PORT(DEV,FIRST_MAJ) ( (MAJOR(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \ + MINOR(DEV) - -#define splrio spltty - -#define RIO_IPL 5 -#define RIO_PRI (PZERO+10) -#define RIO_CLOSE_PRI PZERO-1 /* uninterruptible sleeps for close */ - -typedef struct DbInf { - uint Flag; - char Name[8]; -} DbInf; - -#ifndef TRUE -#define TRUE (1==1) -#endif -#ifndef FALSE -#define FALSE (!TRUE) -#endif - -#define CSUM(pkt_ptr) (((ushort *)(pkt_ptr))[0] + ((ushort *)(pkt_ptr))[1] + \ - ((ushort *)(pkt_ptr))[2] + ((ushort *)(pkt_ptr))[3] + \ - ((ushort *)(pkt_ptr))[4] + ((ushort *)(pkt_ptr))[5] + \ - ((ushort *)(pkt_ptr))[6] + ((ushort *)(pkt_ptr))[7] + \ - ((ushort *)(pkt_ptr))[8] + ((ushort *)(pkt_ptr))[9] ) - -/* -** This happy little macro copies SIZE bytes of data from FROM to TO -** quite well. SIZE must be a constant. -*/ -#define CCOPY( FROM, TO, SIZE ) { *(struct s { char data[SIZE]; } *)(TO) = *(struct s *)(FROM); } - -/* -** increment a buffer pointer modulo the size of the buffer... -*/ -#define BUMP( P, I ) ((P) = (((P)+(I)) & RIOBufferMask)) - -#define INIT_PACKET( PK, PP ) \ -{ \ - *((uint *)PK) = PP->PacketInfo; \ -} +#define CSUM(pkt_ptr) (((u16 *)(pkt_ptr))[0] + ((u16 *)(pkt_ptr))[1] + \ + ((u16 *)(pkt_ptr))[2] + ((u16 *)(pkt_ptr))[3] + \ + ((u16 *)(pkt_ptr))[4] + ((u16 *)(pkt_ptr))[5] + \ + ((u16 *)(pkt_ptr))[6] + ((u16 *)(pkt_ptr))[7] + \ + ((u16 *)(pkt_ptr))[8] + ((u16 *)(pkt_ptr))[9] ) #define RIO_LINK_ENABLE 0x80FF /* FF is a hack, mainly for Mips, to */ /* prevent a really stupid race condition. */ @@ -267,27 +167,42 @@ typedef struct DbInf { #define DISCONNECT 0 #define CONNECT 1 +/* ------ Control Codes ------ */ -/* -** Machine types - these must NOT overlap with product codes 0-15 -*/ -#define RIO_MIPS_R3230 31 -#define RIO_MIPS_R4030 32 +#define CONTROL '^' +#define IFOAD ( CONTROL + 1 ) +#define IDENTIFY ( CONTROL + 2 ) +#define ZOMBIE ( CONTROL + 3 ) +#define UFOAD ( CONTROL + 4 ) +#define IWAIT ( CONTROL + 5 ) + +#define IFOAD_MAGIC 0xF0AD /* of course */ +#define ZOMBIE_MAGIC (~0xDEAD) /* not dead -> zombie */ +#define UFOAD_MAGIC 0xD1E /* kill-your-neighbour */ +#define IWAIT_MAGIC 0xB1DE /* Bide your time */ + +/* ------ Error Codes ------ */ + +#define E_NO_ERROR ((ushort) 0) + +/* ------ Free Lists ------ */ -#define RIO_IO_UNKNOWN -2 +struct rio_free_list { + u16 next; + u16 prev; +}; -#undef MODERN -#define ERROR( E ) do { u.u_error = E; return OPENFAIL } while ( 0 ) +/* NULL for card side linked lists */ +#define TPNULL ((ushort)(0x8000)) +/* We can add another packet to a transmit queue if the packet pointer pointed + * to by the TxAdd pointer has PKT_IN_USE clear in its address. */ +#define PKT_IN_USE 0x1 -/* Defines for MPX line discipline routines */ +/* ------ Topology ------ */ -#define DIST_LINESW_OPEN 0x01 -#define DIST_LINESW_CLOSE 0x02 -#define DIST_LINESW_READ 0x04 -#define DIST_LINESW_WRITE 0x08 -#define DIST_LINESW_IOCTL 0x10 -#define DIST_LINESW_INPUT 0x20 -#define DIST_LINESW_OUTPUT 0x40 -#define DIST_LINESW_MDMINT 0x80 +struct Top { + u8 Unit; + u8 Link; +}; #endif /* __rio_h__ */ diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index f1e9e9a20c85..78dd856534ce 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -57,15 +57,12 @@ #include #include "linux_compat.h" -#include "typdef.h" #include "pkt.h" #include "daemon.h" #include "rio.h" #include "riospace.h" -#include "top.h" #include "cmdpkt.h" #include "map.h" -#include "riotypes.h" #include "rup.h" #include "port.h" #include "riodrvr.h" @@ -78,17 +75,13 @@ #include "unixrup.h" #include "board.h" #include "host.h" -#include "error.h" #include "phb.h" #include "link.h" #include "cmdblk.h" #include "route.h" -#include "control.h" #include "cirrus.h" #include "rioioctl.h" #include "param.h" -#include "list.h" -#include "sam.h" #include "protsts.h" #include "rioboard.h" @@ -350,27 +343,9 @@ int rio_minor(struct tty_struct *tty) return tty->index + (tty->driver == rio_driver) ? 0 : 256; } -int rio_ismodem(struct tty_struct *tty) -{ - return 1; -} - - static int rio_set_real_termios(void *ptr) { - int rv, modem; - struct tty_struct *tty; - func_enter(); - - tty = ((struct Port *) ptr)->gs.tty; - - modem = rio_ismodem(tty); - - rv = RIOParam((struct Port *) ptr, CONFIG, modem, 1); - - func_exit(); - - return rv; + return RIOParam((struct Port *) ptr, CONFIG, 1, 1); } @@ -973,7 +948,6 @@ static int __init rio_init(void) #ifdef CONFIG_PCI struct pci_dev *pdev = NULL; - unsigned int tint; unsigned short tshort; #endif @@ -998,6 +972,8 @@ static int __init rio_init(void) #ifdef CONFIG_PCI /* First look for the JET devices: */ while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) { + u32 tint; + if (pci_enable_device(pdev)) continue; @@ -1008,7 +984,6 @@ static int __init rio_init(void) Also, reading a non-aligned dword doesn't work. So we read the whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID) ourselves */ - /* I don't know why the define doesn't work, constant 0x2c does --REW */ pci_read_config_dword(pdev, 0x2c, &tint); tshort = (tint >> 16) & 0xffff; rio_dprintk(RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint); @@ -1018,10 +993,8 @@ static int __init rio_init(void) } rio_dprintk(RIO_DEBUG_PROBE, "cp1\n"); - pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint); - hp = &p->RIOHosts[p->RIONumHosts]; - hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; + hp->PaddrP = pci_resource_start(pdev, 2); hp->Ivec = pdev->irq; if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; @@ -1035,7 +1008,7 @@ static int __init rio_init(void) rio_start_card_running(hp); rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); - if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == RIO_SUCCESS) { + if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) { rio_dprintk(RIO_DEBUG_INIT, "Done RIOBoardTest\n"); writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); p->RIOHosts[p->RIONumHosts].UniqueNum = @@ -1044,7 +1017,7 @@ static int __init rio_init(void) rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); fix_rio_pci(pdev); - p->RIOLastPCISearch = RIO_SUCCESS; + p->RIOLastPCISearch = 0; p->RIONumHosts++; found++; } else { @@ -1067,10 +1040,8 @@ static int __init rio_init(void) continue; #ifdef CONFIG_RIO_OLDPCI - pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &tint); - hp = &p->RIOHosts[p->RIONumHosts]; - hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; + hp->PaddrP = pci_resource_start(pdev, 0); hp->Ivec = pdev->irq; if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; @@ -1088,14 +1059,14 @@ static int __init rio_init(void) rio_reset_interrupt(hp); rio_start_card_running(hp); rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); - if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == RIO_SUCCESS) { + if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) { writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt); p->RIOHosts[p->RIONumHosts].UniqueNum = ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); - p->RIOLastPCISearch = RIO_SUCCESS; + p->RIOLastPCISearch = 0; p->RIONumHosts++; found++; } else { @@ -1129,7 +1100,7 @@ static int __init rio_init(void) okboard = 0; if ((strncmp(vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) { /* Board is present... */ - if (RIOBoardTest(hp->PaddrP, hp->Caddr, RIO_AT, 0) == RIO_SUCCESS) { + if (RIOBoardTest(hp->PaddrP, hp->Caddr, RIO_AT, 0) == 0) { /* ... and feeling fine!!!! */ rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) { @@ -1231,24 +1202,3 @@ static void __exit rio_exit(void) module_init(rio_init); module_exit(rio_exit); - -/* - * Anybody who knows why this doesn't work for me, please tell me -- REW. - * Snatched from scsi.c (fixed one spelling error): - * Overrides for Emacs so that we follow Linus' tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local Variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c index e1542e8dfb43..acda9326c2ef 100644 --- a/drivers/char/rio/rioboot.c +++ b/drivers/char/rio/rioboot.c @@ -47,15 +47,12 @@ #include "linux_compat.h" #include "rio_linux.h" -#include "typdef.h" #include "pkt.h" #include "daemon.h" #include "rio.h" #include "riospace.h" -#include "top.h" #include "cmdpkt.h" #include "map.h" -#include "riotypes.h" #include "rup.h" #include "port.h" #include "riodrvr.h" @@ -68,7 +65,6 @@ #include "unixrup.h" #include "board.h" #include "host.h" -#include "error.h" #include "phb.h" #include "link.h" #include "cmdblk.h" @@ -386,7 +382,7 @@ int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp) */ offset = (p->RIOConf.HostLoadBase - 2) - 0x7FFC; - writeb(NFIX(((ushort) (~offset) >> (ushort) 12) & 0xF), DestP); + writeb(NFIX(((unsigned short) (~offset) >> (unsigned short) 12) & 0xF), DestP); writeb(PFIX((offset >> 8) & 0xF), DestP + 1); writeb(PFIX((offset >> 4) & 0xF), DestP + 2); writeb(JUMP(offset & 0xF), DestP + 3); @@ -515,10 +511,10 @@ int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp) ** 32 bit pointers for the driver in ioremap space. */ HostP->ParmMapP = ParmMapP; - HostP->PhbP = (PHB *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr)); - HostP->RupP = (RUP *) RIO_PTR(Cad, readw(&ParmMapP->rups)); - HostP->PhbNumP = (ushort *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr)); - HostP->LinkStrP = (LPB *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr)); + HostP->PhbP = (struct PHB *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr)); + HostP->RupP = (struct RUP *) RIO_PTR(Cad, readw(&ParmMapP->rups)); + HostP->PhbNumP = (unsigned short *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr)); + HostP->LinkStrP = (struct LPB *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr)); /* ** point the UnixRups at the real Rups @@ -639,7 +635,7 @@ int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct /* ** Fill in the default info on the command block */ - CmdBlkP->Packet.dest_unit = Rup < (ushort) MAX_RUP ? Rup : 0; + CmdBlkP->Packet.dest_unit = Rup < (unsigned short) MAX_RUP ? Rup : 0; CmdBlkP->Packet.dest_port = BOOT_RUP; CmdBlkP->Packet.src_unit = 0; CmdBlkP->Packet.src_port = BOOT_RUP; @@ -748,7 +744,7 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int */ RtaType = GetUnitType(RtaUniq); - if (Rup >= (ushort) MAX_RUP) + if (Rup >= (unsigned short) MAX_RUP) rio_dprintk(RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", HostP->Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A'); else rio_dprintk(RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", HostP->Mapping[Rup].Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A'); @@ -757,7 +753,7 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int if (RtaUniq == 0x00000000 || RtaUniq == 0xffffffff) { rio_dprintk(RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n"); - return TRUE; + return 1; } /* @@ -785,7 +781,7 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int */ writew(30, &HostP->LinkStrP[MyLink].WaitNoBoot); rio_dprintk(RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum); - return TRUE; + return 1; } /* @@ -826,7 +822,7 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", entry + 1, entry2 + 1); else rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given ID %d\n", entry + 1); - return TRUE; + return 1; } } @@ -868,7 +864,7 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n", entry); if (!p->RIONoMessage) printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); - return TRUE; + return 1; } } @@ -961,13 +957,13 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int if (RtaType == TYPE_RTA16) { if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0) { RIODefaultName(p, HostP, entry); - FillSlot(entry, entry2, RtaUniq, HostP); + rio_fill_host_slot(entry, entry2, RtaUniq, HostP); EmptySlot = 0; } } else { if (RIOFindFreeID(p, HostP, &entry, NULL) == 0) { RIODefaultName(p, HostP, entry); - FillSlot(entry, 0, RtaUniq, HostP); + rio_fill_host_slot(entry, 0, RtaUniq, HostP); EmptySlot = 0; } } @@ -1023,7 +1019,7 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int } else if (!p->RIONoMessage) printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A'); RIOSetChange(p); - return TRUE; + return 1; } /* @@ -1038,7 +1034,7 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int /* ** already got it! */ - return TRUE; + return 1; } } /* @@ -1046,13 +1042,13 @@ static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int */ if (HostP->NumExtraBooted < MAX_EXTRA_UNITS) HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq; - return TRUE; + return 1; } /* ** If the RTA or its host appears in the RIOBindTab[] structure then -** we mustn't boot the RTA and should return FALSE. +** we mustn't boot the RTA and should return 0. ** This operation is slightly different from the other drivers for RIO ** in that this is designed to work with the new utilities ** not config.rio and is FAR SIMPLER. @@ -1080,38 +1076,38 @@ int RIOBootOk(struct rio_info *p, struct Host *HostP, unsigned long RtaUniq) ** slots tentative, and the second one RTA_SECOND_SLOT as well. */ -void FillSlot(int entry, int entry2, unsigned int RtaUniq, struct Host *HostP) +void rio_fill_host_slot(int entry, int entry2, unsigned int rta_uniq, struct Host *host) { int link; - rio_dprintk(RIO_DEBUG_BOOT, "FillSlot(%d, %d, 0x%x...)\n", entry, entry2, RtaUniq); + rio_dprintk(RIO_DEBUG_BOOT, "rio_fill_host_slot(%d, %d, 0x%x...)\n", entry, entry2, rta_uniq); - HostP->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE); - HostP->Mapping[entry].SysPort = NO_PORT; - HostP->Mapping[entry].RtaUniqueNum = RtaUniq; - HostP->Mapping[entry].HostUniqueNum = HostP->UniqueNum; - HostP->Mapping[entry].ID = entry + 1; - HostP->Mapping[entry].ID2 = 0; + host->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE); + host->Mapping[entry].SysPort = NO_PORT; + host->Mapping[entry].RtaUniqueNum = rta_uniq; + host->Mapping[entry].HostUniqueNum = host->UniqueNum; + host->Mapping[entry].ID = entry + 1; + host->Mapping[entry].ID2 = 0; if (entry2) { - HostP->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE | RTA16_SECOND_SLOT); - HostP->Mapping[entry2].SysPort = NO_PORT; - HostP->Mapping[entry2].RtaUniqueNum = RtaUniq; - HostP->Mapping[entry2].HostUniqueNum = HostP->UniqueNum; - HostP->Mapping[entry2].Name[0] = '\0'; - HostP->Mapping[entry2].ID = entry2 + 1; - HostP->Mapping[entry2].ID2 = entry + 1; - HostP->Mapping[entry].ID2 = entry2 + 1; + host->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE | RTA16_SECOND_SLOT); + host->Mapping[entry2].SysPort = NO_PORT; + host->Mapping[entry2].RtaUniqueNum = rta_uniq; + host->Mapping[entry2].HostUniqueNum = host->UniqueNum; + host->Mapping[entry2].Name[0] = '\0'; + host->Mapping[entry2].ID = entry2 + 1; + host->Mapping[entry2].ID2 = entry + 1; + host->Mapping[entry].ID2 = entry2 + 1; } /* ** Must set these up, so that utilities show ** topology of 16 port RTAs correctly */ for (link = 0; link < LINKS_PER_UNIT; link++) { - HostP->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT; - HostP->Mapping[entry].Topology[link].Link = NO_LINK; + host->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT; + host->Mapping[entry].Topology[link].Link = NO_LINK; if (entry2) { - HostP->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT; - HostP->Mapping[entry2].Topology[link].Link = NO_LINK; + host->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT; + host->Mapping[entry2].Topology[link].Link = NO_LINK; } } } diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index 08fcac1f12de..e6d2b14b5e65 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c @@ -51,15 +51,12 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2"; #include "linux_compat.h" #include "rio_linux.h" -#include "typdef.h" #include "pkt.h" #include "daemon.h" #include "rio.h" #include "riospace.h" -#include "top.h" #include "cmdpkt.h" #include "map.h" -#include "riotypes.h" #include "rup.h" #include "port.h" #include "riodrvr.h" @@ -72,12 +69,10 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2"; #include "unixrup.h" #include "board.h" #include "host.h" -#include "error.h" #include "phb.h" #include "link.h" #include "cmdblk.h" #include "route.h" -#include "control.h" #include "cirrus.h" @@ -148,7 +143,7 @@ int RIOCommandRta(struct rio_info *p, unsigned long RtaUnique, int (*func) (stru { unsigned int Host; - rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%lx func 0x%p\n", RtaUnique, func); + rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%lx func %p\n", RtaUnique, func); if (!RtaUnique) return (0); @@ -375,7 +370,7 @@ int RIOFoadWakeup(struct rio_info *p) /* ** Incoming command on the COMMAND_RUP to be processed. */ -static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) +static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struct PKT * PacketP) { struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data; struct Port *PortP; @@ -418,7 +413,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", PacketP->control, PacketP->control); rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", PacketP->csum, PacketP->csum); rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command); - return TRUE; + return 1; } PortP = p->RIOPortp[SysPort]; rio_spin_lock_irqsave(&PortP->portSem, flags); @@ -427,7 +422,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n"); /* If the current line disc. is not multi-threading and the current processor is not the default, reset rup_intr - and return FALSE to ensure that the command packet is + and return 0 to ensure that the command packet is not freed. */ /* Call tmgr HANGUP HERE */ /* Fix this later when every thing works !!!! RAMRAJ */ @@ -541,7 +536,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * func_exit(); - return TRUE; + return 1; } /* @@ -600,13 +595,13 @@ int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) ** straight on the RUP.... */ if ((UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) - : TRUE)) { + : 1)) { rio_dprintk(RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", CmdBlkP->Packet.data[0]); /* ** Whammy! blat that pack! */ - HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT)); + HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(struct PKT)); /* ** place command packet on the pending position. @@ -620,7 +615,7 @@ int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - return RIO_SUCCESS; + return 0; } rio_dprintk(RIO_DEBUG_CMD, "RUP active - en-queing\n"); @@ -633,15 +628,15 @@ int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) Base = &UnixRupP->CmdsWaitingP; - rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk 0x%p at 0x%p\n", CmdBlkP, Base); + rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk %p at %p\n", CmdBlkP, Base); while (*Base) { - rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk 0x%p here\n", *Base); + rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk %p here\n", *Base); Base = &((*Base)->NextP); - rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk 0x%p at 0x%p\n", CmdBlkP, Base); + rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk %p at %p\n", CmdBlkP, Base); } - rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk 0x%p at 0x%p\n", CmdBlkP, Base); + rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk %p at %p\n", CmdBlkP, Base); *Base = CmdBlkP; @@ -649,7 +644,7 @@ int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - return RIO_SUCCESS; + return 0; } /* @@ -681,9 +676,7 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) { int FreeMe; - PacketP = (PKT *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt)); - - ShowPacket(DBG_CMD, PacketP); + PacketP = (struct PKT *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt)); switch (readb(&PacketP->dest_port)) { case BOOT_RUP: @@ -749,7 +742,7 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) if (CmdBlkP->Packet.dest_port == BOOT_RUP) rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]); - rio_dprintk(RIO_DEBUG_CMD, "Command 0x%p completed\n", CmdBlkP); + rio_dprintk(RIO_DEBUG_CMD, "Command %p completed\n", CmdBlkP); /* ** Clear the Rup lock to prevent mutual exclusion. @@ -782,14 +775,14 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) ** If it returns RIO_FAIL then don't ** send this command yet! */ - if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : TRUE)) { - rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command 0x%p\n", CmdBlkP); + if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : 1)) { + rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command %p\n", CmdBlkP); } else { - rio_dprintk(RIO_DEBUG_CMD, "Start new command 0x%p Cmd byte is 0x%x\n", CmdBlkP, CmdBlkP->Packet.data[0]); + rio_dprintk(RIO_DEBUG_CMD, "Start new command %p Cmd byte is 0x%x\n", CmdBlkP, CmdBlkP->Packet.data[0]); /* ** Whammy! blat that pack! */ - HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT)); + HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(struct PKT)); /* ** remove the command from the rup command queue... @@ -831,14 +824,13 @@ int RIOWFlushMark(unsigned long iPortP, struct CmdBlk *CmdBlkP) int RIORFlushEnable(unsigned long iPortP, struct CmdBlk *CmdBlkP) { struct Port *PortP = (struct Port *) iPortP; - PKT *PacketP; + struct PKT *PacketP; unsigned long flags; rio_spin_lock_irqsave(&PortP->portSem, flags); while (can_remove_receive(&PacketP, PortP)) { remove_receive(PortP); - ShowPacket(DBG_PROC, PacketP); put_free_end(PortP->HostP, PacketP); } @@ -892,10 +884,6 @@ int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP) return 0; } -void ShowPacket(uint Flags, struct PKT *PacketP) -{ -} - /* ** ** How to use this file: diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c index f6a19aae1044..d31aba62bb7f 100644 --- a/drivers/char/rio/rioctrl.c +++ b/drivers/char/rio/rioctrl.c @@ -51,15 +51,12 @@ static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c 1.3"; #include "linux_compat.h" #include "rio_linux.h" -#include "typdef.h" #include "pkt.h" #include "daemon.h" #include "rio.h" #include "riospace.h" -#include "top.h" #include "cmdpkt.h" #include "map.h" -#include "riotypes.h" #include "rup.h" #include "port.h" #include "riodrvr.h" @@ -72,12 +69,10 @@ static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c 1.3"; #include "unixrup.h" #include "board.h" #include "host.h" -#include "error.h" #include "phb.h" #include "link.h" #include "cmdblk.h" #include "route.h" -#include "control.h" #include "cirrus.h" #include "rioioctl.h" @@ -144,7 +139,7 @@ int su; ushort loop; int Entry; struct Port *PortP; - PKT *PacketP; + struct PKT *PacketP; int retval = 0; unsigned long flags; @@ -154,7 +149,7 @@ int su; Host = 0; PortP = NULL; - rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: 0x%p\n", cmd, arg); + rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, arg); switch (cmd) { /* @@ -572,8 +567,8 @@ int su; PortSetup.Store = p->RIOPortp[port]->Store; PortSetup.Lock = p->RIOPortp[port]->Lock; PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps; - bcopy(p->RIOPortp[port]->Xprint.XpOn, PortSetup.XpOn, MAX_XP_CTRL_LEN); - bcopy(p->RIOPortp[port]->Xprint.XpOff, PortSetup.XpOff, MAX_XP_CTRL_LEN); + memcpy(PortSetup.XpOn, p->RIOPortp[port]->Xprint.XpOn, MAX_XP_CTRL_LEN); + memcpy(PortSetup.XpOff, p->RIOPortp[port]->Xprint.XpOff, MAX_XP_CTRL_LEN); PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0'; PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0'; @@ -1404,7 +1399,7 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd) return RIO_FAIL; } - rio_dprintk(RIO_DEBUG_CTRL, "Command blk 0x%p - InUse now %d\n", CmdBlkP, PortP->InUse); + rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n", CmdBlkP, PortP->InUse); PktCmdP = (struct PktCmd_M *) &CmdBlkP->Packet.data[0]; @@ -1430,38 +1425,38 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd) switch (Cmd) { case MEMDUMP: - rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk 0x%p (addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr); + rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p (addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr); PktCmdP->SubCommand = MEMDUMP; PktCmdP->SubAddr = SubCmd.Addr; break; case FCLOSE: - rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk 0x%p\n", CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n", CmdBlkP); break; case READ_REGISTER: - rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk 0x%p\n", (int) SubCmd.Addr, CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk %p\n", (int) SubCmd.Addr, CmdBlkP); PktCmdP->SubCommand = READ_REGISTER; PktCmdP->SubAddr = SubCmd.Addr; break; case RESUME: - rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk 0x%p\n", CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n", CmdBlkP); break; case RFLUSH: - rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk 0x%p\n", CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n", CmdBlkP); CmdBlkP->PostFuncP = RIORFlushEnable; break; case SUSPEND: - rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk 0x%p\n", CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n", CmdBlkP); break; case MGET: - rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk 0x%p\n", CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n", CmdBlkP); break; case MSET: case MBIC: case MBIS: CmdBlkP->Packet.data[4] = (char) PortP->ModemLines; - rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk 0x%p\n", CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk %p\n", CmdBlkP); break; case WFLUSH: @@ -1475,7 +1470,7 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd) RIOFreeCmdBlk(CmdBlkP); return (RIO_FAIL); } else { - rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command blk 0x%p\n", CmdBlkP); + rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command blk %p\n", CmdBlkP); CmdBlkP->PostFuncP = RIOWFlushMark; } break; diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c index 1d73c4646bbd..24d2992154cc 100644 --- a/drivers/char/rio/rioinit.c +++ b/drivers/char/rio/rioinit.c @@ -51,15 +51,12 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3"; #include "linux_compat.h" -#include "typdef.h" #include "pkt.h" #include "daemon.h" #include "rio.h" #include "riospace.h" -#include "top.h" #include "cmdpkt.h" #include "map.h" -#include "riotypes.h" #include "rup.h" #include "port.h" #include "riodrvr.h" @@ -72,19 +69,17 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3"; #include "unixrup.h" #include "board.h" #include "host.h" -#include "error.h" #include "phb.h" #include "link.h" #include "cmdblk.h" #include "route.h" -#include "control.h" #include "cirrus.h" #include "rioioctl.h" #include "rio_linux.h" int RIOPCIinit(struct rio_info *p, int Mode); -static int RIOScrub(int, BYTE *, int); +static int RIOScrub(int, u8 *, int); /** @@ -156,7 +151,7 @@ static u8 val[] = { ** RAM test a board. ** Nothing too complicated, just enough to check it out. */ -int RIOBoardTest(paddr_t paddr, caddr_t caddr, unsigned char type, int slot) +int RIOBoardTest(unsigned long paddr, caddr_t caddr, unsigned char type, int slot) { struct DpRam *DpRam = (struct DpRam *)caddr; char *ram[4]; @@ -164,7 +159,7 @@ int RIOBoardTest(paddr_t paddr, caddr_t caddr, unsigned char type, int slot) int op, bank; int nbanks; - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=0x%p, slot=%d\n", + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=%p, slot=%d\n", type, DpRam, slot); RIOHostReset(type, DpRam, slot); @@ -193,10 +188,10 @@ int RIOBoardTest(paddr_t paddr, caddr_t caddr, unsigned char type, int slot) if (nbanks == 3) { - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: 0x%p(0x%x), 0x%p(0x%x), 0x%p(0x%x)\n", + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: %p(0x%x), %p(0x%x), %p(0x%x)\n", ram[0], size[0], ram[1], size[1], ram[2], size[2]); } else { - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: 0x%p(0x%x), 0x%p(0x%x), 0x%p(0x%x), 0x%p(0x%x)\n", + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: %p(0x%x), %p(0x%x), %p(0x%x), %p(0x%x)\n", ram[0], size[0], ram[1], size[1], ram[2], size[2], ram[3], size[3]); } @@ -207,7 +202,7 @@ int RIOBoardTest(paddr_t paddr, caddr_t caddr, unsigned char type, int slot) */ for (op=0; opMagicFlags) { -#if 1 if (PortP->MagicFlags & MAGIC_REBOOT) { /* ** well, the RTA has been rebooted, and there is room @@ -413,13 +407,12 @@ void RIOServiceHost(struct rio_info *p, struct Host *HostP, int From) PortP->InUse = NOT_INUSE; rio_spin_unlock(&PortP->portSem); - if (RIOParam(PortP, OPEN, ((PortP->Cor2Copy & (COR2_RTSFLOW | COR2_CTSFLOW)) == (COR2_RTSFLOW | COR2_CTSFLOW)) ? TRUE : FALSE, DONT_SLEEP) == RIO_FAIL) { + if (RIOParam(PortP, OPEN, ((PortP->Cor2Copy & (COR2_RTSFLOW | COR2_CTSFLOW)) == (COR2_RTSFLOW | COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL) { continue; /* with next port */ } rio_spin_lock(&PortP->portSem); PortP->MagicFlags &= ~MAGIC_REBOOT; } -#endif /* ** As mentioned above, this is a tacky hack to cope diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c index af25d2084f47..d2e8092cdb29 100644 --- a/drivers/char/rio/rioparam.c +++ b/drivers/char/rio/rioparam.c @@ -52,15 +52,12 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3"; #include "linux_compat.h" #include "rio_linux.h" -#include "typdef.h" #include "pkt.h" #include "daemon.h" #include "rio.h" #include "riospace.h" -#include "top.h" #include "cmdpkt.h" #include "map.h" -#include "riotypes.h" #include "rup.h" #include "port.h" #include "riodrvr.h" @@ -73,17 +70,13 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3"; #include "unixrup.h" #include "board.h" #include "host.h" -#include "error.h" #include "phb.h" #include "link.h" #include "cmdblk.h" #include "route.h" -#include "control.h" #include "cirrus.h" #include "rioioctl.h" #include "param.h" -#include "list.h" -#include "sam.h" @@ -162,7 +155,7 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag) struct tty_struct *TtyP; int retval; struct phb_param *phb_param_ptr; - PKT *PacketP; + struct PKT *PacketP; int res; u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0; u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0; @@ -228,7 +221,7 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag) if (PortP->State & RIO_DELETED) { rio_spin_unlock_irqrestore(&PortP->portSem, flags); func_exit(); - return RIO_SUCCESS; + return 0; } } @@ -240,7 +233,7 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag) } rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res); - rio_dprintk(RIO_DEBUG_PARAM, "Packet is 0x%p\n", PacketP); + rio_dprintk(RIO_DEBUG_PARAM, "Packet is %p\n", PacketP); phb_param_ptr = (struct phb_param *) PacketP->data; @@ -579,7 +572,7 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag) */ func_exit(); - return RIO_SUCCESS; + return 0; } @@ -587,11 +580,11 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag) ** We can add another packet to a transmit queue if the packet pointer pointed ** to by the TxAdd pointer has PKT_IN_USE clear in its address. */ -int can_add_transmit(PKT **PktP, struct Port *PortP) +int can_add_transmit(struct PKT **PktP, struct Port *PortP) { - PKT *tp; + struct PKT *tp; - *PktP = tp = (PKT *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd)); + *PktP = tp = (struct PKT *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd)); return !((unsigned long) tp & PKT_IN_USE); } @@ -615,10 +608,10 @@ void add_transmit(struct Port *PortP) * Put a packet onto the end of the * free list ****************************************/ -void put_free_end(struct Host *HostP, PKT *PktP) +void put_free_end(struct Host *HostP, struct PKT *PktP) { - FREE_LIST *tmp_pointer; - ushort old_end, new_end; + struct rio_free_list *tmp_pointer; + unsigned short old_end, new_end; unsigned long flags; rio_spin_lock_irqsave(&HostP->HostLock, flags); @@ -632,15 +625,15 @@ void put_free_end(struct Host *HostP, PKT *PktP) if ((old_end = readw(&HostP->ParmMapP->free_list_end)) != TPNULL) { new_end = RIO_OFF(HostP->Caddr, PktP); - tmp_pointer = (FREE_LIST *) RIO_PTR(HostP->Caddr, old_end); + tmp_pointer = (struct rio_free_list *) RIO_PTR(HostP->Caddr, old_end); writew(new_end, &tmp_pointer->next); - writew(old_end, &((FREE_LIST *) PktP)->prev); - writew(TPNULL, &((FREE_LIST *) PktP)->next); + writew(old_end, &((struct rio_free_list *) PktP)->prev); + writew(TPNULL, &((struct rio_free_list *) PktP)->next); writew(new_end, &HostP->ParmMapP->free_list_end); } else { /* First packet on the free list this should never happen! */ rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n"); writew(RIO_OFF(HostP->Caddr, PktP), &HostP->ParmMapP->free_list_end); - tmp_pointer = (FREE_LIST *) PktP; + tmp_pointer = (struct rio_free_list *) PktP; writew(TPNULL, &tmp_pointer->prev); writew(TPNULL, &tmp_pointer->next); } @@ -654,10 +647,10 @@ void put_free_end(struct Host *HostP, PKT *PktP) ** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear, ** then can_remove_receive() returns 0. */ -int can_remove_receive(PKT **PktP, struct Port *PortP) +int can_remove_receive(struct PKT **PktP, struct Port *PortP) { if (readw(PortP->RxRemove) & PKT_IN_USE) { - *PktP = (PKT *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE); + *PktP = (struct PKT *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE); return 1; } return 0; diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c index 874ac7462388..357085337942 100644 --- a/drivers/char/rio/rioroute.c +++ b/drivers/char/rio/rioroute.c @@ -50,15 +50,12 @@ static char *_rioroute_c_sccs_ = "@(#)rioroute.c 1.3"; #include "linux_compat.h" #include "rio_linux.h" -#include "typdef.h" #include "pkt.h" #include "daemon.h" #include "rio.h" #include "riospace.h" -#include "top.h" #include "cmdpkt.h" #include "map.h" -#include "riotypes.h" #include "rup.h" #include "port.h" #include "riodrvr.h" @@ -71,29 +68,25 @@ static char *_rioroute_c_sccs_ = "@(#)rioroute.c 1.3"; #include "unixrup.h" #include "board.h" #include "host.h" -#include "error.h" #include "phb.h" #include "link.h" #include "cmdblk.h" #include "route.h" -#include "control.h" #include "cirrus.h" #include "rioioctl.h" #include "param.h" -#include "list.h" -#include "sam.h" -static int RIOCheckIsolated(struct rio_info *, struct Host *, uint); -static int RIOIsolate(struct rio_info *, struct Host *, uint); -static int RIOCheck(struct Host *, uint); -static void RIOConCon(struct rio_info *, struct Host *, uint, uint, uint, uint, int); +static int RIOCheckIsolated(struct rio_info *, struct Host *, unsigned int); +static int RIOIsolate(struct rio_info *, struct Host *, unsigned int); +static int RIOCheck(struct Host *, unsigned int); +static void RIOConCon(struct rio_info *, struct Host *, unsigned int, unsigned int, unsigned int, unsigned int, int); /* ** Incoming on the ROUTE_RUP ** I wrote this while I was tired. Forgive me. */ -int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) +int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT * PacketP) { struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data; struct PktCmd_M *PktReplyP; @@ -104,10 +97,10 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) int ThisLink, ThisLinkMin, ThisLinkMax; int port; int Mod, Mod1, Mod2; - ushort RtaType; - uint RtaUniq; - uint ThisUnit, ThisUnit2; /* 2 ids to accommodate 16 port RTA */ - uint OldUnit, NewUnit, OldLink, NewLink; + unsigned short RtaType; + unsigned int RtaUniq; + unsigned int ThisUnit, ThisUnit2; /* 2 ids to accommodate 16 port RTA */ + unsigned int OldUnit, NewUnit, OldLink, NewLink; char *MyType, *MyName; int Lies; unsigned long flags; @@ -125,7 +118,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) ** from an RTA then we need to fill in the Mapping structure's ** Topology array for the unit. */ - if (Rup >= (ushort) MAX_RUP) { + if (Rup >= (unsigned short) MAX_RUP) { ThisUnit = HOST_ID; TopP = HostP->Topology; MyType = "Host"; @@ -151,7 +144,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) ** it won't lie about network interconnect, total disconnects ** and no-IDs. (or at least, it doesn't *matter* if it does) */ - if (readb(&PktCmdP->RouteTopology[ThisLink].Unit) > (ushort) MAX_RUP) + if (readb(&PktCmdP->RouteTopology[ThisLink].Unit) > (unsigned short) MAX_RUP) continue; for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) { @@ -168,7 +161,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) 'A' + readb(&PktCmdP->RouteTopology[0].Link), readb(&PktCmdP->RouteTopology[1].Unit), 'A' + readb(&PktCmdP->RouteTopology[1].Link), readb(&PktCmdP->RouteTopology[2].Unit), 'A' + readb(&PktCmdP->RouteTopology[2].Link), readb(&PktCmdP->RouteTopology[3].Unit), 'A' + readb(&PktCmdP->RouteTopology[3].Link)); - return TRUE; + return 1; } /* @@ -258,7 +251,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) RIOCheckIsolated(p, HostP, OldUnit); } } - return TRUE; + return 1; } /* @@ -266,7 +259,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) */ if (readb(&PktCmdP->Command) != ROUTE_REQUEST) { rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %p ROUTE_RUP\n", readb(&PktCmdP->Command), Rup, HostP); - return TRUE; + return 1; } RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24); @@ -292,10 +285,6 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) rio_dprintk(RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n", p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name); } - if (RtaUniq == 0xffffffff) { - ShowPacket(DBG_SPECIAL, PacketP); - } - /* ** try to unhook a command block from the command free list. */ @@ -320,7 +309,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) PktReplyP->Command = ROUTE_FOAD; HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7); RIOQueueCmdBlk(HostP, Rup, CmdBlkP); - return TRUE; + return 1; } /* @@ -354,7 +343,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) PktReplyP->Command = ROUTE_FOAD; HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7); RIOQueueCmdBlk(HostP, Rup, CmdBlkP); - return TRUE; + return 1; } /* @@ -447,7 +436,7 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) /* ** Job done, get on with the interrupts! */ - return TRUE; + return 1; } } /* @@ -491,28 +480,25 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) if (RtaType == TYPE_RTA16) { if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) { RIODefaultName(p, HostP, ThisUnit); - FillSlot(ThisUnit, ThisUnit2, RtaUniq, HostP); + rio_fill_host_slot(ThisUnit, ThisUnit2, RtaUniq, HostP); } } else { if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) { RIODefaultName(p, HostP, ThisUnit); - FillSlot(ThisUnit, 0, RtaUniq, HostP); + rio_fill_host_slot(ThisUnit, 0, RtaUniq, HostP); } } PktReplyP->Command = ROUTE_USED; HostP->Copy("RT_USED", PktReplyP->CommandText, 7); } RIOQueueCmdBlk(HostP, Rup, CmdBlkP); - return TRUE; + return 1; } -void RIOFixPhbs(p, HostP, unit) -struct rio_info *p; -struct Host *HostP; -uint unit; +void RIOFixPhbs(struct rio_info *p, struct Host *HostP, unsigned int unit) { - ushort link, port; + unsigned short link, port; struct Port *PortP; unsigned long flags; int PortN = HostP->Mapping[unit].SysPort; @@ -520,7 +506,7 @@ uint unit; rio_dprintk(RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN); if (PortN != -1) { - ushort dest_unit = HostP->Mapping[unit].ID2; + unsigned short dest_unit = HostP->Mapping[unit].ID2; /* ** Get the link number used for the 1st 8 phbs on this unit. @@ -530,9 +516,9 @@ uint unit; link = readw(&PortP->PhbP->link); for (port = 0; port < PORTS_PER_RTA; port++, PortN++) { - ushort dest_port = port + 8; - WORD *TxPktP; - PKT *Pkt; + unsigned short dest_port = port + 8; + u16 *TxPktP; + struct PKT *Pkt; PortP = p->RIOPortp[PortN]; @@ -569,12 +555,12 @@ uint unit; ** card. This needs to be translated into a 32 bit pointer ** so it can be accessed from the driver. */ - Pkt = (PKT *) RIO_PTR(HostP->Caddr, readw(TxPktP)); + Pkt = (struct PKT *) RIO_PTR(HostP->Caddr, readw(TxPktP)); /* ** If the packet is used, reset it. */ - Pkt = (PKT *) ((unsigned long) Pkt & ~PKT_IN_USE); + Pkt = (struct PKT *) ((unsigned long) Pkt & ~PKT_IN_USE); writeb(dest_unit, &Pkt->dest_unit); writeb(dest_port, &Pkt->dest_port); } @@ -603,10 +589,7 @@ uint unit; ** the world about it. This is done to ensure that the configurator ** only gets up-to-date information about what is going on. */ -static int RIOCheckIsolated(p, HostP, UnitId) -struct rio_info *p; -struct Host *HostP; -uint UnitId; +static int RIOCheckIsolated(struct rio_info *p, struct Host *HostP, unsigned int UnitId) { unsigned long flags; rio_spin_lock_irqsave(&HostP->HostLock, flags); @@ -628,12 +611,9 @@ uint UnitId; ** all the units attached to it. This will mean that the entire ** subnet will re-introduce itself. */ -static int RIOIsolate(p, HostP, UnitId) -struct rio_info *p; -struct Host *HostP; -uint UnitId; +static int RIOIsolate(struct rio_info *p, struct Host *HostP, unsigned int UnitId) { - uint link, unit; + unsigned int link, unit; UnitId--; /* this trick relies on the Unit Id being UNSIGNED! */ @@ -658,9 +638,7 @@ uint UnitId; return 1; } -static int RIOCheck(HostP, UnitId) -struct Host *HostP; -uint UnitId; +static int RIOCheck(struct Host *HostP, unsigned int UnitId) { unsigned char link; @@ -714,8 +692,7 @@ uint UnitId; ** Returns the type of unit (host, 16/8 port RTA) */ -uint GetUnitType(Uniq) -uint Uniq; +unsigned int GetUnitType(unsigned int Uniq) { switch ((Uniq >> 28) & 0xf) { case RIO_AT: @@ -736,8 +713,7 @@ uint Uniq; } } -int RIOSetChange(p) -struct rio_info *p; +int RIOSetChange(struct rio_info *p) { if (p->RIOQuickCheck != NOT_CHANGED) return (0); @@ -751,14 +727,13 @@ struct rio_info *p; return (0); } -static void RIOConCon(p, HostP, FromId, FromLink, ToId, ToLink, Change) -struct rio_info *p; -struct Host *HostP; -uint FromId; -uint FromLink; -uint ToId; -uint ToLink; -int Change; +static void RIOConCon(struct rio_info *p, + struct Host *HostP, + unsigned int FromId, + unsigned int FromLink, + unsigned int ToId, + unsigned int ToLink, + int Change) { char *FromName; char *FromType; @@ -912,7 +887,8 @@ static int RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit) ** This function scans the given host table for either one ** or two free unit ID's. */ -int RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint * pID1, uint * pID2) + +int RIOFindFreeID(struct rio_info *p, struct Host *HostP, unsigned int * pID1, unsigned int * pID2) { int unit, tempID; diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c index f1d50142b91d..d3abe0d37d64 100644 --- a/drivers/char/rio/riotable.c +++ b/drivers/char/rio/riotable.c @@ -53,15 +53,12 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2"; #include "linux_compat.h" #include "rio_linux.h" -#include "typdef.h" #include "pkt.h" #include "daemon.h" #include "rio.h" #include "riospace.h" -#include "top.h" #include "cmdpkt.h" #include "map.h" -#include "riotypes.h" #include "rup.h" #include "port.h" #include "riodrvr.h" @@ -74,17 +71,13 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2"; #include "unixrup.h" #include "board.h" #include "host.h" -#include "error.h" #include "phb.h" #include "link.h" #include "cmdblk.h" #include "route.h" -#include "control.h" #include "cirrus.h" #include "rioioctl.h" #include "param.h" -#include "list.h" -#include "sam.h" #include "protsts.h" /* @@ -136,7 +129,7 @@ int RIONewTable(struct rio_info *p) cptr = MapP->Name; /* (2) */ cptr[MAX_NAME_LEN - 1] = '\0'; if (cptr[0] == '\0') { - bcopy(MapP->RtaUniqueNum ? "RTA NN" : "HOST NN", MapP->Name, 8); + memcpy(MapP->Name, MapP->RtaUniqueNum ? "RTA NN" : "HOST NN", 8); MapP->Name[5] = '0' + Entry / 10; MapP->Name[6] = '0' + Entry % 10; } @@ -325,7 +318,7 @@ int RIONewTable(struct rio_info *p) */ if (MapP->ID == 0) { rio_dprintk(RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name); - bcopy(MapP->Name, HostP->Name, MAX_NAME_LEN); + memcpy(HostP->Name, MapP->Name, MAX_NAME_LEN); continue; } @@ -369,7 +362,7 @@ int RIONewTable(struct rio_info *p) } } if (!p->RIOHosts[Host].Name[0]) { - bcopy("HOST 1", p->RIOHosts[Host].Name, 7); + memcpy(p->RIOHosts[Host].Name, "HOST 1", 7); p->RIOHosts[Host].Name[5] += Host; } /* @@ -397,7 +390,7 @@ int RIONewTable(struct rio_info *p) */ if (Host1 != Host) { rio_dprintk(RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name); - bcopy("HOST 1", p->RIOHosts[Host].Name, 7); + memcpy(p->RIOHosts[Host].Name, "HOST 1", 7); p->RIOHosts[Host].Name[5] += Host1; } rio_dprintk(RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name); @@ -440,7 +433,7 @@ int RIOApel(struct rio_info *p) MapP->SysPort = NO_PORT; for (link = 0; link < LINKS_PER_UNIT; link++) MapP->Topology[link] = HostP->Topology[link]; - bcopy(HostP->Name, MapP->Name, MAX_NAME_LEN); + memcpy(MapP->Name, HostP->Name, MAX_NAME_LEN); for (Rup = 0; Rup < MAX_RUP; Rup++) { if (HostP->Mapping[Rup].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) { p->RIOConnectTable[Next] = HostP->Mapping[Rup]; @@ -539,10 +532,10 @@ int RIODeleteRta(struct rio_info *p, struct Map *MapP) ** the phb to port mappings in RIORouteRup. */ if (PortP->SecondBlock) { - ushort dest_unit = HostMapP->ID; - ushort dest_port = port - SysPort; + u16 dest_unit = HostMapP->ID; + u16 dest_port = port - SysPort; u16 *TxPktP; - PKT *Pkt; + struct PKT *Pkt; for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) { /* @@ -552,7 +545,7 @@ int RIODeleteRta(struct rio_info *p, struct Map *MapP) ** a 32 bit pointer so it can be ** accessed from the driver. */ - Pkt = (PKT *) RIO_PTR(HostP->Caddr, readw(&*TxPktP)); + Pkt = (struct PKT *) RIO_PTR(HostP->Caddr, readw(&*TxPktP)); rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", *TxPktP, Pkt->dest_unit, Pkt->dest_port, dest_unit, dest_port); writew(dest_unit, &Pkt->dest_unit); writew(dest_port, &Pkt->dest_port); @@ -600,7 +593,7 @@ int RIOAssignRta(struct rio_info *p, struct Map *MapP) rio_dprintk(RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort); - if ((MapP->ID != (ushort) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) { + if ((MapP->ID != (u16) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) { rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n"); p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; return -EINVAL; @@ -646,7 +639,7 @@ int RIOAssignRta(struct rio_info *p, struct Map *MapP) ** Now we have a host we need to allocate an ID ** if the entry does not already have one. */ - if (MapP->ID == (ushort) - 1) { + if (MapP->ID == (u16) - 1) { int nNewID; rio_dprintk(RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", MapP->Name); @@ -665,7 +658,7 @@ int RIOAssignRta(struct rio_info *p, struct Map *MapP) p->RIOError.Error = COULDNT_FIND_ENTRY; return -EBUSY; } - MapP->ID = (ushort) nNewID + 1; + MapP->ID = (u16) nNewID + 1; rio_dprintk(RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID); HostMapP = &p->RIOHosts[host].Mapping[nNewID]; HostMapP->RtaUniqueNum = MapP->RtaUniqueNum; @@ -706,7 +699,7 @@ int RIOAssignRta(struct rio_info *p, struct Map *MapP) */ HostMapP->SysPort = MapP->SysPort; if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) - CCOPY(MapP->Name, HostMapP->Name, MAX_NAME_LEN); + memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN); HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED; #ifdef NEED_TO_FIX RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID - 1]); @@ -743,10 +736,10 @@ int RIOAssignRta(struct rio_info *p, struct Map *MapP) int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP) { struct Port *PortP; - uint SubEnt; - uint HostPort; - uint SysPort; - ushort RtaType; + unsigned int SubEnt; + unsigned int HostPort; + unsigned int SysPort; + u16 RtaType; unsigned long flags; rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID); @@ -808,10 +801,10 @@ int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP) PortP->RupNum = HostMapP->ID - 1; if (HostMapP->Flags & RTA16_SECOND_SLOT) { PortP->ID2 = HostMapP->ID2 - 1; - PortP->SecondBlock = TRUE; + PortP->SecondBlock = 1; } else { PortP->ID2 = 0; - PortP->SecondBlock = FALSE; + PortP->SecondBlock = 0; } PortP->RtaUniqueNum = HostMapP->RtaUniqueNum; @@ -931,7 +924,7 @@ int RIOChangeName(struct rio_info *p, struct Map *MapP) return -ENXIO; } if (MapP->ID == 0) { - CCOPY(MapP->Name, p->RIOHosts[host].Name, MAX_NAME_LEN); + memcpy(p->RIOHosts[host].Name, MapP->Name, MAX_NAME_LEN); return 0; } @@ -941,7 +934,7 @@ int RIOChangeName(struct rio_info *p, struct Map *MapP) p->RIOError.Error = RTA_NUMBER_WRONG; return -ENXIO; } - CCOPY(MapP->Name, HostMapP->Name, MAX_NAME_LEN); + memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN); return 0; } } diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c index 0ca431b4c474..204267613c9c 100644 --- a/drivers/char/rio/riotty.c +++ b/drivers/char/rio/riotty.c @@ -56,15 +56,12 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3"; #include "linux_compat.h" #include "rio_linux.h" -#include "typdef.h" #include "pkt.h" #include "daemon.h" #include "rio.h" #include "riospace.h" -#include "top.h" #include "cmdpkt.h" #include "map.h" -#include "riotypes.h" #include "rup.h" #include "port.h" #include "riodrvr.h" @@ -77,58 +74,18 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3"; #include "unixrup.h" #include "board.h" #include "host.h" -#include "error.h" #include "phb.h" #include "link.h" #include "cmdblk.h" #include "route.h" -#include "control.h" #include "cirrus.h" #include "rioioctl.h" #include "param.h" -#include "list.h" -#include "sam.h" static void RIOClearUp(struct Port *PortP); -int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg); - - -extern int conv_vb[]; /* now defined in ttymgr.c */ -extern int conv_bv[]; /* now defined in ttymgr.c */ - -/* -** 16.09.1998 ARG - Fix to build riotty.k.o for Modular Kernel Support -** -** ep.def.h is necessary for Modular Kernel Support -** DO NOT place any kernel 'extern's after this line -** or this source file will not build riotty.k.o -*/ -#ifdef uLYNX -#include -#endif -#ifdef NEED_THIS2 -static struct old_sgttyb default_sg = { - B19200, B19200, /* input and output speed */ - 'H' - '@', /* erase char */ - -1, /* 2nd erase char */ - 'U' - '@', /* kill char */ - ECHO | CRMOD, /* mode */ - 'C' - '@', /* interrupt character */ - '\\' - '@', /* quit char */ - 'Q' - '@', /* start char */ - 'S' - '@', /* stop char */ - 'D' - '@', /* EOF */ - -1, /* brk */ - (LCRTBS | LCRTERA | LCRTKIL | LCTLECH), /* local mode word */ - 'Z' - '@', /* process stop */ - 'Y' - '@', /* delayed stop */ - 'R' - '@', /* reprint line */ - 'O' - '@', /* flush output */ - 'W' - '@', /* word erase */ - 'V' - '@' /* literal next char */ -}; -#endif +/* Below belongs in func.h */ +int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg); extern struct rio_info *p; @@ -137,7 +94,6 @@ extern struct rio_info *p; int riotopen(struct tty_struct *tty, struct file *filp) { unsigned int SysPort; - int Modem; int repeat_this = 250; struct Port *PortP; /* pointer to the port structure */ unsigned long flags; @@ -151,7 +107,6 @@ int riotopen(struct tty_struct *tty, struct file *filp) tty->driver_data = NULL; SysPort = rio_minor(tty); - Modem = rio_ismodem(tty); if (p->RIOFailed) { rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n"); @@ -159,7 +114,7 @@ int riotopen(struct tty_struct *tty, struct file *filp) return -ENXIO; } - rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (%s) (mapped:%d)\n", SysPort, Modem ? "Modem" : "tty", p->RIOPortp[SysPort]->Mapped); + rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (mapped:%d)\n", SysPort, p->RIOPortp[SysPort]->Mapped); /* ** Validate that we have received a legitimate request. @@ -305,15 +260,12 @@ int riotopen(struct tty_struct *tty, struct file *filp) /* PortP->gs.xmit_cnt = 0; */ rio_spin_unlock_irqrestore(&PortP->portSem, flags); -#ifdef NEED_THIS - ttyseth(PortP, tp, (struct old_sgttyb *) &default_sg); -#endif /* Someone explain to me why this delay/config is here. If I read the docs correctly the "open" command piggybacks the parameters immediately. -- REW */ - RIOParam(PortP, OPEN, Modem, OK_TO_SLEEP); /* Open the port */ + RIOParam(PortP, OPEN, 1, OK_TO_SLEEP); /* Open the port */ rio_spin_lock_irqsave(&PortP->portSem, flags); /* @@ -321,20 +273,6 @@ int riotopen(struct tty_struct *tty, struct file *filp) */ while (!(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted) { rio_dprintk(RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n", PortP->PortState); -/* -** 15.10.1998 ARG - ESIL 0759 -** (Part) fix for port being trashed when opened whilst RTA "disconnected" -** Take out the limited wait - now wait for ever or until user -** bangs us out. -** - if (repeat_this -- <= 0) { - rio_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish timed out.\n")); - RIOPreemptiveCmd(p, PortP, FCLOSE ); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return -EINTR; - } -** -*/ rio_spin_unlock_irqrestore(&PortP->portSem, flags); if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n"); @@ -354,74 +292,58 @@ int riotopen(struct tty_struct *tty, struct file *filp) } rio_dprintk(RIO_DEBUG_TTY, "PORT_ISOPEN found\n"); } -#ifdef MODEM_SUPPORT - if (Modem) { - rio_dprintk(RIO_DEBUG_TTY, "Modem - test for carrier\n"); + rio_dprintk(RIO_DEBUG_TTY, "Modem - test for carrier\n"); + /* + ** ACTION + ** insert test for carrier here. -- ??? + ** I already see that test here. What's the deal? -- REW + */ + if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) { + rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort); /* - ** ACTION - ** insert test for carrier here. -- ??? - ** I already see that test here. What's the deal? -- REW + tp->tm.c_state |= CARR_ON; + wakeup((caddr_t) &tp->tm.c_canq); */ - if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) { - rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort); + PortP->State |= RIO_CARR_ON; + wake_up_interruptible(&PortP->gs.open_wait); + } else { /* no carrier - wait for DCD */ /* - tp->tm.c_state |= CARR_ON; - wakeup((caddr_t) &tp->tm.c_canq); - */ - PortP->State |= RIO_CARR_ON; - wake_up_interruptible(&PortP->gs.open_wait); - } else { /* no carrier - wait for DCD */ - + while (!(PortP->gs.tty->termios->c_state & CARR_ON) && + !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted ) + */ + while (!(PortP->State & RIO_CARR_ON) && !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted) { + rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n", SysPort); /* - while (!(PortP->gs.tty->termios->c_state & CARR_ON) && - !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted ) + PortP->gs.tty->termios->c_state |= WOPEN; */ - while (!(PortP->State & RIO_CARR_ON) && !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted) { - - rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n", SysPort); + PortP->State |= RIO_WOPEN; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { + /* + ** ACTION: verify that this is a good thing + ** to do here. -- ??? + ** I think it's OK. -- REW + */ + rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort); + RIOPreemptiveCmd(p, PortP, FCLOSE); /* - PortP->gs.tty->termios->c_state |= WOPEN; + tp->tm.c_state &= ~WOPEN; */ - PortP->State |= RIO_WOPEN; + PortP->State &= ~RIO_WOPEN; rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) - { - /* - ** ACTION: verify that this is a good thing - ** to do here. -- ??? - ** I think it's OK. -- REW - */ - rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort); - RIOPreemptiveCmd(p, PortP, FCLOSE); - /* - tp->tm.c_state &= ~WOPEN; - */ - PortP->State &= ~RIO_WOPEN; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - func_exit(); - return -EINTR; - } + func_exit(); + return -EINTR; } - PortP->State &= ~RIO_WOPEN; } - if (p->RIOHalted) - goto bombout; - rio_dprintk(RIO_DEBUG_TTY, "Setting RIO_MOPEN\n"); - PortP->State |= RIO_MOPEN; - } else -#endif - { - /* - ** ACTION - ** Direct line open - force carrier (will probably mean - ** that sleeping Modem line fubar) - */ - PortP->State |= RIO_LOPEN; + PortP->State &= ~RIO_WOPEN; } + if (p->RIOHalted) + goto bombout; + rio_dprintk(RIO_DEBUG_TTY, "Setting RIO_MOPEN\n"); + PortP->State |= RIO_MOPEN; - if (p->RIOHalted) { + if (p->RIOHalted) goto bombout; - } rio_dprintk(RIO_DEBUG_TTY, "high level open done\n"); @@ -453,23 +375,21 @@ int riotclose(void *ptr) unsigned long end_time; struct tty_struct *tty; unsigned long flags; - int Modem; int rv = 0; rio_dprintk(RIO_DEBUG_TTY, "port close SysPort %d\n", PortP->PortNum); /* PortP = p->RIOPortp[SysPort]; */ - rio_dprintk(RIO_DEBUG_TTY, "Port is at address 0x%p\n", PortP); + rio_dprintk(RIO_DEBUG_TTY, "Port is at address %p\n", PortP); /* tp = PortP->TtyP; *//* Get tty */ tty = PortP->gs.tty; - rio_dprintk(RIO_DEBUG_TTY, "TTY is at address 0x%p\n", tty); + rio_dprintk(RIO_DEBUG_TTY, "TTY is at address %p\n", tty); if (PortP->gs.closing_wait) end_time = jiffies + PortP->gs.closing_wait; else end_time = jiffies + MAX_SCHEDULE_TIMEOUT; - Modem = rio_ismodem(tty); rio_spin_lock_irqsave(&PortP->portSem, flags); /* @@ -493,7 +413,7 @@ int riotclose(void *ptr) /* ** clear the open bits for this device */ - PortP->State &= (Modem ? ~RIO_MOPEN : ~RIO_LOPEN); + PortP->State &= ~RIO_MOPEN; PortP->State &= ~RIO_CARR_ON; PortP->ModemState &= ~MSVR1_CD; /* @@ -613,7 +533,7 @@ int riotclose(void *ptr) if (PortP->statsGather) PortP->closes++; - close_end: +close_end: /* XXX: Why would a "DELETED" flag be reset here? I'd have thought that a "deleted" flag means that the port was permanently gone, but here we can make it reappear by it @@ -629,8 +549,7 @@ int riotclose(void *ptr) -static void RIOClearUp(PortP) -struct Port *PortP; +static void RIOClearUp(struct Port *PortP) { rio_dprintk(RIO_DEBUG_TTY, "RIOHalted set\n"); PortP->Config = 0; /* Direct semaphore */ @@ -657,7 +576,7 @@ struct Port *PortP; */ int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg) { - PKT *PacketP; + struct PKT *PacketP; int retries = 20; /* at 10 per second -> 2 seconds */ unsigned long flags; diff --git a/drivers/char/rio/riotypes.h b/drivers/char/rio/riotypes.h deleted file mode 100644 index d07bd0aab5a2..000000000000 --- a/drivers/char/rio/riotypes.h +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* R I O T Y P E S - ******* ******* - **************************************************************************** - - Author : Jon Brawn - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _riotypes_h -#define _riotypes_h 1 - -#ifdef SCCS_LABELS -#ifndef lint -/* static char *_rio_riotypes_h_sccs = "@(#)riotypes.h 1.10"; */ -#endif -#endif - -typedef u16 char_ptr; -typedef u16 Channel_ptr; -typedef u16 FREE_LIST_ptr_ptr; -typedef u16 FREE_LIST_ptr; -typedef u16 LPB_ptr; -typedef u16 Process_ptr; -typedef u16 PHB_ptr; -typedef u16 PKT_ptr; -typedef u16 Q_BUF_ptr; -typedef u16 Q_BUF_ptr_ptr; -typedef u16 ROUTE_STR_ptr; -typedef u16 RUP_ptr; -typedef u16 short_ptr; -typedef u16 u_short_ptr; -typedef u16 ushort_ptr; - -#endif /* __riotypes__ */ - -/*********** end of file ***********/ diff --git a/drivers/char/rio/rom.h b/drivers/char/rio/rom.h deleted file mode 100644 index 58a7843625ff..000000000000 --- a/drivers/char/rio/rom.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* R O M - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _rom_h -#define _rom_h 1 - -#ifndef lint -#ifdef SCCS -static char *_rio_rom_h_sccs = "@(#)rom.h 1.1"; -#endif -#endif - -typedef struct ROM ROM; -struct ROM { - u_short slx; - char pcb_letter_rev; - char pcb_number_rev; - char serial[4]; - char year; - char week; -}; - -#endif - -#define HOST_ROM (ROM *) 0x7c00 -#define RTA_ROM (ROM *) 0x7801 -#define ROM_LENGTH 0x20 - -/*********** end of file ***********/ diff --git a/drivers/char/rio/sam.h b/drivers/char/rio/sam.h deleted file mode 100644 index 6f754e19015d..000000000000 --- a/drivers/char/rio/sam.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* S A M . H - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ -#ifndef _sam_h -#define _sam_h 1 - -#ifdef SCCS_LABELS -#ifndef lint -/* static char *_rio_sam_h_sccs = "@(#)sam.h 1.3"; */ -#endif -#endif - - -#define NUM_FREE_LIST_UNITS 500 - -#ifndef FALSE -#define FALSE (short) 0x00 -#endif -#ifndef TRUE -#define TRUE (short) !FALSE -#endif - -#define TX TRUE -#define RX FALSE - - -typedef struct FREE_LIST FREE_LIST; -struct FREE_LIST { - FREE_LIST_ptr next; - FREE_LIST_ptr prev; -}; - - -#endif -/*********** end of file ***********/ diff --git a/drivers/char/rio/space.h b/drivers/char/rio/space.h deleted file mode 100644 index 1f12690f9d1f..000000000000 --- a/drivers/char/rio/space.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. -** -** Module : space.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:19 -** Retrieved : 11/6/98 11:34:22 -** -** ident @(#)space.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_space_h__ -#define __rio_space_h__ - -#ifdef SCCS_LABELS -static char *_space_h_sccs_ = "@(#)space.h 1.2"; -#endif - -extern int rio_cntls; -extern int rio_bases[]; -extern int rio_limits[]; -extern int rio_vects[]; - -#endif /* __rio_space_h__ */ diff --git a/drivers/char/rio/top.h b/drivers/char/rio/top.h deleted file mode 100644 index fe60430cf099..000000000000 --- a/drivers/char/rio/top.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. -** -** Module : top.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:19 -** Retrieved : 11/6/98 11:34:22 -** -** ident @(#)top.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_top_h__ -#define __rio_top_h__ - -#ifdef SCCS_LABELS -static char *_top_h_sccs_ = "@(#)top.h 1.2"; -#endif - -/* -** Topology information -*/ -struct Top { - u8 Unit; - u8 Link; -}; - -#endif /* __rio_top_h__ */ diff --git a/drivers/char/rio/typdef.h b/drivers/char/rio/typdef.h deleted file mode 100644 index f40c1df7db1f..000000000000 --- a/drivers/char/rio/typdef.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. -** -** Module : typdef.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:20 -** Retrieved : 11/6/98 11:34:22 -** -** ident @(#)typdef.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_typdef_h__ -#define __rio_typdef_h__ - -/* -** IT IS REALLY, REALLY, IMPORTANT THAT BYTES ARE UNSIGNED! -** -** These types are ONLY to be used for refering to data structures -** on the RIO Host card! -*/ -typedef u8 BYTE; -typedef u16 WORD; -typedef u32 DWORD; -typedef u16 RIOP; - - -/* -** 27.01.199 ARG - mods to compile 'newutils' on LyxnOS - -** These #defines are for the benefit of the 'libfuncs' library -** only. They are not necessarily correct type mappings and -** are here only to make the source compile. -*/ -/* typedef unsigned int uint; */ -typedef unsigned long ulong_t; -typedef unsigned short ushort_t; -typedef unsigned char uchar_t; -typedef unsigned char queue_t; -typedef unsigned char mblk_t; -typedef unsigned long paddr_t; - -#define TPNULL ((ushort)(0x8000)) - - -/* -** RIO structures defined in other include files. -*/ -typedef struct PKT PKT; -typedef struct LPB LPB; -typedef struct RUP RUP; -typedef struct Port Port; -typedef struct DpRam DpRam; - -#endif /* __rio_typdef_h__ */ diff --git a/drivers/char/rio/unixrup.h b/drivers/char/rio/unixrup.h index a126c7cabac6..4306e01dbf01 100644 --- a/drivers/char/rio/unixrup.h +++ b/drivers/char/rio/unixrup.h @@ -45,9 +45,9 @@ struct UnixRup { struct CmdBlk *CmdsWaitingP; /* Commands waiting to be done */ struct CmdBlk *CmdPendingP; /* The command currently being sent */ struct RUP *RupP; /* the Rup to send it to */ - uint Id; /* Id number */ - uint BaseSysPort; /* SysPort of first tty on this RTA */ - uint ModTypes; /* Modules on this RTA */ + unsigned int Id; /* Id number */ + unsigned int BaseSysPort; /* SysPort of first tty on this RTA */ + unsigned int ModTypes; /* Modules on this RTA */ spinlock_t RupLock; /* Lock structure for MPX */ /* struct lockb RupLock; *//* Lock structure for MPX */ }; -- cgit v1.2.3-59-g8ed1b From 53813158012f4d9272e5ccdc005671e780a39931 Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Fri, 24 Mar 2006 18:10:34 +0100 Subject: tabify drivers/char/Makefile this trivial patch tabifies drivers/char/Makefile for readability. Signed-off-by: Jim Cromie Signed-off-by: Adrian Bunk --- drivers/char/Makefile | 87 ++++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 090d154098bb..b2a11245fa95 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -45,56 +45,57 @@ obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MMTIMER) += mmtimer.o -obj-$(CONFIG_VIOCONS) += viocons.o +obj-$(CONFIG_VIOCONS) += viocons.o obj-$(CONFIG_VIOTAPE) += viotape.o obj-$(CONFIG_HVCS) += hvcs.o obj-$(CONFIG_SGI_MBCS) += mbcs.o -obj-$(CONFIG_PRINTER) += lp.o -obj-$(CONFIG_TIPAR) += tipar.o - -obj-$(CONFIG_DTLK) += dtlk.o -obj-$(CONFIG_R3964) += n_r3964.o -obj-$(CONFIG_APPLICOM) += applicom.o -obj-$(CONFIG_SONYPI) += sonypi.o -obj-$(CONFIG_RTC) += rtc.o -obj-$(CONFIG_HPET) += hpet.o -obj-$(CONFIG_GEN_RTC) += genrtc.o -obj-$(CONFIG_EFI_RTC) += efirtc.o -obj-$(CONFIG_SGI_DS1286) += ds1286.o -obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o -obj-$(CONFIG_DS1302) += ds1302.o -obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o -obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o +obj-$(CONFIG_PRINTER) += lp.o +obj-$(CONFIG_TIPAR) += tipar.o + +obj-$(CONFIG_DTLK) += dtlk.o +obj-$(CONFIG_R3964) += n_r3964.o +obj-$(CONFIG_APPLICOM) += applicom.o +obj-$(CONFIG_SONYPI) += sonypi.o +obj-$(CONFIG_RTC) += rtc.o +obj-$(CONFIG_HPET) += hpet.o +obj-$(CONFIG_GEN_RTC) += genrtc.o +obj-$(CONFIG_EFI_RTC) += efirtc.o +obj-$(CONFIG_SGI_DS1286) += ds1286.o +obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o +obj-$(CONFIG_DS1302) += ds1302.o +obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o +obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o ifeq ($(CONFIG_GENERIC_NVRAM),y) - obj-$(CONFIG_NVRAM) += generic_nvram.o + obj-$(CONFIG_NVRAM) += generic_nvram.o else - obj-$(CONFIG_NVRAM) += nvram.o + obj-$(CONFIG_NVRAM) += nvram.o endif -obj-$(CONFIG_TOSHIBA) += toshiba.o -obj-$(CONFIG_I8K) += i8k.o -obj-$(CONFIG_DS1620) += ds1620.o -obj-$(CONFIG_HW_RANDOM) += hw_random.o -obj-$(CONFIG_FTAPE) += ftape/ -obj-$(CONFIG_COBALT_LCD) += lcd.o -obj-$(CONFIG_PPDEV) += ppdev.o -obj-$(CONFIG_NWBUTTON) += nwbutton.o -obj-$(CONFIG_NWFLASH) += nwflash.o -obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o -obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o -obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o -obj-$(CONFIG_TANBAC_TB0219) += tb0219.o -obj-$(CONFIG_TELCLOCK) += tlclk.o - -obj-$(CONFIG_WATCHDOG) += watchdog/ -obj-$(CONFIG_MWAVE) += mwave/ -obj-$(CONFIG_AGP) += agp/ -obj-$(CONFIG_DRM) += drm/ -obj-$(CONFIG_PCMCIA) += pcmcia/ -obj-$(CONFIG_IPMI_HANDLER) += ipmi/ - -obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o -obj-$(CONFIG_TCG_TPM) += tpm/ +obj-$(CONFIG_TOSHIBA) += toshiba.o +obj-$(CONFIG_I8K) += i8k.o +obj-$(CONFIG_DS1620) += ds1620.o +obj-$(CONFIG_HW_RANDOM) += hw_random.o +obj-$(CONFIG_FTAPE) += ftape/ +obj-$(CONFIG_COBALT_LCD) += lcd.o +obj-$(CONFIG_PPDEV) += ppdev.o +obj-$(CONFIG_NWBUTTON) += nwbutton.o +obj-$(CONFIG_NWFLASH) += nwflash.o +obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o +obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o +obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o +obj-$(CONFIG_TANBAC_TB0219) += tb0219.o +obj-$(CONFIG_TELCLOCK) += tlclk.o + +obj-$(CONFIG_WATCHDOG) += watchdog/ +obj-$(CONFIG_MWAVE) += mwave/ +obj-$(CONFIG_AGP) += agp/ +obj-$(CONFIG_DRM) += drm/ +obj-$(CONFIG_PCMCIA) += pcmcia/ +obj-$(CONFIG_IPMI_HANDLER) += ipmi/ + +obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o +obj-$(CONFIG_TCG_TPM) += tpm/ + # Files generated that shall be removed upon make clean clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c -- cgit v1.2.3-59-g8ed1b From d4b7780ea1d2e08410fcc9963a57254147ae577a Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Fri, 24 Mar 2006 11:50:17 +0200 Subject: [PATCH] AT91RM9200 Ethernet driver This patch adds support for the Ethernet controller integrated in the Atmel AT91RM9200 SoC processor. Changes since the previous submission (01/02/2006) are: - Make use of the clk.h clock infrastructure. - The multicast hash function is not crc32. [Patch by Pedro Perez] Signed-off-by: Andrew Victor Signed-off-by: Jeff Garzik --- drivers/net/arm/Kconfig | 8 + drivers/net/arm/Makefile | 1 + drivers/net/arm/at91_ether.c | 1110 +++++++++++++++++++++ drivers/net/arm/at91_ether.h | 101 ++ include/asm-arm/arch-at91rm9200/at91rm9200_emac.h | 138 +++ 5 files changed, 1358 insertions(+) create mode 100644 drivers/net/arm/at91_ether.c create mode 100644 drivers/net/arm/at91_ether.h create mode 100644 include/asm-arm/arch-at91rm9200/at91rm9200_emac.h (limited to 'drivers') diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig index 625184b65e38..77fe20dbea35 100644 --- a/drivers/net/arm/Kconfig +++ b/drivers/net/arm/Kconfig @@ -31,3 +31,11 @@ config ARM_ETHERH help If you have an Acorn system with one of these network cards, you should say Y to this option if you wish to use it with Linux. + +config ARM_AT91_ETHER + tristate "AT91RM9200 Ethernet support" + depends on NET_ETHERNET && ARM && ARCH_AT91RM9200 + select MII + help + If you wish to compile a kernel for the AT91RM9200 and enable + ethernet support, then you should always answer Y to this. diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile index bc263edf06a7..42c95b79c261 100644 --- a/drivers/net/arm/Makefile +++ b/drivers/net/arm/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o obj-$(CONFIG_ARM_ETHERH) += etherh.o obj-$(CONFIG_ARM_ETHER3) += ether3.o obj-$(CONFIG_ARM_ETHER1) += ether1.o +obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c new file mode 100644 index 000000000000..5503dc8a66e4 --- /dev/null +++ b/drivers/net/arm/at91_ether.c @@ -0,0 +1,1110 @@ +/* + * Ethernet driver for the Atmel AT91RM9200 (Thunder) + * + * Copyright (C) 2003 SAN People (Pty) Ltd + * + * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc. + * Initial version by Rick Bronson 01/11/2003 + * + * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker + * (Polaroid Corporation) + * + * Realtek RTL8201(B)L PHY support by Roman Avramenko + * + * 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 "at91_ether.h" + +#define DRV_NAME "at91_ether" +#define DRV_VERSION "1.0" + +static struct net_device *at91_dev; +static struct clk *ether_clk; + +/* ..................................................................... */ + +/* + * Read from a EMAC register. + */ +static inline unsigned long at91_emac_read(unsigned int reg) +{ + void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC; + + return __raw_readl(emac_base + reg); +} + +/* + * Write to a EMAC register. + */ +static inline void at91_emac_write(unsigned int reg, unsigned long value) +{ + void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC; + + __raw_writel(value, emac_base + reg); +} + +/* ........................... PHY INTERFACE ........................... */ + +/* + * Enable the MDIO bit in MAC control register + * When not called from an interrupt-handler, access to the PHY must be + * protected by a spinlock. + */ +static void enable_mdi(void) +{ + unsigned long ctl; + + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */ +} + +/* + * Disable the MDIO bit in the MAC control register + */ +static void disable_mdi(void) +{ + unsigned long ctl; + + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */ +} + +/* + * Wait until the PHY operation is complete. + */ +static inline void at91_phy_wait(void) { + unsigned long timeout = jiffies + 2; + + while (!(at91_emac_read(AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) { + if (time_after(jiffies, timeout)) { + printk("at91_ether: MIO timeout\n"); + break; + } + cpu_relax(); + } +} + +/* + * Write value to the a PHY register + * Note: MDI interface is assumed to already have been enabled. + */ +static void write_phy(unsigned char phy_addr, unsigned char address, unsigned int value) +{ + at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W + | ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA)); + + /* Wait until IDLE bit in Network Status register is cleared */ + at91_phy_wait(); +} + +/* + * Read value stored in a PHY register. + * Note: MDI interface is assumed to already have been enabled. + */ +static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int *value) +{ + at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R + | ((phy_addr & 0x1f) << 23) | (address << 18)); + + /* Wait until IDLE bit in Network Status register is cleared */ + at91_phy_wait(); + + *value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA; +} + +/* ........................... PHY MANAGEMENT .......................... */ + +/* + * Access the PHY to determine the current link speed and mode, and update the + * MAC accordingly. + * If no link or auto-negotiation is busy, then no changes are made. + */ +static void update_linkspeed(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int bmsr, bmcr, lpa, mac_cfg; + unsigned int speed, duplex; + + if (!mii_link_ok(&lp->mii)) { /* no link */ + netif_carrier_off(dev); + printk(KERN_INFO "%s: Link down.\n", dev->name); + return; + } + + /* Link up, or auto-negotiation still in progress */ + read_phy(lp->phy_address, MII_BMSR, &bmsr); + read_phy(lp->phy_address, MII_BMCR, &bmcr); + if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */ + if (!(bmsr & BMSR_ANEGCOMPLETE)) + return; /* Do nothing - another interrupt generated when negotiation complete */ + + read_phy(lp->phy_address, MII_LPA, &lpa); + if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100; + else speed = SPEED_10; + if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL; + else duplex = DUPLEX_HALF; + } else { + speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; + duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; + } + + /* Update the MAC */ + mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD); + if (speed == SPEED_100) { + if (duplex == DUPLEX_FULL) /* 100 Full Duplex */ + mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD; + else /* 100 Half Duplex */ + mac_cfg |= AT91_EMAC_SPD; + } else { + if (duplex == DUPLEX_FULL) /* 10 Full Duplex */ + mac_cfg |= AT91_EMAC_FD; + else {} /* 10 Half Duplex */ + } + 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"); + netif_carrier_on(dev); +} + +/* + * Handle interrupts from the PHY + */ +static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) dev_id; + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int phy; + + /* + * This hander is triggered on both edges, but the PHY chips expect + * level-triggering. We therefore have to check if the PHY actually has + * an IRQ pending. + */ + enable_mdi(); + if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { + read_phy(lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */ + if (!(phy & (1 << 0))) + goto done; + } + else if (lp->phy_type == MII_LXT971A_ID) { + read_phy(lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */ + if (!(phy & (1 << 2))) + goto done; + } + else if (lp->phy_type == MII_BCM5221_ID) { + read_phy(lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */ + if (!(phy & (1 << 0))) + goto done; + } + else if (lp->phy_type == MII_KS8721_ID) { + read_phy(lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */ + if (!(phy & ((1 << 2) | 1))) + goto done; + } + + update_linkspeed(dev); + +done: + disable_mdi(); + + return IRQ_HANDLED; +} + +/* + * Initialize and enable the PHY interrupt for link-state changes + */ +static void enable_phyirq(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + 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 */ + 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); + return; + } + + spin_lock_irq(&lp->lock); + enable_mdi(); + + if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ + read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); + dsintr = dsintr & ~0xf00; /* clear bits 8..11 */ + write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); + } + else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ + read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); + dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */ + write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); + } + else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ + dsintr = (1 << 15) | ( 1 << 14); + write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); + } + else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */ + dsintr = (1 << 10) | ( 1 << 8); + write_phy(lp->phy_address, MII_TPISTATUS, dsintr); + } + + disable_mdi(); + spin_unlock_irq(&lp->lock); +} + +/* + * Disable the PHY interrupt + */ +static void disable_phyirq(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + 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 */ + return; + + spin_lock_irq(&lp->lock); + enable_mdi(); + + if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ + read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); + dsintr = dsintr | 0xf00; /* set bits 8..11 */ + write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); + } + else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ + read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); + dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */ + write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); + } + else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ + read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr); + dsintr = ~(1 << 14); + write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); + } + else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */ + read_phy(lp->phy_address, MII_TPISTATUS, &dsintr); + dsintr = ~((1 << 10) | (1 << 8)); + write_phy(lp->phy_address, MII_TPISTATUS, dsintr); + } + + disable_mdi(); + spin_unlock_irq(&lp->lock); + + irq_number = lp->board_data.phy_irq_pin; + free_irq(irq_number, dev); /* Free interrupt handler */ +} + +/* + * Perform a software reset of the PHY. + */ +#if 0 +static void reset_phy(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned int bmcr; + + spin_lock_irq(&lp->lock); + enable_mdi(); + + /* Perform PHY reset */ + write_phy(lp->phy_address, MII_BMCR, BMCR_RESET); + + /* Wait until PHY reset is complete */ + do { + read_phy(lp->phy_address, MII_BMCR, &bmcr); + } while (!(bmcr && BMCR_RESET)); + + disable_mdi(); + spin_unlock_irq(&lp->lock); +} +#endif + +/* ......................... ADDRESS MANAGEMENT ........................ */ + +/* + * NOTE: Your bootloader must always set the MAC address correctly before + * booting into Linux. + * + * - It must always set the MAC address after reset, even if it doesn't + * happen to access the Ethernet while it's booting. Some versions of + * U-Boot on the AT91RM9200-DK do not do this. + * + * - Likewise it must store the addresses in the correct byte order. + * MicroMonitor (uMon) on the CSB337 does this incorrectly (and + * continues to do so, for bug-compatibility). + */ + +static short __init unpack_mac_address(struct net_device *dev, unsigned int hi, unsigned int lo) +{ + char addr[6]; + + if (machine_is_csb337()) { + addr[5] = (lo & 0xff); /* The CSB337 bootloader stores the MAC the wrong-way around */ + addr[4] = (lo & 0xff00) >> 8; + addr[3] = (lo & 0xff0000) >> 16; + addr[2] = (lo & 0xff000000) >> 24; + addr[1] = (hi & 0xff); + addr[0] = (hi & 0xff00) >> 8; + } + else { + addr[0] = (lo & 0xff); + addr[1] = (lo & 0xff00) >> 8; + addr[2] = (lo & 0xff0000) >> 16; + addr[3] = (lo & 0xff000000) >> 24; + addr[4] = (hi & 0xff); + addr[5] = (hi & 0xff00) >> 8; + } + + if (is_valid_ether_addr(addr)) { + memcpy(dev->dev_addr, &addr, 6); + return 1; + } + return 0; +} + +/* + * Set the ethernet MAC address in dev->dev_addr + */ +static void __init get_mac_address(struct net_device *dev) +{ + /* Check Specific-Address 1 */ + if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA1H), at91_emac_read(AT91_EMAC_SA1L))) + return; + /* Check Specific-Address 2 */ + if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA2H), at91_emac_read(AT91_EMAC_SA2L))) + return; + /* Check Specific-Address 3 */ + if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA3H), at91_emac_read(AT91_EMAC_SA3L))) + return; + /* Check Specific-Address 4 */ + if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA4H), at91_emac_read(AT91_EMAC_SA4L))) + return; + + printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n"); +} + +/* + * Program the hardware MAC address from dev->dev_addr. + */ +static void update_mac_address(struct net_device *dev) +{ + at91_emac_write(AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0])); + at91_emac_write(AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4])); + + at91_emac_write(AT91_EMAC_SA2L, 0); + at91_emac_write(AT91_EMAC_SA2H, 0); +} + +/* + * Store the new hardware address in dev->dev_addr, and update the MAC. + */ +static int set_mac_address(struct net_device *dev, void* addr) +{ + struct sockaddr *address = addr; + + if (!is_valid_ether_addr(address->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, address->sa_data, dev->addr_len); + update_mac_address(dev); + + printk("%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + + return 0; +} + +static int inline hash_bit_value(int bitnr, __u8 *addr) +{ + if (addr[bitnr / 8] & (1 << (bitnr % 8))) + return 1; + return 0; +} + +/* + * The hash address register is 64 bits long and takes up two locations in the memory map. + * The least significant bits are stored in EMAC_HSL and the most significant + * bits in EMAC_HSH. + * + * The unicast hash enable and the multicast hash enable bits in the network configuration + * register enable the reception of hash matched frames. The destination address is + * reduced to a 6 bit index into the 64 bit hash register using the following hash function. + * The hash function is an exclusive or of every sixth bit of the destination address. + * hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47] + * hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46] + * hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45] + * hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44] + * hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43] + * hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42] + * da[0] represents the least significant bit of the first byte received, that is, the multicast/ + * unicast indicator, and da[47] represents the most significant bit of the last byte + * received. + * If the hash index points to a bit that is set in the hash register then the frame will be + * matched according to whether the frame is multicast or unicast. + * A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and + * the hash index points to a bit set in the hash register. + * A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the + * hash index points to a bit set in the hash register. + * To receive all multicast frames, the hash register should be set with all ones and the + * multicast hash enable bit should be set in the network configuration register. + */ + +/* + * Return the hash index value for the specified address. + */ +static int hash_get_index(__u8 *addr) +{ + int i, j, bitval; + int hash_index = 0; + + for (j = 0; j < 6; j++) { + for (i = 0, bitval = 0; i < 8; i++) + bitval ^= hash_bit_value(i*6 + j, addr); + + hash_index |= (bitval << j); + } + + return hash_index; +} + +/* + * Add multicast addresses to the internal multicast-hash table. + */ +static void at91ether_sethashtable(struct net_device *dev) +{ + struct dev_mc_list *curr; + unsigned long mc_filter[2]; + unsigned int i, bitnr; + + mc_filter[0] = mc_filter[1] = 0; + + curr = dev->mc_list; + for (i = 0; i < dev->mc_count; i++, curr = curr->next) { + if (!curr) break; /* unexpected end of list */ + + bitnr = hash_get_index(curr->dmi_addr); + mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); + } + + at91_emac_write(AT91_EMAC_HSH, mc_filter[0]); + at91_emac_write(AT91_EMAC_HSL, mc_filter[1]); +} + +/* + * Enable/Disable promiscuous and multicast modes. + */ +static void at91ether_set_rx_mode(struct net_device *dev) +{ + unsigned long cfg; + + cfg = at91_emac_read(AT91_EMAC_CFG); + + if (dev->flags & IFF_PROMISC) /* Enable promiscuous mode */ + cfg |= AT91_EMAC_CAF; + else if (dev->flags & (~IFF_PROMISC)) /* Disable promiscuous mode */ + cfg &= ~AT91_EMAC_CAF; + + if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */ + at91_emac_write(AT91_EMAC_HSH, -1); + at91_emac_write(AT91_EMAC_HSL, -1); + cfg |= AT91_EMAC_MTI; + } else if (dev->mc_count > 0) { /* Enable specific multicasts */ + at91ether_sethashtable(dev); + cfg |= AT91_EMAC_MTI; + } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */ + at91_emac_write(AT91_EMAC_HSH, 0); + at91_emac_write(AT91_EMAC_HSL, 0); + cfg &= ~AT91_EMAC_MTI; + } + + 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; + + read_phy(phy_id, location, &value); + return value; +} + +static void mdio_write(struct net_device *dev, int phy_id, int location, int value) +{ + write_phy(phy_id, location, value); +} + +static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + int ret; + + spin_lock_irq(&lp->lock); + enable_mdi(); + + ret = mii_ethtool_gset(&lp->mii, cmd); + + disable_mdi(); + spin_unlock_irq(&lp->lock); + + if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */ + cmd->supported = SUPPORTED_FIBRE; + cmd->port = PORT_FIBRE; + } + + return ret; +} + +static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + int ret; + + spin_lock_irq(&lp->lock); + enable_mdi(); + + ret = mii_ethtool_sset(&lp->mii, cmd); + + disable_mdi(); + spin_unlock_irq(&lp->lock); + + return ret; +} + +static int at91ether_nwayreset(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + int ret; + + spin_lock_irq(&lp->lock); + enable_mdi(); + + ret = mii_nway_restart(&lp->mii); + + disable_mdi(); + spin_unlock_irq(&lp->lock); + + return ret; +} + +static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + strlcpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info)); +} + +static struct ethtool_ops at91ether_ethtool_ops = { + .get_settings = at91ether_get_settings, + .set_settings = at91ether_set_settings, + .get_drvinfo = at91ether_get_drvinfo, + .nway_reset = at91ether_nwayreset, + .get_link = ethtool_op_get_link, +}; + + +/* ................................ MAC ................................ */ + +/* + * Initialize and start the Receiver and Transmit subsystems + */ +static void at91ether_start(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + struct recv_desc_bufs *dlist, *dlist_phys; + int i; + unsigned long ctl; + + dlist = lp->dlist; + dlist_phys = lp->dlist_phys; + + for (i = 0; i < MAX_RX_DESCR; i++) { + dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0]; + dlist->descriptors[i].size = 0; + } + + /* Set the Wrap bit on the last descriptor */ + dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP; + + /* Reset buffer index */ + lp->rxBuffIndex = 0; + + /* Program address of descriptor list in Rx Buffer Queue register */ + at91_emac_write(AT91_EMAC_RBQP, (unsigned long) dlist_phys); + + /* Enable Receive and Transmit */ + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE); +} + +/* + * Open the ethernet interface + */ +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; + + clk_enable(ether_clk); /* Re-enable Peripheral clock */ + + /* Clear internal statistics */ + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_CSR); + + /* Update the MAC address (incase user has changed it) */ + update_mac_address(dev); + + /* Enable PHY interrupt */ + enable_phyirq(dev); + + /* Enable MAC interrupts */ + at91_emac_write(AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA + | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM + | AT91_EMAC_ROVR | AT91_EMAC_ABT); + + /* Determine current link speed */ + spin_lock_irq(&lp->lock); + enable_mdi(); + update_linkspeed(dev); + disable_mdi(); + spin_unlock_irq(&lp->lock); + + at91ether_start(dev); + netif_start_queue(dev); + return 0; +} + +/* + * Close the interface + */ +static int at91ether_close(struct net_device *dev) +{ + unsigned long ctl; + + /* Disable Receiver and Transmitter */ + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE)); + + /* Disable PHY interrupt */ + disable_phyirq(dev); + + /* Disable MAC interrupts */ + at91_emac_write(AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA + | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM + | AT91_EMAC_ROVR | AT91_EMAC_ABT); + + netif_stop_queue(dev); + + clk_disable(ether_clk); /* Disable Peripheral clock */ + + return 0; +} + +/* + * Transmit packet. + */ +static int at91ether_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + + if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) { + netif_stop_queue(dev); + + /* Store packet information (to free when Tx completed) */ + lp->skb = skb; + lp->skb_length = skb->len; + lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE); + lp->stats.tx_bytes += skb->len; + + /* Set address of the data in the Transmit Address register */ + at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr); + /* Set length of the packet in the Transmit Control register */ + at91_emac_write(AT91_EMAC_TCR, skb->len); + + dev->trans_start = jiffies; + } else { + printk(KERN_ERR "at91_ether.c: at91ether_tx() called, but device is busy!\n"); + return 1; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb) + on this skb, he also reports -ENETDOWN and printk's, so either + we free and return(0) or don't free and return 1 */ + } + + return 0; +} + +/* + * Update the current statistics from the internal statistics registers. + */ +static struct net_device_stats *at91ether_stats(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + int ale, lenerr, seqe, lcol, ecol; + + if (netif_running(dev)) { + lp->stats.rx_packets += at91_emac_read(AT91_EMAC_OK); /* Good frames received */ + ale = at91_emac_read(AT91_EMAC_ALE); + lp->stats.rx_frame_errors += ale; /* Alignment errors */ + lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF); + lp->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */ + seqe = at91_emac_read(AT91_EMAC_SEQE); + lp->stats.rx_crc_errors += seqe; /* CRC error */ + lp->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC); /* Receive buffer not available */ + lp->stats.rx_errors += (ale + lenerr + seqe + + at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB)); + + lp->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA); /* Frames successfully transmitted */ + lp->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE); /* Transmit FIFO underruns */ + lp->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE); /* Carrier Sense errors */ + lp->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */ + + lcol = at91_emac_read(AT91_EMAC_LCOL); + ecol = at91_emac_read(AT91_EMAC_ECOL); + lp->stats.tx_window_errors += lcol; /* Late collisions */ + lp->stats.tx_aborted_errors += ecol; /* 16 collisions */ + + lp->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol); + } + return &lp->stats; +} + +/* + * Extract received frame from buffer descriptors and sent to upper layers. + * (Called from interrupt context) + */ +static void at91ether_rx(struct net_device *dev) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + struct recv_desc_bufs *dlist; + unsigned char *p_recv; + struct sk_buff *skb; + unsigned int pktlen; + + dlist = lp->dlist; + while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) { + p_recv = dlist->recv_buf[lp->rxBuffIndex]; + pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */ + skb = alloc_skb(pktlen + 2, GFP_ATOMIC); + if (skb != NULL) { + skb_reserve(skb, 2); + memcpy(skb_put(skb, pktlen), p_recv, pktlen); + + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->len = pktlen; + dev->last_rx = jiffies; + lp->stats.rx_bytes += pktlen; + netif_rx(skb); + } + else { + lp->stats.rx_dropped += 1; + printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); + } + + if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST) + lp->stats.multicast++; + + dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */ + if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */ + lp->rxBuffIndex = 0; + else + lp->rxBuffIndex++; + } +} + +/* + * MAC interrupt handler + */ +static irqreturn_t at91ether_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) dev_id; + struct at91_private *lp = (struct at91_private *) dev->priv; + unsigned long intstatus, ctl; + + /* MAC Interrupt Status register indicates what interrupts are pending. + It is automatically cleared once read. */ + intstatus = at91_emac_read(AT91_EMAC_ISR); + + if (intstatus & AT91_EMAC_RCOM) /* Receive complete */ + at91ether_rx(dev); + + 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; + + if (lp->skb) { + dev_kfree_skb_irq(lp->skb); + lp->skb = NULL; + dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE); + } + netif_wake_queue(dev); + } + + /* Work-around for Errata #11 */ + if (intstatus & AT91_EMAC_RBNA) { + ctl = at91_emac_read(AT91_EMAC_CTL); + at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE); + at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE); + } + + if (intstatus & AT91_EMAC_ROVR) + printk("%s: ROVR error\n", dev->name); + + return IRQ_HANDLED; +} + +/* + * Initialize the ethernet interface + */ +static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address, struct platform_device *pdev) +{ + struct at91_eth_data *board_data = pdev->dev.platform_data; + struct net_device *dev; + struct at91_private *lp; + unsigned int val; + int res; + + if (at91_dev) /* already initialized */ + return 0; + + dev = alloc_etherdev(sizeof(struct at91_private)); + if (!dev) + return -ENOMEM; + + dev->base_addr = AT91_VA_BASE_EMAC; + dev->irq = AT91_ID_EMAC; + SET_MODULE_OWNER(dev); + + /* Install the interrupt handler */ + if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) { + free_netdev(dev); + return -EBUSY; + } + + /* Allocate memory for DMA Receive descriptors */ + lp = (struct at91_private *)dev->priv; + lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL); + if (lp->dlist == NULL) { + free_irq(dev->irq, dev); + free_netdev(dev); + return -ENOMEM; + } + lp->board_data = *board_data; + platform_set_drvdata(pdev, dev); + + spin_lock_init(&lp->lock); + + ether_setup(dev); + dev->open = at91ether_open; + dev->stop = at91ether_close; + dev->hard_start_xmit = at91ether_tx; + dev->get_stats = at91ether_stats; + dev->set_multicast_list = at91ether_set_rx_mode; + dev->set_mac_address = set_mac_address; + dev->ethtool_ops = &at91ether_ethtool_ops; + + SET_NETDEV_DEV(dev, &pdev->dev); + + get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */ + update_mac_address(dev); /* Program ethernet address into MAC */ + + at91_emac_write(AT91_EMAC_CTL, 0); + + if (lp->board_data.is_rmii) + at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII); + else + at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG); + + /* Perform PHY-specific initialization */ + spin_lock_irq(&lp->lock); + enable_mdi(); + if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { + read_phy(phy_address, MII_DSCR_REG, &val); + if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */ + lp->phy_media = PORT_FIBRE; + } else if (machine_is_csb337()) { + /* mix link activity status into LED2 link state */ + write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22); + } + disable_mdi(); + spin_unlock_irq(&lp->lock); + + lp->mii.dev = dev; /* Support for ethtool */ + lp->mii.mdio_read = mdio_read; + lp->mii.mdio_write = mdio_write; + + lp->phy_type = phy_type; /* Type of PHY connected */ + lp->phy_address = phy_address; /* MDI address of PHY */ + + /* Register the network interface */ + res = register_netdev(dev); + if (res) { + free_irq(dev->irq, dev); + free_netdev(dev); + dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); + return res; + } + at91_dev = dev; + + /* Determine current link speed */ + spin_lock_irq(&lp->lock); + enable_mdi(); + update_linkspeed(dev); + disable_mdi(); + spin_unlock_irq(&lp->lock); + netif_carrier_off(dev); /* will be enabled in open() */ + + /* 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, + at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-", + at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex", + 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)"); + else if (phy_type == MII_LXT971A_ID) + printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name); + else if (phy_type == MII_RTL8201_ID) + printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name); + else if (phy_type == MII_BCM5221_ID) + printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name); + else if (phy_type == MII_DP83847_ID) + printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name); + else if (phy_type == MII_AC101L_ID) + printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name); + else if (phy_type == MII_KS8721_ID) + printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name); + + return 0; +} + +/* + * Detect MAC and PHY and perform initialization + */ +static int __init at91ether_probe(struct platform_device *pdev) +{ + unsigned int phyid1, phyid2; + int detected = -1; + unsigned long phy_id; + unsigned short phy_address = 0; + + ether_clk = clk_get(&pdev->dev, "ether_clk"); + if (!ether_clk) { + printk(KERN_ERR "at91_ether: no clock defined\n"); + return -ENODEV; + } + clk_enable(ether_clk); /* Enable Peripheral clock */ + + while ((detected != 0) && (phy_address < 32)) { + /* Read the PHY ID registers */ + enable_mdi(); + read_phy(phy_address, MII_PHYSID1, &phyid1); + read_phy(phy_address, MII_PHYSID2, &phyid2); + disable_mdi(); + + phy_id = (phyid1 << 16) | (phyid2 & 0xfff0); + switch (phy_id) { + case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */ + case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */ + case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */ + case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */ + case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */ + 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); + break; + } + + phy_address++; + } + + clk_disable(ether_clk); /* Disable Peripheral clock */ + + return detected; +} + +static int __devexit at91ether_remove(struct platform_device *pdev) +{ + struct at91_private *lp = (struct at91_private *) at91_dev->priv; + + 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); + + free_netdev(at91_dev); + at91_dev = NULL; + return 0; +} + +static struct platform_driver at91ether_driver = { + .probe = at91ether_probe, + .remove = __devexit_p(at91ether_remove), + /* FIXME: support suspend and resume */ + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init at91ether_init(void) +{ + return platform_driver_register(&at91ether_driver); +} + +static void __exit at91ether_exit(void) +{ + platform_driver_unregister(&at91ether_driver); +} + +module_init(at91ether_init) +module_exit(at91ether_exit) + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver"); +MODULE_AUTHOR("Andrew Victor"); diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/arm/at91_ether.h new file mode 100644 index 000000000000..9885735c9c8a --- /dev/null +++ b/drivers/net/arm/at91_ether.h @@ -0,0 +1,101 @@ +/* + * Ethernet driver for the Atmel AT91RM9200 (Thunder) + * + * Copyright (C) SAN People (Pty) Ltd + * + * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc. + * Initial version by Rick Bronson. + * + * 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 AT91_ETHERNET +#define AT91_ETHERNET + + +/* Davicom 9161 PHY */ +#define MII_DM9161_ID 0x0181b880 +#define MII_DM9161A_ID 0x0181b8a0 + +/* Davicom specific registers */ +#define MII_DSCR_REG 16 +#define MII_DSCSR_REG 17 +#define MII_DSINTR_REG 21 + +/* Intel LXT971A PHY */ +#define MII_LXT971A_ID 0x001378E0 + +/* Intel specific registers */ +#define MII_ISINTE_REG 18 +#define MII_ISINTS_REG 19 +#define MII_LEDCTRL_REG 20 + +/* Realtek RTL8201 PHY */ +#define MII_RTL8201_ID 0x00008200 + +/* Broadcom BCM5221 PHY */ +#define MII_BCM5221_ID 0x004061e0 + +/* Broadcom specific registers */ +#define MII_BCMINTR_REG 26 + +/* National Semiconductor DP83847 */ +#define MII_DP83847_ID 0x20005c30 + +/* Altima AC101L PHY */ +#define MII_AC101L_ID 0x00225520 + +/* Micrel KS8721 PHY */ +#define MII_KS8721_ID 0x00221610 + +/* ........................................................................ */ + +#define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */ +#define MAX_RX_DESCR 9 /* max number of receive buffers */ + +#define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */ +#define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */ + +#define EMAC_BROADCAST 0x80000000 /* broadcast address */ +#define EMAC_MULTICAST 0x40000000 /* multicast address */ +#define EMAC_UNICAST 0x20000000 /* unicast address */ + +struct rbf_t +{ + unsigned int addr; + unsigned long size; +}; + +struct recv_desc_bufs +{ + struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */ + char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */ +}; + +struct at91_private +{ + struct net_device_stats stats; + struct mii_if_info mii; /* ethtool support */ + struct at91_eth_data board_data; /* board-specific configuration */ + + /* PHY */ + unsigned long phy_type; /* type of PHY (PHY_ID) */ + spinlock_t lock; /* lock for MDI interface */ + short phy_media; /* media interface type */ + unsigned short phy_address; /* 5-bit MDI address of PHY (0..31) */ + + /* Transmit */ + struct sk_buff *skb; /* holds skb until xmit interrupt completes */ + dma_addr_t skb_physaddr; /* phys addr from pci_map_single */ + int skb_length; /* saved skb length for pci_unmap_single */ + + /* Receive */ + int rxBuffIndex; /* index into receive descriptor list */ + struct recv_desc_bufs *dlist; /* descriptor list address */ + struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */ +}; + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_emac.h b/include/asm-arm/arch-at91rm9200/at91rm9200_emac.h new file mode 100644 index 000000000000..fbc091e61e2f --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_emac.h @@ -0,0 +1,138 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200_emac.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Ethernet MAC 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_EMAC_H +#define AT91RM9200_EMAC_H + +#define AT91_EMAC_CTL 0x00 /* Control Register */ +#define AT91_EMAC_LB (1 << 0) /* Loopback */ +#define AT91_EMAC_LBL (1 << 1) /* Loopback Local */ +#define AT91_EMAC_RE (1 << 2) /* Receive Enable */ +#define AT91_EMAC_TE (1 << 3) /* Transmit Enable */ +#define AT91_EMAC_MPE (1 << 4) /* Management Port Enable */ +#define AT91_EMAC_CSR (1 << 5) /* Clear Statistics Registers */ +#define AT91_EMAC_INCSTAT (1 << 6) /* Increment Statistics Registers */ +#define AT91_EMAC_WES (1 << 7) /* Write Enable for Statistics Registers */ +#define AT91_EMAC_BP (1 << 8) /* Back Pressure */ + +#define AT91_EMAC_CFG 0x04 /* Configuration Register */ +#define AT91_EMAC_SPD (1 << 0) /* Speed */ +#define AT91_EMAC_FD (1 << 1) /* Full Duplex */ +#define AT91_EMAC_BR (1 << 2) /* Bit Rate */ +#define AT91_EMAC_CAF (1 << 4) /* Copy All Frames */ +#define AT91_EMAC_NBC (1 << 5) /* No Broadcast */ +#define AT91_EMAC_MTI (1 << 6) /* Multicast Hash Enable */ +#define AT91_EMAC_UNI (1 << 7) /* Unicast Hash Enable */ +#define AT91_EMAC_BIG (1 << 8) /* Receive 1522 Bytes */ +#define AT91_EMAC_EAE (1 << 9) /* External Address Match Enable */ +#define AT91_EMAC_CLK (3 << 10) /* MDC Clock Divisor */ +#define AT91_EMAC_CLK_DIV8 (0 << 10) +#define AT91_EMAC_CLK_DIV16 (1 << 10) +#define AT91_EMAC_CLK_DIV32 (2 << 10) +#define AT91_EMAC_CLK_DIV64 (3 << 10) +#define AT91_EMAC_RTY (1 << 12) /* Retry Test */ +#define AT91_EMAC_RMII (1 << 13) /* Reduce MII (RMII) */ + +#define AT91_EMAC_SR 0x08 /* Status Register */ +#define AT91_EMAC_SR_LINK (1 << 0) /* Link */ +#define AT91_EMAC_SR_MDIO (1 << 1) /* MDIO pin */ +#define AT91_EMAC_SR_IDLE (1 << 2) /* PHY idle */ + +#define AT91_EMAC_TAR 0x0c /* Transmit Address Register */ + +#define AT91_EMAC_TCR 0x10 /* Transmit Control Register */ +#define AT91_EMAC_LEN (0x7ff << 0) /* Transmit Frame Length */ +#define AT91_EMAC_NCRC (1 << 15) /* No CRC */ + +#define AT91_EMAC_TSR 0x14 /* Transmit Status Register */ +#define AT91_EMAC_TSR_OVR (1 << 0) /* Transmit Buffer Overrun */ +#define AT91_EMAC_TSR_COL (1 << 1) /* Collision Occurred */ +#define AT91_EMAC_TSR_RLE (1 << 2) /* Retry Limit Exceeded */ +#define AT91_EMAC_TSR_IDLE (1 << 3) /* Transmitter Idle */ +#define AT91_EMAC_TSR_BNQ (1 << 4) /* Transmit Buffer not Queued */ +#define AT91_EMAC_TSR_COMP (1 << 5) /* Transmit Complete */ +#define AT91_EMAC_TSR_UND (1 << 6) /* Transmit Underrun */ + +#define AT91_EMAC_RBQP 0x18 /* Receive Buffer Queue Pointer */ + +#define AT91_EMAC_RSR 0x20 /* Receive Status Register */ +#define AT91_EMAC_RSR_BNA (1 << 0) /* Buffer Not Available */ +#define AT91_EMAC_RSR_REC (1 << 1) /* Frame Received */ +#define AT91_EMAC_RSR_OVR (1 << 2) /* RX Overrun */ + +#define AT91_EMAC_ISR 0x24 /* Interrupt Status Register */ +#define AT91_EMAC_DONE (1 << 0) /* Management Done */ +#define AT91_EMAC_RCOM (1 << 1) /* Receive Complete */ +#define AT91_EMAC_RBNA (1 << 2) /* Receive Buffer Not Available */ +#define AT91_EMAC_TOVR (1 << 3) /* Transmit Buffer Overrun */ +#define AT91_EMAC_TUND (1 << 4) /* Transmit Buffer Underrun */ +#define AT91_EMAC_RTRY (1 << 5) /* Retry Limit */ +#define AT91_EMAC_TBRE (1 << 6) /* Transmit Buffer Register Empty */ +#define AT91_EMAC_TCOM (1 << 7) /* Transmit Complete */ +#define AT91_EMAC_TIDLE (1 << 8) /* Transmit Idle */ +#define AT91_EMAC_LINK (1 << 9) /* Link */ +#define AT91_EMAC_ROVR (1 << 10) /* RX Overrun */ +#define AT91_EMAC_ABT (1 << 11) /* Abort */ + +#define AT91_EMAC_IER 0x28 /* Interrupt Enable Register */ +#define AT91_EMAC_IDR 0x2c /* Interrupt Disable Register */ +#define AT91_EMAC_IMR 0x30 /* Interrupt Mask Register */ + +#define AT91_EMAC_MAN 0x34 /* PHY Maintenance Register */ +#define AT91_EMAC_DATA (0xffff << 0) /* MDIO Data */ +#define AT91_EMAC_REGA (0x1f << 18) /* MDIO Register */ +#define AT91_EMAC_PHYA (0x1f << 23) /* MDIO PHY Address */ +#define AT91_EMAC_RW (3 << 28) /* Read/Write operation */ +#define AT91_EMAC_RW_W (1 << 28) +#define AT91_EMAC_RW_R (2 << 28) +#define AT91_EMAC_MAN_802_3 0x40020000 /* IEEE 802.3 value */ + +/* + * Statistics Registers. + */ +#define AT91_EMAC_FRA 0x40 /* Frames Transmitted OK */ +#define AT91_EMAC_SCOL 0x44 /* Single Collision Frame */ +#define AT91_EMAC_MCOL 0x48 /* Multiple Collision Frame */ +#define AT91_EMAC_OK 0x4c /* Frames Received OK */ +#define AT91_EMAC_SEQE 0x50 /* Frame Check Sequence Error */ +#define AT91_EMAC_ALE 0x54 /* Alignmemt Error */ +#define AT91_EMAC_DTE 0x58 /* Deffered Transmission Frame */ +#define AT91_EMAC_LCOL 0x5c /* Late Collision */ +#define AT91_EMAC_ECOL 0x60 /* Excessive Collision */ +#define AT91_EMAC_TUE 0x64 /* Transmit Underrun Error */ +#define AT91_EMAC_CSE 0x68 /* Carrier Sense Error */ +#define AT91_EMAC_DRFC 0x6c /* Discard RX Frame */ +#define AT91_EMAC_ROV 0x70 /* Receive Overrun */ +#define AT91_EMAC_CDE 0x74 /* Code Error */ +#define AT91_EMAC_ELR 0x78 /* Excessive Length Error */ +#define AT91_EMAC_RJB 0x7c /* Receive Jabber */ +#define AT91_EMAC_USF 0x80 /* Undersize Frame */ +#define AT91_EMAC_SQEE 0x84 /* SQE Test Error */ + +/* + * Address Registers. + */ +#define AT91_EMAC_HSL 0x90 /* Hash Address Low [31:0] */ +#define AT91_EMAC_HSH 0x94 /* Hash Address High [63:32] */ +#define AT91_EMAC_SA1L 0x98 /* Specific Address 1 Low, bytes 0-3 */ +#define AT91_EMAC_SA1H 0x9c /* Specific Address 1 High, bytes 4-5 */ +#define AT91_EMAC_SA2L 0xa0 /* Specific Address 2 Low, bytes 0-3 */ +#define AT91_EMAC_SA2H 0xa4 /* Specific Address 2 High, bytes 4-5 */ +#define AT91_EMAC_SA3L 0xa8 /* Specific Address 3 Low, bytes 0-3 */ +#define AT91_EMAC_SA3H 0xac /* Specific Address 3 High, bytes 4-5 */ +#define AT91_EMAC_SA4L 0xb0 /* Specific Address 4 Low, bytes 0-3 */ +#define AT91_EMAC_SA4H 0xb4 /* Specific Address 4 High, bytes 4-5 */ + +#endif -- cgit v1.2.3-59-g8ed1b From b2fd16b4ff2508ac16ae994f4bcd941f97754c00 Mon Sep 17 00:00:00 2001 From: Horms Date: Thu, 23 Mar 2006 16:36:28 +0900 Subject: [PATCH] net: ne2k.c won't compile if pci_clone_list is const net: ne2k.c won't compile if pci_clone_list is const f71e130966ba429dbd24be08ddbcdf263df9a5ad which (amongst other things) made pci_clone_list in ne2k-pci.c const causes the following compile error. This patch reverses that portion of that changeset drivers/net/ne2k-pci.c:123: error: pci_clone_list causes a section type conflict ~/ gcc --version gcc (GCC) 4.0.3 (Debian 4.0.3-1) ~/ dpkg gcc-4.0 | grep Version Version: 4.0.3-1 Signed-Off-By: Horms --- drivers/net/ne2k-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index e3ebb5803b02..d11821dd86ed 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -117,7 +117,7 @@ enum ne2k_pci_chipsets { }; -static const struct { +static struct { char *name; int flags; } pci_clone_list[] __devinitdata = { -- cgit v1.2.3-59-g8ed1b From c30fe7f73194650148b58ee80908c1bc38246397 Mon Sep 17 00:00:00 2001 From: Uwe Zeisberger Date: Fri, 24 Mar 2006 18:23:14 +0100 Subject: fix typos "wich" -> "which" Signed-off-by: Uwe Zeisberger Signed-off-by: Adrian Bunk --- Documentation/filesystems/proc.txt | 6 +++--- Documentation/networking/packet_mmap.txt | 10 +++++----- drivers/acpi/Kconfig | 3 ++- drivers/isdn/i4l/isdn_x25iface.c | 2 +- drivers/serial/mpc52xx_uart.c | 2 +- drivers/usb/serial/option.c | 2 +- drivers/video/sstfb.c | 2 +- drivers/w1/masters/matrox_w1.c | 2 +- fs/befs/datastream.c | 2 +- scripts/Makefile.modpost | 2 +- 10 files changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 944cf109a6f5..99902ae6804e 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -121,7 +121,7 @@ Table 1-1: Process specific entries in /proc .............................................................................. File Content cmdline Command line arguments - cpu Current and last cpu in wich it was executed (2.4)(smp) + cpu Current and last cpu in which it was executed (2.4)(smp) cwd Link to the current working directory environ Values of environment variables exe Link to the executable of this process @@ -309,13 +309,13 @@ is the same by default: > cat /proc/irq/0/smp_affinity ffffffff -It's a bitmask, in wich you can specify wich CPUs can handle the IRQ, you can +It's a bitmask, in which you can specify which CPUs can handle the IRQ, you can set it by doing: > echo 1 > /proc/irq/prof_cpu_mask This means that only the first CPU will handle the IRQ, but you can also echo 5 -wich means that only the first and fourth CPU can handle the IRQ. +which means that only the first and fourth CPU can handle the IRQ. The way IRQs are routed is handled by the IO-APIC, and it's Round Robin between all the CPUs which are allowed to handle it. As usual the kernel has diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt index 8d4cf78258e4..4fc8e9874320 100644 --- a/Documentation/networking/packet_mmap.txt +++ b/Documentation/networking/packet_mmap.txt @@ -40,7 +40,7 @@ network interface card supports some sort of interrupt load mitigation or + How to use CONFIG_PACKET_MMAP -------------------------------------------------------------------------------- -From the user standpoint, you should use the higher level libpcap library, wich +From the user standpoint, you should use the higher level libpcap library, which is a de facto standard, portable across nearly all operating systems including Win32. @@ -217,8 +217,8 @@ called pg_vec, its size limits the number of blocks that can be allocated. kmalloc allocates any number of bytes of phisically contiguous memory from a pool of pre-determined sizes. This pool of memory is mantained by the slab -allocator wich is at the end the responsible for doing the allocation and -hence wich imposes the maximum memory that kmalloc can allocate. +allocator which is at the end the responsible for doing the allocation and +hence which imposes the maximum memory that kmalloc can allocate. In a 2.4/2.6 kernel and the i386 architecture, the limit is 131072 bytes. The predetermined sizes that kmalloc uses can be checked in the "size-" @@ -254,7 +254,7 @@ and, the number of frames be * / -Suposse the following parameters, wich apply for 2.6 kernel and an +Suposse the following parameters, which apply for 2.6 kernel and an i386 architecture: = 131072 bytes @@ -360,7 +360,7 @@ TP_STATUS_LOSING : indicates there were packet drops from last time statistics where checked with getsockopt() and the PACKET_STATISTICS option. -TP_STATUS_CSUMNOTREADY: currently it's used for outgoing IP packets wich +TP_STATUS_CSUMNOTREADY: currently it's used for outgoing IP packets which it's checksum will be done in hardware. So while reading the packet we should not try to check the checksum. diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 82710ae39228..5cb96300eb0f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -256,7 +256,8 @@ config ACPI_CUSTOM_DSDT_FILE depends on ACPI_CUSTOM_DSDT default "" help - Enter the full path name to the file wich includes the AmlCode declaration. + Enter the full path name to the file which includes the AmlCode + declaration. config ACPI_BLACKLIST_YEAR int "Disable ACPI for systems before Jan 1st this year" if X86_32 diff --git a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c index edf14a2aa3c8..743ac4077f35 100644 --- a/drivers/isdn/i4l/isdn_x25iface.c +++ b/drivers/isdn/i4l/isdn_x25iface.c @@ -7,7 +7,7 @@ * * stuff needed to support the Linux X.25 PLP code on top of devices that * can provide a lab_b service using the concap_proto mechanism. - * This module supports a network interface wich provides lapb_sematics + * This module supports a network interface which provides lapb_sematics * -- as defined in Documentation/networking/x25-iface.txt -- to * the upper layer and assumes that the lower layer provides a reliable * data link service by means of the concap_device_ops callbacks. diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 928e6cf12dca..6459edc7f5c5 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -40,7 +40,7 @@ * and so on). So the PSC1 is mapped to /dev/ttyPSC0, PSC2 to /dev/ttyPSC1 and * so on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly * fpr the console code : without this 1:1 mapping, at early boot time, when we - * are parsing the kernel args console=ttyPSC?, we wouldn't know wich PSC it + * are parsing the kernel args console=ttyPSC?, we wouldn't know which PSC it * will be mapped to. */ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index a8455c9e79dd..495db5755df9 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -102,7 +102,7 @@ static struct usb_driver option_driver = { .no_dynamic_id = 1, }; -/* The card has three separate interfaces, wich the serial driver +/* The card has three separate interfaces, which the serial driver * recognizes separately, thus num_port=1. */ static struct usb_serial_driver option_3port_device = { diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 99921df35474..8c1a8b5135c6 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -32,7 +32,7 @@ -TODO: at one time or another test that the mode is acceptable by the monitor -ASK: Can I choose different ordering for the color bitfields (rgba argb ...) - wich one should i use ? is there any preferred one ? It seems ARGB is + which one should i use ? is there any preferred one ? It seems ARGB is the one ... -TODO: in set_var check the validity of timings (hsync vsync)... -TODO: check and recheck the use of sst_wait_idle : we don't flush the fifo via diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c index 591809cbbb97..2788b8ca9bb1 100644 --- a/drivers/w1/masters/matrox_w1.c +++ b/drivers/w1/masters/matrox_w1.c @@ -98,7 +98,7 @@ static void matrox_w1_write_ddc_bit(void *, u8); * * Using tristate pins, since i can't find any open-drain pin in whole motherboard. * Unfortunately we can't connect to Intel's 82801xx IO controller - * since we don't know motherboard schema, wich has pretty unused(may be not) GPIO. + * since we don't know motherboard schema, which has pretty unused(may be not) GPIO. * * I've heard that PIIX also has open drain pin. * diff --git a/fs/befs/datastream.c b/fs/befs/datastream.c index 785f6b2d5d10..b7d6b920f65f 100644 --- a/fs/befs/datastream.c +++ b/fs/befs/datastream.c @@ -118,7 +118,7 @@ befs_fblock2brun(struct super_block *sb, befs_data_stream * data, * befs_read_lsmylink - read long symlink from datastream. * @sb: Filesystem superblock * @ds: Datastrem to read from - * @buf: Buffer in wich to place long symlink data + * @buf: Buffer in which to place long symlink data * @len: Length of the long symlink in bytes * * Returns the number of bytes read diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index bf96a61d4b86..9a3ec20b0be2 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -4,7 +4,7 @@ # # Stage one of module building created the following: # a) The individual .o files used for the module -# b) A .o file wich is the .o files above linked together +# b) A .o file which is the .o files above linked together # c) A .mod file in $(MODVERDIR)/, listing the name of the # the preliminary .o file, plus all .o files -- cgit v1.2.3-59-g8ed1b From aec5c3c1a929d7d79a420e943285cf3ba26a7c0d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 25 Mar 2006 01:33:34 +0900 Subject: [PATCH] libata: kill E.D.D. E.D.D. has no user in-tree and mostly useless. Kill it. For possible out-of-tree users, add a nice warning message and error handling if LLDD doesn't report any useable reset mechanism (and thus tries to use E.D.D.). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 98 ++++++---------------------------------------- include/linux/libata.h | 1 - 2 files changed, 13 insertions(+), 86 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d279666dcb38..0aff888d9ecd 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1081,9 +1081,8 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * * Read ID data from the specified device. ATA_CMD_ID_ATA is * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI - * devices. This function also takes care of EDD signature - * misreporting (to be removed once EDD support is gone) and - * issues ATA_CMD_INIT_DEV_PARAMS for pre-ATA4 drives. + * devices. This function also issues ATA_CMD_INIT_DEV_PARAMS + * for pre-ATA4 drives. * * LOCKING: * Kernel thread context (may sleep) @@ -1095,7 +1094,6 @@ 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 class = *p_class; - unsigned int using_edd; struct ata_taskfile tf; unsigned int err_mask = 0; u16 *id; @@ -1104,12 +1102,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); - if (ap->ops->probe_reset || - ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET)) - using_edd = 0; - else - using_edd = 1; - ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL); @@ -1139,32 +1131,9 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE, id, sizeof(id[0]) * ATA_ID_WORDS); - if (err_mask) { rc = -EIO; reason = "I/O error"; - - if (err_mask & ~AC_ERR_DEV) - goto err_out; - - /* - * arg! EDD works for all test cases, but seems to return - * the ATA signature for some ATAPI devices. Until the - * reason for this is found and fixed, we fix up the mess - * here. If IDENTIFY DEVICE returns command aborted - * (as ATAPI devices do), then we issue an - * IDENTIFY PACKET DEVICE. - * - * ATA software reset (SRST, the default) does not appear - * to have this problem. - */ - if ((using_edd) && (class == ATA_DEV_ATA)) { - u8 err = tf.feature; - if (err & ATA_ABORTED) { - class = ATA_DEV_ATAPI; - goto retry; - } - } goto err_out; } @@ -2005,45 +1974,6 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask) ap->ops->dev_select(ap, 0); } -/** - * ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command. - * @ap: Port to reset and probe - * - * Use the EXECUTE DEVICE DIAGNOSTIC command to reset and - * probe the bus. Not often used these days. - * - * LOCKING: - * PCI/etc. bus probe sem. - * Obtains host_set lock. - * - */ - -static unsigned int ata_bus_edd(struct ata_port *ap) -{ - struct ata_taskfile tf; - unsigned long flags; - - /* set up execute-device-diag (bus reset) taskfile */ - /* also, take interrupts to a known state (disabled) */ - DPRINTK("execute-device-diag\n"); - ata_tf_init(ap, &tf, 0); - tf.ctl |= ATA_NIEN; - tf.command = ATA_CMD_EDD; - tf.protocol = ATA_PROT_NODATA; - - /* do bus reset */ - spin_lock_irqsave(&ap->host_set->lock, flags); - ata_tf_to_host(ap, &tf); - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - /* spec says at least 2ms. but who knows with those - * crazy ATAPI devices... - */ - msleep(150); - - return ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); -} - static unsigned int ata_bus_softreset(struct ata_port *ap, unsigned int devmask) { @@ -2116,7 +2046,7 @@ void ata_bus_reset(struct ata_port *ap) struct ata_ioports *ioaddr = &ap->ioaddr; unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; u8 err; - unsigned int dev0, dev1 = 0, rc = 0, devmask = 0; + unsigned int dev0, dev1 = 0, devmask = 0; DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no); @@ -2139,18 +2069,8 @@ void ata_bus_reset(struct ata_port *ap) /* issue bus reset */ if (ap->flags & ATA_FLAG_SRST) - rc = ata_bus_softreset(ap, devmask); - else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) { - /* set up device control */ - if (ap->flags & ATA_FLAG_MMIO) - writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); - else - outb(ap->ctl, ioaddr->ctl_addr); - rc = ata_bus_edd(ap); - } - - if (rc) - goto err_out; + if (ata_bus_softreset(ap, devmask)) + goto err_out; /* * determine by signature whether we have ATA or ATAPI devices @@ -4536,6 +4456,14 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, int rc; DPRINTK("ENTER\n"); + + if (!ent->port_ops->probe_reset && + !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) { + printk(KERN_ERR "ata%u: no reset mechanism available\n", + port_no); + return NULL; + } + host = scsi_host_alloc(ent->sht, sizeof(struct ata_port)); if (!host) return NULL; diff --git a/include/linux/libata.h b/include/linux/libata.h index 047192253c3a..9fcc061e3adf 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -161,7 +161,6 @@ enum { ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */ /* various lengths of time */ - ATA_TMOUT_EDD = 5 * HZ, /* heuristic */ ATA_TMOUT_PIO = 30 * HZ, ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */ ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* heuristic */ -- cgit v1.2.3-59-g8ed1b From 5daf2cf19a7d03843d8d2d1b4aaf5260479cc5a7 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 24 Mar 2006 18:35:26 +0100 Subject: BUG_ON() Conversion in md/bitmap.c this changes if() BUG(); constructs to BUG_ON() which is cleaner and can better optimized away Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/md/bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index eae4473eadde..979e8cae5d83 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1309,7 +1309,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect case 1: *bmc = 2; } - if ((*bmc & COUNTER_MAX) == COUNTER_MAX) BUG(); + BUG_ON((*bmc & COUNTER_MAX) == COUNTER_MAX); (*bmc)++; spin_unlock_irq(&bitmap->lock); -- cgit v1.2.3-59-g8ed1b From 4401d138993c652dc7463207fa3afde71b7ae509 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 24 Mar 2006 18:36:27 +0100 Subject: BUG_ON() Conversion in md/dm-hw-handler.c this changes if() BUG(); constructs to BUG_ON() which is cleaner and can better optimized away Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/md/dm-hw-handler.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-hw-handler.c b/drivers/md/dm-hw-handler.c index 4cc0010e0156..baafaaba4d4b 100644 --- a/drivers/md/dm-hw-handler.c +++ b/drivers/md/dm-hw-handler.c @@ -83,8 +83,7 @@ void dm_put_hw_handler(struct hw_handler_type *hwht) if (--hwhi->use == 0) module_put(hwhi->hwht.module); - if (hwhi->use < 0) - BUG(); + BUG_ON(hwhi->use < 0); out: up_read(&_hwh_lock); -- cgit v1.2.3-59-g8ed1b From b1eecf7e04f34e3248ca8d14e49156da63f05117 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 24 Mar 2006 18:37:43 +0100 Subject: BUG_ON() Conversion in input/serio/hil_mlc.c this changes if() BUG(); constructs to BUG_ON() which is cleaner and can better optimized away Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/input/serio/hil_mlc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 5704204964a3..ea499783fb12 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c @@ -556,7 +556,7 @@ static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) { do_gettimeofday(&(mlc->instart)); mlc->icount = 15; memset(mlc->ipacket, 0, 16 * sizeof(hil_packet)); - if (down_trylock(&(mlc->isem))) BUG(); + BUG_ON(down_trylock(&(mlc->isem))); return; } -- cgit v1.2.3-59-g8ed1b From 7ac1e877d48061aa6ebca936189c32b44ccf8d9c Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 24 Mar 2006 18:48:13 +0100 Subject: BUG_ON() Conversion in drivers/s390/block/dasd.c this changes if() BUG(); constructs to BUG_ON() which is cleaner, contains unlikely() and can better optimized away. Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/s390/block/dasd.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index dfe542b206cc..0eab05a37e65 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -542,9 +542,8 @@ dasd_kmalloc_request(char *magic, int cplength, int datasize, struct dasd_ccw_req *cqr; /* Sanity checks */ - if ( magic == NULL || datasize > PAGE_SIZE || - (cplength*sizeof(struct ccw1)) > PAGE_SIZE) - BUG(); + BUG_ON( magic == NULL || datasize > PAGE_SIZE || + (cplength*sizeof(struct ccw1)) > PAGE_SIZE); cqr = kzalloc(sizeof(struct dasd_ccw_req), GFP_ATOMIC); if (cqr == NULL) @@ -584,9 +583,8 @@ dasd_smalloc_request(char *magic, int cplength, int datasize, int size; /* Sanity checks */ - if ( magic == NULL || datasize > PAGE_SIZE || - (cplength*sizeof(struct ccw1)) > PAGE_SIZE) - BUG(); + BUG_ON( magic == NULL || datasize > PAGE_SIZE || + (cplength*sizeof(struct ccw1)) > PAGE_SIZE); size = (sizeof(struct dasd_ccw_req) + 7L) & -8L; if (cplength > 0) -- cgit v1.2.3-59-g8ed1b From 089fe1b23da5468bbf02b721472f71f349837a7d Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 24 Mar 2006 18:50:27 +0100 Subject: BUG_ON() Conversion in drivers/block/ this changes if() BUG(); constructs to BUG_ON() which is cleaner, contains unlikely() and can better optimized away. Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/block/DAC960.c | 3 +-- drivers/block/cciss.c | 3 +-- drivers/block/cciss_scsi.c | 2 +- drivers/block/cpqarray.c | 3 +-- 4 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 37b8cda3e8bc..9bdea2a5cf0e 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -228,8 +228,7 @@ static void *slice_dma_loaf(struct dma_loaf *loaf, size_t len, void *cpu_end = loaf->cpu_free + len; void *cpu_addr = loaf->cpu_free; - if (cpu_end > loaf->cpu_base + loaf->length) - BUG(); + BUG_ON(cpu_end > loaf->cpu_base + loaf->length); *dma_handle = loaf->dma_free; loaf->cpu_free = cpu_end; loaf->dma_free += len; diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 1f2890989b56..71ec9e664383 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2361,8 +2361,7 @@ queue: if (!creq) goto startio; - if (creq->nr_phys_segments > MAXSGENTRIES) - BUG(); + BUG_ON(creq->nr_phys_segments > MAXSGENTRIES); if (( c = cmd_alloc(h, 1)) == NULL) goto full; diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 9e35de05d5c5..0e66e904bd8c 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -1316,7 +1316,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd cp->Request.Timeout = 0; memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); - if (cmd->cmd_len > sizeof(cp->Request.CDB)) BUG(); + BUG_ON(cmd->cmd_len > sizeof(cp->Request.CDB)); cp->Request.CDBLen = cmd->cmd_len; memcpy(cp->Request.CDB, cmd->cmnd, cmd->cmd_len); cp->Request.Type.Type = TYPE_CMD; diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 862b9abac0ae..b6ea2f0c7276 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -906,8 +906,7 @@ queue_next: if (!creq) goto startio; - if (creq->nr_phys_segments > SG_MAX) - BUG(); + BUG_ON(creq->nr_phys_segments > SG_MAX); if ((c = cmd_alloc(h,1)) == NULL) goto startio; -- cgit v1.2.3-59-g8ed1b From b74945547f0679003ede4d1afcd0aa169059a436 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 24 Mar 2006 18:52:10 +0100 Subject: BUG_ON() Conversion in drivers/parisc/ this changes if() BUG(); constructs to BUG_ON() which is cleaner, contains unlikely() and can better optimized away. Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/parisc/sba_iommu.c | 10 +++------- drivers/parisc/superio.c | 7 +++---- 2 files changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 5d47c5965c51..0821747e44cf 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1724,9 +1724,7 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa, sba_dev->chip_resv.start = PCI_F_EXTEND | 0xfef00000UL; sba_dev->chip_resv.end = PCI_F_EXTEND | (0xff000000UL - 1) ; err = request_resource(&iomem_resource, &(sba_dev->chip_resv)); - if (err < 0) { - BUG(); - } + BUG_ON(err < 0); } else if (IS_PLUTO(sba_dev->iodc)) { int err; @@ -2185,8 +2183,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) int i; int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */ - if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT)) - BUG(); + BUG_ON((t!=HPHW_IOA) && (t!=HPHW_BCPORT)); r->start = r->end = 0; @@ -2228,8 +2225,7 @@ void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r ) int base, size; int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */ - if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT)) - BUG(); + BUG_ON((t!=HPHW_IOA) && (t!=HPHW_BCPORT)); r->start = r->end = 0; diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index ba971fecd0d8..ad6d3b28a3a6 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -157,8 +157,8 @@ superio_init(struct pci_dev *pcidev) if (sio->suckyio_irq_enabled) return; - if (!pdev) BUG(); - if (!sio->usb_pdev) BUG(); + BUG_ON(!pdev); + BUG_ON(!sio->usb_pdev); /* use the IRQ iosapic found for USB INT D... */ pdev->irq = sio->usb_pdev->irq; @@ -474,8 +474,7 @@ superio_probe(struct pci_dev *dev, const struct pci_device_id *id) dev->subsystem_vendor, dev->subsystem_device, dev->class); - if (!sio->suckyio_irq_enabled) - BUG(); /* Enabled by PCI_FIXUP_FINAL */ + BUG_ON(!sio->suckyio_irq_enabled); /* Enabled by PCI_FIXUP_FINAL */ if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) { /* Function 1 */ superio_parport_init(); -- cgit v1.2.3-59-g8ed1b From 232443e2c90cc2930624dec89df327615b002c55 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 24 Mar 2006 18:53:18 +0100 Subject: BUG_ON() Conversion in drivers/video/ this changes if() BUG(); constructs to BUG_ON() which is cleaner, contains unlikely() and can better optimized away. Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/video/bw2.c | 3 +-- drivers/video/ffb.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index c029db4646f6..6577fdfdfc16 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -327,8 +327,7 @@ static void bw2_init_one(struct sbus_dev *sdev) } else #else { - if (!sdev) - BUG(); + BUG_ON(!sdev); all->par.physbase = sdev->reg_addrs[0].phys_addr; resp = &sdev->resource[0]; sbusfb_fill_var(&all->info.var, (sdev ? sdev->prom_node : 0), 1); diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 9c9b21d469a1..7633e41adda1 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -466,8 +466,7 @@ static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) unsigned long flags; u32 fg; - if (rect->rop != ROP_COPY && rect->rop != ROP_XOR) - BUG(); + BUG_ON(rect->rop != ROP_COPY && rect->rop != ROP_XOR); fg = ((u32 *)info->pseudo_palette)[rect->color]; -- cgit v1.2.3-59-g8ed1b From c7b0ac0546985fc6361a8d92cf808d46da797677 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 10 Mar 2006 12:29:15 -0300 Subject: V4L/DVB (3516): Make video_buf more generic Video_buf were concerned to allow PCI devices to be used as video capture devices. This patch extends video_buf features by virtualizing pci-dependent functions and allowing other type of devices to use it. It is still DMA centric, although it may be used also by devices that emulates scatter/gather behavior or a DMA device Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_fops.c | 5 +- drivers/media/common/saa7146_vbi.c | 8 +- drivers/media/common/saa7146_video.c | 8 +- drivers/media/video/bttv-driver.c | 19 ++- drivers/media/video/bttv-risc.c | 4 +- drivers/media/video/bttv-vbi.c | 6 +- drivers/media/video/bttvp.h | 3 +- drivers/media/video/cx88/cx88-alsa.c | 4 +- drivers/media/video/cx88/cx88-blackbird.c | 5 +- drivers/media/video/cx88/cx88-core.c | 6 +- drivers/media/video/cx88/cx88-dvb.c | 5 +- drivers/media/video/cx88/cx88-mpeg.c | 28 ++-- drivers/media/video/cx88/cx88-vbi.c | 7 +- drivers/media/video/cx88/cx88-video.c | 35 +++- drivers/media/video/cx88/cx88.h | 6 +- drivers/media/video/saa7134/saa7134-alsa.c | 10 +- drivers/media/video/saa7134/saa7134-core.c | 4 +- drivers/media/video/saa7134/saa7134-oss.c | 6 +- drivers/media/video/saa7134/saa7134-ts.c | 9 +- drivers/media/video/saa7134/saa7134-vbi.c | 10 +- drivers/media/video/saa7134/saa7134-video.c | 9 +- drivers/media/video/saa7134/saa7134.h | 2 +- drivers/media/video/v4l2-common.c | 6 +- drivers/media/video/video-buf.c | 250 +++++++++++++++++++++------- include/media/saa7146_vv.h | 3 +- include/media/video-buf.h | 56 +++++-- 26 files changed, 340 insertions(+), 174 deletions(-) (limited to 'drivers') diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 3870fa948cc0..523ab3851c7b 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -50,14 +50,15 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) /********************************************************************************/ /* common dma functions */ -void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf) +void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q, + struct saa7146_buf *buf) { DEB_EE(("dev:%p, buf:%p\n",dev,buf)); BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); - videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma); + videobuf_dma_unmap(q, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); buf->vb.state = STATE_NEEDS_INIT; } diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index 500bd3f05e16..063608462ebe 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c @@ -236,7 +236,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e } if (buf->vb.size != size) - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); if (STATE_NEEDS_INIT == buf->vb.state) { buf->vb.width = llength; @@ -247,7 +247,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e saa7146_pgtable_free(dev->pci, &buf->pt[2]); saa7146_pgtable_alloc(dev->pci, &buf->pt[2]); - err = videobuf_iolock(dev->pci,&buf->vb, NULL); + err = videobuf_iolock(q,&buf->vb, NULL); if (err) goto oops; err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen); @@ -261,7 +261,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e oops: DEB_VBI(("error out.\n")); - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); return err; } @@ -301,7 +301,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) struct saa7146_buf *buf = (struct saa7146_buf *)vb; DEB_VBI(("vb:%p\n",vb)); - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); } static struct videobuf_queue_ops vbi_qops = { diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 6b42713d97f4..e7079d1bd537 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -1275,7 +1275,7 @@ static int buffer_prepare(struct videobuf_queue *q, buf->vb.field != field || buf->vb.field != fh->video_fmt.field || buf->fmt != &fh->video_fmt) { - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); } if (STATE_NEEDS_INIT == buf->vb.state) { @@ -1304,7 +1304,7 @@ static int buffer_prepare(struct videobuf_queue *q, saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); } - err = videobuf_iolock(dev->pci,&buf->vb, &vv->ov_fb); + err = videobuf_iolock(q,&buf->vb, &vv->ov_fb); if (err) goto oops; err = saa7146_pgtable_build(dev,buf); @@ -1318,7 +1318,7 @@ static int buffer_prepare(struct videobuf_queue *q, oops: DEB_D(("error out.\n")); - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); return err; } @@ -1363,7 +1363,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) struct saa7146_buf *buf = (struct saa7146_buf *)vb; DEB_CAP(("vbuf:%p\n",vb)); - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); } static struct videobuf_queue_ops video_qops = { diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index c0415d6e7fee..2505ae5a7b97 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1397,7 +1397,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, free_btres(btv,fh,RESOURCE_OVERLAY); if (NULL != old) { dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state); - bttv_dma_free(btv, old); + bttv_dma_free(&fh->cap,btv, old); kfree(old); } dprintk("switch_overlay: done\n"); @@ -1407,7 +1407,8 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, /* ----------------------------------------------------------------------- */ /* video4linux (1) interface */ -static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, +static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv, + struct bttv_buffer *buf, const struct bttv_format *fmt, unsigned int width, unsigned int height, enum v4l2_field field) @@ -1450,7 +1451,7 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, /* alloc risc memory */ if (STATE_NEEDS_INIT == buf->vb.state) { redo_dma_risc = 1; - if (0 != (rc = videobuf_iolock(btv->c.pci,&buf->vb,&btv->fbuf))) + if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf))) goto fail; } @@ -1462,7 +1463,7 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, return 0; fail: - bttv_dma_free(btv,buf); + bttv_dma_free(q,btv,buf); return rc; } @@ -1486,7 +1487,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); struct bttv_fh *fh = q->priv_data; - return bttv_prepare_buffer(fh->btv, buf, fh->fmt, + return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt, fh->width, fh->height, field); } @@ -1510,7 +1511,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); struct bttv_fh *fh = q->priv_data; - bttv_dma_free(fh->btv,buf); + bttv_dma_free(&fh->cap,fh->btv,buf); } static struct videobuf_queue_ops bttv_video_qops = { @@ -2496,7 +2497,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2) ? V4L2_FIELD_INTERLACED : V4L2_FIELD_BOTTOM; - retval = bttv_prepare_buffer(btv,buf, + retval = bttv_prepare_buffer(&fh->cap,btv,buf, format_by_palette(vm->format), vm->width,vm->height,field); if (0 != retval) @@ -2528,8 +2529,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, retval = -EIO; /* fall through */ case STATE_DONE: - videobuf_dma_pci_sync(btv->c.pci,&buf->vb.dma); - bttv_dma_free(btv,buf); + videobuf_dma_sync(&fh->cap,&buf->vb.dma); + bttv_dma_free(&fh->cap,btv,buf); break; default: retval = -EINVAL; diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index 344f84e9af04..16323a5d68ac 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -509,11 +509,11 @@ bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, } void -bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf) +bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf) { BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); - videobuf_dma_pci_unmap(btv->c.pci, &buf->vb.dma); + videobuf_dma_unmap(q, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); btcx_riscmem_free(btv->c.pci,&buf->bottom); btcx_riscmem_free(btv->c.pci,&buf->top); diff --git a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c index 72afdd64b882..e20ff238e409 100644 --- a/drivers/media/video/bttv-vbi.c +++ b/drivers/media/video/bttv-vbi.c @@ -96,7 +96,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q, return -EINVAL; if (STATE_NEEDS_INIT == buf->vb.state) { - if (0 != (rc = videobuf_iolock(btv->c.pci, &buf->vb, NULL))) + if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL))) goto fail; if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines))) goto fail; @@ -109,7 +109,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q, return 0; fail: - bttv_dma_free(btv,buf); + bttv_dma_free(q,btv,buf); return rc; } @@ -136,7 +136,7 @@ static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); dprintk("free %p\n",vb); - bttv_dma_free(fh->btv,buf); + bttv_dma_free(&fh->cap,fh->btv,buf); } struct videobuf_queue_ops bttv_vbi_qops = { diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index 9cb72f176f7d..12223a203960 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -190,7 +190,8 @@ int bttv_buffer_activate_video(struct bttv *btv, struct bttv_buffer_set *set); int bttv_buffer_activate_vbi(struct bttv *btv, struct bttv_buffer *vbi); -void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf); +void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv, + struct bttv_buffer *buf); /* overlay handling */ int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 3170b8f72c68..f9d87b86492c 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -303,7 +303,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) BUG_ON(!chip->dma_size); dprintk(2,"Freeing buffer\n"); - videobuf_dma_pci_unmap(chip->pci, &chip->dma_risc); + videobuf_pci_dma_unmap(chip->pci, &chip->dma_risc); videobuf_dma_free(&chip->dma_risc); btcx_riscmem_free(chip->pci,&chip->buf->risc); kfree(chip->buf); @@ -429,7 +429,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE, (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); - videobuf_dma_pci_map(chip->pci,&buf->vb.dma); + videobuf_pci_dma_map(chip->pci,&buf->vb.dma); cx88_risc_databuffer(chip->pci, &buf->risc, diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index a502a4d6e4ae..e100d8ef369a 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1341,7 +1341,7 @@ bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { struct cx8802_fh *fh = q->priv_data; - return cx8802_buf_prepare(fh->dev, (struct cx88_buffer*)vb, field); + return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field); } static void @@ -1354,8 +1354,7 @@ bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct cx8802_fh *fh = q->priv_data; - cx88_free_buffer(fh->dev->pci, (struct cx88_buffer*)vb); + cx88_free_buffer(q, (struct cx88_buffer*)vb); } static struct videobuf_queue_ops blackbird_qops = { diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index c2cdbafdb77b..2c3d9f1999be 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -213,13 +213,13 @@ int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, } void -cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf) +cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) { BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); - videobuf_dma_pci_unmap(pci, &buf->vb.dma); + videobuf_dma_unmap(q, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); - btcx_riscmem_free(pci, &buf->risc); + btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc); buf->vb.state = STATE_NEEDS_INIT; } diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index a9fc2695b157..f0ea9b5cdbc2 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -90,7 +90,7 @@ static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { struct cx8802_dev *dev = q->priv_data; - return cx8802_buf_prepare(dev, (struct cx88_buffer*)vb,field); + return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); } static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) @@ -101,8 +101,7 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct cx8802_dev *dev = q->priv_data; - cx88_free_buffer(dev->pci, (struct cx88_buffer*)vb); + cx88_free_buffer(q, (struct cx88_buffer*)vb); } static struct videobuf_queue_ops dvb_qops = { diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index c79cc1d2bf8b..7d16888b4a86 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -163,8 +163,8 @@ static int cx8802_restart_queue(struct cx8802_dev *dev, /* ------------------------------------------------------------------ */ -int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, - enum v4l2_field field) +int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev, + struct cx88_buffer *buf, enum v4l2_field field) { int size = dev->ts_packet_size * dev->ts_packet_count; int rc; @@ -179,7 +179,7 @@ int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, buf->vb.size = size; buf->vb.field = field /*V4L2_FIELD_TOP*/; - if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL))) + if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) goto fail; cx88_risc_databuffer(dev->pci, &buf->risc, buf->vb.dma.sglist, @@ -189,36 +189,36 @@ int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, return 0; fail: - cx88_free_buffer(dev->pci,buf); + cx88_free_buffer(q,buf); return rc; } void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) { struct cx88_buffer *prev; - struct cx88_dmaqueue *q = &dev->mpegq; + struct cx88_dmaqueue *cx88q = &dev->mpegq; dprintk( 1, "cx8802_buf_queue\n" ); /* add jump to stopper */ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma); - if (list_empty(&q->active)) { + if (list_empty(&cx88q->active)) { dprintk( 0, "queue is empty - first active\n" ); - list_add_tail(&buf->vb.queue,&q->active); - cx8802_start_dma(dev, q, buf); + list_add_tail(&buf->vb.queue,&cx88q->active); + cx8802_start_dma(dev, cx88q, buf); buf->vb.state = STATE_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + buf->count = cx88q->count++; + mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT); dprintk(0,"[%p/%d] %s - first active\n", buf, buf->vb.i, __FUNCTION__); } else { dprintk( 1, "queue is not empty - append to active\n" ); - prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue); - list_add_tail(&buf->vb.queue,&q->active); + prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue); + list_add_tail(&buf->vb.queue,&cx88q->active); buf->vb.state = STATE_ACTIVE; - buf->count = q->count++; + buf->count = cx88q->count++; prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); dprintk( 1, "[%p/%d] %s - append to active\n", buf, buf->vb.i, __FUNCTION__); diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index 9bc6c8995581..846faadc9f1c 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c @@ -175,7 +175,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, buf->vb.size = size; buf->vb.field = V4L2_FIELD_SEQ_TB; - if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL))) + if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) goto fail; cx88_risc_buffer(dev->pci, &buf->risc, buf->vb.dma.sglist, @@ -187,7 +187,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, return 0; fail: - cx88_free_buffer(dev->pci,buf); + cx88_free_buffer(q,buf); return rc; } @@ -227,9 +227,8 @@ vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); - struct cx8800_fh *fh = q->priv_data; - cx88_free_buffer(fh->dev->pci,buf); + cx88_free_buffer(q,buf); } struct videobuf_queue_ops cx8800_vbi_qops = { diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 6c97aa740d27..72a417b31745 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -564,7 +564,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, if (STATE_NEEDS_INIT == buf->vb.state) { init_buffer = 1; - if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL))) + if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) goto fail; } @@ -614,7 +614,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, return 0; fail: - cx88_free_buffer(dev->pci,buf); + cx88_free_buffer(q,buf); return rc; } @@ -671,9 +671,8 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); - struct cx8800_fh *fh = q->priv_data; - cx88_free_buffer(fh->dev->pci,buf); + cx88_free_buffer(q,buf); } static struct videobuf_queue_ops cx8800_video_qops = { @@ -1251,9 +1250,17 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, { int err; - dprintk(2, "CORE IOCTL: 0x%x\n", cmd ); - if (video_debug > 1) - v4l_print_ioctl(core->name,cmd); + if (video_debug) { + if (video_debug > 1) { + if (_IOC_DIR(cmd) & _IOC_WRITE) + v4l_printk_ioctl_arg("cx88(w)",cmd, arg); + else if (!_IOC_DIR(cmd) & _IOC_READ) { + v4l_print_ioctl("cx88", cmd); + } + } else + v4l_print_ioctl(core->name,cmd); + + } switch (cmd) { /* ---------- tv norms ---------- */ @@ -1460,7 +1467,19 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, static int video_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - return video_usercopy(inode, file, cmd, arg, video_do_ioctl); + int retval; + + retval=video_usercopy(inode, file, cmd, arg, video_do_ioctl); + + if (video_debug > 1) { + if (retval < 0) { + v4l_print_ioctl("cx88(err)", cmd); + printk(KERN_DEBUG "cx88(err): errcode=%d\n",retval); + } else if (_IOC_DIR(cmd) & _IOC_READ) + v4l_printk_ioctl_arg("cx88(r)",cmd, (void *)arg); + } + + return retval; } /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index cfa8668784b4..5b2e499eab22 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -485,7 +485,7 @@ extern int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, u32 reg, u32 mask, u32 value); extern void -cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf); +cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf); extern void cx88_risc_disasm(struct cx88_core *core, struct btcx_riscmem *risc); @@ -577,8 +577,8 @@ void cx88_ir_irq(struct cx88_core *core); /* ----------------------------------------------------------- */ /* cx88-mpeg.c */ -int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, - enum v4l2_field field); +int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev, + struct cx88_buffer *buf, enum v4l2_field field); void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf); void cx8802_cancel_buffers(struct cx8802_dev *dev); diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index aca84d2f9825..bb3e0ba946d3 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -507,7 +507,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, /* release the old buffer */ if (substream->runtime->dma_area) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); dsp_buffer_free(dev); substream->runtime->dma_area = NULL; } @@ -523,12 +523,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, return err; } - if (0 != (err = videobuf_dma_pci_map(dev->pci, &dev->dmasound.dma))) { + if (0 != (err = videobuf_pci_dma_map(dev->pci, &dev->dmasound.dma))) { dsp_buffer_free(dev); return err; } if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { - videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); dsp_buffer_free(dev); return err; } @@ -537,7 +537,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, dev->dmasound.dma.sglen, 0))) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); dsp_buffer_free(dev); return err; } @@ -571,7 +571,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream) if (substream->runtime->dma_area) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); dsp_buffer_free(dev); substream->runtime->dma_area = NULL; } diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 58e568d7d2ee..15405d1e1675 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -254,12 +254,12 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt) /* ------------------------------------------------------------------ */ -void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf) +void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf) { BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); - videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma); + videobuf_dma_unmap(q, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); buf->vb.state = STATE_NEEDS_INIT; } diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index d79d05f88705..7aa02b34e012 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -124,7 +124,7 @@ static int dsp_rec_start(struct saa7134_dev *dev) unsigned long flags; /* prepare buffer */ - if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma))) + if (0 != (err = videobuf_pci_dma_map(dev->pci,&dev->dmasound.dma))) return err; if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) goto fail1; @@ -213,7 +213,7 @@ static int dsp_rec_start(struct saa7134_dev *dev) fail2: saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); fail1: - videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci,&dev->dmasound.dma); return err; } @@ -231,7 +231,7 @@ static int dsp_rec_stop(struct saa7134_dev *dev) /* unlock buffer */ saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); - videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci,&dev->dmasound.dma); return 0; } diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index 470903e2f5e5..60a90a2617ae 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -89,7 +89,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, return -EINVAL; if (buf->vb.size != size) { - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); } if (STATE_NEEDS_INIT == buf->vb.state) { @@ -98,7 +98,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, buf->vb.size = size; buf->pt = &dev->ts.pt_ts; - err = videobuf_iolock(dev->pci,&buf->vb,NULL); + err = videobuf_iolock(q,&buf->vb,NULL); if (err) goto oops; err = saa7134_pgtable_build(dev->pci,buf->pt, @@ -126,7 +126,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, return 0; oops: - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); return err; } @@ -152,10 +152,9 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_dev *dev = q->priv_data; struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); } struct videobuf_queue_ops saa7134_ts_qops = { diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c index f4aee0af80e1..f38366a470fa 100644 --- a/drivers/media/video/saa7134/saa7134-vbi.c +++ b/drivers/media/video/saa7134/saa7134-vbi.c @@ -135,7 +135,7 @@ static int buffer_prepare(struct videobuf_queue *q, return -EINVAL; if (buf->vb.size != size) - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); if (STATE_NEEDS_INIT == buf->vb.state) { buf->vb.width = llength; @@ -143,7 +143,7 @@ static int buffer_prepare(struct videobuf_queue *q, buf->vb.size = size; buf->pt = &fh->pt_vbi; - err = videobuf_iolock(dev->pci,&buf->vb,NULL); + err = videobuf_iolock(q,&buf->vb,NULL); if (err) goto oops; err = saa7134_pgtable_build(dev->pci,buf->pt, @@ -159,7 +159,7 @@ static int buffer_prepare(struct videobuf_queue *q, return 0; oops: - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); return err; } @@ -190,11 +190,9 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_fh *fh = q->priv_data; - struct saa7134_dev *dev = fh->dev; struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); } struct videobuf_queue_ops saa7134_vbi_qops = { diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 57a11e71d996..aeef80f88a6b 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -993,7 +993,7 @@ static int buffer_prepare(struct videobuf_queue *q, buf->vb.size != size || buf->vb.field != field || buf->fmt != fh->fmt) { - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); } if (STATE_NEEDS_INIT == buf->vb.state) { @@ -1004,7 +1004,7 @@ static int buffer_prepare(struct videobuf_queue *q, buf->fmt = fh->fmt; buf->pt = &fh->pt_cap; - err = videobuf_iolock(dev->pci,&buf->vb,&dev->ovbuf); + err = videobuf_iolock(q,&buf->vb,&dev->ovbuf); if (err) goto oops; err = saa7134_pgtable_build(dev->pci,buf->pt, @@ -1019,7 +1019,7 @@ static int buffer_prepare(struct videobuf_queue *q, return 0; oops: - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); return err; } @@ -1045,10 +1045,9 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_fh *fh = q->priv_data; struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); - saa7134_dma_free(fh->dev,buf); + saa7134_dma_free(q,buf); } static struct videobuf_queue_ops video_qops = { diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index ce1c2e0b065e..104bd2e054e5 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -579,7 +579,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q, unsigned int state); void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q); void saa7134_buffer_timeout(unsigned long data); -void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf); +void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf); int saa7134_set_dmabits(struct saa7134_dev *dev); diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 95a6e47c99f1..9b029e4dbfb7 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -481,7 +481,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) prt_names(p->memory,v4l2_memory_names), p->m.userptr); printk ("%s: timecode= %02d:%02d:%02d type=%d, " - "flags=0x%08d, frames=%d, userbits=0x%08x", + "flags=0x%08d, frames=%d, userbits=0x%08x\n", s,tc->hours,tc->minutes,tc->seconds, tc->type, tc->flags, tc->frames, (__u32) tc->userbits); break; @@ -489,8 +489,8 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) case VIDIOC_QUERYCAP: { struct v4l2_capability *p=arg; - printk ("%s: driver=%s, card=%s, bus=%s, version=%d, " - "capabilities=%d\n", s, + printk ("%s: driver=%s, card=%s, bus=%s, version=0x%08x, " + "capabilities=0x%08x\n", s, p->driver,p->card,p->bus_info, p->version, p->capabilities); diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 87e937581d5a..d2ca0f08d0df 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -1,15 +1,20 @@ /* * * generic helper functions for video4linux capture buffers, to handle - * memory management and PCI DMA. Right now bttv + saa7134 use it. + * memory management and PCI DMA. + * Right now, bttv, saa7134, saa7146 and cx88 use it. * * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented * into PAGE_SIZE chunks). They also assume the driver does not need - * to touch the video data (thus it is probably not useful for USB 1.1 - * as data often must be uncompressed by the drivers). + * to touch the video data. + * + * device specific map/unmap/sync stuff now are mapped as operations + * to allow its usage by USB and virtual devices. * * (c) 2001-2004 Gerd Knorr [SUSE Labs] + * (c) 2006 Mauro Carvalho Chehab + * (c) 2006 Ted Walther and John Sokol * * 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 @@ -167,6 +172,9 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages); return -ENOMEM; } + dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n", + (unsigned long)dma->vmalloc, + nr_pages << PAGE_SHIFT); memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT); dma->nr_pages = nr_pages; return 0; @@ -186,8 +194,10 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, return 0; } -int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) +int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { + void *dev=q->dev; + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); BUG_ON(0 == dma->nr_pages); @@ -197,7 +207,7 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) } if (dma->vmalloc) { dma->sglist = videobuf_vmalloc_to_sg - (dma->vmalloc,dma->nr_pages); + (dma->vmalloc,dma->nr_pages); } if (dma->bus_addr) { dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); @@ -212,13 +222,14 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) dprintk(1,"scatterlist is NULL\n"); return -ENOMEM; } - if (!dma->bus_addr) { - dma->sglen = pci_map_sg(dev,dma->sglist,dma->nr_pages, - dma->direction); + if (q->ops->vb_map_sg) { + dma->sglen = q->ops->vb_map_sg(dev,dma->sglist, + dma->nr_pages, dma->direction); + } if (0 == dma->sglen) { printk(KERN_WARNING - "%s: pci_map_sg failed\n",__FUNCTION__); + "%s: videobuf_map_sg failed\n",__FUNCTION__); kfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; @@ -228,24 +239,31 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) return 0; } -int videobuf_dma_pci_sync(struct pci_dev *dev, struct videobuf_dmabuf *dma) +int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { + void *dev=q->dev; + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); BUG_ON(!dma->sglen); - if (!dma->bus_addr) - pci_dma_sync_sg_for_cpu(dev,dma->sglist,dma->nr_pages,dma->direction); + if (!dma->bus_addr && q->ops->vb_dma_sync_sg) + q->ops->vb_dma_sync_sg(dev,dma->sglist,dma->nr_pages, + dma->direction); + return 0; } -int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma) +int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { + void *dev=q->dev; + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); if (!dma->sglen) return 0; - if (!dma->bus_addr) - pci_unmap_sg(dev,dma->sglist,dma->nr_pages,dma->direction); + if (!dma->bus_addr && q->ops->vb_unmap_sg) + q->ops->vb_unmap_sg(dev,dma->sglist,dma->nr_pages, + dma->direction); kfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; @@ -318,7 +336,7 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr) } int -videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, +videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf) { int err,pages; @@ -357,7 +375,7 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, default: BUG(); } - err = videobuf_dma_pci_map(pci,&vb->dma); + err = videobuf_dma_map(q,&vb->dma); if (0 != err) return err; @@ -366,9 +384,41 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, /* --------------------------------------------------------------------- */ +void videobuf_queue_pci(struct videobuf_queue* q) +{ + /* If not specified, defaults to PCI map sg */ + if (!q->ops->vb_map_sg) + q->ops->vb_map_sg=(vb_map_sg_t *)pci_map_sg; + + if (!q->ops->vb_dma_sync_sg) + q->ops->vb_dma_sync_sg=(vb_map_sg_t *)pci_dma_sync_sg_for_cpu; + if (!q->ops->vb_unmap_sg) + q->ops->vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg; +} + +int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma) +{ + struct videobuf_queue q; + + q.dev=pci; + q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg; + + return (videobuf_dma_unmap(&q,dma)); +} + +int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma) +{ + struct videobuf_queue q; + + q.dev=pci; + q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg; + + return (videobuf_dma_unmap(&q,dma)); +} + void videobuf_queue_init(struct videobuf_queue* q, struct videobuf_queue_ops *ops, - struct pci_dev *pci, + void *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, @@ -377,13 +427,15 @@ void videobuf_queue_init(struct videobuf_queue* q, { memset(q,0,sizeof(*q)); q->irqlock = irqlock; - q->pci = pci; + q->dev = dev; q->type = type; q->field = field; q->msize = msize; q->ops = ops; q->priv_data = priv; + videobuf_queue_pci(q); + mutex_init(&q->lock); INIT_LIST_HEAD(&q->stream); } @@ -431,7 +483,8 @@ videobuf_queue_cancel(struct videobuf_queue *q) int i; /* remove queued buffers from list */ - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -440,7 +493,8 @@ videobuf_queue_cancel(struct videobuf_queue *q) q->bufs[i]->state = STATE_ERROR; } } - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); /* free all buffers + clear queue */ for (i = 0; i < VIDEO_MAX_FRAME; i++) { @@ -534,19 +588,29 @@ videobuf_reqbufs(struct videobuf_queue *q, unsigned int size,count; int retval; - if (req->type != q->type) + if (req->type != q->type) { + dprintk(1,"reqbufs: queue type invalid\n"); return -EINVAL; - if (req->count < 1) + } + if (req->count < 1) { + dprintk(1,"reqbufs: count invalid (%d)\n",req->count); return -EINVAL; + } if (req->memory != V4L2_MEMORY_MMAP && req->memory != V4L2_MEMORY_USERPTR && - req->memory != V4L2_MEMORY_OVERLAY) + req->memory != V4L2_MEMORY_OVERLAY) { + dprintk(1,"reqbufs: memory type invalid\n"); return -EINVAL; + } - if (q->streaming) + if (q->streaming) { + dprintk(1,"reqbufs: streaming already exists\n"); return -EBUSY; - if (!list_empty(&q->stream)) + } + if (!list_empty(&q->stream)) { + dprintk(1,"reqbufs: stream running\n"); return -EBUSY; + } mutex_lock(&q->lock); count = req->count; @@ -559,8 +623,10 @@ videobuf_reqbufs(struct videobuf_queue *q, count, size, (count*size)>>PAGE_SHIFT); retval = videobuf_mmap_setup(q,count,size,req->memory); - if (retval < 0) + if (retval < 0) { + dprintk(1,"reqbufs: mmap setup returned %d\n",retval); goto done; + } req->count = count; @@ -572,12 +638,18 @@ videobuf_reqbufs(struct videobuf_queue *q, int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) { - if (unlikely(b->type != q->type)) + if (unlikely(b->type != q->type)) { + dprintk(1,"querybuf: Wrong type.\n"); return -EINVAL; - if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) + } + if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) { + dprintk(1,"querybuf: index out of range.\n"); return -EINVAL; - if (unlikely(NULL == q->bufs[b->index])) + } + if (unlikely(NULL == q->bufs[b->index])) { + dprintk(1,"querybuf: buffer is null.\n"); return -EINVAL; + } videobuf_status(b,q->bufs[b->index],q->type); return 0; } @@ -593,26 +665,40 @@ videobuf_qbuf(struct videobuf_queue *q, mutex_lock(&q->lock); retval = -EBUSY; - if (q->reading) + if (q->reading) { + dprintk(1,"qbuf: Reading running...\n"); goto done; + } retval = -EINVAL; - if (b->type != q->type) + if (b->type != q->type) { + dprintk(1,"qbuf: Wrong type.\n"); goto done; - if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) + } + if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) { + dprintk(1,"qbuf: index out of range.\n"); goto done; + } buf = q->bufs[b->index]; - if (NULL == buf) + if (NULL == buf) { + dprintk(1,"qbuf: buffer is null.\n"); goto done; + } MAGIC_CHECK(buf->magic,MAGIC_BUFFER); - if (buf->memory != b->memory) + if (buf->memory != b->memory) { + dprintk(1,"qbuf: memory type is wrong.\n"); goto done; + } if (buf->state == STATE_QUEUED || - buf->state == STATE_ACTIVE) + buf->state == STATE_ACTIVE) { + dprintk(1,"qbuf: buffer is already queued or active.\n"); goto done; + } if (b->flags & V4L2_BUF_FLAG_INPUT) { - if (b->input >= q->inputs) + if (b->input >= q->inputs) { + dprintk(1,"qbuf: wrong input.\n"); goto done; + } buf->input = b->input; } else { buf->input = UNSET; @@ -620,12 +706,16 @@ videobuf_qbuf(struct videobuf_queue *q, switch (b->memory) { case V4L2_MEMORY_MMAP: - if (0 == buf->baddr) + if (0 == buf->baddr) { + dprintk(1,"qbuf: mmap requested but buffer addr is zero!\n"); goto done; + } break; case V4L2_MEMORY_USERPTR: - if (b->length < buf->bsize) + if (b->length < buf->bsize) { + dprintk(1,"qbuf: buffer length is not enough\n"); goto done; + } if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr) q->ops->buf_release(q,buf); buf->baddr = b->m.userptr; @@ -634,20 +724,27 @@ videobuf_qbuf(struct videobuf_queue *q, buf->boff = b->m.offset; break; default: + dprintk(1,"qbuf: wrong memory type\n"); goto done; } + dprintk(1,"qbuf: requesting next field\n"); field = videobuf_next_field(q); retval = q->ops->buf_prepare(q,buf,field); - if (0 != retval) + if (0 != retval) { + dprintk(1,"qbuf: buffer_prepare returned %d\n",retval); goto done; + } list_add_tail(&buf->stream,&q->stream); if (q->streaming) { - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); } + dprintk(1,"qbuf: succeded\n"); retval = 0; done: @@ -664,26 +761,39 @@ videobuf_dqbuf(struct videobuf_queue *q, mutex_lock(&q->lock); retval = -EBUSY; - if (q->reading) + if (q->reading) { + dprintk(1,"dqbuf: Reading running...\n"); goto done; + } retval = -EINVAL; - if (b->type != q->type) + if (b->type != q->type) { + dprintk(1,"dqbuf: Wrong type.\n"); goto done; - if (list_empty(&q->stream)) + } + if (list_empty(&q->stream)) { + dprintk(1,"dqbuf: stream running\n"); goto done; + } buf = list_entry(q->stream.next, struct videobuf_buffer, stream); retval = videobuf_waiton(buf, nonblocking, 1); - if (retval < 0) + if (retval < 0) { + dprintk(1,"dqbuf: waiton returned %d\n",retval); goto done; + } switch (buf->state) { case STATE_ERROR: + dprintk(1,"dqbuf: state is error\n"); retval = -EIO; - /* fall through */ + videobuf_dma_sync(q,&buf->dma); + buf->state = STATE_IDLE; + break; case STATE_DONE: - videobuf_dma_pci_sync(q->pci,&buf->dma); + dprintk(1,"dqbuf: state is done\n"); + videobuf_dma_sync(q,&buf->dma); buf->state = STATE_IDLE; break; default: + dprintk(1,"dqbuf: state invalid\n"); retval = -EINVAL; goto done; } @@ -711,13 +821,15 @@ int videobuf_streamon(struct videobuf_queue *q) if (q->streaming) goto done; q->streaming = 1; - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); list_for_each(list,&q->stream) { buf = list_entry(list, struct videobuf_buffer, stream); if (buf->state == STATE_PREPARED) q->ops->buf_queue(q,buf); } - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); done: mutex_unlock(&q->lock); @@ -762,12 +874,14 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, goto done; /* start capture & wait */ - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); retval = videobuf_waiton(q->read_buf,0,0); if (0 == retval) { - videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); + videobuf_dma_sync(q,&q->read_buf->dma); if (STATE_ERROR == q->read_buf->state) retval = -EIO; else @@ -809,6 +923,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, /* need to capture a new frame */ retval = -ENOMEM; q->read_buf = videobuf_alloc(q->msize); + dprintk(1,"video alloc=0x%08x\n",(unsigned int) q->read_buf); if (NULL == q->read_buf) goto done; q->read_buf->memory = V4L2_MEMORY_USERPTR; @@ -820,9 +935,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, q->read_buf = NULL; goto done; } - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); q->read_off = 0; } @@ -830,7 +947,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, retval = videobuf_waiton(q->read_buf, nonblocking, 1); if (0 != retval) goto done; - videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); + videobuf_dma_sync(q,&q->read_buf->dma); if (STATE_ERROR == q->read_buf->state) { /* catch I/O errors */ @@ -887,10 +1004,12 @@ int videobuf_read_start(struct videobuf_queue *q) return err; list_add_tail(&q->bufs[i]->stream, &q->stream); } - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); for (i = 0; i < count; i++) q->ops->buf_queue(q,q->bufs[i]); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); q->reading = 1; return 0; } @@ -985,9 +1104,11 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, if (q->read_off == q->read_buf->size) { list_add_tail(&q->read_buf->stream, &q->stream); - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); q->read_buf = NULL; } if (retval < 0) @@ -1249,11 +1370,14 @@ EXPORT_SYMBOL_GPL(videobuf_dma_init); EXPORT_SYMBOL_GPL(videobuf_dma_init_user); EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); -EXPORT_SYMBOL_GPL(videobuf_dma_pci_map); -EXPORT_SYMBOL_GPL(videobuf_dma_pci_sync); -EXPORT_SYMBOL_GPL(videobuf_dma_pci_unmap); +EXPORT_SYMBOL_GPL(videobuf_dma_map); +EXPORT_SYMBOL_GPL(videobuf_dma_sync); +EXPORT_SYMBOL_GPL(videobuf_dma_unmap); EXPORT_SYMBOL_GPL(videobuf_dma_free); +EXPORT_SYMBOL_GPL(videobuf_pci_dma_map); +EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap); + EXPORT_SYMBOL_GPL(videobuf_alloc); EXPORT_SYMBOL_GPL(videobuf_waiton); EXPORT_SYMBOL_GPL(videobuf_iolock); diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h index e5e749e984ee..4507cb61ae93 100644 --- a/include/media/saa7146_vv.h +++ b/include/media/saa7146_vv.h @@ -197,7 +197,8 @@ void saa7146_buffer_finish(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, void saa7146_buffer_next(struct saa7146_dev *dev, struct saa7146_dmaqueue *q,int vbi); int saa7146_buffer_queue(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, struct saa7146_buf *buf); void saa7146_buffer_timeout(unsigned long data); -void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf); +void saa7146_dma_free(struct saa7146_dev* dev,struct videobuf_queue *q, + struct saa7146_buf *buf); int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv); int saa7146_vv_release(struct saa7146_dev* dev); diff --git a/include/media/video-buf.h b/include/media/video-buf.h index d90dec5484ee..fff3fd0fbf94 100644 --- a/include/media/video-buf.h +++ b/include/media/video-buf.h @@ -1,15 +1,20 @@ /* * * generic helper functions for video4linux capture buffers, to handle - * memory management and PCI DMA. Right now bttv + saa7134 use it. + * memory management and PCI DMA. + * Right now, bttv, saa7134, saa7146 and cx88 use it. * * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented * into PAGE_SIZE chunks). They also assume the driver does not need - * to touch the video data (thus it is probably not useful for USB as - * data often must be uncompressed by the drivers). + * to touch the video data. + * + * device specific map/unmap/sync stuff now are mapped as file operations + * to allow its usage by USB and virtual devices. * * (c) 2001,02 Gerd Knorr + * (c) 2006 Mauro Carvalho Chehab, + * (c) 2006 Ted Walther and John Sokol * * 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 @@ -38,6 +43,9 @@ struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages); struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset); +struct videobuf_buffer; +struct videobuf_queue; + /* --------------------------------------------------------------------- */ /* @@ -49,7 +57,7 @@ struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages, * pointer + length. The kernel version just wants the size and * does memory allocation too using vmalloc_32(). * - * videobuf_dma_pci_*() + * videobuf_dma_*() * see Documentation/DMA-mapping.txt, these functions to * basically the same. The map function does also build a * scatterlist for the buffer (and unmap frees it ...) @@ -86,12 +94,18 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, int nr_pages); int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, dma_addr_t addr, int nr_pages); -int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma); -int videobuf_dma_pci_sync(struct pci_dev *dev, - struct videobuf_dmabuf *dma); -int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma); int videobuf_dma_free(struct videobuf_dmabuf *dma); +int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma); +int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma); +int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma); + + /*FIXME: these variants are used only on *-alsa code, where videobuf is + * used without queue + */ +int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma); +int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma); + /* --------------------------------------------------------------------- */ /* @@ -115,9 +129,6 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma); * */ -struct videobuf_buffer; -struct videobuf_queue; - struct videobuf_mapping { unsigned int count; unsigned long start; @@ -164,6 +175,10 @@ struct videobuf_buffer { struct timeval ts; }; +typedef int (vb_map_sg_t)(void *dev,struct scatterlist *sglist,int nr_pages, + int direction); + + struct videobuf_queue_ops { int (*buf_setup)(struct videobuf_queue *q, unsigned int *count, unsigned int *size); @@ -174,12 +189,20 @@ struct videobuf_queue_ops { struct videobuf_buffer *vb); void (*buf_release)(struct videobuf_queue *q, struct videobuf_buffer *vb); + + /* Helper operations - device dependent. + * If null, videobuf_init defaults all to PCI handling + */ + + vb_map_sg_t *vb_map_sg; + vb_map_sg_t *vb_dma_sync_sg; + vb_map_sg_t *vb_unmap_sg; }; struct videobuf_queue { struct mutex lock; spinlock_t *irqlock; - struct pci_dev *pci; + void *dev; /* on pci, points to struct pci_dev */ enum v4l2_buf_type type; unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */ @@ -204,12 +227,15 @@ struct videobuf_queue { void* videobuf_alloc(unsigned int size); int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); -int videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, - struct v4l2_framebuffer *fbuf); +int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, + struct v4l2_framebuffer *fbuf); + +/* Maps fops to PCI stuff */ +void videobuf_queue_pci(struct videobuf_queue* q); void videobuf_queue_init(struct videobuf_queue *q, struct videobuf_queue_ops *ops, - struct pci_dev *pci, + void *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, -- cgit v1.2.3-59-g8ed1b From 1e6dd65e17b8b584026334b16485365bab486422 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 10 Mar 2006 12:40:10 -0300 Subject: V4L/DVB (3518): Creates a virtual video device driver The Virtual Video Device Driver (aka vivi) is a device that can be used to: 1) test core v4l functionalities; 2) be a prototype for newer development. Vivi were developed using the best practices for v4l driver. When loaded, it provides a video device that generates a standard color bar, with a timestamp placed at top left corner. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/font.h | 407 +++++++++++++ drivers/media/video/vivi.c | 1453 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1860 insertions(+) create mode 100644 drivers/media/video/font.h create mode 100644 drivers/media/video/vivi.c (limited to 'drivers') diff --git a/drivers/media/video/font.h b/drivers/media/video/font.h new file mode 100644 index 000000000000..8b1fecc37599 --- /dev/null +++ b/drivers/media/video/font.h @@ -0,0 +1,407 @@ +static unsigned char rom8x16_bits[] = { +/* Character 0 (0x30): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + |** ** | + |** *** | + |** **** | + |**** ** | + |*** ** | + |** ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0xce, +0xde, +0xf6, +0xe6, +0xc6, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, + +/* Character 1 (0x31): + ht=16, width=8 + +--------+ + | | + | | + | ** | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x18, +0x78, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x7e, +0x00, +0x00, +0x00, +0x00, + +/* Character 2 (0x32): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + |** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + |** ** | + |******* | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0x06, +0x0c, +0x18, +0x30, +0x60, +0xc6, +0xfe, +0x00, +0x00, +0x00, +0x00, + +/* Character 3 (0x33): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + | ** | + | ** | + | **** | + | ** | + | ** | + | ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0x06, +0x06, +0x3c, +0x06, +0x06, +0x06, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, + +/* Character 4 (0x34): + ht=16, width=8 + +--------+ + | | + | | + | ** | + | *** | + | **** | + | ** ** | + |** ** | + |** ** | + |******* | + | ** | + | ** | + | **** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x0c, +0x1c, +0x3c, +0x6c, +0xcc, +0xcc, +0xfe, +0x0c, +0x0c, +0x1e, +0x00, +0x00, +0x00, +0x00, + +/* Character 5 (0x35): + ht=16, width=8 + +--------+ + | | + | | + |******* | + |** | + |** | + |** | + |****** | + | ** | + | ** | + | ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0xfe, +0xc0, +0xc0, +0xc0, +0xfc, +0x06, +0x06, +0x06, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, + +/* Character 6 (0x36): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + |** | + |** | + |****** | + |** ** | + |** ** | + |** ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0xc0, +0xc0, +0xfc, +0xc6, +0xc6, +0xc6, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, + +/* Character 7 (0x37): + ht=16, width=8 + +--------+ + | | + | | + |******* | + |** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0xfe, +0xc6, +0x06, +0x0c, +0x18, +0x30, +0x30, +0x30, +0x30, +0x30, +0x00, +0x00, +0x00, +0x00, + +/* Character 8 (0x38): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + |** ** | + |** ** | + | ***** | + |** ** | + |** ** | + |** ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0xc6, +0x7c, +0xc6, +0xc6, +0xc6, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, + +/* Character 9 (0x39): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + |** ** | + |** ** | + |** ** | + | ****** | + | ** | + | ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0xc6, +0xc6, +0x7e, +0x06, +0x06, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, +/* Character : (0x3a): + ht=16, width=8 + +--------+ + | | + | | + | | + | | + | | + | ** | + | ** | + | | + | | + | ** | + | ** | + | | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x00, +0x00, +0x00, +0x0c, +0x0c, +0x00, +0x00, +0x0c, +0x0c, +0x00, +0x00, +0x00, +0x00, +0x00, +}; diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c new file mode 100644 index 000000000000..e2d941bae43e --- /dev/null +++ b/drivers/media/video/vivi.c @@ -0,0 +1,1453 @@ +/* + * Virtual Video driver - This code emulates a real video device with v4l2 api + * + * Copyright (c) 2006 by: + * Mauro Carvalho Chehab + * Ted Walther + * John Sokol + * http://v4l.videotechnology.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the BSD Licence, 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 + +/* Wake up at about 30 fps */ +#define WAKE_NUMERATOR 30 +#define WAKE_DENOMINATOR 1001 +#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ + +/* These timers are for 1 fps - used only for testing */ +//#define WAKE_DENOMINATOR 30 /* hack for testing purposes */ +//#define BUFFER_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */ + +#include "font.h" + +#ifndef kzalloc +#define kzalloc(size, flags) \ +({ \ + void *__ret = kmalloc(size, flags); \ + if (__ret) \ + memset(__ret, 0, size); \ + __ret; \ +}) +#endif + +MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); +MODULE_AUTHOR("Ted Walther and John Sokol"); +MODULE_LICENSE("Dual BSD/GPL"); + +#define VIVI_MAJOR_VERSION 0 +#define VIVI_MINOR_VERSION 4 +#define VIVI_RELEASE 0 +#define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) + +static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ +module_param(video_nr, int, 0); + +static int debug = 0; +module_param(debug, int, 0); + +static unsigned int vid_limit = 16; +module_param(vid_limit,int,0644); +MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); + +/* supported controls */ +static struct v4l2_queryctrl vivi_qctrl[] = { + { + .id = V4L2_CID_AUDIO_VOLUME, + .name = "Volume", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 65535, + .flags = 0, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 127, + .flags = 0, + }, { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 255, + .step = 0x1, + .default_value = 0x10, + .flags = 0, + }, { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0, + .maximum = 255, + .step = 0x1, + .default_value = 127, + .flags = 0, + }, { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Hue", + .minimum = -128, + .maximum = 127, + .step = 0x1, + .default_value = 0, + .flags = 0, + } +}; + +static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; + +#define dprintk(level,fmt, arg...) \ + do { \ + if (debug >= (level)) \ + printk(KERN_DEBUG "vivi: " fmt , ## arg); \ + } while (0) + +/* ------------------------------------------------------------------ + Basic structures + ------------------------------------------------------------------*/ + +struct vivi_fmt { + char *name; + u32 fourcc; /* v4l2 format id */ + int depth; +}; + +static struct vivi_fmt format = { + .name = "4:2:2, packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, +}; + +struct sg_to_addr { + int pos; + struct scatterlist *sg; +}; + +/* buffer for one video frame */ +struct vivi_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + struct vivi_fmt *fmt; + + struct sg_to_addr *to_addr; +}; + +struct vivi_dmaqueue { + struct list_head active; + struct list_head queued; + struct timer_list timeout; + + /* thread for generating video stream*/ + struct task_struct *kthread; + wait_queue_head_t wq; + /* Counters to control fps rate */ + int frame; + int ini_jiffies; +}; + +static LIST_HEAD(vivi_devlist); + +struct vivi_dev { + struct list_head vivi_devlist; + + struct semaphore lock; + + int users; + + /* various device info */ + unsigned int resources; + struct video_device video_dev; + + struct vivi_dmaqueue vidq; + + /* Several counters */ + int h,m,s,us,jiffies; + char timestr[13]; +}; + +struct vivi_fh { + struct vivi_dev *dev; + + /* video capture */ + struct vivi_fmt *fmt; + unsigned int width,height; + struct videobuf_queue vb_vidq; + + enum v4l2_buf_type type; +}; + +/* ------------------------------------------------------------------ + DMA and thread functions + ------------------------------------------------------------------*/ + +/* Bars and Colors should match positions */ + +enum colors { + WHITE, + AMBAR, + CYAN, + GREEN, + MAGENTA, + RED, + BLUE +}; + +static u8 bars[8][3] = { + /* R G B */ + {204,204,204}, /* white */ + {208,208, 0}, /* ambar */ + { 0,206,206}, /* cyan */ + { 0,239, 0}, /* green */ + {239, 0,239}, /* magenta */ + {205, 0, 0}, /* red */ + { 0, 0,255}, /* blue */ + { 0, 0, 0} +}; + +#define TO_Y(r,g,b) (((16829*r +33039*g +6416*b + 32768)>>16)+16) +/* RGB to V(Cr) Color transform */ +#define TO_V(r,g,b) (((28784*r -24103*g -4681*b + 32768)>>16)+128) +/* RGB to U(Cb) Color transform */ +#define TO_U(r,g,b) (((-9714*r -19070*g +28784*b + 32768)>>16)+128) + +#define TSTAMP_MIN_Y 24 +#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 +#define TSTAMP_MIN_X 64 + +void prep_to_addr(struct sg_to_addr to_addr[],struct videobuf_buffer *vb) +{ + int i, pos=0; + + for (i=0;idma.nr_pages;i++) { + to_addr[i].sg=&vb->dma.sglist[i]; + to_addr[i].pos=pos; + pos += vb->dma.sglist[i].length; + } +} + +inline int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) +{ + int p1=0,p2=pages-1,p3=pages/2; + + /* Sanity test */ + BUG_ON (pos>=to_addr[p2].pos+to_addr[p2].sg->length); + + while (p1+1= to_addr[p2].pos) + p1=p2; + + return (p1); +} + +void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, + int hmax, int line, char *timestr) +{ + int w,i,j,pos=inipos,pgpos,oldpg,y; + char *p,*s,*basep; + struct page *pg; + u8 chr,r,g,b,color; + + /* Get first addr pointed to pixel position */ + oldpg=get_addr_pos(pos,pages,to_addr); + pg=pfn_to_page(to_addr[oldpg].sg->dma_address >> PAGE_SHIFT); + basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset; + + /* We will just duplicate the second pixel at the packet */ + wmax/=2; + + /* Generate a standard color bar pattern */ + for (w=0;wdma_address >> PAGE_SHIFT); + kunmap_atomic(basep, KM_BOUNCE_READ); + basep= kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[pgpos].sg->offset; + oldpg=pgpos; + } + p=basep+pos-to_addr[pgpos].pos; + + switch (color) { + case 0: + case 2: + *p=TO_Y(r,g,b); /* Luminance */ + break; + case 1: + *p=TO_U(r,g,b); /* Cb */ + break; + case 3: + *p=TO_V(r,g,b); /* Cr */ + break; + } + pos++; + } + } + + /* Checks if it is possible to show timestamp */ + if (TSTAMP_MAX_Y>=hmax) + goto end; + if (TSTAMP_MIN_X+strlen(timestr)>=wmax) + goto end; + + /* Print stream time */ + if (line>=TSTAMP_MIN_Y && line<=TSTAMP_MAX_Y) { + j=TSTAMP_MIN_X; + for (s=timestr;*s;s++) { + chr=rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y]; + for (i=0;i<7;i++) { + if (chr&1<<(7-i)) { /* Font color*/ + r=bars[BLUE][0]; + g=bars[BLUE][1]; + b=bars[BLUE][2]; + r=g=b=0; + g=198; + } else { /* Background color */ + r=bars[WHITE][0]; + g=bars[WHITE][1]; + b=bars[WHITE][2]; + r=g=b=0; + } + + pos=inipos+j*2; + for (color=0;color<4;color++) { + pgpos=get_addr_pos(pos,pages,to_addr); + if (pgpos!=oldpg) { + pg=pfn_to_page(to_addr[pgpos]. + sg->dma_address + >> PAGE_SHIFT); + kunmap_atomic(basep, + KM_BOUNCE_READ); + basep= kmap_atomic(pg, + KM_BOUNCE_READ)+ + to_addr[pgpos].sg->offset; + oldpg=pgpos; + } + p=basep+pos-to_addr[pgpos].pos; + + y=TO_Y(r,g,b); + + switch (color) { + case 0: + case 2: + *p=TO_Y(r,g,b); /* Luminance */ + break; + case 1: + *p=TO_U(r,g,b); /* Cb */ + break; + case 3: + *p=TO_V(r,g,b); /* Cr */ + break; + } + pos++; + } + j++; + } + } + } + + +end: + kunmap_atomic(basep, KM_BOUNCE_READ); +} +static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) +{ + int h,pos=0; + int hmax = buf->vb.height; + int wmax = buf->vb.width; + struct videobuf_buffer *vb=&buf->vb; + struct sg_to_addr *to_addr=buf->to_addr; + struct timeval ts; + + /* Test if DMA mapping is ready */ + if (!vb->dma.sglist[0].dma_address) + return; + + prep_to_addr(to_addr,vb); + + /* Check if there is enough memory */ + BUG_ON(buf->vb.dma.nr_pages << PAGE_SHIFT < (buf->vb.width*buf->vb.height)*2); + + for (h=0;hdma.nr_pages,wmax,hmax,h,dev->timestr); + pos += wmax*2; + } + + /* Updates stream time */ + + dev->us+=jiffies_to_usecs(jiffies-dev->jiffies); + dev->jiffies=jiffies; + if (dev->us>=1000000) { + dev->us-=1000000; + dev->s++; + if (dev->s>=60) { + dev->s-=60; + dev->m++; + if (dev->m>60) { + dev->m-=60; + dev->h++; + if (dev->h>24) + dev->h-=24; + } + } + } + sprintf(dev->timestr,"%02d:%02d:%02d:%03d", + dev->h,dev->m,dev->s,(dev->us+500)/1000); + + dprintk(2,"vivifill at %s: Buffer 0x%08lx size= %d\n",dev->timestr, + (unsigned long)buf->vb.dma.vmalloc,pos); + + /* Advice that buffer was filled */ + buf->vb.state = STATE_DONE; + buf->vb.field_count++; + do_gettimeofday(&ts); + buf->vb.ts = ts; + + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); +} + +static int restart_video_queue(struct vivi_dmaqueue *dma_q); + +static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) +{ + struct vivi_buffer *buf; + struct vivi_dev *dev= container_of(dma_q,struct vivi_dev,vidq); + + int bc; + + /* Announces videobuf that all went ok */ + for (bc = 0;; bc++) { + if (list_empty(&dma_q->active)) { + dprintk(1,"No active queue to serve\n"); + break; + } + + buf = list_entry(dma_q->active.next, + struct vivi_buffer, vb.queue); + + /* Nobody is waiting something to be done, just return */ + if (!waitqueue_active(&buf->vb.done)) { + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + return; + } + + do_gettimeofday(&buf->vb.ts); + dprintk(2,"[%p/%d] wakeup\n",buf,buf->vb.i); + + /* Fill buffer */ + vivi_fillbuff(dev,buf); + } + if (list_empty(&dma_q->active)) { + del_timer(&dma_q->timeout); + } else { + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + } + if (bc != 1) + dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc); +} + +void vivi_sleep(struct vivi_dmaqueue *dma_q) +{ + int timeout; + DECLARE_WAITQUEUE(wait, current); + + dprintk(1,"%s dma_q=0x%08lx\n",__FUNCTION__,(unsigned long)dma_q); + + add_wait_queue(&dma_q->wq, &wait); + if (!kthread_should_stop()) { + dma_q->frame++; + + /* Calculate time to wake up */ + timeout=dma_q->ini_jiffies+msecs_to_jiffies((dma_q->frame*WAKE_NUMERATOR*1000)/WAKE_DENOMINATOR)-jiffies; + + if (timeout <= 0) { + int old=dma_q->frame; + dma_q->frame=(jiffies_to_msecs(jiffies-dma_q->ini_jiffies)*WAKE_DENOMINATOR)/(WAKE_NUMERATOR*1000)+1; + + timeout=dma_q->ini_jiffies+msecs_to_jiffies((dma_q->frame*WAKE_NUMERATOR*1000)/WAKE_DENOMINATOR)-jiffies; + + dprintk(1,"underrun, losed %d frames. " + "Now, frame is %d. Waking on %d jiffies\n", + dma_q->frame-old,dma_q->frame,timeout); + } else + dprintk(1,"will sleep for %i jiffies\n",timeout); + + vivi_thread_tick(dma_q); + + schedule_timeout_interruptible (timeout); + } + + remove_wait_queue(&dma_q->wq, &wait); + try_to_freeze(); +} + +int vivi_thread(void *data) +{ + struct vivi_dmaqueue *dma_q=data; + + dprintk(1,"thread started\n"); + + for (;;) { + vivi_sleep(dma_q); + + if (kthread_should_stop()) + break; + } + dprintk(1, "thread: exit\n"); + return 0; +} + +int vivi_start_thread(struct vivi_dmaqueue *dma_q) +{ + dma_q->frame=0; + dma_q->ini_jiffies=jiffies; + + dprintk(1,"%s\n",__FUNCTION__); + init_waitqueue_head(&dma_q->wq); + + dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi"); + + if (dma_q->kthread == NULL) { + printk(KERN_ERR "vivi: kernel_thread() failed\n"); + return -EINVAL; + } + dprintk(1,"returning from %s\n",__FUNCTION__); + return 0; +} + +void vivi_stop_thread(struct vivi_dmaqueue *dma_q) +{ + dprintk(1,"%s\n",__FUNCTION__); + /* shutdown control thread */ + if (dma_q->kthread) { + kthread_stop(dma_q->kthread); + dma_q->kthread=NULL; + } +} + +static int restart_video_queue(struct vivi_dmaqueue *dma_q) +{ + struct vivi_buffer *buf, *prev; + struct list_head *item; + + dprintk(1,"%s dma_q=0x%08lx\n",__FUNCTION__,(unsigned long)dma_q); + + if (!list_empty(&dma_q->active)) { + buf = list_entry(dma_q->active.next, struct vivi_buffer, vb.queue); + dprintk(2,"restart_queue [%p/%d]: restart dma\n", + buf, buf->vb.i); + + dprintk(1,"Restarting video dma\n"); + vivi_stop_thread(dma_q); +// vivi_start_thread(dma_q); + + /* cancel all outstanding capture / vbi requests */ + list_for_each(item,&dma_q->active) { + buf = list_entry(item, struct vivi_buffer, vb.queue); + + list_del(&buf->vb.queue); + buf->vb.state = STATE_ERROR; + wake_up(&buf->vb.done); + } + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + + return 0; + } + + prev = NULL; + for (;;) { + if (list_empty(&dma_q->queued)) + return 0; + buf = list_entry(dma_q->queued.next, struct vivi_buffer, vb.queue); + if (NULL == prev) { + list_del(&buf->vb.queue); + list_add_tail(&buf->vb.queue,&dma_q->active); + + dprintk(1,"Restarting video dma\n"); + vivi_stop_thread(dma_q); + vivi_start_thread(dma_q); + + buf->vb.state = STATE_ACTIVE; + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2,"[%p/%d] restart_queue - first active\n", + buf,buf->vb.i); + + } else if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_del(&buf->vb.queue); + list_add_tail(&buf->vb.queue,&dma_q->active); + buf->vb.state = STATE_ACTIVE; + dprintk(2,"[%p/%d] restart_queue - move to active\n", + buf,buf->vb.i); + } else { + return 0; + } + prev = buf; + } +} + +static void vivi_vid_timeout(unsigned long data) +{ + struct vivi_dev *dev = (struct vivi_dev*)data; + struct vivi_dmaqueue *vidq = &dev->vidq; + struct vivi_buffer *buf; + + while (!list_empty(&vidq->active)) { + buf = list_entry(vidq->active.next, struct vivi_buffer, vb.queue); + list_del(&buf->vb.queue); + buf->vb.state = STATE_ERROR; + wake_up(&buf->vb.done); + printk("vivi/0: [%p/%d] timeout\n", buf, buf->vb.i); + } + + restart_video_queue(vidq); +} + +/* ------------------------------------------------------------------ + Videobuf operations + ------------------------------------------------------------------*/ +static int +buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) +{ + struct vivi_fh *fh = vq->priv_data; + + *size = fh->width*fh->height*2; + + if (0 == *count) + *count = 32; + while (*size * *count > vid_limit * 1024 * 1024) + (*count)--; + return 0; +} + +void +free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) +{ + dprintk(1,"%s\n",__FUNCTION__); + + if (in_interrupt()) + BUG(); + + /*FIXME: Maybe a spinlock is required here */ + kfree(buf->to_addr); + buf->to_addr=NULL; + + videobuf_waiton(&buf->vb,0,0); + videobuf_dma_unmap(vq, &buf->vb.dma); + videobuf_dma_free(&buf->vb.dma); + buf->vb.state = STATE_NEEDS_INIT; +} + +#define norm_maxw() 1024 +#define norm_maxh() 768 +static int +buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct vivi_fh *fh = vq->priv_data; + struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb); + int rc, init_buffer = 0; + +// dprintk(1,"%s, field=%d\n",__FUNCTION__,field); + + BUG_ON(NULL == fh->fmt); + if (fh->width < 48 || fh->width > norm_maxw() || + fh->height < 32 || fh->height > norm_maxh()) + return -EINVAL; + buf->vb.size = fh->width*fh->height*2; + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + if (buf->fmt != fh->fmt || + buf->vb.width != fh->width || + buf->vb.height != fh->height || + buf->vb.field != field) { + buf->fmt = fh->fmt; + buf->vb.width = fh->width; + buf->vb.height = fh->height; + buf->vb.field = field; + init_buffer = 1; + } + + if (STATE_NEEDS_INIT == buf->vb.state) { + if (0 != (rc = videobuf_iolock(vq,&buf->vb,NULL))) + goto fail; + } + + buf->vb.state = STATE_PREPARED; + + if (NULL == (buf->to_addr = kmalloc(sizeof(*buf->to_addr) * vb->dma.nr_pages,GFP_KERNEL))) { + rc=-ENOMEM; + goto fail; + } + + return 0; + +fail: + free_buffer(vq,buf); + return rc; +} + +static void +buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb); + struct vivi_fh *fh = vq->priv_data; + struct vivi_dev *dev = fh->dev; + struct vivi_dmaqueue *vidq = &dev->vidq; + struct vivi_buffer *prev; + + if (!list_empty(&vidq->queued)) { + dprintk(1,"adding vb queue=0x%08lx\n",(unsigned long)&buf->vb.queue); + list_add_tail(&buf->vb.queue,&vidq->queued); + buf->vb.state = STATE_QUEUED; + dprintk(2,"[%p/%d] buffer_queue - append to queued\n", + buf, buf->vb.i); + } else if (list_empty(&vidq->active)) { + list_add_tail(&buf->vb.queue,&vidq->active); + + buf->vb.state = STATE_ACTIVE; + mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2,"[%p/%d] buffer_queue - first active\n", + buf, buf->vb.i); + + vivi_start_thread(vidq); + } else { + prev = list_entry(vidq->active.prev, struct vivi_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue,&vidq->active); + buf->vb.state = STATE_ACTIVE; + dprintk(2,"[%p/%d] buffer_queue - append to active\n", + buf, buf->vb.i); + + } else { + list_add_tail(&buf->vb.queue,&vidq->queued); + buf->vb.state = STATE_QUEUED; + dprintk(2,"[%p/%d] buffer_queue - first queued\n", + buf, buf->vb.i); + } + } +} + +static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb); + struct vivi_fh *fh = vq->priv_data; + struct vivi_dev *dev = (struct vivi_dev*)fh->dev; + struct vivi_dmaqueue *vidq = &dev->vidq; + + dprintk(1,"%s\n",__FUNCTION__); + + vivi_stop_thread(vidq); + + free_buffer(vq,buf); +} + +int vivi_map_sg (void *dev, struct scatterlist *sg, int nents, + int direction) +{ + int i; + + dprintk(1,"%s, number of pages=%d\n",__FUNCTION__,nents); + BUG_ON(direction == DMA_NONE); + + for (i = 0; i < nents; i++ ) { + BUG_ON(!sg[i].page); + + sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset; + } + + return nents; +} + +int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages, + int direction) +{ + dprintk(1,"%s\n",__FUNCTION__); + return 0; +} + +int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist,int nr_pages, + int direction) +{ +// dprintk(1,"%s\n",__FUNCTION__); + +// flush_write_buffers(); + return 0; +} + +static struct videobuf_queue_ops vivi_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, + + /* Non-pci handling routines */ + .vb_map_sg = vivi_map_sg, + .vb_dma_sync_sg = vivi_dma_sync_sg, + .vb_unmap_sg = vivi_unmap_sg, +}; + +/* ------------------------------------------------------------------ + IOCTL handling + ------------------------------------------------------------------*/ + +static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, + struct v4l2_format *f) +{ + struct vivi_fmt *fmt; + enum v4l2_field field; + unsigned int maxw, maxh; + + if (format.fourcc != f->fmt.pix.pixelformat) { + dprintk(1,"Fourcc format invalid.\n"); + return -EINVAL; + } + fmt=&format; + + field = f->fmt.pix.field; + + if (field == V4L2_FIELD_ANY) { +// field=V4L2_FIELD_INTERLACED; + field=V4L2_FIELD_SEQ_TB; + } else if (V4L2_FIELD_INTERLACED != field) { + dprintk(1,"Field type invalid.\n"); + return -EINVAL; + } + + maxw = norm_maxw(); + maxh = norm_maxh(); + + f->fmt.pix.field = field; + if (f->fmt.pix.height < 32) + f->fmt.pix.height = 32; + if (f->fmt.pix.height > maxh) + f->fmt.pix.height = maxh; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > maxw) + f->fmt.pix.width = maxw; + f->fmt.pix.width &= ~0x03; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; +} + +static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) +{ + /* is it free? */ + down(&dev->lock); + if (dev->resources) { + /* no, someone else uses it */ + up(&dev->lock); + return 0; + } + /* it's free, grab it */ + dev->resources =1; + dprintk(1,"res: get\n"); + up(&dev->lock); + return 1; +} + +static inline int res_locked(struct vivi_dev *dev) +{ + return (dev->resources); +} + +static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) +{ + down(&dev->lock); + dev->resources = 0; + dprintk(1,"res: put\n"); + up(&dev->lock); +} + +static int vivi_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) +{ + struct vivi_fh *fh = file->private_data; + struct vivi_dev *dev = fh->dev; + int ret=0; + + if (debug) { + if (_IOC_DIR(cmd) & _IOC_WRITE) + v4l_printk_ioctl_arg("vivi(w)",cmd, arg); + else if (!_IOC_DIR(cmd) & _IOC_READ) { + v4l_print_ioctl("vivi", cmd); + } + } + + switch(cmd) { + /* --- capabilities ------------------------------------------ */ + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = (struct v4l2_capability*)arg; + + memset(cap, 0, sizeof(*cap)); + + strcpy(cap->driver, "vivi"); + strcpy(cap->card, "vivi"); + cap->version = VIVI_VERSION; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + break; + } + /* --- capture ioctls ---------------------------------------- */ + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *f = arg; + enum v4l2_buf_type type; + unsigned int index; + + index = f->index; + type = f->type; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + + switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (index > 0){ + ret=-EINVAL; + break; + } + memset(f,0,sizeof(*f)); + + f->index = index; + f->type = type; + strlcpy(f->description,format.name,sizeof(f->description)); + f->pixelformat = format.fourcc; + break; + default: + ret=-EINVAL; + } + break; + } + case VIDIOC_G_FMT: + { + struct v4l2_format *f = (struct v4l2_format *)arg; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + + memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); + f->fmt.pix.width = fh->width; + f->fmt.pix.height = fh->height; + f->fmt.pix.field = fh->vb_vidq.field; + f->fmt.pix.pixelformat = fh->fmt->fourcc; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fh->fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + break; + } + case VIDIOC_S_FMT: + { + struct v4l2_format *f = arg; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dprintk(1,"Only capture supported.\n"); + ret=-EINVAL; + break; + } + + ret = vivi_try_fmt(dev,fh,f); + if (ret < 0) + break; + + fh->fmt = &format; + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vb_vidq.field = f->fmt.pix.field; + fh->type = f->type; + + break; + } + case VIDIOC_TRY_FMT: + { + struct v4l2_format *f = arg; + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + + ret=vivi_try_fmt(dev,fh,f); + break; + } + case VIDIOC_REQBUFS: + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + ret=videobuf_reqbufs(&fh->vb_vidq, arg); + break; + case VIDIOC_QUERYBUF: + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + ret=videobuf_querybuf(&fh->vb_vidq, arg); + break; + case VIDIOC_QBUF: + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + ret=videobuf_qbuf(&fh->vb_vidq, arg); + break; + case VIDIOC_DQBUF: + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + ret=videobuf_dqbuf(&fh->vb_vidq, arg, + file->f_flags & O_NONBLOCK); + break; +#ifdef HAVE_V4L1 + /* --- streaming capture ------------------------------------- */ + case VIDIOCGMBUF: + { + struct video_mbuf *mbuf = arg; + struct videobuf_queue *q=&fh->vb_vidq; + struct v4l2_requestbuffers req; + unsigned int i; + + memset(&req,0,sizeof(req)); + req.type = q->type; + req.count = 8; + req.memory = V4L2_MEMORY_MMAP; + ret = videobuf_reqbufs(q,&req); + if (ret < 0) + break; + memset(mbuf,0,sizeof(*mbuf)); + mbuf->frames = req.count; + mbuf->size = 0; + for (i = 0; i < mbuf->frames; i++) { + mbuf->offsets[i] = q->bufs[i]->boff; + mbuf->size += q->bufs[i]->bsize; + } + break; + } +#endif + case VIDIOC_STREAMON: + { + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (!res_get(dev,fh)) + return -EBUSY; + ret=videobuf_streamon(&fh->vb_vidq); + break; + } + case VIDIOC_STREAMOFF: + { + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + ret = videobuf_streamoff(&fh->vb_vidq); + if (ret < 0) + break; + res_free(dev,fh); + break; + } + /* ---------- tv norms ---------- */ + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *e = arg; + + if (e->index>0) { + ret=-EINVAL; + break; + } + ret = v4l2_video_std_construct(e, V4L2_STD_NTSC_M, "NTSC-M"); + + /* Allows vivi to use different fps from video std */ + e->frameperiod.numerator = WAKE_NUMERATOR; + e->frameperiod.denominator = WAKE_DENOMINATOR; + + break; + } + case VIDIOC_G_STD: + { + v4l2_std_id *id = arg; + + *id = V4L2_STD_NTSC_M; + break; + } + case VIDIOC_S_STD: + { + break; + } + /* ------ input switching ---------- */ + case VIDIOC_ENUMINPUT: + { /* only one input in this sample driver */ + struct v4l2_input *inp = arg; + + if (inp->index != 0) { + ret=-EINVAL; + break; + } + memset(inp, 0, sizeof(*inp)); + + inp->index = 0; + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_NTSC_M; + strcpy(inp->name,"Camera"); + break; + } + case VIDIOC_G_INPUT: + { + unsigned int *i = arg; + + *i = 0; + break; + } + case VIDIOC_S_INPUT: + { + unsigned int *i = arg; + + if (*i > 0) + ret=-EINVAL; + break; + } + + /* --- controls ---------------------------------------------- */ + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + int i; + + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + if (qc->id && qc->id == vivi_qctrl[i].id) { + memcpy(qc, &(vivi_qctrl[i]), + sizeof(*qc)); + break; + } + + ret=-EINVAL; + break; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + int i; + + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + if (ctrl->id == vivi_qctrl[i].id) { + ctrl->value=qctl_regs[i]; + break; + } + + ret=-EINVAL; + break; + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + int i; + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + if (ctrl->id == vivi_qctrl[i].id) { + if (ctrl->value < + vivi_qctrl[i].minimum + || ctrl->value > + vivi_qctrl[i].maximum) { + ret=-ERANGE; + break; + } + qctl_regs[i]=ctrl->value; + break; + } + ret=-EINVAL; + break; + } + default: + ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,vivi_do_ioctl); + } + + if (debug) { + if (ret<0) { + v4l_print_ioctl("vivi(err)", cmd); + dprintk(1,"errcode=%d\n",ret); + } else if (_IOC_DIR(cmd) & _IOC_READ) + v4l_printk_ioctl_arg("vivi(r)",cmd, arg); + } + + return ret; +} + +static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl); +} + +/* ------------------------------------------------------------------ + File operations for the device + ------------------------------------------------------------------*/ + +#define line_buf_size(norm) (norm_maxw(norm)*(format.depth+7)/8) + +static int vivi_open(struct inode *inode, struct file *file) +{ + int minor = iminor(inode); + struct vivi_dev *h,*dev = NULL; + struct vivi_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + int i; + + printk(KERN_DEBUG "vivi: open called (minor=%d)\n",minor); + + list_for_each(list,&vivi_devlist) { + h = list_entry(list, struct vivi_dev, vivi_devlist); + if (h->video_dev.minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + if (NULL == dev) + return -ENODEV; + + + /* If more than one user, mutex should be added */ + dev->users++; + + dprintk(1,"open minor=%d type=%s users=%d\n", + minor,v4l2_type_names[type],dev->users); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh),GFP_KERNEL); + if (NULL == fh) { + dev->users--; + return -ENOMEM; + } + + file->private_data = fh; + fh->dev = dev; + fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fh->fmt = &format; + fh->width = 640; + fh->height = 480; + + /* Put all controls at a sane state */ + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + qctl_regs[i] =vivi_qctrl[i].default_value; + + dprintk(1,"Open: fh=0x%08lx, dev=0x%08lx, dev->vidq=0x%08lx\n", + (unsigned long)fh,(unsigned long)dev,(unsigned long)&dev->vidq); + dprintk(1,"Open: list_empty queued=%d\n",list_empty(&dev->vidq.queued)); + dprintk(1,"Open: list_empty active=%d\n",list_empty(&dev->vidq.active)); + + /* Resets frame counters */ + dev->h=0; + dev->m=0; + dev->s=0; + dev->us=0; + dev->jiffies=jiffies; + sprintf(dev->timestr,"%02d:%02d:%02d:%03d", + dev->h,dev->m,dev->s,(dev->us+500)/1000); + + videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops, + NULL, NULL, + fh->type, + V4L2_FIELD_INTERLACED, + sizeof(struct vivi_buffer),fh); + + return 0; +} + +static ssize_t +vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct vivi_fh *fh = file->private_data; + + if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (res_locked(fh->dev)) + return -EBUSY; + return videobuf_read_one(&fh->vb_vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); + } + return 0; +} + +static unsigned int +vivi_poll(struct file *file, struct poll_table_struct *wait) +{ + struct vivi_fh *fh = file->private_data; + struct vivi_buffer *buf; + + dprintk(1,"%s\n",__FUNCTION__); + + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) + return POLLERR; + + if (res_get(fh->dev,fh)) { + dprintk(1,"poll: mmap interface\n"); + /* streaming capture */ + if (list_empty(&fh->vb_vidq.stream)) + return POLLERR; + buf = list_entry(fh->vb_vidq.stream.next,struct vivi_buffer,vb.stream); + } else { + dprintk(1,"poll: read() interface\n"); + /* read() capture */ + buf = (struct vivi_buffer*)fh->vb_vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == STATE_DONE || + buf->vb.state == STATE_ERROR) + return POLLIN|POLLRDNORM; + return 0; +} + +static int vivi_release(struct inode *inode, struct file *file) +{ + struct vivi_fh *fh = file->private_data; + struct vivi_dev *dev = fh->dev; + struct vivi_dmaqueue *vidq = &dev->vidq; + + int minor = iminor(inode); + + vivi_stop_thread(vidq); + videobuf_mmap_free(&fh->vb_vidq); + + kfree (fh); + + dev->users--; + + printk(KERN_DEBUG "vivi: close called (minor=%d, users=%d)\n",minor,dev->users); + + return 0; +} + +static int +vivi_mmap(struct file *file, struct vm_area_struct * vma) +{ + struct vivi_fh *fh = file->private_data; + int ret; + + dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma); + + ret=videobuf_mmap_mapper(&fh->vb_vidq, vma); + + dprintk (1,"vma start=0x%08lx, size=%ld, ret=%d\n", + (unsigned long)vma->vm_start, + (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, + ret); + + return ret; +} + +static struct file_operations vivi_fops = { + .owner = THIS_MODULE, + .open = vivi_open, + .release = vivi_release, + .read = vivi_read, + .poll = vivi_poll, + .ioctl = vivi_ioctl, + .mmap = vivi_mmap, + .llseek = no_llseek, +}; + +static struct video_device vivi = { + .name = "VTM Virtual Video Capture Board", + .type = VID_TYPE_CAPTURE, + .hardware = 0, + .fops = &vivi_fops, + .minor = -1, +// .release = video_device_release, +}; +/* ------------------------------------------------------------------ + Initialization and module stuff + ------------------------------------------------------------------*/ + +static int __init vivi_init(void) +{ + int ret; + struct vivi_dev *dev; + + dev = kzalloc(sizeof(*dev),GFP_KERNEL); + if (NULL == dev) + return -ENOMEM; + list_add_tail(&dev->vivi_devlist,&vivi_devlist); + + /* init video dma queues */ + INIT_LIST_HEAD(&dev->vidq.active); + INIT_LIST_HEAD(&dev->vidq.queued); + + /* initialize locks */ + init_MUTEX(&dev->lock); + + dev->vidq.timeout.function = vivi_vid_timeout; + dev->vidq.timeout.data = (unsigned long)dev; + init_timer(&dev->vidq.timeout); + + ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr); + printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret); + return ret; +} + +static void __exit vivi_exit(void) +{ + struct vivi_dev *h; + struct list_head *list; + + list_for_each(list,&vivi_devlist) { + h = list_entry(list, struct vivi_dev, vivi_devlist); + kfree (h); + } + video_unregister_device(&vivi); +} + +module_init(vivi_init); +module_exit(vivi_exit); -- cgit v1.2.3-59-g8ed1b From 280323ddbc595c463f89c30f3f0f823b076bb4e3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 10 Mar 2006 13:41:26 -0300 Subject: V4L/DVB (3519): Corrects MODULE_AUTHOR Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index e2d941bae43e..e9bb5dad84d5 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -53,7 +53,7 @@ #endif MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); -MODULE_AUTHOR("Ted Walther and John Sokol"); +MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); MODULE_LICENSE("Dual BSD/GPL"); #define VIVI_MAJOR_VERSION 0 -- cgit v1.2.3-59-g8ed1b From faecfb1760325613debd8df9b9374ce4a28c01d9 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 17 Mar 2006 12:07:22 -0300 Subject: V4L/DVB (3539): Move bttv fragments to bt8xx/ Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 26 +- drivers/media/video/Makefile | 7 +- drivers/media/video/bt832.c | 266 -- drivers/media/video/bt832.h | 305 -- drivers/media/video/bt848.h | 366 --- drivers/media/video/bt8xx/Kconfig | 25 + drivers/media/video/bt8xx/bt832.c | 266 ++ drivers/media/video/bt8xx/bt832.h | 305 ++ drivers/media/video/bt8xx/bt848.h | 366 +++ drivers/media/video/bt8xx/bttv-cards.c | 5011 +++++++++++++++++++++++++++++++ drivers/media/video/bt8xx/bttv-driver.c | 4265 ++++++++++++++++++++++++++ drivers/media/video/bt8xx/bttv-gpio.c | 208 ++ drivers/media/video/bt8xx/bttv-i2c.c | 474 +++ drivers/media/video/bt8xx/bttv-if.c | 159 + drivers/media/video/bt8xx/bttv-input.c | 450 +++ drivers/media/video/bt8xx/bttv-risc.c | 795 +++++ drivers/media/video/bt8xx/bttv-vbi.c | 221 ++ drivers/media/video/bt8xx/bttv.h | 407 +++ drivers/media/video/bt8xx/bttvp.h | 411 +++ drivers/media/video/bttv-cards.c | 5011 ------------------------------- drivers/media/video/bttv-driver.c | 4265 -------------------------- drivers/media/video/bttv-gpio.c | 208 -- drivers/media/video/bttv-i2c.c | 474 --- drivers/media/video/bttv-if.c | 159 - drivers/media/video/bttv-input.c | 450 --- drivers/media/video/bttv-risc.c | 795 ----- drivers/media/video/bttv-vbi.c | 221 -- drivers/media/video/bttv.h | 407 --- drivers/media/video/bttvp.h | 411 --- 29 files changed, 13366 insertions(+), 13368 deletions(-) delete mode 100644 drivers/media/video/bt832.c delete mode 100644 drivers/media/video/bt832.h delete mode 100644 drivers/media/video/bt848.h create mode 100644 drivers/media/video/bt8xx/Kconfig create mode 100644 drivers/media/video/bt8xx/bt832.c create mode 100644 drivers/media/video/bt8xx/bt832.h create mode 100644 drivers/media/video/bt8xx/bt848.h create mode 100644 drivers/media/video/bt8xx/bttv-cards.c create mode 100644 drivers/media/video/bt8xx/bttv-driver.c create mode 100644 drivers/media/video/bt8xx/bttv-gpio.c create mode 100644 drivers/media/video/bt8xx/bttv-i2c.c create mode 100644 drivers/media/video/bt8xx/bttv-if.c create mode 100644 drivers/media/video/bt8xx/bttv-input.c create mode 100644 drivers/media/video/bt8xx/bttv-risc.c create mode 100644 drivers/media/video/bt8xx/bttv-vbi.c create mode 100644 drivers/media/video/bt8xx/bttv.h create mode 100644 drivers/media/video/bt8xx/bttvp.h delete mode 100644 drivers/media/video/bttv-cards.c delete mode 100644 drivers/media/video/bttv-driver.c delete mode 100644 drivers/media/video/bttv-gpio.c delete mode 100644 drivers/media/video/bttv-i2c.c delete mode 100644 drivers/media/video/bttv-if.c delete mode 100644 drivers/media/video/bttv-input.c delete mode 100644 drivers/media/video/bttv-risc.c delete mode 100644 drivers/media/video/bttv-vbi.c delete mode 100644 drivers/media/video/bttv.h delete mode 100644 drivers/media/video/bttvp.h (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index c622a4da5663..b3d3b22d3f78 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -16,31 +16,7 @@ config VIDEO_ADV_DEBUG V4L devices. In doubt, say N. -config VIDEO_BT848 - tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C - select I2C_ALGOBIT - select FW_LOADER - select VIDEO_BTCX - select VIDEO_BUF - select VIDEO_IR - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEO_MSP3400 - ---help--- - Support for BT848 based frame grabber/overlay boards. This includes - the Miro, Hauppauge and STB boards. Please read the material in - for more information. - - To compile this driver as a module, choose M here: the - module will be called bttv. - -config VIDEO_BT848_DVB - bool "DVB/ATSC Support for bt878 based TV cards" - depends on VIDEO_BT848 && DVB_CORE - select DVB_BT8XX - ---help--- - This adds support for DVB/ATSC cards based on the BT878 chip. +source "drivers/media/video/bt8xx/Kconfig" config VIDEO_SAA6588 tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index f2bd4c0c4f10..1a56a2d9e294 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -2,9 +2,6 @@ # Makefile for the video capture/playback device drivers. # -bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ - bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \ - bttv-input.o zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o @@ -15,8 +12,8 @@ msp3400-objs := msp3400-driver.o msp3400-kthreads.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o -obj-$(CONFIG_VIDEO_BT848) += bttv.o tvaudio.o \ - tda7432.o tda9875.o ir-kbd-i2c.o +obj-$(CONFIG_VIDEO_BT848) += bt8xx/ +obj-$(CONFIG_VIDEO_BT848) += tvaudio.o tda7432.o tda9875.o ir-kbd-i2c.o obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o obj-$(CONFIG_VIDEO_ZR36120) += zoran.o diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c deleted file mode 100644 index cc54b62f4601..000000000000 --- a/drivers/media/video/bt832.c +++ /dev/null @@ -1,266 +0,0 @@ -/* Driver for Bt832 CMOS Camera Video Processor - i2c-addresses: 0x88 or 0x8a - - The BT832 interfaces to a Quartzsight Digital Camera (352x288, 25 or 30 fps) - via a 9 pin connector ( 4-wire SDATA, 2-wire i2c, SCLK, VCC, GND). - It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly - connected to bt848/bt878 GPIO pins on this purpose. - (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets) - - Supported Cards: - - Pixelview Rev.4E: 0x8a - GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 ! - - (c) Gunther Mayer, 2002 - - STATUS: - - detect chip and hexdump - - reset chip and leave low power mode - - detect camera present - - TODO: - - make it work (find correct setup for Bt832 and Bt878) -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "bt832.h" - -MODULE_LICENSE("GPL"); - -/* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1, - I2C_CLIENT_END }; -I2C_CLIENT_INSMOD; - -int debug; /* debug output */ -module_param(debug, int, 0644); - -/* ---------------------------------------------------------------------- */ - -static int bt832_detach(struct i2c_client *client); - - -static struct i2c_driver driver; -static struct i2c_client client_template; - -struct bt832 { - struct i2c_client client; -}; - -int bt832_hexdump(struct i2c_client *i2c_client_s, unsigned char *buf) -{ - int i,rc; - buf[0]=0x80; // start at register 0 with auto-increment - if (1 != (rc = i2c_master_send(i2c_client_s,buf,1))) - v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 1)\n",rc); - - for(i=0;i<65;i++) - buf[i]=0; - if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65))) - v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 65)\n",rc); - - // Note: On READ the first byte is the current index - // (e.g. 0x80, what we just wrote) - - if(debug>1) { - int i; - v4l_dbg(2, debug,i2c_client_s,"hexdump:"); - for(i=1;i<65;i++) { - if(i!=1) { - if(((i-1)%8)==0) printk(" "); - if(((i-1)%16)==0) { - printk("\n"); - v4l_dbg(2, debug,i2c_client_s,"hexdump:"); - } - } - printk(" %02x",buf[i]); - } - printk("\n"); - } - return 0; -} - -// Return: 1 (is a bt832), 0 (No bt832 here) -int bt832_init(struct i2c_client *i2c_client_s) -{ - unsigned char *buf; - int rc; - - buf=kmalloc(65,GFP_KERNEL); - bt832_hexdump(i2c_client_s,buf); - - if(buf[0x40] != 0x31) { - v4l_err(i2c_client_s,"This i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]); - kfree(buf); - return 0; - } - - v4l_err(i2c_client_s,"Write 0 tp VPSTATUS\n"); - buf[0]=BT832_VP_STATUS; // Reg.52 - buf[1]= 0x00; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc); - - bt832_hexdump(i2c_client_s,buf); - - - // Leave low power mode: - v4l_err(i2c_client_s,"leave low power mode.\n"); - buf[0]=BT832_CAM_SETUP0; //0x39 57 - buf[1]=0x08; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - v4l_err(i2c_client_s,"i2c i/o error LLPM: rc == %d (should be 2)\n",rc); - - bt832_hexdump(i2c_client_s,buf); - - v4l_info(i2c_client_s,"Write 0 tp VPSTATUS\n"); - buf[0]=BT832_VP_STATUS; // Reg.52 - buf[1]= 0x00; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc); - - bt832_hexdump(i2c_client_s,buf); - - - // Enable Output - v4l_info(i2c_client_s,"Enable Output\n"); - buf[0]=BT832_VP_CONTROL1; // Reg.40 - buf[1]= 0x27 & (~0x01); // Default | !skip - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - v4l_err(i2c_client_s,"i2c i/o error EO: rc == %d (should be 2)\n",rc); - - bt832_hexdump(i2c_client_s,buf); - - - // for testing (even works when no camera attached) - v4l_info(i2c_client_s,"*** Generate NTSC M Bars *****\n"); - buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42 - buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - v4l_info(i2c_client_s,"i2c i/o error MBAR: rc == %d (should be 2)\n",rc); - - v4l_info(i2c_client_s,"Camera Present: %s\n", - (buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no"); - - bt832_hexdump(i2c_client_s,buf); - kfree(buf); - return 1; -} - - - -static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) -{ - struct bt832 *t; - - client_template.adapter = adap; - client_template.addr = addr; - - if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL))) - return -ENOMEM; - t->client = client_template; - i2c_set_clientdata(&t->client, t); - i2c_attach_client(&t->client); - - v4l_info(&t->client,"chip found @ 0x%x\n", addr<<1); - - - if(! bt832_init(&t->client)) { - bt832_detach(&t->client); - return -1; - } - - return 0; -} - -static int bt832_probe(struct i2c_adapter *adap) -{ - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, bt832_attach); - return 0; -} - -static int bt832_detach(struct i2c_client *client) -{ - struct bt832 *t = i2c_get_clientdata(client); - - v4l_info(&t->client,"dettach\n"); - i2c_detach_client(client); - kfree(t); - return 0; -} - -static int -bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct bt832 *t = i2c_get_clientdata(client); - - if (debug>1) - v4l_i2c_print_ioctl(&t->client,cmd); - - switch (cmd) { - case BT832_HEXDUMP: { - unsigned char *buf; - buf=kmalloc(65,GFP_KERNEL); - bt832_hexdump(&t->client,buf); - kfree(buf); - } - break; - case BT832_REATTACH: - v4l_info(&t->client,"re-attach\n"); - i2c_del_driver(&driver); - i2c_add_driver(&driver); - break; - } - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static struct i2c_driver driver = { - .driver = { - .name = "bt832", - }, - .id = 0, /* FIXME */ - .attach_adapter = bt832_probe, - .detach_client = bt832_detach, - .command = bt832_command, -}; -static struct i2c_client client_template = -{ - .name = "bt832", - .driver = &driver, -}; - - -static int __init bt832_init_module(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit bt832_cleanup_module(void) -{ - i2c_del_driver(&driver); -} - -module_init(bt832_init_module); -module_exit(bt832_cleanup_module); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/bt832.h b/drivers/media/video/bt832.h deleted file mode 100644 index 1ce8fa71f7db..000000000000 --- a/drivers/media/video/bt832.h +++ /dev/null @@ -1,305 +0,0 @@ -/* Bt832 CMOS Camera Video Processor (VP) - - The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS - color digital camera directly to video capture devices via an 8-bit, - 4:2:2 YUV or YCrCb video interface. - - i2c addresses: 0x88 or 0x8a - */ - -/* The 64 registers: */ - -// Input Processor -#define BT832_OFFSET 0 -#define BT832_RCOMP 1 -#define BT832_G1COMP 2 -#define BT832_G2COMP 3 -#define BT832_BCOMP 4 -// Exposures: -#define BT832_FINEH 5 -#define BT832_FINEL 6 -#define BT832_COARSEH 7 -#define BT832_COARSEL 8 -#define BT832_CAMGAIN 9 -// Main Processor: -#define BT832_M00 10 -#define BT832_M01 11 -#define BT832_M02 12 -#define BT832_M10 13 -#define BT832_M11 14 -#define BT832_M12 15 -#define BT832_M20 16 -#define BT832_M21 17 -#define BT832_M22 18 -#define BT832_APCOR 19 -#define BT832_GAMCOR 20 -// Level Accumulator Inputs -#define BT832_VPCONTROL2 21 -#define BT832_ZONECODE0 22 -#define BT832_ZONECODE1 23 -#define BT832_ZONECODE2 24 -#define BT832_ZONECODE3 25 -// Level Accumulator Outputs: -#define BT832_RACC 26 -#define BT832_GACC 27 -#define BT832_BACC 28 -#define BT832_BLACKACC 29 -#define BT832_EXP_AGC 30 -#define BT832_LACC0 31 -#define BT832_LACC1 32 -#define BT832_LACC2 33 -#define BT832_LACC3 34 -#define BT832_LACC4 35 -#define BT832_LACC5 36 -#define BT832_LACC6 37 -#define BT832_LACC7 38 -// System: -#define BT832_VP_CONTROL0 39 -#define BT832_VP_CONTROL1 40 -#define BT832_THRESH 41 -#define BT832_VP_TESTCONTROL0 42 -#define BT832_VP_DMCODE 43 -#define BT832_ACB_CONFIG 44 -#define BT832_ACB_GNBASE 45 -#define BT832_ACB_MU 46 -#define BT832_CAM_TEST0 47 -#define BT832_AEC_CONFIG 48 -#define BT832_AEC_TL 49 -#define BT832_AEC_TC 50 -#define BT832_AEC_TH 51 -// Status: -#define BT832_VP_STATUS 52 -#define BT832_VP_LINECOUNT 53 -#define BT832_CAM_DEVICEL 54 // e.g. 0x19 -#define BT832_CAM_DEVICEH 55 // e.g. 0x40 == 0x194 Mask0, 0x194 = 404 decimal (VVL-404 camera) -#define BT832_CAM_STATUS 56 - #define BT832_56_CAMERA_PRESENT 0x20 -//Camera Setups: -#define BT832_CAM_SETUP0 57 -#define BT832_CAM_SETUP1 58 -#define BT832_CAM_SETUP2 59 -#define BT832_CAM_SETUP3 60 -// System: -#define BT832_DEFCOR 61 -#define BT832_VP_TESTCONTROL1 62 -#define BT832_DEVICE_ID 63 -# define BT832_DEVICE_ID__31 0x31 // Bt832 has ID 0x31 - -/* STMicroelectronivcs VV5404 camera module - i2c: 0x20: sensor address - i2c: 0xa0: eeprom for ccd defect map - */ -#define VV5404_device_h 0x00 // 0x19 -#define VV5404_device_l 0x01 // 0x40 -#define VV5404_status0 0x02 -#define VV5404_linecountc 0x03 // current line counter -#define VV5404_linecountl 0x04 -#define VV5404_setup0 0x10 -#define VV5404_setup1 0x11 -#define VV5404_setup2 0x12 -#define VV5404_setup4 0x14 -#define VV5404_setup5 0x15 -#define VV5404_fine_h 0x20 // fine exposure -#define VV5404_fine_l 0x21 -#define VV5404_coarse_h 0x22 //coarse exposure -#define VV5404_coarse_l 0x23 -#define VV5404_gain 0x24 // ADC pre-amp gain setting -#define VV5404_clk_div 0x25 -#define VV5404_cr 0x76 // control register -#define VV5404_as0 0x77 // ADC setup register - - -// IOCTL -#define BT832_HEXDUMP _IOR('b',1,int) -#define BT832_REATTACH _IOR('b',2,int) - -/* from BT8x8VXD/capdrv/dialogs.cpp */ - -/* -typedef enum { SVI, Logitech, Rockwell } CAMERA; - -static COMBOBOX_ENTRY gwCameraOptions[] = -{ - { SVI, "Silicon Vision 512N" }, - { Logitech, "Logitech VideoMan 1.3" }, - { Rockwell, "Rockwell QuartzSight PCI 1.0" } -}; - -// SRAM table values -//=========================================================================== -typedef enum { TGB_NTSC624, TGB_NTSC780, TGB_NTSC858, TGB_NTSC392 } TimeGenByte; - -BYTE SRAMTable[][ 60 ] = -{ - // TGB_NTSC624 - { - 0x33, // size of table = 51 - 0x0E, 0xC0, 0x00, 0x00, 0x90, 0x02, 0x03, 0x10, 0x03, 0x06, - 0x10, 0x04, 0x12, 0x12, 0x05, 0x02, 0x13, 0x04, 0x19, 0x00, - 0x04, 0x39, 0x00, 0x06, 0x59, 0x08, 0x03, 0x85, 0x08, 0x07, - 0x03, 0x50, 0x00, 0x91, 0x40, 0x00, 0x11, 0x01, 0x01, 0x4D, - 0x0D, 0x02, 0x03, 0x11, 0x01, 0x05, 0x37, 0x00, 0x37, 0x21, 0x00 - }, - // TGB_NTSC780 - { - 0x33, // size of table = 51 - 0x0e, 0xc0, 0x00, 0x00, 0x90, 0xe2, 0x03, 0x10, 0x03, 0x06, - 0x10, 0x34, 0x12, 0x12, 0x65, 0x02, 0x13, 0x24, 0x19, 0x00, - 0x24, 0x39, 0x00, 0x96, 0x59, 0x08, 0x93, 0x85, 0x08, 0x97, - 0x03, 0x50, 0x50, 0xaf, 0x40, 0x30, 0x5f, 0x01, 0xf1, 0x7f, - 0x0d, 0xf2, 0x03, 0x11, 0xf1, 0x05, 0x37, 0x30, 0x85, 0x21, 0x50 - }, - // TGB_NTSC858 - { - 0x33, // size of table = 51 - 0x0c, 0xc0, 0x00, 0x00, 0x90, 0xc2, 0x03, 0x10, 0x03, 0x06, - 0x10, 0x34, 0x12, 0x12, 0x65, 0x02, 0x13, 0x24, 0x19, 0x00, - 0x24, 0x39, 0x00, 0x96, 0x59, 0x08, 0x93, 0x83, 0x08, 0x97, - 0x03, 0x50, 0x30, 0xc0, 0x40, 0x30, 0x86, 0x01, 0x01, 0xa6, - 0x0d, 0x62, 0x03, 0x11, 0x61, 0x05, 0x37, 0x30, 0xac, 0x21, 0x50 - }, - // TGB_NTSC392 - // This table has been modified to be used for Fusion Rev D - { - 0x2A, // size of table = 42 - 0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24, - 0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10, - 0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00, - 0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3, - 0x20, 0x00 - } -}; - -//=========================================================================== -// This is the structure of the camera specifications -//=========================================================================== -typedef struct tag_cameraSpec -{ - SignalFormat signal; // which digital signal format the camera has - VideoFormat vidFormat; // video standard - SyncVideoRef syncRef; // which sync video reference is used - State syncOutput; // enable sync output for sync video input? - DecInputClk iClk; // which input clock is used - TimeGenByte tgb; // which timing generator byte does the camera use - int HReset; // select 64, 48, 32, or 16 CLKx1 for HReset - PLLFreq pllFreq; // what synthesized frequency to set PLL to - VSIZEPARMS vSize; // video size the camera produces - int lineCount; // expected total number of half-line per frame - 1 - BOOL interlace; // interlace signal? -} CameraSpec; - -//=========================================================================== -// -// Camera specifications database. Update this table whenever camera spec -// has been changed or added/deleted supported camera models -//=========================================================================== -static CameraSpec dbCameraSpec[ N_CAMERAOPTIONS ] = -{ // Silicon Vision 512N - { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC624, 64, KHz19636, - // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace - { 512, 0x64, 480, 0x13, 240 }, 0, TRUE - }, - // Logitech VideoMan 1.3 - { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC780, 64, KHz24545, - // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace - { 640, 0x80, 480, 0x1A, 240 }, 0, TRUE - }, - // Rockwell QuartzSight - // Note: Fusion Rev D (rev ID 0x02) and later supports 16 pixels for HReset which is preferable. - // Use 32 for earlier version of hardware. Clkx1_HDELAY also changed from 0x27 to 0x20. - { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC392, 16, KHz28636, - // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace - { 352, 0x20, 576, 0x08, 288 }, 607, FALSE - } -}; -*/ - -/* -The corresponding APIs required to be invoked are: -SetConnector( ConCamera, TRUE/FALSE ); -SetSignalFormat( spec.signal ); -SetVideoFormat( spec.vidFormat ); -SetSyncVideoRef( spec.syncRef ); -SetEnableSyncOutput( spec.syncOutput ); -SetTimGenByte( SRAMTable[ spec.tgb ], SRAMTableSize[ spec.tgb ] ); -SetHReset( spec.HReset ); -SetPLL( spec.pllFreq ); -SetDecInputClock( spec.iClk ); -SetVideoInfo( spec.vSize ); -SetTotalLineCount( spec.lineCount ); -SetInterlaceMode( spec.interlace ); -*/ - -/* from web: - Video Sampling -Digital video is a sampled form of analog video. The most common sampling schemes in use today are: - Pixel Clock Horiz Horiz Vert - Rate Total Active -NTSC square pixel 12.27 MHz 780 640 525 -NTSC CCIR-601 13.5 MHz 858 720 525 -NTSC 4FSc 14.32 MHz 910 768 525 -PAL square pixel 14.75 MHz 944 768 625 -PAL CCIR-601 13.5 MHz 864 720 625 -PAL 4FSc 17.72 MHz 1135 948 625 - -For the CCIR-601 standards, the sampling is based on a static orthogonal sampling grid. The luminance component (Y) is sampled at 13.5 MHz, while the two color difference signals, Cr and Cb are sampled at half that, or 6.75 MHz. The Cr and Cb samples are colocated with alternate Y samples, and they are taken at the same position on each line, such that one sample is coincident with the 50% point of the falling edge of analog sync. The samples are coded to either 8 or 10 bits per component. -*/ - -/* from DScaler:*/ -/* -//=========================================================================== -// CCIR656 Digital Input Support: The tables were taken from DScaler proyect -// -// 13 Dec 2000 - Michael Eskin, Conexant Systems - Initial version -// - -//=========================================================================== -// Timing generator SRAM table values for CCIR601 720x480 NTSC -//=========================================================================== -// For NTSC CCIR656 -BYTE BtCard::SRAMTable_NTSC[] = -{ - // SRAM Timing Table for NTSC - 0x0c, 0xc0, 0x00, - 0x00, 0x90, 0xc2, - 0x03, 0x10, 0x03, - 0x06, 0x10, 0x34, - 0x12, 0x12, 0x65, - 0x02, 0x13, 0x24, - 0x19, 0x00, 0x24, - 0x39, 0x00, 0x96, - 0x59, 0x08, 0x93, - 0x83, 0x08, 0x97, - 0x03, 0x50, 0x30, - 0xc0, 0x40, 0x30, - 0x86, 0x01, 0x01, - 0xa6, 0x0d, 0x62, - 0x03, 0x11, 0x61, - 0x05, 0x37, 0x30, - 0xac, 0x21, 0x50 -}; - -//=========================================================================== -// Timing generator SRAM table values for CCIR601 720x576 NTSC -//=========================================================================== -// For PAL CCIR656 -BYTE BtCard::SRAMTable_PAL[] = -{ - // SRAM Timing Table for PAL - 0x36, 0x11, 0x01, - 0x00, 0x90, 0x02, - 0x05, 0x10, 0x04, - 0x16, 0x14, 0x05, - 0x11, 0x00, 0x04, - 0x12, 0xc0, 0x00, - 0x31, 0x00, 0x06, - 0x51, 0x08, 0x03, - 0x89, 0x08, 0x07, - 0xc0, 0x44, 0x00, - 0x81, 0x01, 0x01, - 0xa9, 0x0d, 0x02, - 0x02, 0x50, 0x03, - 0x37, 0x3d, 0x00, - 0xaf, 0x21, 0x00, -}; -*/ diff --git a/drivers/media/video/bt848.h b/drivers/media/video/bt848.h deleted file mode 100644 index 0bcd95303bb0..000000000000 --- a/drivers/media/video/bt848.h +++ /dev/null @@ -1,366 +0,0 @@ -/* - bt848.h - Bt848 register offsets - - Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - - 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. -*/ - -#ifndef _BT848_H_ -#define _BT848_H_ - -#ifndef PCI_VENDOR_ID_BROOKTREE -#define PCI_VENDOR_ID_BROOKTREE 0x109e -#endif -#ifndef PCI_DEVICE_ID_BT848 -#define PCI_DEVICE_ID_BT848 0x350 -#endif -#ifndef PCI_DEVICE_ID_BT849 -#define PCI_DEVICE_ID_BT849 0x351 -#endif -#ifndef PCI_DEVICE_ID_BT878 -#define PCI_DEVICE_ID_BT878 0x36e -#endif -#ifndef PCI_DEVICE_ID_BT879 -#define PCI_DEVICE_ID_BT879 0x36f -#endif - - -/* Brooktree 848 registers */ - -#define BT848_DSTATUS 0x000 -#define BT848_DSTATUS_PRES (1<<7) -#define BT848_DSTATUS_HLOC (1<<6) -#define BT848_DSTATUS_FIELD (1<<5) -#define BT848_DSTATUS_NUML (1<<4) -#define BT848_DSTATUS_CSEL (1<<3) -#define BT848_DSTATUS_PLOCK (1<<2) -#define BT848_DSTATUS_LOF (1<<1) -#define BT848_DSTATUS_COF (1<<0) - -#define BT848_IFORM 0x004 -#define BT848_IFORM_HACTIVE (1<<7) -#define BT848_IFORM_MUXSEL (3<<5) -#define BT848_IFORM_MUX0 (2<<5) -#define BT848_IFORM_MUX1 (3<<5) -#define BT848_IFORM_MUX2 (1<<5) -#define BT848_IFORM_XTSEL (3<<3) -#define BT848_IFORM_XT0 (1<<3) -#define BT848_IFORM_XT1 (2<<3) -#define BT848_IFORM_XTAUTO (3<<3) -#define BT848_IFORM_XTBOTH (3<<3) -#define BT848_IFORM_NTSC 1 -#define BT848_IFORM_NTSC_J 2 -#define BT848_IFORM_PAL_BDGHI 3 -#define BT848_IFORM_PAL_M 4 -#define BT848_IFORM_PAL_N 5 -#define BT848_IFORM_SECAM 6 -#define BT848_IFORM_PAL_NC 7 -#define BT848_IFORM_AUTO 0 -#define BT848_IFORM_NORM 7 - -#define BT848_TDEC 0x008 -#define BT848_TDEC_DEC_FIELD (1<<7) -#define BT848_TDEC_FLDALIGN (1<<6) -#define BT848_TDEC_DEC_RAT (0x1f) - -#define BT848_E_CROP 0x00C -#define BT848_O_CROP 0x08C - -#define BT848_E_VDELAY_LO 0x010 -#define BT848_O_VDELAY_LO 0x090 - -#define BT848_E_VACTIVE_LO 0x014 -#define BT848_O_VACTIVE_LO 0x094 - -#define BT848_E_HDELAY_LO 0x018 -#define BT848_O_HDELAY_LO 0x098 - -#define BT848_E_HACTIVE_LO 0x01C -#define BT848_O_HACTIVE_LO 0x09C - -#define BT848_E_HSCALE_HI 0x020 -#define BT848_O_HSCALE_HI 0x0A0 - -#define BT848_E_HSCALE_LO 0x024 -#define BT848_O_HSCALE_LO 0x0A4 - -#define BT848_BRIGHT 0x028 - -#define BT848_E_CONTROL 0x02C -#define BT848_O_CONTROL 0x0AC -#define BT848_CONTROL_LNOTCH (1<<7) -#define BT848_CONTROL_COMP (1<<6) -#define BT848_CONTROL_LDEC (1<<5) -#define BT848_CONTROL_CBSENSE (1<<4) -#define BT848_CONTROL_CON_MSB (1<<2) -#define BT848_CONTROL_SAT_U_MSB (1<<1) -#define BT848_CONTROL_SAT_V_MSB (1<<0) - -#define BT848_CONTRAST_LO 0x030 -#define BT848_SAT_U_LO 0x034 -#define BT848_SAT_V_LO 0x038 -#define BT848_HUE 0x03C - -#define BT848_E_SCLOOP 0x040 -#define BT848_O_SCLOOP 0x0C0 -#define BT848_SCLOOP_CAGC (1<<6) -#define BT848_SCLOOP_CKILL (1<<5) -#define BT848_SCLOOP_HFILT_AUTO (0<<3) -#define BT848_SCLOOP_HFILT_CIF (1<<3) -#define BT848_SCLOOP_HFILT_QCIF (2<<3) -#define BT848_SCLOOP_HFILT_ICON (3<<3) - -#define BT848_SCLOOP_PEAK (1<<7) -#define BT848_SCLOOP_HFILT_MINP (1<<3) -#define BT848_SCLOOP_HFILT_MEDP (2<<3) -#define BT848_SCLOOP_HFILT_MAXP (3<<3) - - -#define BT848_OFORM 0x048 -#define BT848_OFORM_RANGE (1<<7) -#define BT848_OFORM_CORE0 (0<<5) -#define BT848_OFORM_CORE8 (1<<5) -#define BT848_OFORM_CORE16 (2<<5) -#define BT848_OFORM_CORE32 (3<<5) - -#define BT848_E_VSCALE_HI 0x04C -#define BT848_O_VSCALE_HI 0x0CC -#define BT848_VSCALE_YCOMB (1<<7) -#define BT848_VSCALE_COMB (1<<6) -#define BT848_VSCALE_INT (1<<5) -#define BT848_VSCALE_HI 15 - -#define BT848_E_VSCALE_LO 0x050 -#define BT848_O_VSCALE_LO 0x0D0 -#define BT848_TEST 0x054 -#define BT848_ADELAY 0x060 -#define BT848_BDELAY 0x064 - -#define BT848_ADC 0x068 -#define BT848_ADC_RESERVED (2<<6) -#define BT848_ADC_SYNC_T (1<<5) -#define BT848_ADC_AGC_EN (1<<4) -#define BT848_ADC_CLK_SLEEP (1<<3) -#define BT848_ADC_Y_SLEEP (1<<2) -#define BT848_ADC_C_SLEEP (1<<1) -#define BT848_ADC_CRUSH (1<<0) - -#define BT848_WC_UP 0x044 -#define BT848_WC_DOWN 0x078 - -#define BT848_E_VTC 0x06C -#define BT848_O_VTC 0x0EC -#define BT848_VTC_HSFMT (1<<7) -#define BT848_VTC_VFILT_2TAP 0 -#define BT848_VTC_VFILT_3TAP 1 -#define BT848_VTC_VFILT_4TAP 2 -#define BT848_VTC_VFILT_5TAP 3 - -#define BT848_SRESET 0x07C - -#define BT848_COLOR_FMT 0x0D4 -#define BT848_COLOR_FMT_O_RGB32 (0<<4) -#define BT848_COLOR_FMT_O_RGB24 (1<<4) -#define BT848_COLOR_FMT_O_RGB16 (2<<4) -#define BT848_COLOR_FMT_O_RGB15 (3<<4) -#define BT848_COLOR_FMT_O_YUY2 (4<<4) -#define BT848_COLOR_FMT_O_BtYUV (5<<4) -#define BT848_COLOR_FMT_O_Y8 (6<<4) -#define BT848_COLOR_FMT_O_RGB8 (7<<4) -#define BT848_COLOR_FMT_O_YCrCb422 (8<<4) -#define BT848_COLOR_FMT_O_YCrCb411 (9<<4) -#define BT848_COLOR_FMT_O_RAW (14<<4) -#define BT848_COLOR_FMT_E_RGB32 0 -#define BT848_COLOR_FMT_E_RGB24 1 -#define BT848_COLOR_FMT_E_RGB16 2 -#define BT848_COLOR_FMT_E_RGB15 3 -#define BT848_COLOR_FMT_E_YUY2 4 -#define BT848_COLOR_FMT_E_BtYUV 5 -#define BT848_COLOR_FMT_E_Y8 6 -#define BT848_COLOR_FMT_E_RGB8 7 -#define BT848_COLOR_FMT_E_YCrCb422 8 -#define BT848_COLOR_FMT_E_YCrCb411 9 -#define BT848_COLOR_FMT_E_RAW 14 - -#define BT848_COLOR_FMT_RGB32 0x00 -#define BT848_COLOR_FMT_RGB24 0x11 -#define BT848_COLOR_FMT_RGB16 0x22 -#define BT848_COLOR_FMT_RGB15 0x33 -#define BT848_COLOR_FMT_YUY2 0x44 -#define BT848_COLOR_FMT_BtYUV 0x55 -#define BT848_COLOR_FMT_Y8 0x66 -#define BT848_COLOR_FMT_RGB8 0x77 -#define BT848_COLOR_FMT_YCrCb422 0x88 -#define BT848_COLOR_FMT_YCrCb411 0x99 -#define BT848_COLOR_FMT_RAW 0xee - -#define BT848_VTOTAL_LO 0xB0 -#define BT848_VTOTAL_HI 0xB4 - -#define BT848_COLOR_CTL 0x0D8 -#define BT848_COLOR_CTL_EXT_FRMRATE (1<<7) -#define BT848_COLOR_CTL_COLOR_BARS (1<<6) -#define BT848_COLOR_CTL_RGB_DED (1<<5) -#define BT848_COLOR_CTL_GAMMA (1<<4) -#define BT848_COLOR_CTL_WSWAP_ODD (1<<3) -#define BT848_COLOR_CTL_WSWAP_EVEN (1<<2) -#define BT848_COLOR_CTL_BSWAP_ODD (1<<1) -#define BT848_COLOR_CTL_BSWAP_EVEN (1<<0) - -#define BT848_CAP_CTL 0x0DC -#define BT848_CAP_CTL_DITH_FRAME (1<<4) -#define BT848_CAP_CTL_CAPTURE_VBI_ODD (1<<3) -#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2) -#define BT848_CAP_CTL_CAPTURE_ODD (1<<1) -#define BT848_CAP_CTL_CAPTURE_EVEN (1<<0) - -#define BT848_VBI_PACK_SIZE 0x0E0 - -#define BT848_VBI_PACK_DEL 0x0E4 -#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc -#define BT848_VBI_PACK_DEL_EXT_FRAME 2 -#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1 - - -#define BT848_INT_STAT 0x100 -#define BT848_INT_MASK 0x104 - -#define BT848_INT_ETBF (1<<23) - -#define BT848_INT_RISCS (0xf<<28) -#define BT848_INT_RISC_EN (1<<27) -#define BT848_INT_RACK (1<<25) -#define BT848_INT_FIELD (1<<24) -#define BT848_INT_SCERR (1<<19) -#define BT848_INT_OCERR (1<<18) -#define BT848_INT_PABORT (1<<17) -#define BT848_INT_RIPERR (1<<16) -#define BT848_INT_PPERR (1<<15) -#define BT848_INT_FDSR (1<<14) -#define BT848_INT_FTRGT (1<<13) -#define BT848_INT_FBUS (1<<12) -#define BT848_INT_RISCI (1<<11) -#define BT848_INT_GPINT (1<<9) -#define BT848_INT_I2CDONE (1<<8) -#define BT848_INT_VPRES (1<<5) -#define BT848_INT_HLOCK (1<<4) -#define BT848_INT_OFLOW (1<<3) -#define BT848_INT_HSYNC (1<<2) -#define BT848_INT_VSYNC (1<<1) -#define BT848_INT_FMTCHG (1<<0) - - -#define BT848_GPIO_DMA_CTL 0x10C -#define BT848_GPIO_DMA_CTL_GPINTC (1<<15) -#define BT848_GPIO_DMA_CTL_GPINTI (1<<14) -#define BT848_GPIO_DMA_CTL_GPWEC (1<<13) -#define BT848_GPIO_DMA_CTL_GPIOMODE (3<<11) -#define BT848_GPIO_DMA_CTL_GPCLKMODE (1<<10) -#define BT848_GPIO_DMA_CTL_PLTP23_4 (0<<6) -#define BT848_GPIO_DMA_CTL_PLTP23_8 (1<<6) -#define BT848_GPIO_DMA_CTL_PLTP23_16 (2<<6) -#define BT848_GPIO_DMA_CTL_PLTP23_32 (3<<6) -#define BT848_GPIO_DMA_CTL_PLTP1_4 (0<<4) -#define BT848_GPIO_DMA_CTL_PLTP1_8 (1<<4) -#define BT848_GPIO_DMA_CTL_PLTP1_16 (2<<4) -#define BT848_GPIO_DMA_CTL_PLTP1_32 (3<<4) -#define BT848_GPIO_DMA_CTL_PKTP_4 (0<<2) -#define BT848_GPIO_DMA_CTL_PKTP_8 (1<<2) -#define BT848_GPIO_DMA_CTL_PKTP_16 (2<<2) -#define BT848_GPIO_DMA_CTL_PKTP_32 (3<<2) -#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1) -#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0) - -#define BT848_I2C 0x110 -#define BT878_I2C_MODE (1<<7) -#define BT878_I2C_RATE (1<<6) -#define BT878_I2C_NOSTOP (1<<5) -#define BT878_I2C_NOSTART (1<<4) -#define BT848_I2C_DIV (0xf<<4) -#define BT848_I2C_SYNC (1<<3) -#define BT848_I2C_W3B (1<<2) -#define BT848_I2C_SCL (1<<1) -#define BT848_I2C_SDA (1<<0) - -#define BT848_RISC_STRT_ADD 0x114 -#define BT848_GPIO_OUT_EN 0x118 -#define BT848_GPIO_REG_INP 0x11C -#define BT848_RISC_COUNT 0x120 -#define BT848_GPIO_DATA 0x200 - - -/* Bt848 RISC commands */ - -/* only for the SYNC RISC command */ -#define BT848_FIFO_STATUS_FM1 0x06 -#define BT848_FIFO_STATUS_FM3 0x0e -#define BT848_FIFO_STATUS_SOL 0x02 -#define BT848_FIFO_STATUS_EOL4 0x01 -#define BT848_FIFO_STATUS_EOL3 0x0d -#define BT848_FIFO_STATUS_EOL2 0x09 -#define BT848_FIFO_STATUS_EOL1 0x05 -#define BT848_FIFO_STATUS_VRE 0x04 -#define BT848_FIFO_STATUS_VRO 0x0c -#define BT848_FIFO_STATUS_PXV 0x00 - -#define BT848_RISC_RESYNC (1<<15) - -/* WRITE and SKIP */ -/* disable which bytes of each DWORD */ -#define BT848_RISC_BYTE0 (1U<<12) -#define BT848_RISC_BYTE1 (1U<<13) -#define BT848_RISC_BYTE2 (1U<<14) -#define BT848_RISC_BYTE3 (1U<<15) -#define BT848_RISC_BYTE_ALL (0x0fU<<12) -#define BT848_RISC_BYTE_NONE 0 -/* cause RISCI */ -#define BT848_RISC_IRQ (1U<<24) -/* RISC command is last one in this line */ -#define BT848_RISC_EOL (1U<<26) -/* RISC command is first one in this line */ -#define BT848_RISC_SOL (1U<<27) - -#define BT848_RISC_WRITE (0x01U<<28) -#define BT848_RISC_SKIP (0x02U<<28) -#define BT848_RISC_WRITEC (0x05U<<28) -#define BT848_RISC_JUMP (0x07U<<28) -#define BT848_RISC_SYNC (0x08U<<28) - -#define BT848_RISC_WRITE123 (0x09U<<28) -#define BT848_RISC_SKIP123 (0x0aU<<28) -#define BT848_RISC_WRITE1S23 (0x0bU<<28) - - -/* Bt848A and higher only !! */ -#define BT848_TGLB 0x080 -#define BT848_TGCTRL 0x084 -#define BT848_FCAP 0x0E8 -#define BT848_PLL_F_LO 0x0F0 -#define BT848_PLL_F_HI 0x0F4 - -#define BT848_PLL_XCI 0x0F8 -#define BT848_PLL_X (1<<7) -#define BT848_PLL_C (1<<6) - -#define BT848_DVSIF 0x0FC - -/* Bt878 register */ - -#define BT878_DEVCTRL 0x40 -#define BT878_EN_TBFX 0x02 -#define BT878_EN_VSFX 0x04 - -#endif diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig new file mode 100644 index 000000000000..085477c12612 --- /dev/null +++ b/drivers/media/video/bt8xx/Kconfig @@ -0,0 +1,25 @@ +config VIDEO_BT848 + tristate "BT848 Video For Linux" + depends on VIDEO_DEV && PCI && I2C + select I2C_ALGOBIT + select FW_LOADER + select VIDEO_BTCX + select VIDEO_BUF + select VIDEO_IR + select VIDEO_TUNER + select VIDEO_TVEEPROM + select VIDEO_MSP3400 + ---help--- + Support for BT848 based frame grabber/overlay boards. This includes + the Miro, Hauppauge and STB boards. Please read the material in + for more information. + + To compile this driver as a module, choose M here: the + module will be called bttv. + +config VIDEO_BT848_DVB + bool "DVB/ATSC Support for bt878 based TV cards" + depends on VIDEO_BT848 && DVB_CORE + select DVB_BT8XX + ---help--- + This adds support for DVB/ATSC cards based on the BT878 chip. diff --git a/drivers/media/video/bt8xx/bt832.c b/drivers/media/video/bt8xx/bt832.c new file mode 100644 index 000000000000..cc54b62f4601 --- /dev/null +++ b/drivers/media/video/bt8xx/bt832.c @@ -0,0 +1,266 @@ +/* Driver for Bt832 CMOS Camera Video Processor + i2c-addresses: 0x88 or 0x8a + + The BT832 interfaces to a Quartzsight Digital Camera (352x288, 25 or 30 fps) + via a 9 pin connector ( 4-wire SDATA, 2-wire i2c, SCLK, VCC, GND). + It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly + connected to bt848/bt878 GPIO pins on this purpose. + (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets) + + Supported Cards: + - Pixelview Rev.4E: 0x8a + GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 ! + + (c) Gunther Mayer, 2002 + + STATUS: + - detect chip and hexdump + - reset chip and leave low power mode + - detect camera present + + TODO: + - make it work (find correct setup for Bt832 and Bt878) +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bttv.h" +#include "bt832.h" + +MODULE_LICENSE("GPL"); + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1, + I2C_CLIENT_END }; +I2C_CLIENT_INSMOD; + +int debug; /* debug output */ +module_param(debug, int, 0644); + +/* ---------------------------------------------------------------------- */ + +static int bt832_detach(struct i2c_client *client); + + +static struct i2c_driver driver; +static struct i2c_client client_template; + +struct bt832 { + struct i2c_client client; +}; + +int bt832_hexdump(struct i2c_client *i2c_client_s, unsigned char *buf) +{ + int i,rc; + buf[0]=0x80; // start at register 0 with auto-increment + if (1 != (rc = i2c_master_send(i2c_client_s,buf,1))) + v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 1)\n",rc); + + for(i=0;i<65;i++) + buf[i]=0; + if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65))) + v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 65)\n",rc); + + // Note: On READ the first byte is the current index + // (e.g. 0x80, what we just wrote) + + if(debug>1) { + int i; + v4l_dbg(2, debug,i2c_client_s,"hexdump:"); + for(i=1;i<65;i++) { + if(i!=1) { + if(((i-1)%8)==0) printk(" "); + if(((i-1)%16)==0) { + printk("\n"); + v4l_dbg(2, debug,i2c_client_s,"hexdump:"); + } + } + printk(" %02x",buf[i]); + } + printk("\n"); + } + return 0; +} + +// Return: 1 (is a bt832), 0 (No bt832 here) +int bt832_init(struct i2c_client *i2c_client_s) +{ + unsigned char *buf; + int rc; + + buf=kmalloc(65,GFP_KERNEL); + bt832_hexdump(i2c_client_s,buf); + + if(buf[0x40] != 0x31) { + v4l_err(i2c_client_s,"This i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]); + kfree(buf); + return 0; + } + + v4l_err(i2c_client_s,"Write 0 tp VPSTATUS\n"); + buf[0]=BT832_VP_STATUS; // Reg.52 + buf[1]= 0x00; + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc); + + bt832_hexdump(i2c_client_s,buf); + + + // Leave low power mode: + v4l_err(i2c_client_s,"leave low power mode.\n"); + buf[0]=BT832_CAM_SETUP0; //0x39 57 + buf[1]=0x08; + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + v4l_err(i2c_client_s,"i2c i/o error LLPM: rc == %d (should be 2)\n",rc); + + bt832_hexdump(i2c_client_s,buf); + + v4l_info(i2c_client_s,"Write 0 tp VPSTATUS\n"); + buf[0]=BT832_VP_STATUS; // Reg.52 + buf[1]= 0x00; + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc); + + bt832_hexdump(i2c_client_s,buf); + + + // Enable Output + v4l_info(i2c_client_s,"Enable Output\n"); + buf[0]=BT832_VP_CONTROL1; // Reg.40 + buf[1]= 0x27 & (~0x01); // Default | !skip + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + v4l_err(i2c_client_s,"i2c i/o error EO: rc == %d (should be 2)\n",rc); + + bt832_hexdump(i2c_client_s,buf); + + + // for testing (even works when no camera attached) + v4l_info(i2c_client_s,"*** Generate NTSC M Bars *****\n"); + buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42 + buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + v4l_info(i2c_client_s,"i2c i/o error MBAR: rc == %d (should be 2)\n",rc); + + v4l_info(i2c_client_s,"Camera Present: %s\n", + (buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no"); + + bt832_hexdump(i2c_client_s,buf); + kfree(buf); + return 1; +} + + + +static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) +{ + struct bt832 *t; + + client_template.adapter = adap; + client_template.addr = addr; + + if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL))) + return -ENOMEM; + t->client = client_template; + i2c_set_clientdata(&t->client, t); + i2c_attach_client(&t->client); + + v4l_info(&t->client,"chip found @ 0x%x\n", addr<<1); + + + if(! bt832_init(&t->client)) { + bt832_detach(&t->client); + return -1; + } + + return 0; +} + +static int bt832_probe(struct i2c_adapter *adap) +{ + if (adap->class & I2C_CLASS_TV_ANALOG) + return i2c_probe(adap, &addr_data, bt832_attach); + return 0; +} + +static int bt832_detach(struct i2c_client *client) +{ + struct bt832 *t = i2c_get_clientdata(client); + + v4l_info(&t->client,"dettach\n"); + i2c_detach_client(client); + kfree(t); + return 0; +} + +static int +bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + struct bt832 *t = i2c_get_clientdata(client); + + if (debug>1) + v4l_i2c_print_ioctl(&t->client,cmd); + + switch (cmd) { + case BT832_HEXDUMP: { + unsigned char *buf; + buf=kmalloc(65,GFP_KERNEL); + bt832_hexdump(&t->client,buf); + kfree(buf); + } + break; + case BT832_REATTACH: + v4l_info(&t->client,"re-attach\n"); + i2c_del_driver(&driver); + i2c_add_driver(&driver); + break; + } + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static struct i2c_driver driver = { + .driver = { + .name = "bt832", + }, + .id = 0, /* FIXME */ + .attach_adapter = bt832_probe, + .detach_client = bt832_detach, + .command = bt832_command, +}; +static struct i2c_client client_template = +{ + .name = "bt832", + .driver = &driver, +}; + + +static int __init bt832_init_module(void) +{ + return i2c_add_driver(&driver); +} + +static void __exit bt832_cleanup_module(void) +{ + i2c_del_driver(&driver); +} + +module_init(bt832_init_module); +module_exit(bt832_cleanup_module); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bt8xx/bt832.h b/drivers/media/video/bt8xx/bt832.h new file mode 100644 index 000000000000..1ce8fa71f7db --- /dev/null +++ b/drivers/media/video/bt8xx/bt832.h @@ -0,0 +1,305 @@ +/* Bt832 CMOS Camera Video Processor (VP) + + The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS + color digital camera directly to video capture devices via an 8-bit, + 4:2:2 YUV or YCrCb video interface. + + i2c addresses: 0x88 or 0x8a + */ + +/* The 64 registers: */ + +// Input Processor +#define BT832_OFFSET 0 +#define BT832_RCOMP 1 +#define BT832_G1COMP 2 +#define BT832_G2COMP 3 +#define BT832_BCOMP 4 +// Exposures: +#define BT832_FINEH 5 +#define BT832_FINEL 6 +#define BT832_COARSEH 7 +#define BT832_COARSEL 8 +#define BT832_CAMGAIN 9 +// Main Processor: +#define BT832_M00 10 +#define BT832_M01 11 +#define BT832_M02 12 +#define BT832_M10 13 +#define BT832_M11 14 +#define BT832_M12 15 +#define BT832_M20 16 +#define BT832_M21 17 +#define BT832_M22 18 +#define BT832_APCOR 19 +#define BT832_GAMCOR 20 +// Level Accumulator Inputs +#define BT832_VPCONTROL2 21 +#define BT832_ZONECODE0 22 +#define BT832_ZONECODE1 23 +#define BT832_ZONECODE2 24 +#define BT832_ZONECODE3 25 +// Level Accumulator Outputs: +#define BT832_RACC 26 +#define BT832_GACC 27 +#define BT832_BACC 28 +#define BT832_BLACKACC 29 +#define BT832_EXP_AGC 30 +#define BT832_LACC0 31 +#define BT832_LACC1 32 +#define BT832_LACC2 33 +#define BT832_LACC3 34 +#define BT832_LACC4 35 +#define BT832_LACC5 36 +#define BT832_LACC6 37 +#define BT832_LACC7 38 +// System: +#define BT832_VP_CONTROL0 39 +#define BT832_VP_CONTROL1 40 +#define BT832_THRESH 41 +#define BT832_VP_TESTCONTROL0 42 +#define BT832_VP_DMCODE 43 +#define BT832_ACB_CONFIG 44 +#define BT832_ACB_GNBASE 45 +#define BT832_ACB_MU 46 +#define BT832_CAM_TEST0 47 +#define BT832_AEC_CONFIG 48 +#define BT832_AEC_TL 49 +#define BT832_AEC_TC 50 +#define BT832_AEC_TH 51 +// Status: +#define BT832_VP_STATUS 52 +#define BT832_VP_LINECOUNT 53 +#define BT832_CAM_DEVICEL 54 // e.g. 0x19 +#define BT832_CAM_DEVICEH 55 // e.g. 0x40 == 0x194 Mask0, 0x194 = 404 decimal (VVL-404 camera) +#define BT832_CAM_STATUS 56 + #define BT832_56_CAMERA_PRESENT 0x20 +//Camera Setups: +#define BT832_CAM_SETUP0 57 +#define BT832_CAM_SETUP1 58 +#define BT832_CAM_SETUP2 59 +#define BT832_CAM_SETUP3 60 +// System: +#define BT832_DEFCOR 61 +#define BT832_VP_TESTCONTROL1 62 +#define BT832_DEVICE_ID 63 +# define BT832_DEVICE_ID__31 0x31 // Bt832 has ID 0x31 + +/* STMicroelectronivcs VV5404 camera module + i2c: 0x20: sensor address + i2c: 0xa0: eeprom for ccd defect map + */ +#define VV5404_device_h 0x00 // 0x19 +#define VV5404_device_l 0x01 // 0x40 +#define VV5404_status0 0x02 +#define VV5404_linecountc 0x03 // current line counter +#define VV5404_linecountl 0x04 +#define VV5404_setup0 0x10 +#define VV5404_setup1 0x11 +#define VV5404_setup2 0x12 +#define VV5404_setup4 0x14 +#define VV5404_setup5 0x15 +#define VV5404_fine_h 0x20 // fine exposure +#define VV5404_fine_l 0x21 +#define VV5404_coarse_h 0x22 //coarse exposure +#define VV5404_coarse_l 0x23 +#define VV5404_gain 0x24 // ADC pre-amp gain setting +#define VV5404_clk_div 0x25 +#define VV5404_cr 0x76 // control register +#define VV5404_as0 0x77 // ADC setup register + + +// IOCTL +#define BT832_HEXDUMP _IOR('b',1,int) +#define BT832_REATTACH _IOR('b',2,int) + +/* from BT8x8VXD/capdrv/dialogs.cpp */ + +/* +typedef enum { SVI, Logitech, Rockwell } CAMERA; + +static COMBOBOX_ENTRY gwCameraOptions[] = +{ + { SVI, "Silicon Vision 512N" }, + { Logitech, "Logitech VideoMan 1.3" }, + { Rockwell, "Rockwell QuartzSight PCI 1.0" } +}; + +// SRAM table values +//=========================================================================== +typedef enum { TGB_NTSC624, TGB_NTSC780, TGB_NTSC858, TGB_NTSC392 } TimeGenByte; + +BYTE SRAMTable[][ 60 ] = +{ + // TGB_NTSC624 + { + 0x33, // size of table = 51 + 0x0E, 0xC0, 0x00, 0x00, 0x90, 0x02, 0x03, 0x10, 0x03, 0x06, + 0x10, 0x04, 0x12, 0x12, 0x05, 0x02, 0x13, 0x04, 0x19, 0x00, + 0x04, 0x39, 0x00, 0x06, 0x59, 0x08, 0x03, 0x85, 0x08, 0x07, + 0x03, 0x50, 0x00, 0x91, 0x40, 0x00, 0x11, 0x01, 0x01, 0x4D, + 0x0D, 0x02, 0x03, 0x11, 0x01, 0x05, 0x37, 0x00, 0x37, 0x21, 0x00 + }, + // TGB_NTSC780 + { + 0x33, // size of table = 51 + 0x0e, 0xc0, 0x00, 0x00, 0x90, 0xe2, 0x03, 0x10, 0x03, 0x06, + 0x10, 0x34, 0x12, 0x12, 0x65, 0x02, 0x13, 0x24, 0x19, 0x00, + 0x24, 0x39, 0x00, 0x96, 0x59, 0x08, 0x93, 0x85, 0x08, 0x97, + 0x03, 0x50, 0x50, 0xaf, 0x40, 0x30, 0x5f, 0x01, 0xf1, 0x7f, + 0x0d, 0xf2, 0x03, 0x11, 0xf1, 0x05, 0x37, 0x30, 0x85, 0x21, 0x50 + }, + // TGB_NTSC858 + { + 0x33, // size of table = 51 + 0x0c, 0xc0, 0x00, 0x00, 0x90, 0xc2, 0x03, 0x10, 0x03, 0x06, + 0x10, 0x34, 0x12, 0x12, 0x65, 0x02, 0x13, 0x24, 0x19, 0x00, + 0x24, 0x39, 0x00, 0x96, 0x59, 0x08, 0x93, 0x83, 0x08, 0x97, + 0x03, 0x50, 0x30, 0xc0, 0x40, 0x30, 0x86, 0x01, 0x01, 0xa6, + 0x0d, 0x62, 0x03, 0x11, 0x61, 0x05, 0x37, 0x30, 0xac, 0x21, 0x50 + }, + // TGB_NTSC392 + // This table has been modified to be used for Fusion Rev D + { + 0x2A, // size of table = 42 + 0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24, + 0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10, + 0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00, + 0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3, + 0x20, 0x00 + } +}; + +//=========================================================================== +// This is the structure of the camera specifications +//=========================================================================== +typedef struct tag_cameraSpec +{ + SignalFormat signal; // which digital signal format the camera has + VideoFormat vidFormat; // video standard + SyncVideoRef syncRef; // which sync video reference is used + State syncOutput; // enable sync output for sync video input? + DecInputClk iClk; // which input clock is used + TimeGenByte tgb; // which timing generator byte does the camera use + int HReset; // select 64, 48, 32, or 16 CLKx1 for HReset + PLLFreq pllFreq; // what synthesized frequency to set PLL to + VSIZEPARMS vSize; // video size the camera produces + int lineCount; // expected total number of half-line per frame - 1 + BOOL interlace; // interlace signal? +} CameraSpec; + +//=========================================================================== +// +// Camera specifications database. Update this table whenever camera spec +// has been changed or added/deleted supported camera models +//=========================================================================== +static CameraSpec dbCameraSpec[ N_CAMERAOPTIONS ] = +{ // Silicon Vision 512N + { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC624, 64, KHz19636, + // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace + { 512, 0x64, 480, 0x13, 240 }, 0, TRUE + }, + // Logitech VideoMan 1.3 + { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC780, 64, KHz24545, + // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace + { 640, 0x80, 480, 0x1A, 240 }, 0, TRUE + }, + // Rockwell QuartzSight + // Note: Fusion Rev D (rev ID 0x02) and later supports 16 pixels for HReset which is preferable. + // Use 32 for earlier version of hardware. Clkx1_HDELAY also changed from 0x27 to 0x20. + { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC392, 16, KHz28636, + // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace + { 352, 0x20, 576, 0x08, 288 }, 607, FALSE + } +}; +*/ + +/* +The corresponding APIs required to be invoked are: +SetConnector( ConCamera, TRUE/FALSE ); +SetSignalFormat( spec.signal ); +SetVideoFormat( spec.vidFormat ); +SetSyncVideoRef( spec.syncRef ); +SetEnableSyncOutput( spec.syncOutput ); +SetTimGenByte( SRAMTable[ spec.tgb ], SRAMTableSize[ spec.tgb ] ); +SetHReset( spec.HReset ); +SetPLL( spec.pllFreq ); +SetDecInputClock( spec.iClk ); +SetVideoInfo( spec.vSize ); +SetTotalLineCount( spec.lineCount ); +SetInterlaceMode( spec.interlace ); +*/ + +/* from web: + Video Sampling +Digital video is a sampled form of analog video. The most common sampling schemes in use today are: + Pixel Clock Horiz Horiz Vert + Rate Total Active +NTSC square pixel 12.27 MHz 780 640 525 +NTSC CCIR-601 13.5 MHz 858 720 525 +NTSC 4FSc 14.32 MHz 910 768 525 +PAL square pixel 14.75 MHz 944 768 625 +PAL CCIR-601 13.5 MHz 864 720 625 +PAL 4FSc 17.72 MHz 1135 948 625 + +For the CCIR-601 standards, the sampling is based on a static orthogonal sampling grid. The luminance component (Y) is sampled at 13.5 MHz, while the two color difference signals, Cr and Cb are sampled at half that, or 6.75 MHz. The Cr and Cb samples are colocated with alternate Y samples, and they are taken at the same position on each line, such that one sample is coincident with the 50% point of the falling edge of analog sync. The samples are coded to either 8 or 10 bits per component. +*/ + +/* from DScaler:*/ +/* +//=========================================================================== +// CCIR656 Digital Input Support: The tables were taken from DScaler proyect +// +// 13 Dec 2000 - Michael Eskin, Conexant Systems - Initial version +// + +//=========================================================================== +// Timing generator SRAM table values for CCIR601 720x480 NTSC +//=========================================================================== +// For NTSC CCIR656 +BYTE BtCard::SRAMTable_NTSC[] = +{ + // SRAM Timing Table for NTSC + 0x0c, 0xc0, 0x00, + 0x00, 0x90, 0xc2, + 0x03, 0x10, 0x03, + 0x06, 0x10, 0x34, + 0x12, 0x12, 0x65, + 0x02, 0x13, 0x24, + 0x19, 0x00, 0x24, + 0x39, 0x00, 0x96, + 0x59, 0x08, 0x93, + 0x83, 0x08, 0x97, + 0x03, 0x50, 0x30, + 0xc0, 0x40, 0x30, + 0x86, 0x01, 0x01, + 0xa6, 0x0d, 0x62, + 0x03, 0x11, 0x61, + 0x05, 0x37, 0x30, + 0xac, 0x21, 0x50 +}; + +//=========================================================================== +// Timing generator SRAM table values for CCIR601 720x576 NTSC +//=========================================================================== +// For PAL CCIR656 +BYTE BtCard::SRAMTable_PAL[] = +{ + // SRAM Timing Table for PAL + 0x36, 0x11, 0x01, + 0x00, 0x90, 0x02, + 0x05, 0x10, 0x04, + 0x16, 0x14, 0x05, + 0x11, 0x00, 0x04, + 0x12, 0xc0, 0x00, + 0x31, 0x00, 0x06, + 0x51, 0x08, 0x03, + 0x89, 0x08, 0x07, + 0xc0, 0x44, 0x00, + 0x81, 0x01, 0x01, + 0xa9, 0x0d, 0x02, + 0x02, 0x50, 0x03, + 0x37, 0x3d, 0x00, + 0xaf, 0x21, 0x00, +}; +*/ diff --git a/drivers/media/video/bt8xx/bt848.h b/drivers/media/video/bt8xx/bt848.h new file mode 100644 index 000000000000..0bcd95303bb0 --- /dev/null +++ b/drivers/media/video/bt8xx/bt848.h @@ -0,0 +1,366 @@ +/* + bt848.h - Bt848 register offsets + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + + 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. +*/ + +#ifndef _BT848_H_ +#define _BT848_H_ + +#ifndef PCI_VENDOR_ID_BROOKTREE +#define PCI_VENDOR_ID_BROOKTREE 0x109e +#endif +#ifndef PCI_DEVICE_ID_BT848 +#define PCI_DEVICE_ID_BT848 0x350 +#endif +#ifndef PCI_DEVICE_ID_BT849 +#define PCI_DEVICE_ID_BT849 0x351 +#endif +#ifndef PCI_DEVICE_ID_BT878 +#define PCI_DEVICE_ID_BT878 0x36e +#endif +#ifndef PCI_DEVICE_ID_BT879 +#define PCI_DEVICE_ID_BT879 0x36f +#endif + + +/* Brooktree 848 registers */ + +#define BT848_DSTATUS 0x000 +#define BT848_DSTATUS_PRES (1<<7) +#define BT848_DSTATUS_HLOC (1<<6) +#define BT848_DSTATUS_FIELD (1<<5) +#define BT848_DSTATUS_NUML (1<<4) +#define BT848_DSTATUS_CSEL (1<<3) +#define BT848_DSTATUS_PLOCK (1<<2) +#define BT848_DSTATUS_LOF (1<<1) +#define BT848_DSTATUS_COF (1<<0) + +#define BT848_IFORM 0x004 +#define BT848_IFORM_HACTIVE (1<<7) +#define BT848_IFORM_MUXSEL (3<<5) +#define BT848_IFORM_MUX0 (2<<5) +#define BT848_IFORM_MUX1 (3<<5) +#define BT848_IFORM_MUX2 (1<<5) +#define BT848_IFORM_XTSEL (3<<3) +#define BT848_IFORM_XT0 (1<<3) +#define BT848_IFORM_XT1 (2<<3) +#define BT848_IFORM_XTAUTO (3<<3) +#define BT848_IFORM_XTBOTH (3<<3) +#define BT848_IFORM_NTSC 1 +#define BT848_IFORM_NTSC_J 2 +#define BT848_IFORM_PAL_BDGHI 3 +#define BT848_IFORM_PAL_M 4 +#define BT848_IFORM_PAL_N 5 +#define BT848_IFORM_SECAM 6 +#define BT848_IFORM_PAL_NC 7 +#define BT848_IFORM_AUTO 0 +#define BT848_IFORM_NORM 7 + +#define BT848_TDEC 0x008 +#define BT848_TDEC_DEC_FIELD (1<<7) +#define BT848_TDEC_FLDALIGN (1<<6) +#define BT848_TDEC_DEC_RAT (0x1f) + +#define BT848_E_CROP 0x00C +#define BT848_O_CROP 0x08C + +#define BT848_E_VDELAY_LO 0x010 +#define BT848_O_VDELAY_LO 0x090 + +#define BT848_E_VACTIVE_LO 0x014 +#define BT848_O_VACTIVE_LO 0x094 + +#define BT848_E_HDELAY_LO 0x018 +#define BT848_O_HDELAY_LO 0x098 + +#define BT848_E_HACTIVE_LO 0x01C +#define BT848_O_HACTIVE_LO 0x09C + +#define BT848_E_HSCALE_HI 0x020 +#define BT848_O_HSCALE_HI 0x0A0 + +#define BT848_E_HSCALE_LO 0x024 +#define BT848_O_HSCALE_LO 0x0A4 + +#define BT848_BRIGHT 0x028 + +#define BT848_E_CONTROL 0x02C +#define BT848_O_CONTROL 0x0AC +#define BT848_CONTROL_LNOTCH (1<<7) +#define BT848_CONTROL_COMP (1<<6) +#define BT848_CONTROL_LDEC (1<<5) +#define BT848_CONTROL_CBSENSE (1<<4) +#define BT848_CONTROL_CON_MSB (1<<2) +#define BT848_CONTROL_SAT_U_MSB (1<<1) +#define BT848_CONTROL_SAT_V_MSB (1<<0) + +#define BT848_CONTRAST_LO 0x030 +#define BT848_SAT_U_LO 0x034 +#define BT848_SAT_V_LO 0x038 +#define BT848_HUE 0x03C + +#define BT848_E_SCLOOP 0x040 +#define BT848_O_SCLOOP 0x0C0 +#define BT848_SCLOOP_CAGC (1<<6) +#define BT848_SCLOOP_CKILL (1<<5) +#define BT848_SCLOOP_HFILT_AUTO (0<<3) +#define BT848_SCLOOP_HFILT_CIF (1<<3) +#define BT848_SCLOOP_HFILT_QCIF (2<<3) +#define BT848_SCLOOP_HFILT_ICON (3<<3) + +#define BT848_SCLOOP_PEAK (1<<7) +#define BT848_SCLOOP_HFILT_MINP (1<<3) +#define BT848_SCLOOP_HFILT_MEDP (2<<3) +#define BT848_SCLOOP_HFILT_MAXP (3<<3) + + +#define BT848_OFORM 0x048 +#define BT848_OFORM_RANGE (1<<7) +#define BT848_OFORM_CORE0 (0<<5) +#define BT848_OFORM_CORE8 (1<<5) +#define BT848_OFORM_CORE16 (2<<5) +#define BT848_OFORM_CORE32 (3<<5) + +#define BT848_E_VSCALE_HI 0x04C +#define BT848_O_VSCALE_HI 0x0CC +#define BT848_VSCALE_YCOMB (1<<7) +#define BT848_VSCALE_COMB (1<<6) +#define BT848_VSCALE_INT (1<<5) +#define BT848_VSCALE_HI 15 + +#define BT848_E_VSCALE_LO 0x050 +#define BT848_O_VSCALE_LO 0x0D0 +#define BT848_TEST 0x054 +#define BT848_ADELAY 0x060 +#define BT848_BDELAY 0x064 + +#define BT848_ADC 0x068 +#define BT848_ADC_RESERVED (2<<6) +#define BT848_ADC_SYNC_T (1<<5) +#define BT848_ADC_AGC_EN (1<<4) +#define BT848_ADC_CLK_SLEEP (1<<3) +#define BT848_ADC_Y_SLEEP (1<<2) +#define BT848_ADC_C_SLEEP (1<<1) +#define BT848_ADC_CRUSH (1<<0) + +#define BT848_WC_UP 0x044 +#define BT848_WC_DOWN 0x078 + +#define BT848_E_VTC 0x06C +#define BT848_O_VTC 0x0EC +#define BT848_VTC_HSFMT (1<<7) +#define BT848_VTC_VFILT_2TAP 0 +#define BT848_VTC_VFILT_3TAP 1 +#define BT848_VTC_VFILT_4TAP 2 +#define BT848_VTC_VFILT_5TAP 3 + +#define BT848_SRESET 0x07C + +#define BT848_COLOR_FMT 0x0D4 +#define BT848_COLOR_FMT_O_RGB32 (0<<4) +#define BT848_COLOR_FMT_O_RGB24 (1<<4) +#define BT848_COLOR_FMT_O_RGB16 (2<<4) +#define BT848_COLOR_FMT_O_RGB15 (3<<4) +#define BT848_COLOR_FMT_O_YUY2 (4<<4) +#define BT848_COLOR_FMT_O_BtYUV (5<<4) +#define BT848_COLOR_FMT_O_Y8 (6<<4) +#define BT848_COLOR_FMT_O_RGB8 (7<<4) +#define BT848_COLOR_FMT_O_YCrCb422 (8<<4) +#define BT848_COLOR_FMT_O_YCrCb411 (9<<4) +#define BT848_COLOR_FMT_O_RAW (14<<4) +#define BT848_COLOR_FMT_E_RGB32 0 +#define BT848_COLOR_FMT_E_RGB24 1 +#define BT848_COLOR_FMT_E_RGB16 2 +#define BT848_COLOR_FMT_E_RGB15 3 +#define BT848_COLOR_FMT_E_YUY2 4 +#define BT848_COLOR_FMT_E_BtYUV 5 +#define BT848_COLOR_FMT_E_Y8 6 +#define BT848_COLOR_FMT_E_RGB8 7 +#define BT848_COLOR_FMT_E_YCrCb422 8 +#define BT848_COLOR_FMT_E_YCrCb411 9 +#define BT848_COLOR_FMT_E_RAW 14 + +#define BT848_COLOR_FMT_RGB32 0x00 +#define BT848_COLOR_FMT_RGB24 0x11 +#define BT848_COLOR_FMT_RGB16 0x22 +#define BT848_COLOR_FMT_RGB15 0x33 +#define BT848_COLOR_FMT_YUY2 0x44 +#define BT848_COLOR_FMT_BtYUV 0x55 +#define BT848_COLOR_FMT_Y8 0x66 +#define BT848_COLOR_FMT_RGB8 0x77 +#define BT848_COLOR_FMT_YCrCb422 0x88 +#define BT848_COLOR_FMT_YCrCb411 0x99 +#define BT848_COLOR_FMT_RAW 0xee + +#define BT848_VTOTAL_LO 0xB0 +#define BT848_VTOTAL_HI 0xB4 + +#define BT848_COLOR_CTL 0x0D8 +#define BT848_COLOR_CTL_EXT_FRMRATE (1<<7) +#define BT848_COLOR_CTL_COLOR_BARS (1<<6) +#define BT848_COLOR_CTL_RGB_DED (1<<5) +#define BT848_COLOR_CTL_GAMMA (1<<4) +#define BT848_COLOR_CTL_WSWAP_ODD (1<<3) +#define BT848_COLOR_CTL_WSWAP_EVEN (1<<2) +#define BT848_COLOR_CTL_BSWAP_ODD (1<<1) +#define BT848_COLOR_CTL_BSWAP_EVEN (1<<0) + +#define BT848_CAP_CTL 0x0DC +#define BT848_CAP_CTL_DITH_FRAME (1<<4) +#define BT848_CAP_CTL_CAPTURE_VBI_ODD (1<<3) +#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2) +#define BT848_CAP_CTL_CAPTURE_ODD (1<<1) +#define BT848_CAP_CTL_CAPTURE_EVEN (1<<0) + +#define BT848_VBI_PACK_SIZE 0x0E0 + +#define BT848_VBI_PACK_DEL 0x0E4 +#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc +#define BT848_VBI_PACK_DEL_EXT_FRAME 2 +#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1 + + +#define BT848_INT_STAT 0x100 +#define BT848_INT_MASK 0x104 + +#define BT848_INT_ETBF (1<<23) + +#define BT848_INT_RISCS (0xf<<28) +#define BT848_INT_RISC_EN (1<<27) +#define BT848_INT_RACK (1<<25) +#define BT848_INT_FIELD (1<<24) +#define BT848_INT_SCERR (1<<19) +#define BT848_INT_OCERR (1<<18) +#define BT848_INT_PABORT (1<<17) +#define BT848_INT_RIPERR (1<<16) +#define BT848_INT_PPERR (1<<15) +#define BT848_INT_FDSR (1<<14) +#define BT848_INT_FTRGT (1<<13) +#define BT848_INT_FBUS (1<<12) +#define BT848_INT_RISCI (1<<11) +#define BT848_INT_GPINT (1<<9) +#define BT848_INT_I2CDONE (1<<8) +#define BT848_INT_VPRES (1<<5) +#define BT848_INT_HLOCK (1<<4) +#define BT848_INT_OFLOW (1<<3) +#define BT848_INT_HSYNC (1<<2) +#define BT848_INT_VSYNC (1<<1) +#define BT848_INT_FMTCHG (1<<0) + + +#define BT848_GPIO_DMA_CTL 0x10C +#define BT848_GPIO_DMA_CTL_GPINTC (1<<15) +#define BT848_GPIO_DMA_CTL_GPINTI (1<<14) +#define BT848_GPIO_DMA_CTL_GPWEC (1<<13) +#define BT848_GPIO_DMA_CTL_GPIOMODE (3<<11) +#define BT848_GPIO_DMA_CTL_GPCLKMODE (1<<10) +#define BT848_GPIO_DMA_CTL_PLTP23_4 (0<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_8 (1<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_16 (2<<6) +#define BT848_GPIO_DMA_CTL_PLTP23_32 (3<<6) +#define BT848_GPIO_DMA_CTL_PLTP1_4 (0<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_8 (1<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_16 (2<<4) +#define BT848_GPIO_DMA_CTL_PLTP1_32 (3<<4) +#define BT848_GPIO_DMA_CTL_PKTP_4 (0<<2) +#define BT848_GPIO_DMA_CTL_PKTP_8 (1<<2) +#define BT848_GPIO_DMA_CTL_PKTP_16 (2<<2) +#define BT848_GPIO_DMA_CTL_PKTP_32 (3<<2) +#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1) +#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0) + +#define BT848_I2C 0x110 +#define BT878_I2C_MODE (1<<7) +#define BT878_I2C_RATE (1<<6) +#define BT878_I2C_NOSTOP (1<<5) +#define BT878_I2C_NOSTART (1<<4) +#define BT848_I2C_DIV (0xf<<4) +#define BT848_I2C_SYNC (1<<3) +#define BT848_I2C_W3B (1<<2) +#define BT848_I2C_SCL (1<<1) +#define BT848_I2C_SDA (1<<0) + +#define BT848_RISC_STRT_ADD 0x114 +#define BT848_GPIO_OUT_EN 0x118 +#define BT848_GPIO_REG_INP 0x11C +#define BT848_RISC_COUNT 0x120 +#define BT848_GPIO_DATA 0x200 + + +/* Bt848 RISC commands */ + +/* only for the SYNC RISC command */ +#define BT848_FIFO_STATUS_FM1 0x06 +#define BT848_FIFO_STATUS_FM3 0x0e +#define BT848_FIFO_STATUS_SOL 0x02 +#define BT848_FIFO_STATUS_EOL4 0x01 +#define BT848_FIFO_STATUS_EOL3 0x0d +#define BT848_FIFO_STATUS_EOL2 0x09 +#define BT848_FIFO_STATUS_EOL1 0x05 +#define BT848_FIFO_STATUS_VRE 0x04 +#define BT848_FIFO_STATUS_VRO 0x0c +#define BT848_FIFO_STATUS_PXV 0x00 + +#define BT848_RISC_RESYNC (1<<15) + +/* WRITE and SKIP */ +/* disable which bytes of each DWORD */ +#define BT848_RISC_BYTE0 (1U<<12) +#define BT848_RISC_BYTE1 (1U<<13) +#define BT848_RISC_BYTE2 (1U<<14) +#define BT848_RISC_BYTE3 (1U<<15) +#define BT848_RISC_BYTE_ALL (0x0fU<<12) +#define BT848_RISC_BYTE_NONE 0 +/* cause RISCI */ +#define BT848_RISC_IRQ (1U<<24) +/* RISC command is last one in this line */ +#define BT848_RISC_EOL (1U<<26) +/* RISC command is first one in this line */ +#define BT848_RISC_SOL (1U<<27) + +#define BT848_RISC_WRITE (0x01U<<28) +#define BT848_RISC_SKIP (0x02U<<28) +#define BT848_RISC_WRITEC (0x05U<<28) +#define BT848_RISC_JUMP (0x07U<<28) +#define BT848_RISC_SYNC (0x08U<<28) + +#define BT848_RISC_WRITE123 (0x09U<<28) +#define BT848_RISC_SKIP123 (0x0aU<<28) +#define BT848_RISC_WRITE1S23 (0x0bU<<28) + + +/* Bt848A and higher only !! */ +#define BT848_TGLB 0x080 +#define BT848_TGCTRL 0x084 +#define BT848_FCAP 0x0E8 +#define BT848_PLL_F_LO 0x0F0 +#define BT848_PLL_F_HI 0x0F4 + +#define BT848_PLL_XCI 0x0F8 +#define BT848_PLL_X (1<<7) +#define BT848_PLL_C (1<<6) + +#define BT848_DVSIF 0x0FC + +/* Bt878 register */ + +#define BT878_DEVCTRL 0x40 +#define BT878_EN_TBFX 0x02 +#define BT878_EN_VSFX 0x04 + +#endif diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c new file mode 100644 index 000000000000..abfa6ad857a0 --- /dev/null +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -0,0 +1,5011 @@ +/* + + bttv-cards.c + + this file has configuration informations - card-specific stuff + like the big tvcards array for the most part + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) + (c) 1999-2001 Gerd Knorr + + 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 + +#include + +#include "bttvp.h" +#include + +/* fwd decl */ +static void boot_msp34xx(struct bttv *btv, int pin); +static void boot_bt832(struct bttv *btv); +static void hauppauge_eeprom(struct bttv *btv); +static void avermedia_eeprom(struct bttv *btv); +static void osprey_eeprom(struct bttv *btv); +static void modtec_eeprom(struct bttv *btv); +static void init_PXC200(struct bttv *btv); +static void init_RTV24(struct bttv *btv); + +static void winview_audio(struct bttv *btv, struct video_audio *v, int set); +static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set); +static void avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, + int set); +static void avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, + int set); +static void terratv_audio(struct bttv *btv, struct video_audio *v, int set); +static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set); +static void gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set); +static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set); +static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set); +static void fv2000s_audio(struct bttv *btv, struct video_audio *v, int set); +static void windvr_audio(struct bttv *btv, struct video_audio *v, int set); +static void adtvk503_audio(struct bttv *btv, struct video_audio *v, int set); +static void rv605_muxsel(struct bttv *btv, unsigned int input); +static void eagle_muxsel(struct bttv *btv, unsigned int input); +static void xguard_muxsel(struct bttv *btv, unsigned int input); +static void ivc120_muxsel(struct bttv *btv, unsigned int input); +static void gvc1100_muxsel(struct bttv *btv, unsigned int input); + +static void PXC200_muxsel(struct bttv *btv, unsigned int input); + +static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input); +static void picolo_tetra_init(struct bttv *btv); + +static void tibetCS16_muxsel(struct bttv *btv, unsigned int input); +static void tibetCS16_init(struct bttv *btv); + +static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input); +static void kodicom4400r_init(struct bttv *btv); + +static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input); +static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input); + +static int terratec_active_radio_upgrade(struct bttv *btv); +static int tea5757_read(struct bttv *btv); +static int tea5757_write(struct bttv *btv, int value); +static void identify_by_eeprom(struct bttv *btv, + unsigned char eeprom_data[256]); +static int __devinit pvr_boot(struct bttv *btv); + +/* config variables */ +static unsigned int triton1; +static unsigned int vsfx; +static unsigned int latency = UNSET; +int no_overlay=-1; + +static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static unsigned int svhs[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static unsigned int remote[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static struct bttv *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL }; +#ifdef MODULE +static unsigned int autoload = 1; +#else +static unsigned int autoload; +#endif +static unsigned int gpiomask = UNSET; +static unsigned int audioall = UNSET; +static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET }; + +/* insmod options */ +module_param(triton1, int, 0444); +module_param(vsfx, int, 0444); +module_param(no_overlay, int, 0444); +module_param(latency, int, 0444); +module_param(gpiomask, int, 0444); +module_param(audioall, int, 0444); +module_param(autoload, int, 0444); + +module_param_array(card, int, NULL, 0444); +module_param_array(pll, int, NULL, 0444); +module_param_array(tuner, int, NULL, 0444); +module_param_array(svhs, int, NULL, 0444); +module_param_array(remote, int, NULL, 0444); +module_param_array(audiomux, int, NULL, 0444); + +MODULE_PARM_DESC(triton1,"set ETBF pci config bit " + "[enable bug compatibility for triton1 + others]"); +MODULE_PARM_DESC(vsfx,"set VSFX pci config bit " + "[yet another chipset flaw workaround]"); +MODULE_PARM_DESC(latency,"pci latency timer"); +MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list"); +MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)"); +MODULE_PARM_DESC(tuner,"specify installed tuner type"); +MODULE_PARM_DESC(autoload,"automatically load i2c modules like tuner.o, default is 1 (yes)"); +MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)" + " [some VIA/SIS chipsets are known to have problem with overlay]"); + +/* ----------------------------------------------------------------------- */ +/* list of card IDs for bt878+ cards */ + +static struct CARD { + unsigned id; + int cardnr; + char *name; +} cards[] __devinitdata = { + { 0x13eb0070, BTTV_BOARD_HAUPPAUGE878, "Hauppauge WinTV" }, + { 0x39000070, BTTV_BOARD_HAUPPAUGE878, "Hauppauge WinTV-D" }, + { 0x45000070, BTTV_BOARD_HAUPPAUGEPVR, "Hauppauge WinTV/PVR" }, + { 0xff000070, BTTV_BOARD_OSPREY1x0, "Osprey-100" }, + { 0xff010070, BTTV_BOARD_OSPREY2x0_SVID,"Osprey-200" }, + { 0xff020070, BTTV_BOARD_OSPREY500, "Osprey-500" }, + { 0xff030070, BTTV_BOARD_OSPREY2000, "Osprey-2000" }, + { 0xff040070, BTTV_BOARD_OSPREY540, "Osprey-540" }, + { 0xff070070, BTTV_BOARD_OSPREY440, "Osprey-440" }, + + { 0x00011002, BTTV_BOARD_ATI_TVWONDER, "ATI TV Wonder" }, + { 0x00031002, BTTV_BOARD_ATI_TVWONDERVE,"ATI TV Wonder/VE" }, + + { 0x6606107d, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, + { 0x6607107d, BTTV_BOARD_WINFASTVC100, "Leadtek WinFast VC 100" }, + { 0x6609107d, BTTV_BOARD_WINFAST2000, "Leadtek TV 2000 XP" }, + { 0x263610b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, + { 0x264510b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, + { 0x402010fc, BTTV_BOARD_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, + { 0x405010fc, BTTV_BOARD_GVBCTV4PCI, "I-O Data Co. GV-BCTV4/PCI" }, + { 0x407010fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, + { 0xd01810fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, + + { 0x001211bd, BTTV_BOARD_PINNACLE, "Pinnacle PCTV" }, + /* some cards ship with byteswapped IDs ... */ + { 0x1200bd11, BTTV_BOARD_PINNACLE, "Pinnacle PCTV [bswap]" }, + { 0xff00bd11, BTTV_BOARD_PINNACLE, "Pinnacle PCTV [bswap]" }, + /* this seems to happen as well ... */ + { 0xff1211bd, BTTV_BOARD_PINNACLE, "Pinnacle PCTV" }, + + { 0x3000121a, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, + { 0x263710b4, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, + { 0x3060121a, BTTV_BOARD_STB2, "3Dfx VoodooTV 100/ STB OEM" }, + + { 0x3000144f, BTTV_BOARD_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" }, + { 0xa005144f, BTTV_BOARD_MAGICTVIEW063, "CPH06X TView99-Card" }, + { 0x3002144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" }, + { 0x3005144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" }, + { 0x5000144f, BTTV_BOARD_MAGICTVIEW061, "Askey CPH050" }, + { 0x300014ff, BTTV_BOARD_MAGICTVIEW061, "TView 99 (CPH061)" }, + { 0x300214ff, BTTV_BOARD_PHOEBE_TVMAS, "Phoebe TV Master (CPH060)" }, + + { 0x00011461, BTTV_BOARD_AVPHONE98, "AVerMedia TVPhone98" }, + { 0x00021461, BTTV_BOARD_AVERMEDIA98, "AVermedia TVCapture 98" }, + { 0x00031461, BTTV_BOARD_AVPHONE98, "AVerMedia TVPhone98" }, + { 0x00041461, BTTV_BOARD_AVERMEDIA98, "AVerMedia TVCapture 98" }, + { 0x03001461, BTTV_BOARD_AVERMEDIA98, "VDOMATE TV TUNER CARD" }, + + { 0x1117153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Philips PAL B/G)" }, + { 0x1118153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Temic PAL B/G)" }, + { 0x1119153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Philips PAL I)" }, + { 0x111a153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Temic PAL I)" }, + + { 0x1123153b, BTTV_BOARD_TERRATVRADIO, "Terratec TV Radio+" }, + { 0x1127153b, BTTV_BOARD_TERRATV, "Terratec TV+ (V1.05)" }, + /* clashes with FlyVideo + *{ 0x18521852, BTTV_BOARD_TERRATV, "Terratec TV+ (V1.10)" }, */ + { 0x1134153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (LR102)" }, + { 0x1135153b, BTTV_BOARD_TERRATVALUER, "Terratec TValue Radio" }, /* LR102 */ + { 0x5018153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue" }, /* ?? */ + { 0xff3b153b, BTTV_BOARD_TERRATVALUER, "Terratec TValue Radio" }, /* ?? */ + + { 0x400015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" }, + { 0x400a15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" }, + { 0x400d15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, + { 0x401015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, + { 0x401615b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, + + { 0x1430aa00, BTTV_BOARD_PV143, "Provideo PV143A" }, + { 0x1431aa00, BTTV_BOARD_PV143, "Provideo PV143B" }, + { 0x1432aa00, BTTV_BOARD_PV143, "Provideo PV143C" }, + { 0x1433aa00, BTTV_BOARD_PV143, "Provideo PV143D" }, + { 0x1433aa03, BTTV_BOARD_PV143, "Security Eyes" }, + + { 0x1460aa00, BTTV_BOARD_PV150, "Provideo PV150A-1" }, + { 0x1461aa01, BTTV_BOARD_PV150, "Provideo PV150A-2" }, + { 0x1462aa02, BTTV_BOARD_PV150, "Provideo PV150A-3" }, + { 0x1463aa03, BTTV_BOARD_PV150, "Provideo PV150A-4" }, + + { 0x1464aa04, BTTV_BOARD_PV150, "Provideo PV150B-1" }, + { 0x1465aa05, BTTV_BOARD_PV150, "Provideo PV150B-2" }, + { 0x1466aa06, BTTV_BOARD_PV150, "Provideo PV150B-3" }, + { 0x1467aa07, BTTV_BOARD_PV150, "Provideo PV150B-4" }, + + { 0xa132ff00, BTTV_BOARD_IVC100, "IVC-100" }, + { 0xa1550000, BTTV_BOARD_IVC200, "IVC-200" }, + { 0xa1550001, BTTV_BOARD_IVC200, "IVC-200" }, + { 0xa1550002, BTTV_BOARD_IVC200, "IVC-200" }, + { 0xa1550003, BTTV_BOARD_IVC200, "IVC-200" }, + { 0xa1550100, BTTV_BOARD_IVC200, "IVC-200G" }, + { 0xa1550101, BTTV_BOARD_IVC200, "IVC-200G" }, + { 0xa1550102, BTTV_BOARD_IVC200, "IVC-200G" }, + { 0xa1550103, BTTV_BOARD_IVC200, "IVC-200G" }, + { 0xa182ff00, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff01, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff02, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff03, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff04, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff05, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff06, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff07, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff08, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff09, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0a, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0b, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0c, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0d, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0e, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0f, BTTV_BOARD_IVC120, "IVC-120G" }, + + { 0x41424344, BTTV_BOARD_GRANDTEC, "GrandTec Multi Capture" }, + { 0x01020304, BTTV_BOARD_XGUARD, "Grandtec Grand X-Guard" }, + + { 0x18501851, BTTV_BOARD_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, + { 0xa0501851, BTTV_BOARD_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, + { 0x18511851, BTTV_BOARD_FLYVIDEO98EZ, "FlyVideo 98EZ (LR51)/ CyberMail AV" }, + { 0x18521852, BTTV_BOARD_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" }, + { 0x41a0a051, BTTV_BOARD_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" }, + { 0x18501f7f, BTTV_BOARD_FLYVIDEO_98, "Lifeview Flyvideo 98" }, + + { 0x010115cb, BTTV_BOARD_GMV1, "AG GMV1" }, + { 0x010114c7, BTTV_BOARD_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" }, + + { 0x10b42636, BTTV_BOARD_HAUPPAUGE878, "STB ???" }, + { 0x217d6606, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, + { 0xfff6f6ff, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, + { 0x03116000, BTTV_BOARD_SENSORAY311, "Sensoray 311" }, + { 0x00790e11, BTTV_BOARD_WINDVR, "Canopus WinDVR PCI" }, + { 0xa0fca1a0, BTTV_BOARD_ZOLTRIX, "Face to Face Tvmax" }, + { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" }, + { 0x146caa0c, BTTV_BOARD_PV951, "ituner spectra8" }, + { 0x200a1295, BTTV_BOARD_PXC200, "ImageNation PXC200A" }, + + { 0x40111554, BTTV_BOARD_PV_BT878P_9B, "Prolink Pixelview PV-BT" }, + { 0x17de0a01, BTTV_BOARD_KWORLD, "Mecer TV/FM/Video Tuner" }, + + { 0x01051805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #1" }, + { 0x01061805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #2" }, + { 0x01071805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" }, + { 0x01081805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" }, + + { 0x15409511, BTTV_BOARD_ACORP_Y878F, "Acorp Y878F" }, + + /* likely broken, vendor id doesn't match the other magic views ... + * { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */ + + /* Duplicate PCI ID, reconfigure for this board during the eeprom read. + * { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB, "Hauppauge ImpactVCB" }, */ + + /* DVB cards (using pci function .1 for mpeg data xfer) */ + { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" }, + { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, + { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, + { 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, + { 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" }, + { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, + { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, + { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, + { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, + { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, + + { 0, -1, NULL } +}; + +/* ----------------------------------------------------------------------- */ +/* array with description for bt848 / bt878 tv/grabber cards */ + +struct tvcard bttv_tvcards[] = { + /* ---- card 0x00 ---------------------------------- */ + [BTTV_BOARD_UNKNOWN] = { + .name = " *** UNKNOWN/GENERIC *** ", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 0 }, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_MIRO] = { + .name = "MIRO PCTV", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 2, 0, 0, 0, 10 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_HAUPPAUGE] = { + .name = "Hauppauge (bt848)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 1, 2, 3, 4 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_STB] = { + .name = "STB, Gateway P/N 6000699 (bt848)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 4, 0, 2, 3, 1 }, + .no_msp34xx = 1, + .needs_tvaudio = 1, + .tuner_type = TUNER_PHILIPS_NTSC, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + }, + + /* ---- card 0x04 ---------------------------------- */ + [BTTV_BOARD_INTEL] = { + .name = "Intel Create and Share PCI/ Smart Video Recorder III", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = 2, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .tuner_type = 4, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_DIAMOND] = { + .name = "Diamond DTV2000", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 3, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 0, 1, 0, 1, 3 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_AVERMEDIA] = { + .name = "AVerMedia TVPhone", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .muxsel = { 2, 3, 1, 1 }, + .gpiomask = 0x0f, + .audiomux = { 0x0c, 0x04, 0x08, 0x04, 0 }, + /* 0x04 for some cards ?? */ + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = avermedia_tvphone_audio, + .has_remote = 1, + }, + [BTTV_BOARD_MATRIX_VISION] = { + .name = "MATRIX-Vision MV-Delta", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = -1, + .svhs = 3, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0, 0 }, + .audiomux = { 0 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x08 ---------------------------------- */ + [BTTV_BOARD_FLYVIDEO] = { + .name = "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xc00, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 0xc00, 0x800, 0x400, 0xc00, 0 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_TURBOTV] = { + .name = "IMS/IXmicro TurboTV", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 3, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 1, 1, 2, 3, 0 }, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_TEMIC_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_HAUPPAUGE878] = { + .name = "Hauppauge (bt878)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x0f, /* old: 7 */ + .muxsel = { 2, 0, 1, 1 }, + .audiomux = { 0, 1, 2, 3, 4 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_MIROPRO] = { + .name = "MIRO PCTV pro", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x3014f, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x20001,0x10001, 0, 0,10 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x0c ---------------------------------- */ + [BTTV_BOARD_ADSTECH_TV] = { + .name = "ADS Technologies Channel Surfer TV (bt848)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 13, 14, 11, 7, 0, 0 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_AVERMEDIA98] = { + .name = "AVerMedia TVCapture 98", + .video_inputs = 3, + .audio_inputs = 4, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 13, 14, 11, 7, 0, 0 }, + .needs_tvaudio = 1, + .msp34xx_alt = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = avermedia_tv_stereo_audio, + .no_gpioirq = 1, + }, + [BTTV_BOARD_VHX] = { + .name = "Aimslab Video Highway Xtreme (VHX)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 2, 1, 3, 4 }, /* old: {0, 1, 2, 3, 4} */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_ZOLTRIX] = { + .name = "Zoltrix TV-Max", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0 , 0, 1 , 0, 10 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x10 ---------------------------------- */ + [BTTV_BOARD_PIXVIEWPLAYTV] = { + .name = "Prolink Pixelview PlayTV (bt878)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x01fe00, + .muxsel = { 2, 3, 1, 1 }, + #if 0 + /* old */ + .audiomux = { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }, + #else + /* 2003-10-20 by "Anton A. Arapov" */ + .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 }, + #endif + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + }, + [BTTV_BOARD_WINVIEW_601] = { + .name = "Leadtek WinView 601", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x8300f8, + .muxsel = { 2, 3, 1, 1,0 }, + .audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = winview_audio, + .has_radio = 1, + }, + [BTTV_BOARD_AVEC_INTERCAP] = { + .name = "AVEC Intercapture", + .video_inputs = 3, + .audio_inputs = 2, + .tuner = 0, + .svhs = 2, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 1, 0, 0, 0, 0 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_LIFE_FLYKIT] = { + .name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x8dff00, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0 }, + .no_msp34xx = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x14 ---------------------------------- */ + [BTTV_BOARD_CEI_RAFFLES] = { + .name = "CEI Raffles Card", + .video_inputs = 3, + .audio_inputs = 3, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 1 }, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_CONFERENCETV] = { + .name = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50", + .video_inputs = 4, + .audio_inputs = 2, /* tuner, line in */ + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1800, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 }, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL_I, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_PHOEBE_TVMAS] = { + .name = "Askey CPH050/ Phoebe Tv Master + FM", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xc00, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 1, 0x800, 0x400, 0xc00, 0 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_MODTEC_205] = { + .name = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 7, + .muxsel = { 2, 3, -1 }, + .digital_mode = DIGITAL_MODE_CAMERA, + .audiomux = { 0, 0, 0, 0, 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_ALPS_TSBB5_PAL_I, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x18 ---------------------------------- */ + [BTTV_BOARD_MAGICTVIEW061] = { + .name = "Askey CPH05X/06X (bt878) [many vendors]", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xe00, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = {0x400, 0x400, 0x400, 0x400, 0xc00 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_remote = 1, + }, + [BTTV_BOARD_VOBIS_BOOSTAR] = { + .name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1f0fff, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000 }, + .needs_tvaudio = 0, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = terratv_audio, + }, + [BTTV_BOARD_HAUPPAUG_WCAM] = { + .name = "Hauppauge WinCam newer (bt878)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 7, + .muxsel = { 2, 0, 1, 1 }, + .audiomux = { 0, 1, 2, 3, 4 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_MAXI] = { + .name = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50", + .video_inputs = 4, + .audio_inputs = 2, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1800, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 }, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_SECAM, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x1c ---------------------------------- */ + [BTTV_BOARD_TERRATV] = { + .name = "Terratec TerraTV+ Version 1.1 (bt878)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1f0fff, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000 }, + .needs_tvaudio = 0, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = terratv_audio, + /* GPIO wiring: + External 20 pin connector (for Active Radio Upgrade board) + gpio00: i2c-sda + gpio01: i2c-scl + gpio02: om5610-data + gpio03: om5610-clk + gpio04: om5610-wre + gpio05: om5610-stereo + gpio06: rds6588-davn + gpio07: Pin 7 n.c. + gpio08: nIOW + gpio09+10: nIOR, nSEL ?? (bt878) + gpio09: nIOR (bt848) + gpio10: nSEL (bt848) + Sound Routing: + gpio16: u2-A0 (1st 4052bt) + gpio17: u2-A1 + gpio18: u2-nEN + gpio19: u4-A0 (2nd 4052) + gpio20: u4-A1 + u4-nEN - GND + Btspy: + 00000 : Cdrom (internal audio input) + 10000 : ext. Video audio input + 20000 : TV Mono + a0000 : TV Mono/2 + 1a0000 : TV Stereo + 30000 : Radio + 40000 : Mute + */ + + }, + [BTTV_BOARD_PXC200] = { + /* Jannik Fritsch */ + .name = "Imagenation PXC200", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, /* was: 4 */ + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0, 0}, + .audiomux = { 0 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .muxsel_hook = PXC200_muxsel, + + }, + [BTTV_BOARD_FLYVIDEO_98] = { + .name = "Lifeview FlyVideo 98 LR50", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1800, /* 0x8dfe00 */ + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_IPROTV] = { + .name = "Formac iProTV, Formac ProTV I (bt848)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 1, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 1, 0, 0, 0, 0 }, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x20 ---------------------------------- */ + [BTTV_BOARD_INTEL_C_S_PCI] = { + .name = "Intel Create and Share PCI/ Smart Video Recorder III", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = 2, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .tuner_type = 4, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_TERRATVALUE] = { + .name = "Terratec TerraTValue Version Bt878", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xffff00, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x500, 0, 0x300, 0x900, 0x900 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_WINFAST2000] = { + .name = "Leadtek WinFast 2000/ WinFast 2000 XP", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */ + #if 0 + .gpiomask = 0xc33000, + .audiomux = { 0x422000,0x1000,0x0000,0x620000,0x800000 }, + #else + /* Alexander Varakin [stereo version] */ + .gpiomask = 0xb33000, + .audiomux = { 0x122000,0x1000,0x0000,0x620000,0x800000 }, + #endif + /* Audio Routing for "WinFast 2000 XP" (no tv stereo !) + gpio23 -- hef4052:nEnable (0x800000) + gpio12 -- hef4052:A1 + gpio13 -- hef4052:A0 + 0x0000: external audio + 0x1000: FM + 0x2000: TV + 0x3000: n.c. + Note: There exists another variant "Winfast 2000" with tv stereo !? + Note: eeprom only contains FF and pci subsystem id 107d:6606 + */ + .needs_tvaudio = 0, + .pll = PLL_28, + .has_radio = 1, + .tuner_type = 5, /* default for now, gpio reads BFFF06 for Pal bg+dk */ + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = winfast2000_audio, + .has_remote = 1, + }, + [BTTV_BOARD_CHRONOS_VS2] = { + .name = "Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II", + .video_inputs = 4, + .audio_inputs = 3, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1800, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x24 ---------------------------------- */ + [BTTV_BOARD_TYPHOON_TVIEW] = { + .name = "Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner", + .video_inputs = 4, + .audio_inputs = 3, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1800, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_radio = 1, + }, + [BTTV_BOARD_PXELVWPLTVPRO] = { + .name = "Prolink PixelView PlayTV pro", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xff, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_MAGICTVIEW063] = { + .name = "Askey CPH06X TView99", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x551e00, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = 1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_remote = 1, + }, + [BTTV_BOARD_PINNACLE] = { + .name = "Pinnacle PCTV Studio/Rave", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x03000F, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 2, 0xd0001, 0, 0, 1 }, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x28 ---------------------------------- */ + [BTTV_BOARD_STB2] = { + .name = "STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 4, 0, 2, 3, 1 }, + .no_msp34xx = 1, + .needs_tvaudio = 1, + .tuner_type = TUNER_PHILIPS_NTSC, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + }, + [BTTV_BOARD_AVPHONE98] = { + .name = "AVerMedia TVPhone 98", + .video_inputs = 3, + .audio_inputs = 4, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 13, 4, 11, 7, 0, 0 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_radio = 1, + .audio_hook = avermedia_tvphone_audio, + }, + [BTTV_BOARD_PV951] = { + .name = "ProVideo PV951", /* pic16c54 */ + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 0, 0, 0, 0}, + .needs_tvaudio = 1, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = 1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_ONAIR_TV] = { + .name = "Little OnAir TV", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xe00b, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc }, + .no_msp34xx = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x2c ---------------------------------- */ + [BTTV_BOARD_SIGMA_TVII_FM] = { + .name = "Sigma TVII-FM", + .video_inputs = 2, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 3, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 1, 1, 0, 2, 3 }, + .no_msp34xx = 1, + .pll = PLL_NONE, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_MATRIX_VISION2] = { + .name = "MATRIX-Vision MV-Delta 2", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = -1, + .svhs = 3, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0, 0 }, + .audiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_ZOLTRIX_GENIE] = { + .name = "Zoltrix Genie TV/FM", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xbcf03f, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = 21, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_TERRATVRADIO] = { + .name = "Terratec TV/Radio+", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x70000, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000, 0x20000 }, + .needs_tvaudio = 1, + .no_msp34xx = 1, + .pll = PLL_35, + .tuner_type = 1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_radio = 1, + }, + + /* ---- card 0x30 ---------------------------------- */ + [BTTV_BOARD_DYNALINK] = { + .name = "Askey CPH03x/ Dynalink Magic TView", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = {2,0,0,0,1 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_GVBCTV3PCI] = { + .name = "IODATA GV-BCTV3/PCI", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x010f00, + .muxsel = {2, 3, 0, 0 }, + .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_ALPS_TSHC6_NTSC, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = gvbctv3pci_audio, + }, + [BTTV_BOARD_PXELVWPLTVPAK] = { + .name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 0xAA0000, + .muxsel = { 2,3,1,1,-1 }, + .digital_mode = DIGITAL_MODE_CAMERA, + .audiomux = { 0x20000, 0, 0x80000, 0x80000, 0xa8000, 0x46000 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL_I, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_remote = 1, + /* GPIO wiring: (different from Rev.4C !) + GPIO17: U4.A0 (first hef4052bt) + GPIO19: U4.A1 + GPIO20: U5.A1 (second hef4052bt) + GPIO21: U4.nEN + GPIO22: BT832 Reset Line + GPIO23: A5,A0, U5,nEN + Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22 + */ + }, + [BTTV_BOARD_EAGLE] = { + .name = "Eagle Wireless Capricorn2 (bt878A)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 0, 1, 1 }, + .audiomux = { 0, 1, 2, 3, 4 }, + .pll = PLL_28, + .tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x34 ---------------------------------- */ + [BTTV_BOARD_PINNACLEPRO] = { + /* David Härdeman */ + .name = "Pinnacle PCTV Studio Pro", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 0x03000F, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 1, 0xd0001, 0, 0, 10 }, + /* sound path (5 sources): + MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable) + 0= ext. Audio IN + 1= from MUX2 + 2= Mono TV sound from Tuner + 3= not connected + MUX2 (mask 0x30000): + 0,2,3= from MSP34xx + 1= FM stereo Radio from Tuner */ + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_TVIEW_RDS_FM] = { + /* Claas Langbehn , + Sven Grothklags */ + .name = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS", + .video_inputs = 4, + .audio_inputs = 3, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1c, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 0, 0x10, 8, 4 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_radio = 1, + }, + [BTTV_BOARD_LIFETEC_9415] = { + /* Tim Röstermundt + in de.comp.os.unix.linux.hardware: + options bttv card=0 pll=1 radio=1 gpiomask=0x18e0 + audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff + options tuner type=5 */ + .name = "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x18e0, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x0000,0x0800,0x1000,0x1000,0x18e0 }, + /* For cards with tda9820/tda9821: + 0x0000: Tuner normal stereo + 0x0080: Tuner A2 SAP (second audio program = Zweikanalton) + 0x0880: Tuner A2 stereo */ + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_BESTBUY_EASYTV] = { + /* Miguel Angel Alvarez + old Easy TV BT848 version (model CPH031) */ + .name = "Askey CPH031/ BESTBUY Easy TV", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xF, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 2, 0, 0, 0, 10 }, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_TEMIC_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x38 ---------------------------------- */ + [BTTV_BOARD_FLYVIDEO_98FM] = { + /* Gordon Heydon */ + [BTTV_BOARD_GRANDTEC] = { + .name = "GrandTec 'Grand Video Capture' (Bt848)", + .video_inputs = 2, + .audio_inputs = 0, + .tuner = -1, + .svhs = 1, + .gpiomask = 0, + .muxsel = { 3, 1 }, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_35, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_ASKEY_CPH060] = { + /* Daniel Herrington */ + .name = "Askey CPH060/ Phoebe TV Master Only (No FM)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xe00, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = TUNER_TEMIC_4036FY5_NTSC, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_ASKEY_CPH03X] = { + /* Matti Mottus */ + .name = "Askey CPH03x TV Capturer", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x03000F, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 2, 0, 0, 0, 1 }, + .pll = PLL_28, + .tuner_type = 0, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x3c ---------------------------------- */ + [BTTV_BOARD_MM100PCTV] = { + /* Philip Blundell */ + .name = "Modular Technology MM100PCTV", + .video_inputs = 2, + .audio_inputs = 2, + .tuner = 0, + .svhs = -1, + .gpiomask = 11, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 2, 0, 0, 1, 8 }, + .pll = PLL_35, + .tuner_type = TUNER_TEMIC_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_GMV1] = { + /* Adrian Cox + new Easy TV BT878 version (model CPH061) + special thanks to Informatica Mieres for providing the card */ + .name = "Askey CPH061/ BESTBUY Easy TV (bt878)", + .video_inputs = 3, + .audio_inputs = 2, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xFF, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 1, 0, 4, 4, 9 }, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_ATI_TVWONDER] = { + /* Lukas Gebauer */ + .name = "ATI TV-Wonder", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xf03f, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe }, + .pll = PLL_28, + .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x40 ---------------------------------- */ + [BTTV_BOARD_ATI_TVWONDERVE] = { + /* Lukas Gebauer */ + .name = "ATI TV-Wonder VE", + .video_inputs = 2, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 1, + .muxsel = { 2, 3, 0, 1 }, + .audiomux = { 0, 0, 1, 0, 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_FLYVIDEO2000] = { + /* DeeJay */ + .name = "IODATA GV-BCTV4/PCI", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x010f00, + .muxsel = {2, 3, 0, 0 }, + .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_SHARP_2U5JF5540_NTSC, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = gvbctv3pci_audio, + }, + + /* ---- card 0x44 ---------------------------------- */ + [BTTV_BOARD_VOODOOTV_FM] = { + .name = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)", + /* try "insmod msp3400 simple=0" if you have + * sound problems with this card. */ + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 0x4f8a00, + /* 0x100000: 1=MSP enabled (0=disable again) + * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */ + .audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff}, + /* tvtuner, radio, external,internal, mute, stereo + * tuner, Composit, SVid, Composit-on-Svid-adapter */ + .muxsel = { 2, 3 ,0 ,1 }, + .tuner_type = TUNER_MT2032, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + }, + [BTTV_BOARD_AIMMS] = { + /* Philip Blundell */ + .name = "Active Imaging AIMMS", + .video_inputs = 1, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + .muxsel = { 2 }, + .gpiomask = 0 + }, + [BTTV_BOARD_PV_BT878P_PLUS] = { + /* Tomasz Pyra */ + .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)", + .video_inputs = 3, + .audio_inputs = 4, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 0, 11, 7, 13, 0 }, /* TV and Radio with same GPIO ! */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = 25, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_remote = 1, + /* GPIO wiring: + GPIO0: U4.A0 (hef4052bt) + GPIO1: U4.A1 + GPIO2: U4.A1 (second hef4052bt) + GPIO3: U4.nEN, U5.A0, A5.nEN + GPIO8-15: vrd866b ? + */ + }, + [BTTV_BOARD_FLYVIDEO98EZ] = { + .name = "Lifeview FlyVideo 98EZ (capture only) LR51", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = 2, + .muxsel = { 2, 3, 1, 1 }, /* AV1, AV2, SVHS, CVid adapter on SVHS */ + .pll = PLL_28, + .no_msp34xx = 1, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x48 ---------------------------------- */ + [BTTV_BOARD_PV_BT878P_9B] = { + /* Dariusz Kowalewski */ + .name = "Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x3f, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x01, 0x00, 0x03, 0x03, 0x09, 0x02 }, + .needs_tvaudio = 1, + .no_msp34xx = 1, + .no_tda9875 = 1, + .pll = PLL_28, + .tuner_type = 5, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = pvbt878p9b_audio, /* Note: not all cards have stereo */ + .has_radio = 1, /* Note: not all cards have radio */ + .has_remote = 1, + /* GPIO wiring: + GPIO0: A0 hef4052 + GPIO1: A1 hef4052 + GPIO3: nEN hef4052 + GPIO8-15: vrd866b + GPIO20,22,23: R30,R29,R28 + */ + }, + [BTTV_BOARD_SENSORAY311] = { + /* Clay Kunz */ + /* you must jumper JP5 for the card to work */ + .name = "Sensoray 311", + .video_inputs = 5, + .audio_inputs = 0, + .tuner = -1, + .svhs = 4, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0, 0 }, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_RV605] = { + /* Miguel Freitas */ + .name = "RemoteVision MX (RV605)", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x00, + .gpiomask2 = 0x07ff, + .muxsel = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03, + 0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .muxsel_hook = rv605_muxsel, + }, + [BTTV_BOARD_POWERCLR_MTV878] = { + .name = "Powercolor MTV878/ MTV878R/ MTV878F", + .video_inputs = 3, + .audio_inputs = 2, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1C800F, /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */ + .muxsel = { 2, 1, 1, }, + .audiomux = { 0, 1, 2, 2, 4 }, + .needs_tvaudio = 0, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + }, + + /* ---- card 0x4c ---------------------------------- */ + [BTTV_BOARD_WINDVR] = { + /* Masaki Suzuki */ + .name = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x140007, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 1, 2, 3, 4, 0 }, + .tuner_type = TUNER_PHILIPS_NTSC, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = windvr_audio, + }, + [BTTV_BOARD_GRANDTEC_MULTI] = { + .name = "GrandTec Multi Capture Card (Bt878)", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_KWORLD] = { + .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF", + .video_inputs = 4, + .audio_inputs = 3, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1 }, /* Tuner, SVid, SVHS, SVid to SVHS connector */ + .audiomux = { 0 ,0 ,4, 4,4,4},/* Yes, this tuner uses the same audio output for TV and FM radio! + * This card lacks external Audio In, so we mute it on Ext. & Int. + * The PCB can take a sbx1637/sbx1673, wiring unknown. + * This card lacks PCI subsystem ID, sigh. + * audiomux=1: lower volume, 2+3: mute + * btwincap uses 0x80000/0x80003 + */ + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = 5, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and + radio signal strength indicators work fine. */ + .has_radio = 1, + /* GPIO Info: + GPIO0,1: HEF4052 A0,A1 + GPIO2: HEF4052 nENABLE + GPIO3-7: n.c. + GPIO8-13: IRDC357 data0-5 (data6 n.c. ?) [chip not present on my card] + GPIO14,15: ?? + GPIO16-21: n.c. + GPIO22,23: ?? + ?? : mtu8b56ep microcontroller for IR (GPIO wiring unknown)*/ + }, + [BTTV_BOARD_DSP_TCVIDEO] = { + /* Arthur Tetzlaff-Deas, DSP Design Ltd */ + .name = "DSP Design TCVIDEO", + .video_inputs = 4, + .svhs = -1, + .muxsel = { 2, 3, 1, 0 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x50 ---------------------------------- */ + [BTTV_BOARD_HAUPPAUGEPVR] = { + .name = "Hauppauge WinTV PVR", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 0, 1, 1 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + + .gpiomask = 7, + .audiomux = {7}, + }, + [BTTV_BOARD_GVBCTV5PCI] = { + .name = "IODATA GV-BCTV5/PCI", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x0f0f80, + .muxsel = {2, 3, 1, 0 }, + .audiomux = {0x030000, 0x010000, 0, 0, 0x020000, 0}, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = gvbctv5pci_audio, + .has_radio = 1, + }, + [BTTV_BOARD_OSPREY1x0] = { + .name = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */ + .video_inputs = 4, /* id-inputs-clock */ + .audio_inputs = 0, + .tuner = -1, + .svhs = 3, + .muxsel = { 3, 2, 0, 1 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_BOARD_OSPREY1x0_848] = { + .name = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */ + .video_inputs = 3, + .audio_inputs = 0, + .tuner = -1, + .svhs = 2, + .muxsel = { 2, 3, 1 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + + /* ---- card 0x54 ---------------------------------- */ + [BTTV_BOARD_OSPREY101_848] = { + .name = "Osprey 101 (848)", /* 0x05-40C0-C1 */ + .video_inputs = 2, + .audio_inputs = 0, + .tuner = -1, + .svhs = 1, + .muxsel = { 3, 1 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_BOARD_OSPREY1x1] = { + .name = "Osprey 101/151", /* 0x1(4|5)-0004-C4 */ + .video_inputs = 1, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .muxsel = { 0 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_BOARD_OSPREY1x1_SVID] = { + .name = "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */ + .video_inputs = 2, + .audio_inputs = 0, + .tuner = -1, + .svhs = 1, + .muxsel = { 0, 1 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_BOARD_OSPREY2xx] = { + .name = "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */ + .video_inputs = 1, + .audio_inputs = 1, + .tuner = -1, + .svhs = -1, + .muxsel = { 0 }, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + + /* ---- card 0x58 ---------------------------------- */ + [BTTV_BOARD_OSPREY2x0_SVID] = { + .name = "Osprey 200/250", /* 0x1(A|B)-00C4-C1 */ + .video_inputs = 2, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, + .muxsel = { 0, 1 }, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_BOARD_OSPREY2x0] = { + .name = "Osprey 210/220", /* 0x1(A|B)-04C0-C1 */ + .video_inputs = 2, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, + .muxsel = { 2, 3 }, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_BOARD_OSPREY500] = { + .name = "Osprey 500", /* 500 */ + .video_inputs = 2, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, + .muxsel = { 2, 3 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_BOARD_OSPREY540] = { + .name = "Osprey 540", /* 540 */ + .video_inputs = 4, + .audio_inputs = 1, + .tuner = -1, + #if 0 /* TODO ... */ + .svhs = OSPREY540_SVID_ANALOG, + .muxsel = { [OSPREY540_COMP_ANALOG] = 2, + [OSPREY540_SVID_ANALOG] = 3, }, + #endif + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + #if 0 /* TODO ... */ + .muxsel_hook = osprey_540_muxsel, + .picture_hook = osprey_540_set_picture, + #endif + }, + + /* ---- card 0x5C ---------------------------------- */ + [BTTV_BOARD_OSPREY2000] = { + .name = "Osprey 2000", /* 2000 */ + .video_inputs = 2, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, + .muxsel = { 2, 3 }, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */ + }, + [BTTV_BOARD_IDS_EAGLE] = { + /* M G Berberich */ + .name = "IDS Eagle", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .svhs = -1, + .gpiomask = 0, + .muxsel = { 0, 1, 2, 3 }, + .muxsel_hook = eagle_muxsel, + .no_msp34xx = 1, + .no_tda9875 = 1, + .pll = PLL_28, + }, + [BTTV_BOARD_PINNACLESAT] = { + .name = "Pinnacle PCTV Sat", + .video_inputs = 2, + .audio_inputs = 0, + .svhs = 1, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .muxsel = { 3, 0, 1, 2 }, + .pll = PLL_28, + .no_gpioirq = 1, + .has_dvb = 1, + }, + [BTTV_BOARD_FORMAC_PROTV] = { + .name = "Formac ProTV II (bt878)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 2, + /* TV, Comp1, Composite over SVID con, SVID */ + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 2, 2, 0, 0, 0 }, + .pll = PLL_28, + .has_radio = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + /* sound routing: + GPIO=0x00,0x01,0x03: mute (?) + 0x02: both TV and radio (tuner: FM1216/I) + The card has onboard audio connectors labeled "cdrom" and "board", + not soldered here, though unknown wiring. + Card lacks: external audio in, pci subsystem id. + */ + }, + + /* ---- card 0x60 ---------------------------------- */ + [BTTV_BOARD_MACHTV] = { + .name = "MachTV", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 1, 2, 3, 4}, + .needs_tvaudio = 1, + .tuner_type = 5, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + }, + [BTTV_BOARD_EURESYS_PICOLO] = { + .name = "Euresys Picolo", + .video_inputs = 3, + .audio_inputs = 0, + .tuner = -1, + .svhs = 2, + .gpiomask = 0, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .muxsel = { 2, 0, 1}, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_PV150] = { + /* Luc Van Hoeylandt */ + .name = "ProVideo PV150", /* 0x4f */ + .video_inputs = 2, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0, + .muxsel = { 2, 3 }, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_AD_TVK503] = { + /* Hiroshi Takekawa */ + /* This card lacks subsystem ID */ + .name = "AD-TVK503", /* 0x63 */ + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x001e8007, + .muxsel = { 2, 3, 1, 0 }, + /* Tuner, Radio, external, internal, off, on */ + .audiomux = { 0x08, 0x0f, 0x0a, 0x08, 0x0f, 0x08 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = 2, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .audio_hook = adtvk503_audio, + }, + + /* ---- card 0x64 ---------------------------------- */ + [BTTV_BOARD_HERCULES_SM_TV] = { + .name = "Hercules Smart TV Stereo", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x00, + .muxsel = { 2, 3, 1, 1 }, + .needs_tvaudio = 1, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = 5, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + /* Notes: + - card lacks subsystem ID + - stereo variant w/ daughter board with tda9874a @0xb0 + - Audio Routing: + always from tda9874 independent of GPIO (?) + external line in: unknown + - Other chips: em78p156elp @ 0x96 (probably IR remote control) + hef4053 (instead 4052) for unknown function + */ + }, + [BTTV_BOARD_PACETV] = { + .name = "Pace TV & Radio Card", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 1 }, /* Tuner, CVid, SVid, CVid over SVid connector */ + .gpiomask = 0, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = 1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_radio = 1, + .pll = PLL_28, + /* Bt878, Bt832, FI1246 tuner; no pci subsystem id + only internal line out: (4pin header) RGGL + Radio must be decoded by msp3410d (not routed through)*/ + /* + .digital_mode = DIGITAL_MODE_CAMERA, todo! + */ + }, + [BTTV_BOARD_IVC200] = { + /* Chris Willing */ + .name = "IVC-200", + .video_inputs = 1, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .svhs = -1, + .gpiomask = 0xdf, + .muxsel = { 2 }, + .pll = PLL_28, + }, + [BTTV_BOARD_XGUARD] = { + .name = "Grand X-Guard / Trust 814PCI", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .tuner_type = 4, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask2 = 0xff, + .muxsel = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 }, + .muxsel_hook = xguard_muxsel, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + }, + + /* ---- card 0x68 ---------------------------------- */ + [BTTV_BOARD_NEBULA_DIGITV] = { + .name = "Nebula Electronics DigiTV", + .video_inputs = 1, + .tuner = -1, + .svhs = -1, + .muxsel = { 2, 3, 1, 0 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_dvb = 1, + .has_remote = 1, + .gpiomask = 0x1b, + .no_gpioirq = 1, + }, + [BTTV_BOARD_PV143] = { + /* Jorge Boncompte - DTI2 */ + .name = "ProVideo PV143", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_VD009X1_MINIDIN] = { + /* M.Klahr@phytec.de */ + .name = "PHYTEC VD-009-X1 MiniDIN (bt878)", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, /* card has no tuner */ + .svhs = 3, + .gpiomask = 0x00, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_VD009X1_COMBI] = { + .name = "PHYTEC VD-009-X1 Combi (bt878)", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, /* card has no tuner */ + .svhs = 3, + .gpiomask = 0x00, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + + /* ---- card 0x6c ---------------------------------- */ + [BTTV_BOARD_VD009_MINIDIN] = { + .name = "PHYTEC VD-009 MiniDIN (bt878)", + .video_inputs = 10, + .audio_inputs = 0, + .tuner = -1, /* card has no tuner */ + .svhs = 9, + .gpiomask = 0x00, + .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio + via the upper nibble of muxsel. here: used for + xternal video-mux */ + .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 }, + .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_VD009_COMBI] = { + .name = "PHYTEC VD-009 Combi (bt878)", + .video_inputs = 10, + .audio_inputs = 0, + .tuner = -1, /* card has no tuner */ + .svhs = 9, + .gpiomask = 0x00, + .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio + via the upper nibble of muxsel. here: used for + xternal video-mux */ + .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 }, + .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_IVC100] = { + .name = "IVC-100", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .svhs = -1, + .gpiomask = 0xdf, + .muxsel = { 2, 3, 1, 0 }, + .pll = PLL_28, + }, + [BTTV_BOARD_IVC120] = { + /* IVC-120G - Alan Garfield */ + .name = "IVC-120G", + .video_inputs = 16, + .audio_inputs = 0, /* card has no audio */ + .tuner = -1, /* card has no tuner */ + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .svhs = -1, /* card has no svhs */ + .needs_tvaudio = 0, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .gpiomask = 0x00, + .muxsel = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }, + .muxsel_hook = ivc120_muxsel, + .pll = PLL_28, + }, + + /* ---- card 0x70 ---------------------------------- */ + [BTTV_BOARD_PC_HDTV] = { + .name = "pcHDTV HD-2000 TV", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 0 }, + .tuner_type = TUNER_PHILIPS_ATSC, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_dvb = 1, + }, + [BTTV_BOARD_TWINHAN_DST] = { + .name = "Twinhan DST + clones", + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_video = 1, + .has_dvb = 1, + }, + [BTTV_BOARD_WINFASTVC100] = { + .name = "Winfast VC100", + .video_inputs = 3, + .audio_inputs = 0, + .svhs = 1, + .tuner = -1, + .muxsel = { 3, 1, 1, 3 }, /* Vid In, SVid In, Vid over SVid in connector */ + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + }, + [BTTV_BOARD_TEV560] = { + .name = "Teppro TEV-560/InterVision IV-560", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 3, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 1, 1, 1, 1, 0 }, + .needs_tvaudio = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_35, + }, + + /* ---- card 0x74 ---------------------------------- */ + [BTTV_BOARD_SIMUS_GVC1100] = { + .name = "SIMUS GVC1100", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + .muxsel = { 2, 2, 2, 2 }, + .gpiomask = 0x3F, + .muxsel_hook = gvc1100_muxsel, + }, + [BTTV_BOARD_NGSTV_PLUS] = { + /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */ + .name = "NGS NGSTV+", + .video_inputs = 3, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x008007, + .muxsel = { 2, 3, 0, 0 }, + .audiomux = { 0, 0, 0, 0, 0x000003, 0 }, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_remote = 1, + }, + [BTTV_BOARD_LMLBT4] = { + /* http://linuxmedialabs.com */ + .name = "LMLBT4", + .video_inputs = 4, /* IN1,IN2,IN3,IN4 */ + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .muxsel = { 2, 3, 1, 0 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .needs_tvaudio = 0, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_TEKRAM_M205] = { + /* Helmroos Harri */ + .name = "Tekram M205 PRO", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .svhs = 2, + .needs_tvaudio = 0, + .gpiomask = 0x68, + .muxsel = { 2, 3, 1 }, + .audiomux = { 0x68, 0x68, 0x61, 0x61, 0x00 }, + .pll = PLL_28, + }, + + /* ---- card 0x78 ---------------------------------- */ + [BTTV_BOARD_CONTVFMI] = { + /* Javier Cendan Ares */ + /* bt878 TV + FM without subsystem ID */ + .name = "Conceptronic CONTVFMi", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x008007, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 1, 2, 2, 3 }, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_remote = 1, + .has_radio = 1, + }, + [BTTV_BOARD_PICOLO_TETRA_CHIP] = { + /*Eric DEBIEF */ + /*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controled*/ + /* adds picolo_tetra_muxsel(), picolo_tetra_init(), the folowing declaration strucure, and #define BTTV_BOARD_PICOLO_TETRA_CHIP*/ + /*0x79 in bttv.h*/ + .name = "Euresys Picolo Tetra", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0, + .gpiomask2 = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/ + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .muxsel = {2,2,2,2},/*878A input is always MUX0, see above.*/ + .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .pll = PLL_28, + .needs_tvaudio = 0, + .muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/ + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_SPIRIT_TV] = { + /* Spirit TV Tuner from http://spiritmodems.com.au */ + /* Stafford Goodsell */ + .name = "Spirit TV Tuner", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x0000000f, + .muxsel = { 2, 1, 1 }, + .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00 }, + .tuner_type = TUNER_TEMIC_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + }, + [BTTV_BOARD_AVDVBT_771] = { + /* Wolfram Joost */ + .name = "AVerMedia AVerTV DVB-T 771", + .video_inputs = 2, + .svhs = 1, + .tuner = -1, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .muxsel = { 3 , 3 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .has_dvb = 1, + .no_gpioirq = 1, + .has_remote = 1, + }, + /* ---- card 0x7c ---------------------------------- */ + [BTTV_BOARD_AVDVBT_761] = { + /* Matt Jesson */ + /* Based on the Nebula card data - added remote and new card number - BTTV_BOARD_AVDVBT_761, see also ir-kbd-gpio.c */ + .name = "AverMedia AverTV DVB-T 761", + .video_inputs = 2, + .tuner = -1, + .svhs = 1, + .muxsel = { 3, 1, 2, 0 }, /* Comp0, S-Video, ?, ? */ + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_dvb = 1, + .no_gpioirq = 1, + .has_remote = 1, + }, + [BTTV_BOARD_MATRIX_VISIONSQ] = { + /* andre.schwarz@matrix-vision.de */ + .name = "MATRIX Vision Sigma-SQ", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x0, + .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3 }, + .muxsel_hook = sigmaSQ_muxsel, + .audiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_MATRIX_VISIONSLC] = { + /* andre.schwarz@matrix-vision.de */ + .name = "MATRIX Vision Sigma-SLC", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x0, + .muxsel = { 2, 2, 2, 2 }, + .muxsel_hook = sigmaSLC_muxsel, + .audiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + /* BTTV_BOARD_APAC_VIEWCOMP */ + [BTTV_BOARD_APAC_VIEWCOMP] = { + /* Attila Kondoros */ + /* bt878 TV + FM 0x00000000 subsystem ID */ + .name = "APAC Viewcomp 878(AMAX)", + .video_inputs = 2, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 0xFF, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 2, 0, 0, 0, 10 }, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_remote = 1, /* miniremote works, see ir-kbd-gpio.c */ + .has_radio = 1, /* not every card has radio */ + }, + + /* ---- card 0x80 ---------------------------------- */ + [BTTV_BOARD_DVICO_DVBT_LITE] = { + /* Chris Pascoe */ + .name = "DViCO FusionHDTV DVB-T Lite", + .tuner = -1, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .no_video = 1, + .has_dvb = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_VGEAR_MYVCD] = { + /* Steven */ + .name = "V-Gear MyVCD", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x3f, + .muxsel = {2, 3, 1, 0 }, + .audiomux = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_radio = 0, + #if 0 + .has_remote = 1, + #endif + }, + [BTTV_BOARD_SUPER_TV] = { + /* Rick C */ + .name = "Super TV Tuner", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 0 }, + .tuner_type = TUNER_PHILIPS_NTSC, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x008007, + .audiomux = { 0, 0x000001,0,0, 0 }, + .needs_tvaudio = 1, + .has_radio = 1, + }, + [BTTV_BOARD_TIBET_CS16] = { + /* Chris Fanning */ + .name = "Tibet Systems 'Progress DVR' CS16", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .muxsel_hook = tibetCS16_muxsel, + }, + [BTTV_BOARD_KODICOM_4400R] = { + /* Bill Brack */ + /* + * Note that, because of the card's wiring, the "master" + * BT878A chip (i.e. the one which controls the analog switch + * and must use this card type) is the 2nd one detected. The + * other 3 chips should use card type 0x85, whose description + * follows this one. There is a EEPROM on the card (which is + * connected to the I2C of one of those other chips), but is + * not currently handled. There is also a facility for a + * "monitor", which is also not currently implemented. + */ + .name = "Kodicom 4400R (master)", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .svhs = -1, + /* GPIO bits 0-9 used for analog switch: + * 00 - 03: camera selector + * 04 - 06: channel (controller) selector + * 07: data (1->on, 0->off) + * 08: strobe + * 09: reset + * bit 16 is input from sync separator for the channel + */ + .gpiomask = 0x0003ff, + .no_gpioirq = 1, + .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda7432 = 1, + .no_tda9875 = 1, + .muxsel_hook = kodicom4400r_muxsel, + }, + [BTTV_BOARD_KODICOM_4400R_SL] = { + /* Bill Brack */ + /* Note that, for reasons unknown, the "master" BT878A chip (i.e. the + * one which controls the analog switch, and must use the card type) + * is the 2nd one detected. The other 3 chips should use this card + * type + */ + .name = "Kodicom 4400R (slave)", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .svhs = -1, + .gpiomask = 0x010000, + .no_gpioirq = 1, + .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda7432 = 1, + .no_tda9875 = 1, + .muxsel_hook = kodicom4400r_muxsel, + }, + /* ---- card 0x86---------------------------------- */ + [BTTV_BOARD_ADLINK_RTV24] = { + /* Michael Henson */ + /* Adlink RTV24 with special unlock codes */ + .name = "Adlink RTV24", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 0 }, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + }, + /* ---- card 0x87---------------------------------- */ + [BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE] = { + /* Michael Krufky */ + .name = "DViCO FusionHDTV 5 Lite", + .tuner = 0, + .tuner_type = TUNER_LG_TDVS_H062F, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .video_inputs = 3, + .audio_inputs = 1, + .svhs = 2, + .muxsel = { 2, 3, 1 }, + .gpiomask = 0x00e00007, + .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .has_dvb = 1, + }, + /* ---- card 0x88---------------------------------- */ + [BTTV_BOARD_ACORP_Y878F] = { + /* Mauro Carvalho Chehab */ + .name = "Acorp Y878F", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x01fe00, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = TUNER_YMEC_TVF66T5_B_DFF, + .tuner_addr = 0xc1 >>1, + .radio_addr = 0xc1 >>1, + .has_radio = 1, + }, + /* ---- card 0x89 ---------------------------------- */ + [BTTV_BOARD_CONCEPTRONIC_CTVFMI2] = { + .name = "Conceptronic CTVFMi v2", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x001c0007, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 1, 2, 2, 3 }, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_TENA_9533_DI, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_remote = 1, + .has_radio = 1, + }, + /* ---- card 0x8a ---------------------------------- */ + [BTTV_BOARD_PV_BT878P_2E] = { + .name = "Prolink Pixelview PV-BT878P+ (Rev.2E)", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 0x01fe00, + .muxsel = { 2,3,1,1,-1 }, + .digital_mode = DIGITAL_MODE_CAMERA, + .audiomux = { 0x00400, 0x10400, 0x04400, 0x80000, 0x12400, 0x46000 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_LG_PAL_FM, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_remote = 1, + }, + /* ---- card 0x8b ---------------------------------- */ + [BTTV_BOARD_PV_M4900] = { + /* Sérgio Fortier */ + .name = "Prolink PixelView PlayTV MPEG2 PV-M4900", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x3f, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_YMEC_TVF_5533MF, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_radio = 1, + .has_remote = 1, + }, + /* ---- card 0x8c ---------------------------------- */ + [BTTV_BOARD_OSPREY440] = { + .name = "Osprey 440", + .video_inputs = 1, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, + .muxsel = { 2 }, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + /* ---- card 0x8d ---------------------------------- */ + [BTTV_BOARD_ASOUND_SKYEYE] = { + .name = "Asound Skyeye PCTV", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 2, 0, 0, 0, 1 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = 2, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + /* ---- card 0x8e ---------------------------------- */ + [BTTV_BOARD_SABRENT_TVFM] = { + .name = "Sabrent TV-FM (bttv version)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x108007, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 100000, 100002, 100002, 100000 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .tuner_type = TUNER_TNF_5335MF, + .tuner_addr = ADDR_UNSET, + .has_radio = 1, + }, + /* ---- card 0x8f ---------------------------------- */ + [BTTV_BOARD_HAUPPAUGE_IMPACTVCB] = { + .name = "Hauppauge ImpactVCB (bt878)", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x0f, /* old: 7 */ + .muxsel = { 0, 1, 3, 2 }, /* Composite 0-3 */ + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + [BTTV_BOARD_MACHTV_MAGICTV] = { + /* Julian Calaby + * Slightly different from original MachTV definition (0x60) + + * FIXME: RegSpy says gpiomask should be "0x001c800f", but it + * stuffs up remote chip. Bug is a pin on the jaecs is not set + * properly (methinks) causing no keyup bits being set */ + + .name = "MagicTV", /* rebranded MachTV */ + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 1, 2, 3, 4 }, + .tuner_type = TUNER_TEMIC_4009FR5_PAL, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + .has_remote = 1, + }, +}; + +static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); + +/* ----------------------------------------------------------------------- */ + +static unsigned char eeprom_data[256]; + +/* + * identify card + */ +void __devinit bttv_idcard(struct bttv *btv) +{ + unsigned int gpiobits; + int i,type; + unsigned short tmp; + + /* read PCI subsystem ID */ + pci_read_config_word(btv->c.pci, PCI_SUBSYSTEM_ID, &tmp); + btv->cardid = tmp << 16; + pci_read_config_word(btv->c.pci, PCI_SUBSYSTEM_VENDOR_ID, &tmp); + btv->cardid |= tmp; + + if (0 != btv->cardid && 0xffffffff != btv->cardid) { + /* look for the card */ + for (type = -1, i = 0; cards[i].id != 0; i++) + if (cards[i].id == btv->cardid) + type = i; + + if (type != -1) { + /* found it */ + printk(KERN_INFO "bttv%d: detected: %s [card=%d], " + "PCI subsystem ID is %04x:%04x\n", + btv->c.nr,cards[type].name,cards[type].cardnr, + btv->cardid & 0xffff, + (btv->cardid >> 16) & 0xffff); + btv->c.type = cards[type].cardnr; + } else { + /* 404 */ + printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n", + btv->c.nr, btv->cardid & 0xffff, + (btv->cardid >> 16) & 0xffff); + printk(KERN_DEBUG "please mail id, board name and " + "the correct card= insmod option to video4linux-list@redhat.com\n"); + } + } + + /* let the user override the autodetected type */ + if (card[btv->c.nr] < bttv_num_tvcards) + btv->c.type=card[btv->c.nr]; + + /* print which card config we are using */ + printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->c.nr, + bttv_tvcards[btv->c.type].name, btv->c.type, + card[btv->c.nr] < bttv_num_tvcards + ? "insmod option" : "autodetected"); + + /* overwrite gpio stuff ?? */ + if (UNSET == audioall && UNSET == audiomux[0]) + return; + + if (UNSET != audiomux[0]) { + gpiobits = 0; + for (i = 0; i < 5; i++) { + bttv_tvcards[btv->c.type].audiomux[i] = audiomux[i]; + gpiobits |= audiomux[i]; + } + } else { + gpiobits = audioall; + for (i = 0; i < 5; i++) { + bttv_tvcards[btv->c.type].audiomux[i] = audioall; + } + } + bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits; + printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=", + btv->c.nr,bttv_tvcards[btv->c.type].gpiomask); + for (i = 0; i < 5; i++) { + printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].audiomux[i]); + } + printk("\n"); +} + +/* + * (most) board specific initialisations goes here + */ + +/* Some Modular Technology cards have an eeprom, but no subsystem ID */ +static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256]) +{ + int type = -1; + + if (0 == strncmp(eeprom_data,"GET MM20xPCTV",13)) + type = BTTV_BOARD_MODTEC_205; + else if (0 == strncmp(eeprom_data+20,"Picolo",7)) + type = BTTV_BOARD_EURESYS_PICOLO; + else if (eeprom_data[0] == 0x84 && eeprom_data[2]== 0) + type = BTTV_BOARD_HAUPPAUGE; /* old bt848 */ + + if (-1 != type) { + btv->c.type = type; + printk("bttv%d: detected by eeprom: %s [card=%d]\n", + btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type); + } +} + +static void flyvideo_gpio(struct bttv *btv) +{ + int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821; + int tuner=-1,ttype; + + gpio_inout(0xffffff, 0); + udelay(8); /* without this we would see the 0x1800 mask */ + gpio = gpio_read(); + /* FIXME: must restore OUR_EN ??? */ + + /* all cards provide GPIO info, some have an additional eeprom + * LR50: GPIO coding can be found lower right CP1 .. CP9 + * CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1. + * GPIO14-12: n.c. + * LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878) + + * lowest 3 bytes are remote control codes (no handshake needed) + * xxxFFF: No remote control chip soldered + * xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered + * Note: Some bits are Audio_Mask ! + */ + ttype=(gpio&0x0f0000)>>16; + switch(ttype) { + case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */ + break; + case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */ + break; + case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */ + break; + case 0x6: tuner=37;/* LG PAL (newer TAPC series) TAPC-G702P */ + break; + case 0xC: tuner=3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */ + break; + default: + printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr); + } + + has_remote = gpio & 0x800000; + has_radio = gpio & 0x400000; + /* unknown 0x200000; + * unknown2 0x100000; */ + is_capture_only = !(gpio & 0x008000); /* GPIO15 */ + has_tda9820_tda9821 = !(gpio & 0x004000); + is_lr90 = !(gpio & 0x002000); /* else LR26/LR50 (LR38/LR51 f. capture only) */ + /* + * gpio & 0x001000 output bit for audio routing */ + + if(is_capture_only) + tuner=4; /* No tuner present */ + + printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n", + btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio); + printk(KERN_INFO "bttv%d: FlyVideo LR90=%s tda9821/tda9820=%s capture_only=%s\n", + btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ", + is_capture_only?"yes":"no "); + + if(tuner!= -1) /* only set if known tuner autodetected, else let insmod option through */ + btv->tuner_type = tuner; + btv->has_radio = has_radio; + + /* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80 + * LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00 + * Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */ + if(has_tda9820_tda9821) btv->audio_hook = lt9415_audio; + /* todo: if(has_tda9874) btv->audio_hook = fv2000s_audio; */ +} + +static int miro_tunermap[] = { 0,6,2,3, 4,5,6,0, 3,0,4,5, 5,2,16,1, + 14,2,17,1, 4,1,4,3, 1,2,16,1, 4,4,4,4 }; +static int miro_fmtuner[] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, + 1,1,1,1, 1,1,1,0, 0,0,0,0, 0,1,0,0 }; + +static void miro_pinnacle_gpio(struct bttv *btv) +{ + int id,msp,gpio; + char *info; + + gpio_inout(0xffffff, 0); + gpio = gpio_read(); + id = ((gpio>>10) & 63) -1; + msp = bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx"); + if (id < 32) { + btv->tuner_type = miro_tunermap[id]; + if (0 == (gpio & 0x20)) { + btv->has_radio = 1; + if (!miro_fmtuner[id]) { + btv->has_matchbox = 1; + btv->mbox_we = (1<<6); + btv->mbox_most = (1<<7); + btv->mbox_clk = (1<<8); + btv->mbox_data = (1<<9); + btv->mbox_mask = (1<<6)|(1<<7)|(1<<8)|(1<<9); + } + } else { + btv->has_radio = 0; + } + if (-1 != msp) { + if (btv->c.type == BTTV_BOARD_MIRO) + btv->c.type = BTTV_BOARD_MIROPRO; + if (btv->c.type == BTTV_BOARD_PINNACLE) + btv->c.type = BTTV_BOARD_PINNACLEPRO; + } + printk(KERN_INFO + "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n", + btv->c.nr, id+1, btv->tuner_type, + !btv->has_radio ? "no" : + (btv->has_matchbox ? "matchbox" : "fmtuner"), + (-1 == msp) ? "no" : "yes"); + } else { + /* new cards with microtune tuner */ + id = 63 - id; + btv->has_radio = 0; + switch (id) { + case 1: + info = "PAL / mono"; + btv->tda9887_conf = TDA9887_INTERCARRIER; + break; + case 2: + info = "PAL+SECAM / stereo"; + btv->has_radio = 1; + btv->tda9887_conf = TDA9887_QSS; + break; + case 3: + info = "NTSC / stereo"; + btv->has_radio = 1; + btv->tda9887_conf = TDA9887_QSS; + break; + case 4: + info = "PAL+SECAM / mono"; + btv->tda9887_conf = TDA9887_QSS; + break; + case 5: + info = "NTSC / mono"; + btv->tda9887_conf = TDA9887_INTERCARRIER; + break; + case 6: + info = "NTSC / stereo"; + btv->tda9887_conf = TDA9887_INTERCARRIER; + break; + case 7: + info = "PAL / stereo"; + btv->tda9887_conf = TDA9887_INTERCARRIER; + break; + default: + info = "oops: unknown card"; + break; + } + if (-1 != msp) + btv->c.type = BTTV_BOARD_PINNACLEPRO; + printk(KERN_INFO + "bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n", + btv->c.nr, id, info, btv->has_radio ? "yes" : "no"); + btv->tuner_type = TUNER_MT2032; + } +} + +/* GPIO21 L: Buffer aktiv, H: Buffer inaktiv */ +#define LM1882_SYNC_DRIVE 0x200000L + +static void init_ids_eagle(struct bttv *btv) +{ + gpio_inout(0xffffff,0xFFFF37); + gpio_write(0x200020); + + /* flash strobe inverter ?! */ + gpio_write(0x200024); + + /* switch sync drive off */ + gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE); + + /* set BT848 muxel to 2 */ + btaor((2)<<5, ~(2<<5), BT848_IFORM); +} + +/* Muxsel helper for the IDS Eagle. + * the eagles does not use the standard muxsel-bits but + * has its own multiplexer */ +static void eagle_muxsel(struct bttv *btv, unsigned int input) +{ + btaor((2)<<5, ~(3<<5), BT848_IFORM); + gpio_bits(3,bttv_tvcards[btv->c.type].muxsel[input&7]); + + /* composite */ + /* set chroma ADC to sleep */ + btor(BT848_ADC_C_SLEEP, BT848_ADC); + /* set to composite video */ + btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); + btand(~BT848_CONTROL_COMP, BT848_O_CONTROL); + + /* switch sync drive off */ + gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE); +} + +static void gvc1100_muxsel(struct bttv *btv, unsigned int input) +{ + static const int masks[] = {0x30, 0x01, 0x12, 0x23}; + gpio_write(masks[input%4]); +} + +/* LMLBT4x initialization - to allow access to GPIO bits for sensors input and + alarms output + + GPIObit | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + assignment | TI | O3|INx| O2| O1|IN4|IN3|IN2|IN1| | | + + IN - sensor inputs, INx - sensor inputs and TI XORed together + O1,O2,O3 - alarm outputs (relays) + + OUT ENABLE 1 1 0 . 1 1 0 0 . 0 0 0 0 = 0x6C0 + +*/ + +static void init_lmlbt4x(struct bttv *btv) +{ + printk(KERN_DEBUG "LMLBT4x init\n"); + btwrite(0x000000, BT848_GPIO_REG_INP); + gpio_inout(0xffffff, 0x0006C0); + gpio_write(0x000000); +} + +static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input) +{ + unsigned int inmux = input % 8; + gpio_inout( 0xf, 0xf ); + gpio_bits( 0xf, inmux ); +} + +static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input) +{ + unsigned int inmux = input % 4; + gpio_inout( 3<<9, 3<<9 ); + gpio_bits( 3<<9, inmux<<9 ); +} + +/* ----------------------------------------------------------------------- */ + +static void bttv_reset_audio(struct bttv *btv) +{ + /* + * BT878A has a audio-reset register. + * 1. This register is an audio reset function but it is in + * function-0 (video capture) address space. + * 2. It is enough to do this once per power-up of the card. + * 3. There is a typo in the Conexant doc -- it is not at + * 0x5B, but at 0x058. (B is an odd-number, obviously a typo!). + * --//Shrikumar 030609 + */ + if (btv->id != 878) + return; + + if (bttv_debug) + printk("bttv%d: BT878A ARESET\n",btv->c.nr); + btwrite((1<<7), 0x058); + udelay(10); + btwrite( 0, 0x058); +} + +/* initialization part one -- before registering i2c bus */ +void __devinit bttv_init_card1(struct bttv *btv) +{ + switch (btv->c.type) { + case BTTV_BOARD_HAUPPAUGE: + case BTTV_BOARD_HAUPPAUGE878: + boot_msp34xx(btv,5); + break; + case BTTV_BOARD_VOODOOTV_FM: + boot_msp34xx(btv,20); + break; + case BTTV_BOARD_AVERMEDIA98: + boot_msp34xx(btv,11); + break; + case BTTV_BOARD_HAUPPAUGEPVR: + pvr_boot(btv); + break; + case BTTV_BOARD_TWINHAN_DST: + case BTTV_BOARD_AVDVBT_771: + case BTTV_BOARD_PINNACLESAT: + btv->use_i2c_hw = 1; + break; + case BTTV_BOARD_ADLINK_RTV24: + init_RTV24( btv ); + break; + + } + if (!bttv_tvcards[btv->c.type].has_dvb) + bttv_reset_audio(btv); +} + +/* initialization part two -- after registering i2c bus */ +void __devinit bttv_init_card2(struct bttv *btv) +{ + int tda9887; + int addr=ADDR_UNSET; + + btv->tuner_type = -1; + + if (BTTV_BOARD_UNKNOWN == btv->c.type) { + bttv_readee(btv,eeprom_data,0xa0); + identify_by_eeprom(btv,eeprom_data); + } + + switch (btv->c.type) { + case BTTV_BOARD_MIRO: + case BTTV_BOARD_MIROPRO: + case BTTV_BOARD_PINNACLE: + case BTTV_BOARD_PINNACLEPRO: + /* miro/pinnacle */ + miro_pinnacle_gpio(btv); + break; + case BTTV_BOARD_FLYVIDEO_98: + case BTTV_BOARD_MAXI: + case BTTV_BOARD_LIFE_FLYKIT: + case BTTV_BOARD_FLYVIDEO: + case BTTV_BOARD_TYPHOON_TVIEW: + case BTTV_BOARD_CHRONOS_VS2: + case BTTV_BOARD_FLYVIDEO_98FM: + case BTTV_BOARD_FLYVIDEO2000: + case BTTV_BOARD_FLYVIDEO98EZ: + case BTTV_BOARD_CONFERENCETV: + case BTTV_BOARD_LIFETEC_9415: + flyvideo_gpio(btv); + break; + case BTTV_BOARD_HAUPPAUGE: + case BTTV_BOARD_HAUPPAUGE878: + case BTTV_BOARD_HAUPPAUGEPVR: + /* pick up some config infos from the eeprom */ + bttv_readee(btv,eeprom_data,0xa0); + hauppauge_eeprom(btv); + break; + case BTTV_BOARD_AVERMEDIA98: + case BTTV_BOARD_AVPHONE98: + bttv_readee(btv,eeprom_data,0xa0); + avermedia_eeprom(btv); + break; + case BTTV_BOARD_PXC200: + init_PXC200(btv); + break; + case BTTV_BOARD_PICOLO_TETRA_CHIP: + picolo_tetra_init(btv); + break; + case BTTV_BOARD_VHX: + btv->has_radio = 1; + btv->has_matchbox = 1; + btv->mbox_we = 0x20; + btv->mbox_most = 0; + btv->mbox_clk = 0x08; + btv->mbox_data = 0x10; + btv->mbox_mask = 0x38; + break; + case BTTV_BOARD_VOBIS_BOOSTAR: + case BTTV_BOARD_TERRATV: + terratec_active_radio_upgrade(btv); + break; + case BTTV_BOARD_MAGICTVIEW061: + if (btv->cardid == 0x3002144f) { + btv->has_radio=1; + printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr); + } + break; + case BTTV_BOARD_STB2: + if (btv->cardid == 0x3060121a) { + /* Fix up entry for 3DFX VoodooTV 100, + which is an OEM STB card variant. */ + btv->has_radio=0; + btv->tuner_type=TUNER_TEMIC_NTSC; + } + break; + case BTTV_BOARD_OSPREY1x0: + case BTTV_BOARD_OSPREY1x0_848: + case BTTV_BOARD_OSPREY101_848: + case BTTV_BOARD_OSPREY1x1: + case BTTV_BOARD_OSPREY1x1_SVID: + case BTTV_BOARD_OSPREY2xx: + case BTTV_BOARD_OSPREY2x0_SVID: + case BTTV_BOARD_OSPREY2x0: + case BTTV_BOARD_OSPREY500: + case BTTV_BOARD_OSPREY540: + case BTTV_BOARD_OSPREY2000: + bttv_readee(btv,eeprom_data,0xa0); + osprey_eeprom(btv); + break; + case BTTV_BOARD_IDS_EAGLE: + init_ids_eagle(btv); + break; + case BTTV_BOARD_MODTEC_205: + bttv_readee(btv,eeprom_data,0xa0); + modtec_eeprom(btv); + break; + case BTTV_BOARD_LMLBT4: + init_lmlbt4x(btv); + break; + case BTTV_BOARD_TIBET_CS16: + tibetCS16_init(btv); + break; + case BTTV_BOARD_KODICOM_4400R: + kodicom4400r_init(btv); + break; + } + + /* pll configuration */ + if (!(btv->id==848 && btv->revision==0x11)) { + /* defaults from card list */ + if (PLL_28 == bttv_tvcards[btv->c.type].pll) { + btv->pll.pll_ifreq=28636363; + btv->pll.pll_crystal=BT848_IFORM_XT0; + } + if (PLL_35 == bttv_tvcards[btv->c.type].pll) { + btv->pll.pll_ifreq=35468950; + btv->pll.pll_crystal=BT848_IFORM_XT1; + } + /* insmod options can override */ + switch (pll[btv->c.nr]) { + case 0: /* none */ + btv->pll.pll_crystal = 0; + btv->pll.pll_ifreq = 0; + btv->pll.pll_ofreq = 0; + break; + case 1: /* 28 MHz */ + case 28: + btv->pll.pll_ifreq = 28636363; + btv->pll.pll_ofreq = 0; + btv->pll.pll_crystal = BT848_IFORM_XT0; + break; + case 2: /* 35 MHz */ + case 35: + btv->pll.pll_ifreq = 35468950; + btv->pll.pll_ofreq = 0; + btv->pll.pll_crystal = BT848_IFORM_XT1; + break; + } + } + btv->pll.pll_current = -1; + + /* tuner configuration (from card list / autodetect / insmod option) */ + if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) + addr = bttv_tvcards[btv->c.type].tuner_addr; + + if (UNSET != bttv_tvcards[btv->c.type].tuner_type) + if(UNSET == btv->tuner_type) + btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; + if (UNSET != tuner[btv->c.nr]) + btv->tuner_type = tuner[btv->c.nr]; + printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type); + + if (btv->tuner_type != UNSET) { + struct tuner_setup tun_setup; + + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.type = btv->tuner_type; + tun_setup.addr = addr; + + bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); + } + + if (btv->tda9887_conf) { + bttv_call_i2c_clients(btv, TDA9887_SET_CONFIG, + &btv->tda9887_conf); + } + + btv->svhs = bttv_tvcards[btv->c.type].svhs; + if (svhs[btv->c.nr] != UNSET) + btv->svhs = svhs[btv->c.nr]; + if (remote[btv->c.nr] != UNSET) + btv->has_remote = remote[btv->c.nr]; + + if (bttv_tvcards[btv->c.type].has_radio) + btv->has_radio=1; + if (bttv_tvcards[btv->c.type].has_remote) + btv->has_remote=1; + if (!bttv_tvcards[btv->c.type].no_gpioirq) + btv->gpioirq=1; + if (bttv_tvcards[btv->c.type].audio_hook) + btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; + + if (bttv_tvcards[btv->c.type].digital_mode == DIGITAL_MODE_CAMERA) { + /* detect Bt832 chip for quartzsight digital camera */ + if ((bttv_I2CRead(btv, I2C_BT832_ALT1, "Bt832") >=0) || + (bttv_I2CRead(btv, I2C_BT832_ALT2, "Bt832") >=0)) + boot_bt832(btv); + } + + if (!autoload) + return; + + /* try to detect audio/fader chips */ + if (!bttv_tvcards[btv->c.type].no_msp34xx && + bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) + request_module("msp3400"); + + if (bttv_tvcards[btv->c.type].msp34xx_alt && + bttv_I2CRead(btv, I2C_MSP3400_ALT, "MSP34xx (alternate address)") >=0) + request_module("msp3400"); + + if (!bttv_tvcards[btv->c.type].no_tda9875 && + bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) + request_module("tda9875"); + + if (!bttv_tvcards[btv->c.type].no_tda7432 && + bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) + request_module("tda7432"); + + if (bttv_tvcards[btv->c.type].needs_tvaudio) + request_module("tvaudio"); + + /* tuner modules */ + tda9887 = 0; + if (btv->tda9887_conf) + tda9887 = 1; + if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb && + bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0) + tda9887 = 1; + /* Hybrid DVB card, DOES have a tda9887 */ + if (btv->c.type == BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE) + tda9887 = 1; + if((btv->tuner_type == TUNER_PHILIPS_FM1216ME_MK3) || + (btv->tuner_type == TUNER_PHILIPS_FM1236_MK3) || + (btv->tuner_type == TUNER_PHILIPS_FM1256_IH3) || + tda9887) + request_module("tda9887"); + if (btv->tuner_type != UNSET) + request_module("tuner"); +} + + +/* ----------------------------------------------------------------------- */ + +static void modtec_eeprom(struct bttv *btv) +{ + if( strncmp(&(eeprom_data[0x1e]),"Temic 4066 FY5",14) ==0) { + btv->tuner_type=TUNER_TEMIC_4066FY5_PAL_I; + printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", + btv->c.nr,&eeprom_data[0x1e]); + } else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) { + btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I; + printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", + btv->c.nr,&eeprom_data[0x1e]); + } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) { + btv->tuner_type=TUNER_PHILIPS_NTSC; + printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", + btv->c.nr,&eeprom_data[0x1e]); + } else { + printk("bttv%d: Modtec: Unknown TunerString: %s\n", + btv->c.nr,&eeprom_data[0x1e]); + } +} + +static void __devinit hauppauge_eeprom(struct bttv *btv) +{ + struct tveeprom tv; + + tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data); + btv->tuner_type = tv.tuner_type; + btv->has_radio = tv.has_radio; + + printk("bttv%d: Hauppauge eeprom indicates model#%d\n", + btv->c.nr, tv.model); + + /* + * Some of the 878 boards have duplicate PCI IDs. Switch the board + * type based on model #. + */ + if(tv.model == 64900) { + printk("bttv%d: Switching board type from %s to %s\n", + btv->c.nr, + bttv_tvcards[btv->c.type].name, + bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name); + btv->c.type = BTTV_BOARD_HAUPPAUGE_IMPACTVCB; + } +} + +static int terratec_active_radio_upgrade(struct bttv *btv) +{ + int freq; + + btv->has_radio = 1; + btv->has_matchbox = 1; + btv->mbox_we = 0x10; + btv->mbox_most = 0x20; + btv->mbox_clk = 0x08; + btv->mbox_data = 0x04; + btv->mbox_mask = 0x3c; + + btv->mbox_iow = 1 << 8; + btv->mbox_ior = 1 << 9; + btv->mbox_csel = 1 << 10; + + freq=88000/62.5; + tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */ + if (0x1ed8 == tea5757_read(btv)) { + printk("bttv%d: Terratec Active Radio Upgrade found.\n", + btv->c.nr); + btv->has_radio = 1; + btv->has_matchbox = 1; + } else { + btv->has_radio = 0; + btv->has_matchbox = 0; + } + return 0; +} + + +/* ----------------------------------------------------------------------- */ + +/* + * minimal bootstrap for the WinTV/PVR -- upload altera firmware. + * + * The hcwamc.rbf firmware file is on the Hauppauge driver CD. Have + * a look at Pvr/pvr45xxx.EXE (self-extracting zip archive, can be + * unpacked with unzip). + */ +#define PVR_GPIO_DELAY 10 + +#define BTTV_ALT_DATA 0x000001 +#define BTTV_ALT_DCLK 0x100000 +#define BTTV_ALT_NCONFIG 0x800000 + +static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) +{ + u32 n; + u8 bits; + int i; + + gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG); + gpio_write(0); + udelay(PVR_GPIO_DELAY); + + gpio_write(BTTV_ALT_NCONFIG); + udelay(PVR_GPIO_DELAY); + + for (n = 0; n < microlen; n++) { + bits = micro[n]; + for ( i = 0 ; i < 8 ; i++ ) { + gpio_bits(BTTV_ALT_DCLK,0); + if (bits & 0x01) + gpio_bits(BTTV_ALT_DATA,BTTV_ALT_DATA); + else + gpio_bits(BTTV_ALT_DATA,0); + gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK); + bits >>= 1; + } + } + gpio_bits(BTTV_ALT_DCLK,0); + udelay(PVR_GPIO_DELAY); + + /* begin Altera init loop (Not necessary,but doesn't hurt) */ + for (i = 0 ; i < 30 ; i++) { + gpio_bits(BTTV_ALT_DCLK,0); + gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK); + } + gpio_bits(BTTV_ALT_DCLK,0); + return 0; +} + +static int __devinit pvr_boot(struct bttv *btv) +{ + const struct firmware *fw_entry; + int rc; + + rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev); + if (rc != 0) { + printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n", + btv->c.nr); + return rc; + } + rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size); + printk(KERN_INFO "bttv%d: altera firmware upload %s\n", + btv->c.nr, (rc < 0) ? "failed" : "ok"); + release_firmware(fw_entry); + return rc; +} + +/* ----------------------------------------------------------------------- */ +/* some osprey specific stuff */ + +static void __devinit osprey_eeprom(struct bttv *btv) +{ + int i = 0; + unsigned char *ee = eeprom_data; + unsigned long serial = 0; + + if (btv->c.type == 0) { + /* this might be an antique... check for MMAC label in eeprom */ + if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { + unsigned char checksum = 0; + for (i =0; i<21; i++) + checksum += ee[i]; + if (checksum != ee[21]) + return; + btv->c.type = BTTV_BOARD_OSPREY1x0_848; + for (i = 12; i < 21; i++) + serial *= 10, serial += ee[i] - '0'; + } + } else { + unsigned short type; + int offset = 4*16; + + for(; offset < 8*16; offset += 16) { + unsigned short checksum = 0; + /* verify the checksum */ + for(i = 0; i<14; i++) checksum += ee[i+offset]; + checksum = ~checksum; /* no idea why */ + if ((((checksum>>8)&0x0FF) == ee[offset+14]) && + ((checksum & 0x0FF) == ee[offset+15])) { + break; + } + } + + if (offset >= 8*16) + return; + + /* found a valid descriptor */ + type = (ee[offset+4]<<8) | (ee[offset+5]); + + switch(type) { + + /* 848 based */ + case 0x0004: + btv->c.type = BTTV_BOARD_OSPREY1x0_848; + break; + case 0x0005: + btv->c.type = BTTV_BOARD_OSPREY101_848; + break; + + /* 878 based */ + case 0x0012: + case 0x0013: + btv->c.type = BTTV_BOARD_OSPREY1x0; + break; + case 0x0014: + case 0x0015: + btv->c.type = BTTV_BOARD_OSPREY1x1; + break; + case 0x0016: + case 0x0017: + case 0x0020: + btv->c.type = BTTV_BOARD_OSPREY1x1_SVID; + break; + case 0x0018: + case 0x0019: + case 0x001E: + case 0x001F: + btv->c.type = BTTV_BOARD_OSPREY2xx; + break; + case 0x001A: + case 0x001B: + btv->c.type = BTTV_BOARD_OSPREY2x0_SVID; + break; + case 0x0040: + btv->c.type = BTTV_BOARD_OSPREY500; + break; + case 0x0050: + case 0x0056: + btv->c.type = BTTV_BOARD_OSPREY540; + /* bttv_osprey_540_init(btv); */ + break; + case 0x0060: + case 0x0070: + btv->c.type = BTTV_BOARD_OSPREY2x0; + /* enable output on select control lines */ + gpio_inout(0xffffff,0x000303); + break; + default: + /* unknown...leave generic, but get serial # */ + break; + } + serial = (ee[offset+6] << 24) + | (ee[offset+7] << 16) + | (ee[offset+8] << 8) + | (ee[offset+9]); + } + + printk(KERN_INFO "bttv%d: osprey eeprom: card=%d name=%s serial=%ld\n", + btv->c.nr, btv->c.type, bttv_tvcards[btv->c.type].name,serial); +} + +/* ----------------------------------------------------------------------- */ +/* AVermedia specific stuff, from bktr_card.c */ + +static int tuner_0_table[] = { + TUNER_PHILIPS_NTSC, TUNER_PHILIPS_PAL /* PAL-BG*/, + TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL /* PAL-I*/, + TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL, + TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM, + TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL, + TUNER_PHILIPS_FM1216ME_MK3 }; + +static int tuner_1_table[] = { + TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL, + TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, + TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, + TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */ + TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL}; + +static void __devinit avermedia_eeprom(struct bttv *btv) +{ + int tuner_make,tuner_tv_fm,tuner_format,tuner=0; + + tuner_make = (eeprom_data[0x41] & 0x7); + tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3; + tuner_format = (eeprom_data[0x42] & 0xf0) >> 4; + btv->has_remote = (eeprom_data[0x42] & 0x01); + + if (tuner_make == 0 || tuner_make == 2) + if(tuner_format <=0x0a) + tuner = tuner_0_table[tuner_format]; + if (tuner_make == 1) + if(tuner_format <=9) + tuner = tuner_1_table[tuner_format]; + + if (tuner_make == 4) + if(tuner_format == 0x09) + tuner = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */ + + printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=", + btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]); + if(tuner) { + btv->tuner_type=tuner; + printk("%d",tuner); + } else + printk("Unknown type"); + printk(" radio:%s remote control:%s\n", + tuner_tv_fm ? "yes" : "no", + btv->has_remote ? "yes" : "no"); +} + +/* used on Voodoo TV/FM (Voodoo 200), S0 wired to 0x10000 */ +void bttv_tda9880_setnorm(struct bttv *btv, int norm) +{ + /* fix up our card entry */ + if(norm==VIDEO_MODE_NTSC) { + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x957fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x957fff; + dprintk("bttv_tda9880_setnorm to NTSC\n"); + } + else { + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x947fff; + dprintk("bttv_tda9880_setnorm to PAL\n"); + } + /* set GPIO according */ + gpio_bits(bttv_tvcards[btv->c.type].gpiomask, + bttv_tvcards[btv->c.type].audiomux[btv->audio]); +} + + +/* + * reset/enable the MSP on some Hauppauge cards + * Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! + * + * Hauppauge: pin 5 + * Voodoo: pin 20 + */ +static void __devinit boot_msp34xx(struct bttv *btv, int pin) +{ + int mask = (1 << pin); + + gpio_inout(mask,mask); + gpio_bits(mask,0); + udelay(2500); + gpio_bits(mask,mask); + + if (bttv_gpio) + bttv_gpio_tracking(btv,"msp34xx"); + if (bttv_verbose) + printk(KERN_INFO "bttv%d: Hauppauge/Voodoo msp34xx: reset line " + "init [%d]\n", btv->c.nr, pin); +} + +static void __devinit boot_bt832(struct bttv *btv) +{ +} + +/* ----------------------------------------------------------------------- */ +/* Imagenation L-Model PXC200 Framegrabber */ +/* This is basically the same procedure as + * used by Alessandro Rubini in his pxc200 + * driver, but using BTTV functions */ + +static void __devinit init_PXC200(struct bttv *btv) +{ + static int vals[] __devinitdata = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x00 }; + unsigned int i; + int tmp; + u32 val; + + /* Initialise GPIO-connevted stuff */ + gpio_inout(0xffffff, (1<<13)); + gpio_write(0); + udelay(3); + gpio_write(1<<13); + /* GPIO inputs are pulled up, so no need to drive + * reset pin any longer */ + gpio_bits(0xffffff, 0); + if (bttv_gpio) + bttv_gpio_tracking(btv,"pxc200"); + + /* we could/should try and reset/control the AD pots? but + right now we simply turned off the crushing. Without + this the AGC drifts drifts + remember the EN is reverse logic --> + setting BT848_ADC_AGC_EN disable the AGC + tboult@eecs.lehigh.edu + */ + + btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC); + + /* Initialise MAX517 DAC */ + printk(KERN_INFO "Setting DAC reference voltage level ...\n"); + bttv_I2CWrite(btv,0x5E,0,0x80,1); + + /* Initialise 12C508 PIC */ + /* The I2CWrite and I2CRead commmands are actually to the + * same chips - but the R/W bit is included in the address + * argument so the numbers are different */ + + + printk(KERN_INFO "Initialising 12C508 PIC chip ...\n"); + + /* First of all, enable the clock line. This is used in the PXC200-F */ + val = btread(BT848_GPIO_DMA_CTL); + val |= BT848_GPIO_DMA_CTL_GPCLKMODE; + btwrite(val, BT848_GPIO_DMA_CTL); + + /* Then, push to 0 the reset pin long enough to reset the * + * device same as above for the reset line, but not the same + * value sent to the GPIO-connected stuff + * which one is the good one? */ + gpio_inout(0xffffff,(1<<2)); + gpio_write(0); + udelay(10); + gpio_write(1<<2); + + for (i = 0; i < ARRAY_SIZE(vals); i++) { + tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1); + if (tmp != -1) { + printk(KERN_INFO + "I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n", + vals[i],tmp,bttv_I2CRead(btv,0x1F,NULL)); + } + } + + printk(KERN_INFO "PXC200 Initialised.\n"); +} + + + +/* ----------------------------------------------------------------------- */ +/* + * The Adlink RTV-24 (aka Angelo) has some special initialisation to unlock + * it. This apparently involves the following procedure for each 878 chip: + * + * 1) write 0x00C3FEFF to the GPIO_OUT_EN register + * + * 2) write to GPIO_DATA + * - 0x0E + * - sleep 1ms + * - 0x10 + 0x0E + * - sleep 10ms + * - 0x0E + * read from GPIO_DATA into buf (uint_32) + * - if ( data>>18 & 0x01 != 0) || ( buf>>19 & 0x01 != 1 ) + * error. ERROR_CPLD_Check_Failed stop. + * + * 3) write to GPIO_DATA + * - write 0x4400 + 0x0E + * - sleep 10ms + * - write 0x4410 + 0x0E + * - sleep 1ms + * - write 0x0E + * read from GPIO_DATA into buf (uint_32) + * - if ( buf>>18 & 0x01 ) || ( buf>>19 && 0x01 != 0 ) + * error. ERROR_CPLD_Check_Failed. + */ +/* ----------------------------------------------------------------------- */ +static void +init_RTV24 (struct bttv *btv) +{ + uint32_t dataRead = 0; + long watchdog_value = 0x0E; + + printk (KERN_INFO + "bttv%d: Adlink RTV-24 initialisation in progress ...\n", + btv->c.nr); + + btwrite (0x00c3feff, BT848_GPIO_OUT_EN); + + btwrite (0 + watchdog_value, BT848_GPIO_DATA); + msleep (1); + btwrite (0x10 + watchdog_value, BT848_GPIO_DATA); + msleep (10); + btwrite (0 + watchdog_value, BT848_GPIO_DATA); + + dataRead = btread (BT848_GPIO_DATA); + + if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) { + printk (KERN_INFO + "bttv%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n", + btv->c.nr, dataRead); + } + + btwrite (0x4400 + watchdog_value, BT848_GPIO_DATA); + msleep (10); + btwrite (0x4410 + watchdog_value, BT848_GPIO_DATA); + msleep (1); + btwrite (watchdog_value, BT848_GPIO_DATA); + msleep (1); + dataRead = btread (BT848_GPIO_DATA); + + if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) { + printk (KERN_INFO + "bttv%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n", + btv->c.nr, dataRead); + + return; + } + + printk (KERN_INFO + "bttv%d: Adlink RTV-24 initialisation complete.\n", btv->c.nr); +} + + + +/* ----------------------------------------------------------------------- */ +/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */ +/* + * Copyright (c) 1999 Csaba Halasz + * This code is placed under the terms of the GNU General Public License + * + * Brutally hacked by Dan Sheridan djs52 8/3/00 + */ + +static void bus_low(struct bttv *btv, int bit) +{ + if (btv->mbox_ior) { + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); + udelay(5); + } + + gpio_bits(bit,0); + udelay(5); + + if (btv->mbox_ior) { + gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); + udelay(5); + } +} + +static void bus_high(struct bttv *btv, int bit) +{ + if (btv->mbox_ior) { + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); + udelay(5); + } + + gpio_bits(bit,bit); + udelay(5); + + if (btv->mbox_ior) { + gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); + udelay(5); + } +} + +static int bus_in(struct bttv *btv, int bit) +{ + if (btv->mbox_ior) { + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); + udelay(5); + + gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); + udelay(5); + } + return gpio_read() & (bit); +} + +/* TEA5757 register bits */ +#define TEA_FREQ 0:14 +#define TEA_BUFFER 15:15 + +#define TEA_SIGNAL_STRENGTH 16:17 + +#define TEA_PORT1 18:18 +#define TEA_PORT0 19:19 + +#define TEA_BAND 20:21 +#define TEA_BAND_FM 0 +#define TEA_BAND_MW 1 +#define TEA_BAND_LW 2 +#define TEA_BAND_SW 3 + +#define TEA_MONO 22:22 +#define TEA_ALLOW_STEREO 0 +#define TEA_FORCE_MONO 1 + +#define TEA_SEARCH_DIRECTION 23:23 +#define TEA_SEARCH_DOWN 0 +#define TEA_SEARCH_UP 1 + +#define TEA_STATUS 24:24 +#define TEA_STATUS_TUNED 0 +#define TEA_STATUS_SEARCHING 1 + +/* Low-level stuff */ +static int tea5757_read(struct bttv *btv) +{ + unsigned long timeout; + int value = 0; + int i; + + /* better safe than sorry */ + gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we); + + if (btv->mbox_ior) { + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); + udelay(5); + } + + if (bttv_gpio) + bttv_gpio_tracking(btv,"tea5757 read"); + + bus_low(btv,btv->mbox_we); + bus_low(btv,btv->mbox_clk); + + udelay(10); + timeout= jiffies + HZ; + + /* wait for DATA line to go low; error if it doesn't */ + while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout)) + schedule(); + if (bus_in(btv,btv->mbox_data)) { + printk(KERN_WARNING "bttv%d: tea5757: read timeout\n",btv->c.nr); + return -1; + } + + dprintk("bttv%d: tea5757:",btv->c.nr); + for(i = 0; i < 24; i++) + { + udelay(5); + bus_high(btv,btv->mbox_clk); + udelay(5); + dprintk("%c",(bus_in(btv,btv->mbox_most) == 0)?'T':'-'); + bus_low(btv,btv->mbox_clk); + value <<= 1; + value |= (bus_in(btv,btv->mbox_data) == 0)?0:1; /* MSB first */ + dprintk("%c", (bus_in(btv,btv->mbox_most) == 0)?'S':'M'); + } + dprintk("\nbttv%d: tea5757: read 0x%X\n", btv->c.nr, value); + return value; +} + +static int tea5757_write(struct bttv *btv, int value) +{ + int i; + int reg = value; + + gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data); + + if (btv->mbox_ior) { + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); + udelay(5); + } + if (bttv_gpio) + bttv_gpio_tracking(btv,"tea5757 write"); + + dprintk("bttv%d: tea5757: write 0x%X\n", btv->c.nr, value); + bus_low(btv,btv->mbox_clk); + bus_high(btv,btv->mbox_we); + for(i = 0; i < 25; i++) + { + if (reg & 0x1000000) + bus_high(btv,btv->mbox_data); + else + bus_low(btv,btv->mbox_data); + reg <<= 1; + bus_high(btv,btv->mbox_clk); + udelay(10); + bus_low(btv,btv->mbox_clk); + udelay(10); + } + bus_low(btv,btv->mbox_we); /* unmute !!! */ + return 0; +} + +void tea5757_set_freq(struct bttv *btv, unsigned short freq) +{ + dprintk("tea5757_set_freq %d\n",freq); + tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */ +} + + +/* ----------------------------------------------------------------------- */ +/* winview */ + +static void winview_audio(struct bttv *btv, struct video_audio *v, int set) +{ + /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */ + int bits_out, loops, vol, data; + + if (!set) { + /* Fixed by Leandro Lucarella flags |= VIDEO_AUDIO_VOLUME; + return; + } + + /* 32 levels logarithmic */ + vol = 32 - ((v->volume>>11)); + /* units */ + bits_out = (PT2254_DBS_IN_2>>(vol%5)); + /* tens */ + bits_out |= (PT2254_DBS_IN_10>>(vol/5)); + bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL; + data = gpio_read(); + data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA| + WINVIEW_PT2254_STROBE); + for (loops = 17; loops >= 0 ; loops--) { + if (bits_out & (1<mode & VIDEO_SOUND_LANG1) + con = 0x000; + if (v->mode & VIDEO_SOUND_LANG2) + con = 0x300; + if (v->mode & VIDEO_SOUND_STEREO) + con = 0x200; +/* if (v->mode & VIDEO_SOUND_MONO) + * con = 0x100; */ + gpio_bits(0x300, con); + } else { + v->mode = VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +static void +gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int val, con; + + if (btv->radio_user) + return; + + val = gpio_read(); + if (set) { + con = 0x000; + if (v->mode & VIDEO_SOUND_LANG2) { + if (v->mode & VIDEO_SOUND_LANG1) { + /* LANG1 + LANG2 */ + con = 0x100; + } + else { + /* LANG2 */ + con = 0x300; + } + } + if (con != (val & 0x300)) { + gpio_bits(0x300, con); + if (bttv_gpio) + bttv_gpio_tracking(btv,"gvbctv5pci"); + } + } else { + switch (val & 0x70) { + case 0x10: + v->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + break; + case 0x30: + v->mode = VIDEO_SOUND_LANG2; + break; + case 0x50: + v->mode = VIDEO_SOUND_LANG1; + break; + case 0x60: + v->mode = VIDEO_SOUND_STEREO; + break; + case 0x70: + v->mode = VIDEO_SOUND_MONO; + break; + default: + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } + } +} + +/* + * Mario Medina Nussbaum + * I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo, + * 0xdde enables mono and 0xccd enables sap + * + * Petr Vandrovec + * P.S.: At least mask in line above is wrong - GPIO pins 3,2 select + * input/output sound connection, so both must be set for output mode. + * + * Looks like it's needed only for the "tvphone", the "tvphone 98" + * handles this with a tda9840 + * + */ +static void +avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set) +{ + int val = 0; + + if (set) { + if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ + val = 0x02; + if (v->mode & VIDEO_SOUND_STEREO) + val = 0x01; + if (val) { + gpio_bits(0x03,val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"avermedia"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1; + return; + } +} + +static void +avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) +{ + int val = 0; + + if (set) { + if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ + val = 0x01; + if (v->mode & VIDEO_SOUND_STEREO) /* STEREO */ + val = 0x02; + btaor(val, ~0x03, BT848_GPIO_DATA); + if (bttv_gpio) + bttv_gpio_tracking(btv,"avermedia"); + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + return; + } +} + +/* Lifetec 9415 handling */ +static void +lt9415_audio(struct bttv *btv, struct video_audio *v, int set) +{ + int val = 0; + + if (gpio_read() & 0x4000) { + v->mode = VIDEO_SOUND_MONO; + return; + } + + if (set) { + if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */ + val = 0x0080; + if (v->mode & VIDEO_SOUND_STEREO) /* A2 stereo */ + val = 0x0880; + if ((v->mode & VIDEO_SOUND_LANG1) || + (v->mode & VIDEO_SOUND_MONO)) + val = 0; + gpio_bits(0x0880, val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"lt9415"); + } else { + /* autodetect doesn't work with this card :-( */ + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + return; + } +} + +/* TDA9821 on TerraTV+ Bt848, Bt878 */ +static void +terratv_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int con = 0; + + if (set) { + gpio_inout(0x180000,0x180000); + if (v->mode & VIDEO_SOUND_LANG2) + con = 0x080000; + if (v->mode & VIDEO_SOUND_STEREO) + con = 0x180000; + gpio_bits(0x180000, con); + if (bttv_gpio) + bttv_gpio_tracking(btv,"terratv"); + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +static void +winfast2000_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned long val = 0; + + if (set) { + /*btor (0xc32000, BT848_GPIO_OUT_EN);*/ + if (v->mode & VIDEO_SOUND_MONO) /* Mono */ + val = 0x420000; + if (v->mode & VIDEO_SOUND_LANG1) /* Mono */ + val = 0x420000; + if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ + val = 0x410000; + if (v->mode & VIDEO_SOUND_STEREO) /* Stereo */ + val = 0x020000; + if (val) { + gpio_bits(0x430000, val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"winfast2000"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +/* + * Dariusz Kowalewski + * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM + * revision 9B has on-board TDA9874A sound decoder). + * + * Note: There are card variants without tda9874a. Forcing the "stereo sound route" + * will mute this cards. + */ +static void +pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int val = 0; + + if (btv->radio_user) + return; + + if (set) { + if (v->mode & VIDEO_SOUND_MONO) { + val = 0x01; + } + if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2)) + || (v->mode & VIDEO_SOUND_STEREO)) { + val = 0x02; + } + if (val) { + gpio_bits(0x03,val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"pvbt878p9b"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +/* + * Dariusz Kowalewski + * sound control for FlyVideo 2000S (with tda9874 decoder) + * based on pvbt878p9b_audio() - this is not tested, please fix!!! + */ +static void +fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int val = 0xffff; + + if (btv->radio_user) + return; + if (set) { + if (v->mode & VIDEO_SOUND_MONO) { + val = 0x0000; + } + if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2)) + || (v->mode & VIDEO_SOUND_STEREO)) { + val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */ + } + if (val != 0xffff) { + gpio_bits(0x1800, val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"fv2000s"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +/* + * sound control for Canopus WinDVR PCI + * Masaki Suzuki + */ +static void +windvr_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned long val = 0; + + if (set) { + if (v->mode & VIDEO_SOUND_MONO) + val = 0x040000; + if (v->mode & VIDEO_SOUND_LANG1) + val = 0; + if (v->mode & VIDEO_SOUND_LANG2) + val = 0x100000; + if (v->mode & VIDEO_SOUND_STEREO) + val = 0; + if (val) { + gpio_bits(0x140000, val); + if (bttv_gpio) + bttv_gpio_tracking(btv,"windvr"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +/* + * sound control for AD-TVK503 + * Hiroshi Takekawa + */ +static void +adtvk503_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int con = 0xffffff; + + /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */ + + if (set) { + /* btor(***, BT848_GPIO_OUT_EN); */ + if (v->mode & VIDEO_SOUND_LANG1) + con = 0x00000000; + if (v->mode & VIDEO_SOUND_LANG2) + con = 0x00180000; + if (v->mode & VIDEO_SOUND_STEREO) + con = 0x00000000; + if (v->mode & VIDEO_SOUND_MONO) + con = 0x00060000; + if (con != 0xffffff) { + gpio_bits(0x1e0000,con); + if (bttv_gpio) + bttv_gpio_tracking(btv, "adtvk503"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas] + * + * This is needed because rv605 don't use a normal multiplex, but a crosspoint + * switch instead (CD22M3494E). This IC can have multiple active connections + * between Xn (input) and Yn (output) pins. We need to clear any existing + * connection prior to establish a new one, pulsing the STROBE pin. + * + * The board hardwire Y0 (xpoint) to MUX1 and MUXOUT to Yin. + * GPIO pins are wired as: + * GPIO[0:3] - AX[0:3] (xpoint) - P1[0:3] (microcontroler) + * GPIO[4:6] - AY[0:2] (xpoint) - P1[4:6] (microcontroler) + * GPIO[7] - DATA (xpoint) - P1[7] (microcontroler) + * GPIO[8] - - P3[5] (microcontroler) + * GPIO[9] - RESET (xpoint) - P3[6] (microcontroler) + * GPIO[10] - STROBE (xpoint) - P3[7] (microcontroler) + * GPINTR - - P3[4] (microcontroler) + * + * The microcontroler is a 80C32 like. It should be possible to change xpoint + * configuration either directly (as we are doing) or using the microcontroler + * which is also wired to I2C interface. I have no further info on the + * microcontroler features, one would need to disassembly the firmware. + * note: the vendor refused to give any information on this product, all + * that stuff was found using a multimeter! :) + */ +static void rv605_muxsel(struct bttv *btv, unsigned int input) +{ + /* reset all conections */ + gpio_bits(0x200,0x200); + mdelay(1); + gpio_bits(0x200,0x000); + mdelay(1); + + /* create a new conection */ + gpio_bits(0x480,0x080); + gpio_bits(0x480,0x480); + mdelay(1); + gpio_bits(0x480,0x080); + mdelay(1); +} + +/* Tibet Systems 'Progress DVR' CS16 muxsel helper [Chris Fanning] + * + * The CS16 (available on eBay cheap) is a PCI board with four Fusion + * 878A chips, a PCI bridge, an Atmel microcontroller, four sync seperator + * chips, ten eight input analog multiplexors, a not chip and a few + * other components. + * + * 16 inputs on a secondary bracket are provided and can be selected + * from each of the four capture chips. Two of the eight input + * multiplexors are used to select from any of the 16 input signals. + * + * Unsupported hardware capabilities: + * . A video output monitor on the secondary bracket can be selected from + * one of the 878A chips. + * . Another passthrough but I haven't spent any time investigating it. + * . Digital I/O (logic level connected to GPIO) is available from an + * onboard header. + * + * The on chip input mux should always be set to 2. + * GPIO[16:19] - Video input selection + * GPIO[0:3] - Video output monitor select (only available from one 878A) + * GPIO[?:?] - Digital I/O. + * + * There is an ATMEL microcontroller with an 8031 core on board. I have not + * determined what function (if any) it provides. With the microcontroller + * and sync seperator chips a guess is that it might have to do with video + * switching and maybe some digital I/O. + */ +static void tibetCS16_muxsel(struct bttv *btv, unsigned int input) +{ + /* video mux */ + gpio_bits(0x0f0000, input << 16); +} + +static void tibetCS16_init(struct bttv *btv) +{ + /* enable gpio bits, mask obtained via btSpy */ + gpio_inout(0xffffff, 0x0f7fff); + gpio_write(0x0f7fff); +} + +/* + * The following routines for the Kodicom-4400r get a little mind-twisting. + * There is a "master" controller and three "slave" controllers, together + * an analog switch which connects any of 16 cameras to any of the BT87A's. + * The analog switch is controlled by the "master", but the detection order + * of the four BT878A chips is in an order which I just don't understand. + * The "master" is actually the second controller to be detected. The + * logic on the board uses logical numbers for the 4 controlers, but + * those numbers are different from the detection sequence. When working + * with the analog switch, we need to "map" from the detection sequence + * over to the board's logical controller number. This mapping sequence + * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical + * unit 3, the second (which is the master) is logical unit 0, etc. + * We need to maintain the status of the analog switch (which of the 16 + * cameras is connected to which of the 4 controllers). Rather than + * add to the bttv structure for this, we use the data reserved for + * the mbox (unused for this card type). + */ + +/* + * First a routine to set the analog switch, which controls which camera + * is routed to which controller. The switch comprises an X-address + * (gpio bits 0-3, representing the camera, ranging from 0-15), and a + * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3). + * A data value (gpio bit 7) of '1' enables the switch, and '0' disables + * the switch. A STROBE bit (gpio bit 8) latches the data value into the + * specified address. The idea is to set the address and data, then bring + * STROBE high, and finally bring STROBE back to low. + */ +static void kodicom4400r_write(struct bttv *btv, + unsigned char xaddr, + unsigned char yaddr, + unsigned char data) { + unsigned int udata; + + udata = (data << 7) | ((yaddr&3) << 4) | (xaddr&0xf); + gpio_bits(0x1ff, udata); /* write ADDR and DAT */ + gpio_bits(0x1ff, udata | (1 << 8)); /* strobe high */ + gpio_bits(0x1ff, udata); /* strobe low */ +} + +/* + * Next the mux select. Both the "master" and "slave" 'cards' (controllers) + * use this routine. The routine finds the "master" for the card, maps + * the controller number from the detected position over to the logical + * number, writes the appropriate data to the analog switch, and housekeeps + * the local copy of the switch information. The parameter 'input' is the + * requested camera number (0 - 15). + */ +static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) +{ + char *sw_status; + int xaddr, yaddr; + struct bttv *mctlr; + static unsigned char map[4] = {3, 0, 2, 1}; + + mctlr = master[btv->c.nr]; + if (mctlr == NULL) { /* ignore if master not yet detected */ + return; + } + yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */ + yaddr = map[yaddr]; + sw_status = (char *)(&mctlr->mbox_we); + xaddr = input & 0xf; + /* Check if the controller/camera pair has changed, else ignore */ + if (sw_status[yaddr] != xaddr) + { + /* "open" the old switch, "close" the new one, save the new */ + kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0); + sw_status[yaddr] = xaddr; + kodicom4400r_write(mctlr, xaddr, yaddr, 1); + } +} + +/* + * During initialisation, we need to reset the analog switch. We + * also preset the switch to map the 4 connectors on the card to the + * *user's* (see above description of kodicom4400r_muxsel) channels + * 0 through 3 + */ +static void kodicom4400r_init(struct bttv *btv) +{ + char *sw_status = (char *)(&btv->mbox_we); + int ix; + + gpio_inout(0x0003ff, 0x0003ff); + gpio_write(1 << 9); /* reset MUX */ + gpio_write(0); + /* Preset camera 0 to the 4 controllers */ + for (ix=0; ix<4; ix++) { + sw_status[ix] = ix; + kodicom4400r_write(btv, ix, ix, 1); + } + /* + * Since this is the "master", we need to set up the + * other three controller chips' pointers to this structure + * for later use in the muxsel routine. + */ + if ((btv->c.nr<1) || (btv->c.nr>BTTV_MAX-3)) + return; + master[btv->c.nr-1] = btv; + master[btv->c.nr] = btv; + master[btv->c.nr+1] = btv; + master[btv->c.nr+2] = btv; +} + +/* The Grandtec X-Guard framegrabber card uses two Dual 4-channel + * video multiplexers to provide up to 16 video inputs. These + * multiplexers are controlled by the lower 8 GPIO pins of the + * bt878. The multiplexers probably Pericom PI5V331Q or similar. + + * xxx0 is pin xxx of multiplexer U5, + * yyy1 is pin yyy of multiplexer U2 + */ +#define ENA0 0x01 +#define ENB0 0x02 +#define ENA1 0x04 +#define ENB1 0x08 + +#define IN10 0x10 +#define IN00 0x20 +#define IN11 0x40 +#define IN01 0x80 + +static void xguard_muxsel(struct bttv *btv, unsigned int input) +{ + static const int masks[] = { + ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10, + ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10, + ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11, + ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11, + }; + gpio_write(masks[input%16]); +} +static void picolo_tetra_init(struct bttv *btv) +{ + /*This is the video input redirection fonctionality : I DID NOT USED IT. */ + btwrite (0x08<<16,BT848_GPIO_DATA);/*GPIO[19] [==> 4053 B+C] set to 1 */ + btwrite (0x04<<16,BT848_GPIO_DATA);/*GPIO[18] [==> 4053 A] set to 1*/ +} +static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input) +{ + + dprintk (KERN_DEBUG "bttv%d : picolo_tetra_muxsel => input = %d\n",btv->c.nr,input); + /*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/ + /*GPIO[20]&GPIO[21] used to choose the right input*/ + btwrite (input<<20,BT848_GPIO_DATA); + +} + +/* + * ivc120_muxsel [Added by Alan Garfield ] + * + * The IVC120G security card has 4 i2c controlled TDA8540 matrix + * swichers to provide 16 channels to MUX0. The TDA8540's have + * 4 indepedant outputs and as such the IVC120G also has the + * optional "Monitor Out" bus. This allows the card to be looking + * at one input while the monitor is looking at another. + * + * Since I've couldn't be bothered figuring out how to add an + * independant muxsel for the monitor bus, I've just set it to + * whatever the card is looking at. + * + * OUT0 of the TDA8540's is connected to MUX0 (0x03) + * OUT1 of the TDA8540's is connected to "Monitor Out" (0x0C) + * + * TDA8540_ALT3 IN0-3 = Channel 13 - 16 (0x03) + * TDA8540_ALT4 IN0-3 = Channel 1 - 4 (0x03) + * TDA8540_ALT5 IN0-3 = Channel 5 - 8 (0x03) + * TDA8540_ALT6 IN0-3 = Channel 9 - 12 (0x03) + * + */ + +/* All 7 possible sub-ids for the TDA8540 Matrix Switcher */ +#define I2C_TDA8540 0x90 +#define I2C_TDA8540_ALT1 0x92 +#define I2C_TDA8540_ALT2 0x94 +#define I2C_TDA8540_ALT3 0x96 +#define I2C_TDA8540_ALT4 0x98 +#define I2C_TDA8540_ALT5 0x9a +#define I2C_TDA8540_ALT6 0x9c + +static void ivc120_muxsel(struct bttv *btv, unsigned int input) +{ + /* Simple maths */ + int key = input % 4; + int matrix = input / 4; + + dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n", + btv->c.nr, input, matrix, key); + + /* Handles the input selection on the TDA8540's */ + bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00, + ((matrix == 3) ? (key | key << 2) : 0x00), 1); + bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x00, + ((matrix == 0) ? (key | key << 2) : 0x00), 1); + bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x00, + ((matrix == 1) ? (key | key << 2) : 0x00), 1); + bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x00, + ((matrix == 2) ? (key | key << 2) : 0x00), 1); + + /* Handles the output enables on the TDA8540's */ + bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x02, + ((matrix == 3) ? 0x03 : 0x00), 1); /* 13 - 16 */ + bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x02, + ((matrix == 0) ? 0x03 : 0x00), 1); /* 1-4 */ + bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x02, + ((matrix == 1) ? 0x03 : 0x00), 1); /* 5-8 */ + bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02, + ((matrix == 2) ? 0x03 : 0x00), 1); /* 9-12 */ + + /* Selects MUX0 for input on the 878 */ + btaor((0)<<5, ~(3<<5), BT848_IFORM); +} + + +/* PXC200 muxsel helper + * luke@syseng.anu.edu.au + * another transplant + * from Alessandro Rubini (rubini@linux.it) + * + * There are 4 kinds of cards: + * PXC200L which is bt848 + * PXC200F which is bt848 with PIC controlling mux + * PXC200AL which is bt878 + * PXC200AF which is bt878 with PIC controlling mux + */ +#define PX_CFG_PXC200F 0x01 +#define PX_FLAG_PXC200A 0x00001000 /* a pxc200A is bt-878 based */ +#define PX_I2C_PIC 0x0f +#define PX_PXC200A_CARDID 0x200a1295 +#define PX_I2C_CMD_CFG 0x00 + +static void PXC200_muxsel(struct bttv *btv, unsigned int input) +{ + int rc; + long mux; + int bitmask; + unsigned char buf[2]; + + /* Read PIC config to determine if this is a PXC200F */ + /* PX_I2C_CMD_CFG*/ + buf[0]=0; + buf[1]=0; + rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1); + if (rc) { + printk(KERN_DEBUG "bttv%d: PXC200_muxsel: pic cfg write failed:%d\n", btv->c.nr,rc); + /* not PXC ? do nothing */ + return; + } + + rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL); + if (!(rc & PX_CFG_PXC200F)) { + printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc); + return; + } + + + /* The multiplexer in the 200F is handled by the GPIO port */ + /* get correct mapping between inputs */ + /* mux = bttv_tvcards[btv->type].muxsel[input] & 3; */ + /* ** not needed!? */ + mux = input; + + /* make sure output pins are enabled */ + /* bitmask=0x30f; */ + bitmask=0x302; + /* check whether we have a PXC200A */ + if (btv->cardid == PX_PXC200A_CARDID) { + bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */ + bitmask |= 7<<4; /* the DAC */ + } + btwrite(bitmask, BT848_GPIO_OUT_EN); + + bitmask = btread(BT848_GPIO_DATA); + if (btv->cardid == PX_PXC200A_CARDID) + bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7); + else /* older device */ + bitmask = (bitmask & ~0x300) | ((mux & 3) << 8); + btwrite(bitmask,BT848_GPIO_DATA); + + /* + * Was "to be safe, set the bt848 to input 0" + * Actually, since it's ok at load time, better not messing + * with these bits (on PXC200AF you need to set mux 2 here) + * + * needed because bttv-driver sets mux before calling this function + */ + if (btv->cardid == PX_PXC200A_CARDID) + btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM); + else /* older device */ + btand(~BT848_IFORM_MUXSEL,BT848_IFORM); + + printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux); +} + +/* ----------------------------------------------------------------------- */ +/* motherboard chipset specific stuff */ + +void __devinit bttv_check_chipset(void) +{ + int pcipci_fail = 0; + struct pci_dev *dev = NULL; + + if (pci_pci_problems & PCIPCI_FAIL) + pcipci_fail = 1; + if (pci_pci_problems & (PCIPCI_TRITON|PCIPCI_NATOMA|PCIPCI_VIAETBF)) + triton1 = 1; + if (pci_pci_problems & PCIPCI_VSFX) + vsfx = 1; +#ifdef PCIPCI_ALIMAGIK + if (pci_pci_problems & PCIPCI_ALIMAGIK) + latency = 0x0A; +#endif + + + /* print warnings about any quirks found */ + if (triton1) + printk(KERN_INFO "bttv: Host bridge needs ETBF enabled.\n"); + if (vsfx) + printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n"); + if (pcipci_fail) { + printk(KERN_INFO "bttv: bttv and your chipset may not work " + "together.\n"); + if (!no_overlay) { + printk(KERN_INFO "bttv: overlay will be disabled.\n"); + no_overlay = 1; + } else { + printk(KERN_INFO "bttv: overlay forced. Use this " + "option at your own risk.\n"); + } + } + if (UNSET != latency) + printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency); + while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82441, dev))) { + unsigned char b; + pci_read_config_byte(dev, 0x53, &b); + if (bttv_debug) + printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, " + "bufcon=0x%02x\n",b); + } +} + +int __devinit bttv_handle_chipset(struct bttv *btv) +{ + unsigned char command; + + if (!triton1 && !vsfx && UNSET == latency) + return 0; + + if (bttv_verbose) { + if (triton1) + printk(KERN_INFO "bttv%d: enabling ETBF (430FX/VP3 compatibilty)\n",btv->c.nr); + if (vsfx && btv->id >= 878) + printk(KERN_INFO "bttv%d: enabling VSFX\n",btv->c.nr); + if (UNSET != latency) + printk(KERN_INFO "bttv%d: setting pci timer to %d\n", + btv->c.nr,latency); + } + + if (btv->id < 878) { + /* bt848 (mis)uses a bit in the irq mask for etbf */ + if (triton1) + btv->triton1 = BT848_INT_ETBF; + } else { + /* bt878 has a bit in the pci config space for it */ + pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command); + if (triton1) + command |= BT878_EN_TBFX; + if (vsfx) + command |= BT878_EN_VSFX; + pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command); + } + if (UNSET != latency) + pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency); + return 0; +} + + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c new file mode 100644 index 000000000000..2505ae5a7b97 --- /dev/null +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -0,0 +1,4265 @@ +/* + + bttv - Bt848 frame grabber driver + + Copyright (C) 1996,97,98 Ralph Metzler + & Marcus Metzler + (c) 1999-2002 Gerd Knorr + + some v4l2 code lines are taken from Justin's bttv2 driver which is + (c) 2000 Justin Schoeman + + 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 +#include +#include "bttvp.h" +#include + +#include + +#include +#include + +#include "rds.h" + + +unsigned int bttv_num; /* number of Bt848s in use */ +struct bttv bttvs[BTTV_MAX]; + +unsigned int bttv_debug; +unsigned int bttv_verbose = 1; +unsigned int bttv_gpio; + +/* config variables */ +#ifdef __BIG_ENDIAN +static unsigned int bigendian=1; +#else +static unsigned int bigendian; +#endif +static unsigned int radio[BTTV_MAX]; +static unsigned int irq_debug; +static unsigned int gbuffers = 8; +static unsigned int gbufsize = 0x208000; + +static int video_nr = -1; +static int radio_nr = -1; +static int vbi_nr = -1; +static int debug_latency; + +static unsigned int fdsr; + +/* options */ +static unsigned int combfilter; +static unsigned int lumafilter; +static unsigned int automute = 1; +static unsigned int chroma_agc; +static unsigned int adc_crush = 1; +static unsigned int whitecrush_upper = 0xCF; +static unsigned int whitecrush_lower = 0x7F; +static unsigned int vcr_hack; +static unsigned int irq_iswitch; +static unsigned int uv_ratio = 50; +static unsigned int full_luma_range; +static unsigned int coring; +extern int no_overlay; + +/* API features (turn on/off stuff for testing) */ +static unsigned int v4l2 = 1; + +/* insmod args */ +module_param(bttv_verbose, int, 0644); +module_param(bttv_gpio, int, 0644); +module_param(bttv_debug, int, 0644); +module_param(irq_debug, int, 0644); +module_param(debug_latency, int, 0644); + +module_param(fdsr, int, 0444); +module_param(video_nr, int, 0444); +module_param(radio_nr, int, 0444); +module_param(vbi_nr, int, 0444); +module_param(gbuffers, int, 0444); +module_param(gbufsize, int, 0444); + +module_param(v4l2, int, 0644); +module_param(bigendian, int, 0644); +module_param(irq_iswitch, int, 0644); +module_param(combfilter, int, 0444); +module_param(lumafilter, int, 0444); +module_param(automute, int, 0444); +module_param(chroma_agc, int, 0444); +module_param(adc_crush, int, 0444); +module_param(whitecrush_upper, int, 0444); +module_param(whitecrush_lower, int, 0444); +module_param(vcr_hack, int, 0444); +module_param(uv_ratio, int, 0444); +module_param(full_luma_range, int, 0444); +module_param(coring, int, 0444); + +module_param_array(radio, int, NULL, 0444); + +MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)"); +MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian"); +MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)"); +MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)"); +MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)"); +MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)"); +MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8"); +MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000"); +MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)"); +MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)"); +MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)"); +MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207"); +MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127"); +MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)"); +MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler"); +MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50"); +MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)"); +MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)"); + +MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards"); +MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); +MODULE_LICENSE("GPL"); + +/* ----------------------------------------------------------------------- */ +/* sysfs */ + +static ssize_t show_card(struct class_device *cd, char *buf) +{ + struct video_device *vfd = to_video_device(cd); + struct bttv *btv = dev_get_drvdata(vfd->dev); + return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); +} +static CLASS_DEVICE_ATTR(card, S_IRUGO, show_card, NULL); + +/* ----------------------------------------------------------------------- */ +/* static data */ + +/* special timing tables from conexant... */ +static u8 SRAM_Table[][60] = +{ + /* PAL digital input over GPIO[7:0] */ + { + 45, // 45 bytes following + 0x36,0x11,0x01,0x00,0x90,0x02,0x05,0x10,0x04,0x16, + 0x12,0x05,0x11,0x00,0x04,0x12,0xC0,0x00,0x31,0x00, + 0x06,0x51,0x08,0x03,0x89,0x08,0x07,0xC0,0x44,0x00, + 0x81,0x01,0x01,0xA9,0x0D,0x02,0x02,0x50,0x03,0x37, + 0x37,0x00,0xAF,0x21,0x00 + }, + /* NTSC digital input over GPIO[7:0] */ + { + 51, // 51 bytes following + 0x0C,0xC0,0x00,0x00,0x90,0x02,0x03,0x10,0x03,0x06, + 0x10,0x04,0x12,0x12,0x05,0x02,0x13,0x04,0x19,0x00, + 0x04,0x39,0x00,0x06,0x59,0x08,0x03,0x83,0x08,0x07, + 0x03,0x50,0x00,0xC0,0x40,0x00,0x86,0x01,0x01,0xA6, + 0x0D,0x02,0x03,0x11,0x01,0x05,0x37,0x00,0xAC,0x21, + 0x00, + }, + // TGB_NTSC392 // quartzsight + // This table has been modified to be used for Fusion Rev D + { + 0x2A, // size of table = 42 + 0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24, + 0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10, + 0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00, + 0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3, + 0x20, 0x00 + } +}; + +const struct bttv_tvnorm bttv_tvnorms[] = { + /* PAL-BDGHI */ + /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ + /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ + { + .v4l2_id = V4L2_STD_PAL, + .name = "PAL", + .Fsc = 35468950, + .swidth = 924, + .sheight = 576, + .totalwidth = 1135, + .adelay = 0x7f, + .bdelay = 0x72, + .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), + .scaledtwidth = 1135, + .hdelayx1 = 186, + .hactivex1 = 924, + .vdelay = 0x20, + .vbipack = 255, + .sram = 0, + /* ITU-R frame line number of the first VBI line + we can capture, of the first and second field. */ + .vbistart = { 7,320 }, + },{ + .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, + .name = "NTSC", + .Fsc = 28636363, + .swidth = 768, + .sheight = 480, + .totalwidth = 910, + .adelay = 0x68, + .bdelay = 0x5d, + .iform = (BT848_IFORM_NTSC|BT848_IFORM_XT0), + .scaledtwidth = 910, + .hdelayx1 = 128, + .hactivex1 = 910, + .vdelay = 0x1a, + .vbipack = 144, + .sram = 1, + .vbistart = { 10, 273 }, + },{ + .v4l2_id = V4L2_STD_SECAM, + .name = "SECAM", + .Fsc = 35468950, + .swidth = 924, + .sheight = 576, + .totalwidth = 1135, + .adelay = 0x7f, + .bdelay = 0xb0, + .iform = (BT848_IFORM_SECAM|BT848_IFORM_XT1), + .scaledtwidth = 1135, + .hdelayx1 = 186, + .hactivex1 = 922, + .vdelay = 0x20, + .vbipack = 255, + .sram = 0, /* like PAL, correct? */ + .vbistart = { 7, 320 }, + },{ + .v4l2_id = V4L2_STD_PAL_Nc, + .name = "PAL-Nc", + .Fsc = 28636363, + .swidth = 640, + .sheight = 576, + .totalwidth = 910, + .adelay = 0x68, + .bdelay = 0x5d, + .iform = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0), + .scaledtwidth = 780, + .hdelayx1 = 130, + .hactivex1 = 734, + .vdelay = 0x1a, + .vbipack = 144, + .sram = -1, + .vbistart = { 7, 320 }, + },{ + .v4l2_id = V4L2_STD_PAL_M, + .name = "PAL-M", + .Fsc = 28636363, + .swidth = 640, + .sheight = 480, + .totalwidth = 910, + .adelay = 0x68, + .bdelay = 0x5d, + .iform = (BT848_IFORM_PAL_M|BT848_IFORM_XT0), + .scaledtwidth = 780, + .hdelayx1 = 135, + .hactivex1 = 754, + .vdelay = 0x1a, + .vbipack = 144, + .sram = -1, + .vbistart = { 10, 273 }, + },{ + .v4l2_id = V4L2_STD_PAL_N, + .name = "PAL-N", + .Fsc = 35468950, + .swidth = 768, + .sheight = 576, + .totalwidth = 1135, + .adelay = 0x7f, + .bdelay = 0x72, + .iform = (BT848_IFORM_PAL_N|BT848_IFORM_XT1), + .scaledtwidth = 944, + .hdelayx1 = 186, + .hactivex1 = 922, + .vdelay = 0x20, + .vbipack = 144, + .sram = -1, + .vbistart = { 7, 320}, + },{ + .v4l2_id = V4L2_STD_NTSC_M_JP, + .name = "NTSC-JP", + .Fsc = 28636363, + .swidth = 640, + .sheight = 480, + .totalwidth = 910, + .adelay = 0x68, + .bdelay = 0x5d, + .iform = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0), + .scaledtwidth = 780, + .hdelayx1 = 135, + .hactivex1 = 754, + .vdelay = 0x16, + .vbipack = 144, + .sram = -1, + .vbistart = {10, 273}, + },{ + /* that one hopefully works with the strange timing + * which video recorders produce when playing a NTSC + * tape on a PAL TV ... */ + .v4l2_id = V4L2_STD_PAL_60, + .name = "PAL-60", + .Fsc = 35468950, + .swidth = 924, + .sheight = 480, + .totalwidth = 1135, + .adelay = 0x7f, + .bdelay = 0x72, + .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), + .scaledtwidth = 1135, + .hdelayx1 = 186, + .hactivex1 = 924, + .vdelay = 0x1a, + .vbipack = 255, + .vtotal = 524, + .sram = -1, + .vbistart = { 10, 273 }, + } +}; +static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms); + +/* ----------------------------------------------------------------------- */ +/* bttv format list + packed pixel formats must come first */ +static const struct bttv_format bttv_formats[] = { + { + .name = "8 bpp, gray", + .palette = VIDEO_PALETTE_GREY, + .fourcc = V4L2_PIX_FMT_GREY, + .btformat = BT848_COLOR_FMT_Y8, + .depth = 8, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "8 bpp, dithered color", + .palette = VIDEO_PALETTE_HI240, + .fourcc = V4L2_PIX_FMT_HI240, + .btformat = BT848_COLOR_FMT_RGB8, + .depth = 8, + .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER, + },{ + .name = "15 bpp RGB, le", + .palette = VIDEO_PALETTE_RGB555, + .fourcc = V4L2_PIX_FMT_RGB555, + .btformat = BT848_COLOR_FMT_RGB15, + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "15 bpp RGB, be", + .palette = -1, + .fourcc = V4L2_PIX_FMT_RGB555X, + .btformat = BT848_COLOR_FMT_RGB15, + .btswap = 0x03, /* byteswap */ + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "16 bpp RGB, le", + .palette = VIDEO_PALETTE_RGB565, + .fourcc = V4L2_PIX_FMT_RGB565, + .btformat = BT848_COLOR_FMT_RGB16, + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "16 bpp RGB, be", + .palette = -1, + .fourcc = V4L2_PIX_FMT_RGB565X, + .btformat = BT848_COLOR_FMT_RGB16, + .btswap = 0x03, /* byteswap */ + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "24 bpp RGB, le", + .palette = VIDEO_PALETTE_RGB24, + .fourcc = V4L2_PIX_FMT_BGR24, + .btformat = BT848_COLOR_FMT_RGB24, + .depth = 24, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "32 bpp RGB, le", + .palette = VIDEO_PALETTE_RGB32, + .fourcc = V4L2_PIX_FMT_BGR32, + .btformat = BT848_COLOR_FMT_RGB32, + .depth = 32, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "32 bpp RGB, be", + .palette = -1, + .fourcc = V4L2_PIX_FMT_RGB32, + .btformat = BT848_COLOR_FMT_RGB32, + .btswap = 0x0f, /* byte+word swap */ + .depth = 32, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "4:2:2, packed, YUYV", + .palette = VIDEO_PALETTE_YUV422, + .fourcc = V4L2_PIX_FMT_YUYV, + .btformat = BT848_COLOR_FMT_YUY2, + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "4:2:2, packed, YUYV", + .palette = VIDEO_PALETTE_YUYV, + .fourcc = V4L2_PIX_FMT_YUYV, + .btformat = BT848_COLOR_FMT_YUY2, + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "4:2:2, packed, UYVY", + .palette = VIDEO_PALETTE_UYVY, + .fourcc = V4L2_PIX_FMT_UYVY, + .btformat = BT848_COLOR_FMT_YUY2, + .btswap = 0x03, /* byteswap */ + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "4:2:2, planar, Y-Cb-Cr", + .palette = VIDEO_PALETTE_YUV422P, + .fourcc = V4L2_PIX_FMT_YUV422P, + .btformat = BT848_COLOR_FMT_YCrCb422, + .depth = 16, + .flags = FORMAT_FLAGS_PLANAR, + .hshift = 1, + .vshift = 0, + },{ + .name = "4:2:0, planar, Y-Cb-Cr", + .palette = VIDEO_PALETTE_YUV420P, + .fourcc = V4L2_PIX_FMT_YUV420, + .btformat = BT848_COLOR_FMT_YCrCb422, + .depth = 12, + .flags = FORMAT_FLAGS_PLANAR, + .hshift = 1, + .vshift = 1, + },{ + .name = "4:2:0, planar, Y-Cr-Cb", + .palette = -1, + .fourcc = V4L2_PIX_FMT_YVU420, + .btformat = BT848_COLOR_FMT_YCrCb422, + .depth = 12, + .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb, + .hshift = 1, + .vshift = 1, + },{ + .name = "4:1:1, planar, Y-Cb-Cr", + .palette = VIDEO_PALETTE_YUV411P, + .fourcc = V4L2_PIX_FMT_YUV411P, + .btformat = BT848_COLOR_FMT_YCrCb411, + .depth = 12, + .flags = FORMAT_FLAGS_PLANAR, + .hshift = 2, + .vshift = 0, + },{ + .name = "4:1:0, planar, Y-Cb-Cr", + .palette = VIDEO_PALETTE_YUV410P, + .fourcc = V4L2_PIX_FMT_YUV410, + .btformat = BT848_COLOR_FMT_YCrCb411, + .depth = 9, + .flags = FORMAT_FLAGS_PLANAR, + .hshift = 2, + .vshift = 2, + },{ + .name = "4:1:0, planar, Y-Cr-Cb", + .palette = -1, + .fourcc = V4L2_PIX_FMT_YVU410, + .btformat = BT848_COLOR_FMT_YCrCb411, + .depth = 9, + .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb, + .hshift = 2, + .vshift = 2, + },{ + .name = "raw scanlines", + .palette = VIDEO_PALETTE_RAW, + .fourcc = -1, + .btformat = BT848_COLOR_FMT_RAW, + .depth = 8, + .flags = FORMAT_FLAGS_RAW, + } +}; +static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats); + +/* ----------------------------------------------------------------------- */ + +#define V4L2_CID_PRIVATE_CHROMA_AGC (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_PRIVATE_COMBFILTER (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 2) +#define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_PRIVATE_BASE + 4) +#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_PRIVATE_BASE + 5) +#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_PRIVATE_BASE + 6) +#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_PRIVATE_BASE + 7) +#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_PRIVATE_BASE + 8) +#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_PRIVATE_BASE + 9) +#define V4L2_CID_PRIVATE_CORING (V4L2_CID_PRIVATE_BASE + 10) +#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 11) + +static const struct v4l2_queryctrl no_ctl = { + .name = "42", + .flags = V4L2_CTRL_FLAG_DISABLED, +}; +static const struct v4l2_queryctrl bttv_ctls[] = { + /* --- video --- */ + { + .id = V4L2_CID_BRIGHTNESS, + .name = "Brightness", + .minimum = 0, + .maximum = 65535, + .step = 256, + .default_value = 32768, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_CONTRAST, + .name = "Contrast", + .minimum = 0, + .maximum = 65535, + .step = 128, + .default_value = 32768, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_SATURATION, + .name = "Saturation", + .minimum = 0, + .maximum = 65535, + .step = 128, + .default_value = 32768, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_HUE, + .name = "Hue", + .minimum = 0, + .maximum = 65535, + .step = 256, + .default_value = 32768, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + /* --- audio --- */ + { + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_AUDIO_VOLUME, + .name = "Volume", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 65535, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_AUDIO_BALANCE, + .name = "Balance", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 32768, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_AUDIO_BASS, + .name = "Bass", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 32768, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_AUDIO_TREBLE, + .name = "Treble", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 32768, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + /* --- private --- */ + { + .id = V4L2_CID_PRIVATE_CHROMA_AGC, + .name = "chroma agc", + .minimum = 0, + .maximum = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_PRIVATE_COMBFILTER, + .name = "combfilter", + .minimum = 0, + .maximum = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_PRIVATE_AUTOMUTE, + .name = "automute", + .minimum = 0, + .maximum = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_PRIVATE_LUMAFILTER, + .name = "luma decimation filter", + .minimum = 0, + .maximum = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_PRIVATE_AGC_CRUSH, + .name = "agc crush", + .minimum = 0, + .maximum = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_PRIVATE_VCR_HACK, + .name = "vcr hack", + .minimum = 0, + .maximum = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER, + .name = "whitecrush upper", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 0xCF, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER, + .name = "whitecrush lower", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 0x7F, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_PRIVATE_UV_RATIO, + .name = "uv ratio", + .minimum = 0, + .maximum = 100, + .step = 1, + .default_value = 50, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE, + .name = "full luma range", + .minimum = 0, + .maximum = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_PRIVATE_CORING, + .name = "coring", + .minimum = 0, + .maximum = 3, + .step = 1, + .default_value = 0, + .type = V4L2_CTRL_TYPE_INTEGER, + } + + + +}; +static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls); + +/* ----------------------------------------------------------------------- */ +/* resource management */ + +static +int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit) +{ + if (fh->resources & bit) + /* have it already allocated */ + return 1; + + /* is it free? */ + mutex_lock(&btv->reslock); + if (btv->resources & bit) { + /* no, someone else uses it */ + mutex_unlock(&btv->reslock); + return 0; + } + /* it's free, grab it */ + fh->resources |= bit; + btv->resources |= bit; + mutex_unlock(&btv->reslock); + return 1; +} + +static +int check_btres(struct bttv_fh *fh, int bit) +{ + return (fh->resources & bit); +} + +static +int locked_btres(struct bttv *btv, int bit) +{ + return (btv->resources & bit); +} + +static +void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits) +{ + if ((fh->resources & bits) != bits) { + /* trying to free ressources not allocated by us ... */ + printk("bttv: BUG! (btres)\n"); + } + mutex_lock(&btv->reslock); + fh->resources &= ~bits; + btv->resources &= ~bits; + mutex_unlock(&btv->reslock); +} + +/* ----------------------------------------------------------------------- */ +/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */ + +/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C + PLL_X = Reference pre-divider (0=1, 1=2) + PLL_C = Post divider (0=6, 1=4) + PLL_I = Integer input + PLL_F = Fractional input + + F_input = 28.636363 MHz: + PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0 +*/ + +static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout) +{ + unsigned char fl, fh, fi; + + /* prevent overflows */ + fin/=4; + fout/=4; + + fout*=12; + fi=fout/fin; + + fout=(fout%fin)*256; + fh=fout/fin; + + fout=(fout%fin)*256; + fl=fout/fin; + + btwrite(fl, BT848_PLL_F_LO); + btwrite(fh, BT848_PLL_F_HI); + btwrite(fi|BT848_PLL_X, BT848_PLL_XCI); +} + +static void set_pll(struct bttv *btv) +{ + int i; + + if (!btv->pll.pll_crystal) + return; + + if (btv->pll.pll_ofreq == btv->pll.pll_current) { + dprintk("bttv%d: PLL: no change required\n",btv->c.nr); + return; + } + + if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) { + /* no PLL needed */ + if (btv->pll.pll_current == 0) + return; + bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n", + btv->c.nr,btv->pll.pll_ifreq); + btwrite(0x00,BT848_TGCTRL); + btwrite(0x00,BT848_PLL_XCI); + btv->pll.pll_current = 0; + return; + } + + bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr, + btv->pll.pll_ifreq, btv->pll.pll_ofreq); + set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq); + + for (i=0; i<10; i++) { + /* Let other people run while the PLL stabilizes */ + bttv_printk("."); + msleep(10); + + if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) { + btwrite(0,BT848_DSTATUS); + } else { + btwrite(0x08,BT848_TGCTRL); + btv->pll.pll_current = btv->pll.pll_ofreq; + bttv_printk(" ok\n"); + return; + } + } + btv->pll.pll_current = -1; + bttv_printk("failed\n"); + return; +} + +/* used to switch between the bt848's analog/digital video capture modes */ +static void bt848A_set_timing(struct bttv *btv) +{ + int i, len; + int table_idx = bttv_tvnorms[btv->tvnorm].sram; + int fsc = bttv_tvnorms[btv->tvnorm].Fsc; + + if (UNSET == bttv_tvcards[btv->c.type].muxsel[btv->input]) { + dprintk("bttv%d: load digital timing table (table_idx=%d)\n", + btv->c.nr,table_idx); + + /* timing change...reset timing generator address */ + btwrite(0x00, BT848_TGCTRL); + btwrite(0x02, BT848_TGCTRL); + btwrite(0x00, BT848_TGCTRL); + + len=SRAM_Table[table_idx][0]; + for(i = 1; i <= len; i++) + btwrite(SRAM_Table[table_idx][i],BT848_TGLB); + btv->pll.pll_ofreq = 27000000; + + set_pll(btv); + btwrite(0x11, BT848_TGCTRL); + btwrite(0x41, BT848_DVSIF); + } else { + btv->pll.pll_ofreq = fsc; + set_pll(btv); + btwrite(0x0, BT848_DVSIF); + } +} + +/* ----------------------------------------------------------------------- */ + +static void bt848_bright(struct bttv *btv, int bright) +{ + int value; + + // printk("bttv: set bright: %d\n",bright); // DEBUG + btv->bright = bright; + + /* We want -128 to 127 we get 0-65535 */ + value = (bright >> 8) - 128; + btwrite(value & 0xff, BT848_BRIGHT); +} + +static void bt848_hue(struct bttv *btv, int hue) +{ + int value; + + btv->hue = hue; + + /* -128 to 127 */ + value = (hue >> 8) - 128; + btwrite(value & 0xff, BT848_HUE); +} + +static void bt848_contrast(struct bttv *btv, int cont) +{ + int value,hibit; + + btv->contrast = cont; + + /* 0-511 */ + value = (cont >> 7); + hibit = (value >> 6) & 4; + btwrite(value & 0xff, BT848_CONTRAST_LO); + btaor(hibit, ~4, BT848_E_CONTROL); + btaor(hibit, ~4, BT848_O_CONTROL); +} + +static void bt848_sat(struct bttv *btv, int color) +{ + int val_u,val_v,hibits; + + btv->saturation = color; + + /* 0-511 for the color */ + val_u = ((color * btv->opt_uv_ratio) / 50) >> 7; + val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254; + hibits = (val_u >> 7) & 2; + hibits |= (val_v >> 8) & 1; + btwrite(val_u & 0xff, BT848_SAT_U_LO); + btwrite(val_v & 0xff, BT848_SAT_V_LO); + btaor(hibits, ~3, BT848_E_CONTROL); + btaor(hibits, ~3, BT848_O_CONTROL); +} + +/* ----------------------------------------------------------------------- */ + +static int +video_mux(struct bttv *btv, unsigned int input) +{ + int mux,mask2; + + if (input >= bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; + + /* needed by RemoteVideo MX */ + mask2 = bttv_tvcards[btv->c.type].gpiomask2; + if (mask2) + gpio_inout(mask2,mask2); + + if (input == btv->svhs) { + btor(BT848_CONTROL_COMP, BT848_E_CONTROL); + btor(BT848_CONTROL_COMP, BT848_O_CONTROL); + } else { + btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); + btand(~BT848_CONTROL_COMP, BT848_O_CONTROL); + } + mux = bttv_tvcards[btv->c.type].muxsel[input] & 3; + btaor(mux<<5, ~(3<<5), BT848_IFORM); + dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n", + btv->c.nr,input,mux); + + /* card specific hook */ + if(bttv_tvcards[btv->c.type].muxsel_hook) + bttv_tvcards[btv->c.type].muxsel_hook (btv, input); + return 0; +} + +static char *audio_modes[] = { + "audio: tuner", "audio: radio", "audio: extern", + "audio: intern", "audio: off" +}; + +static int +audio_mux(struct bttv *btv, int mode) +{ + int val,mux,i2c_mux,signal; + + gpio_inout(bttv_tvcards[btv->c.type].gpiomask, + bttv_tvcards[btv->c.type].gpiomask); + signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC; + + switch (mode) { + case AUDIO_MUTE: + btv->audio |= AUDIO_MUTE; + break; + case AUDIO_UNMUTE: + btv->audio &= ~AUDIO_MUTE; + break; + case AUDIO_TUNER: + case AUDIO_RADIO: + case AUDIO_EXTERN: + case AUDIO_INTERN: + btv->audio &= AUDIO_MUTE; + btv->audio |= mode; + } + i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio; + if (btv->opt_automute && !signal && !btv->radio_user) + mux = AUDIO_OFF; + + val = bttv_tvcards[btv->c.type].audiomux[mux]; + gpio_bits(bttv_tvcards[btv->c.type].gpiomask,val); + if (bttv_gpio) + bttv_gpio_tracking(btv,audio_modes[mux]); + if (!in_interrupt()) + bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(i2c_mux)); + return 0; +} + +static void +i2c_vidiocschan(struct bttv *btv) +{ + struct video_channel c; + + memset(&c,0,sizeof(c)); + c.norm = btv->tvnorm; + c.channel = btv->input; + bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c); + if (btv->c.type == BTTV_BOARD_VOODOOTV_FM) + bttv_tda9880_setnorm(btv,c.norm); +} + +static int +set_tvnorm(struct bttv *btv, unsigned int norm) +{ + const struct bttv_tvnorm *tvnorm; + + if (norm < 0 || norm >= BTTV_TVNORMS) + return -EINVAL; + + btv->tvnorm = norm; + tvnorm = &bttv_tvnorms[norm]; + + btwrite(tvnorm->adelay, BT848_ADELAY); + btwrite(tvnorm->bdelay, BT848_BDELAY); + btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), + BT848_IFORM); + btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE); + btwrite(1, BT848_VBI_PACK_DEL); + bt848A_set_timing(btv); + + switch (btv->c.type) { + case BTTV_BOARD_VOODOOTV_FM: + bttv_tda9880_setnorm(btv,norm); + break; + } + return 0; +} + +static void +set_input(struct bttv *btv, unsigned int input) +{ + unsigned long flags; + + btv->input = input; + if (irq_iswitch) { + spin_lock_irqsave(&btv->s_lock,flags); + if (btv->curr.frame_irq) { + /* active capture -> delayed input switch */ + btv->new_input = input; + } else { + video_mux(btv,input); + } + spin_unlock_irqrestore(&btv->s_lock,flags); + } else { + video_mux(btv,input); + } + audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ? + AUDIO_TUNER : AUDIO_EXTERN)); + set_tvnorm(btv,btv->tvnorm); + i2c_vidiocschan(btv); +} + +static void init_irqreg(struct bttv *btv) +{ + /* clear status */ + btwrite(0xfffffUL, BT848_INT_STAT); + + if (bttv_tvcards[btv->c.type].no_video) { + /* i2c only */ + btwrite(BT848_INT_I2CDONE, + BT848_INT_MASK); + } else { + /* full video */ + btwrite((btv->triton1) | + (btv->gpioirq ? BT848_INT_GPINT : 0) | + BT848_INT_SCERR | + (fdsr ? BT848_INT_FDSR : 0) | + BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES| + BT848_INT_FMTCHG|BT848_INT_HLOCK| + BT848_INT_I2CDONE, + BT848_INT_MASK); + } +} + +static void init_bt848(struct bttv *btv) +{ + int val; + + if (bttv_tvcards[btv->c.type].no_video) { + /* very basic init only */ + init_irqreg(btv); + return; + } + + btwrite(0x00, BT848_CAP_CTL); + btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); + btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM); + + /* set planar and packed mode trigger points and */ + /* set rising edge of inverted GPINTR pin as irq trigger */ + btwrite(BT848_GPIO_DMA_CTL_PKTP_32| + BT848_GPIO_DMA_CTL_PLTP1_16| + BT848_GPIO_DMA_CTL_PLTP23_16| + BT848_GPIO_DMA_CTL_GPINTC| + BT848_GPIO_DMA_CTL_GPINTI, + BT848_GPIO_DMA_CTL); + + val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0; + btwrite(val, BT848_E_SCLOOP); + btwrite(val, BT848_O_SCLOOP); + + btwrite(0x20, BT848_E_VSCALE_HI); + btwrite(0x20, BT848_O_VSCALE_HI); + btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), + BT848_ADC); + + btwrite(whitecrush_upper, BT848_WC_UP); + btwrite(whitecrush_lower, BT848_WC_DOWN); + + if (btv->opt_lumafilter) { + btwrite(0, BT848_E_CONTROL); + btwrite(0, BT848_O_CONTROL); + } else { + btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL); + btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL); + } + + bt848_bright(btv, btv->bright); + bt848_hue(btv, btv->hue); + bt848_contrast(btv, btv->contrast); + bt848_sat(btv, btv->saturation); + + /* interrupt */ + init_irqreg(btv); +} + +static void bttv_reinit_bt848(struct bttv *btv) +{ + unsigned long flags; + + if (bttv_verbose) + printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr); + spin_lock_irqsave(&btv->s_lock,flags); + btv->errors=0; + bttv_set_dma(btv,0); + spin_unlock_irqrestore(&btv->s_lock,flags); + + init_bt848(btv); + btv->pll.pll_current = -1; + set_input(btv,btv->input); +} + +static int get_control(struct bttv *btv, struct v4l2_control *c) +{ + struct video_audio va; + int i; + + for (i = 0; i < BTTV_CTLS; i++) + if (bttv_ctls[i].id == c->id) + break; + if (i == BTTV_CTLS) + return -EINVAL; + if (i >= 4 && i <= 8) { + memset(&va,0,sizeof(va)); + bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); + if (btv->audio_hook) + btv->audio_hook(btv,&va,0); + } + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + c->value = btv->bright; + break; + case V4L2_CID_HUE: + c->value = btv->hue; + break; + case V4L2_CID_CONTRAST: + c->value = btv->contrast; + break; + case V4L2_CID_SATURATION: + c->value = btv->saturation; + break; + + case V4L2_CID_AUDIO_MUTE: + c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0; + break; + case V4L2_CID_AUDIO_VOLUME: + c->value = va.volume; + break; + case V4L2_CID_AUDIO_BALANCE: + c->value = va.balance; + break; + case V4L2_CID_AUDIO_BASS: + c->value = va.bass; + break; + case V4L2_CID_AUDIO_TREBLE: + c->value = va.treble; + break; + + case V4L2_CID_PRIVATE_CHROMA_AGC: + c->value = btv->opt_chroma_agc; + break; + case V4L2_CID_PRIVATE_COMBFILTER: + c->value = btv->opt_combfilter; + break; + case V4L2_CID_PRIVATE_LUMAFILTER: + c->value = btv->opt_lumafilter; + break; + case V4L2_CID_PRIVATE_AUTOMUTE: + c->value = btv->opt_automute; + break; + case V4L2_CID_PRIVATE_AGC_CRUSH: + c->value = btv->opt_adc_crush; + break; + case V4L2_CID_PRIVATE_VCR_HACK: + c->value = btv->opt_vcr_hack; + break; + case V4L2_CID_PRIVATE_WHITECRUSH_UPPER: + c->value = btv->opt_whitecrush_upper; + break; + case V4L2_CID_PRIVATE_WHITECRUSH_LOWER: + c->value = btv->opt_whitecrush_lower; + break; + case V4L2_CID_PRIVATE_UV_RATIO: + c->value = btv->opt_uv_ratio; + break; + case V4L2_CID_PRIVATE_FULL_LUMA_RANGE: + c->value = btv->opt_full_luma_range; + break; + case V4L2_CID_PRIVATE_CORING: + c->value = btv->opt_coring; + break; + default: + return -EINVAL; + } + return 0; +} + +static int set_control(struct bttv *btv, struct v4l2_control *c) +{ + struct video_audio va; + int i,val; + + for (i = 0; i < BTTV_CTLS; i++) + if (bttv_ctls[i].id == c->id) + break; + if (i == BTTV_CTLS) + return -EINVAL; + if (i >= 4 && i <= 8) { + memset(&va,0,sizeof(va)); + bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); + if (btv->audio_hook) + btv->audio_hook(btv,&va,0); + } + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + bt848_bright(btv,c->value); + break; + case V4L2_CID_HUE: + bt848_hue(btv,c->value); + break; + case V4L2_CID_CONTRAST: + bt848_contrast(btv,c->value); + break; + case V4L2_CID_SATURATION: + bt848_sat(btv,c->value); + break; + case V4L2_CID_AUDIO_MUTE: + if (c->value) { + va.flags |= VIDEO_AUDIO_MUTE; + audio_mux(btv, AUDIO_MUTE); + } else { + va.flags &= ~VIDEO_AUDIO_MUTE; + audio_mux(btv, AUDIO_UNMUTE); + } + break; + + case V4L2_CID_AUDIO_VOLUME: + va.volume = c->value; + break; + case V4L2_CID_AUDIO_BALANCE: + va.balance = c->value; + break; + case V4L2_CID_AUDIO_BASS: + va.bass = c->value; + break; + case V4L2_CID_AUDIO_TREBLE: + va.treble = c->value; + break; + + case V4L2_CID_PRIVATE_CHROMA_AGC: + btv->opt_chroma_agc = c->value; + val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0; + btwrite(val, BT848_E_SCLOOP); + btwrite(val, BT848_O_SCLOOP); + break; + case V4L2_CID_PRIVATE_COMBFILTER: + btv->opt_combfilter = c->value; + break; + case V4L2_CID_PRIVATE_LUMAFILTER: + btv->opt_lumafilter = c->value; + if (btv->opt_lumafilter) { + btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL); + btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL); + } else { + btor(BT848_CONTROL_LDEC, BT848_E_CONTROL); + btor(BT848_CONTROL_LDEC, BT848_O_CONTROL); + } + break; + case V4L2_CID_PRIVATE_AUTOMUTE: + btv->opt_automute = c->value; + break; + case V4L2_CID_PRIVATE_AGC_CRUSH: + btv->opt_adc_crush = c->value; + btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), + BT848_ADC); + break; + case V4L2_CID_PRIVATE_VCR_HACK: + btv->opt_vcr_hack = c->value; + break; + case V4L2_CID_PRIVATE_WHITECRUSH_UPPER: + btv->opt_whitecrush_upper = c->value; + btwrite(c->value, BT848_WC_UP); + break; + case V4L2_CID_PRIVATE_WHITECRUSH_LOWER: + btv->opt_whitecrush_lower = c->value; + btwrite(c->value, BT848_WC_DOWN); + break; + case V4L2_CID_PRIVATE_UV_RATIO: + btv->opt_uv_ratio = c->value; + bt848_sat(btv, btv->saturation); + break; + case V4L2_CID_PRIVATE_FULL_LUMA_RANGE: + btv->opt_full_luma_range = c->value; + btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM); + break; + case V4L2_CID_PRIVATE_CORING: + btv->opt_coring = c->value; + btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM); + break; + default: + return -EINVAL; + } + if (i >= 4 && i <= 8) { + bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va); + if (btv->audio_hook) + btv->audio_hook(btv,&va,1); + } + return 0; +} + +/* ----------------------------------------------------------------------- */ + +void bttv_gpio_tracking(struct bttv *btv, char *comment) +{ + unsigned int outbits, data; + outbits = btread(BT848_GPIO_OUT_EN); + data = btread(BT848_GPIO_DATA); + printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n", + btv->c.nr,outbits,data & outbits, data & ~outbits, comment); +} + +static void bttv_field_count(struct bttv *btv) +{ + int need_count = 0; + + if (btv->users) + need_count++; + + if (need_count) { + /* start field counter */ + btor(BT848_INT_VSYNC,BT848_INT_MASK); + } else { + /* stop field counter */ + btand(~BT848_INT_VSYNC,BT848_INT_MASK); + btv->field_count = 0; + } +} + +static const struct bttv_format* +format_by_palette(int palette) +{ + unsigned int i; + + for (i = 0; i < BTTV_FORMATS; i++) { + if (-1 == bttv_formats[i].palette) + continue; + if (bttv_formats[i].palette == palette) + return bttv_formats+i; + } + return NULL; +} + +static const struct bttv_format* +format_by_fourcc(int fourcc) +{ + unsigned int i; + + for (i = 0; i < BTTV_FORMATS; i++) { + if (-1 == bttv_formats[i].fourcc) + continue; + if (bttv_formats[i].fourcc == fourcc) + return bttv_formats+i; + } + return NULL; +} + +/* ----------------------------------------------------------------------- */ +/* misc helpers */ + +static int +bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, + struct bttv_buffer *new) +{ + struct bttv_buffer *old; + unsigned long flags; + int retval = 0; + + dprintk("switch_overlay: enter [new=%p]\n",new); + if (new) + new->vb.state = STATE_DONE; + spin_lock_irqsave(&btv->s_lock,flags); + old = btv->screen; + btv->screen = new; + btv->loop_irq |= 1; + bttv_set_dma(btv, 0x03); + spin_unlock_irqrestore(&btv->s_lock,flags); + if (NULL == new) + free_btres(btv,fh,RESOURCE_OVERLAY); + if (NULL != old) { + dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state); + bttv_dma_free(&fh->cap,btv, old); + kfree(old); + } + dprintk("switch_overlay: done\n"); + return retval; +} + +/* ----------------------------------------------------------------------- */ +/* video4linux (1) interface */ + +static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv, + struct bttv_buffer *buf, + const struct bttv_format *fmt, + unsigned int width, unsigned int height, + enum v4l2_field field) +{ + int redo_dma_risc = 0; + int rc; + + /* check settings */ + if (NULL == fmt) + return -EINVAL; + if (fmt->btformat == BT848_COLOR_FMT_RAW) { + width = RAW_BPL; + height = RAW_LINES*2; + if (width*height > buf->vb.bsize) + return -EINVAL; + buf->vb.size = buf->vb.bsize; + } else { + if (width < 48 || + height < 32 || + width > bttv_tvnorms[btv->tvnorm].swidth || + height > bttv_tvnorms[btv->tvnorm].sheight) + return -EINVAL; + buf->vb.size = (width * height * fmt->depth) >> 3; + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + } + + /* alloc + fill struct bttv_buffer (if changed) */ + if (buf->vb.width != width || buf->vb.height != height || + buf->vb.field != field || + buf->tvnorm != btv->tvnorm || buf->fmt != fmt) { + buf->vb.width = width; + buf->vb.height = height; + buf->vb.field = field; + buf->tvnorm = btv->tvnorm; + buf->fmt = fmt; + redo_dma_risc = 1; + } + + /* alloc risc memory */ + if (STATE_NEEDS_INIT == buf->vb.state) { + redo_dma_risc = 1; + if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf))) + goto fail; + } + + if (redo_dma_risc) + if (0 != (rc = bttv_buffer_risc(btv,buf))) + goto fail; + + buf->vb.state = STATE_PREPARED; + return 0; + + fail: + bttv_dma_free(q,btv,buf); + return rc; +} + +static int +buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) +{ + struct bttv_fh *fh = q->priv_data; + + *size = fh->fmt->depth*fh->width*fh->height >> 3; + if (0 == *count) + *count = gbuffers; + while (*size * *count > gbuffers * gbufsize) + (*count)--; + return 0; +} + +static int +buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + struct bttv_fh *fh = q->priv_data; + + return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt, + fh->width, fh->height, field); +} + +static void +buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) +{ + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + struct bttv_fh *fh = q->priv_data; + struct bttv *btv = fh->btv; + + buf->vb.state = STATE_QUEUED; + list_add_tail(&buf->vb.queue,&btv->capture); + if (!btv->curr.frame_irq) { + btv->loop_irq |= 1; + bttv_set_dma(btv, 0x03); + } +} + +static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) +{ + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + struct bttv_fh *fh = q->priv_data; + + bttv_dma_free(&fh->cap,fh->btv,buf); +} + +static struct videobuf_queue_ops bttv_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + +static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) +{ + switch (cmd) { + case BTTV_VERSION: + return BTTV_VERSION_CODE; + + /* *** v4l1 *** ************************************************ */ + case VIDIOCGFREQ: + { + unsigned long *freq = arg; + *freq = btv->freq; + return 0; + } + case VIDIOCSFREQ: + { + unsigned long *freq = arg; + mutex_lock(&btv->lock); + btv->freq=*freq; + bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq); + if (btv->has_matchbox && btv->radio_user) + tea5757_set_freq(btv,*freq); + mutex_unlock(&btv->lock); + return 0; + } + + case VIDIOCGTUNER: + { + struct video_tuner *v = arg; + + if (UNSET == bttv_tvcards[btv->c.type].tuner) + return -EINVAL; + if (v->tuner) /* Only tuner 0 */ + return -EINVAL; + strcpy(v->name, "Television"); + v->rangelow = 0; + v->rangehigh = 0x7FFFFFFF; + v->flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; + v->mode = btv->tvnorm; + v->signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0; + bttv_call_i2c_clients(btv,cmd,v); + return 0; + } + case VIDIOCSTUNER: + { + struct video_tuner *v = arg; + + if (v->tuner) /* Only tuner 0 */ + return -EINVAL; + if (v->mode >= BTTV_TVNORMS) + return -EINVAL; + + mutex_lock(&btv->lock); + set_tvnorm(btv,v->mode); + bttv_call_i2c_clients(btv,cmd,v); + mutex_unlock(&btv->lock); + return 0; + } + + case VIDIOCGCHAN: + { + struct video_channel *v = arg; + unsigned int channel = v->channel; + + if (channel >= bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; + v->tuners=0; + v->flags = VIDEO_VC_AUDIO; + v->type = VIDEO_TYPE_CAMERA; + v->norm = btv->tvnorm; + if (channel == bttv_tvcards[btv->c.type].tuner) { + strcpy(v->name,"Television"); + v->flags|=VIDEO_VC_TUNER; + v->type=VIDEO_TYPE_TV; + v->tuners=1; + } else if (channel == btv->svhs) { + strcpy(v->name,"S-Video"); + } else { + sprintf(v->name,"Composite%d",channel); + } + return 0; + } + case VIDIOCSCHAN: + { + struct video_channel *v = arg; + unsigned int channel = v->channel; + + if (channel >= bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; + if (v->norm >= BTTV_TVNORMS) + return -EINVAL; + + mutex_lock(&btv->lock); + if (channel == btv->input && + v->norm == btv->tvnorm) { + /* nothing to do */ + mutex_unlock(&btv->lock); + return 0; + } + + btv->tvnorm = v->norm; + set_input(btv,v->channel); + mutex_unlock(&btv->lock); + return 0; + } + + case VIDIOCGAUDIO: + { + struct video_audio *v = arg; + + memset(v,0,sizeof(*v)); + strcpy(v->name,"Television"); + v->flags |= VIDEO_AUDIO_MUTABLE; + v->mode = VIDEO_SOUND_MONO; + + mutex_lock(&btv->lock); + bttv_call_i2c_clients(btv,cmd,v); + + /* card specific hooks */ + if (btv->audio_hook) + btv->audio_hook(btv,v,0); + + mutex_unlock(&btv->lock); + return 0; + } + case VIDIOCSAUDIO: + { + struct video_audio *v = arg; + unsigned int audio = v->audio; + + if (audio >= bttv_tvcards[btv->c.type].audio_inputs) + return -EINVAL; + + mutex_lock(&btv->lock); + audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE); + bttv_call_i2c_clients(btv,cmd,v); + + /* card specific hooks */ + if (btv->audio_hook) + btv->audio_hook(btv,v,1); + + mutex_unlock(&btv->lock); + return 0; + } + + /* *** v4l2 *** ************************************************ */ + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *e = arg; + unsigned int index = e->index; + + if (index >= BTTV_TVNORMS) + return -EINVAL; + v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id, + bttv_tvnorms[e->index].name); + e->index = index; + return 0; + } + case VIDIOC_G_STD: + { + v4l2_std_id *id = arg; + *id = bttv_tvnorms[btv->tvnorm].v4l2_id; + return 0; + } + case VIDIOC_S_STD: + { + v4l2_std_id *id = arg; + unsigned int i; + + for (i = 0; i < BTTV_TVNORMS; i++) + if (*id & bttv_tvnorms[i].v4l2_id) + break; + if (i == BTTV_TVNORMS) + return -EINVAL; + + mutex_lock(&btv->lock); + set_tvnorm(btv,i); + i2c_vidiocschan(btv); + mutex_unlock(&btv->lock); + return 0; + } + case VIDIOC_QUERYSTD: + { + v4l2_std_id *id = arg; + + if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML) + *id = V4L2_STD_625_50; + else + *id = V4L2_STD_525_60; + return 0; + } + + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *i = arg; + unsigned int n; + + n = i->index; + if (n >= bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; + memset(i,0,sizeof(*i)); + i->index = n; + i->type = V4L2_INPUT_TYPE_CAMERA; + i->audioset = 0; + if (i->index == bttv_tvcards[btv->c.type].tuner) { + sprintf(i->name, "Television"); + i->type = V4L2_INPUT_TYPE_TUNER; + i->tuner = 0; + } else if (i->index == btv->svhs) { + sprintf(i->name, "S-Video"); + } else { + sprintf(i->name,"Composite%d",i->index); + } + if (i->index == btv->input) { + __u32 dstatus = btread(BT848_DSTATUS); + if (0 == (dstatus & BT848_DSTATUS_PRES)) + i->status |= V4L2_IN_ST_NO_SIGNAL; + if (0 == (dstatus & BT848_DSTATUS_HLOC)) + i->status |= V4L2_IN_ST_NO_H_LOCK; + } + for (n = 0; n < BTTV_TVNORMS; n++) + i->std |= bttv_tvnorms[n].v4l2_id; + return 0; + } + case VIDIOC_G_INPUT: + { + int *i = arg; + *i = btv->input; + return 0; + } + case VIDIOC_S_INPUT: + { + unsigned int *i = arg; + + if (*i > bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; + mutex_lock(&btv->lock); + set_input(btv,*i); + mutex_unlock(&btv->lock); + return 0; + } + + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *t = arg; + + if (UNSET == bttv_tvcards[btv->c.type].tuner) + return -EINVAL; + if (0 != t->index) + return -EINVAL; + mutex_lock(&btv->lock); + memset(t,0,sizeof(*t)); + strcpy(t->name, "Television"); + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM; + t->rxsubchans = V4L2_TUNER_SUB_MONO; + if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) + t->signal = 0xffff; + { + struct video_tuner tuner; + + memset(&tuner, 0, sizeof (tuner)); + tuner.rangehigh = 0xffffffffUL; + bttv_call_i2c_clients(btv, VIDIOCGTUNER, &tuner); + t->rangelow = tuner.rangelow; + t->rangehigh = tuner.rangehigh; + } + { + /* Hmmm ... */ + struct video_audio va; + memset(&va, 0, sizeof(struct video_audio)); + bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); + if (btv->audio_hook) + btv->audio_hook(btv,&va,0); + if(va.mode & VIDEO_SOUND_STEREO) { + t->audmode = V4L2_TUNER_MODE_STEREO; + t->rxsubchans |= V4L2_TUNER_SUB_STEREO; + } + if(va.mode & VIDEO_SOUND_LANG1) { + t->audmode = V4L2_TUNER_MODE_LANG1; + t->rxsubchans = V4L2_TUNER_SUB_LANG1 + | V4L2_TUNER_SUB_LANG2; + } + } + /* FIXME: fill capability+audmode */ + mutex_unlock(&btv->lock); + return 0; + } + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *t = arg; + + if (UNSET == bttv_tvcards[btv->c.type].tuner) + return -EINVAL; + if (0 != t->index) + return -EINVAL; + mutex_lock(&btv->lock); + { + struct video_audio va; + memset(&va, 0, sizeof(struct video_audio)); + bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); + if (t->audmode == V4L2_TUNER_MODE_MONO) + va.mode = VIDEO_SOUND_MONO; + else if (t->audmode == V4L2_TUNER_MODE_STEREO) + va.mode = VIDEO_SOUND_STEREO; + else if (t->audmode == V4L2_TUNER_MODE_LANG1) + va.mode = VIDEO_SOUND_LANG1; + else if (t->audmode == V4L2_TUNER_MODE_LANG2) + va.mode = VIDEO_SOUND_LANG2; + bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va); + if (btv->audio_hook) + btv->audio_hook(btv,&va,1); + } + mutex_unlock(&btv->lock); + return 0; + } + + case VIDIOC_G_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + memset(f,0,sizeof(*f)); + f->type = V4L2_TUNER_ANALOG_TV; + f->frequency = btv->freq; + return 0; + } + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + if (unlikely(f->tuner != 0)) + return -EINVAL; + if (unlikely (f->type != V4L2_TUNER_ANALOG_TV)) + return -EINVAL; + mutex_lock(&btv->lock); + btv->freq = f->frequency; + bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq); + if (btv->has_matchbox && btv->radio_user) + tea5757_set_freq(btv,btv->freq); + mutex_unlock(&btv->lock); + return 0; + } + case VIDIOC_LOG_STATUS: + { + bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL); + return 0; + } + + default: + return -ENOIOCTLCMD; + + } + return 0; +} + +static int verify_window(const struct bttv_tvnorm *tvn, + struct v4l2_window *win, int fixup) +{ + enum v4l2_field field; + int maxw, maxh; + + if (win->w.width < 48 || win->w.height < 32) + return -EINVAL; + if (win->clipcount > 2048) + return -EINVAL; + + field = win->field; + maxw = tvn->swidth; + maxh = tvn->sheight; + + if (V4L2_FIELD_ANY == field) { + field = (win->w.height > maxh/2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_TOP; + } + switch (field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + maxh = maxh / 2; + break; + case V4L2_FIELD_INTERLACED: + break; + default: + return -EINVAL; + } + + if (!fixup && (win->w.width > maxw || win->w.height > maxh)) + return -EINVAL; + + if (win->w.width > maxw) + win->w.width = maxw; + if (win->w.height > maxh) + win->w.height = maxh; + win->field = field; + return 0; +} + +static int setup_window(struct bttv_fh *fh, struct bttv *btv, + struct v4l2_window *win, int fixup) +{ + struct v4l2_clip *clips = NULL; + int n,size,retval = 0; + + if (NULL == fh->ovfmt) + return -EINVAL; + if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED)) + return -EINVAL; + retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup); + if (0 != retval) + return retval; + + /* copy clips -- luckily v4l1 + v4l2 are binary + compatible here ...*/ + n = win->clipcount; + size = sizeof(*clips)*(n+4); + clips = kmalloc(size,GFP_KERNEL); + if (NULL == clips) + return -ENOMEM; + if (n > 0) { + if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) { + kfree(clips); + return -EFAULT; + } + } + /* clip against screen */ + if (NULL != btv->fbuf.base) + n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height, + &win->w, clips, n); + btcx_sort_clips(clips,n); + + /* 4-byte alignments */ + switch (fh->ovfmt->depth) { + case 8: + case 24: + btcx_align(&win->w, clips, n, 3); + break; + case 16: + btcx_align(&win->w, clips, n, 1); + break; + case 32: + /* no alignment fixups needed */ + break; + default: + BUG(); + } + + mutex_lock(&fh->cap.lock); + kfree(fh->ov.clips); + fh->ov.clips = clips; + fh->ov.nclips = n; + + fh->ov.w = win->w; + fh->ov.field = win->field; + fh->ov.setup_ok = 1; + btv->init.ov.w.width = win->w.width; + btv->init.ov.w.height = win->w.height; + btv->init.ov.field = win->field; + + /* update overlay if needed */ + retval = 0; + if (check_btres(fh, RESOURCE_OVERLAY)) { + struct bttv_buffer *new; + + new = videobuf_alloc(sizeof(*new)); + bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); + retval = bttv_switch_overlay(btv,fh,new); + } + mutex_unlock(&fh->cap.lock); + return retval; +} + +/* ----------------------------------------------------------------------- */ + +static struct videobuf_queue* bttv_queue(struct bttv_fh *fh) +{ + struct videobuf_queue* q = NULL; + + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + q = &fh->cap; + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + q = &fh->vbi; + break; + default: + BUG(); + } + return q; +} + +static int bttv_resource(struct bttv_fh *fh) +{ + int res = 0; + + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + res = RESOURCE_VIDEO; + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + res = RESOURCE_VBI; + break; + default: + BUG(); + } + return res; +} + +static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type) +{ + struct videobuf_queue *q = bttv_queue(fh); + int res = bttv_resource(fh); + + if (check_btres(fh,res)) + return -EBUSY; + if (videobuf_queue_is_busy(q)) + return -EBUSY; + fh->type = type; + return 0; +} + +static void +pix_format_set_size (struct v4l2_pix_format * f, + const struct bttv_format * fmt, + unsigned int width, + unsigned int height) +{ + f->width = width; + f->height = height; + + if (fmt->flags & FORMAT_FLAGS_PLANAR) { + f->bytesperline = width; /* Y plane */ + f->sizeimage = (width * height * fmt->depth) >> 3; + } else { + f->bytesperline = (width * fmt->depth) >> 3; + f->sizeimage = height * f->bytesperline; + } +} + +static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f) +{ + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + memset(&f->fmt.pix,0,sizeof(struct v4l2_pix_format)); + pix_format_set_size (&f->fmt.pix, fh->fmt, + fh->width, fh->height); + f->fmt.pix.field = fh->cap.field; + f->fmt.pix.pixelformat = fh->fmt->fourcc; + return 0; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + memset(&f->fmt.win,0,sizeof(struct v4l2_window)); + f->fmt.win.w = fh->ov.w; + f->fmt.win.field = fh->ov.field; + return 0; + case V4L2_BUF_TYPE_VBI_CAPTURE: + bttv_vbi_get_fmt(fh,f); + return 0; + default: + return -EINVAL; + } +} + +static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv, + struct v4l2_format *f) +{ + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + { + const struct bttv_format *fmt; + enum v4l2_field field; + unsigned int maxw,maxh; + + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (NULL == fmt) + return -EINVAL; + + /* fixup format */ + maxw = bttv_tvnorms[btv->tvnorm].swidth; + maxh = bttv_tvnorms[btv->tvnorm].sheight; + field = f->fmt.pix.field; + if (V4L2_FIELD_ANY == field) + field = (f->fmt.pix.height > maxh/2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_BOTTOM; + if (V4L2_FIELD_SEQ_BT == field) + field = V4L2_FIELD_SEQ_TB; + switch (field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + case V4L2_FIELD_ALTERNATE: + maxh = maxh/2; + break; + case V4L2_FIELD_INTERLACED: + break; + case V4L2_FIELD_SEQ_TB: + if (fmt->flags & FORMAT_FLAGS_PLANAR) + return -EINVAL; + break; + default: + return -EINVAL; + } + + /* update data for the application */ + f->fmt.pix.field = field; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.height < 32) + f->fmt.pix.height = 32; + if (f->fmt.pix.width > maxw) + f->fmt.pix.width = maxw; + if (f->fmt.pix.height > maxh) + f->fmt.pix.height = maxh; + pix_format_set_size (&f->fmt.pix, fmt, + f->fmt.pix.width & ~3, + f->fmt.pix.height); + + return 0; + } + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + return verify_window(&bttv_tvnorms[btv->tvnorm], + &f->fmt.win, 1); + case V4L2_BUF_TYPE_VBI_CAPTURE: + bttv_vbi_try_fmt(fh,f); + return 0; + default: + return -EINVAL; + } +} + +static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, + struct v4l2_format *f) +{ + int retval; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + { + const struct bttv_format *fmt; + + retval = bttv_switch_type(fh,f->type); + if (0 != retval) + return retval; + retval = bttv_try_fmt(fh,btv,f); + if (0 != retval) + return retval; + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + + /* update our state informations */ + mutex_lock(&fh->cap.lock); + fh->fmt = fmt; + fh->cap.field = f->fmt.pix.field; + fh->cap.last = V4L2_FIELD_NONE; + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + btv->init.fmt = fmt; + btv->init.width = f->fmt.pix.width; + btv->init.height = f->fmt.pix.height; + mutex_unlock(&fh->cap.lock); + + return 0; + } + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (no_overlay > 0) { + printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; + } + return setup_window(fh, btv, &f->fmt.win, 1); + case V4L2_BUF_TYPE_VBI_CAPTURE: + retval = bttv_switch_type(fh,f->type); + if (0 != retval) + return retval; + if (locked_btres(fh->btv, RESOURCE_VBI)) + return -EBUSY; + bttv_vbi_try_fmt(fh,f); + bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]); + bttv_vbi_get_fmt(fh,f); + return 0; + default: + return -EINVAL; + } +} + +static int bttv_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct bttv_fh *fh = file->private_data; + struct bttv *btv = fh->btv; + unsigned long flags; + int retval = 0; + + if (bttv_debug > 1) + v4l_print_ioctl(btv->c.name, cmd); + + if (btv->errors) + bttv_reinit_bt848(btv); + + switch (cmd) { + case VIDIOCSFREQ: + case VIDIOCSTUNER: + case VIDIOCSCHAN: + case VIDIOC_S_CTRL: + case VIDIOC_S_STD: + case VIDIOC_S_INPUT: + case VIDIOC_S_TUNER: + case VIDIOC_S_FREQUENCY: + retval = v4l2_prio_check(&btv->prio,&fh->prio); + if (0 != retval) + return retval; + }; + + switch (cmd) { + + /* *** v4l1 *** ************************************************ */ + case VIDIOCGCAP: + { + struct video_capability *cap = arg; + + memset(cap,0,sizeof(*cap)); + strcpy(cap->name,btv->video_dev->name); + if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { + /* vbi */ + cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT; + } else { + /* others */ + cap->type = VID_TYPE_CAPTURE| + VID_TYPE_TUNER| + VID_TYPE_CLIPPING| + VID_TYPE_SCALES; + if (no_overlay <= 0) + cap->type |= VID_TYPE_OVERLAY; + + cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth; + cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight; + cap->minwidth = 48; + cap->minheight = 32; + } + cap->channels = bttv_tvcards[btv->c.type].video_inputs; + cap->audios = bttv_tvcards[btv->c.type].audio_inputs; + return 0; + } + + case VIDIOCGPICT: + { + struct video_picture *pic = arg; + + memset(pic,0,sizeof(*pic)); + pic->brightness = btv->bright; + pic->contrast = btv->contrast; + pic->hue = btv->hue; + pic->colour = btv->saturation; + if (fh->fmt) { + pic->depth = fh->fmt->depth; + pic->palette = fh->fmt->palette; + } + return 0; + } + case VIDIOCSPICT: + { + struct video_picture *pic = arg; + const struct bttv_format *fmt; + + fmt = format_by_palette(pic->palette); + if (NULL == fmt) + return -EINVAL; + mutex_lock(&fh->cap.lock); + if (fmt->depth != pic->depth) { + retval = -EINVAL; + goto fh_unlock_and_return; + } + if (fmt->flags & FORMAT_FLAGS_RAW) { + /* VIDIOCMCAPTURE uses gbufsize, not RAW_BPL * + RAW_LINES * 2. F1 is stored at offset 0, F2 + at buffer size / 2. */ + fh->width = RAW_BPL; + fh->height = gbufsize / RAW_BPL; + btv->init.width = RAW_BPL; + btv->init.height = gbufsize / RAW_BPL; + } + fh->ovfmt = fmt; + fh->fmt = fmt; + btv->init.ovfmt = fmt; + btv->init.fmt = fmt; + if (bigendian) { + /* dirty hack time: swap bytes for overlay if the + display adaptor is big endian (insmod option) */ + if (fmt->palette == VIDEO_PALETTE_RGB555 || + fmt->palette == VIDEO_PALETTE_RGB565 || + fmt->palette == VIDEO_PALETTE_RGB32) { + fh->ovfmt = fmt+1; + } + } + bt848_bright(btv,pic->brightness); + bt848_contrast(btv,pic->contrast); + bt848_hue(btv,pic->hue); + bt848_sat(btv,pic->colour); + mutex_unlock(&fh->cap.lock); + return 0; + } + + case VIDIOCGWIN: + { + struct video_window *win = arg; + + memset(win,0,sizeof(*win)); + win->x = fh->ov.w.left; + win->y = fh->ov.w.top; + win->width = fh->ov.w.width; + win->height = fh->ov.w.height; + return 0; + } + case VIDIOCSWIN: + { + struct video_window *win = arg; + struct v4l2_window w2; + + if (no_overlay > 0) { + printk ("VIDIOCSWIN: no_overlay\n"); + return -EINVAL; + } + + w2.field = V4L2_FIELD_ANY; + w2.w.left = win->x; + w2.w.top = win->y; + w2.w.width = win->width; + w2.w.height = win->height; + w2.clipcount = win->clipcount; + w2.clips = (struct v4l2_clip __user *)win->clips; + retval = setup_window(fh, btv, &w2, 0); + if (0 == retval) { + /* on v4l1 this ioctl affects the read() size too */ + fh->width = fh->ov.w.width; + fh->height = fh->ov.w.height; + btv->init.width = fh->ov.w.width; + btv->init.height = fh->ov.w.height; + } + return retval; + } + + case VIDIOCGFBUF: + { + struct video_buffer *fbuf = arg; + + fbuf->base = btv->fbuf.base; + fbuf->width = btv->fbuf.fmt.width; + fbuf->height = btv->fbuf.fmt.height; + fbuf->bytesperline = btv->fbuf.fmt.bytesperline; + if (fh->ovfmt) + fbuf->depth = fh->ovfmt->depth; + return 0; + } + case VIDIOCSFBUF: + { + struct video_buffer *fbuf = arg; + const struct bttv_format *fmt; + unsigned long end; + + if(!capable(CAP_SYS_ADMIN) && + !capable(CAP_SYS_RAWIO)) + return -EPERM; + end = (unsigned long)fbuf->base + + fbuf->height * fbuf->bytesperline; + mutex_lock(&fh->cap.lock); + retval = -EINVAL; + + switch (fbuf->depth) { + case 8: + fmt = format_by_palette(VIDEO_PALETTE_HI240); + break; + case 16: + fmt = format_by_palette(VIDEO_PALETTE_RGB565); + break; + case 24: + fmt = format_by_palette(VIDEO_PALETTE_RGB24); + break; + case 32: + fmt = format_by_palette(VIDEO_PALETTE_RGB32); + break; + case 15: + fbuf->depth = 16; + fmt = format_by_palette(VIDEO_PALETTE_RGB555); + break; + default: + fmt = NULL; + break; + } + if (NULL == fmt) + goto fh_unlock_and_return; + + fh->ovfmt = fmt; + fh->fmt = fmt; + btv->init.ovfmt = fmt; + btv->init.fmt = fmt; + btv->fbuf.base = fbuf->base; + btv->fbuf.fmt.width = fbuf->width; + btv->fbuf.fmt.height = fbuf->height; + if (fbuf->bytesperline) + btv->fbuf.fmt.bytesperline = fbuf->bytesperline; + else + btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fbuf->depth/8; + mutex_unlock(&fh->cap.lock); + return 0; + } + + case VIDIOCCAPTURE: + case VIDIOC_OVERLAY: + { + struct bttv_buffer *new; + int *on = arg; + + if (*on) { + /* verify args */ + if (NULL == btv->fbuf.base) + return -EINVAL; + if (!fh->ov.setup_ok) { + dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr); + return -EINVAL; + } + } + + if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY)) + return -EBUSY; + + mutex_lock(&fh->cap.lock); + if (*on) { + fh->ov.tvnorm = btv->tvnorm; + new = videobuf_alloc(sizeof(*new)); + bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); + } else { + new = NULL; + } + + /* switch over */ + retval = bttv_switch_overlay(btv,fh,new); + mutex_unlock(&fh->cap.lock); + return retval; + } + + case VIDIOCGMBUF: + { + struct video_mbuf *mbuf = arg; + unsigned int i; + + mutex_lock(&fh->cap.lock); + retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize, + V4L2_MEMORY_MMAP); + if (retval < 0) + goto fh_unlock_and_return; + memset(mbuf,0,sizeof(*mbuf)); + mbuf->frames = gbuffers; + mbuf->size = gbuffers * gbufsize; + for (i = 0; i < gbuffers; i++) + mbuf->offsets[i] = i * gbufsize; + mutex_unlock(&fh->cap.lock); + return 0; + } + case VIDIOCMCAPTURE: + { + struct video_mmap *vm = arg; + struct bttv_buffer *buf; + enum v4l2_field field; + + if (vm->frame >= VIDEO_MAX_FRAME) + return -EINVAL; + + mutex_lock(&fh->cap.lock); + retval = -EINVAL; + buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame]; + if (NULL == buf) + goto fh_unlock_and_return; + if (0 == buf->vb.baddr) + goto fh_unlock_and_return; + if (buf->vb.state == STATE_QUEUED || + buf->vb.state == STATE_ACTIVE) + goto fh_unlock_and_return; + + field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_BOTTOM; + retval = bttv_prepare_buffer(&fh->cap,btv,buf, + format_by_palette(vm->format), + vm->width,vm->height,field); + if (0 != retval) + goto fh_unlock_and_return; + spin_lock_irqsave(&btv->s_lock,flags); + buffer_queue(&fh->cap,&buf->vb); + spin_unlock_irqrestore(&btv->s_lock,flags); + mutex_unlock(&fh->cap.lock); + return 0; + } + case VIDIOCSYNC: + { + int *frame = arg; + struct bttv_buffer *buf; + + if (*frame >= VIDEO_MAX_FRAME) + return -EINVAL; + + mutex_lock(&fh->cap.lock); + retval = -EINVAL; + buf = (struct bttv_buffer *)fh->cap.bufs[*frame]; + if (NULL == buf) + goto fh_unlock_and_return; + retval = videobuf_waiton(&buf->vb,0,1); + if (0 != retval) + goto fh_unlock_and_return; + switch (buf->vb.state) { + case STATE_ERROR: + retval = -EIO; + /* fall through */ + case STATE_DONE: + videobuf_dma_sync(&fh->cap,&buf->vb.dma); + bttv_dma_free(&fh->cap,btv,buf); + break; + default: + retval = -EINVAL; + break; + } + mutex_unlock(&fh->cap.lock); + return retval; + } + + case VIDIOCGVBIFMT: + { + struct vbi_format *fmt = (void *) arg; + struct v4l2_format fmt2; + + if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) { + retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); + if (0 != retval) + return retval; + } + bttv_vbi_get_fmt(fh, &fmt2); + + memset(fmt,0,sizeof(*fmt)); + fmt->sampling_rate = fmt2.fmt.vbi.sampling_rate; + fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line; + fmt->sample_format = VIDEO_PALETTE_RAW; + fmt->start[0] = fmt2.fmt.vbi.start[0]; + fmt->count[0] = fmt2.fmt.vbi.count[0]; + fmt->start[1] = fmt2.fmt.vbi.start[1]; + fmt->count[1] = fmt2.fmt.vbi.count[1]; + if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC) + fmt->flags |= VBI_UNSYNC; + if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED) + fmt->flags |= VBI_INTERLACED; + return 0; + } + case VIDIOCSVBIFMT: + { + struct vbi_format *fmt = (void *) arg; + struct v4l2_format fmt2; + + retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); + if (0 != retval) + return retval; + bttv_vbi_get_fmt(fh, &fmt2); + + if (fmt->sampling_rate != fmt2.fmt.vbi.sampling_rate || + fmt->samples_per_line != fmt2.fmt.vbi.samples_per_line || + fmt->sample_format != VIDEO_PALETTE_RAW || + fmt->start[0] != fmt2.fmt.vbi.start[0] || + fmt->start[1] != fmt2.fmt.vbi.start[1] || + fmt->count[0] != fmt->count[1] || + fmt->count[0] < 1 || + fmt->count[0] > 32 /* VBI_MAXLINES */) + return -EINVAL; + + bttv_vbi_setlines(fh,btv,fmt->count[0]); + return 0; + } + + case BTTV_VERSION: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGTUNER: + case VIDIOCSTUNER: + case VIDIOCGCHAN: + case VIDIOCSCHAN: + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return bttv_common_ioctls(btv,cmd,arg); + + /* *** v4l2 *** ************************************************ */ + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = arg; + + if (0 == v4l2) + return -EINVAL; + memset(cap, 0, sizeof (*cap)); + strlcpy(cap->driver, "bttv", sizeof (cap->driver)); + strlcpy(cap->card, btv->video_dev->name, sizeof (cap->card)); + snprintf(cap->bus_info, sizeof (cap->bus_info), + "PCI:%s", pci_name(btv->c.pci)); + cap->version = BTTV_VERSION_CODE; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_VBI_CAPTURE | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; + if (no_overlay <= 0) + cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; + + if (bttv_tvcards[btv->c.type].tuner != UNSET && + bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT) + cap->capabilities |= V4L2_CAP_TUNER; + return 0; + } + + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *f = arg; + enum v4l2_buf_type type; + unsigned int i; + int index; + + type = f->type; + if (V4L2_BUF_TYPE_VBI_CAPTURE == type) { + /* vbi */ + index = f->index; + if (0 != index) + return -EINVAL; + memset(f,0,sizeof(*f)); + f->index = index; + f->type = type; + f->pixelformat = V4L2_PIX_FMT_GREY; + strcpy(f->description,"vbi data"); + return 0; + } + + /* video capture + overlay */ + index = -1; + for (i = 0; i < BTTV_FORMATS; i++) { + if (bttv_formats[i].fourcc != -1) + index++; + if ((unsigned int)index == f->index) + break; + } + if (BTTV_FORMATS == i) + return -EINVAL; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (!(bttv_formats[i].flags & FORMAT_FLAGS_PACKED)) + return -EINVAL; + break; + default: + return -EINVAL; + } + memset(f,0,sizeof(*f)); + f->index = index; + f->type = type; + f->pixelformat = bttv_formats[i].fourcc; + strlcpy(f->description,bttv_formats[i].name,sizeof(f->description)); + return 0; + } + + case VIDIOC_TRY_FMT: + { + struct v4l2_format *f = arg; + return bttv_try_fmt(fh,btv,f); + } + case VIDIOC_G_FMT: + { + struct v4l2_format *f = arg; + return bttv_g_fmt(fh,f); + } + case VIDIOC_S_FMT: + { + struct v4l2_format *f = arg; + return bttv_s_fmt(fh,btv,f); + } + + case VIDIOC_G_FBUF: + { + struct v4l2_framebuffer *fb = arg; + + *fb = btv->fbuf; + fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; + if (fh->ovfmt) + fb->fmt.pixelformat = fh->ovfmt->fourcc; + return 0; + } + case VIDIOC_S_FBUF: + { + struct v4l2_framebuffer *fb = arg; + const struct bttv_format *fmt; + + if(!capable(CAP_SYS_ADMIN) && + !capable(CAP_SYS_RAWIO)) + return -EPERM; + + /* check args */ + fmt = format_by_fourcc(fb->fmt.pixelformat); + if (NULL == fmt) + return -EINVAL; + if (0 == (fmt->flags & FORMAT_FLAGS_PACKED)) + return -EINVAL; + + mutex_lock(&fh->cap.lock); + retval = -EINVAL; + if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { + if (fb->fmt.width > bttv_tvnorms[btv->tvnorm].swidth) + goto fh_unlock_and_return; + if (fb->fmt.height > bttv_tvnorms[btv->tvnorm].sheight) + goto fh_unlock_and_return; + } + + /* ok, accept it */ + btv->fbuf.base = fb->base; + btv->fbuf.fmt.width = fb->fmt.width; + btv->fbuf.fmt.height = fb->fmt.height; + if (0 != fb->fmt.bytesperline) + btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline; + else + btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8; + + retval = 0; + fh->ovfmt = fmt; + btv->init.ovfmt = fmt; + if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { + fh->ov.w.left = 0; + fh->ov.w.top = 0; + fh->ov.w.width = fb->fmt.width; + fh->ov.w.height = fb->fmt.height; + btv->init.ov.w.width = fb->fmt.width; + btv->init.ov.w.height = fb->fmt.height; + kfree(fh->ov.clips); + fh->ov.clips = NULL; + fh->ov.nclips = 0; + + if (check_btres(fh, RESOURCE_OVERLAY)) { + struct bttv_buffer *new; + + new = videobuf_alloc(sizeof(*new)); + bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new); + retval = bttv_switch_overlay(btv,fh,new); + } + } + mutex_unlock(&fh->cap.lock); + return retval; + } + + case VIDIOC_REQBUFS: + return videobuf_reqbufs(bttv_queue(fh),arg); + + case VIDIOC_QUERYBUF: + return videobuf_querybuf(bttv_queue(fh),arg); + + case VIDIOC_QBUF: + return videobuf_qbuf(bttv_queue(fh),arg); + + case VIDIOC_DQBUF: + return videobuf_dqbuf(bttv_queue(fh),arg, + file->f_flags & O_NONBLOCK); + + case VIDIOC_STREAMON: + { + int res = bttv_resource(fh); + + if (!check_alloc_btres(btv,fh,res)) + return -EBUSY; + return videobuf_streamon(bttv_queue(fh)); + } + case VIDIOC_STREAMOFF: + { + int res = bttv_resource(fh); + + retval = videobuf_streamoff(bttv_queue(fh)); + if (retval < 0) + return retval; + free_btres(btv,fh,res); + return 0; + } + + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *c = arg; + int i; + + if ((c->id < V4L2_CID_BASE || + c->id >= V4L2_CID_LASTP1) && + (c->id < V4L2_CID_PRIVATE_BASE || + c->id >= V4L2_CID_PRIVATE_LASTP1)) + return -EINVAL; + for (i = 0; i < BTTV_CTLS; i++) + if (bttv_ctls[i].id == c->id) + break; + if (i == BTTV_CTLS) { + *c = no_ctl; + return 0; + } + *c = bttv_ctls[i]; + if (i >= 4 && i <= 8) { + struct video_audio va; + memset(&va,0,sizeof(va)); + bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); + if (btv->audio_hook) + btv->audio_hook(btv,&va,0); + switch (bttv_ctls[i].id) { + case V4L2_CID_AUDIO_VOLUME: + if (!(va.flags & VIDEO_AUDIO_VOLUME)) + *c = no_ctl; + break; + case V4L2_CID_AUDIO_BALANCE: + if (!(va.flags & VIDEO_AUDIO_BALANCE)) + *c = no_ctl; + break; + case V4L2_CID_AUDIO_BASS: + if (!(va.flags & VIDEO_AUDIO_BASS)) + *c = no_ctl; + break; + case V4L2_CID_AUDIO_TREBLE: + if (!(va.flags & VIDEO_AUDIO_TREBLE)) + *c = no_ctl; + break; + } + } + return 0; + } + case VIDIOC_G_CTRL: + return get_control(btv,arg); + case VIDIOC_S_CTRL: + return set_control(btv,arg); + case VIDIOC_G_PARM: + { + struct v4l2_streamparm *parm = arg; + struct v4l2_standard s; + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + memset(parm,0,sizeof(*parm)); + v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id, + bttv_tvnorms[btv->tvnorm].name); + parm->parm.capture.timeperframe = s.frameperiod; + return 0; + } + + case VIDIOC_G_PRIORITY: + { + enum v4l2_priority *p = arg; + + *p = v4l2_prio_max(&btv->prio); + return 0; + } + case VIDIOC_S_PRIORITY: + { + enum v4l2_priority *prio = arg; + + return v4l2_prio_change(&btv->prio, &fh->prio, *prio); + } + + case VIDIOC_ENUMSTD: + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case VIDIOC_ENUMINPUT: + case VIDIOC_G_INPUT: + case VIDIOC_S_INPUT: + case VIDIOC_G_TUNER: + case VIDIOC_S_TUNER: + case VIDIOC_G_FREQUENCY: + case VIDIOC_S_FREQUENCY: + case VIDIOC_LOG_STATUS: + return bttv_common_ioctls(btv,cmd,arg); + + default: + return -ENOIOCTLCMD; + } + return 0; + + fh_unlock_and_return: + mutex_unlock(&fh->cap.lock); + return retval; +} + +static int bttv_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct bttv_fh *fh = file->private_data; + + switch (cmd) { + case BTTV_VBISIZE: + bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); + return fh->lines * 2 * 2048; + default: + return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl); + } +} + +static ssize_t bttv_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) +{ + struct bttv_fh *fh = file->private_data; + int retval = 0; + + if (fh->btv->errors) + bttv_reinit_bt848(fh->btv); + dprintk("bttv%d: read count=%d type=%s\n", + fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]); + + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (locked_btres(fh->btv,RESOURCE_VIDEO)) + return -EBUSY; + retval = videobuf_read_one(&fh->cap, data, count, ppos, + file->f_flags & O_NONBLOCK); + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI)) + return -EBUSY; + retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1, + file->f_flags & O_NONBLOCK); + break; + default: + BUG(); + } + return retval; +} + +static unsigned int bttv_poll(struct file *file, poll_table *wait) +{ + struct bttv_fh *fh = file->private_data; + struct bttv_buffer *buf; + enum v4l2_field field; + + if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { + if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI)) + return POLLERR; + return videobuf_poll_stream(file, &fh->vbi, wait); + } + + if (check_btres(fh,RESOURCE_VIDEO)) { + /* streaming capture */ + if (list_empty(&fh->cap.stream)) + return POLLERR; + buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream); + } else { + /* read() capture */ + mutex_lock(&fh->cap.lock); + if (NULL == fh->cap.read_buf) { + /* need to capture a new frame */ + if (locked_btres(fh->btv,RESOURCE_VIDEO)) { + mutex_unlock(&fh->cap.lock); + return POLLERR; + } + fh->cap.read_buf = videobuf_alloc(fh->cap.msize); + if (NULL == fh->cap.read_buf) { + mutex_unlock(&fh->cap.lock); + return POLLERR; + } + fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR; + field = videobuf_next_field(&fh->cap); + if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) { + kfree (fh->cap.read_buf); + fh->cap.read_buf = NULL; + mutex_unlock(&fh->cap.lock); + return POLLERR; + } + fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); + fh->cap.read_off = 0; + } + mutex_unlock(&fh->cap.lock); + buf = (struct bttv_buffer*)fh->cap.read_buf; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == STATE_DONE || + buf->vb.state == STATE_ERROR) + return POLLIN|POLLRDNORM; + return 0; +} + +static int bttv_open(struct inode *inode, struct file *file) +{ + int minor = iminor(inode); + struct bttv *btv = NULL; + struct bttv_fh *fh; + enum v4l2_buf_type type = 0; + unsigned int i; + + dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); + + for (i = 0; i < bttv_num; i++) { + if (bttvs[i].video_dev && + bttvs[i].video_dev->minor == minor) { + btv = &bttvs[i]; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + break; + } + if (bttvs[i].vbi_dev && + bttvs[i].vbi_dev->minor == minor) { + btv = &bttvs[i]; + type = V4L2_BUF_TYPE_VBI_CAPTURE; + break; + } + } + if (NULL == btv) + return -ENODEV; + + dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n", + btv->c.nr,v4l2_type_names[type]); + + /* allocate per filehandle data */ + fh = kmalloc(sizeof(*fh),GFP_KERNEL); + if (NULL == fh) + return -ENOMEM; + file->private_data = fh; + *fh = btv->init; + fh->type = type; + fh->ov.setup_ok = 0; + v4l2_prio_open(&btv->prio,&fh->prio); + + videobuf_queue_init(&fh->cap, &bttv_video_qops, + btv->c.pci, &btv->s_lock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct bttv_buffer), + fh); + videobuf_queue_init(&fh->vbi, &bttv_vbi_qops, + btv->c.pci, &btv->s_lock, + V4L2_BUF_TYPE_VBI_CAPTURE, + V4L2_FIELD_SEQ_TB, + sizeof(struct bttv_buffer), + fh); + i2c_vidiocschan(btv); + + btv->users++; + if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) + bttv_vbi_setlines(fh,btv,16); + bttv_field_count(btv); + return 0; +} + +static int bttv_release(struct inode *inode, struct file *file) +{ + struct bttv_fh *fh = file->private_data; + struct bttv *btv = fh->btv; + + /* turn off overlay */ + if (check_btres(fh, RESOURCE_OVERLAY)) + bttv_switch_overlay(btv,fh,NULL); + + /* stop video capture */ + if (check_btres(fh, RESOURCE_VIDEO)) { + videobuf_streamoff(&fh->cap); + free_btres(btv,fh,RESOURCE_VIDEO); + } + if (fh->cap.read_buf) { + buffer_release(&fh->cap,fh->cap.read_buf); + kfree(fh->cap.read_buf); + } + + /* stop vbi capture */ + if (check_btres(fh, RESOURCE_VBI)) { + if (fh->vbi.streaming) + videobuf_streamoff(&fh->vbi); + if (fh->vbi.reading) + videobuf_read_stop(&fh->vbi); + free_btres(btv,fh,RESOURCE_VBI); + } + + /* free stuff */ + videobuf_mmap_free(&fh->cap); + videobuf_mmap_free(&fh->vbi); + v4l2_prio_close(&btv->prio,&fh->prio); + file->private_data = NULL; + kfree(fh); + + btv->users--; + bttv_field_count(btv); + return 0; +} + +static int +bttv_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct bttv_fh *fh = file->private_data; + + dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n", + fh->btv->c.nr, v4l2_type_names[fh->type], + vma->vm_start, vma->vm_end - vma->vm_start); + return videobuf_mmap_mapper(bttv_queue(fh),vma); +} + +static struct file_operations bttv_fops = +{ + .owner = THIS_MODULE, + .open = bttv_open, + .release = bttv_release, + .ioctl = bttv_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .llseek = no_llseek, + .read = bttv_read, + .mmap = bttv_mmap, + .poll = bttv_poll, +}; + +static struct video_device bttv_video_template = +{ + .name = "UNSET", + .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| + VID_TYPE_CLIPPING|VID_TYPE_SCALES, + .hardware = VID_HARDWARE_BT848, + .fops = &bttv_fops, + .minor = -1, +}; + +static struct video_device bttv_vbi_template = +{ + .name = "bt848/878 vbi", + .type = VID_TYPE_TUNER|VID_TYPE_TELETEXT, + .hardware = VID_HARDWARE_BT848, + .fops = &bttv_fops, + .minor = -1, +}; + +/* ----------------------------------------------------------------------- */ +/* radio interface */ + +static int radio_open(struct inode *inode, struct file *file) +{ + int minor = iminor(inode); + struct bttv *btv = NULL; + unsigned int i; + + dprintk("bttv: open minor=%d\n",minor); + + for (i = 0; i < bttv_num; i++) { + if (bttvs[i].radio_dev->minor == minor) { + btv = &bttvs[i]; + break; + } + } + if (NULL == btv) + return -ENODEV; + + dprintk("bttv%d: open called (radio)\n",btv->c.nr); + mutex_lock(&btv->lock); + + btv->radio_user++; + + file->private_data = btv; + + bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type); + audio_mux(btv,AUDIO_RADIO); + + mutex_unlock(&btv->lock); + return 0; +} + +static int radio_release(struct inode *inode, struct file *file) +{ + struct bttv *btv = file->private_data; + struct rds_command cmd; + + btv->radio_user--; + + bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd); + + return 0; +} + +static int radio_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct bttv *btv = file->private_data; + + switch (cmd) { + case VIDIOCGCAP: + { + struct video_capability *cap = arg; + + memset(cap,0,sizeof(*cap)); + strcpy(cap->name,btv->radio_dev->name); + cap->type = VID_TYPE_TUNER; + cap->channels = 1; + cap->audios = 1; + return 0; + } + + case VIDIOCGTUNER: + { + struct video_tuner *v = arg; + + if(v->tuner) + return -EINVAL; + memset(v,0,sizeof(*v)); + strcpy(v->name, "Radio"); + bttv_call_i2c_clients(btv,cmd,v); + return 0; + } + case VIDIOCSTUNER: + /* nothing to do */ + return 0; + + case BTTV_VERSION: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + case VIDIOC_LOG_STATUS: + return bttv_common_ioctls(btv,cmd,arg); + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int radio_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, radio_do_ioctl); +} + +static ssize_t radio_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) +{ + struct bttv *btv = file->private_data; + struct rds_command cmd; + cmd.block_count = count/3; + cmd.buffer = data; + cmd.instance = file; + cmd.result = -ENODEV; + + bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd); + + return cmd.result; +} + +static unsigned int radio_poll(struct file *file, poll_table *wait) +{ + struct bttv *btv = file->private_data; + struct rds_command cmd; + cmd.instance = file; + cmd.event_list = wait; + cmd.result = -ENODEV; + bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd); + + return cmd.result; +} + +static struct file_operations radio_fops = +{ + .owner = THIS_MODULE, + .open = radio_open, + .read = radio_read, + .release = radio_release, + .ioctl = radio_ioctl, + .llseek = no_llseek, + .poll = radio_poll, +}; + +static struct video_device radio_template = +{ + .name = "bt848/878 radio", + .type = VID_TYPE_TUNER, + .hardware = VID_HARDWARE_BT848, + .fops = &radio_fops, + .minor = -1, +}; + +/* ----------------------------------------------------------------------- */ +/* some debug code */ + +static int bttv_risc_decode(u32 risc) +{ + static char *instr[16] = { + [ BT848_RISC_WRITE >> 28 ] = "write", + [ BT848_RISC_SKIP >> 28 ] = "skip", + [ BT848_RISC_WRITEC >> 28 ] = "writec", + [ BT848_RISC_JUMP >> 28 ] = "jump", + [ BT848_RISC_SYNC >> 28 ] = "sync", + [ BT848_RISC_WRITE123 >> 28 ] = "write123", + [ BT848_RISC_SKIP123 >> 28 ] = "skip123", + [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23", + }; + static int incr[16] = { + [ BT848_RISC_WRITE >> 28 ] = 2, + [ BT848_RISC_JUMP >> 28 ] = 2, + [ BT848_RISC_SYNC >> 28 ] = 2, + [ BT848_RISC_WRITE123 >> 28 ] = 5, + [ BT848_RISC_SKIP123 >> 28 ] = 2, + [ BT848_RISC_WRITE1S23 >> 28 ] = 3, + }; + static char *bits[] = { + "be0", "be1", "be2", "be3/resync", + "set0", "set1", "set2", "set3", + "clr0", "clr1", "clr2", "clr3", + "irq", "res", "eol", "sol", + }; + int i; + + printk("0x%08x [ %s", risc, + instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); + for (i = ARRAY_SIZE(bits)-1; i >= 0; i--) + if (risc & (1 << (i + 12))) + printk(" %s",bits[i]); + printk(" count=%d ]\n", risc & 0xfff); + return incr[risc >> 28] ? incr[risc >> 28] : 1; +} + +static void bttv_risc_disasm(struct bttv *btv, + struct btcx_riscmem *risc) +{ + unsigned int i,j,n; + + printk("%s: risc disasm: %p [dma=0x%08lx]\n", + btv->c.name, risc->cpu, (unsigned long)risc->dma); + for (i = 0; i < (risc->size >> 2); i += n) { + printk("%s: 0x%lx: ", btv->c.name, + (unsigned long)(risc->dma + (i<<2))); + n = bttv_risc_decode(risc->cpu[i]); + for (j = 1; j < n; j++) + printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n", + btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)), + risc->cpu[i+j], j); + if (0 == risc->cpu[i]) + break; + } +} + +static void bttv_print_riscaddr(struct bttv *btv) +{ + printk(" main: %08Lx\n", + (unsigned long long)btv->main.dma); + printk(" vbi : o=%08Lx e=%08Lx\n", + btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0, + btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0); + printk(" cap : o=%08Lx e=%08Lx\n", + btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, + btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); + printk(" scr : o=%08Lx e=%08Lx\n", + btv->screen ? (unsigned long long)btv->screen->top.dma : 0, + btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0); + bttv_risc_disasm(btv, &btv->main); +} + +/* ----------------------------------------------------------------------- */ +/* irq handler */ + +static char *irq_name[] = { + "FMTCHG", // format change detected (525 vs. 625) + "VSYNC", // vertical sync (new field) + "HSYNC", // horizontal sync + "OFLOW", // chroma/luma AGC overflow + "HLOCK", // horizontal lock changed + "VPRES", // video presence changed + "6", "7", + "I2CDONE", // hw irc operation finished + "GPINT", // gpio port triggered irq + "10", + "RISCI", // risc instruction triggered irq + "FBUS", // pixel data fifo dropped data (high pci bus latencies) + "FTRGT", // pixel data fifo overrun + "FDSR", // fifo data stream resyncronisation + "PPERR", // parity error (data transfer) + "RIPERR", // parity error (read risc instructions) + "PABORT", // pci abort + "OCERR", // risc instruction error + "SCERR", // syncronisation error +}; + +static void bttv_print_irqbits(u32 print, u32 mark) +{ + unsigned int i; + + printk("bits:"); + for (i = 0; i < ARRAY_SIZE(irq_name); i++) { + if (print & (1 << i)) + printk(" %s",irq_name[i]); + if (mark & (1 << i)) + printk("*"); + } +} + +static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc) +{ + printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n", + btv->c.nr, + (unsigned long)btv->main.dma, + (unsigned long)btv->main.cpu[RISC_SLOT_O_VBI+1], + (unsigned long)btv->main.cpu[RISC_SLOT_O_FIELD+1], + (unsigned long)rc); + + if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) { + printk("bttv%d: Oh, there (temporarely?) is no input signal. " + "Ok, then this is harmless, don't worry ;)\n", + btv->c.nr); + return; + } + printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n", + btv->c.nr); + printk("bttv%d: Lets try to catch the culpit red-handed ...\n", + btv->c.nr); + dump_stack(); +} + +static int +bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set) +{ + struct bttv_buffer *item; + + memset(set,0,sizeof(*set)); + + /* capture request ? */ + if (!list_empty(&btv->capture)) { + set->frame_irq = 1; + item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue); + if (V4L2_FIELD_HAS_TOP(item->vb.field)) + set->top = item; + if (V4L2_FIELD_HAS_BOTTOM(item->vb.field)) + set->bottom = item; + + /* capture request for other field ? */ + if (!V4L2_FIELD_HAS_BOTH(item->vb.field) && + (item->vb.queue.next != &btv->capture)) { + item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue); + if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) { + if (NULL == set->top && + V4L2_FIELD_TOP == item->vb.field) { + set->top = item; + } + if (NULL == set->bottom && + V4L2_FIELD_BOTTOM == item->vb.field) { + set->bottom = item; + } + if (NULL != set->top && NULL != set->bottom) + set->top_irq = 2; + } + } + } + + /* screen overlay ? */ + if (NULL != btv->screen) { + if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) { + if (NULL == set->top && NULL == set->bottom) { + set->top = btv->screen; + set->bottom = btv->screen; + } + } else { + if (V4L2_FIELD_TOP == btv->screen->vb.field && + NULL == set->top) { + set->top = btv->screen; + } + if (V4L2_FIELD_BOTTOM == btv->screen->vb.field && + NULL == set->bottom) { + set->bottom = btv->screen; + } + } + } + + dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n", + btv->c.nr,set->top, set->bottom, + btv->screen,set->frame_irq,set->top_irq); + return 0; +} + +static void +bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup, + struct bttv_buffer_set *curr, unsigned int state) +{ + struct timeval ts; + + do_gettimeofday(&ts); + + if (wakeup->top == wakeup->bottom) { + if (NULL != wakeup->top && curr->top != wakeup->top) { + if (irq_debug > 1) + printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top); + wakeup->top->vb.ts = ts; + wakeup->top->vb.field_count = btv->field_count; + wakeup->top->vb.state = state; + wake_up(&wakeup->top->vb.done); + } + } else { + if (NULL != wakeup->top && curr->top != wakeup->top) { + if (irq_debug > 1) + printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top); + wakeup->top->vb.ts = ts; + wakeup->top->vb.field_count = btv->field_count; + wakeup->top->vb.state = state; + wake_up(&wakeup->top->vb.done); + } + if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) { + if (irq_debug > 1) + printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom); + wakeup->bottom->vb.ts = ts; + wakeup->bottom->vb.field_count = btv->field_count; + wakeup->bottom->vb.state = state; + wake_up(&wakeup->bottom->vb.done); + } + } +} + +static void +bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup, + unsigned int state) +{ + struct timeval ts; + + if (NULL == wakeup) + return; + + do_gettimeofday(&ts); + wakeup->vb.ts = ts; + wakeup->vb.field_count = btv->field_count; + wakeup->vb.state = state; + wake_up(&wakeup->vb.done); +} + +static void bttv_irq_timeout(unsigned long data) +{ + struct bttv *btv = (struct bttv *)data; + struct bttv_buffer_set old,new; + struct bttv_buffer *ovbi; + struct bttv_buffer *item; + unsigned long flags; + + if (bttv_verbose) { + printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ", + btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total, + btread(BT848_RISC_COUNT)); + bttv_print_irqbits(btread(BT848_INT_STAT),0); + printk("\n"); + } + + spin_lock_irqsave(&btv->s_lock,flags); + + /* deactivate stuff */ + memset(&new,0,sizeof(new)); + old = btv->curr; + ovbi = btv->cvbi; + btv->curr = new; + btv->cvbi = NULL; + btv->loop_irq = 0; + bttv_buffer_activate_video(btv, &new); + bttv_buffer_activate_vbi(btv, NULL); + bttv_set_dma(btv, 0); + + /* wake up */ + bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR); + bttv_irq_wakeup_vbi(btv, ovbi, STATE_ERROR); + + /* cancel all outstanding capture / vbi requests */ + while (!list_empty(&btv->capture)) { + item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue); + list_del(&item->vb.queue); + item->vb.state = STATE_ERROR; + wake_up(&item->vb.done); + } + while (!list_empty(&btv->vcapture)) { + item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue); + list_del(&item->vb.queue); + item->vb.state = STATE_ERROR; + wake_up(&item->vb.done); + } + + btv->errors++; + spin_unlock_irqrestore(&btv->s_lock,flags); +} + +static void +bttv_irq_wakeup_top(struct bttv *btv) +{ + struct bttv_buffer *wakeup = btv->curr.top; + + if (NULL == wakeup) + return; + + spin_lock(&btv->s_lock); + btv->curr.top_irq = 0; + btv->curr.top = NULL; + bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); + + do_gettimeofday(&wakeup->vb.ts); + wakeup->vb.field_count = btv->field_count; + wakeup->vb.state = STATE_DONE; + wake_up(&wakeup->vb.done); + spin_unlock(&btv->s_lock); +} + +static inline int is_active(struct btcx_riscmem *risc, u32 rc) +{ + if (rc < risc->dma) + return 0; + if (rc > risc->dma + risc->size) + return 0; + return 1; +} + +static void +bttv_irq_switch_video(struct bttv *btv) +{ + struct bttv_buffer_set new; + struct bttv_buffer_set old; + dma_addr_t rc; + + spin_lock(&btv->s_lock); + + /* new buffer set */ + bttv_irq_next_video(btv, &new); + rc = btread(BT848_RISC_COUNT); + if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) || + (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) { + btv->framedrop++; + if (debug_latency) + bttv_irq_debug_low_latency(btv, rc); + spin_unlock(&btv->s_lock); + return; + } + + /* switch over */ + old = btv->curr; + btv->curr = new; + btv->loop_irq &= ~1; + bttv_buffer_activate_video(btv, &new); + bttv_set_dma(btv, 0); + + /* switch input */ + if (UNSET != btv->new_input) { + video_mux(btv,btv->new_input); + btv->new_input = UNSET; + } + + /* wake up finished buffers */ + bttv_irq_wakeup_video(btv, &old, &new, STATE_DONE); + spin_unlock(&btv->s_lock); +} + +static void +bttv_irq_switch_vbi(struct bttv *btv) +{ + struct bttv_buffer *new = NULL; + struct bttv_buffer *old; + u32 rc; + + spin_lock(&btv->s_lock); + + if (!list_empty(&btv->vcapture)) + new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue); + old = btv->cvbi; + + rc = btread(BT848_RISC_COUNT); + if (NULL != old && (is_active(&old->top, rc) || + is_active(&old->bottom, rc))) { + btv->framedrop++; + if (debug_latency) + bttv_irq_debug_low_latency(btv, rc); + spin_unlock(&btv->s_lock); + return; + } + + /* switch */ + btv->cvbi = new; + btv->loop_irq &= ~4; + bttv_buffer_activate_vbi(btv, new); + bttv_set_dma(btv, 0); + + bttv_irq_wakeup_vbi(btv, old, STATE_DONE); + spin_unlock(&btv->s_lock); +} + +static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) +{ + u32 stat,astat; + u32 dstat; + int count; + struct bttv *btv; + int handled = 0; + + btv=(struct bttv *)dev_id; + + if (btv->custom_irq) + handled = btv->custom_irq(btv); + + count=0; + while (1) { + /* get/clear interrupt status bits */ + stat=btread(BT848_INT_STAT); + astat=stat&btread(BT848_INT_MASK); + if (!astat) + break; + handled = 1; + btwrite(stat,BT848_INT_STAT); + + /* get device status bits */ + dstat=btread(BT848_DSTATUS); + + if (irq_debug) { + printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d " + "riscs=%x, riscc=%08x, ", + btv->c.nr, count, btv->field_count, + stat>>28, btread(BT848_RISC_COUNT)); + bttv_print_irqbits(stat,astat); + if (stat & BT848_INT_HLOCK) + printk(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC) + ? "yes" : "no"); + if (stat & BT848_INT_VPRES) + printk(" PRES => %s", (dstat & BT848_DSTATUS_PRES) + ? "yes" : "no"); + if (stat & BT848_INT_FMTCHG) + printk(" NUML => %s", (dstat & BT848_DSTATUS_NUML) + ? "625" : "525"); + printk("\n"); + } + + if (astat&BT848_INT_VSYNC) + btv->field_count++; + + if ((astat & BT848_INT_GPINT) && btv->remote) { + wake_up(&btv->gpioq); + bttv_input_irq(btv); + } + + if (astat & BT848_INT_I2CDONE) { + btv->i2c_done = stat; + wake_up(&btv->i2c_queue); + } + + if ((astat & BT848_INT_RISCI) && (stat & (4<<28))) + bttv_irq_switch_vbi(btv); + + if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) + bttv_irq_wakeup_top(btv); + + if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) + bttv_irq_switch_video(btv); + + if ((astat & BT848_INT_HLOCK) && btv->opt_automute) + audio_mux(btv, -1); + + if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) { + printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr, + (astat & BT848_INT_SCERR) ? "SCERR" : "", + (astat & BT848_INT_OCERR) ? "OCERR" : "", + btread(BT848_RISC_COUNT)); + bttv_print_irqbits(stat,astat); + printk("\n"); + if (bttv_debug) + bttv_print_riscaddr(btv); + } + if (fdsr && astat & BT848_INT_FDSR) { + printk(KERN_INFO "bttv%d: FDSR @ %08x\n", + btv->c.nr,btread(BT848_RISC_COUNT)); + if (bttv_debug) + bttv_print_riscaddr(btv); + } + + count++; + if (count > 4) { + + if (count > 8 || !(astat & BT848_INT_GPINT)) { + btwrite(0, BT848_INT_MASK); + + printk(KERN_ERR + "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr); + } else { + printk(KERN_ERR + "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr); + + btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT), + BT848_INT_MASK); + }; + + bttv_print_irqbits(stat,astat); + + printk("]\n"); + } + } + btv->irq_total++; + if (handled) + btv->irq_me++; + return IRQ_RETVAL(handled); +} + + +/* ----------------------------------------------------------------------- */ +/* initialitation */ + +static struct video_device *vdev_init(struct bttv *btv, + struct video_device *template, + char *type) +{ + struct video_device *vfd; + + vfd = video_device_alloc(); + if (NULL == vfd) + return NULL; + *vfd = *template; + vfd->minor = -1; + vfd->dev = &btv->c.pci->dev; + vfd->release = video_device_release; + snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)", + btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", + type, bttv_tvcards[btv->c.type].name); + return vfd; +} + +static void bttv_unregister_video(struct bttv *btv) +{ + if (btv->video_dev) { + if (-1 != btv->video_dev->minor) + video_unregister_device(btv->video_dev); + else + video_device_release(btv->video_dev); + btv->video_dev = NULL; + } + if (btv->vbi_dev) { + if (-1 != btv->vbi_dev->minor) + video_unregister_device(btv->vbi_dev); + else + video_device_release(btv->vbi_dev); + btv->vbi_dev = NULL; + } + if (btv->radio_dev) { + if (-1 != btv->radio_dev->minor) + video_unregister_device(btv->radio_dev); + else + video_device_release(btv->radio_dev); + btv->radio_dev = NULL; + } +} + +/* register video4linux devices */ +static int __devinit bttv_register_video(struct bttv *btv) +{ + if (no_overlay <= 0) { + bttv_video_template.type |= VID_TYPE_OVERLAY; + } else { + printk("bttv: Overlay support disabled.\n"); + } + + /* video */ + btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); + if (NULL == btv->video_dev) + goto err; + if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) + goto err; + printk(KERN_INFO "bttv%d: registered device video%d\n", + btv->c.nr,btv->video_dev->minor & 0x1f); + video_device_create_file(btv->video_dev, &class_device_attr_card); + + /* vbi */ + btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); + if (NULL == btv->vbi_dev) + goto err; + if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) + goto err; + printk(KERN_INFO "bttv%d: registered device vbi%d\n", + btv->c.nr,btv->vbi_dev->minor & 0x1f); + + if (!btv->has_radio) + return 0; + /* radio */ + btv->radio_dev = vdev_init(btv, &radio_template, "radio"); + if (NULL == btv->radio_dev) + goto err; + if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) + goto err; + printk(KERN_INFO "bttv%d: registered device radio%d\n", + btv->c.nr,btv->radio_dev->minor & 0x1f); + + /* all done */ + return 0; + + err: + bttv_unregister_video(btv); + return -1; +} + + +/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */ +/* response on cards with no firmware is not enabled by OF */ +static void pci_set_command(struct pci_dev *dev) +{ +#if defined(__powerpc__) + unsigned int cmd; + + pci_read_config_dword(dev, PCI_COMMAND, &cmd); + cmd = (cmd | PCI_COMMAND_MEMORY ); + pci_write_config_dword(dev, PCI_COMMAND, cmd); +#endif +} + +static int __devinit bttv_probe(struct pci_dev *dev, + const struct pci_device_id *pci_id) +{ + int result; + unsigned char lat; + struct bttv *btv; + + if (bttv_num == BTTV_MAX) + return -ENOMEM; + printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); + btv=&bttvs[bttv_num]; + memset(btv,0,sizeof(*btv)); + btv->c.nr = bttv_num; + sprintf(btv->c.name,"bttv%d",btv->c.nr); + + /* initialize structs / fill in defaults */ + mutex_init(&btv->lock); + mutex_init(&btv->reslock); + spin_lock_init(&btv->s_lock); + spin_lock_init(&btv->gpio_lock); + init_waitqueue_head(&btv->gpioq); + init_waitqueue_head(&btv->i2c_queue); + INIT_LIST_HEAD(&btv->c.subs); + INIT_LIST_HEAD(&btv->capture); + INIT_LIST_HEAD(&btv->vcapture); + v4l2_prio_init(&btv->prio); + + init_timer(&btv->timeout); + btv->timeout.function = bttv_irq_timeout; + btv->timeout.data = (unsigned long)btv; + + btv->i2c_rc = -1; + btv->tuner_type = UNSET; + btv->new_input = UNSET; + btv->has_radio=radio[btv->c.nr]; + + /* pci stuff (init, get irq/mmio, ... */ + btv->c.pci = dev; + btv->id = dev->device; + if (pci_enable_device(dev)) { + printk(KERN_WARNING "bttv%d: Can't enable device.\n", + btv->c.nr); + return -EIO; + } + if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { + printk(KERN_WARNING "bttv%d: No suitable DMA available.\n", + btv->c.nr); + return -EIO; + } + if (!request_mem_region(pci_resource_start(dev,0), + pci_resource_len(dev,0), + btv->c.name)) { + printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n", + btv->c.nr, pci_resource_start(dev,0)); + return -EBUSY; + } + pci_set_master(dev); + pci_set_command(dev); + pci_set_drvdata(dev,btv); + + pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", + bttv_num,btv->id, btv->revision, pci_name(dev)); + printk("irq: %d, latency: %d, mmio: 0x%lx\n", + btv->c.pci->irq, lat, pci_resource_start(dev,0)); + schedule(); + + btv->bt848_mmio=ioremap(pci_resource_start(dev,0), 0x1000); + if (NULL == ioremap(pci_resource_start(dev,0), 0x1000)) { + printk("bttv%d: ioremap() failed\n", btv->c.nr); + result = -EIO; + goto fail1; + } + + /* identify card */ + bttv_idcard(btv); + + /* disable irqs, register irq handler */ + btwrite(0, BT848_INT_MASK); + result = request_irq(btv->c.pci->irq, bttv_irq, + SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv); + if (result < 0) { + printk(KERN_ERR "bttv%d: can't get IRQ %d\n", + bttv_num,btv->c.pci->irq); + goto fail1; + } + + if (0 != bttv_handle_chipset(btv)) { + result = -EIO; + goto fail2; + } + + /* init options from insmod args */ + btv->opt_combfilter = combfilter; + btv->opt_lumafilter = lumafilter; + btv->opt_automute = automute; + btv->opt_chroma_agc = chroma_agc; + btv->opt_adc_crush = adc_crush; + btv->opt_vcr_hack = vcr_hack; + btv->opt_whitecrush_upper = whitecrush_upper; + btv->opt_whitecrush_lower = whitecrush_lower; + btv->opt_uv_ratio = uv_ratio; + btv->opt_full_luma_range = full_luma_range; + btv->opt_coring = coring; + + /* fill struct bttv with some useful defaults */ + btv->init.btv = btv; + btv->init.ov.w.width = 320; + btv->init.ov.w.height = 240; + btv->init.fmt = format_by_palette(VIDEO_PALETTE_RGB24); + btv->init.width = 320; + btv->init.height = 240; + btv->init.lines = 16; + btv->input = 0; + + /* initialize hardware */ + if (bttv_gpio) + bttv_gpio_tracking(btv,"pre-init"); + + bttv_risc_init_main(btv); + init_bt848(btv); + + /* gpio */ + btwrite(0x00, BT848_GPIO_REG_INP); + btwrite(0x00, BT848_GPIO_OUT_EN); + if (bttv_verbose) + bttv_gpio_tracking(btv,"init"); + + /* needs to be done before i2c is registered */ + bttv_init_card1(btv); + + /* register i2c + gpio */ + init_bttv_i2c(btv); + + /* some card-specific stuff (needs working i2c) */ + bttv_init_card2(btv); + init_irqreg(btv); + + /* register video4linux + input */ + if (!bttv_tvcards[btv->c.type].no_video) { + bttv_register_video(btv); + bt848_bright(btv,32768); + bt848_contrast(btv,32768); + bt848_hue(btv,32768); + bt848_sat(btv,32768); + audio_mux(btv,AUDIO_MUTE); + set_input(btv,0); + } + + /* add subdevices */ + if (bttv_tvcards[btv->c.type].has_dvb) + bttv_sub_add_device(&btv->c, "dvb"); + + bttv_input_init(btv); + + /* everything is fine */ + bttv_num++; + return 0; + + fail2: + free_irq(btv->c.pci->irq,btv); + + fail1: + if (btv->bt848_mmio) + iounmap(btv->bt848_mmio); + release_mem_region(pci_resource_start(btv->c.pci,0), + pci_resource_len(btv->c.pci,0)); + pci_set_drvdata(dev,NULL); + return result; +} + +static void __devexit bttv_remove(struct pci_dev *pci_dev) +{ + struct bttv *btv = pci_get_drvdata(pci_dev); + + if (bttv_verbose) + printk("bttv%d: unloading\n",btv->c.nr); + + /* shutdown everything (DMA+IRQs) */ + btand(~15, BT848_GPIO_DMA_CTL); + btwrite(0, BT848_INT_MASK); + btwrite(~0x0, BT848_INT_STAT); + btwrite(0x0, BT848_GPIO_OUT_EN); + if (bttv_gpio) + bttv_gpio_tracking(btv,"cleanup"); + + /* tell gpio modules we are leaving ... */ + btv->shutdown=1; + wake_up(&btv->gpioq); + bttv_input_fini(btv); + bttv_sub_del_devices(&btv->c); + + /* unregister i2c_bus + input */ + fini_bttv_i2c(btv); + + /* unregister video4linux */ + bttv_unregister_video(btv); + + /* free allocated memory */ + btcx_riscmem_free(btv->c.pci,&btv->main); + + /* free ressources */ + free_irq(btv->c.pci->irq,btv); + iounmap(btv->bt848_mmio); + release_mem_region(pci_resource_start(btv->c.pci,0), + pci_resource_len(btv->c.pci,0)); + + pci_set_drvdata(pci_dev, NULL); + return; +} + +static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) +{ + struct bttv *btv = pci_get_drvdata(pci_dev); + struct bttv_buffer_set idle; + unsigned long flags; + + dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event); + + /* stop dma + irqs */ + spin_lock_irqsave(&btv->s_lock,flags); + memset(&idle, 0, sizeof(idle)); + btv->state.video = btv->curr; + btv->state.vbi = btv->cvbi; + btv->state.loop_irq = btv->loop_irq; + btv->curr = idle; + btv->loop_irq = 0; + bttv_buffer_activate_video(btv, &idle); + bttv_buffer_activate_vbi(btv, NULL); + bttv_set_dma(btv, 0); + btwrite(0, BT848_INT_MASK); + spin_unlock_irqrestore(&btv->s_lock,flags); + + /* save bt878 state */ + btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN); + btv->state.gpio_data = gpio_read(); + + /* save pci state */ + pci_save_state(pci_dev); + if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) { + pci_disable_device(pci_dev); + btv->state.disabled = 1; + } + return 0; +} + +static int bttv_resume(struct pci_dev *pci_dev) +{ + struct bttv *btv = pci_get_drvdata(pci_dev); + unsigned long flags; + int err; + + dprintk("bttv%d: resume\n", btv->c.nr); + + /* restore pci state */ + if (btv->state.disabled) { + err=pci_enable_device(pci_dev); + if (err) { + printk(KERN_WARNING "bttv%d: Can't enable device.\n", + btv->c.nr); + return err; + } + btv->state.disabled = 0; + } + err=pci_set_power_state(pci_dev, PCI_D0); + if (err) { + pci_disable_device(pci_dev); + printk(KERN_WARNING "bttv%d: Can't enable device.\n", + btv->c.nr); + btv->state.disabled = 1; + return err; + } + + pci_restore_state(pci_dev); + + /* restore bt878 state */ + bttv_reinit_bt848(btv); + gpio_inout(0xffffff, btv->state.gpio_enable); + gpio_write(btv->state.gpio_data); + + /* restart dma */ + spin_lock_irqsave(&btv->s_lock,flags); + btv->curr = btv->state.video; + btv->cvbi = btv->state.vbi; + btv->loop_irq = btv->state.loop_irq; + bttv_buffer_activate_video(btv, &btv->curr); + bttv_buffer_activate_vbi(btv, btv->cvbi); + bttv_set_dma(btv, 0); + spin_unlock_irqrestore(&btv->s_lock,flags); + return 0; +} + +static struct pci_device_id bttv_pci_tbl[] = { + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} +}; + +MODULE_DEVICE_TABLE(pci, bttv_pci_tbl); + +static struct pci_driver bttv_pci_driver = { + .name = "bttv", + .id_table = bttv_pci_tbl, + .probe = bttv_probe, + .remove = __devexit_p(bttv_remove), + .suspend = bttv_suspend, + .resume = bttv_resume, +}; + +static int bttv_init_module(void) +{ + bttv_num = 0; + + printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n", + (BTTV_VERSION_CODE >> 16) & 0xff, + (BTTV_VERSION_CODE >> 8) & 0xff, + BTTV_VERSION_CODE & 0xff); +#ifdef SNAPSHOT + printk(KERN_INFO "bttv: snapshot date %04d-%02d-%02d\n", + SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); +#endif + if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME) + gbuffers = 2; + if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF) + gbufsize = BTTV_MAX_FBUF; + gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK; + if (bttv_verbose) + printk(KERN_INFO "bttv: using %d buffers with %dk (%d pages) each for capture\n", + gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT); + + bttv_check_chipset(); + + bus_register(&bttv_sub_bus_type); + return pci_register_driver(&bttv_pci_driver); +} + +static void bttv_cleanup_module(void) +{ + pci_unregister_driver(&bttv_pci_driver); + bus_unregister(&bttv_sub_bus_type); + return; +} + +module_init(bttv_init_module); +module_exit(bttv_cleanup_module); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bt8xx/bttv-gpio.c b/drivers/media/video/bt8xx/bttv-gpio.c new file mode 100644 index 000000000000..c4d5e2b70c28 --- /dev/null +++ b/drivers/media/video/bt8xx/bttv-gpio.c @@ -0,0 +1,208 @@ +/* + + bttv-gpio.c -- gpio sub drivers + + sysfs-based sub driver interface for bttv + mainly intented for gpio access + + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) + (c) 1999-2003 Gerd Knorr + + 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 "bttvp.h" + +/* ----------------------------------------------------------------------- */ +/* internal: the bttv "bus" */ + +static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv) +{ + struct bttv_sub_driver *sub = to_bttv_sub_drv(drv); + int len = strlen(sub->wanted); + + if (0 == strncmp(dev->bus_id, sub->wanted, len)) + return 1; + return 0; +} + +static int bttv_sub_probe(struct device *dev) +{ + struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); + struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); + + return sub->probe ? sub->probe(sdev) : -ENODEV; +} + +static int bttv_sub_remove(struct device *dev) +{ + struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); + struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); + + if (sub->remove) + sub->remove(sdev); + return 0; +} + +struct bus_type bttv_sub_bus_type = { + .name = "bttv-sub", + .match = &bttv_sub_bus_match, + .probe = bttv_sub_probe, + .remove = bttv_sub_remove, +}; +EXPORT_SYMBOL(bttv_sub_bus_type); + +static void release_sub_device(struct device *dev) +{ + struct bttv_sub_device *sub = to_bttv_sub_dev(dev); + kfree(sub); +} + +int bttv_sub_add_device(struct bttv_core *core, char *name) +{ + struct bttv_sub_device *sub; + int err; + + sub = kzalloc(sizeof(*sub),GFP_KERNEL); + if (NULL == sub) + return -ENOMEM; + + sub->core = core; + sub->dev.parent = &core->pci->dev; + sub->dev.bus = &bttv_sub_bus_type; + sub->dev.release = release_sub_device; + snprintf(sub->dev.bus_id,sizeof(sub->dev.bus_id),"%s%d", + name, core->nr); + + err = device_register(&sub->dev); + if (0 != err) { + kfree(sub); + return err; + } + printk("bttv%d: add subdevice \"%s\"\n", core->nr, sub->dev.bus_id); + list_add_tail(&sub->list,&core->subs); + return 0; +} + +int bttv_sub_del_devices(struct bttv_core *core) +{ + struct bttv_sub_device *sub; + struct list_head *item,*save; + + list_for_each_safe(item,save,&core->subs) { + sub = list_entry(item,struct bttv_sub_device,list); + list_del(&sub->list); + device_unregister(&sub->dev); + } + return 0; +} + +void bttv_gpio_irq(struct bttv_core *core) +{ + struct bttv_sub_driver *drv; + struct bttv_sub_device *dev; + struct list_head *item; + + list_for_each(item,&core->subs) { + dev = list_entry(item,struct bttv_sub_device,list); + drv = to_bttv_sub_drv(dev->dev.driver); + if (drv && drv->gpio_irq) + drv->gpio_irq(dev); + } +} + +/* ----------------------------------------------------------------------- */ +/* external: sub-driver register/unregister */ + +int bttv_sub_register(struct bttv_sub_driver *sub, char *wanted) +{ + sub->drv.bus = &bttv_sub_bus_type; + snprintf(sub->wanted,sizeof(sub->wanted),"%s",wanted); + return driver_register(&sub->drv); +} +EXPORT_SYMBOL(bttv_sub_register); + +int bttv_sub_unregister(struct bttv_sub_driver *sub) +{ + driver_unregister(&sub->drv); + return 0; +} +EXPORT_SYMBOL(bttv_sub_unregister); + +/* ----------------------------------------------------------------------- */ +/* external: gpio access functions */ + +void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits) +{ + struct bttv *btv = container_of(core, struct bttv, c); + unsigned long flags; + u32 data; + + spin_lock_irqsave(&btv->gpio_lock,flags); + data = btread(BT848_GPIO_OUT_EN); + data = data & ~mask; + data = data | (mask & outbits); + btwrite(data,BT848_GPIO_OUT_EN); + spin_unlock_irqrestore(&btv->gpio_lock,flags); +} +EXPORT_SYMBOL(bttv_gpio_inout); + +u32 bttv_gpio_read(struct bttv_core *core) +{ + struct bttv *btv = container_of(core, struct bttv, c); + u32 value; + + value = btread(BT848_GPIO_DATA); + return value; +} +EXPORT_SYMBOL(bttv_gpio_read); + +void bttv_gpio_write(struct bttv_core *core, u32 value) +{ + struct bttv *btv = container_of(core, struct bttv, c); + + btwrite(value,BT848_GPIO_DATA); +} +EXPORT_SYMBOL(bttv_gpio_write); + +void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits) +{ + struct bttv *btv = container_of(core, struct bttv, c); + unsigned long flags; + u32 data; + + spin_lock_irqsave(&btv->gpio_lock,flags); + data = btread(BT848_GPIO_DATA); + data = data & ~mask; + data = data | (mask & bits); + btwrite(data,BT848_GPIO_DATA); + spin_unlock_irqrestore(&btv->gpio_lock,flags); +} +EXPORT_SYMBOL(bttv_gpio_bits); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c new file mode 100644 index 000000000000..614c12018557 --- /dev/null +++ b/drivers/media/video/bt8xx/bttv-i2c.c @@ -0,0 +1,474 @@ +/* + + bttv-i2c.c -- all the i2c code is here + + bttv - Bt848 frame grabber driver + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) + (c) 1999-2003 Gerd Knorr + + 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 "bttvp.h" +#include +#include +#include + +static struct i2c_algo_bit_data bttv_i2c_algo_bit_template; +static struct i2c_adapter bttv_i2c_adap_sw_template; +static struct i2c_adapter bttv_i2c_adap_hw_template; +static struct i2c_client bttv_i2c_client_template; + +static int attach_inform(struct i2c_client *client); + +static int i2c_debug; +static int i2c_hw; +static int i2c_scan; +module_param(i2c_debug, int, 0644); +module_param(i2c_hw, int, 0444); +module_param(i2c_scan, int, 0444); +MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); + +/* ----------------------------------------------------------------------- */ +/* I2C functions - bitbanging adapter (software i2c) */ + +static void bttv_bit_setscl(void *data, int state) +{ + struct bttv *btv = (struct bttv*)data; + + if (state) + btv->i2c_state |= 0x02; + else + btv->i2c_state &= ~0x02; + btwrite(btv->i2c_state, BT848_I2C); + btread(BT848_I2C); +} + +static void bttv_bit_setsda(void *data, int state) +{ + struct bttv *btv = (struct bttv*)data; + + if (state) + btv->i2c_state |= 0x01; + else + btv->i2c_state &= ~0x01; + btwrite(btv->i2c_state, BT848_I2C); + btread(BT848_I2C); +} + +static int bttv_bit_getscl(void *data) +{ + struct bttv *btv = (struct bttv*)data; + int state; + + state = btread(BT848_I2C) & 0x02 ? 1 : 0; + return state; +} + +static int bttv_bit_getsda(void *data) +{ + struct bttv *btv = (struct bttv*)data; + int state; + + state = btread(BT848_I2C) & 0x01; + return state; +} + +static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = { + .setsda = bttv_bit_setsda, + .setscl = bttv_bit_setscl, + .getsda = bttv_bit_getsda, + .getscl = bttv_bit_getscl, + .udelay = 16, + .mdelay = 10, + .timeout = 200, +}; + +static struct i2c_adapter bttv_i2c_adap_sw_template = { + .owner = THIS_MODULE, + .class = I2C_CLASS_TV_ANALOG, + .name = "bttv", + .id = I2C_HW_B_BT848, + .client_register = attach_inform, +}; + +/* ----------------------------------------------------------------------- */ +/* I2C functions - hardware i2c */ + +static int algo_control(struct i2c_adapter *adapter, + unsigned int cmd, unsigned long arg) +{ + return 0; +} + +static u32 functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +static int +bttv_i2c_wait_done(struct bttv *btv) +{ + int rc = 0; + + /* timeout */ + if (wait_event_interruptible_timeout(btv->i2c_queue, + btv->i2c_done, msecs_to_jiffies(85)) == -ERESTARTSYS) + + rc = -EIO; + + if (btv->i2c_done & BT848_INT_RACK) + rc = 1; + btv->i2c_done = 0; + return rc; +} + +#define I2C_HW (BT878_I2C_MODE | BT848_I2C_SYNC |\ + BT848_I2C_SCL | BT848_I2C_SDA) + +static int +bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last) +{ + u32 xmit; + int retval,cnt; + + /* sanity checks */ + if (0 == msg->len) + return -EINVAL; + + /* start, address + first byte */ + xmit = (msg->addr << 25) | (msg->buf[0] << 16) | I2C_HW; + if (msg->len > 1 || !last) + xmit |= BT878_I2C_NOSTOP; + btwrite(xmit, BT848_I2C); + retval = bttv_i2c_wait_done(btv); + if (retval < 0) + goto err; + if (retval == 0) + goto eio; + if (i2c_debug) { + printk(" addr << 1, msg->buf[0]); + if (!(xmit & BT878_I2C_NOSTOP)) + printk(" >\n"); + } + + for (cnt = 1; cnt < msg->len; cnt++ ) { + /* following bytes */ + xmit = (msg->buf[cnt] << 24) | I2C_HW | BT878_I2C_NOSTART; + if (cnt < msg->len-1 || !last) + xmit |= BT878_I2C_NOSTOP; + btwrite(xmit, BT848_I2C); + retval = bttv_i2c_wait_done(btv); + if (retval < 0) + goto err; + if (retval == 0) + goto eio; + if (i2c_debug) { + printk(" %02x", msg->buf[cnt]); + if (!(xmit & BT878_I2C_NOSTOP)) + printk(" >\n"); + } + } + return msg->len; + + eio: + retval = -EIO; + err: + if (i2c_debug) + printk(" ERR: %d\n",retval); + return retval; +} + +static int +bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last) +{ + u32 xmit; + u32 cnt; + int retval; + + for(cnt = 0; cnt < msg->len; cnt++) { + xmit = (msg->addr << 25) | (1 << 24) | I2C_HW; + if (cnt < msg->len-1) + xmit |= BT848_I2C_W3B; + if (cnt < msg->len-1 || !last) + xmit |= BT878_I2C_NOSTOP; + if (cnt) + xmit |= BT878_I2C_NOSTART; + btwrite(xmit, BT848_I2C); + retval = bttv_i2c_wait_done(btv); + if (retval < 0) + goto err; + if (retval == 0) + goto eio; + msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff; + if (i2c_debug) { + if (!(xmit & BT878_I2C_NOSTART)) + printk(" addr << 1) +1); + printk(" =%02x", msg->buf[cnt]); + if (!(xmit & BT878_I2C_NOSTOP)) + printk(" >\n"); + } + } + return msg->len; + + eio: + retval = -EIO; + err: + if (i2c_debug) + printk(" ERR: %d\n",retval); + return retval; +} + +static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) +{ + struct bttv *btv = i2c_get_adapdata(i2c_adap); + int retval = 0; + int i; + + if (i2c_debug) + printk("bt-i2c:"); + btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT); + for (i = 0 ; i < num; i++) { + if (msgs[i].flags & I2C_M_RD) { + /* read */ + retval = bttv_i2c_readbytes(btv, &msgs[i], i+1 == num); + if (retval < 0) + goto err; + } else { + /* write */ + retval = bttv_i2c_sendbytes(btv, &msgs[i], i+1 == num); + if (retval < 0) + goto err; + } + } + return num; + + err: + return retval; +} + +static struct i2c_algorithm bttv_algo = { + .master_xfer = bttv_i2c_xfer, + .algo_control = algo_control, + .functionality = functionality, +}; + +static struct i2c_adapter bttv_i2c_adap_hw_template = { + .owner = THIS_MODULE, + .class = I2C_CLASS_TV_ANALOG, + .name = "bt878", + .id = I2C_HW_B_BT848 /* FIXME */, + .algo = &bttv_algo, + .client_register = attach_inform, +}; + +/* ----------------------------------------------------------------------- */ +/* I2C functions - common stuff */ + +static int attach_inform(struct i2c_client *client) +{ + struct bttv *btv = i2c_get_adapdata(client->adapter); + int addr=ADDR_UNSET; + + + if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) + addr = bttv_tvcards[btv->c.type].tuner_addr; + + + if (bttv_debug) + printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n", + btv->c.nr, client->driver->driver.name, client->addr, + client->name); + if (!client->driver->command) + return 0; + + if (btv->tuner_type != UNSET) { + struct tuner_setup tun_setup; + + if ((addr==ADDR_UNSET) || + (addr==client->addr)) { + + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV | T_RADIO; + tun_setup.type = btv->tuner_type; + tun_setup.addr = addr; + bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); + } + + } + + return 0; +} + +void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) +{ + if (0 != btv->i2c_rc) + return; + i2c_clients_command(&btv->c.i2c_adap, cmd, arg); +} + +static struct i2c_client bttv_i2c_client_template = { + .name = "bttv internal", +}; + + +/* read I2C */ +int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) +{ + unsigned char buffer = 0; + + if (0 != btv->i2c_rc) + return -1; + if (bttv_verbose && NULL != probe_for) + printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ", + btv->c.nr,probe_for,addr); + btv->i2c_client.addr = addr >> 1; + if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) { + if (NULL != probe_for) { + if (bttv_verbose) + printk("not found\n"); + } else + printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n", + btv->c.nr,addr); + return -1; + } + if (bttv_verbose && NULL != probe_for) + printk("found\n"); + return buffer; +} + +/* write I2C */ +int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, + unsigned char b2, int both) +{ + unsigned char buffer[2]; + int bytes = both ? 2 : 1; + + if (0 != btv->i2c_rc) + return -1; + btv->i2c_client.addr = addr >> 1; + buffer[0] = b1; + buffer[1] = b2; + if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) + return -1; + return 0; +} + +/* read EEPROM content */ +void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr) +{ + memset(eedata, 0, 256); + if (0 != btv->i2c_rc) + return; + btv->i2c_client.addr = addr >> 1; + tveeprom_read(&btv->i2c_client, eedata, 256); +} + +static char *i2c_devs[128] = { + [ 0x1c >> 1 ] = "lgdt330x", + [ 0x30 >> 1 ] = "IR (hauppauge)", + [ 0x80 >> 1 ] = "msp34xx", + [ 0x86 >> 1 ] = "tda9887", + [ 0xa0 >> 1 ] = "eeprom", + [ 0xc0 >> 1 ] = "tuner (analog)", + [ 0xc2 >> 1 ] = "tuner (analog)", +}; + +static void do_i2c_scan(char *name, struct i2c_client *c) +{ + unsigned char buf; + int i,rc; + + for (i = 0; i < 128; i++) { + c->addr = i; + rc = i2c_master_recv(c,&buf,0); + if (rc < 0) + continue; + printk("%s: i2c scan: found device @ 0x%x [%s]\n", + name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); + } +} + +/* init + register i2c algo-bit adapter */ +int __devinit init_bttv_i2c(struct bttv *btv) +{ + memcpy(&btv->i2c_client, &bttv_i2c_client_template, + sizeof(bttv_i2c_client_template)); + + if (i2c_hw) + btv->use_i2c_hw = 1; + if (btv->use_i2c_hw) { + /* bt878 */ + memcpy(&btv->c.i2c_adap, &bttv_i2c_adap_hw_template, + sizeof(bttv_i2c_adap_hw_template)); + } else { + /* bt848 */ + memcpy(&btv->c.i2c_adap, &bttv_i2c_adap_sw_template, + sizeof(bttv_i2c_adap_sw_template)); + memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template, + sizeof(bttv_i2c_algo_bit_template)); + btv->i2c_algo.data = btv; + btv->c.i2c_adap.algo_data = &btv->i2c_algo; + } + + btv->c.i2c_adap.dev.parent = &btv->c.pci->dev; + snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name), + "bt%d #%d [%s]", btv->id, btv->c.nr, + btv->use_i2c_hw ? "hw" : "sw"); + + i2c_set_adapdata(&btv->c.i2c_adap, btv); + btv->i2c_client.adapter = &btv->c.i2c_adap; + + if (bttv_tvcards[btv->c.type].no_video) + btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG; + if (bttv_tvcards[btv->c.type].has_dvb) + btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL; + + if (btv->use_i2c_hw) { + btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap); + } else { + bttv_bit_setscl(btv,1); + bttv_bit_setsda(btv,1); + btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap); + } + if (0 == btv->i2c_rc && i2c_scan) + do_i2c_scan(btv->c.name,&btv->i2c_client); + return btv->i2c_rc; +} + +int __devexit fini_bttv_i2c(struct bttv *btv) +{ + if (0 != btv->i2c_rc) + return 0; + + if (btv->use_i2c_hw) { + return i2c_del_adapter(&btv->c.i2c_adap); + } else { + return i2c_bit_del_bus(&btv->c.i2c_adap); + } +} + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bt8xx/bttv-if.c b/drivers/media/video/bt8xx/bttv-if.c new file mode 100644 index 000000000000..19b564ab0e92 --- /dev/null +++ b/drivers/media/video/bt8xx/bttv-if.c @@ -0,0 +1,159 @@ +/* + + bttv-if.c -- old gpio interface to other kernel modules + don't use in new code, will go away in 2.7 + have a look at bttv-gpio.c instead. + + bttv - Bt848 frame grabber driver + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) + (c) 1999-2003 Gerd Knorr + + 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 "bttvp.h" + +EXPORT_SYMBOL(bttv_get_cardinfo); +EXPORT_SYMBOL(bttv_get_pcidev); +EXPORT_SYMBOL(bttv_get_id); +EXPORT_SYMBOL(bttv_gpio_enable); +EXPORT_SYMBOL(bttv_read_gpio); +EXPORT_SYMBOL(bttv_write_gpio); +EXPORT_SYMBOL(bttv_get_gpio_queue); +EXPORT_SYMBOL(bttv_i2c_call); + +/* ----------------------------------------------------------------------- */ +/* Exported functions - for other modules which want to access the */ +/* gpio ports (IR for example) */ +/* see bttv.h for comments */ + +int bttv_get_cardinfo(unsigned int card, int *type, unsigned *cardid) +{ + printk("The bttv_* interface is obsolete and will go away,\n" + "please use the new, sysfs based interface instead.\n"); + if (card >= bttv_num) { + return -1; + } + *type = bttvs[card].c.type; + *cardid = bttvs[card].cardid; + return 0; +} + +struct pci_dev* bttv_get_pcidev(unsigned int card) +{ + if (card >= bttv_num) + return NULL; + return bttvs[card].c.pci; +} + +int bttv_get_id(unsigned int card) +{ + printk("The bttv_* interface is obsolete and will go away,\n" + "please use the new, sysfs based interface instead.\n"); + if (card >= bttv_num) { + return -1; + } + return bttvs[card].c.type; +} + + +int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data) +{ + struct bttv *btv; + + if (card >= bttv_num) { + return -EINVAL; + } + + btv = &bttvs[card]; + gpio_inout(mask,data); + if (bttv_gpio) + bttv_gpio_tracking(btv,"extern enable"); + return 0; +} + +int bttv_read_gpio(unsigned int card, unsigned long *data) +{ + struct bttv *btv; + + if (card >= bttv_num) { + return -EINVAL; + } + + btv = &bttvs[card]; + + if(btv->shutdown) { + return -ENODEV; + } + +/* prior setting BT848_GPIO_REG_INP is (probably) not needed + because we set direct input on init */ + *data = gpio_read(); + return 0; +} + +int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data) +{ + struct bttv *btv; + + if (card >= bttv_num) { + return -EINVAL; + } + + btv = &bttvs[card]; + +/* prior setting BT848_GPIO_REG_INP is (probably) not needed + because direct input is set on init */ + gpio_bits(mask,data); + if (bttv_gpio) + bttv_gpio_tracking(btv,"extern write"); + return 0; +} + +wait_queue_head_t* bttv_get_gpio_queue(unsigned int card) +{ + struct bttv *btv; + + if (card >= bttv_num) { + return NULL; + } + + btv = &bttvs[card]; + if (bttvs[card].shutdown) { + return NULL; + } + return &btv->gpioq; +} + +void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg) +{ + if (card >= bttv_num) + return; + bttv_call_i2c_clients(&bttvs[card], cmd, arg); +} + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c new file mode 100644 index 000000000000..69efa0e5174d --- /dev/null +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -0,0 +1,450 @@ +/* + * + * Copyright (c) 2003 Gerd Knorr + * Copyright (c) 2003 Pavel Machek + * + * 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 "bttv.h" +#include "bttvp.h" + + +static int debug; +module_param(debug, int, 0644); /* debug level (0,1,2) */ +static int repeat_delay = 500; +module_param(repeat_delay, int, 0644); +static int repeat_period = 33; +module_param(repeat_period, int, 0644); + +#define DEVNAME "bttv-input" + +/* ---------------------------------------------------------------------- */ + +static void ir_handle_key(struct bttv *btv) +{ + struct bttv_ir *ir = btv->remote; + u32 gpio,data; + + /* read gpio value */ + gpio = bttv_gpio_read(&btv->c); + if (ir->polling) { + if (ir->last_gpio == gpio) + return; + ir->last_gpio = gpio; + } + + /* extract data */ + data = ir_extract_bits(gpio, ir->mask_keycode); + dprintk(KERN_INFO DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n", + gpio, data, + ir->polling ? "poll" : "irq", + (gpio & ir->mask_keydown) ? " down" : "", + (gpio & ir->mask_keyup) ? " up" : ""); + + if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || + (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { + ir_input_keydown(ir->dev,&ir->ir,data,data); + } else { + ir_input_nokey(ir->dev,&ir->ir); + } + +} + +void bttv_input_irq(struct bttv *btv) +{ + struct bttv_ir *ir = btv->remote; + + if (!ir->polling) + ir_handle_key(btv); +} + +static void bttv_input_timer(unsigned long data) +{ + struct bttv *btv = (struct bttv*)data; + struct bttv_ir *ir = btv->remote; + unsigned long timeout; + + ir_handle_key(btv); + timeout = jiffies + (ir->polling * HZ / 1000); + mod_timer(&ir->timer, timeout); +} + +/* ---------------------------------------------------------------*/ + +static int rc5_remote_gap = 885; +module_param(rc5_remote_gap, int, 0644); +static int rc5_key_timeout = 200; +module_param(rc5_key_timeout, int, 0644); + +#define RC5_START(x) (((x)>>12)&3) +#define RC5_TOGGLE(x) (((x)>>11)&1) +#define RC5_ADDR(x) (((x)>>6)&31) +#define RC5_INSTR(x) ((x)&63) + +/* decode raw bit pattern to RC5 code */ +static u32 rc5_decode(unsigned int code) +{ + unsigned int org_code = code; + unsigned int pair; + unsigned int rc5 = 0; + int i; + + code = (code << 1) | 1; + for (i = 0; i < 14; ++i) { + pair = code & 0x3; + code >>= 2; + + rc5 <<= 1; + switch (pair) { + case 0: + case 2: + break; + case 1: + rc5 |= 1; + break; + case 3: + dprintk(KERN_WARNING "bad code: %x\n", org_code); + return 0; + } + } + dprintk(KERN_WARNING "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " + "instr=%x\n", rc5, org_code, RC5_START(rc5), + RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); + return rc5; +} + +static int bttv_rc5_irq(struct bttv *btv) +{ + struct bttv_ir *ir = btv->remote; + struct timeval tv; + u32 gpio; + u32 gap; + unsigned long current_jiffies, timeout; + + /* read gpio port */ + gpio = bttv_gpio_read(&btv->c); + + /* remote IRQ? */ + if (!(gpio & 0x20)) + return 0; + + /* get time of bit */ + current_jiffies = jiffies; + do_gettimeofday(&tv); + + /* avoid overflow with gap >1s */ + if (tv.tv_sec - ir->base_time.tv_sec > 1) { + gap = 200000; + } else { + gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + + tv.tv_usec - ir->base_time.tv_usec; + } + + /* active code => add bit */ + if (ir->active) { + /* only if in the code (otherwise spurious IRQ or timer + late) */ + if (ir->last_bit < 28) { + ir->last_bit = (gap - rc5_remote_gap / 2) / + rc5_remote_gap; + ir->code |= 1 << ir->last_bit; + } + /* starting new code */ + } else { + ir->active = 1; + ir->code = 0; + ir->base_time = tv; + ir->last_bit = 0; + + timeout = current_jiffies + (500 + 30 * HZ) / 1000; + mod_timer(&ir->timer_end, timeout); + } + + /* toggle GPIO pin 4 to reset the irq */ + bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); + bttv_gpio_write(&btv->c, gpio | (1 << 4)); + return 1; +} + + +static void bttv_rc5_timer_end(unsigned long data) +{ + struct bttv_ir *ir = (struct bttv_ir *)data; + struct timeval tv; + unsigned long current_jiffies, timeout; + u32 gap; + + /* get time */ + current_jiffies = jiffies; + do_gettimeofday(&tv); + + /* avoid overflow with gap >1s */ + if (tv.tv_sec - ir->base_time.tv_sec > 1) { + gap = 200000; + } else { + gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + + tv.tv_usec - ir->base_time.tv_usec; + } + + /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */ + if (gap < 28000) { + dprintk(KERN_WARNING "spurious timer_end\n"); + return; + } + + ir->active = 0; + if (ir->last_bit < 20) { + /* ignore spurious codes (caused by light/other remotes) */ + dprintk(KERN_WARNING "short code: %x\n", ir->code); + } else { + u32 rc5 = rc5_decode(ir->code); + + /* two start bits? */ + if (RC5_START(rc5) != 3) { + dprintk(KERN_WARNING "rc5 start bits invalid: %u\n", RC5_START(rc5)); + + /* right address? */ + } else if (RC5_ADDR(rc5) == 0x0) { + u32 toggle = RC5_TOGGLE(rc5); + u32 instr = RC5_INSTR(rc5); + + /* Good code, decide if repeat/repress */ + if (toggle != RC5_TOGGLE(ir->last_rc5) || + instr != RC5_INSTR(ir->last_rc5)) { + dprintk(KERN_WARNING "instruction %x, toggle %x\n", instr, + toggle); + ir_input_nokey(ir->dev, &ir->ir); + ir_input_keydown(ir->dev, &ir->ir, instr, + instr); + } + + /* Set/reset key-up timer */ + timeout = current_jiffies + (500 + rc5_key_timeout + * HZ) / 1000; + mod_timer(&ir->timer_keyup, timeout); + + /* Save code for repeat test */ + ir->last_rc5 = rc5; + } + } +} + +static void bttv_rc5_timer_keyup(unsigned long data) +{ + struct bttv_ir *ir = (struct bttv_ir *)data; + + dprintk(KERN_DEBUG "key released\n"); + ir_input_nokey(ir->dev, &ir->ir); +} + +/* ---------------------------------------------------------------------- */ + +int bttv_input_init(struct bttv *btv) +{ + struct bttv_ir *ir; + IR_KEYTAB_TYPE *ir_codes = NULL; + struct input_dev *input_dev; + int ir_type = IR_TYPE_OTHER; + + if (!btv->has_remote) + return -ENODEV; + + ir = kzalloc(sizeof(*ir),GFP_KERNEL); + input_dev = input_allocate_device(); + if (!ir || !input_dev) { + kfree(ir); + input_free_device(input_dev); + return -ENOMEM; + } + memset(ir,0,sizeof(*ir)); + + /* detect & configure */ + switch (btv->c.type) { + case BTTV_BOARD_AVERMEDIA: + case BTTV_BOARD_AVPHONE98: + case BTTV_BOARD_AVERMEDIA98: + ir_codes = ir_codes_avermedia; + ir->mask_keycode = 0xf88000; + ir->mask_keydown = 0x010000; + ir->polling = 50; // ms + break; + + case BTTV_BOARD_AVDVBT_761: + case BTTV_BOARD_AVDVBT_771: + ir_codes = ir_codes_avermedia_dvbt; + ir->mask_keycode = 0x0f00c0; + ir->mask_keydown = 0x000020; + ir->polling = 50; // ms + break; + + case BTTV_BOARD_PXELVWPLTVPAK: + ir_codes = ir_codes_pixelview; + ir->mask_keycode = 0x003e00; + ir->mask_keyup = 0x010000; + ir->polling = 50; // ms + break; + case BTTV_BOARD_PV_BT878P_9B: + case BTTV_BOARD_PV_BT878P_PLUS: + ir_codes = ir_codes_pixelview; + ir->mask_keycode = 0x001f00; + ir->mask_keyup = 0x008000; + ir->polling = 50; // ms + break; + + case BTTV_BOARD_WINFAST2000: + ir_codes = ir_codes_winfast; + ir->mask_keycode = 0x1f8; + break; + case BTTV_BOARD_MAGICTVIEW061: + case BTTV_BOARD_MAGICTVIEW063: + ir_codes = ir_codes_winfast; + ir->mask_keycode = 0x0008e000; + ir->mask_keydown = 0x00200000; + break; + case BTTV_BOARD_APAC_VIEWCOMP: + ir_codes = ir_codes_apac_viewcomp; + ir->mask_keycode = 0x001f00; + ir->mask_keyup = 0x008000; + ir->polling = 50; // ms + break; + case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: + case BTTV_BOARD_CONTVFMI: + ir_codes = ir_codes_pixelview; + ir->mask_keycode = 0x001F00; + ir->mask_keyup = 0x006000; + ir->polling = 50; // ms + break; + case BTTV_BOARD_NEBULA_DIGITV: + ir_codes = ir_codes_nebula; + btv->custom_irq = bttv_rc5_irq; + ir->rc5_gpio = 1; + break; + case BTTV_BOARD_MACHTV_MAGICTV: + ir_codes = ir_codes_apac_viewcomp; + ir->mask_keycode = 0x001F00; + ir->mask_keyup = 0x004000; + ir->polling = 50; /* ms */ + break; + } + if (NULL == ir_codes) { + dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type); + kfree(ir); + input_free_device(input_dev); + return -ENODEV; + } + + if (ir->rc5_gpio) { + u32 gpio; + /* enable remote irq */ + bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4); + gpio = bttv_gpio_read(&btv->c); + bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); + bttv_gpio_write(&btv->c, gpio | (1 << 4)); + } else { + /* init hardware-specific stuff */ + bttv_gpio_inout(&btv->c, ir->mask_keycode | ir->mask_keydown, 0); + } + + /* init input device */ + ir->dev = input_dev; + + snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", + btv->c.type); + snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", + pci_name(btv->c.pci)); + + ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + input_dev->name = ir->name; + input_dev->phys = ir->phys; + input_dev->id.bustype = BUS_PCI; + input_dev->id.version = 1; + if (btv->c.pci->subsystem_vendor) { + input_dev->id.vendor = btv->c.pci->subsystem_vendor; + input_dev->id.product = btv->c.pci->subsystem_device; + } else { + input_dev->id.vendor = btv->c.pci->vendor; + input_dev->id.product = btv->c.pci->device; + } + input_dev->cdev.dev = &btv->c.pci->dev; + + btv->remote = ir; + if (ir->polling) { + init_timer(&ir->timer); + ir->timer.function = bttv_input_timer; + ir->timer.data = (unsigned long)btv; + ir->timer.expires = jiffies + HZ; + add_timer(&ir->timer); + } else if (ir->rc5_gpio) { + /* set timer_end for code completion */ + init_timer(&ir->timer_end); + ir->timer_end.function = bttv_rc5_timer_end; + ir->timer_end.data = (unsigned long)ir; + + init_timer(&ir->timer_keyup); + ir->timer_keyup.function = bttv_rc5_timer_keyup; + ir->timer_keyup.data = (unsigned long)ir; + } + + /* all done */ + input_register_device(btv->remote->dev); + printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys); + + /* the remote isn't as bouncy as a keyboard */ + ir->dev->rep[REP_DELAY] = repeat_delay; + ir->dev->rep[REP_PERIOD] = repeat_period; + + return 0; +} + +void bttv_input_fini(struct bttv *btv) +{ + if (btv->remote == NULL) + return; + + if (btv->remote->polling) { + del_timer_sync(&btv->remote->timer); + flush_scheduled_work(); + } + + + if (btv->remote->rc5_gpio) { + u32 gpio; + + del_timer_sync(&btv->remote->timer_end); + flush_scheduled_work(); + + gpio = bttv_gpio_read(&btv->c); + bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); + } + + input_unregister_device(btv->remote->dev); + kfree(btv->remote); + btv->remote = NULL; +} + + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c new file mode 100644 index 000000000000..16323a5d68ac --- /dev/null +++ b/drivers/media/video/bt8xx/bttv-risc.c @@ -0,0 +1,795 @@ +/* + + bttv-risc.c -- interfaces to other kernel modules + + bttv risc code handling + - memory management + - generation + + (c) 2000-2003 Gerd Knorr + + 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 "bttvp.h" + +#define VCR_HACK_LINES 4 + +/* ---------------------------------------------------------- */ +/* risc code generators */ + +int +bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int offset, unsigned int bpl, + unsigned int padding, unsigned int lines) +{ + u32 instructions,line,todo; + struct scatterlist *sg; + u32 *rp; + int rc; + + /* estimate risc mem: worst case is one write per page border + + one write per scan line + sync + jump (all 2 dwords). padding + can cause next bpl to start close to a page border. First DMA + region may be smaller than PAGE_SIZE */ + instructions = 1 + ((bpl + padding) * lines) / PAGE_SIZE + lines; + instructions += 2; + if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) + return rc; + + /* sync instruction */ + rp = risc->cpu; + *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); + *(rp++) = cpu_to_le32(0); + + /* scan lines */ + sg = sglist; + for (line = 0; line < lines; line++) { + if ((btv->opt_vcr_hack) && + (line >= (lines - VCR_HACK_LINES))) + continue; + while (offset && offset >= sg_dma_len(sg)) { + offset -= sg_dma_len(sg); + sg++; + } + if (bpl <= sg_dma_len(sg)-offset) { + /* fits into current chunk */ + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| + BT848_RISC_EOL|bpl); + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + offset+=bpl; + } else { + /* scanline needs to be splitted */ + todo = bpl; + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| + (sg_dma_len(sg)-offset)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + todo -= (sg_dma_len(sg)-offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++)=cpu_to_le32(BT848_RISC_WRITE| + sg_dma_len(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); + todo -= sg_dma_len(sg); + sg++; + } + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL| + todo); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); + offset += todo; + } + offset += padding; + } + + /* save pointer to jmp instruction address */ + risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); + return 0; +} + +static int +bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int yoffset, unsigned int ybpl, + unsigned int ypadding, unsigned int ylines, + unsigned int uoffset, unsigned int voffset, + unsigned int hshift, unsigned int vshift, + unsigned int cpadding) +{ + unsigned int instructions,line,todo,ylen,chroma; + u32 *rp,ri; + struct scatterlist *ysg; + struct scatterlist *usg; + struct scatterlist *vsg; + int topfield = (0 == yoffset); + int rc; + + /* estimate risc mem: worst case is one write per page border + + one write per scan line (5 dwords) + plus sync + jump (2 dwords) */ + instructions = (ybpl * ylines * 2) / PAGE_SIZE + ylines; + instructions += 2; + if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0) + return rc; + + /* sync instruction */ + rp = risc->cpu; + *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); + *(rp++) = cpu_to_le32(0); + + /* scan lines */ + ysg = sglist; + usg = sglist; + vsg = sglist; + for (line = 0; line < ylines; line++) { + if ((btv->opt_vcr_hack) && + (line >= (ylines - VCR_HACK_LINES))) + continue; + switch (vshift) { + case 0: + chroma = 1; + break; + case 1: + if (topfield) + chroma = ((line & 1) == 0); + else + chroma = ((line & 1) == 1); + break; + case 2: + if (topfield) + chroma = ((line & 3) == 0); + else + chroma = ((line & 3) == 2); + break; + default: + chroma = 0; + break; + } + + for (todo = ybpl; todo > 0; todo -= ylen) { + /* go to next sg entry if needed */ + while (yoffset && yoffset >= sg_dma_len(ysg)) { + yoffset -= sg_dma_len(ysg); + ysg++; + } + while (uoffset && uoffset >= sg_dma_len(usg)) { + uoffset -= sg_dma_len(usg); + usg++; + } + while (voffset && voffset >= sg_dma_len(vsg)) { + voffset -= sg_dma_len(vsg); + vsg++; + } + + /* calculate max number of bytes we can write */ + ylen = todo; + if (yoffset + ylen > sg_dma_len(ysg)) + ylen = sg_dma_len(ysg) - yoffset; + if (chroma) { + if (uoffset + (ylen>>hshift) > sg_dma_len(usg)) + ylen = (sg_dma_len(usg) - uoffset) << hshift; + if (voffset + (ylen>>hshift) > sg_dma_len(vsg)) + ylen = (sg_dma_len(vsg) - voffset) << hshift; + ri = BT848_RISC_WRITE123; + } else { + ri = BT848_RISC_WRITE1S23; + } + if (ybpl == todo) + ri |= BT848_RISC_SOL; + if (ylen == todo) + ri |= BT848_RISC_EOL; + + /* write risc instruction */ + *(rp++)=cpu_to_le32(ri | ylen); + *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) | + (ylen >> hshift)); + *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset); + yoffset += ylen; + if (chroma) { + *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset); + uoffset += ylen >> hshift; + *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset); + voffset += ylen >> hshift; + } + } + yoffset += ypadding; + if (chroma) { + uoffset += cpadding; + voffset += cpadding; + } + } + + /* save pointer to jmp instruction address */ + risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); + return 0; +} + +static int +bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, + const struct bttv_format *fmt, struct bttv_overlay *ov, + int skip_even, int skip_odd) +{ + int instructions,rc,line,maxy,start,end,skip,nskips; + struct btcx_skiplist *skips; + u32 *rp,ri,ra; + u32 addr; + + /* skip list for window clipping */ + if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL))) + return -ENOMEM; + + /* estimate risc mem: worst case is (clip+1) * lines instructions + + sync + jump (all 2 dwords) */ + instructions = (ov->nclips + 1) * + ((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height); + instructions += 2; + if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) { + kfree(skips); + return rc; + } + + /* sync instruction */ + rp = risc->cpu; + *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); + *(rp++) = cpu_to_le32(0); + + addr = (unsigned long)btv->fbuf.base; + addr += btv->fbuf.fmt.bytesperline * ov->w.top; + addr += (fmt->depth >> 3) * ov->w.left; + + /* scan lines */ + for (maxy = -1, line = 0; line < ov->w.height; + line++, addr += btv->fbuf.fmt.bytesperline) { + if ((btv->opt_vcr_hack) && + (line >= (ov->w.height - VCR_HACK_LINES))) + continue; + if ((line%2) == 0 && skip_even) + continue; + if ((line%2) == 1 && skip_odd) + continue; + + /* calculate clipping */ + if (line > maxy) + btcx_calc_skips(line, ov->w.width, &maxy, + skips, &nskips, ov->clips, ov->nclips); + else + nskips = 0; + + /* write out risc code */ + for (start = 0, skip = 0; start < ov->w.width; start = end) { + if (skip >= nskips) { + ri = BT848_RISC_WRITE; + end = ov->w.width; + } else if (start < skips[skip].start) { + ri = BT848_RISC_WRITE; + end = skips[skip].start; + } else { + ri = BT848_RISC_SKIP; + end = skips[skip].end; + skip++; + } + if (BT848_RISC_WRITE == ri) + ra = addr + (fmt->depth>>3)*start; + else + ra = 0; + + if (0 == start) + ri |= BT848_RISC_SOL; + if (ov->w.width == end) + ri |= BT848_RISC_EOL; + ri |= (fmt->depth>>3) * (end-start); + + *(rp++)=cpu_to_le32(ri); + if (0 != ra) + *(rp++)=cpu_to_le32(ra); + } + } + + /* save pointer to jmp instruction address */ + risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); + kfree(skips); + return 0; +} + +/* ---------------------------------------------------------- */ + +static void +bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, + int width, int height, int interleaved, int norm) +{ + const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm]; + u32 xsf, sr; + int vdelay; + + int swidth = tvnorm->swidth; + int totalwidth = tvnorm->totalwidth; + int scaledtwidth = tvnorm->scaledtwidth; + + if (bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) { + swidth = 720; + totalwidth = 858; + scaledtwidth = 858; + } + + vdelay = tvnorm->vdelay; + + xsf = (width*scaledtwidth)/swidth; + geo->hscale = ((totalwidth*4096UL)/xsf-4096); + geo->hdelay = tvnorm->hdelayx1; + geo->hdelay = (geo->hdelay*width)/swidth; + geo->hdelay &= 0x3fe; + sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512; + geo->vscale = (0x10000UL-sr) & 0x1fff; + geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) | + ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0); + geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0; + geo->vdelay = vdelay; + geo->width = width; + geo->sheight = tvnorm->sheight; + geo->vtotal = tvnorm->vtotal; + + if (btv->opt_combfilter) { + geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); + geo->comb = (width < 769) ? 1 : 0; + } else { + geo->vtc = 0; + geo->comb = 0; + } +} + +static void +bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) +{ + int off = odd ? 0x80 : 0x00; + + if (geo->comb) + btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); + else + btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); + + btwrite(geo->vtc, BT848_E_VTC+off); + btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off); + btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off); + btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); + btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off); + btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off); + btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off); + btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off); + btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off); + btwrite(geo->crop, BT848_E_CROP+off); + btwrite(geo->vtotal>>8, BT848_VTOTAL_HI); + btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO); +} + +/* ---------------------------------------------------------- */ +/* risc group / risc main loop / dma management */ + +void +bttv_set_dma(struct bttv *btv, int override) +{ + unsigned long cmd; + int capctl; + + btv->cap_ctl = 0; + if (NULL != btv->curr.top) btv->cap_ctl |= 0x02; + if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01; + if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c; + + capctl = 0; + capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */ + capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */ + capctl |= override; + + d2printk(KERN_DEBUG + "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n", + btv->c.nr,capctl,btv->loop_irq, + btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0, + btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, + btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0, + btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); + + cmd = BT848_RISC_JUMP; + if (btv->loop_irq) { + cmd |= BT848_RISC_IRQ; + cmd |= (btv->loop_irq & 0x0f) << 16; + cmd |= (~btv->loop_irq & 0x0f) << 20; + } + if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) { + mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT); + } else { + del_timer(&btv->timeout); + } + btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); + + btaor(capctl, ~0x0f, BT848_CAP_CTL); + if (capctl) { + if (btv->dma_on) + return; + btwrite(btv->main.dma, BT848_RISC_STRT_ADD); + btor(3, BT848_GPIO_DMA_CTL); + btv->dma_on = 1; + } else { + if (!btv->dma_on) + return; + btand(~3, BT848_GPIO_DMA_CTL); + btv->dma_on = 0; + } + return; +} + +int +bttv_risc_init_main(struct bttv *btv) +{ + int rc; + + if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0) + return rc; + dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n", + btv->c.nr,(unsigned long long)btv->main.dma); + + btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | + BT848_FIFO_STATUS_VRE); + btv->main.cpu[1] = cpu_to_le32(0); + btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2)); + + /* top field */ + btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2)); + btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2)); + + btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | + BT848_FIFO_STATUS_VRO); + btv->main.cpu[9] = cpu_to_le32(0); + + /* bottom field */ + btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2)); + btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2)); + + /* jump back to top field */ + btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2)); + + return 0; +} + +int +bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, + int irqflags) +{ + unsigned long cmd; + unsigned long next = btv->main.dma + ((slot+2) << 2); + + if (NULL == risc) { + d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n", + btv->c.nr,risc,slot); + btv->main.cpu[slot+1] = cpu_to_le32(next); + } else { + d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n", + btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags); + cmd = BT848_RISC_JUMP; + if (irqflags) { + cmd |= BT848_RISC_IRQ; + cmd |= (irqflags & 0x0f) << 16; + cmd |= (~irqflags & 0x0f) << 20; + } + risc->jmp[0] = cpu_to_le32(cmd); + risc->jmp[1] = cpu_to_le32(next); + btv->main.cpu[slot+1] = cpu_to_le32(risc->dma); + } + return 0; +} + +void +bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf) +{ + BUG_ON(in_interrupt()); + videobuf_waiton(&buf->vb,0,0); + videobuf_dma_unmap(q, &buf->vb.dma); + videobuf_dma_free(&buf->vb.dma); + btcx_riscmem_free(btv->c.pci,&buf->bottom); + btcx_riscmem_free(btv->c.pci,&buf->top); + buf->vb.state = STATE_NEEDS_INIT; +} + +int +bttv_buffer_activate_vbi(struct bttv *btv, + struct bttv_buffer *vbi) +{ + /* vbi capture */ + if (vbi) { + vbi->vb.state = STATE_ACTIVE; + list_del(&vbi->vb.queue); + bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top, 0); + bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4); + } else { + bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0); + bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0); + } + return 0; +} + +int +bttv_buffer_activate_video(struct bttv *btv, + struct bttv_buffer_set *set) +{ + /* video capture */ + if (NULL != set->top && NULL != set->bottom) { + if (set->top == set->bottom) { + set->top->vb.state = STATE_ACTIVE; + if (set->top->vb.queue.next) + list_del(&set->top->vb.queue); + } else { + set->top->vb.state = STATE_ACTIVE; + set->bottom->vb.state = STATE_ACTIVE; + if (set->top->vb.queue.next) + list_del(&set->top->vb.queue); + if (set->bottom->vb.queue.next) + list_del(&set->bottom->vb.queue); + } + bttv_apply_geo(btv, &set->top->geo, 1); + bttv_apply_geo(btv, &set->bottom->geo,0); + bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, + set->top_irq); + bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, + set->frame_irq); + btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f), + ~0xff, BT848_COLOR_FMT); + btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05), + ~0x0f, BT848_COLOR_CTL); + } else if (NULL != set->top) { + set->top->vb.state = STATE_ACTIVE; + if (set->top->vb.queue.next) + list_del(&set->top->vb.queue); + bttv_apply_geo(btv, &set->top->geo,1); + bttv_apply_geo(btv, &set->top->geo,0); + bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, + set->frame_irq); + bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0); + btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT); + btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL); + } else if (NULL != set->bottom) { + set->bottom->vb.state = STATE_ACTIVE; + if (set->bottom->vb.queue.next) + list_del(&set->bottom->vb.queue); + bttv_apply_geo(btv, &set->bottom->geo,1); + bttv_apply_geo(btv, &set->bottom->geo,0); + bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); + bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, + set->frame_irq); + btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT); + btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL); + } else { + bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); + bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0); + } + return 0; +} + +/* ---------------------------------------------------------- */ + +/* calculate geometry, build risc code */ +int +bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) +{ + const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm; + + dprintk(KERN_DEBUG + "bttv%d: buffer field: %s format: %s size: %dx%d\n", + btv->c.nr, v4l2_field_names[buf->vb.field], + buf->fmt->name, buf->vb.width, buf->vb.height); + + /* packed pixel modes */ + if (buf->fmt->flags & FORMAT_FLAGS_PACKED) { + int bpl = (buf->fmt->depth >> 3) * buf->vb.width; + int bpf = bpl * (buf->vb.height >> 1); + + bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height, + V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm); + + switch (buf->vb.field) { + case V4L2_FIELD_TOP: + bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, + 0,bpl,0,buf->vb.height); + break; + case V4L2_FIELD_BOTTOM: + bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, + 0,bpl,0,buf->vb.height); + break; + case V4L2_FIELD_INTERLACED: + bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, + 0,bpl,bpl,buf->vb.height >> 1); + bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, + bpl,bpl,bpl,buf->vb.height >> 1); + break; + case V4L2_FIELD_SEQ_TB: + bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, + 0,bpl,0,buf->vb.height >> 1); + bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, + bpf,bpl,0,buf->vb.height >> 1); + break; + default: + BUG(); + } + } + + /* planar modes */ + if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) { + int uoffset, voffset; + int ypadding, cpadding, lines; + + /* calculate chroma offsets */ + uoffset = buf->vb.width * buf->vb.height; + voffset = buf->vb.width * buf->vb.height; + if (buf->fmt->flags & FORMAT_FLAGS_CrCb) { + /* Y-Cr-Cb plane order */ + uoffset >>= buf->fmt->hshift; + uoffset >>= buf->fmt->vshift; + uoffset += voffset; + } else { + /* Y-Cb-Cr plane order */ + voffset >>= buf->fmt->hshift; + voffset >>= buf->fmt->vshift; + voffset += uoffset; + } + + switch (buf->vb.field) { + case V4L2_FIELD_TOP: + bttv_calc_geo(btv,&buf->geo,buf->vb.width, + buf->vb.height,0,buf->tvnorm); + bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist, + 0,buf->vb.width,0,buf->vb.height, + uoffset,voffset,buf->fmt->hshift, + buf->fmt->vshift,0); + break; + case V4L2_FIELD_BOTTOM: + bttv_calc_geo(btv,&buf->geo,buf->vb.width, + buf->vb.height,0,buf->tvnorm); + bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist, + 0,buf->vb.width,0,buf->vb.height, + uoffset,voffset,buf->fmt->hshift, + buf->fmt->vshift,0); + break; + case V4L2_FIELD_INTERLACED: + bttv_calc_geo(btv,&buf->geo,buf->vb.width, + buf->vb.height,1,buf->tvnorm); + lines = buf->vb.height >> 1; + ypadding = buf->vb.width; + cpadding = buf->vb.width >> buf->fmt->hshift; + bttv_risc_planar(btv,&buf->top, + buf->vb.dma.sglist, + 0,buf->vb.width,ypadding,lines, + uoffset,voffset, + buf->fmt->hshift, + buf->fmt->vshift, + cpadding); + bttv_risc_planar(btv,&buf->bottom, + buf->vb.dma.sglist, + ypadding,buf->vb.width,ypadding,lines, + uoffset+cpadding, + voffset+cpadding, + buf->fmt->hshift, + buf->fmt->vshift, + cpadding); + break; + case V4L2_FIELD_SEQ_TB: + bttv_calc_geo(btv,&buf->geo,buf->vb.width, + buf->vb.height,1,buf->tvnorm); + lines = buf->vb.height >> 1; + ypadding = buf->vb.width; + cpadding = buf->vb.width >> buf->fmt->hshift; + bttv_risc_planar(btv,&buf->top, + buf->vb.dma.sglist, + 0,buf->vb.width,0,lines, + uoffset >> 1, + voffset >> 1, + buf->fmt->hshift, + buf->fmt->vshift, + 0); + bttv_risc_planar(btv,&buf->bottom, + buf->vb.dma.sglist, + lines * ypadding,buf->vb.width,0,lines, + lines * ypadding + (uoffset >> 1), + lines * ypadding + (voffset >> 1), + buf->fmt->hshift, + buf->fmt->vshift, + 0); + break; + default: + BUG(); + } + } + + /* raw data */ + if (buf->fmt->flags & FORMAT_FLAGS_RAW) { + /* build risc code */ + buf->vb.field = V4L2_FIELD_SEQ_TB; + bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight, + 1,buf->tvnorm); + bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist, + 0, RAW_BPL, 0, RAW_LINES); + bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist, + buf->vb.size/2 , RAW_BPL, 0, RAW_LINES); + } + + /* copy format info */ + buf->btformat = buf->fmt->btformat; + buf->btswap = buf->fmt->btswap; + return 0; +} + +/* ---------------------------------------------------------- */ + +/* calculate geometry, build risc code */ +int +bttv_overlay_risc(struct bttv *btv, + struct bttv_overlay *ov, + const struct bttv_format *fmt, + struct bttv_buffer *buf) +{ + /* check interleave, bottom+top fields */ + dprintk(KERN_DEBUG + "bttv%d: overlay fields: %s format: %s size: %dx%d\n", + btv->c.nr, v4l2_field_names[buf->vb.field], + fmt->name,ov->w.width,ov->w.height); + + /* calculate geometry */ + bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height, + V4L2_FIELD_HAS_BOTH(ov->field), ov->tvnorm); + + /* build risc code */ + switch (ov->field) { + case V4L2_FIELD_TOP: + bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0); + break; + case V4L2_FIELD_BOTTOM: + bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0); + break; + case V4L2_FIELD_INTERLACED: + bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 1); + bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0); + break; + default: + BUG(); + } + + /* copy format info */ + buf->btformat = fmt->btformat; + buf->btswap = fmt->btswap; + buf->vb.field = ov->field; + return 0; +} + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c new file mode 100644 index 000000000000..e20ff238e409 --- /dev/null +++ b/drivers/media/video/bt8xx/bttv-vbi.c @@ -0,0 +1,221 @@ +/* + + bttv - Bt848 frame grabber driver + vbi interface + + (c) 2002 Gerd Knorr + + 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 +#include "bttvp.h" + +/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate: + bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC + HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge + of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */ +#define VBI_OFFSET ((64 + 0) * 2) + +#define VBI_DEFLINES 16 +#define VBI_MAXLINES 32 + +static unsigned int vbibufs = 4; +static unsigned int vbi_debug = 0; + +module_param(vbibufs, int, 0444); +module_param(vbi_debug, int, 0644); +MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32, default 4"); +MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)"); + +#ifdef dprintk +# undef dprintk +#endif +#define dprintk(fmt, arg...) if (vbi_debug) \ + printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg) + +/* ----------------------------------------------------------------------- */ +/* vbi risc code + mm */ + +static int +vbi_buffer_risc(struct bttv *btv, struct bttv_buffer *buf, int lines) +{ + int bpl = 2048; + + bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist, + 0, bpl-4, 4, lines); + bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist, + lines * bpl, bpl-4, 4, lines); + return 0; +} + +static int vbi_buffer_setup(struct videobuf_queue *q, + unsigned int *count, unsigned int *size) +{ + struct bttv_fh *fh = q->priv_data; + struct bttv *btv = fh->btv; + + if (0 == *count) + *count = vbibufs; + *size = fh->lines * 2 * 2048; + dprintk("setup: lines=%d\n",fh->lines); + return 0; +} + +static int vbi_buffer_prepare(struct videobuf_queue *q, + struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct bttv_fh *fh = q->priv_data; + struct bttv *btv = fh->btv; + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + int rc; + + buf->vb.size = fh->lines * 2 * 2048; + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + if (STATE_NEEDS_INIT == buf->vb.state) { + if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL))) + goto fail; + if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines))) + goto fail; + } + buf->vb.state = STATE_PREPARED; + buf->vb.field = field; + dprintk("buf prepare %p: top=%p bottom=%p field=%s\n", + vb, &buf->top, &buf->bottom, + v4l2_field_names[buf->vb.field]); + return 0; + + fail: + bttv_dma_free(q,btv,buf); + return rc; +} + +static void +vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) +{ + struct bttv_fh *fh = q->priv_data; + struct bttv *btv = fh->btv; + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + + dprintk("queue %p\n",vb); + buf->vb.state = STATE_QUEUED; + list_add_tail(&buf->vb.queue,&btv->vcapture); + if (NULL == btv->cvbi) { + fh->btv->loop_irq |= 4; + bttv_set_dma(btv,0x0c); + } +} + +static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) +{ + struct bttv_fh *fh = q->priv_data; + struct bttv *btv = fh->btv; + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + + dprintk("free %p\n",vb); + bttv_dma_free(&fh->cap,fh->btv,buf); +} + +struct videobuf_queue_ops bttv_vbi_qops = { + .buf_setup = vbi_buffer_setup, + .buf_prepare = vbi_buffer_prepare, + .buf_queue = vbi_buffer_queue, + .buf_release = vbi_buffer_release, +}; + +/* ----------------------------------------------------------------------- */ + +void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines) +{ + int vdelay; + + if (lines < 1) + lines = 1; + if (lines > VBI_MAXLINES) + lines = VBI_MAXLINES; + fh->lines = lines; + + vdelay = btread(BT848_E_VDELAY_LO); + if (vdelay < lines*2) { + vdelay = lines*2; + btwrite(vdelay,BT848_E_VDELAY_LO); + btwrite(vdelay,BT848_O_VDELAY_LO); + } +} + +void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f) +{ + const struct bttv_tvnorm *tvnorm; + s64 count0,count1,count; + + tvnorm = &bttv_tvnorms[fh->btv->tvnorm]; + f->type = V4L2_BUF_TYPE_VBI_CAPTURE; + f->fmt.vbi.sampling_rate = tvnorm->Fsc; + f->fmt.vbi.samples_per_line = 2048; + f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; + f->fmt.vbi.offset = VBI_OFFSET; + f->fmt.vbi.flags = 0; + + /* s64 to prevent overflow. */ + count0 = (s64) f->fmt.vbi.start[0] + f->fmt.vbi.count[0] + - tvnorm->vbistart[0]; + count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1] + - tvnorm->vbistart[1]; + count = clamp (max (count0, count1), 1LL, (s64) VBI_MAXLINES); + + f->fmt.vbi.start[0] = tvnorm->vbistart[0]; + f->fmt.vbi.start[1] = tvnorm->vbistart[1]; + f->fmt.vbi.count[0] = count; + f->fmt.vbi.count[1] = count; + + f->fmt.vbi.reserved[0] = 0; + f->fmt.vbi.reserved[1] = 0; +} + +void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f) +{ + const struct bttv_tvnorm *tvnorm; + + tvnorm = &bttv_tvnorms[fh->btv->tvnorm]; + memset(f,0,sizeof(*f)); + f->type = V4L2_BUF_TYPE_VBI_CAPTURE; + f->fmt.vbi.sampling_rate = tvnorm->Fsc; + f->fmt.vbi.samples_per_line = 2048; + f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; + f->fmt.vbi.offset = VBI_OFFSET; + f->fmt.vbi.start[0] = tvnorm->vbistart[0]; + f->fmt.vbi.start[1] = tvnorm->vbistart[1]; + f->fmt.vbi.count[0] = fh->lines; + f->fmt.vbi.count[1] = fh->lines; + f->fmt.vbi.flags = 0; +} + +/* ----------------------------------------------------------------------- */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h new file mode 100644 index 000000000000..9908c8e0c951 --- /dev/null +++ b/drivers/media/video/bt8xx/bttv.h @@ -0,0 +1,407 @@ +/* + * + * bttv - Bt848 frame grabber driver + * + * card ID's and external interfaces of the bttv driver + * basically stuff needed by other drivers (i2c, lirc, ...) + * and is supported not to change much over time. + * + * Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) + * (c) 1999,2000 Gerd Knorr + * + */ + +#ifndef _BTTV_H_ +#define _BTTV_H_ + +#include +#include +#include +#include + +/* ---------------------------------------------------------- */ +/* exported by bttv-cards.c */ + +#define BTTV_BOARD_UNKNOWN 0x00 +#define BTTV_BOARD_MIRO 0x01 +#define BTTV_BOARD_HAUPPAUGE 0x02 +#define BTTV_BOARD_STB 0x03 +#define BTTV_BOARD_INTEL 0x04 +#define BTTV_BOARD_DIAMOND 0x05 +#define BTTV_BOARD_AVERMEDIA 0x06 +#define BTTV_BOARD_MATRIX_VISION 0x07 +#define BTTV_BOARD_FLYVIDEO 0x08 +#define BTTV_BOARD_TURBOTV 0x09 +#define BTTV_BOARD_HAUPPAUGE878 0x0a +#define BTTV_BOARD_MIROPRO 0x0b +#define BTTV_BOARD_ADSTECH_TV 0x0c +#define BTTV_BOARD_AVERMEDIA98 0x0d +#define BTTV_BOARD_VHX 0x0e +#define BTTV_BOARD_ZOLTRIX 0x0f +#define BTTV_BOARD_PIXVIEWPLAYTV 0x10 +#define BTTV_BOARD_WINVIEW_601 0x11 +#define BTTV_BOARD_AVEC_INTERCAP 0x12 +#define BTTV_BOARD_LIFE_FLYKIT 0x13 +#define BTTV_BOARD_CEI_RAFFLES 0x14 +#define BTTV_BOARD_CONFERENCETV 0x15 +#define BTTV_BOARD_PHOEBE_TVMAS 0x16 +#define BTTV_BOARD_MODTEC_205 0x17 +#define BTTV_BOARD_MAGICTVIEW061 0x18 +#define BTTV_BOARD_VOBIS_BOOSTAR 0x19 +#define BTTV_BOARD_HAUPPAUG_WCAM 0x1a +#define BTTV_BOARD_MAXI 0x1b +#define BTTV_BOARD_TERRATV 0x1c +#define BTTV_BOARD_PXC200 0x1d +#define BTTV_BOARD_FLYVIDEO_98 0x1e +#define BTTV_BOARD_IPROTV 0x1f +#define BTTV_BOARD_INTEL_C_S_PCI 0x20 +#define BTTV_BOARD_TERRATVALUE 0x21 +#define BTTV_BOARD_WINFAST2000 0x22 +#define BTTV_BOARD_CHRONOS_VS2 0x23 +#define BTTV_BOARD_TYPHOON_TVIEW 0x24 +#define BTTV_BOARD_PXELVWPLTVPRO 0x25 +#define BTTV_BOARD_MAGICTVIEW063 0x26 +#define BTTV_BOARD_PINNACLE 0x27 +#define BTTV_BOARD_STB2 0x28 +#define BTTV_BOARD_AVPHONE98 0x29 +#define BTTV_BOARD_PV951 0x2a +#define BTTV_BOARD_ONAIR_TV 0x2b +#define BTTV_BOARD_SIGMA_TVII_FM 0x2c +#define BTTV_BOARD_MATRIX_VISION2 0x2d +#define BTTV_BOARD_ZOLTRIX_GENIE 0x2e +#define BTTV_BOARD_TERRATVRADIO 0x2f +#define BTTV_BOARD_DYNALINK 0x30 +#define BTTV_BOARD_GVBCTV3PCI 0x31 +#define BTTV_BOARD_PXELVWPLTVPAK 0x32 +#define BTTV_BOARD_EAGLE 0x33 +#define BTTV_BOARD_PINNACLEPRO 0x34 +#define BTTV_BOARD_TVIEW_RDS_FM 0x35 +#define BTTV_BOARD_LIFETEC_9415 0x36 +#define BTTV_BOARD_BESTBUY_EASYTV 0x37 +#define BTTV_BOARD_FLYVIDEO_98FM 0x38 +#define BTTV_BOARD_GRANDTEC 0x39 +#define BTTV_BOARD_ASKEY_CPH060 0x3a +#define BTTV_BOARD_ASKEY_CPH03X 0x3b +#define BTTV_BOARD_MM100PCTV 0x3c +#define BTTV_BOARD_GMV1 0x3d +#define BTTV_BOARD_BESTBUY_EASYTV2 0x3e +#define BTTV_BOARD_ATI_TVWONDER 0x3f +#define BTTV_BOARD_ATI_TVWONDERVE 0x40 +#define BTTV_BOARD_FLYVIDEO2000 0x41 +#define BTTV_BOARD_TERRATVALUER 0x42 +#define BTTV_BOARD_GVBCTV4PCI 0x43 +#define BTTV_BOARD_VOODOOTV_FM 0x44 +#define BTTV_BOARD_AIMMS 0x45 +#define BTTV_BOARD_PV_BT878P_PLUS 0x46 +#define BTTV_BOARD_FLYVIDEO98EZ 0x47 +#define BTTV_BOARD_PV_BT878P_9B 0x48 +#define BTTV_BOARD_SENSORAY311 0x49 +#define BTTV_BOARD_RV605 0x4a +#define BTTV_BOARD_POWERCLR_MTV878 0x4b +#define BTTV_BOARD_WINDVR 0x4c +#define BTTV_BOARD_GRANDTEC_MULTI 0x4d +#define BTTV_BOARD_KWORLD 0x4e +#define BTTV_BOARD_DSP_TCVIDEO 0x4f +#define BTTV_BOARD_HAUPPAUGEPVR 0x50 +#define BTTV_BOARD_GVBCTV5PCI 0x51 +#define BTTV_BOARD_OSPREY1x0 0x52 +#define BTTV_BOARD_OSPREY1x0_848 0x53 +#define BTTV_BOARD_OSPREY101_848 0x54 +#define BTTV_BOARD_OSPREY1x1 0x55 +#define BTTV_BOARD_OSPREY1x1_SVID 0x56 +#define BTTV_BOARD_OSPREY2xx 0x57 +#define BTTV_BOARD_OSPREY2x0_SVID 0x58 +#define BTTV_BOARD_OSPREY2x0 0x59 +#define BTTV_BOARD_OSPREY500 0x5a +#define BTTV_BOARD_OSPREY540 0x5b +#define BTTV_BOARD_OSPREY2000 0x5c +#define BTTV_BOARD_IDS_EAGLE 0x5d +#define BTTV_BOARD_PINNACLESAT 0x5e +#define BTTV_BOARD_FORMAC_PROTV 0x5f +#define BTTV_BOARD_MACHTV 0x60 +#define BTTV_BOARD_EURESYS_PICOLO 0x61 +#define BTTV_BOARD_PV150 0x62 +#define BTTV_BOARD_AD_TVK503 0x63 +#define BTTV_BOARD_HERCULES_SM_TV 0x64 +#define BTTV_BOARD_PACETV 0x65 +#define BTTV_BOARD_IVC200 0x66 +#define BTTV_BOARD_XGUARD 0x67 +#define BTTV_BOARD_NEBULA_DIGITV 0x68 +#define BTTV_BOARD_PV143 0x69 +#define BTTV_BOARD_VD009X1_MINIDIN 0x6a +#define BTTV_BOARD_VD009X1_COMBI 0x6b +#define BTTV_BOARD_VD009_MINIDIN 0x6c +#define BTTV_BOARD_VD009_COMBI 0x6d +#define BTTV_BOARD_IVC100 0x6e +#define BTTV_BOARD_IVC120 0x6f +#define BTTV_BOARD_PC_HDTV 0x70 +#define BTTV_BOARD_TWINHAN_DST 0x71 +#define BTTV_BOARD_WINFASTVC100 0x72 +#define BTTV_BOARD_TEV560 0x73 +#define BTTV_BOARD_SIMUS_GVC1100 0x74 +#define BTTV_BOARD_NGSTV_PLUS 0x75 +#define BTTV_BOARD_LMLBT4 0x76 +#define BTTV_BOARD_TEKRAM_M205 0x77 +#define BTTV_BOARD_CONTVFMI 0x78 +#define BTTV_BOARD_PICOLO_TETRA_CHIP 0x79 +#define BTTV_BOARD_SPIRIT_TV 0x7a +#define BTTV_BOARD_AVDVBT_771 0x7b +#define BTTV_BOARD_AVDVBT_761 0x7c +#define BTTV_BOARD_MATRIX_VISIONSQ 0x7d +#define BTTV_BOARD_MATRIX_VISIONSLC 0x7e +#define BTTV_BOARD_APAC_VIEWCOMP 0x7f +#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 +#define BTTV_BOARD_VGEAR_MYVCD 0x81 +#define BTTV_BOARD_SUPER_TV 0x82 +#define BTTV_BOARD_TIBET_CS16 0x83 +#define BTTV_BOARD_KODICOM_4400R 0x84 +#define BTTV_BOARD_KODICOM_4400R_SL 0x85 +#define BTTV_BOARD_ADLINK_RTV24 0x86 +#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 +#define BTTV_BOARD_ACORP_Y878F 0x88 +#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 +#define BTTV_BOARD_PV_BT878P_2E 0x8a +#define BTTV_BOARD_PV_M4900 0x8b +#define BTTV_BOARD_OSPREY440 0x8c +#define BTTV_BOARD_ASOUND_SKYEYE 0x8d +#define BTTV_BOARD_SABRENT_TVFM 0x8e +#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f +#define BTTV_BOARD_MACHTV_MAGICTV 0x90 + +/* i2c address list */ +#define I2C_TSA5522 0xc2 +#define I2C_TDA7432 0x8a +#define I2C_BT832_ALT1 0x88 +#define I2C_BT832_ALT2 0x8a // alternate setting +#define I2C_TDA8425 0x82 +#define I2C_TDA9840 0x84 +#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */ +#define I2C_TDA9874 0xb0 /* also used by 9875 */ +#define I2C_TDA9875 0xb0 +#define I2C_HAUPEE 0xa0 +#define I2C_STBEE 0xae +#define I2C_VHX 0xc0 +#define I2C_MSP3400 0x80 +#define I2C_MSP3400_ALT 0x88 +#define I2C_TEA6300 0x80 /* also used by 6320 */ +#define I2C_DPL3518 0x84 +#define I2C_TDA9887 0x86 + +/* more card-specific defines */ +#define PT2254_L_CHANNEL 0x10 +#define PT2254_R_CHANNEL 0x08 +#define PT2254_DBS_IN_2 0x400 +#define PT2254_DBS_IN_10 0x20000 +#define WINVIEW_PT2254_CLK 0x40 +#define WINVIEW_PT2254_DATA 0x20 +#define WINVIEW_PT2254_STROBE 0x80 + +/* digital_mode */ +#define DIGITAL_MODE_VIDEO 1 +#define DIGITAL_MODE_CAMERA 2 + +struct bttv_core { + /* device structs */ + struct pci_dev *pci; + struct i2c_adapter i2c_adap; + struct list_head subs; /* struct bttv_sub_device */ + + /* device config */ + unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ + unsigned int type; /* card type (pointer into tvcards[]) */ + char name[8]; /* dev name */ +}; + +struct bttv; + + +struct bttv_ir { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + + /* Usual gpio signalling */ + + u32 mask_keycode; + u32 mask_keydown; + u32 mask_keyup; + u32 polling; + u32 last_gpio; + struct work_struct work; + struct timer_list timer; + + /* RC5 gpio */ + u32 rc5_gpio; + struct timer_list timer_end; /* timer_end for code completion */ + struct timer_list timer_keyup; /* timer_end for key release */ + u32 last_rc5; /* last good rc5 code */ + u32 last_bit; /* last raw bit seen */ + u32 code; /* raw code under construction */ + struct timeval base_time; /* time of last seen code */ + int active; /* building raw code */ +}; + +struct tvcard +{ + char *name; + unsigned int video_inputs; + unsigned int audio_inputs; + unsigned int tuner; + unsigned int svhs; + unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO + u32 gpiomask; + u32 muxsel[16]; + u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ + u32 gpiomask2; /* GPIO MUX mask */ + + /* i2c audio flags */ + unsigned int no_msp34xx:1; + unsigned int no_tda9875:1; + unsigned int no_tda7432:1; + unsigned int needs_tvaudio:1; + unsigned int msp34xx_alt:1; + + /* flag: video pci function is unused */ + unsigned int no_video:1; + unsigned int has_dvb:1; + unsigned int has_remote:1; + unsigned int no_gpioirq:1; + + /* other settings */ + unsigned int pll; +#define PLL_NONE 0 +#define PLL_28 1 +#define PLL_35 2 + + unsigned int tuner_type; + unsigned int tuner_addr; + unsigned int radio_addr; + + unsigned int has_radio; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + void (*muxsel_hook)(struct bttv *btv, unsigned int input); +}; + +extern struct tvcard bttv_tvcards[]; + +/* identification / initialization of the card */ +extern void bttv_idcard(struct bttv *btv); +extern void bttv_init_card1(struct bttv *btv); +extern void bttv_init_card2(struct bttv *btv); + +/* card-specific funtions */ +extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); +extern void bttv_tda9880_setnorm(struct bttv *btv, int norm); + +/* extra tweaks for some chipsets */ +extern void bttv_check_chipset(void); +extern int bttv_handle_chipset(struct bttv *btv); + +/* ---------------------------------------------------------- */ +/* exported by bttv-if.c */ + +/* this obsolete -- please use the sysfs-based + interface below for new code */ + +/* returns card type + card ID (for bt878-based ones) + for possible values see lines below beginning with #define BTTV_BOARD_UNKNOWN + returns negative value if error occurred +*/ +extern int bttv_get_cardinfo(unsigned int card, int *type, + unsigned int *cardid); +extern struct pci_dev* bttv_get_pcidev(unsigned int card); + +/* obsolete, use bttv_get_cardinfo instead */ +extern int bttv_get_id(unsigned int card); + +/* sets GPOE register (BT848_GPIO_OUT_EN) to new value: + data | (current_GPOE_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_gpio_enable(unsigned int card, + unsigned long mask, unsigned long data); + +/* fills data with GPDATA register contents + returns negative value if error occurred +*/ +extern int bttv_read_gpio(unsigned int card, unsigned long *data); + +/* sets GPDATA register to new value: + (data & mask) | (current_GPDATA_value & ~mask) + returns negative value if error occurred +*/ +extern int bttv_write_gpio(unsigned int card, + unsigned long mask, unsigned long data); + +/* returns pointer to task queue which can be used as parameter to + interruptible_sleep_on + in interrupt handler if BT848_INT_GPINT bit is set - this queue is activated + (wake_up_interruptible) and following call to the function bttv_read_gpio + should return new value of GPDATA, + returns NULL value if error occurred or queue is not available + WARNING: because there is no buffer for GPIO data, one MUST + process data ASAP +*/ +extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card); + +/* call i2c clients +*/ +extern void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg); + + + +/* ---------------------------------------------------------- */ +/* sysfs/driver-moded based gpio access interface */ + + +struct bttv_sub_device { + struct device dev; + struct bttv_core *core; + struct list_head list; +}; +#define to_bttv_sub_dev(x) container_of((x), struct bttv_sub_device, dev) + +struct bttv_sub_driver { + struct device_driver drv; + char wanted[BUS_ID_SIZE]; + int (*probe)(struct bttv_sub_device *sub); + void (*remove)(struct bttv_sub_device *sub); + void (*gpio_irq)(struct bttv_sub_device *sub); +}; +#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) + +int bttv_sub_register(struct bttv_sub_driver *drv, char *wanted); +int bttv_sub_unregister(struct bttv_sub_driver *drv); + +/* gpio access functions */ +void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits); +u32 bttv_gpio_read(struct bttv_core *core); +void bttv_gpio_write(struct bttv_core *core, u32 value); +void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits); + +#define gpio_inout(mask,bits) bttv_gpio_inout(&btv->c, mask, bits) +#define gpio_read() bttv_gpio_read(&btv->c) +#define gpio_write(value) bttv_gpio_write(&btv->c, value) +#define gpio_bits(mask,bits) bttv_gpio_bits(&btv->c, mask, bits) + + +/* ---------------------------------------------------------- */ +/* i2c */ + +extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); +extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for); +extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, + unsigned char b2, int both); +extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr); + +extern int bttv_input_init(struct bttv *dev); +extern void bttv_input_fini(struct bttv *dev); +extern void bttv_input_irq(struct bttv *dev); + +#endif /* _BTTV_H_ */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h new file mode 100644 index 000000000000..12223a203960 --- /dev/null +++ b/drivers/media/video/bt8xx/bttvp.h @@ -0,0 +1,411 @@ +/* + + bttv - Bt848 frame grabber driver + + bttv's *private* header file -- nobody other than bttv itself + should ever include this file. + + (c) 2000-2002 Gerd Knorr + + 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. +*/ + +#ifndef _BTTVP_H_ +#define _BTTVP_H_ + +#include +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include "bt848.h" +#include "bttv.h" +#include "btcx-risc.h" + +#ifdef __KERNEL__ + +#define FORMAT_FLAGS_DITHER 0x01 +#define FORMAT_FLAGS_PACKED 0x02 +#define FORMAT_FLAGS_PLANAR 0x04 +#define FORMAT_FLAGS_RAW 0x08 +#define FORMAT_FLAGS_CrCb 0x10 + +#define RISC_SLOT_O_VBI 4 +#define RISC_SLOT_O_FIELD 6 +#define RISC_SLOT_E_VBI 10 +#define RISC_SLOT_E_FIELD 12 +#define RISC_SLOT_LOOP 14 + +#define RESOURCE_OVERLAY 1 +#define RESOURCE_VIDEO 2 +#define RESOURCE_VBI 4 + +#define RAW_LINES 640 +#define RAW_BPL 1024 + +#define UNSET (-1U) + +#define clamp(x, low, high) min (max (low, x), high) + +/* ---------------------------------------------------------- */ + +struct bttv_tvnorm { + int v4l2_id; + char *name; + u32 Fsc; + u16 swidth, sheight; /* scaled standard width, height */ + u16 totalwidth; + u8 adelay, bdelay, iform; + u32 scaledtwidth; + u16 hdelayx1, hactivex1; + u16 vdelay; + u8 vbipack; + u16 vtotal; + int sram; + /* ITU-R frame line number of the first VBI line we can + capture, of the first and second field. */ + u16 vbistart[2]; +}; +extern const struct bttv_tvnorm bttv_tvnorms[]; + +struct bttv_format { + char *name; + int palette; /* video4linux 1 */ + int fourcc; /* video4linux 2 */ + int btformat; /* BT848_COLOR_FMT_* */ + int btswap; /* BT848_COLOR_CTL_* */ + int depth; /* bit/pixel */ + int flags; + int hshift,vshift; /* for planar modes */ +}; + +/* ---------------------------------------------------------- */ + +struct bttv_geometry { + u8 vtc,crop,comb; + u16 width,hscale,hdelay; + u16 sheight,vscale,vdelay,vtotal; +}; + +struct bttv_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + /* bttv specific */ + const struct bttv_format *fmt; + int tvnorm; + int btformat; + int btswap; + struct bttv_geometry geo; + struct btcx_riscmem top; + struct btcx_riscmem bottom; +}; + +struct bttv_buffer_set { + struct bttv_buffer *top; /* top field buffer */ + struct bttv_buffer *bottom; /* bottom field buffer */ + unsigned int top_irq; + unsigned int frame_irq; +}; + +struct bttv_overlay { + int tvnorm; + struct v4l2_rect w; + enum v4l2_field field; + struct v4l2_clip *clips; + int nclips; + int setup_ok; +}; + +struct bttv_fh { + struct bttv *btv; + int resources; +#ifdef VIDIOC_G_PRIORITY + enum v4l2_priority prio; +#endif + enum v4l2_buf_type type; + + /* video capture */ + struct videobuf_queue cap; + const struct bttv_format *fmt; + int width; + int height; + + /* current settings */ + const struct bttv_format *ovfmt; + struct bttv_overlay ov; + + /* video overlay */ + struct videobuf_queue vbi; + int lines; +}; + +/* ---------------------------------------------------------- */ +/* bttv-risc.c */ + +/* risc code generators - capture */ +int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int offset, unsigned int bpl, + unsigned int pitch, unsigned int lines); + +/* control dma register + risc main loop */ +void bttv_set_dma(struct bttv *btv, int override); +int bttv_risc_init_main(struct bttv *btv); +int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, + int irqflags); + +/* capture buffer handling */ +int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf); +int bttv_buffer_activate_video(struct bttv *btv, + struct bttv_buffer_set *set); +int bttv_buffer_activate_vbi(struct bttv *btv, + struct bttv_buffer *vbi); +void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv, + struct bttv_buffer *buf); + +/* overlay handling */ +int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, + const struct bttv_format *fmt, + struct bttv_buffer *buf); + + +/* ---------------------------------------------------------- */ +/* bttv-vbi.c */ + +void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f); +void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f); +void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines); + +extern struct videobuf_queue_ops bttv_vbi_qops; + +/* ---------------------------------------------------------- */ +/* bttv-gpio.c */ + + +extern struct bus_type bttv_sub_bus_type; +int bttv_sub_add_device(struct bttv_core *core, char *name); +int bttv_sub_del_devices(struct bttv_core *core); +void bttv_gpio_irq(struct bttv_core *core); + + +/* ---------------------------------------------------------- */ +/* bttv-driver.c */ + +/* insmod options */ +extern unsigned int bttv_verbose; +extern unsigned int bttv_debug; +extern unsigned int bttv_gpio; +extern void bttv_gpio_tracking(struct bttv *btv, char *comment); +extern int init_bttv_i2c(struct bttv *btv); +extern int fini_bttv_i2c(struct bttv *btv); + +#define bttv_printk if (bttv_verbose) printk +#define dprintk if (bttv_debug >= 1) printk +#define d2printk if (bttv_debug >= 2) printk + +#define BTTV_MAX_FBUF 0x208000 +#define VBIBUF_SIZE (2048*VBI_MAXLINES*2) +#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ +#define BTTV_FREE_IDLE (HZ) /* one second */ + + +struct bttv_pll_info { + unsigned int pll_ifreq; /* PLL input frequency */ + unsigned int pll_ofreq; /* PLL output frequency */ + unsigned int pll_crystal; /* Crystal used for input */ + unsigned int pll_current; /* Currently programmed ofreq */ +}; + +/* for gpio-connected remote control */ +struct bttv_input { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + u32 mask_keycode; + u32 mask_keydown; +}; + +struct bttv_suspend_state { + u32 gpio_enable; + u32 gpio_data; + int disabled; + int loop_irq; + struct bttv_buffer_set video; + struct bttv_buffer *vbi; +}; + +struct bttv { + struct bttv_core c; + + /* pci device config */ + unsigned short id; + unsigned char revision; + unsigned char __iomem *bt848_mmio; /* pointer to mmio */ + + /* card configuration info */ + unsigned int cardid; /* pci subsystem id (bt878 based ones) */ + unsigned int tuner_type; /* tuner chip type */ + unsigned int tda9887_conf; + unsigned int svhs; + struct bttv_pll_info pll; + int triton1; + int gpioirq; + int (*custom_irq)(struct bttv *btv); + + int use_i2c_hw; + + /* old gpio interface */ + wait_queue_head_t gpioq; + int shutdown; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); + + /* new gpio interface */ + spinlock_t gpio_lock; + + /* i2c layer */ + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + int i2c_state, i2c_rc; + int i2c_done; + wait_queue_head_t i2c_queue; + + /* video4linux (1) */ + struct video_device *video_dev; + struct video_device *radio_dev; + struct video_device *vbi_dev; + + /* infrared remote */ + int has_remote; + struct bttv_ir *remote; + + /* locking */ + spinlock_t s_lock; + struct mutex lock; + int resources; + struct mutex reslock; +#ifdef VIDIOC_G_PRIORITY + struct v4l2_prio_state prio; +#endif + + /* video state */ + unsigned int input; + unsigned int audio; + unsigned long freq; + int tvnorm,hue,contrast,bright,saturation; + struct v4l2_framebuffer fbuf; + unsigned int field_count; + + /* various options */ + int opt_combfilter; + int opt_lumafilter; + int opt_automute; + int opt_chroma_agc; + int opt_adc_crush; + int opt_vcr_hack; + int opt_whitecrush_upper; + int opt_whitecrush_lower; + int opt_uv_ratio; + int opt_full_luma_range; + int opt_coring; + + /* radio data/state */ + int has_radio; + int radio_user; + + /* miro/pinnacle + Aimslab VHX + philips matchbox (tea5757 radio tuner) support */ + int has_matchbox; + int mbox_we; + int mbox_data; + int mbox_clk; + int mbox_most; + int mbox_mask; + + /* ISA stuff (Terratec Active Radio Upgrade) */ + int mbox_ior; + int mbox_iow; + int mbox_csel; + + /* risc memory management data + - must aquire s_lock before changing these + - only the irq handler is supported to touch top + bottom + vcurr */ + struct btcx_riscmem main; + struct bttv_buffer *screen; /* overlay */ + struct list_head capture; /* video capture queue */ + struct list_head vcapture; /* vbi capture queue */ + struct bttv_buffer_set curr; /* active buffers */ + struct bttv_buffer *cvbi; /* active vbi buffer */ + int loop_irq; + int new_input; + + unsigned long cap_ctl; + unsigned long dma_on; + struct timer_list timeout; + struct bttv_suspend_state state; + + /* stats */ + unsigned int errors; + unsigned int framedrop; + unsigned int irq_total; + unsigned int irq_me; + + unsigned int users; + struct bttv_fh init; +}; + +/* our devices */ +#define BTTV_MAX 16 +extern unsigned int bttv_num; +extern struct bttv bttvs[BTTV_MAX]; + +/* private ioctls */ +#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) +#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) + +#endif + +#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr)) +#define btread(adr) readl(btv->bt848_mmio+(adr)) + +#define btand(dat,adr) btwrite((dat) & btread(adr), adr) +#define btor(dat,adr) btwrite((dat) | btread(adr), adr) +#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) + +#endif /* _BTTVP_H_ */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c deleted file mode 100644 index abfa6ad857a0..000000000000 --- a/drivers/media/video/bttv-cards.c +++ /dev/null @@ -1,5011 +0,0 @@ -/* - - bttv-cards.c - - this file has configuration informations - card-specific stuff - like the big tvcards array for the most part - - Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) - (c) 1999-2001 Gerd Knorr - - 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 - -#include - -#include "bttvp.h" -#include - -/* fwd decl */ -static void boot_msp34xx(struct bttv *btv, int pin); -static void boot_bt832(struct bttv *btv); -static void hauppauge_eeprom(struct bttv *btv); -static void avermedia_eeprom(struct bttv *btv); -static void osprey_eeprom(struct bttv *btv); -static void modtec_eeprom(struct bttv *btv); -static void init_PXC200(struct bttv *btv); -static void init_RTV24(struct bttv *btv); - -static void winview_audio(struct bttv *btv, struct video_audio *v, int set); -static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set); -static void avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, - int set); -static void avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, - int set); -static void terratv_audio(struct bttv *btv, struct video_audio *v, int set); -static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set); -static void gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set); -static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set); -static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set); -static void fv2000s_audio(struct bttv *btv, struct video_audio *v, int set); -static void windvr_audio(struct bttv *btv, struct video_audio *v, int set); -static void adtvk503_audio(struct bttv *btv, struct video_audio *v, int set); -static void rv605_muxsel(struct bttv *btv, unsigned int input); -static void eagle_muxsel(struct bttv *btv, unsigned int input); -static void xguard_muxsel(struct bttv *btv, unsigned int input); -static void ivc120_muxsel(struct bttv *btv, unsigned int input); -static void gvc1100_muxsel(struct bttv *btv, unsigned int input); - -static void PXC200_muxsel(struct bttv *btv, unsigned int input); - -static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input); -static void picolo_tetra_init(struct bttv *btv); - -static void tibetCS16_muxsel(struct bttv *btv, unsigned int input); -static void tibetCS16_init(struct bttv *btv); - -static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input); -static void kodicom4400r_init(struct bttv *btv); - -static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input); -static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input); - -static int terratec_active_radio_upgrade(struct bttv *btv); -static int tea5757_read(struct bttv *btv); -static int tea5757_write(struct bttv *btv, int value); -static void identify_by_eeprom(struct bttv *btv, - unsigned char eeprom_data[256]); -static int __devinit pvr_boot(struct bttv *btv); - -/* config variables */ -static unsigned int triton1; -static unsigned int vsfx; -static unsigned int latency = UNSET; -int no_overlay=-1; - -static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; -static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; -static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; -static unsigned int svhs[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; -static unsigned int remote[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; -static struct bttv *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL }; -#ifdef MODULE -static unsigned int autoload = 1; -#else -static unsigned int autoload; -#endif -static unsigned int gpiomask = UNSET; -static unsigned int audioall = UNSET; -static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET }; - -/* insmod options */ -module_param(triton1, int, 0444); -module_param(vsfx, int, 0444); -module_param(no_overlay, int, 0444); -module_param(latency, int, 0444); -module_param(gpiomask, int, 0444); -module_param(audioall, int, 0444); -module_param(autoload, int, 0444); - -module_param_array(card, int, NULL, 0444); -module_param_array(pll, int, NULL, 0444); -module_param_array(tuner, int, NULL, 0444); -module_param_array(svhs, int, NULL, 0444); -module_param_array(remote, int, NULL, 0444); -module_param_array(audiomux, int, NULL, 0444); - -MODULE_PARM_DESC(triton1,"set ETBF pci config bit " - "[enable bug compatibility for triton1 + others]"); -MODULE_PARM_DESC(vsfx,"set VSFX pci config bit " - "[yet another chipset flaw workaround]"); -MODULE_PARM_DESC(latency,"pci latency timer"); -MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list"); -MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)"); -MODULE_PARM_DESC(tuner,"specify installed tuner type"); -MODULE_PARM_DESC(autoload,"automatically load i2c modules like tuner.o, default is 1 (yes)"); -MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)" - " [some VIA/SIS chipsets are known to have problem with overlay]"); - -/* ----------------------------------------------------------------------- */ -/* list of card IDs for bt878+ cards */ - -static struct CARD { - unsigned id; - int cardnr; - char *name; -} cards[] __devinitdata = { - { 0x13eb0070, BTTV_BOARD_HAUPPAUGE878, "Hauppauge WinTV" }, - { 0x39000070, BTTV_BOARD_HAUPPAUGE878, "Hauppauge WinTV-D" }, - { 0x45000070, BTTV_BOARD_HAUPPAUGEPVR, "Hauppauge WinTV/PVR" }, - { 0xff000070, BTTV_BOARD_OSPREY1x0, "Osprey-100" }, - { 0xff010070, BTTV_BOARD_OSPREY2x0_SVID,"Osprey-200" }, - { 0xff020070, BTTV_BOARD_OSPREY500, "Osprey-500" }, - { 0xff030070, BTTV_BOARD_OSPREY2000, "Osprey-2000" }, - { 0xff040070, BTTV_BOARD_OSPREY540, "Osprey-540" }, - { 0xff070070, BTTV_BOARD_OSPREY440, "Osprey-440" }, - - { 0x00011002, BTTV_BOARD_ATI_TVWONDER, "ATI TV Wonder" }, - { 0x00031002, BTTV_BOARD_ATI_TVWONDERVE,"ATI TV Wonder/VE" }, - - { 0x6606107d, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, - { 0x6607107d, BTTV_BOARD_WINFASTVC100, "Leadtek WinFast VC 100" }, - { 0x6609107d, BTTV_BOARD_WINFAST2000, "Leadtek TV 2000 XP" }, - { 0x263610b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, - { 0x264510b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, - { 0x402010fc, BTTV_BOARD_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, - { 0x405010fc, BTTV_BOARD_GVBCTV4PCI, "I-O Data Co. GV-BCTV4/PCI" }, - { 0x407010fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, - { 0xd01810fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, - - { 0x001211bd, BTTV_BOARD_PINNACLE, "Pinnacle PCTV" }, - /* some cards ship with byteswapped IDs ... */ - { 0x1200bd11, BTTV_BOARD_PINNACLE, "Pinnacle PCTV [bswap]" }, - { 0xff00bd11, BTTV_BOARD_PINNACLE, "Pinnacle PCTV [bswap]" }, - /* this seems to happen as well ... */ - { 0xff1211bd, BTTV_BOARD_PINNACLE, "Pinnacle PCTV" }, - - { 0x3000121a, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, - { 0x263710b4, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, - { 0x3060121a, BTTV_BOARD_STB2, "3Dfx VoodooTV 100/ STB OEM" }, - - { 0x3000144f, BTTV_BOARD_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" }, - { 0xa005144f, BTTV_BOARD_MAGICTVIEW063, "CPH06X TView99-Card" }, - { 0x3002144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" }, - { 0x3005144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" }, - { 0x5000144f, BTTV_BOARD_MAGICTVIEW061, "Askey CPH050" }, - { 0x300014ff, BTTV_BOARD_MAGICTVIEW061, "TView 99 (CPH061)" }, - { 0x300214ff, BTTV_BOARD_PHOEBE_TVMAS, "Phoebe TV Master (CPH060)" }, - - { 0x00011461, BTTV_BOARD_AVPHONE98, "AVerMedia TVPhone98" }, - { 0x00021461, BTTV_BOARD_AVERMEDIA98, "AVermedia TVCapture 98" }, - { 0x00031461, BTTV_BOARD_AVPHONE98, "AVerMedia TVPhone98" }, - { 0x00041461, BTTV_BOARD_AVERMEDIA98, "AVerMedia TVCapture 98" }, - { 0x03001461, BTTV_BOARD_AVERMEDIA98, "VDOMATE TV TUNER CARD" }, - - { 0x1117153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Philips PAL B/G)" }, - { 0x1118153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Temic PAL B/G)" }, - { 0x1119153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Philips PAL I)" }, - { 0x111a153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Temic PAL I)" }, - - { 0x1123153b, BTTV_BOARD_TERRATVRADIO, "Terratec TV Radio+" }, - { 0x1127153b, BTTV_BOARD_TERRATV, "Terratec TV+ (V1.05)" }, - /* clashes with FlyVideo - *{ 0x18521852, BTTV_BOARD_TERRATV, "Terratec TV+ (V1.10)" }, */ - { 0x1134153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (LR102)" }, - { 0x1135153b, BTTV_BOARD_TERRATVALUER, "Terratec TValue Radio" }, /* LR102 */ - { 0x5018153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue" }, /* ?? */ - { 0xff3b153b, BTTV_BOARD_TERRATVALUER, "Terratec TValue Radio" }, /* ?? */ - - { 0x400015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" }, - { 0x400a15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" }, - { 0x400d15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, - { 0x401015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, - { 0x401615b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, - - { 0x1430aa00, BTTV_BOARD_PV143, "Provideo PV143A" }, - { 0x1431aa00, BTTV_BOARD_PV143, "Provideo PV143B" }, - { 0x1432aa00, BTTV_BOARD_PV143, "Provideo PV143C" }, - { 0x1433aa00, BTTV_BOARD_PV143, "Provideo PV143D" }, - { 0x1433aa03, BTTV_BOARD_PV143, "Security Eyes" }, - - { 0x1460aa00, BTTV_BOARD_PV150, "Provideo PV150A-1" }, - { 0x1461aa01, BTTV_BOARD_PV150, "Provideo PV150A-2" }, - { 0x1462aa02, BTTV_BOARD_PV150, "Provideo PV150A-3" }, - { 0x1463aa03, BTTV_BOARD_PV150, "Provideo PV150A-4" }, - - { 0x1464aa04, BTTV_BOARD_PV150, "Provideo PV150B-1" }, - { 0x1465aa05, BTTV_BOARD_PV150, "Provideo PV150B-2" }, - { 0x1466aa06, BTTV_BOARD_PV150, "Provideo PV150B-3" }, - { 0x1467aa07, BTTV_BOARD_PV150, "Provideo PV150B-4" }, - - { 0xa132ff00, BTTV_BOARD_IVC100, "IVC-100" }, - { 0xa1550000, BTTV_BOARD_IVC200, "IVC-200" }, - { 0xa1550001, BTTV_BOARD_IVC200, "IVC-200" }, - { 0xa1550002, BTTV_BOARD_IVC200, "IVC-200" }, - { 0xa1550003, BTTV_BOARD_IVC200, "IVC-200" }, - { 0xa1550100, BTTV_BOARD_IVC200, "IVC-200G" }, - { 0xa1550101, BTTV_BOARD_IVC200, "IVC-200G" }, - { 0xa1550102, BTTV_BOARD_IVC200, "IVC-200G" }, - { 0xa1550103, BTTV_BOARD_IVC200, "IVC-200G" }, - { 0xa182ff00, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff01, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff02, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff03, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff04, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff05, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff06, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff07, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff08, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff09, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff0a, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff0b, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff0c, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff0d, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff0e, BTTV_BOARD_IVC120, "IVC-120G" }, - { 0xa182ff0f, BTTV_BOARD_IVC120, "IVC-120G" }, - - { 0x41424344, BTTV_BOARD_GRANDTEC, "GrandTec Multi Capture" }, - { 0x01020304, BTTV_BOARD_XGUARD, "Grandtec Grand X-Guard" }, - - { 0x18501851, BTTV_BOARD_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, - { 0xa0501851, BTTV_BOARD_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, - { 0x18511851, BTTV_BOARD_FLYVIDEO98EZ, "FlyVideo 98EZ (LR51)/ CyberMail AV" }, - { 0x18521852, BTTV_BOARD_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" }, - { 0x41a0a051, BTTV_BOARD_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" }, - { 0x18501f7f, BTTV_BOARD_FLYVIDEO_98, "Lifeview Flyvideo 98" }, - - { 0x010115cb, BTTV_BOARD_GMV1, "AG GMV1" }, - { 0x010114c7, BTTV_BOARD_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" }, - - { 0x10b42636, BTTV_BOARD_HAUPPAUGE878, "STB ???" }, - { 0x217d6606, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, - { 0xfff6f6ff, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, - { 0x03116000, BTTV_BOARD_SENSORAY311, "Sensoray 311" }, - { 0x00790e11, BTTV_BOARD_WINDVR, "Canopus WinDVR PCI" }, - { 0xa0fca1a0, BTTV_BOARD_ZOLTRIX, "Face to Face Tvmax" }, - { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" }, - { 0x146caa0c, BTTV_BOARD_PV951, "ituner spectra8" }, - { 0x200a1295, BTTV_BOARD_PXC200, "ImageNation PXC200A" }, - - { 0x40111554, BTTV_BOARD_PV_BT878P_9B, "Prolink Pixelview PV-BT" }, - { 0x17de0a01, BTTV_BOARD_KWORLD, "Mecer TV/FM/Video Tuner" }, - - { 0x01051805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #1" }, - { 0x01061805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #2" }, - { 0x01071805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" }, - { 0x01081805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" }, - - { 0x15409511, BTTV_BOARD_ACORP_Y878F, "Acorp Y878F" }, - - /* likely broken, vendor id doesn't match the other magic views ... - * { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */ - - /* Duplicate PCI ID, reconfigure for this board during the eeprom read. - * { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB, "Hauppauge ImpactVCB" }, */ - - /* DVB cards (using pci function .1 for mpeg data xfer) */ - { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" }, - { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, - { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, - { 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, - { 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" }, - { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, - { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, - { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, - { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, - { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, - - { 0, -1, NULL } -}; - -/* ----------------------------------------------------------------------- */ -/* array with description for bt848 / bt878 tv/grabber cards */ - -struct tvcard bttv_tvcards[] = { - /* ---- card 0x00 ---------------------------------- */ - [BTTV_BOARD_UNKNOWN] = { - .name = " *** UNKNOWN/GENERIC *** ", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 0 }, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_MIRO] = { - .name = "MIRO PCTV", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 0, 0, 0, 10 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_HAUPPAUGE] = { - .name = "Hauppauge (bt848)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_STB] = { - .name = "STB, Gateway P/N 6000699 (bt848)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 4, 0, 2, 3, 1 }, - .no_msp34xx = 1, - .needs_tvaudio = 1, - .tuner_type = TUNER_PHILIPS_NTSC, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .pll = PLL_28, - .has_radio = 1, - }, - - /* ---- card 0x04 ---------------------------------- */ - [BTTV_BOARD_INTEL] = { - .name = "Intel Create and Share PCI/ Smart Video Recorder III", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = 2, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .tuner_type = 4, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_DIAMOND] = { - .name = "Diamond DTV2000", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 3, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0, 1, 0, 1, 3 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_AVERMEDIA] = { - .name = "AVerMedia TVPhone", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .muxsel = { 2, 3, 1, 1 }, - .gpiomask = 0x0f, - .audiomux = { 0x0c, 0x04, 0x08, 0x04, 0 }, - /* 0x04 for some cards ?? */ - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = avermedia_tvphone_audio, - .has_remote = 1, - }, - [BTTV_BOARD_MATRIX_VISION] = { - .name = "MATRIX-Vision MV-Delta", - .video_inputs = 5, - .audio_inputs = 1, - .tuner = -1, - .svhs = 3, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0 }, - .audiomux = { 0 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x08 ---------------------------------- */ - [BTTV_BOARD_FLYVIDEO] = { - .name = "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xc00, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0xc00, 0x800, 0x400, 0xc00, 0 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_TURBOTV] = { - .name = "IMS/IXmicro TurboTV", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 3, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 1, 2, 3, 0 }, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_TEMIC_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_HAUPPAUGE878] = { - .name = "Hauppauge (bt878)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x0f, /* old: 7 */ - .muxsel = { 2, 0, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_MIROPRO] = { - .name = "MIRO PCTV pro", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x3014f, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x20001,0x10001, 0, 0,10 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x0c ---------------------------------- */ - [BTTV_BOARD_ADSTECH_TV] = { - .name = "ADS Technologies Channel Surfer TV (bt848)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 13, 14, 11, 7, 0, 0 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_AVERMEDIA98] = { - .name = "AVerMedia TVCapture 98", - .video_inputs = 3, - .audio_inputs = 4, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 13, 14, 11, 7, 0, 0 }, - .needs_tvaudio = 1, - .msp34xx_alt = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = avermedia_tv_stereo_audio, - .no_gpioirq = 1, - }, - [BTTV_BOARD_VHX] = { - .name = "Aimslab Video Highway Xtreme (VHX)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 2, 1, 3, 4 }, /* old: {0, 1, 2, 3, 4} */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_ZOLTRIX] = { - .name = "Zoltrix TV-Max", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0 , 0, 1 , 0, 10 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x10 ---------------------------------- */ - [BTTV_BOARD_PIXVIEWPLAYTV] = { - .name = "Prolink Pixelview PlayTV (bt878)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x01fe00, - .muxsel = { 2, 3, 1, 1 }, - #if 0 - /* old */ - .audiomux = { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }, - #else - /* 2003-10-20 by "Anton A. Arapov" */ - .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 }, - #endif - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - }, - [BTTV_BOARD_WINVIEW_601] = { - .name = "Leadtek WinView 601", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x8300f8, - .muxsel = { 2, 3, 1, 1,0 }, - .audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = winview_audio, - .has_radio = 1, - }, - [BTTV_BOARD_AVEC_INTERCAP] = { - .name = "AVEC Intercapture", - .video_inputs = 3, - .audio_inputs = 2, - .tuner = 0, - .svhs = 2, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 0, 0, 0, 0 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_LIFE_FLYKIT] = { - .name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = -1, - .svhs = -1, - .gpiomask = 0x8dff00, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0 }, - .no_msp34xx = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x14 ---------------------------------- */ - [BTTV_BOARD_CEI_RAFFLES] = { - .name = "CEI Raffles Card", - .video_inputs = 3, - .audio_inputs = 3, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 1 }, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_CONFERENCETV] = { - .name = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50", - .video_inputs = 4, - .audio_inputs = 2, /* tuner, line in */ - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 }, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL_I, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_PHOEBE_TVMAS] = { - .name = "Askey CPH050/ Phoebe Tv Master + FM", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xc00, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 0x800, 0x400, 0xc00, 0 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_MODTEC_205] = { - .name = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 7, - .muxsel = { 2, 3, -1 }, - .digital_mode = DIGITAL_MODE_CAMERA, - .audiomux = { 0, 0, 0, 0, 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_ALPS_TSBB5_PAL_I, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x18 ---------------------------------- */ - [BTTV_BOARD_MAGICTVIEW061] = { - .name = "Askey CPH05X/06X (bt878) [many vendors]", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xe00, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = {0x400, 0x400, 0x400, 0x400, 0xc00 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_remote = 1, - }, - [BTTV_BOARD_VOBIS_BOOSTAR] = { - .name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1f0fff, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000 }, - .needs_tvaudio = 0, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = terratv_audio, - }, - [BTTV_BOARD_HAUPPAUG_WCAM] = { - .name = "Hauppauge WinCam newer (bt878)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 7, - .muxsel = { 2, 0, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_MAXI] = { - .name = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50", - .video_inputs = 4, - .audio_inputs = 2, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 }, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_SECAM, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x1c ---------------------------------- */ - [BTTV_BOARD_TERRATV] = { - .name = "Terratec TerraTV+ Version 1.1 (bt878)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1f0fff, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000 }, - .needs_tvaudio = 0, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = terratv_audio, - /* GPIO wiring: - External 20 pin connector (for Active Radio Upgrade board) - gpio00: i2c-sda - gpio01: i2c-scl - gpio02: om5610-data - gpio03: om5610-clk - gpio04: om5610-wre - gpio05: om5610-stereo - gpio06: rds6588-davn - gpio07: Pin 7 n.c. - gpio08: nIOW - gpio09+10: nIOR, nSEL ?? (bt878) - gpio09: nIOR (bt848) - gpio10: nSEL (bt848) - Sound Routing: - gpio16: u2-A0 (1st 4052bt) - gpio17: u2-A1 - gpio18: u2-nEN - gpio19: u4-A0 (2nd 4052) - gpio20: u4-A1 - u4-nEN - GND - Btspy: - 00000 : Cdrom (internal audio input) - 10000 : ext. Video audio input - 20000 : TV Mono - a0000 : TV Mono/2 - 1a0000 : TV Stereo - 30000 : Radio - 40000 : Mute - */ - - }, - [BTTV_BOARD_PXC200] = { - /* Jannik Fritsch */ - .name = "Imagenation PXC200", - .video_inputs = 5, - .audio_inputs = 1, - .tuner = -1, - .svhs = 1, /* was: 4 */ - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0}, - .audiomux = { 0 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .muxsel_hook = PXC200_muxsel, - - }, - [BTTV_BOARD_FLYVIDEO_98] = { - .name = "Lifeview FlyVideo 98 LR50", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1800, /* 0x8dfe00 */ - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_IPROTV] = { - .name = "Formac iProTV, Formac ProTV I (bt848)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 1, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 0, 0, 0, 0 }, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x20 ---------------------------------- */ - [BTTV_BOARD_INTEL_C_S_PCI] = { - .name = "Intel Create and Share PCI/ Smart Video Recorder III", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = 2, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .tuner_type = 4, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_TERRATVALUE] = { - .name = "Terratec TerraTValue Version Bt878", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xffff00, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x500, 0, 0x300, 0x900, 0x900 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_WINFAST2000] = { - .name = "Leadtek WinFast 2000/ WinFast 2000 XP", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */ - #if 0 - .gpiomask = 0xc33000, - .audiomux = { 0x422000,0x1000,0x0000,0x620000,0x800000 }, - #else - /* Alexander Varakin [stereo version] */ - .gpiomask = 0xb33000, - .audiomux = { 0x122000,0x1000,0x0000,0x620000,0x800000 }, - #endif - /* Audio Routing for "WinFast 2000 XP" (no tv stereo !) - gpio23 -- hef4052:nEnable (0x800000) - gpio12 -- hef4052:A1 - gpio13 -- hef4052:A0 - 0x0000: external audio - 0x1000: FM - 0x2000: TV - 0x3000: n.c. - Note: There exists another variant "Winfast 2000" with tv stereo !? - Note: eeprom only contains FF and pci subsystem id 107d:6606 - */ - .needs_tvaudio = 0, - .pll = PLL_28, - .has_radio = 1, - .tuner_type = 5, /* default for now, gpio reads BFFF06 for Pal bg+dk */ - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = winfast2000_audio, - .has_remote = 1, - }, - [BTTV_BOARD_CHRONOS_VS2] = { - .name = "Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II", - .video_inputs = 4, - .audio_inputs = 3, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x24 ---------------------------------- */ - [BTTV_BOARD_TYPHOON_TVIEW] = { - .name = "Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner", - .video_inputs = 4, - .audio_inputs = 3, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_radio = 1, - }, - [BTTV_BOARD_PXELVWPLTVPRO] = { - .name = "Prolink PixelView PlayTV pro", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xff, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_MAGICTVIEW063] = { - .name = "Askey CPH06X TView99", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x551e00, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = 1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_remote = 1, - }, - [BTTV_BOARD_PINNACLE] = { - .name = "Pinnacle PCTV Studio/Rave", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x03000F, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 0xd0001, 0, 0, 1 }, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x28 ---------------------------------- */ - [BTTV_BOARD_STB2] = { - .name = "STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 4, 0, 2, 3, 1 }, - .no_msp34xx = 1, - .needs_tvaudio = 1, - .tuner_type = TUNER_PHILIPS_NTSC, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .pll = PLL_28, - .has_radio = 1, - }, - [BTTV_BOARD_AVPHONE98] = { - .name = "AVerMedia TVPhone 98", - .video_inputs = 3, - .audio_inputs = 4, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 13, 4, 11, 7, 0, 0 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_radio = 1, - .audio_hook = avermedia_tvphone_audio, - }, - [BTTV_BOARD_PV951] = { - .name = "ProVideo PV951", /* pic16c54 */ - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0, 0, 0, 0}, - .needs_tvaudio = 1, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = 1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_ONAIR_TV] = { - .name = "Little OnAir TV", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xe00b, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc }, - .no_msp34xx = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x2c ---------------------------------- */ - [BTTV_BOARD_SIGMA_TVII_FM] = { - .name = "Sigma TVII-FM", - .video_inputs = 2, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 3, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 1, 0, 2, 3 }, - .no_msp34xx = 1, - .pll = PLL_NONE, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_MATRIX_VISION2] = { - .name = "MATRIX-Vision MV-Delta 2", - .video_inputs = 5, - .audio_inputs = 1, - .tuner = -1, - .svhs = 3, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0 }, - .audiomux = { 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_ZOLTRIX_GENIE] = { - .name = "Zoltrix Genie TV/FM", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xbcf03f, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = 21, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_TERRATVRADIO] = { - .name = "Terratec TV/Radio+", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x70000, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000, 0x20000 }, - .needs_tvaudio = 1, - .no_msp34xx = 1, - .pll = PLL_35, - .tuner_type = 1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_radio = 1, - }, - - /* ---- card 0x30 ---------------------------------- */ - [BTTV_BOARD_DYNALINK] = { - .name = "Askey CPH03x/ Dynalink Magic TView", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = {2,0,0,0,1 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_GVBCTV3PCI] = { - .name = "IODATA GV-BCTV3/PCI", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x010f00, - .muxsel = {2, 3, 0, 0 }, - .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_ALPS_TSHC6_NTSC, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = gvbctv3pci_audio, - }, - [BTTV_BOARD_PXELVWPLTVPAK] = { - .name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP", - .video_inputs = 5, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 0xAA0000, - .muxsel = { 2,3,1,1,-1 }, - .digital_mode = DIGITAL_MODE_CAMERA, - .audiomux = { 0x20000, 0, 0x80000, 0x80000, 0xa8000, 0x46000 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL_I, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_remote = 1, - /* GPIO wiring: (different from Rev.4C !) - GPIO17: U4.A0 (first hef4052bt) - GPIO19: U4.A1 - GPIO20: U5.A1 (second hef4052bt) - GPIO21: U4.nEN - GPIO22: BT832 Reset Line - GPIO23: A5,A0, U5,nEN - Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22 - */ - }, - [BTTV_BOARD_EAGLE] = { - .name = "Eagle Wireless Capricorn2 (bt878A)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 0, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4 }, - .pll = PLL_28, - .tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x34 ---------------------------------- */ - [BTTV_BOARD_PINNACLEPRO] = { - /* David Härdeman */ - .name = "Pinnacle PCTV Studio Pro", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 0x03000F, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 0xd0001, 0, 0, 10 }, - /* sound path (5 sources): - MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable) - 0= ext. Audio IN - 1= from MUX2 - 2= Mono TV sound from Tuner - 3= not connected - MUX2 (mask 0x30000): - 0,2,3= from MSP34xx - 1= FM stereo Radio from Tuner */ - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_TVIEW_RDS_FM] = { - /* Claas Langbehn , - Sven Grothklags */ - .name = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS", - .video_inputs = 4, - .audio_inputs = 3, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1c, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0, 0x10, 8, 4 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_radio = 1, - }, - [BTTV_BOARD_LIFETEC_9415] = { - /* Tim Röstermundt - in de.comp.os.unix.linux.hardware: - options bttv card=0 pll=1 radio=1 gpiomask=0x18e0 - audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff - options tuner type=5 */ - .name = "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x18e0, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x0000,0x0800,0x1000,0x1000,0x18e0 }, - /* For cards with tda9820/tda9821: - 0x0000: Tuner normal stereo - 0x0080: Tuner A2 SAP (second audio program = Zweikanalton) - 0x0880: Tuner A2 stereo */ - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_BESTBUY_EASYTV] = { - /* Miguel Angel Alvarez - old Easy TV BT848 version (model CPH031) */ - .name = "Askey CPH031/ BESTBUY Easy TV", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xF, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 2, 0, 0, 0, 10 }, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_TEMIC_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x38 ---------------------------------- */ - [BTTV_BOARD_FLYVIDEO_98FM] = { - /* Gordon Heydon */ - [BTTV_BOARD_GRANDTEC] = { - .name = "GrandTec 'Grand Video Capture' (Bt848)", - .video_inputs = 2, - .audio_inputs = 0, - .tuner = -1, - .svhs = 1, - .gpiomask = 0, - .muxsel = { 3, 1 }, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_35, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_ASKEY_CPH060] = { - /* Daniel Herrington */ - .name = "Askey CPH060/ Phoebe TV Master Only (No FM)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xe00, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = TUNER_TEMIC_4036FY5_NTSC, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_ASKEY_CPH03X] = { - /* Matti Mottus */ - .name = "Askey CPH03x TV Capturer", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x03000F, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 2, 0, 0, 0, 1 }, - .pll = PLL_28, - .tuner_type = 0, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x3c ---------------------------------- */ - [BTTV_BOARD_MM100PCTV] = { - /* Philip Blundell */ - .name = "Modular Technology MM100PCTV", - .video_inputs = 2, - .audio_inputs = 2, - .tuner = 0, - .svhs = -1, - .gpiomask = 11, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 0, 0, 1, 8 }, - .pll = PLL_35, - .tuner_type = TUNER_TEMIC_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_GMV1] = { - /* Adrian Cox - new Easy TV BT878 version (model CPH061) - special thanks to Informatica Mieres for providing the card */ - .name = "Askey CPH061/ BESTBUY Easy TV (bt878)", - .video_inputs = 3, - .audio_inputs = 2, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xFF, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 1, 0, 4, 4, 9 }, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_ATI_TVWONDER] = { - /* Lukas Gebauer */ - .name = "ATI TV-Wonder", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xf03f, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe }, - .pll = PLL_28, - .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x40 ---------------------------------- */ - [BTTV_BOARD_ATI_TVWONDERVE] = { - /* Lukas Gebauer */ - .name = "ATI TV-Wonder VE", - .video_inputs = 2, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 1, - .muxsel = { 2, 3, 0, 1 }, - .audiomux = { 0, 0, 1, 0, 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_FLYVIDEO2000] = { - /* DeeJay */ - .name = "IODATA GV-BCTV4/PCI", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x010f00, - .muxsel = {2, 3, 0, 0 }, - .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_SHARP_2U5JF5540_NTSC, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = gvbctv3pci_audio, - }, - - /* ---- card 0x44 ---------------------------------- */ - [BTTV_BOARD_VOODOOTV_FM] = { - .name = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)", - /* try "insmod msp3400 simple=0" if you have - * sound problems with this card. */ - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 0x4f8a00, - /* 0x100000: 1=MSP enabled (0=disable again) - * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */ - .audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff}, - /* tvtuner, radio, external,internal, mute, stereo - * tuner, Composit, SVid, Composit-on-Svid-adapter */ - .muxsel = { 2, 3 ,0 ,1 }, - .tuner_type = TUNER_MT2032, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .pll = PLL_28, - .has_radio = 1, - }, - [BTTV_BOARD_AIMMS] = { - /* Philip Blundell */ - .name = "Active Imaging AIMMS", - .video_inputs = 1, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .pll = PLL_28, - .muxsel = { 2 }, - .gpiomask = 0 - }, - [BTTV_BOARD_PV_BT878P_PLUS] = { - /* Tomasz Pyra */ - .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)", - .video_inputs = 3, - .audio_inputs = 4, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0, 11, 7, 13, 0 }, /* TV and Radio with same GPIO ! */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = 25, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_remote = 1, - /* GPIO wiring: - GPIO0: U4.A0 (hef4052bt) - GPIO1: U4.A1 - GPIO2: U4.A1 (second hef4052bt) - GPIO3: U4.nEN, U5.A0, A5.nEN - GPIO8-15: vrd866b ? - */ - }, - [BTTV_BOARD_FLYVIDEO98EZ] = { - .name = "Lifeview FlyVideo 98EZ (capture only) LR51", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = 2, - .muxsel = { 2, 3, 1, 1 }, /* AV1, AV2, SVHS, CVid adapter on SVHS */ - .pll = PLL_28, - .no_msp34xx = 1, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x48 ---------------------------------- */ - [BTTV_BOARD_PV_BT878P_9B] = { - /* Dariusz Kowalewski */ - .name = "Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x3f, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x01, 0x00, 0x03, 0x03, 0x09, 0x02 }, - .needs_tvaudio = 1, - .no_msp34xx = 1, - .no_tda9875 = 1, - .pll = PLL_28, - .tuner_type = 5, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = pvbt878p9b_audio, /* Note: not all cards have stereo */ - .has_radio = 1, /* Note: not all cards have radio */ - .has_remote = 1, - /* GPIO wiring: - GPIO0: A0 hef4052 - GPIO1: A1 hef4052 - GPIO3: nEN hef4052 - GPIO8-15: vrd866b - GPIO20,22,23: R30,R29,R28 - */ - }, - [BTTV_BOARD_SENSORAY311] = { - /* Clay Kunz */ - /* you must jumper JP5 for the card to work */ - .name = "Sensoray 311", - .video_inputs = 5, - .audio_inputs = 0, - .tuner = -1, - .svhs = 4, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0 }, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_RV605] = { - /* Miguel Freitas */ - .name = "RemoteVision MX (RV605)", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0x00, - .gpiomask2 = 0x07ff, - .muxsel = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03, - 0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 }, - .no_msp34xx = 1, - .no_tda9875 = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .muxsel_hook = rv605_muxsel, - }, - [BTTV_BOARD_POWERCLR_MTV878] = { - .name = "Powercolor MTV878/ MTV878R/ MTV878F", - .video_inputs = 3, - .audio_inputs = 2, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1C800F, /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */ - .muxsel = { 2, 1, 1, }, - .audiomux = { 0, 1, 2, 2, 4 }, - .needs_tvaudio = 0, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .pll = PLL_28, - .has_radio = 1, - }, - - /* ---- card 0x4c ---------------------------------- */ - [BTTV_BOARD_WINDVR] = { - /* Masaki Suzuki */ - .name = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x140007, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4, 0 }, - .tuner_type = TUNER_PHILIPS_NTSC, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = windvr_audio, - }, - [BTTV_BOARD_GRANDTEC_MULTI] = { - .name = "GrandTec Multi Capture Card (Bt878)", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_KWORLD] = { - .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF", - .video_inputs = 4, - .audio_inputs = 3, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, /* Tuner, SVid, SVHS, SVid to SVHS connector */ - .audiomux = { 0 ,0 ,4, 4,4,4},/* Yes, this tuner uses the same audio output for TV and FM radio! - * This card lacks external Audio In, so we mute it on Ext. & Int. - * The PCB can take a sbx1637/sbx1673, wiring unknown. - * This card lacks PCI subsystem ID, sigh. - * audiomux=1: lower volume, 2+3: mute - * btwincap uses 0x80000/0x80003 - */ - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = 5, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and - radio signal strength indicators work fine. */ - .has_radio = 1, - /* GPIO Info: - GPIO0,1: HEF4052 A0,A1 - GPIO2: HEF4052 nENABLE - GPIO3-7: n.c. - GPIO8-13: IRDC357 data0-5 (data6 n.c. ?) [chip not present on my card] - GPIO14,15: ?? - GPIO16-21: n.c. - GPIO22,23: ?? - ?? : mtu8b56ep microcontroller for IR (GPIO wiring unknown)*/ - }, - [BTTV_BOARD_DSP_TCVIDEO] = { - /* Arthur Tetzlaff-Deas, DSP Design Ltd */ - .name = "DSP Design TCVIDEO", - .video_inputs = 4, - .svhs = -1, - .muxsel = { 2, 3, 1, 0 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x50 ---------------------------------- */ - [BTTV_BOARD_HAUPPAUGEPVR] = { - .name = "Hauppauge WinTV PVR", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 0, 1, 1 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - - .gpiomask = 7, - .audiomux = {7}, - }, - [BTTV_BOARD_GVBCTV5PCI] = { - .name = "IODATA GV-BCTV5/PCI", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x0f0f80, - .muxsel = {2, 3, 1, 0 }, - .audiomux = {0x030000, 0x010000, 0, 0, 0x020000, 0}, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = gvbctv5pci_audio, - .has_radio = 1, - }, - [BTTV_BOARD_OSPREY1x0] = { - .name = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */ - .video_inputs = 4, /* id-inputs-clock */ - .audio_inputs = 0, - .tuner = -1, - .svhs = 3, - .muxsel = { 3, 2, 0, 1 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - }, - [BTTV_BOARD_OSPREY1x0_848] = { - .name = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */ - .video_inputs = 3, - .audio_inputs = 0, - .tuner = -1, - .svhs = 2, - .muxsel = { 2, 3, 1 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - }, - - /* ---- card 0x54 ---------------------------------- */ - [BTTV_BOARD_OSPREY101_848] = { - .name = "Osprey 101 (848)", /* 0x05-40C0-C1 */ - .video_inputs = 2, - .audio_inputs = 0, - .tuner = -1, - .svhs = 1, - .muxsel = { 3, 1 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - }, - [BTTV_BOARD_OSPREY1x1] = { - .name = "Osprey 101/151", /* 0x1(4|5)-0004-C4 */ - .video_inputs = 1, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .muxsel = { 0 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - }, - [BTTV_BOARD_OSPREY1x1_SVID] = { - .name = "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */ - .video_inputs = 2, - .audio_inputs = 0, - .tuner = -1, - .svhs = 1, - .muxsel = { 0, 1 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - }, - [BTTV_BOARD_OSPREY2xx] = { - .name = "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */ - .video_inputs = 1, - .audio_inputs = 1, - .tuner = -1, - .svhs = -1, - .muxsel = { 0 }, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - }, - - /* ---- card 0x58 ---------------------------------- */ - [BTTV_BOARD_OSPREY2x0_SVID] = { - .name = "Osprey 200/250", /* 0x1(A|B)-00C4-C1 */ - .video_inputs = 2, - .audio_inputs = 1, - .tuner = -1, - .svhs = 1, - .muxsel = { 0, 1 }, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - }, - [BTTV_BOARD_OSPREY2x0] = { - .name = "Osprey 210/220", /* 0x1(A|B)-04C0-C1 */ - .video_inputs = 2, - .audio_inputs = 1, - .tuner = -1, - .svhs = 1, - .muxsel = { 2, 3 }, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - }, - [BTTV_BOARD_OSPREY500] = { - .name = "Osprey 500", /* 500 */ - .video_inputs = 2, - .audio_inputs = 1, - .tuner = -1, - .svhs = 1, - .muxsel = { 2, 3 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - }, - [BTTV_BOARD_OSPREY540] = { - .name = "Osprey 540", /* 540 */ - .video_inputs = 4, - .audio_inputs = 1, - .tuner = -1, - #if 0 /* TODO ... */ - .svhs = OSPREY540_SVID_ANALOG, - .muxsel = { [OSPREY540_COMP_ANALOG] = 2, - [OSPREY540_SVID_ANALOG] = 3, }, - #endif - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - #if 0 /* TODO ... */ - .muxsel_hook = osprey_540_muxsel, - .picture_hook = osprey_540_set_picture, - #endif - }, - - /* ---- card 0x5C ---------------------------------- */ - [BTTV_BOARD_OSPREY2000] = { - .name = "Osprey 2000", /* 2000 */ - .video_inputs = 2, - .audio_inputs = 1, - .tuner = -1, - .svhs = 1, - .muxsel = { 2, 3 }, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */ - }, - [BTTV_BOARD_IDS_EAGLE] = { - /* M G Berberich */ - .name = "IDS Eagle", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = -1, - .gpiomask = 0, - .muxsel = { 0, 1, 2, 3 }, - .muxsel_hook = eagle_muxsel, - .no_msp34xx = 1, - .no_tda9875 = 1, - .pll = PLL_28, - }, - [BTTV_BOARD_PINNACLESAT] = { - .name = "Pinnacle PCTV Sat", - .video_inputs = 2, - .audio_inputs = 0, - .svhs = 1, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .muxsel = { 3, 0, 1, 2 }, - .pll = PLL_28, - .no_gpioirq = 1, - .has_dvb = 1, - }, - [BTTV_BOARD_FORMAC_PROTV] = { - .name = "Formac ProTV II (bt878)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 2, - /* TV, Comp1, Composite over SVID con, SVID */ - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 2, 0, 0, 0 }, - .pll = PLL_28, - .has_radio = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - /* sound routing: - GPIO=0x00,0x01,0x03: mute (?) - 0x02: both TV and radio (tuner: FM1216/I) - The card has onboard audio connectors labeled "cdrom" and "board", - not soldered here, though unknown wiring. - Card lacks: external audio in, pci subsystem id. - */ - }, - - /* ---- card 0x60 ---------------------------------- */ - [BTTV_BOARD_MACHTV] = { - .name = "MachTV", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 1, 2, 3, 4}, - .needs_tvaudio = 1, - .tuner_type = 5, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .pll = PLL_28, - }, - [BTTV_BOARD_EURESYS_PICOLO] = { - .name = "Euresys Picolo", - .video_inputs = 3, - .audio_inputs = 0, - .tuner = -1, - .svhs = 2, - .gpiomask = 0, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .muxsel = { 2, 0, 1}, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_PV150] = { - /* Luc Van Hoeylandt */ - .name = "ProVideo PV150", /* 0x4f */ - .video_inputs = 2, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0, - .muxsel = { 2, 3 }, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_AD_TVK503] = { - /* Hiroshi Takekawa */ - /* This card lacks subsystem ID */ - .name = "AD-TVK503", /* 0x63 */ - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x001e8007, - .muxsel = { 2, 3, 1, 0 }, - /* Tuner, Radio, external, internal, off, on */ - .audiomux = { 0x08, 0x0f, 0x0a, 0x08, 0x0f, 0x08 }, - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = 2, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_hook = adtvk503_audio, - }, - - /* ---- card 0x64 ---------------------------------- */ - [BTTV_BOARD_HERCULES_SM_TV] = { - .name = "Hercules Smart TV Stereo", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x00, - .muxsel = { 2, 3, 1, 1 }, - .needs_tvaudio = 1, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = 5, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - /* Notes: - - card lacks subsystem ID - - stereo variant w/ daughter board with tda9874a @0xb0 - - Audio Routing: - always from tda9874 independent of GPIO (?) - external line in: unknown - - Other chips: em78p156elp @ 0x96 (probably IR remote control) - hef4053 (instead 4052) for unknown function - */ - }, - [BTTV_BOARD_PACETV] = { - .name = "Pace TV & Radio Card", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 1 }, /* Tuner, CVid, SVid, CVid over SVid connector */ - .gpiomask = 0, - .no_tda9875 = 1, - .no_tda7432 = 1, - .tuner_type = 1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_radio = 1, - .pll = PLL_28, - /* Bt878, Bt832, FI1246 tuner; no pci subsystem id - only internal line out: (4pin header) RGGL - Radio must be decoded by msp3410d (not routed through)*/ - /* - .digital_mode = DIGITAL_MODE_CAMERA, todo! - */ - }, - [BTTV_BOARD_IVC200] = { - /* Chris Willing */ - .name = "IVC-200", - .video_inputs = 1, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = -1, - .gpiomask = 0xdf, - .muxsel = { 2 }, - .pll = PLL_28, - }, - [BTTV_BOARD_XGUARD] = { - .name = "Grand X-Guard / Trust 814PCI", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .tuner_type = 4, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .gpiomask2 = 0xff, - .muxsel = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 }, - .muxsel_hook = xguard_muxsel, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .pll = PLL_28, - }, - - /* ---- card 0x68 ---------------------------------- */ - [BTTV_BOARD_NEBULA_DIGITV] = { - .name = "Nebula Electronics DigiTV", - .video_inputs = 1, - .tuner = -1, - .svhs = -1, - .muxsel = { 2, 3, 1, 0 }, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_dvb = 1, - .has_remote = 1, - .gpiomask = 0x1b, - .no_gpioirq = 1, - }, - [BTTV_BOARD_PV143] = { - /* Jorge Boncompte - DTI2 */ - .name = "ProVideo PV143", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_VD009X1_MINIDIN] = { - /* M.Klahr@phytec.de */ - .name = "PHYTEC VD-009-X1 MiniDIN (bt878)", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ - .svhs = 3, - .gpiomask = 0x00, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_VD009X1_COMBI] = { - .name = "PHYTEC VD-009-X1 Combi (bt878)", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ - .svhs = 3, - .gpiomask = 0x00, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - - /* ---- card 0x6c ---------------------------------- */ - [BTTV_BOARD_VD009_MINIDIN] = { - .name = "PHYTEC VD-009 MiniDIN (bt878)", - .video_inputs = 10, - .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ - .svhs = 9, - .gpiomask = 0x00, - .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio - via the upper nibble of muxsel. here: used for - xternal video-mux */ - .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 }, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_VD009_COMBI] = { - .name = "PHYTEC VD-009 Combi (bt878)", - .video_inputs = 10, - .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ - .svhs = 9, - .gpiomask = 0x00, - .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio - via the upper nibble of muxsel. here: used for - xternal video-mux */ - .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 }, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_IVC100] = { - .name = "IVC-100", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = -1, - .gpiomask = 0xdf, - .muxsel = { 2, 3, 1, 0 }, - .pll = PLL_28, - }, - [BTTV_BOARD_IVC120] = { - /* IVC-120G - Alan Garfield */ - .name = "IVC-120G", - .video_inputs = 16, - .audio_inputs = 0, /* card has no audio */ - .tuner = -1, /* card has no tuner */ - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = -1, /* card has no svhs */ - .needs_tvaudio = 0, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .gpiomask = 0x00, - .muxsel = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }, - .muxsel_hook = ivc120_muxsel, - .pll = PLL_28, - }, - - /* ---- card 0x70 ---------------------------------- */ - [BTTV_BOARD_PC_HDTV] = { - .name = "pcHDTV HD-2000 TV", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 0 }, - .tuner_type = TUNER_PHILIPS_ATSC, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_dvb = 1, - }, - [BTTV_BOARD_TWINHAN_DST] = { - .name = "Twinhan DST + clones", - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .tuner_type = TUNER_ABSENT, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_video = 1, - .has_dvb = 1, - }, - [BTTV_BOARD_WINFASTVC100] = { - .name = "Winfast VC100", - .video_inputs = 3, - .audio_inputs = 0, - .svhs = 1, - .tuner = -1, - .muxsel = { 3, 1, 1, 3 }, /* Vid In, SVid In, Vid over SVid in connector */ - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .tuner_type = TUNER_ABSENT, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .pll = PLL_28, - }, - [BTTV_BOARD_TEV560] = { - .name = "Teppro TEV-560/InterVision IV-560", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 3, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 1, 1, 1, 0 }, - .needs_tvaudio = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .pll = PLL_35, - }, - - /* ---- card 0x74 ---------------------------------- */ - [BTTV_BOARD_SIMUS_GVC1100] = { - .name = "SIMUS GVC1100", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .pll = PLL_28, - .muxsel = { 2, 2, 2, 2 }, - .gpiomask = 0x3F, - .muxsel_hook = gvc1100_muxsel, - }, - [BTTV_BOARD_NGSTV_PLUS] = { - /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */ - .name = "NGS NGSTV+", - .video_inputs = 3, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x008007, - .muxsel = { 2, 3, 0, 0 }, - .audiomux = { 0, 0, 0, 0, 0x000003, 0 }, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_remote = 1, - }, - [BTTV_BOARD_LMLBT4] = { - /* http://linuxmedialabs.com */ - .name = "LMLBT4", - .video_inputs = 4, /* IN1,IN2,IN3,IN4 */ - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .muxsel = { 2, 3, 1, 0 }, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .needs_tvaudio = 0, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_TEKRAM_M205] = { - /* Helmroos Harri */ - .name = "Tekram M205 PRO", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = 2, - .needs_tvaudio = 0, - .gpiomask = 0x68, - .muxsel = { 2, 3, 1 }, - .audiomux = { 0x68, 0x68, 0x61, 0x61, 0x00 }, - .pll = PLL_28, - }, - - /* ---- card 0x78 ---------------------------------- */ - [BTTV_BOARD_CONTVFMI] = { - /* Javier Cendan Ares */ - /* bt878 TV + FM without subsystem ID */ - .name = "Conceptronic CONTVFMi", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x008007, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 2, 3 }, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_remote = 1, - .has_radio = 1, - }, - [BTTV_BOARD_PICOLO_TETRA_CHIP] = { - /*Eric DEBIEF */ - /*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controled*/ - /* adds picolo_tetra_muxsel(), picolo_tetra_init(), the folowing declaration strucure, and #define BTTV_BOARD_PICOLO_TETRA_CHIP*/ - /*0x79 in bttv.h*/ - .name = "Euresys Picolo Tetra", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0, - .gpiomask2 = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/ - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .muxsel = {2,2,2,2},/*878A input is always MUX0, see above.*/ - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ - .pll = PLL_28, - .needs_tvaudio = 0, - .muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/ - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_SPIRIT_TV] = { - /* Spirit TV Tuner from http://spiritmodems.com.au */ - /* Stafford Goodsell */ - .name = "Spirit TV Tuner", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x0000000f, - .muxsel = { 2, 1, 1 }, - .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00 }, - .tuner_type = TUNER_TEMIC_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - }, - [BTTV_BOARD_AVDVBT_771] = { - /* Wolfram Joost */ - .name = "AVerMedia AVerTV DVB-T 771", - .video_inputs = 2, - .svhs = 1, - .tuner = -1, - .tuner_type = TUNER_ABSENT, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .muxsel = { 3 , 3 }, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .pll = PLL_28, - .has_dvb = 1, - .no_gpioirq = 1, - .has_remote = 1, - }, - /* ---- card 0x7c ---------------------------------- */ - [BTTV_BOARD_AVDVBT_761] = { - /* Matt Jesson */ - /* Based on the Nebula card data - added remote and new card number - BTTV_BOARD_AVDVBT_761, see also ir-kbd-gpio.c */ - .name = "AverMedia AverTV DVB-T 761", - .video_inputs = 2, - .tuner = -1, - .svhs = 1, - .muxsel = { 3, 1, 2, 0 }, /* Comp0, S-Video, ?, ? */ - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_dvb = 1, - .no_gpioirq = 1, - .has_remote = 1, - }, - [BTTV_BOARD_MATRIX_VISIONSQ] = { - /* andre.schwarz@matrix-vision.de */ - .name = "MATRIX Vision Sigma-SQ", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0x0, - .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3 }, - .muxsel_hook = sigmaSQ_muxsel, - .audiomux = { 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_MATRIX_VISIONSLC] = { - /* andre.schwarz@matrix-vision.de */ - .name = "MATRIX Vision Sigma-SLC", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0x0, - .muxsel = { 2, 2, 2, 2 }, - .muxsel_hook = sigmaSLC_muxsel, - .audiomux = { 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - /* BTTV_BOARD_APAC_VIEWCOMP */ - [BTTV_BOARD_APAC_VIEWCOMP] = { - /* Attila Kondoros */ - /* bt878 TV + FM 0x00000000 subsystem ID */ - .name = "APAC Viewcomp 878(AMAX)", - .video_inputs = 2, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 0xFF, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 0, 0, 0, 10 }, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_remote = 1, /* miniremote works, see ir-kbd-gpio.c */ - .has_radio = 1, /* not every card has radio */ - }, - - /* ---- card 0x80 ---------------------------------- */ - [BTTV_BOARD_DVICO_DVBT_LITE] = { - /* Chris Pascoe */ - .name = "DViCO FusionHDTV DVB-T Lite", - .tuner = -1, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .pll = PLL_28, - .no_video = 1, - .has_dvb = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_VGEAR_MYVCD] = { - /* Steven */ - .name = "V-Gear MyVCD", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x3f, - .muxsel = {2, 3, 1, 0 }, - .audiomux = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_radio = 0, - #if 0 - .has_remote = 1, - #endif - }, - [BTTV_BOARD_SUPER_TV] = { - /* Rick C */ - .name = "Super TV Tuner", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 0 }, - .tuner_type = TUNER_PHILIPS_NTSC, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .gpiomask = 0x008007, - .audiomux = { 0, 0x000001,0,0, 0 }, - .needs_tvaudio = 1, - .has_radio = 1, - }, - [BTTV_BOARD_TIBET_CS16] = { - /* Chris Fanning */ - .name = "Tibet Systems 'Progress DVR' CS16", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, - .pll = PLL_28, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .muxsel_hook = tibetCS16_muxsel, - }, - [BTTV_BOARD_KODICOM_4400R] = { - /* Bill Brack */ - /* - * Note that, because of the card's wiring, the "master" - * BT878A chip (i.e. the one which controls the analog switch - * and must use this card type) is the 2nd one detected. The - * other 3 chips should use card type 0x85, whose description - * follows this one. There is a EEPROM on the card (which is - * connected to the I2C of one of those other chips), but is - * not currently handled. There is also a facility for a - * "monitor", which is also not currently implemented. - */ - .name = "Kodicom 4400R (master)", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = -1, - /* GPIO bits 0-9 used for analog switch: - * 00 - 03: camera selector - * 04 - 06: channel (controller) selector - * 07: data (1->on, 0->off) - * 08: strobe - * 09: reset - * bit 16 is input from sync separator for the channel - */ - .gpiomask = 0x0003ff, - .no_gpioirq = 1, - .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, - .pll = PLL_28, - .no_msp34xx = 1, - .no_tda7432 = 1, - .no_tda9875 = 1, - .muxsel_hook = kodicom4400r_muxsel, - }, - [BTTV_BOARD_KODICOM_4400R_SL] = { - /* Bill Brack */ - /* Note that, for reasons unknown, the "master" BT878A chip (i.e. the - * one which controls the analog switch, and must use the card type) - * is the 2nd one detected. The other 3 chips should use this card - * type - */ - .name = "Kodicom 4400R (slave)", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = -1, - .gpiomask = 0x010000, - .no_gpioirq = 1, - .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, - .pll = PLL_28, - .no_msp34xx = 1, - .no_tda7432 = 1, - .no_tda9875 = 1, - .muxsel_hook = kodicom4400r_muxsel, - }, - /* ---- card 0x86---------------------------------- */ - [BTTV_BOARD_ADLINK_RTV24] = { - /* Michael Henson */ - /* Adlink RTV24 with special unlock codes */ - .name = "Adlink RTV24", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 0 }, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .pll = PLL_28, - }, - /* ---- card 0x87---------------------------------- */ - [BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE] = { - /* Michael Krufky */ - .name = "DViCO FusionHDTV 5 Lite", - .tuner = 0, - .tuner_type = TUNER_LG_TDVS_H062F, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .video_inputs = 3, - .audio_inputs = 1, - .svhs = 2, - .muxsel = { 2, 3, 1 }, - .gpiomask = 0x00e00007, - .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 }, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .has_dvb = 1, - }, - /* ---- card 0x88---------------------------------- */ - [BTTV_BOARD_ACORP_Y878F] = { - /* Mauro Carvalho Chehab */ - .name = "Acorp Y878F", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x01fe00, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = TUNER_YMEC_TVF66T5_B_DFF, - .tuner_addr = 0xc1 >>1, - .radio_addr = 0xc1 >>1, - .has_radio = 1, - }, - /* ---- card 0x89 ---------------------------------- */ - [BTTV_BOARD_CONCEPTRONIC_CTVFMI2] = { - .name = "Conceptronic CTVFMi v2", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x001c0007, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 2, 3 }, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_TENA_9533_DI, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_remote = 1, - .has_radio = 1, - }, - /* ---- card 0x8a ---------------------------------- */ - [BTTV_BOARD_PV_BT878P_2E] = { - .name = "Prolink Pixelview PV-BT878P+ (Rev.2E)", - .video_inputs = 5, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 0x01fe00, - .muxsel = { 2,3,1,1,-1 }, - .digital_mode = DIGITAL_MODE_CAMERA, - .audiomux = { 0x00400, 0x10400, 0x04400, 0x80000, 0x12400, 0x46000 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_LG_PAL_FM, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_remote = 1, - }, - /* ---- card 0x8b ---------------------------------- */ - [BTTV_BOARD_PV_M4900] = { - /* Sérgio Fortier */ - .name = "Prolink PixelView PlayTV MPEG2 PV-M4900", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x3f, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_YMEC_TVF_5533MF, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_radio = 1, - .has_remote = 1, - }, - /* ---- card 0x8c ---------------------------------- */ - [BTTV_BOARD_OSPREY440] = { - .name = "Osprey 440", - .video_inputs = 1, - .audio_inputs = 1, - .tuner = -1, - .svhs = 1, - .muxsel = { 2 }, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - }, - /* ---- card 0x8d ---------------------------------- */ - [BTTV_BOARD_ASOUND_SKYEYE] = { - .name = "Asound Skyeye PCTV", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 0, 0, 0, 1 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = 2, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - /* ---- card 0x8e ---------------------------------- */ - [BTTV_BOARD_SABRENT_TVFM] = { - .name = "Sabrent TV-FM (bttv version)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x108007, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 100000, 100002, 100002, 100000 }, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .pll = PLL_28, - .tuner_type = TUNER_TNF_5335MF, - .tuner_addr = ADDR_UNSET, - .has_radio = 1, - }, - /* ---- card 0x8f ---------------------------------- */ - [BTTV_BOARD_HAUPPAUGE_IMPACTVCB] = { - .name = "Hauppauge ImpactVCB (bt878)", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0x0f, /* old: 7 */ - .muxsel = { 0, 1, 3, 2 }, /* Composite 0-3 */ - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [BTTV_BOARD_MACHTV_MAGICTV] = { - /* Julian Calaby - * Slightly different from original MachTV definition (0x60) - - * FIXME: RegSpy says gpiomask should be "0x001c800f", but it - * stuffs up remote chip. Bug is a pin on the jaecs is not set - * properly (methinks) causing no keyup bits being set */ - - .name = "MagicTV", /* rebranded MachTV */ - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4 }, - .tuner_type = TUNER_TEMIC_4009FR5_PAL, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .pll = PLL_28, - .has_radio = 1, - .has_remote = 1, - }, -}; - -static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); - -/* ----------------------------------------------------------------------- */ - -static unsigned char eeprom_data[256]; - -/* - * identify card - */ -void __devinit bttv_idcard(struct bttv *btv) -{ - unsigned int gpiobits; - int i,type; - unsigned short tmp; - - /* read PCI subsystem ID */ - pci_read_config_word(btv->c.pci, PCI_SUBSYSTEM_ID, &tmp); - btv->cardid = tmp << 16; - pci_read_config_word(btv->c.pci, PCI_SUBSYSTEM_VENDOR_ID, &tmp); - btv->cardid |= tmp; - - if (0 != btv->cardid && 0xffffffff != btv->cardid) { - /* look for the card */ - for (type = -1, i = 0; cards[i].id != 0; i++) - if (cards[i].id == btv->cardid) - type = i; - - if (type != -1) { - /* found it */ - printk(KERN_INFO "bttv%d: detected: %s [card=%d], " - "PCI subsystem ID is %04x:%04x\n", - btv->c.nr,cards[type].name,cards[type].cardnr, - btv->cardid & 0xffff, - (btv->cardid >> 16) & 0xffff); - btv->c.type = cards[type].cardnr; - } else { - /* 404 */ - printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n", - btv->c.nr, btv->cardid & 0xffff, - (btv->cardid >> 16) & 0xffff); - printk(KERN_DEBUG "please mail id, board name and " - "the correct card= insmod option to video4linux-list@redhat.com\n"); - } - } - - /* let the user override the autodetected type */ - if (card[btv->c.nr] < bttv_num_tvcards) - btv->c.type=card[btv->c.nr]; - - /* print which card config we are using */ - printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->c.nr, - bttv_tvcards[btv->c.type].name, btv->c.type, - card[btv->c.nr] < bttv_num_tvcards - ? "insmod option" : "autodetected"); - - /* overwrite gpio stuff ?? */ - if (UNSET == audioall && UNSET == audiomux[0]) - return; - - if (UNSET != audiomux[0]) { - gpiobits = 0; - for (i = 0; i < 5; i++) { - bttv_tvcards[btv->c.type].audiomux[i] = audiomux[i]; - gpiobits |= audiomux[i]; - } - } else { - gpiobits = audioall; - for (i = 0; i < 5; i++) { - bttv_tvcards[btv->c.type].audiomux[i] = audioall; - } - } - bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits; - printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=", - btv->c.nr,bttv_tvcards[btv->c.type].gpiomask); - for (i = 0; i < 5; i++) { - printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].audiomux[i]); - } - printk("\n"); -} - -/* - * (most) board specific initialisations goes here - */ - -/* Some Modular Technology cards have an eeprom, but no subsystem ID */ -static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256]) -{ - int type = -1; - - if (0 == strncmp(eeprom_data,"GET MM20xPCTV",13)) - type = BTTV_BOARD_MODTEC_205; - else if (0 == strncmp(eeprom_data+20,"Picolo",7)) - type = BTTV_BOARD_EURESYS_PICOLO; - else if (eeprom_data[0] == 0x84 && eeprom_data[2]== 0) - type = BTTV_BOARD_HAUPPAUGE; /* old bt848 */ - - if (-1 != type) { - btv->c.type = type; - printk("bttv%d: detected by eeprom: %s [card=%d]\n", - btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type); - } -} - -static void flyvideo_gpio(struct bttv *btv) -{ - int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821; - int tuner=-1,ttype; - - gpio_inout(0xffffff, 0); - udelay(8); /* without this we would see the 0x1800 mask */ - gpio = gpio_read(); - /* FIXME: must restore OUR_EN ??? */ - - /* all cards provide GPIO info, some have an additional eeprom - * LR50: GPIO coding can be found lower right CP1 .. CP9 - * CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1. - * GPIO14-12: n.c. - * LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878) - - * lowest 3 bytes are remote control codes (no handshake needed) - * xxxFFF: No remote control chip soldered - * xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered - * Note: Some bits are Audio_Mask ! - */ - ttype=(gpio&0x0f0000)>>16; - switch(ttype) { - case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */ - break; - case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */ - break; - case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */ - break; - case 0x6: tuner=37;/* LG PAL (newer TAPC series) TAPC-G702P */ - break; - case 0xC: tuner=3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */ - break; - default: - printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr); - } - - has_remote = gpio & 0x800000; - has_radio = gpio & 0x400000; - /* unknown 0x200000; - * unknown2 0x100000; */ - is_capture_only = !(gpio & 0x008000); /* GPIO15 */ - has_tda9820_tda9821 = !(gpio & 0x004000); - is_lr90 = !(gpio & 0x002000); /* else LR26/LR50 (LR38/LR51 f. capture only) */ - /* - * gpio & 0x001000 output bit for audio routing */ - - if(is_capture_only) - tuner=4; /* No tuner present */ - - printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n", - btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio); - printk(KERN_INFO "bttv%d: FlyVideo LR90=%s tda9821/tda9820=%s capture_only=%s\n", - btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ", - is_capture_only?"yes":"no "); - - if(tuner!= -1) /* only set if known tuner autodetected, else let insmod option through */ - btv->tuner_type = tuner; - btv->has_radio = has_radio; - - /* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80 - * LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00 - * Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */ - if(has_tda9820_tda9821) btv->audio_hook = lt9415_audio; - /* todo: if(has_tda9874) btv->audio_hook = fv2000s_audio; */ -} - -static int miro_tunermap[] = { 0,6,2,3, 4,5,6,0, 3,0,4,5, 5,2,16,1, - 14,2,17,1, 4,1,4,3, 1,2,16,1, 4,4,4,4 }; -static int miro_fmtuner[] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, - 1,1,1,1, 1,1,1,0, 0,0,0,0, 0,1,0,0 }; - -static void miro_pinnacle_gpio(struct bttv *btv) -{ - int id,msp,gpio; - char *info; - - gpio_inout(0xffffff, 0); - gpio = gpio_read(); - id = ((gpio>>10) & 63) -1; - msp = bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx"); - if (id < 32) { - btv->tuner_type = miro_tunermap[id]; - if (0 == (gpio & 0x20)) { - btv->has_radio = 1; - if (!miro_fmtuner[id]) { - btv->has_matchbox = 1; - btv->mbox_we = (1<<6); - btv->mbox_most = (1<<7); - btv->mbox_clk = (1<<8); - btv->mbox_data = (1<<9); - btv->mbox_mask = (1<<6)|(1<<7)|(1<<8)|(1<<9); - } - } else { - btv->has_radio = 0; - } - if (-1 != msp) { - if (btv->c.type == BTTV_BOARD_MIRO) - btv->c.type = BTTV_BOARD_MIROPRO; - if (btv->c.type == BTTV_BOARD_PINNACLE) - btv->c.type = BTTV_BOARD_PINNACLEPRO; - } - printk(KERN_INFO - "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n", - btv->c.nr, id+1, btv->tuner_type, - !btv->has_radio ? "no" : - (btv->has_matchbox ? "matchbox" : "fmtuner"), - (-1 == msp) ? "no" : "yes"); - } else { - /* new cards with microtune tuner */ - id = 63 - id; - btv->has_radio = 0; - switch (id) { - case 1: - info = "PAL / mono"; - btv->tda9887_conf = TDA9887_INTERCARRIER; - break; - case 2: - info = "PAL+SECAM / stereo"; - btv->has_radio = 1; - btv->tda9887_conf = TDA9887_QSS; - break; - case 3: - info = "NTSC / stereo"; - btv->has_radio = 1; - btv->tda9887_conf = TDA9887_QSS; - break; - case 4: - info = "PAL+SECAM / mono"; - btv->tda9887_conf = TDA9887_QSS; - break; - case 5: - info = "NTSC / mono"; - btv->tda9887_conf = TDA9887_INTERCARRIER; - break; - case 6: - info = "NTSC / stereo"; - btv->tda9887_conf = TDA9887_INTERCARRIER; - break; - case 7: - info = "PAL / stereo"; - btv->tda9887_conf = TDA9887_INTERCARRIER; - break; - default: - info = "oops: unknown card"; - break; - } - if (-1 != msp) - btv->c.type = BTTV_BOARD_PINNACLEPRO; - printk(KERN_INFO - "bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n", - btv->c.nr, id, info, btv->has_radio ? "yes" : "no"); - btv->tuner_type = TUNER_MT2032; - } -} - -/* GPIO21 L: Buffer aktiv, H: Buffer inaktiv */ -#define LM1882_SYNC_DRIVE 0x200000L - -static void init_ids_eagle(struct bttv *btv) -{ - gpio_inout(0xffffff,0xFFFF37); - gpio_write(0x200020); - - /* flash strobe inverter ?! */ - gpio_write(0x200024); - - /* switch sync drive off */ - gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE); - - /* set BT848 muxel to 2 */ - btaor((2)<<5, ~(2<<5), BT848_IFORM); -} - -/* Muxsel helper for the IDS Eagle. - * the eagles does not use the standard muxsel-bits but - * has its own multiplexer */ -static void eagle_muxsel(struct bttv *btv, unsigned int input) -{ - btaor((2)<<5, ~(3<<5), BT848_IFORM); - gpio_bits(3,bttv_tvcards[btv->c.type].muxsel[input&7]); - - /* composite */ - /* set chroma ADC to sleep */ - btor(BT848_ADC_C_SLEEP, BT848_ADC); - /* set to composite video */ - btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); - btand(~BT848_CONTROL_COMP, BT848_O_CONTROL); - - /* switch sync drive off */ - gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE); -} - -static void gvc1100_muxsel(struct bttv *btv, unsigned int input) -{ - static const int masks[] = {0x30, 0x01, 0x12, 0x23}; - gpio_write(masks[input%4]); -} - -/* LMLBT4x initialization - to allow access to GPIO bits for sensors input and - alarms output - - GPIObit | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - assignment | TI | O3|INx| O2| O1|IN4|IN3|IN2|IN1| | | - - IN - sensor inputs, INx - sensor inputs and TI XORed together - O1,O2,O3 - alarm outputs (relays) - - OUT ENABLE 1 1 0 . 1 1 0 0 . 0 0 0 0 = 0x6C0 - -*/ - -static void init_lmlbt4x(struct bttv *btv) -{ - printk(KERN_DEBUG "LMLBT4x init\n"); - btwrite(0x000000, BT848_GPIO_REG_INP); - gpio_inout(0xffffff, 0x0006C0); - gpio_write(0x000000); -} - -static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input) -{ - unsigned int inmux = input % 8; - gpio_inout( 0xf, 0xf ); - gpio_bits( 0xf, inmux ); -} - -static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input) -{ - unsigned int inmux = input % 4; - gpio_inout( 3<<9, 3<<9 ); - gpio_bits( 3<<9, inmux<<9 ); -} - -/* ----------------------------------------------------------------------- */ - -static void bttv_reset_audio(struct bttv *btv) -{ - /* - * BT878A has a audio-reset register. - * 1. This register is an audio reset function but it is in - * function-0 (video capture) address space. - * 2. It is enough to do this once per power-up of the card. - * 3. There is a typo in the Conexant doc -- it is not at - * 0x5B, but at 0x058. (B is an odd-number, obviously a typo!). - * --//Shrikumar 030609 - */ - if (btv->id != 878) - return; - - if (bttv_debug) - printk("bttv%d: BT878A ARESET\n",btv->c.nr); - btwrite((1<<7), 0x058); - udelay(10); - btwrite( 0, 0x058); -} - -/* initialization part one -- before registering i2c bus */ -void __devinit bttv_init_card1(struct bttv *btv) -{ - switch (btv->c.type) { - case BTTV_BOARD_HAUPPAUGE: - case BTTV_BOARD_HAUPPAUGE878: - boot_msp34xx(btv,5); - break; - case BTTV_BOARD_VOODOOTV_FM: - boot_msp34xx(btv,20); - break; - case BTTV_BOARD_AVERMEDIA98: - boot_msp34xx(btv,11); - break; - case BTTV_BOARD_HAUPPAUGEPVR: - pvr_boot(btv); - break; - case BTTV_BOARD_TWINHAN_DST: - case BTTV_BOARD_AVDVBT_771: - case BTTV_BOARD_PINNACLESAT: - btv->use_i2c_hw = 1; - break; - case BTTV_BOARD_ADLINK_RTV24: - init_RTV24( btv ); - break; - - } - if (!bttv_tvcards[btv->c.type].has_dvb) - bttv_reset_audio(btv); -} - -/* initialization part two -- after registering i2c bus */ -void __devinit bttv_init_card2(struct bttv *btv) -{ - int tda9887; - int addr=ADDR_UNSET; - - btv->tuner_type = -1; - - if (BTTV_BOARD_UNKNOWN == btv->c.type) { - bttv_readee(btv,eeprom_data,0xa0); - identify_by_eeprom(btv,eeprom_data); - } - - switch (btv->c.type) { - case BTTV_BOARD_MIRO: - case BTTV_BOARD_MIROPRO: - case BTTV_BOARD_PINNACLE: - case BTTV_BOARD_PINNACLEPRO: - /* miro/pinnacle */ - miro_pinnacle_gpio(btv); - break; - case BTTV_BOARD_FLYVIDEO_98: - case BTTV_BOARD_MAXI: - case BTTV_BOARD_LIFE_FLYKIT: - case BTTV_BOARD_FLYVIDEO: - case BTTV_BOARD_TYPHOON_TVIEW: - case BTTV_BOARD_CHRONOS_VS2: - case BTTV_BOARD_FLYVIDEO_98FM: - case BTTV_BOARD_FLYVIDEO2000: - case BTTV_BOARD_FLYVIDEO98EZ: - case BTTV_BOARD_CONFERENCETV: - case BTTV_BOARD_LIFETEC_9415: - flyvideo_gpio(btv); - break; - case BTTV_BOARD_HAUPPAUGE: - case BTTV_BOARD_HAUPPAUGE878: - case BTTV_BOARD_HAUPPAUGEPVR: - /* pick up some config infos from the eeprom */ - bttv_readee(btv,eeprom_data,0xa0); - hauppauge_eeprom(btv); - break; - case BTTV_BOARD_AVERMEDIA98: - case BTTV_BOARD_AVPHONE98: - bttv_readee(btv,eeprom_data,0xa0); - avermedia_eeprom(btv); - break; - case BTTV_BOARD_PXC200: - init_PXC200(btv); - break; - case BTTV_BOARD_PICOLO_TETRA_CHIP: - picolo_tetra_init(btv); - break; - case BTTV_BOARD_VHX: - btv->has_radio = 1; - btv->has_matchbox = 1; - btv->mbox_we = 0x20; - btv->mbox_most = 0; - btv->mbox_clk = 0x08; - btv->mbox_data = 0x10; - btv->mbox_mask = 0x38; - break; - case BTTV_BOARD_VOBIS_BOOSTAR: - case BTTV_BOARD_TERRATV: - terratec_active_radio_upgrade(btv); - break; - case BTTV_BOARD_MAGICTVIEW061: - if (btv->cardid == 0x3002144f) { - btv->has_radio=1; - printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr); - } - break; - case BTTV_BOARD_STB2: - if (btv->cardid == 0x3060121a) { - /* Fix up entry for 3DFX VoodooTV 100, - which is an OEM STB card variant. */ - btv->has_radio=0; - btv->tuner_type=TUNER_TEMIC_NTSC; - } - break; - case BTTV_BOARD_OSPREY1x0: - case BTTV_BOARD_OSPREY1x0_848: - case BTTV_BOARD_OSPREY101_848: - case BTTV_BOARD_OSPREY1x1: - case BTTV_BOARD_OSPREY1x1_SVID: - case BTTV_BOARD_OSPREY2xx: - case BTTV_BOARD_OSPREY2x0_SVID: - case BTTV_BOARD_OSPREY2x0: - case BTTV_BOARD_OSPREY500: - case BTTV_BOARD_OSPREY540: - case BTTV_BOARD_OSPREY2000: - bttv_readee(btv,eeprom_data,0xa0); - osprey_eeprom(btv); - break; - case BTTV_BOARD_IDS_EAGLE: - init_ids_eagle(btv); - break; - case BTTV_BOARD_MODTEC_205: - bttv_readee(btv,eeprom_data,0xa0); - modtec_eeprom(btv); - break; - case BTTV_BOARD_LMLBT4: - init_lmlbt4x(btv); - break; - case BTTV_BOARD_TIBET_CS16: - tibetCS16_init(btv); - break; - case BTTV_BOARD_KODICOM_4400R: - kodicom4400r_init(btv); - break; - } - - /* pll configuration */ - if (!(btv->id==848 && btv->revision==0x11)) { - /* defaults from card list */ - if (PLL_28 == bttv_tvcards[btv->c.type].pll) { - btv->pll.pll_ifreq=28636363; - btv->pll.pll_crystal=BT848_IFORM_XT0; - } - if (PLL_35 == bttv_tvcards[btv->c.type].pll) { - btv->pll.pll_ifreq=35468950; - btv->pll.pll_crystal=BT848_IFORM_XT1; - } - /* insmod options can override */ - switch (pll[btv->c.nr]) { - case 0: /* none */ - btv->pll.pll_crystal = 0; - btv->pll.pll_ifreq = 0; - btv->pll.pll_ofreq = 0; - break; - case 1: /* 28 MHz */ - case 28: - btv->pll.pll_ifreq = 28636363; - btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal = BT848_IFORM_XT0; - break; - case 2: /* 35 MHz */ - case 35: - btv->pll.pll_ifreq = 35468950; - btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal = BT848_IFORM_XT1; - break; - } - } - btv->pll.pll_current = -1; - - /* tuner configuration (from card list / autodetect / insmod option) */ - if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) - addr = bttv_tvcards[btv->c.type].tuner_addr; - - if (UNSET != bttv_tvcards[btv->c.type].tuner_type) - if(UNSET == btv->tuner_type) - btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; - if (UNSET != tuner[btv->c.nr]) - btv->tuner_type = tuner[btv->c.nr]; - printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type); - - if (btv->tuner_type != UNSET) { - struct tuner_setup tun_setup; - - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; - tun_setup.type = btv->tuner_type; - tun_setup.addr = addr; - - bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); - } - - if (btv->tda9887_conf) { - bttv_call_i2c_clients(btv, TDA9887_SET_CONFIG, - &btv->tda9887_conf); - } - - btv->svhs = bttv_tvcards[btv->c.type].svhs; - if (svhs[btv->c.nr] != UNSET) - btv->svhs = svhs[btv->c.nr]; - if (remote[btv->c.nr] != UNSET) - btv->has_remote = remote[btv->c.nr]; - - if (bttv_tvcards[btv->c.type].has_radio) - btv->has_radio=1; - if (bttv_tvcards[btv->c.type].has_remote) - btv->has_remote=1; - if (!bttv_tvcards[btv->c.type].no_gpioirq) - btv->gpioirq=1; - if (bttv_tvcards[btv->c.type].audio_hook) - btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; - - if (bttv_tvcards[btv->c.type].digital_mode == DIGITAL_MODE_CAMERA) { - /* detect Bt832 chip for quartzsight digital camera */ - if ((bttv_I2CRead(btv, I2C_BT832_ALT1, "Bt832") >=0) || - (bttv_I2CRead(btv, I2C_BT832_ALT2, "Bt832") >=0)) - boot_bt832(btv); - } - - if (!autoload) - return; - - /* try to detect audio/fader chips */ - if (!bttv_tvcards[btv->c.type].no_msp34xx && - bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) - request_module("msp3400"); - - if (bttv_tvcards[btv->c.type].msp34xx_alt && - bttv_I2CRead(btv, I2C_MSP3400_ALT, "MSP34xx (alternate address)") >=0) - request_module("msp3400"); - - if (!bttv_tvcards[btv->c.type].no_tda9875 && - bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) - request_module("tda9875"); - - if (!bttv_tvcards[btv->c.type].no_tda7432 && - bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) - request_module("tda7432"); - - if (bttv_tvcards[btv->c.type].needs_tvaudio) - request_module("tvaudio"); - - /* tuner modules */ - tda9887 = 0; - if (btv->tda9887_conf) - tda9887 = 1; - if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb && - bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0) - tda9887 = 1; - /* Hybrid DVB card, DOES have a tda9887 */ - if (btv->c.type == BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE) - tda9887 = 1; - if((btv->tuner_type == TUNER_PHILIPS_FM1216ME_MK3) || - (btv->tuner_type == TUNER_PHILIPS_FM1236_MK3) || - (btv->tuner_type == TUNER_PHILIPS_FM1256_IH3) || - tda9887) - request_module("tda9887"); - if (btv->tuner_type != UNSET) - request_module("tuner"); -} - - -/* ----------------------------------------------------------------------- */ - -static void modtec_eeprom(struct bttv *btv) -{ - if( strncmp(&(eeprom_data[0x1e]),"Temic 4066 FY5",14) ==0) { - btv->tuner_type=TUNER_TEMIC_4066FY5_PAL_I; - printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", - btv->c.nr,&eeprom_data[0x1e]); - } else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) { - btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I; - printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", - btv->c.nr,&eeprom_data[0x1e]); - } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) { - btv->tuner_type=TUNER_PHILIPS_NTSC; - printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", - btv->c.nr,&eeprom_data[0x1e]); - } else { - printk("bttv%d: Modtec: Unknown TunerString: %s\n", - btv->c.nr,&eeprom_data[0x1e]); - } -} - -static void __devinit hauppauge_eeprom(struct bttv *btv) -{ - struct tveeprom tv; - - tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data); - btv->tuner_type = tv.tuner_type; - btv->has_radio = tv.has_radio; - - printk("bttv%d: Hauppauge eeprom indicates model#%d\n", - btv->c.nr, tv.model); - - /* - * Some of the 878 boards have duplicate PCI IDs. Switch the board - * type based on model #. - */ - if(tv.model == 64900) { - printk("bttv%d: Switching board type from %s to %s\n", - btv->c.nr, - bttv_tvcards[btv->c.type].name, - bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name); - btv->c.type = BTTV_BOARD_HAUPPAUGE_IMPACTVCB; - } -} - -static int terratec_active_radio_upgrade(struct bttv *btv) -{ - int freq; - - btv->has_radio = 1; - btv->has_matchbox = 1; - btv->mbox_we = 0x10; - btv->mbox_most = 0x20; - btv->mbox_clk = 0x08; - btv->mbox_data = 0x04; - btv->mbox_mask = 0x3c; - - btv->mbox_iow = 1 << 8; - btv->mbox_ior = 1 << 9; - btv->mbox_csel = 1 << 10; - - freq=88000/62.5; - tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */ - if (0x1ed8 == tea5757_read(btv)) { - printk("bttv%d: Terratec Active Radio Upgrade found.\n", - btv->c.nr); - btv->has_radio = 1; - btv->has_matchbox = 1; - } else { - btv->has_radio = 0; - btv->has_matchbox = 0; - } - return 0; -} - - -/* ----------------------------------------------------------------------- */ - -/* - * minimal bootstrap for the WinTV/PVR -- upload altera firmware. - * - * The hcwamc.rbf firmware file is on the Hauppauge driver CD. Have - * a look at Pvr/pvr45xxx.EXE (self-extracting zip archive, can be - * unpacked with unzip). - */ -#define PVR_GPIO_DELAY 10 - -#define BTTV_ALT_DATA 0x000001 -#define BTTV_ALT_DCLK 0x100000 -#define BTTV_ALT_NCONFIG 0x800000 - -static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) -{ - u32 n; - u8 bits; - int i; - - gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG); - gpio_write(0); - udelay(PVR_GPIO_DELAY); - - gpio_write(BTTV_ALT_NCONFIG); - udelay(PVR_GPIO_DELAY); - - for (n = 0; n < microlen; n++) { - bits = micro[n]; - for ( i = 0 ; i < 8 ; i++ ) { - gpio_bits(BTTV_ALT_DCLK,0); - if (bits & 0x01) - gpio_bits(BTTV_ALT_DATA,BTTV_ALT_DATA); - else - gpio_bits(BTTV_ALT_DATA,0); - gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK); - bits >>= 1; - } - } - gpio_bits(BTTV_ALT_DCLK,0); - udelay(PVR_GPIO_DELAY); - - /* begin Altera init loop (Not necessary,but doesn't hurt) */ - for (i = 0 ; i < 30 ; i++) { - gpio_bits(BTTV_ALT_DCLK,0); - gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK); - } - gpio_bits(BTTV_ALT_DCLK,0); - return 0; -} - -static int __devinit pvr_boot(struct bttv *btv) -{ - const struct firmware *fw_entry; - int rc; - - rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev); - if (rc != 0) { - printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n", - btv->c.nr); - return rc; - } - rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size); - printk(KERN_INFO "bttv%d: altera firmware upload %s\n", - btv->c.nr, (rc < 0) ? "failed" : "ok"); - release_firmware(fw_entry); - return rc; -} - -/* ----------------------------------------------------------------------- */ -/* some osprey specific stuff */ - -static void __devinit osprey_eeprom(struct bttv *btv) -{ - int i = 0; - unsigned char *ee = eeprom_data; - unsigned long serial = 0; - - if (btv->c.type == 0) { - /* this might be an antique... check for MMAC label in eeprom */ - if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { - unsigned char checksum = 0; - for (i =0; i<21; i++) - checksum += ee[i]; - if (checksum != ee[21]) - return; - btv->c.type = BTTV_BOARD_OSPREY1x0_848; - for (i = 12; i < 21; i++) - serial *= 10, serial += ee[i] - '0'; - } - } else { - unsigned short type; - int offset = 4*16; - - for(; offset < 8*16; offset += 16) { - unsigned short checksum = 0; - /* verify the checksum */ - for(i = 0; i<14; i++) checksum += ee[i+offset]; - checksum = ~checksum; /* no idea why */ - if ((((checksum>>8)&0x0FF) == ee[offset+14]) && - ((checksum & 0x0FF) == ee[offset+15])) { - break; - } - } - - if (offset >= 8*16) - return; - - /* found a valid descriptor */ - type = (ee[offset+4]<<8) | (ee[offset+5]); - - switch(type) { - - /* 848 based */ - case 0x0004: - btv->c.type = BTTV_BOARD_OSPREY1x0_848; - break; - case 0x0005: - btv->c.type = BTTV_BOARD_OSPREY101_848; - break; - - /* 878 based */ - case 0x0012: - case 0x0013: - btv->c.type = BTTV_BOARD_OSPREY1x0; - break; - case 0x0014: - case 0x0015: - btv->c.type = BTTV_BOARD_OSPREY1x1; - break; - case 0x0016: - case 0x0017: - case 0x0020: - btv->c.type = BTTV_BOARD_OSPREY1x1_SVID; - break; - case 0x0018: - case 0x0019: - case 0x001E: - case 0x001F: - btv->c.type = BTTV_BOARD_OSPREY2xx; - break; - case 0x001A: - case 0x001B: - btv->c.type = BTTV_BOARD_OSPREY2x0_SVID; - break; - case 0x0040: - btv->c.type = BTTV_BOARD_OSPREY500; - break; - case 0x0050: - case 0x0056: - btv->c.type = BTTV_BOARD_OSPREY540; - /* bttv_osprey_540_init(btv); */ - break; - case 0x0060: - case 0x0070: - btv->c.type = BTTV_BOARD_OSPREY2x0; - /* enable output on select control lines */ - gpio_inout(0xffffff,0x000303); - break; - default: - /* unknown...leave generic, but get serial # */ - break; - } - serial = (ee[offset+6] << 24) - | (ee[offset+7] << 16) - | (ee[offset+8] << 8) - | (ee[offset+9]); - } - - printk(KERN_INFO "bttv%d: osprey eeprom: card=%d name=%s serial=%ld\n", - btv->c.nr, btv->c.type, bttv_tvcards[btv->c.type].name,serial); -} - -/* ----------------------------------------------------------------------- */ -/* AVermedia specific stuff, from bktr_card.c */ - -static int tuner_0_table[] = { - TUNER_PHILIPS_NTSC, TUNER_PHILIPS_PAL /* PAL-BG*/, - TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL /* PAL-I*/, - TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL, - TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM, - TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL, - TUNER_PHILIPS_FM1216ME_MK3 }; - -static int tuner_1_table[] = { - TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL, - TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, - TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, - TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */ - TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL}; - -static void __devinit avermedia_eeprom(struct bttv *btv) -{ - int tuner_make,tuner_tv_fm,tuner_format,tuner=0; - - tuner_make = (eeprom_data[0x41] & 0x7); - tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3; - tuner_format = (eeprom_data[0x42] & 0xf0) >> 4; - btv->has_remote = (eeprom_data[0x42] & 0x01); - - if (tuner_make == 0 || tuner_make == 2) - if(tuner_format <=0x0a) - tuner = tuner_0_table[tuner_format]; - if (tuner_make == 1) - if(tuner_format <=9) - tuner = tuner_1_table[tuner_format]; - - if (tuner_make == 4) - if(tuner_format == 0x09) - tuner = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */ - - printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=", - btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]); - if(tuner) { - btv->tuner_type=tuner; - printk("%d",tuner); - } else - printk("Unknown type"); - printk(" radio:%s remote control:%s\n", - tuner_tv_fm ? "yes" : "no", - btv->has_remote ? "yes" : "no"); -} - -/* used on Voodoo TV/FM (Voodoo 200), S0 wired to 0x10000 */ -void bttv_tda9880_setnorm(struct bttv *btv, int norm) -{ - /* fix up our card entry */ - if(norm==VIDEO_MODE_NTSC) { - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x957fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x957fff; - dprintk("bttv_tda9880_setnorm to NTSC\n"); - } - else { - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x947fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x947fff; - dprintk("bttv_tda9880_setnorm to PAL\n"); - } - /* set GPIO according */ - gpio_bits(bttv_tvcards[btv->c.type].gpiomask, - bttv_tvcards[btv->c.type].audiomux[btv->audio]); -} - - -/* - * reset/enable the MSP on some Hauppauge cards - * Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! - * - * Hauppauge: pin 5 - * Voodoo: pin 20 - */ -static void __devinit boot_msp34xx(struct bttv *btv, int pin) -{ - int mask = (1 << pin); - - gpio_inout(mask,mask); - gpio_bits(mask,0); - udelay(2500); - gpio_bits(mask,mask); - - if (bttv_gpio) - bttv_gpio_tracking(btv,"msp34xx"); - if (bttv_verbose) - printk(KERN_INFO "bttv%d: Hauppauge/Voodoo msp34xx: reset line " - "init [%d]\n", btv->c.nr, pin); -} - -static void __devinit boot_bt832(struct bttv *btv) -{ -} - -/* ----------------------------------------------------------------------- */ -/* Imagenation L-Model PXC200 Framegrabber */ -/* This is basically the same procedure as - * used by Alessandro Rubini in his pxc200 - * driver, but using BTTV functions */ - -static void __devinit init_PXC200(struct bttv *btv) -{ - static int vals[] __devinitdata = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x00 }; - unsigned int i; - int tmp; - u32 val; - - /* Initialise GPIO-connevted stuff */ - gpio_inout(0xffffff, (1<<13)); - gpio_write(0); - udelay(3); - gpio_write(1<<13); - /* GPIO inputs are pulled up, so no need to drive - * reset pin any longer */ - gpio_bits(0xffffff, 0); - if (bttv_gpio) - bttv_gpio_tracking(btv,"pxc200"); - - /* we could/should try and reset/control the AD pots? but - right now we simply turned off the crushing. Without - this the AGC drifts drifts - remember the EN is reverse logic --> - setting BT848_ADC_AGC_EN disable the AGC - tboult@eecs.lehigh.edu - */ - - btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC); - - /* Initialise MAX517 DAC */ - printk(KERN_INFO "Setting DAC reference voltage level ...\n"); - bttv_I2CWrite(btv,0x5E,0,0x80,1); - - /* Initialise 12C508 PIC */ - /* The I2CWrite and I2CRead commmands are actually to the - * same chips - but the R/W bit is included in the address - * argument so the numbers are different */ - - - printk(KERN_INFO "Initialising 12C508 PIC chip ...\n"); - - /* First of all, enable the clock line. This is used in the PXC200-F */ - val = btread(BT848_GPIO_DMA_CTL); - val |= BT848_GPIO_DMA_CTL_GPCLKMODE; - btwrite(val, BT848_GPIO_DMA_CTL); - - /* Then, push to 0 the reset pin long enough to reset the * - * device same as above for the reset line, but not the same - * value sent to the GPIO-connected stuff - * which one is the good one? */ - gpio_inout(0xffffff,(1<<2)); - gpio_write(0); - udelay(10); - gpio_write(1<<2); - - for (i = 0; i < ARRAY_SIZE(vals); i++) { - tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1); - if (tmp != -1) { - printk(KERN_INFO - "I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n", - vals[i],tmp,bttv_I2CRead(btv,0x1F,NULL)); - } - } - - printk(KERN_INFO "PXC200 Initialised.\n"); -} - - - -/* ----------------------------------------------------------------------- */ -/* - * The Adlink RTV-24 (aka Angelo) has some special initialisation to unlock - * it. This apparently involves the following procedure for each 878 chip: - * - * 1) write 0x00C3FEFF to the GPIO_OUT_EN register - * - * 2) write to GPIO_DATA - * - 0x0E - * - sleep 1ms - * - 0x10 + 0x0E - * - sleep 10ms - * - 0x0E - * read from GPIO_DATA into buf (uint_32) - * - if ( data>>18 & 0x01 != 0) || ( buf>>19 & 0x01 != 1 ) - * error. ERROR_CPLD_Check_Failed stop. - * - * 3) write to GPIO_DATA - * - write 0x4400 + 0x0E - * - sleep 10ms - * - write 0x4410 + 0x0E - * - sleep 1ms - * - write 0x0E - * read from GPIO_DATA into buf (uint_32) - * - if ( buf>>18 & 0x01 ) || ( buf>>19 && 0x01 != 0 ) - * error. ERROR_CPLD_Check_Failed. - */ -/* ----------------------------------------------------------------------- */ -static void -init_RTV24 (struct bttv *btv) -{ - uint32_t dataRead = 0; - long watchdog_value = 0x0E; - - printk (KERN_INFO - "bttv%d: Adlink RTV-24 initialisation in progress ...\n", - btv->c.nr); - - btwrite (0x00c3feff, BT848_GPIO_OUT_EN); - - btwrite (0 + watchdog_value, BT848_GPIO_DATA); - msleep (1); - btwrite (0x10 + watchdog_value, BT848_GPIO_DATA); - msleep (10); - btwrite (0 + watchdog_value, BT848_GPIO_DATA); - - dataRead = btread (BT848_GPIO_DATA); - - if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) { - printk (KERN_INFO - "bttv%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n", - btv->c.nr, dataRead); - } - - btwrite (0x4400 + watchdog_value, BT848_GPIO_DATA); - msleep (10); - btwrite (0x4410 + watchdog_value, BT848_GPIO_DATA); - msleep (1); - btwrite (watchdog_value, BT848_GPIO_DATA); - msleep (1); - dataRead = btread (BT848_GPIO_DATA); - - if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) { - printk (KERN_INFO - "bttv%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n", - btv->c.nr, dataRead); - - return; - } - - printk (KERN_INFO - "bttv%d: Adlink RTV-24 initialisation complete.\n", btv->c.nr); -} - - - -/* ----------------------------------------------------------------------- */ -/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */ -/* - * Copyright (c) 1999 Csaba Halasz - * This code is placed under the terms of the GNU General Public License - * - * Brutally hacked by Dan Sheridan djs52 8/3/00 - */ - -static void bus_low(struct bttv *btv, int bit) -{ - if (btv->mbox_ior) { - gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); - udelay(5); - } - - gpio_bits(bit,0); - udelay(5); - - if (btv->mbox_ior) { - gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); - udelay(5); - } -} - -static void bus_high(struct bttv *btv, int bit) -{ - if (btv->mbox_ior) { - gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); - udelay(5); - } - - gpio_bits(bit,bit); - udelay(5); - - if (btv->mbox_ior) { - gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); - udelay(5); - } -} - -static int bus_in(struct bttv *btv, int bit) -{ - if (btv->mbox_ior) { - gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); - udelay(5); - - gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); - udelay(5); - } - return gpio_read() & (bit); -} - -/* TEA5757 register bits */ -#define TEA_FREQ 0:14 -#define TEA_BUFFER 15:15 - -#define TEA_SIGNAL_STRENGTH 16:17 - -#define TEA_PORT1 18:18 -#define TEA_PORT0 19:19 - -#define TEA_BAND 20:21 -#define TEA_BAND_FM 0 -#define TEA_BAND_MW 1 -#define TEA_BAND_LW 2 -#define TEA_BAND_SW 3 - -#define TEA_MONO 22:22 -#define TEA_ALLOW_STEREO 0 -#define TEA_FORCE_MONO 1 - -#define TEA_SEARCH_DIRECTION 23:23 -#define TEA_SEARCH_DOWN 0 -#define TEA_SEARCH_UP 1 - -#define TEA_STATUS 24:24 -#define TEA_STATUS_TUNED 0 -#define TEA_STATUS_SEARCHING 1 - -/* Low-level stuff */ -static int tea5757_read(struct bttv *btv) -{ - unsigned long timeout; - int value = 0; - int i; - - /* better safe than sorry */ - gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we); - - if (btv->mbox_ior) { - gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); - udelay(5); - } - - if (bttv_gpio) - bttv_gpio_tracking(btv,"tea5757 read"); - - bus_low(btv,btv->mbox_we); - bus_low(btv,btv->mbox_clk); - - udelay(10); - timeout= jiffies + HZ; - - /* wait for DATA line to go low; error if it doesn't */ - while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout)) - schedule(); - if (bus_in(btv,btv->mbox_data)) { - printk(KERN_WARNING "bttv%d: tea5757: read timeout\n",btv->c.nr); - return -1; - } - - dprintk("bttv%d: tea5757:",btv->c.nr); - for(i = 0; i < 24; i++) - { - udelay(5); - bus_high(btv,btv->mbox_clk); - udelay(5); - dprintk("%c",(bus_in(btv,btv->mbox_most) == 0)?'T':'-'); - bus_low(btv,btv->mbox_clk); - value <<= 1; - value |= (bus_in(btv,btv->mbox_data) == 0)?0:1; /* MSB first */ - dprintk("%c", (bus_in(btv,btv->mbox_most) == 0)?'S':'M'); - } - dprintk("\nbttv%d: tea5757: read 0x%X\n", btv->c.nr, value); - return value; -} - -static int tea5757_write(struct bttv *btv, int value) -{ - int i; - int reg = value; - - gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data); - - if (btv->mbox_ior) { - gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); - udelay(5); - } - if (bttv_gpio) - bttv_gpio_tracking(btv,"tea5757 write"); - - dprintk("bttv%d: tea5757: write 0x%X\n", btv->c.nr, value); - bus_low(btv,btv->mbox_clk); - bus_high(btv,btv->mbox_we); - for(i = 0; i < 25; i++) - { - if (reg & 0x1000000) - bus_high(btv,btv->mbox_data); - else - bus_low(btv,btv->mbox_data); - reg <<= 1; - bus_high(btv,btv->mbox_clk); - udelay(10); - bus_low(btv,btv->mbox_clk); - udelay(10); - } - bus_low(btv,btv->mbox_we); /* unmute !!! */ - return 0; -} - -void tea5757_set_freq(struct bttv *btv, unsigned short freq) -{ - dprintk("tea5757_set_freq %d\n",freq); - tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */ -} - - -/* ----------------------------------------------------------------------- */ -/* winview */ - -static void winview_audio(struct bttv *btv, struct video_audio *v, int set) -{ - /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */ - int bits_out, loops, vol, data; - - if (!set) { - /* Fixed by Leandro Lucarella flags |= VIDEO_AUDIO_VOLUME; - return; - } - - /* 32 levels logarithmic */ - vol = 32 - ((v->volume>>11)); - /* units */ - bits_out = (PT2254_DBS_IN_2>>(vol%5)); - /* tens */ - bits_out |= (PT2254_DBS_IN_10>>(vol/5)); - bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL; - data = gpio_read(); - data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA| - WINVIEW_PT2254_STROBE); - for (loops = 17; loops >= 0 ; loops--) { - if (bits_out & (1<mode & VIDEO_SOUND_LANG1) - con = 0x000; - if (v->mode & VIDEO_SOUND_LANG2) - con = 0x300; - if (v->mode & VIDEO_SOUND_STEREO) - con = 0x200; -/* if (v->mode & VIDEO_SOUND_MONO) - * con = 0x100; */ - gpio_bits(0x300, con); - } else { - v->mode = VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -static void -gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned int val, con; - - if (btv->radio_user) - return; - - val = gpio_read(); - if (set) { - con = 0x000; - if (v->mode & VIDEO_SOUND_LANG2) { - if (v->mode & VIDEO_SOUND_LANG1) { - /* LANG1 + LANG2 */ - con = 0x100; - } - else { - /* LANG2 */ - con = 0x300; - } - } - if (con != (val & 0x300)) { - gpio_bits(0x300, con); - if (bttv_gpio) - bttv_gpio_tracking(btv,"gvbctv5pci"); - } - } else { - switch (val & 0x70) { - case 0x10: - v->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - break; - case 0x30: - v->mode = VIDEO_SOUND_LANG2; - break; - case 0x50: - v->mode = VIDEO_SOUND_LANG1; - break; - case 0x60: - v->mode = VIDEO_SOUND_STEREO; - break; - case 0x70: - v->mode = VIDEO_SOUND_MONO; - break; - default: - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } - } -} - -/* - * Mario Medina Nussbaum - * I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo, - * 0xdde enables mono and 0xccd enables sap - * - * Petr Vandrovec - * P.S.: At least mask in line above is wrong - GPIO pins 3,2 select - * input/output sound connection, so both must be set for output mode. - * - * Looks like it's needed only for the "tvphone", the "tvphone 98" - * handles this with a tda9840 - * - */ -static void -avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set) -{ - int val = 0; - - if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ - val = 0x02; - if (v->mode & VIDEO_SOUND_STEREO) - val = 0x01; - if (val) { - gpio_bits(0x03,val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"avermedia"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1; - return; - } -} - -static void -avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) -{ - int val = 0; - - if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ - val = 0x01; - if (v->mode & VIDEO_SOUND_STEREO) /* STEREO */ - val = 0x02; - btaor(val, ~0x03, BT848_GPIO_DATA); - if (bttv_gpio) - bttv_gpio_tracking(btv,"avermedia"); - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - return; - } -} - -/* Lifetec 9415 handling */ -static void -lt9415_audio(struct bttv *btv, struct video_audio *v, int set) -{ - int val = 0; - - if (gpio_read() & 0x4000) { - v->mode = VIDEO_SOUND_MONO; - return; - } - - if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */ - val = 0x0080; - if (v->mode & VIDEO_SOUND_STEREO) /* A2 stereo */ - val = 0x0880; - if ((v->mode & VIDEO_SOUND_LANG1) || - (v->mode & VIDEO_SOUND_MONO)) - val = 0; - gpio_bits(0x0880, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"lt9415"); - } else { - /* autodetect doesn't work with this card :-( */ - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - return; - } -} - -/* TDA9821 on TerraTV+ Bt848, Bt878 */ -static void -terratv_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned int con = 0; - - if (set) { - gpio_inout(0x180000,0x180000); - if (v->mode & VIDEO_SOUND_LANG2) - con = 0x080000; - if (v->mode & VIDEO_SOUND_STEREO) - con = 0x180000; - gpio_bits(0x180000, con); - if (bttv_gpio) - bttv_gpio_tracking(btv,"terratv"); - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -static void -winfast2000_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned long val = 0; - - if (set) { - /*btor (0xc32000, BT848_GPIO_OUT_EN);*/ - if (v->mode & VIDEO_SOUND_MONO) /* Mono */ - val = 0x420000; - if (v->mode & VIDEO_SOUND_LANG1) /* Mono */ - val = 0x420000; - if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ - val = 0x410000; - if (v->mode & VIDEO_SOUND_STEREO) /* Stereo */ - val = 0x020000; - if (val) { - gpio_bits(0x430000, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"winfast2000"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -/* - * Dariusz Kowalewski - * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM - * revision 9B has on-board TDA9874A sound decoder). - * - * Note: There are card variants without tda9874a. Forcing the "stereo sound route" - * will mute this cards. - */ -static void -pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned int val = 0; - - if (btv->radio_user) - return; - - if (set) { - if (v->mode & VIDEO_SOUND_MONO) { - val = 0x01; - } - if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2)) - || (v->mode & VIDEO_SOUND_STEREO)) { - val = 0x02; - } - if (val) { - gpio_bits(0x03,val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"pvbt878p9b"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -/* - * Dariusz Kowalewski - * sound control for FlyVideo 2000S (with tda9874 decoder) - * based on pvbt878p9b_audio() - this is not tested, please fix!!! - */ -static void -fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned int val = 0xffff; - - if (btv->radio_user) - return; - if (set) { - if (v->mode & VIDEO_SOUND_MONO) { - val = 0x0000; - } - if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2)) - || (v->mode & VIDEO_SOUND_STEREO)) { - val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */ - } - if (val != 0xffff) { - gpio_bits(0x1800, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"fv2000s"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -/* - * sound control for Canopus WinDVR PCI - * Masaki Suzuki - */ -static void -windvr_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned long val = 0; - - if (set) { - if (v->mode & VIDEO_SOUND_MONO) - val = 0x040000; - if (v->mode & VIDEO_SOUND_LANG1) - val = 0; - if (v->mode & VIDEO_SOUND_LANG2) - val = 0x100000; - if (v->mode & VIDEO_SOUND_STEREO) - val = 0; - if (val) { - gpio_bits(0x140000, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"windvr"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -/* - * sound control for AD-TVK503 - * Hiroshi Takekawa - */ -static void -adtvk503_audio(struct bttv *btv, struct video_audio *v, int set) -{ - unsigned int con = 0xffffff; - - /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */ - - if (set) { - /* btor(***, BT848_GPIO_OUT_EN); */ - if (v->mode & VIDEO_SOUND_LANG1) - con = 0x00000000; - if (v->mode & VIDEO_SOUND_LANG2) - con = 0x00180000; - if (v->mode & VIDEO_SOUND_STEREO) - con = 0x00000000; - if (v->mode & VIDEO_SOUND_MONO) - con = 0x00060000; - if (con != 0xffffff) { - gpio_bits(0x1e0000,con); - if (bttv_gpio) - bttv_gpio_tracking(btv, "adtvk503"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -} - -/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas] - * - * This is needed because rv605 don't use a normal multiplex, but a crosspoint - * switch instead (CD22M3494E). This IC can have multiple active connections - * between Xn (input) and Yn (output) pins. We need to clear any existing - * connection prior to establish a new one, pulsing the STROBE pin. - * - * The board hardwire Y0 (xpoint) to MUX1 and MUXOUT to Yin. - * GPIO pins are wired as: - * GPIO[0:3] - AX[0:3] (xpoint) - P1[0:3] (microcontroler) - * GPIO[4:6] - AY[0:2] (xpoint) - P1[4:6] (microcontroler) - * GPIO[7] - DATA (xpoint) - P1[7] (microcontroler) - * GPIO[8] - - P3[5] (microcontroler) - * GPIO[9] - RESET (xpoint) - P3[6] (microcontroler) - * GPIO[10] - STROBE (xpoint) - P3[7] (microcontroler) - * GPINTR - - P3[4] (microcontroler) - * - * The microcontroler is a 80C32 like. It should be possible to change xpoint - * configuration either directly (as we are doing) or using the microcontroler - * which is also wired to I2C interface. I have no further info on the - * microcontroler features, one would need to disassembly the firmware. - * note: the vendor refused to give any information on this product, all - * that stuff was found using a multimeter! :) - */ -static void rv605_muxsel(struct bttv *btv, unsigned int input) -{ - /* reset all conections */ - gpio_bits(0x200,0x200); - mdelay(1); - gpio_bits(0x200,0x000); - mdelay(1); - - /* create a new conection */ - gpio_bits(0x480,0x080); - gpio_bits(0x480,0x480); - mdelay(1); - gpio_bits(0x480,0x080); - mdelay(1); -} - -/* Tibet Systems 'Progress DVR' CS16 muxsel helper [Chris Fanning] - * - * The CS16 (available on eBay cheap) is a PCI board with four Fusion - * 878A chips, a PCI bridge, an Atmel microcontroller, four sync seperator - * chips, ten eight input analog multiplexors, a not chip and a few - * other components. - * - * 16 inputs on a secondary bracket are provided and can be selected - * from each of the four capture chips. Two of the eight input - * multiplexors are used to select from any of the 16 input signals. - * - * Unsupported hardware capabilities: - * . A video output monitor on the secondary bracket can be selected from - * one of the 878A chips. - * . Another passthrough but I haven't spent any time investigating it. - * . Digital I/O (logic level connected to GPIO) is available from an - * onboard header. - * - * The on chip input mux should always be set to 2. - * GPIO[16:19] - Video input selection - * GPIO[0:3] - Video output monitor select (only available from one 878A) - * GPIO[?:?] - Digital I/O. - * - * There is an ATMEL microcontroller with an 8031 core on board. I have not - * determined what function (if any) it provides. With the microcontroller - * and sync seperator chips a guess is that it might have to do with video - * switching and maybe some digital I/O. - */ -static void tibetCS16_muxsel(struct bttv *btv, unsigned int input) -{ - /* video mux */ - gpio_bits(0x0f0000, input << 16); -} - -static void tibetCS16_init(struct bttv *btv) -{ - /* enable gpio bits, mask obtained via btSpy */ - gpio_inout(0xffffff, 0x0f7fff); - gpio_write(0x0f7fff); -} - -/* - * The following routines for the Kodicom-4400r get a little mind-twisting. - * There is a "master" controller and three "slave" controllers, together - * an analog switch which connects any of 16 cameras to any of the BT87A's. - * The analog switch is controlled by the "master", but the detection order - * of the four BT878A chips is in an order which I just don't understand. - * The "master" is actually the second controller to be detected. The - * logic on the board uses logical numbers for the 4 controlers, but - * those numbers are different from the detection sequence. When working - * with the analog switch, we need to "map" from the detection sequence - * over to the board's logical controller number. This mapping sequence - * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical - * unit 3, the second (which is the master) is logical unit 0, etc. - * We need to maintain the status of the analog switch (which of the 16 - * cameras is connected to which of the 4 controllers). Rather than - * add to the bttv structure for this, we use the data reserved for - * the mbox (unused for this card type). - */ - -/* - * First a routine to set the analog switch, which controls which camera - * is routed to which controller. The switch comprises an X-address - * (gpio bits 0-3, representing the camera, ranging from 0-15), and a - * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3). - * A data value (gpio bit 7) of '1' enables the switch, and '0' disables - * the switch. A STROBE bit (gpio bit 8) latches the data value into the - * specified address. The idea is to set the address and data, then bring - * STROBE high, and finally bring STROBE back to low. - */ -static void kodicom4400r_write(struct bttv *btv, - unsigned char xaddr, - unsigned char yaddr, - unsigned char data) { - unsigned int udata; - - udata = (data << 7) | ((yaddr&3) << 4) | (xaddr&0xf); - gpio_bits(0x1ff, udata); /* write ADDR and DAT */ - gpio_bits(0x1ff, udata | (1 << 8)); /* strobe high */ - gpio_bits(0x1ff, udata); /* strobe low */ -} - -/* - * Next the mux select. Both the "master" and "slave" 'cards' (controllers) - * use this routine. The routine finds the "master" for the card, maps - * the controller number from the detected position over to the logical - * number, writes the appropriate data to the analog switch, and housekeeps - * the local copy of the switch information. The parameter 'input' is the - * requested camera number (0 - 15). - */ -static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) -{ - char *sw_status; - int xaddr, yaddr; - struct bttv *mctlr; - static unsigned char map[4] = {3, 0, 2, 1}; - - mctlr = master[btv->c.nr]; - if (mctlr == NULL) { /* ignore if master not yet detected */ - return; - } - yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */ - yaddr = map[yaddr]; - sw_status = (char *)(&mctlr->mbox_we); - xaddr = input & 0xf; - /* Check if the controller/camera pair has changed, else ignore */ - if (sw_status[yaddr] != xaddr) - { - /* "open" the old switch, "close" the new one, save the new */ - kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0); - sw_status[yaddr] = xaddr; - kodicom4400r_write(mctlr, xaddr, yaddr, 1); - } -} - -/* - * During initialisation, we need to reset the analog switch. We - * also preset the switch to map the 4 connectors on the card to the - * *user's* (see above description of kodicom4400r_muxsel) channels - * 0 through 3 - */ -static void kodicom4400r_init(struct bttv *btv) -{ - char *sw_status = (char *)(&btv->mbox_we); - int ix; - - gpio_inout(0x0003ff, 0x0003ff); - gpio_write(1 << 9); /* reset MUX */ - gpio_write(0); - /* Preset camera 0 to the 4 controllers */ - for (ix=0; ix<4; ix++) { - sw_status[ix] = ix; - kodicom4400r_write(btv, ix, ix, 1); - } - /* - * Since this is the "master", we need to set up the - * other three controller chips' pointers to this structure - * for later use in the muxsel routine. - */ - if ((btv->c.nr<1) || (btv->c.nr>BTTV_MAX-3)) - return; - master[btv->c.nr-1] = btv; - master[btv->c.nr] = btv; - master[btv->c.nr+1] = btv; - master[btv->c.nr+2] = btv; -} - -/* The Grandtec X-Guard framegrabber card uses two Dual 4-channel - * video multiplexers to provide up to 16 video inputs. These - * multiplexers are controlled by the lower 8 GPIO pins of the - * bt878. The multiplexers probably Pericom PI5V331Q or similar. - - * xxx0 is pin xxx of multiplexer U5, - * yyy1 is pin yyy of multiplexer U2 - */ -#define ENA0 0x01 -#define ENB0 0x02 -#define ENA1 0x04 -#define ENB1 0x08 - -#define IN10 0x10 -#define IN00 0x20 -#define IN11 0x40 -#define IN01 0x80 - -static void xguard_muxsel(struct bttv *btv, unsigned int input) -{ - static const int masks[] = { - ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10, - ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10, - ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11, - ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11, - }; - gpio_write(masks[input%16]); -} -static void picolo_tetra_init(struct bttv *btv) -{ - /*This is the video input redirection fonctionality : I DID NOT USED IT. */ - btwrite (0x08<<16,BT848_GPIO_DATA);/*GPIO[19] [==> 4053 B+C] set to 1 */ - btwrite (0x04<<16,BT848_GPIO_DATA);/*GPIO[18] [==> 4053 A] set to 1*/ -} -static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input) -{ - - dprintk (KERN_DEBUG "bttv%d : picolo_tetra_muxsel => input = %d\n",btv->c.nr,input); - /*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/ - /*GPIO[20]&GPIO[21] used to choose the right input*/ - btwrite (input<<20,BT848_GPIO_DATA); - -} - -/* - * ivc120_muxsel [Added by Alan Garfield ] - * - * The IVC120G security card has 4 i2c controlled TDA8540 matrix - * swichers to provide 16 channels to MUX0. The TDA8540's have - * 4 indepedant outputs and as such the IVC120G also has the - * optional "Monitor Out" bus. This allows the card to be looking - * at one input while the monitor is looking at another. - * - * Since I've couldn't be bothered figuring out how to add an - * independant muxsel for the monitor bus, I've just set it to - * whatever the card is looking at. - * - * OUT0 of the TDA8540's is connected to MUX0 (0x03) - * OUT1 of the TDA8540's is connected to "Monitor Out" (0x0C) - * - * TDA8540_ALT3 IN0-3 = Channel 13 - 16 (0x03) - * TDA8540_ALT4 IN0-3 = Channel 1 - 4 (0x03) - * TDA8540_ALT5 IN0-3 = Channel 5 - 8 (0x03) - * TDA8540_ALT6 IN0-3 = Channel 9 - 12 (0x03) - * - */ - -/* All 7 possible sub-ids for the TDA8540 Matrix Switcher */ -#define I2C_TDA8540 0x90 -#define I2C_TDA8540_ALT1 0x92 -#define I2C_TDA8540_ALT2 0x94 -#define I2C_TDA8540_ALT3 0x96 -#define I2C_TDA8540_ALT4 0x98 -#define I2C_TDA8540_ALT5 0x9a -#define I2C_TDA8540_ALT6 0x9c - -static void ivc120_muxsel(struct bttv *btv, unsigned int input) -{ - /* Simple maths */ - int key = input % 4; - int matrix = input / 4; - - dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n", - btv->c.nr, input, matrix, key); - - /* Handles the input selection on the TDA8540's */ - bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00, - ((matrix == 3) ? (key | key << 2) : 0x00), 1); - bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x00, - ((matrix == 0) ? (key | key << 2) : 0x00), 1); - bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x00, - ((matrix == 1) ? (key | key << 2) : 0x00), 1); - bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x00, - ((matrix == 2) ? (key | key << 2) : 0x00), 1); - - /* Handles the output enables on the TDA8540's */ - bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x02, - ((matrix == 3) ? 0x03 : 0x00), 1); /* 13 - 16 */ - bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x02, - ((matrix == 0) ? 0x03 : 0x00), 1); /* 1-4 */ - bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x02, - ((matrix == 1) ? 0x03 : 0x00), 1); /* 5-8 */ - bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02, - ((matrix == 2) ? 0x03 : 0x00), 1); /* 9-12 */ - - /* Selects MUX0 for input on the 878 */ - btaor((0)<<5, ~(3<<5), BT848_IFORM); -} - - -/* PXC200 muxsel helper - * luke@syseng.anu.edu.au - * another transplant - * from Alessandro Rubini (rubini@linux.it) - * - * There are 4 kinds of cards: - * PXC200L which is bt848 - * PXC200F which is bt848 with PIC controlling mux - * PXC200AL which is bt878 - * PXC200AF which is bt878 with PIC controlling mux - */ -#define PX_CFG_PXC200F 0x01 -#define PX_FLAG_PXC200A 0x00001000 /* a pxc200A is bt-878 based */ -#define PX_I2C_PIC 0x0f -#define PX_PXC200A_CARDID 0x200a1295 -#define PX_I2C_CMD_CFG 0x00 - -static void PXC200_muxsel(struct bttv *btv, unsigned int input) -{ - int rc; - long mux; - int bitmask; - unsigned char buf[2]; - - /* Read PIC config to determine if this is a PXC200F */ - /* PX_I2C_CMD_CFG*/ - buf[0]=0; - buf[1]=0; - rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1); - if (rc) { - printk(KERN_DEBUG "bttv%d: PXC200_muxsel: pic cfg write failed:%d\n", btv->c.nr,rc); - /* not PXC ? do nothing */ - return; - } - - rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL); - if (!(rc & PX_CFG_PXC200F)) { - printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc); - return; - } - - - /* The multiplexer in the 200F is handled by the GPIO port */ - /* get correct mapping between inputs */ - /* mux = bttv_tvcards[btv->type].muxsel[input] & 3; */ - /* ** not needed!? */ - mux = input; - - /* make sure output pins are enabled */ - /* bitmask=0x30f; */ - bitmask=0x302; - /* check whether we have a PXC200A */ - if (btv->cardid == PX_PXC200A_CARDID) { - bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */ - bitmask |= 7<<4; /* the DAC */ - } - btwrite(bitmask, BT848_GPIO_OUT_EN); - - bitmask = btread(BT848_GPIO_DATA); - if (btv->cardid == PX_PXC200A_CARDID) - bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7); - else /* older device */ - bitmask = (bitmask & ~0x300) | ((mux & 3) << 8); - btwrite(bitmask,BT848_GPIO_DATA); - - /* - * Was "to be safe, set the bt848 to input 0" - * Actually, since it's ok at load time, better not messing - * with these bits (on PXC200AF you need to set mux 2 here) - * - * needed because bttv-driver sets mux before calling this function - */ - if (btv->cardid == PX_PXC200A_CARDID) - btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM); - else /* older device */ - btand(~BT848_IFORM_MUXSEL,BT848_IFORM); - - printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux); -} - -/* ----------------------------------------------------------------------- */ -/* motherboard chipset specific stuff */ - -void __devinit bttv_check_chipset(void) -{ - int pcipci_fail = 0; - struct pci_dev *dev = NULL; - - if (pci_pci_problems & PCIPCI_FAIL) - pcipci_fail = 1; - if (pci_pci_problems & (PCIPCI_TRITON|PCIPCI_NATOMA|PCIPCI_VIAETBF)) - triton1 = 1; - if (pci_pci_problems & PCIPCI_VSFX) - vsfx = 1; -#ifdef PCIPCI_ALIMAGIK - if (pci_pci_problems & PCIPCI_ALIMAGIK) - latency = 0x0A; -#endif - - - /* print warnings about any quirks found */ - if (triton1) - printk(KERN_INFO "bttv: Host bridge needs ETBF enabled.\n"); - if (vsfx) - printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n"); - if (pcipci_fail) { - printk(KERN_INFO "bttv: bttv and your chipset may not work " - "together.\n"); - if (!no_overlay) { - printk(KERN_INFO "bttv: overlay will be disabled.\n"); - no_overlay = 1; - } else { - printk(KERN_INFO "bttv: overlay forced. Use this " - "option at your own risk.\n"); - } - } - if (UNSET != latency) - printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency); - while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82441, dev))) { - unsigned char b; - pci_read_config_byte(dev, 0x53, &b); - if (bttv_debug) - printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, " - "bufcon=0x%02x\n",b); - } -} - -int __devinit bttv_handle_chipset(struct bttv *btv) -{ - unsigned char command; - - if (!triton1 && !vsfx && UNSET == latency) - return 0; - - if (bttv_verbose) { - if (triton1) - printk(KERN_INFO "bttv%d: enabling ETBF (430FX/VP3 compatibilty)\n",btv->c.nr); - if (vsfx && btv->id >= 878) - printk(KERN_INFO "bttv%d: enabling VSFX\n",btv->c.nr); - if (UNSET != latency) - printk(KERN_INFO "bttv%d: setting pci timer to %d\n", - btv->c.nr,latency); - } - - if (btv->id < 878) { - /* bt848 (mis)uses a bit in the irq mask for etbf */ - if (triton1) - btv->triton1 = BT848_INT_ETBF; - } else { - /* bt878 has a bit in the pci config space for it */ - pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command); - if (triton1) - command |= BT878_EN_TBFX; - if (vsfx) - command |= BT878_EN_VSFX; - pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command); - } - if (UNSET != latency) - pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency); - return 0; -} - - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c deleted file mode 100644 index 2505ae5a7b97..000000000000 --- a/drivers/media/video/bttv-driver.c +++ /dev/null @@ -1,4265 +0,0 @@ -/* - - bttv - Bt848 frame grabber driver - - Copyright (C) 1996,97,98 Ralph Metzler - & Marcus Metzler - (c) 1999-2002 Gerd Knorr - - some v4l2 code lines are taken from Justin's bttv2 driver which is - (c) 2000 Justin Schoeman - - 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 -#include -#include "bttvp.h" -#include - -#include - -#include -#include - -#include "rds.h" - - -unsigned int bttv_num; /* number of Bt848s in use */ -struct bttv bttvs[BTTV_MAX]; - -unsigned int bttv_debug; -unsigned int bttv_verbose = 1; -unsigned int bttv_gpio; - -/* config variables */ -#ifdef __BIG_ENDIAN -static unsigned int bigendian=1; -#else -static unsigned int bigendian; -#endif -static unsigned int radio[BTTV_MAX]; -static unsigned int irq_debug; -static unsigned int gbuffers = 8; -static unsigned int gbufsize = 0x208000; - -static int video_nr = -1; -static int radio_nr = -1; -static int vbi_nr = -1; -static int debug_latency; - -static unsigned int fdsr; - -/* options */ -static unsigned int combfilter; -static unsigned int lumafilter; -static unsigned int automute = 1; -static unsigned int chroma_agc; -static unsigned int adc_crush = 1; -static unsigned int whitecrush_upper = 0xCF; -static unsigned int whitecrush_lower = 0x7F; -static unsigned int vcr_hack; -static unsigned int irq_iswitch; -static unsigned int uv_ratio = 50; -static unsigned int full_luma_range; -static unsigned int coring; -extern int no_overlay; - -/* API features (turn on/off stuff for testing) */ -static unsigned int v4l2 = 1; - -/* insmod args */ -module_param(bttv_verbose, int, 0644); -module_param(bttv_gpio, int, 0644); -module_param(bttv_debug, int, 0644); -module_param(irq_debug, int, 0644); -module_param(debug_latency, int, 0644); - -module_param(fdsr, int, 0444); -module_param(video_nr, int, 0444); -module_param(radio_nr, int, 0444); -module_param(vbi_nr, int, 0444); -module_param(gbuffers, int, 0444); -module_param(gbufsize, int, 0444); - -module_param(v4l2, int, 0644); -module_param(bigendian, int, 0644); -module_param(irq_iswitch, int, 0644); -module_param(combfilter, int, 0444); -module_param(lumafilter, int, 0444); -module_param(automute, int, 0444); -module_param(chroma_agc, int, 0444); -module_param(adc_crush, int, 0444); -module_param(whitecrush_upper, int, 0444); -module_param(whitecrush_lower, int, 0444); -module_param(vcr_hack, int, 0444); -module_param(uv_ratio, int, 0444); -module_param(full_luma_range, int, 0444); -module_param(coring, int, 0444); - -module_param_array(radio, int, NULL, 0444); - -MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)"); -MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian"); -MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)"); -MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)"); -MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)"); -MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)"); -MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8"); -MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000"); -MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)"); -MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)"); -MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)"); -MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207"); -MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127"); -MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)"); -MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler"); -MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50"); -MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)"); -MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)"); - -MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards"); -MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); -MODULE_LICENSE("GPL"); - -/* ----------------------------------------------------------------------- */ -/* sysfs */ - -static ssize_t show_card(struct class_device *cd, char *buf) -{ - struct video_device *vfd = to_video_device(cd); - struct bttv *btv = dev_get_drvdata(vfd->dev); - return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); -} -static CLASS_DEVICE_ATTR(card, S_IRUGO, show_card, NULL); - -/* ----------------------------------------------------------------------- */ -/* static data */ - -/* special timing tables from conexant... */ -static u8 SRAM_Table[][60] = -{ - /* PAL digital input over GPIO[7:0] */ - { - 45, // 45 bytes following - 0x36,0x11,0x01,0x00,0x90,0x02,0x05,0x10,0x04,0x16, - 0x12,0x05,0x11,0x00,0x04,0x12,0xC0,0x00,0x31,0x00, - 0x06,0x51,0x08,0x03,0x89,0x08,0x07,0xC0,0x44,0x00, - 0x81,0x01,0x01,0xA9,0x0D,0x02,0x02,0x50,0x03,0x37, - 0x37,0x00,0xAF,0x21,0x00 - }, - /* NTSC digital input over GPIO[7:0] */ - { - 51, // 51 bytes following - 0x0C,0xC0,0x00,0x00,0x90,0x02,0x03,0x10,0x03,0x06, - 0x10,0x04,0x12,0x12,0x05,0x02,0x13,0x04,0x19,0x00, - 0x04,0x39,0x00,0x06,0x59,0x08,0x03,0x83,0x08,0x07, - 0x03,0x50,0x00,0xC0,0x40,0x00,0x86,0x01,0x01,0xA6, - 0x0D,0x02,0x03,0x11,0x01,0x05,0x37,0x00,0xAC,0x21, - 0x00, - }, - // TGB_NTSC392 // quartzsight - // This table has been modified to be used for Fusion Rev D - { - 0x2A, // size of table = 42 - 0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24, - 0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10, - 0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00, - 0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3, - 0x20, 0x00 - } -}; - -const struct bttv_tvnorm bttv_tvnorms[] = { - /* PAL-BDGHI */ - /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ - /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ - { - .v4l2_id = V4L2_STD_PAL, - .name = "PAL", - .Fsc = 35468950, - .swidth = 924, - .sheight = 576, - .totalwidth = 1135, - .adelay = 0x7f, - .bdelay = 0x72, - .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), - .scaledtwidth = 1135, - .hdelayx1 = 186, - .hactivex1 = 924, - .vdelay = 0x20, - .vbipack = 255, - .sram = 0, - /* ITU-R frame line number of the first VBI line - we can capture, of the first and second field. */ - .vbistart = { 7,320 }, - },{ - .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, - .name = "NTSC", - .Fsc = 28636363, - .swidth = 768, - .sheight = 480, - .totalwidth = 910, - .adelay = 0x68, - .bdelay = 0x5d, - .iform = (BT848_IFORM_NTSC|BT848_IFORM_XT0), - .scaledtwidth = 910, - .hdelayx1 = 128, - .hactivex1 = 910, - .vdelay = 0x1a, - .vbipack = 144, - .sram = 1, - .vbistart = { 10, 273 }, - },{ - .v4l2_id = V4L2_STD_SECAM, - .name = "SECAM", - .Fsc = 35468950, - .swidth = 924, - .sheight = 576, - .totalwidth = 1135, - .adelay = 0x7f, - .bdelay = 0xb0, - .iform = (BT848_IFORM_SECAM|BT848_IFORM_XT1), - .scaledtwidth = 1135, - .hdelayx1 = 186, - .hactivex1 = 922, - .vdelay = 0x20, - .vbipack = 255, - .sram = 0, /* like PAL, correct? */ - .vbistart = { 7, 320 }, - },{ - .v4l2_id = V4L2_STD_PAL_Nc, - .name = "PAL-Nc", - .Fsc = 28636363, - .swidth = 640, - .sheight = 576, - .totalwidth = 910, - .adelay = 0x68, - .bdelay = 0x5d, - .iform = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0), - .scaledtwidth = 780, - .hdelayx1 = 130, - .hactivex1 = 734, - .vdelay = 0x1a, - .vbipack = 144, - .sram = -1, - .vbistart = { 7, 320 }, - },{ - .v4l2_id = V4L2_STD_PAL_M, - .name = "PAL-M", - .Fsc = 28636363, - .swidth = 640, - .sheight = 480, - .totalwidth = 910, - .adelay = 0x68, - .bdelay = 0x5d, - .iform = (BT848_IFORM_PAL_M|BT848_IFORM_XT0), - .scaledtwidth = 780, - .hdelayx1 = 135, - .hactivex1 = 754, - .vdelay = 0x1a, - .vbipack = 144, - .sram = -1, - .vbistart = { 10, 273 }, - },{ - .v4l2_id = V4L2_STD_PAL_N, - .name = "PAL-N", - .Fsc = 35468950, - .swidth = 768, - .sheight = 576, - .totalwidth = 1135, - .adelay = 0x7f, - .bdelay = 0x72, - .iform = (BT848_IFORM_PAL_N|BT848_IFORM_XT1), - .scaledtwidth = 944, - .hdelayx1 = 186, - .hactivex1 = 922, - .vdelay = 0x20, - .vbipack = 144, - .sram = -1, - .vbistart = { 7, 320}, - },{ - .v4l2_id = V4L2_STD_NTSC_M_JP, - .name = "NTSC-JP", - .Fsc = 28636363, - .swidth = 640, - .sheight = 480, - .totalwidth = 910, - .adelay = 0x68, - .bdelay = 0x5d, - .iform = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0), - .scaledtwidth = 780, - .hdelayx1 = 135, - .hactivex1 = 754, - .vdelay = 0x16, - .vbipack = 144, - .sram = -1, - .vbistart = {10, 273}, - },{ - /* that one hopefully works with the strange timing - * which video recorders produce when playing a NTSC - * tape on a PAL TV ... */ - .v4l2_id = V4L2_STD_PAL_60, - .name = "PAL-60", - .Fsc = 35468950, - .swidth = 924, - .sheight = 480, - .totalwidth = 1135, - .adelay = 0x7f, - .bdelay = 0x72, - .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), - .scaledtwidth = 1135, - .hdelayx1 = 186, - .hactivex1 = 924, - .vdelay = 0x1a, - .vbipack = 255, - .vtotal = 524, - .sram = -1, - .vbistart = { 10, 273 }, - } -}; -static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms); - -/* ----------------------------------------------------------------------- */ -/* bttv format list - packed pixel formats must come first */ -static const struct bttv_format bttv_formats[] = { - { - .name = "8 bpp, gray", - .palette = VIDEO_PALETTE_GREY, - .fourcc = V4L2_PIX_FMT_GREY, - .btformat = BT848_COLOR_FMT_Y8, - .depth = 8, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "8 bpp, dithered color", - .palette = VIDEO_PALETTE_HI240, - .fourcc = V4L2_PIX_FMT_HI240, - .btformat = BT848_COLOR_FMT_RGB8, - .depth = 8, - .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER, - },{ - .name = "15 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB555, - .fourcc = V4L2_PIX_FMT_RGB555, - .btformat = BT848_COLOR_FMT_RGB15, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "15 bpp RGB, be", - .palette = -1, - .fourcc = V4L2_PIX_FMT_RGB555X, - .btformat = BT848_COLOR_FMT_RGB15, - .btswap = 0x03, /* byteswap */ - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "16 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB565, - .fourcc = V4L2_PIX_FMT_RGB565, - .btformat = BT848_COLOR_FMT_RGB16, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "16 bpp RGB, be", - .palette = -1, - .fourcc = V4L2_PIX_FMT_RGB565X, - .btformat = BT848_COLOR_FMT_RGB16, - .btswap = 0x03, /* byteswap */ - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "24 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB24, - .fourcc = V4L2_PIX_FMT_BGR24, - .btformat = BT848_COLOR_FMT_RGB24, - .depth = 24, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "32 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB32, - .fourcc = V4L2_PIX_FMT_BGR32, - .btformat = BT848_COLOR_FMT_RGB32, - .depth = 32, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "32 bpp RGB, be", - .palette = -1, - .fourcc = V4L2_PIX_FMT_RGB32, - .btformat = BT848_COLOR_FMT_RGB32, - .btswap = 0x0f, /* byte+word swap */ - .depth = 32, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "4:2:2, packed, YUYV", - .palette = VIDEO_PALETTE_YUV422, - .fourcc = V4L2_PIX_FMT_YUYV, - .btformat = BT848_COLOR_FMT_YUY2, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "4:2:2, packed, YUYV", - .palette = VIDEO_PALETTE_YUYV, - .fourcc = V4L2_PIX_FMT_YUYV, - .btformat = BT848_COLOR_FMT_YUY2, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "4:2:2, packed, UYVY", - .palette = VIDEO_PALETTE_UYVY, - .fourcc = V4L2_PIX_FMT_UYVY, - .btformat = BT848_COLOR_FMT_YUY2, - .btswap = 0x03, /* byteswap */ - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "4:2:2, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV422P, - .fourcc = V4L2_PIX_FMT_YUV422P, - .btformat = BT848_COLOR_FMT_YCrCb422, - .depth = 16, - .flags = FORMAT_FLAGS_PLANAR, - .hshift = 1, - .vshift = 0, - },{ - .name = "4:2:0, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV420P, - .fourcc = V4L2_PIX_FMT_YUV420, - .btformat = BT848_COLOR_FMT_YCrCb422, - .depth = 12, - .flags = FORMAT_FLAGS_PLANAR, - .hshift = 1, - .vshift = 1, - },{ - .name = "4:2:0, planar, Y-Cr-Cb", - .palette = -1, - .fourcc = V4L2_PIX_FMT_YVU420, - .btformat = BT848_COLOR_FMT_YCrCb422, - .depth = 12, - .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb, - .hshift = 1, - .vshift = 1, - },{ - .name = "4:1:1, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV411P, - .fourcc = V4L2_PIX_FMT_YUV411P, - .btformat = BT848_COLOR_FMT_YCrCb411, - .depth = 12, - .flags = FORMAT_FLAGS_PLANAR, - .hshift = 2, - .vshift = 0, - },{ - .name = "4:1:0, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV410P, - .fourcc = V4L2_PIX_FMT_YUV410, - .btformat = BT848_COLOR_FMT_YCrCb411, - .depth = 9, - .flags = FORMAT_FLAGS_PLANAR, - .hshift = 2, - .vshift = 2, - },{ - .name = "4:1:0, planar, Y-Cr-Cb", - .palette = -1, - .fourcc = V4L2_PIX_FMT_YVU410, - .btformat = BT848_COLOR_FMT_YCrCb411, - .depth = 9, - .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb, - .hshift = 2, - .vshift = 2, - },{ - .name = "raw scanlines", - .palette = VIDEO_PALETTE_RAW, - .fourcc = -1, - .btformat = BT848_COLOR_FMT_RAW, - .depth = 8, - .flags = FORMAT_FLAGS_RAW, - } -}; -static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats); - -/* ----------------------------------------------------------------------- */ - -#define V4L2_CID_PRIVATE_CHROMA_AGC (V4L2_CID_PRIVATE_BASE + 0) -#define V4L2_CID_PRIVATE_COMBFILTER (V4L2_CID_PRIVATE_BASE + 1) -#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 2) -#define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_PRIVATE_BASE + 3) -#define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_PRIVATE_BASE + 4) -#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_PRIVATE_BASE + 5) -#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_PRIVATE_BASE + 6) -#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_PRIVATE_BASE + 7) -#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_PRIVATE_BASE + 8) -#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_PRIVATE_BASE + 9) -#define V4L2_CID_PRIVATE_CORING (V4L2_CID_PRIVATE_BASE + 10) -#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 11) - -static const struct v4l2_queryctrl no_ctl = { - .name = "42", - .flags = V4L2_CTRL_FLAG_DISABLED, -}; -static const struct v4l2_queryctrl bttv_ctls[] = { - /* --- video --- */ - { - .id = V4L2_CID_BRIGHTNESS, - .name = "Brightness", - .minimum = 0, - .maximum = 65535, - .step = 256, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_CONTRAST, - .name = "Contrast", - .minimum = 0, - .maximum = 65535, - .step = 128, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_SATURATION, - .name = "Saturation", - .minimum = 0, - .maximum = 65535, - .step = 128, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_HUE, - .name = "Hue", - .minimum = 0, - .maximum = 65535, - .step = 256, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - /* --- audio --- */ - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 65535, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_BALANCE, - .name = "Balance", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_BASS, - .name = "Bass", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_TREBLE, - .name = "Treble", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - /* --- private --- */ - { - .id = V4L2_CID_PRIVATE_CHROMA_AGC, - .name = "chroma agc", - .minimum = 0, - .maximum = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_PRIVATE_COMBFILTER, - .name = "combfilter", - .minimum = 0, - .maximum = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_PRIVATE_AUTOMUTE, - .name = "automute", - .minimum = 0, - .maximum = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_PRIVATE_LUMAFILTER, - .name = "luma decimation filter", - .minimum = 0, - .maximum = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_PRIVATE_AGC_CRUSH, - .name = "agc crush", - .minimum = 0, - .maximum = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_PRIVATE_VCR_HACK, - .name = "vcr hack", - .minimum = 0, - .maximum = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER, - .name = "whitecrush upper", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 0xCF, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER, - .name = "whitecrush lower", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 0x7F, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_PRIVATE_UV_RATIO, - .name = "uv ratio", - .minimum = 0, - .maximum = 100, - .step = 1, - .default_value = 50, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE, - .name = "full luma range", - .minimum = 0, - .maximum = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_PRIVATE_CORING, - .name = "coring", - .minimum = 0, - .maximum = 3, - .step = 1, - .default_value = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - } - - - -}; -static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls); - -/* ----------------------------------------------------------------------- */ -/* resource management */ - -static -int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit) -{ - if (fh->resources & bit) - /* have it already allocated */ - return 1; - - /* is it free? */ - mutex_lock(&btv->reslock); - if (btv->resources & bit) { - /* no, someone else uses it */ - mutex_unlock(&btv->reslock); - return 0; - } - /* it's free, grab it */ - fh->resources |= bit; - btv->resources |= bit; - mutex_unlock(&btv->reslock); - return 1; -} - -static -int check_btres(struct bttv_fh *fh, int bit) -{ - return (fh->resources & bit); -} - -static -int locked_btres(struct bttv *btv, int bit) -{ - return (btv->resources & bit); -} - -static -void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits) -{ - if ((fh->resources & bits) != bits) { - /* trying to free ressources not allocated by us ... */ - printk("bttv: BUG! (btres)\n"); - } - mutex_lock(&btv->reslock); - fh->resources &= ~bits; - btv->resources &= ~bits; - mutex_unlock(&btv->reslock); -} - -/* ----------------------------------------------------------------------- */ -/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */ - -/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C - PLL_X = Reference pre-divider (0=1, 1=2) - PLL_C = Post divider (0=6, 1=4) - PLL_I = Integer input - PLL_F = Fractional input - - F_input = 28.636363 MHz: - PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0 -*/ - -static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout) -{ - unsigned char fl, fh, fi; - - /* prevent overflows */ - fin/=4; - fout/=4; - - fout*=12; - fi=fout/fin; - - fout=(fout%fin)*256; - fh=fout/fin; - - fout=(fout%fin)*256; - fl=fout/fin; - - btwrite(fl, BT848_PLL_F_LO); - btwrite(fh, BT848_PLL_F_HI); - btwrite(fi|BT848_PLL_X, BT848_PLL_XCI); -} - -static void set_pll(struct bttv *btv) -{ - int i; - - if (!btv->pll.pll_crystal) - return; - - if (btv->pll.pll_ofreq == btv->pll.pll_current) { - dprintk("bttv%d: PLL: no change required\n",btv->c.nr); - return; - } - - if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) { - /* no PLL needed */ - if (btv->pll.pll_current == 0) - return; - bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n", - btv->c.nr,btv->pll.pll_ifreq); - btwrite(0x00,BT848_TGCTRL); - btwrite(0x00,BT848_PLL_XCI); - btv->pll.pll_current = 0; - return; - } - - bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr, - btv->pll.pll_ifreq, btv->pll.pll_ofreq); - set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq); - - for (i=0; i<10; i++) { - /* Let other people run while the PLL stabilizes */ - bttv_printk("."); - msleep(10); - - if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) { - btwrite(0,BT848_DSTATUS); - } else { - btwrite(0x08,BT848_TGCTRL); - btv->pll.pll_current = btv->pll.pll_ofreq; - bttv_printk(" ok\n"); - return; - } - } - btv->pll.pll_current = -1; - bttv_printk("failed\n"); - return; -} - -/* used to switch between the bt848's analog/digital video capture modes */ -static void bt848A_set_timing(struct bttv *btv) -{ - int i, len; - int table_idx = bttv_tvnorms[btv->tvnorm].sram; - int fsc = bttv_tvnorms[btv->tvnorm].Fsc; - - if (UNSET == bttv_tvcards[btv->c.type].muxsel[btv->input]) { - dprintk("bttv%d: load digital timing table (table_idx=%d)\n", - btv->c.nr,table_idx); - - /* timing change...reset timing generator address */ - btwrite(0x00, BT848_TGCTRL); - btwrite(0x02, BT848_TGCTRL); - btwrite(0x00, BT848_TGCTRL); - - len=SRAM_Table[table_idx][0]; - for(i = 1; i <= len; i++) - btwrite(SRAM_Table[table_idx][i],BT848_TGLB); - btv->pll.pll_ofreq = 27000000; - - set_pll(btv); - btwrite(0x11, BT848_TGCTRL); - btwrite(0x41, BT848_DVSIF); - } else { - btv->pll.pll_ofreq = fsc; - set_pll(btv); - btwrite(0x0, BT848_DVSIF); - } -} - -/* ----------------------------------------------------------------------- */ - -static void bt848_bright(struct bttv *btv, int bright) -{ - int value; - - // printk("bttv: set bright: %d\n",bright); // DEBUG - btv->bright = bright; - - /* We want -128 to 127 we get 0-65535 */ - value = (bright >> 8) - 128; - btwrite(value & 0xff, BT848_BRIGHT); -} - -static void bt848_hue(struct bttv *btv, int hue) -{ - int value; - - btv->hue = hue; - - /* -128 to 127 */ - value = (hue >> 8) - 128; - btwrite(value & 0xff, BT848_HUE); -} - -static void bt848_contrast(struct bttv *btv, int cont) -{ - int value,hibit; - - btv->contrast = cont; - - /* 0-511 */ - value = (cont >> 7); - hibit = (value >> 6) & 4; - btwrite(value & 0xff, BT848_CONTRAST_LO); - btaor(hibit, ~4, BT848_E_CONTROL); - btaor(hibit, ~4, BT848_O_CONTROL); -} - -static void bt848_sat(struct bttv *btv, int color) -{ - int val_u,val_v,hibits; - - btv->saturation = color; - - /* 0-511 for the color */ - val_u = ((color * btv->opt_uv_ratio) / 50) >> 7; - val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254; - hibits = (val_u >> 7) & 2; - hibits |= (val_v >> 8) & 1; - btwrite(val_u & 0xff, BT848_SAT_U_LO); - btwrite(val_v & 0xff, BT848_SAT_V_LO); - btaor(hibits, ~3, BT848_E_CONTROL); - btaor(hibits, ~3, BT848_O_CONTROL); -} - -/* ----------------------------------------------------------------------- */ - -static int -video_mux(struct bttv *btv, unsigned int input) -{ - int mux,mask2; - - if (input >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - - /* needed by RemoteVideo MX */ - mask2 = bttv_tvcards[btv->c.type].gpiomask2; - if (mask2) - gpio_inout(mask2,mask2); - - if (input == btv->svhs) { - btor(BT848_CONTROL_COMP, BT848_E_CONTROL); - btor(BT848_CONTROL_COMP, BT848_O_CONTROL); - } else { - btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); - btand(~BT848_CONTROL_COMP, BT848_O_CONTROL); - } - mux = bttv_tvcards[btv->c.type].muxsel[input] & 3; - btaor(mux<<5, ~(3<<5), BT848_IFORM); - dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n", - btv->c.nr,input,mux); - - /* card specific hook */ - if(bttv_tvcards[btv->c.type].muxsel_hook) - bttv_tvcards[btv->c.type].muxsel_hook (btv, input); - return 0; -} - -static char *audio_modes[] = { - "audio: tuner", "audio: radio", "audio: extern", - "audio: intern", "audio: off" -}; - -static int -audio_mux(struct bttv *btv, int mode) -{ - int val,mux,i2c_mux,signal; - - gpio_inout(bttv_tvcards[btv->c.type].gpiomask, - bttv_tvcards[btv->c.type].gpiomask); - signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC; - - switch (mode) { - case AUDIO_MUTE: - btv->audio |= AUDIO_MUTE; - break; - case AUDIO_UNMUTE: - btv->audio &= ~AUDIO_MUTE; - break; - case AUDIO_TUNER: - case AUDIO_RADIO: - case AUDIO_EXTERN: - case AUDIO_INTERN: - btv->audio &= AUDIO_MUTE; - btv->audio |= mode; - } - i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio; - if (btv->opt_automute && !signal && !btv->radio_user) - mux = AUDIO_OFF; - - val = bttv_tvcards[btv->c.type].audiomux[mux]; - gpio_bits(bttv_tvcards[btv->c.type].gpiomask,val); - if (bttv_gpio) - bttv_gpio_tracking(btv,audio_modes[mux]); - if (!in_interrupt()) - bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(i2c_mux)); - return 0; -} - -static void -i2c_vidiocschan(struct bttv *btv) -{ - struct video_channel c; - - memset(&c,0,sizeof(c)); - c.norm = btv->tvnorm; - c.channel = btv->input; - bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c); - if (btv->c.type == BTTV_BOARD_VOODOOTV_FM) - bttv_tda9880_setnorm(btv,c.norm); -} - -static int -set_tvnorm(struct bttv *btv, unsigned int norm) -{ - const struct bttv_tvnorm *tvnorm; - - if (norm < 0 || norm >= BTTV_TVNORMS) - return -EINVAL; - - btv->tvnorm = norm; - tvnorm = &bttv_tvnorms[norm]; - - btwrite(tvnorm->adelay, BT848_ADELAY); - btwrite(tvnorm->bdelay, BT848_BDELAY); - btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), - BT848_IFORM); - btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE); - btwrite(1, BT848_VBI_PACK_DEL); - bt848A_set_timing(btv); - - switch (btv->c.type) { - case BTTV_BOARD_VOODOOTV_FM: - bttv_tda9880_setnorm(btv,norm); - break; - } - return 0; -} - -static void -set_input(struct bttv *btv, unsigned int input) -{ - unsigned long flags; - - btv->input = input; - if (irq_iswitch) { - spin_lock_irqsave(&btv->s_lock,flags); - if (btv->curr.frame_irq) { - /* active capture -> delayed input switch */ - btv->new_input = input; - } else { - video_mux(btv,input); - } - spin_unlock_irqrestore(&btv->s_lock,flags); - } else { - video_mux(btv,input); - } - audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ? - AUDIO_TUNER : AUDIO_EXTERN)); - set_tvnorm(btv,btv->tvnorm); - i2c_vidiocschan(btv); -} - -static void init_irqreg(struct bttv *btv) -{ - /* clear status */ - btwrite(0xfffffUL, BT848_INT_STAT); - - if (bttv_tvcards[btv->c.type].no_video) { - /* i2c only */ - btwrite(BT848_INT_I2CDONE, - BT848_INT_MASK); - } else { - /* full video */ - btwrite((btv->triton1) | - (btv->gpioirq ? BT848_INT_GPINT : 0) | - BT848_INT_SCERR | - (fdsr ? BT848_INT_FDSR : 0) | - BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES| - BT848_INT_FMTCHG|BT848_INT_HLOCK| - BT848_INT_I2CDONE, - BT848_INT_MASK); - } -} - -static void init_bt848(struct bttv *btv) -{ - int val; - - if (bttv_tvcards[btv->c.type].no_video) { - /* very basic init only */ - init_irqreg(btv); - return; - } - - btwrite(0x00, BT848_CAP_CTL); - btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); - btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM); - - /* set planar and packed mode trigger points and */ - /* set rising edge of inverted GPINTR pin as irq trigger */ - btwrite(BT848_GPIO_DMA_CTL_PKTP_32| - BT848_GPIO_DMA_CTL_PLTP1_16| - BT848_GPIO_DMA_CTL_PLTP23_16| - BT848_GPIO_DMA_CTL_GPINTC| - BT848_GPIO_DMA_CTL_GPINTI, - BT848_GPIO_DMA_CTL); - - val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0; - btwrite(val, BT848_E_SCLOOP); - btwrite(val, BT848_O_SCLOOP); - - btwrite(0x20, BT848_E_VSCALE_HI); - btwrite(0x20, BT848_O_VSCALE_HI); - btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), - BT848_ADC); - - btwrite(whitecrush_upper, BT848_WC_UP); - btwrite(whitecrush_lower, BT848_WC_DOWN); - - if (btv->opt_lumafilter) { - btwrite(0, BT848_E_CONTROL); - btwrite(0, BT848_O_CONTROL); - } else { - btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL); - btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL); - } - - bt848_bright(btv, btv->bright); - bt848_hue(btv, btv->hue); - bt848_contrast(btv, btv->contrast); - bt848_sat(btv, btv->saturation); - - /* interrupt */ - init_irqreg(btv); -} - -static void bttv_reinit_bt848(struct bttv *btv) -{ - unsigned long flags; - - if (bttv_verbose) - printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr); - spin_lock_irqsave(&btv->s_lock,flags); - btv->errors=0; - bttv_set_dma(btv,0); - spin_unlock_irqrestore(&btv->s_lock,flags); - - init_bt848(btv); - btv->pll.pll_current = -1; - set_input(btv,btv->input); -} - -static int get_control(struct bttv *btv, struct v4l2_control *c) -{ - struct video_audio va; - int i; - - for (i = 0; i < BTTV_CTLS; i++) - if (bttv_ctls[i].id == c->id) - break; - if (i == BTTV_CTLS) - return -EINVAL; - if (i >= 4 && i <= 8) { - memset(&va,0,sizeof(va)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); - } - switch (c->id) { - case V4L2_CID_BRIGHTNESS: - c->value = btv->bright; - break; - case V4L2_CID_HUE: - c->value = btv->hue; - break; - case V4L2_CID_CONTRAST: - c->value = btv->contrast; - break; - case V4L2_CID_SATURATION: - c->value = btv->saturation; - break; - - case V4L2_CID_AUDIO_MUTE: - c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0; - break; - case V4L2_CID_AUDIO_VOLUME: - c->value = va.volume; - break; - case V4L2_CID_AUDIO_BALANCE: - c->value = va.balance; - break; - case V4L2_CID_AUDIO_BASS: - c->value = va.bass; - break; - case V4L2_CID_AUDIO_TREBLE: - c->value = va.treble; - break; - - case V4L2_CID_PRIVATE_CHROMA_AGC: - c->value = btv->opt_chroma_agc; - break; - case V4L2_CID_PRIVATE_COMBFILTER: - c->value = btv->opt_combfilter; - break; - case V4L2_CID_PRIVATE_LUMAFILTER: - c->value = btv->opt_lumafilter; - break; - case V4L2_CID_PRIVATE_AUTOMUTE: - c->value = btv->opt_automute; - break; - case V4L2_CID_PRIVATE_AGC_CRUSH: - c->value = btv->opt_adc_crush; - break; - case V4L2_CID_PRIVATE_VCR_HACK: - c->value = btv->opt_vcr_hack; - break; - case V4L2_CID_PRIVATE_WHITECRUSH_UPPER: - c->value = btv->opt_whitecrush_upper; - break; - case V4L2_CID_PRIVATE_WHITECRUSH_LOWER: - c->value = btv->opt_whitecrush_lower; - break; - case V4L2_CID_PRIVATE_UV_RATIO: - c->value = btv->opt_uv_ratio; - break; - case V4L2_CID_PRIVATE_FULL_LUMA_RANGE: - c->value = btv->opt_full_luma_range; - break; - case V4L2_CID_PRIVATE_CORING: - c->value = btv->opt_coring; - break; - default: - return -EINVAL; - } - return 0; -} - -static int set_control(struct bttv *btv, struct v4l2_control *c) -{ - struct video_audio va; - int i,val; - - for (i = 0; i < BTTV_CTLS; i++) - if (bttv_ctls[i].id == c->id) - break; - if (i == BTTV_CTLS) - return -EINVAL; - if (i >= 4 && i <= 8) { - memset(&va,0,sizeof(va)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); - } - switch (c->id) { - case V4L2_CID_BRIGHTNESS: - bt848_bright(btv,c->value); - break; - case V4L2_CID_HUE: - bt848_hue(btv,c->value); - break; - case V4L2_CID_CONTRAST: - bt848_contrast(btv,c->value); - break; - case V4L2_CID_SATURATION: - bt848_sat(btv,c->value); - break; - case V4L2_CID_AUDIO_MUTE: - if (c->value) { - va.flags |= VIDEO_AUDIO_MUTE; - audio_mux(btv, AUDIO_MUTE); - } else { - va.flags &= ~VIDEO_AUDIO_MUTE; - audio_mux(btv, AUDIO_UNMUTE); - } - break; - - case V4L2_CID_AUDIO_VOLUME: - va.volume = c->value; - break; - case V4L2_CID_AUDIO_BALANCE: - va.balance = c->value; - break; - case V4L2_CID_AUDIO_BASS: - va.bass = c->value; - break; - case V4L2_CID_AUDIO_TREBLE: - va.treble = c->value; - break; - - case V4L2_CID_PRIVATE_CHROMA_AGC: - btv->opt_chroma_agc = c->value; - val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0; - btwrite(val, BT848_E_SCLOOP); - btwrite(val, BT848_O_SCLOOP); - break; - case V4L2_CID_PRIVATE_COMBFILTER: - btv->opt_combfilter = c->value; - break; - case V4L2_CID_PRIVATE_LUMAFILTER: - btv->opt_lumafilter = c->value; - if (btv->opt_lumafilter) { - btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL); - btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL); - } else { - btor(BT848_CONTROL_LDEC, BT848_E_CONTROL); - btor(BT848_CONTROL_LDEC, BT848_O_CONTROL); - } - break; - case V4L2_CID_PRIVATE_AUTOMUTE: - btv->opt_automute = c->value; - break; - case V4L2_CID_PRIVATE_AGC_CRUSH: - btv->opt_adc_crush = c->value; - btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), - BT848_ADC); - break; - case V4L2_CID_PRIVATE_VCR_HACK: - btv->opt_vcr_hack = c->value; - break; - case V4L2_CID_PRIVATE_WHITECRUSH_UPPER: - btv->opt_whitecrush_upper = c->value; - btwrite(c->value, BT848_WC_UP); - break; - case V4L2_CID_PRIVATE_WHITECRUSH_LOWER: - btv->opt_whitecrush_lower = c->value; - btwrite(c->value, BT848_WC_DOWN); - break; - case V4L2_CID_PRIVATE_UV_RATIO: - btv->opt_uv_ratio = c->value; - bt848_sat(btv, btv->saturation); - break; - case V4L2_CID_PRIVATE_FULL_LUMA_RANGE: - btv->opt_full_luma_range = c->value; - btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM); - break; - case V4L2_CID_PRIVATE_CORING: - btv->opt_coring = c->value; - btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM); - break; - default: - return -EINVAL; - } - if (i >= 4 && i <= 8) { - bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,1); - } - return 0; -} - -/* ----------------------------------------------------------------------- */ - -void bttv_gpio_tracking(struct bttv *btv, char *comment) -{ - unsigned int outbits, data; - outbits = btread(BT848_GPIO_OUT_EN); - data = btread(BT848_GPIO_DATA); - printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n", - btv->c.nr,outbits,data & outbits, data & ~outbits, comment); -} - -static void bttv_field_count(struct bttv *btv) -{ - int need_count = 0; - - if (btv->users) - need_count++; - - if (need_count) { - /* start field counter */ - btor(BT848_INT_VSYNC,BT848_INT_MASK); - } else { - /* stop field counter */ - btand(~BT848_INT_VSYNC,BT848_INT_MASK); - btv->field_count = 0; - } -} - -static const struct bttv_format* -format_by_palette(int palette) -{ - unsigned int i; - - for (i = 0; i < BTTV_FORMATS; i++) { - if (-1 == bttv_formats[i].palette) - continue; - if (bttv_formats[i].palette == palette) - return bttv_formats+i; - } - return NULL; -} - -static const struct bttv_format* -format_by_fourcc(int fourcc) -{ - unsigned int i; - - for (i = 0; i < BTTV_FORMATS; i++) { - if (-1 == bttv_formats[i].fourcc) - continue; - if (bttv_formats[i].fourcc == fourcc) - return bttv_formats+i; - } - return NULL; -} - -/* ----------------------------------------------------------------------- */ -/* misc helpers */ - -static int -bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, - struct bttv_buffer *new) -{ - struct bttv_buffer *old; - unsigned long flags; - int retval = 0; - - dprintk("switch_overlay: enter [new=%p]\n",new); - if (new) - new->vb.state = STATE_DONE; - spin_lock_irqsave(&btv->s_lock,flags); - old = btv->screen; - btv->screen = new; - btv->loop_irq |= 1; - bttv_set_dma(btv, 0x03); - spin_unlock_irqrestore(&btv->s_lock,flags); - if (NULL == new) - free_btres(btv,fh,RESOURCE_OVERLAY); - if (NULL != old) { - dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state); - bttv_dma_free(&fh->cap,btv, old); - kfree(old); - } - dprintk("switch_overlay: done\n"); - return retval; -} - -/* ----------------------------------------------------------------------- */ -/* video4linux (1) interface */ - -static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv, - struct bttv_buffer *buf, - const struct bttv_format *fmt, - unsigned int width, unsigned int height, - enum v4l2_field field) -{ - int redo_dma_risc = 0; - int rc; - - /* check settings */ - if (NULL == fmt) - return -EINVAL; - if (fmt->btformat == BT848_COLOR_FMT_RAW) { - width = RAW_BPL; - height = RAW_LINES*2; - if (width*height > buf->vb.bsize) - return -EINVAL; - buf->vb.size = buf->vb.bsize; - } else { - if (width < 48 || - height < 32 || - width > bttv_tvnorms[btv->tvnorm].swidth || - height > bttv_tvnorms[btv->tvnorm].sheight) - return -EINVAL; - buf->vb.size = (width * height * fmt->depth) >> 3; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - } - - /* alloc + fill struct bttv_buffer (if changed) */ - if (buf->vb.width != width || buf->vb.height != height || - buf->vb.field != field || - buf->tvnorm != btv->tvnorm || buf->fmt != fmt) { - buf->vb.width = width; - buf->vb.height = height; - buf->vb.field = field; - buf->tvnorm = btv->tvnorm; - buf->fmt = fmt; - redo_dma_risc = 1; - } - - /* alloc risc memory */ - if (STATE_NEEDS_INIT == buf->vb.state) { - redo_dma_risc = 1; - if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf))) - goto fail; - } - - if (redo_dma_risc) - if (0 != (rc = bttv_buffer_risc(btv,buf))) - goto fail; - - buf->vb.state = STATE_PREPARED; - return 0; - - fail: - bttv_dma_free(q,btv,buf); - return rc; -} - -static int -buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) -{ - struct bttv_fh *fh = q->priv_data; - - *size = fh->fmt->depth*fh->width*fh->height >> 3; - if (0 == *count) - *count = gbuffers; - while (*size * *count > gbuffers * gbufsize) - (*count)--; - return 0; -} - -static int -buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); - struct bttv_fh *fh = q->priv_data; - - return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt, - fh->width, fh->height, field); -} - -static void -buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); - struct bttv_fh *fh = q->priv_data; - struct bttv *btv = fh->btv; - - buf->vb.state = STATE_QUEUED; - list_add_tail(&buf->vb.queue,&btv->capture); - if (!btv->curr.frame_irq) { - btv->loop_irq |= 1; - bttv_set_dma(btv, 0x03); - } -} - -static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); - struct bttv_fh *fh = q->priv_data; - - bttv_dma_free(&fh->cap,fh->btv,buf); -} - -static struct videobuf_queue_ops bttv_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) -{ - switch (cmd) { - case BTTV_VERSION: - return BTTV_VERSION_CODE; - - /* *** v4l1 *** ************************************************ */ - case VIDIOCGFREQ: - { - unsigned long *freq = arg; - *freq = btv->freq; - return 0; - } - case VIDIOCSFREQ: - { - unsigned long *freq = arg; - mutex_lock(&btv->lock); - btv->freq=*freq; - bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq); - if (btv->has_matchbox && btv->radio_user) - tea5757_set_freq(btv,*freq); - mutex_unlock(&btv->lock); - return 0; - } - - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; - - if (UNSET == bttv_tvcards[btv->c.type].tuner) - return -EINVAL; - if (v->tuner) /* Only tuner 0 */ - return -EINVAL; - strcpy(v->name, "Television"); - v->rangelow = 0; - v->rangehigh = 0x7FFFFFFF; - v->flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; - v->mode = btv->tvnorm; - v->signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0; - bttv_call_i2c_clients(btv,cmd,v); - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner *v = arg; - - if (v->tuner) /* Only tuner 0 */ - return -EINVAL; - if (v->mode >= BTTV_TVNORMS) - return -EINVAL; - - mutex_lock(&btv->lock); - set_tvnorm(btv,v->mode); - bttv_call_i2c_clients(btv,cmd,v); - mutex_unlock(&btv->lock); - return 0; - } - - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - unsigned int channel = v->channel; - - if (channel >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - v->tuners=0; - v->flags = VIDEO_VC_AUDIO; - v->type = VIDEO_TYPE_CAMERA; - v->norm = btv->tvnorm; - if (channel == bttv_tvcards[btv->c.type].tuner) { - strcpy(v->name,"Television"); - v->flags|=VIDEO_VC_TUNER; - v->type=VIDEO_TYPE_TV; - v->tuners=1; - } else if (channel == btv->svhs) { - strcpy(v->name,"S-Video"); - } else { - sprintf(v->name,"Composite%d",channel); - } - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - unsigned int channel = v->channel; - - if (channel >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - if (v->norm >= BTTV_TVNORMS) - return -EINVAL; - - mutex_lock(&btv->lock); - if (channel == btv->input && - v->norm == btv->tvnorm) { - /* nothing to do */ - mutex_unlock(&btv->lock); - return 0; - } - - btv->tvnorm = v->norm; - set_input(btv,v->channel); - mutex_unlock(&btv->lock); - return 0; - } - - case VIDIOCGAUDIO: - { - struct video_audio *v = arg; - - memset(v,0,sizeof(*v)); - strcpy(v->name,"Television"); - v->flags |= VIDEO_AUDIO_MUTABLE; - v->mode = VIDEO_SOUND_MONO; - - mutex_lock(&btv->lock); - bttv_call_i2c_clients(btv,cmd,v); - - /* card specific hooks */ - if (btv->audio_hook) - btv->audio_hook(btv,v,0); - - mutex_unlock(&btv->lock); - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio *v = arg; - unsigned int audio = v->audio; - - if (audio >= bttv_tvcards[btv->c.type].audio_inputs) - return -EINVAL; - - mutex_lock(&btv->lock); - audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE); - bttv_call_i2c_clients(btv,cmd,v); - - /* card specific hooks */ - if (btv->audio_hook) - btv->audio_hook(btv,v,1); - - mutex_unlock(&btv->lock); - return 0; - } - - /* *** v4l2 *** ************************************************ */ - case VIDIOC_ENUMSTD: - { - struct v4l2_standard *e = arg; - unsigned int index = e->index; - - if (index >= BTTV_TVNORMS) - return -EINVAL; - v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id, - bttv_tvnorms[e->index].name); - e->index = index; - return 0; - } - case VIDIOC_G_STD: - { - v4l2_std_id *id = arg; - *id = bttv_tvnorms[btv->tvnorm].v4l2_id; - return 0; - } - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; - unsigned int i; - - for (i = 0; i < BTTV_TVNORMS; i++) - if (*id & bttv_tvnorms[i].v4l2_id) - break; - if (i == BTTV_TVNORMS) - return -EINVAL; - - mutex_lock(&btv->lock); - set_tvnorm(btv,i); - i2c_vidiocschan(btv); - mutex_unlock(&btv->lock); - return 0; - } - case VIDIOC_QUERYSTD: - { - v4l2_std_id *id = arg; - - if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML) - *id = V4L2_STD_625_50; - else - *id = V4L2_STD_525_60; - return 0; - } - - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; - unsigned int n; - - n = i->index; - if (n >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - memset(i,0,sizeof(*i)); - i->index = n; - i->type = V4L2_INPUT_TYPE_CAMERA; - i->audioset = 0; - if (i->index == bttv_tvcards[btv->c.type].tuner) { - sprintf(i->name, "Television"); - i->type = V4L2_INPUT_TYPE_TUNER; - i->tuner = 0; - } else if (i->index == btv->svhs) { - sprintf(i->name, "S-Video"); - } else { - sprintf(i->name,"Composite%d",i->index); - } - if (i->index == btv->input) { - __u32 dstatus = btread(BT848_DSTATUS); - if (0 == (dstatus & BT848_DSTATUS_PRES)) - i->status |= V4L2_IN_ST_NO_SIGNAL; - if (0 == (dstatus & BT848_DSTATUS_HLOC)) - i->status |= V4L2_IN_ST_NO_H_LOCK; - } - for (n = 0; n < BTTV_TVNORMS; n++) - i->std |= bttv_tvnorms[n].v4l2_id; - return 0; - } - case VIDIOC_G_INPUT: - { - int *i = arg; - *i = btv->input; - return 0; - } - case VIDIOC_S_INPUT: - { - unsigned int *i = arg; - - if (*i > bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - mutex_lock(&btv->lock); - set_input(btv,*i); - mutex_unlock(&btv->lock); - return 0; - } - - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *t = arg; - - if (UNSET == bttv_tvcards[btv->c.type].tuner) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - mutex_lock(&btv->lock); - memset(t,0,sizeof(*t)); - strcpy(t->name, "Television"); - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM; - t->rxsubchans = V4L2_TUNER_SUB_MONO; - if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) - t->signal = 0xffff; - { - struct video_tuner tuner; - - memset(&tuner, 0, sizeof (tuner)); - tuner.rangehigh = 0xffffffffUL; - bttv_call_i2c_clients(btv, VIDIOCGTUNER, &tuner); - t->rangelow = tuner.rangelow; - t->rangehigh = tuner.rangehigh; - } - { - /* Hmmm ... */ - struct video_audio va; - memset(&va, 0, sizeof(struct video_audio)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); - if(va.mode & VIDEO_SOUND_STEREO) { - t->audmode = V4L2_TUNER_MODE_STEREO; - t->rxsubchans |= V4L2_TUNER_SUB_STEREO; - } - if(va.mode & VIDEO_SOUND_LANG1) { - t->audmode = V4L2_TUNER_MODE_LANG1; - t->rxsubchans = V4L2_TUNER_SUB_LANG1 - | V4L2_TUNER_SUB_LANG2; - } - } - /* FIXME: fill capability+audmode */ - mutex_unlock(&btv->lock); - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *t = arg; - - if (UNSET == bttv_tvcards[btv->c.type].tuner) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - mutex_lock(&btv->lock); - { - struct video_audio va; - memset(&va, 0, sizeof(struct video_audio)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (t->audmode == V4L2_TUNER_MODE_MONO) - va.mode = VIDEO_SOUND_MONO; - else if (t->audmode == V4L2_TUNER_MODE_STEREO) - va.mode = VIDEO_SOUND_STEREO; - else if (t->audmode == V4L2_TUNER_MODE_LANG1) - va.mode = VIDEO_SOUND_LANG1; - else if (t->audmode == V4L2_TUNER_MODE_LANG2) - va.mode = VIDEO_SOUND_LANG2; - bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,1); - } - mutex_unlock(&btv->lock); - return 0; - } - - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - memset(f,0,sizeof(*f)); - f->type = V4L2_TUNER_ANALOG_TV; - f->frequency = btv->freq; - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - if (unlikely(f->tuner != 0)) - return -EINVAL; - if (unlikely (f->type != V4L2_TUNER_ANALOG_TV)) - return -EINVAL; - mutex_lock(&btv->lock); - btv->freq = f->frequency; - bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq); - if (btv->has_matchbox && btv->radio_user) - tea5757_set_freq(btv,btv->freq); - mutex_unlock(&btv->lock); - return 0; - } - case VIDIOC_LOG_STATUS: - { - bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL); - return 0; - } - - default: - return -ENOIOCTLCMD; - - } - return 0; -} - -static int verify_window(const struct bttv_tvnorm *tvn, - struct v4l2_window *win, int fixup) -{ - enum v4l2_field field; - int maxw, maxh; - - if (win->w.width < 48 || win->w.height < 32) - return -EINVAL; - if (win->clipcount > 2048) - return -EINVAL; - - field = win->field; - maxw = tvn->swidth; - maxh = tvn->sheight; - - if (V4L2_FIELD_ANY == field) { - field = (win->w.height > maxh/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_TOP; - } - switch (field) { - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - maxh = maxh / 2; - break; - case V4L2_FIELD_INTERLACED: - break; - default: - return -EINVAL; - } - - if (!fixup && (win->w.width > maxw || win->w.height > maxh)) - return -EINVAL; - - if (win->w.width > maxw) - win->w.width = maxw; - if (win->w.height > maxh) - win->w.height = maxh; - win->field = field; - return 0; -} - -static int setup_window(struct bttv_fh *fh, struct bttv *btv, - struct v4l2_window *win, int fixup) -{ - struct v4l2_clip *clips = NULL; - int n,size,retval = 0; - - if (NULL == fh->ovfmt) - return -EINVAL; - if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED)) - return -EINVAL; - retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup); - if (0 != retval) - return retval; - - /* copy clips -- luckily v4l1 + v4l2 are binary - compatible here ...*/ - n = win->clipcount; - size = sizeof(*clips)*(n+4); - clips = kmalloc(size,GFP_KERNEL); - if (NULL == clips) - return -ENOMEM; - if (n > 0) { - if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) { - kfree(clips); - return -EFAULT; - } - } - /* clip against screen */ - if (NULL != btv->fbuf.base) - n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height, - &win->w, clips, n); - btcx_sort_clips(clips,n); - - /* 4-byte alignments */ - switch (fh->ovfmt->depth) { - case 8: - case 24: - btcx_align(&win->w, clips, n, 3); - break; - case 16: - btcx_align(&win->w, clips, n, 1); - break; - case 32: - /* no alignment fixups needed */ - break; - default: - BUG(); - } - - mutex_lock(&fh->cap.lock); - kfree(fh->ov.clips); - fh->ov.clips = clips; - fh->ov.nclips = n; - - fh->ov.w = win->w; - fh->ov.field = win->field; - fh->ov.setup_ok = 1; - btv->init.ov.w.width = win->w.width; - btv->init.ov.w.height = win->w.height; - btv->init.ov.field = win->field; - - /* update overlay if needed */ - retval = 0; - if (check_btres(fh, RESOURCE_OVERLAY)) { - struct bttv_buffer *new; - - new = videobuf_alloc(sizeof(*new)); - bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); - retval = bttv_switch_overlay(btv,fh,new); - } - mutex_unlock(&fh->cap.lock); - return retval; -} - -/* ----------------------------------------------------------------------- */ - -static struct videobuf_queue* bttv_queue(struct bttv_fh *fh) -{ - struct videobuf_queue* q = NULL; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - q = &fh->cap; - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - q = &fh->vbi; - break; - default: - BUG(); - } - return q; -} - -static int bttv_resource(struct bttv_fh *fh) -{ - int res = 0; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - res = RESOURCE_VIDEO; - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - res = RESOURCE_VBI; - break; - default: - BUG(); - } - return res; -} - -static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type) -{ - struct videobuf_queue *q = bttv_queue(fh); - int res = bttv_resource(fh); - - if (check_btres(fh,res)) - return -EBUSY; - if (videobuf_queue_is_busy(q)) - return -EBUSY; - fh->type = type; - return 0; -} - -static void -pix_format_set_size (struct v4l2_pix_format * f, - const struct bttv_format * fmt, - unsigned int width, - unsigned int height) -{ - f->width = width; - f->height = height; - - if (fmt->flags & FORMAT_FLAGS_PLANAR) { - f->bytesperline = width; /* Y plane */ - f->sizeimage = (width * height * fmt->depth) >> 3; - } else { - f->bytesperline = (width * fmt->depth) >> 3; - f->sizeimage = height * f->bytesperline; - } -} - -static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f) -{ - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - memset(&f->fmt.pix,0,sizeof(struct v4l2_pix_format)); - pix_format_set_size (&f->fmt.pix, fh->fmt, - fh->width, fh->height); - f->fmt.pix.field = fh->cap.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; - return 0; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - memset(&f->fmt.win,0,sizeof(struct v4l2_window)); - f->fmt.win.w = fh->ov.w; - f->fmt.win.field = fh->ov.field; - return 0; - case V4L2_BUF_TYPE_VBI_CAPTURE: - bttv_vbi_get_fmt(fh,f); - return 0; - default: - return -EINVAL; - } -} - -static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv, - struct v4l2_format *f) -{ - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - const struct bttv_format *fmt; - enum v4l2_field field; - unsigned int maxw,maxh; - - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (NULL == fmt) - return -EINVAL; - - /* fixup format */ - maxw = bttv_tvnorms[btv->tvnorm].swidth; - maxh = bttv_tvnorms[btv->tvnorm].sheight; - field = f->fmt.pix.field; - if (V4L2_FIELD_ANY == field) - field = (f->fmt.pix.height > maxh/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_BOTTOM; - if (V4L2_FIELD_SEQ_BT == field) - field = V4L2_FIELD_SEQ_TB; - switch (field) { - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - case V4L2_FIELD_ALTERNATE: - maxh = maxh/2; - break; - case V4L2_FIELD_INTERLACED: - break; - case V4L2_FIELD_SEQ_TB: - if (fmt->flags & FORMAT_FLAGS_PLANAR) - return -EINVAL; - break; - default: - return -EINVAL; - } - - /* update data for the application */ - f->fmt.pix.field = field; - if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; - if (f->fmt.pix.height < 32) - f->fmt.pix.height = 32; - if (f->fmt.pix.width > maxw) - f->fmt.pix.width = maxw; - if (f->fmt.pix.height > maxh) - f->fmt.pix.height = maxh; - pix_format_set_size (&f->fmt.pix, fmt, - f->fmt.pix.width & ~3, - f->fmt.pix.height); - - return 0; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - return verify_window(&bttv_tvnorms[btv->tvnorm], - &f->fmt.win, 1); - case V4L2_BUF_TYPE_VBI_CAPTURE: - bttv_vbi_try_fmt(fh,f); - return 0; - default: - return -EINVAL; - } -} - -static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, - struct v4l2_format *f) -{ - int retval; - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - const struct bttv_format *fmt; - - retval = bttv_switch_type(fh,f->type); - if (0 != retval) - return retval; - retval = bttv_try_fmt(fh,btv,f); - if (0 != retval) - return retval; - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - - /* update our state informations */ - mutex_lock(&fh->cap.lock); - fh->fmt = fmt; - fh->cap.field = f->fmt.pix.field; - fh->cap.last = V4L2_FIELD_NONE; - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - btv->init.fmt = fmt; - btv->init.width = f->fmt.pix.width; - btv->init.height = f->fmt.pix.height; - mutex_unlock(&fh->cap.lock); - - return 0; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (no_overlay > 0) { - printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); - return -EINVAL; - } - return setup_window(fh, btv, &f->fmt.win, 1); - case V4L2_BUF_TYPE_VBI_CAPTURE: - retval = bttv_switch_type(fh,f->type); - if (0 != retval) - return retval; - if (locked_btres(fh->btv, RESOURCE_VBI)) - return -EBUSY; - bttv_vbi_try_fmt(fh,f); - bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]); - bttv_vbi_get_fmt(fh,f); - return 0; - default: - return -EINVAL; - } -} - -static int bttv_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct bttv_fh *fh = file->private_data; - struct bttv *btv = fh->btv; - unsigned long flags; - int retval = 0; - - if (bttv_debug > 1) - v4l_print_ioctl(btv->c.name, cmd); - - if (btv->errors) - bttv_reinit_bt848(btv); - - switch (cmd) { - case VIDIOCSFREQ: - case VIDIOCSTUNER: - case VIDIOCSCHAN: - case VIDIOC_S_CTRL: - case VIDIOC_S_STD: - case VIDIOC_S_INPUT: - case VIDIOC_S_TUNER: - case VIDIOC_S_FREQUENCY: - retval = v4l2_prio_check(&btv->prio,&fh->prio); - if (0 != retval) - return retval; - }; - - switch (cmd) { - - /* *** v4l1 *** ************************************************ */ - case VIDIOCGCAP: - { - struct video_capability *cap = arg; - - memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->video_dev->name); - if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { - /* vbi */ - cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT; - } else { - /* others */ - cap->type = VID_TYPE_CAPTURE| - VID_TYPE_TUNER| - VID_TYPE_CLIPPING| - VID_TYPE_SCALES; - if (no_overlay <= 0) - cap->type |= VID_TYPE_OVERLAY; - - cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth; - cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight; - cap->minwidth = 48; - cap->minheight = 32; - } - cap->channels = bttv_tvcards[btv->c.type].video_inputs; - cap->audios = bttv_tvcards[btv->c.type].audio_inputs; - return 0; - } - - case VIDIOCGPICT: - { - struct video_picture *pic = arg; - - memset(pic,0,sizeof(*pic)); - pic->brightness = btv->bright; - pic->contrast = btv->contrast; - pic->hue = btv->hue; - pic->colour = btv->saturation; - if (fh->fmt) { - pic->depth = fh->fmt->depth; - pic->palette = fh->fmt->palette; - } - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *pic = arg; - const struct bttv_format *fmt; - - fmt = format_by_palette(pic->palette); - if (NULL == fmt) - return -EINVAL; - mutex_lock(&fh->cap.lock); - if (fmt->depth != pic->depth) { - retval = -EINVAL; - goto fh_unlock_and_return; - } - if (fmt->flags & FORMAT_FLAGS_RAW) { - /* VIDIOCMCAPTURE uses gbufsize, not RAW_BPL * - RAW_LINES * 2. F1 is stored at offset 0, F2 - at buffer size / 2. */ - fh->width = RAW_BPL; - fh->height = gbufsize / RAW_BPL; - btv->init.width = RAW_BPL; - btv->init.height = gbufsize / RAW_BPL; - } - fh->ovfmt = fmt; - fh->fmt = fmt; - btv->init.ovfmt = fmt; - btv->init.fmt = fmt; - if (bigendian) { - /* dirty hack time: swap bytes for overlay if the - display adaptor is big endian (insmod option) */ - if (fmt->palette == VIDEO_PALETTE_RGB555 || - fmt->palette == VIDEO_PALETTE_RGB565 || - fmt->palette == VIDEO_PALETTE_RGB32) { - fh->ovfmt = fmt+1; - } - } - bt848_bright(btv,pic->brightness); - bt848_contrast(btv,pic->contrast); - bt848_hue(btv,pic->hue); - bt848_sat(btv,pic->colour); - mutex_unlock(&fh->cap.lock); - return 0; - } - - case VIDIOCGWIN: - { - struct video_window *win = arg; - - memset(win,0,sizeof(*win)); - win->x = fh->ov.w.left; - win->y = fh->ov.w.top; - win->width = fh->ov.w.width; - win->height = fh->ov.w.height; - return 0; - } - case VIDIOCSWIN: - { - struct video_window *win = arg; - struct v4l2_window w2; - - if (no_overlay > 0) { - printk ("VIDIOCSWIN: no_overlay\n"); - return -EINVAL; - } - - w2.field = V4L2_FIELD_ANY; - w2.w.left = win->x; - w2.w.top = win->y; - w2.w.width = win->width; - w2.w.height = win->height; - w2.clipcount = win->clipcount; - w2.clips = (struct v4l2_clip __user *)win->clips; - retval = setup_window(fh, btv, &w2, 0); - if (0 == retval) { - /* on v4l1 this ioctl affects the read() size too */ - fh->width = fh->ov.w.width; - fh->height = fh->ov.w.height; - btv->init.width = fh->ov.w.width; - btv->init.height = fh->ov.w.height; - } - return retval; - } - - case VIDIOCGFBUF: - { - struct video_buffer *fbuf = arg; - - fbuf->base = btv->fbuf.base; - fbuf->width = btv->fbuf.fmt.width; - fbuf->height = btv->fbuf.fmt.height; - fbuf->bytesperline = btv->fbuf.fmt.bytesperline; - if (fh->ovfmt) - fbuf->depth = fh->ovfmt->depth; - return 0; - } - case VIDIOCSFBUF: - { - struct video_buffer *fbuf = arg; - const struct bttv_format *fmt; - unsigned long end; - - if(!capable(CAP_SYS_ADMIN) && - !capable(CAP_SYS_RAWIO)) - return -EPERM; - end = (unsigned long)fbuf->base + - fbuf->height * fbuf->bytesperline; - mutex_lock(&fh->cap.lock); - retval = -EINVAL; - - switch (fbuf->depth) { - case 8: - fmt = format_by_palette(VIDEO_PALETTE_HI240); - break; - case 16: - fmt = format_by_palette(VIDEO_PALETTE_RGB565); - break; - case 24: - fmt = format_by_palette(VIDEO_PALETTE_RGB24); - break; - case 32: - fmt = format_by_palette(VIDEO_PALETTE_RGB32); - break; - case 15: - fbuf->depth = 16; - fmt = format_by_palette(VIDEO_PALETTE_RGB555); - break; - default: - fmt = NULL; - break; - } - if (NULL == fmt) - goto fh_unlock_and_return; - - fh->ovfmt = fmt; - fh->fmt = fmt; - btv->init.ovfmt = fmt; - btv->init.fmt = fmt; - btv->fbuf.base = fbuf->base; - btv->fbuf.fmt.width = fbuf->width; - btv->fbuf.fmt.height = fbuf->height; - if (fbuf->bytesperline) - btv->fbuf.fmt.bytesperline = fbuf->bytesperline; - else - btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fbuf->depth/8; - mutex_unlock(&fh->cap.lock); - return 0; - } - - case VIDIOCCAPTURE: - case VIDIOC_OVERLAY: - { - struct bttv_buffer *new; - int *on = arg; - - if (*on) { - /* verify args */ - if (NULL == btv->fbuf.base) - return -EINVAL; - if (!fh->ov.setup_ok) { - dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr); - return -EINVAL; - } - } - - if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY)) - return -EBUSY; - - mutex_lock(&fh->cap.lock); - if (*on) { - fh->ov.tvnorm = btv->tvnorm; - new = videobuf_alloc(sizeof(*new)); - bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); - } else { - new = NULL; - } - - /* switch over */ - retval = bttv_switch_overlay(btv,fh,new); - mutex_unlock(&fh->cap.lock); - return retval; - } - - case VIDIOCGMBUF: - { - struct video_mbuf *mbuf = arg; - unsigned int i; - - mutex_lock(&fh->cap.lock); - retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize, - V4L2_MEMORY_MMAP); - if (retval < 0) - goto fh_unlock_and_return; - memset(mbuf,0,sizeof(*mbuf)); - mbuf->frames = gbuffers; - mbuf->size = gbuffers * gbufsize; - for (i = 0; i < gbuffers; i++) - mbuf->offsets[i] = i * gbufsize; - mutex_unlock(&fh->cap.lock); - return 0; - } - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - struct bttv_buffer *buf; - enum v4l2_field field; - - if (vm->frame >= VIDEO_MAX_FRAME) - return -EINVAL; - - mutex_lock(&fh->cap.lock); - retval = -EINVAL; - buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame]; - if (NULL == buf) - goto fh_unlock_and_return; - if (0 == buf->vb.baddr) - goto fh_unlock_and_return; - if (buf->vb.state == STATE_QUEUED || - buf->vb.state == STATE_ACTIVE) - goto fh_unlock_and_return; - - field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_BOTTOM; - retval = bttv_prepare_buffer(&fh->cap,btv,buf, - format_by_palette(vm->format), - vm->width,vm->height,field); - if (0 != retval) - goto fh_unlock_and_return; - spin_lock_irqsave(&btv->s_lock,flags); - buffer_queue(&fh->cap,&buf->vb); - spin_unlock_irqrestore(&btv->s_lock,flags); - mutex_unlock(&fh->cap.lock); - return 0; - } - case VIDIOCSYNC: - { - int *frame = arg; - struct bttv_buffer *buf; - - if (*frame >= VIDEO_MAX_FRAME) - return -EINVAL; - - mutex_lock(&fh->cap.lock); - retval = -EINVAL; - buf = (struct bttv_buffer *)fh->cap.bufs[*frame]; - if (NULL == buf) - goto fh_unlock_and_return; - retval = videobuf_waiton(&buf->vb,0,1); - if (0 != retval) - goto fh_unlock_and_return; - switch (buf->vb.state) { - case STATE_ERROR: - retval = -EIO; - /* fall through */ - case STATE_DONE: - videobuf_dma_sync(&fh->cap,&buf->vb.dma); - bttv_dma_free(&fh->cap,btv,buf); - break; - default: - retval = -EINVAL; - break; - } - mutex_unlock(&fh->cap.lock); - return retval; - } - - case VIDIOCGVBIFMT: - { - struct vbi_format *fmt = (void *) arg; - struct v4l2_format fmt2; - - if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) { - retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); - if (0 != retval) - return retval; - } - bttv_vbi_get_fmt(fh, &fmt2); - - memset(fmt,0,sizeof(*fmt)); - fmt->sampling_rate = fmt2.fmt.vbi.sampling_rate; - fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line; - fmt->sample_format = VIDEO_PALETTE_RAW; - fmt->start[0] = fmt2.fmt.vbi.start[0]; - fmt->count[0] = fmt2.fmt.vbi.count[0]; - fmt->start[1] = fmt2.fmt.vbi.start[1]; - fmt->count[1] = fmt2.fmt.vbi.count[1]; - if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC) - fmt->flags |= VBI_UNSYNC; - if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED) - fmt->flags |= VBI_INTERLACED; - return 0; - } - case VIDIOCSVBIFMT: - { - struct vbi_format *fmt = (void *) arg; - struct v4l2_format fmt2; - - retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); - if (0 != retval) - return retval; - bttv_vbi_get_fmt(fh, &fmt2); - - if (fmt->sampling_rate != fmt2.fmt.vbi.sampling_rate || - fmt->samples_per_line != fmt2.fmt.vbi.samples_per_line || - fmt->sample_format != VIDEO_PALETTE_RAW || - fmt->start[0] != fmt2.fmt.vbi.start[0] || - fmt->start[1] != fmt2.fmt.vbi.start[1] || - fmt->count[0] != fmt->count[1] || - fmt->count[0] < 1 || - fmt->count[0] > 32 /* VBI_MAXLINES */) - return -EINVAL; - - bttv_vbi_setlines(fh,btv,fmt->count[0]); - return 0; - } - - case BTTV_VERSION: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGCHAN: - case VIDIOCSCHAN: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return bttv_common_ioctls(btv,cmd,arg); - - /* *** v4l2 *** ************************************************ */ - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = arg; - - if (0 == v4l2) - return -EINVAL; - memset(cap, 0, sizeof (*cap)); - strlcpy(cap->driver, "bttv", sizeof (cap->driver)); - strlcpy(cap->card, btv->video_dev->name, sizeof (cap->card)); - snprintf(cap->bus_info, sizeof (cap->bus_info), - "PCI:%s", pci_name(btv->c.pci)); - cap->version = BTTV_VERSION_CODE; - cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VBI_CAPTURE | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - if (no_overlay <= 0) - cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; - - if (bttv_tvcards[btv->c.type].tuner != UNSET && - bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT) - cap->capabilities |= V4L2_CAP_TUNER; - return 0; - } - - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *f = arg; - enum v4l2_buf_type type; - unsigned int i; - int index; - - type = f->type; - if (V4L2_BUF_TYPE_VBI_CAPTURE == type) { - /* vbi */ - index = f->index; - if (0 != index) - return -EINVAL; - memset(f,0,sizeof(*f)); - f->index = index; - f->type = type; - f->pixelformat = V4L2_PIX_FMT_GREY; - strcpy(f->description,"vbi data"); - return 0; - } - - /* video capture + overlay */ - index = -1; - for (i = 0; i < BTTV_FORMATS; i++) { - if (bttv_formats[i].fourcc != -1) - index++; - if ((unsigned int)index == f->index) - break; - } - if (BTTV_FORMATS == i) - return -EINVAL; - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (!(bttv_formats[i].flags & FORMAT_FLAGS_PACKED)) - return -EINVAL; - break; - default: - return -EINVAL; - } - memset(f,0,sizeof(*f)); - f->index = index; - f->type = type; - f->pixelformat = bttv_formats[i].fourcc; - strlcpy(f->description,bttv_formats[i].name,sizeof(f->description)); - return 0; - } - - case VIDIOC_TRY_FMT: - { - struct v4l2_format *f = arg; - return bttv_try_fmt(fh,btv,f); - } - case VIDIOC_G_FMT: - { - struct v4l2_format *f = arg; - return bttv_g_fmt(fh,f); - } - case VIDIOC_S_FMT: - { - struct v4l2_format *f = arg; - return bttv_s_fmt(fh,btv,f); - } - - case VIDIOC_G_FBUF: - { - struct v4l2_framebuffer *fb = arg; - - *fb = btv->fbuf; - fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; - if (fh->ovfmt) - fb->fmt.pixelformat = fh->ovfmt->fourcc; - return 0; - } - case VIDIOC_S_FBUF: - { - struct v4l2_framebuffer *fb = arg; - const struct bttv_format *fmt; - - if(!capable(CAP_SYS_ADMIN) && - !capable(CAP_SYS_RAWIO)) - return -EPERM; - - /* check args */ - fmt = format_by_fourcc(fb->fmt.pixelformat); - if (NULL == fmt) - return -EINVAL; - if (0 == (fmt->flags & FORMAT_FLAGS_PACKED)) - return -EINVAL; - - mutex_lock(&fh->cap.lock); - retval = -EINVAL; - if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { - if (fb->fmt.width > bttv_tvnorms[btv->tvnorm].swidth) - goto fh_unlock_and_return; - if (fb->fmt.height > bttv_tvnorms[btv->tvnorm].sheight) - goto fh_unlock_and_return; - } - - /* ok, accept it */ - btv->fbuf.base = fb->base; - btv->fbuf.fmt.width = fb->fmt.width; - btv->fbuf.fmt.height = fb->fmt.height; - if (0 != fb->fmt.bytesperline) - btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline; - else - btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8; - - retval = 0; - fh->ovfmt = fmt; - btv->init.ovfmt = fmt; - if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { - fh->ov.w.left = 0; - fh->ov.w.top = 0; - fh->ov.w.width = fb->fmt.width; - fh->ov.w.height = fb->fmt.height; - btv->init.ov.w.width = fb->fmt.width; - btv->init.ov.w.height = fb->fmt.height; - kfree(fh->ov.clips); - fh->ov.clips = NULL; - fh->ov.nclips = 0; - - if (check_btres(fh, RESOURCE_OVERLAY)) { - struct bttv_buffer *new; - - new = videobuf_alloc(sizeof(*new)); - bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new); - retval = bttv_switch_overlay(btv,fh,new); - } - } - mutex_unlock(&fh->cap.lock); - return retval; - } - - case VIDIOC_REQBUFS: - return videobuf_reqbufs(bttv_queue(fh),arg); - - case VIDIOC_QUERYBUF: - return videobuf_querybuf(bttv_queue(fh),arg); - - case VIDIOC_QBUF: - return videobuf_qbuf(bttv_queue(fh),arg); - - case VIDIOC_DQBUF: - return videobuf_dqbuf(bttv_queue(fh),arg, - file->f_flags & O_NONBLOCK); - - case VIDIOC_STREAMON: - { - int res = bttv_resource(fh); - - if (!check_alloc_btres(btv,fh,res)) - return -EBUSY; - return videobuf_streamon(bttv_queue(fh)); - } - case VIDIOC_STREAMOFF: - { - int res = bttv_resource(fh); - - retval = videobuf_streamoff(bttv_queue(fh)); - if (retval < 0) - return retval; - free_btres(btv,fh,res); - return 0; - } - - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *c = arg; - int i; - - if ((c->id < V4L2_CID_BASE || - c->id >= V4L2_CID_LASTP1) && - (c->id < V4L2_CID_PRIVATE_BASE || - c->id >= V4L2_CID_PRIVATE_LASTP1)) - return -EINVAL; - for (i = 0; i < BTTV_CTLS; i++) - if (bttv_ctls[i].id == c->id) - break; - if (i == BTTV_CTLS) { - *c = no_ctl; - return 0; - } - *c = bttv_ctls[i]; - if (i >= 4 && i <= 8) { - struct video_audio va; - memset(&va,0,sizeof(va)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); - switch (bttv_ctls[i].id) { - case V4L2_CID_AUDIO_VOLUME: - if (!(va.flags & VIDEO_AUDIO_VOLUME)) - *c = no_ctl; - break; - case V4L2_CID_AUDIO_BALANCE: - if (!(va.flags & VIDEO_AUDIO_BALANCE)) - *c = no_ctl; - break; - case V4L2_CID_AUDIO_BASS: - if (!(va.flags & VIDEO_AUDIO_BASS)) - *c = no_ctl; - break; - case V4L2_CID_AUDIO_TREBLE: - if (!(va.flags & VIDEO_AUDIO_TREBLE)) - *c = no_ctl; - break; - } - } - return 0; - } - case VIDIOC_G_CTRL: - return get_control(btv,arg); - case VIDIOC_S_CTRL: - return set_control(btv,arg); - case VIDIOC_G_PARM: - { - struct v4l2_streamparm *parm = arg; - struct v4l2_standard s; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - memset(parm,0,sizeof(*parm)); - v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id, - bttv_tvnorms[btv->tvnorm].name); - parm->parm.capture.timeperframe = s.frameperiod; - return 0; - } - - case VIDIOC_G_PRIORITY: - { - enum v4l2_priority *p = arg; - - *p = v4l2_prio_max(&btv->prio); - return 0; - } - case VIDIOC_S_PRIORITY: - { - enum v4l2_priority *prio = arg; - - return v4l2_prio_change(&btv->prio, &fh->prio, *prio); - } - - case VIDIOC_ENUMSTD: - case VIDIOC_G_STD: - case VIDIOC_S_STD: - case VIDIOC_ENUMINPUT: - case VIDIOC_G_INPUT: - case VIDIOC_S_INPUT: - case VIDIOC_G_TUNER: - case VIDIOC_S_TUNER: - case VIDIOC_G_FREQUENCY: - case VIDIOC_S_FREQUENCY: - case VIDIOC_LOG_STATUS: - return bttv_common_ioctls(btv,cmd,arg); - - default: - return -ENOIOCTLCMD; - } - return 0; - - fh_unlock_and_return: - mutex_unlock(&fh->cap.lock); - return retval; -} - -static int bttv_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct bttv_fh *fh = file->private_data; - - switch (cmd) { - case BTTV_VBISIZE: - bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); - return fh->lines * 2 * 2048; - default: - return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl); - } -} - -static ssize_t bttv_read(struct file *file, char __user *data, - size_t count, loff_t *ppos) -{ - struct bttv_fh *fh = file->private_data; - int retval = 0; - - if (fh->btv->errors) - bttv_reinit_bt848(fh->btv); - dprintk("bttv%d: read count=%d type=%s\n", - fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]); - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (locked_btres(fh->btv,RESOURCE_VIDEO)) - return -EBUSY; - retval = videobuf_read_one(&fh->cap, data, count, ppos, - file->f_flags & O_NONBLOCK); - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI)) - return -EBUSY; - retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1, - file->f_flags & O_NONBLOCK); - break; - default: - BUG(); - } - return retval; -} - -static unsigned int bttv_poll(struct file *file, poll_table *wait) -{ - struct bttv_fh *fh = file->private_data; - struct bttv_buffer *buf; - enum v4l2_field field; - - if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { - if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI)) - return POLLERR; - return videobuf_poll_stream(file, &fh->vbi, wait); - } - - if (check_btres(fh,RESOURCE_VIDEO)) { - /* streaming capture */ - if (list_empty(&fh->cap.stream)) - return POLLERR; - buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream); - } else { - /* read() capture */ - mutex_lock(&fh->cap.lock); - if (NULL == fh->cap.read_buf) { - /* need to capture a new frame */ - if (locked_btres(fh->btv,RESOURCE_VIDEO)) { - mutex_unlock(&fh->cap.lock); - return POLLERR; - } - fh->cap.read_buf = videobuf_alloc(fh->cap.msize); - if (NULL == fh->cap.read_buf) { - mutex_unlock(&fh->cap.lock); - return POLLERR; - } - fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR; - field = videobuf_next_field(&fh->cap); - if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) { - kfree (fh->cap.read_buf); - fh->cap.read_buf = NULL; - mutex_unlock(&fh->cap.lock); - return POLLERR; - } - fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); - fh->cap.read_off = 0; - } - mutex_unlock(&fh->cap.lock); - buf = (struct bttv_buffer*)fh->cap.read_buf; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == STATE_DONE || - buf->vb.state == STATE_ERROR) - return POLLIN|POLLRDNORM; - return 0; -} - -static int bttv_open(struct inode *inode, struct file *file) -{ - int minor = iminor(inode); - struct bttv *btv = NULL; - struct bttv_fh *fh; - enum v4l2_buf_type type = 0; - unsigned int i; - - dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); - - for (i = 0; i < bttv_num; i++) { - if (bttvs[i].video_dev && - bttvs[i].video_dev->minor == minor) { - btv = &bttvs[i]; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - } - if (bttvs[i].vbi_dev && - bttvs[i].vbi_dev->minor == minor) { - btv = &bttvs[i]; - type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - } - } - if (NULL == btv) - return -ENODEV; - - dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n", - btv->c.nr,v4l2_type_names[type]); - - /* allocate per filehandle data */ - fh = kmalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - file->private_data = fh; - *fh = btv->init; - fh->type = type; - fh->ov.setup_ok = 0; - v4l2_prio_open(&btv->prio,&fh->prio); - - videobuf_queue_init(&fh->cap, &bttv_video_qops, - btv->c.pci, &btv->s_lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct bttv_buffer), - fh); - videobuf_queue_init(&fh->vbi, &bttv_vbi_qops, - btv->c.pci, &btv->s_lock, - V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_FIELD_SEQ_TB, - sizeof(struct bttv_buffer), - fh); - i2c_vidiocschan(btv); - - btv->users++; - if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) - bttv_vbi_setlines(fh,btv,16); - bttv_field_count(btv); - return 0; -} - -static int bttv_release(struct inode *inode, struct file *file) -{ - struct bttv_fh *fh = file->private_data; - struct bttv *btv = fh->btv; - - /* turn off overlay */ - if (check_btres(fh, RESOURCE_OVERLAY)) - bttv_switch_overlay(btv,fh,NULL); - - /* stop video capture */ - if (check_btres(fh, RESOURCE_VIDEO)) { - videobuf_streamoff(&fh->cap); - free_btres(btv,fh,RESOURCE_VIDEO); - } - if (fh->cap.read_buf) { - buffer_release(&fh->cap,fh->cap.read_buf); - kfree(fh->cap.read_buf); - } - - /* stop vbi capture */ - if (check_btres(fh, RESOURCE_VBI)) { - if (fh->vbi.streaming) - videobuf_streamoff(&fh->vbi); - if (fh->vbi.reading) - videobuf_read_stop(&fh->vbi); - free_btres(btv,fh,RESOURCE_VBI); - } - - /* free stuff */ - videobuf_mmap_free(&fh->cap); - videobuf_mmap_free(&fh->vbi); - v4l2_prio_close(&btv->prio,&fh->prio); - file->private_data = NULL; - kfree(fh); - - btv->users--; - bttv_field_count(btv); - return 0; -} - -static int -bttv_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct bttv_fh *fh = file->private_data; - - dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n", - fh->btv->c.nr, v4l2_type_names[fh->type], - vma->vm_start, vma->vm_end - vma->vm_start); - return videobuf_mmap_mapper(bttv_queue(fh),vma); -} - -static struct file_operations bttv_fops = -{ - .owner = THIS_MODULE, - .open = bttv_open, - .release = bttv_release, - .ioctl = bttv_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, - .read = bttv_read, - .mmap = bttv_mmap, - .poll = bttv_poll, -}; - -static struct video_device bttv_video_template = -{ - .name = "UNSET", - .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| - VID_TYPE_CLIPPING|VID_TYPE_SCALES, - .hardware = VID_HARDWARE_BT848, - .fops = &bttv_fops, - .minor = -1, -}; - -static struct video_device bttv_vbi_template = -{ - .name = "bt848/878 vbi", - .type = VID_TYPE_TUNER|VID_TYPE_TELETEXT, - .hardware = VID_HARDWARE_BT848, - .fops = &bttv_fops, - .minor = -1, -}; - -/* ----------------------------------------------------------------------- */ -/* radio interface */ - -static int radio_open(struct inode *inode, struct file *file) -{ - int minor = iminor(inode); - struct bttv *btv = NULL; - unsigned int i; - - dprintk("bttv: open minor=%d\n",minor); - - for (i = 0; i < bttv_num; i++) { - if (bttvs[i].radio_dev->minor == minor) { - btv = &bttvs[i]; - break; - } - } - if (NULL == btv) - return -ENODEV; - - dprintk("bttv%d: open called (radio)\n",btv->c.nr); - mutex_lock(&btv->lock); - - btv->radio_user++; - - file->private_data = btv; - - bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type); - audio_mux(btv,AUDIO_RADIO); - - mutex_unlock(&btv->lock); - return 0; -} - -static int radio_release(struct inode *inode, struct file *file) -{ - struct bttv *btv = file->private_data; - struct rds_command cmd; - - btv->radio_user--; - - bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd); - - return 0; -} - -static int radio_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct bttv *btv = file->private_data; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *cap = arg; - - memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->radio_dev->name); - cap->type = VID_TYPE_TUNER; - cap->channels = 1; - cap->audios = 1; - return 0; - } - - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; - - if(v->tuner) - return -EINVAL; - memset(v,0,sizeof(*v)); - strcpy(v->name, "Radio"); - bttv_call_i2c_clients(btv,cmd,v); - return 0; - } - case VIDIOCSTUNER: - /* nothing to do */ - return 0; - - case BTTV_VERSION: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - case VIDIOC_LOG_STATUS: - return bttv_common_ioctls(btv,cmd,arg); - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int radio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, radio_do_ioctl); -} - -static ssize_t radio_read(struct file *file, char __user *data, - size_t count, loff_t *ppos) -{ - struct bttv *btv = file->private_data; - struct rds_command cmd; - cmd.block_count = count/3; - cmd.buffer = data; - cmd.instance = file; - cmd.result = -ENODEV; - - bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd); - - return cmd.result; -} - -static unsigned int radio_poll(struct file *file, poll_table *wait) -{ - struct bttv *btv = file->private_data; - struct rds_command cmd; - cmd.instance = file; - cmd.event_list = wait; - cmd.result = -ENODEV; - bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd); - - return cmd.result; -} - -static struct file_operations radio_fops = -{ - .owner = THIS_MODULE, - .open = radio_open, - .read = radio_read, - .release = radio_release, - .ioctl = radio_ioctl, - .llseek = no_llseek, - .poll = radio_poll, -}; - -static struct video_device radio_template = -{ - .name = "bt848/878 radio", - .type = VID_TYPE_TUNER, - .hardware = VID_HARDWARE_BT848, - .fops = &radio_fops, - .minor = -1, -}; - -/* ----------------------------------------------------------------------- */ -/* some debug code */ - -static int bttv_risc_decode(u32 risc) -{ - static char *instr[16] = { - [ BT848_RISC_WRITE >> 28 ] = "write", - [ BT848_RISC_SKIP >> 28 ] = "skip", - [ BT848_RISC_WRITEC >> 28 ] = "writec", - [ BT848_RISC_JUMP >> 28 ] = "jump", - [ BT848_RISC_SYNC >> 28 ] = "sync", - [ BT848_RISC_WRITE123 >> 28 ] = "write123", - [ BT848_RISC_SKIP123 >> 28 ] = "skip123", - [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23", - }; - static int incr[16] = { - [ BT848_RISC_WRITE >> 28 ] = 2, - [ BT848_RISC_JUMP >> 28 ] = 2, - [ BT848_RISC_SYNC >> 28 ] = 2, - [ BT848_RISC_WRITE123 >> 28 ] = 5, - [ BT848_RISC_SKIP123 >> 28 ] = 2, - [ BT848_RISC_WRITE1S23 >> 28 ] = 3, - }; - static char *bits[] = { - "be0", "be1", "be2", "be3/resync", - "set0", "set1", "set2", "set3", - "clr0", "clr1", "clr2", "clr3", - "irq", "res", "eol", "sol", - }; - int i; - - printk("0x%08x [ %s", risc, - instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); - for (i = ARRAY_SIZE(bits)-1; i >= 0; i--) - if (risc & (1 << (i + 12))) - printk(" %s",bits[i]); - printk(" count=%d ]\n", risc & 0xfff); - return incr[risc >> 28] ? incr[risc >> 28] : 1; -} - -static void bttv_risc_disasm(struct bttv *btv, - struct btcx_riscmem *risc) -{ - unsigned int i,j,n; - - printk("%s: risc disasm: %p [dma=0x%08lx]\n", - btv->c.name, risc->cpu, (unsigned long)risc->dma); - for (i = 0; i < (risc->size >> 2); i += n) { - printk("%s: 0x%lx: ", btv->c.name, - (unsigned long)(risc->dma + (i<<2))); - n = bttv_risc_decode(risc->cpu[i]); - for (j = 1; j < n; j++) - printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n", - btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)), - risc->cpu[i+j], j); - if (0 == risc->cpu[i]) - break; - } -} - -static void bttv_print_riscaddr(struct bttv *btv) -{ - printk(" main: %08Lx\n", - (unsigned long long)btv->main.dma); - printk(" vbi : o=%08Lx e=%08Lx\n", - btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0, - btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0); - printk(" cap : o=%08Lx e=%08Lx\n", - btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, - btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); - printk(" scr : o=%08Lx e=%08Lx\n", - btv->screen ? (unsigned long long)btv->screen->top.dma : 0, - btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0); - bttv_risc_disasm(btv, &btv->main); -} - -/* ----------------------------------------------------------------------- */ -/* irq handler */ - -static char *irq_name[] = { - "FMTCHG", // format change detected (525 vs. 625) - "VSYNC", // vertical sync (new field) - "HSYNC", // horizontal sync - "OFLOW", // chroma/luma AGC overflow - "HLOCK", // horizontal lock changed - "VPRES", // video presence changed - "6", "7", - "I2CDONE", // hw irc operation finished - "GPINT", // gpio port triggered irq - "10", - "RISCI", // risc instruction triggered irq - "FBUS", // pixel data fifo dropped data (high pci bus latencies) - "FTRGT", // pixel data fifo overrun - "FDSR", // fifo data stream resyncronisation - "PPERR", // parity error (data transfer) - "RIPERR", // parity error (read risc instructions) - "PABORT", // pci abort - "OCERR", // risc instruction error - "SCERR", // syncronisation error -}; - -static void bttv_print_irqbits(u32 print, u32 mark) -{ - unsigned int i; - - printk("bits:"); - for (i = 0; i < ARRAY_SIZE(irq_name); i++) { - if (print & (1 << i)) - printk(" %s",irq_name[i]); - if (mark & (1 << i)) - printk("*"); - } -} - -static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc) -{ - printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n", - btv->c.nr, - (unsigned long)btv->main.dma, - (unsigned long)btv->main.cpu[RISC_SLOT_O_VBI+1], - (unsigned long)btv->main.cpu[RISC_SLOT_O_FIELD+1], - (unsigned long)rc); - - if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) { - printk("bttv%d: Oh, there (temporarely?) is no input signal. " - "Ok, then this is harmless, don't worry ;)\n", - btv->c.nr); - return; - } - printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n", - btv->c.nr); - printk("bttv%d: Lets try to catch the culpit red-handed ...\n", - btv->c.nr); - dump_stack(); -} - -static int -bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set) -{ - struct bttv_buffer *item; - - memset(set,0,sizeof(*set)); - - /* capture request ? */ - if (!list_empty(&btv->capture)) { - set->frame_irq = 1; - item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue); - if (V4L2_FIELD_HAS_TOP(item->vb.field)) - set->top = item; - if (V4L2_FIELD_HAS_BOTTOM(item->vb.field)) - set->bottom = item; - - /* capture request for other field ? */ - if (!V4L2_FIELD_HAS_BOTH(item->vb.field) && - (item->vb.queue.next != &btv->capture)) { - item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue); - if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) { - if (NULL == set->top && - V4L2_FIELD_TOP == item->vb.field) { - set->top = item; - } - if (NULL == set->bottom && - V4L2_FIELD_BOTTOM == item->vb.field) { - set->bottom = item; - } - if (NULL != set->top && NULL != set->bottom) - set->top_irq = 2; - } - } - } - - /* screen overlay ? */ - if (NULL != btv->screen) { - if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) { - if (NULL == set->top && NULL == set->bottom) { - set->top = btv->screen; - set->bottom = btv->screen; - } - } else { - if (V4L2_FIELD_TOP == btv->screen->vb.field && - NULL == set->top) { - set->top = btv->screen; - } - if (V4L2_FIELD_BOTTOM == btv->screen->vb.field && - NULL == set->bottom) { - set->bottom = btv->screen; - } - } - } - - dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n", - btv->c.nr,set->top, set->bottom, - btv->screen,set->frame_irq,set->top_irq); - return 0; -} - -static void -bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup, - struct bttv_buffer_set *curr, unsigned int state) -{ - struct timeval ts; - - do_gettimeofday(&ts); - - if (wakeup->top == wakeup->bottom) { - if (NULL != wakeup->top && curr->top != wakeup->top) { - if (irq_debug > 1) - printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top); - wakeup->top->vb.ts = ts; - wakeup->top->vb.field_count = btv->field_count; - wakeup->top->vb.state = state; - wake_up(&wakeup->top->vb.done); - } - } else { - if (NULL != wakeup->top && curr->top != wakeup->top) { - if (irq_debug > 1) - printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top); - wakeup->top->vb.ts = ts; - wakeup->top->vb.field_count = btv->field_count; - wakeup->top->vb.state = state; - wake_up(&wakeup->top->vb.done); - } - if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) { - if (irq_debug > 1) - printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom); - wakeup->bottom->vb.ts = ts; - wakeup->bottom->vb.field_count = btv->field_count; - wakeup->bottom->vb.state = state; - wake_up(&wakeup->bottom->vb.done); - } - } -} - -static void -bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup, - unsigned int state) -{ - struct timeval ts; - - if (NULL == wakeup) - return; - - do_gettimeofday(&ts); - wakeup->vb.ts = ts; - wakeup->vb.field_count = btv->field_count; - wakeup->vb.state = state; - wake_up(&wakeup->vb.done); -} - -static void bttv_irq_timeout(unsigned long data) -{ - struct bttv *btv = (struct bttv *)data; - struct bttv_buffer_set old,new; - struct bttv_buffer *ovbi; - struct bttv_buffer *item; - unsigned long flags; - - if (bttv_verbose) { - printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ", - btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total, - btread(BT848_RISC_COUNT)); - bttv_print_irqbits(btread(BT848_INT_STAT),0); - printk("\n"); - } - - spin_lock_irqsave(&btv->s_lock,flags); - - /* deactivate stuff */ - memset(&new,0,sizeof(new)); - old = btv->curr; - ovbi = btv->cvbi; - btv->curr = new; - btv->cvbi = NULL; - btv->loop_irq = 0; - bttv_buffer_activate_video(btv, &new); - bttv_buffer_activate_vbi(btv, NULL); - bttv_set_dma(btv, 0); - - /* wake up */ - bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR); - bttv_irq_wakeup_vbi(btv, ovbi, STATE_ERROR); - - /* cancel all outstanding capture / vbi requests */ - while (!list_empty(&btv->capture)) { - item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue); - list_del(&item->vb.queue); - item->vb.state = STATE_ERROR; - wake_up(&item->vb.done); - } - while (!list_empty(&btv->vcapture)) { - item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue); - list_del(&item->vb.queue); - item->vb.state = STATE_ERROR; - wake_up(&item->vb.done); - } - - btv->errors++; - spin_unlock_irqrestore(&btv->s_lock,flags); -} - -static void -bttv_irq_wakeup_top(struct bttv *btv) -{ - struct bttv_buffer *wakeup = btv->curr.top; - - if (NULL == wakeup) - return; - - spin_lock(&btv->s_lock); - btv->curr.top_irq = 0; - btv->curr.top = NULL; - bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); - - do_gettimeofday(&wakeup->vb.ts); - wakeup->vb.field_count = btv->field_count; - wakeup->vb.state = STATE_DONE; - wake_up(&wakeup->vb.done); - spin_unlock(&btv->s_lock); -} - -static inline int is_active(struct btcx_riscmem *risc, u32 rc) -{ - if (rc < risc->dma) - return 0; - if (rc > risc->dma + risc->size) - return 0; - return 1; -} - -static void -bttv_irq_switch_video(struct bttv *btv) -{ - struct bttv_buffer_set new; - struct bttv_buffer_set old; - dma_addr_t rc; - - spin_lock(&btv->s_lock); - - /* new buffer set */ - bttv_irq_next_video(btv, &new); - rc = btread(BT848_RISC_COUNT); - if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) || - (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) { - btv->framedrop++; - if (debug_latency) - bttv_irq_debug_low_latency(btv, rc); - spin_unlock(&btv->s_lock); - return; - } - - /* switch over */ - old = btv->curr; - btv->curr = new; - btv->loop_irq &= ~1; - bttv_buffer_activate_video(btv, &new); - bttv_set_dma(btv, 0); - - /* switch input */ - if (UNSET != btv->new_input) { - video_mux(btv,btv->new_input); - btv->new_input = UNSET; - } - - /* wake up finished buffers */ - bttv_irq_wakeup_video(btv, &old, &new, STATE_DONE); - spin_unlock(&btv->s_lock); -} - -static void -bttv_irq_switch_vbi(struct bttv *btv) -{ - struct bttv_buffer *new = NULL; - struct bttv_buffer *old; - u32 rc; - - spin_lock(&btv->s_lock); - - if (!list_empty(&btv->vcapture)) - new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue); - old = btv->cvbi; - - rc = btread(BT848_RISC_COUNT); - if (NULL != old && (is_active(&old->top, rc) || - is_active(&old->bottom, rc))) { - btv->framedrop++; - if (debug_latency) - bttv_irq_debug_low_latency(btv, rc); - spin_unlock(&btv->s_lock); - return; - } - - /* switch */ - btv->cvbi = new; - btv->loop_irq &= ~4; - bttv_buffer_activate_vbi(btv, new); - bttv_set_dma(btv, 0); - - bttv_irq_wakeup_vbi(btv, old, STATE_DONE); - spin_unlock(&btv->s_lock); -} - -static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) -{ - u32 stat,astat; - u32 dstat; - int count; - struct bttv *btv; - int handled = 0; - - btv=(struct bttv *)dev_id; - - if (btv->custom_irq) - handled = btv->custom_irq(btv); - - count=0; - while (1) { - /* get/clear interrupt status bits */ - stat=btread(BT848_INT_STAT); - astat=stat&btread(BT848_INT_MASK); - if (!astat) - break; - handled = 1; - btwrite(stat,BT848_INT_STAT); - - /* get device status bits */ - dstat=btread(BT848_DSTATUS); - - if (irq_debug) { - printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d " - "riscs=%x, riscc=%08x, ", - btv->c.nr, count, btv->field_count, - stat>>28, btread(BT848_RISC_COUNT)); - bttv_print_irqbits(stat,astat); - if (stat & BT848_INT_HLOCK) - printk(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC) - ? "yes" : "no"); - if (stat & BT848_INT_VPRES) - printk(" PRES => %s", (dstat & BT848_DSTATUS_PRES) - ? "yes" : "no"); - if (stat & BT848_INT_FMTCHG) - printk(" NUML => %s", (dstat & BT848_DSTATUS_NUML) - ? "625" : "525"); - printk("\n"); - } - - if (astat&BT848_INT_VSYNC) - btv->field_count++; - - if ((astat & BT848_INT_GPINT) && btv->remote) { - wake_up(&btv->gpioq); - bttv_input_irq(btv); - } - - if (astat & BT848_INT_I2CDONE) { - btv->i2c_done = stat; - wake_up(&btv->i2c_queue); - } - - if ((astat & BT848_INT_RISCI) && (stat & (4<<28))) - bttv_irq_switch_vbi(btv); - - if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) - bttv_irq_wakeup_top(btv); - - if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) - bttv_irq_switch_video(btv); - - if ((astat & BT848_INT_HLOCK) && btv->opt_automute) - audio_mux(btv, -1); - - if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) { - printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr, - (astat & BT848_INT_SCERR) ? "SCERR" : "", - (astat & BT848_INT_OCERR) ? "OCERR" : "", - btread(BT848_RISC_COUNT)); - bttv_print_irqbits(stat,astat); - printk("\n"); - if (bttv_debug) - bttv_print_riscaddr(btv); - } - if (fdsr && astat & BT848_INT_FDSR) { - printk(KERN_INFO "bttv%d: FDSR @ %08x\n", - btv->c.nr,btread(BT848_RISC_COUNT)); - if (bttv_debug) - bttv_print_riscaddr(btv); - } - - count++; - if (count > 4) { - - if (count > 8 || !(astat & BT848_INT_GPINT)) { - btwrite(0, BT848_INT_MASK); - - printk(KERN_ERR - "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr); - } else { - printk(KERN_ERR - "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr); - - btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT), - BT848_INT_MASK); - }; - - bttv_print_irqbits(stat,astat); - - printk("]\n"); - } - } - btv->irq_total++; - if (handled) - btv->irq_me++; - return IRQ_RETVAL(handled); -} - - -/* ----------------------------------------------------------------------- */ -/* initialitation */ - -static struct video_device *vdev_init(struct bttv *btv, - struct video_device *template, - char *type) -{ - struct video_device *vfd; - - vfd = video_device_alloc(); - if (NULL == vfd) - return NULL; - *vfd = *template; - vfd->minor = -1; - vfd->dev = &btv->c.pci->dev; - vfd->release = video_device_release; - snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)", - btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", - type, bttv_tvcards[btv->c.type].name); - return vfd; -} - -static void bttv_unregister_video(struct bttv *btv) -{ - if (btv->video_dev) { - if (-1 != btv->video_dev->minor) - video_unregister_device(btv->video_dev); - else - video_device_release(btv->video_dev); - btv->video_dev = NULL; - } - if (btv->vbi_dev) { - if (-1 != btv->vbi_dev->minor) - video_unregister_device(btv->vbi_dev); - else - video_device_release(btv->vbi_dev); - btv->vbi_dev = NULL; - } - if (btv->radio_dev) { - if (-1 != btv->radio_dev->minor) - video_unregister_device(btv->radio_dev); - else - video_device_release(btv->radio_dev); - btv->radio_dev = NULL; - } -} - -/* register video4linux devices */ -static int __devinit bttv_register_video(struct bttv *btv) -{ - if (no_overlay <= 0) { - bttv_video_template.type |= VID_TYPE_OVERLAY; - } else { - printk("bttv: Overlay support disabled.\n"); - } - - /* video */ - btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); - if (NULL == btv->video_dev) - goto err; - if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) - goto err; - printk(KERN_INFO "bttv%d: registered device video%d\n", - btv->c.nr,btv->video_dev->minor & 0x1f); - video_device_create_file(btv->video_dev, &class_device_attr_card); - - /* vbi */ - btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); - if (NULL == btv->vbi_dev) - goto err; - if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) - goto err; - printk(KERN_INFO "bttv%d: registered device vbi%d\n", - btv->c.nr,btv->vbi_dev->minor & 0x1f); - - if (!btv->has_radio) - return 0; - /* radio */ - btv->radio_dev = vdev_init(btv, &radio_template, "radio"); - if (NULL == btv->radio_dev) - goto err; - if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) - goto err; - printk(KERN_INFO "bttv%d: registered device radio%d\n", - btv->c.nr,btv->radio_dev->minor & 0x1f); - - /* all done */ - return 0; - - err: - bttv_unregister_video(btv); - return -1; -} - - -/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */ -/* response on cards with no firmware is not enabled by OF */ -static void pci_set_command(struct pci_dev *dev) -{ -#if defined(__powerpc__) - unsigned int cmd; - - pci_read_config_dword(dev, PCI_COMMAND, &cmd); - cmd = (cmd | PCI_COMMAND_MEMORY ); - pci_write_config_dword(dev, PCI_COMMAND, cmd); -#endif -} - -static int __devinit bttv_probe(struct pci_dev *dev, - const struct pci_device_id *pci_id) -{ - int result; - unsigned char lat; - struct bttv *btv; - - if (bttv_num == BTTV_MAX) - return -ENOMEM; - printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); - btv=&bttvs[bttv_num]; - memset(btv,0,sizeof(*btv)); - btv->c.nr = bttv_num; - sprintf(btv->c.name,"bttv%d",btv->c.nr); - - /* initialize structs / fill in defaults */ - mutex_init(&btv->lock); - mutex_init(&btv->reslock); - spin_lock_init(&btv->s_lock); - spin_lock_init(&btv->gpio_lock); - init_waitqueue_head(&btv->gpioq); - init_waitqueue_head(&btv->i2c_queue); - INIT_LIST_HEAD(&btv->c.subs); - INIT_LIST_HEAD(&btv->capture); - INIT_LIST_HEAD(&btv->vcapture); - v4l2_prio_init(&btv->prio); - - init_timer(&btv->timeout); - btv->timeout.function = bttv_irq_timeout; - btv->timeout.data = (unsigned long)btv; - - btv->i2c_rc = -1; - btv->tuner_type = UNSET; - btv->new_input = UNSET; - btv->has_radio=radio[btv->c.nr]; - - /* pci stuff (init, get irq/mmio, ... */ - btv->c.pci = dev; - btv->id = dev->device; - if (pci_enable_device(dev)) { - printk(KERN_WARNING "bttv%d: Can't enable device.\n", - btv->c.nr); - return -EIO; - } - if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { - printk(KERN_WARNING "bttv%d: No suitable DMA available.\n", - btv->c.nr); - return -EIO; - } - if (!request_mem_region(pci_resource_start(dev,0), - pci_resource_len(dev,0), - btv->c.name)) { - printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n", - btv->c.nr, pci_resource_start(dev,0)); - return -EBUSY; - } - pci_set_master(dev); - pci_set_command(dev); - pci_set_drvdata(dev,btv); - - pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", - bttv_num,btv->id, btv->revision, pci_name(dev)); - printk("irq: %d, latency: %d, mmio: 0x%lx\n", - btv->c.pci->irq, lat, pci_resource_start(dev,0)); - schedule(); - - btv->bt848_mmio=ioremap(pci_resource_start(dev,0), 0x1000); - if (NULL == ioremap(pci_resource_start(dev,0), 0x1000)) { - printk("bttv%d: ioremap() failed\n", btv->c.nr); - result = -EIO; - goto fail1; - } - - /* identify card */ - bttv_idcard(btv); - - /* disable irqs, register irq handler */ - btwrite(0, BT848_INT_MASK); - result = request_irq(btv->c.pci->irq, bttv_irq, - SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv); - if (result < 0) { - printk(KERN_ERR "bttv%d: can't get IRQ %d\n", - bttv_num,btv->c.pci->irq); - goto fail1; - } - - if (0 != bttv_handle_chipset(btv)) { - result = -EIO; - goto fail2; - } - - /* init options from insmod args */ - btv->opt_combfilter = combfilter; - btv->opt_lumafilter = lumafilter; - btv->opt_automute = automute; - btv->opt_chroma_agc = chroma_agc; - btv->opt_adc_crush = adc_crush; - btv->opt_vcr_hack = vcr_hack; - btv->opt_whitecrush_upper = whitecrush_upper; - btv->opt_whitecrush_lower = whitecrush_lower; - btv->opt_uv_ratio = uv_ratio; - btv->opt_full_luma_range = full_luma_range; - btv->opt_coring = coring; - - /* fill struct bttv with some useful defaults */ - btv->init.btv = btv; - btv->init.ov.w.width = 320; - btv->init.ov.w.height = 240; - btv->init.fmt = format_by_palette(VIDEO_PALETTE_RGB24); - btv->init.width = 320; - btv->init.height = 240; - btv->init.lines = 16; - btv->input = 0; - - /* initialize hardware */ - if (bttv_gpio) - bttv_gpio_tracking(btv,"pre-init"); - - bttv_risc_init_main(btv); - init_bt848(btv); - - /* gpio */ - btwrite(0x00, BT848_GPIO_REG_INP); - btwrite(0x00, BT848_GPIO_OUT_EN); - if (bttv_verbose) - bttv_gpio_tracking(btv,"init"); - - /* needs to be done before i2c is registered */ - bttv_init_card1(btv); - - /* register i2c + gpio */ - init_bttv_i2c(btv); - - /* some card-specific stuff (needs working i2c) */ - bttv_init_card2(btv); - init_irqreg(btv); - - /* register video4linux + input */ - if (!bttv_tvcards[btv->c.type].no_video) { - bttv_register_video(btv); - bt848_bright(btv,32768); - bt848_contrast(btv,32768); - bt848_hue(btv,32768); - bt848_sat(btv,32768); - audio_mux(btv,AUDIO_MUTE); - set_input(btv,0); - } - - /* add subdevices */ - if (bttv_tvcards[btv->c.type].has_dvb) - bttv_sub_add_device(&btv->c, "dvb"); - - bttv_input_init(btv); - - /* everything is fine */ - bttv_num++; - return 0; - - fail2: - free_irq(btv->c.pci->irq,btv); - - fail1: - if (btv->bt848_mmio) - iounmap(btv->bt848_mmio); - release_mem_region(pci_resource_start(btv->c.pci,0), - pci_resource_len(btv->c.pci,0)); - pci_set_drvdata(dev,NULL); - return result; -} - -static void __devexit bttv_remove(struct pci_dev *pci_dev) -{ - struct bttv *btv = pci_get_drvdata(pci_dev); - - if (bttv_verbose) - printk("bttv%d: unloading\n",btv->c.nr); - - /* shutdown everything (DMA+IRQs) */ - btand(~15, BT848_GPIO_DMA_CTL); - btwrite(0, BT848_INT_MASK); - btwrite(~0x0, BT848_INT_STAT); - btwrite(0x0, BT848_GPIO_OUT_EN); - if (bttv_gpio) - bttv_gpio_tracking(btv,"cleanup"); - - /* tell gpio modules we are leaving ... */ - btv->shutdown=1; - wake_up(&btv->gpioq); - bttv_input_fini(btv); - bttv_sub_del_devices(&btv->c); - - /* unregister i2c_bus + input */ - fini_bttv_i2c(btv); - - /* unregister video4linux */ - bttv_unregister_video(btv); - - /* free allocated memory */ - btcx_riscmem_free(btv->c.pci,&btv->main); - - /* free ressources */ - free_irq(btv->c.pci->irq,btv); - iounmap(btv->bt848_mmio); - release_mem_region(pci_resource_start(btv->c.pci,0), - pci_resource_len(btv->c.pci,0)); - - pci_set_drvdata(pci_dev, NULL); - return; -} - -static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) -{ - struct bttv *btv = pci_get_drvdata(pci_dev); - struct bttv_buffer_set idle; - unsigned long flags; - - dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event); - - /* stop dma + irqs */ - spin_lock_irqsave(&btv->s_lock,flags); - memset(&idle, 0, sizeof(idle)); - btv->state.video = btv->curr; - btv->state.vbi = btv->cvbi; - btv->state.loop_irq = btv->loop_irq; - btv->curr = idle; - btv->loop_irq = 0; - bttv_buffer_activate_video(btv, &idle); - bttv_buffer_activate_vbi(btv, NULL); - bttv_set_dma(btv, 0); - btwrite(0, BT848_INT_MASK); - spin_unlock_irqrestore(&btv->s_lock,flags); - - /* save bt878 state */ - btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN); - btv->state.gpio_data = gpio_read(); - - /* save pci state */ - pci_save_state(pci_dev); - if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) { - pci_disable_device(pci_dev); - btv->state.disabled = 1; - } - return 0; -} - -static int bttv_resume(struct pci_dev *pci_dev) -{ - struct bttv *btv = pci_get_drvdata(pci_dev); - unsigned long flags; - int err; - - dprintk("bttv%d: resume\n", btv->c.nr); - - /* restore pci state */ - if (btv->state.disabled) { - err=pci_enable_device(pci_dev); - if (err) { - printk(KERN_WARNING "bttv%d: Can't enable device.\n", - btv->c.nr); - return err; - } - btv->state.disabled = 0; - } - err=pci_set_power_state(pci_dev, PCI_D0); - if (err) { - pci_disable_device(pci_dev); - printk(KERN_WARNING "bttv%d: Can't enable device.\n", - btv->c.nr); - btv->state.disabled = 1; - return err; - } - - pci_restore_state(pci_dev); - - /* restore bt878 state */ - bttv_reinit_bt848(btv); - gpio_inout(0xffffff, btv->state.gpio_enable); - gpio_write(btv->state.gpio_data); - - /* restart dma */ - spin_lock_irqsave(&btv->s_lock,flags); - btv->curr = btv->state.video; - btv->cvbi = btv->state.vbi; - btv->loop_irq = btv->state.loop_irq; - bttv_buffer_activate_video(btv, &btv->curr); - bttv_buffer_activate_vbi(btv, btv->cvbi); - bttv_set_dma(btv, 0); - spin_unlock_irqrestore(&btv->s_lock,flags); - return 0; -} - -static struct pci_device_id bttv_pci_tbl[] = { - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0,} -}; - -MODULE_DEVICE_TABLE(pci, bttv_pci_tbl); - -static struct pci_driver bttv_pci_driver = { - .name = "bttv", - .id_table = bttv_pci_tbl, - .probe = bttv_probe, - .remove = __devexit_p(bttv_remove), - .suspend = bttv_suspend, - .resume = bttv_resume, -}; - -static int bttv_init_module(void) -{ - bttv_num = 0; - - printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n", - (BTTV_VERSION_CODE >> 16) & 0xff, - (BTTV_VERSION_CODE >> 8) & 0xff, - BTTV_VERSION_CODE & 0xff); -#ifdef SNAPSHOT - printk(KERN_INFO "bttv: snapshot date %04d-%02d-%02d\n", - SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); -#endif - if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME) - gbuffers = 2; - if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF) - gbufsize = BTTV_MAX_FBUF; - gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK; - if (bttv_verbose) - printk(KERN_INFO "bttv: using %d buffers with %dk (%d pages) each for capture\n", - gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT); - - bttv_check_chipset(); - - bus_register(&bttv_sub_bus_type); - return pci_register_driver(&bttv_pci_driver); -} - -static void bttv_cleanup_module(void) -{ - pci_unregister_driver(&bttv_pci_driver); - bus_unregister(&bttv_sub_bus_type); - return; -} - -module_init(bttv_init_module); -module_exit(bttv_cleanup_module); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c deleted file mode 100644 index c4d5e2b70c28..000000000000 --- a/drivers/media/video/bttv-gpio.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - - bttv-gpio.c -- gpio sub drivers - - sysfs-based sub driver interface for bttv - mainly intented for gpio access - - - Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) - (c) 1999-2003 Gerd Knorr - - 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 "bttvp.h" - -/* ----------------------------------------------------------------------- */ -/* internal: the bttv "bus" */ - -static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv) -{ - struct bttv_sub_driver *sub = to_bttv_sub_drv(drv); - int len = strlen(sub->wanted); - - if (0 == strncmp(dev->bus_id, sub->wanted, len)) - return 1; - return 0; -} - -static int bttv_sub_probe(struct device *dev) -{ - struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); - struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); - - return sub->probe ? sub->probe(sdev) : -ENODEV; -} - -static int bttv_sub_remove(struct device *dev) -{ - struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); - struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); - - if (sub->remove) - sub->remove(sdev); - return 0; -} - -struct bus_type bttv_sub_bus_type = { - .name = "bttv-sub", - .match = &bttv_sub_bus_match, - .probe = bttv_sub_probe, - .remove = bttv_sub_remove, -}; -EXPORT_SYMBOL(bttv_sub_bus_type); - -static void release_sub_device(struct device *dev) -{ - struct bttv_sub_device *sub = to_bttv_sub_dev(dev); - kfree(sub); -} - -int bttv_sub_add_device(struct bttv_core *core, char *name) -{ - struct bttv_sub_device *sub; - int err; - - sub = kzalloc(sizeof(*sub),GFP_KERNEL); - if (NULL == sub) - return -ENOMEM; - - sub->core = core; - sub->dev.parent = &core->pci->dev; - sub->dev.bus = &bttv_sub_bus_type; - sub->dev.release = release_sub_device; - snprintf(sub->dev.bus_id,sizeof(sub->dev.bus_id),"%s%d", - name, core->nr); - - err = device_register(&sub->dev); - if (0 != err) { - kfree(sub); - return err; - } - printk("bttv%d: add subdevice \"%s\"\n", core->nr, sub->dev.bus_id); - list_add_tail(&sub->list,&core->subs); - return 0; -} - -int bttv_sub_del_devices(struct bttv_core *core) -{ - struct bttv_sub_device *sub; - struct list_head *item,*save; - - list_for_each_safe(item,save,&core->subs) { - sub = list_entry(item,struct bttv_sub_device,list); - list_del(&sub->list); - device_unregister(&sub->dev); - } - return 0; -} - -void bttv_gpio_irq(struct bttv_core *core) -{ - struct bttv_sub_driver *drv; - struct bttv_sub_device *dev; - struct list_head *item; - - list_for_each(item,&core->subs) { - dev = list_entry(item,struct bttv_sub_device,list); - drv = to_bttv_sub_drv(dev->dev.driver); - if (drv && drv->gpio_irq) - drv->gpio_irq(dev); - } -} - -/* ----------------------------------------------------------------------- */ -/* external: sub-driver register/unregister */ - -int bttv_sub_register(struct bttv_sub_driver *sub, char *wanted) -{ - sub->drv.bus = &bttv_sub_bus_type; - snprintf(sub->wanted,sizeof(sub->wanted),"%s",wanted); - return driver_register(&sub->drv); -} -EXPORT_SYMBOL(bttv_sub_register); - -int bttv_sub_unregister(struct bttv_sub_driver *sub) -{ - driver_unregister(&sub->drv); - return 0; -} -EXPORT_SYMBOL(bttv_sub_unregister); - -/* ----------------------------------------------------------------------- */ -/* external: gpio access functions */ - -void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits) -{ - struct bttv *btv = container_of(core, struct bttv, c); - unsigned long flags; - u32 data; - - spin_lock_irqsave(&btv->gpio_lock,flags); - data = btread(BT848_GPIO_OUT_EN); - data = data & ~mask; - data = data | (mask & outbits); - btwrite(data,BT848_GPIO_OUT_EN); - spin_unlock_irqrestore(&btv->gpio_lock,flags); -} -EXPORT_SYMBOL(bttv_gpio_inout); - -u32 bttv_gpio_read(struct bttv_core *core) -{ - struct bttv *btv = container_of(core, struct bttv, c); - u32 value; - - value = btread(BT848_GPIO_DATA); - return value; -} -EXPORT_SYMBOL(bttv_gpio_read); - -void bttv_gpio_write(struct bttv_core *core, u32 value) -{ - struct bttv *btv = container_of(core, struct bttv, c); - - btwrite(value,BT848_GPIO_DATA); -} -EXPORT_SYMBOL(bttv_gpio_write); - -void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits) -{ - struct bttv *btv = container_of(core, struct bttv, c); - unsigned long flags; - u32 data; - - spin_lock_irqsave(&btv->gpio_lock,flags); - data = btread(BT848_GPIO_DATA); - data = data & ~mask; - data = data | (mask & bits); - btwrite(data,BT848_GPIO_DATA); - spin_unlock_irqrestore(&btv->gpio_lock,flags); -} -EXPORT_SYMBOL(bttv_gpio_bits); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c deleted file mode 100644 index 614c12018557..000000000000 --- a/drivers/media/video/bttv-i2c.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - - bttv-i2c.c -- all the i2c code is here - - bttv - Bt848 frame grabber driver - - Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) - (c) 1999-2003 Gerd Knorr - - 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 "bttvp.h" -#include -#include -#include - -static struct i2c_algo_bit_data bttv_i2c_algo_bit_template; -static struct i2c_adapter bttv_i2c_adap_sw_template; -static struct i2c_adapter bttv_i2c_adap_hw_template; -static struct i2c_client bttv_i2c_client_template; - -static int attach_inform(struct i2c_client *client); - -static int i2c_debug; -static int i2c_hw; -static int i2c_scan; -module_param(i2c_debug, int, 0644); -module_param(i2c_hw, int, 0444); -module_param(i2c_scan, int, 0444); -MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); - -/* ----------------------------------------------------------------------- */ -/* I2C functions - bitbanging adapter (software i2c) */ - -static void bttv_bit_setscl(void *data, int state) -{ - struct bttv *btv = (struct bttv*)data; - - if (state) - btv->i2c_state |= 0x02; - else - btv->i2c_state &= ~0x02; - btwrite(btv->i2c_state, BT848_I2C); - btread(BT848_I2C); -} - -static void bttv_bit_setsda(void *data, int state) -{ - struct bttv *btv = (struct bttv*)data; - - if (state) - btv->i2c_state |= 0x01; - else - btv->i2c_state &= ~0x01; - btwrite(btv->i2c_state, BT848_I2C); - btread(BT848_I2C); -} - -static int bttv_bit_getscl(void *data) -{ - struct bttv *btv = (struct bttv*)data; - int state; - - state = btread(BT848_I2C) & 0x02 ? 1 : 0; - return state; -} - -static int bttv_bit_getsda(void *data) -{ - struct bttv *btv = (struct bttv*)data; - int state; - - state = btread(BT848_I2C) & 0x01; - return state; -} - -static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = { - .setsda = bttv_bit_setsda, - .setscl = bttv_bit_setscl, - .getsda = bttv_bit_getsda, - .getscl = bttv_bit_getscl, - .udelay = 16, - .mdelay = 10, - .timeout = 200, -}; - -static struct i2c_adapter bttv_i2c_adap_sw_template = { - .owner = THIS_MODULE, - .class = I2C_CLASS_TV_ANALOG, - .name = "bttv", - .id = I2C_HW_B_BT848, - .client_register = attach_inform, -}; - -/* ----------------------------------------------------------------------- */ -/* I2C functions - hardware i2c */ - -static int algo_control(struct i2c_adapter *adapter, - unsigned int cmd, unsigned long arg) -{ - return 0; -} - -static u32 functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL; -} - -static int -bttv_i2c_wait_done(struct bttv *btv) -{ - int rc = 0; - - /* timeout */ - if (wait_event_interruptible_timeout(btv->i2c_queue, - btv->i2c_done, msecs_to_jiffies(85)) == -ERESTARTSYS) - - rc = -EIO; - - if (btv->i2c_done & BT848_INT_RACK) - rc = 1; - btv->i2c_done = 0; - return rc; -} - -#define I2C_HW (BT878_I2C_MODE | BT848_I2C_SYNC |\ - BT848_I2C_SCL | BT848_I2C_SDA) - -static int -bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last) -{ - u32 xmit; - int retval,cnt; - - /* sanity checks */ - if (0 == msg->len) - return -EINVAL; - - /* start, address + first byte */ - xmit = (msg->addr << 25) | (msg->buf[0] << 16) | I2C_HW; - if (msg->len > 1 || !last) - xmit |= BT878_I2C_NOSTOP; - btwrite(xmit, BT848_I2C); - retval = bttv_i2c_wait_done(btv); - if (retval < 0) - goto err; - if (retval == 0) - goto eio; - if (i2c_debug) { - printk(" addr << 1, msg->buf[0]); - if (!(xmit & BT878_I2C_NOSTOP)) - printk(" >\n"); - } - - for (cnt = 1; cnt < msg->len; cnt++ ) { - /* following bytes */ - xmit = (msg->buf[cnt] << 24) | I2C_HW | BT878_I2C_NOSTART; - if (cnt < msg->len-1 || !last) - xmit |= BT878_I2C_NOSTOP; - btwrite(xmit, BT848_I2C); - retval = bttv_i2c_wait_done(btv); - if (retval < 0) - goto err; - if (retval == 0) - goto eio; - if (i2c_debug) { - printk(" %02x", msg->buf[cnt]); - if (!(xmit & BT878_I2C_NOSTOP)) - printk(" >\n"); - } - } - return msg->len; - - eio: - retval = -EIO; - err: - if (i2c_debug) - printk(" ERR: %d\n",retval); - return retval; -} - -static int -bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last) -{ - u32 xmit; - u32 cnt; - int retval; - - for(cnt = 0; cnt < msg->len; cnt++) { - xmit = (msg->addr << 25) | (1 << 24) | I2C_HW; - if (cnt < msg->len-1) - xmit |= BT848_I2C_W3B; - if (cnt < msg->len-1 || !last) - xmit |= BT878_I2C_NOSTOP; - if (cnt) - xmit |= BT878_I2C_NOSTART; - btwrite(xmit, BT848_I2C); - retval = bttv_i2c_wait_done(btv); - if (retval < 0) - goto err; - if (retval == 0) - goto eio; - msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff; - if (i2c_debug) { - if (!(xmit & BT878_I2C_NOSTART)) - printk(" addr << 1) +1); - printk(" =%02x", msg->buf[cnt]); - if (!(xmit & BT878_I2C_NOSTOP)) - printk(" >\n"); - } - } - return msg->len; - - eio: - retval = -EIO; - err: - if (i2c_debug) - printk(" ERR: %d\n",retval); - return retval; -} - -static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) -{ - struct bttv *btv = i2c_get_adapdata(i2c_adap); - int retval = 0; - int i; - - if (i2c_debug) - printk("bt-i2c:"); - btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT); - for (i = 0 ; i < num; i++) { - if (msgs[i].flags & I2C_M_RD) { - /* read */ - retval = bttv_i2c_readbytes(btv, &msgs[i], i+1 == num); - if (retval < 0) - goto err; - } else { - /* write */ - retval = bttv_i2c_sendbytes(btv, &msgs[i], i+1 == num); - if (retval < 0) - goto err; - } - } - return num; - - err: - return retval; -} - -static struct i2c_algorithm bttv_algo = { - .master_xfer = bttv_i2c_xfer, - .algo_control = algo_control, - .functionality = functionality, -}; - -static struct i2c_adapter bttv_i2c_adap_hw_template = { - .owner = THIS_MODULE, - .class = I2C_CLASS_TV_ANALOG, - .name = "bt878", - .id = I2C_HW_B_BT848 /* FIXME */, - .algo = &bttv_algo, - .client_register = attach_inform, -}; - -/* ----------------------------------------------------------------------- */ -/* I2C functions - common stuff */ - -static int attach_inform(struct i2c_client *client) -{ - struct bttv *btv = i2c_get_adapdata(client->adapter); - int addr=ADDR_UNSET; - - - if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) - addr = bttv_tvcards[btv->c.type].tuner_addr; - - - if (bttv_debug) - printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n", - btv->c.nr, client->driver->driver.name, client->addr, - client->name); - if (!client->driver->command) - return 0; - - if (btv->tuner_type != UNSET) { - struct tuner_setup tun_setup; - - if ((addr==ADDR_UNSET) || - (addr==client->addr)) { - - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV | T_RADIO; - tun_setup.type = btv->tuner_type; - tun_setup.addr = addr; - bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); - } - - } - - return 0; -} - -void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) -{ - if (0 != btv->i2c_rc) - return; - i2c_clients_command(&btv->c.i2c_adap, cmd, arg); -} - -static struct i2c_client bttv_i2c_client_template = { - .name = "bttv internal", -}; - - -/* read I2C */ -int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) -{ - unsigned char buffer = 0; - - if (0 != btv->i2c_rc) - return -1; - if (bttv_verbose && NULL != probe_for) - printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ", - btv->c.nr,probe_for,addr); - btv->i2c_client.addr = addr >> 1; - if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) { - if (NULL != probe_for) { - if (bttv_verbose) - printk("not found\n"); - } else - printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n", - btv->c.nr,addr); - return -1; - } - if (bttv_verbose && NULL != probe_for) - printk("found\n"); - return buffer; -} - -/* write I2C */ -int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, - unsigned char b2, int both) -{ - unsigned char buffer[2]; - int bytes = both ? 2 : 1; - - if (0 != btv->i2c_rc) - return -1; - btv->i2c_client.addr = addr >> 1; - buffer[0] = b1; - buffer[1] = b2; - if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) - return -1; - return 0; -} - -/* read EEPROM content */ -void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr) -{ - memset(eedata, 0, 256); - if (0 != btv->i2c_rc) - return; - btv->i2c_client.addr = addr >> 1; - tveeprom_read(&btv->i2c_client, eedata, 256); -} - -static char *i2c_devs[128] = { - [ 0x1c >> 1 ] = "lgdt330x", - [ 0x30 >> 1 ] = "IR (hauppauge)", - [ 0x80 >> 1 ] = "msp34xx", - [ 0x86 >> 1 ] = "tda9887", - [ 0xa0 >> 1 ] = "eeprom", - [ 0xc0 >> 1 ] = "tuner (analog)", - [ 0xc2 >> 1 ] = "tuner (analog)", -}; - -static void do_i2c_scan(char *name, struct i2c_client *c) -{ - unsigned char buf; - int i,rc; - - for (i = 0; i < 128; i++) { - c->addr = i; - rc = i2c_master_recv(c,&buf,0); - if (rc < 0) - continue; - printk("%s: i2c scan: found device @ 0x%x [%s]\n", - name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); - } -} - -/* init + register i2c algo-bit adapter */ -int __devinit init_bttv_i2c(struct bttv *btv) -{ - memcpy(&btv->i2c_client, &bttv_i2c_client_template, - sizeof(bttv_i2c_client_template)); - - if (i2c_hw) - btv->use_i2c_hw = 1; - if (btv->use_i2c_hw) { - /* bt878 */ - memcpy(&btv->c.i2c_adap, &bttv_i2c_adap_hw_template, - sizeof(bttv_i2c_adap_hw_template)); - } else { - /* bt848 */ - memcpy(&btv->c.i2c_adap, &bttv_i2c_adap_sw_template, - sizeof(bttv_i2c_adap_sw_template)); - memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template, - sizeof(bttv_i2c_algo_bit_template)); - btv->i2c_algo.data = btv; - btv->c.i2c_adap.algo_data = &btv->i2c_algo; - } - - btv->c.i2c_adap.dev.parent = &btv->c.pci->dev; - snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name), - "bt%d #%d [%s]", btv->id, btv->c.nr, - btv->use_i2c_hw ? "hw" : "sw"); - - i2c_set_adapdata(&btv->c.i2c_adap, btv); - btv->i2c_client.adapter = &btv->c.i2c_adap; - - if (bttv_tvcards[btv->c.type].no_video) - btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG; - if (bttv_tvcards[btv->c.type].has_dvb) - btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL; - - if (btv->use_i2c_hw) { - btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap); - } else { - bttv_bit_setscl(btv,1); - bttv_bit_setsda(btv,1); - btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap); - } - if (0 == btv->i2c_rc && i2c_scan) - do_i2c_scan(btv->c.name,&btv->i2c_client); - return btv->i2c_rc; -} - -int __devexit fini_bttv_i2c(struct bttv *btv) -{ - if (0 != btv->i2c_rc) - return 0; - - if (btv->use_i2c_hw) { - return i2c_del_adapter(&btv->c.i2c_adap); - } else { - return i2c_bit_del_bus(&btv->c.i2c_adap); - } -} - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c deleted file mode 100644 index 19b564ab0e92..000000000000 --- a/drivers/media/video/bttv-if.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - - bttv-if.c -- old gpio interface to other kernel modules - don't use in new code, will go away in 2.7 - have a look at bttv-gpio.c instead. - - bttv - Bt848 frame grabber driver - - Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) - (c) 1999-2003 Gerd Knorr - - 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 "bttvp.h" - -EXPORT_SYMBOL(bttv_get_cardinfo); -EXPORT_SYMBOL(bttv_get_pcidev); -EXPORT_SYMBOL(bttv_get_id); -EXPORT_SYMBOL(bttv_gpio_enable); -EXPORT_SYMBOL(bttv_read_gpio); -EXPORT_SYMBOL(bttv_write_gpio); -EXPORT_SYMBOL(bttv_get_gpio_queue); -EXPORT_SYMBOL(bttv_i2c_call); - -/* ----------------------------------------------------------------------- */ -/* Exported functions - for other modules which want to access the */ -/* gpio ports (IR for example) */ -/* see bttv.h for comments */ - -int bttv_get_cardinfo(unsigned int card, int *type, unsigned *cardid) -{ - printk("The bttv_* interface is obsolete and will go away,\n" - "please use the new, sysfs based interface instead.\n"); - if (card >= bttv_num) { - return -1; - } - *type = bttvs[card].c.type; - *cardid = bttvs[card].cardid; - return 0; -} - -struct pci_dev* bttv_get_pcidev(unsigned int card) -{ - if (card >= bttv_num) - return NULL; - return bttvs[card].c.pci; -} - -int bttv_get_id(unsigned int card) -{ - printk("The bttv_* interface is obsolete and will go away,\n" - "please use the new, sysfs based interface instead.\n"); - if (card >= bttv_num) { - return -1; - } - return bttvs[card].c.type; -} - - -int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data) -{ - struct bttv *btv; - - if (card >= bttv_num) { - return -EINVAL; - } - - btv = &bttvs[card]; - gpio_inout(mask,data); - if (bttv_gpio) - bttv_gpio_tracking(btv,"extern enable"); - return 0; -} - -int bttv_read_gpio(unsigned int card, unsigned long *data) -{ - struct bttv *btv; - - if (card >= bttv_num) { - return -EINVAL; - } - - btv = &bttvs[card]; - - if(btv->shutdown) { - return -ENODEV; - } - -/* prior setting BT848_GPIO_REG_INP is (probably) not needed - because we set direct input on init */ - *data = gpio_read(); - return 0; -} - -int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data) -{ - struct bttv *btv; - - if (card >= bttv_num) { - return -EINVAL; - } - - btv = &bttvs[card]; - -/* prior setting BT848_GPIO_REG_INP is (probably) not needed - because direct input is set on init */ - gpio_bits(mask,data); - if (bttv_gpio) - bttv_gpio_tracking(btv,"extern write"); - return 0; -} - -wait_queue_head_t* bttv_get_gpio_queue(unsigned int card) -{ - struct bttv *btv; - - if (card >= bttv_num) { - return NULL; - } - - btv = &bttvs[card]; - if (bttvs[card].shutdown) { - return NULL; - } - return &btv->gpioq; -} - -void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg) -{ - if (card >= bttv_num) - return; - bttv_call_i2c_clients(&bttvs[card], cmd, arg); -} - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/bttv-input.c b/drivers/media/video/bttv-input.c deleted file mode 100644 index 69efa0e5174d..000000000000 --- a/drivers/media/video/bttv-input.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * - * Copyright (c) 2003 Gerd Knorr - * Copyright (c) 2003 Pavel Machek - * - * 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 "bttv.h" -#include "bttvp.h" - - -static int debug; -module_param(debug, int, 0644); /* debug level (0,1,2) */ -static int repeat_delay = 500; -module_param(repeat_delay, int, 0644); -static int repeat_period = 33; -module_param(repeat_period, int, 0644); - -#define DEVNAME "bttv-input" - -/* ---------------------------------------------------------------------- */ - -static void ir_handle_key(struct bttv *btv) -{ - struct bttv_ir *ir = btv->remote; - u32 gpio,data; - - /* read gpio value */ - gpio = bttv_gpio_read(&btv->c); - if (ir->polling) { - if (ir->last_gpio == gpio) - return; - ir->last_gpio = gpio; - } - - /* extract data */ - data = ir_extract_bits(gpio, ir->mask_keycode); - dprintk(KERN_INFO DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n", - gpio, data, - ir->polling ? "poll" : "irq", - (gpio & ir->mask_keydown) ? " down" : "", - (gpio & ir->mask_keyup) ? " up" : ""); - - if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || - (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_input_keydown(ir->dev,&ir->ir,data,data); - } else { - ir_input_nokey(ir->dev,&ir->ir); - } - -} - -void bttv_input_irq(struct bttv *btv) -{ - struct bttv_ir *ir = btv->remote; - - if (!ir->polling) - ir_handle_key(btv); -} - -static void bttv_input_timer(unsigned long data) -{ - struct bttv *btv = (struct bttv*)data; - struct bttv_ir *ir = btv->remote; - unsigned long timeout; - - ir_handle_key(btv); - timeout = jiffies + (ir->polling * HZ / 1000); - mod_timer(&ir->timer, timeout); -} - -/* ---------------------------------------------------------------*/ - -static int rc5_remote_gap = 885; -module_param(rc5_remote_gap, int, 0644); -static int rc5_key_timeout = 200; -module_param(rc5_key_timeout, int, 0644); - -#define RC5_START(x) (((x)>>12)&3) -#define RC5_TOGGLE(x) (((x)>>11)&1) -#define RC5_ADDR(x) (((x)>>6)&31) -#define RC5_INSTR(x) ((x)&63) - -/* decode raw bit pattern to RC5 code */ -static u32 rc5_decode(unsigned int code) -{ - unsigned int org_code = code; - unsigned int pair; - unsigned int rc5 = 0; - int i; - - code = (code << 1) | 1; - for (i = 0; i < 14; ++i) { - pair = code & 0x3; - code >>= 2; - - rc5 <<= 1; - switch (pair) { - case 0: - case 2: - break; - case 1: - rc5 |= 1; - break; - case 3: - dprintk(KERN_WARNING "bad code: %x\n", org_code); - return 0; - } - } - dprintk(KERN_WARNING "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " - "instr=%x\n", rc5, org_code, RC5_START(rc5), - RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); - return rc5; -} - -static int bttv_rc5_irq(struct bttv *btv) -{ - struct bttv_ir *ir = btv->remote; - struct timeval tv; - u32 gpio; - u32 gap; - unsigned long current_jiffies, timeout; - - /* read gpio port */ - gpio = bttv_gpio_read(&btv->c); - - /* remote IRQ? */ - if (!(gpio & 0x20)) - return 0; - - /* get time of bit */ - current_jiffies = jiffies; - do_gettimeofday(&tv); - - /* avoid overflow with gap >1s */ - if (tv.tv_sec - ir->base_time.tv_sec > 1) { - gap = 200000; - } else { - gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + - tv.tv_usec - ir->base_time.tv_usec; - } - - /* active code => add bit */ - if (ir->active) { - /* only if in the code (otherwise spurious IRQ or timer - late) */ - if (ir->last_bit < 28) { - ir->last_bit = (gap - rc5_remote_gap / 2) / - rc5_remote_gap; - ir->code |= 1 << ir->last_bit; - } - /* starting new code */ - } else { - ir->active = 1; - ir->code = 0; - ir->base_time = tv; - ir->last_bit = 0; - - timeout = current_jiffies + (500 + 30 * HZ) / 1000; - mod_timer(&ir->timer_end, timeout); - } - - /* toggle GPIO pin 4 to reset the irq */ - bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); - bttv_gpio_write(&btv->c, gpio | (1 << 4)); - return 1; -} - - -static void bttv_rc5_timer_end(unsigned long data) -{ - struct bttv_ir *ir = (struct bttv_ir *)data; - struct timeval tv; - unsigned long current_jiffies, timeout; - u32 gap; - - /* get time */ - current_jiffies = jiffies; - do_gettimeofday(&tv); - - /* avoid overflow with gap >1s */ - if (tv.tv_sec - ir->base_time.tv_sec > 1) { - gap = 200000; - } else { - gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + - tv.tv_usec - ir->base_time.tv_usec; - } - - /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */ - if (gap < 28000) { - dprintk(KERN_WARNING "spurious timer_end\n"); - return; - } - - ir->active = 0; - if (ir->last_bit < 20) { - /* ignore spurious codes (caused by light/other remotes) */ - dprintk(KERN_WARNING "short code: %x\n", ir->code); - } else { - u32 rc5 = rc5_decode(ir->code); - - /* two start bits? */ - if (RC5_START(rc5) != 3) { - dprintk(KERN_WARNING "rc5 start bits invalid: %u\n", RC5_START(rc5)); - - /* right address? */ - } else if (RC5_ADDR(rc5) == 0x0) { - u32 toggle = RC5_TOGGLE(rc5); - u32 instr = RC5_INSTR(rc5); - - /* Good code, decide if repeat/repress */ - if (toggle != RC5_TOGGLE(ir->last_rc5) || - instr != RC5_INSTR(ir->last_rc5)) { - dprintk(KERN_WARNING "instruction %x, toggle %x\n", instr, - toggle); - ir_input_nokey(ir->dev, &ir->ir); - ir_input_keydown(ir->dev, &ir->ir, instr, - instr); - } - - /* Set/reset key-up timer */ - timeout = current_jiffies + (500 + rc5_key_timeout - * HZ) / 1000; - mod_timer(&ir->timer_keyup, timeout); - - /* Save code for repeat test */ - ir->last_rc5 = rc5; - } - } -} - -static void bttv_rc5_timer_keyup(unsigned long data) -{ - struct bttv_ir *ir = (struct bttv_ir *)data; - - dprintk(KERN_DEBUG "key released\n"); - ir_input_nokey(ir->dev, &ir->ir); -} - -/* ---------------------------------------------------------------------- */ - -int bttv_input_init(struct bttv *btv) -{ - struct bttv_ir *ir; - IR_KEYTAB_TYPE *ir_codes = NULL; - struct input_dev *input_dev; - int ir_type = IR_TYPE_OTHER; - - if (!btv->has_remote) - return -ENODEV; - - ir = kzalloc(sizeof(*ir),GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) { - kfree(ir); - input_free_device(input_dev); - return -ENOMEM; - } - memset(ir,0,sizeof(*ir)); - - /* detect & configure */ - switch (btv->c.type) { - case BTTV_BOARD_AVERMEDIA: - case BTTV_BOARD_AVPHONE98: - case BTTV_BOARD_AVERMEDIA98: - ir_codes = ir_codes_avermedia; - ir->mask_keycode = 0xf88000; - ir->mask_keydown = 0x010000; - ir->polling = 50; // ms - break; - - case BTTV_BOARD_AVDVBT_761: - case BTTV_BOARD_AVDVBT_771: - ir_codes = ir_codes_avermedia_dvbt; - ir->mask_keycode = 0x0f00c0; - ir->mask_keydown = 0x000020; - ir->polling = 50; // ms - break; - - case BTTV_BOARD_PXELVWPLTVPAK: - ir_codes = ir_codes_pixelview; - ir->mask_keycode = 0x003e00; - ir->mask_keyup = 0x010000; - ir->polling = 50; // ms - break; - case BTTV_BOARD_PV_BT878P_9B: - case BTTV_BOARD_PV_BT878P_PLUS: - ir_codes = ir_codes_pixelview; - ir->mask_keycode = 0x001f00; - ir->mask_keyup = 0x008000; - ir->polling = 50; // ms - break; - - case BTTV_BOARD_WINFAST2000: - ir_codes = ir_codes_winfast; - ir->mask_keycode = 0x1f8; - break; - case BTTV_BOARD_MAGICTVIEW061: - case BTTV_BOARD_MAGICTVIEW063: - ir_codes = ir_codes_winfast; - ir->mask_keycode = 0x0008e000; - ir->mask_keydown = 0x00200000; - break; - case BTTV_BOARD_APAC_VIEWCOMP: - ir_codes = ir_codes_apac_viewcomp; - ir->mask_keycode = 0x001f00; - ir->mask_keyup = 0x008000; - ir->polling = 50; // ms - break; - case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: - case BTTV_BOARD_CONTVFMI: - ir_codes = ir_codes_pixelview; - ir->mask_keycode = 0x001F00; - ir->mask_keyup = 0x006000; - ir->polling = 50; // ms - break; - case BTTV_BOARD_NEBULA_DIGITV: - ir_codes = ir_codes_nebula; - btv->custom_irq = bttv_rc5_irq; - ir->rc5_gpio = 1; - break; - case BTTV_BOARD_MACHTV_MAGICTV: - ir_codes = ir_codes_apac_viewcomp; - ir->mask_keycode = 0x001F00; - ir->mask_keyup = 0x004000; - ir->polling = 50; /* ms */ - break; - } - if (NULL == ir_codes) { - dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type); - kfree(ir); - input_free_device(input_dev); - return -ENODEV; - } - - if (ir->rc5_gpio) { - u32 gpio; - /* enable remote irq */ - bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4); - gpio = bttv_gpio_read(&btv->c); - bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); - bttv_gpio_write(&btv->c, gpio | (1 << 4)); - } else { - /* init hardware-specific stuff */ - bttv_gpio_inout(&btv->c, ir->mask_keycode | ir->mask_keydown, 0); - } - - /* init input device */ - ir->dev = input_dev; - - snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", - btv->c.type); - snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", - pci_name(btv->c.pci)); - - ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); - input_dev->name = ir->name; - input_dev->phys = ir->phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 1; - if (btv->c.pci->subsystem_vendor) { - input_dev->id.vendor = btv->c.pci->subsystem_vendor; - input_dev->id.product = btv->c.pci->subsystem_device; - } else { - input_dev->id.vendor = btv->c.pci->vendor; - input_dev->id.product = btv->c.pci->device; - } - input_dev->cdev.dev = &btv->c.pci->dev; - - btv->remote = ir; - if (ir->polling) { - init_timer(&ir->timer); - ir->timer.function = bttv_input_timer; - ir->timer.data = (unsigned long)btv; - ir->timer.expires = jiffies + HZ; - add_timer(&ir->timer); - } else if (ir->rc5_gpio) { - /* set timer_end for code completion */ - init_timer(&ir->timer_end); - ir->timer_end.function = bttv_rc5_timer_end; - ir->timer_end.data = (unsigned long)ir; - - init_timer(&ir->timer_keyup); - ir->timer_keyup.function = bttv_rc5_timer_keyup; - ir->timer_keyup.data = (unsigned long)ir; - } - - /* all done */ - input_register_device(btv->remote->dev); - printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys); - - /* the remote isn't as bouncy as a keyboard */ - ir->dev->rep[REP_DELAY] = repeat_delay; - ir->dev->rep[REP_PERIOD] = repeat_period; - - return 0; -} - -void bttv_input_fini(struct bttv *btv) -{ - if (btv->remote == NULL) - return; - - if (btv->remote->polling) { - del_timer_sync(&btv->remote->timer); - flush_scheduled_work(); - } - - - if (btv->remote->rc5_gpio) { - u32 gpio; - - del_timer_sync(&btv->remote->timer_end); - flush_scheduled_work(); - - gpio = bttv_gpio_read(&btv->c); - bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); - } - - input_unregister_device(btv->remote->dev); - kfree(btv->remote); - btv->remote = NULL; -} - - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c deleted file mode 100644 index 16323a5d68ac..000000000000 --- a/drivers/media/video/bttv-risc.c +++ /dev/null @@ -1,795 +0,0 @@ -/* - - bttv-risc.c -- interfaces to other kernel modules - - bttv risc code handling - - memory management - - generation - - (c) 2000-2003 Gerd Knorr - - 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 "bttvp.h" - -#define VCR_HACK_LINES 4 - -/* ---------------------------------------------------------- */ -/* risc code generators */ - -int -bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, - struct scatterlist *sglist, - unsigned int offset, unsigned int bpl, - unsigned int padding, unsigned int lines) -{ - u32 instructions,line,todo; - struct scatterlist *sg; - u32 *rp; - int rc; - - /* estimate risc mem: worst case is one write per page border + - one write per scan line + sync + jump (all 2 dwords). padding - can cause next bpl to start close to a page border. First DMA - region may be smaller than PAGE_SIZE */ - instructions = 1 + ((bpl + padding) * lines) / PAGE_SIZE + lines; - instructions += 2; - if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) - return rc; - - /* sync instruction */ - rp = risc->cpu; - *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(rp++) = cpu_to_le32(0); - - /* scan lines */ - sg = sglist; - for (line = 0; line < lines; line++) { - if ((btv->opt_vcr_hack) && - (line >= (lines - VCR_HACK_LINES))) - continue; - while (offset && offset >= sg_dma_len(sg)) { - offset -= sg_dma_len(sg); - sg++; - } - if (bpl <= sg_dma_len(sg)-offset) { - /* fits into current chunk */ - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| - BT848_RISC_EOL|bpl); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - offset+=bpl; - } else { - /* scanline needs to be splitted */ - todo = bpl; - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| - (sg_dma_len(sg)-offset)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(BT848_RISC_WRITE| - sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); - todo -= sg_dma_len(sg); - sg++; - } - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL| - todo); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); - offset += todo; - } - offset += padding; - } - - /* save pointer to jmp instruction address */ - risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); - return 0; -} - -static int -bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, - struct scatterlist *sglist, - unsigned int yoffset, unsigned int ybpl, - unsigned int ypadding, unsigned int ylines, - unsigned int uoffset, unsigned int voffset, - unsigned int hshift, unsigned int vshift, - unsigned int cpadding) -{ - unsigned int instructions,line,todo,ylen,chroma; - u32 *rp,ri; - struct scatterlist *ysg; - struct scatterlist *usg; - struct scatterlist *vsg; - int topfield = (0 == yoffset); - int rc; - - /* estimate risc mem: worst case is one write per page border + - one write per scan line (5 dwords) - plus sync + jump (2 dwords) */ - instructions = (ybpl * ylines * 2) / PAGE_SIZE + ylines; - instructions += 2; - if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0) - return rc; - - /* sync instruction */ - rp = risc->cpu; - *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); - *(rp++) = cpu_to_le32(0); - - /* scan lines */ - ysg = sglist; - usg = sglist; - vsg = sglist; - for (line = 0; line < ylines; line++) { - if ((btv->opt_vcr_hack) && - (line >= (ylines - VCR_HACK_LINES))) - continue; - switch (vshift) { - case 0: - chroma = 1; - break; - case 1: - if (topfield) - chroma = ((line & 1) == 0); - else - chroma = ((line & 1) == 1); - break; - case 2: - if (topfield) - chroma = ((line & 3) == 0); - else - chroma = ((line & 3) == 2); - break; - default: - chroma = 0; - break; - } - - for (todo = ybpl; todo > 0; todo -= ylen) { - /* go to next sg entry if needed */ - while (yoffset && yoffset >= sg_dma_len(ysg)) { - yoffset -= sg_dma_len(ysg); - ysg++; - } - while (uoffset && uoffset >= sg_dma_len(usg)) { - uoffset -= sg_dma_len(usg); - usg++; - } - while (voffset && voffset >= sg_dma_len(vsg)) { - voffset -= sg_dma_len(vsg); - vsg++; - } - - /* calculate max number of bytes we can write */ - ylen = todo; - if (yoffset + ylen > sg_dma_len(ysg)) - ylen = sg_dma_len(ysg) - yoffset; - if (chroma) { - if (uoffset + (ylen>>hshift) > sg_dma_len(usg)) - ylen = (sg_dma_len(usg) - uoffset) << hshift; - if (voffset + (ylen>>hshift) > sg_dma_len(vsg)) - ylen = (sg_dma_len(vsg) - voffset) << hshift; - ri = BT848_RISC_WRITE123; - } else { - ri = BT848_RISC_WRITE1S23; - } - if (ybpl == todo) - ri |= BT848_RISC_SOL; - if (ylen == todo) - ri |= BT848_RISC_EOL; - - /* write risc instruction */ - *(rp++)=cpu_to_le32(ri | ylen); - *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) | - (ylen >> hshift)); - *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset); - yoffset += ylen; - if (chroma) { - *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset); - uoffset += ylen >> hshift; - *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset); - voffset += ylen >> hshift; - } - } - yoffset += ypadding; - if (chroma) { - uoffset += cpadding; - voffset += cpadding; - } - } - - /* save pointer to jmp instruction address */ - risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); - return 0; -} - -static int -bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, - const struct bttv_format *fmt, struct bttv_overlay *ov, - int skip_even, int skip_odd) -{ - int instructions,rc,line,maxy,start,end,skip,nskips; - struct btcx_skiplist *skips; - u32 *rp,ri,ra; - u32 addr; - - /* skip list for window clipping */ - if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL))) - return -ENOMEM; - - /* estimate risc mem: worst case is (clip+1) * lines instructions - + sync + jump (all 2 dwords) */ - instructions = (ov->nclips + 1) * - ((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height); - instructions += 2; - if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) { - kfree(skips); - return rc; - } - - /* sync instruction */ - rp = risc->cpu; - *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(rp++) = cpu_to_le32(0); - - addr = (unsigned long)btv->fbuf.base; - addr += btv->fbuf.fmt.bytesperline * ov->w.top; - addr += (fmt->depth >> 3) * ov->w.left; - - /* scan lines */ - for (maxy = -1, line = 0; line < ov->w.height; - line++, addr += btv->fbuf.fmt.bytesperline) { - if ((btv->opt_vcr_hack) && - (line >= (ov->w.height - VCR_HACK_LINES))) - continue; - if ((line%2) == 0 && skip_even) - continue; - if ((line%2) == 1 && skip_odd) - continue; - - /* calculate clipping */ - if (line > maxy) - btcx_calc_skips(line, ov->w.width, &maxy, - skips, &nskips, ov->clips, ov->nclips); - else - nskips = 0; - - /* write out risc code */ - for (start = 0, skip = 0; start < ov->w.width; start = end) { - if (skip >= nskips) { - ri = BT848_RISC_WRITE; - end = ov->w.width; - } else if (start < skips[skip].start) { - ri = BT848_RISC_WRITE; - end = skips[skip].start; - } else { - ri = BT848_RISC_SKIP; - end = skips[skip].end; - skip++; - } - if (BT848_RISC_WRITE == ri) - ra = addr + (fmt->depth>>3)*start; - else - ra = 0; - - if (0 == start) - ri |= BT848_RISC_SOL; - if (ov->w.width == end) - ri |= BT848_RISC_EOL; - ri |= (fmt->depth>>3) * (end-start); - - *(rp++)=cpu_to_le32(ri); - if (0 != ra) - *(rp++)=cpu_to_le32(ra); - } - } - - /* save pointer to jmp instruction address */ - risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); - kfree(skips); - return 0; -} - -/* ---------------------------------------------------------- */ - -static void -bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, - int width, int height, int interleaved, int norm) -{ - const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm]; - u32 xsf, sr; - int vdelay; - - int swidth = tvnorm->swidth; - int totalwidth = tvnorm->totalwidth; - int scaledtwidth = tvnorm->scaledtwidth; - - if (bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) { - swidth = 720; - totalwidth = 858; - scaledtwidth = 858; - } - - vdelay = tvnorm->vdelay; - - xsf = (width*scaledtwidth)/swidth; - geo->hscale = ((totalwidth*4096UL)/xsf-4096); - geo->hdelay = tvnorm->hdelayx1; - geo->hdelay = (geo->hdelay*width)/swidth; - geo->hdelay &= 0x3fe; - sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512; - geo->vscale = (0x10000UL-sr) & 0x1fff; - geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) | - ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0); - geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0; - geo->vdelay = vdelay; - geo->width = width; - geo->sheight = tvnorm->sheight; - geo->vtotal = tvnorm->vtotal; - - if (btv->opt_combfilter) { - geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); - geo->comb = (width < 769) ? 1 : 0; - } else { - geo->vtc = 0; - geo->comb = 0; - } -} - -static void -bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) -{ - int off = odd ? 0x80 : 0x00; - - if (geo->comb) - btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); - else - btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); - - btwrite(geo->vtc, BT848_E_VTC+off); - btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off); - btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off); - btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); - btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off); - btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off); - btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off); - btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off); - btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off); - btwrite(geo->crop, BT848_E_CROP+off); - btwrite(geo->vtotal>>8, BT848_VTOTAL_HI); - btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO); -} - -/* ---------------------------------------------------------- */ -/* risc group / risc main loop / dma management */ - -void -bttv_set_dma(struct bttv *btv, int override) -{ - unsigned long cmd; - int capctl; - - btv->cap_ctl = 0; - if (NULL != btv->curr.top) btv->cap_ctl |= 0x02; - if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01; - if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c; - - capctl = 0; - capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */ - capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */ - capctl |= override; - - d2printk(KERN_DEBUG - "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n", - btv->c.nr,capctl,btv->loop_irq, - btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0, - btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, - btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0, - btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); - - cmd = BT848_RISC_JUMP; - if (btv->loop_irq) { - cmd |= BT848_RISC_IRQ; - cmd |= (btv->loop_irq & 0x0f) << 16; - cmd |= (~btv->loop_irq & 0x0f) << 20; - } - if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) { - mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT); - } else { - del_timer(&btv->timeout); - } - btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); - - btaor(capctl, ~0x0f, BT848_CAP_CTL); - if (capctl) { - if (btv->dma_on) - return; - btwrite(btv->main.dma, BT848_RISC_STRT_ADD); - btor(3, BT848_GPIO_DMA_CTL); - btv->dma_on = 1; - } else { - if (!btv->dma_on) - return; - btand(~3, BT848_GPIO_DMA_CTL); - btv->dma_on = 0; - } - return; -} - -int -bttv_risc_init_main(struct bttv *btv) -{ - int rc; - - if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0) - return rc; - dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n", - btv->c.nr,(unsigned long long)btv->main.dma); - - btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | - BT848_FIFO_STATUS_VRE); - btv->main.cpu[1] = cpu_to_le32(0); - btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP); - btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2)); - - /* top field */ - btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP); - btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2)); - btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP); - btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2)); - - btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | - BT848_FIFO_STATUS_VRO); - btv->main.cpu[9] = cpu_to_le32(0); - - /* bottom field */ - btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP); - btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2)); - btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP); - btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2)); - - /* jump back to top field */ - btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP); - btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2)); - - return 0; -} - -int -bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, - int irqflags) -{ - unsigned long cmd; - unsigned long next = btv->main.dma + ((slot+2) << 2); - - if (NULL == risc) { - d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n", - btv->c.nr,risc,slot); - btv->main.cpu[slot+1] = cpu_to_le32(next); - } else { - d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n", - btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags); - cmd = BT848_RISC_JUMP; - if (irqflags) { - cmd |= BT848_RISC_IRQ; - cmd |= (irqflags & 0x0f) << 16; - cmd |= (~irqflags & 0x0f) << 20; - } - risc->jmp[0] = cpu_to_le32(cmd); - risc->jmp[1] = cpu_to_le32(next); - btv->main.cpu[slot+1] = cpu_to_le32(risc->dma); - } - return 0; -} - -void -bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf) -{ - BUG_ON(in_interrupt()); - videobuf_waiton(&buf->vb,0,0); - videobuf_dma_unmap(q, &buf->vb.dma); - videobuf_dma_free(&buf->vb.dma); - btcx_riscmem_free(btv->c.pci,&buf->bottom); - btcx_riscmem_free(btv->c.pci,&buf->top); - buf->vb.state = STATE_NEEDS_INIT; -} - -int -bttv_buffer_activate_vbi(struct bttv *btv, - struct bttv_buffer *vbi) -{ - /* vbi capture */ - if (vbi) { - vbi->vb.state = STATE_ACTIVE; - list_del(&vbi->vb.queue); - bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top, 0); - bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4); - } else { - bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0); - bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0); - } - return 0; -} - -int -bttv_buffer_activate_video(struct bttv *btv, - struct bttv_buffer_set *set) -{ - /* video capture */ - if (NULL != set->top && NULL != set->bottom) { - if (set->top == set->bottom) { - set->top->vb.state = STATE_ACTIVE; - if (set->top->vb.queue.next) - list_del(&set->top->vb.queue); - } else { - set->top->vb.state = STATE_ACTIVE; - set->bottom->vb.state = STATE_ACTIVE; - if (set->top->vb.queue.next) - list_del(&set->top->vb.queue); - if (set->bottom->vb.queue.next) - list_del(&set->bottom->vb.queue); - } - bttv_apply_geo(btv, &set->top->geo, 1); - bttv_apply_geo(btv, &set->bottom->geo,0); - bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, - set->top_irq); - bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, - set->frame_irq); - btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f), - ~0xff, BT848_COLOR_FMT); - btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05), - ~0x0f, BT848_COLOR_CTL); - } else if (NULL != set->top) { - set->top->vb.state = STATE_ACTIVE; - if (set->top->vb.queue.next) - list_del(&set->top->vb.queue); - bttv_apply_geo(btv, &set->top->geo,1); - bttv_apply_geo(btv, &set->top->geo,0); - bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, - set->frame_irq); - bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0); - btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT); - btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL); - } else if (NULL != set->bottom) { - set->bottom->vb.state = STATE_ACTIVE; - if (set->bottom->vb.queue.next) - list_del(&set->bottom->vb.queue); - bttv_apply_geo(btv, &set->bottom->geo,1); - bttv_apply_geo(btv, &set->bottom->geo,0); - bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); - bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, - set->frame_irq); - btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT); - btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL); - } else { - bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); - bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0); - } - return 0; -} - -/* ---------------------------------------------------------- */ - -/* calculate geometry, build risc code */ -int -bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) -{ - const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm; - - dprintk(KERN_DEBUG - "bttv%d: buffer field: %s format: %s size: %dx%d\n", - btv->c.nr, v4l2_field_names[buf->vb.field], - buf->fmt->name, buf->vb.width, buf->vb.height); - - /* packed pixel modes */ - if (buf->fmt->flags & FORMAT_FLAGS_PACKED) { - int bpl = (buf->fmt->depth >> 3) * buf->vb.width; - int bpf = bpl * (buf->vb.height >> 1); - - bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height, - V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm); - - switch (buf->vb.field) { - case V4L2_FIELD_TOP: - bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, - 0,bpl,0,buf->vb.height); - break; - case V4L2_FIELD_BOTTOM: - bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, - 0,bpl,0,buf->vb.height); - break; - case V4L2_FIELD_INTERLACED: - bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, - 0,bpl,bpl,buf->vb.height >> 1); - bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, - bpl,bpl,bpl,buf->vb.height >> 1); - break; - case V4L2_FIELD_SEQ_TB: - bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, - 0,bpl,0,buf->vb.height >> 1); - bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, - bpf,bpl,0,buf->vb.height >> 1); - break; - default: - BUG(); - } - } - - /* planar modes */ - if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) { - int uoffset, voffset; - int ypadding, cpadding, lines; - - /* calculate chroma offsets */ - uoffset = buf->vb.width * buf->vb.height; - voffset = buf->vb.width * buf->vb.height; - if (buf->fmt->flags & FORMAT_FLAGS_CrCb) { - /* Y-Cr-Cb plane order */ - uoffset >>= buf->fmt->hshift; - uoffset >>= buf->fmt->vshift; - uoffset += voffset; - } else { - /* Y-Cb-Cr plane order */ - voffset >>= buf->fmt->hshift; - voffset >>= buf->fmt->vshift; - voffset += uoffset; - } - - switch (buf->vb.field) { - case V4L2_FIELD_TOP: - bttv_calc_geo(btv,&buf->geo,buf->vb.width, - buf->vb.height,0,buf->tvnorm); - bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist, - 0,buf->vb.width,0,buf->vb.height, - uoffset,voffset,buf->fmt->hshift, - buf->fmt->vshift,0); - break; - case V4L2_FIELD_BOTTOM: - bttv_calc_geo(btv,&buf->geo,buf->vb.width, - buf->vb.height,0,buf->tvnorm); - bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist, - 0,buf->vb.width,0,buf->vb.height, - uoffset,voffset,buf->fmt->hshift, - buf->fmt->vshift,0); - break; - case V4L2_FIELD_INTERLACED: - bttv_calc_geo(btv,&buf->geo,buf->vb.width, - buf->vb.height,1,buf->tvnorm); - lines = buf->vb.height >> 1; - ypadding = buf->vb.width; - cpadding = buf->vb.width >> buf->fmt->hshift; - bttv_risc_planar(btv,&buf->top, - buf->vb.dma.sglist, - 0,buf->vb.width,ypadding,lines, - uoffset,voffset, - buf->fmt->hshift, - buf->fmt->vshift, - cpadding); - bttv_risc_planar(btv,&buf->bottom, - buf->vb.dma.sglist, - ypadding,buf->vb.width,ypadding,lines, - uoffset+cpadding, - voffset+cpadding, - buf->fmt->hshift, - buf->fmt->vshift, - cpadding); - break; - case V4L2_FIELD_SEQ_TB: - bttv_calc_geo(btv,&buf->geo,buf->vb.width, - buf->vb.height,1,buf->tvnorm); - lines = buf->vb.height >> 1; - ypadding = buf->vb.width; - cpadding = buf->vb.width >> buf->fmt->hshift; - bttv_risc_planar(btv,&buf->top, - buf->vb.dma.sglist, - 0,buf->vb.width,0,lines, - uoffset >> 1, - voffset >> 1, - buf->fmt->hshift, - buf->fmt->vshift, - 0); - bttv_risc_planar(btv,&buf->bottom, - buf->vb.dma.sglist, - lines * ypadding,buf->vb.width,0,lines, - lines * ypadding + (uoffset >> 1), - lines * ypadding + (voffset >> 1), - buf->fmt->hshift, - buf->fmt->vshift, - 0); - break; - default: - BUG(); - } - } - - /* raw data */ - if (buf->fmt->flags & FORMAT_FLAGS_RAW) { - /* build risc code */ - buf->vb.field = V4L2_FIELD_SEQ_TB; - bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight, - 1,buf->tvnorm); - bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist, - 0, RAW_BPL, 0, RAW_LINES); - bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist, - buf->vb.size/2 , RAW_BPL, 0, RAW_LINES); - } - - /* copy format info */ - buf->btformat = buf->fmt->btformat; - buf->btswap = buf->fmt->btswap; - return 0; -} - -/* ---------------------------------------------------------- */ - -/* calculate geometry, build risc code */ -int -bttv_overlay_risc(struct bttv *btv, - struct bttv_overlay *ov, - const struct bttv_format *fmt, - struct bttv_buffer *buf) -{ - /* check interleave, bottom+top fields */ - dprintk(KERN_DEBUG - "bttv%d: overlay fields: %s format: %s size: %dx%d\n", - btv->c.nr, v4l2_field_names[buf->vb.field], - fmt->name,ov->w.width,ov->w.height); - - /* calculate geometry */ - bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height, - V4L2_FIELD_HAS_BOTH(ov->field), ov->tvnorm); - - /* build risc code */ - switch (ov->field) { - case V4L2_FIELD_TOP: - bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0); - break; - case V4L2_FIELD_BOTTOM: - bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0); - break; - case V4L2_FIELD_INTERLACED: - bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 1); - bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0); - break; - default: - BUG(); - } - - /* copy format info */ - buf->btformat = fmt->btformat; - buf->btswap = fmt->btswap; - buf->vb.field = ov->field; - return 0; -} - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c deleted file mode 100644 index e20ff238e409..000000000000 --- a/drivers/media/video/bttv-vbi.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - - bttv - Bt848 frame grabber driver - vbi interface - - (c) 2002 Gerd Knorr - - 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 -#include "bttvp.h" - -/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate: - bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC - HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge - of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */ -#define VBI_OFFSET ((64 + 0) * 2) - -#define VBI_DEFLINES 16 -#define VBI_MAXLINES 32 - -static unsigned int vbibufs = 4; -static unsigned int vbi_debug = 0; - -module_param(vbibufs, int, 0444); -module_param(vbi_debug, int, 0644); -MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32, default 4"); -MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)"); - -#ifdef dprintk -# undef dprintk -#endif -#define dprintk(fmt, arg...) if (vbi_debug) \ - printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg) - -/* ----------------------------------------------------------------------- */ -/* vbi risc code + mm */ - -static int -vbi_buffer_risc(struct bttv *btv, struct bttv_buffer *buf, int lines) -{ - int bpl = 2048; - - bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist, - 0, bpl-4, 4, lines); - bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist, - lines * bpl, bpl-4, 4, lines); - return 0; -} - -static int vbi_buffer_setup(struct videobuf_queue *q, - unsigned int *count, unsigned int *size) -{ - struct bttv_fh *fh = q->priv_data; - struct bttv *btv = fh->btv; - - if (0 == *count) - *count = vbibufs; - *size = fh->lines * 2 * 2048; - dprintk("setup: lines=%d\n",fh->lines); - return 0; -} - -static int vbi_buffer_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct bttv_fh *fh = q->priv_data; - struct bttv *btv = fh->btv; - struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); - int rc; - - buf->vb.size = fh->lines * 2 * 2048; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - if (STATE_NEEDS_INIT == buf->vb.state) { - if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL))) - goto fail; - if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines))) - goto fail; - } - buf->vb.state = STATE_PREPARED; - buf->vb.field = field; - dprintk("buf prepare %p: top=%p bottom=%p field=%s\n", - vb, &buf->top, &buf->bottom, - v4l2_field_names[buf->vb.field]); - return 0; - - fail: - bttv_dma_free(q,btv,buf); - return rc; -} - -static void -vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct bttv_fh *fh = q->priv_data; - struct bttv *btv = fh->btv; - struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); - - dprintk("queue %p\n",vb); - buf->vb.state = STATE_QUEUED; - list_add_tail(&buf->vb.queue,&btv->vcapture); - if (NULL == btv->cvbi) { - fh->btv->loop_irq |= 4; - bttv_set_dma(btv,0x0c); - } -} - -static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct bttv_fh *fh = q->priv_data; - struct bttv *btv = fh->btv; - struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); - - dprintk("free %p\n",vb); - bttv_dma_free(&fh->cap,fh->btv,buf); -} - -struct videobuf_queue_ops bttv_vbi_qops = { - .buf_setup = vbi_buffer_setup, - .buf_prepare = vbi_buffer_prepare, - .buf_queue = vbi_buffer_queue, - .buf_release = vbi_buffer_release, -}; - -/* ----------------------------------------------------------------------- */ - -void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines) -{ - int vdelay; - - if (lines < 1) - lines = 1; - if (lines > VBI_MAXLINES) - lines = VBI_MAXLINES; - fh->lines = lines; - - vdelay = btread(BT848_E_VDELAY_LO); - if (vdelay < lines*2) { - vdelay = lines*2; - btwrite(vdelay,BT848_E_VDELAY_LO); - btwrite(vdelay,BT848_O_VDELAY_LO); - } -} - -void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f) -{ - const struct bttv_tvnorm *tvnorm; - s64 count0,count1,count; - - tvnorm = &bttv_tvnorms[fh->btv->tvnorm]; - f->type = V4L2_BUF_TYPE_VBI_CAPTURE; - f->fmt.vbi.sampling_rate = tvnorm->Fsc; - f->fmt.vbi.samples_per_line = 2048; - f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - f->fmt.vbi.offset = VBI_OFFSET; - f->fmt.vbi.flags = 0; - - /* s64 to prevent overflow. */ - count0 = (s64) f->fmt.vbi.start[0] + f->fmt.vbi.count[0] - - tvnorm->vbistart[0]; - count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1] - - tvnorm->vbistart[1]; - count = clamp (max (count0, count1), 1LL, (s64) VBI_MAXLINES); - - f->fmt.vbi.start[0] = tvnorm->vbistart[0]; - f->fmt.vbi.start[1] = tvnorm->vbistart[1]; - f->fmt.vbi.count[0] = count; - f->fmt.vbi.count[1] = count; - - f->fmt.vbi.reserved[0] = 0; - f->fmt.vbi.reserved[1] = 0; -} - -void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f) -{ - const struct bttv_tvnorm *tvnorm; - - tvnorm = &bttv_tvnorms[fh->btv->tvnorm]; - memset(f,0,sizeof(*f)); - f->type = V4L2_BUF_TYPE_VBI_CAPTURE; - f->fmt.vbi.sampling_rate = tvnorm->Fsc; - f->fmt.vbi.samples_per_line = 2048; - f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - f->fmt.vbi.offset = VBI_OFFSET; - f->fmt.vbi.start[0] = tvnorm->vbistart[0]; - f->fmt.vbi.start[1] = tvnorm->vbistart[1]; - f->fmt.vbi.count[0] = fh->lines; - f->fmt.vbi.count[1] = fh->lines; - f->fmt.vbi.flags = 0; -} - -/* ----------------------------------------------------------------------- */ -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h deleted file mode 100644 index 9908c8e0c951..000000000000 --- a/drivers/media/video/bttv.h +++ /dev/null @@ -1,407 +0,0 @@ -/* - * - * bttv - Bt848 frame grabber driver - * - * card ID's and external interfaces of the bttv driver - * basically stuff needed by other drivers (i2c, lirc, ...) - * and is supported not to change much over time. - * - * Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) - * (c) 1999,2000 Gerd Knorr - * - */ - -#ifndef _BTTV_H_ -#define _BTTV_H_ - -#include -#include -#include -#include - -/* ---------------------------------------------------------- */ -/* exported by bttv-cards.c */ - -#define BTTV_BOARD_UNKNOWN 0x00 -#define BTTV_BOARD_MIRO 0x01 -#define BTTV_BOARD_HAUPPAUGE 0x02 -#define BTTV_BOARD_STB 0x03 -#define BTTV_BOARD_INTEL 0x04 -#define BTTV_BOARD_DIAMOND 0x05 -#define BTTV_BOARD_AVERMEDIA 0x06 -#define BTTV_BOARD_MATRIX_VISION 0x07 -#define BTTV_BOARD_FLYVIDEO 0x08 -#define BTTV_BOARD_TURBOTV 0x09 -#define BTTV_BOARD_HAUPPAUGE878 0x0a -#define BTTV_BOARD_MIROPRO 0x0b -#define BTTV_BOARD_ADSTECH_TV 0x0c -#define BTTV_BOARD_AVERMEDIA98 0x0d -#define BTTV_BOARD_VHX 0x0e -#define BTTV_BOARD_ZOLTRIX 0x0f -#define BTTV_BOARD_PIXVIEWPLAYTV 0x10 -#define BTTV_BOARD_WINVIEW_601 0x11 -#define BTTV_BOARD_AVEC_INTERCAP 0x12 -#define BTTV_BOARD_LIFE_FLYKIT 0x13 -#define BTTV_BOARD_CEI_RAFFLES 0x14 -#define BTTV_BOARD_CONFERENCETV 0x15 -#define BTTV_BOARD_PHOEBE_TVMAS 0x16 -#define BTTV_BOARD_MODTEC_205 0x17 -#define BTTV_BOARD_MAGICTVIEW061 0x18 -#define BTTV_BOARD_VOBIS_BOOSTAR 0x19 -#define BTTV_BOARD_HAUPPAUG_WCAM 0x1a -#define BTTV_BOARD_MAXI 0x1b -#define BTTV_BOARD_TERRATV 0x1c -#define BTTV_BOARD_PXC200 0x1d -#define BTTV_BOARD_FLYVIDEO_98 0x1e -#define BTTV_BOARD_IPROTV 0x1f -#define BTTV_BOARD_INTEL_C_S_PCI 0x20 -#define BTTV_BOARD_TERRATVALUE 0x21 -#define BTTV_BOARD_WINFAST2000 0x22 -#define BTTV_BOARD_CHRONOS_VS2 0x23 -#define BTTV_BOARD_TYPHOON_TVIEW 0x24 -#define BTTV_BOARD_PXELVWPLTVPRO 0x25 -#define BTTV_BOARD_MAGICTVIEW063 0x26 -#define BTTV_BOARD_PINNACLE 0x27 -#define BTTV_BOARD_STB2 0x28 -#define BTTV_BOARD_AVPHONE98 0x29 -#define BTTV_BOARD_PV951 0x2a -#define BTTV_BOARD_ONAIR_TV 0x2b -#define BTTV_BOARD_SIGMA_TVII_FM 0x2c -#define BTTV_BOARD_MATRIX_VISION2 0x2d -#define BTTV_BOARD_ZOLTRIX_GENIE 0x2e -#define BTTV_BOARD_TERRATVRADIO 0x2f -#define BTTV_BOARD_DYNALINK 0x30 -#define BTTV_BOARD_GVBCTV3PCI 0x31 -#define BTTV_BOARD_PXELVWPLTVPAK 0x32 -#define BTTV_BOARD_EAGLE 0x33 -#define BTTV_BOARD_PINNACLEPRO 0x34 -#define BTTV_BOARD_TVIEW_RDS_FM 0x35 -#define BTTV_BOARD_LIFETEC_9415 0x36 -#define BTTV_BOARD_BESTBUY_EASYTV 0x37 -#define BTTV_BOARD_FLYVIDEO_98FM 0x38 -#define BTTV_BOARD_GRANDTEC 0x39 -#define BTTV_BOARD_ASKEY_CPH060 0x3a -#define BTTV_BOARD_ASKEY_CPH03X 0x3b -#define BTTV_BOARD_MM100PCTV 0x3c -#define BTTV_BOARD_GMV1 0x3d -#define BTTV_BOARD_BESTBUY_EASYTV2 0x3e -#define BTTV_BOARD_ATI_TVWONDER 0x3f -#define BTTV_BOARD_ATI_TVWONDERVE 0x40 -#define BTTV_BOARD_FLYVIDEO2000 0x41 -#define BTTV_BOARD_TERRATVALUER 0x42 -#define BTTV_BOARD_GVBCTV4PCI 0x43 -#define BTTV_BOARD_VOODOOTV_FM 0x44 -#define BTTV_BOARD_AIMMS 0x45 -#define BTTV_BOARD_PV_BT878P_PLUS 0x46 -#define BTTV_BOARD_FLYVIDEO98EZ 0x47 -#define BTTV_BOARD_PV_BT878P_9B 0x48 -#define BTTV_BOARD_SENSORAY311 0x49 -#define BTTV_BOARD_RV605 0x4a -#define BTTV_BOARD_POWERCLR_MTV878 0x4b -#define BTTV_BOARD_WINDVR 0x4c -#define BTTV_BOARD_GRANDTEC_MULTI 0x4d -#define BTTV_BOARD_KWORLD 0x4e -#define BTTV_BOARD_DSP_TCVIDEO 0x4f -#define BTTV_BOARD_HAUPPAUGEPVR 0x50 -#define BTTV_BOARD_GVBCTV5PCI 0x51 -#define BTTV_BOARD_OSPREY1x0 0x52 -#define BTTV_BOARD_OSPREY1x0_848 0x53 -#define BTTV_BOARD_OSPREY101_848 0x54 -#define BTTV_BOARD_OSPREY1x1 0x55 -#define BTTV_BOARD_OSPREY1x1_SVID 0x56 -#define BTTV_BOARD_OSPREY2xx 0x57 -#define BTTV_BOARD_OSPREY2x0_SVID 0x58 -#define BTTV_BOARD_OSPREY2x0 0x59 -#define BTTV_BOARD_OSPREY500 0x5a -#define BTTV_BOARD_OSPREY540 0x5b -#define BTTV_BOARD_OSPREY2000 0x5c -#define BTTV_BOARD_IDS_EAGLE 0x5d -#define BTTV_BOARD_PINNACLESAT 0x5e -#define BTTV_BOARD_FORMAC_PROTV 0x5f -#define BTTV_BOARD_MACHTV 0x60 -#define BTTV_BOARD_EURESYS_PICOLO 0x61 -#define BTTV_BOARD_PV150 0x62 -#define BTTV_BOARD_AD_TVK503 0x63 -#define BTTV_BOARD_HERCULES_SM_TV 0x64 -#define BTTV_BOARD_PACETV 0x65 -#define BTTV_BOARD_IVC200 0x66 -#define BTTV_BOARD_XGUARD 0x67 -#define BTTV_BOARD_NEBULA_DIGITV 0x68 -#define BTTV_BOARD_PV143 0x69 -#define BTTV_BOARD_VD009X1_MINIDIN 0x6a -#define BTTV_BOARD_VD009X1_COMBI 0x6b -#define BTTV_BOARD_VD009_MINIDIN 0x6c -#define BTTV_BOARD_VD009_COMBI 0x6d -#define BTTV_BOARD_IVC100 0x6e -#define BTTV_BOARD_IVC120 0x6f -#define BTTV_BOARD_PC_HDTV 0x70 -#define BTTV_BOARD_TWINHAN_DST 0x71 -#define BTTV_BOARD_WINFASTVC100 0x72 -#define BTTV_BOARD_TEV560 0x73 -#define BTTV_BOARD_SIMUS_GVC1100 0x74 -#define BTTV_BOARD_NGSTV_PLUS 0x75 -#define BTTV_BOARD_LMLBT4 0x76 -#define BTTV_BOARD_TEKRAM_M205 0x77 -#define BTTV_BOARD_CONTVFMI 0x78 -#define BTTV_BOARD_PICOLO_TETRA_CHIP 0x79 -#define BTTV_BOARD_SPIRIT_TV 0x7a -#define BTTV_BOARD_AVDVBT_771 0x7b -#define BTTV_BOARD_AVDVBT_761 0x7c -#define BTTV_BOARD_MATRIX_VISIONSQ 0x7d -#define BTTV_BOARD_MATRIX_VISIONSLC 0x7e -#define BTTV_BOARD_APAC_VIEWCOMP 0x7f -#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 -#define BTTV_BOARD_VGEAR_MYVCD 0x81 -#define BTTV_BOARD_SUPER_TV 0x82 -#define BTTV_BOARD_TIBET_CS16 0x83 -#define BTTV_BOARD_KODICOM_4400R 0x84 -#define BTTV_BOARD_KODICOM_4400R_SL 0x85 -#define BTTV_BOARD_ADLINK_RTV24 0x86 -#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 -#define BTTV_BOARD_ACORP_Y878F 0x88 -#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 -#define BTTV_BOARD_PV_BT878P_2E 0x8a -#define BTTV_BOARD_PV_M4900 0x8b -#define BTTV_BOARD_OSPREY440 0x8c -#define BTTV_BOARD_ASOUND_SKYEYE 0x8d -#define BTTV_BOARD_SABRENT_TVFM 0x8e -#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f -#define BTTV_BOARD_MACHTV_MAGICTV 0x90 - -/* i2c address list */ -#define I2C_TSA5522 0xc2 -#define I2C_TDA7432 0x8a -#define I2C_BT832_ALT1 0x88 -#define I2C_BT832_ALT2 0x8a // alternate setting -#define I2C_TDA8425 0x82 -#define I2C_TDA9840 0x84 -#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */ -#define I2C_TDA9874 0xb0 /* also used by 9875 */ -#define I2C_TDA9875 0xb0 -#define I2C_HAUPEE 0xa0 -#define I2C_STBEE 0xae -#define I2C_VHX 0xc0 -#define I2C_MSP3400 0x80 -#define I2C_MSP3400_ALT 0x88 -#define I2C_TEA6300 0x80 /* also used by 6320 */ -#define I2C_DPL3518 0x84 -#define I2C_TDA9887 0x86 - -/* more card-specific defines */ -#define PT2254_L_CHANNEL 0x10 -#define PT2254_R_CHANNEL 0x08 -#define PT2254_DBS_IN_2 0x400 -#define PT2254_DBS_IN_10 0x20000 -#define WINVIEW_PT2254_CLK 0x40 -#define WINVIEW_PT2254_DATA 0x20 -#define WINVIEW_PT2254_STROBE 0x80 - -/* digital_mode */ -#define DIGITAL_MODE_VIDEO 1 -#define DIGITAL_MODE_CAMERA 2 - -struct bttv_core { - /* device structs */ - struct pci_dev *pci; - struct i2c_adapter i2c_adap; - struct list_head subs; /* struct bttv_sub_device */ - - /* device config */ - unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ - unsigned int type; /* card type (pointer into tvcards[]) */ - char name[8]; /* dev name */ -}; - -struct bttv; - - -struct bttv_ir { - struct input_dev *dev; - struct ir_input_state ir; - char name[32]; - char phys[32]; - - /* Usual gpio signalling */ - - u32 mask_keycode; - u32 mask_keydown; - u32 mask_keyup; - u32 polling; - u32 last_gpio; - struct work_struct work; - struct timer_list timer; - - /* RC5 gpio */ - u32 rc5_gpio; - struct timer_list timer_end; /* timer_end for code completion */ - struct timer_list timer_keyup; /* timer_end for key release */ - u32 last_rc5; /* last good rc5 code */ - u32 last_bit; /* last raw bit seen */ - u32 code; /* raw code under construction */ - struct timeval base_time; /* time of last seen code */ - int active; /* building raw code */ -}; - -struct tvcard -{ - char *name; - unsigned int video_inputs; - unsigned int audio_inputs; - unsigned int tuner; - unsigned int svhs; - unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO - u32 gpiomask; - u32 muxsel[16]; - u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ - u32 gpiomask2; /* GPIO MUX mask */ - - /* i2c audio flags */ - unsigned int no_msp34xx:1; - unsigned int no_tda9875:1; - unsigned int no_tda7432:1; - unsigned int needs_tvaudio:1; - unsigned int msp34xx_alt:1; - - /* flag: video pci function is unused */ - unsigned int no_video:1; - unsigned int has_dvb:1; - unsigned int has_remote:1; - unsigned int no_gpioirq:1; - - /* other settings */ - unsigned int pll; -#define PLL_NONE 0 -#define PLL_28 1 -#define PLL_35 2 - - unsigned int tuner_type; - unsigned int tuner_addr; - unsigned int radio_addr; - - unsigned int has_radio; - void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); - void (*muxsel_hook)(struct bttv *btv, unsigned int input); -}; - -extern struct tvcard bttv_tvcards[]; - -/* identification / initialization of the card */ -extern void bttv_idcard(struct bttv *btv); -extern void bttv_init_card1(struct bttv *btv); -extern void bttv_init_card2(struct bttv *btv); - -/* card-specific funtions */ -extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); -extern void bttv_tda9880_setnorm(struct bttv *btv, int norm); - -/* extra tweaks for some chipsets */ -extern void bttv_check_chipset(void); -extern int bttv_handle_chipset(struct bttv *btv); - -/* ---------------------------------------------------------- */ -/* exported by bttv-if.c */ - -/* this obsolete -- please use the sysfs-based - interface below for new code */ - -/* returns card type + card ID (for bt878-based ones) - for possible values see lines below beginning with #define BTTV_BOARD_UNKNOWN - returns negative value if error occurred -*/ -extern int bttv_get_cardinfo(unsigned int card, int *type, - unsigned int *cardid); -extern struct pci_dev* bttv_get_pcidev(unsigned int card); - -/* obsolete, use bttv_get_cardinfo instead */ -extern int bttv_get_id(unsigned int card); - -/* sets GPOE register (BT848_GPIO_OUT_EN) to new value: - data | (current_GPOE_value & ~mask) - returns negative value if error occurred -*/ -extern int bttv_gpio_enable(unsigned int card, - unsigned long mask, unsigned long data); - -/* fills data with GPDATA register contents - returns negative value if error occurred -*/ -extern int bttv_read_gpio(unsigned int card, unsigned long *data); - -/* sets GPDATA register to new value: - (data & mask) | (current_GPDATA_value & ~mask) - returns negative value if error occurred -*/ -extern int bttv_write_gpio(unsigned int card, - unsigned long mask, unsigned long data); - -/* returns pointer to task queue which can be used as parameter to - interruptible_sleep_on - in interrupt handler if BT848_INT_GPINT bit is set - this queue is activated - (wake_up_interruptible) and following call to the function bttv_read_gpio - should return new value of GPDATA, - returns NULL value if error occurred or queue is not available - WARNING: because there is no buffer for GPIO data, one MUST - process data ASAP -*/ -extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card); - -/* call i2c clients -*/ -extern void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg); - - - -/* ---------------------------------------------------------- */ -/* sysfs/driver-moded based gpio access interface */ - - -struct bttv_sub_device { - struct device dev; - struct bttv_core *core; - struct list_head list; -}; -#define to_bttv_sub_dev(x) container_of((x), struct bttv_sub_device, dev) - -struct bttv_sub_driver { - struct device_driver drv; - char wanted[BUS_ID_SIZE]; - int (*probe)(struct bttv_sub_device *sub); - void (*remove)(struct bttv_sub_device *sub); - void (*gpio_irq)(struct bttv_sub_device *sub); -}; -#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) - -int bttv_sub_register(struct bttv_sub_driver *drv, char *wanted); -int bttv_sub_unregister(struct bttv_sub_driver *drv); - -/* gpio access functions */ -void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits); -u32 bttv_gpio_read(struct bttv_core *core); -void bttv_gpio_write(struct bttv_core *core, u32 value); -void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits); - -#define gpio_inout(mask,bits) bttv_gpio_inout(&btv->c, mask, bits) -#define gpio_read() bttv_gpio_read(&btv->c) -#define gpio_write(value) bttv_gpio_write(&btv->c, value) -#define gpio_bits(mask,bits) bttv_gpio_bits(&btv->c, mask, bits) - - -/* ---------------------------------------------------------- */ -/* i2c */ - -extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); -extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for); -extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, - unsigned char b2, int both); -extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr); - -extern int bttv_input_init(struct bttv *dev); -extern void bttv_input_fini(struct bttv *dev); -extern void bttv_input_irq(struct bttv *dev); - -#endif /* _BTTV_H_ */ -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h deleted file mode 100644 index 12223a203960..000000000000 --- a/drivers/media/video/bttvp.h +++ /dev/null @@ -1,411 +0,0 @@ -/* - - bttv - Bt848 frame grabber driver - - bttv's *private* header file -- nobody other than bttv itself - should ever include this file. - - (c) 2000-2002 Gerd Knorr - - 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. -*/ - -#ifndef _BTTVP_H_ -#define _BTTVP_H_ - -#include -#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -#include "bt848.h" -#include "bttv.h" -#include "btcx-risc.h" - -#ifdef __KERNEL__ - -#define FORMAT_FLAGS_DITHER 0x01 -#define FORMAT_FLAGS_PACKED 0x02 -#define FORMAT_FLAGS_PLANAR 0x04 -#define FORMAT_FLAGS_RAW 0x08 -#define FORMAT_FLAGS_CrCb 0x10 - -#define RISC_SLOT_O_VBI 4 -#define RISC_SLOT_O_FIELD 6 -#define RISC_SLOT_E_VBI 10 -#define RISC_SLOT_E_FIELD 12 -#define RISC_SLOT_LOOP 14 - -#define RESOURCE_OVERLAY 1 -#define RESOURCE_VIDEO 2 -#define RESOURCE_VBI 4 - -#define RAW_LINES 640 -#define RAW_BPL 1024 - -#define UNSET (-1U) - -#define clamp(x, low, high) min (max (low, x), high) - -/* ---------------------------------------------------------- */ - -struct bttv_tvnorm { - int v4l2_id; - char *name; - u32 Fsc; - u16 swidth, sheight; /* scaled standard width, height */ - u16 totalwidth; - u8 adelay, bdelay, iform; - u32 scaledtwidth; - u16 hdelayx1, hactivex1; - u16 vdelay; - u8 vbipack; - u16 vtotal; - int sram; - /* ITU-R frame line number of the first VBI line we can - capture, of the first and second field. */ - u16 vbistart[2]; -}; -extern const struct bttv_tvnorm bttv_tvnorms[]; - -struct bttv_format { - char *name; - int palette; /* video4linux 1 */ - int fourcc; /* video4linux 2 */ - int btformat; /* BT848_COLOR_FMT_* */ - int btswap; /* BT848_COLOR_CTL_* */ - int depth; /* bit/pixel */ - int flags; - int hshift,vshift; /* for planar modes */ -}; - -/* ---------------------------------------------------------- */ - -struct bttv_geometry { - u8 vtc,crop,comb; - u16 width,hscale,hdelay; - u16 sheight,vscale,vdelay,vtotal; -}; - -struct bttv_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - /* bttv specific */ - const struct bttv_format *fmt; - int tvnorm; - int btformat; - int btswap; - struct bttv_geometry geo; - struct btcx_riscmem top; - struct btcx_riscmem bottom; -}; - -struct bttv_buffer_set { - struct bttv_buffer *top; /* top field buffer */ - struct bttv_buffer *bottom; /* bottom field buffer */ - unsigned int top_irq; - unsigned int frame_irq; -}; - -struct bttv_overlay { - int tvnorm; - struct v4l2_rect w; - enum v4l2_field field; - struct v4l2_clip *clips; - int nclips; - int setup_ok; -}; - -struct bttv_fh { - struct bttv *btv; - int resources; -#ifdef VIDIOC_G_PRIORITY - enum v4l2_priority prio; -#endif - enum v4l2_buf_type type; - - /* video capture */ - struct videobuf_queue cap; - const struct bttv_format *fmt; - int width; - int height; - - /* current settings */ - const struct bttv_format *ovfmt; - struct bttv_overlay ov; - - /* video overlay */ - struct videobuf_queue vbi; - int lines; -}; - -/* ---------------------------------------------------------- */ -/* bttv-risc.c */ - -/* risc code generators - capture */ -int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, - struct scatterlist *sglist, - unsigned int offset, unsigned int bpl, - unsigned int pitch, unsigned int lines); - -/* control dma register + risc main loop */ -void bttv_set_dma(struct bttv *btv, int override); -int bttv_risc_init_main(struct bttv *btv); -int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, - int irqflags); - -/* capture buffer handling */ -int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf); -int bttv_buffer_activate_video(struct bttv *btv, - struct bttv_buffer_set *set); -int bttv_buffer_activate_vbi(struct bttv *btv, - struct bttv_buffer *vbi); -void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv, - struct bttv_buffer *buf); - -/* overlay handling */ -int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, - const struct bttv_format *fmt, - struct bttv_buffer *buf); - - -/* ---------------------------------------------------------- */ -/* bttv-vbi.c */ - -void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f); -void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f); -void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines); - -extern struct videobuf_queue_ops bttv_vbi_qops; - -/* ---------------------------------------------------------- */ -/* bttv-gpio.c */ - - -extern struct bus_type bttv_sub_bus_type; -int bttv_sub_add_device(struct bttv_core *core, char *name); -int bttv_sub_del_devices(struct bttv_core *core); -void bttv_gpio_irq(struct bttv_core *core); - - -/* ---------------------------------------------------------- */ -/* bttv-driver.c */ - -/* insmod options */ -extern unsigned int bttv_verbose; -extern unsigned int bttv_debug; -extern unsigned int bttv_gpio; -extern void bttv_gpio_tracking(struct bttv *btv, char *comment); -extern int init_bttv_i2c(struct bttv *btv); -extern int fini_bttv_i2c(struct bttv *btv); - -#define bttv_printk if (bttv_verbose) printk -#define dprintk if (bttv_debug >= 1) printk -#define d2printk if (bttv_debug >= 2) printk - -#define BTTV_MAX_FBUF 0x208000 -#define VBIBUF_SIZE (2048*VBI_MAXLINES*2) -#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ -#define BTTV_FREE_IDLE (HZ) /* one second */ - - -struct bttv_pll_info { - unsigned int pll_ifreq; /* PLL input frequency */ - unsigned int pll_ofreq; /* PLL output frequency */ - unsigned int pll_crystal; /* Crystal used for input */ - unsigned int pll_current; /* Currently programmed ofreq */ -}; - -/* for gpio-connected remote control */ -struct bttv_input { - struct input_dev *dev; - struct ir_input_state ir; - char name[32]; - char phys[32]; - u32 mask_keycode; - u32 mask_keydown; -}; - -struct bttv_suspend_state { - u32 gpio_enable; - u32 gpio_data; - int disabled; - int loop_irq; - struct bttv_buffer_set video; - struct bttv_buffer *vbi; -}; - -struct bttv { - struct bttv_core c; - - /* pci device config */ - unsigned short id; - unsigned char revision; - unsigned char __iomem *bt848_mmio; /* pointer to mmio */ - - /* card configuration info */ - unsigned int cardid; /* pci subsystem id (bt878 based ones) */ - unsigned int tuner_type; /* tuner chip type */ - unsigned int tda9887_conf; - unsigned int svhs; - struct bttv_pll_info pll; - int triton1; - int gpioirq; - int (*custom_irq)(struct bttv *btv); - - int use_i2c_hw; - - /* old gpio interface */ - wait_queue_head_t gpioq; - int shutdown; - void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); - - /* new gpio interface */ - spinlock_t gpio_lock; - - /* i2c layer */ - struct i2c_algo_bit_data i2c_algo; - struct i2c_client i2c_client; - int i2c_state, i2c_rc; - int i2c_done; - wait_queue_head_t i2c_queue; - - /* video4linux (1) */ - struct video_device *video_dev; - struct video_device *radio_dev; - struct video_device *vbi_dev; - - /* infrared remote */ - int has_remote; - struct bttv_ir *remote; - - /* locking */ - spinlock_t s_lock; - struct mutex lock; - int resources; - struct mutex reslock; -#ifdef VIDIOC_G_PRIORITY - struct v4l2_prio_state prio; -#endif - - /* video state */ - unsigned int input; - unsigned int audio; - unsigned long freq; - int tvnorm,hue,contrast,bright,saturation; - struct v4l2_framebuffer fbuf; - unsigned int field_count; - - /* various options */ - int opt_combfilter; - int opt_lumafilter; - int opt_automute; - int opt_chroma_agc; - int opt_adc_crush; - int opt_vcr_hack; - int opt_whitecrush_upper; - int opt_whitecrush_lower; - int opt_uv_ratio; - int opt_full_luma_range; - int opt_coring; - - /* radio data/state */ - int has_radio; - int radio_user; - - /* miro/pinnacle + Aimslab VHX - philips matchbox (tea5757 radio tuner) support */ - int has_matchbox; - int mbox_we; - int mbox_data; - int mbox_clk; - int mbox_most; - int mbox_mask; - - /* ISA stuff (Terratec Active Radio Upgrade) */ - int mbox_ior; - int mbox_iow; - int mbox_csel; - - /* risc memory management data - - must aquire s_lock before changing these - - only the irq handler is supported to touch top + bottom + vcurr */ - struct btcx_riscmem main; - struct bttv_buffer *screen; /* overlay */ - struct list_head capture; /* video capture queue */ - struct list_head vcapture; /* vbi capture queue */ - struct bttv_buffer_set curr; /* active buffers */ - struct bttv_buffer *cvbi; /* active vbi buffer */ - int loop_irq; - int new_input; - - unsigned long cap_ctl; - unsigned long dma_on; - struct timer_list timeout; - struct bttv_suspend_state state; - - /* stats */ - unsigned int errors; - unsigned int framedrop; - unsigned int irq_total; - unsigned int irq_me; - - unsigned int users; - struct bttv_fh init; -}; - -/* our devices */ -#define BTTV_MAX 16 -extern unsigned int bttv_num; -extern struct bttv bttvs[BTTV_MAX]; - -/* private ioctls */ -#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) -#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) - -#endif - -#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr)) -#define btread(adr) readl(btv->bt848_mmio+(adr)) - -#define btand(dat,adr) btwrite((dat) & btread(adr), adr) -#define btor(dat,adr) btwrite((dat) | btread(adr), adr) -#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) - -#endif /* _BTTVP_H_ */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ -- cgit v1.2.3-59-g8ed1b From c72602b8250cc0d3ace59d1a7334c5cd7aa9490e Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 17 Mar 2006 18:21:17 -0300 Subject: V4L/DVB (3543): Fix Makefile to adapt to bt8xx/ conversion Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile index d188e4c670b5..9d197efb481d 100644 --- a/drivers/media/dvb/bt8xx/Makefile +++ b/drivers/media/dvb/bt8xx/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o -EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends -- cgit v1.2.3-59-g8ed1b From fa3fcceb30eb8a3cb2ac299c207c6f89b9aed379 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 23 Mar 2006 21:45:24 -0300 Subject: V4L/DVB (3546): Fix Compilation after moving bttv code - Missing a Makefile for bt8xx - rds.h were at wrong directory, since it is a global header for an internal interface - tda7432 and tda9875 were dependent from bttv.h - bttv.h were holding i2c addresses Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/Makefile | 12 ++++++++ drivers/media/video/bt8xx/bttv-driver.c | 2 +- drivers/media/video/bt8xx/bttv.h | 20 +------------ drivers/media/video/rds.h | 48 ------------------------------ drivers/media/video/saa6588.c | 2 +- drivers/media/video/saa7134/saa7134-core.c | 2 +- drivers/media/video/tda7432.c | 2 +- drivers/media/video/tda9875.c | 4 +-- include/media/i2c-addr.h | 30 +++++++++++++++++++ include/media/rds.h | 44 +++++++++++++++++++++++++++ 10 files changed, 93 insertions(+), 73 deletions(-) create mode 100644 drivers/media/video/bt8xx/Makefile delete mode 100644 drivers/media/video/rds.h create mode 100644 include/media/i2c-addr.h create mode 100644 include/media/rds.h (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile new file mode 100644 index 000000000000..94350f21cdc0 --- /dev/null +++ b/drivers/media/video/bt8xx/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for the video capture/playback device drivers. +# + +bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ + bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \ + bttv-input.o + +obj-$(CONFIG_VIDEO_BT848) += bttv.o + +EXTRA_CFLAGS += -I$(src)/.. +EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 2505ae5a7b97..71535775f2e8 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -42,7 +42,7 @@ #include #include -#include "rds.h" +#include unsigned int bttv_num; /* number of Bt848s in use */ diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 9908c8e0c951..ebde3e8219cf 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -18,6 +18,7 @@ #include #include #include +#include /* ---------------------------------------------------------- */ /* exported by bttv-cards.c */ @@ -168,25 +169,6 @@ #define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f #define BTTV_BOARD_MACHTV_MAGICTV 0x90 -/* i2c address list */ -#define I2C_TSA5522 0xc2 -#define I2C_TDA7432 0x8a -#define I2C_BT832_ALT1 0x88 -#define I2C_BT832_ALT2 0x8a // alternate setting -#define I2C_TDA8425 0x82 -#define I2C_TDA9840 0x84 -#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */ -#define I2C_TDA9874 0xb0 /* also used by 9875 */ -#define I2C_TDA9875 0xb0 -#define I2C_HAUPEE 0xa0 -#define I2C_STBEE 0xae -#define I2C_VHX 0xc0 -#define I2C_MSP3400 0x80 -#define I2C_MSP3400_ALT 0x88 -#define I2C_TEA6300 0x80 /* also used by 6320 */ -#define I2C_DPL3518 0x84 -#define I2C_TDA9887 0x86 - /* more card-specific defines */ #define PT2254_L_CHANNEL 0x10 #define PT2254_R_CHANNEL 0x08 diff --git a/drivers/media/video/rds.h b/drivers/media/video/rds.h deleted file mode 100644 index 0d30eb744e61..000000000000 --- a/drivers/media/video/rds.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - - Types and defines needed for RDS. This is included by - saa6588.c and every driver (e.g. bttv-driver.c) that wants - to use the saa6588 module. - - Instead of having a seperate rds.h, I'd prefer to include - this stuff in one of the already existing files like tuner.h - - (c) 2005 by Hans J. Koch - - 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. - -*/ - -#ifndef _RDS_H -#define _RDS_H - -struct rds_command { - unsigned int block_count; - int result; - unsigned char __user *buffer; - struct file *instance; - poll_table *event_list; -}; - -#define RDS_CMD_OPEN _IOW('R',1,int) -#define RDS_CMD_CLOSE _IOW('R',2,int) -#define RDS_CMD_READ _IOR('R',3,int) -#define RDS_CMD_POLL _IOR('R',4,int) - -#endif - - - - diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index d17395c4f55c..a81285ca7d5b 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -32,7 +32,7 @@ #include -#include "rds.h" +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 15405d1e1675..c98571c9d5a6 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -960,7 +960,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (saa7134_no_overlay <= 0) { saa7134_video_template.type |= VID_TYPE_OVERLAY; } else { - printk("bttv: Overlay support disabled.\n"); + printk("%s: Overlay support disabled.\n",dev->name); } dev->video_dev = vdev_init(dev,&saa7134_video_template,"video"); err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index fc3d5824efff..600dacb873f4 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -48,9 +48,9 @@ #include #include -#include "bttv.h" #include #include +#include #ifndef VIDEO_AUDIO_BALANCE # define VIDEO_AUDIO_BALANCE 32 diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index ef98c4982250..8a1e58e72c00 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -30,14 +30,14 @@ #include #include -#include "bttv.h" #include +#include + static int debug; /* insmod parameter */ module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_LICENSE("GPL"); - /* Addresses to scan */ static unsigned short normal_i2c[] = { I2C_TDA9875 >> 1, diff --git a/include/media/i2c-addr.h b/include/media/i2c-addr.h new file mode 100644 index 000000000000..4212832d48aa --- /dev/null +++ b/include/media/i2c-addr.h @@ -0,0 +1,30 @@ +/* + * V4L I2C address list + * + * + * Copyright (C) 2006 Mauro Carvalho Chehab + * Based on a previous mapping by + * Ralph Metzler (rjkm@thp.uni-koeln.de) + * Gerd Knorr + * + */ + +/* bttv address list */ +#define I2C_TSA5522 0xc2 +#define I2C_TDA7432 0x8a +#define I2C_BT832_ALT1 0x88 +#define I2C_BT832_ALT2 0x8a // alternate setting +#define I2C_TDA8425 0x82 +#define I2C_TDA9840 0x84 +#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */ +#define I2C_TDA9874 0xb0 /* also used by 9875 */ +#define I2C_TDA9875 0xb0 +#define I2C_HAUPEE 0xa0 +#define I2C_STBEE 0xae +#define I2C_VHX 0xc0 +#define I2C_MSP3400 0x80 +#define I2C_MSP3400_ALT 0x88 +#define I2C_TEA6300 0x80 /* also used by 6320 */ +#define I2C_DPL3518 0x84 +#define I2C_TDA9887 0x86 + diff --git a/include/media/rds.h b/include/media/rds.h new file mode 100644 index 000000000000..951c1ae0be74 --- /dev/null +++ b/include/media/rds.h @@ -0,0 +1,44 @@ +/* + + Types and defines needed for RDS. This is included by + saa6588.c and every driver (e.g. bttv-driver.c) that wants + to use the saa6588 module. + + Instead of having a seperate rds.h, I'd prefer to include + this stuff in one of the already existing files like tuner.h + + (c) 2005 by Hans J. Koch + + 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. + +*/ + +#ifndef _RDS_H +#define _RDS_H + +struct rds_command { + unsigned int block_count; + int result; + unsigned char __user *buffer; + struct file *instance; + poll_table *event_list; +}; + +#define RDS_CMD_OPEN _IOW('R',1,int) +#define RDS_CMD_CLOSE _IOW('R',2,int) +#define RDS_CMD_READ _IOR('R',3,int) +#define RDS_CMD_POLL _IOR('R',4,int) + +#endif -- cgit v1.2.3-59-g8ed1b From 7c9b5048305ead226fb16def98d86f3ed67c4807 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 18 Mar 2006 08:08:14 -0300 Subject: V4L/DVB (3547): Tvaudio.h are just i2c addresses. Merged into i2c-addr.h Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 2 +- drivers/media/video/tvaudio.h | 14 -------------- include/media/i2c-addr.h | 14 ++++++++++++++ 3 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 drivers/media/video/tvaudio.h (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 4efb01bb44ac..e68d5190cbbb 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -33,7 +33,7 @@ #include #include -#include "tvaudio.h" +#include /* ---------------------------------------------------------------------- */ /* insmod args */ diff --git a/drivers/media/video/tvaudio.h b/drivers/media/video/tvaudio.h deleted file mode 100644 index af7e116af9a9..000000000000 --- a/drivers/media/video/tvaudio.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * i2c bus addresses for the chips supported by tvaudio.c - */ - -#define I2C_TDA8425 0x82 -#define I2C_TDA9840 0x84 /* also used by TA8874Z */ -#define I2C_TDA985x_L 0xb4 /* also used by 9873 */ -#define I2C_TDA985x_H 0xb6 -#define I2C_TDA9874 0xb0 /* also used by 9875 */ - -#define I2C_TEA6300 0x80 /* also used by 6320 */ -#define I2C_TEA6420 0x98 - -#define I2C_PIC16C54 0x96 /* PV951 */ diff --git a/include/media/i2c-addr.h b/include/media/i2c-addr.h index 4212832d48aa..7b0f5fe94e08 100644 --- a/include/media/i2c-addr.h +++ b/include/media/i2c-addr.h @@ -28,3 +28,17 @@ #define I2C_DPL3518 0x84 #define I2C_TDA9887 0x86 +/* + * i2c bus addresses for the chips supported by tvaudio.c + */ + +#define I2C_TDA8425 0x82 +#define I2C_TDA9840 0x84 /* also used by TA8874Z */ +#define I2C_TDA985x_L 0xb4 /* also used by 9873 */ +#define I2C_TDA985x_H 0xb6 +#define I2C_TDA9874 0xb0 /* also used by 9875 */ + +#define I2C_TEA6300 0x80 /* also used by 6320 */ +#define I2C_TEA6420 0x98 + +#define I2C_PIC16C54 0x96 /* PV951 */ -- cgit v1.2.3-59-g8ed1b From 09df1c163adcf43e2c4234b52985f34b95b7634e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 18 Mar 2006 08:31:34 -0300 Subject: V4L/DVB (3548): Renamed I2C_foo addresses to I2C_ADDR_foo I2C_foo were used for some i2c addresses. Bad, since those constants could mean other i2c chip things. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bt832.c | 2 +- drivers/media/video/bt8xx/bttv-cards.c | 16 ++++----- drivers/media/video/mxb.c | 6 ++-- drivers/media/video/tda7432.c | 2 +- drivers/media/video/tda9840.c | 2 +- drivers/media/video/tda9840.h | 2 +- drivers/media/video/tda9875.c | 2 +- drivers/media/video/tea6420.c | 2 +- drivers/media/video/tea6420.h | 4 +-- drivers/media/video/tvaudio.c | 60 +++++++++++++++++----------------- include/media/i2c-addr.h | 58 ++++++++++++++++---------------- 11 files changed, 78 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bt832.c b/drivers/media/video/bt8xx/bt832.c index cc54b62f4601..f1309d94e96e 100644 --- a/drivers/media/video/bt8xx/bt832.c +++ b/drivers/media/video/bt8xx/bt832.c @@ -39,7 +39,7 @@ MODULE_LICENSE("GPL"); /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1, +static unsigned short normal_i2c[] = { I2C_ADDR_BT832_ALT1>>1, I2C_ADDR_BT832_ALT2>>1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index abfa6ad857a0..e869bfbab378 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -3046,7 +3046,7 @@ static void miro_pinnacle_gpio(struct bttv *btv) gpio_inout(0xffffff, 0); gpio = gpio_read(); id = ((gpio>>10) & 63) -1; - msp = bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx"); + msp = bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx"); if (id < 32) { btv->tuner_type = miro_tunermap[id]; if (0 == (gpio & 0x20)) { @@ -3442,8 +3442,8 @@ void __devinit bttv_init_card2(struct bttv *btv) if (bttv_tvcards[btv->c.type].digital_mode == DIGITAL_MODE_CAMERA) { /* detect Bt832 chip for quartzsight digital camera */ - if ((bttv_I2CRead(btv, I2C_BT832_ALT1, "Bt832") >=0) || - (bttv_I2CRead(btv, I2C_BT832_ALT2, "Bt832") >=0)) + if ((bttv_I2CRead(btv, I2C_ADDR_BT832_ALT1, "Bt832") >=0) || + (bttv_I2CRead(btv, I2C_ADDR_BT832_ALT2, "Bt832") >=0)) boot_bt832(btv); } @@ -3452,19 +3452,19 @@ void __devinit bttv_init_card2(struct bttv *btv) /* try to detect audio/fader chips */ if (!bttv_tvcards[btv->c.type].no_msp34xx && - bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) + bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx") >=0) request_module("msp3400"); if (bttv_tvcards[btv->c.type].msp34xx_alt && - bttv_I2CRead(btv, I2C_MSP3400_ALT, "MSP34xx (alternate address)") >=0) + bttv_I2CRead(btv, I2C_ADDR_MSP3400_ALT, "MSP34xx (alternate address)") >=0) request_module("msp3400"); if (!bttv_tvcards[btv->c.type].no_tda9875 && - bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) + bttv_I2CRead(btv, I2C_ADDR_TDA9875, "TDA9875") >=0) request_module("tda9875"); if (!bttv_tvcards[btv->c.type].no_tda7432 && - bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) + bttv_I2CRead(btv, I2C_ADDR_TDA7432, "TDA7432") >=0) request_module("tda7432"); if (bttv_tvcards[btv->c.type].needs_tvaudio) @@ -3475,7 +3475,7 @@ void __devinit bttv_init_card2(struct bttv *btv) if (btv->tda9887_conf) tda9887 = 1; if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb && - bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0) + bttv_I2CRead(btv, I2C_ADDR_TDA9887, "TDA9887") >=0) tda9887 = 1; /* Hybrid DVB card, DOES have a tda9887 */ if (btv->c.type == BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE) diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index eb3b31867494..14ca251787d5 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -198,13 +198,13 @@ static int mxb_probe(struct saa7146_dev* dev) /* loop through all i2c-devices on the bus and look who is there */ list_for_each(item,&mxb->i2c_adapter.clients) { client = list_entry(item, struct i2c_client, list); - if( I2C_TEA6420_1 == client->addr ) + if( I2C_ADDR_TEA6420_1 == client->addr ) mxb->tea6420_1 = client; - if( I2C_TEA6420_2 == client->addr ) + if( I2C_ADDR_TEA6420_2 == client->addr ) mxb->tea6420_2 = client; if( I2C_TEA6415C_2 == client->addr ) mxb->tea6415c = client; - if( I2C_TDA9840 == client->addr ) + if( I2C_ADDR_TDA9840 == client->addr ) mxb->tda9840 = client; if( I2C_SAA7111 == client->addr ) mxb->saa7111a = client; diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 600dacb873f4..12b8981efd13 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -71,7 +71,7 @@ module_param(maxvol, int, S_IRUGO | S_IWUSR); /* Address to scan (I2C address of this chip) */ static unsigned short normal_i2c[] = { - I2C_TDA7432 >> 1, + I2C_ADDR_TDA7432 >> 1, I2C_CLIENT_END, }; I2C_CLIENT_INSMOD; diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index 0243700f58ae..56e08e156cf0 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -43,7 +43,7 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define TEST 0x04 /* addresses to scan, found only at 0x42 (7-Bit) */ -static unsigned short normal_i2c[] = { I2C_TDA9840, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END }; /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; diff --git a/drivers/media/video/tda9840.h b/drivers/media/video/tda9840.h index 28021053bd09..7da8432cdca7 100644 --- a/drivers/media/video/tda9840.h +++ b/drivers/media/video/tda9840.h @@ -1,7 +1,7 @@ #ifndef __INCLUDED_TDA9840__ #define __INCLUDED_TDA9840__ -#define I2C_TDA9840 0x42 +#define I2C_ADDR_TDA9840 0x42 #define TDA9840_DETECT _IOR('v',1,int) /* return values for TDA9840_DETCT */ diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 8a1e58e72c00..ccfd3b90ea9f 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -40,7 +40,7 @@ MODULE_LICENSE("GPL"); /* Addresses to scan */ static unsigned short normal_i2c[] = { - I2C_TDA9875 >> 1, + I2C_ADDR_TDA9875 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index ad7d2872cfbf..b4263b630712 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -40,7 +40,7 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0) /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */ -static unsigned short normal_i2c[] = { I2C_TEA6420_1, I2C_TEA6420_2, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END }; /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; diff --git a/drivers/media/video/tea6420.h b/drivers/media/video/tea6420.h index ea664df15ad4..5ef7c18e0c54 100644 --- a/drivers/media/video/tea6420.h +++ b/drivers/media/video/tea6420.h @@ -2,8 +2,8 @@ #define __INCLUDED_TEA6420__ /* possible addresses */ -#define I2C_TEA6420_1 0x4c -#define I2C_TEA6420_2 0x4d +#define I2C_ADDR_TEA6420_1 0x4c +#define I2C_ADDR_TEA6420_2 0x4d struct tea6420_multiplex { diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index e68d5190cbbb..4cc0497dcbde 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -137,14 +137,14 @@ struct CHIPSTATE { /* i2c addresses */ static unsigned short normal_i2c[] = { - I2C_TDA8425 >> 1, - I2C_TEA6300 >> 1, - I2C_TEA6420 >> 1, - I2C_TDA9840 >> 1, - I2C_TDA985x_L >> 1, - I2C_TDA985x_H >> 1, - I2C_TDA9874 >> 1, - I2C_PIC16C54 >> 1, + I2C_ADDR_TDA8425 >> 1, + I2C_ADDR_TEA6300 >> 1, + I2C_ADDR_TEA6420 >> 1, + I2C_ADDR_TDA9840 >> 1, + I2C_ADDR_TDA985x_L >> 1, + I2C_ADDR_TDA985x_H >> 1, + I2C_ADDR_TDA9874 >> 1, + I2C_ADDR_PIC16C54 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; @@ -1269,8 +1269,8 @@ static struct CHIPDESC chiplist[] = { .name = "tda9840", .id = I2C_DRIVERID_TDA9840, .insmodopt = &tda9840, - .addr_lo = I2C_TDA9840 >> 1, - .addr_hi = I2C_TDA9840 >> 1, + .addr_lo = I2C_ADDR_TDA9840 >> 1, + .addr_hi = I2C_ADDR_TDA9840 >> 1, .registers = 5, .checkit = tda9840_checkit, @@ -1286,8 +1286,8 @@ static struct CHIPDESC chiplist[] = { .id = I2C_DRIVERID_TDA9873, .checkit = tda9873_checkit, .insmodopt = &tda9873, - .addr_lo = I2C_TDA985x_L >> 1, - .addr_hi = I2C_TDA985x_H >> 1, + .addr_lo = I2C_ADDR_TDA985x_L >> 1, + .addr_hi = I2C_ADDR_TDA985x_H >> 1, .registers = 3, .flags = CHIP_HAS_INPUTSEL, @@ -1308,8 +1308,8 @@ static struct CHIPDESC chiplist[] = { .checkit = tda9874a_checkit, .initialize = tda9874a_initialize, .insmodopt = &tda9874a, - .addr_lo = I2C_TDA9874 >> 1, - .addr_hi = I2C_TDA9874 >> 1, + .addr_lo = I2C_ADDR_TDA9874 >> 1, + .addr_hi = I2C_ADDR_TDA9874 >> 1, .getmode = tda9874a_getmode, .setmode = tda9874a_setmode, @@ -1319,8 +1319,8 @@ static struct CHIPDESC chiplist[] = { .name = "tda9850", .id = I2C_DRIVERID_TDA9850, .insmodopt = &tda9850, - .addr_lo = I2C_TDA985x_L >> 1, - .addr_hi = I2C_TDA985x_H >> 1, + .addr_lo = I2C_ADDR_TDA985x_L >> 1, + .addr_hi = I2C_ADDR_TDA985x_H >> 1, .registers = 11, .getmode = tda985x_getmode, @@ -1332,8 +1332,8 @@ static struct CHIPDESC chiplist[] = { .name = "tda9855", .id = I2C_DRIVERID_TDA9855, .insmodopt = &tda9855, - .addr_lo = I2C_TDA985x_L >> 1, - .addr_hi = I2C_TDA985x_H >> 1, + .addr_lo = I2C_ADDR_TDA985x_L >> 1, + .addr_hi = I2C_ADDR_TDA985x_H >> 1, .registers = 11, .flags = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE, @@ -1357,8 +1357,8 @@ static struct CHIPDESC chiplist[] = { .name = "tea6300", .id = I2C_DRIVERID_TEA6300, .insmodopt = &tea6300, - .addr_lo = I2C_TEA6300 >> 1, - .addr_hi = I2C_TEA6300 >> 1, + .addr_lo = I2C_ADDR_TEA6300 >> 1, + .addr_hi = I2C_ADDR_TEA6300 >> 1, .registers = 6, .flags = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL, @@ -1379,8 +1379,8 @@ static struct CHIPDESC chiplist[] = { .id = I2C_DRIVERID_TEA6300, .initialize = tea6320_initialize, .insmodopt = &tea6320, - .addr_lo = I2C_TEA6300 >> 1, - .addr_hi = I2C_TEA6300 >> 1, + .addr_lo = I2C_ADDR_TEA6300 >> 1, + .addr_hi = I2C_ADDR_TEA6300 >> 1, .registers = 8, .flags = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL, @@ -1400,8 +1400,8 @@ static struct CHIPDESC chiplist[] = { .name = "tea6420", .id = I2C_DRIVERID_TEA6420, .insmodopt = &tea6420, - .addr_lo = I2C_TEA6420 >> 1, - .addr_hi = I2C_TEA6420 >> 1, + .addr_lo = I2C_ADDR_TEA6420 >> 1, + .addr_hi = I2C_ADDR_TEA6420 >> 1, .registers = 1, .flags = CHIP_HAS_INPUTSEL, @@ -1413,8 +1413,8 @@ static struct CHIPDESC chiplist[] = { .name = "tda8425", .id = I2C_DRIVERID_TDA8425, .insmodopt = &tda8425, - .addr_lo = I2C_TDA8425 >> 1, - .addr_hi = I2C_TDA8425 >> 1, + .addr_lo = I2C_ADDR_TDA8425 >> 1, + .addr_hi = I2C_ADDR_TDA8425 >> 1, .registers = 9, .flags = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL, @@ -1437,8 +1437,8 @@ static struct CHIPDESC chiplist[] = { .name = "pic16c54 (PV951)", .id = I2C_DRIVERID_PIC16C54_PV9, .insmodopt = &pic16c54, - .addr_lo = I2C_PIC16C54 >> 1, - .addr_hi = I2C_PIC16C54>> 1, + .addr_lo = I2C_ADDR_PIC16C54 >> 1, + .addr_hi = I2C_ADDR_PIC16C54>> 1, .registers = 2, .flags = CHIP_HAS_INPUTSEL, @@ -1456,8 +1456,8 @@ static struct CHIPDESC chiplist[] = { /*.id = I2C_DRIVERID_TA8874Z, */ .checkit = ta8874z_checkit, .insmodopt = &ta8874z, - .addr_lo = I2C_TDA9840 >> 1, - .addr_hi = I2C_TDA9840 >> 1, + .addr_lo = I2C_ADDR_TDA9840 >> 1, + .addr_hi = I2C_ADDR_TDA9840 >> 1, .registers = 2, .getmode = ta8874z_getmode, diff --git a/include/media/i2c-addr.h b/include/media/i2c-addr.h index 7b0f5fe94e08..e7ff44a35ca0 100644 --- a/include/media/i2c-addr.h +++ b/include/media/i2c-addr.h @@ -1,44 +1,44 @@ /* - * V4L I2C address list + * V4L I2C address list * * - * Copyright (C) 2006 Mauro Carvalho Chehab + * Copyright (C) 2006 Mauro Carvalho Chehab * Based on a previous mapping by - * Ralph Metzler (rjkm@thp.uni-koeln.de) - * Gerd Knorr + * Ralph Metzler (rjkm@thp.uni-koeln.de) + * Gerd Knorr * */ /* bttv address list */ -#define I2C_TSA5522 0xc2 -#define I2C_TDA7432 0x8a -#define I2C_BT832_ALT1 0x88 -#define I2C_BT832_ALT2 0x8a // alternate setting -#define I2C_TDA8425 0x82 -#define I2C_TDA9840 0x84 -#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */ -#define I2C_TDA9874 0xb0 /* also used by 9875 */ -#define I2C_TDA9875 0xb0 -#define I2C_HAUPEE 0xa0 -#define I2C_STBEE 0xae -#define I2C_VHX 0xc0 -#define I2C_MSP3400 0x80 -#define I2C_MSP3400_ALT 0x88 -#define I2C_TEA6300 0x80 /* also used by 6320 */ -#define I2C_DPL3518 0x84 -#define I2C_TDA9887 0x86 +#define I2C_ADDR_TSA5522 0xc2 +#define I2C_ADDR_TDA7432 0x8a +#define I2C_ADDR_BT832_ALT1 0x88 +#define I2C_ADDR_BT832_ALT2 0x8a // alternate setting +#define I2C_ADDR_TDA8425 0x82 +#define I2C_ADDR_TDA9840 0x84 +#define I2C_ADDR_TDA9850 0xb6 /* also used by 9855,9873 */ +#define I2C_ADDR_TDA9874 0xb0 /* also used by 9875 */ +#define I2C_ADDR_TDA9875 0xb0 +#define I2C_ADDR_HAUPEE 0xa0 +#define I2C_ADDR_STBEE 0xae +#define I2C_ADDR_VHX 0xc0 +#define I2C_ADDR_MSP3400 0x80 +#define I2C_ADDR_MSP3400_ALT 0x88 +#define I2C_ADDR_TEA6300 0x80 /* also used by 6320 */ +#define I2C_ADDR_DPL3518 0x84 +#define I2C_ADDR_TDA9887 0x86 /* * i2c bus addresses for the chips supported by tvaudio.c */ -#define I2C_TDA8425 0x82 -#define I2C_TDA9840 0x84 /* also used by TA8874Z */ -#define I2C_TDA985x_L 0xb4 /* also used by 9873 */ -#define I2C_TDA985x_H 0xb6 -#define I2C_TDA9874 0xb0 /* also used by 9875 */ +#define I2C_ADDR_TDA8425 0x82 +#define I2C_ADDR_TDA9840 0x84 /* also used by TA8874Z */ +#define I2C_ADDR_TDA985x_L 0xb4 /* also used by 9873 */ +#define I2C_ADDR_TDA985x_H 0xb6 +#define I2C_ADDR_TDA9874 0xb0 /* also used by 9875 */ -#define I2C_TEA6300 0x80 /* also used by 6320 */ -#define I2C_TEA6420 0x98 +#define I2C_ADDR_TEA6300 0x80 /* also used by 6320 */ +#define I2C_ADDR_TEA6420 0x98 -#define I2C_PIC16C54 0x96 /* PV951 */ +#define I2C_ADDR_PIC16C54 0x96 /* PV951 */ -- cgit v1.2.3-59-g8ed1b From 6637e6fd2a930567f1878e4585d70b444a9cb3b3 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 18 Mar 2006 14:13:22 -0300 Subject: V4L/DVB (3549): Make hotplug automatically load the b2c2-flexcop-usb module There was no MODULE_DEVICE_TABLE for the b2c2-flexcop-usb module. This makes it impossible for hotplug to load the module automatically, when such a device is connected. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop-usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c index a6c91db40ad6..06ec9fff0ec1 100644 --- a/drivers/media/dvb/b2c2/flexcop-usb.c +++ b/drivers/media/dvb/b2c2/flexcop-usb.c @@ -541,6 +541,7 @@ static struct usb_device_id flexcop_usb_table [] = { { USB_DEVICE(0x0af7, 0x0101) }, { } }; +MODULE_DEVICE_TABLE (usb, flexcop_usb_table); /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver flexcop_usb_driver = { -- cgit v1.2.3-59-g8ed1b From 73dcddc583c40bcc9e6bf468c78c31930899922c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 16 Mar 2006 20:23:47 -0300 Subject: V4L/DVB (3551): Fix saturation bug. Fix NTSC->PAL standard change. Detect NTSC-KR standard. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 35 ++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 8a257978056f..bcb7ef85eb23 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -176,9 +176,9 @@ static void cx25840_initialize(struct i2c_client *client, int loadfw) cx25840_write(client, 0x4a5, 0x00); cx25840_write(client, 0x402, 0x00); /* 8. */ - cx25840_write(client, 0x401, 0x18); - cx25840_write(client, 0x4a2, 0x10); - cx25840_write(client, 0x402, 0x04); + cx25840_and_or(client, 0x401, ~0x18, 0); + cx25840_and_or(client, 0x4a2, ~0x10, 0x10); + /* steps 8c and 8d are done in change_input() */ /* 10. */ cx25840_write(client, 0x8d3, 0x1f); cx25840_write(client, 0x8e3, 0x03); @@ -209,6 +209,17 @@ static void input_change(struct i2c_client *client) struct cx25840_state *state = i2c_get_clientdata(client); v4l2_std_id std = cx25840_get_v4lstd(client); + /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */ + if (std & V4L2_STD_SECAM) { + cx25840_write(client, 0x402, 0); + } + else { + cx25840_write(client, 0x402, 0x04); + cx25840_write(client, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11); + } + cx25840_and_or(client, 0x401, ~0x60, 0); + cx25840_and_or(client, 0x401, ~0x60, 0x60); + /* Note: perhaps V4L2_STD_PAL_M should be handled as V4L2_STD_NTSC instead of V4L2_STD_PAL. Someone needs to test this. */ if (std & V4L2_STD_PAL) { @@ -343,6 +354,15 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) } } + /* Follow step 9 of section 3.16 in the cx25840 datasheet. + Without this PAL may display a vertical ghosting effect. + This happens for example with the Yuan MPC622. */ + if (fmt >= 4 && fmt < 8) { + /* Set format to NTSC-M */ + cx25840_and_or(client, 0x400, ~0xf, 1); + /* Turn off LCOMB */ + cx25840_and_or(client, 0x47b, ~6, 0); + } cx25840_and_or(client, 0x400, ~0xf, fmt); cx25840_vbi_setup(client); return 0; @@ -359,7 +379,14 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) } switch (fmt) { - case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR; + case 0x1: + { + /* if the audio std is A2-M, then this is the South Korean + NTSC standard */ + if (cx25840_read(client, 0x805) == 2) + return V4L2_STD_NTSC_M_KR; + return V4L2_STD_NTSC_M; + } case 0x2: return V4L2_STD_NTSC_M_JP; case 0x3: return V4L2_STD_NTSC_443; case 0x4: return V4L2_STD_PAL; -- cgit v1.2.3-59-g8ed1b From bc2c7c365bd18c00f5fefaf1a560c440f3ce13f3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 18 Mar 2006 18:36:44 -0300 Subject: V4L/DVB (3557): Kconfig: fix title and description for VIDEO_CX88_ALSA Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index e140996e6ee4..ff0f72340d69 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -16,12 +16,13 @@ config VIDEO_CX88 module will be called cx8800 config VIDEO_CX88_ALSA - tristate "ALSA DMA audio support" + tristate "Conexant 2388x DMA audio support" depends on VIDEO_CX88 && SND && EXPERIMENTAL select SND_PCM ---help--- This is a video4linux driver for direct (DMA) audio on - Conexant 2388x based TV cards. + Conexant 2388x based TV cards using ALSA. + It only works with boards with function 01 enabled. To check if your board supports, use lspci -n. If supported, you should see 1471:8801 or 1471:8811 -- cgit v1.2.3-59-g8ed1b From 2ae151911e31e6a012a46431cc515cc251242573 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 20 Mar 2006 13:59:42 -0300 Subject: V4L/DVB (3569): PATCH: switch cpia2 to mutexes and use ioctl 32 compat lib func Signed-off-by: Alan Cox Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cpia2/cpia2.h | 2 +- drivers/media/video/cpia2/cpia2_core.c | 40 +++++++++++++++---------------- drivers/media/video/cpia2/cpia2_v4l.c | 43 +++++++++++++++++----------------- 3 files changed, 43 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h index 95d3afa94a3d..8394283993f6 100644 --- a/drivers/media/video/cpia2/cpia2.h +++ b/drivers/media/video/cpia2/cpia2.h @@ -381,7 +381,7 @@ struct cpia2_fh { struct camera_data { /* locks */ - struct semaphore busy_lock; /* guard against SMP multithreading */ + struct mutex busy_lock; /* guard against SMP multithreading */ struct v4l2_prio_state prio; /* camera status */ diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c index 5dfb242d5b8c..fd771c7a2fe2 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/video/cpia2/cpia2_core.c @@ -2238,7 +2238,7 @@ struct camera_data *cpia2_init_camera_struct(void) memset(cam, 0, sizeof(struct camera_data)); cam->present = 1; - init_MUTEX(&cam->busy_lock); + mutex_init(&cam->busy_lock); init_waitqueue_head(&cam->wq_stream); return cam; @@ -2371,12 +2371,12 @@ long cpia2_read(struct camera_data *cam, } /* make this _really_ smp and multithread-safe */ - if (down_interruptible(&cam->busy_lock)) + if (mutex_lock_interruptible(&cam->busy_lock)) return -ERESTARTSYS; if (!cam->present) { LOG("%s: camera removed\n",__FUNCTION__); - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return 0; /* EOF */ } @@ -2389,34 +2389,34 @@ long cpia2_read(struct camera_data *cam, /* Copy cam->curbuff in case it changes while we're processing */ frame = cam->curbuff; if (noblock && frame->status != FRAME_READY) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EAGAIN; } if(frame->status != FRAME_READY) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); wait_event_interruptible(cam->wq_stream, !cam->present || (frame = cam->curbuff)->status == FRAME_READY); if (signal_pending(current)) return -ERESTARTSYS; /* make this _really_ smp and multithread-safe */ - if (down_interruptible(&cam->busy_lock)) { + if (mutex_lock_interruptible(&cam->busy_lock)) { return -ERESTARTSYS; } if(!cam->present) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return 0; } } /* copy data to user space */ if (frame->length > count) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EFAULT; } if (copy_to_user(buf, frame->data, frame->length)) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EFAULT; } @@ -2424,7 +2424,7 @@ long cpia2_read(struct camera_data *cam, frame->status = FRAME_EMPTY; - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return count; } @@ -2443,10 +2443,10 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp, return POLLERR; } - down(&cam->busy_lock); + mutex_lock(&cam->busy_lock); if(!cam->present) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return POLLHUP; } @@ -2456,16 +2456,16 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp, cam->params.camera_state.stream_mode); } - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); poll_wait(filp, &cam->wq_stream, wait); - down(&cam->busy_lock); + mutex_lock(&cam->busy_lock); if(!cam->present) status = POLLHUP; else if(cam->curbuff->status == FRAME_READY) status = POLLIN | POLLRDNORM; - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return status; } @@ -2488,18 +2488,18 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma) DBG("mmap offset:%ld size:%ld\n", start_offset, size); /* make this _really_ smp-safe */ - if (down_interruptible(&cam->busy_lock)) + if (mutex_lock_interruptible(&cam->busy_lock)) return -ERESTARTSYS; if (!cam->present) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -ENODEV; } if (size > cam->frame_size*cam->num_frames || (start_offset % cam->frame_size) != 0 || (start_offset+size > cam->frame_size*cam->num_frames)) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EINVAL; } @@ -2507,7 +2507,7 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma) while (size > 0) { page = kvirt_to_pa(pos); if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EAGAIN; } start += PAGE_SIZE; @@ -2519,7 +2519,7 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma) } cam->mmapped = true; - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return 0; } diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 08f8be345fa8..481e178ef56d 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -255,7 +255,7 @@ static int cpia2_open(struct inode *inode, struct file *file) return -ENODEV; } - if(down_interruptible(&cam->busy_lock)) + if(mutex_lock_interruptible(&cam->busy_lock)) return -ERESTARTSYS; if(!cam->present) { @@ -299,7 +299,7 @@ skip_init: cpia2_dbg_dump_registers(cam); err_return: - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return retval; } @@ -314,7 +314,7 @@ static int cpia2_close(struct inode *inode, struct file *file) struct camera_data *cam = video_get_drvdata(dev); struct cpia2_fh *fh = file->private_data; - down(&cam->busy_lock); + mutex_lock(&cam->busy_lock); if (cam->present && (cam->open_count == 1 @@ -347,7 +347,7 @@ static int cpia2_close(struct inode *inode, struct file *file) } } - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return 0; } @@ -523,11 +523,11 @@ static int sync(struct camera_data *cam, int frame_nr) return 0; } - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); wait_event_interruptible(cam->wq_stream, !cam->streaming || frame->status == FRAME_READY); - down(&cam->busy_lock); + mutex_lock(&cam->busy_lock); if (signal_pending(current)) return -ERESTARTSYS; if(!cam->present) @@ -1544,11 +1544,11 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file) if(frame < 0) { /* Wait for a frame to become available */ struct framebuf *cb=cam->curbuff; - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); wait_event_interruptible(cam->wq_stream, !cam->present || (cb=cam->curbuff)->status == FRAME_READY); - down(&cam->busy_lock); + mutex_lock(&cam->busy_lock); if (signal_pending(current)) return -ERESTARTSYS; if(!cam->present) @@ -1591,11 +1591,11 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file, return -ENOTTY; /* make this _really_ smp-safe */ - if (down_interruptible(&cam->busy_lock)) + if (mutex_lock_interruptible(&cam->busy_lock)) return -ERESTARTSYS; if (!cam->present) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -ENODEV; } @@ -1608,7 +1608,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file, struct cpia2_fh *fh = file->private_data; retval = v4l2_prio_check(&cam->prio, &fh->prio); if(retval) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return retval; } break; @@ -1618,7 +1618,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file, { struct cpia2_fh *fh = file->private_data; if(fh->prio != V4L2_PRIORITY_RECORD) { - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return -EBUSY; } break; @@ -1847,7 +1847,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file, break; } - up(&cam->busy_lock); + mutex_unlock(&cam->busy_lock); return retval; } @@ -1924,14 +1924,15 @@ static void reset_camera_struct_v4l(struct camera_data *cam) * The v4l video device structure initialized for this device ***/ static struct file_operations fops_template = { - .owner= THIS_MODULE, - .open= cpia2_open, - .release= cpia2_close, - .read= cpia2_v4l_read, - .poll= cpia2_v4l_poll, - .ioctl= cpia2_ioctl, - .llseek= no_llseek, - .mmap= cpia2_mmap, + .owner = THIS_MODULE, + .open = cpia2_open, + .release = cpia2_close, + .read = cpia2_v4l_read, + .poll = cpia2_v4l_poll, + .ioctl = cpia2_ioctl, + .llseek = no_llseek, + .compat_ioctl = v4l_compat_ioctl32, + .mmap = cpia2_mmap, }; static struct video_device cpia2_template = { -- cgit v1.2.3-59-g8ed1b From 5245953e1893152662dad47c87fa88213d5d09a1 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 22 Mar 2006 15:01:59 -0300 Subject: V4L/DVB (3571): Printk warning fixes On ppc64, u64 is `unsigned long' drivers/media/video/v4l2-common.c: In function `v4l_printk_ioctl_arg': drivers/media/video/v4l2-common.c:486: warning: cast from pointer to integer of different size drivers/media/video/v4l2-common.c:580: warning: long long int format, v4l2_std_id arg (arg 8) drivers/media/video/v4l2-common.c:625: warning: long long int format, v4l2_std_id arg (arg 8) drivers/media/video/v4l2-common.c:693: warning: long long int format, v4l2_std_id arg (arg 4) drivers/media/video/v4l2-common.c:910: warning: long long unsigned int format, long unsigned int a$ Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 9b029e4dbfb7..1717663d3e51 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -481,9 +481,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) prt_names(p->memory,v4l2_memory_names), p->m.userptr); printk ("%s: timecode= %02d:%02d:%02d type=%d, " - "flags=0x%08d, frames=%d, userbits=0x%08x\n", + "flags=0x%08d, frames=%d, userbits=0x%p", s,tc->hours,tc->minutes,tc->seconds, - tc->type, tc->flags, tc->frames, (__u32) tc->userbits); + tc->type, tc->flags, tc->frames, tc->userbits); break; } case VIDIOC_QUERYCAP: @@ -574,9 +574,10 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) { struct v4l2_input *p=arg; printk ("%s: index=%d, name=%s, type=%d, audioset=%d, " - "tuner=%d, std=%lld, status=%d\n", s, + "tuner=%d, std=%Ld, status=%d\n", s, p->index,p->name,p->type,p->audioset, - p->tuner,p->std, + p->tuner, + (unsigned long long)p->std, p->status); break; } @@ -620,9 +621,10 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) { struct v4l2_output *p=arg; printk ("%s: index=%d, name=%s,type=%d, audioset=%d, " - "modulator=%d, std=%lld\n", + "modulator=%d, std=%Ld\n", s,p->index,p->name,p->type,p->audioset, - p->modulator,p->std); + p->modulator, + (unsigned long long)p->std); break; } case VIDIOC_QUERYCTRL: @@ -686,8 +688,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) case VIDIOC_ENUMSTD: { struct v4l2_standard *p=arg; - printk ("%s: index=%d, id=%lld, name=%s, fps=%d/%d, framelines=%d\n", s, - p->index, p->id, p->name, + printk ("%s: index=%d, id=%Ld, name=%s, fps=%d/%d, " + "framelines=%d\n", s, p->index, + (unsigned long long)p->id, p->name, p->frameperiod.numerator, p->frameperiod.denominator, p->framelines); @@ -907,7 +910,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) { v4l2_std_id *p=arg; - printk ("%s: value=%llu\n", s, *p); + printk ("%s: value=%Lu\n", s, (unsigned long long)*p); break; } } -- cgit v1.2.3-59-g8ed1b From 5e805eff15b17e64d5a0913c9e4c816a96677398 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 23 Mar 2006 00:01:34 -0300 Subject: V4L/DVB (3572): Cxusb: conditionalize gpio write for the medion box This patch removes the (harmless) -ETIMEDOUT during device init for the DViCO FusionHDTV Bluebird boxes, by conditionalizing the gpio write inside cxusb_i2c_xfer to happen only for Medion boxes. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index e14bf43941e3..61d19ced495a 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -85,14 +85,15 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) for (i = 0; i < num; i++) { - switch (msg[i].addr) { - case 0x63: - cxusb_gpio_tuner(d,0); - break; - default: - cxusb_gpio_tuner(d,1); - break; - } + if (d->udev->descriptor.idVendor == USB_VID_MEDION) + switch (msg[i].addr) { + case 0x63: + cxusb_gpio_tuner(d,0); + break; + default: + cxusb_gpio_tuner(d,1); + break; + } /* read request */ if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { -- cgit v1.2.3-59-g8ed1b From afdebc94ea86168973102fa77128764ac034d569 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 23 Mar 2006 00:15:55 -0300 Subject: V4L/DVB (3573): Cxusb: remove FIXME: comment in bluebird_patch_dvico_firmware_download Removed the FIXME comment from bluebird_patch_dvico_firmware_download: /* FIXME: are we allowed to change the fw-data ? */ Yes, we are allowed. DViCO's Windows driver also does the same thing. A single firmware image is used to support all of the bluebird boxes. The firmware sets all devices to PID: d700. Instead of using that, the driver replaces the d700 with the cold PID+1 before the download. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 61d19ced495a..f9c99224d85e 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -411,7 +411,6 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) && fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { - /* FIXME: are we allowed to change the fw-data ? */ fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1; fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8; -- cgit v1.2.3-59-g8ed1b From 4d6e772d989c11af7d7e41095f976cff5eeb43f3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 23 Mar 2006 00:55:23 -0300 Subject: V4L/DVB (3574): Cxusb: fix debug messages - corrects the wording in some of the debug messages. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index f9c99224d85e..9f9adb77e7e3 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -81,7 +81,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) return -EAGAIN; if (num > 2) - warn("more than 2 i2c messages at a time is not handled yet. TODO."); + warn("more than two i2c messages at a time is not handled yet. TODO."); for (i = 0; i < num; i++) { @@ -109,7 +109,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) break; if (ibuf[0] != 0x08) - deb_info("i2c read could have been failed\n"); + deb_info("i2c read may have failed\n"); memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len); @@ -123,7 +123,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0) break; if (ibuf != 0x08) - deb_info("i2c write could have been failed\n"); + deb_info("i2c write may have failed\n"); } } -- cgit v1.2.3-59-g8ed1b From ae62e3d4a8194680023b47ab778bf1dcea8d6b42 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 23 Mar 2006 01:11:18 -0300 Subject: V4L/DVB (3575): Cxusb: fix i2c debug messages for bluebird devices Only the Medion boxes return 0x08 after an i2c read/write. The bluebird devices do not return anything at all. This patch conditionalizes the test for the 0x08 return code to produce a warning message when using the Medion box, only. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 4 ++-- drivers/media/dvb/dvb-usb/cxusb.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 9f9adb77e7e3..a14e737ec848 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -109,7 +109,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) break; if (ibuf[0] != 0x08) - deb_info("i2c read may have failed\n"); + deb_i2c("i2c read may have failed\n"); memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len); @@ -123,7 +123,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0) break; if (ibuf != 0x08) - deb_info("i2c write may have failed\n"); + deb_i2c("i2c write may have failed\n"); } } diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h index 087c99427853..c8ef77554b00 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.h +++ b/drivers/media/dvb/dvb-usb/cxusb.h @@ -6,6 +6,8 @@ extern int dvb_usb_cxusb_debug; #define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args) +#define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \ + dprintk(dvb_usb_cxusb_debug,0x01,args) /* usb commands - some of it are guesses, don't have a reference yet */ #define CMD_I2C_WRITE 0x08 -- cgit v1.2.3-59-g8ed1b From 8bf2f8e747700419cc5bbc56c4496774eb8f2f1f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 18 Mar 2006 21:31:00 -0300 Subject: V4L/DVB (3577): Cleanup audio input handling Cleanup audio input handling in bttv and tvaudio: - inputs were specified that were never used - mute was handled as a special input which led to confusing code - confusing naming made it difficult to see if the setting was for i2c or gpio. The old audiochip.h input names moved to tvaudio.h. Currently this is used both by tvaudio and msp3400 until the msp3400 implements the new msp3400-specific inputs. Detect in bttv the tvaudio and msp3400 i2c clients and use these client pointers to set the inputs directly instead of broadcasting the command. Removed AUDC_SET_INPUT. Now replaced by VIDIOC_S_AUDIO. This will be replaced again later by the new ROUTING commands. Removed VIDIOC_G_AUDIO implementations in i2c drivers: this command is a user level command and not to be used internally. It wasn't called at all anyway. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bt832.c | 1 - drivers/media/video/bt8xx/bttv-cards.c | 299 +++++++++++++++++----------- drivers/media/video/bt8xx/bttv-driver.c | 91 +++++---- drivers/media/video/bt8xx/bttv-i2c.c | 4 + drivers/media/video/bt8xx/bttv.h | 3 +- drivers/media/video/bt8xx/bttvp.h | 4 +- drivers/media/video/cs53l32a.c | 5 - drivers/media/video/cx25840/cx25840-audio.c | 1 - drivers/media/video/cx25840/cx25840-core.c | 11 - drivers/media/video/cx88/cx88.h | 1 - drivers/media/video/msp3400-driver.c | 104 +--------- drivers/media/video/msp3400-kthreads.c | 1 - drivers/media/video/saa7115.c | 1 - drivers/media/video/saa7134/saa7134.h | 1 - drivers/media/video/tda7432.c | 1 - drivers/media/video/tda9875.c | 3 - drivers/media/video/tuner-core.c | 1 - drivers/media/video/tvaudio.c | 67 +++++-- drivers/media/video/tveeprom.c | 30 +-- drivers/media/video/v4l2-common.c | 2 - drivers/media/video/wm8775.c | 5 - include/media/audiochip.h | 14 -- include/media/tvaudio.h | 30 +++ include/media/v4l2-common.h | 11 +- 24 files changed, 350 insertions(+), 341 deletions(-) create mode 100644 include/media/tvaudio.h (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bt832.c b/drivers/media/video/bt8xx/bt832.c index f1309d94e96e..a51876137880 100644 --- a/drivers/media/video/bt8xx/bt832.c +++ b/drivers/media/video/bt8xx/bt832.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include "bttv.h" diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index e869bfbab378..f209a7492051 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -39,6 +39,7 @@ #include "bttvp.h" #include +#include /* fwd decl */ static void boot_msp34xx(struct bttv *btv, int pin); @@ -336,7 +337,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 0, 0, 0, 10 }, + .gpiomux = { 2, 0, 0, 0 }, + .gpiomute = 10, .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -350,7 +352,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4 }, + .gpiomux = { 0, 1, 2, 3 }, + .gpiomute = 4, .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -364,7 +367,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 4, 0, 2, 3, 1 }, + .gpiomux = { 4, 0, 2, 3 }, + .gpiomute = 1, .no_msp34xx = 1, .needs_tvaudio = 1, .tuner_type = TUNER_PHILIPS_NTSC, @@ -383,7 +387,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0 }, + .gpiomux = { 0 }, .needs_tvaudio = 0, .tuner_type = 4, .tuner_addr = ADDR_UNSET, @@ -397,7 +401,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 3, .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0, 1, 0, 1, 3 }, + .gpiomux = { 0, 1, 0, 1 }, + .gpiomute = 3, .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -411,7 +416,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 3, .muxsel = { 2, 3, 1, 1 }, .gpiomask = 0x0f, - .audiomux = { 0x0c, 0x04, 0x08, 0x04, 0 }, + .gpiomux = { 0x0c, 0x04, 0x08, 0x04 }, /* 0x04 for some cards ?? */ .needs_tvaudio = 1, .tuner_type = -1, @@ -428,7 +433,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 3, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, - .audiomux = { 0 }, + .gpiomux = { 0 }, .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -444,7 +449,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xc00, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0xc00, 0x800, 0x400, 0xc00, 0 }, + .gpiomux = { 0, 0xc00, 0x800, 0x400 }, + .gpiomute = 0xc00, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -459,7 +465,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 3, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 1, 2, 3, 0 }, + .gpiomux = { 1, 1, 2, 3 }, .needs_tvaudio = 0, .pll = PLL_28, .tuner_type = TUNER_TEMIC_PAL, @@ -474,7 +480,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x0f, /* old: 7 */ .muxsel = { 2, 0, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4 }, + .gpiomux = { 0, 1, 2, 3 }, + .gpiomute = 4, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -489,7 +496,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x3014f, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x20001,0x10001, 0, 0,10 }, + .gpiomux = { 0x20001,0x10001, 0, 0 }, + .gpiomute = 10, .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -505,7 +513,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 13, 14, 11, 7, 0, 0 }, + .gpiomux = { 13, 14, 11, 7 }, .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -519,7 +527,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 13, 14, 11, 7, 0, 0 }, + .gpiomux = { 13, 14, 11, 7 }, .needs_tvaudio = 1, .msp34xx_alt = 1, .pll = PLL_28, @@ -537,7 +545,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 2, 1, 3, 4 }, /* old: {0, 1, 2, 3, 4} */ + .gpiomux = { 0, 2, 1, 3 }, /* old: {0, 1, 2, 3, 4} */ + .gpiomute = 4, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -552,7 +561,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0 , 0, 1 , 0, 10 }, + .gpiomux = { 0, 0, 1, 0 }, + .gpiomute = 10, .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -570,10 +580,11 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 3, 1, 1 }, #if 0 /* old */ - .audiomux = { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }, + .gpiomux = { 0x01c000, 0, 0x018000, 0x014000, 0x002000 }, #else /* 2003-10-20 by "Anton A. Arapov" */ - .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 }, + .gpiomux = { 0x001e00, 0, 0x018000, 0x014000 }, + .gpiomute = 0x002000, #endif .needs_tvaudio = 1, .pll = PLL_28, @@ -587,7 +598,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x8300f8, .muxsel = { 2, 3, 1, 1,0 }, - .audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007 }, + .gpiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007 }, + .gpiomute = 0xcfa007, .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -603,7 +615,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 0, 0, 0, 0 }, + .gpiomux = { 1, 0, 0, 0 }, .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -617,7 +629,7 @@ struct tvcard bttv_tvcards[] = { .svhs = -1, .gpiomask = 0x8dff00, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0 }, + .gpiomux = { 0 }, .no_msp34xx = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -644,7 +656,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 }, + .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, + .gpiomute = 0x1800, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, @@ -658,7 +671,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xc00, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 0x800, 0x400, 0xc00, 0 }, + .gpiomux = { 0, 1, 0x800, 0x400 }, + .gpiomute = 0xc00, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -674,7 +688,7 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 7, .muxsel = { 2, 3, -1 }, .digital_mode = DIGITAL_MODE_CAMERA, - .audiomux = { 0, 0, 0, 0, 0 }, + .gpiomux = { 0, 0, 0, 0 }, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = TUNER_ALPS_TSBB5_PAL_I, @@ -691,7 +705,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xe00, .muxsel = { 2, 3, 1, 1 }, - .audiomux = {0x400, 0x400, 0x400, 0x400, 0xc00 }, + .gpiomux = {0x400, 0x400, 0x400, 0x400 }, + .gpiomute = 0xc00, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -707,7 +722,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x1f0fff, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000 }, + .gpiomux = { 0x20000, 0x30000, 0x10000, 0 }, + .gpiomute = 0x40000, .needs_tvaudio = 0, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, @@ -722,7 +738,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 3, .gpiomask = 7, .muxsel = { 2, 0, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4 }, + .gpiomux = { 0, 1, 2, 3 }, + .gpiomute = 4, .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -736,7 +753,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 }, + .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, + .gpiomute = 0x1800, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_SECAM, .tuner_addr = ADDR_UNSET, @@ -752,7 +770,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x1f0fff, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000 }, + .gpiomux = { 0x20000, 0x30000, 0x10000, 0x00000 }, + .gpiomute = 0x40000, .needs_tvaudio = 0, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, @@ -799,7 +818,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 1, /* was: 4 */ .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0}, - .audiomux = { 0 }, + .gpiomux = { 0 }, .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -815,7 +834,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x1800, /* 0x8dfe00 */ .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 }, + .gpiomux = { 0, 0x0800, 0x1000, 0x1000 }, + .gpiomute = 0x1800, .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -829,7 +849,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 3, .gpiomask = 1, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 0, 0, 0, 0 }, + .gpiomux = { 1, 0, 0, 0 }, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, @@ -845,7 +865,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0 }, + .gpiomux = { 0 }, .needs_tvaudio = 0, .tuner_type = 4, .tuner_addr = ADDR_UNSET, @@ -859,7 +879,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xffff00, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x500, 0, 0x300, 0x900, 0x900 }, + .gpiomux = { 0x500, 0, 0x300, 0x900 }, + .gpiomute = 0x900, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, @@ -875,11 +896,12 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */ #if 0 .gpiomask = 0xc33000, - .audiomux = { 0x422000,0x1000,0x0000,0x620000,0x800000 }, + .gpiomux = { 0x422000,0x1000,0x0000,0x620000,0x800000 }, #else /* Alexander Varakin [stereo version] */ .gpiomask = 0xb33000, - .audiomux = { 0x122000,0x1000,0x0000,0x620000,0x800000 }, + .gpiomux = { 0x122000,0x1000,0x0000,0x620000 }, + .gpiomute = 0x800000, #endif /* Audio Routing for "WinFast 2000 XP" (no tv stereo !) gpio23 -- hef4052:nEnable (0x800000) @@ -909,7 +931,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 }, + .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, + .gpiomute = 0x1800, .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -925,7 +948,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 }, + .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, + .gpiomute = 0x1800, .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -940,7 +964,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xff, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, + .gpiomux = { 0x21, 0x20, 0x24, 0x2c }, + .gpiomute = 0x29, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = -1, @@ -955,7 +980,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x551e00, .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 }, + .gpiomux = { 0x551400, 0x551200, 0, 0 }, + .gpiomute = 0x551c00, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = 1, @@ -971,7 +997,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x03000F, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 0xd0001, 0, 0, 1 }, + .gpiomux = { 2, 0xd0001, 0, 0 }, + .gpiomute = 1, .needs_tvaudio = 0, .pll = PLL_28, .tuner_type = -1, @@ -988,7 +1015,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 4, 0, 2, 3, 1 }, + .gpiomux = { 4, 0, 2, 3 }, + .gpiomute = 1, .no_msp34xx = 1, .needs_tvaudio = 1, .tuner_type = TUNER_PHILIPS_NTSC, @@ -1005,7 +1033,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 13, 4, 11, 7, 0, 0 }, + .gpiomux = { 13, 4, 11, 7 }, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -1022,7 +1050,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0, 0, 0, 0}, + .gpiomux = { 0, 0, 0, 0}, .needs_tvaudio = 1, .no_msp34xx = 1, .pll = PLL_28, @@ -1038,7 +1066,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xe00b, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc }, + .gpiomux = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0 }, + .gpiomute = 0xff3ffc, .no_msp34xx = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -1054,7 +1083,8 @@ struct tvcard bttv_tvcards[] = { .svhs = -1, .gpiomask = 3, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 1, 0, 2, 3 }, + .gpiomux = { 1, 1, 0, 2 }, + .gpiomute = 3, .no_msp34xx = 1, .pll = PLL_NONE, .tuner_type = -1, @@ -1069,7 +1099,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 3, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, - .audiomux = { 0 }, + .gpiomux = { 0 }, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = -1, @@ -1084,7 +1114,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xbcf03f, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f }, + .gpiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0 }, + .gpiomute = 0xbcb03f, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = 21, @@ -1099,7 +1130,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x70000, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000, 0x20000 }, + .gpiomux = { 0x20000, 0x30000, 0x10000, 0 }, + .gpiomute = 0x40000, .needs_tvaudio = 1, .no_msp34xx = 1, .pll = PLL_35, @@ -1118,7 +1150,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, - .audiomux = {2,0,0,0,1 }, + .gpiomux = {2,0,0,0 }, + .gpiomute = 1, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -1133,7 +1166,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x010f00, .muxsel = {2, 3, 0, 0 }, - .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 }, + .gpiomux = {0x10000, 0, 0x10000, 0 }, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = TUNER_ALPS_TSHC6_NTSC, @@ -1150,7 +1183,8 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 0xAA0000, .muxsel = { 2,3,1,1,-1 }, .digital_mode = DIGITAL_MODE_CAMERA, - .audiomux = { 0x20000, 0, 0x80000, 0x80000, 0xa8000, 0x46000 }, + .gpiomux = { 0x20000, 0, 0x80000, 0x80000 }, + .gpiomute = 0xa8000, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL_I, @@ -1175,7 +1209,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 7, .muxsel = { 2, 0, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4 }, + .gpiomux = { 0, 1, 2, 3 }, + .gpiomute = 4, .pll = PLL_28, .tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */, .tuner_addr = ADDR_UNSET, @@ -1192,7 +1227,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 3, .gpiomask = 0x03000F, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 0xd0001, 0, 0, 10 }, + .gpiomux = { 1, 0xd0001, 0, 0 }, + .gpiomute = 10, /* sound path (5 sources): MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable) 0= ext. Audio IN @@ -1218,7 +1254,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x1c, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0, 0x10, 8, 4 }, + .gpiomux = { 0, 0, 0x10, 8 }, + .gpiomute = 4, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, @@ -1230,7 +1267,7 @@ struct tvcard bttv_tvcards[] = { /* Tim Röstermundt in de.comp.os.unix.linux.hardware: options bttv card=0 pll=1 radio=1 gpiomask=0x18e0 - audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff + gpiomux =0x44c71f,0x44d71f,0,0x44d71f,0x44dfff options tuner type=5 */ .name = "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]", .video_inputs = 4, @@ -1239,7 +1276,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x18e0, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x0000,0x0800,0x1000,0x1000,0x18e0 }, + .gpiomux = { 0x0000,0x0800,0x1000,0x1000 }, + .gpiomute = 0x18e0, /* For cards with tda9820/tda9821: 0x0000: Tuner normal stereo 0x0080: Tuner A2 SAP (second audio program = Zweikanalton) @@ -1259,7 +1297,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xF, .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 2, 0, 0, 0, 10 }, + .gpiomux = { 2, 0, 0, 0 }, + .gpiomute = 10, .needs_tvaudio = 0, .pll = PLL_28, .tuner_type = TUNER_TEMIC_PAL, @@ -1277,7 +1316,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 }, + .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, + .gpiomute = 0x1800, .pll = PLL_28, .tuner_type = 5, .tuner_addr = ADDR_UNSET, @@ -1294,7 +1334,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 1, .gpiomask = 0, .muxsel = { 3, 1 }, - .audiomux = { 0 }, + .gpiomux = { 0 }, .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_35, @@ -1311,7 +1351,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xe00, .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 }, + .gpiomux = { 0x400, 0x400, 0x400, 0x400 }, + .gpiomute = 0x800, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = TUNER_TEMIC_4036FY5_NTSC, @@ -1327,7 +1368,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x03000F, .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 2, 0, 0, 0, 1 }, + .gpiomux = { 2, 0, 0, 0 }, + .gpiomute = 1, .pll = PLL_28, .tuner_type = 0, .tuner_addr = ADDR_UNSET, @@ -1344,7 +1386,8 @@ struct tvcard bttv_tvcards[] = { .svhs = -1, .gpiomask = 11, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 0, 0, 1, 8 }, + .gpiomux = { 2, 0, 0, 1 }, + .gpiomute = 8, .pll = PLL_35, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, @@ -1359,7 +1402,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 1, .gpiomask = 0xF, .muxsel = { 2, 2 }, - .audiomux = { }, + .gpiomux = { }, .no_msp34xx = 1, .needs_tvaudio = 0, .pll = PLL_28, @@ -1378,7 +1421,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xFF, .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 1, 0, 4, 4, 9 }, + .gpiomux = { 1, 0, 4, 4 }, + .gpiomute = 9, .needs_tvaudio = 0, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, @@ -1394,7 +1438,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xf03f, .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe }, + .gpiomux = { 0xbffe, 0, 0xbfff, 0 }, + .gpiomute = 0xbffe, .pll = PLL_28, .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, .tuner_addr = ADDR_UNSET, @@ -1411,7 +1456,7 @@ struct tvcard bttv_tvcards[] = { .svhs = -1, .gpiomask = 1, .muxsel = { 2, 3, 0, 1 }, - .audiomux = { 0, 0, 1, 0, 0 }, + .gpiomux = { 0, 0, 1, 0 }, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, @@ -1430,7 +1475,8 @@ struct tvcard bttv_tvcards[] = { /* Radio changed from 1e80 to 0x800 to make FlyVideo2000S in .hu happy (gm)*/ /* -dk-???: set mute=0x1800 for tda9874h daughterboard */ - .audiomux = { 0x0000,0x0800,0x1000,0x1000,0x1800, 0x1080 }, + .gpiomux = { 0x0000,0x0800,0x1000,0x1000 }, + .gpiomute = 0x1800, .audio_hook = fv2000s_audio, .no_msp34xx = 1, .no_tda9875 = 1, @@ -1448,7 +1494,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0xffff00, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x500, 0x500, 0x300, 0x900, 0x900 }, + .gpiomux = { 0x500, 0x500, 0x300, 0x900 }, + .gpiomute = 0x900, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, @@ -1465,7 +1512,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x010f00, .muxsel = {2, 3, 0, 0 }, - .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 }, + .gpiomux = {0x10000, 0, 0x10000, 0 }, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = TUNER_SHARP_2U5JF5540_NTSC, @@ -1486,7 +1533,8 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 0x4f8a00, /* 0x100000: 1=MSP enabled (0=disable again) * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */ - .audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff}, + .gpiomux = {0x947fff, 0x987fff,0x947fff,0x947fff }, + .gpiomute = 0x947fff, /* tvtuner, radio, external,internal, mute, stereo * tuner, Composit, SVid, Composit-on-Svid-adapter */ .muxsel = { 2, 3 ,0 ,1 }, @@ -1518,7 +1566,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0, 11, 7, 13, 0 }, /* TV and Radio with same GPIO ! */ + .gpiomux = { 0, 0, 11, 7 }, /* TV and Radio with same GPIO ! */ + .gpiomute = 13, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = 25, @@ -1557,7 +1606,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x3f, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x01, 0x00, 0x03, 0x03, 0x09, 0x02 }, + .gpiomux = { 0x01, 0x00, 0x03, 0x03 }, + .gpiomute = 0x09, .needs_tvaudio = 1, .no_msp34xx = 1, .no_tda9875 = 1, @@ -1586,7 +1636,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 4, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, - .audiomux = { 0 }, + .gpiomux = { 0 }, .needs_tvaudio = 0, .tuner_type = -1, .tuner_addr = ADDR_UNSET, @@ -1618,7 +1668,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x1C800F, /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */ .muxsel = { 2, 1, 1, }, - .audiomux = { 0, 1, 2, 2, 4 }, + .gpiomux = { 0, 1, 2, 2 }, + .gpiomute = 4, .needs_tvaudio = 0, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, @@ -1637,7 +1688,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x140007, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4, 0 }, + .gpiomux = { 0, 1, 2, 3 }, + .gpiomute = 4, .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -1651,7 +1703,7 @@ struct tvcard bttv_tvcards[] = { .svhs = -1, .gpiomask = 0, .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0 }, + .gpiomux = { 0 }, .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, @@ -1667,13 +1719,14 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, /* Tuner, SVid, SVHS, SVid to SVHS connector */ - .audiomux = { 0 ,0 ,4, 4,4,4},/* Yes, this tuner uses the same audio output for TV and FM radio! + .gpiomux = { 0, 0, 4, 4 },/* Yes, this tuner uses the same audio output for TV and FM radio! * This card lacks external Audio In, so we mute it on Ext. & Int. * The PCB can take a sbx1637/sbx1673, wiring unknown. * This card lacks PCI subsystem ID, sigh. - * audiomux=1: lower volume, 2+3: mute + * gpiomux =1: lower volume, 2+3: mute * btwincap uses 0x80000/0x80003 */ + .gpiomute = 4, .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, @@ -1720,7 +1773,7 @@ struct tvcard bttv_tvcards[] = { .radio_addr = ADDR_UNSET, .gpiomask = 7, - .audiomux = {7}, + .gpiomux = {7}, }, [BTTV_BOARD_GVBCTV5PCI] = { .name = "IODATA GV-BCTV5/PCI", @@ -1730,7 +1783,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x0f0f80, .muxsel = {2, 3, 1, 0 }, - .audiomux = {0x030000, 0x010000, 0, 0, 0x020000, 0}, + .gpiomux = {0x030000, 0x010000, 0, 0 }, + .gpiomute = 0x020000, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_NTSC_M, @@ -1960,7 +2014,7 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 2, /* TV, Comp1, Composite over SVID con, SVID */ .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 2, 0, 0, 0 }, + .gpiomux = { 2, 2, 0, 0 }, .pll = PLL_28, .has_radio = 1, .tuner_type = TUNER_PHILIPS_PAL, @@ -1984,7 +2038,8 @@ struct tvcard bttv_tvcards[] = { .svhs = -1, .gpiomask = 7, .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 1, 2, 3, 4}, + .gpiomux = { 0, 1, 2, 3}, + .gpiomute = 4, .needs_tvaudio = 1, .tuner_type = 5, .tuner_addr = ADDR_UNSET, @@ -2016,7 +2071,7 @@ struct tvcard bttv_tvcards[] = { .svhs = -1, .gpiomask = 0, .muxsel = { 2, 3 }, - .audiomux = { 0 }, + .gpiomux = { 0 }, .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, @@ -2035,7 +2090,8 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 0x001e8007, .muxsel = { 2, 3, 1, 0 }, /* Tuner, Radio, external, internal, off, on */ - .audiomux = { 0x08, 0x0f, 0x0a, 0x08, 0x0f, 0x08 }, + .gpiomux = { 0x08, 0x0f, 0x0a, 0x08 }, + .gpiomute = 0x0f, .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, @@ -2152,7 +2208,7 @@ struct tvcard bttv_tvcards[] = { .svhs = -1, .gpiomask = 0, .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0 }, + .gpiomux = { 0 }, .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, @@ -2169,7 +2225,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 3, .gpiomask = 0x00, .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -2184,7 +2240,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 3, .gpiomask = 0x00, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -2204,7 +2260,7 @@ struct tvcard bttv_tvcards[] = { via the upper nibble of muxsel. here: used for xternal video-mux */ .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 }, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -2222,7 +2278,7 @@ struct tvcard bttv_tvcards[] = { via the upper nibble of muxsel. here: used for xternal video-mux */ .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 }, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -2310,7 +2366,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 3, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 1, 1, 1, 1, 0 }, + .gpiomux = { 1, 1, 1, 1 }, .needs_tvaudio = 1, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, @@ -2341,7 +2397,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x008007, .muxsel = { 2, 3, 0, 0 }, - .audiomux = { 0, 0, 0, 0, 0x000003, 0 }, + .gpiomux = { 0, 0, 0, 0 }, + .gpiomute = 0x000003, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, @@ -2377,7 +2434,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .gpiomask = 0x68, .muxsel = { 2, 3, 1 }, - .audiomux = { 0x68, 0x68, 0x61, 0x61, 0x00 }, + .gpiomux = { 0x68, 0x68, 0x61, 0x61 }, .pll = PLL_28, }, @@ -2392,7 +2449,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x008007, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 2, 3 }, + .gpiomux = { 0, 1, 2, 2 }, + .gpiomute = 3, .needs_tvaudio = 0, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, @@ -2417,7 +2475,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, .muxsel = {2,2,2,2},/*878A input is always MUX0, see above.*/ - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .pll = PLL_28, .needs_tvaudio = 0, .muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/ @@ -2435,7 +2493,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x0000000f, .muxsel = { 2, 1, 1 }, - .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00 }, + .gpiomux = { 0x02, 0x00, 0x00, 0x00 }, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -2491,7 +2549,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 }, .muxsel_hook = sigmaSQ_muxsel, - .audiomux = { 0 }, + .gpiomux = { 0 }, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = -1, @@ -2508,7 +2566,7 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 0x0, .muxsel = { 2, 2, 2, 2 }, .muxsel_hook = sigmaSLC_muxsel, - .audiomux = { 0 }, + .gpiomux = { 0 }, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = -1, @@ -2526,7 +2584,8 @@ struct tvcard bttv_tvcards[] = { .svhs = -1, .gpiomask = 0xFF, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 0, 0, 0, 10 }, + .gpiomux = { 2, 0, 0, 0 }, + .gpiomute = 10, .needs_tvaudio = 0, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, @@ -2560,7 +2619,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x3f, .muxsel = {2, 3, 1, 0 }, - .audiomux = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }, + .gpiomux = {0x31, 0x31, 0x31, 0x31 }, + .gpiomute = 0x31, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_NTSC_M, @@ -2583,7 +2643,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .gpiomask = 0x008007, - .audiomux = { 0, 0x000001,0,0, 0 }, + .gpiomux = { 0, 0x000001,0,0 }, .needs_tvaudio = 1, .has_radio = 1, }, @@ -2693,7 +2753,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .muxsel = { 2, 3, 1 }, .gpiomask = 0x00e00007, - .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 }, + .gpiomux = { 0x00400005, 0, 0x00000001, 0 }, + .gpiomute = 0x00c00007, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -2709,7 +2770,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x01fe00, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 }, + .gpiomux = { 0x001e00, 0, 0x018000, 0x014000 }, + .gpiomute = 0x002000, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = TUNER_YMEC_TVF66T5_B_DFF, @@ -2726,7 +2788,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x001c0007, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 2, 3 }, + .gpiomux = { 0, 1, 2, 2 }, + .gpiomute = 3, .needs_tvaudio = 0, .pll = PLL_28, .tuner_type = TUNER_TENA_9533_DI, @@ -2745,7 +2808,8 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 0x01fe00, .muxsel = { 2,3,1,1,-1 }, .digital_mode = DIGITAL_MODE_CAMERA, - .audiomux = { 0x00400, 0x10400, 0x04400, 0x80000, 0x12400, 0x46000 }, + .gpiomux = { 0x00400, 0x10400, 0x04400, 0x80000 }, + .gpiomute = 0x12400, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = TUNER_LG_PAL_FM, @@ -2763,7 +2827,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x3f, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, + .gpiomux = { 0x21, 0x20, 0x24, 0x2c }, + .gpiomute = 0x29, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = TUNER_YMEC_TVF_5533MF, @@ -2797,7 +2862,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 2, 0, 0, 0, 1 }, + .gpiomux = { 2, 0, 0, 0 }, + .gpiomute = 1, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = 2, @@ -2813,7 +2879,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x108007, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 100000, 100002, 100002, 100000 }, + .gpiomux = { 100000, 100002, 100002, 100000 }, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -2853,7 +2919,8 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4 }, + .gpiomux = { 0, 1, 2, 3 }, + .gpiomute = 4, .tuner_type = TUNER_TEMIC_4009FR5_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -2925,20 +2992,20 @@ void __devinit bttv_idcard(struct bttv *btv) if (UNSET != audiomux[0]) { gpiobits = 0; for (i = 0; i < 5; i++) { - bttv_tvcards[btv->c.type].audiomux[i] = audiomux[i]; + bttv_tvcards[btv->c.type].gpiomux[i] = audiomux[i]; gpiobits |= audiomux[i]; } } else { gpiobits = audioall; for (i = 0; i < 5; i++) { - bttv_tvcards[btv->c.type].audiomux[i] = audioall; + bttv_tvcards[btv->c.type].gpiomux[i] = audioall; } } bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits; printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=", btv->c.nr,bttv_tvcards[btv->c.type].gpiomask); for (i = 0; i < 5; i++) { - printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].audiomux[i]); + printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]); } printk("\n"); } @@ -3796,18 +3863,18 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm) { /* fix up our card entry */ if(norm==VIDEO_MODE_NTSC) { - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x957fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x957fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x957fff; dprintk("bttv_tda9880_setnorm to NTSC\n"); } else { - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x947fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x947fff; dprintk("bttv_tda9880_setnorm to PAL\n"); } /* set GPIO according */ gpio_bits(bttv_tvcards[btv->c.type].gpiomask, - bttv_tvcards[btv->c.type].audiomux[btv->audio]); + bttv_tvcards[btv->c.type].gpiomux[btv->audio]); } diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 71535775f2e8..be567ec9e145 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -36,6 +36,7 @@ #include #include "bttvp.h" #include +#include #include @@ -926,45 +927,65 @@ video_mux(struct bttv *btv, unsigned int input) static char *audio_modes[] = { "audio: tuner", "audio: radio", "audio: extern", - "audio: intern", "audio: off" + "audio: intern", "audio: mute" }; static int -audio_mux(struct bttv *btv, int mode) +audio_mux(struct bttv *btv, int input, int mute) { - int val,mux,i2c_mux,signal; + int gpio_val, signal; + struct v4l2_audio aud_input; + struct v4l2_control ctrl; + struct i2c_client *c; + memset(&aud_input, 0, sizeof(aud_input)); gpio_inout(bttv_tvcards[btv->c.type].gpiomask, bttv_tvcards[btv->c.type].gpiomask); signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC; - switch (mode) { - case AUDIO_MUTE: - btv->audio |= AUDIO_MUTE; - break; - case AUDIO_UNMUTE: - btv->audio &= ~AUDIO_MUTE; - break; - case AUDIO_TUNER: - case AUDIO_RADIO: - case AUDIO_EXTERN: - case AUDIO_INTERN: - btv->audio &= AUDIO_MUTE; - btv->audio |= mode; - } - i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio; - if (btv->opt_automute && !signal && !btv->radio_user) - mux = AUDIO_OFF; - - val = bttv_tvcards[btv->c.type].audiomux[mux]; - gpio_bits(bttv_tvcards[btv->c.type].gpiomask,val); + btv->mute = mute; + btv->audio = input; + + /* automute */ + mute = mute || (btv->opt_automute && !signal && !btv->radio_user); + + if (mute) + gpio_val = bttv_tvcards[btv->c.type].gpiomute; + else + gpio_val = bttv_tvcards[btv->c.type].gpiomux[input]; + aud_input.index = btv->audio; + + gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val); if (bttv_gpio) - bttv_gpio_tracking(btv,audio_modes[mux]); - if (!in_interrupt()) - bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(i2c_mux)); + bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]); + if (in_interrupt()) + return 0; + + ctrl.id = V4L2_CID_AUDIO_MUTE; + /* take automute into account, just btv->mute is not enough */ + ctrl.value = mute; + bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl); + c = btv->i2c_msp34xx_client; + if (c) + c->driver->command(c, VIDIOC_S_AUDIO, &aud_input); + c = btv->i2c_tvaudio_client; + if (c) + c->driver->command(c, VIDIOC_S_AUDIO, &aud_input); return 0; } +static inline int +audio_mute(struct bttv *btv, int mute) +{ + return audio_mux(btv, btv->audio, mute); +} + +static inline int +audio_input(struct bttv *btv, int input) +{ + return audio_mux(btv, input, btv->mute); +} + static void i2c_vidiocschan(struct bttv *btv) { @@ -1023,8 +1044,8 @@ set_input(struct bttv *btv, unsigned int input) } else { video_mux(btv,input); } - audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ? - AUDIO_TUNER : AUDIO_EXTERN)); + audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ? + TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN)); set_tvnorm(btv,btv->tvnorm); i2c_vidiocschan(btv); } @@ -1236,10 +1257,10 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) case V4L2_CID_AUDIO_MUTE: if (c->value) { va.flags |= VIDEO_AUDIO_MUTE; - audio_mux(btv, AUDIO_MUTE); + audio_mute(btv, 1); } else { va.flags &= ~VIDEO_AUDIO_MUTE; - audio_mux(btv, AUDIO_UNMUTE); + audio_mute(btv, 0); } break; @@ -1654,7 +1675,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return -EINVAL; mutex_lock(&btv->lock); - audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE); + audio_mute(btv, (v->flags&VIDEO_AUDIO_MUTE) ? 1 : 0); bttv_call_i2c_clients(btv,cmd,v); /* card specific hooks */ @@ -3163,8 +3184,8 @@ static int radio_open(struct inode *inode, struct file *file) file->private_data = btv; - bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type); - audio_mux(btv,AUDIO_RADIO); + bttv_call_i2c_clients(btv,AUDC_SET_RADIO,NULL); + audio_input(btv,TVAUDIO_INPUT_RADIO); mutex_unlock(&btv->lock); return 0; @@ -3750,7 +3771,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) bttv_irq_switch_video(btv); if ((astat & BT848_INT_HLOCK) && btv->opt_automute) - audio_mux(btv, -1); + audio_mute(btv, btv->mute); /* trigger automute */ if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) { printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr, @@ -4051,7 +4072,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, bt848_contrast(btv,32768); bt848_hue(btv,32768); bt848_sat(btv,32768); - audio_mux(btv,AUDIO_MUTE); + audio_mute(btv, 1); set_input(btv,0); } diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index 614c12018557..4b562b386fcf 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c @@ -302,6 +302,10 @@ static int attach_inform(struct i2c_client *client) if (!client->driver->command) return 0; + if (client->driver->id == I2C_DRIVERID_MSP3400) + btv->i2c_msp34xx_client = client; + if (client->driver->id == I2C_DRIVERID_TVAUDIO) + btv->i2c_tvaudio_client = client; if (btv->tuner_type != UNSET) { struct tuner_setup tun_setup; diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index ebde3e8219cf..3a23265c1538 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -234,7 +234,8 @@ struct tvcard unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO u32 gpiomask; u32 muxsel[16]; - u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ + u32 gpiomux[4]; /* Tuner, Radio, external, internal */ + u32 gpiomute; /* GPIO mute setting */ u32 gpiomask2; /* GPIO MUX mask */ /* i2c audio flags */ diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 12223a203960..ee989d2e15d9 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -41,7 +41,6 @@ #include #include -#include #include #include #include @@ -299,6 +298,8 @@ struct bttv { int i2c_state, i2c_rc; int i2c_done; wait_queue_head_t i2c_queue; + struct i2c_client *i2c_msp34xx_client; + struct i2c_client *i2c_tvaudio_client; /* video4linux (1) */ struct video_device *video_dev; @@ -321,6 +322,7 @@ struct bttv { /* video state */ unsigned int input; unsigned int audio; + unsigned int mute; unsigned long freq; int tvnorm,hue,contrast,bright,saturation; struct v4l2_framebuffer fbuf; diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c index 8739c64785ef..bc3331870240 100644 --- a/drivers/media/video/cs53l32a.c +++ b/drivers/media/video/cs53l32a.c @@ -75,11 +75,6 @@ static int cs53l32a_command(struct i2c_client *client, unsigned int cmd, cs53l32a_write(client, 0x01, 0x01 + (input->index << 4)); break; - case VIDIOC_G_AUDIO: - memset(input, 0, sizeof(*input)); - input->index = (cs53l32a_read(client, 0x01) >> 4) & 3; - break; - case VIDIOC_G_CTRL: if (ctrl->id == V4L2_CID_AUDIO_MUTE) { ctrl->value = (cs53l32a_read(client, 0x03) & 0xc0) != 0; diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index cb9a7981e408..a4540e858f21 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c @@ -18,7 +18,6 @@ #include #include -#include #include #include "cx25840.h" diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index bcb7ef85eb23..7aee37645d63 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include "cx25840.h" @@ -764,16 +763,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, return set_input(client, state->vid_input, input->index); } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *input = arg; - - memset(input, 0, sizeof(*input)); - input->index = state->aud_input; - input->capability = V4L2_AUDCAP_STEREO; - break; - } - case VIDIOC_S_FREQUENCY: input_change(client); break; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 5b2e499eab22..326a25f147f6 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -27,7 +27,6 @@ #include #include -#include #include #include diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 11ea9765769c..bd0b036c5cab 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include #include #include "msp3400.h" @@ -585,51 +585,12 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp_state *state = i2c_get_clientdata(client); - u16 *sarg = arg; int scart = 0; if (msp_debug >= 2) v4l_i2c_print_ioctl(client, cmd); switch (cmd) { - case AUDC_SET_INPUT: - if (*sarg == state->input) - break; - state->input = *sarg; - switch (*sarg) { - case AUDIO_RADIO: - /* Hauppauge uses IN2 for the radio */ - state->mode = MSP_MODE_FM_RADIO; - scart = SCART_IN2; - break; - case AUDIO_EXTERN_1: - /* IN1 is often used for external input ... */ - state->mode = MSP_MODE_EXTERN; - scart = SCART_IN1; - break; - case AUDIO_EXTERN_2: - /* ... sometimes it is IN2 through ;) */ - state->mode = MSP_MODE_EXTERN; - scart = SCART_IN2; - break; - case AUDIO_TUNER: - state->mode = -1; - break; - default: - if (*sarg & AUDIO_MUTE) - msp_set_scart(client, SCART_MUTE, 0); - break; - } - if (scart) { - state->rxsubchans = V4L2_TUNER_SUB_STEREO; - msp_set_scart(client, scart, 0); - msp_write_dsp(client, 0x000d, 0x1900); - if (state->opmode != OPMODE_AUTOSELECT) - msp_set_audmode(client); - } - msp_wake_thread(client); - break; - case AUDC_SET_RADIO: if (state->radio) return 0; @@ -750,82 +711,27 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; - - if (i->index != 0) - return -EINVAL; - - i->type = V4L2_INPUT_TYPE_TUNER; - switch (i->index) { - case AUDIO_RADIO: - strcpy(i->name, "Radio"); - break; - case AUDIO_EXTERN_1: - strcpy(i->name, "Extern 1"); - break; - case AUDIO_EXTERN_2: - strcpy(i->name, "Extern 2"); - break; - case AUDIO_TUNER: - strcpy(i->name, "Television"); - break; - default: - return -EINVAL; - } - return 0; - } - - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *a = arg; - - memset(a, 0, sizeof(*a)); - - switch (a->index) { - case AUDIO_RADIO: - strcpy(a->name, "Radio"); - break; - case AUDIO_EXTERN_1: - strcpy(a->name, "Extern 1"); - break; - case AUDIO_EXTERN_2: - strcpy(a->name, "Extern 2"); - break; - case AUDIO_TUNER: - strcpy(a->name, "Television"); - break; - default: - return -EINVAL; - } - - a->capability = V4L2_AUDCAP_STEREO; - a->mode = 0; /* TODO: add support for AVL */ - break; - } - case VIDIOC_S_AUDIO: { struct v4l2_audio *sarg = arg; switch (sarg->index) { - case AUDIO_RADIO: + case TVAUDIO_INPUT_RADIO: /* Hauppauge uses IN2 for the radio */ state->mode = MSP_MODE_FM_RADIO; scart = SCART_IN2; break; - case AUDIO_EXTERN_1: + case TVAUDIO_INPUT_EXTERN: /* IN1 is often used for external input ... */ state->mode = MSP_MODE_EXTERN; scart = SCART_IN1; break; - case AUDIO_EXTERN_2: + case TVAUDIO_INPUT_INTERN: /* ... sometimes it is IN2 through ;) */ state->mode = MSP_MODE_EXTERN; scart = SCART_IN2; break; - case AUDIO_TUNER: + case TVAUDIO_INPUT_TUNER: state->mode = -1; break; } diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 852ab6a115fa..71a944b447e2 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include "msp3400.h" diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index b184fd00b4e7..b05015282601 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -40,7 +40,6 @@ #include #include #include -#include #include MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver"); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 104bd2e054e5..31ba293854c1 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -34,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 12b8981efd13..78e043ac9ea0 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -48,7 +48,6 @@ #include #include -#include #include #include diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index ccfd3b90ea9f..103ccb919292 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -30,7 +30,6 @@ #include #include -#include #include @@ -47,7 +46,6 @@ I2C_CLIENT_INSMOD; /* This is a superset of the TDA9875 */ struct tda9875 { - int mode; int rvol, lvol; int bass, treble; struct i2c_client c; @@ -197,7 +195,6 @@ static void do_tda9875_init(struct i2c_client *client) tda9875_write(client, TDA9875_MUT, 0xcc ); /* General mute */ - t->mode=AUDIO_UNMUTE; t->lvol=t->rvol =0; /* 0dB */ t->bass=0; /* 0dB */ t->treble=0; /* 0dB */ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 32e1849441fb..df195c905366 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -21,7 +21,6 @@ #include #include -#include #define UNSET (-1U) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 4cc0497dcbde..15fd55ff69ca 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include @@ -102,7 +102,7 @@ struct CHIPDESC { /* input switch register + values for v4l inputs */ int inputreg; - int inputmap[8]; + int inputmap[4]; int inputmute; int inputmask; }; @@ -119,9 +119,10 @@ struct CHIPSTATE { audiocmd shadow; /* current settings */ - __u16 left,right,treble,bass,mode; + __u16 left,right,treble,bass,muted,mode; int prevmode; int radio; + int input; /* thread */ pid_t tpid; @@ -1101,9 +1102,8 @@ static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; } static int tda8425_initialize(struct CHIPSTATE *chip) { struct CHIPDESC *desc = chiplist + chip->type; - int inputmap[8] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, - /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF, - /* off */ TDA8425_S1_OFF, /* on */ TDA8425_S1_CH2}; + int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, + /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF}; if (chip->c.adapter->id == I2C_HW_B_RIVA) { memcpy (desc->inputmap, inputmap, sizeof (inputmap)); @@ -1298,7 +1298,7 @@ static struct CHIPDESC chiplist[] = { .init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } }, .inputreg = TDA9873_SW, .inputmute = TDA9873_MUTE | TDA9873_AUTOMUTE, - .inputmap = {0xa0, 0xa2, 0xa0, 0xa0, 0xc0}, + .inputmap = {0xa0, 0xa2, 0xa0, 0xa0}, .inputmask = TDA9873_INP_MASK|TDA9873_MUTE|TDA9873_AUTOMUTE, }, @@ -1446,8 +1446,7 @@ static struct CHIPDESC chiplist[] = { .inputmap = {PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_TUNER, PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE, PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE, - PIC16C54_MISC_SND_MUTE,PIC16C54_MISC_SND_MUTE, - PIC16C54_MISC_SND_NOTMUTE}, + PIC16C54_MISC_SND_MUTE}, .inputmute = PIC16C54_MISC_SND_MUTE, }, { @@ -1583,28 +1582,40 @@ static int chip_detach(struct i2c_client *client) return 0; } +static int tvaudio_set_ctrl(struct CHIPSTATE *chip, struct v4l2_control *ctrl) +{ + struct CHIPDESC *desc = chiplist + chip->type; + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value < 0 || ctrl->value >= 2) + return -ERANGE; + chip->muted = ctrl->value; + if (chip->muted) + chip_write_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask); + else + chip_write_masked(chip,desc->inputreg, + desc->inputmap[chip->input],desc->inputmask); + break; + default: + return -EINVAL; + } + return 0; +} + + /* ---------------------------------------------------------------------- */ /* video4linux interface */ static int chip_command(struct i2c_client *client, unsigned int cmd, void *arg) { - __u16 *sarg = arg; struct CHIPSTATE *chip = i2c_get_clientdata(client); struct CHIPDESC *desc = chiplist + chip->type; v4l_dbg(1, debug, &chip->c, "%s: chip_command 0x%x\n", chip->c.name, cmd); switch (cmd) { - case AUDC_SET_INPUT: - if (desc->flags & CHIP_HAS_INPUTSEL) { - if (*sarg & 0x80) - chip_write_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask); - else - chip_write_masked(chip,desc->inputreg,desc->inputmap[*sarg],desc->inputmask); - } - break; - case AUDC_SET_RADIO: chip->radio = 1; chip->watch_stereo = 0; @@ -1668,6 +1679,24 @@ static int chip_command(struct i2c_client *client, break; } + case VIDIOC_S_CTRL: + return tvaudio_set_ctrl(chip, arg); + + case VIDIOC_S_AUDIO: + { + struct v4l2_audio *sarg = arg; + + if (!(desc->flags & CHIP_HAS_INPUTSEL) || sarg->index >= 4) + return -EINVAL; + /* There are four inputs: tuner, radio, extern and intern. */ + chip->input = sarg->index; + if (chip->muted) + break; + chip_write_masked(chip, desc->inputreg, + desc->inputmap[chip->input], desc->inputmask); + break; + } + case VIDIOC_S_TUNER: { struct v4l2_tuner *vt = arg; diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 582551b0969b..e0d2ff83fc91 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -248,32 +248,32 @@ audioIC[] = {AUDIO_CHIP_MSP34XX, "MSP3410D"}, {AUDIO_CHIP_MSP34XX, "MSP3415"}, {AUDIO_CHIP_MSP34XX, "MSP3430"}, - {AUDIO_CHIP_UNKNOWN, "MSP3438"}, + {AUDIO_CHIP_MSP34XX, "MSP3438"}, {AUDIO_CHIP_UNKNOWN, "CS5331"}, /* 10-14 */ {AUDIO_CHIP_MSP34XX, "MSP3435"}, {AUDIO_CHIP_MSP34XX, "MSP3440"}, {AUDIO_CHIP_MSP34XX, "MSP3445"}, - {AUDIO_CHIP_UNKNOWN, "MSP3411"}, - {AUDIO_CHIP_UNKNOWN, "MSP3416"}, + {AUDIO_CHIP_MSP34XX, "MSP3411"}, + {AUDIO_CHIP_MSP34XX, "MSP3416"}, /* 15-19 */ {AUDIO_CHIP_MSP34XX, "MSP3425"}, - {AUDIO_CHIP_UNKNOWN, "MSP3451"}, - {AUDIO_CHIP_UNKNOWN, "MSP3418"}, + {AUDIO_CHIP_MSP34XX, "MSP3451"}, + {AUDIO_CHIP_MSP34XX, "MSP3418"}, {AUDIO_CHIP_UNKNOWN, "Type 0x12"}, {AUDIO_CHIP_UNKNOWN, "OKI7716"}, /* 20-24 */ - {AUDIO_CHIP_UNKNOWN, "MSP4410"}, - {AUDIO_CHIP_UNKNOWN, "MSP4420"}, - {AUDIO_CHIP_UNKNOWN, "MSP4440"}, - {AUDIO_CHIP_UNKNOWN, "MSP4450"}, - {AUDIO_CHIP_UNKNOWN, "MSP4408"}, + {AUDIO_CHIP_MSP34XX, "MSP4410"}, + {AUDIO_CHIP_MSP34XX, "MSP4420"}, + {AUDIO_CHIP_MSP34XX, "MSP4440"}, + {AUDIO_CHIP_MSP34XX, "MSP4450"}, + {AUDIO_CHIP_MSP34XX, "MSP4408"}, /* 25-29 */ - {AUDIO_CHIP_UNKNOWN, "MSP4418"}, - {AUDIO_CHIP_UNKNOWN, "MSP4428"}, - {AUDIO_CHIP_UNKNOWN, "MSP4448"}, - {AUDIO_CHIP_UNKNOWN, "MSP4458"}, - {AUDIO_CHIP_UNKNOWN, "Type 0x1d"}, + {AUDIO_CHIP_MSP34XX, "MSP4418"}, + {AUDIO_CHIP_MSP34XX, "MSP4428"}, + {AUDIO_CHIP_MSP34XX, "MSP4448"}, + {AUDIO_CHIP_MSP34XX, "MSP4458"}, + {AUDIO_CHIP_MSP34XX, "Type 0x1d"}, /* 30-34 */ {AUDIO_CHIP_INTERNAL, "CX880"}, {AUDIO_CHIP_INTERNAL, "CX881"}, diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 1717663d3e51..d1234d781e16 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -312,7 +312,6 @@ static const char *v4l2_int_ioctls[] = { [_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP", #endif [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO", - [_IOC_NR(AUDC_SET_INPUT)] = "AUDC_SET_INPUT", [_IOC_NR(MSP_SET_MATRIX)] = "MSP_SET_MATRIX", [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR", @@ -419,7 +418,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) case TUNER_SET_TYPE_ADDR: case TUNER_SET_STANDBY: case TDA9887_SET_CONFIG: - case AUDC_SET_INPUT: case VIDIOC_OVERLAY_OLD: case VIDIOC_STREAMOFF: case VIDIOC_G_OUTPUT: diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 8cb64f8a8a91..9b90225226e6 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -102,11 +102,6 @@ static int wm8775_command(struct i2c_client *client, unsigned int cmd, wm8775_write(client, R21, 0x100 + state->input); break; - case VIDIOC_G_AUDIO: - memset(input, 0, sizeof(*input)); - input->index = state->input; - break; - case VIDIOC_G_CTRL: if (ctrl->id != V4L2_CID_AUDIO_MUTE) return -EINVAL; diff --git a/include/media/audiochip.h b/include/media/audiochip.h index 295d256ee811..1fd4a2207574 100644 --- a/include/media/audiochip.h +++ b/include/media/audiochip.h @@ -21,18 +21,4 @@ enum audiochip { AUDIO_CHIP_MSP34XX }; -/* ---------------------------------------------------------------------- */ - -/* audio inputs */ -#define AUDIO_TUNER 0x00 -#define AUDIO_RADIO 0x01 -#define AUDIO_EXTERN 0x02 -#define AUDIO_INTERN 0x03 -#define AUDIO_OFF 0x04 -#define AUDIO_ON 0x05 -#define AUDIO_EXTERN_1 AUDIO_EXTERN -#define AUDIO_EXTERN_2 0x06 -#define AUDIO_MUTE 0x80 -#define AUDIO_UNMUTE 0x81 - #endif /* AUDIOCHIP_H */ diff --git a/include/media/tvaudio.h b/include/media/tvaudio.h new file mode 100644 index 000000000000..6915aafc875a --- /dev/null +++ b/include/media/tvaudio.h @@ -0,0 +1,30 @@ +/* + tvaudio.h - definition for tvaudio inputs + + Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + + 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. +*/ + +#ifndef _TVAUDIO_H +#define _TVAUDIO_H + +/* The tvaudio module accepts the following inputs: */ +#define TVAUDIO_INPUT_TUNER 0 +#define TVAUDIO_INPUT_RADIO 1 +#define TVAUDIO_INPUT_EXTERN 2 +#define TVAUDIO_INPUT_INTERN 3 + +#endif diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 2360453e7496..07130474a0df 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -123,9 +123,6 @@ enum v4l2_chip_ident { /* v4l device was opened in Radio mode, to be replaced by VIDIOC_INT_S_TUNER_MODE */ #define AUDC_SET_RADIO _IO('d',88) -/* select from TV,radio,extern,MUTE, to be replaced with VIDIOC_INT_S_AUDIO_ROUTING */ -#define AUDC_SET_INPUT _IOW('d',89,int) - /* msp3400 ioctl: will be removed in the near future, to be replaced by VIDIOC_INT_S_AUDIO_ROUTING. */ struct msp_matrix { @@ -209,10 +206,10 @@ struct v4l2_routing { }; /* These internal commands should be used to define the inputs and outputs - of an audio/video chip. They will replace AUDC_SET_INPUT. - The v4l2 API commands VIDIOC_S/G_INPUT, VIDIOC_S/G_OUTPUT, - VIDIOC_S/G_AUDIO and VIDIOC_S/G_AUDOUT are meant to be used by the - user. Internally these commands should be used to switch inputs/outputs + of an audio/video chip. They will replace the v4l2 API commands + VIDIOC_S/G_INPUT, VIDIOC_S/G_OUTPUT, VIDIOC_S/G_AUDIO and VIDIOC_S/G_AUDOUT + that are meant to be used by the user. + The internal commands should be used to switch inputs/outputs because only the driver knows how to map a 'Television' input to the precise input/output routing of an A/D converter, or a DSP, or a video digitizer. These four commands should only be sent directly to an i2c device, they -- cgit v1.2.3-59-g8ed1b From 427725748b38997628d95ffdf8501bcc176cf631 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 19 Mar 2006 06:48:51 -0300 Subject: V4L/DVB (3578): Make scart definitions easier to handle For the new routing implementation it is easier if all the 'normal' scart inputs (IN1-IN4) are consecutive. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-driver.c | 30 ++++++++++++++++-------------- drivers/media/video/msp3400.h | 17 ++++++++--------- 2 files changed, 24 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index bd0b036c5cab..db6a52771c1b 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -245,31 +245,31 @@ int msp_write_dsp(struct i2c_client *client, int addr, int val) * ----------------------------------------------------------------------- */ static int scarts[3][9] = { - /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ + /* MASK IN1 IN2 IN3 IN4 IN1_DA IN2_DA MONO MUTE */ /* SCART DSP Input select */ - { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, + { 0x0320, 0x0000, 0x0200, 0x0300, 0x0020, -1, -1, 0x0100, 0x0320 }, /* SCART1 Output select */ - { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 }, + { 0x0c40, 0x0440, 0x0400, 0x0000, 0x0840, 0x0c00, 0x0040, 0x0800, 0x0c40 }, /* SCART2 Output select */ - { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 }, + { 0x3080, 0x1000, 0x1080, 0x2080, 0x3080, 0x0000, 0x0080, 0x2000, 0x3000 }, }; static char *scart_names[] = { - "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute" + "in1", "in2", "in3", "in4", "in1 da", "in2 da", "mono", "mute" }; void msp_set_scart(struct i2c_client *client, int in, int out) { struct msp_state *state = i2c_get_clientdata(client); - state->in_scart=in; + state->in_scart = in; - if (in >= 1 && in <= 8 && out >= 0 && out <= 2) { - if (-1 == scarts[out][in]) + if (in >= 0 && in <= 7 && out >= 0 && out <= 2) { + if (-1 == scarts[out][in + 1]) return; - state->acb &= ~scarts[out][SCART_MASK]; - state->acb |= scarts[out][in]; + state->acb &= ~scarts[out][0]; + state->acb |= scarts[out][in + 1]; } else state->acb = 0xf60; /* Mute Input and SCART 1 Output */ @@ -585,7 +585,7 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp_state *state = i2c_get_clientdata(client); - int scart = 0; + int scart = -1; if (msp_debug >= 2) v4l_i2c_print_ioctl(client, cmd); @@ -694,7 +694,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp_matrix *mspm = arg; - msp_set_scart(client, mspm->input, mspm->output); + msp_set_scart(client, mspm->input - 1, mspm->output); break; } @@ -735,7 +735,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) state->mode = -1; break; } - if (scart) { + if (scart >= 0) { state->rxsubchans = V4L2_TUNER_SUB_STEREO; msp_set_scart(client, scart, 0); msp_write_dsp(client, 0x000d, 0x1900); @@ -885,12 +885,14 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); } else { - v4l_info(client, "Mode: %s\n", p); + if (state->opmode == OPMODE_AUTODETECT) + v4l_info(client, "Mode: %s\n", p); v4l_info(client, "Standard: %s (%s%s)\n", msp_standard_std_name(state->std), (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); } + v4l_info(client, "Audmode: 0x%04x\n", state->audmode); v4l_info(client, "ACB: 0x%04x\n", state->acb); break; } diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index 6fb5c8c994e7..7fac3ad6228d 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h @@ -20,15 +20,14 @@ #define MSP_MODE_BTSC 8 #define MSP_MODE_EXTERN 9 -#define SCART_MASK 0 -#define SCART_IN1 1 -#define SCART_IN2 2 -#define SCART_IN1_DA 3 -#define SCART_IN2_DA 4 -#define SCART_IN3 5 -#define SCART_IN4 6 -#define SCART_MONO 7 -#define SCART_MUTE 8 +#define SCART_IN1 0 +#define SCART_IN2 1 +#define SCART_IN3 2 +#define SCART_IN4 3 +#define SCART_IN1_DA 4 +#define SCART_IN2_DA 5 +#define SCART_MONO 6 +#define SCART_MUTE 7 #define SCART_DSP_IN 0 #define SCART1_OUT 1 -- cgit v1.2.3-59-g8ed1b From 9a80a93da738c631de644175fbd669ab9a9cb624 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 19 Mar 2006 07:25:42 -0300 Subject: V4L/DVB (3579): Move msp_modus to msp3400-kthreads, add JP and KR std detection msp_modus is 'G' model specific. Moved it to kthreads and also added proper handling for the Japanese and South Korean TV standards. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-driver.c | 31 ------------------------------- drivers/media/video/msp3400-kthreads.c | 34 +++++++++++++++++++++++++++++++++- drivers/media/video/msp3400.h | 1 - 3 files changed, 33 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index db6a52771c1b..2d59d041f368 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -336,37 +336,6 @@ void msp_set_audio(struct i2c_client *client) msp_write_dsp(client, 0x0033, loudness); } -int msp_modus(struct i2c_client *client) -{ - struct msp_state *state = i2c_get_clientdata(client); - - if (state->radio) { - v4l_dbg(1, msp_debug, client, "video mode selected to Radio\n"); - return 0x0003; - } - - if (state->v4l2_std & V4L2_STD_PAL) { - v4l_dbg(1, msp_debug, client, "video mode selected to PAL\n"); - -#if 1 - /* experimental: not sure this works with all chip versions */ - return 0x7003; -#else - /* previous value, try this if it breaks ... */ - return 0x1003; -#endif - } - if (state->v4l2_std & V4L2_STD_NTSC) { - v4l_dbg(1, msp_debug, client, "video mode selected to NTSC\n"); - return 0x2003; - } - if (state->v4l2_std & V4L2_STD_SECAM) { - v4l_dbg(1, msp_debug, client, "video mode selected to SECAM\n"); - return 0x0003; - } - return 0x0003; -} - /* ------------------------------------------------------------------------ */ diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 71a944b447e2..972f2c80dbe2 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -806,6 +806,38 @@ static void msp34xxg_set_source(struct i2c_client *client, int source) state->source = source; } +static int msp34xxg_modus(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + + if (state->radio) { + v4l_dbg(1, msp_debug, client, "selected radio modus\n"); + return 0x0001; + } + + if (state->v4l2_std & V4L2_STD_PAL) { + v4l_dbg(1, msp_debug, client, "selected PAL modus\n"); + return 0x7001; + } + if (state->v4l2_std == V4L2_STD_NTSC_M_JP) { + v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n"); + return 0x4001; + } + if (state->v4l2_std == V4L2_STD_NTSC_M_KR) { + v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n"); + return 0x0001; + } + if (state->v4l2_std & V4L2_STD_MN) { + v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n"); + return 0x2001; + } + if (state->v4l2_std & V4L2_STD_SECAM) { + v4l_dbg(1, msp_debug, client, "selected SECAM modus\n"); + return 0x6001; + } + return 0x0001; +} + /* (re-)initialize the msp34xxg, according to the current norm in state->norm * return 0 if it worked, -1 if it failed */ @@ -826,7 +858,7 @@ static int msp34xxg_reset(struct i2c_client *client) msp_write_dem(client, 0x40, state->i2s_mode); /* step-by-step initialisation, as described in the manual */ - modus = msp_modus(client); + modus = msp34xxg_modus(client); if (state->radio) std = 0x40; else diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index 7fac3ad6228d..c4553f50aa40 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h @@ -98,7 +98,6 @@ int msp_reset(struct i2c_client *client); void msp_set_scart(struct i2c_client *client, int in, int out); void msp_set_mute(struct i2c_client *client); void msp_set_audio(struct i2c_client *client); -int msp_modus(struct i2c_client *client); int msp_sleep(struct msp_state *state, int timeout); /* msp3400-kthreads.c */ -- cgit v1.2.3-59-g8ed1b From de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 19 Mar 2006 08:21:56 -0300 Subject: V4L/DVB (3580): Last round of msp3400 cleanups before adding routing commands Lots of cleanups: - remove duplicate actions - add D/K3 Dual FM-Stereo and D/K NICAM FM (HDEV3) support - put prescales in the proper place - add missing D/K NICAM - msp34xxg_reset now only resets instead of also starting the autodetect (moved that to msp34xxg_thread) - fix support for SAP. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-driver.c | 2 +- drivers/media/video/msp3400-kthreads.c | 188 ++++++++++++++++++--------------- drivers/media/video/msp3400.h | 2 +- 3 files changed, 107 insertions(+), 85 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 2d59d041f368..9a47ba22c133 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -622,6 +622,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) if (va->mode != 0 && state->radio == 0) { state->audmode = msp_mode_v4l1_to_v4l2(va->mode); + msp_set_audmode(client); } break; } @@ -707,7 +708,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) if (scart >= 0) { state->rxsubchans = V4L2_TUNER_SUB_STEREO; msp_set_scart(client, scart, 0); - msp_write_dsp(client, 0x000d, 0x1900); } msp_set_audmode(client); msp_wake_thread(client); diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 972f2c80dbe2..88b216cc49d7 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -44,11 +44,13 @@ static struct { { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" }, { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" }, { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" }, + { 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), "6.5/5.74 D/K3 Dual FM-Stereo" }, { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" }, { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" }, { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" }, { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" }, { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" }, + { 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV3)" }, { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" }, { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" }, { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" }, @@ -206,12 +208,13 @@ void msp3400c_set_mode(struct i2c_client *client, int mode) msp3400c_set_carrier(client, data->cdo1, data->cdo2); msp_set_source(client, data->dsp_src); - msp_write_dsp(client, 0x000e, data->dsp_matrix); + /* set prescales */ - if (state->has_nicam) { - /* nicam prescale */ - msp_write_dsp(client, 0x0010, 0x5a00); /* was: 0x3000 */ - } + /* volume prescale for SCART (AM mono input) */ + msp_write_dsp(client, 0x000d, 0x1900); + msp_write_dsp(client, 0x000e, data->dsp_matrix); + if (state->has_nicam) /* nicam prescale */ + msp_write_dsp(client, 0x0010, 0x5a00); } /* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP, @@ -270,7 +273,6 @@ static void msp3400c_set_audmode(struct i2c_client *client) case MSP_MODE_FM_NICAM2: case MSP_MODE_AM_NICAM: v4l_dbg(1, msp_debug, client, "NICAM set_audmode: %s\n",modestr); - msp3400c_set_carrier(client, state->second, state->main); if (state->nicam_on) src = 0x0100; /* NICAM */ break; @@ -426,8 +428,8 @@ static void watch_stereo(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); - if (msp3400c_detect_stereo(client)) { - msp3400c_set_audmode(client); + if (msp_detect_stereo(client)) { + msp_set_audmode(client); } if (msp_once) @@ -463,7 +465,7 @@ int msp3400c_thread(void *data) /* mute */ msp_set_mute(client); - msp3400c_set_mode(client, MSP_MODE_AM_DETECT /* +1 */ ); + msp3400c_set_mode(client, MSP_MODE_AM_DETECT); val1 = val2 = 0; max1 = max2 = -1; state->watch_stereo = 0; @@ -571,8 +573,6 @@ int msp3400c_thread(void *data) state->second = msp3400c_carrier_detect_65[max2].cdo; msp3400c_set_mode(client, MSP_MODE_AM_NICAM); msp3400c_set_carrier(client, state->second, state->main); - /* volume prescale for SCART (AM mono input) */ - msp_write_dsp(client, 0x000d, 0x1900); state->watch_stereo = 1; } else if (max2 == 0 && state->has_nicam) { /* D/K NICAM */ @@ -650,7 +650,8 @@ int msp3410d_thread(void *data) if (msp_sleep(state,200)) goto restart; - /* start autodetect */ + /* start autodetect. Note: autodetect is not supported for + NTSC-M and radio, hence we force the standard in those cases. */ if (state->radio) std = 0x40; else @@ -694,23 +695,19 @@ int msp3410d_thread(void *data) v4l_dbg(1, msp_debug, client, "autodetection failed," " switching to backup standard: %s (0x%04x)\n", msp_stdlist[8].name ? msp_stdlist[8].name : "unknown",val); - val = 0x0009; + state->std = val = 0x0009; msp_write_dem(client, 0x20, val); } - /* set various prescales */ - msp_write_dsp(client, 0x0d, 0x1900); /* scart */ - msp_write_dsp(client, 0x0e, 0x2403); /* FM */ - msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ - /* set stereo */ switch (val) { case 0x0008: /* B/G NICAM */ case 0x000a: /* I NICAM */ - if (val == 0x0008) - state->mode = MSP_MODE_FM_NICAM1; - else + case 0x000b: /* D/K NICAM */ + if (val == 0x000a) state->mode = MSP_MODE_FM_NICAM2; + else + state->mode = MSP_MODE_FM_NICAM1; /* just turn on stereo */ state->rxsubchans = V4L2_TUNER_SUB_STEREO; state->nicam_on = 1; @@ -738,6 +735,7 @@ int msp3410d_thread(void *data) /* scart routing (this doesn't belong here I think) */ msp_set_scart(client,SCART_IN2,0); break; + case 0x0002: case 0x0003: case 0x0004: case 0x0005: @@ -747,12 +745,19 @@ int msp3410d_thread(void *data) break; } - /* unmute, restore misc registers */ - msp_set_audio(client); - msp_write_dsp(client, 0x13, state->acb); + /* set various prescales */ + msp_write_dsp(client, 0x0d, 0x1900); /* scart */ + msp_write_dsp(client, 0x0e, 0x3000); /* FM */ + if (state->has_nicam) + msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ + if (state->has_i2s_conf) msp_write_dem(client, 0x40, state->i2s_mode); + /* unmute, restore misc registers */ + msp_set_audio(client); + + msp_write_dsp(client, 0x13, state->acb); msp3400c_set_audmode(client); /* monitor tv audio mode, the first time don't wait @@ -771,16 +776,15 @@ int msp3410d_thread(void *data) /* ----------------------------------------------------------------------- */ -/* msp34xxG + (autoselect no-thread) */ -/* this one uses both automatic standard detection and automatic sound */ -/* select which are available in the newer G versions */ -/* struct msp: only norm, acb and source are really used in this mode */ +/* msp34xxG + (autoselect no-thread) + * this one uses both automatic standard detection and automatic sound + * select which are available in the newer G versions + * struct msp: only norm, acb and source are really used in this mode + */ /* set the same 'source' for the loudspeaker, scart and quasi-peak detector * the value for source is the same as bit 15:8 of DSP registers 0x08, * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B - * - * this function replaces msp3400c_set_audmode */ static void msp34xxg_set_source(struct i2c_client *client, int source) { @@ -838,58 +842,56 @@ static int msp34xxg_modus(struct i2c_client *client) return 0x0001; } -/* (re-)initialize the msp34xxg, according to the current norm in state->norm - * return 0 if it worked, -1 if it failed - */ -static int msp34xxg_reset(struct i2c_client *client) +/* (re-)initialize the msp34xxg */ +static void msp34xxg_reset(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); - int modus, std; + int modus; - if (msp_reset(client)) - return -1; + /* initialize std to 1 (autodetect) to signal that no standard is + selected yet. */ + state->std = 1; + + msp_reset(client); /* make sure that input/output is muted (paranoid mode) */ /* ACB, mute DSP input, mute SCART 1 */ - if (msp_write_dsp(client, 0x13, 0x0f20)) - return -1; + msp_write_dsp(client, 0x13, 0x0f20); if (state->has_i2s_conf) msp_write_dem(client, 0x40, state->i2s_mode); /* step-by-step initialisation, as described in the manual */ modus = msp34xxg_modus(client); - if (state->radio) - std = 0x40; - else - std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1; - modus &= ~0x03; /* STATUS_CHANGE = 0 */ - modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION = 1 */ - if (msp_write_dem(client, 0x30, modus)) - return -1; - if (msp_write_dem(client, 0x20, std)) - return -1; + msp_write_dem(client, 0x30, modus); /* write the dsps that may have an influence on standard/audio autodetection right now */ msp34xxg_set_source(client, state->source); - /* AM/FM Prescale [15:8] 75khz deviation */ - if (msp_write_dsp(client, 0x0e, 0x3000)) - return -1; - - /* NICAM Prescale 9db gain (as recommended) */ - if (msp_write_dsp(client, 0x10, 0x5a00)) - return -1; + msp_write_dsp(client, 0x0d, 0x1900); /* scart */ + msp_write_dsp(client, 0x0e, 0x3000); /* FM */ + if (state->has_nicam) + msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ - return 0; + /* set identification threshold. Personally, I + * I set it to a higher value than the default + * of 0x190 to ignore noisy stereo signals. + * this needs tuning. (recommended range 0x00a0-0x03c0) + * 0x7f0 = forced mono mode + * + * a2 threshold for stereo/bilingual. + * Note: this register is part of the Manual/Compatibility mode. + * It is supported by all 'G'-family chips. + */ + msp_write_dem(client, 0x22, msp_stereo_thresh); } int msp34xxg_thread(void *data) { struct i2c_client *client = data; struct msp_state *state = i2c_get_clientdata(client); - int val, std, i; + int val, i; v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); @@ -907,12 +909,14 @@ int msp34xxg_thread(void *data) /* setup the chip*/ msp34xxg_reset(client); - std = msp_standard; - if (std != 0x01) + state->std = state->radio ? 0x40 : msp_standard; + if (state->std != 1) goto unmute; + /* start autodetect */ + msp_write_dem(client, 0x20, state->std); /* watch autodetect */ - v4l_dbg(1, msp_debug, client, "triggered autodetect, waiting for result\n"); + v4l_dbg(1, msp_debug, client, "started autodetect, waiting for result\n"); for (i = 0; i < 10; i++) { if (msp_sleep(state, 100)) goto restart; @@ -920,20 +924,19 @@ int msp34xxg_thread(void *data) /* check results */ val = msp_read_dem(client, 0x7e); if (val < 0x07ff) { - std = val; + state->std = val; break; } v4l_dbg(2, msp_debug, client, "detection still in progress\n"); } - if (std == 1) { + if (state->std == 1) { v4l_dbg(1, msp_debug, client, "detection still in progress after 10 tries. giving up.\n"); continue; } unmute: - state->std = std; - v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n", - msp_standard_std_name(std), std); + v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n", + msp_standard_std_name(state->std), state->std); /* unmute: dispatch sound to scart output, set scart volume */ msp_set_audio(client); @@ -942,20 +945,33 @@ int msp34xxg_thread(void *data) if (msp_write_dsp(client, 0x13, state->acb)) return -1; - if (state->has_i2s_conf) - msp_write_dem(client, 0x40, state->i2s_mode); + /* the periodic stereo/SAP check is only relevant for + the 0x20 standard (BTSC) */ + if (state->std != 0x20) + continue; + + state->watch_stereo = 1; + + /* monitor tv audio mode, the first time don't wait + in order to get a quick stereo/SAP update */ + watch_stereo(client); + while (state->watch_stereo) { + watch_stereo(client); + if (msp_sleep(state, 5000)) + goto restart; + } } v4l_dbg(1, msp_debug, client, "thread: exit\n"); return 0; } -static void msp34xxg_detect_stereo(struct i2c_client *client) +static int msp34xxg_detect_stereo(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); - int status = msp_read_dem(client, 0x0200); int is_bilingual = status & 0x100; int is_stereo = status & 0x40; + int oldrx = state->rxsubchans; state->rxsubchans = 0; if (is_stereo) @@ -963,16 +979,14 @@ static void msp34xxg_detect_stereo(struct i2c_client *client) else state->rxsubchans = V4L2_TUNER_SUB_MONO; if (is_bilingual) { - state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; - /* I'm supposed to check whether it's SAP or not - * and set only LANG2/SAP in this case. Yet, the MSP - * does a lot of work to hide this and handle everything - * the same way. I don't want to work around it so unless - * this is a problem, I'll handle SAP just like lang1/lang2. - */ + if (state->std == 0x20) + state->rxsubchans |= V4L2_TUNER_SUB_SAP; + else + state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; } v4l_dbg(1, msp_debug, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", status, is_stereo, is_bilingual, state->rxsubchans); + return (oldrx != state->rxsubchans); } static void msp34xxg_set_audmode(struct i2c_client *client) @@ -980,6 +994,16 @@ static void msp34xxg_set_audmode(struct i2c_client *client) struct msp_state *state = i2c_get_clientdata(client); int source; + if (state->std == 0x20) { + if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) && + (state->audmode == V4L2_TUNER_MODE_STEREO || + state->audmode == V4L2_TUNER_MODE_LANG2)) { + msp_write_dem(client, 0x20, 0x21); + } else { + msp_write_dem(client, 0x20, 0x20); + } + } + switch (state->audmode) { case V4L2_TUNER_MODE_MONO: source = 0; /* mono only */ @@ -1008,7 +1032,6 @@ void msp_set_audmode(struct i2c_client *client) switch (state->opmode) { case OPMODE_MANUAL: case OPMODE_AUTODETECT: - state->watch_stereo = 0; msp3400c_set_audmode(client); break; case OPMODE_AUTOSELECT: @@ -1017,18 +1040,17 @@ void msp_set_audmode(struct i2c_client *client) } } -void msp_detect_stereo(struct i2c_client *client) +int msp_detect_stereo(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); switch (state->opmode) { case OPMODE_MANUAL: case OPMODE_AUTODETECT: - msp3400c_detect_stereo(client); - break; + return msp3400c_detect_stereo(client); case OPMODE_AUTOSELECT: - msp34xxg_detect_stereo(client); - break; + return msp34xxg_detect_stereo(client); } + return 0; } diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index c4553f50aa40..25482046fc68 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h @@ -103,7 +103,7 @@ int msp_sleep(struct msp_state *state, int timeout); /* msp3400-kthreads.c */ const char *msp_standard_std_name(int std); void msp_set_audmode(struct i2c_client *client); -void msp_detect_stereo(struct i2c_client *client); +int msp_detect_stereo(struct i2c_client *client); int msp3400c_thread(void *data); int msp3410d_thread(void *data); int msp34xxg_thread(void *data); -- cgit v1.2.3-59-g8ed1b From 49965a80a4c4f5cbe15fb3bb1f8f8b0ec4ef02bc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 19 Mar 2006 08:45:38 -0300 Subject: V4L/DVB (3581): Add new media/msp3400.h header containing the routing macros Moved msp3400.h to msp3400-driver.h. Created media/msp3400.h with the new routing defines and lots of comments. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 1 - drivers/media/video/msp3400-driver.c | 3 +- drivers/media/video/msp3400-driver.h | 113 +++++++++++++++ drivers/media/video/msp3400-kthreads.c | 3 +- drivers/media/video/msp3400.h | 113 --------------- include/media/msp3400.h | 221 ++++++++++++++++++++++++++++++ 6 files changed, 338 insertions(+), 116 deletions(-) create mode 100644 drivers/media/video/msp3400-driver.h delete mode 100644 drivers/media/video/msp3400.h create mode 100644 include/media/msp3400.h (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 4e22fc4889e1..2d68a27417eb 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -31,7 +31,6 @@ #include #include #include -#include "msp3400.h" #include "em28xx.h" diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 9a47ba22c133..04250284ff1e 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -54,9 +54,10 @@ #include #include #include +#include #include #include -#include "msp3400.h" +#include "msp3400-driver.h" /* ---------------------------------------------------------------------- */ diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h new file mode 100644 index 000000000000..04821ebfe04a --- /dev/null +++ b/drivers/media/video/msp3400-driver.h @@ -0,0 +1,113 @@ +/* + */ + +#ifndef MSP3400_DRIVER_H +#define MSP3400_DRIVER_H + +/* ---------------------------------------------------------------------- */ + +/* This macro is allowed for *constants* only, gcc must calculate it + at compile time. Remember -- no floats in kernel mode */ +#define MSP_CARRIER(freq) ((int)((float)(freq / 18.432) * (1 << 24))) + +#define MSP_MODE_AM_DETECT 0 +#define MSP_MODE_FM_RADIO 2 +#define MSP_MODE_FM_TERRA 3 +#define MSP_MODE_FM_SAT 4 +#define MSP_MODE_FM_NICAM1 5 +#define MSP_MODE_FM_NICAM2 6 +#define MSP_MODE_AM_NICAM 7 +#define MSP_MODE_BTSC 8 +#define MSP_MODE_EXTERN 9 + +#define SCART_IN1 0 +#define SCART_IN2 1 +#define SCART_IN3 2 +#define SCART_IN4 3 +#define SCART_IN1_DA 4 +#define SCART_IN2_DA 5 +#define SCART_MONO 6 +#define SCART_MUTE 7 + +#define SCART_DSP_IN 0 +#define SCART1_OUT 1 +#define SCART2_OUT 2 + +#define OPMODE_AUTO -1 +#define OPMODE_MANUAL 0 +#define OPMODE_AUTODETECT 1 /* use autodetect (>= msp3410 only) */ +#define OPMODE_AUTOSELECT 2 /* use autodetect & autoselect (>= msp34xxG) */ + +/* module parameters */ +extern int msp_debug; +extern int msp_once; +extern int msp_amsound; +extern int msp_standard; +extern int msp_dolby; +extern int msp_stereo_thresh; + +struct msp_state { + int rev1, rev2; + u8 has_nicam; + u8 has_radio; + u8 has_headphones; + u8 has_ntsc_jp_d_k3; + u8 has_scart4; + u8 has_scart23_in_scart2_out; + u8 has_scart2_out_volume; + u8 has_i2s_conf; + u8 has_subwoofer; + u8 has_sound_processing; + u8 has_virtual_dolby_surround; + u8 has_dolby_pro_logic; + + int radio; + int opmode; + int std; + int mode; + v4l2_std_id v4l2_std; + int nicam_on; + int acb; + int in_scart; + int i2s_mode; + int main, second; /* sound carrier */ + int input; + int source; /* see msp34xxg_set_source */ + + /* v4l2 */ + int audmode; + int rxsubchans; + + int volume, muted; + int balance, loudness; + int bass, treble; + + /* thread */ + struct task_struct *kthread; + wait_queue_head_t wq; + int restart:1; + int watch_stereo:1; +}; + +/* msp3400-driver.c */ +int msp_write_dem(struct i2c_client *client, int addr, int val); +int msp_write_dsp(struct i2c_client *client, int addr, int val); +int msp_read_dem(struct i2c_client *client, int addr); +int msp_read_dsp(struct i2c_client *client, int addr); +int msp_reset(struct i2c_client *client); +void msp_set_scart(struct i2c_client *client, int in, int out); +void msp_set_mute(struct i2c_client *client); +void msp_set_audio(struct i2c_client *client); +int msp_sleep(struct msp_state *state, int timeout); + +/* msp3400-kthreads.c */ +const char *msp_standard_std_name(int std); +void msp_set_audmode(struct i2c_client *client); +int msp_detect_stereo(struct i2c_client *client); +int msp3400c_thread(void *data); +int msp3410d_thread(void *data); +int msp34xxg_thread(void *data); +void msp3400c_set_mode(struct i2c_client *client, int mode); +void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2); + +#endif /* MSP3400_DRIVER_H */ diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 88b216cc49d7..9ee8dc216d7f 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -26,9 +26,10 @@ #include #include #include +#include #include #include -#include "msp3400.h" +#include "msp3400-driver.h" /* this one uses the automatic sound standard detection of newer msp34xx chip versions */ diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h deleted file mode 100644 index 25482046fc68..000000000000 --- a/drivers/media/video/msp3400.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - */ - -#ifndef MSP3400_H -#define MSP3400_H - -/* ---------------------------------------------------------------------- */ - -/* This macro is allowed for *constants* only, gcc must calculate it - at compile time. Remember -- no floats in kernel mode */ -#define MSP_CARRIER(freq) ((int)((float)(freq / 18.432) * (1 << 24))) - -#define MSP_MODE_AM_DETECT 0 -#define MSP_MODE_FM_RADIO 2 -#define MSP_MODE_FM_TERRA 3 -#define MSP_MODE_FM_SAT 4 -#define MSP_MODE_FM_NICAM1 5 -#define MSP_MODE_FM_NICAM2 6 -#define MSP_MODE_AM_NICAM 7 -#define MSP_MODE_BTSC 8 -#define MSP_MODE_EXTERN 9 - -#define SCART_IN1 0 -#define SCART_IN2 1 -#define SCART_IN3 2 -#define SCART_IN4 3 -#define SCART_IN1_DA 4 -#define SCART_IN2_DA 5 -#define SCART_MONO 6 -#define SCART_MUTE 7 - -#define SCART_DSP_IN 0 -#define SCART1_OUT 1 -#define SCART2_OUT 2 - -#define OPMODE_AUTO -1 -#define OPMODE_MANUAL 0 -#define OPMODE_AUTODETECT 1 /* use autodetect (>= msp3410 only) */ -#define OPMODE_AUTOSELECT 2 /* use autodetect & autoselect (>= msp34xxG) */ - -/* module parameters */ -extern int msp_debug; -extern int msp_once; -extern int msp_amsound; -extern int msp_standard; -extern int msp_dolby; -extern int msp_stereo_thresh; - -struct msp_state { - int rev1, rev2; - u8 has_nicam; - u8 has_radio; - u8 has_headphones; - u8 has_ntsc_jp_d_k3; - u8 has_scart4; - u8 has_scart23_in_scart2_out; - u8 has_scart2_out_volume; - u8 has_i2s_conf; - u8 has_subwoofer; - u8 has_sound_processing; - u8 has_virtual_dolby_surround; - u8 has_dolby_pro_logic; - - int radio; - int opmode; - int std; - int mode; - v4l2_std_id v4l2_std; - int nicam_on; - int acb; - int in_scart; - int i2s_mode; - int main, second; /* sound carrier */ - int input; - int source; /* see msp34xxg_set_source */ - - /* v4l2 */ - int audmode; - int rxsubchans; - - int volume, muted; - int balance, loudness; - int bass, treble; - - /* thread */ - struct task_struct *kthread; - wait_queue_head_t wq; - int restart:1; - int watch_stereo:1; -}; - -/* msp3400-driver.c */ -int msp_write_dem(struct i2c_client *client, int addr, int val); -int msp_write_dsp(struct i2c_client *client, int addr, int val); -int msp_read_dem(struct i2c_client *client, int addr); -int msp_read_dsp(struct i2c_client *client, int addr); -int msp_reset(struct i2c_client *client); -void msp_set_scart(struct i2c_client *client, int in, int out); -void msp_set_mute(struct i2c_client *client); -void msp_set_audio(struct i2c_client *client); -int msp_sleep(struct msp_state *state, int timeout); - -/* msp3400-kthreads.c */ -const char *msp_standard_std_name(int std); -void msp_set_audmode(struct i2c_client *client); -int msp_detect_stereo(struct i2c_client *client); -int msp3400c_thread(void *data); -int msp3410d_thread(void *data); -int msp34xxg_thread(void *data); -void msp3400c_set_mode(struct i2c_client *client, int mode); -void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2); - -#endif /* MSP3400_H */ diff --git a/include/media/msp3400.h b/include/media/msp3400.h new file mode 100644 index 000000000000..26e26585273f --- /dev/null +++ b/include/media/msp3400.h @@ -0,0 +1,221 @@ +/* + msp3400.h - definition for msp3400 inputs and outputs + + Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + + 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. +*/ + +#ifndef _MSP3400_H_ +#define _MSP3400_H_ + +/* msp3400 routing + =============== + + The msp3400 has a complicated routing scheme with many possible + combinations. The details are all in the datasheets but I will try + to give a short description here. + + Inputs + ====== + + There are 1) tuner inputs, 2) I2S inputs, 3) SCART inputs. You will have + to select which tuner input to use and which SCART input to use. The + selected tuner input, the selected SCART input and all I2S inputs go to + the DSP (the tuner input first goes through the demodulator). + + The DSP handles things like volume, bass/treble, balance, and some chips + have support for surround sound. It has several outputs: MAIN, AUX, I2S + and SCART1/2. Each output can select which DSP input to use. So the MAIN + output can select the tuner input while at the same time the SCART1 output + uses the I2S input. + + Outputs + ======= + + Most DSP outputs are also the outputs of the msp3400. However, the SCART + outputs of the msp3400 can select which input to use: either the SCART1 or + SCART2 output from the DSP, or the msp3400 SCART inputs, thus completely + bypassing the DSP. + + Summary + ======= + + So to specify a complete routing scheme for the msp3400 you will have to + specify in the 'input' field of the v4l2_routing struct: + + 1) which tuner input to use + 2) which SCART input to use + 3) which DSP input to use for each DSP output + + And in the 'output' field of the v4l2_routing struct you specify: + + 1) which SCART input to use for each SCART output + + Depending on how the msp is wired to the other components you can + ignore or mute certain inputs or outputs. + + Also, depending on the msp version only a subset of the inputs or + outputs may be present. At the end of this header some tables are + added containing a list of what is available for each msp version. + */ + +/* Inputs to the DSP unit: two independent selections have to be made: + 1) the tuner (SIF) input + 2) the SCART input + Bits 0-2 are used for the SCART input select, bit 3 is used for the tuner + input, bits 4-7 are reserved. + */ + +/* SCART input to DSP selection */ +#define MSP_IN_SCART_1 0 /* Pin SC1_IN */ +#define MSP_IN_SCART_2 1 /* Pin SC2_IN */ +#define MSP_IN_SCART_3 2 /* Pin SC3_IN */ +#define MSP_IN_SCART_4 3 /* Pin SC4_IN */ +#define MSP_IN_MONO 6 /* Pin MONO_IN */ +#define MSP_IN_MUTE 7 /* Mute DSP input */ +#define MSP_SCART_TO_DSP(in) (in) +/* Tuner input to demodulator and DSP selection */ +#define MSP_IN_TUNER_1 0 /* Analog Sound IF input pin ANA_IN1 */ +#define MSP_IN_TUNER_2 1 /* Analog Sound IF input pin ANA_IN2 */ +#define MSP_TUNER_TO_DSP(in) ((in) << 3) + +/* The msp has up to 5 DSP outputs, each output can independently select + a DSP input. + + The DSP outputs are: loudspeaker output (aka MAIN), headphones output + (aka AUX), SCART1 DA output, SCART2 DA output and an I2S output. + There also is a quasi-peak detector output, but that is not used by + this driver and is set to the same input as the loudspeaker output. + Not all outputs are supported by all msp models. Setting the input + of an unsupported output will be ignored by the driver. + + There are up to 16 DSP inputs to choose from, so each output is + assigned 4 bits. + + Note: the 44x8G can mix two inputs and feed the result back to the + DSP. This is currently not implemented. Also not implemented is the + multi-channel capable I2S3 input of the 44x0G. If someone can demonstrate + a need for one of those features then additional support can be added. */ +#define MSP_DSP_OUT_TUNER 0 /* Tuner output */ +#define MSP_DSP_OUT_SCART 2 /* SCART output */ +#define MSP_DSP_OUT_I2S1 5 /* I2S1 output */ +#define MSP_DSP_OUT_I2S2 6 /* I2S2 output */ +#define MSP_DSP_OUT_I2S3 7 /* I2S3 output */ +#define MSP_DSP_OUT_MAIN_AVC 11 /* MAIN AVC processed output */ +#define MSP_DSP_OUT_MAIN 12 /* MAIN output */ +#define MSP_DSP_OUT_AUX 13 /* AUX output */ +#define MSP_DSP_TO_MAIN(in) ((in) << 4) +#define MSP_DSP_TO_AUX(in) ((in) << 8) +#define MSP_DSP_TO_SCART1(in) ((in) << 12) +#define MSP_DSP_TO_SCART2(in) ((in) << 16) +#define MSP_DSP_TO_I2S(in) ((in) << 20) + +/* Output SCART select: the SCART outputs can select which input + to use. */ +#define MSP_OUT_SCART1 0 /* SCART1 input, bypassing the DSP */ +#define MSP_OUT_SCART2 1 /* SCART2 input, bypassing the DSP */ +#define MSP_OUT_SCART3 2 /* SCART3 input, bypassing the DSP */ +#define MSP_OUT_SCART4 3 /* SCART4 input, bypassing the DSP */ +#define MSP_OUT_SCART1_DA 4 /* DSP SCART1 output */ +#define MSP_OUT_SCART2_DA 5 /* DSP SCART2 output */ +#define MSP_OUT_MONO 6 /* MONO input, bypassing the DSP */ +#define MSP_OUT_MUTE 7 /* MUTE output */ +#define MSP_OUT_TO_SCART1(in) (in) +#define MSP_OUT_TO_SCART2(in) ((in) << 4) + +/* Shortcut macros */ +#define MSP_INPUT(sc, t, main_aux_src, sc_i2s_src) \ + (MSP_SCART_TO_DSP(sc) | \ + MSP_TUNER_TO_DSP(t) | \ + MSP_DSP_TO_MAIN(main_aux_src) | \ + MSP_DSP_TO_AUX(main_aux_src) | \ + MSP_DSP_TO_SCART1(sc_i2s_src) | \ + MSP_DSP_TO_SCART2(sc_i2s_src) | \ + MSP_DSP_TO_I2S(sc_i2s_src)) +#define MSP_OUTPUT(sc) \ + (MSP_OUT_TO_SCART1(sc) | \ + MSP_OUT_TO_SCART2(sc)) + +/* Tuner inputs vs. msp version */ +/* Chip TUNER_1 TUNER_2 + ------------------------- + msp34x0b y y + msp34x0c y y + msp34x0d y y + msp34x5d y n + msp34x7d y n + msp34x0g y y + msp34x1g y y + msp34x2g y y + msp34x5g y n + msp34x7g y n + msp44x0g y y + msp44x8g y y + */ + +/* SCART inputs vs. msp version */ +/* Chip SC1 SC2 SC3 SC4 + ------------------------- + msp34x0b y y y n + msp34x0c y y y n + msp34x0d y y y y + msp34x5d y y n n + msp34x7d y n n n + msp34x0g y y y y + msp34x1g y y y y + msp34x2g y y y y + msp34x5g y y n n + msp34x7g y n n n + msp44x0g y y y y + msp44x8g y y y y + */ + +/* DSP inputs vs. msp version (tuner and SCART inputs are always available) */ +/* Chip I2S1 I2S2 I2S3 MAIN_AVC MAIN AUX + ------------------------------------------ + msp34x0b y n n n n n + msp34x0c y y n n n n + msp34x0d y y n n n n + msp34x5d y y n n n n + msp34x7d n n n n n n + msp34x0g y y n n n n + msp34x1g y y n n n n + msp34x2g y y n y y y + msp34x5g y y n n n n + msp34x7g n n n n n n + msp44x0g y y y y y y + msp44x8g y y y n n n + */ + +/* DSP outputs vs. msp version */ +/* Chip MAIN AUX SCART1 SCART2 I2S + ------------------------------------ + msp34x0b y y y n y + msp34x0c y y y n y + msp34x0d y y y y y + msp34x5d y n y n y + msp34x7d y n y n n + msp34x0g y y y y y + msp34x1g y y y y y + msp34x2g y y y y y + msp34x5g y n y n y + msp34x7g y n y n n + msp44x0g y y y y y + msp44x8g y y y y y + */ + +#endif /* MSP3400_H */ + -- cgit v1.2.3-59-g8ed1b From 2474ed444b475614ef795523076be7cc8437ae00 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 19 Mar 2006 12:35:57 -0300 Subject: V4L/DVB (3582): Implement correct msp3400 input/output routing - implement VIDIOC_INT_S_AUDIO_ROUTING for msp3400 and tvaudio - use the new command in bttv, pvrusb2 and em28xx. - remove the now obsolete MSP_SET_MATRIX from msp3400 (yeah!) - remove the obsolete VIDIOC_S_AUDIO from msp3400. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 52 +++++++++++--- drivers/media/video/em28xx/em28xx-cards.c | 8 ++- drivers/media/video/em28xx/em28xx-video.c | 8 ++- drivers/media/video/msp3400-driver.c | 67 +++++++++--------- drivers/media/video/msp3400-driver.h | 4 +- drivers/media/video/msp3400-kthreads.c | 111 ++++++++++++++++-------------- drivers/media/video/tvaudio.c | 24 +++++++ drivers/media/video/v4l2-common.c | 13 +--- include/media/msp3400.h | 5 ++ include/media/v4l2-common.h | 8 --- 10 files changed, 181 insertions(+), 119 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index be567ec9e145..80e4a7406ac2 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -37,6 +37,7 @@ #include "bttvp.h" #include #include +#include #include @@ -934,11 +935,9 @@ static int audio_mux(struct bttv *btv, int input, int mute) { int gpio_val, signal; - struct v4l2_audio aud_input; struct v4l2_control ctrl; struct i2c_client *c; - memset(&aud_input, 0, sizeof(aud_input)); gpio_inout(bttv_tvcards[btv->c.type].gpiomask, bttv_tvcards[btv->c.type].gpiomask); signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC; @@ -953,7 +952,6 @@ audio_mux(struct bttv *btv, int input, int mute) gpio_val = bttv_tvcards[btv->c.type].gpiomute; else gpio_val = bttv_tvcards[btv->c.type].gpiomux[input]; - aud_input.index = btv->audio; gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val); if (bttv_gpio) @@ -962,15 +960,51 @@ audio_mux(struct bttv *btv, int input, int mute) return 0; ctrl.id = V4L2_CID_AUDIO_MUTE; - /* take automute into account, just btv->mute is not enough */ - ctrl.value = mute; + ctrl.value = btv->mute; bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl); c = btv->i2c_msp34xx_client; - if (c) - c->driver->command(c, VIDIOC_S_AUDIO, &aud_input); + if (c) { + struct v4l2_routing route; + + /* Note: the inputs tuner/radio/extern/intern are translated + to msp routings. This assumes common behavior for all msp3400 + based TV cards. When this assumption fails, then the + specific MSP routing must be added to the card table. + For now this is sufficient. */ + switch (input) { + case TVAUDIO_INPUT_RADIO: + route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1, + MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART); + break; + case TVAUDIO_INPUT_EXTERN: + route.input = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1, + MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART); + break; + case TVAUDIO_INPUT_INTERN: + /* Yes, this is the same input as for RADIO. I doubt + if this is ever used. The only board with an INTERN + input is the BTTV_BOARD_AVERMEDIA98. I wonder how + that was tested. My guess is that the whole INTERN + input does not work. */ + route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1, + MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART); + break; + case TVAUDIO_INPUT_TUNER: + default: + route.input = MSP_INPUT_DEFAULT; + break; + } + route.output = MSP_OUTPUT_DEFAULT; + c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route); + } c = btv->i2c_tvaudio_client; - if (c) - c->driver->command(c, VIDIOC_S_AUDIO, &aud_input); + if (c) { + struct v4l2_routing route; + + route.input = input; + route.output = 0; + c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route); + } return 0; } diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 2d68a27417eb..f62fd706b45a 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -28,8 +28,9 @@ #include #include #include -#include +#include #include +#include #include #include "em28xx.h" @@ -146,11 +147,12 @@ struct em28xx_board em28xx_boards[] = { .input = {{ .type = EM28XX_VMUX_TELEVISION, .vmux = 0, - .amux = 6, + .amux = MSP_INPUT_DEFAULT, },{ .type = EM28XX_VMUX_SVIDEO, .vmux = 2, - .amux = 1, + .amux = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1, + MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART), }}, }, [EM2820_BOARD_MSI_VOX_USB_2] = { diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 780342f7b239..dfba33d0fa61 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -38,6 +38,7 @@ #include "em28xx.h" #include #include +#include #define DRIVER_AUTHOR "Ludovico Cavedon , " \ "Markus Rechberger , " \ @@ -216,9 +217,14 @@ static void video_mux(struct em28xx *dev, int index) em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput); if (dev->has_msp34xx) { + struct v4l2_routing route; + if (dev->i2s_speed) em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed); - em28xx_i2c_call_clients(dev, VIDIOC_S_AUDIO, &dev->ctl_ainput); + route.input = dev->ctl_ainput; + route.output = MSP_OUTPUT(MSP_OUT_SCART1_DA); + /* Note: this is msp3400 specific */ + em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); ainput = EM28XX_AUDIO_SRC_TUNER; em28xx_audio_source(dev, ainput); } else { diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 04250284ff1e..8ba1c960388a 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -555,7 +555,6 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp_state *state = i2c_get_clientdata(client); - int scart = -1; if (msp_debug >= 2) v4l_i2c_print_ioctl(client, cmd); @@ -660,15 +659,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } - /* msp34xx specific */ - case MSP_SET_MATRIX: - { - struct msp_matrix *mspm = arg; - - msp_set_scart(client, mspm->input - 1, mspm->output); - break; - } - /* --- v4l2 ioctls --- */ case VIDIOC_S_STD: { @@ -682,36 +672,38 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } - case VIDIOC_S_AUDIO: + case VIDIOC_INT_G_AUDIO_ROUTING: { - struct v4l2_audio *sarg = arg; + struct v4l2_routing *rt = arg; - switch (sarg->index) { - case TVAUDIO_INPUT_RADIO: - /* Hauppauge uses IN2 for the radio */ - state->mode = MSP_MODE_FM_RADIO; - scart = SCART_IN2; - break; - case TVAUDIO_INPUT_EXTERN: - /* IN1 is often used for external input ... */ - state->mode = MSP_MODE_EXTERN; - scart = SCART_IN1; - break; - case TVAUDIO_INPUT_INTERN: - /* ... sometimes it is IN2 through ;) */ - state->mode = MSP_MODE_EXTERN; - scart = SCART_IN2; - break; - case TVAUDIO_INPUT_TUNER: - state->mode = -1; - break; - } - if (scart >= 0) { - state->rxsubchans = V4L2_TUNER_SUB_STEREO; - msp_set_scart(client, scart, 0); + *rt = state->routing; + break; + } + + case VIDIOC_INT_S_AUDIO_ROUTING: + { + struct v4l2_routing *rt = arg; + int tuner = (rt->input >> 3) & 1; + int old_tuner = (state->routing.input >> 3) & 1; + int sc_in = rt->input & 0x7; + int sc1_out = rt->output & 0xf; + int sc2_out = (rt->output >> 4) & 0xf; + u16 val; + + state->routing = *rt; + if (state->opmode == OPMODE_AUTOSELECT) { + val = msp_read_dem(client, 0x30) & ~0x100; + msp_write_dem(client, 0x30, val | (tuner ? 0x100 : 0)); + } else { + val = msp_read_dem(client, 0xbb) & ~0x100; + msp_write_dem(client, 0xbb, val | (tuner ? 0x100 : 0)); } + msp_set_scart(client, sc_in, 0); + msp_set_scart(client, sc1_out, 1); + msp_set_scart(client, sc2_out, 2); msp_set_audmode(client); - msp_wake_thread(client); + if (tuner != old_tuner) + msp_wake_thread(client); break; } @@ -941,6 +933,9 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) state->muted = 0; state->i2s_mode = 0; init_waitqueue_head(&state->wq); + /* These are the reset input/output positions */ + state->routing.input = MSP_INPUT_DEFAULT; + state->routing.output = MSP_OUTPUT_DEFAULT; state->rev1 = msp_read_dsp(client, 0x1e); if (state->rev1 != -1) diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h index 04821ebfe04a..1940748bb633 100644 --- a/drivers/media/video/msp3400-driver.h +++ b/drivers/media/video/msp3400-driver.h @@ -4,6 +4,8 @@ #ifndef MSP3400_DRIVER_H #define MSP3400_DRIVER_H +#include + /* ---------------------------------------------------------------------- */ /* This macro is allowed for *constants* only, gcc must calculate it @@ -72,7 +74,7 @@ struct msp_state { int i2s_mode; int main, second; /* sound carrier */ int input; - int source; /* see msp34xxg_set_source */ + struct v4l2_routing routing; /* v4l2 */ int audmode; diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 9ee8dc216d7f..1c794c3b9f21 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -187,13 +187,14 @@ void msp3400c_set_mode(struct i2c_client *client, int mode) { struct msp_state *state = i2c_get_clientdata(client); struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode]; + int tuner = (state->routing.input >> 3) & 1; int i; v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode); state->mode = mode; state->rxsubchans = V4L2_TUNER_SUB_MONO; - msp_write_dem(client, 0x00bb, data->ad_cv); + msp_write_dem(client, 0x00bb, data->ad_cv | (tuner ? 0x100 : 0)); for (i = 5; i >= 0; i--) /* fir 1 */ msp_write_dem(client, 0x0001, data->fir1[i]); @@ -783,34 +784,6 @@ int msp3410d_thread(void *data) * struct msp: only norm, acb and source are really used in this mode */ -/* set the same 'source' for the loudspeaker, scart and quasi-peak detector - * the value for source is the same as bit 15:8 of DSP registers 0x08, - * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B - */ -static void msp34xxg_set_source(struct i2c_client *client, int source) -{ - struct msp_state *state = i2c_get_clientdata(client); - - /* fix matrix mode to stereo and let the msp choose what - * to output according to 'source', as recommended - * for MONO (source==0) downmixing set bit[7:0] to 0x30 - */ - int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20); - - v4l_dbg(1, msp_debug, client, "set source to %d (0x%x)\n", source, value); - msp_set_source(client, value); - /* - * set identification threshold. Personally, I - * I set it to a higher value that the default - * of 0x190 to ignore noisy stereo signals. - * this needs tuning. (recommended range 0x00a0-0x03c0) - * 0x7f0 = forced mono mode - */ - /* a2 threshold for stereo/bilingual */ - msp_write_dem(client, 0x22, msp_stereo_thresh); - state->source = source; -} - static int msp34xxg_modus(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); @@ -843,10 +816,65 @@ static int msp34xxg_modus(struct i2c_client *client) return 0x0001; } +static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) + { + struct msp_state *state = i2c_get_clientdata(client); + int source, matrix; + + switch (state->audmode) { + case V4L2_TUNER_MODE_MONO: + source = 0; /* mono only */ + matrix = 0x30; + break; + case V4L2_TUNER_MODE_LANG1: + source = 3; /* stereo or A */ + matrix = 0x00; + break; + case V4L2_TUNER_MODE_LANG2: + source = 4; /* stereo or B */ + matrix = 0x10; + break; + case V4L2_TUNER_MODE_STEREO: + default: + source = 1; /* stereo or A|B */ + matrix = 0x20; + break; + } + + if (in == MSP_DSP_OUT_TUNER) + source = (source << 8) | 0x20; + /* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14 + instead of 11, 12, 13. So we add one for that msp version. */ + else if (in >= MSP_DSP_OUT_MAIN_AVC && state->has_dolby_pro_logic) + source = ((in + 1) << 8) | matrix; + else + source = (in << 8) | matrix; + + v4l_dbg(1, msp_debug, client, "set source to %d (0x%x) for output %02x\n", + in, source, reg); + msp_write_dsp(client, reg, source); +} + +static void msp34xxg_set_sources(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + u32 in = state->routing.input; + + msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf); + /* quasi-peak detector is set to same input as the loudspeaker (MAIN) */ + msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf); + msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf); + msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf); + if (state->has_scart23_in_scart2_out) + msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf); + msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf); +} + /* (re-)initialize the msp34xxg */ static void msp34xxg_reset(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); + int tuner = (state->routing.input >> 3) & 1; int modus; /* initialize std to 1 (autodetect) to signal that no standard is @@ -864,11 +892,12 @@ static void msp34xxg_reset(struct i2c_client *client) /* step-by-step initialisation, as described in the manual */ modus = msp34xxg_modus(client); + modus |= tuner ? 0x100 : 0; msp_write_dem(client, 0x30, modus); /* write the dsps that may have an influence on standard/audio autodetection right now */ - msp34xxg_set_source(client, state->source); + msp34xxg_set_sources(client); msp_write_dsp(client, 0x0d, 0x1900); /* scart */ msp_write_dsp(client, 0x0e, 0x3000); /* FM */ @@ -896,7 +925,6 @@ int msp34xxg_thread(void *data) v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); - state->source = 1; /* default */ for (;;) { v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); msp_sleep(state, -1); @@ -993,7 +1021,6 @@ static int msp34xxg_detect_stereo(struct i2c_client *client) static void msp34xxg_set_audmode(struct i2c_client *client) { struct msp_state *state = i2c_get_clientdata(client); - int source; if (state->std == 0x20) { if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) && @@ -1005,25 +1032,7 @@ static void msp34xxg_set_audmode(struct i2c_client *client) } } - switch (state->audmode) { - case V4L2_TUNER_MODE_MONO: - source = 0; /* mono only */ - break; - case V4L2_TUNER_MODE_STEREO: - source = 1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ - /* problem: that could also mean 2 (scart input) */ - break; - case V4L2_TUNER_MODE_LANG1: - source = 3; /* stereo or A */ - break; - case V4L2_TUNER_MODE_LANG2: - source = 4; /* stereo or B */ - break; - default: - source = 1; - break; - } - msp34xxg_set_source(client, source); + msp34xxg_set_sources(client); } void msp_set_audmode(struct i2c_client *client) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 15fd55ff69ca..4e6d030d83c0 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1682,6 +1682,30 @@ static int chip_command(struct i2c_client *client, case VIDIOC_S_CTRL: return tvaudio_set_ctrl(chip, arg); + case VIDIOC_INT_G_AUDIO_ROUTING: + { + struct v4l2_routing *rt = arg; + + rt->input = chip->input; + rt->output = 0; + break; + } + + case VIDIOC_INT_S_AUDIO_ROUTING: + { + struct v4l2_routing *rt = arg; + + if (!(desc->flags & CHIP_HAS_INPUTSEL) || rt->input >= 4) + return -EINVAL; + /* There are four inputs: tuner, radio, extern and intern. */ + chip->input = rt->input; + if (chip->muted) + break; + chip_write_masked(chip, desc->inputreg, + desc->inputmap[chip->input], desc->inputmask); + break; + } + case VIDIOC_S_AUDIO: { struct v4l2_audio *sarg = arg; diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index d1234d781e16..6824ee045fe6 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -312,7 +312,6 @@ static const char *v4l2_int_ioctls[] = { [_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP", #endif [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO", - [_IOC_NR(MSP_SET_MATRIX)] = "MSP_SET_MATRIX", [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR", [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", @@ -431,12 +430,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) printk ("%s: value=%d\n", s, *p); break; } - case MSP_SET_MATRIX: - { - struct msp_matrix *p=arg; - printk ("%s: input=%d, output=%d\n", s, p->input, p->output); - break; - } case VIDIOC_G_AUDIO: case VIDIOC_S_AUDIO: case VIDIOC_ENUMAUDIO: @@ -465,7 +458,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) struct v4l2_buffer *p=arg; struct v4l2_timecode *tc=&p->timecode; printk ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%s, " - "bytesused=%d, flags=0x%08d, " + "bytesused=%d, flags=0x%08x, " "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n", s, (p->timestamp.tv_sec/3600), @@ -479,7 +472,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) prt_names(p->memory,v4l2_memory_names), p->m.userptr); printk ("%s: timecode= %02d:%02d:%02d type=%d, " - "flags=0x%08d, frames=%d, userbits=0x%p", + "flags=0x%08x, frames=%d, userbits=0x%08p\n", s,tc->hours,tc->minutes,tc->seconds, tc->type, tc->flags, tc->frames, tc->userbits); break; @@ -665,7 +658,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) case VIDIOC_INT_G_VIDEO_ROUTING: { struct v4l2_routing *p=arg; - printk ("%s: input=%d, output=%d\n", s, p->input, p->output); + printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output); break; } case VIDIOC_G_SLICED_VBI_CAP: diff --git a/include/media/msp3400.h b/include/media/msp3400.h index 26e26585273f..0be61a021d45 100644 --- a/include/media/msp3400.h +++ b/include/media/msp3400.h @@ -145,9 +145,14 @@ MSP_DSP_TO_SCART1(sc_i2s_src) | \ MSP_DSP_TO_SCART2(sc_i2s_src) | \ MSP_DSP_TO_I2S(sc_i2s_src)) +#define MSP_INPUT_DEFAULT MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1, \ + MSP_DSP_OUT_TUNER, MSP_DSP_OUT_TUNER) #define MSP_OUTPUT(sc) \ (MSP_OUT_TO_SCART1(sc) | \ MSP_OUT_TO_SCART2(sc)) +/* This equals the RESET position of the msp3400 ACB register */ +#define MSP_OUTPUT_DEFAULT (MSP_OUT_TO_SCART1(MSP_OUT_SCART3) | \ + MSP_OUT_TO_SCART2(MSP_OUT_SCART1_DA)) /* Tuner inputs vs. msp version */ /* Chip TUNER_1 TUNER_2 diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 07130474a0df..642520acdfa7 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -123,14 +123,6 @@ enum v4l2_chip_ident { /* v4l device was opened in Radio mode, to be replaced by VIDIOC_INT_S_TUNER_MODE */ #define AUDC_SET_RADIO _IO('d',88) -/* msp3400 ioctl: will be removed in the near future, to be replaced by - VIDIOC_INT_S_AUDIO_ROUTING. */ -struct msp_matrix { - int input; - int output; -}; -#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix) - /* tuner ioctls */ /* Sets tuner type and its I2C addr */ -- cgit v1.2.3-59-g8ed1b From 301e22d69140898eddd38a9134da711cb5dfc170 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 18 Mar 2006 17:15:00 -0300 Subject: V4L/DVB (3584): Implement V4L2_TUNER_MODE_LANG1_LANG2 audio mode Add a new audio mode V4L2_TUNER_MODE_LANG1_LANG2 (used by VIDIOC_G/S_TUNER). This mode allows the user to select both languages of a bilingual transmission, one language on the left, one on the right audio channel. If there is no bilingual transmission, or it is not supported, then this mode should act like V4L2_TUNER_MODE_STEREO. This mode is introduced for PVR-like drivers where it is useful to be able to record both languages of a bilingual broadcast. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110_v4l.c | 5 +++++ drivers/media/video/bt8xx/bttv-driver.c | 3 ++- drivers/media/video/cx25840/cx25840-core.c | 5 +++-- drivers/media/video/cx88/cx88-tvaudio.c | 3 +++ drivers/media/video/msp3400-kthreads.c | 8 ++++++-- drivers/media/video/mxb.c | 6 ++++++ drivers/media/video/saa7134/saa7134-tvaudio.c | 2 ++ drivers/media/video/tvaudio.c | 1 + include/linux/videodev2.h | 1 + 9 files changed, 29 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index 2f23ceab8d44..603a22e4bfe2 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c @@ -369,6 +369,11 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) fm_matrix = 0x3001; // stereo src = 0x0020; break; + case V4L2_TUNER_MODE_LANG1_LANG2: + dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n"); + fm_matrix = 0x3000; // bilingual + src = 0x0020; + break; case V4L2_TUNER_MODE_LANG1: dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"); fm_matrix = 0x3000; // mono diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 80e4a7406ac2..74def9c23952 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1878,7 +1878,8 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); if (t->audmode == V4L2_TUNER_MODE_MONO) va.mode = VIDEO_SOUND_MONO; - else if (t->audmode == V4L2_TUNER_MODE_STEREO) + else if (t->audmode == V4L2_TUNER_MODE_STEREO || + t->audmode == V4L2_TUNER_MODE_LANG1_LANG2) va.mode = VIDEO_SOUND_STEREO; else if (t->audmode == V4L2_TUNER_MODE_LANG1) va.mode = VIDEO_SOUND_LANG1; diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 7aee37645d63..a65b3cc4bf03 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -810,13 +810,14 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, bilingual -> lang1 */ cx25840_and_or(client, 0x809, ~0xf, 0x00); break; + case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_LANG1: /* mono -> mono stereo -> stereo bilingual -> lang1 */ cx25840_and_or(client, 0x809, ~0xf, 0x04); break; - case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1_LANG2: /* mono -> mono stereo -> stereo bilingual -> lang1/lang2 */ @@ -824,7 +825,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, break; case V4L2_TUNER_MODE_LANG2: /* mono -> mono - stereo ->stereo + stereo -> stereo bilingual -> lang2 */ cx25840_and_or(client, 0x809, ~0xf, 0x01); break; diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index da8d97ce0c4b..641a0c5a6490 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -885,6 +885,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP); break; case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1_LANG2: set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO); break; } @@ -905,6 +906,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) EN_NICAM_FORCE_MONO2); break; case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1_LANG2: set_audio_standard_NICAM(core, EN_NICAM_FORCE_STEREO); break; @@ -926,6 +928,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) EN_A2_FORCE_MONO2); break; case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1_LANG2: set_audio_standard_A2(core, EN_A2_FORCE_STEREO); break; diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 1c794c3b9f21..c3984ea9ca07 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -223,9 +223,9 @@ void msp3400c_set_mode(struct i2c_client *client, int mode) nor do they support stereo BTSC. */ static void msp3400c_set_audmode(struct i2c_client *client) { - static char *strmode[] = { "mono", "stereo", "lang2", "lang1" }; + static char *strmode[] = { "mono", "stereo", "lang2", "lang1", "lang1+lang2" }; struct msp_state *state = i2c_get_clientdata(client); - char *modestr = (state->audmode >= 0 && state->audmode < 4) ? + char *modestr = (state->audmode >= 0 && state->audmode < 5) ? strmode[state->audmode] : "unknown"; int src = 0; /* channel source: FM/AM, nicam or SCART */ @@ -250,6 +250,7 @@ static void msp3400c_set_audmode(struct i2c_client *client) case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_LANG1: case V4L2_TUNER_MODE_LANG2: + case V4L2_TUNER_MODE_LANG1_LANG2: msp_write_dsp(client, 0x000e, 0x3000); break; } @@ -261,6 +262,7 @@ static void msp3400c_set_audmode(struct i2c_client *client) msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); break; case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1_LANG2: msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); break; case V4L2_TUNER_MODE_LANG1: @@ -296,6 +298,7 @@ static void msp3400c_set_audmode(struct i2c_client *client) /* switch audio */ switch (state->audmode) { case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1_LANG2: src |= 0x0020; break; case V4L2_TUNER_MODE_MONO: @@ -835,6 +838,7 @@ static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) matrix = 0x10; break; case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1_LANG2: default: source = 1; /* stereo or A|B */ matrix = 0x20; diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 14ca251787d5..b0aea4002d11 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -790,6 +790,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n")); break; } + case V4L2_TUNER_MODE_LANG1_LANG2: { + mxb->cur_mode = V4L2_TUNER_MODE_LANG1_LANG2; + byte = TDA9840_SET_BOTH; + DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n")); + break; + } case V4L2_TUNER_MODE_LANG1: { mxb->cur_mode = V4L2_TUNER_MODE_LANG1; byte = TDA9840_SET_LANG1; diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 3043233a8b6e..0db53d192b2a 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -482,12 +482,14 @@ static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au [ V4L2_TUNER_MODE_STEREO ] = "stereo", [ V4L2_TUNER_MODE_LANG1 ] = "lang1", [ V4L2_TUNER_MODE_LANG2 ] = "lang2", + [ V4L2_TUNER_MODE_LANG1_LANG2 ] = "lang1+lang2", }; static u32 fm[] = { [ V4L2_TUNER_MODE_MONO ] = 0x00, /* ch1 */ [ V4L2_TUNER_MODE_STEREO ] = 0x80, /* auto */ [ V4L2_TUNER_MODE_LANG1 ] = 0x00, /* ch1 */ [ V4L2_TUNER_MODE_LANG2 ] = 0x01, /* ch2 */ + [ V4L2_TUNER_MODE_LANG1_LANG2 ] = 0x80, /* auto */ }; u32 reg; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 4e6d030d83c0..356bff455ad1 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1733,6 +1733,7 @@ static int chip_command(struct i2c_client *client, mode = VIDEO_SOUND_MONO; break; case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1_LANG2: mode = VIDEO_SOUND_STEREO; break; case V4L2_TUNER_MODE_LANG1: diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 724cfbf54b8a..2275bfec5b68 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -883,6 +883,7 @@ struct v4l2_modulator #define V4L2_TUNER_MODE_LANG2 0x0002 #define V4L2_TUNER_MODE_SAP 0x0002 #define V4L2_TUNER_MODE_LANG1 0x0003 +#define V4L2_TUNER_MODE_LANG1_LANG2 0x0004 struct v4l2_frequency { -- cgit v1.2.3-59-g8ed1b From c68735180c6e274d938b8c07d61dcf5077085c7f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 19 Mar 2006 18:43:50 -0300 Subject: V4L/DVB (3587): Always wake thread after routing change. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-driver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 8ba1c960388a..fb3d1f41f116 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -702,8 +702,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp_set_scart(client, sc1_out, 1); msp_set_scart(client, sc2_out, 2); msp_set_audmode(client); - if (tuner != old_tuner) - msp_wake_thread(client); + msp_wake_thread(client); break; } -- cgit v1.2.3-59-g8ed1b From e3bb83420346534b51a500e3b13f75e269c3dd60 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 20 Mar 2006 16:32:52 -0300 Subject: V4L/DVB (3588): Remove VIDIOC_G/S_AUDOUT from msp3400 VIDIOC_G/S_AUDOUT does not belong in msp3400 (it's a user level command, not to be used in internal i2c drivers). Also fix a compile warning and improve LOG_STATUS. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-driver.c | 39 ++---------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index fb3d1f41f116..c40e8ba9a2ea 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -684,7 +684,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct v4l2_routing *rt = arg; int tuner = (rt->input >> 3) & 1; - int old_tuner = (state->routing.input >> 3) & 1; int sc_in = rt->input & 0x7; int sc1_out = rt->output & 0xf; int sc2_out = (rt->output >> 4) & 0xf; @@ -733,42 +732,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } - case VIDIOC_G_AUDOUT: - { - struct v4l2_audioout *a = (struct v4l2_audioout *)arg; - int idx = a->index; - - memset(a, 0, sizeof(*a)); - - switch (idx) { - case 0: - strcpy(a->name, "Scart1 Out"); - break; - case 1: - strcpy(a->name, "Scart2 Out"); - break; - case 2: - strcpy(a->name, "I2S Out"); - break; - default: - return -EINVAL; - } - break; - } - - case VIDIOC_S_AUDOUT: - { - struct v4l2_audioout *a = (struct v4l2_audioout *)arg; - - if (a->index < 0 || a->index > 2) - return -EINVAL; - - v4l_dbg(1, msp_debug, client, "Setting audio out on msp34xx to input %i\n", a->index); - msp_set_scart(client, state->in_scart, a->index + 1); - - break; - } - case VIDIOC_INT_I2S_CLOCK_FREQ: { u32 *a = (u32 *)arg; @@ -854,6 +817,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); } v4l_info(client, "Audmode: 0x%04x\n", state->audmode); + v4l_info(client, "Routing: 0x%08x (input) 0x%08x (output)\n", + state->routing.input, state->routing.output); v4l_info(client, "ACB: 0x%04x\n", state->acb); break; } -- cgit v1.2.3-59-g8ed1b From f13df9195b2b4db874ba2d6bd1c2a09ea64d39e0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 23 Mar 2006 22:01:44 -0300 Subject: V4L/DVB (3597): Vivi: fix warning: implicit declaration of function 'in_interrupt' Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index e9bb5dad84d5..5e813404d068 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3-59-g8ed1b From 7fa033b103bc3f5c37f934695473f63adf140dba Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 23 Mar 2006 20:12:26 -0300 Subject: V4L/DVB (3599): Implement new routing commands for wm8775 and cs53l32a. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cs53l32a.c | 15 ++++++++++----- drivers/media/video/wm8775.c | 15 ++++++++++----- include/media/cs53l32a.h | 34 ++++++++++++++++++++++++++++++++++ include/media/wm8775.h | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 10 deletions(-) create mode 100644 include/media/cs53l32a.h create mode 100644 include/media/wm8775.h (limited to 'drivers') diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c index bc3331870240..de87247c74ee 100644 --- a/drivers/media/video/cs53l32a.c +++ b/drivers/media/video/cs53l32a.c @@ -59,20 +59,25 @@ static int cs53l32a_read(struct i2c_client *client, u8 reg) static int cs53l32a_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct v4l2_audio *input = arg; + struct v4l2_routing *route = arg; struct v4l2_control *ctrl = arg; switch (cmd) { - case VIDIOC_S_AUDIO: + case VIDIOC_INT_G_AUDIO_ROUTING: + route->input = (cs53l32a_read(client, 0x01) >> 4) & 3; + route->output = 0; + break; + + case VIDIOC_INT_S_AUDIO_ROUTING: /* There are 2 physical inputs, but the second input can be placed in two modes, the first mode bypasses the PGA (gain), the second goes through the PGA. Hence there are three possible inputs to choose from. */ - if (input->index > 2) { - v4l_err(client, "Invalid input %d.\n", input->index); + if (route->input > 2) { + v4l_err(client, "Invalid input %d.\n", route->input); return -EINVAL; } - cs53l32a_write(client, 0x01, 0x01 + (input->index << 4)); + cs53l32a_write(client, 0x01, 0x01 + (route->input << 4)); break; case VIDIOC_G_CTRL: diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 9b90225226e6..d81a88bbe43d 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -79,21 +79,26 @@ static int wm8775_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct wm8775_state *state = i2c_get_clientdata(client); - struct v4l2_audio *input = arg; + struct v4l2_routing *route = arg; struct v4l2_control *ctrl = arg; switch (cmd) { - case VIDIOC_S_AUDIO: + case VIDIOC_INT_G_AUDIO_ROUTING: + route->input = state->input; + route->output = 0; + break; + + case VIDIOC_INT_S_AUDIO_ROUTING: /* There are 4 inputs and one output. Zero or more inputs are multiplexed together to the output. Hence there are 16 combinations. If only one input is active (the normal case) then the input values 1, 2, 4 or 8 should be used. */ - if (input->index > 15) { - v4l_err(client, "Invalid input %d.\n", input->index); + if (route->input > 15) { + v4l_err(client, "Invalid input %d.\n", route->input); return -EINVAL; } - state->input = input->index; + state->input = route->input; if (state->muted) break; wm8775_write(client, R21, 0x0c0); diff --git a/include/media/cs53l32a.h b/include/media/cs53l32a.h new file mode 100644 index 000000000000..bf76197d3790 --- /dev/null +++ b/include/media/cs53l32a.h @@ -0,0 +1,34 @@ +/* + cs53l32a.h - definition for cs53l32a inputs and outputs + + Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + + 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. +*/ + +#ifndef _CS53L32A_H_ +#define _CS53L32A_H_ + +/* There are 2 physical inputs, but the second input can be + placed in two modes, the first mode bypasses the PGA (gain), + the second goes through the PGA. Hence there are three + possible inputs to choose from. */ + +/* CS53L32A HW inputs */ +#define CS53L32A_IN0 0 +#define CS53L32A_IN1 1 +#define CS53L32A_IN2 2 + +#endif diff --git a/include/media/wm8775.h b/include/media/wm8775.h new file mode 100644 index 000000000000..60739c5a23ae --- /dev/null +++ b/include/media/wm8775.h @@ -0,0 +1,35 @@ +/* + wm8775.h - definition for wm8775 inputs and outputs + + Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + + 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. +*/ + +#ifndef _WM8775_H_ +#define _WM8775_H_ + +/* The WM8775 has 4 inputs and one output. Zero or more inputs + are multiplexed together to the output. Hence there are + 16 combinations. + If only one input is active (the normal case) then the + input values 1, 2, 4 or 8 should be used. */ + +#define WM8775_AIN1 1 +#define WM8775_AIN2 2 +#define WM8775_AIN3 4 +#define WM8775_AIN4 8 + +#endif -- cgit v1.2.3-59-g8ed1b From 6f633c8d69415aabbccfcc494008e8e1300a98c1 Mon Sep 17 00:00:00 2001 From: Leonid Arsh Date: Fri, 24 Mar 2006 15:47:25 -0800 Subject: IPoIB: Pass correct pointer when flushing child interfaces ipoib_ib_dev_flush() should get passed cpriv->dev, not &cpriv->dev. Signed-off-by: Leonid Arsh Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index a1f5a05f2f36..f2be500f62c8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -605,7 +605,7 @@ void ipoib_ib_dev_flush(void *_dev) /* Flush any child interfaces too */ list_for_each_entry(cpriv, &priv->child_intfs, list) - ipoib_ib_dev_flush(&cpriv->dev); + ipoib_ib_dev_flush(cpriv->dev); mutex_unlock(&priv->vlan_mutex); } -- cgit v1.2.3-59-g8ed1b From 868d2c1efe9cdd259b67a80d60a7fb2fcecd3d68 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 24 Mar 2006 15:47:25 -0800 Subject: [WIRELESS]: Fix config dependencies. I accidentally ended up with a config that set NET_RADIO off, and NET_WIRELESS_RTNETLINK on, which blew up thus.. net/built-in.o: In function `do_setlink':net/core/rtnetlink.c:479: undefined reference to `wireless_rtnetlink_set' net/built-in.o: In function `do_getlink':net/core/rtnetlink.c:521: undefined reference to `wireless_rtnetlink_get' Signed-off-by: Dave Jones Signed-off-by: David S. Miller --- drivers/net/wireless/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 6a1033ec06cf..fd17aa8491b6 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -27,6 +27,7 @@ config NET_RADIO config NET_WIRELESS_RTNETLINK bool "Wireless Extension API over RtNetlink" + depends on NET_RADIO ---help--- Support the Wireless Extension API over the RtNetlink socket in addition to the traditional ioctl interface (selected above). -- cgit v1.2.3-59-g8ed1b From cf368713a3f3b2eb737a92d1b7186dedcc51167c Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 24 Mar 2006 15:47:26 -0800 Subject: IB/srp: Use a fake scatterlist for non-SG SCSI commands Since the SCSI midlayer is moving towards entirely getting rid of commands with use_sg == 0, we should treat this case as an exception. Therefore, change the IB SRP initiator to create a fake scatterlist for these commands with sg_init_one(). This simplifies the flow of DMA mapping and unmapping, since SRP can just use dma_map_sg() and dma_unmap_sg() unconditionally, rather than having to choose between the dma_{map,unmap}_sg() and dma_{map,unmap}_single() variants. Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 145 +++++++++++++++++------------------- drivers/infiniband/ulp/srp/ib_srp.h | 7 +- 2 files changed, 75 insertions(+), 77 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index a13dcdf90a4f..61924cc30e55 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -503,8 +503,10 @@ err: static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, struct srp_request *req) { + struct scatterlist *scat; struct srp_cmd *cmd = req->cmd->buf; - int len; + int len, nents, count; + int i; u8 fmt; if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE) @@ -517,82 +519,66 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, return -EINVAL; } - if (scmnd->use_sg) { - struct scatterlist *scat = scmnd->request_buffer; - int n; - int i; - - n = dma_map_sg(target->srp_host->dev->dma_device, - scat, scmnd->use_sg, scmnd->sc_data_direction); + /* + * This handling of non-SG commands can be killed when the + * SCSI midlayer no longer generates non-SG commands. + */ + if (likely(scmnd->use_sg)) { + nents = scmnd->use_sg; + scat = scmnd->request_buffer; + } else { + nents = 1; + scat = &req->fake_sg; + sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen); + } - if (n == 1) { - struct srp_direct_buf *buf = (void *) cmd->add_data; + count = dma_map_sg(target->srp_host->dev->dma_device, scat, nents, + scmnd->sc_data_direction); - fmt = SRP_DATA_DESC_DIRECT; + if (count == 1) { + struct srp_direct_buf *buf = (void *) cmd->add_data; - buf->va = cpu_to_be64(sg_dma_address(scat)); - buf->key = cpu_to_be32(target->srp_host->mr->rkey); - buf->len = cpu_to_be32(sg_dma_len(scat)); + fmt = SRP_DATA_DESC_DIRECT; - len = sizeof (struct srp_cmd) + - sizeof (struct srp_direct_buf); - } else { - struct srp_indirect_buf *buf = (void *) cmd->add_data; - u32 datalen = 0; + buf->va = cpu_to_be64(sg_dma_address(scat)); + buf->key = cpu_to_be32(target->srp_host->mr->rkey); + buf->len = cpu_to_be32(sg_dma_len(scat)); - fmt = SRP_DATA_DESC_INDIRECT; + len = sizeof (struct srp_cmd) + + sizeof (struct srp_direct_buf); + } else { + struct srp_indirect_buf *buf = (void *) cmd->add_data; + u32 datalen = 0; - if (scmnd->sc_data_direction == DMA_TO_DEVICE) - cmd->data_out_desc_cnt = n; - else - cmd->data_in_desc_cnt = n; + fmt = SRP_DATA_DESC_INDIRECT; - buf->table_desc.va = cpu_to_be64(req->cmd->dma + - sizeof *cmd + - sizeof *buf); - buf->table_desc.key = + if (scmnd->sc_data_direction == DMA_TO_DEVICE) + cmd->data_out_desc_cnt = count; + else + cmd->data_in_desc_cnt = count; + + buf->table_desc.va = cpu_to_be64(req->cmd->dma + + sizeof *cmd + + sizeof *buf); + buf->table_desc.key = + cpu_to_be32(target->srp_host->mr->rkey); + buf->table_desc.len = + cpu_to_be32(count * sizeof (struct srp_direct_buf)); + + for (i = 0; i < count; ++i) { + buf->desc_list[i].va = cpu_to_be64(sg_dma_address(&scat[i])); + buf->desc_list[i].key = cpu_to_be32(target->srp_host->mr->rkey); - buf->table_desc.len = - cpu_to_be32(n * sizeof (struct srp_direct_buf)); - - for (i = 0; i < n; ++i) { - buf->desc_list[i].va = cpu_to_be64(sg_dma_address(&scat[i])); - buf->desc_list[i].key = - cpu_to_be32(target->srp_host->mr->rkey); - buf->desc_list[i].len = cpu_to_be32(sg_dma_len(&scat[i])); - - datalen += sg_dma_len(&scat[i]); - } + buf->desc_list[i].len = cpu_to_be32(sg_dma_len(&scat[i])); - buf->len = cpu_to_be32(datalen); - - len = sizeof (struct srp_cmd) + - sizeof (struct srp_indirect_buf) + - n * sizeof (struct srp_direct_buf); - } - } else { - struct srp_direct_buf *buf = (void *) cmd->add_data; - dma_addr_t dma; - - dma = dma_map_single(target->srp_host->dev->dma_device, - scmnd->request_buffer, scmnd->request_bufflen, - scmnd->sc_data_direction); - if (dma_mapping_error(dma)) { - printk(KERN_WARNING PFX "unable to map %p/%d (dir %d)\n", - scmnd->request_buffer, (int) scmnd->request_bufflen, - scmnd->sc_data_direction); - return -EINVAL; + datalen += sg_dma_len(&scat[i]); } - pci_unmap_addr_set(req, direct_mapping, dma); + buf->len = cpu_to_be32(datalen); - buf->va = cpu_to_be64(dma); - buf->key = cpu_to_be32(target->srp_host->mr->rkey); - buf->len = cpu_to_be32(scmnd->request_bufflen); - - fmt = SRP_DATA_DESC_DIRECT; - - len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf); + len = sizeof (struct srp_cmd) + + sizeof (struct srp_indirect_buf) + + count * sizeof (struct srp_direct_buf); } if (scmnd->sc_data_direction == DMA_TO_DEVICE) @@ -600,7 +586,6 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, else cmd->buf_fmt = fmt; - return len; } @@ -608,20 +593,28 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, struct srp_request *req) { + struct scatterlist *scat; + int nents; + if (!scmnd->request_buffer || (scmnd->sc_data_direction != DMA_TO_DEVICE && scmnd->sc_data_direction != DMA_FROM_DEVICE)) - return; + return; - if (scmnd->use_sg) - dma_unmap_sg(target->srp_host->dev->dma_device, - (struct scatterlist *) scmnd->request_buffer, - scmnd->use_sg, scmnd->sc_data_direction); - else - dma_unmap_single(target->srp_host->dev->dma_device, - pci_unmap_addr(req, direct_mapping), - scmnd->request_bufflen, - scmnd->sc_data_direction); + /* + * This handling of non-SG commands can be killed when the + * SCSI midlayer no longer generates non-SG commands. + */ + if (likely(scmnd->use_sg)) { + nents = scmnd->use_sg; + scat = (struct scatterlist *) scmnd->request_buffer; + } else { + nents = 1; + scat = (struct scatterlist *) scmnd->request_buffer; + } + + dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents, + scmnd->sc_data_direction); } static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index 4e7727df32f1..bd7f7c3115de 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -94,7 +95,11 @@ struct srp_request { struct scsi_cmnd *scmnd; struct srp_iu *cmd; struct srp_iu *tsk_mgmt; - DECLARE_PCI_UNMAP_ADDR(direct_mapping) + /* + * Fake scatterlist used when scmnd->use_sg==0. Can be killed + * when the SCSI midlayer no longer generates non-SG commands. + */ + struct scatterlist fake_sg; struct completion done; short next; u8 cmd_done; -- cgit v1.2.3-59-g8ed1b From 0ef61db837c93d4377fabd37182bb6f83ea5ca70 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Sun, 19 Mar 2006 17:20:36 +0200 Subject: IB/mthca: Check that sgid_index and path_mtu are valid in modify_qp Add a check that the modify QP parameters sgid_index and path_mtu are valid, since they might come from userspace. Signed-off-by: Dotan Barak Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_qp.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index f673c461e30b..c4b74dbc16f2 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -483,13 +483,20 @@ out: return err; } -static void mthca_path_set(struct ib_ah_attr *ah, struct mthca_qp_path *path) +static int mthca_path_set(struct mthca_dev *dev, struct ib_ah_attr *ah, + struct mthca_qp_path *path) { path->g_mylmc = ah->src_path_bits & 0x7f; path->rlid = cpu_to_be16(ah->dlid); path->static_rate = !!ah->static_rate; if (ah->ah_flags & IB_AH_GRH) { + if (ah->grh.sgid_index >= dev->limits.gid_table_len) { + mthca_dbg(dev, "sgid_index (%u) too large. max is %d\n", + ah->grh.sgid_index, dev->limits.gid_table_len-1); + return -1; + } + path->g_mylmc |= 1 << 7; path->mgid_index = ah->grh.sgid_index; path->hop_limit = ah->grh.hop_limit; @@ -500,6 +507,8 @@ static void mthca_path_set(struct ib_ah_attr *ah, struct mthca_qp_path *path) memcpy(path->rgid, ah->grh.dgid.raw, 16); } else path->sl_tclass_flowlabel = cpu_to_be32(ah->sl << 28); + + return 0; } int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) @@ -592,8 +601,14 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) if (qp->transport == MLX || qp->transport == UD) qp_context->mtu_msgmax = (IB_MTU_2048 << 5) | 11; - else if (attr_mask & IB_QP_PATH_MTU) + else if (attr_mask & IB_QP_PATH_MTU) { + if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_2048) { + mthca_dbg(dev, "path MTU (%u) is invalid\n", + attr->path_mtu); + return -EINVAL; + } qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31; + } if (mthca_is_memfree(dev)) { if (qp->rq.max) @@ -642,7 +657,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) } if (attr_mask & IB_QP_AV) { - mthca_path_set(&attr->ah_attr, &qp_context->pri_path); + if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path)) + return -EINVAL; + qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH); } @@ -664,7 +681,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) return -EINVAL; } - mthca_path_set(&attr->alt_ah_attr, &qp_context->alt_path); + if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path)) + return -EINVAL; + qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index | attr->alt_port_num << 24); qp_context->alt_path.ackto = attr->alt_timeout << 3; -- cgit v1.2.3-59-g8ed1b From ded9ad721d220d47989177076a181ae1f1b93af5 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Mon, 20 Mar 2006 12:35:34 +0200 Subject: IB/mthca: Check that SRQ WQE size does not exceed device's max value Guarantee the calculated work queue entry size does not exceed the max allowable WQE size when creating an SRQ. This is a problem with Arbel in Tavor-compatibility mode because the current WQE size computation method rounds up to next power of 2. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_srq.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 47a6a754a591..4e671e00e42b 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -205,6 +205,10 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, ds = max(64UL, roundup_pow_of_two(sizeof (struct mthca_next_seg) + srq->max_gs * sizeof (struct mthca_data_seg))); + + if (ds > dev->limits.max_desc_sz) + return -EINVAL; + srq->wqe_shift = long_log2(ds); srq->srqn = mthca_alloc(&dev->srq_table.alloc); -- cgit v1.2.3-59-g8ed1b From d4301e2c6685c87206f24f54969120b182119ab0 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Mon, 20 Mar 2006 17:32:43 +0200 Subject: IB/mthca: Check SRQ limit in modify SRQ operation When setting the shared receive queue (SRQ) watermark in a modify SRQ operation, make sure that the supplied value is not larger than the full size of the SRQ. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_srq.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 4e671e00e42b..0cfd15802217 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -358,6 +358,8 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, return -EINVAL; if (attr_mask & IB_SRQ_LIMIT) { + if (attr->srq_limit > srq->max) + return -EINVAL; ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status); if (ret) return ret; -- cgit v1.2.3-59-g8ed1b From b3f64967fafad2d3487cdba18bc5166aec33a823 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Wed, 22 Mar 2006 09:52:31 +0200 Subject: IB/mthca: Fix uninitialized variable in mthca_alloc_qp() mthca_alloc_sqp() by mthca_set_qp_size() need to set qp->transport before calling mthca_set_qp_size(), since the value is used there. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_qp.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index c4b74dbc16f2..361c6ce3a9ff 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -1196,10 +1196,6 @@ int mthca_alloc_qp(struct mthca_dev *dev, { int err; - err = mthca_set_qp_size(dev, cap, pd, qp); - if (err) - return err; - switch (type) { case IB_QPT_RC: qp->transport = RC; break; case IB_QPT_UC: qp->transport = UC; break; @@ -1207,6 +1203,10 @@ int mthca_alloc_qp(struct mthca_dev *dev, default: return -EINVAL; } + err = mthca_set_qp_size(dev, cap, pd, qp); + if (err) + return err; + qp->qpn = mthca_alloc(&dev->qp_table.alloc); if (qp->qpn == -1) return -ENOMEM; @@ -1239,6 +1239,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev, u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1; int err; + sqp->qp.transport = MLX; err = mthca_set_qp_size(dev, cap, pd, &sqp->qp); if (err) return err; -- cgit v1.2.3-59-g8ed1b From b0b3a8e1939d18c9bd4caca0b4b859b118a4167e Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 24 Mar 2006 15:47:29 -0800 Subject: IB/mthca: Fix indentation Fix some whitespace damage (indenting with spaces) that snuck in. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_qp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 361c6ce3a9ff..a09873d2ef5e 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -2000,8 +2000,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, wmb(); ((struct mthca_next_seg *) prev_wqe)->ee_nds = cpu_to_be32(MTHCA_NEXT_DBD | size | - ((wr->send_flags & IB_SEND_FENCE) ? - MTHCA_NEXT_FENCE : 0)); + ((wr->send_flags & IB_SEND_FENCE) ? + MTHCA_NEXT_FENCE : 0)); if (!size0) { size0 = size; -- cgit v1.2.3-59-g8ed1b From 4e37b956161c3a3b160972c11c55f07b38b9830c Mon Sep 17 00:00:00 2001 From: Leonid Arsh Date: Wed, 22 Mar 2006 19:54:24 +0200 Subject: IPoIB: Fix network interface "RUNNING" status With the current IPoIB driver, the status of network interfaces stays "RUNNING" even if the link goes down (for example because a cable is unplugged). Fix this by flushing the IPoIB interface when the link goes down. Signed-off-by: Leonid Arsh Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_verbs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index 18d2f53ec34c..a35b798b8128 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c @@ -251,10 +251,11 @@ void ipoib_event(struct ib_event_handler *handler, struct ipoib_dev_priv *priv = container_of(handler, struct ipoib_dev_priv, event_handler); - if (record->event == IB_EVENT_PORT_ACTIVE || + if (record->event == IB_EVENT_PORT_ERR || + record->event == IB_EVENT_PORT_ACTIVE || record->event == IB_EVENT_LID_CHANGE || record->event == IB_EVENT_SM_CHANGE) { - ipoib_dbg(priv, "Port active event\n"); + ipoib_dbg(priv, "Port state change event\n"); queue_work(ipoib_workqueue, &priv->flush_task); } } -- cgit v1.2.3-59-g8ed1b From 192daa18dd7bfcaeb092a2ef928135745f2e6883 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 24 Mar 2006 15:47:30 -0800 Subject: IB/mthca: Fix modify QP error path If the call to mthca_MODIFY_QP() failed, then mthca_modify_qp() would still do some things it shouldn't, such as store away attributes for special QPs. Fix this, and simplify the code, by simply jumping to the exit path if mthca_MODIFY_QP() fails. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_qp.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index a09873d2ef5e..1bc2678c2fae 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -777,21 +777,20 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) err = mthca_MODIFY_QP(dev, cur_state, new_state, qp->qpn, 0, mailbox, sqd_event, &status); + if (err) + goto out; if (status) { mthca_warn(dev, "modify QP %d->%d returned status %02x.\n", cur_state, new_state, status); err = -EINVAL; + goto out; } - if (!err) { - qp->state = new_state; - if (attr_mask & IB_QP_ACCESS_FLAGS) - qp->atomic_rd_en = attr->qp_access_flags; - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) - qp->resp_depth = attr->max_dest_rd_atomic; - } - - mthca_free_mailbox(dev, mailbox); + qp->state = new_state; + if (attr_mask & IB_QP_ACCESS_FLAGS) + qp->atomic_rd_en = attr->qp_access_flags; + if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) + qp->resp_depth = attr->max_dest_rd_atomic; if (is_sqp(dev, qp)) store_attrs(to_msqp(qp), attr, attr_mask); @@ -816,7 +815,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) * If we moved a kernel QP to RESET, clean up all old CQ * entries and reinitialize the QP. */ - if (!err && new_state == IB_QPS_RESET && !qp->ibqp.uobject) { + if (new_state == IB_QPS_RESET && !qp->ibqp.uobject) { mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn, qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL); if (qp->ibqp.send_cq != qp->ibqp.recv_cq) @@ -835,6 +834,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) } } +out: + mthca_free_mailbox(dev, mailbox); return err; } -- cgit v1.2.3-59-g8ed1b From 7a343d4c46bc59fe617f968e996ce2fd67c5d179 Mon Sep 17 00:00:00 2001 From: Leonid Arsh Date: Thu, 23 Mar 2006 19:52:51 +0200 Subject: IPoIB: P_Key change event handling This patch causes the network interface to respond to P_Key change events correctly. As a result, you'll see a child interface in the "RUNNING" state (netif_carrier_on()) only when the corresponding P_Key is configured by the SM. When SM removes a P_Key, the "RUNNING" state will be disabled for the corresponding network interface. To implement this, I added IB_EVENT_PKEY_CHANGE event handling. To prevent flushing the device before the device is open by the "delay open" mechanism, I added an additional device flag called IPOIB_FLAG_INITIALIZED. This also prevents the child network interface from trying to join to multicast groups until the PKEY is configured. We used to get error messages like: ib0.f2f2: couldn't attach QP to multicast group ff12:401b:f2f2:0:0:0:ffff:ffff in this case. To fix this, I just check IPOIB_FLAG_OPER_UP flag in ipoib_set_mcast_list(). Signed-off-by: Leonid Arsh Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib.h | 15 ++++++----- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 42 +++++++++++++++++++++--------- drivers/infiniband/ulp/ipoib/ipoib_main.c | 5 ++++ drivers/infiniband/ulp/ipoib/ipoib_verbs.c | 1 + 4 files changed, 44 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 1251f86ec856..b640107fb732 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -72,13 +72,14 @@ enum { IPOIB_MAX_MCAST_QUEUE = 3, IPOIB_FLAG_OPER_UP = 0, - IPOIB_FLAG_ADMIN_UP = 1, - IPOIB_PKEY_ASSIGNED = 2, - IPOIB_PKEY_STOP = 3, - IPOIB_FLAG_SUBINTERFACE = 4, - IPOIB_MCAST_RUN = 5, - IPOIB_STOP_REAPER = 6, - IPOIB_MCAST_STARTED = 7, + IPOIB_FLAG_INITIALIZED = 1, + IPOIB_FLAG_ADMIN_UP = 2, + IPOIB_PKEY_ASSIGNED = 3, + IPOIB_PKEY_STOP = 4, + IPOIB_FLAG_SUBINTERFACE = 5, + IPOIB_MCAST_RUN = 6, + IPOIB_STOP_REAPER = 7, + IPOIB_MCAST_STARTED = 8, IPOIB_MAX_BACKOFF_SECONDS = 16, diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index f2be500f62c8..ed65202878d8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -423,13 +423,33 @@ int ipoib_ib_dev_open(struct net_device *dev) clear_bit(IPOIB_STOP_REAPER, &priv->flags); queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, HZ); + set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); + return 0; } +static void ipoib_pkey_dev_check_presence(struct net_device *dev) +{ + struct ipoib_dev_priv *priv = netdev_priv(dev); + u16 pkey_index = 0; + + if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) + clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); + else + set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); +} + int ipoib_ib_dev_up(struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); + ipoib_pkey_dev_check_presence(dev); + + if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { + ipoib_dbg(priv, "PKEY is not assigned.\n"); + return 0; + } + set_bit(IPOIB_FLAG_OPER_UP, &priv->flags); return ipoib_mcast_start_thread(dev); @@ -483,6 +503,8 @@ int ipoib_ib_dev_stop(struct net_device *dev) struct ipoib_tx_buf *tx_req; int i; + clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); + /* * Move our QP to the error state and then reinitialize in * when all work requests have completed or have been flushed. @@ -587,8 +609,15 @@ void ipoib_ib_dev_flush(void *_dev) struct net_device *dev = (struct net_device *)_dev; struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv; - if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) + if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) ) { + ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n"); + return; + } + + if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) { + ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_ADMIN_UP not set.\n"); return; + } ipoib_dbg(priv, "flushing\n"); @@ -632,17 +661,6 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) * change async notification is available. */ -static void ipoib_pkey_dev_check_presence(struct net_device *dev) -{ - struct ipoib_dev_priv *priv = netdev_priv(dev); - u16 pkey_index = 0; - - if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) - clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); - else - set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); -} - void ipoib_pkey_poll(void *dev_ptr) { struct net_device *dev = dev_ptr; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 37da8d3dc388..53a32f65788d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -736,6 +736,11 @@ static void ipoib_set_mcast_list(struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); + if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) { + ipoib_dbg(priv, "IPOIB_FLAG_OPER_UP not set"); + return; + } + queue_work(ipoib_workqueue, &priv->restart_task); } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index a35b798b8128..5f0388027b25 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c @@ -252,6 +252,7 @@ void ipoib_event(struct ib_event_handler *handler, container_of(handler, struct ipoib_dev_priv, event_handler); if (record->event == IB_EVENT_PORT_ERR || + record->event == IB_EVENT_PKEY_CHANGE || record->event == IB_EVENT_PORT_ACTIVE || record->event == IB_EVENT_LID_CHANGE || record->event == IB_EVENT_SM_CHANGE) { -- cgit v1.2.3-59-g8ed1b From 5c48b0e3599ff7559b39093219e8a428776f7932 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Thu, 23 Mar 2006 21:29:19 +0100 Subject: [AGPGART] x86_64: Fix wrong PCI ID for ALI M1695 AGP bridge [description by AK] Made a cut'n'paste error when adding the entry for the ALI M1695 AGP bridge and added a second entry for the 1689 Signed-off-by: Andi Kleen Signed-off-by: Dave Jones --- drivers/char/agp/amd64-agp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index cccf05fdc6cb..36517d4d1ad9 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -725,7 +725,7 @@ static struct pci_device_id agp_amd64_pci_table[] = { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_AL, - .device = 0x1689, + .device = 0x1695, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, -- cgit v1.2.3-59-g8ed1b From 9d1f6b28ee2429a1f94a9f7074ffae7f918d33be Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 23 Mar 2006 21:31:34 +0100 Subject: [AGPGART] x86_64: Enable VIA AGP driver on x86-64 for VIA P4 chipsets Untested so far [davej: but needed for some newer EM64T systems] Signed-off-by: Andi Kleen Signed-off-by: Dave Jones --- drivers/char/agp/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 80d86a9d2e63..0b9cf9c59a21 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -103,7 +103,7 @@ config AGP_SWORKS config AGP_VIA tristate "VIA chipset support" - depends on AGP && X86_32 + depends on AGP help This option gives you AGP support for the GLX component of X on VIA MVP3/Apollo Pro chipsets. -- cgit v1.2.3-59-g8ed1b From 298a41ca41b4c933adc7b5a56a0adb0e1df2e556 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 25 Mar 2006 02:58:13 +0900 Subject: [PATCH] libata: cosmetic changes in ata_bus_softreset() ata_bus_softreset() should return AC_ERR_* on failure not arbitrary positive number. While at it, reformat comment above it. Signed-off-by: Tejun Heo Acked-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 0aff888d9ecd..64f71df19ed1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2008,13 +2008,12 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, */ msleep(150); - /* Before we perform post reset processing we want to see if - the bus shows 0xFF because the odd clown forgets the D7 pulldown - resistor */ - + * the bus shows 0xFF because the odd clown forgets the D7 + * pulldown resistor. + */ if (ata_check_status(ap) == 0xFF) - return 1; /* Positive is failure for some reason */ + return AC_ERR_OTHER; ata_bus_post_reset(ap, devmask); -- cgit v1.2.3-59-g8ed1b From 600511e86babe3727264a0883a3a264f6fb6caf5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 25 Mar 2006 11:14:07 +0900 Subject: [PATCH] libata: add FIXME above ata_dev_xfermask() Add FIXME above ata_dev_xfermask noting that the current implementation limits all transfer modes to the fastest of the slowest device on a port which isn't necessary. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 64f71df19ed1..1cb981375323 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2633,6 +2633,10 @@ static int ata_dma_blacklisted(const struct ata_device *dev) * known limits including host controller limits, device * blacklist, etc... * + * FIXME: The current implementation limits all transfer modes to + * the fastest of the lowested device on the port. This is not + * required on most controllers. + * * LOCKING: * None. */ -- cgit v1.2.3-59-g8ed1b From f3dd5c37382472a8b245ad791ed768771594e60c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 25 Mar 2006 18:09:46 +1100 Subject: drm: add new radeon PCI ids.. This adds all the r300 and r400 PCI ids from DRM CVS, it also makes these cards only initialise when the new xorg driver is used, as otherwise the DRM can cause lockups. Signed-off-by: Dave Airlie --- drivers/char/drm/drm_pciids.h | 99 +++++++++++++++++++++++++++++++------------ drivers/char/drm/radeon_cp.c | 8 ++++ drivers/char/drm/radeon_drv.h | 1 + 3 files changed, 81 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 24b80357b967..b1bb3c7b568d 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -3,18 +3,27 @@ Please contact dri-devel@lists.sf.net to add new cards to this list */ #define radeon_PCI_IDS \ - {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY},\ + {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ + {0x1002, 0x4148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x4149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x414A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x414B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ + {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ @@ -24,8 +33,20 @@ {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ - {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ - {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ + {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ @@ -35,14 +56,16 @@ {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ - {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ + {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ - {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ + {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ @@ -50,44 +73,66 @@ {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x5149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \ {0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \ {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ - {0x1002, 0x5168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x5169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x516A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ - {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ - {0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ - {0x1002, 0x5837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x5963, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x5968, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ + {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ - {0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ + {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ - {0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ - {0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ - {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ + {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ {0, 0, 0} #define r128_PCI_IDS \ diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index cc4942a112cb..7f949c9c9691 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -1332,6 +1332,14 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) DRM_DEBUG("\n"); + /* if we require new memory map but we don't have it fail */ + if ((dev_priv->flags & CHIP_NEW_MEMMAP) && !dev_priv->new_memmap) + { + DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX\n"); + radeon_do_cleanup_cp(dev); + return DRM_ERR(EINVAL); + } + if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP)) { DRM_DEBUG("Forcing AGP card to PCI mode\n"); diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 31bacfa2edee..78345cee8f8e 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -139,6 +139,7 @@ enum radeon_chip_flags { CHIP_IS_AGP = 0x00080000UL, CHIP_HAS_HIERZ = 0x00100000UL, CHIP_IS_PCIE = 0x00200000UL, + CHIP_NEW_MEMMAP = 0x00400000UL, }; #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ -- cgit v1.2.3-59-g8ed1b From 9f6933be665ce3b049c274c99810ac754edabf19 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 25 Mar 2006 09:05:39 -0300 Subject: V4L/DVB (3599a): Move drivers/usb/media to drivers/media/video Because of historic reasons, there are two separate directories with V4L stuff. Most drivers are located at driver/media/video. However, some code for USB Webcams were inserted under drivers/usb/media. This makes difficult for module authors to know were things should be. Also, makes Kconfig menu confusing for normal users. This patch moves all V4L content under drivers/usb/media to drivers/media/video, and fixes Kconfig/Makefile entries. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 14 + drivers/media/video/Kconfig | 232 +- drivers/media/video/Makefile | 19 + drivers/media/video/dabfirmware.h | 1408 +++++ drivers/media/video/dabusb.c | 874 +++ drivers/media/video/dabusb.h | 85 + drivers/media/video/dsbr100.c | 429 ++ drivers/media/video/et61x251/Makefile | 4 + drivers/media/video/et61x251/et61x251.h | 234 + drivers/media/video/et61x251/et61x251_core.c | 2630 +++++++++ drivers/media/video/et61x251/et61x251_sensor.h | 116 + drivers/media/video/et61x251/et61x251_tas5130d1b.c | 141 + drivers/media/video/ov511.c | 5932 ++++++++++++++++++++ drivers/media/video/ov511.h | 568 ++ drivers/media/video/pwc/Makefile | 20 + drivers/media/video/pwc/philips.txt | 236 + drivers/media/video/pwc/pwc-ctrl.c | 1541 +++++ drivers/media/video/pwc/pwc-if.c | 2205 ++++++++ drivers/media/video/pwc/pwc-ioctl.h | 292 + drivers/media/video/pwc/pwc-kiara.c | 318 ++ drivers/media/video/pwc/pwc-kiara.h | 45 + drivers/media/video/pwc/pwc-misc.c | 140 + drivers/media/video/pwc/pwc-nala.h | 66 + drivers/media/video/pwc/pwc-timon.c | 316 ++ drivers/media/video/pwc/pwc-timon.h | 61 + drivers/media/video/pwc/pwc-uncompress.c | 146 + drivers/media/video/pwc/pwc-uncompress.h | 41 + drivers/media/video/pwc/pwc.h | 272 + drivers/media/video/se401.c | 1435 +++++ drivers/media/video/se401.h | 234 + drivers/media/video/sn9c102/Makefile | 7 + drivers/media/video/sn9c102/sn9c102.h | 218 + drivers/media/video/sn9c102/sn9c102_core.c | 2919 ++++++++++ drivers/media/video/sn9c102/sn9c102_hv7131d.c | 271 + drivers/media/video/sn9c102/sn9c102_mi0343.c | 363 ++ drivers/media/video/sn9c102/sn9c102_ov7630.c | 401 ++ drivers/media/video/sn9c102/sn9c102_pas106b.c | 307 + drivers/media/video/sn9c102/sn9c102_pas202bca.c | 238 + drivers/media/video/sn9c102/sn9c102_pas202bcb.c | 293 + drivers/media/video/sn9c102/sn9c102_sensor.h | 389 ++ drivers/media/video/sn9c102/sn9c102_tas5110c1b.c | 159 + drivers/media/video/sn9c102/sn9c102_tas5130d1b.c | 169 + drivers/media/video/stv680.c | 1508 +++++ drivers/media/video/stv680.h | 227 + drivers/media/video/usbvideo/Makefile | 4 + drivers/media/video/usbvideo/ibmcam.c | 3932 +++++++++++++ drivers/media/video/usbvideo/konicawc.c | 978 ++++ drivers/media/video/usbvideo/ultracam.c | 679 +++ drivers/media/video/usbvideo/usbvideo.c | 2190 ++++++++ drivers/media/video/usbvideo/usbvideo.h | 394 ++ drivers/media/video/usbvideo/vicam.c | 1411 +++++ drivers/media/video/w9968cf.c | 3691 ++++++++++++ drivers/media/video/w9968cf.h | 330 ++ drivers/media/video/w9968cf_decoder.h | 86 + drivers/media/video/w9968cf_vpp.h | 40 + drivers/media/video/zc0301/Makefile | 3 + drivers/media/video/zc0301/zc0301.h | 192 + drivers/media/video/zc0301/zc0301_core.c | 2055 +++++++ drivers/media/video/zc0301/zc0301_pas202bcb.c | 361 ++ drivers/media/video/zc0301/zc0301_sensor.h | 103 + drivers/usb/Kconfig | 2 - drivers/usb/Makefile | 14 - drivers/usb/media/Kconfig | 241 - drivers/usb/media/Makefile | 24 - drivers/usb/media/dabfirmware.h | 1408 ----- drivers/usb/media/dabusb.c | 874 --- drivers/usb/media/dabusb.h | 85 - drivers/usb/media/dsbr100.c | 429 -- drivers/usb/media/et61x251.h | 234 - drivers/usb/media/et61x251_core.c | 2630 --------- drivers/usb/media/et61x251_sensor.h | 116 - drivers/usb/media/et61x251_tas5130d1b.c | 141 - drivers/usb/media/ibmcam.c | 3932 ------------- drivers/usb/media/konicawc.c | 978 ---- drivers/usb/media/ov511.c | 5932 -------------------- drivers/usb/media/ov511.h | 568 -- drivers/usb/media/pwc/Makefile | 20 - drivers/usb/media/pwc/philips.txt | 236 - drivers/usb/media/pwc/pwc-ctrl.c | 1541 ----- drivers/usb/media/pwc/pwc-if.c | 2205 -------- drivers/usb/media/pwc/pwc-ioctl.h | 292 - drivers/usb/media/pwc/pwc-kiara.c | 318 -- drivers/usb/media/pwc/pwc-kiara.h | 45 - drivers/usb/media/pwc/pwc-misc.c | 140 - drivers/usb/media/pwc/pwc-nala.h | 66 - drivers/usb/media/pwc/pwc-timon.c | 316 -- drivers/usb/media/pwc/pwc-timon.h | 61 - drivers/usb/media/pwc/pwc-uncompress.c | 146 - drivers/usb/media/pwc/pwc-uncompress.h | 41 - drivers/usb/media/pwc/pwc.h | 272 - drivers/usb/media/se401.c | 1435 ----- drivers/usb/media/se401.h | 234 - drivers/usb/media/sn9c102.h | 218 - drivers/usb/media/sn9c102_core.c | 2919 ---------- drivers/usb/media/sn9c102_hv7131d.c | 271 - drivers/usb/media/sn9c102_mi0343.c | 363 -- drivers/usb/media/sn9c102_ov7630.c | 401 -- drivers/usb/media/sn9c102_pas106b.c | 307 - drivers/usb/media/sn9c102_pas202bca.c | 238 - drivers/usb/media/sn9c102_pas202bcb.c | 293 - drivers/usb/media/sn9c102_sensor.h | 389 -- drivers/usb/media/sn9c102_tas5110c1b.c | 159 - drivers/usb/media/sn9c102_tas5130d1b.c | 169 - drivers/usb/media/stv680.c | 1508 ----- drivers/usb/media/stv680.h | 227 - drivers/usb/media/ultracam.c | 679 --- drivers/usb/media/usbvideo.c | 2190 -------- drivers/usb/media/usbvideo.h | 394 -- drivers/usb/media/vicam.c | 1411 ----- drivers/usb/media/w9968cf.c | 3691 ------------ drivers/usb/media/w9968cf.h | 330 -- drivers/usb/media/w9968cf_decoder.h | 86 - drivers/usb/media/w9968cf_vpp.h | 40 - drivers/usb/media/zc0301.h | 192 - drivers/usb/media/zc0301_core.c | 2055 ------- drivers/usb/media/zc0301_pas202bcb.c | 361 -- drivers/usb/media/zc0301_sensor.h | 103 - 117 files changed, 43970 insertions(+), 43972 deletions(-) create mode 100644 drivers/media/video/dabfirmware.h create mode 100644 drivers/media/video/dabusb.c create mode 100644 drivers/media/video/dabusb.h create mode 100644 drivers/media/video/dsbr100.c create mode 100644 drivers/media/video/et61x251/Makefile create mode 100644 drivers/media/video/et61x251/et61x251.h create mode 100644 drivers/media/video/et61x251/et61x251_core.c create mode 100644 drivers/media/video/et61x251/et61x251_sensor.h create mode 100644 drivers/media/video/et61x251/et61x251_tas5130d1b.c create mode 100644 drivers/media/video/ov511.c create mode 100644 drivers/media/video/ov511.h create mode 100644 drivers/media/video/pwc/Makefile create mode 100644 drivers/media/video/pwc/philips.txt create mode 100644 drivers/media/video/pwc/pwc-ctrl.c create mode 100644 drivers/media/video/pwc/pwc-if.c create mode 100644 drivers/media/video/pwc/pwc-ioctl.h create mode 100644 drivers/media/video/pwc/pwc-kiara.c create mode 100644 drivers/media/video/pwc/pwc-kiara.h create mode 100644 drivers/media/video/pwc/pwc-misc.c create mode 100644 drivers/media/video/pwc/pwc-nala.h create mode 100644 drivers/media/video/pwc/pwc-timon.c create mode 100644 drivers/media/video/pwc/pwc-timon.h create mode 100644 drivers/media/video/pwc/pwc-uncompress.c create mode 100644 drivers/media/video/pwc/pwc-uncompress.h create mode 100644 drivers/media/video/pwc/pwc.h create mode 100644 drivers/media/video/se401.c create mode 100644 drivers/media/video/se401.h create mode 100644 drivers/media/video/sn9c102/Makefile create mode 100644 drivers/media/video/sn9c102/sn9c102.h create mode 100644 drivers/media/video/sn9c102/sn9c102_core.c create mode 100644 drivers/media/video/sn9c102/sn9c102_hv7131d.c create mode 100644 drivers/media/video/sn9c102/sn9c102_mi0343.c create mode 100644 drivers/media/video/sn9c102/sn9c102_ov7630.c create mode 100644 drivers/media/video/sn9c102/sn9c102_pas106b.c create mode 100644 drivers/media/video/sn9c102/sn9c102_pas202bca.c create mode 100644 drivers/media/video/sn9c102/sn9c102_pas202bcb.c create mode 100644 drivers/media/video/sn9c102/sn9c102_sensor.h create mode 100644 drivers/media/video/sn9c102/sn9c102_tas5110c1b.c create mode 100644 drivers/media/video/sn9c102/sn9c102_tas5130d1b.c create mode 100644 drivers/media/video/stv680.c create mode 100644 drivers/media/video/stv680.h create mode 100644 drivers/media/video/usbvideo/Makefile create mode 100644 drivers/media/video/usbvideo/ibmcam.c create mode 100644 drivers/media/video/usbvideo/konicawc.c create mode 100644 drivers/media/video/usbvideo/ultracam.c create mode 100644 drivers/media/video/usbvideo/usbvideo.c create mode 100644 drivers/media/video/usbvideo/usbvideo.h create mode 100644 drivers/media/video/usbvideo/vicam.c create mode 100644 drivers/media/video/w9968cf.c create mode 100644 drivers/media/video/w9968cf.h create mode 100644 drivers/media/video/w9968cf_decoder.h create mode 100644 drivers/media/video/w9968cf_vpp.h create mode 100644 drivers/media/video/zc0301/Makefile create mode 100644 drivers/media/video/zc0301/zc0301.h create mode 100644 drivers/media/video/zc0301/zc0301_core.c create mode 100644 drivers/media/video/zc0301/zc0301_pas202bcb.c create mode 100644 drivers/media/video/zc0301/zc0301_sensor.h delete mode 100644 drivers/usb/media/Kconfig delete mode 100644 drivers/usb/media/Makefile delete mode 100644 drivers/usb/media/dabfirmware.h delete mode 100644 drivers/usb/media/dabusb.c delete mode 100644 drivers/usb/media/dabusb.h delete mode 100644 drivers/usb/media/dsbr100.c delete mode 100644 drivers/usb/media/et61x251.h delete mode 100644 drivers/usb/media/et61x251_core.c delete mode 100644 drivers/usb/media/et61x251_sensor.h delete mode 100644 drivers/usb/media/et61x251_tas5130d1b.c delete mode 100644 drivers/usb/media/ibmcam.c delete mode 100644 drivers/usb/media/konicawc.c delete mode 100644 drivers/usb/media/ov511.c delete mode 100644 drivers/usb/media/ov511.h delete mode 100644 drivers/usb/media/pwc/Makefile delete mode 100644 drivers/usb/media/pwc/philips.txt delete mode 100644 drivers/usb/media/pwc/pwc-ctrl.c delete mode 100644 drivers/usb/media/pwc/pwc-if.c delete mode 100644 drivers/usb/media/pwc/pwc-ioctl.h delete mode 100644 drivers/usb/media/pwc/pwc-kiara.c delete mode 100644 drivers/usb/media/pwc/pwc-kiara.h delete mode 100644 drivers/usb/media/pwc/pwc-misc.c delete mode 100644 drivers/usb/media/pwc/pwc-nala.h delete mode 100644 drivers/usb/media/pwc/pwc-timon.c delete mode 100644 drivers/usb/media/pwc/pwc-timon.h delete mode 100644 drivers/usb/media/pwc/pwc-uncompress.c delete mode 100644 drivers/usb/media/pwc/pwc-uncompress.h delete mode 100644 drivers/usb/media/pwc/pwc.h delete mode 100644 drivers/usb/media/se401.c delete mode 100644 drivers/usb/media/se401.h delete mode 100644 drivers/usb/media/sn9c102.h delete mode 100644 drivers/usb/media/sn9c102_core.c delete mode 100644 drivers/usb/media/sn9c102_hv7131d.c delete mode 100644 drivers/usb/media/sn9c102_mi0343.c delete mode 100644 drivers/usb/media/sn9c102_ov7630.c delete mode 100644 drivers/usb/media/sn9c102_pas106b.c delete mode 100644 drivers/usb/media/sn9c102_pas202bca.c delete mode 100644 drivers/usb/media/sn9c102_pas202bcb.c delete mode 100644 drivers/usb/media/sn9c102_sensor.h delete mode 100644 drivers/usb/media/sn9c102_tas5110c1b.c delete mode 100644 drivers/usb/media/sn9c102_tas5130d1b.c delete mode 100644 drivers/usb/media/stv680.c delete mode 100644 drivers/usb/media/stv680.h delete mode 100644 drivers/usb/media/ultracam.c delete mode 100644 drivers/usb/media/usbvideo.c delete mode 100644 drivers/usb/media/usbvideo.h delete mode 100644 drivers/usb/media/vicam.c delete mode 100644 drivers/usb/media/w9968cf.c delete mode 100644 drivers/usb/media/w9968cf.h delete mode 100644 drivers/usb/media/w9968cf_decoder.h delete mode 100644 drivers/usb/media/w9968cf_vpp.h delete mode 100644 drivers/usb/media/zc0301.h delete mode 100644 drivers/usb/media/zc0301_core.c delete mode 100644 drivers/usb/media/zc0301_pas202bcb.c delete mode 100644 drivers/usb/media/zc0301_sensor.h (limited to 'drivers') diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index c2602b340491..baa9f58beffc 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -50,5 +50,19 @@ config VIDEO_IR config VIDEO_TVEEPROM tristate +config USB_DABUSB + tristate "DABUSB driver" + depends on USB + ---help--- + A Digital Audio Broadcasting (DAB) Receiver for USB and Linux + brought to you by the DAB-Team + . This driver can be taken + as an example for URB-based bulk, control, and isochronous + transactions. URB's are explained in + . + + To compile this driver as a module, choose M here: the + module will be called dabusb. + endmenu diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index b3d3b22d3f78..1f8a46b5916e 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -291,8 +291,6 @@ config VIDEO_HEXIUM_GEMINI source "drivers/media/video/cx88/Kconfig" -source "drivers/media/video/em28xx/Kconfig" - config VIDEO_OVCAMCHIP tristate "OmniVision Camera Chip support" depends on VIDEO_DEV && I2C @@ -367,4 +365,234 @@ config VIDEO_SAA7127 To compile this driver as a module, choose M here: the module will be called saa7127 +# +# USB Multimedia device configuration +# + +menu "V4L USB devices" + depends on USB && VIDEO_DEV + +source "drivers/media/video/em28xx/Kconfig" + +config USB_VICAM + tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" + depends on USB && VIDEO_DEV && EXPERIMENTAL + ---help--- + Say Y here if you have 3com homeconnect camera (vicam). + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" (under Multimedia Devices) to use this driver. + Information on this API and pointers to "v4l" programs may be found + at . + + To compile this driver as a module, choose M here: the + module will be called vicam. + +config USB_DSBR + tristate "D-Link USB FM radio support (EXPERIMENTAL)" + depends on USB && VIDEO_DEV && EXPERIMENTAL + ---help--- + Say Y here if you want to connect this type of radio to your + computer's USB port. Note that the audio is not digital, and + you must connect the line out connector to a sound card or a + set of speakers. + + This driver uses the Video For Linux API. You must enable + (Y or M in config) Video For Linux (under Character Devices) + to use this driver. Information on this API and pointers to + "v4l" programs may be found at + . + + To compile this driver as a module, choose M here: the + module will be called dsbr100. + +config USB_ET61X251 + tristate "USB ET61X[12]51 PC Camera Controller support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want support for cameras based on Etoms ET61X151 + or ET61X251 PC Camera Controllers. + + See for more informations. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" to use this driver. + + To compile this driver as a module, choose M here: the + module will be called et61x251. + +config USB_IBMCAM + tristate "USB IBM (Xirlink) C-it Camera support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want to connect a IBM "C-It" camera, also known as + "Xirlink PC Camera" to your computer's USB port. For more + information, read . + + This driver uses the Video For Linux API. You must enable + (Y or M in config) Video For Linux (under Character Devices) + to use this driver. Information on this API and pointers to + "v4l" programs may be found at + . + + To compile this driver as a module, choose M here: the + module will be called ibmcam. + + This camera has several configuration options which + can be specified when you load the module. Read + to learn more. + +config USB_KONICAWC + tristate "USB Konica Webcam support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want support for webcams based on a Konica + chipset. This is known to work with the Intel YC76 webcam. + + This driver uses the Video For Linux API. You must enable + (Y or M in config) Video For Linux (under Character Devices) + to use this driver. Information on this API and pointers to + "v4l" programs may be found at + . + + To compile this driver as a module, choose M here: the + module will be called konicawc. + +config USB_OV511 + tristate "USB OV511 Camera support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want to connect this type of camera to your + computer's USB port. See for more + information and for a list of supported cameras. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" (under Character Devices) to use this driver. + Information on this API and pointers to "v4l" programs may be found + at . + + To compile this driver as a module, choose M here: the + module will be called ov511. + +config USB_SE401 + tristate "USB SE401 Camera support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want to connect this type of camera to your + computer's USB port. See for more + information and for a list of supported cameras. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" (under Multimedia Devices) to use this driver. + Information on this API and pointers to "v4l" programs may be found + at . + + To compile this driver as a module, choose M here: the + module will be called se401. + +config USB_SN9C102 + tristate "USB SN9C10x PC Camera Controller support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want support for cameras based on SONiX SN9C101, + SN9C102 or SN9C103 PC Camera Controllers. + + See for more informations. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" to use this driver. + + To compile this driver as a module, choose M here: the + module will be called sn9c102. + +config USB_STV680 + tristate "USB STV680 (Pencam) Camera support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want to connect this type of camera to your + computer's USB port. This includes the Pencam line of cameras. + See for more information and for + a list of supported cameras. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" (under Multimedia Devices) to use this driver. + Information on this API and pointers to "v4l" programs may be found + at . + + To compile this driver as a module, choose M here: the + module will be called stv680. + +config USB_W9968CF + tristate "USB W996[87]CF JPEG Dual Mode Camera support" + depends on USB && VIDEO_DEV && I2C && VIDEO_OVCAMCHIP + ---help--- + Say Y here if you want support for cameras based on OV681 or + Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. + + This driver has an optional plugin, which is distributed as a + separate module only (released under GPL). It allows to use higher + resolutions and framerates, but cannot be included in the official + Linux kernel for performance purposes. + + See for more informations. + + This driver uses the Video For Linux and the I2C APIs. It needs the + OmniVision Camera Chip support as well. You must say Y or M to + "Video For Linux", "I2C Support" and "OmniVision Camera Chip + support" to use this driver. + + To compile this driver as a module, choose M here: the + module will be called w9968cf. + +config USB_ZC0301 + tristate "USB ZC0301 Image Processor and Control Chip support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want support for cameras based on the ZC0301 + Image Processor and Control Chip. + + See for more informations. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" to use this driver. + + To compile this driver as a module, choose M here: the + module will be called zc0301. + +config USB_PWC + tristate "USB Philips Cameras" + depends on USB && VIDEO_DEV + ---help--- + Say Y or M here if you want to use one of these Philips & OEM + webcams: + * Philips PCA645, PCA646 + * Philips PCVC675, PCVC680, PCVC690 + * Philips PCVC720/40, PCVC730, PCVC740, PCVC750 + * Askey VC010 + * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' + and 'Orbit'/'Sphere' + * Samsung MPC-C10, MPC-C30 + * Creative Webcam 5, Pro Ex + * SOTEC Afina Eye + * Visionite VCS-UC300, VCS-UM100 + + The PCA635, PCVC665 and PCVC720/20 are not supported by this driver + and never will be, but the 665 and 720/20 are supported by other + drivers. + + See for more information and + installation instructions. + + The built-in microphone is enabled by selecting USB Audio support. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" (under Character Devices) to use this driver. + Information on this API and pointers to "v4l" programs may be found + at . + + To compile this driver as a module, choose M here: the + module will be called pwc. + +endmenu # V4L USB devices + endmenu diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 1a56a2d9e294..1c0e72e5a593 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -65,4 +65,23 @@ obj-$(CONFIG_VIDEO_CX25840) += cx25840/ obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o +et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o +zc0301-objs := zc0301_core.o zc0301_pas202bcb.o + +obj-$(CONFIG_USB_DABUSB) += dabusb.o +obj-$(CONFIG_USB_DSBR) += dsbr100.o +obj-$(CONFIG_USB_OV511) += ov511.o +obj-$(CONFIG_USB_SE401) += se401.o +obj-$(CONFIG_USB_STV680) += stv680.o +obj-$(CONFIG_USB_W9968CF) += w9968cf.o + +obj-$(CONFIG_USB_SN9C102) += sn9c102/ +obj-$(CONFIG_USB_ET61X251) += et61x251/ +obj-$(CONFIG_USB_PWC) += pwc/ +obj-$(CONFIG_USB_ZC0301) += zc0301/ + +obj-$(CONFIG_USB_IBMCAM) += usbvideo/ +obj-$(CONFIG_USB_KONICAWC) += usbvideo/ +obj-$(CONFIG_USB_VICAM) += usbvideo/ + EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core diff --git a/drivers/media/video/dabfirmware.h b/drivers/media/video/dabfirmware.h new file mode 100644 index 000000000000..d14d803566a3 --- /dev/null +++ b/drivers/media/video/dabfirmware.h @@ -0,0 +1,1408 @@ +/* + * dabdata.h - dab usb firmware and bitstream data + */ + +static INTEL_HEX_RECORD firmware[] = { + +{ 2, 0x0000, 0, {0x21,0x57} }, +{ 3, 0x0003, 0, {0x02,0x01,0x66} }, +{ 3, 0x000b, 0, {0x02,0x01,0x66} }, +{ 3, 0x0013, 0, {0x02,0x01,0x66} }, +{ 3, 0x001b, 0, {0x02,0x01,0x66} }, +{ 3, 0x0023, 0, {0x02,0x01,0x66} }, +{ 3, 0x002b, 0, {0x02,0x01,0x66} }, +{ 3, 0x0033, 0, {0x02,0x03,0x0f} }, +{ 3, 0x003b, 0, {0x02,0x01,0x66} }, +{ 3, 0x0043, 0, {0x02,0x01,0x00} }, +{ 3, 0x004b, 0, {0x02,0x01,0x66} }, +{ 3, 0x0053, 0, {0x02,0x01,0x66} }, +{ 3, 0x005b, 0, {0x02,0x04,0xbd} }, +{ 3, 0x0063, 0, {0x02,0x01,0x67} }, +{ 3, 0x0100, 0, {0x02,0x0c,0x5a} }, +{ 3, 0x0104, 0, {0x02,0x01,0xed} }, +{ 3, 0x0108, 0, {0x02,0x02,0x51} }, +{ 3, 0x010c, 0, {0x02,0x02,0x7c} }, +{ 3, 0x0110, 0, {0x02,0x02,0xe4} }, +{ 1, 0x0114, 0, {0x32} }, +{ 1, 0x0118, 0, {0x32} }, +{ 3, 0x011c, 0, {0x02,0x05,0xfd} }, +{ 3, 0x0120, 0, {0x02,0x00,0x00} }, +{ 3, 0x0124, 0, {0x02,0x00,0x00} }, +{ 3, 0x0128, 0, {0x02,0x04,0x3c} }, +{ 3, 0x012c, 0, {0x02,0x04,0x6a} }, +{ 3, 0x0130, 0, {0x02,0x00,0x00} }, +{ 3, 0x0134, 0, {0x02,0x00,0x00} }, +{ 3, 0x0138, 0, {0x02,0x00,0x00} }, +{ 3, 0x013c, 0, {0x02,0x00,0x00} }, +{ 3, 0x0140, 0, {0x02,0x00,0x00} }, +{ 3, 0x0144, 0, {0x02,0x00,0x00} }, +{ 3, 0x0148, 0, {0x02,0x00,0x00} }, +{ 3, 0x014c, 0, {0x02,0x00,0x00} }, +{ 3, 0x0150, 0, {0x02,0x00,0x00} }, +{ 3, 0x0154, 0, {0x02,0x00,0x00} }, +{ 10, 0x0157, 0, {0x75,0x81,0x7f,0xe5,0x82,0x60,0x03,0x02,0x01,0x61} }, +{ 5, 0x0161, 0, {0x12,0x07,0x6f,0x21,0x64} }, +{ 1, 0x0166, 0, {0x32} }, +{ 14, 0x0167, 0, {0xc0,0xd0,0xc0,0x86,0xc0,0x82,0xc0,0x83,0xc0,0xe0,0x90,0x7f,0x97,0xe0} }, +{ 14, 0x0175, 0, {0x44,0x80,0xf0,0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, +{ 14, 0x0183, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, +{ 14, 0x0191, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x90,0x7f,0x97,0xe0} }, +{ 3, 0x019f, 0, {0x55,0x7f,0xf0} }, +{ 14, 0x01a2, 0, {0x90,0x7f,0x9a,0xe0,0x30,0xe4,0x23,0x90,0x7f,0x68,0xf0,0xf0,0xf0,0xf0} }, +{ 14, 0x01b0, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, +{ 14, 0x01be, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, +{ 14, 0x01cc, 0, {0xe5,0xd8,0xc2,0xe3,0xf5,0xd8,0xd0,0xe0,0xd0,0x83,0xd0,0x82,0xd0,0x86} }, +{ 3, 0x01da, 0, {0xd0,0xd0,0x32} }, +{ 8, 0x01dd, 0, {0x75,0x86,0x00,0x90,0xff,0xc3,0x7c,0x05} }, +{ 7, 0x01e5, 0, {0xa3,0xe5,0x82,0x45,0x83,0x70,0xf9} }, +{ 1, 0x01ec, 0, {0x22} }, +{ 14, 0x01ed, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0xd0} }, +{ 14, 0x01fb, 0, {0x75,0xd0,0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91} }, +{ 13, 0x0209, 0, {0x90,0x88,0x00,0xe0,0xf5,0x41,0x90,0x7f,0xab,0x74,0x02,0xf0,0x90} }, +{ 9, 0x0216, 0, {0x7f,0xab,0x74,0x02,0xf0,0xe5,0x32,0x60,0x21} }, +{ 4, 0x021f, 0, {0x7a,0x00,0x7b,0x00} }, +{ 11, 0x0223, 0, {0xc3,0xea,0x94,0x18,0xeb,0x64,0x80,0x94,0x80,0x50,0x12} }, +{ 14, 0x022e, 0, {0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0a,0xba,0x00} }, +{ 2, 0x023c, 0, {0x01,0x0b} }, +{ 2, 0x023e, 0, {0x80,0xe3} }, +{ 2, 0x0240, 0, {0xd0,0x86} }, +{ 14, 0x0242, 0, {0xd0,0xd0,0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0} }, +{ 1, 0x0250, 0, {0x32} }, +{ 14, 0x0251, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 14, 0x025f, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} }, +{ 4, 0x026d, 0, {0x04,0xf0,0xd0,0x86} }, +{ 11, 0x0271, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x027c, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, +{ 14, 0x028a, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, +{ 13, 0x0298, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} }, +{ 12, 0x02a5, 0, {0x7f,0xab,0x74,0x08,0xf0,0x75,0x6e,0x00,0x75,0x6f,0x02,0x12} }, +{ 6, 0x02b1, 0, {0x11,0x44,0x75,0x70,0x39,0x75} }, +{ 6, 0x02b7, 0, {0x71,0x0c,0x75,0x72,0x02,0x12} }, +{ 12, 0x02bd, 0, {0x11,0x75,0x90,0x7f,0xd6,0xe4,0xf0,0x75,0xd8,0x20,0xd0,0x86} }, +{ 14, 0x02c9, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, +{ 13, 0x02d7, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x02e4, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 14, 0x02f2, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} }, +{ 4, 0x0300, 0, {0x10,0xf0,0xd0,0x86} }, +{ 11, 0x0304, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x030f, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, +{ 14, 0x031d, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, +{ 12, 0x032b, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0x75,0x6e,0x00,0x75,0x6f,0x02} }, +{ 7, 0x0337, 0, {0x12,0x11,0x44,0x75,0x70,0x40,0x75} }, +{ 6, 0x033e, 0, {0x71,0x0c,0x75,0x72,0x02,0x12} }, +{ 14, 0x0344, 0, {0x11,0x75,0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0} }, +{ 5, 0x0352, 0, {0x75,0xd8,0x10,0xd0,0x86} }, +{ 14, 0x0357, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, +{ 13, 0x0365, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 13, 0x0372, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} }, +{ 12, 0x037f, 0, {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x42,0xf0,0x12,0x10,0x1b,0x90} }, +{ 13, 0x038b, 0, {0x7f,0xa6,0xe5,0x43,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40} }, +{ 1, 0x0398, 0, {0xf0} }, +{ 1, 0x0399, 0, {0x22} }, +{ 13, 0x039a, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} }, +{ 12, 0x03a7, 0, {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x44,0xf0,0x12,0x10,0x1b,0x90} }, +{ 12, 0x03b3, 0, {0x7f,0xa6,0xe5,0x45,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0xe5} }, +{ 11, 0x03bf, 0, {0x46,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40,0xf0} }, +{ 1, 0x03ca, 0, {0x22} }, +{ 10, 0x03cb, 0, {0x75,0x44,0x02,0x75,0x45,0x00,0x75,0x46,0x00,0x12} }, +{ 9, 0x03d5, 0, {0x03,0x9a,0x75,0x42,0x03,0x75,0x43,0x00,0x12} }, +{ 2, 0x03de, 0, {0x03,0x72} }, +{ 1, 0x03e0, 0, {0x22} }, +{ 12, 0x03e1, 0, {0x90,0x88,0x00,0xe5,0x36,0xf0,0x90,0x88,0x00,0x74,0x10,0x25} }, +{ 9, 0x03ed, 0, {0x36,0xf0,0x12,0x01,0xdd,0x75,0x42,0x01,0x75} }, +{ 9, 0x03f6, 0, {0x43,0x18,0x12,0x03,0x72,0x75,0x44,0x02,0x75} }, +{ 9, 0x03ff, 0,{0x45,0x00,0x75,0x46,0x00,0x12,0x03,0x9a,0x75} }, +{ 8, 0x0408, 0,{0x42,0x03,0x75,0x43,0x44,0x12,0x03,0x72} }, +{ 1, 0x0410, 0,{0x22} }, +{ 14, 0x0411, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 14, 0x041f, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} }, +{ 4, 0x042d, 0, {0x02,0xf0,0xd0,0x86} }, +{ 11, 0x0431, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x043c, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 14, 0x044a, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xa9,0x74} }, +{ 7, 0x0458, 0, {0x04,0xf0,0x75,0x30,0x01,0xd0,0x86} }, +{ 11, 0x045f, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x046a, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 14, 0x0478, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} }, +{ 7, 0x0486, 0, {0x04,0xf0,0x75,0x31,0x01,0xd0,0x86} }, +{ 11, 0x048d, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x0498, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 12, 0x04a6, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe5,0xf5,0x91,0xd0,0x86} }, +{ 11, 0x04b2, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x04bd, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 12, 0x04cb, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe7,0xf5,0x91,0xd0,0x86} }, +{ 11, 0x04d7, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 12, 0x04e2, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x20,0x90,0x7f,0x96,0xe4,0xf0} }, +{ 1, 0x04ee, 0, {0x22} }, +{ 7, 0x04ef, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x21} }, +{ 1, 0x04f6, 0, {0x22} }, +{ 14, 0x04f7, 0, {0x90,0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xe0,0xfb,0x74,0x80,0x2a,0xfa} }, +{ 14, 0x0505, 0, {0x74,0x80,0x2b,0xfb,0xea,0x03,0x03,0x54,0x3f,0xfc,0xea,0xc4,0x23,0x54} }, +{ 14, 0x0513, 0, {0x1f,0xfa,0x2c,0xfa,0xeb,0x03,0x03,0x54,0x3f,0xfc,0xeb,0xc4,0x23,0x54} }, +{ 11, 0x0521, 0, {0x1f,0xfb,0x2c,0xfb,0x90,0x17,0x0a,0xe0,0xfc,0x60,0x02} }, +{ 2, 0x052c, 0, {0x7a,0x00} }, +{ 7, 0x052e, 0, {0x90,0x17,0x0c,0xe0,0xfc,0x60,0x02} }, +{ 2, 0x0535, 0, {0x7b,0x00} }, +{ 11, 0x0537, 0, {0xea,0x2b,0xfc,0xc3,0x13,0xf5,0x3a,0x75,0x44,0x02,0x8b} }, +{ 7, 0x0542, 0, {0x45,0x8a,0x46,0x12,0x03,0x9a,0x75} }, +{ 9, 0x0549, 0, {0x6e,0x08,0x75,0x6f,0x00,0x12,0x11,0x44,0x75} }, +{ 4, 0x0552, 0, {0x70,0x47,0x75,0x71} }, +{ 8, 0x0556, 0, {0x0c,0x75,0x72,0x02,0x12,0x11,0x75,0x85} }, +{ 5, 0x055e, 0, {0x3a,0x73,0x12,0x11,0xa0} }, +{ 1, 0x0563, 0, {0x22} }, +{ 14, 0x0564, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} }, +{ 14, 0x0572, 0, {0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xef,0xe0,0xfc} }, +{ 14, 0x0580, 0, {0x33,0x95,0xe0,0xfd,0x8c,0x05,0x7c,0x00,0x90,0x7f,0xee,0xe0,0xfe,0x33} }, +{ 14, 0x058e, 0, {0x95,0xe0,0xff,0xec,0x2e,0xfc,0xed,0x3f,0xfd,0x90,0x7f,0xe9,0xe0,0xfe} }, +{ 5, 0x059c, 0, {0xbe,0x01,0x02,0x80,0x03} }, +{ 3, 0x05a1, 0, {0x02,0x05,0xf9} }, +{ 6, 0x05a4, 0, {0xbc,0x01,0x21,0xbd,0x00,0x1e} }, +{ 14, 0x05aa, 0, {0xea,0xc4,0x03,0x54,0xf8,0xfc,0xeb,0x25,0xe0,0xfd,0x2c,0x24,0x00,0xfc} }, +{ 14, 0x05b8, 0, {0xe4,0x34,0x17,0xfd,0x90,0x7e,0xc0,0xe0,0xfe,0x8c,0x82,0x8d,0x83,0xf0} }, +{ 2, 0x05c6, 0, {0x80,0x31} }, +{ 14, 0x05c8, 0, {0xea,0xc4,0x03,0x54,0xf8,0xfa,0xeb,0x25,0xe0,0xfb,0x2a,0xfa,0x24,0x00} }, +{ 14, 0x05d6, 0, {0xfb,0xe4,0x34,0x17,0xfc,0x90,0x7e,0xc0,0xe0,0xfd,0x8b,0x82,0x8c,0x83} }, +{ 14, 0x05e4, 0, {0xf0,0x74,0x01,0x2a,0x24,0x00,0xfa,0xe4,0x34,0x17,0xfb,0x90,0x7e,0xc1} }, +{ 7, 0x05f2, 0, {0xe0,0xfc,0x8a,0x82,0x8b,0x83,0xf0} }, +{ 3, 0x05f9, 0, {0x75,0x38,0x01} }, +{ 1, 0x05fc, 0, {0x22} }, +{ 14, 0x05fd, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, +{ 14, 0x060b, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, +{ 13, 0x0619, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} }, +{ 13, 0x0626, 0, {0x7f,0xaa,0x74,0x01,0xf0,0x12,0x05,0x64,0x75,0x37,0x00,0xd0,0x86} }, +{ 14, 0x0633, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, +{ 13, 0x0641, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x064e, 0, {0x90,0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xee,0xe0} }, +{ 14, 0x065c, 0, {0xfc,0x33,0x95,0xe0,0xfd,0x90,0x7f,0x96,0xe0,0xfe,0x90,0x7f,0x96,0x74} }, +{ 14, 0x066a, 0, {0x80,0x65,0x06,0xf0,0x90,0x7f,0x00,0x74,0x01,0xf0,0xea,0xc4,0x03,0x54} }, +{ 14, 0x0678, 0, {0xf8,0xfe,0xeb,0x25,0xe0,0xfb,0x2e,0xfe,0x24,0x00,0xfb,0xe4,0x34,0x17} }, +{ 14, 0x0686, 0, {0xff,0x8b,0x82,0x8f,0x83,0xe0,0xfb,0x74,0x01,0x2e,0x24,0x00,0xfe,0xe4} }, +{ 14, 0x0694, 0, {0x34,0x17,0xff,0x8e,0x82,0x8f,0x83,0xe0,0xfe,0x90,0x7f,0xe9,0xe0,0xff} }, +{ 3, 0x06a2, 0, {0xbf,0x81,0x0a} }, +{ 10, 0x06a5, 0, {0x90,0x7f,0x00,0xeb,0xf0,0x90,0x7f,0x01,0xee,0xf0} }, +{ 8, 0x06af, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x82,0x1a} }, +{ 3, 0x06b7, 0, {0xba,0x01,0x0c} }, +{ 12, 0x06ba, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} }, +{ 11, 0x06c6, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0xb5,0xf0} }, +{ 8, 0x06d1, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x83,0x1b} }, +{ 3, 0x06d9, 0, {0xba,0x01,0x0d} }, +{ 13, 0x06dc, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} }, +{ 11, 0x06e9, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0x12,0xf0} }, +{ 8, 0x06f4, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x84,0x1c} }, +{ 3, 0x06fc, 0, {0xba,0x01,0x0d} }, +{ 13, 0x06ff, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0c} }, +{ 12, 0x070c, 0, {0x90,0x7f,0x00,0x74,0x80,0xf0,0x90,0x7f,0x01,0x74,0x01,0xf0} }, +{ 5, 0x0718, 0, {0x90,0x7f,0xb5,0xec,0xf0} }, +{ 1, 0x071d, 0, {0x22} }, +{ 12, 0x071e, 0, {0x75,0x36,0x0d,0x90,0x88,0x00,0x74,0x1d,0xf0,0x75,0x6b,0x80} }, +{ 10, 0x072a, 0, {0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} }, +{ 9, 0x0734, 0, {0x6c,0x0f,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} }, +{ 9, 0x073d, 0, {0x6c,0x06,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} }, +{ 7, 0x0746, 0, {0x6c,0x01,0x12,0x10,0xe2,0x7a,0x00} }, +{ 3, 0x074d, 0, {0xba,0xff,0x00} }, +{ 2, 0x0750, 0, {0x50,0x0a} }, +{ 10, 0x0752, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} }, +{ 10, 0x075c, 0, {0x75,0x6b,0x80,0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75} }, +{ 8, 0x0766, 0, {0x6b,0x80,0x75,0x6c,0x0f,0x12,0x10,0xe2} }, +{ 1, 0x076e, 0, {0x22} }, +{ 14, 0x076f, 0, {0x90,0x7f,0xa1,0xe4,0xf0,0x90,0x7f,0xaf,0x74,0x01,0xf0,0x90,0x7f,0x92} }, +{ 14, 0x077d, 0, {0x74,0x02,0xf0,0x75,0x8e,0x31,0x75,0x89,0x21,0x75,0x88,0x00,0x75,0xc8} }, +{ 14, 0x078b, 0, {0x00,0x75,0x8d,0x40,0x75,0x98,0x40,0x75,0xc0,0x40,0x75,0x87,0x00,0x75} }, +{ 9, 0x0799, 0, {0x20,0x00,0x75,0x21,0x00,0x75,0x22,0x00,0x75} }, +{ 5, 0x07a2, 0, {0x23,0x00,0x75,0x47,0x00} }, +{ 7, 0x07a7, 0, {0xc3,0xe5,0x47,0x94,0x20,0x50,0x11} }, +{ 13, 0x07ae, 0, {0xe5,0x47,0x24,0x00,0xf5,0x82,0xe4,0x34,0x17,0xf5,0x83,0xe4,0xf0} }, +{ 4, 0x07bb, 0, {0x05,0x47,0x80,0xe8} }, +{ 9, 0x07bf, 0, {0xe4,0xf5,0x40,0xf5,0x3f,0xe4,0xf5,0x3c,0xf5} }, +{ 7, 0x07c8, 0, {0x3b,0xe4,0xf5,0x3e,0xf5,0x3d,0x75} }, +{ 11, 0x07cf, 0, {0x32,0x00,0x75,0x37,0x00,0x75,0x39,0x00,0x90,0x7f,0x93} }, +{ 14, 0x07da, 0, {0x74,0x3c,0xf0,0x90,0x7f,0x9c,0x74,0xff,0xf0,0x90,0x7f,0x96,0x74,0x80} }, +{ 14, 0x07e8, 0, {0xf0,0x90,0x7f,0x94,0x74,0x70,0xf0,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} }, +{ 14, 0x07f6, 0, {0x7f,0x97,0xe4,0xf0,0x90,0x7f,0x95,0x74,0xc2,0xf0,0x90,0x7f,0x98,0x74} }, +{ 14, 0x0804, 0, {0x28,0xf0,0x90,0x7f,0x9e,0x74,0x28,0xf0,0x90,0x7f,0xf0,0xe4,0xf0,0x90} }, +{ 14, 0x0812, 0, {0x7f,0xf1,0xe4,0xf0,0x90,0x7f,0xf2,0xe4,0xf0,0x90,0x7f,0xf3,0xe4,0xf0} }, +{ 14, 0x0820, 0, {0x90,0x7f,0xf4,0xe4,0xf0,0x90,0x7f,0xf5,0xe4,0xf0,0x90,0x7f,0xf6,0xe4} }, +{ 14, 0x082e, 0, {0xf0,0x90,0x7f,0xf7,0xe4,0xf0,0x90,0x7f,0xf8,0xe4,0xf0,0x90,0x7f,0xf9} }, +{ 14, 0x083c, 0, {0x74,0x38,0xf0,0x90,0x7f,0xfa,0x74,0xa0,0xf0,0x90,0x7f,0xfb,0x74,0xa0} }, +{ 14, 0x084a, 0, {0xf0,0x90,0x7f,0xfc,0x74,0xa0,0xf0,0x90,0x7f,0xfd,0x74,0xa0,0xf0,0x90} }, +{ 14, 0x0858, 0, {0x7f,0xfe,0x74,0xa0,0xf0,0x90,0x7f,0xff,0x74,0xa0,0xf0,0x90,0x7f,0xe0} }, +{ 14, 0x0866, 0, {0x74,0x03,0xf0,0x90,0x7f,0xe1,0x74,0x01,0xf0,0x90,0x7f,0xdd,0x74,0x80} }, +{ 11, 0x0874, 0, {0xf0,0x12,0x12,0x43,0x12,0x07,0x1e,0x7a,0x00,0x7b,0x00} }, +{ 9, 0x087f, 0, {0xc3,0xea,0x94,0x1e,0xeb,0x94,0x00,0x50,0x17} }, +{ 12, 0x0888, 0, {0x90,0x88,0x00,0xe0,0xf5,0x47,0x90,0x88,0x0b,0xe0,0xf5,0x47} }, +{ 9, 0x0894, 0, {0x90,0x7f,0x68,0xf0,0x0a,0xba,0x00,0x01,0x0b} }, +{ 2, 0x089d, 0, {0x80,0xe0} }, +{ 12, 0x089f, 0, {0x12,0x03,0xe1,0x90,0x7f,0xd6,0xe4,0xf0,0x7a,0x00,0x7b,0x00} }, +{ 13, 0x08ab, 0, {0x8a,0x04,0x8b,0x05,0xc3,0xea,0x94,0xe0,0xeb,0x94,0x2e,0x50,0x1a} }, +{ 14, 0x08b8, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} }, +{ 10, 0x08c6, 0, {0x04,0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} }, +{ 2, 0x08d0, 0, {0x80,0xd9} }, +{ 13, 0x08d2, 0, {0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0,0x90} }, +{ 14, 0x08df, 0, {0x7f,0xde,0x74,0x05,0xf0,0x90,0x7f,0xdf,0x74,0x05,0xf0,0x90,0x7f,0xac} }, +{ 14, 0x08ed, 0, {0xe4,0xf0,0x90,0x7f,0xad,0x74,0x05,0xf0,0x75,0xa8,0x80,0x75,0xf8,0x10} }, +{ 13, 0x08fb, 0, {0x90,0x7f,0xae,0x74,0x0b,0xf0,0x90,0x7f,0xe2,0x74,0x88,0xf0,0x90} }, +{ 12, 0x0908, 0, {0x7f,0xab,0x74,0x08,0xf0,0x75,0xe8,0x11,0x75,0x32,0x01,0x75} }, +{ 12, 0x0914, 0, {0x31,0x00,0x75,0x30,0x00,0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7} }, +{ 10, 0x0920, 0, {0xd0,0x05,0xd0,0x04,0x75,0x34,0x00,0x75,0x35,0x01} }, +{ 13, 0x092a, 0, {0x90,0x7f,0xae,0x74,0x03,0xf0,0x8c,0x02,0xba,0x00,0x02,0x80,0x03} }, +{ 3, 0x0937, 0, {0x02,0x0a,0x3f} }, +{ 12, 0x093a, 0, {0x85,0x33,0x34,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90,0x7f,0x97} }, +{ 14, 0x0946, 0, {0x74,0x08,0xf0,0x90,0x7f,0x9d,0x74,0x88,0xf0,0x90,0x7f,0x9a,0xe0,0xfa} }, +{ 12, 0x0954, 0, {0x74,0x05,0x5a,0xf5,0x33,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} }, +{ 13, 0x0960, 0, {0x7f,0x97,0x74,0x02,0xf0,0x90,0x7f,0x9d,0x74,0x82,0xf0,0xe5,0x33} }, +{ 13, 0x096d, 0, {0x25,0xe0,0xfa,0x90,0x7f,0x9a,0xe0,0x54,0x05,0xfb,0x4a,0xf5,0x33} }, +{ 2, 0x097a, 0, {0x60,0x0c} }, +{ 12, 0x097c, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x4a,0xf0} }, +{ 11, 0x0988, 0, {0x75,0x6e,0x00,0x75,0x6f,0x00,0xc0,0x04,0xc0,0x05,0x12} }, +{ 14, 0x0993, 0, {0x11,0x44,0xd0,0x05,0xd0,0x04,0x90,0x17,0x13,0xe0,0xfa,0x74,0x80,0x2a} }, +{ 6, 0x09a1, 0, {0xfa,0xe5,0x33,0xb4,0x04,0x29} }, +{ 3, 0x09a7, 0, {0xba,0xa0,0x00} }, +{ 2, 0x09aa, 0, {0x50,0x24} }, +{ 13, 0x09ac, 0, {0x90,0x17,0x13,0xe0,0x04,0xfb,0x0b,0x90,0x17,0x13,0xeb,0xf0,0x90} }, +{ 14, 0x09b9, 0, {0x17,0x13,0xe0,0xfb,0x90,0x17,0x15,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05} }, +{ 9, 0x09c7, 0, {0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02} }, +{ 5, 0x09d0, 0, {0xe5,0x33,0xb4,0x02,0x26} }, +{ 6, 0x09d5, 0, {0xc3,0x74,0x04,0x9a,0x50,0x20} }, +{ 13, 0x09db, 0, {0x90,0x17,0x13,0xe0,0xfa,0x1a,0x1a,0x90,0x17,0x13,0xea,0xf0,0x90} }, +{ 13, 0x09e8, 0, {0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xf0,0xc0,0x04,0xc0,0x05,0x12} }, +{ 6, 0x09f5, 0, {0x04,0xf7,0xd0,0x05,0xd0,0x04} }, +{ 5, 0x09fb, 0, {0xe5,0x33,0xb4,0x08,0x1d} }, +{ 4, 0x0a00, 0, {0xe5,0x34,0x70,0x19} }, +{ 10, 0x0a04, 0, {0x74,0x01,0x25,0x35,0x54,0x0f,0xf5,0x35,0x85,0x35} }, +{ 12, 0x0a0e, 0, {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} }, +{ 3, 0x0a1a, 0, {0x05,0xd0,0x04} }, +{ 5, 0x0a1d, 0, {0xe5,0x33,0xb4,0x01,0x1d} }, +{ 4, 0x0a22, 0, {0xe5,0x34,0x70,0x19} }, +{ 10, 0x0a26, 0, {0xe5,0x35,0x24,0xff,0x54,0x0f,0xf5,0x35,0x85,0x35} }, +{ 12, 0x0a30, 0, {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} }, +{ 3, 0x0a3c, 0, {0x05,0xd0,0x04} }, +{ 14, 0x0a3f, 0, {0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0,0x04,0x90,0x7f,0x96} }, +{ 14, 0x0a4d, 0, {0xe0,0xfa,0x90,0x7f,0x96,0x74,0x7f,0x5a,0xf0,0x90,0x7f,0x97,0x74,0x08} }, +{ 10, 0x0a5b, 0, {0xf0,0xc3,0xec,0x94,0x00,0xed,0x94,0x02,0x40,0x08} }, +{ 8, 0x0a65, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x20,0xe6,0x08} }, +{ 8, 0x0a6d, 0, {0xc3,0xe4,0x9c,0x74,0x08,0x9d,0x50,0x13} }, +{ 14, 0x0a75, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x40,0x65,0x02,0xf0,0x7c} }, +{ 5, 0x0a83, 0, {0x00,0x7d,0x00,0x80,0x05} }, +{ 5, 0x0a88, 0, {0x0c,0xbc,0x00,0x01,0x0d} }, +{ 5, 0x0a8d, 0, {0xe5,0x38,0xb4,0x01,0x0e} }, +{ 13, 0x0a92, 0, {0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0x75,0x38} }, +{ 1, 0x0a9f, 0, {0x00} }, +{ 7, 0x0aa0, 0, {0xe5,0x31,0x70,0x03,0x02,0x09,0x2a} }, +{ 10, 0x0aa7, 0, {0x90,0x7f,0xc9,0xe0,0xfa,0x70,0x03,0x02,0x0c,0x2d} }, +{ 14, 0x0ab1, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} }, +{ 9, 0x0abf, 0, {0x7d,0xc0,0xe0,0xfa,0xba,0x2c,0x02,0x80,0x03} }, +{ 3, 0x0ac8, 0, {0x02,0x0b,0x36} }, +{ 5, 0x0acb, 0, {0x75,0x32,0x00,0x7b,0x00} }, +{ 3, 0x0ad0, 0, {0xbb,0x64,0x00} }, +{ 2, 0x0ad3, 0, {0x50,0x1c} }, +{ 14, 0x0ad5, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} }, +{ 13, 0x0ae3, 0, {0x04,0xd0,0x03,0xd0,0x02,0x90,0x88,0x0f,0xe0,0xf5,0x47,0x0b,0x80} }, +{ 1, 0x0af0, 0, {0xdf} }, +{ 13, 0x0af1, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x07,0x1e,0x12,0x03,0xe1,0x12} }, +{ 12, 0x0afe, 0, {0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x75,0x6e,0x00,0x75} }, +{ 13, 0x0b0a, 0, {0x6f,0x01,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0x44,0xd0,0x05} }, +{ 9, 0x0b17, 0, {0xd0,0x04,0xd0,0x02,0x75,0x70,0x4d,0x75,0x71} }, +{ 11, 0x0b20, 0, {0x0c,0x75,0x72,0x02,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} }, +{ 11, 0x0b2b, 0, {0x11,0x75,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x02,0x0c,0x2d} }, +{ 3, 0x0b36, 0, {0xba,0x2a,0x3b} }, +{ 13, 0x0b39, 0, {0x90,0x7f,0x98,0x74,0x20,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} }, +{ 14, 0x0b46, 0, {0x01,0xdd,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x90,0x7f,0x98,0x74,0x28,0xf0} }, +{ 2, 0x0b54, 0, {0x7b,0x00} }, +{ 3, 0x0b56, 0, {0xbb,0x0a,0x00} }, +{ 5, 0x0b59, 0, {0x40,0x03,0x02,0x0c,0x2d} }, +{ 14, 0x0b5e, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} }, +{ 8, 0x0b6c, 0, {0x04,0xd0,0x03,0xd0,0x02,0x0b,0x80,0xe2} }, +{ 3, 0x0b74, 0, {0xba,0x2b,0x1a} }, +{ 8, 0x0b77, 0, {0x90,0x7f,0xc9,0xe0,0xfb,0xbb,0x40,0x12} }, +{ 14, 0x0b7f, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x12,0x05,0xd0,0x05,0xd0,0x04,0xd0} }, +{ 4, 0x0b8d, 0, {0x02,0x02,0x0c,0x2d} }, +{ 3, 0x0b91, 0, {0xba,0x10,0x1f} }, +{ 14, 0x0b94, 0, {0x90,0x7f,0x96,0xe0,0xfb,0x90,0x7f,0x96,0x74,0x80,0x65,0x03,0xf0,0xc0} }, +{ 14, 0x0ba2, 0, {0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x3d,0xd0,0x05,0xd0,0x04,0xd0,0x02} }, +{ 3, 0x0bb0, 0, {0x02,0x0c,0x2d} }, +{ 3, 0x0bb3, 0, {0xba,0x11,0x12} }, +{ 14, 0x0bb6, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x6a,0xd0,0x05,0xd0,0x04,0xd0} }, +{ 4, 0x0bc4, 0, {0x02,0x02,0x0c,0x2d} }, +{ 3, 0x0bc8, 0, {0xba,0x12,0x12} }, +{ 14, 0x0bcb, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x8f,0xd0,0x05,0xd0,0x04,0xd0} }, +{ 4, 0x0bd9, 0, {0x02,0x02,0x0c,0x2d} }, +{ 3, 0x0bdd, 0, {0xba,0x13,0x0b} }, +{ 11, 0x0be0, 0, {0x90,0x7d,0xc1,0xe0,0xfb,0x90,0x88,0x00,0xf0,0x80,0x42} }, +{ 3, 0x0beb, 0, {0xba,0x14,0x11} }, +{ 14, 0x0bee, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0xdd,0xd0,0x05,0xd0,0x04,0xd0} }, +{ 3, 0x0bfc, 0, {0x02,0x80,0x2e} }, +{ 3, 0x0bff, 0, {0xba,0x15,0x1d} }, +{ 12, 0x0c02, 0, {0x90,0x7d,0xc1,0xe0,0xf5,0x75,0x90,0x7d,0xc2,0xe0,0xf5,0x76} }, +{ 14, 0x0c0e, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0,0x05,0xd0,0x04,0xd0} }, +{ 3, 0x0c1c, 0, {0x02,0x80,0x0e} }, +{ 3, 0x0c1f, 0, {0xba,0x16,0x0b} }, +{ 11, 0x0c22, 0, {0xc0,0x04,0xc0,0x05,0x12,0x13,0xa3,0xd0,0x05,0xd0,0x04} }, +{ 11, 0x0c2d, 0, {0x90,0x7f,0xc9,0xe4,0xf0,0x75,0x31,0x00,0x02,0x09,0x2a} }, +{ 1, 0x0c38, 0, {0x22} }, +{ 7, 0x0c39, 0, {0x53,0x55,0x50,0x45,0x4e,0x44,0x00} }, +{ 7, 0x0c40, 0, {0x52,0x45,0x53,0x55,0x4d,0x45,0x00} }, +{ 6, 0x0c47, 0, {0x20,0x56,0x6f,0x6c,0x20,0x00} }, +{ 13, 0x0c4d, 0, {0x44,0x41,0x42,0x55,0x53,0x42,0x20,0x76,0x31,0x2e,0x30,0x30,0x00} }, +{ 14, 0x0c5a, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, +{ 14, 0x0c68, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, +{ 13, 0x0c76, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} }, +{ 14, 0x0c83, 0, {0x7f,0xab,0x74,0x01,0xf0,0x90,0x7f,0xe8,0xe0,0xfa,0x90,0x7f,0xe9,0xe0} }, +{ 6, 0x0c91, 0, {0xfb,0xbb,0x00,0x02,0x80,0x03} }, +{ 3, 0x0c97, 0, {0x02,0x0d,0x38} }, +{ 3, 0x0c9a, 0, {0xba,0x80,0x14} }, +{ 14, 0x0c9d, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5} }, +{ 6, 0x0cab, 0, {0x74,0x02,0xf0,0x02,0x0e,0xcd} }, +{ 5, 0x0cb1, 0, {0xba,0x82,0x02,0x80,0x03} }, +{ 3, 0x0cb6, 0, {0x02,0x0d,0x1d} }, +{ 8, 0x0cb9, 0, {0x90,0x7f,0xec,0xe0,0xfc,0xbc,0x01,0x00} }, +{ 2, 0x0cc1, 0, {0x40,0x21} }, +{ 6, 0x0cc3, 0, {0xc3,0x74,0x07,0x9c,0x40,0x1b} }, +{ 14, 0x0cc9, 0, {0xec,0x24,0xff,0x25,0xe0,0xfd,0x24,0xc6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} }, +{ 13, 0x0cd7, 0, {0x83,0xe0,0xfd,0x53,0x05,0x01,0x90,0x7f,0x00,0xed,0xf0,0x80,0x2b} }, +{ 3, 0x0ce4, 0, {0xbc,0x81,0x00} }, +{ 2, 0x0ce7, 0, {0x40,0x21} }, +{ 6, 0x0ce9, 0, {0xc3,0x74,0x87,0x9c,0x40,0x1b} }, +{ 14, 0x0cef, 0, {0xec,0x24,0x7f,0x25,0xe0,0xfc,0x24,0xb6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} }, +{ 13, 0x0cfd, 0, {0x83,0xe0,0xfc,0x53,0x04,0x01,0x90,0x7f,0x00,0xec,0xf0,0x80,0x05} }, +{ 5, 0x0d0a, 0, {0x90,0x7f,0x00,0xe4,0xf0} }, +{ 14, 0x0d0f, 0, {0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0x02,0x0e,0xcd} }, +{ 5, 0x0d1d, 0, {0xba,0x81,0x02,0x80,0x03} }, +{ 3, 0x0d22, 0, {0x02,0x0e,0xc5} }, +{ 14, 0x0d25, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74} }, +{ 5, 0x0d33, 0, {0x02,0xf0,0x02,0x0e,0xcd} }, +{ 3, 0x0d38, 0, {0xbb,0x01,0x2d} }, +{ 6, 0x0d3b, 0, {0xba,0x00,0x03,0x02,0x0e,0xcd} }, +{ 3, 0x0d41, 0, {0xba,0x02,0x11} }, +{ 13, 0x0d44, 0, {0x75,0x59,0x00,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} }, +{ 4, 0x0d51, 0, {0x02,0x02,0x0e,0xcd} }, +{ 5, 0x0d55, 0, {0xba,0x21,0x02,0x80,0x03} }, +{ 3, 0x0d5a, 0, {0x02,0x0e,0xcd} }, +{ 11, 0x0d5d, 0, {0x75,0x37,0x01,0x90,0x7f,0xc5,0xe4,0xf0,0x02,0x0e,0xcd} }, +{ 3, 0x0d68, 0, {0xbb,0x03,0x1f} }, +{ 6, 0x0d6b, 0, {0xba,0x00,0x03,0x02,0x0e,0xcd} }, +{ 5, 0x0d71, 0, {0xba,0x02,0x02,0x80,0x03} }, +{ 3, 0x0d76, 0, {0x02,0x0e,0xcd} }, +{ 13, 0x0d79, 0, {0x75,0x59,0x01,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} }, +{ 4, 0x0d86, 0, {0x02,0x02,0x0e,0xcd} }, +{ 3, 0x0d8a, 0, {0xbb,0x06,0x54} }, +{ 5, 0x0d8d, 0, {0xba,0x80,0x02,0x80,0x03} }, +{ 3, 0x0d92, 0, {0x02,0x0e,0xc5} }, +{ 8, 0x0d95, 0, {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x01,0x15} }, +{ 12, 0x0d9d, 0, {0x7c,0xfb,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} }, +{ 9, 0x0da9, 0, {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} }, +{ 10, 0x0db2, 0, {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x02,0x02,0x80,0x03} }, +{ 3, 0x0dbc, 0, {0x02,0x0e,0xc5} }, +{ 10, 0x0dbf, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x02,0x80,0x03} }, +{ 3, 0x0dc9, 0, {0x02,0x0e,0xc5} }, +{ 12, 0x0dcc, 0, {0x7c,0x3b,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} }, +{ 9, 0x0dd8, 0, {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} }, +{ 6, 0x0de1, 0, {0xbb,0x07,0x03,0x02,0x0e,0xc5} }, +{ 3, 0x0de7, 0, {0xbb,0x08,0x10} }, +{ 13, 0x0dea, 0, {0xac,0x48,0x90,0x7f,0x00,0xec,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} }, +{ 3, 0x0df7, 0, {0x02,0x0e,0xcd} }, +{ 3, 0x0dfa, 0, {0xbb,0x09,0x31} }, +{ 5, 0x0dfd, 0, {0xba,0x00,0x02,0x80,0x03} }, +{ 3, 0x0e02, 0, {0x02,0x0e,0xc5} }, +{ 14, 0x0e05, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xc3,0x74,0x01,0x9c,0x50,0x03,0x02,0x0e,0xc5} }, +{ 8, 0x0e13, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x0a} }, +{ 10, 0x0e1b, 0, {0x90,0x17,0x21,0xe4,0xf0,0x90,0x17,0x22,0xe4,0xf0} }, +{ 9, 0x0e25, 0, {0x90,0x7f,0xea,0xe0,0xf5,0x48,0x02,0x0e,0xcd} }, +{ 3, 0x0e2e, 0, {0xbb,0x0a,0x27} }, +{ 5, 0x0e31, 0, {0xba,0x81,0x02,0x80,0x03} }, +{ 3, 0x0e36, 0, {0x02,0x0e,0xc5} }, +{ 14, 0x0e39, 0, {0x90,0x7f,0xec,0xe0,0xfa,0x24,0x20,0xfa,0xe4,0x34,0x17,0xfc,0x8a,0x82} }, +{ 14, 0x0e47, 0, {0x8c,0x83,0xe0,0xfa,0x90,0x7f,0x00,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} }, +{ 3, 0x0e55, 0, {0x02,0x0e,0xcd} }, +{ 5, 0x0e58, 0, {0xbb,0x0b,0x02,0x80,0x03} }, +{ 3, 0x0e5d, 0, {0x02,0x0e,0xa9} }, +{ 13, 0x0e60, 0, {0x90,0x17,0x20,0xe4,0xf0,0x90,0x7f,0xec,0xe0,0xfa,0xba,0x01,0x1a} }, +{ 8, 0x0e6d, 0, {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x12} }, +{ 14, 0x0e75, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x90,0x17,0x21,0xf0,0xc0,0x03,0x12,0x04,0xe2} }, +{ 4, 0x0e83, 0, {0xd0,0x03,0x80,0x46} }, +{ 8, 0x0e87, 0, {0x90,0x7f,0xec,0xe0,0xfa,0xba,0x02,0x3e} }, +{ 8, 0x0e8f, 0, {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x36} }, +{ 13, 0x0e97, 0, {0xc0,0x03,0x12,0x04,0xef,0xd0,0x03,0x90,0x7f,0xea,0xe0,0xfa,0x90} }, +{ 5, 0x0ea4, 0, {0x17,0x22,0xf0,0x80,0x24} }, +{ 5, 0x0ea9, 0, {0xbb,0x12,0x02,0x80,0x17} }, +{ 5, 0x0eae, 0, {0xbb,0x81,0x02,0x80,0x0d} }, +{ 5, 0x0eb3, 0, {0xbb,0x83,0x02,0x80,0x08} }, +{ 5, 0x0eb8, 0, {0xbb,0x82,0x02,0x80,0x03} }, +{ 3, 0x0ebd, 0, {0xbb,0x84,0x05} }, +{ 5, 0x0ec0, 0, {0x12,0x06,0x4e,0x80,0x08} }, +{ 8, 0x0ec5, 0, {0x90,0x7f,0xb4,0x74,0x03,0xf0,0x80,0x06} }, +{ 6, 0x0ecd, 0, {0x90,0x7f,0xb4,0x74,0x02,0xf0} }, +{ 2, 0x0ed3, 0, {0xd0,0x86} }, +{ 14, 0x0ed5, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, +{ 13, 0x0ee3, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 11, 0x0ef0, 0, {0x90,0x7f,0xec,0xe0,0xf5,0x5a,0xc3,0x94,0x01,0x40,0x1d} }, +{ 7, 0x0efb, 0, {0xc3,0x74,0x07,0x95,0x5a,0x40,0x16} }, +{ 13, 0x0f02, 0, {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xc6,0xf5,0x82,0xe4,0x34} }, +{ 9, 0x0f0f, 0, {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0,0x80,0x22} }, +{ 7, 0x0f18, 0, {0xc3,0xe5,0x5a,0x94,0x81,0x40,0x1b} }, +{ 7, 0x0f1f, 0, {0xc3,0x74,0x87,0x95,0x5a,0x40,0x14} }, +{ 13, 0x0f26, 0, {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xb6,0xf5,0x82,0xe4,0x34} }, +{ 7, 0x0f33, 0, {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0} }, +{ 1, 0x0f3a, 0, {0x22} }, +{ 14, 0x0f3b, 0, {0x09,0x02,0xba,0x00,0x03,0x01,0x00,0x40,0x00,0x09,0x04,0x00,0x00,0x00} }, +{ 14, 0x0f49, 0, {0x01,0x01,0x00,0x00,0x09,0x24,0x01,0x00,0x01,0x3d,0x00,0x01,0x01,0x0c} }, +{ 14, 0x0f57, 0, {0x24,0x02,0x01,0x10,0x07,0x00,0x02,0x03,0x00,0x00,0x00,0x0d,0x24,0x06} }, +{ 14, 0x0f65, 0, {0x03,0x01,0x02,0x15,0x00,0x03,0x00,0x03,0x00,0x00,0x09,0x24,0x03,0x02} }, +{ 14, 0x0f73, 0, {0x01,0x01,0x00,0x01,0x00,0x09,0x24,0x03,0x04,0x02,0x03,0x00,0x03,0x00} }, +{ 14, 0x0f81, 0, {0x09,0x24,0x03,0x05,0x03,0x06,0x00,0x01,0x00,0x09,0x04,0x01,0x00,0x00} }, +{ 14, 0x0f8f, 0, {0x01,0x02,0x00,0x00,0x09,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00,0x07} }, +{ 14, 0x0f9d, 0, {0x24,0x01,0x02,0x01,0x01,0x00,0x0b,0x24,0x02,0x01,0x02,0x02,0x10,0x01} }, +{ 14, 0x0fab, 0, {0x80,0xbb,0x00,0x09,0x05,0x88,0x05,0x00,0x01,0x01,0x00,0x00,0x07,0x25} }, +{ 14, 0x0fb9, 0, {0x01,0x00,0x00,0x00,0x00,0x09,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00} }, +{ 14, 0x0fc7, 0, {0x07,0x05,0x82,0x02,0x40,0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00} }, +{ 14, 0x0fd5, 0, {0x09,0x04,0x02,0x01,0x03,0x00,0x00,0x00,0x00,0x07,0x05,0x82,0x02,0x40} }, +{ 14, 0x0fe3, 0, {0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00,0x09,0x05,0x89,0x05,0xa0} }, +{ 10, 0x0ff1, 0, {0x01,0x01,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00} }, +{ 14, 0x0ffb, 0, {0x12,0x01,0x00,0x01,0x00,0x00,0x00,0x40,0x47,0x05,0x99,0x99,0x00,0x01} }, +{ 14, 0x1009, 0, {0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x02,0xba} }, +{ 4, 0x1017, 0, {0x00,0x03,0x01,0x00} }, +{ 2, 0x101b, 0, {0x7a,0x00} }, +{ 3, 0x101d, 0, {0xba,0x05,0x00} }, +{ 2, 0x1020, 0, {0x50,0x17} }, +{ 8, 0x1022, 0, {0x90,0x7f,0xa5,0xe0,0xfb,0x30,0xe0,0x05} }, +{ 5, 0x102a, 0, {0x90,0x00,0x01,0x80,0x0d} }, +{ 10, 0x102f, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xe4} }, +{ 3, 0x1039, 0, {0x90,0x00,0x01} }, +{ 1, 0x103c, 0, {0x22} }, +{ 14, 0x103d, 0, {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0x00,0x7d} }, +{ 4, 0x104b, 0, {0x7e,0xeb,0x60,0x12} }, +{ 14, 0x104f, 0, {0x89,0x82,0x8a,0x83,0xe0,0xa3,0xa9,0x82,0xaa,0x83,0x8c,0x82,0x8d,0x83} }, +{ 4, 0x105d, 0, {0xf0,0x0c,0xdb,0xee} }, +{ 8, 0x1061, 0, {0x90,0x7d,0xc3,0xe0,0x90,0x7f,0xb9,0xf0} }, +{ 1, 0x1069, 0, {0x22} }, +{ 14, 0x106a, 0, {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0xc4,0x7d} }, +{ 4, 0x1078, 0, {0x7d,0xeb,0x60,0xe5} }, +{ 14, 0x107c, 0, {0x8c,0x82,0x8d,0x83,0xe0,0x0c,0x89,0x82,0x8a,0x83,0xf0,0xa3,0xa9,0x82} }, +{ 4, 0x108a, 0, {0xaa,0x83,0xdb,0xee} }, +{ 1, 0x108e, 0, {0x22} }, +{ 14, 0x108f, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x05,0x86,0x90,0x7d,0xc1,0xe0,0x05,0x86} }, +{ 14, 0x109d, 0, {0xa3,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0x05,0x86,0xa3,0xa3,0xe0,0xf9} }, +{ 5, 0x10ab, 0, {0x60,0x16,0xa3,0x05,0x86} }, +{ 13, 0x10b0, 0, {0x90,0x7f,0xa6,0x05,0x86,0xe0,0xa3,0x05,0x86,0xf0,0xc0,0x01,0x12} }, +{ 6, 0x10bd, 0, {0x10,0x1b,0xd0,0x01,0xd9,0xed} }, +{ 6, 0x10c3, 0, {0x90,0x7f,0xa5,0x74,0x40,0xf0} }, +{ 1, 0x10c9, 0, {0x22} }, +{ 8, 0x10ca, 0, {0x90,0x88,0x02,0x74,0x01,0xf0,0x7a,0x00} }, +{ 3, 0x10d2, 0, {0xba,0xff,0x00} }, +{ 2, 0x10d5, 0, {0x50,0x0a} }, +{ 10, 0x10d7, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} }, +{ 1, 0x10e1, 0, {0x22} }, +{ 5, 0x10e2, 0, {0xe5,0x6b,0xb4,0xc0,0x08} }, +{ 8, 0x10e7, 0, {0x90,0x88,0x03,0xe5,0x6c,0xf0,0x80,0x06} }, +{ 6, 0x10ef, 0, {0x90,0x88,0x02,0xe5,0x6c,0xf0} }, +{ 4, 0x10f5, 0, {0x7a,0x00,0x7b,0x00} }, +{ 11, 0x10f9, 0, {0xc3,0xea,0x94,0x32,0xeb,0x64,0x80,0x94,0x80,0x50,0x07} }, +{ 5, 0x1104, 0, {0x0a,0xba,0x00,0x01,0x0b} }, +{ 2, 0x1109, 0, {0x80,0xee} }, +{ 1, 0x110b, 0, {0x22} }, +{ 10, 0x110c, 0, {0x90,0x88,0x03,0xe5,0x6d,0xf0,0x05,0x39,0x7a,0x00} }, +{ 3, 0x1116, 0, {0xba,0x28,0x00} }, +{ 2, 0x1119, 0, {0x50,0x03} }, +{ 3, 0x111b, 0, {0x0a,0x80,0xf8} }, +{ 5, 0x111e, 0, {0xe5,0x39,0xb4,0x10,0x08} }, +{ 8, 0x1123, 0, {0x90,0x88,0x02,0x74,0xc0,0xf0,0x80,0x0e} }, +{ 5, 0x112b, 0, {0xe5,0x39,0xb4,0x20,0x09} }, +{ 9, 0x1130, 0, {0x90,0x88,0x02,0x74,0x80,0xf0,0x75,0x39,0x00} }, +{ 2, 0x1139, 0, {0x7a,0x00} }, +{ 3, 0x113b, 0, {0xba,0x28,0x00} }, +{ 2, 0x113e, 0, {0x50,0x03} }, +{ 3, 0x1140, 0, {0x0a,0x80,0xf8} }, +{ 1, 0x1143, 0, {0x22} }, +{ 4, 0x1144, 0, {0xe5,0x6f,0x60,0x02} }, +{ 2, 0x1148, 0, {0x80,0x07} }, +{ 7, 0x114a, 0, {0x7a,0x00,0x75,0x39,0x00,0x80,0x05} }, +{ 5, 0x1151, 0, {0x7a,0x40,0x75,0x39,0x10} }, +{ 9, 0x1156, 0, {0xe5,0x6e,0x2a,0xfa,0xe5,0x6e,0x25,0x39,0xf5} }, +{ 10, 0x115f, 0, {0x39,0x90,0x88,0x02,0x74,0x80,0x2a,0xf0,0x7a,0x00} }, +{ 8, 0x1169, 0, {0xc3,0xea,0x64,0x80,0x94,0xa8,0x50,0x03} }, +{ 3, 0x1171, 0, {0x0a,0x80,0xf5} }, +{ 1, 0x1174, 0, {0x22} }, +{ 6, 0x1175, 0, {0xaa,0x70,0xab,0x71,0xac,0x72} }, +{ 12, 0x117b, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x12,0x14,0xee,0xfd,0x60,0x18} }, +{ 13, 0x1187, 0, {0x8d,0x6d,0xc0,0x02,0xc0,0x03,0xc0,0x04,0x12,0x11,0x0c,0xd0,0x04} }, +{ 9, 0x1194, 0, {0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} }, +{ 2, 0x119d, 0, {0x80,0xdc} }, +{ 1, 0x119f, 0, {0x22} }, +{ 13, 0x11a0, 0, {0xe5,0x73,0xc4,0x54,0x0f,0xfa,0x53,0x02,0x0f,0xc3,0x74,0x09,0x9a} }, +{ 2, 0x11ad, 0, {0x50,0x06} }, +{ 6, 0x11af, 0, {0x74,0x37,0x2a,0xfb,0x80,0x04} }, +{ 4, 0x11b5, 0, {0x74,0x30,0x2a,0xfb} }, +{ 12, 0x11b9, 0, {0x8b,0x6d,0xc0,0x03,0x12,0x11,0x0c,0xd0,0x03,0xaa,0x73,0x53} }, +{ 8, 0x11c5, 0, {0x02,0x0f,0xc3,0x74,0x09,0x9a,0x50,0x06} }, +{ 6, 0x11cd, 0, {0x74,0x37,0x2a,0xfb,0x80,0x04} }, +{ 4, 0x11d3, 0, {0x74,0x30,0x2a,0xfb} }, +{ 5, 0x11d7, 0, {0x8b,0x6d,0x12,0x11,0x0c} }, +{ 1, 0x11dc, 0, {0x22} }, +{ 7, 0x11dd, 0, {0x90,0x7d,0xc3,0xe0,0xfa,0x60,0x0f} }, +{ 12, 0x11e4, 0, {0x90,0x7d,0xc1,0xe0,0xf5,0x6e,0x90,0x7d,0xc2,0xe0,0xf5,0x6f} }, +{ 3, 0x11f0, 0, {0x12,0x11,0x44} }, +{ 12, 0x11f3, 0, {0x90,0x7d,0xff,0xe4,0xf0,0x75,0x70,0xc4,0x75,0x71,0x7d,0x75} }, +{ 5, 0x11ff, 0, {0x72,0x01,0x12,0x11,0x75} }, +{ 1, 0x1204, 0, {0x22} }, +{ 2, 0x1205, 0, {0x7a,0x04} }, +{ 3, 0x1207, 0, {0xba,0x40,0x00} }, +{ 2, 0x120a, 0, {0x50,0x36} }, +{ 14, 0x120c, 0, {0xea,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfb,0x7c,0x00} }, +{ 3, 0x121a, 0, {0xbc,0x08,0x00} }, +{ 2, 0x121d, 0, {0x50,0x20} }, +{ 6, 0x121f, 0, {0x8b,0x05,0xed,0x30,0xe7,0x0b} }, +{ 11, 0x1225, 0, {0x90,0x7f,0x96,0x74,0x42,0xf0,0x74,0xc3,0xf0,0x80,0x08} }, +{ 8, 0x1230, 0, {0x90,0x7f,0x96,0xe4,0xf0,0x74,0x81,0xf0} }, +{ 7, 0x1238, 0, {0xeb,0x25,0xe0,0xfb,0x0c,0x80,0xdb} }, +{ 3, 0x123f, 0, {0x0a,0x80,0xc5} }, +{ 1, 0x1242, 0, {0x22} }, +{ 4, 0x1243, 0, {0x7a,0x00,0x7b,0xef} }, +{ 3, 0x1247, 0, {0xba,0x10,0x00} }, +{ 2, 0x124a, 0, {0x50,0x20} }, +{ 14, 0x124c, 0, {0x74,0x11,0x2b,0xfb,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0x8c,0x82,0x8d} }, +{ 14, 0x125a, 0, {0x83,0xe4,0xf0,0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe4} }, +{ 4, 0x1268, 0, {0xf0,0x0a,0x80,0xdb} }, +{ 1, 0x126c, 0, {0x22} }, +{ 14, 0x126d, 0, {0x74,0xf8,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, +{ 14, 0x127b, 0, {0x74,0xf9,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, +{ 14, 0x1289, 0, {0x74,0xfa,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, +{ 14, 0x1297, 0, {0x74,0xfb,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, +{ 14, 0x12a5, 0, {0x74,0xff,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, +{ 1, 0x12b3, 0, {0x22} }, +{ 14, 0x12b4, 0, {0x12,0x03,0xcb,0x12,0x12,0x6d,0x7a,0xc0,0x7b,0x87,0x7c,0x01,0x74,0x01} }, +{ 14, 0x12c2, 0, {0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74} }, +{ 14, 0x12d0, 0, {0x01,0x12,0x14,0xbf,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e} }, +{ 14, 0x12de, 0, {0x83,0x8f,0xf0,0x74,0x06,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b} }, +{ 14, 0x12ec, 0, {0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74} }, +{ 14, 0x12fa, 0, {0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0} }, +{ 14, 0x1308, 0, {0x74,0x0b,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07} }, +{ 14, 0x1316, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74,0x08,0x12,0x14,0xbf,0x74,0x01,0x2d} }, +{ 14, 0x1324, 0, {0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x01} }, +{ 14, 0x1332, 0, {0x12,0x14,0xbf,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83} }, +{ 14, 0x1340, 0, {0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74,0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f} }, +{ 14, 0x134e, 0, {0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x03,0x12,0x14,0xbf,0x7d,0x00} }, +{ 3, 0x135c, 0, {0xbd,0x06,0x00} }, +{ 2, 0x135f, 0, {0x50,0x12} }, +{ 11, 0x1361, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x0a,0xba,0x00,0x01,0x0b} }, +{ 7, 0x136c, 0, {0xe4,0x12,0x14,0xbf,0x0d,0x80,0xe9} }, +{ 13, 0x1373, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe5,0x74,0x12,0x14,0xbf,0x74,0xf9} }, +{ 14, 0x1380, 0, {0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x0f,0xf0,0x74} }, +{ 14, 0x138e, 0, {0xfe,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x01,0xf0} }, +{ 6, 0x139c, 0, {0x12,0x03,0xe1,0x12,0x04,0xf7} }, +{ 1, 0x13a2, 0, {0x22} }, +{ 13, 0x13a3, 0, {0x90,0x7d,0xc1,0xe0,0xfa,0x24,0x00,0xfb,0xe4,0x34,0x19,0xfc,0x90} }, +{ 14, 0x13b0, 0, {0x7d,0xc2,0xe0,0xfd,0x8b,0x82,0x8c,0x83,0xf0,0x75,0xf0,0x11,0xea,0xa4} }, +{ 3, 0x13be, 0, {0xfa,0x7b,0x00} }, +{ 3, 0x13c1, 0, {0xbb,0x10,0x00} }, +{ 2, 0x13c4, 0, {0x50,0x24} }, +{ 14, 0x13c6, 0, {0xea,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0xeb,0x2c,0xfc,0xe4,0x3d,0xfd} }, +{ 14, 0x13d4, 0, {0x74,0x04,0x2b,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfe} }, +{ 8, 0x13e2, 0, {0x8c,0x82,0x8d,0x83,0xf0,0x0b,0x80,0xd7} }, +{ 14, 0x13ea, 0, {0xea,0x24,0x00,0xfa,0xe4,0x34,0x18,0xfb,0x74,0x10,0x2a,0xf5,0x82,0xe4} }, +{ 5, 0x13f8, 0, {0x3b,0xf5,0x83,0xe4,0xf0} }, +{ 1, 0x13fd, 0, {0x22} }, +{ 4, 0x13fe, 0, {0xe5,0x76,0x60,0x02} }, +{ 2, 0x1402, 0, {0x80,0x16} }, +{ 12, 0x1404, 0, {0x74,0x0f,0x55,0x75,0xfa,0x8a,0x75,0x24,0x00,0xf5,0x82,0xe4} }, +{ 10, 0x1410, 0, {0x34,0x19,0xf5,0x83,0xe0,0xf5,0x74,0x12,0x12,0xb4} }, +{ 10, 0x141a, 0, {0x12,0x10,0xca,0x75,0x6e,0x00,0x75,0x6f,0x00,0x12} }, +{ 6, 0x1424, 0, {0x11,0x44,0x75,0x70,0xb9,0x75} }, +{ 6, 0x142a, 0, {0x71,0x14,0x75,0x72,0x02,0x12} }, +{ 11, 0x1430, 0, {0x11,0x75,0xe5,0x76,0xb4,0x02,0x04,0x74,0x01,0x80,0x01} }, +{ 1, 0x143b, 0, {0xe4} }, +{ 3, 0x143c, 0, {0xfa,0x70,0x0f} }, +{ 12, 0x143f, 0, {0x74,0x01,0x25,0x75,0xf5,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0} }, +{ 3, 0x144b, 0, {0x02,0x80,0x0a} }, +{ 10, 0x144e, 0, {0x85,0x75,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0,0x02} }, +{ 12, 0x1458, 0, {0x75,0x6e,0x00,0x75,0x6f,0x01,0xc0,0x02,0x12,0x11,0x44,0xd0} }, +{ 4, 0x1464, 0, {0x02,0xea,0x70,0x1a} }, +{ 13, 0x1468, 0, {0x75,0xf0,0x11,0xe5,0x75,0xa4,0xfa,0x24,0x00,0xfa,0xe4,0x34,0x18} }, +{ 9, 0x1475, 0, {0xfb,0x8a,0x70,0x8b,0x71,0x75,0x72,0x01,0x12} }, +{ 4, 0x147e, 0, {0x11,0x75,0x80,0x36} }, +{ 2, 0x1482, 0, {0x7a,0x00} }, +{ 3, 0x1484, 0, {0xba,0x10,0x00} }, +{ 2, 0x1487, 0, {0x50,0x2f} }, +{ 13, 0x1489, 0, {0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe0,0xfb,0xe5} }, +{ 4, 0x1496, 0, {0x75,0xb5,0x03,0x1b} }, +{ 14, 0x149a, 0, {0x75,0xf0,0x11,0xea,0xa4,0xfb,0x24,0x00,0xfb,0xe4,0x34,0x18,0xfc,0x8b} }, +{ 9, 0x14a8, 0, {0x70,0x8c,0x71,0x75,0x72,0x01,0xc0,0x02,0x12} }, +{ 4, 0x14b1, 0, {0x11,0x75,0xd0,0x02} }, +{ 3, 0x14b5, 0, {0x0a,0x80,0xcc} }, +{ 1, 0x14b8, 0, {0x22} }, +{ 6, 0x14b9, 0, {0x50,0x72,0x6f,0x67,0x20,0x00} }, +{ 14, 0x14bf, 0, {0xc8,0xc0,0xe0,0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0b,0x14,0x60,0x0f,0x14} }, +{ 7, 0x14cd, 0, {0x60,0x11,0x14,0x60,0x12,0x80,0x15} }, +{ 7, 0x14d4, 0, {0xd0,0xe0,0xa8,0x82,0xf6,0x80,0x0e} }, +{ 5, 0x14db, 0, {0xd0,0xe0,0xf0,0x80,0x09} }, +{ 4, 0x14e0, 0, {0xd0,0xe0,0x80,0x05} }, +{ 5, 0x14e4, 0, {0xd0,0xe0,0xa8,0x82,0xf2} }, +{ 4, 0x14e9, 0, {0xc8,0xd0,0xe0,0xc8} }, +{ 1, 0x14ed, 0, {0x22} }, +{ 14, 0x14ee, 0, {0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0d,0x14,0x60,0x0f,0x14,0x60,0x0f,0x14} }, +{ 6, 0x14fc, 0, {0x60,0x10,0x74,0xff,0x80,0x0f} }, +{ 5, 0x1502, 0, {0xa8,0x82,0xe6,0x80,0x0a} }, +{ 3, 0x1507, 0, {0xe0,0x80,0x07} }, +{ 4, 0x150a, 0, {0xe4,0x93,0x80,0x03} }, +{ 3, 0x150e, 0, {0xa8,0x82,0xe2} }, +{ 4, 0x1511, 0, {0xf8,0xd0,0xe0,0xc8} }, +{ 1, 0x1515, 0, {0x22} }, +{ 0, 0x0000, 1, {0} } + +}; + +static unsigned char bitstream[] = { + +0x00,0x09,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0, 0x0F,0xF0,0x00,0x00,0x01,0x61,0x00,0x0D, +0x64,0x61,0x62,0x75,0x73,0x62,0x74,0x72, 0x2E,0x6E,0x63,0x64,0x00,0x62,0x00,0x0B, +0x73,0x31,0x30,0x78,0x6C,0x76,0x71,0x31, 0x30,0x30,0x00,0x63,0x00,0x0B,0x31,0x39, +0x39,0x39,0x2F,0x30,0x39,0x2F,0x32,0x34, 0x00,0x64,0x00,0x09,0x31,0x30,0x3A,0x34, +0x32,0x3A,0x34,0x36,0x00,0x65,0x00,0x00, 0x2E,0xC0,0xFF,0x20,0x17,0x5F,0x9F,0x5B, +0xFE,0xFB,0xBB,0xB7,0xBB,0xBB,0xFB,0xBF, 0xAF,0xEF,0xFB,0xDF,0xB7,0xFB,0xFB,0x7F, +0xBF,0xB7,0xEF,0xF2,0xFF,0xFB,0xFE,0xFF, 0xFF,0xEF,0xFF,0xFE,0xFF,0xBF,0xFF,0xFF, +0xFF,0xFF,0xAF,0xFF,0xFA,0xFF,0xFF,0xFF, 0xC9,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFB,0xFF,0xA3,0xFF,0xFB, +0xFE,0xFF,0xBF,0xEF,0xE3,0xFE,0xFF,0xBF, 0xE3,0xFE,0xFF,0xBF,0x6F,0xFB,0xF6,0xFF, +0xBF,0xFF,0x47,0xFF,0xFF,0x9F,0xEE,0xF9, 0xFE,0xCF,0x9F,0xEF,0xFB,0xCF,0x9B,0xEE, +0xF8,0xFE,0xEF,0x8F,0xEE,0xFB,0xFE,0x0B, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xBF,0xFF,0xFF,0xFB,0xFF,0xFF, 0xBF,0xFF,0xFF,0xFC,0x17,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xFB,0xFF,0xFF,0x7F,0xFF,0xFF, +0xFC,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x5F,0xFF, 0xFF,0xFD,0xFF,0xFF,0xDB,0xFF,0xFD,0xFF, +0x77,0xFF,0xFD,0xFF,0xFF,0xDF,0xFE,0xFD, 0xFF,0xFF,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1, +0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xE3,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF, +0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x67,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0x7F,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF, 0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x2F,0xFF, +0xF3,0xFD,0xFF,0x7F,0xDE,0xF7,0xFD,0xFF, 0x7F,0xF7,0x7D,0xFF,0x7F,0xDF,0xF7,0xBD, +0xFF,0x7F,0xFF,0x1F,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xEF,0xFB, +0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF, 0x3F,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F, +0x9F,0xE7,0xFA,0x7F,0x9F,0xE7,0xF9,0xFE, 0x7F,0x9F,0xE7,0xFF,0xFC,0x7F,0xBF,0xBF, +0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xB7, 0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, +0xFF,0xE0,0xFD,0xF9,0xFE,0x7F,0x9F,0xE7, 0xF9,0xFE,0x7F,0x9D,0xF9,0xFE,0x7D,0x9D, +0xE7,0xF9,0xFE,0x7F,0x9F,0xED,0xED,0xFF, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, +0xDF,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF, 0x7F,0xDF,0xFF,0x9B,0xFF,0xEF,0xFB,0xFE, +0xFB,0xBF,0xEF,0xBB,0xFE,0xFF,0xAF,0xBB, 0xBE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF, +0xB7,0xBF,0xDB,0xF6,0xBD,0xBF,0x6B,0xDB, 0xF6,0xF9,0xBF,0x5B,0xD6,0xF9,0xBF,0x6F, +0xDB,0xF6,0xFD,0xBF,0xFF,0x0E,0xFF,0xFF, 0xFF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0x7F, +0xF7,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xDF,0x9F,0xFF,0xFF,0xFF,0xFE,0xFF, +0xFF,0xEF,0xFE,0xFE,0xFF,0xFF,0x77,0xFF, 0xFB,0xFB,0xFF,0xFF,0xFF,0xFF,0xF8,0x3F, +0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF4,0x7F,0xFF,0xFE,0xFD, 0xBE,0xFF,0xDF,0xFE,0xFF,0xFF,0xEF,0x7F, +0xFF,0xCF,0xFF,0xCF,0xFF,0xFF,0xFF,0xDF, 0xE6,0xFF,0xFF,0x7F,0xDF,0xF7,0xDD,0x7F, +0x7F,0xDF,0xF7,0xFF,0x7F,0xDF,0xD7,0xFD, 0xFF,0x7F,0xDF,0xF7,0xFF,0xCD,0xFF,0xF2, +0xFF,0xFF,0x4F,0x7F,0xF4,0xFF,0xFF,0xFF, 0xE7,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xBB,0xFF,0xEF,0xFF,0xFE,0xFF, 0xFF,0xFF,0xEF,0xFF,0xFF,0xEF,0xFF,0xFB, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x65, 0xEF,0xFF,0xFF,0x7F,0xFF,0xFD,0xEF,0xFF, +0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xCF,0xDF,0xFE,0xFF, +0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xF3,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFE,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xBF,0xFF, 0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xEF,0xEB,0xFF,0xFE,0xBF,0xFF, 0xEB,0xFF,0xFC,0x7F,0xFF,0xFF,0xFF,0xEE, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, 0xD6,0xFF,0xFD,0xBF,0xFF,0xFB,0xFF,0xFE, +0xFD,0xFF,0xFF,0xFD,0xEF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0x7F,0xBF, 0xFF,0x5F,0xDF,0xFF,0xFF,0xBF,0x77,0xFF, +0xFF,0xFF,0x7F,0xD7,0xFF,0xFF,0xFF,0xFF, 0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xDF,0xEF, +0xFF,0xFF,0xFE,0xFB,0xFF,0xFF,0xDF,0xBF, 0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xB7,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xAF,0x7F,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xDF,0xBF,0xDF,0xF3,0xFD,0xFB,0xFF,0x5B, +0xFD,0xFF,0xBF,0xEF,0xF7,0xFF,0xFF,0x7D, 0xFF,0xFF,0xFF,0xFF,0xF8,0x3B,0xFF,0xBF, +0x6F,0xFF,0xFE,0xFF,0xBF,0xFF,0xEB,0x7D, 0xFF,0xEF,0xFB,0xFE,0xFF,0xFF,0xFF,0xFF, +0xFF,0xF2,0x7F,0xFC,0xFF,0x3F,0xDF,0xED, 0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0x5F,0xF7, +0xB5,0xFF,0xEF,0xFF,0xFF,0xFF,0xE0,0x3F, 0x9F,0x9E,0xFF,0xFF,0xEF,0xFF,0xDF,0xFF, +0xBF,0x5F,0xBF,0xCF,0xF3,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0x69,0xAF,0x33,0xFD,0xFF, +0xFB,0xFF,0xFF,0xFF,0xFF,0xFC,0xFF,0x7F, 0xD9,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xF5, +0xA3,0xDF,0x6E,0xDE,0xFF,0xFF,0xBD,0xFF, 0xFF,0xFE,0xFF,0xFF,0xFF,0xFE,0xE7,0xFD, +0xFF,0xFF,0xFF,0xF9,0xEF,0xC6,0xFE,0xB7, 0xAD,0xE5,0xF9,0xFF,0xFF,0xFF,0xCF,0xFF, +0xFF,0xFF,0xCD,0xFB,0x7F,0xFF,0xFF,0xFF, 0xF9,0xF6,0x0F,0xDF,0xEC,0xCF,0x7F,0xFF, +0xFB,0x7F,0xFF,0xFF,0xFF,0xFD,0xFF,0xFE, 0xF9,0xFD,0x7F,0xFF,0x7F,0xFF,0xF9,0x5B, +0xFF,0x73,0xDC,0xFD,0x7B,0xDF,0xFF,0xFF, 0xFF,0x7B,0xFF,0xFF,0xF7,0x53,0xD6,0xFF, +0xFF,0xFF,0xFF,0xD8,0x9F,0xFE,0xFF,0xEF, 0x7F,0xEE,0xFF,0xFF,0xFF,0xFB,0xED,0xED, +0xFD,0xFF,0xFE,0xFF,0xFF,0xFB,0x7F,0xFF, 0xE2,0x7F,0xFF,0x6F,0xD8,0x57,0xF7,0xFF, +0xFF,0xFF,0xDF,0xFF,0xE8,0xFF,0xFF,0xFD, 0xFF,0xFF,0xFC,0x7F,0xFF,0xE4,0xFF,0xFB, +0xEF,0xFB,0xFE,0xDF,0xB7,0xED,0xFF,0xFE, 0xDF,0x7F,0xFF,0xFE,0x7F,0xB7,0xFF,0xFF, +0xFF,0xFF,0x89,0xFF,0xFF,0xCF,0xF3,0xFE, 0x7F,0xFF,0xEF,0xFF,0xFE,0x7E,0x7F,0xFB, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1, 0xFF,0xEB,0x7A,0xD5,0xBF,0x6F,0xDB,0xBE, +0xFD,0xB7,0xD8,0xF6,0xE5,0xBF,0x6F,0xFB, 0xFE,0xF5,0xBD,0x7E,0x06,0xFF,0xDF,0xF7, +0xFB,0xF6,0xFF,0x3F,0xFF,0xDB,0xFF,0xFF, 0x6F,0xFB,0xF7,0xFF,0xFF,0xFF,0xFB,0xFE, +0xF7,0xAF,0xFF,0xB7,0xED,0xEF,0xF7,0xFE, 0xFF,0xFF,0xDF,0xFF,0xFE,0xFF,0xEF,0xFF, +0xFF,0xFF,0xFF,0xBF,0xF7,0xFC,0x1F,0xEE, 0xFB,0xFE,0xBD,0xFF,0x7F,0x5F,0xD7,0xFD, +0xFB,0x43,0xFF,0xFF,0xFD,0xFF,0x5F,0xFF, 0xF7,0xFF,0xF9,0x3F,0xFF,0xCF,0xF3,0xFD, +0xF7,0x7E,0xEF,0xA7,0xF9,0xFE,0x8F,0xA7, 0xE9,0xF3,0x7E,0x9F,0xFB,0xF8,0xFF,0xFF, +0x3F,0xFD,0x7F,0x5F,0xDF,0xFD,0xFF,0xFF, 0x5F,0xFF,0xFD,0x5F,0xFF,0xFF,0x7F,0xFD, +0x7F,0xFD,0x9F,0xFF,0xE0,0xFF,0xFA,0xF8, 0xBE,0x6F,0x9F,0xE6,0xF8,0xBE,0x3F,0x9A, +0xF9,0xBE,0x6F,0x9F,0xE2,0xF9,0xFE,0x6F, 0x9F,0xF9,0xFF,0xF5,0xFD,0x7F,0xCF,0xDF, +0xFD,0xFD,0x7F,0xFF,0xF5,0xFF,0xFF,0xFF, 0xF7,0xF5,0xFD,0x0F,0xDB,0xFF,0xD3,0xFF, +0xEB,0xFA,0xFF,0xFF,0xBF,0xFF,0xFA,0xFF, 0xFF,0xCB,0xFB,0xFE,0xFF,0xFF,0xEB,0xFA, +0xFE,0xFF,0xFF,0xB7,0xFF,0xFF,0xFF,0xFF, 0xBF,0xFF,0xDF,0xF5,0xFF,0xFF,0xD7,0xFF, +0xFF,0xFF,0xDF,0xD7,0xF5,0xFF,0x7F,0xFE, 0x4F,0xFF,0xFD,0xFF,0x7F,0x7F,0xFF,0xAD, +0xEB,0xFB,0xFF,0xAD,0xFF,0xFF,0xFF,0xFF, 0xAF,0xEB,0xFB,0xFF,0xFC,0x0D,0xFF,0xFF, +0xDF,0xD2,0xFD,0xFF,0xFF,0xFD,0xF6,0xFF, 0xFF,0x7F,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFB,0x3F,0x7D,0xEB,0x32,0xFE,0xBF, 0x2F,0xEB,0xFA,0xAE,0xBD,0xE0,0xFA,0x7E, +0xBF,0xAD,0xEB,0xFA,0xFE,0xBF,0xF5,0x7F, 0xFF,0xDE,0xFE,0xE3,0xFB,0xFF,0xFF,0xFF, +0xDF,0xEF,0x4F,0xDF,0xFF,0x7F,0xDF,0xFF, 0xF7,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xEF, +0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xDF, 0xED,0xFB,0xDF,0xFF,0xBF,0xFF,0xFF,0xFF, +0x81,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF, 0xFF,0xFF,0xFE,0xDD,0xFE,0xEF,0xFD,0xFF, +0xFF,0xFB,0xFE,0xF7,0xFF,0x93,0xFD,0xFB, 0x7E,0xFF,0xFE,0x87,0xE9,0xFF,0x7F,0xB3, +0x9F,0xFE,0xFE,0xFF,0xAF,0xFD,0xFE,0x7E, 0x3F,0xFE,0x67,0xFF,0xFF,0xF7,0xFF,0xFF, +0xFC,0xF7,0xDF,0xFD,0xFF,0x7F,0xFF,0xFF, 0x7F,0x6D,0xFF,0xFF,0xFE,0xFF,0xFF,0x2F, +0xFF,0xBF,0xFF,0xFF,0xEE,0xFF,0xBE,0xFF, 0xFF,0xFE,0xFF,0xEF,0xFF,0xFF,0xFE,0xFF, +0xEF,0xFF,0xFF,0xFA,0x5F,0xFF,0xFF,0xFB, 0xFF,0xFF,0xEF,0xFF,0xFB,0xFE,0xFD,0xFF, +0xFE,0xFF,0xFB,0xFF,0xFF,0xFF,0x7F,0xFF, 0xFE,0xBF,0xDF,0xFF,0xFB,0xFF,0xFF,0xF7, +0xFC,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0x7F,0xFF, +0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, 0xF3,0xFF,0xFF,0xFF,0xEF,0xFB,0xFF,0xFF, +0xFF,0xDF,0xE2,0xFF,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFB,0xE7,0xFF,0xFD, +0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xED, 0xEF,0xFD,0xFF,0xFF,0xDF,0xD7,0xF5,0xFD, +0x7F,0x5D,0xFD,0xFF,0x7F,0xDF,0x97,0xF4, 0xFD,0x7B,0x5F,0xFF,0xC9,0xFF,0xFB,0xFE, +0xFF,0xBF,0xFF,0x5F,0xFF,0xFF,0xF7,0xFF, 0xEF,0xFD,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xF7,0xFF,0xD7,0xFD,0x7D,0x7F,0xFF, 0xFF,0xFF,0xFF,0xEF,0xDF,0xF7,0xFD,0xFF, +0xBB,0xFF,0xFF,0x7F,0xFF,0xFE,0xE3,0xFF, 0xF9,0xFE,0x7F,0xBF,0xEF,0xFB,0xFE,0xFF, +0xBF,0xF9,0xFE,0xFF,0x9F,0xEF,0xF9,0xFE, 0xFF,0xBF,0xF3,0xDA,0xFF,0x37,0xCD,0xF3, +0x7C,0xDF,0x37,0xCD,0xF3,0x7F,0x37,0xCD, 0xF3,0x7C,0xDF,0x37,0xCC,0xF3,0x7F,0x5A, +0xBD,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFD, 0xBF,0x6F,0xDE,0xFD,0xBF,0x6F,0xDB,0xF6, +0xFD,0xBF,0x6F,0xFE,0xF1,0x6F,0xEB,0x7A, 0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7,0xAF, +0x7A,0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7, 0xFF,0x7E,0xFF,0xFE,0xCD,0xB3,0x6C,0xDB, +0x36,0xCD,0xB3,0x6C,0xDE,0xCD,0xB3,0x6C, 0xDB,0x36,0xCD,0xB3,0x6C,0xDF,0xC9,0xBF, +0xF7,0xBD,0xEF,0x7A,0x9E,0xA7,0xA9,0xEA, 0x7A,0xB7,0xBD,0xEA,0x7B,0xDE,0xA7,0xBD, +0xCA,0x72,0x8D,0x91,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFE,0xF7,0xEF,0xFB, +0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFE, 0x87,0xFF,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6, +0xFD,0xBF,0x6F,0xF6,0xFD,0xBF,0x6F,0xDB, 0xF6,0xFD,0xBF,0x6F,0xFE,0x4F,0xFF,0xBF, +0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB,0xEF, 0xBE,0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB, +0xEF,0xFC,0x5F,0xFF,0xFF,0xFF,0x3F,0xCF, 0xF3,0xFC,0xFF,0x3F,0xCF,0xFC,0xFF,0x3F, +0xCF,0xF3,0xFC,0xFF,0x3F,0xCF,0xFD,0x9F, 0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF, +0xEB,0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF, 0xAF,0xEB,0xFF,0xE1,0x6F,0xFD,0xFF,0x7F, +0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFD,0xFF, 0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF, +0x7A,0xBF,0xFB,0xFE,0xDF,0xB7,0xED,0xFB, 0x7E,0xDF,0xB7,0xFB,0x7E,0xDF,0xB7,0xED, +0xFB,0x7E,0xDF,0xB7,0xFF,0xC9,0xFF,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, +0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEE, 0xFB,0xFE,0xBB,0xFF,0xFE,0xFF,0xBF,0xEF, +0xFB,0xFE,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0x3F,0xCF,0xFF,0xE7, +0xFE,0xFF,0xF5,0xFD,0x77,0x5D,0xD7,0x35, 0xDD,0x77,0xD7,0xF5,0xCD,0x7B,0x5D,0xD7, +0xF5,0xDD,0x77,0xFE,0x27,0xFF,0xFF,0x8B, 0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9,0xAF, +0x8B,0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9, 0xFE,0x1F,0xFF,0x5F,0xD7,0xF5,0xFD,0x7F, +0x5F,0xD7,0xF5,0xFF,0x5F,0xD7,0xF5,0xFD, 0x7F,0x5F,0xD7,0xF5,0xFF,0xFA,0x3F,0xFE, +0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xEB, 0xEC,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF, +0xEB,0xFF,0xFE,0x7F,0xFD,0x7F,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6, 0xFF,0xFA,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF, +0xF7,0xFC,0xFF,0xDF,0xF7,0xFD,0xFF,0x7F, 0xDF,0xF7,0xFD,0xFF,0xF5,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0x02,0xFF,0xFE,0xBF,0xAB,0xEB,0xFA, 0xBE,0xBF,0x23,0xEB,0xDE,0x1F,0xAF,0xEA, +0xFA,0xFE,0xAF,0xAF,0xEB,0xFD,0x97,0xFF, 0xF3,0xFC,0x7B,0x1F,0xCF,0xF1,0xFC,0x7F, +0x1F,0xF1,0xFC,0x77,0x1F,0xCD,0xF1,0xFC, 0xFF,0x1F,0xFE,0x87,0xFF,0xAF,0xEF,0xFA, +0xFE,0xFF,0xAF,0xEF,0xFA,0xFD,0xBF,0x2B, 0xFB,0x7E,0xBF,0xBF,0xEB,0xFB,0xFB,0xFB, +0xDF,0xFF,0xFB,0xF7,0xFF,0xFF,0x7F,0xF7, 0xF7,0xFF,0xFD,0xDF,0xFE,0xFC,0xDF,0xFF, +0xDF,0xFF,0xFD,0xFF,0xDA,0xBF,0xFF,0xBB, 0xEF,0xFB,0xF9,0xFF,0xBE,0xEF,0xFB,0xFB, +0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xF7,0x7F,0xFD,0xD7,0xFF,0xFF,0x7F, +0xFF,0xFF,0xFF,0xFE,0xF7,0xFF,0xFE,0xFF, 0xF7,0xFF,0xFF,0x7F,0xFF,0xFF,0xEC,0xFF, +0xFF,0xFE,0xDF,0xBF,0xFF,0xFB,0xFE,0xFF, 0xBB,0x68,0xAE,0x1F,0xAE,0xFB,0xFB,0xFF, +0xFF,0xBF,0xFF,0xD5,0xFF,0x7F,0xFF,0xFF, 0xF7,0xFE,0xFE,0xFF,0xBF,0xEF,0x9F,0xFD, +0x7F,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF,0xFF, 0xBB,0xF7,0xBF,0xFF,0xFF,0xFF,0xFF,0xDF, +0xFF,0xBF,0xFB,0xFF,0xFF,0xFF,0xDE,0x3F, 0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0xFF,0xFF, +0xFF,0xFF,0xEF,0xFF,0x7F,0xFB,0xFD,0xFB, 0x7F,0xFF,0xFF,0xFF,0xFF,0xCF,0xF3,0x7C, +0xFF,0x7F,0x8D,0x7F,0xFF,0xFF,0xFF,0xFF, 0xFB,0xFF,0xF7,0xFB,0xFE,0xFD,0xFF,0xFF, +0xFF,0xFF,0xF7,0xFD,0xFF,0x7F,0xFD,0x1F, 0xFD,0xFF,0xFF,0xFF,0xFF,0xBF,0xDF,0xFF, +0xFF,0xFE,0x5C,0xFF,0x6D,0xFF,0x7F,0xAB, 0xE7,0xF1,0xFF,0xFD,0x9F,0xFF,0xFF,0xAD, +0xEB,0x7A,0x3F,0x1F,0xFF,0xFF,0xFE,0xBF, 0xAF,0xF3,0xDE,0xF5,0xFF,0x8F,0xFB,0xDF, +0xE6,0x7F,0xFF,0xDF,0xF3,0xFD,0xFF,0x7E, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xF7,0xF3, +0x7F,0xDF,0xF7,0xEF,0xFF,0xF6,0x3F,0x9F, 0xDF,0xFF,0xFF,0xEE,0xFF,0xFF,0xEF,0xFB, +0xFF,0xFF,0xF9,0xFB,0xFE,0x4F,0xBF,0xEF, 0xBB,0xFF,0x69,0xAF,0xAF,0xFC,0xFF,0x3F, +0xDD,0xFF,0xFC,0xBF,0x8F,0xFF,0xFD,0xF3, 0xBF,0xED,0x9E,0xFC,0xBF,0x6F,0xF5,0xD3, +0xDF,0xFF,0xDB,0xD6,0xF5,0xEF,0xFD,0xFE, 0xFF,0xB9,0xFF,0x1F,0xD2,0xA9,0xAF,0xFF, +0xDB,0xF7,0xBF,0xEF,0x46,0xFF,0xFF,0xAD, 0xEB,0x7A,0xDF,0xEF,0xF7,0xFF,0x7F,0xF7, +0x9F,0xED,0xFF,0x7F,0xFF,0xAD,0xEB,0x7F, 0xF5,0x6F,0xFF,0xFD,0xFB,0xD6,0xF4,0xF7, +0xFB,0xF9,0x7E,0x7F,0xFF,0x5F,0xC2,0xFE, 0xBF,0xFD,0xFB,0x33,0xDF,0xF9,0x5B,0xFF, +0xFF,0xDD,0x67,0x7D,0xCF,0xEF,0xDB,0xEC, 0xFF,0x77,0xDD,0xF7,0xFD,0xFF,0xFF,0xDE, +0xA7,0xBF,0xD4,0x9F,0xFF,0xFF,0xBF,0xEF, 0xFE,0xFF,0xDF,0xEF,0xBB,0xFF,0xFF,0xEF, +0xEB,0xFA,0xFF,0xEF,0xBD,0xFB,0xFF,0xE2, 0x7F,0xFF,0xDF,0xDF,0xF7,0xFD,0xBF,0xBB, +0x73,0xF7,0xFD,0x7F,0xDF,0xDE,0xF7,0xBF, 0xEA,0xDB,0xF6,0xFF,0xD6,0xFF,0xFF,0x66, +0xFF,0xBE,0xFF,0xBF,0x6B,0xD9,0xF6,0xDF, 0xFF,0xFB,0x7E,0x7F,0xB7,0x7E,0xFF,0xFE, +0xFF,0xCD,0xFF,0xFE,0x7F,0xFF,0xFC,0xFD, 0x3F,0xFB,0xFB,0xF7,0xFF,0xFF,0xFB,0xF6, +0x7D,0xFE,0x7F,0xFF,0xFC,0xFF,0xB9,0xFF, 0xF9,0xFA,0xFE,0xBF,0xAF,0x5B,0xD6,0xED, +0xAD,0x7B,0xF6,0xF9,0xBF,0xEF,0xF8,0xFA, 0xFE,0xBF,0xFE,0xE6,0xFF,0xFF,0xF7,0xFD, +0xFF,0x7F,0xBF,0xEF,0xF3,0xFF,0xFF,0x6F, 0xF7,0xFE,0xFF,0xFF,0xF7,0xFD,0xFE,0xF7, +0xEF,0xFF,0xFB,0xEF,0xFB,0x7E,0xDE,0xFE, 0xFF,0xBF,0xFF,0xFE,0xFF,0xFF,0xFB,0xFF, +0xFF,0xEF,0xFB,0x6F,0xFC,0x1F,0xFE,0xE7, 0xFF,0xFF,0xFF,0xEF,0xFF,0xD3,0xB4,0xBB, +0xFF,0xFF,0xFD,0xBF,0x6F,0xE3,0xFE,0xFF, 0xBF,0xFC,0xBF,0xF7,0xCF,0xF7,0xFD,0xFF, +0x2F,0xDF,0xAB,0xEA,0xFF,0xDF,0xE7,0xEA, 0x9A,0xAF,0xEF,0xFB,0xFE,0xFF,0xF5,0x3F, +0xFD,0x7E,0xFF,0xD7,0xF5,0xFB,0xFF,0xFD, 0xF7,0xFF,0x7F,0xFE,0xF7,0xFD,0xFF,0xD7, +0xFF,0xD7,0x7F,0xEE,0x7F,0xFA,0x79,0xFE, 0x2F,0x8B,0xE6,0xF9,0xFE,0x3F,0x9E,0xF9, +0xBE,0x2F,0x0B,0xE7,0xF9,0xFE,0x2F,0x9F, 0xFD,0xFF,0xFE,0x7D,0x7F,0x5F,0xD7,0xFF, +0xFF,0x7F,0xFF,0xFD,0xFF,0x7F,0x5F,0x97, 0xFF,0xFD,0x7F,0x5F,0xFF,0xE3,0xFF,0xFF, +0xFA,0xFE,0xBF,0xAF,0xFB,0xFB,0xFF,0xFF, 0xCF,0xEB,0xFE,0xBF,0xAF,0xFF,0xFA,0xFE, +0xBF,0xFF,0x87,0xFF,0xFF,0xF5,0xFF,0xFF, 0xFF,0xFF,0xFD,0xFF,0x7F,0xFF,0xFF,0xFF, +0xFB,0xFF,0xFF,0xF5,0xFF,0xFF,0xFE,0x0F, 0xFF,0xFD,0xEB,0xFF,0xFF,0xF7,0xFF,0xEF, +0x7B,0xDF,0xFE,0xFF,0xFF,0xDF,0xF7,0xFD, 0xEB,0x7F,0xDF,0xFF,0x5F,0xFF,0xFF,0xFF, +0xFF,0xFD,0xBF,0xFF,0x7E,0xFA,0xBF,0xC7, 0xDB,0xF7,0xBD,0x3F,0xFB,0xFF,0xF6,0xFF, +0xFA,0xAF,0xFF,0xEB,0xFA,0xFE,0x3F,0x2F, 0xEA,0xFA,0x3E,0xAD,0xC9,0xBA,0xF6,0xAD, +0xAF,0xEB,0xFA,0xF6,0xBF,0xFE,0x7F,0xFF, 0xFF,0xFD,0xFF,0xF1,0x7F,0x3F,0xCF,0xF1, +0xEF,0xFF,0x7F,0xFF,0xBC,0xDF,0xDF,0xF7, 0xDD,0xFF,0xE0,0x7F,0xFF,0xFF,0xFE,0xFF, +0xFA,0xEC,0xBB,0x7F,0x5F,0xFF,0xFB,0xEC, 0xFF,0xEF,0xB7,0xFF,0xF7,0xFF,0xFF,0xB5, +0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xEE,0xDF, 0x5F,0xDF,0xDE,0xFF,0xAE,0xE7,0x77,0xFF, +0xFF,0xDF,0xF7,0xFF,0xE3,0xFF,0xFA,0xBB, 0xFE,0xFF,0xAF,0xFD,0xFB,0xFE,0xBF,0xAB, +0xF9,0xFE,0xFF,0xBF,0x7F,0xBF,0xFE,0xBD, 0xFE,0xD7,0xFF,0x9F,0xFD,0xFF,0xBE,0xEF, +0xFF,0xEE,0xFD,0xBB,0x5B,0xEF,0xFF,0x7F, 0xEF,0xFF,0xEF,0xFF,0x7F,0xFF,0x4F,0xFF, +0xEF,0xFB,0xBC,0xFC,0xFF,0xFF,0xFF,0xFE, 0xFE,0xFD,0xFA,0xFE,0xFB,0xFF,0xFD,0xF3, +0xFB,0xFF,0xF8,0x5F,0xFF,0xFF,0xD7,0xF5, 0xFD,0xDF,0xEF,0xFF,0xF3,0xDC,0x5F,0xCE, +0xF5,0xBD,0xFF,0xFF,0xD7,0xFF,0xFF,0xF9, 0x3F,0xFF,0xDF,0xF7,0xFF,0xFE,0xFF,0xFD, +0xFF,0xFB,0xFF,0xF7,0xB9,0x7D,0xFE,0xDF, 0xFF,0xFF,0xFF,0xFF,0xF9,0x7F,0xFF,0xFE, +0xFF,0xFF,0x7F,0xFF,0xFE,0xFF,0xFF,0xF7, 0xF6,0xFF,0xBF,0xF1,0xF8,0xFF,0xFF,0xFF, +0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF, 0xFF,0xFF,0xFF,0xFF,0xEF,0xEF,0xFF,0xFF, +0x9B,0xFB,0x7F,0xFF,0xFF,0xFF,0xC1,0xFF, 0xDF,0xFF,0x3F,0x5F,0xD7,0xBF,0xEF,0xBB, +0xDE,0xEE,0xFF,0x7F,0xDF,0xFF,0xFE,0xF5, 0x7F,0xDF,0xFF,0x99,0xFF,0xFF,0xFA,0xFF, +0xBF,0xFD,0xEB,0x7A,0xFF,0xB7,0xFE,0xFE, 0xFF,0xFF,0xEF,0xFF,0xFF,0xFD,0xBF,0xFF, +0x97,0xFF,0xFD,0xF7,0xFF,0x7F,0xF7,0xFF, 0xFF,0xFD,0x5F,0xFE,0xF3,0xF9,0xDF,0xDF, +0xFF,0xFF,0xFC,0xFF,0xFF,0x83,0xFF,0xFF, 0xFE,0xFF,0x9E,0xEC,0xFB,0xEE,0xFF,0x9F, +0xBF,0xEF,0xFF,0xFE,0xED,0x7B,0xFF,0xFF, 0xFF,0xF1,0x5A,0xFF,0xFF,0xFD,0xFF,0x7C, +0x69,0x3B,0xDF,0xFF,0x7F,0x1F,0xDF,0xFF, 0xFD,0xBA,0xFF,0xFF,0xFB,0xFF,0x5B,0xBD, +0xFF,0xFF,0xFF,0xFF,0xD7,0xB6,0xED,0xE9, 0xFF,0xD6,0xBD,0x6F,0x5F,0xFB,0xFF,0xEF, +0xFF,0x5F,0xFE,0xF6,0x6F,0xFF,0xFF,0xFF, 0xFF,0xF7,0xEB,0x7A,0xDF,0xFF,0x9F,0x7F, +0x7F,0xFF,0xB7,0xFF,0xFF,0xFE,0xDF,0xFF, 0x6C,0xFF,0xFB,0xFF,0xBB,0x6F,0xEB,0xFE, +0xCC,0xF7,0xA5,0xFA,0x5C,0xF5,0x75,0xBB, 0xB7,0xDF,0xFE,0x6F,0x5F,0xC5,0xBF,0xFD, +0x7B,0xFE,0xFF,0x95,0xE7,0x29,0xCF,0x4F, 0xF5,0x91,0xEE,0x6B,0xDF,0xEF,0xFD,0x54, +0xF5,0xBD,0xB1,0xFF,0xEF,0xEE,0xFB,0xBE, 0xBF,0xAF,0xFE,0xDE,0xBD,0x6F,0xDA,0xF2, +0xFF,0xAF,0xBE,0xFF,0xFF,0xFD,0x7E,0xA7, 0xFF,0xF7,0xFF,0xBF,0xEF,0x7B,0xF6,0xFD, +0xBD,0x4A,0xF2,0x85,0x85,0xBF,0x5B,0xFE, 0xB5,0xFD,0xFA,0xFF,0x4F,0xFF,0xFE,0xDF, +0xFF,0xED,0xFF,0xBF,0xFF,0xBF,0x7F,0xFE, 0xFF,0xB7,0x6D,0xFF,0xF7,0xBF,0xBF,0xEF, +0xFD,0x1F,0xFF,0xFE,0x7D,0xFF,0x67,0xFF, 0xFF,0xFF,0x3F,0x7F,0xFE,0xBF,0xFF,0xE7, +0xDF,0xE7,0xFF,0xEF,0x6B,0xFC,0x1F,0xFF, 0xBF,0xEF,0xFB,0xFE,0xDE,0xBF,0xAF,0xFA, +0xFF,0xB6,0xEF,0xF9,0xFE,0xFF,0x8F,0xEF, 0xDB,0xEF,0xAB,0x6F,0xFB,0xFE,0xFF,0xFF, +0xEF,0xFD,0xFF,0x7F,0xFF,0xFF,0xDE,0xFF, 0xFF,0xEF,0xFF,0xFF,0xFF,0x3F,0xFF,0x6C, +0xFF,0xBF,0xFB,0xFF,0xFE,0xFF,0xFB,0xFE, 0xDF,0xFF,0xFF,0xEF,0xFF,0xFF,0xBF,0xFF, +0xFF,0xFE,0xFB,0xFF,0xD5,0x7F,0xFF,0xFF, 0xEF,0xFB,0xFF,0xFF,0xBF,0xEF,0x43,0xB5, +0xFD,0x6F,0xCF,0xD6,0xBE,0x3F,0x7F,0xDB, 0xFE,0xC3,0xFF,0xFD,0xFF,0xAF,0xEB,0xFB, +0xFC,0xFF,0x3E,0xEF,0xE8,0xFA,0xBD,0xCD, 0xAA,0xFE,0xFE,0x7D,0xCF,0xFF,0xB7,0xFF, +0xF7,0xFF,0xFF,0xFF,0xFD,0xFF,0x75,0xCD, 0x52,0xD7,0xFD,0xFB,0xF7,0xDD,0xFB,0xEF, +0xEB,0xFF,0xFF,0x4F,0xFF,0xBF,0x9F,0xE7, 0xF9,0xFC,0x7F,0x8B,0xC3,0xF9,0xAF,0x8F, +0xE7,0xE9,0xBE,0x7F,0x9F,0xE6,0xF9,0xFC, 0x5F,0xFF,0xFF,0xF7,0xFD,0xFF,0x7A,0x5F, +0xD7,0xED,0xFF,0xFF,0xD7,0xFF,0xDD,0x7F, 0xE7,0xFF,0xFC,0xFF,0xFC,0x3F,0xFF,0xFF, +0xFF,0xFB,0xFF,0xFE,0xBF,0xAF,0xFF,0xFD, 0xFF,0xEF,0xFF,0xEB,0xFF,0xFF,0xFF,0xFF, +0xFF,0xF7,0x7F,0xFF,0x7F,0xDF,0xFF,0xFD, 0xFD,0x7F,0xFE,0xF7,0xFD,0x7F,0xDF,0xFF, +0xFD,0xFF,0xFF,0xDF,0xFB,0xFF,0xEE,0xFF, 0xFB,0xFF,0xF7,0xFD,0xFF,0x7A,0xDF,0xF5, +0xFD,0xFA,0xDF,0xF7,0xFC,0xFF,0x7F,0xDF, 0xBF,0xED,0xFF,0xC9,0xFF,0xDF,0xFF,0xBF, +0x2F,0xFB,0xFF,0xBC,0xAD,0xFF,0xF7,0xFF, 0xFF,0xEF,0xD3,0xFF,0x7D,0xBF,0x6F,0xFF, +0xFA,0xFF,0xFE,0xBF,0xAE,0xEA,0xFA,0xBE, 0xAD,0xA5,0xEB,0xCE,0xBF,0xA7,0xEB,0x5A, +0xDE,0xBD,0xAF,0x6B,0xFD,0x57,0xFF,0xFF, 0xF4,0x7F,0x1F,0x7F,0xFD,0xFF,0x7F,0x36, +0xF0,0xDF,0x79,0xFF,0xFF,0xFF,0xF7,0xFD, 0xBF,0xFF,0x87,0xFF,0xFB,0xF3,0xFC,0xFF, +0xFF,0xFF,0xFF,0x7E,0xFF,0xBF,0xDF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xF8,0x9F, +0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFD, 0xF7,0xFC,0xBD,0xFF,0xFE,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFB,0xF9,0xBF,0xFF,0xFF,0xEB, 0xE2,0xFE,0xFF,0xBF,0xEF,0xA9,0xBA,0x2F, +0xEB,0xF9,0xFE,0x77,0xDF,0xF7,0xFF,0xFF, 0xF9,0x7F,0xFF,0xFF,0x7F,0xEF,0xD7,0xFF, +0xFD,0xFF,0xFB,0xF5,0xFF,0xBF,0x6F,0xDF, 0xFF,0xFF,0xFD,0xFF,0xFF,0xF0,0xFF,0xFF, +0xFF,0x3F,0xCF,0xFF,0xBA,0xEE,0x9B,0xBF, 0xEE,0xD7,0xFE,0xCD,0xEF,0xFF,0xDF,0xBF, +0xFF,0xFF,0xC5,0xFF,0xFF,0xFD,0x7F,0x4F, 0xFD,0xF6,0xD9,0xFF,0x4F,0xD6,0xFD,0xBF, +0x6E,0xFF,0xFF,0xF4,0x7F,0xFF,0x7F,0x8B, 0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xF9,0xFE, +0x37,0xFF,0xD9,0xFB,0xF5,0xAF,0xFD,0xFF, 0xFF,0xFB,0xFF,0xFF,0x07,0xFF,0xFF,0xFF, +0xFB,0xF7,0xFF,0xFD,0xFF,0x7C,0xFA,0x7E, 0x4F,0xFC,0xDF,0x1D,0xC7,0xFF,0xFF,0xFF, +0xFF,0xAE,0xFF,0xFF,0xFF,0xFF,0xFD,0xFB, 0xFF,0xFF,0xFE,0xFE,0xFC,0xFF,0x7F,0x7F, +0xBF,0xEF,0xFE,0xFF,0xFF,0xFF,0x5F,0xFD, 0xFF,0xFF,0xFF,0xFD,0x6F,0x5A,0xD7,0x7B, +0xBE,0x5F,0xFE,0x39,0xFF,0xF7,0xFF,0xF7, 0xFD,0xFE,0xAA,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFE,0xFE,0xAB,0xAF,0xFD,0xFE,0xBF,0xFF, 0xF7,0xFF,0x7F,0xFE,0x8F,0xE3,0xFB,0xEE, +0x7F,0xFF,0xFF,0xFF,0xFF,0xEB,0xFB,0xFF, 0xFD,0xBF,0xEF,0xDF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFB,0xE4,0x3F,0xFF,0xDF, 0xFF,0xFF,0xFF,0xFF,0xF3,0xEF,0xBB,0xFB, +0xBF,0xEF,0xBB,0xFF,0xD7,0xBF,0xFF,0xFF, 0xFF,0x29,0xAF,0xF7,0xFF,0xFF,0xFB,0xFF, +0xFB,0xE6,0xFF,0x0F,0xFB,0x3F,0xDF,0x0F, 0xFF,0xAF,0xFF,0xFF,0xFF,0xF5,0xC3,0xDF, +0x5F,0xFF,0xFF,0xFF,0xFE,0x6B,0xCA,0xBE, 0xBC,0xFF,0x9F,0xF2,0xBF,0xFF,0xFE,0xFA, +0xFF,0xFF,0xEF,0x16,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFC,0xDF,0x97,0xFD,0x79,0xFF,0x37, +0xE7,0x7F,0xFF,0xFF,0xB5,0xFF,0xFF,0xF6, 0x2F,0xFF,0xFD,0xFB,0xFE,0xFF,0xFF,0xFD, +0x5F,0x57,0x5F,0xFF,0xDB,0x52,0xDF,0xFF, 0xFD,0xBF,0xFF,0xFF,0xFC,0xDB,0xFF,0x7B, +0xB5,0xFD,0x7F,0xFF,0x71,0x9C,0x6E,0xFF, 0xF6,0x35,0xA5,0x9B,0xFF,0xFF,0xFD,0xFF, +0xFF,0xDB,0x9E,0x7F,0xFE,0xEF,0xFB,0xFF, 0xFF,0xBD,0xEF,0xFF,0xDE,0xB7,0xF9,0x4B, +0xFF,0xF5,0xEF,0xFF,0xFF,0xFF,0xE8,0x7E, 0xFF,0xEA,0xDF,0xF7,0xFF,0xFD,0x69,0x5B, +0xFC,0x9F,0xEF,0x78,0xD6,0xFF,0xEB,0xEF, 0xFF,0xFF,0xFF,0xE8,0xFF,0xFF,0xED,0xFF, +0xFF,0xFF,0xFF,0xE3,0xF9,0xF6,0xBF,0xFF, 0xFF,0xFE,0xDF,0xFF,0x7F,0xFF,0xFF,0xFF, +0xD1,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF, 0xE7,0xF9,0xFF,0xBF,0x7F,0xD9,0xFF,0xFD, +0xFE,0x7F,0xFF,0xFE,0xFF,0xF9,0xFF,0xFB, 0xD6,0xDF,0xBF,0xEF,0x5B,0xD6,0xFF,0xBF, +0xFB,0xF6,0xFF,0xBF,0xEF,0xF8,0xF6,0xDD, 0xBE,0xFE,0x16,0xFF,0xBF,0xEF,0xFF,0xFE, +0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0x6F,0xFB, 0xFF,0xFF,0xFF,0x6F,0xF3,0xFF,0xF7,0xEF, +0xFB,0xFF,0xBF,0xFF,0xEF,0xFE,0xFF,0xBF, 0xFF,0xFF,0xFF,0xBE,0xBF,0xFF,0xEF,0xFF, +0x7F,0xEF,0xFF,0xFD,0x17,0xFB,0x7B,0xFF, 0xFF,0xFD,0x7F,0xDB,0xF6,0xF4,0x7F,0xFA, +0xFE,0xF5,0xBF,0xEB,0xE3,0xF7,0xFF,0xFF, 0xE9,0xBF,0xFF,0xAF,0xF7,0xFD,0xF3,0x7E, +0x8F,0xA3,0xEA,0xFF,0xCB,0xF3,0xEE,0xFF, 0xBF,0xEF,0xF7,0xF9,0xFF,0xFE,0x7F,0xFF, +0xFF,0xFF,0xFF,0xF5,0xFB,0xF6,0xFF,0xF5, 0x2F,0xFE,0xFB,0xD7,0xBF,0xFF,0xBE,0xDF, +0x9F,0xFF,0xF0,0xFF,0xFF,0xF9,0xFE,0x7F, 0x8F,0xA3,0xF8,0xFE,0x6F,0x9F,0xF9,0xF6, +0x2F,0x9F,0xE7,0xF9,0xFE,0x2F,0x9F,0xE1, 0xFF,0xFF,0xFF,0x7F,0xDF,0xF7,0xF5,0xFD, +0x7F,0x7F,0xF5,0xFF,0x9F,0x5F,0xFB,0xFE, 0xFF,0x7F,0xFF,0xFF,0xCB,0xFF,0xFF,0xFB, +0xFE,0xFF,0xBF,0xAF,0xFB,0xFE,0xFF,0xDF, 0xFE,0xFE,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF, +0xFF,0xC7,0xFF,0xFF,0xFD,0xFF,0x7F,0xDD, 0xF7,0xFD,0xFF,0xFF,0xD7,0xFF,0xFD,0x7F, +0xFF,0xFB,0xFD,0xFF,0xFF,0xFE,0xEF,0x7F, 0xFD,0xEF,0xFB,0xFE,0xFB,0xFD,0xFF,0x7F, +0xDF,0xFD,0xFF,0x7A,0xDF,0xF7,0xFD,0xFF, 0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xD3,0xF7, +0xFF,0xFF,0x6F,0xDB,0xFF,0xFF,0xEF,0xCB, 0xF4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, +0x29,0xFF,0xE8,0xDA,0x76,0x9F,0xAF,0x6A, 0xDA,0xFE,0x35,0xEB,0xDA,0xD6,0xBF,0xAB, +0xEB,0x7A,0xDE,0xBF,0xD7,0x7F,0xFF,0xFE, 0xFF,0xBF,0xEF,0xFD,0xDF,0x77,0xBF,0xFD, +0x37,0xEF,0xFF,0xEF,0xFF,0x3F,0xFF,0xFF, 0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xF7,0x7E, +0xDF,0xFF,0xFF,0xFF,0xFA,0xB7,0x7F,0xFF, 0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x89,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x9F,0xFB,0xFF,0xFF,0xFF,0xE7,0xFF, +0xFF,0xFF,0xFF,0xAA,0xFF,0xAB,0xFB,0xFA, 0xEF,0xBF,0xFF,0xDF,0xFA,0x7B,0xB9,0xFE, +0xFE,0xFF,0xFD,0xFF,0xF7,0xFE,0x3F,0xFF, 0xB7,0xFF,0xF7,0xEE,0xFF,0x7F,0xEF,0xFF, +0xFF,0x7F,0xFF,0x1F,0xFB,0xFF,0xBF,0xFB, 0xFE,0xFF,0xBD,0xFF,0xFF,0x2F,0xFF,0xBF, +0xFF,0x7F,0xDF,0xFA,0xFF,0xFF,0xFC,0xEE, 0xF5,0xF3,0xBE,0xFB,0x0F,0xEF,0xF3,0xBE, +0xEF,0xFC,0x5F,0xFF,0x5A,0xFF,0xF7,0xDF, 0xFF,0xFF,0xFE,0xD5,0xFC,0x5F,0xFB,0xF2, +0xFF,0xFF,0x2F,0xBB,0xF3,0xFF,0xFF,0xBF, 0xFF,0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, +0xBF,0xFF,0xFF,0xFD,0x7B,0xFF,0xDF,0xB9, 0xFF,0xFB,0xFF,0xD8,0x7F,0xFF,0xFF,0xFF, +0xFB,0xFF,0xFC,0x7F,0x1F,0xBF,0xE0,0xDF, 0xF7,0xEF,0xFF,0xFD,0x7F,0xFE,0xDF,0xFF, +0xE0,0xFF,0xFF,0xFD,0xEF,0xFB,0xFF,0xFE, 0xF7,0xDF,0xFF,0xEB,0x5F,0xFF,0xF7,0xFF, +0xFF,0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0xFD, 0xFF,0xFF,0xFF,0xF7,0xFD,0xFF,0x3B,0xDC, +0xFD,0x6D,0x7B,0x5F,0x57,0xF5,0xFD,0x7F, 0x5F,0xFF,0xB1,0xFF,0xEB,0xFF,0xFF,0xFF, +0xFB,0xFB,0xFE,0xFF,0xBF,0xFB,0xBE,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFF,0xAF,0xFE,0xF7, +0xDF,0xDF,0xFF,0xFF,0xFF,0x7F,0xCF,0xF3, 0xF8,0xFF,0xD7,0xFB,0xFF,0x5F,0xBF,0xF7, +0xFB,0xFF,0x7F,0xFE,0x23,0xFF,0xFF,0xFE, 0x7F,0xF3,0xFF,0xFB,0xFE,0xFF,0xFF,0xF3, +0xFF,0xFF,0xF5,0xF9,0xFF,0x3F,0xFF,0xFF, 0xF0,0x9A,0xFF,0xBE,0x7F,0xFF,0xFC,0xF9, +0xFF,0xFD,0xAF,0xEB,0xFE,0xBF,0xFF,0xCF, 0xF3,0xFE,0x7F,0xFF,0xFF,0x5B,0xBD,0xFF, +0xBC,0xEB,0xFF,0xD7,0xD4,0xAF,0xAF,0xFD, 0xFF,0xCF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, +0xFD,0xFE,0xFF,0x6F,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFD,0x7F,0x5E,0xFD,0xBF,0xDB,0xF6, +0xFD,0xBF,0x6F,0xFB,0xEE,0xFD,0xFF,0x7A, 0xFF,0xFA,0xFB,0xFF,0x3F,0xFB,0xB7,0x5F, +0xD6,0xF7,0x1F,0x71,0xDC,0x77,0x1D,0xC7, 0x31,0xDC,0x77,0xDF,0xF9,0xBF,0xF5,0x5B, +0xF4,0xD7,0x9D,0xAE,0xFF,0xBF,0xFD,0xBF, 0xDB,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFE, +0x3D,0x81,0xFF,0xEB,0xFE,0xFE,0xFE,0xFF, 0xEB,0x7A,0xDF,0x7D,0x77,0x7D,0xF5,0x79, +0xDF,0x57,0xDD,0xF5,0x7D,0x7E,0xE6,0xFF, 0xD6,0x3F,0xBF,0x7F,0xFF,0xD4,0xF5,0x3F, +0xBF,0xFB,0xBE,0xEF,0xB3,0xEE,0xFB,0x9E, 0xEF,0xBB,0xFE,0x8B,0xFF,0xFE,0xDF,0xB7, +0xED,0xFF,0xF7,0xFD,0xFE,0xFF,0xEF,0xBB, 0xEE,0xFF,0xBE,0xEF,0xBB,0xEE,0xEB,0xFC, +0x1F,0xFF,0xFF,0xFD,0xFF,0xE7,0xFF,0xF7, 0xFD,0xFF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB, +0xFE,0xFF,0xBF,0xEB,0xFA,0x1F,0xFF,0xB7, 0xEF,0x5B,0xFE,0xFF,0xAF,0xEB,0xDD,0xE7, +0xDE,0x77,0x9D,0xE7,0x79,0xDE,0x77,0x9D, 0xBF,0xE6,0x6F,0xFF,0xFE,0xFF,0xBF,0xEF, +0xFB,0xFE,0xFD,0xBF,0x6F,0xF6,0xFD,0xBF, 0x6F,0xDB,0xF6,0xFD,0xBF,0xFF,0x7E,0xFF, +0xFF,0xFB,0xFE,0xFE,0xFF,0xEF,0xFB,0xFD, 0xEF,0x7E,0xF7,0xBD,0xEF,0x7B,0xDE,0xF7, +0xBD,0xEF,0xFF,0xD5,0xFF,0xBF,0xFF,0xEF, 0xFE,0xFF,0xFC,0x3F,0x0F,0xE7,0xFE,0x7F, +0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFE, 0xF3,0xFF,0xFE,0xDF,0xAD,0xDF,0x67,0xEE, +0xFB,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFE,0xFF,0xBF,0xEF,0xFF,0x23,0xFF,0xFF, +0xFF,0xFF,0x7F,0xFF,0xF3,0xBC,0xDB,0xFE, 0xFB,0xFF,0xFB,0xBE,0xF7,0xFB,0xFF,0x7F, +0xDF,0xFF,0xCF,0xFB,0xFF,0x9F,0xE3,0xF9, 0xBE,0x3F,0x8F,0xE7,0x79,0xFF,0x9D,0xE7, +0xF9,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x5F, 0xFF,0xCF,0xF7,0xFF,0xFF,0xFF,0xDF,0xF7, +0xFE,0x7F,0xE7,0xF9,0xFE,0x7F,0xFF,0xFF, 0xFB,0xFE,0xFF,0xFF,0xBF,0xFF,0xBF,0xBF, +0xFF,0xFE,0xFF,0xBF,0xEF,0xFF,0xFD,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFD,0xFF, +0xFF,0x3F,0xFF,0xBF,0xFF,0xF7,0xFF,0xFF, 0x7F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0xEF,0xFF, 0x5F,0xF7,0xBF,0xF9,0xFE,0xDF,0xB7,0xFD, +0xFF,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0xDD,0xFF,0xF2,0xFF,0xBF,0xFF, +0xFF,0xBF,0xFF,0xFF,0x2F,0xF2,0xFF,0xBF, 0x2F,0x7B,0xD2,0xF7,0xBF,0x2F,0xFF,0xBB, +0xFF,0xEE,0x8F,0xAF,0xEB,0xFA,0xFE,0x3F, 0xA7,0x69,0xCE,0x8F,0xA4,0xEA,0xFA,0xEE, +0xB7,0xAE,0xEB,0xFD,0xC7,0xFF,0xF7,0xF7, 0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3E,0xF3, +0x74,0xFF,0x3F,0x4F,0xFF,0xE7,0xFF,0x3F, 0xFE,0xA7,0xFF,0xFF,0xDF,0xF7,0xB7,0xFF, +0xF7,0xFF,0xBA,0xEF,0x37,0xEB,0xFB,0xFE, 0xBF,0xFB,0xFE,0xF3,0xFF,0xF9,0xDF,0xFF, +0xBF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, 0xFD,0xDF,0xFF,0xFD,0xFF,0xFF,0xFB,0xFE, +0xFD,0xFF,0xFB,0xBF,0xFE,0x3F,0xED,0xFF, 0xDF,0xBE,0x3D,0xA7,0xFB,0xFA,0x3F,0xE6, +0xE1,0xFE,0xFE,0x3F,0xEF,0xE3,0xDF,0xF5, 0x7F,0xFE,0xFF,0x7E,0xFF,0xFF,0xFF,0xFF, +0xEF,0x6F,0xF6,0xFF,0x7D,0xEF,0xD7,0xDE, 0xFF,0x7D,0xEF,0xFF,0xF2,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0x7B,0xDE,0xFB,0xE6,0xEE, 0xEF,0x37,0x6E,0xF3,0x7E,0xEB,0x37,0xEF, +0xFF,0xC1,0xFF,0xFE,0xFF,0xF7,0xEF,0xFF, 0xFF,0xFF,0xBF,0x3F,0xD2,0xDF,0xBF,0x2F, +0x7B,0xE2,0xFF,0xFE,0x3B,0xBD,0xDB,0xFF, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFE, +0xFF,0xFB,0xFF,0xFF,0xBF,0xFF,0xFB,0xDF, 0xFF,0xBF,0xFF,0xB7,0xFF,0xFF,0xBF,0xEF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF, 0x7F,0xFF,0x1F,0xEF,0xF1,0xFD,0xFF,0xF6, +0xAF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF, 0xFF,0xFF,0xFE,0x9F,0xFF,0xFF,0xFF,0x77, +0xEF,0xF7,0xFB,0xFF,0xFE,0x5F,0xFF,0xFF, 0xBF,0xCF,0xFB,0xF7,0xDD,0xF7,0xF5,0xFF, +0x5F,0xD5,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5, 0xFF,0xFB,0x0F,0xFF,0xFF,0xA9,0xEA,0x7A, +0xFF,0xAF,0x8F,0xFE,0xDF,0xAF,0xEF,0xFB, 0xFE,0xFF,0xBF,0xEF,0xFB,0xDF,0xE5,0x5F, +0xFF,0xFF,0xFF,0xFF,0xFF,0xBD,0x57,0xFF, 0xFF,0x6F,0x77,0xBF,0xF7,0xFB,0xFF,0x7F, +0xBF,0xF7,0xFF,0xFC,0xBF,0xFF,0x9F,0xFF, 0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF,0x1F, +0xCF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0xFB, 0x65,0xAF,0xF3,0x7C,0xFF,0x3F,0xDF,0xFF, +0xFD,0xE9,0xFE,0x7F,0xE7,0xFF,0xFE,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFD,0xE3,0xDF,0xFB, +0xDB,0xF6,0xFD,0xEF,0x5B,0xFB,0xFF,0xDF, 0xFC,0xFF,0x3F,0xDF,0xF3,0xFD,0xFF,0x7F, +0xDF,0xEF,0x66,0xFF,0xDF,0xAD,0xEB,0x7A, 0xDE,0xF7,0xF7,0xE7,0xD9,0xFD,0x9F,0x67, +0xD9,0xF6,0x7D,0x9F,0xE7,0xDF,0xF5,0x47, 0xFD,0x65,0x5B,0xD6,0xF4,0xFE,0xFF,0xEF, +0xFF,0x6D,0xF6,0xDD,0xB7,0x6D,0xDB,0x76, 0xDC,0xB7,0x7D,0xFA,0x9B,0xF6,0x6D,0x9D, +0x67,0x59,0xDF,0xF7,0xDD,0xFF,0xEB,0xFE, 0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xE3, +0xD1,0x9F,0xFF,0xBD,0xBF,0xEF,0xFE,0xF7, 0xBF,0xBF,0xF7,0xD7,0x7F,0xDD,0xF7,0x9D, +0xDF,0x7F,0xDF,0xF7,0xFF,0xE0,0x7F,0xFD, 0xC1,0xDF,0xF7,0xFD,0xC7,0x7F,0x7F,0xFB, +0xFF,0xBB,0xEC,0xFB,0x3E,0xFF,0xBF,0xEC, 0xFB,0xFF,0xD8,0x7F,0xBF,0x6C,0xFF,0xBE, +0xFF,0xBF,0xED,0xFF,0xEF,0xFE,0xFB,0xBF, 0xEF,0xFB,0xFE,0xFF,0xBF,0xEE,0xFF,0xC5, +0xFF,0xAF,0x6F,0xFF,0xFC,0xFD,0x3F,0xE7, 0xFF,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF, +0xEF,0xFB,0xFE,0xBF,0x89,0xFE,0xFA,0xBA, 0xFE,0xBF,0xAF,0xFB,0xF6,0xF5,0xD9,0x7D, +0x97,0x65,0xD9,0x74,0x5D,0x97,0x65,0xD3, 0xFE,0xD6,0xFF,0xBF,0xF7,0xFD,0xFF,0x7F, +0xBF,0xCF,0xFB,0xFE,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFF,0xF6,0x8F,0xFB, +0xFF,0xEF,0xFB,0x7E,0xDB,0xFE,0xFF,0xBE, 0xEF,0xEE,0xFB,0xBE,0xEF,0xBB,0xEE,0xFB, +0xBE,0xFF,0xFF,0xDF,0xFF,0x43,0xFF,0xFF, 0xFB,0xEF,0x5F,0xB7,0xFE,0x7F,0xE7,0xF9, +0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xF9, 0xBF,0xFE,0xAF,0x77,0xFD,0xFF,0x2F,0xAF, +0xA7,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0xF1,0x7F,0xEF,0xDF, +0xFF,0x97,0xF5,0xEF,0xFF,0xDF,0xFF,0xFF, 0xBF,0xFF,0xBF,0xFF,0xFF,0xFE,0xFF,0xFF, +0xFF,0xE0,0xFF,0xFF,0xF9,0xFE,0x2F,0x8B, 0xE3,0xF8,0xBE,0x77,0x9F,0xF9,0xDA,0x77, +0x9D,0xE7,0x79,0xDE,0x77,0x9F,0xDD,0xFF, 0xFD,0xFD,0x7F,0x5F,0xD7,0xFD,0xFF,0x7F, +0xE7,0xFE,0x7F,0x97,0xE7,0xFB,0xFE,0xFF, 0xBF,0xEF,0xFF,0xAB,0xFF,0xEF,0xFA,0xFE, +0xBF,0xAF,0xFF,0xFA,0xFF,0xFF,0xDF,0xFF, 0xFB,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF, +0x67,0xFF,0xF7,0xF5,0xFF,0xFF,0xFF,0xDF, 0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xBD, 0xEB,0xFF,0xFF,0xF7,0xAD,0xEB,0xFF,0xDF, +0xFD,0xFF,0x3F,0xDF,0xF7,0xFD,0xFF,0x7F, 0xDF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0xFD, +0xBF,0xFF,0xCB,0xF4,0xFF,0x7F,0xD3,0xF7, 0xFD,0x3F,0x7F,0xD3,0xF7,0xFF,0xFC,0x3F, +0xFF,0xEA,0xFA,0xBE,0xAF,0xAB,0xEB,0xBA, 0xF4,0x95,0x6B,0x52,0xD4,0xAD,0x2F,0x4A, +0xD2,0xF6,0xBF,0xD2,0x7F,0xF7,0x3F,0xFF, 0xFF,0xF3,0x7F,0xFF,0xFF,0xF7,0xFF,0xBA, +0xDF,0xFB,0xFD,0xFF,0xBF,0xFF,0xFB,0xFF, 0xF8,0x7F,0xEA,0xFF,0xFE,0xFE,0xDF,0xFF, +0xF7,0xFF,0x7F,0xBB,0xFF,0xFF,0xBF,0xDF, 0xFB,0xFF,0xFF,0xBF,0xFF,0xB1,0x7F,0xFF, +0xFB,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF, 0xCF,0xFE,0xFF,0xFF,0xEF,0xFF,0xF7,0xFF, +0xFF,0xFF,0xF1,0xFF,0x69,0xBE,0xFA,0xBF, 0xAF,0xE2,0xFF,0xFE,0xFD,0xAF,0xF3,0xFE, +0xFF,0xBF,0xEF,0xFB,0xFC,0xFF,0xFF,0x07, 0xFD,0x95,0xDB,0xDF,0x7F,0xDF,0xAF,0xFF, +0xF7,0xAF,0x36,0xFE,0xBF,0x65,0xEB,0xF6, 0xFE,0x9F,0x6F,0xFE,0x07,0xFF,0xCF,0xFF, +0xF8,0xFE,0xFF,0xCF,0xFF,0xF6,0xFA,0xE7, 0xFB,0xFE,0xFF,0xBB,0xED,0xF9,0xFF,0xFF, +0xFF,0x5F,0xFF,0xFF,0xFF,0x75,0xFF,0xEF, 0x7E,0xFD,0xE0,0xE8,0x5E,0xD3,0xE5,0xF9, +0x3E,0x5F,0xD7,0xF7,0xFF,0xFA,0x2F,0xFB, 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0x7F, +0x7F,0xD7,0xF5,0x7D,0x5F,0x57,0xD5,0xF5, 0xEF,0xFF,0xF3,0x7F,0xFC,0x7F,0xFF,0xC7, +0xF1,0xFF,0xFF,0x1F,0xCF,0xB0,0xFF,0x3F, 0xCF,0xF3,0xFC,0xFF,0x3F,0xCE,0xFF,0xE4, +0xFF,0xDF,0x7F,0xFE,0xF7,0xBB,0xFF,0xFF, 0xDF,0xEF,0xEE,0xFF,0xBF,0xEF,0xFB,0xFE, +0xBF,0xBF,0xEF,0xFF,0xD1,0xFF,0xFF,0xFF, 0xFD,0xFB,0xFF,0xFD,0xFF,0xFB,0x9F,0xE9, +0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xBF, 0xFF,0xB3,0xFF,0xFF,0xF7,0xFF,0xFF,0xAF, +0xF7,0xFF,0xB6,0x3F,0xEB,0xFA,0xFE,0xBF, 0xAF,0xEB,0xFA,0xFE,0xBF,0xFE,0xA7,0xFF, +0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF, 0xFE,0x9F,0xF7,0xF9,0xFF,0x7F,0x9F,0xE7, +0xFF,0xFF,0xFE,0xAF,0x6F,0xFF,0xFF,0xFF, 0x9F,0xFF,0xDF,0xFF,0x7D,0x5F,0xDD,0xFF, +0xFB,0xBF,0xE7,0xBB,0xFF,0xFB,0xDF,0x6D, 0x5F,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xEB,0xF7,0xFF,0xE7,0xEF,0xF7,0xFF,0xFF, 0x7F,0xFF,0xF7,0xFF,0xFC,0x8F,0xFF,0xEF, +0xFD,0xFE,0xFF,0xBE,0xF4,0xF2,0x7D,0xD7, 0xCF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xCF,0x6B,0xFF,0xBF,0x3F,0xFB,0xF2, 0xFC,0x7F,0xEB,0xFF,0x9F,0xFA,0xFF,0xFF, +0x3F,0xFF,0xF3,0xFF,0xFF,0xFD,0x70,0xF7, 0xFF,0xFF,0xBF,0xFF,0xFB,0xD7,0xFE,0xF5, +0x77,0xFF,0x15,0xDD,0x77,0xFD,0xFF,0x7F, 0xDF,0xF7,0xFB,0xCD,0xBF,0xFF,0xFD,0xFF, +0xFF,0xDF,0x37,0xCD,0xF9,0xEC,0xFE,0xEF, 0xBB,0xF4,0xFB,0x3F,0x4F,0xB3,0xFF,0xFD, +0xCB,0xFF,0xE9,0x7E,0x54,0x9F,0xE5,0x4B, 0xB7,0xFF,0xDD,0x7D,0xC7,0x71,0xDD,0x77, +0x5D,0xD7,0x75,0xCD,0x7F,0xD6,0xFF,0xD3, 0xF6,0xF9,0x3F,0x6D,0x95,0xAF,0x7F,0xFE, +0xFF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFE,0xF6,0xC7,0xFF,0xAD,0x7B,0xCA,0xFF, +0xBF,0xBF,0xEF,0xFD,0xE3,0xDF,0xB7,0xED, 0xFB,0x7E,0xDF,0x37,0xED,0xE3,0xFB,0xDF, +0xFF,0x52,0x5C,0x15,0xFD,0xCF,0x7F,0xDF, 0xFE,0xEF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEC, +0x7B,0xFE,0xFF,0xFE,0x3E,0x7F,0xDA,0xF7, 0xFD,0xFF,0x7F,0xFF,0xFF,0xFB,0xEF,0xBB, +0x6F,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF, 0xF7,0x7D,0xFF,0xD8,0xFF,0xFD,0xBF,0x7F, +0xFB,0xFF,0xFF,0x9F,0xFB,0xFE,0x7F,0x9F, 0xE7,0xF9,0xFE,0x7F,0x9F,0xEA,0x7F,0xF6, +0xBF,0xBD,0x6A,0x5A,0xF6,0xE5,0xBF,0x77, 0x5F,0x6D,0xDD,0x77,0x5D,0xD7,0x75,0xDD, +0x77,0xFF,0xA5,0xBF,0xCF,0xFB,0xFF,0xFF, 0xBF,0xCF,0xFB,0xFD,0xFF,0xBF,0xF3,0xFE, +0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD,0xAB, 0xFF,0xBF,0xBF,0xFF,0xFB,0xFF,0x7F,0xEF, +0xFF,0xBE,0xFB,0xEE,0xFB,0xBE,0xEF,0xBB, 0xEE,0xFB,0xBF,0xFF,0xB5,0xFF,0xD0,0xBC, +0xFD,0x2F,0x4B,0xF7,0xFF,0xFF,0x9F,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x9F, +0xFA,0x8F,0xFD,0xAB,0xFA,0xDA,0xBF,0xAF, 0xB3,0xFD,0xFF,0xBF,0xFB,0xFE,0xFF,0xBF, +0xEF,0xFB,0xFE,0xF7,0xBF,0xFF,0x9F,0xFF, 0x77,0xF7,0xBD,0xFD,0x77,0xDF,0xFF,0x7E, +0xDF,0xED,0xBB,0xFE,0xFF,0xBE,0xEF,0xFB, 0xFE,0xFF,0xFA,0x3F,0xFF,0xBE,0x6F,0x8F, +0xE6,0xF9,0xFE,0x7F,0x9F,0xC7,0xFE,0x7F, 0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFB, +0x7F,0xFF,0x7F,0xCF,0xFF,0xFD,0xFF,0xFF, 0xDF,0xFB,0xAF,0xBF,0xEF,0xFF,0xFE,0xFF, +0x9F,0xEF,0xFB,0xFF,0xFC,0xFF,0xFB,0xFE, 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xF7, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xF5,0xFF,0xFF,0xFF,0x3F,0xDF,0xF7, +0xFF,0xFF,0x7F,0xEF,0xFE,0xFF,0xBF,0xFF, 0xFB,0xFF,0xFF,0xBF,0xEF,0xFF,0xB3,0x7F, +0xFF,0x7B,0x5E,0xF7,0xFD,0xFF,0x7B,0x7F, 0xF7,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, +0xDF,0xF7,0xFF,0x17,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xDD,0xF6,0xFC,0xBF,0xCB,0xF2, +0xBC,0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xFE, 0x8F,0xFF,0xFA,0x7E,0xBF,0xA7,0xEB,0xDA, +0xFC,0xBF,0xAF,0x7A,0xFE,0xBF,0xAF,0xEA, 0xFA,0xFE,0xBF,0xAF,0xF4,0xDF,0xFE,0xFF, +0xF3,0x3C,0x7F,0x3E,0xFF,0xCF,0xF8,0xBF, 0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xE7,0xE8, +0xFF,0xFC,0x9F,0xFF,0xFF,0xCF,0xEB,0xB3, 0xE7,0xFB,0x7B,0xF3,0xFE,0xFF,0xCF,0xDB, +0xFB,0xFB,0xBF,0x6F,0x6F,0xDF,0xEC,0x7F, 0xFF,0xFF,0xF7,0xFD,0xFD,0xFF,0xFF,0xFF, +0xFF,0xB2,0xBF,0xFF,0xDE,0xFD,0xBD,0xEF, 0xFB,0xF6,0xDF,0xEA,0xE7,0xDB,0xFE,0xBB, +0xFF,0xEB,0xFB,0xBF,0x9F,0x8F,0xE8,0xFE, 0x3F,0x8F,0xA3,0xF8,0xFE,0x3F,0x8F,0xFF, +0xF8,0x7E,0xFD,0xFD,0x7F,0xFF,0xFB,0xCD, 0xFF,0xFD,0xFF,0x5F,0xEF,0xFD,0xFF,0xFF, +0xDF,0xF7,0xFD,0xFF,0xBE,0x90,0xFF,0xFF, 0xEE,0xFF,0x3F,0xBF,0xF3,0xBB,0xFE,0xB7, +0xAB,0xFA,0xFE,0xAF,0xAD,0xEA,0xFA,0xDE, 0xAB,0xFF,0x63,0xFF,0xFE,0xF2,0xFF,0xB3, +0xFF,0xDF,0xEE,0x7D,0xFF,0x03,0xF1,0xF4, 0x3F,0x1F,0xC3,0xF1,0xEC,0x7F,0xFE,0x6F, +0xFF,0xFB,0xFB,0xFF,0x9F,0xFF,0xBF,0xFF, 0x7B,0x5F,0xFD,0xFF,0xDF,0xF7,0xFD,0xFD, +0x7F,0x7F,0xDF,0xFE,0xCF,0xFB,0xFF,0xFF, 0xAF,0xFB,0xFF,0x1F,0xEF,0xA5,0xFD,0xBF, +0xDF,0xFB,0x7D,0xFF,0xBF,0xDF,0xFB,0xFF, 0xFD,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, +0xAF,0xF3,0xFF,0xFB,0x7F,0xBF,0xD7,0xFB, 0xBF,0x7F,0xBB,0xF7,0xFF,0xF8,0x7F,0xFF, +0xFA,0x5F,0xD7,0xFF,0xDF,0x7F,0xEF,0xFF, 0xFF,0x7F,0xDB,0xF7,0xFD,0xFF,0x7F,0xDF, +0xB7,0xFB,0xEC,0xFF,0xFF,0xF7,0xBF,0xEF, 0xFD,0xFC,0xFB,0xFF,0xEF,0xF0,0xFE,0x3F, +0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xEF,0x8D, 0xFF,0xFF,0xEF,0x7F,0xBF,0xFF,0xFB,0xFF, +0xDB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xEF,0xD8,0xFF,0x2E,0x7F, +0xBE,0xEF,0xFE,0x6E,0xFF,0xBF,0xF9,0xFF, 0xFF,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFC,0x66,0xBE,0x47,0xF3,0x7F,0xDF,0xFE, 0x87,0x9F,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0x6F,0x7C, 0xFB,0x4F,0xD2,0xFF,0xFD,0x2B,0xFE,0xFF, +0xFF,0xFD,0x5F,0xD7,0xD5,0xF5,0x7D,0xFF, 0xFF,0xFF,0xBF,0x9B,0xFF,0xFF,0xDF,0xB7, +0xFF,0xFF,0xDF,0xFF,0x3F,0xCF,0xFE,0x7F, 0xBF,0xEF,0xFB,0xFC,0xFF,0x3F,0xFF,0xD9, +0xBF,0xFE,0x97,0xEC,0x8F,0xB7,0xFE,0x9B, 0x7D,0xFD,0xB7,0xDD,0x77,0x1D,0xC7,0x71, +0xDD,0x77,0x5D,0xD7,0xF3,0x6F,0xFD,0x3F, 0x73,0xDD,0xAF,0xFD,0x7A,0xFF,0xFF,0xAF, +0xFE,0xFD,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF, 0xEF,0x66,0x7F,0xFF,0xFF,0xBF,0xBF,0xFF, +0xFB,0xFF,0xF7,0xDF,0xFD,0xFB,0x7D,0xDF, 0xB7,0xCD,0xF3,0x7C,0x5F,0x3F,0x91,0x3F, +0xFF,0x3D,0xEF,0x7B,0xFF,0xFC,0xFF,0xCA, 0xEF,0xFE,0xFF,0xBD,0xEF,0xFB,0x1E,0xE7, +0xBB,0xEC,0x7F,0xB3,0xFF,0xFD,0x9F,0xFF, 0xFF,0xFE,0xFF,0xFF,0x7F,0xBF,0xFB,0xFE, +0xFF,0xBF,0xEF,0xFB,0xEE,0xFB,0xBF,0xDF, 0x67,0xFF,0xFF,0xBF,0xEF,0xDB,0xFF,0xBC, +0xFE,0x7F,0xFB,0xFF,0x9F,0xEF,0xF9,0xFE, 0x7F,0x9F,0xE7,0xF9,0xFE,0x87,0xFF,0xEE, +0xFB,0xBE,0xE5,0xBF,0xEF,0xF9,0xD7,0x65, 0xF7,0xDD,0xE7,0x7D,0xDF,0x77,0x5D,0xD7, +0x7F,0xF8,0x9B,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xFF,0xBF,0xEF,0xFB,0xFF,0x7F,0xCF, +0xF3,0xFC,0xFF,0xBF,0xEF,0xFF,0xDB,0x3F, 0xEF,0xFB,0xFE,0xFF,0xDF,0xFF,0xFE,0xFB, +0xBB,0xEF,0xBF,0xEF,0xBB,0xEE,0xFB,0xBE, 0xEF,0xBB,0xFF,0xFC,0x7F,0xFD,0x3B,0x5B, +0xD6,0xE5,0xFD,0x4F,0xC3,0xFB,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF, +0xB4,0xFF,0xFA,0xBC,0x8F,0xB2,0xE9,0xD2, 0x2E,0xCF,0xFB,0xFF,0xBF,0xEF,0xFB,0xFE, +0xFF,0xBF,0xEF,0xFB,0xFF,0xEC,0xFF,0xFD, 0xFD,0x7F,0xDF,0xF7,0xE4,0xDF,0x5F,0xFF, +0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xC3,0xFF,0xEF,0xE6,0xF8,0xFE, +0x3F,0x8B,0x83,0xF9,0xFE,0x7F,0xE7,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x17, +0xFD,0xFF,0xFF,0xFF,0x7F,0x5F,0xF7,0x2C, 0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xE7,0xF9, +0xFE,0x7F,0x9F,0xFE,0x2F,0xFF,0xFF,0xEF, 0xFF,0xFE,0xBF,0xEF,0xAD,0xFF,0xFF,0x7F, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFE,0xDF,0xFF,0xDF,0xFF,0xFD,0xFD,0x7F, +0xDF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x3F,0xFE, +0xF7,0xFD,0xEF,0x7A,0xFF,0xB1,0xBD,0xFF, 0x7F,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD, +0xFF,0x7F,0xF3,0x27,0xFF,0xDF,0xFF,0xDD, 0xFF,0xFC,0x9B,0xFF,0xCB,0xFC,0xBF,0x2F, +0xCB,0xF2,0xFC,0xBF,0x2F,0xC9,0xFF,0xDE, 0xFF,0xDF,0xAF,0xEB,0xDA,0xFE,0xBB,0xAF, +0xEB,0xF8,0xF7,0xAF,0xE8,0xFA,0xFE,0xBF, 0xAF,0xEB,0xF2,0xFF,0xFD,0xFF,0xFF,0xEF, +0xBD,0xD7,0xBF,0xFF,0xFF,0xDE,0x8F,0xB8, 0xDE,0x37,0x8D,0xA3,0x78,0xDA,0x3F,0x8F, +0xFF,0xA1,0xFF,0xFF,0xFB,0xFB,0xFF,0xFF, 0xFF,0xFF,0xA7,0xBD,0xFB,0x76,0xFD,0xBF, +0xEF,0xDB,0xFE,0xBB,0xBF,0xFE,0x27,0x7F, 0xFF,0xFE,0xFE,0xFD,0xF5,0xFF,0xEF,0xF5, +0xDF,0x1F,0xE7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0xFF,0xCD,0xFD,0xAE,0xFF,0xFA, +0x3E,0x3F,0xAB,0xFD,0xF8,0x7E,0x8F,0xE3, 0xF8,0xFE,0x3E,0x8F,0xE3,0xF8,0xFF,0xFE, +0x1F,0xEF,0xDF,0xBF,0xFE,0xDE,0xDF,0xD9, 0xFF,0xDF,0xBC,0xFF,0xFF,0x7F,0xFF,0xEF, +0xFD,0x7F,0xDF,0xF7,0xF9,0x3F,0xFE,0xFF, 0xFF,0x6F,0xFE,0xDE,0xBF,0xF7,0xED,0xEA, +0xFD,0x8F,0x83,0xF8,0xEA,0x3F,0x8F,0xEF, 0xFF,0xF4,0x7F,0xFF,0xEF,0xEF,0x7B,0xF3, +0xF1,0x5F,0xFF,0xFF,0xF1,0x3B,0x7F,0xDF, 0xF7,0xFD,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF, +0xFF,0xFF,0xF7,0xFF,0x6F,0xFF,0x7F,0xFF, 0xFF,0xF7,0xDE,0xF7,0xBF,0xEF,0xFB,0xF7, +0xFD,0xFF,0xFF,0xF5,0xFA,0xFF,0xFF,0xFB, 0xE7,0xFF,0xF3,0xF8,0x7F,0xF3,0xDF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0xEF, 0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, +0xFF,0x7F,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xCF,0xFF,0x37,0xFF,0xFF, +0x7F,0xDF,0x77,0x5D,0xE7,0xFC,0xFF,0xBF, 0xF7,0xF5,0xFB,0xFF,0xFF,0xD7,0xF5,0xFB, +0xFF,0xFF,0x45,0xFD,0x7F,0xEA,0xFD,0xBE, 0xBF,0xDF,0xF7,0xFF,0xFF,0xDB,0xFB,0xFE, +0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0xFB,0x5F, 0x7F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFE,0xFF,0xEF,0xFD,0xFF,0x7F,0xDF, 0xFF,0xEF,0xFB,0xF8,0x0F,0xF3,0xFF,0xF9, +0x2E,0xFB,0xFE,0xFC,0xF3,0xEF,0xFF,0xFF, 0xBF,0xFF,0xFB,0xE7,0xFF,0xFE,0x7E,0xFF, +0xC0,0x6B,0xCF,0xFF,0x34,0xDF,0xF1,0xFD, 0xFF,0xEF,0xFF,0xFF,0xFF,0xDF,0xF7,0xFD, +0xCF,0x7F,0x9C,0xFD,0xFD,0x6C,0xF7,0xFF, 0xF6,0xFD,0xEB,0x2B,0x9F,0xFF,0xFC,0xFE, +0x7E,0xFF,0xFF,0xFF,0xFF,0xD7,0xF3,0xF7, 0xFF,0xFB,0xE1,0xBF,0xFF,0xEB,0x7A,0xDE, +0xD7,0xFB,0xFF,0xF9,0xFE,0xFF,0xFF,0xF3, 0xDE,0x7F,0xFD,0xE7,0x7F,0xFF,0xFD,0xBB, +0xFF,0xFF,0x7E,0xCC,0xF6,0xAF,0x5F,0x7F, 0xFE,0xF4,0x7D,0xF7,0xFD,0xBB,0x6E,0xDB, +0xB7,0xFF,0xF7,0xDF,0x66,0xFF,0xFF,0xF7, 0x3D,0xCF,0xDE,0xBD,0xFF,0xFF,0xDE,0xDB, +0x8D,0xF7,0x7E,0xDF,0xB7,0xEF,0x7F,0xFF, 0xF6,0x87,0xFF,0xFF,0xEF,0xFE,0xDE,0xBF, +0xFF,0xFF,0xFF,0xBB,0xEF,0xFD,0xFF,0x7B, 0xDE,0xF7,0x3F,0xFF,0xBF,0xFB,0xDB,0xFF, +0xF2,0xB6,0xFD,0xBD,0x7F,0xE7,0xFF,0xFF, 0xFF,0x6F,0xF7,0xFF,0xFF,0xFF,0xFE,0x77, +0xFF,0xBF,0xF8,0xAF,0xFF,0xDF,0xBF,0xFF, 0xBF,0x7F,0xFB,0xFF,0xFF,0xFF,0xDB,0xFE, +0xFF,0xBF,0xFF,0xFA,0xFF,0xFD,0xFF,0xF6, 0x7F,0xFF,0x9F,0xFF,0xFF,0x3F,0xEF,0xF8, +0xEE,0x7E,0x9F,0xBA,0xFE,0xBF,0x8F,0xEF, 0xFE,0xFE,0xF9,0xFF,0xFA,0x7F,0xFE,0x7E, +0xBF,0xAF,0xFB,0x96,0xFD,0x9F,0xEF,0x5E, 0x65,0xBE,0xEF,0x5B,0xB6,0xFF,0xBE,0xE3, +0xFF,0xB5,0xBF,0xFF,0xFD,0xFF,0x7F,0xFF, 0xEF,0xDF,0xFE,0xFF,0xBF,0xFB,0xFE,0xFF, +0xBF,0xCF,0xFF,0xFF,0xFF,0xFD,0x9B,0xFF, 0xFE,0xFB,0xFE,0xDF,0xFF,0x7F,0xFF,0xF7, +0xFE,0xFF,0xDF,0xFB,0xFB,0xFE,0xFF,0xFF, 0xFF,0xFF,0xFF,0xB7,0xFE,0xFA,0xFF,0xAB, +0xEF,0xFF,0xFD,0xB5,0x7B,0x7F,0xFB,0xF7, 0xFD,0xFF,0xFF,0xDD,0xFF,0xEF,0x8F,0xFF, +0x2F,0xFF,0xFB,0x7C,0xFF,0x3F,0xDF,0x73, 0xEB,0xFE,0x3F,0xFF,0xEF,0xFB,0xFE,0xFF, +0xEF,0xFD,0xFF,0xBF,0xFD,0x0F,0xFF,0xFF, 0xFF,0xF5,0xF9,0xFF,0x7F,0xD7,0xFD,0xFF, +0xDF,0xFF,0xF7,0xFB,0xFF,0x7F,0xBF,0xFF, 0xFF,0xF0,0x9F,0xFF,0xFE,0x7F,0x8B,0xE3, +0xF9,0xDE,0x27,0x9B,0xE6,0xBE,0x7F,0x9B, 0xC3,0xF8,0xDE,0x7F,0x9D,0xE7,0xFE,0x7F, +0xFF,0xFF,0x5F,0xD7,0xFF,0xFF,0xFF,0x4F, 0xFB,0xFF,0xFF,0x7F,0xFF,0xAF,0xFF,0x9F, +0x7F,0xFB,0xFF,0xE8,0xFF,0xFF,0xFE,0xBF, 0xAF,0xFF,0xFF,0xFE,0xBF,0xEF,0xF7,0xFF, +0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, 0xFC,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF, +0xFD,0x3F,0xCF,0xFF,0xFF,0xFF,0xFF,0xF7, 0xFF,0xFD,0x7F,0xFF,0xFF,0x93,0xFF,0xFF, +0x7A,0xDF,0xF7,0xFF,0xFF,0x7B,0x7F,0xB7, 0xEF,0xFF,0xFF,0xFD,0xBF,0xFD,0xFB,0xFF, +0xF7,0xFF,0xD7,0xFF,0xFF,0xFF,0xFC,0x9F, 0x6F,0xCB,0xFF,0xF4,0xBB,0xDF,0xD6,0xFD, +0xBF,0x2F,0xD3,0xF7,0xFF,0xDF,0xFF,0xCF, 0xFF,0xFA,0xBE,0xBD,0xAF,0x6A,0xDA,0xBE, +0xBB,0xAB,0x3A,0xBE,0x2D,0xAE,0xEB,0xDA, 0xF6,0x3F,0xAD,0xF5,0xDD,0xFF,0xCF,0xF1, +0xFF,0xF9,0x7F,0xFF,0x73,0xFE,0xFF,0xCF, 0xC3,0xF4,0xF7,0x2F,0xF3,0xFF,0xFC,0xFF, +0x7C,0x1F,0xFF,0x3F,0x4F,0xFF,0x7E,0xFF, 0xEF,0xBD,0xF6,0xFE,0xFF,0x2B,0xEF,0xDC, +0xFB,0xFD,0xFF,0xFB,0xFF,0xEA,0x7B,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFB,0xF7,0xDF,0xFF, +0xE3,0x7D,0xFF,0xB7,0xFF,0xBF,0xFF,0xFF, 0xDF,0xFF,0xF8,0xFF,0xBF,0xFF,0xBF,0xEB, +0xE7,0xFA,0xFE,0x3D,0xBF,0xE9,0xFC,0xBF, 0xFF,0xFA,0xFB,0xFE,0xFF,0xFF,0xFF,0xD9, +0xFF,0xFF,0xFF,0xF6,0x7F,0xFF,0xF6,0x7D, 0xFF,0xDF,0xCF,0xFD,0xBF,0xFB,0xEF,0x7E, +0xFF,0x7F,0xFF,0xFF,0xD3,0xFF,0xFD,0xFB, 0xFF,0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xBF, +0xFE,0xFF,0xF7,0xEF,0xFF,0xFF,0xFF,0xFB, 0xFF,0x87,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF, +0x7B,0xFE,0xFF,0xFE,0x3B,0xF7,0xF7,0xFF, 0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF, +0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xF7, 0xFF,0xFF,0xAD,0xFF,0xFE,0xF7,0xFF,0xFF, +0x5F,0xFF,0xFF,0xDF,0xFF,0xFD,0xFF,0xF5, 0xFF,0xDF,0xFF,0xBD,0xFF,0xE9,0xFF,0xC7, +0xF3,0xFF,0xFF,0xF7,0xFF,0xF3,0xFF,0xF8, 0x3B,0xFF,0xFF,0x7B,0xDF,0xBF,0xFB,0xEF, +0xFB,0xFF,0xFB,0xF7,0xF7,0xBB,0xFF,0xFF, 0xFF,0xFF,0xFB,0xFF,0xFE,0x7F,0xF3,0x7F, +0x5E,0xB7,0xBF,0xFD,0x7F,0xFF,0xF9,0x7F, 0xFB,0xFF,0xEB,0xFD,0x7F,0x7F,0xFF,0xEF, +0xFB,0xE0,0x3F,0xFE,0xBF,0xBF,0xDF,0xFF, 0x7E,0xFF,0xF7,0xFF,0xFF,0xFE,0xBF,0xFF, +0xDB,0x78,0xFF,0xFF,0xFF,0xEE,0xA1,0xBF, 0xF5,0xDE,0xFB,0xF7,0xFF,0xFB,0xFF,0xFF, +0xFF,0xFF,0xFB,0xFF,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xEF,0xF0,0xFF,0xFF,0xFF,0xF3, +0xF7,0xFF,0xEF,0xFF,0xE7,0xCF,0xFF,0xFB, 0xFF,0xEF,0xFF,0xFF,0x9F,0x9F,0xEF,0xFC, +0x16,0xBF,0xFE,0xF3,0xE4,0xFF,0xFF,0xC6, 0xFF,0xE7,0xFF,0xFF,0xFD,0xFF,0xBF,0xFF, +0xFF,0x3F,0xFF,0xBF,0xD6,0xAF,0x7F,0xFE, 0x6B,0x7E,0x7F,0xFF,0xAF,0xFF,0xFF,0xBF, +0xFF,0x5F,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF, 0xFF,0xBD,0xDB,0xFF,0xFE,0x5F,0xF2,0xFF, +0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xEF,0x7F,0xFF,0xFF,0xFF,0xFF,0xDE,0xBF, +0xFF,0xFF,0xEF,0xFB,0x77,0xFE,0xBD,0x7F, 0x5F,0xFF,0xFF,0xFF,0xDF,0x6F,0xED,0xFF, +0xFD,0xFF,0x7F,0xFD,0x6F,0xFF,0xFF,0x77, 0xDA,0xCF,0xFD,0x5F,0xFF,0xBF,0xFF,0xFF, +0xDF,0x7F,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF, 0x66,0x7F,0xFF,0xFE,0xBF,0xE7,0xBF,0xFA, +0xFF,0xFE,0xFF,0xFF,0xFF,0xDF,0xFF,0x59, 0xEF,0xFF,0xEF,0xFB,0x7F,0x89,0xFF,0xFF, +0xE9,0xFF,0x6F,0xFF,0xF5,0xFF,0xFF,0xFF, 0xFF,0xFF,0x7F,0xF2,0xF7,0xFF,0xFF,0xEF, +0xF8,0x7F,0xFB,0xFF,0xFD,0xFF,0xFF,0xD9, 0xFF,0xEF,0xBB,0xFF,0xFF,0xFF,0xBF,0xEF, +0xDE,0xFF,0xFF,0x9F,0x7F,0xDF,0xFF,0xF7, 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xAF, +0xFF,0xFF,0xF7,0x3F,0xEB,0x9F,0xFE,0x7F, 0x9E,0x7F,0x9F,0xFE,0x87,0xFF,0xED,0xDB, +0x56,0xFF,0xBF,0xAF,0x0B,0xD2,0xFF,0xEF, 0xDB,0x6E,0x7D,0xBD,0x6F,0xF8,0xFE,0x3F, +0xFA,0x5B,0xFF,0xFD,0xBF,0xEF,0xFF,0xBF, 0x6F,0xDB,0xE6,0xFF,0xFF,0x3F,0xFF,0xDF, +0xFE,0xFF,0xFF,0xFF,0xFF,0xDA,0x3F,0xFF, 0xFB,0xFE,0xFE,0xFF,0xFF,0xDF,0xF7,0xBD, +0xFF,0xFD,0xFF,0xFE,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFF,0xF1,0x5F,0xFD,0x9F,0xDF,0xFD, +0xFF,0xFD,0x7F,0xFF,0xFF,0xFF,0xFF,0x76, 0xFA,0xFF,0xFF,0x7F,0xE3,0xF8,0xFF,0xAE, +0xFF,0xFB,0x7E,0x9D,0x73,0xFF,0xFA,0x7F, 0xDF,0xFF,0xFF,0x7F,0xFF,0xFB,0xCD,0xFF, +0x7F,0xEF,0xFB,0xFF,0xFD,0xFF,0xF7,0x7F, 0x7F,0xEF,0xFF,0xED,0xFF,0xFF,0xFF,0xB5, +0xFF,0xBF,0xFF,0xBF,0xFD,0xEF,0xDB,0xF7, 0xFF,0x93,0xFF,0xEF,0xE2,0xF9,0xBE,0x7F, +0x8B,0xE7,0xF9,0xFE,0x6B,0xE7,0xF9,0xFE, 0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x47,0xFF, +0xFF,0xFD,0xFF,0x9F,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xF5,0xFF,0x9F,0xFF,0xF7,0xFE, +0xFF,0xBF,0xFE,0x6F,0xFF,0xFF,0xFB,0xFF, 0xFF,0xFF,0xAF,0xFF,0xFF,0xFF,0x7F,0xFB, +0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, 0xDF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xDF, +0xFF,0xFF,0xFF,0x5F,0xFF,0xFF,0xFF,0xFF, 0x5F,0xFB,0xFE,0xFF,0xF8,0x37,0xFF,0xFF, +0xEF,0xFF,0x7F,0xFE,0xBF,0xFF,0xFF,0xFE, 0xBF,0xFF,0xFF,0x7F,0xFF,0xBF,0xFD,0xFF, +0x7F,0xFA,0x7F,0xFF,0xFF,0x6F,0xFF,0xFF, 0x7D,0xFF,0xCF,0xFF,0xFF,0xFF,0x4F,0xFF, +0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xBF, 0xFF,0xAE,0xEB,0xFA,0xFE,0xBB,0xAD,0xEB, +0xFA,0xF7,0xAF,0x6B,0xFA,0xF6,0xBF,0x25, 0xE9,0xF2,0x7F,0x45,0xFF,0xFF,0xFD,0xF7, +0xF7,0xBF,0xFF,0xDF,0xFF,0xFF,0xBF,0xFB, 0xFF,0xDF,0xF3,0xFF,0xF7,0x3F,0xCF,0xFF, +0xA1,0xFF,0xFF,0xBF,0xE7,0xFF,0xFF,0x7F, 0xFF,0x3D,0xFF,0xFF,0xFF,0xF7,0xFF,0x2F, +0xFF,0xFB,0xF5,0x7F,0xFE,0x57,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, +0x3F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD,0xFE, 0xF7,0xEE,0xAF,0xFE,0xEE,0xE7,0xFA,0xFF, +0xFE,0x9D,0xF9,0x5E,0xFE,0xFF,0xEB,0xFF, 0xFF,0xDF,0xA7,0xFF,0xFF,0xFF,0xFC,0xDB, +0xFF,0xFF,0xFF,0x7E,0xFB,0xFF,0xFF,0xEF, 0xFB,0xFD,0xFF,0xDB,0xFF,0xFF,0xFF,0xEF, +0xFF,0xFF,0xFF,0xFD,0xBF,0xFE,0xBF,0xFF, 0x6F,0x7F,0xFF,0xF7,0xFF,0xFF,0xF9,0xFF, +0xF7,0xFF,0xBF,0xDE,0xF7,0xFF,0xFF,0xFF, 0xFA,0x7F,0xFD,0xBF,0x5F,0xFF,0xFF,0xBF, +0xFF,0xED,0xFF,0xF7,0xBF,0xFF,0xFF,0xEF, 0xFF,0xDF,0xFF,0xFF,0xFF,0xE6,0xFF,0xFB, +0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0xFF, +0xFD,0xFF,0xF5,0xFF,0xF6,0x7F,0xDF,0xBD, 0xCF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF, +0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3, 0xFF,0xEE,0xBF,0xFF,0x7D,0xEF,0xFE,0xFF, +0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFE, 0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xB5,0xAE, +0xFF,0xFF,0xB6,0xFE,0xBF,0xFF,0xFF,0xBF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0x27,0xFF,0xEF,0xFE,0x7F,0xDF,0xFF, 0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFD,0xFF,0xF7,0xF9,0x9F,0xFF, 0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F, +0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0x0F,0xFF,0xE7,0xBF,0xFE, +0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFC,0xBF, 0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xC4, +0x6B,0xFF,0x29,0x1F,0xFB,0xAF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xEF,0x1B,0xFE,0xFF,0xFC, +0x6F,0xFF,0xFF,0xFD,0x6A,0xF7,0xD7,0xF5, 0xBF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFE,0xBF,0xFF,0xFF,0xFA,0xFF,0xFF,0xF7, 0xFB,0xDD,0xBF,0xFF,0xE7,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x7F,0xFF, 0xFF,0xF5,0xFF,0xFF,0xF7,0xFD,0xB3,0xEF, +0xFD,0x7E,0x5D,0xFF,0xFD,0xFF,0xFF,0xFF, 0xFD,0x7F,0xD2,0xF5,0xFB,0x7E,0xCB,0xB7, +0xFF,0xFF,0xFF,0xC6,0xFF,0xFD,0xEE,0x63, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xFD,0x65, +0x5B,0xDF,0xFF,0xD5,0xFF,0xFF,0xFF,0xF6, 0xE7,0xBF,0xF7,0xA9,0xFF,0xFF,0xED,0xFF, +0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFF,0xFF, 0xAF,0xFF,0xFF,0xFF,0xF8,0x1B,0xFF,0xE3, +0xD0,0xBF,0xFF,0xE1,0xFF,0xFF,0xFF,0xFF, 0xFF,0xD7,0xFF,0xFF,0xFF,0x5F,0xFF,0xFF, +0xFF,0xFF,0xAF,0xFF,0xDB,0x76,0xBF,0xFF, 0x7F,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF, +0xFB,0xFE,0xFF,0xFF,0xFF,0xBF,0xF2,0x7F, 0xFF,0x9F,0xFE,0xBD,0xFE,0x7F,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xF7,0x3F,0xEC,0x7F,0xF6,0x95,0xBB, +0xEF,0xF8,0xFE,0xFC,0xBF,0x2F,0xDA,0xFC, 0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xEF,0xFF, +0xA9,0xBF,0xCF,0xFB,0xFF,0xFF,0xFF,0xFE, 0xDD,0xB7,0x6D,0xF6,0xD9,0xB6,0x6D,0x9B, +0x76,0xD9,0xBF,0xFB,0xFD,0xA3,0xFF,0xBF, 0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0x7F,0xDF, +0xFD,0xEF,0x7B,0xDE,0xF7,0xFD,0xEF,0x7F, 0xFF,0xFF,0x05,0xFF,0xFA,0xFE,0x7F,0xEF, +0xE3,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF, 0xFF,0x5F,0xFF,0xFF,0xFD,0x7F,0xFB,0xAF, +0xFF,0x63,0xC8,0xFF,0xBF,0xEF,0xFF,0xFF, 0xFA,0x7F,0xFF,0xFF,0xFF,0xFE,0x9F,0xF7, +0xFF,0xFA,0xBF,0xFE,0x9F,0xFB,0x7F,0xFF, 0xFF,0xEF,0xD7,0xFF,0xFF,0xF5,0xFF,0xFF, +0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xBF,0xFF, 0xF9,0xBF,0xFF,0xBE,0x27,0x9F,0xE7,0xF9, +0xFE,0x7F,0x8B,0xE7,0xFE,0x7F,0x9F,0xE2, 0xF9,0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF, +0xFF,0xFF,0xFB,0xFE,0xFF,0xFF,0xFF,0xD7, 0xFF,0xFF,0xFF,0xFF,0xF5,0xFF,0xFF,0xFF, +0xD7,0xFF,0xFA,0xFF,0xFE,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF,0xAF,0xF7,0xFF,0xFF, +0xFF,0xEB,0xFF,0xFF,0xFF,0xAF,0xFF,0xC4, 0xFF,0xF7,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF, +0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xD7,0xFF, 0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFB,0x7A, +0xDF,0xF7,0xFD,0xFF,0xFF,0xFE,0xBF,0xFF, 0xFF,0x7F,0xFF,0xAF,0xFF,0xFF,0xFF,0xF7, +0xEF,0xE3,0xFF,0xDD,0xD2,0xFF,0xDF,0xFF, 0xFF,0xF2,0xFC,0xBF,0xCB,0xF6,0xFD,0xBF, +0x2F,0xCB,0xFF,0x7F,0xDF,0xDE,0xAF,0xFF, 0xDA,0xEE,0xBF,0xAF,0xE9,0xFA,0xF4,0xBD, +0xAF,0x5A,0xAE,0xBB,0xAB,0x6B,0xDA,0xDE, 0xBF,0xAD,0xD7,0x5E,0xFF,0xFF,0xBF,0xFC, +0xFF,0xDF,0xFD,0xFF,0xFF,0xFF,0xFF,0xDF, 0xF7,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFA, +0x1F,0xFF,0xFE,0xFB,0xEF,0xBF,0xFD,0xFF, 0xFD,0xBD,0x77,0xFF,0xFF,0xFF,0xFF,0x9D, +0xEF,0xFF,0xFF,0xFF,0xEF,0x7D,0xFF,0xFB, 0xFE,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE, 0xBF,0xE4,0xFB,0xFF,0xFE,0x3F,0xFE,0xFF, +0xFF,0xFF,0xFF,0xAF,0xEA,0xFE,0xBF,0xAF, 0xEB,0xFA,0xFE,0xFF,0xFF,0xFF,0x55,0xF6, +0xFF,0xFE,0xF7,0xFF,0x7F,0xFF,0xEB,0xF7, 0x5F,0xC5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF, +0x6F,0xFB,0xFF,0x8A,0xFF,0xFF,0xFF,0xFF, 0xEB,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0xBF, +0xEF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, 0x77,0xDF,0xFB,0xFF,0xFD,0x7F,0xEF,0xFF, +0xFF,0xFF,0xBF,0x7F,0xFF,0xDF,0xBF,0xFF, 0xFB,0xFF,0xFF,0xFF,0xFE,0xEF,0xDF,0xFF, +0xFE,0xFF,0x9F,0xEF,0x7D,0xFF,0xF7,0xFF, 0x7F,0xFF,0xFF,0xDF,0xF7,0xFD,0xFF,0xEF, +0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFB, +0xFD,0xFF,0xBF,0xDF,0xD1,0xFF,0xF8,0x3B, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0x7E,0xDB,0xFD,0xFF,0x77,0xDB,0xB7,0x7D, 0xBF,0xFB,0xFF,0xF8,0x7F,0xED,0x7B,0x5E, +0xFF,0xFE,0xFF,0xFF,0x4F,0xD7,0xFD,0x7F, 0xDF,0xD7,0xF5,0xFF,0x7F,0xFF,0xFF,0xFF, +0xF2,0x3F,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF, 0xFF,0xBF,0xEF,0xFE,0xFF,0x3B,0xEE,0xFF, +0xFC,0xEF,0xFF,0xFF,0xFF,0x85,0xFF,0xFD, 0xFE,0xFF,0xF5,0xFF,0xFF,0xFE,0xFF,0xDF, +0xFB,0xFF,0x5F,0xBF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xA8,0xFF,0xFF,0x9F,0x9E,0xFF, +0xFF,0xFF,0x7F,0xF3,0xFF,0xFF,0xCF,0xFF, 0xF7,0xFD,0xFF,0x7F,0xFF,0xFF,0xFC,0x16, +0xBF,0xCF,0xA3,0xE5,0xEF,0x7F,0xFF,0xF3, 0xE4,0xFF,0xCF,0x93,0xFC,0xFF,0x3F,0xCF, +0xFF,0xFF,0xFF,0xD6,0x0F,0x7D,0xBF,0x6E, 0xFB,0xF4,0xFC,0xAF,0x6D,0xDB,0x77,0xB7, +0x6D,0xDB,0xF6,0xFD,0xBF,0xFF,0xFF,0xFF, 0xBF,0x9B,0xFA,0xDE,0xB7,0xB7,0xED,0xF9, +0x7E,0xB7,0xAC,0xEB,0xD6,0xB3,0xAD,0xEB, 0x7A,0xDF,0xFF,0xFF,0xFF,0xD8,0xBF,0xFF, +0xB7,0xED,0x9F,0x6F,0xDD,0xF7,0x68,0xDB, 0x37,0xB3,0x6C,0xDB,0x36,0xCD,0xB3,0x7F, +0xFF,0x7F,0xF5,0x6F,0xFD,0xEF,0x79,0x3D, 0xF7,0x93,0xE4,0x7A,0x9E,0xAD,0xEA,0x7A, +0x9E,0xF7,0xBD,0xEF,0xFF,0xFF,0xFF,0x76, 0x7F,0xFB,0xC6,0xFF,0xBB,0xEF,0xDA,0xFE, +0xFD,0xBF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xFF,0xFB,0xFF,0xA5,0xFF,0xFD,0xAB, +0x6F,0x78,0xDE,0x17,0x8F,0x79,0xDF,0xFD, 0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xFF,0xFB, +0xFF,0xFB,0xFF,0xEF,0xFB,0xEF,0xFB,0xFE, 0xFF,0xBB,0xDA,0xF3,0xEF,0x3B,0xCE,0xF3, +0xBC,0xEF,0x3F,0xCF,0xDF,0xFF,0xB7,0xFF, 0xFF,0xFF,0xCF,0x73,0xFF,0xBF,0xEF,0xFF, +0xF3,0xFF,0x3F,0xCF,0xF3,0xFC,0xFF,0x3D, 0xCF,0x9F,0xFE,0x07,0xFF,0xAF,0xEB,0xFE, +0xFD,0xBF,0xEF,0xEB,0xFA,0xFF,0xAF,0xEB, 0xFA,0xFE,0xBF,0xAF,0xFB,0xFE,0x3F,0xFB, +0x9B,0xFF,0x7F,0xDF,0xFF,0xF3,0xFE,0xFF, 0xDE,0xF7,0xBF,0x7B,0xDE,0xF7,0xBD,0xEF, +0x7B,0xFE,0xFF,0xFF,0xDF,0x3F,0xFE,0xFF, 0xB7,0xFF,0xEF,0xF7,0xFF,0xBF,0xED,0xFE, +0xDF,0xB7,0xED,0xFB,0x7E,0xDF,0xFF,0xFF, 0xFF,0xFD,0x5F,0xEF,0xEB,0xFA,0xFE,0xF5, +0xBF,0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xF8,0xFF,0xA8,0xFF, +0xFF,0xBF,0xEF,0xFB,0x6A,0xFB,0xB7,0xEF, 0xFB,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF, +0xEF,0xFB,0xFF,0xE0,0xFF,0xFF,0xFD,0x7F, 0x5C,0xD7,0x7D,0xDF,0xF3,0x5C,0xF5,0xCD, +0x73,0x5E,0xD7,0xB5,0xFD,0x7F,0xEF,0xFF, 0xDB,0xFF,0xFF,0xE2,0xF8,0xBE,0x2F,0x8F, +0xE7,0xF8,0xBE,0x6B,0xE2,0xF8,0xBE,0x2F, 0x8B,0xE2,0xF9,0xFE,0x7F,0xE7,0xFF,0xD7, +0xF5,0xFD,0x7F,0xFF,0xF7,0xF5,0xFD,0x7F, 0xD7,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF, +0xFF,0xFF,0x8F,0xFF,0xAF,0xEB,0xFA,0xFF, 0xFF,0xBF,0xEB,0xFA,0xFF,0x2F,0xEB,0xFA, +0xFE,0xBF,0xAF,0xEB,0xFF,0xFF,0xFE,0x5F, 0xFF,0x5F,0xFF,0xFF,0xFD,0xFF,0xFF,0xD7, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xBF,0xFE,0xB7,0xFD, +0xFF,0x7E,0xDF,0xF7,0xAD,0xFF,0x7F,0xF7, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, +0xF6,0x7F,0xFF,0xFF,0xFF,0xDB,0xF6,0xFC, 0xAF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xEC,0xBF,0xFF, 0xAF,0xEB,0xFA,0xF6,0xAB,0x8F,0xEB,0xFA, +0xF7,0xA5,0xEB,0xFA,0xBE,0xBF,0xAF,0xEB, 0xFA,0xFF,0x6D,0xFF,0xFF,0x7F,0xDF,0x33, +0xDD,0xFF,0x7F,0xFE,0xF7,0xFC,0x7F,0xFB, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9, +0xFF,0xFD,0xFF,0xFF,0xFE,0xFF,0xFF,0xDF, 0xFF,0xFF,0xEF,0xEF,0xFD,0xFF,0x7F,0xFF, +0xFF,0xFF,0xFF,0xFE,0xA7,0xFF,0xFF,0xFF, 0x77,0xDF,0xF7,0xFD,0x9F,0x7F,0xFE,0x77, +0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xAF,0xBF,0xAF,0xFF,0xF9,0xBE,0xBF, +0x8F,0xFB,0xFE,0xFE,0xEF,0xFB,0xFE,0xFF, 0xBF,0xEF,0xFB,0xFF,0xFF,0xFD,0xDF,0x6F, +0xEF,0xFF,0x7F,0xFF,0xBF,0xBF,0xDF,0xFF, 0xFC,0xFF,0xDF,0xF7,0xFD,0xEF,0x7F,0xDF, +0xFF,0xFF,0xFF,0x3F,0xF6,0xFF,0xCF,0xFF, 0xDB,0xFB,0xF7,0xFF,0xEB,0x7A,0xFF,0xFF, +0xFF,0xBF,0xEF,0xFB,0xFF,0xFF,0xFF,0xFE, 0x6D,0xFD,0xFF,0x5F,0xFB,0xFF,0xFF,0xF7, +0xFF,0x5F,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFB,0xFF, +0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xE7,0xF6, 0xBF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF, +0xFF,0xC9,0xFF,0xFF,0xFF,0xBD,0xFF,0xBF, 0xAF,0xEF,0xEF,0x3F,0xD1,0xFC,0x7F,0xFB, +0xC7,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0xFF, 0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x77,0xFF, +0xDF,0xB7,0xFD,0xF7,0xFD,0xF7,0xFF,0xFF, 0xFF,0xFF,0xFF,0x57,0xFF,0xF7,0xA5,0xFD, +0x3F,0xDF,0xBF,0xBF,0xFE,0x7F,0xFF,0xFF, 0xFF,0xDF,0xFA,0xFD,0xFF,0xFF,0xFF,0xFE, +0x87,0xFF,0xE9,0xFF,0xFE,0xEF,0xBF,0xEF, 0xFE,0xFE,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFA,0x9F,0xFF,0x3F, 0xFF,0xFD,0xFD,0x57,0xDF,0xFD,0xF3,0xFF, +0xDF,0xFD,0xFF,0x5F,0xDF,0xF5,0xFD,0xFF, 0xFF,0xF9,0x8F,0xFF,0xFF,0xFF,0xEE,0x7F, +0xFF,0xFF,0xBF,0x5E,0xFE,0xEC,0xFB,0x3F, 0x7F,0x9F,0xEF,0xF9,0xFF,0xFF,0xCD,0x6B, +0xFF,0xFF,0xFF,0xC5,0xF3,0xFC,0xFA,0x38, 0xFF,0xAF,0x3F,0xEE,0x7F,0x9F,0xFF,0xD9, +0xFF,0xFF,0xFD,0x7A,0xF7,0xFF,0xF3,0xFF, 0xAF,0x6F,0xDB,0xF2,0xB9,0xE9,0xFB,0xFF, +0xFF,0xFF,0xFE,0xFF,0xFF,0xEF,0xFF,0xFB, 0xC5,0xBF,0xFF,0xEF,0xFF,0x5E,0xB7,0xAD, +0xCD,0x79,0x7C,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0x93,0xFF,0xEF, +0xEA,0xFE,0xBF,0xEF,0x5B,0xD2,0xCD,0xF5, 0x6D,0x77,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF, +0xFF,0xFF,0x66,0xFF,0xD5,0x65,0x7D,0x5F, 0x75,0x9D,0x65,0x7F,0xD6,0xFB,0x4F,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xC7, 0xFF,0xBF,0xEF,0xFA,0xFE,0xFF,0xBF,0xEB, +0xFF,0xDF,0xFF,0x7E,0xFF,0xFF,0xEF,0xFD, 0x7E,0xD7,0xFF,0x78,0xDF,0xFF,0x5F,0xDF, +0xF5,0xBF,0x7F,0xDF,0xC5,0xFF,0x3F,0xF6, 0x7E,0xFF,0x0F,0xEF,0xF2,0x3E,0xBF,0xFF, +0xFB,0x3F,0xFF,0xFB,0x7F,0xFF,0xB3,0xFE, 0xFB,0xF6,0xFD,0xFF,0xDA,0xF7,0xFD,0xFF, +0x7F,0xDF,0xF7,0xBF,0xFF,0xFA,0x7F,0xFF, 0xFF,0xFF,0xFF,0x9F,0xFF,0xF3,0xDC,0xF9, +0xBF,0xCE,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7, 0xFF,0xFF,0xE2,0x7F,0xFE,0xFF,0xBF,0xEF, +0xEB,0xFA,0xFF,0x9F,0x67,0x1E,0xFF,0x8F, 0xE7,0xF8,0xFE,0x7F,0x8F,0xEF,0xFF,0xBD, +0xBF,0xFF,0xFB,0xFF,0xFF,0xDF,0xF7,0xFF, 0xFC,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFD,0xB3,0xFF,0xFF,0xEF, 0xFF,0xFF,0xBF,0xED,0xFF,0xFB,0xEE,0xFE, +0xFF,0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF, 0xFF,0xB5,0xFF,0xB7,0xFD,0xFD,0x6E,0xFF, +0xFF,0xFE,0xFD,0x2F,0xD8,0xFE,0xBF,0x8F, 0xEB,0xF9,0xFE,0x3F,0xFF,0xFA,0xCF,0xFF, +0xE7,0xD9,0xFA,0xBF,0xDF,0x77,0xFC,0xFB, 0x3F,0xAB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFE, +0xFF,0xFF,0xEE,0x1F,0xFF,0xDF,0xF7,0xFF, 0xFF,0xFF,0x5F,0x97,0x35,0xBF,0x5E,0xFE, +0xBF,0xEF,0xFF,0xF7,0xFD,0xFF,0xFF,0xFA, 0xBF,0xFF,0xBE,0x6F,0x9F,0xE7,0xF8,0xBE, +0x2F,0x8B,0x66,0x94,0x7D,0x9D,0xE7,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF,0xFF, +0xFF,0xF7,0xF5,0xFD,0x7F,0x5F,0xFB,0xFD, 0x9E,0xFF,0xFB,0xFE,0xFF,0xFF,0xEF,0xFF, +0xFF,0xA0,0xFF,0xFF,0xFF,0xBF,0xEF,0xEB, 0xFA,0xFE,0xBF,0xB7,0xF7,0xF7,0xFF,0xFF, +0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, 0xFD,0xFF,0xFF,0xFF,0xD7,0xFF,0xFF,0xFF, +0x7F,0xF5,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF, 0xBF,0xFF,0xFF,0xAB,0xFE,0xFB,0xFE,0xFF, +0xF7,0xAF,0xFF,0xFF,0xDE,0xF7,0xEB,0x5F, 0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF,0xFF, +0xB3,0xFF,0xC9,0xFE,0xFF,0xFF,0xFF,0xFF, 0xD6,0xFF,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFC,0x8F,0xFF,0xBA, 0xBE,0xBF,0xAF,0xEB,0x78,0xFE,0xB7,0xAD, +0x3A,0xFE,0xB7,0xAF,0xEB,0x7A,0xFE,0xBF, 0xAF,0xFF,0x9F,0xFF,0xFF,0xDF,0xFC,0xFF, +0xFF,0xFE,0xC3,0xFE,0xFF,0xFF,0x33,0xFC, 0xFF,0xBF,0xDF,0xF3,0xFF,0xFF,0xBB,0x9F, +0xFF,0xFF,0xFF,0xEB,0xDF,0xFF,0xFF,0xAF, 0xF7,0x6F,0xF9,0xBF,0xEF,0xFD,0xFF,0xFF, +0xFF,0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF, 0xFB,0xFF,0xFF,0xBF,0xFD,0xFB,0xF7,0xFF, +0xDF,0xF7,0xFF,0xFE,0xEF,0x5F,0xBD,0xFF, 0xFA,0xFF,0xF8,0xFF,0xBF,0xAF,0xFB,0xFE, +0xFE,0x3F,0xEF,0xE8,0xFF,0xDF,0xF3,0xFD, 0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xFB, +0xFD,0xFF,0xAF,0xFF,0xFF,0xFE,0xFE,0xBF, 0xDB,0xFF,0xFF,0xFF,0xBF,0xFF,0xDF,0xFF, +0xFD,0xFF,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF, 0xBF,0x6F,0xFF,0x7F,0xB7,0xB3,0xFF,0xFF, +0xDF,0xFF,0xFB,0xEF,0xFF,0xFF,0xFF,0x07, 0xFF,0xFB,0xFF,0xFF,0xFF,0xED,0xFF,0xF5, +0x7C,0xFF,0x7F,0xFE,0xFF,0xFF,0xEF,0xCF, 0xFF,0xFB,0xFF,0xFF,0x2F,0xFF,0xFF,0xFF, +0xFF,0xF3,0xFF,0xFB,0xFF,0xFE,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, +0xFD,0x1B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFE,0x7C,0xFF,0xFF,0xFF,0xFF, +0xEF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0x7F, 0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, 0xFF,0xFF,0xF0,0x7F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xDF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xFE, +0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xEF,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xEF,0xFA,0xB5,0xFF,0xFF,0xFF, 0xF7,0xF7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFB, +0xFC,0xFF,0xFF,0xFE,0xFF,0x7F,0xDF,0xBF, 0xFF,0xCB,0xBF,0xF9,0xFE,0x7F,0x9F,0xE7, +0xF9,0xFE,0x7F,0x97,0xE1,0xFE,0x79,0x9F, 0xE7,0xFD,0xFE,0x7F,0xDF,0xFE,0x37,0xFF, +0xFB,0xDE,0xDE,0xBD,0xEF,0xF3,0xFE,0xFB, 0xAF,0xEB,0xFE,0xFF,0xFF,0xCF,0xFF,0xFE, +0xFF,0xBF,0xFF,0x8F,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xE7,0xF9,0x5E,0x7F,0xEF,0xFB, +0xDA,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD, 0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF, +0xFF,0xFF,0x7F,0xFF,0xFF,0xF7,0xFB,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFC,0x3F,0xFF,0xBF, +0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0x7B,0x7F, 0xBF,0xEF,0xFB,0xFE,0xFF,0xB5,0xEF,0xFB, +0xBF,0xFA,0x7F,0xFC,0xFF,0x3F,0xCF,0xF3, 0xFC,0xFF,0x3F,0xCF,0xBC,0xFF,0x3F,0xEF, +0xF3,0xFC,0xFE,0x3F,0xCF,0xFF,0xEE,0xEF, 0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0x6A,0xD7, +0xB7,0xFB,0xF8,0xFF,0xB7,0xEF,0xBA,0xFE, 0xFF,0xBF,0x7F,0xE9,0xFF,0xF9,0x7E,0x5F, +0x97,0xE5,0xF9,0xFE,0x7F,0xBF,0xF9,0x7E, 0x5F,0x9F,0xE5,0xFB,0xFE,0x5F,0xB7,0xFF, +0xA3,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0x5E,0xF7,0x7D,0xFF,0x77,0xDF, +0xF7,0xFD,0xFF,0x7F,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xDF,0xFB,0x7F, +0xFF,0xFF,0xEF,0xFF,0xFE,0xFB,0xFF,0xFF, 0xBF,0xFE,0x8F,0xFF,0xDF,0xF7,0xFD,0xFD, +0x7F,0xDF,0xF7,0xFD,0x3E,0xDF,0xF5,0xBD, 0xFF,0x7F,0xDF,0xF7,0xFD,0xF7,0xFF,0x9F, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFD,0xFF,0xBE,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFD,0x3F,0xFF,0xDF,0xF7, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xCF, +0x77,0xFC,0xFF,0x5F,0xDF,0xF7,0xFD,0xFF, 0xF4,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFD,0xFF,0xFF,0xFF,0xEE,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xED,0xFB,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xE9,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFB,0xFF,0xFF,0xFF,0xD3,0xFF,0xFF, +0xBF,0x3F,0xFB,0xFF,0xFF,0xFF,0xFB,0xF3, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xF7, 0xFF,0xFF,0xFF,0xFF,0x17,0xFF,0xFF,0xFF, +0xDF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF, 0xDF,0xDF,0xFF,0xFD,0xFF,0xFF,0xDF,0xF7, +0xFF,0x4F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD, +0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0x9F,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF, 0xFF,0xFF,0x7A,0x3F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2, +0x7F,0xFF,0xFB,0xFE,0xFF,0xBF,0xEF,0xF8, 0xFE,0xFF,0xBF,0xFB,0xFE,0xFF,0x8F,0xEC, +0xFB,0xFE,0xFF,0xBF,0xF8,0xF7,0xFE,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFD,0xBF,0xCF,0xEC, +0xFF,0x3F,0xEF,0xDB,0xF8,0xFF,0xBF,0xCF, 0xFF,0xF9,0xFF,0xFF,0xBF,0xFF,0xFB,0xFF, +0xFF,0xFF,0xEF,0xFB,0xDF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xBB,0xFF, +0xEF,0xFB,0xFE,0xEF,0xBF,0xEE,0xEB,0xFB, 0xFE,0xFF,0xEF,0xFE,0xEE,0xBF,0xFE,0xEB, +0xFF,0xEF,0xFF,0x17,0xFF,0x7E,0xEB,0xBB, 0xFE,0xBF,0xBE,0xFB,0xEF,0x5B,0xF7,0xBD, +0xFB,0xCF,0xBF,0xBF,0xBB,0xFB,0x7E,0xCC, 0xEF,0xFF + +}; diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c new file mode 100644 index 000000000000..1774ab7a40d2 --- /dev/null +++ b/drivers/media/video/dabusb.c @@ -0,0 +1,874 @@ +/*****************************************************************************/ + +/* + * dabusb.c -- dab usb driver. + * + * Copyright (C) 1999 Deti Fliegl (deti@fliegl.de) + * + * 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. + * + * + * + * $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $ + * + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dabusb.h" +#include "dabfirmware.h" + +/* + * Version Information + */ +#define DRIVER_VERSION "v1.54" +#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de" +#define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999" + +/* --------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_DYNAMIC_MINORS +#define NRDABUSB 256 +#else +#define NRDABUSB 4 +#endif + +/*-------------------------------------------------------------------*/ + +static dabusb_t dabusb[NRDABUSB]; +static int buffers = 256; +static struct usb_driver dabusb_driver; + +/*-------------------------------------------------------------------*/ + +static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src) +{ + unsigned long flags; + struct list_head *tmp; + int ret = 0; + + spin_lock_irqsave (&s->lock, flags); + + if (list_empty (src)) { + // no elements in source buffer + ret = -1; + goto err; + } + tmp = src->next; + list_move_tail (tmp, dst); + + err: spin_unlock_irqrestore (&s->lock, flags); + return ret; +} +/*-------------------------------------------------------------------*/ +#ifdef DEBUG +static void dump_urb (struct urb *urb) +{ + dbg("urb :%p", urb); + dbg("dev :%p", urb->dev); + dbg("pipe :%08X", urb->pipe); + dbg("status :%d", urb->status); + dbg("transfer_flags :%08X", urb->transfer_flags); + dbg("transfer_buffer :%p", urb->transfer_buffer); + dbg("transfer_buffer_length:%d", urb->transfer_buffer_length); + dbg("actual_length :%d", urb->actual_length); + dbg("setup_packet :%p", urb->setup_packet); + dbg("start_frame :%d", urb->start_frame); + dbg("number_of_packets :%d", urb->number_of_packets); + dbg("interval :%d", urb->interval); + dbg("error_count :%d", urb->error_count); + dbg("context :%p", urb->context); + dbg("complete :%p", urb->complete); +} +#endif +/*-------------------------------------------------------------------*/ +static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q) +{ + unsigned long flags; + pbuff_t b; + + dbg("dabusb_cancel_queue"); + + spin_lock_irqsave (&s->lock, flags); + + list_for_each_entry(b, q, buff_list) { +#ifdef DEBUG + dump_urb(b->purb); +#endif + usb_unlink_urb (b->purb); + } + spin_unlock_irqrestore (&s->lock, flags); + return 0; +} +/*-------------------------------------------------------------------*/ +static int dabusb_free_queue (struct list_head *q) +{ + struct list_head *tmp; + struct list_head *p; + pbuff_t b; + + dbg("dabusb_free_queue"); + for (p = q->next; p != q;) { + b = list_entry (p, buff_t, buff_list); + +#ifdef DEBUG + dump_urb(b->purb); +#endif + kfree(b->purb->transfer_buffer); + usb_free_urb(b->purb); + tmp = p->next; + list_del (p); + kfree (b); + p = tmp; + } + + return 0; +} +/*-------------------------------------------------------------------*/ +static int dabusb_free_buffers (pdabusb_t s) +{ + unsigned long flags; + dbg("dabusb_free_buffers"); + + spin_lock_irqsave(&s->lock, flags); + + dabusb_free_queue (&s->free_buff_list); + dabusb_free_queue (&s->rec_buff_list); + + spin_unlock_irqrestore(&s->lock, flags); + + s->got_mem = 0; + return 0; +} +/*-------------------------------------------------------------------*/ +static void dabusb_iso_complete (struct urb *purb, struct pt_regs *regs) +{ + pbuff_t b = purb->context; + pdabusb_t s = b->s; + int i; + int len; + int dst = 0; + void *buf = purb->transfer_buffer; + + dbg("dabusb_iso_complete"); + + // process if URB was not killed + if (purb->status != -ENOENT) { + unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE); + int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe)); + for (i = 0; i < purb->number_of_packets; i++) + if (!purb->iso_frame_desc[i].status) { + len = purb->iso_frame_desc[i].actual_length; + if (len <= pipesize) { + memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len); + dst += len; + } + else + err("dabusb_iso_complete: invalid len %d", len); + } + else + warn("dabusb_iso_complete: corrupted packet status: %d", purb->iso_frame_desc[i].status); + if (dst != purb->actual_length) + err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length); + } + + if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) { + s->overruns++; + err("overrun (%d)", s->overruns); + } + wake_up (&s->wait); +} +/*-------------------------------------------------------------------*/ +static int dabusb_alloc_buffers (pdabusb_t s) +{ + int buffers = 0; + pbuff_t b; + unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE); + int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe)); + int packets = _ISOPIPESIZE / pipesize; + int transfer_buffer_length = packets * pipesize; + int i; + + dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d", + pipesize, packets, transfer_buffer_length); + + while (buffers < (s->total_buffer_size << 10)) { + b = (pbuff_t) kzalloc (sizeof (buff_t), GFP_KERNEL); + if (!b) { + err("kzalloc(sizeof(buff_t))==NULL"); + goto err; + } + b->s = s; + b->purb = usb_alloc_urb(packets, GFP_KERNEL); + if (!b->purb) { + err("usb_alloc_urb == NULL"); + kfree (b); + goto err; + } + + b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL); + if (!b->purb->transfer_buffer) { + kfree (b->purb); + kfree (b); + err("kmalloc(%d)==NULL", transfer_buffer_length); + goto err; + } + + b->purb->transfer_buffer_length = transfer_buffer_length; + b->purb->number_of_packets = packets; + b->purb->complete = dabusb_iso_complete; + b->purb->context = b; + b->purb->dev = s->usbdev; + b->purb->pipe = pipe; + b->purb->transfer_flags = URB_ISO_ASAP; + + for (i = 0; i < packets; i++) { + b->purb->iso_frame_desc[i].offset = i * pipesize; + b->purb->iso_frame_desc[i].length = pipesize; + } + + buffers += transfer_buffer_length; + list_add_tail (&b->buff_list, &s->free_buff_list); + } + s->got_mem = buffers; + + return 0; + + err: + dabusb_free_buffers (s); + return -ENOMEM; +} +/*-------------------------------------------------------------------*/ +static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) +{ + int ret; + unsigned int pipe; + int actual_length; + + dbg("dabusb_bulk"); + + if (!pb->pipe) + pipe = usb_rcvbulkpipe (s->usbdev, 2); + else + pipe = usb_sndbulkpipe (s->usbdev, 2); + + ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100); + if(ret<0) { + err("dabusb: usb_bulk_msg failed(%d)",ret); + + if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { + err("set_interface failed"); + return -EINVAL; + } + + } + + if( ret == -EPIPE ) { + warn("CLEAR_FEATURE request to remove STALL condition."); + if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) + err("request failed"); + } + + pb->size = actual_length; + return ret; +} +/* --------------------------------------------------------------------- */ +static int dabusb_writemem (pdabusb_t s, int pos, unsigned char *data, int len) +{ + int ret; + unsigned char *transfer_buffer = kmalloc (len, GFP_KERNEL); + + if (!transfer_buffer) { + err("dabusb_writemem: kmalloc(%d) failed.", len); + return -ENOMEM; + } + + memcpy (transfer_buffer, data, len); + + ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300); + + kfree (transfer_buffer); + return ret; +} +/* --------------------------------------------------------------------- */ +static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit) +{ + dbg("dabusb_8051_reset: %d",reset_bit); + return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1); +} +/* --------------------------------------------------------------------- */ +static int dabusb_loadmem (pdabusb_t s, const char *fname) +{ + int ret; + PINTEL_HEX_RECORD ptr = firmware; + + dbg("Enter dabusb_loadmem (internal)"); + + ret = dabusb_8051_reset (s, 1); + while (ptr->Type == 0) { + + dbg("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length); + + ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length); + if (ret < 0) { + err("dabusb_writemem failed (%d %04X %p %d)", ret, ptr->Address, ptr->Data, ptr->Length); + break; + } + ptr++; + } + ret = dabusb_8051_reset (s, 0); + + dbg("dabusb_loadmem: exit"); + + return ret; +} +/* --------------------------------------------------------------------- */ +static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b) +{ + b->size = 4; + b->data[0] = 0x2a; + b->data[1] = 0; + b->data[2] = 0; + b->data[3] = 0; + + dbg("dabusb_fpga_clear"); + + return dabusb_bulk (s, b); +} +/* --------------------------------------------------------------------- */ +static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b) +{ + b->size = 4; + b->data[0] = 0x2c; + b->data[1] = 0; + b->data[2] = 0; + b->data[3] = 0; + + dbg("dabusb_fpga_init"); + + return dabusb_bulk (s, b); +} +/* --------------------------------------------------------------------- */ +static int dabusb_fpga_download (pdabusb_t s, const char *fname) +{ + pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL); + unsigned int blen, n; + int ret; + unsigned char *buf = bitstream; + + dbg("Enter dabusb_fpga_download (internal)"); + + if (!b) { + err("kmalloc(sizeof(bulk_transfer_t))==NULL"); + return -ENOMEM; + } + + b->pipe = 1; + ret = dabusb_fpga_clear (s, b); + mdelay (10); + blen = buf[73] + (buf[72] << 8); + + dbg("Bitstream len: %i", blen); + + b->data[0] = 0x2b; + b->data[1] = 0; + b->data[2] = 0; + b->data[3] = 60; + + for (n = 0; n <= blen + 60; n += 60) { + // some cclks for startup + b->size = 64; + memcpy (b->data + 4, buf + 74 + n, 60); + ret = dabusb_bulk (s, b); + if (ret < 0) { + err("dabusb_bulk failed."); + break; + } + mdelay (1); + } + + ret = dabusb_fpga_init (s, b); + kfree (b); + + dbg("exit dabusb_fpga_download"); + + return ret; +} + +static int dabusb_stop (pdabusb_t s) +{ + dbg("dabusb_stop"); + + s->state = _stopped; + dabusb_cancel_queue (s, &s->rec_buff_list); + + dbg("pending_io: %d", s->pending_io.counter); + + s->pending_io.counter = 0; + return 0; +} + +static int dabusb_startrek (pdabusb_t s) +{ + if (!s->got_mem && s->state != _started) { + + dbg("dabusb_startrek"); + + if (dabusb_alloc_buffers (s) < 0) + return -ENOMEM; + dabusb_stop (s); + s->state = _started; + s->readptr = 0; + } + + if (!list_empty (&s->free_buff_list)) { + pbuff_t end; + int ret; + + while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) { + + dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list); + + end = list_entry (s->rec_buff_list.prev, buff_t, buff_list); + + ret = usb_submit_urb (end->purb, GFP_KERNEL); + if (ret) { + err("usb_submit_urb returned:%d", ret); + if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) + err("startrek: dabusb_add_buf_tail failed"); + break; + } + else + atomic_inc (&s->pending_io); + } + dbg("pending_io: %d",s->pending_io.counter); + } + + return 0; +} + +static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, loff_t * ppos) +{ + pdabusb_t s = (pdabusb_t) file->private_data; + unsigned long flags; + unsigned ret = 0; + int rem; + int cnt; + pbuff_t b; + struct urb *purb = NULL; + + dbg("dabusb_read"); + + if (*ppos) + return -ESPIPE; + + if (s->remove_pending) + return -EIO; + + + if (!s->usbdev) + return -EIO; + + while (count > 0) { + dabusb_startrek (s); + + spin_lock_irqsave (&s->lock, flags); + + if (list_empty (&s->rec_buff_list)) { + + spin_unlock_irqrestore(&s->lock, flags); + + err("error: rec_buf_list is empty"); + goto err; + } + + b = list_entry (s->rec_buff_list.next, buff_t, buff_list); + purb = b->purb; + + spin_unlock_irqrestore(&s->lock, flags); + + if (purb->status == -EINPROGRESS) { + if (file->f_flags & O_NONBLOCK) // return nonblocking + { + if (!ret) + ret = -EAGAIN; + goto err; + } + + interruptible_sleep_on (&s->wait); + + if (signal_pending (current)) { + if (!ret) + ret = -ERESTARTSYS; + goto err; + } + + spin_lock_irqsave (&s->lock, flags); + + if (list_empty (&s->rec_buff_list)) { + spin_unlock_irqrestore(&s->lock, flags); + err("error: still no buffer available."); + goto err; + } + spin_unlock_irqrestore(&s->lock, flags); + s->readptr = 0; + } + if (s->remove_pending) { + ret = -EIO; + goto err; + } + + rem = purb->actual_length - s->readptr; // set remaining bytes to copy + + if (count >= rem) + cnt = rem; + else + cnt = count; + + dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt); + + if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) { + err("read: copy_to_user failed"); + if (!ret) + ret = -EFAULT; + goto err; + } + + s->readptr += cnt; + count -= cnt; + buf += cnt; + ret += cnt; + + if (s->readptr == purb->actual_length) { + // finished, take next buffer + if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) + err("read: dabusb_add_buf_tail failed"); + s->readptr = 0; + } + } + err: //mutex_unlock(&s->mutex); + return ret; +} + +static int dabusb_open (struct inode *inode, struct file *file) +{ + int devnum = iminor(inode); + pdabusb_t s; + + if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB)) + return -EIO; + + s = &dabusb[devnum - DABUSB_MINOR]; + + dbg("dabusb_open"); + mutex_lock(&s->mutex); + + while (!s->usbdev || s->opened) { + mutex_unlock(&s->mutex); + + if (file->f_flags & O_NONBLOCK) { + return -EBUSY; + } + msleep_interruptible(500); + + if (signal_pending (current)) { + return -EAGAIN; + } + mutex_lock(&s->mutex); + } + if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { + mutex_unlock(&s->mutex); + err("set_interface failed"); + return -EINVAL; + } + s->opened = 1; + mutex_unlock(&s->mutex); + + file->f_pos = 0; + file->private_data = s; + + return nonseekable_open(inode, file); +} + +static int dabusb_release (struct inode *inode, struct file *file) +{ + pdabusb_t s = (pdabusb_t) file->private_data; + + dbg("dabusb_release"); + + mutex_lock(&s->mutex); + dabusb_stop (s); + dabusb_free_buffers (s); + mutex_unlock(&s->mutex); + + if (!s->remove_pending) { + if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) + err("set_interface failed"); + } + else + wake_up (&s->remove_ok); + + s->opened = 0; + return 0; +} + +static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + pdabusb_t s = (pdabusb_t) file->private_data; + pbulk_transfer_t pbulk; + int ret = 0; + int version = DABUSB_VERSION; + + dbg("dabusb_ioctl"); + + if (s->remove_pending) + return -EIO; + + mutex_lock(&s->mutex); + + if (!s->usbdev) { + mutex_unlock(&s->mutex); + return -EIO; + } + + switch (cmd) { + + case IOCTL_DAB_BULK: + pbulk = (pbulk_transfer_t) kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL); + + if (!pbulk) { + ret = -ENOMEM; + break; + } + + if (copy_from_user (pbulk, (void __user *) arg, sizeof (bulk_transfer_t))) { + ret = -EFAULT; + kfree (pbulk); + break; + } + + ret=dabusb_bulk (s, pbulk); + if(ret==0) + if (copy_to_user((void __user *)arg, pbulk, + sizeof(bulk_transfer_t))) + ret = -EFAULT; + kfree (pbulk); + break; + + case IOCTL_DAB_OVERRUNS: + ret = put_user (s->overruns, (unsigned int __user *) arg); + break; + + case IOCTL_DAB_VERSION: + ret = put_user (version, (unsigned int __user *) arg); + break; + + default: + ret = -ENOIOCTLCMD; + break; + } + mutex_unlock(&s->mutex); + return ret; +} + +static struct file_operations dabusb_fops = +{ + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = dabusb_read, + .ioctl = dabusb_ioctl, + .open = dabusb_open, + .release = dabusb_release, +}; + +static struct usb_class_driver dabusb_class = { + .name = "dabusb%d", + .fops = &dabusb_fops, + .minor_base = DABUSB_MINOR, +}; + + +/* --------------------------------------------------------------------- */ +static int dabusb_probe (struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *usbdev = interface_to_usbdev(intf); + int retval; + pdabusb_t s; + + dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d", + le16_to_cpu(usbdev->descriptor.idVendor), + le16_to_cpu(usbdev->descriptor.idProduct), + intf->altsetting->desc.bInterfaceNumber); + + /* We don't handle multiple configurations */ + if (usbdev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && + le16_to_cpu(usbdev->descriptor.idProduct) == 0x9999) + return -ENODEV; + + + + s = &dabusb[intf->minor]; + + mutex_lock(&s->mutex); + s->remove_pending = 0; + s->usbdev = usbdev; + s->devnum = intf->minor; + + if (usb_reset_configuration (usbdev) < 0) { + err("reset_configuration failed"); + goto reject; + } + if (le16_to_cpu(usbdev->descriptor.idProduct) == 0x2131) { + dabusb_loadmem (s, NULL); + goto reject; + } + else { + dabusb_fpga_download (s, NULL); + + if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) { + err("set_interface failed"); + goto reject; + } + } + dbg("bound to interface: %d", intf->altsetting->desc.bInterfaceNumber); + usb_set_intfdata (intf, s); + mutex_unlock(&s->mutex); + + retval = usb_register_dev(intf, &dabusb_class); + if (retval) { + usb_set_intfdata (intf, NULL); + return -ENOMEM; + } + + return 0; + + reject: + mutex_unlock(&s->mutex); + s->usbdev = NULL; + return -ENODEV; +} + +static void dabusb_disconnect (struct usb_interface *intf) +{ + wait_queue_t __wait; + pdabusb_t s = usb_get_intfdata (intf); + + dbg("dabusb_disconnect"); + + init_waitqueue_entry(&__wait, current); + + usb_set_intfdata (intf, NULL); + if (s) { + usb_deregister_dev (intf, &dabusb_class); + s->remove_pending = 1; + wake_up (&s->wait); + add_wait_queue(&s->remove_ok, &__wait); + set_current_state(TASK_UNINTERRUPTIBLE); + if (s->state == _started) + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&s->remove_ok, &__wait); + + s->usbdev = NULL; + s->overruns = 0; + } +} + +static struct usb_device_id dabusb_ids [] = { + // { USB_DEVICE(0x0547, 0x2131) }, /* An2131 chip, no boot ROM */ + { USB_DEVICE(0x0547, 0x9999) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, dabusb_ids); + +static struct usb_driver dabusb_driver = { + .name = "dabusb", + .probe = dabusb_probe, + .disconnect = dabusb_disconnect, + .id_table = dabusb_ids, +}; + +/* --------------------------------------------------------------------- */ + +static int __init dabusb_init (void) +{ + int retval; + unsigned u; + + /* initialize struct */ + for (u = 0; u < NRDABUSB; u++) { + pdabusb_t s = &dabusb[u]; + memset (s, 0, sizeof (dabusb_t)); + mutex_init (&s->mutex); + s->usbdev = NULL; + s->total_buffer_size = buffers; + init_waitqueue_head (&s->wait); + init_waitqueue_head (&s->remove_ok); + spin_lock_init (&s->lock); + INIT_LIST_HEAD (&s->free_buff_list); + INIT_LIST_HEAD (&s->rec_buff_list); + } + + /* register misc device */ + retval = usb_register(&dabusb_driver); + if (retval) + goto out; + + dbg("dabusb_init: driver registered"); + + info(DRIVER_VERSION ":" DRIVER_DESC); + +out: + return retval; +} + +static void __exit dabusb_cleanup (void) +{ + dbg("dabusb_cleanup"); + + usb_deregister (&dabusb_driver); +} + +/* --------------------------------------------------------------------- */ + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); + +module_param(buffers, int, 0); +MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); + +module_init (dabusb_init); +module_exit (dabusb_cleanup); + +/* --------------------------------------------------------------------- */ diff --git a/drivers/media/video/dabusb.h b/drivers/media/video/dabusb.h new file mode 100644 index 000000000000..96b03e4af8b9 --- /dev/null +++ b/drivers/media/video/dabusb.h @@ -0,0 +1,85 @@ +#define _BULK_DATA_LEN 64 +typedef struct +{ + unsigned char data[_BULK_DATA_LEN]; + unsigned int size; + unsigned int pipe; +}bulk_transfer_t,*pbulk_transfer_t; + +#define DABUSB_MINOR 240 /* some unassigned USB minor */ +#define DABUSB_VERSION 0x1000 +#define IOCTL_DAB_BULK _IOWR('d', 0x30, bulk_transfer_t) +#define IOCTL_DAB_OVERRUNS _IOR('d', 0x15, int) +#define IOCTL_DAB_VERSION _IOR('d', 0x3f, int) + +#ifdef __KERNEL__ + +typedef enum { _stopped=0, _started } driver_state_t; + +typedef struct +{ + struct mutex mutex; + struct usb_device *usbdev; + wait_queue_head_t wait; + wait_queue_head_t remove_ok; + spinlock_t lock; + atomic_t pending_io; + driver_state_t state; + int remove_pending; + int got_mem; + int total_buffer_size; + unsigned int overruns; + int readptr; + int opened; + int devnum; + struct list_head free_buff_list; + struct list_head rec_buff_list; +} dabusb_t,*pdabusb_t; + +typedef struct +{ + pdabusb_t s; + struct urb *purb; + struct list_head buff_list; +} buff_t,*pbuff_t; + +typedef struct +{ + wait_queue_head_t wait; +} bulk_completion_context_t, *pbulk_completion_context_t; + + +#define _DABUSB_IF 2 +#define _DABUSB_ISOPIPE 0x09 +#define _ISOPIPESIZE 16384 + +#define _BULK_DATA_LEN 64 +// Vendor specific request code for Anchor Upload/Download +// This one is implemented in the core +#define ANCHOR_LOAD_INTERNAL 0xA0 + +// EZ-USB Control and Status Register. Bit 0 controls 8051 reset +#define CPUCS_REG 0x7F92 +#define _TOTAL_BUFFERS 384 + +#define MAX_INTEL_HEX_RECORD_LENGTH 16 + +#ifndef _BYTE_DEFINED +#define _BYTE_DEFINED +typedef unsigned char BYTE; +#endif // !_BYTE_DEFINED + +#ifndef _WORD_DEFINED +#define _WORD_DEFINED +typedef unsigned short WORD; +#endif // !_WORD_DEFINED + +typedef struct _INTEL_HEX_RECORD +{ + BYTE Length; + WORD Address; + BYTE Type; + BYTE Data[MAX_INTEL_HEX_RECORD_LENGTH]; +} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD; + +#endif diff --git a/drivers/media/video/dsbr100.c b/drivers/media/video/dsbr100.c new file mode 100644 index 000000000000..25646804d5be --- /dev/null +++ b/drivers/media/video/dsbr100.c @@ -0,0 +1,429 @@ +/* A driver for the D-Link DSB-R100 USB radio. The R100 plugs + into both the USB and an analog audio input, so this thing + only deals with initialisation and frequency setting, the + audio data has to be handled by a sound driver. + + Major issue: I can't find out where the device reports the signal + strength, and indeed the windows software appearantly just looks + at the stereo indicator as well. So, scanning will only find + stereo stations. Sad, but I can't help it. + + Also, the windows program sends oodles of messages over to the + device, and I couldn't figure out their meaning. My suspicion + is that they don't have any:-) + + You might find some interesting stuff about this module at + http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr + + Copyright (c) 2000 Markus Demleitner + + 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 + + History: + + Version 0.40: + Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing + + Version 0.30: + Markus: Updates for 2.5.x kernel and more ISO compliant source + + Version 0.25: + PSL and Markus: Cleanup, radio now doesn't stop on device close + + Version 0.24: + Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally + right. Some minor cleanup, improved standalone compilation + + Version 0.23: + Markus: Sign extension bug fixed by declaring transfer_buffer unsigned + + Version 0.22: + Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns, + thanks to Mike Cox for pointing the problem out. + + Version 0.21: + Markus: Minor cleanup, warnings if something goes wrong, lame attempt + to adhere to Documentation/CodingStyle + + Version 0.2: + Brad Hards : Fixes to make it work as non-module + Markus: Copyright clarification + + Version 0.01: Markus: initial release + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Version Information + */ +#define DRIVER_VERSION "v0.40" +#define DRIVER_AUTHOR "Markus Demleitner " +#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" + +#define DSB100_VENDOR 0x04b4 +#define DSB100_PRODUCT 0x1002 + +/* Commands the device appears to understand */ +#define DSB100_TUNE 1 +#define DSB100_ONOFF 2 + +#define TB_LEN 16 + +/* Frequency limits in MHz -- these are European values. For Japanese +devices, that would be 76 and 91. */ +#define FREQ_MIN 87.5 +#define FREQ_MAX 108.0 +#define FREQ_MUL 16000 + + +static int usb_dsbr100_probe(struct usb_interface *intf, + const struct usb_device_id *id); +static void usb_dsbr100_disconnect(struct usb_interface *intf); +static int usb_dsbr100_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +static int usb_dsbr100_open(struct inode *inode, struct file *file); +static int usb_dsbr100_close(struct inode *inode, struct file *file); + +static int radio_nr = -1; +module_param(radio_nr, int, 0); + +/* Data for one (physical) device */ +typedef struct { + struct usb_device *usbdev; + struct video_device *videodev; + unsigned char transfer_buffer[TB_LEN]; + int curfreq; + int stereo; + int users; + int removed; +} dsbr100_device; + + +/* File system interface */ +static struct file_operations usb_dsbr100_fops = { + .owner = THIS_MODULE, + .open = usb_dsbr100_open, + .release = usb_dsbr100_close, + .ioctl = usb_dsbr100_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .llseek = no_llseek, +}; + +/* V4L interface */ +static struct video_device dsbr100_videodev_template= +{ + .owner = THIS_MODULE, + .name = "D-Link DSB-R 100", + .type = VID_TYPE_TUNER, + .hardware = VID_HARDWARE_AZTECH, + .fops = &usb_dsbr100_fops, + .release = video_device_release, +}; + +static struct usb_device_id usb_dsbr100_device_table [] = { + { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table); + +/* USB subsystem interface */ +static struct usb_driver usb_dsbr100_driver = { + .name = "dsbr100", + .probe = usb_dsbr100_probe, + .disconnect = usb_dsbr100_disconnect, + .id_table = usb_dsbr100_device_table, +}; + +/* Low-level device interface begins here */ + +/* switch on radio */ +static int dsbr100_start(dsbr100_device *radio) +{ + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_ONOFF, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x01, 0x00, radio->transfer_buffer, 8, 300)<0) + return -1; + return (radio->transfer_buffer)[0]; +} + + +/* switch off radio */ +static int dsbr100_stop(dsbr100_device *radio) +{ + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_ONOFF, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0x00, radio->transfer_buffer, 8, 300)<0) + return -1; + return (radio->transfer_buffer)[0]; +} + +/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ +static int dsbr100_setfreq(dsbr100_device *radio, int freq) +{ + freq = (freq/16*80)/1000+856; + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_TUNE, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + (freq>>8)&0x00ff, freq&0xff, + radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) { + radio->stereo = -1; + return -1; + } + radio->stereo = ! ((radio->transfer_buffer)[0]&0x01); + return (radio->transfer_buffer)[0]; +} + +/* return the device status. This is, in effect, just whether it +sees a stereo signal or not. Pity. */ +static void dsbr100_getstat(dsbr100_device *radio) +{ + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0) + radio->stereo = -1; + else + radio->stereo = ! (radio->transfer_buffer[0]&0x01); +} + + +/* USB subsystem interface begins here */ + +/* check if the device is present and register with v4l and +usb if it is */ +static int usb_dsbr100_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + dsbr100_device *radio; + + if (!(radio = kmalloc(sizeof(dsbr100_device), GFP_KERNEL))) + return -ENOMEM; + if (!(radio->videodev = video_device_alloc())) { + kfree(radio); + return -ENOMEM; + } + memcpy(radio->videodev, &dsbr100_videodev_template, + sizeof(dsbr100_videodev_template)); + radio->removed = 0; + radio->users = 0; + radio->usbdev = interface_to_usbdev(intf); + radio->curfreq = FREQ_MIN*FREQ_MUL; + video_set_drvdata(radio->videodev, radio); + if (video_register_device(radio->videodev, VFL_TYPE_RADIO, + radio_nr)) { + warn("Could not register video device"); + video_device_release(radio->videodev); + kfree(radio); + return -EIO; + } + usb_set_intfdata(intf, radio); + return 0; +} + +/* handle unplugging of the device, release data structures +if nothing keeps us from doing it. If something is still +keeping us busy, the release callback of v4l will take care +of releasing it. stv680.c does not relase its private +data, so I don't do this here either. Checking out the +code I'd expect I better did that, but if there's a memory +leak here it's tiny (~50 bytes per disconnect) */ +static void usb_dsbr100_disconnect(struct usb_interface *intf) +{ + dsbr100_device *radio = usb_get_intfdata(intf); + + usb_set_intfdata (intf, NULL); + if (radio) { + video_unregister_device(radio->videodev); + radio->videodev = NULL; + if (radio->users) { + kfree(radio); + } else { + radio->removed = 1; + } + } +} + + +/* Video for Linux interface */ + +static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + dsbr100_device *radio=video_get_drvdata(video_devdata(file)); + + if (!radio) + return -EIO; + + switch(cmd) { + case VIDIOCGCAP: { + struct video_capability *v = arg; + + memset(v, 0, sizeof(*v)); + v->type = VID_TYPE_TUNER; + v->channels = 1; + v->audios = 1; + strcpy(v->name, "D-Link R-100 USB FM Radio"); + return 0; + } + case VIDIOCGTUNER: { + struct video_tuner *v = arg; + + dsbr100_getstat(radio); + if(v->tuner) /* Only 1 tuner */ + return -EINVAL; + v->rangelow = FREQ_MIN*FREQ_MUL; + v->rangehigh = FREQ_MAX*FREQ_MUL; + v->flags = VIDEO_TUNER_LOW; + v->mode = VIDEO_MODE_AUTO; + v->signal = radio->stereo*0x7000; + /* Don't know how to get signal strength */ + v->flags |= VIDEO_TUNER_STEREO_ON*radio->stereo; + strcpy(v->name, "DSB R-100"); + return 0; + } + case VIDIOCSTUNER: { + struct video_tuner *v = arg; + + if(v->tuner!=0) + return -EINVAL; + /* Only 1 tuner so no setting needed ! */ + return 0; + } + case VIDIOCGFREQ: { + int *freq = arg; + + if (radio->curfreq==-1) + return -EINVAL; + *freq = radio->curfreq; + return 0; + } + case VIDIOCSFREQ: { + int *freq = arg; + + radio->curfreq = *freq; + if (dsbr100_setfreq(radio, radio->curfreq)==-1) + warn("Set frequency failed"); + return 0; + } + case VIDIOCGAUDIO: { + struct video_audio *v = arg; + + memset(v, 0, sizeof(*v)); + v->flags |= VIDEO_AUDIO_MUTABLE; + v->mode = VIDEO_SOUND_STEREO; + v->volume = 1; + v->step = 1; + strcpy(v->name, "Radio"); + return 0; + } + case VIDIOCSAUDIO: { + struct video_audio *v = arg; + + if (v->audio) + return -EINVAL; + if (v->flags&VIDEO_AUDIO_MUTE) { + if (dsbr100_stop(radio)==-1) + warn("Radio did not respond properly"); + } + else + if (dsbr100_start(radio)==-1) + warn("Radio did not respond properly"); + return 0; + } + default: + return -ENOIOCTLCMD; + } +} + +static int usb_dsbr100_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl); +} + +static int usb_dsbr100_open(struct inode *inode, struct file *file) +{ + dsbr100_device *radio=video_get_drvdata(video_devdata(file)); + + radio->users = 1; + if (dsbr100_start(radio)<0) { + warn("Radio did not start up properly"); + radio->users = 0; + return -EIO; + } + dsbr100_setfreq(radio, radio->curfreq); + return 0; +} + +static int usb_dsbr100_close(struct inode *inode, struct file *file) +{ + dsbr100_device *radio=video_get_drvdata(video_devdata(file)); + + if (!radio) + return -ENODEV; + radio->users = 0; + if (radio->removed) { + kfree(radio); + } + return 0; +} + +static int __init dsbr100_init(void) +{ + int retval = usb_register(&usb_dsbr100_driver); + info(DRIVER_VERSION ":" DRIVER_DESC); + return retval; +} + +static void __exit dsbr100_exit(void) +{ + usb_deregister(&usb_dsbr100_driver); +} + +module_init (dsbr100_init); +module_exit (dsbr100_exit); + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/et61x251/Makefile b/drivers/media/video/et61x251/Makefile new file mode 100644 index 000000000000..2ff4db9ec882 --- /dev/null +++ b/drivers/media/video/et61x251/Makefile @@ -0,0 +1,4 @@ +et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o + +obj-$(CONFIG_USB_ET61X251) += et61x251.o + diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h new file mode 100644 index 000000000000..eee8afc9be72 --- /dev/null +++ b/drivers/media/video/et61x251/et61x251.h @@ -0,0 +1,234 @@ +/*************************************************************************** + * V4L2 driver for ET61X[12]51 PC Camera Controllers * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * 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. * + ***************************************************************************/ + +#ifndef _ET61X251_H_ +#define _ET61X251_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "et61x251_sensor.h" + +/*****************************************************************************/ + +#define ET61X251_DEBUG +#define ET61X251_DEBUG_LEVEL 2 +#define ET61X251_MAX_DEVICES 64 +#define ET61X251_PRESERVE_IMGSCALE 0 +#define ET61X251_FORCE_MUNMAP 0 +#define ET61X251_MAX_FRAMES 32 +#define ET61X251_COMPRESSION_QUALITY 0 +#define ET61X251_URBS 2 +#define ET61X251_ISO_PACKETS 7 +#define ET61X251_ALTERNATE_SETTING 13 +#define ET61X251_URB_TIMEOUT msecs_to_jiffies(2 * ET61X251_ISO_PACKETS) +#define ET61X251_CTRL_TIMEOUT 100 +#define ET61X251_FRAME_TIMEOUT 2 + +/*****************************************************************************/ + +static const struct usb_device_id et61x251_id_table[] = { + { USB_DEVICE(0x102c, 0x6151), }, + { USB_DEVICE(0x102c, 0x6251), }, + { USB_DEVICE(0x102c, 0x6253), }, + { USB_DEVICE(0x102c, 0x6254), }, + { USB_DEVICE(0x102c, 0x6255), }, + { USB_DEVICE(0x102c, 0x6256), }, + { USB_DEVICE(0x102c, 0x6257), }, + { USB_DEVICE(0x102c, 0x6258), }, + { USB_DEVICE(0x102c, 0x6259), }, + { USB_DEVICE(0x102c, 0x625a), }, + { USB_DEVICE(0x102c, 0x625b), }, + { USB_DEVICE(0x102c, 0x625c), }, + { USB_DEVICE(0x102c, 0x625d), }, + { USB_DEVICE(0x102c, 0x625e), }, + { USB_DEVICE(0x102c, 0x625f), }, + { USB_DEVICE(0x102c, 0x6260), }, + { USB_DEVICE(0x102c, 0x6261), }, + { USB_DEVICE(0x102c, 0x6262), }, + { USB_DEVICE(0x102c, 0x6263), }, + { USB_DEVICE(0x102c, 0x6264), }, + { USB_DEVICE(0x102c, 0x6265), }, + { USB_DEVICE(0x102c, 0x6266), }, + { USB_DEVICE(0x102c, 0x6267), }, + { USB_DEVICE(0x102c, 0x6268), }, + { USB_DEVICE(0x102c, 0x6269), }, + { } +}; + +ET61X251_SENSOR_TABLE + +/*****************************************************************************/ + +enum et61x251_frame_state { + F_UNUSED, + F_QUEUED, + F_GRABBING, + F_DONE, + F_ERROR, +}; + +struct et61x251_frame_t { + void* bufmem; + struct v4l2_buffer buf; + enum et61x251_frame_state state; + struct list_head frame; + unsigned long vma_use_count; +}; + +enum et61x251_dev_state { + DEV_INITIALIZED = 0x01, + DEV_DISCONNECTED = 0x02, + DEV_MISCONFIGURED = 0x04, +}; + +enum et61x251_io_method { + IO_NONE, + IO_READ, + IO_MMAP, +}; + +enum et61x251_stream_state { + STREAM_OFF, + STREAM_INTERRUPT, + STREAM_ON, +}; + +struct et61x251_sysfs_attr { + u8 reg, i2c_reg; +}; + +struct et61x251_module_param { + u8 force_munmap; + u16 frame_timeout; +}; + +static DEFINE_MUTEX(et61x251_sysfs_lock); +static DECLARE_RWSEM(et61x251_disconnect); + +struct et61x251_device { + struct video_device* v4ldev; + + struct et61x251_sensor sensor; + + struct usb_device* usbdev; + struct urb* urb[ET61X251_URBS]; + void* transfer_buffer[ET61X251_URBS]; + u8* control_buffer; + + struct et61x251_frame_t *frame_current, frame[ET61X251_MAX_FRAMES]; + struct list_head inqueue, outqueue; + u32 frame_count, nbuffers, nreadbuffers; + + enum et61x251_io_method io; + enum et61x251_stream_state stream; + + struct v4l2_jpegcompression compression; + + struct et61x251_sysfs_attr sysfs; + struct et61x251_module_param module_param; + + enum et61x251_dev_state state; + u8 users; + + struct mutex dev_mutex, fileop_mutex; + spinlock_t queue_lock; + wait_queue_head_t open, wait_frame, wait_stream; +}; + +/*****************************************************************************/ + +struct et61x251_device* +et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) +{ + if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) + return cam; + + return NULL; +} + + +void +et61x251_attach_sensor(struct et61x251_device* cam, + struct et61x251_sensor* sensor) +{ + memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor)); +} + +/*****************************************************************************/ + +#undef DBG +#undef KDBG +#ifdef ET61X251_DEBUG +# define DBG(level, fmt, args...) \ +do { \ + if (debug >= (level)) { \ + if ((level) == 1) \ + dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ + else if ((level) == 2) \ + dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ + else if ((level) >= 3) \ + dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args); \ + } \ +} while (0) +# define KDBG(level, fmt, args...) \ +do { \ + if (debug >= (level)) { \ + if ((level) == 1 || (level) == 2) \ + pr_info("et61x251: " fmt "\n", ## args); \ + else if ((level) == 3) \ + pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \ + __LINE__ , ## args); \ + } \ +} while (0) +# define V4LDBG(level, name, cmd) \ +do { \ + if (debug >= (level)) \ + v4l_print_ioctl(name, cmd); \ +} while (0) +#else +# define DBG(level, fmt, args...) do {;} while(0) +# define KDBG(level, fmt, args...) do {;} while(0) +# define V4LDBG(level, name, cmd) do {;} while(0) +#endif + +#undef PDBG +#define PDBG(fmt, args...) \ +dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args) + +#undef PDBGG +#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ + +#endif /* _ET61X251_H_ */ diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c new file mode 100644 index 000000000000..7cc01b828b3d --- /dev/null +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -0,0 +1,2630 @@ +/*************************************************************************** + * V4L2 driver for ET61X[12]51 PC Camera Controllers * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "et61x251.h" + +/*****************************************************************************/ + +#define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \ + "PC Camera Controllers" +#define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" +#define ET61X251_AUTHOR_EMAIL "" +#define ET61X251_MODULE_LICENSE "GPL" +#define ET61X251_MODULE_VERSION "1:1.02" +#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2) + +/*****************************************************************************/ + +MODULE_DEVICE_TABLE(usb, et61x251_id_table); + +MODULE_AUTHOR(ET61X251_MODULE_AUTHOR " " ET61X251_AUTHOR_EMAIL); +MODULE_DESCRIPTION(ET61X251_MODULE_NAME); +MODULE_VERSION(ET61X251_MODULE_VERSION); +MODULE_LICENSE(ET61X251_MODULE_LICENSE); + +static short video_nr[] = {[0 ... ET61X251_MAX_DEVICES-1] = -1}; +module_param_array(video_nr, short, NULL, 0444); +MODULE_PARM_DESC(video_nr, + "\n<-1|n[,...]> Specify V4L2 minor mode number." + "\n -1 = use next available (default)" + "\n n = use minor number n (integer >= 0)" + "\nYou can specify up to " + __MODULE_STRING(ET61X251_MAX_DEVICES) " cameras this way." + "\nFor example:" + "\nvideo_nr=-1,2,-1 would assign minor number 2 to" + "\nthe second registered camera and use auto for the first" + "\none and for every other camera." + "\n"); + +static short force_munmap[] = {[0 ... ET61X251_MAX_DEVICES-1] = + ET61X251_FORCE_MUNMAP}; +module_param_array(force_munmap, bool, NULL, 0444); +MODULE_PARM_DESC(force_munmap, + "\n<0|1[,...]> Force the application to unmap previously" + "\nmapped buffer memory before calling any VIDIOC_S_CROP or" + "\nVIDIOC_S_FMT ioctl's. Not all the applications support" + "\nthis feature. This parameter is specific for each" + "\ndetected camera." + "\n 0 = do not force memory unmapping" + "\n 1 = force memory unmapping (save memory)" + "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." + "\n"); + +static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] = + ET61X251_FRAME_TIMEOUT}; +module_param_array(frame_timeout, uint, NULL, 0644); +MODULE_PARM_DESC(frame_timeout, + "\n Timeout for a video frame in seconds." + "\nThis parameter is specific for each detected camera." + "\nDefault value is " + __MODULE_STRING(ET61X251_FRAME_TIMEOUT)"." + "\n"); + +#ifdef ET61X251_DEBUG +static unsigned short debug = ET61X251_DEBUG_LEVEL; +module_param(debug, ushort, 0644); +MODULE_PARM_DESC(debug, + "\n Debugging information level, from 0 to 3:" + "\n0 = none (use carefully)" + "\n1 = critical errors" + "\n2 = significant informations" + "\n3 = more verbose messages" + "\nLevel 3 is useful for testing only, when only " + "one device is used." + "\nDefault value is "__MODULE_STRING(ET61X251_DEBUG_LEVEL)"." + "\n"); +#endif + +/*****************************************************************************/ + +static u32 +et61x251_request_buffers(struct et61x251_device* cam, u32 count, + enum et61x251_io_method io) +{ + struct v4l2_pix_format* p = &(cam->sensor.pix_format); + struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); + const size_t imagesize = cam->module_param.force_munmap || + io == IO_READ ? + (p->width * p->height * p->priv) / 8 : + (r->width * r->height * p->priv) / 8; + void* buff = NULL; + u32 i; + + if (count > ET61X251_MAX_FRAMES) + count = ET61X251_MAX_FRAMES; + + cam->nbuffers = count; + while (cam->nbuffers > 0) { + if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) + break; + cam->nbuffers--; + } + + for (i = 0; i < cam->nbuffers; i++) { + cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); + cam->frame[i].buf.index = i; + cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); + cam->frame[i].buf.length = imagesize; + cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cam->frame[i].buf.sequence = 0; + cam->frame[i].buf.field = V4L2_FIELD_NONE; + cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; + cam->frame[i].buf.flags = 0; + } + + return cam->nbuffers; +} + + +static void et61x251_release_buffers(struct et61x251_device* cam) +{ + if (cam->nbuffers) { + vfree(cam->frame[0].bufmem); + cam->nbuffers = 0; + } + cam->frame_current = NULL; +} + + +static void et61x251_empty_framequeues(struct et61x251_device* cam) +{ + u32 i; + + INIT_LIST_HEAD(&cam->inqueue); + INIT_LIST_HEAD(&cam->outqueue); + + for (i = 0; i < ET61X251_MAX_FRAMES; i++) { + cam->frame[i].state = F_UNUSED; + cam->frame[i].buf.bytesused = 0; + } +} + + +static void et61x251_requeue_outqueue(struct et61x251_device* cam) +{ + struct et61x251_frame_t *i; + + list_for_each_entry(i, &cam->outqueue, frame) { + i->state = F_QUEUED; + list_add(&i->frame, &cam->inqueue); + } + + INIT_LIST_HEAD(&cam->outqueue); +} + + +static void et61x251_queue_unusedframes(struct et61x251_device* cam) +{ + unsigned long lock_flags; + u32 i; + + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].state == F_UNUSED) { + cam->frame[i].state = F_QUEUED; + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_add_tail(&cam->frame[i].frame, &cam->inqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + } +} + +/*****************************************************************************/ + +int et61x251_write_reg(struct et61x251_device* cam, u8 value, u16 index) +{ + struct usb_device* udev = cam->usbdev; + u8* buff = cam->control_buffer; + int res; + + *buff = value; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, index, buff, 1, ET61X251_CTRL_TIMEOUT); + if (res < 0) { + DBG(3, "Failed to write a register (value 0x%02X, index " + "0x%02X, error %d)", value, index, res); + return -1; + } + + return 0; +} + + +int et61x251_read_reg(struct et61x251_device* cam, u16 index) +{ + struct usb_device* udev = cam->usbdev; + u8* buff = cam->control_buffer; + int res; + + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, + 0, index, buff, 1, ET61X251_CTRL_TIMEOUT); + if (res < 0) + DBG(3, "Failed to read a register (index 0x%02X, error %d)", + index, res); + + return (res >= 0) ? (int)(*buff) : -1; +} + + +static int +et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor) +{ + int i, r; + + for (i = 1; i <= 8; i++) { + if (sensor->interface == ET61X251_I2C_3WIRES) { + r = et61x251_read_reg(cam, 0x8e); + if (!(r & 0x02) && (r >= 0)) + return 0; + } else { + r = et61x251_read_reg(cam, 0x8b); + if (!(r & 0x01) && (r >= 0)) + return 0; + } + if (r < 0) + return -EIO; + udelay(8*8); /* minimum for sensors at 400kHz */ + } + + return -EBUSY; +} + + +int +et61x251_i2c_try_read(struct et61x251_device* cam, + struct et61x251_sensor* sensor, u8 address) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + data[0] = address; + data[1] = cam->sensor.i2c_slave_id; + data[2] = cam->sensor.rsta | 0x10; + data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02); + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += et61x251_i2c_wait(cam, sensor); + + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, + 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + if (err) + DBG(3, "I2C read failed for %s image sensor", sensor->name); + + PDBGG("I2C read: address 0x%02X, value: 0x%02X", address, data[0]); + + return err ? -1 : (int)data[0]; +} + + +int +et61x251_i2c_try_write(struct et61x251_device* cam, + struct et61x251_sensor* sensor, u8 address, u8 value) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + data[0] = address; + data[1] = cam->sensor.i2c_slave_id; + data[2] = cam->sensor.rsta | 0x12; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + data[0] = value; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += et61x251_i2c_wait(cam, sensor); + + if (err) + DBG(3, "I2C write failed for %s image sensor", sensor->name); + + PDBGG("I2C write: address 0x%02X, value: 0x%02X", address, value); + + return err ? -1 : 0; +} + + +int +et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, + u8 data3, u8 data4, u8 data5, u8 data6, u8 data7, + u8 data8, u8 address) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + data[0] = data2; + data[1] = data3; + data[2] = data4; + data[3] = data5; + data[4] = data6; + data[5] = data7; + data[6] = data8; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x81, data, n-1, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + data[0] = address; + data[1] = cam->sensor.i2c_slave_id; + data[2] = cam->sensor.rsta | 0x02 | (n << 4); + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + /* Start writing through the serial interface */ + data[0] = data1; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, + 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += et61x251_i2c_wait(cam, &cam->sensor); + + if (err) + DBG(3, "I2C raw write failed for %s image sensor", + cam->sensor.name); + + PDBGG("I2C raw write: %u bytes, address = 0x%02X, data1 = 0x%02X, " + "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X," + " data6 = 0x%02X, data7 = 0x%02X, data8 = 0x%02X", n, address, + data1, data2, data3, data4, data5, data6, data7, data8); + + return err ? -1 : 0; + +} + + +int et61x251_i2c_read(struct et61x251_device* cam, u8 address) +{ + return et61x251_i2c_try_read(cam, &cam->sensor, address); +} + + +int et61x251_i2c_write(struct et61x251_device* cam, u8 address, u8 value) +{ + return et61x251_i2c_try_write(cam, &cam->sensor, address, value); +} + +/*****************************************************************************/ + +static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs) +{ + struct et61x251_device* cam = urb->context; + struct et61x251_frame_t** f; + size_t imagesize; + u8 i; + int err = 0; + + if (urb->status == -ENOENT) + return; + + f = &cam->frame_current; + + if (cam->stream == STREAM_INTERRUPT) { + cam->stream = STREAM_OFF; + if ((*f)) + (*f)->state = F_QUEUED; + DBG(3, "Stream interrupted"); + wake_up(&cam->wait_stream); + } + + if (cam->state & DEV_DISCONNECTED) + return; + + if (cam->state & DEV_MISCONFIGURED) { + wake_up_interruptible(&cam->wait_frame); + return; + } + + if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) + goto resubmit_urb; + + if (!(*f)) + (*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t, + frame); + + imagesize = (cam->sensor.pix_format.width * + cam->sensor.pix_format.height * + cam->sensor.pix_format.priv) / 8; + + for (i = 0; i < urb->number_of_packets; i++) { + unsigned int len, status; + void *pos; + u8* b1, * b2, sof; + const u8 VOID_BYTES = 6; + size_t imglen; + + len = urb->iso_frame_desc[i].actual_length; + status = urb->iso_frame_desc[i].status; + pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; + + if (status) { + DBG(3, "Error in isochronous frame"); + (*f)->state = F_ERROR; + continue; + } + + b1 = pos++; + b2 = pos++; + sof = ((*b1 & 0x3f) == 63); + imglen = ((*b1 & 0xc0) << 2) | *b2; + + PDBGG("Isochrnous frame: length %u, #%u i, image length %zu", + len, i, imglen); + + if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) +start_of_frame: + if (sof) { + (*f)->state = F_GRABBING; + (*f)->buf.bytesused = 0; + do_gettimeofday(&(*f)->buf.timestamp); + pos += 22; + DBG(3, "SOF detected: new video frame"); + } + + if ((*f)->state == F_GRABBING) { + if (sof && (*f)->buf.bytesused) { + if (cam->sensor.pix_format.pixelformat == + V4L2_PIX_FMT_ET61X251) + goto end_of_frame; + else { + DBG(3, "Not expected SOF detected " + "after %lu bytes", + (unsigned long)(*f)->buf.bytesused); + (*f)->state = F_ERROR; + continue; + } + } + + if ((*f)->buf.bytesused + imglen > imagesize) { + DBG(3, "Video frame size exceeded"); + (*f)->state = F_ERROR; + continue; + } + + pos += VOID_BYTES; + + memcpy((*f)->bufmem+(*f)->buf.bytesused, pos, imglen); + (*f)->buf.bytesused += imglen; + + if ((*f)->buf.bytesused == imagesize) { + u32 b; +end_of_frame: + b = (*f)->buf.bytesused; + (*f)->state = F_DONE; + (*f)->buf.sequence= ++cam->frame_count; + spin_lock(&cam->queue_lock); + list_move_tail(&(*f)->frame, &cam->outqueue); + if (!list_empty(&cam->inqueue)) + (*f) = list_entry(cam->inqueue.next, + struct et61x251_frame_t, + frame); + else + (*f) = NULL; + spin_unlock(&cam->queue_lock); + DBG(3, "Video frame captured: : %lu bytes", + (unsigned long)(b)); + + if (!(*f)) + goto resubmit_urb; + + if (sof && + cam->sensor.pix_format.pixelformat == + V4L2_PIX_FMT_ET61X251) + goto start_of_frame; + } + } + } + +resubmit_urb: + urb->dev = cam->usbdev; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0 && err != -EPERM) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "usb_submit_urb() failed"); + } + + wake_up_interruptible(&cam->wait_frame); +} + + +static int et61x251_start_transfer(struct et61x251_device* cam) +{ + struct usb_device *udev = cam->usbdev; + struct urb* urb; + const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832, + 864, 896, 920, 956, 980, 1000, + 1022}; + const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING]; + s8 i, j; + int err = 0; + + for (i = 0; i < ET61X251_URBS; i++) { + cam->transfer_buffer[i] = kzalloc(ET61X251_ISO_PACKETS * psz, + GFP_KERNEL); + if (!cam->transfer_buffer[i]) { + err = -ENOMEM; + DBG(1, "Not enough memory"); + goto free_buffers; + } + } + + for (i = 0; i < ET61X251_URBS; i++) { + urb = usb_alloc_urb(ET61X251_ISO_PACKETS, GFP_KERNEL); + cam->urb[i] = urb; + if (!urb) { + err = -ENOMEM; + DBG(1, "usb_alloc_urb() failed"); + goto free_urbs; + } + urb->dev = udev; + urb->context = cam; + urb->pipe = usb_rcvisocpipe(udev, 1); + urb->transfer_flags = URB_ISO_ASAP; + urb->number_of_packets = ET61X251_ISO_PACKETS; + urb->complete = et61x251_urb_complete; + urb->transfer_buffer = cam->transfer_buffer[i]; + urb->transfer_buffer_length = psz * ET61X251_ISO_PACKETS; + urb->interval = 1; + for (j = 0; j < ET61X251_ISO_PACKETS; j++) { + urb->iso_frame_desc[j].offset = psz * j; + urb->iso_frame_desc[j].length = psz; + } + } + + err = et61x251_write_reg(cam, 0x01, 0x03); + err = et61x251_write_reg(cam, 0x00, 0x03); + err = et61x251_write_reg(cam, 0x08, 0x03); + if (err) { + err = -EIO; + DBG(1, "I/O hardware error"); + goto free_urbs; + } + + err = usb_set_interface(udev, 0, ET61X251_ALTERNATE_SETTING); + if (err) { + DBG(1, "usb_set_interface() failed"); + goto free_urbs; + } + + cam->frame_current = NULL; + + for (i = 0; i < ET61X251_URBS; i++) { + err = usb_submit_urb(cam->urb[i], GFP_KERNEL); + if (err) { + for (j = i-1; j >= 0; j--) + usb_kill_urb(cam->urb[j]); + DBG(1, "usb_submit_urb() failed, error %d", err); + goto free_urbs; + } + } + + return 0; + +free_urbs: + for (i = 0; (i < ET61X251_URBS) && cam->urb[i]; i++) + usb_free_urb(cam->urb[i]); + +free_buffers: + for (i = 0; (i < ET61X251_URBS) && cam->transfer_buffer[i]; i++) + kfree(cam->transfer_buffer[i]); + + return err; +} + + +static int et61x251_stop_transfer(struct et61x251_device* cam) +{ + struct usb_device *udev = cam->usbdev; + s8 i; + int err = 0; + + if (cam->state & DEV_DISCONNECTED) + return 0; + + for (i = ET61X251_URBS-1; i >= 0; i--) { + usb_kill_urb(cam->urb[i]); + usb_free_urb(cam->urb[i]); + kfree(cam->transfer_buffer[i]); + } + + err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ + if (err) + DBG(3, "usb_set_interface() failed"); + + return err; +} + + +static int et61x251_stream_interrupt(struct et61x251_device* cam) +{ + long timeout; + + cam->stream = STREAM_INTERRUPT; + timeout = wait_event_timeout(cam->wait_stream, + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + ET61X251_URB_TIMEOUT); + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + else if (cam->stream != STREAM_OFF) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "URB timeout reached. The camera is misconfigured. To " + "use it, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + return 0; +} + +/*****************************************************************************/ + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count) +{ + char str[5]; + char* endp; + unsigned long val; + + if (len < 4) { + strncpy(str, buff, len); + str[len+1] = '\0'; + } else { + strncpy(str, buff, 4); + str[4] = '\0'; + } + + val = simple_strtoul(str, &endp, 0); + + *count = 0; + if (val <= 0xff) + *count = (ssize_t)(endp - str); + if ((*count) && (len == *count+1) && (buff[*count] == '\n')) + *count += 1; + + return (u8)val; +} + +/* + NOTE 1: being inside one of the following methods implies that the v4l + device exists for sure (see kobjects and reference counters) + NOTE 2: buffers are PAGE_SIZE long +*/ + +static ssize_t et61x251_show_reg(struct class_device* cd, char* buf) +{ + struct et61x251_device* cam; + ssize_t count; + + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&et61x251_sysfs_lock); + return -ENODEV; + } + + count = sprintf(buf, "%u\n", cam->sysfs.reg); + + mutex_unlock(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t +et61x251_store_reg(struct class_device* cd, const char* buf, size_t len) +{ + struct et61x251_device* cam; + u8 index; + ssize_t count; + + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&et61x251_sysfs_lock); + return -ENODEV; + } + + index = et61x251_strtou8(buf, len, &count); + if (index > 0x8e || !count) { + mutex_unlock(&et61x251_sysfs_lock); + return -EINVAL; + } + + cam->sysfs.reg = index; + + DBG(2, "Moved ET61X[12]51 register index to 0x%02X", cam->sysfs.reg); + DBG(3, "Written bytes: %zd", count); + + mutex_unlock(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t et61x251_show_val(struct class_device* cd, char* buf) +{ + struct et61x251_device* cam; + ssize_t count; + int val; + + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&et61x251_sysfs_lock); + return -ENODEV; + } + + if ((val = et61x251_read_reg(cam, cam->sysfs.reg)) < 0) { + mutex_unlock(&et61x251_sysfs_lock); + return -EIO; + } + + count = sprintf(buf, "%d\n", val); + + DBG(3, "Read bytes: %zd", count); + + mutex_unlock(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t +et61x251_store_val(struct class_device* cd, const char* buf, size_t len) +{ + struct et61x251_device* cam; + u8 value; + ssize_t count; + int err; + + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&et61x251_sysfs_lock); + return -ENODEV; + } + + value = et61x251_strtou8(buf, len, &count); + if (!count) { + mutex_unlock(&et61x251_sysfs_lock); + return -EINVAL; + } + + err = et61x251_write_reg(cam, value, cam->sysfs.reg); + if (err) { + mutex_unlock(&et61x251_sysfs_lock); + return -EIO; + } + + DBG(2, "Written ET61X[12]51 reg. 0x%02X, val. 0x%02X", + cam->sysfs.reg, value); + DBG(3, "Written bytes: %zd", count); + + mutex_unlock(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf) +{ + struct et61x251_device* cam; + ssize_t count; + + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&et61x251_sysfs_lock); + return -ENODEV; + } + + count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg); + + DBG(3, "Read bytes: %zd", count); + + mutex_unlock(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t +et61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) +{ + struct et61x251_device* cam; + u8 index; + ssize_t count; + + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&et61x251_sysfs_lock); + return -ENODEV; + } + + index = et61x251_strtou8(buf, len, &count); + if (!count) { + mutex_unlock(&et61x251_sysfs_lock); + return -EINVAL; + } + + cam->sysfs.i2c_reg = index; + + DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); + DBG(3, "Written bytes: %zd", count); + + mutex_unlock(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf) +{ + struct et61x251_device* cam; + ssize_t count; + int val; + + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&et61x251_sysfs_lock); + return -ENODEV; + } + + if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) { + mutex_unlock(&et61x251_sysfs_lock); + return -ENOSYS; + } + + if ((val = et61x251_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { + mutex_unlock(&et61x251_sysfs_lock); + return -EIO; + } + + count = sprintf(buf, "%d\n", val); + + DBG(3, "Read bytes: %zd", count); + + mutex_unlock(&et61x251_sysfs_lock); + + return count; +} + + +static ssize_t +et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len) +{ + struct et61x251_device* cam; + u8 value; + ssize_t count; + int err; + + if (mutex_lock_interruptible(&et61x251_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&et61x251_sysfs_lock); + return -ENODEV; + } + + if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) { + mutex_unlock(&et61x251_sysfs_lock); + return -ENOSYS; + } + + value = et61x251_strtou8(buf, len, &count); + if (!count) { + mutex_unlock(&et61x251_sysfs_lock); + return -EINVAL; + } + + err = et61x251_i2c_write(cam, cam->sysfs.i2c_reg, value); + if (err) { + mutex_unlock(&et61x251_sysfs_lock); + return -EIO; + } + + DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X", + cam->sysfs.i2c_reg, value); + DBG(3, "Written bytes: %zd", count); + + mutex_unlock(&et61x251_sysfs_lock); + + return count; +} + + +static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, + et61x251_show_reg, et61x251_store_reg); +static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR, + et61x251_show_val, et61x251_store_val); +static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, + et61x251_show_i2c_reg, et61x251_store_i2c_reg); +static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, + et61x251_show_i2c_val, et61x251_store_i2c_val); + + +static void et61x251_create_sysfs(struct et61x251_device* cam) +{ + struct video_device *v4ldev = cam->v4ldev; + + video_device_create_file(v4ldev, &class_device_attr_reg); + video_device_create_file(v4ldev, &class_device_attr_val); + if (cam->sensor.sysfs_ops) { + video_device_create_file(v4ldev, &class_device_attr_i2c_reg); + video_device_create_file(v4ldev, &class_device_attr_i2c_val); + } +} +#endif /* CONFIG_VIDEO_ADV_DEBUG */ + +/*****************************************************************************/ + +static int +et61x251_set_pix_format(struct et61x251_device* cam, + struct v4l2_pix_format* pix) +{ + int r, err = 0; + + if ((r = et61x251_read_reg(cam, 0x12)) < 0) + err += r; + if (pix->pixelformat == V4L2_PIX_FMT_ET61X251) + err += et61x251_write_reg(cam, r & 0xfd, 0x12); + else + err += et61x251_write_reg(cam, r | 0x02, 0x12); + + return err ? -EIO : 0; +} + + +static int +et61x251_set_compression(struct et61x251_device* cam, + struct v4l2_jpegcompression* compression) +{ + int r, err = 0; + + if ((r = et61x251_read_reg(cam, 0x12)) < 0) + err += r; + if (compression->quality == 0) + err += et61x251_write_reg(cam, r & 0xfb, 0x12); + else + err += et61x251_write_reg(cam, r | 0x04, 0x12); + + return err ? -EIO : 0; +} + + +static int et61x251_set_scale(struct et61x251_device* cam, u8 scale) +{ + int r = 0, err = 0; + + r = et61x251_read_reg(cam, 0x12); + if (r < 0) + err += r; + + if (scale == 1) + err += et61x251_write_reg(cam, r & ~0x01, 0x12); + else if (scale == 2) + err += et61x251_write_reg(cam, r | 0x01, 0x12); + + if (err) + return -EIO; + + PDBGG("Scaling factor: %u", scale); + + return 0; +} + + +static int +et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect) +{ + struct et61x251_sensor* s = &cam->sensor; + u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left + + s->active_pixel.left), + fmw_sy = (u16)(rect->top - s->cropcap.bounds.top + + s->active_pixel.top), + fmw_length = (u16)(rect->width), + fmw_height = (u16)(rect->height); + int err = 0; + + err += et61x251_write_reg(cam, fmw_sx & 0xff, 0x69); + err += et61x251_write_reg(cam, fmw_sy & 0xff, 0x6a); + err += et61x251_write_reg(cam, fmw_length & 0xff, 0x6b); + err += et61x251_write_reg(cam, fmw_height & 0xff, 0x6c); + err += et61x251_write_reg(cam, (fmw_sx >> 8) | ((fmw_sy & 0x300) >> 6) + | ((fmw_length & 0x300) >> 4) + | ((fmw_height & 0x300) >> 2), 0x6d); + if (err) + return -EIO; + + PDBGG("fmw_sx, fmw_sy, fmw_length, fmw_height: %u %u %u %u", + fmw_sx, fmw_sy, fmw_length, fmw_height); + + return 0; +} + + +static int et61x251_init(struct et61x251_device* cam) +{ + struct et61x251_sensor* s = &cam->sensor; + struct v4l2_control ctrl; + struct v4l2_queryctrl *qctrl; + struct v4l2_rect* rect; + u8 i = 0; + int err = 0; + + if (!(cam->state & DEV_INITIALIZED)) { + init_waitqueue_head(&cam->open); + qctrl = s->qctrl; + rect = &(s->cropcap.defrect); + cam->compression.quality = ET61X251_COMPRESSION_QUALITY; + } else { /* use current values */ + qctrl = s->_qctrl; + rect = &(s->_rect); + } + + err += et61x251_set_scale(cam, rect->width / s->pix_format.width); + err += et61x251_set_crop(cam, rect); + if (err) + return err; + + if (s->init) { + err = s->init(cam); + if (err) { + DBG(3, "Sensor initialization failed"); + return err; + } + } + + err += et61x251_set_compression(cam, &cam->compression); + err += et61x251_set_pix_format(cam, &s->pix_format); + if (s->set_pix_format) + err += s->set_pix_format(cam, &s->pix_format); + if (err) + return err; + + if (s->pix_format.pixelformat == V4L2_PIX_FMT_ET61X251) + DBG(3, "Compressed video format is active, quality %d", + cam->compression.quality); + else + DBG(3, "Uncompressed video format is active"); + + if (s->set_crop) + if ((err = s->set_crop(cam, rect))) { + DBG(3, "set_crop() failed"); + return err; + } + + if (s->set_ctrl) { + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (s->qctrl[i].id != 0 && + !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { + ctrl.id = s->qctrl[i].id; + ctrl.value = qctrl[i].default_value; + err = s->set_ctrl(cam, &ctrl); + if (err) { + DBG(3, "Set %s control failed", + s->qctrl[i].name); + return err; + } + DBG(3, "Image sensor supports '%s' control", + s->qctrl[i].name); + } + } + + if (!(cam->state & DEV_INITIALIZED)) { + mutex_init(&cam->fileop_mutex); + spin_lock_init(&cam->queue_lock); + init_waitqueue_head(&cam->wait_frame); + init_waitqueue_head(&cam->wait_stream); + cam->nreadbuffers = 2; + memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); + memcpy(&(s->_rect), &(s->cropcap.defrect), + sizeof(struct v4l2_rect)); + cam->state |= DEV_INITIALIZED; + } + + DBG(2, "Initialization succeeded"); + return 0; +} + + +static void et61x251_release_resources(struct et61x251_device* cam) +{ + mutex_lock(&et61x251_sysfs_lock); + + DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); + video_set_drvdata(cam->v4ldev, NULL); + video_unregister_device(cam->v4ldev); + + usb_put_dev(cam->usbdev); + + mutex_unlock(&et61x251_sysfs_lock); + + kfree(cam->control_buffer); +} + +/*****************************************************************************/ + +static int et61x251_open(struct inode* inode, struct file* filp) +{ + struct et61x251_device* cam; + int err = 0; + + /* + This is the only safe way to prevent race conditions with + disconnect + */ + if (!down_read_trylock(&et61x251_disconnect)) + return -ERESTARTSYS; + + cam = video_get_drvdata(video_devdata(filp)); + + if (mutex_lock_interruptible(&cam->dev_mutex)) { + up_read(&et61x251_disconnect); + return -ERESTARTSYS; + } + + if (cam->users) { + DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); + if ((filp->f_flags & O_NONBLOCK) || + (filp->f_flags & O_NDELAY)) { + err = -EWOULDBLOCK; + goto out; + } + mutex_unlock(&cam->dev_mutex); + err = wait_event_interruptible_exclusive(cam->open, + cam->state & DEV_DISCONNECTED + || !cam->users); + if (err) { + up_read(&et61x251_disconnect); + return err; + } + if (cam->state & DEV_DISCONNECTED) { + up_read(&et61x251_disconnect); + return -ENODEV; + } + mutex_lock(&cam->dev_mutex); + } + + + if (cam->state & DEV_MISCONFIGURED) { + err = et61x251_init(cam); + if (err) { + DBG(1, "Initialization failed again. " + "I will retry on next open()."); + goto out; + } + cam->state &= ~DEV_MISCONFIGURED; + } + + if ((err = et61x251_start_transfer(cam))) + goto out; + + filp->private_data = cam; + cam->users++; + cam->io = IO_NONE; + cam->stream = STREAM_OFF; + cam->nbuffers = 0; + cam->frame_count = 0; + et61x251_empty_framequeues(cam); + + DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); + +out: + mutex_unlock(&cam->dev_mutex); + up_read(&et61x251_disconnect); + return err; +} + + +static int et61x251_release(struct inode* inode, struct file* filp) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + + mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ + + et61x251_stop_transfer(cam); + + et61x251_release_buffers(cam); + + if (cam->state & DEV_DISCONNECTED) { + et61x251_release_resources(cam); + mutex_unlock(&cam->dev_mutex); + kfree(cam); + return 0; + } + + cam->users--; + wake_up_interruptible_nr(&cam->open, 1); + + DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); + + mutex_unlock(&cam->dev_mutex); + + return 0; +} + + +static ssize_t +et61x251_read(struct file* filp, char __user * buf, + size_t count, loff_t* f_pos) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + struct et61x251_frame_t* f, * i; + unsigned long lock_flags; + long timeout; + int err = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + if (cam->io == IO_MMAP) { + DBG(3, "Close and open the device again to choose the read " + "method"); + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + if (cam->io == IO_NONE) { + if (!et61x251_request_buffers(cam, cam->nreadbuffers, + IO_READ)) { + DBG(1, "read() failed, not enough memory"); + mutex_unlock(&cam->fileop_mutex); + return -ENOMEM; + } + cam->io = IO_READ; + cam->stream = STREAM_ON; + } + + if (list_empty(&cam->inqueue)) { + if (!list_empty(&cam->outqueue)) + et61x251_empty_framequeues(cam); + et61x251_queue_unusedframes(cam); + } + + if (!count) { + mutex_unlock(&cam->fileop_mutex); + return 0; + } + + if (list_empty(&cam->outqueue)) { + if (filp->f_flags & O_NONBLOCK) { + mutex_unlock(&cam->fileop_mutex); + return -EAGAIN; + } + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) { + mutex_unlock(&cam->fileop_mutex); + return timeout; + } + if (cam->state & DEV_DISCONNECTED) { + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + if (!timeout || (cam->state & DEV_MISCONFIGURED)) { + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + } + + f = list_entry(cam->outqueue.prev, struct et61x251_frame_t, frame); + + if (count > f->buf.bytesused) + count = f->buf.bytesused; + + if (copy_to_user(buf, f->bufmem, count)) { + err = -EFAULT; + goto exit; + } + *f_pos += count; + +exit: + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_for_each_entry(i, &cam->outqueue, frame) + i->state = F_UNUSED; + INIT_LIST_HEAD(&cam->outqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + et61x251_queue_unusedframes(cam); + + PDBGG("Frame #%lu, bytes read: %zu", + (unsigned long)f->buf.index, count); + + mutex_unlock(&cam->fileop_mutex); + + return err ? err : count; +} + + +static unsigned int et61x251_poll(struct file *filp, poll_table *wait) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + struct et61x251_frame_t* f; + unsigned long lock_flags; + unsigned int mask = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return POLLERR; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + goto error; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + goto error; + } + + if (cam->io == IO_NONE) { + if (!et61x251_request_buffers(cam, cam->nreadbuffers, + IO_READ)) { + DBG(1, "poll() failed, not enough memory"); + goto error; + } + cam->io = IO_READ; + cam->stream = STREAM_ON; + } + + if (cam->io == IO_READ) { + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_for_each_entry(f, &cam->outqueue, frame) + f->state = F_UNUSED; + INIT_LIST_HEAD(&cam->outqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + et61x251_queue_unusedframes(cam); + } + + poll_wait(filp, &cam->wait_frame, wait); + + if (!list_empty(&cam->outqueue)) + mask |= POLLIN | POLLRDNORM; + + mutex_unlock(&cam->fileop_mutex); + + return mask; + +error: + mutex_unlock(&cam->fileop_mutex); + return POLLERR; +} + + +static void et61x251_vm_open(struct vm_area_struct* vma) +{ + struct et61x251_frame_t* f = vma->vm_private_data; + f->vma_use_count++; +} + + +static void et61x251_vm_close(struct vm_area_struct* vma) +{ + /* NOTE: buffers are not freed here */ + struct et61x251_frame_t* f = vma->vm_private_data; + f->vma_use_count--; +} + + +static struct vm_operations_struct et61x251_vm_ops = { + .open = et61x251_vm_open, + .close = et61x251_vm_close, +}; + + +static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + unsigned long size = vma->vm_end - vma->vm_start, + start = vma->vm_start; + void *pos; + u32 i; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || + size != PAGE_ALIGN(cam->frame[0].buf.length)) { + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + for (i = 0; i < cam->nbuffers; i++) { + if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) + break; + } + if (i == cam->nbuffers) { + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED; + + pos = cam->frame[i].bufmem; + while (size > 0) { /* size is page-aligned */ + if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { + mutex_unlock(&cam->fileop_mutex); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + size -= PAGE_SIZE; + } + + vma->vm_ops = &et61x251_vm_ops; + vma->vm_private_data = &cam->frame[i]; + + et61x251_vm_open(vma); + + mutex_unlock(&cam->fileop_mutex); + + return 0; +} + +/*****************************************************************************/ + +static int +et61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_capability cap = { + .driver = "et61x251", + .version = ET61X251_MODULE_VERSION_CODE, + .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING, + }; + + strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); + if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) + strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, + sizeof(cap.bus_info)); + + if (copy_to_user(arg, &cap, sizeof(cap))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_enuminput(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_input i; + + if (copy_from_user(&i, arg, sizeof(i))) + return -EFAULT; + + if (i.index) + return -EINVAL; + + memset(&i, 0, sizeof(i)); + strcpy(i.name, "Camera"); + i.type = V4L2_INPUT_TYPE_CAMERA; + + if (copy_to_user(arg, &i, sizeof(i))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_g_input(struct et61x251_device* cam, void __user * arg) +{ + int index = 0; + + if (copy_to_user(arg, &index, sizeof(index))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_s_input(struct et61x251_device* cam, void __user * arg) +{ + int index; + + if (copy_from_user(&index, arg, sizeof(index))) + return -EFAULT; + + if (index != 0) + return -EINVAL; + + return 0; +} + + +static int +et61x251_vidioc_query_ctrl(struct et61x251_device* cam, void __user * arg) +{ + struct et61x251_sensor* s = &cam->sensor; + struct v4l2_queryctrl qc; + u8 i; + + if (copy_from_user(&qc, arg, sizeof(qc))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (qc.id && qc.id == s->qctrl[i].id) { + memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); + if (copy_to_user(arg, &qc, sizeof(qc))) + return -EFAULT; + return 0; + } + + return -EINVAL; +} + + +static int +et61x251_vidioc_g_ctrl(struct et61x251_device* cam, void __user * arg) +{ + struct et61x251_sensor* s = &cam->sensor; + struct v4l2_control ctrl; + int err = 0; + u8 i; + + if (!s->get_ctrl && !s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + + if (!s->get_ctrl) { + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (ctrl.id == s->qctrl[i].id) { + ctrl.value = s->_qctrl[i].default_value; + goto exit; + } + return -EINVAL; + } else + err = s->get_ctrl(cam, &ctrl); + +exit: + if (copy_to_user(arg, &ctrl, sizeof(ctrl))) + return -EFAULT; + + return err; +} + + +static int +et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg) +{ + struct et61x251_sensor* s = &cam->sensor; + struct v4l2_control ctrl; + u8 i; + int err = 0; + + if (!s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (ctrl.id == s->qctrl[i].id) { + if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) + return -EINVAL; + if (ctrl.value < s->qctrl[i].minimum || + ctrl.value > s->qctrl[i].maximum) + return -ERANGE; + ctrl.value -= ctrl.value % s->qctrl[i].step; + break; + } + + if ((err = s->set_ctrl(cam, &ctrl))) + return err; + + s->_qctrl[i].default_value = ctrl.value; + + return 0; +} + + +static int +et61x251_vidioc_cropcap(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_cropcap* cc = &(cam->sensor.cropcap); + + cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cc->pixelaspect.numerator = 1; + cc->pixelaspect.denominator = 1; + + if (copy_to_user(arg, cc, sizeof(*cc))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_g_crop(struct et61x251_device* cam, void __user * arg) +{ + struct et61x251_sensor* s = &cam->sensor; + struct v4l2_crop crop = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + }; + + memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); + + if (copy_to_user(arg, &crop, sizeof(crop))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) +{ + struct et61x251_sensor* s = &cam->sensor; + struct v4l2_crop crop; + struct v4l2_rect* rect; + struct v4l2_rect* bounds = &(s->cropcap.bounds); + struct v4l2_pix_format* pix_format = &(s->pix_format); + u8 scale; + const enum et61x251_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; + + if (copy_from_user(&crop, arg, sizeof(crop))) + return -EFAULT; + + rect = &(crop.c); + + if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_CROP failed. " + "Unmap the buffers first."); + return -EINVAL; + } + + /* Preserve R,G or B origin */ + rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; + rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; + + if (rect->width < 4) + rect->width = 4; + if (rect->height < 4) + rect->height = 4; + if (rect->width > bounds->width) + rect->width = bounds->width; + if (rect->height > bounds->height) + rect->height = bounds->height; + if (rect->left < bounds->left) + rect->left = bounds->left; + if (rect->top < bounds->top) + rect->top = bounds->top; + if (rect->left + rect->width > bounds->left + bounds->width) + rect->left = bounds->left+bounds->width - rect->width; + if (rect->top + rect->height > bounds->top + bounds->height) + rect->top = bounds->top+bounds->height - rect->height; + + rect->width &= ~3L; + rect->height &= ~3L; + + if (ET61X251_PRESERVE_IMGSCALE) { + /* Calculate the actual scaling factor */ + u32 a, b; + a = rect->width * rect->height; + b = pix_format->width * pix_format->height; + scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1; + } else + scale = 1; + + if (cam->stream == STREAM_ON) + if ((err = et61x251_stream_interrupt(cam))) + return err; + + if (copy_to_user(arg, &crop, sizeof(crop))) { + cam->stream = stream; + return -EFAULT; + } + + if (cam->module_param.force_munmap || cam->io == IO_READ) + et61x251_release_buffers(cam); + + err = et61x251_set_crop(cam, rect); + if (s->set_crop) + err += s->set_crop(cam, rect); + err += et61x251_set_scale(cam, scale); + + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + s->pix_format.width = rect->width/scale; + s->pix_format.height = rect->height/scale; + memcpy(&(s->_rect), rect, sizeof(*rect)); + + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } + + if (cam->io == IO_READ) + et61x251_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + et61x251_requeue_outqueue(cam); + + cam->stream = stream; + + return 0; +} + + +static int +et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_fmtdesc fmtd; + + if (copy_from_user(&fmtd, arg, sizeof(fmtd))) + return -EFAULT; + + if (fmtd.index == 0) { + strcpy(fmtd.description, "bayer rgb"); + fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; + } else if (fmtd.index == 1) { + strcpy(fmtd.description, "compressed"); + fmtd.pixelformat = V4L2_PIX_FMT_ET61X251; + fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; + } else + return -EINVAL; + + fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); + + if (copy_to_user(arg, &fmtd, sizeof(fmtd))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_format format; + struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); + + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; + + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251) + ? 0 : (pfmt->width * pfmt->priv) / 8; + pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); + pfmt->field = V4L2_FIELD_NONE; + memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); + + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, + void __user * arg) +{ + struct et61x251_sensor* s = &cam->sensor; + struct v4l2_format format; + struct v4l2_pix_format* pix; + struct v4l2_pix_format* pfmt = &(s->pix_format); + struct v4l2_rect* bounds = &(s->cropcap.bounds); + struct v4l2_rect rect; + u8 scale; + const enum et61x251_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; + + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; + + pix = &(format.fmt.pix); + + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + memcpy(&rect, &(s->_rect), sizeof(rect)); + + { /* calculate the actual scaling factor */ + u32 a, b; + a = rect.width * rect.height; + b = pix->width * pix->height; + scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1; + } + + rect.width = scale * pix->width; + rect.height = scale * pix->height; + + if (rect.width < 4) + rect.width = 4; + if (rect.height < 4) + rect.height = 4; + if (rect.width > bounds->left + bounds->width - rect.left) + rect.width = bounds->left + bounds->width - rect.left; + if (rect.height > bounds->top + bounds->height - rect.top) + rect.height = bounds->top + bounds->height - rect.top; + + rect.width &= ~3L; + rect.height &= ~3L; + + { /* adjust the scaling factor */ + u32 a, b; + a = rect.width * rect.height; + b = pix->width * pix->height; + scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1; + } + + pix->width = rect.width / scale; + pix->height = rect.height / scale; + + if (pix->pixelformat != V4L2_PIX_FMT_ET61X251 && + pix->pixelformat != V4L2_PIX_FMT_SBGGR8) + pix->pixelformat = pfmt->pixelformat; + pix->priv = pfmt->priv; /* bpp */ + pix->colorspace = pfmt->colorspace; + pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251) + ? 0 : (pix->width * pix->priv) / 8; + pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); + pix->field = V4L2_FIELD_NONE; + + if (cmd == VIDIOC_TRY_FMT) { + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; + return 0; + } + + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_FMT failed. " + "Unmap the buffers first."); + return -EINVAL; + } + + if (cam->stream == STREAM_ON) + if ((err = et61x251_stream_interrupt(cam))) + return err; + + if (copy_to_user(arg, &format, sizeof(format))) { + cam->stream = stream; + return -EFAULT; + } + + if (cam->module_param.force_munmap || cam->io == IO_READ) + et61x251_release_buffers(cam); + + err += et61x251_set_pix_format(cam, pix); + err += et61x251_set_crop(cam, &rect); + if (s->set_pix_format) + err += s->set_pix_format(cam, pix); + if (s->set_crop) + err += s->set_crop(cam, &rect); + err += et61x251_set_scale(cam, scale); + + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + memcpy(pfmt, pix, sizeof(*pix)); + memcpy(&(s->_rect), &rect, sizeof(rect)); + + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } + + if (cam->io == IO_READ) + et61x251_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + et61x251_requeue_outqueue(cam); + + cam->stream = stream; + + return 0; +} + + +static int +et61x251_vidioc_g_jpegcomp(struct et61x251_device* cam, void __user * arg) +{ + if (copy_to_user(arg, &cam->compression, + sizeof(cam->compression))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_s_jpegcomp(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_jpegcompression jc; + const enum et61x251_stream_state stream = cam->stream; + int err = 0; + + if (copy_from_user(&jc, arg, sizeof(jc))) + return -EFAULT; + + if (jc.quality != 0 && jc.quality != 1) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = et61x251_stream_interrupt(cam))) + return err; + + err += et61x251_set_compression(cam, &jc); + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " + "problems. To use the camera, close and open " + "/dev/video%d again.", cam->v4ldev->minor); + return -EIO; + } + + cam->compression.quality = jc.quality; + + cam->stream = stream; + + return 0; +} + + +static int +et61x251_vidioc_reqbufs(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_requestbuffers rb; + u32 i; + int err; + + if (copy_from_user(&rb, arg, sizeof(rb))) + return -EFAULT; + + if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + rb.memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + if (cam->io == IO_READ) { + DBG(3, "Close and open the device again to choose the mmap " + "I/O method"); + return -EINVAL; + } + + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_REQBUFS failed. " + "Previous buffers are still mapped."); + return -EINVAL; + } + + if (cam->stream == STREAM_ON) + if ((err = et61x251_stream_interrupt(cam))) + return err; + + et61x251_empty_framequeues(cam); + + et61x251_release_buffers(cam); + if (rb.count) + rb.count = et61x251_request_buffers(cam, rb.count, IO_MMAP); + + if (copy_to_user(arg, &rb, sizeof(rb))) { + et61x251_release_buffers(cam); + cam->io = IO_NONE; + return -EFAULT; + } + + cam->io = rb.count ? IO_MMAP : IO_NONE; + + return 0; +} + + +static int +et61x251_vidioc_querybuf(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_buffer b; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; + + memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); + + if (cam->frame[b.index].vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; + + if (cam->frame[b.index].state == F_DONE) + b.flags |= V4L2_BUF_FLAG_DONE; + else if (cam->frame[b.index].state != F_UNUSED) + b.flags |= V4L2_BUF_FLAG_QUEUED; + + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_qbuf(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_buffer b; + unsigned long lock_flags; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; + + if (cam->frame[b.index].state != F_UNUSED) + return -EINVAL; + + cam->frame[b.index].state = F_QUEUED; + + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + PDBGG("Frame #%lu queued", (unsigned long)b.index); + + return 0; +} + + +static int +et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp, + void __user * arg) +{ + struct v4l2_buffer b; + struct et61x251_frame_t *f; + unsigned long lock_flags; + long timeout; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP) + return -EINVAL; + + if (list_empty(&cam->outqueue)) { + if (cam->stream == STREAM_OFF) + return -EINVAL; + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) + return timeout; + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + if (!timeout || (cam->state & DEV_MISCONFIGURED)) + return -EIO; + } + + spin_lock_irqsave(&cam->queue_lock, lock_flags); + f = list_entry(cam->outqueue.next, struct et61x251_frame_t, frame); + list_del(cam->outqueue.next); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + f->state = F_UNUSED; + + memcpy(&b, &f->buf, sizeof(b)); + if (f->vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; + + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + + PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); + + return 0; +} + + +static int +et61x251_vidioc_streamon(struct et61x251_device* cam, void __user * arg) +{ + int type; + + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (list_empty(&cam->inqueue)) + return -EINVAL; + + cam->stream = STREAM_ON; + + DBG(3, "Stream on"); + + return 0; +} + + +static int +et61x251_vidioc_streamoff(struct et61x251_device* cam, void __user * arg) +{ + int type, err; + + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = et61x251_stream_interrupt(cam))) + return err; + + et61x251_empty_framequeues(cam); + + DBG(3, "Stream off"); + + return 0; +} + + +static int +et61x251_vidioc_g_parm(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + return 0; +} + + +static int +et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + + if (sp.parm.capture.readbuffers == 0) + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (sp.parm.capture.readbuffers > ET61X251_MAX_FRAMES) + sp.parm.capture.readbuffers = ET61X251_MAX_FRAMES; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + cam->nreadbuffers = sp.parm.capture.readbuffers; + + return 0; +} + + +static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, + unsigned int cmd, void __user * arg) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + + switch (cmd) { + + case VIDIOC_QUERYCAP: + return et61x251_vidioc_querycap(cam, arg); + + case VIDIOC_ENUMINPUT: + return et61x251_vidioc_enuminput(cam, arg); + + case VIDIOC_G_INPUT: + return et61x251_vidioc_g_input(cam, arg); + + case VIDIOC_S_INPUT: + return et61x251_vidioc_s_input(cam, arg); + + case VIDIOC_QUERYCTRL: + return et61x251_vidioc_query_ctrl(cam, arg); + + case VIDIOC_G_CTRL: + return et61x251_vidioc_g_ctrl(cam, arg); + + case VIDIOC_S_CTRL_OLD: + case VIDIOC_S_CTRL: + return et61x251_vidioc_s_ctrl(cam, arg); + + case VIDIOC_CROPCAP_OLD: + case VIDIOC_CROPCAP: + return et61x251_vidioc_cropcap(cam, arg); + + case VIDIOC_G_CROP: + return et61x251_vidioc_g_crop(cam, arg); + + case VIDIOC_S_CROP: + return et61x251_vidioc_s_crop(cam, arg); + + case VIDIOC_ENUM_FMT: + return et61x251_vidioc_enum_fmt(cam, arg); + + case VIDIOC_G_FMT: + return et61x251_vidioc_g_fmt(cam, arg); + + case VIDIOC_TRY_FMT: + case VIDIOC_S_FMT: + return et61x251_vidioc_try_s_fmt(cam, cmd, arg); + + case VIDIOC_G_JPEGCOMP: + return et61x251_vidioc_g_jpegcomp(cam, arg); + + case VIDIOC_S_JPEGCOMP: + return et61x251_vidioc_s_jpegcomp(cam, arg); + + case VIDIOC_REQBUFS: + return et61x251_vidioc_reqbufs(cam, arg); + + case VIDIOC_QUERYBUF: + return et61x251_vidioc_querybuf(cam, arg); + + case VIDIOC_QBUF: + return et61x251_vidioc_qbuf(cam, arg); + + case VIDIOC_DQBUF: + return et61x251_vidioc_dqbuf(cam, filp, arg); + + case VIDIOC_STREAMON: + return et61x251_vidioc_streamon(cam, arg); + + case VIDIOC_STREAMOFF: + return et61x251_vidioc_streamoff(cam, arg); + + case VIDIOC_G_PARM: + return et61x251_vidioc_g_parm(cam, arg); + + case VIDIOC_S_PARM_OLD: + case VIDIOC_S_PARM: + return et61x251_vidioc_s_parm(cam, arg); + + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case VIDIOC_QUERYSTD: + case VIDIOC_ENUMSTD: + case VIDIOC_QUERYMENU: + return -EINVAL; + + default: + return -EINVAL; + + } +} + + +static int et61x251_ioctl(struct inode* inode, struct file* filp, + unsigned int cmd, unsigned long arg) +{ + struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + int err = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + V4LDBG(3, "et61x251", cmd); + + err = et61x251_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); + + mutex_unlock(&cam->fileop_mutex); + + return err; +} + + +static struct file_operations et61x251_fops = { + .owner = THIS_MODULE, + .open = et61x251_open, + .release = et61x251_release, + .ioctl = et61x251_ioctl, + .read = et61x251_read, + .poll = et61x251_poll, + .mmap = et61x251_mmap, + .llseek = no_llseek, +}; + +/*****************************************************************************/ + +/* It exists a single interface only. We do not need to validate anything. */ +static int +et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct et61x251_device* cam; + static unsigned int dev_nr = 0; + unsigned int i; + int err = 0; + + if (!(cam = kzalloc(sizeof(struct et61x251_device), GFP_KERNEL))) + return -ENOMEM; + + cam->usbdev = udev; + + if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { + DBG(1, "kmalloc() failed"); + err = -ENOMEM; + goto fail; + } + + if (!(cam->v4ldev = video_device_alloc())) { + DBG(1, "video_device_alloc() failed"); + err = -ENOMEM; + goto fail; + } + + mutex_init(&cam->dev_mutex); + + DBG(2, "ET61X[12]51 PC Camera Controller detected " + "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); + + for (i = 0; et61x251_sensor_table[i]; i++) { + err = et61x251_sensor_table[i](cam); + if (!err) + break; + } + + if (!err) + DBG(2, "%s image sensor detected", cam->sensor.name); + else { + DBG(1, "No supported image sensor detected"); + err = -ENODEV; + goto fail; + } + + if (et61x251_init(cam)) { + DBG(1, "Initialization failed. I will retry on open()."); + cam->state |= DEV_MISCONFIGURED; + } + + strcpy(cam->v4ldev->name, "ET61X[12]51 PC Camera"); + cam->v4ldev->owner = THIS_MODULE; + cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; + cam->v4ldev->hardware = 0; + cam->v4ldev->fops = &et61x251_fops; + cam->v4ldev->minor = video_nr[dev_nr]; + cam->v4ldev->release = video_device_release; + video_set_drvdata(cam->v4ldev, cam); + + mutex_lock(&cam->dev_mutex); + + err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, + video_nr[dev_nr]); + if (err) { + DBG(1, "V4L2 device registration failed"); + if (err == -ENFILE && video_nr[dev_nr] == -1) + DBG(1, "Free /dev/videoX node not found"); + video_nr[dev_nr] = -1; + dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; + mutex_unlock(&cam->dev_mutex); + goto fail; + } + + DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); + + cam->module_param.force_munmap = force_munmap[dev_nr]; + cam->module_param.frame_timeout = frame_timeout[dev_nr]; + + dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; + +#ifdef CONFIG_VIDEO_ADV_DEBUG + et61x251_create_sysfs(cam); + DBG(2, "Optional device control through 'sysfs' interface ready"); +#endif + + usb_set_intfdata(intf, cam); + + mutex_unlock(&cam->dev_mutex); + + return 0; + +fail: + if (cam) { + kfree(cam->control_buffer); + if (cam->v4ldev) + video_device_release(cam->v4ldev); + kfree(cam); + } + return err; +} + + +static void et61x251_usb_disconnect(struct usb_interface* intf) +{ + struct et61x251_device* cam = usb_get_intfdata(intf); + + if (!cam) + return; + + down_write(&et61x251_disconnect); + + mutex_lock(&cam->dev_mutex); + + DBG(2, "Disconnecting %s...", cam->v4ldev->name); + + wake_up_interruptible_all(&cam->open); + + if (cam->users) { + DBG(2, "Device /dev/video%d is open! Deregistration and " + "memory deallocation are deferred on close.", + cam->v4ldev->minor); + cam->state |= DEV_MISCONFIGURED; + et61x251_stop_transfer(cam); + cam->state |= DEV_DISCONNECTED; + wake_up_interruptible(&cam->wait_frame); + wake_up(&cam->wait_stream); + usb_get_dev(cam->usbdev); + } else { + cam->state |= DEV_DISCONNECTED; + et61x251_release_resources(cam); + } + + mutex_unlock(&cam->dev_mutex); + + if (!cam->users) + kfree(cam); + + up_write(&et61x251_disconnect); +} + + +static struct usb_driver et61x251_usb_driver = { + .name = "et61x251", + .id_table = et61x251_id_table, + .probe = et61x251_usb_probe, + .disconnect = et61x251_usb_disconnect, +}; + +/*****************************************************************************/ + +static int __init et61x251_module_init(void) +{ + int err = 0; + + KDBG(2, ET61X251_MODULE_NAME " v" ET61X251_MODULE_VERSION); + KDBG(3, ET61X251_MODULE_AUTHOR); + + if ((err = usb_register(&et61x251_usb_driver))) + KDBG(1, "usb_register() failed"); + + return err; +} + + +static void __exit et61x251_module_exit(void) +{ + usb_deregister(&et61x251_usb_driver); +} + + +module_init(et61x251_module_init); +module_exit(et61x251_module_exit); diff --git a/drivers/media/video/et61x251/et61x251_sensor.h b/drivers/media/video/et61x251/et61x251_sensor.h new file mode 100644 index 000000000000..56841ae8a207 --- /dev/null +++ b/drivers/media/video/et61x251/et61x251_sensor.h @@ -0,0 +1,116 @@ +/*************************************************************************** + * API for image sensors connected to ET61X[12]51 PC Camera Controllers * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * 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. * + ***************************************************************************/ + +#ifndef _ET61X251_SENSOR_H_ +#define _ET61X251_SENSOR_H_ + +#include +#include +#include +#include +#include +#include + +struct et61x251_device; +struct et61x251_sensor; + +/*****************************************************************************/ + +extern int et61x251_probe_tas5130d1b(struct et61x251_device* cam); + +#define ET61X251_SENSOR_TABLE \ +/* Weak detections must go at the end of the list */ \ +static int (*et61x251_sensor_table[])(struct et61x251_device*) = { \ + &et61x251_probe_tas5130d1b, \ + NULL, \ +}; + +extern struct et61x251_device* +et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id); + +extern void +et61x251_attach_sensor(struct et61x251_device* cam, + struct et61x251_sensor* sensor); + +/*****************************************************************************/ + +extern int et61x251_write_reg(struct et61x251_device*, u8 value, u16 index); +extern int et61x251_read_reg(struct et61x251_device*, u16 index); +extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value); +extern int et61x251_i2c_read(struct et61x251_device*, u8 address); +extern int et61x251_i2c_try_write(struct et61x251_device*, + struct et61x251_sensor*, u8 address, + u8 value); +extern int et61x251_i2c_try_read(struct et61x251_device*, + struct et61x251_sensor*, u8 address); +extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1, + u8 data2, u8 data3, u8 data4, u8 data5, + u8 data6, u8 data7, u8 data8, u8 address); + +/*****************************************************************************/ + +enum et61x251_i2c_sysfs_ops { + ET61X251_I2C_READ = 0x01, + ET61X251_I2C_WRITE = 0x02, +}; + +enum et61x251_i2c_interface { + ET61X251_I2C_2WIRES, + ET61X251_I2C_3WIRES, +}; + +/* Repeat start condition when RSTA is high */ +enum et61x251_i2c_rsta { + ET61X251_I2C_RSTA_STOP = 0x00, /* stop then start */ + ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */ +}; + +#define ET61X251_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 + +struct et61x251_sensor { + char name[32]; + + enum et61x251_i2c_sysfs_ops sysfs_ops; + + enum et61x251_i2c_interface interface; + u8 i2c_slave_id; + enum et61x251_i2c_rsta rsta; + struct v4l2_rect active_pixel; /* left and top define FVSX and FVSY */ + + struct v4l2_queryctrl qctrl[ET61X251_MAX_CTRLS]; + struct v4l2_cropcap cropcap; + struct v4l2_pix_format pix_format; + + int (*init)(struct et61x251_device* cam); + int (*get_ctrl)(struct et61x251_device* cam, + struct v4l2_control* ctrl); + int (*set_ctrl)(struct et61x251_device* cam, + const struct v4l2_control* ctrl); + int (*set_crop)(struct et61x251_device* cam, + const struct v4l2_rect* rect); + int (*set_pix_format)(struct et61x251_device* cam, + const struct v4l2_pix_format* pix); + + /* Private */ + struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS]; + struct v4l2_rect _rect; +}; + +#endif /* _ET61X251_SENSOR_H_ */ diff --git a/drivers/media/video/et61x251/et61x251_tas5130d1b.c b/drivers/media/video/et61x251/et61x251_tas5130d1b.c new file mode 100644 index 000000000000..3998d76a307a --- /dev/null +++ b/drivers/media/video/et61x251/et61x251_tas5130d1b.c @@ -0,0 +1,141 @@ +/*************************************************************************** + * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51 * + * PC Camera Controllers * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * 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 "et61x251_sensor.h" + + +static int tas5130d1b_init(struct et61x251_device* cam) +{ + int err = 0; + + err += et61x251_write_reg(cam, 0x14, 0x01); + err += et61x251_write_reg(cam, 0x1b, 0x02); + err += et61x251_write_reg(cam, 0x02, 0x12); + err += et61x251_write_reg(cam, 0x0e, 0x60); + err += et61x251_write_reg(cam, 0x80, 0x61); + err += et61x251_write_reg(cam, 0xf0, 0x62); + err += et61x251_write_reg(cam, 0x03, 0x63); + err += et61x251_write_reg(cam, 0x14, 0x64); + err += et61x251_write_reg(cam, 0xf4, 0x65); + err += et61x251_write_reg(cam, 0x01, 0x66); + err += et61x251_write_reg(cam, 0x05, 0x67); + err += et61x251_write_reg(cam, 0x8f, 0x68); + err += et61x251_write_reg(cam, 0x0f, 0x8d); + err += et61x251_write_reg(cam, 0x08, 0x8e); + + return err; +} + + +static int tas5130d1b_set_ctrl(struct et61x251_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_GAIN: + err += et61x251_i2c_raw_write(cam, 2, 0x20, + 0xf6-ctrl->value, 0, 0, 0, + 0, 0, 0, 0); + break; + case V4L2_CID_EXPOSURE: + err += et61x251_i2c_raw_write(cam, 2, 0x40, + 0x47-ctrl->value, 0, 0, 0, + 0, 0, 0, 0); + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + +static struct et61x251_sensor tas5130d1b = { + .name = "TAS5130D1B", + .interface = ET61X251_I2C_3WIRES, + .rsta = ET61X251_I2C_RSTA_STOP, + .active_pixel = { + .left = 106, + .top = 13, + }, + .init = &tas5130d1b_init, + .qctrl = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0xf6, + .step = 0x02, + .default_value = 0x0d, + .flags = 0, + }, + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0x47, + .step = 0x01, + .default_value = 0x23, + .flags = 0, + }, + }, + .set_ctrl = &tas5130d1b_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, +}; + + +int et61x251_probe_tas5130d1b(struct et61x251_device* cam) +{ + const struct usb_device_id tas5130d1b_id_table[] = { + { USB_DEVICE(0x102c, 0x6251), }, + { } + }; + + /* Sensor detection is based on USB pid/vid */ + if (!et61x251_match_id(cam, tas5130d1b_id_table)) + return -ENODEV; + + et61x251_attach_sensor(cam, &tas5130d1b); + + return 0; +} diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c new file mode 100644 index 000000000000..da44579d6f29 --- /dev/null +++ b/drivers/media/video/ov511.c @@ -0,0 +1,5932 @@ +/* + * OmniVision OV511 Camera-to-USB Bridge Driver + * + * Copyright (c) 1999-2003 Mark W. McClelland + * Original decompression code Copyright 1998-2000 OmniVision Technologies + * Many improvements by Bret Wallach + * Color fixes by by Orion Sky Lawlor (2/26/2000) + * Snapshot code by Kevin Moore + * OV7620 fixes by Charl P. Botha + * Changes by Claudio Matsuoka + * Original SAA7111A code by Dave Perks + * URB error messages from pwc driver by Nemosoft + * generic_ioctl() code from videodev.c by Gerd Knorr and Alan Cox + * Memory management (rvmalloc) code from bttv driver, by Gerd Knorr and others + * + * Based on the Linux CPiA driver written by Peter Pregler, + * Scott J. Bertin and Johannes Erdfelt. + * + * Please see the file: Documentation/usb/ov511.txt + * and the website at: http://alpha.dyndns.org/ov511 + * for more info. + * + * 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 +#include +#include + +#if defined (__i386__) + #include +#endif + +#include "ov511.h" + +/* + * Version Information + */ +#define DRIVER_VERSION "v1.64 for Linux 2.5" +#define EMAIL "mark@alpha.dyndns.org" +#define DRIVER_AUTHOR "Mark McClelland & Bret Wallach \ + & Orion Sky Lawlor & Kevin Moore & Charl P. Botha \ + & Claudio Matsuoka " +#define DRIVER_DESC "ov511 USB Camera Driver" + +#define OV511_I2C_RETRIES 3 +#define ENABLE_Y_QUANTABLE 1 +#define ENABLE_UV_QUANTABLE 1 + +#define OV511_MAX_UNIT_VIDEO 16 + +/* Pixel count * bytes per YUV420 pixel (1.5) */ +#define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3 / 2) + +#define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval)) + +/* Max size * bytes per YUV420 pixel (1.5) + one extra isoc frame for safety */ +#define MAX_RAW_DATA_SIZE(w, h) ((w) * (h) * 3 / 2 + 1024) + +#define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM) + +/********************************************************************** + * Module Parameters + * (See ov511.txt for detailed descriptions of these) + **********************************************************************/ + +/* These variables (and all static globals) default to zero */ +static int autobright = 1; +static int autogain = 1; +static int autoexp = 1; +static int debug; +static int snapshot; +static int cams = 1; +static int compress; +static int testpat; +static int dumppix; +static int led = 1; +static int dump_bridge; +static int dump_sensor; +static int printph; +static int phy = 0x1f; +static int phuv = 0x05; +static int pvy = 0x06; +static int pvuv = 0x06; +static int qhy = 0x14; +static int qhuv = 0x03; +static int qvy = 0x04; +static int qvuv = 0x04; +static int lightfreq; +static int bandingfilter; +static int clockdiv = -1; +static int packetsize = -1; +static int framedrop = -1; +static int fastset; +static int force_palette; +static int backlight; +static int unit_video[OV511_MAX_UNIT_VIDEO]; +static int remove_zeros; +static int mirror; +static int ov518_color; + +module_param(autobright, int, 0); +MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness"); +module_param(autogain, int, 0); +MODULE_PARM_DESC(autogain, "Sensor automatically changes gain"); +module_param(autoexp, int, 0); +MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure"); +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, + "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max"); +module_param(snapshot, int, 0); +MODULE_PARM_DESC(snapshot, "Enable snapshot mode"); +module_param(cams, int, 0); +MODULE_PARM_DESC(cams, "Number of simultaneous cameras"); +module_param(compress, int, 0); +MODULE_PARM_DESC(compress, "Turn on compression"); +module_param(testpat, int, 0); +MODULE_PARM_DESC(testpat, + "Replace image with vertical bar testpattern (only partially working)"); +module_param(dumppix, int, 0); +MODULE_PARM_DESC(dumppix, "Dump raw pixel data"); +module_param(led, int, 0); +MODULE_PARM_DESC(led, + "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)"); +module_param(dump_bridge, int, 0); +MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers"); +module_param(dump_sensor, int, 0); +MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers"); +module_param(printph, int, 0); +MODULE_PARM_DESC(printph, "Print frame start/end headers"); +module_param(phy, int, 0); +MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)"); +module_param(phuv, int, 0); +MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)"); +module_param(pvy, int, 0); +MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)"); +module_param(pvuv, int, 0); +MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)"); +module_param(qhy, int, 0); +MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)"); +module_param(qhuv, int, 0); +MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)"); +module_param(qvy, int, 0); +MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)"); +module_param(qvuv, int, 0); +MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)"); +module_param(lightfreq, int, 0); +MODULE_PARM_DESC(lightfreq, + "Light frequency. Set to 50 or 60 Hz, or zero for default settings"); +module_param(bandingfilter, int, 0); +MODULE_PARM_DESC(bandingfilter, + "Enable banding filter (to reduce effects of fluorescent lighting)"); +module_param(clockdiv, int, 0); +MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value"); +module_param(packetsize, int, 0); +MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size"); +module_param(framedrop, int, 0); +MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting"); +module_param(fastset, int, 0); +MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately"); +module_param(force_palette, int, 0); +MODULE_PARM_DESC(force_palette, "Force the palette to a specific value"); +module_param(backlight, int, 0); +MODULE_PARM_DESC(backlight, "For objects that are lit from behind"); +static int num_uv; +module_param_array(unit_video, int, &num_uv, 0); +MODULE_PARM_DESC(unit_video, + "Force use of specific minor number(s). 0 is not allowed."); +module_param(remove_zeros, int, 0); +MODULE_PARM_DESC(remove_zeros, + "Remove zero-padding from uncompressed incoming data"); +module_param(mirror, int, 0); +MODULE_PARM_DESC(mirror, "Reverse image horizontally"); +module_param(ov518_color, int, 0); +MODULE_PARM_DESC(ov518_color, "Enable OV518 color (experimental)"); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +/********************************************************************** + * Miscellaneous Globals + **********************************************************************/ + +static struct usb_driver ov511_driver; + +/* Number of times to retry a failed I2C transaction. Increase this if you + * are getting "Failed to read sensor ID..." */ +static const int i2c_detect_tries = 5; + +static struct usb_device_id device_table [] = { + { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) }, + { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) }, + { USB_DEVICE(VEND_OMNIVISION, PROD_OV518) }, + { USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) }, + { USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, device_table); + +static unsigned char yQuanTable511[] = OV511_YQUANTABLE; +static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE; +static unsigned char yQuanTable518[] = OV518_YQUANTABLE; +static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE; + +/********************************************************************** + * Symbolic Names + **********************************************************************/ + +/* Known OV511-based cameras */ +static struct symbolic_list camlist[] = { + { 0, "Generic Camera (no ID)" }, + { 1, "Mustek WCam 3X" }, + { 3, "D-Link DSB-C300" }, + { 4, "Generic OV511/OV7610" }, + { 5, "Puretek PT-6007" }, + { 6, "Lifeview USB Life TV (NTSC)" }, + { 21, "Creative Labs WebCam 3" }, + { 22, "Lifeview USB Life TV (PAL D/K+B/G)" }, + { 36, "Koala-Cam" }, + { 38, "Lifeview USB Life TV (PAL)" }, + { 41, "Samsung Anycam MPC-M10" }, + { 43, "Mtekvision Zeca MV402" }, + { 46, "Suma eON" }, + { 70, "Lifeview USB Life TV (PAL/SECAM)" }, + { 100, "Lifeview RoboCam" }, + { 102, "AverMedia InterCam Elite" }, + { 112, "MediaForte MV300" }, /* or OV7110 evaluation kit */ + { 134, "Ezonics EZCam II" }, + { 192, "Webeye 2000B" }, + { 253, "Alpha Vision Tech. AlphaCam SE" }, + { -1, NULL } +}; + +/* Video4Linux1 Palettes */ +static struct symbolic_list v4l1_plist[] = { + { VIDEO_PALETTE_GREY, "GREY" }, + { VIDEO_PALETTE_HI240, "HI240" }, + { VIDEO_PALETTE_RGB565, "RGB565" }, + { VIDEO_PALETTE_RGB24, "RGB24" }, + { VIDEO_PALETTE_RGB32, "RGB32" }, + { VIDEO_PALETTE_RGB555, "RGB555" }, + { VIDEO_PALETTE_YUV422, "YUV422" }, + { VIDEO_PALETTE_YUYV, "YUYV" }, + { VIDEO_PALETTE_UYVY, "UYVY" }, + { VIDEO_PALETTE_YUV420, "YUV420" }, + { VIDEO_PALETTE_YUV411, "YUV411" }, + { VIDEO_PALETTE_RAW, "RAW" }, + { VIDEO_PALETTE_YUV422P,"YUV422P" }, + { VIDEO_PALETTE_YUV411P,"YUV411P" }, + { VIDEO_PALETTE_YUV420P,"YUV420P" }, + { VIDEO_PALETTE_YUV410P,"YUV410P" }, + { -1, NULL } +}; + +static struct symbolic_list brglist[] = { + { BRG_OV511, "OV511" }, + { BRG_OV511PLUS, "OV511+" }, + { BRG_OV518, "OV518" }, + { BRG_OV518PLUS, "OV518+" }, + { -1, NULL } +}; + +static struct symbolic_list senlist[] = { + { SEN_OV76BE, "OV76BE" }, + { SEN_OV7610, "OV7610" }, + { SEN_OV7620, "OV7620" }, + { SEN_OV7620AE, "OV7620AE" }, + { SEN_OV6620, "OV6620" }, + { SEN_OV6630, "OV6630" }, + { SEN_OV6630AE, "OV6630AE" }, + { SEN_OV6630AF, "OV6630AF" }, + { SEN_OV8600, "OV8600" }, + { SEN_KS0127, "KS0127" }, + { SEN_KS0127B, "KS0127B" }, + { SEN_SAA7111A, "SAA7111A" }, + { -1, NULL } +}; + +/* URB error codes: */ +static struct symbolic_list urb_errlist[] = { + { -ENOSR, "Buffer error (overrun)" }, + { -EPIPE, "Stalled (device not responding)" }, + { -EOVERFLOW, "Babble (bad cable?)" }, + { -EPROTO, "Bit-stuff error (bad cable?)" }, + { -EILSEQ, "CRC/Timeout" }, + { -ETIMEDOUT, "NAK (device does not respond)" }, + { -1, NULL } +}; + +/********************************************************************** + * Memory management + **********************************************************************/ +static void * +rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + +static void +rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + +/********************************************************************** + * + * Register I/O + * + **********************************************************************/ + +/* Write an OV51x register */ +static int +reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value) +{ + int rc; + + PDEBUG(5, "0x%02X:0x%02X", reg, value); + + mutex_lock(&ov->cbuf_lock); + ov->cbuf[0] = value; + rc = usb_control_msg(ov->dev, + usb_sndctrlpipe(ov->dev, 0), + (ov->bclass == BCL_OV518)?1:2 /* REG_IO */, + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, (__u16)reg, &ov->cbuf[0], 1, 1000); + mutex_unlock(&ov->cbuf_lock); + + if (rc < 0) + err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc)); + + return rc; +} + +/* Read from an OV51x register */ +/* returns: negative is error, pos or zero is data */ +static int +reg_r(struct usb_ov511 *ov, unsigned char reg) +{ + int rc; + + mutex_lock(&ov->cbuf_lock); + rc = usb_control_msg(ov->dev, + usb_rcvctrlpipe(ov->dev, 0), + (ov->bclass == BCL_OV518)?1:3 /* REG_IO */, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, (__u16)reg, &ov->cbuf[0], 1, 1000); + + if (rc < 0) { + err("reg read: error %d: %s", rc, symbolic(urb_errlist, rc)); + } else { + rc = ov->cbuf[0]; + PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]); + } + + mutex_unlock(&ov->cbuf_lock); + + return rc; +} + +/* + * Writes bits at positions specified by mask to an OV51x reg. Bits that are in + * the same position as 1's in "mask" are cleared and set to "value". Bits + * that are in the same position as 0's in "mask" are preserved, regardless + * of their respective state in "value". + */ +static int +reg_w_mask(struct usb_ov511 *ov, + unsigned char reg, + unsigned char value, + unsigned char mask) +{ + int ret; + unsigned char oldval, newval; + + ret = reg_r(ov, reg); + if (ret < 0) + return ret; + + oldval = (unsigned char) ret; + oldval &= (~mask); /* Clear the masked bits */ + value &= mask; /* Enforce mask on value */ + newval = oldval | value; /* Set the desired bits */ + + return (reg_w(ov, reg, newval)); +} + +/* + * Writes multiple (n) byte value to a single register. Only valid with certain + * registers (0x30 and 0xc4 - 0xce). + */ +static int +ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n) +{ + int rc; + + PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n); + + mutex_lock(&ov->cbuf_lock); + + *((__le32 *)ov->cbuf) = __cpu_to_le32(val); + + rc = usb_control_msg(ov->dev, + usb_sndctrlpipe(ov->dev, 0), + 1 /* REG_IO */, + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, (__u16)reg, ov->cbuf, n, 1000); + mutex_unlock(&ov->cbuf_lock); + + if (rc < 0) + err("reg write multiple: error %d: %s", rc, + symbolic(urb_errlist, rc)); + + return rc; +} + +static int +ov511_upload_quan_tables(struct usb_ov511 *ov) +{ + unsigned char *pYTable = yQuanTable511; + unsigned char *pUVTable = uvQuanTable511; + unsigned char val0, val1; + int i, rc, reg = R511_COMP_LUT_BEGIN; + + PDEBUG(4, "Uploading quantization tables"); + + for (i = 0; i < OV511_QUANTABLESIZE / 2; i++) { + if (ENABLE_Y_QUANTABLE) { + val0 = *pYTable++; + val1 = *pYTable++; + val0 &= 0x0f; + val1 &= 0x0f; + val0 |= val1 << 4; + rc = reg_w(ov, reg, val0); + if (rc < 0) + return rc; + } + + if (ENABLE_UV_QUANTABLE) { + val0 = *pUVTable++; + val1 = *pUVTable++; + val0 &= 0x0f; + val1 &= 0x0f; + val0 |= val1 << 4; + rc = reg_w(ov, reg + OV511_QUANTABLESIZE/2, val0); + if (rc < 0) + return rc; + } + + reg++; + } + + return 0; +} + +/* OV518 quantization tables are 8x4 (instead of 8x8) */ +static int +ov518_upload_quan_tables(struct usb_ov511 *ov) +{ + unsigned char *pYTable = yQuanTable518; + unsigned char *pUVTable = uvQuanTable518; + unsigned char val0, val1; + int i, rc, reg = R511_COMP_LUT_BEGIN; + + PDEBUG(4, "Uploading quantization tables"); + + for (i = 0; i < OV518_QUANTABLESIZE / 2; i++) { + if (ENABLE_Y_QUANTABLE) { + val0 = *pYTable++; + val1 = *pYTable++; + val0 &= 0x0f; + val1 &= 0x0f; + val0 |= val1 << 4; + rc = reg_w(ov, reg, val0); + if (rc < 0) + return rc; + } + + if (ENABLE_UV_QUANTABLE) { + val0 = *pUVTable++; + val1 = *pUVTable++; + val0 &= 0x0f; + val1 &= 0x0f; + val0 |= val1 << 4; + rc = reg_w(ov, reg + OV518_QUANTABLESIZE/2, val0); + if (rc < 0) + return rc; + } + + reg++; + } + + return 0; +} + +static int +ov51x_reset(struct usb_ov511 *ov, unsigned char reset_type) +{ + int rc; + + /* Setting bit 0 not allowed on 518/518Plus */ + if (ov->bclass == BCL_OV518) + reset_type &= 0xfe; + + PDEBUG(4, "Reset: type=0x%02X", reset_type); + + rc = reg_w(ov, R51x_SYS_RESET, reset_type); + rc = reg_w(ov, R51x_SYS_RESET, 0); + + if (rc < 0) + err("reset: command failed"); + + return rc; +} + +/********************************************************************** + * + * Low-level I2C I/O functions + * + **********************************************************************/ + +/* NOTE: Do not call this function directly! + * The OV518 I2C I/O procedure is different, hence, this function. + * This is normally only called from i2c_w(). Note that this function + * always succeeds regardless of whether the sensor is present and working. + */ +static int +ov518_i2c_write_internal(struct usb_ov511 *ov, + unsigned char reg, + unsigned char value) +{ + int rc; + + PDEBUG(5, "0x%02X:0x%02X", reg, value); + + /* Select camera register */ + rc = reg_w(ov, R51x_I2C_SADDR_3, reg); + if (rc < 0) + return rc; + + /* Write "value" to I2C data port of OV511 */ + rc = reg_w(ov, R51x_I2C_DATA, value); + if (rc < 0) + return rc; + + /* Initiate 3-byte write cycle */ + rc = reg_w(ov, R518_I2C_CTL, 0x01); + if (rc < 0) + return rc; + + return 0; +} + +/* NOTE: Do not call this function directly! */ +static int +ov511_i2c_write_internal(struct usb_ov511 *ov, + unsigned char reg, + unsigned char value) +{ + int rc, retries; + + PDEBUG(5, "0x%02X:0x%02X", reg, value); + + /* Three byte write cycle */ + for (retries = OV511_I2C_RETRIES; ; ) { + /* Select camera register */ + rc = reg_w(ov, R51x_I2C_SADDR_3, reg); + if (rc < 0) + break; + + /* Write "value" to I2C data port of OV511 */ + rc = reg_w(ov, R51x_I2C_DATA, value); + if (rc < 0) + break; + + /* Initiate 3-byte write cycle */ + rc = reg_w(ov, R511_I2C_CTL, 0x01); + if (rc < 0) + break; + + /* Retry until idle */ + do + rc = reg_r(ov, R511_I2C_CTL); + while (rc > 0 && ((rc&1) == 0)); + if (rc < 0) + break; + + /* Ack? */ + if ((rc&2) == 0) { + rc = 0; + break; + } +#if 0 + /* I2C abort */ + reg_w(ov, R511_I2C_CTL, 0x10); +#endif + if (--retries < 0) { + err("i2c write retries exhausted"); + rc = -1; + break; + } + } + + return rc; +} + +/* NOTE: Do not call this function directly! + * The OV518 I2C I/O procedure is different, hence, this function. + * This is normally only called from i2c_r(). Note that this function + * always succeeds regardless of whether the sensor is present and working. + */ +static int +ov518_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg) +{ + int rc, value; + + /* Select camera register */ + rc = reg_w(ov, R51x_I2C_SADDR_2, reg); + if (rc < 0) + return rc; + + /* Initiate 2-byte write cycle */ + rc = reg_w(ov, R518_I2C_CTL, 0x03); + if (rc < 0) + return rc; + + /* Initiate 2-byte read cycle */ + rc = reg_w(ov, R518_I2C_CTL, 0x05); + if (rc < 0) + return rc; + + value = reg_r(ov, R51x_I2C_DATA); + + PDEBUG(5, "0x%02X:0x%02X", reg, value); + + return value; +} + +/* NOTE: Do not call this function directly! + * returns: negative is error, pos or zero is data */ +static int +ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg) +{ + int rc, value, retries; + + /* Two byte write cycle */ + for (retries = OV511_I2C_RETRIES; ; ) { + /* Select camera register */ + rc = reg_w(ov, R51x_I2C_SADDR_2, reg); + if (rc < 0) + return rc; + + /* Initiate 2-byte write cycle */ + rc = reg_w(ov, R511_I2C_CTL, 0x03); + if (rc < 0) + return rc; + + /* Retry until idle */ + do + rc = reg_r(ov, R511_I2C_CTL); + while (rc > 0 && ((rc&1) == 0)); + if (rc < 0) + return rc; + + if ((rc&2) == 0) /* Ack? */ + break; + + /* I2C abort */ + reg_w(ov, R511_I2C_CTL, 0x10); + + if (--retries < 0) { + err("i2c write retries exhausted"); + return -1; + } + } + + /* Two byte read cycle */ + for (retries = OV511_I2C_RETRIES; ; ) { + /* Initiate 2-byte read cycle */ + rc = reg_w(ov, R511_I2C_CTL, 0x05); + if (rc < 0) + return rc; + + /* Retry until idle */ + do + rc = reg_r(ov, R511_I2C_CTL); + while (rc > 0 && ((rc&1) == 0)); + if (rc < 0) + return rc; + + if ((rc&2) == 0) /* Ack? */ + break; + + /* I2C abort */ + rc = reg_w(ov, R511_I2C_CTL, 0x10); + if (rc < 0) + return rc; + + if (--retries < 0) { + err("i2c read retries exhausted"); + return -1; + } + } + + value = reg_r(ov, R51x_I2C_DATA); + + PDEBUG(5, "0x%02X:0x%02X", reg, value); + + /* This is needed to make i2c_w() work */ + rc = reg_w(ov, R511_I2C_CTL, 0x05); + if (rc < 0) + return rc; + + return value; +} + +/* returns: negative is error, pos or zero is data */ +static int +i2c_r(struct usb_ov511 *ov, unsigned char reg) +{ + int rc; + + mutex_lock(&ov->i2c_lock); + + if (ov->bclass == BCL_OV518) + rc = ov518_i2c_read_internal(ov, reg); + else + rc = ov511_i2c_read_internal(ov, reg); + + mutex_unlock(&ov->i2c_lock); + + return rc; +} + +static int +i2c_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value) +{ + int rc; + + mutex_lock(&ov->i2c_lock); + + if (ov->bclass == BCL_OV518) + rc = ov518_i2c_write_internal(ov, reg, value); + else + rc = ov511_i2c_write_internal(ov, reg, value); + + mutex_unlock(&ov->i2c_lock); + + return rc; +} + +/* Do not call this function directly! */ +static int +ov51x_i2c_write_mask_internal(struct usb_ov511 *ov, + unsigned char reg, + unsigned char value, + unsigned char mask) +{ + int rc; + unsigned char oldval, newval; + + if (mask == 0xff) { + newval = value; + } else { + if (ov->bclass == BCL_OV518) + rc = ov518_i2c_read_internal(ov, reg); + else + rc = ov511_i2c_read_internal(ov, reg); + if (rc < 0) + return rc; + + oldval = (unsigned char) rc; + oldval &= (~mask); /* Clear the masked bits */ + value &= mask; /* Enforce mask on value */ + newval = oldval | value; /* Set the desired bits */ + } + + if (ov->bclass == BCL_OV518) + return (ov518_i2c_write_internal(ov, reg, newval)); + else + return (ov511_i2c_write_internal(ov, reg, newval)); +} + +/* Writes bits at positions specified by mask to an I2C reg. Bits that are in + * the same position as 1's in "mask" are cleared and set to "value". Bits + * that are in the same position as 0's in "mask" are preserved, regardless + * of their respective state in "value". + */ +static int +i2c_w_mask(struct usb_ov511 *ov, + unsigned char reg, + unsigned char value, + unsigned char mask) +{ + int rc; + + mutex_lock(&ov->i2c_lock); + rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask); + mutex_unlock(&ov->i2c_lock); + + return rc; +} + +/* Set the read and write slave IDs. The "slave" argument is the write slave, + * and the read slave will be set to (slave + 1). ov->i2c_lock should be held + * when calling this. This should not be called from outside the i2c I/O + * functions. + */ +static int +i2c_set_slave_internal(struct usb_ov511 *ov, unsigned char slave) +{ + int rc; + + rc = reg_w(ov, R51x_I2C_W_SID, slave); + if (rc < 0) + return rc; + + rc = reg_w(ov, R51x_I2C_R_SID, slave + 1); + if (rc < 0) + return rc; + + return 0; +} + +/* Write to a specific I2C slave ID and register, using the specified mask */ +static int +i2c_w_slave(struct usb_ov511 *ov, + unsigned char slave, + unsigned char reg, + unsigned char value, + unsigned char mask) +{ + int rc = 0; + + mutex_lock(&ov->i2c_lock); + + /* Set new slave IDs */ + rc = i2c_set_slave_internal(ov, slave); + if (rc < 0) + goto out; + + rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask); + +out: + /* Restore primary IDs */ + if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) + err("Couldn't restore primary I2C slave"); + + mutex_unlock(&ov->i2c_lock); + return rc; +} + +/* Read from a specific I2C slave ID and register */ +static int +i2c_r_slave(struct usb_ov511 *ov, + unsigned char slave, + unsigned char reg) +{ + int rc; + + mutex_lock(&ov->i2c_lock); + + /* Set new slave IDs */ + rc = i2c_set_slave_internal(ov, slave); + if (rc < 0) + goto out; + + if (ov->bclass == BCL_OV518) + rc = ov518_i2c_read_internal(ov, reg); + else + rc = ov511_i2c_read_internal(ov, reg); + +out: + /* Restore primary IDs */ + if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) + err("Couldn't restore primary I2C slave"); + + mutex_unlock(&ov->i2c_lock); + return rc; +} + +/* Sets I2C read and write slave IDs. Returns <0 for error */ +static int +ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid) +{ + int rc; + + mutex_lock(&ov->i2c_lock); + + rc = i2c_set_slave_internal(ov, sid); + if (rc < 0) + goto out; + + // FIXME: Is this actually necessary? + rc = ov51x_reset(ov, OV511_RESET_NOREGS); +out: + mutex_unlock(&ov->i2c_lock); + return rc; +} + +static int +write_regvals(struct usb_ov511 *ov, struct ov511_regvals * pRegvals) +{ + int rc; + + while (pRegvals->bus != OV511_DONE_BUS) { + if (pRegvals->bus == OV511_REG_BUS) { + if ((rc = reg_w(ov, pRegvals->reg, pRegvals->val)) < 0) + return rc; + } else if (pRegvals->bus == OV511_I2C_BUS) { + if ((rc = i2c_w(ov, pRegvals->reg, pRegvals->val)) < 0) + return rc; + } else { + err("Bad regval array"); + return -1; + } + pRegvals++; + } + return 0; +} + +#ifdef OV511_DEBUG +static void +dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn) +{ + int i, rc; + + for (i = reg1; i <= regn; i++) { + rc = i2c_r(ov, i); + info("Sensor[0x%02X] = 0x%02X", i, rc); + } +} + +static void +dump_i2c_regs(struct usb_ov511 *ov) +{ + info("I2C REGS"); + dump_i2c_range(ov, 0x00, 0x7C); +} + +static void +dump_reg_range(struct usb_ov511 *ov, int reg1, int regn) +{ + int i, rc; + + for (i = reg1; i <= regn; i++) { + rc = reg_r(ov, i); + info("OV511[0x%02X] = 0x%02X", i, rc); + } +} + +static void +ov511_dump_regs(struct usb_ov511 *ov) +{ + info("CAMERA INTERFACE REGS"); + dump_reg_range(ov, 0x10, 0x1f); + info("DRAM INTERFACE REGS"); + dump_reg_range(ov, 0x20, 0x23); + info("ISO FIFO REGS"); + dump_reg_range(ov, 0x30, 0x31); + info("PIO REGS"); + dump_reg_range(ov, 0x38, 0x39); + dump_reg_range(ov, 0x3e, 0x3e); + info("I2C REGS"); + dump_reg_range(ov, 0x40, 0x49); + info("SYSTEM CONTROL REGS"); + dump_reg_range(ov, 0x50, 0x55); + dump_reg_range(ov, 0x5e, 0x5f); + info("OmniCE REGS"); + dump_reg_range(ov, 0x70, 0x79); + /* NOTE: Quantization tables are not readable. You will get the value + * in reg. 0x79 for every table register */ + dump_reg_range(ov, 0x80, 0x9f); + dump_reg_range(ov, 0xa0, 0xbf); + +} + +static void +ov518_dump_regs(struct usb_ov511 *ov) +{ + info("VIDEO MODE REGS"); + dump_reg_range(ov, 0x20, 0x2f); + info("DATA PUMP AND SNAPSHOT REGS"); + dump_reg_range(ov, 0x30, 0x3f); + info("I2C REGS"); + dump_reg_range(ov, 0x40, 0x4f); + info("SYSTEM CONTROL AND VENDOR REGS"); + dump_reg_range(ov, 0x50, 0x5f); + info("60 - 6F"); + dump_reg_range(ov, 0x60, 0x6f); + info("70 - 7F"); + dump_reg_range(ov, 0x70, 0x7f); + info("Y QUANTIZATION TABLE"); + dump_reg_range(ov, 0x80, 0x8f); + info("UV QUANTIZATION TABLE"); + dump_reg_range(ov, 0x90, 0x9f); + info("A0 - BF"); + dump_reg_range(ov, 0xa0, 0xbf); + info("CBR"); + dump_reg_range(ov, 0xc0, 0xcf); +} +#endif + +/*****************************************************************************/ + +/* Temporarily stops OV511 from functioning. Must do this before changing + * registers while the camera is streaming */ +static inline int +ov51x_stop(struct usb_ov511 *ov) +{ + PDEBUG(4, "stopping"); + ov->stopped = 1; + if (ov->bclass == BCL_OV518) + return (reg_w_mask(ov, R51x_SYS_RESET, 0x3a, 0x3a)); + else + return (reg_w(ov, R51x_SYS_RESET, 0x3d)); +} + +/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not + * actually stopped (for performance). */ +static inline int +ov51x_restart(struct usb_ov511 *ov) +{ + if (ov->stopped) { + PDEBUG(4, "restarting"); + ov->stopped = 0; + + /* Reinitialize the stream */ + if (ov->bclass == BCL_OV518) + reg_w(ov, 0x2f, 0x80); + + return (reg_w(ov, R51x_SYS_RESET, 0x00)); + } + + return 0; +} + +/* Sleeps until no frames are active. Returns !0 if got signal */ +static int +ov51x_wait_frames_inactive(struct usb_ov511 *ov) +{ + return wait_event_interruptible(ov->wq, ov->curframe < 0); +} + +/* Resets the hardware snapshot button */ +static void +ov51x_clear_snapshot(struct usb_ov511 *ov) +{ + if (ov->bclass == BCL_OV511) { + reg_w(ov, R51x_SYS_SNAP, 0x00); + reg_w(ov, R51x_SYS_SNAP, 0x02); + reg_w(ov, R51x_SYS_SNAP, 0x00); + } else if (ov->bclass == BCL_OV518) { + warn("snapshot reset not supported yet on OV518(+)"); + } else { + err("clear snap: invalid bridge type"); + } +} + +#if 0 +/* Checks the status of the snapshot button. Returns 1 if it was pressed since + * it was last cleared, and zero in all other cases (including errors) */ +static int +ov51x_check_snapshot(struct usb_ov511 *ov) +{ + int ret, status = 0; + + if (ov->bclass == BCL_OV511) { + ret = reg_r(ov, R51x_SYS_SNAP); + if (ret < 0) { + err("Error checking snspshot status (%d)", ret); + } else if (ret & 0x08) { + status = 1; + } + } else if (ov->bclass == BCL_OV518) { + warn("snapshot check not supported yet on OV518(+)"); + } else { + err("check snap: invalid bridge type"); + } + + return status; +} +#endif + +/* This does an initial reset of an OmniVision sensor and ensures that I2C + * is synchronized. Returns <0 for failure. + */ +static int +init_ov_sensor(struct usb_ov511 *ov) +{ + int i, success; + + /* Reset the sensor */ + if (i2c_w(ov, 0x12, 0x80) < 0) + return -EIO; + + /* Wait for it to initialize */ + msleep(150); + + for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) { + if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) && + (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) { + success = 1; + continue; + } + + /* Reset the sensor */ + if (i2c_w(ov, 0x12, 0x80) < 0) + return -EIO; + /* Wait for it to initialize */ + msleep(150); + /* Dummy read to sync I2C */ + if (i2c_r(ov, 0x00) < 0) + return -EIO; + } + + if (!success) + return -EIO; + + PDEBUG(1, "I2C synced in %d attempt(s)", i); + + return 0; +} + +static int +ov511_set_packet_size(struct usb_ov511 *ov, int size) +{ + int alt, mult; + + if (ov51x_stop(ov) < 0) + return -EIO; + + mult = size >> 5; + + if (ov->bridge == BRG_OV511) { + if (size == 0) + alt = OV511_ALT_SIZE_0; + else if (size == 257) + alt = OV511_ALT_SIZE_257; + else if (size == 513) + alt = OV511_ALT_SIZE_513; + else if (size == 769) + alt = OV511_ALT_SIZE_769; + else if (size == 993) + alt = OV511_ALT_SIZE_993; + else { + err("Set packet size: invalid size (%d)", size); + return -EINVAL; + } + } else if (ov->bridge == BRG_OV511PLUS) { + if (size == 0) + alt = OV511PLUS_ALT_SIZE_0; + else if (size == 33) + alt = OV511PLUS_ALT_SIZE_33; + else if (size == 129) + alt = OV511PLUS_ALT_SIZE_129; + else if (size == 257) + alt = OV511PLUS_ALT_SIZE_257; + else if (size == 385) + alt = OV511PLUS_ALT_SIZE_385; + else if (size == 513) + alt = OV511PLUS_ALT_SIZE_513; + else if (size == 769) + alt = OV511PLUS_ALT_SIZE_769; + else if (size == 961) + alt = OV511PLUS_ALT_SIZE_961; + else { + err("Set packet size: invalid size (%d)", size); + return -EINVAL; + } + } else { + err("Set packet size: Invalid bridge type"); + return -EINVAL; + } + + PDEBUG(3, "%d, mult=%d, alt=%d", size, mult, alt); + + if (reg_w(ov, R51x_FIFO_PSIZE, mult) < 0) + return -EIO; + + if (usb_set_interface(ov->dev, ov->iface, alt) < 0) { + err("Set packet size: set interface error"); + return -EBUSY; + } + + if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) + return -EIO; + + ov->packet_size = size; + + if (ov51x_restart(ov) < 0) + return -EIO; + + return 0; +} + +/* Note: Unlike the OV511/OV511+, the size argument does NOT include the + * optional packet number byte. The actual size *is* stored in ov->packet_size, + * though. */ +static int +ov518_set_packet_size(struct usb_ov511 *ov, int size) +{ + int alt; + + if (ov51x_stop(ov) < 0) + return -EIO; + + if (ov->bclass == BCL_OV518) { + if (size == 0) + alt = OV518_ALT_SIZE_0; + else if (size == 128) + alt = OV518_ALT_SIZE_128; + else if (size == 256) + alt = OV518_ALT_SIZE_256; + else if (size == 384) + alt = OV518_ALT_SIZE_384; + else if (size == 512) + alt = OV518_ALT_SIZE_512; + else if (size == 640) + alt = OV518_ALT_SIZE_640; + else if (size == 768) + alt = OV518_ALT_SIZE_768; + else if (size == 896) + alt = OV518_ALT_SIZE_896; + else { + err("Set packet size: invalid size (%d)", size); + return -EINVAL; + } + } else { + err("Set packet size: Invalid bridge type"); + return -EINVAL; + } + + PDEBUG(3, "%d, alt=%d", size, alt); + + ov->packet_size = size; + if (size > 0) { + /* Program ISO FIFO size reg (packet number isn't included) */ + ov518_reg_w32(ov, 0x30, size, 2); + + if (ov->packet_numbering) + ++ov->packet_size; + } + + if (usb_set_interface(ov->dev, ov->iface, alt) < 0) { + err("Set packet size: set interface error"); + return -EBUSY; + } + + /* Initialize the stream */ + if (reg_w(ov, 0x2f, 0x80) < 0) + return -EIO; + + if (ov51x_restart(ov) < 0) + return -EIO; + + if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) + return -EIO; + + return 0; +} + +/* Upload compression params and quantization tables. Returns 0 for success. */ +static int +ov511_init_compression(struct usb_ov511 *ov) +{ + int rc = 0; + + if (!ov->compress_inited) { + reg_w(ov, 0x70, phy); + reg_w(ov, 0x71, phuv); + reg_w(ov, 0x72, pvy); + reg_w(ov, 0x73, pvuv); + reg_w(ov, 0x74, qhy); + reg_w(ov, 0x75, qhuv); + reg_w(ov, 0x76, qvy); + reg_w(ov, 0x77, qvuv); + + if (ov511_upload_quan_tables(ov) < 0) { + err("Error uploading quantization tables"); + rc = -EIO; + goto out; + } + } + + ov->compress_inited = 1; +out: + return rc; +} + +/* Upload compression params and quantization tables. Returns 0 for success. */ +static int +ov518_init_compression(struct usb_ov511 *ov) +{ + int rc = 0; + + if (!ov->compress_inited) { + if (ov518_upload_quan_tables(ov) < 0) { + err("Error uploading quantization tables"); + rc = -EIO; + goto out; + } + } + + ov->compress_inited = 1; +out: + return rc; +} + +/* -------------------------------------------------------------------------- */ + +/* Sets sensor's contrast setting to "val" */ +static int +sensor_set_contrast(struct usb_ov511 *ov, unsigned short val) +{ + int rc; + + PDEBUG(3, "%d", val); + + if (ov->stop_during_set) + if (ov51x_stop(ov) < 0) + return -EIO; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV6620: + { + rc = i2c_w(ov, OV7610_REG_CNT, val >> 8); + if (rc < 0) + goto out; + break; + } + case SEN_OV6630: + { + rc = i2c_w_mask(ov, OV7610_REG_CNT, val >> 12, 0x0f); + if (rc < 0) + goto out; + break; + } + case SEN_OV7620: + { + unsigned char ctab[] = { + 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, + 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff + }; + + /* Use Y gamma control instead. Bit 0 enables it. */ + rc = i2c_w(ov, 0x64, ctab[val>>12]); + if (rc < 0) + goto out; + break; + } + case SEN_SAA7111A: + { + rc = i2c_w(ov, 0x0b, val >> 9); + if (rc < 0) + goto out; + break; + } + default: + { + PDEBUG(3, "Unsupported with this sensor"); + rc = -EPERM; + goto out; + } + } + + rc = 0; /* Success */ + ov->contrast = val; +out: + if (ov51x_restart(ov) < 0) + return -EIO; + + return rc; +} + +/* Gets sensor's contrast setting */ +static int +sensor_get_contrast(struct usb_ov511 *ov, unsigned short *val) +{ + int rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV6620: + rc = i2c_r(ov, OV7610_REG_CNT); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_OV6630: + rc = i2c_r(ov, OV7610_REG_CNT); + if (rc < 0) + return rc; + else + *val = rc << 12; + break; + case SEN_OV7620: + /* Use Y gamma reg instead. Bit 0 is the enable bit. */ + rc = i2c_r(ov, 0x64); + if (rc < 0) + return rc; + else + *val = (rc & 0xfe) << 8; + break; + case SEN_SAA7111A: + *val = ov->contrast; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + } + + PDEBUG(3, "%d", *val); + ov->contrast = *val; + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +/* Sets sensor's brightness setting to "val" */ +static int +sensor_set_brightness(struct usb_ov511 *ov, unsigned short val) +{ + int rc; + + PDEBUG(4, "%d", val); + + if (ov->stop_during_set) + if (ov51x_stop(ov) < 0) + return -EIO; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV76BE: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_w(ov, OV7610_REG_BRT, val >> 8); + if (rc < 0) + goto out; + break; + case SEN_OV7620: + /* 7620 doesn't like manual changes when in auto mode */ + if (!ov->auto_brt) { + rc = i2c_w(ov, OV7610_REG_BRT, val >> 8); + if (rc < 0) + goto out; + } + break; + case SEN_SAA7111A: + rc = i2c_w(ov, 0x0a, val >> 8); + if (rc < 0) + goto out; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + rc = -EPERM; + goto out; + } + + rc = 0; /* Success */ + ov->brightness = val; +out: + if (ov51x_restart(ov) < 0) + return -EIO; + + return rc; +} + +/* Gets sensor's brightness setting */ +static int +sensor_get_brightness(struct usb_ov511 *ov, unsigned short *val) +{ + int rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV76BE: + case SEN_OV7620: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_r(ov, OV7610_REG_BRT); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_SAA7111A: + *val = ov->brightness; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + } + + PDEBUG(3, "%d", *val); + ov->brightness = *val; + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +/* Sets sensor's saturation (color intensity) setting to "val" */ +static int +sensor_set_saturation(struct usb_ov511 *ov, unsigned short val) +{ + int rc; + + PDEBUG(3, "%d", val); + + if (ov->stop_during_set) + if (ov51x_stop(ov) < 0) + return -EIO; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV76BE: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_w(ov, OV7610_REG_SAT, val >> 8); + if (rc < 0) + goto out; + break; + case SEN_OV7620: +// /* Use UV gamma control instead. Bits 0 & 7 are reserved. */ +// rc = ov_i2c_write(ov->dev, 0x62, (val >> 9) & 0x7e); +// if (rc < 0) +// goto out; + rc = i2c_w(ov, OV7610_REG_SAT, val >> 8); + if (rc < 0) + goto out; + break; + case SEN_SAA7111A: + rc = i2c_w(ov, 0x0c, val >> 9); + if (rc < 0) + goto out; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + rc = -EPERM; + goto out; + } + + rc = 0; /* Success */ + ov->colour = val; +out: + if (ov51x_restart(ov) < 0) + return -EIO; + + return rc; +} + +/* Gets sensor's saturation (color intensity) setting */ +static int +sensor_get_saturation(struct usb_ov511 *ov, unsigned short *val) +{ + int rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV76BE: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_r(ov, OV7610_REG_SAT); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_OV7620: +// /* Use UV gamma reg instead. Bits 0 & 7 are reserved. */ +// rc = i2c_r(ov, 0x62); +// if (rc < 0) +// return rc; +// else +// *val = (rc & 0x7e) << 9; + rc = i2c_r(ov, OV7610_REG_SAT); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_SAA7111A: + *val = ov->colour; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + } + + PDEBUG(3, "%d", *val); + ov->colour = *val; + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +/* Sets sensor's hue (red/blue balance) setting to "val" */ +static int +sensor_set_hue(struct usb_ov511 *ov, unsigned short val) +{ + int rc; + + PDEBUG(3, "%d", val); + + if (ov->stop_during_set) + if (ov51x_stop(ov) < 0) + return -EIO; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_w(ov, OV7610_REG_RED, 0xFF - (val >> 8)); + if (rc < 0) + goto out; + + rc = i2c_w(ov, OV7610_REG_BLUE, val >> 8); + if (rc < 0) + goto out; + break; + case SEN_OV7620: +// Hue control is causing problems. I will enable it once it's fixed. +#if 0 + rc = i2c_w(ov, 0x7a, (unsigned char)(val >> 8) + 0xb); + if (rc < 0) + goto out; + + rc = i2c_w(ov, 0x79, (unsigned char)(val >> 8) + 0xb); + if (rc < 0) + goto out; +#endif + break; + case SEN_SAA7111A: + rc = i2c_w(ov, 0x0d, (val + 32768) >> 8); + if (rc < 0) + goto out; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + rc = -EPERM; + goto out; + } + + rc = 0; /* Success */ + ov->hue = val; +out: + if (ov51x_restart(ov) < 0) + return -EIO; + + return rc; +} + +/* Gets sensor's hue (red/blue balance) setting */ +static int +sensor_get_hue(struct usb_ov511 *ov, unsigned short *val) +{ + int rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV6620: + case SEN_OV6630: + rc = i2c_r(ov, OV7610_REG_BLUE); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_OV7620: + rc = i2c_r(ov, 0x7a); + if (rc < 0) + return rc; + else + *val = rc << 8; + break; + case SEN_SAA7111A: + *val = ov->hue; + break; + default: + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + } + + PDEBUG(3, "%d", *val); + ov->hue = *val; + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +static int +sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p) +{ + int rc; + + PDEBUG(4, "sensor_set_picture"); + + ov->whiteness = p->whiteness; + + /* Don't return error if a setting is unsupported, or rest of settings + * will not be performed */ + + rc = sensor_set_contrast(ov, p->contrast); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_brightness(ov, p->brightness); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_saturation(ov, p->colour); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_hue(ov, p->hue); + if (FATAL_ERROR(rc)) + return rc; + + return 0; +} + +static int +sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p) +{ + int rc; + + PDEBUG(4, "sensor_get_picture"); + + /* Don't return error if a setting is unsupported, or rest of settings + * will not be performed */ + + rc = sensor_get_contrast(ov, &(p->contrast)); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_get_brightness(ov, &(p->brightness)); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_get_saturation(ov, &(p->colour)); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_get_hue(ov, &(p->hue)); + if (FATAL_ERROR(rc)) + return rc; + + p->whiteness = 105 << 8; + + return 0; +} + +#if 0 +// FIXME: Exposure range is only 0x00-0x7f in interlace mode +/* Sets current exposure for sensor. This only has an effect if auto-exposure + * is off */ +static inline int +sensor_set_exposure(struct usb_ov511 *ov, unsigned char val) +{ + int rc; + + PDEBUG(3, "%d", val); + + if (ov->stop_during_set) + if (ov51x_stop(ov) < 0) + return -EIO; + + switch (ov->sensor) { + case SEN_OV6620: + case SEN_OV6630: + case SEN_OV7610: + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + rc = i2c_w(ov, 0x10, val); + if (rc < 0) + goto out; + + break; + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for set_exposure"); + return -EINVAL; + } + + rc = 0; /* Success */ + ov->exposure = val; +out: + if (ov51x_restart(ov) < 0) + return -EIO; + + return rc; +} +#endif + +/* Gets current exposure level from sensor, regardless of whether it is under + * manual control. */ +static int +sensor_get_exposure(struct usb_ov511 *ov, unsigned char *val) +{ + int rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV6620: + case SEN_OV6630: + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + rc = i2c_r(ov, 0x10); + if (rc < 0) + return rc; + else + *val = rc; + break; + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + val = NULL; + PDEBUG(3, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for get_exposure"); + return -EINVAL; + } + + PDEBUG(3, "%d", *val); + ov->exposure = *val; + + return 0; +} + +/* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */ +static void +ov51x_led_control(struct usb_ov511 *ov, int enable) +{ + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + if (ov->bridge == BRG_OV511PLUS) + reg_w(ov, R511_SYS_LED_CTL, enable ? 1 : 0); + else if (ov->bclass == BCL_OV518) + reg_w_mask(ov, R518_GPIO_OUT, enable ? 0x02 : 0x00, 0x02); + + return; +} + +/* Matches the sensor's internal frame rate to the lighting frequency. + * Valid frequencies are: + * 50 - 50Hz, for European and Asian lighting + * 60 - 60Hz, for American lighting + * + * Tested with: OV7610, OV7620, OV76BE, OV6620 + * Unsupported: KS0127, KS0127B, SAA7111A + * Returns: 0 for success + */ +static int +sensor_set_light_freq(struct usb_ov511 *ov, int freq) +{ + int sixty; + + PDEBUG(4, "%d Hz", freq); + + if (freq == 60) + sixty = 1; + else if (freq == 50) + sixty = 0; + else { + err("Invalid light freq (%d Hz)", freq); + return -EINVAL; + } + + switch (ov->sensor) { + case SEN_OV7610: + i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80); + i2c_w(ov, 0x2b, sixty?0x00:0xac); + i2c_w_mask(ov, 0x13, 0x10, 0x10); + i2c_w_mask(ov, 0x13, 0x00, 0x10); + break; + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80); + i2c_w(ov, 0x2b, sixty?0x00:0xac); + i2c_w_mask(ov, 0x76, 0x01, 0x01); + break; + case SEN_OV6620: + case SEN_OV6630: + i2c_w(ov, 0x2b, sixty?0xa8:0x28); + i2c_w(ov, 0x2a, sixty?0x84:0xa4); + break; + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for set_light_freq"); + return -EINVAL; + } + + ov->lightfreq = freq; + + return 0; +} + +/* If enable is true, turn on the sensor's banding filter, otherwise turn it + * off. This filter tries to reduce the pattern of horizontal light/dark bands + * caused by some (usually fluorescent) lighting. The light frequency must be + * set either before or after enabling it with ov51x_set_light_freq(). + * + * Tested with: OV7610, OV7620, OV76BE, OV6620. + * Unsupported: KS0127, KS0127B, SAA7111A + * Returns: 0 for success + */ +static int +sensor_set_banding_filter(struct usb_ov511 *ov, int enable) +{ + int rc; + + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B + || ov->sensor == SEN_SAA7111A) { + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + } + + rc = i2c_w_mask(ov, 0x2d, enable?0x04:0x00, 0x04); + if (rc < 0) + return rc; + + ov->bandfilt = enable; + + return 0; +} + +/* If enable is true, turn on the sensor's auto brightness control, otherwise + * turn it off. + * + * Unsupported: KS0127, KS0127B, SAA7111A + * Returns: 0 for success + */ +static int +sensor_set_auto_brightness(struct usb_ov511 *ov, int enable) +{ + int rc; + + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B + || ov->sensor == SEN_SAA7111A) { + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + } + + rc = i2c_w_mask(ov, 0x2d, enable?0x10:0x00, 0x10); + if (rc < 0) + return rc; + + ov->auto_brt = enable; + + return 0; +} + +/* If enable is true, turn on the sensor's auto exposure control, otherwise + * turn it off. + * + * Unsupported: KS0127, KS0127B, SAA7111A + * Returns: 0 for success + */ +static int +sensor_set_auto_exposure(struct usb_ov511 *ov, int enable) +{ + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + switch (ov->sensor) { + case SEN_OV7610: + i2c_w_mask(ov, 0x29, enable?0x00:0x80, 0x80); + break; + case SEN_OV6620: + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + i2c_w_mask(ov, 0x13, enable?0x01:0x00, 0x01); + break; + case SEN_OV6630: + i2c_w_mask(ov, 0x28, enable?0x00:0x10, 0x10); + break; + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for set_auto_exposure"); + return -EINVAL; + } + + ov->auto_exp = enable; + + return 0; +} + +/* Modifies the sensor's exposure algorithm to allow proper exposure of objects + * that are illuminated from behind. + * + * Tested with: OV6620, OV7620 + * Unsupported: OV7610, OV76BE, KS0127, KS0127B, SAA7111A + * Returns: 0 for success + */ +static int +sensor_set_backlight(struct usb_ov511 *ov, int enable) +{ + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + switch (ov->sensor) { + case SEN_OV7620: + case SEN_OV8600: + i2c_w_mask(ov, 0x68, enable?0xe0:0xc0, 0xe0); + i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); + i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02); + break; + case SEN_OV6620: + i2c_w_mask(ov, 0x4e, enable?0xe0:0xc0, 0xe0); + i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); + i2c_w_mask(ov, 0x0e, enable?0x80:0x00, 0x80); + break; + case SEN_OV6630: + i2c_w_mask(ov, 0x4e, enable?0x80:0x60, 0xe0); + i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); + i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02); + break; + case SEN_OV7610: + case SEN_OV76BE: + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for set_backlight"); + return -EINVAL; + } + + ov->backlight = enable; + + return 0; +} + +static int +sensor_set_mirror(struct usb_ov511 *ov, int enable) +{ + PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); + + switch (ov->sensor) { + case SEN_OV6620: + case SEN_OV6630: + case SEN_OV7610: + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + i2c_w_mask(ov, 0x12, enable?0x40:0x00, 0x40); + break; + case SEN_KS0127: + case SEN_KS0127B: + case SEN_SAA7111A: + PDEBUG(5, "Unsupported with this sensor"); + return -EPERM; + default: + err("Sensor not supported for set_mirror"); + return -EINVAL; + } + + ov->mirror = enable; + + return 0; +} + +/* Returns number of bits per pixel (regardless of where they are located; + * planar or not), or zero for unsupported format. + */ +static inline int +get_depth(int palette) +{ + switch (palette) { + case VIDEO_PALETTE_GREY: return 8; + case VIDEO_PALETTE_YUV420: return 12; + case VIDEO_PALETTE_YUV420P: return 12; /* Planar */ + default: return 0; /* Invalid format */ + } +} + +/* Bytes per frame. Used by read(). Return of 0 indicates error */ +static inline long int +get_frame_length(struct ov511_frame *frame) +{ + if (!frame) + return 0; + else + return ((frame->width * frame->height + * get_depth(frame->format)) >> 3); +} + +static int +mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height, + int mode, int sub_flag, int qvga) +{ + int clock; + + /******** Mode (VGA/QVGA) and sensor specific regs ********/ + + switch (ov->sensor) { + case SEN_OV7610: + i2c_w(ov, 0x14, qvga?0x24:0x04); +// FIXME: Does this improve the image quality or frame rate? +#if 0 + i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); + i2c_w(ov, 0x24, 0x10); + i2c_w(ov, 0x25, qvga?0x40:0x8a); + i2c_w(ov, 0x2f, qvga?0x30:0xb0); + i2c_w(ov, 0x35, qvga?0x1c:0x9c); +#endif + break; + case SEN_OV7620: +// i2c_w(ov, 0x2b, 0x00); + i2c_w(ov, 0x14, qvga?0xa4:0x84); + i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); + i2c_w(ov, 0x24, qvga?0x20:0x3a); + i2c_w(ov, 0x25, qvga?0x30:0x60); + i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40); + i2c_w_mask(ov, 0x67, qvga?0xf0:0x90, 0xf0); + i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20); + break; + case SEN_OV76BE: +// i2c_w(ov, 0x2b, 0x00); + i2c_w(ov, 0x14, qvga?0xa4:0x84); +// FIXME: Enable this once 7620AE uses 7620 initial settings +#if 0 + i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); + i2c_w(ov, 0x24, qvga?0x20:0x3a); + i2c_w(ov, 0x25, qvga?0x30:0x60); + i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40); + i2c_w_mask(ov, 0x67, qvga?0xb0:0x90, 0xf0); + i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20); +#endif + break; + case SEN_OV6620: + i2c_w(ov, 0x14, qvga?0x24:0x04); + break; + case SEN_OV6630: + i2c_w(ov, 0x14, qvga?0xa0:0x80); + break; + default: + err("Invalid sensor"); + return -EINVAL; + } + + /******** Palette-specific regs ********/ + + if (mode == VIDEO_PALETTE_GREY) { + if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { + /* these aren't valid on the OV6620/OV7620/6630? */ + i2c_w_mask(ov, 0x0e, 0x40, 0x40); + } + + if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 + && ov518_color) { + i2c_w_mask(ov, 0x12, 0x00, 0x10); + i2c_w_mask(ov, 0x13, 0x00, 0x20); + } else { + i2c_w_mask(ov, 0x13, 0x20, 0x20); + } + } else { + if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { + /* not valid on the OV6620/OV7620/6630? */ + i2c_w_mask(ov, 0x0e, 0x00, 0x40); + } + + /* The OV518 needs special treatment. Although both the OV518 + * and the OV6630 support a 16-bit video bus, only the 8 bit Y + * bus is actually used. The UV bus is tied to ground. + * Therefore, the OV6630 needs to be in 8-bit multiplexed + * output mode */ + + if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 + && ov518_color) { + i2c_w_mask(ov, 0x12, 0x10, 0x10); + i2c_w_mask(ov, 0x13, 0x20, 0x20); + } else { + i2c_w_mask(ov, 0x13, 0x00, 0x20); + } + } + + /******** Clock programming ********/ + + /* The OV6620 needs special handling. This prevents the + * severe banding that normally occurs */ + if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) + { + /* Clock down */ + + i2c_w(ov, 0x2a, 0x04); + + if (ov->compress) { +// clock = 0; /* This ensures the highest frame rate */ + clock = 3; + } else if (clockdiv == -1) { /* If user didn't override it */ + clock = 3; /* Gives better exposure time */ + } else { + clock = clockdiv; + } + + PDEBUG(4, "Setting clock divisor to %d", clock); + + i2c_w(ov, 0x11, clock); + + i2c_w(ov, 0x2a, 0x84); + /* This next setting is critical. It seems to improve + * the gain or the contrast. The "reserved" bits seem + * to have some effect in this case. */ + i2c_w(ov, 0x2d, 0x85); + } + else + { + if (ov->compress) { + clock = 1; /* This ensures the highest frame rate */ + } else if (clockdiv == -1) { /* If user didn't override it */ + /* Calculate and set the clock divisor */ + clock = ((sub_flag ? ov->subw * ov->subh + : width * height) + * (mode == VIDEO_PALETTE_GREY ? 2 : 3) / 2) + / 66000; + } else { + clock = clockdiv; + } + + PDEBUG(4, "Setting clock divisor to %d", clock); + + i2c_w(ov, 0x11, clock); + } + + /******** Special Features ********/ + + if (framedrop >= 0) + i2c_w(ov, 0x16, framedrop); + + /* Test Pattern */ + i2c_w_mask(ov, 0x12, (testpat?0x02:0x00), 0x02); + + /* Enable auto white balance */ + i2c_w_mask(ov, 0x12, 0x04, 0x04); + + // This will go away as soon as ov51x_mode_init_sensor_regs() + // is fully tested. + /* 7620/6620/6630? don't have register 0x35, so play it safe */ + if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { + if (width == 640 && height == 480) + i2c_w(ov, 0x35, 0x9e); + else + i2c_w(ov, 0x35, 0x1e); + } + + return 0; +} + +static int +set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode, + int sub_flag) +{ + int ret; + int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; + int hoffset, voffset, hwscale = 0, vwscale = 0; + + /* The different sensor ICs handle setting up of window differently. + * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!!! */ + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV76BE: + hwsbase = 0x38; + hwebase = 0x3a; + vwsbase = vwebase = 0x05; + break; + case SEN_OV6620: + case SEN_OV6630: + hwsbase = 0x38; + hwebase = 0x3a; + vwsbase = 0x05; + vwebase = 0x06; + break; + case SEN_OV7620: + hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ + hwebase = 0x2f; + vwsbase = vwebase = 0x05; + break; + default: + err("Invalid sensor"); + return -EINVAL; + } + + if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) { + /* Note: OV518(+) does downsample on its own) */ + if ((width > 176 && height > 144) + || ov->bclass == BCL_OV518) { /* CIF */ + ret = mode_init_ov_sensor_regs(ov, width, height, + mode, sub_flag, 0); + if (ret < 0) + return ret; + hwscale = 1; + vwscale = 1; /* The datasheet says 0; it's wrong */ + hwsize = 352; + vwsize = 288; + } else if (width > 176 || height > 144) { + err("Illegal dimensions"); + return -EINVAL; + } else { /* QCIF */ + ret = mode_init_ov_sensor_regs(ov, width, height, + mode, sub_flag, 1); + if (ret < 0) + return ret; + hwsize = 176; + vwsize = 144; + } + } else { + if (width > 320 && height > 240) { /* VGA */ + ret = mode_init_ov_sensor_regs(ov, width, height, + mode, sub_flag, 0); + if (ret < 0) + return ret; + hwscale = 2; + vwscale = 1; + hwsize = 640; + vwsize = 480; + } else if (width > 320 || height > 240) { + err("Illegal dimensions"); + return -EINVAL; + } else { /* QVGA */ + ret = mode_init_ov_sensor_regs(ov, width, height, + mode, sub_flag, 1); + if (ret < 0) + return ret; + hwscale = 1; + hwsize = 320; + vwsize = 240; + } + } + + /* Center the window */ + hoffset = ((hwsize - width) / 2) >> hwscale; + voffset = ((vwsize - height) / 2) >> vwscale; + + /* FIXME! - This needs to be changed to support 160x120 and 6620!!! */ + if (sub_flag) { + i2c_w(ov, 0x17, hwsbase+(ov->subx>>hwscale)); + i2c_w(ov, 0x18, hwebase+((ov->subx+ov->subw)>>hwscale)); + i2c_w(ov, 0x19, vwsbase+(ov->suby>>vwscale)); + i2c_w(ov, 0x1a, vwebase+((ov->suby+ov->subh)>>vwscale)); + } else { + i2c_w(ov, 0x17, hwsbase + hoffset); + i2c_w(ov, 0x18, hwebase + hoffset + (hwsize>>hwscale)); + i2c_w(ov, 0x19, vwsbase + voffset); + i2c_w(ov, 0x1a, vwebase + voffset + (vwsize>>vwscale)); + } + +#ifdef OV511_DEBUG + if (dump_sensor) + dump_i2c_regs(ov); +#endif + + return 0; +} + +/* Set up the OV511/OV511+ with the given image parameters. + * + * Do not put any sensor-specific code in here (including I2C I/O functions) + */ +static int +ov511_mode_init_regs(struct usb_ov511 *ov, + int width, int height, int mode, int sub_flag) +{ + int hsegs, vsegs; + + if (sub_flag) { + width = ov->subw; + height = ov->subh; + } + + PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d", + width, height, mode, sub_flag); + + // FIXME: This should be moved to a 7111a-specific function once + // subcapture is dealt with properly + if (ov->sensor == SEN_SAA7111A) { + if (width == 320 && height == 240) { + /* No need to do anything special */ + } else if (width == 640 && height == 480) { + /* Set the OV511 up as 320x480, but keep the + * V4L resolution as 640x480 */ + width = 320; + } else { + err("SAA7111A only allows 320x240 or 640x480"); + return -EINVAL; + } + } + + /* Make sure width and height are a multiple of 8 */ + if (width % 8 || height % 8) { + err("Invalid size (%d, %d) (mode = %d)", width, height, mode); + return -EINVAL; + } + + if (width < ov->minwidth || height < ov->minheight) { + err("Requested dimensions are too small"); + return -EINVAL; + } + + if (ov51x_stop(ov) < 0) + return -EIO; + + if (mode == VIDEO_PALETTE_GREY) { + reg_w(ov, R511_CAM_UV_EN, 0x00); + reg_w(ov, R511_SNAP_UV_EN, 0x00); + reg_w(ov, R511_SNAP_OPTS, 0x01); + } else { + reg_w(ov, R511_CAM_UV_EN, 0x01); + reg_w(ov, R511_SNAP_UV_EN, 0x01); + reg_w(ov, R511_SNAP_OPTS, 0x03); + } + + /* Here I'm assuming that snapshot size == image size. + * I hope that's always true. --claudio + */ + hsegs = (width >> 3) - 1; + vsegs = (height >> 3) - 1; + + reg_w(ov, R511_CAM_PXCNT, hsegs); + reg_w(ov, R511_CAM_LNCNT, vsegs); + reg_w(ov, R511_CAM_PXDIV, 0x00); + reg_w(ov, R511_CAM_LNDIV, 0x00); + + /* YUV420, low pass filter on */ + reg_w(ov, R511_CAM_OPTS, 0x03); + + /* Snapshot additions */ + reg_w(ov, R511_SNAP_PXCNT, hsegs); + reg_w(ov, R511_SNAP_LNCNT, vsegs); + reg_w(ov, R511_SNAP_PXDIV, 0x00); + reg_w(ov, R511_SNAP_LNDIV, 0x00); + + if (ov->compress) { + /* Enable Y and UV quantization and compression */ + reg_w(ov, R511_COMP_EN, 0x07); + reg_w(ov, R511_COMP_LUT_EN, 0x03); + ov51x_reset(ov, OV511_RESET_OMNICE); + } + + if (ov51x_restart(ov) < 0) + return -EIO; + + return 0; +} + +/* Sets up the OV518/OV518+ with the given image parameters + * + * OV518 needs a completely different approach, until we can figure out what + * the individual registers do. Also, only 15 FPS is supported now. + * + * Do not put any sensor-specific code in here (including I2C I/O functions) + */ +static int +ov518_mode_init_regs(struct usb_ov511 *ov, + int width, int height, int mode, int sub_flag) +{ + int hsegs, vsegs, hi_res; + + if (sub_flag) { + width = ov->subw; + height = ov->subh; + } + + PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d", + width, height, mode, sub_flag); + + if (width % 16 || height % 8) { + err("Invalid size (%d, %d)", width, height); + return -EINVAL; + } + + if (width < ov->minwidth || height < ov->minheight) { + err("Requested dimensions are too small"); + return -EINVAL; + } + + if (width >= 320 && height >= 240) { + hi_res = 1; + } else if (width >= 320 || height >= 240) { + err("Invalid width/height combination (%d, %d)", width, height); + return -EINVAL; + } else { + hi_res = 0; + } + + if (ov51x_stop(ov) < 0) + return -EIO; + + /******** Set the mode ********/ + + reg_w(ov, 0x2b, 0); + reg_w(ov, 0x2c, 0); + reg_w(ov, 0x2d, 0); + reg_w(ov, 0x2e, 0); + reg_w(ov, 0x3b, 0); + reg_w(ov, 0x3c, 0); + reg_w(ov, 0x3d, 0); + reg_w(ov, 0x3e, 0); + + if (ov->bridge == BRG_OV518 && ov518_color) { + /* OV518 needs U and V swapped */ + i2c_w_mask(ov, 0x15, 0x00, 0x01); + + if (mode == VIDEO_PALETTE_GREY) { + /* Set 16-bit input format (UV data are ignored) */ + reg_w_mask(ov, 0x20, 0x00, 0x08); + + /* Set 8-bit (4:0:0) output format */ + reg_w_mask(ov, 0x28, 0x00, 0xf0); + reg_w_mask(ov, 0x38, 0x00, 0xf0); + } else { + /* Set 8-bit (YVYU) input format */ + reg_w_mask(ov, 0x20, 0x08, 0x08); + + /* Set 12-bit (4:2:0) output format */ + reg_w_mask(ov, 0x28, 0x80, 0xf0); + reg_w_mask(ov, 0x38, 0x80, 0xf0); + } + } else { + reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); + reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); + } + + hsegs = width / 16; + vsegs = height / 4; + + reg_w(ov, 0x29, hsegs); + reg_w(ov, 0x2a, vsegs); + + reg_w(ov, 0x39, hsegs); + reg_w(ov, 0x3a, vsegs); + + /* Windows driver does this here; who knows why */ + reg_w(ov, 0x2f, 0x80); + + /******** Set the framerate (to 15 FPS) ********/ + + /* Mode independent, but framerate dependent, regs */ + reg_w(ov, 0x51, 0x02); /* Clock divider; lower==faster */ + reg_w(ov, 0x22, 0x18); + reg_w(ov, 0x23, 0xff); + + if (ov->bridge == BRG_OV518PLUS) + reg_w(ov, 0x21, 0x19); + else + reg_w(ov, 0x71, 0x19); /* Compression-related? */ + + // FIXME: Sensor-specific + /* Bit 5 is what matters here. Of course, it is "reserved" */ + i2c_w(ov, 0x54, 0x23); + + reg_w(ov, 0x2f, 0x80); + + if (ov->bridge == BRG_OV518PLUS) { + reg_w(ov, 0x24, 0x94); + reg_w(ov, 0x25, 0x90); + ov518_reg_w32(ov, 0xc4, 400, 2); /* 190h */ + ov518_reg_w32(ov, 0xc6, 540, 2); /* 21ch */ + ov518_reg_w32(ov, 0xc7, 540, 2); /* 21ch */ + ov518_reg_w32(ov, 0xc8, 108, 2); /* 6ch */ + ov518_reg_w32(ov, 0xca, 131098, 3); /* 2001ah */ + ov518_reg_w32(ov, 0xcb, 532, 2); /* 214h */ + ov518_reg_w32(ov, 0xcc, 2400, 2); /* 960h */ + ov518_reg_w32(ov, 0xcd, 32, 2); /* 20h */ + ov518_reg_w32(ov, 0xce, 608, 2); /* 260h */ + } else { + reg_w(ov, 0x24, 0x9f); + reg_w(ov, 0x25, 0x90); + ov518_reg_w32(ov, 0xc4, 400, 2); /* 190h */ + ov518_reg_w32(ov, 0xc6, 500, 2); /* 1f4h */ + ov518_reg_w32(ov, 0xc7, 500, 2); /* 1f4h */ + ov518_reg_w32(ov, 0xc8, 142, 2); /* 8eh */ + ov518_reg_w32(ov, 0xca, 131098, 3); /* 2001ah */ + ov518_reg_w32(ov, 0xcb, 532, 2); /* 214h */ + ov518_reg_w32(ov, 0xcc, 2000, 2); /* 7d0h */ + ov518_reg_w32(ov, 0xcd, 32, 2); /* 20h */ + ov518_reg_w32(ov, 0xce, 608, 2); /* 260h */ + } + + reg_w(ov, 0x2f, 0x80); + + if (ov51x_restart(ov) < 0) + return -EIO; + + /* Reset it just for good measure */ + if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) + return -EIO; + + return 0; +} + +/* This is a wrapper around the OV511, OV518, and sensor specific functions */ +static int +mode_init_regs(struct usb_ov511 *ov, + int width, int height, int mode, int sub_flag) +{ + int rc = 0; + + if (!ov || !ov->dev) + return -EFAULT; + + if (ov->bclass == BCL_OV518) { + rc = ov518_mode_init_regs(ov, width, height, mode, sub_flag); + } else { + rc = ov511_mode_init_regs(ov, width, height, mode, sub_flag); + } + + if (FATAL_ERROR(rc)) + return rc; + + switch (ov->sensor) { + case SEN_OV7610: + case SEN_OV7620: + case SEN_OV76BE: + case SEN_OV8600: + case SEN_OV6620: + case SEN_OV6630: + rc = set_ov_sensor_window(ov, width, height, mode, sub_flag); + break; + case SEN_KS0127: + case SEN_KS0127B: + err("KS0127-series decoders not supported yet"); + rc = -EINVAL; + break; + case SEN_SAA7111A: +// rc = mode_init_saa_sensor_regs(ov, width, height, mode, +// sub_flag); + + PDEBUG(1, "SAA status = 0x%02X", i2c_r(ov, 0x1f)); + break; + default: + err("Unknown sensor"); + rc = -EINVAL; + } + + if (FATAL_ERROR(rc)) + return rc; + + /* Sensor-independent settings */ + rc = sensor_set_auto_brightness(ov, ov->auto_brt); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_auto_exposure(ov, ov->auto_exp); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_banding_filter(ov, bandingfilter); + if (FATAL_ERROR(rc)) + return rc; + + if (ov->lightfreq) { + rc = sensor_set_light_freq(ov, lightfreq); + if (FATAL_ERROR(rc)) + return rc; + } + + rc = sensor_set_backlight(ov, ov->backlight); + if (FATAL_ERROR(rc)) + return rc; + + rc = sensor_set_mirror(ov, ov->mirror); + if (FATAL_ERROR(rc)) + return rc; + + return 0; +} + +/* This sets the default image parameters. This is useful for apps that use + * read() and do not set these. + */ +static int +ov51x_set_default_params(struct usb_ov511 *ov) +{ + int i; + + /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used + * (using read() instead). */ + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].width = ov->maxwidth; + ov->frame[i].height = ov->maxheight; + ov->frame[i].bytes_read = 0; + if (force_palette) + ov->frame[i].format = force_palette; + else + ov->frame[i].format = VIDEO_PALETTE_YUV420; + + ov->frame[i].depth = get_depth(ov->frame[i].format); + } + + PDEBUG(3, "%dx%d, %s", ov->maxwidth, ov->maxheight, + symbolic(v4l1_plist, ov->frame[0].format)); + + /* Initialize to max width/height, YUV420 or RGB24 (if supported) */ + if (mode_init_regs(ov, ov->maxwidth, ov->maxheight, + ov->frame[0].format, 0) < 0) + return -EINVAL; + + return 0; +} + +/********************************************************************** + * + * Video decoder stuff + * + **********************************************************************/ + +/* Set analog input port of decoder */ +static int +decoder_set_input(struct usb_ov511 *ov, int input) +{ + PDEBUG(4, "port %d", input); + + switch (ov->sensor) { + case SEN_SAA7111A: + { + /* Select mode */ + i2c_w_mask(ov, 0x02, input, 0x07); + /* Bypass chrominance trap for modes 4..7 */ + i2c_w_mask(ov, 0x09, (input > 3) ? 0x80:0x00, 0x80); + break; + } + default: + return -EINVAL; + } + + return 0; +} + +/* Get ASCII name of video input */ +static int +decoder_get_input_name(struct usb_ov511 *ov, int input, char *name) +{ + switch (ov->sensor) { + case SEN_SAA7111A: + { + if (input < 0 || input > 7) + return -EINVAL; + else if (input < 4) + sprintf(name, "CVBS-%d", input); + else // if (input < 8) + sprintf(name, "S-Video-%d", input - 4); + break; + } + default: + sprintf(name, "%s", "Camera"); + } + + return 0; +} + +/* Set norm (NTSC, PAL, SECAM, AUTO) */ +static int +decoder_set_norm(struct usb_ov511 *ov, int norm) +{ + PDEBUG(4, "%d", norm); + + switch (ov->sensor) { + case SEN_SAA7111A: + { + int reg_8, reg_e; + + if (norm == VIDEO_MODE_NTSC) { + reg_8 = 0x40; /* 60 Hz */ + reg_e = 0x00; /* NTSC M / PAL BGHI */ + } else if (norm == VIDEO_MODE_PAL) { + reg_8 = 0x00; /* 50 Hz */ + reg_e = 0x00; /* NTSC M / PAL BGHI */ + } else if (norm == VIDEO_MODE_AUTO) { + reg_8 = 0x80; /* Auto field detect */ + reg_e = 0x00; /* NTSC M / PAL BGHI */ + } else if (norm == VIDEO_MODE_SECAM) { + reg_8 = 0x00; /* 50 Hz */ + reg_e = 0x50; /* SECAM / PAL 4.43 */ + } else { + return -EINVAL; + } + + i2c_w_mask(ov, 0x08, reg_8, 0xc0); + i2c_w_mask(ov, 0x0e, reg_e, 0x70); + break; + } + default: + return -EINVAL; + } + + return 0; +} + +/********************************************************************** + * + * Raw data parsing + * + **********************************************************************/ + +/* Copies a 64-byte segment at pIn to an 8x8 block at pOut. The width of the + * image at pOut is specified by w. + */ +static inline void +make_8x8(unsigned char *pIn, unsigned char *pOut, int w) +{ + unsigned char *pOut1 = pOut; + int x, y; + + for (y = 0; y < 8; y++) { + pOut1 = pOut; + for (x = 0; x < 8; x++) { + *pOut1++ = *pIn++; + } + pOut += w; + } +} + +/* + * For RAW BW (YUV 4:0:0) images, data show up in 256 byte segments. + * The segments represent 4 squares of 8x8 pixels as follows: + * + * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 + * 8 9 ... 15 72 73 ... 79 200 201 ... 207 + * ... ... ... + * 56 57 ... 63 120 121 ... 127 248 249 ... 255 + * + */ +static void +yuv400raw_to_yuv400p(struct ov511_frame *frame, + unsigned char *pIn0, unsigned char *pOut0) +{ + int x, y; + unsigned char *pIn, *pOut, *pOutLine; + + /* Copy Y */ + pIn = pIn0; + pOutLine = pOut0; + for (y = 0; y < frame->rawheight - 1; y += 8) { + pOut = pOutLine; + for (x = 0; x < frame->rawwidth - 1; x += 8) { + make_8x8(pIn, pOut, frame->rawwidth); + pIn += 64; + pOut += 8; + } + pOutLine += 8 * frame->rawwidth; + } +} + +/* + * For YUV 4:2:0 images, the data show up in 384 byte segments. + * The first 64 bytes of each segment are U, the next 64 are V. The U and + * V are arranged as follows: + * + * 0 1 ... 7 + * 8 9 ... 15 + * ... + * 56 57 ... 63 + * + * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block). + * + * The next 256 bytes are full resolution Y data and represent 4 squares + * of 8x8 pixels as follows: + * + * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 + * 8 9 ... 15 72 73 ... 79 200 201 ... 207 + * ... ... ... + * 56 57 ... 63 120 121 ... 127 ... 248 249 ... 255 + * + * Note that the U and V data in one segment represent a 16 x 16 pixel + * area, but the Y data represent a 32 x 8 pixel area. If the width is not an + * even multiple of 32, the extra 8x8 blocks within a 32x8 block belong to the + * next horizontal stripe. + * + * If dumppix module param is set, _parse_data just dumps the incoming segments, + * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480 + * this puts the data on the standard output and can be analyzed with the + * parseppm.c utility I wrote. That's a much faster way for figuring out how + * these data are scrambled. + */ + +/* Converts from raw, uncompressed segments at pIn0 to a YUV420P frame at pOut0. + * + * FIXME: Currently only handles width and height that are multiples of 16 + */ +static void +yuv420raw_to_yuv420p(struct ov511_frame *frame, + unsigned char *pIn0, unsigned char *pOut0) +{ + int k, x, y; + unsigned char *pIn, *pOut, *pOutLine; + const unsigned int a = frame->rawwidth * frame->rawheight; + const unsigned int w = frame->rawwidth / 2; + + /* Copy U and V */ + pIn = pIn0; + pOutLine = pOut0 + a; + for (y = 0; y < frame->rawheight - 1; y += 16) { + pOut = pOutLine; + for (x = 0; x < frame->rawwidth - 1; x += 16) { + make_8x8(pIn, pOut, w); + make_8x8(pIn + 64, pOut + a/4, w); + pIn += 384; + pOut += 8; + } + pOutLine += 8 * w; + } + + /* Copy Y */ + pIn = pIn0 + 128; + pOutLine = pOut0; + k = 0; + for (y = 0; y < frame->rawheight - 1; y += 8) { + pOut = pOutLine; + for (x = 0; x < frame->rawwidth - 1; x += 8) { + make_8x8(pIn, pOut, frame->rawwidth); + pIn += 64; + pOut += 8; + if ((++k) > 3) { + k = 0; + pIn += 128; + } + } + pOutLine += 8 * frame->rawwidth; + } +} + +/********************************************************************** + * + * Decompression + * + **********************************************************************/ + +static int +request_decompressor(struct usb_ov511 *ov) +{ + if (ov->bclass == BCL_OV511 || ov->bclass == BCL_OV518) { + err("No decompressor available"); + } else { + err("Unknown bridge"); + } + + return -ENOSYS; +} + +static void +decompress(struct usb_ov511 *ov, struct ov511_frame *frame, + unsigned char *pIn0, unsigned char *pOut0) +{ + if (!ov->decomp_ops) + if (request_decompressor(ov)) + return; + +} + +/********************************************************************** + * + * Format conversion + * + **********************************************************************/ + +/* Fuses even and odd fields together, and doubles width. + * INPUT: an odd field followed by an even field at pIn0, in YUV planar format + * OUTPUT: a normal YUV planar image, with correct aspect ratio + */ +static void +deinterlace(struct ov511_frame *frame, int rawformat, + unsigned char *pIn0, unsigned char *pOut0) +{ + const int fieldheight = frame->rawheight / 2; + const int fieldpix = fieldheight * frame->rawwidth; + const int w = frame->width; + int x, y; + unsigned char *pInEven, *pInOdd, *pOut; + + PDEBUG(5, "fieldheight=%d", fieldheight); + + if (frame->rawheight != frame->height) { + err("invalid height"); + return; + } + + if ((frame->rawwidth * 2) != frame->width) { + err("invalid width"); + return; + } + + /* Y */ + pInOdd = pIn0; + pInEven = pInOdd + fieldpix; + pOut = pOut0; + for (y = 0; y < fieldheight; y++) { + for (x = 0; x < frame->rawwidth; x++) { + *pOut = *pInEven; + *(pOut+1) = *pInEven++; + *(pOut+w) = *pInOdd; + *(pOut+w+1) = *pInOdd++; + pOut += 2; + } + pOut += w; + } + + if (rawformat == RAWFMT_YUV420) { + /* U */ + pInOdd = pIn0 + fieldpix * 2; + pInEven = pInOdd + fieldpix / 4; + for (y = 0; y < fieldheight / 2; y++) { + for (x = 0; x < frame->rawwidth / 2; x++) { + *pOut = *pInEven; + *(pOut+1) = *pInEven++; + *(pOut+w/2) = *pInOdd; + *(pOut+w/2+1) = *pInOdd++; + pOut += 2; + } + pOut += w/2; + } + /* V */ + pInOdd = pIn0 + fieldpix * 2 + fieldpix / 2; + pInEven = pInOdd + fieldpix / 4; + for (y = 0; y < fieldheight / 2; y++) { + for (x = 0; x < frame->rawwidth / 2; x++) { + *pOut = *pInEven; + *(pOut+1) = *pInEven++; + *(pOut+w/2) = *pInOdd; + *(pOut+w/2+1) = *pInOdd++; + pOut += 2; + } + pOut += w/2; + } + } +} + +static void +ov51x_postprocess_grey(struct usb_ov511 *ov, struct ov511_frame *frame) +{ + /* Deinterlace frame, if necessary */ + if (ov->sensor == SEN_SAA7111A && frame->rawheight >= 480) { + if (frame->compressed) + decompress(ov, frame, frame->rawdata, + frame->tempdata); + else + yuv400raw_to_yuv400p(frame, frame->rawdata, + frame->tempdata); + + deinterlace(frame, RAWFMT_YUV400, frame->tempdata, + frame->data); + } else { + if (frame->compressed) + decompress(ov, frame, frame->rawdata, + frame->data); + else + yuv400raw_to_yuv400p(frame, frame->rawdata, + frame->data); + } +} + +/* Process raw YUV420 data into standard YUV420P */ +static void +ov51x_postprocess_yuv420(struct usb_ov511 *ov, struct ov511_frame *frame) +{ + /* Deinterlace frame, if necessary */ + if (ov->sensor == SEN_SAA7111A && frame->rawheight >= 480) { + if (frame->compressed) + decompress(ov, frame, frame->rawdata, frame->tempdata); + else + yuv420raw_to_yuv420p(frame, frame->rawdata, + frame->tempdata); + + deinterlace(frame, RAWFMT_YUV420, frame->tempdata, + frame->data); + } else { + if (frame->compressed) + decompress(ov, frame, frame->rawdata, frame->data); + else + yuv420raw_to_yuv420p(frame, frame->rawdata, + frame->data); + } +} + +/* Post-processes the specified frame. This consists of: + * 1. Decompress frame, if necessary + * 2. Deinterlace frame and scale to proper size, if necessary + * 3. Convert from YUV planar to destination format, if necessary + * 4. Fix the RGB offset, if necessary + */ +static void +ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame) +{ + if (dumppix) { + memset(frame->data, 0, + MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)); + PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd); + memcpy(frame->data, frame->rawdata, frame->bytes_recvd); + } else { + switch (frame->format) { + case VIDEO_PALETTE_GREY: + ov51x_postprocess_grey(ov, frame); + break; + case VIDEO_PALETTE_YUV420: + case VIDEO_PALETTE_YUV420P: + ov51x_postprocess_yuv420(ov, frame); + break; + default: + err("Cannot convert data to %s", + symbolic(v4l1_plist, frame->format)); + } + } +} + +/********************************************************************** + * + * OV51x data transfer, IRQ handler + * + **********************************************************************/ + +static inline void +ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n) +{ + int num, offset; + int pnum = in[ov->packet_size - 1]; /* Get packet number */ + int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight); + struct ov511_frame *frame = &ov->frame[ov->curframe]; + struct timeval *ts; + + /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th + * byte non-zero. The EOF packet has image width/height in the + * 10th and 11th bytes. The 9th byte is given as follows: + * + * bit 7: EOF + * 6: compression enabled + * 5: 422/420/400 modes + * 4: 422/420/400 modes + * 3: 1 + * 2: snapshot button on + * 1: snapshot frame + * 0: even/odd field + */ + + if (printph) { + info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", + pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6], + in[7], in[8], in[9], in[10], in[11]); + } + + /* Check for SOF/EOF packet */ + if ((in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) || + (~in[8] & 0x08)) + goto check_middle; + + /* Frame end */ + if (in[8] & 0x80) { + ts = (struct timeval *)(frame->data + + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight)); + do_gettimeofday(ts); + + /* Get the actual frame size from the EOF header */ + frame->rawwidth = ((int)(in[9]) + 1) * 8; + frame->rawheight = ((int)(in[10]) + 1) * 8; + + PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d", + ov->curframe, pnum, frame->rawwidth, frame->rawheight, + frame->bytes_recvd); + + /* Validate the header data */ + RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth); + RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, + ov->maxheight); + + /* Don't allow byte count to exceed buffer size */ + RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); + + if (frame->scanstate == STATE_LINES) { + int nextf; + + frame->grabstate = FRAME_DONE; + wake_up_interruptible(&frame->wq); + + /* If next frame is ready or grabbing, + * point to it */ + nextf = (ov->curframe + 1) % OV511_NUMFRAMES; + if (ov->frame[nextf].grabstate == FRAME_READY + || ov->frame[nextf].grabstate == FRAME_GRABBING) { + ov->curframe = nextf; + ov->frame[nextf].scanstate = STATE_SCANNING; + } else { + if (frame->grabstate == FRAME_DONE) { + PDEBUG(4, "** Frame done **"); + } else { + PDEBUG(4, "Frame not ready? state = %d", + ov->frame[nextf].grabstate); + } + + ov->curframe = -1; + } + } else { + PDEBUG(5, "Frame done, but not scanning"); + } + /* Image corruption caused by misplaced frame->segment = 0 + * fixed by carlosf@conectiva.com.br + */ + } else { + /* Frame start */ + PDEBUG(4, "Frame start, framenum = %d", ov->curframe); + + /* Check to see if it's a snapshot frame */ + /* FIXME?? Should the snapshot reset go here? Performance? */ + if (in[8] & 0x02) { + frame->snapshot = 1; + PDEBUG(3, "snapshot detected"); + } + + frame->scanstate = STATE_LINES; + frame->bytes_recvd = 0; + frame->compressed = in[8] & 0x40; + } + +check_middle: + /* Are we in a frame? */ + if (frame->scanstate != STATE_LINES) { + PDEBUG(5, "Not in a frame; packet skipped"); + return; + } + + /* If frame start, skip header */ + if (frame->bytes_recvd == 0) + offset = 9; + else + offset = 0; + + num = n - offset - 1; + + /* Dump all data exactly as received */ + if (dumppix == 2) { + frame->bytes_recvd += n - 1; + if (frame->bytes_recvd <= max_raw) + memcpy(frame->rawdata + frame->bytes_recvd - (n - 1), + in, n - 1); + else + PDEBUG(3, "Raw data buffer overrun!! (%d)", + frame->bytes_recvd - max_raw); + } else if (!frame->compressed && !remove_zeros) { + frame->bytes_recvd += num; + if (frame->bytes_recvd <= max_raw) + memcpy(frame->rawdata + frame->bytes_recvd - num, + in + offset, num); + else + PDEBUG(3, "Raw data buffer overrun!! (%d)", + frame->bytes_recvd - max_raw); + } else { /* Remove all-zero FIFO lines (aligned 32-byte blocks) */ + int b, read = 0, allzero, copied = 0; + if (offset) { + frame->bytes_recvd += 32 - offset; // Bytes out + memcpy(frame->rawdata, in + offset, 32 - offset); + read += 32; + } + + while (read < n - 1) { + allzero = 1; + for (b = 0; b < 32; b++) { + if (in[read + b]) { + allzero = 0; + break; + } + } + + if (allzero) { + /* Don't copy it */ + } else { + if (frame->bytes_recvd + copied + 32 <= max_raw) + { + memcpy(frame->rawdata + + frame->bytes_recvd + copied, + in + read, 32); + copied += 32; + } else { + PDEBUG(3, "Raw data buffer overrun!!"); + } + } + read += 32; + } + + frame->bytes_recvd += copied; + } +} + +static inline void +ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n) +{ + int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight); + struct ov511_frame *frame = &ov->frame[ov->curframe]; + struct timeval *ts; + + /* Don't copy the packet number byte */ + if (ov->packet_numbering) + --n; + + /* A false positive here is likely, until OVT gives me + * the definitive SOF/EOF format */ + if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) { + if (printph) { + info("ph: %2x %2x %2x %2x %2x %2x %2x %2x", in[0], + in[1], in[2], in[3], in[4], in[5], in[6], in[7]); + } + + if (frame->scanstate == STATE_LINES) { + PDEBUG(4, "Detected frame end/start"); + goto eof; + } else { //scanstate == STATE_SCANNING + /* Frame start */ + PDEBUG(4, "Frame start, framenum = %d", ov->curframe); + goto sof; + } + } else { + goto check_middle; + } + +eof: + ts = (struct timeval *)(frame->data + + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight)); + do_gettimeofday(ts); + + PDEBUG(4, "Frame end, curframe = %d, hw=%d, vw=%d, recvd=%d", + ov->curframe, + (int)(in[9]), (int)(in[10]), frame->bytes_recvd); + + // FIXME: Since we don't know the header formats yet, + // there is no way to know what the actual image size is + frame->rawwidth = frame->width; + frame->rawheight = frame->height; + + /* Validate the header data */ + RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth); + RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, ov->maxheight); + + /* Don't allow byte count to exceed buffer size */ + RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); + + if (frame->scanstate == STATE_LINES) { + int nextf; + + frame->grabstate = FRAME_DONE; + wake_up_interruptible(&frame->wq); + + /* If next frame is ready or grabbing, + * point to it */ + nextf = (ov->curframe + 1) % OV511_NUMFRAMES; + if (ov->frame[nextf].grabstate == FRAME_READY + || ov->frame[nextf].grabstate == FRAME_GRABBING) { + ov->curframe = nextf; + ov->frame[nextf].scanstate = STATE_SCANNING; + frame = &ov->frame[nextf]; + } else { + if (frame->grabstate == FRAME_DONE) { + PDEBUG(4, "** Frame done **"); + } else { + PDEBUG(4, "Frame not ready? state = %d", + ov->frame[nextf].grabstate); + } + + ov->curframe = -1; + PDEBUG(4, "SOF dropped (no active frame)"); + return; /* Nowhere to store this frame */ + } + } +sof: + PDEBUG(4, "Starting capture on frame %d", frame->framenum); + +// Snapshot not reverse-engineered yet. +#if 0 + /* Check to see if it's a snapshot frame */ + /* FIXME?? Should the snapshot reset go here? Performance? */ + if (in[8] & 0x02) { + frame->snapshot = 1; + PDEBUG(3, "snapshot detected"); + } +#endif + frame->scanstate = STATE_LINES; + frame->bytes_recvd = 0; + frame->compressed = 1; + +check_middle: + /* Are we in a frame? */ + if (frame->scanstate != STATE_LINES) { + PDEBUG(4, "scanstate: no SOF yet"); + return; + } + + /* Dump all data exactly as received */ + if (dumppix == 2) { + frame->bytes_recvd += n; + if (frame->bytes_recvd <= max_raw) + memcpy(frame->rawdata + frame->bytes_recvd - n, in, n); + else + PDEBUG(3, "Raw data buffer overrun!! (%d)", + frame->bytes_recvd - max_raw); + } else { + /* All incoming data are divided into 8-byte segments. If the + * segment contains all zero bytes, it must be skipped. These + * zero-segments allow the OV518 to mainain a constant data rate + * regardless of the effectiveness of the compression. Segments + * are aligned relative to the beginning of each isochronous + * packet. The first segment in each image is a header (the + * decompressor skips it later). + */ + + int b, read = 0, allzero, copied = 0; + + while (read < n) { + allzero = 1; + for (b = 0; b < 8; b++) { + if (in[read + b]) { + allzero = 0; + break; + } + } + + if (allzero) { + /* Don't copy it */ + } else { + if (frame->bytes_recvd + copied + 8 <= max_raw) + { + memcpy(frame->rawdata + + frame->bytes_recvd + copied, + in + read, 8); + copied += 8; + } else { + PDEBUG(3, "Raw data buffer overrun!!"); + } + } + read += 8; + } + frame->bytes_recvd += copied; + } +} + +static void +ov51x_isoc_irq(struct urb *urb, struct pt_regs *regs) +{ + int i; + struct usb_ov511 *ov; + struct ov511_sbuf *sbuf; + + if (!urb->context) { + PDEBUG(4, "no context"); + return; + } + + sbuf = urb->context; + ov = sbuf->ov; + + if (!ov || !ov->dev || !ov->user) { + PDEBUG(4, "no device, or not open"); + return; + } + + if (!ov->streaming) { + PDEBUG(4, "hmmm... not streaming, but got interrupt"); + return; + } + + if (urb->status == -ENOENT || urb->status == -ECONNRESET) { + PDEBUG(4, "URB unlinked"); + return; + } + + if (urb->status != -EINPROGRESS && urb->status != 0) { + err("ERROR: urb->status=%d: %s", urb->status, + symbolic(urb_errlist, urb->status)); + } + + /* Copy the data received into our frame buffer */ + PDEBUG(5, "sbuf[%d]: Moving %d packets", sbuf->n, + urb->number_of_packets); + for (i = 0; i < urb->number_of_packets; i++) { + /* Warning: Don't call *_move_data() if no frame active! */ + if (ov->curframe >= 0) { + int n = urb->iso_frame_desc[i].actual_length; + int st = urb->iso_frame_desc[i].status; + unsigned char *cdata; + + urb->iso_frame_desc[i].actual_length = 0; + urb->iso_frame_desc[i].status = 0; + + cdata = urb->transfer_buffer + + urb->iso_frame_desc[i].offset; + + if (!n) { + PDEBUG(4, "Zero-length packet"); + continue; + } + + if (st) + PDEBUG(2, "data error: [%d] len=%d, status=%d", + i, n, st); + + if (ov->bclass == BCL_OV511) + ov511_move_data(ov, cdata, n); + else if (ov->bclass == BCL_OV518) + ov518_move_data(ov, cdata, n); + else + err("Unknown bridge device (%d)", ov->bridge); + + } else if (waitqueue_active(&ov->wq)) { + wake_up_interruptible(&ov->wq); + } + } + + /* Resubmit this URB */ + urb->dev = ov->dev; + if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0) + err("usb_submit_urb() ret %d", i); + + return; +} + +/**************************************************************************** + * + * Stream initialization and termination + * + ***************************************************************************/ + +static int +ov51x_init_isoc(struct usb_ov511 *ov) +{ + struct urb *urb; + int fx, err, n, size; + + PDEBUG(3, "*** Initializing capture ***"); + + ov->curframe = -1; + + if (ov->bridge == BRG_OV511) { + if (cams == 1) + size = 993; + else if (cams == 2) + size = 513; + else if (cams == 3 || cams == 4) + size = 257; + else { + err("\"cams\" parameter too high!"); + return -1; + } + } else if (ov->bridge == BRG_OV511PLUS) { + if (cams == 1) + size = 961; + else if (cams == 2) + size = 513; + else if (cams == 3 || cams == 4) + size = 257; + else if (cams >= 5 && cams <= 8) + size = 129; + else if (cams >= 9 && cams <= 31) + size = 33; + else { + err("\"cams\" parameter too high!"); + return -1; + } + } else if (ov->bclass == BCL_OV518) { + if (cams == 1) + size = 896; + else if (cams == 2) + size = 512; + else if (cams == 3 || cams == 4) + size = 256; + else if (cams >= 5 && cams <= 8) + size = 128; + else { + err("\"cams\" parameter too high!"); + return -1; + } + } else { + err("invalid bridge type"); + return -1; + } + + // FIXME: OV518 is hardcoded to 15 FPS (alternate 5) for now + if (ov->bclass == BCL_OV518) { + if (packetsize == -1) { + ov518_set_packet_size(ov, 640); + } else { + info("Forcing packet size to %d", packetsize); + ov518_set_packet_size(ov, packetsize); + } + } else { + if (packetsize == -1) { + ov511_set_packet_size(ov, size); + } else { + info("Forcing packet size to %d", packetsize); + ov511_set_packet_size(ov, packetsize); + } + } + + for (n = 0; n < OV511_NUMSBUF; n++) { + urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); + if (!urb) { + err("init isoc: usb_alloc_urb ret. NULL"); + return -ENOMEM; + } + ov->sbuf[n].urb = urb; + urb->dev = ov->dev; + urb->context = &ov->sbuf[n]; + urb->pipe = usb_rcvisocpipe(ov->dev, OV511_ENDPOINT_ADDRESS); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = ov->sbuf[n].data; + urb->complete = ov51x_isoc_irq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = ov->packet_size * FRAMES_PER_DESC; + urb->interval = 1; + for (fx = 0; fx < FRAMES_PER_DESC; fx++) { + urb->iso_frame_desc[fx].offset = ov->packet_size * fx; + urb->iso_frame_desc[fx].length = ov->packet_size; + } + } + + ov->streaming = 1; + + for (n = 0; n < OV511_NUMSBUF; n++) { + ov->sbuf[n].urb->dev = ov->dev; + err = usb_submit_urb(ov->sbuf[n].urb, GFP_KERNEL); + if (err) { + err("init isoc: usb_submit_urb(%d) ret %d", n, err); + return err; + } + } + + return 0; +} + +static void +ov51x_unlink_isoc(struct usb_ov511 *ov) +{ + int n; + + /* Unschedule all of the iso td's */ + for (n = OV511_NUMSBUF - 1; n >= 0; n--) { + if (ov->sbuf[n].urb) { + usb_kill_urb(ov->sbuf[n].urb); + usb_free_urb(ov->sbuf[n].urb); + ov->sbuf[n].urb = NULL; + } + } +} + +static void +ov51x_stop_isoc(struct usb_ov511 *ov) +{ + if (!ov->streaming || !ov->dev) + return; + + PDEBUG(3, "*** Stopping capture ***"); + + if (ov->bclass == BCL_OV518) + ov518_set_packet_size(ov, 0); + else + ov511_set_packet_size(ov, 0); + + ov->streaming = 0; + + ov51x_unlink_isoc(ov); +} + +static int +ov51x_new_frame(struct usb_ov511 *ov, int framenum) +{ + struct ov511_frame *frame; + int newnum; + + PDEBUG(4, "ov->curframe = %d, framenum = %d", ov->curframe, framenum); + + if (!ov->dev) + return -1; + + /* If we're not grabbing a frame right now and the other frame is */ + /* ready to be grabbed into, then use it instead */ + if (ov->curframe == -1) { + newnum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES; + if (ov->frame[newnum].grabstate == FRAME_READY) + framenum = newnum; + } else + return 0; + + frame = &ov->frame[framenum]; + + PDEBUG(4, "framenum = %d, width = %d, height = %d", framenum, + frame->width, frame->height); + + frame->grabstate = FRAME_GRABBING; + frame->scanstate = STATE_SCANNING; + frame->snapshot = 0; + + ov->curframe = framenum; + + /* Make sure it's not too big */ + if (frame->width > ov->maxwidth) + frame->width = ov->maxwidth; + + frame->width &= ~7L; /* Multiple of 8 */ + + if (frame->height > ov->maxheight) + frame->height = ov->maxheight; + + frame->height &= ~3L; /* Multiple of 4 */ + + return 0; +} + +/**************************************************************************** + * + * Buffer management + * + ***************************************************************************/ + +/* + * - You must acquire buf_lock before entering this function. + * - Because this code will free any non-null pointer, you must be sure to null + * them if you explicitly free them somewhere else! + */ +static void +ov51x_do_dealloc(struct usb_ov511 *ov) +{ + int i; + PDEBUG(4, "entered"); + + if (ov->fbuf) { + rvfree(ov->fbuf, OV511_NUMFRAMES + * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)); + ov->fbuf = NULL; + } + + vfree(ov->rawfbuf); + ov->rawfbuf = NULL; + + vfree(ov->tempfbuf); + ov->tempfbuf = NULL; + + for (i = 0; i < OV511_NUMSBUF; i++) { + kfree(ov->sbuf[i].data); + ov->sbuf[i].data = NULL; + } + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].data = NULL; + ov->frame[i].rawdata = NULL; + ov->frame[i].tempdata = NULL; + if (ov->frame[i].compbuf) { + free_page((unsigned long) ov->frame[i].compbuf); + ov->frame[i].compbuf = NULL; + } + } + + PDEBUG(4, "buffer memory deallocated"); + ov->buf_state = BUF_NOT_ALLOCATED; + PDEBUG(4, "leaving"); +} + +static int +ov51x_alloc(struct usb_ov511 *ov) +{ + int i; + const int w = ov->maxwidth; + const int h = ov->maxheight; + const int data_bufsize = OV511_NUMFRAMES * MAX_DATA_SIZE(w, h); + const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h); + + PDEBUG(4, "entered"); + mutex_lock(&ov->buf_lock); + + if (ov->buf_state == BUF_ALLOCATED) + goto out; + + ov->fbuf = rvmalloc(data_bufsize); + if (!ov->fbuf) + goto error; + + ov->rawfbuf = vmalloc(raw_bufsize); + if (!ov->rawfbuf) + goto error; + + memset(ov->rawfbuf, 0, raw_bufsize); + + ov->tempfbuf = vmalloc(raw_bufsize); + if (!ov->tempfbuf) + goto error; + + memset(ov->tempfbuf, 0, raw_bufsize); + + for (i = 0; i < OV511_NUMSBUF; i++) { + ov->sbuf[i].data = kmalloc(FRAMES_PER_DESC * + MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); + if (!ov->sbuf[i].data) + goto error; + + PDEBUG(4, "sbuf[%d] @ %p", i, ov->sbuf[i].data); + } + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].data = ov->fbuf + i * MAX_DATA_SIZE(w, h); + ov->frame[i].rawdata = ov->rawfbuf + + i * MAX_RAW_DATA_SIZE(w, h); + ov->frame[i].tempdata = ov->tempfbuf + + i * MAX_RAW_DATA_SIZE(w, h); + + ov->frame[i].compbuf = + (unsigned char *) __get_free_page(GFP_KERNEL); + if (!ov->frame[i].compbuf) + goto error; + + PDEBUG(4, "frame[%d] @ %p", i, ov->frame[i].data); + } + + ov->buf_state = BUF_ALLOCATED; +out: + mutex_unlock(&ov->buf_lock); + PDEBUG(4, "leaving"); + return 0; +error: + ov51x_do_dealloc(ov); + mutex_unlock(&ov->buf_lock); + PDEBUG(4, "errored"); + return -ENOMEM; +} + +static void +ov51x_dealloc(struct usb_ov511 *ov) +{ + PDEBUG(4, "entered"); + mutex_lock(&ov->buf_lock); + ov51x_do_dealloc(ov); + mutex_unlock(&ov->buf_lock); + PDEBUG(4, "leaving"); +} + +/**************************************************************************** + * + * V4L 1 API + * + ***************************************************************************/ + +static int +ov51x_v4l1_open(struct inode *inode, struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct usb_ov511 *ov = video_get_drvdata(vdev); + int err, i; + + PDEBUG(4, "opening"); + + mutex_lock(&ov->lock); + + err = -EBUSY; + if (ov->user) + goto out; + + ov->sub_flag = 0; + + /* In case app doesn't set them... */ + err = ov51x_set_default_params(ov); + if (err < 0) + goto out; + + /* Make sure frames are reset */ + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].grabstate = FRAME_UNUSED; + ov->frame[i].bytes_read = 0; + } + + /* If compression is on, make sure now that a + * decompressor can be loaded */ + if (ov->compress && !ov->decomp_ops) { + err = request_decompressor(ov); + if (err && !dumppix) + goto out; + } + + err = ov51x_alloc(ov); + if (err < 0) + goto out; + + err = ov51x_init_isoc(ov); + if (err) { + ov51x_dealloc(ov); + goto out; + } + + ov->user++; + file->private_data = vdev; + + if (ov->led_policy == LED_AUTO) + ov51x_led_control(ov, 1); + +out: + mutex_unlock(&ov->lock); + return err; +} + +static int +ov51x_v4l1_close(struct inode *inode, struct file *file) +{ + struct video_device *vdev = file->private_data; + struct usb_ov511 *ov = video_get_drvdata(vdev); + + PDEBUG(4, "ov511_close"); + + mutex_lock(&ov->lock); + + ov->user--; + ov51x_stop_isoc(ov); + + if (ov->led_policy == LED_AUTO) + ov51x_led_control(ov, 0); + + if (ov->dev) + ov51x_dealloc(ov); + + mutex_unlock(&ov->lock); + + /* Device unplugged while open. Only a minimum of unregistration is done + * here; the disconnect callback already did the rest. */ + if (!ov->dev) { + mutex_lock(&ov->cbuf_lock); + kfree(ov->cbuf); + ov->cbuf = NULL; + mutex_unlock(&ov->cbuf_lock); + + ov51x_dealloc(ov); + kfree(ov); + ov = NULL; + } + + file->private_data = NULL; + return 0; +} + +/* Do not call this function directly! */ +static int +ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct video_device *vdev = file->private_data; + struct usb_ov511 *ov = video_get_drvdata(vdev); + PDEBUG(5, "IOCtl: 0x%X", cmd); + + if (!ov->dev) + return -EIO; + + switch (cmd) { + case VIDIOCGCAP: + { + struct video_capability *b = arg; + + PDEBUG(4, "VIDIOCGCAP"); + + memset(b, 0, sizeof(struct video_capability)); + sprintf(b->name, "%s USB Camera", + symbolic(brglist, ov->bridge)); + b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE; + b->channels = ov->num_inputs; + b->audios = 0; + b->maxwidth = ov->maxwidth; + b->maxheight = ov->maxheight; + b->minwidth = ov->minwidth; + b->minheight = ov->minheight; + + return 0; + } + case VIDIOCGCHAN: + { + struct video_channel *v = arg; + + PDEBUG(4, "VIDIOCGCHAN"); + + if ((unsigned)(v->channel) >= ov->num_inputs) { + err("Invalid channel (%d)", v->channel); + return -EINVAL; + } + + v->norm = ov->norm; + v->type = VIDEO_TYPE_CAMERA; + v->flags = 0; +// v->flags |= (ov->has_decoder) ? VIDEO_VC_NORM : 0; + v->tuners = 0; + decoder_get_input_name(ov, v->channel, v->name); + + return 0; + } + case VIDIOCSCHAN: + { + struct video_channel *v = arg; + int err; + + PDEBUG(4, "VIDIOCSCHAN"); + + /* Make sure it's not a camera */ + if (!ov->has_decoder) { + if (v->channel == 0) + return 0; + else + return -EINVAL; + } + + if (v->norm != VIDEO_MODE_PAL && + v->norm != VIDEO_MODE_NTSC && + v->norm != VIDEO_MODE_SECAM && + v->norm != VIDEO_MODE_AUTO) { + err("Invalid norm (%d)", v->norm); + return -EINVAL; + } + + if ((unsigned)(v->channel) >= ov->num_inputs) { + err("Invalid channel (%d)", v->channel); + return -EINVAL; + } + + err = decoder_set_input(ov, v->channel); + if (err) + return err; + + err = decoder_set_norm(ov, v->norm); + if (err) + return err; + + return 0; + } + case VIDIOCGPICT: + { + struct video_picture *p = arg; + + PDEBUG(4, "VIDIOCGPICT"); + + memset(p, 0, sizeof(struct video_picture)); + if (sensor_get_picture(ov, p)) + return -EIO; + + /* Can we get these from frame[0]? -claudio? */ + p->depth = ov->frame[0].depth; + p->palette = ov->frame[0].format; + + return 0; + } + case VIDIOCSPICT: + { + struct video_picture *p = arg; + int i, rc; + + PDEBUG(4, "VIDIOCSPICT"); + + if (!get_depth(p->palette)) + return -EINVAL; + + if (sensor_set_picture(ov, p)) + return -EIO; + + if (force_palette && p->palette != force_palette) { + info("Palette rejected (%s)", + symbolic(v4l1_plist, p->palette)); + return -EINVAL; + } + + // FIXME: Format should be independent of frames + if (p->palette != ov->frame[0].format) { + PDEBUG(4, "Detected format change"); + + rc = ov51x_wait_frames_inactive(ov); + if (rc) + return rc; + + mode_init_regs(ov, ov->frame[0].width, + ov->frame[0].height, p->palette, ov->sub_flag); + } + + PDEBUG(4, "Setting depth=%d, palette=%s", + p->depth, symbolic(v4l1_plist, p->palette)); + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].depth = p->depth; + ov->frame[i].format = p->palette; + } + + return 0; + } + case VIDIOCGCAPTURE: + { + int *vf = arg; + + PDEBUG(4, "VIDIOCGCAPTURE"); + + ov->sub_flag = *vf; + return 0; + } + case VIDIOCSCAPTURE: + { + struct video_capture *vc = arg; + + PDEBUG(4, "VIDIOCSCAPTURE"); + + if (vc->flags) + return -EINVAL; + if (vc->decimation) + return -EINVAL; + + vc->x &= ~3L; + vc->y &= ~1L; + vc->y &= ~31L; + + if (vc->width == 0) + vc->width = 32; + + vc->height /= 16; + vc->height *= 16; + if (vc->height == 0) + vc->height = 16; + + ov->subx = vc->x; + ov->suby = vc->y; + ov->subw = vc->width; + ov->subh = vc->height; + + return 0; + } + case VIDIOCSWIN: + { + struct video_window *vw = arg; + int i, rc; + + PDEBUG(4, "VIDIOCSWIN: %dx%d", vw->width, vw->height); + +#if 0 + if (vw->flags) + return -EINVAL; + if (vw->clipcount) + return -EINVAL; + if (vw->height != ov->maxheight) + return -EINVAL; + if (vw->width != ov->maxwidth) + return -EINVAL; +#endif + + rc = ov51x_wait_frames_inactive(ov); + if (rc) + return rc; + + rc = mode_init_regs(ov, vw->width, vw->height, + ov->frame[0].format, ov->sub_flag); + if (rc < 0) + return rc; + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].width = vw->width; + ov->frame[i].height = vw->height; + } + + return 0; + } + case VIDIOCGWIN: + { + struct video_window *vw = arg; + + memset(vw, 0, sizeof(struct video_window)); + vw->x = 0; /* FIXME */ + vw->y = 0; + vw->width = ov->frame[0].width; + vw->height = ov->frame[0].height; + vw->flags = 30; + + PDEBUG(4, "VIDIOCGWIN: %dx%d", vw->width, vw->height); + + return 0; + } + case VIDIOCGMBUF: + { + struct video_mbuf *vm = arg; + int i; + + PDEBUG(4, "VIDIOCGMBUF"); + + memset(vm, 0, sizeof(struct video_mbuf)); + vm->size = OV511_NUMFRAMES + * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight); + vm->frames = OV511_NUMFRAMES; + + vm->offsets[0] = 0; + for (i = 1; i < OV511_NUMFRAMES; i++) { + vm->offsets[i] = vm->offsets[i-1] + + MAX_DATA_SIZE(ov->maxwidth, ov->maxheight); + } + + return 0; + } + case VIDIOCMCAPTURE: + { + struct video_mmap *vm = arg; + int rc, depth; + unsigned int f = vm->frame; + + PDEBUG(4, "VIDIOCMCAPTURE: frame: %d, %dx%d, %s", f, vm->width, + vm->height, symbolic(v4l1_plist, vm->format)); + + depth = get_depth(vm->format); + if (!depth) { + PDEBUG(2, "VIDIOCMCAPTURE: invalid format (%s)", + symbolic(v4l1_plist, vm->format)); + return -EINVAL; + } + + if (f >= OV511_NUMFRAMES) { + err("VIDIOCMCAPTURE: invalid frame (%d)", f); + return -EINVAL; + } + + if (vm->width > ov->maxwidth + || vm->height > ov->maxheight) { + err("VIDIOCMCAPTURE: requested dimensions too big"); + return -EINVAL; + } + + if (ov->frame[f].grabstate == FRAME_GRABBING) { + PDEBUG(4, "VIDIOCMCAPTURE: already grabbing"); + return -EBUSY; + } + + if (force_palette && (vm->format != force_palette)) { + PDEBUG(2, "palette rejected (%s)", + symbolic(v4l1_plist, vm->format)); + return -EINVAL; + } + + if ((ov->frame[f].width != vm->width) || + (ov->frame[f].height != vm->height) || + (ov->frame[f].format != vm->format) || + (ov->frame[f].sub_flag != ov->sub_flag) || + (ov->frame[f].depth != depth)) { + PDEBUG(4, "VIDIOCMCAPTURE: change in image parameters"); + + rc = ov51x_wait_frames_inactive(ov); + if (rc) + return rc; + + rc = mode_init_regs(ov, vm->width, vm->height, + vm->format, ov->sub_flag); +#if 0 + if (rc < 0) { + PDEBUG(1, "Got error while initializing regs "); + return ret; + } +#endif + ov->frame[f].width = vm->width; + ov->frame[f].height = vm->height; + ov->frame[f].format = vm->format; + ov->frame[f].sub_flag = ov->sub_flag; + ov->frame[f].depth = depth; + } + + /* Mark it as ready */ + ov->frame[f].grabstate = FRAME_READY; + + PDEBUG(4, "VIDIOCMCAPTURE: renewing frame %d", f); + + return ov51x_new_frame(ov, f); + } + case VIDIOCSYNC: + { + unsigned int fnum = *((unsigned int *) arg); + struct ov511_frame *frame; + int rc; + + if (fnum >= OV511_NUMFRAMES) { + err("VIDIOCSYNC: invalid frame (%d)", fnum); + return -EINVAL; + } + + frame = &ov->frame[fnum]; + + PDEBUG(4, "syncing to frame %d, grabstate = %d", fnum, + frame->grabstate); + + switch (frame->grabstate) { + case FRAME_UNUSED: + return -EINVAL; + case FRAME_READY: + case FRAME_GRABBING: + case FRAME_ERROR: +redo: + if (!ov->dev) + return -EIO; + + rc = wait_event_interruptible(frame->wq, + (frame->grabstate == FRAME_DONE) + || (frame->grabstate == FRAME_ERROR)); + + if (rc) + return rc; + + if (frame->grabstate == FRAME_ERROR) { + if ((rc = ov51x_new_frame(ov, fnum)) < 0) + return rc; + goto redo; + } + /* Fall through */ + case FRAME_DONE: + if (ov->snap_enabled && !frame->snapshot) { + if ((rc = ov51x_new_frame(ov, fnum)) < 0) + return rc; + goto redo; + } + + frame->grabstate = FRAME_UNUSED; + + /* Reset the hardware snapshot button */ + /* FIXME - Is this the best place for this? */ + if ((ov->snap_enabled) && (frame->snapshot)) { + frame->snapshot = 0; + ov51x_clear_snapshot(ov); + } + + /* Decompression, format conversion, etc... */ + ov51x_postprocess(ov, frame); + + break; + } /* end switch */ + + return 0; + } + case VIDIOCGFBUF: + { + struct video_buffer *vb = arg; + + PDEBUG(4, "VIDIOCGFBUF"); + + memset(vb, 0, sizeof(struct video_buffer)); + + return 0; + } + case VIDIOCGUNIT: + { + struct video_unit *vu = arg; + + PDEBUG(4, "VIDIOCGUNIT"); + + memset(vu, 0, sizeof(struct video_unit)); + + vu->video = ov->vdev->minor; + vu->vbi = VIDEO_NO_UNIT; + vu->radio = VIDEO_NO_UNIT; + vu->audio = VIDEO_NO_UNIT; + vu->teletext = VIDEO_NO_UNIT; + + return 0; + } + case OV511IOC_WI2C: + { + struct ov511_i2c_struct *w = arg; + + return i2c_w_slave(ov, w->slave, w->reg, w->value, w->mask); + } + case OV511IOC_RI2C: + { + struct ov511_i2c_struct *r = arg; + int rc; + + rc = i2c_r_slave(ov, r->slave, r->reg); + if (rc < 0) + return rc; + + r->value = rc; + return 0; + } + default: + PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd); + return -ENOIOCTLCMD; + } /* end switch */ + + return 0; +} + +static int +ov51x_v4l1_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct video_device *vdev = file->private_data; + struct usb_ov511 *ov = video_get_drvdata(vdev); + int rc; + + if (mutex_lock_interruptible(&ov->lock)) + return -EINTR; + + rc = video_usercopy(inode, file, cmd, arg, ov51x_v4l1_ioctl_internal); + + mutex_unlock(&ov->lock); + return rc; +} + +static ssize_t +ov51x_v4l1_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos) +{ + struct video_device *vdev = file->private_data; + int noblock = file->f_flags&O_NONBLOCK; + unsigned long count = cnt; + struct usb_ov511 *ov = video_get_drvdata(vdev); + int i, rc = 0, frmx = -1; + struct ov511_frame *frame; + + if (mutex_lock_interruptible(&ov->lock)) + return -EINTR; + + PDEBUG(4, "%ld bytes, noblock=%d", count, noblock); + + if (!vdev || !buf) { + rc = -EFAULT; + goto error; + } + + if (!ov->dev) { + rc = -EIO; + goto error; + } + +// FIXME: Only supports two frames + /* See if a frame is completed, then use it. */ + if (ov->frame[0].grabstate >= FRAME_DONE) /* _DONE or _ERROR */ + frmx = 0; + else if (ov->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */ + frmx = 1; + + /* If nonblocking we return immediately */ + if (noblock && (frmx == -1)) { + rc = -EAGAIN; + goto error; + } + + /* If no FRAME_DONE, look for a FRAME_GRABBING state. */ + /* See if a frame is in process (grabbing), then use it. */ + if (frmx == -1) { + if (ov->frame[0].grabstate == FRAME_GRABBING) + frmx = 0; + else if (ov->frame[1].grabstate == FRAME_GRABBING) + frmx = 1; + } + + /* If no frame is active, start one. */ + if (frmx == -1) { + if ((rc = ov51x_new_frame(ov, frmx = 0))) { + err("read: ov51x_new_frame error"); + goto error; + } + } + + frame = &ov->frame[frmx]; + +restart: + if (!ov->dev) { + rc = -EIO; + goto error; + } + + /* Wait while we're grabbing the image */ + PDEBUG(4, "Waiting image grabbing"); + rc = wait_event_interruptible(frame->wq, + (frame->grabstate == FRAME_DONE) + || (frame->grabstate == FRAME_ERROR)); + + if (rc) + goto error; + + PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate); + PDEBUG(4, "bytes_recvd = %d", frame->bytes_recvd); + + if (frame->grabstate == FRAME_ERROR) { + frame->bytes_read = 0; + err("** ick! ** Errored frame %d", ov->curframe); + if (ov51x_new_frame(ov, frmx)) { + err("read: ov51x_new_frame error"); + goto error; + } + goto restart; + } + + + /* Repeat until we get a snapshot frame */ + if (ov->snap_enabled) + PDEBUG(4, "Waiting snapshot frame"); + if (ov->snap_enabled && !frame->snapshot) { + frame->bytes_read = 0; + if ((rc = ov51x_new_frame(ov, frmx))) { + err("read: ov51x_new_frame error"); + goto error; + } + goto restart; + } + + /* Clear the snapshot */ + if (ov->snap_enabled && frame->snapshot) { + frame->snapshot = 0; + ov51x_clear_snapshot(ov); + } + + /* Decompression, format conversion, etc... */ + ov51x_postprocess(ov, frame); + + PDEBUG(4, "frmx=%d, bytes_read=%ld, length=%ld", frmx, + frame->bytes_read, + get_frame_length(frame)); + + /* copy bytes to user space; we allow for partials reads */ +// if ((count + frame->bytes_read) +// > get_frame_length((struct ov511_frame *)frame)) +// count = frame->scanlength - frame->bytes_read; + + /* FIXME - count hardwired to be one frame... */ + count = get_frame_length(frame); + + PDEBUG(4, "Copy to user space: %ld bytes", count); + if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) { + PDEBUG(4, "Copy failed! %d bytes not copied", i); + rc = -EFAULT; + goto error; + } + + frame->bytes_read += count; + PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld", + count, frame->bytes_read); + + /* If all data have been read... */ + if (frame->bytes_read + >= get_frame_length(frame)) { + frame->bytes_read = 0; + +// FIXME: Only supports two frames + /* Mark it as available to be used again. */ + ov->frame[frmx].grabstate = FRAME_UNUSED; + if ((rc = ov51x_new_frame(ov, !frmx))) { + err("ov51x_new_frame returned error"); + goto error; + } + } + + PDEBUG(4, "read finished, returning %ld (sweet)", count); + + mutex_unlock(&ov->lock); + return count; + +error: + mutex_unlock(&ov->lock); + return rc; +} + +static int +ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct video_device *vdev = file->private_data; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end - vma->vm_start; + struct usb_ov511 *ov = video_get_drvdata(vdev); + unsigned long page, pos; + + if (ov->dev == NULL) + return -EIO; + + PDEBUG(4, "mmap: %ld (%lX) bytes", size, size); + + if (size > (((OV511_NUMFRAMES + * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight) + + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))) + return -EINVAL; + + if (mutex_lock_interruptible(&ov->lock)) + return -EINTR; + + pos = (unsigned long)ov->fbuf; + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { + mutex_unlock(&ov->lock); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + mutex_unlock(&ov->lock); + return 0; +} + +static struct file_operations ov511_fops = { + .owner = THIS_MODULE, + .open = ov51x_v4l1_open, + .release = ov51x_v4l1_close, + .read = ov51x_v4l1_read, + .mmap = ov51x_v4l1_mmap, + .ioctl = ov51x_v4l1_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .llseek = no_llseek, +}; + +static struct video_device vdev_template = { + .owner = THIS_MODULE, + .name = "OV511 USB Camera", + .type = VID_TYPE_CAPTURE, + .hardware = VID_HARDWARE_OV511, + .fops = &ov511_fops, + .release = video_device_release, + .minor = -1, +}; + +/**************************************************************************** + * + * OV511 and sensor configuration + * + ***************************************************************************/ + +/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses + * the same register settings as the OV7610, since they are very similar. + */ +static int +ov7xx0_configure(struct usb_ov511 *ov) +{ + int i, success; + int rc; + + /* Lawrence Glaister reports: + * + * Register 0x0f in the 7610 has the following effects: + * + * 0x85 (AEC method 1): Best overall, good contrast range + * 0x45 (AEC method 2): Very overexposed + * 0xa5 (spec sheet default): Ok, but the black level is + * shifted resulting in loss of contrast + * 0x05 (old driver setting): very overexposed, too much + * contrast + */ + static struct ov511_regvals aRegvalsNorm7610[] = { + { OV511_I2C_BUS, 0x10, 0xff }, + { OV511_I2C_BUS, 0x16, 0x06 }, + { OV511_I2C_BUS, 0x28, 0x24 }, + { OV511_I2C_BUS, 0x2b, 0xac }, + { OV511_I2C_BUS, 0x12, 0x00 }, + { OV511_I2C_BUS, 0x38, 0x81 }, + { OV511_I2C_BUS, 0x28, 0x24 }, /* 0c */ + { OV511_I2C_BUS, 0x0f, 0x85 }, /* lg's setting */ + { OV511_I2C_BUS, 0x15, 0x01 }, + { OV511_I2C_BUS, 0x20, 0x1c }, + { OV511_I2C_BUS, 0x23, 0x2a }, + { OV511_I2C_BUS, 0x24, 0x10 }, + { OV511_I2C_BUS, 0x25, 0x8a }, + { OV511_I2C_BUS, 0x26, 0xa2 }, + { OV511_I2C_BUS, 0x27, 0xc2 }, + { OV511_I2C_BUS, 0x2a, 0x04 }, + { OV511_I2C_BUS, 0x2c, 0xfe }, + { OV511_I2C_BUS, 0x2d, 0x93 }, + { OV511_I2C_BUS, 0x30, 0x71 }, + { OV511_I2C_BUS, 0x31, 0x60 }, + { OV511_I2C_BUS, 0x32, 0x26 }, + { OV511_I2C_BUS, 0x33, 0x20 }, + { OV511_I2C_BUS, 0x34, 0x48 }, + { OV511_I2C_BUS, 0x12, 0x24 }, + { OV511_I2C_BUS, 0x11, 0x01 }, + { OV511_I2C_BUS, 0x0c, 0x24 }, + { OV511_I2C_BUS, 0x0d, 0x24 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + static struct ov511_regvals aRegvalsNorm7620[] = { + { OV511_I2C_BUS, 0x00, 0x00 }, + { OV511_I2C_BUS, 0x01, 0x80 }, + { OV511_I2C_BUS, 0x02, 0x80 }, + { OV511_I2C_BUS, 0x03, 0xc0 }, + { OV511_I2C_BUS, 0x06, 0x60 }, + { OV511_I2C_BUS, 0x07, 0x00 }, + { OV511_I2C_BUS, 0x0c, 0x24 }, + { OV511_I2C_BUS, 0x0c, 0x24 }, + { OV511_I2C_BUS, 0x0d, 0x24 }, + { OV511_I2C_BUS, 0x11, 0x01 }, + { OV511_I2C_BUS, 0x12, 0x24 }, + { OV511_I2C_BUS, 0x13, 0x01 }, + { OV511_I2C_BUS, 0x14, 0x84 }, + { OV511_I2C_BUS, 0x15, 0x01 }, + { OV511_I2C_BUS, 0x16, 0x03 }, + { OV511_I2C_BUS, 0x17, 0x2f }, + { OV511_I2C_BUS, 0x18, 0xcf }, + { OV511_I2C_BUS, 0x19, 0x06 }, + { OV511_I2C_BUS, 0x1a, 0xf5 }, + { OV511_I2C_BUS, 0x1b, 0x00 }, + { OV511_I2C_BUS, 0x20, 0x18 }, + { OV511_I2C_BUS, 0x21, 0x80 }, + { OV511_I2C_BUS, 0x22, 0x80 }, + { OV511_I2C_BUS, 0x23, 0x00 }, + { OV511_I2C_BUS, 0x26, 0xa2 }, + { OV511_I2C_BUS, 0x27, 0xea }, + { OV511_I2C_BUS, 0x28, 0x20 }, + { OV511_I2C_BUS, 0x29, 0x00 }, + { OV511_I2C_BUS, 0x2a, 0x10 }, + { OV511_I2C_BUS, 0x2b, 0x00 }, + { OV511_I2C_BUS, 0x2c, 0x88 }, + { OV511_I2C_BUS, 0x2d, 0x91 }, + { OV511_I2C_BUS, 0x2e, 0x80 }, + { OV511_I2C_BUS, 0x2f, 0x44 }, + { OV511_I2C_BUS, 0x60, 0x27 }, + { OV511_I2C_BUS, 0x61, 0x02 }, + { OV511_I2C_BUS, 0x62, 0x5f }, + { OV511_I2C_BUS, 0x63, 0xd5 }, + { OV511_I2C_BUS, 0x64, 0x57 }, + { OV511_I2C_BUS, 0x65, 0x83 }, + { OV511_I2C_BUS, 0x66, 0x55 }, + { OV511_I2C_BUS, 0x67, 0x92 }, + { OV511_I2C_BUS, 0x68, 0xcf }, + { OV511_I2C_BUS, 0x69, 0x76 }, + { OV511_I2C_BUS, 0x6a, 0x22 }, + { OV511_I2C_BUS, 0x6b, 0x00 }, + { OV511_I2C_BUS, 0x6c, 0x02 }, + { OV511_I2C_BUS, 0x6d, 0x44 }, + { OV511_I2C_BUS, 0x6e, 0x80 }, + { OV511_I2C_BUS, 0x6f, 0x1d }, + { OV511_I2C_BUS, 0x70, 0x8b }, + { OV511_I2C_BUS, 0x71, 0x00 }, + { OV511_I2C_BUS, 0x72, 0x14 }, + { OV511_I2C_BUS, 0x73, 0x54 }, + { OV511_I2C_BUS, 0x74, 0x00 }, + { OV511_I2C_BUS, 0x75, 0x8e }, + { OV511_I2C_BUS, 0x76, 0x00 }, + { OV511_I2C_BUS, 0x77, 0xff }, + { OV511_I2C_BUS, 0x78, 0x80 }, + { OV511_I2C_BUS, 0x79, 0x80 }, + { OV511_I2C_BUS, 0x7a, 0x80 }, + { OV511_I2C_BUS, 0x7b, 0xe2 }, + { OV511_I2C_BUS, 0x7c, 0x00 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + PDEBUG(4, "starting configuration"); + + /* This looks redundant, but is necessary for WebCam 3 */ + ov->primary_i2c_slave = OV7xx0_SID; + if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) + return -1; + + if (init_ov_sensor(ov) >= 0) { + PDEBUG(1, "OV7xx0 sensor initalized (method 1)"); + } else { + /* Reset the 76xx */ + if (i2c_w(ov, 0x12, 0x80) < 0) + return -1; + + /* Wait for it to initialize */ + msleep(150); + + i = 0; + success = 0; + while (i <= i2c_detect_tries) { + if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) && + (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) { + success = 1; + break; + } else { + i++; + } + } + +// Was (i == i2c_detect_tries) previously. This obviously used to always report +// success. Whether anyone actually depended on that bug is unknown + if ((i >= i2c_detect_tries) && (success == 0)) { + err("Failed to read sensor ID. You might not have an"); + err("OV7610/20, or it may be not responding. Report"); + err("this to " EMAIL); + err("This is only a warning. You can attempt to use"); + err("your camera anyway"); +// Only issue a warning for now +// return -1; + } else { + PDEBUG(1, "OV7xx0 initialized (method 2, %dx)", i+1); + } + } + + /* Detect sensor (sub)type */ + rc = i2c_r(ov, OV7610_REG_COM_I); + + if (rc < 0) { + err("Error detecting sensor type"); + return -1; + } else if ((rc & 3) == 3) { + info("Sensor is an OV7610"); + ov->sensor = SEN_OV7610; + } else if ((rc & 3) == 1) { + /* I don't know what's different about the 76BE yet. */ + if (i2c_r(ov, 0x15) & 1) + info("Sensor is an OV7620AE"); + else + info("Sensor is an OV76BE"); + + /* OV511+ will return all zero isoc data unless we + * configure the sensor as a 7620. Someone needs to + * find the exact reg. setting that causes this. */ + if (ov->bridge == BRG_OV511PLUS) { + info("Enabling 511+/7620AE workaround"); + ov->sensor = SEN_OV7620; + } else { + ov->sensor = SEN_OV76BE; + } + } else if ((rc & 3) == 0) { + info("Sensor is an OV7620"); + ov->sensor = SEN_OV7620; + } else { + err("Unknown image sensor version: %d", rc & 3); + return -1; + } + + if (ov->sensor == SEN_OV7620) { + PDEBUG(4, "Writing 7620 registers"); + if (write_regvals(ov, aRegvalsNorm7620)) + return -1; + } else { + PDEBUG(4, "Writing 7610 registers"); + if (write_regvals(ov, aRegvalsNorm7610)) + return -1; + } + + /* Set sensor-specific vars */ + ov->maxwidth = 640; + ov->maxheight = 480; + ov->minwidth = 64; + ov->minheight = 48; + + // FIXME: These do not match the actual settings yet + ov->brightness = 0x80 << 8; + ov->contrast = 0x80 << 8; + ov->colour = 0x80 << 8; + ov->hue = 0x80 << 8; + + return 0; +} + +/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */ +static int +ov6xx0_configure(struct usb_ov511 *ov) +{ + int rc; + + static struct ov511_regvals aRegvalsNorm6x20[] = { + { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */ + { OV511_I2C_BUS, 0x11, 0x01 }, + { OV511_I2C_BUS, 0x03, 0x60 }, + { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */ + { OV511_I2C_BUS, 0x07, 0xa8 }, + /* The ratio of 0x0c and 0x0d controls the white point */ + { OV511_I2C_BUS, 0x0c, 0x24 }, + { OV511_I2C_BUS, 0x0d, 0x24 }, + { OV511_I2C_BUS, 0x0f, 0x15 }, /* COMS */ + { OV511_I2C_BUS, 0x10, 0x75 }, /* AEC Exposure time */ + { OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */ + { OV511_I2C_BUS, 0x14, 0x04 }, + /* 0x16: 0x06 helps frame stability with moving objects */ + { OV511_I2C_BUS, 0x16, 0x06 }, +// { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */ + { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */ + /* 0x28: 0x05 Selects RGB format if RGB on */ + { OV511_I2C_BUS, 0x28, 0x05 }, + { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */ +// { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */ + { OV511_I2C_BUS, 0x2d, 0x99 }, + { OV511_I2C_BUS, 0x33, 0xa0 }, /* Color Processing Parameter */ + { OV511_I2C_BUS, 0x34, 0xd2 }, /* Max A/D range */ + { OV511_I2C_BUS, 0x38, 0x8b }, + { OV511_I2C_BUS, 0x39, 0x40 }, + + { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */ + { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */ + { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */ + + { OV511_I2C_BUS, 0x3d, 0x80 }, + /* These next two registers (0x4a, 0x4b) are undocumented. They + * control the color balance */ + { OV511_I2C_BUS, 0x4a, 0x80 }, + { OV511_I2C_BUS, 0x4b, 0x80 }, + { OV511_I2C_BUS, 0x4d, 0xd2 }, /* This reduces noise a bit */ + { OV511_I2C_BUS, 0x4e, 0xc1 }, + { OV511_I2C_BUS, 0x4f, 0x04 }, +// Do 50-53 have any effect? +// Toggle 0x12[2] off and on here? + { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ + }; + + static struct ov511_regvals aRegvalsNorm6x30[] = { + /*OK*/ { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */ + { OV511_I2C_BUS, 0x11, 0x00 }, + /*OK*/ { OV511_I2C_BUS, 0x03, 0x60 }, + /*0A?*/ { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */ + { OV511_I2C_BUS, 0x07, 0xa8 }, + /* The ratio of 0x0c and 0x0d controls the white point */ + /*OK*/ { OV511_I2C_BUS, 0x0c, 0x24 }, + /*OK*/ { OV511_I2C_BUS, 0x0d, 0x24 }, + /*A*/ { OV511_I2C_BUS, 0x0e, 0x20 }, +// /*04?*/ { OV511_I2C_BUS, 0x14, 0x80 }, + { OV511_I2C_BUS, 0x16, 0x03 }, +// /*OK*/ { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */ + // 21 & 22? The suggested values look wrong. Go with default + /*A*/ { OV511_I2C_BUS, 0x23, 0xc0 }, + /*A*/ { OV511_I2C_BUS, 0x25, 0x9a }, // Check this against default +// /*OK*/ { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */ + + /* 0x28: 0x05 Selects RGB format if RGB on */ +// /*04?*/ { OV511_I2C_BUS, 0x28, 0x05 }, +// /*04?*/ { OV511_I2C_BUS, 0x28, 0x45 }, // DEBUG: Tristate UV bus + + /*OK*/ { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */ +// /*OK*/ { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */ + { OV511_I2C_BUS, 0x2d, 0x99 }, +// /*A*/ { OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620 +// /*d2?*/ { OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */ +// /*8b?*/ { OV511_I2C_BUS, 0x38, 0x83 }, +// /*40?*/ { OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7 +// { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */ +// { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */ +// { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */ + { OV511_I2C_BUS, 0x3d, 0x80 }, +// /*A*/ { OV511_I2C_BUS, 0x3f, 0x0e }, + + /* These next two registers (0x4a, 0x4b) are undocumented. They + * control the color balance */ +// /*OK?*/ { OV511_I2C_BUS, 0x4a, 0x80 }, // Check these +// /*OK?*/ { OV511_I2C_BUS, 0x4b, 0x80 }, + { OV511_I2C_BUS, 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ + /*c1?*/ { OV511_I2C_BUS, 0x4e, 0x40 }, + + /* UV average mode, color killer: strongest */ + { OV511_I2C_BUS, 0x4f, 0x07 }, + + { OV511_I2C_BUS, 0x54, 0x23 }, /* Max AGC gain: 18dB */ + { OV511_I2C_BUS, 0x57, 0x81 }, /* (default) */ + { OV511_I2C_BUS, 0x59, 0x01 }, /* AGC dark current comp: +1 */ + { OV511_I2C_BUS, 0x5a, 0x2c }, /* (undocumented) */ + { OV511_I2C_BUS, 0x5b, 0x0f }, /* AWB chrominance levels */ +// { OV511_I2C_BUS, 0x5c, 0x10 }, + { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ + }; + + PDEBUG(4, "starting sensor configuration"); + + if (init_ov_sensor(ov) < 0) { + err("Failed to read sensor ID. You might not have an OV6xx0,"); + err("or it may be not responding. Report this to " EMAIL); + return -1; + } else { + PDEBUG(1, "OV6xx0 sensor detected"); + } + + /* Detect sensor (sub)type */ + rc = i2c_r(ov, OV7610_REG_COM_I); + + if (rc < 0) { + err("Error detecting sensor type"); + return -1; + } + + if ((rc & 3) == 0) { + ov->sensor = SEN_OV6630; + info("Sensor is an OV6630"); + } else if ((rc & 3) == 1) { + ov->sensor = SEN_OV6620; + info("Sensor is an OV6620"); + } else if ((rc & 3) == 2) { + ov->sensor = SEN_OV6630; + info("Sensor is an OV6630AE"); + } else if ((rc & 3) == 3) { + ov->sensor = SEN_OV6630; + info("Sensor is an OV6630AF"); + } + + /* Set sensor-specific vars */ + ov->maxwidth = 352; + ov->maxheight = 288; + ov->minwidth = 64; + ov->minheight = 48; + + // FIXME: These do not match the actual settings yet + ov->brightness = 0x80 << 8; + ov->contrast = 0x80 << 8; + ov->colour = 0x80 << 8; + ov->hue = 0x80 << 8; + + if (ov->sensor == SEN_OV6620) { + PDEBUG(4, "Writing 6x20 registers"); + if (write_regvals(ov, aRegvalsNorm6x20)) + return -1; + } else { + PDEBUG(4, "Writing 6x30 registers"); + if (write_regvals(ov, aRegvalsNorm6x30)) + return -1; + } + + return 0; +} + +/* This initializes the KS0127 and KS0127B video decoders. */ +static int +ks0127_configure(struct usb_ov511 *ov) +{ + int rc; + +// FIXME: I don't know how to sync or reset it yet +#if 0 + if (ov51x_init_ks_sensor(ov) < 0) { + err("Failed to initialize the KS0127"); + return -1; + } else { + PDEBUG(1, "KS012x(B) sensor detected"); + } +#endif + + /* Detect decoder subtype */ + rc = i2c_r(ov, 0x00); + if (rc < 0) { + err("Error detecting sensor type"); + return -1; + } else if (rc & 0x08) { + rc = i2c_r(ov, 0x3d); + if (rc < 0) { + err("Error detecting sensor type"); + return -1; + } else if ((rc & 0x0f) == 0) { + info("Sensor is a KS0127"); + ov->sensor = SEN_KS0127; + } else if ((rc & 0x0f) == 9) { + info("Sensor is a KS0127B Rev. A"); + ov->sensor = SEN_KS0127B; + } + } else { + err("Error: Sensor is an unsupported KS0122"); + return -1; + } + + /* Set sensor-specific vars */ + ov->maxwidth = 640; + ov->maxheight = 480; + ov->minwidth = 64; + ov->minheight = 48; + + // FIXME: These do not match the actual settings yet + ov->brightness = 0x80 << 8; + ov->contrast = 0x80 << 8; + ov->colour = 0x80 << 8; + ov->hue = 0x80 << 8; + + /* This device is not supported yet. Bail out now... */ + err("This sensor is not supported yet."); + return -1; + + return 0; +} + +/* This initializes the SAA7111A video decoder. */ +static int +saa7111a_configure(struct usb_ov511 *ov) +{ + int rc; + + /* Since there is no register reset command, all registers must be + * written, otherwise gives erratic results */ + static struct ov511_regvals aRegvalsNormSAA7111A[] = { + { OV511_I2C_BUS, 0x06, 0xce }, + { OV511_I2C_BUS, 0x07, 0x00 }, + { OV511_I2C_BUS, 0x10, 0x44 }, /* YUV422, 240/286 lines */ + { OV511_I2C_BUS, 0x0e, 0x01 }, /* NTSC M or PAL BGHI */ + { OV511_I2C_BUS, 0x00, 0x00 }, + { OV511_I2C_BUS, 0x01, 0x00 }, + { OV511_I2C_BUS, 0x03, 0x23 }, + { OV511_I2C_BUS, 0x04, 0x00 }, + { OV511_I2C_BUS, 0x05, 0x00 }, + { OV511_I2C_BUS, 0x08, 0xc8 }, /* Auto field freq */ + { OV511_I2C_BUS, 0x09, 0x01 }, /* Chrom. trap off, APER=0.25 */ + { OV511_I2C_BUS, 0x0a, 0x80 }, /* BRIG=128 */ + { OV511_I2C_BUS, 0x0b, 0x40 }, /* CONT=1.0 */ + { OV511_I2C_BUS, 0x0c, 0x40 }, /* SATN=1.0 */ + { OV511_I2C_BUS, 0x0d, 0x00 }, /* HUE=0 */ + { OV511_I2C_BUS, 0x0f, 0x00 }, + { OV511_I2C_BUS, 0x11, 0x0c }, + { OV511_I2C_BUS, 0x12, 0x00 }, + { OV511_I2C_BUS, 0x13, 0x00 }, + { OV511_I2C_BUS, 0x14, 0x00 }, + { OV511_I2C_BUS, 0x15, 0x00 }, + { OV511_I2C_BUS, 0x16, 0x00 }, + { OV511_I2C_BUS, 0x17, 0x00 }, + { OV511_I2C_BUS, 0x02, 0xc0 }, /* Composite input 0 */ + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + +// FIXME: I don't know how to sync or reset it yet +#if 0 + if (ov51x_init_saa_sensor(ov) < 0) { + err("Failed to initialize the SAA7111A"); + return -1; + } else { + PDEBUG(1, "SAA7111A sensor detected"); + } +#endif + + /* 640x480 not supported with PAL */ + if (ov->pal) { + ov->maxwidth = 320; + ov->maxheight = 240; /* Even field only */ + } else { + ov->maxwidth = 640; + ov->maxheight = 480; /* Even/Odd fields */ + } + + ov->minwidth = 320; + ov->minheight = 240; /* Even field only */ + + ov->has_decoder = 1; + ov->num_inputs = 8; + ov->norm = VIDEO_MODE_AUTO; + ov->stop_during_set = 0; /* Decoder guarantees stable image */ + + /* Decoder doesn't change these values, so we use these instead of + * acutally reading the registers (which doesn't work) */ + ov->brightness = 0x80 << 8; + ov->contrast = 0x40 << 9; + ov->colour = 0x40 << 9; + ov->hue = 32768; + + PDEBUG(4, "Writing SAA7111A registers"); + if (write_regvals(ov, aRegvalsNormSAA7111A)) + return -1; + + /* Detect version of decoder. This must be done after writing the + * initial regs or the decoder will lock up. */ + rc = i2c_r(ov, 0x00); + + if (rc < 0) { + err("Error detecting sensor version"); + return -1; + } else { + info("Sensor is an SAA7111A (version 0x%x)", rc); + ov->sensor = SEN_SAA7111A; + } + + // FIXME: Fix this for OV518(+) + /* Latch to negative edge of clock. Otherwise, we get incorrect + * colors and jitter in the digital signal. */ + if (ov->bclass == BCL_OV511) + reg_w(ov, 0x11, 0x00); + else + warn("SAA7111A not yet supported with OV518/OV518+"); + + return 0; +} + +/* This initializes the OV511/OV511+ and the sensor */ +static int +ov511_configure(struct usb_ov511 *ov) +{ + static struct ov511_regvals aRegvalsInit511[] = { + { OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, + { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, + { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x3f }, + { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x3d }, + { OV511_DONE_BUS, 0x0, 0x00}, + }; + + static struct ov511_regvals aRegvalsNorm511[] = { + { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0x01 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, + { OV511_REG_BUS, R511_FIFO_OPTS, 0x1f }, + { OV511_REG_BUS, R511_COMP_EN, 0x00 }, + { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + static struct ov511_regvals aRegvalsNorm511Plus[] = { + { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0xff }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, + { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, + { OV511_REG_BUS, R511_FIFO_OPTS, 0xff }, + { OV511_REG_BUS, R511_COMP_EN, 0x00 }, + { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + PDEBUG(4, ""); + + ov->customid = reg_r(ov, R511_SYS_CUST_ID); + if (ov->customid < 0) { + err("Unable to read camera bridge registers"); + goto error; + } + + PDEBUG (1, "CustomID = %d", ov->customid); + ov->desc = symbolic(camlist, ov->customid); + info("model: %s", ov->desc); + + if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) { + err("Camera type (%d) not recognized", ov->customid); + err("Please notify " EMAIL " of the name,"); + err("manufacturer, model, and this number of your camera."); + err("Also include the output of the detection process."); + } + + if (ov->customid == 70) /* USB Life TV (PAL/SECAM) */ + ov->pal = 1; + + if (write_regvals(ov, aRegvalsInit511)) + goto error; + + if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO) + ov51x_led_control(ov, 0); + + /* The OV511+ has undocumented bits in the flow control register. + * Setting it to 0xff fixes the corruption with moving objects. */ + if (ov->bridge == BRG_OV511) { + if (write_regvals(ov, aRegvalsNorm511)) + goto error; + } else if (ov->bridge == BRG_OV511PLUS) { + if (write_regvals(ov, aRegvalsNorm511Plus)) + goto error; + } else { + err("Invalid bridge"); + } + + if (ov511_init_compression(ov)) + goto error; + + ov->packet_numbering = 1; + ov511_set_packet_size(ov, 0); + + ov->snap_enabled = snapshot; + + /* Test for 7xx0 */ + PDEBUG(3, "Testing for 0V7xx0"); + ov->primary_i2c_slave = OV7xx0_SID; + if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) + goto error; + + if (i2c_w(ov, 0x12, 0x80) < 0) { + /* Test for 6xx0 */ + PDEBUG(3, "Testing for 0V6xx0"); + ov->primary_i2c_slave = OV6xx0_SID; + if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0) + goto error; + + if (i2c_w(ov, 0x12, 0x80) < 0) { + /* Test for 8xx0 */ + PDEBUG(3, "Testing for 0V8xx0"); + ov->primary_i2c_slave = OV8xx0_SID; + if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0) + goto error; + + if (i2c_w(ov, 0x12, 0x80) < 0) { + /* Test for SAA7111A */ + PDEBUG(3, "Testing for SAA7111A"); + ov->primary_i2c_slave = SAA7111A_SID; + if (ov51x_set_slave_ids(ov, SAA7111A_SID) < 0) + goto error; + + if (i2c_w(ov, 0x0d, 0x00) < 0) { + /* Test for KS0127 */ + PDEBUG(3, "Testing for KS0127"); + ov->primary_i2c_slave = KS0127_SID; + if (ov51x_set_slave_ids(ov, KS0127_SID) < 0) + goto error; + + if (i2c_w(ov, 0x10, 0x00) < 0) { + err("Can't determine sensor slave IDs"); + goto error; + } else { + if (ks0127_configure(ov) < 0) { + err("Failed to configure KS0127"); + goto error; + } + } + } else { + if (saa7111a_configure(ov) < 0) { + err("Failed to configure SAA7111A"); + goto error; + } + } + } else { + err("Detected unsupported OV8xx0 sensor"); + goto error; + } + } else { + if (ov6xx0_configure(ov) < 0) { + err("Failed to configure OV6xx0"); + goto error; + } + } + } else { + if (ov7xx0_configure(ov) < 0) { + err("Failed to configure OV7xx0"); + goto error; + } + } + + return 0; + +error: + err("OV511 Config failed"); + + return -EBUSY; +} + +/* This initializes the OV518/OV518+ and the sensor */ +static int +ov518_configure(struct usb_ov511 *ov) +{ + /* For 518 and 518+ */ + static struct ov511_regvals aRegvalsInit518[] = { + { OV511_REG_BUS, R51x_SYS_RESET, 0x40 }, + { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x3e }, + { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x00 }, + { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, + { OV511_REG_BUS, 0x46, 0x00 }, + { OV511_REG_BUS, 0x5d, 0x03 }, + { OV511_DONE_BUS, 0x0, 0x00}, + }; + + static struct ov511_regvals aRegvalsNorm518[] = { + { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */ + { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */ + { OV511_REG_BUS, 0x31, 0x0f }, + { OV511_REG_BUS, 0x5d, 0x03 }, + { OV511_REG_BUS, 0x24, 0x9f }, + { OV511_REG_BUS, 0x25, 0x90 }, + { OV511_REG_BUS, 0x20, 0x00 }, + { OV511_REG_BUS, 0x51, 0x04 }, + { OV511_REG_BUS, 0x71, 0x19 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + static struct ov511_regvals aRegvalsNorm518Plus[] = { + { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */ + { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */ + { OV511_REG_BUS, 0x31, 0x0f }, + { OV511_REG_BUS, 0x5d, 0x03 }, + { OV511_REG_BUS, 0x24, 0x9f }, + { OV511_REG_BUS, 0x25, 0x90 }, + { OV511_REG_BUS, 0x20, 0x60 }, + { OV511_REG_BUS, 0x51, 0x02 }, + { OV511_REG_BUS, 0x71, 0x19 }, + { OV511_REG_BUS, 0x40, 0xff }, + { OV511_REG_BUS, 0x41, 0x42 }, + { OV511_REG_BUS, 0x46, 0x00 }, + { OV511_REG_BUS, 0x33, 0x04 }, + { OV511_REG_BUS, 0x21, 0x19 }, + { OV511_REG_BUS, 0x3f, 0x10 }, + { OV511_DONE_BUS, 0x0, 0x00 }, + }; + + PDEBUG(4, ""); + + /* First 5 bits of custom ID reg are a revision ID on OV518 */ + info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID)); + + /* Give it the default description */ + ov->desc = symbolic(camlist, 0); + + if (write_regvals(ov, aRegvalsInit518)) + goto error; + + /* Set LED GPIO pin to output mode */ + if (reg_w_mask(ov, 0x57, 0x00, 0x02) < 0) + goto error; + + /* LED is off by default with OV518; have to explicitly turn it on */ + if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO) + ov51x_led_control(ov, 0); + else + ov51x_led_control(ov, 1); + + /* Don't require compression if dumppix is enabled; otherwise it's + * required. OV518 has no uncompressed mode, to save RAM. */ + if (!dumppix && !ov->compress) { + ov->compress = 1; + warn("Compression required with OV518...enabling"); + } + + if (ov->bridge == BRG_OV518) { + if (write_regvals(ov, aRegvalsNorm518)) + goto error; + } else if (ov->bridge == BRG_OV518PLUS) { + if (write_regvals(ov, aRegvalsNorm518Plus)) + goto error; + } else { + err("Invalid bridge"); + } + + if (reg_w(ov, 0x2f, 0x80) < 0) + goto error; + + if (ov518_init_compression(ov)) + goto error; + + if (ov->bridge == BRG_OV518) + { + struct usb_interface *ifp; + struct usb_host_interface *alt; + __u16 mxps = 0; + + ifp = usb_ifnum_to_if(ov->dev, 0); + if (ifp) { + alt = usb_altnum_to_altsetting(ifp, 7); + if (alt) + mxps = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + } + + /* Some OV518s have packet numbering by default, some don't */ + if (mxps == 897) + ov->packet_numbering = 1; + else + ov->packet_numbering = 0; + } else { + /* OV518+ has packet numbering turned on by default */ + ov->packet_numbering = 1; + } + + ov518_set_packet_size(ov, 0); + + ov->snap_enabled = snapshot; + + /* Test for 76xx */ + ov->primary_i2c_slave = OV7xx0_SID; + if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) + goto error; + + /* The OV518 must be more aggressive about sensor detection since + * I2C write will never fail if the sensor is not present. We have + * to try to initialize the sensor to detect its presence */ + + if (init_ov_sensor(ov) < 0) { + /* Test for 6xx0 */ + ov->primary_i2c_slave = OV6xx0_SID; + if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0) + goto error; + + if (init_ov_sensor(ov) < 0) { + /* Test for 8xx0 */ + ov->primary_i2c_slave = OV8xx0_SID; + if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0) + goto error; + + if (init_ov_sensor(ov) < 0) { + err("Can't determine sensor slave IDs"); + goto error; + } else { + err("Detected unsupported OV8xx0 sensor"); + goto error; + } + } else { + if (ov6xx0_configure(ov) < 0) { + err("Failed to configure OV6xx0"); + goto error; + } + } + } else { + if (ov7xx0_configure(ov) < 0) { + err("Failed to configure OV7xx0"); + goto error; + } + } + + ov->maxwidth = 352; + ov->maxheight = 288; + + // The OV518 cannot go as low as the sensor can + ov->minwidth = 160; + ov->minheight = 120; + + return 0; + +error: + err("OV518 Config failed"); + + return -EBUSY; +} + +/**************************************************************************** + * sysfs + ***************************************************************************/ + +static inline struct usb_ov511 *cd_to_ov(struct class_device *cd) +{ + struct video_device *vdev = to_video_device(cd); + return video_get_drvdata(vdev); +} + +static ssize_t show_custom_id(struct class_device *cd, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + return sprintf(buf, "%d\n", ov->customid); +} +static CLASS_DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL); + +static ssize_t show_model(struct class_device *cd, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + return sprintf(buf, "%s\n", ov->desc); +} +static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); + +static ssize_t show_bridge(struct class_device *cd, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + return sprintf(buf, "%s\n", symbolic(brglist, ov->bridge)); +} +static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL); + +static ssize_t show_sensor(struct class_device *cd, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + return sprintf(buf, "%s\n", symbolic(senlist, ov->sensor)); +} +static CLASS_DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL); + +static ssize_t show_brightness(struct class_device *cd, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + unsigned short x; + + if (!ov->dev) + return -ENODEV; + sensor_get_brightness(ov, &x); + return sprintf(buf, "%d\n", x >> 8); +} +static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); + +static ssize_t show_saturation(struct class_device *cd, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + unsigned short x; + + if (!ov->dev) + return -ENODEV; + sensor_get_saturation(ov, &x); + return sprintf(buf, "%d\n", x >> 8); +} +static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); + +static ssize_t show_contrast(struct class_device *cd, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + unsigned short x; + + if (!ov->dev) + return -ENODEV; + sensor_get_contrast(ov, &x); + return sprintf(buf, "%d\n", x >> 8); +} +static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); + +static ssize_t show_hue(struct class_device *cd, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + unsigned short x; + + if (!ov->dev) + return -ENODEV; + sensor_get_hue(ov, &x); + return sprintf(buf, "%d\n", x >> 8); +} +static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); + +static ssize_t show_exposure(struct class_device *cd, char *buf) +{ + struct usb_ov511 *ov = cd_to_ov(cd); + unsigned char exp = 0; + + if (!ov->dev) + return -ENODEV; + sensor_get_exposure(ov, &exp); + return sprintf(buf, "%d\n", exp >> 8); +} +static CLASS_DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL); + +static void ov_create_sysfs(struct video_device *vdev) +{ + video_device_create_file(vdev, &class_device_attr_custom_id); + video_device_create_file(vdev, &class_device_attr_model); + video_device_create_file(vdev, &class_device_attr_bridge); + video_device_create_file(vdev, &class_device_attr_sensor); + video_device_create_file(vdev, &class_device_attr_brightness); + video_device_create_file(vdev, &class_device_attr_saturation); + video_device_create_file(vdev, &class_device_attr_contrast); + video_device_create_file(vdev, &class_device_attr_hue); + video_device_create_file(vdev, &class_device_attr_exposure); +} + +/**************************************************************************** + * USB routines + ***************************************************************************/ + +static int +ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_interface_descriptor *idesc; + struct usb_ov511 *ov; + int i; + + PDEBUG(1, "probing for device..."); + + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + idesc = &intf->cur_altsetting->desc; + + if (idesc->bInterfaceClass != 0xFF) + return -ENODEV; + if (idesc->bInterfaceSubClass != 0x00) + return -ENODEV; + + if ((ov = kzalloc(sizeof(*ov), GFP_KERNEL)) == NULL) { + err("couldn't kmalloc ov struct"); + goto error_out; + } + + ov->dev = dev; + ov->iface = idesc->bInterfaceNumber; + ov->led_policy = led; + ov->compress = compress; + ov->lightfreq = lightfreq; + ov->num_inputs = 1; /* Video decoder init functs. change this */ + ov->stop_during_set = !fastset; + ov->backlight = backlight; + ov->mirror = mirror; + ov->auto_brt = autobright; + ov->auto_gain = autogain; + ov->auto_exp = autoexp; + + switch (le16_to_cpu(dev->descriptor.idProduct)) { + case PROD_OV511: + ov->bridge = BRG_OV511; + ov->bclass = BCL_OV511; + break; + case PROD_OV511PLUS: + ov->bridge = BRG_OV511PLUS; + ov->bclass = BCL_OV511; + break; + case PROD_OV518: + ov->bridge = BRG_OV518; + ov->bclass = BCL_OV518; + break; + case PROD_OV518PLUS: + ov->bridge = BRG_OV518PLUS; + ov->bclass = BCL_OV518; + break; + case PROD_ME2CAM: + if (le16_to_cpu(dev->descriptor.idVendor) != VEND_MATTEL) + goto error; + ov->bridge = BRG_OV511PLUS; + ov->bclass = BCL_OV511; + break; + default: + err("Unknown product ID 0x%04x", le16_to_cpu(dev->descriptor.idProduct)); + goto error; + } + + info("USB %s video device found", symbolic(brglist, ov->bridge)); + + init_waitqueue_head(&ov->wq); + + mutex_init(&ov->lock); /* to 1 == available */ + mutex_init(&ov->buf_lock); + mutex_init(&ov->i2c_lock); + mutex_init(&ov->cbuf_lock); + + ov->buf_state = BUF_NOT_ALLOCATED; + + if (usb_make_path(dev, ov->usb_path, OV511_USB_PATH_LEN) < 0) { + err("usb_make_path error"); + goto error; + } + + /* Allocate control transfer buffer. */ + /* Must be kmalloc()'ed, for DMA compatibility */ + ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL); + if (!ov->cbuf) + goto error; + + if (ov->bclass == BCL_OV518) { + if (ov518_configure(ov) < 0) + goto error; + } else { + if (ov511_configure(ov) < 0) + goto error; + } + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov->frame[i].framenum = i; + init_waitqueue_head(&ov->frame[i].wq); + } + + for (i = 0; i < OV511_NUMSBUF; i++) { + ov->sbuf[i].ov = ov; + spin_lock_init(&ov->sbuf[i].lock); + ov->sbuf[i].n = i; + } + + /* Unnecessary? (This is done on open(). Need to make sure variables + * are properly initialized without this before removing it, though). */ + if (ov51x_set_default_params(ov) < 0) + goto error; + +#ifdef OV511_DEBUG + if (dump_bridge) { + if (ov->bclass == BCL_OV511) + ov511_dump_regs(ov); + else + ov518_dump_regs(ov); + } +#endif + + ov->vdev = video_device_alloc(); + if (!ov->vdev) + goto error; + + memcpy(ov->vdev, &vdev_template, sizeof(*ov->vdev)); + ov->vdev->dev = &dev->dev; + video_set_drvdata(ov->vdev, ov); + + for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) { + /* Minor 0 cannot be specified; assume user wants autodetect */ + if (unit_video[i] == 0) + break; + + if (video_register_device(ov->vdev, VFL_TYPE_GRABBER, + unit_video[i]) >= 0) { + break; + } + } + + /* Use the next available one */ + if ((ov->vdev->minor == -1) && + video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1) < 0) { + err("video_register_device failed"); + goto error; + } + + info("Device at %s registered to minor %d", ov->usb_path, + ov->vdev->minor); + + usb_set_intfdata(intf, ov); + ov_create_sysfs(ov->vdev); + return 0; + +error: + if (ov->vdev) { + if (-1 == ov->vdev->minor) + video_device_release(ov->vdev); + else + video_unregister_device(ov->vdev); + ov->vdev = NULL; + } + + if (ov->cbuf) { + mutex_lock(&ov->cbuf_lock); + kfree(ov->cbuf); + ov->cbuf = NULL; + mutex_unlock(&ov->cbuf_lock); + } + + kfree(ov); + ov = NULL; + +error_out: + err("Camera initialization failed"); + return -EIO; +} + +static void +ov51x_disconnect(struct usb_interface *intf) +{ + struct usb_ov511 *ov = usb_get_intfdata(intf); + int n; + + PDEBUG(3, ""); + + usb_set_intfdata (intf, NULL); + + if (!ov) + return; + + if (ov->vdev) + video_unregister_device(ov->vdev); + + for (n = 0; n < OV511_NUMFRAMES; n++) + ov->frame[n].grabstate = FRAME_ERROR; + + ov->curframe = -1; + + /* This will cause the process to request another frame */ + for (n = 0; n < OV511_NUMFRAMES; n++) + wake_up_interruptible(&ov->frame[n].wq); + + wake_up_interruptible(&ov->wq); + + ov->streaming = 0; + ov51x_unlink_isoc(ov); + + ov->dev = NULL; + + /* Free the memory */ + if (ov && !ov->user) { + mutex_lock(&ov->cbuf_lock); + kfree(ov->cbuf); + ov->cbuf = NULL; + mutex_unlock(&ov->cbuf_lock); + + ov51x_dealloc(ov); + kfree(ov); + ov = NULL; + } + + PDEBUG(3, "Disconnect complete"); +} + +static struct usb_driver ov511_driver = { + .name = "ov511", + .id_table = device_table, + .probe = ov51x_probe, + .disconnect = ov51x_disconnect +}; + +/**************************************************************************** + * + * Module routines + * + ***************************************************************************/ + +static int __init +usb_ov511_init(void) +{ + int retval; + + retval = usb_register(&ov511_driver); + if (retval) + goto out; + + info(DRIVER_VERSION " : " DRIVER_DESC); + +out: + return retval; +} + +static void __exit +usb_ov511_exit(void) +{ + usb_deregister(&ov511_driver); + info("driver deregistered"); + +} + +module_init(usb_ov511_init); +module_exit(usb_ov511_exit); + diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h new file mode 100644 index 000000000000..bce9b3633889 --- /dev/null +++ b/drivers/media/video/ov511.h @@ -0,0 +1,568 @@ +#ifndef __LINUX_OV511_H +#define __LINUX_OV511_H + +#include +#include +#include +#include +#include + +#define OV511_DEBUG /* Turn on debug messages */ + +#ifdef OV511_DEBUG + #define PDEBUG(level, fmt, args...) \ + if (debug >= (level)) info("[%s:%d] " fmt, \ + __FUNCTION__, __LINE__ , ## args) +#else + #define PDEBUG(level, fmt, args...) do {} while(0) +#endif + +/* This macro restricts an int variable to an inclusive range */ +#define RESTRICT_TO_RANGE(v,mi,ma) { \ + if ((v) < (mi)) (v) = (mi); \ + else if ((v) > (ma)) (v) = (ma); \ +} + +/* --------------------------------- */ +/* DEFINES FOR OV511 AND OTHER CHIPS */ +/* --------------------------------- */ + +/* USB IDs */ +#define VEND_OMNIVISION 0x05A9 +#define PROD_OV511 0x0511 +#define PROD_OV511PLUS 0xA511 +#define PROD_OV518 0x0518 +#define PROD_OV518PLUS 0xA518 + +#define VEND_MATTEL 0x0813 +#define PROD_ME2CAM 0x0002 + +/* --------------------------------- */ +/* OV51x REGISTER MNEMONICS */ +/* --------------------------------- */ + +/* Camera interface register numbers */ +#define R511_CAM_DELAY 0x10 +#define R511_CAM_EDGE 0x11 +#define R511_CAM_PXCNT 0x12 +#define R511_CAM_LNCNT 0x13 +#define R511_CAM_PXDIV 0x14 +#define R511_CAM_LNDIV 0x15 +#define R511_CAM_UV_EN 0x16 +#define R511_CAM_LINE_MODE 0x17 +#define R511_CAM_OPTS 0x18 + +/* Snapshot mode camera interface register numbers */ +#define R511_SNAP_FRAME 0x19 +#define R511_SNAP_PXCNT 0x1A +#define R511_SNAP_LNCNT 0x1B +#define R511_SNAP_PXDIV 0x1C +#define R511_SNAP_LNDIV 0x1D +#define R511_SNAP_UV_EN 0x1E +#define R511_SNAP_OPTS 0x1F + +/* DRAM register numbers */ +#define R511_DRAM_FLOW_CTL 0x20 +#define R511_DRAM_ARCP 0x21 +#define R511_DRAM_MRC 0x22 +#define R511_DRAM_RFC 0x23 + +/* ISO FIFO register numbers */ +#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ +#define R511_FIFO_OPTS 0x31 + +/* Parallel IO register numbers */ +#define R511_PIO_OPTS 0x38 +#define R511_PIO_DATA 0x39 +#define R511_PIO_BIST 0x3E +#define R518_GPIO_IN 0x55 /* OV518(+) only */ +#define R518_GPIO_OUT 0x56 /* OV518(+) only */ +#define R518_GPIO_CTL 0x57 /* OV518(+) only */ +#define R518_GPIO_PULSE_IN 0x58 /* OV518(+) only */ +#define R518_GPIO_PULSE_CLEAR 0x59 /* OV518(+) only */ +#define R518_GPIO_PULSE_POL 0x5a /* OV518(+) only */ +#define R518_GPIO_PULSE_EN 0x5b /* OV518(+) only */ +#define R518_GPIO_RESET 0x5c /* OV518(+) only */ + +/* I2C registers */ +#define R511_I2C_CTL 0x40 +#define R518_I2C_CTL 0x47 /* OV518(+) only */ +#define R51x_I2C_W_SID 0x41 +#define R51x_I2C_SADDR_3 0x42 +#define R51x_I2C_SADDR_2 0x43 +#define R51x_I2C_R_SID 0x44 +#define R51x_I2C_DATA 0x45 +#define R51x_I2C_CLOCK 0x46 +#define R51x_I2C_TIMEOUT 0x47 + +/* I2C snapshot registers */ +#define R511_SI2C_SADDR_3 0x48 +#define R511_SI2C_DATA 0x49 + +/* System control registers */ +#define R51x_SYS_RESET 0x50 + /* Reset type definitions */ +#define OV511_RESET_UDC 0x01 +#define OV511_RESET_I2C 0x02 +#define OV511_RESET_FIFO 0x04 +#define OV511_RESET_OMNICE 0x08 +#define OV511_RESET_DRAM 0x10 +#define OV511_RESET_CAM_INT 0x20 +#define OV511_RESET_OV511 0x40 +#define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */ +#define OV511_RESET_ALL 0x7F + +#define R511_SYS_CLOCK_DIV 0x51 +#define R51x_SYS_SNAP 0x52 +#define R51x_SYS_INIT 0x53 +#define R511_SYS_PWR_CLK 0x54 /* OV511+/OV518(+) only */ +#define R511_SYS_LED_CTL 0x55 /* OV511+ only */ +#define R511_SYS_USER 0x5E +#define R511_SYS_CUST_ID 0x5F + +/* OmniCE (compression) registers */ +#define R511_COMP_PHY 0x70 +#define R511_COMP_PHUV 0x71 +#define R511_COMP_PVY 0x72 +#define R511_COMP_PVUV 0x73 +#define R511_COMP_QHY 0x74 +#define R511_COMP_QHUV 0x75 +#define R511_COMP_QVY 0x76 +#define R511_COMP_QVUV 0x77 +#define R511_COMP_EN 0x78 +#define R511_COMP_LUT_EN 0x79 +#define R511_COMP_LUT_BEGIN 0x80 + +/* --------------------------------- */ +/* ALTERNATE NUMBERS */ +/* --------------------------------- */ + +/* Alternate numbers for various max packet sizes (OV511 only) */ +#define OV511_ALT_SIZE_992 0 +#define OV511_ALT_SIZE_993 1 +#define OV511_ALT_SIZE_768 2 +#define OV511_ALT_SIZE_769 3 +#define OV511_ALT_SIZE_512 4 +#define OV511_ALT_SIZE_513 5 +#define OV511_ALT_SIZE_257 6 +#define OV511_ALT_SIZE_0 7 + +/* Alternate numbers for various max packet sizes (OV511+ only) */ +#define OV511PLUS_ALT_SIZE_0 0 +#define OV511PLUS_ALT_SIZE_33 1 +#define OV511PLUS_ALT_SIZE_129 2 +#define OV511PLUS_ALT_SIZE_257 3 +#define OV511PLUS_ALT_SIZE_385 4 +#define OV511PLUS_ALT_SIZE_513 5 +#define OV511PLUS_ALT_SIZE_769 6 +#define OV511PLUS_ALT_SIZE_961 7 + +/* Alternate numbers for various max packet sizes (OV518(+) only) */ +#define OV518_ALT_SIZE_0 0 +#define OV518_ALT_SIZE_128 1 +#define OV518_ALT_SIZE_256 2 +#define OV518_ALT_SIZE_384 3 +#define OV518_ALT_SIZE_512 4 +#define OV518_ALT_SIZE_640 5 +#define OV518_ALT_SIZE_768 6 +#define OV518_ALT_SIZE_896 7 + +/* --------------------------------- */ +/* OV7610 REGISTER MNEMONICS */ +/* --------------------------------- */ + +/* OV7610 registers */ +#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */ +#define OV7610_REG_BLUE 0x01 /* blue channel balance */ +#define OV7610_REG_RED 0x02 /* red channel balance */ +#define OV7610_REG_SAT 0x03 /* saturation */ + /* 04 reserved */ +#define OV7610_REG_CNT 0x05 /* Y contrast */ +#define OV7610_REG_BRT 0x06 /* Y brightness */ + /* 08-0b reserved */ +#define OV7610_REG_BLUE_BIAS 0x0C /* blue channel bias (5:0) */ +#define OV7610_REG_RED_BIAS 0x0D /* read channel bias (5:0) */ +#define OV7610_REG_GAMMA_COEFF 0x0E /* gamma settings */ +#define OV7610_REG_WB_RANGE 0x0F /* AEC/ALC/S-AWB settings */ +#define OV7610_REG_EXP 0x10 /* manual exposure setting */ +#define OV7610_REG_CLOCK 0x11 /* polarity/clock prescaler */ +#define OV7610_REG_COM_A 0x12 /* misc common regs */ +#define OV7610_REG_COM_B 0x13 /* misc common regs */ +#define OV7610_REG_COM_C 0x14 /* misc common regs */ +#define OV7610_REG_COM_D 0x15 /* misc common regs */ +#define OV7610_REG_FIELD_DIVIDE 0x16 /* field interval/mode settings */ +#define OV7610_REG_HWIN_START 0x17 /* horizontal window start */ +#define OV7610_REG_HWIN_END 0x18 /* horizontal window end */ +#define OV7610_REG_VWIN_START 0x19 /* vertical window start */ +#define OV7610_REG_VWIN_END 0x1A /* vertical window end */ +#define OV7610_REG_PIXEL_SHIFT 0x1B /* pixel shift */ +#define OV7610_REG_ID_HIGH 0x1C /* manufacturer ID MSB */ +#define OV7610_REG_ID_LOW 0x1D /* manufacturer ID LSB */ + /* 0e-0f reserved */ +#define OV7610_REG_COM_E 0x20 /* misc common regs */ +#define OV7610_REG_YOFFSET 0x21 /* Y channel offset */ +#define OV7610_REG_UOFFSET 0x22 /* U channel offset */ + /* 23 reserved */ +#define OV7610_REG_ECW 0x24 /* Exposure white level for AEC */ +#define OV7610_REG_ECB 0x25 /* Exposure black level for AEC */ +#define OV7610_REG_COM_F 0x26 /* misc settings */ +#define OV7610_REG_COM_G 0x27 /* misc settings */ +#define OV7610_REG_COM_H 0x28 /* misc settings */ +#define OV7610_REG_COM_I 0x29 /* misc settings */ +#define OV7610_REG_FRAMERATE_H 0x2A /* frame rate MSB + misc */ +#define OV7610_REG_FRAMERATE_L 0x2B /* frame rate LSB */ +#define OV7610_REG_ALC 0x2C /* Auto Level Control settings */ +#define OV7610_REG_COM_J 0x2D /* misc settings */ +#define OV7610_REG_VOFFSET 0x2E /* V channel offset adjustment */ +#define OV7610_REG_ARRAY_BIAS 0x2F /* Array bias -- don't change */ + /* 30-32 reserved */ +#define OV7610_REG_YGAMMA 0x33 /* misc gamma settings (7:6) */ +#define OV7610_REG_BIAS_ADJUST 0x34 /* misc bias settings */ +#define OV7610_REG_COM_L 0x35 /* misc settings */ + /* 36-37 reserved */ +#define OV7610_REG_COM_K 0x38 /* misc registers */ + +/* --------------------------------- */ +/* I2C ADDRESSES */ +/* --------------------------------- */ + +#define OV7xx0_SID 0x42 +#define OV6xx0_SID 0xC0 +#define OV8xx0_SID 0xA0 +#define KS0127_SID 0xD8 +#define SAA7111A_SID 0x48 + +/* --------------------------------- */ +/* MISCELLANEOUS DEFINES */ +/* --------------------------------- */ + +#define I2C_CLOCK_PRESCALER 0x03 + +#define FRAMES_PER_DESC 10 /* FIXME - What should this be? */ +#define MAX_FRAME_SIZE_PER_DESC 993 /* For statically allocated stuff */ +#define PIXELS_PER_SEG 256 /* Pixels per segment */ + +#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ + +#define OV511_NUMFRAMES 2 +#if OV511_NUMFRAMES > VIDEO_MAX_FRAME + #error "OV511_NUMFRAMES is too high" +#endif + +#define OV511_NUMSBUF 2 + +/* Control transfers use up to 4 bytes */ +#define OV511_CBUF_SIZE 4 + +/* Size of usb_make_path() buffer */ +#define OV511_USB_PATH_LEN 64 + +/* Bridge types */ +enum { + BRG_UNKNOWN, + BRG_OV511, + BRG_OV511PLUS, + BRG_OV518, + BRG_OV518PLUS, +}; + +/* Bridge classes */ +enum { + BCL_UNKNOWN, + BCL_OV511, + BCL_OV518, +}; + +/* Sensor types */ +enum { + SEN_UNKNOWN, + SEN_OV76BE, + SEN_OV7610, + SEN_OV7620, + SEN_OV7620AE, + SEN_OV6620, + SEN_OV6630, + SEN_OV6630AE, + SEN_OV6630AF, + SEN_OV8600, + SEN_KS0127, + SEN_KS0127B, + SEN_SAA7111A, +}; + +enum { + STATE_SCANNING, /* Scanning for start */ + STATE_HEADER, /* Parsing header */ + STATE_LINES, /* Parsing lines */ +}; + +/* Buffer states */ +enum { + BUF_NOT_ALLOCATED, + BUF_ALLOCATED, +}; + +/* --------- Definition of ioctl interface --------- */ + +#define OV511_INTERFACE_VER 101 + +/* LED options */ +enum { + LED_OFF, + LED_ON, + LED_AUTO, +}; + +/* Raw frame formats */ +enum { + RAWFMT_INVALID, + RAWFMT_YUV400, + RAWFMT_YUV420, + RAWFMT_YUV422, + RAWFMT_GBR422, +}; + +struct ov511_i2c_struct { + unsigned char slave; /* Write slave ID (read ID - 1) */ + unsigned char reg; /* Index of register */ + unsigned char value; /* User sets this w/ write, driver does w/ read */ + unsigned char mask; /* Bits to be changed. Not used with read ops */ +}; + +/* ioctls */ +#define OV511IOC_WI2C _IOW('v', BASE_VIDIOCPRIVATE + 5, \ + struct ov511_i2c_struct) +#define OV511IOC_RI2C _IOWR('v', BASE_VIDIOCPRIVATE + 6, \ + struct ov511_i2c_struct) +/* ------------- End IOCTL interface -------------- */ + +struct usb_ov511; /* Forward declaration */ + +struct ov511_sbuf { + struct usb_ov511 *ov; + unsigned char *data; + struct urb *urb; + spinlock_t lock; + int n; +}; + +enum { + FRAME_UNUSED, /* Unused (no MCAPTURE) */ + FRAME_READY, /* Ready to start grabbing */ + FRAME_GRABBING, /* In the process of being grabbed into */ + FRAME_DONE, /* Finished grabbing, but not been synced yet */ + FRAME_ERROR, /* Something bad happened while processing */ +}; + +struct ov511_regvals { + enum { + OV511_DONE_BUS, + OV511_REG_BUS, + OV511_I2C_BUS, + } bus; + unsigned char reg; + unsigned char val; +}; + +struct ov511_frame { + int framenum; /* Index of this frame */ + unsigned char *data; /* Frame buffer */ + unsigned char *tempdata; /* Temp buffer for multi-stage conversions */ + unsigned char *rawdata; /* Raw camera data buffer */ + unsigned char *compbuf; /* Temp buffer for decompressor */ + + int depth; /* Bytes per pixel */ + int width; /* Width application is expecting */ + int height; /* Height application is expecting */ + + int rawwidth; /* Actual width of frame sent from camera */ + int rawheight; /* Actual height of frame sent from camera */ + + int sub_flag; /* Sub-capture mode for this frame? */ + unsigned int format; /* Format for this frame */ + int compressed; /* Is frame compressed? */ + + volatile int grabstate; /* State of grabbing */ + int scanstate; /* State of scanning */ + + int bytes_recvd; /* Number of image bytes received from camera */ + + long bytes_read; /* Amount that has been read() */ + + wait_queue_head_t wq; /* Processes waiting */ + + int snapshot; /* True if frame was a snapshot */ +}; + +#define DECOMP_INTERFACE_VER 4 + +/* Compression module operations */ +struct ov51x_decomp_ops { + int (*decomp_400)(unsigned char *, unsigned char *, unsigned char *, + int, int, int); + int (*decomp_420)(unsigned char *, unsigned char *, unsigned char *, + int, int, int); + int (*decomp_422)(unsigned char *, unsigned char *, unsigned char *, + int, int, int); + struct module *owner; +}; + +struct usb_ov511 { + struct video_device *vdev; + struct usb_device *dev; + + int customid; + char *desc; + unsigned char iface; + char usb_path[OV511_USB_PATH_LEN]; + + /* Determined by sensor type */ + int maxwidth; + int maxheight; + int minwidth; + int minheight; + + int brightness; + int colour; + int contrast; + int hue; + int whiteness; + int exposure; + int auto_brt; /* Auto brightness enabled flag */ + int auto_gain; /* Auto gain control enabled flag */ + int auto_exp; /* Auto exposure enabled flag */ + int backlight; /* Backlight exposure algorithm flag */ + int mirror; /* Image is reversed horizontally */ + + int led_policy; /* LED: off|on|auto; OV511+ only */ + + struct mutex lock; /* Serializes user-accessible operations */ + int user; /* user count for exclusive use */ + + int streaming; /* Are we streaming Isochronous? */ + int grabbing; /* Are we grabbing? */ + + int compress; /* Should the next frame be compressed? */ + int compress_inited; /* Are compression params uploaded? */ + + int lightfreq; /* Power (lighting) frequency */ + int bandfilt; /* Banding filter enabled flag */ + + unsigned char *fbuf; /* Videodev buffer area */ + unsigned char *tempfbuf; /* Temporary (intermediate) buffer area */ + unsigned char *rawfbuf; /* Raw camera data buffer area */ + + int sub_flag; /* Pix Array subcapture on flag */ + int subx; /* Pix Array subcapture x offset */ + int suby; /* Pix Array subcapture y offset */ + int subw; /* Pix Array subcapture width */ + int subh; /* Pix Array subcapture height */ + + int curframe; /* Current receiving sbuf */ + struct ov511_frame frame[OV511_NUMFRAMES]; + + struct ov511_sbuf sbuf[OV511_NUMSBUF]; + + wait_queue_head_t wq; /* Processes waiting */ + + int snap_enabled; /* Snapshot mode enabled */ + + int bridge; /* Type of bridge (BRG_*) */ + int bclass; /* Class of bridge (BCL_*) */ + int sensor; /* Type of image sensor chip (SEN_*) */ + + int packet_size; /* Frame size per isoc desc */ + int packet_numbering; /* Is ISO frame numbering enabled? */ + + /* Framebuffer/sbuf management */ + int buf_state; + struct mutex buf_lock; + + struct ov51x_decomp_ops *decomp_ops; + + /* Stop streaming while changing picture settings */ + int stop_during_set; + + int stopped; /* Streaming is temporarily paused */ + + /* Video decoder stuff */ + int input; /* Composite, S-VIDEO, etc... */ + int num_inputs; /* Number of inputs */ + int norm; /* NTSC / PAL / SECAM */ + int has_decoder; /* Device has a video decoder */ + int pal; /* Device is designed for PAL resolution */ + + /* I2C interface */ + struct mutex i2c_lock; /* Protect I2C controller regs */ + unsigned char primary_i2c_slave; /* I2C write id of sensor */ + + /* Control transaction stuff */ + unsigned char *cbuf; /* Buffer for payload */ + struct mutex cbuf_lock; +}; + +/* Used to represent a list of values and their respective symbolic names */ +struct symbolic_list { + int num; + char *name; +}; + +#define NOT_DEFINED_STR "Unknown" + +/* Returns the name of the matching element in the symbolic_list array. The + * end of the list must be marked with an element that has a NULL name. + */ +static inline char * +symbolic(struct symbolic_list list[], int num) +{ + int i; + + for (i = 0; list[i].name != NULL; i++) + if (list[i].num == num) + return (list[i].name); + + return (NOT_DEFINED_STR); +} + +/* Compression stuff */ + +#define OV511_QUANTABLESIZE 64 +#define OV518_QUANTABLESIZE 32 + +#define OV511_YQUANTABLE { \ + 0, 1, 1, 2, 2, 3, 3, 4, \ + 1, 1, 1, 2, 2, 3, 4, 4, \ + 1, 1, 2, 2, 3, 4, 4, 4, \ + 2, 2, 2, 3, 4, 4, 4, 4, \ + 2, 2, 3, 4, 4, 5, 5, 5, \ + 3, 3, 4, 4, 5, 5, 5, 5, \ + 3, 4, 4, 4, 5, 5, 5, 5, \ + 4, 4, 4, 4, 5, 5, 5, 5 \ +} + +#define OV511_UVQUANTABLE { \ + 0, 2, 2, 3, 4, 4, 4, 4, \ + 2, 2, 2, 4, 4, 4, 4, 4, \ + 2, 2, 3, 4, 4, 4, 4, 4, \ + 3, 4, 4, 4, 4, 4, 4, 4, \ + 4, 4, 4, 4, 4, 4, 4, 4, \ + 4, 4, 4, 4, 4, 4, 4, 4, \ + 4, 4, 4, 4, 4, 4, 4, 4, \ + 4, 4, 4, 4, 4, 4, 4, 4 \ +} + +#define OV518_YQUANTABLE { \ + 5, 4, 5, 6, 6, 7, 7, 7, \ + 5, 5, 5, 5, 6, 7, 7, 7, \ + 6, 6, 6, 6, 7, 7, 7, 8, \ + 7, 7, 6, 7, 7, 7, 8, 8 \ +} + +#define OV518_UVQUANTABLE { \ + 6, 6, 6, 7, 7, 7, 7, 7, \ + 6, 6, 6, 7, 7, 7, 7, 7, \ + 6, 6, 6, 7, 7, 7, 7, 8, \ + 7, 7, 7, 7, 7, 7, 8, 8 \ +} + +#endif diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile new file mode 100644 index 000000000000..2d93a775011a --- /dev/null +++ b/drivers/media/video/pwc/Makefile @@ -0,0 +1,20 @@ +ifneq ($(KERNELRELEASE),) + +pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o + +obj-$(CONFIG_USB_PWC) += pwc.o + +else + +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) + +default: + $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules + +endif + +clean: + rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c + rm -rf .tmp_versions + diff --git a/drivers/media/video/pwc/philips.txt b/drivers/media/video/pwc/philips.txt new file mode 100644 index 000000000000..04a640d723ed --- /dev/null +++ b/drivers/media/video/pwc/philips.txt @@ -0,0 +1,236 @@ +This file contains some additional information for the Philips and OEM webcams. +E-mail: webcam@smcc.demon.nl Last updated: 2004-01-19 +Site: http://www.smcc.demon.nl/webcam/ + +As of this moment, the following cameras are supported: + * Philips PCA645 + * Philips PCA646 + * Philips PCVC675 + * Philips PCVC680 + * Philips PCVC690 + * Philips PCVC720/40 + * Philips PCVC730 + * Philips PCVC740 + * Philips PCVC750 + * Askey VC010 + * Creative Labs Webcam 5 + * Creative Labs Webcam Pro Ex + * Logitech QuickCam 3000 Pro + * Logitech QuickCam 4000 Pro + * Logitech QuickCam Notebook Pro + * Logitech QuickCam Zoom + * Logitech QuickCam Orbit + * Logitech QuickCam Sphere + * Samsung MPC-C10 + * Samsung MPC-C30 + * Sotec Afina Eye + * AME CU-001 + * Visionite VCS-UM100 + * Visionite VCS-UC300 + +The main webpage for the Philips driver is at the address above. It contains +a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin +contains decompression routines that allow you to use higher image sizes and +framerates; in addition the webcam uses less bandwidth on the USB bus (handy +if you want to run more than 1 camera simultaneously). These routines fall +under a NDA, and may therefor not be distributed as source; however, its use +is completely optional. + +You can build this code either into your kernel, or as a module. I recommend +the latter, since it makes troubleshooting a lot easier. The built-in +microphone is supported through the USB Audio class. + +When you load the module you can set some default settings for the +camera; some programs depend on a particular image-size or -format and +don't know how to set it properly in the driver. The options are: + +size + Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or + 'vga', for an image size of resp. 128x96, 160x120, 176x144, + 320x240, 352x288 and 640x480 (of course, only for those cameras that + support these resolutions). + +fps + Specifies the desired framerate. Is an integer in the range of 4-30. + +fbufs + This paramter specifies the number of internal buffers to use for storing + frames from the cam. This will help if the process that reads images from + the cam is a bit slow or momentarely busy. However, on slow machines it + only introduces lag, so choose carefully. The default is 3, which is + reasonable. You can set it between 2 and 5. + +mbufs + This is an integer between 1 and 10. It will tell the module the number of + buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends. + The default is 2, which is adequate for most applications (double + buffering). + + Should you experience a lot of 'Dumping frame...' messages during + grabbing with a tool that uses mmap(), you might want to increase if. + However, it doesn't really buffer images, it just gives you a bit more + slack when your program is behind. But you need a multi-threaded or + forked program to really take advantage of these buffers. + + The absolute maximum is 10, but don't set it too high! Every buffer takes + up 460 KB of RAM, so unless you have a lot of memory setting this to + something more than 4 is an absolute waste. This memory is only + allocated during open(), so nothing is wasted when the camera is not in + use. + +power_save + When power_save is enabled (set to 1), the module will try to shut down + the cam on close() and re-activate on open(). This will save power and + turn off the LED. Not all cameras support this though (the 645 and 646 + don't have power saving at all), and some models don't work either (they + will shut down, but never wake up). Consider this experimental. By + default this option is disabled. + +compression (only useful with the plugin) + With this option you can control the compression factor that the camera + uses to squeeze the image through the USB bus. You can set the + parameter between 0 and 3: + 0 = prefer uncompressed images; if the requested mode is not available + in an uncompressed format, the driver will silently switch to low + compression. + 1 = low compression. + 2 = medium compression. + 3 = high compression. + + High compression takes less bandwidth of course, but it could also + introduce some unwanted artefacts. The default is 2, medium compression. + See the FAQ on the website for an overview of which modes require + compression. + + The compression parameter does not apply to the 645 and 646 cameras + and OEM models derived from those (only a few). Most cams honour this + parameter. + +leds + This settings takes 2 integers, that define the on/off time for the LED + (in milliseconds). One of the interesting things that you can do with + this is let the LED blink while the camera is in use. This: + + leds=500,500 + + will blink the LED once every second. But with: + + leds=0,0 + + the LED never goes on, making it suitable for silent surveillance. + + By default the camera's LED is on solid while in use, and turned off + when the camera is not used anymore. + + This parameter works only with the ToUCam range of cameras (720, 730, 740, + 750) and OEMs. For other cameras this command is silently ignored, and + the LED cannot be controlled. + + Finally: this parameters does not take effect UNTIL the first time you + open the camera device. Until then, the LED remains on. + +dev_hint + A long standing problem with USB devices is their dynamic nature: you + never know what device a camera gets assigned; it depends on module load + order, the hub configuration, the order in which devices are plugged in, + and the phase of the moon (i.e. it can be random). With this option you + can give the driver a hint as to what video device node (/dev/videoX) it + should use with a specific camera. This is also handy if you have two + cameras of the same model. + + A camera is specified by its type (the number from the camera model, + like PCA645, PCVC750VC, etc) and optionally the serial number (visible + in /proc/bus/usb/devices). A hint consists of a string with the following + format: + + [type[.serialnumber]:]node + + The square brackets mean that both the type and the serialnumber are + optional, but a serialnumber cannot be specified without a type (which + would be rather pointless). The serialnumber is separated from the type + by a '.'; the node number by a ':'. + + This somewhat cryptic syntax is best explained by a few examples: + + dev_hint=3,5 The first detected cam gets assigned + /dev/video3, the second /dev/video5. Any + other cameras will get the first free + available slot (see below). + + dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1, + and a PCVC680 /dev/video2. + + dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber + 0123 goes to /dev/video3, the same + camera model with the 4567 serial + gets /dev/video0. + + dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the + next 3 Philips cams will use /dev/video4 + through /dev/video6. + + Some points worth knowing: + - Serialnumbers are case sensitive and must be written full, including + leading zeroes (it's treated as a string). + - If a device node is already occupied, registration will fail and + the webcam is not available. + - You can have up to 64 video devices; be sure to make enough device + nodes in /dev if you want to spread the numbers (this does not apply + to devfs). After /dev/video9 comes /dev/video10 (not /dev/videoA). + - If a camera does not match any dev_hint, it will simply get assigned + the first available device node, just as it used to be. + +trace + In order to better detect problems, it is now possible to turn on a + 'trace' of some of the calls the module makes; it logs all items in your + kernel log at debug level. + + The trace variable is a bitmask; each bit represents a certain feature. + If you want to trace something, look up the bit value(s) in the table + below, add the values together and supply that to the trace variable. + + Value Value Description Default + (dec) (hex) + 1 0x1 Module initialization; this will log messages On + while loading and unloading the module + + 2 0x2 probe() and disconnect() traces On + + 4 0x4 Trace open() and close() calls Off + + 8 0x8 read(), mmap() and associated ioctl() calls Off + + 16 0x10 Memory allocation of buffers, etc. Off + + 32 0x20 Showing underflow, overflow and Dumping frame On + messages + + 64 0x40 Show viewport and image sizes Off + + 128 0x80 PWCX debugging Off + + For example, to trace the open() & read() fuctions, sum 8 + 4 = 12, + so you would supply trace=12 during insmod or modprobe. If + you want to turn the initialization and probing tracing off, set trace=0. + The default value for trace is 35 (0x23). + + + +Example: + + # modprobe pwc size=cif fps=15 power_save=1 + +The fbufs, mbufs and trace parameters are global and apply to all connected +cameras. Each camera has its own set of buffers. + +size and fps only specify defaults when you open() the device; this is to +accommodate some tools that don't set the size. You can change these +settings after open() with the Video4Linux ioctl() calls. The default of +defaults is QCIF size at 10 fps. + +The compression parameter is semiglobal; it sets the initial compression +preference for all camera's, but this parameter can be set per camera with +the VIDIOCPWCSCQUAL ioctl() call. + +All parameters are optional. + diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c new file mode 100644 index 000000000000..0398b812e0ce --- /dev/null +++ b/drivers/media/video/pwc/pwc-ctrl.c @@ -0,0 +1,1541 @@ +/* Driver for Philips webcam + Functions that send various control messages to the webcam, including + video modes. + (C) 1999-2003 Nemosoft Unv. + (C) 2004 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + 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 +*/ + +/* + Changes + 2001/08/03 Alvarado Added methods for changing white balance and + red/green gains + */ + +/* Control functions for the cam; brightness, contrast, video mode, etc. */ + +#ifdef __KERNEL__ +#include +#endif +#include + +#include "pwc.h" +#include "pwc-ioctl.h" +#include "pwc-uncompress.h" +#include "pwc-kiara.h" +#include "pwc-timon.h" + +/* Request types: video */ +#define SET_LUM_CTL 0x01 +#define GET_LUM_CTL 0x02 +#define SET_CHROM_CTL 0x03 +#define GET_CHROM_CTL 0x04 +#define SET_STATUS_CTL 0x05 +#define GET_STATUS_CTL 0x06 +#define SET_EP_STREAM_CTL 0x07 +#define GET_EP_STREAM_CTL 0x08 +#define SET_MPT_CTL 0x0D +#define GET_MPT_CTL 0x0E + +/* Selectors for the Luminance controls [GS]ET_LUM_CTL */ +#define AGC_MODE_FORMATTER 0x2000 +#define PRESET_AGC_FORMATTER 0x2100 +#define SHUTTER_MODE_FORMATTER 0x2200 +#define PRESET_SHUTTER_FORMATTER 0x2300 +#define PRESET_CONTOUR_FORMATTER 0x2400 +#define AUTO_CONTOUR_FORMATTER 0x2500 +#define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600 +#define CONTRAST_FORMATTER 0x2700 +#define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800 +#define FLICKERLESS_MODE_FORMATTER 0x2900 +#define AE_CONTROL_SPEED 0x2A00 +#define BRIGHTNESS_FORMATTER 0x2B00 +#define GAMMA_FORMATTER 0x2C00 + +/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */ +#define WB_MODE_FORMATTER 0x1000 +#define AWB_CONTROL_SPEED_FORMATTER 0x1100 +#define AWB_CONTROL_DELAY_FORMATTER 0x1200 +#define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300 +#define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400 +#define COLOUR_MODE_FORMATTER 0x1500 +#define SATURATION_MODE_FORMATTER1 0x1600 +#define SATURATION_MODE_FORMATTER2 0x1700 + +/* Selectors for the Status controls [GS]ET_STATUS_CTL */ +#define SAVE_USER_DEFAULTS_FORMATTER 0x0200 +#define RESTORE_USER_DEFAULTS_FORMATTER 0x0300 +#define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400 +#define READ_AGC_FORMATTER 0x0500 +#define READ_SHUTTER_FORMATTER 0x0600 +#define READ_RED_GAIN_FORMATTER 0x0700 +#define READ_BLUE_GAIN_FORMATTER 0x0800 +#define SENSOR_TYPE_FORMATTER1 0x0C00 +#define READ_RAW_Y_MEAN_FORMATTER 0x3100 +#define SET_POWER_SAVE_MODE_FORMATTER 0x3200 +#define MIRROR_IMAGE_FORMATTER 0x3300 +#define LED_FORMATTER 0x3400 +#define SENSOR_TYPE_FORMATTER2 0x3700 + +/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ +#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100 + +/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */ +#define PT_RELATIVE_CONTROL_FORMATTER 0x01 +#define PT_RESET_CONTROL_FORMATTER 0x02 +#define PT_STATUS_FORMATTER 0x03 + +static const char *size2name[PSZ_MAX] = +{ + "subQCIF", + "QSIF", + "QCIF", + "SIF", + "CIF", + "VGA", +}; + +/********/ + +/* Entries for the Nala (645/646) camera; the Nala doesn't have compression + preferences, so you either get compressed or non-compressed streams. + + An alternate value of 0 means this mode is not available at all. + */ + +struct Nala_table_entry { + char alternate; /* USB alternate setting */ + int compressed; /* Compressed yes/no */ + + unsigned char mode[3]; /* precomputed mode table */ +}; + +static struct Nala_table_entry Nala_table[PSZ_MAX][8] = +{ +#include "pwc-nala.h" +}; + + +/****************************************************************************/ + + +#define SendControlMsg(request, value, buflen) \ + usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \ + request, \ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \ + value, \ + pdev->vcinterface, \ + &buf, buflen, 500) + +#define RecvControlMsg(request, value, buflen) \ + usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \ + request, \ + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \ + value, \ + pdev->vcinterface, \ + &buf, buflen, 500) + + +#if PWC_DEBUG +void pwc_hexdump(void *p, int len) +{ + int i; + unsigned char *s; + char buf[100], *d; + + s = (unsigned char *)p; + d = buf; + *d = '\0'; + Debug("Doing hexdump @ %p, %d bytes.\n", p, len); + for (i = 0; i < len; i++) { + d += sprintf(d, "%02X ", *s++); + if ((i & 0xF) == 0xF) { + Debug("%s\n", buf); + d = buf; + *d = '\0'; + } + } + if ((i & 0xF) != 0) + Debug("%s\n", buf); +} +#endif + +static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen) +{ + return usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + SET_EP_STREAM_CTL, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + VIDEO_OUTPUT_CONTROL_FORMATTER, + index, + buf, buflen, 1000); +} + + + +static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) +{ + unsigned char buf[3]; + int ret, fps; + struct Nala_table_entry *pEntry; + int frames2frames[31] = + { /* closest match of framerate */ + 0, 0, 0, 0, 4, /* 0-4 */ + 5, 5, 7, 7, 10, /* 5-9 */ + 10, 10, 12, 12, 15, /* 10-14 */ + 15, 15, 15, 20, 20, /* 15-19 */ + 20, 20, 20, 24, 24, /* 20-24 */ + 24, 24, 24, 24, 24, /* 25-29 */ + 24 /* 30 */ + }; + int frames2table[31] = + { 0, 0, 0, 0, 0, /* 0-4 */ + 1, 1, 1, 2, 2, /* 5-9 */ + 3, 3, 4, 4, 4, /* 10-14 */ + 5, 5, 5, 5, 5, /* 15-19 */ + 6, 6, 6, 6, 7, /* 20-24 */ + 7, 7, 7, 7, 7, /* 25-29 */ + 7 /* 30 */ + }; + + if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25) + return -EINVAL; + frames = frames2frames[frames]; + fps = frames2table[frames]; + pEntry = &Nala_table[size][fps]; + if (pEntry->alternate == 0) + return -EINVAL; + + if (pEntry->compressed) + return -ENOENT; /* Not supported. */ + + memcpy(buf, pEntry->mode, 3); + ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); + if (ret < 0) { + Debug("Failed to send video command... %d\n", ret); + return ret; + } + if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW) + { + switch(pdev->type) { + case 645: + case 646: +/* pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ + break; + + case 675: + case 680: + case 690: + case 720: + case 730: + case 740: + case 750: +/* pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ + break; + } + } + + pdev->cmd_len = 3; + memcpy(pdev->cmd_buf, buf, 3); + + /* Set various parameters */ + pdev->vframes = frames; + pdev->vsize = size; + pdev->valternate = pEntry->alternate; + pdev->image = pwc_image_sizes[size]; + pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2; + if (pEntry->compressed) { + if (pdev->release < 5) { /* 4 fold compression */ + pdev->vbandlength = 528; + pdev->frame_size /= 4; + } + else { + pdev->vbandlength = 704; + pdev->frame_size /= 3; + } + } + else + pdev->vbandlength = 0; + return 0; +} + + +static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) +{ + unsigned char buf[13]; + const struct Timon_table_entry *pChoose; + int ret, fps; + + if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3) + return -EINVAL; + if (size == PSZ_VGA && frames > 15) + return -EINVAL; + fps = (frames / 5) - 1; + + /* Find a supported framerate with progressively higher compression ratios + if the preferred ratio is not available. + */ + pChoose = NULL; + while (compression <= 3) { + pChoose = &Timon_table[size][fps][compression]; + if (pChoose->alternate != 0) + break; + compression++; + } + if (pChoose == NULL || pChoose->alternate == 0) + return -ENOENT; /* Not supported. */ + + memcpy(buf, pChoose->mode, 13); + if (snapshot) + buf[0] |= 0x80; + ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13); + if (ret < 0) + return ret; + +/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) + pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ + + pdev->cmd_len = 13; + memcpy(pdev->cmd_buf, buf, 13); + + /* Set various parameters */ + pdev->vframes = frames; + pdev->vsize = size; + pdev->vsnapshot = snapshot; + pdev->valternate = pChoose->alternate; + pdev->image = pwc_image_sizes[size]; + pdev->vbandlength = pChoose->bandlength; + if (pChoose->bandlength > 0) + pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4; + else + pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; + return 0; +} + + +static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) +{ + const struct Kiara_table_entry *pChoose = NULL; + int fps, ret; + unsigned char buf[12]; + struct Kiara_table_entry RawEntry = {6, 773, 1272, {0xAD, 0xF4, 0x10, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}}; + + if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3) + return -EINVAL; + if (size == PSZ_VGA && frames > 15) + return -EINVAL; + fps = (frames / 5) - 1; + + /* special case: VGA @ 5 fps and snapshot is raw bayer mode */ + if (size == PSZ_VGA && frames == 5 && snapshot) + { + /* Only available in case the raw palette is selected or + we have the decompressor available. This mode is + only available in compressed form + */ + if (pdev->vpalette == VIDEO_PALETTE_RAW) + { + Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette); + pChoose = &RawEntry; + } + else + { + Info("VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.\n"); + } + } + else + { + /* Find a supported framerate with progressively higher compression ratios + if the preferred ratio is not available. + Skip this step when using RAW modes. + */ + while (compression <= 3) { + pChoose = &Kiara_table[size][fps][compression]; + if (pChoose->alternate != 0) + break; + compression++; + } + } + if (pChoose == NULL || pChoose->alternate == 0) + return -ENOENT; /* Not supported. */ + + Debug("Using alternate setting %d.\n", pChoose->alternate); + + /* usb_control_msg won't take staticly allocated arrays as argument?? */ + memcpy(buf, pChoose->mode, 12); + if (snapshot) + buf[0] |= 0x80; + + /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ + ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12); + if (ret < 0) + return ret; + +/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) + pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ + + pdev->cmd_len = 12; + memcpy(pdev->cmd_buf, buf, 12); + /* All set and go */ + pdev->vframes = frames; + pdev->vsize = size; + pdev->vsnapshot = snapshot; + pdev->valternate = pChoose->alternate; + pdev->image = pwc_image_sizes[size]; + pdev->vbandlength = pChoose->bandlength; + if (pdev->vbandlength > 0) + pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4; + else + pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; + return 0; +} + + + +static void pwc_set_image_buffer_size(struct pwc_device *pdev) +{ + int i, factor = 0, filler = 0; + + /* for PALETTE_YUV420P */ + switch(pdev->vpalette) + { + case VIDEO_PALETTE_YUV420P: + factor = 6; + filler = 128; + break; + case VIDEO_PALETTE_RAW: + factor = 6; /* can be uncompressed YUV420P */ + filler = 0; + break; + } + + /* Set sizes in bytes */ + pdev->image.size = pdev->image.x * pdev->image.y * factor / 4; + pdev->view.size = pdev->view.x * pdev->view.y * factor / 4; + + /* Align offset, or you'll get some very weird results in + YUV420 mode... x must be multiple of 4 (to get the Y's in + place), and y even (or you'll mixup U & V). This is less of a + problem for YUV420P. + */ + pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC; + pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE; + + /* Fill buffers with gray or black */ + for (i = 0; i < MAX_IMAGES; i++) { + if (pdev->image_ptr[i] != NULL) + memset(pdev->image_ptr[i], filler, pdev->view.size); + } +} + + + +/** + @pdev: device structure + @width: viewport width + @height: viewport height + @frame: framerate, in fps + @compression: preferred compression ratio + @snapshot: snapshot mode or streaming + */ +int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot) +{ + int ret, size; + + Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette); + size = pwc_decode_size(pdev, width, height); + if (size < 0) { + Debug("Could not find suitable size.\n"); + return -ERANGE; + } + Debug("decode_size = %d.\n", size); + + ret = -EINVAL; + switch(pdev->type) { + case 645: + case 646: + ret = set_video_mode_Nala(pdev, size, frames); + break; + + case 675: + case 680: + case 690: + ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot); + break; + + case 720: + case 730: + case 740: + case 750: + ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot); + break; + } + if (ret < 0) { + if (ret == -ENOENT) + Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames); + else { + Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); + } + return ret; + } + pdev->view.x = width; + pdev->view.y = height; + pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; + pwc_set_image_buffer_size(pdev); + Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y); + return 0; +} + + +/* BRIGHTNESS */ + +int pwc_get_brightness(struct pwc_device *pdev) +{ + char buf; + int ret; + + ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); + if (ret < 0) + return ret; + return buf << 9; +} + +int pwc_set_brightness(struct pwc_device *pdev, int value) +{ + char buf; + + if (value < 0) + value = 0; + if (value > 0xffff) + value = 0xffff; + buf = (value >> 9) & 0x7f; + return SendControlMsg(SET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); +} + +/* CONTRAST */ + +int pwc_get_contrast(struct pwc_device *pdev) +{ + char buf; + int ret; + + ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1); + if (ret < 0) + return ret; + return buf << 10; +} + +int pwc_set_contrast(struct pwc_device *pdev, int value) +{ + char buf; + + if (value < 0) + value = 0; + if (value > 0xffff) + value = 0xffff; + buf = (value >> 10) & 0x3f; + return SendControlMsg(SET_LUM_CTL, CONTRAST_FORMATTER, 1); +} + +/* GAMMA */ + +int pwc_get_gamma(struct pwc_device *pdev) +{ + char buf; + int ret; + + ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1); + if (ret < 0) + return ret; + return buf << 11; +} + +int pwc_set_gamma(struct pwc_device *pdev, int value) +{ + char buf; + + if (value < 0) + value = 0; + if (value > 0xffff) + value = 0xffff; + buf = (value >> 11) & 0x1f; + return SendControlMsg(SET_LUM_CTL, GAMMA_FORMATTER, 1); +} + + +/* SATURATION */ + +int pwc_get_saturation(struct pwc_device *pdev) +{ + char buf; + int ret; + + if (pdev->type < 675) + return -1; + ret = RecvControlMsg(GET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1); + if (ret < 0) + return ret; + return 32768 + buf * 327; +} + +int pwc_set_saturation(struct pwc_device *pdev, int value) +{ + char buf; + + if (pdev->type < 675) + return -EINVAL; + if (value < 0) + value = 0; + if (value > 0xffff) + value = 0xffff; + /* saturation ranges from -100 to +100 */ + buf = (value - 32768) / 327; + return SendControlMsg(SET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1); +} + +/* AGC */ + +static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value) +{ + char buf; + int ret; + + if (mode) + buf = 0x0; /* auto */ + else + buf = 0xff; /* fixed */ + + ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1); + + if (!mode && ret >= 0) { + if (value < 0) + value = 0; + if (value > 0xffff) + value = 0xffff; + buf = (value >> 10) & 0x3F; + ret = SendControlMsg(SET_LUM_CTL, PRESET_AGC_FORMATTER, 1); + } + if (ret < 0) + return ret; + return 0; +} + +static inline int pwc_get_agc(struct pwc_device *pdev, int *value) +{ + unsigned char buf; + int ret; + + ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1); + if (ret < 0) + return ret; + + if (buf != 0) { /* fixed */ + ret = RecvControlMsg(GET_LUM_CTL, PRESET_AGC_FORMATTER, 1); + if (ret < 0) + return ret; + if (buf > 0x3F) + buf = 0x3F; + *value = (buf << 10); + } + else { /* auto */ + ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1); + if (ret < 0) + return ret; + /* Gah... this value ranges from 0x00 ... 0x9F */ + if (buf > 0x9F) + buf = 0x9F; + *value = -(48 + buf * 409); + } + + return 0; +} + +static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) +{ + char buf[2]; + int speed, ret; + + + if (mode) + buf[0] = 0x0; /* auto */ + else + buf[0] = 0xff; /* fixed */ + + ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1); + + if (!mode && ret >= 0) { + if (value < 0) + value = 0; + if (value > 0xffff) + value = 0xffff; + switch(pdev->type) { + case 675: + case 680: + case 690: + /* speed ranges from 0x0 to 0x290 (656) */ + speed = (value / 100); + buf[1] = speed >> 8; + buf[0] = speed & 0xff; + break; + case 720: + case 730: + case 740: + case 750: + /* speed seems to range from 0x0 to 0xff */ + buf[1] = 0; + buf[0] = value >> 8; + break; + } + + ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2); + } + return ret; +} + + +/* POWER */ + +int pwc_camera_power(struct pwc_device *pdev, int power) +{ + char buf; + + if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6)) + return 0; /* Not supported by Nala or Timon < release 6 */ + + if (power) + buf = 0x00; /* active */ + else + buf = 0xFF; /* power save */ + return SendControlMsg(SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, 1); +} + + + +/* private calls */ + +static inline int pwc_restore_user(struct pwc_device *pdev) +{ + char buf; /* dummy */ + return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0); +} + +static inline int pwc_save_user(struct pwc_device *pdev) +{ + char buf; /* dummy */ + return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0); +} + +static inline int pwc_restore_factory(struct pwc_device *pdev) +{ + char buf; /* dummy */ + return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0); +} + + /* ************************************************* */ + /* Patch by Alvarado: (not in the original version */ + + /* + * the camera recognizes modes from 0 to 4: + * + * 00: indoor (incandescant lighting) + * 01: outdoor (sunlight) + * 02: fluorescent lighting + * 03: manual + * 04: auto + */ +static inline int pwc_set_awb(struct pwc_device *pdev, int mode) +{ + char buf; + int ret; + + if (mode < 0) + mode = 0; + + if (mode > 4) + mode = 4; + + buf = mode & 0x07; /* just the lowest three bits */ + + ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1); + + if (ret < 0) + return ret; + return 0; +} + +static inline int pwc_get_awb(struct pwc_device *pdev) +{ + unsigned char buf; + int ret; + + ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1); + + if (ret < 0) + return ret; + return buf; +} + +static inline int pwc_set_red_gain(struct pwc_device *pdev, int value) +{ + unsigned char buf; + + if (value < 0) + value = 0; + if (value > 0xffff) + value = 0xffff; + /* only the msb is considered */ + buf = value >> 8; + return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); +} + +static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value) +{ + unsigned char buf; + int ret; + + ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); + if (ret < 0) + return ret; + *value = buf << 8; + return 0; +} + + +static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value) +{ + unsigned char buf; + + if (value < 0) + value = 0; + if (value > 0xffff) + value = 0xffff; + /* only the msb is considered */ + buf = value >> 8; + return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); +} + +static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value) +{ + unsigned char buf; + int ret; + + ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); + if (ret < 0) + return ret; + *value = buf << 8; + return 0; +} + + +/* The following two functions are different, since they only read the + internal red/blue gains, which may be different from the manual + gains set or read above. + */ +static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value) +{ + unsigned char buf; + int ret; + + ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1); + if (ret < 0) + return ret; + *value = buf << 8; + return 0; +} + +static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value) +{ + unsigned char buf; + int ret; + + ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1); + if (ret < 0) + return ret; + *value = buf << 8; + return 0; +} + + +static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed) +{ + unsigned char buf; + + /* useful range is 0x01..0x20 */ + buf = speed / 0x7f0; + return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); +} + +static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value) +{ + unsigned char buf; + int ret; + + ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); + if (ret < 0) + return ret; + *value = buf * 0x7f0; + return 0; +} + + +static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay) +{ + unsigned char buf; + + /* useful range is 0x01..0x3F */ + buf = (delay >> 10); + return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); +} + +static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value) +{ + unsigned char buf; + int ret; + + ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); + if (ret < 0) + return ret; + *value = buf << 10; + return 0; +} + + +int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) +{ + unsigned char buf[2]; + + if (pdev->type < 730) + return 0; + on_value /= 100; + off_value /= 100; + if (on_value < 0) + on_value = 0; + if (on_value > 0xff) + on_value = 0xff; + if (off_value < 0) + off_value = 0; + if (off_value > 0xff) + off_value = 0xff; + + buf[0] = on_value; + buf[1] = off_value; + + return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2); +} + +static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) +{ + unsigned char buf[2]; + int ret; + + if (pdev->type < 730) { + *on_value = -1; + *off_value = -1; + return 0; + } + + ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2); + if (ret < 0) + return ret; + *on_value = buf[0] * 100; + *off_value = buf[1] * 100; + return 0; +} + +static inline int pwc_set_contour(struct pwc_device *pdev, int contour) +{ + unsigned char buf; + int ret; + + if (contour < 0) + buf = 0xff; /* auto contour on */ + else + buf = 0x0; /* auto contour off */ + ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); + if (ret < 0) + return ret; + + if (contour < 0) + return 0; + if (contour > 0xffff) + contour = 0xffff; + + buf = (contour >> 10); /* contour preset is [0..3f] */ + ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); + if (ret < 0) + return ret; + return 0; +} + +static inline int pwc_get_contour(struct pwc_device *pdev, int *contour) +{ + unsigned char buf; + int ret; + + ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); + if (ret < 0) + return ret; + + if (buf == 0) { + /* auto mode off, query current preset value */ + ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); + if (ret < 0) + return ret; + *contour = buf << 10; + } + else + *contour = -1; + return 0; +} + + +static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight) +{ + unsigned char buf; + + if (backlight) + buf = 0xff; + else + buf = 0x0; + return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); +} + +static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight) +{ + int ret; + unsigned char buf; + + ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); + if (ret < 0) + return ret; + *backlight = buf; + return 0; +} + + +static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker) +{ + unsigned char buf; + + if (flicker) + buf = 0xff; + else + buf = 0x0; + return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); +} + +static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker) +{ + int ret; + unsigned char buf; + + ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); + if (ret < 0) + return ret; + *flicker = buf; + return 0; +} + + +static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise) +{ + unsigned char buf; + + if (noise < 0) + noise = 0; + if (noise > 3) + noise = 3; + buf = noise; + return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); +} + +static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) +{ + int ret; + unsigned char buf; + + ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); + if (ret < 0) + return ret; + *noise = buf; + return 0; +} + +static int pwc_mpt_reset(struct pwc_device *pdev, int flags) +{ + unsigned char buf; + + buf = flags & 0x03; // only lower two bits are currently used + return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1); +} + +static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) +{ + unsigned char buf[4]; + + /* set new relative angle; angles are expressed in degrees * 100, + but cam as .5 degree resolution, hence divide by 200. Also + the angle must be multiplied by 64 before it's send to + the cam (??) + */ + pan = 64 * pan / 100; + tilt = -64 * tilt / 100; /* positive tilt is down, which is not what the user would expect */ + buf[0] = pan & 0xFF; + buf[1] = (pan >> 8) & 0xFF; + buf[2] = tilt & 0xFF; + buf[3] = (tilt >> 8) & 0xFF; + return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4); +} + +static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status) +{ + int ret; + unsigned char buf[5]; + + ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5); + if (ret < 0) + return ret; + status->status = buf[0] & 0x7; // 3 bits are used for reporting + status->time_pan = (buf[1] << 8) + buf[2]; + status->time_tilt = (buf[3] << 8) + buf[4]; + return 0; +} + + +int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) +{ + unsigned char buf; + int ret = -1, request; + + if (pdev->type < 675) + request = SENSOR_TYPE_FORMATTER1; + else if (pdev->type < 730) + return -1; /* The Vesta series doesn't have this call */ + else + request = SENSOR_TYPE_FORMATTER2; + + ret = RecvControlMsg(GET_STATUS_CTL, request, 1); + if (ret < 0) + return ret; + if (pdev->type < 675) + *sensor = buf | 0x100; + else + *sensor = buf; + return 0; +} + + + /* End of Add-Ons */ + /* ************************************************* */ + + +int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) +{ + int ret = 0; + + switch(cmd) { + case VIDIOCPWCRUSER: + { + if (pwc_restore_user(pdev)) + ret = -EINVAL; + break; + } + + case VIDIOCPWCSUSER: + { + if (pwc_save_user(pdev)) + ret = -EINVAL; + break; + } + + case VIDIOCPWCFACTORY: + { + if (pwc_restore_factory(pdev)) + ret = -EINVAL; + break; + } + + case VIDIOCPWCSCQUAL: + { + int *qual = arg; + + if (*qual < 0 || *qual > 3) + ret = -EINVAL; + else + ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot); + if (ret >= 0) + pdev->vcompression = *qual; + break; + } + + case VIDIOCPWCGCQUAL: + { + int *qual = arg; + *qual = pdev->vcompression; + break; + } + + case VIDIOCPWCPROBE: + { + struct pwc_probe *probe = arg; + strcpy(probe->name, pdev->vdev->name); + probe->type = pdev->type; + break; + } + + case VIDIOCPWCGSERIAL: + { + struct pwc_serial *serial = arg; + strcpy(serial->serial, pdev->serial); + break; + } + + case VIDIOCPWCSAGC: + { + int *agc = arg; + if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc)) + ret = -EINVAL; + break; + } + + case VIDIOCPWCGAGC: + { + int *agc = arg; + + if (pwc_get_agc(pdev, agc)) + ret = -EINVAL; + break; + } + + case VIDIOCPWCSSHUTTER: + { + int *shutter_speed = arg; + ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed); + break; + } + + case VIDIOCPWCSAWB: + { + struct pwc_whitebalance *wb = arg; + + ret = pwc_set_awb(pdev, wb->mode); + if (ret >= 0 && wb->mode == PWC_WB_MANUAL) { + pwc_set_red_gain(pdev, wb->manual_red); + pwc_set_blue_gain(pdev, wb->manual_blue); + } + break; + } + + case VIDIOCPWCGAWB: + { + struct pwc_whitebalance *wb = arg; + + memset(wb, 0, sizeof(struct pwc_whitebalance)); + wb->mode = pwc_get_awb(pdev); + if (wb->mode < 0) + ret = -EINVAL; + else { + if (wb->mode == PWC_WB_MANUAL) { + ret = pwc_get_red_gain(pdev, &wb->manual_red); + if (ret < 0) + break; + ret = pwc_get_blue_gain(pdev, &wb->manual_blue); + if (ret < 0) + break; + } + if (wb->mode == PWC_WB_AUTO) { + ret = pwc_read_red_gain(pdev, &wb->read_red); + if (ret < 0) + break; + ret = pwc_read_blue_gain(pdev, &wb->read_blue); + if (ret < 0) + break; + } + } + break; + } + + case VIDIOCPWCSAWBSPEED: + { + struct pwc_wb_speed *wbs = arg; + + if (wbs->control_speed > 0) { + ret = pwc_set_wb_speed(pdev, wbs->control_speed); + } + if (wbs->control_delay > 0) { + ret = pwc_set_wb_delay(pdev, wbs->control_delay); + } + break; + } + + case VIDIOCPWCGAWBSPEED: + { + struct pwc_wb_speed *wbs = arg; + + ret = pwc_get_wb_speed(pdev, &wbs->control_speed); + if (ret < 0) + break; + ret = pwc_get_wb_delay(pdev, &wbs->control_delay); + if (ret < 0) + break; + break; + } + + case VIDIOCPWCSLED: + { + struct pwc_leds *leds = arg; + ret = pwc_set_leds(pdev, leds->led_on, leds->led_off); + break; + } + + + case VIDIOCPWCGLED: + { + struct pwc_leds *leds = arg; + ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off); + break; + } + + case VIDIOCPWCSCONTOUR: + { + int *contour = arg; + ret = pwc_set_contour(pdev, *contour); + break; + } + + case VIDIOCPWCGCONTOUR: + { + int *contour = arg; + ret = pwc_get_contour(pdev, contour); + break; + } + + case VIDIOCPWCSBACKLIGHT: + { + int *backlight = arg; + ret = pwc_set_backlight(pdev, *backlight); + break; + } + + case VIDIOCPWCGBACKLIGHT: + { + int *backlight = arg; + ret = pwc_get_backlight(pdev, backlight); + break; + } + + case VIDIOCPWCSFLICKER: + { + int *flicker = arg; + ret = pwc_set_flicker(pdev, *flicker); + break; + } + + case VIDIOCPWCGFLICKER: + { + int *flicker = arg; + ret = pwc_get_flicker(pdev, flicker); + break; + } + + case VIDIOCPWCSDYNNOISE: + { + int *dynnoise = arg; + ret = pwc_set_dynamic_noise(pdev, *dynnoise); + break; + } + + case VIDIOCPWCGDYNNOISE: + { + int *dynnoise = arg; + ret = pwc_get_dynamic_noise(pdev, dynnoise); + break; + } + + case VIDIOCPWCGREALSIZE: + { + struct pwc_imagesize *size = arg; + size->width = pdev->image.x; + size->height = pdev->image.y; + break; + } + + case VIDIOCPWCMPTRESET: + { + if (pdev->features & FEATURE_MOTOR_PANTILT) + { + int *flags = arg; + + ret = pwc_mpt_reset(pdev, *flags); + if (ret >= 0) + { + pdev->pan_angle = 0; + pdev->tilt_angle = 0; + } + } + else + { + ret = -ENXIO; + } + break; + } + + case VIDIOCPWCMPTGRANGE: + { + if (pdev->features & FEATURE_MOTOR_PANTILT) + { + struct pwc_mpt_range *range = arg; + *range = pdev->angle_range; + } + else + { + ret = -ENXIO; + } + break; + } + + case VIDIOCPWCMPTSANGLE: + { + int new_pan, new_tilt; + + if (pdev->features & FEATURE_MOTOR_PANTILT) + { + struct pwc_mpt_angles *angles = arg; + /* The camera can only set relative angles, so + do some calculations when getting an absolute angle . + */ + if (angles->absolute) + { + new_pan = angles->pan; + new_tilt = angles->tilt; + } + else + { + new_pan = pdev->pan_angle + angles->pan; + new_tilt = pdev->tilt_angle + angles->tilt; + } + /* check absolute ranges */ + if (new_pan < pdev->angle_range.pan_min || + new_pan > pdev->angle_range.pan_max || + new_tilt < pdev->angle_range.tilt_min || + new_tilt > pdev->angle_range.tilt_max) + { + ret = -ERANGE; + } + else + { + /* go to relative range, check again */ + new_pan -= pdev->pan_angle; + new_tilt -= pdev->tilt_angle; + /* angles are specified in degrees * 100, thus the limit = 36000 */ + if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000) + ret = -ERANGE; + } + if (ret == 0) /* no errors so far */ + { + ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt); + if (ret >= 0) + { + pdev->pan_angle += new_pan; + pdev->tilt_angle += new_tilt; + } + if (ret == -EPIPE) /* stall -> out of range */ + ret = -ERANGE; + } + } + else + { + ret = -ENXIO; + } + break; + } + + case VIDIOCPWCMPTGANGLE: + { + + if (pdev->features & FEATURE_MOTOR_PANTILT) + { + struct pwc_mpt_angles *angles = arg; + + angles->absolute = 1; + angles->pan = pdev->pan_angle; + angles->tilt = pdev->tilt_angle; + } + else + { + ret = -ENXIO; + } + break; + } + + case VIDIOCPWCMPTSTATUS: + { + if (pdev->features & FEATURE_MOTOR_PANTILT) + { + struct pwc_mpt_status *status = arg; + ret = pwc_mpt_get_status(pdev, status); + } + else + { + ret = -ENXIO; + } + break; + } + + case VIDIOCPWCGVIDCMD: + { + struct pwc_video_command *cmd = arg; + + cmd->type = pdev->type; + cmd->release = pdev->release; + cmd->command_len = pdev->cmd_len; + memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len); + cmd->bandlength = pdev->vbandlength; + cmd->frame_size = pdev->frame_size; + break; + } + /* + case VIDIOCPWCGVIDTABLE: + { + struct pwc_table_init_buffer *table = arg; + table->len = pdev->cmd_len; + memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size); + break; + } + */ + + default: + ret = -ENOIOCTLCMD; + break; + } + + if (ret > 0) + return 0; + return ret; +} + + + diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c new file mode 100644 index 000000000000..90eb26042817 --- /dev/null +++ b/drivers/media/video/pwc/pwc-if.c @@ -0,0 +1,2205 @@ +/* Linux driver for Philips webcam + USB and Video4Linux interface part. + (C) 1999-2004 Nemosoft Unv. + (C) 2004 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + 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 + +*/ + +/* + This code forms the interface between the USB layers and the Philips + specific stuff. Some adanved stuff of the driver falls under an + NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and + is thus not distributed in source form. The binary pwcx.o module + contains the code that falls under the NDA. + + In case you're wondering: 'pwc' stands for "Philips WebCam", but + I really didn't want to type 'philips_web_cam' every time (I'm lazy as + any Linux kernel hacker, but I don't like uncomprehensible abbreviations + without explanation). + + Oh yes, convention: to disctinguish between all the various pointers to + device-structures, I use these names for the pointer variables: + udev: struct usb_device * + vdev: struct video_device * + pdev: struct pwc_devive * +*/ + +/* Contributors: + - Alvarado: adding whitebalance code + - Alistar Moire: QuickCam 3000 Pro device/product ID + - Tony Hoyle: Creative Labs Webcam 5 device/product ID + - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged + - Jk Fang: Sotec Afina Eye ID + - Xavier Roche: QuickCam Pro 4000 ID + - Jens Knudsen: QuickCam Zoom ID + - J. Debert: QuickCam for Notebooks ID +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pwc.h" +#include "pwc-ioctl.h" +#include "pwc-kiara.h" +#include "pwc-timon.h" +#include "pwc-uncompress.h" + +/* Function prototypes and driver templates */ + +/* hotplug device table support */ +static struct usb_device_id pwc_device_table [] = { + { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */ + { USB_DEVICE(0x0471, 0x0303) }, + { USB_DEVICE(0x0471, 0x0304) }, + { USB_DEVICE(0x0471, 0x0307) }, + { USB_DEVICE(0x0471, 0x0308) }, + { USB_DEVICE(0x0471, 0x030C) }, + { USB_DEVICE(0x0471, 0x0310) }, + { USB_DEVICE(0x0471, 0x0311) }, + { USB_DEVICE(0x0471, 0x0312) }, + { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ + { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ + { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ + { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ + { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */ + { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */ + { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */ + { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */ + { USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */ + { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */ + { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */ + { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */ + { USB_DEVICE(0x055D, 0x9001) }, + { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ + { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */ + { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */ + { USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */ + { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */ + { USB_DEVICE(0x0d81, 0x1900) }, + { } +}; +MODULE_DEVICE_TABLE(usb, pwc_device_table); + +static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id); +static void usb_pwc_disconnect(struct usb_interface *intf); + +static struct usb_driver pwc_driver = { + .name = "Philips webcam", /* name */ + .id_table = pwc_device_table, + .probe = usb_pwc_probe, /* probe() */ + .disconnect = usb_pwc_disconnect, /* disconnect() */ +}; + +#define MAX_DEV_HINTS 20 +#define MAX_ISOC_ERRORS 20 + +static int default_size = PSZ_QCIF; +static int default_fps = 10; +static int default_fbufs = 3; /* Default number of frame buffers */ +static int default_mbufs = 2; /* Default number of mmap() buffers */ + int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX; +static int power_save = 0; +static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ +static int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */ +static struct { + int type; + char serial_number[30]; + int device_node; + struct pwc_device *pdev; +} device_hint[MAX_DEV_HINTS]; + +/***/ + +static int pwc_video_open(struct inode *inode, struct file *file); +static int pwc_video_close(struct inode *inode, struct file *file); +static ssize_t pwc_video_read(struct file *file, char __user * buf, + size_t count, loff_t *ppos); +static unsigned int pwc_video_poll(struct file *file, poll_table *wait); +static int pwc_video_ioctl(struct inode *inode, struct file *file, + unsigned int ioctlnr, unsigned long arg); +static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma); + +static struct file_operations pwc_fops = { + .owner = THIS_MODULE, + .open = pwc_video_open, + .release = pwc_video_close, + .read = pwc_video_read, + .poll = pwc_video_poll, + .mmap = pwc_video_mmap, + .ioctl = pwc_video_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .llseek = no_llseek, +}; +static struct video_device pwc_template = { + .owner = THIS_MODULE, + .name = "Philips Webcam", /* Filled in later */ + .type = VID_TYPE_CAPTURE, + .hardware = VID_HARDWARE_PWC, + .release = video_device_release, + .fops = &pwc_fops, + .minor = -1, +}; + +/***************************************************************************/ + +/* Okay, this is some magic that I worked out and the reasoning behind it... + + The biggest problem with any USB device is of course: "what to do + when the user unplugs the device while it is in use by an application?" + We have several options: + 1) Curse them with the 7 plagues when they do (requires divine intervention) + 2) Tell them not to (won't work: they'll do it anyway) + 3) Oops the kernel (this will have a negative effect on a user's uptime) + 4) Do something sensible. + + Of course, we go for option 4. + + It happens that this device will be linked to two times, once from + usb_device and once from the video_device in their respective 'private' + pointers. This is done when the device is probed() and all initialization + succeeded. The pwc_device struct links back to both structures. + + When a device is unplugged while in use it will be removed from the + list of known USB devices; I also de-register it as a V4L device, but + unfortunately I can't free the memory since the struct is still in use + by the file descriptor. This free-ing is then deferend until the first + opportunity. Crude, but it works. + + A small 'advantage' is that if a user unplugs the cam and plugs it back + in, it should get assigned the same video device minor, but unfortunately + it's non-trivial to re-link the cam back to the video device... (that + would surely be magic! :)) +*/ + +/***************************************************************************/ +/* Private functions */ + +/* Here we want the physical address of the memory. + * This is used when initializing the contents of the area. + */ +static inline unsigned long kvirt_to_pa(unsigned long adr) +{ + unsigned long kva, ret; + + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ + ret = __pa(kva); + return ret; +} + +static void * rvmalloc(unsigned long size) +{ + void * mem; + unsigned long adr; + + size=PAGE_ALIGN(size); + mem=vmalloc_32(size); + if (mem) + { + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr=(unsigned long) mem; + while (size > 0) + { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr+=PAGE_SIZE; + size-=PAGE_SIZE; + } + } + return mem; +} + +static void rvfree(void * mem, unsigned long size) +{ + unsigned long adr; + + if (mem) + { + adr=(unsigned long) mem; + while ((long) size > 0) + { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr+=PAGE_SIZE; + size-=PAGE_SIZE; + } + vfree(mem); + } +} + + + + +static int pwc_allocate_buffers(struct pwc_device *pdev) +{ + int i; + void *kbuf; + + Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev); + + if (pdev == NULL) + return -ENXIO; + +#ifdef PWC_MAGIC + if (pdev->magic != PWC_MAGIC) { + Err("allocate_buffers(): magic failed.\n"); + return -ENXIO; + } +#endif + /* Allocate Isochronous pipe buffers */ + for (i = 0; i < MAX_ISO_BUFS; i++) { + if (pdev->sbuf[i].data == NULL) { + kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL); + if (kbuf == NULL) { + Err("Failed to allocate iso buffer %d.\n", i); + return -ENOMEM; + } + Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf); + pdev->sbuf[i].data = kbuf; + memset(kbuf, 0, ISO_BUFFER_SIZE); + } + } + + /* Allocate frame buffer structure */ + if (pdev->fbuf == NULL) { + kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL); + if (kbuf == NULL) { + Err("Failed to allocate frame buffer structure.\n"); + return -ENOMEM; + } + Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf); + pdev->fbuf = kbuf; + memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf)); + } + /* create frame buffers, and make circular ring */ + for (i = 0; i < default_fbufs; i++) { + if (pdev->fbuf[i].data == NULL) { + kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ + if (kbuf == NULL) { + Err("Failed to allocate frame buffer %d.\n", i); + return -ENOMEM; + } + Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf); + pdev->fbuf[i].data = kbuf; + memset(kbuf, 128, PWC_FRAME_SIZE); + } + } + + /* Allocate decompressor table space */ + kbuf = NULL; + switch (pdev->type) + { + case 675: + case 680: + case 690: + case 720: + case 730: + case 740: + case 750: +#if 0 + Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private)); + kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */ + break; + case 645: + case 646: + /* TODO & FIXME */ + kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); + break; +#endif + ; + } + pdev->decompress_data = kbuf; + + /* Allocate image buffer; double buffer for mmap() */ + kbuf = rvmalloc(default_mbufs * pdev->len_per_image); + if (kbuf == NULL) { + Err("Failed to allocate image buffer(s). needed (%d)\n",default_mbufs * pdev->len_per_image); + return -ENOMEM; + } + Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf); + pdev->image_data = kbuf; + for (i = 0; i < default_mbufs; i++) + pdev->image_ptr[i] = kbuf + i * pdev->len_per_image; + for (; i < MAX_IMAGES; i++) + pdev->image_ptr[i] = NULL; + + kbuf = NULL; + + Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n"); + return 0; +} + +static void pwc_free_buffers(struct pwc_device *pdev) +{ + int i; + + Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev); + + if (pdev == NULL) + return; +#ifdef PWC_MAGIC + if (pdev->magic != PWC_MAGIC) { + Err("free_buffers(): magic failed.\n"); + return; + } +#endif + + /* Release Iso-pipe buffers */ + for (i = 0; i < MAX_ISO_BUFS; i++) + if (pdev->sbuf[i].data != NULL) { + Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data); + kfree(pdev->sbuf[i].data); + pdev->sbuf[i].data = NULL; + } + + /* The same for frame buffers */ + if (pdev->fbuf != NULL) { + for (i = 0; i < default_fbufs; i++) { + if (pdev->fbuf[i].data != NULL) { + Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data); + vfree(pdev->fbuf[i].data); + pdev->fbuf[i].data = NULL; + } + } + kfree(pdev->fbuf); + pdev->fbuf = NULL; + } + + /* Intermediate decompression buffer & tables */ + if (pdev->decompress_data != NULL) { + Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data); + kfree(pdev->decompress_data); + pdev->decompress_data = NULL; + } + pdev->decompressor = NULL; + + /* Release image buffers */ + if (pdev->image_data != NULL) { + Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data); + rvfree(pdev->image_data, default_mbufs * pdev->len_per_image); + } + pdev->image_data = NULL; + + Trace(TRACE_MEMORY, "Leaving free_buffers().\n"); +} + +/* The frame & image buffer mess. + + Yes, this is a mess. Well, it used to be simple, but alas... In this + module, 3 buffers schemes are used to get the data from the USB bus to + the user program. The first scheme involves the ISO buffers (called thus + since they transport ISO data from the USB controller), and not really + interesting. Suffices to say the data from this buffer is quickly + gathered in an interrupt handler (pwc_isoc_handler) and placed into the + frame buffer. + + The frame buffer is the second scheme, and is the central element here. + It collects the data from a single frame from the camera (hence, the + name). Frames are delimited by the USB camera with a short USB packet, + so that's easy to detect. The frame buffers form a list that is filled + by the camera+USB controller and drained by the user process through + either read() or mmap(). + + The image buffer is the third scheme, in which frames are decompressed + and converted into planar format. For mmap() there is more than + one image buffer available. + + The frame buffers provide the image buffering. In case the user process + is a bit slow, this introduces lag and some undesired side-effects. + The problem arises when the frame buffer is full. I used to drop the last + frame, which makes the data in the queue stale very quickly. But dropping + the frame at the head of the queue proved to be a litte bit more difficult. + I tried a circular linked scheme, but this introduced more problems than + it solved. + + Because filling and draining are completely asynchronous processes, this + requires some fiddling with pointers and mutexes. + + Eventually, I came up with a system with 2 lists: an 'empty' frame list + and a 'full' frame list: + * Initially, all frame buffers but one are on the 'empty' list; the one + remaining buffer is our initial fill frame. + * If a frame is needed for filling, we try to take it from the 'empty' + list, unless that list is empty, in which case we take the buffer at + the head of the 'full' list. + * When our fill buffer has been filled, it is appended to the 'full' + list. + * If a frame is needed by read() or mmap(), it is taken from the head of + the 'full' list, handled, and then appended to the 'empty' list. If no + buffer is present on the 'full' list, we wait. + The advantage is that the buffer that is currently being decompressed/ + converted, is on neither list, and thus not in our way (any other scheme + I tried had the problem of old data lingering in the queue). + + Whatever strategy you choose, it always remains a tradeoff: with more + frame buffers the chances of a missed frame are reduced. On the other + hand, on slower machines it introduces lag because the queue will + always be full. + */ + +/** + \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first. + */ +static inline int pwc_next_fill_frame(struct pwc_device *pdev) +{ + int ret; + unsigned long flags; + + ret = 0; + spin_lock_irqsave(&pdev->ptrlock, flags); + if (pdev->fill_frame != NULL) { + /* append to 'full' list */ + if (pdev->full_frames == NULL) { + pdev->full_frames = pdev->fill_frame; + pdev->full_frames_tail = pdev->full_frames; + } + else { + pdev->full_frames_tail->next = pdev->fill_frame; + pdev->full_frames_tail = pdev->fill_frame; + } + } + if (pdev->empty_frames != NULL) { + /* We have empty frames available. That's easy */ + pdev->fill_frame = pdev->empty_frames; + pdev->empty_frames = pdev->empty_frames->next; + } + else { + /* Hmm. Take it from the full list */ +#if PWC_DEBUG + /* sanity check */ + if (pdev->full_frames == NULL) { + Err("Neither empty or full frames available!\n"); + spin_unlock_irqrestore(&pdev->ptrlock, flags); + return -EINVAL; + } +#endif + pdev->fill_frame = pdev->full_frames; + pdev->full_frames = pdev->full_frames->next; + ret = 1; + } + pdev->fill_frame->next = NULL; +#if PWC_DEBUG + Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence); + pdev->fill_frame->sequence = pdev->sequence++; +#endif + spin_unlock_irqrestore(&pdev->ptrlock, flags); + return ret; +} + + +/** + \brief Reset all buffers, pointers and lists, except for the image_used[] buffer. + + If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble. + */ +static void pwc_reset_buffers(struct pwc_device *pdev) +{ + int i; + unsigned long flags; + + spin_lock_irqsave(&pdev->ptrlock, flags); + pdev->full_frames = NULL; + pdev->full_frames_tail = NULL; + for (i = 0; i < default_fbufs; i++) { + pdev->fbuf[i].filled = 0; + if (i > 0) + pdev->fbuf[i].next = &pdev->fbuf[i - 1]; + else + pdev->fbuf->next = NULL; + } + pdev->empty_frames = &pdev->fbuf[default_fbufs - 1]; + pdev->empty_frames_tail = pdev->fbuf; + pdev->read_frame = NULL; + pdev->fill_frame = pdev->empty_frames; + pdev->empty_frames = pdev->empty_frames->next; + + pdev->image_read_pos = 0; + pdev->fill_image = 0; + spin_unlock_irqrestore(&pdev->ptrlock, flags); +} + + +/** + \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers. + */ +static int pwc_handle_frame(struct pwc_device *pdev) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&pdev->ptrlock, flags); + /* First grab our read_frame; this is removed from all lists, so + we can release the lock after this without problems */ + if (pdev->read_frame != NULL) { + /* This can't theoretically happen */ + Err("Huh? Read frame still in use?\n"); + } + else { + if (pdev->full_frames == NULL) { + Err("Woops. No frames ready.\n"); + } + else { + pdev->read_frame = pdev->full_frames; + pdev->full_frames = pdev->full_frames->next; + pdev->read_frame->next = NULL; + } + + if (pdev->read_frame != NULL) { +#if PWC_DEBUG + Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence); +#endif + /* Decompression is a lenghty process, so it's outside of the lock. + This gives the isoc_handler the opportunity to fill more frames + in the mean time. + */ + spin_unlock_irqrestore(&pdev->ptrlock, flags); + ret = pwc_decompress(pdev); + spin_lock_irqsave(&pdev->ptrlock, flags); + + /* We're done with read_buffer, tack it to the end of the empty buffer list */ + if (pdev->empty_frames == NULL) { + pdev->empty_frames = pdev->read_frame; + pdev->empty_frames_tail = pdev->empty_frames; + } + else { + pdev->empty_frames_tail->next = pdev->read_frame; + pdev->empty_frames_tail = pdev->read_frame; + } + pdev->read_frame = NULL; + } + } + spin_unlock_irqrestore(&pdev->ptrlock, flags); + return ret; +} + +/** + \brief Advance pointers of image buffer (after each user request) +*/ +static inline void pwc_next_image(struct pwc_device *pdev) +{ + pdev->image_used[pdev->fill_image] = 0; + pdev->fill_image = (pdev->fill_image + 1) % default_mbufs; +} + + +/* This gets called for the Isochronous pipe (video). This is done in + * interrupt time, so it has to be fast, not crash, and not stall. Neat. + */ +static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) +{ + struct pwc_device *pdev; + int i, fst, flen; + int awake; + struct pwc_frame_buf *fbuf; + unsigned char *fillptr = NULL, *iso_buf = NULL; + + awake = 0; + pdev = (struct pwc_device *)urb->context; + if (pdev == NULL) { + Err("isoc_handler() called with NULL device?!\n"); + return; + } +#ifdef PWC_MAGIC + if (pdev->magic != PWC_MAGIC) { + Err("isoc_handler() called with bad magic!\n"); + return; + } +#endif + if (urb->status == -ENOENT || urb->status == -ECONNRESET) { + Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); + return; + } + if (urb->status != -EINPROGRESS && urb->status != 0) { + const char *errmsg; + + errmsg = "Unknown"; + switch(urb->status) { + case -ENOSR: errmsg = "Buffer error (overrun)"; break; + case -EPIPE: errmsg = "Stalled (device not responding)"; break; + case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break; + case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break; + case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break; + case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break; + } + Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); + /* Give up after a number of contiguous errors on the USB bus. + Appearantly something is wrong so we simulate an unplug event. + */ + if (++pdev->visoc_errors > MAX_ISOC_ERRORS) + { + Info("Too many ISOC errors, bailing out.\n"); + pdev->error_status = EIO; + awake = 1; + wake_up_interruptible(&pdev->frameq); + } + goto handler_end; // ugly, but practical + } + + fbuf = pdev->fill_frame; + if (fbuf == NULL) { + Err("pwc_isoc_handler without valid fill frame.\n"); + awake = 1; + goto handler_end; + } + else { + fillptr = fbuf->data + fbuf->filled; + } + + /* Reset ISOC error counter. We did get here, after all. */ + pdev->visoc_errors = 0; + + /* vsync: 0 = don't copy data + 1 = sync-hunt + 2 = synched + */ + /* Compact data */ + for (i = 0; i < urb->number_of_packets; i++) { + fst = urb->iso_frame_desc[i].status; + flen = urb->iso_frame_desc[i].actual_length; + iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + if (fst == 0) { + if (flen > 0) { /* if valid data... */ + if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */ + pdev->vsync = 2; + + /* ...copy data to frame buffer, if possible */ + if (flen + fbuf->filled > pdev->frame_total_size) { + Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size); + pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */ + pdev->vframes_error++; + } + else { + memmove(fillptr, iso_buf, flen); + fillptr += flen; + } + } + fbuf->filled += flen; + } /* ..flen > 0 */ + + if (flen < pdev->vlast_packet_size) { + /* Shorter packet... We probably have the end of an image-frame; + wake up read() process and let select()/poll() do something. + Decompression is done in user time over there. + */ + if (pdev->vsync == 2) { + /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus + frames on the USB wire after an exposure change. This conditition is + however detected in the cam and a bit is set in the header. + */ + if (pdev->type == 730) { + unsigned char *ptr = (unsigned char *)fbuf->data; + + if (ptr[1] == 1 && ptr[0] & 0x10) { +#if PWC_DEBUG + Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence); +#endif + pdev->drop_frames += 2; + pdev->vframes_error++; + } + if ((ptr[0] ^ pdev->vmirror) & 0x01) { + if (ptr[0] & 0x01) + Info("Snapshot button pressed.\n"); + else + Info("Snapshot button released.\n"); + } + if ((ptr[0] ^ pdev->vmirror) & 0x02) { + if (ptr[0] & 0x02) + Info("Image is mirrored.\n"); + else + Info("Image is normal.\n"); + } + pdev->vmirror = ptr[0] & 0x03; + /* Sometimes the trailer of the 730 is still sent as a 4 byte packet + after a short frame; this condition is filtered out specifically. A 4 byte + frame doesn't make sense anyway. + So we get either this sequence: + drop_bit set -> 4 byte frame -> short frame -> good frame + Or this one: + drop_bit set -> short frame -> good frame + So we drop either 3 or 2 frames in all! + */ + if (fbuf->filled == 4) + pdev->drop_frames++; + } + + /* In case we were instructed to drop the frame, do so silently. + The buffer pointers are not updated either (but the counters are reset below). + */ + if (pdev->drop_frames > 0) + pdev->drop_frames--; + else { + /* Check for underflow first */ + if (fbuf->filled < pdev->frame_total_size) { + Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled); + pdev->vframes_error++; + } + else { + /* Send only once per EOF */ + awake = 1; /* delay wake_ups */ + + /* Find our next frame to fill. This will always succeed, since we + * nick a frame from either empty or full list, but if we had to + * take it from the full list, it means a frame got dropped. + */ + if (pwc_next_fill_frame(pdev)) { + pdev->vframes_dumped++; + if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) { + if (pdev->vframes_dumped < 20) + Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count); + if (pdev->vframes_dumped == 20) + Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count); + } + } + fbuf = pdev->fill_frame; + } + } /* !drop_frames */ + pdev->vframe_count++; + } + fbuf->filled = 0; + fillptr = fbuf->data; + pdev->vsync = 1; + } /* .. flen < last_packet_size */ + pdev->vlast_packet_size = flen; + } /* ..status == 0 */ +#if PWC_DEBUG + /* This is normally not interesting to the user, unless you are really debugging something */ + else { + static int iso_error = 0; + iso_error++; + if (iso_error < 20) + Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst); + } +#endif + } + +handler_end: + if (awake) + wake_up_interruptible(&pdev->frameq); + + urb->dev = pdev->udev; + i = usb_submit_urb(urb, GFP_ATOMIC); + if (i != 0) + Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i); +} + + +static int pwc_isoc_init(struct pwc_device *pdev) +{ + struct usb_device *udev; + struct urb *urb; + int i, j, ret; + + struct usb_interface *intf; + struct usb_host_interface *idesc = NULL; + + if (pdev == NULL) + return -EFAULT; + if (pdev->iso_init) + return 0; + pdev->vsync = 0; + udev = pdev->udev; + + /* Get the current alternate interface, adjust packet size */ + if (!udev->actconfig) + return -EFAULT; + + intf = usb_ifnum_to_if(udev, 0); + if (intf) + idesc = usb_altnum_to_altsetting(intf, pdev->valternate); + + if (!idesc) + return -EFAULT; + + /* Search video endpoint */ + pdev->vmax_packet_size = -1; + for (i = 0; i < idesc->desc.bNumEndpoints; i++) + if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) { + pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize); + break; + } + + if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { + Err("Failed to find packet size for video endpoint in current alternate setting.\n"); + return -ENFILE; /* Odd error, that should be noticeable */ + } + + /* Set alternate interface */ + ret = 0; + Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate); + ret = usb_set_interface(pdev->udev, 0, pdev->valternate); + if (ret < 0) + return ret; + + for (i = 0; i < MAX_ISO_BUFS; i++) { + urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); + if (urb == NULL) { + Err("Failed to allocate urb %d\n", i); + ret = -ENOMEM; + break; + } + pdev->sbuf[i].urb = urb; + Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb); + } + if (ret) { + /* De-allocate in reverse order */ + while (i >= 0) { + if (pdev->sbuf[i].urb != NULL) + usb_free_urb(pdev->sbuf[i].urb); + pdev->sbuf[i].urb = NULL; + i--; + } + return ret; + } + + /* init URB structure */ + for (i = 0; i < MAX_ISO_BUFS; i++) { + urb = pdev->sbuf[i].urb; + + urb->interval = 1; // devik + urb->dev = udev; + urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = pdev->sbuf[i].data; + urb->transfer_buffer_length = ISO_BUFFER_SIZE; + urb->complete = pwc_isoc_handler; + urb->context = pdev; + urb->start_frame = 0; + urb->number_of_packets = ISO_FRAMES_PER_DESC; + for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { + urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; + urb->iso_frame_desc[j].length = pdev->vmax_packet_size; + } + } + + /* link */ + for (i = 0; i < MAX_ISO_BUFS; i++) { + ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL); + if (ret) + Err("isoc_init() submit_urb %d failed with error %d\n", i, ret); + else + Trace(TRACE_MEMORY, "URB 0x%p submitted.\n", pdev->sbuf[i].urb); + } + + /* All is done... */ + pdev->iso_init = 1; + Trace(TRACE_OPEN, "<< pwc_isoc_init()\n"); + return 0; +} + +static void pwc_isoc_cleanup(struct pwc_device *pdev) +{ + int i; + + Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n"); + if (pdev == NULL) + return; + + /* Unlinking ISOC buffers one by one */ + for (i = 0; i < MAX_ISO_BUFS; i++) { + struct urb *urb; + + urb = pdev->sbuf[i].urb; + if (urb != 0) { + if (pdev->iso_init) { + Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb); + usb_kill_urb(urb); + } + Trace(TRACE_MEMORY, "Freeing URB\n"); + usb_free_urb(urb); + pdev->sbuf[i].urb = NULL; + } + } + + /* Stop camera, but only if we are sure the camera is still there (unplug + is signalled by EPIPE) + */ + if (pdev->error_status && pdev->error_status != EPIPE) { + Trace(TRACE_OPEN, "Setting alternate interface 0.\n"); + usb_set_interface(pdev->udev, 0, 0); + } + + pdev->iso_init = 0; + Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n"); +} + +int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot) +{ + int ret, start; + + /* Stop isoc stuff */ + pwc_isoc_cleanup(pdev); + /* Reset parameters */ + pwc_reset_buffers(pdev); + /* Try to set video mode... */ + start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); + if (ret) { + Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n"); + /* That failed... restore old mode (we know that worked) */ + start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); + if (start) { + Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n"); + } + } + if (start == 0) + { + if (pwc_isoc_init(pdev) < 0) + { + Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n"); + ret = -EAGAIN; /* let's try again, who knows if it works a second time */ + } + } + pdev->drop_frames++; /* try to avoid garbage during switch */ + return ret; /* Return original error code */ +} + + +/***************************************************************************/ +/* Video4Linux functions */ + +static int pwc_video_open(struct inode *inode, struct file *file) +{ + int i; + struct video_device *vdev = video_devdata(file); + struct pwc_device *pdev; + + Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev); + + pdev = (struct pwc_device *)vdev->priv; + if (pdev == NULL) + BUG(); + if (pdev->vopen) + return -EBUSY; + + down(&pdev->modlock); + if (!pdev->usb_init) { + Trace(TRACE_OPEN, "Doing first time initialization.\n"); + pdev->usb_init = 1; + + if (pwc_trace & TRACE_OPEN) + { + /* Query sensor type */ + const char *sensor_type = NULL; + int ret; + + ret = pwc_get_cmos_sensor(pdev, &i); + if (ret >= 0) + { + switch(i) { + case 0x00: sensor_type = "Hyundai CMOS sensor"; break; + case 0x20: sensor_type = "Sony CCD sensor + TDA8787"; break; + case 0x2E: sensor_type = "Sony CCD sensor + Exas 98L59"; break; + case 0x2F: sensor_type = "Sony CCD sensor + ADI 9804"; break; + case 0x30: sensor_type = "Sharp CCD sensor + TDA8787"; break; + case 0x3E: sensor_type = "Sharp CCD sensor + Exas 98L59"; break; + case 0x3F: sensor_type = "Sharp CCD sensor + ADI 9804"; break; + case 0x40: sensor_type = "UPA 1021 sensor"; break; + case 0x100: sensor_type = "VGA sensor"; break; + case 0x101: sensor_type = "PAL MR sensor"; break; + default: sensor_type = "unknown type of sensor"; break; + } + } + if (sensor_type != NULL) + Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i); + } + } + + /* Turn on camera */ + if (power_save) { + i = pwc_camera_power(pdev, 1); + if (i < 0) + Info("Failed to restore power to the camera! (%d)\n", i); + } + /* Set LED on/off time */ + if (pwc_set_leds(pdev, led_on, led_off) < 0) + Info("Failed to set LED on/off time.\n"); + + pwc_construct(pdev); /* set min/max sizes correct */ + + /* So far, so good. Allocate memory. */ + i = pwc_allocate_buffers(pdev); + if (i < 0) { + Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n"); + up(&pdev->modlock); + return i; + } + + /* Reset buffers & parameters */ + pwc_reset_buffers(pdev); + for (i = 0; i < default_mbufs; i++) + pdev->image_used[i] = 0; + pdev->vframe_count = 0; + pdev->vframes_dumped = 0; + pdev->vframes_error = 0; + pdev->visoc_errors = 0; + pdev->error_status = 0; +#if PWC_DEBUG + pdev->sequence = 0; +#endif + pwc_construct(pdev); /* set min/max sizes correct */ + + /* Set some defaults */ + pdev->vsnapshot = 0; + + /* Start iso pipe for video; first try the last used video size + (or the default one); if that fails try QCIF/10 or QSIF/10; + it that fails too, give up. + */ + i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0); + if (i) { + Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n"); + if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750) + i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0); + else + i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0); + } + if (i) { + Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n"); + up(&pdev->modlock); + return i; + } + + i = pwc_isoc_init(pdev); + if (i) { + Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i); + up(&pdev->modlock); + return i; + } + + pdev->vopen++; + file->private_data = vdev; + up(&pdev->modlock); + Trace(TRACE_OPEN, "<< video_open() returns 0.\n"); + return 0; +} + +/* Note that all cleanup is done in the reverse order as in _open */ +static int pwc_video_close(struct inode *inode, struct file *file) +{ + struct video_device *vdev = file->private_data; + struct pwc_device *pdev; + int i; + + Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev); + + pdev = (struct pwc_device *)vdev->priv; + if (pdev->vopen == 0) + Info("video_close() called on closed device?\n"); + + /* Dump statistics, but only if a reasonable amount of frames were + processed (to prevent endless log-entries in case of snap-shot + programs) + */ + if (pdev->vframe_count > 20) + Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error); + + switch (pdev->type) + { + case 675: + case 680: + case 690: + case 720: + case 730: + case 740: + case 750: +/* pwc_dec23_exit(); *//* Timon & Kiara */ + break; + case 645: + case 646: +/* pwc_dec1_exit(); */ + break; + } + + pwc_isoc_cleanup(pdev); + pwc_free_buffers(pdev); + + /* Turn off LEDS and power down camera, but only when not unplugged */ + if (pdev->error_status != EPIPE) { + /* Turn LEDs off */ + if (pwc_set_leds(pdev, 0, 0) < 0) + Info("Failed to set LED on/off time.\n"); + if (power_save) { + i = pwc_camera_power(pdev, 0); + if (i < 0) + Err("Failed to power down camera (%d)\n", i); + } + } + pdev->vopen = 0; + Trace(TRACE_OPEN, "<< video_close()\n"); + return 0; +} + +/* + * FIXME: what about two parallel reads ???? + * ANSWER: Not supported. You can't open the device more than once, + despite what the V4L1 interface says. First, I don't see + the need, second there's no mechanism of alerting the + 2nd/3rd/... process of events like changing image size. + And I don't see the point of blocking that for the + 2nd/3rd/... process. + In multi-threaded environments reading parallel from any + device is tricky anyhow. + */ + +static ssize_t pwc_video_read(struct file *file, char __user * buf, + size_t count, loff_t *ppos) +{ + struct video_device *vdev = file->private_data; + struct pwc_device *pdev; + int noblock = file->f_flags & O_NONBLOCK; + DECLARE_WAITQUEUE(wait, current); + int bytes_to_read; + + Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count); + if (vdev == NULL) + return -EFAULT; + pdev = vdev->priv; + if (pdev == NULL) + return -EFAULT; + if (pdev->error_status) + return -pdev->error_status; /* Something happened, report what. */ + + /* In case we're doing partial reads, we don't have to wait for a frame */ + if (pdev->image_read_pos == 0) { + /* Do wait queueing according to the (doc)book */ + add_wait_queue(&pdev->frameq, &wait); + while (pdev->full_frames == NULL) { + /* Check for unplugged/etc. here */ + if (pdev->error_status) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -pdev->error_status ; + } + if (noblock) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -EWOULDBLOCK; + } + if (signal_pending(current)) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -ERESTARTSYS; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + + /* Decompress and release frame */ + if (pwc_handle_frame(pdev)) + return -EFAULT; + } + + Trace(TRACE_READ, "Copying data to user space.\n"); + if (pdev->vpalette == VIDEO_PALETTE_RAW) + bytes_to_read = pdev->frame_size; + else + bytes_to_read = pdev->view.size; + + /* copy bytes to user space; we allow for partial reads */ + if (count + pdev->image_read_pos > bytes_to_read) + count = bytes_to_read - pdev->image_read_pos; + if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count)) + return -EFAULT; + pdev->image_read_pos += count; + if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */ + pdev->image_read_pos = 0; + pwc_next_image(pdev); + } + return count; +} + +static unsigned int pwc_video_poll(struct file *file, poll_table *wait) +{ + struct video_device *vdev = file->private_data; + struct pwc_device *pdev; + + if (vdev == NULL) + return -EFAULT; + pdev = vdev->priv; + if (pdev == NULL) + return -EFAULT; + + poll_wait(file, &pdev->frameq, wait); + if (pdev->error_status) + return POLLERR; + if (pdev->full_frames != NULL) /* we have frames waiting */ + return (POLLIN | POLLRDNORM); + + return 0; +} + +static int pwc_video_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct video_device *vdev = file->private_data; + struct pwc_device *pdev; + DECLARE_WAITQUEUE(wait, current); + + if (vdev == NULL) + return -EFAULT; + pdev = vdev->priv; + if (pdev == NULL) + return -EFAULT; + + switch (cmd) { + /* Query cabapilities */ + case VIDIOCGCAP: + { + struct video_capability *caps = arg; + + strcpy(caps->name, vdev->name); + caps->type = VID_TYPE_CAPTURE; + caps->channels = 1; + caps->audios = 1; + caps->minwidth = pdev->view_min.x; + caps->minheight = pdev->view_min.y; + caps->maxwidth = pdev->view_max.x; + caps->maxheight = pdev->view_max.y; + break; + } + + /* Channel functions (simulate 1 channel) */ + case VIDIOCGCHAN: + { + struct video_channel *v = arg; + + if (v->channel != 0) + return -EINVAL; + v->flags = 0; + v->tuners = 0; + v->type = VIDEO_TYPE_CAMERA; + strcpy(v->name, "Webcam"); + return 0; + } + + case VIDIOCSCHAN: + { + /* The spec says the argument is an integer, but + the bttv driver uses a video_channel arg, which + makes sense becasue it also has the norm flag. + */ + struct video_channel *v = arg; + if (v->channel != 0) + return -EINVAL; + return 0; + } + + + /* Picture functions; contrast etc. */ + case VIDIOCGPICT: + { + struct video_picture *p = arg; + int val; + + val = pwc_get_brightness(pdev); + if (val >= 0) + p->brightness = val; + else + p->brightness = 0xffff; + val = pwc_get_contrast(pdev); + if (val >= 0) + p->contrast = val; + else + p->contrast = 0xffff; + /* Gamma, Whiteness, what's the difference? :) */ + val = pwc_get_gamma(pdev); + if (val >= 0) + p->whiteness = val; + else + p->whiteness = 0xffff; + val = pwc_get_saturation(pdev); + if (val >= 0) + p->colour = val; + else + p->colour = 0xffff; + p->depth = 24; + p->palette = pdev->vpalette; + p->hue = 0xFFFF; /* N/A */ + break; + } + + case VIDIOCSPICT: + { + struct video_picture *p = arg; + /* + * FIXME: Suppose we are mid read + ANSWER: No problem: the firmware of the camera + can handle brightness/contrast/etc + changes at _any_ time, and the palette + is used exactly once in the uncompress + routine. + */ + pwc_set_brightness(pdev, p->brightness); + pwc_set_contrast(pdev, p->contrast); + pwc_set_gamma(pdev, p->whiteness); + pwc_set_saturation(pdev, p->colour); + if (p->palette && p->palette != pdev->vpalette) { + switch (p->palette) { + case VIDEO_PALETTE_YUV420P: + case VIDEO_PALETTE_RAW: + pdev->vpalette = p->palette; + return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); + break; + default: + return -EINVAL; + break; + } + } + break; + } + + /* Window/size parameters */ + case VIDIOCGWIN: + { + struct video_window *vw = arg; + + vw->x = 0; + vw->y = 0; + vw->width = pdev->view.x; + vw->height = pdev->view.y; + vw->chromakey = 0; + vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | + (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0); + break; + } + + case VIDIOCSWIN: + { + struct video_window *vw = arg; + int fps, snapshot, ret; + + fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; + snapshot = vw->flags & PWC_FPS_SNAPSHOT; + if (fps == 0) + fps = pdev->vframes; + if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot) + return 0; + ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot); + if (ret) + return ret; + break; + } + + /* We don't have overlay support (yet) */ + case VIDIOCGFBUF: + { + struct video_buffer *vb = arg; + + memset(vb,0,sizeof(*vb)); + break; + } + + /* mmap() functions */ + case VIDIOCGMBUF: + { + /* Tell the user program how much memory is needed for a mmap() */ + struct video_mbuf *vm = arg; + int i; + + memset(vm, 0, sizeof(*vm)); + vm->size = default_mbufs * pdev->len_per_image; + vm->frames = default_mbufs; /* double buffering should be enough for most applications */ + for (i = 0; i < default_mbufs; i++) + vm->offsets[i] = i * pdev->len_per_image; + break; + } + + case VIDIOCMCAPTURE: + { + /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */ + struct video_mmap *vm = arg; + + Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format); + if (vm->frame < 0 || vm->frame >= default_mbufs) + return -EINVAL; + + /* xawtv is nasty. It probes the available palettes + by setting a very small image size and trying + various palettes... The driver doesn't support + such small images, so I'm working around it. + */ + if (vm->format) + { + switch (vm->format) + { + case VIDEO_PALETTE_YUV420P: + case VIDEO_PALETTE_RAW: + break; + default: + return -EINVAL; + break; + } + } + + if ((vm->width != pdev->view.x || vm->height != pdev->view.y) && + (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) { + int ret; + + Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n"); + ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot); + if (ret) + return ret; + } /* ... size mismatch */ + + /* FIXME: should we lock here? */ + if (pdev->image_used[vm->frame]) + return -EBUSY; /* buffer wasn't available. Bummer */ + pdev->image_used[vm->frame] = 1; + + /* Okay, we're done here. In the SYNC call we wait until a + frame comes available, then expand image into the given + buffer. + In contrast to the CPiA cam the Philips cams deliver a + constant stream, almost like a grabber card. Also, + we have separate buffers for the rawdata and the image, + meaning we can nearly always expand into the requested buffer. + */ + Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n"); + break; + } + + case VIDIOCSYNC: + { + /* The doc says: "Whenever a buffer is used it should + call VIDIOCSYNC to free this frame up and continue." + + The only odd thing about this whole procedure is + that MCAPTURE flags the buffer as "in use", and + SYNC immediately unmarks it, while it isn't + after SYNC that you know that the buffer actually + got filled! So you better not start a CAPTURE in + the same frame immediately (use double buffering). + This is not a problem for this cam, since it has + extra intermediate buffers, but a hardware + grabber card will then overwrite the buffer + you're working on. + */ + int *mbuf = arg; + int ret; + + Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", *mbuf); + + /* bounds check */ + if (*mbuf < 0 || *mbuf >= default_mbufs) + return -EINVAL; + /* check if this buffer was requested anyway */ + if (pdev->image_used[*mbuf] == 0) + return -EINVAL; + + /* Add ourselves to the frame wait-queue. + + FIXME: needs auditing for safety. + QUESTION: In what respect? I think that using the + frameq is safe now. + */ + add_wait_queue(&pdev->frameq, &wait); + while (pdev->full_frames == NULL) { + if (pdev->error_status) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -pdev->error_status; + } + + if (signal_pending(current)) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -ERESTARTSYS; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + + /* The frame is ready. Expand in the image buffer + requested by the user. I don't care if you + mmap() 5 buffers and request data in this order: + buffer 4 2 3 0 1 2 3 0 4 3 1 . . . + Grabber hardware may not be so forgiving. + */ + Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n"); + pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */ + /* Decompress, etc */ + ret = pwc_handle_frame(pdev); + pdev->image_used[*mbuf] = 0; + if (ret) + return -EFAULT; + break; + } + + case VIDIOCGAUDIO: + { + struct video_audio *v = arg; + + strcpy(v->name, "Microphone"); + v->audio = -1; /* unknown audio minor */ + v->flags = 0; + v->mode = VIDEO_SOUND_MONO; + v->volume = 0; + v->bass = 0; + v->treble = 0; + v->balance = 0x8000; + v->step = 1; + break; + } + + case VIDIOCSAUDIO: + { + /* Dummy: nothing can be set */ + break; + } + + case VIDIOCGUNIT: + { + struct video_unit *vu = arg; + + vu->video = pdev->vdev->minor & 0x3F; + vu->audio = -1; /* not known yet */ + vu->vbi = -1; + vu->radio = -1; + vu->teletext = -1; + break; + } + default: + return pwc_ioctl(pdev, cmd, arg); + } /* ..switch */ + return 0; +} + +static int pwc_video_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl); +} + + +static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct video_device *vdev = file->private_data; + struct pwc_device *pdev; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end-vma->vm_start; + unsigned long page, pos; + + Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size); + pdev = vdev->priv; + + vma->vm_flags |= VM_IO; + + pos = (unsigned long)pdev->image_data; + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + return 0; +} + +/***************************************************************************/ +/* USB functions */ + +/* This function gets called when a new device is plugged in or the usb core + * is loaded. + */ + +static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct pwc_device *pdev = NULL; + int vendor_id, product_id, type_id; + int i, hint; + int features = 0; + int video_nr = -1; /* default: use next available device */ + char serial_number[30], *name; + + /* Check if we can handle this device */ + Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + intf->altsetting->desc.bInterfaceNumber); + + /* the interfaces are probed one by one. We are only interested in the + video interface (0) now. + Interface 1 is the Audio Control, and interface 2 Audio itself. + */ + if (intf->altsetting->desc.bInterfaceNumber > 0) + return -ENODEV; + + vendor_id = le16_to_cpu(udev->descriptor.idVendor); + product_id = le16_to_cpu(udev->descriptor.idProduct); + + if (vendor_id == 0x0471) { + switch (product_id) { + case 0x0302: + Info("Philips PCA645VC USB webcam detected.\n"); + name = "Philips 645 webcam"; + type_id = 645; + break; + case 0x0303: + Info("Philips PCA646VC USB webcam detected.\n"); + name = "Philips 646 webcam"; + type_id = 646; + break; + case 0x0304: + Info("Askey VC010 type 2 USB webcam detected.\n"); + name = "Askey VC010 webcam"; + type_id = 646; + break; + case 0x0307: + Info("Philips PCVC675K (Vesta) USB webcam detected.\n"); + name = "Philips 675 webcam"; + type_id = 675; + break; + case 0x0308: + Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n"); + name = "Philips 680 webcam"; + type_id = 680; + break; + case 0x030C: + Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n"); + name = "Philips 690 webcam"; + type_id = 690; + break; + case 0x0310: + Info("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n"); + name = "Philips 730 webcam"; + type_id = 730; + break; + case 0x0311: + Info("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n"); + name = "Philips 740 webcam"; + type_id = 740; + break; + case 0x0312: + Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n"); + name = "Philips 750 webcam"; + type_id = 750; + break; + case 0x0313: + Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n"); + name = "Philips 720K/40 webcam"; + type_id = 720; + break; + default: + return -ENODEV; + break; + } + } + else if (vendor_id == 0x069A) { + switch(product_id) { + case 0x0001: + Info("Askey VC010 type 1 USB webcam detected.\n"); + name = "Askey VC010 webcam"; + type_id = 645; + break; + default: + return -ENODEV; + break; + } + } + else if (vendor_id == 0x046d) { + switch(product_id) { + case 0x08b0: + Info("Logitech QuickCam Pro 3000 USB webcam detected.\n"); + name = "Logitech QuickCam Pro 3000"; + type_id = 740; /* CCD sensor */ + break; + case 0x08b1: + Info("Logitech QuickCam Notebook Pro USB webcam detected.\n"); + name = "Logitech QuickCam Notebook Pro"; + type_id = 740; /* CCD sensor */ + break; + case 0x08b2: + Info("Logitech QuickCam 4000 Pro USB webcam detected.\n"); + name = "Logitech QuickCam Pro 4000"; + type_id = 740; /* CCD sensor */ + break; + case 0x08b3: + Info("Logitech QuickCam Zoom USB webcam detected.\n"); + name = "Logitech QuickCam Zoom"; + type_id = 740; /* CCD sensor */ + break; + case 0x08B4: + Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n"); + name = "Logitech QuickCam Zoom"; + type_id = 740; /* CCD sensor */ + break; + case 0x08b5: + Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n"); + name = "Logitech QuickCam Orbit"; + type_id = 740; /* CCD sensor */ + features |= FEATURE_MOTOR_PANTILT; + break; + case 0x08b6: + case 0x08b7: + case 0x08b8: + Info("Logitech QuickCam detected (reserved ID).\n"); + name = "Logitech QuickCam (res.)"; + type_id = 730; /* Assuming CMOS */ + break; + default: + return -ENODEV; + break; + } + } + else if (vendor_id == 0x055d) { + /* I don't know the difference between the C10 and the C30; + I suppose the difference is the sensor, but both cameras + work equally well with a type_id of 675 + */ + switch(product_id) { + case 0x9000: + Info("Samsung MPC-C10 USB webcam detected.\n"); + name = "Samsung MPC-C10"; + type_id = 675; + break; + case 0x9001: + Info("Samsung MPC-C30 USB webcam detected.\n"); + name = "Samsung MPC-C30"; + type_id = 675; + break; + default: + return -ENODEV; + break; + } + } + else if (vendor_id == 0x041e) { + switch(product_id) { + case 0x400c: + Info("Creative Labs Webcam 5 detected.\n"); + name = "Creative Labs Webcam 5"; + type_id = 730; + break; + case 0x4011: + Info("Creative Labs Webcam Pro Ex detected.\n"); + name = "Creative Labs Webcam Pro Ex"; + type_id = 740; + break; + default: + return -ENODEV; + break; + } + } + else if (vendor_id == 0x04cc) { + switch(product_id) { + case 0x8116: + Info("Sotec Afina Eye USB webcam detected.\n"); + name = "Sotec Afina Eye"; + type_id = 730; + break; + default: + return -ENODEV; + break; + } + } + else if (vendor_id == 0x06be) { + switch(product_id) { + case 0x8116: + /* This is essentially the same cam as the Sotec Afina Eye */ + Info("AME Co. Afina Eye USB webcam detected.\n"); + name = "AME Co. Afina Eye"; + type_id = 750; + break; + default: + return -ENODEV; + break; + } + + } + else if (vendor_id == 0x0d81) { + switch(product_id) { + case 0x1900: + Info("Visionite VCS-UC300 USB webcam detected.\n"); + name = "Visionite VCS-UC300"; + type_id = 740; /* CCD sensor */ + break; + case 0x1910: + Info("Visionite VCS-UM100 USB webcam detected.\n"); + name = "Visionite VCS-UM100"; + type_id = 730; /* CMOS sensor */ + break; + default: + return -ENODEV; + break; + } + } + else + return -ENODEV; /* Not any of the know types; but the list keeps growing. */ + + memset(serial_number, 0, 30); + usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29); + Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number); + + if (udev->descriptor.bNumConfigurations > 1) + Info("Warning: more than 1 configuration available.\n"); + + /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */ + pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL); + if (pdev == NULL) { + Err("Oops, could not allocate memory for pwc_device.\n"); + return -ENOMEM; + } + pdev->type = type_id; + pdev->vsize = default_size; + pdev->vframes = default_fps; + strcpy(pdev->serial, serial_number); + pdev->features = features; + if (vendor_id == 0x046D && product_id == 0x08B5) + { + /* Logitech QuickCam Orbit + The ranges have been determined experimentally; they may differ from cam to cam. + Also, the exact ranges left-right and up-down are different for my cam + */ + pdev->angle_range.pan_min = -7000; + pdev->angle_range.pan_max = 7000; + pdev->angle_range.tilt_min = -3000; + pdev->angle_range.tilt_max = 2500; + } + + init_MUTEX(&pdev->modlock); + spin_lock_init(&pdev->ptrlock); + + pdev->udev = udev; + init_waitqueue_head(&pdev->frameq); + pdev->vcompression = pwc_preferred_compression; + + /* Allocate video_device structure */ + pdev->vdev = video_device_alloc(); + if (pdev->vdev == 0) + { + Err("Err, cannot allocate video_device struture. Failing probe."); + kfree(pdev); + return -ENOMEM; + } + memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template)); + strcpy(pdev->vdev->name, name); + pdev->vdev->owner = THIS_MODULE; + video_set_drvdata(pdev->vdev, pdev); + + pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); + Trace(TRACE_PROBE, "Release: %04x\n", pdev->release); + + /* Now search device_hint[] table for a match, so we can hint a node number. */ + for (hint = 0; hint < MAX_DEV_HINTS; hint++) { + if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) && + (device_hint[hint].pdev == NULL)) { + /* so far, so good... try serial number */ + if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) { + /* match! */ + video_nr = device_hint[hint].device_node; + Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr); + break; + } + } + } + + pdev->vdev->release = video_device_release; + i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); + if (i < 0) { + Err("Failed to register as video device (%d).\n", i); + video_device_release(pdev->vdev); /* Drip... drip... drip... */ + kfree(pdev); /* Oops, no memory leaks please */ + return -EIO; + } + else { + Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F); + } + + /* occupy slot */ + if (hint < MAX_DEV_HINTS) + device_hint[hint].pdev = pdev; + + Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev); + usb_set_intfdata (intf, pdev); + return 0; +} + +/* The user janked out the cable... */ +static void usb_pwc_disconnect(struct usb_interface *intf) +{ + struct pwc_device *pdev; + int hint; + + lock_kernel(); + pdev = usb_get_intfdata (intf); + usb_set_intfdata (intf, NULL); + if (pdev == NULL) { + Err("pwc_disconnect() Called without private pointer.\n"); + goto disconnect_out; + } + if (pdev->udev == NULL) { + Err("pwc_disconnect() already called for %p\n", pdev); + goto disconnect_out; + } + if (pdev->udev != interface_to_usbdev(intf)) { + Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n"); + goto disconnect_out; + } +#ifdef PWC_MAGIC + if (pdev->magic != PWC_MAGIC) { + Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n"); + goto disconnect_out; + } +#endif + + /* We got unplugged; this is signalled by an EPIPE error code */ + if (pdev->vopen) { + Info("Disconnected while webcam is in use!\n"); + pdev->error_status = EPIPE; + } + + /* Alert waiting processes */ + wake_up_interruptible(&pdev->frameq); + /* Wait until device is closed */ + while (pdev->vopen) + schedule(); + /* Device is now closed, so we can safely unregister it */ + Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n"); + video_unregister_device(pdev->vdev); + + /* Free memory (don't set pdev to 0 just yet) */ + kfree(pdev); + +disconnect_out: + /* search device_hint[] table if we occupy a slot, by any chance */ + for (hint = 0; hint < MAX_DEV_HINTS; hint++) + if (device_hint[hint].pdev == pdev) + device_hint[hint].pdev = NULL; + + unlock_kernel(); +} + + +/* *grunt* We have to do atoi ourselves :-( */ +static int pwc_atoi(const char *s) +{ + int k = 0; + + k = 0; + while (*s != '\0' && *s >= '0' && *s <= '9') { + k = 10 * k + (*s - '0'); + s++; + } + return k; +} + + +/* + * Initialization code & module stuff + */ + +static char size[10]; +static int fps = 0; +static int fbufs = 0; +static int mbufs = 0; +static int trace = -1; +static int compression = -1; +static int leds[2] = { -1, -1 }; +static char *dev_hint[MAX_DEV_HINTS] = { }; + +module_param_string(size, size, sizeof(size), 0); +MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga"); +module_param(fps, int, 0000); +MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); +module_param(fbufs, int, 0000); +MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve"); +module_param(mbufs, int, 0000); +MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers"); +module_param(trace, int, 0000); +MODULE_PARM_DESC(trace, "For debugging purposes"); +module_param(power_save, bool, 0000); +MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off"); +module_param(compression, int, 0000); +MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); +module_param_array(leds, int, NULL, 0000); +MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); +module_param_array(dev_hint, charp, NULL, 0000); +MODULE_PARM_DESC(dev_hint, "Device node hints"); + +MODULE_DESCRIPTION("Philips & OEM USB webcam driver"); +MODULE_AUTHOR("Luc Saillard "); +MODULE_LICENSE("GPL"); + +static int __init usb_pwc_init(void) +{ + int i, sz; + char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" }; + + Info("Philips webcam module version " PWC_VERSION " loaded.\n"); + Info("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n"); + Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n"); + Info("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n"); + + if (fps) { + if (fps < 4 || fps > 30) { + Err("Framerate out of bounds (4-30).\n"); + return -EINVAL; + } + default_fps = fps; + Info("Default framerate set to %d.\n", default_fps); + } + + if (size[0]) { + /* string; try matching with array */ + for (sz = 0; sz < PSZ_MAX; sz++) { + if (!strcmp(sizenames[sz], size)) { /* Found! */ + default_size = sz; + break; + } + } + if (sz == PSZ_MAX) { + Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n"); + return -EINVAL; + } + Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y); + } + if (mbufs) { + if (mbufs < 1 || mbufs > MAX_IMAGES) { + Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES); + return -EINVAL; + } + default_mbufs = mbufs; + Info("Number of image buffers set to %d.\n", default_mbufs); + } + if (fbufs) { + if (fbufs < 2 || fbufs > MAX_FRAMES) { + Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES); + return -EINVAL; + } + default_fbufs = fbufs; + Info("Number of frame buffers set to %d.\n", default_fbufs); + } + if (trace >= 0) { + Info("Trace options: 0x%04x\n", trace); + pwc_trace = trace; + } + if (compression >= 0) { + if (compression > 3) { + Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n"); + return -EINVAL; + } + pwc_preferred_compression = compression; + Info("Preferred compression set to %d.\n", pwc_preferred_compression); + } + if (power_save) + Info("Enabling power save on open/close.\n"); + if (leds[0] >= 0) + led_on = leds[0]; + if (leds[1] >= 0) + led_off = leds[1]; + + /* Big device node whoopla. Basically, it allows you to assign a + device node (/dev/videoX) to a camera, based on its type + & serial number. The format is [type[.serialnumber]:]node. + + Any camera that isn't matched by these rules gets the next + available free device node. + */ + for (i = 0; i < MAX_DEV_HINTS; i++) { + char *s, *colon, *dot; + + /* This loop also initializes the array */ + device_hint[i].pdev = NULL; + s = dev_hint[i]; + if (s != NULL && *s != '\0') { + device_hint[i].type = -1; /* wildcard */ + strcpy(device_hint[i].serial_number, "*"); + + /* parse string: chop at ':' & '/' */ + colon = dot = s; + while (*colon != '\0' && *colon != ':') + colon++; + while (*dot != '\0' && *dot != '.') + dot++; + /* Few sanity checks */ + if (*dot != '\0' && dot > colon) { + Err("Malformed camera hint: the colon must be after the dot.\n"); + return -EINVAL; + } + + if (*colon == '\0') { + /* No colon */ + if (*dot != '\0') { + Err("Malformed camera hint: no colon + device node given.\n"); + return -EINVAL; + } + else { + /* No type or serial number specified, just a number. */ + device_hint[i].device_node = pwc_atoi(s); + } + } + else { + /* There's a colon, so we have at least a type and a device node */ + device_hint[i].type = pwc_atoi(s); + device_hint[i].device_node = pwc_atoi(colon + 1); + if (*dot != '\0') { + /* There's a serial number as well */ + int k; + + dot++; + k = 0; + while (*dot != ':' && k < 29) { + device_hint[i].serial_number[k++] = *dot; + dot++; + } + device_hint[i].serial_number[k] = '\0'; + } + } +#if PWC_DEBUG + Debug("device_hint[%d]:\n", i); + Debug(" type : %d\n", device_hint[i].type); + Debug(" serial# : %s\n", device_hint[i].serial_number); + Debug(" node : %d\n", device_hint[i].device_node); +#endif + } + else + device_hint[i].type = 0; /* not filled */ + } /* ..for MAX_DEV_HINTS */ + + Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver); + return usb_register(&pwc_driver); +} + +static void __exit usb_pwc_exit(void) +{ + Trace(TRACE_MODULE, "Deregistering driver.\n"); + usb_deregister(&pwc_driver); + Info("Philips webcam module removed.\n"); +} + +module_init(usb_pwc_init); +module_exit(usb_pwc_exit); + diff --git a/drivers/media/video/pwc/pwc-ioctl.h b/drivers/media/video/pwc/pwc-ioctl.h new file mode 100644 index 000000000000..5f9cb08bc02e --- /dev/null +++ b/drivers/media/video/pwc/pwc-ioctl.h @@ -0,0 +1,292 @@ +#ifndef PWC_IOCTL_H +#define PWC_IOCTL_H + +/* (C) 2001-2004 Nemosoft Unv. + (C) 2004 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + 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 +*/ + +/* This is pwc-ioctl.h belonging to PWC 8.12.1 + It contains structures and defines to communicate from user space + directly to the driver. + */ + +/* + Changes + 2001/08/03 Alvarado Added ioctl constants to access methods for + changing white balance and red/blue gains + 2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE + 2003/12/13 Nemosft Unv. Some modifications to make interfacing to + PWCX easier + */ + +/* These are private ioctl() commands, specific for the Philips webcams. + They contain functions not found in other webcams, and settings not + specified in the Video4Linux API. + + The #define names are built up like follows: + VIDIOC VIDeo IOCtl prefix + PWC Philps WebCam + G optional: Get + S optional: Set + ... the function + */ + + + /* Enumeration of image sizes */ +#define PSZ_SQCIF 0x00 +#define PSZ_QSIF 0x01 +#define PSZ_QCIF 0x02 +#define PSZ_SIF 0x03 +#define PSZ_CIF 0x04 +#define PSZ_VGA 0x05 +#define PSZ_MAX 6 + + +/* The frame rate is encoded in the video_window.flags parameter using + the upper 16 bits, since some flags are defined nowadays. The following + defines provide a mask and shift to filter out this value. + + In 'Snapshot' mode the camera freezes its automatic exposure and colour + balance controls. + */ +#define PWC_FPS_SHIFT 16 +#define PWC_FPS_MASK 0x00FF0000 +#define PWC_FPS_FRMASK 0x003F0000 +#define PWC_FPS_SNAPSHOT 0x00400000 + + +/* structure for transferring x & y coordinates */ +struct pwc_coord +{ + int x, y; /* guess what */ + int size; /* size, or offset */ +}; + + +/* Used with VIDIOCPWCPROBE */ +struct pwc_probe +{ + char name[32]; + int type; +}; + +struct pwc_serial +{ + char serial[30]; /* String with serial number. Contains terminating 0 */ +}; + +/* pwc_whitebalance.mode values */ +#define PWC_WB_INDOOR 0 +#define PWC_WB_OUTDOOR 1 +#define PWC_WB_FL 2 +#define PWC_WB_MANUAL 3 +#define PWC_WB_AUTO 4 + +/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). + Set mode to one of the PWC_WB_* values above. + *red and *blue are the respective gains of these colour components inside + the camera; range 0..65535 + When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read; + otherwise undefined. + 'read_red' and 'read_blue' are read-only. +*/ +struct pwc_whitebalance +{ + int mode; + int manual_red, manual_blue; /* R/W */ + int read_red, read_blue; /* R/O */ +}; + +/* + 'control_speed' and 'control_delay' are used in automatic whitebalance mode, + and tell the camera how fast it should react to changes in lighting, and + with how much delay. Valid values are 0..65535. +*/ +struct pwc_wb_speed +{ + int control_speed; + int control_delay; + +}; + +/* Used with VIDIOCPWC[SG]LED */ +struct pwc_leds +{ + int led_on; /* Led on-time; range = 0..25000 */ + int led_off; /* Led off-time; range = 0..25000 */ +}; + +/* Image size (used with GREALSIZE) */ +struct pwc_imagesize +{ + int width; + int height; +}; + +/* Defines and structures for Motorized Pan & Tilt */ +#define PWC_MPT_PAN 0x01 +#define PWC_MPT_TILT 0x02 +#define PWC_MPT_TIMEOUT 0x04 /* for status */ + +/* Set angles; when absolute != 0, the angle is absolute and the + driver calculates the relative offset for you. This can only + be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns + absolute angles. + */ +struct pwc_mpt_angles +{ + int absolute; /* write-only */ + int pan; /* degrees * 100 */ + int tilt; /* degress * 100 */ +}; + +/* Range of angles of the camera, both horizontally and vertically. + */ +struct pwc_mpt_range +{ + int pan_min, pan_max; /* degrees * 100 */ + int tilt_min, tilt_max; +}; + +struct pwc_mpt_status +{ + int status; + int time_pan; + int time_tilt; +}; + + +/* This is used for out-of-kernel decompression. With it, you can get + all the necessary information to initialize and use the decompressor + routines in standalone applications. + */ +struct pwc_video_command +{ + int type; /* camera type (645, 675, 730, etc.) */ + int release; /* release number */ + + int size; /* one of PSZ_* */ + int alternate; + int command_len; /* length of USB video command */ + unsigned char command_buf[13]; /* Actual USB video command */ + int bandlength; /* >0 = compressed */ + int frame_size; /* Size of one (un)compressed frame */ +}; + +/* Flags for PWCX subroutines. Not all modules honour all flags. */ +#define PWCX_FLAG_PLANAR 0x0001 +#define PWCX_FLAG_BAYER 0x0008 + + +/* IOCTL definitions */ + + /* Restore user settings */ +#define VIDIOCPWCRUSER _IO('v', 192) + /* Save user settings */ +#define VIDIOCPWCSUSER _IO('v', 193) + /* Restore factory settings */ +#define VIDIOCPWCFACTORY _IO('v', 194) + + /* You can manipulate the compression factor. A compression preference of 0 + means use uncompressed modes when available; 1 is low compression, 2 is + medium and 3 is high compression preferred. Of course, the higher the + compression, the lower the bandwidth used but more chance of artefacts + in the image. The driver automatically chooses a higher compression when + the preferred mode is not available. + */ + /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */ +#define VIDIOCPWCSCQUAL _IOW('v', 195, int) + /* Get preferred compression quality */ +#define VIDIOCPWCGCQUAL _IOR('v', 195, int) + + +/* Retrieve serial number of camera */ +#define VIDIOCPWCGSERIAL _IOR('v', 198, struct pwc_serial) + + /* This is a probe function; since so many devices are supported, it + becomes difficult to include all the names in programs that want to + check for the enhanced Philips stuff. So in stead, try this PROBE; + it returns a structure with the original name, and the corresponding + Philips type. + To use, fill the structure with zeroes, call PROBE and if that succeeds, + compare the name with that returned from VIDIOCGCAP; they should be the + same. If so, you can be assured it is a Philips (OEM) cam and the type + is valid. + */ +#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe) + + /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */ +#define VIDIOCPWCSAGC _IOW('v', 200, int) + /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */ +#define VIDIOCPWCGAGC _IOR('v', 200, int) + /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */ +#define VIDIOCPWCSSHUTTER _IOW('v', 201, int) + + /* Color compensation (Auto White Balance) */ +#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance) +#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance) + + /* Auto WB speed */ +#define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed) +#define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed) + + /* LEDs on/off/blink; int range 0..65535 */ +#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds) +#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds) + + /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */ +#define VIDIOCPWCSCONTOUR _IOW('v', 206, int) +#define VIDIOCPWCGCONTOUR _IOR('v', 206, int) + + /* Backlight compensation; 0 = off, otherwise on */ +#define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int) +#define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int) + + /* Flickerless mode; = 0 off, otherwise on */ +#define VIDIOCPWCSFLICKER _IOW('v', 208, int) +#define VIDIOCPWCGFLICKER _IOR('v', 208, int) + + /* Dynamic noise reduction; 0 off, 3 = high noise reduction */ +#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int) +#define VIDIOCPWCGDYNNOISE _IOR('v', 209, int) + + /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */ +#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize) + + /* Motorized pan & tilt functions */ +#define VIDIOCPWCMPTRESET _IOW('v', 211, int) +#define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range) +#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles) +#define VIDIOCPWCMPTGANGLE _IOR('v', 212, struct pwc_mpt_angles) +#define VIDIOCPWCMPTSTATUS _IOR('v', 213, struct pwc_mpt_status) + + /* Get the USB set-video command; needed for initializing libpwcx */ +#define VIDIOCPWCGVIDCMD _IOR('v', 215, struct pwc_video_command) +struct pwc_table_init_buffer { + int len; + char *buffer; + +}; +#define VIDIOCPWCGVIDTABLE _IOR('v', 216, struct pwc_table_init_buffer) + +#endif diff --git a/drivers/media/video/pwc/pwc-kiara.c b/drivers/media/video/pwc/pwc-kiara.c new file mode 100644 index 000000000000..c498c68bace1 --- /dev/null +++ b/drivers/media/video/pwc/pwc-kiara.c @@ -0,0 +1,318 @@ +/* Linux driver for Philips webcam + (C) 2004 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + 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 +*/ + + +/* This tables contains entries for the 730/740/750 (Kiara) camera, with + 4 different qualities (no compression, low, medium, high). + It lists the bandwidth requirements for said mode by its alternate interface + number. An alternate of 0 means that the mode is unavailable. + + There are 6 * 4 * 4 entries: + 6 different resolutions subqcif, qsif, qcif, sif, cif, vga + 6 framerates: 5, 10, 15, 20, 25, 30 + 4 compression modi: none, low, medium, high + + When an uncompressed mode is not available, the next available compressed mode + will be chosen (unless the decompressor is absent). Sometimes there are only + 1 or 2 compressed modes available; in that case entries are duplicated. +*/ + + +#include "pwc-kiara.h" +#include "pwc-uncompress.h" + +const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] = +{ + /* SQCIF */ + { + /* 5 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 10 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 15 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 20 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 25 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 30 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + }, + /* QSIF */ + { + /* 5 fps */ + { + {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, + {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, + {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, + {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, + }, + /* 10 fps */ + { + {2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}}, + {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, + {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, + {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, + }, + /* 15 fps */ + { + {3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}}, + {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}}, + {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}}, + {1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}}, + }, + /* 20 fps */ + { + {4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}}, + {3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}}, + {2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}}, + {1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}}, + }, + /* 25 fps */ + { + {5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}}, + {3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}}, + {2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}}, + {1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}}, + }, + /* 30 fps */ + { + {8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}}, + {5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}}, + {3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}}, + {2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}}, + }, + }, + /* QCIF */ + { + /* 5 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 10 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 15 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 20 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 25 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 30 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + }, + /* SIF */ + { + /* 5 fps */ + { + {4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}}, + {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}}, + {2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}}, + {1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}}, + }, + /* 10 fps */ + { + {0, }, + {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}}, + {3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}}, + {2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}}, + }, + /* 15 fps */ + { + {0, }, + {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}}, + {4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}}, + {3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}}, + }, + /* 20 fps */ + { + {0, }, + {9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}}, + {5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}}, + {3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}}, + }, + /* 25 fps */ + { + {0, }, + {9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}}, + {6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}}, + {4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}}, + }, + /* 30 fps */ + { + {0, }, + {9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}}, + {6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}}, + {4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}}, + }, + }, + /* CIF */ + { + /* 5 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 10 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 15 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 20 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 25 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 30 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + }, + /* VGA */ + { + /* 5 fps */ + { + {0, }, + {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}}, + {4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}}, + {3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}}, + }, + /* 10 fps */ + { + {0, }, + {9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}}, + {6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}}, + {4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}}, + }, + /* 15 fps */ + { + {0, }, + {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}}, + {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}}, + {8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}}, + }, + /* 20 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 25 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 30 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + }, +}; + diff --git a/drivers/media/video/pwc/pwc-kiara.h b/drivers/media/video/pwc/pwc-kiara.h new file mode 100644 index 000000000000..12929abbb1f0 --- /dev/null +++ b/drivers/media/video/pwc/pwc-kiara.h @@ -0,0 +1,45 @@ +/* Linux driver for Philips webcam + (C) 2004 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + 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 +*/ + +/* Entries for the Kiara (730/740/750) camera */ + +#ifndef PWC_KIARA_H +#define PWC_KIARA_H + +#include "pwc-ioctl.h" + +struct Kiara_table_entry +{ + char alternate; /* USB alternate interface */ + unsigned short packetsize; /* Normal packet size */ + unsigned short bandlength; /* Bandlength when decompressing */ + unsigned char mode[12]; /* precomputed mode settings for cam */ +}; + +const extern struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4]; +const extern unsigned int KiaraRomTable[8][2][16][8]; + +#endif + + diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c new file mode 100644 index 000000000000..b7a4bd3524c7 --- /dev/null +++ b/drivers/media/video/pwc/pwc-misc.c @@ -0,0 +1,140 @@ +/* Linux driver for Philips webcam + Various miscellaneous functions and tables. + (C) 1999-2003 Nemosoft Unv. + (C) 2004 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + 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 "pwc.h" + +struct pwc_coord pwc_image_sizes[PSZ_MAX] = +{ + { 128, 96, 0 }, + { 160, 120, 0 }, + { 176, 144, 0 }, + { 320, 240, 0 }, + { 352, 288, 0 }, + { 640, 480, 0 }, +}; + +/* x,y -> PSZ_ */ +int pwc_decode_size(struct pwc_device *pdev, int width, int height) +{ + int i, find; + + /* Make sure we don't go beyond our max size. + NB: we have different limits for RAW and normal modes. In case + you don't have the decompressor loaded or use RAW mode, + the maximum viewable size is smaller. + */ + if (pdev->vpalette == VIDEO_PALETTE_RAW) + { + if (width > pdev->abs_max.x || height > pdev->abs_max.y) + { + Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n"); + return -1; + } + } + else + { + if (width > pdev->view_max.x || height > pdev->view_max.y) + { + Debug("VIDEO_PALETTE_ not RAW: going beyond view_max.\n"); + return -1; + } + } + + /* Find the largest size supported by the camera that fits into the + requested size. + */ + find = -1; + for (i = 0; i < PSZ_MAX; i++) { + if (pdev->image_mask & (1 << i)) { + if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height) + find = i; + } + } + return find; +} + +/* initialize variables depending on type and decompressor*/ +void pwc_construct(struct pwc_device *pdev) +{ + switch(pdev->type) { + case 645: + case 646: + pdev->view_min.x = 128; + pdev->view_min.y = 96; + pdev->view_max.x = 352; + pdev->view_max.y = 288; + pdev->abs_max.x = 352; + pdev->abs_max.y = 288; + pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF; + pdev->vcinterface = 2; + pdev->vendpoint = 4; + pdev->frame_header_size = 0; + pdev->frame_trailer_size = 0; + break; + case 675: + case 680: + case 690: + pdev->view_min.x = 128; + pdev->view_min.y = 96; + /* Anthill bug #38: PWC always reports max size, even without PWCX */ + pdev->view_max.x = 640; + pdev->view_max.y = 480; + pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA; + pdev->abs_max.x = 640; + pdev->abs_max.y = 480; + pdev->vcinterface = 3; + pdev->vendpoint = 4; + pdev->frame_header_size = 0; + pdev->frame_trailer_size = 0; + break; + case 720: + case 730: + case 740: + case 750: + pdev->view_min.x = 160; + pdev->view_min.y = 120; + pdev->view_max.x = 640; + pdev->view_max.y = 480; + pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; + pdev->abs_max.x = 640; + pdev->abs_max.y = 480; + pdev->vcinterface = 3; + pdev->vendpoint = 5; + pdev->frame_header_size = TOUCAM_HEADER_SIZE; + pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE; + break; + } + Debug("type = %d\n",pdev->type); + pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */ + pdev->view_min.size = pdev->view_min.x * pdev->view_min.y; + pdev->view_max.size = pdev->view_max.x * pdev->view_max.y; + /* length of image, in YUV format; always allocate enough memory. */ + pdev->len_per_image = (pdev->abs_max.x * pdev->abs_max.y * 3) / 2; +} + + diff --git a/drivers/media/video/pwc/pwc-nala.h b/drivers/media/video/pwc/pwc-nala.h new file mode 100644 index 000000000000..e6c5cb69d03b --- /dev/null +++ b/drivers/media/video/pwc/pwc-nala.h @@ -0,0 +1,66 @@ + /* SQCIF */ + { + {0, 0, {0x04, 0x01, 0x03}}, + {8, 0, {0x05, 0x01, 0x03}}, + {7, 0, {0x08, 0x01, 0x03}}, + {7, 0, {0x0A, 0x01, 0x03}}, + {6, 0, {0x0C, 0x01, 0x03}}, + {5, 0, {0x0F, 0x01, 0x03}}, + {4, 0, {0x14, 0x01, 0x03}}, + {3, 0, {0x18, 0x01, 0x03}}, + }, + /* QSIF */ + { + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + }, + /* QCIF */ + { + {0, 0, {0x04, 0x01, 0x02}}, + {8, 0, {0x05, 0x01, 0x02}}, + {7, 0, {0x08, 0x01, 0x02}}, + {6, 0, {0x0A, 0x01, 0x02}}, + {5, 0, {0x0C, 0x01, 0x02}}, + {4, 0, {0x0F, 0x01, 0x02}}, + {1, 0, {0x14, 0x01, 0x02}}, + {1, 0, {0x18, 0x01, 0x02}}, + }, + /* SIF */ + { + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + }, + /* CIF */ + { + {4, 0, {0x04, 0x01, 0x01}}, + {7, 1, {0x05, 0x03, 0x01}}, + {6, 1, {0x08, 0x03, 0x01}}, + {4, 1, {0x0A, 0x03, 0x01}}, + {3, 1, {0x0C, 0x03, 0x01}}, + {2, 1, {0x0F, 0x03, 0x01}}, + {0}, + {0}, + }, + /* VGA */ + { + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + {0}, + }, diff --git a/drivers/media/video/pwc/pwc-timon.c b/drivers/media/video/pwc/pwc-timon.c new file mode 100644 index 000000000000..dee967173d6c --- /dev/null +++ b/drivers/media/video/pwc/pwc-timon.c @@ -0,0 +1,316 @@ +/* Linux driver for Philips webcam + (C) 2004 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + 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 +*/ + + +/* This tables contains entries for the 675/680/690 (Timon) camera, with + 4 different qualities (no compression, low, medium, high). + It lists the bandwidth requirements for said mode by its alternate interface + number. An alternate of 0 means that the mode is unavailable. + + There are 6 * 4 * 4 entries: + 6 different resolutions subqcif, qsif, qcif, sif, cif, vga + 6 framerates: 5, 10, 15, 20, 25, 30 + 4 compression modi: none, low, medium, high + + When an uncompressed mode is not available, the next available compressed mode + will be chosen (unless the decompressor is absent). Sometimes there are only + 1 or 2 compressed modes available; in that case entries are duplicated. +*/ + +#include "pwc-timon.h" + +const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = +{ + /* SQCIF */ + { + /* 5 fps */ + { + {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, + {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, + {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, + {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, + }, + /* 10 fps */ + { + {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, + {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, + {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, + {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, + }, + /* 15 fps */ + { + {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, + {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, + {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, + {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, + }, + /* 20 fps */ + { + {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, + {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, + {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, + {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, + }, + /* 25 fps */ + { + {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, + {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, + {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, + {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, + }, + /* 30 fps */ + { + {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, + {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, + {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, + {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, + }, + }, + /* QSIF */ + { + /* 5 fps */ + { + {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, + {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, + {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, + {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, + }, + /* 10 fps */ + { + {2, 291, 0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}}, + {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, + {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, + {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, + }, + /* 15 fps */ + { + {3, 437, 0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}}, + {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, + {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, + {1, 191, 420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, + }, + /* 20 fps */ + { + {4, 588, 0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}}, + {3, 447, 730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, + {2, 292, 476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, + {1, 192, 312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}}, + }, + /* 25 fps */ + { + {5, 703, 0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}}, + {3, 447, 610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, + {2, 292, 398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, + {1, 192, 262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}}, + }, + /* 30 fps */ + { + {8, 873, 0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}}, + {5, 704, 774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}}, + {3, 448, 492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}}, + {2, 291, 320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}}, + }, + }, + /* QCIF */ + { + /* 5 fps */ + { + {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, + {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, + {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, + {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, + }, + /* 10 fps */ + { + {3, 385, 0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}}, + {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, + {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, + {1, 194, 532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}}, + }, + /* 15 fps */ + { + {4, 577, 0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}}, + {3, 447, 818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}}, + {2, 292, 534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}}, + {1, 195, 356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}}, + }, + /* 20 fps */ + { + {6, 776, 0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}}, + {4, 591, 804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}}, + {3, 447, 608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, + {2, 291, 396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}}, + }, + /* 25 fps */ + { + {9, 928, 0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}}, + {5, 703, 800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}}, + {3, 447, 508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, + {2, 292, 332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, + }, + /* 30 fps */ + { + {0, }, + {9, 956, 876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}}, + {4, 592, 542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}}, + {2, 291, 266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}}, + }, + }, + /* SIF */ + { + /* 5 fps */ + { + {4, 582, 0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}}, + {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}}, + {2, 291, 960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}}, + {1, 191, 630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}}, + }, + /* 10 fps */ + { + {0, }, + {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}}, + {3, 447, 736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}}, + {2, 291, 480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}}, + }, + /* 15 fps */ + { + {0, }, + {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}}, + {4, 591, 650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}}, + {3, 448, 492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}}, + }, + /* 20 fps */ + { + {0, }, + {9, 958, 782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}}, + {5, 703, 574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}}, + {3, 446, 364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}}, + }, + /* 25 fps */ + { + {0, }, + {9, 958, 654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}}, + {6, 776, 530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}}, + {4, 592, 404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}}, + }, + /* 30 fps */ + { + {0, }, + {9, 957, 526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}}, + {6, 775, 426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}}, + {4, 590, 324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}}, + }, + }, + /* CIF */ + { + /* 5 fps */ + { + {6, 771, 0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}}, + {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}}, + {2, 291, 800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}}, + {1, 193, 528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}}, + }, + /* 10 fps */ + { + {0, }, + {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}}, + {4, 591, 812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}}, + {2, 291, 400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}}, + }, + /* 15 fps */ + { + {0, }, + {9, 956, 876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}}, + {5, 703, 644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}}, + {3, 448, 410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}}, + }, + /* 20 fps */ + { + {0, }, + {9, 956, 650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}}, + {6, 776, 528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}}, + {4, 591, 402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}}, + }, + /* 25 fps */ + { + {0, }, + {9, 956, 544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}}, + {7, 840, 478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}}, + {5, 703, 400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}}, + }, + /* 30 fps */ + { + {0, }, + {9, 956, 438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}}, + {7, 838, 384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}}, + {6, 773, 354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}}, + }, + }, + /* VGA */ + { + /* 5 fps */ + { + {0, }, + {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}}, + {4, 592, 976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}}, + {3, 448, 738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}}, + }, + /* 10 fps */ + { + {0, }, + {9, 956, 788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}}, + {6, 776, 640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}}, + {4, 592, 488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}}, + }, + /* 15 fps */ + { + {0, }, + {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}}, + {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}}, + {8, 895, 492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}}, + }, + /* 20 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 25 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + /* 30 fps */ + { + {0, }, + {0, }, + {0, }, + {0, }, + }, + }, +}; + diff --git a/drivers/media/video/pwc/pwc-timon.h b/drivers/media/video/pwc/pwc-timon.h new file mode 100644 index 000000000000..a86b3782a081 --- /dev/null +++ b/drivers/media/video/pwc/pwc-timon.h @@ -0,0 +1,61 @@ +/* Linux driver for Philips webcam + (C) 2004 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + 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 +*/ + + + +/* This tables contains entries for the 675/680/690 (Timon) camera, with + 4 different qualities (no compression, low, medium, high). + It lists the bandwidth requirements for said mode by its alternate interface + number. An alternate of 0 means that the mode is unavailable. + + There are 6 * 4 * 4 entries: + 6 different resolutions subqcif, qsif, qcif, sif, cif, vga + 6 framerates: 5, 10, 15, 20, 25, 30 + 4 compression modi: none, low, medium, high + + When an uncompressed mode is not available, the next available compressed mode + will be chosen (unless the decompressor is absent). Sometimes there are only + 1 or 2 compressed modes available; in that case entries are duplicated. +*/ + +#ifndef PWC_TIMON_H +#define PWC_TIMON_H + +#include "pwc-ioctl.h" + +struct Timon_table_entry +{ + char alternate; /* USB alternate interface */ + unsigned short packetsize; /* Normal packet size */ + unsigned short bandlength; /* Bandlength when decompressing */ + unsigned char mode[13]; /* precomputed mode settings for cam */ +}; + +const extern struct Timon_table_entry Timon_table[PSZ_MAX][6][4]; +const extern unsigned int TimonRomTable [16][2][16][8]; + + +#endif + + diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c new file mode 100644 index 000000000000..ef4204eab6c4 --- /dev/null +++ b/drivers/media/video/pwc/pwc-uncompress.c @@ -0,0 +1,146 @@ +/* Linux driver for Philips webcam + Decompression frontend. + (C) 1999-2003 Nemosoft Unv. + (C) 2004 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + 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 "pwc.h" +#include "pwc-uncompress.h" + +int pwc_decompress(struct pwc_device *pdev) +{ + struct pwc_frame_buf *fbuf; + int n, line, col, stride; + void *yuv, *image; + u16 *src; + u16 *dsty, *dstu, *dstv; + + if (pdev == NULL) + return -EFAULT; +#if defined(__KERNEL__) && defined(PWC_MAGIC) + if (pdev->magic != PWC_MAGIC) { + Err("pwc_decompress(): magic failed.\n"); + return -EFAULT; + } +#endif + + fbuf = pdev->read_frame; + if (fbuf == NULL) + return -EFAULT; + image = pdev->image_ptr[pdev->fill_image]; + if (!image) + return -EFAULT; + + yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ + + /* Raw format; that's easy... */ + if (pdev->vpalette == VIDEO_PALETTE_RAW) + { + memcpy(image, yuv, pdev->frame_size); + return 0; + } + + if (pdev->vbandlength == 0) { + /* Uncompressed mode. We copy the data into the output buffer, + using the viewport size (which may be larger than the image + size). Unfortunately we have to do a bit of byte stuffing + to get the desired output format/size. + */ + /* + * We do some byte shuffling here to go from the + * native format to YUV420P. + */ + src = (u16 *)yuv; + n = pdev->view.x * pdev->view.y; + + /* offset in Y plane */ + stride = pdev->view.x * pdev->offset.y + pdev->offset.x; + dsty = (u16 *)(image + stride); + + /* offsets in U/V planes */ + stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; + dstu = (u16 *)(image + n + stride); + dstv = (u16 *)(image + n + n / 4 + stride); + + /* increment after each line */ + stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ + + for (line = 0; line < pdev->image.y; line++) { + for (col = 0; col < pdev->image.x; col += 4) { + *dsty++ = *src++; + *dsty++ = *src++; + if (line & 1) + *dstv++ = *src++; + else + *dstu++ = *src++; + } + dsty += stride; + if (line & 1) + dstv += (stride >> 1); + else + dstu += (stride >> 1); + } + } + else { + /* Compressed; the decompressor routines will write the data + in planar format immediately. + */ + int flags; + + flags = PWCX_FLAG_PLANAR; + if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) + { + printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n"); + flags |= PWCX_FLAG_BAYER; + return -ENXIO; /* No such device or address: missing decompressor */ + } + +#if 0 + switch (pdev->type) + { + case 675: + case 680: + case 690: + case 720: + case 730: + case 740: + case 750: + pwc_dec23_decompress(&pdev->image, &pdev->view, + &pdev->offset, yuv, image, flags, + pdev->decompress_data, pdev->vbandlength); + break; + case 645: + case 646: + /* TODO & FIXME */ + return -ENXIO; /* Missing decompressor */ + break; + } +#endif + } + return 0; +} + + diff --git a/drivers/media/video/pwc/pwc-uncompress.h b/drivers/media/video/pwc/pwc-uncompress.h new file mode 100644 index 000000000000..d3b9250e4ed3 --- /dev/null +++ b/drivers/media/video/pwc/pwc-uncompress.h @@ -0,0 +1,41 @@ +/* (C) 1999-2003 Nemosoft Unv. + (C) 2004 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + 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 +*/ + +/* This file is the bridge between the kernel module and the plugin; it + describes the structures and datatypes used in both modules. Any + significant change should be reflected by increasing the + pwc_decompressor_version major number. + */ +#ifndef PWC_UNCOMPRESS_H +#define PWC_UNCOMPRESS_H + +#include + +#include "pwc-ioctl.h" + +/* from pwc-dec.h */ +#define PWCX_FLAG_PLANAR 0x0001 +/* */ + +#endif diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h new file mode 100644 index 000000000000..6dd76bb3dff1 --- /dev/null +++ b/drivers/media/video/pwc/pwc.h @@ -0,0 +1,272 @@ +/* (C) 1999-2003 Nemosoft Unv. + (C) 2004 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + 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 PWC_H +#define PWC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pwc-uncompress.h" +#include "pwc-ioctl.h" + +/* Defines and structures for the Philips webcam */ +/* Used for checking memory corruption/pointer validation */ +#define PWC_MAGIC 0x89DC10ABUL +#undef PWC_MAGIC + +/* Turn some debugging options on/off */ +#define PWC_DEBUG 0 + +/* Trace certain actions in the driver */ +#define TRACE_MODULE 0x0001 +#define TRACE_PROBE 0x0002 +#define TRACE_OPEN 0x0004 +#define TRACE_READ 0x0008 +#define TRACE_MEMORY 0x0010 +#define TRACE_FLOW 0x0020 +#define TRACE_SIZE 0x0040 +#define TRACE_PWCX 0x0080 +#define TRACE_SEQUENCE 0x1000 + +#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A) +#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A) +#define Info(A...) printk(KERN_INFO PWC_NAME " " A) +#define Err(A...) printk(KERN_ERR PWC_NAME " " A) + + +/* Defines for ToUCam cameras */ +#define TOUCAM_HEADER_SIZE 8 +#define TOUCAM_TRAILER_SIZE 4 + +#define FEATURE_MOTOR_PANTILT 0x0001 + +/* Version block */ +#define PWC_MAJOR 9 +#define PWC_MINOR 0 +#define PWC_VERSION "9.0.2-unofficial" +#define PWC_NAME "pwc" + +/* Turn certain features on/off */ +#define PWC_INT_PIPE 0 + +/* Ignore errors in the first N frames, to allow for startup delays */ +#define FRAME_LOWMARK 5 + +/* Size and number of buffers for the ISO pipe. */ +#define MAX_ISO_BUFS 2 +#define ISO_FRAMES_PER_DESC 10 +#define ISO_MAX_FRAME_SIZE 960 +#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE) + +/* Frame buffers: contains compressed or uncompressed video data. */ +#define MAX_FRAMES 5 +/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */ +#define PWC_FRAME_SIZE (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE) + +/* Absolute maximum number of buffers available for mmap() */ +#define MAX_IMAGES 10 + +/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */ +struct pwc_iso_buf +{ + void *data; + int length; + int read; + struct urb *urb; +}; + +/* intermediate buffers with raw data from the USB cam */ +struct pwc_frame_buf +{ + void *data; + volatile int filled; /* number of bytes filled */ + struct pwc_frame_buf *next; /* list */ +#if PWC_DEBUG + int sequence; /* Sequence number */ +#endif +}; + +struct pwc_device +{ + struct video_device *vdev; +#ifdef PWC_MAGIC + int magic; +#endif + /* Pointer to our usb_device */ + struct usb_device *udev; + + int type; /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */ + int release; /* release number */ + int features; /* feature bits */ + char serial[30]; /* serial number (string) */ + int error_status; /* set when something goes wrong with the cam (unplugged, USB errors) */ + int usb_init; /* set when the cam has been initialized over USB */ + + /*** Video data ***/ + int vopen; /* flag */ + int vendpoint; /* video isoc endpoint */ + int vcinterface; /* video control interface */ + int valternate; /* alternate interface needed */ + int vframes, vsize; /* frames-per-second & size (see PSZ_*) */ + int vpalette; /* palette: 420P, RAW or RGBBAYER */ + int vframe_count; /* received frames */ + int vframes_dumped; /* counter for dumped frames */ + int vframes_error; /* frames received in error */ + int vmax_packet_size; /* USB maxpacket size */ + int vlast_packet_size; /* for frame synchronisation */ + int visoc_errors; /* number of contiguous ISOC errors */ + int vcompression; /* desired compression factor */ + int vbandlength; /* compressed band length; 0 is uncompressed */ + char vsnapshot; /* snapshot mode */ + char vsync; /* used by isoc handler */ + char vmirror; /* for ToUCaM series */ + + int cmd_len; + unsigned char cmd_buf[13]; + + /* The image acquisition requires 3 to 4 steps: + 1. data is gathered in short packets from the USB controller + 2. data is synchronized and packed into a frame buffer + 3a. in case data is compressed, decompress it directly into image buffer + 3b. in case data is uncompressed, copy into image buffer with viewport + 4. data is transferred to the user process + + Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES.... + We have in effect a back-to-back-double-buffer system. + */ + /* 1: isoc */ + struct pwc_iso_buf sbuf[MAX_ISO_BUFS]; + char iso_init; + + /* 2: frame */ + struct pwc_frame_buf *fbuf; /* all frames */ + struct pwc_frame_buf *empty_frames, *empty_frames_tail; /* all empty frames */ + struct pwc_frame_buf *full_frames, *full_frames_tail; /* all filled frames */ + struct pwc_frame_buf *fill_frame; /* frame currently being filled */ + struct pwc_frame_buf *read_frame; /* frame currently read by user process */ + int frame_header_size, frame_trailer_size; + int frame_size; + int frame_total_size; /* including header & trailer */ + int drop_frames; +#if PWC_DEBUG + int sequence; /* Debugging aid */ +#endif + + /* 3: decompression */ + struct pwc_decompressor *decompressor; /* function block with decompression routines */ + void *decompress_data; /* private data for decompression engine */ + + /* 4: image */ + /* We have an 'image' and a 'view', where 'image' is the fixed-size image + as delivered by the camera, and 'view' is the size requested by the + program. The camera image is centered in this viewport, laced with + a gray or black border. view_min <= image <= view <= view_max; + */ + int image_mask; /* bitmask of supported sizes */ + struct pwc_coord view_min, view_max; /* minimum and maximum viewable sizes */ + struct pwc_coord abs_max; /* maximum supported size with compression */ + struct pwc_coord image, view; /* image and viewport size */ + struct pwc_coord offset; /* offset within the viewport */ + + void *image_data; /* total buffer, which is subdivided into ... */ + void *image_ptr[MAX_IMAGES]; /* ...several images... */ + int fill_image; /* ...which are rotated. */ + int len_per_image; /* length per image */ + int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */ + int image_used[MAX_IMAGES]; /* For MCAPTURE and SYNC */ + + struct semaphore modlock; /* to prevent races in video_open(), etc */ + spinlock_t ptrlock; /* for manipulating the buffer pointers */ + + /*** motorized pan/tilt feature */ + struct pwc_mpt_range angle_range; + int pan_angle; /* in degrees * 100 */ + int tilt_angle; /* absolute angle; 0,0 is home position */ + + /*** Misc. data ***/ + wait_queue_head_t frameq; /* When waiting for a frame to finish... */ +#if PWC_INT_PIPE + void *usb_int_handler; /* for the interrupt endpoint */ +#endif +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Global variable */ +extern int pwc_trace; + +/** functions in pwc-if.c */ +int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot); + +/** Functions in pwc-misc.c */ +/* sizes in pixels */ +extern struct pwc_coord pwc_image_sizes[PSZ_MAX]; + +int pwc_decode_size(struct pwc_device *pdev, int width, int height); +void pwc_construct(struct pwc_device *pdev); + +/** Functions in pwc-ctrl.c */ +/* Request a certain video mode. Returns < 0 if not possible */ +extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot); + +/* Various controls; should be obvious. Value 0..65535, or < 0 on error */ +extern int pwc_get_brightness(struct pwc_device *pdev); +extern int pwc_set_brightness(struct pwc_device *pdev, int value); +extern int pwc_get_contrast(struct pwc_device *pdev); +extern int pwc_set_contrast(struct pwc_device *pdev, int value); +extern int pwc_get_gamma(struct pwc_device *pdev); +extern int pwc_set_gamma(struct pwc_device *pdev, int value); +extern int pwc_get_saturation(struct pwc_device *pdev); +extern int pwc_set_saturation(struct pwc_device *pdev, int value); +extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value); +extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor); + +/* Power down or up the camera; not supported by all models */ +extern int pwc_camera_power(struct pwc_device *pdev, int power); + +/* Private ioctl()s; see pwc-ioctl.h */ +extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg); + + +/** pwc-uncompress.c */ +/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */ +extern int pwc_decompress(struct pwc_device *pdev); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c new file mode 100644 index 000000000000..f03ea7f89596 --- /dev/null +++ b/drivers/media/video/se401.c @@ -0,0 +1,1435 @@ +/* + * Endpoints (formerly known as AOX) se401 USB Camera Driver + * + * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) + * + * Still somewhat based on the Linux ov511 driver. + * + * 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. + * + * + * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on + * their chipset available and supporting me while writing this driver. + * - Jeroen Vreeken + */ + +static const char version[] = "0.24"; + +#include +#include +#include +#include +#include +#include +#include +#include "se401.h" + +static int flickerless=0; +static int video_nr = -1; + +static struct usb_device_id device_table [] = { + { USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */ + { USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */ + { USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */ + { USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */ + { USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */ + { } +}; + +MODULE_DEVICE_TABLE(usb, device_table); + +MODULE_AUTHOR("Jeroen Vreeken "); +MODULE_DESCRIPTION("SE401 USB Camera Driver"); +MODULE_LICENSE("GPL"); +module_param(flickerless, int, 0); +MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)"); +module_param(video_nr, int, 0); + +static struct usb_driver se401_driver; + + +/********************************************************************** + * + * Memory management + * + **********************************************************************/ +static void *rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + +static void rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + + + +/**************************************************************************** + * + * se401 register read/write functions + * + ***************************************************************************/ + +static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req, + unsigned short value, unsigned char *cp, int size) +{ + return usb_control_msg ( + se401->dev, + set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0), + req, + (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + 0, + cp, + size, + 1000 + ); +} + +static int se401_set_feature(struct usb_se401 *se401, unsigned short selector, + unsigned short param) +{ + /* specs say that the selector (address) should go in the value field + and the param in index, but in the logs of the windows driver they do + this the other way around... + */ + return usb_control_msg ( + se401->dev, + usb_sndctrlpipe(se401->dev, 0), + SE401_REQ_SET_EXT_FEATURE, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + param, + selector, + NULL, + 0, + 1000 + ); +} + +static unsigned short se401_get_feature(struct usb_se401 *se401, + unsigned short selector) +{ + /* For 'set' the selecetor should be in index, not sure if the spec is + wrong here to.... + */ + unsigned char cp[2]; + usb_control_msg ( + se401->dev, + usb_rcvctrlpipe(se401->dev, 0), + SE401_REQ_GET_EXT_FEATURE, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, + selector, + cp, + 2, + 1000 + ); + return cp[0]+cp[1]*256; +} + +/**************************************************************************** + * + * Camera control + * + ***************************************************************************/ + + +static int se401_send_pict(struct usb_se401 *se401) +{ + se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */ + se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */ + se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */ + se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */ + se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */ + se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */ + se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */ + + return 0; +} + +static void se401_set_exposure(struct usb_se401 *se401, int brightness) +{ + int integration=brightness<<5; + + if (flickerless==50) { + integration=integration-integration%106667; + } + if (flickerless==60) { + integration=integration-integration%88889; + } + se401->brightness=integration>>5; + se401->expose_h=(integration>>16)&0xff; + se401->expose_m=(integration>>8)&0xff; + se401->expose_l=integration&0xff; +} + +static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p) +{ + p->brightness=se401->brightness; + if (se401->enhance) { + p->whiteness=32768; + } else { + p->whiteness=0; + } + p->colour=65535; + p->contrast=65535; + p->hue=se401->rgain<<10; + p->palette=se401->palette; + p->depth=3; /* rgb24 */ + return 0; +} + + +static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p) +{ + if (p->palette != VIDEO_PALETTE_RGB24) + return 1; + se401->palette=p->palette; + if (p->hue!=se401->hue) { + se401->rgain= p->hue>>10; + se401->bgain= 0x40-(p->hue>>10); + se401->hue=p->hue; + } + if (p->brightness!=se401->brightness) { + se401_set_exposure(se401, p->brightness); + } + if (p->whiteness>=32768) { + se401->enhance=1; + } else { + se401->enhance=0; + } + se401_send_pict(se401); + se401_send_pict(se401); + return 0; +} + +/* + Hyundai have some really nice docs about this and other sensor related + stuff on their homepage: www.hei.co.kr +*/ +static void se401_auto_resetlevel(struct usb_se401 *se401) +{ + unsigned int ahrc, alrc; + int oldreset=se401->resetlevel; + + /* For some reason this normally read-only register doesn't get reset + to zero after reading them just once... + */ + se401_get_feature(se401, HV7131_REG_HIREFNOH); + se401_get_feature(se401, HV7131_REG_HIREFNOL); + se401_get_feature(se401, HV7131_REG_LOREFNOH); + se401_get_feature(se401, HV7131_REG_LOREFNOL); + ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + + se401_get_feature(se401, HV7131_REG_HIREFNOL); + alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) + + se401_get_feature(se401, HV7131_REG_LOREFNOL); + + /* Not an exact science, but it seems to work pretty well... */ + if (alrc > 10) { + while (alrc>=10 && se401->resetlevel < 63) { + se401->resetlevel++; + alrc /=2; + } + } else if (ahrc > 20) { + while (ahrc>=20 && se401->resetlevel > 0) { + se401->resetlevel--; + ahrc /=2; + } + } + if (se401->resetlevel!=oldreset) + se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); + + return; +} + +/* irq handler for snapshot button */ +static void se401_button_irq(struct urb *urb, struct pt_regs *regs) +{ + struct usb_se401 *se401 = urb->context; + int status; + + if (!se401->dev) { + info("ohoh: device vapourished"); + return; + } + + switch (urb->status) { + case 0: + /* success */ + break; + 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; + } + + if (urb->actual_length >=2) { + if (se401->button) + se401->buttonpressed=1; + } +exit: + status = usb_submit_urb (urb, GFP_ATOMIC); + if (status) + err ("%s - usb_submit_urb failed with result %d", + __FUNCTION__, status); +} + +static void se401_video_irq(struct urb *urb, struct pt_regs *regs) +{ + struct usb_se401 *se401 = urb->context; + int length = urb->actual_length; + + /* ohoh... */ + if (!se401->streaming) + return; + + if (!se401->dev) { + info ("ohoh: device vapourished"); + return; + } + + /* 0 sized packets happen if we are to fast, but sometimes the camera + keeps sending them forever... + */ + if (length && !urb->status) { + se401->nullpackets=0; + switch(se401->scratch[se401->scratch_next].state) { + case BUFFER_READY: + case BUFFER_BUSY: { + se401->dropped++; + break; + } + case BUFFER_UNUSED: { + memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length); + se401->scratch[se401->scratch_next].state=BUFFER_READY; + se401->scratch[se401->scratch_next].offset=se401->bayeroffset; + se401->scratch[se401->scratch_next].length=length; + if (waitqueue_active(&se401->wq)) { + wake_up_interruptible(&se401->wq); + } + se401->scratch_overflow=0; + se401->scratch_next++; + if (se401->scratch_next>=SE401_NUMSCRATCH) + se401->scratch_next=0; + break; + } + } + se401->bayeroffset+=length; + if (se401->bayeroffset>=se401->cheight*se401->cwidth) { + se401->bayeroffset=0; + } + } else { + se401->nullpackets++; + if (se401->nullpackets > SE401_MAX_NULLPACKETS) { + if (waitqueue_active(&se401->wq)) { + wake_up_interruptible(&se401->wq); + } + } + } + + /* Resubmit urb for new data */ + urb->status=0; + urb->dev=se401->dev; + if(usb_submit_urb(urb, GFP_KERNEL)) + info("urb burned down"); + return; +} + +static void se401_send_size(struct usb_se401 *se401, int width, int height) +{ + int i=0; + int mode=0x03; /* No compression */ + int sendheight=height; + int sendwidth=width; + + /* JangGu compression can only be used with the camera supported sizes, + but bayer seems to work with any size that fits on the sensor. + We check if we can use compression with the current size with either + 4 or 16 times subcapturing, if not we use uncompressed bayer data + but this will result in cutouts of the maximum size.... + */ + while (isizes && !(se401->width[i]==width && se401->height[i]==height)) + i++; + while (isizes) { + if (se401->width[i]==width*2 && se401->height[i]==height*2) { + sendheight=se401->height[i]; + sendwidth=se401->width[i]; + mode=0x40; + } + if (se401->width[i]==width*4 && se401->height[i]==height*4) { + sendheight=se401->height[i]; + sendwidth=se401->width[i]; + mode=0x42; + } + i++; + } + + se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0); + se401_set_feature(se401, SE401_OPERATINGMODE, mode); + + if (mode==0x03) { + se401->format=FMT_BAYER; + } else { + se401->format=FMT_JANGGU; + } + + return; +} + +/* + In this function se401_send_pict is called several times, + for some reason (depending on the state of the sensor and the phase of + the moon :) doing this only in either place doesn't always work... +*/ +static int se401_start_stream(struct usb_se401 *se401) +{ + struct urb *urb; + int err=0, i; + se401->streaming=1; + + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + + /* Set picture settings */ + se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */ + se401_send_pict(se401); + + se401_send_size(se401, se401->cwidth, se401->cheight); + + se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0); + + /* Do some memory allocation */ + for (i=0; iframe[i].data=se401->fbuf + i * se401->maxframesize; + se401->frame[i].curpix=0; + } + for (i=0; isbuf[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL); + } + + se401->bayeroffset=0; + se401->scratch_next=0; + se401->scratch_use=0; + se401->scratch_overflow=0; + for (i=0; iscratch[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL); + se401->scratch[i].state=BUFFER_UNUSED; + } + + for (i=0; idev, + usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT), + se401->sbuf[i].data, SE401_PACKETSIZE, + se401_video_irq, + se401); + + se401->urb[i]=urb; + + err=usb_submit_urb(se401->urb[i], GFP_KERNEL); + if(err) + err("urb burned down"); + } + + se401->framecount=0; + + return 0; +} + +static int se401_stop_stream(struct usb_se401 *se401) +{ + int i; + + if (!se401->streaming || !se401->dev) + return 1; + + se401->streaming=0; + + se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0); + + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); + + for (i=0; iurb[i]) { + usb_kill_urb(se401->urb[i]); + usb_free_urb(se401->urb[i]); + se401->urb[i]=NULL; + kfree(se401->sbuf[i].data); + } + for (i=0; iscratch[i].data); + se401->scratch[i].data=NULL; + } + + return 0; +} + +static int se401_set_size(struct usb_se401 *se401, int width, int height) +{ + int wasstreaming=se401->streaming; + /* Check to see if we need to change */ + if (se401->cwidth==width && se401->cheight==height) + return 0; + + /* Check for a valid mode */ + if (!width || !height) + return 1; + if ((width & 1) || (height & 1)) + return 1; + if (width>se401->width[se401->sizes-1]) + return 1; + if (height>se401->height[se401->sizes-1]) + return 1; + + /* Stop a current stream and start it again at the new size */ + if (wasstreaming) + se401_stop_stream(se401); + se401->cwidth=width; + se401->cheight=height; + if (wasstreaming) + se401_start_stream(se401); + return 0; +} + + +/**************************************************************************** + * + * Video Decoding + * + ***************************************************************************/ + +/* + This shouldn't really be done in a v4l driver.... + But it does make the image look a lot more usable. + Basically it lifts the dark pixels more than the light pixels. +*/ +static inline void enhance_picture(unsigned char *frame, int len) +{ + while (len--) { + *frame=(((*frame^255)*(*frame^255))/255)^255; + frame++; + } +} + +static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data) +{ + struct se401_frame *frame=&se401->frame[se401->curframe]; + int linelength=se401->cwidth*3; + + if (frame->curlinepix >= linelength) { + frame->curlinepix=0; + frame->curline+=linelength; + } + + /* First three are absolute, all others relative. + * Format is rgb from right to left (mirrorred image), + * we flip it to get bgr from left to right. */ + if (frame->curlinepix < 3) { + *(frame->curline-frame->curlinepix)=1+data*4; + } else { + *(frame->curline-frame->curlinepix)= + *(frame->curline-frame->curlinepix+3)+data*4; + } + frame->curlinepix++; +} + +static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength) +{ + int pos=0; + int vlc_cod=0; + int vlc_size=0; + int vlc_data=0; + int bit_cur; + int bit; + data+=4; + while (pos < packetlength) { + bit_cur=8; + while (bit_cur && bit_exp) { + bit=((*data)>>(bit_cur-1))&1; + if (!vlc_cod) { + if (bit) { + vlc_size++; + } else { + if (!vlc_size) { + decode_JangGu_integrate(se401, 0); + } else { + vlc_cod=2; + vlc_data=0; + } + } + } else { + if (vlc_cod==2) { + if (!bit) + vlc_data = -(1<data; + int len=buffer->length; + int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size; + int datapos=0; + + /* New image? */ + if (!se401->frame[se401->curframe].curpix) { + se401->frame[se401->curframe].curlinepix=0; + se401->frame[se401->curframe].curline= + se401->frame[se401->curframe].data+ + se401->cwidth*3-1; + if (se401->frame[se401->curframe].grabstate==FRAME_READY) + se401->frame[se401->curframe].grabstate=FRAME_GRABBING; + se401->vlcdatapos=0; + } + while (datapos < len) { + size=1024-se401->vlcdatapos; + if (size+datapos > len) + size=len-datapos; + memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size); + se401->vlcdatapos+=size; + packetlength=0; + if (se401->vlcdatapos >= 4) { + bit_exp=se401->vlcdata[3]+(se401->vlcdata[2]<<8); + pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8); + frameinfo=se401->vlcdata[0]&0xc0; + packetlength=((bit_exp+47)>>4)<<1; + if (packetlength > 1024) { + se401->vlcdatapos=0; + datapos=len; + packetlength=0; + se401->error++; + se401->frame[se401->curframe].curpix=0; + } + } + if (packetlength && se401->vlcdatapos >= packetlength) { + decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength); + se401->frame[se401->curframe].curpix+=pix_exp*3; + datapos+=size-(se401->vlcdatapos-packetlength); + se401->vlcdatapos=0; + if (se401->frame[se401->curframe].curpix>=se401->cwidth*se401->cheight*3) { + if (se401->frame[se401->curframe].curpix==se401->cwidth*se401->cheight*3) { + if (se401->frame[se401->curframe].grabstate==FRAME_GRABBING) { + se401->frame[se401->curframe].grabstate=FRAME_DONE; + se401->framecount++; + se401->readcount++; + } + if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { + se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1); + } + } else { + se401->error++; + } + se401->frame[se401->curframe].curpix=0; + datapos=len; + } + } else { + datapos+=size; + } + } +} + +static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer) +{ + unsigned char *data=buffer->data; + int len=buffer->length; + int offset=buffer->offset; + int datasize=se401->cwidth*se401->cheight; + struct se401_frame *frame=&se401->frame[se401->curframe]; + + unsigned char *framedata=frame->data, *curline, *nextline; + int width=se401->cwidth; + int blineoffset=0, bline; + int linelength=width*3, i; + + + if (frame->curpix==0) { + if (frame->grabstate==FRAME_READY) { + frame->grabstate=FRAME_GRABBING; + } + frame->curline=framedata+linelength; + frame->curlinepix=0; + } + + if (offset!=frame->curpix) { + /* Regard frame as lost :( */ + frame->curpix=0; + se401->error++; + return; + } + + /* Check if we have to much data */ + if (frame->curpix+len > datasize) { + len=datasize-frame->curpix; + } + if (se401->cheight%4) + blineoffset=1; + bline=frame->curpix/se401->cwidth+blineoffset; + + curline=frame->curline; + nextline=curline+linelength; + if (nextline >= framedata+datasize*3) + nextline=curline; + while (len) { + if (frame->curlinepix>=width) { + frame->curlinepix-=width; + bline=frame->curpix/width+blineoffset; + curline+=linelength*2; + nextline+=linelength*2; + if (curline >= framedata+datasize*3) { + frame->curlinepix++; + curline-=3; + nextline-=3; + len--; + data++; + frame->curpix++; + } + if (nextline >= framedata+datasize*3) + nextline=curline; + } + if ((bline&1)) { + if ((frame->curlinepix&1)) { + *(curline+2)=*data; + *(curline-1)=*data; + *(nextline+2)=*data; + *(nextline-1)=*data; + } else { + *(curline+1)= + (*(curline+1)+*data)/2; + *(curline-2)= + (*(curline-2)+*data)/2; + *(nextline+1)=*data; + *(nextline-2)=*data; + } + } else { + if ((frame->curlinepix&1)) { + *(curline+1)= + (*(curline+1)+*data)/2; + *(curline-2)= + (*(curline-2)+*data)/2; + *(nextline+1)=*data; + *(nextline-2)=*data; + } else { + *curline=*data; + *(curline-3)=*data; + *nextline=*data; + *(nextline-3)=*data; + } + } + frame->curlinepix++; + curline-=3; + nextline-=3; + len--; + data++; + frame->curpix++; + } + frame->curline=curline; + + if (frame->curpix>=datasize) { + /* Fix the top line */ + framedata+=linelength; + for (i=0; icheight; i++) { + *framedata=*(framedata+3); + *(framedata+1)=*(framedata+4); + *(framedata+2)=*(framedata+5); + framedata+=linelength; + } + frame->curpix=0; + frame->grabstate=FRAME_DONE; + se401->framecount++; + se401->readcount++; + if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { + se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1); + } + } +} + +static int se401_newframe(struct usb_se401 *se401, int framenr) +{ + DECLARE_WAITQUEUE(wait, current); + int errors=0; + + while (se401->streaming && + (se401->frame[framenr].grabstate==FRAME_READY || + se401->frame[framenr].grabstate==FRAME_GRABBING) ) { + if(!se401->frame[framenr].curpix) { + errors++; + } + wait_interruptible( + se401->scratch[se401->scratch_use].state!=BUFFER_READY, + &se401->wq, + &wait + ); + if (se401->nullpackets > SE401_MAX_NULLPACKETS) { + se401->nullpackets=0; + info("to many null length packets, restarting capture"); + se401_stop_stream(se401); + se401_start_stream(se401); + } else { + if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) { + se401->frame[framenr].grabstate=FRAME_ERROR; + return -EIO; + } + se401->scratch[se401->scratch_use].state=BUFFER_BUSY; + if (se401->format==FMT_JANGGU) { + decode_JangGu(se401, &se401->scratch[se401->scratch_use]); + } else { + decode_bayer(se401, &se401->scratch[se401->scratch_use]); + } + se401->scratch[se401->scratch_use].state=BUFFER_UNUSED; + se401->scratch_use++; + if (se401->scratch_use>=SE401_NUMSCRATCH) + se401->scratch_use=0; + if (errors > SE401_MAX_ERRORS) { + errors=0; + info("to much errors, restarting capture"); + se401_stop_stream(se401); + se401_start_stream(se401); + } + } + } + + if (se401->frame[framenr].grabstate==FRAME_DONE) + if (se401->enhance) + enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3); + return 0; +} + +static void usb_se401_remove_disconnected (struct usb_se401 *se401) +{ + int i; + + se401->dev = NULL; + + for (i=0; iurb[i]) { + usb_kill_urb(se401->urb[i]); + usb_free_urb(se401->urb[i]); + se401->urb[i] = NULL; + kfree(se401->sbuf[i].data); + } + for (i=0; iscratch[i].data); + } + if (se401->inturb) { + usb_kill_urb(se401->inturb); + usb_free_urb(se401->inturb); + } + info("%s disconnected", se401->camera_name); + + /* Free the memory */ + kfree(se401->width); + kfree(se401->height); + kfree(se401); +} + + + +/**************************************************************************** + * + * Video4Linux + * + ***************************************************************************/ + + +static int se401_open(struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct usb_se401 *se401 = (struct usb_se401 *)dev; + int err = 0; + + if (se401->user) + return -EBUSY; + se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); + if (se401->fbuf) + file->private_data = dev; + else + err = -ENOMEM; + se401->user = !err; + + return err; +} + +static int se401_close(struct inode *inode, struct file *file) +{ + struct video_device *dev = file->private_data; + struct usb_se401 *se401 = (struct usb_se401 *)dev; + int i; + + rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); + if (se401->removed) { + usb_se401_remove_disconnected(se401); + info("device unregistered"); + } else { + for (i=0; iframe[i].grabstate=FRAME_UNUSED; + if (se401->streaming) + se401_stop_stream(se401); + se401->user=0; + } + file->private_data = NULL; + return 0; +} + +static int se401_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct video_device *vdev = file->private_data; + struct usb_se401 *se401 = (struct usb_se401 *)vdev; + + if (!se401->dev) + return -EIO; + + switch (cmd) { + case VIDIOCGCAP: + { + struct video_capability *b = arg; + strcpy(b->name, se401->camera_name); + b->type = VID_TYPE_CAPTURE; + b->channels = 1; + b->audios = 0; + b->maxwidth = se401->width[se401->sizes-1]; + b->maxheight = se401->height[se401->sizes-1]; + b->minwidth = se401->width[0]; + b->minheight = se401->height[0]; + return 0; + } + case VIDIOCGCHAN: + { + struct video_channel *v = arg; + + if (v->channel != 0) + return -EINVAL; + v->flags = 0; + v->tuners = 0; + v->type = VIDEO_TYPE_CAMERA; + strcpy(v->name, "Camera"); + return 0; + } + case VIDIOCSCHAN: + { + struct video_channel *v = arg; + + if (v->channel != 0) + return -EINVAL; + return 0; + } + case VIDIOCGPICT: + { + struct video_picture *p = arg; + + se401_get_pict(se401, p); + return 0; + } + case VIDIOCSPICT: + { + struct video_picture *p = arg; + + if (se401_set_pict(se401, p)) + return -EINVAL; + return 0; + } + case VIDIOCSWIN: + { + struct video_window *vw = arg; + + if (vw->flags) + return -EINVAL; + if (vw->clipcount) + return -EINVAL; + if (se401_set_size(se401, vw->width, vw->height)) + return -EINVAL; + return 0; + } + case VIDIOCGWIN: + { + struct video_window *vw = arg; + + vw->x = 0; /* FIXME */ + vw->y = 0; + vw->chromakey = 0; + vw->flags = 0; + vw->clipcount = 0; + vw->width = se401->cwidth; + vw->height = se401->cheight; + return 0; + } + case VIDIOCGMBUF: + { + struct video_mbuf *vm = arg; + int i; + + memset(vm, 0, sizeof(*vm)); + vm->size = SE401_NUMFRAMES * se401->maxframesize; + vm->frames = SE401_NUMFRAMES; + for (i=0; ioffsets[i] = se401->maxframesize * i; + return 0; + } + case VIDIOCMCAPTURE: + { + struct video_mmap *vm = arg; + + if (vm->format != VIDEO_PALETTE_RGB24) + return -EINVAL; + if (vm->frame >= SE401_NUMFRAMES) + return -EINVAL; + if (se401->frame[vm->frame].grabstate != FRAME_UNUSED) + return -EBUSY; + + /* Is this according to the v4l spec??? */ + if (se401_set_size(se401, vm->width, vm->height)) + return -EINVAL; + se401->frame[vm->frame].grabstate=FRAME_READY; + + if (!se401->streaming) + se401_start_stream(se401); + + /* Set the picture properties */ + if (se401->framecount==0) + se401_send_pict(se401); + /* Calibrate the reset level after a few frames. */ + if (se401->framecount%20==1) + se401_auto_resetlevel(se401); + + return 0; + } + case VIDIOCSYNC: + { + int *frame = arg; + int ret=0; + + if(*frame <0 || *frame >= SE401_NUMFRAMES) + return -EINVAL; + + ret=se401_newframe(se401, *frame); + se401->frame[*frame].grabstate=FRAME_UNUSED; + return ret; + } + case VIDIOCGFBUF: + { + struct video_buffer *vb = arg; + + memset(vb, 0, sizeof(*vb)); + return 0; + } + case VIDIOCKEY: + return 0; + case VIDIOCCAPTURE: + return -EINVAL; + case VIDIOCSFBUF: + return -EINVAL; + case VIDIOCGTUNER: + case VIDIOCSTUNER: + return -EINVAL; + case VIDIOCGFREQ: + case VIDIOCSFREQ: + return -EINVAL; + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + default: + return -ENOIOCTLCMD; + } /* end switch */ + + return 0; +} + +static int se401_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, se401_do_ioctl); +} + +static ssize_t se401_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int realcount=count, ret=0; + struct video_device *dev = file->private_data; + struct usb_se401 *se401 = (struct usb_se401 *)dev; + + + if (se401->dev == NULL) + return -EIO; + if (realcount > se401->cwidth*se401->cheight*3) + realcount=se401->cwidth*se401->cheight*3; + + /* Shouldn't happen: */ + if (se401->frame[0].grabstate==FRAME_GRABBING) + return -EBUSY; + se401->frame[0].grabstate=FRAME_READY; + se401->frame[1].grabstate=FRAME_UNUSED; + se401->curframe=0; + + if (!se401->streaming) + se401_start_stream(se401); + + /* Set the picture properties */ + if (se401->framecount==0) + se401_send_pict(se401); + /* Calibrate the reset level after a few frames. */ + if (se401->framecount%20==1) + se401_auto_resetlevel(se401); + + ret=se401_newframe(se401, 0); + + se401->frame[0].grabstate=FRAME_UNUSED; + if (ret) + return ret; + if (copy_to_user(buf, se401->frame[0].data, realcount)) + return -EFAULT; + + return realcount; +} + +static int se401_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct video_device *dev = file->private_data; + struct usb_se401 *se401 = (struct usb_se401 *)dev; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end-vma->vm_start; + unsigned long page, pos; + + mutex_lock(&se401->lock); + + if (se401->dev == NULL) { + mutex_unlock(&se401->lock); + return -EIO; + } + if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { + mutex_unlock(&se401->lock); + return -EINVAL; + } + pos = (unsigned long)se401->fbuf; + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { + mutex_unlock(&se401->lock); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + mutex_unlock(&se401->lock); + + return 0; +} + +static struct file_operations se401_fops = { + .owner = THIS_MODULE, + .open = se401_open, + .release = se401_close, + .read = se401_read, + .mmap = se401_mmap, + .ioctl = se401_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .llseek = no_llseek, +}; +static struct video_device se401_template = { + .owner = THIS_MODULE, + .name = "se401 USB camera", + .type = VID_TYPE_CAPTURE, + .hardware = VID_HARDWARE_SE401, + .fops = &se401_fops, +}; + + + +/***************************/ +static int se401_init(struct usb_se401 *se401, int button) +{ + int i=0, rc; + unsigned char cp[0x40]; + char temp[200]; + + /* led on */ + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + + /* get camera descriptor */ + rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp)); + if (cp[1]!=0x41) { + err("Wrong descriptor type"); + return 1; + } + sprintf (temp, "ExtraFeatures: %d", cp[3]); + + se401->sizes=cp[4]+cp[5]*256; + se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); + if (!se401->width) + return 1; + se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); + if (!se401->height) { + kfree(se401->width); + return 1; + } + for (i=0; isizes; i++) { + se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256; + se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256; + } + sprintf (temp, "%s Sizes:", temp); + for (i=0; isizes; i++) { + sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]); + } + info("%s", temp); + se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; + + rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); + se401->cwidth=cp[0]+cp[1]*256; + rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp)); + se401->cheight=cp[0]+cp[1]*256; + + if (!cp[2] && SE401_FORMAT_BAYER) { + err("Bayer format not supported!"); + return 1; + } + /* set output mode (BAYER) */ + se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0); + + rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); + se401->brightness=cp[0]+cp[1]*256; + /* some default values */ + se401->resetlevel=0x2d; + se401->rgain=0x20; + se401->ggain=0x20; + se401->bgain=0x20; + se401_set_exposure(se401, 20000); + se401->palette=VIDEO_PALETTE_RGB24; + se401->enhance=1; + se401->dropped=0; + se401->error=0; + se401->framecount=0; + se401->readcount=0; + + /* Start interrupt transfers for snapshot button */ + if (button) { + se401->inturb=usb_alloc_urb(0, GFP_KERNEL); + if (!se401->inturb) { + info("Allocation of inturb failed"); + return 1; + } + usb_fill_int_urb(se401->inturb, se401->dev, + usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT), + &se401->button, sizeof(se401->button), + se401_button_irq, + se401, + 8 + ); + if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { + info("int urb burned down"); + return 1; + } + } else + se401->inturb=NULL; + + /* Flash the led */ + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); + + return 0; +} + +static int se401_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_interface_descriptor *interface; + struct usb_se401 *se401; + char *camera_name=NULL; + int button=1; + + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + interface = &intf->cur_altsetting->desc; + + /* Is it an se401? */ + if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 && + le16_to_cpu(dev->descriptor.idProduct) == 0x0004) { + camera_name="Endpoints/Aox SE401"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 && + le16_to_cpu(dev->descriptor.idProduct) == 0x030b) { + camera_name="Philips PCVC665K"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + le16_to_cpu(dev->descriptor.idProduct) == 0x5001) { + camera_name="Kensington VideoCAM 67014"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + le16_to_cpu(dev->descriptor.idProduct) == 0x5002) { + camera_name="Kensington VideoCAM 6701(5/7)"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + le16_to_cpu(dev->descriptor.idProduct) == 0x5003) { + camera_name="Kensington VideoCAM 67016"; + button=0; + } else + return -ENODEV; + + /* Checking vendor/product should be enough, but what the hell */ + if (interface->bInterfaceClass != 0x00) + return -ENODEV; + if (interface->bInterfaceSubClass != 0x00) + return -ENODEV; + + /* We found one */ + info("SE401 camera found: %s", camera_name); + + if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { + err("couldn't kmalloc se401 struct"); + return -ENOMEM; + } + + se401->dev = dev; + se401->iface = interface->bInterfaceNumber; + se401->camera_name = camera_name; + + info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255); + + if (se401_init(se401, button)) { + kfree(se401); + return -EIO; + } + + memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); + memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name)); + init_waitqueue_head(&se401->wq); + mutex_init(&se401->lock); + wmb(); + + if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + kfree(se401); + err("video_register_device failed"); + return -EIO; + } + info("registered new video device: video%d", se401->vdev.minor); + + usb_set_intfdata (intf, se401); + return 0; +} + +static void se401_disconnect(struct usb_interface *intf) +{ + struct usb_se401 *se401 = usb_get_intfdata (intf); + + usb_set_intfdata (intf, NULL); + if (se401) { + video_unregister_device(&se401->vdev); + if (!se401->user){ + usb_se401_remove_disconnected(se401); + } else { + se401->frame[0].grabstate = FRAME_ERROR; + se401->frame[0].grabstate = FRAME_ERROR; + + se401->streaming = 0; + + wake_up_interruptible(&se401->wq); + se401->removed = 1; + } + } +} + +static struct usb_driver se401_driver = { + .name = "se401", + .id_table = device_table, + .probe = se401_probe, + .disconnect = se401_disconnect, +}; + + + +/**************************************************************************** + * + * Module routines + * + ***************************************************************************/ + +static int __init usb_se401_init(void) +{ + info("SE401 usb camera driver version %s registering", version); + if (flickerless) + if (flickerless!=50 && flickerless!=60) { + info("Invallid flickerless value, use 0, 50 or 60."); + return -1; + } + return usb_register(&se401_driver); +} + +static void __exit usb_se401_exit(void) +{ + usb_deregister(&se401_driver); + info("SE401 driver deregistered"); +} + +module_init(usb_se401_init); +module_exit(usb_se401_exit); diff --git a/drivers/media/video/se401.h b/drivers/media/video/se401.h new file mode 100644 index 000000000000..e88a40d4c86a --- /dev/null +++ b/drivers/media/video/se401.h @@ -0,0 +1,234 @@ + +#ifndef __LINUX_se401_H +#define __LINUX_se401_H + +#include +#include +#include +#include + +#define se401_DEBUG /* Turn on debug messages */ + +#ifdef se401_DEBUG +# define PDEBUG(level, fmt, args...) \ +if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) +#else +# define PDEBUG(level, fmt, args...) do {} while(0) +#endif + +/* An almost drop-in replacement for sleep_on_interruptible */ +#define wait_interruptible(test, queue, wait) \ +{ \ + add_wait_queue(queue, wait); \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (test) \ + schedule(); \ + remove_wait_queue(queue, wait); \ + set_current_state(TASK_RUNNING); \ + if (signal_pending(current)) \ + break; \ +} + +#define SE401_REQ_GET_CAMERA_DESCRIPTOR 0x06 +#define SE401_REQ_START_CONTINUOUS_CAPTURE 0x41 +#define SE401_REQ_STOP_CONTINUOUS_CAPTURE 0x42 +#define SE401_REQ_CAPTURE_FRAME 0x43 +#define SE401_REQ_GET_BRT 0x44 +#define SE401_REQ_SET_BRT 0x45 +#define SE401_REQ_GET_WIDTH 0x4c +#define SE401_REQ_SET_WIDTH 0x4d +#define SE401_REQ_GET_HEIGHT 0x4e +#define SE401_REQ_SET_HEIGHT 0x4f +#define SE401_REQ_GET_OUTPUT_MODE 0x50 +#define SE401_REQ_SET_OUTPUT_MODE 0x51 +#define SE401_REQ_GET_EXT_FEATURE 0x52 +#define SE401_REQ_SET_EXT_FEATURE 0x53 +#define SE401_REQ_CAMERA_POWER 0x56 +#define SE401_REQ_LED_CONTROL 0x57 +#define SE401_REQ_BIOS 0xff + +#define SE401_BIOS_READ 0x07 + +#define SE401_FORMAT_BAYER 0x40 + +/* Hyundai hv7131b registers + 7121 and 7141 should be the same (haven't really checked...) */ +/* Mode registers: */ +#define HV7131_REG_MODE_A 0x00 +#define HV7131_REG_MODE_B 0x01 +#define HV7131_REG_MODE_C 0x02 +/* Frame registers: */ +#define HV7131_REG_FRSU 0x10 +#define HV7131_REG_FRSL 0x11 +#define HV7131_REG_FCSU 0x12 +#define HV7131_REG_FCSL 0x13 +#define HV7131_REG_FWHU 0x14 +#define HV7131_REG_FWHL 0x15 +#define HV7131_REG_FWWU 0x16 +#define HV7131_REG_FWWL 0x17 +/* Timing registers: */ +#define HV7131_REG_THBU 0x20 +#define HV7131_REG_THBL 0x21 +#define HV7131_REG_TVBU 0x22 +#define HV7131_REG_TVBL 0x23 +#define HV7131_REG_TITU 0x25 +#define HV7131_REG_TITM 0x26 +#define HV7131_REG_TITL 0x27 +#define HV7131_REG_TMCD 0x28 +/* Adjust Registers: */ +#define HV7131_REG_ARLV 0x30 +#define HV7131_REG_ARCG 0x31 +#define HV7131_REG_AGCG 0x32 +#define HV7131_REG_ABCG 0x33 +#define HV7131_REG_APBV 0x34 +#define HV7131_REG_ASLP 0x54 +/* Offset Registers: */ +#define HV7131_REG_OFSR 0x50 +#define HV7131_REG_OFSG 0x51 +#define HV7131_REG_OFSB 0x52 +/* REset level statistics registers: */ +#define HV7131_REG_LOREFNOH 0x57 +#define HV7131_REG_LOREFNOL 0x58 +#define HV7131_REG_HIREFNOH 0x59 +#define HV7131_REG_HIREFNOL 0x5a + +/* se401 registers */ +#define SE401_OPERATINGMODE 0x2000 + + +/* size of usb transfers */ +#define SE401_PACKETSIZE 4096 +/* number of queued bulk transfers to use, should be about 8 */ +#define SE401_NUMSBUF 1 +/* read the usb specs for this one :) */ +#define SE401_VIDEO_ENDPOINT 1 +#define SE401_BUTTON_ENDPOINT 2 +/* number of frames supported by the v4l part */ +#define SE401_NUMFRAMES 2 +/* scratch buffers for passing data to the decoders */ +#define SE401_NUMSCRATCH 32 +/* maximum amount of data in a JangGu packet */ +#define SE401_VLCDATALEN 1024 +/* number of nul sized packets to receive before kicking the camera */ +#define SE401_MAX_NULLPACKETS 4000 +/* number of decoding errors before kicking the camera */ +#define SE401_MAX_ERRORS 200 + +struct usb_device; + +struct se401_sbuf { + unsigned char *data; +}; + +enum { + FRAME_UNUSED, /* Unused (no MCAPTURE) */ + FRAME_READY, /* Ready to start grabbing */ + FRAME_GRABBING, /* In the process of being grabbed into */ + FRAME_DONE, /* Finished grabbing, but not been synced yet */ + FRAME_ERROR, /* Something bad happened while processing */ +}; + +enum { + FMT_BAYER, + FMT_JANGGU, +}; + +enum { + BUFFER_UNUSED, + BUFFER_READY, + BUFFER_BUSY, + BUFFER_DONE, +}; + +struct se401_scratch { + unsigned char *data; + volatile int state; + int offset; + int length; +}; + +struct se401_frame { + unsigned char *data; /* Frame buffer */ + + volatile int grabstate; /* State of grabbing */ + + unsigned char *curline; + int curlinepix; + int curpix; +}; + +struct usb_se401 { + struct video_device vdev; + + /* Device structure */ + struct usb_device *dev; + + unsigned char iface; + + char *camera_name; + + int change; + int brightness; + int hue; + int rgain; + int ggain; + int bgain; + int expose_h; + int expose_m; + int expose_l; + int resetlevel; + + int enhance; + + int format; + int sizes; + int *width; + int *height; + int cwidth; /* current width */ + int cheight; /* current height */ + int palette; + int maxframesize; + int cframesize; /* current framesize */ + + struct mutex lock; + int user; /* user count for exclusive use */ + int removed; /* device disconnected */ + + int streaming; /* Are we streaming video? */ + + char *fbuf; /* Videodev buffer area */ + + struct urb *urb[SE401_NUMSBUF]; + struct urb *inturb; + + int button; + int buttonpressed; + + int curframe; /* Current receiving frame */ + struct se401_frame frame[SE401_NUMFRAMES]; + int readcount; + int framecount; + int error; + int dropped; + + int scratch_next; + int scratch_use; + int scratch_overflow; + struct se401_scratch scratch[SE401_NUMSCRATCH]; + + /* Decoder specific data: */ + unsigned char vlcdata[SE401_VLCDATALEN]; + int vlcdatapos; + int bayeroffset; + + struct se401_sbuf sbuf[SE401_NUMSBUF]; + + wait_queue_head_t wq; /* Processes waiting */ + + int nullpackets; +}; + + + +#endif + diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile new file mode 100644 index 000000000000..8bcb0f71d69f --- /dev/null +++ b/drivers/media/video/sn9c102/Makefile @@ -0,0 +1,7 @@ +sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ + sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \ + sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ + sn9c102_tas5130d1b.o + +obj-$(CONFIG_USB_SN9C102) += sn9c102.o + diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h new file mode 100644 index 000000000000..1d70a62b9f23 --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102.h @@ -0,0 +1,218 @@ +/*************************************************************************** + * V4L2 driver for SN9C10x PC Camera Controllers * + * * + * Copyright (C) 2004-2006 by Luca Risolia * + * * + * 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. * + ***************************************************************************/ + +#ifndef _SN9C102_H_ +#define _SN9C102_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sn9c102_sensor.h" + +/*****************************************************************************/ + +#define SN9C102_DEBUG +#define SN9C102_DEBUG_LEVEL 2 +#define SN9C102_MAX_DEVICES 64 +#define SN9C102_PRESERVE_IMGSCALE 0 +#define SN9C102_FORCE_MUNMAP 0 +#define SN9C102_MAX_FRAMES 32 +#define SN9C102_URBS 2 +#define SN9C102_ISO_PACKETS 7 +#define SN9C102_ALTERNATE_SETTING 8 +#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS) +#define SN9C102_CTRL_TIMEOUT 300 +#define SN9C102_FRAME_TIMEOUT 2 + +/*****************************************************************************/ + +enum sn9c102_bridge { + BRIDGE_SN9C101 = 0x01, + BRIDGE_SN9C102 = 0x02, + BRIDGE_SN9C103 = 0x04, +}; + +SN9C102_ID_TABLE +SN9C102_SENSOR_TABLE + +enum sn9c102_frame_state { + F_UNUSED, + F_QUEUED, + F_GRABBING, + F_DONE, + F_ERROR, +}; + +struct sn9c102_frame_t { + void* bufmem; + struct v4l2_buffer buf; + enum sn9c102_frame_state state; + struct list_head frame; + unsigned long vma_use_count; +}; + +enum sn9c102_dev_state { + DEV_INITIALIZED = 0x01, + DEV_DISCONNECTED = 0x02, + DEV_MISCONFIGURED = 0x04, +}; + +enum sn9c102_io_method { + IO_NONE, + IO_READ, + IO_MMAP, +}; + +enum sn9c102_stream_state { + STREAM_OFF, + STREAM_INTERRUPT, + STREAM_ON, +}; + +typedef char sn9c103_sof_header_t[18]; +typedef char sn9c102_sof_header_t[12]; +typedef char sn9c102_eof_header_t[4]; + +struct sn9c102_sysfs_attr { + u8 reg, i2c_reg; + sn9c103_sof_header_t frame_header; +}; + +struct sn9c102_module_param { + u8 force_munmap; + u16 frame_timeout; +}; + +static DEFINE_MUTEX(sn9c102_sysfs_lock); +static DECLARE_RWSEM(sn9c102_disconnect); + +struct sn9c102_device { + struct video_device* v4ldev; + + enum sn9c102_bridge bridge; + struct sn9c102_sensor sensor; + + struct usb_device* usbdev; + struct urb* urb[SN9C102_URBS]; + void* transfer_buffer[SN9C102_URBS]; + u8* control_buffer; + + struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES]; + struct list_head inqueue, outqueue; + u32 frame_count, nbuffers, nreadbuffers; + + enum sn9c102_io_method io; + enum sn9c102_stream_state stream; + + struct v4l2_jpegcompression compression; + + struct sn9c102_sysfs_attr sysfs; + sn9c103_sof_header_t sof_header; + u16 reg[63]; + + struct sn9c102_module_param module_param; + + enum sn9c102_dev_state state; + u8 users; + + struct mutex dev_mutex, fileop_mutex; + spinlock_t queue_lock; + wait_queue_head_t open, wait_frame, wait_stream; +}; + +/*****************************************************************************/ + +struct sn9c102_device* +sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) +{ + if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) + return cam; + + return NULL; +} + + +void +sn9c102_attach_sensor(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor) +{ + memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); +} + +/*****************************************************************************/ + +#undef DBG +#undef KDBG +#ifdef SN9C102_DEBUG +# define DBG(level, fmt, args...) \ +do { \ + if (debug >= (level)) { \ + if ((level) == 1) \ + dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ + else if ((level) == 2) \ + dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ + else if ((level) >= 3) \ + dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args); \ + } \ +} while (0) +# define V4LDBG(level, name, cmd) \ +do { \ + if (debug >= (level)) \ + v4l_print_ioctl(name, cmd); \ +} while (0) +# define KDBG(level, fmt, args...) \ +do { \ + if (debug >= (level)) { \ + if ((level) == 1 || (level) == 2) \ + pr_info("sn9c102: " fmt "\n", ## args); \ + else if ((level) == 3) \ + pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \ + __LINE__ , ## args); \ + } \ +} while (0) +#else +# define DBG(level, fmt, args...) do {;} while(0) +# define V4LDBG(level, name, cmd) do {;} while(0) +# define KDBG(level, fmt, args...) do {;} while(0) +#endif + +#undef PDBG +#define PDBG(fmt, args...) \ +dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args) + +#undef PDBGG +#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ + +#endif /* _SN9C102_H_ */ diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c new file mode 100644 index 000000000000..4c6cc6395723 --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -0,0 +1,2919 @@ +/*************************************************************************** + * V4L2 driver for SN9C10x PC Camera Controllers * + * * + * Copyright (C) 2004-2006 by Luca Risolia * + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sn9c102.h" + +/*****************************************************************************/ + +#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers" +#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" +#define SN9C102_AUTHOR_EMAIL "" +#define SN9C102_MODULE_LICENSE "GPL" +#define SN9C102_MODULE_VERSION "1:1.27" +#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 27) + +/*****************************************************************************/ + +MODULE_DEVICE_TABLE(usb, sn9c102_id_table); + +MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL); +MODULE_DESCRIPTION(SN9C102_MODULE_NAME); +MODULE_VERSION(SN9C102_MODULE_VERSION); +MODULE_LICENSE(SN9C102_MODULE_LICENSE); + +static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1}; +module_param_array(video_nr, short, NULL, 0444); +MODULE_PARM_DESC(video_nr, + "\n<-1|n[,...]> Specify V4L2 minor mode number." + "\n -1 = use next available (default)" + "\n n = use minor number n (integer >= 0)" + "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES) + " cameras this way." + "\nFor example:" + "\nvideo_nr=-1,2,-1 would assign minor number 2 to" + "\nthe second camera and use auto for the first" + "\none and for every other camera." + "\n"); + +static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] = + SN9C102_FORCE_MUNMAP}; +module_param_array(force_munmap, bool, NULL, 0444); +MODULE_PARM_DESC(force_munmap, + "\n<0|1[,...]> Force the application to unmap previously" + "\nmapped buffer memory before calling any VIDIOC_S_CROP or" + "\nVIDIOC_S_FMT ioctl's. Not all the applications support" + "\nthis feature. This parameter is specific for each" + "\ndetected camera." + "\n 0 = do not force memory unmapping" + "\n 1 = force memory unmapping (save memory)" + "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." + "\n"); + +static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = + SN9C102_FRAME_TIMEOUT}; +module_param_array(frame_timeout, uint, NULL, 0644); +MODULE_PARM_DESC(frame_timeout, + "\n Timeout for a video frame in seconds." + "\nThis parameter is specific for each detected camera." + "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." + "\n"); + +#ifdef SN9C102_DEBUG +static unsigned short debug = SN9C102_DEBUG_LEVEL; +module_param(debug, ushort, 0644); +MODULE_PARM_DESC(debug, + "\n Debugging information level, from 0 to 3:" + "\n0 = none (use carefully)" + "\n1 = critical errors" + "\n2 = significant informations" + "\n3 = more verbose messages" + "\nLevel 3 is useful for testing only, when only " + "one device is used." + "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"." + "\n"); +#endif + +/*****************************************************************************/ + +static sn9c102_sof_header_t sn9c102_sof_header[] = { + {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00}, + {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01}, +}; + +static sn9c103_sof_header_t sn9c103_sof_header[] = { + {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x20}, +}; + +static sn9c102_eof_header_t sn9c102_eof_header[] = { + {0x00, 0x00, 0x00, 0x00}, + {0x40, 0x00, 0x00, 0x00}, + {0x80, 0x00, 0x00, 0x00}, + {0xc0, 0x00, 0x00, 0x00}, +}; + +/*****************************************************************************/ + +static u32 +sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, + enum sn9c102_io_method io) +{ + struct v4l2_pix_format* p = &(cam->sensor.pix_format); + struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); + const size_t imagesize = cam->module_param.force_munmap || + io == IO_READ ? + (p->width * p->height * p->priv) / 8 : + (r->width * r->height * p->priv) / 8; + void* buff = NULL; + u32 i; + + if (count > SN9C102_MAX_FRAMES) + count = SN9C102_MAX_FRAMES; + + cam->nbuffers = count; + while (cam->nbuffers > 0) { + if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) + break; + cam->nbuffers--; + } + + for (i = 0; i < cam->nbuffers; i++) { + cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); + cam->frame[i].buf.index = i; + cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); + cam->frame[i].buf.length = imagesize; + cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cam->frame[i].buf.sequence = 0; + cam->frame[i].buf.field = V4L2_FIELD_NONE; + cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; + cam->frame[i].buf.flags = 0; + } + + return cam->nbuffers; +} + + +static void sn9c102_release_buffers(struct sn9c102_device* cam) +{ + if (cam->nbuffers) { + vfree(cam->frame[0].bufmem); + cam->nbuffers = 0; + } + cam->frame_current = NULL; +} + + +static void sn9c102_empty_framequeues(struct sn9c102_device* cam) +{ + u32 i; + + INIT_LIST_HEAD(&cam->inqueue); + INIT_LIST_HEAD(&cam->outqueue); + + for (i = 0; i < SN9C102_MAX_FRAMES; i++) { + cam->frame[i].state = F_UNUSED; + cam->frame[i].buf.bytesused = 0; + } +} + + +static void sn9c102_requeue_outqueue(struct sn9c102_device* cam) +{ + struct sn9c102_frame_t *i; + + list_for_each_entry(i, &cam->outqueue, frame) { + i->state = F_QUEUED; + list_add(&i->frame, &cam->inqueue); + } + + INIT_LIST_HEAD(&cam->outqueue); +} + + +static void sn9c102_queue_unusedframes(struct sn9c102_device* cam) +{ + unsigned long lock_flags; + u32 i; + + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].state == F_UNUSED) { + cam->frame[i].state = F_QUEUED; + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_add_tail(&cam->frame[i].frame, &cam->inqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + } +} + +/*****************************************************************************/ + +int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index) +{ + struct usb_device* udev = cam->usbdev; + int i, res; + + if (index + sizeof(buff) >= ARRAY_SIZE(cam->reg)) + return -1; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, + index, 0, buff, sizeof(buff), + SN9C102_CTRL_TIMEOUT*sizeof(buff)); + if (res < 0) { + DBG(3, "Failed to write registers (index 0x%02X, error %d)", + index, res); + return -1; + } + + for (i = 0; i < sizeof(buff); i++) + cam->reg[index+i] = buff[i]; + + return 0; +} + + +int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index) +{ + struct usb_device* udev = cam->usbdev; + u8* buff = cam->control_buffer; + int res; + + if (index >= ARRAY_SIZE(cam->reg)) + return -1; + + *buff = value; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, + index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); + if (res < 0) { + DBG(3, "Failed to write a register (value 0x%02X, index " + "0x%02X, error %d)", value, index, res); + return -1; + } + + cam->reg[index] = value; + + return 0; +} + + +/* NOTE: reading some registers always returns 0 */ +static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index) +{ + struct usb_device* udev = cam->usbdev; + u8* buff = cam->control_buffer; + int res; + + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, + index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); + if (res < 0) + DBG(3, "Failed to read a register (index 0x%02X, error %d)", + index, res); + + return (res >= 0) ? (int)(*buff) : -1; +} + + +int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index) +{ + if (index >= ARRAY_SIZE(cam->reg)) + return -1; + + return cam->reg[index]; +} + + +static int +sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor) +{ + int i, r; + + for (i = 1; i <= 5; i++) { + r = sn9c102_read_reg(cam, 0x08); + if (r < 0) + return -EIO; + if (r & 0x04) + return 0; + if (sensor->frequency & SN9C102_I2C_400KHZ) + udelay(5*16); + else + udelay(16*16); + } + return -EBUSY; +} + + +static int +sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor) +{ + int r; + r = sn9c102_read_reg(cam, 0x08); + return (r < 0 || (r >= 0 && !(r & 0x08))) ? -EIO : 0; +} + + +static int +sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor) +{ + int r; + r = sn9c102_read_reg(cam, 0x08); + return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0; +} + + +int +sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor, u8 data0, u8 data1, + u8 n, u8 buffer[]) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + /* Write cycle */ + data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | + ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10; + data[1] = data0; /* I2C slave id */ + data[2] = data1; /* address */ + data[7] = 0x10; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, + 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += sn9c102_i2c_wait(cam, sensor); + + /* Read cycle - n bytes */ + data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | + ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | + (n << 4) | 0x02; + data[1] = data0; + data[7] = 0x10; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, + 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += sn9c102_i2c_wait(cam, sensor); + + /* The first read byte will be placed in data[4] */ + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, + 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += sn9c102_i2c_detect_read_error(cam, sensor); + + PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1, + data[4]); + + if (err) { + DBG(3, "I2C read failed for %s image sensor", sensor->name); + return -1; + } + + if (buffer) + memcpy(buffer, data, sizeof(buffer)); + + return (int)data[4]; +} + + +int +sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor, u8 n, u8 data0, + u8 data1, u8 data2, u8 data3, u8 data4, u8 data5) +{ + struct usb_device* udev = cam->usbdev; + u8* data = cam->control_buffer; + int err = 0, res; + + /* Write cycle. It usually is address + value */ + data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | + ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) + | ((n - 1) << 4); + data[1] = data0; + data[2] = data1; + data[3] = data2; + data[4] = data3; + data[5] = data4; + data[6] = data5; + data[7] = 0x14; + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, + 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); + if (res < 0) + err += res; + + err += sn9c102_i2c_wait(cam, sensor); + err += sn9c102_i2c_detect_write_error(cam, sensor); + + if (err) + DBG(3, "I2C write failed for %s image sensor", sensor->name); + + PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, " + "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X", + n, data0, data1, data2, data3, data4, data5); + + return err ? -1 : 0; +} + + +int +sn9c102_i2c_try_read(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor, u8 address) +{ + return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id, + address, 1, NULL); +} + + +int +sn9c102_i2c_try_write(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor, u8 address, u8 value) +{ + return sn9c102_i2c_try_raw_write(cam, sensor, 3, + sensor->i2c_slave_id, address, + value, 0, 0, 0); +} + + +int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address) +{ + return sn9c102_i2c_try_read(cam, &cam->sensor, address); +} + + +int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value) +{ + return sn9c102_i2c_try_write(cam, &cam->sensor, address, value); +} + +/*****************************************************************************/ + +static void* +sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) +{ + size_t soflen = 0, i; + u8 j, n = 0; + + switch (cam->bridge) { + case BRIDGE_SN9C101: + case BRIDGE_SN9C102: + soflen = sizeof(sn9c102_sof_header_t); + n = sizeof(sn9c102_sof_header) / soflen; + break; + case BRIDGE_SN9C103: + soflen = sizeof(sn9c103_sof_header_t); + n = sizeof(sn9c103_sof_header) / soflen; + } + + for (i = 0; (len >= soflen) && (i <= len - soflen); i++) + for (j = 0; j < n; j++) + /* The invariable part of the header is 6 bytes long */ + if ((cam->bridge != BRIDGE_SN9C103 && + !memcmp(mem + i, sn9c102_sof_header[j], 6)) || + (cam->bridge == BRIDGE_SN9C103 && + !memcmp(mem + i, sn9c103_sof_header[j], 6))) { + memcpy(cam->sof_header, mem + i, soflen); + /* Skip the header */ + return mem + i + soflen; + } + + return NULL; +} + + +static void* +sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) +{ + size_t eoflen = sizeof(sn9c102_eof_header_t), i; + unsigned j, n = sizeof(sn9c102_eof_header) / eoflen; + + if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) + return NULL; /* EOF header does not exist in compressed data */ + + for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++) + for (j = 0; j < n; j++) + if (!memcmp(mem + i, sn9c102_eof_header[j], eoflen)) + return mem + i; + + return NULL; +} + + +static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) +{ + struct sn9c102_device* cam = urb->context; + struct sn9c102_frame_t** f; + size_t imagesize, soflen; + u8 i; + int err = 0; + + if (urb->status == -ENOENT) + return; + + f = &cam->frame_current; + + if (cam->stream == STREAM_INTERRUPT) { + cam->stream = STREAM_OFF; + if ((*f)) + (*f)->state = F_QUEUED; + DBG(3, "Stream interrupted"); + wake_up(&cam->wait_stream); + } + + if (cam->state & DEV_DISCONNECTED) + return; + + if (cam->state & DEV_MISCONFIGURED) { + wake_up_interruptible(&cam->wait_frame); + return; + } + + if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) + goto resubmit_urb; + + if (!(*f)) + (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t, + frame); + + imagesize = (cam->sensor.pix_format.width * + cam->sensor.pix_format.height * + cam->sensor.pix_format.priv) / 8; + + soflen = (cam->bridge) == BRIDGE_SN9C103 ? + sizeof(sn9c103_sof_header_t) : + sizeof(sn9c102_sof_header_t); + + for (i = 0; i < urb->number_of_packets; i++) { + unsigned int img, len, status; + void *pos, *sof, *eof; + + len = urb->iso_frame_desc[i].actual_length; + status = urb->iso_frame_desc[i].status; + pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; + + if (status) { + DBG(3, "Error in isochronous frame"); + (*f)->state = F_ERROR; + continue; + } + + PDBGG("Isochrnous frame: length %u, #%u i", len, i); + +redo: + sof = sn9c102_find_sof_header(cam, pos, len); + if (likely(!sof)) { + eof = sn9c102_find_eof_header(cam, pos, len); + if ((*f)->state == F_GRABBING) { +end_of_frame: + img = len; + + if (eof) + img = (eof > pos) ? eof - pos - 1 : 0; + + if ((*f)->buf.bytesused+img > imagesize) { + u32 b; + b = (*f)->buf.bytesused + img - + imagesize; + img = imagesize - (*f)->buf.bytesused; + DBG(3, "Expected EOF not found: " + "video frame cut"); + if (eof) + DBG(3, "Exceeded limit: +%u " + "bytes", (unsigned)(b)); + } + + memcpy((*f)->bufmem + (*f)->buf.bytesused, pos, + img); + + if ((*f)->buf.bytesused == 0) + do_gettimeofday(&(*f)->buf.timestamp); + + (*f)->buf.bytesused += img; + + if ((*f)->buf.bytesused == imagesize || + (cam->sensor.pix_format.pixelformat == + V4L2_PIX_FMT_SN9C10X && eof)) { + u32 b; + b = (*f)->buf.bytesused; + (*f)->state = F_DONE; + (*f)->buf.sequence= ++cam->frame_count; + spin_lock(&cam->queue_lock); + list_move_tail(&(*f)->frame, + &cam->outqueue); + if (!list_empty(&cam->inqueue)) + (*f) = list_entry( + cam->inqueue.next, + struct sn9c102_frame_t, + frame ); + else + (*f) = NULL; + spin_unlock(&cam->queue_lock); + memcpy(cam->sysfs.frame_header, + cam->sof_header, soflen); + DBG(3, "Video frame captured: %lu " + "bytes", (unsigned long)(b)); + + if (!(*f)) + goto resubmit_urb; + + } else if (eof) { + (*f)->state = F_ERROR; + DBG(3, "Not expected EOF after %lu " + "bytes of image data", + (unsigned long) + ((*f)->buf.bytesused)); + } + + if (sof) /* (1) */ + goto start_of_frame; + + } else if (eof) { + DBG(3, "EOF without SOF"); + continue; + + } else { + PDBGG("Ignoring pointless isochronous frame"); + continue; + } + + } else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) { +start_of_frame: + (*f)->state = F_GRABBING; + (*f)->buf.bytesused = 0; + len -= (sof - pos); + pos = sof; + DBG(3, "SOF detected: new video frame"); + if (len) + goto redo; + + } else if ((*f)->state == F_GRABBING) { + eof = sn9c102_find_eof_header(cam, pos, len); + if (eof && eof < sof) + goto end_of_frame; /* (1) */ + else { + if (cam->sensor.pix_format.pixelformat == + V4L2_PIX_FMT_SN9C10X) { + eof = sof - soflen; + goto end_of_frame; + } else { + DBG(3, "SOF before expected EOF after " + "%lu bytes of image data", + (unsigned long) + ((*f)->buf.bytesused)); + goto start_of_frame; + } + } + } + } + +resubmit_urb: + urb->dev = cam->usbdev; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0 && err != -EPERM) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "usb_submit_urb() failed"); + } + + wake_up_interruptible(&cam->wait_frame); +} + + +static int sn9c102_start_transfer(struct sn9c102_device* cam) +{ + struct usb_device *udev = cam->usbdev; + struct urb* urb; + const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512, + 680, 800, 900, 1023}; + const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512, + 680, 800, 900, 1003}; + const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ? + sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] : + sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING]; + s8 i, j; + int err = 0; + + for (i = 0; i < SN9C102_URBS; i++) { + cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz, + GFP_KERNEL); + if (!cam->transfer_buffer[i]) { + err = -ENOMEM; + DBG(1, "Not enough memory"); + goto free_buffers; + } + } + + for (i = 0; i < SN9C102_URBS; i++) { + urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL); + cam->urb[i] = urb; + if (!urb) { + err = -ENOMEM; + DBG(1, "usb_alloc_urb() failed"); + goto free_urbs; + } + urb->dev = udev; + urb->context = cam; + urb->pipe = usb_rcvisocpipe(udev, 1); + urb->transfer_flags = URB_ISO_ASAP; + urb->number_of_packets = SN9C102_ISO_PACKETS; + urb->complete = sn9c102_urb_complete; + urb->transfer_buffer = cam->transfer_buffer[i]; + urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS; + urb->interval = 1; + for (j = 0; j < SN9C102_ISO_PACKETS; j++) { + urb->iso_frame_desc[j].offset = psz * j; + urb->iso_frame_desc[j].length = psz; + } + } + + /* Enable video */ + if (!(cam->reg[0x01] & 0x04)) { + err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01); + if (err) { + err = -EIO; + DBG(1, "I/O hardware error"); + goto free_urbs; + } + } + + err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING); + if (err) { + DBG(1, "usb_set_interface() failed"); + goto free_urbs; + } + + cam->frame_current = NULL; + + for (i = 0; i < SN9C102_URBS; i++) { + err = usb_submit_urb(cam->urb[i], GFP_KERNEL); + if (err) { + for (j = i-1; j >= 0; j--) + usb_kill_urb(cam->urb[j]); + DBG(1, "usb_submit_urb() failed, error %d", err); + goto free_urbs; + } + } + + return 0; + +free_urbs: + for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++) + usb_free_urb(cam->urb[i]); + +free_buffers: + for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++) + kfree(cam->transfer_buffer[i]); + + return err; +} + + +static int sn9c102_stop_transfer(struct sn9c102_device* cam) +{ + struct usb_device *udev = cam->usbdev; + s8 i; + int err = 0; + + if (cam->state & DEV_DISCONNECTED) + return 0; + + for (i = SN9C102_URBS-1; i >= 0; i--) { + usb_kill_urb(cam->urb[i]); + usb_free_urb(cam->urb[i]); + kfree(cam->transfer_buffer[i]); + } + + err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ + if (err) + DBG(3, "usb_set_interface() failed"); + + return err; +} + + +static int sn9c102_stream_interrupt(struct sn9c102_device* cam) +{ + long timeout; + + cam->stream = STREAM_INTERRUPT; + timeout = wait_event_timeout(cam->wait_stream, + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + SN9C102_URB_TIMEOUT); + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + else if (cam->stream != STREAM_OFF) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "URB timeout reached. The camera is misconfigured. " + "To use it, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + return 0; +} + +/*****************************************************************************/ + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count) +{ + char str[5]; + char* endp; + unsigned long val; + + if (len < 4) { + strncpy(str, buff, len); + str[len+1] = '\0'; + } else { + strncpy(str, buff, 4); + str[4] = '\0'; + } + + val = simple_strtoul(str, &endp, 0); + + *count = 0; + if (val <= 0xff) + *count = (ssize_t)(endp - str); + if ((*count) && (len == *count+1) && (buff[*count] == '\n')) + *count += 1; + + return (u8)val; +} + +/* + NOTE 1: being inside one of the following methods implies that the v4l + device exists for sure (see kobjects and reference counters) + NOTE 2: buffers are PAGE_SIZE long +*/ + +static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf) +{ + struct sn9c102_device* cam; + ssize_t count; + + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&sn9c102_sysfs_lock); + return -ENODEV; + } + + count = sprintf(buf, "%u\n", cam->sysfs.reg); + + mutex_unlock(&sn9c102_sysfs_lock); + + return count; +} + + +static ssize_t +sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) +{ + struct sn9c102_device* cam; + u8 index; + ssize_t count; + + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&sn9c102_sysfs_lock); + return -ENODEV; + } + + index = sn9c102_strtou8(buf, len, &count); + if (index > 0x1f || !count) { + mutex_unlock(&sn9c102_sysfs_lock); + return -EINVAL; + } + + cam->sysfs.reg = index; + + DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg); + DBG(3, "Written bytes: %zd", count); + + mutex_unlock(&sn9c102_sysfs_lock); + + return count; +} + + +static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) +{ + struct sn9c102_device* cam; + ssize_t count; + int val; + + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&sn9c102_sysfs_lock); + return -ENODEV; + } + + if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) { + mutex_unlock(&sn9c102_sysfs_lock); + return -EIO; + } + + count = sprintf(buf, "%d\n", val); + + DBG(3, "Read bytes: %zd", count); + + mutex_unlock(&sn9c102_sysfs_lock); + + return count; +} + + +static ssize_t +sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) +{ + struct sn9c102_device* cam; + u8 value; + ssize_t count; + int err; + + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&sn9c102_sysfs_lock); + return -ENODEV; + } + + value = sn9c102_strtou8(buf, len, &count); + if (!count) { + mutex_unlock(&sn9c102_sysfs_lock); + return -EINVAL; + } + + err = sn9c102_write_reg(cam, value, cam->sysfs.reg); + if (err) { + mutex_unlock(&sn9c102_sysfs_lock); + return -EIO; + } + + DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X", + cam->sysfs.reg, value); + DBG(3, "Written bytes: %zd", count); + + mutex_unlock(&sn9c102_sysfs_lock); + + return count; +} + + +static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf) +{ + struct sn9c102_device* cam; + ssize_t count; + + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&sn9c102_sysfs_lock); + return -ENODEV; + } + + count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg); + + DBG(3, "Read bytes: %zd", count); + + mutex_unlock(&sn9c102_sysfs_lock); + + return count; +} + + +static ssize_t +sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) +{ + struct sn9c102_device* cam; + u8 index; + ssize_t count; + + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&sn9c102_sysfs_lock); + return -ENODEV; + } + + index = sn9c102_strtou8(buf, len, &count); + if (!count) { + mutex_unlock(&sn9c102_sysfs_lock); + return -EINVAL; + } + + cam->sysfs.i2c_reg = index; + + DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); + DBG(3, "Written bytes: %zd", count); + + mutex_unlock(&sn9c102_sysfs_lock); + + return count; +} + + +static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) +{ + struct sn9c102_device* cam; + ssize_t count; + int val; + + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&sn9c102_sysfs_lock); + return -ENODEV; + } + + if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) { + mutex_unlock(&sn9c102_sysfs_lock); + return -ENOSYS; + } + + if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { + mutex_unlock(&sn9c102_sysfs_lock); + return -EIO; + } + + count = sprintf(buf, "%d\n", val); + + DBG(3, "Read bytes: %zd", count); + + mutex_unlock(&sn9c102_sysfs_lock); + + return count; +} + + +static ssize_t +sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) +{ + struct sn9c102_device* cam; + u8 value; + ssize_t count; + int err; + + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&sn9c102_sysfs_lock); + return -ENODEV; + } + + if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) { + mutex_unlock(&sn9c102_sysfs_lock); + return -ENOSYS; + } + + value = sn9c102_strtou8(buf, len, &count); + if (!count) { + mutex_unlock(&sn9c102_sysfs_lock); + return -EINVAL; + } + + err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value); + if (err) { + mutex_unlock(&sn9c102_sysfs_lock); + return -EIO; + } + + DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X", + cam->sysfs.i2c_reg, value); + DBG(3, "Written bytes: %zd", count); + + mutex_unlock(&sn9c102_sysfs_lock); + + return count; +} + + +static ssize_t +sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) +{ + struct sn9c102_device* cam; + enum sn9c102_bridge bridge; + ssize_t res = 0; + u8 value; + ssize_t count; + + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + mutex_unlock(&sn9c102_sysfs_lock); + return -ENODEV; + } + + bridge = cam->bridge; + + mutex_unlock(&sn9c102_sysfs_lock); + + value = sn9c102_strtou8(buf, len, &count); + if (!count) + return -EINVAL; + + switch (bridge) { + case BRIDGE_SN9C101: + case BRIDGE_SN9C102: + if (value > 0x0f) + return -EINVAL; + if ((res = sn9c102_store_reg(cd, "0x11", 4)) >= 0) + res = sn9c102_store_val(cd, buf, len); + break; + case BRIDGE_SN9C103: + if (value > 0x7f) + return -EINVAL; + if ((res = sn9c102_store_reg(cd, "0x04", 4)) >= 0) + res = sn9c102_store_val(cd, buf, len); + break; + } + + return res; +} + + +static ssize_t +sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len) +{ + ssize_t res = 0; + u8 value; + ssize_t count; + + value = sn9c102_strtou8(buf, len, &count); + if (!count || value > 0x7f) + return -EINVAL; + + if ((res = sn9c102_store_reg(cd, "0x06", 4)) >= 0) + res = sn9c102_store_val(cd, buf, len); + + return res; +} + + +static ssize_t +sn9c102_store_red(struct class_device* cd, const char* buf, size_t len) +{ + ssize_t res = 0; + u8 value; + ssize_t count; + + value = sn9c102_strtou8(buf, len, &count); + if (!count || value > 0x7f) + return -EINVAL; + + if ((res = sn9c102_store_reg(cd, "0x05", 4)) >= 0) + res = sn9c102_store_val(cd, buf, len); + + return res; +} + + +static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf) +{ + struct sn9c102_device* cam; + ssize_t count; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) + return -ENODEV; + + count = sizeof(cam->sysfs.frame_header); + memcpy(buf, cam->sysfs.frame_header, count); + + DBG(3, "Frame header, read bytes: %zd", count); + + return count; +} + + +static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, + sn9c102_show_reg, sn9c102_store_reg); +static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR, + sn9c102_show_val, sn9c102_store_val); +static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, + sn9c102_show_i2c_reg, sn9c102_store_i2c_reg); +static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, + sn9c102_show_i2c_val, sn9c102_store_i2c_val); +static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green); +static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue); +static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red); +static CLASS_DEVICE_ATTR(frame_header, S_IRUGO, + sn9c102_show_frame_header, NULL); + + +static void sn9c102_create_sysfs(struct sn9c102_device* cam) +{ + struct video_device *v4ldev = cam->v4ldev; + + video_device_create_file(v4ldev, &class_device_attr_reg); + video_device_create_file(v4ldev, &class_device_attr_val); + video_device_create_file(v4ldev, &class_device_attr_frame_header); + if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) + video_device_create_file(v4ldev, &class_device_attr_green); + else if (cam->bridge == BRIDGE_SN9C103) { + video_device_create_file(v4ldev, &class_device_attr_blue); + video_device_create_file(v4ldev, &class_device_attr_red); + } + if (cam->sensor.sysfs_ops) { + video_device_create_file(v4ldev, &class_device_attr_i2c_reg); + video_device_create_file(v4ldev, &class_device_attr_i2c_val); + } +} +#endif /* CONFIG_VIDEO_ADV_DEBUG */ + +/*****************************************************************************/ + +static int +sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18); + else + err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18); + + return err ? -EIO : 0; +} + + +static int +sn9c102_set_compression(struct sn9c102_device* cam, + struct v4l2_jpegcompression* compression) +{ + int err = 0; + + if (compression->quality == 0) + err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17); + else if (compression->quality == 1) + err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17); + + return err ? -EIO : 0; +} + + +static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale) +{ + u8 r = 0; + int err = 0; + + if (scale == 1) + r = cam->reg[0x18] & 0xcf; + else if (scale == 2) { + r = cam->reg[0x18] & 0xcf; + r |= 0x10; + } else if (scale == 4) + r = cam->reg[0x18] | 0x20; + + err += sn9c102_write_reg(cam, r, 0x18); + if (err) + return -EIO; + + PDBGG("Scaling factor: %u", scale); + + return 0; +} + + +static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = &cam->sensor; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left), + v_start = (u8)(rect->top - s->cropcap.bounds.top), + h_size = (u8)(rect->width / 16), + v_size = (u8)(rect->height / 16); + int err = 0; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + err += sn9c102_write_reg(cam, h_size, 0x15); + err += sn9c102_write_reg(cam, v_size, 0x16); + if (err) + return -EIO; + + PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size " + "%u %u %u %u", h_start, v_start, h_size, v_size); + + return 0; +} + + +static int sn9c102_init(struct sn9c102_device* cam) +{ + struct sn9c102_sensor* s = &cam->sensor; + struct v4l2_control ctrl; + struct v4l2_queryctrl *qctrl; + struct v4l2_rect* rect; + u8 i = 0; + int err = 0; + + if (!(cam->state & DEV_INITIALIZED)) { + init_waitqueue_head(&cam->open); + qctrl = s->qctrl; + rect = &(s->cropcap.defrect); + } else { /* use current values */ + qctrl = s->_qctrl; + rect = &(s->_rect); + } + + err += sn9c102_set_scale(cam, rect->width / s->pix_format.width); + err += sn9c102_set_crop(cam, rect); + if (err) + return err; + + if (s->init) { + err = s->init(cam); + if (err) { + DBG(3, "Sensor initialization failed"); + return err; + } + } + + if (!(cam->state & DEV_INITIALIZED)) + cam->compression.quality = cam->reg[0x17] & 0x01 ? 0 : 1; + else + err += sn9c102_set_compression(cam, &cam->compression); + err += sn9c102_set_pix_format(cam, &s->pix_format); + if (s->set_pix_format) + err += s->set_pix_format(cam, &s->pix_format); + if (err) + return err; + + if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) + DBG(3, "Compressed video format is active, quality %d", + cam->compression.quality); + else + DBG(3, "Uncompressed video format is active"); + + if (s->set_crop) + if ((err = s->set_crop(cam, rect))) { + DBG(3, "set_crop() failed"); + return err; + } + + if (s->set_ctrl) { + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (s->qctrl[i].id != 0 && + !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { + ctrl.id = s->qctrl[i].id; + ctrl.value = qctrl[i].default_value; + err = s->set_ctrl(cam, &ctrl); + if (err) { + DBG(3, "Set %s control failed", + s->qctrl[i].name); + return err; + } + DBG(3, "Image sensor supports '%s' control", + s->qctrl[i].name); + } + } + + if (!(cam->state & DEV_INITIALIZED)) { + mutex_init(&cam->fileop_mutex); + spin_lock_init(&cam->queue_lock); + init_waitqueue_head(&cam->wait_frame); + init_waitqueue_head(&cam->wait_stream); + cam->nreadbuffers = 2; + memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); + memcpy(&(s->_rect), &(s->cropcap.defrect), + sizeof(struct v4l2_rect)); + cam->state |= DEV_INITIALIZED; + } + + DBG(2, "Initialization succeeded"); + return 0; +} + + +static void sn9c102_release_resources(struct sn9c102_device* cam) +{ + mutex_lock(&sn9c102_sysfs_lock); + + DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); + video_set_drvdata(cam->v4ldev, NULL); + video_unregister_device(cam->v4ldev); + + usb_put_dev(cam->usbdev); + + mutex_unlock(&sn9c102_sysfs_lock); + + kfree(cam->control_buffer); +} + +/*****************************************************************************/ + +static int sn9c102_open(struct inode* inode, struct file* filp) +{ + struct sn9c102_device* cam; + int err = 0; + + /* + This is the only safe way to prevent race conditions with + disconnect + */ + if (!down_read_trylock(&sn9c102_disconnect)) + return -ERESTARTSYS; + + cam = video_get_drvdata(video_devdata(filp)); + + if (mutex_lock_interruptible(&cam->dev_mutex)) { + up_read(&sn9c102_disconnect); + return -ERESTARTSYS; + } + + if (cam->users) { + DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); + if ((filp->f_flags & O_NONBLOCK) || + (filp->f_flags & O_NDELAY)) { + err = -EWOULDBLOCK; + goto out; + } + mutex_unlock(&cam->dev_mutex); + err = wait_event_interruptible_exclusive(cam->open, + cam->state & DEV_DISCONNECTED + || !cam->users); + if (err) { + up_read(&sn9c102_disconnect); + return err; + } + if (cam->state & DEV_DISCONNECTED) { + up_read(&sn9c102_disconnect); + return -ENODEV; + } + mutex_lock(&cam->dev_mutex); + } + + + if (cam->state & DEV_MISCONFIGURED) { + err = sn9c102_init(cam); + if (err) { + DBG(1, "Initialization failed again. " + "I will retry on next open()."); + goto out; + } + cam->state &= ~DEV_MISCONFIGURED; + } + + if ((err = sn9c102_start_transfer(cam))) + goto out; + + filp->private_data = cam; + cam->users++; + cam->io = IO_NONE; + cam->stream = STREAM_OFF; + cam->nbuffers = 0; + cam->frame_count = 0; + sn9c102_empty_framequeues(cam); + + DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); + +out: + mutex_unlock(&cam->dev_mutex); + up_read(&sn9c102_disconnect); + return err; +} + + +static int sn9c102_release(struct inode* inode, struct file* filp) +{ + struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + + mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ + + sn9c102_stop_transfer(cam); + + sn9c102_release_buffers(cam); + + if (cam->state & DEV_DISCONNECTED) { + sn9c102_release_resources(cam); + mutex_unlock(&cam->dev_mutex); + kfree(cam); + return 0; + } + + cam->users--; + wake_up_interruptible_nr(&cam->open, 1); + + DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); + + mutex_unlock(&cam->dev_mutex); + + return 0; +} + + +static ssize_t +sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) +{ + struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + struct sn9c102_frame_t* f, * i; + unsigned long lock_flags; + long timeout; + int err = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + if (cam->io == IO_MMAP) { + DBG(3, "Close and open the device again to choose " + "the read method"); + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + if (cam->io == IO_NONE) { + if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) { + DBG(1, "read() failed, not enough memory"); + mutex_unlock(&cam->fileop_mutex); + return -ENOMEM; + } + cam->io = IO_READ; + cam->stream = STREAM_ON; + } + + if (list_empty(&cam->inqueue)) { + if (!list_empty(&cam->outqueue)) + sn9c102_empty_framequeues(cam); + sn9c102_queue_unusedframes(cam); + } + + if (!count) { + mutex_unlock(&cam->fileop_mutex); + return 0; + } + + if (list_empty(&cam->outqueue)) { + if (filp->f_flags & O_NONBLOCK) { + mutex_unlock(&cam->fileop_mutex); + return -EAGAIN; + } + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) { + mutex_unlock(&cam->fileop_mutex); + return timeout; + } + if (cam->state & DEV_DISCONNECTED) { + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + if (!timeout || (cam->state & DEV_MISCONFIGURED)) { + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + } + + f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame); + + if (count > f->buf.bytesused) + count = f->buf.bytesused; + + if (copy_to_user(buf, f->bufmem, count)) { + err = -EFAULT; + goto exit; + } + *f_pos += count; + +exit: + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_for_each_entry(i, &cam->outqueue, frame) + i->state = F_UNUSED; + INIT_LIST_HEAD(&cam->outqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + sn9c102_queue_unusedframes(cam); + + PDBGG("Frame #%lu, bytes read: %zu", + (unsigned long)f->buf.index, count); + + mutex_unlock(&cam->fileop_mutex); + + return count; +} + + +static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) +{ + struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + struct sn9c102_frame_t* f; + unsigned long lock_flags; + unsigned int mask = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return POLLERR; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + goto error; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + goto error; + } + + if (cam->io == IO_NONE) { + if (!sn9c102_request_buffers(cam, cam->nreadbuffers, + IO_READ)) { + DBG(1, "poll() failed, not enough memory"); + goto error; + } + cam->io = IO_READ; + cam->stream = STREAM_ON; + } + + if (cam->io == IO_READ) { + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_for_each_entry(f, &cam->outqueue, frame) + f->state = F_UNUSED; + INIT_LIST_HEAD(&cam->outqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + sn9c102_queue_unusedframes(cam); + } + + poll_wait(filp, &cam->wait_frame, wait); + + if (!list_empty(&cam->outqueue)) + mask |= POLLIN | POLLRDNORM; + + mutex_unlock(&cam->fileop_mutex); + + return mask; + +error: + mutex_unlock(&cam->fileop_mutex); + return POLLERR; +} + + +static void sn9c102_vm_open(struct vm_area_struct* vma) +{ + struct sn9c102_frame_t* f = vma->vm_private_data; + f->vma_use_count++; +} + + +static void sn9c102_vm_close(struct vm_area_struct* vma) +{ + /* NOTE: buffers are not freed here */ + struct sn9c102_frame_t* f = vma->vm_private_data; + f->vma_use_count--; +} + + +static struct vm_operations_struct sn9c102_vm_ops = { + .open = sn9c102_vm_open, + .close = sn9c102_vm_close, +}; + + +static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) +{ + struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + unsigned long size = vma->vm_end - vma->vm_start, + start = vma->vm_start; + void *pos; + u32 i; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || + size != PAGE_ALIGN(cam->frame[0].buf.length)) { + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + for (i = 0; i < cam->nbuffers; i++) { + if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) + break; + } + if (i == cam->nbuffers) { + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED; + + pos = cam->frame[i].bufmem; + while (size > 0) { /* size is page-aligned */ + if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { + mutex_unlock(&cam->fileop_mutex); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + size -= PAGE_SIZE; + } + + vma->vm_ops = &sn9c102_vm_ops; + vma->vm_private_data = &cam->frame[i]; + + sn9c102_vm_open(vma); + + mutex_unlock(&cam->fileop_mutex); + + return 0; +} + +/*****************************************************************************/ + +static int +sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_capability cap = { + .driver = "sn9c102", + .version = SN9C102_MODULE_VERSION_CODE, + .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING, + }; + + strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); + if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) + strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, + sizeof(cap.bus_info)); + + if (copy_to_user(arg, &cap, sizeof(cap))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_input i; + + if (copy_from_user(&i, arg, sizeof(i))) + return -EFAULT; + + if (i.index) + return -EINVAL; + + memset(&i, 0, sizeof(i)); + strcpy(i.name, "Camera"); + i.type = V4L2_INPUT_TYPE_CAMERA; + + if (copy_to_user(arg, &i, sizeof(i))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg) +{ + int index = 0; + + if (copy_to_user(arg, &index, sizeof(index))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg) +{ + int index; + + if (copy_from_user(&index, arg, sizeof(index))) + return -EFAULT; + + if (index != 0) + return -EINVAL; + + return 0; +} + + +static int +sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg) +{ + struct sn9c102_sensor* s = &cam->sensor; + struct v4l2_queryctrl qc; + u8 i; + + if (copy_from_user(&qc, arg, sizeof(qc))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (qc.id && qc.id == s->qctrl[i].id) { + memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); + if (copy_to_user(arg, &qc, sizeof(qc))) + return -EFAULT; + return 0; + } + + return -EINVAL; +} + + +static int +sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg) +{ + struct sn9c102_sensor* s = &cam->sensor; + struct v4l2_control ctrl; + int err = 0; + u8 i; + + if (!s->get_ctrl && !s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + + if (!s->get_ctrl) { + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (ctrl.id && ctrl.id == s->qctrl[i].id) { + ctrl.value = s->_qctrl[i].default_value; + goto exit; + } + return -EINVAL; + } else + err = s->get_ctrl(cam, &ctrl); + +exit: + if (copy_to_user(arg, &ctrl, sizeof(ctrl))) + return -EFAULT; + + return err; +} + + +static int +sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) +{ + struct sn9c102_sensor* s = &cam->sensor; + struct v4l2_control ctrl; + u8 i; + int err = 0; + + if (!s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (ctrl.id == s->qctrl[i].id) { + if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) + return -EINVAL; + if (ctrl.value < s->qctrl[i].minimum || + ctrl.value > s->qctrl[i].maximum) + return -ERANGE; + ctrl.value -= ctrl.value % s->qctrl[i].step; + break; + } + + if ((err = s->set_ctrl(cam, &ctrl))) + return err; + + s->_qctrl[i].default_value = ctrl.value; + + PDBGG("VIDIOC_S_CTRL: id %lu, value %lu", + (unsigned long)ctrl.id, (unsigned long)ctrl.value); + + return 0; +} + + +static int +sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_cropcap* cc = &(cam->sensor.cropcap); + + cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cc->pixelaspect.numerator = 1; + cc->pixelaspect.denominator = 1; + + if (copy_to_user(arg, cc, sizeof(*cc))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg) +{ + struct sn9c102_sensor* s = &cam->sensor; + struct v4l2_crop crop = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + }; + + memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); + + if (copy_to_user(arg, &crop, sizeof(crop))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) +{ + struct sn9c102_sensor* s = &cam->sensor; + struct v4l2_crop crop; + struct v4l2_rect* rect; + struct v4l2_rect* bounds = &(s->cropcap.bounds); + struct v4l2_pix_format* pix_format = &(s->pix_format); + u8 scale; + const enum sn9c102_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; + + if (copy_from_user(&crop, arg, sizeof(crop))) + return -EFAULT; + + rect = &(crop.c); + + if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_CROP failed. " + "Unmap the buffers first."); + return -EINVAL; + } + + /* Preserve R,G or B origin */ + rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; + rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; + + if (rect->width < 16) + rect->width = 16; + if (rect->height < 16) + rect->height = 16; + if (rect->width > bounds->width) + rect->width = bounds->width; + if (rect->height > bounds->height) + rect->height = bounds->height; + if (rect->left < bounds->left) + rect->left = bounds->left; + if (rect->top < bounds->top) + rect->top = bounds->top; + if (rect->left + rect->width > bounds->left + bounds->width) + rect->left = bounds->left+bounds->width - rect->width; + if (rect->top + rect->height > bounds->top + bounds->height) + rect->top = bounds->top+bounds->height - rect->height; + + rect->width &= ~15L; + rect->height &= ~15L; + + if (SN9C102_PRESERVE_IMGSCALE) { + /* Calculate the actual scaling factor */ + u32 a, b; + a = rect->width * rect->height; + b = pix_format->width * pix_format->height; + scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; + } else + scale = 1; + + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) + return err; + + if (copy_to_user(arg, &crop, sizeof(crop))) { + cam->stream = stream; + return -EFAULT; + } + + if (cam->module_param.force_munmap || cam->io == IO_READ) + sn9c102_release_buffers(cam); + + err = sn9c102_set_crop(cam, rect); + if (s->set_crop) + err += s->set_crop(cam, rect); + err += sn9c102_set_scale(cam, scale); + + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + s->pix_format.width = rect->width/scale; + s->pix_format.height = rect->height/scale; + memcpy(&(s->_rect), rect, sizeof(*rect)); + + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } + + if (cam->io == IO_READ) + sn9c102_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + sn9c102_requeue_outqueue(cam); + + cam->stream = stream; + + return 0; +} + + +static int +sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_fmtdesc fmtd; + + if (copy_from_user(&fmtd, arg, sizeof(fmtd))) + return -EFAULT; + + if (fmtd.index == 0) { + strcpy(fmtd.description, "bayer rgb"); + fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; + } else if (fmtd.index == 1) { + strcpy(fmtd.description, "compressed"); + fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; + fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; + } else + return -EINVAL; + + fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); + + if (copy_to_user(arg, &fmtd, sizeof(fmtd))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_format format; + struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); + + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; + + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X) + ? 0 : (pfmt->width * pfmt->priv) / 8; + pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); + pfmt->field = V4L2_FIELD_NONE; + memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); + + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, + void __user * arg) +{ + struct sn9c102_sensor* s = &cam->sensor; + struct v4l2_format format; + struct v4l2_pix_format* pix; + struct v4l2_pix_format* pfmt = &(s->pix_format); + struct v4l2_rect* bounds = &(s->cropcap.bounds); + struct v4l2_rect rect; + u8 scale; + const enum sn9c102_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; + + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; + + pix = &(format.fmt.pix); + + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + memcpy(&rect, &(s->_rect), sizeof(rect)); + + { /* calculate the actual scaling factor */ + u32 a, b; + a = rect.width * rect.height; + b = pix->width * pix->height; + scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; + } + + rect.width = scale * pix->width; + rect.height = scale * pix->height; + + if (rect.width < 16) + rect.width = 16; + if (rect.height < 16) + rect.height = 16; + if (rect.width > bounds->left + bounds->width - rect.left) + rect.width = bounds->left + bounds->width - rect.left; + if (rect.height > bounds->top + bounds->height - rect.top) + rect.height = bounds->top + bounds->height - rect.top; + + rect.width &= ~15L; + rect.height &= ~15L; + + { /* adjust the scaling factor */ + u32 a, b; + a = rect.width * rect.height; + b = pix->width * pix->height; + scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; + } + + pix->width = rect.width / scale; + pix->height = rect.height / scale; + + if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && + pix->pixelformat != V4L2_PIX_FMT_SBGGR8) + pix->pixelformat = pfmt->pixelformat; + pix->priv = pfmt->priv; /* bpp */ + pix->colorspace = pfmt->colorspace; + pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + ? 0 : (pix->width * pix->priv) / 8; + pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); + pix->field = V4L2_FIELD_NONE; + + if (cmd == VIDIOC_TRY_FMT) { + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; + return 0; + } + + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_FMT failed. Unmap the " + "buffers first."); + return -EINVAL; + } + + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) + return err; + + if (copy_to_user(arg, &format, sizeof(format))) { + cam->stream = stream; + return -EFAULT; + } + + if (cam->module_param.force_munmap || cam->io == IO_READ) + sn9c102_release_buffers(cam); + + err += sn9c102_set_pix_format(cam, pix); + err += sn9c102_set_crop(cam, &rect); + if (s->set_pix_format) + err += s->set_pix_format(cam, pix); + if (s->set_crop) + err += s->set_crop(cam, &rect); + err += sn9c102_set_scale(cam, scale); + + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + memcpy(pfmt, pix, sizeof(*pix)); + memcpy(&(s->_rect), &rect, sizeof(rect)); + + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } + + if (cam->io == IO_READ) + sn9c102_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + sn9c102_requeue_outqueue(cam); + + cam->stream = stream; + + return 0; +} + + +static int +sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg) +{ + if (copy_to_user(arg, &cam->compression, + sizeof(cam->compression))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_jpegcompression jc; + const enum sn9c102_stream_state stream = cam->stream; + int err = 0; + + if (copy_from_user(&jc, arg, sizeof(jc))) + return -EFAULT; + + if (jc.quality != 0 && jc.quality != 1) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) + return err; + + err += sn9c102_set_compression(cam, &jc); + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " + "problems. To use the camera, close and open " + "/dev/video%d again.", cam->v4ldev->minor); + return -EIO; + } + + cam->compression.quality = jc.quality; + + cam->stream = stream; + + return 0; +} + + +static int +sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_requestbuffers rb; + u32 i; + int err; + + if (copy_from_user(&rb, arg, sizeof(rb))) + return -EFAULT; + + if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + rb.memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + if (cam->io == IO_READ) { + DBG(3, "Close and open the device again to choose the mmap " + "I/O method"); + return -EINVAL; + } + + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are " + "still mapped."); + return -EINVAL; + } + + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) + return err; + + sn9c102_empty_framequeues(cam); + + sn9c102_release_buffers(cam); + if (rb.count) + rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP); + + if (copy_to_user(arg, &rb, sizeof(rb))) { + sn9c102_release_buffers(cam); + cam->io = IO_NONE; + return -EFAULT; + } + + cam->io = rb.count ? IO_MMAP : IO_NONE; + + return 0; +} + + +static int +sn9c102_vidioc_querybuf(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_buffer b; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; + + memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); + + if (cam->frame[b.index].vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; + + if (cam->frame[b.index].state == F_DONE) + b.flags |= V4L2_BUF_FLAG_DONE; + else if (cam->frame[b.index].state != F_UNUSED) + b.flags |= V4L2_BUF_FLAG_QUEUED; + + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_buffer b; + unsigned long lock_flags; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; + + if (cam->frame[b.index].state != F_UNUSED) + return -EINVAL; + + cam->frame[b.index].state = F_QUEUED; + + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + PDBGG("Frame #%lu queued", (unsigned long)b.index); + + return 0; +} + + +static int +sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, + void __user * arg) +{ + struct v4l2_buffer b; + struct sn9c102_frame_t *f; + unsigned long lock_flags; + long timeout; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (list_empty(&cam->outqueue)) { + if (cam->stream == STREAM_OFF) + return -EINVAL; + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) + return timeout; + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + if (!timeout || (cam->state & DEV_MISCONFIGURED)) + return -EIO; + } + + spin_lock_irqsave(&cam->queue_lock, lock_flags); + f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame); + list_del(cam->outqueue.next); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + f->state = F_UNUSED; + + memcpy(&b, &f->buf, sizeof(b)); + if (f->vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; + + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + + PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); + + return 0; +} + + +static int +sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg) +{ + int type; + + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (list_empty(&cam->inqueue)) + return -EINVAL; + + cam->stream = STREAM_ON; + + DBG(3, "Stream on"); + + return 0; +} + + +static int +sn9c102_vidioc_streamoff(struct sn9c102_device* cam, void __user * arg) +{ + int type, err; + + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) + return err; + + sn9c102_empty_framequeues(cam); + + DBG(3, "Stream off"); + + return 0; +} + + +static int +sn9c102_vidioc_g_parm(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + return 0; +} + + +static int +sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + + if (sp.parm.capture.readbuffers == 0) + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES) + sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + cam->nreadbuffers = sp.parm.capture.readbuffers; + + return 0; +} + + +static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, + unsigned int cmd, void __user * arg) +{ + struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + + switch (cmd) { + + case VIDIOC_QUERYCAP: + return sn9c102_vidioc_querycap(cam, arg); + + case VIDIOC_ENUMINPUT: + return sn9c102_vidioc_enuminput(cam, arg); + + case VIDIOC_G_INPUT: + return sn9c102_vidioc_g_input(cam, arg); + + case VIDIOC_S_INPUT: + return sn9c102_vidioc_s_input(cam, arg); + + case VIDIOC_QUERYCTRL: + return sn9c102_vidioc_query_ctrl(cam, arg); + + case VIDIOC_G_CTRL: + return sn9c102_vidioc_g_ctrl(cam, arg); + + case VIDIOC_S_CTRL_OLD: + case VIDIOC_S_CTRL: + return sn9c102_vidioc_s_ctrl(cam, arg); + + case VIDIOC_CROPCAP_OLD: + case VIDIOC_CROPCAP: + return sn9c102_vidioc_cropcap(cam, arg); + + case VIDIOC_G_CROP: + return sn9c102_vidioc_g_crop(cam, arg); + + case VIDIOC_S_CROP: + return sn9c102_vidioc_s_crop(cam, arg); + + case VIDIOC_ENUM_FMT: + return sn9c102_vidioc_enum_fmt(cam, arg); + + case VIDIOC_G_FMT: + return sn9c102_vidioc_g_fmt(cam, arg); + + case VIDIOC_TRY_FMT: + case VIDIOC_S_FMT: + return sn9c102_vidioc_try_s_fmt(cam, cmd, arg); + + case VIDIOC_G_JPEGCOMP: + return sn9c102_vidioc_g_jpegcomp(cam, arg); + + case VIDIOC_S_JPEGCOMP: + return sn9c102_vidioc_s_jpegcomp(cam, arg); + + case VIDIOC_REQBUFS: + return sn9c102_vidioc_reqbufs(cam, arg); + + case VIDIOC_QUERYBUF: + return sn9c102_vidioc_querybuf(cam, arg); + + case VIDIOC_QBUF: + return sn9c102_vidioc_qbuf(cam, arg); + + case VIDIOC_DQBUF: + return sn9c102_vidioc_dqbuf(cam, filp, arg); + + case VIDIOC_STREAMON: + return sn9c102_vidioc_streamon(cam, arg); + + case VIDIOC_STREAMOFF: + return sn9c102_vidioc_streamoff(cam, arg); + + case VIDIOC_G_PARM: + return sn9c102_vidioc_g_parm(cam, arg); + + case VIDIOC_S_PARM_OLD: + case VIDIOC_S_PARM: + return sn9c102_vidioc_s_parm(cam, arg); + + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case VIDIOC_QUERYSTD: + case VIDIOC_ENUMSTD: + case VIDIOC_QUERYMENU: + return -EINVAL; + + default: + return -EINVAL; + + } +} + + +static int sn9c102_ioctl(struct inode* inode, struct file* filp, + unsigned int cmd, unsigned long arg) +{ + struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + int err = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + V4LDBG(3, "sn9c102", cmd); + + err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); + + mutex_unlock(&cam->fileop_mutex); + + return err; +} + +/*****************************************************************************/ + +static struct file_operations sn9c102_fops = { + .owner = THIS_MODULE, + .open = sn9c102_open, + .release = sn9c102_release, + .ioctl = sn9c102_ioctl, + .read = sn9c102_read, + .poll = sn9c102_poll, + .mmap = sn9c102_mmap, + .llseek = no_llseek, +}; + +/*****************************************************************************/ + +/* It exists a single interface only. We do not need to validate anything. */ +static int +sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct sn9c102_device* cam; + static unsigned int dev_nr = 0; + unsigned int i; + int err = 0, r; + + if (!(cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL))) + return -ENOMEM; + + cam->usbdev = udev; + + if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { + DBG(1, "kmalloc() failed"); + err = -ENOMEM; + goto fail; + } + + if (!(cam->v4ldev = video_device_alloc())) { + DBG(1, "video_device_alloc() failed"); + err = -ENOMEM; + goto fail; + } + + mutex_init(&cam->dev_mutex); + + r = sn9c102_read_reg(cam, 0x00); + if (r < 0 || r != 0x10) { + DBG(1, "Sorry, this is not a SN9C10x based camera " + "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); + err = -ENODEV; + goto fail; + } + + cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ? + BRIDGE_SN9C103 : BRIDGE_SN9C102; + switch (cam->bridge) { + case BRIDGE_SN9C101: + case BRIDGE_SN9C102: + DBG(2, "SN9C10[12] PC Camera Controller detected " + "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); + break; + case BRIDGE_SN9C103: + DBG(2, "SN9C103 PC Camera Controller detected " + "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); + break; + } + + for (i = 0; sn9c102_sensor_table[i]; i++) { + err = sn9c102_sensor_table[i](cam); + if (!err) + break; + } + + if (!err) { + DBG(2, "%s image sensor detected", cam->sensor.name); + DBG(3, "Support for %s maintained by %s", + cam->sensor.name, cam->sensor.maintainer); + } else { + DBG(1, "No supported image sensor detected"); + err = -ENODEV; + goto fail; + } + + if (sn9c102_init(cam)) { + DBG(1, "Initialization failed. I will retry on open()."); + cam->state |= DEV_MISCONFIGURED; + } + + strcpy(cam->v4ldev->name, "SN9C10x PC Camera"); + cam->v4ldev->owner = THIS_MODULE; + cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; + cam->v4ldev->hardware = 0; + cam->v4ldev->fops = &sn9c102_fops; + cam->v4ldev->minor = video_nr[dev_nr]; + cam->v4ldev->release = video_device_release; + video_set_drvdata(cam->v4ldev, cam); + + mutex_lock(&cam->dev_mutex); + + err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, + video_nr[dev_nr]); + if (err) { + DBG(1, "V4L2 device registration failed"); + if (err == -ENFILE && video_nr[dev_nr] == -1) + DBG(1, "Free /dev/videoX node not found"); + video_nr[dev_nr] = -1; + dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; + mutex_unlock(&cam->dev_mutex); + goto fail; + } + + DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); + + cam->module_param.force_munmap = force_munmap[dev_nr]; + cam->module_param.frame_timeout = frame_timeout[dev_nr]; + + dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; + +#ifdef CONFIG_VIDEO_ADV_DEBUG + sn9c102_create_sysfs(cam); + DBG(2, "Optional device control through 'sysfs' interface ready"); +#endif + + usb_set_intfdata(intf, cam); + + mutex_unlock(&cam->dev_mutex); + + return 0; + +fail: + if (cam) { + kfree(cam->control_buffer); + if (cam->v4ldev) + video_device_release(cam->v4ldev); + kfree(cam); + } + return err; +} + + +static void sn9c102_usb_disconnect(struct usb_interface* intf) +{ + struct sn9c102_device* cam = usb_get_intfdata(intf); + + if (!cam) + return; + + down_write(&sn9c102_disconnect); + + mutex_lock(&cam->dev_mutex); + + DBG(2, "Disconnecting %s...", cam->v4ldev->name); + + wake_up_interruptible_all(&cam->open); + + if (cam->users) { + DBG(2, "Device /dev/video%d is open! Deregistration and " + "memory deallocation are deferred on close.", + cam->v4ldev->minor); + cam->state |= DEV_MISCONFIGURED; + sn9c102_stop_transfer(cam); + cam->state |= DEV_DISCONNECTED; + wake_up_interruptible(&cam->wait_frame); + wake_up(&cam->wait_stream); + usb_get_dev(cam->usbdev); + } else { + cam->state |= DEV_DISCONNECTED; + sn9c102_release_resources(cam); + } + + mutex_unlock(&cam->dev_mutex); + + if (!cam->users) + kfree(cam); + + up_write(&sn9c102_disconnect); +} + + +static struct usb_driver sn9c102_usb_driver = { + .name = "sn9c102", + .id_table = sn9c102_id_table, + .probe = sn9c102_usb_probe, + .disconnect = sn9c102_usb_disconnect, +}; + +/*****************************************************************************/ + +static int __init sn9c102_module_init(void) +{ + int err = 0; + + KDBG(2, SN9C102_MODULE_NAME " v" SN9C102_MODULE_VERSION); + KDBG(3, SN9C102_MODULE_AUTHOR); + + if ((err = usb_register(&sn9c102_usb_driver))) + KDBG(1, "usb_register() failed"); + + return err; +} + + +static void __exit sn9c102_module_exit(void) +{ + usb_deregister(&sn9c102_usb_driver); +} + + +module_init(sn9c102_module_init); +module_exit(sn9c102_module_exit); diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c new file mode 100644 index 000000000000..46c12ec3ca62 --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c @@ -0,0 +1,271 @@ +/*************************************************************************** + * Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera * + * Controllers * + * * + * Copyright (C) 2004-2006 by Luca Risolia * + * * + * 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 "sn9c102_sensor.h" + + +static struct sn9c102_sensor hv7131d; + + +static int hv7131d_init(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x00, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x11); + err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x60, 0x17); + err += sn9c102_write_reg(cam, 0x0e, 0x18); + err += sn9c102_write_reg(cam, 0xf2, 0x19); + + err += sn9c102_i2c_write(cam, 0x01, 0x04); + err += sn9c102_i2c_write(cam, 0x02, 0x00); + err += sn9c102_i2c_write(cam, 0x28, 0x00); + + return err; +} + + +static int hv7131d_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + { + int r1 = sn9c102_i2c_read(cam, 0x26), + r2 = sn9c102_i2c_read(cam, 0x27); + if (r1 < 0 || r2 < 0) + return -EIO; + ctrl->value = (r1 << 8) | (r2 & 0xff); + } + return 0; + case V4L2_CID_RED_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0) + return -EIO; + ctrl->value = 0x3f - (ctrl->value & 0x3f); + return 0; + case V4L2_CID_BLUE_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0) + return -EIO; + ctrl->value = 0x3f - (ctrl->value & 0x3f); + return 0; + case SN9C102_V4L2_CID_GREEN_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0) + return -EIO; + ctrl->value = 0x3f - (ctrl->value & 0x3f); + return 0; + case SN9C102_V4L2_CID_RESET_LEVEL: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0) + return -EIO; + ctrl->value &= 0x3f; + return 0; + case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x34)) < 0) + return -EIO; + ctrl->value &= 0x07; + return 0; + default: + return -EINVAL; + } +} + + +static int hv7131d_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8); + err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff); + break; + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value); + break; + case SN9C102_V4L2_CID_RESET_LEVEL: + err += sn9c102_i2c_write(cam, 0x30, ctrl->value); + break; + case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE: + err += sn9c102_i2c_write(cam, 0x34, ctrl->value); + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + +static int hv7131d_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = &hv7131d; + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + + +static int hv7131d_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, 0x42, 0x19); + else + err += sn9c102_write_reg(cam, 0xf2, 0x19); + + return err; +} + + +static struct sn9c102_sensor hv7131d = { + .name = "HV7131D", + .maintainer = "Luca Risolia ", + .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x11, + .init = &hv7131d_init, + .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x0250, + .maximum = 0xffff, + .step = 0x0001, + .default_value = 0x0250, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x20, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x1e, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_RESET_LEVEL, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "reset level", + .minimum = 0x19, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x30, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "pixel bias voltage", + .minimum = 0x00, + .maximum = 0x07, + .step = 0x01, + .default_value = 0x02, + .flags = 0, + }, + }, + .get_ctrl = &hv7131d_get_ctrl, + .set_ctrl = &hv7131d_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .set_crop = &hv7131d_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &hv7131d_set_pix_format +}; + + +int sn9c102_probe_hv7131d(struct sn9c102_device* cam) +{ + int r0 = 0, r1 = 0, err = 0; + + err += sn9c102_write_reg(cam, 0x01, 0x01); + err += sn9c102_write_reg(cam, 0x00, 0x01); + err += sn9c102_write_reg(cam, 0x28, 0x17); + if (err) + return -EIO; + + r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00); + r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01); + if (r0 < 0 || r1 < 0) + return -EIO; + + if (r0 != 0x00 && r1 != 0x04) + return -ENODEV; + + sn9c102_attach_sensor(cam, &hv7131d); + + return 0; +} diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c new file mode 100644 index 000000000000..d9aa7a61095d --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c @@ -0,0 +1,363 @@ +/*************************************************************************** + * Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera * + * Controllers * + * * + * Copyright (C) 2004-2006 by Luca Risolia * + * * + * 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 "sn9c102_sensor.h" + + +static struct sn9c102_sensor mi0343; +static u8 mi0343_i2c_data[5+1]; + + +static int mi0343_init(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x00, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x11); + err += sn9c102_write_reg(cam, 0x0a, 0x14); + err += sn9c102_write_reg(cam, 0x40, 0x01); + err += sn9c102_write_reg(cam, 0x20, 0x17); + err += sn9c102_write_reg(cam, 0x07, 0x18); + err += sn9c102_write_reg(cam, 0xa0, 0x19); + + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, + 0x0d, 0x00, 0x01, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, + 0x0d, 0x00, 0x00, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, + 0x03, 0x01, 0xe1, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, + 0x04, 0x02, 0x81, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, + 0x05, 0x00, 0x17, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, + 0x06, 0x00, 0x11, 0, 0); + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, + 0x62, 0x04, 0x9a, 0, 0); + + return err; +} + + +static int mi0343_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, + 0x09, 2+1, mi0343_i2c_data) < 0) + return -EIO; + ctrl->value = mi0343_i2c_data[2]; + return 0; + case V4L2_CID_GAIN: + if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, + 0x35, 2+1, mi0343_i2c_data) < 0) + return -EIO; + break; + case V4L2_CID_HFLIP: + if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, + 0x20, 2+1, mi0343_i2c_data) < 0) + return -EIO; + ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0; + return 0; + case V4L2_CID_VFLIP: + if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, + 0x20, 2+1, mi0343_i2c_data) < 0) + return -EIO; + ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0; + return 0; + case V4L2_CID_RED_BALANCE: + if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, + 0x2d, 2+1, mi0343_i2c_data) < 0) + return -EIO; + break; + case V4L2_CID_BLUE_BALANCE: + if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, + 0x2c, 2+1, mi0343_i2c_data) < 0) + return -EIO; + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, + 0x2e, 2+1, mi0343_i2c_data) < 0) + return -EIO; + break; + default: + return -EINVAL; + } + + switch (ctrl->id) { + case V4L2_CID_GAIN: + case V4L2_CID_RED_BALANCE: + case V4L2_CID_BLUE_BALANCE: + case SN9C102_V4L2_CID_GREEN_BALANCE: + ctrl->value = mi0343_i2c_data[3] | (mi0343_i2c_data[2] << 8); + if (ctrl->value >= 0x10 && ctrl->value <= 0x3f) + ctrl->value -= 0x10; + else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f) + ctrl->value -= 0x60; + else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff) + ctrl->value -= 0xe0; + } + + return 0; +} + + +static int mi0343_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + u16 reg = 0; + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_GAIN: + case V4L2_CID_RED_BALANCE: + case V4L2_CID_BLUE_BALANCE: + case SN9C102_V4L2_CID_GREEN_BALANCE: + if (ctrl->value <= (0x3f-0x10)) + reg = 0x10 + ctrl->value; + else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60))) + reg = 0x60 + (ctrl->value - (0x3f-0x10)); + else + reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60)); + break; + } + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, + mi0343.i2c_slave_id, + 0x09, ctrl->value, 0x00, + 0, 0); + break; + case V4L2_CID_GAIN: + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, + mi0343.i2c_slave_id, + 0x35, reg >> 8, reg & 0xff, + 0, 0); + break; + case V4L2_CID_HFLIP: + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, + mi0343.i2c_slave_id, + 0x20, ctrl->value ? 0x40:0x00, + ctrl->value ? 0x20:0x00, + 0, 0); + break; + case V4L2_CID_VFLIP: + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, + mi0343.i2c_slave_id, + 0x20, ctrl->value ? 0x80:0x00, + ctrl->value ? 0x80:0x00, + 0, 0); + break; + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, + mi0343.i2c_slave_id, + 0x2d, reg >> 8, reg & 0xff, + 0, 0); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, + mi0343.i2c_slave_id, + 0x2c, reg >> 8, reg & 0xff, + 0, 0); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, + mi0343.i2c_slave_id, + 0x2b, reg >> 8, reg & 0xff, + 0, 0); + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, + mi0343.i2c_slave_id, + 0x2e, reg >> 8, reg & 0xff, + 0, 0); + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + +static int mi0343_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = &mi0343; + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + + +static int mi0343_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, + mi0343.i2c_slave_id, + 0x0a, 0x00, 0x03, 0, 0); + err += sn9c102_write_reg(cam, 0x20, 0x19); + } else { + err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, + mi0343.i2c_slave_id, + 0x0a, 0x00, 0x05, 0, 0); + err += sn9c102_write_reg(cam, 0xa0, 0x19); + } + + return err; +} + + +static struct sn9c102_sensor mi0343 = { + .name = "MI-0343", + .maintainer = "Luca Risolia ", + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x5d, + .init = &mi0343_init, + .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x06, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/ + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal mirror", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical mirror", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0), + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0), + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)), + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + }, + .get_ctrl = &mi0343_get_ctrl, + .set_ctrl = &mi0343_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .set_crop = &mi0343_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &mi0343_set_pix_format +}; + + +int sn9c102_probe_mi0343(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x01, 0x01); + err += sn9c102_write_reg(cam, 0x00, 0x01); + err += sn9c102_write_reg(cam, 0x28, 0x17); + if (err) + return -EIO; + + if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00, + 2, mi0343_i2c_data) < 0) + return -EIO; + + if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3) + return -ENODEV; + + sn9c102_attach_sensor(cam, &mi0343); + + return 0; +} diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c new file mode 100644 index 000000000000..42852b7cb042 --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c @@ -0,0 +1,401 @@ +/*************************************************************************** + * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera * + * Controllers * + * * + * Copyright (C) 2005-2006 by Luca Risolia * + * * + * 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 "sn9c102_sensor.h" + + +static struct sn9c102_sensor ov7630; + + +static int ov7630_init(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x60, 0x17); + err += sn9c102_write_reg(cam, 0x0f, 0x18); + err += sn9c102_write_reg(cam, 0x50, 0x19); + + err += sn9c102_i2c_write(cam, 0x12, 0x80); + err += sn9c102_i2c_write(cam, 0x11, 0x01); + err += sn9c102_i2c_write(cam, 0x15, 0x34); + err += sn9c102_i2c_write(cam, 0x16, 0x03); + err += sn9c102_i2c_write(cam, 0x17, 0x1c); + err += sn9c102_i2c_write(cam, 0x18, 0xbd); + err += sn9c102_i2c_write(cam, 0x19, 0x06); + err += sn9c102_i2c_write(cam, 0x1a, 0xf6); + err += sn9c102_i2c_write(cam, 0x1b, 0x04); + err += sn9c102_i2c_write(cam, 0x20, 0xf6); + err += sn9c102_i2c_write(cam, 0x23, 0xee); + err += sn9c102_i2c_write(cam, 0x26, 0xa0); + err += sn9c102_i2c_write(cam, 0x27, 0x9a); + err += sn9c102_i2c_write(cam, 0x28, 0xa0); + err += sn9c102_i2c_write(cam, 0x29, 0x30); + err += sn9c102_i2c_write(cam, 0x2a, 0xa0); + err += sn9c102_i2c_write(cam, 0x2b, 0x1f); + err += sn9c102_i2c_write(cam, 0x2f, 0x3d); + err += sn9c102_i2c_write(cam, 0x30, 0x24); + err += sn9c102_i2c_write(cam, 0x32, 0x86); + err += sn9c102_i2c_write(cam, 0x60, 0xa9); + err += sn9c102_i2c_write(cam, 0x61, 0x42); + err += sn9c102_i2c_write(cam, 0x65, 0x00); + err += sn9c102_i2c_write(cam, 0x69, 0x38); + err += sn9c102_i2c_write(cam, 0x6f, 0x88); + err += sn9c102_i2c_write(cam, 0x70, 0x0b); + err += sn9c102_i2c_write(cam, 0x71, 0x00); + err += sn9c102_i2c_write(cam, 0x74, 0x21); + err += sn9c102_i2c_write(cam, 0x7d, 0xf7); + + return err; +} + + +static int ov7630_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_write(cam, 0x10, ctrl->value >> 2); + err += sn9c102_i2c_write(cam, 0x76, ctrl->value & 0x03); + break; + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_write(cam, 0x02, ctrl->value); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_write(cam, 0x01, ctrl->value); + break; + case V4L2_CID_GAIN: + err += sn9c102_i2c_write(cam, 0x00, ctrl->value); + break; + case V4L2_CID_CONTRAST: + err += ctrl->value ? sn9c102_i2c_write(cam, 0x05, + (ctrl->value-1) | 0x20) + : sn9c102_i2c_write(cam, 0x05, 0x00); + break; + case V4L2_CID_BRIGHTNESS: + err += sn9c102_i2c_write(cam, 0x06, ctrl->value); + break; + case V4L2_CID_SATURATION: + err += sn9c102_i2c_write(cam, 0x03, ctrl->value << 4); + break; + case V4L2_CID_HUE: + err += ctrl->value ? sn9c102_i2c_write(cam, 0x04, + (ctrl->value-1) | 0x20) + : sn9c102_i2c_write(cam, 0x04, 0x00); + break; + case V4L2_CID_DO_WHITE_BALANCE: + err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); + break; + case V4L2_CID_WHITENESS: + err += sn9c102_i2c_write(cam, 0x0d, ctrl->value); + break; + case V4L2_CID_AUTO_WHITE_BALANCE: + err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78); + break; + case V4L2_CID_AUTOGAIN: + err += sn9c102_i2c_write(cam, 0x13, ctrl->value); + break; + case V4L2_CID_VFLIP: + err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7)); + break; + case V4L2_CID_BLACK_LEVEL: + err += sn9c102_i2c_write(cam, 0x25, ctrl->value); + break; + case SN9C102_V4L2_CID_BRIGHT_LEVEL: + err += sn9c102_i2c_write(cam, 0x24, ctrl->value); + break; + case SN9C102_V4L2_CID_GAMMA: + err += sn9c102_i2c_write(cam, 0x14, (ctrl->value << 2) | 0x80); + break; + case SN9C102_V4L2_CID_BAND_FILTER: + err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2); + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + +static int ov7630_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = &ov7630; + int err = 0; + u8 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; + + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + + +static int ov7630_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, 0x20, 0x19); + else + err += sn9c102_write_reg(cam, 0x50, 0x19); + + return err; +} + + +static struct sn9c102_sensor ov7630 = { + .name = "OV7630", + .maintainer = "Luca Risolia ", + .sysfs_ops = SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x21, + .init = &ov7630_init, + .qctrl = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x14, + .flags = 0, + }, + { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "hue", + .minimum = 0x00, + .maximum = 0x1f+1, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "saturation", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x08, + .flags = 0, + }, + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "contrast", + .minimum = 0x00, + .maximum = 0x1f+1, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x000, + .maximum = 0x3ff, + .step = 0x001, + .default_value = 0x83<<2, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = 0x3a, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = 0x77, + .flags = 0, + }, + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "brightness", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = 0xa0, + .flags = 0, + }, + { + .id = V4L2_CID_DO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "white balance background: blue", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x20, + .flags = 0, + }, + { + .id = V4L2_CID_WHITENESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "white balance background: red", + .minimum = 0x00, + .maximum = 0x3f, + .step = 0x01, + .default_value = 0x20, + .flags = 0, + }, + { + .id = V4L2_CID_AUTO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "auto white balance", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x01, + .flags = 0, + }, + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain & exposure mode", + .minimum = 0x00, + .maximum = 0x03, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x01, + .flags = 0, + }, + { + .id = V4L2_CID_BLACK_LEVEL, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "black pixel ratio", + .minimum = 0x01, + .maximum = 0x9a, + .step = 0x01, + .default_value = 0x8a, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_BRIGHT_LEVEL, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "bright pixel ratio", + .minimum = 0x01, + .maximum = 0x9a, + .step = 0x01, + .default_value = 0x10, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_BAND_FILTER, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "band filter", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GAMMA, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "rgb gamma", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + }, + .set_ctrl = &ov7630_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .set_crop = &ov7630_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &ov7630_set_pix_format +}; + + +int sn9c102_probe_ov7630(struct sn9c102_device* cam) +{ + const struct usb_device_id ov7630_id_table[] = { + { USB_DEVICE(0x0c45, 0x602c), }, + { USB_DEVICE(0x0c45, 0x602d), }, + { USB_DEVICE(0x0c45, 0x608f), }, + { USB_DEVICE(0x0c45, 0x60b0), }, + { } + }; + int err = 0; + + if (!sn9c102_match_id(cam, ov7630_id_table)) + return -ENODEV; + + err += sn9c102_write_reg(cam, 0x01, 0x01); + err += sn9c102_write_reg(cam, 0x00, 0x01); + err += sn9c102_write_reg(cam, 0x28, 0x17); + if (err) + return -EIO; + + err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0); + if (err) + return -ENODEV; + + sn9c102_attach_sensor(cam, &ov7630); + + return 0; +} diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c new file mode 100644 index 000000000000..b1dee78abe04 --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c @@ -0,0 +1,307 @@ +/*************************************************************************** + * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera * + * Controllers * + * * + * Copyright (C) 2004-2006 by Luca Risolia * + * * + * 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 "sn9c102_sensor.h" + + +static struct sn9c102_sensor pas106b; + + +static int pas106b_init(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x00, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x11); + err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x20, 0x17); + err += sn9c102_write_reg(cam, 0x20, 0x19); + err += sn9c102_write_reg(cam, 0x09, 0x18); + + err += sn9c102_i2c_write(cam, 0x02, 0x0c); + err += sn9c102_i2c_write(cam, 0x05, 0x5a); + err += sn9c102_i2c_write(cam, 0x06, 0x88); + err += sn9c102_i2c_write(cam, 0x07, 0x80); + err += sn9c102_i2c_write(cam, 0x10, 0x06); + err += sn9c102_i2c_write(cam, 0x11, 0x06); + err += sn9c102_i2c_write(cam, 0x12, 0x00); + err += sn9c102_i2c_write(cam, 0x14, 0x02); + err += sn9c102_i2c_write(cam, 0x13, 0x01); + + msleep(400); + + return err; +} + + +static int pas106b_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + { + int r1 = sn9c102_i2c_read(cam, 0x03), + r2 = sn9c102_i2c_read(cam, 0x04); + if (r1 < 0 || r2 < 0) + return -EIO; + ctrl->value = (r1 << 4) | (r2 & 0x0f); + } + return 0; + case V4L2_CID_RED_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) + return -EIO; + ctrl->value &= 0x1f; + return 0; + case V4L2_CID_BLUE_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0) + return -EIO; + ctrl->value &= 0x1f; + return 0; + case V4L2_CID_GAIN: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0e)) < 0) + return -EIO; + ctrl->value &= 0x1f; + return 0; + case V4L2_CID_CONTRAST: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0) + return -EIO; + ctrl->value &= 0x07; + return 0; + case SN9C102_V4L2_CID_GREEN_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0a)) < 0) + return -EIO; + ctrl->value = (ctrl->value & 0x1f) << 1; + return 0; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0) + return -EIO; + ctrl->value &= 0xf8; + return 0; + default: + return -EINVAL; + } +} + + +static int pas106b_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4); + err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f); + break; + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_write(cam, 0x09, ctrl->value); + break; + case V4L2_CID_GAIN: + err += sn9c102_i2c_write(cam, 0x0e, ctrl->value); + break; + case V4L2_CID_CONTRAST: + err += sn9c102_i2c_write(cam, 0x0f, ctrl->value); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1); + err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1); + break; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3); + break; + default: + return -EINVAL; + } + err += sn9c102_i2c_write(cam, 0x13, 0x01); + + return err ? -EIO : 0; +} + + +static int pas106b_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = &pas106b; + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + + +static int pas106b_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, 0x2c, 0x17); + else + err += sn9c102_write_reg(cam, 0x20, 0x17); + + return err; +} + + +static struct sn9c102_sensor pas106b = { + .name = "PAS106B", + .maintainer = "Luca Risolia ", + .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x40, + .init = &pas106b_init, + .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x125, + .maximum = 0xfff, + .step = 0x001, + .default_value = 0x140, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x0d, + .flags = 0, + }, + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "contrast", + .minimum = 0x00, + .maximum = 0x07, + .step = 0x01, + .default_value = 0x00, /* 0x00~0x03 have same effect */ + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x04, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x06, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x3e, + .step = 0x02, + .default_value = 0x02, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "DAC magnitude", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x01, + .flags = 0, + }, + }, + .get_ctrl = &pas106b_get_ctrl, + .set_ctrl = &pas106b_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 352, + .height = 288, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 352, + .height = 288, + }, + }, + .set_crop = &pas106b_set_crop, + .pix_format = { + .width = 352, + .height = 288, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, /* we use this field as 'bits per pixel' */ + }, + .set_pix_format = &pas106b_set_pix_format +}; + + +int sn9c102_probe_pas106b(struct sn9c102_device* cam) +{ + int r0 = 0, r1 = 0, err = 0; + unsigned int pid = 0; + + /* + Minimal initialization to enable the I2C communication + NOTE: do NOT change the values! + */ + err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ + err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */ + err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */ + if (err) + return -EIO; + + r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00); + r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01); + + if (r0 < 0 || r1 < 0) + return -EIO; + + pid = (r0 << 11) | ((r1 & 0xf0) >> 4); + if (pid != 0x007) + return -ENODEV; + + sn9c102_attach_sensor(cam, &pas106b); + + return 0; +} diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bca.c b/drivers/media/video/sn9c102/sn9c102_pas202bca.c new file mode 100644 index 000000000000..3453237055bb --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_pas202bca.c @@ -0,0 +1,238 @@ +/*************************************************************************** + * Plug-in for PAS202BCA image sensor connected to the SN9C10x PC Camera * + * Controllers * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * 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 "sn9c102_sensor.h" + + +static struct sn9c102_sensor pas202bca; + + +static int pas202bca_init(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x00, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x11); + err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x20, 0x17); + err += sn9c102_write_reg(cam, 0x30, 0x19); + err += sn9c102_write_reg(cam, 0x09, 0x18); + + err += sn9c102_i2c_write(cam, 0x02, 0x14); + err += sn9c102_i2c_write(cam, 0x03, 0x40); + err += sn9c102_i2c_write(cam, 0x0d, 0x2c); + err += sn9c102_i2c_write(cam, 0x0e, 0x01); + err += sn9c102_i2c_write(cam, 0x0f, 0xa9); + err += sn9c102_i2c_write(cam, 0x10, 0x08); + err += sn9c102_i2c_write(cam, 0x13, 0x63); + err += sn9c102_i2c_write(cam, 0x15, 0x70); + err += sn9c102_i2c_write(cam, 0x11, 0x01); + + msleep(400); + + return err; +} + + +static int pas202bca_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, 0x24, 0x17); + else + err += sn9c102_write_reg(cam, 0x20, 0x17); + + return err; +} + + +static int pas202bca_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); + err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); + break; + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_write(cam, 0x09, ctrl->value); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_write(cam, 0x07, ctrl->value); + break; + case V4L2_CID_GAIN: + err += sn9c102_i2c_write(cam, 0x10, ctrl->value); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_write(cam, 0x08, ctrl->value); + break; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); + break; + default: + return -EINVAL; + } + err += sn9c102_i2c_write(cam, 0x11, 0x01); + + return err ? -EIO : 0; +} + + +static int pas202bca_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = &pas202bca; + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + + +static struct sn9c102_sensor pas202bca = { + .name = "PAS202BCA", + .maintainer = "Luca Risolia ", + .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x40, + .init = &pas202bca_init, + .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x01e5, + .maximum = 0x3fff, + .step = 0x0001, + .default_value = 0x01e5, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x0c, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x01, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x05, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "DAC magnitude", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = 0x04, + .flags = 0, + }, + }, + .set_ctrl = &pas202bca_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .set_crop = &pas202bca_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &pas202bca_set_pix_format +}; + + +int sn9c102_probe_pas202bca(struct sn9c102_device* cam) +{ + const struct usb_device_id pas202bca_id_table[] = { + { USB_DEVICE(0x0c45, 0x60af), }, + { } + }; + int err = 0; + + if (!sn9c102_match_id(cam,pas202bca_id_table)) + return -ENODEV; + + err += sn9c102_write_reg(cam, 0x01, 0x01); + err += sn9c102_write_reg(cam, 0x40, 0x01); + err += sn9c102_write_reg(cam, 0x28, 0x17); + if (err) + return -EIO; + + if (sn9c102_i2c_try_write(cam, &pas202bca, 0x10, 0)) /* try to write */ + return -ENODEV; + + sn9c102_attach_sensor(cam, &pas202bca); + + return 0; +} diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c new file mode 100644 index 000000000000..d068616ab337 --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c @@ -0,0 +1,293 @@ +/*************************************************************************** + * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera * + * Controllers * + * * + * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio * + * * + * http://cadu.homelinux.com:8080/ * + * * + * DAC Magnitude, exposure and green gain controls added by * + * Luca Risolia * + * * + * 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 "sn9c102_sensor.h" + + +static struct sn9c102_sensor pas202bcb; + + +static int pas202bcb_init(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x00, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x11); + err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x20, 0x17); + err += sn9c102_write_reg(cam, 0x30, 0x19); + err += sn9c102_write_reg(cam, 0x09, 0x18); + + err += sn9c102_i2c_write(cam, 0x02, 0x14); + err += sn9c102_i2c_write(cam, 0x03, 0x40); + err += sn9c102_i2c_write(cam, 0x0d, 0x2c); + err += sn9c102_i2c_write(cam, 0x0e, 0x01); + err += sn9c102_i2c_write(cam, 0x0f, 0xa9); + err += sn9c102_i2c_write(cam, 0x10, 0x08); + err += sn9c102_i2c_write(cam, 0x13, 0x63); + err += sn9c102_i2c_write(cam, 0x15, 0x70); + err += sn9c102_i2c_write(cam, 0x11, 0x01); + + msleep(400); + + return err; +} + + +static int pas202bcb_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + { + int r1 = sn9c102_i2c_read(cam, 0x04), + r2 = sn9c102_i2c_read(cam, 0x05); + if (r1 < 0 || r2 < 0) + return -EIO; + ctrl->value = (r1 << 6) | (r2 & 0x3f); + } + return 0; + case V4L2_CID_RED_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case V4L2_CID_BLUE_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case V4L2_CID_GAIN: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0) + return -EIO; + ctrl->value &= 0x1f; + return 0; + case SN9C102_V4L2_CID_GREEN_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) + return -EIO; + return 0; + default: + return -EINVAL; + } +} + + +static int pas202bcb_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, 0x24, 0x17); + else + err += sn9c102_write_reg(cam, 0x20, 0x17); + + return err; +} + + +static int pas202bcb_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); + err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); + break; + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_write(cam, 0x09, ctrl->value); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_write(cam, 0x07, ctrl->value); + break; + case V4L2_CID_GAIN: + err += sn9c102_i2c_write(cam, 0x10, ctrl->value); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_write(cam, 0x08, ctrl->value); + break; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); + break; + default: + return -EINVAL; + } + err += sn9c102_i2c_write(cam, 0x11, 0x01); + + return err ? -EIO : 0; +} + + +static int pas202bcb_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = &pas202bcb; + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + + +static struct sn9c102_sensor pas202bcb = { + .name = "PAS202BCB", + .maintainer = "Carlos Eduardo Medaglia Dyonisio " + "", + .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .i2c_slave_id = 0x40, + .init = &pas202bcb_init, + .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x01e5, + .maximum = 0x3fff, + .step = 0x0001, + .default_value = 0x01e5, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x0c, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x01, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x05, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "DAC magnitude", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = 0x04, + .flags = 0, + }, + }, + .get_ctrl = &pas202bcb_get_ctrl, + .set_ctrl = &pas202bcb_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .set_crop = &pas202bcb_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &pas202bcb_set_pix_format +}; + + +int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) +{ + int r0 = 0, r1 = 0, err = 0; + unsigned int pid = 0; + + /* + * Minimal initialization to enable the I2C communication + * NOTE: do NOT change the values! + */ + err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ + err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */ + err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */ + if (err) + return -EIO; + + r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00); + r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01); + + if (r0 < 0 || r1 < 0) + return -EIO; + + pid = (r0 << 4) | ((r1 & 0xf0) >> 4); + if (pid != 0x017) + return -ENODEV; + + sn9c102_attach_sensor(cam, &pas202bcb); + + return 0; +} diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h new file mode 100644 index 000000000000..2afd9e9d09bb --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_sensor.h @@ -0,0 +1,389 @@ +/*************************************************************************** + * API for image sensors connected to the SN9C10x PC Camera Controllers * + * * + * Copyright (C) 2004-2006 by Luca Risolia * + * * + * 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. * + ***************************************************************************/ + +#ifndef _SN9C102_SENSOR_H_ +#define _SN9C102_SENSOR_H_ + +#include +#include +#include +#include +#include +#include + +struct sn9c102_device; +struct sn9c102_sensor; + +/*****************************************************************************/ + +/* + OVERVIEW. + This is a small interface that allows you to add support for any CCD/CMOS + image sensors connected to the SN9C10X bridges. The entire API is documented + below. In the most general case, to support a sensor there are three steps + you have to follow: + 1) define the main "sn9c102_sensor" structure by setting the basic fields; + 2) write a probing function to be called by the core module when the USB + camera is recognized, then add both the USB ids and the name of that + function to the two corresponding tables SENSOR_TABLE and ID_TABLE (see + below); + 3) implement the methods that you want/need (and fill the rest of the main + structure accordingly). + "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do + NOT need to touch the source code of the core module for the things to work + properly, unless you find bugs or flaws in it. Finally, do not forget to + read the V4L2 API for completeness. +*/ + +/*****************************************************************************/ + +/* + Probing functions: on success, you must attach the sensor to the camera + by calling sn9c102_attach_sensor() provided below. + To enable the I2C communication, you might need to perform a really basic + initialization of the SN9C10X chip by using the write function declared + ahead. + Functions must return 0 on success, the appropriate error otherwise. +*/ +extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); +extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); +extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); +extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); +extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam); +extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); +extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); +extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); + +/* + Add the above entries to this table. Be sure to add the entry in the right + place, since, on failure, the next probing routine is called according to + the order of the list below, from top to bottom. +*/ +#define SN9C102_SENSOR_TABLE \ +static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { \ + &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ \ + &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \ + &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \ + &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \ + &sn9c102_probe_pas202bca, /* detection mostly based on USB pid/vid */ \ + &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \ + &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \ + &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \ + NULL, \ +}; + +/* Device identification */ +extern struct sn9c102_device* +sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); + +/* Attach a probed sensor to the camera. */ +extern void +sn9c102_attach_sensor(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor); + +/* + Each SN9C10x camera has proper PID/VID identifiers. + SN9C103 supports multiple interfaces, but we only handle the video class + interface. +*/ +#define SN9C102_USB_DEVICE(vend, prod, intclass) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ + USB_DEVICE_ID_MATCH_INT_CLASS, \ + .idVendor = (vend), \ + .idProduct = (prod), \ + .bInterfaceClass = (intclass) + +#define SN9C102_ID_TABLE \ +static const struct usb_device_id sn9c102_id_table[] = { \ + { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \ + { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \ + { USB_DEVICE(0x0c45, 0x6007), }, \ + { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \ + { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \ + { USB_DEVICE(0x0c45, 0x6024), }, \ + { USB_DEVICE(0x0c45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */ \ + { USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */ \ + { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \ + { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */ \ + { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \ + { USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */ \ + { USB_DEVICE(0x0c45, 0x602d), }, \ + { USB_DEVICE(0x0c45, 0x602e), }, /* OV7630 */ \ + { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x6080, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x6082, 0xff), }, /* MI0343 & MI0360 */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x6083, 0xff), }, /* HV7131[D|E1] */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60a2, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60a3, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60a8, 0xff), }, /* PAS106B */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60aa, 0xff), }, /* TAS5130D1B */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60ab, 0xff), }, /* TAS5110C1B */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60ac, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60ae, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60af, 0xff), }, /* PAS202BCB */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60b0, 0xff), }, /* OV7630 (?) */ \ + { SN9C102_USB_DEVICE(0x0c45, 0x60b2, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60b3, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60b8, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60ba, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60bb, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60bc, 0xff), }, \ + { SN9C102_USB_DEVICE(0x0c45, 0x60be, 0xff), }, \ + { } \ +}; + +/*****************************************************************************/ + +/* + Read/write routines: they always return -1 on error, 0 or the read value + otherwise. NOTE that a real read operation is not supported by the SN9C10X + chip for some of its registers. To work around this problem, a pseudo-read + call is provided instead: it returns the last successfully written value + on the register (0 if it has never been written), the usual -1 on error. +*/ + +/* The "try" I2C I/O versions are used when probing the sensor */ +extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*, + u8 address, u8 value); +extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, + u8 address); + +/* + These must be used if and only if the sensor doesn't implement the standard + I2C protocol. There are a number of good reasons why you must use the + single-byte versions of these functions: do not abuse. The first function + writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C10X + chip. The second one programs the registers 0x09 and 0x10 with data0 and + data1, and places the n bytes read from the sensor register table in the + buffer pointed by 'buffer'. Both the functions return -1 on error; the write + version returns 0 on success, while the read version returns the first read + byte. +*/ +extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor, u8 n, + u8 data0, u8 data1, u8 data2, u8 data3, + u8 data4, u8 data5); +extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor, u8 data0, + u8 data1, u8 n, u8 buffer[]); + +/* To be used after the sensor struct has been attached to the camera struct */ +extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value); +extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address); + +/* I/O on registers in the bridge. Could be used by the sensor methods too */ +extern int sn9c102_write_regs(struct sn9c102_device*, u8* buff, u16 index); +extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); +extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); + +/* + NOTE: there are no exported debugging functions. To uniform the output you + must use the dev_info()/dev_warn()/dev_err() macros defined in device.h, + already included here, the argument being the struct device '&usbdev->dev' + of the sensor structure. Do NOT use these macros before the sensor is + attached or the kernel will crash! However, you should not need to notify + the user about common errors or other messages, since this is done by the + master module. +*/ + +/*****************************************************************************/ + +enum sn9c102_i2c_sysfs_ops { + SN9C102_I2C_READ = 0x01, + SN9C102_I2C_WRITE = 0x02, +}; + +enum sn9c102_i2c_frequency { /* sensors may support both the frequencies */ + SN9C102_I2C_100KHZ = 0x01, + SN9C102_I2C_400KHZ = 0x02, +}; + +enum sn9c102_i2c_interface { + SN9C102_I2C_2WIRES, + SN9C102_I2C_3WIRES, +}; + +#define SN9C102_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 + +struct sn9c102_sensor { + char name[32], /* sensor name */ + maintainer[64]; /* name of the mantainer */ + + /* Supported operations through the 'sysfs' interface */ + enum sn9c102_i2c_sysfs_ops sysfs_ops; + + /* + These sensor capabilities must be provided if the SN9C10X controller + needs to communicate through the sensor serial interface by using + at least one of the i2c functions available. + */ + enum sn9c102_i2c_frequency frequency; + enum sn9c102_i2c_interface interface; + + /* + This identifier must be provided if the image sensor implements + the standard I2C protocol. + */ + u8 i2c_slave_id; /* reg. 0x09 */ + + /* + NOTE: Where not noted,most of the functions below are not mandatory. + Set to null if you do not implement them. If implemented, + they must return 0 on success, the proper error otherwise. + */ + + int (*init)(struct sn9c102_device* cam); + /* + This function will be called after the sensor has been attached. + It should be used to initialize the sensor only, but may also + configure part of the SN9C10X chip if necessary. You don't need to + setup picture settings like brightness, contrast, etc.. here, if + the corrisponding controls are implemented (see below), since + they are adjusted in the core driver by calling the set_ctrl() + method after init(), where the arguments are the default values + specified in the v4l2_queryctrl list of supported controls; + Same suggestions apply for other settings, _if_ the corresponding + methods are present; if not, the initialization must configure the + sensor according to the default configuration structures below. + */ + + struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS]; + /* + Optional list of default controls, defined as indicated in the + V4L2 API. Menu type controls are not handled by this interface. + */ + + int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl); + int (*set_ctrl)(struct sn9c102_device* cam, + const struct v4l2_control* ctrl); + /* + You must implement at least the set_ctrl method if you have defined + the list above. The returned value must follow the V4L2 + specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER + are not supported by this driver, so do not implement them. Also, + you don't have to check whether the passed values are out of bounds, + given that this is done by the core module. + */ + + struct v4l2_cropcap cropcap; + /* + Think the image sensor as a grid of R,G,B monochromatic pixels + disposed according to a particular Bayer pattern, which describes + the complete array of pixels, from (0,0) to (xmax, ymax). We will + use this coordinate system from now on. It is assumed the sensor + chip can be programmed to capture/transmit a subsection of that + array of pixels: we will call this subsection "active window". + It is not always true that the largest achievable active window can + cover the whole array of pixels. The V4L2 API defines another + area called "source rectangle", which, in turn, is a subrectangle of + the active window. The SN9C10X chip is always programmed to read the + source rectangle. + The bounds of both the active window and the source rectangle are + specified in the cropcap substructures 'bounds' and 'defrect'. + By default, the source rectangle should cover the largest possible + area. Again, it is not always true that the largest source rectangle + can cover the entire active window, although it is a rare case for + the hardware we have. The bounds of the source rectangle _must_ be + multiple of 16 and must use the same coordinate system as indicated + before; their centers shall align initially. + If necessary, the sensor chip must be initialized during init() to + set the bounds of the active sensor window; however, by default, it + usually covers the largest achievable area (maxwidth x maxheight) + of pixels, so no particular initialization is needed, if you have + defined the correct default bounds in the structures. + See the V4L2 API for further details. + NOTE: once you have defined the bounds of the active window + (struct cropcap.bounds) you must not change them.anymore. + Only 'bounds' and 'defrect' fields are mandatory, other fields + will be ignored. + */ + + int (*set_crop)(struct sn9c102_device* cam, + const struct v4l2_rect* rect); + /* + To be called on VIDIOC_C_SETCROP. The core module always calls a + default routine which configures the appropriate SN9C10X regs (also + scaling), but you may need to override/adjust specific stuff. + 'rect' contains width and height values that are multiple of 16: in + case you override the default function, you always have to program + the chip to match those values; on error return the corresponding + error code without rolling back. + NOTE: in case, you must program the SN9C10X chip to get rid of + blank pixels or blank lines at the _start_ of each line or + frame after each HSYNC or VSYNC, so that the image starts with + real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, + V_SIZE you don't have to care about blank pixels or blank + lines at the end of each line or frame). + */ + + struct v4l2_pix_format pix_format; + /* + What you have to define here are: 1) initial 'width' and 'height' of + the target rectangle 2) the initial 'pixelformat', which can be + either V4L2_PIX_FMT_SN9C10X (for compressed video) or + V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate the + number of bits per pixel for uncompressed video, 8 or 9 (despite the + current value of 'pixelformat'). + NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4 + of cropcap.defrect.width and cropcap.defrect.height. I + suggest 1/1. + NOTE 2: The initial compression quality is defined by the first bit + of reg 0x17 during the initialization of the image sensor. + NOTE 3: as said above, you have to program the SN9C10X chip to get + rid of any blank pixels, so that the output of the sensor + matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). + */ + + int (*set_pix_format)(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix); + /* + To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to + SN9C10X pixel format or viceversa. On error return the corresponding + error code without rolling back. + */ + + /* + Do NOT write to the data below, it's READ ONLY. It is used by the + core module to store successfully updated values of the above + settings, for rollbacks..etc..in case of errors during atomic I/O + */ + struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS]; + struct v4l2_rect _rect; +}; + +/*****************************************************************************/ + +/* Private ioctl's for control settings supported by some image sensors */ +#define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE +#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1 +#define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2 +#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3 +#define SN9C102_V4L2_CID_GAMMA V4L2_CID_PRIVATE_BASE + 4 +#define SN9C102_V4L2_CID_BAND_FILTER V4L2_CID_PRIVATE_BASE + 5 +#define SN9C102_V4L2_CID_BRIGHT_LEVEL V4L2_CID_PRIVATE_BASE + 6 + +#endif /* _SN9C102_SENSOR_H_ */ diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c new file mode 100644 index 000000000000..2e08c552f40a --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c @@ -0,0 +1,159 @@ +/*************************************************************************** + * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera * + * Controllers * + * * + * Copyright (C) 2004-2006 by Luca Risolia * + * * + * 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 "sn9c102_sensor.h" + + +static struct sn9c102_sensor tas5110c1b; + + +static int tas5110c1b_init(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x01, 0x01); + err += sn9c102_write_reg(cam, 0x44, 0x01); + err += sn9c102_write_reg(cam, 0x00, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x11); + err += sn9c102_write_reg(cam, 0x0a, 0x14); + err += sn9c102_write_reg(cam, 0x60, 0x17); + err += sn9c102_write_reg(cam, 0x06, 0x18); + err += sn9c102_write_reg(cam, 0xfb, 0x19); + + err += sn9c102_i2c_write(cam, 0xc0, 0x80); + + return err; +} + + +static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_GAIN: + err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value); + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + +static int tas5110c1b_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = &tas5110c1b; + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + /* Don't change ! */ + err += sn9c102_write_reg(cam, 0x14, 0x1a); + err += sn9c102_write_reg(cam, 0x0a, 0x1b); + err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19); + + return err; +} + + +static int tas5110c1b_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, 0x2b, 0x19); + else + err += sn9c102_write_reg(cam, 0xfb, 0x19); + + return err; +} + + +static struct sn9c102_sensor tas5110c1b = { + .name = "TAS5110C1B", + .maintainer = "Luca Risolia ", + .sysfs_ops = SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_3WIRES, + .init = &tas5110c1b_init, + .qctrl = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0xf6, + .step = 0x01, + .default_value = 0x40, + .flags = 0, + }, + }, + .set_ctrl = &tas5110c1b_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 352, + .height = 288, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 352, + .height = 288, + }, + }, + .set_crop = &tas5110c1b_set_crop, + .pix_format = { + .width = 352, + .height = 288, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &tas5110c1b_set_pix_format +}; + + +int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) +{ + const struct usb_device_id tas5110c1b_id_table[] = { + { USB_DEVICE(0x0c45, 0x6001), }, + { USB_DEVICE(0x0c45, 0x6005), }, + { USB_DEVICE(0x0c45, 0x60ab), }, + { } + }; + + /* Sensor detection is based on USB pid/vid */ + if (!sn9c102_match_id(cam, tas5110c1b_id_table)) + return -ENODEV; + + sn9c102_attach_sensor(cam, &tas5110c1b); + + return 0; +} diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c new file mode 100644 index 000000000000..c7b339740bbf --- /dev/null +++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c @@ -0,0 +1,169 @@ +/*************************************************************************** + * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera * + * Controllers * + * * + * Copyright (C) 2004-2006 by Luca Risolia * + * * + * 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 "sn9c102_sensor.h" + + +static struct sn9c102_sensor tas5130d1b; + + +static int tas5130d1b_init(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x01, 0x01); + err += sn9c102_write_reg(cam, 0x20, 0x17); + err += sn9c102_write_reg(cam, 0x04, 0x01); + err += sn9c102_write_reg(cam, 0x01, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x11); + err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x60, 0x17); + err += sn9c102_write_reg(cam, 0x07, 0x18); + + return err; +} + + +static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_GAIN: + err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value); + break; + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value); + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + +static int tas5130d1b_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = &tas5130d1b; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12; + int err = 0; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + /* Do NOT change! */ + err += sn9c102_write_reg(cam, 0x1f, 0x1a); + err += sn9c102_write_reg(cam, 0x1a, 0x1b); + err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19); + + return err; +} + + +static int tas5130d1b_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) +{ + int err = 0; + + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, 0x63, 0x19); + else + err += sn9c102_write_reg(cam, 0xf3, 0x19); + + return err; +} + + +static struct sn9c102_sensor tas5130d1b = { + .name = "TAS5130D1B", + .maintainer = "Luca Risolia ", + .sysfs_ops = SN9C102_I2C_WRITE, + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_3WIRES, + .init = &tas5130d1b_init, + .qctrl = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0xf6, + .step = 0x02, + .default_value = 0x00, + .flags = 0, + }, + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0x47, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + }, + .set_ctrl = &tas5130d1b_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .set_crop = &tas5130d1b_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, + }, + .set_pix_format = &tas5130d1b_set_pix_format +}; + + +int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) +{ + const struct usb_device_id tas5130d1b_id_table[] = { + { USB_DEVICE(0x0c45, 0x6025), }, + { USB_DEVICE(0x0c45, 0x60aa), }, + { } + }; + + /* Sensor detection is based on USB pid/vid */ + if (!sn9c102_match_id(cam, tas5130d1b_id_table)) + return -ENODEV; + + sn9c102_attach_sensor(cam, &tas5130d1b); + + return 0; +} diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c new file mode 100644 index 000000000000..9636da20748d --- /dev/null +++ b/drivers/media/video/stv680.c @@ -0,0 +1,1508 @@ +/* + * STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net) + * + * Thanks to STMicroelectronics for information on the usb commands, and + * to Steve Miller at STM for his help and encouragement while I was + * writing this driver. + * + * This driver is based heavily on the + * Endpoints (formerly known as AOX) se401 USB Camera Driver + * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) + * + * Still somewhat based on the Linux ov511 driver. + * + * 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. + * + * History: + * ver 0.1 October, 2001. Initial attempt. + * + * ver 0.2 November, 2001. Fixed asbility to resize, added brightness + * function, made more stable (?) + * + * ver 0.21 Nov, 2001. Added gamma correction and white balance, + * due to Alexander Schwartz. Still trying to + * improve stablility. Moved stuff into stv680.h + * + * ver 0.22 Nov, 2001. Added sharpen function (by Michael Sweet, + * mike@easysw.com) from GIMP, also used in pencam. + * Simple, fast, good integer math routine. + * + * ver 0.23 Dec, 2001 (gkh) + * Took out sharpen function, ran code through + * Lindent, and did other minor tweaks to get + * things to work properly with 2.5.1 + * + * ver 0.24 Jan, 2002 (kjs) + * Fixed the problem with webcam crashing after + * two pictures. Changed the way pic is halved to + * improve quality. Got rid of green line around + * frame. Fix brightness reset when changing size + * bug. Adjusted gamma filters slightly. + * + * ver 0.25 Jan, 2002 (kjs) + * Fixed a bug in which the driver sometimes attempted + * to set to a non-supported size. This allowed + * gnomemeeting to work. + * Fixed proc entry removal bug. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stv680.h" + +static int video_nr = -1; +static int swapRGB = 0; /* default for auto sleect */ +static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */ + +static unsigned int debug = 0; + +#define PDEBUG(level, fmt, args...) \ + do { \ + if (debug >= level) \ + info("[%s:%d] " fmt, __FUNCTION__, __LINE__ , ## args); \ + } while (0) + + +/* + * Version Information + */ +#define DRIVER_VERSION "v0.25" +#define DRIVER_AUTHOR "Kevin Sisson " +#define DRIVER_DESC "STV0680 USB Camera Driver" + +MODULE_AUTHOR (DRIVER_AUTHOR); +MODULE_DESCRIPTION (DRIVER_DESC); +MODULE_LICENSE ("GPL"); +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC (debug, "Debug enabled or not"); +module_param(swapRGB_on, int, 0); +MODULE_PARM_DESC (swapRGB_on, "Red/blue swap: 1=always, 0=auto, -1=never"); +module_param(video_nr, int, 0); + +/******************************************************************** + * + * Memory management + * + * This is a shameless copy from the USB-cpia driver (linux kernel + * version 2.3.29 or so, I have no idea what this code actually does ;). + * Actually it seems to be a copy of a shameless copy of the bttv-driver. + * Or that is a copy of a shameless copy of ... (To the powers: is there + * no generic kernel-function to do this sort of stuff?) + * + * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says + * there will be one, but apparentely not yet -jerdfelt + * + * So I copied it again for the ov511 driver -claudio + * + * Same for the se401 driver -Jeroen + * + * And the STV0680 driver - Kevin + ********************************************************************/ +static void *rvmalloc (unsigned long size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32 (size); + if (!mem) + return NULL; + + memset (mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + return mem; +} + +static void rvfree (void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree (mem); +} + + +/********************************************************************* + * pencam read/write functions + ********************************************************************/ + +static int stv_sndctrl (int set, struct usb_stv *stv680, unsigned short req, unsigned short value, unsigned char *buffer, int size) +{ + int ret = -1; + + switch (set) { + case 0: /* 0xc1 */ + ret = usb_control_msg (stv680->udev, + usb_rcvctrlpipe (stv680->udev, 0), + req, + (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT), + value, 0, buffer, size, PENCAM_TIMEOUT); + break; + + case 1: /* 0x41 */ + ret = usb_control_msg (stv680->udev, + usb_sndctrlpipe (stv680->udev, 0), + req, + (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT), + value, 0, buffer, size, PENCAM_TIMEOUT); + break; + + case 2: /* 0x80 */ + ret = usb_control_msg (stv680->udev, + usb_rcvctrlpipe (stv680->udev, 0), + req, + (USB_DIR_IN | USB_RECIP_DEVICE), + value, 0, buffer, size, PENCAM_TIMEOUT); + break; + + case 3: /* 0x40 */ + ret = usb_control_msg (stv680->udev, + usb_sndctrlpipe (stv680->udev, 0), + req, + (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE), + value, 0, buffer, size, PENCAM_TIMEOUT); + break; + + } + if ((ret < 0) && (req != 0x0a)) { + PDEBUG (1, "STV(e): usb_control_msg error %i, request = 0x%x, error = %i", set, req, ret); + } + return ret; +} + +static int stv_set_config (struct usb_stv *dev, int configuration, int interface, int alternate) +{ + + if (configuration != dev->udev->actconfig->desc.bConfigurationValue + || usb_reset_configuration (dev->udev) < 0) { + PDEBUG (1, "STV(e): FAILED to reset configuration %i", configuration); + return -1; + } + if (usb_set_interface (dev->udev, interface, alternate) < 0) { + PDEBUG (1, "STV(e): FAILED to set alternate interface %i", alternate); + return -1; + } + return 0; +} + +static int stv_stop_video (struct usb_stv *dev) +{ + int i; + unsigned char *buf; + + buf = kmalloc (40, GFP_KERNEL); + if (buf == NULL) { + PDEBUG (0, "STV(e): Out of (small buf) memory"); + return -1; + } + + /* this is a high priority command; it stops all lower order commands */ + if ((i = stv_sndctrl (1, dev, 0x04, 0x0000, buf, 0x0)) < 0) { + i = stv_sndctrl (0, dev, 0x80, 0, buf, 0x02); /* Get Last Error; 2 = busy */ + PDEBUG (1, "STV(i): last error: %i, command = 0x%x", buf[0], buf[1]); + } else { + PDEBUG (1, "STV(i): Camera reset to idle mode."); + } + + if ((i = stv_set_config (dev, 1, 0, 0)) < 0) + PDEBUG (1, "STV(e): Reset config during exit failed"); + + /* get current mode */ + buf[0] = 0xf0; + if ((i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08)) != 0x08) /* get mode */ + PDEBUG (0, "STV(e): Stop_video: problem setting original mode"); + if (dev->origMode != buf[0]) { + memset (buf, 0, 8); + buf[0] = (unsigned char) dev->origMode; + if ((i = stv_sndctrl (3, dev, 0x07, 0x0100, buf, 0x08)) != 0x08) { + PDEBUG (0, "STV(e): Stop_video: Set_Camera_Mode failed"); + i = -1; + } + buf[0] = 0xf0; + i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08); + if ((i != 0x08) || (buf[0] != dev->origMode)) { + PDEBUG (0, "STV(e): camera NOT set to original resolution."); + i = -1; + } else + PDEBUG (0, "STV(i): Camera set to original resolution"); + } + /* origMode */ + kfree(buf); + return i; +} + +static int stv_set_video_mode (struct usb_stv *dev) +{ + int i, stop_video = 1; + unsigned char *buf; + + buf = kmalloc (40, GFP_KERNEL); + if (buf == NULL) { + PDEBUG (0, "STV(e): Out of (small buf) memory"); + return -1; + } + + if ((i = stv_set_config (dev, 1, 0, 0)) < 0) { + kfree(buf); + return i; + } + + i = stv_sndctrl (2, dev, 0x06, 0x0100, buf, 0x12); + if (!(i > 0) && (buf[8] == 0x53) && (buf[9] == 0x05)) { + PDEBUG (1, "STV(e): Could not get descriptor 0100."); + goto error; + } + + /* set alternate interface 1 */ + if ((i = stv_set_config (dev, 1, 0, 1)) < 0) + goto error; + + if ((i = stv_sndctrl (0, dev, 0x85, 0, buf, 0x10)) != 0x10) + goto error; + PDEBUG (1, "STV(i): Setting video mode."); + /* Switch to Video mode: 0x0100 = VGA (640x480), 0x0000 = CIF (352x288) 0x0300 = QVGA (320x240) */ + if ((i = stv_sndctrl (1, dev, 0x09, dev->VideoMode, buf, 0x0)) < 0) { + stop_video = 0; + goto error; + } + goto exit; + +error: + kfree(buf); + if (stop_video == 1) + stv_stop_video (dev); + return -1; + +exit: + kfree(buf); + return 0; +} + +static int stv_init (struct usb_stv *stv680) +{ + int i = 0; + unsigned char *buffer; + unsigned long int bufsize; + + buffer = kzalloc (40, GFP_KERNEL); + if (buffer == NULL) { + PDEBUG (0, "STV(e): Out of (small buf) memory"); + return -1; + } + udelay (100); + + /* set config 1, interface 0, alternate 0 */ + if ((i = stv_set_config (stv680, 1, 0, 0)) < 0) { + kfree(buffer); + PDEBUG (0, "STV(e): set config 1,0,0 failed"); + return -1; + } + /* ping camera to be sure STV0680 is present */ + if ((i = stv_sndctrl (0, stv680, 0x88, 0x5678, buffer, 0x02)) != 0x02) + goto error; + if ((buffer[0] != 0x56) || (buffer[1] != 0x78)) { + PDEBUG (1, "STV(e): camera ping failed!!"); + goto error; + } + + /* get camera descriptor */ + if ((i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x09)) != 0x09) + goto error; + i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x22); + if (!(i >= 0) && (buffer[7] == 0xa0) && (buffer[8] == 0x23)) { + PDEBUG (1, "STV(e): Could not get descriptor 0200."); + goto error; + } + if ((i = stv_sndctrl (0, stv680, 0x8a, 0, buffer, 0x02)) != 0x02) + goto error; + if ((i = stv_sndctrl (0, stv680, 0x8b, 0, buffer, 0x24)) != 0x24) + goto error; + if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10) + goto error; + + stv680->SupportedModes = buffer[7]; + i = stv680->SupportedModes; + stv680->CIF = 0; + stv680->VGA = 0; + stv680->QVGA = 0; + if (i & 1) + stv680->CIF = 1; + if (i & 2) + stv680->VGA = 1; + if (i & 8) + stv680->QVGA = 1; + if (stv680->SupportedModes == 0) { + PDEBUG (0, "STV(e): There are NO supported STV680 modes!!"); + i = -1; + goto error; + } else { + if (stv680->CIF) + PDEBUG (0, "STV(i): CIF is supported"); + if (stv680->QVGA) + PDEBUG (0, "STV(i): QVGA is supported"); + } + /* FW rev, ASIC rev, sensor ID */ + PDEBUG (1, "STV(i): Firmware rev is %i.%i", buffer[0], buffer[1]); + PDEBUG (1, "STV(i): ASIC rev is %i.%i", buffer[2], buffer[3]); + PDEBUG (1, "STV(i): Sensor ID is %i", (buffer[4]*16) + (buffer[5]>>4)); + + /* set alternate interface 1 */ + if ((i = stv_set_config (stv680, 1, 0, 1)) < 0) + goto error; + + if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10) + goto error; + if ((i = stv_sndctrl (0, stv680, 0x8d, 0, buffer, 0x08)) != 0x08) + goto error; + i = buffer[3]; + PDEBUG (0, "STV(i): Camera has %i pictures.", i); + + /* get current mode */ + if ((i = stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08)) != 0x08) + goto error; + stv680->origMode = buffer[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */ + + /* This will attemp CIF mode, if supported. If not, set to QVGA */ + memset (buffer, 0, 8); + if (stv680->CIF) + buffer[0] = 0x00; + else if (stv680->QVGA) + buffer[0] = 0x03; + if ((i = stv_sndctrl (3, stv680, 0x07, 0x0100, buffer, 0x08)) != 0x08) { + PDEBUG (0, "STV(i): Set_Camera_Mode failed"); + i = -1; + goto error; + } + buffer[0] = 0xf0; + stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08); + if (((stv680->CIF == 1) && (buffer[0] != 0x00)) || ((stv680->QVGA == 1) && (buffer[0] != 0x03))) { + PDEBUG (0, "STV(e): Error setting camera video mode!"); + i = -1; + goto error; + } else { + if (buffer[0] == 0) { + stv680->VideoMode = 0x0000; + PDEBUG (0, "STV(i): Video Mode set to CIF"); + } + if (buffer[0] == 0x03) { + stv680->VideoMode = 0x0300; + PDEBUG (0, "STV(i): Video Mode set to QVGA"); + } + } + if ((i = stv_sndctrl (0, stv680, 0x8f, 0, buffer, 0x10)) != 0x10) + goto error; + bufsize = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3]); + stv680->cwidth = (buffer[4] << 8) | (buffer[5]); /* ->camera = 322, 356, 644 */ + stv680->cheight = (buffer[6] << 8) | (buffer[7]); /* ->camera = 242, 292, 484 */ + stv680->origGain = buffer[12]; + + goto exit; + +error: + i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02); /* Get Last Error */ + PDEBUG (1, "STV(i): last error: %i, command = 0x%x", buffer[0], buffer[1]); + kfree(buffer); + return -1; + +exit: + kfree(buffer); + + /* video = 320x240, 352x288 */ + if (stv680->CIF == 1) { + stv680->maxwidth = 352; + stv680->maxheight = 288; + stv680->vwidth = 352; + stv680->vheight = 288; + } + if (stv680->QVGA == 1) { + stv680->maxwidth = 320; + stv680->maxheight = 240; + stv680->vwidth = 320; + stv680->vheight = 240; + } + + stv680->rawbufsize = bufsize; /* must be ./. by 8 */ + stv680->maxframesize = bufsize * 3; /* RGB size */ + PDEBUG (2, "STV(i): cwidth = %i, cheight = %i", stv680->cwidth, stv680->cheight); + PDEBUG (1, "STV(i): width = %i, height = %i, rawbufsize = %li", stv680->vwidth, stv680->vheight, stv680->rawbufsize); + + /* some default values */ + stv680->bulk_in_endpointAddr = 0x82; + stv680->dropped = 0; + stv680->error = 0; + stv680->framecount = 0; + stv680->readcount = 0; + stv680->streaming = 0; + /* bright, white, colour, hue, contrast are set by software, not in stv0680 */ + stv680->brightness = 32767; + stv680->chgbright = 0; + stv680->whiteness = 0; /* only for greyscale */ + stv680->colour = 32767; + stv680->contrast = 32767; + stv680->hue = 32767; + stv680->palette = STV_VIDEO_PALETTE; + stv680->depth = 24; /* rgb24 bits */ + if ((swapRGB_on == 0) && (swapRGB == 0)) + PDEBUG (1, "STV(i): swapRGB is (auto) OFF"); + else if ((swapRGB_on == 0) && (swapRGB == 1)) + PDEBUG (1, "STV(i): swapRGB is (auto) ON"); + else if (swapRGB_on == 1) + PDEBUG (1, "STV(i): swapRGB is (forced) ON"); + else if (swapRGB_on == -1) + PDEBUG (1, "STV(i): swapRGB is (forced) OFF"); + + if (stv_set_video_mode (stv680) < 0) { + PDEBUG (0, "STV(e): Could not set video mode in stv_init"); + return -1; + } + + return 0; +} + +/***************** last of pencam routines *******************/ + +/**************************************************************************** + * sysfs + ***************************************************************************/ +#define stv680_file(name, variable, field) \ +static ssize_t show_##name(struct class_device *class_dev, char *buf) \ +{ \ + struct video_device *vdev = to_video_device(class_dev); \ + struct usb_stv *stv = video_get_drvdata(vdev); \ + return sprintf(buf, field, stv->variable); \ +} \ +static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); + +stv680_file(model, camera_name, "%s\n"); +stv680_file(in_use, user, "%d\n"); +stv680_file(streaming, streaming, "%d\n"); +stv680_file(palette, palette, "%i\n"); +stv680_file(frames_total, readcount, "%d\n"); +stv680_file(frames_read, framecount, "%d\n"); +stv680_file(packets_dropped, dropped, "%d\n"); +stv680_file(decoding_errors, error, "%d\n"); + +static void stv680_create_sysfs_files(struct video_device *vdev) +{ + video_device_create_file(vdev, &class_device_attr_model); + video_device_create_file(vdev, &class_device_attr_in_use); + video_device_create_file(vdev, &class_device_attr_streaming); + video_device_create_file(vdev, &class_device_attr_palette); + video_device_create_file(vdev, &class_device_attr_frames_total); + video_device_create_file(vdev, &class_device_attr_frames_read); + video_device_create_file(vdev, &class_device_attr_packets_dropped); + video_device_create_file(vdev, &class_device_attr_decoding_errors); +} + +static void stv680_remove_sysfs_files(struct video_device *vdev) +{ + video_device_remove_file(vdev, &class_device_attr_model); + video_device_remove_file(vdev, &class_device_attr_in_use); + video_device_remove_file(vdev, &class_device_attr_streaming); + video_device_remove_file(vdev, &class_device_attr_palette); + video_device_remove_file(vdev, &class_device_attr_frames_total); + video_device_remove_file(vdev, &class_device_attr_frames_read); + video_device_remove_file(vdev, &class_device_attr_packets_dropped); + video_device_remove_file(vdev, &class_device_attr_decoding_errors); +} + +/******************************************************************** + * Camera control + *******************************************************************/ + +static int stv680_get_pict (struct usb_stv *stv680, struct video_picture *p) +{ + /* This sets values for v4l interface. max/min = 65535/0 */ + + p->brightness = stv680->brightness; + p->whiteness = stv680->whiteness; /* greyscale */ + p->colour = stv680->colour; + p->contrast = stv680->contrast; + p->hue = stv680->hue; + p->palette = stv680->palette; + p->depth = stv680->depth; + return 0; +} + +static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p) +{ + /* See above stv680_get_pict */ + + if (p->palette != STV_VIDEO_PALETTE) { + PDEBUG (2, "STV(e): Palette set error in _set_pic"); + return 1; + } + + if (stv680->brightness != p->brightness) { + stv680->chgbright = 1; + stv680->brightness = p->brightness; + } + + stv680->whiteness = p->whiteness; /* greyscale */ + stv680->colour = p->colour; + stv680->contrast = p->contrast; + stv680->hue = p->hue; + stv680->palette = p->palette; + stv680->depth = p->depth; + + return 0; +} + +static void stv680_video_irq (struct urb *urb, struct pt_regs *regs) +{ + struct usb_stv *stv680 = urb->context; + int length = urb->actual_length; + + if (length < stv680->rawbufsize) + PDEBUG (2, "STV(i): Lost data in transfer: exp %li, got %i", stv680->rawbufsize, length); + + /* ohoh... */ + if (!stv680->streaming) + return; + + if (!stv680->udev) { + PDEBUG (0, "STV(e): device vapourished in video_irq"); + return; + } + + /* 0 sized packets happen if we are to fast, but sometimes the camera + keeps sending them forever... + */ + if (length && !urb->status) { + stv680->nullpackets = 0; + switch (stv680->scratch[stv680->scratch_next].state) { + case BUFFER_READY: + case BUFFER_BUSY: + stv680->dropped++; + break; + + case BUFFER_UNUSED: + memcpy (stv680->scratch[stv680->scratch_next].data, + (unsigned char *) urb->transfer_buffer, length); + stv680->scratch[stv680->scratch_next].state = BUFFER_READY; + stv680->scratch[stv680->scratch_next].length = length; + if (waitqueue_active (&stv680->wq)) { + wake_up_interruptible (&stv680->wq); + } + stv680->scratch_overflow = 0; + stv680->scratch_next++; + if (stv680->scratch_next >= STV680_NUMSCRATCH) + stv680->scratch_next = 0; + break; + } /* switch */ + } else { + stv680->nullpackets++; + if (stv680->nullpackets > STV680_MAX_NULLPACKETS) { + if (waitqueue_active (&stv680->wq)) { + wake_up_interruptible (&stv680->wq); + } + } + } /* if - else */ + + /* Resubmit urb for new data */ + urb->status = 0; + urb->dev = stv680->udev; + if (usb_submit_urb (urb, GFP_ATOMIC)) + PDEBUG (0, "STV(e): urb burned down in video irq"); + return; +} /* _video_irq */ + +static int stv680_start_stream (struct usb_stv *stv680) +{ + struct urb *urb; + int err = 0, i; + + stv680->streaming = 1; + + /* Do some memory allocation */ + for (i = 0; i < STV680_NUMFRAMES; i++) { + stv680->frame[i].data = stv680->fbuf + i * stv680->maxframesize; + stv680->frame[i].curpix = 0; + } + /* packet size = 4096 */ + for (i = 0; i < STV680_NUMSBUF; i++) { + stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); + if (stv680->sbuf[i].data == NULL) { + PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i); + return -1; + } + } + + stv680->scratch_next = 0; + stv680->scratch_use = 0; + stv680->scratch_overflow = 0; + for (i = 0; i < STV680_NUMSCRATCH; i++) { + stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); + if (stv680->scratch[i].data == NULL) { + PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i); + return -1; + } + stv680->scratch[i].state = BUFFER_UNUSED; + } + + for (i = 0; i < STV680_NUMSBUF; i++) { + urb = usb_alloc_urb (0, GFP_KERNEL); + if (!urb) + return -ENOMEM; + + /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */ + usb_fill_bulk_urb (urb, stv680->udev, + usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr), + stv680->sbuf[i].data, stv680->rawbufsize, + stv680_video_irq, stv680); + stv680->urb[i] = urb; + err = usb_submit_urb (stv680->urb[i], GFP_KERNEL); + if (err) + PDEBUG (0, "STV(e): urb burned down in start stream"); + } /* i STV680_NUMSBUF */ + + stv680->framecount = 0; + return 0; +} + +static int stv680_stop_stream (struct usb_stv *stv680) +{ + int i; + + if (!stv680->streaming || !stv680->udev) + return 1; + + stv680->streaming = 0; + + for (i = 0; i < STV680_NUMSBUF; i++) + if (stv680->urb[i]) { + usb_kill_urb (stv680->urb[i]); + usb_free_urb (stv680->urb[i]); + stv680->urb[i] = NULL; + kfree(stv680->sbuf[i].data); + } + for (i = 0; i < STV680_NUMSCRATCH; i++) { + kfree(stv680->scratch[i].data); + stv680->scratch[i].data = NULL; + } + + return 0; +} + +static int stv680_set_size (struct usb_stv *stv680, int width, int height) +{ + int wasstreaming = stv680->streaming; + + /* Check to see if we need to change */ + if ((stv680->vwidth == width) && (stv680->vheight == height)) + return 0; + + PDEBUG (1, "STV(i): size request for %i x %i", width, height); + /* Check for a valid mode */ + if ((!width || !height) || ((width & 1) || (height & 1))) { + PDEBUG (1, "STV(e): set_size error: request: v.width = %i, v.height = %i actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight); + return 1; + } + + if ((width < (stv680->maxwidth / 2)) || (height < (stv680->maxheight / 2))) { + width = stv680->maxwidth / 2; + height = stv680->maxheight / 2; + } else if ((width >= 158) && (width <= 166) && (stv680->QVGA == 1)) { + width = 160; + height = 120; + } else if ((width >= 172) && (width <= 180) && (stv680->CIF == 1)) { + width = 176; + height = 144; + } else if ((width >= 318) && (width <= 350) && (stv680->QVGA == 1)) { + width = 320; + height = 240; + } else if ((width >= 350) && (width <= 358) && (stv680->CIF == 1)) { + width = 352; + height = 288; + } else { + PDEBUG (1, "STV(e): request for non-supported size: request: v.width = %i, v.height = %i actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight); + return 1; + } + + /* Stop a current stream and start it again at the new size */ + if (wasstreaming) + stv680_stop_stream (stv680); + stv680->vwidth = width; + stv680->vheight = height; + PDEBUG (1, "STV(i): size set to %i x %i", stv680->vwidth, stv680->vheight); + if (wasstreaming) + stv680_start_stream (stv680); + + return 0; +} + +/********************************************************************** + * Video Decoding + **********************************************************************/ + +/******* routines from the pencam program; hey, they work! ********/ + +/* + * STV0680 Vision Camera Chipset Driver + * Copyright (C) 2000 Adam Harrison +*/ + +#define RED 0 +#define GREEN 1 +#define BLUE 2 +#define AD(x, y, w) (((y)*(w)+(x))*3) + +static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buffer) +{ + int x, y, i; + int w = stv680->cwidth; + int vw = stv680->cwidth, vh = stv680->cheight; + unsigned int p = 0; + int colour = 0, bayer = 0; + unsigned char *raw = buffer->data; + struct stv680_frame *frame = &stv680->frame[stv680->curframe]; + unsigned char *output = frame->data; + unsigned char *temp = frame->data; + int offset = buffer->offset; + + if (frame->curpix == 0) { + if (frame->grabstate == FRAME_READY) { + frame->grabstate = FRAME_GRABBING; + } + } + if (offset != frame->curpix) { /* Regard frame as lost :( */ + frame->curpix = 0; + stv680->error++; + return; + } + + if ((stv680->vwidth == 320) || (stv680->vwidth == 160)) { + vw = 320; + vh = 240; + } + if ((stv680->vwidth == 352) || (stv680->vwidth == 176)) { + vw = 352; + vh = 288; + } + + memset (output, 0, 3 * vw * vh); /* clear output matrix. */ + + for (y = 0; y < vh; y++) { + for (x = 0; x < vw; x++) { + if (x & 1) + p = *(raw + y * w + (x >> 1)); + else + p = *(raw + y * w + (x >> 1) + (w >> 1)); + + if (y & 1) + bayer = 2; + else + bayer = 0; + if (x & 1) + bayer++; + + switch (bayer) { + case 0: + case 3: + colour = 1; + break; + case 1: + colour = 0; + break; + case 2: + colour = 2; + break; + } + i = (y * vw + x) * 3; + *(output + i + colour) = (unsigned char) p; + } /* for x */ + + } /* for y */ + + /****** gamma correction plus hardcoded white balance */ + /* Thanks to Alexander Schwartx for this code. + Correction values red[], green[], blue[], are generated by + (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1> 1; + *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x, y - 1, vw) + RED) + (int) *(output + AD (x, y + 1, vw) + RED)) >> 1; + break; + + case 1: /* blue. green lrtb, red diagonals */ + *(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2; + *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y - 1, vw) + RED) + (int) *(output + AD (x - 1, y + 1, vw) + RED) + (int) *(output + AD (x + 1, y - 1, vw) + RED) + (int) *(output + AD (x + 1, y + 1, vw) + RED)) >> 2; + break; + + case 2: /* red. green lrtb, blue diagonals */ + *(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2; + *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y - 1, vw) + BLUE) + (int) *(output + AD (x + 1, y - 1, vw) + BLUE) + (int) *(output + AD (x - 1, y + 1, vw) + BLUE) + (int) *(output + AD (x + 1, y + 1, vw) + BLUE)) >> 2; + break; + + case 3: /* green. red lr, blue tb */ + *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y, vw) + RED) + (int) *(output + AD (x + 1, y, vw) + RED)) >> 1; + *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x, y - 1, vw) + BLUE) + (int) *(output + AD (x, y + 1, vw) + BLUE)) >> 1; + break; + } /* switch */ + } /* for x */ + } /* for y - end demosaic */ + + /* fix top and bottom row, left and right side */ + i = vw * 3; + memcpy (output, (output + i), i); + memcpy ((output + (vh * i)), (output + ((vh - 1) * i)), i); + for (y = 0; y < vh; y++) { + i = y * vw * 3; + memcpy ((output + i), (output + i + 3), 3); + memcpy ((output + i + (vw * 3)), (output + i + (vw - 1) * 3), 3); + } + + /* process all raw data, then trim to size if necessary */ + if ((stv680->vwidth == 160) || (stv680->vwidth == 176)) { + i = 0; + for (y = 0; y < vh; y++) { + if (!(y & 1)) { + for (x = 0; x < vw; x++) { + p = (y * vw + x) * 3; + if (!(x & 1)) { + *(output + i) = *(output + p); + *(output + i + 1) = *(output + p + 1); + *(output + i + 2) = *(output + p + 2); + i += 3; + } + } /* for x */ + } + } /* for y */ + } + /* reset to proper width */ + if ((stv680->vwidth == 160)) { + vw = 160; + vh = 120; + } + if ((stv680->vwidth == 176)) { + vw = 176; + vh = 144; + } + + /* output is RGB; some programs want BGR */ + /* swapRGB_on=0 -> program decides; swapRGB_on=1, always swap */ + /* swapRGB_on=-1, never swap */ + if (((swapRGB == 1) && (swapRGB_on != -1)) || (swapRGB_on == 1)) { + for (y = 0; y < vh; y++) { + for (x = 0; x < vw; x++) { + i = (y * vw + x) * 3; + *(temp) = *(output + i); + *(output + i) = *(output + i + 2); + *(output + i + 2) = *(temp); + } + } + } + /* brightness */ + if (stv680->chgbright == 1) { + if (stv680->brightness >= 32767) { + p = (stv680->brightness - 32767) / 256; + for (x = 0; x < (vw * vh * 3); x++) { + if ((*(output + x) + (unsigned char) p) > 255) + *(output + x) = 255; + else + *(output + x) += (unsigned char) p; + } /* for */ + } else { + p = (32767 - stv680->brightness) / 256; + for (x = 0; x < (vw * vh * 3); x++) { + if ((unsigned char) p > *(output + x)) + *(output + x) = 0; + else + *(output + x) -= (unsigned char) p; + } /* for */ + } /* else */ + } + /* if */ + frame->curpix = 0; + frame->curlinepix = 0; + frame->grabstate = FRAME_DONE; + stv680->framecount++; + stv680->readcount++; + if (stv680->frame[(stv680->curframe + 1) & (STV680_NUMFRAMES - 1)].grabstate == FRAME_READY) { + stv680->curframe = (stv680->curframe + 1) & (STV680_NUMFRAMES - 1); + } + +} /* bayer_unshuffle */ + +/******* end routines from the pencam program *********/ + +static int stv680_newframe (struct usb_stv *stv680, int framenr) +{ + int errors = 0; + + while (stv680->streaming && (stv680->frame[framenr].grabstate == FRAME_READY || stv680->frame[framenr].grabstate == FRAME_GRABBING)) { + if (!stv680->frame[framenr].curpix) { + errors++; + } + wait_event_interruptible (stv680->wq, (stv680->scratch[stv680->scratch_use].state == BUFFER_READY)); + + if (stv680->nullpackets > STV680_MAX_NULLPACKETS) { + stv680->nullpackets = 0; + PDEBUG (2, "STV(i): too many null length packets, restarting capture"); + stv680_stop_stream (stv680); + stv680_start_stream (stv680); + } else { + if (stv680->scratch[stv680->scratch_use].state != BUFFER_READY) { + stv680->frame[framenr].grabstate = FRAME_ERROR; + PDEBUG (2, "STV(e): FRAME_ERROR in _newframe"); + return -EIO; + } + stv680->scratch[stv680->scratch_use].state = BUFFER_BUSY; + + bayer_unshuffle (stv680, &stv680->scratch[stv680->scratch_use]); + + stv680->scratch[stv680->scratch_use].state = BUFFER_UNUSED; + stv680->scratch_use++; + if (stv680->scratch_use >= STV680_NUMSCRATCH) + stv680->scratch_use = 0; + if (errors > STV680_MAX_ERRORS) { + errors = 0; + PDEBUG (2, "STV(i): too many errors, restarting capture"); + stv680_stop_stream (stv680); + stv680_start_stream (stv680); + } + } /* else */ + } /* while */ + return 0; +} + +/********************************************************************* + * Video4Linux + *********************************************************************/ + +static int stv_open (struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct usb_stv *stv680 = video_get_drvdata(dev); + int err = 0; + + /* we are called with the BKL held */ + stv680->user = 1; + err = stv_init (stv680); /* main initialization routine for camera */ + + if (err >= 0) { + stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES); + if (!stv680->fbuf) { + PDEBUG (0, "STV(e): Could not rvmalloc frame bufer"); + err = -ENOMEM; + } + file->private_data = dev; + } + if (err) + stv680->user = 0; + + return err; +} + +static int stv_close (struct inode *inode, struct file *file) +{ + struct video_device *dev = file->private_data; + struct usb_stv *stv680 = video_get_drvdata(dev); + int i; + + for (i = 0; i < STV680_NUMFRAMES; i++) + stv680->frame[i].grabstate = FRAME_UNUSED; + if (stv680->streaming) + stv680_stop_stream (stv680); + + if ((i = stv_stop_video (stv680)) < 0) + PDEBUG (1, "STV(e): stop_video failed in stv_close"); + + rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES); + stv680->user = 0; + + if (stv680->removed) { + kfree(stv680); + stv680 = NULL; + PDEBUG (0, "STV(i): device unregistered"); + } + file->private_data = NULL; + return 0; +} + +static int stv680_do_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct video_device *vdev = file->private_data; + struct usb_stv *stv680 = video_get_drvdata(vdev); + + if (!stv680->udev) + return -EIO; + + switch (cmd) { + case VIDIOCGCAP:{ + struct video_capability *b = arg; + + strcpy (b->name, stv680->camera_name); + b->type = VID_TYPE_CAPTURE; + b->channels = 1; + b->audios = 0; + b->maxwidth = stv680->maxwidth; + b->maxheight = stv680->maxheight; + b->minwidth = stv680->maxwidth / 2; + b->minheight = stv680->maxheight / 2; + return 0; + } + case VIDIOCGCHAN:{ + struct video_channel *v = arg; + + if (v->channel != 0) + return -EINVAL; + v->flags = 0; + v->tuners = 0; + v->type = VIDEO_TYPE_CAMERA; + strcpy (v->name, "STV Camera"); + return 0; + } + case VIDIOCSCHAN:{ + struct video_channel *v = arg; + if (v->channel != 0) + return -EINVAL; + return 0; + } + case VIDIOCGPICT:{ + struct video_picture *p = arg; + + stv680_get_pict (stv680, p); + return 0; + } + case VIDIOCSPICT:{ + struct video_picture *p = arg; + + if (stv680_set_pict (stv680, p)) + return -EINVAL; + return 0; + } + case VIDIOCSWIN:{ + struct video_window *vw = arg; + + if (vw->flags) + return -EINVAL; + if (vw->clipcount) + return -EINVAL; + if (vw->width != stv680->vwidth) { + if (stv680_set_size (stv680, vw->width, vw->height)) { + PDEBUG (2, "STV(e): failed (from user) set size in VIDIOCSWIN"); + return -EINVAL; + } + } + return 0; + } + case VIDIOCGWIN:{ + struct video_window *vw = arg; + + vw->x = 0; /* FIXME */ + vw->y = 0; + vw->chromakey = 0; + vw->flags = 0; + vw->clipcount = 0; + vw->width = stv680->vwidth; + vw->height = stv680->vheight; + return 0; + } + case VIDIOCGMBUF:{ + struct video_mbuf *vm = arg; + int i; + + memset (vm, 0, sizeof (*vm)); + vm->size = STV680_NUMFRAMES * stv680->maxframesize; + vm->frames = STV680_NUMFRAMES; + for (i = 0; i < STV680_NUMFRAMES; i++) + vm->offsets[i] = stv680->maxframesize * i; + return 0; + } + case VIDIOCMCAPTURE:{ + struct video_mmap *vm = arg; + + if (vm->format != STV_VIDEO_PALETTE) { + PDEBUG (2, "STV(i): VIDIOCMCAPTURE vm.format (%i) != VIDEO_PALETTE (%i)", + vm->format, STV_VIDEO_PALETTE); + if ((vm->format == 3) && (swapRGB_on == 0)) { + PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is (auto) ON"); + /* this may fix those apps (e.g., xawtv) that want BGR */ + swapRGB = 1; + } + return -EINVAL; + } + if (vm->frame >= STV680_NUMFRAMES) { + PDEBUG (2, "STV(e): VIDIOCMCAPTURE vm.frame > NUMFRAMES"); + return -EINVAL; + } + if ((stv680->frame[vm->frame].grabstate == FRAME_ERROR) + || (stv680->frame[vm->frame].grabstate == FRAME_GRABBING)) { + PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate (%i) error", + stv680->frame[vm->frame].grabstate); + return -EBUSY; + } + /* Is this according to the v4l spec??? */ + if (stv680->vwidth != vm->width) { + if (stv680_set_size (stv680, vm->width, vm->height)) { + PDEBUG (2, "STV(e): VIDIOCMCAPTURE set_size failed"); + return -EINVAL; + } + } + stv680->frame[vm->frame].grabstate = FRAME_READY; + + if (!stv680->streaming) + stv680_start_stream (stv680); + + return 0; + } + case VIDIOCSYNC:{ + int *frame = arg; + int ret = 0; + + if (*frame < 0 || *frame >= STV680_NUMFRAMES) { + PDEBUG (2, "STV(e): Bad frame # in VIDIOCSYNC"); + return -EINVAL; + } + ret = stv680_newframe (stv680, *frame); + stv680->frame[*frame].grabstate = FRAME_UNUSED; + return ret; + } + case VIDIOCGFBUF:{ + struct video_buffer *vb = arg; + + memset (vb, 0, sizeof (*vb)); + return 0; + } + case VIDIOCKEY: + return 0; + case VIDIOCCAPTURE: + { + PDEBUG (2, "STV(e): VIDIOCCAPTURE failed"); + return -EINVAL; + } + case VIDIOCSFBUF: + case VIDIOCGTUNER: + case VIDIOCSTUNER: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + default: + return -ENOIOCTLCMD; + } /* end switch */ + + return 0; +} + +static int stv680_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, stv680_do_ioctl); +} + +static int stv680_mmap (struct file *file, struct vm_area_struct *vma) +{ + struct video_device *dev = file->private_data; + struct usb_stv *stv680 = video_get_drvdata(dev); + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end-vma->vm_start; + unsigned long page, pos; + + mutex_lock(&stv680->lock); + + if (stv680->udev == NULL) { + mutex_unlock(&stv680->lock); + return -EIO; + } + if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1) + & ~(PAGE_SIZE - 1))) { + mutex_unlock(&stv680->lock); + return -EINVAL; + } + pos = (unsigned long) stv680->fbuf; + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { + mutex_unlock(&stv680->lock); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + mutex_unlock(&stv680->lock); + + return 0; +} + +static ssize_t stv680_read (struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct video_device *dev = file->private_data; + unsigned long int realcount = count; + int ret = 0; + struct usb_stv *stv680 = video_get_drvdata(dev); + unsigned long int i; + + if (STV680_NUMFRAMES != 2) { + PDEBUG (0, "STV(e): STV680_NUMFRAMES needs to be 2!"); + return -1; + } + if (stv680->udev == NULL) + return -EIO; + if (realcount > (stv680->vwidth * stv680->vheight * 3)) + realcount = stv680->vwidth * stv680->vheight * 3; + + /* Shouldn't happen: */ + if (stv680->frame[0].grabstate == FRAME_GRABBING) { + PDEBUG (2, "STV(e): FRAME_GRABBING in stv680_read"); + return -EBUSY; + } + stv680->frame[0].grabstate = FRAME_READY; + stv680->frame[1].grabstate = FRAME_UNUSED; + stv680->curframe = 0; + + if (!stv680->streaming) + stv680_start_stream (stv680); + + if (!stv680->streaming) { + ret = stv680_newframe (stv680, 0); /* ret should = 0 */ + } + + ret = stv680_newframe (stv680, 0); + + if (!ret) { + if ((i = copy_to_user (buf, stv680->frame[0].data, realcount)) != 0) { + PDEBUG (2, "STV(e): copy_to_user frame 0 failed, ret count = %li", i); + return -EFAULT; + } + } else { + realcount = ret; + } + stv680->frame[0].grabstate = FRAME_UNUSED; + return realcount; +} /* stv680_read */ + +static struct file_operations stv680_fops = { + .owner = THIS_MODULE, + .open = stv_open, + .release = stv_close, + .read = stv680_read, + .mmap = stv680_mmap, + .ioctl = stv680_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .llseek = no_llseek, +}; +static struct video_device stv680_template = { + .owner = THIS_MODULE, + .name = "STV0680 USB camera", + .type = VID_TYPE_CAPTURE, + .hardware = VID_HARDWARE_SE401, + .fops = &stv680_fops, + .release = video_device_release, + .minor = -1, +}; + +static int stv680_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_stv *stv680 = NULL; + char *camera_name = NULL; + int retval = 0; + + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) { + PDEBUG (0, "STV(e): Number of Configurations != 1"); + return -ENODEV; + } + + interface = &intf->altsetting[0]; + /* Is it a STV680? */ + if ((le16_to_cpu(dev->descriptor.idVendor) == USB_PENCAM_VENDOR_ID) && + (le16_to_cpu(dev->descriptor.idProduct) == USB_PENCAM_PRODUCT_ID)) { + camera_name = "STV0680"; + PDEBUG (0, "STV(i): STV0680 camera found."); + } else if ((le16_to_cpu(dev->descriptor.idVendor) == USB_CREATIVEGOMINI_VENDOR_ID) && + (le16_to_cpu(dev->descriptor.idProduct) == USB_CREATIVEGOMINI_PRODUCT_ID)) { + camera_name = "Creative WebCam Go Mini"; + PDEBUG (0, "STV(i): Creative WebCam Go Mini found."); + } else { + PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 or Creative WebCam Go Mini values."); + PDEBUG (0, "STV(e): Check that the STV0680 or Creative WebCam Go Mini camera is connected to the computer."); + retval = -ENODEV; + goto error; + } + /* We found one */ + if ((stv680 = kzalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) { + PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct."); + retval = -ENOMEM; + goto error; + } + + stv680->udev = dev; + stv680->camera_name = camera_name; + + stv680->vdev = video_device_alloc(); + if (!stv680->vdev) { + retval = -ENOMEM; + goto error; + } + memcpy(stv680->vdev, &stv680_template, sizeof(stv680_template)); + stv680->vdev->dev = &intf->dev; + video_set_drvdata(stv680->vdev, stv680); + + memcpy (stv680->vdev->name, stv680->camera_name, strlen (stv680->camera_name)); + init_waitqueue_head (&stv680->wq); + mutex_init (&stv680->lock); + wmb (); + + if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + PDEBUG (0, "STV(e): video_register_device failed"); + retval = -EIO; + goto error_vdev; + } + PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev->minor); + + usb_set_intfdata (intf, stv680); + stv680_create_sysfs_files(stv680->vdev); + return 0; + +error_vdev: + video_device_release(stv680->vdev); +error: + kfree(stv680); + return retval; +} + +static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680) +{ + int i; + + stv680->udev = NULL; + stv680->frame[0].grabstate = FRAME_ERROR; + stv680->frame[1].grabstate = FRAME_ERROR; + stv680->streaming = 0; + + wake_up_interruptible (&stv680->wq); + + for (i = 0; i < STV680_NUMSBUF; i++) + if (stv680->urb[i]) { + usb_kill_urb (stv680->urb[i]); + usb_free_urb (stv680->urb[i]); + stv680->urb[i] = NULL; + kfree(stv680->sbuf[i].data); + } + for (i = 0; i < STV680_NUMSCRATCH; i++) + kfree(stv680->scratch[i].data); + PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name); + + /* Free the memory */ + kfree(stv680); +} + +static void stv680_disconnect (struct usb_interface *intf) +{ + struct usb_stv *stv680 = usb_get_intfdata (intf); + + usb_set_intfdata (intf, NULL); + + if (stv680) { + /* We don't want people trying to open up the device */ + if (stv680->vdev) { + stv680_remove_sysfs_files(stv680->vdev); + video_unregister_device(stv680->vdev); + stv680->vdev = NULL; + } + if (!stv680->user) { + usb_stv680_remove_disconnected (stv680); + } else { + stv680->removed = 1; + } + } +} + +static struct usb_driver stv680_driver = { + .name = "stv680", + .probe = stv680_probe, + .disconnect = stv680_disconnect, + .id_table = device_table +}; + +/******************************************************************** + * Module routines + ********************************************************************/ + +static int __init usb_stv680_init (void) +{ + if (usb_register (&stv680_driver) < 0) { + PDEBUG (0, "STV(e): Could not setup STV0680 driver"); + return -1; + } + PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION); + + info(DRIVER_DESC " " DRIVER_VERSION); + return 0; +} + +static void __exit usb_stv680_exit (void) +{ + usb_deregister (&stv680_driver); + PDEBUG (0, "STV(i): driver deregistered"); +} + +module_init (usb_stv680_init); +module_exit (usb_stv680_exit); diff --git a/drivers/media/video/stv680.h b/drivers/media/video/stv680.h new file mode 100644 index 000000000000..ea46e0001e6d --- /dev/null +++ b/drivers/media/video/stv680.h @@ -0,0 +1,227 @@ +/**************************************************************************** + * + * Filename: stv680.h + * + * Description: + * This is a USB driver for STV0680 based usb video cameras. + * + * 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. + * + ****************************************************************************/ + +/* size of usb transfers */ +#define STV680_PACKETSIZE 4096 + +/* number of queued bulk transfers to use, may have problems if > 1 */ +#define STV680_NUMSBUF 1 + +/* number of frames supported by the v4l part */ +#define STV680_NUMFRAMES 2 + +/* scratch buffers for passing data to the decoders: 2 or 4 are good */ +#define STV680_NUMSCRATCH 2 + +/* number of nul sized packets to receive before kicking the camera */ +#define STV680_MAX_NULLPACKETS 200 + +/* number of decoding errors before kicking the camera */ +#define STV680_MAX_ERRORS 100 + +#define USB_PENCAM_VENDOR_ID 0x0553 +#define USB_PENCAM_PRODUCT_ID 0x0202 + +#define USB_CREATIVEGOMINI_VENDOR_ID 0x041e +#define USB_CREATIVEGOMINI_PRODUCT_ID 0x4007 + +#define PENCAM_TIMEOUT 1000 +/* fmt 4 */ +#define STV_VIDEO_PALETTE VIDEO_PALETTE_RGB24 + +static struct usb_device_id device_table[] = { + {USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)}, + {USB_DEVICE (USB_CREATIVEGOMINI_VENDOR_ID, USB_CREATIVEGOMINI_PRODUCT_ID)}, + {} +}; +MODULE_DEVICE_TABLE (usb, device_table); + +struct stv680_sbuf { + unsigned char *data; +}; + +enum { + FRAME_UNUSED, /* Unused (no MCAPTURE) */ + FRAME_READY, /* Ready to start grabbing */ + FRAME_GRABBING, /* In the process of being grabbed into */ + FRAME_DONE, /* Finished grabbing, but not been synced yet */ + FRAME_ERROR, /* Something bad happened while processing */ +}; + +enum { + BUFFER_UNUSED, + BUFFER_READY, + BUFFER_BUSY, + BUFFER_DONE, +}; + +/* raw camera data <- sbuf (urb transfer buf) */ +struct stv680_scratch { + unsigned char *data; + volatile int state; + int offset; + int length; +}; + +/* processed data for display ends up here, after bayer */ +struct stv680_frame { + unsigned char *data; /* Frame buffer */ + volatile int grabstate; /* State of grabbing */ + unsigned char *curline; + int curlinepix; + int curpix; +}; + +/* this is almost the video structure uvd_t, with extra parameters for stv */ +struct usb_stv { + struct video_device *vdev; + + struct usb_device *udev; + + unsigned char bulk_in_endpointAddr; /* __u8 the address of the bulk in endpoint */ + char *camera_name; + + unsigned int VideoMode; /* 0x0100 = VGA, 0x0000 = CIF, 0x0300 = QVGA */ + int SupportedModes; + int CIF; + int VGA; + int QVGA; + int cwidth; /* camera width */ + int cheight; /* camera height */ + int maxwidth; /* max video width */ + int maxheight; /* max video height */ + int vwidth; /* current width for video window */ + int vheight; /* current height for video window */ + unsigned long int rawbufsize; + unsigned long int maxframesize; /* rawbufsize * 3 for RGB */ + + int origGain; + int origMode; /* original camera mode */ + + struct mutex lock; /* to lock the structure */ + int user; /* user count for exclusive use */ + int removed; /* device disconnected */ + int streaming; /* Are we streaming video? */ + char *fbuf; /* Videodev buffer area */ + struct urb *urb[STV680_NUMSBUF]; /* # of queued bulk transfers */ + int curframe; /* Current receiving frame */ + struct stv680_frame frame[STV680_NUMFRAMES]; /* # frames supported by v4l part */ + int readcount; + int framecount; + int error; + int dropped; + int scratch_next; + int scratch_use; + int scratch_overflow; + struct stv680_scratch scratch[STV680_NUMSCRATCH]; /* for decoders */ + struct stv680_sbuf sbuf[STV680_NUMSBUF]; + + unsigned int brightness; + unsigned int chgbright; + unsigned int whiteness; + unsigned int colour; + unsigned int contrast; + unsigned int hue; + unsigned int palette; + unsigned int depth; /* rgb24 in bits */ + + wait_queue_head_t wq; /* Processes waiting */ + + int nullpackets; +}; + + +static const unsigned char red[256] = { + 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42, + 44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69, + 71, 71, 73, 75, 77, 78, 80, 81, 82, 84, 85, 87, + 88, 89, 90, 91, 93, 94, 95, 97, 98, 98, 99, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134, + 134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, + 143, 143, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151, + 152, 152, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159, + 159, 160, 161, 161, 161, 162, 163, 163, 164, 165, 165, 166, + 167, 167, 168, 168, 169, 170, 170, 170, 171, 171, 172, 173, + 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 179, 179, + 180, 180, 181, 181, 182, 183, 183, 184, 184, 185, 185, 186, + 187, 187, 188, 188, 188, 188, 189, 190, 190, 191, 191, 192, + 192, 193, 193, 194, 195, 195, 196, 196, 197, 197, 197, 197, + 198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 203, 204, + 204, 205, 205, 206, 206, 206, 206, 207, 207, 208, 208, 209, + 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, + 215, 215, 215, 216, 216, 217, 217, 218, 218, 218, 219, 219, + 220, 220, 221, 221 +}; + +static const unsigned char green[256] = { + 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47, + 50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77, + 79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97, + 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113, + 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, + 150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159, + 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168, + 169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177, + 177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185, + 186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, + 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200, + 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, + 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, + 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, + 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, + 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, + 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, + 239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244, + 245, 245, 246, 246 +}; + +static const unsigned char blue[256] = { + 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51, + 55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84, + 86, 88, 90, 92, 94, 95, 97, 100, 101, 103, 104, 106, + 107, 110, 111, 112, 114, 115, 116, 118, 119, 121, 122, 124, + 125, 126, 127, 128, 129, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163, + 165, 166, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, + 176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184, + 185, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, + 194, 195, 196, 196, 198, 199, 200, 200, 201, 202, 202, 203, + 204, 204, 205, 205, 206, 207, 207, 209, 210, 210, 211, 212, + 212, 213, 213, 214, 215, 215, 216, 217, 217, 218, 218, 220, + 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, + 228, 228, 229, 229, 231, 231, 232, 233, 233, 234, 234, 235, + 235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 242, 242, + 243, 243, 244, 244, 245, 246, 246, 247, 247, 248, 248, 249, + 249, 250, 250, 251, 251, 253, 253, 254, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255 +}; diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile new file mode 100644 index 000000000000..ed410a5ee8c9 --- /dev/null +++ b/drivers/media/video/usbvideo/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o +obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o +obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o + diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c new file mode 100644 index 000000000000..a42c22294124 --- /dev/null +++ b/drivers/media/video/usbvideo/ibmcam.c @@ -0,0 +1,3932 @@ +/* + * USB IBM C-It Video Camera driver + * + * Supports Xirlink C-It Video Camera, IBM PC Camera, + * IBM NetCamera and Veo Stingray. + * + * This driver is based on earlier work of: + * + * (C) Copyright 1999 Johannes Erdfelt + * (C) Copyright 1999 Randy Dunlap + * + * 5/24/00 Removed optional (and unnecessary) locking of the driver while + * the device remains plugged in. Corrected race conditions in ibmcam_open + * and ibmcam_probe() routines using this as a guideline: + */ + +#include +#include +#include +#include + +#include "usbvideo.h" + +#define IBMCAM_VENDOR_ID 0x0545 +#define IBMCAM_PRODUCT_ID 0x8080 +#define NETCAM_PRODUCT_ID 0x8002 /* IBM NetCamera, close to model 2 */ +#define VEO_800C_PRODUCT_ID 0x800C /* Veo Stingray, repackaged Model 2 */ +#define VEO_800D_PRODUCT_ID 0x800D /* Veo Stingray, repackaged Model 4 */ + +#define MAX_IBMCAM 4 /* How many devices we allow to connect */ +#define USES_IBMCAM_PUTPIXEL 0 /* 0=Fast/oops 1=Slow/secure */ + +/* Header signatures */ + +/* Model 1 header: 00 FF 00 xx */ +#define HDRSIG_MODEL1_128x96 0x06 /* U Y V Y ... */ +#define HDRSIG_MODEL1_176x144 0x0e /* U Y V Y ... */ +#define HDRSIG_MODEL1_352x288 0x00 /* V Y U Y ... */ + +#define IBMCAM_MODEL_1 1 /* XVP-501, 3 interfaces, rev. 0.02 */ +#define IBMCAM_MODEL_2 2 /* KSX-X9903, 2 interfaces, rev. 3.0a */ +#define IBMCAM_MODEL_3 3 /* KSX-X9902, 2 interfaces, rev. 3.01 */ +#define IBMCAM_MODEL_4 4 /* IBM NetCamera, 0545/8002/3.0a */ + +/* Video sizes supported */ +#define VIDEOSIZE_128x96 VIDEOSIZE(128, 96) +#define VIDEOSIZE_176x144 VIDEOSIZE(176,144) +#define VIDEOSIZE_352x288 VIDEOSIZE(352,288) +#define VIDEOSIZE_320x240 VIDEOSIZE(320,240) +#define VIDEOSIZE_352x240 VIDEOSIZE(352,240) +#define VIDEOSIZE_640x480 VIDEOSIZE(640,480) +#define VIDEOSIZE_160x120 VIDEOSIZE(160,120) + +/* Video sizes supported */ +enum { + SIZE_128x96 = 0, + SIZE_160x120, + SIZE_176x144, + SIZE_320x240, + SIZE_352x240, + SIZE_352x288, + SIZE_640x480, + /* Add/remove/rearrange items before this line */ + SIZE_LastItem +}; + +/* + * This structure lives in uvd->user field. + */ +typedef struct { + int initialized; /* Had we already sent init sequence? */ + int camera_model; /* What type of IBM camera we got? */ + int has_hdr; +} ibmcam_t; +#define IBMCAM_T(uvd) ((ibmcam_t *)((uvd)->user_data)) + +static struct usbvideo *cams; + +static int debug; + +static int flags; /* = FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ + +static const int min_canvasWidth = 8; +static const int min_canvasHeight = 4; + +static int lighting = 1; /* Medium */ + +#define SHARPNESS_MIN 0 +#define SHARPNESS_MAX 6 +static int sharpness = 4; /* Low noise, good details */ + +#define FRAMERATE_MIN 0 +#define FRAMERATE_MAX 6 +static int framerate = -1; + +static int size = SIZE_352x288; + +/* + * Here we define several initialization variables. They may + * be used to automatically set color, hue, brightness and + * contrast to desired values. This is particularly useful in + * case of webcams (which have no controls and no on-screen + * output) and also when a client V4L software is used that + * does not have some of those controls. In any case it's + * good to have startup values as options. + * + * These values are all in [0..255] range. This simplifies + * operation. Note that actual values of V4L variables may + * be scaled up (as much as << 8). User can see that only + * on overlay output, however, or through a V4L client. + */ +static int init_brightness = 128; +static int init_contrast = 192; +static int init_color = 128; +static int init_hue = 128; +static int hue_correction = 128; + +/* Settings for camera model 2 */ +static int init_model2_rg2 = -1; +static int init_model2_sat = -1; +static int init_model2_yb = -1; + +/* 01.01.08 - Added for RCA video in support -LO */ +/* Settings for camera model 3 */ +static int init_model3_input = 0; + +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); +module_param(flags, int, 0); +MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames"); +module_param(framerate, int, 0); +MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); +module_param(lighting, int, 0); +MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light"); +module_param(sharpness, int, 0); +MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)"); +module_param(size, int, 0); +MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480 (default=5)"); +module_param(init_brightness, int, 0); +MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); +module_param(init_contrast, int, 0); +MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); +module_param(init_color, int, 0); +MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)"); +module_param(init_hue, int, 0); +MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); +module_param(hue_correction, int, 0); +MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); + +module_param(init_model2_rg2, int, 0); +MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)"); +module_param(init_model2_sat, int, 0); +MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)"); +module_param(init_model2_yb, int, 0); +MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)"); + +/* 01.01.08 - Added for RCA video in support -LO */ +module_param(init_model3_input, int, 0); +MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA"); + +MODULE_AUTHOR ("Dmitri"); +MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000"); +MODULE_LICENSE("GPL"); + +/* Still mysterious i2c commands */ +static const unsigned short unknown_88 = 0x0088; +static const unsigned short unknown_89 = 0x0089; +static const unsigned short bright_3x[3] = { 0x0031, 0x0032, 0x0033 }; +static const unsigned short contrast_14 = 0x0014; +static const unsigned short light_27 = 0x0027; +static const unsigned short sharp_13 = 0x0013; + +/* i2c commands for Model 2 cameras */ +static const unsigned short mod2_brightness = 0x001a; /* $5b .. $ee; default=$5a */ +static const unsigned short mod2_set_framerate = 0x001c; /* 0 (fast).. $1F (slow) */ +static const unsigned short mod2_color_balance_rg2 = 0x001e; /* 0 (red) .. $7F (green) */ +static const unsigned short mod2_saturation = 0x0020; /* 0 (b/w) - $7F (full color) */ +static const unsigned short mod2_color_balance_yb = 0x0022; /* 0..$7F, $50 is about right */ +static const unsigned short mod2_hue = 0x0024; /* 0..$7F, $70 is about right */ +static const unsigned short mod2_sensitivity = 0x0028; /* 0 (min) .. $1F (max) */ + +struct struct_initData { + unsigned char req; + unsigned short value; + unsigned short index; +}; + +/* + * ibmcam_size_to_videosize() + * + * This procedure converts module option 'size' into the actual + * videosize_t that defines the image size in pixels. We need + * simplified 'size' because user wants a simple enumerated list + * of choices, not an infinite set of possibilities. + */ +static videosize_t ibmcam_size_to_videosize(int size) +{ + videosize_t vs = VIDEOSIZE_352x288; + RESTRICT_TO_RANGE(size, 0, (SIZE_LastItem-1)); + switch (size) { + case SIZE_128x96: + vs = VIDEOSIZE_128x96; + break; + case SIZE_160x120: + vs = VIDEOSIZE_160x120; + break; + case SIZE_176x144: + vs = VIDEOSIZE_176x144; + break; + case SIZE_320x240: + vs = VIDEOSIZE_320x240; + break; + case SIZE_352x240: + vs = VIDEOSIZE_352x240; + break; + case SIZE_352x288: + vs = VIDEOSIZE_352x288; + break; + case SIZE_640x480: + vs = VIDEOSIZE_640x480; + break; + default: + err("size=%d. is not valid", size); + break; + } + return vs; +} + +/* + * ibmcam_find_header() + * + * Locate one of supported header markers in the queue. + * Once found, remove all preceding bytes AND the marker (4 bytes) + * from the data pump queue. Whatever follows must be video lines. + * + * History: + * 1/21/00 Created. + */ +static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame here */ +{ + struct usbvideo_frame *frame; + ibmcam_t *icam; + + if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { + err("ibmcam_find_header: Illegal frame %d.", uvd->curframe); + return scan_EndParse; + } + icam = IBMCAM_T(uvd); + assert(icam != NULL); + frame = &uvd->frame[uvd->curframe]; + icam->has_hdr = 0; + switch (icam->camera_model) { + case IBMCAM_MODEL_1: + { + const int marker_len = 4; + while (RingQueue_GetLength(&uvd->dp) >= marker_len) { + if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) && + (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00)) + { +#if 0 /* This code helps to detect new frame markers */ + info("Header sig: 00 FF 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 3)); +#endif + frame->header = RING_QUEUE_PEEK(&uvd->dp, 3); + if ((frame->header == HDRSIG_MODEL1_128x96) || + (frame->header == HDRSIG_MODEL1_176x144) || + (frame->header == HDRSIG_MODEL1_352x288)) + { +#if 0 + info("Header found."); +#endif + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); + icam->has_hdr = 1; + break; + } + } + /* If we are still here then this doesn't look like a header */ + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); + } + break; + } + case IBMCAM_MODEL_2: +case IBMCAM_MODEL_4: + { + int marker_len = 0; + switch (uvd->videosize) { + case VIDEOSIZE_176x144: + marker_len = 10; + break; + default: + marker_len = 2; + break; + } + while (RingQueue_GetLength(&uvd->dp) >= marker_len) { + if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF)) + { +#if 0 + info("Header found."); +#endif + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); + icam->has_hdr = 1; + frame->header = HDRSIG_MODEL1_176x144; + break; + } + /* If we are still here then this doesn't look like a header */ + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); + } + break; + } + case IBMCAM_MODEL_3: + { /* + * Headers: (one precedes every frame). nc=no compression, + * bq=best quality bf=best frame rate. + * + * 176x144: 00 FF 02 { 0A=nc CA=bq EA=bf } + * 320x240: 00 FF 02 { 08=nc 28=bq 68=bf } + * 640x480: 00 FF 03 { 08=nc 28=bq 68=bf } + * + * Bytes '00 FF' seem to indicate header. Other two bytes + * encode the frame type. This is a set of bit fields that + * encode image size, compression type etc. These fields + * do NOT contain frame number because all frames carry + * the same header. + */ + const int marker_len = 4; + while (RingQueue_GetLength(&uvd->dp) >= marker_len) { + if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) && + (RING_QUEUE_PEEK(&uvd->dp, 2) != 0xFF)) + { + /* + * Combine 2 bytes of frame type into one + * easy to use value + */ + unsigned long byte3, byte4; + + byte3 = RING_QUEUE_PEEK(&uvd->dp, 2); + byte4 = RING_QUEUE_PEEK(&uvd->dp, 3); + frame->header = (byte3 << 8) | byte4; +#if 0 + info("Header found."); +#endif + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); + icam->has_hdr = 1; + break; + } + /* If we are still here then this doesn't look like a header */ + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); + } + break; + } + default: + break; + } + if (!icam->has_hdr) { + if (uvd->debug > 2) + info("Skipping frame, no header"); + return scan_EndParse; + } + + /* Header found */ + icam->has_hdr = 1; + uvd->stats.header_count++; + frame->scanstate = ScanState_Lines; + frame->curline = 0; + + if (flags & FLAGS_FORCE_TESTPATTERN) { + usbvideo_TestPattern(uvd, 1, 1); + return scan_NextFrame; + } + return scan_Continue; +} + +/* + * ibmcam_parse_lines() + * + * Parse one line (interlaced) from the buffer, put + * decoded RGB value into the current frame buffer + * and add the written number of bytes (RGB) to + * the *pcopylen. + * + * History: + * 21-Jan-2000 Created. + * 12-Oct-2000 Reworked to reflect interlaced nature of the data. + */ +static enum ParseState ibmcam_parse_lines( + struct uvd *uvd, + struct usbvideo_frame *frame, + long *pcopylen) +{ + unsigned char *f; + ibmcam_t *icam; + unsigned int len, scanLength, scanHeight, order_uv, order_yc; + int v4l_linesize; /* V4L line offset */ + const int hue_corr = (uvd->vpic.hue - 0x8000) >> 10; /* -32..+31 */ + const int hue2_corr = (hue_correction - 128) / 4; /* -32..+31 */ + const int ccm = 128; /* Color correction median - see below */ + int y, u, v, i, frame_done=0, color_corr; + static unsigned char lineBuffer[640*3]; + unsigned const char *chromaLine, *lumaLine; + + assert(uvd != NULL); + assert(frame != NULL); + icam = IBMCAM_T(uvd); + assert(icam != NULL); + color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ + RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1); + + v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; + + if (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_4) { + /* Model 4 frame markers do not carry image size identification */ + switch (uvd->videosize) { + case VIDEOSIZE_128x96: + case VIDEOSIZE_160x120: + case VIDEOSIZE_176x144: + scanLength = VIDEOSIZE_X(uvd->videosize); + scanHeight = VIDEOSIZE_Y(uvd->videosize); + break; + default: + err("ibmcam_parse_lines: Wrong mode."); + return scan_Out; + } + order_yc = 1; /* order_yc: true=Yc false=cY ('c'=either U or V) */ + order_uv = 1; /* Always true in this algorithm */ + } else { + switch (frame->header) { + case HDRSIG_MODEL1_128x96: + scanLength = 128; + scanHeight = 96; + order_uv = 1; /* U Y V Y ... */ + break; + case HDRSIG_MODEL1_176x144: + scanLength = 176; + scanHeight = 144; + order_uv = 1; /* U Y V Y ... */ + break; + case HDRSIG_MODEL1_352x288: + scanLength = 352; + scanHeight = 288; + order_uv = 0; /* Y V Y V ... */ + break; + default: + err("Unknown header signature 00 FF 00 %02lX", frame->header); + return scan_NextFrame; + } + /* order_yc: true=Yc false=cY ('c'=either U or V) */ + order_yc = (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_2); + } + + len = scanLength * 3; + assert(len <= sizeof(lineBuffer)); + + /* + * Lines are organized this way: + * + * I420: + * ~~~~ + * + * ___________________________________ + * |-----Y-----|---UVUVUV...UVUV-----| \ + * |-----------+---------------------| \ + * |<-- 176 -->|<------ 176*2 ------>| Total 72. lines (interlaced) + * |... ... | ... | / + * |<-- 352 -->|<------ 352*2 ------>| Total 144. lines (interlaced) + * |___________|_____________________| / + * \ \ + * lumaLine chromaLine + */ + + /* Make sure there's enough data for the entire line */ + if (RingQueue_GetLength(&uvd->dp) < len) + return scan_Out; + + /* Suck one line out of the ring queue */ + RingQueue_Dequeue(&uvd->dp, lineBuffer, len); + + /* + * Make sure that our writing into output buffer + * will not exceed the buffer. Mind that we may write + * not into current output scanline but in several after + * it as well (if we enlarge image vertically.) + */ + if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request)) + return scan_NextFrame; + + /* + * Now we are sure that entire line (representing all 'scanLength' + * pixels from the camera) is available in the buffer. We + * start copying the line left-aligned to the V4L buffer. + * If the camera line is shorter then we should pad the V4L + * buffer with something (black) to complete the line. + */ + assert(frame->data != NULL); + f = frame->data + (v4l_linesize * frame->curline); + + /* + * To obtain chrominance data from the 'chromaLine' use this: + * v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]... + * u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]... + * + * Indices must be calculated this way: + * v_index = (i >> 1) << 2; + * u_index = (i >> 1) << 2 + 2; + * + * where 'i' is the column number [0..VIDEOSIZE_X(frame->request)-1] + */ + lumaLine = lineBuffer; + chromaLine = lineBuffer + scanLength; + for (i = 0; i < VIDEOSIZE_X(frame->request); i++) + { + unsigned char rv, gv, bv; /* RGB components */ + + /* Check for various visual debugging hints (colorized pixels) */ + if ((flags & FLAGS_DISPLAY_HINTS) && (icam->has_hdr)) { + /* + * This is bad and should not happen. This means that + * we somehow overshoot the line and encountered new + * frame! Obviously our camera/V4L frame size is out + * of whack. This cyan dot will help you to figure + * out where exactly the new frame arrived. + */ + if (icam->has_hdr == 1) { + bv = 0; /* Yellow marker */ + gv = 0xFF; + rv = 0xFF; + } else { + bv = 0xFF; /* Cyan marker */ + gv = 0xFF; + rv = 0; + } + icam->has_hdr = 0; + goto make_pixel; + } + + /* + * Check if we are still in range. We may be out of range if our + * V4L canvas is wider or taller than the camera "native" image. + * Then we quickly fill the remainder of the line with zeros to + * make black color and quit the horizontal scanning loop. + */ + if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) { + const int j = i * V4L_BYTES_PER_PIXEL; +#if USES_IBMCAM_PUTPIXEL + /* Refresh 'f' because we don't use it much with PUTPIXEL */ + f = frame->data + (v4l_linesize * frame->curline) + j; +#endif + memset(f, 0, v4l_linesize - j); + break; + } + + y = lumaLine[i]; + if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */ + rv = gv = bv = y; + else { + int off_0, off_2; + + off_0 = (i >> 1) << 2; + off_2 = off_0 + 2; + + if (order_yc) { + off_0++; + off_2++; + } + if (!order_uv) { + off_0 += 2; + off_2 -= 2; + } + u = chromaLine[off_0] + hue_corr; + v = chromaLine[off_2] + hue2_corr; + + /* Apply color correction */ + if (color_corr != 0) { + /* Magnify up to 2 times, reduce down to zero saturation */ + u = 128 + ((ccm + color_corr) * (u - 128)) / ccm; + v = 128 + ((ccm + color_corr) * (v - 128)) / ccm; + } + YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); + } + + make_pixel: + /* + * The purpose of creating the pixel here, in one, + * dedicated place is that we may need to make the + * pixel wider and taller than it actually is. This + * may be used if camera generates small frames for + * sake of frame rate (or any other reason.) + * + * The output data consists of B, G, R bytes + * (in this order). + */ +#if USES_IBMCAM_PUTPIXEL + RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); +#else + *f++ = bv; + *f++ = gv; + *f++ = rv; +#endif + /* + * Typically we do not decide within a legitimate frame + * that we want to end the frame. However debugging code + * may detect marker of new frame within the data. Then + * this condition activates. The 'data' pointer is already + * pointing at the new marker, so we'd better leave it as is. + */ + if (frame_done) + break; /* End scanning of lines */ + } + /* + * Account for number of bytes that we wrote into output V4L frame. + * We do it here, after we are done with the scanline, because we + * may fill more than one output scanline if we do vertical + * enlargement. + */ + frame->curline += 2; + if (pcopylen != NULL) + *pcopylen += 2 * v4l_linesize; + frame->deinterlace = Deinterlace_FillOddLines; + + if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request))) + return scan_NextFrame; + else + return scan_Continue; +} + +/* + * ibmcam_model2_320x240_parse_lines() + * + * This procedure deals with a weird RGB format that is produced by IBM + * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175, + * depending on horizontal size of the picture: + * + * <--- 160 or 176 pairs of RA,RB bytes -----> + * *-----------------------------------------* \ + * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx | \ This is pair of horizontal lines, + * |-----+-----+-----+-----+ ... +-----+-----| *- or one interlaced line, total + * | B0 | G0 | B1 | G1 | ... | Bx | Gx | / 120 or 144 such pairs which yield + * |=====+=====+=====+=====+ ... +=====+=====| / 240 or 288 lines after deinterlacing. + * + * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1 + * defines ONE pixel. Therefore this format yields 176x144 "decoded" + * resolution at best. I do not know why camera sends such format - the + * previous model (1) just used interlaced I420 and everyone was happy. + * + * I do not know what is the difference between RAi and RBi bytes. Both + * seemingly represent R component, but slightly vary in value (so that + * the picture looks a bit colored if one or another is used). I use + * them both as R component in attempt to at least partially recover the + * lost resolution. + */ +static enum ParseState ibmcam_model2_320x240_parse_lines( + struct uvd *uvd, + struct usbvideo_frame *frame, + long *pcopylen) +{ + unsigned char *f, *la, *lb; + unsigned int len; + int v4l_linesize; /* V4L line offset */ + int i, j, frame_done=0, color_corr; + int scanLength, scanHeight; + static unsigned char lineBuffer[352*2]; + + switch (uvd->videosize) { + case VIDEOSIZE_320x240: + case VIDEOSIZE_352x240: + case VIDEOSIZE_352x288: + scanLength = VIDEOSIZE_X(uvd->videosize); + scanHeight = VIDEOSIZE_Y(uvd->videosize); + break; + default: + err("ibmcam_model2_320x240_parse_lines: Wrong mode."); + return scan_Out; + } + + color_corr = (uvd->vpic.colour) >> 8; /* 0..+255 */ + v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; + + len = scanLength * 2; /* See explanation above */ + assert(len <= sizeof(lineBuffer)); + + /* Make sure there's enough data for the entire line */ + if (RingQueue_GetLength(&uvd->dp) < len) + return scan_Out; + + /* Suck one line out of the ring queue */ + RingQueue_Dequeue(&uvd->dp, lineBuffer, len); + + /* + * Make sure that our writing into output buffer + * will not exceed the buffer. Mind that we may write + * not into current output scanline but in several after + * it as well (if we enlarge image vertically.) + */ + if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request)) + return scan_NextFrame; + + la = lineBuffer; + lb = lineBuffer + scanLength; + + /* + * Now we are sure that entire line (representing all + * VIDEOSIZE_X(frame->request) + * pixels from the camera) is available in the scratch buffer. We + * start copying the line left-aligned to the V4L buffer (which + * might be larger - not smaller, hopefully). If the camera + * line is shorter then we should pad the V4L buffer with something + * (black in this case) to complete the line. + */ + f = frame->data + (v4l_linesize * frame->curline); + + /* Fill the 2-line strip */ + for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { + int y, rv, gv, bv; /* RGB components */ + + j = i & (~1); + + /* Check for various visual debugging hints (colorized pixels) */ + if ((flags & FLAGS_DISPLAY_HINTS) && (IBMCAM_T(uvd)->has_hdr)) { + if (IBMCAM_T(uvd)->has_hdr == 1) { + bv = 0; /* Yellow marker */ + gv = 0xFF; + rv = 0xFF; + } else { + bv = 0xFF; /* Cyan marker */ + gv = 0xFF; + rv = 0; + } + IBMCAM_T(uvd)->has_hdr = 0; + goto make_pixel; + } + + /* + * Check if we are still in range. We may be out of range if our + * V4L canvas is wider or taller than the camera "native" image. + * Then we quickly fill the remainder of the line with zeros to + * make black color and quit the horizontal scanning loop. + */ + if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) { + const int j = i * V4L_BYTES_PER_PIXEL; +#if USES_IBMCAM_PUTPIXEL + /* Refresh 'f' because we don't use it much with PUTPIXEL */ + f = frame->data + (v4l_linesize * frame->curline) + j; +#endif + memset(f, 0, v4l_linesize - j); + break; + } + + /* + * Here I use RA and RB components, one per physical pixel. + * This causes fine vertical grid on the picture but may improve + * horizontal resolution. If you prefer replicating, use this: + * rv = la[j + 0]; ... or ... rv = la[j + 1]; + * then the pixel will be replicated. + */ + rv = la[i]; + gv = lb[j + 1]; + bv = lb[j + 0]; + + y = (rv + gv + bv) / 3; /* Brightness (badly calculated) */ + + if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */ + rv = gv = bv = y; + else if (color_corr != 128) { + + /* Calculate difference between color and brightness */ + rv -= y; + gv -= y; + bv -= y; + + /* Scale differences */ + rv = (rv * color_corr) / 128; + gv = (gv * color_corr) / 128; + bv = (bv * color_corr) / 128; + + /* Reapply brightness */ + rv += y; + gv += y; + bv += y; + + /* Watch for overflows */ + RESTRICT_TO_RANGE(rv, 0, 255); + RESTRICT_TO_RANGE(gv, 0, 255); + RESTRICT_TO_RANGE(bv, 0, 255); + } + + make_pixel: + RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); + } + /* + * Account for number of bytes that we wrote into output V4L frame. + * We do it here, after we are done with the scanline, because we + * may fill more than one output scanline if we do vertical + * enlargement. + */ + frame->curline += 2; + *pcopylen += v4l_linesize * 2; + frame->deinterlace = Deinterlace_FillOddLines; + + if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request))) + return scan_NextFrame; + else + return scan_Continue; +} + +static enum ParseState ibmcam_model3_parse_lines( + struct uvd *uvd, + struct usbvideo_frame *frame, + long *pcopylen) +{ + unsigned char *data; + const unsigned char *color; + unsigned int len; + int v4l_linesize; /* V4L line offset */ + const int hue_corr = (uvd->vpic.hue - 0x8000) >> 10; /* -32..+31 */ + const int hue2_corr = (hue_correction - 128) / 4; /* -32..+31 */ + const int ccm = 128; /* Color correction median - see below */ + int i, u, v, rw, data_w=0, data_h=0, color_corr; + static unsigned char lineBuffer[640*3]; + + color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ + RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1); + + v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; + + /* The header tells us what sort of data is in this frame */ + switch (frame->header) { + /* + * Uncompressed modes (that are easy to decode). + */ + case 0x0308: + data_w = 640; + data_h = 480; + break; + case 0x0208: + data_w = 320; + data_h = 240; + break; + case 0x020A: + data_w = 160; + data_h = 120; + break; + /* + * Compressed modes (ViCE - that I don't know how to decode). + */ + case 0x0328: /* 640x480, best quality compression */ + case 0x0368: /* 640x480, best frame rate compression */ + case 0x0228: /* 320x240, best quality compression */ + case 0x0268: /* 320x240, best frame rate compression */ + case 0x02CA: /* 160x120, best quality compression */ + case 0x02EA: /* 160x120, best frame rate compression */ + /* Do nothing with this - not supported */ + err("Unsupported mode $%04lx", frame->header); + return scan_NextFrame; + default: + /* Catch unknown headers, may help in learning new headers */ + err("Strange frame->header=$%08lx", frame->header); + return scan_NextFrame; + } + + /* + * Make sure that our writing into output buffer + * will not exceed the buffer. Note that we may write + * not into current output scanline but in several after + * it as well (if we enlarge image vertically.) + */ + if ((frame->curline + 1) >= data_h) { + if (uvd->debug >= 3) + info("Reached line %d. (frame is done)", frame->curline); + return scan_NextFrame; + } + + /* Make sure there's enough data for the entire line */ + len = 3 * data_w; /* */ + assert(len <= sizeof(lineBuffer)); + + /* Make sure there's enough data for the entire line */ + if (RingQueue_GetLength(&uvd->dp) < len) + return scan_Out; + + /* Suck one line out of the ring queue */ + RingQueue_Dequeue(&uvd->dp, lineBuffer, len); + + data = lineBuffer; + color = data + data_w; /* Point to where color planes begin */ + + /* Bottom-to-top scanning */ + rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1; + RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1); + + for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { + int y, rv, gv, bv; /* RGB components */ + + if (i < data_w) { + y = data[i]; /* Luminosity is the first line */ + + /* Apply static color correction */ + u = color[i*2] + hue_corr; + v = color[i*2 + 1] + hue2_corr; + + /* Apply color correction */ + if (color_corr != 0) { + /* Magnify up to 2 times, reduce down to zero saturation */ + u = 128 + ((ccm + color_corr) * (u - 128)) / ccm; + v = 128 + ((ccm + color_corr) * (v - 128)) / ccm; + } + } else + y = 0, u = v = 128; + + YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); + RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */ + } + frame->deinterlace = Deinterlace_FillEvenLines; + + /* + * Account for number of bytes that we wrote into output V4L frame. + * We do it here, after we are done with the scanline, because we + * may fill more than one output scanline if we do vertical + * enlargement. + */ + frame->curline += 2; + *pcopylen += 2 * v4l_linesize; + + if (frame->curline >= VIDEOSIZE_Y(frame->request)) { + if (uvd->debug >= 3) { + info("All requested lines (%ld.) done.", + VIDEOSIZE_Y(frame->request)); + } + return scan_NextFrame; + } else + return scan_Continue; +} + +/* + * ibmcam_model4_128x96_parse_lines() + * + * This decoder is for one strange data format that is produced by Model 4 + * camera only in 128x96 mode. This is RGB format and here is its description. + * First of all, this is non-interlaced stream, meaning that all scan lines + * are present in the datastream. There are 96 consecutive blocks of data + * that describe all 96 lines of the image. Each block is 5*128 bytes long + * and carries R, G, B components. The format of the block is shown in the + * code below. First 128*2 bytes are interleaved R and G components. Then + * we have a gap (junk data) 64 bytes long. Then follow B and something + * else, also interleaved (this makes another 128*2 bytes). After that + * probably another 64 bytes of junk follow. + * + * History: + * 10-Feb-2001 Created. + */ +static enum ParseState ibmcam_model4_128x96_parse_lines( + struct uvd *uvd, + struct usbvideo_frame *frame, + long *pcopylen) +{ + const unsigned char *data_rv, *data_gv, *data_bv; + unsigned int len; + int i, v4l_linesize; /* V4L line offset */ + const int data_w=128, data_h=96; + static unsigned char lineBuffer[128*5]; + + v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; + + /* + * Make sure that our writing into output buffer + * will not exceed the buffer. Note that we may write + * not into current output scanline but in several after + * it as well (if we enlarge image vertically.) + */ + if ((frame->curline + 1) >= data_h) { + if (uvd->debug >= 3) + info("Reached line %d. (frame is done)", frame->curline); + return scan_NextFrame; + } + + /* + * RGRGRG .... RGRG_____________B?B?B? ... B?B?____________ + * <---- 128*2 ---><---- 64 ---><--- 128*2 ---><--- 64 ---> + */ + + /* Make sure there's enough data for the entire line */ + len = 5 * data_w; + assert(len <= sizeof(lineBuffer)); + + /* Make sure there's enough data for the entire line */ + if (RingQueue_GetLength(&uvd->dp) < len) + return scan_Out; + + /* Suck one line out of the ring queue */ + RingQueue_Dequeue(&uvd->dp, lineBuffer, len); + + data_rv = lineBuffer; + data_gv = lineBuffer + 1; + data_bv = lineBuffer + data_w*2 + data_w/2; + for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { + int rv, gv, bv; /* RGB components */ + if (i < data_w) { + const int j = i * 2; + gv = data_rv[j]; + rv = data_gv[j]; + bv = data_bv[j]; + if (flags & FLAGS_MONOCHROME) { + unsigned long y; + y = rv + gv + bv; + y /= 3; + if (y > 0xFF) + y = 0xFF; + rv = gv = bv = (unsigned char) y; + } + } else { + rv = gv = bv = 0; + } + RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); + } + frame->deinterlace = Deinterlace_None; + frame->curline++; + *pcopylen += v4l_linesize; + + if (frame->curline >= VIDEOSIZE_Y(frame->request)) { + if (uvd->debug >= 3) { + info("All requested lines (%ld.) done.", + VIDEOSIZE_Y(frame->request)); + } + return scan_NextFrame; + } else + return scan_Continue; +} + +/* + * ibmcam_ProcessIsocData() + * + * Generic routine to parse the ring queue data. It employs either + * ibmcam_find_header() or ibmcam_parse_lines() to do most + * of work. + * + * History: + * 1/21/00 Created. + */ +static void ibmcam_ProcessIsocData(struct uvd *uvd, + struct usbvideo_frame *frame) +{ + enum ParseState newstate; + long copylen = 0; + int mod = IBMCAM_T(uvd)->camera_model; + + while (1) { + newstate = scan_Out; + if (RingQueue_GetLength(&uvd->dp) > 0) { + if (frame->scanstate == ScanState_Scanning) { + newstate = ibmcam_find_header(uvd); + } else if (frame->scanstate == ScanState_Lines) { + if ((mod == IBMCAM_MODEL_2) && + ((uvd->videosize == VIDEOSIZE_352x288) || + (uvd->videosize == VIDEOSIZE_320x240) || + (uvd->videosize == VIDEOSIZE_352x240))) + { + newstate = ibmcam_model2_320x240_parse_lines( + uvd, frame, ©len); + } else if (mod == IBMCAM_MODEL_4) { + /* + * Model 4 cameras (IBM NetCamera) use Model 2 decoder (RGB) + * for 320x240 and above; 160x120 and 176x144 uses Model 1 + * decoder (YUV), and 128x96 mode uses ??? + */ + if ((uvd->videosize == VIDEOSIZE_352x288) || + (uvd->videosize == VIDEOSIZE_320x240) || + (uvd->videosize == VIDEOSIZE_352x240)) + { + newstate = ibmcam_model2_320x240_parse_lines(uvd, frame, ©len); + } else if (uvd->videosize == VIDEOSIZE_128x96) { + newstate = ibmcam_model4_128x96_parse_lines(uvd, frame, ©len); + } else { + newstate = ibmcam_parse_lines(uvd, frame, ©len); + } + } else if (mod == IBMCAM_MODEL_3) { + newstate = ibmcam_model3_parse_lines(uvd, frame, ©len); + } else { + newstate = ibmcam_parse_lines(uvd, frame, ©len); + } + } + } + if (newstate == scan_Continue) + continue; + else if ((newstate == scan_NextFrame) || (newstate == scan_Out)) + break; + else + return; /* scan_EndParse */ + } + + if (newstate == scan_NextFrame) { + frame->frameState = FrameState_Done; + uvd->curframe = -1; + uvd->stats.frame_num++; + if ((mod == IBMCAM_MODEL_2) || (mod == IBMCAM_MODEL_4)) { + /* Need software contrast adjustment for those cameras */ + frame->flags |= USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST; + } + } + + /* Update the frame's uncompressed length. */ + frame->seqRead_Length += copylen; + +#if 0 + { + static unsigned char j=0; + memset(frame->data, j++, uvd->max_frame_size); + frame->frameState = FrameState_Ready; + } +#endif +} + +/* + * ibmcam_veio() + * + * History: + * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. + */ +static int ibmcam_veio( + struct uvd *uvd, + unsigned char req, + unsigned short value, + unsigned short index) +{ + static const char proc[] = "ibmcam_veio"; + unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */; + int i; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return 0; + + if (req == 1) { + i = usb_control_msg( + uvd->dev, + usb_rcvctrlpipe(uvd->dev, 0), + req, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, + value, + index, + cp, + sizeof(cp), + 1000); +#if 0 + info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " + "(req=$%02x val=$%04x ind=$%04x)", + cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], + req, value, index); +#endif + } else { + i = usb_control_msg( + uvd->dev, + usb_sndctrlpipe(uvd->dev, 0), + req, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, + value, + index, + NULL, + 0, + 1000); + } + if (i < 0) { + err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.", + proc, i); + uvd->last_error = i; + } + return i; +} + +/* + * ibmcam_calculate_fps() + * + * This procedure roughly calculates the real frame rate based + * on FPS code (framerate=NNN option). Actual FPS differs + * slightly depending on lighting conditions, so that actual frame + * rate is determined by the camera. Since I don't know how to ask + * the camera what FPS is now I have to use the FPS code instead. + * + * The FPS code is in range [0..6], 0 is slowest, 6 is fastest. + * Corresponding real FPS should be in range [3..30] frames per second. + * The conversion formula is obvious: + * + * real_fps = 3 + (fps_code * 4.5) + * + * History: + * 1/18/00 Created. + */ +static int ibmcam_calculate_fps(struct uvd *uvd) +{ + return 3 + framerate*4 + framerate/2; +} + +/* + * ibmcam_send_FF_04_02() + * + * This procedure sends magic 3-command prefix to the camera. + * The purpose of this prefix is not known. + * + * History: + * 1/2/00 Created. + */ +static void ibmcam_send_FF_04_02(struct uvd *uvd) +{ + ibmcam_veio(uvd, 0, 0x00FF, 0x0127); + ibmcam_veio(uvd, 0, 0x0004, 0x0124); + ibmcam_veio(uvd, 0, 0x0002, 0x0124); +} + +static void ibmcam_send_00_04_06(struct uvd *uvd) +{ + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0x0004, 0x0124); + ibmcam_veio(uvd, 0, 0x0006, 0x0124); +} + +static void ibmcam_send_x_00(struct uvd *uvd, unsigned short x) +{ + ibmcam_veio(uvd, 0, x, 0x0127); + ibmcam_veio(uvd, 0, 0x0000, 0x0124); +} + +static void ibmcam_send_x_00_05(struct uvd *uvd, unsigned short x) +{ + ibmcam_send_x_00(uvd, x); + ibmcam_veio(uvd, 0, 0x0005, 0x0124); +} + +static void ibmcam_send_x_00_05_02(struct uvd *uvd, unsigned short x) +{ + ibmcam_veio(uvd, 0, x, 0x0127); + ibmcam_veio(uvd, 0, 0x0000, 0x0124); + ibmcam_veio(uvd, 0, 0x0005, 0x0124); + ibmcam_veio(uvd, 0, 0x0002, 0x0124); +} + +static void ibmcam_send_x_01_00_05(struct uvd *uvd, unsigned short x) +{ + ibmcam_veio(uvd, 0, x, 0x0127); + ibmcam_veio(uvd, 0, 0x0001, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0124); + ibmcam_veio(uvd, 0, 0x0005, 0x0124); +} + +static void ibmcam_send_x_00_05_02_01(struct uvd *uvd, unsigned short x) +{ + ibmcam_veio(uvd, 0, x, 0x0127); + ibmcam_veio(uvd, 0, 0x0000, 0x0124); + ibmcam_veio(uvd, 0, 0x0005, 0x0124); + ibmcam_veio(uvd, 0, 0x0002, 0x0124); + ibmcam_veio(uvd, 0, 0x0001, 0x0124); +} + +static void ibmcam_send_x_00_05_02_08_01(struct uvd *uvd, unsigned short x) +{ + ibmcam_veio(uvd, 0, x, 0x0127); + ibmcam_veio(uvd, 0, 0x0000, 0x0124); + ibmcam_veio(uvd, 0, 0x0005, 0x0124); + ibmcam_veio(uvd, 0, 0x0002, 0x0124); + ibmcam_veio(uvd, 0, 0x0008, 0x0124); + ibmcam_veio(uvd, 0, 0x0001, 0x0124); +} + +static void ibmcam_Packet_Format1(struct uvd *uvd, unsigned char fkey, unsigned char val) +{ + ibmcam_send_x_01_00_05(uvd, unknown_88); + ibmcam_send_x_00_05(uvd, fkey); + ibmcam_send_x_00_05_02_08_01(uvd, val); + ibmcam_send_x_00_05(uvd, unknown_88); + ibmcam_send_x_00_05_02_01(uvd, fkey); + ibmcam_send_x_00_05(uvd, unknown_89); + ibmcam_send_x_00(uvd, fkey); + ibmcam_send_00_04_06(uvd); + ibmcam_veio(uvd, 1, 0x0000, 0x0126); + ibmcam_send_FF_04_02(uvd); +} + +static void ibmcam_PacketFormat2(struct uvd *uvd, unsigned char fkey, unsigned char val) +{ + ibmcam_send_x_01_00_05 (uvd, unknown_88); + ibmcam_send_x_00_05 (uvd, fkey); + ibmcam_send_x_00_05_02 (uvd, val); +} + +static void ibmcam_model2_Packet2(struct uvd *uvd) +{ + ibmcam_veio(uvd, 0, 0x00ff, 0x012d); + ibmcam_veio(uvd, 0, 0xfea3, 0x0124); +} + +static void ibmcam_model2_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2) +{ + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x00ff, 0x012e); + ibmcam_veio(uvd, 0, v1, 0x012f); + ibmcam_veio(uvd, 0, 0x00ff, 0x0130); + ibmcam_veio(uvd, 0, 0xc719, 0x0124); + ibmcam_veio(uvd, 0, v2, 0x0127); + + ibmcam_model2_Packet2(uvd); +} + +/* + * ibmcam_model3_Packet1() + * + * 00_0078_012d + * 00_0097_012f + * 00_d141_0124 + * 00_0096_0127 + * 00_fea8_0124 +*/ +static void ibmcam_model3_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2) +{ + ibmcam_veio(uvd, 0, 0x0078, 0x012d); + ibmcam_veio(uvd, 0, v1, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, v2, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); +} + +static void ibmcam_model4_BrightnessPacket(struct uvd *uvd, int i) +{ + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0026, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, i, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x0038, 0x012d); + ibmcam_veio(uvd, 0, 0x0004, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0xfffa, 0x0124); +} + +/* + * ibmcam_adjust_contrast() + * + * The contrast value changes from 0 (high contrast) to 15 (low contrast). + * This is in reverse to usual order of things (such as TV controls), so + * we reverse it again here. + * + * TODO: we probably don't need to send the setup 5 times... + * + * History: + * 1/2/00 Created. + */ +static void ibmcam_adjust_contrast(struct uvd *uvd) +{ + unsigned char a_contrast = uvd->vpic.contrast >> 12; + unsigned char new_contrast; + + if (a_contrast >= 16) + a_contrast = 15; + new_contrast = 15 - a_contrast; + if (new_contrast == uvd->vpic_old.contrast) + return; + uvd->vpic_old.contrast = new_contrast; + switch (IBMCAM_T(uvd)->camera_model) { + case IBMCAM_MODEL_1: + { + const int ntries = 5; + int i; + for (i=0; i < ntries; i++) { + ibmcam_Packet_Format1(uvd, contrast_14, new_contrast); + ibmcam_send_FF_04_02(uvd); + } + break; + } + case IBMCAM_MODEL_2: + case IBMCAM_MODEL_4: + /* Models 2, 4 do not have this control; implemented in software. */ + break; + case IBMCAM_MODEL_3: + { /* Preset hardware values */ + static const struct { + unsigned short cv1; + unsigned short cv2; + unsigned short cv3; + } cv[7] = { + { 0x05, 0x05, 0x0f }, /* Minimum */ + { 0x04, 0x04, 0x16 }, + { 0x02, 0x03, 0x16 }, + { 0x02, 0x08, 0x16 }, + { 0x01, 0x0c, 0x16 }, + { 0x01, 0x0e, 0x16 }, + { 0x01, 0x10, 0x16 } /* Maximum */ + }; + int i = a_contrast / 2; + RESTRICT_TO_RANGE(i, 0, 6); + ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ + ibmcam_model3_Packet1(uvd, 0x0067, cv[i].cv1); + ibmcam_model3_Packet1(uvd, 0x005b, cv[i].cv2); + ibmcam_model3_Packet1(uvd, 0x005c, cv[i].cv3); + ibmcam_veio(uvd, 0, 0x0001, 0x0114); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ + usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); + break; + } + default: + break; + } +} + +/* + * ibmcam_change_lighting_conditions() + * + * Camera model 1: + * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low. + * + * Camera model 2: + * We have 16 levels of lighting, 0 for bright light and up to 15 for + * low light. But values above 5 or so are useless because camera is + * not really capable to produce anything worth viewing at such light. + * This setting may be altered only in certain camera state. + * + * Low lighting forces slower FPS. Lighting is set as a module parameter. + * + * History: + * 1/5/00 Created. + * 2/20/00 Added support for Model 2 cameras. + */ +static void ibmcam_change_lighting_conditions(struct uvd *uvd) +{ + static const char proc[] = "ibmcam_change_lighting_conditions"; + + if (debug > 0) + info("%s: Set lighting to %hu.", proc, lighting); + + switch (IBMCAM_T(uvd)->camera_model) { + case IBMCAM_MODEL_1: + { + const int ntries = 5; + int i; + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, light_27, (unsigned short) lighting); + break; + } + case IBMCAM_MODEL_2: +#if 0 + /* + * This command apparently requires camera to be stopped. My + * experiments showed that it -is- possible to alter the lighting + * conditions setting "on the fly", but why bother? This setting does + * not work reliably in all cases, so I decided simply to leave the + * setting where Xirlink put it - in the camera setup phase. This code + * is commented out because it does not work at -any- moment, so its + * presence makes no sense. You may use it for experiments. + */ + ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop camera */ + ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Start camera */ +#endif + break; + case IBMCAM_MODEL_3: + case IBMCAM_MODEL_4: + default: + break; + } +} + +/* + * ibmcam_set_sharpness() + * + * Cameras model 1 have internal smoothing feature. It is controlled by value in + * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess). + * Recommended value is 4. Cameras model 2 do not have this feature at all. + */ +static void ibmcam_set_sharpness(struct uvd *uvd) +{ + static const char proc[] = "ibmcam_set_sharpness"; + + switch (IBMCAM_T(uvd)->camera_model) { + case IBMCAM_MODEL_1: + { + static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a }; + unsigned short i, sv; + + RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); + if (debug > 0) + info("%s: Set sharpness to %hu.", proc, sharpness); + + sv = sa[sharpness - SHARPNESS_MIN]; + for (i=0; i < 2; i++) { + ibmcam_send_x_01_00_05 (uvd, unknown_88); + ibmcam_send_x_00_05 (uvd, sharp_13); + ibmcam_send_x_00_05_02 (uvd, sv); + } + break; + } + case IBMCAM_MODEL_2: + case IBMCAM_MODEL_4: + /* Models 2, 4 do not have this control */ + break; + case IBMCAM_MODEL_3: + { /* + * "Use a table of magic numbers. + * This setting doesn't really change much. + * But that's how Windows does it." + */ + static const struct { + unsigned short sv1; + unsigned short sv2; + unsigned short sv3; + unsigned short sv4; + } sv[7] = { + { 0x00, 0x00, 0x05, 0x14 }, /* Smoothest */ + { 0x01, 0x04, 0x05, 0x14 }, + { 0x02, 0x04, 0x05, 0x14 }, + { 0x03, 0x04, 0x05, 0x14 }, + { 0x03, 0x05, 0x05, 0x14 }, + { 0x03, 0x06, 0x05, 0x14 }, + { 0x03, 0x07, 0x05, 0x14 } /* Sharpest */ + }; + RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); + RESTRICT_TO_RANGE(sharpness, 0, 6); + ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ + ibmcam_model3_Packet1(uvd, 0x0060, sv[sharpness].sv1); + ibmcam_model3_Packet1(uvd, 0x0061, sv[sharpness].sv2); + ibmcam_model3_Packet1(uvd, 0x0062, sv[sharpness].sv3); + ibmcam_model3_Packet1(uvd, 0x0063, sv[sharpness].sv4); + ibmcam_veio(uvd, 0, 0x0001, 0x0114); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ + usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); + ibmcam_veio(uvd, 0, 0x0001, 0x0113); + break; + } + default: + break; + } +} + +/* + * ibmcam_set_brightness() + * + * This procedure changes brightness of the picture. + */ +static void ibmcam_set_brightness(struct uvd *uvd) +{ + static const char proc[] = "ibmcam_set_brightness"; + static const unsigned short n = 1; + + if (debug > 0) + info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness); + + switch (IBMCAM_T(uvd)->camera_model) { + case IBMCAM_MODEL_1: + { + unsigned short i, j, bv[3]; + bv[0] = bv[1] = bv[2] = uvd->vpic.brightness >> 10; + if (bv[0] == (uvd->vpic_old.brightness >> 10)) + return; + uvd->vpic_old.brightness = bv[0]; + for (j=0; j < 3; j++) + for (i=0; i < n; i++) + ibmcam_Packet_Format1(uvd, bright_3x[j], bv[j]); + break; + } + case IBMCAM_MODEL_2: + { + unsigned short i, j; + i = uvd->vpic.brightness >> 12; /* 0 .. 15 */ + j = 0x60 + i * ((0xee - 0x60) / 16); /* 0x60 .. 0xee or so */ + if (uvd->vpic_old.brightness == j) + break; + uvd->vpic_old.brightness = j; + ibmcam_model2_Packet1(uvd, mod2_brightness, j); + break; + } + case IBMCAM_MODEL_3: + { + /* Model 3: Brightness range 'i' in [0x0C..0x3F] */ + unsigned short i = + 0x0C + (uvd->vpic.brightness / (0xFFFF / (0x3F - 0x0C + 1))); + RESTRICT_TO_RANGE(i, 0x0C, 0x3F); + if (uvd->vpic_old.brightness == i) + break; + uvd->vpic_old.brightness = i; + ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ + ibmcam_model3_Packet1(uvd, 0x0036, i); + ibmcam_veio(uvd, 0, 0x0001, 0x0114); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ + usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); + ibmcam_veio(uvd, 0, 0x0001, 0x0113); + break; + } + case IBMCAM_MODEL_4: + { + /* Model 4: Brightness range 'i' in [0x04..0xb4] */ + unsigned short i = 0x04 + (uvd->vpic.brightness / (0xFFFF / (0xb4 - 0x04 + 1))); + RESTRICT_TO_RANGE(i, 0x04, 0xb4); + if (uvd->vpic_old.brightness == i) + break; + uvd->vpic_old.brightness = i; + ibmcam_model4_BrightnessPacket(uvd, i); + break; + } + default: + break; + } +} + +static void ibmcam_set_hue(struct uvd *uvd) +{ + switch (IBMCAM_T(uvd)->camera_model) { + case IBMCAM_MODEL_2: + { + unsigned short hue = uvd->vpic.hue >> 9; /* 0 .. 7F */ + if (uvd->vpic_old.hue == hue) + return; + uvd->vpic_old.hue = hue; + ibmcam_model2_Packet1(uvd, mod2_hue, hue); + /* ibmcam_model2_Packet1(uvd, mod2_saturation, sat); */ + break; + } + case IBMCAM_MODEL_3: + { +#if 0 /* This seems not to work. No problem, will fix programmatically */ + unsigned short hue = 0x05 + (uvd->vpic.hue / (0xFFFF / (0x37 - 0x05 + 1))); + RESTRICT_TO_RANGE(hue, 0x05, 0x37); + if (uvd->vpic_old.hue == hue) + return; + uvd->vpic_old.hue = hue; + ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ + ibmcam_model3_Packet1(uvd, 0x007e, hue); + ibmcam_veio(uvd, 0, 0x0001, 0x0114); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ + usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); + ibmcam_veio(uvd, 0, 0x0001, 0x0113); +#endif + break; + } + case IBMCAM_MODEL_4: + { + unsigned short r_gain, g_gain, b_gain, hue; + + /* + * I am not sure r/g/b_gain variables exactly control gain + * of those channels. Most likely they subtly change some + * very internal image processing settings in the camera. + * In any case, here is what they do, and feel free to tweak: + * + * r_gain: seriously affects red gain + * g_gain: seriously affects green gain + * b_gain: seriously affects blue gain + * hue: changes average color from violet (0) to red (0xFF) + * + * These settings are preset for a decent white balance in + * 320x240, 352x288 modes. Low-res modes exhibit higher contrast + * and therefore may need different values here. + */ + hue = 20 + (uvd->vpic.hue >> 9); + switch (uvd->videosize) { + case VIDEOSIZE_128x96: + r_gain = 90; + g_gain = 166; + b_gain = 175; + break; + case VIDEOSIZE_160x120: + r_gain = 70; + g_gain = 166; + b_gain = 185; + break; + case VIDEOSIZE_176x144: + r_gain = 160; + g_gain = 175; + b_gain = 185; + break; + default: + r_gain = 120; + g_gain = 166; + b_gain = 175; + break; + } + RESTRICT_TO_RANGE(hue, 1, 0x7f); + + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x001e, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, g_gain, 0x0127); /* Green gain */ + ibmcam_veio(uvd, 0, r_gain, 0x012e); /* Red gain */ + ibmcam_veio(uvd, 0, b_gain, 0x0130); /* Blue gain */ + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, hue, 0x012d); /* Hue */ + ibmcam_veio(uvd, 0, 0xf545, 0x0124); + break; + } + default: + break; + } +} + +/* + * ibmcam_adjust_picture() + * + * This procedure gets called from V4L interface to update picture settings. + * Here we change brightness and contrast. + */ +static void ibmcam_adjust_picture(struct uvd *uvd) +{ + ibmcam_adjust_contrast(uvd); + ibmcam_set_brightness(uvd); + ibmcam_set_hue(uvd); +} + +static int ibmcam_model1_setup(struct uvd *uvd) +{ + const int ntries = 5; + int i; + + ibmcam_veio(uvd, 1, 0x00, 0x0128); + ibmcam_veio(uvd, 1, 0x00, 0x0100); + ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ + ibmcam_veio(uvd, 1, 0x00, 0x0100); + ibmcam_veio(uvd, 0, 0x81, 0x0100); /* LED Off */ + ibmcam_veio(uvd, 1, 0x00, 0x0100); + ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ + ibmcam_veio(uvd, 0, 0x01, 0x0108); + + ibmcam_veio(uvd, 0, 0x03, 0x0112); + ibmcam_veio(uvd, 1, 0x00, 0x0115); + ibmcam_veio(uvd, 0, 0x06, 0x0115); + ibmcam_veio(uvd, 1, 0x00, 0x0116); + ibmcam_veio(uvd, 0, 0x44, 0x0116); + ibmcam_veio(uvd, 1, 0x00, 0x0116); + ibmcam_veio(uvd, 0, 0x40, 0x0116); + ibmcam_veio(uvd, 1, 0x00, 0x0115); + ibmcam_veio(uvd, 0, 0x0e, 0x0115); + ibmcam_veio(uvd, 0, 0x19, 0x012c); + + ibmcam_Packet_Format1(uvd, 0x00, 0x1e); + ibmcam_Packet_Format1(uvd, 0x39, 0x0d); + ibmcam_Packet_Format1(uvd, 0x39, 0x09); + ibmcam_Packet_Format1(uvd, 0x3b, 0x00); + ibmcam_Packet_Format1(uvd, 0x28, 0x22); + ibmcam_Packet_Format1(uvd, light_27, 0); + ibmcam_Packet_Format1(uvd, 0x2b, 0x1f); + ibmcam_Packet_Format1(uvd, 0x39, 0x08); + + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x2c, 0x00); + + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x30, 0x14); + + ibmcam_PacketFormat2(uvd, 0x39, 0x02); + ibmcam_PacketFormat2(uvd, 0x01, 0xe1); + ibmcam_PacketFormat2(uvd, 0x02, 0xcd); + ibmcam_PacketFormat2(uvd, 0x03, 0xcd); + ibmcam_PacketFormat2(uvd, 0x04, 0xfa); + ibmcam_PacketFormat2(uvd, 0x3f, 0xff); + ibmcam_PacketFormat2(uvd, 0x39, 0x00); + + ibmcam_PacketFormat2(uvd, 0x39, 0x02); + ibmcam_PacketFormat2(uvd, 0x0a, 0x37); + ibmcam_PacketFormat2(uvd, 0x0b, 0xb8); + ibmcam_PacketFormat2(uvd, 0x0c, 0xf3); + ibmcam_PacketFormat2(uvd, 0x0d, 0xe3); + ibmcam_PacketFormat2(uvd, 0x0e, 0x0d); + ibmcam_PacketFormat2(uvd, 0x0f, 0xf2); + ibmcam_PacketFormat2(uvd, 0x10, 0xd5); + ibmcam_PacketFormat2(uvd, 0x11, 0xba); + ibmcam_PacketFormat2(uvd, 0x12, 0x53); + ibmcam_PacketFormat2(uvd, 0x3f, 0xff); + ibmcam_PacketFormat2(uvd, 0x39, 0x00); + + ibmcam_PacketFormat2(uvd, 0x39, 0x02); + ibmcam_PacketFormat2(uvd, 0x16, 0x00); + ibmcam_PacketFormat2(uvd, 0x17, 0x28); + ibmcam_PacketFormat2(uvd, 0x18, 0x7d); + ibmcam_PacketFormat2(uvd, 0x19, 0xbe); + ibmcam_PacketFormat2(uvd, 0x3f, 0xff); + ibmcam_PacketFormat2(uvd, 0x39, 0x00); + + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x00, 0x18); + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x13, 0x18); + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x14, 0x06); + + /* This is default brightness */ + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x31, 0x37); + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x32, 0x46); + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x33, 0x55); + + ibmcam_Packet_Format1(uvd, 0x2e, 0x04); + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x2d, 0x04); + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x29, 0x80); + ibmcam_Packet_Format1(uvd, 0x2c, 0x01); + ibmcam_Packet_Format1(uvd, 0x30, 0x17); + ibmcam_Packet_Format1(uvd, 0x39, 0x08); + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x34, 0x00); + + ibmcam_veio(uvd, 0, 0x00, 0x0101); + ibmcam_veio(uvd, 0, 0x00, 0x010a); + + switch (uvd->videosize) { + case VIDEOSIZE_128x96: + ibmcam_veio(uvd, 0, 0x80, 0x0103); + ibmcam_veio(uvd, 0, 0x60, 0x0105); + ibmcam_veio(uvd, 0, 0x0c, 0x010b); + ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x0b, 0x011d); + ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x00, 0x0129); + break; + case VIDEOSIZE_176x144: + ibmcam_veio(uvd, 0, 0xb0, 0x0103); + ibmcam_veio(uvd, 0, 0x8f, 0x0105); + ibmcam_veio(uvd, 0, 0x06, 0x010b); + ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x0d, 0x011d); + ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x03, 0x0129); + break; + case VIDEOSIZE_352x288: + ibmcam_veio(uvd, 0, 0xb0, 0x0103); + ibmcam_veio(uvd, 0, 0x90, 0x0105); + ibmcam_veio(uvd, 0, 0x02, 0x010b); + ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x05, 0x011d); + ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x00, 0x0129); + break; + } + + ibmcam_veio(uvd, 0, 0xff, 0x012b); + + /* This is another brightness - don't know why */ + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x31, 0xc3); + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x32, 0xd2); + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, 0x33, 0xe1); + + /* Default contrast */ + for (i=0; i < ntries; i++) + ibmcam_Packet_Format1(uvd, contrast_14, 0x0a); + + /* Default sharpness */ + for (i=0; i < 2; i++) + ibmcam_PacketFormat2(uvd, sharp_13, 0x1a); /* Level 4 FIXME */ + + /* Default lighting conditions */ + ibmcam_Packet_Format1(uvd, light_27, lighting); /* 0=Bright 2=Low */ + + /* Assorted init */ + + switch (uvd->videosize) { + case VIDEOSIZE_128x96: + ibmcam_Packet_Format1(uvd, 0x2b, 0x1e); + ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x36, 0x0102); + ibmcam_veio(uvd, 0, 0x1a, 0x0104); + ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x2b, 0x011c); + ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ +#if 0 + ibmcam_veio(uvd, 0, 0x00, 0x0106); + ibmcam_veio(uvd, 0, 0x38, 0x0107); +#else + ibmcam_veio(uvd, 0, 0x02, 0x0106); + ibmcam_veio(uvd, 0, 0x2a, 0x0107); +#endif + break; + case VIDEOSIZE_176x144: + ibmcam_Packet_Format1(uvd, 0x2b, 0x1e); + ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x04, 0x0102); + ibmcam_veio(uvd, 0, 0x02, 0x0104); + ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x2b, 0x011c); + ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x01, 0x0106); + ibmcam_veio(uvd, 0, 0xca, 0x0107); + break; + case VIDEOSIZE_352x288: + ibmcam_Packet_Format1(uvd, 0x2b, 0x1f); + ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x08, 0x0102); + ibmcam_veio(uvd, 0, 0x01, 0x0104); + ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x2f, 0x011c); + ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ + ibmcam_veio(uvd, 0, 0x03, 0x0106); + ibmcam_veio(uvd, 0, 0xf6, 0x0107); + break; + } + return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT); +} + +static int ibmcam_model2_setup(struct uvd *uvd) +{ + ibmcam_veio(uvd, 0, 0x0000, 0x0100); /* LED on */ + ibmcam_veio(uvd, 1, 0x0000, 0x0116); + ibmcam_veio(uvd, 0, 0x0060, 0x0116); + ibmcam_veio(uvd, 0, 0x0002, 0x0112); + ibmcam_veio(uvd, 0, 0x00bc, 0x012c); + ibmcam_veio(uvd, 0, 0x0008, 0x012b); + ibmcam_veio(uvd, 0, 0x0000, 0x0108); + ibmcam_veio(uvd, 0, 0x0001, 0x0133); + ibmcam_veio(uvd, 0, 0x0001, 0x0102); + switch (uvd->videosize) { + case VIDEOSIZE_176x144: + ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ + ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ + ibmcam_veio(uvd, 0, 0x0024, 0x0105); /* 176x144, 352x288 */ + ibmcam_veio(uvd, 0, 0x00b9, 0x010a); /* Unique to this mode */ + ibmcam_veio(uvd, 0, 0x0038, 0x0119); /* Unique to this mode */ + ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ + ibmcam_veio(uvd, 0, 0x0090, 0x0107); /* Unique to every mode*/ + break; + case VIDEOSIZE_320x240: + ibmcam_veio(uvd, 0, 0x0028, 0x0103); /* Unique to this mode */ + ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ + ibmcam_veio(uvd, 0, 0x001e, 0x0105); /* 320x240, 352x240 */ + ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ + ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ + ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ + ibmcam_veio(uvd, 0, 0x0098, 0x0107); /* Unique to every mode*/ + break; + case VIDEOSIZE_352x240: + ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ + ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ + ibmcam_veio(uvd, 0, 0x001e, 0x0105); /* 320x240, 352x240 */ + ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ + ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ + ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ + ibmcam_veio(uvd, 0, 0x00da, 0x0107); /* Unique to every mode*/ + break; + case VIDEOSIZE_352x288: + ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ + ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ + ibmcam_veio(uvd, 0, 0x0024, 0x0105); /* 176x144, 352x288 */ + ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ + ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ + ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ + ibmcam_veio(uvd, 0, 0x00fe, 0x0107); /* Unique to every mode*/ + break; + } + return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT); +} + +/* + * ibmcam_model1_setup_after_video_if() + * + * This code adds finishing touches to the video data interface. + * Here we configure the frame rate and turn on the LED. + */ +static void ibmcam_model1_setup_after_video_if(struct uvd *uvd) +{ + unsigned short internal_frame_rate; + + RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX); + internal_frame_rate = FRAMERATE_MAX - framerate; /* 0=Fast 6=Slow */ + ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ + ibmcam_veio(uvd, 0, internal_frame_rate, 0x0111); + ibmcam_veio(uvd, 0, 0x01, 0x0114); + ibmcam_veio(uvd, 0, 0xc0, 0x010c); +} + +static void ibmcam_model2_setup_after_video_if(struct uvd *uvd) +{ + unsigned short setup_model2_rg2, setup_model2_sat, setup_model2_yb; + + ibmcam_veio(uvd, 0, 0x0000, 0x0100); /* LED on */ + + switch (uvd->videosize) { + case VIDEOSIZE_176x144: + ibmcam_veio(uvd, 0, 0x0050, 0x0111); + ibmcam_veio(uvd, 0, 0x00d0, 0x0111); + break; + case VIDEOSIZE_320x240: + case VIDEOSIZE_352x240: + case VIDEOSIZE_352x288: + ibmcam_veio(uvd, 0, 0x0040, 0x0111); + ibmcam_veio(uvd, 0, 0x00c0, 0x0111); + break; + } + ibmcam_veio(uvd, 0, 0x009b, 0x010f); + ibmcam_veio(uvd, 0, 0x00bb, 0x010f); + + /* + * Hardware settings, may affect CMOS sensor; not user controls! + * ------------------------------------------------------------- + * 0x0004: no effect + * 0x0006: hardware effect + * 0x0008: no effect + * 0x000a: stops video stream, probably important h/w setting + * 0x000c: changes color in hardware manner (not user setting) + * 0x0012: changes number of colors (does not affect speed) + * 0x002a: no effect + * 0x002c: hardware setting (related to scan lines) + * 0x002e: stops video stream, probably important h/w setting + */ + ibmcam_model2_Packet1(uvd, 0x000a, 0x005c); + ibmcam_model2_Packet1(uvd, 0x0004, 0x0000); + ibmcam_model2_Packet1(uvd, 0x0006, 0x00fb); + ibmcam_model2_Packet1(uvd, 0x0008, 0x0000); + ibmcam_model2_Packet1(uvd, 0x000c, 0x0009); + ibmcam_model2_Packet1(uvd, 0x0012, 0x000a); + ibmcam_model2_Packet1(uvd, 0x002a, 0x0000); + ibmcam_model2_Packet1(uvd, 0x002c, 0x0000); + ibmcam_model2_Packet1(uvd, 0x002e, 0x0008); + + /* + * Function 0x0030 pops up all over the place. Apparently + * it is a hardware control register, with every bit assigned to + * do something. + */ + ibmcam_model2_Packet1(uvd, 0x0030, 0x0000); + + /* + * Magic control of CMOS sensor. Only lower values like + * 0-3 work, and picture shifts left or right. Don't change. + */ + switch (uvd->videosize) { + case VIDEOSIZE_176x144: + ibmcam_model2_Packet1(uvd, 0x0014, 0x0002); + ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */ + ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */ + break; + case VIDEOSIZE_320x240: + ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); + ibmcam_model2_Packet1(uvd, 0x0016, 0x0005); /* Horizontal shift */ + ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Another hardware setting */ + break; + case VIDEOSIZE_352x240: + /* This mode doesn't work as Windows programs it; changed to work */ + ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); /* Windows sets this to 8 */ + ibmcam_model2_Packet1(uvd, 0x0016, 0x0003); /* Horizontal shift */ + ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Windows sets this to 0x0045 */ + break; + case VIDEOSIZE_352x288: + ibmcam_model2_Packet1(uvd, 0x0014, 0x0003); + ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */ + ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */ + break; + } + + ibmcam_model2_Packet1(uvd, mod2_brightness, 0x005a); + + /* + * We have our own frame rate setting varying from 0 (slowest) to 6 (fastest). + * The camera model 2 allows frame rate in range [0..0x1F] where 0 is also the + * slowest setting. However for all practical reasons high settings make no + * sense because USB is not fast enough to support high FPS. Be aware that + * the picture datastream will be severely disrupted if you ask for + * frame rate faster than allowed for the video size - see below: + * + * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz): + * ----------------------------------------------------------------- + * 176x144: [6..31] + * 320x240: [8..31] + * 352x240: [10..31] + * 352x288: [16..31] I have to raise lower threshold for stability... + * + * As usual, slower FPS provides better sensitivity. + */ + { + short hw_fps=31, i_framerate; + + RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX); + i_framerate = FRAMERATE_MAX - framerate + FRAMERATE_MIN; + switch (uvd->videosize) { + case VIDEOSIZE_176x144: + hw_fps = 6 + i_framerate*4; + break; + case VIDEOSIZE_320x240: + hw_fps = 8 + i_framerate*3; + break; + case VIDEOSIZE_352x240: + hw_fps = 10 + i_framerate*2; + break; + case VIDEOSIZE_352x288: + hw_fps = 28 + i_framerate/2; + break; + } + if (uvd->debug > 0) + info("Framerate (hardware): %hd.", hw_fps); + RESTRICT_TO_RANGE(hw_fps, 0, 31); + ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps); + } + + /* + * This setting does not visibly affect pictures; left it here + * because it was present in Windows USB data stream. This function + * does not allow arbitrary values and apparently is a bit mask, to + * be activated only at appropriate time. Don't change it randomly! + */ + switch (uvd->videosize) { + case VIDEOSIZE_176x144: + ibmcam_model2_Packet1(uvd, 0x0026, 0x00c2); + break; + case VIDEOSIZE_320x240: + ibmcam_model2_Packet1(uvd, 0x0026, 0x0044); + break; + case VIDEOSIZE_352x240: + ibmcam_model2_Packet1(uvd, 0x0026, 0x0046); + break; + case VIDEOSIZE_352x288: + ibmcam_model2_Packet1(uvd, 0x0026, 0x0048); + break; + } + + ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting); + + if (init_model2_rg2 >= 0) { + RESTRICT_TO_RANGE(init_model2_rg2, 0, 255); + setup_model2_rg2 = init_model2_rg2; + } else + setup_model2_rg2 = 0x002f; + + if (init_model2_sat >= 0) { + RESTRICT_TO_RANGE(init_model2_sat, 0, 255); + setup_model2_sat = init_model2_sat; + } else + setup_model2_sat = 0x0034; + + if (init_model2_yb >= 0) { + RESTRICT_TO_RANGE(init_model2_yb, 0, 255); + setup_model2_yb = init_model2_yb; + } else + setup_model2_yb = 0x00a0; + + ibmcam_model2_Packet1(uvd, mod2_color_balance_rg2, setup_model2_rg2); + ibmcam_model2_Packet1(uvd, mod2_saturation, setup_model2_sat); + ibmcam_model2_Packet1(uvd, mod2_color_balance_yb, setup_model2_yb); + ibmcam_model2_Packet1(uvd, mod2_hue, uvd->vpic.hue >> 9); /* 0 .. 7F */; + + /* Hardware control command */ + ibmcam_model2_Packet1(uvd, 0x0030, 0x0004); + + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go camera, go! */ + usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); +} + +static void ibmcam_model4_setup_after_video_if(struct uvd *uvd) +{ + switch (uvd->videosize) { + case VIDEOSIZE_128x96: + ibmcam_veio(uvd, 0, 0x0000, 0x0100); + ibmcam_veio(uvd, 0, 0x00c0, 0x0111); + ibmcam_veio(uvd, 0, 0x00bc, 0x012c); + ibmcam_veio(uvd, 0, 0x0080, 0x012b); + ibmcam_veio(uvd, 0, 0x0000, 0x0108); + ibmcam_veio(uvd, 0, 0x0001, 0x0133); + ibmcam_veio(uvd, 0, 0x009b, 0x010f); + ibmcam_veio(uvd, 0, 0x00bb, 0x010f); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0038, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x000a, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x005c, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0004, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0x00fb, 0x012e); + ibmcam_veio(uvd, 0, 0x0000, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012f); + ibmcam_veio(uvd, 0, 0xd055, 0x0124); + ibmcam_veio(uvd, 0, 0x000c, 0x0127); + ibmcam_veio(uvd, 0, 0x0009, 0x012e); + ibmcam_veio(uvd, 0, 0xaa28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0012, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0008, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x002a, 0x012d); + ibmcam_veio(uvd, 0, 0x0000, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0xfffa, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0034, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x0070, 0x0119); + ibmcam_veio(uvd, 0, 0x00d2, 0x0107); + ibmcam_veio(uvd, 0, 0x0003, 0x0106); + ibmcam_veio(uvd, 0, 0x005e, 0x0107); + ibmcam_veio(uvd, 0, 0x0003, 0x0106); + ibmcam_veio(uvd, 0, 0x00d0, 0x0111); + ibmcam_veio(uvd, 0, 0x0039, 0x010a); + ibmcam_veio(uvd, 0, 0x0001, 0x0102); + ibmcam_veio(uvd, 0, 0x0028, 0x0103); + ibmcam_veio(uvd, 0, 0x0000, 0x0104); + ibmcam_veio(uvd, 0, 0x001e, 0x0105); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0016, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x000a, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x0014, 0x012d); + ibmcam_veio(uvd, 0, 0x0008, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012e); + ibmcam_veio(uvd, 0, 0x001a, 0x0130); + ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); + ibmcam_veio(uvd, 0, 0x005a, 0x012d); + ibmcam_veio(uvd, 0, 0x9545, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x0127); + ibmcam_veio(uvd, 0, 0x0018, 0x012e); + ibmcam_veio(uvd, 0, 0x0043, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012f); + ibmcam_veio(uvd, 0, 0xd055, 0x0124); + ibmcam_veio(uvd, 0, 0x001c, 0x0127); + ibmcam_veio(uvd, 0, 0x00eb, 0x012e); + ibmcam_veio(uvd, 0, 0xaa28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0032, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x0036, 0x012d); + ibmcam_veio(uvd, 0, 0x0008, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0xfffa, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x001e, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0017, 0x0127); + ibmcam_veio(uvd, 0, 0x0013, 0x012e); + ibmcam_veio(uvd, 0, 0x0031, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x0017, 0x012d); + ibmcam_veio(uvd, 0, 0x0078, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0038, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0004, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); + break; + case VIDEOSIZE_160x120: + ibmcam_veio(uvd, 0, 0x0000, 0x0100); + ibmcam_veio(uvd, 0, 0x00c0, 0x0111); + ibmcam_veio(uvd, 0, 0x00bc, 0x012c); + ibmcam_veio(uvd, 0, 0x0080, 0x012b); + ibmcam_veio(uvd, 0, 0x0000, 0x0108); + ibmcam_veio(uvd, 0, 0x0001, 0x0133); + ibmcam_veio(uvd, 0, 0x009b, 0x010f); + ibmcam_veio(uvd, 0, 0x00bb, 0x010f); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0038, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x000a, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x005c, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0004, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0x00fb, 0x012e); + ibmcam_veio(uvd, 0, 0x0000, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012f); + ibmcam_veio(uvd, 0, 0xd055, 0x0124); + ibmcam_veio(uvd, 0, 0x000c, 0x0127); + ibmcam_veio(uvd, 0, 0x0009, 0x012e); + ibmcam_veio(uvd, 0, 0xaa28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0012, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0008, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x002a, 0x012d); + ibmcam_veio(uvd, 0, 0x0000, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0xfffa, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0034, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x0038, 0x0119); + ibmcam_veio(uvd, 0, 0x00d8, 0x0107); + ibmcam_veio(uvd, 0, 0x0002, 0x0106); + ibmcam_veio(uvd, 0, 0x00d0, 0x0111); + ibmcam_veio(uvd, 0, 0x00b9, 0x010a); + ibmcam_veio(uvd, 0, 0x0001, 0x0102); + ibmcam_veio(uvd, 0, 0x0028, 0x0103); + ibmcam_veio(uvd, 0, 0x0000, 0x0104); + ibmcam_veio(uvd, 0, 0x001e, 0x0105); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0016, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x000b, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x0014, 0x012d); + ibmcam_veio(uvd, 0, 0x0008, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012e); + ibmcam_veio(uvd, 0, 0x001a, 0x0130); + ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); + ibmcam_veio(uvd, 0, 0x005a, 0x012d); + ibmcam_veio(uvd, 0, 0x9545, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x0127); + ibmcam_veio(uvd, 0, 0x0018, 0x012e); + ibmcam_veio(uvd, 0, 0x0043, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012f); + ibmcam_veio(uvd, 0, 0xd055, 0x0124); + ibmcam_veio(uvd, 0, 0x001c, 0x0127); + ibmcam_veio(uvd, 0, 0x00c7, 0x012e); + ibmcam_veio(uvd, 0, 0xaa28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0032, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0025, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x0036, 0x012d); + ibmcam_veio(uvd, 0, 0x0008, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0xfffa, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x001e, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0048, 0x0127); + ibmcam_veio(uvd, 0, 0x0035, 0x012e); + ibmcam_veio(uvd, 0, 0x00d0, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x0048, 0x012d); + ibmcam_veio(uvd, 0, 0x0090, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0x0001, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0038, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0004, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); + break; + case VIDEOSIZE_176x144: + ibmcam_veio(uvd, 0, 0x0000, 0x0100); + ibmcam_veio(uvd, 0, 0x00c0, 0x0111); + ibmcam_veio(uvd, 0, 0x00bc, 0x012c); + ibmcam_veio(uvd, 0, 0x0080, 0x012b); + ibmcam_veio(uvd, 0, 0x0000, 0x0108); + ibmcam_veio(uvd, 0, 0x0001, 0x0133); + ibmcam_veio(uvd, 0, 0x009b, 0x010f); + ibmcam_veio(uvd, 0, 0x00bb, 0x010f); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0038, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x000a, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x005c, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0004, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0x00fb, 0x012e); + ibmcam_veio(uvd, 0, 0x0000, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012f); + ibmcam_veio(uvd, 0, 0xd055, 0x0124); + ibmcam_veio(uvd, 0, 0x000c, 0x0127); + ibmcam_veio(uvd, 0, 0x0009, 0x012e); + ibmcam_veio(uvd, 0, 0xaa28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0012, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0008, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x002a, 0x012d); + ibmcam_veio(uvd, 0, 0x0000, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0xfffa, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0034, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x0038, 0x0119); + ibmcam_veio(uvd, 0, 0x00d6, 0x0107); + ibmcam_veio(uvd, 0, 0x0003, 0x0106); + ibmcam_veio(uvd, 0, 0x0018, 0x0107); + ibmcam_veio(uvd, 0, 0x0003, 0x0106); + ibmcam_veio(uvd, 0, 0x00d0, 0x0111); + ibmcam_veio(uvd, 0, 0x00b9, 0x010a); + ibmcam_veio(uvd, 0, 0x0001, 0x0102); + ibmcam_veio(uvd, 0, 0x002c, 0x0103); + ibmcam_veio(uvd, 0, 0x0000, 0x0104); + ibmcam_veio(uvd, 0, 0x0024, 0x0105); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0016, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0007, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x0014, 0x012d); + ibmcam_veio(uvd, 0, 0x0001, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012e); + ibmcam_veio(uvd, 0, 0x001a, 0x0130); + ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); + ibmcam_veio(uvd, 0, 0x005e, 0x012d); + ibmcam_veio(uvd, 0, 0x9545, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x0127); + ibmcam_veio(uvd, 0, 0x0018, 0x012e); + ibmcam_veio(uvd, 0, 0x0049, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012f); + ibmcam_veio(uvd, 0, 0xd055, 0x0124); + ibmcam_veio(uvd, 0, 0x001c, 0x0127); + ibmcam_veio(uvd, 0, 0x00c7, 0x012e); + ibmcam_veio(uvd, 0, 0xaa28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0032, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0028, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x0036, 0x012d); + ibmcam_veio(uvd, 0, 0x0008, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0xfffa, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x001e, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0010, 0x0127); + ibmcam_veio(uvd, 0, 0x0013, 0x012e); + ibmcam_veio(uvd, 0, 0x002a, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x0010, 0x012d); + ibmcam_veio(uvd, 0, 0x006d, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0x0001, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0038, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0004, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); + break; + case VIDEOSIZE_320x240: + ibmcam_veio(uvd, 0, 0x0000, 0x0100); + ibmcam_veio(uvd, 0, 0x00c0, 0x0111); + ibmcam_veio(uvd, 0, 0x00bc, 0x012c); + ibmcam_veio(uvd, 0, 0x0080, 0x012b); + ibmcam_veio(uvd, 0, 0x0000, 0x0108); + ibmcam_veio(uvd, 0, 0x0001, 0x0133); + ibmcam_veio(uvd, 0, 0x009b, 0x010f); + ibmcam_veio(uvd, 0, 0x00bb, 0x010f); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0038, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x000a, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x005c, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0004, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0x00fb, 0x012e); + ibmcam_veio(uvd, 0, 0x0000, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012f); + ibmcam_veio(uvd, 0, 0xd055, 0x0124); + ibmcam_veio(uvd, 0, 0x000c, 0x0127); + ibmcam_veio(uvd, 0, 0x0009, 0x012e); + ibmcam_veio(uvd, 0, 0xaa28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0012, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0008, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x002a, 0x012d); + ibmcam_veio(uvd, 0, 0x0000, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0xfffa, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0034, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x0070, 0x0119); + ibmcam_veio(uvd, 0, 0x00d2, 0x0107); + ibmcam_veio(uvd, 0, 0x0003, 0x0106); + ibmcam_veio(uvd, 0, 0x005e, 0x0107); + ibmcam_veio(uvd, 0, 0x0003, 0x0106); + ibmcam_veio(uvd, 0, 0x00d0, 0x0111); + ibmcam_veio(uvd, 0, 0x0039, 0x010a); + ibmcam_veio(uvd, 0, 0x0001, 0x0102); + ibmcam_veio(uvd, 0, 0x0028, 0x0103); + ibmcam_veio(uvd, 0, 0x0000, 0x0104); + ibmcam_veio(uvd, 0, 0x001e, 0x0105); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0016, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x000a, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x0014, 0x012d); + ibmcam_veio(uvd, 0, 0x0008, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012e); + ibmcam_veio(uvd, 0, 0x001a, 0x0130); + ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); + ibmcam_veio(uvd, 0, 0x005a, 0x012d); + ibmcam_veio(uvd, 0, 0x9545, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x0127); + ibmcam_veio(uvd, 0, 0x0018, 0x012e); + ibmcam_veio(uvd, 0, 0x0043, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012f); + ibmcam_veio(uvd, 0, 0xd055, 0x0124); + ibmcam_veio(uvd, 0, 0x001c, 0x0127); + ibmcam_veio(uvd, 0, 0x00eb, 0x012e); + ibmcam_veio(uvd, 0, 0xaa28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0032, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x0036, 0x012d); + ibmcam_veio(uvd, 0, 0x0008, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0xfffa, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x001e, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0017, 0x0127); + ibmcam_veio(uvd, 0, 0x0013, 0x012e); + ibmcam_veio(uvd, 0, 0x0031, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x0017, 0x012d); + ibmcam_veio(uvd, 0, 0x0078, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0038, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0004, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); + break; + case VIDEOSIZE_352x288: + ibmcam_veio(uvd, 0, 0x0000, 0x0100); + ibmcam_veio(uvd, 0, 0x00c0, 0x0111); + ibmcam_veio(uvd, 0, 0x00bc, 0x012c); + ibmcam_veio(uvd, 0, 0x0080, 0x012b); + ibmcam_veio(uvd, 0, 0x0000, 0x0108); + ibmcam_veio(uvd, 0, 0x0001, 0x0133); + ibmcam_veio(uvd, 0, 0x009b, 0x010f); + ibmcam_veio(uvd, 0, 0x00bb, 0x010f); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0038, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x000a, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x005c, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0004, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0x00fb, 0x012e); + ibmcam_veio(uvd, 0, 0x0000, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012f); + ibmcam_veio(uvd, 0, 0xd055, 0x0124); + ibmcam_veio(uvd, 0, 0x000c, 0x0127); + ibmcam_veio(uvd, 0, 0x0009, 0x012e); + ibmcam_veio(uvd, 0, 0xaa28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0012, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0008, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x002a, 0x012d); + ibmcam_veio(uvd, 0, 0x0000, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0xfffa, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0034, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x0070, 0x0119); + ibmcam_veio(uvd, 0, 0x00f2, 0x0107); + ibmcam_veio(uvd, 0, 0x0003, 0x0106); + ibmcam_veio(uvd, 0, 0x008c, 0x0107); + ibmcam_veio(uvd, 0, 0x0003, 0x0106); + ibmcam_veio(uvd, 0, 0x00c0, 0x0111); + ibmcam_veio(uvd, 0, 0x0039, 0x010a); + ibmcam_veio(uvd, 0, 0x0001, 0x0102); + ibmcam_veio(uvd, 0, 0x002c, 0x0103); + ibmcam_veio(uvd, 0, 0x0000, 0x0104); + ibmcam_veio(uvd, 0, 0x0024, 0x0105); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0016, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0006, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x0014, 0x012d); + ibmcam_veio(uvd, 0, 0x0002, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012e); + ibmcam_veio(uvd, 0, 0x001a, 0x0130); + ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); + ibmcam_veio(uvd, 0, 0x005e, 0x012d); + ibmcam_veio(uvd, 0, 0x9545, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x0127); + ibmcam_veio(uvd, 0, 0x0018, 0x012e); + ibmcam_veio(uvd, 0, 0x0049, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012f); + ibmcam_veio(uvd, 0, 0xd055, 0x0124); + ibmcam_veio(uvd, 0, 0x001c, 0x0127); + ibmcam_veio(uvd, 0, 0x00cf, 0x012e); + ibmcam_veio(uvd, 0, 0xaa28, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0032, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0x00aa, 0x0130); + ibmcam_veio(uvd, 0, 0x82a8, 0x0124); + ibmcam_veio(uvd, 0, 0x0036, 0x012d); + ibmcam_veio(uvd, 0, 0x0008, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0xfffa, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x001e, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0010, 0x0127); + ibmcam_veio(uvd, 0, 0x0013, 0x012e); + ibmcam_veio(uvd, 0, 0x0025, 0x0130); + ibmcam_veio(uvd, 0, 0x8a28, 0x0124); + ibmcam_veio(uvd, 0, 0x0010, 0x012d); + ibmcam_veio(uvd, 0, 0x0048, 0x012f); + ibmcam_veio(uvd, 0, 0xd145, 0x0124); + ibmcam_veio(uvd, 0, 0x0000, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00aa, 0x012d); + ibmcam_veio(uvd, 0, 0x0038, 0x012f); + ibmcam_veio(uvd, 0, 0xd141, 0x0124); + ibmcam_veio(uvd, 0, 0x0004, 0x0127); + ibmcam_veio(uvd, 0, 0xfea8, 0x0124); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); + break; + } + usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); +} + +static void ibmcam_model3_setup_after_video_if(struct uvd *uvd) +{ + int i; + /* + * 01.01.08 - Added for RCA video in support -LO + * This struct is used to init the Model3 cam to use the RCA video in port + * instead of the CCD sensor. + */ + static const struct struct_initData initData[] = { + {0, 0x0000, 0x010c}, + {0, 0x0006, 0x012c}, + {0, 0x0078, 0x012d}, + {0, 0x0046, 0x012f}, + {0, 0xd141, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfea8, 0x0124}, + {1, 0x0000, 0x0116}, + {0, 0x0064, 0x0116}, + {1, 0x0000, 0x0115}, + {0, 0x0003, 0x0115}, + {0, 0x0008, 0x0123}, + {0, 0x0000, 0x0117}, + {0, 0x0000, 0x0112}, + {0, 0x0080, 0x0100}, + {0, 0x0000, 0x0100}, + {1, 0x0000, 0x0116}, + {0, 0x0060, 0x0116}, + {0, 0x0002, 0x0112}, + {0, 0x0000, 0x0123}, + {0, 0x0001, 0x0117}, + {0, 0x0040, 0x0108}, + {0, 0x0019, 0x012c}, + {0, 0x0040, 0x0116}, + {0, 0x000a, 0x0115}, + {0, 0x000b, 0x0115}, + {0, 0x0078, 0x012d}, + {0, 0x0046, 0x012f}, + {0, 0xd141, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfea8, 0x0124}, + {0, 0x0064, 0x0116}, + {0, 0x0000, 0x0115}, + {0, 0x0001, 0x0115}, + {0, 0xffff, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x00aa, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xffff, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x00f2, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x000f, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xffff, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x00f8, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x00fc, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xffff, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x00f9, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x003c, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xffff, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0027, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0019, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0021, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0006, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0045, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x002a, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x000e, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x002b, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x00f4, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x002c, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0004, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x002d, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0014, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x002e, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0003, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x002f, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0003, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0014, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0040, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0040, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0053, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0x0000, 0x0101}, + {0, 0x00a0, 0x0103}, + {0, 0x0078, 0x0105}, + {0, 0x0000, 0x010a}, + {0, 0x0024, 0x010b}, + {0, 0x0028, 0x0119}, + {0, 0x0088, 0x011b}, + {0, 0x0002, 0x011d}, + {0, 0x0003, 0x011e}, + {0, 0x0000, 0x0129}, + {0, 0x00fc, 0x012b}, + {0, 0x0008, 0x0102}, + {0, 0x0000, 0x0104}, + {0, 0x0008, 0x011a}, + {0, 0x0028, 0x011c}, + {0, 0x0021, 0x012a}, + {0, 0x0000, 0x0118}, + {0, 0x0000, 0x0132}, + {0, 0x0000, 0x0109}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0031, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0040, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0040, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x00dc, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0032, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0020, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0001, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0040, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0040, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0037, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0030, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0xfff9, 0x0124}, + {0, 0x0086, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0038, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0008, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0x0000, 0x0127}, + {0, 0xfff8, 0x0124}, + {0, 0xfffd, 0x0124}, + {0, 0xfffa, 0x0124}, + {0, 0x0003, 0x0106}, + {0, 0x0062, 0x0107}, + {0, 0x0003, 0x0111}, + }; +#define NUM_INIT_DATA + + unsigned short compression = 0; /* 0=none, 7=best frame rate */ + int f_rate; /* 0=Fastest 7=slowest */ + + if (IBMCAM_T(uvd)->initialized) + return; + + /* Internal frame rate is controlled by f_rate value */ + f_rate = 7 - framerate; + RESTRICT_TO_RANGE(f_rate, 0, 7); + + ibmcam_veio(uvd, 0, 0x0000, 0x0100); + ibmcam_veio(uvd, 1, 0x0000, 0x0116); + ibmcam_veio(uvd, 0, 0x0060, 0x0116); + ibmcam_veio(uvd, 0, 0x0002, 0x0112); + ibmcam_veio(uvd, 0, 0x0000, 0x0123); + ibmcam_veio(uvd, 0, 0x0001, 0x0117); + ibmcam_veio(uvd, 0, 0x0040, 0x0108); + ibmcam_veio(uvd, 0, 0x0019, 0x012c); + ibmcam_veio(uvd, 0, 0x0060, 0x0116); + ibmcam_veio(uvd, 0, 0x0002, 0x0115); + ibmcam_veio(uvd, 0, 0x0003, 0x0115); + ibmcam_veio(uvd, 1, 0x0000, 0x0115); + ibmcam_veio(uvd, 0, 0x000b, 0x0115); + ibmcam_model3_Packet1(uvd, 0x000a, 0x0040); + ibmcam_model3_Packet1(uvd, 0x000b, 0x00f6); + ibmcam_model3_Packet1(uvd, 0x000c, 0x0002); + ibmcam_model3_Packet1(uvd, 0x000d, 0x0020); + ibmcam_model3_Packet1(uvd, 0x000e, 0x0033); + ibmcam_model3_Packet1(uvd, 0x000f, 0x0007); + ibmcam_model3_Packet1(uvd, 0x0010, 0x0000); + ibmcam_model3_Packet1(uvd, 0x0011, 0x0070); + ibmcam_model3_Packet1(uvd, 0x0012, 0x0030); + ibmcam_model3_Packet1(uvd, 0x0013, 0x0000); + ibmcam_model3_Packet1(uvd, 0x0014, 0x0001); + ibmcam_model3_Packet1(uvd, 0x0015, 0x0001); + ibmcam_model3_Packet1(uvd, 0x0016, 0x0001); + ibmcam_model3_Packet1(uvd, 0x0017, 0x0001); + ibmcam_model3_Packet1(uvd, 0x0018, 0x0000); + ibmcam_model3_Packet1(uvd, 0x001e, 0x00c3); + ibmcam_model3_Packet1(uvd, 0x0020, 0x0000); + ibmcam_model3_Packet1(uvd, 0x0028, 0x0010); + ibmcam_model3_Packet1(uvd, 0x0029, 0x0054); + ibmcam_model3_Packet1(uvd, 0x002a, 0x0013); + ibmcam_model3_Packet1(uvd, 0x002b, 0x0007); + ibmcam_model3_Packet1(uvd, 0x002d, 0x0028); + ibmcam_model3_Packet1(uvd, 0x002e, 0x0000); + ibmcam_model3_Packet1(uvd, 0x0031, 0x0000); + ibmcam_model3_Packet1(uvd, 0x0032, 0x0000); + ibmcam_model3_Packet1(uvd, 0x0033, 0x0000); + ibmcam_model3_Packet1(uvd, 0x0034, 0x0000); + ibmcam_model3_Packet1(uvd, 0x0035, 0x0038); + ibmcam_model3_Packet1(uvd, 0x003a, 0x0001); + ibmcam_model3_Packet1(uvd, 0x003c, 0x001e); + ibmcam_model3_Packet1(uvd, 0x003f, 0x000a); + ibmcam_model3_Packet1(uvd, 0x0041, 0x0000); + ibmcam_model3_Packet1(uvd, 0x0046, 0x003f); + ibmcam_model3_Packet1(uvd, 0x0047, 0x0000); + ibmcam_model3_Packet1(uvd, 0x0050, 0x0005); + ibmcam_model3_Packet1(uvd, 0x0052, 0x001a); + ibmcam_model3_Packet1(uvd, 0x0053, 0x0003); + ibmcam_model3_Packet1(uvd, 0x005a, 0x006b); + ibmcam_model3_Packet1(uvd, 0x005d, 0x001e); + ibmcam_model3_Packet1(uvd, 0x005e, 0x0030); + ibmcam_model3_Packet1(uvd, 0x005f, 0x0041); + ibmcam_model3_Packet1(uvd, 0x0064, 0x0008); + ibmcam_model3_Packet1(uvd, 0x0065, 0x0015); + ibmcam_model3_Packet1(uvd, 0x0068, 0x000f); + ibmcam_model3_Packet1(uvd, 0x0079, 0x0000); + ibmcam_model3_Packet1(uvd, 0x007a, 0x0000); + ibmcam_model3_Packet1(uvd, 0x007c, 0x003f); + ibmcam_model3_Packet1(uvd, 0x0082, 0x000f); + ibmcam_model3_Packet1(uvd, 0x0085, 0x0000); + ibmcam_model3_Packet1(uvd, 0x0099, 0x0000); + ibmcam_model3_Packet1(uvd, 0x009b, 0x0023); + ibmcam_model3_Packet1(uvd, 0x009c, 0x0022); + ibmcam_model3_Packet1(uvd, 0x009d, 0x0096); + ibmcam_model3_Packet1(uvd, 0x009e, 0x0096); + ibmcam_model3_Packet1(uvd, 0x009f, 0x000a); + + switch (uvd->videosize) { + case VIDEOSIZE_160x120: + ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */ + ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */ + ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */ + ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ + ibmcam_veio(uvd, 0, 0x0024, 0x010b); /* Differs everywhere */ + ibmcam_veio(uvd, 0, 0x00a9, 0x0119); + ibmcam_veio(uvd, 0, 0x0016, 0x011b); + ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same on 176x144, 320x240 */ + ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */ + ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ + ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ + ibmcam_veio(uvd, 0, 0x0018, 0x0102); + ibmcam_veio(uvd, 0, 0x0004, 0x0104); + ibmcam_veio(uvd, 0, 0x0004, 0x011a); + ibmcam_veio(uvd, 0, 0x0028, 0x011c); + ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ + ibmcam_veio(uvd, 0, 0x0000, 0x0118); + ibmcam_veio(uvd, 0, 0x0000, 0x0132); + ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ + ibmcam_veio(uvd, 0, compression, 0x0109); + break; + case VIDEOSIZE_320x240: + ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */ + ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */ + ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */ + ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ + ibmcam_veio(uvd, 0, 0x0028, 0x010b); /* Differs everywhere */ + ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same */ + ibmcam_veio(uvd, 0, 0x0000, 0x011e); + ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ + ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ + /* 4 commands from 160x120 skipped */ + ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ + ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ + ibmcam_veio(uvd, 0, compression, 0x0109); + ibmcam_veio(uvd, 0, 0x00d9, 0x0119); + ibmcam_veio(uvd, 0, 0x0006, 0x011b); + ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */ + ibmcam_veio(uvd, 0, 0x0010, 0x0104); + ibmcam_veio(uvd, 0, 0x0004, 0x011a); + ibmcam_veio(uvd, 0, 0x003f, 0x011c); + ibmcam_veio(uvd, 0, 0x001c, 0x0118); + ibmcam_veio(uvd, 0, 0x0000, 0x0132); + break; + case VIDEOSIZE_640x480: + ibmcam_veio(uvd, 0, 0x00f0, 0x0105); + ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ + ibmcam_veio(uvd, 0, 0x0038, 0x010b); /* Differs everywhere */ + ibmcam_veio(uvd, 0, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */ + ibmcam_veio(uvd, 0, 0x0006, 0x011b); /* Same on 320x240, 640x480 */ + ibmcam_veio(uvd, 0, 0x0004, 0x011d); /* NC */ + ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */ + ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ + ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ + ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */ + ibmcam_veio(uvd, 0, 0x0016, 0x0104); /* NC */ + ibmcam_veio(uvd, 0, 0x0004, 0x011a); /* Same on 320x240, 640x480 */ + ibmcam_veio(uvd, 0, 0x003f, 0x011c); /* Same on 320x240, 640x480 */ + ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ + ibmcam_veio(uvd, 0, 0x001c, 0x0118); /* Same on 320x240, 640x480 */ + ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ + ibmcam_veio(uvd, 0, compression, 0x0109); + ibmcam_veio(uvd, 0, 0x0040, 0x0101); + ibmcam_veio(uvd, 0, 0x0040, 0x0103); + ibmcam_veio(uvd, 0, 0x0000, 0x0132); /* Same on 320x240, 640x480 */ + break; + } + ibmcam_model3_Packet1(uvd, 0x007e, 0x000e); /* Hue */ + ibmcam_model3_Packet1(uvd, 0x0036, 0x0011); /* Brightness */ + ibmcam_model3_Packet1(uvd, 0x0060, 0x0002); /* Sharpness */ + ibmcam_model3_Packet1(uvd, 0x0061, 0x0004); /* Sharpness */ + ibmcam_model3_Packet1(uvd, 0x0062, 0x0005); /* Sharpness */ + ibmcam_model3_Packet1(uvd, 0x0063, 0x0014); /* Sharpness */ + ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0); /* Red gain */ + ibmcam_model3_Packet1(uvd, 0x0097, 0x0096); /* Blue gain */ + ibmcam_model3_Packet1(uvd, 0x0067, 0x0001); /* Contrast */ + ibmcam_model3_Packet1(uvd, 0x005b, 0x000c); /* Contrast */ + ibmcam_model3_Packet1(uvd, 0x005c, 0x0016); /* Contrast */ + ibmcam_model3_Packet1(uvd, 0x0098, 0x000b); + ibmcam_model3_Packet1(uvd, 0x002c, 0x0003); /* Was 1, broke 640x480 */ + ibmcam_model3_Packet1(uvd, 0x002f, 0x002a); + ibmcam_model3_Packet1(uvd, 0x0030, 0x0029); + ibmcam_model3_Packet1(uvd, 0x0037, 0x0002); + ibmcam_model3_Packet1(uvd, 0x0038, 0x0059); + ibmcam_model3_Packet1(uvd, 0x003d, 0x002e); + ibmcam_model3_Packet1(uvd, 0x003e, 0x0028); + ibmcam_model3_Packet1(uvd, 0x0078, 0x0005); + ibmcam_model3_Packet1(uvd, 0x007b, 0x0011); + ibmcam_model3_Packet1(uvd, 0x007d, 0x004b); + ibmcam_model3_Packet1(uvd, 0x007f, 0x0022); + ibmcam_model3_Packet1(uvd, 0x0080, 0x000c); + ibmcam_model3_Packet1(uvd, 0x0081, 0x000b); + ibmcam_model3_Packet1(uvd, 0x0083, 0x00fd); + ibmcam_model3_Packet1(uvd, 0x0086, 0x000b); + ibmcam_model3_Packet1(uvd, 0x0087, 0x000b); + ibmcam_model3_Packet1(uvd, 0x007e, 0x000e); + ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0); /* Red gain */ + ibmcam_model3_Packet1(uvd, 0x0097, 0x0096); /* Blue gain */ + ibmcam_model3_Packet1(uvd, 0x0098, 0x000b); + + switch (uvd->videosize) { + case VIDEOSIZE_160x120: + ibmcam_veio(uvd, 0, 0x0002, 0x0106); + ibmcam_veio(uvd, 0, 0x0008, 0x0107); + ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ + ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */ + ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */ + ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */ + ibmcam_model3_Packet1(uvd, 0x0040, 0x000a); + ibmcam_model3_Packet1(uvd, 0x0051, 0x000a); + break; + case VIDEOSIZE_320x240: + ibmcam_veio(uvd, 0, 0x0003, 0x0106); + ibmcam_veio(uvd, 0, 0x0062, 0x0107); + ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ + ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */ + ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */ + ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */ + ibmcam_model3_Packet1(uvd, 0x0040, 0x0008); + ibmcam_model3_Packet1(uvd, 0x0051, 0x000b); + break; + case VIDEOSIZE_640x480: + ibmcam_veio(uvd, 0, 0x0002, 0x0106); /* Adjustments */ + ibmcam_veio(uvd, 0, 0x00b4, 0x0107); /* Adjustments */ + ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ + ibmcam_model3_Packet1(uvd, 0x001f, 0x0002); /* !Same */ + ibmcam_model3_Packet1(uvd, 0x0039, 0x003e); /* !Same */ + ibmcam_model3_Packet1(uvd, 0x0040, 0x0008); + ibmcam_model3_Packet1(uvd, 0x0051, 0x000a); + break; + } + + /* 01.01.08 - Added for RCA video in support -LO */ + if(init_model3_input) { + if (debug > 0) + info("Setting input to RCA."); + for (i=0; i < ARRAY_SIZE(initData); i++) { + ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index); + } + } + + ibmcam_veio(uvd, 0, 0x0001, 0x0114); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); + usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); +} + +/* + * ibmcam_video_stop() + * + * This code tells camera to stop streaming. The interface remains + * configured and bandwidth - claimed. + */ +static void ibmcam_video_stop(struct uvd *uvd) +{ + switch (IBMCAM_T(uvd)->camera_model) { + case IBMCAM_MODEL_1: + ibmcam_veio(uvd, 0, 0x00, 0x010c); + ibmcam_veio(uvd, 0, 0x00, 0x010c); + ibmcam_veio(uvd, 0, 0x01, 0x0114); + ibmcam_veio(uvd, 0, 0xc0, 0x010c); + ibmcam_veio(uvd, 0, 0x00, 0x010c); + ibmcam_send_FF_04_02(uvd); + ibmcam_veio(uvd, 1, 0x00, 0x0100); + ibmcam_veio(uvd, 0, 0x81, 0x0100); /* LED Off */ + break; + case IBMCAM_MODEL_2: +case IBMCAM_MODEL_4: + ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop the camera */ + + ibmcam_model2_Packet1(uvd, 0x0030, 0x0004); + + ibmcam_veio(uvd, 0, 0x0080, 0x0100); /* LED Off */ + ibmcam_veio(uvd, 0, 0x0020, 0x0111); + ibmcam_veio(uvd, 0, 0x00a0, 0x0111); + + ibmcam_model2_Packet1(uvd, 0x0030, 0x0002); + + ibmcam_veio(uvd, 0, 0x0020, 0x0111); + ibmcam_veio(uvd, 0, 0x0000, 0x0112); + break; + case IBMCAM_MODEL_3: +#if 1 + ibmcam_veio(uvd, 0, 0x0000, 0x010c); + + /* Here we are supposed to select video interface alt. setting 0 */ + ibmcam_veio(uvd, 0, 0x0006, 0x012c); + + ibmcam_model3_Packet1(uvd, 0x0046, 0x0000); + + ibmcam_veio(uvd, 1, 0x0000, 0x0116); + ibmcam_veio(uvd, 0, 0x0064, 0x0116); + ibmcam_veio(uvd, 1, 0x0000, 0x0115); + ibmcam_veio(uvd, 0, 0x0003, 0x0115); + ibmcam_veio(uvd, 0, 0x0008, 0x0123); + ibmcam_veio(uvd, 0, 0x0000, 0x0117); + ibmcam_veio(uvd, 0, 0x0000, 0x0112); + ibmcam_veio(uvd, 0, 0x0080, 0x0100); + IBMCAM_T(uvd)->initialized = 0; +#endif + break; + } /* switch */ +} + +/* + * ibmcam_reinit_iso() + * + * This procedure sends couple of commands to the camera and then + * resets the video pipe. This sequence was observed to reinit the + * camera or, at least, to initiate ISO data stream. + * + * History: + * 1/2/00 Created. + */ +static void ibmcam_reinit_iso(struct uvd *uvd, int do_stop) +{ + switch (IBMCAM_T(uvd)->camera_model) { + case IBMCAM_MODEL_1: + if (do_stop) + ibmcam_video_stop(uvd); + ibmcam_veio(uvd, 0, 0x0001, 0x0114); + ibmcam_veio(uvd, 0, 0x00c0, 0x010c); + usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); + ibmcam_model1_setup_after_video_if(uvd); + break; + case IBMCAM_MODEL_2: + ibmcam_model2_setup_after_video_if(uvd); + break; + case IBMCAM_MODEL_3: + ibmcam_video_stop(uvd); + ibmcam_model3_setup_after_video_if(uvd); + break; + case IBMCAM_MODEL_4: + ibmcam_model4_setup_after_video_if(uvd); + break; + } +} + +static void ibmcam_video_start(struct uvd *uvd) +{ + ibmcam_change_lighting_conditions(uvd); + ibmcam_set_sharpness(uvd); + ibmcam_reinit_iso(uvd, 0); +} + +/* + * Return negative code on failure, 0 on success. + */ +static int ibmcam_setup_on_open(struct uvd *uvd) +{ + int setup_ok = 0; /* Success by default */ + /* Send init sequence only once, it's large! */ + if (!IBMCAM_T(uvd)->initialized) { /* FIXME rename */ + switch (IBMCAM_T(uvd)->camera_model) { + case IBMCAM_MODEL_1: + setup_ok = ibmcam_model1_setup(uvd); + break; + case IBMCAM_MODEL_2: + setup_ok = ibmcam_model2_setup(uvd); + break; + case IBMCAM_MODEL_3: + case IBMCAM_MODEL_4: + /* We do all setup when Isoc stream is requested */ + break; + } + IBMCAM_T(uvd)->initialized = (setup_ok != 0); + } + return setup_ok; +} + +static void ibmcam_configure_video(struct uvd *uvd) +{ + if (uvd == NULL) + return; + + RESTRICT_TO_RANGE(init_brightness, 0, 255); + RESTRICT_TO_RANGE(init_contrast, 0, 255); + RESTRICT_TO_RANGE(init_color, 0, 255); + RESTRICT_TO_RANGE(init_hue, 0, 255); + RESTRICT_TO_RANGE(hue_correction, 0, 255); + + memset(&uvd->vpic, 0, sizeof(uvd->vpic)); + memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); + + uvd->vpic.colour = init_color << 8; + uvd->vpic.hue = init_hue << 8; + uvd->vpic.brightness = init_brightness << 8; + uvd->vpic.contrast = init_contrast << 8; + uvd->vpic.whiteness = 105 << 8; /* This one isn't used */ + uvd->vpic.depth = 24; + uvd->vpic.palette = VIDEO_PALETTE_RGB24; + + memset(&uvd->vcap, 0, sizeof(uvd->vcap)); + strcpy(uvd->vcap.name, "IBM USB Camera"); + uvd->vcap.type = VID_TYPE_CAPTURE; + uvd->vcap.channels = 1; + uvd->vcap.audios = 0; + uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas); + uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas); + uvd->vcap.minwidth = min_canvasWidth; + uvd->vcap.minheight = min_canvasHeight; + + memset(&uvd->vchan, 0, sizeof(uvd->vchan)); + uvd->vchan.flags = 0; + uvd->vchan.tuners = 0; + uvd->vchan.channel = 0; + uvd->vchan.type = VIDEO_TYPE_CAMERA; + strcpy(uvd->vchan.name, "Camera"); +} + +/* + * ibmcam_probe() + * + * This procedure queries device descriptor and accepts the interface + * if it looks like IBM C-it camera. + * + * History: + * 22-Jan-2000 Moved camera init code to ibmcam_open() + * 27=Jan-2000 Changed to use static structures, added locking. + * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). + * 03-Jul-2000 Fixed endianness bug. + * 12-Nov-2000 Reworked to comply with new probe() signature. + * 23-Jan-2001 Added compatibility with 2.2.x kernels. + */ +static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *devid) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct uvd *uvd = NULL; + int ix, i, nas, model=0, canvasX=0, canvasY=0; + int actInterface=-1, inactInterface=-1, maxPS=0; + __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; + unsigned char video_ep = 0; + + if (debug >= 1) + info("ibmcam_probe(%p,%u.)", intf, ifnum); + + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + /* Check the version/revision */ + switch (le16_to_cpu(dev->descriptor.bcdDevice)) { + case 0x0002: + if (ifnum != 2) + return -ENODEV; + model = IBMCAM_MODEL_1; + break; + case 0x030A: + if (ifnum != 0) + return -ENODEV; + if ((le16_to_cpu(dev->descriptor.idProduct) == NETCAM_PRODUCT_ID) || + (le16_to_cpu(dev->descriptor.idProduct) == VEO_800D_PRODUCT_ID)) + model = IBMCAM_MODEL_4; + else + model = IBMCAM_MODEL_2; + break; + case 0x0301: + if (ifnum != 0) + return -ENODEV; + model = IBMCAM_MODEL_3; + break; + default: + err("IBM camera with revision 0x%04x is not supported.", + le16_to_cpu(dev->descriptor.bcdDevice)); + return -ENODEV; + } + + /* Print detailed info on what we found so far */ + do { + char *brand = NULL; + switch (le16_to_cpu(dev->descriptor.idProduct)) { + case NETCAM_PRODUCT_ID: + brand = "IBM NetCamera"; + break; + case VEO_800C_PRODUCT_ID: + brand = "Veo Stingray [800C]"; + break; + case VEO_800D_PRODUCT_ID: + brand = "Veo Stingray [800D]"; + break; + case IBMCAM_PRODUCT_ID: + default: + brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ + break; + } + info("%s USB camera found (model %d, rev. 0x%04x)", + brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); + } while (0); + + /* Validate found interface: must have one ISO endpoint */ + nas = intf->num_altsetting; + if (debug > 0) + info("Number of alternate settings=%d.", nas); + if (nas < 2) { + err("Too few alternate settings for this camera!"); + return -ENODEV; + } + /* Validate all alternate settings */ + for (ix=0; ix < nas; ix++) { + const struct usb_host_interface *interface; + const struct usb_endpoint_descriptor *endpoint; + + interface = &intf->altsetting[ix]; + i = interface->desc.bAlternateSetting; + if (interface->desc.bNumEndpoints != 1) { + err("Interface %d. has %u. endpoints!", + ifnum, (unsigned)(interface->desc.bNumEndpoints)); + return -ENODEV; + } + endpoint = &interface->endpoint[0].desc; + if (video_ep == 0) + video_ep = endpoint->bEndpointAddress; + else if (video_ep != endpoint->bEndpointAddress) { + err("Alternate settings have different endpoint addresses!"); + return -ENODEV; + } + if ((endpoint->bmAttributes & 0x03) != 0x01) { + err("Interface %d. has non-ISO endpoint!", ifnum); + return -ENODEV; + } + if ((endpoint->bEndpointAddress & 0x80) == 0) { + err("Interface %d. has ISO OUT endpoint!", ifnum); + return -ENODEV; + } + if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { + if (inactInterface < 0) + inactInterface = i; + else { + err("More than one inactive alt. setting!"); + return -ENODEV; + } + } else { + if (actInterface < 0) { + actInterface = i; + maxPS = le16_to_cpu(endpoint->wMaxPacketSize); + if (debug > 0) + info("Active setting=%d. maxPS=%d.", i, maxPS); + } else + err("More than one active alt. setting! Ignoring #%d.", i); + } + } + if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) { + err("Failed to recognize the camera!"); + return -ENODEV; + } + + /* Validate options */ + switch (model) { + case IBMCAM_MODEL_1: + RESTRICT_TO_RANGE(lighting, 0, 2); + RESTRICT_TO_RANGE(size, SIZE_128x96, SIZE_352x288); + if (framerate < 0) + framerate = 2; + canvasX = 352; + canvasY = 288; + break; + case IBMCAM_MODEL_2: + RESTRICT_TO_RANGE(lighting, 0, 15); + RESTRICT_TO_RANGE(size, SIZE_176x144, SIZE_352x240); + if (framerate < 0) + framerate = 2; + canvasX = 352; + canvasY = 240; + break; + case IBMCAM_MODEL_3: + RESTRICT_TO_RANGE(lighting, 0, 15); /* FIXME */ + switch (size) { + case SIZE_160x120: + canvasX = 160; + canvasY = 120; + if (framerate < 0) + framerate = 2; + RESTRICT_TO_RANGE(framerate, 0, 5); + break; + default: + info("IBM camera: using 320x240"); + size = SIZE_320x240; + /* No break here */ + case SIZE_320x240: + canvasX = 320; + canvasY = 240; + if (framerate < 0) + framerate = 3; + RESTRICT_TO_RANGE(framerate, 0, 5); + break; + case SIZE_640x480: + canvasX = 640; + canvasY = 480; + framerate = 0; /* Slowest, and maybe even that is too fast */ + break; + } + break; + case IBMCAM_MODEL_4: + RESTRICT_TO_RANGE(lighting, 0, 2); + switch (size) { + case SIZE_128x96: + canvasX = 128; + canvasY = 96; + break; + case SIZE_160x120: + canvasX = 160; + canvasY = 120; + break; + default: + info("IBM NetCamera: using 176x144"); + size = SIZE_176x144; + /* No break here */ + case SIZE_176x144: + canvasX = 176; + canvasY = 144; + break; + case SIZE_320x240: + canvasX = 320; + canvasY = 240; + break; + case SIZE_352x288: + canvasX = 352; + canvasY = 288; + break; + } + break; + default: + err("IBM camera: Model %d. not supported!", model); + return -ENODEV; + } + + uvd = usbvideo_AllocateDevice(cams); + if (uvd != NULL) { + /* Here uvd is a fully allocated uvd object */ + uvd->flags = flags; + uvd->debug = debug; + uvd->dev = dev; + uvd->iface = ifnum; + uvd->ifaceAltInactive = inactInterface; + uvd->ifaceAltActive = actInterface; + uvd->video_endp = video_ep; + uvd->iso_packet_len = maxPS; + uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; + uvd->defaultPalette = VIDEO_PALETTE_RGB24; + uvd->canvas = VIDEOSIZE(canvasX, canvasY); + uvd->videosize = ibmcam_size_to_videosize(size); + + /* Initialize ibmcam-specific data */ + assert(IBMCAM_T(uvd) != NULL); + IBMCAM_T(uvd)->camera_model = model; + IBMCAM_T(uvd)->initialized = 0; + + ibmcam_configure_video(uvd); + + i = usbvideo_RegisterVideoDevice(uvd); + if (i != 0) { + err("usbvideo_RegisterVideoDevice() failed."); + uvd = NULL; + } + } + usb_set_intfdata (intf, uvd); + return 0; +} + + +static struct usb_device_id id_table[] = { + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) }, /* Model 1 */ + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) }, /* Model 3 */ + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ + { } /* Terminating entry */ +}; + +/* + * ibmcam_init() + * + * This code is run to initialize the driver. + * + * History: + * 1/27/00 Reworked to use statically allocated ibmcam structures. + * 21/10/00 Completely redesigned to use usbvideo services. + */ +static int __init ibmcam_init(void) +{ + struct usbvideo_cb cbTbl; + memset(&cbTbl, 0, sizeof(cbTbl)); + cbTbl.probe = ibmcam_probe; + cbTbl.setupOnOpen = ibmcam_setup_on_open; + cbTbl.videoStart = ibmcam_video_start; + cbTbl.videoStop = ibmcam_video_stop; + cbTbl.processData = ibmcam_ProcessIsocData; + cbTbl.postProcess = usbvideo_DeinterlaceFrame; + cbTbl.adjustPicture = ibmcam_adjust_picture; + cbTbl.getFPS = ibmcam_calculate_fps; + return usbvideo_register( + &cams, + MAX_IBMCAM, + sizeof(ibmcam_t), + "ibmcam", + &cbTbl, + THIS_MODULE, + id_table); +} + +static void __exit ibmcam_cleanup(void) +{ + usbvideo_Deregister(&cams); +} + +MODULE_DEVICE_TABLE(usb, id_table); + +module_init(ibmcam_init); +module_exit(ibmcam_cleanup); diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c new file mode 100644 index 000000000000..e2ede583518f --- /dev/null +++ b/drivers/media/video/usbvideo/konicawc.c @@ -0,0 +1,978 @@ +/* + * konicawc.c - konica webcam driver + * + * Author: Simon Evans + * + * Copyright (C) 2002 Simon Evans + * + * Licence: GPL + * + * Driver for USB webcams based on Konica chipset. This + * chipset is used in Intel YC76 camera. + * + */ + +#include +#include +#include +#include +#include + +#include "usbvideo.h" + +#define MAX_BRIGHTNESS 108 +#define MAX_CONTRAST 108 +#define MAX_SATURATION 108 +#define MAX_SHARPNESS 108 +#define MAX_WHITEBAL 372 +#define MAX_SPEED 6 + + +#define MAX_CAMERAS 1 + +#define DRIVER_VERSION "v1.4" +#define DRIVER_DESC "Konica Webcam driver" + +enum ctrl_req { + SetWhitebal = 0x01, + SetBrightness = 0x02, + SetSharpness = 0x03, + SetContrast = 0x04, + SetSaturation = 0x05, +}; + + +enum frame_sizes { + SIZE_160X120 = 0, + SIZE_160X136 = 1, + SIZE_176X144 = 2, + SIZE_320X240 = 3, + +}; + +#define MAX_FRAME_SIZE SIZE_320X240 + +static struct usbvideo *cams; + +#ifdef CONFIG_USB_DEBUG +static int debug; +#define DEBUG(n, format, arg...) \ + if (n <= debug) { \ + printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \ + } +#else +#define DEBUG(n, arg...) +static const int debug = 0; +#endif + + +/* Some default values for initial camera settings, + can be set by modprobe */ + +static int size; +static int speed = 6; /* Speed (fps) 0 (slowest) to 6 (fastest) */ +static int brightness = MAX_BRIGHTNESS/2; +static int contrast = MAX_CONTRAST/2; +static int saturation = MAX_SATURATION/2; +static int sharpness = MAX_SHARPNESS/2; +static int whitebal = 3*(MAX_WHITEBAL/4); + +static const int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 }; + +/* These FPS speeds are from the windows config box. They are + * indexed on size (0-2) and speed (0-6). Divide by 3 to get the + * real fps. + */ + +static const int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 }, + { 24, 40, 48, 60, 72, 80, 100 }, + { 18, 30, 36, 45, 54, 60, 75 }, + { 6, 10, 12, 15, 18, 21, 25 } }; + +struct cam_size { + u16 width; + u16 height; + u8 cmd; +}; + +static const struct cam_size camera_sizes[] = { { 160, 120, 0x7 }, + { 160, 136, 0xa }, + { 176, 144, 0x4 }, + { 320, 240, 0x5 } }; + +struct konicawc { + u8 brightness; /* camera uses 0 - 9, x11 for real value */ + u8 contrast; /* as above */ + u8 saturation; /* as above */ + u8 sharpness; /* as above */ + u8 white_bal; /* 0 - 33, x11 for real value */ + u8 speed; /* Stored as 0 - 6, used as index in spd_to_* (above) */ + u8 size; /* Frame Size */ + int height; + int width; + struct urb *sts_urb[USBVIDEO_NUMSBUF]; + u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC]; + struct urb *last_data_urb; + int lastframe; + int cur_frame_size; /* number of bytes in current frame size */ + int maxline; /* number of lines per frame */ + int yplanesz; /* Number of bytes in the Y plane */ + unsigned int buttonsts:1; +#ifdef CONFIG_INPUT + struct input_dev *input; + char input_physname[64]; +#endif +}; + + +#define konicawc_set_misc(uvd, req, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0) +#define konicawc_get_misc(uvd, req, value, index, buf, sz) konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz) +#define konicawc_set_value(uvd, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0) + + +static int konicawc_ctrl_msg(struct uvd *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len) +{ + int retval = usb_control_msg(uvd->dev, + dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0), + request, 0x40 | dir, value, index, buf, len, 1000); + return retval < 0 ? retval : 0; +} + + +static inline void konicawc_camera_on(struct uvd *uvd) +{ + DEBUG(0, "camera on"); + konicawc_set_misc(uvd, 0x2, 1, 0x0b); +} + + +static inline void konicawc_camera_off(struct uvd *uvd) +{ + DEBUG(0, "camera off"); + konicawc_set_misc(uvd, 0x2, 0, 0x0b); +} + + +static void konicawc_set_camera_size(struct uvd *uvd) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + + konicawc_set_misc(uvd, 0x2, camera_sizes[cam->size].cmd, 0x08); + cam->width = camera_sizes[cam->size].width; + cam->height = camera_sizes[cam->size].height; + cam->yplanesz = cam->height * cam->width; + cam->cur_frame_size = (cam->yplanesz * 3) / 2; + cam->maxline = cam->yplanesz / 256; + uvd->videosize = VIDEOSIZE(cam->width, cam->height); +} + + +static int konicawc_setup_on_open(struct uvd *uvd) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + + DEBUG(1, "setting brightness to %d (%d)", cam->brightness, + cam->brightness * 11); + konicawc_set_value(uvd, cam->brightness, SetBrightness); + DEBUG(1, "setting white balance to %d (%d)", cam->white_bal, + cam->white_bal * 11); + konicawc_set_value(uvd, cam->white_bal, SetWhitebal); + DEBUG(1, "setting contrast to %d (%d)", cam->contrast, + cam->contrast * 11); + konicawc_set_value(uvd, cam->contrast, SetContrast); + DEBUG(1, "setting saturation to %d (%d)", cam->saturation, + cam->saturation * 11); + konicawc_set_value(uvd, cam->saturation, SetSaturation); + DEBUG(1, "setting sharpness to %d (%d)", cam->sharpness, + cam->sharpness * 11); + konicawc_set_value(uvd, cam->sharpness, SetSharpness); + konicawc_set_camera_size(uvd); + cam->lastframe = -2; + cam->buttonsts = 0; + return 0; +} + + +static void konicawc_adjust_picture(struct uvd *uvd) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + + konicawc_camera_off(uvd); + DEBUG(1, "new brightness: %d", uvd->vpic.brightness); + uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness; + if(cam->brightness != uvd->vpic.brightness / 11) { + cam->brightness = uvd->vpic.brightness / 11; + DEBUG(1, "setting brightness to %d (%d)", cam->brightness, + cam->brightness * 11); + konicawc_set_value(uvd, cam->brightness, SetBrightness); + } + + DEBUG(1, "new contrast: %d", uvd->vpic.contrast); + uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : uvd->vpic.contrast; + if(cam->contrast != uvd->vpic.contrast / 11) { + cam->contrast = uvd->vpic.contrast / 11; + DEBUG(1, "setting contrast to %d (%d)", cam->contrast, + cam->contrast * 11); + konicawc_set_value(uvd, cam->contrast, SetContrast); + } + konicawc_camera_on(uvd); +} + +#ifdef CONFIG_INPUT + +static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) +{ + struct input_dev *input_dev; + + usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); + strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); + + cam->input = input_dev = input_allocate_device(); + if (!input_dev) { + warn("Not enough memory for camera's input device\n"); + return; + } + + input_dev->name = "Konicawc snapshot button"; + input_dev->phys = cam->input_physname; + usb_to_input_id(dev, &input_dev->id); + input_dev->cdev.dev = &dev->dev; + + input_dev->evbit[0] = BIT(EV_KEY); + input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); + + input_dev->private = cam; + + input_register_device(cam->input); +} + +static void konicawc_unregister_input(struct konicawc *cam) +{ + if (cam->input) { + input_unregister_device(cam->input); + cam->input = NULL; + } +} + +static void konicawc_report_buttonstat(struct konicawc *cam) +{ + if (cam->input) { + input_report_key(cam->input, BTN_0, cam->buttonsts); + input_sync(cam->input); + } +} + +#else + +static inline void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) { } +static inline void konicawc_unregister_input(struct konicawc *cam) { } +static inline void konicawc_report_buttonstat(struct konicawc *cam) { } + +#endif /* CONFIG_INPUT */ + +static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb) +{ + char *cdata; + int i, totlen = 0; + unsigned char *status = stsurb->transfer_buffer; + int keep = 0, discard = 0, bad = 0; + struct konicawc *cam = (struct konicawc *)uvd->user_data; + + for (i = 0; i < dataurb->number_of_packets; i++) { + int button = cam->buttonsts; + unsigned char sts; + int n = dataurb->iso_frame_desc[i].actual_length; + int st = dataurb->iso_frame_desc[i].status; + cdata = dataurb->transfer_buffer + + dataurb->iso_frame_desc[i].offset; + + /* Detect and ignore errored packets */ + if (st < 0) { + DEBUG(1, "Data error: packet=%d. len=%d. status=%d.", + i, n, st); + uvd->stats.iso_err_count++; + continue; + } + + /* Detect and ignore empty packets */ + if (n <= 0) { + uvd->stats.iso_skip_count++; + continue; + } + + /* See what the status data said about the packet */ + sts = *(status+stsurb->iso_frame_desc[i].offset); + + /* sts: 0x80-0xff: frame start with frame number (ie 0-7f) + * otherwise: + * bit 0 0: keep packet + * 1: drop packet (padding data) + * + * bit 4 0 button not clicked + * 1 button clicked + * button is used to `take a picture' (in software) + */ + + if(sts < 0x80) { + button = !!(sts & 0x40); + sts &= ~0x40; + } + + /* work out the button status, but don't do + anything with it for now */ + + if(button != cam->buttonsts) { + DEBUG(2, "button: %sclicked", button ? "" : "un"); + cam->buttonsts = button; + konicawc_report_buttonstat(cam); + } + + if(sts == 0x01) { /* drop frame */ + discard++; + continue; + } + + if((sts > 0x01) && (sts < 0x80)) { + info("unknown status %2.2x", sts); + bad++; + continue; + } + if(!sts && cam->lastframe == -2) { + DEBUG(2, "dropping frame looking for image start"); + continue; + } + + keep++; + if(sts & 0x80) { /* frame start */ + unsigned char marker[] = { 0, 0xff, 0, 0x00 }; + + if(cam->lastframe == -2) { + DEBUG(2, "found initial image"); + cam->lastframe = -1; + } + + marker[3] = sts & 0x7F; + RingQueue_Enqueue(&uvd->dp, marker, 4); + totlen += 4; + } + + totlen += n; /* Little local accounting */ + RingQueue_Enqueue(&uvd->dp, cdata, n); + } + DEBUG(8, "finished: keep = %d discard = %d bad = %d added %d bytes", + keep, discard, bad, totlen); + return totlen; +} + + +static void resubmit_urb(struct uvd *uvd, struct urb *urb) +{ + int i, ret; + for (i = 0; i < FRAMES_PER_DESC; i++) { + urb->iso_frame_desc[i].status = 0; + } + urb->dev = uvd->dev; + urb->status = 0; + ret = usb_submit_urb(urb, GFP_ATOMIC); + DEBUG(3, "submitting urb of length %d", urb->transfer_buffer_length); + if(ret) + err("usb_submit_urb error (%d)", ret); + +} + + +static void konicawc_isoc_irq(struct urb *urb, struct pt_regs *regs) +{ + struct uvd *uvd = urb->context; + struct konicawc *cam = (struct konicawc *)uvd->user_data; + + /* We don't want to do anything if we are about to be removed! */ + if (!CAMERA_IS_OPERATIONAL(uvd)) + return; + + if (!uvd->streaming) { + DEBUG(1, "Not streaming, but interrupt!"); + return; + } + + DEBUG(3, "got frame %d len = %d buflen =%d", urb->start_frame, urb->actual_length, urb->transfer_buffer_length); + + uvd->stats.urb_count++; + + if (urb->transfer_buffer_length > 32) { + cam->last_data_urb = urb; + return; + } + /* Copy the data received into ring queue */ + if(cam->last_data_urb) { + int len = 0; + if(urb->start_frame != cam->last_data_urb->start_frame) + err("Lost sync on frames"); + else if (!urb->status && !cam->last_data_urb->status) + len = konicawc_compress_iso(uvd, cam->last_data_urb, urb); + + resubmit_urb(uvd, cam->last_data_urb); + resubmit_urb(uvd, urb); + cam->last_data_urb = NULL; + uvd->stats.urb_length = len; + uvd->stats.data_count += len; + if(len) + RingQueue_WakeUpInterruptible(&uvd->dp); + return; + } + return; +} + + +static int konicawc_start_data(struct uvd *uvd) +{ + struct usb_device *dev = uvd->dev; + int i, errFlag; + struct konicawc *cam = (struct konicawc *)uvd->user_data; + int pktsz; + struct usb_interface *intf; + struct usb_host_interface *interface = NULL; + + intf = usb_ifnum_to_if(dev, uvd->iface); + if (intf) + interface = usb_altnum_to_altsetting(intf, + spd_to_iface[cam->speed]); + if (!interface) + return -ENXIO; + pktsz = le16_to_cpu(interface->endpoint[1].desc.wMaxPacketSize); + DEBUG(1, "pktsz = %d", pktsz); + if (!CAMERA_IS_OPERATIONAL(uvd)) { + err("Camera is not operational"); + return -EFAULT; + } + uvd->curframe = -1; + konicawc_camera_on(uvd); + /* Alternate interface 1 is is the biggest frame size */ + i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); + if (i < 0) { + err("usb_set_interface error"); + uvd->last_error = i; + return -EBUSY; + } + + /* We double buffer the Iso lists */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + int j, k; + struct urb *urb = uvd->sbuf[i].urb; + urb->dev = dev; + urb->context = uvd; + urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); + urb->interval = 1; + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = uvd->sbuf[i].data; + urb->complete = konicawc_isoc_irq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC; + for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = pktsz; + } + + urb = cam->sts_urb[i]; + urb->dev = dev; + urb->context = uvd; + urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1); + urb->interval = 1; + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = cam->sts_buf[i]; + urb->complete = konicawc_isoc_irq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = FRAMES_PER_DESC; + for (j=0; j < FRAMES_PER_DESC; j++) { + urb->iso_frame_desc[j].offset = j; + urb->iso_frame_desc[j].length = 1; + } + } + + cam->last_data_urb = NULL; + + /* Submit all URBs */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + errFlag = usb_submit_urb(cam->sts_urb[i], GFP_KERNEL); + if (errFlag) + err("usb_submit_isoc(%d) ret %d", i, errFlag); + + errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); + if (errFlag) + err ("usb_submit_isoc(%d) ret %d", i, errFlag); + } + + uvd->streaming = 1; + DEBUG(1, "streaming=1 video_endp=$%02x", uvd->video_endp); + return 0; +} + + +static void konicawc_stop_data(struct uvd *uvd) +{ + int i, j; + struct konicawc *cam; + + if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) + return; + + konicawc_camera_off(uvd); + uvd->streaming = 0; + cam = (struct konicawc *)uvd->user_data; + cam->last_data_urb = NULL; + + /* Unschedule all of the iso td's */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + usb_kill_urb(uvd->sbuf[i].urb); + usb_kill_urb(cam->sts_urb[i]); + } + + if (!uvd->remove_pending) { + /* Set packet size to 0 */ + j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); + if (j < 0) { + err("usb_set_interface() error %d.", j); + uvd->last_error = j; + } + } +} + + +static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + int maxline = cam->maxline; + int yplanesz = cam->yplanesz; + + assert(frame != NULL); + + DEBUG(5, "maxline = %d yplanesz = %d", maxline, yplanesz); + DEBUG(3, "Frame state = %d", frame->scanstate); + + if(frame->scanstate == ScanState_Scanning) { + int drop = 0; + int curframe; + int fdrops = 0; + DEBUG(3, "Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp)); + while(RingQueue_GetLength(&uvd->dp) >= 4) { + if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) && + (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) { + curframe = RING_QUEUE_PEEK(&uvd->dp, 3); + if(cam->lastframe >= 0) { + fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; + fdrops--; + if(fdrops) { + info("Dropped %d frames (%d -> %d)", fdrops, + cam->lastframe, curframe); + } + } + cam->lastframe = curframe; + frame->curline = 0; + frame->scanstate = ScanState_Lines; + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4); + break; + } + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); + drop++; + } + if(drop) + DEBUG(2, "dropped %d bytes looking for new frame", drop); + } + + if(frame->scanstate == ScanState_Scanning) + return; + + /* Try to move data from queue into frame buffer + * We get data in blocks of 384 bytes made up of: + * 256 Y, 64 U, 64 V. + * This needs to be written out as a Y plane, a U plane and a V plane. + */ + + while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) { + /* Y */ + RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256); + /* U */ + RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64); + /* V */ + RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64); + frame->seqRead_Length += 384; + frame->curline++; + } + /* See if we filled the frame */ + if (frame->curline == maxline) { + DEBUG(5, "got whole frame"); + + frame->frameState = FrameState_Done_Hold; + frame->curline = 0; + uvd->curframe = -1; + uvd->stats.frame_num++; + } +} + + +static int konicawc_find_fps(int size, int fps) +{ + int i; + + fps *= 3; + DEBUG(1, "konica_find_fps: size = %d fps = %d", size, fps); + if(fps <= spd_to_fps[size][0]) + return 0; + + if(fps >= spd_to_fps[size][MAX_SPEED]) + return MAX_SPEED; + + for(i = 0; i < MAX_SPEED; i++) { + if((fps >= spd_to_fps[size][i]) && (fps <= spd_to_fps[size][i+1])) { + DEBUG(2, "fps %d between %d and %d", fps, i, i+1); + if( (fps - spd_to_fps[size][i]) < (spd_to_fps[size][i+1] - fps)) + return i; + else + return i+1; + } + } + return MAX_SPEED+1; +} + + +static int konicawc_set_video_mode(struct uvd *uvd, struct video_window *vw) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + int newspeed = cam->speed; + int newsize; + int x = vw->width; + int y = vw->height; + int fps = vw->flags; + + if(x > 0 && y > 0) { + DEBUG(2, "trying to find size %d,%d", x, y); + for(newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) { + if((camera_sizes[newsize].width == x) && (camera_sizes[newsize].height == y)) + break; + } + } else { + newsize = cam->size; + } + + if(newsize > MAX_FRAME_SIZE) { + DEBUG(1, "couldn't find size %d,%d", x, y); + return -EINVAL; + } + + if(fps > 0) { + DEBUG(1, "trying to set fps to %d", fps); + newspeed = konicawc_find_fps(newsize, fps); + DEBUG(1, "find_fps returned %d (%d)", newspeed, spd_to_fps[newsize][newspeed]); + } + + if(newspeed > MAX_SPEED) + return -EINVAL; + + DEBUG(1, "setting size to %d speed to %d", newsize, newspeed); + if((newsize == cam->size) && (newspeed == cam->speed)) { + DEBUG(1, "Nothing to do"); + return 0; + } + DEBUG(0, "setting to %dx%d @ %d fps", camera_sizes[newsize].width, + camera_sizes[newsize].height, spd_to_fps[newsize][newspeed]/3); + + konicawc_stop_data(uvd); + uvd->ifaceAltActive = spd_to_iface[newspeed]; + DEBUG(1, "new interface = %d", uvd->ifaceAltActive); + cam->speed = newspeed; + + if(cam->size != newsize) { + cam->size = newsize; + konicawc_set_camera_size(uvd); + } + + /* Flush the input queue and clear any current frame in progress */ + + RingQueue_Flush(&uvd->dp); + cam->lastframe = -2; + if(uvd->curframe != -1) { + uvd->frame[uvd->curframe].curline = 0; + uvd->frame[uvd->curframe].seqRead_Length = 0; + uvd->frame[uvd->curframe].seqRead_Index = 0; + } + + konicawc_start_data(uvd); + return 0; +} + + +static int konicawc_calculate_fps(struct uvd *uvd) +{ + struct konicawc *cam = uvd->user_data; + return spd_to_fps[cam->size][cam->speed]/3; +} + + +static void konicawc_configure_video(struct uvd *uvd) +{ + struct konicawc *cam = (struct konicawc *)uvd->user_data; + u8 buf[2]; + + memset(&uvd->vpic, 0, sizeof(uvd->vpic)); + memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); + + RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS); + RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST); + RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION); + RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS); + RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL); + + cam->brightness = brightness / 11; + cam->contrast = contrast / 11; + cam->saturation = saturation / 11; + cam->sharpness = sharpness / 11; + cam->white_bal = whitebal / 11; + + uvd->vpic.colour = 108; + uvd->vpic.hue = 108; + uvd->vpic.brightness = brightness; + uvd->vpic.contrast = contrast; + uvd->vpic.whiteness = whitebal; + uvd->vpic.depth = 6; + uvd->vpic.palette = VIDEO_PALETTE_YUV420P; + + memset(&uvd->vcap, 0, sizeof(uvd->vcap)); + strcpy(uvd->vcap.name, "Konica Webcam"); + uvd->vcap.type = VID_TYPE_CAPTURE; + uvd->vcap.channels = 1; + uvd->vcap.audios = 0; + uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width; + uvd->vcap.minheight = camera_sizes[SIZE_160X120].height; + uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width; + uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height; + + memset(&uvd->vchan, 0, sizeof(uvd->vchan)); + uvd->vchan.flags = 0 ; + uvd->vchan.tuners = 0; + uvd->vchan.channel = 0; + uvd->vchan.type = VIDEO_TYPE_CAMERA; + strcpy(uvd->vchan.name, "Camera"); + + /* Talk to device */ + DEBUG(1, "device init"); + if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) + DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); + if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) + DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); + if(konicawc_set_misc(uvd, 0x2, 0, 0xd)) + DEBUG(2, "2,0,d failed"); + DEBUG(1, "setting initial values"); +} + +static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct uvd *uvd = NULL; + int ix, i, nas; + int actInterface=-1, inactInterface=-1, maxPS=0; + unsigned char video_ep = 0; + + DEBUG(1, "konicawc_probe(%p)", intf); + + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + info("Konica Webcam (rev. 0x%04x)", le16_to_cpu(dev->descriptor.bcdDevice)); + RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); + + /* Validate found interface: must have one ISO endpoint */ + nas = intf->num_altsetting; + if (nas != 8) { + err("Incorrect number of alternate settings (%d) for this camera!", nas); + return -ENODEV; + } + /* Validate all alternate settings */ + for (ix=0; ix < nas; ix++) { + const struct usb_host_interface *interface; + const struct usb_endpoint_descriptor *endpoint; + + interface = &intf->altsetting[ix]; + i = interface->desc.bAlternateSetting; + if (interface->desc.bNumEndpoints != 2) { + err("Interface %d. has %u. endpoints!", + interface->desc.bInterfaceNumber, + (unsigned)(interface->desc.bNumEndpoints)); + return -ENODEV; + } + endpoint = &interface->endpoint[1].desc; + DEBUG(1, "found endpoint: addr: 0x%2.2x maxps = 0x%4.4x", + endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize)); + if (video_ep == 0) + video_ep = endpoint->bEndpointAddress; + else if (video_ep != endpoint->bEndpointAddress) { + err("Alternate settings have different endpoint addresses!"); + return -ENODEV; + } + if ((endpoint->bmAttributes & 0x03) != 0x01) { + err("Interface %d. has non-ISO endpoint!", + interface->desc.bInterfaceNumber); + return -ENODEV; + } + if ((endpoint->bEndpointAddress & 0x80) == 0) { + err("Interface %d. has ISO OUT endpoint!", + interface->desc.bInterfaceNumber); + return -ENODEV; + } + if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { + if (inactInterface < 0) + inactInterface = i; + else { + err("More than one inactive alt. setting!"); + return -ENODEV; + } + } else { + if (i == spd_to_iface[speed]) { + /* This one is the requested one */ + actInterface = i; + } + } + if (le16_to_cpu(endpoint->wMaxPacketSize) > maxPS) + maxPS = le16_to_cpu(endpoint->wMaxPacketSize); + } + if(actInterface == -1) { + err("Cant find required endpoint"); + return -ENODEV; + } + + DEBUG(1, "Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS); + + uvd = usbvideo_AllocateDevice(cams); + if (uvd != NULL) { + struct konicawc *cam = (struct konicawc *)(uvd->user_data); + /* Here uvd is a fully allocated uvd object */ + for(i = 0; i < USBVIDEO_NUMSBUF; i++) { + cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); + if(cam->sts_urb[i] == NULL) { + while(i--) { + usb_free_urb(cam->sts_urb[i]); + } + err("can't allocate urbs"); + return -ENOMEM; + } + } + cam->speed = speed; + RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); + cam->width = camera_sizes[size].width; + cam->height = camera_sizes[size].height; + cam->size = size; + + uvd->flags = 0; + uvd->debug = debug; + uvd->dev = dev; + uvd->iface = intf->altsetting->desc.bInterfaceNumber; + uvd->ifaceAltInactive = inactInterface; + uvd->ifaceAltActive = actInterface; + uvd->video_endp = video_ep; + uvd->iso_packet_len = maxPS; + uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P; + uvd->defaultPalette = VIDEO_PALETTE_YUV420P; + uvd->canvas = VIDEOSIZE(320, 240); + uvd->videosize = VIDEOSIZE(cam->width, cam->height); + + /* Initialize konicawc specific data */ + konicawc_configure_video(uvd); + + i = usbvideo_RegisterVideoDevice(uvd); + uvd->max_frame_size = (320 * 240 * 3)/2; + if (i != 0) { + err("usbvideo_RegisterVideoDevice() failed."); + uvd = NULL; + } + + konicawc_register_input(cam, dev); + } + + if (uvd) { + usb_set_intfdata (intf, uvd); + return 0; + } + return -EIO; +} + + +static void konicawc_free_uvd(struct uvd *uvd) +{ + int i; + struct konicawc *cam = (struct konicawc *)uvd->user_data; + + konicawc_unregister_input(cam); + + for (i = 0; i < USBVIDEO_NUMSBUF; i++) { + usb_free_urb(cam->sts_urb[i]); + cam->sts_urb[i] = NULL; + } +} + + +static struct usb_device_id id_table[] = { + { USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */ + { } /* Terminating entry */ +}; + + +static int __init konicawc_init(void) +{ + struct usbvideo_cb cbTbl; + info(DRIVER_DESC " " DRIVER_VERSION); + memset(&cbTbl, 0, sizeof(cbTbl)); + cbTbl.probe = konicawc_probe; + cbTbl.setupOnOpen = konicawc_setup_on_open; + cbTbl.processData = konicawc_process_isoc; + cbTbl.getFPS = konicawc_calculate_fps; + cbTbl.setVideoMode = konicawc_set_video_mode; + cbTbl.startDataPump = konicawc_start_data; + cbTbl.stopDataPump = konicawc_stop_data; + cbTbl.adjustPicture = konicawc_adjust_picture; + cbTbl.userFree = konicawc_free_uvd; + return usbvideo_register( + &cams, + MAX_CAMERAS, + sizeof(struct konicawc), + "konicawc", + &cbTbl, + THIS_MODULE, + id_table); +} + + +static void __exit konicawc_cleanup(void) +{ + usbvideo_Deregister(&cams); +} + + +MODULE_DEVICE_TABLE(usb, id_table); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Simon Evans "); +MODULE_DESCRIPTION(DRIVER_DESC); +module_param(speed, int, 0); +MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)"); +module_param(size, int, 0); +MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240"); +module_param(brightness, int, 0); +MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108"); +module_param(contrast, int, 0); +MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108"); +module_param(saturation, int, 0); +MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108"); +module_param(sharpness, int, 0); +MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108"); +module_param(whitebal, int, 0); +MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363"); + +#ifdef CONFIG_USB_DEBUG +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); +#endif + +module_init(konicawc_init); +module_exit(konicawc_cleanup); diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c new file mode 100644 index 000000000000..75ff755224df --- /dev/null +++ b/drivers/media/video/usbvideo/ultracam.c @@ -0,0 +1,679 @@ +/* + * USB NB Camera driver + * + * HISTORY: + * 25-Dec-2002 Dmitri Removed lighting, sharpness parameters, methods. + */ + +#include +#include +#include +#include + +#include "usbvideo.h" + +#define ULTRACAM_VENDOR_ID 0x0461 +#define ULTRACAM_PRODUCT_ID 0x0813 + +#define MAX_CAMERAS 4 /* How many devices we allow to connect */ + +/* + * This structure lives in uvd_t->user field. + */ +typedef struct { + int initialized; /* Had we already sent init sequence? */ + int camera_model; /* What type of IBM camera we got? */ + int has_hdr; +} ultracam_t; +#define ULTRACAM_T(uvd) ((ultracam_t *)((uvd)->user_data)) + +static struct usbvideo *cams = NULL; + +static int debug = 0; + +static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ + +static const int min_canvasWidth = 8; +static const int min_canvasHeight = 4; + +#define FRAMERATE_MIN 0 +#define FRAMERATE_MAX 6 +static int framerate = -1; + +/* + * Here we define several initialization variables. They may + * be used to automatically set color, hue, brightness and + * contrast to desired values. This is particularly useful in + * case of webcams (which have no controls and no on-screen + * output) and also when a client V4L software is used that + * does not have some of those controls. In any case it's + * good to have startup values as options. + * + * These values are all in [0..255] range. This simplifies + * operation. Note that actual values of V4L variables may + * be scaled up (as much as << 8). User can see that only + * on overlay output, however, or through a V4L client. + */ +static int init_brightness = 128; +static int init_contrast = 192; +static int init_color = 128; +static int init_hue = 128; +static int hue_correction = 128; + +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); +module_param(flags, int, 0); +MODULE_PARM_DESC(flags, + "Bitfield: 0=VIDIOCSYNC, " + "1=B/W, " + "2=show hints, " + "3=show stats, " + "4=test pattern, " + "5=separate frames, " + "6=clean frames"); +module_param(framerate, int, 0); +MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); + +module_param(init_brightness, int, 0); +MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); +module_param(init_contrast, int, 0); +MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); +module_param(init_color, int, 0); +MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)"); +module_param(init_hue, int, 0); +MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); +module_param(hue_correction, int, 0); +MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); + +/* + * ultracam_ProcessIsocData() + * + * Generic routine to parse the ring queue data. It employs either + * ultracam_find_header() or ultracam_parse_lines() to do most + * of work. + * + * 02-Nov-2000 First (mostly dummy) version. + * 06-Nov-2000 Rewrote to dump all data into frame. + */ +static void ultracam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame) +{ + int n; + + assert(uvd != NULL); + assert(frame != NULL); + + /* Try to move data from queue into frame buffer */ + n = RingQueue_GetLength(&uvd->dp); + if (n > 0) { + int m; + /* See how much spare we have left */ + m = uvd->max_frame_size - frame->seqRead_Length; + if (n > m) + n = m; + /* Now move that much data into frame buffer */ + RingQueue_Dequeue( + &uvd->dp, + frame->data + frame->seqRead_Length, + m); + frame->seqRead_Length += m; + } + /* See if we filled the frame */ + if (frame->seqRead_Length >= uvd->max_frame_size) { + frame->frameState = FrameState_Done; + uvd->curframe = -1; + uvd->stats.frame_num++; + } +} + +/* + * ultracam_veio() + * + * History: + * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. + */ +static int ultracam_veio( + struct uvd *uvd, + unsigned char req, + unsigned short value, + unsigned short index, + int is_out) +{ + static const char proc[] = "ultracam_veio"; + unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */; + int i; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return 0; + + if (!is_out) { + i = usb_control_msg( + uvd->dev, + usb_rcvctrlpipe(uvd->dev, 0), + req, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + index, + cp, + sizeof(cp), + 1000); +#if 1 + info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " + "(req=$%02x val=$%04x ind=$%04x)", + cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], + req, value, index); +#endif + } else { + i = usb_control_msg( + uvd->dev, + usb_sndctrlpipe(uvd->dev, 0), + req, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + index, + NULL, + 0, + 1000); + } + if (i < 0) { + err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.", + proc, i); + uvd->last_error = i; + } + return i; +} + +/* + * ultracam_calculate_fps() + */ +static int ultracam_calculate_fps(struct uvd *uvd) +{ + return 3 + framerate*4 + framerate/2; +} + +/* + * ultracam_adjust_contrast() + */ +static void ultracam_adjust_contrast(struct uvd *uvd) +{ +} + +/* + * ultracam_set_brightness() + * + * This procedure changes brightness of the picture. + */ +static void ultracam_set_brightness(struct uvd *uvd) +{ +} + +static void ultracam_set_hue(struct uvd *uvd) +{ +} + +/* + * ultracam_adjust_picture() + * + * This procedure gets called from V4L interface to update picture settings. + * Here we change brightness and contrast. + */ +static void ultracam_adjust_picture(struct uvd *uvd) +{ + ultracam_adjust_contrast(uvd); + ultracam_set_brightness(uvd); + ultracam_set_hue(uvd); +} + +/* + * ultracam_video_stop() + * + * This code tells camera to stop streaming. The interface remains + * configured and bandwidth - claimed. + */ +static void ultracam_video_stop(struct uvd *uvd) +{ +} + +/* + * ultracam_reinit_iso() + * + * This procedure sends couple of commands to the camera and then + * resets the video pipe. This sequence was observed to reinit the + * camera or, at least, to initiate ISO data stream. + */ +static void ultracam_reinit_iso(struct uvd *uvd, int do_stop) +{ +} + +static void ultracam_video_start(struct uvd *uvd) +{ + ultracam_reinit_iso(uvd, 0); +} + +static int ultracam_resetPipe(struct uvd *uvd) +{ + usb_clear_halt(uvd->dev, uvd->video_endp); + return 0; +} + +static int ultracam_alternateSetting(struct uvd *uvd, int setting) +{ + static const char proc[] = "ultracam_alternateSetting"; + int i; + i = usb_set_interface(uvd->dev, uvd->iface, setting); + if (i < 0) { + err("%s: usb_set_interface error", proc); + uvd->last_error = i; + return -EBUSY; + } + return 0; +} + +/* + * Return negative code on failure, 0 on success. + */ +static int ultracam_setup_on_open(struct uvd *uvd) +{ + int setup_ok = 0; /* Success by default */ + /* Send init sequence only once, it's large! */ + if (!ULTRACAM_T(uvd)->initialized) { + ultracam_alternateSetting(uvd, 0x04); + ultracam_alternateSetting(uvd, 0x00); + ultracam_veio(uvd, 0x02, 0x0004, 0x000b, 1); + ultracam_veio(uvd, 0x02, 0x0001, 0x0005, 1); + ultracam_veio(uvd, 0x02, 0x8000, 0x0000, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1); + ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x0002, 1); + ultracam_veio(uvd, 0x00, 0x000c, 0x0003, 1); + ultracam_veio(uvd, 0x00, 0x000b, 0x0004, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x0005, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x0006, 1); + ultracam_veio(uvd, 0x00, 0x0079, 0x0007, 1); + ultracam_veio(uvd, 0x00, 0x003b, 0x0008, 1); + ultracam_veio(uvd, 0x00, 0x0002, 0x000f, 1); + ultracam_veio(uvd, 0x00, 0x0001, 0x0010, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x0011, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, 1); + ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, 1); + ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, 1); + ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, 1); + ultracam_veio(uvd, 0x01, 0x0010, 0x0002, 1); + ultracam_veio(uvd, 0x01, 0x0066, 0x0007, 1); + ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1); + ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1); + ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1); + ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1); + ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1); + ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1); + ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1); + ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1); + ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1); + ultracam_veio(uvd, 0x01, 0x000b, 0x0011, 1); + ultracam_veio(uvd, 0x01, 0x0001, 0x0012, 1); + ultracam_veio(uvd, 0x01, 0x0000, 0x0013, 1); + ultracam_veio(uvd, 0x01, 0x0000, 0x0014, 1); + ultracam_veio(uvd, 0x01, 0x0087, 0x0051, 1); + ultracam_veio(uvd, 0x01, 0x0040, 0x0052, 1); + ultracam_veio(uvd, 0x01, 0x0058, 0x0053, 1); + ultracam_veio(uvd, 0x01, 0x0040, 0x0054, 1); + ultracam_veio(uvd, 0x01, 0x0000, 0x0040, 1); + ultracam_veio(uvd, 0x01, 0x0010, 0x0041, 1); + ultracam_veio(uvd, 0x01, 0x0020, 0x0042, 1); + ultracam_veio(uvd, 0x01, 0x0030, 0x0043, 1); + ultracam_veio(uvd, 0x01, 0x0040, 0x0044, 1); + ultracam_veio(uvd, 0x01, 0x0050, 0x0045, 1); + ultracam_veio(uvd, 0x01, 0x0060, 0x0046, 1); + ultracam_veio(uvd, 0x01, 0x0070, 0x0047, 1); + ultracam_veio(uvd, 0x01, 0x0080, 0x0048, 1); + ultracam_veio(uvd, 0x01, 0x0090, 0x0049, 1); + ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, 1); + ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, 1); + ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, 1); + ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, 1); + ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, 1); + ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, 1); + ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, 1); + ultracam_veio(uvd, 0x01, 0x0000, 0x0056, 1); + ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1); + ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, 1); + ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, 1); + ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); + ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); + ultracam_veio(uvd, 0x02, 0xc040, 0x0001, 1); + ultracam_veio(uvd, 0x01, 0x0000, 0x0008, 0); + ultracam_veio(uvd, 0x01, 0x0000, 0x0009, 0); + ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 0); + ultracam_veio(uvd, 0x01, 0x0000, 0x000b, 0); + ultracam_veio(uvd, 0x01, 0x0000, 0x000c, 0); + ultracam_veio(uvd, 0x01, 0x0000, 0x000d, 0); + ultracam_veio(uvd, 0x01, 0x0000, 0x000e, 0); + ultracam_veio(uvd, 0x01, 0x0000, 0x000f, 0); + ultracam_veio(uvd, 0x01, 0x0000, 0x0010, 0); + ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1); + ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1); + ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1); + ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1); + ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1); + ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1); + ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1); + ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1); + ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1); + ultracam_veio(uvd, 0x01, 0x0000, 0x0001, 0); + ultracam_veio(uvd, 0x01, 0x0064, 0x0001, 1); + ultracam_veio(uvd, 0x01, 0x0059, 0x0051, 1); + ultracam_veio(uvd, 0x01, 0x003f, 0x0052, 1); + ultracam_veio(uvd, 0x01, 0x0094, 0x0053, 1); + ultracam_veio(uvd, 0x01, 0x00ff, 0x0011, 1); + ultracam_veio(uvd, 0x01, 0x0003, 0x0012, 1); + ultracam_veio(uvd, 0x01, 0x00f7, 0x0013, 1); + ultracam_veio(uvd, 0x00, 0x0009, 0x0011, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x0001, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1); + ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, 1); + ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, 1); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); + ultracam_alternateSetting(uvd, 0x04); + ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1); + ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1); + ultracam_veio(uvd, 0x02, 0x0000, 0x0006, 1); + ultracam_veio(uvd, 0x02, 0x9000, 0x0007, 1); + ultracam_veio(uvd, 0x02, 0x0042, 0x0001, 1); + ultracam_veio(uvd, 0x02, 0x0000, 0x000b, 0); + ultracam_resetPipe(uvd); + ULTRACAM_T(uvd)->initialized = (setup_ok != 0); + } + return setup_ok; +} + +static void ultracam_configure_video(struct uvd *uvd) +{ + if (uvd == NULL) + return; + + RESTRICT_TO_RANGE(init_brightness, 0, 255); + RESTRICT_TO_RANGE(init_contrast, 0, 255); + RESTRICT_TO_RANGE(init_color, 0, 255); + RESTRICT_TO_RANGE(init_hue, 0, 255); + RESTRICT_TO_RANGE(hue_correction, 0, 255); + + memset(&uvd->vpic, 0, sizeof(uvd->vpic)); + memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); + + uvd->vpic.colour = init_color << 8; + uvd->vpic.hue = init_hue << 8; + uvd->vpic.brightness = init_brightness << 8; + uvd->vpic.contrast = init_contrast << 8; + uvd->vpic.whiteness = 105 << 8; /* This one isn't used */ + uvd->vpic.depth = 24; + uvd->vpic.palette = VIDEO_PALETTE_RGB24; + + memset(&uvd->vcap, 0, sizeof(uvd->vcap)); + strcpy(uvd->vcap.name, "IBM Ultra Camera"); + uvd->vcap.type = VID_TYPE_CAPTURE; + uvd->vcap.channels = 1; + uvd->vcap.audios = 0; + uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas); + uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas); + uvd->vcap.minwidth = min_canvasWidth; + uvd->vcap.minheight = min_canvasHeight; + + memset(&uvd->vchan, 0, sizeof(uvd->vchan)); + uvd->vchan.flags = 0; + uvd->vchan.tuners = 0; + uvd->vchan.channel = 0; + uvd->vchan.type = VIDEO_TYPE_CAMERA; + strcpy(uvd->vchan.name, "Camera"); +} + +/* + * ultracam_probe() + * + * This procedure queries device descriptor and accepts the interface + * if it looks like our camera. + * + * History: + * 12-Nov-2000 Reworked to comply with new probe() signature. + * 23-Jan-2001 Added compatibility with 2.2.x kernels. + */ +static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id *devid) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct uvd *uvd = NULL; + int ix, i, nas; + int actInterface=-1, inactInterface=-1, maxPS=0; + unsigned char video_ep = 0; + + if (debug >= 1) + info("ultracam_probe(%p)", intf); + + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + info("IBM Ultra camera found (rev. 0x%04x)", + le16_to_cpu(dev->descriptor.bcdDevice)); + + /* Validate found interface: must have one ISO endpoint */ + nas = intf->num_altsetting; + if (debug > 0) + info("Number of alternate settings=%d.", nas); + if (nas < 8) { + err("Too few alternate settings for this camera!"); + return -ENODEV; + } + /* Validate all alternate settings */ + for (ix=0; ix < nas; ix++) { + const struct usb_host_interface *interface; + const struct usb_endpoint_descriptor *endpoint; + + interface = &intf->altsetting[ix]; + i = interface->desc.bAlternateSetting; + if (interface->desc.bNumEndpoints != 1) { + err("Interface %d. has %u. endpoints!", + interface->desc.bInterfaceNumber, + (unsigned)(interface->desc.bNumEndpoints)); + return -ENODEV; + } + endpoint = &interface->endpoint[0].desc; + if (video_ep == 0) + video_ep = endpoint->bEndpointAddress; + else if (video_ep != endpoint->bEndpointAddress) { + err("Alternate settings have different endpoint addresses!"); + return -ENODEV; + } + if ((endpoint->bmAttributes & 0x03) != 0x01) { + err("Interface %d. has non-ISO endpoint!", + interface->desc.bInterfaceNumber); + return -ENODEV; + } + if ((endpoint->bEndpointAddress & 0x80) == 0) { + err("Interface %d. has ISO OUT endpoint!", + interface->desc.bInterfaceNumber); + return -ENODEV; + } + if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { + if (inactInterface < 0) + inactInterface = i; + else { + err("More than one inactive alt. setting!"); + return -ENODEV; + } + } else { + if (actInterface < 0) { + actInterface = i; + maxPS = le16_to_cpu(endpoint->wMaxPacketSize); + if (debug > 0) + info("Active setting=%d. maxPS=%d.", i, maxPS); + } else { + /* Got another active alt. setting */ + if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) { + /* This one is better! */ + actInterface = i; + maxPS = le16_to_cpu(endpoint->wMaxPacketSize); + if (debug > 0) { + info("Even better ctive setting=%d. maxPS=%d.", + i, maxPS); + } + } + } + } + } + if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) { + err("Failed to recognize the camera!"); + return -ENODEV; + } + + uvd = usbvideo_AllocateDevice(cams); + if (uvd != NULL) { + /* Here uvd is a fully allocated uvd object */ + uvd->flags = flags; + uvd->debug = debug; + uvd->dev = dev; + uvd->iface = intf->altsetting->desc.bInterfaceNumber; + uvd->ifaceAltInactive = inactInterface; + uvd->ifaceAltActive = actInterface; + uvd->video_endp = video_ep; + uvd->iso_packet_len = maxPS; + uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; + uvd->defaultPalette = VIDEO_PALETTE_RGB24; + uvd->canvas = VIDEOSIZE(640, 480); /* FIXME */ + uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/ + + /* Initialize ibmcam-specific data */ + assert(ULTRACAM_T(uvd) != NULL); + ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */ + ULTRACAM_T(uvd)->initialized = 0; + + ultracam_configure_video(uvd); + + i = usbvideo_RegisterVideoDevice(uvd); + if (i != 0) { + err("usbvideo_RegisterVideoDevice() failed."); + uvd = NULL; + } + } + + if (uvd) { + usb_set_intfdata (intf, uvd); + return 0; + } + return -EIO; +} + + +static struct usb_device_id id_table[] = { + { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) }, + { } /* Terminating entry */ +}; + +/* + * ultracam_init() + * + * This code is run to initialize the driver. + */ +static int __init ultracam_init(void) +{ + struct usbvideo_cb cbTbl; + memset(&cbTbl, 0, sizeof(cbTbl)); + cbTbl.probe = ultracam_probe; + cbTbl.setupOnOpen = ultracam_setup_on_open; + cbTbl.videoStart = ultracam_video_start; + cbTbl.videoStop = ultracam_video_stop; + cbTbl.processData = ultracam_ProcessIsocData; + cbTbl.postProcess = usbvideo_DeinterlaceFrame; + cbTbl.adjustPicture = ultracam_adjust_picture; + cbTbl.getFPS = ultracam_calculate_fps; + return usbvideo_register( + &cams, + MAX_CAMERAS, + sizeof(ultracam_t), + "ultracam", + &cbTbl, + THIS_MODULE, + id_table); +} + +static void __exit ultracam_cleanup(void) +{ + usbvideo_Deregister(&cams); +} + +MODULE_DEVICE_TABLE(usb, id_table); +MODULE_LICENSE("GPL"); + +module_init(ultracam_init); +module_exit(ultracam_cleanup); diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c new file mode 100644 index 000000000000..0b51fae720a9 --- /dev/null +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -0,0 +1,2190 @@ +/* + * 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; 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 +#include + +#include + +#include "usbvideo.h" + +#if defined(MAP_NR) +#define virt_to_page(v) MAP_NR(v) /* Kernels 2.2.x */ +#endif + +static int video_nr = -1; +module_param(video_nr, int, 0); + +/* + * Local prototypes. + */ +static void usbvideo_Disconnect(struct usb_interface *intf); +static void usbvideo_CameraRelease(struct uvd *uvd); + +static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma); +static int usbvideo_v4l_open(struct inode *inode, struct file *file); +static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos); +static int usbvideo_v4l_close(struct inode *inode, struct file *file); + +static int usbvideo_StartDataPump(struct uvd *uvd); +static void usbvideo_StopDataPump(struct uvd *uvd); +static int usbvideo_GetFrame(struct uvd *uvd, int frameNum); +static int usbvideo_NewFrame(struct uvd *uvd, int framenum); +static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, + struct usbvideo_frame *frame); + +/*******************************/ +/* Memory management functions */ +/*******************************/ +static void *usbvideo_rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + +static void usbvideo_rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + +static void RingQueue_Initialize(struct RingQueue *rq) +{ + assert(rq != NULL); + init_waitqueue_head(&rq->wqh); +} + +static void RingQueue_Allocate(struct RingQueue *rq, int rqLen) +{ + /* Make sure the requested size is a power of 2 and + round up if necessary. This allows index wrapping + using masks rather than modulo */ + + int i = 1; + assert(rq != NULL); + assert(rqLen > 0); + + while(rqLen >> i) + i++; + if(rqLen != 1 << (i-1)) + rqLen = 1 << i; + + rq->length = rqLen; + rq->ri = rq->wi = 0; + rq->queue = usbvideo_rvmalloc(rq->length); + assert(rq->queue != NULL); +} + +static int RingQueue_IsAllocated(const struct RingQueue *rq) +{ + if (rq == NULL) + return 0; + return (rq->queue != NULL) && (rq->length > 0); +} + +static void RingQueue_Free(struct RingQueue *rq) +{ + assert(rq != NULL); + if (RingQueue_IsAllocated(rq)) { + usbvideo_rvfree(rq->queue, rq->length); + rq->queue = NULL; + rq->length = 0; + } +} + +int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len) +{ + int rql, toread; + + assert(rq != NULL); + assert(dst != NULL); + + rql = RingQueue_GetLength(rq); + if(!rql) + return 0; + + /* Clip requested length to available data */ + if(len > rql) + len = rql; + + toread = len; + if(rq->ri > rq->wi) { + /* Read data from tail */ + int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri; + memcpy(dst, rq->queue + rq->ri, read); + toread -= read; + dst += read; + rq->ri = (rq->ri + read) & (rq->length-1); + } + if(toread) { + /* Read data from head */ + memcpy(dst, rq->queue + rq->ri, toread); + rq->ri = (rq->ri + toread) & (rq->length-1); + } + return len; +} + +EXPORT_SYMBOL(RingQueue_Dequeue); + +int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n) +{ + int enqueued = 0; + + assert(rq != NULL); + assert(cdata != NULL); + assert(rq->length > 0); + while (n > 0) { + int m, q_avail; + + /* Calculate the largest chunk that fits the tail of the ring */ + q_avail = rq->length - rq->wi; + if (q_avail <= 0) { + rq->wi = 0; + q_avail = rq->length; + } + m = n; + assert(q_avail > 0); + if (m > q_avail) + m = q_avail; + + memcpy(rq->queue + rq->wi, cdata, m); + RING_QUEUE_ADVANCE_INDEX(rq, wi, m); + cdata += m; + enqueued += m; + n -= m; + } + return enqueued; +} + +EXPORT_SYMBOL(RingQueue_Enqueue); + +static void RingQueue_InterruptibleSleepOn(struct RingQueue *rq) +{ + assert(rq != NULL); + interruptible_sleep_on(&rq->wqh); +} + +void RingQueue_WakeUpInterruptible(struct RingQueue *rq) +{ + assert(rq != NULL); + if (waitqueue_active(&rq->wqh)) + wake_up_interruptible(&rq->wqh); +} + +EXPORT_SYMBOL(RingQueue_WakeUpInterruptible); + +void RingQueue_Flush(struct RingQueue *rq) +{ + assert(rq != NULL); + rq->ri = 0; + rq->wi = 0; +} + +EXPORT_SYMBOL(RingQueue_Flush); + + +/* + * usbvideo_VideosizeToString() + * + * This procedure converts given videosize value to readable string. + * + * History: + * 07-Aug-2000 Created. + * 19-Oct-2000 Reworked for usbvideo module. + */ +static void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs) +{ + char tmp[40]; + int n; + + n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs)); + assert(n < sizeof(tmp)); + if ((buf == NULL) || (bufLen < n)) + err("usbvideo_VideosizeToString: buffer is too small."); + else + memmove(buf, tmp, n); +} + +/* + * usbvideo_OverlayChar() + * + * History: + * 01-Feb-2000 Created. + */ +static void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame, + int x, int y, int ch) +{ + static const unsigned short digits[16] = { + 0xF6DE, /* 0 */ + 0x2492, /* 1 */ + 0xE7CE, /* 2 */ + 0xE79E, /* 3 */ + 0xB792, /* 4 */ + 0xF39E, /* 5 */ + 0xF3DE, /* 6 */ + 0xF492, /* 7 */ + 0xF7DE, /* 8 */ + 0xF79E, /* 9 */ + 0x77DA, /* a */ + 0xD75C, /* b */ + 0xF24E, /* c */ + 0xD6DC, /* d */ + 0xF34E, /* e */ + 0xF348 /* f */ + }; + unsigned short digit; + int ix, iy; + + if ((uvd == NULL) || (frame == NULL)) + return; + + if (ch >= '0' && ch <= '9') + ch -= '0'; + else if (ch >= 'A' && ch <= 'F') + ch = 10 + (ch - 'A'); + else if (ch >= 'a' && ch <= 'f') + ch = 10 + (ch - 'a'); + else + return; + digit = digits[ch]; + + for (iy=0; iy < 5; iy++) { + for (ix=0; ix < 3; ix++) { + if (digit & 0x8000) { + if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) { +/* TODO */ RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF); + } + } + digit = digit << 1; + } + } +} + +/* + * usbvideo_OverlayString() + * + * History: + * 01-Feb-2000 Created. + */ +static void usbvideo_OverlayString(struct uvd *uvd, struct usbvideo_frame *frame, + int x, int y, const char *str) +{ + while (*str) { + usbvideo_OverlayChar(uvd, frame, x, y, *str); + str++; + x += 4; /* 3 pixels character + 1 space */ + } +} + +/* + * usbvideo_OverlayStats() + * + * Overlays important debugging information. + * + * History: + * 01-Feb-2000 Created. + */ +static void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame) +{ + const int y_diff = 8; + char tmp[16]; + int x = 10, y=10; + long i, j, barLength; + const int qi_x1 = 60, qi_y1 = 10; + const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10; + + /* Call the user callback, see if we may proceed after that */ + if (VALID_CALLBACK(uvd, overlayHook)) { + if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0) + return; + } + + /* + * We draw a (mostly) hollow rectangle with qi_xxx coordinates. + * Left edge symbolizes the queue index 0; right edge symbolizes + * the full capacity of the queue. + */ + barLength = qi_x2 - qi_x1 - 2; + if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) { +/* TODO */ long u_lo, u_hi, q_used; + long m_ri, m_wi, m_lo, m_hi; + + /* + * Determine fill zones (used areas of the queue): + * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length + * + * if u_lo < 0 then there is no first filler. + */ + + q_used = RingQueue_GetLength(&uvd->dp); + if ((uvd->dp.ri + q_used) >= uvd->dp.length) { + u_hi = uvd->dp.length; + u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1); + } else { + u_hi = (q_used + uvd->dp.ri); + u_lo = -1; + } + + /* Convert byte indices into screen units */ + m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length); + m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length); + m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1; + m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length); + + for (j=qi_y1; j < (qi_y1 + qi_h); j++) { + for (i=qi_x1; i < qi_x2; i++) { + /* Draw border lines */ + if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) || + (i == qi_x1) || (i == (qi_x2 - 1))) { + RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF); + continue; + } + /* For all other points the Y coordinate does not matter */ + if ((i >= m_ri) && (i <= (m_ri + 3))) { + RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00); + } else if ((i >= m_wi) && (i <= (m_wi + 3))) { + RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00); + } else if ((i < m_lo) || ((i > m_ri) && (i < m_hi))) + RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF); + } + } + } + + sprintf(tmp, "%8lx", uvd->stats.frame_num); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.urb_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.urb_length); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.data_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.header_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.iso_skip_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.iso_err_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.colour); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.hue); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.brightness >> 8); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.contrast >> 12); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; +} + +/* + * usbvideo_ReportStatistics() + * + * This procedure prints packet and transfer statistics. + * + * History: + * 14-Jan-2000 Corrected default multiplier. + */ +static void usbvideo_ReportStatistics(const struct uvd *uvd) +{ + if ((uvd != NULL) && (uvd->stats.urb_count > 0)) { + unsigned long allPackets, badPackets, goodPackets, percent; + allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES; + badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count; + goodPackets = allPackets - badPackets; + /* Calculate percentage wisely, remember integer limits */ + assert(allPackets != 0); + if (goodPackets < (((unsigned long)-1)/100)) + percent = (100 * goodPackets) / allPackets; + else + percent = goodPackets / (allPackets / 100); + info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%", + allPackets, badPackets, percent); + if (uvd->iso_packet_len > 0) { + unsigned long allBytes, xferBytes; + char multiplier = ' '; + allBytes = allPackets * uvd->iso_packet_len; + xferBytes = uvd->stats.data_count; + assert(allBytes != 0); + if (xferBytes < (((unsigned long)-1)/100)) + percent = (100 * xferBytes) / allBytes; + else + percent = xferBytes / (allBytes / 100); + /* Scale xferBytes for easy reading */ + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'K'; + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'M'; + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'G'; + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'T'; + } + } + } + } + info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%", + xferBytes, multiplier, percent); + } + } +} + +/* + * usbvideo_TestPattern() + * + * Procedure forms a test pattern (yellow grid on blue background). + * + * Parameters: + * fullframe: if TRUE then entire frame is filled, otherwise the procedure + * continues from the current scanline. + * pmode 0: fill the frame with solid blue color (like on VCR or TV) + * 1: Draw a colored grid + * + * History: + * 01-Feb-2000 Created. + */ +void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) +{ + struct usbvideo_frame *frame; + int num_cell = 0; + int scan_length = 0; + static int num_pass = 0; + + if (uvd == NULL) { + err("%s: uvd == NULL", __FUNCTION__); + return; + } + if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { + err("%s: uvd->curframe=%d.", __FUNCTION__, uvd->curframe); + return; + } + + /* Grab the current frame */ + frame = &uvd->frame[uvd->curframe]; + + /* Optionally start at the beginning */ + if (fullframe) { + frame->curline = 0; + frame->seqRead_Length = 0; + } +#if 0 + { /* For debugging purposes only */ + char tmp[20]; + usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); + info("testpattern: frame=%s", tmp); + } +#endif + /* Form every scan line */ + for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) { + int i; + unsigned char *f = frame->data + + (VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline); + for (i=0; i < VIDEOSIZE_X(frame->request); i++) { + unsigned char cb=0x80; + unsigned char cg = 0; + unsigned char cr = 0; + + if (pmode == 1) { + if (frame->curline % 32 == 0) + cb = 0, cg = cr = 0xFF; + else if (i % 32 == 0) { + if (frame->curline % 32 == 1) + num_cell++; + cb = 0, cg = cr = 0xFF; + } else { + cb = ((num_cell*7) + num_pass) & 0xFF; + cg = ((num_cell*5) + num_pass*2) & 0xFF; + cr = ((num_cell*3) + num_pass*3) & 0xFF; + } + } else { + /* Just the blue screen */ + } + + *f++ = cb; + *f++ = cg; + *f++ = cr; + scan_length += 3; + } + } + + frame->frameState = FrameState_Done; + frame->seqRead_Length += scan_length; + ++num_pass; + + /* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */ + usbvideo_OverlayStats(uvd, frame); +} + +EXPORT_SYMBOL(usbvideo_TestPattern); + + +#ifdef DEBUG +/* + * usbvideo_HexDump() + * + * A debugging tool. Prints hex dumps. + * + * History: + * 29-Jul-2000 Added printing of offsets. + */ +void usbvideo_HexDump(const unsigned char *data, int len) +{ + const int bytes_per_line = 32; + char tmp[128]; /* 32*3 + 5 */ + int i, k; + + for (i=k=0; len > 0; i++, len--) { + if (i > 0 && ((i % bytes_per_line) == 0)) { + printk("%s\n", tmp); + k=0; + } + if ((i % bytes_per_line) == 0) + k += sprintf(&tmp[k], "%04x: ", i); + k += sprintf(&tmp[k], "%02x ", data[i]); + } + if (k > 0) + printk("%s\n", tmp); +} + +EXPORT_SYMBOL(usbvideo_HexDump); + +#endif + +/* ******************************************************************** */ + +/* XXX: this piece of crap really wants some error handling.. */ +static void usbvideo_ClientIncModCount(struct uvd *uvd) +{ + if (uvd == NULL) { + err("%s: uvd == NULL", __FUNCTION__); + return; + } + if (uvd->handle == NULL) { + err("%s: uvd->handle == NULL", __FUNCTION__); + return; + } + if (uvd->handle->md_module == NULL) { + err("%s: uvd->handle->md_module == NULL", __FUNCTION__); + return; + } + if (!try_module_get(uvd->handle->md_module)) { + err("%s: try_module_get() == 0", __FUNCTION__); + return; + } +} + +static void usbvideo_ClientDecModCount(struct uvd *uvd) +{ + if (uvd == NULL) { + err("%s: uvd == NULL", __FUNCTION__); + return; + } + if (uvd->handle == NULL) { + err("%s: uvd->handle == NULL", __FUNCTION__); + return; + } + if (uvd->handle->md_module == NULL) { + err("%s: uvd->handle->md_module == NULL", __FUNCTION__); + return; + } + module_put(uvd->handle->md_module); +} + +int usbvideo_register( + struct usbvideo **pCams, + const int num_cams, + const int num_extra, + const char *driverName, + const struct usbvideo_cb *cbTbl, + struct module *md, + const struct usb_device_id *id_table) +{ + struct usbvideo *cams; + int i, base_size, result; + + /* Check parameters for sanity */ + if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) { + err("%s: Illegal call", __FUNCTION__); + return -EINVAL; + } + + /* Check registration callback - must be set! */ + if (cbTbl->probe == NULL) { + err("%s: probe() is required!", __FUNCTION__); + return -EINVAL; + } + + base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo); + cams = (struct usbvideo *) kzalloc(base_size, GFP_KERNEL); + if (cams == NULL) { + err("Failed to allocate %d. bytes for usbvideo struct", base_size); + return -ENOMEM; + } + dbg("%s: Allocated $%p (%d. bytes) for %d. cameras", + __FUNCTION__, cams, base_size, num_cams); + + /* Copy callbacks, apply defaults for those that are not set */ + memmove(&cams->cb, cbTbl, sizeof(cams->cb)); + if (cams->cb.getFrame == NULL) + cams->cb.getFrame = usbvideo_GetFrame; + if (cams->cb.disconnect == NULL) + cams->cb.disconnect = usbvideo_Disconnect; + if (cams->cb.startDataPump == NULL) + cams->cb.startDataPump = usbvideo_StartDataPump; + if (cams->cb.stopDataPump == NULL) + cams->cb.stopDataPump = usbvideo_StopDataPump; + + cams->num_cameras = num_cams; + cams->cam = (struct uvd *) &cams[1]; + cams->md_module = md; + if (cams->md_module == NULL) + warn("%s: module == NULL!", __FUNCTION__); + mutex_init(&cams->lock); /* to 1 == available */ + + for (i = 0; i < num_cams; i++) { + struct uvd *up = &cams->cam[i]; + + up->handle = cams; + + /* Allocate user_data separately because of kmalloc's limits */ + if (num_extra > 0) { + up->user_size = num_cams * num_extra; + up->user_data = kmalloc(up->user_size, GFP_KERNEL); + if (up->user_data == NULL) { + err("%s: Failed to allocate user_data (%d. bytes)", + __FUNCTION__, up->user_size); + while (i) { + up = &cams->cam[--i]; + kfree(up->user_data); + } + kfree(cams); + return -ENOMEM; + } + dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)", + __FUNCTION__, i, up->user_data, up->user_size); + } + } + + /* + * Register ourselves with USB stack. + */ + strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown"); + cams->usbdrv.name = cams->drvName; + cams->usbdrv.probe = cams->cb.probe; + cams->usbdrv.disconnect = cams->cb.disconnect; + cams->usbdrv.id_table = id_table; + + /* + * Update global handle to usbvideo. This is very important + * because probe() can be called before usb_register() returns. + * If the handle is not yet updated then the probe() will fail. + */ + *pCams = cams; + result = usb_register(&cams->usbdrv); + if (result) { + for (i = 0; i < num_cams; i++) { + struct uvd *up = &cams->cam[i]; + kfree(up->user_data); + } + kfree(cams); + } + + return result; +} + +EXPORT_SYMBOL(usbvideo_register); + +/* + * usbvideo_Deregister() + * + * Procedure frees all usbvideo and user data structures. Be warned that + * if you had some dynamically allocated components in ->user field then + * you should free them before calling here. + */ +void usbvideo_Deregister(struct usbvideo **pCams) +{ + struct usbvideo *cams; + int i; + + if (pCams == NULL) { + err("%s: pCams == NULL", __FUNCTION__); + return; + } + cams = *pCams; + if (cams == NULL) { + err("%s: cams == NULL", __FUNCTION__); + return; + } + + dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName); + usb_deregister(&cams->usbdrv); + + dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, cams, cams->num_cameras); + for (i=0; i < cams->num_cameras; i++) { + struct uvd *up = &cams->cam[i]; + int warning = 0; + + if (up->user_data != NULL) { + if (up->user_size <= 0) + ++warning; + } else { + if (up->user_size > 0) + ++warning; + } + if (warning) { + err("%s: Warning: user_data=$%p user_size=%d.", + __FUNCTION__, up->user_data, up->user_size); + } else { + dbg("%s: Freeing %d. $%p->user_data=$%p", + __FUNCTION__, i, up, up->user_data); + kfree(up->user_data); + } + } + /* Whole array was allocated in one chunk */ + dbg("%s: Freed %d uvd structures", + __FUNCTION__, cams->num_cameras); + kfree(cams); + *pCams = NULL; +} + +EXPORT_SYMBOL(usbvideo_Deregister); + +/* + * usbvideo_Disconnect() + * + * This procedure stops all driver activity. Deallocation of + * the interface-private structure (pointed by 'ptr') is done now + * (if we don't have any open files) or later, when those files + * are closed. After that driver should be removable. + * + * This code handles surprise removal. The uvd->user is a counter which + * increments on open() and decrements on close(). If we see here that + * this counter is not 0 then we have a client who still has us opened. + * We set uvd->remove_pending flag as early as possible, and after that + * all access to the camera will gracefully fail. These failures should + * prompt client to (eventually) close the video device, and then - in + * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter. + * + * History: + * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone. + * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close() + * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). + * 19-Oct-2000 Moved to usbvideo module. + */ +static void usbvideo_Disconnect(struct usb_interface *intf) +{ + struct uvd *uvd = usb_get_intfdata (intf); + int i; + + if (uvd == NULL) { + err("%s($%p): Illegal call.", __FUNCTION__, intf); + return; + } + + usb_set_intfdata (intf, NULL); + + usbvideo_ClientIncModCount(uvd); + if (uvd->debug > 0) + info("%s(%p.)", __FUNCTION__, intf); + + mutex_lock(&uvd->lock); + uvd->remove_pending = 1; /* Now all ISO data will be ignored */ + + /* At this time we ask to cancel outstanding URBs */ + GET_CALLBACK(uvd, stopDataPump)(uvd); + + for (i=0; i < USBVIDEO_NUMSBUF; i++) + usb_free_urb(uvd->sbuf[i].urb); + + usb_put_dev(uvd->dev); + uvd->dev = NULL; /* USB device is no more */ + + video_unregister_device(&uvd->vdev); + if (uvd->debug > 0) + info("%s: Video unregistered.", __FUNCTION__); + + if (uvd->user) + info("%s: In use, disconnect pending.", __FUNCTION__); + else + usbvideo_CameraRelease(uvd); + mutex_unlock(&uvd->lock); + info("USB camera disconnected."); + + usbvideo_ClientDecModCount(uvd); +} + +/* + * usbvideo_CameraRelease() + * + * This code does final release of uvd. This happens + * after the device is disconnected -and- all clients + * closed their files. + * + * History: + * 27-Jan-2000 Created. + */ +static void usbvideo_CameraRelease(struct uvd *uvd) +{ + if (uvd == NULL) { + err("%s: Illegal call", __FUNCTION__); + return; + } + + RingQueue_Free(&uvd->dp); + if (VALID_CALLBACK(uvd, userFree)) + GET_CALLBACK(uvd, userFree)(uvd); + uvd->uvd_used = 0; /* This is atomic, no need to take mutex */ +} + +/* + * usbvideo_find_struct() + * + * This code searches the array of preallocated (static) structures + * and returns index of the first one that isn't in use. Returns -1 + * if there are no free structures. + * + * History: + * 27-Jan-2000 Created. + */ +static int usbvideo_find_struct(struct usbvideo *cams) +{ + int u, rv = -1; + + if (cams == NULL) { + err("No usbvideo handle?"); + return -1; + } + mutex_lock(&cams->lock); + for (u = 0; u < cams->num_cameras; u++) { + struct uvd *uvd = &cams->cam[u]; + if (!uvd->uvd_used) /* This one is free */ + { + uvd->uvd_used = 1; /* In use now */ + mutex_init(&uvd->lock); /* to 1 == available */ + uvd->dev = NULL; + rv = u; + break; + } + } + mutex_unlock(&cams->lock); + return rv; +} + +static struct file_operations usbvideo_fops = { + .owner = THIS_MODULE, + .open = usbvideo_v4l_open, + .release =usbvideo_v4l_close, + .read = usbvideo_v4l_read, + .mmap = usbvideo_v4l_mmap, + .ioctl = usbvideo_v4l_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .llseek = no_llseek, +}; +static const struct video_device usbvideo_template = { + .owner = THIS_MODULE, + .type = VID_TYPE_CAPTURE, + .hardware = VID_HARDWARE_CPIA, + .fops = &usbvideo_fops, +}; + +struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams) +{ + int i, devnum; + struct uvd *uvd = NULL; + + if (cams == NULL) { + err("No usbvideo handle?"); + return NULL; + } + + devnum = usbvideo_find_struct(cams); + if (devnum == -1) { + err("IBM USB camera driver: Too many devices!"); + return NULL; + } + uvd = &cams->cam[devnum]; + dbg("Device entry #%d. at $%p", devnum, uvd); + + /* Not relying upon caller we increase module counter ourselves */ + usbvideo_ClientIncModCount(uvd); + + mutex_lock(&uvd->lock); + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); + if (uvd->sbuf[i].urb == NULL) { + err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC); + uvd->uvd_used = 0; + uvd = NULL; + goto allocate_done; + } + } + uvd->user=0; + uvd->remove_pending = 0; + uvd->last_error = 0; + RingQueue_Initialize(&uvd->dp); + + /* Initialize video device structure */ + uvd->vdev = usbvideo_template; + sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName); + /* + * The client is free to overwrite those because we + * return control to the client's probe function right now. + */ +allocate_done: + mutex_unlock(&uvd->lock); + usbvideo_ClientDecModCount(uvd); + return uvd; +} + +EXPORT_SYMBOL(usbvideo_AllocateDevice); + +int usbvideo_RegisterVideoDevice(struct uvd *uvd) +{ + char tmp1[20], tmp2[20]; /* Buffers for printing */ + + if (uvd == NULL) { + err("%s: Illegal call.", __FUNCTION__); + return -EINVAL; + } + if (uvd->video_endp == 0) { + info("%s: No video endpoint specified; data pump disabled.", __FUNCTION__); + } + if (uvd->paletteBits == 0) { + err("%s: No palettes specified!", __FUNCTION__); + return -EINVAL; + } + if (uvd->defaultPalette == 0) { + info("%s: No default palette!", __FUNCTION__); + } + + uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * + VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL; + usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize); + usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); + + if (uvd->debug > 0) { + info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx", + __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits); + } + if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + err("%s: video_register_device failed", __FUNCTION__); + return -EPIPE; + } + if (uvd->debug > 1) { + info("%s: video_register_device() successful", __FUNCTION__); + } + if (uvd->dev == NULL) { + err("%s: uvd->dev == NULL", __FUNCTION__); + return -EINVAL; + } + + info("%s on /dev/video%d: canvas=%s videosize=%s", + (uvd->handle != NULL) ? uvd->handle->drvName : "???", + uvd->vdev.minor, tmp2, tmp1); + + usb_get_dev(uvd->dev); + return 0; +} + +EXPORT_SYMBOL(usbvideo_RegisterVideoDevice); + +/* ******************************************************************** */ + +static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct uvd *uvd = file->private_data; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end-vma->vm_start; + unsigned long page, pos; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return -EFAULT; + + if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) + return -EINVAL; + + pos = (unsigned long) uvd->fbuf; + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + return 0; +} + +/* + * usbvideo_v4l_open() + * + * This is part of Video 4 Linux API. The driver can be opened by one + * client only (checks internal counter 'uvdser'). The procedure + * then allocates buffers needed for video processing. + * + * History: + * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the + * camera is also initialized here (once per connect), at + * expense of V4L client (it waits on open() call). + * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. + * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). + */ +static int usbvideo_v4l_open(struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct uvd *uvd = (struct uvd *) dev; + const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len; + int i, errCode = 0; + + if (uvd->debug > 1) + info("%s($%p)", __FUNCTION__, dev); + + usbvideo_ClientIncModCount(uvd); + mutex_lock(&uvd->lock); + + if (uvd->user) { + err("%s: Someone tried to open an already opened device!", __FUNCTION__); + errCode = -EBUSY; + } else { + /* Clear statistics */ + memset(&uvd->stats, 0, sizeof(uvd->stats)); + + /* Clean pointers so we know if we allocated something */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) + uvd->sbuf[i].data = NULL; + + /* Allocate memory for the frame buffers */ + uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size; + uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size); + RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE); + if ((uvd->fbuf == NULL) || + (!RingQueue_IsAllocated(&uvd->dp))) { + err("%s: Failed to allocate fbuf or dp", __FUNCTION__); + errCode = -ENOMEM; + } else { + /* Allocate all buffers */ + for (i=0; i < USBVIDEO_NUMFRAMES; i++) { + uvd->frame[i].frameState = FrameState_Unused; + uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size); + /* + * Set default sizes in case IOCTL (VIDIOCMCAPTURE) + * is not used (using read() instead). + */ + uvd->frame[i].canvas = uvd->canvas; + uvd->frame[i].seqRead_Index = 0; + } + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL); + if (uvd->sbuf[i].data == NULL) { + errCode = -ENOMEM; + break; + } + } + } + if (errCode != 0) { + /* Have to free all that memory */ + if (uvd->fbuf != NULL) { + usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); + uvd->fbuf = NULL; + } + RingQueue_Free(&uvd->dp); + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + kfree(uvd->sbuf[i].data); + uvd->sbuf[i].data = NULL; + } + } + } + + /* If so far no errors then we shall start the camera */ + if (errCode == 0) { + /* Start data pump if we have valid endpoint */ + if (uvd->video_endp != 0) + errCode = GET_CALLBACK(uvd, startDataPump)(uvd); + if (errCode == 0) { + if (VALID_CALLBACK(uvd, setupOnOpen)) { + if (uvd->debug > 1) + info("%s: setupOnOpen callback", __FUNCTION__); + errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); + if (errCode < 0) { + err("%s: setupOnOpen callback failed (%d.).", + __FUNCTION__, errCode); + } else if (uvd->debug > 1) { + info("%s: setupOnOpen callback successful", __FUNCTION__); + } + } + if (errCode == 0) { + uvd->settingsAdjusted = 0; + if (uvd->debug > 1) + info("%s: Open succeeded.", __FUNCTION__); + uvd->user++; + file->private_data = uvd; + } + } + } + mutex_unlock(&uvd->lock); + if (errCode != 0) + usbvideo_ClientDecModCount(uvd); + if (uvd->debug > 0) + info("%s: Returning %d.", __FUNCTION__, errCode); + return errCode; +} + +/* + * usbvideo_v4l_close() + * + * This is part of Video 4 Linux API. The procedure + * stops streaming and deallocates all buffers that were earlier + * allocated in usbvideo_v4l_open(). + * + * History: + * 22-Jan-2000 Moved scratch buffer deallocation here. + * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. + * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep. + */ +static int usbvideo_v4l_close(struct inode *inode, struct file *file) +{ + struct video_device *dev = file->private_data; + struct uvd *uvd = (struct uvd *) dev; + int i; + + if (uvd->debug > 1) + info("%s($%p)", __FUNCTION__, dev); + + mutex_lock(&uvd->lock); + GET_CALLBACK(uvd, stopDataPump)(uvd); + usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); + uvd->fbuf = NULL; + RingQueue_Free(&uvd->dp); + + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + kfree(uvd->sbuf[i].data); + uvd->sbuf[i].data = NULL; + } + +#if USBVIDEO_REPORT_STATS + usbvideo_ReportStatistics(uvd); +#endif + + uvd->user--; + if (uvd->remove_pending) { + if (uvd->debug > 0) + info("usbvideo_v4l_close: Final disconnect."); + usbvideo_CameraRelease(uvd); + } + mutex_unlock(&uvd->lock); + usbvideo_ClientDecModCount(uvd); + + if (uvd->debug > 1) + info("%s: Completed.", __FUNCTION__); + file->private_data = NULL; + return 0; +} + +/* + * usbvideo_v4l_ioctl() + * + * This is part of Video 4 Linux API. The procedure handles ioctl() calls. + * + * History: + * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings. + */ +static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct uvd *uvd = file->private_data; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return -EIO; + + switch (cmd) { + case VIDIOCGCAP: + { + struct video_capability *b = arg; + *b = uvd->vcap; + return 0; + } + case VIDIOCGCHAN: + { + struct video_channel *v = arg; + *v = uvd->vchan; + return 0; + } + case VIDIOCSCHAN: + { + struct video_channel *v = arg; + if (v->channel != 0) + return -EINVAL; + return 0; + } + case VIDIOCGPICT: + { + struct video_picture *pic = arg; + *pic = uvd->vpic; + return 0; + } + case VIDIOCSPICT: + { + struct video_picture *pic = arg; + /* + * Use temporary 'video_picture' structure to preserve our + * own settings (such as color depth, palette) that we + * aren't allowing everyone (V4L client) to change. + */ + uvd->vpic.brightness = pic->brightness; + uvd->vpic.hue = pic->hue; + uvd->vpic.colour = pic->colour; + uvd->vpic.contrast = pic->contrast; + uvd->settingsAdjusted = 0; /* Will force new settings */ + return 0; + } + case VIDIOCSWIN: + { + struct video_window *vw = arg; + + if(VALID_CALLBACK(uvd, setVideoMode)) { + return GET_CALLBACK(uvd, setVideoMode)(uvd, vw); + } + + if (vw->flags) + return -EINVAL; + if (vw->clipcount) + return -EINVAL; + if (vw->width != VIDEOSIZE_X(uvd->canvas)) + return -EINVAL; + if (vw->height != VIDEOSIZE_Y(uvd->canvas)) + return -EINVAL; + + return 0; + } + case VIDIOCGWIN: + { + struct video_window *vw = arg; + + vw->x = 0; + vw->y = 0; + vw->width = VIDEOSIZE_X(uvd->videosize); + vw->height = VIDEOSIZE_Y(uvd->videosize); + vw->chromakey = 0; + if (VALID_CALLBACK(uvd, getFPS)) + vw->flags = GET_CALLBACK(uvd, getFPS)(uvd); + else + vw->flags = 10; /* FIXME: do better! */ + return 0; + } + case VIDIOCGMBUF: + { + struct video_mbuf *vm = arg; + int i; + + memset(vm, 0, sizeof(*vm)); + vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES; + vm->frames = USBVIDEO_NUMFRAMES; + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) + vm->offsets[i] = i * uvd->max_frame_size; + + return 0; + } + case VIDIOCMCAPTURE: + { + struct video_mmap *vm = arg; + + if (uvd->debug >= 1) { + info("VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.", + vm->frame, vm->width, vm->height, vm->format); + } + /* + * Check if the requested size is supported. If the requestor + * requests too big a frame then we may be tricked into accessing + * outside of own preallocated frame buffer (in uvd->frame). + * This will cause oops or a security hole. Theoretically, we + * could only clamp the size down to acceptable bounds, but then + * we'd need to figure out how to insert our smaller buffer into + * larger caller's buffer... this is not an easy question. So we + * here just flatly reject too large requests, assuming that the + * caller will resubmit with smaller size. Callers should know + * what size we support (returned by VIDIOCGCAP). However vidcat, + * for one, does not care and allows to ask for any size. + */ + if ((vm->width > VIDEOSIZE_X(uvd->canvas)) || + (vm->height > VIDEOSIZE_Y(uvd->canvas))) { + if (uvd->debug > 0) { + info("VIDIOCMCAPTURE: Size=%dx%d too large; " + "allowed only up to %ldx%ld", vm->width, vm->height, + VIDEOSIZE_X(uvd->canvas), VIDEOSIZE_Y(uvd->canvas)); + } + return -EINVAL; + } + /* Check if the palette is supported */ + if (((1L << vm->format) & uvd->paletteBits) == 0) { + if (uvd->debug > 0) { + info("VIDIOCMCAPTURE: format=%d. not supported" + " (paletteBits=$%08lx)", + vm->format, uvd->paletteBits); + } + return -EINVAL; + } + if ((vm->frame < 0) || (vm->frame >= USBVIDEO_NUMFRAMES)) { + err("VIDIOCMCAPTURE: vm.frame=%d. !E [0-%d]", vm->frame, USBVIDEO_NUMFRAMES-1); + return -EINVAL; + } + if (uvd->frame[vm->frame].frameState == FrameState_Grabbing) { + /* Not an error - can happen */ + } + uvd->frame[vm->frame].request = VIDEOSIZE(vm->width, vm->height); + uvd->frame[vm->frame].palette = vm->format; + + /* Mark it as ready */ + uvd->frame[vm->frame].frameState = FrameState_Ready; + + return usbvideo_NewFrame(uvd, vm->frame); + } + case VIDIOCSYNC: + { + int *frameNum = arg; + int ret; + + if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES) + return -EINVAL; + + if (uvd->debug >= 1) + info("VIDIOCSYNC: syncing to frame %d.", *frameNum); + if (uvd->flags & FLAGS_NO_DECODING) + ret = usbvideo_GetFrame(uvd, *frameNum); + else if (VALID_CALLBACK(uvd, getFrame)) { + ret = GET_CALLBACK(uvd, getFrame)(uvd, *frameNum); + if ((ret < 0) && (uvd->debug >= 1)) { + err("VIDIOCSYNC: getFrame() returned %d.", ret); + } + } else { + err("VIDIOCSYNC: getFrame is not set"); + ret = -EFAULT; + } + + /* + * The frame is in FrameState_Done_Hold state. Release it + * right now because its data is already mapped into + * the user space and it's up to the application to + * make use of it until it asks for another frame. + */ + uvd->frame[*frameNum].frameState = FrameState_Unused; + return ret; + } + case VIDIOCGFBUF: + { + struct video_buffer *vb = arg; + + memset(vb, 0, sizeof(*vb)); + return 0; + } + case VIDIOCKEY: + return 0; + + case VIDIOCCAPTURE: + return -EINVAL; + + case VIDIOCSFBUF: + + case VIDIOCGTUNER: + case VIDIOCSTUNER: + + case VIDIOCGFREQ: + case VIDIOCSFREQ: + + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, usbvideo_v4l_do_ioctl); +} + +/* + * usbvideo_v4l_read() + * + * This is mostly boring stuff. We simply ask for a frame and when it + * arrives copy all the video data from it into user space. There is + * no obvious need to override this method. + * + * History: + * 20-Oct-2000 Created. + * 01-Nov-2000 Added mutex (uvd->lock). + */ +static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct uvd *uvd = file->private_data; + int noblock = file->f_flags & O_NONBLOCK; + int frmx = -1, i; + struct usbvideo_frame *frame; + + if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL)) + return -EFAULT; + + if (uvd->debug >= 1) + info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock); + + mutex_lock(&uvd->lock); + + /* See if a frame is completed, then use it. */ + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { + if ((uvd->frame[i].frameState == FrameState_Done) || + (uvd->frame[i].frameState == FrameState_Done_Hold) || + (uvd->frame[i].frameState == FrameState_Error)) { + frmx = i; + break; + } + } + + /* FIXME: If we don't start a frame here then who ever does? */ + if (noblock && (frmx == -1)) { + count = -EAGAIN; + goto read_done; + } + + /* + * If no FrameState_Done, look for a FrameState_Grabbing state. + * See if a frame is in process (grabbing), then use it. + * We will need to wait until it becomes cooked, of course. + */ + if (frmx == -1) { + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { + if (uvd->frame[i].frameState == FrameState_Grabbing) { + frmx = i; + break; + } + } + } + + /* + * If no frame is active, start one. We don't care which one + * it will be, so #0 is as good as any. + * In read access mode we don't have convenience of VIDIOCMCAPTURE + * to specify the requested palette (video format) on per-frame + * basis. This means that we have to return data in -some- format + * and just hope that the client knows what to do with it. + * The default format is configured in uvd->defaultPalette field + * as one of VIDEO_PALETTE_xxx values. We stuff it into the new + * frame and initiate the frame filling process. + */ + if (frmx == -1) { + if (uvd->defaultPalette == 0) { + err("%s: No default palette; don't know what to do!", __FUNCTION__); + count = -EFAULT; + goto read_done; + } + frmx = 0; + /* + * We have no per-frame control over video size. + * Therefore we only can use whatever size was + * specified as default. + */ + uvd->frame[frmx].request = uvd->videosize; + uvd->frame[frmx].palette = uvd->defaultPalette; + uvd->frame[frmx].frameState = FrameState_Ready; + usbvideo_NewFrame(uvd, frmx); + /* Now frame 0 is supposed to start filling... */ + } + + /* + * Get a pointer to the active frame. It is either previously + * completed frame or frame in progress but not completed yet. + */ + frame = &uvd->frame[frmx]; + + /* + * Sit back & wait until the frame gets filled and postprocessed. + * If we fail to get the picture [in time] then return the error. + * In this call we specify that we want the frame to be waited for, + * postprocessed and switched into FrameState_Done_Hold state. This + * state is used to hold the frame as "fully completed" between + * subsequent partial reads of the same frame. + */ + if (frame->frameState != FrameState_Done_Hold) { + long rv = -EFAULT; + if (uvd->flags & FLAGS_NO_DECODING) + rv = usbvideo_GetFrame(uvd, frmx); + else if (VALID_CALLBACK(uvd, getFrame)) + rv = GET_CALLBACK(uvd, getFrame)(uvd, frmx); + else + err("getFrame is not set"); + if ((rv != 0) || (frame->frameState != FrameState_Done_Hold)) { + count = rv; + goto read_done; + } + } + + /* + * Copy bytes to user space. We allow for partial reads, which + * means that the user application can request read less than + * the full frame size. It is up to the application to issue + * subsequent calls until entire frame is read. + * + * First things first, make sure we don't copy more than we + * have - even if the application wants more. That would be + * a big security embarassment! + */ + if ((count + frame->seqRead_Index) > frame->seqRead_Length) + count = frame->seqRead_Length - frame->seqRead_Index; + + /* + * Copy requested amount of data to user space. We start + * copying from the position where we last left it, which + * will be zero for a new frame (not read before). + */ + if (copy_to_user(buf, frame->data + frame->seqRead_Index, count)) { + count = -EFAULT; + goto read_done; + } + + /* Update last read position */ + frame->seqRead_Index += count; + if (uvd->debug >= 1) { + err("%s: {copy} count used=%Zd, new seqRead_Index=%ld", + __FUNCTION__, count, frame->seqRead_Index); + } + + /* Finally check if the frame is done with and "release" it */ + if (frame->seqRead_Index >= frame->seqRead_Length) { + /* All data has been read */ + frame->seqRead_Index = 0; + + /* Mark it as available to be used again. */ + uvd->frame[frmx].frameState = FrameState_Unused; + if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) { + err("%s: usbvideo_NewFrame failed.", __FUNCTION__); + } + } +read_done: + mutex_unlock(&uvd->lock); + return count; +} + +/* + * Make all of the blocks of data contiguous + */ +static int usbvideo_CompressIsochronous(struct uvd *uvd, struct urb *urb) +{ + char *cdata; + int i, totlen = 0; + + for (i = 0; i < urb->number_of_packets; i++) { + int n = urb->iso_frame_desc[i].actual_length; + int st = urb->iso_frame_desc[i].status; + + cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + + /* Detect and ignore errored packets */ + if (st < 0) { + if (uvd->debug >= 1) + err("Data error: packet=%d. len=%d. status=%d.", i, n, st); + uvd->stats.iso_err_count++; + continue; + } + + /* Detect and ignore empty packets */ + if (n <= 0) { + uvd->stats.iso_skip_count++; + continue; + } + totlen += n; /* Little local accounting */ + RingQueue_Enqueue(&uvd->dp, cdata, n); + } + return totlen; +} + +static void usbvideo_IsocIrq(struct urb *urb, struct pt_regs *regs) +{ + int i, ret, len; + struct uvd *uvd = urb->context; + + /* We don't want to do anything if we are about to be removed! */ + if (!CAMERA_IS_OPERATIONAL(uvd)) + return; +#if 0 + if (urb->actual_length > 0) { + info("urb=$%p status=%d. errcount=%d. length=%d.", + urb, urb->status, urb->error_count, urb->actual_length); + } else { + static int c = 0; + if (c++ % 100 == 0) + info("No Isoc data"); + } +#endif + + if (!uvd->streaming) { + if (uvd->debug >= 1) + info("Not streaming, but interrupt!"); + return; + } + + uvd->stats.urb_count++; + if (urb->actual_length <= 0) + goto urb_done_with; + + /* Copy the data received into ring queue */ + len = usbvideo_CompressIsochronous(uvd, urb); + uvd->stats.urb_length = len; + if (len <= 0) + goto urb_done_with; + + /* Here we got some data */ + uvd->stats.data_count += len; + RingQueue_WakeUpInterruptible(&uvd->dp); + +urb_done_with: + for (i = 0; i < FRAMES_PER_DESC; i++) { + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + urb->status = 0; + urb->dev = uvd->dev; + ret = usb_submit_urb (urb, GFP_KERNEL); + if(ret) + err("usb_submit_urb error (%d)", ret); + return; +} + +/* + * usbvideo_StartDataPump() + * + * History: + * 27-Jan-2000 Used ibmcam->iface, ibmcam->ifaceAltActive instead + * of hardcoded values. Simplified by using for loop, + * allowed any number of URBs. + */ +static int usbvideo_StartDataPump(struct uvd *uvd) +{ + struct usb_device *dev = uvd->dev; + int i, errFlag; + + if (uvd->debug > 1) + info("%s($%p)", __FUNCTION__, uvd); + + if (!CAMERA_IS_OPERATIONAL(uvd)) { + err("%s: Camera is not operational", __FUNCTION__); + return -EFAULT; + } + uvd->curframe = -1; + + /* Alternate interface 1 is is the biggest frame size */ + i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); + if (i < 0) { + err("%s: usb_set_interface error", __FUNCTION__); + uvd->last_error = i; + return -EBUSY; + } + if (VALID_CALLBACK(uvd, videoStart)) + GET_CALLBACK(uvd, videoStart)(uvd); + else + err("%s: videoStart not set", __FUNCTION__); + + /* We double buffer the Iso lists */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + int j, k; + struct urb *urb = uvd->sbuf[i].urb; + urb->dev = dev; + urb->context = uvd; + urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); + urb->interval = 1; + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = uvd->sbuf[i].data; + urb->complete = usbvideo_IsocIrq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC; + for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = uvd->iso_packet_len; + } + } + + /* Submit all URBs */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); + if (errFlag) + err("%s: usb_submit_isoc(%d) ret %d", __FUNCTION__, i, errFlag); + } + + uvd->streaming = 1; + if (uvd->debug > 1) + info("%s: streaming=1 video_endp=$%02x", __FUNCTION__, uvd->video_endp); + return 0; +} + +/* + * usbvideo_StopDataPump() + * + * This procedure stops streaming and deallocates URBs. Then it + * activates zero-bandwidth alt. setting of the video interface. + * + * History: + * 22-Jan-2000 Corrected order of actions to work after surprise removal. + * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values. + */ +static void usbvideo_StopDataPump(struct uvd *uvd) +{ + int i, j; + + if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) + return; + + if (uvd->debug > 1) + info("%s($%p)", __FUNCTION__, uvd); + + /* Unschedule all of the iso td's */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + usb_kill_urb(uvd->sbuf[i].urb); + } + if (uvd->debug > 1) + info("%s: streaming=0", __FUNCTION__); + uvd->streaming = 0; + + if (!uvd->remove_pending) { + /* Invoke minidriver's magic to stop the camera */ + if (VALID_CALLBACK(uvd, videoStop)) + GET_CALLBACK(uvd, videoStop)(uvd); + else + err("%s: videoStop not set", __FUNCTION__); + + /* Set packet size to 0 */ + j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); + if (j < 0) { + err("%s: usb_set_interface() error %d.", __FUNCTION__, j); + uvd->last_error = j; + } + } +} + +/* + * usbvideo_NewFrame() + * + * History: + * 29-Mar-00 Added copying of previous frame into the current one. + * 6-Aug-00 Added model 3 video sizes, removed redundant width, height. + */ +static int usbvideo_NewFrame(struct uvd *uvd, int framenum) +{ + struct usbvideo_frame *frame; + int n; + + if (uvd->debug > 1) + info("usbvideo_NewFrame($%p,%d.)", uvd, framenum); + + /* If we're not grabbing a frame right now and the other frame is */ + /* ready to be grabbed into, then use it instead */ + if (uvd->curframe != -1) + return 0; + + /* If necessary we adjust picture settings between frames */ + if (!uvd->settingsAdjusted) { + if (VALID_CALLBACK(uvd, adjustPicture)) + GET_CALLBACK(uvd, adjustPicture)(uvd); + uvd->settingsAdjusted = 1; + } + + n = (framenum + 1) % USBVIDEO_NUMFRAMES; + if (uvd->frame[n].frameState == FrameState_Ready) + framenum = n; + + frame = &uvd->frame[framenum]; + + frame->frameState = FrameState_Grabbing; + frame->scanstate = ScanState_Scanning; + frame->seqRead_Length = 0; /* Accumulated in xxx_parse_data() */ + frame->deinterlace = Deinterlace_None; + frame->flags = 0; /* No flags yet, up to minidriver (or us) to set them */ + uvd->curframe = framenum; + + /* + * Normally we would want to copy previous frame into the current one + * before we even start filling it with data; this allows us to stop + * filling at any moment; top portion of the frame will be new and + * bottom portion will stay as it was in previous frame. If we don't + * do that then missing chunks of video stream will result in flickering + * portions of old data whatever it was before. + * + * If we choose not to copy previous frame (to, for example, save few + * bus cycles - the frame can be pretty large!) then we have an option + * to clear the frame before using. If we experience losses in this + * mode then missing picture will be black (no flickering). + * + * Finally, if user chooses not to clean the current frame before + * filling it with data then the old data will be visible if we fail + * to refill entire frame with new data. + */ + if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) { + /* This copies previous frame into this one to mask losses */ + int prev = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES; + memmove(frame->data, uvd->frame[prev].data, uvd->max_frame_size); + } else { + if (uvd->flags & FLAGS_CLEAN_FRAMES) { + /* This provides a "clean" frame but slows things down */ + memset(frame->data, 0, uvd->max_frame_size); + } + } + return 0; +} + +/* + * usbvideo_CollectRawData() + * + * This procedure can be used instead of 'processData' callback if you + * only want to dump the raw data from the camera into the output + * device (frame buffer). You can look at it with V4L client, but the + * image will be unwatchable. The main purpose of this code and of the + * mode FLAGS_NO_DECODING is debugging and capturing of datastreams from + * new, unknown cameras. This procedure will be automatically invoked + * instead of the specified callback handler when uvd->flags has bit + * FLAGS_NO_DECODING set. Therefore, any regular build of any driver + * based on usbvideo can use this feature at any time. + */ +static void usbvideo_CollectRawData(struct uvd *uvd, struct usbvideo_frame *frame) +{ + int n; + + assert(uvd != NULL); + assert(frame != NULL); + + /* Try to move data from queue into frame buffer */ + n = RingQueue_GetLength(&uvd->dp); + if (n > 0) { + int m; + /* See how much space we have left */ + m = uvd->max_frame_size - frame->seqRead_Length; + if (n > m) + n = m; + /* Now move that much data into frame buffer */ + RingQueue_Dequeue( + &uvd->dp, + frame->data + frame->seqRead_Length, + m); + frame->seqRead_Length += m; + } + /* See if we filled the frame */ + if (frame->seqRead_Length >= uvd->max_frame_size) { + frame->frameState = FrameState_Done; + uvd->curframe = -1; + uvd->stats.frame_num++; + } +} + +static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) +{ + struct usbvideo_frame *frame = &uvd->frame[frameNum]; + + if (uvd->debug >= 2) + info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum); + + switch (frame->frameState) { + case FrameState_Unused: + if (uvd->debug >= 2) + info("%s: FrameState_Unused", __FUNCTION__); + return -EINVAL; + case FrameState_Ready: + case FrameState_Grabbing: + case FrameState_Error: + { + int ntries, signalPending; + redo: + if (!CAMERA_IS_OPERATIONAL(uvd)) { + if (uvd->debug >= 2) + info("%s: Camera is not operational (1)", __FUNCTION__); + return -EIO; + } + ntries = 0; + do { + RingQueue_InterruptibleSleepOn(&uvd->dp); + signalPending = signal_pending(current); + if (!CAMERA_IS_OPERATIONAL(uvd)) { + if (uvd->debug >= 2) + info("%s: Camera is not operational (2)", __FUNCTION__); + return -EIO; + } + assert(uvd->fbuf != NULL); + if (signalPending) { + if (uvd->debug >= 2) + info("%s: Signal=$%08x", __FUNCTION__, signalPending); + if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { + usbvideo_TestPattern(uvd, 1, 0); + uvd->curframe = -1; + uvd->stats.frame_num++; + if (uvd->debug >= 2) + info("%s: Forced test pattern screen", __FUNCTION__); + return 0; + } else { + /* Standard answer: Interrupted! */ + if (uvd->debug >= 2) + info("%s: Interrupted!", __FUNCTION__); + return -EINTR; + } + } else { + /* No signals - we just got new data in dp queue */ + if (uvd->flags & FLAGS_NO_DECODING) + usbvideo_CollectRawData(uvd, frame); + else if (VALID_CALLBACK(uvd, processData)) + GET_CALLBACK(uvd, processData)(uvd, frame); + else + err("%s: processData not set", __FUNCTION__); + } + } while (frame->frameState == FrameState_Grabbing); + if (uvd->debug >= 2) { + info("%s: Grabbing done; state=%d. (%lu. bytes)", + __FUNCTION__, frame->frameState, frame->seqRead_Length); + } + if (frame->frameState == FrameState_Error) { + int ret = usbvideo_NewFrame(uvd, frameNum); + if (ret < 0) { + err("%s: usbvideo_NewFrame() failed (%d.)", __FUNCTION__, ret); + return ret; + } + goto redo; + } + /* Note that we fall through to meet our destiny below */ + } + case FrameState_Done: + /* + * Do all necessary postprocessing of data prepared in + * "interrupt" code and the collecting code above. The + * frame gets marked as FrameState_Done by queue parsing code. + * This status means that we collected enough data and + * most likely processed it as we went through. However + * the data may need postprocessing, such as deinterlacing + * or picture adjustments implemented in software (horror!) + * + * As soon as the frame becomes "final" it gets promoted to + * FrameState_Done_Hold status where it will remain until the + * caller consumed all the video data from the frame. Then + * the empty shell of ex-frame is thrown out for dogs to eat. + * But we, worried about pets, will recycle the frame! + */ + uvd->stats.frame_num++; + if ((uvd->flags & FLAGS_NO_DECODING) == 0) { + if (VALID_CALLBACK(uvd, postProcess)) + GET_CALLBACK(uvd, postProcess)(uvd, frame); + if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST) + usbvideo_SoftwareContrastAdjustment(uvd, frame); + } + frame->frameState = FrameState_Done_Hold; + if (uvd->debug >= 2) + info("%s: Entered FrameState_Done_Hold state.", __FUNCTION__); + return 0; + + case FrameState_Done_Hold: + /* + * We stay in this state indefinitely until someone external, + * like ioctl() or read() call finishes digesting the frame + * data. Then it will mark the frame as FrameState_Unused and + * it will be released back into the wild to roam freely. + */ + if (uvd->debug >= 2) + info("%s: FrameState_Done_Hold state.", __FUNCTION__); + return 0; + } + + /* Catch-all for other cases. We shall not be here. */ + err("%s: Invalid state %d.", __FUNCTION__, frame->frameState); + frame->frameState = FrameState_Unused; + return 0; +} + +/* + * usbvideo_DeinterlaceFrame() + * + * This procedure deinterlaces the given frame. Some cameras produce + * only half of scanlines - sometimes only even lines, sometimes only + * odd lines. The deinterlacing method is stored in frame->deinterlace + * variable. + * + * Here we scan the frame vertically and replace missing scanlines with + * average between surrounding ones - before and after. If we have no + * line above then we just copy next line. Similarly, if we need to + * create a last line then preceding line is used. + */ +void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame) +{ + if ((uvd == NULL) || (frame == NULL)) + return; + + if ((frame->deinterlace == Deinterlace_FillEvenLines) || + (frame->deinterlace == Deinterlace_FillOddLines)) + { + const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; + int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1; + + for (; i < VIDEOSIZE_Y(frame->request); i += 2) { + const unsigned char *fs1, *fs2; + unsigned char *fd; + int ip, in, j; /* Previous and next lines */ + + /* + * Need to average lines before and after 'i'. + * If we go out of bounds seeking those lines then + * we point back to existing line. + */ + ip = i - 1; /* First, get rough numbers */ + in = i + 1; + + /* Now validate */ + if (ip < 0) + ip = in; + if (in >= VIDEOSIZE_Y(frame->request)) + in = ip; + + /* Sanity check */ + if ((ip < 0) || (in < 0) || + (ip >= VIDEOSIZE_Y(frame->request)) || + (in >= VIDEOSIZE_Y(frame->request))) + { + err("Error: ip=%d. in=%d. req.height=%ld.", + ip, in, VIDEOSIZE_Y(frame->request)); + break; + } + + /* Now we need to average lines 'ip' and 'in' to produce line 'i' */ + fs1 = frame->data + (v4l_linesize * ip); + fs2 = frame->data + (v4l_linesize * in); + fd = frame->data + (v4l_linesize * i); + + /* Average lines around destination */ + for (j=0; j < v4l_linesize; j++) { + fd[j] = (unsigned char)((((unsigned) fs1[j]) + + ((unsigned)fs2[j])) >> 1); + } + } + } + + /* Optionally display statistics on the screen */ + if (uvd->flags & FLAGS_OVERLAY_STATS) + usbvideo_OverlayStats(uvd, frame); +} + +EXPORT_SYMBOL(usbvideo_DeinterlaceFrame); + +/* + * usbvideo_SoftwareContrastAdjustment() + * + * This code adjusts the contrast of the frame, assuming RGB24 format. + * As most software image processing, this job is CPU-intensive. + * Get a camera that supports hardware adjustment! + * + * History: + * 09-Feb-2001 Created. + */ +static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, + struct usbvideo_frame *frame) +{ + int i, j, v4l_linesize; + signed long adj; + const int ccm = 128; /* Color correction median - see below */ + + if ((uvd == NULL) || (frame == NULL)) { + err("%s: Illegal call.", __FUNCTION__); + return; + } + adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ + RESTRICT_TO_RANGE(adj, -ccm, ccm+1); + if (adj == 0) { + /* In rare case of no adjustment */ + return; + } + v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; + for (i=0; i < VIDEOSIZE_Y(frame->request); i++) { + unsigned char *fd = frame->data + (v4l_linesize * i); + for (j=0; j < v4l_linesize; j++) { + signed long v = (signed long) fd[j]; + /* Magnify up to 2 times, reduce down to zero */ + v = 128 + ((ccm + adj) * (v - 128)) / ccm; + RESTRICT_TO_RANGE(v, 0, 0xFF); /* Must flatten tails */ + fd[j] = (unsigned char) v; + } + } +} + +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/usbvideo/usbvideo.h b/drivers/media/video/usbvideo/usbvideo.h new file mode 100644 index 000000000000..135433c2680a --- /dev/null +++ b/drivers/media/video/usbvideo/usbvideo.h @@ -0,0 +1,394 @@ +/* + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef usbvideo_h +#define usbvideo_h + +#include +#include +#include +#include + +/* Most helpful debugging aid */ +#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__)))) + +#define USBVIDEO_REPORT_STATS 1 /* Set to 0 to block statistics on close */ + +/* Bit flags (options) */ +#define FLAGS_RETRY_VIDIOCSYNC (1 << 0) +#define FLAGS_MONOCHROME (1 << 1) +#define FLAGS_DISPLAY_HINTS (1 << 2) +#define FLAGS_OVERLAY_STATS (1 << 3) +#define FLAGS_FORCE_TESTPATTERN (1 << 4) +#define FLAGS_SEPARATE_FRAMES (1 << 5) +#define FLAGS_CLEAN_FRAMES (1 << 6) +#define FLAGS_NO_DECODING (1 << 7) + +/* Bit flags for frames (apply to the frame where they are specified) */ +#define USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST (1 << 0) + +/* Camera capabilities (maximum) */ +#define CAMERA_URB_FRAMES 32 +#define CAMERA_MAX_ISO_PACKET 1023 /* 1022 actually sent by camera */ +#define FRAMES_PER_DESC (CAMERA_URB_FRAMES) +#define FRAME_SIZE_PER_DESC (CAMERA_MAX_ISO_PACKET) + +/* This macro restricts an int variable to an inclusive range */ +#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } + +#define V4L_BYTES_PER_PIXEL 3 /* Because we produce RGB24 */ + +/* + * Use this macro to construct constants for different video sizes. + * We have to deal with different video sizes that have to be + * configured in the device or compared against when we receive + * a data. Normally one would define a bunch of VIDEOSIZE_x_by_y + * #defines and that's the end of story. However this solution + * does not allow to convert between real pixel sizes and the + * constant (integer) value that may be used to tag a frame or + * whatever. The set of macros below constructs videosize constants + * from the pixel size and allows to reconstruct the pixel size + * from the combined value later. + */ +#define VIDEOSIZE(x,y) (((x) & 0xFFFFL) | (((y) & 0xFFFFL) << 16)) +#define VIDEOSIZE_X(vs) ((vs) & 0xFFFFL) +#define VIDEOSIZE_Y(vs) (((vs) >> 16) & 0xFFFFL) +typedef unsigned long videosize_t; + +/* + * This macro checks if the camera is still operational. The 'uvd' + * pointer must be valid, uvd->dev must be valid, we are not + * removing the device and the device has not erred on us. + */ +#define CAMERA_IS_OPERATIONAL(uvd) (\ + (uvd != NULL) && \ + ((uvd)->dev != NULL) && \ + ((uvd)->last_error == 0) && \ + (!(uvd)->remove_pending)) + +/* + * We use macros to do YUV -> RGB conversion because this is + * very important for speed and totally unimportant for size. + * + * YUV -> RGB Conversion + * --------------------- + * + * B = 1.164*(Y-16) + 2.018*(V-128) + * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) + * R = 1.164*(Y-16) + 1.596*(U-128) + * + * If you fancy integer arithmetics (as you should), hear this: + * + * 65536*B = 76284*(Y-16) + 132252*(V-128) + * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) + * 65536*R = 76284*(Y-16) + 104595*(U-128) + * + * Make sure the output values are within [0..255] range. + */ +#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) +#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ + int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ + mm_y = (my) - 16; \ + mm_u = (mu) - 128; \ + mm_v = (mv) - 128; \ + mm_yc= mm_y * 76284; \ + mm_b = (mm_yc + 132252*mm_v ) >> 16; \ + mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ + mm_r = (mm_yc + 104595*mm_u ) >> 16; \ + mb = LIMIT_RGB(mm_b); \ + mg = LIMIT_RGB(mm_g); \ + mr = LIMIT_RGB(mm_r); \ +} + +#define RING_QUEUE_SIZE (128*1024) /* Must be a power of 2 */ +#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1) +#define RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n) +#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)]) + +struct RingQueue { + unsigned char *queue; /* Data from the Isoc data pump */ + int length; /* How many bytes allocated for the queue */ + int wi; /* That's where we write */ + int ri; /* Read from here until you hit write index */ + wait_queue_head_t wqh; /* Processes waiting */ +}; + +enum ScanState { + ScanState_Scanning, /* Scanning for header */ + ScanState_Lines /* Parsing lines */ +}; + +/* Completion states of the data parser */ +enum ParseState { + scan_Continue, /* Just parse next item */ + scan_NextFrame, /* Frame done, send it to V4L */ + scan_Out, /* Not enough data for frame */ + scan_EndParse /* End parsing */ +}; + +enum FrameState { + FrameState_Unused, /* Unused (no MCAPTURE) */ + FrameState_Ready, /* Ready to start grabbing */ + FrameState_Grabbing, /* In the process of being grabbed into */ + FrameState_Done, /* Finished grabbing, but not been synced yet */ + FrameState_Done_Hold, /* Are syncing or reading */ + FrameState_Error, /* Something bad happened while processing */ +}; + +/* + * Some frames may contain only even or odd lines. This type + * specifies what type of deinterlacing is required. + */ +enum Deinterlace { + Deinterlace_None=0, + Deinterlace_FillOddLines, + Deinterlace_FillEvenLines +}; + +#define USBVIDEO_NUMFRAMES 2 /* How many frames we work with */ +#define USBVIDEO_NUMSBUF 2 /* How many URBs linked in a ring */ + +/* This structure represents one Isoc request - URB and buffer */ +struct usbvideo_sbuf { + char *data; + struct urb *urb; +}; + +struct usbvideo_frame { + char *data; /* Frame buffer */ + unsigned long header; /* Significant bits from the header */ + + videosize_t canvas; /* The canvas (max. image) allocated */ + videosize_t request; /* That's what the application asked for */ + unsigned short palette; /* The desired format */ + + enum FrameState frameState;/* State of grabbing */ + enum ScanState scanstate; /* State of scanning */ + enum Deinterlace deinterlace; + int flags; /* USBVIDEO_FRAME_FLAG_xxx bit flags */ + + int curline; /* Line of frame we're working on */ + + long seqRead_Length; /* Raw data length of frame */ + long seqRead_Index; /* Amount of data that has been already read */ + + void *user; /* Additional data that user may need */ +}; + +/* Statistics that can be overlaid on screen */ +struct usbvideo_statistics { + unsigned long frame_num; /* Sequential number of the frame */ + unsigned long urb_count; /* How many URBs we received so far */ + unsigned long urb_length; /* Length of last URB */ + unsigned long data_count; /* How many bytes we received */ + unsigned long header_count; /* How many frame headers we found */ + unsigned long iso_skip_count; /* How many empty ISO packets received */ + unsigned long iso_err_count; /* How many bad ISO packets received */ +}; + +struct usbvideo; + +struct uvd { + struct video_device vdev; /* Must be the first field! */ + struct usb_device *dev; + struct usbvideo *handle; /* Points back to the struct usbvideo */ + void *user_data; /* Camera-dependent data */ + int user_size; /* Size of that camera-dependent data */ + int debug; /* Debug level for usbvideo */ + unsigned char iface; /* Video interface number */ + unsigned char video_endp; + unsigned char ifaceAltActive; + unsigned char ifaceAltInactive; /* Alt settings */ + unsigned long flags; /* FLAGS_USBVIDEO_xxx */ + unsigned long paletteBits; /* Which palettes we accept? */ + unsigned short defaultPalette; /* What palette to use for read() */ + struct mutex lock; + int user; /* user count for exclusive use */ + + videosize_t videosize; /* Current setting */ + videosize_t canvas; /* This is the width,height of the V4L canvas */ + int max_frame_size; /* Bytes in one video frame */ + + int uvd_used; /* Is this structure in use? */ + int streaming; /* Are we streaming Isochronous? */ + int grabbing; /* Are we grabbing? */ + int settingsAdjusted; /* Have we adjusted contrast etc.? */ + int last_error; /* What calamity struck us? */ + + char *fbuf; /* Videodev buffer area */ + int fbuf_size; /* Videodev buffer size */ + + int curframe; + int iso_packet_len; /* Videomode-dependent, saves bus bandwidth */ + + struct RingQueue dp; /* Isoc data pump */ + struct usbvideo_frame frame[USBVIDEO_NUMFRAMES]; + struct usbvideo_sbuf sbuf[USBVIDEO_NUMSBUF]; + + volatile int remove_pending; /* If set then about to exit */ + + struct video_picture vpic, vpic_old; /* Picture settings */ + struct video_capability vcap; /* Video capabilities */ + struct video_channel vchan; /* May be used for tuner support */ + struct usbvideo_statistics stats; + char videoName[32]; /* Holds name like "video7" */ +}; + +/* + * usbvideo callbacks (virtual methods). They are set when usbvideo + * services are registered. All of these default to NULL, except those + * that default to usbvideo-provided methods. + */ +struct usbvideo_cb { + int (*probe)(struct usb_interface *, const struct usb_device_id *); + void (*userFree)(struct uvd *); + void (*disconnect)(struct usb_interface *); + int (*setupOnOpen)(struct uvd *); + void (*videoStart)(struct uvd *); + void (*videoStop)(struct uvd *); + void (*processData)(struct uvd *, struct usbvideo_frame *); + void (*postProcess)(struct uvd *, struct usbvideo_frame *); + void (*adjustPicture)(struct uvd *); + int (*getFPS)(struct uvd *); + int (*overlayHook)(struct uvd *, struct usbvideo_frame *); + int (*getFrame)(struct uvd *, int); + int (*startDataPump)(struct uvd *uvd); + void (*stopDataPump)(struct uvd *uvd); + int (*setVideoMode)(struct uvd *uvd, struct video_window *vw); +}; + +struct usbvideo { + int num_cameras; /* As allocated */ + struct usb_driver usbdrv; /* Interface to the USB stack */ + char drvName[80]; /* Driver name */ + struct mutex lock; /* Mutex protecting camera structures */ + struct usbvideo_cb cb; /* Table of callbacks (virtual methods) */ + struct video_device vdt; /* Video device template */ + struct uvd *cam; /* Array of camera structures */ + struct module *md_module; /* Minidriver module */ +}; + + +/* + * This macro retrieves callback address from the struct uvd object. + * No validity checks are done here, so be sure to check the + * callback beforehand with VALID_CALLBACK. + */ +#define GET_CALLBACK(uvd,cbName) ((uvd)->handle->cb.cbName) + +/* + * This macro returns either callback pointer or NULL. This is safe + * macro, meaning that most of components of data structures involved + * may be NULL - this only results in NULL being returned. You may + * wish to use this macro to make sure that the callback is callable. + * However keep in mind that those checks take time. + */ +#define VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \ + ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL) + +int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len); +int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n); +void RingQueue_WakeUpInterruptible(struct RingQueue *rq); +void RingQueue_Flush(struct RingQueue *rq); + +static inline int RingQueue_GetLength(const struct RingQueue *rq) +{ + return (rq->wi - rq->ri + rq->length) & (rq->length-1); +} + +static inline int RingQueue_GetFreeSpace(const struct RingQueue *rq) +{ + return rq->length - RingQueue_GetLength(rq); +} + +void usbvideo_DrawLine( + struct usbvideo_frame *frame, + int x1, int y1, + int x2, int y2, + unsigned char cr, unsigned char cg, unsigned char cb); +void usbvideo_HexDump(const unsigned char *data, int len); +void usbvideo_SayAndWait(const char *what); +void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode); + +/* Memory allocation routines */ +unsigned long usbvideo_kvirt_to_pa(unsigned long adr); + +int usbvideo_register( + struct usbvideo **pCams, + const int num_cams, + const int num_extra, + const char *driverName, + const struct usbvideo_cb *cbTable, + struct module *md, + const struct usb_device_id *id_table); +struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams); +int usbvideo_RegisterVideoDevice(struct uvd *uvd); +void usbvideo_Deregister(struct usbvideo **uvt); + +int usbvideo_v4l_initialize(struct video_device *dev); + +void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame); + +/* + * This code performs bounds checking - use it when working with + * new formats, or else you may get oopses all over the place. + * If pixel falls out of bounds then it gets shoved back (as close + * to place of offence as possible) and is painted bright red. + * + * There are two important concepts: frame width, height and + * V4L canvas width, height. The former is the area requested by + * the application -for this very frame-. The latter is the largest + * possible frame that we can serve (we advertise that via V4L ioctl). + * The frame data is expected to be formatted as lines of length + * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines. + */ +static inline void RGB24_PUTPIXEL( + struct usbvideo_frame *fr, + int ix, int iy, + unsigned char vr, + unsigned char vg, + unsigned char vb) +{ + register unsigned char *pf; + int limiter = 0, mx, my; + mx = ix; + my = iy; + if (mx < 0) { + mx=0; + limiter++; + } else if (mx >= VIDEOSIZE_X((fr)->request)) { + mx= VIDEOSIZE_X((fr)->request) - 1; + limiter++; + } + if (my < 0) { + my = 0; + limiter++; + } else if (my >= VIDEOSIZE_Y((fr)->request)) { + my = VIDEOSIZE_Y((fr)->request) - 1; + limiter++; + } + pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*VIDEOSIZE_X((fr)->request) + (ix)); + if (limiter) { + *pf++ = 0; + *pf++ = 0; + *pf++ = 0xFF; + } else { + *pf++ = (vb); + *pf++ = (vg); + *pf++ = (vr); + } +} + +#endif /* usbvideo_h */ diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c new file mode 100644 index 000000000000..1d06e53ec7c5 --- /dev/null +++ b/drivers/media/video/usbvideo/vicam.c @@ -0,0 +1,1411 @@ +/* + * USB ViCam WebCam driver + * Copyright (c) 2002 Joe Burks (jburks@wavicle.org), + * Christopher L Cheney (ccheney@cheney.cx), + * Pavel Machek (pavel@suse.cz), + * John Tyner (jtyner@cs.ucr.edu), + * Monroe Williams (monroe@pobox.com) + * + * Supports 3COM HomeConnect PC Digital WebCam + * + * 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 source code is based heavily on the CPiA webcam driver which was + * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt + * + * Portions of this code were also copied from usbvideo.c + * + * Special thanks to the the whole team at Sourceforge for help making + * this driver become a reality. Notably: + * Andy Armstrong who reverse engineered the color encoding and + * Pavel Machek and Chris Cheney who worked on reverse engineering the + * camera controls and wrote the first generation driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "usbvideo.h" + +// #define VICAM_DEBUG + +#ifdef VICAM_DEBUG +#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args) +#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args) +#else +#define DBG(fmn,args...) do {} while(0) +#endif + +#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org" +#define DRIVER_DESC "ViCam WebCam Driver" + +/* Define these values to match your device */ +#define USB_VICAM_VENDOR_ID 0x04c1 +#define USB_VICAM_PRODUCT_ID 0x009d + +#define VICAM_BYTES_PER_PIXEL 3 +#define VICAM_MAX_READ_SIZE (512*242+128) +#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240) +#define VICAM_FRAMES 2 + +#define VICAM_HEADER_SIZE 64 + +#define clamp( x, l, h ) max_t( __typeof__( x ), \ + ( l ), \ + min_t( __typeof__( x ), \ + ( h ), \ + ( x ) ) ) + +/* Not sure what all the bytes in these char + * arrays do, but they're necessary to make + * the camera work. + */ + +static unsigned char setup1[] = { + 0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64, 0xE7, 0x67, + 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09, 0xDE, 0x00, + 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03, 0xC0, 0x17, + 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07, 0x00, 0x00, + 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00 +}; + +static unsigned char setup2[] = { + 0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64, 0x18, 0x00, + 0x00, 0x00 +}; + +static unsigned char setup3[] = { + 0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00 +}; + +static unsigned char setup4[] = { + 0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64, 0xE7, 0x07, + 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07, 0x00, 0x00, + 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01, 0xAA, 0x00, + 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00, 0xE7, 0x07, + 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07, 0x7C, 0x00, + 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00, 0x18, 0x00, + 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0, 0xE7, 0x07, + 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF, + 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00, 0x24, 0xC0, + 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0, 0xE7, 0x07, + 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87, 0x01, 0x00, + 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09, 0x00, 0xC0, + 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0, 0x09, 0xC1, + 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01, 0xE7, 0x09, + 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07, 0x07, 0x00, + 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0, 0xC0, 0xDF, + 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00, 0x17, 0x02, + 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00, + 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57, 0xFF, 0xFF, + 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57, 0x00, 0x00, + 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF, 0xC6, 0x00, + 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05, 0xC1, 0x05, + 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF, 0x27, 0xDA, + 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x0B, 0x06, + 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01, 0x9F, 0xAF, + 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09, 0xFC, 0x05, + 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06, 0x26, 0x01, + 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0, 0xE7, 0x09, + 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09, 0x02, 0x06, + 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06, 0xFC, 0x05, + 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06, 0x27, 0xDA, + 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00, 0xFA, 0x05, + 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, + 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07, 0x40, 0x00, + 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05, 0x9F, 0xAF, + 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17, 0x02, 0x00, + 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06, 0x9F, 0xA0, + 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00, 0x09, 0x06, + 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57, 0x01, 0x00, + 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03, 0xE7, 0x07, + 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF, 0x47, 0xAF, + 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07, 0x2E, 0x00, + 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06, + 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00, 0xC0, 0x57, + 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02, 0xC0, 0x57, + 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57, 0x55, 0x00, + 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00, 0x9F, 0xC0, + 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02, 0xC1, 0x0B, + 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90, 0x08, 0x06, + 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06, + 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF, 0x2F, 0x0E, + 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07, 0x08, 0x00, + 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05, + 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E, 0x02, 0x00, + 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06, + 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67, 0x7F, 0xFF, + 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD, 0x22, 0xC0, + 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0, 0xE7, 0x87, + 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF, 0xB8, 0x05, + 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0, 0x9F, 0xAF, + 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00, 0x24, 0xC0, + 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0, 0xC8, 0x07, + 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00, 0xC1, 0x07, + 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0x9F, 0xAF, + 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00, 0x9F, 0xAF, + 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0, + 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01, + 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02, 0x0F, 0xC1, + 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x67, + 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x08, 0x00, + 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1, 0xEF, 0x07, + 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF, 0xEF, 0x07, + 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF, 0xEF, 0x07, + 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07, 0x00, 0x00, + 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF, 0x09, 0x06, + 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xE7, 0x67, + 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67, 0x17, 0xD8, + 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0, + 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0, 0x97, 0xCF, + 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF, 0xDA, 0x02, + 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07, + 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0x0E, 0x06, + 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02, 0xF8, 0x05, + 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80, + 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C, 0x02, 0x00, + 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00, 0x06, 0x06, + 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07, + 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0xE2, 0x05, + 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02, 0xF8, 0x05, + 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80, + 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF, 0x66, 0x04, + 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF, 0x97, 0xCF, + 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B, 0x0C, 0x06, + 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, + 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0x68, 0x00, + 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF, 0x44, 0x05, + 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00, 0xE0, 0x07, + 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06, 0xE8, 0x07, + 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02, 0xE0, 0x07, + 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF, 0x97, 0xCF, + 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05, 0xEF, 0x07, + 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07, 0x0E, 0x06, + 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06, 0xFE, 0x05, + 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01, 0xE7, 0x07, + 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07, 0x07, 0x00, + 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07, 0x02, 0x00, + 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01, 0xEF, 0x77, + 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0, 0x14, 0x04, + 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06, 0x37, 0xC0, + 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06, 0x0F, 0xC1, + 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06, 0xC0, 0x07, + 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00, 0x9F, 0xAF, + 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, + 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07, + 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07, + 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x77, + 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA, 0x75, 0xC1, + 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1, 0xC0, 0x07, + 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF, + 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x06, 0x06, + 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, + 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07, + 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF, 0xEF, 0x07, + 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57, 0x01, 0x00, + 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07, 0x01, 0x00, + 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05, + 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00, + 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07, 0xFF, 0x4F, + 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07, 0x38, 0x00, + 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67, 0x03, 0x00, + 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0, 0x08, 0xDA, + 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, + 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00, 0x06, 0x06, + 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00, 0x9F, 0xAF, + 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00, 0xC1, 0x0B, + 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, + 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x09, + 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8, 0xFA, 0x05, + 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05, 0xE7, 0x07, + 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07, 0x40, 0x00, + 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05, 0x9F, 0xAF, + 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B, 0xE2, 0x05, + 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17, 0x23, 0x00, + 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07, 0x04, 0x00, + 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF, 0x28, 0x05, + 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09, 0xE6, 0x05, + 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x07, 0x00, + 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1, 0x9F, 0xAF, + 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00, 0xC1, 0x09, + 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, + 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05, 0xC1, 0xD1, + 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0D, 0x00, + 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF, 0x28, 0x05, + 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07, 0x32, 0x00, + 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0F, 0x00, + 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF, 0x28, 0x05, + 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9, 0x24, 0xC0, + 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00, 0xC0, 0x67, + 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0, 0xE7, 0x87, + 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xF9, + 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA, 0x72, 0xC1, + 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0, 0x97, 0xCF, + 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87, 0xFF, 0x00, + 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF, 0x24, 0xC0, + 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0xE7, 0x87, + 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, + 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0, 0xE7, 0x67, + 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, + 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, + 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x67, + 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, + 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0, + 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01, + 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07, 0x40, 0x00, + 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67, 0x00, 0xFF, + 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0, + 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x67, + 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA, 0xE8, 0x09, + 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, + 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, 0x00, 0xDA, + 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1, 0xE7, 0x87, + 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xE7, 0x07, + 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80, + 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0xE7, 0x07, + 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80, + 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0x09, 0x02, + 0x19, 0x00, 0x01, 0x01, 0x00, 0x80, 0x96, 0x09, + 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static unsigned char setup5[] = { + 0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64, 0x0E, 0x00, + 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00, 0x26, 0x00, + 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00, 0x92, 0x00, + 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00, 0xB8, 0x00, + 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00, 0xCE, 0x00, + 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00, 0xE0, 0x00, + 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00, 0xEC, 0x00, + 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01, 0x0A, 0x01, + 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01, 0x22, 0x01, + 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01, 0x36, 0x01, + 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01, 0x72, 0x01, + 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01, 0x88, 0x01, + 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01, 0xA0, 0x01, + 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01, 0xB4, 0x01, + 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01, 0xF6, 0x01, + 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02, 0x3C, 0x02, + 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02, 0x56, 0x02, + 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02, 0x84, 0x02, + 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02, 0x8E, 0x02, + 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02, 0xAE, 0x02, + 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02, 0xC0, 0x02, + 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02, 0xD4, 0x02, + 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02, 0xF8, 0x02, + 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03, 0x24, 0x03, + 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03, 0x3C, 0x03, + 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03, 0x58, 0x03, + 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03, 0x7A, 0x03, + 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03, 0xB2, 0x03, + 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03, 0xD4, 0x03, + 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03, 0xFC, 0x03, + 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04, 0x32, 0x04, + 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04, 0x42, 0x04, + 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04, 0x54, 0x04, + 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04, 0x62, 0x04, + 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04, 0x80, 0x04, + 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04, 0x9A, 0x04, + 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04, 0xB4, 0x04, + 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04, 0x2A, 0x05, + 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00 +}; + +/* rvmalloc / rvfree copied from usbvideo.c + * + * Not sure why these are not yet non-statics which I can reference through + * usbvideo.h the same as it is in 2.4.20. I bet this will get fixed sometime + * in the future. + * +*/ +static void *rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + +static void rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + +struct vicam_camera { + u16 shutter_speed; // capture shutter speed + u16 gain; // capture gain + + u8 *raw_image; // raw data captured from the camera + u8 *framebuf; // processed data in RGB24 format + u8 *cntrlbuf; // area used to send control msgs + + struct video_device vdev; // v4l video device + struct usb_device *udev; // usb device + + /* guard against simultaneous accesses to the camera */ + struct mutex cam_lock; + + int is_initialized; + u8 open_count; + u8 bulkEndpoint; + int needsDummyRead; + +#if defined(CONFIG_VIDEO_PROC_FS) + struct proc_dir_entry *proc_dir; +#endif + +}; + +static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id); +static void vicam_disconnect(struct usb_interface *intf); +static void read_frame(struct vicam_camera *cam, int framenum); +static void vicam_decode_color(const u8 *, u8 *); + +static int __send_control_msg(struct vicam_camera *cam, + u8 request, + u16 value, + u16 index, + unsigned char *cp, + u16 size) +{ + int status; + + /* cp must be memory that has been allocated by kmalloc */ + + status = usb_control_msg(cam->udev, + usb_sndctrlpipe(cam->udev, 0), + request, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, + cp, size, 1000); + + status = min(status, 0); + + if (status < 0) { + printk(KERN_INFO "Failed sending control message, error %d.\n", + status); + } + + return status; +} + +static int send_control_msg(struct vicam_camera *cam, + u8 request, + u16 value, + u16 index, + unsigned char *cp, + u16 size) +{ + int status = -ENODEV; + mutex_lock(&cam->cam_lock); + if (cam->udev) { + status = __send_control_msg(cam, request, value, + index, cp, size); + } + mutex_unlock(&cam->cam_lock); + return status; +} +static int +initialize_camera(struct vicam_camera *cam) +{ + const struct { + u8 *data; + u32 size; + } firmware[] = { + { .data = setup1, .size = sizeof(setup1) }, + { .data = setup2, .size = sizeof(setup2) }, + { .data = setup3, .size = sizeof(setup3) }, + { .data = setup4, .size = sizeof(setup4) }, + { .data = setup5, .size = sizeof(setup5) }, + { .data = setup3, .size = sizeof(setup3) }, + { .data = NULL, .size = 0 } + }; + + int err, i; + + for (i = 0, err = 0; firmware[i].data && !err; i++) { + memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size); + + err = send_control_msg(cam, 0xff, 0, 0, + cam->cntrlbuf, firmware[i].size); + } + + return err; +} + +static int +set_camera_power(struct vicam_camera *cam, int state) +{ + int status; + + if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0) + return status; + + if (state) { + send_control_msg(cam, 0x55, 1, 0, NULL, 0); + } + + return 0; +} + +static int +vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg) +{ + void __user *user_arg = (void __user *)arg; + struct vicam_camera *cam = file->private_data; + int retval = 0; + + if (!cam) + return -ENODEV; + + switch (ioctlnr) { + /* query capabilities */ + case VIDIOCGCAP: + { + struct video_capability b; + + DBG("VIDIOCGCAP\n"); + memset(&b, 0, sizeof(b)); + strcpy(b.name, "ViCam-based Camera"); + b.type = VID_TYPE_CAPTURE; + b.channels = 1; + b.audios = 0; + b.maxwidth = 320; /* VIDEOSIZE_CIF */ + b.maxheight = 240; + b.minwidth = 320; /* VIDEOSIZE_48_48 */ + b.minheight = 240; + + if (copy_to_user(user_arg, &b, sizeof(b))) + retval = -EFAULT; + + break; + } + /* get/set video source - we are a camera and nothing else */ + case VIDIOCGCHAN: + { + struct video_channel v; + + DBG("VIDIOCGCHAN\n"); + if (copy_from_user(&v, user_arg, sizeof(v))) { + retval = -EFAULT; + break; + } + if (v.channel != 0) { + retval = -EINVAL; + break; + } + + v.channel = 0; + strcpy(v.name, "Camera"); + v.tuners = 0; + v.flags = 0; + v.type = VIDEO_TYPE_CAMERA; + v.norm = 0; + + if (copy_to_user(user_arg, &v, sizeof(v))) + retval = -EFAULT; + break; + } + + case VIDIOCSCHAN: + { + int v; + + if (copy_from_user(&v, user_arg, sizeof(v))) + retval = -EFAULT; + DBG("VIDIOCSCHAN %d\n", v); + + if (retval == 0 && v != 0) + retval = -EINVAL; + + break; + } + + /* image properties */ + case VIDIOCGPICT: + { + struct video_picture vp; + DBG("VIDIOCGPICT\n"); + memset(&vp, 0, sizeof (struct video_picture)); + vp.brightness = cam->gain << 8; + vp.depth = 24; + vp.palette = VIDEO_PALETTE_RGB24; + if (copy_to_user(user_arg, &vp, sizeof (struct video_picture))) + retval = -EFAULT; + break; + } + + case VIDIOCSPICT: + { + struct video_picture vp; + + if (copy_from_user(&vp, user_arg, sizeof(vp))) { + retval = -EFAULT; + break; + } + + DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth, + vp.palette); + + cam->gain = vp.brightness >> 8; + + if (vp.depth != 24 + || vp.palette != VIDEO_PALETTE_RGB24) + retval = -EINVAL; + + break; + } + + /* get/set capture window */ + case VIDIOCGWIN: + { + struct video_window vw; + vw.x = 0; + vw.y = 0; + vw.width = 320; + vw.height = 240; + vw.chromakey = 0; + vw.flags = 0; + vw.clips = NULL; + vw.clipcount = 0; + + DBG("VIDIOCGWIN\n"); + + if (copy_to_user(user_arg, (void *)&vw, sizeof(vw))) + retval = -EFAULT; + + // I'm not sure what the deal with a capture window is, it is very poorly described + // in the doc. So I won't support it now. + break; + } + + case VIDIOCSWIN: + { + + struct video_window vw; + + if (copy_from_user(&vw, user_arg, sizeof(vw))) { + retval = -EFAULT; + break; + } + + DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height); + + if ( vw.width != 320 || vw.height != 240 ) + retval = -EFAULT; + + break; + } + + /* mmap interface */ + case VIDIOCGMBUF: + { + struct video_mbuf vm; + int i; + + DBG("VIDIOCGMBUF\n"); + memset(&vm, 0, sizeof (vm)); + vm.size = + VICAM_MAX_FRAME_SIZE * VICAM_FRAMES; + vm.frames = VICAM_FRAMES; + for (i = 0; i < VICAM_FRAMES; i++) + vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i; + + if (copy_to_user(user_arg, (void *)&vm, sizeof(vm))) + retval = -EFAULT; + + break; + } + + case VIDIOCMCAPTURE: + { + struct video_mmap vm; + // int video_size; + + if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) { + retval = -EFAULT; + break; + } + + DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format); + + if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 ) + retval = -EINVAL; + + // in theory right here we'd start the image capturing + // (fill in a bulk urb and submit it asynchronously) + // + // Instead we're going to do a total hack job for now and + // retrieve the frame in VIDIOCSYNC + + break; + } + + case VIDIOCSYNC: + { + int frame; + + if (copy_from_user((void *)&frame, user_arg, sizeof(int))) { + retval = -EFAULT; + break; + } + DBG("VIDIOCSYNC: %d\n", frame); + + read_frame(cam, frame); + vicam_decode_color(cam->raw_image, + cam->framebuf + + frame * VICAM_MAX_FRAME_SIZE ); + + break; + } + + /* pointless to implement overlay with this camera */ + case VIDIOCCAPTURE: + case VIDIOCGFBUF: + case VIDIOCSFBUF: + case VIDIOCKEY: + retval = -EINVAL; + break; + + /* tuner interface - we have none */ + case VIDIOCGTUNER: + case VIDIOCSTUNER: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + retval = -EINVAL; + break; + + /* audio interface - we have none */ + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + retval = -EINVAL; + break; + default: + retval = -ENOIOCTLCMD; + break; + } + + return retval; +} + +static int +vicam_open(struct inode *inode, struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct vicam_camera *cam = + (struct vicam_camera *) dev->priv; + DBG("open\n"); + + if (!cam) { + printk(KERN_ERR + "vicam video_device improperly initialized"); + return -EINVAL; + } + + /* the videodev_lock held above us protects us from + * simultaneous opens...for now. we probably shouldn't + * rely on this fact forever. + */ + + if (cam->open_count > 0) { + printk(KERN_INFO + "vicam_open called on already opened camera"); + return -EBUSY; + } + + cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); + if (!cam->raw_image) { + return -ENOMEM; + } + + cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); + if (!cam->framebuf) { + kfree(cam->raw_image); + return -ENOMEM; + } + + cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!cam->cntrlbuf) { + kfree(cam->raw_image); + rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); + return -ENOMEM; + } + + // First upload firmware, then turn the camera on + + if (!cam->is_initialized) { + initialize_camera(cam); + + cam->is_initialized = 1; + } + + set_camera_power(cam, 1); + + cam->needsDummyRead = 1; + cam->open_count++; + + file->private_data = cam; + + return 0; +} + +static int +vicam_close(struct inode *inode, struct file *file) +{ + struct vicam_camera *cam = file->private_data; + int open_count; + struct usb_device *udev; + + DBG("close\n"); + + /* it's not the end of the world if + * we fail to turn the camera off. + */ + + set_camera_power(cam, 0); + + kfree(cam->raw_image); + rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); + kfree(cam->cntrlbuf); + + mutex_lock(&cam->cam_lock); + + cam->open_count--; + open_count = cam->open_count; + udev = cam->udev; + + mutex_unlock(&cam->cam_lock); + + if (!open_count && !udev) { + kfree(cam); + } + + return 0; +} + +static void vicam_decode_color(const u8 *data, u8 *rgb) +{ + /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB + * Copyright (C) 2002 Monroe Williams (monroe@pobox.com) + */ + + int i, prevY, nextY; + + prevY = 512; + nextY = 512; + + data += VICAM_HEADER_SIZE; + + for( i = 0; i < 240; i++, data += 512 ) { + const int y = ( i * 242 ) / 240; + + int j, prevX, nextX; + int Y, Cr, Cb; + + if ( y == 242 - 1 ) { + nextY = -512; + } + + prevX = 1; + nextX = 1; + + for ( j = 0; j < 320; j++, rgb += 3 ) { + const int x = ( j * 512 ) / 320; + const u8 * const src = &data[x]; + + if ( x == 512 - 1 ) { + nextX = -1; + } + + Cr = ( src[prevX] - src[0] ) + + ( src[nextX] - src[0] ); + Cr /= 2; + + Cb = ( src[prevY] - src[prevX + prevY] ) + + ( src[prevY] - src[nextX + prevY] ) + + ( src[nextY] - src[prevX + nextY] ) + + ( src[nextY] - src[nextX + nextY] ); + Cb /= 4; + + Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 ); + + if ( i & 1 ) { + int Ct = Cr; + Cr = Cb; + Cb = Ct; + } + + if ( ( x ^ i ) & 1 ) { + Cr = -Cr; + Cb = -Cb; + } + + rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) + + 500 ) / 900, 0, 255 ); + rgb[1] = clamp( ( ( Y - ( 392 * Cb ) - + ( 813 * Cr ) ) + + 500 ) / 1000, 0, 255 ); + rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) + + 500 ) / 1300, 0, 255 ); + + prevX = -1; + } + + prevY = -512; + } +} + +static void +read_frame(struct vicam_camera *cam, int framenum) +{ + unsigned char *request = cam->cntrlbuf; + int realShutter; + int n; + int actual_length; + + if (cam->needsDummyRead) { + cam->needsDummyRead = 0; + read_frame(cam, framenum); + } + + memset(request, 0, 16); + request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain + + request[1] = 0; // 512x242 capture + + request[2] = 0x90; // the function of these two bytes + request[3] = 0x07; // is not yet understood + + if (cam->shutter_speed > 60) { + // Short exposure + realShutter = + ((-15631900 / cam->shutter_speed) + 260533) / 1000; + request[4] = realShutter & 0xFF; + request[5] = (realShutter >> 8) & 0xFF; + request[6] = 0x03; + request[7] = 0x01; + } else { + // Long exposure + realShutter = 15600 / cam->shutter_speed - 1; + request[4] = 0; + request[5] = 0; + request[6] = realShutter & 0xFF; + request[7] = realShutter >> 8; + } + + // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0 + request[8] = 0; + // bytes 9-15 do not seem to affect exposure or image quality + + mutex_lock(&cam->cam_lock); + + if (!cam->udev) { + goto done; + } + + n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16); + + if (n < 0) { + printk(KERN_ERR + " Problem sending frame capture control message"); + goto done; + } + + n = usb_bulk_msg(cam->udev, + usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint), + cam->raw_image, + 512 * 242 + 128, &actual_length, 10000); + + if (n < 0) { + printk(KERN_ERR "Problem during bulk read of frame data: %d\n", + n); + } + + done: + mutex_unlock(&cam->cam_lock); +} + +static ssize_t +vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos ) +{ + struct vicam_camera *cam = file->private_data; + + DBG("read %d bytes.\n", (int) count); + + if (*ppos >= VICAM_MAX_FRAME_SIZE) { + *ppos = 0; + return 0; + } + + if (*ppos == 0) { + read_frame(cam, 0); + vicam_decode_color(cam->raw_image, + cam->framebuf + + 0 * VICAM_MAX_FRAME_SIZE); + } + + count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos); + + if (copy_to_user(buf, &cam->framebuf[*ppos], count)) { + count = -EFAULT; + } else { + *ppos += count; + } + + if (count == VICAM_MAX_FRAME_SIZE) { + *ppos = 0; + } + + return count; +} + + +static int +vicam_mmap(struct file *file, struct vm_area_struct *vma) +{ + // TODO: allocate the raw frame buffer if necessary + unsigned long page, pos; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end-vma->vm_start; + struct vicam_camera *cam = file->private_data; + + if (!cam) + return -ENODEV; + + DBG("vicam_mmap: %ld\n", size); + + /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes + * to the size the application requested for mmap and it was screwing apps up. + if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE) + return -EINVAL; + */ + + pos = (unsigned long)cam->framebuf; + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + return 0; +} + +#if defined(CONFIG_VIDEO_PROC_FS) + +static struct proc_dir_entry *vicam_proc_root = NULL; + +static int vicam_read_helper(char *page, char **start, off_t off, + int count, int *eof, int value) +{ + char *out = page; + int len; + + out += sprintf(out, "%d",value); + + 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 vicam_read_proc_shutter(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + return vicam_read_helper(page,start,off,count,eof, + ((struct vicam_camera *)data)->shutter_speed); +} + +static int vicam_read_proc_gain(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + return vicam_read_helper(page,start,off,count,eof, + ((struct vicam_camera *)data)->gain); +} + +static int +vicam_write_proc_shutter(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + u16 stmp; + char kbuf[8]; + struct vicam_camera *cam = (struct vicam_camera *) data; + + if (count > 6) + return -EINVAL; + + if (copy_from_user(kbuf, buffer, count)) + return -EFAULT; + + stmp = (u16) simple_strtoul(kbuf, NULL, 10); + if (stmp < 4 || stmp > 32000) + return -EINVAL; + + cam->shutter_speed = stmp; + + return count; +} + +static int +vicam_write_proc_gain(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + u16 gtmp; + char kbuf[8]; + + struct vicam_camera *cam = (struct vicam_camera *) data; + + if (count > 4) + return -EINVAL; + + if (copy_from_user(kbuf, buffer, count)) + return -EFAULT; + + gtmp = (u16) simple_strtoul(kbuf, NULL, 10); + if (gtmp > 255) + return -EINVAL; + cam->gain = gtmp; + + return count; +} + +static void +vicam_create_proc_root(void) +{ + vicam_proc_root = proc_mkdir("video/vicam", NULL); + + if (vicam_proc_root) + vicam_proc_root->owner = THIS_MODULE; + else + printk(KERN_ERR + "could not create /proc entry for vicam!"); +} + +static void +vicam_destroy_proc_root(void) +{ + if (vicam_proc_root) + remove_proc_entry("video/vicam", 0); +} + +static void +vicam_create_proc_entry(struct vicam_camera *cam) +{ + char name[64]; + struct proc_dir_entry *ent; + + DBG(KERN_INFO "vicam: creating proc entry\n"); + + if (!vicam_proc_root || !cam) { + printk(KERN_INFO + "vicam: could not create proc entry, %s pointer is null.\n", + (!cam ? "camera" : "root")); + return; + } + + sprintf(name, "video%d", cam->vdev.minor); + + cam->proc_dir = proc_mkdir(name, vicam_proc_root); + + if ( !cam->proc_dir ) + return; // FIXME: We should probably return an error here + + ent = create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR, + cam->proc_dir); + if (ent) { + ent->data = cam; + ent->read_proc = vicam_read_proc_shutter; + ent->write_proc = vicam_write_proc_shutter; + ent->size = 64; + } + + ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR, + cam->proc_dir); + if (ent) { + ent->data = cam; + ent->read_proc = vicam_read_proc_gain; + ent->write_proc = vicam_write_proc_gain; + ent->size = 64; + } +} + +static void +vicam_destroy_proc_entry(void *ptr) +{ + struct vicam_camera *cam = (struct vicam_camera *) ptr; + char name[16]; + + if ( !cam->proc_dir ) + return; + + sprintf(name, "video%d", cam->vdev.minor); + remove_proc_entry("shutter", cam->proc_dir); + remove_proc_entry("gain", cam->proc_dir); + remove_proc_entry(name,vicam_proc_root); + cam->proc_dir = NULL; + +} + +#else +static inline void vicam_create_proc_root(void) { } +static inline void vicam_destroy_proc_root(void) { } +static inline void vicam_create_proc_entry(struct vicam_camera *cam) { } +static inline void vicam_destroy_proc_entry(void *ptr) { } +#endif + +static struct file_operations vicam_fops = { + .owner = THIS_MODULE, + .open = vicam_open, + .release = vicam_close, + .read = vicam_read, + .mmap = vicam_mmap, + .ioctl = vicam_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .llseek = no_llseek, +}; + +static struct video_device vicam_template = { + .owner = THIS_MODULE, + .name = "ViCam-based USB Camera", + .type = VID_TYPE_CAPTURE, + .hardware = VID_HARDWARE_VICAM, + .fops = &vicam_fops, + .minor = -1, +}; + +/* table of devices that work with this driver */ +static struct usb_device_id vicam_table[] = { + {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)}, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, vicam_table); + +static struct usb_driver vicam_driver = { + .name = "vicam", + .probe = vicam_probe, + .disconnect = vicam_disconnect, + .id_table = vicam_table +}; + +/** + * vicam_probe + * @intf: the interface + * @id: the device id + * + * Called by the usb core when a new device is connected that it thinks + * this driver might be interested in. + */ +static int +vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + int bulkEndpoint = 0; + const struct usb_host_interface *interface; + const struct usb_endpoint_descriptor *endpoint; + struct vicam_camera *cam; + + printk(KERN_INFO "ViCam based webcam connected\n"); + + interface = intf->cur_altsetting; + + DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n", + interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints)); + endpoint = &interface->endpoint[0].desc; + + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk in endpoint */ + bulkEndpoint = endpoint->bEndpointAddress; + } else { + printk(KERN_ERR + "No bulk in endpoint was found ?! (this is bad)\n"); + } + + if ((cam = + kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) { + printk(KERN_WARNING + "could not allocate kernel memory for vicam_camera struct\n"); + return -ENOMEM; + } + + memset(cam, 0, sizeof (struct vicam_camera)); + + cam->shutter_speed = 15; + + mutex_init(&cam->cam_lock); + + memcpy(&cam->vdev, &vicam_template, + sizeof (vicam_template)); + cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only + + cam->udev = dev; + cam->bulkEndpoint = bulkEndpoint; + + if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) { + kfree(cam); + printk(KERN_WARNING "video_register_device failed\n"); + return -EIO; + } + + vicam_create_proc_entry(cam); + + printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor); + + usb_set_intfdata (intf, cam); + + return 0; +} + +static void +vicam_disconnect(struct usb_interface *intf) +{ + int open_count; + struct vicam_camera *cam = usb_get_intfdata (intf); + usb_set_intfdata (intf, NULL); + + /* we must unregister the device before taking its + * cam_lock. This is because the video open call + * holds the same lock as video unregister. if we + * unregister inside of the cam_lock and open also + * uses the cam_lock, we get deadlock. + */ + + video_unregister_device(&cam->vdev); + + /* stop the camera from being used */ + + mutex_lock(&cam->cam_lock); + + /* mark the camera as gone */ + + cam->udev = NULL; + + vicam_destroy_proc_entry(cam); + + /* the only thing left to do is synchronize with + * our close/release function on who should release + * the camera memory. if there are any users using the + * camera, it's their job. if there are no users, + * it's ours. + */ + + open_count = cam->open_count; + + mutex_unlock(&cam->cam_lock); + + if (!open_count) { + kfree(cam); + } + + printk(KERN_DEBUG "ViCam-based WebCam disconnected\n"); +} + +/* + */ +static int __init +usb_vicam_init(void) +{ + int retval; + DBG(KERN_INFO "ViCam-based WebCam driver startup\n"); + vicam_create_proc_root(); + retval = usb_register(&vicam_driver); + if (retval) + printk(KERN_WARNING "usb_register failed!\n"); + return retval; +} + +static void __exit +usb_vicam_exit(void) +{ + DBG(KERN_INFO + "ViCam-based WebCam driver shutdown\n"); + + usb_deregister(&vicam_driver); + vicam_destroy_proc_root(); +} + +module_init(usb_vicam_init); +module_exit(usb_vicam_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c new file mode 100644 index 000000000000..b57dec3782e0 --- /dev/null +++ b/drivers/media/video/w9968cf.c @@ -0,0 +1,3691 @@ +/*************************************************************************** + * Video4Linux driver for W996[87]CF JPEG USB Dual Mode Camera Chip. * + * * + * Copyright (C) 2002-2004 by Luca Risolia * + * * + * - Memory management code from bttv driver by Ralph Metzler, * + * Marcus Metzler and Gerd Knorr. * + * - I2C interface to kernel, high-level image sensor control routines and * + * some symbolic names from OV511 driver by Mark W. McClelland. * + * - Low-level I2C fast write function by Piotr Czerczak. * + * - Low-level I2C read function by Frederic Jouault. * + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "w9968cf.h" +#include "w9968cf_decoder.h" + +static struct w9968cf_vpp_t* w9968cf_vpp; +static DECLARE_WAIT_QUEUE_HEAD(w9968cf_vppmod_wait); + +static LIST_HEAD(w9968cf_dev_list); /* head of V4L registered cameras list */ +static DEFINE_MUTEX(w9968cf_devlist_mutex); /* semaphore for list traversal */ + +static DECLARE_RWSEM(w9968cf_disconnect); /* prevent races with open() */ + + +/**************************************************************************** + * Module macros and parameters * + ****************************************************************************/ + +MODULE_DEVICE_TABLE(usb, winbond_id_table); + +MODULE_AUTHOR(W9968CF_MODULE_AUTHOR" "W9968CF_AUTHOR_EMAIL); +MODULE_DESCRIPTION(W9968CF_MODULE_NAME); +MODULE_VERSION(W9968CF_MODULE_VERSION); +MODULE_LICENSE(W9968CF_MODULE_LICENSE); +MODULE_SUPPORTED_DEVICE("Video"); + +static int ovmod_load = W9968CF_OVMOD_LOAD; +static unsigned short simcams = W9968CF_SIMCAMS; +static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/ +static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_PACKET_SIZE}; +static unsigned short max_buffers[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_BUFFERS}; +static int double_buffer[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_DOUBLE_BUFFER}; +static int clamping[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLAMPING}; +static unsigned short filter_type[]= {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_FILTER_TYPE}; +static int largeview[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_LARGEVIEW}; +static unsigned short decompression[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_DECOMPRESSION}; +static int upscaling[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_UPSCALING}; +static unsigned short force_palette[] = {[0 ... W9968CF_MAX_DEVICES-1] = 0}; +static int force_rgb[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_FORCE_RGB}; +static int autobright[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOBRIGHT}; +static int autoexp[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOEXP}; +static unsigned short lightfreq[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_LIGHTFREQ}; +static int bandingfilter[] = {[0 ... W9968CF_MAX_DEVICES-1]= + W9968CF_BANDINGFILTER}; +static short clockdiv[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLOCKDIV}; +static int backlight[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_BACKLIGHT}; +static int mirror[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_MIRROR}; +static int monochrome[] = {[0 ... W9968CF_MAX_DEVICES-1]=W9968CF_MONOCHROME}; +static unsigned int brightness[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_BRIGHTNESS}; +static unsigned int hue[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_HUE}; +static unsigned int colour[]={[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_COLOUR}; +static unsigned int contrast[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_CONTRAST}; +static unsigned int whiteness[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_WHITENESS}; +#ifdef W9968CF_DEBUG +static unsigned short debug = W9968CF_DEBUG_LEVEL; +static int specific_debug = W9968CF_SPECIFIC_DEBUG; +#endif + +static unsigned int param_nv[24]; /* number of values per parameter */ + +#ifdef CONFIG_KMOD +module_param(ovmod_load, bool, 0644); +#endif +module_param(simcams, ushort, 0644); +module_param_array(video_nr, short, ¶m_nv[0], 0444); +module_param_array(packet_size, uint, ¶m_nv[1], 0444); +module_param_array(max_buffers, ushort, ¶m_nv[2], 0444); +module_param_array(double_buffer, bool, ¶m_nv[3], 0444); +module_param_array(clamping, bool, ¶m_nv[4], 0444); +module_param_array(filter_type, ushort, ¶m_nv[5], 0444); +module_param_array(largeview, bool, ¶m_nv[6], 0444); +module_param_array(decompression, ushort, ¶m_nv[7], 0444); +module_param_array(upscaling, bool, ¶m_nv[8], 0444); +module_param_array(force_palette, ushort, ¶m_nv[9], 0444); +module_param_array(force_rgb, ushort, ¶m_nv[10], 0444); +module_param_array(autobright, bool, ¶m_nv[11], 0444); +module_param_array(autoexp, bool, ¶m_nv[12], 0444); +module_param_array(lightfreq, ushort, ¶m_nv[13], 0444); +module_param_array(bandingfilter, bool, ¶m_nv[14], 0444); +module_param_array(clockdiv, short, ¶m_nv[15], 0444); +module_param_array(backlight, bool, ¶m_nv[16], 0444); +module_param_array(mirror, bool, ¶m_nv[17], 0444); +module_param_array(monochrome, bool, ¶m_nv[18], 0444); +module_param_array(brightness, uint, ¶m_nv[19], 0444); +module_param_array(hue, uint, ¶m_nv[20], 0444); +module_param_array(colour, uint, ¶m_nv[21], 0444); +module_param_array(contrast, uint, ¶m_nv[22], 0444); +module_param_array(whiteness, uint, ¶m_nv[23], 0444); +#ifdef W9968CF_DEBUG +module_param(debug, ushort, 0644); +module_param(specific_debug, bool, 0644); +#endif + +#ifdef CONFIG_KMOD +MODULE_PARM_DESC(ovmod_load, + "\n<0|1> Automatic 'ovcamchip' module loading." + "\n0 disabled, 1 enabled." + "\nIf enabled,'insmod' searches for the required 'ovcamchip'" + "\nmodule in the system, according to its configuration, and" + "\nattempts to load that module automatically. This action is" + "\nperformed once as soon as the 'w9968cf' module is loaded" + "\ninto memory." + "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"." + "\n"); +#endif +MODULE_PARM_DESC(simcams, + "\n Number of cameras allowed to stream simultaneously." + "\nn may vary from 0 to " + __MODULE_STRING(W9968CF_MAX_DEVICES)"." + "\nDefault value is "__MODULE_STRING(W9968CF_SIMCAMS)"." + "\n"); +MODULE_PARM_DESC(video_nr, + "\n<-1|n[,...]> Specify V4L minor mode number." + "\n -1 = use next available (default)" + "\n n = use minor number n (integer >= 0)" + "\nYou can specify up to "__MODULE_STRING(W9968CF_MAX_DEVICES) + " cameras this way." + "\nFor example:" + "\nvideo_nr=-1,2,-1 would assign minor number 2 to" + "\nthe second camera and use auto for the first" + "\none and for every other camera." + "\n"); +MODULE_PARM_DESC(packet_size, + "\n Specify the maximum data payload" + "\nsize in bytes for alternate settings, for each device." + "\nn is scaled between 63 and 1023 " + "(default is "__MODULE_STRING(W9968CF_PACKET_SIZE)")." + "\n"); +MODULE_PARM_DESC(max_buffers, + "\n For advanced users." + "\nSpecify the maximum number of video frame buffers" + "\nto allocate for each device, from 2 to " + __MODULE_STRING(W9968CF_MAX_BUFFERS) + ". (default is "__MODULE_STRING(W9968CF_BUFFERS)")." + "\n"); +MODULE_PARM_DESC(double_buffer, + "\n<0|1[,...]> " + "Hardware double buffering: 0 disabled, 1 enabled." + "\nIt should be enabled if you want smooth video output: if" + "\nyou obtain out of sync. video, disable it, or try to" + "\ndecrease the 'clockdiv' module parameter value." + "\nDefault value is "__MODULE_STRING(W9968CF_DOUBLE_BUFFER) + " for every device." + "\n"); +MODULE_PARM_DESC(clamping, + "\n<0|1[,...]> Video data clamping: 0 disabled, 1 enabled." + "\nDefault value is "__MODULE_STRING(W9968CF_CLAMPING) + " for every device." + "\n"); +MODULE_PARM_DESC(filter_type, + "\n<0|1|2[,...]> Video filter type." + "\n0 none, 1 (1-2-1) 3-tap filter, " + "2 (2-3-6-3-2) 5-tap filter." + "\nDefault value is "__MODULE_STRING(W9968CF_FILTER_TYPE) + " for every device." + "\nThe filter is used to reduce noise and aliasing artifacts" + "\nproduced by the CCD or CMOS image sensor, and the scaling" + " process." + "\n"); +MODULE_PARM_DESC(largeview, + "\n<0|1[,...]> Large view: 0 disabled, 1 enabled." + "\nDefault value is "__MODULE_STRING(W9968CF_LARGEVIEW) + " for every device." + "\n"); +MODULE_PARM_DESC(upscaling, + "\n<0|1[,...]> Software scaling (for non-compressed video):" + "\n0 disabled, 1 enabled." + "\nDisable it if you have a slow CPU or you don't have" + " enough memory." + "\nDefault value is "__MODULE_STRING(W9968CF_UPSCALING) + " for every device." + "\nIf 'w9968cf-vpp' is not present, this parameter is" + " set to 0." + "\n"); +MODULE_PARM_DESC(decompression, + "\n<0|1|2[,...]> Software video decompression:" + "\n- 0 disables decompression (doesn't allow formats needing" + " decompression)" + "\n- 1 forces decompression (allows formats needing" + " decompression only);" + "\n- 2 allows any permitted formats." + "\nFormats supporting compressed video are YUV422P and" + " YUV420P/YUV420 " + "\nin any resolutions where both width and height are " + "a multiple of 16." + "\nDefault value is "__MODULE_STRING(W9968CF_DECOMPRESSION) + " for every device." + "\nIf 'w9968cf-vpp' is not present, forcing decompression is " + "\nnot allowed; in this case this parameter is set to 2." + "\n"); +MODULE_PARM_DESC(force_palette, + "\n<0" + "|" __MODULE_STRING(VIDEO_PALETTE_UYVY) + "|" __MODULE_STRING(VIDEO_PALETTE_YUV420) + "|" __MODULE_STRING(VIDEO_PALETTE_YUV422P) + "|" __MODULE_STRING(VIDEO_PALETTE_YUV420P) + "|" __MODULE_STRING(VIDEO_PALETTE_YUYV) + "|" __MODULE_STRING(VIDEO_PALETTE_YUV422) + "|" __MODULE_STRING(VIDEO_PALETTE_GREY) + "|" __MODULE_STRING(VIDEO_PALETTE_RGB555) + "|" __MODULE_STRING(VIDEO_PALETTE_RGB565) + "|" __MODULE_STRING(VIDEO_PALETTE_RGB24) + "|" __MODULE_STRING(VIDEO_PALETTE_RGB32) + "[,...]>" + " Force picture palette." + "\nIn order:" + "\n- 0 allows any of the following formats:" + "\n- UYVY 16 bpp - Original video, compression disabled" + "\n- YUV420 12 bpp - Original video, compression enabled" + "\n- YUV422P 16 bpp - Original video, compression enabled" + "\n- YUV420P 12 bpp - Original video, compression enabled" + "\n- YUVY 16 bpp - Software conversion from UYVY" + "\n- YUV422 16 bpp - Software conversion from UYVY" + "\n- GREY 8 bpp - Software conversion from UYVY" + "\n- RGB555 16 bpp - Software conversion from UYVY" + "\n- RGB565 16 bpp - Software conversion from UYVY" + "\n- RGB24 24 bpp - Software conversion from UYVY" + "\n- RGB32 32 bpp - Software conversion from UYVY" + "\nWhen not 0, this parameter will override 'decompression'." + "\nDefault value is 0 for every device." + "\nInitial palette is " + __MODULE_STRING(W9968CF_PALETTE_DECOMP_ON)"." + "\nIf 'w9968cf-vpp' is not present, this parameter is" + " set to 9 (UYVY)." + "\n"); +MODULE_PARM_DESC(force_rgb, + "\n<0|1[,...]> Read RGB video data instead of BGR:" + "\n 1 = use RGB component ordering." + "\n 0 = use BGR component ordering." + "\nThis parameter has effect when using RGBX palettes only." + "\nDefault value is "__MODULE_STRING(W9968CF_FORCE_RGB) + " for every device." + "\n"); +MODULE_PARM_DESC(autobright, + "\n<0|1[,...]> Image sensor automatically changes brightness:" + "\n 0 = no, 1 = yes" + "\nDefault value is "__MODULE_STRING(W9968CF_AUTOBRIGHT) + " for every device." + "\n"); +MODULE_PARM_DESC(autoexp, + "\n<0|1[,...]> Image sensor automatically changes exposure:" + "\n 0 = no, 1 = yes" + "\nDefault value is "__MODULE_STRING(W9968CF_AUTOEXP) + " for every device." + "\n"); +MODULE_PARM_DESC(lightfreq, + "\n<50|60[,...]> Light frequency in Hz:" + "\n 50 for European and Asian lighting," + " 60 for American lighting." + "\nDefault value is "__MODULE_STRING(W9968CF_LIGHTFREQ) + " for every device." + "\n"); +MODULE_PARM_DESC(bandingfilter, + "\n<0|1[,...]> Banding filter to reduce effects of" + " fluorescent lighting:" + "\n 0 disabled, 1 enabled." + "\nThis filter tries to reduce the pattern of horizontal" + "\nlight/dark bands caused by some (usually fluorescent)" + " lighting." + "\nDefault value is "__MODULE_STRING(W9968CF_BANDINGFILTER) + " for every device." + "\n"); +MODULE_PARM_DESC(clockdiv, + "\n<-1|n[,...]> " + "Force pixel clock divisor to a specific value (for experts):" + "\n n may vary from 0 to 127." + "\n -1 for automatic value." + "\nSee also the 'double_buffer' module parameter." + "\nDefault value is "__MODULE_STRING(W9968CF_CLOCKDIV) + " for every device." + "\n"); +MODULE_PARM_DESC(backlight, + "\n<0|1[,...]> Objects are lit from behind:" + "\n 0 = no, 1 = yes" + "\nDefault value is "__MODULE_STRING(W9968CF_BACKLIGHT) + " for every device." + "\n"); +MODULE_PARM_DESC(mirror, + "\n<0|1[,...]> Reverse image horizontally:" + "\n 0 = no, 1 = yes" + "\nDefault value is "__MODULE_STRING(W9968CF_MIRROR) + " for every device." + "\n"); +MODULE_PARM_DESC(monochrome, + "\n<0|1[,...]> Use image sensor as monochrome sensor:" + "\n 0 = no, 1 = yes" + "\nNot all the sensors support monochrome color." + "\nDefault value is "__MODULE_STRING(W9968CF_MONOCHROME) + " for every device." + "\n"); +MODULE_PARM_DESC(brightness, + "\n Set picture brightness (0-65535)." + "\nDefault value is "__MODULE_STRING(W9968CF_BRIGHTNESS) + " for every device." + "\nThis parameter has no effect if 'autobright' is enabled." + "\n"); +MODULE_PARM_DESC(hue, + "\n Set picture hue (0-65535)." + "\nDefault value is "__MODULE_STRING(W9968CF_HUE) + " for every device." + "\n"); +MODULE_PARM_DESC(colour, + "\n Set picture saturation (0-65535)." + "\nDefault value is "__MODULE_STRING(W9968CF_COLOUR) + " for every device." + "\n"); +MODULE_PARM_DESC(contrast, + "\n Set picture contrast (0-65535)." + "\nDefault value is "__MODULE_STRING(W9968CF_CONTRAST) + " for every device." + "\n"); +MODULE_PARM_DESC(whiteness, + "\n Set picture whiteness (0-65535)." + "\nDefault value is "__MODULE_STRING(W9968CF_WHITENESS) + " for every device." + "\n"); +#ifdef W9968CF_DEBUG +MODULE_PARM_DESC(debug, + "\n Debugging information level, from 0 to 6:" + "\n0 = none (use carefully)" + "\n1 = critical errors" + "\n2 = significant informations" + "\n3 = configuration or general messages" + "\n4 = warnings" + "\n5 = called functions" + "\n6 = function internals" + "\nLevel 5 and 6 are useful for testing only, when only " + "one device is used." + "\nDefault value is "__MODULE_STRING(W9968CF_DEBUG_LEVEL)"." + "\n"); +MODULE_PARM_DESC(specific_debug, + "\n<0|1> Enable or disable specific debugging messages:" + "\n0 = print messages concerning every level" + " <= 'debug' level." + "\n1 = print messages concerning the level" + " indicated by 'debug'." + "\nDefault value is " + __MODULE_STRING(W9968CF_SPECIFIC_DEBUG)"." + "\n"); +#endif /* W9968CF_DEBUG */ + + + +/**************************************************************************** + * Some prototypes * + ****************************************************************************/ + +/* Video4linux interface */ +static struct file_operations w9968cf_fops; +static int w9968cf_open(struct inode*, struct file*); +static int w9968cf_release(struct inode*, struct file*); +static int w9968cf_mmap(struct file*, struct vm_area_struct*); +static int w9968cf_ioctl(struct inode*, struct file*, unsigned, unsigned long); +static ssize_t w9968cf_read(struct file*, char __user *, size_t, loff_t*); +static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int, + void __user *); + +/* USB-specific */ +static int w9968cf_start_transfer(struct w9968cf_device*); +static int w9968cf_stop_transfer(struct w9968cf_device*); +static int w9968cf_write_reg(struct w9968cf_device*, u16 value, u16 index); +static int w9968cf_read_reg(struct w9968cf_device*, u16 index); +static int w9968cf_write_fsb(struct w9968cf_device*, u16* data); +static int w9968cf_write_sb(struct w9968cf_device*, u16 value); +static int w9968cf_read_sb(struct w9968cf_device*); +static int w9968cf_upload_quantizationtables(struct w9968cf_device*); +static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs); + +/* Low-level I2C (SMBus) I/O */ +static int w9968cf_smbus_start(struct w9968cf_device*); +static int w9968cf_smbus_stop(struct w9968cf_device*); +static int w9968cf_smbus_write_byte(struct w9968cf_device*, u8 v); +static int w9968cf_smbus_read_byte(struct w9968cf_device*, u8* v); +static int w9968cf_smbus_write_ack(struct w9968cf_device*); +static int w9968cf_smbus_read_ack(struct w9968cf_device*); +static int w9968cf_smbus_refresh_bus(struct w9968cf_device*); +static int w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam, + u16 address, u8* value); +static int w9968cf_i2c_adap_read_byte_data(struct w9968cf_device*, u16 address, + u8 subaddress, u8* value); +static int w9968cf_i2c_adap_write_byte(struct w9968cf_device*, + u16 address, u8 subaddress); +static int w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device*, + u16 address, u8 subaddress, + u8 value); + +/* I2C interface to kernel */ +static int w9968cf_i2c_init(struct w9968cf_device*); +static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data*); +static u32 w9968cf_i2c_func(struct i2c_adapter*); +static int w9968cf_i2c_attach_inform(struct i2c_client*); +static int w9968cf_i2c_detach_inform(struct i2c_client*); +static int w9968cf_i2c_control(struct i2c_adapter*, unsigned int cmd, + unsigned long arg); + +/* Memory management */ +static void* rvmalloc(unsigned long size); +static void rvfree(void *mem, unsigned long size); +static void w9968cf_deallocate_memory(struct w9968cf_device*); +static int w9968cf_allocate_memory(struct w9968cf_device*); + +/* High-level image sensor control functions */ +static int w9968cf_sensor_set_control(struct w9968cf_device*,int cid,int val); +static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val); +static int w9968cf_sensor_cmd(struct w9968cf_device*, + unsigned int cmd, void *arg); +static int w9968cf_sensor_init(struct w9968cf_device*); +static int w9968cf_sensor_update_settings(struct w9968cf_device*); +static int w9968cf_sensor_get_picture(struct w9968cf_device*); +static int w9968cf_sensor_update_picture(struct w9968cf_device*, + struct video_picture pict); + +/* Other helper functions */ +static void w9968cf_configure_camera(struct w9968cf_device*,struct usb_device*, + enum w9968cf_model_id, + const unsigned short dev_nr); +static void w9968cf_adjust_configuration(struct w9968cf_device*); +static int w9968cf_turn_on_led(struct w9968cf_device*); +static int w9968cf_init_chip(struct w9968cf_device*); +static inline u16 w9968cf_valid_palette(u16 palette); +static inline u16 w9968cf_valid_depth(u16 palette); +static inline u8 w9968cf_need_decompression(u16 palette); +static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture); +static int w9968cf_set_window(struct w9968cf_device*, struct video_window); +static int w9968cf_postprocess_frame(struct w9968cf_device*, + struct w9968cf_frame_t*); +static int w9968cf_adjust_window_size(struct w9968cf_device*, u16* w, u16* h); +static void w9968cf_init_framelist(struct w9968cf_device*); +static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num); +static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**); +static void w9968cf_release_resources(struct w9968cf_device*); + + + +/**************************************************************************** + * Symbolic names * + ****************************************************************************/ + +/* Used to represent a list of values and their respective symbolic names */ +struct w9968cf_symbolic_list { + const int num; + const char *name; +}; + +/*-------------------------------------------------------------------------- + Returns the name of the matching element in the symbolic_list array. The + end of the list must be marked with an element that has a NULL name. + --------------------------------------------------------------------------*/ +static inline const char * +symbolic(struct w9968cf_symbolic_list list[], const int num) +{ + int i; + + for (i = 0; list[i].name != NULL; i++) + if (list[i].num == num) + return (list[i].name); + + return "Unknown"; +} + +static struct w9968cf_symbolic_list camlist[] = { + { W9968CF_MOD_GENERIC, "W996[87]CF JPEG USB Dual Mode Camera" }, + { W9968CF_MOD_CLVBWGP, "Creative Labs Video Blaster WebCam Go Plus" }, + + /* Other cameras (having the same descriptors as Generic W996[87]CF) */ + { W9968CF_MOD_ADPVDMA, "Aroma Digi Pen VGA Dual Mode ADG-5000" }, + { W9986CF_MOD_AAU, "AVerMedia AVerTV USB" }, + { W9968CF_MOD_CLVBWG, "Creative Labs Video Blaster WebCam Go" }, + { W9968CF_MOD_LL, "Lebon LDC-035A" }, + { W9968CF_MOD_EEEMC, "Ezonics EZ-802 EZMega Cam" }, + { W9968CF_MOD_OOE, "OmniVision OV8610-EDE" }, + { W9968CF_MOD_ODPVDMPC, "OPCOM Digi Pen VGA Dual Mode Pen Camera" }, + { W9968CF_MOD_PDPII, "Pretec Digi Pen-II" }, + { W9968CF_MOD_PDP480, "Pretec DigiPen-480" }, + + { -1, NULL } +}; + +static struct w9968cf_symbolic_list senlist[] = { + { CC_OV76BE, "OV76BE" }, + { CC_OV7610, "OV7610" }, + { CC_OV7620, "OV7620" }, + { CC_OV7620AE, "OV7620AE" }, + { CC_OV6620, "OV6620" }, + { CC_OV6630, "OV6630" }, + { CC_OV6630AE, "OV6630AE" }, + { CC_OV6630AF, "OV6630AF" }, + { -1, NULL } +}; + +/* Video4Linux1 palettes */ +static struct w9968cf_symbolic_list v4l1_plist[] = { + { VIDEO_PALETTE_GREY, "GREY" }, + { VIDEO_PALETTE_HI240, "HI240" }, + { VIDEO_PALETTE_RGB565, "RGB565" }, + { VIDEO_PALETTE_RGB24, "RGB24" }, + { VIDEO_PALETTE_RGB32, "RGB32" }, + { VIDEO_PALETTE_RGB555, "RGB555" }, + { VIDEO_PALETTE_YUV422, "YUV422" }, + { VIDEO_PALETTE_YUYV, "YUYV" }, + { VIDEO_PALETTE_UYVY, "UYVY" }, + { VIDEO_PALETTE_YUV420, "YUV420" }, + { VIDEO_PALETTE_YUV411, "YUV411" }, + { VIDEO_PALETTE_RAW, "RAW" }, + { VIDEO_PALETTE_YUV422P, "YUV422P" }, + { VIDEO_PALETTE_YUV411P, "YUV411P" }, + { VIDEO_PALETTE_YUV420P, "YUV420P" }, + { VIDEO_PALETTE_YUV410P, "YUV410P" }, + { -1, NULL } +}; + +/* Decoder error codes: */ +static struct w9968cf_symbolic_list decoder_errlist[] = { + { W9968CF_DEC_ERR_CORRUPTED_DATA, "Corrupted data" }, + { W9968CF_DEC_ERR_BUF_OVERFLOW, "Buffer overflow" }, + { W9968CF_DEC_ERR_NO_SOI, "SOI marker not found" }, + { W9968CF_DEC_ERR_NO_SOF0, "SOF0 marker not found" }, + { W9968CF_DEC_ERR_NO_SOS, "SOS marker not found" }, + { W9968CF_DEC_ERR_NO_EOI, "EOI marker not found" }, + { -1, NULL } +}; + +/* URB error codes: */ +static struct w9968cf_symbolic_list urb_errlist[] = { + { -ENOMEM, "No memory for allocation of internal structures" }, + { -ENOSPC, "The host controller's bandwidth is already consumed" }, + { -ENOENT, "URB was canceled by unlink_urb" }, + { -EXDEV, "ISO transfer only partially completed" }, + { -EAGAIN, "Too match scheduled for the future" }, + { -ENXIO, "URB already queued" }, + { -EFBIG, "Too much ISO frames requested" }, + { -ENOSR, "Buffer error (overrun)" }, + { -EPIPE, "Specified endpoint is stalled (device not responding)"}, + { -EOVERFLOW, "Babble (bad cable?)" }, + { -EPROTO, "Bit-stuff error (bad cable?)" }, + { -EILSEQ, "CRC/Timeout" }, + { -ETIMEDOUT, "NAK (device does not respond)" }, + { -1, NULL } +}; + + + +/**************************************************************************** + * Memory management functions * + ****************************************************************************/ +static void* rvmalloc(unsigned long size) +{ + void* mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + + +static void rvfree(void* mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + + +/*-------------------------------------------------------------------------- + Deallocate previously allocated memory. + --------------------------------------------------------------------------*/ +static void w9968cf_deallocate_memory(struct w9968cf_device* cam) +{ + u8 i; + + /* Free the isochronous transfer buffers */ + for (i = 0; i < W9968CF_URBS; i++) { + kfree(cam->transfer_buffer[i]); + cam->transfer_buffer[i] = NULL; + } + + /* Free temporary frame buffer */ + if (cam->frame_tmp.buffer) { + rvfree(cam->frame_tmp.buffer, cam->frame_tmp.size); + cam->frame_tmp.buffer = NULL; + } + + /* Free helper buffer */ + if (cam->frame_vpp.buffer) { + rvfree(cam->frame_vpp.buffer, cam->frame_vpp.size); + cam->frame_vpp.buffer = NULL; + } + + /* Free video frame buffers */ + if (cam->frame[0].buffer) { + rvfree(cam->frame[0].buffer, cam->nbuffers*cam->frame[0].size); + cam->frame[0].buffer = NULL; + } + + cam->nbuffers = 0; + + DBG(5, "Memory successfully deallocated") +} + + +/*-------------------------------------------------------------------------- + Allocate memory buffers for USB transfers and video frames. + This function is called by open() only. + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_allocate_memory(struct w9968cf_device* cam) +{ + const u16 p_size = wMaxPacketSize[cam->altsetting-1]; + void* buff = NULL; + unsigned long hw_bufsize, vpp_bufsize; + u8 i, bpp; + + /* NOTE: Deallocation is done elsewhere in case of error */ + + /* Calculate the max amount of raw data per frame from the device */ + hw_bufsize = cam->maxwidth*cam->maxheight*2; + + /* Calculate the max buf. size needed for post-processing routines */ + bpp = (w9968cf_vpp) ? 4 : 2; + if (cam->upscaling) + vpp_bufsize = max(W9968CF_MAX_WIDTH*W9968CF_MAX_HEIGHT*bpp, + cam->maxwidth*cam->maxheight*bpp); + else + vpp_bufsize = cam->maxwidth*cam->maxheight*bpp; + + /* Allocate memory for the isochronous transfer buffers */ + for (i = 0; i < W9968CF_URBS; i++) { + if (!(cam->transfer_buffer[i] = + kzalloc(W9968CF_ISO_PACKETS*p_size, GFP_KERNEL))) { + DBG(1, "Couldn't allocate memory for the isochronous " + "transfer buffers (%u bytes)", + p_size * W9968CF_ISO_PACKETS) + return -ENOMEM; + } + } + + /* Allocate memory for the temporary frame buffer */ + if (!(cam->frame_tmp.buffer = rvmalloc(hw_bufsize))) { + DBG(1, "Couldn't allocate memory for the temporary " + "video frame buffer (%lu bytes)", hw_bufsize) + return -ENOMEM; + } + cam->frame_tmp.size = hw_bufsize; + cam->frame_tmp.number = -1; + + /* Allocate memory for the helper buffer */ + if (w9968cf_vpp) { + if (!(cam->frame_vpp.buffer = rvmalloc(vpp_bufsize))) { + DBG(1, "Couldn't allocate memory for the helper buffer" + " (%lu bytes)", vpp_bufsize) + return -ENOMEM; + } + cam->frame_vpp.size = vpp_bufsize; + } else + cam->frame_vpp.buffer = NULL; + + /* Allocate memory for video frame buffers */ + cam->nbuffers = cam->max_buffers; + while (cam->nbuffers >= 2) { + if ((buff = rvmalloc(cam->nbuffers * vpp_bufsize))) + break; + else + cam->nbuffers--; + } + + if (!buff) { + DBG(1, "Couldn't allocate memory for the video frame buffers") + cam->nbuffers = 0; + return -ENOMEM; + } + + if (cam->nbuffers != cam->max_buffers) + DBG(2, "Couldn't allocate memory for %u video frame buffers. " + "Only memory for %u buffers has been allocated", + cam->max_buffers, cam->nbuffers) + + for (i = 0; i < cam->nbuffers; i++) { + cam->frame[i].buffer = buff + i*vpp_bufsize; + cam->frame[i].size = vpp_bufsize; + cam->frame[i].number = i; + /* Circular list */ + if (i != cam->nbuffers-1) + cam->frame[i].next = &cam->frame[i+1]; + else + cam->frame[i].next = &cam->frame[0]; + cam->frame[i].status = F_UNUSED; + } + + DBG(5, "Memory successfully allocated") + return 0; +} + + + +/**************************************************************************** + * USB-specific functions * + ****************************************************************************/ + +/*-------------------------------------------------------------------------- + This is an handler function which is called after the URBs are completed. + It collects multiple data packets coming from the camera by putting them + into frame buffers: one or more zero data length data packets are used to + mark the end of a video frame; the first non-zero data packet is the start + of the next video frame; if an error is encountered in a packet, the entire + video frame is discarded and grabbed again. + If there are no requested frames in the FIFO list, packets are collected into + a temporary buffer. + --------------------------------------------------------------------------*/ +static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs) +{ + struct w9968cf_device* cam = (struct w9968cf_device*)urb->context; + struct w9968cf_frame_t** f; + unsigned int len, status; + void* pos; + u8 i; + int err = 0; + + if ((!cam->streaming) || cam->disconnected) { + DBG(4, "Got interrupt, but not streaming") + return; + } + + /* "(*f)" will be used instead of "cam->frame_current" */ + f = &cam->frame_current; + + /* If a frame has been requested and we are grabbing into + the temporary frame, we'll switch to that requested frame */ + if ((*f) == &cam->frame_tmp && *cam->requested_frame) { + if (cam->frame_tmp.status == F_GRABBING) { + w9968cf_pop_frame(cam, &cam->frame_current); + (*f)->status = F_GRABBING; + (*f)->length = cam->frame_tmp.length; + memcpy((*f)->buffer, cam->frame_tmp.buffer, + (*f)->length); + DBG(6, "Switched from temp. frame to frame #%d", + (*f)->number) + } + } + + for (i = 0; i < urb->number_of_packets; i++) { + len = urb->iso_frame_desc[i].actual_length; + status = urb->iso_frame_desc[i].status; + pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; + + if (status && len != 0) { + DBG(4, "URB failed, error in data packet " + "(error #%u, %s)", + status, symbolic(urb_errlist, status)) + (*f)->status = F_ERROR; + continue; + } + + if (len) { /* start of frame */ + + if ((*f)->status == F_UNUSED) { + (*f)->status = F_GRABBING; + (*f)->length = 0; + } + + /* Buffer overflows shouldn't happen, however...*/ + if ((*f)->length + len > (*f)->size) { + DBG(4, "Buffer overflow: bad data packets") + (*f)->status = F_ERROR; + } + + if ((*f)->status == F_GRABBING) { + memcpy((*f)->buffer + (*f)->length, pos, len); + (*f)->length += len; + } + + } else if ((*f)->status == F_GRABBING) { /* end of frame */ + + DBG(6, "Frame #%d successfully grabbed", (*f)->number) + + if (cam->vpp_flag & VPP_DECOMPRESSION) { + err = w9968cf_vpp->check_headers((*f)->buffer, + (*f)->length); + if (err) { + DBG(4, "Skip corrupted frame: %s", + symbolic(decoder_errlist, err)) + (*f)->status = F_UNUSED; + continue; /* grab this frame again */ + } + } + + (*f)->status = F_READY; + (*f)->queued = 0; + + /* Take a pointer to the new frame from the FIFO list. + If the list is empty,we'll use the temporary frame*/ + if (*cam->requested_frame) + w9968cf_pop_frame(cam, &cam->frame_current); + else { + cam->frame_current = &cam->frame_tmp; + (*f)->status = F_UNUSED; + } + + } else if ((*f)->status == F_ERROR) + (*f)->status = F_UNUSED; /* grab it again */ + + PDBGG("Frame length %lu | pack.#%u | pack.len. %u | state %d", + (unsigned long)(*f)->length, i, len, (*f)->status) + + } /* end for */ + + /* Resubmit this URB */ + urb->dev = cam->usbdev; + urb->status = 0; + spin_lock(&cam->urb_lock); + if (cam->streaming) + if ((err = usb_submit_urb(urb, GFP_ATOMIC))) { + cam->misconfigured = 1; + DBG(1, "Couldn't resubmit the URB: error %d, %s", + err, symbolic(urb_errlist, err)) + } + spin_unlock(&cam->urb_lock); + + /* Wake up the user process */ + wake_up_interruptible(&cam->wait_queue); +} + + +/*--------------------------------------------------------------------------- + Setup the URB structures for the isochronous transfer. + Submit the URBs so that the data transfer begins. + Return 0 on success, a negative number otherwise. + ---------------------------------------------------------------------------*/ +static int w9968cf_start_transfer(struct w9968cf_device* cam) +{ + struct usb_device *udev = cam->usbdev; + struct urb* urb; + const u16 p_size = wMaxPacketSize[cam->altsetting-1]; + u16 w, h, d; + int vidcapt; + u32 t_size; + int err = 0; + s8 i, j; + + for (i = 0; i < W9968CF_URBS; i++) { + urb = usb_alloc_urb(W9968CF_ISO_PACKETS, GFP_KERNEL); + cam->urb[i] = urb; + if (!urb) { + for (j = 0; j < i; j++) + usb_free_urb(cam->urb[j]); + DBG(1, "Couldn't allocate the URB structures") + return -ENOMEM; + } + + urb->dev = udev; + urb->context = (void*)cam; + urb->pipe = usb_rcvisocpipe(udev, 1); + urb->transfer_flags = URB_ISO_ASAP; + urb->number_of_packets = W9968CF_ISO_PACKETS; + urb->complete = w9968cf_urb_complete; + urb->transfer_buffer = cam->transfer_buffer[i]; + urb->transfer_buffer_length = p_size*W9968CF_ISO_PACKETS; + urb->interval = 1; + for (j = 0; j < W9968CF_ISO_PACKETS; j++) { + urb->iso_frame_desc[j].offset = p_size*j; + urb->iso_frame_desc[j].length = p_size; + } + } + + /* Transfer size per frame, in WORD ! */ + d = cam->hw_depth; + w = cam->hw_width; + h = cam->hw_height; + + t_size = (w*h*d)/16; + + err = w9968cf_write_reg(cam, 0xbf17, 0x00); /* reset everything */ + err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* normal operation */ + + /* Transfer size */ + err += w9968cf_write_reg(cam, t_size & 0xffff, 0x3d); /* low bits */ + err += w9968cf_write_reg(cam, t_size >> 16, 0x3e); /* high bits */ + + if (cam->vpp_flag & VPP_DECOMPRESSION) + err += w9968cf_upload_quantizationtables(cam); + + vidcapt = w9968cf_read_reg(cam, 0x16); /* read picture settings */ + err += w9968cf_write_reg(cam, vidcapt|0x8000, 0x16); /* capt. enable */ + + err += usb_set_interface(udev, 0, cam->altsetting); + err += w9968cf_write_reg(cam, 0x8a05, 0x3c); /* USB FIFO enable */ + + if (err || (vidcapt < 0)) { + for (i = 0; i < W9968CF_URBS; i++) + usb_free_urb(cam->urb[i]); + DBG(1, "Couldn't tell the camera to start the data transfer") + return err; + } + + w9968cf_init_framelist(cam); + + /* Begin to grab into the temporary buffer */ + cam->frame_tmp.status = F_UNUSED; + cam->frame_tmp.queued = 0; + cam->frame_current = &cam->frame_tmp; + + if (!(cam->vpp_flag & VPP_DECOMPRESSION)) + DBG(5, "Isochronous transfer size: %lu bytes/frame", + (unsigned long)t_size*2) + + DBG(5, "Starting the isochronous transfer...") + + cam->streaming = 1; + + /* Submit the URBs */ + for (i = 0; i < W9968CF_URBS; i++) { + err = usb_submit_urb(cam->urb[i], GFP_KERNEL); + if (err) { + cam->streaming = 0; + for (j = i-1; j >= 0; j--) { + usb_kill_urb(cam->urb[j]); + usb_free_urb(cam->urb[j]); + } + DBG(1, "Couldn't send a transfer request to the " + "USB core (error #%d, %s)", err, + symbolic(urb_errlist, err)) + return err; + } + } + + return 0; +} + + +/*-------------------------------------------------------------------------- + Stop the isochronous transfer and set alternate setting to 0 (0Mb/s). + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_stop_transfer(struct w9968cf_device* cam) +{ + struct usb_device *udev = cam->usbdev; + unsigned long lock_flags; + int err = 0; + s8 i; + + if (!cam->streaming) + return 0; + + /* This avoids race conditions with usb_submit_urb() + in the URB completition handler */ + spin_lock_irqsave(&cam->urb_lock, lock_flags); + cam->streaming = 0; + spin_unlock_irqrestore(&cam->urb_lock, lock_flags); + + for (i = W9968CF_URBS-1; i >= 0; i--) + if (cam->urb[i]) { + usb_kill_urb(cam->urb[i]); + usb_free_urb(cam->urb[i]); + cam->urb[i] = NULL; + } + + if (cam->disconnected) + goto exit; + + err = w9968cf_write_reg(cam, 0x0a05, 0x3c); /* stop USB transfer */ + err += usb_set_interface(udev, 0, 0); /* 0 Mb/s */ + err += w9968cf_write_reg(cam, 0x0000, 0x39); /* disable JPEG encoder */ + err += w9968cf_write_reg(cam, 0x0000, 0x16); /* stop video capture */ + + if (err) { + DBG(2, "Failed to tell the camera to stop the isochronous " + "transfer. However this is not a critical error.") + return -EIO; + } + +exit: + DBG(5, "Isochronous transfer stopped") + return 0; +} + + +/*-------------------------------------------------------------------------- + Write a W9968CF register. + Return 0 on success, -1 otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_write_reg(struct w9968cf_device* cam, u16 value, u16 index) +{ + struct usb_device* udev = cam->usbdev; + int res; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, + USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, + value, index, NULL, 0, W9968CF_USB_CTRL_TIMEOUT); + + if (res < 0) + DBG(4, "Failed to write a register " + "(value 0x%04X, index 0x%02X, error #%d, %s)", + value, index, res, symbolic(urb_errlist, res)) + + return (res >= 0) ? 0 : -1; +} + + +/*-------------------------------------------------------------------------- + Read a W9968CF register. + Return the register value on success, -1 otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_read_reg(struct w9968cf_device* cam, u16 index) +{ + struct usb_device* udev = cam->usbdev; + u16* buff = cam->control_buffer; + int res; + + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 1, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, index, buff, 2, W9968CF_USB_CTRL_TIMEOUT); + + if (res < 0) + DBG(4, "Failed to read a register " + "(index 0x%02X, error #%d, %s)", + index, res, symbolic(urb_errlist, res)) + + return (res >= 0) ? (int)(*buff) : -1; +} + + +/*-------------------------------------------------------------------------- + Write 64-bit data to the fast serial bus registers. + Return 0 on success, -1 otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_write_fsb(struct w9968cf_device* cam, u16* data) +{ + struct usb_device* udev = cam->usbdev; + u16 value; + int res; + + value = *data++; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, + USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, + value, 0x06, data, 6, W9968CF_USB_CTRL_TIMEOUT); + + if (res < 0) + DBG(4, "Failed to write the FSB registers " + "(error #%d, %s)", res, symbolic(urb_errlist, res)) + + return (res >= 0) ? 0 : -1; +} + + +/*-------------------------------------------------------------------------- + Write data to the serial bus control register. + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_write_sb(struct w9968cf_device* cam, u16 value) +{ + int err = 0; + + err = w9968cf_write_reg(cam, value, 0x01); + udelay(W9968CF_I2C_BUS_DELAY); + + return err; +} + + +/*-------------------------------------------------------------------------- + Read data from the serial bus control register. + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_read_sb(struct w9968cf_device* cam) +{ + int v = 0; + + v = w9968cf_read_reg(cam, 0x01); + udelay(W9968CF_I2C_BUS_DELAY); + + return v; +} + + +/*-------------------------------------------------------------------------- + Upload quantization tables for the JPEG compression. + This function is called by w9968cf_start_transfer(). + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_upload_quantizationtables(struct w9968cf_device* cam) +{ + u16 a, b; + int err = 0, i, j; + + err += w9968cf_write_reg(cam, 0x0010, 0x39); /* JPEG clock enable */ + + for (i = 0, j = 0; i < 32; i++, j += 2) { + a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8); + b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8); + err += w9968cf_write_reg(cam, a, 0x40+i); + err += w9968cf_write_reg(cam, b, 0x60+i); + } + err += w9968cf_write_reg(cam, 0x0012, 0x39); /* JPEG encoder enable */ + + return err; +} + + + +/**************************************************************************** + * Low-level I2C I/O functions. * + * The adapter supports the following I2C transfer functions: * + * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) * + * i2c_adap_read_byte_data() * + * i2c_adap_read_byte() * + ****************************************************************************/ + +static int w9968cf_smbus_start(struct w9968cf_device* cam) +{ + int err = 0; + + err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ + err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ + + return err; +} + + +static int w9968cf_smbus_stop(struct w9968cf_device* cam) +{ + int err = 0; + + err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ + err += w9968cf_write_sb(cam, 0x0013); /* SDE=1, SDA=1, SCL=1 */ + + return err; +} + + +static int w9968cf_smbus_write_byte(struct w9968cf_device* cam, u8 v) +{ + u8 bit; + int err = 0, sda; + + for (bit = 0 ; bit < 8 ; bit++) { + sda = (v & 0x80) ? 2 : 0; + v <<= 1; + /* SDE=1, SDA=sda, SCL=0 */ + err += w9968cf_write_sb(cam, 0x10 | sda); + /* SDE=1, SDA=sda, SCL=1 */ + err += w9968cf_write_sb(cam, 0x11 | sda); + /* SDE=1, SDA=sda, SCL=0 */ + err += w9968cf_write_sb(cam, 0x10 | sda); + } + + return err; +} + + +static int w9968cf_smbus_read_byte(struct w9968cf_device* cam, u8* v) +{ + u8 bit; + int err = 0; + + *v = 0; + for (bit = 0 ; bit < 8 ; bit++) { + *v <<= 1; + err += w9968cf_write_sb(cam, 0x0013); + *v |= (w9968cf_read_sb(cam) & 0x0008) ? 1 : 0; + err += w9968cf_write_sb(cam, 0x0012); + } + + return err; +} + + +static int w9968cf_smbus_write_ack(struct w9968cf_device* cam) +{ + int err = 0; + + err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ + err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ + err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ + + return err; +} + + +static int w9968cf_smbus_read_ack(struct w9968cf_device* cam) +{ + int err = 0, sda; + + err += w9968cf_write_sb(cam, 0x0013); /* SDE=1, SDA=1, SCL=1 */ + sda = (w9968cf_read_sb(cam) & 0x08) ? 1 : 0; /* sda = SDA */ + err += w9968cf_write_sb(cam, 0x0012); /* SDE=1, SDA=1, SCL=0 */ + if (sda < 0) + err += sda; + if (sda == 1) { + DBG(6, "Couldn't receive the ACK") + err += -1; + } + + return err; +} + + +/* This seems to refresh the communication through the serial bus */ +static int w9968cf_smbus_refresh_bus(struct w9968cf_device* cam) +{ + int err = 0, j; + + for (j = 1; j <= 10; j++) { + err = w9968cf_write_reg(cam, 0x0020, 0x01); + err += w9968cf_write_reg(cam, 0x0000, 0x01); + if (err) + break; + } + + return err; +} + + +/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ +static int +w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam, + u16 address, u8 subaddress,u8 value) +{ + u16* data = cam->data_buffer; + int err = 0; + + err += w9968cf_smbus_refresh_bus(cam); + + /* Enable SBUS outputs */ + err += w9968cf_write_sb(cam, 0x0020); + + data[0] = 0x082f | ((address & 0x80) ? 0x1500 : 0x0); + data[0] |= (address & 0x40) ? 0x4000 : 0x0; + data[1] = 0x2082 | ((address & 0x40) ? 0x0005 : 0x0); + data[1] |= (address & 0x20) ? 0x0150 : 0x0; + data[1] |= (address & 0x10) ? 0x5400 : 0x0; + data[2] = 0x8208 | ((address & 0x08) ? 0x0015 : 0x0); + data[2] |= (address & 0x04) ? 0x0540 : 0x0; + data[2] |= (address & 0x02) ? 0x5000 : 0x0; + data[3] = 0x1d20 | ((address & 0x02) ? 0x0001 : 0x0); + data[3] |= (address & 0x01) ? 0x0054 : 0x0; + + err += w9968cf_write_fsb(cam, data); + + data[0] = 0x8208 | ((subaddress & 0x80) ? 0x0015 : 0x0); + data[0] |= (subaddress & 0x40) ? 0x0540 : 0x0; + data[0] |= (subaddress & 0x20) ? 0x5000 : 0x0; + data[1] = 0x0820 | ((subaddress & 0x20) ? 0x0001 : 0x0); + data[1] |= (subaddress & 0x10) ? 0x0054 : 0x0; + data[1] |= (subaddress & 0x08) ? 0x1500 : 0x0; + data[1] |= (subaddress & 0x04) ? 0x4000 : 0x0; + data[2] = 0x2082 | ((subaddress & 0x04) ? 0x0005 : 0x0); + data[2] |= (subaddress & 0x02) ? 0x0150 : 0x0; + data[2] |= (subaddress & 0x01) ? 0x5400 : 0x0; + data[3] = 0x001d; + + err += w9968cf_write_fsb(cam, data); + + data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); + data[0] |= (value & 0x40) ? 0x0540 : 0x0; + data[0] |= (value & 0x20) ? 0x5000 : 0x0; + data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0); + data[1] |= (value & 0x10) ? 0x0054 : 0x0; + data[1] |= (value & 0x08) ? 0x1500 : 0x0; + data[1] |= (value & 0x04) ? 0x4000 : 0x0; + data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0); + data[2] |= (value & 0x02) ? 0x0150 : 0x0; + data[2] |= (value & 0x01) ? 0x5400 : 0x0; + data[3] = 0xfe1d; + + err += w9968cf_write_fsb(cam, data); + + /* Disable SBUS outputs */ + err += w9968cf_write_sb(cam, 0x0000); + + if (!err) + DBG(5, "I2C write byte data done, addr.0x%04X, subaddr.0x%02X " + "value 0x%02X", address, subaddress, value) + else + DBG(5, "I2C write byte data failed, addr.0x%04X, " + "subaddr.0x%02X, value 0x%02X", + address, subaddress, value) + + return err; +} + + +/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ +static int +w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam, + u16 address, u8 subaddress, + u8* value) +{ + int err = 0; + + /* Serial data enable */ + err += w9968cf_write_sb(cam, 0x0013); /* don't change ! */ + + err += w9968cf_smbus_start(cam); + err += w9968cf_smbus_write_byte(cam, address); + err += w9968cf_smbus_read_ack(cam); + err += w9968cf_smbus_write_byte(cam, subaddress); + err += w9968cf_smbus_read_ack(cam); + err += w9968cf_smbus_stop(cam); + err += w9968cf_smbus_start(cam); + err += w9968cf_smbus_write_byte(cam, address + 1); + err += w9968cf_smbus_read_ack(cam); + err += w9968cf_smbus_read_byte(cam, value); + err += w9968cf_smbus_write_ack(cam); + err += w9968cf_smbus_stop(cam); + + /* Serial data disable */ + err += w9968cf_write_sb(cam, 0x0000); + + if (!err) + DBG(5, "I2C read byte data done, addr.0x%04X, " + "subaddr.0x%02X, value 0x%02X", + address, subaddress, *value) + else + DBG(5, "I2C read byte data failed, addr.0x%04X, " + "subaddr.0x%02X, wrong value 0x%02X", + address, subaddress, *value) + + return err; +} + + +/* SMBus protocol: S Addr+1 Rd [A] [Value] NA P */ +static int +w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam, + u16 address, u8* value) +{ + int err = 0; + + /* Serial data enable */ + err += w9968cf_write_sb(cam, 0x0013); + + err += w9968cf_smbus_start(cam); + err += w9968cf_smbus_write_byte(cam, address + 1); + err += w9968cf_smbus_read_ack(cam); + err += w9968cf_smbus_read_byte(cam, value); + err += w9968cf_smbus_write_ack(cam); + err += w9968cf_smbus_stop(cam); + + /* Serial data disable */ + err += w9968cf_write_sb(cam, 0x0000); + + if (!err) + DBG(5, "I2C read byte done, addr.0x%04X, " + "value 0x%02X", address, *value) + else + DBG(5, "I2C read byte failed, addr.0x%04X, " + "wrong value 0x%02X", address, *value) + + return err; +} + + +/* SMBus protocol: S Addr Wr [A] Value [A] P */ +static int +w9968cf_i2c_adap_write_byte(struct w9968cf_device* cam, + u16 address, u8 value) +{ + DBG(4, "i2c_write_byte() is an unsupported transfer mode") + return -EINVAL; +} + + + +/**************************************************************************** + * I2C interface to kernel * + ****************************************************************************/ + +static int +w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data *data) +{ + struct w9968cf_device* cam = i2c_get_adapdata(adapter); + u8 i; + int err = 0; + + switch (addr) { + case OV6xx0_SID: + case OV7xx0_SID: + break; + default: + DBG(4, "Rejected slave ID 0x%04X", addr) + return -EINVAL; + } + + if (size == I2C_SMBUS_BYTE) { + /* Why addr <<= 1? See OVXXX0_SID defines in ovcamchip.h */ + addr <<= 1; + + if (read_write == I2C_SMBUS_WRITE) + err = w9968cf_i2c_adap_write_byte(cam, addr, command); + else if (read_write == I2C_SMBUS_READ) + err = w9968cf_i2c_adap_read_byte(cam,addr,&data->byte); + + } else if (size == I2C_SMBUS_BYTE_DATA) { + addr <<= 1; + + if (read_write == I2C_SMBUS_WRITE) + err = w9968cf_i2c_adap_fastwrite_byte_data(cam, addr, + command, data->byte); + else if (read_write == I2C_SMBUS_READ) { + for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) { + err = w9968cf_i2c_adap_read_byte_data(cam,addr, + command, &data->byte); + if (err) { + if (w9968cf_smbus_refresh_bus(cam)) { + err = -EIO; + break; + } + } else + break; + } + + } else + return -EINVAL; + + } else { + DBG(4, "Unsupported I2C transfer mode (%d)", size) + return -EINVAL; + } + + return err; +} + + +static u32 w9968cf_i2c_func(struct i2c_adapter* adap) +{ + return I2C_FUNC_SMBUS_READ_BYTE | + I2C_FUNC_SMBUS_READ_BYTE_DATA | + I2C_FUNC_SMBUS_WRITE_BYTE_DATA; +} + + +static int w9968cf_i2c_attach_inform(struct i2c_client* client) +{ + struct w9968cf_device* cam = i2c_get_adapdata(client->adapter); + int id = client->driver->id, err = 0; + + if (id == I2C_DRIVERID_OVCAMCHIP) { + cam->sensor_client = client; + err = w9968cf_sensor_init(cam); + if (err) { + cam->sensor_client = NULL; + return err; + } + } else { + DBG(4, "Rejected client [%s] with driver [%s]", + client->name, client->driver->driver.name) + return -EINVAL; + } + + DBG(5, "I2C attach client [%s] with driver [%s]", + client->name, client->driver->driver.name) + + return 0; +} + + +static int w9968cf_i2c_detach_inform(struct i2c_client* client) +{ + struct w9968cf_device* cam = i2c_get_adapdata(client->adapter); + + if (cam->sensor_client == client) + cam->sensor_client = NULL; + + DBG(5, "I2C detach client [%s]", client->name) + + return 0; +} + + +static int +w9968cf_i2c_control(struct i2c_adapter* adapter, unsigned int cmd, + unsigned long arg) +{ + return 0; +} + + +static int w9968cf_i2c_init(struct w9968cf_device* cam) +{ + int err = 0; + + static struct i2c_algorithm algo = { + .smbus_xfer = w9968cf_i2c_smbus_xfer, + .algo_control = w9968cf_i2c_control, + .functionality = w9968cf_i2c_func, + }; + + static struct i2c_adapter adap = { + .id = I2C_HW_SMBUS_W9968CF, + .class = I2C_CLASS_CAM_DIGITAL, + .owner = THIS_MODULE, + .client_register = w9968cf_i2c_attach_inform, + .client_unregister = w9968cf_i2c_detach_inform, + .algo = &algo, + }; + + memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter)); + strcpy(cam->i2c_adapter.name, "w9968cf"); + i2c_set_adapdata(&cam->i2c_adapter, cam); + + DBG(6, "Registering I2C adapter with kernel...") + + err = i2c_add_adapter(&cam->i2c_adapter); + if (err) + DBG(1, "Failed to register the I2C adapter") + else + DBG(5, "I2C adapter registered") + + return err; +} + + + +/**************************************************************************** + * Helper functions * + ****************************************************************************/ + +/*-------------------------------------------------------------------------- + Turn on the LED on some webcams. A beep should be heard too. + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_turn_on_led(struct w9968cf_device* cam) +{ + int err = 0; + + err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power-down */ + err += w9968cf_write_reg(cam, 0xbf17, 0x00); /* reset everything */ + err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* normal operation */ + err += w9968cf_write_reg(cam, 0x0010, 0x01); /* serial bus, SDS high */ + err += w9968cf_write_reg(cam, 0x0000, 0x01); /* serial bus, SDS low */ + err += w9968cf_write_reg(cam, 0x0010, 0x01); /* ..high 'beep-beep' */ + + if (err) + DBG(2, "Couldn't turn on the LED") + + DBG(5, "LED turned on") + + return err; +} + + +/*-------------------------------------------------------------------------- + Write some registers for the device initialization. + This function is called once on open(). + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_init_chip(struct w9968cf_device* cam) +{ + unsigned long hw_bufsize = cam->maxwidth*cam->maxheight*2, + y0 = 0x0000, + u0 = y0 + hw_bufsize/2, + v0 = u0 + hw_bufsize/4, + y1 = v0 + hw_bufsize/4, + u1 = y1 + hw_bufsize/2, + v1 = u1 + hw_bufsize/4; + int err = 0; + + err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power off */ + err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* power on */ + + err += w9968cf_write_reg(cam, 0x405d, 0x03); /* DRAM timings */ + err += w9968cf_write_reg(cam, 0x0030, 0x04); /* SDRAM timings */ + + err += w9968cf_write_reg(cam, y0 & 0xffff, 0x20); /* Y buf.0, low */ + err += w9968cf_write_reg(cam, y0 >> 16, 0x21); /* Y buf.0, high */ + err += w9968cf_write_reg(cam, u0 & 0xffff, 0x24); /* U buf.0, low */ + err += w9968cf_write_reg(cam, u0 >> 16, 0x25); /* U buf.0, high */ + err += w9968cf_write_reg(cam, v0 & 0xffff, 0x28); /* V buf.0, low */ + err += w9968cf_write_reg(cam, v0 >> 16, 0x29); /* V buf.0, high */ + + err += w9968cf_write_reg(cam, y1 & 0xffff, 0x22); /* Y buf.1, low */ + err += w9968cf_write_reg(cam, y1 >> 16, 0x23); /* Y buf.1, high */ + err += w9968cf_write_reg(cam, u1 & 0xffff, 0x26); /* U buf.1, low */ + err += w9968cf_write_reg(cam, u1 >> 16, 0x27); /* U buf.1, high */ + err += w9968cf_write_reg(cam, v1 & 0xffff, 0x2a); /* V buf.1, low */ + err += w9968cf_write_reg(cam, v1 >> 16, 0x2b); /* V buf.1, high */ + + err += w9968cf_write_reg(cam, y1 & 0xffff, 0x32); /* JPEG buf 0 low */ + err += w9968cf_write_reg(cam, y1 >> 16, 0x33); /* JPEG buf 0 high */ + + err += w9968cf_write_reg(cam, y1 & 0xffff, 0x34); /* JPEG buf 1 low */ + err += w9968cf_write_reg(cam, y1 >> 16, 0x35); /* JPEG bug 1 high */ + + err += w9968cf_write_reg(cam, 0x0000, 0x36);/* JPEG restart interval */ + err += w9968cf_write_reg(cam, 0x0804, 0x37);/*JPEG VLE FIFO threshold*/ + err += w9968cf_write_reg(cam, 0x0000, 0x38);/* disable hw up-scaling */ + err += w9968cf_write_reg(cam, 0x0000, 0x3f); /* JPEG/MCTL test data */ + + err += w9968cf_set_picture(cam, cam->picture); /* this before */ + err += w9968cf_set_window(cam, cam->window); + + if (err) + DBG(1, "Chip initialization failed") + else + DBG(5, "Chip successfully initialized") + + return err; +} + + +/*-------------------------------------------------------------------------- + Return non-zero if the palette is supported, 0 otherwise. + --------------------------------------------------------------------------*/ +static inline u16 w9968cf_valid_palette(u16 palette) +{ + u8 i = 0; + while (w9968cf_formatlist[i].palette != 0) { + if (palette == w9968cf_formatlist[i].palette) + return palette; + i++; + } + return 0; +} + + +/*-------------------------------------------------------------------------- + Return the depth corresponding to the given palette. + Palette _must_ be supported ! + --------------------------------------------------------------------------*/ +static inline u16 w9968cf_valid_depth(u16 palette) +{ + u8 i=0; + while (w9968cf_formatlist[i].palette != palette) + i++; + + return w9968cf_formatlist[i].depth; +} + + +/*-------------------------------------------------------------------------- + Return non-zero if the format requires decompression, 0 otherwise. + --------------------------------------------------------------------------*/ +static inline u8 w9968cf_need_decompression(u16 palette) +{ + u8 i = 0; + while (w9968cf_formatlist[i].palette != 0) { + if (palette == w9968cf_formatlist[i].palette) + return w9968cf_formatlist[i].compression; + i++; + } + return 0; +} + + +/*-------------------------------------------------------------------------- + Change the picture settings of the camera. + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int +w9968cf_set_picture(struct w9968cf_device* cam, struct video_picture pict) +{ + u16 fmt, hw_depth, hw_palette, reg_v = 0x0000; + int err = 0; + + /* Make sure we are using a valid depth */ + pict.depth = w9968cf_valid_depth(pict.palette); + + fmt = pict.palette; + + hw_depth = pict.depth; /* depth used by the winbond chip */ + hw_palette = pict.palette; /* palette used by the winbond chip */ + + /* VS & HS polarities */ + reg_v = (cam->vs_polarity << 12) | (cam->hs_polarity << 11); + + switch (fmt) + { + case VIDEO_PALETTE_UYVY: + reg_v |= 0x0000; + cam->vpp_flag = VPP_NONE; + break; + case VIDEO_PALETTE_YUV422P: + reg_v |= 0x0002; + cam->vpp_flag = VPP_DECOMPRESSION; + break; + case VIDEO_PALETTE_YUV420: + case VIDEO_PALETTE_YUV420P: + reg_v |= 0x0003; + cam->vpp_flag = VPP_DECOMPRESSION; + break; + case VIDEO_PALETTE_YUYV: + case VIDEO_PALETTE_YUV422: + reg_v |= 0x0000; + cam->vpp_flag = VPP_SWAP_YUV_BYTES; + hw_palette = VIDEO_PALETTE_UYVY; + break; + /* Original video is used instead of RGBX palettes. + Software conversion later. */ + case VIDEO_PALETTE_GREY: + case VIDEO_PALETTE_RGB555: + case VIDEO_PALETTE_RGB565: + case VIDEO_PALETTE_RGB24: + case VIDEO_PALETTE_RGB32: + reg_v |= 0x0000; /* UYVY 16 bit is used */ + hw_depth = 16; + hw_palette = VIDEO_PALETTE_UYVY; + cam->vpp_flag = VPP_UYVY_TO_RGBX; + break; + } + + /* NOTE: due to memory issues, it is better to disable the hardware + double buffering during compression */ + if (cam->double_buffer && !(cam->vpp_flag & VPP_DECOMPRESSION)) + reg_v |= 0x0080; + + if (cam->clamping) + reg_v |= 0x0020; + + if (cam->filter_type == 1) + reg_v |= 0x0008; + else if (cam->filter_type == 2) + reg_v |= 0x000c; + + if ((err = w9968cf_write_reg(cam, reg_v, 0x16))) + goto error; + + if ((err = w9968cf_sensor_update_picture(cam, pict))) + goto error; + + /* If all went well, update the device data structure */ + memcpy(&cam->picture, &pict, sizeof(pict)); + cam->hw_depth = hw_depth; + cam->hw_palette = hw_palette; + + /* Settings changed, so we clear the frame buffers */ + memset(cam->frame[0].buffer, 0, cam->nbuffers*cam->frame[0].size); + + DBG(4, "Palette is %s, depth is %u bpp", + symbolic(v4l1_plist, pict.palette), pict.depth) + + return 0; + +error: + DBG(1, "Failed to change picture settings") + return err; +} + + +/*-------------------------------------------------------------------------- + Change the capture area size of the camera. + This function _must_ be called _after_ w9968cf_set_picture(). + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int +w9968cf_set_window(struct w9968cf_device* cam, struct video_window win) +{ + u16 x, y, w, h, scx, scy, cw, ch, ax, ay; + unsigned long fw, fh; + struct ovcamchip_window s_win; + int err = 0; + + /* Work around to avoid FP arithmetics */ + #define __SC(x) ((x) << 10) + #define __UNSC(x) ((x) >> 10) + + /* Make sure we are using a supported resolution */ + if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, + (u16*)&win.height))) + goto error; + + /* Scaling factors */ + fw = __SC(win.width) / cam->maxwidth; + fh = __SC(win.height) / cam->maxheight; + + /* Set up the width and height values used by the chip */ + if ((win.width > cam->maxwidth) || (win.height > cam->maxheight)) { + cam->vpp_flag |= VPP_UPSCALE; + /* Calculate largest w,h mantaining the same w/h ratio */ + w = (fw >= fh) ? cam->maxwidth : __SC(win.width)/fh; + h = (fw >= fh) ? __SC(win.height)/fw : cam->maxheight; + if (w < cam->minwidth) /* just in case */ + w = cam->minwidth; + if (h < cam->minheight) /* just in case */ + h = cam->minheight; + } else { + cam->vpp_flag &= ~VPP_UPSCALE; + w = win.width; + h = win.height; + } + + /* x,y offsets of the cropped area */ + scx = cam->start_cropx; + scy = cam->start_cropy; + + /* Calculate cropped area manteining the right w/h ratio */ + if (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE)) { + cw = (fw >= fh) ? cam->maxwidth : __SC(win.width)/fh; + ch = (fw >= fh) ? __SC(win.height)/fw : cam->maxheight; + } else { + cw = w; + ch = h; + } + + /* Setup the window of the sensor */ + s_win.format = VIDEO_PALETTE_UYVY; + s_win.width = cam->maxwidth; + s_win.height = cam->maxheight; + s_win.quarter = 0; /* full progressive video */ + + /* Center it */ + s_win.x = (s_win.width - cw) / 2; + s_win.y = (s_win.height - ch) / 2; + + /* Clock divisor */ + if (cam->clockdiv >= 0) + s_win.clockdiv = cam->clockdiv; /* manual override */ + else + switch (cam->sensor) { + case CC_OV6620: + s_win.clockdiv = 0; + break; + case CC_OV6630: + s_win.clockdiv = 0; + break; + case CC_OV76BE: + case CC_OV7610: + case CC_OV7620: + s_win.clockdiv = 0; + break; + default: + s_win.clockdiv = W9968CF_DEF_CLOCKDIVISOR; + } + + /* We have to scale win.x and win.y offsets */ + if ( (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE)) + || (cam->vpp_flag & VPP_UPSCALE) ) { + ax = __SC(win.x)/fw; + ay = __SC(win.y)/fh; + } else { + ax = win.x; + ay = win.y; + } + + if ((ax + cw) > cam->maxwidth) + ax = cam->maxwidth - cw; + + if ((ay + ch) > cam->maxheight) + ay = cam->maxheight - ch; + + /* Adjust win.x, win.y */ + if ( (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE)) + || (cam->vpp_flag & VPP_UPSCALE) ) { + win.x = __UNSC(ax*fw); + win.y = __UNSC(ay*fh); + } else { + win.x = ax; + win.y = ay; + } + + /* Offsets used by the chip */ + x = ax + s_win.x; + y = ay + s_win.y; + + /* Go ! */ + if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_MODE, &s_win))) + goto error; + + err += w9968cf_write_reg(cam, scx + x, 0x10); + err += w9968cf_write_reg(cam, scy + y, 0x11); + err += w9968cf_write_reg(cam, scx + x + cw, 0x12); + err += w9968cf_write_reg(cam, scy + y + ch, 0x13); + err += w9968cf_write_reg(cam, w, 0x14); + err += w9968cf_write_reg(cam, h, 0x15); + + /* JPEG width & height */ + err += w9968cf_write_reg(cam, w, 0x30); + err += w9968cf_write_reg(cam, h, 0x31); + + /* Y & UV frame buffer strides (in WORD) */ + if (cam->vpp_flag & VPP_DECOMPRESSION) { + err += w9968cf_write_reg(cam, w/2, 0x2c); + err += w9968cf_write_reg(cam, w/4, 0x2d); + } else + err += w9968cf_write_reg(cam, w, 0x2c); + + if (err) + goto error; + + /* If all went well, update the device data structure */ + memcpy(&cam->window, &win, sizeof(win)); + cam->hw_width = w; + cam->hw_height = h; + + /* Settings changed, so we clear the frame buffers */ + memset(cam->frame[0].buffer, 0, cam->nbuffers*cam->frame[0].size); + + DBG(4, "The capture area is %dx%d, Offset (x,y)=(%u,%u)", + win.width, win.height, win.x, win.y) + + PDBGG("x=%u ,y=%u, w=%u, h=%u, ax=%u, ay=%u, s_win.x=%u, s_win.y=%u, " + "cw=%u, ch=%u, win.x=%u, win.y=%u, win.width=%u, win.height=%u", + x, y, w, h, ax, ay, s_win.x, s_win.y, cw, ch, win.x, win.y, + win.width, win.height) + + return 0; + +error: + DBG(1, "Failed to change the capture area size") + return err; +} + + +/*-------------------------------------------------------------------------- + Adjust the asked values for window width and height. + Return 0 on success, -1 otherwise. + --------------------------------------------------------------------------*/ +static int +w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height) +{ + u16 maxw, maxh; + + if ((*width < cam->minwidth) || (*height < cam->minheight)) + return -ERANGE; + + maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && + w9968cf_vpp ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) + : cam->maxwidth; + maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && + w9968cf_vpp ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) + : cam->maxheight; + + if (*width > maxw) + *width = maxw; + if (*height > maxh) + *height = maxh; + + if (cam->vpp_flag & VPP_DECOMPRESSION) { + *width &= ~15L; /* multiple of 16 */ + *height &= ~15L; + } + + PDBGG("Window size adjusted w=%u, h=%u ", *width, *height) + + return 0; +} + + +/*-------------------------------------------------------------------------- + Initialize the FIFO list of requested frames. + --------------------------------------------------------------------------*/ +static void w9968cf_init_framelist(struct w9968cf_device* cam) +{ + u8 i; + + for (i = 0; i < cam->nbuffers; i++) { + cam->requested_frame[i] = NULL; + cam->frame[i].queued = 0; + cam->frame[i].status = F_UNUSED; + } +} + + +/*-------------------------------------------------------------------------- + Add a frame in the FIFO list of requested frames. + This function is called in process context. + --------------------------------------------------------------------------*/ +static void w9968cf_push_frame(struct w9968cf_device* cam, u8 f_num) +{ + u8 f; + unsigned long lock_flags; + + spin_lock_irqsave(&cam->flist_lock, lock_flags); + + for (f=0; cam->requested_frame[f] != NULL; f++); + cam->requested_frame[f] = &cam->frame[f_num]; + cam->frame[f_num].queued = 1; + cam->frame[f_num].status = F_UNUSED; /* clear the status */ + + spin_unlock_irqrestore(&cam->flist_lock, lock_flags); + + DBG(6, "Frame #%u pushed into the FIFO list. Position %u", f_num, f) +} + + +/*-------------------------------------------------------------------------- + Read, store and remove the first pointer in the FIFO list of requested + frames. This function is called in interrupt context. + --------------------------------------------------------------------------*/ +static void +w9968cf_pop_frame(struct w9968cf_device* cam, struct w9968cf_frame_t** framep) +{ + u8 i; + + spin_lock(&cam->flist_lock); + + *framep = cam->requested_frame[0]; + + /* Shift the list of pointers */ + for (i = 0; i < cam->nbuffers-1; i++) + cam->requested_frame[i] = cam->requested_frame[i+1]; + cam->requested_frame[i] = NULL; + + spin_unlock(&cam->flist_lock); + + DBG(6,"Popped frame #%d from the list", (*framep)->number) +} + + +/*-------------------------------------------------------------------------- + High-level video post-processing routine on grabbed frames. + Return 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int +w9968cf_postprocess_frame(struct w9968cf_device* cam, + struct w9968cf_frame_t* fr) +{ + void *pIn = fr->buffer, *pOut = cam->frame_vpp.buffer, *tmp; + u16 w = cam->window.width, + h = cam->window.height, + d = cam->picture.depth, + fmt = cam->picture.palette, + rgb = cam->force_rgb, + hw_w = cam->hw_width, + hw_h = cam->hw_height, + hw_d = cam->hw_depth; + int err = 0; + + #define _PSWAP(pIn, pOut) {tmp = (pIn); (pIn) = (pOut); (pOut) = tmp;} + + if (cam->vpp_flag & VPP_DECOMPRESSION) { + memcpy(pOut, pIn, fr->length); + _PSWAP(pIn, pOut) + err = w9968cf_vpp->decode(pIn, fr->length, hw_w, hw_h, pOut); + PDBGG("Compressed frame length: %lu",(unsigned long)fr->length) + fr->length = (hw_w*hw_h*hw_d)/8; + _PSWAP(pIn, pOut) + if (err) { + DBG(4, "An error occurred while decoding the frame: " + "%s", symbolic(decoder_errlist, err)) + return err; + } else + DBG(6, "Frame decoded") + } + + if (cam->vpp_flag & VPP_SWAP_YUV_BYTES) { + w9968cf_vpp->swap_yuvbytes(pIn, fr->length); + DBG(6, "Original UYVY component ordering changed") + } + + if (cam->vpp_flag & VPP_UPSCALE) { + w9968cf_vpp->scale_up(pIn, pOut, hw_w, hw_h, hw_d, w, h); + fr->length = (w*h*hw_d)/8; + _PSWAP(pIn, pOut) + DBG(6, "Vertical up-scaling done: %u,%u,%ubpp->%u,%u", + hw_w, hw_h, hw_d, w, h) + } + + if (cam->vpp_flag & VPP_UYVY_TO_RGBX) { + w9968cf_vpp->uyvy_to_rgbx(pIn, fr->length, pOut, fmt, rgb); + fr->length = (w*h*d)/8; + _PSWAP(pIn, pOut) + DBG(6, "UYVY-16bit to %s conversion done", + symbolic(v4l1_plist, fmt)) + } + + if (pOut == fr->buffer) + memcpy(fr->buffer, cam->frame_vpp.buffer, fr->length); + + return 0; +} + + + +/**************************************************************************** + * Image sensor control routines * + ****************************************************************************/ + +static int +w9968cf_sensor_set_control(struct w9968cf_device* cam, int cid, int val) +{ + struct ovcamchip_control ctl; + int err; + + ctl.id = cid; + ctl.value = val; + + err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_CTRL, &ctl); + + return err; +} + + +static int +w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int* val) +{ + struct ovcamchip_control ctl; + int err; + + ctl.id = cid; + + err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_G_CTRL, &ctl); + if (!err) + *val = ctl.value; + + return err; +} + + +static int +w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg) +{ + struct i2c_client* c = cam->sensor_client; + int rc = 0; + + if (!c || !c->driver || !c->driver->command) + return -EINVAL; + + rc = c->driver->command(c, cmd, arg); + /* The I2C driver returns -EPERM on non-supported controls */ + return (rc < 0 && rc != -EPERM) ? rc : 0; +} + + +/*-------------------------------------------------------------------------- + Update some settings of the image sensor. + Returns: 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_sensor_update_settings(struct w9968cf_device* cam) +{ + int err = 0; + + /* Auto brightness */ + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOBRIGHT, + cam->auto_brt); + if (err) + return err; + + /* Auto exposure */ + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOEXP, + cam->auto_exp); + if (err) + return err; + + /* Banding filter */ + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BANDFILT, + cam->bandfilt); + if (err) + return err; + + /* Light frequency */ + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_FREQ, + cam->lightfreq); + if (err) + return err; + + /* Back light */ + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BACKLIGHT, + cam->backlight); + if (err) + return err; + + /* Mirror */ + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_MIRROR, + cam->mirror); + if (err) + return err; + + return 0; +} + + +/*-------------------------------------------------------------------------- + Get some current picture settings from the image sensor and update the + internal 'picture' structure of the camera. + Returns: 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_sensor_get_picture(struct w9968cf_device* cam) +{ + int err, v; + + err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_CONT, &v); + if (err) + return err; + cam->picture.contrast = v; + + err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_BRIGHT, &v); + if (err) + return err; + cam->picture.brightness = v; + + err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_SAT, &v); + if (err) + return err; + cam->picture.colour = v; + + err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_HUE, &v); + if (err) + return err; + cam->picture.hue = v; + + DBG(5, "Got picture settings from the image sensor") + + PDBGG("Brightness, contrast, hue, colour, whiteness are " + "%u,%u,%u,%u,%u", cam->picture.brightness,cam->picture.contrast, + cam->picture.hue, cam->picture.colour, cam->picture.whiteness) + + return 0; +} + + +/*-------------------------------------------------------------------------- + Update picture settings of the image sensor. + Returns: 0 on success, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int +w9968cf_sensor_update_picture(struct w9968cf_device* cam, + struct video_picture pict) +{ + int err = 0; + + if ((!cam->sensor_initialized) + || pict.contrast != cam->picture.contrast) { + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_CONT, + pict.contrast); + if (err) + goto fail; + DBG(4, "Contrast changed from %u to %u", + cam->picture.contrast, pict.contrast) + cam->picture.contrast = pict.contrast; + } + + if (((!cam->sensor_initialized) || + pict.brightness != cam->picture.brightness) && (!cam->auto_brt)) { + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BRIGHT, + pict.brightness); + if (err) + goto fail; + DBG(4, "Brightness changed from %u to %u", + cam->picture.brightness, pict.brightness) + cam->picture.brightness = pict.brightness; + } + + if ((!cam->sensor_initialized) || pict.colour != cam->picture.colour) { + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_SAT, + pict.colour); + if (err) + goto fail; + DBG(4, "Colour changed from %u to %u", + cam->picture.colour, pict.colour) + cam->picture.colour = pict.colour; + } + + if ((!cam->sensor_initialized) || pict.hue != cam->picture.hue) { + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_HUE, + pict.hue); + if (err) + goto fail; + DBG(4, "Hue changed from %u to %u", + cam->picture.hue, pict.hue) + cam->picture.hue = pict.hue; + } + + return 0; + +fail: + DBG(4, "Failed to change sensor picture setting") + return err; +} + + + +/**************************************************************************** + * Camera configuration * + ****************************************************************************/ + +/*-------------------------------------------------------------------------- + This function is called when a supported image sensor is detected. + Return 0 if the initialization succeeds, a negative number otherwise. + --------------------------------------------------------------------------*/ +static int w9968cf_sensor_init(struct w9968cf_device* cam) +{ + int err = 0; + + if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_INITIALIZE, + &cam->monochrome))) + goto error; + + if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_Q_SUBTYPE, + &cam->sensor))) + goto error; + + /* NOTE: Make sure width and height are a multiple of 16 */ + switch (cam->sensor_client->addr) { + case OV6xx0_SID: + cam->maxwidth = 352; + cam->maxheight = 288; + cam->minwidth = 64; + cam->minheight = 48; + break; + case OV7xx0_SID: + cam->maxwidth = 640; + cam->maxheight = 480; + cam->minwidth = 64; + cam->minheight = 48; + break; + default: + DBG(1, "Not supported image sensor detected for %s", + symbolic(camlist, cam->id)) + return -EINVAL; + } + + /* These values depend on the ones in the ovxxx0.c sources */ + switch (cam->sensor) { + case CC_OV7620: + cam->start_cropx = 287; + cam->start_cropy = 35; + /* Seems to work around a bug in the image sensor */ + cam->vs_polarity = 1; + cam->hs_polarity = 1; + break; + default: + cam->start_cropx = 320; + cam->start_cropy = 35; + cam->vs_polarity = 1; + cam->hs_polarity = 0; + } + + if ((err = w9968cf_sensor_update_settings(cam))) + goto error; + + if ((err = w9968cf_sensor_update_picture(cam, cam->picture))) + goto error; + + cam->sensor_initialized = 1; + + DBG(2, "%s image sensor initialized", symbolic(senlist, cam->sensor)) + return 0; + +error: + cam->sensor_initialized = 0; + cam->sensor = CC_UNKNOWN; + DBG(1, "Image sensor initialization failed for %s (/dev/video%d). " + "Try to detach and attach this device again", + symbolic(camlist, cam->id), cam->v4ldev->minor) + return err; +} + + +/*-------------------------------------------------------------------------- + Fill some basic fields in the main device data structure. + This function is called once on w9968cf_usb_probe() for each recognized + camera. + --------------------------------------------------------------------------*/ +static void +w9968cf_configure_camera(struct w9968cf_device* cam, + struct usb_device* udev, + enum w9968cf_model_id mod_id, + const unsigned short dev_nr) +{ + mutex_init(&cam->fileop_mutex); + init_waitqueue_head(&cam->open); + spin_lock_init(&cam->urb_lock); + spin_lock_init(&cam->flist_lock); + + cam->users = 0; + cam->disconnected = 0; + cam->id = mod_id; + cam->sensor = CC_UNKNOWN; + cam->sensor_initialized = 0; + + /* Calculate the alternate setting number (from 1 to 16) + according to the 'packet_size' module parameter */ + if (packet_size[dev_nr] < W9968CF_MIN_PACKET_SIZE) + packet_size[dev_nr] = W9968CF_MIN_PACKET_SIZE; + for (cam->altsetting = 1; + packet_size[dev_nr] < wMaxPacketSize[cam->altsetting-1]; + cam->altsetting++); + + cam->max_buffers = (max_buffers[dev_nr] < 2 || + max_buffers[dev_nr] > W9968CF_MAX_BUFFERS) + ? W9968CF_BUFFERS : (u8)max_buffers[dev_nr]; + + cam->double_buffer = (double_buffer[dev_nr] == 0 || + double_buffer[dev_nr] == 1) + ? (u8)double_buffer[dev_nr]:W9968CF_DOUBLE_BUFFER; + + cam->clamping = (clamping[dev_nr] == 0 || clamping[dev_nr] == 1) + ? (u8)clamping[dev_nr] : W9968CF_CLAMPING; + + cam->filter_type = (filter_type[dev_nr] == 0 || + filter_type[dev_nr] == 1 || + filter_type[dev_nr] == 2) + ? (u8)filter_type[dev_nr] : W9968CF_FILTER_TYPE; + + cam->capture = 1; + + cam->largeview = (largeview[dev_nr] == 0 || largeview[dev_nr] == 1) + ? (u8)largeview[dev_nr] : W9968CF_LARGEVIEW; + + cam->decompression = (decompression[dev_nr] == 0 || + decompression[dev_nr] == 1 || + decompression[dev_nr] == 2) + ? (u8)decompression[dev_nr]:W9968CF_DECOMPRESSION; + + cam->upscaling = (upscaling[dev_nr] == 0 || + upscaling[dev_nr] == 1) + ? (u8)upscaling[dev_nr] : W9968CF_UPSCALING; + + cam->auto_brt = (autobright[dev_nr] == 0 || autobright[dev_nr] == 1) + ? (u8)autobright[dev_nr] : W9968CF_AUTOBRIGHT; + + cam->auto_exp = (autoexp[dev_nr] == 0 || autoexp[dev_nr] == 1) + ? (u8)autoexp[dev_nr] : W9968CF_AUTOEXP; + + cam->lightfreq = (lightfreq[dev_nr] == 50 || lightfreq[dev_nr] == 60) + ? (u8)lightfreq[dev_nr] : W9968CF_LIGHTFREQ; + + cam->bandfilt = (bandingfilter[dev_nr] == 0 || + bandingfilter[dev_nr] == 1) + ? (u8)bandingfilter[dev_nr] : W9968CF_BANDINGFILTER; + + cam->backlight = (backlight[dev_nr] == 0 || backlight[dev_nr] == 1) + ? (u8)backlight[dev_nr] : W9968CF_BACKLIGHT; + + cam->clockdiv = (clockdiv[dev_nr] == -1 || clockdiv[dev_nr] >= 0) + ? (s8)clockdiv[dev_nr] : W9968CF_CLOCKDIV; + + cam->mirror = (mirror[dev_nr] == 0 || mirror[dev_nr] == 1) + ? (u8)mirror[dev_nr] : W9968CF_MIRROR; + + cam->monochrome = (monochrome[dev_nr] == 0 || monochrome[dev_nr] == 1) + ? monochrome[dev_nr] : W9968CF_MONOCHROME; + + cam->picture.brightness = (u16)brightness[dev_nr]; + cam->picture.hue = (u16)hue[dev_nr]; + cam->picture.colour = (u16)colour[dev_nr]; + cam->picture.contrast = (u16)contrast[dev_nr]; + cam->picture.whiteness = (u16)whiteness[dev_nr]; + if (w9968cf_valid_palette((u16)force_palette[dev_nr])) { + cam->picture.palette = (u16)force_palette[dev_nr]; + cam->force_palette = 1; + } else { + cam->force_palette = 0; + if (cam->decompression == 0) + cam->picture.palette = W9968CF_PALETTE_DECOMP_OFF; + else if (cam->decompression == 1) + cam->picture.palette = W9968CF_PALETTE_DECOMP_FORCE; + else + cam->picture.palette = W9968CF_PALETTE_DECOMP_ON; + } + cam->picture.depth = w9968cf_valid_depth(cam->picture.palette); + + cam->force_rgb = (force_rgb[dev_nr] == 0 || force_rgb[dev_nr] == 1) + ? (u8)force_rgb[dev_nr] : W9968CF_FORCE_RGB; + + cam->window.x = 0; + cam->window.y = 0; + cam->window.width = W9968CF_WIDTH; + cam->window.height = W9968CF_HEIGHT; + cam->window.chromakey = 0; + cam->window.clipcount = 0; + cam->window.flags = 0; + + DBG(3, "%s configured with settings #%u:", + symbolic(camlist, cam->id), dev_nr) + + DBG(3, "- Data packet size for USB isochrnous transfer: %u bytes", + wMaxPacketSize[cam->altsetting-1]) + + DBG(3, "- Number of requested video frame buffers: %u", + cam->max_buffers) + + if (cam->double_buffer) + DBG(3, "- Hardware double buffering enabled") + else + DBG(3, "- Hardware double buffering disabled") + + if (cam->filter_type == 0) + DBG(3, "- Video filtering disabled") + else if (cam->filter_type == 1) + DBG(3, "- Video filtering enabled: type 1-2-1") + else if (cam->filter_type == 2) + DBG(3, "- Video filtering enabled: type 2-3-6-3-2") + + if (cam->clamping) + DBG(3, "- Video data clamping (CCIR-601 format) enabled") + else + DBG(3, "- Video data clamping (CCIR-601 format) disabled") + + if (cam->largeview) + DBG(3, "- Large view enabled") + else + DBG(3, "- Large view disabled") + + if ((cam->decompression) == 0 && (!cam->force_palette)) + DBG(3, "- Decompression disabled") + else if ((cam->decompression) == 1 && (!cam->force_palette)) + DBG(3, "- Decompression forced") + else if ((cam->decompression) == 2 && (!cam->force_palette)) + DBG(3, "- Decompression allowed") + + if (cam->upscaling) + DBG(3, "- Software image scaling enabled") + else + DBG(3, "- Software image scaling disabled") + + if (cam->force_palette) + DBG(3, "- Image palette forced to %s", + symbolic(v4l1_plist, cam->picture.palette)) + + if (cam->force_rgb) + DBG(3, "- RGB component ordering will be used instead of BGR") + + if (cam->auto_brt) + DBG(3, "- Auto brightness enabled") + else + DBG(3, "- Auto brightness disabled") + + if (cam->auto_exp) + DBG(3, "- Auto exposure enabled") + else + DBG(3, "- Auto exposure disabled") + + if (cam->backlight) + DBG(3, "- Backlight exposure algorithm enabled") + else + DBG(3, "- Backlight exposure algorithm disabled") + + if (cam->mirror) + DBG(3, "- Mirror enabled") + else + DBG(3, "- Mirror disabled") + + if (cam->bandfilt) + DBG(3, "- Banding filter enabled") + else + DBG(3, "- Banding filter disabled") + + DBG(3, "- Power lighting frequency: %u", cam->lightfreq) + + if (cam->clockdiv == -1) + DBG(3, "- Automatic clock divisor enabled") + else + DBG(3, "- Clock divisor: %d", cam->clockdiv) + + if (cam->monochrome) + DBG(3, "- Image sensor used as monochrome") + else + DBG(3, "- Image sensor not used as monochrome") +} + + +/*-------------------------------------------------------------------------- + If the video post-processing module is not loaded, some parameters + must be overridden. + --------------------------------------------------------------------------*/ +static void w9968cf_adjust_configuration(struct w9968cf_device* cam) +{ + if (!w9968cf_vpp) { + if (cam->decompression == 1) { + cam->decompression = 2; + DBG(2, "Video post-processing module not found: " + "'decompression' parameter forced to 2") + } + if (cam->upscaling) { + cam->upscaling = 0; + DBG(2, "Video post-processing module not found: " + "'upscaling' parameter forced to 0") + } + if (cam->picture.palette != VIDEO_PALETTE_UYVY) { + cam->force_palette = 0; + DBG(2, "Video post-processing module not found: " + "'force_palette' parameter forced to 0") + } + cam->picture.palette = VIDEO_PALETTE_UYVY; + cam->picture.depth = w9968cf_valid_depth(cam->picture.palette); + } +} + + +/*-------------------------------------------------------------------------- + Release the resources used by the driver. + This function is called on disconnect + (or on close if deallocation has been deferred) + --------------------------------------------------------------------------*/ +static void w9968cf_release_resources(struct w9968cf_device* cam) +{ + mutex_lock(&w9968cf_devlist_mutex); + + DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->minor) + + video_unregister_device(cam->v4ldev); + list_del(&cam->v4llist); + i2c_del_adapter(&cam->i2c_adapter); + w9968cf_deallocate_memory(cam); + kfree(cam->control_buffer); + kfree(cam->data_buffer); + + mutex_unlock(&w9968cf_devlist_mutex); +} + + + +/**************************************************************************** + * Video4Linux interface * + ****************************************************************************/ + +static int w9968cf_open(struct inode* inode, struct file* filp) +{ + struct w9968cf_device* cam; + int err; + + /* This the only safe way to prevent race conditions with disconnect */ + if (!down_read_trylock(&w9968cf_disconnect)) + return -ERESTARTSYS; + + cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); + + mutex_lock(&cam->dev_mutex); + + if (cam->sensor == CC_UNKNOWN) { + DBG(2, "No supported image sensor has been detected by the " + "'ovcamchip' module for the %s (/dev/video%d). Make " + "sure it is loaded *before* (re)connecting the camera.", + symbolic(camlist, cam->id), cam->v4ldev->minor) + mutex_unlock(&cam->dev_mutex); + up_read(&w9968cf_disconnect); + return -ENODEV; + } + + if (cam->users) { + DBG(2, "%s (/dev/video%d) has been already occupied by '%s'", + symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command) + if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) { + mutex_unlock(&cam->dev_mutex); + up_read(&w9968cf_disconnect); + return -EWOULDBLOCK; + } + mutex_unlock(&cam->dev_mutex); + err = wait_event_interruptible_exclusive(cam->open, + cam->disconnected || + !cam->users); + if (err) { + up_read(&w9968cf_disconnect); + return err; + } + if (cam->disconnected) { + up_read(&w9968cf_disconnect); + return -ENODEV; + } + mutex_lock(&cam->dev_mutex); + } + + DBG(5, "Opening '%s', /dev/video%d ...", + symbolic(camlist, cam->id), cam->v4ldev->minor) + + cam->streaming = 0; + cam->misconfigured = 0; + + w9968cf_adjust_configuration(cam); + + if ((err = w9968cf_allocate_memory(cam))) + goto deallocate_memory; + + if ((err = w9968cf_init_chip(cam))) + goto deallocate_memory; + + if ((err = w9968cf_start_transfer(cam))) + goto deallocate_memory; + + filp->private_data = cam; + + cam->users++; + strcpy(cam->command, current->comm); + + init_waitqueue_head(&cam->wait_queue); + + DBG(5, "Video device is open") + + mutex_unlock(&cam->dev_mutex); + up_read(&w9968cf_disconnect); + + return 0; + +deallocate_memory: + w9968cf_deallocate_memory(cam); + DBG(2, "Failed to open the video device") + mutex_unlock(&cam->dev_mutex); + up_read(&w9968cf_disconnect); + return err; +} + + +static int w9968cf_release(struct inode* inode, struct file* filp) +{ + struct w9968cf_device* cam; + + cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); + + mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ + + w9968cf_stop_transfer(cam); + + if (cam->disconnected) { + w9968cf_release_resources(cam); + mutex_unlock(&cam->dev_mutex); + kfree(cam); + return 0; + } + + cam->users--; + w9968cf_deallocate_memory(cam); + wake_up_interruptible_nr(&cam->open, 1); + + DBG(5, "Video device closed") + mutex_unlock(&cam->dev_mutex); + return 0; +} + + +static ssize_t +w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) +{ + struct w9968cf_device* cam; + struct w9968cf_frame_t* fr; + int err = 0; + + cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); + + if (filp->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->disconnected) { + DBG(2, "Device not present") + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->misconfigured) { + DBG(2, "The camera is misconfigured. Close and open it again.") + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + if (!cam->frame[0].queued) + w9968cf_push_frame(cam, 0); + + if (!cam->frame[1].queued) + w9968cf_push_frame(cam, 1); + + err = wait_event_interruptible(cam->wait_queue, + cam->frame[0].status == F_READY || + cam->frame[1].status == F_READY || + cam->disconnected); + if (err) { + mutex_unlock(&cam->fileop_mutex); + return err; + } + if (cam->disconnected) { + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + fr = (cam->frame[0].status == F_READY) ? &cam->frame[0]:&cam->frame[1]; + + if (w9968cf_vpp) + w9968cf_postprocess_frame(cam, fr); + + if (count > fr->length) + count = fr->length; + + if (copy_to_user(buf, fr->buffer, count)) { + fr->status = F_UNUSED; + mutex_unlock(&cam->fileop_mutex); + return -EFAULT; + } + *f_pos += count; + + fr->status = F_UNUSED; + + DBG(5, "%zu bytes read", count) + + mutex_unlock(&cam->fileop_mutex); + return count; +} + + +static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma) +{ + struct w9968cf_device* cam = (struct w9968cf_device*) + video_get_drvdata(video_devdata(filp)); + unsigned long vsize = vma->vm_end - vma->vm_start, + psize = cam->nbuffers * cam->frame[0].size, + start = vma->vm_start, + pos = (unsigned long)cam->frame[0].buffer, + page; + + if (cam->disconnected) { + DBG(2, "Device not present") + return -ENODEV; + } + + if (cam->misconfigured) { + DBG(2, "The camera is misconfigured. Close and open it again") + return -EIO; + } + + PDBGG("mmapping %lu bytes...", vsize) + + if (vsize > psize - (vma->vm_pgoff << PAGE_SHIFT)) + return -EINVAL; + + while (vsize > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page + vma->vm_pgoff, + PAGE_SIZE, vma->vm_page_prot)) + return -EAGAIN; + start += PAGE_SIZE; + pos += PAGE_SIZE; + vsize -= PAGE_SIZE; + } + + DBG(5, "mmap method successfully called") + return 0; +} + + +static int +w9968cf_ioctl(struct inode* inode, struct file* filp, + unsigned int cmd, unsigned long arg) +{ + struct w9968cf_device* cam; + int err; + + cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->disconnected) { + DBG(2, "Device not present") + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->misconfigured) { + DBG(2, "The camera is misconfigured. Close and open it again.") + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + err = w9968cf_v4l_ioctl(inode, filp, cmd, (void __user *)arg); + + mutex_unlock(&cam->fileop_mutex); + return err; +} + + +static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, + unsigned int cmd, void __user * arg) +{ + struct w9968cf_device* cam; + const char* v4l1_ioctls[] = { + "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", + "GPICT", "SPICT", "CCAPTURE", "GWIN", "SWIN", "GFBUF", + "SFBUF", "KEY", "GFREQ", "SFREQ", "GAUDIO", "SAUDIO", + "SYNC", "MCAPTURE", "GMBUF", "GUNIT", "GCAPTURE", "SCAPTURE", + "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", "SMICROCODE", + "GVBIFMT", "SVBIFMT" + }; + + #define V4L1_IOCTL(cmd) \ + ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \ + v4l1_ioctls[_IOC_NR((cmd))] : "?") + + cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); + + switch (cmd) { + + case VIDIOCGCAP: /* get video capability */ + { + struct video_capability cap = { + .type = VID_TYPE_CAPTURE | VID_TYPE_SCALES, + .channels = 1, + .audios = 0, + .minwidth = cam->minwidth, + .minheight = cam->minheight, + }; + sprintf(cap.name, "W996[87]CF USB Camera #%d", + cam->v4ldev->minor); + cap.maxwidth = (cam->upscaling && w9968cf_vpp) + ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) + : cam->maxwidth; + cap.maxheight = (cam->upscaling && w9968cf_vpp) + ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) + : cam->maxheight; + + if (copy_to_user(arg, &cap, sizeof(cap))) + return -EFAULT; + + DBG(5, "VIDIOCGCAP successfully called") + return 0; + } + + case VIDIOCGCHAN: /* get video channel informations */ + { + struct video_channel chan; + if (copy_from_user(&chan, arg, sizeof(chan))) + return -EFAULT; + + if (chan.channel != 0) + return -EINVAL; + + strcpy(chan.name, "Camera"); + chan.tuners = 0; + chan.flags = 0; + chan.type = VIDEO_TYPE_CAMERA; + chan.norm = VIDEO_MODE_AUTO; + + if (copy_to_user(arg, &chan, sizeof(chan))) + return -EFAULT; + + DBG(5, "VIDIOCGCHAN successfully called") + return 0; + } + + case VIDIOCSCHAN: /* set active channel */ + { + struct video_channel chan; + + if (copy_from_user(&chan, arg, sizeof(chan))) + return -EFAULT; + + if (chan.channel != 0) + return -EINVAL; + + DBG(5, "VIDIOCSCHAN successfully called") + return 0; + } + + case VIDIOCGPICT: /* get image properties of the picture */ + { + if (w9968cf_sensor_get_picture(cam)) + return -EIO; + + if (copy_to_user(arg, &cam->picture, sizeof(cam->picture))) + return -EFAULT; + + DBG(5, "VIDIOCGPICT successfully called") + return 0; + } + + case VIDIOCSPICT: /* change picture settings */ + { + struct video_picture pict; + int err = 0; + + if (copy_from_user(&pict, arg, sizeof(pict))) + return -EFAULT; + + if ( (cam->force_palette || !w9968cf_vpp) + && pict.palette != cam->picture.palette ) { + DBG(4, "Palette %s rejected: only %s is allowed", + symbolic(v4l1_plist, pict.palette), + symbolic(v4l1_plist, cam->picture.palette)) + return -EINVAL; + } + + if (!w9968cf_valid_palette(pict.palette)) { + DBG(4, "Palette %s not supported. VIDIOCSPICT failed", + symbolic(v4l1_plist, pict.palette)) + return -EINVAL; + } + + if (!cam->force_palette) { + if (cam->decompression == 0) { + if (w9968cf_need_decompression(pict.palette)) { + DBG(4, "Decompression disabled: palette %s is not " + "allowed. VIDIOCSPICT failed", + symbolic(v4l1_plist, pict.palette)) + return -EINVAL; + } + } else if (cam->decompression == 1) { + if (!w9968cf_need_decompression(pict.palette)) { + DBG(4, "Decompression forced: palette %s is not " + "allowed. VIDIOCSPICT failed", + symbolic(v4l1_plist, pict.palette)) + return -EINVAL; + } + } + } + + if (pict.depth != w9968cf_valid_depth(pict.palette)) { + DBG(4, "Requested depth %u bpp is not valid for %s " + "palette: ignored and changed to %u bpp", + pict.depth, symbolic(v4l1_plist, pict.palette), + w9968cf_valid_depth(pict.palette)) + pict.depth = w9968cf_valid_depth(pict.palette); + } + + if (pict.palette != cam->picture.palette) { + if(*cam->requested_frame + || cam->frame_current->queued) { + err = wait_event_interruptible + ( cam->wait_queue, + cam->disconnected || + (!*cam->requested_frame && + !cam->frame_current->queued) ); + if (err) + return err; + if (cam->disconnected) + return -ENODEV; + } + + if (w9968cf_stop_transfer(cam)) + goto ioctl_fail; + + if (w9968cf_set_picture(cam, pict)) + goto ioctl_fail; + + if (w9968cf_start_transfer(cam)) + goto ioctl_fail; + + } else if (w9968cf_sensor_update_picture(cam, pict)) + return -EIO; + + + DBG(5, "VIDIOCSPICT successfully called") + return 0; + } + + case VIDIOCSWIN: /* set capture area */ + { + struct video_window win; + int err = 0; + + if (copy_from_user(&win, arg, sizeof(win))) + return -EFAULT; + + DBG(6, "VIDIOCSWIN called: clipcount=%d, flags=%u, " + "x=%u, y=%u, %ux%u", win.clipcount, win.flags, + win.x, win.y, win.width, win.height) + + if (win.clipcount != 0 || win.flags != 0) + return -EINVAL; + + if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, + (u16*)&win.height))) { + DBG(4, "Resolution not supported (%ux%u). " + "VIDIOCSWIN failed", win.width, win.height) + return err; + } + + if (win.x != cam->window.x || + win.y != cam->window.y || + win.width != cam->window.width || + win.height != cam->window.height) { + if(*cam->requested_frame + || cam->frame_current->queued) { + err = wait_event_interruptible + ( cam->wait_queue, + cam->disconnected || + (!*cam->requested_frame && + !cam->frame_current->queued) ); + if (err) + return err; + if (cam->disconnected) + return -ENODEV; + } + + if (w9968cf_stop_transfer(cam)) + goto ioctl_fail; + + /* This _must_ be called before set_window() */ + if (w9968cf_set_picture(cam, cam->picture)) + goto ioctl_fail; + + if (w9968cf_set_window(cam, win)) + goto ioctl_fail; + + if (w9968cf_start_transfer(cam)) + goto ioctl_fail; + } + + DBG(5, "VIDIOCSWIN successfully called. ") + return 0; + } + + case VIDIOCGWIN: /* get current window properties */ + { + if (copy_to_user(arg,&cam->window,sizeof(struct video_window))) + return -EFAULT; + + DBG(5, "VIDIOCGWIN successfully called") + return 0; + } + + case VIDIOCGMBUF: /* request for memory (mapped) buffer */ + { + struct video_mbuf mbuf; + u8 i; + + mbuf.size = cam->nbuffers * cam->frame[0].size; + mbuf.frames = cam->nbuffers; + for (i = 0; i < cam->nbuffers; i++) + mbuf.offsets[i] = (unsigned long)cam->frame[i].buffer - + (unsigned long)cam->frame[0].buffer; + + if (copy_to_user(arg, &mbuf, sizeof(mbuf))) + return -EFAULT; + + DBG(5, "VIDIOCGMBUF successfully called") + return 0; + } + + case VIDIOCMCAPTURE: /* start the capture to a frame */ + { + struct video_mmap mmap; + struct w9968cf_frame_t* fr; + int err = 0; + + if (copy_from_user(&mmap, arg, sizeof(mmap))) + return -EFAULT; + + DBG(6, "VIDIOCMCAPTURE called: frame #%u, format=%s, %dx%d", + mmap.frame, symbolic(v4l1_plist, mmap.format), + mmap.width, mmap.height) + + if (mmap.frame >= cam->nbuffers) { + DBG(4, "Invalid frame number (%u). " + "VIDIOCMCAPTURE failed", mmap.frame) + return -EINVAL; + } + + if (mmap.format!=cam->picture.palette && + (cam->force_palette || !w9968cf_vpp)) { + DBG(4, "Palette %s rejected: only %s is allowed", + symbolic(v4l1_plist, mmap.format), + symbolic(v4l1_plist, cam->picture.palette)) + return -EINVAL; + } + + if (!w9968cf_valid_palette(mmap.format)) { + DBG(4, "Palette %s not supported. " + "VIDIOCMCAPTURE failed", + symbolic(v4l1_plist, mmap.format)) + return -EINVAL; + } + + if (!cam->force_palette) { + if (cam->decompression == 0) { + if (w9968cf_need_decompression(mmap.format)) { + DBG(4, "Decompression disabled: palette %s is not " + "allowed. VIDIOCSPICT failed", + symbolic(v4l1_plist, mmap.format)) + return -EINVAL; + } + } else if (cam->decompression == 1) { + if (!w9968cf_need_decompression(mmap.format)) { + DBG(4, "Decompression forced: palette %s is not " + "allowed. VIDIOCSPICT failed", + symbolic(v4l1_plist, mmap.format)) + return -EINVAL; + } + } + } + + if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width, + (u16*)&mmap.height))) { + DBG(4, "Resolution not supported (%dx%d). " + "VIDIOCMCAPTURE failed", + mmap.width, mmap.height) + return err; + } + + fr = &cam->frame[mmap.frame]; + + if (mmap.width != cam->window.width || + mmap.height != cam->window.height || + mmap.format != cam->picture.palette) { + + struct video_window win; + struct video_picture pict; + + if(*cam->requested_frame + || cam->frame_current->queued) { + DBG(6, "VIDIOCMCAPTURE. Change settings for " + "frame #%u: %dx%d, format %s. Wait...", + mmap.frame, mmap.width, mmap.height, + symbolic(v4l1_plist, mmap.format)) + err = wait_event_interruptible + ( cam->wait_queue, + cam->disconnected || + (!*cam->requested_frame && + !cam->frame_current->queued) ); + if (err) + return err; + if (cam->disconnected) + return -ENODEV; + } + + memcpy(&win, &cam->window, sizeof(win)); + memcpy(&pict, &cam->picture, sizeof(pict)); + win.width = mmap.width; + win.height = mmap.height; + pict.palette = mmap.format; + + if (w9968cf_stop_transfer(cam)) + goto ioctl_fail; + + /* This before set_window */ + if (w9968cf_set_picture(cam, pict)) + goto ioctl_fail; + + if (w9968cf_set_window(cam, win)) + goto ioctl_fail; + + if (w9968cf_start_transfer(cam)) + goto ioctl_fail; + + } else if (fr->queued) { + + DBG(6, "Wait until frame #%u is free", mmap.frame) + + err = wait_event_interruptible(cam->wait_queue, + cam->disconnected || + (!fr->queued)); + if (err) + return err; + if (cam->disconnected) + return -ENODEV; + } + + w9968cf_push_frame(cam, mmap.frame); + DBG(5, "VIDIOCMCAPTURE(%u): successfully called", mmap.frame) + return 0; + } + + case VIDIOCSYNC: /* wait until the capture of a frame is finished */ + { + unsigned int f_num; + struct w9968cf_frame_t* fr; + int err = 0; + + if (copy_from_user(&f_num, arg, sizeof(f_num))) + return -EFAULT; + + if (f_num >= cam->nbuffers) { + DBG(4, "Invalid frame number (%u). " + "VIDIOCMCAPTURE failed", f_num) + return -EINVAL; + } + + DBG(6, "VIDIOCSYNC called for frame #%u", f_num) + + fr = &cam->frame[f_num]; + + switch (fr->status) { + case F_UNUSED: + if (!fr->queued) { + DBG(4, "VIDIOSYNC: Frame #%u not requested!", + f_num) + return -EFAULT; + } + case F_ERROR: + case F_GRABBING: + err = wait_event_interruptible(cam->wait_queue, + (fr->status == F_READY) + || cam->disconnected); + if (err) + return err; + if (cam->disconnected) + return -ENODEV; + break; + case F_READY: + break; + } + + if (w9968cf_vpp) + w9968cf_postprocess_frame(cam, fr); + + fr->status = F_UNUSED; + + DBG(5, "VIDIOCSYNC(%u) successfully called", f_num) + return 0; + } + + case VIDIOCGUNIT:/* report the unit numbers of the associated devices*/ + { + struct video_unit unit = { + .video = cam->v4ldev->minor, + .vbi = VIDEO_NO_UNIT, + .radio = VIDEO_NO_UNIT, + .audio = VIDEO_NO_UNIT, + .teletext = VIDEO_NO_UNIT, + }; + + if (copy_to_user(arg, &unit, sizeof(unit))) + return -EFAULT; + + DBG(5, "VIDIOCGUNIT successfully called") + return 0; + } + + case VIDIOCKEY: + return 0; + + case VIDIOCGFBUF: + { + if (clear_user(arg, sizeof(struct video_buffer))) + return -EFAULT; + + DBG(5, "VIDIOCGFBUF successfully called") + return 0; + } + + case VIDIOCGTUNER: + { + struct video_tuner tuner; + if (copy_from_user(&tuner, arg, sizeof(tuner))) + return -EFAULT; + + if (tuner.tuner != 0) + return -EINVAL; + + strcpy(tuner.name, "no_tuner"); + tuner.rangelow = 0; + tuner.rangehigh = 0; + tuner.flags = VIDEO_TUNER_NORM; + tuner.mode = VIDEO_MODE_AUTO; + tuner.signal = 0xffff; + + if (copy_to_user(arg, &tuner, sizeof(tuner))) + return -EFAULT; + + DBG(5, "VIDIOCGTUNER successfully called") + return 0; + } + + case VIDIOCSTUNER: + { + struct video_tuner tuner; + if (copy_from_user(&tuner, arg, sizeof(tuner))) + return -EFAULT; + + if (tuner.tuner != 0) + return -EINVAL; + + if (tuner.mode != VIDEO_MODE_AUTO) + return -EINVAL; + + DBG(5, "VIDIOCSTUNER successfully called") + return 0; + } + + case VIDIOCSFBUF: + case VIDIOCCAPTURE: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + case VIDIOCSPLAYMODE: + case VIDIOCSWRITEMODE: + case VIDIOCGPLAYINFO: + case VIDIOCSMICROCODE: + case VIDIOCGVBIFMT: + case VIDIOCSVBIFMT: + DBG(4, "Unsupported V4L1 IOCtl: VIDIOC%s " + "(type 0x%01X, " + "n. 0x%01X, " + "dir. 0x%01X, " + "size 0x%02X)", + V4L1_IOCTL(cmd), + _IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd)) + + return -EINVAL; + + default: + DBG(4, "Invalid V4L1 IOCtl: VIDIOC%s " + "type 0x%01X, " + "n. 0x%01X, " + "dir. 0x%01X, " + "size 0x%02X", + V4L1_IOCTL(cmd), + _IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd)) + + return -ENOIOCTLCMD; + + } /* end of switch */ + +ioctl_fail: + cam->misconfigured = 1; + DBG(1, "VIDIOC%s failed because of hardware problems. " + "To use the camera, close and open it again.", V4L1_IOCTL(cmd)) + return -EFAULT; +} + + +static struct file_operations w9968cf_fops = { + .owner = THIS_MODULE, + .open = w9968cf_open, + .release = w9968cf_release, + .read = w9968cf_read, + .ioctl = w9968cf_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .mmap = w9968cf_mmap, + .llseek = no_llseek, +}; + + + +/**************************************************************************** + * USB probe and V4L registration, disconnect and id_table[] definition * + ****************************************************************************/ + +static int +w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct w9968cf_device* cam; + int err = 0; + enum w9968cf_model_id mod_id; + struct list_head* ptr; + u8 sc = 0; /* number of simultaneous cameras */ + static unsigned short dev_nr = 0; /* we are handling device number n */ + + if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor && + le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct) + mod_id = W9968CF_MOD_CLVBWGP; /* see camlist[] table */ + else if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[1].idVendor && + le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[1].idProduct) + mod_id = W9968CF_MOD_GENERIC; /* see camlist[] table */ + else + return -ENODEV; + + cam = (struct w9968cf_device*) + kzalloc(sizeof(struct w9968cf_device), GFP_KERNEL); + if (!cam) + return -ENOMEM; + + mutex_init(&cam->dev_mutex); + mutex_lock(&cam->dev_mutex); + + cam->usbdev = udev; + /* NOTE: a local copy is used to avoid possible race conditions */ + memcpy(&cam->dev, &udev->dev, sizeof(struct device)); + + DBG(2, "%s detected", symbolic(camlist, mod_id)) + + if (simcams > W9968CF_MAX_DEVICES) + simcams = W9968CF_SIMCAMS; + + /* How many cameras are connected ? */ + mutex_lock(&w9968cf_devlist_mutex); + list_for_each(ptr, &w9968cf_dev_list) + sc++; + mutex_unlock(&w9968cf_devlist_mutex); + + if (sc >= simcams) { + DBG(2, "Device rejected: too many connected cameras " + "(max. %u)", simcams) + err = -EPERM; + goto fail; + } + + + /* Allocate 2 bytes of memory for camera control USB transfers */ + if (!(cam->control_buffer = kzalloc(2, GFP_KERNEL))) { + DBG(1,"Couldn't allocate memory for camera control transfers") + err = -ENOMEM; + goto fail; + } + + /* Allocate 8 bytes of memory for USB data transfers to the FSB */ + if (!(cam->data_buffer = kzalloc(8, GFP_KERNEL))) { + DBG(1, "Couldn't allocate memory for data " + "transfers to the FSB") + err = -ENOMEM; + goto fail; + } + + /* Register the V4L device */ + cam->v4ldev = video_device_alloc(); + if (!cam->v4ldev) { + DBG(1, "Could not allocate memory for a V4L structure") + err = -ENOMEM; + goto fail; + } + + strcpy(cam->v4ldev->name, symbolic(camlist, mod_id)); + cam->v4ldev->owner = THIS_MODULE; + cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; + cam->v4ldev->hardware = VID_HARDWARE_W9968CF; + cam->v4ldev->fops = &w9968cf_fops; + cam->v4ldev->minor = video_nr[dev_nr]; + cam->v4ldev->release = video_device_release; + video_set_drvdata(cam->v4ldev, cam); + cam->v4ldev->dev = &cam->dev; + + err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, + video_nr[dev_nr]); + if (err) { + DBG(1, "V4L device registration failed") + if (err == -ENFILE && video_nr[dev_nr] == -1) + DBG(2, "Couldn't find a free /dev/videoX node") + video_nr[dev_nr] = -1; + dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0; + goto fail; + } + + DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->minor) + + /* Set some basic constants */ + w9968cf_configure_camera(cam, udev, mod_id, dev_nr); + + /* Add a new entry into the list of V4L registered devices */ + mutex_lock(&w9968cf_devlist_mutex); + list_add(&cam->v4llist, &w9968cf_dev_list); + mutex_unlock(&w9968cf_devlist_mutex); + dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0; + + w9968cf_turn_on_led(cam); + + w9968cf_i2c_init(cam); + + usb_set_intfdata(intf, cam); + mutex_unlock(&cam->dev_mutex); + return 0; + +fail: /* Free unused memory */ + kfree(cam->control_buffer); + kfree(cam->data_buffer); + if (cam->v4ldev) + video_device_release(cam->v4ldev); + mutex_unlock(&cam->dev_mutex); + kfree(cam); + return err; +} + + +static void w9968cf_usb_disconnect(struct usb_interface* intf) +{ + struct w9968cf_device* cam = + (struct w9968cf_device*)usb_get_intfdata(intf); + + down_write(&w9968cf_disconnect); + + if (cam) { + /* Prevent concurrent accesses to data */ + mutex_lock(&cam->dev_mutex); + + cam->disconnected = 1; + + DBG(2, "Disconnecting %s...", symbolic(camlist, cam->id)) + + wake_up_interruptible_all(&cam->open); + + if (cam->users) { + DBG(2, "The device is open (/dev/video%d)! " + "Process name: %s. Deregistration and memory " + "deallocation are deferred on close.", + cam->v4ldev->minor, cam->command) + cam->misconfigured = 1; + w9968cf_stop_transfer(cam); + wake_up_interruptible(&cam->wait_queue); + } else + w9968cf_release_resources(cam); + + mutex_unlock(&cam->dev_mutex); + + if (!cam->users) + kfree(cam); + } + + up_write(&w9968cf_disconnect); +} + + +static struct usb_driver w9968cf_usb_driver = { + .name = "w9968cf", + .id_table = winbond_id_table, + .probe = w9968cf_usb_probe, + .disconnect = w9968cf_usb_disconnect, +}; + + + +/**************************************************************************** + * Module init, exit and intermodule communication * + ****************************************************************************/ + +static int __init w9968cf_module_init(void) +{ + int err; + + KDBG(2, W9968CF_MODULE_NAME" "W9968CF_MODULE_VERSION) + KDBG(3, W9968CF_MODULE_AUTHOR) + + if (ovmod_load) + request_module("ovcamchip"); + + if ((err = usb_register(&w9968cf_usb_driver))) + return err; + + return 0; +} + + +static void __exit w9968cf_module_exit(void) +{ + /* w9968cf_usb_disconnect() will be called */ + usb_deregister(&w9968cf_usb_driver); + + KDBG(2, W9968CF_MODULE_NAME" deregistered") +} + + +module_init(w9968cf_module_init); +module_exit(w9968cf_module_exit); + diff --git a/drivers/media/video/w9968cf.h b/drivers/media/video/w9968cf.h new file mode 100644 index 000000000000..a87be719a281 --- /dev/null +++ b/drivers/media/video/w9968cf.h @@ -0,0 +1,330 @@ +/*************************************************************************** + * Video4Linux driver for W996[87]CF JPEG USB Dual Mode Camera Chip. * + * * + * Copyright (C) 2002-2004 by Luca Risolia * + * * + * 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. * + ***************************************************************************/ + +#ifndef _W9968CF_H_ +#define _W9968CF_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "w9968cf_vpp.h" + + +/**************************************************************************** + * Default values * + ****************************************************************************/ + +#define W9968CF_OVMOD_LOAD 1 /* automatic 'ovcamchip' module loading */ +#define W9968CF_VPPMOD_LOAD 1 /* automatic 'w9968cf-vpp' module loading */ + +/* Comment/uncomment the following line to enable/disable debugging messages */ +#define W9968CF_DEBUG + +/* These have effect only if W9968CF_DEBUG is defined */ +#define W9968CF_DEBUG_LEVEL 2 /* from 0 to 6. 0 for no debug informations */ +#define W9968CF_SPECIFIC_DEBUG 0 /* 0 or 1 */ + +#define W9968CF_MAX_DEVICES 32 +#define W9968CF_SIMCAMS W9968CF_MAX_DEVICES /* simultaneous cameras */ + +#define W9968CF_MAX_BUFFERS 32 +#define W9968CF_BUFFERS 2 /* n. of frame buffers from 2 to MAX_BUFFERS */ + +/* Maximum data payload sizes in bytes for alternate settings */ +static const u16 wMaxPacketSize[] = {1023, 959, 895, 831, 767, 703, 639, 575, + 511, 447, 383, 319, 255, 191, 127, 63}; +#define W9968CF_PACKET_SIZE 1023 /* according to wMaxPacketSizes[] */ +#define W9968CF_MIN_PACKET_SIZE 63 /* minimum value */ +#define W9968CF_ISO_PACKETS 5 /* n.of packets for isochronous transfers */ +#define W9968CF_USB_CTRL_TIMEOUT 1000 /* timeout (ms) for usb control commands */ +#define W9968CF_URBS 2 /* n. of scheduled URBs for ISO transfer */ + +#define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ +#define W9968CF_I2C_RW_RETRIES 15 /* number of max I2C r/w retries */ + +/* Available video formats */ +struct w9968cf_format { + const u16 palette; + const u16 depth; + const u8 compression; +}; + +static const struct w9968cf_format w9968cf_formatlist[] = { + { VIDEO_PALETTE_UYVY, 16, 0 }, /* original video */ + { VIDEO_PALETTE_YUV422P, 16, 1 }, /* with JPEG compression */ + { VIDEO_PALETTE_YUV420P, 12, 1 }, /* with JPEG compression */ + { VIDEO_PALETTE_YUV420, 12, 1 }, /* same as YUV420P */ + { VIDEO_PALETTE_YUYV, 16, 0 }, /* software conversion */ + { VIDEO_PALETTE_YUV422, 16, 0 }, /* software conversion */ + { VIDEO_PALETTE_GREY, 8, 0 }, /* software conversion */ + { VIDEO_PALETTE_RGB555, 16, 0 }, /* software conversion */ + { VIDEO_PALETTE_RGB565, 16, 0 }, /* software conversion */ + { VIDEO_PALETTE_RGB24, 24, 0 }, /* software conversion */ + { VIDEO_PALETTE_RGB32, 32, 0 }, /* software conversion */ + { 0, 0, 0 } /* 0 is a terminating entry */ +}; + +#define W9968CF_DECOMPRESSION 2 /* decomp:0=disable,1=force,2=any formats */ +#define W9968CF_PALETTE_DECOMP_OFF VIDEO_PALETTE_UYVY /* when decomp=0 */ +#define W9968CF_PALETTE_DECOMP_FORCE VIDEO_PALETTE_YUV420P /* when decomp=1 */ +#define W9968CF_PALETTE_DECOMP_ON VIDEO_PALETTE_UYVY /* when decomp=2 */ + +#define W9968CF_FORCE_RGB 0 /* read RGB instead of BGR, yes=1/no=0 */ + +#define W9968CF_MAX_WIDTH 800 /* Has effect if up-scaling is on */ +#define W9968CF_MAX_HEIGHT 600 /* Has effect if up-scaling is on */ +#define W9968CF_WIDTH 320 /* from 128 to 352, multiple of 16 */ +#define W9968CF_HEIGHT 240 /* from 96 to 288, multiple of 16 */ + +#define W9968CF_CLAMPING 0 /* 0 disable, 1 enable video data clamping */ +#define W9968CF_FILTER_TYPE 0 /* 0 disable 1 (1-2-1), 2 (2-3-6-3-2) */ +#define W9968CF_DOUBLE_BUFFER 1 /* 0 disable, 1 enable double buffer */ +#define W9968CF_LARGEVIEW 1 /* 0 disable, 1 enable */ +#define W9968CF_UPSCALING 0 /* 0 disable, 1 enable */ + +#define W9968CF_MONOCHROME 0 /* 0 not monochrome, 1 monochrome sensor */ +#define W9968CF_BRIGHTNESS 31000 /* from 0 to 65535 */ +#define W9968CF_HUE 32768 /* from 0 to 65535 */ +#define W9968CF_COLOUR 32768 /* from 0 to 65535 */ +#define W9968CF_CONTRAST 50000 /* from 0 to 65535 */ +#define W9968CF_WHITENESS 32768 /* from 0 to 65535 */ + +#define W9968CF_AUTOBRIGHT 0 /* 0 disable, 1 enable automatic brightness */ +#define W9968CF_AUTOEXP 1 /* 0 disable, 1 enable automatic exposure */ +#define W9968CF_LIGHTFREQ 50 /* light frequency. 50Hz (Europe) or 60Hz */ +#define W9968CF_BANDINGFILTER 0 /* 0 disable, 1 enable banding filter */ +#define W9968CF_BACKLIGHT 0 /* 0 or 1, 1=object is lit from behind */ +#define W9968CF_MIRROR 0 /* 0 or 1 [don't] reverse image horizontally*/ + +#define W9968CF_CLOCKDIV -1 /* -1 = automatic clock divisor */ +#define W9968CF_DEF_CLOCKDIVISOR 0 /* default sensor clock divisor value */ + + +/**************************************************************************** + * Globals * + ****************************************************************************/ + +#define W9968CF_MODULE_NAME "V4L driver for W996[87]CF JPEG USB " \ + "Dual Mode Camera Chip" +#define W9968CF_MODULE_VERSION "1:1.33-basic" +#define W9968CF_MODULE_AUTHOR "(C) 2002-2004 Luca Risolia" +#define W9968CF_AUTHOR_EMAIL "" +#define W9968CF_MODULE_LICENSE "GPL" + +static const struct usb_device_id winbond_id_table[] = { + { + /* Creative Labs Video Blaster WebCam Go Plus */ + USB_DEVICE(0x041e, 0x4003), + .driver_info = (unsigned long)"w9968cf", + }, + { + /* Generic W996[87]CF JPEG USB Dual Mode Camera */ + USB_DEVICE(0x1046, 0x9967), + .driver_info = (unsigned long)"w9968cf", + }, + { } /* terminating entry */ +}; + +/* W996[87]CF camera models, internal ids: */ +enum w9968cf_model_id { + W9968CF_MOD_GENERIC = 1, /* Generic W996[87]CF based device */ + W9968CF_MOD_CLVBWGP = 11,/*Creative Labs Video Blaster WebCam Go Plus*/ + W9968CF_MOD_ADPVDMA = 21, /* Aroma Digi Pen VGA Dual Mode ADG-5000 */ + W9986CF_MOD_AAU = 31, /* AVerMedia AVerTV USB */ + W9968CF_MOD_CLVBWG = 34, /* Creative Labs Video Blaster WebCam Go */ + W9968CF_MOD_LL = 37, /* Lebon LDC-035A */ + W9968CF_MOD_EEEMC = 40, /* Ezonics EZ-802 EZMega Cam */ + W9968CF_MOD_OOE = 42, /* OmniVision OV8610-EDE */ + W9968CF_MOD_ODPVDMPC = 43,/* OPCOM Digi Pen VGA Dual Mode Pen Camera */ + W9968CF_MOD_PDPII = 46, /* Pretec Digi Pen-II */ + W9968CF_MOD_PDP480 = 49, /* Pretec DigiPen-480 */ +}; + +enum w9968cf_frame_status { + F_READY, /* finished grabbing & ready to be read/synced */ + F_GRABBING, /* in the process of being grabbed into */ + F_ERROR, /* something bad happened while processing */ + F_UNUSED /* unused (no VIDIOCMCAPTURE) */ +}; + +struct w9968cf_frame_t { + void* buffer; + unsigned long size; + u32 length; + int number; + enum w9968cf_frame_status status; + struct w9968cf_frame_t* next; + u8 queued; +}; + +enum w9968cf_vpp_flag { + VPP_NONE = 0x00, + VPP_UPSCALE = 0x01, + VPP_SWAP_YUV_BYTES = 0x02, + VPP_DECOMPRESSION = 0x04, + VPP_UYVY_TO_RGBX = 0x08, +}; + +/* Main device driver structure */ +struct w9968cf_device { + struct device dev; /* device structure */ + + enum w9968cf_model_id id; /* private device identifier */ + + struct video_device* v4ldev; /* -> V4L structure */ + struct list_head v4llist; /* entry of the list of V4L cameras */ + + struct usb_device* usbdev; /* -> main USB structure */ + struct urb* urb[W9968CF_URBS]; /* -> USB request block structs */ + void* transfer_buffer[W9968CF_URBS]; /* -> ISO transfer buffers */ + u16* control_buffer; /* -> buffer for control req.*/ + u16* data_buffer; /* -> data to send to the FSB */ + + struct w9968cf_frame_t frame[W9968CF_MAX_BUFFERS]; + struct w9968cf_frame_t frame_tmp; /* temporary frame */ + struct w9968cf_frame_t frame_vpp; /* helper frame.*/ + struct w9968cf_frame_t* frame_current; /* -> frame being grabbed */ + struct w9968cf_frame_t* requested_frame[W9968CF_MAX_BUFFERS]; + + u8 max_buffers, /* number of requested buffers */ + force_palette, /* yes=1/no=0 */ + force_rgb, /* read RGB instead of BGR, yes=1, no=0 */ + double_buffer, /* hardware double buffering yes=1/no=0 */ + clamping, /* video data clamping yes=1/no=0 */ + filter_type, /* 0=disabled, 1=3 tap, 2=5 tap filter */ + capture, /* 0=disabled, 1=enabled */ + largeview, /* 0=disabled, 1=enabled */ + decompression, /* 0=disabled, 1=forced, 2=allowed */ + upscaling; /* software image scaling, 0=enabled, 1=disabled */ + + struct video_picture picture; /* current picture settings */ + struct video_window window; /* current window settings */ + + u16 hw_depth, /* depth (used by the chip) */ + hw_palette, /* palette (used by the chip) */ + hw_width, /* width (used by the chip) */ + hw_height, /* height (used by the chip) */ + hs_polarity, /* 0=negative sync pulse, 1=positive sync pulse */ + vs_polarity, /* 0=negative sync pulse, 1=positive sync pulse */ + start_cropx, /* pixels from HS inactive edge to 1st cropped pixel*/ + start_cropy; /* pixels from VS inactive edge to 1st cropped pixel*/ + + enum w9968cf_vpp_flag vpp_flag; /* post-processing routines in use */ + + u8 nbuffers, /* number of allocated frame buffers */ + altsetting, /* camera alternate setting */ + disconnected, /* flag: yes=1, no=0 */ + misconfigured, /* flag: yes=1, no=0 */ + users, /* flag: number of users holding the device */ + streaming; /* flag: yes=1, no=0 */ + + u8 sensor_initialized; /* flag: yes=1, no=0 */ + + /* Determined by the image sensor type: */ + int sensor, /* type of image sensor chip (CC_*) */ + monochrome; /* image sensor is (probably) monochrome */ + u16 maxwidth, /* maximum width supported by the image sensor */ + maxheight, /* maximum height supported by the image sensor */ + minwidth, /* minimum width supported by the image sensor */ + minheight; /* minimum height supported by the image sensor */ + u8 auto_brt, /* auto brightness enabled flag */ + auto_exp, /* auto exposure enabled flag */ + backlight, /* backlight exposure algorithm flag */ + mirror, /* image is reversed horizontally */ + lightfreq, /* power (lighting) frequency */ + bandfilt; /* banding filter enabled flag */ + s8 clockdiv; /* clock divisor */ + + /* I2C interface to kernel */ + struct i2c_adapter i2c_adapter; + struct i2c_client* sensor_client; + + /* Locks */ + struct mutex dev_mutex, /* for probe, disconnect,open and close */ + fileop_mutex; /* for read and ioctl */ + spinlock_t urb_lock, /* for submit_urb() and unlink_urb() */ + flist_lock; /* for requested frame list accesses */ + wait_queue_head_t open, wait_queue; + + char command[16]; /* name of the program holding the device */ +}; + + +/**************************************************************************** + * Macros for debugging * + ****************************************************************************/ + +#undef DBG +#undef KDBG +#ifdef W9968CF_DEBUG +/* For device specific debugging messages */ +# define DBG(level, fmt, args...) \ +{ \ + if ( ((specific_debug) && (debug == (level))) || \ + ((!specific_debug) && (debug >= (level))) ) { \ + if ((level) == 1) \ + dev_err(&cam->dev, fmt "\n", ## args); \ + else if ((level) == 2 || (level) == 3) \ + dev_info(&cam->dev, fmt "\n", ## args); \ + else if ((level) == 4) \ + dev_warn(&cam->dev, fmt "\n", ## args); \ + else if ((level) >= 5) \ + dev_info(&cam->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args); \ + } \ +} +/* For generic kernel (not device specific) messages */ +# define KDBG(level, fmt, args...) \ +{ \ + if ( ((specific_debug) && (debug == (level))) || \ + ((!specific_debug) && (debug >= (level))) ) { \ + if ((level) >= 1 && (level) <= 4) \ + pr_info("w9968cf: " fmt "\n", ## args); \ + else if ((level) >= 5) \ + pr_debug("w9968cf: [%s:%d] " fmt "\n", __FUNCTION__, \ + __LINE__ , ## args); \ + } \ +} +#else + /* Not debugging: nothing */ +# define DBG(level, fmt, args...) do {;} while(0); +# define KDBG(level, fmt, args...) do {;} while(0); +#endif + +#undef PDBG +#define PDBG(fmt, args...) \ +dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args); + +#undef PDBGG +#define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */ + +#endif /* _W9968CF_H_ */ diff --git a/drivers/media/video/w9968cf_decoder.h b/drivers/media/video/w9968cf_decoder.h new file mode 100644 index 000000000000..31faccbe8f03 --- /dev/null +++ b/drivers/media/video/w9968cf_decoder.h @@ -0,0 +1,86 @@ +/*************************************************************************** + * Video decoder for the W996[87]CF driver for Linux. * + * * + * Copyright (C) 2003 2004 by Luca Risolia * + * * + * 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. * + ***************************************************************************/ + +#ifndef _W9968CF_DECODER_H_ +#define _W9968CF_DECODER_H_ + +/* Comment/uncomment this for high/low quality of compressed video */ +#define W9968CF_DEC_FAST_LOWQUALITY_VIDEO + +#ifdef W9968CF_DEC_FAST_LOWQUALITY_VIDEO +static const unsigned char Y_QUANTABLE[64] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; + +static const unsigned char UV_QUANTABLE[64] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; +#else +static const unsigned char Y_QUANTABLE[64] = { + 8, 5, 5, 8, 12, 20, 25, 30, + 6, 6, 7, 9, 13, 29, 30, 27, + 7, 6, 8, 12, 20, 28, 34, 28, + 7, 8, 11, 14, 25, 43, 40, 31, + 9, 11, 18, 28, 34, 54, 51, 38, + 12, 17, 27, 32, 40, 52, 56, 46, + 24, 32, 39, 43, 51, 60, 60, 50, + 36, 46, 47, 49, 56, 50, 51, 49 +}; + +static const unsigned char UV_QUANTABLE[64] = { + 8, 9, 12, 23, 49, 49, 49, 49, + 9, 10, 13, 33, 49, 49, 49, 49, + 12, 13, 28, 49, 49, 49, 49, 49, + 23, 33, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49 +}; +#endif + +#define W9968CF_DEC_ERR_CORRUPTED_DATA -1 +#define W9968CF_DEC_ERR_BUF_OVERFLOW -2 +#define W9968CF_DEC_ERR_NO_SOI -3 +#define W9968CF_DEC_ERR_NO_SOF0 -4 +#define W9968CF_DEC_ERR_NO_SOS -5 +#define W9968CF_DEC_ERR_NO_EOI -6 + +extern void w9968cf_init_decoder(void); +extern int w9968cf_check_headers(const unsigned char* Pin, + const unsigned long BUF_SIZE); +extern int w9968cf_decode(const char* Pin, const unsigned long BUF_SIZE, + const unsigned W, const unsigned H, char* Pout); + +#endif /* _W9968CF_DECODER_H_ */ diff --git a/drivers/media/video/w9968cf_vpp.h b/drivers/media/video/w9968cf_vpp.h new file mode 100644 index 000000000000..f3b91b782671 --- /dev/null +++ b/drivers/media/video/w9968cf_vpp.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Interface for video post-processing functions for the W996[87]CF driver * + * for Linux. * + * * + * Copyright (C) 2002-2004 by Luca Risolia * + * * + * 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. * + ***************************************************************************/ + +#ifndef _W9968CF_VPP_H_ +#define _W9968CF_VPP_H_ + +#include +#include + +struct w9968cf_vpp_t { + struct module* owner; + int (*check_headers)(const unsigned char*, const unsigned long); + int (*decode)(const char*, const unsigned long, const unsigned, + const unsigned, char*); + void (*swap_yuvbytes)(void*, unsigned long); + void (*uyvy_to_rgbx)(u8*, unsigned long, u8*, u16, u8); + void (*scale_up)(u8*, u8*, u16, u16, u16, u16, u16); + + u8 busy; /* read-only flag: module is/is not in use */ +}; + +#endif /* _W9968CF_VPP_H_ */ diff --git a/drivers/media/video/zc0301/Makefile b/drivers/media/video/zc0301/Makefile new file mode 100644 index 000000000000..d749199d8f06 --- /dev/null +++ b/drivers/media/video/zc0301/Makefile @@ -0,0 +1,3 @@ +zc0301-objs := zc0301_core.o zc0301_pas202bcb.o + +obj-$(CONFIG_USB_ZC0301) += zc0301.o diff --git a/drivers/media/video/zc0301/zc0301.h b/drivers/media/video/zc0301/zc0301.h new file mode 100644 index 000000000000..8e0655140e60 --- /dev/null +++ b/drivers/media/video/zc0301/zc0301.h @@ -0,0 +1,192 @@ +/*************************************************************************** + * V4L2 driver for ZC0301 Image Processor and Control Chip * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * 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. * + ***************************************************************************/ + +#ifndef _ZC0301_H_ +#define _ZC0301_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zc0301_sensor.h" + +/*****************************************************************************/ + +#define ZC0301_DEBUG +#define ZC0301_DEBUG_LEVEL 2 +#define ZC0301_MAX_DEVICES 64 +#define ZC0301_FORCE_MUNMAP 0 +#define ZC0301_MAX_FRAMES 32 +#define ZC0301_COMPRESSION_QUALITY 0 +#define ZC0301_URBS 2 +#define ZC0301_ISO_PACKETS 7 +#define ZC0301_ALTERNATE_SETTING 7 +#define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS) +#define ZC0301_CTRL_TIMEOUT 100 +#define ZC0301_FRAME_TIMEOUT 2 + +/*****************************************************************************/ + +ZC0301_ID_TABLE +ZC0301_SENSOR_TABLE + +enum zc0301_frame_state { + F_UNUSED, + F_QUEUED, + F_GRABBING, + F_DONE, + F_ERROR, +}; + +struct zc0301_frame_t { + void* bufmem; + struct v4l2_buffer buf; + enum zc0301_frame_state state; + struct list_head frame; + unsigned long vma_use_count; +}; + +enum zc0301_dev_state { + DEV_INITIALIZED = 0x01, + DEV_DISCONNECTED = 0x02, + DEV_MISCONFIGURED = 0x04, +}; + +enum zc0301_io_method { + IO_NONE, + IO_READ, + IO_MMAP, +}; + +enum zc0301_stream_state { + STREAM_OFF, + STREAM_INTERRUPT, + STREAM_ON, +}; + +struct zc0301_module_param { + u8 force_munmap; + u16 frame_timeout; +}; + +static DECLARE_RWSEM(zc0301_disconnect); + +struct zc0301_device { + struct video_device* v4ldev; + + struct zc0301_sensor sensor; + + struct usb_device* usbdev; + struct urb* urb[ZC0301_URBS]; + void* transfer_buffer[ZC0301_URBS]; + u8* control_buffer; + + struct zc0301_frame_t *frame_current, frame[ZC0301_MAX_FRAMES]; + struct list_head inqueue, outqueue; + u32 frame_count, nbuffers, nreadbuffers; + + enum zc0301_io_method io; + enum zc0301_stream_state stream; + + struct v4l2_jpegcompression compression; + + struct zc0301_module_param module_param; + + enum zc0301_dev_state state; + u8 users; + + struct mutex dev_mutex, fileop_mutex; + spinlock_t queue_lock; + wait_queue_head_t open, wait_frame, wait_stream; +}; + +/*****************************************************************************/ + +struct zc0301_device* +zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id) +{ + return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; +} + +void +zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor) +{ + memcpy(&cam->sensor, sensor, sizeof(struct zc0301_sensor)); +} + +/*****************************************************************************/ + +#undef DBG +#undef KDBG +#ifdef ZC0301_DEBUG +# define DBG(level, fmt, args...) \ +do { \ + if (debug >= (level)) { \ + if ((level) == 1) \ + dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ + else if ((level) == 2) \ + dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ + else if ((level) >= 3) \ + dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args); \ + } \ +} while (0) +# define KDBG(level, fmt, args...) \ +do { \ + if (debug >= (level)) { \ + if ((level) == 1 || (level) == 2) \ + pr_info("zc0301: " fmt "\n", ## args); \ + else if ((level) == 3) \ + pr_debug("zc0301: [%s:%d] " fmt "\n", __FUNCTION__, \ + __LINE__ , ## args); \ + } \ +} while (0) +# define V4LDBG(level, name, cmd) \ +do { \ + if (debug >= (level)) \ + v4l_print_ioctl(name, cmd); \ +} while (0) +#else +# define DBG(level, fmt, args...) do {;} while(0) +# define KDBG(level, fmt, args...) do {;} while(0) +# define V4LDBG(level, name, cmd) do {;} while(0) +#endif + +#undef PDBG +#define PDBG(fmt, args...) \ +dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ + __FUNCTION__, __LINE__ , ## args) + +#undef PDBGG +#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ + +#endif /* _ZC0301_H_ */ diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c new file mode 100644 index 000000000000..4036c6268bff --- /dev/null +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -0,0 +1,2055 @@ +/*************************************************************************** + * Video4Linux2 driver for ZC0301 Image Processor and Control Chip * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * Informations about the chip internals needed to enable the I2C protocol * + * have been taken from the documentation of the ZC030x Video4Linux1 * + * driver written by Andrew Birkett * + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zc0301.h" + +/*****************************************************************************/ + +#define ZC0301_MODULE_NAME "V4L2 driver for ZC0301 " \ + "Image Processor and Control Chip" +#define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" +#define ZC0301_AUTHOR_EMAIL "" +#define ZC0301_MODULE_LICENSE "GPL" +#define ZC0301_MODULE_VERSION "1:1.03" +#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 3) + +/*****************************************************************************/ + +MODULE_DEVICE_TABLE(usb, zc0301_id_table); + +MODULE_AUTHOR(ZC0301_MODULE_AUTHOR " " ZC0301_AUTHOR_EMAIL); +MODULE_DESCRIPTION(ZC0301_MODULE_NAME); +MODULE_VERSION(ZC0301_MODULE_VERSION); +MODULE_LICENSE(ZC0301_MODULE_LICENSE); + +static short video_nr[] = {[0 ... ZC0301_MAX_DEVICES-1] = -1}; +module_param_array(video_nr, short, NULL, 0444); +MODULE_PARM_DESC(video_nr, + "\n<-1|n[,...]> Specify V4L2 minor mode number." + "\n -1 = use next available (default)" + "\n n = use minor number n (integer >= 0)" + "\nYou can specify up to " + __MODULE_STRING(ZC0301_MAX_DEVICES) " cameras this way." + "\nFor example:" + "\nvideo_nr=-1,2,-1 would assign minor number 2 to" + "\nthe second registered camera and use auto for the first" + "\none and for every other camera." + "\n"); + +static short force_munmap[] = {[0 ... ZC0301_MAX_DEVICES-1] = + ZC0301_FORCE_MUNMAP}; +module_param_array(force_munmap, bool, NULL, 0444); +MODULE_PARM_DESC(force_munmap, + "\n<0|1[,...]> Force the application to unmap previously" + "\nmapped buffer memory before calling any VIDIOC_S_CROP or" + "\nVIDIOC_S_FMT ioctl's. Not all the applications support" + "\nthis feature. This parameter is specific for each" + "\ndetected camera." + "\n 0 = do not force memory unmapping" + "\n 1 = force memory unmapping (save memory)" + "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." + "\n"); + +static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] = + ZC0301_FRAME_TIMEOUT}; +module_param_array(frame_timeout, uint, NULL, 0644); +MODULE_PARM_DESC(frame_timeout, + "\n Timeout for a video frame in seconds." + "\nThis parameter is specific for each detected camera." + "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"." + "\n"); + +#ifdef ZC0301_DEBUG +static unsigned short debug = ZC0301_DEBUG_LEVEL; +module_param(debug, ushort, 0644); +MODULE_PARM_DESC(debug, + "\n Debugging information level, from 0 to 3:" + "\n0 = none (use carefully)" + "\n1 = critical errors" + "\n2 = significant informations" + "\n3 = more verbose messages" + "\nLevel 3 is useful for testing only, when only " + "one device is used." + "\nDefault value is "__MODULE_STRING(ZC0301_DEBUG_LEVEL)"." + "\n"); +#endif + +/*****************************************************************************/ + +static u32 +zc0301_request_buffers(struct zc0301_device* cam, u32 count, + enum zc0301_io_method io) +{ + struct v4l2_pix_format* p = &(cam->sensor.pix_format); + struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); + const size_t imagesize = cam->module_param.force_munmap || + io == IO_READ ? + (p->width * p->height * p->priv) / 8 : + (r->width * r->height * p->priv) / 8; + void* buff = NULL; + u32 i; + + if (count > ZC0301_MAX_FRAMES) + count = ZC0301_MAX_FRAMES; + + cam->nbuffers = count; + while (cam->nbuffers > 0) { + if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) + break; + cam->nbuffers--; + } + + for (i = 0; i < cam->nbuffers; i++) { + cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); + cam->frame[i].buf.index = i; + cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); + cam->frame[i].buf.length = imagesize; + cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cam->frame[i].buf.sequence = 0; + cam->frame[i].buf.field = V4L2_FIELD_NONE; + cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; + cam->frame[i].buf.flags = 0; + } + + return cam->nbuffers; +} + + +static void zc0301_release_buffers(struct zc0301_device* cam) +{ + if (cam->nbuffers) { + vfree(cam->frame[0].bufmem); + cam->nbuffers = 0; + } + cam->frame_current = NULL; +} + + +static void zc0301_empty_framequeues(struct zc0301_device* cam) +{ + u32 i; + + INIT_LIST_HEAD(&cam->inqueue); + INIT_LIST_HEAD(&cam->outqueue); + + for (i = 0; i < ZC0301_MAX_FRAMES; i++) { + cam->frame[i].state = F_UNUSED; + cam->frame[i].buf.bytesused = 0; + } +} + + +static void zc0301_requeue_outqueue(struct zc0301_device* cam) +{ + struct zc0301_frame_t *i; + + list_for_each_entry(i, &cam->outqueue, frame) { + i->state = F_QUEUED; + list_add(&i->frame, &cam->inqueue); + } + + INIT_LIST_HEAD(&cam->outqueue); +} + + +static void zc0301_queue_unusedframes(struct zc0301_device* cam) +{ + unsigned long lock_flags; + u32 i; + + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].state == F_UNUSED) { + cam->frame[i].state = F_QUEUED; + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_add_tail(&cam->frame[i].frame, &cam->inqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + } +} + +/*****************************************************************************/ + +int zc0301_write_reg(struct zc0301_device* cam, u16 index, u16 value) +{ + struct usb_device* udev = cam->usbdev; + int res; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0xa0, 0x40, + value, index, NULL, 0, ZC0301_CTRL_TIMEOUT); + if (res < 0) { + DBG(3, "Failed to write a register (index 0x%04X, " + "value 0x%02X, error %d)",index, value, res); + return -1; + } + + return 0; +} + + +int zc0301_read_reg(struct zc0301_device* cam, u16 index) +{ + struct usb_device* udev = cam->usbdev; + u8* buff = cam->control_buffer; + int res; + + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0xa1, 0xc0, + 0x0001, index, buff, 1, ZC0301_CTRL_TIMEOUT); + if (res < 0) + DBG(3, "Failed to read a register (index 0x%04X, error %d)", + index, res); + + PDBGG("Read: index 0x%04X, value: 0x%04X", index, (int)(*buff)); + + return (res >= 0) ? (int)(*buff) : -1; +} + + +int zc0301_i2c_read(struct zc0301_device* cam, u16 address, u8 length) +{ + int err = 0, res, r0, r1; + + err += zc0301_write_reg(cam, 0x0092, address); + err += zc0301_write_reg(cam, 0x0090, 0x02); + + msleep(1); + + res = zc0301_read_reg(cam, 0x0091); + if (res < 0) + err += res; + r0 = zc0301_read_reg(cam, 0x0095); + if (r0 < 0) + err += r0; + r1 = zc0301_read_reg(cam, 0x0096); + if (r1 < 0) + err += r1; + + res = (length <= 1) ? r0 : r0 | (r1 << 8); + + if (err) + DBG(3, "I2C read failed at address 0x%04X, value: 0x%04X", + address, res); + + + PDBGG("I2C read: address 0x%04X, value: 0x%04X", address, res); + + return err ? -1 : res; +} + + +int zc0301_i2c_write(struct zc0301_device* cam, u16 address, u16 value) +{ + int err = 0, res; + + err += zc0301_write_reg(cam, 0x0092, address); + err += zc0301_write_reg(cam, 0x0093, value & 0xff); + err += zc0301_write_reg(cam, 0x0094, value >> 8); + err += zc0301_write_reg(cam, 0x0090, 0x01); + + msleep(1); + + res = zc0301_read_reg(cam, 0x0091); + if (res < 0) + err += res; + + if (err) + DBG(3, "I2C write failed at address 0x%04X, value: 0x%04X", + address, value); + + PDBGG("I2C write: address 0x%04X, value: 0x%04X", address, value); + + return err ? -1 : 0; +} + +/*****************************************************************************/ + +static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs) +{ + struct zc0301_device* cam = urb->context; + struct zc0301_frame_t** f; + size_t imagesize; + u8 i; + int err = 0; + + if (urb->status == -ENOENT) + return; + + f = &cam->frame_current; + + if (cam->stream == STREAM_INTERRUPT) { + cam->stream = STREAM_OFF; + if ((*f)) + (*f)->state = F_QUEUED; + DBG(3, "Stream interrupted"); + wake_up(&cam->wait_stream); + } + + if (cam->state & DEV_DISCONNECTED) + return; + + if (cam->state & DEV_MISCONFIGURED) { + wake_up_interruptible(&cam->wait_frame); + return; + } + + if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) + goto resubmit_urb; + + if (!(*f)) + (*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t, + frame); + + imagesize = (cam->sensor.pix_format.width * + cam->sensor.pix_format.height * + cam->sensor.pix_format.priv) / 8; + + for (i = 0; i < urb->number_of_packets; i++) { + unsigned int len, status; + void *pos; + u16* soi; + u8 sof; + + len = urb->iso_frame_desc[i].actual_length; + status = urb->iso_frame_desc[i].status; + pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; + + if (status) { + DBG(3, "Error in isochronous frame"); + (*f)->state = F_ERROR; + continue; + } + + sof = (*(soi = pos) == 0xd8ff); + + PDBGG("Isochrnous frame: length %u, #%u i,", len, i); + + if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) +start_of_frame: + if (sof) { + (*f)->state = F_GRABBING; + (*f)->buf.bytesused = 0; + do_gettimeofday(&(*f)->buf.timestamp); + DBG(3, "SOF detected: new video frame"); + } + + if ((*f)->state == F_GRABBING) { + if (sof && (*f)->buf.bytesused) + goto end_of_frame; + + if ((*f)->buf.bytesused + len > imagesize) { + DBG(3, "Video frame size exceeded"); + (*f)->state = F_ERROR; + continue; + } + + memcpy((*f)->bufmem+(*f)->buf.bytesused, pos, len); + (*f)->buf.bytesused += len; + + if ((*f)->buf.bytesused == imagesize) { + u32 b; +end_of_frame: + b = (*f)->buf.bytesused; + (*f)->state = F_DONE; + (*f)->buf.sequence= ++cam->frame_count; + spin_lock(&cam->queue_lock); + list_move_tail(&(*f)->frame, &cam->outqueue); + if (!list_empty(&cam->inqueue)) + (*f) = list_entry(cam->inqueue.next, + struct zc0301_frame_t, + frame); + else + (*f) = NULL; + spin_unlock(&cam->queue_lock); + DBG(3, "Video frame captured: : %lu bytes", + (unsigned long)(b)); + + if (!(*f)) + goto resubmit_urb; + + if (sof) + goto start_of_frame; + } + } + } + +resubmit_urb: + urb->dev = cam->usbdev; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0 && err != -EPERM) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "usb_submit_urb() failed"); + } + + wake_up_interruptible(&cam->wait_frame); +} + + +static int zc0301_start_transfer(struct zc0301_device* cam) +{ + struct usb_device *udev = cam->usbdev; + struct urb* urb; + const unsigned int wMaxPacketSize[] = {0, 128, 192, 256, 384, + 512, 768, 1023}; + const unsigned int psz = wMaxPacketSize[ZC0301_ALTERNATE_SETTING]; + s8 i, j; + int err = 0; + + for (i = 0; i < ZC0301_URBS; i++) { + cam->transfer_buffer[i] = kzalloc(ZC0301_ISO_PACKETS * psz, + GFP_KERNEL); + if (!cam->transfer_buffer[i]) { + err = -ENOMEM; + DBG(1, "Not enough memory"); + goto free_buffers; + } + } + + for (i = 0; i < ZC0301_URBS; i++) { + urb = usb_alloc_urb(ZC0301_ISO_PACKETS, GFP_KERNEL); + cam->urb[i] = urb; + if (!urb) { + err = -ENOMEM; + DBG(1, "usb_alloc_urb() failed"); + goto free_urbs; + } + urb->dev = udev; + urb->context = cam; + urb->pipe = usb_rcvisocpipe(udev, 1); + urb->transfer_flags = URB_ISO_ASAP; + urb->number_of_packets = ZC0301_ISO_PACKETS; + urb->complete = zc0301_urb_complete; + urb->transfer_buffer = cam->transfer_buffer[i]; + urb->transfer_buffer_length = psz * ZC0301_ISO_PACKETS; + urb->interval = 1; + for (j = 0; j < ZC0301_ISO_PACKETS; j++) { + urb->iso_frame_desc[j].offset = psz * j; + urb->iso_frame_desc[j].length = psz; + } + } + + err = usb_set_interface(udev, 0, ZC0301_ALTERNATE_SETTING); + if (err) { + DBG(1, "usb_set_interface() failed"); + goto free_urbs; + } + + cam->frame_current = NULL; + + for (i = 0; i < ZC0301_URBS; i++) { + err = usb_submit_urb(cam->urb[i], GFP_KERNEL); + if (err) { + for (j = i-1; j >= 0; j--) + usb_kill_urb(cam->urb[j]); + DBG(1, "usb_submit_urb() failed, error %d", err); + goto free_urbs; + } + } + + return 0; + +free_urbs: + for (i = 0; (i < ZC0301_URBS) && cam->urb[i]; i++) + usb_free_urb(cam->urb[i]); + +free_buffers: + for (i = 0; (i < ZC0301_URBS) && cam->transfer_buffer[i]; i++) + kfree(cam->transfer_buffer[i]); + + return err; +} + + +static int zc0301_stop_transfer(struct zc0301_device* cam) +{ + struct usb_device *udev = cam->usbdev; + s8 i; + int err = 0; + + if (cam->state & DEV_DISCONNECTED) + return 0; + + for (i = ZC0301_URBS-1; i >= 0; i--) { + usb_kill_urb(cam->urb[i]); + usb_free_urb(cam->urb[i]); + kfree(cam->transfer_buffer[i]); + } + + err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ + if (err) + DBG(3, "usb_set_interface() failed"); + + return err; +} + + +static int zc0301_stream_interrupt(struct zc0301_device* cam) +{ + long timeout; + + cam->stream = STREAM_INTERRUPT; + timeout = wait_event_timeout(cam->wait_stream, + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + ZC0301_URB_TIMEOUT); + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + else if (cam->stream != STREAM_OFF) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "URB timeout reached. The camera is misconfigured. To " + "use it, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + return 0; +} + +/*****************************************************************************/ + +static int +zc0301_set_compression(struct zc0301_device* cam, + struct v4l2_jpegcompression* compression) +{ + int r, err = 0; + + if ((r = zc0301_read_reg(cam, 0x0008)) < 0) + err += r; + err += zc0301_write_reg(cam, 0x0008, r | 0x11 | compression->quality); + + return err ? -EIO : 0; +} + + +static int zc0301_init(struct zc0301_device* cam) +{ + struct zc0301_sensor* s = &cam->sensor; + struct v4l2_control ctrl; + struct v4l2_queryctrl *qctrl; + struct v4l2_rect* rect; + u8 i = 0; + int err = 0; + + if (!(cam->state & DEV_INITIALIZED)) { + init_waitqueue_head(&cam->open); + qctrl = s->qctrl; + rect = &(s->cropcap.defrect); + cam->compression.quality = ZC0301_COMPRESSION_QUALITY; + } else { /* use current values */ + qctrl = s->_qctrl; + rect = &(s->_rect); + } + + if (s->init) { + err = s->init(cam); + if (err) { + DBG(3, "Sensor initialization failed"); + return err; + } + } + + if ((err = zc0301_set_compression(cam, &cam->compression))) { + DBG(3, "set_compression() failed"); + return err; + } + + if (s->set_crop) + if ((err = s->set_crop(cam, rect))) { + DBG(3, "set_crop() failed"); + return err; + } + + if (s->set_ctrl) { + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (s->qctrl[i].id != 0 && + !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { + ctrl.id = s->qctrl[i].id; + ctrl.value = qctrl[i].default_value; + err = s->set_ctrl(cam, &ctrl); + if (err) { + DBG(3, "Set %s control failed", + s->qctrl[i].name); + return err; + } + DBG(3, "Image sensor supports '%s' control", + s->qctrl[i].name); + } + } + + if (!(cam->state & DEV_INITIALIZED)) { + mutex_init(&cam->fileop_mutex); + spin_lock_init(&cam->queue_lock); + init_waitqueue_head(&cam->wait_frame); + init_waitqueue_head(&cam->wait_stream); + cam->nreadbuffers = 2; + memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); + memcpy(&(s->_rect), &(s->cropcap.defrect), + sizeof(struct v4l2_rect)); + cam->state |= DEV_INITIALIZED; + } + + DBG(2, "Initialization succeeded"); + return 0; +} + + +static void zc0301_release_resources(struct zc0301_device* cam) +{ + DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); + video_set_drvdata(cam->v4ldev, NULL); + video_unregister_device(cam->v4ldev); + kfree(cam->control_buffer); +} + +/*****************************************************************************/ + +static int zc0301_open(struct inode* inode, struct file* filp) +{ + struct zc0301_device* cam; + int err = 0; + + /* + This is the only safe way to prevent race conditions with + disconnect + */ + if (!down_read_trylock(&zc0301_disconnect)) + return -ERESTARTSYS; + + cam = video_get_drvdata(video_devdata(filp)); + + if (mutex_lock_interruptible(&cam->dev_mutex)) { + up_read(&zc0301_disconnect); + return -ERESTARTSYS; + } + + if (cam->users) { + DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); + if ((filp->f_flags & O_NONBLOCK) || + (filp->f_flags & O_NDELAY)) { + err = -EWOULDBLOCK; + goto out; + } + mutex_unlock(&cam->dev_mutex); + err = wait_event_interruptible_exclusive(cam->open, + cam->state & DEV_DISCONNECTED + || !cam->users); + if (err) { + up_read(&zc0301_disconnect); + return err; + } + if (cam->state & DEV_DISCONNECTED) { + up_read(&zc0301_disconnect); + return -ENODEV; + } + mutex_lock(&cam->dev_mutex); + } + + + if (cam->state & DEV_MISCONFIGURED) { + err = zc0301_init(cam); + if (err) { + DBG(1, "Initialization failed again. " + "I will retry on next open()."); + goto out; + } + cam->state &= ~DEV_MISCONFIGURED; + } + + if ((err = zc0301_start_transfer(cam))) + goto out; + + filp->private_data = cam; + cam->users++; + cam->io = IO_NONE; + cam->stream = STREAM_OFF; + cam->nbuffers = 0; + cam->frame_count = 0; + zc0301_empty_framequeues(cam); + + DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); + +out: + mutex_unlock(&cam->dev_mutex); + up_read(&zc0301_disconnect); + return err; +} + + +static int zc0301_release(struct inode* inode, struct file* filp) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + + mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ + + zc0301_stop_transfer(cam); + + zc0301_release_buffers(cam); + + if (cam->state & DEV_DISCONNECTED) { + zc0301_release_resources(cam); + usb_put_dev(cam->usbdev); + mutex_unlock(&cam->dev_mutex); + kfree(cam); + return 0; + } + + cam->users--; + wake_up_interruptible_nr(&cam->open, 1); + + DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); + + mutex_unlock(&cam->dev_mutex); + + return 0; +} + + +static ssize_t +zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + struct zc0301_frame_t* f, * i; + unsigned long lock_flags; + long timeout; + int err = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + if (cam->io == IO_MMAP) { + DBG(3, "Close and open the device again to choose the read " + "method"); + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + if (cam->io == IO_NONE) { + if (!zc0301_request_buffers(cam, cam->nreadbuffers, IO_READ)) { + DBG(1, "read() failed, not enough memory"); + mutex_unlock(&cam->fileop_mutex); + return -ENOMEM; + } + cam->io = IO_READ; + cam->stream = STREAM_ON; + } + + if (list_empty(&cam->inqueue)) { + if (!list_empty(&cam->outqueue)) + zc0301_empty_framequeues(cam); + zc0301_queue_unusedframes(cam); + } + + if (!count) { + mutex_unlock(&cam->fileop_mutex); + return 0; + } + + if (list_empty(&cam->outqueue)) { + if (filp->f_flags & O_NONBLOCK) { + mutex_unlock(&cam->fileop_mutex); + return -EAGAIN; + } + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) { + mutex_unlock(&cam->fileop_mutex); + return timeout; + } + if (cam->state & DEV_DISCONNECTED) { + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + if (!timeout || (cam->state & DEV_MISCONFIGURED)) { + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + } + + f = list_entry(cam->outqueue.prev, struct zc0301_frame_t, frame); + + if (count > f->buf.bytesused) + count = f->buf.bytesused; + + if (copy_to_user(buf, f->bufmem, count)) { + err = -EFAULT; + goto exit; + } + *f_pos += count; + +exit: + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_for_each_entry(i, &cam->outqueue, frame) + i->state = F_UNUSED; + INIT_LIST_HEAD(&cam->outqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + zc0301_queue_unusedframes(cam); + + PDBGG("Frame #%lu, bytes read: %zu", + (unsigned long)f->buf.index, count); + + mutex_unlock(&cam->fileop_mutex); + + return err ? err : count; +} + + +static unsigned int zc0301_poll(struct file *filp, poll_table *wait) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + struct zc0301_frame_t* f; + unsigned long lock_flags; + unsigned int mask = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return POLLERR; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + goto error; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + goto error; + } + + if (cam->io == IO_NONE) { + if (!zc0301_request_buffers(cam, cam->nreadbuffers, IO_READ)) { + DBG(1, "poll() failed, not enough memory"); + goto error; + } + cam->io = IO_READ; + cam->stream = STREAM_ON; + } + + if (cam->io == IO_READ) { + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_for_each_entry(f, &cam->outqueue, frame) + f->state = F_UNUSED; + INIT_LIST_HEAD(&cam->outqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + zc0301_queue_unusedframes(cam); + } + + poll_wait(filp, &cam->wait_frame, wait); + + if (!list_empty(&cam->outqueue)) + mask |= POLLIN | POLLRDNORM; + + mutex_unlock(&cam->fileop_mutex); + + return mask; + +error: + mutex_unlock(&cam->fileop_mutex); + return POLLERR; +} + + +static void zc0301_vm_open(struct vm_area_struct* vma) +{ + struct zc0301_frame_t* f = vma->vm_private_data; + f->vma_use_count++; +} + + +static void zc0301_vm_close(struct vm_area_struct* vma) +{ + /* NOTE: buffers are not freed here */ + struct zc0301_frame_t* f = vma->vm_private_data; + f->vma_use_count--; +} + + +static struct vm_operations_struct zc0301_vm_ops = { + .open = zc0301_vm_open, + .close = zc0301_vm_close, +}; + + +static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + unsigned long size = vma->vm_end - vma->vm_start, + start = vma->vm_start; + void *pos; + u32 i; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || + size != PAGE_ALIGN(cam->frame[0].buf.length)) { + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + for (i = 0; i < cam->nbuffers; i++) { + if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) + break; + } + if (i == cam->nbuffers) { + mutex_unlock(&cam->fileop_mutex); + return -EINVAL; + } + + vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED; + + pos = cam->frame[i].bufmem; + while (size > 0) { /* size is page-aligned */ + if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { + mutex_unlock(&cam->fileop_mutex); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + size -= PAGE_SIZE; + } + + vma->vm_ops = &zc0301_vm_ops; + vma->vm_private_data = &cam->frame[i]; + + zc0301_vm_open(vma); + + mutex_unlock(&cam->fileop_mutex); + + return 0; +} + +/*****************************************************************************/ + +static int +zc0301_vidioc_querycap(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_capability cap = { + .driver = "zc0301", + .version = ZC0301_MODULE_VERSION_CODE, + .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING, + }; + + strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); + if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) + strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, + sizeof(cap.bus_info)); + + if (copy_to_user(arg, &cap, sizeof(cap))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_enuminput(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_input i; + + if (copy_from_user(&i, arg, sizeof(i))) + return -EFAULT; + + if (i.index) + return -EINVAL; + + memset(&i, 0, sizeof(i)); + strcpy(i.name, "Camera"); + i.type = V4L2_INPUT_TYPE_CAMERA; + + if (copy_to_user(arg, &i, sizeof(i))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_g_input(struct zc0301_device* cam, void __user * arg) +{ + int index = 0; + + if (copy_to_user(arg, &index, sizeof(index))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_s_input(struct zc0301_device* cam, void __user * arg) +{ + int index; + + if (copy_from_user(&index, arg, sizeof(index))) + return -EFAULT; + + if (index != 0) + return -EINVAL; + + return 0; +} + + +static int +zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg) +{ + struct zc0301_sensor* s = &cam->sensor; + struct v4l2_queryctrl qc; + u8 i; + + if (copy_from_user(&qc, arg, sizeof(qc))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (qc.id && qc.id == s->qctrl[i].id) { + memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); + if (copy_to_user(arg, &qc, sizeof(qc))) + return -EFAULT; + return 0; + } + + return -EINVAL; +} + + +static int +zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg) +{ + struct zc0301_sensor* s = &cam->sensor; + struct v4l2_control ctrl; + int err = 0; + u8 i; + + if (!s->get_ctrl && !s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + + if (!s->get_ctrl) { + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (ctrl.id == s->qctrl[i].id) { + ctrl.value = s->_qctrl[i].default_value; + goto exit; + } + return -EINVAL; + } else + err = s->get_ctrl(cam, &ctrl); + +exit: + if (copy_to_user(arg, &ctrl, sizeof(ctrl))) + return -EFAULT; + + return err; +} + + +static int +zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) +{ + struct zc0301_sensor* s = &cam->sensor; + struct v4l2_control ctrl; + u8 i; + int err = 0; + + if (!s->set_ctrl) + return -EINVAL; + + if (copy_from_user(&ctrl, arg, sizeof(ctrl))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + if (ctrl.id == s->qctrl[i].id) { + if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) + return -EINVAL; + if (ctrl.value < s->qctrl[i].minimum || + ctrl.value > s->qctrl[i].maximum) + return -ERANGE; + ctrl.value -= ctrl.value % s->qctrl[i].step; + break; + } + + if ((err = s->set_ctrl(cam, &ctrl))) + return err; + + s->_qctrl[i].default_value = ctrl.value; + + return 0; +} + + +static int +zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_cropcap* cc = &(cam->sensor.cropcap); + + cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cc->pixelaspect.numerator = 1; + cc->pixelaspect.denominator = 1; + + if (copy_to_user(arg, cc, sizeof(*cc))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg) +{ + struct zc0301_sensor* s = &cam->sensor; + struct v4l2_crop crop = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + }; + + memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); + + if (copy_to_user(arg, &crop, sizeof(crop))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) +{ + struct zc0301_sensor* s = &cam->sensor; + struct v4l2_crop crop; + struct v4l2_rect* rect; + struct v4l2_rect* bounds = &(s->cropcap.bounds); + const enum zc0301_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; + + if (copy_from_user(&crop, arg, sizeof(crop))) + return -EFAULT; + + rect = &(crop.c); + + if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_CROP failed. " + "Unmap the buffers first."); + return -EINVAL; + } + + if (!s->set_crop) { + memcpy(rect, &(s->_rect), sizeof(*rect)); + if (copy_to_user(arg, &crop, sizeof(crop))) + return -EFAULT; + return 0; + } + + rect->left &= ~7L; + rect->top &= ~7L; + if (rect->width < 8) + rect->width = 8; + if (rect->height < 8) + rect->height = 8; + if (rect->width > bounds->width) + rect->width = bounds->width; + if (rect->height > bounds->height) + rect->height = bounds->height; + if (rect->left < bounds->left) + rect->left = bounds->left; + if (rect->top < bounds->top) + rect->top = bounds->top; + if (rect->left + rect->width > bounds->left + bounds->width) + rect->left = bounds->left+bounds->width - rect->width; + if (rect->top + rect->height > bounds->top + bounds->height) + rect->top = bounds->top+bounds->height - rect->height; + rect->width &= ~7L; + rect->height &= ~7L; + + if (cam->stream == STREAM_ON) + if ((err = zc0301_stream_interrupt(cam))) + return err; + + if (copy_to_user(arg, &crop, sizeof(crop))) { + cam->stream = stream; + return -EFAULT; + } + + if (cam->module_param.force_munmap || cam->io == IO_READ) + zc0301_release_buffers(cam); + + if (s->set_crop) + err += s->set_crop(cam, rect); + + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + s->pix_format.width = rect->width; + s->pix_format.height = rect->height; + memcpy(&(s->_rect), rect, sizeof(*rect)); + + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } + + if (cam->io == IO_READ) + zc0301_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + zc0301_requeue_outqueue(cam); + + cam->stream = stream; + + return 0; +} + + +static int +zc0301_vidioc_enum_fmt(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_fmtdesc fmtd; + + if (copy_from_user(&fmtd, arg, sizeof(fmtd))) + return -EFAULT; + + if (fmtd.index == 0) { + strcpy(fmtd.description, "JPEG"); + fmtd.pixelformat = V4L2_PIX_FMT_JPEG; + fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; + } else + return -EINVAL; + + fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); + + if (copy_to_user(arg, &fmtd, sizeof(fmtd))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_format format; + struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); + + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; + + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + pfmt->bytesperline = 0; + pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); + pfmt->field = V4L2_FIELD_NONE; + memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); + + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, + void __user * arg) +{ + struct zc0301_sensor* s = &cam->sensor; + struct v4l2_format format; + struct v4l2_pix_format* pix; + struct v4l2_pix_format* pfmt = &(s->pix_format); + struct v4l2_rect* bounds = &(s->cropcap.bounds); + struct v4l2_rect rect; + const enum zc0301_stream_state stream = cam->stream; + const u32 nbuffers = cam->nbuffers; + u32 i; + int err = 0; + + if (copy_from_user(&format, arg, sizeof(format))) + return -EFAULT; + + pix = &(format.fmt.pix); + + if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + memcpy(&rect, &(s->_rect), sizeof(rect)); + + if (!s->set_crop) { + pix->width = rect.width; + pix->height = rect.height; + } else { + rect.width = pix->width; + rect.height = pix->height; + } + + if (rect.width < 8) + rect.width = 8; + if (rect.height < 8) + rect.height = 8; + if (rect.width > bounds->left + bounds->width - rect.left) + rect.width = bounds->left + bounds->width - rect.left; + if (rect.height > bounds->top + bounds->height - rect.top) + rect.height = bounds->top + bounds->height - rect.top; + rect.width &= ~7L; + rect.height &= ~7L; + + pix->width = rect.width; + pix->height = rect.height; + pix->pixelformat = pfmt->pixelformat; + pix->priv = pfmt->priv; + pix->colorspace = pfmt->colorspace; + pix->bytesperline = 0; + pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); + pix->field = V4L2_FIELD_NONE; + + if (cmd == VIDIOC_TRY_FMT) { + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; + return 0; + } + + if (cam->module_param.force_munmap) + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_S_FMT failed. " + "Unmap the buffers first."); + return -EINVAL; + } + + if (cam->stream == STREAM_ON) + if ((err = zc0301_stream_interrupt(cam))) + return err; + + if (copy_to_user(arg, &format, sizeof(format))) { + cam->stream = stream; + return -EFAULT; + } + + if (cam->module_param.force_munmap || cam->io == IO_READ) + zc0301_release_buffers(cam); + + if (s->set_crop) + err += s->set_crop(cam, &rect); + + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -EIO; + } + + memcpy(pfmt, pix, sizeof(*pix)); + memcpy(&(s->_rect), &rect, sizeof(rect)); + + if ((cam->module_param.force_munmap || cam->io == IO_READ) && + nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " + "use the camera, close and open /dev/video%d again.", + cam->v4ldev->minor); + return -ENOMEM; + } + + if (cam->io == IO_READ) + zc0301_empty_framequeues(cam); + else if (cam->module_param.force_munmap) + zc0301_requeue_outqueue(cam); + + cam->stream = stream; + + return 0; +} + + +static int +zc0301_vidioc_g_jpegcomp(struct zc0301_device* cam, void __user * arg) +{ + if (copy_to_user(arg, &cam->compression, sizeof(cam->compression))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_jpegcompression jc; + const enum zc0301_stream_state stream = cam->stream; + int err = 0; + + if (copy_from_user(&jc, arg, sizeof(jc))) + return -EFAULT; + + if (jc.quality != 0) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = zc0301_stream_interrupt(cam))) + return err; + + err += zc0301_set_compression(cam, &jc); + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " + "problems. To use the camera, close and open " + "/dev/video%d again.", cam->v4ldev->minor); + return -EIO; + } + + cam->compression.quality = jc.quality; + + cam->stream = stream; + + return 0; +} + + +static int +zc0301_vidioc_reqbufs(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_requestbuffers rb; + u32 i; + int err; + + if (copy_from_user(&rb, arg, sizeof(rb))) + return -EFAULT; + + if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + rb.memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + if (cam->io == IO_READ) { + DBG(3, "Close and open the device again to choose the mmap " + "I/O method"); + return -EINVAL; + } + + for (i = 0; i < cam->nbuffers; i++) + if (cam->frame[i].vma_use_count) { + DBG(3, "VIDIOC_REQBUFS failed. " + "Previous buffers are still mapped."); + return -EINVAL; + } + + if (cam->stream == STREAM_ON) + if ((err = zc0301_stream_interrupt(cam))) + return err; + + zc0301_empty_framequeues(cam); + + zc0301_release_buffers(cam); + if (rb.count) + rb.count = zc0301_request_buffers(cam, rb.count, IO_MMAP); + + if (copy_to_user(arg, &rb, sizeof(rb))) { + zc0301_release_buffers(cam); + cam->io = IO_NONE; + return -EFAULT; + } + + cam->io = rb.count ? IO_MMAP : IO_NONE; + + return 0; +} + + +static int +zc0301_vidioc_querybuf(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_buffer b; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; + + memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); + + if (cam->frame[b.index].vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; + + if (cam->frame[b.index].state == F_DONE) + b.flags |= V4L2_BUF_FLAG_DONE; + else if (cam->frame[b.index].state != F_UNUSED) + b.flags |= V4L2_BUF_FLAG_QUEUED; + + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_qbuf(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_buffer b; + unsigned long lock_flags; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b.index >= cam->nbuffers || cam->io != IO_MMAP) + return -EINVAL; + + if (cam->frame[b.index].state != F_UNUSED) + return -EINVAL; + + cam->frame[b.index].state = F_QUEUED; + + spin_lock_irqsave(&cam->queue_lock, lock_flags); + list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + PDBGG("Frame #%lu queued", (unsigned long)b.index); + + return 0; +} + + +static int +zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp, + void __user * arg) +{ + struct v4l2_buffer b; + struct zc0301_frame_t *f; + unsigned long lock_flags; + long timeout; + + if (copy_from_user(&b, arg, sizeof(b))) + return -EFAULT; + + if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP) + return -EINVAL; + + if (list_empty(&cam->outqueue)) { + if (cam->stream == STREAM_OFF) + return -EINVAL; + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + timeout = wait_event_interruptible_timeout + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); + if (timeout < 0) + return timeout; + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + if (!timeout || (cam->state & DEV_MISCONFIGURED)) + return -EIO; + } + + spin_lock_irqsave(&cam->queue_lock, lock_flags); + f = list_entry(cam->outqueue.next, struct zc0301_frame_t, frame); + list_del(cam->outqueue.next); + spin_unlock_irqrestore(&cam->queue_lock, lock_flags); + + f->state = F_UNUSED; + + memcpy(&b, &f->buf, sizeof(b)); + if (f->vma_use_count) + b.flags |= V4L2_BUF_FLAG_MAPPED; + + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + + PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); + + return 0; +} + + +static int +zc0301_vidioc_streamon(struct zc0301_device* cam, void __user * arg) +{ + int type; + + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (list_empty(&cam->inqueue)) + return -EINVAL; + + cam->stream = STREAM_ON; + + DBG(3, "Stream on"); + + return 0; +} + + +static int +zc0301_vidioc_streamoff(struct zc0301_device* cam, void __user * arg) +{ + int type, err; + + if (copy_from_user(&type, arg, sizeof(type))) + return -EFAULT; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = zc0301_stream_interrupt(cam))) + return err; + + zc0301_empty_framequeues(cam); + + DBG(3, "Stream off"); + + return 0; +} + + +static int +zc0301_vidioc_g_parm(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + return 0; +} + + +static int +zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg) +{ + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + + if (sp.parm.capture.readbuffers == 0) + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (sp.parm.capture.readbuffers > ZC0301_MAX_FRAMES) + sp.parm.capture.readbuffers = ZC0301_MAX_FRAMES; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + cam->nreadbuffers = sp.parm.capture.readbuffers; + + return 0; +} + + +static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, + unsigned int cmd, void __user * arg) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + + switch (cmd) { + + case VIDIOC_QUERYCAP: + return zc0301_vidioc_querycap(cam, arg); + + case VIDIOC_ENUMINPUT: + return zc0301_vidioc_enuminput(cam, arg); + + case VIDIOC_G_INPUT: + return zc0301_vidioc_g_input(cam, arg); + + case VIDIOC_S_INPUT: + return zc0301_vidioc_s_input(cam, arg); + + case VIDIOC_QUERYCTRL: + return zc0301_vidioc_query_ctrl(cam, arg); + + case VIDIOC_G_CTRL: + return zc0301_vidioc_g_ctrl(cam, arg); + + case VIDIOC_S_CTRL_OLD: + case VIDIOC_S_CTRL: + return zc0301_vidioc_s_ctrl(cam, arg); + + case VIDIOC_CROPCAP_OLD: + case VIDIOC_CROPCAP: + return zc0301_vidioc_cropcap(cam, arg); + + case VIDIOC_G_CROP: + return zc0301_vidioc_g_crop(cam, arg); + + case VIDIOC_S_CROP: + return zc0301_vidioc_s_crop(cam, arg); + + case VIDIOC_ENUM_FMT: + return zc0301_vidioc_enum_fmt(cam, arg); + + case VIDIOC_G_FMT: + return zc0301_vidioc_g_fmt(cam, arg); + + case VIDIOC_TRY_FMT: + case VIDIOC_S_FMT: + return zc0301_vidioc_try_s_fmt(cam, cmd, arg); + + case VIDIOC_G_JPEGCOMP: + return zc0301_vidioc_g_jpegcomp(cam, arg); + + case VIDIOC_S_JPEGCOMP: + return zc0301_vidioc_s_jpegcomp(cam, arg); + + case VIDIOC_REQBUFS: + return zc0301_vidioc_reqbufs(cam, arg); + + case VIDIOC_QUERYBUF: + return zc0301_vidioc_querybuf(cam, arg); + + case VIDIOC_QBUF: + return zc0301_vidioc_qbuf(cam, arg); + + case VIDIOC_DQBUF: + return zc0301_vidioc_dqbuf(cam, filp, arg); + + case VIDIOC_STREAMON: + return zc0301_vidioc_streamon(cam, arg); + + case VIDIOC_STREAMOFF: + return zc0301_vidioc_streamoff(cam, arg); + + case VIDIOC_G_PARM: + return zc0301_vidioc_g_parm(cam, arg); + + case VIDIOC_S_PARM_OLD: + case VIDIOC_S_PARM: + return zc0301_vidioc_s_parm(cam, arg); + + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case VIDIOC_QUERYSTD: + case VIDIOC_ENUMSTD: + case VIDIOC_QUERYMENU: + return -EINVAL; + + default: + return -EINVAL; + + } +} + + +static int zc0301_ioctl(struct inode* inode, struct file* filp, + unsigned int cmd, unsigned long arg) +{ + struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + int err = 0; + + if (mutex_lock_interruptible(&cam->fileop_mutex)) + return -ERESTARTSYS; + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + mutex_unlock(&cam->fileop_mutex); + return -ENODEV; + } + + if (cam->state & DEV_MISCONFIGURED) { + DBG(1, "The camera is misconfigured. Close and open it " + "again."); + mutex_unlock(&cam->fileop_mutex); + return -EIO; + } + + V4LDBG(3, "zc0301", cmd); + + err = zc0301_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); + + mutex_unlock(&cam->fileop_mutex); + + return err; +} + + +static struct file_operations zc0301_fops = { + .owner = THIS_MODULE, + .open = zc0301_open, + .release = zc0301_release, + .ioctl = zc0301_ioctl, + .read = zc0301_read, + .poll = zc0301_poll, + .mmap = zc0301_mmap, + .llseek = no_llseek, +}; + +/*****************************************************************************/ + +static int +zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct zc0301_device* cam; + static unsigned int dev_nr = 0; + unsigned int i; + int err = 0; + + if (!(cam = kzalloc(sizeof(struct zc0301_device), GFP_KERNEL))) + return -ENOMEM; + + cam->usbdev = udev; + + if (!(cam->control_buffer = kzalloc(4, GFP_KERNEL))) { + DBG(1, "kmalloc() failed"); + err = -ENOMEM; + goto fail; + } + + if (!(cam->v4ldev = video_device_alloc())) { + DBG(1, "video_device_alloc() failed"); + err = -ENOMEM; + goto fail; + } + + mutex_init(&cam->dev_mutex); + + DBG(2, "ZC0301 Image Processor and Control Chip detected " + "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); + + for (i = 0; zc0301_sensor_table[i]; i++) { + err = zc0301_sensor_table[i](cam); + if (!err) + break; + } + + if (!err) + DBG(2, "%s image sensor detected", cam->sensor.name); + else { + DBG(1, "No supported image sensor detected"); + err = -ENODEV; + goto fail; + } + + if (zc0301_init(cam)) { + DBG(1, "Initialization failed. I will retry on open()."); + cam->state |= DEV_MISCONFIGURED; + } + + strcpy(cam->v4ldev->name, "ZC0301 PC Camera"); + cam->v4ldev->owner = THIS_MODULE; + cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; + cam->v4ldev->hardware = 0; + cam->v4ldev->fops = &zc0301_fops; + cam->v4ldev->minor = video_nr[dev_nr]; + cam->v4ldev->release = video_device_release; + video_set_drvdata(cam->v4ldev, cam); + + mutex_lock(&cam->dev_mutex); + + err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, + video_nr[dev_nr]); + if (err) { + DBG(1, "V4L2 device registration failed"); + if (err == -ENFILE && video_nr[dev_nr] == -1) + DBG(1, "Free /dev/videoX node not found"); + video_nr[dev_nr] = -1; + dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; + mutex_unlock(&cam->dev_mutex); + goto fail; + } + + DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); + + cam->module_param.force_munmap = force_munmap[dev_nr]; + cam->module_param.frame_timeout = frame_timeout[dev_nr]; + + dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; + + usb_set_intfdata(intf, cam); + + mutex_unlock(&cam->dev_mutex); + + return 0; + +fail: + if (cam) { + kfree(cam->control_buffer); + if (cam->v4ldev) + video_device_release(cam->v4ldev); + kfree(cam); + } + return err; +} + + +static void zc0301_usb_disconnect(struct usb_interface* intf) +{ + struct zc0301_device* cam = usb_get_intfdata(intf); + + if (!cam) + return; + + down_write(&zc0301_disconnect); + + mutex_lock(&cam->dev_mutex); + + DBG(2, "Disconnecting %s...", cam->v4ldev->name); + + wake_up_interruptible_all(&cam->open); + + if (cam->users) { + DBG(2, "Device /dev/video%d is open! Deregistration and " + "memory deallocation are deferred on close.", + cam->v4ldev->minor); + cam->state |= DEV_MISCONFIGURED; + zc0301_stop_transfer(cam); + cam->state |= DEV_DISCONNECTED; + wake_up_interruptible(&cam->wait_frame); + wake_up(&cam->wait_stream); + usb_get_dev(cam->usbdev); + } else { + cam->state |= DEV_DISCONNECTED; + zc0301_release_resources(cam); + } + + mutex_unlock(&cam->dev_mutex); + + if (!cam->users) + kfree(cam); + + up_write(&zc0301_disconnect); +} + + +static struct usb_driver zc0301_usb_driver = { + .name = "zc0301", + .id_table = zc0301_id_table, + .probe = zc0301_usb_probe, + .disconnect = zc0301_usb_disconnect, +}; + +/*****************************************************************************/ + +static int __init zc0301_module_init(void) +{ + int err = 0; + + KDBG(2, ZC0301_MODULE_NAME " v" ZC0301_MODULE_VERSION); + KDBG(3, ZC0301_MODULE_AUTHOR); + + if ((err = usb_register(&zc0301_usb_driver))) + KDBG(1, "usb_register() failed"); + + return err; +} + + +static void __exit zc0301_module_exit(void) +{ + usb_deregister(&zc0301_usb_driver); +} + + +module_init(zc0301_module_init); +module_exit(zc0301_module_exit); diff --git a/drivers/media/video/zc0301/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c new file mode 100644 index 000000000000..9d282a22c15f --- /dev/null +++ b/drivers/media/video/zc0301/zc0301_pas202bcb.c @@ -0,0 +1,361 @@ +/*************************************************************************** + * Plug-in for PAS202BCB image sensor connected to the ZC030! Image * + * Processor and Control Chip * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * Initialization values of the ZC0301 have been taken from the SPCA5XX * + * driver maintained by Michel Xhaard * + * * + * 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. * + ***************************************************************************/ + +/* + NOTE: Sensor controls are disabled for now, becouse changing them while + streaming sometimes results in out-of-sync video frames. We'll use + the default initialization, until we know how to stop and start video + in the chip. However, the image quality still looks good under various + light conditions. +*/ + +#include +#include "zc0301_sensor.h" + + +static struct zc0301_sensor pas202bcb; + + +static int pas202bcb_init(struct zc0301_device* cam) +{ + int err = 0; + + err += zc0301_write_reg(cam, 0x0002, 0x00); + err += zc0301_write_reg(cam, 0x0003, 0x02); + err += zc0301_write_reg(cam, 0x0004, 0x80); + err += zc0301_write_reg(cam, 0x0005, 0x01); + err += zc0301_write_reg(cam, 0x0006, 0xE0); + err += zc0301_write_reg(cam, 0x0098, 0x00); + err += zc0301_write_reg(cam, 0x009A, 0x03); + err += zc0301_write_reg(cam, 0x011A, 0x00); + err += zc0301_write_reg(cam, 0x011C, 0x03); + err += zc0301_write_reg(cam, 0x009B, 0x01); + err += zc0301_write_reg(cam, 0x009C, 0xE6); + err += zc0301_write_reg(cam, 0x009D, 0x02); + err += zc0301_write_reg(cam, 0x009E, 0x86); + + err += zc0301_i2c_write(cam, 0x02, 0x02); + err += zc0301_i2c_write(cam, 0x0A, 0x01); + err += zc0301_i2c_write(cam, 0x0B, 0x01); + err += zc0301_i2c_write(cam, 0x0D, 0x00); + err += zc0301_i2c_write(cam, 0x12, 0x05); + err += zc0301_i2c_write(cam, 0x13, 0x63); + err += zc0301_i2c_write(cam, 0x15, 0x70); + + err += zc0301_write_reg(cam, 0x0101, 0xB7); + err += zc0301_write_reg(cam, 0x0100, 0x0D); + err += zc0301_write_reg(cam, 0x0189, 0x06); + err += zc0301_write_reg(cam, 0x01AD, 0x00); + err += zc0301_write_reg(cam, 0x01C5, 0x03); + err += zc0301_write_reg(cam, 0x01CB, 0x13); + err += zc0301_write_reg(cam, 0x0250, 0x08); + err += zc0301_write_reg(cam, 0x0301, 0x08); + err += zc0301_write_reg(cam, 0x018D, 0x70); + err += zc0301_write_reg(cam, 0x0008, 0x03); + err += zc0301_write_reg(cam, 0x01C6, 0x04); + err += zc0301_write_reg(cam, 0x01CB, 0x07); + err += zc0301_write_reg(cam, 0x0120, 0x11); + err += zc0301_write_reg(cam, 0x0121, 0x37); + err += zc0301_write_reg(cam, 0x0122, 0x58); + err += zc0301_write_reg(cam, 0x0123, 0x79); + err += zc0301_write_reg(cam, 0x0124, 0x91); + err += zc0301_write_reg(cam, 0x0125, 0xA6); + err += zc0301_write_reg(cam, 0x0126, 0xB8); + err += zc0301_write_reg(cam, 0x0127, 0xC7); + err += zc0301_write_reg(cam, 0x0128, 0xD3); + err += zc0301_write_reg(cam, 0x0129, 0xDE); + err += zc0301_write_reg(cam, 0x012A, 0xE6); + err += zc0301_write_reg(cam, 0x012B, 0xED); + err += zc0301_write_reg(cam, 0x012C, 0xF3); + err += zc0301_write_reg(cam, 0x012D, 0xF8); + err += zc0301_write_reg(cam, 0x012E, 0xFB); + err += zc0301_write_reg(cam, 0x012F, 0xFF); + err += zc0301_write_reg(cam, 0x0130, 0x26); + err += zc0301_write_reg(cam, 0x0131, 0x23); + err += zc0301_write_reg(cam, 0x0132, 0x20); + err += zc0301_write_reg(cam, 0x0133, 0x1C); + err += zc0301_write_reg(cam, 0x0134, 0x16); + err += zc0301_write_reg(cam, 0x0135, 0x13); + err += zc0301_write_reg(cam, 0x0136, 0x10); + err += zc0301_write_reg(cam, 0x0137, 0x0D); + err += zc0301_write_reg(cam, 0x0138, 0x0B); + err += zc0301_write_reg(cam, 0x0139, 0x09); + err += zc0301_write_reg(cam, 0x013A, 0x07); + err += zc0301_write_reg(cam, 0x013B, 0x06); + err += zc0301_write_reg(cam, 0x013C, 0x05); + err += zc0301_write_reg(cam, 0x013D, 0x04); + err += zc0301_write_reg(cam, 0x013E, 0x03); + err += zc0301_write_reg(cam, 0x013F, 0x02); + err += zc0301_write_reg(cam, 0x010A, 0x4C); + err += zc0301_write_reg(cam, 0x010B, 0xF5); + err += zc0301_write_reg(cam, 0x010C, 0xFF); + err += zc0301_write_reg(cam, 0x010D, 0xF9); + err += zc0301_write_reg(cam, 0x010E, 0x51); + err += zc0301_write_reg(cam, 0x010F, 0xF5); + err += zc0301_write_reg(cam, 0x0110, 0xFB); + err += zc0301_write_reg(cam, 0x0111, 0xED); + err += zc0301_write_reg(cam, 0x0112, 0x5F); + err += zc0301_write_reg(cam, 0x0180, 0x00); + err += zc0301_write_reg(cam, 0x0019, 0x00); + err += zc0301_write_reg(cam, 0x0087, 0x20); + err += zc0301_write_reg(cam, 0x0088, 0x21); + + err += zc0301_i2c_write(cam, 0x20, 0x02); + err += zc0301_i2c_write(cam, 0x21, 0x1B); + err += zc0301_i2c_write(cam, 0x03, 0x44); + err += zc0301_i2c_write(cam, 0x0E, 0x01); + err += zc0301_i2c_write(cam, 0x0F, 0x00); + + err += zc0301_write_reg(cam, 0x01A9, 0x14); + err += zc0301_write_reg(cam, 0x01AA, 0x24); + err += zc0301_write_reg(cam, 0x0190, 0x00); + err += zc0301_write_reg(cam, 0x0191, 0x02); + err += zc0301_write_reg(cam, 0x0192, 0x1B); + err += zc0301_write_reg(cam, 0x0195, 0x00); + err += zc0301_write_reg(cam, 0x0196, 0x00); + err += zc0301_write_reg(cam, 0x0197, 0x4D); + err += zc0301_write_reg(cam, 0x018C, 0x10); + err += zc0301_write_reg(cam, 0x018F, 0x20); + err += zc0301_write_reg(cam, 0x001D, 0x44); + err += zc0301_write_reg(cam, 0x001E, 0x6F); + err += zc0301_write_reg(cam, 0x001F, 0xAD); + err += zc0301_write_reg(cam, 0x0020, 0xEB); + err += zc0301_write_reg(cam, 0x0087, 0x0F); + err += zc0301_write_reg(cam, 0x0088, 0x0E); + err += zc0301_write_reg(cam, 0x0180, 0x40); + err += zc0301_write_reg(cam, 0x0192, 0x1B); + err += zc0301_write_reg(cam, 0x0191, 0x02); + err += zc0301_write_reg(cam, 0x0190, 0x00); + err += zc0301_write_reg(cam, 0x0116, 0x1D); + err += zc0301_write_reg(cam, 0x0117, 0x40); + err += zc0301_write_reg(cam, 0x0118, 0x99); + err += zc0301_write_reg(cam, 0x0180, 0x42); + err += zc0301_write_reg(cam, 0x0116, 0x1D); + err += zc0301_write_reg(cam, 0x0117, 0x40); + err += zc0301_write_reg(cam, 0x0118, 0x99); + err += zc0301_write_reg(cam, 0x0007, 0x00); + + err += zc0301_i2c_write(cam, 0x11, 0x01); + + msleep(100); + + return err; +} + + +static int pas202bcb_get_ctrl(struct zc0301_device* cam, + struct v4l2_control* ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + { + int r1 = zc0301_i2c_read(cam, 0x04, 1), + r2 = zc0301_i2c_read(cam, 0x05, 1); + if (r1 < 0 || r2 < 0) + return -EIO; + ctrl->value = (r1 << 6) | (r2 & 0x3f); + } + return 0; + case V4L2_CID_RED_BALANCE: + if ((ctrl->value = zc0301_i2c_read(cam, 0x09, 1)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case V4L2_CID_BLUE_BALANCE: + if ((ctrl->value = zc0301_i2c_read(cam, 0x07, 1)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case V4L2_CID_GAIN: + if ((ctrl->value = zc0301_i2c_read(cam, 0x10, 1)) < 0) + return -EIO; + ctrl->value &= 0x1f; + return 0; + case ZC0301_V4L2_CID_GREEN_BALANCE: + if ((ctrl->value = zc0301_i2c_read(cam, 0x08, 1)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case ZC0301_V4L2_CID_DAC_MAGNITUDE: + if ((ctrl->value = zc0301_i2c_read(cam, 0x0c, 1)) < 0) + return -EIO; + return 0; + default: + return -EINVAL; + } +} + + +static int pas202bcb_set_ctrl(struct zc0301_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += zc0301_i2c_write(cam, 0x04, ctrl->value >> 6); + err += zc0301_i2c_write(cam, 0x05, ctrl->value & 0x3f); + break; + case V4L2_CID_RED_BALANCE: + err += zc0301_i2c_write(cam, 0x09, ctrl->value); + break; + case V4L2_CID_BLUE_BALANCE: + err += zc0301_i2c_write(cam, 0x07, ctrl->value); + break; + case V4L2_CID_GAIN: + err += zc0301_i2c_write(cam, 0x10, ctrl->value); + break; + case ZC0301_V4L2_CID_GREEN_BALANCE: + err += zc0301_i2c_write(cam, 0x08, ctrl->value); + break; + case ZC0301_V4L2_CID_DAC_MAGNITUDE: + err += zc0301_i2c_write(cam, 0x0c, ctrl->value); + break; + default: + return -EINVAL; + } + err += zc0301_i2c_write(cam, 0x11, 0x01); + + return err ? -EIO : 0; +} + + +static struct zc0301_sensor pas202bcb = { + .name = "PAS202BCB", + .init = &pas202bcb_init, + .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x01e5, + .maximum = 0x3fff, + .step = 0x0001, + .default_value = 0x01e5, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x0c, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = ZC0301_V4L2_CID_DAC_MAGNITUDE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "DAC magnitude", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = 0x00, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x01, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x05, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + { + .id = ZC0301_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x00, + .flags = V4L2_CTRL_FLAG_DISABLED, + }, + }, + .get_ctrl = &pas202bcb_get_ctrl, + .set_ctrl = &pas202bcb_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_JPEG, + .priv = 8, + }, +}; + + +int zc0301_probe_pas202bcb(struct zc0301_device* cam) +{ + int r0 = 0, r1 = 0, err = 0; + unsigned int pid = 0; + + err += zc0301_write_reg(cam, 0x0000, 0x01); + err += zc0301_write_reg(cam, 0x0010, 0x0e); + err += zc0301_write_reg(cam, 0x0001, 0x01); + err += zc0301_write_reg(cam, 0x0012, 0x03); + err += zc0301_write_reg(cam, 0x0012, 0x01); + err += zc0301_write_reg(cam, 0x008d, 0x08); + + msleep(10); + + r0 = zc0301_i2c_read(cam, 0x00, 1); + r1 = zc0301_i2c_read(cam, 0x01, 1); + + if (r0 < 0 || r1 < 0 || err) + return -EIO; + + pid = (r0 << 4) | ((r1 & 0xf0) >> 4); + if (pid != 0x017) + return -ENODEV; + + zc0301_attach_sensor(cam, &pas202bcb); + + return 0; +} diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h new file mode 100644 index 000000000000..cf0965a81d01 --- /dev/null +++ b/drivers/media/video/zc0301/zc0301_sensor.h @@ -0,0 +1,103 @@ +/*************************************************************************** + * API for image sensors connected to the ZC030! Image Processor and * + * Control Chip * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * 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. * + ***************************************************************************/ + +#ifndef _ZC0301_SENSOR_H_ +#define _ZC0301_SENSOR_H_ + +#include +#include +#include +#include +#include +#include + +struct zc0301_device; +struct zc0301_sensor; + +/*****************************************************************************/ + +extern int zc0301_probe_pas202bcb(struct zc0301_device* cam); + +#define ZC0301_SENSOR_TABLE \ +/* Weak detections must go at the end of the list */ \ +static int (*zc0301_sensor_table[])(struct zc0301_device*) = { \ + &zc0301_probe_pas202bcb, \ + NULL, \ +}; + +extern struct zc0301_device* +zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id); + +extern void +zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); + +#define ZC0301_USB_DEVICE(vend, prod, intclass) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ + USB_DEVICE_ID_MATCH_INT_CLASS, \ + .idVendor = (vend), \ + .idProduct = (prod), \ + .bInterfaceClass = (intclass) + +#define ZC0301_ID_TABLE \ +static const struct usb_device_id zc0301_id_table[] = { \ + { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, \ + { ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */ \ + { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131B */ \ + { ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */ \ + { ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */ \ + { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \ + { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \ + { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \ + { } \ +}; + +/*****************************************************************************/ + +extern int zc0301_write_reg(struct zc0301_device*, u16 index, u16 value); +extern int zc0301_read_reg(struct zc0301_device*, u16 index); +extern int zc0301_i2c_write(struct zc0301_device*, u16 address, u16 value); +extern int zc0301_i2c_read(struct zc0301_device*, u16 address, u8 length); + +/*****************************************************************************/ + +#define ZC0301_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 +#define ZC0301_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE +#define ZC0301_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1 + +struct zc0301_sensor { + char name[32]; + + struct v4l2_queryctrl qctrl[ZC0301_MAX_CTRLS]; + struct v4l2_cropcap cropcap; + struct v4l2_pix_format pix_format; + + int (*init)(struct zc0301_device*); + int (*get_ctrl)(struct zc0301_device*, struct v4l2_control* ctrl); + int (*set_ctrl)(struct zc0301_device*, + const struct v4l2_control* ctrl); + int (*set_crop)(struct zc0301_device*, const struct v4l2_rect* rect); + + /* Private */ + struct v4l2_queryctrl _qctrl[ZC0301_MAX_CTRLS]; + struct v4l2_rect _rect; +}; + +#endif /* _ZC0301_SENSOR_H_ */ diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index b1222cd4aa46..7fdbc5dad5fd 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -87,8 +87,6 @@ source "drivers/usb/input/Kconfig" source "drivers/usb/image/Kconfig" -source "drivers/usb/media/Kconfig" - source "drivers/usb/net/Kconfig" source "drivers/usb/mon/Kconfig" diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index bb36a1c1dbb3..9b7d9769fdcc 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -35,20 +35,6 @@ obj-$(CONFIG_USB_WACOM) += input/ obj-$(CONFIG_USB_ACECAD) += input/ obj-$(CONFIG_USB_XPAD) += input/ -obj-$(CONFIG_USB_DABUSB) += media/ -obj-$(CONFIG_USB_DSBR) += media/ -obj-$(CONFIG_USB_ET61X251) += media/ -obj-$(CONFIG_USB_IBMCAM) += media/ -obj-$(CONFIG_USB_KONICAWC) += media/ -obj-$(CONFIG_USB_OV511) += media/ -obj-$(CONFIG_USB_PWC) += media/ -obj-$(CONFIG_USB_SE401) += media/ -obj-$(CONFIG_USB_SN9C102) += media/ -obj-$(CONFIG_USB_STV680) += media/ -obj-$(CONFIG_USB_VICAM) += media/ -obj-$(CONFIG_USB_W9968CF) += media/ -obj-$(CONFIG_USB_ZC0301) += media/ - obj-$(CONFIG_USB_CATC) += net/ obj-$(CONFIG_USB_KAWETH) += net/ obj-$(CONFIG_USB_PEGASUS) += net/ diff --git a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig deleted file mode 100644 index 189d40f96be5..000000000000 --- a/drivers/usb/media/Kconfig +++ /dev/null @@ -1,241 +0,0 @@ -# -# USB Multimedia device configuration -# -comment "USB Multimedia devices" - depends on USB - -config USB_DABUSB - tristate "DABUSB driver" - depends on USB - ---help--- - A Digital Audio Broadcasting (DAB) Receiver for USB and Linux - brought to you by the DAB-Team - . This driver can be taken - as an example for URB-based bulk, control, and isochronous - transactions. URB's are explained in - . - - To compile this driver as a module, choose M here: the - module will be called dabusb. - -comment "Video4Linux support is needed for USB Multimedia device support" - depends on USB && VIDEO_DEV=n - -config USB_VICAM - tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && EXPERIMENTAL - ---help--- - Say Y here if you have 3com homeconnect camera (vicam). - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Multimedia Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - at . - - To compile this driver as a module, choose M here: the - module will be called vicam. - -config USB_DSBR - tristate "D-Link USB FM radio support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && EXPERIMENTAL - ---help--- - Say Y here if you want to connect this type of radio to your - computer's USB port. Note that the audio is not digital, and - you must connect the line out connector to a sound card or a - set of speakers. - - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found at - . - - To compile this driver as a module, choose M here: the - module will be called dsbr100. - -config USB_ET61X251 - tristate "USB ET61X[12]51 PC Camera Controller support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want support for cameras based on Etoms ET61X151 - or ET61X251 PC Camera Controllers. - - See for more informations. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" to use this driver. - - To compile this driver as a module, choose M here: the - module will be called et61x251. - -config USB_IBMCAM - tristate "USB IBM (Xirlink) C-it Camera support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want to connect a IBM "C-It" camera, also known as - "Xirlink PC Camera" to your computer's USB port. For more - information, read . - - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found at - . - - To compile this driver as a module, choose M here: the - module will be called ibmcam. - - This camera has several configuration options which - can be specified when you load the module. Read - to learn more. - -config USB_KONICAWC - tristate "USB Konica Webcam support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want support for webcams based on a Konica - chipset. This is known to work with the Intel YC76 webcam. - - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found at - . - - To compile this driver as a module, choose M here: the - module will be called konicawc. - -config USB_OV511 - tristate "USB OV511 Camera support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want to connect this type of camera to your - computer's USB port. See for more - information and for a list of supported cameras. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Character Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - at . - - To compile this driver as a module, choose M here: the - module will be called ov511. - -config USB_SE401 - tristate "USB SE401 Camera support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want to connect this type of camera to your - computer's USB port. See for more - information and for a list of supported cameras. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Multimedia Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - at . - - To compile this driver as a module, choose M here: the - module will be called se401. - -config USB_SN9C102 - tristate "USB SN9C10x PC Camera Controller support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want support for cameras based on SONiX SN9C101, - SN9C102 or SN9C103 PC Camera Controllers. - - See for more informations. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" to use this driver. - - To compile this driver as a module, choose M here: the - module will be called sn9c102. - -config USB_STV680 - tristate "USB STV680 (Pencam) Camera support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want to connect this type of camera to your - computer's USB port. This includes the Pencam line of cameras. - See for more information and for - a list of supported cameras. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Multimedia Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - at . - - To compile this driver as a module, choose M here: the - module will be called stv680. - -config USB_W9968CF - tristate "USB W996[87]CF JPEG Dual Mode Camera support" - depends on USB && VIDEO_DEV && I2C && VIDEO_OVCAMCHIP - ---help--- - Say Y here if you want support for cameras based on OV681 or - Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. - - This driver has an optional plugin, which is distributed as a - separate module only (released under GPL). It allows to use higher - resolutions and framerates, but cannot be included in the official - Linux kernel for performance purposes. - - See for more informations. - - This driver uses the Video For Linux and the I2C APIs. It needs the - OmniVision Camera Chip support as well. You must say Y or M to - "Video For Linux", "I2C Support" and "OmniVision Camera Chip - support" to use this driver. - - To compile this driver as a module, choose M here: the - module will be called w9968cf. - -config USB_ZC0301 - tristate "USB ZC0301 Image Processor and Control Chip support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want support for cameras based on the ZC0301 - Image Processor and Control Chip. - - See for more informations. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" to use this driver. - - To compile this driver as a module, choose M here: the - module will be called zc0301. - -config USB_PWC - tristate "USB Philips Cameras" - depends on USB && VIDEO_DEV - ---help--- - Say Y or M here if you want to use one of these Philips & OEM - webcams: - * Philips PCA645, PCA646 - * Philips PCVC675, PCVC680, PCVC690 - * Philips PCVC720/40, PCVC730, PCVC740, PCVC750 - * Askey VC010 - * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' - and 'Orbit'/'Sphere' - * Samsung MPC-C10, MPC-C30 - * Creative Webcam 5, Pro Ex - * SOTEC Afina Eye - * Visionite VCS-UC300, VCS-UM100 - - The PCA635, PCVC665 and PCVC720/20 are not supported by this driver - and never will be, but the 665 and 720/20 are supported by other - drivers. - - See for more information and - installation instructions. - - The built-in microphone is enabled by selecting USB Audio support. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Character Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - at . - - To compile this driver as a module, choose M here: the - module will be called pwc. diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile deleted file mode 100644 index 50e89a33b85e..000000000000 --- a/drivers/usb/media/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# -# Makefile for USB Media drivers -# - -sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ - sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \ - sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ - sn9c102_tas5130d1b.o -et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o -zc0301-objs := zc0301_core.o zc0301_pas202bcb.o - -obj-$(CONFIG_USB_DABUSB) += dabusb.o -obj-$(CONFIG_USB_DSBR) += dsbr100.o -obj-$(CONFIG_USB_ET61X251) += et61x251.o -obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o -obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o -obj-$(CONFIG_USB_OV511) += ov511.o -obj-$(CONFIG_USB_SE401) += se401.o -obj-$(CONFIG_USB_SN9C102) += sn9c102.o -obj-$(CONFIG_USB_STV680) += stv680.o -obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o -obj-$(CONFIG_USB_W9968CF) += w9968cf.o -obj-$(CONFIG_USB_ZC0301) += zc0301.o -obj-$(CONFIG_USB_PWC) += pwc/ diff --git a/drivers/usb/media/dabfirmware.h b/drivers/usb/media/dabfirmware.h deleted file mode 100644 index d14d803566a3..000000000000 --- a/drivers/usb/media/dabfirmware.h +++ /dev/null @@ -1,1408 +0,0 @@ -/* - * dabdata.h - dab usb firmware and bitstream data - */ - -static INTEL_HEX_RECORD firmware[] = { - -{ 2, 0x0000, 0, {0x21,0x57} }, -{ 3, 0x0003, 0, {0x02,0x01,0x66} }, -{ 3, 0x000b, 0, {0x02,0x01,0x66} }, -{ 3, 0x0013, 0, {0x02,0x01,0x66} }, -{ 3, 0x001b, 0, {0x02,0x01,0x66} }, -{ 3, 0x0023, 0, {0x02,0x01,0x66} }, -{ 3, 0x002b, 0, {0x02,0x01,0x66} }, -{ 3, 0x0033, 0, {0x02,0x03,0x0f} }, -{ 3, 0x003b, 0, {0x02,0x01,0x66} }, -{ 3, 0x0043, 0, {0x02,0x01,0x00} }, -{ 3, 0x004b, 0, {0x02,0x01,0x66} }, -{ 3, 0x0053, 0, {0x02,0x01,0x66} }, -{ 3, 0x005b, 0, {0x02,0x04,0xbd} }, -{ 3, 0x0063, 0, {0x02,0x01,0x67} }, -{ 3, 0x0100, 0, {0x02,0x0c,0x5a} }, -{ 3, 0x0104, 0, {0x02,0x01,0xed} }, -{ 3, 0x0108, 0, {0x02,0x02,0x51} }, -{ 3, 0x010c, 0, {0x02,0x02,0x7c} }, -{ 3, 0x0110, 0, {0x02,0x02,0xe4} }, -{ 1, 0x0114, 0, {0x32} }, -{ 1, 0x0118, 0, {0x32} }, -{ 3, 0x011c, 0, {0x02,0x05,0xfd} }, -{ 3, 0x0120, 0, {0x02,0x00,0x00} }, -{ 3, 0x0124, 0, {0x02,0x00,0x00} }, -{ 3, 0x0128, 0, {0x02,0x04,0x3c} }, -{ 3, 0x012c, 0, {0x02,0x04,0x6a} }, -{ 3, 0x0130, 0, {0x02,0x00,0x00} }, -{ 3, 0x0134, 0, {0x02,0x00,0x00} }, -{ 3, 0x0138, 0, {0x02,0x00,0x00} }, -{ 3, 0x013c, 0, {0x02,0x00,0x00} }, -{ 3, 0x0140, 0, {0x02,0x00,0x00} }, -{ 3, 0x0144, 0, {0x02,0x00,0x00} }, -{ 3, 0x0148, 0, {0x02,0x00,0x00} }, -{ 3, 0x014c, 0, {0x02,0x00,0x00} }, -{ 3, 0x0150, 0, {0x02,0x00,0x00} }, -{ 3, 0x0154, 0, {0x02,0x00,0x00} }, -{ 10, 0x0157, 0, {0x75,0x81,0x7f,0xe5,0x82,0x60,0x03,0x02,0x01,0x61} }, -{ 5, 0x0161, 0, {0x12,0x07,0x6f,0x21,0x64} }, -{ 1, 0x0166, 0, {0x32} }, -{ 14, 0x0167, 0, {0xc0,0xd0,0xc0,0x86,0xc0,0x82,0xc0,0x83,0xc0,0xe0,0x90,0x7f,0x97,0xe0} }, -{ 14, 0x0175, 0, {0x44,0x80,0xf0,0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, -{ 14, 0x0183, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, -{ 14, 0x0191, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x90,0x7f,0x97,0xe0} }, -{ 3, 0x019f, 0, {0x55,0x7f,0xf0} }, -{ 14, 0x01a2, 0, {0x90,0x7f,0x9a,0xe0,0x30,0xe4,0x23,0x90,0x7f,0x68,0xf0,0xf0,0xf0,0xf0} }, -{ 14, 0x01b0, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, -{ 14, 0x01be, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, -{ 14, 0x01cc, 0, {0xe5,0xd8,0xc2,0xe3,0xf5,0xd8,0xd0,0xe0,0xd0,0x83,0xd0,0x82,0xd0,0x86} }, -{ 3, 0x01da, 0, {0xd0,0xd0,0x32} }, -{ 8, 0x01dd, 0, {0x75,0x86,0x00,0x90,0xff,0xc3,0x7c,0x05} }, -{ 7, 0x01e5, 0, {0xa3,0xe5,0x82,0x45,0x83,0x70,0xf9} }, -{ 1, 0x01ec, 0, {0x22} }, -{ 14, 0x01ed, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0xd0} }, -{ 14, 0x01fb, 0, {0x75,0xd0,0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91} }, -{ 13, 0x0209, 0, {0x90,0x88,0x00,0xe0,0xf5,0x41,0x90,0x7f,0xab,0x74,0x02,0xf0,0x90} }, -{ 9, 0x0216, 0, {0x7f,0xab,0x74,0x02,0xf0,0xe5,0x32,0x60,0x21} }, -{ 4, 0x021f, 0, {0x7a,0x00,0x7b,0x00} }, -{ 11, 0x0223, 0, {0xc3,0xea,0x94,0x18,0xeb,0x64,0x80,0x94,0x80,0x50,0x12} }, -{ 14, 0x022e, 0, {0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0a,0xba,0x00} }, -{ 2, 0x023c, 0, {0x01,0x0b} }, -{ 2, 0x023e, 0, {0x80,0xe3} }, -{ 2, 0x0240, 0, {0xd0,0x86} }, -{ 14, 0x0242, 0, {0xd0,0xd0,0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0} }, -{ 1, 0x0250, 0, {0x32} }, -{ 14, 0x0251, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, -{ 14, 0x025f, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} }, -{ 4, 0x026d, 0, {0x04,0xf0,0xd0,0x86} }, -{ 11, 0x0271, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, -{ 14, 0x027c, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, -{ 14, 0x028a, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, -{ 13, 0x0298, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} }, -{ 12, 0x02a5, 0, {0x7f,0xab,0x74,0x08,0xf0,0x75,0x6e,0x00,0x75,0x6f,0x02,0x12} }, -{ 6, 0x02b1, 0, {0x11,0x44,0x75,0x70,0x39,0x75} }, -{ 6, 0x02b7, 0, {0x71,0x0c,0x75,0x72,0x02,0x12} }, -{ 12, 0x02bd, 0, {0x11,0x75,0x90,0x7f,0xd6,0xe4,0xf0,0x75,0xd8,0x20,0xd0,0x86} }, -{ 14, 0x02c9, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, -{ 13, 0x02d7, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, -{ 14, 0x02e4, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, -{ 14, 0x02f2, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} }, -{ 4, 0x0300, 0, {0x10,0xf0,0xd0,0x86} }, -{ 11, 0x0304, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, -{ 14, 0x030f, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, -{ 14, 0x031d, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, -{ 12, 0x032b, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0x75,0x6e,0x00,0x75,0x6f,0x02} }, -{ 7, 0x0337, 0, {0x12,0x11,0x44,0x75,0x70,0x40,0x75} }, -{ 6, 0x033e, 0, {0x71,0x0c,0x75,0x72,0x02,0x12} }, -{ 14, 0x0344, 0, {0x11,0x75,0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0} }, -{ 5, 0x0352, 0, {0x75,0xd8,0x10,0xd0,0x86} }, -{ 14, 0x0357, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, -{ 13, 0x0365, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, -{ 13, 0x0372, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} }, -{ 12, 0x037f, 0, {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x42,0xf0,0x12,0x10,0x1b,0x90} }, -{ 13, 0x038b, 0, {0x7f,0xa6,0xe5,0x43,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40} }, -{ 1, 0x0398, 0, {0xf0} }, -{ 1, 0x0399, 0, {0x22} }, -{ 13, 0x039a, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} }, -{ 12, 0x03a7, 0, {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x44,0xf0,0x12,0x10,0x1b,0x90} }, -{ 12, 0x03b3, 0, {0x7f,0xa6,0xe5,0x45,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0xe5} }, -{ 11, 0x03bf, 0, {0x46,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40,0xf0} }, -{ 1, 0x03ca, 0, {0x22} }, -{ 10, 0x03cb, 0, {0x75,0x44,0x02,0x75,0x45,0x00,0x75,0x46,0x00,0x12} }, -{ 9, 0x03d5, 0, {0x03,0x9a,0x75,0x42,0x03,0x75,0x43,0x00,0x12} }, -{ 2, 0x03de, 0, {0x03,0x72} }, -{ 1, 0x03e0, 0, {0x22} }, -{ 12, 0x03e1, 0, {0x90,0x88,0x00,0xe5,0x36,0xf0,0x90,0x88,0x00,0x74,0x10,0x25} }, -{ 9, 0x03ed, 0, {0x36,0xf0,0x12,0x01,0xdd,0x75,0x42,0x01,0x75} }, -{ 9, 0x03f6, 0, {0x43,0x18,0x12,0x03,0x72,0x75,0x44,0x02,0x75} }, -{ 9, 0x03ff, 0,{0x45,0x00,0x75,0x46,0x00,0x12,0x03,0x9a,0x75} }, -{ 8, 0x0408, 0,{0x42,0x03,0x75,0x43,0x44,0x12,0x03,0x72} }, -{ 1, 0x0410, 0,{0x22} }, -{ 14, 0x0411, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, -{ 14, 0x041f, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} }, -{ 4, 0x042d, 0, {0x02,0xf0,0xd0,0x86} }, -{ 11, 0x0431, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, -{ 14, 0x043c, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, -{ 14, 0x044a, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xa9,0x74} }, -{ 7, 0x0458, 0, {0x04,0xf0,0x75,0x30,0x01,0xd0,0x86} }, -{ 11, 0x045f, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, -{ 14, 0x046a, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, -{ 14, 0x0478, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} }, -{ 7, 0x0486, 0, {0x04,0xf0,0x75,0x31,0x01,0xd0,0x86} }, -{ 11, 0x048d, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, -{ 14, 0x0498, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, -{ 12, 0x04a6, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe5,0xf5,0x91,0xd0,0x86} }, -{ 11, 0x04b2, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, -{ 14, 0x04bd, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, -{ 12, 0x04cb, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe7,0xf5,0x91,0xd0,0x86} }, -{ 11, 0x04d7, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, -{ 12, 0x04e2, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x20,0x90,0x7f,0x96,0xe4,0xf0} }, -{ 1, 0x04ee, 0, {0x22} }, -{ 7, 0x04ef, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x21} }, -{ 1, 0x04f6, 0, {0x22} }, -{ 14, 0x04f7, 0, {0x90,0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xe0,0xfb,0x74,0x80,0x2a,0xfa} }, -{ 14, 0x0505, 0, {0x74,0x80,0x2b,0xfb,0xea,0x03,0x03,0x54,0x3f,0xfc,0xea,0xc4,0x23,0x54} }, -{ 14, 0x0513, 0, {0x1f,0xfa,0x2c,0xfa,0xeb,0x03,0x03,0x54,0x3f,0xfc,0xeb,0xc4,0x23,0x54} }, -{ 11, 0x0521, 0, {0x1f,0xfb,0x2c,0xfb,0x90,0x17,0x0a,0xe0,0xfc,0x60,0x02} }, -{ 2, 0x052c, 0, {0x7a,0x00} }, -{ 7, 0x052e, 0, {0x90,0x17,0x0c,0xe0,0xfc,0x60,0x02} }, -{ 2, 0x0535, 0, {0x7b,0x00} }, -{ 11, 0x0537, 0, {0xea,0x2b,0xfc,0xc3,0x13,0xf5,0x3a,0x75,0x44,0x02,0x8b} }, -{ 7, 0x0542, 0, {0x45,0x8a,0x46,0x12,0x03,0x9a,0x75} }, -{ 9, 0x0549, 0, {0x6e,0x08,0x75,0x6f,0x00,0x12,0x11,0x44,0x75} }, -{ 4, 0x0552, 0, {0x70,0x47,0x75,0x71} }, -{ 8, 0x0556, 0, {0x0c,0x75,0x72,0x02,0x12,0x11,0x75,0x85} }, -{ 5, 0x055e, 0, {0x3a,0x73,0x12,0x11,0xa0} }, -{ 1, 0x0563, 0, {0x22} }, -{ 14, 0x0564, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} }, -{ 14, 0x0572, 0, {0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xef,0xe0,0xfc} }, -{ 14, 0x0580, 0, {0x33,0x95,0xe0,0xfd,0x8c,0x05,0x7c,0x00,0x90,0x7f,0xee,0xe0,0xfe,0x33} }, -{ 14, 0x058e, 0, {0x95,0xe0,0xff,0xec,0x2e,0xfc,0xed,0x3f,0xfd,0x90,0x7f,0xe9,0xe0,0xfe} }, -{ 5, 0x059c, 0, {0xbe,0x01,0x02,0x80,0x03} }, -{ 3, 0x05a1, 0, {0x02,0x05,0xf9} }, -{ 6, 0x05a4, 0, {0xbc,0x01,0x21,0xbd,0x00,0x1e} }, -{ 14, 0x05aa, 0, {0xea,0xc4,0x03,0x54,0xf8,0xfc,0xeb,0x25,0xe0,0xfd,0x2c,0x24,0x00,0xfc} }, -{ 14, 0x05b8, 0, {0xe4,0x34,0x17,0xfd,0x90,0x7e,0xc0,0xe0,0xfe,0x8c,0x82,0x8d,0x83,0xf0} }, -{ 2, 0x05c6, 0, {0x80,0x31} }, -{ 14, 0x05c8, 0, {0xea,0xc4,0x03,0x54,0xf8,0xfa,0xeb,0x25,0xe0,0xfb,0x2a,0xfa,0x24,0x00} }, -{ 14, 0x05d6, 0, {0xfb,0xe4,0x34,0x17,0xfc,0x90,0x7e,0xc0,0xe0,0xfd,0x8b,0x82,0x8c,0x83} }, -{ 14, 0x05e4, 0, {0xf0,0x74,0x01,0x2a,0x24,0x00,0xfa,0xe4,0x34,0x17,0xfb,0x90,0x7e,0xc1} }, -{ 7, 0x05f2, 0, {0xe0,0xfc,0x8a,0x82,0x8b,0x83,0xf0} }, -{ 3, 0x05f9, 0, {0x75,0x38,0x01} }, -{ 1, 0x05fc, 0, {0x22} }, -{ 14, 0x05fd, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, -{ 14, 0x060b, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, -{ 13, 0x0619, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} }, -{ 13, 0x0626, 0, {0x7f,0xaa,0x74,0x01,0xf0,0x12,0x05,0x64,0x75,0x37,0x00,0xd0,0x86} }, -{ 14, 0x0633, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, -{ 13, 0x0641, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, -{ 14, 0x064e, 0, {0x90,0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xee,0xe0} }, -{ 14, 0x065c, 0, {0xfc,0x33,0x95,0xe0,0xfd,0x90,0x7f,0x96,0xe0,0xfe,0x90,0x7f,0x96,0x74} }, -{ 14, 0x066a, 0, {0x80,0x65,0x06,0xf0,0x90,0x7f,0x00,0x74,0x01,0xf0,0xea,0xc4,0x03,0x54} }, -{ 14, 0x0678, 0, {0xf8,0xfe,0xeb,0x25,0xe0,0xfb,0x2e,0xfe,0x24,0x00,0xfb,0xe4,0x34,0x17} }, -{ 14, 0x0686, 0, {0xff,0x8b,0x82,0x8f,0x83,0xe0,0xfb,0x74,0x01,0x2e,0x24,0x00,0xfe,0xe4} }, -{ 14, 0x0694, 0, {0x34,0x17,0xff,0x8e,0x82,0x8f,0x83,0xe0,0xfe,0x90,0x7f,0xe9,0xe0,0xff} }, -{ 3, 0x06a2, 0, {0xbf,0x81,0x0a} }, -{ 10, 0x06a5, 0, {0x90,0x7f,0x00,0xeb,0xf0,0x90,0x7f,0x01,0xee,0xf0} }, -{ 8, 0x06af, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x82,0x1a} }, -{ 3, 0x06b7, 0, {0xba,0x01,0x0c} }, -{ 12, 0x06ba, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} }, -{ 11, 0x06c6, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0xb5,0xf0} }, -{ 8, 0x06d1, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x83,0x1b} }, -{ 3, 0x06d9, 0, {0xba,0x01,0x0d} }, -{ 13, 0x06dc, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} }, -{ 11, 0x06e9, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0x12,0xf0} }, -{ 8, 0x06f4, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x84,0x1c} }, -{ 3, 0x06fc, 0, {0xba,0x01,0x0d} }, -{ 13, 0x06ff, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0c} }, -{ 12, 0x070c, 0, {0x90,0x7f,0x00,0x74,0x80,0xf0,0x90,0x7f,0x01,0x74,0x01,0xf0} }, -{ 5, 0x0718, 0, {0x90,0x7f,0xb5,0xec,0xf0} }, -{ 1, 0x071d, 0, {0x22} }, -{ 12, 0x071e, 0, {0x75,0x36,0x0d,0x90,0x88,0x00,0x74,0x1d,0xf0,0x75,0x6b,0x80} }, -{ 10, 0x072a, 0, {0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} }, -{ 9, 0x0734, 0, {0x6c,0x0f,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} }, -{ 9, 0x073d, 0, {0x6c,0x06,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} }, -{ 7, 0x0746, 0, {0x6c,0x01,0x12,0x10,0xe2,0x7a,0x00} }, -{ 3, 0x074d, 0, {0xba,0xff,0x00} }, -{ 2, 0x0750, 0, {0x50,0x0a} }, -{ 10, 0x0752, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} }, -{ 10, 0x075c, 0, {0x75,0x6b,0x80,0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75} }, -{ 8, 0x0766, 0, {0x6b,0x80,0x75,0x6c,0x0f,0x12,0x10,0xe2} }, -{ 1, 0x076e, 0, {0x22} }, -{ 14, 0x076f, 0, {0x90,0x7f,0xa1,0xe4,0xf0,0x90,0x7f,0xaf,0x74,0x01,0xf0,0x90,0x7f,0x92} }, -{ 14, 0x077d, 0, {0x74,0x02,0xf0,0x75,0x8e,0x31,0x75,0x89,0x21,0x75,0x88,0x00,0x75,0xc8} }, -{ 14, 0x078b, 0, {0x00,0x75,0x8d,0x40,0x75,0x98,0x40,0x75,0xc0,0x40,0x75,0x87,0x00,0x75} }, -{ 9, 0x0799, 0, {0x20,0x00,0x75,0x21,0x00,0x75,0x22,0x00,0x75} }, -{ 5, 0x07a2, 0, {0x23,0x00,0x75,0x47,0x00} }, -{ 7, 0x07a7, 0, {0xc3,0xe5,0x47,0x94,0x20,0x50,0x11} }, -{ 13, 0x07ae, 0, {0xe5,0x47,0x24,0x00,0xf5,0x82,0xe4,0x34,0x17,0xf5,0x83,0xe4,0xf0} }, -{ 4, 0x07bb, 0, {0x05,0x47,0x80,0xe8} }, -{ 9, 0x07bf, 0, {0xe4,0xf5,0x40,0xf5,0x3f,0xe4,0xf5,0x3c,0xf5} }, -{ 7, 0x07c8, 0, {0x3b,0xe4,0xf5,0x3e,0xf5,0x3d,0x75} }, -{ 11, 0x07cf, 0, {0x32,0x00,0x75,0x37,0x00,0x75,0x39,0x00,0x90,0x7f,0x93} }, -{ 14, 0x07da, 0, {0x74,0x3c,0xf0,0x90,0x7f,0x9c,0x74,0xff,0xf0,0x90,0x7f,0x96,0x74,0x80} }, -{ 14, 0x07e8, 0, {0xf0,0x90,0x7f,0x94,0x74,0x70,0xf0,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} }, -{ 14, 0x07f6, 0, {0x7f,0x97,0xe4,0xf0,0x90,0x7f,0x95,0x74,0xc2,0xf0,0x90,0x7f,0x98,0x74} }, -{ 14, 0x0804, 0, {0x28,0xf0,0x90,0x7f,0x9e,0x74,0x28,0xf0,0x90,0x7f,0xf0,0xe4,0xf0,0x90} }, -{ 14, 0x0812, 0, {0x7f,0xf1,0xe4,0xf0,0x90,0x7f,0xf2,0xe4,0xf0,0x90,0x7f,0xf3,0xe4,0xf0} }, -{ 14, 0x0820, 0, {0x90,0x7f,0xf4,0xe4,0xf0,0x90,0x7f,0xf5,0xe4,0xf0,0x90,0x7f,0xf6,0xe4} }, -{ 14, 0x082e, 0, {0xf0,0x90,0x7f,0xf7,0xe4,0xf0,0x90,0x7f,0xf8,0xe4,0xf0,0x90,0x7f,0xf9} }, -{ 14, 0x083c, 0, {0x74,0x38,0xf0,0x90,0x7f,0xfa,0x74,0xa0,0xf0,0x90,0x7f,0xfb,0x74,0xa0} }, -{ 14, 0x084a, 0, {0xf0,0x90,0x7f,0xfc,0x74,0xa0,0xf0,0x90,0x7f,0xfd,0x74,0xa0,0xf0,0x90} }, -{ 14, 0x0858, 0, {0x7f,0xfe,0x74,0xa0,0xf0,0x90,0x7f,0xff,0x74,0xa0,0xf0,0x90,0x7f,0xe0} }, -{ 14, 0x0866, 0, {0x74,0x03,0xf0,0x90,0x7f,0xe1,0x74,0x01,0xf0,0x90,0x7f,0xdd,0x74,0x80} }, -{ 11, 0x0874, 0, {0xf0,0x12,0x12,0x43,0x12,0x07,0x1e,0x7a,0x00,0x7b,0x00} }, -{ 9, 0x087f, 0, {0xc3,0xea,0x94,0x1e,0xeb,0x94,0x00,0x50,0x17} }, -{ 12, 0x0888, 0, {0x90,0x88,0x00,0xe0,0xf5,0x47,0x90,0x88,0x0b,0xe0,0xf5,0x47} }, -{ 9, 0x0894, 0, {0x90,0x7f,0x68,0xf0,0x0a,0xba,0x00,0x01,0x0b} }, -{ 2, 0x089d, 0, {0x80,0xe0} }, -{ 12, 0x089f, 0, {0x12,0x03,0xe1,0x90,0x7f,0xd6,0xe4,0xf0,0x7a,0x00,0x7b,0x00} }, -{ 13, 0x08ab, 0, {0x8a,0x04,0x8b,0x05,0xc3,0xea,0x94,0xe0,0xeb,0x94,0x2e,0x50,0x1a} }, -{ 14, 0x08b8, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} }, -{ 10, 0x08c6, 0, {0x04,0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} }, -{ 2, 0x08d0, 0, {0x80,0xd9} }, -{ 13, 0x08d2, 0, {0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0,0x90} }, -{ 14, 0x08df, 0, {0x7f,0xde,0x74,0x05,0xf0,0x90,0x7f,0xdf,0x74,0x05,0xf0,0x90,0x7f,0xac} }, -{ 14, 0x08ed, 0, {0xe4,0xf0,0x90,0x7f,0xad,0x74,0x05,0xf0,0x75,0xa8,0x80,0x75,0xf8,0x10} }, -{ 13, 0x08fb, 0, {0x90,0x7f,0xae,0x74,0x0b,0xf0,0x90,0x7f,0xe2,0x74,0x88,0xf0,0x90} }, -{ 12, 0x0908, 0, {0x7f,0xab,0x74,0x08,0xf0,0x75,0xe8,0x11,0x75,0x32,0x01,0x75} }, -{ 12, 0x0914, 0, {0x31,0x00,0x75,0x30,0x00,0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7} }, -{ 10, 0x0920, 0, {0xd0,0x05,0xd0,0x04,0x75,0x34,0x00,0x75,0x35,0x01} }, -{ 13, 0x092a, 0, {0x90,0x7f,0xae,0x74,0x03,0xf0,0x8c,0x02,0xba,0x00,0x02,0x80,0x03} }, -{ 3, 0x0937, 0, {0x02,0x0a,0x3f} }, -{ 12, 0x093a, 0, {0x85,0x33,0x34,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90,0x7f,0x97} }, -{ 14, 0x0946, 0, {0x74,0x08,0xf0,0x90,0x7f,0x9d,0x74,0x88,0xf0,0x90,0x7f,0x9a,0xe0,0xfa} }, -{ 12, 0x0954, 0, {0x74,0x05,0x5a,0xf5,0x33,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} }, -{ 13, 0x0960, 0, {0x7f,0x97,0x74,0x02,0xf0,0x90,0x7f,0x9d,0x74,0x82,0xf0,0xe5,0x33} }, -{ 13, 0x096d, 0, {0x25,0xe0,0xfa,0x90,0x7f,0x9a,0xe0,0x54,0x05,0xfb,0x4a,0xf5,0x33} }, -{ 2, 0x097a, 0, {0x60,0x0c} }, -{ 12, 0x097c, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x4a,0xf0} }, -{ 11, 0x0988, 0, {0x75,0x6e,0x00,0x75,0x6f,0x00,0xc0,0x04,0xc0,0x05,0x12} }, -{ 14, 0x0993, 0, {0x11,0x44,0xd0,0x05,0xd0,0x04,0x90,0x17,0x13,0xe0,0xfa,0x74,0x80,0x2a} }, -{ 6, 0x09a1, 0, {0xfa,0xe5,0x33,0xb4,0x04,0x29} }, -{ 3, 0x09a7, 0, {0xba,0xa0,0x00} }, -{ 2, 0x09aa, 0, {0x50,0x24} }, -{ 13, 0x09ac, 0, {0x90,0x17,0x13,0xe0,0x04,0xfb,0x0b,0x90,0x17,0x13,0xeb,0xf0,0x90} }, -{ 14, 0x09b9, 0, {0x17,0x13,0xe0,0xfb,0x90,0x17,0x15,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05} }, -{ 9, 0x09c7, 0, {0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02} }, -{ 5, 0x09d0, 0, {0xe5,0x33,0xb4,0x02,0x26} }, -{ 6, 0x09d5, 0, {0xc3,0x74,0x04,0x9a,0x50,0x20} }, -{ 13, 0x09db, 0, {0x90,0x17,0x13,0xe0,0xfa,0x1a,0x1a,0x90,0x17,0x13,0xea,0xf0,0x90} }, -{ 13, 0x09e8, 0, {0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xf0,0xc0,0x04,0xc0,0x05,0x12} }, -{ 6, 0x09f5, 0, {0x04,0xf7,0xd0,0x05,0xd0,0x04} }, -{ 5, 0x09fb, 0, {0xe5,0x33,0xb4,0x08,0x1d} }, -{ 4, 0x0a00, 0, {0xe5,0x34,0x70,0x19} }, -{ 10, 0x0a04, 0, {0x74,0x01,0x25,0x35,0x54,0x0f,0xf5,0x35,0x85,0x35} }, -{ 12, 0x0a0e, 0, {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} }, -{ 3, 0x0a1a, 0, {0x05,0xd0,0x04} }, -{ 5, 0x0a1d, 0, {0xe5,0x33,0xb4,0x01,0x1d} }, -{ 4, 0x0a22, 0, {0xe5,0x34,0x70,0x19} }, -{ 10, 0x0a26, 0, {0xe5,0x35,0x24,0xff,0x54,0x0f,0xf5,0x35,0x85,0x35} }, -{ 12, 0x0a30, 0, {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} }, -{ 3, 0x0a3c, 0, {0x05,0xd0,0x04} }, -{ 14, 0x0a3f, 0, {0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0,0x04,0x90,0x7f,0x96} }, -{ 14, 0x0a4d, 0, {0xe0,0xfa,0x90,0x7f,0x96,0x74,0x7f,0x5a,0xf0,0x90,0x7f,0x97,0x74,0x08} }, -{ 10, 0x0a5b, 0, {0xf0,0xc3,0xec,0x94,0x00,0xed,0x94,0x02,0x40,0x08} }, -{ 8, 0x0a65, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x20,0xe6,0x08} }, -{ 8, 0x0a6d, 0, {0xc3,0xe4,0x9c,0x74,0x08,0x9d,0x50,0x13} }, -{ 14, 0x0a75, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x40,0x65,0x02,0xf0,0x7c} }, -{ 5, 0x0a83, 0, {0x00,0x7d,0x00,0x80,0x05} }, -{ 5, 0x0a88, 0, {0x0c,0xbc,0x00,0x01,0x0d} }, -{ 5, 0x0a8d, 0, {0xe5,0x38,0xb4,0x01,0x0e} }, -{ 13, 0x0a92, 0, {0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0x75,0x38} }, -{ 1, 0x0a9f, 0, {0x00} }, -{ 7, 0x0aa0, 0, {0xe5,0x31,0x70,0x03,0x02,0x09,0x2a} }, -{ 10, 0x0aa7, 0, {0x90,0x7f,0xc9,0xe0,0xfa,0x70,0x03,0x02,0x0c,0x2d} }, -{ 14, 0x0ab1, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} }, -{ 9, 0x0abf, 0, {0x7d,0xc0,0xe0,0xfa,0xba,0x2c,0x02,0x80,0x03} }, -{ 3, 0x0ac8, 0, {0x02,0x0b,0x36} }, -{ 5, 0x0acb, 0, {0x75,0x32,0x00,0x7b,0x00} }, -{ 3, 0x0ad0, 0, {0xbb,0x64,0x00} }, -{ 2, 0x0ad3, 0, {0x50,0x1c} }, -{ 14, 0x0ad5, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} }, -{ 13, 0x0ae3, 0, {0x04,0xd0,0x03,0xd0,0x02,0x90,0x88,0x0f,0xe0,0xf5,0x47,0x0b,0x80} }, -{ 1, 0x0af0, 0, {0xdf} }, -{ 13, 0x0af1, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x07,0x1e,0x12,0x03,0xe1,0x12} }, -{ 12, 0x0afe, 0, {0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x75,0x6e,0x00,0x75} }, -{ 13, 0x0b0a, 0, {0x6f,0x01,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0x44,0xd0,0x05} }, -{ 9, 0x0b17, 0, {0xd0,0x04,0xd0,0x02,0x75,0x70,0x4d,0x75,0x71} }, -{ 11, 0x0b20, 0, {0x0c,0x75,0x72,0x02,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} }, -{ 11, 0x0b2b, 0, {0x11,0x75,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x02,0x0c,0x2d} }, -{ 3, 0x0b36, 0, {0xba,0x2a,0x3b} }, -{ 13, 0x0b39, 0, {0x90,0x7f,0x98,0x74,0x20,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} }, -{ 14, 0x0b46, 0, {0x01,0xdd,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x90,0x7f,0x98,0x74,0x28,0xf0} }, -{ 2, 0x0b54, 0, {0x7b,0x00} }, -{ 3, 0x0b56, 0, {0xbb,0x0a,0x00} }, -{ 5, 0x0b59, 0, {0x40,0x03,0x02,0x0c,0x2d} }, -{ 14, 0x0b5e, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} }, -{ 8, 0x0b6c, 0, {0x04,0xd0,0x03,0xd0,0x02,0x0b,0x80,0xe2} }, -{ 3, 0x0b74, 0, {0xba,0x2b,0x1a} }, -{ 8, 0x0b77, 0, {0x90,0x7f,0xc9,0xe0,0xfb,0xbb,0x40,0x12} }, -{ 14, 0x0b7f, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x12,0x05,0xd0,0x05,0xd0,0x04,0xd0} }, -{ 4, 0x0b8d, 0, {0x02,0x02,0x0c,0x2d} }, -{ 3, 0x0b91, 0, {0xba,0x10,0x1f} }, -{ 14, 0x0b94, 0, {0x90,0x7f,0x96,0xe0,0xfb,0x90,0x7f,0x96,0x74,0x80,0x65,0x03,0xf0,0xc0} }, -{ 14, 0x0ba2, 0, {0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x3d,0xd0,0x05,0xd0,0x04,0xd0,0x02} }, -{ 3, 0x0bb0, 0, {0x02,0x0c,0x2d} }, -{ 3, 0x0bb3, 0, {0xba,0x11,0x12} }, -{ 14, 0x0bb6, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x6a,0xd0,0x05,0xd0,0x04,0xd0} }, -{ 4, 0x0bc4, 0, {0x02,0x02,0x0c,0x2d} }, -{ 3, 0x0bc8, 0, {0xba,0x12,0x12} }, -{ 14, 0x0bcb, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x8f,0xd0,0x05,0xd0,0x04,0xd0} }, -{ 4, 0x0bd9, 0, {0x02,0x02,0x0c,0x2d} }, -{ 3, 0x0bdd, 0, {0xba,0x13,0x0b} }, -{ 11, 0x0be0, 0, {0x90,0x7d,0xc1,0xe0,0xfb,0x90,0x88,0x00,0xf0,0x80,0x42} }, -{ 3, 0x0beb, 0, {0xba,0x14,0x11} }, -{ 14, 0x0bee, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0xdd,0xd0,0x05,0xd0,0x04,0xd0} }, -{ 3, 0x0bfc, 0, {0x02,0x80,0x2e} }, -{ 3, 0x0bff, 0, {0xba,0x15,0x1d} }, -{ 12, 0x0c02, 0, {0x90,0x7d,0xc1,0xe0,0xf5,0x75,0x90,0x7d,0xc2,0xe0,0xf5,0x76} }, -{ 14, 0x0c0e, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0,0x05,0xd0,0x04,0xd0} }, -{ 3, 0x0c1c, 0, {0x02,0x80,0x0e} }, -{ 3, 0x0c1f, 0, {0xba,0x16,0x0b} }, -{ 11, 0x0c22, 0, {0xc0,0x04,0xc0,0x05,0x12,0x13,0xa3,0xd0,0x05,0xd0,0x04} }, -{ 11, 0x0c2d, 0, {0x90,0x7f,0xc9,0xe4,0xf0,0x75,0x31,0x00,0x02,0x09,0x2a} }, -{ 1, 0x0c38, 0, {0x22} }, -{ 7, 0x0c39, 0, {0x53,0x55,0x50,0x45,0x4e,0x44,0x00} }, -{ 7, 0x0c40, 0, {0x52,0x45,0x53,0x55,0x4d,0x45,0x00} }, -{ 6, 0x0c47, 0, {0x20,0x56,0x6f,0x6c,0x20,0x00} }, -{ 13, 0x0c4d, 0, {0x44,0x41,0x42,0x55,0x53,0x42,0x20,0x76,0x31,0x2e,0x30,0x30,0x00} }, -{ 14, 0x0c5a, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, -{ 14, 0x0c68, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, -{ 13, 0x0c76, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} }, -{ 14, 0x0c83, 0, {0x7f,0xab,0x74,0x01,0xf0,0x90,0x7f,0xe8,0xe0,0xfa,0x90,0x7f,0xe9,0xe0} }, -{ 6, 0x0c91, 0, {0xfb,0xbb,0x00,0x02,0x80,0x03} }, -{ 3, 0x0c97, 0, {0x02,0x0d,0x38} }, -{ 3, 0x0c9a, 0, {0xba,0x80,0x14} }, -{ 14, 0x0c9d, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5} }, -{ 6, 0x0cab, 0, {0x74,0x02,0xf0,0x02,0x0e,0xcd} }, -{ 5, 0x0cb1, 0, {0xba,0x82,0x02,0x80,0x03} }, -{ 3, 0x0cb6, 0, {0x02,0x0d,0x1d} }, -{ 8, 0x0cb9, 0, {0x90,0x7f,0xec,0xe0,0xfc,0xbc,0x01,0x00} }, -{ 2, 0x0cc1, 0, {0x40,0x21} }, -{ 6, 0x0cc3, 0, {0xc3,0x74,0x07,0x9c,0x40,0x1b} }, -{ 14, 0x0cc9, 0, {0xec,0x24,0xff,0x25,0xe0,0xfd,0x24,0xc6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} }, -{ 13, 0x0cd7, 0, {0x83,0xe0,0xfd,0x53,0x05,0x01,0x90,0x7f,0x00,0xed,0xf0,0x80,0x2b} }, -{ 3, 0x0ce4, 0, {0xbc,0x81,0x00} }, -{ 2, 0x0ce7, 0, {0x40,0x21} }, -{ 6, 0x0ce9, 0, {0xc3,0x74,0x87,0x9c,0x40,0x1b} }, -{ 14, 0x0cef, 0, {0xec,0x24,0x7f,0x25,0xe0,0xfc,0x24,0xb6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} }, -{ 13, 0x0cfd, 0, {0x83,0xe0,0xfc,0x53,0x04,0x01,0x90,0x7f,0x00,0xec,0xf0,0x80,0x05} }, -{ 5, 0x0d0a, 0, {0x90,0x7f,0x00,0xe4,0xf0} }, -{ 14, 0x0d0f, 0, {0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0x02,0x0e,0xcd} }, -{ 5, 0x0d1d, 0, {0xba,0x81,0x02,0x80,0x03} }, -{ 3, 0x0d22, 0, {0x02,0x0e,0xc5} }, -{ 14, 0x0d25, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74} }, -{ 5, 0x0d33, 0, {0x02,0xf0,0x02,0x0e,0xcd} }, -{ 3, 0x0d38, 0, {0xbb,0x01,0x2d} }, -{ 6, 0x0d3b, 0, {0xba,0x00,0x03,0x02,0x0e,0xcd} }, -{ 3, 0x0d41, 0, {0xba,0x02,0x11} }, -{ 13, 0x0d44, 0, {0x75,0x59,0x00,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} }, -{ 4, 0x0d51, 0, {0x02,0x02,0x0e,0xcd} }, -{ 5, 0x0d55, 0, {0xba,0x21,0x02,0x80,0x03} }, -{ 3, 0x0d5a, 0, {0x02,0x0e,0xcd} }, -{ 11, 0x0d5d, 0, {0x75,0x37,0x01,0x90,0x7f,0xc5,0xe4,0xf0,0x02,0x0e,0xcd} }, -{ 3, 0x0d68, 0, {0xbb,0x03,0x1f} }, -{ 6, 0x0d6b, 0, {0xba,0x00,0x03,0x02,0x0e,0xcd} }, -{ 5, 0x0d71, 0, {0xba,0x02,0x02,0x80,0x03} }, -{ 3, 0x0d76, 0, {0x02,0x0e,0xcd} }, -{ 13, 0x0d79, 0, {0x75,0x59,0x01,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} }, -{ 4, 0x0d86, 0, {0x02,0x02,0x0e,0xcd} }, -{ 3, 0x0d8a, 0, {0xbb,0x06,0x54} }, -{ 5, 0x0d8d, 0, {0xba,0x80,0x02,0x80,0x03} }, -{ 3, 0x0d92, 0, {0x02,0x0e,0xc5} }, -{ 8, 0x0d95, 0, {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x01,0x15} }, -{ 12, 0x0d9d, 0, {0x7c,0xfb,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} }, -{ 9, 0x0da9, 0, {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} }, -{ 10, 0x0db2, 0, {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x02,0x02,0x80,0x03} }, -{ 3, 0x0dbc, 0, {0x02,0x0e,0xc5} }, -{ 10, 0x0dbf, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x02,0x80,0x03} }, -{ 3, 0x0dc9, 0, {0x02,0x0e,0xc5} }, -{ 12, 0x0dcc, 0, {0x7c,0x3b,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} }, -{ 9, 0x0dd8, 0, {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} }, -{ 6, 0x0de1, 0, {0xbb,0x07,0x03,0x02,0x0e,0xc5} }, -{ 3, 0x0de7, 0, {0xbb,0x08,0x10} }, -{ 13, 0x0dea, 0, {0xac,0x48,0x90,0x7f,0x00,0xec,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} }, -{ 3, 0x0df7, 0, {0x02,0x0e,0xcd} }, -{ 3, 0x0dfa, 0, {0xbb,0x09,0x31} }, -{ 5, 0x0dfd, 0, {0xba,0x00,0x02,0x80,0x03} }, -{ 3, 0x0e02, 0, {0x02,0x0e,0xc5} }, -{ 14, 0x0e05, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xc3,0x74,0x01,0x9c,0x50,0x03,0x02,0x0e,0xc5} }, -{ 8, 0x0e13, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x0a} }, -{ 10, 0x0e1b, 0, {0x90,0x17,0x21,0xe4,0xf0,0x90,0x17,0x22,0xe4,0xf0} }, -{ 9, 0x0e25, 0, {0x90,0x7f,0xea,0xe0,0xf5,0x48,0x02,0x0e,0xcd} }, -{ 3, 0x0e2e, 0, {0xbb,0x0a,0x27} }, -{ 5, 0x0e31, 0, {0xba,0x81,0x02,0x80,0x03} }, -{ 3, 0x0e36, 0, {0x02,0x0e,0xc5} }, -{ 14, 0x0e39, 0, {0x90,0x7f,0xec,0xe0,0xfa,0x24,0x20,0xfa,0xe4,0x34,0x17,0xfc,0x8a,0x82} }, -{ 14, 0x0e47, 0, {0x8c,0x83,0xe0,0xfa,0x90,0x7f,0x00,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} }, -{ 3, 0x0e55, 0, {0x02,0x0e,0xcd} }, -{ 5, 0x0e58, 0, {0xbb,0x0b,0x02,0x80,0x03} }, -{ 3, 0x0e5d, 0, {0x02,0x0e,0xa9} }, -{ 13, 0x0e60, 0, {0x90,0x17,0x20,0xe4,0xf0,0x90,0x7f,0xec,0xe0,0xfa,0xba,0x01,0x1a} }, -{ 8, 0x0e6d, 0, {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x12} }, -{ 14, 0x0e75, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x90,0x17,0x21,0xf0,0xc0,0x03,0x12,0x04,0xe2} }, -{ 4, 0x0e83, 0, {0xd0,0x03,0x80,0x46} }, -{ 8, 0x0e87, 0, {0x90,0x7f,0xec,0xe0,0xfa,0xba,0x02,0x3e} }, -{ 8, 0x0e8f, 0, {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x36} }, -{ 13, 0x0e97, 0, {0xc0,0x03,0x12,0x04,0xef,0xd0,0x03,0x90,0x7f,0xea,0xe0,0xfa,0x90} }, -{ 5, 0x0ea4, 0, {0x17,0x22,0xf0,0x80,0x24} }, -{ 5, 0x0ea9, 0, {0xbb,0x12,0x02,0x80,0x17} }, -{ 5, 0x0eae, 0, {0xbb,0x81,0x02,0x80,0x0d} }, -{ 5, 0x0eb3, 0, {0xbb,0x83,0x02,0x80,0x08} }, -{ 5, 0x0eb8, 0, {0xbb,0x82,0x02,0x80,0x03} }, -{ 3, 0x0ebd, 0, {0xbb,0x84,0x05} }, -{ 5, 0x0ec0, 0, {0x12,0x06,0x4e,0x80,0x08} }, -{ 8, 0x0ec5, 0, {0x90,0x7f,0xb4,0x74,0x03,0xf0,0x80,0x06} }, -{ 6, 0x0ecd, 0, {0x90,0x7f,0xb4,0x74,0x02,0xf0} }, -{ 2, 0x0ed3, 0, {0xd0,0x86} }, -{ 14, 0x0ed5, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, -{ 13, 0x0ee3, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, -{ 11, 0x0ef0, 0, {0x90,0x7f,0xec,0xe0,0xf5,0x5a,0xc3,0x94,0x01,0x40,0x1d} }, -{ 7, 0x0efb, 0, {0xc3,0x74,0x07,0x95,0x5a,0x40,0x16} }, -{ 13, 0x0f02, 0, {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xc6,0xf5,0x82,0xe4,0x34} }, -{ 9, 0x0f0f, 0, {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0,0x80,0x22} }, -{ 7, 0x0f18, 0, {0xc3,0xe5,0x5a,0x94,0x81,0x40,0x1b} }, -{ 7, 0x0f1f, 0, {0xc3,0x74,0x87,0x95,0x5a,0x40,0x14} }, -{ 13, 0x0f26, 0, {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xb6,0xf5,0x82,0xe4,0x34} }, -{ 7, 0x0f33, 0, {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0} }, -{ 1, 0x0f3a, 0, {0x22} }, -{ 14, 0x0f3b, 0, {0x09,0x02,0xba,0x00,0x03,0x01,0x00,0x40,0x00,0x09,0x04,0x00,0x00,0x00} }, -{ 14, 0x0f49, 0, {0x01,0x01,0x00,0x00,0x09,0x24,0x01,0x00,0x01,0x3d,0x00,0x01,0x01,0x0c} }, -{ 14, 0x0f57, 0, {0x24,0x02,0x01,0x10,0x07,0x00,0x02,0x03,0x00,0x00,0x00,0x0d,0x24,0x06} }, -{ 14, 0x0f65, 0, {0x03,0x01,0x02,0x15,0x00,0x03,0x00,0x03,0x00,0x00,0x09,0x24,0x03,0x02} }, -{ 14, 0x0f73, 0, {0x01,0x01,0x00,0x01,0x00,0x09,0x24,0x03,0x04,0x02,0x03,0x00,0x03,0x00} }, -{ 14, 0x0f81, 0, {0x09,0x24,0x03,0x05,0x03,0x06,0x00,0x01,0x00,0x09,0x04,0x01,0x00,0x00} }, -{ 14, 0x0f8f, 0, {0x01,0x02,0x00,0x00,0x09,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00,0x07} }, -{ 14, 0x0f9d, 0, {0x24,0x01,0x02,0x01,0x01,0x00,0x0b,0x24,0x02,0x01,0x02,0x02,0x10,0x01} }, -{ 14, 0x0fab, 0, {0x80,0xbb,0x00,0x09,0x05,0x88,0x05,0x00,0x01,0x01,0x00,0x00,0x07,0x25} }, -{ 14, 0x0fb9, 0, {0x01,0x00,0x00,0x00,0x00,0x09,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00} }, -{ 14, 0x0fc7, 0, {0x07,0x05,0x82,0x02,0x40,0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00} }, -{ 14, 0x0fd5, 0, {0x09,0x04,0x02,0x01,0x03,0x00,0x00,0x00,0x00,0x07,0x05,0x82,0x02,0x40} }, -{ 14, 0x0fe3, 0, {0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00,0x09,0x05,0x89,0x05,0xa0} }, -{ 10, 0x0ff1, 0, {0x01,0x01,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00} }, -{ 14, 0x0ffb, 0, {0x12,0x01,0x00,0x01,0x00,0x00,0x00,0x40,0x47,0x05,0x99,0x99,0x00,0x01} }, -{ 14, 0x1009, 0, {0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x02,0xba} }, -{ 4, 0x1017, 0, {0x00,0x03,0x01,0x00} }, -{ 2, 0x101b, 0, {0x7a,0x00} }, -{ 3, 0x101d, 0, {0xba,0x05,0x00} }, -{ 2, 0x1020, 0, {0x50,0x17} }, -{ 8, 0x1022, 0, {0x90,0x7f,0xa5,0xe0,0xfb,0x30,0xe0,0x05} }, -{ 5, 0x102a, 0, {0x90,0x00,0x01,0x80,0x0d} }, -{ 10, 0x102f, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xe4} }, -{ 3, 0x1039, 0, {0x90,0x00,0x01} }, -{ 1, 0x103c, 0, {0x22} }, -{ 14, 0x103d, 0, {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0x00,0x7d} }, -{ 4, 0x104b, 0, {0x7e,0xeb,0x60,0x12} }, -{ 14, 0x104f, 0, {0x89,0x82,0x8a,0x83,0xe0,0xa3,0xa9,0x82,0xaa,0x83,0x8c,0x82,0x8d,0x83} }, -{ 4, 0x105d, 0, {0xf0,0x0c,0xdb,0xee} }, -{ 8, 0x1061, 0, {0x90,0x7d,0xc3,0xe0,0x90,0x7f,0xb9,0xf0} }, -{ 1, 0x1069, 0, {0x22} }, -{ 14, 0x106a, 0, {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0xc4,0x7d} }, -{ 4, 0x1078, 0, {0x7d,0xeb,0x60,0xe5} }, -{ 14, 0x107c, 0, {0x8c,0x82,0x8d,0x83,0xe0,0x0c,0x89,0x82,0x8a,0x83,0xf0,0xa3,0xa9,0x82} }, -{ 4, 0x108a, 0, {0xaa,0x83,0xdb,0xee} }, -{ 1, 0x108e, 0, {0x22} }, -{ 14, 0x108f, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x05,0x86,0x90,0x7d,0xc1,0xe0,0x05,0x86} }, -{ 14, 0x109d, 0, {0xa3,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0x05,0x86,0xa3,0xa3,0xe0,0xf9} }, -{ 5, 0x10ab, 0, {0x60,0x16,0xa3,0x05,0x86} }, -{ 13, 0x10b0, 0, {0x90,0x7f,0xa6,0x05,0x86,0xe0,0xa3,0x05,0x86,0xf0,0xc0,0x01,0x12} }, -{ 6, 0x10bd, 0, {0x10,0x1b,0xd0,0x01,0xd9,0xed} }, -{ 6, 0x10c3, 0, {0x90,0x7f,0xa5,0x74,0x40,0xf0} }, -{ 1, 0x10c9, 0, {0x22} }, -{ 8, 0x10ca, 0, {0x90,0x88,0x02,0x74,0x01,0xf0,0x7a,0x00} }, -{ 3, 0x10d2, 0, {0xba,0xff,0x00} }, -{ 2, 0x10d5, 0, {0x50,0x0a} }, -{ 10, 0x10d7, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} }, -{ 1, 0x10e1, 0, {0x22} }, -{ 5, 0x10e2, 0, {0xe5,0x6b,0xb4,0xc0,0x08} }, -{ 8, 0x10e7, 0, {0x90,0x88,0x03,0xe5,0x6c,0xf0,0x80,0x06} }, -{ 6, 0x10ef, 0, {0x90,0x88,0x02,0xe5,0x6c,0xf0} }, -{ 4, 0x10f5, 0, {0x7a,0x00,0x7b,0x00} }, -{ 11, 0x10f9, 0, {0xc3,0xea,0x94,0x32,0xeb,0x64,0x80,0x94,0x80,0x50,0x07} }, -{ 5, 0x1104, 0, {0x0a,0xba,0x00,0x01,0x0b} }, -{ 2, 0x1109, 0, {0x80,0xee} }, -{ 1, 0x110b, 0, {0x22} }, -{ 10, 0x110c, 0, {0x90,0x88,0x03,0xe5,0x6d,0xf0,0x05,0x39,0x7a,0x00} }, -{ 3, 0x1116, 0, {0xba,0x28,0x00} }, -{ 2, 0x1119, 0, {0x50,0x03} }, -{ 3, 0x111b, 0, {0x0a,0x80,0xf8} }, -{ 5, 0x111e, 0, {0xe5,0x39,0xb4,0x10,0x08} }, -{ 8, 0x1123, 0, {0x90,0x88,0x02,0x74,0xc0,0xf0,0x80,0x0e} }, -{ 5, 0x112b, 0, {0xe5,0x39,0xb4,0x20,0x09} }, -{ 9, 0x1130, 0, {0x90,0x88,0x02,0x74,0x80,0xf0,0x75,0x39,0x00} }, -{ 2, 0x1139, 0, {0x7a,0x00} }, -{ 3, 0x113b, 0, {0xba,0x28,0x00} }, -{ 2, 0x113e, 0, {0x50,0x03} }, -{ 3, 0x1140, 0, {0x0a,0x80,0xf8} }, -{ 1, 0x1143, 0, {0x22} }, -{ 4, 0x1144, 0, {0xe5,0x6f,0x60,0x02} }, -{ 2, 0x1148, 0, {0x80,0x07} }, -{ 7, 0x114a, 0, {0x7a,0x00,0x75,0x39,0x00,0x80,0x05} }, -{ 5, 0x1151, 0, {0x7a,0x40,0x75,0x39,0x10} }, -{ 9, 0x1156, 0, {0xe5,0x6e,0x2a,0xfa,0xe5,0x6e,0x25,0x39,0xf5} }, -{ 10, 0x115f, 0, {0x39,0x90,0x88,0x02,0x74,0x80,0x2a,0xf0,0x7a,0x00} }, -{ 8, 0x1169, 0, {0xc3,0xea,0x64,0x80,0x94,0xa8,0x50,0x03} }, -{ 3, 0x1171, 0, {0x0a,0x80,0xf5} }, -{ 1, 0x1174, 0, {0x22} }, -{ 6, 0x1175, 0, {0xaa,0x70,0xab,0x71,0xac,0x72} }, -{ 12, 0x117b, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x12,0x14,0xee,0xfd,0x60,0x18} }, -{ 13, 0x1187, 0, {0x8d,0x6d,0xc0,0x02,0xc0,0x03,0xc0,0x04,0x12,0x11,0x0c,0xd0,0x04} }, -{ 9, 0x1194, 0, {0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} }, -{ 2, 0x119d, 0, {0x80,0xdc} }, -{ 1, 0x119f, 0, {0x22} }, -{ 13, 0x11a0, 0, {0xe5,0x73,0xc4,0x54,0x0f,0xfa,0x53,0x02,0x0f,0xc3,0x74,0x09,0x9a} }, -{ 2, 0x11ad, 0, {0x50,0x06} }, -{ 6, 0x11af, 0, {0x74,0x37,0x2a,0xfb,0x80,0x04} }, -{ 4, 0x11b5, 0, {0x74,0x30,0x2a,0xfb} }, -{ 12, 0x11b9, 0, {0x8b,0x6d,0xc0,0x03,0x12,0x11,0x0c,0xd0,0x03,0xaa,0x73,0x53} }, -{ 8, 0x11c5, 0, {0x02,0x0f,0xc3,0x74,0x09,0x9a,0x50,0x06} }, -{ 6, 0x11cd, 0, {0x74,0x37,0x2a,0xfb,0x80,0x04} }, -{ 4, 0x11d3, 0, {0x74,0x30,0x2a,0xfb} }, -{ 5, 0x11d7, 0, {0x8b,0x6d,0x12,0x11,0x0c} }, -{ 1, 0x11dc, 0, {0x22} }, -{ 7, 0x11dd, 0, {0x90,0x7d,0xc3,0xe0,0xfa,0x60,0x0f} }, -{ 12, 0x11e4, 0, {0x90,0x7d,0xc1,0xe0,0xf5,0x6e,0x90,0x7d,0xc2,0xe0,0xf5,0x6f} }, -{ 3, 0x11f0, 0, {0x12,0x11,0x44} }, -{ 12, 0x11f3, 0, {0x90,0x7d,0xff,0xe4,0xf0,0x75,0x70,0xc4,0x75,0x71,0x7d,0x75} }, -{ 5, 0x11ff, 0, {0x72,0x01,0x12,0x11,0x75} }, -{ 1, 0x1204, 0, {0x22} }, -{ 2, 0x1205, 0, {0x7a,0x04} }, -{ 3, 0x1207, 0, {0xba,0x40,0x00} }, -{ 2, 0x120a, 0, {0x50,0x36} }, -{ 14, 0x120c, 0, {0xea,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfb,0x7c,0x00} }, -{ 3, 0x121a, 0, {0xbc,0x08,0x00} }, -{ 2, 0x121d, 0, {0x50,0x20} }, -{ 6, 0x121f, 0, {0x8b,0x05,0xed,0x30,0xe7,0x0b} }, -{ 11, 0x1225, 0, {0x90,0x7f,0x96,0x74,0x42,0xf0,0x74,0xc3,0xf0,0x80,0x08} }, -{ 8, 0x1230, 0, {0x90,0x7f,0x96,0xe4,0xf0,0x74,0x81,0xf0} }, -{ 7, 0x1238, 0, {0xeb,0x25,0xe0,0xfb,0x0c,0x80,0xdb} }, -{ 3, 0x123f, 0, {0x0a,0x80,0xc5} }, -{ 1, 0x1242, 0, {0x22} }, -{ 4, 0x1243, 0, {0x7a,0x00,0x7b,0xef} }, -{ 3, 0x1247, 0, {0xba,0x10,0x00} }, -{ 2, 0x124a, 0, {0x50,0x20} }, -{ 14, 0x124c, 0, {0x74,0x11,0x2b,0xfb,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0x8c,0x82,0x8d} }, -{ 14, 0x125a, 0, {0x83,0xe4,0xf0,0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe4} }, -{ 4, 0x1268, 0, {0xf0,0x0a,0x80,0xdb} }, -{ 1, 0x126c, 0, {0x22} }, -{ 14, 0x126d, 0, {0x74,0xf8,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, -{ 14, 0x127b, 0, {0x74,0xf9,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, -{ 14, 0x1289, 0, {0x74,0xfa,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, -{ 14, 0x1297, 0, {0x74,0xfb,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, -{ 14, 0x12a5, 0, {0x74,0xff,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, -{ 1, 0x12b3, 0, {0x22} }, -{ 14, 0x12b4, 0, {0x12,0x03,0xcb,0x12,0x12,0x6d,0x7a,0xc0,0x7b,0x87,0x7c,0x01,0x74,0x01} }, -{ 14, 0x12c2, 0, {0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74} }, -{ 14, 0x12d0, 0, {0x01,0x12,0x14,0xbf,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e} }, -{ 14, 0x12de, 0, {0x83,0x8f,0xf0,0x74,0x06,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b} }, -{ 14, 0x12ec, 0, {0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74} }, -{ 14, 0x12fa, 0, {0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0} }, -{ 14, 0x1308, 0, {0x74,0x0b,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07} }, -{ 14, 0x1316, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74,0x08,0x12,0x14,0xbf,0x74,0x01,0x2d} }, -{ 14, 0x1324, 0, {0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x01} }, -{ 14, 0x1332, 0, {0x12,0x14,0xbf,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83} }, -{ 14, 0x1340, 0, {0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74,0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f} }, -{ 14, 0x134e, 0, {0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x03,0x12,0x14,0xbf,0x7d,0x00} }, -{ 3, 0x135c, 0, {0xbd,0x06,0x00} }, -{ 2, 0x135f, 0, {0x50,0x12} }, -{ 11, 0x1361, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x0a,0xba,0x00,0x01,0x0b} }, -{ 7, 0x136c, 0, {0xe4,0x12,0x14,0xbf,0x0d,0x80,0xe9} }, -{ 13, 0x1373, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe5,0x74,0x12,0x14,0xbf,0x74,0xf9} }, -{ 14, 0x1380, 0, {0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x0f,0xf0,0x74} }, -{ 14, 0x138e, 0, {0xfe,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x01,0xf0} }, -{ 6, 0x139c, 0, {0x12,0x03,0xe1,0x12,0x04,0xf7} }, -{ 1, 0x13a2, 0, {0x22} }, -{ 13, 0x13a3, 0, {0x90,0x7d,0xc1,0xe0,0xfa,0x24,0x00,0xfb,0xe4,0x34,0x19,0xfc,0x90} }, -{ 14, 0x13b0, 0, {0x7d,0xc2,0xe0,0xfd,0x8b,0x82,0x8c,0x83,0xf0,0x75,0xf0,0x11,0xea,0xa4} }, -{ 3, 0x13be, 0, {0xfa,0x7b,0x00} }, -{ 3, 0x13c1, 0, {0xbb,0x10,0x00} }, -{ 2, 0x13c4, 0, {0x50,0x24} }, -{ 14, 0x13c6, 0, {0xea,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0xeb,0x2c,0xfc,0xe4,0x3d,0xfd} }, -{ 14, 0x13d4, 0, {0x74,0x04,0x2b,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfe} }, -{ 8, 0x13e2, 0, {0x8c,0x82,0x8d,0x83,0xf0,0x0b,0x80,0xd7} }, -{ 14, 0x13ea, 0, {0xea,0x24,0x00,0xfa,0xe4,0x34,0x18,0xfb,0x74,0x10,0x2a,0xf5,0x82,0xe4} }, -{ 5, 0x13f8, 0, {0x3b,0xf5,0x83,0xe4,0xf0} }, -{ 1, 0x13fd, 0, {0x22} }, -{ 4, 0x13fe, 0, {0xe5,0x76,0x60,0x02} }, -{ 2, 0x1402, 0, {0x80,0x16} }, -{ 12, 0x1404, 0, {0x74,0x0f,0x55,0x75,0xfa,0x8a,0x75,0x24,0x00,0xf5,0x82,0xe4} }, -{ 10, 0x1410, 0, {0x34,0x19,0xf5,0x83,0xe0,0xf5,0x74,0x12,0x12,0xb4} }, -{ 10, 0x141a, 0, {0x12,0x10,0xca,0x75,0x6e,0x00,0x75,0x6f,0x00,0x12} }, -{ 6, 0x1424, 0, {0x11,0x44,0x75,0x70,0xb9,0x75} }, -{ 6, 0x142a, 0, {0x71,0x14,0x75,0x72,0x02,0x12} }, -{ 11, 0x1430, 0, {0x11,0x75,0xe5,0x76,0xb4,0x02,0x04,0x74,0x01,0x80,0x01} }, -{ 1, 0x143b, 0, {0xe4} }, -{ 3, 0x143c, 0, {0xfa,0x70,0x0f} }, -{ 12, 0x143f, 0, {0x74,0x01,0x25,0x75,0xf5,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0} }, -{ 3, 0x144b, 0, {0x02,0x80,0x0a} }, -{ 10, 0x144e, 0, {0x85,0x75,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0,0x02} }, -{ 12, 0x1458, 0, {0x75,0x6e,0x00,0x75,0x6f,0x01,0xc0,0x02,0x12,0x11,0x44,0xd0} }, -{ 4, 0x1464, 0, {0x02,0xea,0x70,0x1a} }, -{ 13, 0x1468, 0, {0x75,0xf0,0x11,0xe5,0x75,0xa4,0xfa,0x24,0x00,0xfa,0xe4,0x34,0x18} }, -{ 9, 0x1475, 0, {0xfb,0x8a,0x70,0x8b,0x71,0x75,0x72,0x01,0x12} }, -{ 4, 0x147e, 0, {0x11,0x75,0x80,0x36} }, -{ 2, 0x1482, 0, {0x7a,0x00} }, -{ 3, 0x1484, 0, {0xba,0x10,0x00} }, -{ 2, 0x1487, 0, {0x50,0x2f} }, -{ 13, 0x1489, 0, {0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe0,0xfb,0xe5} }, -{ 4, 0x1496, 0, {0x75,0xb5,0x03,0x1b} }, -{ 14, 0x149a, 0, {0x75,0xf0,0x11,0xea,0xa4,0xfb,0x24,0x00,0xfb,0xe4,0x34,0x18,0xfc,0x8b} }, -{ 9, 0x14a8, 0, {0x70,0x8c,0x71,0x75,0x72,0x01,0xc0,0x02,0x12} }, -{ 4, 0x14b1, 0, {0x11,0x75,0xd0,0x02} }, -{ 3, 0x14b5, 0, {0x0a,0x80,0xcc} }, -{ 1, 0x14b8, 0, {0x22} }, -{ 6, 0x14b9, 0, {0x50,0x72,0x6f,0x67,0x20,0x00} }, -{ 14, 0x14bf, 0, {0xc8,0xc0,0xe0,0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0b,0x14,0x60,0x0f,0x14} }, -{ 7, 0x14cd, 0, {0x60,0x11,0x14,0x60,0x12,0x80,0x15} }, -{ 7, 0x14d4, 0, {0xd0,0xe0,0xa8,0x82,0xf6,0x80,0x0e} }, -{ 5, 0x14db, 0, {0xd0,0xe0,0xf0,0x80,0x09} }, -{ 4, 0x14e0, 0, {0xd0,0xe0,0x80,0x05} }, -{ 5, 0x14e4, 0, {0xd0,0xe0,0xa8,0x82,0xf2} }, -{ 4, 0x14e9, 0, {0xc8,0xd0,0xe0,0xc8} }, -{ 1, 0x14ed, 0, {0x22} }, -{ 14, 0x14ee, 0, {0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0d,0x14,0x60,0x0f,0x14,0x60,0x0f,0x14} }, -{ 6, 0x14fc, 0, {0x60,0x10,0x74,0xff,0x80,0x0f} }, -{ 5, 0x1502, 0, {0xa8,0x82,0xe6,0x80,0x0a} }, -{ 3, 0x1507, 0, {0xe0,0x80,0x07} }, -{ 4, 0x150a, 0, {0xe4,0x93,0x80,0x03} }, -{ 3, 0x150e, 0, {0xa8,0x82,0xe2} }, -{ 4, 0x1511, 0, {0xf8,0xd0,0xe0,0xc8} }, -{ 1, 0x1515, 0, {0x22} }, -{ 0, 0x0000, 1, {0} } - -}; - -static unsigned char bitstream[] = { - -0x00,0x09,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0, 0x0F,0xF0,0x00,0x00,0x01,0x61,0x00,0x0D, -0x64,0x61,0x62,0x75,0x73,0x62,0x74,0x72, 0x2E,0x6E,0x63,0x64,0x00,0x62,0x00,0x0B, -0x73,0x31,0x30,0x78,0x6C,0x76,0x71,0x31, 0x30,0x30,0x00,0x63,0x00,0x0B,0x31,0x39, -0x39,0x39,0x2F,0x30,0x39,0x2F,0x32,0x34, 0x00,0x64,0x00,0x09,0x31,0x30,0x3A,0x34, -0x32,0x3A,0x34,0x36,0x00,0x65,0x00,0x00, 0x2E,0xC0,0xFF,0x20,0x17,0x5F,0x9F,0x5B, -0xFE,0xFB,0xBB,0xB7,0xBB,0xBB,0xFB,0xBF, 0xAF,0xEF,0xFB,0xDF,0xB7,0xFB,0xFB,0x7F, -0xBF,0xB7,0xEF,0xF2,0xFF,0xFB,0xFE,0xFF, 0xFF,0xEF,0xFF,0xFE,0xFF,0xBF,0xFF,0xFF, -0xFF,0xFF,0xAF,0xFF,0xFA,0xFF,0xFF,0xFF, 0xC9,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFB,0xFF,0xA3,0xFF,0xFB, -0xFE,0xFF,0xBF,0xEF,0xE3,0xFE,0xFF,0xBF, 0xE3,0xFE,0xFF,0xBF,0x6F,0xFB,0xF6,0xFF, -0xBF,0xFF,0x47,0xFF,0xFF,0x9F,0xEE,0xF9, 0xFE,0xCF,0x9F,0xEF,0xFB,0xCF,0x9B,0xEE, -0xF8,0xFE,0xEF,0x8F,0xEE,0xFB,0xFE,0x0B, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xBF,0xFF,0xFF,0xFB,0xFF,0xFF, 0xBF,0xFF,0xFF,0xFC,0x17,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xFB,0xFF,0xFF,0x7F,0xFF,0xFF, -0xFC,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x5F,0xFF, 0xFF,0xFD,0xFF,0xFF,0xDB,0xFF,0xFD,0xFF, -0x77,0xFF,0xFD,0xFF,0xFF,0xDF,0xFE,0xFD, 0xFF,0xFF,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1, -0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xE3,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF, -0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x67,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0x7F,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF, 0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x2F,0xFF, -0xF3,0xFD,0xFF,0x7F,0xDE,0xF7,0xFD,0xFF, 0x7F,0xF7,0x7D,0xFF,0x7F,0xDF,0xF7,0xBD, -0xFF,0x7F,0xFF,0x1F,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xEF,0xFB, -0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF, 0x3F,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F, -0x9F,0xE7,0xFA,0x7F,0x9F,0xE7,0xF9,0xFE, 0x7F,0x9F,0xE7,0xFF,0xFC,0x7F,0xBF,0xBF, -0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xB7, 0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, -0xFF,0xE0,0xFD,0xF9,0xFE,0x7F,0x9F,0xE7, 0xF9,0xFE,0x7F,0x9D,0xF9,0xFE,0x7D,0x9D, -0xE7,0xF9,0xFE,0x7F,0x9F,0xED,0xED,0xFF, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, -0xDF,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF, 0x7F,0xDF,0xFF,0x9B,0xFF,0xEF,0xFB,0xFE, -0xFB,0xBF,0xEF,0xBB,0xFE,0xFF,0xAF,0xBB, 0xBE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF, -0xB7,0xBF,0xDB,0xF6,0xBD,0xBF,0x6B,0xDB, 0xF6,0xF9,0xBF,0x5B,0xD6,0xF9,0xBF,0x6F, -0xDB,0xF6,0xFD,0xBF,0xFF,0x0E,0xFF,0xFF, 0xFF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0x7F, -0xF7,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xDF,0x9F,0xFF,0xFF,0xFF,0xFE,0xFF, -0xFF,0xEF,0xFE,0xFE,0xFF,0xFF,0x77,0xFF, 0xFB,0xFB,0xFF,0xFF,0xFF,0xFF,0xF8,0x3F, -0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xF4,0x7F,0xFF,0xFE,0xFD, 0xBE,0xFF,0xDF,0xFE,0xFF,0xFF,0xEF,0x7F, -0xFF,0xCF,0xFF,0xCF,0xFF,0xFF,0xFF,0xDF, 0xE6,0xFF,0xFF,0x7F,0xDF,0xF7,0xDD,0x7F, -0x7F,0xDF,0xF7,0xFF,0x7F,0xDF,0xD7,0xFD, 0xFF,0x7F,0xDF,0xF7,0xFF,0xCD,0xFF,0xF2, -0xFF,0xFF,0x4F,0x7F,0xF4,0xFF,0xFF,0xFF, 0xE7,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xBB,0xFF,0xEF,0xFF,0xFE,0xFF, 0xFF,0xFF,0xEF,0xFF,0xFF,0xEF,0xFF,0xFB, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x65, 0xEF,0xFF,0xFF,0x7F,0xFF,0xFD,0xEF,0xFF, -0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xCF,0xDF,0xFE,0xFF, -0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xF3,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFE,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xBF,0xFF, 0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xEF,0xEB,0xFF,0xFE,0xBF,0xFF, 0xEB,0xFF,0xFC,0x7F,0xFF,0xFF,0xFF,0xEE, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, 0xD6,0xFF,0xFD,0xBF,0xFF,0xFB,0xFF,0xFE, -0xFD,0xFF,0xFF,0xFD,0xEF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0x7F,0xBF, 0xFF,0x5F,0xDF,0xFF,0xFF,0xBF,0x77,0xFF, -0xFF,0xFF,0x7F,0xD7,0xFF,0xFF,0xFF,0xFF, 0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xDF,0xEF, -0xFF,0xFF,0xFE,0xFB,0xFF,0xFF,0xDF,0xBF, 0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xB7,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xAF,0x7F,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xDF,0xBF,0xDF,0xF3,0xFD,0xFB,0xFF,0x5B, -0xFD,0xFF,0xBF,0xEF,0xF7,0xFF,0xFF,0x7D, 0xFF,0xFF,0xFF,0xFF,0xF8,0x3B,0xFF,0xBF, -0x6F,0xFF,0xFE,0xFF,0xBF,0xFF,0xEB,0x7D, 0xFF,0xEF,0xFB,0xFE,0xFF,0xFF,0xFF,0xFF, -0xFF,0xF2,0x7F,0xFC,0xFF,0x3F,0xDF,0xED, 0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0x5F,0xF7, -0xB5,0xFF,0xEF,0xFF,0xFF,0xFF,0xE0,0x3F, 0x9F,0x9E,0xFF,0xFF,0xEF,0xFF,0xDF,0xFF, -0xBF,0x5F,0xBF,0xCF,0xF3,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0x69,0xAF,0x33,0xFD,0xFF, -0xFB,0xFF,0xFF,0xFF,0xFF,0xFC,0xFF,0x7F, 0xD9,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xF5, -0xA3,0xDF,0x6E,0xDE,0xFF,0xFF,0xBD,0xFF, 0xFF,0xFE,0xFF,0xFF,0xFF,0xFE,0xE7,0xFD, -0xFF,0xFF,0xFF,0xF9,0xEF,0xC6,0xFE,0xB7, 0xAD,0xE5,0xF9,0xFF,0xFF,0xFF,0xCF,0xFF, -0xFF,0xFF,0xCD,0xFB,0x7F,0xFF,0xFF,0xFF, 0xF9,0xF6,0x0F,0xDF,0xEC,0xCF,0x7F,0xFF, -0xFB,0x7F,0xFF,0xFF,0xFF,0xFD,0xFF,0xFE, 0xF9,0xFD,0x7F,0xFF,0x7F,0xFF,0xF9,0x5B, -0xFF,0x73,0xDC,0xFD,0x7B,0xDF,0xFF,0xFF, 0xFF,0x7B,0xFF,0xFF,0xF7,0x53,0xD6,0xFF, -0xFF,0xFF,0xFF,0xD8,0x9F,0xFE,0xFF,0xEF, 0x7F,0xEE,0xFF,0xFF,0xFF,0xFB,0xED,0xED, -0xFD,0xFF,0xFE,0xFF,0xFF,0xFB,0x7F,0xFF, 0xE2,0x7F,0xFF,0x6F,0xD8,0x57,0xF7,0xFF, -0xFF,0xFF,0xDF,0xFF,0xE8,0xFF,0xFF,0xFD, 0xFF,0xFF,0xFC,0x7F,0xFF,0xE4,0xFF,0xFB, -0xEF,0xFB,0xFE,0xDF,0xB7,0xED,0xFF,0xFE, 0xDF,0x7F,0xFF,0xFE,0x7F,0xB7,0xFF,0xFF, -0xFF,0xFF,0x89,0xFF,0xFF,0xCF,0xF3,0xFE, 0x7F,0xFF,0xEF,0xFF,0xFE,0x7E,0x7F,0xFB, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1, 0xFF,0xEB,0x7A,0xD5,0xBF,0x6F,0xDB,0xBE, -0xFD,0xB7,0xD8,0xF6,0xE5,0xBF,0x6F,0xFB, 0xFE,0xF5,0xBD,0x7E,0x06,0xFF,0xDF,0xF7, -0xFB,0xF6,0xFF,0x3F,0xFF,0xDB,0xFF,0xFF, 0x6F,0xFB,0xF7,0xFF,0xFF,0xFF,0xFB,0xFE, -0xF7,0xAF,0xFF,0xB7,0xED,0xEF,0xF7,0xFE, 0xFF,0xFF,0xDF,0xFF,0xFE,0xFF,0xEF,0xFF, -0xFF,0xFF,0xFF,0xBF,0xF7,0xFC,0x1F,0xEE, 0xFB,0xFE,0xBD,0xFF,0x7F,0x5F,0xD7,0xFD, -0xFB,0x43,0xFF,0xFF,0xFD,0xFF,0x5F,0xFF, 0xF7,0xFF,0xF9,0x3F,0xFF,0xCF,0xF3,0xFD, -0xF7,0x7E,0xEF,0xA7,0xF9,0xFE,0x8F,0xA7, 0xE9,0xF3,0x7E,0x9F,0xFB,0xF8,0xFF,0xFF, -0x3F,0xFD,0x7F,0x5F,0xDF,0xFD,0xFF,0xFF, 0x5F,0xFF,0xFD,0x5F,0xFF,0xFF,0x7F,0xFD, -0x7F,0xFD,0x9F,0xFF,0xE0,0xFF,0xFA,0xF8, 0xBE,0x6F,0x9F,0xE6,0xF8,0xBE,0x3F,0x9A, -0xF9,0xBE,0x6F,0x9F,0xE2,0xF9,0xFE,0x6F, 0x9F,0xF9,0xFF,0xF5,0xFD,0x7F,0xCF,0xDF, -0xFD,0xFD,0x7F,0xFF,0xF5,0xFF,0xFF,0xFF, 0xF7,0xF5,0xFD,0x0F,0xDB,0xFF,0xD3,0xFF, -0xEB,0xFA,0xFF,0xFF,0xBF,0xFF,0xFA,0xFF, 0xFF,0xCB,0xFB,0xFE,0xFF,0xFF,0xEB,0xFA, -0xFE,0xFF,0xFF,0xB7,0xFF,0xFF,0xFF,0xFF, 0xBF,0xFF,0xDF,0xF5,0xFF,0xFF,0xD7,0xFF, -0xFF,0xFF,0xDF,0xD7,0xF5,0xFF,0x7F,0xFE, 0x4F,0xFF,0xFD,0xFF,0x7F,0x7F,0xFF,0xAD, -0xEB,0xFB,0xFF,0xAD,0xFF,0xFF,0xFF,0xFF, 0xAF,0xEB,0xFB,0xFF,0xFC,0x0D,0xFF,0xFF, -0xDF,0xD2,0xFD,0xFF,0xFF,0xFD,0xF6,0xFF, 0xFF,0x7F,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF, -0xFF,0xFB,0x3F,0x7D,0xEB,0x32,0xFE,0xBF, 0x2F,0xEB,0xFA,0xAE,0xBD,0xE0,0xFA,0x7E, -0xBF,0xAD,0xEB,0xFA,0xFE,0xBF,0xF5,0x7F, 0xFF,0xDE,0xFE,0xE3,0xFB,0xFF,0xFF,0xFF, -0xDF,0xEF,0x4F,0xDF,0xFF,0x7F,0xDF,0xFF, 0xF7,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xEF, -0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xDF, 0xED,0xFB,0xDF,0xFF,0xBF,0xFF,0xFF,0xFF, -0x81,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF, 0xFF,0xFF,0xFE,0xDD,0xFE,0xEF,0xFD,0xFF, -0xFF,0xFB,0xFE,0xF7,0xFF,0x93,0xFD,0xFB, 0x7E,0xFF,0xFE,0x87,0xE9,0xFF,0x7F,0xB3, -0x9F,0xFE,0xFE,0xFF,0xAF,0xFD,0xFE,0x7E, 0x3F,0xFE,0x67,0xFF,0xFF,0xF7,0xFF,0xFF, -0xFC,0xF7,0xDF,0xFD,0xFF,0x7F,0xFF,0xFF, 0x7F,0x6D,0xFF,0xFF,0xFE,0xFF,0xFF,0x2F, -0xFF,0xBF,0xFF,0xFF,0xEE,0xFF,0xBE,0xFF, 0xFF,0xFE,0xFF,0xEF,0xFF,0xFF,0xFE,0xFF, -0xEF,0xFF,0xFF,0xFA,0x5F,0xFF,0xFF,0xFB, 0xFF,0xFF,0xEF,0xFF,0xFB,0xFE,0xFD,0xFF, -0xFE,0xFF,0xFB,0xFF,0xFF,0xFF,0x7F,0xFF, 0xFE,0xBF,0xDF,0xFF,0xFB,0xFF,0xFF,0xF7, -0xFC,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0x7F,0xFF, -0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, 0xF3,0xFF,0xFF,0xFF,0xEF,0xFB,0xFF,0xFF, -0xFF,0xDF,0xE2,0xFF,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFB,0xE7,0xFF,0xFD, -0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xED, 0xEF,0xFD,0xFF,0xFF,0xDF,0xD7,0xF5,0xFD, -0x7F,0x5D,0xFD,0xFF,0x7F,0xDF,0x97,0xF4, 0xFD,0x7B,0x5F,0xFF,0xC9,0xFF,0xFB,0xFE, -0xFF,0xBF,0xFF,0x5F,0xFF,0xFF,0xF7,0xFF, 0xEF,0xFD,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xF7,0xFF,0xD7,0xFD,0x7D,0x7F,0xFF, 0xFF,0xFF,0xFF,0xEF,0xDF,0xF7,0xFD,0xFF, -0xBB,0xFF,0xFF,0x7F,0xFF,0xFE,0xE3,0xFF, 0xF9,0xFE,0x7F,0xBF,0xEF,0xFB,0xFE,0xFF, -0xBF,0xF9,0xFE,0xFF,0x9F,0xEF,0xF9,0xFE, 0xFF,0xBF,0xF3,0xDA,0xFF,0x37,0xCD,0xF3, -0x7C,0xDF,0x37,0xCD,0xF3,0x7F,0x37,0xCD, 0xF3,0x7C,0xDF,0x37,0xCC,0xF3,0x7F,0x5A, -0xBD,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFD, 0xBF,0x6F,0xDE,0xFD,0xBF,0x6F,0xDB,0xF6, -0xFD,0xBF,0x6F,0xFE,0xF1,0x6F,0xEB,0x7A, 0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7,0xAF, -0x7A,0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7, 0xFF,0x7E,0xFF,0xFE,0xCD,0xB3,0x6C,0xDB, -0x36,0xCD,0xB3,0x6C,0xDE,0xCD,0xB3,0x6C, 0xDB,0x36,0xCD,0xB3,0x6C,0xDF,0xC9,0xBF, -0xF7,0xBD,0xEF,0x7A,0x9E,0xA7,0xA9,0xEA, 0x7A,0xB7,0xBD,0xEA,0x7B,0xDE,0xA7,0xBD, -0xCA,0x72,0x8D,0x91,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFE,0xF7,0xEF,0xFB, -0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFE, 0x87,0xFF,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6, -0xFD,0xBF,0x6F,0xF6,0xFD,0xBF,0x6F,0xDB, 0xF6,0xFD,0xBF,0x6F,0xFE,0x4F,0xFF,0xBF, -0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB,0xEF, 0xBE,0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB, -0xEF,0xFC,0x5F,0xFF,0xFF,0xFF,0x3F,0xCF, 0xF3,0xFC,0xFF,0x3F,0xCF,0xFC,0xFF,0x3F, -0xCF,0xF3,0xFC,0xFF,0x3F,0xCF,0xFD,0x9F, 0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF, -0xEB,0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF, 0xAF,0xEB,0xFF,0xE1,0x6F,0xFD,0xFF,0x7F, -0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFD,0xFF, 0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF, -0x7A,0xBF,0xFB,0xFE,0xDF,0xB7,0xED,0xFB, 0x7E,0xDF,0xB7,0xFB,0x7E,0xDF,0xB7,0xED, -0xFB,0x7E,0xDF,0xB7,0xFF,0xC9,0xFF,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, -0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEE, 0xFB,0xFE,0xBB,0xFF,0xFE,0xFF,0xBF,0xEF, -0xFB,0xFE,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0x3F,0xCF,0xFF,0xE7, -0xFE,0xFF,0xF5,0xFD,0x77,0x5D,0xD7,0x35, 0xDD,0x77,0xD7,0xF5,0xCD,0x7B,0x5D,0xD7, -0xF5,0xDD,0x77,0xFE,0x27,0xFF,0xFF,0x8B, 0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9,0xAF, -0x8B,0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9, 0xFE,0x1F,0xFF,0x5F,0xD7,0xF5,0xFD,0x7F, -0x5F,0xD7,0xF5,0xFF,0x5F,0xD7,0xF5,0xFD, 0x7F,0x5F,0xD7,0xF5,0xFF,0xFA,0x3F,0xFE, -0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xEB, 0xEC,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF, -0xEB,0xFF,0xFE,0x7F,0xFD,0x7F,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6, 0xFF,0xFA,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF, -0xF7,0xFC,0xFF,0xDF,0xF7,0xFD,0xFF,0x7F, 0xDF,0xF7,0xFD,0xFF,0xF5,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0x02,0xFF,0xFE,0xBF,0xAB,0xEB,0xFA, 0xBE,0xBF,0x23,0xEB,0xDE,0x1F,0xAF,0xEA, -0xFA,0xFE,0xAF,0xAF,0xEB,0xFD,0x97,0xFF, 0xF3,0xFC,0x7B,0x1F,0xCF,0xF1,0xFC,0x7F, -0x1F,0xF1,0xFC,0x77,0x1F,0xCD,0xF1,0xFC, 0xFF,0x1F,0xFE,0x87,0xFF,0xAF,0xEF,0xFA, -0xFE,0xFF,0xAF,0xEF,0xFA,0xFD,0xBF,0x2B, 0xFB,0x7E,0xBF,0xBF,0xEB,0xFB,0xFB,0xFB, -0xDF,0xFF,0xFB,0xF7,0xFF,0xFF,0x7F,0xF7, 0xF7,0xFF,0xFD,0xDF,0xFE,0xFC,0xDF,0xFF, -0xDF,0xFF,0xFD,0xFF,0xDA,0xBF,0xFF,0xBB, 0xEF,0xFB,0xF9,0xFF,0xBE,0xEF,0xFB,0xFB, -0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xF7,0x7F,0xFD,0xD7,0xFF,0xFF,0x7F, -0xFF,0xFF,0xFF,0xFE,0xF7,0xFF,0xFE,0xFF, 0xF7,0xFF,0xFF,0x7F,0xFF,0xFF,0xEC,0xFF, -0xFF,0xFE,0xDF,0xBF,0xFF,0xFB,0xFE,0xFF, 0xBB,0x68,0xAE,0x1F,0xAE,0xFB,0xFB,0xFF, -0xFF,0xBF,0xFF,0xD5,0xFF,0x7F,0xFF,0xFF, 0xF7,0xFE,0xFE,0xFF,0xBF,0xEF,0x9F,0xFD, -0x7F,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF,0xFF, 0xBB,0xF7,0xBF,0xFF,0xFF,0xFF,0xFF,0xDF, -0xFF,0xBF,0xFB,0xFF,0xFF,0xFF,0xDE,0x3F, 0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0xFF,0xFF, -0xFF,0xFF,0xEF,0xFF,0x7F,0xFB,0xFD,0xFB, 0x7F,0xFF,0xFF,0xFF,0xFF,0xCF,0xF3,0x7C, -0xFF,0x7F,0x8D,0x7F,0xFF,0xFF,0xFF,0xFF, 0xFB,0xFF,0xF7,0xFB,0xFE,0xFD,0xFF,0xFF, -0xFF,0xFF,0xF7,0xFD,0xFF,0x7F,0xFD,0x1F, 0xFD,0xFF,0xFF,0xFF,0xFF,0xBF,0xDF,0xFF, -0xFF,0xFE,0x5C,0xFF,0x6D,0xFF,0x7F,0xAB, 0xE7,0xF1,0xFF,0xFD,0x9F,0xFF,0xFF,0xAD, -0xEB,0x7A,0x3F,0x1F,0xFF,0xFF,0xFE,0xBF, 0xAF,0xF3,0xDE,0xF5,0xFF,0x8F,0xFB,0xDF, -0xE6,0x7F,0xFF,0xDF,0xF3,0xFD,0xFF,0x7E, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xF7,0xF3, -0x7F,0xDF,0xF7,0xEF,0xFF,0xF6,0x3F,0x9F, 0xDF,0xFF,0xFF,0xEE,0xFF,0xFF,0xEF,0xFB, -0xFF,0xFF,0xF9,0xFB,0xFE,0x4F,0xBF,0xEF, 0xBB,0xFF,0x69,0xAF,0xAF,0xFC,0xFF,0x3F, -0xDD,0xFF,0xFC,0xBF,0x8F,0xFF,0xFD,0xF3, 0xBF,0xED,0x9E,0xFC,0xBF,0x6F,0xF5,0xD3, -0xDF,0xFF,0xDB,0xD6,0xF5,0xEF,0xFD,0xFE, 0xFF,0xB9,0xFF,0x1F,0xD2,0xA9,0xAF,0xFF, -0xDB,0xF7,0xBF,0xEF,0x46,0xFF,0xFF,0xAD, 0xEB,0x7A,0xDF,0xEF,0xF7,0xFF,0x7F,0xF7, -0x9F,0xED,0xFF,0x7F,0xFF,0xAD,0xEB,0x7F, 0xF5,0x6F,0xFF,0xFD,0xFB,0xD6,0xF4,0xF7, -0xFB,0xF9,0x7E,0x7F,0xFF,0x5F,0xC2,0xFE, 0xBF,0xFD,0xFB,0x33,0xDF,0xF9,0x5B,0xFF, -0xFF,0xDD,0x67,0x7D,0xCF,0xEF,0xDB,0xEC, 0xFF,0x77,0xDD,0xF7,0xFD,0xFF,0xFF,0xDE, -0xA7,0xBF,0xD4,0x9F,0xFF,0xFF,0xBF,0xEF, 0xFE,0xFF,0xDF,0xEF,0xBB,0xFF,0xFF,0xEF, -0xEB,0xFA,0xFF,0xEF,0xBD,0xFB,0xFF,0xE2, 0x7F,0xFF,0xDF,0xDF,0xF7,0xFD,0xBF,0xBB, -0x73,0xF7,0xFD,0x7F,0xDF,0xDE,0xF7,0xBF, 0xEA,0xDB,0xF6,0xFF,0xD6,0xFF,0xFF,0x66, -0xFF,0xBE,0xFF,0xBF,0x6B,0xD9,0xF6,0xDF, 0xFF,0xFB,0x7E,0x7F,0xB7,0x7E,0xFF,0xFE, -0xFF,0xCD,0xFF,0xFE,0x7F,0xFF,0xFC,0xFD, 0x3F,0xFB,0xFB,0xF7,0xFF,0xFF,0xFB,0xF6, -0x7D,0xFE,0x7F,0xFF,0xFC,0xFF,0xB9,0xFF, 0xF9,0xFA,0xFE,0xBF,0xAF,0x5B,0xD6,0xED, -0xAD,0x7B,0xF6,0xF9,0xBF,0xEF,0xF8,0xFA, 0xFE,0xBF,0xFE,0xE6,0xFF,0xFF,0xF7,0xFD, -0xFF,0x7F,0xBF,0xEF,0xF3,0xFF,0xFF,0x6F, 0xF7,0xFE,0xFF,0xFF,0xF7,0xFD,0xFE,0xF7, -0xEF,0xFF,0xFB,0xEF,0xFB,0x7E,0xDE,0xFE, 0xFF,0xBF,0xFF,0xFE,0xFF,0xFF,0xFB,0xFF, -0xFF,0xEF,0xFB,0x6F,0xFC,0x1F,0xFE,0xE7, 0xFF,0xFF,0xFF,0xEF,0xFF,0xD3,0xB4,0xBB, -0xFF,0xFF,0xFD,0xBF,0x6F,0xE3,0xFE,0xFF, 0xBF,0xFC,0xBF,0xF7,0xCF,0xF7,0xFD,0xFF, -0x2F,0xDF,0xAB,0xEA,0xFF,0xDF,0xE7,0xEA, 0x9A,0xAF,0xEF,0xFB,0xFE,0xFF,0xF5,0x3F, -0xFD,0x7E,0xFF,0xD7,0xF5,0xFB,0xFF,0xFD, 0xF7,0xFF,0x7F,0xFE,0xF7,0xFD,0xFF,0xD7, -0xFF,0xD7,0x7F,0xEE,0x7F,0xFA,0x79,0xFE, 0x2F,0x8B,0xE6,0xF9,0xFE,0x3F,0x9E,0xF9, -0xBE,0x2F,0x0B,0xE7,0xF9,0xFE,0x2F,0x9F, 0xFD,0xFF,0xFE,0x7D,0x7F,0x5F,0xD7,0xFF, -0xFF,0x7F,0xFF,0xFD,0xFF,0x7F,0x5F,0x97, 0xFF,0xFD,0x7F,0x5F,0xFF,0xE3,0xFF,0xFF, -0xFA,0xFE,0xBF,0xAF,0xFB,0xFB,0xFF,0xFF, 0xCF,0xEB,0xFE,0xBF,0xAF,0xFF,0xFA,0xFE, -0xBF,0xFF,0x87,0xFF,0xFF,0xF5,0xFF,0xFF, 0xFF,0xFF,0xFD,0xFF,0x7F,0xFF,0xFF,0xFF, -0xFB,0xFF,0xFF,0xF5,0xFF,0xFF,0xFE,0x0F, 0xFF,0xFD,0xEB,0xFF,0xFF,0xF7,0xFF,0xEF, -0x7B,0xDF,0xFE,0xFF,0xFF,0xDF,0xF7,0xFD, 0xEB,0x7F,0xDF,0xFF,0x5F,0xFF,0xFF,0xFF, -0xFF,0xFD,0xBF,0xFF,0x7E,0xFA,0xBF,0xC7, 0xDB,0xF7,0xBD,0x3F,0xFB,0xFF,0xF6,0xFF, -0xFA,0xAF,0xFF,0xEB,0xFA,0xFE,0x3F,0x2F, 0xEA,0xFA,0x3E,0xAD,0xC9,0xBA,0xF6,0xAD, -0xAF,0xEB,0xFA,0xF6,0xBF,0xFE,0x7F,0xFF, 0xFF,0xFD,0xFF,0xF1,0x7F,0x3F,0xCF,0xF1, -0xEF,0xFF,0x7F,0xFF,0xBC,0xDF,0xDF,0xF7, 0xDD,0xFF,0xE0,0x7F,0xFF,0xFF,0xFE,0xFF, -0xFA,0xEC,0xBB,0x7F,0x5F,0xFF,0xFB,0xEC, 0xFF,0xEF,0xB7,0xFF,0xF7,0xFF,0xFF,0xB5, -0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xEE,0xDF, 0x5F,0xDF,0xDE,0xFF,0xAE,0xE7,0x77,0xFF, -0xFF,0xDF,0xF7,0xFF,0xE3,0xFF,0xFA,0xBB, 0xFE,0xFF,0xAF,0xFD,0xFB,0xFE,0xBF,0xAB, -0xF9,0xFE,0xFF,0xBF,0x7F,0xBF,0xFE,0xBD, 0xFE,0xD7,0xFF,0x9F,0xFD,0xFF,0xBE,0xEF, -0xFF,0xEE,0xFD,0xBB,0x5B,0xEF,0xFF,0x7F, 0xEF,0xFF,0xEF,0xFF,0x7F,0xFF,0x4F,0xFF, -0xEF,0xFB,0xBC,0xFC,0xFF,0xFF,0xFF,0xFE, 0xFE,0xFD,0xFA,0xFE,0xFB,0xFF,0xFD,0xF3, -0xFB,0xFF,0xF8,0x5F,0xFF,0xFF,0xD7,0xF5, 0xFD,0xDF,0xEF,0xFF,0xF3,0xDC,0x5F,0xCE, -0xF5,0xBD,0xFF,0xFF,0xD7,0xFF,0xFF,0xF9, 0x3F,0xFF,0xDF,0xF7,0xFF,0xFE,0xFF,0xFD, -0xFF,0xFB,0xFF,0xF7,0xB9,0x7D,0xFE,0xDF, 0xFF,0xFF,0xFF,0xFF,0xF9,0x7F,0xFF,0xFE, -0xFF,0xFF,0x7F,0xFF,0xFE,0xFF,0xFF,0xF7, 0xF6,0xFF,0xBF,0xF1,0xF8,0xFF,0xFF,0xFF, -0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF, 0xFF,0xFF,0xFF,0xFF,0xEF,0xEF,0xFF,0xFF, -0x9B,0xFB,0x7F,0xFF,0xFF,0xFF,0xC1,0xFF, 0xDF,0xFF,0x3F,0x5F,0xD7,0xBF,0xEF,0xBB, -0xDE,0xEE,0xFF,0x7F,0xDF,0xFF,0xFE,0xF5, 0x7F,0xDF,0xFF,0x99,0xFF,0xFF,0xFA,0xFF, -0xBF,0xFD,0xEB,0x7A,0xFF,0xB7,0xFE,0xFE, 0xFF,0xFF,0xEF,0xFF,0xFF,0xFD,0xBF,0xFF, -0x97,0xFF,0xFD,0xF7,0xFF,0x7F,0xF7,0xFF, 0xFF,0xFD,0x5F,0xFE,0xF3,0xF9,0xDF,0xDF, -0xFF,0xFF,0xFC,0xFF,0xFF,0x83,0xFF,0xFF, 0xFE,0xFF,0x9E,0xEC,0xFB,0xEE,0xFF,0x9F, -0xBF,0xEF,0xFF,0xFE,0xED,0x7B,0xFF,0xFF, 0xFF,0xF1,0x5A,0xFF,0xFF,0xFD,0xFF,0x7C, -0x69,0x3B,0xDF,0xFF,0x7F,0x1F,0xDF,0xFF, 0xFD,0xBA,0xFF,0xFF,0xFB,0xFF,0x5B,0xBD, -0xFF,0xFF,0xFF,0xFF,0xD7,0xB6,0xED,0xE9, 0xFF,0xD6,0xBD,0x6F,0x5F,0xFB,0xFF,0xEF, -0xFF,0x5F,0xFE,0xF6,0x6F,0xFF,0xFF,0xFF, 0xFF,0xF7,0xEB,0x7A,0xDF,0xFF,0x9F,0x7F, -0x7F,0xFF,0xB7,0xFF,0xFF,0xFE,0xDF,0xFF, 0x6C,0xFF,0xFB,0xFF,0xBB,0x6F,0xEB,0xFE, -0xCC,0xF7,0xA5,0xFA,0x5C,0xF5,0x75,0xBB, 0xB7,0xDF,0xFE,0x6F,0x5F,0xC5,0xBF,0xFD, -0x7B,0xFE,0xFF,0x95,0xE7,0x29,0xCF,0x4F, 0xF5,0x91,0xEE,0x6B,0xDF,0xEF,0xFD,0x54, -0xF5,0xBD,0xB1,0xFF,0xEF,0xEE,0xFB,0xBE, 0xBF,0xAF,0xFE,0xDE,0xBD,0x6F,0xDA,0xF2, -0xFF,0xAF,0xBE,0xFF,0xFF,0xFD,0x7E,0xA7, 0xFF,0xF7,0xFF,0xBF,0xEF,0x7B,0xF6,0xFD, -0xBD,0x4A,0xF2,0x85,0x85,0xBF,0x5B,0xFE, 0xB5,0xFD,0xFA,0xFF,0x4F,0xFF,0xFE,0xDF, -0xFF,0xED,0xFF,0xBF,0xFF,0xBF,0x7F,0xFE, 0xFF,0xB7,0x6D,0xFF,0xF7,0xBF,0xBF,0xEF, -0xFD,0x1F,0xFF,0xFE,0x7D,0xFF,0x67,0xFF, 0xFF,0xFF,0x3F,0x7F,0xFE,0xBF,0xFF,0xE7, -0xDF,0xE7,0xFF,0xEF,0x6B,0xFC,0x1F,0xFF, 0xBF,0xEF,0xFB,0xFE,0xDE,0xBF,0xAF,0xFA, -0xFF,0xB6,0xEF,0xF9,0xFE,0xFF,0x8F,0xEF, 0xDB,0xEF,0xAB,0x6F,0xFB,0xFE,0xFF,0xFF, -0xEF,0xFD,0xFF,0x7F,0xFF,0xFF,0xDE,0xFF, 0xFF,0xEF,0xFF,0xFF,0xFF,0x3F,0xFF,0x6C, -0xFF,0xBF,0xFB,0xFF,0xFE,0xFF,0xFB,0xFE, 0xDF,0xFF,0xFF,0xEF,0xFF,0xFF,0xBF,0xFF, -0xFF,0xFE,0xFB,0xFF,0xD5,0x7F,0xFF,0xFF, 0xEF,0xFB,0xFF,0xFF,0xBF,0xEF,0x43,0xB5, -0xFD,0x6F,0xCF,0xD6,0xBE,0x3F,0x7F,0xDB, 0xFE,0xC3,0xFF,0xFD,0xFF,0xAF,0xEB,0xFB, -0xFC,0xFF,0x3E,0xEF,0xE8,0xFA,0xBD,0xCD, 0xAA,0xFE,0xFE,0x7D,0xCF,0xFF,0xB7,0xFF, -0xF7,0xFF,0xFF,0xFF,0xFD,0xFF,0x75,0xCD, 0x52,0xD7,0xFD,0xFB,0xF7,0xDD,0xFB,0xEF, -0xEB,0xFF,0xFF,0x4F,0xFF,0xBF,0x9F,0xE7, 0xF9,0xFC,0x7F,0x8B,0xC3,0xF9,0xAF,0x8F, -0xE7,0xE9,0xBE,0x7F,0x9F,0xE6,0xF9,0xFC, 0x5F,0xFF,0xFF,0xF7,0xFD,0xFF,0x7A,0x5F, -0xD7,0xED,0xFF,0xFF,0xD7,0xFF,0xDD,0x7F, 0xE7,0xFF,0xFC,0xFF,0xFC,0x3F,0xFF,0xFF, -0xFF,0xFB,0xFF,0xFE,0xBF,0xAF,0xFF,0xFD, 0xFF,0xEF,0xFF,0xEB,0xFF,0xFF,0xFF,0xFF, -0xFF,0xF7,0x7F,0xFF,0x7F,0xDF,0xFF,0xFD, 0xFD,0x7F,0xFE,0xF7,0xFD,0x7F,0xDF,0xFF, -0xFD,0xFF,0xFF,0xDF,0xFB,0xFF,0xEE,0xFF, 0xFB,0xFF,0xF7,0xFD,0xFF,0x7A,0xDF,0xF5, -0xFD,0xFA,0xDF,0xF7,0xFC,0xFF,0x7F,0xDF, 0xBF,0xED,0xFF,0xC9,0xFF,0xDF,0xFF,0xBF, -0x2F,0xFB,0xFF,0xBC,0xAD,0xFF,0xF7,0xFF, 0xFF,0xEF,0xD3,0xFF,0x7D,0xBF,0x6F,0xFF, -0xFA,0xFF,0xFE,0xBF,0xAE,0xEA,0xFA,0xBE, 0xAD,0xA5,0xEB,0xCE,0xBF,0xA7,0xEB,0x5A, -0xDE,0xBD,0xAF,0x6B,0xFD,0x57,0xFF,0xFF, 0xF4,0x7F,0x1F,0x7F,0xFD,0xFF,0x7F,0x36, -0xF0,0xDF,0x79,0xFF,0xFF,0xFF,0xF7,0xFD, 0xBF,0xFF,0x87,0xFF,0xFB,0xF3,0xFC,0xFF, -0xFF,0xFF,0xFF,0x7E,0xFF,0xBF,0xDF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xF8,0x9F, -0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFD, 0xF7,0xFC,0xBD,0xFF,0xFE,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFB,0xF9,0xBF,0xFF,0xFF,0xEB, 0xE2,0xFE,0xFF,0xBF,0xEF,0xA9,0xBA,0x2F, -0xEB,0xF9,0xFE,0x77,0xDF,0xF7,0xFF,0xFF, 0xF9,0x7F,0xFF,0xFF,0x7F,0xEF,0xD7,0xFF, -0xFD,0xFF,0xFB,0xF5,0xFF,0xBF,0x6F,0xDF, 0xFF,0xFF,0xFD,0xFF,0xFF,0xF0,0xFF,0xFF, -0xFF,0x3F,0xCF,0xFF,0xBA,0xEE,0x9B,0xBF, 0xEE,0xD7,0xFE,0xCD,0xEF,0xFF,0xDF,0xBF, -0xFF,0xFF,0xC5,0xFF,0xFF,0xFD,0x7F,0x4F, 0xFD,0xF6,0xD9,0xFF,0x4F,0xD6,0xFD,0xBF, -0x6E,0xFF,0xFF,0xF4,0x7F,0xFF,0x7F,0x8B, 0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xF9,0xFE, -0x37,0xFF,0xD9,0xFB,0xF5,0xAF,0xFD,0xFF, 0xFF,0xFB,0xFF,0xFF,0x07,0xFF,0xFF,0xFF, -0xFB,0xF7,0xFF,0xFD,0xFF,0x7C,0xFA,0x7E, 0x4F,0xFC,0xDF,0x1D,0xC7,0xFF,0xFF,0xFF, -0xFF,0xAE,0xFF,0xFF,0xFF,0xFF,0xFD,0xFB, 0xFF,0xFF,0xFE,0xFE,0xFC,0xFF,0x7F,0x7F, -0xBF,0xEF,0xFE,0xFF,0xFF,0xFF,0x5F,0xFD, 0xFF,0xFF,0xFF,0xFD,0x6F,0x5A,0xD7,0x7B, -0xBE,0x5F,0xFE,0x39,0xFF,0xF7,0xFF,0xF7, 0xFD,0xFE,0xAA,0x1F,0xFF,0xFF,0xFF,0xFF, -0xFE,0xFE,0xAB,0xAF,0xFD,0xFE,0xBF,0xFF, 0xF7,0xFF,0x7F,0xFE,0x8F,0xE3,0xFB,0xEE, -0x7F,0xFF,0xFF,0xFF,0xFF,0xEB,0xFB,0xFF, 0xFD,0xBF,0xEF,0xDF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFB,0xE4,0x3F,0xFF,0xDF, 0xFF,0xFF,0xFF,0xFF,0xF3,0xEF,0xBB,0xFB, -0xBF,0xEF,0xBB,0xFF,0xD7,0xBF,0xFF,0xFF, 0xFF,0x29,0xAF,0xF7,0xFF,0xFF,0xFB,0xFF, -0xFB,0xE6,0xFF,0x0F,0xFB,0x3F,0xDF,0x0F, 0xFF,0xAF,0xFF,0xFF,0xFF,0xF5,0xC3,0xDF, -0x5F,0xFF,0xFF,0xFF,0xFE,0x6B,0xCA,0xBE, 0xBC,0xFF,0x9F,0xF2,0xBF,0xFF,0xFE,0xFA, -0xFF,0xFF,0xEF,0x16,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFC,0xDF,0x97,0xFD,0x79,0xFF,0x37, -0xE7,0x7F,0xFF,0xFF,0xB5,0xFF,0xFF,0xF6, 0x2F,0xFF,0xFD,0xFB,0xFE,0xFF,0xFF,0xFD, -0x5F,0x57,0x5F,0xFF,0xDB,0x52,0xDF,0xFF, 0xFD,0xBF,0xFF,0xFF,0xFC,0xDB,0xFF,0x7B, -0xB5,0xFD,0x7F,0xFF,0x71,0x9C,0x6E,0xFF, 0xF6,0x35,0xA5,0x9B,0xFF,0xFF,0xFD,0xFF, -0xFF,0xDB,0x9E,0x7F,0xFE,0xEF,0xFB,0xFF, 0xFF,0xBD,0xEF,0xFF,0xDE,0xB7,0xF9,0x4B, -0xFF,0xF5,0xEF,0xFF,0xFF,0xFF,0xE8,0x7E, 0xFF,0xEA,0xDF,0xF7,0xFF,0xFD,0x69,0x5B, -0xFC,0x9F,0xEF,0x78,0xD6,0xFF,0xEB,0xEF, 0xFF,0xFF,0xFF,0xE8,0xFF,0xFF,0xED,0xFF, -0xFF,0xFF,0xFF,0xE3,0xF9,0xF6,0xBF,0xFF, 0xFF,0xFE,0xDF,0xFF,0x7F,0xFF,0xFF,0xFF, -0xD1,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF, 0xE7,0xF9,0xFF,0xBF,0x7F,0xD9,0xFF,0xFD, -0xFE,0x7F,0xFF,0xFE,0xFF,0xF9,0xFF,0xFB, 0xD6,0xDF,0xBF,0xEF,0x5B,0xD6,0xFF,0xBF, -0xFB,0xF6,0xFF,0xBF,0xEF,0xF8,0xF6,0xDD, 0xBE,0xFE,0x16,0xFF,0xBF,0xEF,0xFF,0xFE, -0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0x6F,0xFB, 0xFF,0xFF,0xFF,0x6F,0xF3,0xFF,0xF7,0xEF, -0xFB,0xFF,0xBF,0xFF,0xEF,0xFE,0xFF,0xBF, 0xFF,0xFF,0xFF,0xBE,0xBF,0xFF,0xEF,0xFF, -0x7F,0xEF,0xFF,0xFD,0x17,0xFB,0x7B,0xFF, 0xFF,0xFD,0x7F,0xDB,0xF6,0xF4,0x7F,0xFA, -0xFE,0xF5,0xBF,0xEB,0xE3,0xF7,0xFF,0xFF, 0xE9,0xBF,0xFF,0xAF,0xF7,0xFD,0xF3,0x7E, -0x8F,0xA3,0xEA,0xFF,0xCB,0xF3,0xEE,0xFF, 0xBF,0xEF,0xF7,0xF9,0xFF,0xFE,0x7F,0xFF, -0xFF,0xFF,0xFF,0xF5,0xFB,0xF6,0xFF,0xF5, 0x2F,0xFE,0xFB,0xD7,0xBF,0xFF,0xBE,0xDF, -0x9F,0xFF,0xF0,0xFF,0xFF,0xF9,0xFE,0x7F, 0x8F,0xA3,0xF8,0xFE,0x6F,0x9F,0xF9,0xF6, -0x2F,0x9F,0xE7,0xF9,0xFE,0x2F,0x9F,0xE1, 0xFF,0xFF,0xFF,0x7F,0xDF,0xF7,0xF5,0xFD, -0x7F,0x7F,0xF5,0xFF,0x9F,0x5F,0xFB,0xFE, 0xFF,0x7F,0xFF,0xFF,0xCB,0xFF,0xFF,0xFB, -0xFE,0xFF,0xBF,0xAF,0xFB,0xFE,0xFF,0xDF, 0xFE,0xFE,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF, -0xFF,0xC7,0xFF,0xFF,0xFD,0xFF,0x7F,0xDD, 0xF7,0xFD,0xFF,0xFF,0xD7,0xFF,0xFD,0x7F, -0xFF,0xFB,0xFD,0xFF,0xFF,0xFE,0xEF,0x7F, 0xFD,0xEF,0xFB,0xFE,0xFB,0xFD,0xFF,0x7F, -0xDF,0xFD,0xFF,0x7A,0xDF,0xF7,0xFD,0xFF, 0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xD3,0xF7, -0xFF,0xFF,0x6F,0xDB,0xFF,0xFF,0xEF,0xCB, 0xF4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, -0x29,0xFF,0xE8,0xDA,0x76,0x9F,0xAF,0x6A, 0xDA,0xFE,0x35,0xEB,0xDA,0xD6,0xBF,0xAB, -0xEB,0x7A,0xDE,0xBF,0xD7,0x7F,0xFF,0xFE, 0xFF,0xBF,0xEF,0xFD,0xDF,0x77,0xBF,0xFD, -0x37,0xEF,0xFF,0xEF,0xFF,0x3F,0xFF,0xFF, 0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xF7,0x7E, -0xDF,0xFF,0xFF,0xFF,0xFA,0xB7,0x7F,0xFF, 0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x89,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x9F,0xFB,0xFF,0xFF,0xFF,0xE7,0xFF, -0xFF,0xFF,0xFF,0xAA,0xFF,0xAB,0xFB,0xFA, 0xEF,0xBF,0xFF,0xDF,0xFA,0x7B,0xB9,0xFE, -0xFE,0xFF,0xFD,0xFF,0xF7,0xFE,0x3F,0xFF, 0xB7,0xFF,0xF7,0xEE,0xFF,0x7F,0xEF,0xFF, -0xFF,0x7F,0xFF,0x1F,0xFB,0xFF,0xBF,0xFB, 0xFE,0xFF,0xBD,0xFF,0xFF,0x2F,0xFF,0xBF, -0xFF,0x7F,0xDF,0xFA,0xFF,0xFF,0xFC,0xEE, 0xF5,0xF3,0xBE,0xFB,0x0F,0xEF,0xF3,0xBE, -0xEF,0xFC,0x5F,0xFF,0x5A,0xFF,0xF7,0xDF, 0xFF,0xFF,0xFE,0xD5,0xFC,0x5F,0xFB,0xF2, -0xFF,0xFF,0x2F,0xBB,0xF3,0xFF,0xFF,0xBF, 0xFF,0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, -0xBF,0xFF,0xFF,0xFD,0x7B,0xFF,0xDF,0xB9, 0xFF,0xFB,0xFF,0xD8,0x7F,0xFF,0xFF,0xFF, -0xFB,0xFF,0xFC,0x7F,0x1F,0xBF,0xE0,0xDF, 0xF7,0xEF,0xFF,0xFD,0x7F,0xFE,0xDF,0xFF, -0xE0,0xFF,0xFF,0xFD,0xEF,0xFB,0xFF,0xFE, 0xF7,0xDF,0xFF,0xEB,0x5F,0xFF,0xF7,0xFF, -0xFF,0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0xFD, 0xFF,0xFF,0xFF,0xF7,0xFD,0xFF,0x3B,0xDC, -0xFD,0x6D,0x7B,0x5F,0x57,0xF5,0xFD,0x7F, 0x5F,0xFF,0xB1,0xFF,0xEB,0xFF,0xFF,0xFF, -0xFB,0xFB,0xFE,0xFF,0xBF,0xFB,0xBE,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFF,0xAF,0xFE,0xF7, -0xDF,0xDF,0xFF,0xFF,0xFF,0x7F,0xCF,0xF3, 0xF8,0xFF,0xD7,0xFB,0xFF,0x5F,0xBF,0xF7, -0xFB,0xFF,0x7F,0xFE,0x23,0xFF,0xFF,0xFE, 0x7F,0xF3,0xFF,0xFB,0xFE,0xFF,0xFF,0xF3, -0xFF,0xFF,0xF5,0xF9,0xFF,0x3F,0xFF,0xFF, 0xF0,0x9A,0xFF,0xBE,0x7F,0xFF,0xFC,0xF9, -0xFF,0xFD,0xAF,0xEB,0xFE,0xBF,0xFF,0xCF, 0xF3,0xFE,0x7F,0xFF,0xFF,0x5B,0xBD,0xFF, -0xBC,0xEB,0xFF,0xD7,0xD4,0xAF,0xAF,0xFD, 0xFF,0xCF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, -0xFD,0xFE,0xFF,0x6F,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFD,0x7F,0x5E,0xFD,0xBF,0xDB,0xF6, -0xFD,0xBF,0x6F,0xFB,0xEE,0xFD,0xFF,0x7A, 0xFF,0xFA,0xFB,0xFF,0x3F,0xFB,0xB7,0x5F, -0xD6,0xF7,0x1F,0x71,0xDC,0x77,0x1D,0xC7, 0x31,0xDC,0x77,0xDF,0xF9,0xBF,0xF5,0x5B, -0xF4,0xD7,0x9D,0xAE,0xFF,0xBF,0xFD,0xBF, 0xDB,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFE, -0x3D,0x81,0xFF,0xEB,0xFE,0xFE,0xFE,0xFF, 0xEB,0x7A,0xDF,0x7D,0x77,0x7D,0xF5,0x79, -0xDF,0x57,0xDD,0xF5,0x7D,0x7E,0xE6,0xFF, 0xD6,0x3F,0xBF,0x7F,0xFF,0xD4,0xF5,0x3F, -0xBF,0xFB,0xBE,0xEF,0xB3,0xEE,0xFB,0x9E, 0xEF,0xBB,0xFE,0x8B,0xFF,0xFE,0xDF,0xB7, -0xED,0xFF,0xF7,0xFD,0xFE,0xFF,0xEF,0xBB, 0xEE,0xFF,0xBE,0xEF,0xBB,0xEE,0xEB,0xFC, -0x1F,0xFF,0xFF,0xFD,0xFF,0xE7,0xFF,0xF7, 0xFD,0xFF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB, -0xFE,0xFF,0xBF,0xEB,0xFA,0x1F,0xFF,0xB7, 0xEF,0x5B,0xFE,0xFF,0xAF,0xEB,0xDD,0xE7, -0xDE,0x77,0x9D,0xE7,0x79,0xDE,0x77,0x9D, 0xBF,0xE6,0x6F,0xFF,0xFE,0xFF,0xBF,0xEF, -0xFB,0xFE,0xFD,0xBF,0x6F,0xF6,0xFD,0xBF, 0x6F,0xDB,0xF6,0xFD,0xBF,0xFF,0x7E,0xFF, -0xFF,0xFB,0xFE,0xFE,0xFF,0xEF,0xFB,0xFD, 0xEF,0x7E,0xF7,0xBD,0xEF,0x7B,0xDE,0xF7, -0xBD,0xEF,0xFF,0xD5,0xFF,0xBF,0xFF,0xEF, 0xFE,0xFF,0xFC,0x3F,0x0F,0xE7,0xFE,0x7F, -0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFE, 0xF3,0xFF,0xFE,0xDF,0xAD,0xDF,0x67,0xEE, -0xFB,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFE,0xFF,0xBF,0xEF,0xFF,0x23,0xFF,0xFF, -0xFF,0xFF,0x7F,0xFF,0xF3,0xBC,0xDB,0xFE, 0xFB,0xFF,0xFB,0xBE,0xF7,0xFB,0xFF,0x7F, -0xDF,0xFF,0xCF,0xFB,0xFF,0x9F,0xE3,0xF9, 0xBE,0x3F,0x8F,0xE7,0x79,0xFF,0x9D,0xE7, -0xF9,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x5F, 0xFF,0xCF,0xF7,0xFF,0xFF,0xFF,0xDF,0xF7, -0xFE,0x7F,0xE7,0xF9,0xFE,0x7F,0xFF,0xFF, 0xFB,0xFE,0xFF,0xFF,0xBF,0xFF,0xBF,0xBF, -0xFF,0xFE,0xFF,0xBF,0xEF,0xFF,0xFD,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFD,0xFF, -0xFF,0x3F,0xFF,0xBF,0xFF,0xF7,0xFF,0xFF, 0x7F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0xEF,0xFF, 0x5F,0xF7,0xBF,0xF9,0xFE,0xDF,0xB7,0xFD, -0xFF,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0xDD,0xFF,0xF2,0xFF,0xBF,0xFF, -0xFF,0xBF,0xFF,0xFF,0x2F,0xF2,0xFF,0xBF, 0x2F,0x7B,0xD2,0xF7,0xBF,0x2F,0xFF,0xBB, -0xFF,0xEE,0x8F,0xAF,0xEB,0xFA,0xFE,0x3F, 0xA7,0x69,0xCE,0x8F,0xA4,0xEA,0xFA,0xEE, -0xB7,0xAE,0xEB,0xFD,0xC7,0xFF,0xF7,0xF7, 0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3E,0xF3, -0x74,0xFF,0x3F,0x4F,0xFF,0xE7,0xFF,0x3F, 0xFE,0xA7,0xFF,0xFF,0xDF,0xF7,0xB7,0xFF, -0xF7,0xFF,0xBA,0xEF,0x37,0xEB,0xFB,0xFE, 0xBF,0xFB,0xFE,0xF3,0xFF,0xF9,0xDF,0xFF, -0xBF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, 0xFD,0xDF,0xFF,0xFD,0xFF,0xFF,0xFB,0xFE, -0xFD,0xFF,0xFB,0xBF,0xFE,0x3F,0xED,0xFF, 0xDF,0xBE,0x3D,0xA7,0xFB,0xFA,0x3F,0xE6, -0xE1,0xFE,0xFE,0x3F,0xEF,0xE3,0xDF,0xF5, 0x7F,0xFE,0xFF,0x7E,0xFF,0xFF,0xFF,0xFF, -0xEF,0x6F,0xF6,0xFF,0x7D,0xEF,0xD7,0xDE, 0xFF,0x7D,0xEF,0xFF,0xF2,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0x7B,0xDE,0xFB,0xE6,0xEE, 0xEF,0x37,0x6E,0xF3,0x7E,0xEB,0x37,0xEF, -0xFF,0xC1,0xFF,0xFE,0xFF,0xF7,0xEF,0xFF, 0xFF,0xFF,0xBF,0x3F,0xD2,0xDF,0xBF,0x2F, -0x7B,0xE2,0xFF,0xFE,0x3B,0xBD,0xDB,0xFF, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFE, -0xFF,0xFB,0xFF,0xFF,0xBF,0xFF,0xFB,0xDF, 0xFF,0xBF,0xFF,0xB7,0xFF,0xFF,0xBF,0xEF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF, 0x7F,0xFF,0x1F,0xEF,0xF1,0xFD,0xFF,0xF6, -0xAF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF, 0xFF,0xFF,0xFE,0x9F,0xFF,0xFF,0xFF,0x77, -0xEF,0xF7,0xFB,0xFF,0xFE,0x5F,0xFF,0xFF, 0xBF,0xCF,0xFB,0xF7,0xDD,0xF7,0xF5,0xFF, -0x5F,0xD5,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5, 0xFF,0xFB,0x0F,0xFF,0xFF,0xA9,0xEA,0x7A, -0xFF,0xAF,0x8F,0xFE,0xDF,0xAF,0xEF,0xFB, 0xFE,0xFF,0xBF,0xEF,0xFB,0xDF,0xE5,0x5F, -0xFF,0xFF,0xFF,0xFF,0xFF,0xBD,0x57,0xFF, 0xFF,0x6F,0x77,0xBF,0xF7,0xFB,0xFF,0x7F, -0xBF,0xF7,0xFF,0xFC,0xBF,0xFF,0x9F,0xFF, 0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF,0x1F, -0xCF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0xFB, 0x65,0xAF,0xF3,0x7C,0xFF,0x3F,0xDF,0xFF, -0xFD,0xE9,0xFE,0x7F,0xE7,0xFF,0xFE,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFD,0xE3,0xDF,0xFB, -0xDB,0xF6,0xFD,0xEF,0x5B,0xFB,0xFF,0xDF, 0xFC,0xFF,0x3F,0xDF,0xF3,0xFD,0xFF,0x7F, -0xDF,0xEF,0x66,0xFF,0xDF,0xAD,0xEB,0x7A, 0xDE,0xF7,0xF7,0xE7,0xD9,0xFD,0x9F,0x67, -0xD9,0xF6,0x7D,0x9F,0xE7,0xDF,0xF5,0x47, 0xFD,0x65,0x5B,0xD6,0xF4,0xFE,0xFF,0xEF, -0xFF,0x6D,0xF6,0xDD,0xB7,0x6D,0xDB,0x76, 0xDC,0xB7,0x7D,0xFA,0x9B,0xF6,0x6D,0x9D, -0x67,0x59,0xDF,0xF7,0xDD,0xFF,0xEB,0xFE, 0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xE3, -0xD1,0x9F,0xFF,0xBD,0xBF,0xEF,0xFE,0xF7, 0xBF,0xBF,0xF7,0xD7,0x7F,0xDD,0xF7,0x9D, -0xDF,0x7F,0xDF,0xF7,0xFF,0xE0,0x7F,0xFD, 0xC1,0xDF,0xF7,0xFD,0xC7,0x7F,0x7F,0xFB, -0xFF,0xBB,0xEC,0xFB,0x3E,0xFF,0xBF,0xEC, 0xFB,0xFF,0xD8,0x7F,0xBF,0x6C,0xFF,0xBE, -0xFF,0xBF,0xED,0xFF,0xEF,0xFE,0xFB,0xBF, 0xEF,0xFB,0xFE,0xFF,0xBF,0xEE,0xFF,0xC5, -0xFF,0xAF,0x6F,0xFF,0xFC,0xFD,0x3F,0xE7, 0xFF,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF, -0xEF,0xFB,0xFE,0xBF,0x89,0xFE,0xFA,0xBA, 0xFE,0xBF,0xAF,0xFB,0xF6,0xF5,0xD9,0x7D, -0x97,0x65,0xD9,0x74,0x5D,0x97,0x65,0xD3, 0xFE,0xD6,0xFF,0xBF,0xF7,0xFD,0xFF,0x7F, -0xBF,0xCF,0xFB,0xFE,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFF,0xF6,0x8F,0xFB, -0xFF,0xEF,0xFB,0x7E,0xDB,0xFE,0xFF,0xBE, 0xEF,0xEE,0xFB,0xBE,0xEF,0xBB,0xEE,0xFB, -0xBE,0xFF,0xFF,0xDF,0xFF,0x43,0xFF,0xFF, 0xFB,0xEF,0x5F,0xB7,0xFE,0x7F,0xE7,0xF9, -0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xF9, 0xBF,0xFE,0xAF,0x77,0xFD,0xFF,0x2F,0xAF, -0xA7,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0xF1,0x7F,0xEF,0xDF, -0xFF,0x97,0xF5,0xEF,0xFF,0xDF,0xFF,0xFF, 0xBF,0xFF,0xBF,0xFF,0xFF,0xFE,0xFF,0xFF, -0xFF,0xE0,0xFF,0xFF,0xF9,0xFE,0x2F,0x8B, 0xE3,0xF8,0xBE,0x77,0x9F,0xF9,0xDA,0x77, -0x9D,0xE7,0x79,0xDE,0x77,0x9F,0xDD,0xFF, 0xFD,0xFD,0x7F,0x5F,0xD7,0xFD,0xFF,0x7F, -0xE7,0xFE,0x7F,0x97,0xE7,0xFB,0xFE,0xFF, 0xBF,0xEF,0xFF,0xAB,0xFF,0xEF,0xFA,0xFE, -0xBF,0xAF,0xFF,0xFA,0xFF,0xFF,0xDF,0xFF, 0xFB,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF, -0x67,0xFF,0xF7,0xF5,0xFF,0xFF,0xFF,0xDF, 0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xBD, 0xEB,0xFF,0xFF,0xF7,0xAD,0xEB,0xFF,0xDF, -0xFD,0xFF,0x3F,0xDF,0xF7,0xFD,0xFF,0x7F, 0xDF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0xFD, -0xBF,0xFF,0xCB,0xF4,0xFF,0x7F,0xD3,0xF7, 0xFD,0x3F,0x7F,0xD3,0xF7,0xFF,0xFC,0x3F, -0xFF,0xEA,0xFA,0xBE,0xAF,0xAB,0xEB,0xBA, 0xF4,0x95,0x6B,0x52,0xD4,0xAD,0x2F,0x4A, -0xD2,0xF6,0xBF,0xD2,0x7F,0xF7,0x3F,0xFF, 0xFF,0xF3,0x7F,0xFF,0xFF,0xF7,0xFF,0xBA, -0xDF,0xFB,0xFD,0xFF,0xBF,0xFF,0xFB,0xFF, 0xF8,0x7F,0xEA,0xFF,0xFE,0xFE,0xDF,0xFF, -0xF7,0xFF,0x7F,0xBB,0xFF,0xFF,0xBF,0xDF, 0xFB,0xFF,0xFF,0xBF,0xFF,0xB1,0x7F,0xFF, -0xFB,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF, 0xCF,0xFE,0xFF,0xFF,0xEF,0xFF,0xF7,0xFF, -0xFF,0xFF,0xF1,0xFF,0x69,0xBE,0xFA,0xBF, 0xAF,0xE2,0xFF,0xFE,0xFD,0xAF,0xF3,0xFE, -0xFF,0xBF,0xEF,0xFB,0xFC,0xFF,0xFF,0x07, 0xFD,0x95,0xDB,0xDF,0x7F,0xDF,0xAF,0xFF, -0xF7,0xAF,0x36,0xFE,0xBF,0x65,0xEB,0xF6, 0xFE,0x9F,0x6F,0xFE,0x07,0xFF,0xCF,0xFF, -0xF8,0xFE,0xFF,0xCF,0xFF,0xF6,0xFA,0xE7, 0xFB,0xFE,0xFF,0xBB,0xED,0xF9,0xFF,0xFF, -0xFF,0x5F,0xFF,0xFF,0xFF,0x75,0xFF,0xEF, 0x7E,0xFD,0xE0,0xE8,0x5E,0xD3,0xE5,0xF9, -0x3E,0x5F,0xD7,0xF7,0xFF,0xFA,0x2F,0xFB, 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0x7F, -0x7F,0xD7,0xF5,0x7D,0x5F,0x57,0xD5,0xF5, 0xEF,0xFF,0xF3,0x7F,0xFC,0x7F,0xFF,0xC7, -0xF1,0xFF,0xFF,0x1F,0xCF,0xB0,0xFF,0x3F, 0xCF,0xF3,0xFC,0xFF,0x3F,0xCE,0xFF,0xE4, -0xFF,0xDF,0x7F,0xFE,0xF7,0xBB,0xFF,0xFF, 0xDF,0xEF,0xEE,0xFF,0xBF,0xEF,0xFB,0xFE, -0xBF,0xBF,0xEF,0xFF,0xD1,0xFF,0xFF,0xFF, 0xFD,0xFB,0xFF,0xFD,0xFF,0xFB,0x9F,0xE9, -0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xBF, 0xFF,0xB3,0xFF,0xFF,0xF7,0xFF,0xFF,0xAF, -0xF7,0xFF,0xB6,0x3F,0xEB,0xFA,0xFE,0xBF, 0xAF,0xEB,0xFA,0xFE,0xBF,0xFE,0xA7,0xFF, -0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF, 0xFE,0x9F,0xF7,0xF9,0xFF,0x7F,0x9F,0xE7, -0xFF,0xFF,0xFE,0xAF,0x6F,0xFF,0xFF,0xFF, 0x9F,0xFF,0xDF,0xFF,0x7D,0x5F,0xDD,0xFF, -0xFB,0xBF,0xE7,0xBB,0xFF,0xFB,0xDF,0x6D, 0x5F,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xEB,0xF7,0xFF,0xE7,0xEF,0xF7,0xFF,0xFF, 0x7F,0xFF,0xF7,0xFF,0xFC,0x8F,0xFF,0xEF, -0xFD,0xFE,0xFF,0xBE,0xF4,0xF2,0x7D,0xD7, 0xCF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xCF,0x6B,0xFF,0xBF,0x3F,0xFB,0xF2, 0xFC,0x7F,0xEB,0xFF,0x9F,0xFA,0xFF,0xFF, -0x3F,0xFF,0xF3,0xFF,0xFF,0xFD,0x70,0xF7, 0xFF,0xFF,0xBF,0xFF,0xFB,0xD7,0xFE,0xF5, -0x77,0xFF,0x15,0xDD,0x77,0xFD,0xFF,0x7F, 0xDF,0xF7,0xFB,0xCD,0xBF,0xFF,0xFD,0xFF, -0xFF,0xDF,0x37,0xCD,0xF9,0xEC,0xFE,0xEF, 0xBB,0xF4,0xFB,0x3F,0x4F,0xB3,0xFF,0xFD, -0xCB,0xFF,0xE9,0x7E,0x54,0x9F,0xE5,0x4B, 0xB7,0xFF,0xDD,0x7D,0xC7,0x71,0xDD,0x77, -0x5D,0xD7,0x75,0xCD,0x7F,0xD6,0xFF,0xD3, 0xF6,0xF9,0x3F,0x6D,0x95,0xAF,0x7F,0xFE, -0xFF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFE,0xF6,0xC7,0xFF,0xAD,0x7B,0xCA,0xFF, -0xBF,0xBF,0xEF,0xFD,0xE3,0xDF,0xB7,0xED, 0xFB,0x7E,0xDF,0x37,0xED,0xE3,0xFB,0xDF, -0xFF,0x52,0x5C,0x15,0xFD,0xCF,0x7F,0xDF, 0xFE,0xEF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEC, -0x7B,0xFE,0xFF,0xFE,0x3E,0x7F,0xDA,0xF7, 0xFD,0xFF,0x7F,0xFF,0xFF,0xFB,0xEF,0xBB, -0x6F,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF, 0xF7,0x7D,0xFF,0xD8,0xFF,0xFD,0xBF,0x7F, -0xFB,0xFF,0xFF,0x9F,0xFB,0xFE,0x7F,0x9F, 0xE7,0xF9,0xFE,0x7F,0x9F,0xEA,0x7F,0xF6, -0xBF,0xBD,0x6A,0x5A,0xF6,0xE5,0xBF,0x77, 0x5F,0x6D,0xDD,0x77,0x5D,0xD7,0x75,0xDD, -0x77,0xFF,0xA5,0xBF,0xCF,0xFB,0xFF,0xFF, 0xBF,0xCF,0xFB,0xFD,0xFF,0xBF,0xF3,0xFE, -0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD,0xAB, 0xFF,0xBF,0xBF,0xFF,0xFB,0xFF,0x7F,0xEF, -0xFF,0xBE,0xFB,0xEE,0xFB,0xBE,0xEF,0xBB, 0xEE,0xFB,0xBF,0xFF,0xB5,0xFF,0xD0,0xBC, -0xFD,0x2F,0x4B,0xF7,0xFF,0xFF,0x9F,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x9F, -0xFA,0x8F,0xFD,0xAB,0xFA,0xDA,0xBF,0xAF, 0xB3,0xFD,0xFF,0xBF,0xFB,0xFE,0xFF,0xBF, -0xEF,0xFB,0xFE,0xF7,0xBF,0xFF,0x9F,0xFF, 0x77,0xF7,0xBD,0xFD,0x77,0xDF,0xFF,0x7E, -0xDF,0xED,0xBB,0xFE,0xFF,0xBE,0xEF,0xFB, 0xFE,0xFF,0xFA,0x3F,0xFF,0xBE,0x6F,0x8F, -0xE6,0xF9,0xFE,0x7F,0x9F,0xC7,0xFE,0x7F, 0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFB, -0x7F,0xFF,0x7F,0xCF,0xFF,0xFD,0xFF,0xFF, 0xDF,0xFB,0xAF,0xBF,0xEF,0xFF,0xFE,0xFF, -0x9F,0xEF,0xFB,0xFF,0xFC,0xFF,0xFB,0xFE, 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xF7, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xF5,0xFF,0xFF,0xFF,0x3F,0xDF,0xF7, -0xFF,0xFF,0x7F,0xEF,0xFE,0xFF,0xBF,0xFF, 0xFB,0xFF,0xFF,0xBF,0xEF,0xFF,0xB3,0x7F, -0xFF,0x7B,0x5E,0xF7,0xFD,0xFF,0x7B,0x7F, 0xF7,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, -0xDF,0xF7,0xFF,0x17,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xDD,0xF6,0xFC,0xBF,0xCB,0xF2, -0xBC,0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xFE, 0x8F,0xFF,0xFA,0x7E,0xBF,0xA7,0xEB,0xDA, -0xFC,0xBF,0xAF,0x7A,0xFE,0xBF,0xAF,0xEA, 0xFA,0xFE,0xBF,0xAF,0xF4,0xDF,0xFE,0xFF, -0xF3,0x3C,0x7F,0x3E,0xFF,0xCF,0xF8,0xBF, 0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xE7,0xE8, -0xFF,0xFC,0x9F,0xFF,0xFF,0xCF,0xEB,0xB3, 0xE7,0xFB,0x7B,0xF3,0xFE,0xFF,0xCF,0xDB, -0xFB,0xFB,0xBF,0x6F,0x6F,0xDF,0xEC,0x7F, 0xFF,0xFF,0xF7,0xFD,0xFD,0xFF,0xFF,0xFF, -0xFF,0xB2,0xBF,0xFF,0xDE,0xFD,0xBD,0xEF, 0xFB,0xF6,0xDF,0xEA,0xE7,0xDB,0xFE,0xBB, -0xFF,0xEB,0xFB,0xBF,0x9F,0x8F,0xE8,0xFE, 0x3F,0x8F,0xA3,0xF8,0xFE,0x3F,0x8F,0xFF, -0xF8,0x7E,0xFD,0xFD,0x7F,0xFF,0xFB,0xCD, 0xFF,0xFD,0xFF,0x5F,0xEF,0xFD,0xFF,0xFF, -0xDF,0xF7,0xFD,0xFF,0xBE,0x90,0xFF,0xFF, 0xEE,0xFF,0x3F,0xBF,0xF3,0xBB,0xFE,0xB7, -0xAB,0xFA,0xFE,0xAF,0xAD,0xEA,0xFA,0xDE, 0xAB,0xFF,0x63,0xFF,0xFE,0xF2,0xFF,0xB3, -0xFF,0xDF,0xEE,0x7D,0xFF,0x03,0xF1,0xF4, 0x3F,0x1F,0xC3,0xF1,0xEC,0x7F,0xFE,0x6F, -0xFF,0xFB,0xFB,0xFF,0x9F,0xFF,0xBF,0xFF, 0x7B,0x5F,0xFD,0xFF,0xDF,0xF7,0xFD,0xFD, -0x7F,0x7F,0xDF,0xFE,0xCF,0xFB,0xFF,0xFF, 0xAF,0xFB,0xFF,0x1F,0xEF,0xA5,0xFD,0xBF, -0xDF,0xFB,0x7D,0xFF,0xBF,0xDF,0xFB,0xFF, 0xFD,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, -0xAF,0xF3,0xFF,0xFB,0x7F,0xBF,0xD7,0xFB, 0xBF,0x7F,0xBB,0xF7,0xFF,0xF8,0x7F,0xFF, -0xFA,0x5F,0xD7,0xFF,0xDF,0x7F,0xEF,0xFF, 0xFF,0x7F,0xDB,0xF7,0xFD,0xFF,0x7F,0xDF, -0xB7,0xFB,0xEC,0xFF,0xFF,0xF7,0xBF,0xEF, 0xFD,0xFC,0xFB,0xFF,0xEF,0xF0,0xFE,0x3F, -0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xEF,0x8D, 0xFF,0xFF,0xEF,0x7F,0xBF,0xFF,0xFB,0xFF, -0xDB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xEF,0xD8,0xFF,0x2E,0x7F, -0xBE,0xEF,0xFE,0x6E,0xFF,0xBF,0xF9,0xFF, 0xFF,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFC,0x66,0xBE,0x47,0xF3,0x7F,0xDF,0xFE, 0x87,0x9F,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0x6F,0x7C, 0xFB,0x4F,0xD2,0xFF,0xFD,0x2B,0xFE,0xFF, -0xFF,0xFD,0x5F,0xD7,0xD5,0xF5,0x7D,0xFF, 0xFF,0xFF,0xBF,0x9B,0xFF,0xFF,0xDF,0xB7, -0xFF,0xFF,0xDF,0xFF,0x3F,0xCF,0xFE,0x7F, 0xBF,0xEF,0xFB,0xFC,0xFF,0x3F,0xFF,0xD9, -0xBF,0xFE,0x97,0xEC,0x8F,0xB7,0xFE,0x9B, 0x7D,0xFD,0xB7,0xDD,0x77,0x1D,0xC7,0x71, -0xDD,0x77,0x5D,0xD7,0xF3,0x6F,0xFD,0x3F, 0x73,0xDD,0xAF,0xFD,0x7A,0xFF,0xFF,0xAF, -0xFE,0xFD,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF, 0xEF,0x66,0x7F,0xFF,0xFF,0xBF,0xBF,0xFF, -0xFB,0xFF,0xF7,0xDF,0xFD,0xFB,0x7D,0xDF, 0xB7,0xCD,0xF3,0x7C,0x5F,0x3F,0x91,0x3F, -0xFF,0x3D,0xEF,0x7B,0xFF,0xFC,0xFF,0xCA, 0xEF,0xFE,0xFF,0xBD,0xEF,0xFB,0x1E,0xE7, -0xBB,0xEC,0x7F,0xB3,0xFF,0xFD,0x9F,0xFF, 0xFF,0xFE,0xFF,0xFF,0x7F,0xBF,0xFB,0xFE, -0xFF,0xBF,0xEF,0xFB,0xEE,0xFB,0xBF,0xDF, 0x67,0xFF,0xFF,0xBF,0xEF,0xDB,0xFF,0xBC, -0xFE,0x7F,0xFB,0xFF,0x9F,0xEF,0xF9,0xFE, 0x7F,0x9F,0xE7,0xF9,0xFE,0x87,0xFF,0xEE, -0xFB,0xBE,0xE5,0xBF,0xEF,0xF9,0xD7,0x65, 0xF7,0xDD,0xE7,0x7D,0xDF,0x77,0x5D,0xD7, -0x7F,0xF8,0x9B,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xFF,0xBF,0xEF,0xFB,0xFF,0x7F,0xCF, -0xF3,0xFC,0xFF,0xBF,0xEF,0xFF,0xDB,0x3F, 0xEF,0xFB,0xFE,0xFF,0xDF,0xFF,0xFE,0xFB, -0xBB,0xEF,0xBF,0xEF,0xBB,0xEE,0xFB,0xBE, 0xEF,0xBB,0xFF,0xFC,0x7F,0xFD,0x3B,0x5B, -0xD6,0xE5,0xFD,0x4F,0xC3,0xFB,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF, -0xB4,0xFF,0xFA,0xBC,0x8F,0xB2,0xE9,0xD2, 0x2E,0xCF,0xFB,0xFF,0xBF,0xEF,0xFB,0xFE, -0xFF,0xBF,0xEF,0xFB,0xFF,0xEC,0xFF,0xFD, 0xFD,0x7F,0xDF,0xF7,0xE4,0xDF,0x5F,0xFF, -0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xC3,0xFF,0xEF,0xE6,0xF8,0xFE, -0x3F,0x8B,0x83,0xF9,0xFE,0x7F,0xE7,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x17, -0xFD,0xFF,0xFF,0xFF,0x7F,0x5F,0xF7,0x2C, 0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xE7,0xF9, -0xFE,0x7F,0x9F,0xFE,0x2F,0xFF,0xFF,0xEF, 0xFF,0xFE,0xBF,0xEF,0xAD,0xFF,0xFF,0x7F, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFE,0xDF,0xFF,0xDF,0xFF,0xFD,0xFD,0x7F, -0xDF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x3F,0xFE, -0xF7,0xFD,0xEF,0x7A,0xFF,0xB1,0xBD,0xFF, 0x7F,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD, -0xFF,0x7F,0xF3,0x27,0xFF,0xDF,0xFF,0xDD, 0xFF,0xFC,0x9B,0xFF,0xCB,0xFC,0xBF,0x2F, -0xCB,0xF2,0xFC,0xBF,0x2F,0xC9,0xFF,0xDE, 0xFF,0xDF,0xAF,0xEB,0xDA,0xFE,0xBB,0xAF, -0xEB,0xF8,0xF7,0xAF,0xE8,0xFA,0xFE,0xBF, 0xAF,0xEB,0xF2,0xFF,0xFD,0xFF,0xFF,0xEF, -0xBD,0xD7,0xBF,0xFF,0xFF,0xDE,0x8F,0xB8, 0xDE,0x37,0x8D,0xA3,0x78,0xDA,0x3F,0x8F, -0xFF,0xA1,0xFF,0xFF,0xFB,0xFB,0xFF,0xFF, 0xFF,0xFF,0xA7,0xBD,0xFB,0x76,0xFD,0xBF, -0xEF,0xDB,0xFE,0xBB,0xBF,0xFE,0x27,0x7F, 0xFF,0xFE,0xFE,0xFD,0xF5,0xFF,0xEF,0xF5, -0xDF,0x1F,0xE7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0xFF,0xCD,0xFD,0xAE,0xFF,0xFA, -0x3E,0x3F,0xAB,0xFD,0xF8,0x7E,0x8F,0xE3, 0xF8,0xFE,0x3E,0x8F,0xE3,0xF8,0xFF,0xFE, -0x1F,0xEF,0xDF,0xBF,0xFE,0xDE,0xDF,0xD9, 0xFF,0xDF,0xBC,0xFF,0xFF,0x7F,0xFF,0xEF, -0xFD,0x7F,0xDF,0xF7,0xF9,0x3F,0xFE,0xFF, 0xFF,0x6F,0xFE,0xDE,0xBF,0xF7,0xED,0xEA, -0xFD,0x8F,0x83,0xF8,0xEA,0x3F,0x8F,0xEF, 0xFF,0xF4,0x7F,0xFF,0xEF,0xEF,0x7B,0xF3, -0xF1,0x5F,0xFF,0xFF,0xF1,0x3B,0x7F,0xDF, 0xF7,0xFD,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF, -0xFF,0xFF,0xF7,0xFF,0x6F,0xFF,0x7F,0xFF, 0xFF,0xF7,0xDE,0xF7,0xBF,0xEF,0xFB,0xF7, -0xFD,0xFF,0xFF,0xF5,0xFA,0xFF,0xFF,0xFB, 0xE7,0xFF,0xF3,0xF8,0x7F,0xF3,0xDF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0xEF, 0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, -0xFF,0x7F,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xCF,0xFF,0x37,0xFF,0xFF, -0x7F,0xDF,0x77,0x5D,0xE7,0xFC,0xFF,0xBF, 0xF7,0xF5,0xFB,0xFF,0xFF,0xD7,0xF5,0xFB, -0xFF,0xFF,0x45,0xFD,0x7F,0xEA,0xFD,0xBE, 0xBF,0xDF,0xF7,0xFF,0xFF,0xDB,0xFB,0xFE, -0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0xFB,0x5F, 0x7F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFE,0xFF,0xEF,0xFD,0xFF,0x7F,0xDF, 0xFF,0xEF,0xFB,0xF8,0x0F,0xF3,0xFF,0xF9, -0x2E,0xFB,0xFE,0xFC,0xF3,0xEF,0xFF,0xFF, 0xBF,0xFF,0xFB,0xE7,0xFF,0xFE,0x7E,0xFF, -0xC0,0x6B,0xCF,0xFF,0x34,0xDF,0xF1,0xFD, 0xFF,0xEF,0xFF,0xFF,0xFF,0xDF,0xF7,0xFD, -0xCF,0x7F,0x9C,0xFD,0xFD,0x6C,0xF7,0xFF, 0xF6,0xFD,0xEB,0x2B,0x9F,0xFF,0xFC,0xFE, -0x7E,0xFF,0xFF,0xFF,0xFF,0xD7,0xF3,0xF7, 0xFF,0xFB,0xE1,0xBF,0xFF,0xEB,0x7A,0xDE, -0xD7,0xFB,0xFF,0xF9,0xFE,0xFF,0xFF,0xF3, 0xDE,0x7F,0xFD,0xE7,0x7F,0xFF,0xFD,0xBB, -0xFF,0xFF,0x7E,0xCC,0xF6,0xAF,0x5F,0x7F, 0xFE,0xF4,0x7D,0xF7,0xFD,0xBB,0x6E,0xDB, -0xB7,0xFF,0xF7,0xDF,0x66,0xFF,0xFF,0xF7, 0x3D,0xCF,0xDE,0xBD,0xFF,0xFF,0xDE,0xDB, -0x8D,0xF7,0x7E,0xDF,0xB7,0xEF,0x7F,0xFF, 0xF6,0x87,0xFF,0xFF,0xEF,0xFE,0xDE,0xBF, -0xFF,0xFF,0xFF,0xBB,0xEF,0xFD,0xFF,0x7B, 0xDE,0xF7,0x3F,0xFF,0xBF,0xFB,0xDB,0xFF, -0xF2,0xB6,0xFD,0xBD,0x7F,0xE7,0xFF,0xFF, 0xFF,0x6F,0xF7,0xFF,0xFF,0xFF,0xFE,0x77, -0xFF,0xBF,0xF8,0xAF,0xFF,0xDF,0xBF,0xFF, 0xBF,0x7F,0xFB,0xFF,0xFF,0xFF,0xDB,0xFE, -0xFF,0xBF,0xFF,0xFA,0xFF,0xFD,0xFF,0xF6, 0x7F,0xFF,0x9F,0xFF,0xFF,0x3F,0xEF,0xF8, -0xEE,0x7E,0x9F,0xBA,0xFE,0xBF,0x8F,0xEF, 0xFE,0xFE,0xF9,0xFF,0xFA,0x7F,0xFE,0x7E, -0xBF,0xAF,0xFB,0x96,0xFD,0x9F,0xEF,0x5E, 0x65,0xBE,0xEF,0x5B,0xB6,0xFF,0xBE,0xE3, -0xFF,0xB5,0xBF,0xFF,0xFD,0xFF,0x7F,0xFF, 0xEF,0xDF,0xFE,0xFF,0xBF,0xFB,0xFE,0xFF, -0xBF,0xCF,0xFF,0xFF,0xFF,0xFD,0x9B,0xFF, 0xFE,0xFB,0xFE,0xDF,0xFF,0x7F,0xFF,0xF7, -0xFE,0xFF,0xDF,0xFB,0xFB,0xFE,0xFF,0xFF, 0xFF,0xFF,0xFF,0xB7,0xFE,0xFA,0xFF,0xAB, -0xEF,0xFF,0xFD,0xB5,0x7B,0x7F,0xFB,0xF7, 0xFD,0xFF,0xFF,0xDD,0xFF,0xEF,0x8F,0xFF, -0x2F,0xFF,0xFB,0x7C,0xFF,0x3F,0xDF,0x73, 0xEB,0xFE,0x3F,0xFF,0xEF,0xFB,0xFE,0xFF, -0xEF,0xFD,0xFF,0xBF,0xFD,0x0F,0xFF,0xFF, 0xFF,0xF5,0xF9,0xFF,0x7F,0xD7,0xFD,0xFF, -0xDF,0xFF,0xF7,0xFB,0xFF,0x7F,0xBF,0xFF, 0xFF,0xF0,0x9F,0xFF,0xFE,0x7F,0x8B,0xE3, -0xF9,0xDE,0x27,0x9B,0xE6,0xBE,0x7F,0x9B, 0xC3,0xF8,0xDE,0x7F,0x9D,0xE7,0xFE,0x7F, -0xFF,0xFF,0x5F,0xD7,0xFF,0xFF,0xFF,0x4F, 0xFB,0xFF,0xFF,0x7F,0xFF,0xAF,0xFF,0x9F, -0x7F,0xFB,0xFF,0xE8,0xFF,0xFF,0xFE,0xBF, 0xAF,0xFF,0xFF,0xFE,0xBF,0xEF,0xF7,0xFF, -0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, 0xFC,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF, -0xFD,0x3F,0xCF,0xFF,0xFF,0xFF,0xFF,0xF7, 0xFF,0xFD,0x7F,0xFF,0xFF,0x93,0xFF,0xFF, -0x7A,0xDF,0xF7,0xFF,0xFF,0x7B,0x7F,0xB7, 0xEF,0xFF,0xFF,0xFD,0xBF,0xFD,0xFB,0xFF, -0xF7,0xFF,0xD7,0xFF,0xFF,0xFF,0xFC,0x9F, 0x6F,0xCB,0xFF,0xF4,0xBB,0xDF,0xD6,0xFD, -0xBF,0x2F,0xD3,0xF7,0xFF,0xDF,0xFF,0xCF, 0xFF,0xFA,0xBE,0xBD,0xAF,0x6A,0xDA,0xBE, -0xBB,0xAB,0x3A,0xBE,0x2D,0xAE,0xEB,0xDA, 0xF6,0x3F,0xAD,0xF5,0xDD,0xFF,0xCF,0xF1, -0xFF,0xF9,0x7F,0xFF,0x73,0xFE,0xFF,0xCF, 0xC3,0xF4,0xF7,0x2F,0xF3,0xFF,0xFC,0xFF, -0x7C,0x1F,0xFF,0x3F,0x4F,0xFF,0x7E,0xFF, 0xEF,0xBD,0xF6,0xFE,0xFF,0x2B,0xEF,0xDC, -0xFB,0xFD,0xFF,0xFB,0xFF,0xEA,0x7B,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFB,0xF7,0xDF,0xFF, -0xE3,0x7D,0xFF,0xB7,0xFF,0xBF,0xFF,0xFF, 0xDF,0xFF,0xF8,0xFF,0xBF,0xFF,0xBF,0xEB, -0xE7,0xFA,0xFE,0x3D,0xBF,0xE9,0xFC,0xBF, 0xFF,0xFA,0xFB,0xFE,0xFF,0xFF,0xFF,0xD9, -0xFF,0xFF,0xFF,0xF6,0x7F,0xFF,0xF6,0x7D, 0xFF,0xDF,0xCF,0xFD,0xBF,0xFB,0xEF,0x7E, -0xFF,0x7F,0xFF,0xFF,0xD3,0xFF,0xFD,0xFB, 0xFF,0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xBF, -0xFE,0xFF,0xF7,0xEF,0xFF,0xFF,0xFF,0xFB, 0xFF,0x87,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF, -0x7B,0xFE,0xFF,0xFE,0x3B,0xF7,0xF7,0xFF, 0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF, -0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xF7, 0xFF,0xFF,0xAD,0xFF,0xFE,0xF7,0xFF,0xFF, -0x5F,0xFF,0xFF,0xDF,0xFF,0xFD,0xFF,0xF5, 0xFF,0xDF,0xFF,0xBD,0xFF,0xE9,0xFF,0xC7, -0xF3,0xFF,0xFF,0xF7,0xFF,0xF3,0xFF,0xF8, 0x3B,0xFF,0xFF,0x7B,0xDF,0xBF,0xFB,0xEF, -0xFB,0xFF,0xFB,0xF7,0xF7,0xBB,0xFF,0xFF, 0xFF,0xFF,0xFB,0xFF,0xFE,0x7F,0xF3,0x7F, -0x5E,0xB7,0xBF,0xFD,0x7F,0xFF,0xF9,0x7F, 0xFB,0xFF,0xEB,0xFD,0x7F,0x7F,0xFF,0xEF, -0xFB,0xE0,0x3F,0xFE,0xBF,0xBF,0xDF,0xFF, 0x7E,0xFF,0xF7,0xFF,0xFF,0xFE,0xBF,0xFF, -0xDB,0x78,0xFF,0xFF,0xFF,0xEE,0xA1,0xBF, 0xF5,0xDE,0xFB,0xF7,0xFF,0xFB,0xFF,0xFF, -0xFF,0xFF,0xFB,0xFF,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xEF,0xF0,0xFF,0xFF,0xFF,0xF3, -0xF7,0xFF,0xEF,0xFF,0xE7,0xCF,0xFF,0xFB, 0xFF,0xEF,0xFF,0xFF,0x9F,0x9F,0xEF,0xFC, -0x16,0xBF,0xFE,0xF3,0xE4,0xFF,0xFF,0xC6, 0xFF,0xE7,0xFF,0xFF,0xFD,0xFF,0xBF,0xFF, -0xFF,0x3F,0xFF,0xBF,0xD6,0xAF,0x7F,0xFE, 0x6B,0x7E,0x7F,0xFF,0xAF,0xFF,0xFF,0xBF, -0xFF,0x5F,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF, 0xFF,0xBD,0xDB,0xFF,0xFE,0x5F,0xF2,0xFF, -0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xEF,0x7F,0xFF,0xFF,0xFF,0xFF,0xDE,0xBF, -0xFF,0xFF,0xEF,0xFB,0x77,0xFE,0xBD,0x7F, 0x5F,0xFF,0xFF,0xFF,0xDF,0x6F,0xED,0xFF, -0xFD,0xFF,0x7F,0xFD,0x6F,0xFF,0xFF,0x77, 0xDA,0xCF,0xFD,0x5F,0xFF,0xBF,0xFF,0xFF, -0xDF,0x7F,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF, 0x66,0x7F,0xFF,0xFE,0xBF,0xE7,0xBF,0xFA, -0xFF,0xFE,0xFF,0xFF,0xFF,0xDF,0xFF,0x59, 0xEF,0xFF,0xEF,0xFB,0x7F,0x89,0xFF,0xFF, -0xE9,0xFF,0x6F,0xFF,0xF5,0xFF,0xFF,0xFF, 0xFF,0xFF,0x7F,0xF2,0xF7,0xFF,0xFF,0xEF, -0xF8,0x7F,0xFB,0xFF,0xFD,0xFF,0xFF,0xD9, 0xFF,0xEF,0xBB,0xFF,0xFF,0xFF,0xBF,0xEF, -0xDE,0xFF,0xFF,0x9F,0x7F,0xDF,0xFF,0xF7, 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xAF, -0xFF,0xFF,0xF7,0x3F,0xEB,0x9F,0xFE,0x7F, 0x9E,0x7F,0x9F,0xFE,0x87,0xFF,0xED,0xDB, -0x56,0xFF,0xBF,0xAF,0x0B,0xD2,0xFF,0xEF, 0xDB,0x6E,0x7D,0xBD,0x6F,0xF8,0xFE,0x3F, -0xFA,0x5B,0xFF,0xFD,0xBF,0xEF,0xFF,0xBF, 0x6F,0xDB,0xE6,0xFF,0xFF,0x3F,0xFF,0xDF, -0xFE,0xFF,0xFF,0xFF,0xFF,0xDA,0x3F,0xFF, 0xFB,0xFE,0xFE,0xFF,0xFF,0xDF,0xF7,0xBD, -0xFF,0xFD,0xFF,0xFE,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFF,0xF1,0x5F,0xFD,0x9F,0xDF,0xFD, -0xFF,0xFD,0x7F,0xFF,0xFF,0xFF,0xFF,0x76, 0xFA,0xFF,0xFF,0x7F,0xE3,0xF8,0xFF,0xAE, -0xFF,0xFB,0x7E,0x9D,0x73,0xFF,0xFA,0x7F, 0xDF,0xFF,0xFF,0x7F,0xFF,0xFB,0xCD,0xFF, -0x7F,0xEF,0xFB,0xFF,0xFD,0xFF,0xF7,0x7F, 0x7F,0xEF,0xFF,0xED,0xFF,0xFF,0xFF,0xB5, -0xFF,0xBF,0xFF,0xBF,0xFD,0xEF,0xDB,0xF7, 0xFF,0x93,0xFF,0xEF,0xE2,0xF9,0xBE,0x7F, -0x8B,0xE7,0xF9,0xFE,0x6B,0xE7,0xF9,0xFE, 0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x47,0xFF, -0xFF,0xFD,0xFF,0x9F,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xF5,0xFF,0x9F,0xFF,0xF7,0xFE, -0xFF,0xBF,0xFE,0x6F,0xFF,0xFF,0xFB,0xFF, 0xFF,0xFF,0xAF,0xFF,0xFF,0xFF,0x7F,0xFB, -0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, 0xDF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xDF, -0xFF,0xFF,0xFF,0x5F,0xFF,0xFF,0xFF,0xFF, 0x5F,0xFB,0xFE,0xFF,0xF8,0x37,0xFF,0xFF, -0xEF,0xFF,0x7F,0xFE,0xBF,0xFF,0xFF,0xFE, 0xBF,0xFF,0xFF,0x7F,0xFF,0xBF,0xFD,0xFF, -0x7F,0xFA,0x7F,0xFF,0xFF,0x6F,0xFF,0xFF, 0x7D,0xFF,0xCF,0xFF,0xFF,0xFF,0x4F,0xFF, -0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xBF, 0xFF,0xAE,0xEB,0xFA,0xFE,0xBB,0xAD,0xEB, -0xFA,0xF7,0xAF,0x6B,0xFA,0xF6,0xBF,0x25, 0xE9,0xF2,0x7F,0x45,0xFF,0xFF,0xFD,0xF7, -0xF7,0xBF,0xFF,0xDF,0xFF,0xFF,0xBF,0xFB, 0xFF,0xDF,0xF3,0xFF,0xF7,0x3F,0xCF,0xFF, -0xA1,0xFF,0xFF,0xBF,0xE7,0xFF,0xFF,0x7F, 0xFF,0x3D,0xFF,0xFF,0xFF,0xF7,0xFF,0x2F, -0xFF,0xFB,0xF5,0x7F,0xFE,0x57,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, -0x3F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD,0xFE, 0xF7,0xEE,0xAF,0xFE,0xEE,0xE7,0xFA,0xFF, -0xFE,0x9D,0xF9,0x5E,0xFE,0xFF,0xEB,0xFF, 0xFF,0xDF,0xA7,0xFF,0xFF,0xFF,0xFC,0xDB, -0xFF,0xFF,0xFF,0x7E,0xFB,0xFF,0xFF,0xEF, 0xFB,0xFD,0xFF,0xDB,0xFF,0xFF,0xFF,0xEF, -0xFF,0xFF,0xFF,0xFD,0xBF,0xFE,0xBF,0xFF, 0x6F,0x7F,0xFF,0xF7,0xFF,0xFF,0xF9,0xFF, -0xF7,0xFF,0xBF,0xDE,0xF7,0xFF,0xFF,0xFF, 0xFA,0x7F,0xFD,0xBF,0x5F,0xFF,0xFF,0xBF, -0xFF,0xED,0xFF,0xF7,0xBF,0xFF,0xFF,0xEF, 0xFF,0xDF,0xFF,0xFF,0xFF,0xE6,0xFF,0xFB, -0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0xFF, -0xFD,0xFF,0xF5,0xFF,0xF6,0x7F,0xDF,0xBD, 0xCF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF, -0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3, 0xFF,0xEE,0xBF,0xFF,0x7D,0xEF,0xFE,0xFF, -0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFE, 0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xB5,0xAE, -0xFF,0xFF,0xB6,0xFE,0xBF,0xFF,0xFF,0xBF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0x27,0xFF,0xEF,0xFE,0x7F,0xDF,0xFF, 0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFD,0xFF,0xF7,0xF9,0x9F,0xFF, 0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F, -0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0x0F,0xFF,0xE7,0xBF,0xFE, -0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFC,0xBF, 0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xC4, -0x6B,0xFF,0x29,0x1F,0xFB,0xAF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xEF,0x1B,0xFE,0xFF,0xFC, -0x6F,0xFF,0xFF,0xFD,0x6A,0xF7,0xD7,0xF5, 0xBF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFE,0xBF,0xFF,0xFF,0xFA,0xFF,0xFF,0xF7, 0xFB,0xDD,0xBF,0xFF,0xE7,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x7F,0xFF, 0xFF,0xF5,0xFF,0xFF,0xF7,0xFD,0xB3,0xEF, -0xFD,0x7E,0x5D,0xFF,0xFD,0xFF,0xFF,0xFF, 0xFD,0x7F,0xD2,0xF5,0xFB,0x7E,0xCB,0xB7, -0xFF,0xFF,0xFF,0xC6,0xFF,0xFD,0xEE,0x63, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xFD,0x65, -0x5B,0xDF,0xFF,0xD5,0xFF,0xFF,0xFF,0xF6, 0xE7,0xBF,0xF7,0xA9,0xFF,0xFF,0xED,0xFF, -0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFF,0xFF, 0xAF,0xFF,0xFF,0xFF,0xF8,0x1B,0xFF,0xE3, -0xD0,0xBF,0xFF,0xE1,0xFF,0xFF,0xFF,0xFF, 0xFF,0xD7,0xFF,0xFF,0xFF,0x5F,0xFF,0xFF, -0xFF,0xFF,0xAF,0xFF,0xDB,0x76,0xBF,0xFF, 0x7F,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF, -0xFB,0xFE,0xFF,0xFF,0xFF,0xBF,0xF2,0x7F, 0xFF,0x9F,0xFE,0xBD,0xFE,0x7F,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xF7,0x3F,0xEC,0x7F,0xF6,0x95,0xBB, -0xEF,0xF8,0xFE,0xFC,0xBF,0x2F,0xDA,0xFC, 0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xEF,0xFF, -0xA9,0xBF,0xCF,0xFB,0xFF,0xFF,0xFF,0xFE, 0xDD,0xB7,0x6D,0xF6,0xD9,0xB6,0x6D,0x9B, -0x76,0xD9,0xBF,0xFB,0xFD,0xA3,0xFF,0xBF, 0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0x7F,0xDF, -0xFD,0xEF,0x7B,0xDE,0xF7,0xFD,0xEF,0x7F, 0xFF,0xFF,0x05,0xFF,0xFA,0xFE,0x7F,0xEF, -0xE3,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF, 0xFF,0x5F,0xFF,0xFF,0xFD,0x7F,0xFB,0xAF, -0xFF,0x63,0xC8,0xFF,0xBF,0xEF,0xFF,0xFF, 0xFA,0x7F,0xFF,0xFF,0xFF,0xFE,0x9F,0xF7, -0xFF,0xFA,0xBF,0xFE,0x9F,0xFB,0x7F,0xFF, 0xFF,0xEF,0xD7,0xFF,0xFF,0xF5,0xFF,0xFF, -0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xBF,0xFF, 0xF9,0xBF,0xFF,0xBE,0x27,0x9F,0xE7,0xF9, -0xFE,0x7F,0x8B,0xE7,0xFE,0x7F,0x9F,0xE2, 0xF9,0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF, -0xFF,0xFF,0xFB,0xFE,0xFF,0xFF,0xFF,0xD7, 0xFF,0xFF,0xFF,0xFF,0xF5,0xFF,0xFF,0xFF, -0xD7,0xFF,0xFA,0xFF,0xFE,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF,0xAF,0xF7,0xFF,0xFF, -0xFF,0xEB,0xFF,0xFF,0xFF,0xAF,0xFF,0xC4, 0xFF,0xF7,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF, -0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xD7,0xFF, 0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFB,0x7A, -0xDF,0xF7,0xFD,0xFF,0xFF,0xFE,0xBF,0xFF, 0xFF,0x7F,0xFF,0xAF,0xFF,0xFF,0xFF,0xF7, -0xEF,0xE3,0xFF,0xDD,0xD2,0xFF,0xDF,0xFF, 0xFF,0xF2,0xFC,0xBF,0xCB,0xF6,0xFD,0xBF, -0x2F,0xCB,0xFF,0x7F,0xDF,0xDE,0xAF,0xFF, 0xDA,0xEE,0xBF,0xAF,0xE9,0xFA,0xF4,0xBD, -0xAF,0x5A,0xAE,0xBB,0xAB,0x6B,0xDA,0xDE, 0xBF,0xAD,0xD7,0x5E,0xFF,0xFF,0xBF,0xFC, -0xFF,0xDF,0xFD,0xFF,0xFF,0xFF,0xFF,0xDF, 0xF7,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFA, -0x1F,0xFF,0xFE,0xFB,0xEF,0xBF,0xFD,0xFF, 0xFD,0xBD,0x77,0xFF,0xFF,0xFF,0xFF,0x9D, -0xEF,0xFF,0xFF,0xFF,0xEF,0x7D,0xFF,0xFB, 0xFE,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE, 0xBF,0xE4,0xFB,0xFF,0xFE,0x3F,0xFE,0xFF, -0xFF,0xFF,0xFF,0xAF,0xEA,0xFE,0xBF,0xAF, 0xEB,0xFA,0xFE,0xFF,0xFF,0xFF,0x55,0xF6, -0xFF,0xFE,0xF7,0xFF,0x7F,0xFF,0xEB,0xF7, 0x5F,0xC5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF, -0x6F,0xFB,0xFF,0x8A,0xFF,0xFF,0xFF,0xFF, 0xEB,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0xBF, -0xEF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, 0x77,0xDF,0xFB,0xFF,0xFD,0x7F,0xEF,0xFF, -0xFF,0xFF,0xBF,0x7F,0xFF,0xDF,0xBF,0xFF, 0xFB,0xFF,0xFF,0xFF,0xFE,0xEF,0xDF,0xFF, -0xFE,0xFF,0x9F,0xEF,0x7D,0xFF,0xF7,0xFF, 0x7F,0xFF,0xFF,0xDF,0xF7,0xFD,0xFF,0xEF, -0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFB, -0xFD,0xFF,0xBF,0xDF,0xD1,0xFF,0xF8,0x3B, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0x7E,0xDB,0xFD,0xFF,0x77,0xDB,0xB7,0x7D, 0xBF,0xFB,0xFF,0xF8,0x7F,0xED,0x7B,0x5E, -0xFF,0xFE,0xFF,0xFF,0x4F,0xD7,0xFD,0x7F, 0xDF,0xD7,0xF5,0xFF,0x7F,0xFF,0xFF,0xFF, -0xF2,0x3F,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF, 0xFF,0xBF,0xEF,0xFE,0xFF,0x3B,0xEE,0xFF, -0xFC,0xEF,0xFF,0xFF,0xFF,0x85,0xFF,0xFD, 0xFE,0xFF,0xF5,0xFF,0xFF,0xFE,0xFF,0xDF, -0xFB,0xFF,0x5F,0xBF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xA8,0xFF,0xFF,0x9F,0x9E,0xFF, -0xFF,0xFF,0x7F,0xF3,0xFF,0xFF,0xCF,0xFF, 0xF7,0xFD,0xFF,0x7F,0xFF,0xFF,0xFC,0x16, -0xBF,0xCF,0xA3,0xE5,0xEF,0x7F,0xFF,0xF3, 0xE4,0xFF,0xCF,0x93,0xFC,0xFF,0x3F,0xCF, -0xFF,0xFF,0xFF,0xD6,0x0F,0x7D,0xBF,0x6E, 0xFB,0xF4,0xFC,0xAF,0x6D,0xDB,0x77,0xB7, -0x6D,0xDB,0xF6,0xFD,0xBF,0xFF,0xFF,0xFF, 0xBF,0x9B,0xFA,0xDE,0xB7,0xB7,0xED,0xF9, -0x7E,0xB7,0xAC,0xEB,0xD6,0xB3,0xAD,0xEB, 0x7A,0xDF,0xFF,0xFF,0xFF,0xD8,0xBF,0xFF, -0xB7,0xED,0x9F,0x6F,0xDD,0xF7,0x68,0xDB, 0x37,0xB3,0x6C,0xDB,0x36,0xCD,0xB3,0x7F, -0xFF,0x7F,0xF5,0x6F,0xFD,0xEF,0x79,0x3D, 0xF7,0x93,0xE4,0x7A,0x9E,0xAD,0xEA,0x7A, -0x9E,0xF7,0xBD,0xEF,0xFF,0xFF,0xFF,0x76, 0x7F,0xFB,0xC6,0xFF,0xBB,0xEF,0xDA,0xFE, -0xFD,0xBF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xFF,0xFB,0xFF,0xA5,0xFF,0xFD,0xAB, -0x6F,0x78,0xDE,0x17,0x8F,0x79,0xDF,0xFD, 0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xFF,0xFB, -0xFF,0xFB,0xFF,0xEF,0xFB,0xEF,0xFB,0xFE, 0xFF,0xBB,0xDA,0xF3,0xEF,0x3B,0xCE,0xF3, -0xBC,0xEF,0x3F,0xCF,0xDF,0xFF,0xB7,0xFF, 0xFF,0xFF,0xCF,0x73,0xFF,0xBF,0xEF,0xFF, -0xF3,0xFF,0x3F,0xCF,0xF3,0xFC,0xFF,0x3D, 0xCF,0x9F,0xFE,0x07,0xFF,0xAF,0xEB,0xFE, -0xFD,0xBF,0xEF,0xEB,0xFA,0xFF,0xAF,0xEB, 0xFA,0xFE,0xBF,0xAF,0xFB,0xFE,0x3F,0xFB, -0x9B,0xFF,0x7F,0xDF,0xFF,0xF3,0xFE,0xFF, 0xDE,0xF7,0xBF,0x7B,0xDE,0xF7,0xBD,0xEF, -0x7B,0xFE,0xFF,0xFF,0xDF,0x3F,0xFE,0xFF, 0xB7,0xFF,0xEF,0xF7,0xFF,0xBF,0xED,0xFE, -0xDF,0xB7,0xED,0xFB,0x7E,0xDF,0xFF,0xFF, 0xFF,0xFD,0x5F,0xEF,0xEB,0xFA,0xFE,0xF5, -0xBF,0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xF8,0xFF,0xA8,0xFF, -0xFF,0xBF,0xEF,0xFB,0x6A,0xFB,0xB7,0xEF, 0xFB,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF, -0xEF,0xFB,0xFF,0xE0,0xFF,0xFF,0xFD,0x7F, 0x5C,0xD7,0x7D,0xDF,0xF3,0x5C,0xF5,0xCD, -0x73,0x5E,0xD7,0xB5,0xFD,0x7F,0xEF,0xFF, 0xDB,0xFF,0xFF,0xE2,0xF8,0xBE,0x2F,0x8F, -0xE7,0xF8,0xBE,0x6B,0xE2,0xF8,0xBE,0x2F, 0x8B,0xE2,0xF9,0xFE,0x7F,0xE7,0xFF,0xD7, -0xF5,0xFD,0x7F,0xFF,0xF7,0xF5,0xFD,0x7F, 0xD7,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF, -0xFF,0xFF,0x8F,0xFF,0xAF,0xEB,0xFA,0xFF, 0xFF,0xBF,0xEB,0xFA,0xFF,0x2F,0xEB,0xFA, -0xFE,0xBF,0xAF,0xEB,0xFF,0xFF,0xFE,0x5F, 0xFF,0x5F,0xFF,0xFF,0xFD,0xFF,0xFF,0xD7, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xBF,0xFE,0xB7,0xFD, -0xFF,0x7E,0xDF,0xF7,0xAD,0xFF,0x7F,0xF7, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, -0xF6,0x7F,0xFF,0xFF,0xFF,0xDB,0xF6,0xFC, 0xAF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xEC,0xBF,0xFF, 0xAF,0xEB,0xFA,0xF6,0xAB,0x8F,0xEB,0xFA, -0xF7,0xA5,0xEB,0xFA,0xBE,0xBF,0xAF,0xEB, 0xFA,0xFF,0x6D,0xFF,0xFF,0x7F,0xDF,0x33, -0xDD,0xFF,0x7F,0xFE,0xF7,0xFC,0x7F,0xFB, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9, -0xFF,0xFD,0xFF,0xFF,0xFE,0xFF,0xFF,0xDF, 0xFF,0xFF,0xEF,0xEF,0xFD,0xFF,0x7F,0xFF, -0xFF,0xFF,0xFF,0xFE,0xA7,0xFF,0xFF,0xFF, 0x77,0xDF,0xF7,0xFD,0x9F,0x7F,0xFE,0x77, -0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xAF,0xBF,0xAF,0xFF,0xF9,0xBE,0xBF, -0x8F,0xFB,0xFE,0xFE,0xEF,0xFB,0xFE,0xFF, 0xBF,0xEF,0xFB,0xFF,0xFF,0xFD,0xDF,0x6F, -0xEF,0xFF,0x7F,0xFF,0xBF,0xBF,0xDF,0xFF, 0xFC,0xFF,0xDF,0xF7,0xFD,0xEF,0x7F,0xDF, -0xFF,0xFF,0xFF,0x3F,0xF6,0xFF,0xCF,0xFF, 0xDB,0xFB,0xF7,0xFF,0xEB,0x7A,0xFF,0xFF, -0xFF,0xBF,0xEF,0xFB,0xFF,0xFF,0xFF,0xFE, 0x6D,0xFD,0xFF,0x5F,0xFB,0xFF,0xFF,0xF7, -0xFF,0x5F,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFB,0xFF, -0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xE7,0xF6, 0xBF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF, -0xFF,0xC9,0xFF,0xFF,0xFF,0xBD,0xFF,0xBF, 0xAF,0xEF,0xEF,0x3F,0xD1,0xFC,0x7F,0xFB, -0xC7,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0xFF, 0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x77,0xFF, -0xDF,0xB7,0xFD,0xF7,0xFD,0xF7,0xFF,0xFF, 0xFF,0xFF,0xFF,0x57,0xFF,0xF7,0xA5,0xFD, -0x3F,0xDF,0xBF,0xBF,0xFE,0x7F,0xFF,0xFF, 0xFF,0xDF,0xFA,0xFD,0xFF,0xFF,0xFF,0xFE, -0x87,0xFF,0xE9,0xFF,0xFE,0xEF,0xBF,0xEF, 0xFE,0xFE,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFA,0x9F,0xFF,0x3F, 0xFF,0xFD,0xFD,0x57,0xDF,0xFD,0xF3,0xFF, -0xDF,0xFD,0xFF,0x5F,0xDF,0xF5,0xFD,0xFF, 0xFF,0xF9,0x8F,0xFF,0xFF,0xFF,0xEE,0x7F, -0xFF,0xFF,0xBF,0x5E,0xFE,0xEC,0xFB,0x3F, 0x7F,0x9F,0xEF,0xF9,0xFF,0xFF,0xCD,0x6B, -0xFF,0xFF,0xFF,0xC5,0xF3,0xFC,0xFA,0x38, 0xFF,0xAF,0x3F,0xEE,0x7F,0x9F,0xFF,0xD9, -0xFF,0xFF,0xFD,0x7A,0xF7,0xFF,0xF3,0xFF, 0xAF,0x6F,0xDB,0xF2,0xB9,0xE9,0xFB,0xFF, -0xFF,0xFF,0xFE,0xFF,0xFF,0xEF,0xFF,0xFB, 0xC5,0xBF,0xFF,0xEF,0xFF,0x5E,0xB7,0xAD, -0xCD,0x79,0x7C,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0x93,0xFF,0xEF, -0xEA,0xFE,0xBF,0xEF,0x5B,0xD2,0xCD,0xF5, 0x6D,0x77,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF, -0xFF,0xFF,0x66,0xFF,0xD5,0x65,0x7D,0x5F, 0x75,0x9D,0x65,0x7F,0xD6,0xFB,0x4F,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xC7, 0xFF,0xBF,0xEF,0xFA,0xFE,0xFF,0xBF,0xEB, -0xFF,0xDF,0xFF,0x7E,0xFF,0xFF,0xEF,0xFD, 0x7E,0xD7,0xFF,0x78,0xDF,0xFF,0x5F,0xDF, -0xF5,0xBF,0x7F,0xDF,0xC5,0xFF,0x3F,0xF6, 0x7E,0xFF,0x0F,0xEF,0xF2,0x3E,0xBF,0xFF, -0xFB,0x3F,0xFF,0xFB,0x7F,0xFF,0xB3,0xFE, 0xFB,0xF6,0xFD,0xFF,0xDA,0xF7,0xFD,0xFF, -0x7F,0xDF,0xF7,0xBF,0xFF,0xFA,0x7F,0xFF, 0xFF,0xFF,0xFF,0x9F,0xFF,0xF3,0xDC,0xF9, -0xBF,0xCE,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7, 0xFF,0xFF,0xE2,0x7F,0xFE,0xFF,0xBF,0xEF, -0xEB,0xFA,0xFF,0x9F,0x67,0x1E,0xFF,0x8F, 0xE7,0xF8,0xFE,0x7F,0x8F,0xEF,0xFF,0xBD, -0xBF,0xFF,0xFB,0xFF,0xFF,0xDF,0xF7,0xFF, 0xFC,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFD,0xB3,0xFF,0xFF,0xEF, 0xFF,0xFF,0xBF,0xED,0xFF,0xFB,0xEE,0xFE, -0xFF,0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF, 0xFF,0xB5,0xFF,0xB7,0xFD,0xFD,0x6E,0xFF, -0xFF,0xFE,0xFD,0x2F,0xD8,0xFE,0xBF,0x8F, 0xEB,0xF9,0xFE,0x3F,0xFF,0xFA,0xCF,0xFF, -0xE7,0xD9,0xFA,0xBF,0xDF,0x77,0xFC,0xFB, 0x3F,0xAB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFE, -0xFF,0xFF,0xEE,0x1F,0xFF,0xDF,0xF7,0xFF, 0xFF,0xFF,0x5F,0x97,0x35,0xBF,0x5E,0xFE, -0xBF,0xEF,0xFF,0xF7,0xFD,0xFF,0xFF,0xFA, 0xBF,0xFF,0xBE,0x6F,0x9F,0xE7,0xF8,0xBE, -0x2F,0x8B,0x66,0x94,0x7D,0x9D,0xE7,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF,0xFF, -0xFF,0xF7,0xF5,0xFD,0x7F,0x5F,0xFB,0xFD, 0x9E,0xFF,0xFB,0xFE,0xFF,0xFF,0xEF,0xFF, -0xFF,0xA0,0xFF,0xFF,0xFF,0xBF,0xEF,0xEB, 0xFA,0xFE,0xBF,0xB7,0xF7,0xF7,0xFF,0xFF, -0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, 0xFD,0xFF,0xFF,0xFF,0xD7,0xFF,0xFF,0xFF, -0x7F,0xF5,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF, 0xBF,0xFF,0xFF,0xAB,0xFE,0xFB,0xFE,0xFF, -0xF7,0xAF,0xFF,0xFF,0xDE,0xF7,0xEB,0x5F, 0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF,0xFF, -0xB3,0xFF,0xC9,0xFE,0xFF,0xFF,0xFF,0xFF, 0xD6,0xFF,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFC,0x8F,0xFF,0xBA, 0xBE,0xBF,0xAF,0xEB,0x78,0xFE,0xB7,0xAD, -0x3A,0xFE,0xB7,0xAF,0xEB,0x7A,0xFE,0xBF, 0xAF,0xFF,0x9F,0xFF,0xFF,0xDF,0xFC,0xFF, -0xFF,0xFE,0xC3,0xFE,0xFF,0xFF,0x33,0xFC, 0xFF,0xBF,0xDF,0xF3,0xFF,0xFF,0xBB,0x9F, -0xFF,0xFF,0xFF,0xEB,0xDF,0xFF,0xFF,0xAF, 0xF7,0x6F,0xF9,0xBF,0xEF,0xFD,0xFF,0xFF, -0xFF,0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF, 0xFB,0xFF,0xFF,0xBF,0xFD,0xFB,0xF7,0xFF, -0xDF,0xF7,0xFF,0xFE,0xEF,0x5F,0xBD,0xFF, 0xFA,0xFF,0xF8,0xFF,0xBF,0xAF,0xFB,0xFE, -0xFE,0x3F,0xEF,0xE8,0xFF,0xDF,0xF3,0xFD, 0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xFB, -0xFD,0xFF,0xAF,0xFF,0xFF,0xFE,0xFE,0xBF, 0xDB,0xFF,0xFF,0xFF,0xBF,0xFF,0xDF,0xFF, -0xFD,0xFF,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF, 0xBF,0x6F,0xFF,0x7F,0xB7,0xB3,0xFF,0xFF, -0xDF,0xFF,0xFB,0xEF,0xFF,0xFF,0xFF,0x07, 0xFF,0xFB,0xFF,0xFF,0xFF,0xED,0xFF,0xF5, -0x7C,0xFF,0x7F,0xFE,0xFF,0xFF,0xEF,0xCF, 0xFF,0xFB,0xFF,0xFF,0x2F,0xFF,0xFF,0xFF, -0xFF,0xF3,0xFF,0xFB,0xFF,0xFE,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, -0xFD,0x1B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFE,0x7C,0xFF,0xFF,0xFF,0xFF, -0xEF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0x7F, 0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, 0xFF,0xFF,0xF0,0x7F,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xDF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xFE, -0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xEF,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xEF,0xFA,0xB5,0xFF,0xFF,0xFF, 0xF7,0xF7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFB, -0xFC,0xFF,0xFF,0xFE,0xFF,0x7F,0xDF,0xBF, 0xFF,0xCB,0xBF,0xF9,0xFE,0x7F,0x9F,0xE7, -0xF9,0xFE,0x7F,0x97,0xE1,0xFE,0x79,0x9F, 0xE7,0xFD,0xFE,0x7F,0xDF,0xFE,0x37,0xFF, -0xFB,0xDE,0xDE,0xBD,0xEF,0xF3,0xFE,0xFB, 0xAF,0xEB,0xFE,0xFF,0xFF,0xCF,0xFF,0xFE, -0xFF,0xBF,0xFF,0x8F,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xE7,0xF9,0x5E,0x7F,0xEF,0xFB, -0xDA,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD, 0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF, -0xFF,0xFF,0x7F,0xFF,0xFF,0xF7,0xFB,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFC,0x3F,0xFF,0xBF, -0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0x7B,0x7F, 0xBF,0xEF,0xFB,0xFE,0xFF,0xB5,0xEF,0xFB, -0xBF,0xFA,0x7F,0xFC,0xFF,0x3F,0xCF,0xF3, 0xFC,0xFF,0x3F,0xCF,0xBC,0xFF,0x3F,0xEF, -0xF3,0xFC,0xFE,0x3F,0xCF,0xFF,0xEE,0xEF, 0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0x6A,0xD7, -0xB7,0xFB,0xF8,0xFF,0xB7,0xEF,0xBA,0xFE, 0xFF,0xBF,0x7F,0xE9,0xFF,0xF9,0x7E,0x5F, -0x97,0xE5,0xF9,0xFE,0x7F,0xBF,0xF9,0x7E, 0x5F,0x9F,0xE5,0xFB,0xFE,0x5F,0xB7,0xFF, -0xA3,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0x5E,0xF7,0x7D,0xFF,0x77,0xDF, -0xF7,0xFD,0xFF,0x7F,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xDF,0xFB,0x7F, -0xFF,0xFF,0xEF,0xFF,0xFE,0xFB,0xFF,0xFF, 0xBF,0xFE,0x8F,0xFF,0xDF,0xF7,0xFD,0xFD, -0x7F,0xDF,0xF7,0xFD,0x3E,0xDF,0xF5,0xBD, 0xFF,0x7F,0xDF,0xF7,0xFD,0xF7,0xFF,0x9F, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFD,0xFF,0xBE,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFD,0x3F,0xFF,0xDF,0xF7, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xCF, -0x77,0xFC,0xFF,0x5F,0xDF,0xF7,0xFD,0xFF, 0xF4,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFD,0xFF,0xFF,0xFF,0xEE,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xED,0xFB,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xE9,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFB,0xFF,0xFF,0xFF,0xD3,0xFF,0xFF, -0xBF,0x3F,0xFB,0xFF,0xFF,0xFF,0xFB,0xF3, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xF7, 0xFF,0xFF,0xFF,0xFF,0x17,0xFF,0xFF,0xFF, -0xDF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF, 0xDF,0xDF,0xFF,0xFD,0xFF,0xFF,0xDF,0xF7, -0xFF,0x4F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD, -0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0x9F,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF, 0xFF,0xFF,0x7A,0x3F,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2, -0x7F,0xFF,0xFB,0xFE,0xFF,0xBF,0xEF,0xF8, 0xFE,0xFF,0xBF,0xFB,0xFE,0xFF,0x8F,0xEC, -0xFB,0xFE,0xFF,0xBF,0xF8,0xF7,0xFE,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFD,0xBF,0xCF,0xEC, -0xFF,0x3F,0xEF,0xDB,0xF8,0xFF,0xBF,0xCF, 0xFF,0xF9,0xFF,0xFF,0xBF,0xFF,0xFB,0xFF, -0xFF,0xFF,0xEF,0xFB,0xDF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xBB,0xFF, -0xEF,0xFB,0xFE,0xEF,0xBF,0xEE,0xEB,0xFB, 0xFE,0xFF,0xEF,0xFE,0xEE,0xBF,0xFE,0xEB, -0xFF,0xEF,0xFF,0x17,0xFF,0x7E,0xEB,0xBB, 0xFE,0xBF,0xBE,0xFB,0xEF,0x5B,0xF7,0xBD, -0xFB,0xCF,0xBF,0xBF,0xBB,0xFB,0x7E,0xCC, 0xEF,0xFF - -}; diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c deleted file mode 100644 index 1774ab7a40d2..000000000000 --- a/drivers/usb/media/dabusb.c +++ /dev/null @@ -1,874 +0,0 @@ -/*****************************************************************************/ - -/* - * dabusb.c -- dab usb driver. - * - * Copyright (C) 1999 Deti Fliegl (deti@fliegl.de) - * - * 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. - * - * - * - * $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $ - * - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dabusb.h" -#include "dabfirmware.h" - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.54" -#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de" -#define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999" - -/* --------------------------------------------------------------------- */ - -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define NRDABUSB 256 -#else -#define NRDABUSB 4 -#endif - -/*-------------------------------------------------------------------*/ - -static dabusb_t dabusb[NRDABUSB]; -static int buffers = 256; -static struct usb_driver dabusb_driver; - -/*-------------------------------------------------------------------*/ - -static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src) -{ - unsigned long flags; - struct list_head *tmp; - int ret = 0; - - spin_lock_irqsave (&s->lock, flags); - - if (list_empty (src)) { - // no elements in source buffer - ret = -1; - goto err; - } - tmp = src->next; - list_move_tail (tmp, dst); - - err: spin_unlock_irqrestore (&s->lock, flags); - return ret; -} -/*-------------------------------------------------------------------*/ -#ifdef DEBUG -static void dump_urb (struct urb *urb) -{ - dbg("urb :%p", urb); - dbg("dev :%p", urb->dev); - dbg("pipe :%08X", urb->pipe); - dbg("status :%d", urb->status); - dbg("transfer_flags :%08X", urb->transfer_flags); - dbg("transfer_buffer :%p", urb->transfer_buffer); - dbg("transfer_buffer_length:%d", urb->transfer_buffer_length); - dbg("actual_length :%d", urb->actual_length); - dbg("setup_packet :%p", urb->setup_packet); - dbg("start_frame :%d", urb->start_frame); - dbg("number_of_packets :%d", urb->number_of_packets); - dbg("interval :%d", urb->interval); - dbg("error_count :%d", urb->error_count); - dbg("context :%p", urb->context); - dbg("complete :%p", urb->complete); -} -#endif -/*-------------------------------------------------------------------*/ -static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q) -{ - unsigned long flags; - pbuff_t b; - - dbg("dabusb_cancel_queue"); - - spin_lock_irqsave (&s->lock, flags); - - list_for_each_entry(b, q, buff_list) { -#ifdef DEBUG - dump_urb(b->purb); -#endif - usb_unlink_urb (b->purb); - } - spin_unlock_irqrestore (&s->lock, flags); - return 0; -} -/*-------------------------------------------------------------------*/ -static int dabusb_free_queue (struct list_head *q) -{ - struct list_head *tmp; - struct list_head *p; - pbuff_t b; - - dbg("dabusb_free_queue"); - for (p = q->next; p != q;) { - b = list_entry (p, buff_t, buff_list); - -#ifdef DEBUG - dump_urb(b->purb); -#endif - kfree(b->purb->transfer_buffer); - usb_free_urb(b->purb); - tmp = p->next; - list_del (p); - kfree (b); - p = tmp; - } - - return 0; -} -/*-------------------------------------------------------------------*/ -static int dabusb_free_buffers (pdabusb_t s) -{ - unsigned long flags; - dbg("dabusb_free_buffers"); - - spin_lock_irqsave(&s->lock, flags); - - dabusb_free_queue (&s->free_buff_list); - dabusb_free_queue (&s->rec_buff_list); - - spin_unlock_irqrestore(&s->lock, flags); - - s->got_mem = 0; - return 0; -} -/*-------------------------------------------------------------------*/ -static void dabusb_iso_complete (struct urb *purb, struct pt_regs *regs) -{ - pbuff_t b = purb->context; - pdabusb_t s = b->s; - int i; - int len; - int dst = 0; - void *buf = purb->transfer_buffer; - - dbg("dabusb_iso_complete"); - - // process if URB was not killed - if (purb->status != -ENOENT) { - unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE); - int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe)); - for (i = 0; i < purb->number_of_packets; i++) - if (!purb->iso_frame_desc[i].status) { - len = purb->iso_frame_desc[i].actual_length; - if (len <= pipesize) { - memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len); - dst += len; - } - else - err("dabusb_iso_complete: invalid len %d", len); - } - else - warn("dabusb_iso_complete: corrupted packet status: %d", purb->iso_frame_desc[i].status); - if (dst != purb->actual_length) - err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length); - } - - if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) { - s->overruns++; - err("overrun (%d)", s->overruns); - } - wake_up (&s->wait); -} -/*-------------------------------------------------------------------*/ -static int dabusb_alloc_buffers (pdabusb_t s) -{ - int buffers = 0; - pbuff_t b; - unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE); - int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe)); - int packets = _ISOPIPESIZE / pipesize; - int transfer_buffer_length = packets * pipesize; - int i; - - dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d", - pipesize, packets, transfer_buffer_length); - - while (buffers < (s->total_buffer_size << 10)) { - b = (pbuff_t) kzalloc (sizeof (buff_t), GFP_KERNEL); - if (!b) { - err("kzalloc(sizeof(buff_t))==NULL"); - goto err; - } - b->s = s; - b->purb = usb_alloc_urb(packets, GFP_KERNEL); - if (!b->purb) { - err("usb_alloc_urb == NULL"); - kfree (b); - goto err; - } - - b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL); - if (!b->purb->transfer_buffer) { - kfree (b->purb); - kfree (b); - err("kmalloc(%d)==NULL", transfer_buffer_length); - goto err; - } - - b->purb->transfer_buffer_length = transfer_buffer_length; - b->purb->number_of_packets = packets; - b->purb->complete = dabusb_iso_complete; - b->purb->context = b; - b->purb->dev = s->usbdev; - b->purb->pipe = pipe; - b->purb->transfer_flags = URB_ISO_ASAP; - - for (i = 0; i < packets; i++) { - b->purb->iso_frame_desc[i].offset = i * pipesize; - b->purb->iso_frame_desc[i].length = pipesize; - } - - buffers += transfer_buffer_length; - list_add_tail (&b->buff_list, &s->free_buff_list); - } - s->got_mem = buffers; - - return 0; - - err: - dabusb_free_buffers (s); - return -ENOMEM; -} -/*-------------------------------------------------------------------*/ -static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) -{ - int ret; - unsigned int pipe; - int actual_length; - - dbg("dabusb_bulk"); - - if (!pb->pipe) - pipe = usb_rcvbulkpipe (s->usbdev, 2); - else - pipe = usb_sndbulkpipe (s->usbdev, 2); - - ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100); - if(ret<0) { - err("dabusb: usb_bulk_msg failed(%d)",ret); - - if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { - err("set_interface failed"); - return -EINVAL; - } - - } - - if( ret == -EPIPE ) { - warn("CLEAR_FEATURE request to remove STALL condition."); - if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) - err("request failed"); - } - - pb->size = actual_length; - return ret; -} -/* --------------------------------------------------------------------- */ -static int dabusb_writemem (pdabusb_t s, int pos, unsigned char *data, int len) -{ - int ret; - unsigned char *transfer_buffer = kmalloc (len, GFP_KERNEL); - - if (!transfer_buffer) { - err("dabusb_writemem: kmalloc(%d) failed.", len); - return -ENOMEM; - } - - memcpy (transfer_buffer, data, len); - - ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300); - - kfree (transfer_buffer); - return ret; -} -/* --------------------------------------------------------------------- */ -static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit) -{ - dbg("dabusb_8051_reset: %d",reset_bit); - return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1); -} -/* --------------------------------------------------------------------- */ -static int dabusb_loadmem (pdabusb_t s, const char *fname) -{ - int ret; - PINTEL_HEX_RECORD ptr = firmware; - - dbg("Enter dabusb_loadmem (internal)"); - - ret = dabusb_8051_reset (s, 1); - while (ptr->Type == 0) { - - dbg("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length); - - ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length); - if (ret < 0) { - err("dabusb_writemem failed (%d %04X %p %d)", ret, ptr->Address, ptr->Data, ptr->Length); - break; - } - ptr++; - } - ret = dabusb_8051_reset (s, 0); - - dbg("dabusb_loadmem: exit"); - - return ret; -} -/* --------------------------------------------------------------------- */ -static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b) -{ - b->size = 4; - b->data[0] = 0x2a; - b->data[1] = 0; - b->data[2] = 0; - b->data[3] = 0; - - dbg("dabusb_fpga_clear"); - - return dabusb_bulk (s, b); -} -/* --------------------------------------------------------------------- */ -static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b) -{ - b->size = 4; - b->data[0] = 0x2c; - b->data[1] = 0; - b->data[2] = 0; - b->data[3] = 0; - - dbg("dabusb_fpga_init"); - - return dabusb_bulk (s, b); -} -/* --------------------------------------------------------------------- */ -static int dabusb_fpga_download (pdabusb_t s, const char *fname) -{ - pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL); - unsigned int blen, n; - int ret; - unsigned char *buf = bitstream; - - dbg("Enter dabusb_fpga_download (internal)"); - - if (!b) { - err("kmalloc(sizeof(bulk_transfer_t))==NULL"); - return -ENOMEM; - } - - b->pipe = 1; - ret = dabusb_fpga_clear (s, b); - mdelay (10); - blen = buf[73] + (buf[72] << 8); - - dbg("Bitstream len: %i", blen); - - b->data[0] = 0x2b; - b->data[1] = 0; - b->data[2] = 0; - b->data[3] = 60; - - for (n = 0; n <= blen + 60; n += 60) { - // some cclks for startup - b->size = 64; - memcpy (b->data + 4, buf + 74 + n, 60); - ret = dabusb_bulk (s, b); - if (ret < 0) { - err("dabusb_bulk failed."); - break; - } - mdelay (1); - } - - ret = dabusb_fpga_init (s, b); - kfree (b); - - dbg("exit dabusb_fpga_download"); - - return ret; -} - -static int dabusb_stop (pdabusb_t s) -{ - dbg("dabusb_stop"); - - s->state = _stopped; - dabusb_cancel_queue (s, &s->rec_buff_list); - - dbg("pending_io: %d", s->pending_io.counter); - - s->pending_io.counter = 0; - return 0; -} - -static int dabusb_startrek (pdabusb_t s) -{ - if (!s->got_mem && s->state != _started) { - - dbg("dabusb_startrek"); - - if (dabusb_alloc_buffers (s) < 0) - return -ENOMEM; - dabusb_stop (s); - s->state = _started; - s->readptr = 0; - } - - if (!list_empty (&s->free_buff_list)) { - pbuff_t end; - int ret; - - while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) { - - dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list); - - end = list_entry (s->rec_buff_list.prev, buff_t, buff_list); - - ret = usb_submit_urb (end->purb, GFP_KERNEL); - if (ret) { - err("usb_submit_urb returned:%d", ret); - if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) - err("startrek: dabusb_add_buf_tail failed"); - break; - } - else - atomic_inc (&s->pending_io); - } - dbg("pending_io: %d",s->pending_io.counter); - } - - return 0; -} - -static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, loff_t * ppos) -{ - pdabusb_t s = (pdabusb_t) file->private_data; - unsigned long flags; - unsigned ret = 0; - int rem; - int cnt; - pbuff_t b; - struct urb *purb = NULL; - - dbg("dabusb_read"); - - if (*ppos) - return -ESPIPE; - - if (s->remove_pending) - return -EIO; - - - if (!s->usbdev) - return -EIO; - - while (count > 0) { - dabusb_startrek (s); - - spin_lock_irqsave (&s->lock, flags); - - if (list_empty (&s->rec_buff_list)) { - - spin_unlock_irqrestore(&s->lock, flags); - - err("error: rec_buf_list is empty"); - goto err; - } - - b = list_entry (s->rec_buff_list.next, buff_t, buff_list); - purb = b->purb; - - spin_unlock_irqrestore(&s->lock, flags); - - if (purb->status == -EINPROGRESS) { - if (file->f_flags & O_NONBLOCK) // return nonblocking - { - if (!ret) - ret = -EAGAIN; - goto err; - } - - interruptible_sleep_on (&s->wait); - - if (signal_pending (current)) { - if (!ret) - ret = -ERESTARTSYS; - goto err; - } - - spin_lock_irqsave (&s->lock, flags); - - if (list_empty (&s->rec_buff_list)) { - spin_unlock_irqrestore(&s->lock, flags); - err("error: still no buffer available."); - goto err; - } - spin_unlock_irqrestore(&s->lock, flags); - s->readptr = 0; - } - if (s->remove_pending) { - ret = -EIO; - goto err; - } - - rem = purb->actual_length - s->readptr; // set remaining bytes to copy - - if (count >= rem) - cnt = rem; - else - cnt = count; - - dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt); - - if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) { - err("read: copy_to_user failed"); - if (!ret) - ret = -EFAULT; - goto err; - } - - s->readptr += cnt; - count -= cnt; - buf += cnt; - ret += cnt; - - if (s->readptr == purb->actual_length) { - // finished, take next buffer - if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) - err("read: dabusb_add_buf_tail failed"); - s->readptr = 0; - } - } - err: //mutex_unlock(&s->mutex); - return ret; -} - -static int dabusb_open (struct inode *inode, struct file *file) -{ - int devnum = iminor(inode); - pdabusb_t s; - - if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB)) - return -EIO; - - s = &dabusb[devnum - DABUSB_MINOR]; - - dbg("dabusb_open"); - mutex_lock(&s->mutex); - - while (!s->usbdev || s->opened) { - mutex_unlock(&s->mutex); - - if (file->f_flags & O_NONBLOCK) { - return -EBUSY; - } - msleep_interruptible(500); - - if (signal_pending (current)) { - return -EAGAIN; - } - mutex_lock(&s->mutex); - } - if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { - mutex_unlock(&s->mutex); - err("set_interface failed"); - return -EINVAL; - } - s->opened = 1; - mutex_unlock(&s->mutex); - - file->f_pos = 0; - file->private_data = s; - - return nonseekable_open(inode, file); -} - -static int dabusb_release (struct inode *inode, struct file *file) -{ - pdabusb_t s = (pdabusb_t) file->private_data; - - dbg("dabusb_release"); - - mutex_lock(&s->mutex); - dabusb_stop (s); - dabusb_free_buffers (s); - mutex_unlock(&s->mutex); - - if (!s->remove_pending) { - if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) - err("set_interface failed"); - } - else - wake_up (&s->remove_ok); - - s->opened = 0; - return 0; -} - -static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - pdabusb_t s = (pdabusb_t) file->private_data; - pbulk_transfer_t pbulk; - int ret = 0; - int version = DABUSB_VERSION; - - dbg("dabusb_ioctl"); - - if (s->remove_pending) - return -EIO; - - mutex_lock(&s->mutex); - - if (!s->usbdev) { - mutex_unlock(&s->mutex); - return -EIO; - } - - switch (cmd) { - - case IOCTL_DAB_BULK: - pbulk = (pbulk_transfer_t) kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL); - - if (!pbulk) { - ret = -ENOMEM; - break; - } - - if (copy_from_user (pbulk, (void __user *) arg, sizeof (bulk_transfer_t))) { - ret = -EFAULT; - kfree (pbulk); - break; - } - - ret=dabusb_bulk (s, pbulk); - if(ret==0) - if (copy_to_user((void __user *)arg, pbulk, - sizeof(bulk_transfer_t))) - ret = -EFAULT; - kfree (pbulk); - break; - - case IOCTL_DAB_OVERRUNS: - ret = put_user (s->overruns, (unsigned int __user *) arg); - break; - - case IOCTL_DAB_VERSION: - ret = put_user (version, (unsigned int __user *) arg); - break; - - default: - ret = -ENOIOCTLCMD; - break; - } - mutex_unlock(&s->mutex); - return ret; -} - -static struct file_operations dabusb_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = dabusb_read, - .ioctl = dabusb_ioctl, - .open = dabusb_open, - .release = dabusb_release, -}; - -static struct usb_class_driver dabusb_class = { - .name = "dabusb%d", - .fops = &dabusb_fops, - .minor_base = DABUSB_MINOR, -}; - - -/* --------------------------------------------------------------------- */ -static int dabusb_probe (struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *usbdev = interface_to_usbdev(intf); - int retval; - pdabusb_t s; - - dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d", - le16_to_cpu(usbdev->descriptor.idVendor), - le16_to_cpu(usbdev->descriptor.idProduct), - intf->altsetting->desc.bInterfaceNumber); - - /* We don't handle multiple configurations */ - if (usbdev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && - le16_to_cpu(usbdev->descriptor.idProduct) == 0x9999) - return -ENODEV; - - - - s = &dabusb[intf->minor]; - - mutex_lock(&s->mutex); - s->remove_pending = 0; - s->usbdev = usbdev; - s->devnum = intf->minor; - - if (usb_reset_configuration (usbdev) < 0) { - err("reset_configuration failed"); - goto reject; - } - if (le16_to_cpu(usbdev->descriptor.idProduct) == 0x2131) { - dabusb_loadmem (s, NULL); - goto reject; - } - else { - dabusb_fpga_download (s, NULL); - - if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) { - err("set_interface failed"); - goto reject; - } - } - dbg("bound to interface: %d", intf->altsetting->desc.bInterfaceNumber); - usb_set_intfdata (intf, s); - mutex_unlock(&s->mutex); - - retval = usb_register_dev(intf, &dabusb_class); - if (retval) { - usb_set_intfdata (intf, NULL); - return -ENOMEM; - } - - return 0; - - reject: - mutex_unlock(&s->mutex); - s->usbdev = NULL; - return -ENODEV; -} - -static void dabusb_disconnect (struct usb_interface *intf) -{ - wait_queue_t __wait; - pdabusb_t s = usb_get_intfdata (intf); - - dbg("dabusb_disconnect"); - - init_waitqueue_entry(&__wait, current); - - usb_set_intfdata (intf, NULL); - if (s) { - usb_deregister_dev (intf, &dabusb_class); - s->remove_pending = 1; - wake_up (&s->wait); - add_wait_queue(&s->remove_ok, &__wait); - set_current_state(TASK_UNINTERRUPTIBLE); - if (s->state == _started) - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&s->remove_ok, &__wait); - - s->usbdev = NULL; - s->overruns = 0; - } -} - -static struct usb_device_id dabusb_ids [] = { - // { USB_DEVICE(0x0547, 0x2131) }, /* An2131 chip, no boot ROM */ - { USB_DEVICE(0x0547, 0x9999) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, dabusb_ids); - -static struct usb_driver dabusb_driver = { - .name = "dabusb", - .probe = dabusb_probe, - .disconnect = dabusb_disconnect, - .id_table = dabusb_ids, -}; - -/* --------------------------------------------------------------------- */ - -static int __init dabusb_init (void) -{ - int retval; - unsigned u; - - /* initialize struct */ - for (u = 0; u < NRDABUSB; u++) { - pdabusb_t s = &dabusb[u]; - memset (s, 0, sizeof (dabusb_t)); - mutex_init (&s->mutex); - s->usbdev = NULL; - s->total_buffer_size = buffers; - init_waitqueue_head (&s->wait); - init_waitqueue_head (&s->remove_ok); - spin_lock_init (&s->lock); - INIT_LIST_HEAD (&s->free_buff_list); - INIT_LIST_HEAD (&s->rec_buff_list); - } - - /* register misc device */ - retval = usb_register(&dabusb_driver); - if (retval) - goto out; - - dbg("dabusb_init: driver registered"); - - info(DRIVER_VERSION ":" DRIVER_DESC); - -out: - return retval; -} - -static void __exit dabusb_cleanup (void) -{ - dbg("dabusb_cleanup"); - - usb_deregister (&dabusb_driver); -} - -/* --------------------------------------------------------------------- */ - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); - -module_param(buffers, int, 0); -MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); - -module_init (dabusb_init); -module_exit (dabusb_cleanup); - -/* --------------------------------------------------------------------- */ diff --git a/drivers/usb/media/dabusb.h b/drivers/usb/media/dabusb.h deleted file mode 100644 index 96b03e4af8b9..000000000000 --- a/drivers/usb/media/dabusb.h +++ /dev/null @@ -1,85 +0,0 @@ -#define _BULK_DATA_LEN 64 -typedef struct -{ - unsigned char data[_BULK_DATA_LEN]; - unsigned int size; - unsigned int pipe; -}bulk_transfer_t,*pbulk_transfer_t; - -#define DABUSB_MINOR 240 /* some unassigned USB minor */ -#define DABUSB_VERSION 0x1000 -#define IOCTL_DAB_BULK _IOWR('d', 0x30, bulk_transfer_t) -#define IOCTL_DAB_OVERRUNS _IOR('d', 0x15, int) -#define IOCTL_DAB_VERSION _IOR('d', 0x3f, int) - -#ifdef __KERNEL__ - -typedef enum { _stopped=0, _started } driver_state_t; - -typedef struct -{ - struct mutex mutex; - struct usb_device *usbdev; - wait_queue_head_t wait; - wait_queue_head_t remove_ok; - spinlock_t lock; - atomic_t pending_io; - driver_state_t state; - int remove_pending; - int got_mem; - int total_buffer_size; - unsigned int overruns; - int readptr; - int opened; - int devnum; - struct list_head free_buff_list; - struct list_head rec_buff_list; -} dabusb_t,*pdabusb_t; - -typedef struct -{ - pdabusb_t s; - struct urb *purb; - struct list_head buff_list; -} buff_t,*pbuff_t; - -typedef struct -{ - wait_queue_head_t wait; -} bulk_completion_context_t, *pbulk_completion_context_t; - - -#define _DABUSB_IF 2 -#define _DABUSB_ISOPIPE 0x09 -#define _ISOPIPESIZE 16384 - -#define _BULK_DATA_LEN 64 -// Vendor specific request code for Anchor Upload/Download -// This one is implemented in the core -#define ANCHOR_LOAD_INTERNAL 0xA0 - -// EZ-USB Control and Status Register. Bit 0 controls 8051 reset -#define CPUCS_REG 0x7F92 -#define _TOTAL_BUFFERS 384 - -#define MAX_INTEL_HEX_RECORD_LENGTH 16 - -#ifndef _BYTE_DEFINED -#define _BYTE_DEFINED -typedef unsigned char BYTE; -#endif // !_BYTE_DEFINED - -#ifndef _WORD_DEFINED -#define _WORD_DEFINED -typedef unsigned short WORD; -#endif // !_WORD_DEFINED - -typedef struct _INTEL_HEX_RECORD -{ - BYTE Length; - WORD Address; - BYTE Type; - BYTE Data[MAX_INTEL_HEX_RECORD_LENGTH]; -} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD; - -#endif diff --git a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c deleted file mode 100644 index 25646804d5be..000000000000 --- a/drivers/usb/media/dsbr100.c +++ /dev/null @@ -1,429 +0,0 @@ -/* A driver for the D-Link DSB-R100 USB radio. The R100 plugs - into both the USB and an analog audio input, so this thing - only deals with initialisation and frequency setting, the - audio data has to be handled by a sound driver. - - Major issue: I can't find out where the device reports the signal - strength, and indeed the windows software appearantly just looks - at the stereo indicator as well. So, scanning will only find - stereo stations. Sad, but I can't help it. - - Also, the windows program sends oodles of messages over to the - device, and I couldn't figure out their meaning. My suspicion - is that they don't have any:-) - - You might find some interesting stuff about this module at - http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr - - Copyright (c) 2000 Markus Demleitner - - 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 - - History: - - Version 0.40: - Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing - - Version 0.30: - Markus: Updates for 2.5.x kernel and more ISO compliant source - - Version 0.25: - PSL and Markus: Cleanup, radio now doesn't stop on device close - - Version 0.24: - Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally - right. Some minor cleanup, improved standalone compilation - - Version 0.23: - Markus: Sign extension bug fixed by declaring transfer_buffer unsigned - - Version 0.22: - Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns, - thanks to Mike Cox for pointing the problem out. - - Version 0.21: - Markus: Minor cleanup, warnings if something goes wrong, lame attempt - to adhere to Documentation/CodingStyle - - Version 0.2: - Brad Hards : Fixes to make it work as non-module - Markus: Copyright clarification - - Version 0.01: Markus: initial release - -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Version Information - */ -#define DRIVER_VERSION "v0.40" -#define DRIVER_AUTHOR "Markus Demleitner " -#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" - -#define DSB100_VENDOR 0x04b4 -#define DSB100_PRODUCT 0x1002 - -/* Commands the device appears to understand */ -#define DSB100_TUNE 1 -#define DSB100_ONOFF 2 - -#define TB_LEN 16 - -/* Frequency limits in MHz -- these are European values. For Japanese -devices, that would be 76 and 91. */ -#define FREQ_MIN 87.5 -#define FREQ_MAX 108.0 -#define FREQ_MUL 16000 - - -static int usb_dsbr100_probe(struct usb_interface *intf, - const struct usb_device_id *id); -static void usb_dsbr100_disconnect(struct usb_interface *intf); -static int usb_dsbr100_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); -static int usb_dsbr100_open(struct inode *inode, struct file *file); -static int usb_dsbr100_close(struct inode *inode, struct file *file); - -static int radio_nr = -1; -module_param(radio_nr, int, 0); - -/* Data for one (physical) device */ -typedef struct { - struct usb_device *usbdev; - struct video_device *videodev; - unsigned char transfer_buffer[TB_LEN]; - int curfreq; - int stereo; - int users; - int removed; -} dsbr100_device; - - -/* File system interface */ -static struct file_operations usb_dsbr100_fops = { - .owner = THIS_MODULE, - .open = usb_dsbr100_open, - .release = usb_dsbr100_close, - .ioctl = usb_dsbr100_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, -}; - -/* V4L interface */ -static struct video_device dsbr100_videodev_template= -{ - .owner = THIS_MODULE, - .name = "D-Link DSB-R 100", - .type = VID_TYPE_TUNER, - .hardware = VID_HARDWARE_AZTECH, - .fops = &usb_dsbr100_fops, - .release = video_device_release, -}; - -static struct usb_device_id usb_dsbr100_device_table [] = { - { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table); - -/* USB subsystem interface */ -static struct usb_driver usb_dsbr100_driver = { - .name = "dsbr100", - .probe = usb_dsbr100_probe, - .disconnect = usb_dsbr100_disconnect, - .id_table = usb_dsbr100_device_table, -}; - -/* Low-level device interface begins here */ - -/* switch on radio */ -static int dsbr100_start(dsbr100_device *radio) -{ - if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 || - usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - DSB100_ONOFF, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x01, 0x00, radio->transfer_buffer, 8, 300)<0) - return -1; - return (radio->transfer_buffer)[0]; -} - - -/* switch off radio */ -static int dsbr100_stop(dsbr100_device *radio) -{ - if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 || - usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - DSB100_ONOFF, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00, 0x00, radio->transfer_buffer, 8, 300)<0) - return -1; - return (radio->transfer_buffer)[0]; -} - -/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ -static int dsbr100_setfreq(dsbr100_device *radio, int freq) -{ - freq = (freq/16*80)/1000+856; - if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - DSB100_TUNE, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - (freq>>8)&0x00ff, freq&0xff, - radio->transfer_buffer, 8, 300)<0 || - usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 || - usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) { - radio->stereo = -1; - return -1; - } - radio->stereo = ! ((radio->transfer_buffer)[0]&0x01); - return (radio->transfer_buffer)[0]; -} - -/* return the device status. This is, in effect, just whether it -sees a stereo signal or not. Pity. */ -static void dsbr100_getstat(dsbr100_device *radio) -{ - if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0) - radio->stereo = -1; - else - radio->stereo = ! (radio->transfer_buffer[0]&0x01); -} - - -/* USB subsystem interface begins here */ - -/* check if the device is present and register with v4l and -usb if it is */ -static int usb_dsbr100_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - dsbr100_device *radio; - - if (!(radio = kmalloc(sizeof(dsbr100_device), GFP_KERNEL))) - return -ENOMEM; - if (!(radio->videodev = video_device_alloc())) { - kfree(radio); - return -ENOMEM; - } - memcpy(radio->videodev, &dsbr100_videodev_template, - sizeof(dsbr100_videodev_template)); - radio->removed = 0; - radio->users = 0; - radio->usbdev = interface_to_usbdev(intf); - radio->curfreq = FREQ_MIN*FREQ_MUL; - video_set_drvdata(radio->videodev, radio); - if (video_register_device(radio->videodev, VFL_TYPE_RADIO, - radio_nr)) { - warn("Could not register video device"); - video_device_release(radio->videodev); - kfree(radio); - return -EIO; - } - usb_set_intfdata(intf, radio); - return 0; -} - -/* handle unplugging of the device, release data structures -if nothing keeps us from doing it. If something is still -keeping us busy, the release callback of v4l will take care -of releasing it. stv680.c does not relase its private -data, so I don't do this here either. Checking out the -code I'd expect I better did that, but if there's a memory -leak here it's tiny (~50 bytes per disconnect) */ -static void usb_dsbr100_disconnect(struct usb_interface *intf) -{ - dsbr100_device *radio = usb_get_intfdata(intf); - - usb_set_intfdata (intf, NULL); - if (radio) { - video_unregister_device(radio->videodev); - radio->videodev = NULL; - if (radio->users) { - kfree(radio); - } else { - radio->removed = 1; - } - } -} - - -/* Video for Linux interface */ - -static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - dsbr100_device *radio=video_get_drvdata(video_devdata(file)); - - if (!radio) - return -EIO; - - switch(cmd) { - case VIDIOCGCAP: { - struct video_capability *v = arg; - - memset(v, 0, sizeof(*v)); - v->type = VID_TYPE_TUNER; - v->channels = 1; - v->audios = 1; - strcpy(v->name, "D-Link R-100 USB FM Radio"); - return 0; - } - case VIDIOCGTUNER: { - struct video_tuner *v = arg; - - dsbr100_getstat(radio); - if(v->tuner) /* Only 1 tuner */ - return -EINVAL; - v->rangelow = FREQ_MIN*FREQ_MUL; - v->rangehigh = FREQ_MAX*FREQ_MUL; - v->flags = VIDEO_TUNER_LOW; - v->mode = VIDEO_MODE_AUTO; - v->signal = radio->stereo*0x7000; - /* Don't know how to get signal strength */ - v->flags |= VIDEO_TUNER_STEREO_ON*radio->stereo; - strcpy(v->name, "DSB R-100"); - return 0; - } - case VIDIOCSTUNER: { - struct video_tuner *v = arg; - - if(v->tuner!=0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: { - int *freq = arg; - - if (radio->curfreq==-1) - return -EINVAL; - *freq = radio->curfreq; - return 0; - } - case VIDIOCSFREQ: { - int *freq = arg; - - radio->curfreq = *freq; - if (dsbr100_setfreq(radio, radio->curfreq)==-1) - warn("Set frequency failed"); - return 0; - } - case VIDIOCGAUDIO: { - struct video_audio *v = arg; - - memset(v, 0, sizeof(*v)); - v->flags |= VIDEO_AUDIO_MUTABLE; - v->mode = VIDEO_SOUND_STEREO; - v->volume = 1; - v->step = 1; - strcpy(v->name, "Radio"); - return 0; - } - case VIDIOCSAUDIO: { - struct video_audio *v = arg; - - if (v->audio) - return -EINVAL; - if (v->flags&VIDEO_AUDIO_MUTE) { - if (dsbr100_stop(radio)==-1) - warn("Radio did not respond properly"); - } - else - if (dsbr100_start(radio)==-1) - warn("Radio did not respond properly"); - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int usb_dsbr100_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl); -} - -static int usb_dsbr100_open(struct inode *inode, struct file *file) -{ - dsbr100_device *radio=video_get_drvdata(video_devdata(file)); - - radio->users = 1; - if (dsbr100_start(radio)<0) { - warn("Radio did not start up properly"); - radio->users = 0; - return -EIO; - } - dsbr100_setfreq(radio, radio->curfreq); - return 0; -} - -static int usb_dsbr100_close(struct inode *inode, struct file *file) -{ - dsbr100_device *radio=video_get_drvdata(video_devdata(file)); - - if (!radio) - return -ENODEV; - radio->users = 0; - if (radio->removed) { - kfree(radio); - } - return 0; -} - -static int __init dsbr100_init(void) -{ - int retval = usb_register(&usb_dsbr100_driver); - info(DRIVER_VERSION ":" DRIVER_DESC); - return retval; -} - -static void __exit dsbr100_exit(void) -{ - usb_deregister(&usb_dsbr100_driver); -} - -module_init (dsbr100_init); -module_exit (dsbr100_exit); - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/media/et61x251.h b/drivers/usb/media/et61x251.h deleted file mode 100644 index eee8afc9be72..000000000000 --- a/drivers/usb/media/et61x251.h +++ /dev/null @@ -1,234 +0,0 @@ -/*************************************************************************** - * V4L2 driver for ET61X[12]51 PC Camera Controllers * - * * - * Copyright (C) 2006 by Luca Risolia * - * * - * 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. * - ***************************************************************************/ - -#ifndef _ET61X251_H_ -#define _ET61X251_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "et61x251_sensor.h" - -/*****************************************************************************/ - -#define ET61X251_DEBUG -#define ET61X251_DEBUG_LEVEL 2 -#define ET61X251_MAX_DEVICES 64 -#define ET61X251_PRESERVE_IMGSCALE 0 -#define ET61X251_FORCE_MUNMAP 0 -#define ET61X251_MAX_FRAMES 32 -#define ET61X251_COMPRESSION_QUALITY 0 -#define ET61X251_URBS 2 -#define ET61X251_ISO_PACKETS 7 -#define ET61X251_ALTERNATE_SETTING 13 -#define ET61X251_URB_TIMEOUT msecs_to_jiffies(2 * ET61X251_ISO_PACKETS) -#define ET61X251_CTRL_TIMEOUT 100 -#define ET61X251_FRAME_TIMEOUT 2 - -/*****************************************************************************/ - -static const struct usb_device_id et61x251_id_table[] = { - { USB_DEVICE(0x102c, 0x6151), }, - { USB_DEVICE(0x102c, 0x6251), }, - { USB_DEVICE(0x102c, 0x6253), }, - { USB_DEVICE(0x102c, 0x6254), }, - { USB_DEVICE(0x102c, 0x6255), }, - { USB_DEVICE(0x102c, 0x6256), }, - { USB_DEVICE(0x102c, 0x6257), }, - { USB_DEVICE(0x102c, 0x6258), }, - { USB_DEVICE(0x102c, 0x6259), }, - { USB_DEVICE(0x102c, 0x625a), }, - { USB_DEVICE(0x102c, 0x625b), }, - { USB_DEVICE(0x102c, 0x625c), }, - { USB_DEVICE(0x102c, 0x625d), }, - { USB_DEVICE(0x102c, 0x625e), }, - { USB_DEVICE(0x102c, 0x625f), }, - { USB_DEVICE(0x102c, 0x6260), }, - { USB_DEVICE(0x102c, 0x6261), }, - { USB_DEVICE(0x102c, 0x6262), }, - { USB_DEVICE(0x102c, 0x6263), }, - { USB_DEVICE(0x102c, 0x6264), }, - { USB_DEVICE(0x102c, 0x6265), }, - { USB_DEVICE(0x102c, 0x6266), }, - { USB_DEVICE(0x102c, 0x6267), }, - { USB_DEVICE(0x102c, 0x6268), }, - { USB_DEVICE(0x102c, 0x6269), }, - { } -}; - -ET61X251_SENSOR_TABLE - -/*****************************************************************************/ - -enum et61x251_frame_state { - F_UNUSED, - F_QUEUED, - F_GRABBING, - F_DONE, - F_ERROR, -}; - -struct et61x251_frame_t { - void* bufmem; - struct v4l2_buffer buf; - enum et61x251_frame_state state; - struct list_head frame; - unsigned long vma_use_count; -}; - -enum et61x251_dev_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04, -}; - -enum et61x251_io_method { - IO_NONE, - IO_READ, - IO_MMAP, -}; - -enum et61x251_stream_state { - STREAM_OFF, - STREAM_INTERRUPT, - STREAM_ON, -}; - -struct et61x251_sysfs_attr { - u8 reg, i2c_reg; -}; - -struct et61x251_module_param { - u8 force_munmap; - u16 frame_timeout; -}; - -static DEFINE_MUTEX(et61x251_sysfs_lock); -static DECLARE_RWSEM(et61x251_disconnect); - -struct et61x251_device { - struct video_device* v4ldev; - - struct et61x251_sensor sensor; - - struct usb_device* usbdev; - struct urb* urb[ET61X251_URBS]; - void* transfer_buffer[ET61X251_URBS]; - u8* control_buffer; - - struct et61x251_frame_t *frame_current, frame[ET61X251_MAX_FRAMES]; - struct list_head inqueue, outqueue; - u32 frame_count, nbuffers, nreadbuffers; - - enum et61x251_io_method io; - enum et61x251_stream_state stream; - - struct v4l2_jpegcompression compression; - - struct et61x251_sysfs_attr sysfs; - struct et61x251_module_param module_param; - - enum et61x251_dev_state state; - u8 users; - - struct mutex dev_mutex, fileop_mutex; - spinlock_t queue_lock; - wait_queue_head_t open, wait_frame, wait_stream; -}; - -/*****************************************************************************/ - -struct et61x251_device* -et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) -{ - if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) - return cam; - - return NULL; -} - - -void -et61x251_attach_sensor(struct et61x251_device* cam, - struct et61x251_sensor* sensor) -{ - memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor)); -} - -/*****************************************************************************/ - -#undef DBG -#undef KDBG -#ifdef ET61X251_DEBUG -# define DBG(level, fmt, args...) \ -do { \ - if (debug >= (level)) { \ - if ((level) == 1) \ - dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ - else if ((level) == 2) \ - dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ - else if ((level) >= 3) \ - dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ - } \ -} while (0) -# define KDBG(level, fmt, args...) \ -do { \ - if (debug >= (level)) { \ - if ((level) == 1 || (level) == 2) \ - pr_info("et61x251: " fmt "\n", ## args); \ - else if ((level) == 3) \ - pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ - } \ -} while (0) -# define V4LDBG(level, name, cmd) \ -do { \ - if (debug >= (level)) \ - v4l_print_ioctl(name, cmd); \ -} while (0) -#else -# define DBG(level, fmt, args...) do {;} while(0) -# define KDBG(level, fmt, args...) do {;} while(0) -# define V4LDBG(level, name, cmd) do {;} while(0) -#endif - -#undef PDBG -#define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) - -#undef PDBGG -#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ - -#endif /* _ET61X251_H_ */ diff --git a/drivers/usb/media/et61x251_core.c b/drivers/usb/media/et61x251_core.c deleted file mode 100644 index 7cc01b828b3d..000000000000 --- a/drivers/usb/media/et61x251_core.c +++ /dev/null @@ -1,2630 +0,0 @@ -/*************************************************************************** - * V4L2 driver for ET61X[12]51 PC Camera Controllers * - * * - * Copyright (C) 2006 by Luca Risolia * - * * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "et61x251.h" - -/*****************************************************************************/ - -#define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \ - "PC Camera Controllers" -#define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" -#define ET61X251_AUTHOR_EMAIL "" -#define ET61X251_MODULE_LICENSE "GPL" -#define ET61X251_MODULE_VERSION "1:1.02" -#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2) - -/*****************************************************************************/ - -MODULE_DEVICE_TABLE(usb, et61x251_id_table); - -MODULE_AUTHOR(ET61X251_MODULE_AUTHOR " " ET61X251_AUTHOR_EMAIL); -MODULE_DESCRIPTION(ET61X251_MODULE_NAME); -MODULE_VERSION(ET61X251_MODULE_VERSION); -MODULE_LICENSE(ET61X251_MODULE_LICENSE); - -static short video_nr[] = {[0 ... ET61X251_MAX_DEVICES-1] = -1}; -module_param_array(video_nr, short, NULL, 0444); -MODULE_PARM_DESC(video_nr, - "\n<-1|n[,...]> Specify V4L2 minor mode number." - "\n -1 = use next available (default)" - "\n n = use minor number n (integer >= 0)" - "\nYou can specify up to " - __MODULE_STRING(ET61X251_MAX_DEVICES) " cameras this way." - "\nFor example:" - "\nvideo_nr=-1,2,-1 would assign minor number 2 to" - "\nthe second registered camera and use auto for the first" - "\none and for every other camera." - "\n"); - -static short force_munmap[] = {[0 ... ET61X251_MAX_DEVICES-1] = - ET61X251_FORCE_MUNMAP}; -module_param_array(force_munmap, bool, NULL, 0444); -MODULE_PARM_DESC(force_munmap, - "\n<0|1[,...]> Force the application to unmap previously" - "\nmapped buffer memory before calling any VIDIOC_S_CROP or" - "\nVIDIOC_S_FMT ioctl's. Not all the applications support" - "\nthis feature. This parameter is specific for each" - "\ndetected camera." - "\n 0 = do not force memory unmapping" - "\n 1 = force memory unmapping (save memory)" - "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." - "\n"); - -static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] = - ET61X251_FRAME_TIMEOUT}; -module_param_array(frame_timeout, uint, NULL, 0644); -MODULE_PARM_DESC(frame_timeout, - "\n Timeout for a video frame in seconds." - "\nThis parameter is specific for each detected camera." - "\nDefault value is " - __MODULE_STRING(ET61X251_FRAME_TIMEOUT)"." - "\n"); - -#ifdef ET61X251_DEBUG -static unsigned short debug = ET61X251_DEBUG_LEVEL; -module_param(debug, ushort, 0644); -MODULE_PARM_DESC(debug, - "\n Debugging information level, from 0 to 3:" - "\n0 = none (use carefully)" - "\n1 = critical errors" - "\n2 = significant informations" - "\n3 = more verbose messages" - "\nLevel 3 is useful for testing only, when only " - "one device is used." - "\nDefault value is "__MODULE_STRING(ET61X251_DEBUG_LEVEL)"." - "\n"); -#endif - -/*****************************************************************************/ - -static u32 -et61x251_request_buffers(struct et61x251_device* cam, u32 count, - enum et61x251_io_method io) -{ - struct v4l2_pix_format* p = &(cam->sensor.pix_format); - struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); - const size_t imagesize = cam->module_param.force_munmap || - io == IO_READ ? - (p->width * p->height * p->priv) / 8 : - (r->width * r->height * p->priv) / 8; - void* buff = NULL; - u32 i; - - if (count > ET61X251_MAX_FRAMES) - count = ET61X251_MAX_FRAMES; - - cam->nbuffers = count; - while (cam->nbuffers > 0) { - if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) - break; - cam->nbuffers--; - } - - for (i = 0; i < cam->nbuffers; i++) { - cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); - cam->frame[i].buf.index = i; - cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); - cam->frame[i].buf.length = imagesize; - cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cam->frame[i].buf.sequence = 0; - cam->frame[i].buf.field = V4L2_FIELD_NONE; - cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; - cam->frame[i].buf.flags = 0; - } - - return cam->nbuffers; -} - - -static void et61x251_release_buffers(struct et61x251_device* cam) -{ - if (cam->nbuffers) { - vfree(cam->frame[0].bufmem); - cam->nbuffers = 0; - } - cam->frame_current = NULL; -} - - -static void et61x251_empty_framequeues(struct et61x251_device* cam) -{ - u32 i; - - INIT_LIST_HEAD(&cam->inqueue); - INIT_LIST_HEAD(&cam->outqueue); - - for (i = 0; i < ET61X251_MAX_FRAMES; i++) { - cam->frame[i].state = F_UNUSED; - cam->frame[i].buf.bytesused = 0; - } -} - - -static void et61x251_requeue_outqueue(struct et61x251_device* cam) -{ - struct et61x251_frame_t *i; - - list_for_each_entry(i, &cam->outqueue, frame) { - i->state = F_QUEUED; - list_add(&i->frame, &cam->inqueue); - } - - INIT_LIST_HEAD(&cam->outqueue); -} - - -static void et61x251_queue_unusedframes(struct et61x251_device* cam) -{ - unsigned long lock_flags; - u32 i; - - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].state == F_UNUSED) { - cam->frame[i].state = F_QUEUED; - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_add_tail(&cam->frame[i].frame, &cam->inqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - } -} - -/*****************************************************************************/ - -int et61x251_write_reg(struct et61x251_device* cam, u8 value, u16 index) -{ - struct usb_device* udev = cam->usbdev; - u8* buff = cam->control_buffer; - int res; - - *buff = value; - - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, index, buff, 1, ET61X251_CTRL_TIMEOUT); - if (res < 0) { - DBG(3, "Failed to write a register (value 0x%02X, index " - "0x%02X, error %d)", value, index, res); - return -1; - } - - return 0; -} - - -int et61x251_read_reg(struct et61x251_device* cam, u16 index) -{ - struct usb_device* udev = cam->usbdev; - u8* buff = cam->control_buffer; - int res; - - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - 0, index, buff, 1, ET61X251_CTRL_TIMEOUT); - if (res < 0) - DBG(3, "Failed to read a register (index 0x%02X, error %d)", - index, res); - - return (res >= 0) ? (int)(*buff) : -1; -} - - -static int -et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor) -{ - int i, r; - - for (i = 1; i <= 8; i++) { - if (sensor->interface == ET61X251_I2C_3WIRES) { - r = et61x251_read_reg(cam, 0x8e); - if (!(r & 0x02) && (r >= 0)) - return 0; - } else { - r = et61x251_read_reg(cam, 0x8b); - if (!(r & 0x01) && (r >= 0)) - return 0; - } - if (r < 0) - return -EIO; - udelay(8*8); /* minimum for sensors at 400kHz */ - } - - return -EBUSY; -} - - -int -et61x251_i2c_try_read(struct et61x251_device* cam, - struct et61x251_sensor* sensor, u8 address) -{ - struct usb_device* udev = cam->usbdev; - u8* data = cam->control_buffer; - int err = 0, res; - - data[0] = address; - data[1] = cam->sensor.i2c_slave_id; - data[2] = cam->sensor.rsta | 0x10; - data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02); - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += et61x251_i2c_wait(cam, sensor); - - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - if (err) - DBG(3, "I2C read failed for %s image sensor", sensor->name); - - PDBGG("I2C read: address 0x%02X, value: 0x%02X", address, data[0]); - - return err ? -1 : (int)data[0]; -} - - -int -et61x251_i2c_try_write(struct et61x251_device* cam, - struct et61x251_sensor* sensor, u8 address, u8 value) -{ - struct usb_device* udev = cam->usbdev; - u8* data = cam->control_buffer; - int err = 0, res; - - data[0] = address; - data[1] = cam->sensor.i2c_slave_id; - data[2] = cam->sensor.rsta | 0x12; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - data[0] = value; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += et61x251_i2c_wait(cam, sensor); - - if (err) - DBG(3, "I2C write failed for %s image sensor", sensor->name); - - PDBGG("I2C write: address 0x%02X, value: 0x%02X", address, value); - - return err ? -1 : 0; -} - - -int -et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, - u8 data3, u8 data4, u8 data5, u8 data6, u8 data7, - u8 data8, u8 address) -{ - struct usb_device* udev = cam->usbdev; - u8* data = cam->control_buffer; - int err = 0, res; - - data[0] = data2; - data[1] = data3; - data[2] = data4; - data[3] = data5; - data[4] = data6; - data[5] = data7; - data[6] = data8; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x81, data, n-1, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - data[0] = address; - data[1] = cam->sensor.i2c_slave_id; - data[2] = cam->sensor.rsta | 0x02 | (n << 4); - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - /* Start writing through the serial interface */ - data[0] = data1; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += et61x251_i2c_wait(cam, &cam->sensor); - - if (err) - DBG(3, "I2C raw write failed for %s image sensor", - cam->sensor.name); - - PDBGG("I2C raw write: %u bytes, address = 0x%02X, data1 = 0x%02X, " - "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X," - " data6 = 0x%02X, data7 = 0x%02X, data8 = 0x%02X", n, address, - data1, data2, data3, data4, data5, data6, data7, data8); - - return err ? -1 : 0; - -} - - -int et61x251_i2c_read(struct et61x251_device* cam, u8 address) -{ - return et61x251_i2c_try_read(cam, &cam->sensor, address); -} - - -int et61x251_i2c_write(struct et61x251_device* cam, u8 address, u8 value) -{ - return et61x251_i2c_try_write(cam, &cam->sensor, address, value); -} - -/*****************************************************************************/ - -static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs) -{ - struct et61x251_device* cam = urb->context; - struct et61x251_frame_t** f; - size_t imagesize; - u8 i; - int err = 0; - - if (urb->status == -ENOENT) - return; - - f = &cam->frame_current; - - if (cam->stream == STREAM_INTERRUPT) { - cam->stream = STREAM_OFF; - if ((*f)) - (*f)->state = F_QUEUED; - DBG(3, "Stream interrupted"); - wake_up(&cam->wait_stream); - } - - if (cam->state & DEV_DISCONNECTED) - return; - - if (cam->state & DEV_MISCONFIGURED) { - wake_up_interruptible(&cam->wait_frame); - return; - } - - if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) - goto resubmit_urb; - - if (!(*f)) - (*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t, - frame); - - imagesize = (cam->sensor.pix_format.width * - cam->sensor.pix_format.height * - cam->sensor.pix_format.priv) / 8; - - for (i = 0; i < urb->number_of_packets; i++) { - unsigned int len, status; - void *pos; - u8* b1, * b2, sof; - const u8 VOID_BYTES = 6; - size_t imglen; - - len = urb->iso_frame_desc[i].actual_length; - status = urb->iso_frame_desc[i].status; - pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; - - if (status) { - DBG(3, "Error in isochronous frame"); - (*f)->state = F_ERROR; - continue; - } - - b1 = pos++; - b2 = pos++; - sof = ((*b1 & 0x3f) == 63); - imglen = ((*b1 & 0xc0) << 2) | *b2; - - PDBGG("Isochrnous frame: length %u, #%u i, image length %zu", - len, i, imglen); - - if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) -start_of_frame: - if (sof) { - (*f)->state = F_GRABBING; - (*f)->buf.bytesused = 0; - do_gettimeofday(&(*f)->buf.timestamp); - pos += 22; - DBG(3, "SOF detected: new video frame"); - } - - if ((*f)->state == F_GRABBING) { - if (sof && (*f)->buf.bytesused) { - if (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_ET61X251) - goto end_of_frame; - else { - DBG(3, "Not expected SOF detected " - "after %lu bytes", - (unsigned long)(*f)->buf.bytesused); - (*f)->state = F_ERROR; - continue; - } - } - - if ((*f)->buf.bytesused + imglen > imagesize) { - DBG(3, "Video frame size exceeded"); - (*f)->state = F_ERROR; - continue; - } - - pos += VOID_BYTES; - - memcpy((*f)->bufmem+(*f)->buf.bytesused, pos, imglen); - (*f)->buf.bytesused += imglen; - - if ((*f)->buf.bytesused == imagesize) { - u32 b; -end_of_frame: - b = (*f)->buf.bytesused; - (*f)->state = F_DONE; - (*f)->buf.sequence= ++cam->frame_count; - spin_lock(&cam->queue_lock); - list_move_tail(&(*f)->frame, &cam->outqueue); - if (!list_empty(&cam->inqueue)) - (*f) = list_entry(cam->inqueue.next, - struct et61x251_frame_t, - frame); - else - (*f) = NULL; - spin_unlock(&cam->queue_lock); - DBG(3, "Video frame captured: : %lu bytes", - (unsigned long)(b)); - - if (!(*f)) - goto resubmit_urb; - - if (sof && - cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_ET61X251) - goto start_of_frame; - } - } - } - -resubmit_urb: - urb->dev = cam->usbdev; - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0 && err != -EPERM) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "usb_submit_urb() failed"); - } - - wake_up_interruptible(&cam->wait_frame); -} - - -static int et61x251_start_transfer(struct et61x251_device* cam) -{ - struct usb_device *udev = cam->usbdev; - struct urb* urb; - const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832, - 864, 896, 920, 956, 980, 1000, - 1022}; - const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING]; - s8 i, j; - int err = 0; - - for (i = 0; i < ET61X251_URBS; i++) { - cam->transfer_buffer[i] = kzalloc(ET61X251_ISO_PACKETS * psz, - GFP_KERNEL); - if (!cam->transfer_buffer[i]) { - err = -ENOMEM; - DBG(1, "Not enough memory"); - goto free_buffers; - } - } - - for (i = 0; i < ET61X251_URBS; i++) { - urb = usb_alloc_urb(ET61X251_ISO_PACKETS, GFP_KERNEL); - cam->urb[i] = urb; - if (!urb) { - err = -ENOMEM; - DBG(1, "usb_alloc_urb() failed"); - goto free_urbs; - } - urb->dev = udev; - urb->context = cam; - urb->pipe = usb_rcvisocpipe(udev, 1); - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = ET61X251_ISO_PACKETS; - urb->complete = et61x251_urb_complete; - urb->transfer_buffer = cam->transfer_buffer[i]; - urb->transfer_buffer_length = psz * ET61X251_ISO_PACKETS; - urb->interval = 1; - for (j = 0; j < ET61X251_ISO_PACKETS; j++) { - urb->iso_frame_desc[j].offset = psz * j; - urb->iso_frame_desc[j].length = psz; - } - } - - err = et61x251_write_reg(cam, 0x01, 0x03); - err = et61x251_write_reg(cam, 0x00, 0x03); - err = et61x251_write_reg(cam, 0x08, 0x03); - if (err) { - err = -EIO; - DBG(1, "I/O hardware error"); - goto free_urbs; - } - - err = usb_set_interface(udev, 0, ET61X251_ALTERNATE_SETTING); - if (err) { - DBG(1, "usb_set_interface() failed"); - goto free_urbs; - } - - cam->frame_current = NULL; - - for (i = 0; i < ET61X251_URBS; i++) { - err = usb_submit_urb(cam->urb[i], GFP_KERNEL); - if (err) { - for (j = i-1; j >= 0; j--) - usb_kill_urb(cam->urb[j]); - DBG(1, "usb_submit_urb() failed, error %d", err); - goto free_urbs; - } - } - - return 0; - -free_urbs: - for (i = 0; (i < ET61X251_URBS) && cam->urb[i]; i++) - usb_free_urb(cam->urb[i]); - -free_buffers: - for (i = 0; (i < ET61X251_URBS) && cam->transfer_buffer[i]; i++) - kfree(cam->transfer_buffer[i]); - - return err; -} - - -static int et61x251_stop_transfer(struct et61x251_device* cam) -{ - struct usb_device *udev = cam->usbdev; - s8 i; - int err = 0; - - if (cam->state & DEV_DISCONNECTED) - return 0; - - for (i = ET61X251_URBS-1; i >= 0; i--) { - usb_kill_urb(cam->urb[i]); - usb_free_urb(cam->urb[i]); - kfree(cam->transfer_buffer[i]); - } - - err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ - if (err) - DBG(3, "usb_set_interface() failed"); - - return err; -} - - -static int et61x251_stream_interrupt(struct et61x251_device* cam) -{ - long timeout; - - cam->stream = STREAM_INTERRUPT; - timeout = wait_event_timeout(cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED), - ET61X251_URB_TIMEOUT); - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - else if (cam->stream != STREAM_OFF) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "URB timeout reached. The camera is misconfigured. To " - "use it, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -EIO; - } - - return 0; -} - -/*****************************************************************************/ - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count) -{ - char str[5]; - char* endp; - unsigned long val; - - if (len < 4) { - strncpy(str, buff, len); - str[len+1] = '\0'; - } else { - strncpy(str, buff, 4); - str[4] = '\0'; - } - - val = simple_strtoul(str, &endp, 0); - - *count = 0; - if (val <= 0xff) - *count = (ssize_t)(endp - str); - if ((*count) && (len == *count+1) && (buff[*count] == '\n')) - *count += 1; - - return (u8)val; -} - -/* - NOTE 1: being inside one of the following methods implies that the v4l - device exists for sure (see kobjects and reference counters) - NOTE 2: buffers are PAGE_SIZE long -*/ - -static ssize_t et61x251_show_reg(struct class_device* cd, char* buf) -{ - struct et61x251_device* cam; - ssize_t count; - - if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - count = sprintf(buf, "%u\n", cam->sysfs.reg); - - mutex_unlock(&et61x251_sysfs_lock); - - return count; -} - - -static ssize_t -et61x251_store_reg(struct class_device* cd, const char* buf, size_t len) -{ - struct et61x251_device* cam; - u8 index; - ssize_t count; - - if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - index = et61x251_strtou8(buf, len, &count); - if (index > 0x8e || !count) { - mutex_unlock(&et61x251_sysfs_lock); - return -EINVAL; - } - - cam->sysfs.reg = index; - - DBG(2, "Moved ET61X[12]51 register index to 0x%02X", cam->sysfs.reg); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&et61x251_sysfs_lock); - - return count; -} - - -static ssize_t et61x251_show_val(struct class_device* cd, char* buf) -{ - struct et61x251_device* cam; - ssize_t count; - int val; - - if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - if ((val = et61x251_read_reg(cam, cam->sysfs.reg)) < 0) { - mutex_unlock(&et61x251_sysfs_lock); - return -EIO; - } - - count = sprintf(buf, "%d\n", val); - - DBG(3, "Read bytes: %zd", count); - - mutex_unlock(&et61x251_sysfs_lock); - - return count; -} - - -static ssize_t -et61x251_store_val(struct class_device* cd, const char* buf, size_t len) -{ - struct et61x251_device* cam; - u8 value; - ssize_t count; - int err; - - if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - value = et61x251_strtou8(buf, len, &count); - if (!count) { - mutex_unlock(&et61x251_sysfs_lock); - return -EINVAL; - } - - err = et61x251_write_reg(cam, value, cam->sysfs.reg); - if (err) { - mutex_unlock(&et61x251_sysfs_lock); - return -EIO; - } - - DBG(2, "Written ET61X[12]51 reg. 0x%02X, val. 0x%02X", - cam->sysfs.reg, value); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&et61x251_sysfs_lock); - - return count; -} - - -static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf) -{ - struct et61x251_device* cam; - ssize_t count; - - if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg); - - DBG(3, "Read bytes: %zd", count); - - mutex_unlock(&et61x251_sysfs_lock); - - return count; -} - - -static ssize_t -et61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) -{ - struct et61x251_device* cam; - u8 index; - ssize_t count; - - if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - index = et61x251_strtou8(buf, len, &count); - if (!count) { - mutex_unlock(&et61x251_sysfs_lock); - return -EINVAL; - } - - cam->sysfs.i2c_reg = index; - - DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&et61x251_sysfs_lock); - - return count; -} - - -static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf) -{ - struct et61x251_device* cam; - ssize_t count; - int val; - - if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) { - mutex_unlock(&et61x251_sysfs_lock); - return -ENOSYS; - } - - if ((val = et61x251_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { - mutex_unlock(&et61x251_sysfs_lock); - return -EIO; - } - - count = sprintf(buf, "%d\n", val); - - DBG(3, "Read bytes: %zd", count); - - mutex_unlock(&et61x251_sysfs_lock); - - return count; -} - - -static ssize_t -et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len) -{ - struct et61x251_device* cam; - u8 value; - ssize_t count; - int err; - - if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) { - mutex_unlock(&et61x251_sysfs_lock); - return -ENOSYS; - } - - value = et61x251_strtou8(buf, len, &count); - if (!count) { - mutex_unlock(&et61x251_sysfs_lock); - return -EINVAL; - } - - err = et61x251_i2c_write(cam, cam->sysfs.i2c_reg, value); - if (err) { - mutex_unlock(&et61x251_sysfs_lock); - return -EIO; - } - - DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X", - cam->sysfs.i2c_reg, value); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&et61x251_sysfs_lock); - - return count; -} - - -static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, - et61x251_show_reg, et61x251_store_reg); -static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR, - et61x251_show_val, et61x251_store_val); -static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, - et61x251_show_i2c_reg, et61x251_store_i2c_reg); -static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, - et61x251_show_i2c_val, et61x251_store_i2c_val); - - -static void et61x251_create_sysfs(struct et61x251_device* cam) -{ - struct video_device *v4ldev = cam->v4ldev; - - video_device_create_file(v4ldev, &class_device_attr_reg); - video_device_create_file(v4ldev, &class_device_attr_val); - if (cam->sensor.sysfs_ops) { - video_device_create_file(v4ldev, &class_device_attr_i2c_reg); - video_device_create_file(v4ldev, &class_device_attr_i2c_val); - } -} -#endif /* CONFIG_VIDEO_ADV_DEBUG */ - -/*****************************************************************************/ - -static int -et61x251_set_pix_format(struct et61x251_device* cam, - struct v4l2_pix_format* pix) -{ - int r, err = 0; - - if ((r = et61x251_read_reg(cam, 0x12)) < 0) - err += r; - if (pix->pixelformat == V4L2_PIX_FMT_ET61X251) - err += et61x251_write_reg(cam, r & 0xfd, 0x12); - else - err += et61x251_write_reg(cam, r | 0x02, 0x12); - - return err ? -EIO : 0; -} - - -static int -et61x251_set_compression(struct et61x251_device* cam, - struct v4l2_jpegcompression* compression) -{ - int r, err = 0; - - if ((r = et61x251_read_reg(cam, 0x12)) < 0) - err += r; - if (compression->quality == 0) - err += et61x251_write_reg(cam, r & 0xfb, 0x12); - else - err += et61x251_write_reg(cam, r | 0x04, 0x12); - - return err ? -EIO : 0; -} - - -static int et61x251_set_scale(struct et61x251_device* cam, u8 scale) -{ - int r = 0, err = 0; - - r = et61x251_read_reg(cam, 0x12); - if (r < 0) - err += r; - - if (scale == 1) - err += et61x251_write_reg(cam, r & ~0x01, 0x12); - else if (scale == 2) - err += et61x251_write_reg(cam, r | 0x01, 0x12); - - if (err) - return -EIO; - - PDBGG("Scaling factor: %u", scale); - - return 0; -} - - -static int -et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect) -{ - struct et61x251_sensor* s = &cam->sensor; - u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left + - s->active_pixel.left), - fmw_sy = (u16)(rect->top - s->cropcap.bounds.top + - s->active_pixel.top), - fmw_length = (u16)(rect->width), - fmw_height = (u16)(rect->height); - int err = 0; - - err += et61x251_write_reg(cam, fmw_sx & 0xff, 0x69); - err += et61x251_write_reg(cam, fmw_sy & 0xff, 0x6a); - err += et61x251_write_reg(cam, fmw_length & 0xff, 0x6b); - err += et61x251_write_reg(cam, fmw_height & 0xff, 0x6c); - err += et61x251_write_reg(cam, (fmw_sx >> 8) | ((fmw_sy & 0x300) >> 6) - | ((fmw_length & 0x300) >> 4) - | ((fmw_height & 0x300) >> 2), 0x6d); - if (err) - return -EIO; - - PDBGG("fmw_sx, fmw_sy, fmw_length, fmw_height: %u %u %u %u", - fmw_sx, fmw_sy, fmw_length, fmw_height); - - return 0; -} - - -static int et61x251_init(struct et61x251_device* cam) -{ - struct et61x251_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - struct v4l2_queryctrl *qctrl; - struct v4l2_rect* rect; - u8 i = 0; - int err = 0; - - if (!(cam->state & DEV_INITIALIZED)) { - init_waitqueue_head(&cam->open); - qctrl = s->qctrl; - rect = &(s->cropcap.defrect); - cam->compression.quality = ET61X251_COMPRESSION_QUALITY; - } else { /* use current values */ - qctrl = s->_qctrl; - rect = &(s->_rect); - } - - err += et61x251_set_scale(cam, rect->width / s->pix_format.width); - err += et61x251_set_crop(cam, rect); - if (err) - return err; - - if (s->init) { - err = s->init(cam); - if (err) { - DBG(3, "Sensor initialization failed"); - return err; - } - } - - err += et61x251_set_compression(cam, &cam->compression); - err += et61x251_set_pix_format(cam, &s->pix_format); - if (s->set_pix_format) - err += s->set_pix_format(cam, &s->pix_format); - if (err) - return err; - - if (s->pix_format.pixelformat == V4L2_PIX_FMT_ET61X251) - DBG(3, "Compressed video format is active, quality %d", - cam->compression.quality); - else - DBG(3, "Uncompressed video format is active"); - - if (s->set_crop) - if ((err = s->set_crop(cam, rect))) { - DBG(3, "set_crop() failed"); - return err; - } - - if (s->set_ctrl) { - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (s->qctrl[i].id != 0 && - !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { - ctrl.id = s->qctrl[i].id; - ctrl.value = qctrl[i].default_value; - err = s->set_ctrl(cam, &ctrl); - if (err) { - DBG(3, "Set %s control failed", - s->qctrl[i].name); - return err; - } - DBG(3, "Image sensor supports '%s' control", - s->qctrl[i].name); - } - } - - if (!(cam->state & DEV_INITIALIZED)) { - mutex_init(&cam->fileop_mutex); - spin_lock_init(&cam->queue_lock); - init_waitqueue_head(&cam->wait_frame); - init_waitqueue_head(&cam->wait_stream); - cam->nreadbuffers = 2; - memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); - memcpy(&(s->_rect), &(s->cropcap.defrect), - sizeof(struct v4l2_rect)); - cam->state |= DEV_INITIALIZED; - } - - DBG(2, "Initialization succeeded"); - return 0; -} - - -static void et61x251_release_resources(struct et61x251_device* cam) -{ - mutex_lock(&et61x251_sysfs_lock); - - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); - video_set_drvdata(cam->v4ldev, NULL); - video_unregister_device(cam->v4ldev); - - usb_put_dev(cam->usbdev); - - mutex_unlock(&et61x251_sysfs_lock); - - kfree(cam->control_buffer); -} - -/*****************************************************************************/ - -static int et61x251_open(struct inode* inode, struct file* filp) -{ - struct et61x251_device* cam; - int err = 0; - - /* - This is the only safe way to prevent race conditions with - disconnect - */ - if (!down_read_trylock(&et61x251_disconnect)) - return -ERESTARTSYS; - - cam = video_get_drvdata(video_devdata(filp)); - - if (mutex_lock_interruptible(&cam->dev_mutex)) { - up_read(&et61x251_disconnect); - return -ERESTARTSYS; - } - - if (cam->users) { - DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); - if ((filp->f_flags & O_NONBLOCK) || - (filp->f_flags & O_NDELAY)) { - err = -EWOULDBLOCK; - goto out; - } - mutex_unlock(&cam->dev_mutex); - err = wait_event_interruptible_exclusive(cam->open, - cam->state & DEV_DISCONNECTED - || !cam->users); - if (err) { - up_read(&et61x251_disconnect); - return err; - } - if (cam->state & DEV_DISCONNECTED) { - up_read(&et61x251_disconnect); - return -ENODEV; - } - mutex_lock(&cam->dev_mutex); - } - - - if (cam->state & DEV_MISCONFIGURED) { - err = et61x251_init(cam); - if (err) { - DBG(1, "Initialization failed again. " - "I will retry on next open()."); - goto out; - } - cam->state &= ~DEV_MISCONFIGURED; - } - - if ((err = et61x251_start_transfer(cam))) - goto out; - - filp->private_data = cam; - cam->users++; - cam->io = IO_NONE; - cam->stream = STREAM_OFF; - cam->nbuffers = 0; - cam->frame_count = 0; - et61x251_empty_framequeues(cam); - - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); - -out: - mutex_unlock(&cam->dev_mutex); - up_read(&et61x251_disconnect); - return err; -} - - -static int et61x251_release(struct inode* inode, struct file* filp) -{ - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); - - mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ - - et61x251_stop_transfer(cam); - - et61x251_release_buffers(cam); - - if (cam->state & DEV_DISCONNECTED) { - et61x251_release_resources(cam); - mutex_unlock(&cam->dev_mutex); - kfree(cam); - return 0; - } - - cam->users--; - wake_up_interruptible_nr(&cam->open, 1); - - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); - - mutex_unlock(&cam->dev_mutex); - - return 0; -} - - -static ssize_t -et61x251_read(struct file* filp, char __user * buf, - size_t count, loff_t* f_pos) -{ - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); - struct et61x251_frame_t* f, * i; - unsigned long lock_flags; - long timeout; - int err = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io == IO_MMAP) { - DBG(3, "Close and open the device again to choose the read " - "method"); - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - if (cam->io == IO_NONE) { - if (!et61x251_request_buffers(cam, cam->nreadbuffers, - IO_READ)) { - DBG(1, "read() failed, not enough memory"); - mutex_unlock(&cam->fileop_mutex); - return -ENOMEM; - } - cam->io = IO_READ; - cam->stream = STREAM_ON; - } - - if (list_empty(&cam->inqueue)) { - if (!list_empty(&cam->outqueue)) - et61x251_empty_framequeues(cam); - et61x251_queue_unusedframes(cam); - } - - if (!count) { - mutex_unlock(&cam->fileop_mutex); - return 0; - } - - if (list_empty(&cam->outqueue)) { - if (filp->f_flags & O_NONBLOCK) { - mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) { - mutex_unlock(&cam->fileop_mutex); - return timeout; - } - if (cam->state & DEV_DISCONNECTED) { - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - if (!timeout || (cam->state & DEV_MISCONFIGURED)) { - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - } - - f = list_entry(cam->outqueue.prev, struct et61x251_frame_t, frame); - - if (count > f->buf.bytesused) - count = f->buf.bytesused; - - if (copy_to_user(buf, f->bufmem, count)) { - err = -EFAULT; - goto exit; - } - *f_pos += count; - -exit: - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_for_each_entry(i, &cam->outqueue, frame) - i->state = F_UNUSED; - INIT_LIST_HEAD(&cam->outqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - et61x251_queue_unusedframes(cam); - - PDBGG("Frame #%lu, bytes read: %zu", - (unsigned long)f->buf.index, count); - - mutex_unlock(&cam->fileop_mutex); - - return err ? err : count; -} - - -static unsigned int et61x251_poll(struct file *filp, poll_table *wait) -{ - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); - struct et61x251_frame_t* f; - unsigned long lock_flags; - unsigned int mask = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return POLLERR; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - goto error; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - goto error; - } - - if (cam->io == IO_NONE) { - if (!et61x251_request_buffers(cam, cam->nreadbuffers, - IO_READ)) { - DBG(1, "poll() failed, not enough memory"); - goto error; - } - cam->io = IO_READ; - cam->stream = STREAM_ON; - } - - if (cam->io == IO_READ) { - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_for_each_entry(f, &cam->outqueue, frame) - f->state = F_UNUSED; - INIT_LIST_HEAD(&cam->outqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - et61x251_queue_unusedframes(cam); - } - - poll_wait(filp, &cam->wait_frame, wait); - - if (!list_empty(&cam->outqueue)) - mask |= POLLIN | POLLRDNORM; - - mutex_unlock(&cam->fileop_mutex); - - return mask; - -error: - mutex_unlock(&cam->fileop_mutex); - return POLLERR; -} - - -static void et61x251_vm_open(struct vm_area_struct* vma) -{ - struct et61x251_frame_t* f = vma->vm_private_data; - f->vma_use_count++; -} - - -static void et61x251_vm_close(struct vm_area_struct* vma) -{ - /* NOTE: buffers are not freed here */ - struct et61x251_frame_t* f = vma->vm_private_data; - f->vma_use_count--; -} - - -static struct vm_operations_struct et61x251_vm_ops = { - .open = et61x251_vm_open, - .close = et61x251_vm_close, -}; - - -static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) -{ - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); - unsigned long size = vma->vm_end - vma->vm_start, - start = vma->vm_start; - void *pos; - u32 i; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || - size != PAGE_ALIGN(cam->frame[0].buf.length)) { - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - for (i = 0; i < cam->nbuffers; i++) { - if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) - break; - } - if (i == cam->nbuffers) { - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - vma->vm_flags |= VM_IO; - vma->vm_flags |= VM_RESERVED; - - pos = cam->frame[i].bufmem; - while (size > 0) { /* size is page-aligned */ - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { - mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vma->vm_ops = &et61x251_vm_ops; - vma->vm_private_data = &cam->frame[i]; - - et61x251_vm_open(vma); - - mutex_unlock(&cam->fileop_mutex); - - return 0; -} - -/*****************************************************************************/ - -static int -et61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg) -{ - struct v4l2_capability cap = { - .driver = "et61x251", - .version = ET61X251_MODULE_VERSION_CODE, - .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, - }; - - strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); - if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) - strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, - sizeof(cap.bus_info)); - - if (copy_to_user(arg, &cap, sizeof(cap))) - return -EFAULT; - - return 0; -} - - -static int -et61x251_vidioc_enuminput(struct et61x251_device* cam, void __user * arg) -{ - struct v4l2_input i; - - if (copy_from_user(&i, arg, sizeof(i))) - return -EFAULT; - - if (i.index) - return -EINVAL; - - memset(&i, 0, sizeof(i)); - strcpy(i.name, "Camera"); - i.type = V4L2_INPUT_TYPE_CAMERA; - - if (copy_to_user(arg, &i, sizeof(i))) - return -EFAULT; - - return 0; -} - - -static int -et61x251_vidioc_g_input(struct et61x251_device* cam, void __user * arg) -{ - int index = 0; - - if (copy_to_user(arg, &index, sizeof(index))) - return -EFAULT; - - return 0; -} - - -static int -et61x251_vidioc_s_input(struct et61x251_device* cam, void __user * arg) -{ - int index; - - if (copy_from_user(&index, arg, sizeof(index))) - return -EFAULT; - - if (index != 0) - return -EINVAL; - - return 0; -} - - -static int -et61x251_vidioc_query_ctrl(struct et61x251_device* cam, void __user * arg) -{ - struct et61x251_sensor* s = &cam->sensor; - struct v4l2_queryctrl qc; - u8 i; - - if (copy_from_user(&qc, arg, sizeof(qc))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (qc.id && qc.id == s->qctrl[i].id) { - memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); - if (copy_to_user(arg, &qc, sizeof(qc))) - return -EFAULT; - return 0; - } - - return -EINVAL; -} - - -static int -et61x251_vidioc_g_ctrl(struct et61x251_device* cam, void __user * arg) -{ - struct et61x251_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - int err = 0; - u8 i; - - if (!s->get_ctrl && !s->set_ctrl) - return -EINVAL; - - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; - - if (!s->get_ctrl) { - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id == s->qctrl[i].id) { - ctrl.value = s->_qctrl[i].default_value; - goto exit; - } - return -EINVAL; - } else - err = s->get_ctrl(cam, &ctrl); - -exit: - if (copy_to_user(arg, &ctrl, sizeof(ctrl))) - return -EFAULT; - - return err; -} - - -static int -et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg) -{ - struct et61x251_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - u8 i; - int err = 0; - - if (!s->set_ctrl) - return -EINVAL; - - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id == s->qctrl[i].id) { - if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) - return -EINVAL; - if (ctrl.value < s->qctrl[i].minimum || - ctrl.value > s->qctrl[i].maximum) - return -ERANGE; - ctrl.value -= ctrl.value % s->qctrl[i].step; - break; - } - - if ((err = s->set_ctrl(cam, &ctrl))) - return err; - - s->_qctrl[i].default_value = ctrl.value; - - return 0; -} - - -static int -et61x251_vidioc_cropcap(struct et61x251_device* cam, void __user * arg) -{ - struct v4l2_cropcap* cc = &(cam->sensor.cropcap); - - cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cc->pixelaspect.numerator = 1; - cc->pixelaspect.denominator = 1; - - if (copy_to_user(arg, cc, sizeof(*cc))) - return -EFAULT; - - return 0; -} - - -static int -et61x251_vidioc_g_crop(struct et61x251_device* cam, void __user * arg) -{ - struct et61x251_sensor* s = &cam->sensor; - struct v4l2_crop crop = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - }; - - memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); - - if (copy_to_user(arg, &crop, sizeof(crop))) - return -EFAULT; - - return 0; -} - - -static int -et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) -{ - struct et61x251_sensor* s = &cam->sensor; - struct v4l2_crop crop; - struct v4l2_rect* rect; - struct v4l2_rect* bounds = &(s->cropcap.bounds); - struct v4l2_pix_format* pix_format = &(s->pix_format); - u8 scale; - const enum et61x251_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&crop, arg, sizeof(crop))) - return -EFAULT; - - rect = &(crop.c); - - if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_CROP failed. " - "Unmap the buffers first."); - return -EINVAL; - } - - /* Preserve R,G or B origin */ - rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; - rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; - - if (rect->width < 4) - rect->width = 4; - if (rect->height < 4) - rect->height = 4; - if (rect->width > bounds->width) - rect->width = bounds->width; - if (rect->height > bounds->height) - rect->height = bounds->height; - if (rect->left < bounds->left) - rect->left = bounds->left; - if (rect->top < bounds->top) - rect->top = bounds->top; - if (rect->left + rect->width > bounds->left + bounds->width) - rect->left = bounds->left+bounds->width - rect->width; - if (rect->top + rect->height > bounds->top + bounds->height) - rect->top = bounds->top+bounds->height - rect->height; - - rect->width &= ~3L; - rect->height &= ~3L; - - if (ET61X251_PRESERVE_IMGSCALE) { - /* Calculate the actual scaling factor */ - u32 a, b; - a = rect->width * rect->height; - b = pix_format->width * pix_format->height; - scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1; - } else - scale = 1; - - if (cam->stream == STREAM_ON) - if ((err = et61x251_stream_interrupt(cam))) - return err; - - if (copy_to_user(arg, &crop, sizeof(crop))) { - cam->stream = stream; - return -EFAULT; - } - - if (cam->module_param.force_munmap || cam->io == IO_READ) - et61x251_release_buffers(cam); - - err = et61x251_set_crop(cam, rect); - if (s->set_crop) - err += s->set_crop(cam, rect); - err += et61x251_set_scale(cam, scale); - - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -EIO; - } - - s->pix_format.width = rect->width/scale; - s->pix_format.height = rect->height/scale; - memcpy(&(s->_rect), rect, sizeof(*rect)); - - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -ENOMEM; - } - - if (cam->io == IO_READ) - et61x251_empty_framequeues(cam); - else if (cam->module_param.force_munmap) - et61x251_requeue_outqueue(cam); - - cam->stream = stream; - - return 0; -} - - -static int -et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg) -{ - struct v4l2_fmtdesc fmtd; - - if (copy_from_user(&fmtd, arg, sizeof(fmtd))) - return -EFAULT; - - if (fmtd.index == 0) { - strcpy(fmtd.description, "bayer rgb"); - fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; - } else if (fmtd.index == 1) { - strcpy(fmtd.description, "compressed"); - fmtd.pixelformat = V4L2_PIX_FMT_ET61X251; - fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; - } else - return -EINVAL; - - fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); - - if (copy_to_user(arg, &fmtd, sizeof(fmtd))) - return -EFAULT; - - return 0; -} - - -static int -et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg) -{ - struct v4l2_format format; - struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; - - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251) - ? 0 : (pfmt->width * pfmt->priv) / 8; - pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); - pfmt->field = V4L2_FIELD_NONE; - memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); - - if (copy_to_user(arg, &format, sizeof(format))) - return -EFAULT; - - return 0; -} - - -static int -et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, - void __user * arg) -{ - struct et61x251_sensor* s = &cam->sensor; - struct v4l2_format format; - struct v4l2_pix_format* pix; - struct v4l2_pix_format* pfmt = &(s->pix_format); - struct v4l2_rect* bounds = &(s->cropcap.bounds); - struct v4l2_rect rect; - u8 scale; - const enum et61x251_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; - - pix = &(format.fmt.pix); - - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - memcpy(&rect, &(s->_rect), sizeof(rect)); - - { /* calculate the actual scaling factor */ - u32 a, b; - a = rect.width * rect.height; - b = pix->width * pix->height; - scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1; - } - - rect.width = scale * pix->width; - rect.height = scale * pix->height; - - if (rect.width < 4) - rect.width = 4; - if (rect.height < 4) - rect.height = 4; - if (rect.width > bounds->left + bounds->width - rect.left) - rect.width = bounds->left + bounds->width - rect.left; - if (rect.height > bounds->top + bounds->height - rect.top) - rect.height = bounds->top + bounds->height - rect.top; - - rect.width &= ~3L; - rect.height &= ~3L; - - { /* adjust the scaling factor */ - u32 a, b; - a = rect.width * rect.height; - b = pix->width * pix->height; - scale = b ? (u8)((a / b) < 4 ? 1 : 2) : 1; - } - - pix->width = rect.width / scale; - pix->height = rect.height / scale; - - if (pix->pixelformat != V4L2_PIX_FMT_ET61X251 && - pix->pixelformat != V4L2_PIX_FMT_SBGGR8) - pix->pixelformat = pfmt->pixelformat; - pix->priv = pfmt->priv; /* bpp */ - pix->colorspace = pfmt->colorspace; - pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251) - ? 0 : (pix->width * pix->priv) / 8; - pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); - pix->field = V4L2_FIELD_NONE; - - if (cmd == VIDIOC_TRY_FMT) { - if (copy_to_user(arg, &format, sizeof(format))) - return -EFAULT; - return 0; - } - - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_FMT failed. " - "Unmap the buffers first."); - return -EINVAL; - } - - if (cam->stream == STREAM_ON) - if ((err = et61x251_stream_interrupt(cam))) - return err; - - if (copy_to_user(arg, &format, sizeof(format))) { - cam->stream = stream; - return -EFAULT; - } - - if (cam->module_param.force_munmap || cam->io == IO_READ) - et61x251_release_buffers(cam); - - err += et61x251_set_pix_format(cam, pix); - err += et61x251_set_crop(cam, &rect); - if (s->set_pix_format) - err += s->set_pix_format(cam, pix); - if (s->set_crop) - err += s->set_crop(cam, &rect); - err += et61x251_set_scale(cam, scale); - - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -EIO; - } - - memcpy(pfmt, pix, sizeof(*pix)); - memcpy(&(s->_rect), &rect, sizeof(rect)); - - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -ENOMEM; - } - - if (cam->io == IO_READ) - et61x251_empty_framequeues(cam); - else if (cam->module_param.force_munmap) - et61x251_requeue_outqueue(cam); - - cam->stream = stream; - - return 0; -} - - -static int -et61x251_vidioc_g_jpegcomp(struct et61x251_device* cam, void __user * arg) -{ - if (copy_to_user(arg, &cam->compression, - sizeof(cam->compression))) - return -EFAULT; - - return 0; -} - - -static int -et61x251_vidioc_s_jpegcomp(struct et61x251_device* cam, void __user * arg) -{ - struct v4l2_jpegcompression jc; - const enum et61x251_stream_state stream = cam->stream; - int err = 0; - - if (copy_from_user(&jc, arg, sizeof(jc))) - return -EFAULT; - - if (jc.quality != 0 && jc.quality != 1) - return -EINVAL; - - if (cam->stream == STREAM_ON) - if ((err = et61x251_stream_interrupt(cam))) - return err; - - err += et61x251_set_compression(cam, &jc); - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " - "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->minor); - return -EIO; - } - - cam->compression.quality = jc.quality; - - cam->stream = stream; - - return 0; -} - - -static int -et61x251_vidioc_reqbufs(struct et61x251_device* cam, void __user * arg) -{ - struct v4l2_requestbuffers rb; - u32 i; - int err; - - if (copy_from_user(&rb, arg, sizeof(rb))) - return -EFAULT; - - if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - rb.memory != V4L2_MEMORY_MMAP) - return -EINVAL; - - if (cam->io == IO_READ) { - DBG(3, "Close and open the device again to choose the mmap " - "I/O method"); - return -EINVAL; - } - - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_REQBUFS failed. " - "Previous buffers are still mapped."); - return -EINVAL; - } - - if (cam->stream == STREAM_ON) - if ((err = et61x251_stream_interrupt(cam))) - return err; - - et61x251_empty_framequeues(cam); - - et61x251_release_buffers(cam); - if (rb.count) - rb.count = et61x251_request_buffers(cam, rb.count, IO_MMAP); - - if (copy_to_user(arg, &rb, sizeof(rb))) { - et61x251_release_buffers(cam); - cam->io = IO_NONE; - return -EFAULT; - } - - cam->io = rb.count ? IO_MMAP : IO_NONE; - - return 0; -} - - -static int -et61x251_vidioc_querybuf(struct et61x251_device* cam, void __user * arg) -{ - struct v4l2_buffer b; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; - - memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); - - if (cam->frame[b.index].vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; - - if (cam->frame[b.index].state == F_DONE) - b.flags |= V4L2_BUF_FLAG_DONE; - else if (cam->frame[b.index].state != F_UNUSED) - b.flags |= V4L2_BUF_FLAG_QUEUED; - - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - - return 0; -} - - -static int -et61x251_vidioc_qbuf(struct et61x251_device* cam, void __user * arg) -{ - struct v4l2_buffer b; - unsigned long lock_flags; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; - - if (cam->frame[b.index].state != F_UNUSED) - return -EINVAL; - - cam->frame[b.index].state = F_QUEUED; - - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - PDBGG("Frame #%lu queued", (unsigned long)b.index); - - return 0; -} - - -static int -et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp, - void __user * arg) -{ - struct v4l2_buffer b; - struct et61x251_frame_t *f; - unsigned long lock_flags; - long timeout; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP) - return -EINVAL; - - if (list_empty(&cam->outqueue)) { - if (cam->stream == STREAM_OFF) - return -EINVAL; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) - return timeout; - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - if (!timeout || (cam->state & DEV_MISCONFIGURED)) - return -EIO; - } - - spin_lock_irqsave(&cam->queue_lock, lock_flags); - f = list_entry(cam->outqueue.next, struct et61x251_frame_t, frame); - list_del(cam->outqueue.next); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - f->state = F_UNUSED; - - memcpy(&b, &f->buf, sizeof(b)); - if (f->vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; - - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - - PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); - - return 0; -} - - -static int -et61x251_vidioc_streamon(struct et61x251_device* cam, void __user * arg) -{ - int type; - - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - if (list_empty(&cam->inqueue)) - return -EINVAL; - - cam->stream = STREAM_ON; - - DBG(3, "Stream on"); - - return 0; -} - - -static int -et61x251_vidioc_streamoff(struct et61x251_device* cam, void __user * arg) -{ - int type, err; - - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - if (cam->stream == STREAM_ON) - if ((err = et61x251_stream_interrupt(cam))) - return err; - - et61x251_empty_framequeues(cam); - - DBG(3, "Stream off"); - - return 0; -} - - -static int -et61x251_vidioc_g_parm(struct et61x251_device* cam, void __user * arg) -{ - struct v4l2_streamparm sp; - - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; - - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - sp.parm.capture.extendedmode = 0; - sp.parm.capture.readbuffers = cam->nreadbuffers; - - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; - - return 0; -} - - -static int -et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg) -{ - struct v4l2_streamparm sp; - - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; - - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - sp.parm.capture.extendedmode = 0; - - if (sp.parm.capture.readbuffers == 0) - sp.parm.capture.readbuffers = cam->nreadbuffers; - - if (sp.parm.capture.readbuffers > ET61X251_MAX_FRAMES) - sp.parm.capture.readbuffers = ET61X251_MAX_FRAMES; - - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; - - cam->nreadbuffers = sp.parm.capture.readbuffers; - - return 0; -} - - -static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) -{ - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); - - switch (cmd) { - - case VIDIOC_QUERYCAP: - return et61x251_vidioc_querycap(cam, arg); - - case VIDIOC_ENUMINPUT: - return et61x251_vidioc_enuminput(cam, arg); - - case VIDIOC_G_INPUT: - return et61x251_vidioc_g_input(cam, arg); - - case VIDIOC_S_INPUT: - return et61x251_vidioc_s_input(cam, arg); - - case VIDIOC_QUERYCTRL: - return et61x251_vidioc_query_ctrl(cam, arg); - - case VIDIOC_G_CTRL: - return et61x251_vidioc_g_ctrl(cam, arg); - - case VIDIOC_S_CTRL_OLD: - case VIDIOC_S_CTRL: - return et61x251_vidioc_s_ctrl(cam, arg); - - case VIDIOC_CROPCAP_OLD: - case VIDIOC_CROPCAP: - return et61x251_vidioc_cropcap(cam, arg); - - case VIDIOC_G_CROP: - return et61x251_vidioc_g_crop(cam, arg); - - case VIDIOC_S_CROP: - return et61x251_vidioc_s_crop(cam, arg); - - case VIDIOC_ENUM_FMT: - return et61x251_vidioc_enum_fmt(cam, arg); - - case VIDIOC_G_FMT: - return et61x251_vidioc_g_fmt(cam, arg); - - case VIDIOC_TRY_FMT: - case VIDIOC_S_FMT: - return et61x251_vidioc_try_s_fmt(cam, cmd, arg); - - case VIDIOC_G_JPEGCOMP: - return et61x251_vidioc_g_jpegcomp(cam, arg); - - case VIDIOC_S_JPEGCOMP: - return et61x251_vidioc_s_jpegcomp(cam, arg); - - case VIDIOC_REQBUFS: - return et61x251_vidioc_reqbufs(cam, arg); - - case VIDIOC_QUERYBUF: - return et61x251_vidioc_querybuf(cam, arg); - - case VIDIOC_QBUF: - return et61x251_vidioc_qbuf(cam, arg); - - case VIDIOC_DQBUF: - return et61x251_vidioc_dqbuf(cam, filp, arg); - - case VIDIOC_STREAMON: - return et61x251_vidioc_streamon(cam, arg); - - case VIDIOC_STREAMOFF: - return et61x251_vidioc_streamoff(cam, arg); - - case VIDIOC_G_PARM: - return et61x251_vidioc_g_parm(cam, arg); - - case VIDIOC_S_PARM_OLD: - case VIDIOC_S_PARM: - return et61x251_vidioc_s_parm(cam, arg); - - case VIDIOC_G_STD: - case VIDIOC_S_STD: - case VIDIOC_QUERYSTD: - case VIDIOC_ENUMSTD: - case VIDIOC_QUERYMENU: - return -EINVAL; - - default: - return -EINVAL; - - } -} - - -static int et61x251_ioctl(struct inode* inode, struct file* filp, - unsigned int cmd, unsigned long arg) -{ - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); - int err = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - V4LDBG(3, "et61x251", cmd); - - err = et61x251_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); - - mutex_unlock(&cam->fileop_mutex); - - return err; -} - - -static struct file_operations et61x251_fops = { - .owner = THIS_MODULE, - .open = et61x251_open, - .release = et61x251_release, - .ioctl = et61x251_ioctl, - .read = et61x251_read, - .poll = et61x251_poll, - .mmap = et61x251_mmap, - .llseek = no_llseek, -}; - -/*****************************************************************************/ - -/* It exists a single interface only. We do not need to validate anything. */ -static int -et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct et61x251_device* cam; - static unsigned int dev_nr = 0; - unsigned int i; - int err = 0; - - if (!(cam = kzalloc(sizeof(struct et61x251_device), GFP_KERNEL))) - return -ENOMEM; - - cam->usbdev = udev; - - if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { - DBG(1, "kmalloc() failed"); - err = -ENOMEM; - goto fail; - } - - if (!(cam->v4ldev = video_device_alloc())) { - DBG(1, "video_device_alloc() failed"); - err = -ENOMEM; - goto fail; - } - - mutex_init(&cam->dev_mutex); - - DBG(2, "ET61X[12]51 PC Camera Controller detected " - "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); - - for (i = 0; et61x251_sensor_table[i]; i++) { - err = et61x251_sensor_table[i](cam); - if (!err) - break; - } - - if (!err) - DBG(2, "%s image sensor detected", cam->sensor.name); - else { - DBG(1, "No supported image sensor detected"); - err = -ENODEV; - goto fail; - } - - if (et61x251_init(cam)) { - DBG(1, "Initialization failed. I will retry on open()."); - cam->state |= DEV_MISCONFIGURED; - } - - strcpy(cam->v4ldev->name, "ET61X[12]51 PC Camera"); - cam->v4ldev->owner = THIS_MODULE; - cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; - cam->v4ldev->hardware = 0; - cam->v4ldev->fops = &et61x251_fops; - cam->v4ldev->minor = video_nr[dev_nr]; - cam->v4ldev->release = video_device_release; - video_set_drvdata(cam->v4ldev, cam); - - mutex_lock(&cam->dev_mutex); - - err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); - if (err) { - DBG(1, "V4L2 device registration failed"); - if (err == -ENFILE && video_nr[dev_nr] == -1) - DBG(1, "Free /dev/videoX node not found"); - video_nr[dev_nr] = -1; - dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; - mutex_unlock(&cam->dev_mutex); - goto fail; - } - - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); - - cam->module_param.force_munmap = force_munmap[dev_nr]; - cam->module_param.frame_timeout = frame_timeout[dev_nr]; - - dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; - -#ifdef CONFIG_VIDEO_ADV_DEBUG - et61x251_create_sysfs(cam); - DBG(2, "Optional device control through 'sysfs' interface ready"); -#endif - - usb_set_intfdata(intf, cam); - - mutex_unlock(&cam->dev_mutex); - - return 0; - -fail: - if (cam) { - kfree(cam->control_buffer); - if (cam->v4ldev) - video_device_release(cam->v4ldev); - kfree(cam); - } - return err; -} - - -static void et61x251_usb_disconnect(struct usb_interface* intf) -{ - struct et61x251_device* cam = usb_get_intfdata(intf); - - if (!cam) - return; - - down_write(&et61x251_disconnect); - - mutex_lock(&cam->dev_mutex); - - DBG(2, "Disconnecting %s...", cam->v4ldev->name); - - wake_up_interruptible_all(&cam->open); - - if (cam->users) { - DBG(2, "Device /dev/video%d is open! Deregistration and " - "memory deallocation are deferred on close.", - cam->v4ldev->minor); - cam->state |= DEV_MISCONFIGURED; - et61x251_stop_transfer(cam); - cam->state |= DEV_DISCONNECTED; - wake_up_interruptible(&cam->wait_frame); - wake_up(&cam->wait_stream); - usb_get_dev(cam->usbdev); - } else { - cam->state |= DEV_DISCONNECTED; - et61x251_release_resources(cam); - } - - mutex_unlock(&cam->dev_mutex); - - if (!cam->users) - kfree(cam); - - up_write(&et61x251_disconnect); -} - - -static struct usb_driver et61x251_usb_driver = { - .name = "et61x251", - .id_table = et61x251_id_table, - .probe = et61x251_usb_probe, - .disconnect = et61x251_usb_disconnect, -}; - -/*****************************************************************************/ - -static int __init et61x251_module_init(void) -{ - int err = 0; - - KDBG(2, ET61X251_MODULE_NAME " v" ET61X251_MODULE_VERSION); - KDBG(3, ET61X251_MODULE_AUTHOR); - - if ((err = usb_register(&et61x251_usb_driver))) - KDBG(1, "usb_register() failed"); - - return err; -} - - -static void __exit et61x251_module_exit(void) -{ - usb_deregister(&et61x251_usb_driver); -} - - -module_init(et61x251_module_init); -module_exit(et61x251_module_exit); diff --git a/drivers/usb/media/et61x251_sensor.h b/drivers/usb/media/et61x251_sensor.h deleted file mode 100644 index 56841ae8a207..000000000000 --- a/drivers/usb/media/et61x251_sensor.h +++ /dev/null @@ -1,116 +0,0 @@ -/*************************************************************************** - * API for image sensors connected to ET61X[12]51 PC Camera Controllers * - * * - * Copyright (C) 2006 by Luca Risolia * - * * - * 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. * - ***************************************************************************/ - -#ifndef _ET61X251_SENSOR_H_ -#define _ET61X251_SENSOR_H_ - -#include -#include -#include -#include -#include -#include - -struct et61x251_device; -struct et61x251_sensor; - -/*****************************************************************************/ - -extern int et61x251_probe_tas5130d1b(struct et61x251_device* cam); - -#define ET61X251_SENSOR_TABLE \ -/* Weak detections must go at the end of the list */ \ -static int (*et61x251_sensor_table[])(struct et61x251_device*) = { \ - &et61x251_probe_tas5130d1b, \ - NULL, \ -}; - -extern struct et61x251_device* -et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id); - -extern void -et61x251_attach_sensor(struct et61x251_device* cam, - struct et61x251_sensor* sensor); - -/*****************************************************************************/ - -extern int et61x251_write_reg(struct et61x251_device*, u8 value, u16 index); -extern int et61x251_read_reg(struct et61x251_device*, u16 index); -extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value); -extern int et61x251_i2c_read(struct et61x251_device*, u8 address); -extern int et61x251_i2c_try_write(struct et61x251_device*, - struct et61x251_sensor*, u8 address, - u8 value); -extern int et61x251_i2c_try_read(struct et61x251_device*, - struct et61x251_sensor*, u8 address); -extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1, - u8 data2, u8 data3, u8 data4, u8 data5, - u8 data6, u8 data7, u8 data8, u8 address); - -/*****************************************************************************/ - -enum et61x251_i2c_sysfs_ops { - ET61X251_I2C_READ = 0x01, - ET61X251_I2C_WRITE = 0x02, -}; - -enum et61x251_i2c_interface { - ET61X251_I2C_2WIRES, - ET61X251_I2C_3WIRES, -}; - -/* Repeat start condition when RSTA is high */ -enum et61x251_i2c_rsta { - ET61X251_I2C_RSTA_STOP = 0x00, /* stop then start */ - ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */ -}; - -#define ET61X251_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 - -struct et61x251_sensor { - char name[32]; - - enum et61x251_i2c_sysfs_ops sysfs_ops; - - enum et61x251_i2c_interface interface; - u8 i2c_slave_id; - enum et61x251_i2c_rsta rsta; - struct v4l2_rect active_pixel; /* left and top define FVSX and FVSY */ - - struct v4l2_queryctrl qctrl[ET61X251_MAX_CTRLS]; - struct v4l2_cropcap cropcap; - struct v4l2_pix_format pix_format; - - int (*init)(struct et61x251_device* cam); - int (*get_ctrl)(struct et61x251_device* cam, - struct v4l2_control* ctrl); - int (*set_ctrl)(struct et61x251_device* cam, - const struct v4l2_control* ctrl); - int (*set_crop)(struct et61x251_device* cam, - const struct v4l2_rect* rect); - int (*set_pix_format)(struct et61x251_device* cam, - const struct v4l2_pix_format* pix); - - /* Private */ - struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS]; - struct v4l2_rect _rect; -}; - -#endif /* _ET61X251_SENSOR_H_ */ diff --git a/drivers/usb/media/et61x251_tas5130d1b.c b/drivers/usb/media/et61x251_tas5130d1b.c deleted file mode 100644 index 3998d76a307a..000000000000 --- a/drivers/usb/media/et61x251_tas5130d1b.c +++ /dev/null @@ -1,141 +0,0 @@ -/*************************************************************************** - * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51 * - * PC Camera Controllers * - * * - * Copyright (C) 2006 by Luca Risolia * - * * - * 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 "et61x251_sensor.h" - - -static int tas5130d1b_init(struct et61x251_device* cam) -{ - int err = 0; - - err += et61x251_write_reg(cam, 0x14, 0x01); - err += et61x251_write_reg(cam, 0x1b, 0x02); - err += et61x251_write_reg(cam, 0x02, 0x12); - err += et61x251_write_reg(cam, 0x0e, 0x60); - err += et61x251_write_reg(cam, 0x80, 0x61); - err += et61x251_write_reg(cam, 0xf0, 0x62); - err += et61x251_write_reg(cam, 0x03, 0x63); - err += et61x251_write_reg(cam, 0x14, 0x64); - err += et61x251_write_reg(cam, 0xf4, 0x65); - err += et61x251_write_reg(cam, 0x01, 0x66); - err += et61x251_write_reg(cam, 0x05, 0x67); - err += et61x251_write_reg(cam, 0x8f, 0x68); - err += et61x251_write_reg(cam, 0x0f, 0x8d); - err += et61x251_write_reg(cam, 0x08, 0x8e); - - return err; -} - - -static int tas5130d1b_set_ctrl(struct et61x251_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_GAIN: - err += et61x251_i2c_raw_write(cam, 2, 0x20, - 0xf6-ctrl->value, 0, 0, 0, - 0, 0, 0, 0); - break; - case V4L2_CID_EXPOSURE: - err += et61x251_i2c_raw_write(cam, 2, 0x40, - 0x47-ctrl->value, 0, 0, 0, - 0, 0, 0, 0); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static struct et61x251_sensor tas5130d1b = { - .name = "TAS5130D1B", - .interface = ET61X251_I2C_3WIRES, - .rsta = ET61X251_I2C_RSTA_STOP, - .active_pixel = { - .left = 106, - .top = 13, - }, - .init = &tas5130d1b_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0xf6, - .step = 0x02, - .default_value = 0x0d, - .flags = 0, - }, - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0x47, - .step = 0x01, - .default_value = 0x23, - .flags = 0, - }, - }, - .set_ctrl = &tas5130d1b_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, -}; - - -int et61x251_probe_tas5130d1b(struct et61x251_device* cam) -{ - const struct usb_device_id tas5130d1b_id_table[] = { - { USB_DEVICE(0x102c, 0x6251), }, - { } - }; - - /* Sensor detection is based on USB pid/vid */ - if (!et61x251_match_id(cam, tas5130d1b_id_table)) - return -ENODEV; - - et61x251_attach_sensor(cam, &tas5130d1b); - - return 0; -} diff --git a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c deleted file mode 100644 index a42c22294124..000000000000 --- a/drivers/usb/media/ibmcam.c +++ /dev/null @@ -1,3932 +0,0 @@ -/* - * USB IBM C-It Video Camera driver - * - * Supports Xirlink C-It Video Camera, IBM PC Camera, - * IBM NetCamera and Veo Stingray. - * - * This driver is based on earlier work of: - * - * (C) Copyright 1999 Johannes Erdfelt - * (C) Copyright 1999 Randy Dunlap - * - * 5/24/00 Removed optional (and unnecessary) locking of the driver while - * the device remains plugged in. Corrected race conditions in ibmcam_open - * and ibmcam_probe() routines using this as a guideline: - */ - -#include -#include -#include -#include - -#include "usbvideo.h" - -#define IBMCAM_VENDOR_ID 0x0545 -#define IBMCAM_PRODUCT_ID 0x8080 -#define NETCAM_PRODUCT_ID 0x8002 /* IBM NetCamera, close to model 2 */ -#define VEO_800C_PRODUCT_ID 0x800C /* Veo Stingray, repackaged Model 2 */ -#define VEO_800D_PRODUCT_ID 0x800D /* Veo Stingray, repackaged Model 4 */ - -#define MAX_IBMCAM 4 /* How many devices we allow to connect */ -#define USES_IBMCAM_PUTPIXEL 0 /* 0=Fast/oops 1=Slow/secure */ - -/* Header signatures */ - -/* Model 1 header: 00 FF 00 xx */ -#define HDRSIG_MODEL1_128x96 0x06 /* U Y V Y ... */ -#define HDRSIG_MODEL1_176x144 0x0e /* U Y V Y ... */ -#define HDRSIG_MODEL1_352x288 0x00 /* V Y U Y ... */ - -#define IBMCAM_MODEL_1 1 /* XVP-501, 3 interfaces, rev. 0.02 */ -#define IBMCAM_MODEL_2 2 /* KSX-X9903, 2 interfaces, rev. 3.0a */ -#define IBMCAM_MODEL_3 3 /* KSX-X9902, 2 interfaces, rev. 3.01 */ -#define IBMCAM_MODEL_4 4 /* IBM NetCamera, 0545/8002/3.0a */ - -/* Video sizes supported */ -#define VIDEOSIZE_128x96 VIDEOSIZE(128, 96) -#define VIDEOSIZE_176x144 VIDEOSIZE(176,144) -#define VIDEOSIZE_352x288 VIDEOSIZE(352,288) -#define VIDEOSIZE_320x240 VIDEOSIZE(320,240) -#define VIDEOSIZE_352x240 VIDEOSIZE(352,240) -#define VIDEOSIZE_640x480 VIDEOSIZE(640,480) -#define VIDEOSIZE_160x120 VIDEOSIZE(160,120) - -/* Video sizes supported */ -enum { - SIZE_128x96 = 0, - SIZE_160x120, - SIZE_176x144, - SIZE_320x240, - SIZE_352x240, - SIZE_352x288, - SIZE_640x480, - /* Add/remove/rearrange items before this line */ - SIZE_LastItem -}; - -/* - * This structure lives in uvd->user field. - */ -typedef struct { - int initialized; /* Had we already sent init sequence? */ - int camera_model; /* What type of IBM camera we got? */ - int has_hdr; -} ibmcam_t; -#define IBMCAM_T(uvd) ((ibmcam_t *)((uvd)->user_data)) - -static struct usbvideo *cams; - -static int debug; - -static int flags; /* = FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ - -static const int min_canvasWidth = 8; -static const int min_canvasHeight = 4; - -static int lighting = 1; /* Medium */ - -#define SHARPNESS_MIN 0 -#define SHARPNESS_MAX 6 -static int sharpness = 4; /* Low noise, good details */ - -#define FRAMERATE_MIN 0 -#define FRAMERATE_MAX 6 -static int framerate = -1; - -static int size = SIZE_352x288; - -/* - * Here we define several initialization variables. They may - * be used to automatically set color, hue, brightness and - * contrast to desired values. This is particularly useful in - * case of webcams (which have no controls and no on-screen - * output) and also when a client V4L software is used that - * does not have some of those controls. In any case it's - * good to have startup values as options. - * - * These values are all in [0..255] range. This simplifies - * operation. Note that actual values of V4L variables may - * be scaled up (as much as << 8). User can see that only - * on overlay output, however, or through a V4L client. - */ -static int init_brightness = 128; -static int init_contrast = 192; -static int init_color = 128; -static int init_hue = 128; -static int hue_correction = 128; - -/* Settings for camera model 2 */ -static int init_model2_rg2 = -1; -static int init_model2_sat = -1; -static int init_model2_yb = -1; - -/* 01.01.08 - Added for RCA video in support -LO */ -/* Settings for camera model 3 */ -static int init_model3_input = 0; - -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); -module_param(flags, int, 0); -MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames"); -module_param(framerate, int, 0); -MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); -module_param(lighting, int, 0); -MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light"); -module_param(sharpness, int, 0); -MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)"); -module_param(size, int, 0); -MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480 (default=5)"); -module_param(init_brightness, int, 0); -MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); -module_param(init_contrast, int, 0); -MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); -module_param(init_color, int, 0); -MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)"); -module_param(init_hue, int, 0); -MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); -module_param(hue_correction, int, 0); -MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); - -module_param(init_model2_rg2, int, 0); -MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)"); -module_param(init_model2_sat, int, 0); -MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)"); -module_param(init_model2_yb, int, 0); -MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)"); - -/* 01.01.08 - Added for RCA video in support -LO */ -module_param(init_model3_input, int, 0); -MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA"); - -MODULE_AUTHOR ("Dmitri"); -MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000"); -MODULE_LICENSE("GPL"); - -/* Still mysterious i2c commands */ -static const unsigned short unknown_88 = 0x0088; -static const unsigned short unknown_89 = 0x0089; -static const unsigned short bright_3x[3] = { 0x0031, 0x0032, 0x0033 }; -static const unsigned short contrast_14 = 0x0014; -static const unsigned short light_27 = 0x0027; -static const unsigned short sharp_13 = 0x0013; - -/* i2c commands for Model 2 cameras */ -static const unsigned short mod2_brightness = 0x001a; /* $5b .. $ee; default=$5a */ -static const unsigned short mod2_set_framerate = 0x001c; /* 0 (fast).. $1F (slow) */ -static const unsigned short mod2_color_balance_rg2 = 0x001e; /* 0 (red) .. $7F (green) */ -static const unsigned short mod2_saturation = 0x0020; /* 0 (b/w) - $7F (full color) */ -static const unsigned short mod2_color_balance_yb = 0x0022; /* 0..$7F, $50 is about right */ -static const unsigned short mod2_hue = 0x0024; /* 0..$7F, $70 is about right */ -static const unsigned short mod2_sensitivity = 0x0028; /* 0 (min) .. $1F (max) */ - -struct struct_initData { - unsigned char req; - unsigned short value; - unsigned short index; -}; - -/* - * ibmcam_size_to_videosize() - * - * This procedure converts module option 'size' into the actual - * videosize_t that defines the image size in pixels. We need - * simplified 'size' because user wants a simple enumerated list - * of choices, not an infinite set of possibilities. - */ -static videosize_t ibmcam_size_to_videosize(int size) -{ - videosize_t vs = VIDEOSIZE_352x288; - RESTRICT_TO_RANGE(size, 0, (SIZE_LastItem-1)); - switch (size) { - case SIZE_128x96: - vs = VIDEOSIZE_128x96; - break; - case SIZE_160x120: - vs = VIDEOSIZE_160x120; - break; - case SIZE_176x144: - vs = VIDEOSIZE_176x144; - break; - case SIZE_320x240: - vs = VIDEOSIZE_320x240; - break; - case SIZE_352x240: - vs = VIDEOSIZE_352x240; - break; - case SIZE_352x288: - vs = VIDEOSIZE_352x288; - break; - case SIZE_640x480: - vs = VIDEOSIZE_640x480; - break; - default: - err("size=%d. is not valid", size); - break; - } - return vs; -} - -/* - * ibmcam_find_header() - * - * Locate one of supported header markers in the queue. - * Once found, remove all preceding bytes AND the marker (4 bytes) - * from the data pump queue. Whatever follows must be video lines. - * - * History: - * 1/21/00 Created. - */ -static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame here */ -{ - struct usbvideo_frame *frame; - ibmcam_t *icam; - - if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { - err("ibmcam_find_header: Illegal frame %d.", uvd->curframe); - return scan_EndParse; - } - icam = IBMCAM_T(uvd); - assert(icam != NULL); - frame = &uvd->frame[uvd->curframe]; - icam->has_hdr = 0; - switch (icam->camera_model) { - case IBMCAM_MODEL_1: - { - const int marker_len = 4; - while (RingQueue_GetLength(&uvd->dp) >= marker_len) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) && - (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00)) - { -#if 0 /* This code helps to detect new frame markers */ - info("Header sig: 00 FF 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 3)); -#endif - frame->header = RING_QUEUE_PEEK(&uvd->dp, 3); - if ((frame->header == HDRSIG_MODEL1_128x96) || - (frame->header == HDRSIG_MODEL1_176x144) || - (frame->header == HDRSIG_MODEL1_352x288)) - { -#if 0 - info("Header found."); -#endif - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); - icam->has_hdr = 1; - break; - } - } - /* If we are still here then this doesn't look like a header */ - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - } - break; - } - case IBMCAM_MODEL_2: -case IBMCAM_MODEL_4: - { - int marker_len = 0; - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - marker_len = 10; - break; - default: - marker_len = 2; - break; - } - while (RingQueue_GetLength(&uvd->dp) >= marker_len) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF)) - { -#if 0 - info("Header found."); -#endif - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); - icam->has_hdr = 1; - frame->header = HDRSIG_MODEL1_176x144; - break; - } - /* If we are still here then this doesn't look like a header */ - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - } - break; - } - case IBMCAM_MODEL_3: - { /* - * Headers: (one precedes every frame). nc=no compression, - * bq=best quality bf=best frame rate. - * - * 176x144: 00 FF 02 { 0A=nc CA=bq EA=bf } - * 320x240: 00 FF 02 { 08=nc 28=bq 68=bf } - * 640x480: 00 FF 03 { 08=nc 28=bq 68=bf } - * - * Bytes '00 FF' seem to indicate header. Other two bytes - * encode the frame type. This is a set of bit fields that - * encode image size, compression type etc. These fields - * do NOT contain frame number because all frames carry - * the same header. - */ - const int marker_len = 4; - while (RingQueue_GetLength(&uvd->dp) >= marker_len) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) && - (RING_QUEUE_PEEK(&uvd->dp, 2) != 0xFF)) - { - /* - * Combine 2 bytes of frame type into one - * easy to use value - */ - unsigned long byte3, byte4; - - byte3 = RING_QUEUE_PEEK(&uvd->dp, 2); - byte4 = RING_QUEUE_PEEK(&uvd->dp, 3); - frame->header = (byte3 << 8) | byte4; -#if 0 - info("Header found."); -#endif - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); - icam->has_hdr = 1; - break; - } - /* If we are still here then this doesn't look like a header */ - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - } - break; - } - default: - break; - } - if (!icam->has_hdr) { - if (uvd->debug > 2) - info("Skipping frame, no header"); - return scan_EndParse; - } - - /* Header found */ - icam->has_hdr = 1; - uvd->stats.header_count++; - frame->scanstate = ScanState_Lines; - frame->curline = 0; - - if (flags & FLAGS_FORCE_TESTPATTERN) { - usbvideo_TestPattern(uvd, 1, 1); - return scan_NextFrame; - } - return scan_Continue; -} - -/* - * ibmcam_parse_lines() - * - * Parse one line (interlaced) from the buffer, put - * decoded RGB value into the current frame buffer - * and add the written number of bytes (RGB) to - * the *pcopylen. - * - * History: - * 21-Jan-2000 Created. - * 12-Oct-2000 Reworked to reflect interlaced nature of the data. - */ -static enum ParseState ibmcam_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - unsigned char *f; - ibmcam_t *icam; - unsigned int len, scanLength, scanHeight, order_uv, order_yc; - int v4l_linesize; /* V4L line offset */ - const int hue_corr = (uvd->vpic.hue - 0x8000) >> 10; /* -32..+31 */ - const int hue2_corr = (hue_correction - 128) / 4; /* -32..+31 */ - const int ccm = 128; /* Color correction median - see below */ - int y, u, v, i, frame_done=0, color_corr; - static unsigned char lineBuffer[640*3]; - unsigned const char *chromaLine, *lumaLine; - - assert(uvd != NULL); - assert(frame != NULL); - icam = IBMCAM_T(uvd); - assert(icam != NULL); - color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ - RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1); - - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - if (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_4) { - /* Model 4 frame markers do not carry image size identification */ - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - case VIDEOSIZE_160x120: - case VIDEOSIZE_176x144: - scanLength = VIDEOSIZE_X(uvd->videosize); - scanHeight = VIDEOSIZE_Y(uvd->videosize); - break; - default: - err("ibmcam_parse_lines: Wrong mode."); - return scan_Out; - } - order_yc = 1; /* order_yc: true=Yc false=cY ('c'=either U or V) */ - order_uv = 1; /* Always true in this algorithm */ - } else { - switch (frame->header) { - case HDRSIG_MODEL1_128x96: - scanLength = 128; - scanHeight = 96; - order_uv = 1; /* U Y V Y ... */ - break; - case HDRSIG_MODEL1_176x144: - scanLength = 176; - scanHeight = 144; - order_uv = 1; /* U Y V Y ... */ - break; - case HDRSIG_MODEL1_352x288: - scanLength = 352; - scanHeight = 288; - order_uv = 0; /* Y V Y V ... */ - break; - default: - err("Unknown header signature 00 FF 00 %02lX", frame->header); - return scan_NextFrame; - } - /* order_yc: true=Yc false=cY ('c'=either U or V) */ - order_yc = (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_2); - } - - len = scanLength * 3; - assert(len <= sizeof(lineBuffer)); - - /* - * Lines are organized this way: - * - * I420: - * ~~~~ - * - * ___________________________________ - * |-----Y-----|---UVUVUV...UVUV-----| \ - * |-----------+---------------------| \ - * |<-- 176 -->|<------ 176*2 ------>| Total 72. lines (interlaced) - * |... ... | ... | / - * |<-- 352 -->|<------ 352*2 ------>| Total 144. lines (interlaced) - * |___________|_____________________| / - * \ \ - * lumaLine chromaLine - */ - - /* Make sure there's enough data for the entire line */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck one line out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Mind that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request)) - return scan_NextFrame; - - /* - * Now we are sure that entire line (representing all 'scanLength' - * pixels from the camera) is available in the buffer. We - * start copying the line left-aligned to the V4L buffer. - * If the camera line is shorter then we should pad the V4L - * buffer with something (black) to complete the line. - */ - assert(frame->data != NULL); - f = frame->data + (v4l_linesize * frame->curline); - - /* - * To obtain chrominance data from the 'chromaLine' use this: - * v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]... - * u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]... - * - * Indices must be calculated this way: - * v_index = (i >> 1) << 2; - * u_index = (i >> 1) << 2 + 2; - * - * where 'i' is the column number [0..VIDEOSIZE_X(frame->request)-1] - */ - lumaLine = lineBuffer; - chromaLine = lineBuffer + scanLength; - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) - { - unsigned char rv, gv, bv; /* RGB components */ - - /* Check for various visual debugging hints (colorized pixels) */ - if ((flags & FLAGS_DISPLAY_HINTS) && (icam->has_hdr)) { - /* - * This is bad and should not happen. This means that - * we somehow overshoot the line and encountered new - * frame! Obviously our camera/V4L frame size is out - * of whack. This cyan dot will help you to figure - * out where exactly the new frame arrived. - */ - if (icam->has_hdr == 1) { - bv = 0; /* Yellow marker */ - gv = 0xFF; - rv = 0xFF; - } else { - bv = 0xFF; /* Cyan marker */ - gv = 0xFF; - rv = 0; - } - icam->has_hdr = 0; - goto make_pixel; - } - - /* - * Check if we are still in range. We may be out of range if our - * V4L canvas is wider or taller than the camera "native" image. - * Then we quickly fill the remainder of the line with zeros to - * make black color and quit the horizontal scanning loop. - */ - if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) { - const int j = i * V4L_BYTES_PER_PIXEL; -#if USES_IBMCAM_PUTPIXEL - /* Refresh 'f' because we don't use it much with PUTPIXEL */ - f = frame->data + (v4l_linesize * frame->curline) + j; -#endif - memset(f, 0, v4l_linesize - j); - break; - } - - y = lumaLine[i]; - if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */ - rv = gv = bv = y; - else { - int off_0, off_2; - - off_0 = (i >> 1) << 2; - off_2 = off_0 + 2; - - if (order_yc) { - off_0++; - off_2++; - } - if (!order_uv) { - off_0 += 2; - off_2 -= 2; - } - u = chromaLine[off_0] + hue_corr; - v = chromaLine[off_2] + hue2_corr; - - /* Apply color correction */ - if (color_corr != 0) { - /* Magnify up to 2 times, reduce down to zero saturation */ - u = 128 + ((ccm + color_corr) * (u - 128)) / ccm; - v = 128 + ((ccm + color_corr) * (v - 128)) / ccm; - } - YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); - } - - make_pixel: - /* - * The purpose of creating the pixel here, in one, - * dedicated place is that we may need to make the - * pixel wider and taller than it actually is. This - * may be used if camera generates small frames for - * sake of frame rate (or any other reason.) - * - * The output data consists of B, G, R bytes - * (in this order). - */ -#if USES_IBMCAM_PUTPIXEL - RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); -#else - *f++ = bv; - *f++ = gv; - *f++ = rv; -#endif - /* - * Typically we do not decide within a legitimate frame - * that we want to end the frame. However debugging code - * may detect marker of new frame within the data. Then - * this condition activates. The 'data' pointer is already - * pointing at the new marker, so we'd better leave it as is. - */ - if (frame_done) - break; /* End scanning of lines */ - } - /* - * Account for number of bytes that we wrote into output V4L frame. - * We do it here, after we are done with the scanline, because we - * may fill more than one output scanline if we do vertical - * enlargement. - */ - frame->curline += 2; - if (pcopylen != NULL) - *pcopylen += 2 * v4l_linesize; - frame->deinterlace = Deinterlace_FillOddLines; - - if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request))) - return scan_NextFrame; - else - return scan_Continue; -} - -/* - * ibmcam_model2_320x240_parse_lines() - * - * This procedure deals with a weird RGB format that is produced by IBM - * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175, - * depending on horizontal size of the picture: - * - * <--- 160 or 176 pairs of RA,RB bytes -----> - * *-----------------------------------------* \ - * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx | \ This is pair of horizontal lines, - * |-----+-----+-----+-----+ ... +-----+-----| *- or one interlaced line, total - * | B0 | G0 | B1 | G1 | ... | Bx | Gx | / 120 or 144 such pairs which yield - * |=====+=====+=====+=====+ ... +=====+=====| / 240 or 288 lines after deinterlacing. - * - * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1 - * defines ONE pixel. Therefore this format yields 176x144 "decoded" - * resolution at best. I do not know why camera sends such format - the - * previous model (1) just used interlaced I420 and everyone was happy. - * - * I do not know what is the difference between RAi and RBi bytes. Both - * seemingly represent R component, but slightly vary in value (so that - * the picture looks a bit colored if one or another is used). I use - * them both as R component in attempt to at least partially recover the - * lost resolution. - */ -static enum ParseState ibmcam_model2_320x240_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - unsigned char *f, *la, *lb; - unsigned int len; - int v4l_linesize; /* V4L line offset */ - int i, j, frame_done=0, color_corr; - int scanLength, scanHeight; - static unsigned char lineBuffer[352*2]; - - switch (uvd->videosize) { - case VIDEOSIZE_320x240: - case VIDEOSIZE_352x240: - case VIDEOSIZE_352x288: - scanLength = VIDEOSIZE_X(uvd->videosize); - scanHeight = VIDEOSIZE_Y(uvd->videosize); - break; - default: - err("ibmcam_model2_320x240_parse_lines: Wrong mode."); - return scan_Out; - } - - color_corr = (uvd->vpic.colour) >> 8; /* 0..+255 */ - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - len = scanLength * 2; /* See explanation above */ - assert(len <= sizeof(lineBuffer)); - - /* Make sure there's enough data for the entire line */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck one line out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Mind that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request)) - return scan_NextFrame; - - la = lineBuffer; - lb = lineBuffer + scanLength; - - /* - * Now we are sure that entire line (representing all - * VIDEOSIZE_X(frame->request) - * pixels from the camera) is available in the scratch buffer. We - * start copying the line left-aligned to the V4L buffer (which - * might be larger - not smaller, hopefully). If the camera - * line is shorter then we should pad the V4L buffer with something - * (black in this case) to complete the line. - */ - f = frame->data + (v4l_linesize * frame->curline); - - /* Fill the 2-line strip */ - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { - int y, rv, gv, bv; /* RGB components */ - - j = i & (~1); - - /* Check for various visual debugging hints (colorized pixels) */ - if ((flags & FLAGS_DISPLAY_HINTS) && (IBMCAM_T(uvd)->has_hdr)) { - if (IBMCAM_T(uvd)->has_hdr == 1) { - bv = 0; /* Yellow marker */ - gv = 0xFF; - rv = 0xFF; - } else { - bv = 0xFF; /* Cyan marker */ - gv = 0xFF; - rv = 0; - } - IBMCAM_T(uvd)->has_hdr = 0; - goto make_pixel; - } - - /* - * Check if we are still in range. We may be out of range if our - * V4L canvas is wider or taller than the camera "native" image. - * Then we quickly fill the remainder of the line with zeros to - * make black color and quit the horizontal scanning loop. - */ - if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) { - const int j = i * V4L_BYTES_PER_PIXEL; -#if USES_IBMCAM_PUTPIXEL - /* Refresh 'f' because we don't use it much with PUTPIXEL */ - f = frame->data + (v4l_linesize * frame->curline) + j; -#endif - memset(f, 0, v4l_linesize - j); - break; - } - - /* - * Here I use RA and RB components, one per physical pixel. - * This causes fine vertical grid on the picture but may improve - * horizontal resolution. If you prefer replicating, use this: - * rv = la[j + 0]; ... or ... rv = la[j + 1]; - * then the pixel will be replicated. - */ - rv = la[i]; - gv = lb[j + 1]; - bv = lb[j + 0]; - - y = (rv + gv + bv) / 3; /* Brightness (badly calculated) */ - - if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */ - rv = gv = bv = y; - else if (color_corr != 128) { - - /* Calculate difference between color and brightness */ - rv -= y; - gv -= y; - bv -= y; - - /* Scale differences */ - rv = (rv * color_corr) / 128; - gv = (gv * color_corr) / 128; - bv = (bv * color_corr) / 128; - - /* Reapply brightness */ - rv += y; - gv += y; - bv += y; - - /* Watch for overflows */ - RESTRICT_TO_RANGE(rv, 0, 255); - RESTRICT_TO_RANGE(gv, 0, 255); - RESTRICT_TO_RANGE(bv, 0, 255); - } - - make_pixel: - RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); - } - /* - * Account for number of bytes that we wrote into output V4L frame. - * We do it here, after we are done with the scanline, because we - * may fill more than one output scanline if we do vertical - * enlargement. - */ - frame->curline += 2; - *pcopylen += v4l_linesize * 2; - frame->deinterlace = Deinterlace_FillOddLines; - - if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request))) - return scan_NextFrame; - else - return scan_Continue; -} - -static enum ParseState ibmcam_model3_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - unsigned char *data; - const unsigned char *color; - unsigned int len; - int v4l_linesize; /* V4L line offset */ - const int hue_corr = (uvd->vpic.hue - 0x8000) >> 10; /* -32..+31 */ - const int hue2_corr = (hue_correction - 128) / 4; /* -32..+31 */ - const int ccm = 128; /* Color correction median - see below */ - int i, u, v, rw, data_w=0, data_h=0, color_corr; - static unsigned char lineBuffer[640*3]; - - color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ - RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1); - - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - /* The header tells us what sort of data is in this frame */ - switch (frame->header) { - /* - * Uncompressed modes (that are easy to decode). - */ - case 0x0308: - data_w = 640; - data_h = 480; - break; - case 0x0208: - data_w = 320; - data_h = 240; - break; - case 0x020A: - data_w = 160; - data_h = 120; - break; - /* - * Compressed modes (ViCE - that I don't know how to decode). - */ - case 0x0328: /* 640x480, best quality compression */ - case 0x0368: /* 640x480, best frame rate compression */ - case 0x0228: /* 320x240, best quality compression */ - case 0x0268: /* 320x240, best frame rate compression */ - case 0x02CA: /* 160x120, best quality compression */ - case 0x02EA: /* 160x120, best frame rate compression */ - /* Do nothing with this - not supported */ - err("Unsupported mode $%04lx", frame->header); - return scan_NextFrame; - default: - /* Catch unknown headers, may help in learning new headers */ - err("Strange frame->header=$%08lx", frame->header); - return scan_NextFrame; - } - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Note that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 1) >= data_h) { - if (uvd->debug >= 3) - info("Reached line %d. (frame is done)", frame->curline); - return scan_NextFrame; - } - - /* Make sure there's enough data for the entire line */ - len = 3 * data_w; /* */ - assert(len <= sizeof(lineBuffer)); - - /* Make sure there's enough data for the entire line */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck one line out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - data = lineBuffer; - color = data + data_w; /* Point to where color planes begin */ - - /* Bottom-to-top scanning */ - rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1; - RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1); - - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { - int y, rv, gv, bv; /* RGB components */ - - if (i < data_w) { - y = data[i]; /* Luminosity is the first line */ - - /* Apply static color correction */ - u = color[i*2] + hue_corr; - v = color[i*2 + 1] + hue2_corr; - - /* Apply color correction */ - if (color_corr != 0) { - /* Magnify up to 2 times, reduce down to zero saturation */ - u = 128 + ((ccm + color_corr) * (u - 128)) / ccm; - v = 128 + ((ccm + color_corr) * (v - 128)) / ccm; - } - } else - y = 0, u = v = 128; - - YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); - RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */ - } - frame->deinterlace = Deinterlace_FillEvenLines; - - /* - * Account for number of bytes that we wrote into output V4L frame. - * We do it here, after we are done with the scanline, because we - * may fill more than one output scanline if we do vertical - * enlargement. - */ - frame->curline += 2; - *pcopylen += 2 * v4l_linesize; - - if (frame->curline >= VIDEOSIZE_Y(frame->request)) { - if (uvd->debug >= 3) { - info("All requested lines (%ld.) done.", - VIDEOSIZE_Y(frame->request)); - } - return scan_NextFrame; - } else - return scan_Continue; -} - -/* - * ibmcam_model4_128x96_parse_lines() - * - * This decoder is for one strange data format that is produced by Model 4 - * camera only in 128x96 mode. This is RGB format and here is its description. - * First of all, this is non-interlaced stream, meaning that all scan lines - * are present in the datastream. There are 96 consecutive blocks of data - * that describe all 96 lines of the image. Each block is 5*128 bytes long - * and carries R, G, B components. The format of the block is shown in the - * code below. First 128*2 bytes are interleaved R and G components. Then - * we have a gap (junk data) 64 bytes long. Then follow B and something - * else, also interleaved (this makes another 128*2 bytes). After that - * probably another 64 bytes of junk follow. - * - * History: - * 10-Feb-2001 Created. - */ -static enum ParseState ibmcam_model4_128x96_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - const unsigned char *data_rv, *data_gv, *data_bv; - unsigned int len; - int i, v4l_linesize; /* V4L line offset */ - const int data_w=128, data_h=96; - static unsigned char lineBuffer[128*5]; - - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Note that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 1) >= data_h) { - if (uvd->debug >= 3) - info("Reached line %d. (frame is done)", frame->curline); - return scan_NextFrame; - } - - /* - * RGRGRG .... RGRG_____________B?B?B? ... B?B?____________ - * <---- 128*2 ---><---- 64 ---><--- 128*2 ---><--- 64 ---> - */ - - /* Make sure there's enough data for the entire line */ - len = 5 * data_w; - assert(len <= sizeof(lineBuffer)); - - /* Make sure there's enough data for the entire line */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck one line out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - data_rv = lineBuffer; - data_gv = lineBuffer + 1; - data_bv = lineBuffer + data_w*2 + data_w/2; - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { - int rv, gv, bv; /* RGB components */ - if (i < data_w) { - const int j = i * 2; - gv = data_rv[j]; - rv = data_gv[j]; - bv = data_bv[j]; - if (flags & FLAGS_MONOCHROME) { - unsigned long y; - y = rv + gv + bv; - y /= 3; - if (y > 0xFF) - y = 0xFF; - rv = gv = bv = (unsigned char) y; - } - } else { - rv = gv = bv = 0; - } - RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); - } - frame->deinterlace = Deinterlace_None; - frame->curline++; - *pcopylen += v4l_linesize; - - if (frame->curline >= VIDEOSIZE_Y(frame->request)) { - if (uvd->debug >= 3) { - info("All requested lines (%ld.) done.", - VIDEOSIZE_Y(frame->request)); - } - return scan_NextFrame; - } else - return scan_Continue; -} - -/* - * ibmcam_ProcessIsocData() - * - * Generic routine to parse the ring queue data. It employs either - * ibmcam_find_header() or ibmcam_parse_lines() to do most - * of work. - * - * History: - * 1/21/00 Created. - */ -static void ibmcam_ProcessIsocData(struct uvd *uvd, - struct usbvideo_frame *frame) -{ - enum ParseState newstate; - long copylen = 0; - int mod = IBMCAM_T(uvd)->camera_model; - - while (1) { - newstate = scan_Out; - if (RingQueue_GetLength(&uvd->dp) > 0) { - if (frame->scanstate == ScanState_Scanning) { - newstate = ibmcam_find_header(uvd); - } else if (frame->scanstate == ScanState_Lines) { - if ((mod == IBMCAM_MODEL_2) && - ((uvd->videosize == VIDEOSIZE_352x288) || - (uvd->videosize == VIDEOSIZE_320x240) || - (uvd->videosize == VIDEOSIZE_352x240))) - { - newstate = ibmcam_model2_320x240_parse_lines( - uvd, frame, ©len); - } else if (mod == IBMCAM_MODEL_4) { - /* - * Model 4 cameras (IBM NetCamera) use Model 2 decoder (RGB) - * for 320x240 and above; 160x120 and 176x144 uses Model 1 - * decoder (YUV), and 128x96 mode uses ??? - */ - if ((uvd->videosize == VIDEOSIZE_352x288) || - (uvd->videosize == VIDEOSIZE_320x240) || - (uvd->videosize == VIDEOSIZE_352x240)) - { - newstate = ibmcam_model2_320x240_parse_lines(uvd, frame, ©len); - } else if (uvd->videosize == VIDEOSIZE_128x96) { - newstate = ibmcam_model4_128x96_parse_lines(uvd, frame, ©len); - } else { - newstate = ibmcam_parse_lines(uvd, frame, ©len); - } - } else if (mod == IBMCAM_MODEL_3) { - newstate = ibmcam_model3_parse_lines(uvd, frame, ©len); - } else { - newstate = ibmcam_parse_lines(uvd, frame, ©len); - } - } - } - if (newstate == scan_Continue) - continue; - else if ((newstate == scan_NextFrame) || (newstate == scan_Out)) - break; - else - return; /* scan_EndParse */ - } - - if (newstate == scan_NextFrame) { - frame->frameState = FrameState_Done; - uvd->curframe = -1; - uvd->stats.frame_num++; - if ((mod == IBMCAM_MODEL_2) || (mod == IBMCAM_MODEL_4)) { - /* Need software contrast adjustment for those cameras */ - frame->flags |= USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST; - } - } - - /* Update the frame's uncompressed length. */ - frame->seqRead_Length += copylen; - -#if 0 - { - static unsigned char j=0; - memset(frame->data, j++, uvd->max_frame_size); - frame->frameState = FrameState_Ready; - } -#endif -} - -/* - * ibmcam_veio() - * - * History: - * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. - */ -static int ibmcam_veio( - struct uvd *uvd, - unsigned char req, - unsigned short value, - unsigned short index) -{ - static const char proc[] = "ibmcam_veio"; - unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */; - int i; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return 0; - - if (req == 1) { - i = usb_control_msg( - uvd->dev, - usb_rcvctrlpipe(uvd->dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - value, - index, - cp, - sizeof(cp), - 1000); -#if 0 - info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " - "(req=$%02x val=$%04x ind=$%04x)", - cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], - req, value, index); -#endif - } else { - i = usb_control_msg( - uvd->dev, - usb_sndctrlpipe(uvd->dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - value, - index, - NULL, - 0, - 1000); - } - if (i < 0) { - err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.", - proc, i); - uvd->last_error = i; - } - return i; -} - -/* - * ibmcam_calculate_fps() - * - * This procedure roughly calculates the real frame rate based - * on FPS code (framerate=NNN option). Actual FPS differs - * slightly depending on lighting conditions, so that actual frame - * rate is determined by the camera. Since I don't know how to ask - * the camera what FPS is now I have to use the FPS code instead. - * - * The FPS code is in range [0..6], 0 is slowest, 6 is fastest. - * Corresponding real FPS should be in range [3..30] frames per second. - * The conversion formula is obvious: - * - * real_fps = 3 + (fps_code * 4.5) - * - * History: - * 1/18/00 Created. - */ -static int ibmcam_calculate_fps(struct uvd *uvd) -{ - return 3 + framerate*4 + framerate/2; -} - -/* - * ibmcam_send_FF_04_02() - * - * This procedure sends magic 3-command prefix to the camera. - * The purpose of this prefix is not known. - * - * History: - * 1/2/00 Created. - */ -static void ibmcam_send_FF_04_02(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x00FF, 0x0127); - ibmcam_veio(uvd, 0, 0x0004, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); -} - -static void ibmcam_send_00_04_06(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x0004, 0x0124); - ibmcam_veio(uvd, 0, 0x0006, 0x0124); -} - -static void ibmcam_send_x_00(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); -} - -static void ibmcam_send_x_00_05(struct uvd *uvd, unsigned short x) -{ - ibmcam_send_x_00(uvd, x); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); -} - -static void ibmcam_send_x_00_05_02(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); -} - -static void ibmcam_send_x_01_00_05(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0001, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); -} - -static void ibmcam_send_x_00_05_02_01(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0124); -} - -static void ibmcam_send_x_00_05_02_08_01(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0124); -} - -static void ibmcam_Packet_Format1(struct uvd *uvd, unsigned char fkey, unsigned char val) -{ - ibmcam_send_x_01_00_05(uvd, unknown_88); - ibmcam_send_x_00_05(uvd, fkey); - ibmcam_send_x_00_05_02_08_01(uvd, val); - ibmcam_send_x_00_05(uvd, unknown_88); - ibmcam_send_x_00_05_02_01(uvd, fkey); - ibmcam_send_x_00_05(uvd, unknown_89); - ibmcam_send_x_00(uvd, fkey); - ibmcam_send_00_04_06(uvd); - ibmcam_veio(uvd, 1, 0x0000, 0x0126); - ibmcam_send_FF_04_02(uvd); -} - -static void ibmcam_PacketFormat2(struct uvd *uvd, unsigned char fkey, unsigned char val) -{ - ibmcam_send_x_01_00_05 (uvd, unknown_88); - ibmcam_send_x_00_05 (uvd, fkey); - ibmcam_send_x_00_05_02 (uvd, val); -} - -static void ibmcam_model2_Packet2(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x00ff, 0x012d); - ibmcam_veio(uvd, 0, 0xfea3, 0x0124); -} - -static void ibmcam_model2_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2) -{ - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x00ff, 0x012e); - ibmcam_veio(uvd, 0, v1, 0x012f); - ibmcam_veio(uvd, 0, 0x00ff, 0x0130); - ibmcam_veio(uvd, 0, 0xc719, 0x0124); - ibmcam_veio(uvd, 0, v2, 0x0127); - - ibmcam_model2_Packet2(uvd); -} - -/* - * ibmcam_model3_Packet1() - * - * 00_0078_012d - * 00_0097_012f - * 00_d141_0124 - * 00_0096_0127 - * 00_fea8_0124 -*/ -static void ibmcam_model3_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2) -{ - ibmcam_veio(uvd, 0, 0x0078, 0x012d); - ibmcam_veio(uvd, 0, v1, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, v2, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); -} - -static void ibmcam_model4_BrightnessPacket(struct uvd *uvd, int i) -{ - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0026, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, i, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0038, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); -} - -/* - * ibmcam_adjust_contrast() - * - * The contrast value changes from 0 (high contrast) to 15 (low contrast). - * This is in reverse to usual order of things (such as TV controls), so - * we reverse it again here. - * - * TODO: we probably don't need to send the setup 5 times... - * - * History: - * 1/2/00 Created. - */ -static void ibmcam_adjust_contrast(struct uvd *uvd) -{ - unsigned char a_contrast = uvd->vpic.contrast >> 12; - unsigned char new_contrast; - - if (a_contrast >= 16) - a_contrast = 15; - new_contrast = 15 - a_contrast; - if (new_contrast == uvd->vpic_old.contrast) - return; - uvd->vpic_old.contrast = new_contrast; - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - const int ntries = 5; - int i; - for (i=0; i < ntries; i++) { - ibmcam_Packet_Format1(uvd, contrast_14, new_contrast); - ibmcam_send_FF_04_02(uvd); - } - break; - } - case IBMCAM_MODEL_2: - case IBMCAM_MODEL_4: - /* Models 2, 4 do not have this control; implemented in software. */ - break; - case IBMCAM_MODEL_3: - { /* Preset hardware values */ - static const struct { - unsigned short cv1; - unsigned short cv2; - unsigned short cv3; - } cv[7] = { - { 0x05, 0x05, 0x0f }, /* Minimum */ - { 0x04, 0x04, 0x16 }, - { 0x02, 0x03, 0x16 }, - { 0x02, 0x08, 0x16 }, - { 0x01, 0x0c, 0x16 }, - { 0x01, 0x0e, 0x16 }, - { 0x01, 0x10, 0x16 } /* Maximum */ - }; - int i = a_contrast / 2; - RESTRICT_TO_RANGE(i, 0, 6); - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x0067, cv[i].cv1); - ibmcam_model3_Packet1(uvd, 0x005b, cv[i].cv2); - ibmcam_model3_Packet1(uvd, 0x005c, cv[i].cv3); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - break; - } - default: - break; - } -} - -/* - * ibmcam_change_lighting_conditions() - * - * Camera model 1: - * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low. - * - * Camera model 2: - * We have 16 levels of lighting, 0 for bright light and up to 15 for - * low light. But values above 5 or so are useless because camera is - * not really capable to produce anything worth viewing at such light. - * This setting may be altered only in certain camera state. - * - * Low lighting forces slower FPS. Lighting is set as a module parameter. - * - * History: - * 1/5/00 Created. - * 2/20/00 Added support for Model 2 cameras. - */ -static void ibmcam_change_lighting_conditions(struct uvd *uvd) -{ - static const char proc[] = "ibmcam_change_lighting_conditions"; - - if (debug > 0) - info("%s: Set lighting to %hu.", proc, lighting); - - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - const int ntries = 5; - int i; - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, light_27, (unsigned short) lighting); - break; - } - case IBMCAM_MODEL_2: -#if 0 - /* - * This command apparently requires camera to be stopped. My - * experiments showed that it -is- possible to alter the lighting - * conditions setting "on the fly", but why bother? This setting does - * not work reliably in all cases, so I decided simply to leave the - * setting where Xirlink put it - in the camera setup phase. This code - * is commented out because it does not work at -any- moment, so its - * presence makes no sense. You may use it for experiments. - */ - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop camera */ - ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Start camera */ -#endif - break; - case IBMCAM_MODEL_3: - case IBMCAM_MODEL_4: - default: - break; - } -} - -/* - * ibmcam_set_sharpness() - * - * Cameras model 1 have internal smoothing feature. It is controlled by value in - * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess). - * Recommended value is 4. Cameras model 2 do not have this feature at all. - */ -static void ibmcam_set_sharpness(struct uvd *uvd) -{ - static const char proc[] = "ibmcam_set_sharpness"; - - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a }; - unsigned short i, sv; - - RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); - if (debug > 0) - info("%s: Set sharpness to %hu.", proc, sharpness); - - sv = sa[sharpness - SHARPNESS_MIN]; - for (i=0; i < 2; i++) { - ibmcam_send_x_01_00_05 (uvd, unknown_88); - ibmcam_send_x_00_05 (uvd, sharp_13); - ibmcam_send_x_00_05_02 (uvd, sv); - } - break; - } - case IBMCAM_MODEL_2: - case IBMCAM_MODEL_4: - /* Models 2, 4 do not have this control */ - break; - case IBMCAM_MODEL_3: - { /* - * "Use a table of magic numbers. - * This setting doesn't really change much. - * But that's how Windows does it." - */ - static const struct { - unsigned short sv1; - unsigned short sv2; - unsigned short sv3; - unsigned short sv4; - } sv[7] = { - { 0x00, 0x00, 0x05, 0x14 }, /* Smoothest */ - { 0x01, 0x04, 0x05, 0x14 }, - { 0x02, 0x04, 0x05, 0x14 }, - { 0x03, 0x04, 0x05, 0x14 }, - { 0x03, 0x05, 0x05, 0x14 }, - { 0x03, 0x06, 0x05, 0x14 }, - { 0x03, 0x07, 0x05, 0x14 } /* Sharpest */ - }; - RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); - RESTRICT_TO_RANGE(sharpness, 0, 6); - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x0060, sv[sharpness].sv1); - ibmcam_model3_Packet1(uvd, 0x0061, sv[sharpness].sv2); - ibmcam_model3_Packet1(uvd, 0x0062, sv[sharpness].sv3); - ibmcam_model3_Packet1(uvd, 0x0063, sv[sharpness].sv4); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_veio(uvd, 0, 0x0001, 0x0113); - break; - } - default: - break; - } -} - -/* - * ibmcam_set_brightness() - * - * This procedure changes brightness of the picture. - */ -static void ibmcam_set_brightness(struct uvd *uvd) -{ - static const char proc[] = "ibmcam_set_brightness"; - static const unsigned short n = 1; - - if (debug > 0) - info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness); - - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - unsigned short i, j, bv[3]; - bv[0] = bv[1] = bv[2] = uvd->vpic.brightness >> 10; - if (bv[0] == (uvd->vpic_old.brightness >> 10)) - return; - uvd->vpic_old.brightness = bv[0]; - for (j=0; j < 3; j++) - for (i=0; i < n; i++) - ibmcam_Packet_Format1(uvd, bright_3x[j], bv[j]); - break; - } - case IBMCAM_MODEL_2: - { - unsigned short i, j; - i = uvd->vpic.brightness >> 12; /* 0 .. 15 */ - j = 0x60 + i * ((0xee - 0x60) / 16); /* 0x60 .. 0xee or so */ - if (uvd->vpic_old.brightness == j) - break; - uvd->vpic_old.brightness = j; - ibmcam_model2_Packet1(uvd, mod2_brightness, j); - break; - } - case IBMCAM_MODEL_3: - { - /* Model 3: Brightness range 'i' in [0x0C..0x3F] */ - unsigned short i = - 0x0C + (uvd->vpic.brightness / (0xFFFF / (0x3F - 0x0C + 1))); - RESTRICT_TO_RANGE(i, 0x0C, 0x3F); - if (uvd->vpic_old.brightness == i) - break; - uvd->vpic_old.brightness = i; - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x0036, i); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_veio(uvd, 0, 0x0001, 0x0113); - break; - } - case IBMCAM_MODEL_4: - { - /* Model 4: Brightness range 'i' in [0x04..0xb4] */ - unsigned short i = 0x04 + (uvd->vpic.brightness / (0xFFFF / (0xb4 - 0x04 + 1))); - RESTRICT_TO_RANGE(i, 0x04, 0xb4); - if (uvd->vpic_old.brightness == i) - break; - uvd->vpic_old.brightness = i; - ibmcam_model4_BrightnessPacket(uvd, i); - break; - } - default: - break; - } -} - -static void ibmcam_set_hue(struct uvd *uvd) -{ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_2: - { - unsigned short hue = uvd->vpic.hue >> 9; /* 0 .. 7F */ - if (uvd->vpic_old.hue == hue) - return; - uvd->vpic_old.hue = hue; - ibmcam_model2_Packet1(uvd, mod2_hue, hue); - /* ibmcam_model2_Packet1(uvd, mod2_saturation, sat); */ - break; - } - case IBMCAM_MODEL_3: - { -#if 0 /* This seems not to work. No problem, will fix programmatically */ - unsigned short hue = 0x05 + (uvd->vpic.hue / (0xFFFF / (0x37 - 0x05 + 1))); - RESTRICT_TO_RANGE(hue, 0x05, 0x37); - if (uvd->vpic_old.hue == hue) - return; - uvd->vpic_old.hue = hue; - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x007e, hue); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_veio(uvd, 0, 0x0001, 0x0113); -#endif - break; - } - case IBMCAM_MODEL_4: - { - unsigned short r_gain, g_gain, b_gain, hue; - - /* - * I am not sure r/g/b_gain variables exactly control gain - * of those channels. Most likely they subtly change some - * very internal image processing settings in the camera. - * In any case, here is what they do, and feel free to tweak: - * - * r_gain: seriously affects red gain - * g_gain: seriously affects green gain - * b_gain: seriously affects blue gain - * hue: changes average color from violet (0) to red (0xFF) - * - * These settings are preset for a decent white balance in - * 320x240, 352x288 modes. Low-res modes exhibit higher contrast - * and therefore may need different values here. - */ - hue = 20 + (uvd->vpic.hue >> 9); - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - r_gain = 90; - g_gain = 166; - b_gain = 175; - break; - case VIDEOSIZE_160x120: - r_gain = 70; - g_gain = 166; - b_gain = 185; - break; - case VIDEOSIZE_176x144: - r_gain = 160; - g_gain = 175; - b_gain = 185; - break; - default: - r_gain = 120; - g_gain = 166; - b_gain = 175; - break; - } - RESTRICT_TO_RANGE(hue, 1, 0x7f); - - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, g_gain, 0x0127); /* Green gain */ - ibmcam_veio(uvd, 0, r_gain, 0x012e); /* Red gain */ - ibmcam_veio(uvd, 0, b_gain, 0x0130); /* Blue gain */ - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, hue, 0x012d); /* Hue */ - ibmcam_veio(uvd, 0, 0xf545, 0x0124); - break; - } - default: - break; - } -} - -/* - * ibmcam_adjust_picture() - * - * This procedure gets called from V4L interface to update picture settings. - * Here we change brightness and contrast. - */ -static void ibmcam_adjust_picture(struct uvd *uvd) -{ - ibmcam_adjust_contrast(uvd); - ibmcam_set_brightness(uvd); - ibmcam_set_hue(uvd); -} - -static int ibmcam_model1_setup(struct uvd *uvd) -{ - const int ntries = 5; - int i; - - ibmcam_veio(uvd, 1, 0x00, 0x0128); - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x81, 0x0100); /* LED Off */ - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ - ibmcam_veio(uvd, 0, 0x01, 0x0108); - - ibmcam_veio(uvd, 0, 0x03, 0x0112); - ibmcam_veio(uvd, 1, 0x00, 0x0115); - ibmcam_veio(uvd, 0, 0x06, 0x0115); - ibmcam_veio(uvd, 1, 0x00, 0x0116); - ibmcam_veio(uvd, 0, 0x44, 0x0116); - ibmcam_veio(uvd, 1, 0x00, 0x0116); - ibmcam_veio(uvd, 0, 0x40, 0x0116); - ibmcam_veio(uvd, 1, 0x00, 0x0115); - ibmcam_veio(uvd, 0, 0x0e, 0x0115); - ibmcam_veio(uvd, 0, 0x19, 0x012c); - - ibmcam_Packet_Format1(uvd, 0x00, 0x1e); - ibmcam_Packet_Format1(uvd, 0x39, 0x0d); - ibmcam_Packet_Format1(uvd, 0x39, 0x09); - ibmcam_Packet_Format1(uvd, 0x3b, 0x00); - ibmcam_Packet_Format1(uvd, 0x28, 0x22); - ibmcam_Packet_Format1(uvd, light_27, 0); - ibmcam_Packet_Format1(uvd, 0x2b, 0x1f); - ibmcam_Packet_Format1(uvd, 0x39, 0x08); - - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x2c, 0x00); - - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x30, 0x14); - - ibmcam_PacketFormat2(uvd, 0x39, 0x02); - ibmcam_PacketFormat2(uvd, 0x01, 0xe1); - ibmcam_PacketFormat2(uvd, 0x02, 0xcd); - ibmcam_PacketFormat2(uvd, 0x03, 0xcd); - ibmcam_PacketFormat2(uvd, 0x04, 0xfa); - ibmcam_PacketFormat2(uvd, 0x3f, 0xff); - ibmcam_PacketFormat2(uvd, 0x39, 0x00); - - ibmcam_PacketFormat2(uvd, 0x39, 0x02); - ibmcam_PacketFormat2(uvd, 0x0a, 0x37); - ibmcam_PacketFormat2(uvd, 0x0b, 0xb8); - ibmcam_PacketFormat2(uvd, 0x0c, 0xf3); - ibmcam_PacketFormat2(uvd, 0x0d, 0xe3); - ibmcam_PacketFormat2(uvd, 0x0e, 0x0d); - ibmcam_PacketFormat2(uvd, 0x0f, 0xf2); - ibmcam_PacketFormat2(uvd, 0x10, 0xd5); - ibmcam_PacketFormat2(uvd, 0x11, 0xba); - ibmcam_PacketFormat2(uvd, 0x12, 0x53); - ibmcam_PacketFormat2(uvd, 0x3f, 0xff); - ibmcam_PacketFormat2(uvd, 0x39, 0x00); - - ibmcam_PacketFormat2(uvd, 0x39, 0x02); - ibmcam_PacketFormat2(uvd, 0x16, 0x00); - ibmcam_PacketFormat2(uvd, 0x17, 0x28); - ibmcam_PacketFormat2(uvd, 0x18, 0x7d); - ibmcam_PacketFormat2(uvd, 0x19, 0xbe); - ibmcam_PacketFormat2(uvd, 0x3f, 0xff); - ibmcam_PacketFormat2(uvd, 0x39, 0x00); - - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x00, 0x18); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x13, 0x18); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x14, 0x06); - - /* This is default brightness */ - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x31, 0x37); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x32, 0x46); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x33, 0x55); - - ibmcam_Packet_Format1(uvd, 0x2e, 0x04); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x2d, 0x04); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x29, 0x80); - ibmcam_Packet_Format1(uvd, 0x2c, 0x01); - ibmcam_Packet_Format1(uvd, 0x30, 0x17); - ibmcam_Packet_Format1(uvd, 0x39, 0x08); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x34, 0x00); - - ibmcam_veio(uvd, 0, 0x00, 0x0101); - ibmcam_veio(uvd, 0, 0x00, 0x010a); - - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - ibmcam_veio(uvd, 0, 0x80, 0x0103); - ibmcam_veio(uvd, 0, 0x60, 0x0105); - ibmcam_veio(uvd, 0, 0x0c, 0x010b); - ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x0b, 0x011d); - ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x00, 0x0129); - break; - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0xb0, 0x0103); - ibmcam_veio(uvd, 0, 0x8f, 0x0105); - ibmcam_veio(uvd, 0, 0x06, 0x010b); - ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x0d, 0x011d); - ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x03, 0x0129); - break; - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0xb0, 0x0103); - ibmcam_veio(uvd, 0, 0x90, 0x0105); - ibmcam_veio(uvd, 0, 0x02, 0x010b); - ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x05, 0x011d); - ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x00, 0x0129); - break; - } - - ibmcam_veio(uvd, 0, 0xff, 0x012b); - - /* This is another brightness - don't know why */ - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x31, 0xc3); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x32, 0xd2); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x33, 0xe1); - - /* Default contrast */ - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, contrast_14, 0x0a); - - /* Default sharpness */ - for (i=0; i < 2; i++) - ibmcam_PacketFormat2(uvd, sharp_13, 0x1a); /* Level 4 FIXME */ - - /* Default lighting conditions */ - ibmcam_Packet_Format1(uvd, light_27, lighting); /* 0=Bright 2=Low */ - - /* Assorted init */ - - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - ibmcam_Packet_Format1(uvd, 0x2b, 0x1e); - ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x36, 0x0102); - ibmcam_veio(uvd, 0, 0x1a, 0x0104); - ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x2b, 0x011c); - ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ -#if 0 - ibmcam_veio(uvd, 0, 0x00, 0x0106); - ibmcam_veio(uvd, 0, 0x38, 0x0107); -#else - ibmcam_veio(uvd, 0, 0x02, 0x0106); - ibmcam_veio(uvd, 0, 0x2a, 0x0107); -#endif - break; - case VIDEOSIZE_176x144: - ibmcam_Packet_Format1(uvd, 0x2b, 0x1e); - ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x04, 0x0102); - ibmcam_veio(uvd, 0, 0x02, 0x0104); - ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x2b, 0x011c); - ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x01, 0x0106); - ibmcam_veio(uvd, 0, 0xca, 0x0107); - break; - case VIDEOSIZE_352x288: - ibmcam_Packet_Format1(uvd, 0x2b, 0x1f); - ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x08, 0x0102); - ibmcam_veio(uvd, 0, 0x01, 0x0104); - ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x2f, 0x011c); - ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x03, 0x0106); - ibmcam_veio(uvd, 0, 0xf6, 0x0107); - break; - } - return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT); -} - -static int ibmcam_model2_setup(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x0000, 0x0100); /* LED on */ - ibmcam_veio(uvd, 1, 0x0000, 0x0116); - ibmcam_veio(uvd, 0, 0x0060, 0x0116); - ibmcam_veio(uvd, 0, 0x0002, 0x0112); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0008, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x0024, 0x0105); /* 176x144, 352x288 */ - ibmcam_veio(uvd, 0, 0x00b9, 0x010a); /* Unique to this mode */ - ibmcam_veio(uvd, 0, 0x0038, 0x0119); /* Unique to this mode */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x0090, 0x0107); /* Unique to every mode*/ - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0028, 0x0103); /* Unique to this mode */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x001e, 0x0105); /* 320x240, 352x240 */ - ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x0098, 0x0107); /* Unique to every mode*/ - break; - case VIDEOSIZE_352x240: - ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x001e, 0x0105); /* 320x240, 352x240 */ - ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x00da, 0x0107); /* Unique to every mode*/ - break; - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x0024, 0x0105); /* 176x144, 352x288 */ - ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x00fe, 0x0107); /* Unique to every mode*/ - break; - } - return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT); -} - -/* - * ibmcam_model1_setup_after_video_if() - * - * This code adds finishing touches to the video data interface. - * Here we configure the frame rate and turn on the LED. - */ -static void ibmcam_model1_setup_after_video_if(struct uvd *uvd) -{ - unsigned short internal_frame_rate; - - RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX); - internal_frame_rate = FRAMERATE_MAX - framerate; /* 0=Fast 6=Slow */ - ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ - ibmcam_veio(uvd, 0, internal_frame_rate, 0x0111); - ibmcam_veio(uvd, 0, 0x01, 0x0114); - ibmcam_veio(uvd, 0, 0xc0, 0x010c); -} - -static void ibmcam_model2_setup_after_video_if(struct uvd *uvd) -{ - unsigned short setup_model2_rg2, setup_model2_sat, setup_model2_yb; - - ibmcam_veio(uvd, 0, 0x0000, 0x0100); /* LED on */ - - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0x0050, 0x0111); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - break; - case VIDEOSIZE_320x240: - case VIDEOSIZE_352x240: - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0x0040, 0x0111); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - break; - } - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - - /* - * Hardware settings, may affect CMOS sensor; not user controls! - * ------------------------------------------------------------- - * 0x0004: no effect - * 0x0006: hardware effect - * 0x0008: no effect - * 0x000a: stops video stream, probably important h/w setting - * 0x000c: changes color in hardware manner (not user setting) - * 0x0012: changes number of colors (does not affect speed) - * 0x002a: no effect - * 0x002c: hardware setting (related to scan lines) - * 0x002e: stops video stream, probably important h/w setting - */ - ibmcam_model2_Packet1(uvd, 0x000a, 0x005c); - ibmcam_model2_Packet1(uvd, 0x0004, 0x0000); - ibmcam_model2_Packet1(uvd, 0x0006, 0x00fb); - ibmcam_model2_Packet1(uvd, 0x0008, 0x0000); - ibmcam_model2_Packet1(uvd, 0x000c, 0x0009); - ibmcam_model2_Packet1(uvd, 0x0012, 0x000a); - ibmcam_model2_Packet1(uvd, 0x002a, 0x0000); - ibmcam_model2_Packet1(uvd, 0x002c, 0x0000); - ibmcam_model2_Packet1(uvd, 0x002e, 0x0008); - - /* - * Function 0x0030 pops up all over the place. Apparently - * it is a hardware control register, with every bit assigned to - * do something. - */ - ibmcam_model2_Packet1(uvd, 0x0030, 0x0000); - - /* - * Magic control of CMOS sensor. Only lower values like - * 0-3 work, and picture shifts left or right. Don't change. - */ - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_model2_Packet1(uvd, 0x0014, 0x0002); - ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */ - break; - case VIDEOSIZE_320x240: - ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); - ibmcam_model2_Packet1(uvd, 0x0016, 0x0005); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Another hardware setting */ - break; - case VIDEOSIZE_352x240: - /* This mode doesn't work as Windows programs it; changed to work */ - ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); /* Windows sets this to 8 */ - ibmcam_model2_Packet1(uvd, 0x0016, 0x0003); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Windows sets this to 0x0045 */ - break; - case VIDEOSIZE_352x288: - ibmcam_model2_Packet1(uvd, 0x0014, 0x0003); - ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */ - break; - } - - ibmcam_model2_Packet1(uvd, mod2_brightness, 0x005a); - - /* - * We have our own frame rate setting varying from 0 (slowest) to 6 (fastest). - * The camera model 2 allows frame rate in range [0..0x1F] where 0 is also the - * slowest setting. However for all practical reasons high settings make no - * sense because USB is not fast enough to support high FPS. Be aware that - * the picture datastream will be severely disrupted if you ask for - * frame rate faster than allowed for the video size - see below: - * - * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz): - * ----------------------------------------------------------------- - * 176x144: [6..31] - * 320x240: [8..31] - * 352x240: [10..31] - * 352x288: [16..31] I have to raise lower threshold for stability... - * - * As usual, slower FPS provides better sensitivity. - */ - { - short hw_fps=31, i_framerate; - - RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX); - i_framerate = FRAMERATE_MAX - framerate + FRAMERATE_MIN; - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - hw_fps = 6 + i_framerate*4; - break; - case VIDEOSIZE_320x240: - hw_fps = 8 + i_framerate*3; - break; - case VIDEOSIZE_352x240: - hw_fps = 10 + i_framerate*2; - break; - case VIDEOSIZE_352x288: - hw_fps = 28 + i_framerate/2; - break; - } - if (uvd->debug > 0) - info("Framerate (hardware): %hd.", hw_fps); - RESTRICT_TO_RANGE(hw_fps, 0, 31); - ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps); - } - - /* - * This setting does not visibly affect pictures; left it here - * because it was present in Windows USB data stream. This function - * does not allow arbitrary values and apparently is a bit mask, to - * be activated only at appropriate time. Don't change it randomly! - */ - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_model2_Packet1(uvd, 0x0026, 0x00c2); - break; - case VIDEOSIZE_320x240: - ibmcam_model2_Packet1(uvd, 0x0026, 0x0044); - break; - case VIDEOSIZE_352x240: - ibmcam_model2_Packet1(uvd, 0x0026, 0x0046); - break; - case VIDEOSIZE_352x288: - ibmcam_model2_Packet1(uvd, 0x0026, 0x0048); - break; - } - - ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting); - - if (init_model2_rg2 >= 0) { - RESTRICT_TO_RANGE(init_model2_rg2, 0, 255); - setup_model2_rg2 = init_model2_rg2; - } else - setup_model2_rg2 = 0x002f; - - if (init_model2_sat >= 0) { - RESTRICT_TO_RANGE(init_model2_sat, 0, 255); - setup_model2_sat = init_model2_sat; - } else - setup_model2_sat = 0x0034; - - if (init_model2_yb >= 0) { - RESTRICT_TO_RANGE(init_model2_yb, 0, 255); - setup_model2_yb = init_model2_yb; - } else - setup_model2_yb = 0x00a0; - - ibmcam_model2_Packet1(uvd, mod2_color_balance_rg2, setup_model2_rg2); - ibmcam_model2_Packet1(uvd, mod2_saturation, setup_model2_sat); - ibmcam_model2_Packet1(uvd, mod2_color_balance_yb, setup_model2_yb); - ibmcam_model2_Packet1(uvd, mod2_hue, uvd->vpic.hue >> 9); /* 0 .. 7F */; - - /* Hardware control command */ - ibmcam_model2_Packet1(uvd, 0x0030, 0x0004); - - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go camera, go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); -} - -static void ibmcam_model4_setup_after_video_if(struct uvd *uvd) -{ - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0070, 0x0119); - ibmcam_veio(uvd, 0, 0x00d2, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x005e, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x0039, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x0028, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x001e, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x000a, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005a, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0043, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00eb, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x0031, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x012d); - ibmcam_veio(uvd, 0, 0x0078, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_160x120: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0038, 0x0119); - ibmcam_veio(uvd, 0, 0x00d8, 0x0107); - ibmcam_veio(uvd, 0, 0x0002, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x00b9, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x0028, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x001e, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x000b, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005a, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0043, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00c7, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0025, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0048, 0x0127); - ibmcam_veio(uvd, 0, 0x0035, 0x012e); - ibmcam_veio(uvd, 0, 0x00d0, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0048, 0x012d); - ibmcam_veio(uvd, 0, 0x0090, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0038, 0x0119); - ibmcam_veio(uvd, 0, 0x00d6, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x0018, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x00b9, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x002c, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x0024, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0007, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0001, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005e, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0049, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00c7, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0028, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x002a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x012d); - ibmcam_veio(uvd, 0, 0x006d, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0070, 0x0119); - ibmcam_veio(uvd, 0, 0x00d2, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x005e, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x0039, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x0028, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x001e, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x000a, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005a, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0043, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00eb, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x0031, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x012d); - ibmcam_veio(uvd, 0, 0x0078, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0070, 0x0119); - ibmcam_veio(uvd, 0, 0x00f2, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x008c, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x0039, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x002c, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x0024, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0006, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0002, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005e, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0049, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00cf, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x0025, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x012d); - ibmcam_veio(uvd, 0, 0x0048, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - } - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); -} - -static void ibmcam_model3_setup_after_video_if(struct uvd *uvd) -{ - int i; - /* - * 01.01.08 - Added for RCA video in support -LO - * This struct is used to init the Model3 cam to use the RCA video in port - * instead of the CCD sensor. - */ - static const struct struct_initData initData[] = { - {0, 0x0000, 0x010c}, - {0, 0x0006, 0x012c}, - {0, 0x0078, 0x012d}, - {0, 0x0046, 0x012f}, - {0, 0xd141, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfea8, 0x0124}, - {1, 0x0000, 0x0116}, - {0, 0x0064, 0x0116}, - {1, 0x0000, 0x0115}, - {0, 0x0003, 0x0115}, - {0, 0x0008, 0x0123}, - {0, 0x0000, 0x0117}, - {0, 0x0000, 0x0112}, - {0, 0x0080, 0x0100}, - {0, 0x0000, 0x0100}, - {1, 0x0000, 0x0116}, - {0, 0x0060, 0x0116}, - {0, 0x0002, 0x0112}, - {0, 0x0000, 0x0123}, - {0, 0x0001, 0x0117}, - {0, 0x0040, 0x0108}, - {0, 0x0019, 0x012c}, - {0, 0x0040, 0x0116}, - {0, 0x000a, 0x0115}, - {0, 0x000b, 0x0115}, - {0, 0x0078, 0x012d}, - {0, 0x0046, 0x012f}, - {0, 0xd141, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfea8, 0x0124}, - {0, 0x0064, 0x0116}, - {0, 0x0000, 0x0115}, - {0, 0x0001, 0x0115}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00aa, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f2, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x000f, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f8, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00fc, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f9, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x003c, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0027, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0019, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0021, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0006, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0045, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002a, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x000e, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002b, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f4, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002c, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0004, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002d, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0014, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002e, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0003, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002f, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0003, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0014, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0053, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0x0000, 0x0101}, - {0, 0x00a0, 0x0103}, - {0, 0x0078, 0x0105}, - {0, 0x0000, 0x010a}, - {0, 0x0024, 0x010b}, - {0, 0x0028, 0x0119}, - {0, 0x0088, 0x011b}, - {0, 0x0002, 0x011d}, - {0, 0x0003, 0x011e}, - {0, 0x0000, 0x0129}, - {0, 0x00fc, 0x012b}, - {0, 0x0008, 0x0102}, - {0, 0x0000, 0x0104}, - {0, 0x0008, 0x011a}, - {0, 0x0028, 0x011c}, - {0, 0x0021, 0x012a}, - {0, 0x0000, 0x0118}, - {0, 0x0000, 0x0132}, - {0, 0x0000, 0x0109}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0031, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00dc, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0032, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0020, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0030, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0008, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0x0003, 0x0106}, - {0, 0x0062, 0x0107}, - {0, 0x0003, 0x0111}, - }; -#define NUM_INIT_DATA - - unsigned short compression = 0; /* 0=none, 7=best frame rate */ - int f_rate; /* 0=Fastest 7=slowest */ - - if (IBMCAM_T(uvd)->initialized) - return; - - /* Internal frame rate is controlled by f_rate value */ - f_rate = 7 - framerate; - RESTRICT_TO_RANGE(f_rate, 0, 7); - - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 1, 0x0000, 0x0116); - ibmcam_veio(uvd, 0, 0x0060, 0x0116); - ibmcam_veio(uvd, 0, 0x0002, 0x0112); - ibmcam_veio(uvd, 0, 0x0000, 0x0123); - ibmcam_veio(uvd, 0, 0x0001, 0x0117); - ibmcam_veio(uvd, 0, 0x0040, 0x0108); - ibmcam_veio(uvd, 0, 0x0019, 0x012c); - ibmcam_veio(uvd, 0, 0x0060, 0x0116); - ibmcam_veio(uvd, 0, 0x0002, 0x0115); - ibmcam_veio(uvd, 0, 0x0003, 0x0115); - ibmcam_veio(uvd, 1, 0x0000, 0x0115); - ibmcam_veio(uvd, 0, 0x000b, 0x0115); - ibmcam_model3_Packet1(uvd, 0x000a, 0x0040); - ibmcam_model3_Packet1(uvd, 0x000b, 0x00f6); - ibmcam_model3_Packet1(uvd, 0x000c, 0x0002); - ibmcam_model3_Packet1(uvd, 0x000d, 0x0020); - ibmcam_model3_Packet1(uvd, 0x000e, 0x0033); - ibmcam_model3_Packet1(uvd, 0x000f, 0x0007); - ibmcam_model3_Packet1(uvd, 0x0010, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0011, 0x0070); - ibmcam_model3_Packet1(uvd, 0x0012, 0x0030); - ibmcam_model3_Packet1(uvd, 0x0013, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0014, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0015, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0016, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0017, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0018, 0x0000); - ibmcam_model3_Packet1(uvd, 0x001e, 0x00c3); - ibmcam_model3_Packet1(uvd, 0x0020, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0028, 0x0010); - ibmcam_model3_Packet1(uvd, 0x0029, 0x0054); - ibmcam_model3_Packet1(uvd, 0x002a, 0x0013); - ibmcam_model3_Packet1(uvd, 0x002b, 0x0007); - ibmcam_model3_Packet1(uvd, 0x002d, 0x0028); - ibmcam_model3_Packet1(uvd, 0x002e, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0031, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0032, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0033, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0034, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0035, 0x0038); - ibmcam_model3_Packet1(uvd, 0x003a, 0x0001); - ibmcam_model3_Packet1(uvd, 0x003c, 0x001e); - ibmcam_model3_Packet1(uvd, 0x003f, 0x000a); - ibmcam_model3_Packet1(uvd, 0x0041, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0046, 0x003f); - ibmcam_model3_Packet1(uvd, 0x0047, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0050, 0x0005); - ibmcam_model3_Packet1(uvd, 0x0052, 0x001a); - ibmcam_model3_Packet1(uvd, 0x0053, 0x0003); - ibmcam_model3_Packet1(uvd, 0x005a, 0x006b); - ibmcam_model3_Packet1(uvd, 0x005d, 0x001e); - ibmcam_model3_Packet1(uvd, 0x005e, 0x0030); - ibmcam_model3_Packet1(uvd, 0x005f, 0x0041); - ibmcam_model3_Packet1(uvd, 0x0064, 0x0008); - ibmcam_model3_Packet1(uvd, 0x0065, 0x0015); - ibmcam_model3_Packet1(uvd, 0x0068, 0x000f); - ibmcam_model3_Packet1(uvd, 0x0079, 0x0000); - ibmcam_model3_Packet1(uvd, 0x007a, 0x0000); - ibmcam_model3_Packet1(uvd, 0x007c, 0x003f); - ibmcam_model3_Packet1(uvd, 0x0082, 0x000f); - ibmcam_model3_Packet1(uvd, 0x0085, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0099, 0x0000); - ibmcam_model3_Packet1(uvd, 0x009b, 0x0023); - ibmcam_model3_Packet1(uvd, 0x009c, 0x0022); - ibmcam_model3_Packet1(uvd, 0x009d, 0x0096); - ibmcam_model3_Packet1(uvd, 0x009e, 0x0096); - ibmcam_model3_Packet1(uvd, 0x009f, 0x000a); - - switch (uvd->videosize) { - case VIDEOSIZE_160x120: - ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ - ibmcam_veio(uvd, 0, 0x0024, 0x010b); /* Differs everywhere */ - ibmcam_veio(uvd, 0, 0x00a9, 0x0119); - ibmcam_veio(uvd, 0, 0x0016, 0x011b); - ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ - ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ - ibmcam_veio(uvd, 0, 0x0018, 0x0102); - ibmcam_veio(uvd, 0, 0x0004, 0x0104); - ibmcam_veio(uvd, 0, 0x0004, 0x011a); - ibmcam_veio(uvd, 0, 0x0028, 0x011c); - ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ - ibmcam_veio(uvd, 0, 0x0000, 0x0118); - ibmcam_veio(uvd, 0, 0x0000, 0x0132); - ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ - ibmcam_veio(uvd, 0, compression, 0x0109); - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ - ibmcam_veio(uvd, 0, 0x0028, 0x010b); /* Differs everywhere */ - ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same */ - ibmcam_veio(uvd, 0, 0x0000, 0x011e); - ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ - ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ - /* 4 commands from 160x120 skipped */ - ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ - ibmcam_veio(uvd, 0, compression, 0x0109); - ibmcam_veio(uvd, 0, 0x00d9, 0x0119); - ibmcam_veio(uvd, 0, 0x0006, 0x011b); - ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0010, 0x0104); - ibmcam_veio(uvd, 0, 0x0004, 0x011a); - ibmcam_veio(uvd, 0, 0x003f, 0x011c); - ibmcam_veio(uvd, 0, 0x001c, 0x0118); - ibmcam_veio(uvd, 0, 0x0000, 0x0132); - break; - case VIDEOSIZE_640x480: - ibmcam_veio(uvd, 0, 0x00f0, 0x0105); - ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ - ibmcam_veio(uvd, 0, 0x0038, 0x010b); /* Differs everywhere */ - ibmcam_veio(uvd, 0, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0006, 0x011b); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0004, 0x011d); /* NC */ - ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ - ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ - ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0016, 0x0104); /* NC */ - ibmcam_veio(uvd, 0, 0x0004, 0x011a); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x003f, 0x011c); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ - ibmcam_veio(uvd, 0, 0x001c, 0x0118); /* Same on 320x240, 640x480 */ - ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ - ibmcam_veio(uvd, 0, compression, 0x0109); - ibmcam_veio(uvd, 0, 0x0040, 0x0101); - ibmcam_veio(uvd, 0, 0x0040, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0132); /* Same on 320x240, 640x480 */ - break; - } - ibmcam_model3_Packet1(uvd, 0x007e, 0x000e); /* Hue */ - ibmcam_model3_Packet1(uvd, 0x0036, 0x0011); /* Brightness */ - ibmcam_model3_Packet1(uvd, 0x0060, 0x0002); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0061, 0x0004); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0062, 0x0005); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0063, 0x0014); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0); /* Red gain */ - ibmcam_model3_Packet1(uvd, 0x0097, 0x0096); /* Blue gain */ - ibmcam_model3_Packet1(uvd, 0x0067, 0x0001); /* Contrast */ - ibmcam_model3_Packet1(uvd, 0x005b, 0x000c); /* Contrast */ - ibmcam_model3_Packet1(uvd, 0x005c, 0x0016); /* Contrast */ - ibmcam_model3_Packet1(uvd, 0x0098, 0x000b); - ibmcam_model3_Packet1(uvd, 0x002c, 0x0003); /* Was 1, broke 640x480 */ - ibmcam_model3_Packet1(uvd, 0x002f, 0x002a); - ibmcam_model3_Packet1(uvd, 0x0030, 0x0029); - ibmcam_model3_Packet1(uvd, 0x0037, 0x0002); - ibmcam_model3_Packet1(uvd, 0x0038, 0x0059); - ibmcam_model3_Packet1(uvd, 0x003d, 0x002e); - ibmcam_model3_Packet1(uvd, 0x003e, 0x0028); - ibmcam_model3_Packet1(uvd, 0x0078, 0x0005); - ibmcam_model3_Packet1(uvd, 0x007b, 0x0011); - ibmcam_model3_Packet1(uvd, 0x007d, 0x004b); - ibmcam_model3_Packet1(uvd, 0x007f, 0x0022); - ibmcam_model3_Packet1(uvd, 0x0080, 0x000c); - ibmcam_model3_Packet1(uvd, 0x0081, 0x000b); - ibmcam_model3_Packet1(uvd, 0x0083, 0x00fd); - ibmcam_model3_Packet1(uvd, 0x0086, 0x000b); - ibmcam_model3_Packet1(uvd, 0x0087, 0x000b); - ibmcam_model3_Packet1(uvd, 0x007e, 0x000e); - ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0); /* Red gain */ - ibmcam_model3_Packet1(uvd, 0x0097, 0x0096); /* Blue gain */ - ibmcam_model3_Packet1(uvd, 0x0098, 0x000b); - - switch (uvd->videosize) { - case VIDEOSIZE_160x120: - ibmcam_veio(uvd, 0, 0x0002, 0x0106); - ibmcam_veio(uvd, 0, 0x0008, 0x0107); - ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ - ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */ - ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0040, 0x000a); - ibmcam_model3_Packet1(uvd, 0x0051, 0x000a); - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x0062, 0x0107); - ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ - ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */ - ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0040, 0x0008); - ibmcam_model3_Packet1(uvd, 0x0051, 0x000b); - break; - case VIDEOSIZE_640x480: - ibmcam_veio(uvd, 0, 0x0002, 0x0106); /* Adjustments */ - ibmcam_veio(uvd, 0, 0x00b4, 0x0107); /* Adjustments */ - ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ - ibmcam_model3_Packet1(uvd, 0x001f, 0x0002); /* !Same */ - ibmcam_model3_Packet1(uvd, 0x0039, 0x003e); /* !Same */ - ibmcam_model3_Packet1(uvd, 0x0040, 0x0008); - ibmcam_model3_Packet1(uvd, 0x0051, 0x000a); - break; - } - - /* 01.01.08 - Added for RCA video in support -LO */ - if(init_model3_input) { - if (debug > 0) - info("Setting input to RCA."); - for (i=0; i < ARRAY_SIZE(initData); i++) { - ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index); - } - } - - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); -} - -/* - * ibmcam_video_stop() - * - * This code tells camera to stop streaming. The interface remains - * configured and bandwidth - claimed. - */ -static void ibmcam_video_stop(struct uvd *uvd) -{ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - ibmcam_veio(uvd, 0, 0x00, 0x010c); - ibmcam_veio(uvd, 0, 0x00, 0x010c); - ibmcam_veio(uvd, 0, 0x01, 0x0114); - ibmcam_veio(uvd, 0, 0xc0, 0x010c); - ibmcam_veio(uvd, 0, 0x00, 0x010c); - ibmcam_send_FF_04_02(uvd); - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x81, 0x0100); /* LED Off */ - break; - case IBMCAM_MODEL_2: -case IBMCAM_MODEL_4: - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop the camera */ - - ibmcam_model2_Packet1(uvd, 0x0030, 0x0004); - - ibmcam_veio(uvd, 0, 0x0080, 0x0100); /* LED Off */ - ibmcam_veio(uvd, 0, 0x0020, 0x0111); - ibmcam_veio(uvd, 0, 0x00a0, 0x0111); - - ibmcam_model2_Packet1(uvd, 0x0030, 0x0002); - - ibmcam_veio(uvd, 0, 0x0020, 0x0111); - ibmcam_veio(uvd, 0, 0x0000, 0x0112); - break; - case IBMCAM_MODEL_3: -#if 1 - ibmcam_veio(uvd, 0, 0x0000, 0x010c); - - /* Here we are supposed to select video interface alt. setting 0 */ - ibmcam_veio(uvd, 0, 0x0006, 0x012c); - - ibmcam_model3_Packet1(uvd, 0x0046, 0x0000); - - ibmcam_veio(uvd, 1, 0x0000, 0x0116); - ibmcam_veio(uvd, 0, 0x0064, 0x0116); - ibmcam_veio(uvd, 1, 0x0000, 0x0115); - ibmcam_veio(uvd, 0, 0x0003, 0x0115); - ibmcam_veio(uvd, 0, 0x0008, 0x0123); - ibmcam_veio(uvd, 0, 0x0000, 0x0117); - ibmcam_veio(uvd, 0, 0x0000, 0x0112); - ibmcam_veio(uvd, 0, 0x0080, 0x0100); - IBMCAM_T(uvd)->initialized = 0; -#endif - break; - } /* switch */ -} - -/* - * ibmcam_reinit_iso() - * - * This procedure sends couple of commands to the camera and then - * resets the video pipe. This sequence was observed to reinit the - * camera or, at least, to initiate ISO data stream. - * - * History: - * 1/2/00 Created. - */ -static void ibmcam_reinit_iso(struct uvd *uvd, int do_stop) -{ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - if (do_stop) - ibmcam_video_stop(uvd); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_model1_setup_after_video_if(uvd); - break; - case IBMCAM_MODEL_2: - ibmcam_model2_setup_after_video_if(uvd); - break; - case IBMCAM_MODEL_3: - ibmcam_video_stop(uvd); - ibmcam_model3_setup_after_video_if(uvd); - break; - case IBMCAM_MODEL_4: - ibmcam_model4_setup_after_video_if(uvd); - break; - } -} - -static void ibmcam_video_start(struct uvd *uvd) -{ - ibmcam_change_lighting_conditions(uvd); - ibmcam_set_sharpness(uvd); - ibmcam_reinit_iso(uvd, 0); -} - -/* - * Return negative code on failure, 0 on success. - */ -static int ibmcam_setup_on_open(struct uvd *uvd) -{ - int setup_ok = 0; /* Success by default */ - /* Send init sequence only once, it's large! */ - if (!IBMCAM_T(uvd)->initialized) { /* FIXME rename */ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - setup_ok = ibmcam_model1_setup(uvd); - break; - case IBMCAM_MODEL_2: - setup_ok = ibmcam_model2_setup(uvd); - break; - case IBMCAM_MODEL_3: - case IBMCAM_MODEL_4: - /* We do all setup when Isoc stream is requested */ - break; - } - IBMCAM_T(uvd)->initialized = (setup_ok != 0); - } - return setup_ok; -} - -static void ibmcam_configure_video(struct uvd *uvd) -{ - if (uvd == NULL) - return; - - RESTRICT_TO_RANGE(init_brightness, 0, 255); - RESTRICT_TO_RANGE(init_contrast, 0, 255); - RESTRICT_TO_RANGE(init_color, 0, 255); - RESTRICT_TO_RANGE(init_hue, 0, 255); - RESTRICT_TO_RANGE(hue_correction, 0, 255); - - memset(&uvd->vpic, 0, sizeof(uvd->vpic)); - memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); - - uvd->vpic.colour = init_color << 8; - uvd->vpic.hue = init_hue << 8; - uvd->vpic.brightness = init_brightness << 8; - uvd->vpic.contrast = init_contrast << 8; - uvd->vpic.whiteness = 105 << 8; /* This one isn't used */ - uvd->vpic.depth = 24; - uvd->vpic.palette = VIDEO_PALETTE_RGB24; - - memset(&uvd->vcap, 0, sizeof(uvd->vcap)); - strcpy(uvd->vcap.name, "IBM USB Camera"); - uvd->vcap.type = VID_TYPE_CAPTURE; - uvd->vcap.channels = 1; - uvd->vcap.audios = 0; - uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas); - uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas); - uvd->vcap.minwidth = min_canvasWidth; - uvd->vcap.minheight = min_canvasHeight; - - memset(&uvd->vchan, 0, sizeof(uvd->vchan)); - uvd->vchan.flags = 0; - uvd->vchan.tuners = 0; - uvd->vchan.channel = 0; - uvd->vchan.type = VIDEO_TYPE_CAMERA; - strcpy(uvd->vchan.name, "Camera"); -} - -/* - * ibmcam_probe() - * - * This procedure queries device descriptor and accepts the interface - * if it looks like IBM C-it camera. - * - * History: - * 22-Jan-2000 Moved camera init code to ibmcam_open() - * 27=Jan-2000 Changed to use static structures, added locking. - * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). - * 03-Jul-2000 Fixed endianness bug. - * 12-Nov-2000 Reworked to comply with new probe() signature. - * 23-Jan-2001 Added compatibility with 2.2.x kernels. - */ -static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *devid) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct uvd *uvd = NULL; - int ix, i, nas, model=0, canvasX=0, canvasY=0; - int actInterface=-1, inactInterface=-1, maxPS=0; - __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; - unsigned char video_ep = 0; - - if (debug >= 1) - info("ibmcam_probe(%p,%u.)", intf, ifnum); - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - /* Check the version/revision */ - switch (le16_to_cpu(dev->descriptor.bcdDevice)) { - case 0x0002: - if (ifnum != 2) - return -ENODEV; - model = IBMCAM_MODEL_1; - break; - case 0x030A: - if (ifnum != 0) - return -ENODEV; - if ((le16_to_cpu(dev->descriptor.idProduct) == NETCAM_PRODUCT_ID) || - (le16_to_cpu(dev->descriptor.idProduct) == VEO_800D_PRODUCT_ID)) - model = IBMCAM_MODEL_4; - else - model = IBMCAM_MODEL_2; - break; - case 0x0301: - if (ifnum != 0) - return -ENODEV; - model = IBMCAM_MODEL_3; - break; - default: - err("IBM camera with revision 0x%04x is not supported.", - le16_to_cpu(dev->descriptor.bcdDevice)); - return -ENODEV; - } - - /* Print detailed info on what we found so far */ - do { - char *brand = NULL; - switch (le16_to_cpu(dev->descriptor.idProduct)) { - case NETCAM_PRODUCT_ID: - brand = "IBM NetCamera"; - break; - case VEO_800C_PRODUCT_ID: - brand = "Veo Stingray [800C]"; - break; - case VEO_800D_PRODUCT_ID: - brand = "Veo Stingray [800D]"; - break; - case IBMCAM_PRODUCT_ID: - default: - brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ - break; - } - info("%s USB camera found (model %d, rev. 0x%04x)", - brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); - } while (0); - - /* Validate found interface: must have one ISO endpoint */ - nas = intf->num_altsetting; - if (debug > 0) - info("Number of alternate settings=%d.", nas); - if (nas < 2) { - err("Too few alternate settings for this camera!"); - return -ENODEV; - } - /* Validate all alternate settings */ - for (ix=0; ix < nas; ix++) { - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - - interface = &intf->altsetting[ix]; - i = interface->desc.bAlternateSetting; - if (interface->desc.bNumEndpoints != 1) { - err("Interface %d. has %u. endpoints!", - ifnum, (unsigned)(interface->desc.bNumEndpoints)); - return -ENODEV; - } - endpoint = &interface->endpoint[0].desc; - if (video_ep == 0) - video_ep = endpoint->bEndpointAddress; - else if (video_ep != endpoint->bEndpointAddress) { - err("Alternate settings have different endpoint addresses!"); - return -ENODEV; - } - if ((endpoint->bmAttributes & 0x03) != 0x01) { - err("Interface %d. has non-ISO endpoint!", ifnum); - return -ENODEV; - } - if ((endpoint->bEndpointAddress & 0x80) == 0) { - err("Interface %d. has ISO OUT endpoint!", ifnum); - return -ENODEV; - } - if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { - if (inactInterface < 0) - inactInterface = i; - else { - err("More than one inactive alt. setting!"); - return -ENODEV; - } - } else { - if (actInterface < 0) { - actInterface = i; - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - if (debug > 0) - info("Active setting=%d. maxPS=%d.", i, maxPS); - } else - err("More than one active alt. setting! Ignoring #%d.", i); - } - } - if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) { - err("Failed to recognize the camera!"); - return -ENODEV; - } - - /* Validate options */ - switch (model) { - case IBMCAM_MODEL_1: - RESTRICT_TO_RANGE(lighting, 0, 2); - RESTRICT_TO_RANGE(size, SIZE_128x96, SIZE_352x288); - if (framerate < 0) - framerate = 2; - canvasX = 352; - canvasY = 288; - break; - case IBMCAM_MODEL_2: - RESTRICT_TO_RANGE(lighting, 0, 15); - RESTRICT_TO_RANGE(size, SIZE_176x144, SIZE_352x240); - if (framerate < 0) - framerate = 2; - canvasX = 352; - canvasY = 240; - break; - case IBMCAM_MODEL_3: - RESTRICT_TO_RANGE(lighting, 0, 15); /* FIXME */ - switch (size) { - case SIZE_160x120: - canvasX = 160; - canvasY = 120; - if (framerate < 0) - framerate = 2; - RESTRICT_TO_RANGE(framerate, 0, 5); - break; - default: - info("IBM camera: using 320x240"); - size = SIZE_320x240; - /* No break here */ - case SIZE_320x240: - canvasX = 320; - canvasY = 240; - if (framerate < 0) - framerate = 3; - RESTRICT_TO_RANGE(framerate, 0, 5); - break; - case SIZE_640x480: - canvasX = 640; - canvasY = 480; - framerate = 0; /* Slowest, and maybe even that is too fast */ - break; - } - break; - case IBMCAM_MODEL_4: - RESTRICT_TO_RANGE(lighting, 0, 2); - switch (size) { - case SIZE_128x96: - canvasX = 128; - canvasY = 96; - break; - case SIZE_160x120: - canvasX = 160; - canvasY = 120; - break; - default: - info("IBM NetCamera: using 176x144"); - size = SIZE_176x144; - /* No break here */ - case SIZE_176x144: - canvasX = 176; - canvasY = 144; - break; - case SIZE_320x240: - canvasX = 320; - canvasY = 240; - break; - case SIZE_352x288: - canvasX = 352; - canvasY = 288; - break; - } - break; - default: - err("IBM camera: Model %d. not supported!", model); - return -ENODEV; - } - - uvd = usbvideo_AllocateDevice(cams); - if (uvd != NULL) { - /* Here uvd is a fully allocated uvd object */ - uvd->flags = flags; - uvd->debug = debug; - uvd->dev = dev; - uvd->iface = ifnum; - uvd->ifaceAltInactive = inactInterface; - uvd->ifaceAltActive = actInterface; - uvd->video_endp = video_ep; - uvd->iso_packet_len = maxPS; - uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; - uvd->defaultPalette = VIDEO_PALETTE_RGB24; - uvd->canvas = VIDEOSIZE(canvasX, canvasY); - uvd->videosize = ibmcam_size_to_videosize(size); - - /* Initialize ibmcam-specific data */ - assert(IBMCAM_T(uvd) != NULL); - IBMCAM_T(uvd)->camera_model = model; - IBMCAM_T(uvd)->initialized = 0; - - ibmcam_configure_video(uvd); - - i = usbvideo_RegisterVideoDevice(uvd); - if (i != 0) { - err("usbvideo_RegisterVideoDevice() failed."); - uvd = NULL; - } - } - usb_set_intfdata (intf, uvd); - return 0; -} - - -static struct usb_device_id id_table[] = { - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) }, /* Model 1 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) }, /* Model 3 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ - { } /* Terminating entry */ -}; - -/* - * ibmcam_init() - * - * This code is run to initialize the driver. - * - * History: - * 1/27/00 Reworked to use statically allocated ibmcam structures. - * 21/10/00 Completely redesigned to use usbvideo services. - */ -static int __init ibmcam_init(void) -{ - struct usbvideo_cb cbTbl; - memset(&cbTbl, 0, sizeof(cbTbl)); - cbTbl.probe = ibmcam_probe; - cbTbl.setupOnOpen = ibmcam_setup_on_open; - cbTbl.videoStart = ibmcam_video_start; - cbTbl.videoStop = ibmcam_video_stop; - cbTbl.processData = ibmcam_ProcessIsocData; - cbTbl.postProcess = usbvideo_DeinterlaceFrame; - cbTbl.adjustPicture = ibmcam_adjust_picture; - cbTbl.getFPS = ibmcam_calculate_fps; - return usbvideo_register( - &cams, - MAX_IBMCAM, - sizeof(ibmcam_t), - "ibmcam", - &cbTbl, - THIS_MODULE, - id_table); -} - -static void __exit ibmcam_cleanup(void) -{ - usbvideo_Deregister(&cams); -} - -MODULE_DEVICE_TABLE(usb, id_table); - -module_init(ibmcam_init); -module_exit(ibmcam_cleanup); diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c deleted file mode 100644 index e2ede583518f..000000000000 --- a/drivers/usb/media/konicawc.c +++ /dev/null @@ -1,978 +0,0 @@ -/* - * konicawc.c - konica webcam driver - * - * Author: Simon Evans - * - * Copyright (C) 2002 Simon Evans - * - * Licence: GPL - * - * Driver for USB webcams based on Konica chipset. This - * chipset is used in Intel YC76 camera. - * - */ - -#include -#include -#include -#include -#include - -#include "usbvideo.h" - -#define MAX_BRIGHTNESS 108 -#define MAX_CONTRAST 108 -#define MAX_SATURATION 108 -#define MAX_SHARPNESS 108 -#define MAX_WHITEBAL 372 -#define MAX_SPEED 6 - - -#define MAX_CAMERAS 1 - -#define DRIVER_VERSION "v1.4" -#define DRIVER_DESC "Konica Webcam driver" - -enum ctrl_req { - SetWhitebal = 0x01, - SetBrightness = 0x02, - SetSharpness = 0x03, - SetContrast = 0x04, - SetSaturation = 0x05, -}; - - -enum frame_sizes { - SIZE_160X120 = 0, - SIZE_160X136 = 1, - SIZE_176X144 = 2, - SIZE_320X240 = 3, - -}; - -#define MAX_FRAME_SIZE SIZE_320X240 - -static struct usbvideo *cams; - -#ifdef CONFIG_USB_DEBUG -static int debug; -#define DEBUG(n, format, arg...) \ - if (n <= debug) { \ - printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \ - } -#else -#define DEBUG(n, arg...) -static const int debug = 0; -#endif - - -/* Some default values for initial camera settings, - can be set by modprobe */ - -static int size; -static int speed = 6; /* Speed (fps) 0 (slowest) to 6 (fastest) */ -static int brightness = MAX_BRIGHTNESS/2; -static int contrast = MAX_CONTRAST/2; -static int saturation = MAX_SATURATION/2; -static int sharpness = MAX_SHARPNESS/2; -static int whitebal = 3*(MAX_WHITEBAL/4); - -static const int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 }; - -/* These FPS speeds are from the windows config box. They are - * indexed on size (0-2) and speed (0-6). Divide by 3 to get the - * real fps. - */ - -static const int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 }, - { 24, 40, 48, 60, 72, 80, 100 }, - { 18, 30, 36, 45, 54, 60, 75 }, - { 6, 10, 12, 15, 18, 21, 25 } }; - -struct cam_size { - u16 width; - u16 height; - u8 cmd; -}; - -static const struct cam_size camera_sizes[] = { { 160, 120, 0x7 }, - { 160, 136, 0xa }, - { 176, 144, 0x4 }, - { 320, 240, 0x5 } }; - -struct konicawc { - u8 brightness; /* camera uses 0 - 9, x11 for real value */ - u8 contrast; /* as above */ - u8 saturation; /* as above */ - u8 sharpness; /* as above */ - u8 white_bal; /* 0 - 33, x11 for real value */ - u8 speed; /* Stored as 0 - 6, used as index in spd_to_* (above) */ - u8 size; /* Frame Size */ - int height; - int width; - struct urb *sts_urb[USBVIDEO_NUMSBUF]; - u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC]; - struct urb *last_data_urb; - int lastframe; - int cur_frame_size; /* number of bytes in current frame size */ - int maxline; /* number of lines per frame */ - int yplanesz; /* Number of bytes in the Y plane */ - unsigned int buttonsts:1; -#ifdef CONFIG_INPUT - struct input_dev *input; - char input_physname[64]; -#endif -}; - - -#define konicawc_set_misc(uvd, req, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0) -#define konicawc_get_misc(uvd, req, value, index, buf, sz) konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz) -#define konicawc_set_value(uvd, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0) - - -static int konicawc_ctrl_msg(struct uvd *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len) -{ - int retval = usb_control_msg(uvd->dev, - dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0), - request, 0x40 | dir, value, index, buf, len, 1000); - return retval < 0 ? retval : 0; -} - - -static inline void konicawc_camera_on(struct uvd *uvd) -{ - DEBUG(0, "camera on"); - konicawc_set_misc(uvd, 0x2, 1, 0x0b); -} - - -static inline void konicawc_camera_off(struct uvd *uvd) -{ - DEBUG(0, "camera off"); - konicawc_set_misc(uvd, 0x2, 0, 0x0b); -} - - -static void konicawc_set_camera_size(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - konicawc_set_misc(uvd, 0x2, camera_sizes[cam->size].cmd, 0x08); - cam->width = camera_sizes[cam->size].width; - cam->height = camera_sizes[cam->size].height; - cam->yplanesz = cam->height * cam->width; - cam->cur_frame_size = (cam->yplanesz * 3) / 2; - cam->maxline = cam->yplanesz / 256; - uvd->videosize = VIDEOSIZE(cam->width, cam->height); -} - - -static int konicawc_setup_on_open(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - DEBUG(1, "setting brightness to %d (%d)", cam->brightness, - cam->brightness * 11); - konicawc_set_value(uvd, cam->brightness, SetBrightness); - DEBUG(1, "setting white balance to %d (%d)", cam->white_bal, - cam->white_bal * 11); - konicawc_set_value(uvd, cam->white_bal, SetWhitebal); - DEBUG(1, "setting contrast to %d (%d)", cam->contrast, - cam->contrast * 11); - konicawc_set_value(uvd, cam->contrast, SetContrast); - DEBUG(1, "setting saturation to %d (%d)", cam->saturation, - cam->saturation * 11); - konicawc_set_value(uvd, cam->saturation, SetSaturation); - DEBUG(1, "setting sharpness to %d (%d)", cam->sharpness, - cam->sharpness * 11); - konicawc_set_value(uvd, cam->sharpness, SetSharpness); - konicawc_set_camera_size(uvd); - cam->lastframe = -2; - cam->buttonsts = 0; - return 0; -} - - -static void konicawc_adjust_picture(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - konicawc_camera_off(uvd); - DEBUG(1, "new brightness: %d", uvd->vpic.brightness); - uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness; - if(cam->brightness != uvd->vpic.brightness / 11) { - cam->brightness = uvd->vpic.brightness / 11; - DEBUG(1, "setting brightness to %d (%d)", cam->brightness, - cam->brightness * 11); - konicawc_set_value(uvd, cam->brightness, SetBrightness); - } - - DEBUG(1, "new contrast: %d", uvd->vpic.contrast); - uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : uvd->vpic.contrast; - if(cam->contrast != uvd->vpic.contrast / 11) { - cam->contrast = uvd->vpic.contrast / 11; - DEBUG(1, "setting contrast to %d (%d)", cam->contrast, - cam->contrast * 11); - konicawc_set_value(uvd, cam->contrast, SetContrast); - } - konicawc_camera_on(uvd); -} - -#ifdef CONFIG_INPUT - -static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) -{ - struct input_dev *input_dev; - - usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); - strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); - - cam->input = input_dev = input_allocate_device(); - if (!input_dev) { - warn("Not enough memory for camera's input device\n"); - return; - } - - input_dev->name = "Konicawc snapshot button"; - input_dev->phys = cam->input_physname; - usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &dev->dev; - - input_dev->evbit[0] = BIT(EV_KEY); - input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); - - input_dev->private = cam; - - input_register_device(cam->input); -} - -static void konicawc_unregister_input(struct konicawc *cam) -{ - if (cam->input) { - input_unregister_device(cam->input); - cam->input = NULL; - } -} - -static void konicawc_report_buttonstat(struct konicawc *cam) -{ - if (cam->input) { - input_report_key(cam->input, BTN_0, cam->buttonsts); - input_sync(cam->input); - } -} - -#else - -static inline void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) { } -static inline void konicawc_unregister_input(struct konicawc *cam) { } -static inline void konicawc_report_buttonstat(struct konicawc *cam) { } - -#endif /* CONFIG_INPUT */ - -static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb) -{ - char *cdata; - int i, totlen = 0; - unsigned char *status = stsurb->transfer_buffer; - int keep = 0, discard = 0, bad = 0; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - for (i = 0; i < dataurb->number_of_packets; i++) { - int button = cam->buttonsts; - unsigned char sts; - int n = dataurb->iso_frame_desc[i].actual_length; - int st = dataurb->iso_frame_desc[i].status; - cdata = dataurb->transfer_buffer + - dataurb->iso_frame_desc[i].offset; - - /* Detect and ignore errored packets */ - if (st < 0) { - DEBUG(1, "Data error: packet=%d. len=%d. status=%d.", - i, n, st); - uvd->stats.iso_err_count++; - continue; - } - - /* Detect and ignore empty packets */ - if (n <= 0) { - uvd->stats.iso_skip_count++; - continue; - } - - /* See what the status data said about the packet */ - sts = *(status+stsurb->iso_frame_desc[i].offset); - - /* sts: 0x80-0xff: frame start with frame number (ie 0-7f) - * otherwise: - * bit 0 0: keep packet - * 1: drop packet (padding data) - * - * bit 4 0 button not clicked - * 1 button clicked - * button is used to `take a picture' (in software) - */ - - if(sts < 0x80) { - button = !!(sts & 0x40); - sts &= ~0x40; - } - - /* work out the button status, but don't do - anything with it for now */ - - if(button != cam->buttonsts) { - DEBUG(2, "button: %sclicked", button ? "" : "un"); - cam->buttonsts = button; - konicawc_report_buttonstat(cam); - } - - if(sts == 0x01) { /* drop frame */ - discard++; - continue; - } - - if((sts > 0x01) && (sts < 0x80)) { - info("unknown status %2.2x", sts); - bad++; - continue; - } - if(!sts && cam->lastframe == -2) { - DEBUG(2, "dropping frame looking for image start"); - continue; - } - - keep++; - if(sts & 0x80) { /* frame start */ - unsigned char marker[] = { 0, 0xff, 0, 0x00 }; - - if(cam->lastframe == -2) { - DEBUG(2, "found initial image"); - cam->lastframe = -1; - } - - marker[3] = sts & 0x7F; - RingQueue_Enqueue(&uvd->dp, marker, 4); - totlen += 4; - } - - totlen += n; /* Little local accounting */ - RingQueue_Enqueue(&uvd->dp, cdata, n); - } - DEBUG(8, "finished: keep = %d discard = %d bad = %d added %d bytes", - keep, discard, bad, totlen); - return totlen; -} - - -static void resubmit_urb(struct uvd *uvd, struct urb *urb) -{ - int i, ret; - for (i = 0; i < FRAMES_PER_DESC; i++) { - urb->iso_frame_desc[i].status = 0; - } - urb->dev = uvd->dev; - urb->status = 0; - ret = usb_submit_urb(urb, GFP_ATOMIC); - DEBUG(3, "submitting urb of length %d", urb->transfer_buffer_length); - if(ret) - err("usb_submit_urb error (%d)", ret); - -} - - -static void konicawc_isoc_irq(struct urb *urb, struct pt_regs *regs) -{ - struct uvd *uvd = urb->context; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - /* We don't want to do anything if we are about to be removed! */ - if (!CAMERA_IS_OPERATIONAL(uvd)) - return; - - if (!uvd->streaming) { - DEBUG(1, "Not streaming, but interrupt!"); - return; - } - - DEBUG(3, "got frame %d len = %d buflen =%d", urb->start_frame, urb->actual_length, urb->transfer_buffer_length); - - uvd->stats.urb_count++; - - if (urb->transfer_buffer_length > 32) { - cam->last_data_urb = urb; - return; - } - /* Copy the data received into ring queue */ - if(cam->last_data_urb) { - int len = 0; - if(urb->start_frame != cam->last_data_urb->start_frame) - err("Lost sync on frames"); - else if (!urb->status && !cam->last_data_urb->status) - len = konicawc_compress_iso(uvd, cam->last_data_urb, urb); - - resubmit_urb(uvd, cam->last_data_urb); - resubmit_urb(uvd, urb); - cam->last_data_urb = NULL; - uvd->stats.urb_length = len; - uvd->stats.data_count += len; - if(len) - RingQueue_WakeUpInterruptible(&uvd->dp); - return; - } - return; -} - - -static int konicawc_start_data(struct uvd *uvd) -{ - struct usb_device *dev = uvd->dev; - int i, errFlag; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - int pktsz; - struct usb_interface *intf; - struct usb_host_interface *interface = NULL; - - intf = usb_ifnum_to_if(dev, uvd->iface); - if (intf) - interface = usb_altnum_to_altsetting(intf, - spd_to_iface[cam->speed]); - if (!interface) - return -ENXIO; - pktsz = le16_to_cpu(interface->endpoint[1].desc.wMaxPacketSize); - DEBUG(1, "pktsz = %d", pktsz); - if (!CAMERA_IS_OPERATIONAL(uvd)) { - err("Camera is not operational"); - return -EFAULT; - } - uvd->curframe = -1; - konicawc_camera_on(uvd); - /* Alternate interface 1 is is the biggest frame size */ - i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); - if (i < 0) { - err("usb_set_interface error"); - uvd->last_error = i; - return -EBUSY; - } - - /* We double buffer the Iso lists */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - int j, k; - struct urb *urb = uvd->sbuf[i].urb; - urb->dev = dev; - urb->context = uvd; - urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); - urb->interval = 1; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = uvd->sbuf[i].data; - urb->complete = konicawc_isoc_irq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC; - for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = pktsz; - } - - urb = cam->sts_urb[i]; - urb->dev = dev; - urb->context = uvd; - urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1); - urb->interval = 1; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = cam->sts_buf[i]; - urb->complete = konicawc_isoc_irq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = FRAMES_PER_DESC; - for (j=0; j < FRAMES_PER_DESC; j++) { - urb->iso_frame_desc[j].offset = j; - urb->iso_frame_desc[j].length = 1; - } - } - - cam->last_data_urb = NULL; - - /* Submit all URBs */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - errFlag = usb_submit_urb(cam->sts_urb[i], GFP_KERNEL); - if (errFlag) - err("usb_submit_isoc(%d) ret %d", i, errFlag); - - errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); - if (errFlag) - err ("usb_submit_isoc(%d) ret %d", i, errFlag); - } - - uvd->streaming = 1; - DEBUG(1, "streaming=1 video_endp=$%02x", uvd->video_endp); - return 0; -} - - -static void konicawc_stop_data(struct uvd *uvd) -{ - int i, j; - struct konicawc *cam; - - if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) - return; - - konicawc_camera_off(uvd); - uvd->streaming = 0; - cam = (struct konicawc *)uvd->user_data; - cam->last_data_urb = NULL; - - /* Unschedule all of the iso td's */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - usb_kill_urb(uvd->sbuf[i].urb); - usb_kill_urb(cam->sts_urb[i]); - } - - if (!uvd->remove_pending) { - /* Set packet size to 0 */ - j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); - if (j < 0) { - err("usb_set_interface() error %d.", j); - uvd->last_error = j; - } - } -} - - -static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - int maxline = cam->maxline; - int yplanesz = cam->yplanesz; - - assert(frame != NULL); - - DEBUG(5, "maxline = %d yplanesz = %d", maxline, yplanesz); - DEBUG(3, "Frame state = %d", frame->scanstate); - - if(frame->scanstate == ScanState_Scanning) { - int drop = 0; - int curframe; - int fdrops = 0; - DEBUG(3, "Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp)); - while(RingQueue_GetLength(&uvd->dp) >= 4) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) && - (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) { - curframe = RING_QUEUE_PEEK(&uvd->dp, 3); - if(cam->lastframe >= 0) { - fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; - fdrops--; - if(fdrops) { - info("Dropped %d frames (%d -> %d)", fdrops, - cam->lastframe, curframe); - } - } - cam->lastframe = curframe; - frame->curline = 0; - frame->scanstate = ScanState_Lines; - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4); - break; - } - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - drop++; - } - if(drop) - DEBUG(2, "dropped %d bytes looking for new frame", drop); - } - - if(frame->scanstate == ScanState_Scanning) - return; - - /* Try to move data from queue into frame buffer - * We get data in blocks of 384 bytes made up of: - * 256 Y, 64 U, 64 V. - * This needs to be written out as a Y plane, a U plane and a V plane. - */ - - while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) { - /* Y */ - RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256); - /* U */ - RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64); - /* V */ - RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64); - frame->seqRead_Length += 384; - frame->curline++; - } - /* See if we filled the frame */ - if (frame->curline == maxline) { - DEBUG(5, "got whole frame"); - - frame->frameState = FrameState_Done_Hold; - frame->curline = 0; - uvd->curframe = -1; - uvd->stats.frame_num++; - } -} - - -static int konicawc_find_fps(int size, int fps) -{ - int i; - - fps *= 3; - DEBUG(1, "konica_find_fps: size = %d fps = %d", size, fps); - if(fps <= spd_to_fps[size][0]) - return 0; - - if(fps >= spd_to_fps[size][MAX_SPEED]) - return MAX_SPEED; - - for(i = 0; i < MAX_SPEED; i++) { - if((fps >= spd_to_fps[size][i]) && (fps <= spd_to_fps[size][i+1])) { - DEBUG(2, "fps %d between %d and %d", fps, i, i+1); - if( (fps - spd_to_fps[size][i]) < (spd_to_fps[size][i+1] - fps)) - return i; - else - return i+1; - } - } - return MAX_SPEED+1; -} - - -static int konicawc_set_video_mode(struct uvd *uvd, struct video_window *vw) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - int newspeed = cam->speed; - int newsize; - int x = vw->width; - int y = vw->height; - int fps = vw->flags; - - if(x > 0 && y > 0) { - DEBUG(2, "trying to find size %d,%d", x, y); - for(newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) { - if((camera_sizes[newsize].width == x) && (camera_sizes[newsize].height == y)) - break; - } - } else { - newsize = cam->size; - } - - if(newsize > MAX_FRAME_SIZE) { - DEBUG(1, "couldn't find size %d,%d", x, y); - return -EINVAL; - } - - if(fps > 0) { - DEBUG(1, "trying to set fps to %d", fps); - newspeed = konicawc_find_fps(newsize, fps); - DEBUG(1, "find_fps returned %d (%d)", newspeed, spd_to_fps[newsize][newspeed]); - } - - if(newspeed > MAX_SPEED) - return -EINVAL; - - DEBUG(1, "setting size to %d speed to %d", newsize, newspeed); - if((newsize == cam->size) && (newspeed == cam->speed)) { - DEBUG(1, "Nothing to do"); - return 0; - } - DEBUG(0, "setting to %dx%d @ %d fps", camera_sizes[newsize].width, - camera_sizes[newsize].height, spd_to_fps[newsize][newspeed]/3); - - konicawc_stop_data(uvd); - uvd->ifaceAltActive = spd_to_iface[newspeed]; - DEBUG(1, "new interface = %d", uvd->ifaceAltActive); - cam->speed = newspeed; - - if(cam->size != newsize) { - cam->size = newsize; - konicawc_set_camera_size(uvd); - } - - /* Flush the input queue and clear any current frame in progress */ - - RingQueue_Flush(&uvd->dp); - cam->lastframe = -2; - if(uvd->curframe != -1) { - uvd->frame[uvd->curframe].curline = 0; - uvd->frame[uvd->curframe].seqRead_Length = 0; - uvd->frame[uvd->curframe].seqRead_Index = 0; - } - - konicawc_start_data(uvd); - return 0; -} - - -static int konicawc_calculate_fps(struct uvd *uvd) -{ - struct konicawc *cam = uvd->user_data; - return spd_to_fps[cam->size][cam->speed]/3; -} - - -static void konicawc_configure_video(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - u8 buf[2]; - - memset(&uvd->vpic, 0, sizeof(uvd->vpic)); - memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); - - RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS); - RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST); - RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION); - RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS); - RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL); - - cam->brightness = brightness / 11; - cam->contrast = contrast / 11; - cam->saturation = saturation / 11; - cam->sharpness = sharpness / 11; - cam->white_bal = whitebal / 11; - - uvd->vpic.colour = 108; - uvd->vpic.hue = 108; - uvd->vpic.brightness = brightness; - uvd->vpic.contrast = contrast; - uvd->vpic.whiteness = whitebal; - uvd->vpic.depth = 6; - uvd->vpic.palette = VIDEO_PALETTE_YUV420P; - - memset(&uvd->vcap, 0, sizeof(uvd->vcap)); - strcpy(uvd->vcap.name, "Konica Webcam"); - uvd->vcap.type = VID_TYPE_CAPTURE; - uvd->vcap.channels = 1; - uvd->vcap.audios = 0; - uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width; - uvd->vcap.minheight = camera_sizes[SIZE_160X120].height; - uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width; - uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height; - - memset(&uvd->vchan, 0, sizeof(uvd->vchan)); - uvd->vchan.flags = 0 ; - uvd->vchan.tuners = 0; - uvd->vchan.channel = 0; - uvd->vchan.type = VIDEO_TYPE_CAMERA; - strcpy(uvd->vchan.name, "Camera"); - - /* Talk to device */ - DEBUG(1, "device init"); - if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) - DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); - if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) - DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); - if(konicawc_set_misc(uvd, 0x2, 0, 0xd)) - DEBUG(2, "2,0,d failed"); - DEBUG(1, "setting initial values"); -} - -static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct uvd *uvd = NULL; - int ix, i, nas; - int actInterface=-1, inactInterface=-1, maxPS=0; - unsigned char video_ep = 0; - - DEBUG(1, "konicawc_probe(%p)", intf); - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - info("Konica Webcam (rev. 0x%04x)", le16_to_cpu(dev->descriptor.bcdDevice)); - RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); - - /* Validate found interface: must have one ISO endpoint */ - nas = intf->num_altsetting; - if (nas != 8) { - err("Incorrect number of alternate settings (%d) for this camera!", nas); - return -ENODEV; - } - /* Validate all alternate settings */ - for (ix=0; ix < nas; ix++) { - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - - interface = &intf->altsetting[ix]; - i = interface->desc.bAlternateSetting; - if (interface->desc.bNumEndpoints != 2) { - err("Interface %d. has %u. endpoints!", - interface->desc.bInterfaceNumber, - (unsigned)(interface->desc.bNumEndpoints)); - return -ENODEV; - } - endpoint = &interface->endpoint[1].desc; - DEBUG(1, "found endpoint: addr: 0x%2.2x maxps = 0x%4.4x", - endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize)); - if (video_ep == 0) - video_ep = endpoint->bEndpointAddress; - else if (video_ep != endpoint->bEndpointAddress) { - err("Alternate settings have different endpoint addresses!"); - return -ENODEV; - } - if ((endpoint->bmAttributes & 0x03) != 0x01) { - err("Interface %d. has non-ISO endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if ((endpoint->bEndpointAddress & 0x80) == 0) { - err("Interface %d. has ISO OUT endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { - if (inactInterface < 0) - inactInterface = i; - else { - err("More than one inactive alt. setting!"); - return -ENODEV; - } - } else { - if (i == spd_to_iface[speed]) { - /* This one is the requested one */ - actInterface = i; - } - } - if (le16_to_cpu(endpoint->wMaxPacketSize) > maxPS) - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - } - if(actInterface == -1) { - err("Cant find required endpoint"); - return -ENODEV; - } - - DEBUG(1, "Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS); - - uvd = usbvideo_AllocateDevice(cams); - if (uvd != NULL) { - struct konicawc *cam = (struct konicawc *)(uvd->user_data); - /* Here uvd is a fully allocated uvd object */ - for(i = 0; i < USBVIDEO_NUMSBUF; i++) { - cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); - if(cam->sts_urb[i] == NULL) { - while(i--) { - usb_free_urb(cam->sts_urb[i]); - } - err("can't allocate urbs"); - return -ENOMEM; - } - } - cam->speed = speed; - RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); - cam->width = camera_sizes[size].width; - cam->height = camera_sizes[size].height; - cam->size = size; - - uvd->flags = 0; - uvd->debug = debug; - uvd->dev = dev; - uvd->iface = intf->altsetting->desc.bInterfaceNumber; - uvd->ifaceAltInactive = inactInterface; - uvd->ifaceAltActive = actInterface; - uvd->video_endp = video_ep; - uvd->iso_packet_len = maxPS; - uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P; - uvd->defaultPalette = VIDEO_PALETTE_YUV420P; - uvd->canvas = VIDEOSIZE(320, 240); - uvd->videosize = VIDEOSIZE(cam->width, cam->height); - - /* Initialize konicawc specific data */ - konicawc_configure_video(uvd); - - i = usbvideo_RegisterVideoDevice(uvd); - uvd->max_frame_size = (320 * 240 * 3)/2; - if (i != 0) { - err("usbvideo_RegisterVideoDevice() failed."); - uvd = NULL; - } - - konicawc_register_input(cam, dev); - } - - if (uvd) { - usb_set_intfdata (intf, uvd); - return 0; - } - return -EIO; -} - - -static void konicawc_free_uvd(struct uvd *uvd) -{ - int i; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - konicawc_unregister_input(cam); - - for (i = 0; i < USBVIDEO_NUMSBUF; i++) { - usb_free_urb(cam->sts_urb[i]); - cam->sts_urb[i] = NULL; - } -} - - -static struct usb_device_id id_table[] = { - { USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */ - { } /* Terminating entry */ -}; - - -static int __init konicawc_init(void) -{ - struct usbvideo_cb cbTbl; - info(DRIVER_DESC " " DRIVER_VERSION); - memset(&cbTbl, 0, sizeof(cbTbl)); - cbTbl.probe = konicawc_probe; - cbTbl.setupOnOpen = konicawc_setup_on_open; - cbTbl.processData = konicawc_process_isoc; - cbTbl.getFPS = konicawc_calculate_fps; - cbTbl.setVideoMode = konicawc_set_video_mode; - cbTbl.startDataPump = konicawc_start_data; - cbTbl.stopDataPump = konicawc_stop_data; - cbTbl.adjustPicture = konicawc_adjust_picture; - cbTbl.userFree = konicawc_free_uvd; - return usbvideo_register( - &cams, - MAX_CAMERAS, - sizeof(struct konicawc), - "konicawc", - &cbTbl, - THIS_MODULE, - id_table); -} - - -static void __exit konicawc_cleanup(void) -{ - usbvideo_Deregister(&cams); -} - - -MODULE_DEVICE_TABLE(usb, id_table); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Simon Evans "); -MODULE_DESCRIPTION(DRIVER_DESC); -module_param(speed, int, 0); -MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)"); -module_param(size, int, 0); -MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240"); -module_param(brightness, int, 0); -MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108"); -module_param(contrast, int, 0); -MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108"); -module_param(saturation, int, 0); -MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108"); -module_param(sharpness, int, 0); -MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108"); -module_param(whitebal, int, 0); -MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363"); - -#ifdef CONFIG_USB_DEBUG -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); -#endif - -module_init(konicawc_init); -module_exit(konicawc_cleanup); diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c deleted file mode 100644 index da44579d6f29..000000000000 --- a/drivers/usb/media/ov511.c +++ /dev/null @@ -1,5932 +0,0 @@ -/* - * OmniVision OV511 Camera-to-USB Bridge Driver - * - * Copyright (c) 1999-2003 Mark W. McClelland - * Original decompression code Copyright 1998-2000 OmniVision Technologies - * Many improvements by Bret Wallach - * Color fixes by by Orion Sky Lawlor (2/26/2000) - * Snapshot code by Kevin Moore - * OV7620 fixes by Charl P. Botha - * Changes by Claudio Matsuoka - * Original SAA7111A code by Dave Perks - * URB error messages from pwc driver by Nemosoft - * generic_ioctl() code from videodev.c by Gerd Knorr and Alan Cox - * Memory management (rvmalloc) code from bttv driver, by Gerd Knorr and others - * - * Based on the Linux CPiA driver written by Peter Pregler, - * Scott J. Bertin and Johannes Erdfelt. - * - * Please see the file: Documentation/usb/ov511.txt - * and the website at: http://alpha.dyndns.org/ov511 - * for more info. - * - * 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 -#include -#include - -#if defined (__i386__) - #include -#endif - -#include "ov511.h" - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.64 for Linux 2.5" -#define EMAIL "mark@alpha.dyndns.org" -#define DRIVER_AUTHOR "Mark McClelland & Bret Wallach \ - & Orion Sky Lawlor & Kevin Moore & Charl P. Botha \ - & Claudio Matsuoka " -#define DRIVER_DESC "ov511 USB Camera Driver" - -#define OV511_I2C_RETRIES 3 -#define ENABLE_Y_QUANTABLE 1 -#define ENABLE_UV_QUANTABLE 1 - -#define OV511_MAX_UNIT_VIDEO 16 - -/* Pixel count * bytes per YUV420 pixel (1.5) */ -#define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3 / 2) - -#define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval)) - -/* Max size * bytes per YUV420 pixel (1.5) + one extra isoc frame for safety */ -#define MAX_RAW_DATA_SIZE(w, h) ((w) * (h) * 3 / 2 + 1024) - -#define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM) - -/********************************************************************** - * Module Parameters - * (See ov511.txt for detailed descriptions of these) - **********************************************************************/ - -/* These variables (and all static globals) default to zero */ -static int autobright = 1; -static int autogain = 1; -static int autoexp = 1; -static int debug; -static int snapshot; -static int cams = 1; -static int compress; -static int testpat; -static int dumppix; -static int led = 1; -static int dump_bridge; -static int dump_sensor; -static int printph; -static int phy = 0x1f; -static int phuv = 0x05; -static int pvy = 0x06; -static int pvuv = 0x06; -static int qhy = 0x14; -static int qhuv = 0x03; -static int qvy = 0x04; -static int qvuv = 0x04; -static int lightfreq; -static int bandingfilter; -static int clockdiv = -1; -static int packetsize = -1; -static int framedrop = -1; -static int fastset; -static int force_palette; -static int backlight; -static int unit_video[OV511_MAX_UNIT_VIDEO]; -static int remove_zeros; -static int mirror; -static int ov518_color; - -module_param(autobright, int, 0); -MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness"); -module_param(autogain, int, 0); -MODULE_PARM_DESC(autogain, "Sensor automatically changes gain"); -module_param(autoexp, int, 0); -MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure"); -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, - "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max"); -module_param(snapshot, int, 0); -MODULE_PARM_DESC(snapshot, "Enable snapshot mode"); -module_param(cams, int, 0); -MODULE_PARM_DESC(cams, "Number of simultaneous cameras"); -module_param(compress, int, 0); -MODULE_PARM_DESC(compress, "Turn on compression"); -module_param(testpat, int, 0); -MODULE_PARM_DESC(testpat, - "Replace image with vertical bar testpattern (only partially working)"); -module_param(dumppix, int, 0); -MODULE_PARM_DESC(dumppix, "Dump raw pixel data"); -module_param(led, int, 0); -MODULE_PARM_DESC(led, - "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)"); -module_param(dump_bridge, int, 0); -MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers"); -module_param(dump_sensor, int, 0); -MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers"); -module_param(printph, int, 0); -MODULE_PARM_DESC(printph, "Print frame start/end headers"); -module_param(phy, int, 0); -MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)"); -module_param(phuv, int, 0); -MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)"); -module_param(pvy, int, 0); -MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)"); -module_param(pvuv, int, 0); -MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)"); -module_param(qhy, int, 0); -MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)"); -module_param(qhuv, int, 0); -MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)"); -module_param(qvy, int, 0); -MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)"); -module_param(qvuv, int, 0); -MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)"); -module_param(lightfreq, int, 0); -MODULE_PARM_DESC(lightfreq, - "Light frequency. Set to 50 or 60 Hz, or zero for default settings"); -module_param(bandingfilter, int, 0); -MODULE_PARM_DESC(bandingfilter, - "Enable banding filter (to reduce effects of fluorescent lighting)"); -module_param(clockdiv, int, 0); -MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value"); -module_param(packetsize, int, 0); -MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size"); -module_param(framedrop, int, 0); -MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting"); -module_param(fastset, int, 0); -MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately"); -module_param(force_palette, int, 0); -MODULE_PARM_DESC(force_palette, "Force the palette to a specific value"); -module_param(backlight, int, 0); -MODULE_PARM_DESC(backlight, "For objects that are lit from behind"); -static int num_uv; -module_param_array(unit_video, int, &num_uv, 0); -MODULE_PARM_DESC(unit_video, - "Force use of specific minor number(s). 0 is not allowed."); -module_param(remove_zeros, int, 0); -MODULE_PARM_DESC(remove_zeros, - "Remove zero-padding from uncompressed incoming data"); -module_param(mirror, int, 0); -MODULE_PARM_DESC(mirror, "Reverse image horizontally"); -module_param(ov518_color, int, 0); -MODULE_PARM_DESC(ov518_color, "Enable OV518 color (experimental)"); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -/********************************************************************** - * Miscellaneous Globals - **********************************************************************/ - -static struct usb_driver ov511_driver; - -/* Number of times to retry a failed I2C transaction. Increase this if you - * are getting "Failed to read sensor ID..." */ -static const int i2c_detect_tries = 5; - -static struct usb_device_id device_table [] = { - { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) }, - { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) }, - { USB_DEVICE(VEND_OMNIVISION, PROD_OV518) }, - { USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) }, - { USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, device_table); - -static unsigned char yQuanTable511[] = OV511_YQUANTABLE; -static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE; -static unsigned char yQuanTable518[] = OV518_YQUANTABLE; -static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE; - -/********************************************************************** - * Symbolic Names - **********************************************************************/ - -/* Known OV511-based cameras */ -static struct symbolic_list camlist[] = { - { 0, "Generic Camera (no ID)" }, - { 1, "Mustek WCam 3X" }, - { 3, "D-Link DSB-C300" }, - { 4, "Generic OV511/OV7610" }, - { 5, "Puretek PT-6007" }, - { 6, "Lifeview USB Life TV (NTSC)" }, - { 21, "Creative Labs WebCam 3" }, - { 22, "Lifeview USB Life TV (PAL D/K+B/G)" }, - { 36, "Koala-Cam" }, - { 38, "Lifeview USB Life TV (PAL)" }, - { 41, "Samsung Anycam MPC-M10" }, - { 43, "Mtekvision Zeca MV402" }, - { 46, "Suma eON" }, - { 70, "Lifeview USB Life TV (PAL/SECAM)" }, - { 100, "Lifeview RoboCam" }, - { 102, "AverMedia InterCam Elite" }, - { 112, "MediaForte MV300" }, /* or OV7110 evaluation kit */ - { 134, "Ezonics EZCam II" }, - { 192, "Webeye 2000B" }, - { 253, "Alpha Vision Tech. AlphaCam SE" }, - { -1, NULL } -}; - -/* Video4Linux1 Palettes */ -static struct symbolic_list v4l1_plist[] = { - { VIDEO_PALETTE_GREY, "GREY" }, - { VIDEO_PALETTE_HI240, "HI240" }, - { VIDEO_PALETTE_RGB565, "RGB565" }, - { VIDEO_PALETTE_RGB24, "RGB24" }, - { VIDEO_PALETTE_RGB32, "RGB32" }, - { VIDEO_PALETTE_RGB555, "RGB555" }, - { VIDEO_PALETTE_YUV422, "YUV422" }, - { VIDEO_PALETTE_YUYV, "YUYV" }, - { VIDEO_PALETTE_UYVY, "UYVY" }, - { VIDEO_PALETTE_YUV420, "YUV420" }, - { VIDEO_PALETTE_YUV411, "YUV411" }, - { VIDEO_PALETTE_RAW, "RAW" }, - { VIDEO_PALETTE_YUV422P,"YUV422P" }, - { VIDEO_PALETTE_YUV411P,"YUV411P" }, - { VIDEO_PALETTE_YUV420P,"YUV420P" }, - { VIDEO_PALETTE_YUV410P,"YUV410P" }, - { -1, NULL } -}; - -static struct symbolic_list brglist[] = { - { BRG_OV511, "OV511" }, - { BRG_OV511PLUS, "OV511+" }, - { BRG_OV518, "OV518" }, - { BRG_OV518PLUS, "OV518+" }, - { -1, NULL } -}; - -static struct symbolic_list senlist[] = { - { SEN_OV76BE, "OV76BE" }, - { SEN_OV7610, "OV7610" }, - { SEN_OV7620, "OV7620" }, - { SEN_OV7620AE, "OV7620AE" }, - { SEN_OV6620, "OV6620" }, - { SEN_OV6630, "OV6630" }, - { SEN_OV6630AE, "OV6630AE" }, - { SEN_OV6630AF, "OV6630AF" }, - { SEN_OV8600, "OV8600" }, - { SEN_KS0127, "KS0127" }, - { SEN_KS0127B, "KS0127B" }, - { SEN_SAA7111A, "SAA7111A" }, - { -1, NULL } -}; - -/* URB error codes: */ -static struct symbolic_list urb_errlist[] = { - { -ENOSR, "Buffer error (overrun)" }, - { -EPIPE, "Stalled (device not responding)" }, - { -EOVERFLOW, "Babble (bad cable?)" }, - { -EPROTO, "Bit-stuff error (bad cable?)" }, - { -EILSEQ, "CRC/Timeout" }, - { -ETIMEDOUT, "NAK (device does not respond)" }, - { -1, NULL } -}; - -/********************************************************************** - * Memory management - **********************************************************************/ -static void * -rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void -rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - -/********************************************************************** - * - * Register I/O - * - **********************************************************************/ - -/* Write an OV51x register */ -static int -reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value) -{ - int rc; - - PDEBUG(5, "0x%02X:0x%02X", reg, value); - - mutex_lock(&ov->cbuf_lock); - ov->cbuf[0] = value; - rc = usb_control_msg(ov->dev, - usb_sndctrlpipe(ov->dev, 0), - (ov->bclass == BCL_OV518)?1:2 /* REG_IO */, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, (__u16)reg, &ov->cbuf[0], 1, 1000); - mutex_unlock(&ov->cbuf_lock); - - if (rc < 0) - err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc)); - - return rc; -} - -/* Read from an OV51x register */ -/* returns: negative is error, pos or zero is data */ -static int -reg_r(struct usb_ov511 *ov, unsigned char reg) -{ - int rc; - - mutex_lock(&ov->cbuf_lock); - rc = usb_control_msg(ov->dev, - usb_rcvctrlpipe(ov->dev, 0), - (ov->bclass == BCL_OV518)?1:3 /* REG_IO */, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, (__u16)reg, &ov->cbuf[0], 1, 1000); - - if (rc < 0) { - err("reg read: error %d: %s", rc, symbolic(urb_errlist, rc)); - } else { - rc = ov->cbuf[0]; - PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]); - } - - mutex_unlock(&ov->cbuf_lock); - - return rc; -} - -/* - * Writes bits at positions specified by mask to an OV51x reg. Bits that are in - * the same position as 1's in "mask" are cleared and set to "value". Bits - * that are in the same position as 0's in "mask" are preserved, regardless - * of their respective state in "value". - */ -static int -reg_w_mask(struct usb_ov511 *ov, - unsigned char reg, - unsigned char value, - unsigned char mask) -{ - int ret; - unsigned char oldval, newval; - - ret = reg_r(ov, reg); - if (ret < 0) - return ret; - - oldval = (unsigned char) ret; - oldval &= (~mask); /* Clear the masked bits */ - value &= mask; /* Enforce mask on value */ - newval = oldval | value; /* Set the desired bits */ - - return (reg_w(ov, reg, newval)); -} - -/* - * Writes multiple (n) byte value to a single register. Only valid with certain - * registers (0x30 and 0xc4 - 0xce). - */ -static int -ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n) -{ - int rc; - - PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n); - - mutex_lock(&ov->cbuf_lock); - - *((__le32 *)ov->cbuf) = __cpu_to_le32(val); - - rc = usb_control_msg(ov->dev, - usb_sndctrlpipe(ov->dev, 0), - 1 /* REG_IO */, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, (__u16)reg, ov->cbuf, n, 1000); - mutex_unlock(&ov->cbuf_lock); - - if (rc < 0) - err("reg write multiple: error %d: %s", rc, - symbolic(urb_errlist, rc)); - - return rc; -} - -static int -ov511_upload_quan_tables(struct usb_ov511 *ov) -{ - unsigned char *pYTable = yQuanTable511; - unsigned char *pUVTable = uvQuanTable511; - unsigned char val0, val1; - int i, rc, reg = R511_COMP_LUT_BEGIN; - - PDEBUG(4, "Uploading quantization tables"); - - for (i = 0; i < OV511_QUANTABLESIZE / 2; i++) { - if (ENABLE_Y_QUANTABLE) { - val0 = *pYTable++; - val1 = *pYTable++; - val0 &= 0x0f; - val1 &= 0x0f; - val0 |= val1 << 4; - rc = reg_w(ov, reg, val0); - if (rc < 0) - return rc; - } - - if (ENABLE_UV_QUANTABLE) { - val0 = *pUVTable++; - val1 = *pUVTable++; - val0 &= 0x0f; - val1 &= 0x0f; - val0 |= val1 << 4; - rc = reg_w(ov, reg + OV511_QUANTABLESIZE/2, val0); - if (rc < 0) - return rc; - } - - reg++; - } - - return 0; -} - -/* OV518 quantization tables are 8x4 (instead of 8x8) */ -static int -ov518_upload_quan_tables(struct usb_ov511 *ov) -{ - unsigned char *pYTable = yQuanTable518; - unsigned char *pUVTable = uvQuanTable518; - unsigned char val0, val1; - int i, rc, reg = R511_COMP_LUT_BEGIN; - - PDEBUG(4, "Uploading quantization tables"); - - for (i = 0; i < OV518_QUANTABLESIZE / 2; i++) { - if (ENABLE_Y_QUANTABLE) { - val0 = *pYTable++; - val1 = *pYTable++; - val0 &= 0x0f; - val1 &= 0x0f; - val0 |= val1 << 4; - rc = reg_w(ov, reg, val0); - if (rc < 0) - return rc; - } - - if (ENABLE_UV_QUANTABLE) { - val0 = *pUVTable++; - val1 = *pUVTable++; - val0 &= 0x0f; - val1 &= 0x0f; - val0 |= val1 << 4; - rc = reg_w(ov, reg + OV518_QUANTABLESIZE/2, val0); - if (rc < 0) - return rc; - } - - reg++; - } - - return 0; -} - -static int -ov51x_reset(struct usb_ov511 *ov, unsigned char reset_type) -{ - int rc; - - /* Setting bit 0 not allowed on 518/518Plus */ - if (ov->bclass == BCL_OV518) - reset_type &= 0xfe; - - PDEBUG(4, "Reset: type=0x%02X", reset_type); - - rc = reg_w(ov, R51x_SYS_RESET, reset_type); - rc = reg_w(ov, R51x_SYS_RESET, 0); - - if (rc < 0) - err("reset: command failed"); - - return rc; -} - -/********************************************************************** - * - * Low-level I2C I/O functions - * - **********************************************************************/ - -/* NOTE: Do not call this function directly! - * The OV518 I2C I/O procedure is different, hence, this function. - * This is normally only called from i2c_w(). Note that this function - * always succeeds regardless of whether the sensor is present and working. - */ -static int -ov518_i2c_write_internal(struct usb_ov511 *ov, - unsigned char reg, - unsigned char value) -{ - int rc; - - PDEBUG(5, "0x%02X:0x%02X", reg, value); - - /* Select camera register */ - rc = reg_w(ov, R51x_I2C_SADDR_3, reg); - if (rc < 0) - return rc; - - /* Write "value" to I2C data port of OV511 */ - rc = reg_w(ov, R51x_I2C_DATA, value); - if (rc < 0) - return rc; - - /* Initiate 3-byte write cycle */ - rc = reg_w(ov, R518_I2C_CTL, 0x01); - if (rc < 0) - return rc; - - return 0; -} - -/* NOTE: Do not call this function directly! */ -static int -ov511_i2c_write_internal(struct usb_ov511 *ov, - unsigned char reg, - unsigned char value) -{ - int rc, retries; - - PDEBUG(5, "0x%02X:0x%02X", reg, value); - - /* Three byte write cycle */ - for (retries = OV511_I2C_RETRIES; ; ) { - /* Select camera register */ - rc = reg_w(ov, R51x_I2C_SADDR_3, reg); - if (rc < 0) - break; - - /* Write "value" to I2C data port of OV511 */ - rc = reg_w(ov, R51x_I2C_DATA, value); - if (rc < 0) - break; - - /* Initiate 3-byte write cycle */ - rc = reg_w(ov, R511_I2C_CTL, 0x01); - if (rc < 0) - break; - - /* Retry until idle */ - do - rc = reg_r(ov, R511_I2C_CTL); - while (rc > 0 && ((rc&1) == 0)); - if (rc < 0) - break; - - /* Ack? */ - if ((rc&2) == 0) { - rc = 0; - break; - } -#if 0 - /* I2C abort */ - reg_w(ov, R511_I2C_CTL, 0x10); -#endif - if (--retries < 0) { - err("i2c write retries exhausted"); - rc = -1; - break; - } - } - - return rc; -} - -/* NOTE: Do not call this function directly! - * The OV518 I2C I/O procedure is different, hence, this function. - * This is normally only called from i2c_r(). Note that this function - * always succeeds regardless of whether the sensor is present and working. - */ -static int -ov518_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg) -{ - int rc, value; - - /* Select camera register */ - rc = reg_w(ov, R51x_I2C_SADDR_2, reg); - if (rc < 0) - return rc; - - /* Initiate 2-byte write cycle */ - rc = reg_w(ov, R518_I2C_CTL, 0x03); - if (rc < 0) - return rc; - - /* Initiate 2-byte read cycle */ - rc = reg_w(ov, R518_I2C_CTL, 0x05); - if (rc < 0) - return rc; - - value = reg_r(ov, R51x_I2C_DATA); - - PDEBUG(5, "0x%02X:0x%02X", reg, value); - - return value; -} - -/* NOTE: Do not call this function directly! - * returns: negative is error, pos or zero is data */ -static int -ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg) -{ - int rc, value, retries; - - /* Two byte write cycle */ - for (retries = OV511_I2C_RETRIES; ; ) { - /* Select camera register */ - rc = reg_w(ov, R51x_I2C_SADDR_2, reg); - if (rc < 0) - return rc; - - /* Initiate 2-byte write cycle */ - rc = reg_w(ov, R511_I2C_CTL, 0x03); - if (rc < 0) - return rc; - - /* Retry until idle */ - do - rc = reg_r(ov, R511_I2C_CTL); - while (rc > 0 && ((rc&1) == 0)); - if (rc < 0) - return rc; - - if ((rc&2) == 0) /* Ack? */ - break; - - /* I2C abort */ - reg_w(ov, R511_I2C_CTL, 0x10); - - if (--retries < 0) { - err("i2c write retries exhausted"); - return -1; - } - } - - /* Two byte read cycle */ - for (retries = OV511_I2C_RETRIES; ; ) { - /* Initiate 2-byte read cycle */ - rc = reg_w(ov, R511_I2C_CTL, 0x05); - if (rc < 0) - return rc; - - /* Retry until idle */ - do - rc = reg_r(ov, R511_I2C_CTL); - while (rc > 0 && ((rc&1) == 0)); - if (rc < 0) - return rc; - - if ((rc&2) == 0) /* Ack? */ - break; - - /* I2C abort */ - rc = reg_w(ov, R511_I2C_CTL, 0x10); - if (rc < 0) - return rc; - - if (--retries < 0) { - err("i2c read retries exhausted"); - return -1; - } - } - - value = reg_r(ov, R51x_I2C_DATA); - - PDEBUG(5, "0x%02X:0x%02X", reg, value); - - /* This is needed to make i2c_w() work */ - rc = reg_w(ov, R511_I2C_CTL, 0x05); - if (rc < 0) - return rc; - - return value; -} - -/* returns: negative is error, pos or zero is data */ -static int -i2c_r(struct usb_ov511 *ov, unsigned char reg) -{ - int rc; - - mutex_lock(&ov->i2c_lock); - - if (ov->bclass == BCL_OV518) - rc = ov518_i2c_read_internal(ov, reg); - else - rc = ov511_i2c_read_internal(ov, reg); - - mutex_unlock(&ov->i2c_lock); - - return rc; -} - -static int -i2c_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value) -{ - int rc; - - mutex_lock(&ov->i2c_lock); - - if (ov->bclass == BCL_OV518) - rc = ov518_i2c_write_internal(ov, reg, value); - else - rc = ov511_i2c_write_internal(ov, reg, value); - - mutex_unlock(&ov->i2c_lock); - - return rc; -} - -/* Do not call this function directly! */ -static int -ov51x_i2c_write_mask_internal(struct usb_ov511 *ov, - unsigned char reg, - unsigned char value, - unsigned char mask) -{ - int rc; - unsigned char oldval, newval; - - if (mask == 0xff) { - newval = value; - } else { - if (ov->bclass == BCL_OV518) - rc = ov518_i2c_read_internal(ov, reg); - else - rc = ov511_i2c_read_internal(ov, reg); - if (rc < 0) - return rc; - - oldval = (unsigned char) rc; - oldval &= (~mask); /* Clear the masked bits */ - value &= mask; /* Enforce mask on value */ - newval = oldval | value; /* Set the desired bits */ - } - - if (ov->bclass == BCL_OV518) - return (ov518_i2c_write_internal(ov, reg, newval)); - else - return (ov511_i2c_write_internal(ov, reg, newval)); -} - -/* Writes bits at positions specified by mask to an I2C reg. Bits that are in - * the same position as 1's in "mask" are cleared and set to "value". Bits - * that are in the same position as 0's in "mask" are preserved, regardless - * of their respective state in "value". - */ -static int -i2c_w_mask(struct usb_ov511 *ov, - unsigned char reg, - unsigned char value, - unsigned char mask) -{ - int rc; - - mutex_lock(&ov->i2c_lock); - rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask); - mutex_unlock(&ov->i2c_lock); - - return rc; -} - -/* Set the read and write slave IDs. The "slave" argument is the write slave, - * and the read slave will be set to (slave + 1). ov->i2c_lock should be held - * when calling this. This should not be called from outside the i2c I/O - * functions. - */ -static int -i2c_set_slave_internal(struct usb_ov511 *ov, unsigned char slave) -{ - int rc; - - rc = reg_w(ov, R51x_I2C_W_SID, slave); - if (rc < 0) - return rc; - - rc = reg_w(ov, R51x_I2C_R_SID, slave + 1); - if (rc < 0) - return rc; - - return 0; -} - -/* Write to a specific I2C slave ID and register, using the specified mask */ -static int -i2c_w_slave(struct usb_ov511 *ov, - unsigned char slave, - unsigned char reg, - unsigned char value, - unsigned char mask) -{ - int rc = 0; - - mutex_lock(&ov->i2c_lock); - - /* Set new slave IDs */ - rc = i2c_set_slave_internal(ov, slave); - if (rc < 0) - goto out; - - rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask); - -out: - /* Restore primary IDs */ - if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) - err("Couldn't restore primary I2C slave"); - - mutex_unlock(&ov->i2c_lock); - return rc; -} - -/* Read from a specific I2C slave ID and register */ -static int -i2c_r_slave(struct usb_ov511 *ov, - unsigned char slave, - unsigned char reg) -{ - int rc; - - mutex_lock(&ov->i2c_lock); - - /* Set new slave IDs */ - rc = i2c_set_slave_internal(ov, slave); - if (rc < 0) - goto out; - - if (ov->bclass == BCL_OV518) - rc = ov518_i2c_read_internal(ov, reg); - else - rc = ov511_i2c_read_internal(ov, reg); - -out: - /* Restore primary IDs */ - if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) - err("Couldn't restore primary I2C slave"); - - mutex_unlock(&ov->i2c_lock); - return rc; -} - -/* Sets I2C read and write slave IDs. Returns <0 for error */ -static int -ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid) -{ - int rc; - - mutex_lock(&ov->i2c_lock); - - rc = i2c_set_slave_internal(ov, sid); - if (rc < 0) - goto out; - - // FIXME: Is this actually necessary? - rc = ov51x_reset(ov, OV511_RESET_NOREGS); -out: - mutex_unlock(&ov->i2c_lock); - return rc; -} - -static int -write_regvals(struct usb_ov511 *ov, struct ov511_regvals * pRegvals) -{ - int rc; - - while (pRegvals->bus != OV511_DONE_BUS) { - if (pRegvals->bus == OV511_REG_BUS) { - if ((rc = reg_w(ov, pRegvals->reg, pRegvals->val)) < 0) - return rc; - } else if (pRegvals->bus == OV511_I2C_BUS) { - if ((rc = i2c_w(ov, pRegvals->reg, pRegvals->val)) < 0) - return rc; - } else { - err("Bad regval array"); - return -1; - } - pRegvals++; - } - return 0; -} - -#ifdef OV511_DEBUG -static void -dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn) -{ - int i, rc; - - for (i = reg1; i <= regn; i++) { - rc = i2c_r(ov, i); - info("Sensor[0x%02X] = 0x%02X", i, rc); - } -} - -static void -dump_i2c_regs(struct usb_ov511 *ov) -{ - info("I2C REGS"); - dump_i2c_range(ov, 0x00, 0x7C); -} - -static void -dump_reg_range(struct usb_ov511 *ov, int reg1, int regn) -{ - int i, rc; - - for (i = reg1; i <= regn; i++) { - rc = reg_r(ov, i); - info("OV511[0x%02X] = 0x%02X", i, rc); - } -} - -static void -ov511_dump_regs(struct usb_ov511 *ov) -{ - info("CAMERA INTERFACE REGS"); - dump_reg_range(ov, 0x10, 0x1f); - info("DRAM INTERFACE REGS"); - dump_reg_range(ov, 0x20, 0x23); - info("ISO FIFO REGS"); - dump_reg_range(ov, 0x30, 0x31); - info("PIO REGS"); - dump_reg_range(ov, 0x38, 0x39); - dump_reg_range(ov, 0x3e, 0x3e); - info("I2C REGS"); - dump_reg_range(ov, 0x40, 0x49); - info("SYSTEM CONTROL REGS"); - dump_reg_range(ov, 0x50, 0x55); - dump_reg_range(ov, 0x5e, 0x5f); - info("OmniCE REGS"); - dump_reg_range(ov, 0x70, 0x79); - /* NOTE: Quantization tables are not readable. You will get the value - * in reg. 0x79 for every table register */ - dump_reg_range(ov, 0x80, 0x9f); - dump_reg_range(ov, 0xa0, 0xbf); - -} - -static void -ov518_dump_regs(struct usb_ov511 *ov) -{ - info("VIDEO MODE REGS"); - dump_reg_range(ov, 0x20, 0x2f); - info("DATA PUMP AND SNAPSHOT REGS"); - dump_reg_range(ov, 0x30, 0x3f); - info("I2C REGS"); - dump_reg_range(ov, 0x40, 0x4f); - info("SYSTEM CONTROL AND VENDOR REGS"); - dump_reg_range(ov, 0x50, 0x5f); - info("60 - 6F"); - dump_reg_range(ov, 0x60, 0x6f); - info("70 - 7F"); - dump_reg_range(ov, 0x70, 0x7f); - info("Y QUANTIZATION TABLE"); - dump_reg_range(ov, 0x80, 0x8f); - info("UV QUANTIZATION TABLE"); - dump_reg_range(ov, 0x90, 0x9f); - info("A0 - BF"); - dump_reg_range(ov, 0xa0, 0xbf); - info("CBR"); - dump_reg_range(ov, 0xc0, 0xcf); -} -#endif - -/*****************************************************************************/ - -/* Temporarily stops OV511 from functioning. Must do this before changing - * registers while the camera is streaming */ -static inline int -ov51x_stop(struct usb_ov511 *ov) -{ - PDEBUG(4, "stopping"); - ov->stopped = 1; - if (ov->bclass == BCL_OV518) - return (reg_w_mask(ov, R51x_SYS_RESET, 0x3a, 0x3a)); - else - return (reg_w(ov, R51x_SYS_RESET, 0x3d)); -} - -/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not - * actually stopped (for performance). */ -static inline int -ov51x_restart(struct usb_ov511 *ov) -{ - if (ov->stopped) { - PDEBUG(4, "restarting"); - ov->stopped = 0; - - /* Reinitialize the stream */ - if (ov->bclass == BCL_OV518) - reg_w(ov, 0x2f, 0x80); - - return (reg_w(ov, R51x_SYS_RESET, 0x00)); - } - - return 0; -} - -/* Sleeps until no frames are active. Returns !0 if got signal */ -static int -ov51x_wait_frames_inactive(struct usb_ov511 *ov) -{ - return wait_event_interruptible(ov->wq, ov->curframe < 0); -} - -/* Resets the hardware snapshot button */ -static void -ov51x_clear_snapshot(struct usb_ov511 *ov) -{ - if (ov->bclass == BCL_OV511) { - reg_w(ov, R51x_SYS_SNAP, 0x00); - reg_w(ov, R51x_SYS_SNAP, 0x02); - reg_w(ov, R51x_SYS_SNAP, 0x00); - } else if (ov->bclass == BCL_OV518) { - warn("snapshot reset not supported yet on OV518(+)"); - } else { - err("clear snap: invalid bridge type"); - } -} - -#if 0 -/* Checks the status of the snapshot button. Returns 1 if it was pressed since - * it was last cleared, and zero in all other cases (including errors) */ -static int -ov51x_check_snapshot(struct usb_ov511 *ov) -{ - int ret, status = 0; - - if (ov->bclass == BCL_OV511) { - ret = reg_r(ov, R51x_SYS_SNAP); - if (ret < 0) { - err("Error checking snspshot status (%d)", ret); - } else if (ret & 0x08) { - status = 1; - } - } else if (ov->bclass == BCL_OV518) { - warn("snapshot check not supported yet on OV518(+)"); - } else { - err("check snap: invalid bridge type"); - } - - return status; -} -#endif - -/* This does an initial reset of an OmniVision sensor and ensures that I2C - * is synchronized. Returns <0 for failure. - */ -static int -init_ov_sensor(struct usb_ov511 *ov) -{ - int i, success; - - /* Reset the sensor */ - if (i2c_w(ov, 0x12, 0x80) < 0) - return -EIO; - - /* Wait for it to initialize */ - msleep(150); - - for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) { - if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) && - (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) { - success = 1; - continue; - } - - /* Reset the sensor */ - if (i2c_w(ov, 0x12, 0x80) < 0) - return -EIO; - /* Wait for it to initialize */ - msleep(150); - /* Dummy read to sync I2C */ - if (i2c_r(ov, 0x00) < 0) - return -EIO; - } - - if (!success) - return -EIO; - - PDEBUG(1, "I2C synced in %d attempt(s)", i); - - return 0; -} - -static int -ov511_set_packet_size(struct usb_ov511 *ov, int size) -{ - int alt, mult; - - if (ov51x_stop(ov) < 0) - return -EIO; - - mult = size >> 5; - - if (ov->bridge == BRG_OV511) { - if (size == 0) - alt = OV511_ALT_SIZE_0; - else if (size == 257) - alt = OV511_ALT_SIZE_257; - else if (size == 513) - alt = OV511_ALT_SIZE_513; - else if (size == 769) - alt = OV511_ALT_SIZE_769; - else if (size == 993) - alt = OV511_ALT_SIZE_993; - else { - err("Set packet size: invalid size (%d)", size); - return -EINVAL; - } - } else if (ov->bridge == BRG_OV511PLUS) { - if (size == 0) - alt = OV511PLUS_ALT_SIZE_0; - else if (size == 33) - alt = OV511PLUS_ALT_SIZE_33; - else if (size == 129) - alt = OV511PLUS_ALT_SIZE_129; - else if (size == 257) - alt = OV511PLUS_ALT_SIZE_257; - else if (size == 385) - alt = OV511PLUS_ALT_SIZE_385; - else if (size == 513) - alt = OV511PLUS_ALT_SIZE_513; - else if (size == 769) - alt = OV511PLUS_ALT_SIZE_769; - else if (size == 961) - alt = OV511PLUS_ALT_SIZE_961; - else { - err("Set packet size: invalid size (%d)", size); - return -EINVAL; - } - } else { - err("Set packet size: Invalid bridge type"); - return -EINVAL; - } - - PDEBUG(3, "%d, mult=%d, alt=%d", size, mult, alt); - - if (reg_w(ov, R51x_FIFO_PSIZE, mult) < 0) - return -EIO; - - if (usb_set_interface(ov->dev, ov->iface, alt) < 0) { - err("Set packet size: set interface error"); - return -EBUSY; - } - - if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) - return -EIO; - - ov->packet_size = size; - - if (ov51x_restart(ov) < 0) - return -EIO; - - return 0; -} - -/* Note: Unlike the OV511/OV511+, the size argument does NOT include the - * optional packet number byte. The actual size *is* stored in ov->packet_size, - * though. */ -static int -ov518_set_packet_size(struct usb_ov511 *ov, int size) -{ - int alt; - - if (ov51x_stop(ov) < 0) - return -EIO; - - if (ov->bclass == BCL_OV518) { - if (size == 0) - alt = OV518_ALT_SIZE_0; - else if (size == 128) - alt = OV518_ALT_SIZE_128; - else if (size == 256) - alt = OV518_ALT_SIZE_256; - else if (size == 384) - alt = OV518_ALT_SIZE_384; - else if (size == 512) - alt = OV518_ALT_SIZE_512; - else if (size == 640) - alt = OV518_ALT_SIZE_640; - else if (size == 768) - alt = OV518_ALT_SIZE_768; - else if (size == 896) - alt = OV518_ALT_SIZE_896; - else { - err("Set packet size: invalid size (%d)", size); - return -EINVAL; - } - } else { - err("Set packet size: Invalid bridge type"); - return -EINVAL; - } - - PDEBUG(3, "%d, alt=%d", size, alt); - - ov->packet_size = size; - if (size > 0) { - /* Program ISO FIFO size reg (packet number isn't included) */ - ov518_reg_w32(ov, 0x30, size, 2); - - if (ov->packet_numbering) - ++ov->packet_size; - } - - if (usb_set_interface(ov->dev, ov->iface, alt) < 0) { - err("Set packet size: set interface error"); - return -EBUSY; - } - - /* Initialize the stream */ - if (reg_w(ov, 0x2f, 0x80) < 0) - return -EIO; - - if (ov51x_restart(ov) < 0) - return -EIO; - - if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) - return -EIO; - - return 0; -} - -/* Upload compression params and quantization tables. Returns 0 for success. */ -static int -ov511_init_compression(struct usb_ov511 *ov) -{ - int rc = 0; - - if (!ov->compress_inited) { - reg_w(ov, 0x70, phy); - reg_w(ov, 0x71, phuv); - reg_w(ov, 0x72, pvy); - reg_w(ov, 0x73, pvuv); - reg_w(ov, 0x74, qhy); - reg_w(ov, 0x75, qhuv); - reg_w(ov, 0x76, qvy); - reg_w(ov, 0x77, qvuv); - - if (ov511_upload_quan_tables(ov) < 0) { - err("Error uploading quantization tables"); - rc = -EIO; - goto out; - } - } - - ov->compress_inited = 1; -out: - return rc; -} - -/* Upload compression params and quantization tables. Returns 0 for success. */ -static int -ov518_init_compression(struct usb_ov511 *ov) -{ - int rc = 0; - - if (!ov->compress_inited) { - if (ov518_upload_quan_tables(ov) < 0) { - err("Error uploading quantization tables"); - rc = -EIO; - goto out; - } - } - - ov->compress_inited = 1; -out: - return rc; -} - -/* -------------------------------------------------------------------------- */ - -/* Sets sensor's contrast setting to "val" */ -static int -sensor_set_contrast(struct usb_ov511 *ov, unsigned short val) -{ - int rc; - - PDEBUG(3, "%d", val); - - if (ov->stop_during_set) - if (ov51x_stop(ov) < 0) - return -EIO; - - switch (ov->sensor) { - case SEN_OV7610: - case SEN_OV6620: - { - rc = i2c_w(ov, OV7610_REG_CNT, val >> 8); - if (rc < 0) - goto out; - break; - } - case SEN_OV6630: - { - rc = i2c_w_mask(ov, OV7610_REG_CNT, val >> 12, 0x0f); - if (rc < 0) - goto out; - break; - } - case SEN_OV7620: - { - unsigned char ctab[] = { - 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, - 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff - }; - - /* Use Y gamma control instead. Bit 0 enables it. */ - rc = i2c_w(ov, 0x64, ctab[val>>12]); - if (rc < 0) - goto out; - break; - } - case SEN_SAA7111A: - { - rc = i2c_w(ov, 0x0b, val >> 9); - if (rc < 0) - goto out; - break; - } - default: - { - PDEBUG(3, "Unsupported with this sensor"); - rc = -EPERM; - goto out; - } - } - - rc = 0; /* Success */ - ov->contrast = val; -out: - if (ov51x_restart(ov) < 0) - return -EIO; - - return rc; -} - -/* Gets sensor's contrast setting */ -static int -sensor_get_contrast(struct usb_ov511 *ov, unsigned short *val) -{ - int rc; - - switch (ov->sensor) { - case SEN_OV7610: - case SEN_OV6620: - rc = i2c_r(ov, OV7610_REG_CNT); - if (rc < 0) - return rc; - else - *val = rc << 8; - break; - case SEN_OV6630: - rc = i2c_r(ov, OV7610_REG_CNT); - if (rc < 0) - return rc; - else - *val = rc << 12; - break; - case SEN_OV7620: - /* Use Y gamma reg instead. Bit 0 is the enable bit. */ - rc = i2c_r(ov, 0x64); - if (rc < 0) - return rc; - else - *val = (rc & 0xfe) << 8; - break; - case SEN_SAA7111A: - *val = ov->contrast; - break; - default: - PDEBUG(3, "Unsupported with this sensor"); - return -EPERM; - } - - PDEBUG(3, "%d", *val); - ov->contrast = *val; - - return 0; -} - -/* -------------------------------------------------------------------------- */ - -/* Sets sensor's brightness setting to "val" */ -static int -sensor_set_brightness(struct usb_ov511 *ov, unsigned short val) -{ - int rc; - - PDEBUG(4, "%d", val); - - if (ov->stop_during_set) - if (ov51x_stop(ov) < 0) - return -EIO; - - switch (ov->sensor) { - case SEN_OV7610: - case SEN_OV76BE: - case SEN_OV6620: - case SEN_OV6630: - rc = i2c_w(ov, OV7610_REG_BRT, val >> 8); - if (rc < 0) - goto out; - break; - case SEN_OV7620: - /* 7620 doesn't like manual changes when in auto mode */ - if (!ov->auto_brt) { - rc = i2c_w(ov, OV7610_REG_BRT, val >> 8); - if (rc < 0) - goto out; - } - break; - case SEN_SAA7111A: - rc = i2c_w(ov, 0x0a, val >> 8); - if (rc < 0) - goto out; - break; - default: - PDEBUG(3, "Unsupported with this sensor"); - rc = -EPERM; - goto out; - } - - rc = 0; /* Success */ - ov->brightness = val; -out: - if (ov51x_restart(ov) < 0) - return -EIO; - - return rc; -} - -/* Gets sensor's brightness setting */ -static int -sensor_get_brightness(struct usb_ov511 *ov, unsigned short *val) -{ - int rc; - - switch (ov->sensor) { - case SEN_OV7610: - case SEN_OV76BE: - case SEN_OV7620: - case SEN_OV6620: - case SEN_OV6630: - rc = i2c_r(ov, OV7610_REG_BRT); - if (rc < 0) - return rc; - else - *val = rc << 8; - break; - case SEN_SAA7111A: - *val = ov->brightness; - break; - default: - PDEBUG(3, "Unsupported with this sensor"); - return -EPERM; - } - - PDEBUG(3, "%d", *val); - ov->brightness = *val; - - return 0; -} - -/* -------------------------------------------------------------------------- */ - -/* Sets sensor's saturation (color intensity) setting to "val" */ -static int -sensor_set_saturation(struct usb_ov511 *ov, unsigned short val) -{ - int rc; - - PDEBUG(3, "%d", val); - - if (ov->stop_during_set) - if (ov51x_stop(ov) < 0) - return -EIO; - - switch (ov->sensor) { - case SEN_OV7610: - case SEN_OV76BE: - case SEN_OV6620: - case SEN_OV6630: - rc = i2c_w(ov, OV7610_REG_SAT, val >> 8); - if (rc < 0) - goto out; - break; - case SEN_OV7620: -// /* Use UV gamma control instead. Bits 0 & 7 are reserved. */ -// rc = ov_i2c_write(ov->dev, 0x62, (val >> 9) & 0x7e); -// if (rc < 0) -// goto out; - rc = i2c_w(ov, OV7610_REG_SAT, val >> 8); - if (rc < 0) - goto out; - break; - case SEN_SAA7111A: - rc = i2c_w(ov, 0x0c, val >> 9); - if (rc < 0) - goto out; - break; - default: - PDEBUG(3, "Unsupported with this sensor"); - rc = -EPERM; - goto out; - } - - rc = 0; /* Success */ - ov->colour = val; -out: - if (ov51x_restart(ov) < 0) - return -EIO; - - return rc; -} - -/* Gets sensor's saturation (color intensity) setting */ -static int -sensor_get_saturation(struct usb_ov511 *ov, unsigned short *val) -{ - int rc; - - switch (ov->sensor) { - case SEN_OV7610: - case SEN_OV76BE: - case SEN_OV6620: - case SEN_OV6630: - rc = i2c_r(ov, OV7610_REG_SAT); - if (rc < 0) - return rc; - else - *val = rc << 8; - break; - case SEN_OV7620: -// /* Use UV gamma reg instead. Bits 0 & 7 are reserved. */ -// rc = i2c_r(ov, 0x62); -// if (rc < 0) -// return rc; -// else -// *val = (rc & 0x7e) << 9; - rc = i2c_r(ov, OV7610_REG_SAT); - if (rc < 0) - return rc; - else - *val = rc << 8; - break; - case SEN_SAA7111A: - *val = ov->colour; - break; - default: - PDEBUG(3, "Unsupported with this sensor"); - return -EPERM; - } - - PDEBUG(3, "%d", *val); - ov->colour = *val; - - return 0; -} - -/* -------------------------------------------------------------------------- */ - -/* Sets sensor's hue (red/blue balance) setting to "val" */ -static int -sensor_set_hue(struct usb_ov511 *ov, unsigned short val) -{ - int rc; - - PDEBUG(3, "%d", val); - - if (ov->stop_during_set) - if (ov51x_stop(ov) < 0) - return -EIO; - - switch (ov->sensor) { - case SEN_OV7610: - case SEN_OV6620: - case SEN_OV6630: - rc = i2c_w(ov, OV7610_REG_RED, 0xFF - (val >> 8)); - if (rc < 0) - goto out; - - rc = i2c_w(ov, OV7610_REG_BLUE, val >> 8); - if (rc < 0) - goto out; - break; - case SEN_OV7620: -// Hue control is causing problems. I will enable it once it's fixed. -#if 0 - rc = i2c_w(ov, 0x7a, (unsigned char)(val >> 8) + 0xb); - if (rc < 0) - goto out; - - rc = i2c_w(ov, 0x79, (unsigned char)(val >> 8) + 0xb); - if (rc < 0) - goto out; -#endif - break; - case SEN_SAA7111A: - rc = i2c_w(ov, 0x0d, (val + 32768) >> 8); - if (rc < 0) - goto out; - break; - default: - PDEBUG(3, "Unsupported with this sensor"); - rc = -EPERM; - goto out; - } - - rc = 0; /* Success */ - ov->hue = val; -out: - if (ov51x_restart(ov) < 0) - return -EIO; - - return rc; -} - -/* Gets sensor's hue (red/blue balance) setting */ -static int -sensor_get_hue(struct usb_ov511 *ov, unsigned short *val) -{ - int rc; - - switch (ov->sensor) { - case SEN_OV7610: - case SEN_OV6620: - case SEN_OV6630: - rc = i2c_r(ov, OV7610_REG_BLUE); - if (rc < 0) - return rc; - else - *val = rc << 8; - break; - case SEN_OV7620: - rc = i2c_r(ov, 0x7a); - if (rc < 0) - return rc; - else - *val = rc << 8; - break; - case SEN_SAA7111A: - *val = ov->hue; - break; - default: - PDEBUG(3, "Unsupported with this sensor"); - return -EPERM; - } - - PDEBUG(3, "%d", *val); - ov->hue = *val; - - return 0; -} - -/* -------------------------------------------------------------------------- */ - -static int -sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p) -{ - int rc; - - PDEBUG(4, "sensor_set_picture"); - - ov->whiteness = p->whiteness; - - /* Don't return error if a setting is unsupported, or rest of settings - * will not be performed */ - - rc = sensor_set_contrast(ov, p->contrast); - if (FATAL_ERROR(rc)) - return rc; - - rc = sensor_set_brightness(ov, p->brightness); - if (FATAL_ERROR(rc)) - return rc; - - rc = sensor_set_saturation(ov, p->colour); - if (FATAL_ERROR(rc)) - return rc; - - rc = sensor_set_hue(ov, p->hue); - if (FATAL_ERROR(rc)) - return rc; - - return 0; -} - -static int -sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p) -{ - int rc; - - PDEBUG(4, "sensor_get_picture"); - - /* Don't return error if a setting is unsupported, or rest of settings - * will not be performed */ - - rc = sensor_get_contrast(ov, &(p->contrast)); - if (FATAL_ERROR(rc)) - return rc; - - rc = sensor_get_brightness(ov, &(p->brightness)); - if (FATAL_ERROR(rc)) - return rc; - - rc = sensor_get_saturation(ov, &(p->colour)); - if (FATAL_ERROR(rc)) - return rc; - - rc = sensor_get_hue(ov, &(p->hue)); - if (FATAL_ERROR(rc)) - return rc; - - p->whiteness = 105 << 8; - - return 0; -} - -#if 0 -// FIXME: Exposure range is only 0x00-0x7f in interlace mode -/* Sets current exposure for sensor. This only has an effect if auto-exposure - * is off */ -static inline int -sensor_set_exposure(struct usb_ov511 *ov, unsigned char val) -{ - int rc; - - PDEBUG(3, "%d", val); - - if (ov->stop_during_set) - if (ov51x_stop(ov) < 0) - return -EIO; - - switch (ov->sensor) { - case SEN_OV6620: - case SEN_OV6630: - case SEN_OV7610: - case SEN_OV7620: - case SEN_OV76BE: - case SEN_OV8600: - rc = i2c_w(ov, 0x10, val); - if (rc < 0) - goto out; - - break; - case SEN_KS0127: - case SEN_KS0127B: - case SEN_SAA7111A: - PDEBUG(3, "Unsupported with this sensor"); - return -EPERM; - default: - err("Sensor not supported for set_exposure"); - return -EINVAL; - } - - rc = 0; /* Success */ - ov->exposure = val; -out: - if (ov51x_restart(ov) < 0) - return -EIO; - - return rc; -} -#endif - -/* Gets current exposure level from sensor, regardless of whether it is under - * manual control. */ -static int -sensor_get_exposure(struct usb_ov511 *ov, unsigned char *val) -{ - int rc; - - switch (ov->sensor) { - case SEN_OV7610: - case SEN_OV6620: - case SEN_OV6630: - case SEN_OV7620: - case SEN_OV76BE: - case SEN_OV8600: - rc = i2c_r(ov, 0x10); - if (rc < 0) - return rc; - else - *val = rc; - break; - case SEN_KS0127: - case SEN_KS0127B: - case SEN_SAA7111A: - val = NULL; - PDEBUG(3, "Unsupported with this sensor"); - return -EPERM; - default: - err("Sensor not supported for get_exposure"); - return -EINVAL; - } - - PDEBUG(3, "%d", *val); - ov->exposure = *val; - - return 0; -} - -/* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */ -static void -ov51x_led_control(struct usb_ov511 *ov, int enable) -{ - PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); - - if (ov->bridge == BRG_OV511PLUS) - reg_w(ov, R511_SYS_LED_CTL, enable ? 1 : 0); - else if (ov->bclass == BCL_OV518) - reg_w_mask(ov, R518_GPIO_OUT, enable ? 0x02 : 0x00, 0x02); - - return; -} - -/* Matches the sensor's internal frame rate to the lighting frequency. - * Valid frequencies are: - * 50 - 50Hz, for European and Asian lighting - * 60 - 60Hz, for American lighting - * - * Tested with: OV7610, OV7620, OV76BE, OV6620 - * Unsupported: KS0127, KS0127B, SAA7111A - * Returns: 0 for success - */ -static int -sensor_set_light_freq(struct usb_ov511 *ov, int freq) -{ - int sixty; - - PDEBUG(4, "%d Hz", freq); - - if (freq == 60) - sixty = 1; - else if (freq == 50) - sixty = 0; - else { - err("Invalid light freq (%d Hz)", freq); - return -EINVAL; - } - - switch (ov->sensor) { - case SEN_OV7610: - i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80); - i2c_w(ov, 0x2b, sixty?0x00:0xac); - i2c_w_mask(ov, 0x13, 0x10, 0x10); - i2c_w_mask(ov, 0x13, 0x00, 0x10); - break; - case SEN_OV7620: - case SEN_OV76BE: - case SEN_OV8600: - i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80); - i2c_w(ov, 0x2b, sixty?0x00:0xac); - i2c_w_mask(ov, 0x76, 0x01, 0x01); - break; - case SEN_OV6620: - case SEN_OV6630: - i2c_w(ov, 0x2b, sixty?0xa8:0x28); - i2c_w(ov, 0x2a, sixty?0x84:0xa4); - break; - case SEN_KS0127: - case SEN_KS0127B: - case SEN_SAA7111A: - PDEBUG(5, "Unsupported with this sensor"); - return -EPERM; - default: - err("Sensor not supported for set_light_freq"); - return -EINVAL; - } - - ov->lightfreq = freq; - - return 0; -} - -/* If enable is true, turn on the sensor's banding filter, otherwise turn it - * off. This filter tries to reduce the pattern of horizontal light/dark bands - * caused by some (usually fluorescent) lighting. The light frequency must be - * set either before or after enabling it with ov51x_set_light_freq(). - * - * Tested with: OV7610, OV7620, OV76BE, OV6620. - * Unsupported: KS0127, KS0127B, SAA7111A - * Returns: 0 for success - */ -static int -sensor_set_banding_filter(struct usb_ov511 *ov, int enable) -{ - int rc; - - PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); - - if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B - || ov->sensor == SEN_SAA7111A) { - PDEBUG(5, "Unsupported with this sensor"); - return -EPERM; - } - - rc = i2c_w_mask(ov, 0x2d, enable?0x04:0x00, 0x04); - if (rc < 0) - return rc; - - ov->bandfilt = enable; - - return 0; -} - -/* If enable is true, turn on the sensor's auto brightness control, otherwise - * turn it off. - * - * Unsupported: KS0127, KS0127B, SAA7111A - * Returns: 0 for success - */ -static int -sensor_set_auto_brightness(struct usb_ov511 *ov, int enable) -{ - int rc; - - PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); - - if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B - || ov->sensor == SEN_SAA7111A) { - PDEBUG(5, "Unsupported with this sensor"); - return -EPERM; - } - - rc = i2c_w_mask(ov, 0x2d, enable?0x10:0x00, 0x10); - if (rc < 0) - return rc; - - ov->auto_brt = enable; - - return 0; -} - -/* If enable is true, turn on the sensor's auto exposure control, otherwise - * turn it off. - * - * Unsupported: KS0127, KS0127B, SAA7111A - * Returns: 0 for success - */ -static int -sensor_set_auto_exposure(struct usb_ov511 *ov, int enable) -{ - PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); - - switch (ov->sensor) { - case SEN_OV7610: - i2c_w_mask(ov, 0x29, enable?0x00:0x80, 0x80); - break; - case SEN_OV6620: - case SEN_OV7620: - case SEN_OV76BE: - case SEN_OV8600: - i2c_w_mask(ov, 0x13, enable?0x01:0x00, 0x01); - break; - case SEN_OV6630: - i2c_w_mask(ov, 0x28, enable?0x00:0x10, 0x10); - break; - case SEN_KS0127: - case SEN_KS0127B: - case SEN_SAA7111A: - PDEBUG(5, "Unsupported with this sensor"); - return -EPERM; - default: - err("Sensor not supported for set_auto_exposure"); - return -EINVAL; - } - - ov->auto_exp = enable; - - return 0; -} - -/* Modifies the sensor's exposure algorithm to allow proper exposure of objects - * that are illuminated from behind. - * - * Tested with: OV6620, OV7620 - * Unsupported: OV7610, OV76BE, KS0127, KS0127B, SAA7111A - * Returns: 0 for success - */ -static int -sensor_set_backlight(struct usb_ov511 *ov, int enable) -{ - PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); - - switch (ov->sensor) { - case SEN_OV7620: - case SEN_OV8600: - i2c_w_mask(ov, 0x68, enable?0xe0:0xc0, 0xe0); - i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); - i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02); - break; - case SEN_OV6620: - i2c_w_mask(ov, 0x4e, enable?0xe0:0xc0, 0xe0); - i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); - i2c_w_mask(ov, 0x0e, enable?0x80:0x00, 0x80); - break; - case SEN_OV6630: - i2c_w_mask(ov, 0x4e, enable?0x80:0x60, 0xe0); - i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); - i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02); - break; - case SEN_OV7610: - case SEN_OV76BE: - case SEN_KS0127: - case SEN_KS0127B: - case SEN_SAA7111A: - PDEBUG(5, "Unsupported with this sensor"); - return -EPERM; - default: - err("Sensor not supported for set_backlight"); - return -EINVAL; - } - - ov->backlight = enable; - - return 0; -} - -static int -sensor_set_mirror(struct usb_ov511 *ov, int enable) -{ - PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); - - switch (ov->sensor) { - case SEN_OV6620: - case SEN_OV6630: - case SEN_OV7610: - case SEN_OV7620: - case SEN_OV76BE: - case SEN_OV8600: - i2c_w_mask(ov, 0x12, enable?0x40:0x00, 0x40); - break; - case SEN_KS0127: - case SEN_KS0127B: - case SEN_SAA7111A: - PDEBUG(5, "Unsupported with this sensor"); - return -EPERM; - default: - err("Sensor not supported for set_mirror"); - return -EINVAL; - } - - ov->mirror = enable; - - return 0; -} - -/* Returns number of bits per pixel (regardless of where they are located; - * planar or not), or zero for unsupported format. - */ -static inline int -get_depth(int palette) -{ - switch (palette) { - case VIDEO_PALETTE_GREY: return 8; - case VIDEO_PALETTE_YUV420: return 12; - case VIDEO_PALETTE_YUV420P: return 12; /* Planar */ - default: return 0; /* Invalid format */ - } -} - -/* Bytes per frame. Used by read(). Return of 0 indicates error */ -static inline long int -get_frame_length(struct ov511_frame *frame) -{ - if (!frame) - return 0; - else - return ((frame->width * frame->height - * get_depth(frame->format)) >> 3); -} - -static int -mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height, - int mode, int sub_flag, int qvga) -{ - int clock; - - /******** Mode (VGA/QVGA) and sensor specific regs ********/ - - switch (ov->sensor) { - case SEN_OV7610: - i2c_w(ov, 0x14, qvga?0x24:0x04); -// FIXME: Does this improve the image quality or frame rate? -#if 0 - i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); - i2c_w(ov, 0x24, 0x10); - i2c_w(ov, 0x25, qvga?0x40:0x8a); - i2c_w(ov, 0x2f, qvga?0x30:0xb0); - i2c_w(ov, 0x35, qvga?0x1c:0x9c); -#endif - break; - case SEN_OV7620: -// i2c_w(ov, 0x2b, 0x00); - i2c_w(ov, 0x14, qvga?0xa4:0x84); - i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); - i2c_w(ov, 0x24, qvga?0x20:0x3a); - i2c_w(ov, 0x25, qvga?0x30:0x60); - i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40); - i2c_w_mask(ov, 0x67, qvga?0xf0:0x90, 0xf0); - i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20); - break; - case SEN_OV76BE: -// i2c_w(ov, 0x2b, 0x00); - i2c_w(ov, 0x14, qvga?0xa4:0x84); -// FIXME: Enable this once 7620AE uses 7620 initial settings -#if 0 - i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); - i2c_w(ov, 0x24, qvga?0x20:0x3a); - i2c_w(ov, 0x25, qvga?0x30:0x60); - i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40); - i2c_w_mask(ov, 0x67, qvga?0xb0:0x90, 0xf0); - i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20); -#endif - break; - case SEN_OV6620: - i2c_w(ov, 0x14, qvga?0x24:0x04); - break; - case SEN_OV6630: - i2c_w(ov, 0x14, qvga?0xa0:0x80); - break; - default: - err("Invalid sensor"); - return -EINVAL; - } - - /******** Palette-specific regs ********/ - - if (mode == VIDEO_PALETTE_GREY) { - if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { - /* these aren't valid on the OV6620/OV7620/6630? */ - i2c_w_mask(ov, 0x0e, 0x40, 0x40); - } - - if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 - && ov518_color) { - i2c_w_mask(ov, 0x12, 0x00, 0x10); - i2c_w_mask(ov, 0x13, 0x00, 0x20); - } else { - i2c_w_mask(ov, 0x13, 0x20, 0x20); - } - } else { - if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { - /* not valid on the OV6620/OV7620/6630? */ - i2c_w_mask(ov, 0x0e, 0x00, 0x40); - } - - /* The OV518 needs special treatment. Although both the OV518 - * and the OV6630 support a 16-bit video bus, only the 8 bit Y - * bus is actually used. The UV bus is tied to ground. - * Therefore, the OV6630 needs to be in 8-bit multiplexed - * output mode */ - - if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 - && ov518_color) { - i2c_w_mask(ov, 0x12, 0x10, 0x10); - i2c_w_mask(ov, 0x13, 0x20, 0x20); - } else { - i2c_w_mask(ov, 0x13, 0x00, 0x20); - } - } - - /******** Clock programming ********/ - - /* The OV6620 needs special handling. This prevents the - * severe banding that normally occurs */ - if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) - { - /* Clock down */ - - i2c_w(ov, 0x2a, 0x04); - - if (ov->compress) { -// clock = 0; /* This ensures the highest frame rate */ - clock = 3; - } else if (clockdiv == -1) { /* If user didn't override it */ - clock = 3; /* Gives better exposure time */ - } else { - clock = clockdiv; - } - - PDEBUG(4, "Setting clock divisor to %d", clock); - - i2c_w(ov, 0x11, clock); - - i2c_w(ov, 0x2a, 0x84); - /* This next setting is critical. It seems to improve - * the gain or the contrast. The "reserved" bits seem - * to have some effect in this case. */ - i2c_w(ov, 0x2d, 0x85); - } - else - { - if (ov->compress) { - clock = 1; /* This ensures the highest frame rate */ - } else if (clockdiv == -1) { /* If user didn't override it */ - /* Calculate and set the clock divisor */ - clock = ((sub_flag ? ov->subw * ov->subh - : width * height) - * (mode == VIDEO_PALETTE_GREY ? 2 : 3) / 2) - / 66000; - } else { - clock = clockdiv; - } - - PDEBUG(4, "Setting clock divisor to %d", clock); - - i2c_w(ov, 0x11, clock); - } - - /******** Special Features ********/ - - if (framedrop >= 0) - i2c_w(ov, 0x16, framedrop); - - /* Test Pattern */ - i2c_w_mask(ov, 0x12, (testpat?0x02:0x00), 0x02); - - /* Enable auto white balance */ - i2c_w_mask(ov, 0x12, 0x04, 0x04); - - // This will go away as soon as ov51x_mode_init_sensor_regs() - // is fully tested. - /* 7620/6620/6630? don't have register 0x35, so play it safe */ - if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { - if (width == 640 && height == 480) - i2c_w(ov, 0x35, 0x9e); - else - i2c_w(ov, 0x35, 0x1e); - } - - return 0; -} - -static int -set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode, - int sub_flag) -{ - int ret; - int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; - int hoffset, voffset, hwscale = 0, vwscale = 0; - - /* The different sensor ICs handle setting up of window differently. - * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!!! */ - switch (ov->sensor) { - case SEN_OV7610: - case SEN_OV76BE: - hwsbase = 0x38; - hwebase = 0x3a; - vwsbase = vwebase = 0x05; - break; - case SEN_OV6620: - case SEN_OV6630: - hwsbase = 0x38; - hwebase = 0x3a; - vwsbase = 0x05; - vwebase = 0x06; - break; - case SEN_OV7620: - hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ - hwebase = 0x2f; - vwsbase = vwebase = 0x05; - break; - default: - err("Invalid sensor"); - return -EINVAL; - } - - if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) { - /* Note: OV518(+) does downsample on its own) */ - if ((width > 176 && height > 144) - || ov->bclass == BCL_OV518) { /* CIF */ - ret = mode_init_ov_sensor_regs(ov, width, height, - mode, sub_flag, 0); - if (ret < 0) - return ret; - hwscale = 1; - vwscale = 1; /* The datasheet says 0; it's wrong */ - hwsize = 352; - vwsize = 288; - } else if (width > 176 || height > 144) { - err("Illegal dimensions"); - return -EINVAL; - } else { /* QCIF */ - ret = mode_init_ov_sensor_regs(ov, width, height, - mode, sub_flag, 1); - if (ret < 0) - return ret; - hwsize = 176; - vwsize = 144; - } - } else { - if (width > 320 && height > 240) { /* VGA */ - ret = mode_init_ov_sensor_regs(ov, width, height, - mode, sub_flag, 0); - if (ret < 0) - return ret; - hwscale = 2; - vwscale = 1; - hwsize = 640; - vwsize = 480; - } else if (width > 320 || height > 240) { - err("Illegal dimensions"); - return -EINVAL; - } else { /* QVGA */ - ret = mode_init_ov_sensor_regs(ov, width, height, - mode, sub_flag, 1); - if (ret < 0) - return ret; - hwscale = 1; - hwsize = 320; - vwsize = 240; - } - } - - /* Center the window */ - hoffset = ((hwsize - width) / 2) >> hwscale; - voffset = ((vwsize - height) / 2) >> vwscale; - - /* FIXME! - This needs to be changed to support 160x120 and 6620!!! */ - if (sub_flag) { - i2c_w(ov, 0x17, hwsbase+(ov->subx>>hwscale)); - i2c_w(ov, 0x18, hwebase+((ov->subx+ov->subw)>>hwscale)); - i2c_w(ov, 0x19, vwsbase+(ov->suby>>vwscale)); - i2c_w(ov, 0x1a, vwebase+((ov->suby+ov->subh)>>vwscale)); - } else { - i2c_w(ov, 0x17, hwsbase + hoffset); - i2c_w(ov, 0x18, hwebase + hoffset + (hwsize>>hwscale)); - i2c_w(ov, 0x19, vwsbase + voffset); - i2c_w(ov, 0x1a, vwebase + voffset + (vwsize>>vwscale)); - } - -#ifdef OV511_DEBUG - if (dump_sensor) - dump_i2c_regs(ov); -#endif - - return 0; -} - -/* Set up the OV511/OV511+ with the given image parameters. - * - * Do not put any sensor-specific code in here (including I2C I/O functions) - */ -static int -ov511_mode_init_regs(struct usb_ov511 *ov, - int width, int height, int mode, int sub_flag) -{ - int hsegs, vsegs; - - if (sub_flag) { - width = ov->subw; - height = ov->subh; - } - - PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d", - width, height, mode, sub_flag); - - // FIXME: This should be moved to a 7111a-specific function once - // subcapture is dealt with properly - if (ov->sensor == SEN_SAA7111A) { - if (width == 320 && height == 240) { - /* No need to do anything special */ - } else if (width == 640 && height == 480) { - /* Set the OV511 up as 320x480, but keep the - * V4L resolution as 640x480 */ - width = 320; - } else { - err("SAA7111A only allows 320x240 or 640x480"); - return -EINVAL; - } - } - - /* Make sure width and height are a multiple of 8 */ - if (width % 8 || height % 8) { - err("Invalid size (%d, %d) (mode = %d)", width, height, mode); - return -EINVAL; - } - - if (width < ov->minwidth || height < ov->minheight) { - err("Requested dimensions are too small"); - return -EINVAL; - } - - if (ov51x_stop(ov) < 0) - return -EIO; - - if (mode == VIDEO_PALETTE_GREY) { - reg_w(ov, R511_CAM_UV_EN, 0x00); - reg_w(ov, R511_SNAP_UV_EN, 0x00); - reg_w(ov, R511_SNAP_OPTS, 0x01); - } else { - reg_w(ov, R511_CAM_UV_EN, 0x01); - reg_w(ov, R511_SNAP_UV_EN, 0x01); - reg_w(ov, R511_SNAP_OPTS, 0x03); - } - - /* Here I'm assuming that snapshot size == image size. - * I hope that's always true. --claudio - */ - hsegs = (width >> 3) - 1; - vsegs = (height >> 3) - 1; - - reg_w(ov, R511_CAM_PXCNT, hsegs); - reg_w(ov, R511_CAM_LNCNT, vsegs); - reg_w(ov, R511_CAM_PXDIV, 0x00); - reg_w(ov, R511_CAM_LNDIV, 0x00); - - /* YUV420, low pass filter on */ - reg_w(ov, R511_CAM_OPTS, 0x03); - - /* Snapshot additions */ - reg_w(ov, R511_SNAP_PXCNT, hsegs); - reg_w(ov, R511_SNAP_LNCNT, vsegs); - reg_w(ov, R511_SNAP_PXDIV, 0x00); - reg_w(ov, R511_SNAP_LNDIV, 0x00); - - if (ov->compress) { - /* Enable Y and UV quantization and compression */ - reg_w(ov, R511_COMP_EN, 0x07); - reg_w(ov, R511_COMP_LUT_EN, 0x03); - ov51x_reset(ov, OV511_RESET_OMNICE); - } - - if (ov51x_restart(ov) < 0) - return -EIO; - - return 0; -} - -/* Sets up the OV518/OV518+ with the given image parameters - * - * OV518 needs a completely different approach, until we can figure out what - * the individual registers do. Also, only 15 FPS is supported now. - * - * Do not put any sensor-specific code in here (including I2C I/O functions) - */ -static int -ov518_mode_init_regs(struct usb_ov511 *ov, - int width, int height, int mode, int sub_flag) -{ - int hsegs, vsegs, hi_res; - - if (sub_flag) { - width = ov->subw; - height = ov->subh; - } - - PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d", - width, height, mode, sub_flag); - - if (width % 16 || height % 8) { - err("Invalid size (%d, %d)", width, height); - return -EINVAL; - } - - if (width < ov->minwidth || height < ov->minheight) { - err("Requested dimensions are too small"); - return -EINVAL; - } - - if (width >= 320 && height >= 240) { - hi_res = 1; - } else if (width >= 320 || height >= 240) { - err("Invalid width/height combination (%d, %d)", width, height); - return -EINVAL; - } else { - hi_res = 0; - } - - if (ov51x_stop(ov) < 0) - return -EIO; - - /******** Set the mode ********/ - - reg_w(ov, 0x2b, 0); - reg_w(ov, 0x2c, 0); - reg_w(ov, 0x2d, 0); - reg_w(ov, 0x2e, 0); - reg_w(ov, 0x3b, 0); - reg_w(ov, 0x3c, 0); - reg_w(ov, 0x3d, 0); - reg_w(ov, 0x3e, 0); - - if (ov->bridge == BRG_OV518 && ov518_color) { - /* OV518 needs U and V swapped */ - i2c_w_mask(ov, 0x15, 0x00, 0x01); - - if (mode == VIDEO_PALETTE_GREY) { - /* Set 16-bit input format (UV data are ignored) */ - reg_w_mask(ov, 0x20, 0x00, 0x08); - - /* Set 8-bit (4:0:0) output format */ - reg_w_mask(ov, 0x28, 0x00, 0xf0); - reg_w_mask(ov, 0x38, 0x00, 0xf0); - } else { - /* Set 8-bit (YVYU) input format */ - reg_w_mask(ov, 0x20, 0x08, 0x08); - - /* Set 12-bit (4:2:0) output format */ - reg_w_mask(ov, 0x28, 0x80, 0xf0); - reg_w_mask(ov, 0x38, 0x80, 0xf0); - } - } else { - reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); - reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); - } - - hsegs = width / 16; - vsegs = height / 4; - - reg_w(ov, 0x29, hsegs); - reg_w(ov, 0x2a, vsegs); - - reg_w(ov, 0x39, hsegs); - reg_w(ov, 0x3a, vsegs); - - /* Windows driver does this here; who knows why */ - reg_w(ov, 0x2f, 0x80); - - /******** Set the framerate (to 15 FPS) ********/ - - /* Mode independent, but framerate dependent, regs */ - reg_w(ov, 0x51, 0x02); /* Clock divider; lower==faster */ - reg_w(ov, 0x22, 0x18); - reg_w(ov, 0x23, 0xff); - - if (ov->bridge == BRG_OV518PLUS) - reg_w(ov, 0x21, 0x19); - else - reg_w(ov, 0x71, 0x19); /* Compression-related? */ - - // FIXME: Sensor-specific - /* Bit 5 is what matters here. Of course, it is "reserved" */ - i2c_w(ov, 0x54, 0x23); - - reg_w(ov, 0x2f, 0x80); - - if (ov->bridge == BRG_OV518PLUS) { - reg_w(ov, 0x24, 0x94); - reg_w(ov, 0x25, 0x90); - ov518_reg_w32(ov, 0xc4, 400, 2); /* 190h */ - ov518_reg_w32(ov, 0xc6, 540, 2); /* 21ch */ - ov518_reg_w32(ov, 0xc7, 540, 2); /* 21ch */ - ov518_reg_w32(ov, 0xc8, 108, 2); /* 6ch */ - ov518_reg_w32(ov, 0xca, 131098, 3); /* 2001ah */ - ov518_reg_w32(ov, 0xcb, 532, 2); /* 214h */ - ov518_reg_w32(ov, 0xcc, 2400, 2); /* 960h */ - ov518_reg_w32(ov, 0xcd, 32, 2); /* 20h */ - ov518_reg_w32(ov, 0xce, 608, 2); /* 260h */ - } else { - reg_w(ov, 0x24, 0x9f); - reg_w(ov, 0x25, 0x90); - ov518_reg_w32(ov, 0xc4, 400, 2); /* 190h */ - ov518_reg_w32(ov, 0xc6, 500, 2); /* 1f4h */ - ov518_reg_w32(ov, 0xc7, 500, 2); /* 1f4h */ - ov518_reg_w32(ov, 0xc8, 142, 2); /* 8eh */ - ov518_reg_w32(ov, 0xca, 131098, 3); /* 2001ah */ - ov518_reg_w32(ov, 0xcb, 532, 2); /* 214h */ - ov518_reg_w32(ov, 0xcc, 2000, 2); /* 7d0h */ - ov518_reg_w32(ov, 0xcd, 32, 2); /* 20h */ - ov518_reg_w32(ov, 0xce, 608, 2); /* 260h */ - } - - reg_w(ov, 0x2f, 0x80); - - if (ov51x_restart(ov) < 0) - return -EIO; - - /* Reset it just for good measure */ - if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) - return -EIO; - - return 0; -} - -/* This is a wrapper around the OV511, OV518, and sensor specific functions */ -static int -mode_init_regs(struct usb_ov511 *ov, - int width, int height, int mode, int sub_flag) -{ - int rc = 0; - - if (!ov || !ov->dev) - return -EFAULT; - - if (ov->bclass == BCL_OV518) { - rc = ov518_mode_init_regs(ov, width, height, mode, sub_flag); - } else { - rc = ov511_mode_init_regs(ov, width, height, mode, sub_flag); - } - - if (FATAL_ERROR(rc)) - return rc; - - switch (ov->sensor) { - case SEN_OV7610: - case SEN_OV7620: - case SEN_OV76BE: - case SEN_OV8600: - case SEN_OV6620: - case SEN_OV6630: - rc = set_ov_sensor_window(ov, width, height, mode, sub_flag); - break; - case SEN_KS0127: - case SEN_KS0127B: - err("KS0127-series decoders not supported yet"); - rc = -EINVAL; - break; - case SEN_SAA7111A: -// rc = mode_init_saa_sensor_regs(ov, width, height, mode, -// sub_flag); - - PDEBUG(1, "SAA status = 0x%02X", i2c_r(ov, 0x1f)); - break; - default: - err("Unknown sensor"); - rc = -EINVAL; - } - - if (FATAL_ERROR(rc)) - return rc; - - /* Sensor-independent settings */ - rc = sensor_set_auto_brightness(ov, ov->auto_brt); - if (FATAL_ERROR(rc)) - return rc; - - rc = sensor_set_auto_exposure(ov, ov->auto_exp); - if (FATAL_ERROR(rc)) - return rc; - - rc = sensor_set_banding_filter(ov, bandingfilter); - if (FATAL_ERROR(rc)) - return rc; - - if (ov->lightfreq) { - rc = sensor_set_light_freq(ov, lightfreq); - if (FATAL_ERROR(rc)) - return rc; - } - - rc = sensor_set_backlight(ov, ov->backlight); - if (FATAL_ERROR(rc)) - return rc; - - rc = sensor_set_mirror(ov, ov->mirror); - if (FATAL_ERROR(rc)) - return rc; - - return 0; -} - -/* This sets the default image parameters. This is useful for apps that use - * read() and do not set these. - */ -static int -ov51x_set_default_params(struct usb_ov511 *ov) -{ - int i; - - /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used - * (using read() instead). */ - for (i = 0; i < OV511_NUMFRAMES; i++) { - ov->frame[i].width = ov->maxwidth; - ov->frame[i].height = ov->maxheight; - ov->frame[i].bytes_read = 0; - if (force_palette) - ov->frame[i].format = force_palette; - else - ov->frame[i].format = VIDEO_PALETTE_YUV420; - - ov->frame[i].depth = get_depth(ov->frame[i].format); - } - - PDEBUG(3, "%dx%d, %s", ov->maxwidth, ov->maxheight, - symbolic(v4l1_plist, ov->frame[0].format)); - - /* Initialize to max width/height, YUV420 or RGB24 (if supported) */ - if (mode_init_regs(ov, ov->maxwidth, ov->maxheight, - ov->frame[0].format, 0) < 0) - return -EINVAL; - - return 0; -} - -/********************************************************************** - * - * Video decoder stuff - * - **********************************************************************/ - -/* Set analog input port of decoder */ -static int -decoder_set_input(struct usb_ov511 *ov, int input) -{ - PDEBUG(4, "port %d", input); - - switch (ov->sensor) { - case SEN_SAA7111A: - { - /* Select mode */ - i2c_w_mask(ov, 0x02, input, 0x07); - /* Bypass chrominance trap for modes 4..7 */ - i2c_w_mask(ov, 0x09, (input > 3) ? 0x80:0x00, 0x80); - break; - } - default: - return -EINVAL; - } - - return 0; -} - -/* Get ASCII name of video input */ -static int -decoder_get_input_name(struct usb_ov511 *ov, int input, char *name) -{ - switch (ov->sensor) { - case SEN_SAA7111A: - { - if (input < 0 || input > 7) - return -EINVAL; - else if (input < 4) - sprintf(name, "CVBS-%d", input); - else // if (input < 8) - sprintf(name, "S-Video-%d", input - 4); - break; - } - default: - sprintf(name, "%s", "Camera"); - } - - return 0; -} - -/* Set norm (NTSC, PAL, SECAM, AUTO) */ -static int -decoder_set_norm(struct usb_ov511 *ov, int norm) -{ - PDEBUG(4, "%d", norm); - - switch (ov->sensor) { - case SEN_SAA7111A: - { - int reg_8, reg_e; - - if (norm == VIDEO_MODE_NTSC) { - reg_8 = 0x40; /* 60 Hz */ - reg_e = 0x00; /* NTSC M / PAL BGHI */ - } else if (norm == VIDEO_MODE_PAL) { - reg_8 = 0x00; /* 50 Hz */ - reg_e = 0x00; /* NTSC M / PAL BGHI */ - } else if (norm == VIDEO_MODE_AUTO) { - reg_8 = 0x80; /* Auto field detect */ - reg_e = 0x00; /* NTSC M / PAL BGHI */ - } else if (norm == VIDEO_MODE_SECAM) { - reg_8 = 0x00; /* 50 Hz */ - reg_e = 0x50; /* SECAM / PAL 4.43 */ - } else { - return -EINVAL; - } - - i2c_w_mask(ov, 0x08, reg_8, 0xc0); - i2c_w_mask(ov, 0x0e, reg_e, 0x70); - break; - } - default: - return -EINVAL; - } - - return 0; -} - -/********************************************************************** - * - * Raw data parsing - * - **********************************************************************/ - -/* Copies a 64-byte segment at pIn to an 8x8 block at pOut. The width of the - * image at pOut is specified by w. - */ -static inline void -make_8x8(unsigned char *pIn, unsigned char *pOut, int w) -{ - unsigned char *pOut1 = pOut; - int x, y; - - for (y = 0; y < 8; y++) { - pOut1 = pOut; - for (x = 0; x < 8; x++) { - *pOut1++ = *pIn++; - } - pOut += w; - } -} - -/* - * For RAW BW (YUV 4:0:0) images, data show up in 256 byte segments. - * The segments represent 4 squares of 8x8 pixels as follows: - * - * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 - * 8 9 ... 15 72 73 ... 79 200 201 ... 207 - * ... ... ... - * 56 57 ... 63 120 121 ... 127 248 249 ... 255 - * - */ -static void -yuv400raw_to_yuv400p(struct ov511_frame *frame, - unsigned char *pIn0, unsigned char *pOut0) -{ - int x, y; - unsigned char *pIn, *pOut, *pOutLine; - - /* Copy Y */ - pIn = pIn0; - pOutLine = pOut0; - for (y = 0; y < frame->rawheight - 1; y += 8) { - pOut = pOutLine; - for (x = 0; x < frame->rawwidth - 1; x += 8) { - make_8x8(pIn, pOut, frame->rawwidth); - pIn += 64; - pOut += 8; - } - pOutLine += 8 * frame->rawwidth; - } -} - -/* - * For YUV 4:2:0 images, the data show up in 384 byte segments. - * The first 64 bytes of each segment are U, the next 64 are V. The U and - * V are arranged as follows: - * - * 0 1 ... 7 - * 8 9 ... 15 - * ... - * 56 57 ... 63 - * - * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block). - * - * The next 256 bytes are full resolution Y data and represent 4 squares - * of 8x8 pixels as follows: - * - * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 - * 8 9 ... 15 72 73 ... 79 200 201 ... 207 - * ... ... ... - * 56 57 ... 63 120 121 ... 127 ... 248 249 ... 255 - * - * Note that the U and V data in one segment represent a 16 x 16 pixel - * area, but the Y data represent a 32 x 8 pixel area. If the width is not an - * even multiple of 32, the extra 8x8 blocks within a 32x8 block belong to the - * next horizontal stripe. - * - * If dumppix module param is set, _parse_data just dumps the incoming segments, - * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480 - * this puts the data on the standard output and can be analyzed with the - * parseppm.c utility I wrote. That's a much faster way for figuring out how - * these data are scrambled. - */ - -/* Converts from raw, uncompressed segments at pIn0 to a YUV420P frame at pOut0. - * - * FIXME: Currently only handles width and height that are multiples of 16 - */ -static void -yuv420raw_to_yuv420p(struct ov511_frame *frame, - unsigned char *pIn0, unsigned char *pOut0) -{ - int k, x, y; - unsigned char *pIn, *pOut, *pOutLine; - const unsigned int a = frame->rawwidth * frame->rawheight; - const unsigned int w = frame->rawwidth / 2; - - /* Copy U and V */ - pIn = pIn0; - pOutLine = pOut0 + a; - for (y = 0; y < frame->rawheight - 1; y += 16) { - pOut = pOutLine; - for (x = 0; x < frame->rawwidth - 1; x += 16) { - make_8x8(pIn, pOut, w); - make_8x8(pIn + 64, pOut + a/4, w); - pIn += 384; - pOut += 8; - } - pOutLine += 8 * w; - } - - /* Copy Y */ - pIn = pIn0 + 128; - pOutLine = pOut0; - k = 0; - for (y = 0; y < frame->rawheight - 1; y += 8) { - pOut = pOutLine; - for (x = 0; x < frame->rawwidth - 1; x += 8) { - make_8x8(pIn, pOut, frame->rawwidth); - pIn += 64; - pOut += 8; - if ((++k) > 3) { - k = 0; - pIn += 128; - } - } - pOutLine += 8 * frame->rawwidth; - } -} - -/********************************************************************** - * - * Decompression - * - **********************************************************************/ - -static int -request_decompressor(struct usb_ov511 *ov) -{ - if (ov->bclass == BCL_OV511 || ov->bclass == BCL_OV518) { - err("No decompressor available"); - } else { - err("Unknown bridge"); - } - - return -ENOSYS; -} - -static void -decompress(struct usb_ov511 *ov, struct ov511_frame *frame, - unsigned char *pIn0, unsigned char *pOut0) -{ - if (!ov->decomp_ops) - if (request_decompressor(ov)) - return; - -} - -/********************************************************************** - * - * Format conversion - * - **********************************************************************/ - -/* Fuses even and odd fields together, and doubles width. - * INPUT: an odd field followed by an even field at pIn0, in YUV planar format - * OUTPUT: a normal YUV planar image, with correct aspect ratio - */ -static void -deinterlace(struct ov511_frame *frame, int rawformat, - unsigned char *pIn0, unsigned char *pOut0) -{ - const int fieldheight = frame->rawheight / 2; - const int fieldpix = fieldheight * frame->rawwidth; - const int w = frame->width; - int x, y; - unsigned char *pInEven, *pInOdd, *pOut; - - PDEBUG(5, "fieldheight=%d", fieldheight); - - if (frame->rawheight != frame->height) { - err("invalid height"); - return; - } - - if ((frame->rawwidth * 2) != frame->width) { - err("invalid width"); - return; - } - - /* Y */ - pInOdd = pIn0; - pInEven = pInOdd + fieldpix; - pOut = pOut0; - for (y = 0; y < fieldheight; y++) { - for (x = 0; x < frame->rawwidth; x++) { - *pOut = *pInEven; - *(pOut+1) = *pInEven++; - *(pOut+w) = *pInOdd; - *(pOut+w+1) = *pInOdd++; - pOut += 2; - } - pOut += w; - } - - if (rawformat == RAWFMT_YUV420) { - /* U */ - pInOdd = pIn0 + fieldpix * 2; - pInEven = pInOdd + fieldpix / 4; - for (y = 0; y < fieldheight / 2; y++) { - for (x = 0; x < frame->rawwidth / 2; x++) { - *pOut = *pInEven; - *(pOut+1) = *pInEven++; - *(pOut+w/2) = *pInOdd; - *(pOut+w/2+1) = *pInOdd++; - pOut += 2; - } - pOut += w/2; - } - /* V */ - pInOdd = pIn0 + fieldpix * 2 + fieldpix / 2; - pInEven = pInOdd + fieldpix / 4; - for (y = 0; y < fieldheight / 2; y++) { - for (x = 0; x < frame->rawwidth / 2; x++) { - *pOut = *pInEven; - *(pOut+1) = *pInEven++; - *(pOut+w/2) = *pInOdd; - *(pOut+w/2+1) = *pInOdd++; - pOut += 2; - } - pOut += w/2; - } - } -} - -static void -ov51x_postprocess_grey(struct usb_ov511 *ov, struct ov511_frame *frame) -{ - /* Deinterlace frame, if necessary */ - if (ov->sensor == SEN_SAA7111A && frame->rawheight >= 480) { - if (frame->compressed) - decompress(ov, frame, frame->rawdata, - frame->tempdata); - else - yuv400raw_to_yuv400p(frame, frame->rawdata, - frame->tempdata); - - deinterlace(frame, RAWFMT_YUV400, frame->tempdata, - frame->data); - } else { - if (frame->compressed) - decompress(ov, frame, frame->rawdata, - frame->data); - else - yuv400raw_to_yuv400p(frame, frame->rawdata, - frame->data); - } -} - -/* Process raw YUV420 data into standard YUV420P */ -static void -ov51x_postprocess_yuv420(struct usb_ov511 *ov, struct ov511_frame *frame) -{ - /* Deinterlace frame, if necessary */ - if (ov->sensor == SEN_SAA7111A && frame->rawheight >= 480) { - if (frame->compressed) - decompress(ov, frame, frame->rawdata, frame->tempdata); - else - yuv420raw_to_yuv420p(frame, frame->rawdata, - frame->tempdata); - - deinterlace(frame, RAWFMT_YUV420, frame->tempdata, - frame->data); - } else { - if (frame->compressed) - decompress(ov, frame, frame->rawdata, frame->data); - else - yuv420raw_to_yuv420p(frame, frame->rawdata, - frame->data); - } -} - -/* Post-processes the specified frame. This consists of: - * 1. Decompress frame, if necessary - * 2. Deinterlace frame and scale to proper size, if necessary - * 3. Convert from YUV planar to destination format, if necessary - * 4. Fix the RGB offset, if necessary - */ -static void -ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame) -{ - if (dumppix) { - memset(frame->data, 0, - MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)); - PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd); - memcpy(frame->data, frame->rawdata, frame->bytes_recvd); - } else { - switch (frame->format) { - case VIDEO_PALETTE_GREY: - ov51x_postprocess_grey(ov, frame); - break; - case VIDEO_PALETTE_YUV420: - case VIDEO_PALETTE_YUV420P: - ov51x_postprocess_yuv420(ov, frame); - break; - default: - err("Cannot convert data to %s", - symbolic(v4l1_plist, frame->format)); - } - } -} - -/********************************************************************** - * - * OV51x data transfer, IRQ handler - * - **********************************************************************/ - -static inline void -ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n) -{ - int num, offset; - int pnum = in[ov->packet_size - 1]; /* Get packet number */ - int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight); - struct ov511_frame *frame = &ov->frame[ov->curframe]; - struct timeval *ts; - - /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th - * byte non-zero. The EOF packet has image width/height in the - * 10th and 11th bytes. The 9th byte is given as follows: - * - * bit 7: EOF - * 6: compression enabled - * 5: 422/420/400 modes - * 4: 422/420/400 modes - * 3: 1 - * 2: snapshot button on - * 1: snapshot frame - * 0: even/odd field - */ - - if (printph) { - info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", - pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6], - in[7], in[8], in[9], in[10], in[11]); - } - - /* Check for SOF/EOF packet */ - if ((in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) || - (~in[8] & 0x08)) - goto check_middle; - - /* Frame end */ - if (in[8] & 0x80) { - ts = (struct timeval *)(frame->data - + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight)); - do_gettimeofday(ts); - - /* Get the actual frame size from the EOF header */ - frame->rawwidth = ((int)(in[9]) + 1) * 8; - frame->rawheight = ((int)(in[10]) + 1) * 8; - - PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d", - ov->curframe, pnum, frame->rawwidth, frame->rawheight, - frame->bytes_recvd); - - /* Validate the header data */ - RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth); - RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, - ov->maxheight); - - /* Don't allow byte count to exceed buffer size */ - RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); - - if (frame->scanstate == STATE_LINES) { - int nextf; - - frame->grabstate = FRAME_DONE; - wake_up_interruptible(&frame->wq); - - /* If next frame is ready or grabbing, - * point to it */ - nextf = (ov->curframe + 1) % OV511_NUMFRAMES; - if (ov->frame[nextf].grabstate == FRAME_READY - || ov->frame[nextf].grabstate == FRAME_GRABBING) { - ov->curframe = nextf; - ov->frame[nextf].scanstate = STATE_SCANNING; - } else { - if (frame->grabstate == FRAME_DONE) { - PDEBUG(4, "** Frame done **"); - } else { - PDEBUG(4, "Frame not ready? state = %d", - ov->frame[nextf].grabstate); - } - - ov->curframe = -1; - } - } else { - PDEBUG(5, "Frame done, but not scanning"); - } - /* Image corruption caused by misplaced frame->segment = 0 - * fixed by carlosf@conectiva.com.br - */ - } else { - /* Frame start */ - PDEBUG(4, "Frame start, framenum = %d", ov->curframe); - - /* Check to see if it's a snapshot frame */ - /* FIXME?? Should the snapshot reset go here? Performance? */ - if (in[8] & 0x02) { - frame->snapshot = 1; - PDEBUG(3, "snapshot detected"); - } - - frame->scanstate = STATE_LINES; - frame->bytes_recvd = 0; - frame->compressed = in[8] & 0x40; - } - -check_middle: - /* Are we in a frame? */ - if (frame->scanstate != STATE_LINES) { - PDEBUG(5, "Not in a frame; packet skipped"); - return; - } - - /* If frame start, skip header */ - if (frame->bytes_recvd == 0) - offset = 9; - else - offset = 0; - - num = n - offset - 1; - - /* Dump all data exactly as received */ - if (dumppix == 2) { - frame->bytes_recvd += n - 1; - if (frame->bytes_recvd <= max_raw) - memcpy(frame->rawdata + frame->bytes_recvd - (n - 1), - in, n - 1); - else - PDEBUG(3, "Raw data buffer overrun!! (%d)", - frame->bytes_recvd - max_raw); - } else if (!frame->compressed && !remove_zeros) { - frame->bytes_recvd += num; - if (frame->bytes_recvd <= max_raw) - memcpy(frame->rawdata + frame->bytes_recvd - num, - in + offset, num); - else - PDEBUG(3, "Raw data buffer overrun!! (%d)", - frame->bytes_recvd - max_raw); - } else { /* Remove all-zero FIFO lines (aligned 32-byte blocks) */ - int b, read = 0, allzero, copied = 0; - if (offset) { - frame->bytes_recvd += 32 - offset; // Bytes out - memcpy(frame->rawdata, in + offset, 32 - offset); - read += 32; - } - - while (read < n - 1) { - allzero = 1; - for (b = 0; b < 32; b++) { - if (in[read + b]) { - allzero = 0; - break; - } - } - - if (allzero) { - /* Don't copy it */ - } else { - if (frame->bytes_recvd + copied + 32 <= max_raw) - { - memcpy(frame->rawdata - + frame->bytes_recvd + copied, - in + read, 32); - copied += 32; - } else { - PDEBUG(3, "Raw data buffer overrun!!"); - } - } - read += 32; - } - - frame->bytes_recvd += copied; - } -} - -static inline void -ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n) -{ - int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight); - struct ov511_frame *frame = &ov->frame[ov->curframe]; - struct timeval *ts; - - /* Don't copy the packet number byte */ - if (ov->packet_numbering) - --n; - - /* A false positive here is likely, until OVT gives me - * the definitive SOF/EOF format */ - if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) { - if (printph) { - info("ph: %2x %2x %2x %2x %2x %2x %2x %2x", in[0], - in[1], in[2], in[3], in[4], in[5], in[6], in[7]); - } - - if (frame->scanstate == STATE_LINES) { - PDEBUG(4, "Detected frame end/start"); - goto eof; - } else { //scanstate == STATE_SCANNING - /* Frame start */ - PDEBUG(4, "Frame start, framenum = %d", ov->curframe); - goto sof; - } - } else { - goto check_middle; - } - -eof: - ts = (struct timeval *)(frame->data - + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight)); - do_gettimeofday(ts); - - PDEBUG(4, "Frame end, curframe = %d, hw=%d, vw=%d, recvd=%d", - ov->curframe, - (int)(in[9]), (int)(in[10]), frame->bytes_recvd); - - // FIXME: Since we don't know the header formats yet, - // there is no way to know what the actual image size is - frame->rawwidth = frame->width; - frame->rawheight = frame->height; - - /* Validate the header data */ - RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth); - RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, ov->maxheight); - - /* Don't allow byte count to exceed buffer size */ - RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); - - if (frame->scanstate == STATE_LINES) { - int nextf; - - frame->grabstate = FRAME_DONE; - wake_up_interruptible(&frame->wq); - - /* If next frame is ready or grabbing, - * point to it */ - nextf = (ov->curframe + 1) % OV511_NUMFRAMES; - if (ov->frame[nextf].grabstate == FRAME_READY - || ov->frame[nextf].grabstate == FRAME_GRABBING) { - ov->curframe = nextf; - ov->frame[nextf].scanstate = STATE_SCANNING; - frame = &ov->frame[nextf]; - } else { - if (frame->grabstate == FRAME_DONE) { - PDEBUG(4, "** Frame done **"); - } else { - PDEBUG(4, "Frame not ready? state = %d", - ov->frame[nextf].grabstate); - } - - ov->curframe = -1; - PDEBUG(4, "SOF dropped (no active frame)"); - return; /* Nowhere to store this frame */ - } - } -sof: - PDEBUG(4, "Starting capture on frame %d", frame->framenum); - -// Snapshot not reverse-engineered yet. -#if 0 - /* Check to see if it's a snapshot frame */ - /* FIXME?? Should the snapshot reset go here? Performance? */ - if (in[8] & 0x02) { - frame->snapshot = 1; - PDEBUG(3, "snapshot detected"); - } -#endif - frame->scanstate = STATE_LINES; - frame->bytes_recvd = 0; - frame->compressed = 1; - -check_middle: - /* Are we in a frame? */ - if (frame->scanstate != STATE_LINES) { - PDEBUG(4, "scanstate: no SOF yet"); - return; - } - - /* Dump all data exactly as received */ - if (dumppix == 2) { - frame->bytes_recvd += n; - if (frame->bytes_recvd <= max_raw) - memcpy(frame->rawdata + frame->bytes_recvd - n, in, n); - else - PDEBUG(3, "Raw data buffer overrun!! (%d)", - frame->bytes_recvd - max_raw); - } else { - /* All incoming data are divided into 8-byte segments. If the - * segment contains all zero bytes, it must be skipped. These - * zero-segments allow the OV518 to mainain a constant data rate - * regardless of the effectiveness of the compression. Segments - * are aligned relative to the beginning of each isochronous - * packet. The first segment in each image is a header (the - * decompressor skips it later). - */ - - int b, read = 0, allzero, copied = 0; - - while (read < n) { - allzero = 1; - for (b = 0; b < 8; b++) { - if (in[read + b]) { - allzero = 0; - break; - } - } - - if (allzero) { - /* Don't copy it */ - } else { - if (frame->bytes_recvd + copied + 8 <= max_raw) - { - memcpy(frame->rawdata - + frame->bytes_recvd + copied, - in + read, 8); - copied += 8; - } else { - PDEBUG(3, "Raw data buffer overrun!!"); - } - } - read += 8; - } - frame->bytes_recvd += copied; - } -} - -static void -ov51x_isoc_irq(struct urb *urb, struct pt_regs *regs) -{ - int i; - struct usb_ov511 *ov; - struct ov511_sbuf *sbuf; - - if (!urb->context) { - PDEBUG(4, "no context"); - return; - } - - sbuf = urb->context; - ov = sbuf->ov; - - if (!ov || !ov->dev || !ov->user) { - PDEBUG(4, "no device, or not open"); - return; - } - - if (!ov->streaming) { - PDEBUG(4, "hmmm... not streaming, but got interrupt"); - return; - } - - if (urb->status == -ENOENT || urb->status == -ECONNRESET) { - PDEBUG(4, "URB unlinked"); - return; - } - - if (urb->status != -EINPROGRESS && urb->status != 0) { - err("ERROR: urb->status=%d: %s", urb->status, - symbolic(urb_errlist, urb->status)); - } - - /* Copy the data received into our frame buffer */ - PDEBUG(5, "sbuf[%d]: Moving %d packets", sbuf->n, - urb->number_of_packets); - for (i = 0; i < urb->number_of_packets; i++) { - /* Warning: Don't call *_move_data() if no frame active! */ - if (ov->curframe >= 0) { - int n = urb->iso_frame_desc[i].actual_length; - int st = urb->iso_frame_desc[i].status; - unsigned char *cdata; - - urb->iso_frame_desc[i].actual_length = 0; - urb->iso_frame_desc[i].status = 0; - - cdata = urb->transfer_buffer - + urb->iso_frame_desc[i].offset; - - if (!n) { - PDEBUG(4, "Zero-length packet"); - continue; - } - - if (st) - PDEBUG(2, "data error: [%d] len=%d, status=%d", - i, n, st); - - if (ov->bclass == BCL_OV511) - ov511_move_data(ov, cdata, n); - else if (ov->bclass == BCL_OV518) - ov518_move_data(ov, cdata, n); - else - err("Unknown bridge device (%d)", ov->bridge); - - } else if (waitqueue_active(&ov->wq)) { - wake_up_interruptible(&ov->wq); - } - } - - /* Resubmit this URB */ - urb->dev = ov->dev; - if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0) - err("usb_submit_urb() ret %d", i); - - return; -} - -/**************************************************************************** - * - * Stream initialization and termination - * - ***************************************************************************/ - -static int -ov51x_init_isoc(struct usb_ov511 *ov) -{ - struct urb *urb; - int fx, err, n, size; - - PDEBUG(3, "*** Initializing capture ***"); - - ov->curframe = -1; - - if (ov->bridge == BRG_OV511) { - if (cams == 1) - size = 993; - else if (cams == 2) - size = 513; - else if (cams == 3 || cams == 4) - size = 257; - else { - err("\"cams\" parameter too high!"); - return -1; - } - } else if (ov->bridge == BRG_OV511PLUS) { - if (cams == 1) - size = 961; - else if (cams == 2) - size = 513; - else if (cams == 3 || cams == 4) - size = 257; - else if (cams >= 5 && cams <= 8) - size = 129; - else if (cams >= 9 && cams <= 31) - size = 33; - else { - err("\"cams\" parameter too high!"); - return -1; - } - } else if (ov->bclass == BCL_OV518) { - if (cams == 1) - size = 896; - else if (cams == 2) - size = 512; - else if (cams == 3 || cams == 4) - size = 256; - else if (cams >= 5 && cams <= 8) - size = 128; - else { - err("\"cams\" parameter too high!"); - return -1; - } - } else { - err("invalid bridge type"); - return -1; - } - - // FIXME: OV518 is hardcoded to 15 FPS (alternate 5) for now - if (ov->bclass == BCL_OV518) { - if (packetsize == -1) { - ov518_set_packet_size(ov, 640); - } else { - info("Forcing packet size to %d", packetsize); - ov518_set_packet_size(ov, packetsize); - } - } else { - if (packetsize == -1) { - ov511_set_packet_size(ov, size); - } else { - info("Forcing packet size to %d", packetsize); - ov511_set_packet_size(ov, packetsize); - } - } - - for (n = 0; n < OV511_NUMSBUF; n++) { - urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); - if (!urb) { - err("init isoc: usb_alloc_urb ret. NULL"); - return -ENOMEM; - } - ov->sbuf[n].urb = urb; - urb->dev = ov->dev; - urb->context = &ov->sbuf[n]; - urb->pipe = usb_rcvisocpipe(ov->dev, OV511_ENDPOINT_ADDRESS); - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = ov->sbuf[n].data; - urb->complete = ov51x_isoc_irq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = ov->packet_size * FRAMES_PER_DESC; - urb->interval = 1; - for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = ov->packet_size * fx; - urb->iso_frame_desc[fx].length = ov->packet_size; - } - } - - ov->streaming = 1; - - for (n = 0; n < OV511_NUMSBUF; n++) { - ov->sbuf[n].urb->dev = ov->dev; - err = usb_submit_urb(ov->sbuf[n].urb, GFP_KERNEL); - if (err) { - err("init isoc: usb_submit_urb(%d) ret %d", n, err); - return err; - } - } - - return 0; -} - -static void -ov51x_unlink_isoc(struct usb_ov511 *ov) -{ - int n; - - /* Unschedule all of the iso td's */ - for (n = OV511_NUMSBUF - 1; n >= 0; n--) { - if (ov->sbuf[n].urb) { - usb_kill_urb(ov->sbuf[n].urb); - usb_free_urb(ov->sbuf[n].urb); - ov->sbuf[n].urb = NULL; - } - } -} - -static void -ov51x_stop_isoc(struct usb_ov511 *ov) -{ - if (!ov->streaming || !ov->dev) - return; - - PDEBUG(3, "*** Stopping capture ***"); - - if (ov->bclass == BCL_OV518) - ov518_set_packet_size(ov, 0); - else - ov511_set_packet_size(ov, 0); - - ov->streaming = 0; - - ov51x_unlink_isoc(ov); -} - -static int -ov51x_new_frame(struct usb_ov511 *ov, int framenum) -{ - struct ov511_frame *frame; - int newnum; - - PDEBUG(4, "ov->curframe = %d, framenum = %d", ov->curframe, framenum); - - if (!ov->dev) - return -1; - - /* If we're not grabbing a frame right now and the other frame is */ - /* ready to be grabbed into, then use it instead */ - if (ov->curframe == -1) { - newnum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES; - if (ov->frame[newnum].grabstate == FRAME_READY) - framenum = newnum; - } else - return 0; - - frame = &ov->frame[framenum]; - - PDEBUG(4, "framenum = %d, width = %d, height = %d", framenum, - frame->width, frame->height); - - frame->grabstate = FRAME_GRABBING; - frame->scanstate = STATE_SCANNING; - frame->snapshot = 0; - - ov->curframe = framenum; - - /* Make sure it's not too big */ - if (frame->width > ov->maxwidth) - frame->width = ov->maxwidth; - - frame->width &= ~7L; /* Multiple of 8 */ - - if (frame->height > ov->maxheight) - frame->height = ov->maxheight; - - frame->height &= ~3L; /* Multiple of 4 */ - - return 0; -} - -/**************************************************************************** - * - * Buffer management - * - ***************************************************************************/ - -/* - * - You must acquire buf_lock before entering this function. - * - Because this code will free any non-null pointer, you must be sure to null - * them if you explicitly free them somewhere else! - */ -static void -ov51x_do_dealloc(struct usb_ov511 *ov) -{ - int i; - PDEBUG(4, "entered"); - - if (ov->fbuf) { - rvfree(ov->fbuf, OV511_NUMFRAMES - * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)); - ov->fbuf = NULL; - } - - vfree(ov->rawfbuf); - ov->rawfbuf = NULL; - - vfree(ov->tempfbuf); - ov->tempfbuf = NULL; - - for (i = 0; i < OV511_NUMSBUF; i++) { - kfree(ov->sbuf[i].data); - ov->sbuf[i].data = NULL; - } - - for (i = 0; i < OV511_NUMFRAMES; i++) { - ov->frame[i].data = NULL; - ov->frame[i].rawdata = NULL; - ov->frame[i].tempdata = NULL; - if (ov->frame[i].compbuf) { - free_page((unsigned long) ov->frame[i].compbuf); - ov->frame[i].compbuf = NULL; - } - } - - PDEBUG(4, "buffer memory deallocated"); - ov->buf_state = BUF_NOT_ALLOCATED; - PDEBUG(4, "leaving"); -} - -static int -ov51x_alloc(struct usb_ov511 *ov) -{ - int i; - const int w = ov->maxwidth; - const int h = ov->maxheight; - const int data_bufsize = OV511_NUMFRAMES * MAX_DATA_SIZE(w, h); - const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h); - - PDEBUG(4, "entered"); - mutex_lock(&ov->buf_lock); - - if (ov->buf_state == BUF_ALLOCATED) - goto out; - - ov->fbuf = rvmalloc(data_bufsize); - if (!ov->fbuf) - goto error; - - ov->rawfbuf = vmalloc(raw_bufsize); - if (!ov->rawfbuf) - goto error; - - memset(ov->rawfbuf, 0, raw_bufsize); - - ov->tempfbuf = vmalloc(raw_bufsize); - if (!ov->tempfbuf) - goto error; - - memset(ov->tempfbuf, 0, raw_bufsize); - - for (i = 0; i < OV511_NUMSBUF; i++) { - ov->sbuf[i].data = kmalloc(FRAMES_PER_DESC * - MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!ov->sbuf[i].data) - goto error; - - PDEBUG(4, "sbuf[%d] @ %p", i, ov->sbuf[i].data); - } - - for (i = 0; i < OV511_NUMFRAMES; i++) { - ov->frame[i].data = ov->fbuf + i * MAX_DATA_SIZE(w, h); - ov->frame[i].rawdata = ov->rawfbuf - + i * MAX_RAW_DATA_SIZE(w, h); - ov->frame[i].tempdata = ov->tempfbuf - + i * MAX_RAW_DATA_SIZE(w, h); - - ov->frame[i].compbuf = - (unsigned char *) __get_free_page(GFP_KERNEL); - if (!ov->frame[i].compbuf) - goto error; - - PDEBUG(4, "frame[%d] @ %p", i, ov->frame[i].data); - } - - ov->buf_state = BUF_ALLOCATED; -out: - mutex_unlock(&ov->buf_lock); - PDEBUG(4, "leaving"); - return 0; -error: - ov51x_do_dealloc(ov); - mutex_unlock(&ov->buf_lock); - PDEBUG(4, "errored"); - return -ENOMEM; -} - -static void -ov51x_dealloc(struct usb_ov511 *ov) -{ - PDEBUG(4, "entered"); - mutex_lock(&ov->buf_lock); - ov51x_do_dealloc(ov); - mutex_unlock(&ov->buf_lock); - PDEBUG(4, "leaving"); -} - -/**************************************************************************** - * - * V4L 1 API - * - ***************************************************************************/ - -static int -ov51x_v4l1_open(struct inode *inode, struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct usb_ov511 *ov = video_get_drvdata(vdev); - int err, i; - - PDEBUG(4, "opening"); - - mutex_lock(&ov->lock); - - err = -EBUSY; - if (ov->user) - goto out; - - ov->sub_flag = 0; - - /* In case app doesn't set them... */ - err = ov51x_set_default_params(ov); - if (err < 0) - goto out; - - /* Make sure frames are reset */ - for (i = 0; i < OV511_NUMFRAMES; i++) { - ov->frame[i].grabstate = FRAME_UNUSED; - ov->frame[i].bytes_read = 0; - } - - /* If compression is on, make sure now that a - * decompressor can be loaded */ - if (ov->compress && !ov->decomp_ops) { - err = request_decompressor(ov); - if (err && !dumppix) - goto out; - } - - err = ov51x_alloc(ov); - if (err < 0) - goto out; - - err = ov51x_init_isoc(ov); - if (err) { - ov51x_dealloc(ov); - goto out; - } - - ov->user++; - file->private_data = vdev; - - if (ov->led_policy == LED_AUTO) - ov51x_led_control(ov, 1); - -out: - mutex_unlock(&ov->lock); - return err; -} - -static int -ov51x_v4l1_close(struct inode *inode, struct file *file) -{ - struct video_device *vdev = file->private_data; - struct usb_ov511 *ov = video_get_drvdata(vdev); - - PDEBUG(4, "ov511_close"); - - mutex_lock(&ov->lock); - - ov->user--; - ov51x_stop_isoc(ov); - - if (ov->led_policy == LED_AUTO) - ov51x_led_control(ov, 0); - - if (ov->dev) - ov51x_dealloc(ov); - - mutex_unlock(&ov->lock); - - /* Device unplugged while open. Only a minimum of unregistration is done - * here; the disconnect callback already did the rest. */ - if (!ov->dev) { - mutex_lock(&ov->cbuf_lock); - kfree(ov->cbuf); - ov->cbuf = NULL; - mutex_unlock(&ov->cbuf_lock); - - ov51x_dealloc(ov); - kfree(ov); - ov = NULL; - } - - file->private_data = NULL; - return 0; -} - -/* Do not call this function directly! */ -static int -ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct video_device *vdev = file->private_data; - struct usb_ov511 *ov = video_get_drvdata(vdev); - PDEBUG(5, "IOCtl: 0x%X", cmd); - - if (!ov->dev) - return -EIO; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - - PDEBUG(4, "VIDIOCGCAP"); - - memset(b, 0, sizeof(struct video_capability)); - sprintf(b->name, "%s USB Camera", - symbolic(brglist, ov->bridge)); - b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE; - b->channels = ov->num_inputs; - b->audios = 0; - b->maxwidth = ov->maxwidth; - b->maxheight = ov->maxheight; - b->minwidth = ov->minwidth; - b->minheight = ov->minheight; - - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - - PDEBUG(4, "VIDIOCGCHAN"); - - if ((unsigned)(v->channel) >= ov->num_inputs) { - err("Invalid channel (%d)", v->channel); - return -EINVAL; - } - - v->norm = ov->norm; - v->type = VIDEO_TYPE_CAMERA; - v->flags = 0; -// v->flags |= (ov->has_decoder) ? VIDEO_VC_NORM : 0; - v->tuners = 0; - decoder_get_input_name(ov, v->channel, v->name); - - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - int err; - - PDEBUG(4, "VIDIOCSCHAN"); - - /* Make sure it's not a camera */ - if (!ov->has_decoder) { - if (v->channel == 0) - return 0; - else - return -EINVAL; - } - - if (v->norm != VIDEO_MODE_PAL && - v->norm != VIDEO_MODE_NTSC && - v->norm != VIDEO_MODE_SECAM && - v->norm != VIDEO_MODE_AUTO) { - err("Invalid norm (%d)", v->norm); - return -EINVAL; - } - - if ((unsigned)(v->channel) >= ov->num_inputs) { - err("Invalid channel (%d)", v->channel); - return -EINVAL; - } - - err = decoder_set_input(ov, v->channel); - if (err) - return err; - - err = decoder_set_norm(ov, v->norm); - if (err) - return err; - - return 0; - } - case VIDIOCGPICT: - { - struct video_picture *p = arg; - - PDEBUG(4, "VIDIOCGPICT"); - - memset(p, 0, sizeof(struct video_picture)); - if (sensor_get_picture(ov, p)) - return -EIO; - - /* Can we get these from frame[0]? -claudio? */ - p->depth = ov->frame[0].depth; - p->palette = ov->frame[0].format; - - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *p = arg; - int i, rc; - - PDEBUG(4, "VIDIOCSPICT"); - - if (!get_depth(p->palette)) - return -EINVAL; - - if (sensor_set_picture(ov, p)) - return -EIO; - - if (force_palette && p->palette != force_palette) { - info("Palette rejected (%s)", - symbolic(v4l1_plist, p->palette)); - return -EINVAL; - } - - // FIXME: Format should be independent of frames - if (p->palette != ov->frame[0].format) { - PDEBUG(4, "Detected format change"); - - rc = ov51x_wait_frames_inactive(ov); - if (rc) - return rc; - - mode_init_regs(ov, ov->frame[0].width, - ov->frame[0].height, p->palette, ov->sub_flag); - } - - PDEBUG(4, "Setting depth=%d, palette=%s", - p->depth, symbolic(v4l1_plist, p->palette)); - - for (i = 0; i < OV511_NUMFRAMES; i++) { - ov->frame[i].depth = p->depth; - ov->frame[i].format = p->palette; - } - - return 0; - } - case VIDIOCGCAPTURE: - { - int *vf = arg; - - PDEBUG(4, "VIDIOCGCAPTURE"); - - ov->sub_flag = *vf; - return 0; - } - case VIDIOCSCAPTURE: - { - struct video_capture *vc = arg; - - PDEBUG(4, "VIDIOCSCAPTURE"); - - if (vc->flags) - return -EINVAL; - if (vc->decimation) - return -EINVAL; - - vc->x &= ~3L; - vc->y &= ~1L; - vc->y &= ~31L; - - if (vc->width == 0) - vc->width = 32; - - vc->height /= 16; - vc->height *= 16; - if (vc->height == 0) - vc->height = 16; - - ov->subx = vc->x; - ov->suby = vc->y; - ov->subw = vc->width; - ov->subh = vc->height; - - return 0; - } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - int i, rc; - - PDEBUG(4, "VIDIOCSWIN: %dx%d", vw->width, vw->height); - -#if 0 - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (vw->height != ov->maxheight) - return -EINVAL; - if (vw->width != ov->maxwidth) - return -EINVAL; -#endif - - rc = ov51x_wait_frames_inactive(ov); - if (rc) - return rc; - - rc = mode_init_regs(ov, vw->width, vw->height, - ov->frame[0].format, ov->sub_flag); - if (rc < 0) - return rc; - - for (i = 0; i < OV511_NUMFRAMES; i++) { - ov->frame[i].width = vw->width; - ov->frame[i].height = vw->height; - } - - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; - - memset(vw, 0, sizeof(struct video_window)); - vw->x = 0; /* FIXME */ - vw->y = 0; - vw->width = ov->frame[0].width; - vw->height = ov->frame[0].height; - vw->flags = 30; - - PDEBUG(4, "VIDIOCGWIN: %dx%d", vw->width, vw->height); - - return 0; - } - case VIDIOCGMBUF: - { - struct video_mbuf *vm = arg; - int i; - - PDEBUG(4, "VIDIOCGMBUF"); - - memset(vm, 0, sizeof(struct video_mbuf)); - vm->size = OV511_NUMFRAMES - * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight); - vm->frames = OV511_NUMFRAMES; - - vm->offsets[0] = 0; - for (i = 1; i < OV511_NUMFRAMES; i++) { - vm->offsets[i] = vm->offsets[i-1] - + MAX_DATA_SIZE(ov->maxwidth, ov->maxheight); - } - - return 0; - } - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - int rc, depth; - unsigned int f = vm->frame; - - PDEBUG(4, "VIDIOCMCAPTURE: frame: %d, %dx%d, %s", f, vm->width, - vm->height, symbolic(v4l1_plist, vm->format)); - - depth = get_depth(vm->format); - if (!depth) { - PDEBUG(2, "VIDIOCMCAPTURE: invalid format (%s)", - symbolic(v4l1_plist, vm->format)); - return -EINVAL; - } - - if (f >= OV511_NUMFRAMES) { - err("VIDIOCMCAPTURE: invalid frame (%d)", f); - return -EINVAL; - } - - if (vm->width > ov->maxwidth - || vm->height > ov->maxheight) { - err("VIDIOCMCAPTURE: requested dimensions too big"); - return -EINVAL; - } - - if (ov->frame[f].grabstate == FRAME_GRABBING) { - PDEBUG(4, "VIDIOCMCAPTURE: already grabbing"); - return -EBUSY; - } - - if (force_palette && (vm->format != force_palette)) { - PDEBUG(2, "palette rejected (%s)", - symbolic(v4l1_plist, vm->format)); - return -EINVAL; - } - - if ((ov->frame[f].width != vm->width) || - (ov->frame[f].height != vm->height) || - (ov->frame[f].format != vm->format) || - (ov->frame[f].sub_flag != ov->sub_flag) || - (ov->frame[f].depth != depth)) { - PDEBUG(4, "VIDIOCMCAPTURE: change in image parameters"); - - rc = ov51x_wait_frames_inactive(ov); - if (rc) - return rc; - - rc = mode_init_regs(ov, vm->width, vm->height, - vm->format, ov->sub_flag); -#if 0 - if (rc < 0) { - PDEBUG(1, "Got error while initializing regs "); - return ret; - } -#endif - ov->frame[f].width = vm->width; - ov->frame[f].height = vm->height; - ov->frame[f].format = vm->format; - ov->frame[f].sub_flag = ov->sub_flag; - ov->frame[f].depth = depth; - } - - /* Mark it as ready */ - ov->frame[f].grabstate = FRAME_READY; - - PDEBUG(4, "VIDIOCMCAPTURE: renewing frame %d", f); - - return ov51x_new_frame(ov, f); - } - case VIDIOCSYNC: - { - unsigned int fnum = *((unsigned int *) arg); - struct ov511_frame *frame; - int rc; - - if (fnum >= OV511_NUMFRAMES) { - err("VIDIOCSYNC: invalid frame (%d)", fnum); - return -EINVAL; - } - - frame = &ov->frame[fnum]; - - PDEBUG(4, "syncing to frame %d, grabstate = %d", fnum, - frame->grabstate); - - switch (frame->grabstate) { - case FRAME_UNUSED: - return -EINVAL; - case FRAME_READY: - case FRAME_GRABBING: - case FRAME_ERROR: -redo: - if (!ov->dev) - return -EIO; - - rc = wait_event_interruptible(frame->wq, - (frame->grabstate == FRAME_DONE) - || (frame->grabstate == FRAME_ERROR)); - - if (rc) - return rc; - - if (frame->grabstate == FRAME_ERROR) { - if ((rc = ov51x_new_frame(ov, fnum)) < 0) - return rc; - goto redo; - } - /* Fall through */ - case FRAME_DONE: - if (ov->snap_enabled && !frame->snapshot) { - if ((rc = ov51x_new_frame(ov, fnum)) < 0) - return rc; - goto redo; - } - - frame->grabstate = FRAME_UNUSED; - - /* Reset the hardware snapshot button */ - /* FIXME - Is this the best place for this? */ - if ((ov->snap_enabled) && (frame->snapshot)) { - frame->snapshot = 0; - ov51x_clear_snapshot(ov); - } - - /* Decompression, format conversion, etc... */ - ov51x_postprocess(ov, frame); - - break; - } /* end switch */ - - return 0; - } - case VIDIOCGFBUF: - { - struct video_buffer *vb = arg; - - PDEBUG(4, "VIDIOCGFBUF"); - - memset(vb, 0, sizeof(struct video_buffer)); - - return 0; - } - case VIDIOCGUNIT: - { - struct video_unit *vu = arg; - - PDEBUG(4, "VIDIOCGUNIT"); - - memset(vu, 0, sizeof(struct video_unit)); - - vu->video = ov->vdev->minor; - vu->vbi = VIDEO_NO_UNIT; - vu->radio = VIDEO_NO_UNIT; - vu->audio = VIDEO_NO_UNIT; - vu->teletext = VIDEO_NO_UNIT; - - return 0; - } - case OV511IOC_WI2C: - { - struct ov511_i2c_struct *w = arg; - - return i2c_w_slave(ov, w->slave, w->reg, w->value, w->mask); - } - case OV511IOC_RI2C: - { - struct ov511_i2c_struct *r = arg; - int rc; - - rc = i2c_r_slave(ov, r->slave, r->reg); - if (rc < 0) - return rc; - - r->value = rc; - return 0; - } - default: - PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd); - return -ENOIOCTLCMD; - } /* end switch */ - - return 0; -} - -static int -ov51x_v4l1_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct video_device *vdev = file->private_data; - struct usb_ov511 *ov = video_get_drvdata(vdev); - int rc; - - if (mutex_lock_interruptible(&ov->lock)) - return -EINTR; - - rc = video_usercopy(inode, file, cmd, arg, ov51x_v4l1_ioctl_internal); - - mutex_unlock(&ov->lock); - return rc; -} - -static ssize_t -ov51x_v4l1_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos) -{ - struct video_device *vdev = file->private_data; - int noblock = file->f_flags&O_NONBLOCK; - unsigned long count = cnt; - struct usb_ov511 *ov = video_get_drvdata(vdev); - int i, rc = 0, frmx = -1; - struct ov511_frame *frame; - - if (mutex_lock_interruptible(&ov->lock)) - return -EINTR; - - PDEBUG(4, "%ld bytes, noblock=%d", count, noblock); - - if (!vdev || !buf) { - rc = -EFAULT; - goto error; - } - - if (!ov->dev) { - rc = -EIO; - goto error; - } - -// FIXME: Only supports two frames - /* See if a frame is completed, then use it. */ - if (ov->frame[0].grabstate >= FRAME_DONE) /* _DONE or _ERROR */ - frmx = 0; - else if (ov->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */ - frmx = 1; - - /* If nonblocking we return immediately */ - if (noblock && (frmx == -1)) { - rc = -EAGAIN; - goto error; - } - - /* If no FRAME_DONE, look for a FRAME_GRABBING state. */ - /* See if a frame is in process (grabbing), then use it. */ - if (frmx == -1) { - if (ov->frame[0].grabstate == FRAME_GRABBING) - frmx = 0; - else if (ov->frame[1].grabstate == FRAME_GRABBING) - frmx = 1; - } - - /* If no frame is active, start one. */ - if (frmx == -1) { - if ((rc = ov51x_new_frame(ov, frmx = 0))) { - err("read: ov51x_new_frame error"); - goto error; - } - } - - frame = &ov->frame[frmx]; - -restart: - if (!ov->dev) { - rc = -EIO; - goto error; - } - - /* Wait while we're grabbing the image */ - PDEBUG(4, "Waiting image grabbing"); - rc = wait_event_interruptible(frame->wq, - (frame->grabstate == FRAME_DONE) - || (frame->grabstate == FRAME_ERROR)); - - if (rc) - goto error; - - PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate); - PDEBUG(4, "bytes_recvd = %d", frame->bytes_recvd); - - if (frame->grabstate == FRAME_ERROR) { - frame->bytes_read = 0; - err("** ick! ** Errored frame %d", ov->curframe); - if (ov51x_new_frame(ov, frmx)) { - err("read: ov51x_new_frame error"); - goto error; - } - goto restart; - } - - - /* Repeat until we get a snapshot frame */ - if (ov->snap_enabled) - PDEBUG(4, "Waiting snapshot frame"); - if (ov->snap_enabled && !frame->snapshot) { - frame->bytes_read = 0; - if ((rc = ov51x_new_frame(ov, frmx))) { - err("read: ov51x_new_frame error"); - goto error; - } - goto restart; - } - - /* Clear the snapshot */ - if (ov->snap_enabled && frame->snapshot) { - frame->snapshot = 0; - ov51x_clear_snapshot(ov); - } - - /* Decompression, format conversion, etc... */ - ov51x_postprocess(ov, frame); - - PDEBUG(4, "frmx=%d, bytes_read=%ld, length=%ld", frmx, - frame->bytes_read, - get_frame_length(frame)); - - /* copy bytes to user space; we allow for partials reads */ -// if ((count + frame->bytes_read) -// > get_frame_length((struct ov511_frame *)frame)) -// count = frame->scanlength - frame->bytes_read; - - /* FIXME - count hardwired to be one frame... */ - count = get_frame_length(frame); - - PDEBUG(4, "Copy to user space: %ld bytes", count); - if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) { - PDEBUG(4, "Copy failed! %d bytes not copied", i); - rc = -EFAULT; - goto error; - } - - frame->bytes_read += count; - PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld", - count, frame->bytes_read); - - /* If all data have been read... */ - if (frame->bytes_read - >= get_frame_length(frame)) { - frame->bytes_read = 0; - -// FIXME: Only supports two frames - /* Mark it as available to be used again. */ - ov->frame[frmx].grabstate = FRAME_UNUSED; - if ((rc = ov51x_new_frame(ov, !frmx))) { - err("ov51x_new_frame returned error"); - goto error; - } - } - - PDEBUG(4, "read finished, returning %ld (sweet)", count); - - mutex_unlock(&ov->lock); - return count; - -error: - mutex_unlock(&ov->lock); - return rc; -} - -static int -ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct video_device *vdev = file->private_data; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end - vma->vm_start; - struct usb_ov511 *ov = video_get_drvdata(vdev); - unsigned long page, pos; - - if (ov->dev == NULL) - return -EIO; - - PDEBUG(4, "mmap: %ld (%lX) bytes", size, size); - - if (size > (((OV511_NUMFRAMES - * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight) - + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))) - return -EINVAL; - - if (mutex_lock_interruptible(&ov->lock)) - return -EINTR; - - pos = (unsigned long)ov->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - mutex_unlock(&ov->lock); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - mutex_unlock(&ov->lock); - return 0; -} - -static struct file_operations ov511_fops = { - .owner = THIS_MODULE, - .open = ov51x_v4l1_open, - .release = ov51x_v4l1_close, - .read = ov51x_v4l1_read, - .mmap = ov51x_v4l1_mmap, - .ioctl = ov51x_v4l1_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, -}; - -static struct video_device vdev_template = { - .owner = THIS_MODULE, - .name = "OV511 USB Camera", - .type = VID_TYPE_CAPTURE, - .hardware = VID_HARDWARE_OV511, - .fops = &ov511_fops, - .release = video_device_release, - .minor = -1, -}; - -/**************************************************************************** - * - * OV511 and sensor configuration - * - ***************************************************************************/ - -/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses - * the same register settings as the OV7610, since they are very similar. - */ -static int -ov7xx0_configure(struct usb_ov511 *ov) -{ - int i, success; - int rc; - - /* Lawrence Glaister reports: - * - * Register 0x0f in the 7610 has the following effects: - * - * 0x85 (AEC method 1): Best overall, good contrast range - * 0x45 (AEC method 2): Very overexposed - * 0xa5 (spec sheet default): Ok, but the black level is - * shifted resulting in loss of contrast - * 0x05 (old driver setting): very overexposed, too much - * contrast - */ - static struct ov511_regvals aRegvalsNorm7610[] = { - { OV511_I2C_BUS, 0x10, 0xff }, - { OV511_I2C_BUS, 0x16, 0x06 }, - { OV511_I2C_BUS, 0x28, 0x24 }, - { OV511_I2C_BUS, 0x2b, 0xac }, - { OV511_I2C_BUS, 0x12, 0x00 }, - { OV511_I2C_BUS, 0x38, 0x81 }, - { OV511_I2C_BUS, 0x28, 0x24 }, /* 0c */ - { OV511_I2C_BUS, 0x0f, 0x85 }, /* lg's setting */ - { OV511_I2C_BUS, 0x15, 0x01 }, - { OV511_I2C_BUS, 0x20, 0x1c }, - { OV511_I2C_BUS, 0x23, 0x2a }, - { OV511_I2C_BUS, 0x24, 0x10 }, - { OV511_I2C_BUS, 0x25, 0x8a }, - { OV511_I2C_BUS, 0x26, 0xa2 }, - { OV511_I2C_BUS, 0x27, 0xc2 }, - { OV511_I2C_BUS, 0x2a, 0x04 }, - { OV511_I2C_BUS, 0x2c, 0xfe }, - { OV511_I2C_BUS, 0x2d, 0x93 }, - { OV511_I2C_BUS, 0x30, 0x71 }, - { OV511_I2C_BUS, 0x31, 0x60 }, - { OV511_I2C_BUS, 0x32, 0x26 }, - { OV511_I2C_BUS, 0x33, 0x20 }, - { OV511_I2C_BUS, 0x34, 0x48 }, - { OV511_I2C_BUS, 0x12, 0x24 }, - { OV511_I2C_BUS, 0x11, 0x01 }, - { OV511_I2C_BUS, 0x0c, 0x24 }, - { OV511_I2C_BUS, 0x0d, 0x24 }, - { OV511_DONE_BUS, 0x0, 0x00 }, - }; - - static struct ov511_regvals aRegvalsNorm7620[] = { - { OV511_I2C_BUS, 0x00, 0x00 }, - { OV511_I2C_BUS, 0x01, 0x80 }, - { OV511_I2C_BUS, 0x02, 0x80 }, - { OV511_I2C_BUS, 0x03, 0xc0 }, - { OV511_I2C_BUS, 0x06, 0x60 }, - { OV511_I2C_BUS, 0x07, 0x00 }, - { OV511_I2C_BUS, 0x0c, 0x24 }, - { OV511_I2C_BUS, 0x0c, 0x24 }, - { OV511_I2C_BUS, 0x0d, 0x24 }, - { OV511_I2C_BUS, 0x11, 0x01 }, - { OV511_I2C_BUS, 0x12, 0x24 }, - { OV511_I2C_BUS, 0x13, 0x01 }, - { OV511_I2C_BUS, 0x14, 0x84 }, - { OV511_I2C_BUS, 0x15, 0x01 }, - { OV511_I2C_BUS, 0x16, 0x03 }, - { OV511_I2C_BUS, 0x17, 0x2f }, - { OV511_I2C_BUS, 0x18, 0xcf }, - { OV511_I2C_BUS, 0x19, 0x06 }, - { OV511_I2C_BUS, 0x1a, 0xf5 }, - { OV511_I2C_BUS, 0x1b, 0x00 }, - { OV511_I2C_BUS, 0x20, 0x18 }, - { OV511_I2C_BUS, 0x21, 0x80 }, - { OV511_I2C_BUS, 0x22, 0x80 }, - { OV511_I2C_BUS, 0x23, 0x00 }, - { OV511_I2C_BUS, 0x26, 0xa2 }, - { OV511_I2C_BUS, 0x27, 0xea }, - { OV511_I2C_BUS, 0x28, 0x20 }, - { OV511_I2C_BUS, 0x29, 0x00 }, - { OV511_I2C_BUS, 0x2a, 0x10 }, - { OV511_I2C_BUS, 0x2b, 0x00 }, - { OV511_I2C_BUS, 0x2c, 0x88 }, - { OV511_I2C_BUS, 0x2d, 0x91 }, - { OV511_I2C_BUS, 0x2e, 0x80 }, - { OV511_I2C_BUS, 0x2f, 0x44 }, - { OV511_I2C_BUS, 0x60, 0x27 }, - { OV511_I2C_BUS, 0x61, 0x02 }, - { OV511_I2C_BUS, 0x62, 0x5f }, - { OV511_I2C_BUS, 0x63, 0xd5 }, - { OV511_I2C_BUS, 0x64, 0x57 }, - { OV511_I2C_BUS, 0x65, 0x83 }, - { OV511_I2C_BUS, 0x66, 0x55 }, - { OV511_I2C_BUS, 0x67, 0x92 }, - { OV511_I2C_BUS, 0x68, 0xcf }, - { OV511_I2C_BUS, 0x69, 0x76 }, - { OV511_I2C_BUS, 0x6a, 0x22 }, - { OV511_I2C_BUS, 0x6b, 0x00 }, - { OV511_I2C_BUS, 0x6c, 0x02 }, - { OV511_I2C_BUS, 0x6d, 0x44 }, - { OV511_I2C_BUS, 0x6e, 0x80 }, - { OV511_I2C_BUS, 0x6f, 0x1d }, - { OV511_I2C_BUS, 0x70, 0x8b }, - { OV511_I2C_BUS, 0x71, 0x00 }, - { OV511_I2C_BUS, 0x72, 0x14 }, - { OV511_I2C_BUS, 0x73, 0x54 }, - { OV511_I2C_BUS, 0x74, 0x00 }, - { OV511_I2C_BUS, 0x75, 0x8e }, - { OV511_I2C_BUS, 0x76, 0x00 }, - { OV511_I2C_BUS, 0x77, 0xff }, - { OV511_I2C_BUS, 0x78, 0x80 }, - { OV511_I2C_BUS, 0x79, 0x80 }, - { OV511_I2C_BUS, 0x7a, 0x80 }, - { OV511_I2C_BUS, 0x7b, 0xe2 }, - { OV511_I2C_BUS, 0x7c, 0x00 }, - { OV511_DONE_BUS, 0x0, 0x00 }, - }; - - PDEBUG(4, "starting configuration"); - - /* This looks redundant, but is necessary for WebCam 3 */ - ov->primary_i2c_slave = OV7xx0_SID; - if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) - return -1; - - if (init_ov_sensor(ov) >= 0) { - PDEBUG(1, "OV7xx0 sensor initalized (method 1)"); - } else { - /* Reset the 76xx */ - if (i2c_w(ov, 0x12, 0x80) < 0) - return -1; - - /* Wait for it to initialize */ - msleep(150); - - i = 0; - success = 0; - while (i <= i2c_detect_tries) { - if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) && - (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) { - success = 1; - break; - } else { - i++; - } - } - -// Was (i == i2c_detect_tries) previously. This obviously used to always report -// success. Whether anyone actually depended on that bug is unknown - if ((i >= i2c_detect_tries) && (success == 0)) { - err("Failed to read sensor ID. You might not have an"); - err("OV7610/20, or it may be not responding. Report"); - err("this to " EMAIL); - err("This is only a warning. You can attempt to use"); - err("your camera anyway"); -// Only issue a warning for now -// return -1; - } else { - PDEBUG(1, "OV7xx0 initialized (method 2, %dx)", i+1); - } - } - - /* Detect sensor (sub)type */ - rc = i2c_r(ov, OV7610_REG_COM_I); - - if (rc < 0) { - err("Error detecting sensor type"); - return -1; - } else if ((rc & 3) == 3) { - info("Sensor is an OV7610"); - ov->sensor = SEN_OV7610; - } else if ((rc & 3) == 1) { - /* I don't know what's different about the 76BE yet. */ - if (i2c_r(ov, 0x15) & 1) - info("Sensor is an OV7620AE"); - else - info("Sensor is an OV76BE"); - - /* OV511+ will return all zero isoc data unless we - * configure the sensor as a 7620. Someone needs to - * find the exact reg. setting that causes this. */ - if (ov->bridge == BRG_OV511PLUS) { - info("Enabling 511+/7620AE workaround"); - ov->sensor = SEN_OV7620; - } else { - ov->sensor = SEN_OV76BE; - } - } else if ((rc & 3) == 0) { - info("Sensor is an OV7620"); - ov->sensor = SEN_OV7620; - } else { - err("Unknown image sensor version: %d", rc & 3); - return -1; - } - - if (ov->sensor == SEN_OV7620) { - PDEBUG(4, "Writing 7620 registers"); - if (write_regvals(ov, aRegvalsNorm7620)) - return -1; - } else { - PDEBUG(4, "Writing 7610 registers"); - if (write_regvals(ov, aRegvalsNorm7610)) - return -1; - } - - /* Set sensor-specific vars */ - ov->maxwidth = 640; - ov->maxheight = 480; - ov->minwidth = 64; - ov->minheight = 48; - - // FIXME: These do not match the actual settings yet - ov->brightness = 0x80 << 8; - ov->contrast = 0x80 << 8; - ov->colour = 0x80 << 8; - ov->hue = 0x80 << 8; - - return 0; -} - -/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */ -static int -ov6xx0_configure(struct usb_ov511 *ov) -{ - int rc; - - static struct ov511_regvals aRegvalsNorm6x20[] = { - { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */ - { OV511_I2C_BUS, 0x11, 0x01 }, - { OV511_I2C_BUS, 0x03, 0x60 }, - { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */ - { OV511_I2C_BUS, 0x07, 0xa8 }, - /* The ratio of 0x0c and 0x0d controls the white point */ - { OV511_I2C_BUS, 0x0c, 0x24 }, - { OV511_I2C_BUS, 0x0d, 0x24 }, - { OV511_I2C_BUS, 0x0f, 0x15 }, /* COMS */ - { OV511_I2C_BUS, 0x10, 0x75 }, /* AEC Exposure time */ - { OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */ - { OV511_I2C_BUS, 0x14, 0x04 }, - /* 0x16: 0x06 helps frame stability with moving objects */ - { OV511_I2C_BUS, 0x16, 0x06 }, -// { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */ - { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */ - /* 0x28: 0x05 Selects RGB format if RGB on */ - { OV511_I2C_BUS, 0x28, 0x05 }, - { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */ -// { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */ - { OV511_I2C_BUS, 0x2d, 0x99 }, - { OV511_I2C_BUS, 0x33, 0xa0 }, /* Color Processing Parameter */ - { OV511_I2C_BUS, 0x34, 0xd2 }, /* Max A/D range */ - { OV511_I2C_BUS, 0x38, 0x8b }, - { OV511_I2C_BUS, 0x39, 0x40 }, - - { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */ - { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */ - { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */ - - { OV511_I2C_BUS, 0x3d, 0x80 }, - /* These next two registers (0x4a, 0x4b) are undocumented. They - * control the color balance */ - { OV511_I2C_BUS, 0x4a, 0x80 }, - { OV511_I2C_BUS, 0x4b, 0x80 }, - { OV511_I2C_BUS, 0x4d, 0xd2 }, /* This reduces noise a bit */ - { OV511_I2C_BUS, 0x4e, 0xc1 }, - { OV511_I2C_BUS, 0x4f, 0x04 }, -// Do 50-53 have any effect? -// Toggle 0x12[2] off and on here? - { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ - }; - - static struct ov511_regvals aRegvalsNorm6x30[] = { - /*OK*/ { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */ - { OV511_I2C_BUS, 0x11, 0x00 }, - /*OK*/ { OV511_I2C_BUS, 0x03, 0x60 }, - /*0A?*/ { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */ - { OV511_I2C_BUS, 0x07, 0xa8 }, - /* The ratio of 0x0c and 0x0d controls the white point */ - /*OK*/ { OV511_I2C_BUS, 0x0c, 0x24 }, - /*OK*/ { OV511_I2C_BUS, 0x0d, 0x24 }, - /*A*/ { OV511_I2C_BUS, 0x0e, 0x20 }, -// /*04?*/ { OV511_I2C_BUS, 0x14, 0x80 }, - { OV511_I2C_BUS, 0x16, 0x03 }, -// /*OK*/ { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */ - // 21 & 22? The suggested values look wrong. Go with default - /*A*/ { OV511_I2C_BUS, 0x23, 0xc0 }, - /*A*/ { OV511_I2C_BUS, 0x25, 0x9a }, // Check this against default -// /*OK*/ { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */ - - /* 0x28: 0x05 Selects RGB format if RGB on */ -// /*04?*/ { OV511_I2C_BUS, 0x28, 0x05 }, -// /*04?*/ { OV511_I2C_BUS, 0x28, 0x45 }, // DEBUG: Tristate UV bus - - /*OK*/ { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */ -// /*OK*/ { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */ - { OV511_I2C_BUS, 0x2d, 0x99 }, -// /*A*/ { OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620 -// /*d2?*/ { OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */ -// /*8b?*/ { OV511_I2C_BUS, 0x38, 0x83 }, -// /*40?*/ { OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7 -// { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */ -// { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */ -// { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */ - { OV511_I2C_BUS, 0x3d, 0x80 }, -// /*A*/ { OV511_I2C_BUS, 0x3f, 0x0e }, - - /* These next two registers (0x4a, 0x4b) are undocumented. They - * control the color balance */ -// /*OK?*/ { OV511_I2C_BUS, 0x4a, 0x80 }, // Check these -// /*OK?*/ { OV511_I2C_BUS, 0x4b, 0x80 }, - { OV511_I2C_BUS, 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ - /*c1?*/ { OV511_I2C_BUS, 0x4e, 0x40 }, - - /* UV average mode, color killer: strongest */ - { OV511_I2C_BUS, 0x4f, 0x07 }, - - { OV511_I2C_BUS, 0x54, 0x23 }, /* Max AGC gain: 18dB */ - { OV511_I2C_BUS, 0x57, 0x81 }, /* (default) */ - { OV511_I2C_BUS, 0x59, 0x01 }, /* AGC dark current comp: +1 */ - { OV511_I2C_BUS, 0x5a, 0x2c }, /* (undocumented) */ - { OV511_I2C_BUS, 0x5b, 0x0f }, /* AWB chrominance levels */ -// { OV511_I2C_BUS, 0x5c, 0x10 }, - { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ - }; - - PDEBUG(4, "starting sensor configuration"); - - if (init_ov_sensor(ov) < 0) { - err("Failed to read sensor ID. You might not have an OV6xx0,"); - err("or it may be not responding. Report this to " EMAIL); - return -1; - } else { - PDEBUG(1, "OV6xx0 sensor detected"); - } - - /* Detect sensor (sub)type */ - rc = i2c_r(ov, OV7610_REG_COM_I); - - if (rc < 0) { - err("Error detecting sensor type"); - return -1; - } - - if ((rc & 3) == 0) { - ov->sensor = SEN_OV6630; - info("Sensor is an OV6630"); - } else if ((rc & 3) == 1) { - ov->sensor = SEN_OV6620; - info("Sensor is an OV6620"); - } else if ((rc & 3) == 2) { - ov->sensor = SEN_OV6630; - info("Sensor is an OV6630AE"); - } else if ((rc & 3) == 3) { - ov->sensor = SEN_OV6630; - info("Sensor is an OV6630AF"); - } - - /* Set sensor-specific vars */ - ov->maxwidth = 352; - ov->maxheight = 288; - ov->minwidth = 64; - ov->minheight = 48; - - // FIXME: These do not match the actual settings yet - ov->brightness = 0x80 << 8; - ov->contrast = 0x80 << 8; - ov->colour = 0x80 << 8; - ov->hue = 0x80 << 8; - - if (ov->sensor == SEN_OV6620) { - PDEBUG(4, "Writing 6x20 registers"); - if (write_regvals(ov, aRegvalsNorm6x20)) - return -1; - } else { - PDEBUG(4, "Writing 6x30 registers"); - if (write_regvals(ov, aRegvalsNorm6x30)) - return -1; - } - - return 0; -} - -/* This initializes the KS0127 and KS0127B video decoders. */ -static int -ks0127_configure(struct usb_ov511 *ov) -{ - int rc; - -// FIXME: I don't know how to sync or reset it yet -#if 0 - if (ov51x_init_ks_sensor(ov) < 0) { - err("Failed to initialize the KS0127"); - return -1; - } else { - PDEBUG(1, "KS012x(B) sensor detected"); - } -#endif - - /* Detect decoder subtype */ - rc = i2c_r(ov, 0x00); - if (rc < 0) { - err("Error detecting sensor type"); - return -1; - } else if (rc & 0x08) { - rc = i2c_r(ov, 0x3d); - if (rc < 0) { - err("Error detecting sensor type"); - return -1; - } else if ((rc & 0x0f) == 0) { - info("Sensor is a KS0127"); - ov->sensor = SEN_KS0127; - } else if ((rc & 0x0f) == 9) { - info("Sensor is a KS0127B Rev. A"); - ov->sensor = SEN_KS0127B; - } - } else { - err("Error: Sensor is an unsupported KS0122"); - return -1; - } - - /* Set sensor-specific vars */ - ov->maxwidth = 640; - ov->maxheight = 480; - ov->minwidth = 64; - ov->minheight = 48; - - // FIXME: These do not match the actual settings yet - ov->brightness = 0x80 << 8; - ov->contrast = 0x80 << 8; - ov->colour = 0x80 << 8; - ov->hue = 0x80 << 8; - - /* This device is not supported yet. Bail out now... */ - err("This sensor is not supported yet."); - return -1; - - return 0; -} - -/* This initializes the SAA7111A video decoder. */ -static int -saa7111a_configure(struct usb_ov511 *ov) -{ - int rc; - - /* Since there is no register reset command, all registers must be - * written, otherwise gives erratic results */ - static struct ov511_regvals aRegvalsNormSAA7111A[] = { - { OV511_I2C_BUS, 0x06, 0xce }, - { OV511_I2C_BUS, 0x07, 0x00 }, - { OV511_I2C_BUS, 0x10, 0x44 }, /* YUV422, 240/286 lines */ - { OV511_I2C_BUS, 0x0e, 0x01 }, /* NTSC M or PAL BGHI */ - { OV511_I2C_BUS, 0x00, 0x00 }, - { OV511_I2C_BUS, 0x01, 0x00 }, - { OV511_I2C_BUS, 0x03, 0x23 }, - { OV511_I2C_BUS, 0x04, 0x00 }, - { OV511_I2C_BUS, 0x05, 0x00 }, - { OV511_I2C_BUS, 0x08, 0xc8 }, /* Auto field freq */ - { OV511_I2C_BUS, 0x09, 0x01 }, /* Chrom. trap off, APER=0.25 */ - { OV511_I2C_BUS, 0x0a, 0x80 }, /* BRIG=128 */ - { OV511_I2C_BUS, 0x0b, 0x40 }, /* CONT=1.0 */ - { OV511_I2C_BUS, 0x0c, 0x40 }, /* SATN=1.0 */ - { OV511_I2C_BUS, 0x0d, 0x00 }, /* HUE=0 */ - { OV511_I2C_BUS, 0x0f, 0x00 }, - { OV511_I2C_BUS, 0x11, 0x0c }, - { OV511_I2C_BUS, 0x12, 0x00 }, - { OV511_I2C_BUS, 0x13, 0x00 }, - { OV511_I2C_BUS, 0x14, 0x00 }, - { OV511_I2C_BUS, 0x15, 0x00 }, - { OV511_I2C_BUS, 0x16, 0x00 }, - { OV511_I2C_BUS, 0x17, 0x00 }, - { OV511_I2C_BUS, 0x02, 0xc0 }, /* Composite input 0 */ - { OV511_DONE_BUS, 0x0, 0x00 }, - }; - -// FIXME: I don't know how to sync or reset it yet -#if 0 - if (ov51x_init_saa_sensor(ov) < 0) { - err("Failed to initialize the SAA7111A"); - return -1; - } else { - PDEBUG(1, "SAA7111A sensor detected"); - } -#endif - - /* 640x480 not supported with PAL */ - if (ov->pal) { - ov->maxwidth = 320; - ov->maxheight = 240; /* Even field only */ - } else { - ov->maxwidth = 640; - ov->maxheight = 480; /* Even/Odd fields */ - } - - ov->minwidth = 320; - ov->minheight = 240; /* Even field only */ - - ov->has_decoder = 1; - ov->num_inputs = 8; - ov->norm = VIDEO_MODE_AUTO; - ov->stop_during_set = 0; /* Decoder guarantees stable image */ - - /* Decoder doesn't change these values, so we use these instead of - * acutally reading the registers (which doesn't work) */ - ov->brightness = 0x80 << 8; - ov->contrast = 0x40 << 9; - ov->colour = 0x40 << 9; - ov->hue = 32768; - - PDEBUG(4, "Writing SAA7111A registers"); - if (write_regvals(ov, aRegvalsNormSAA7111A)) - return -1; - - /* Detect version of decoder. This must be done after writing the - * initial regs or the decoder will lock up. */ - rc = i2c_r(ov, 0x00); - - if (rc < 0) { - err("Error detecting sensor version"); - return -1; - } else { - info("Sensor is an SAA7111A (version 0x%x)", rc); - ov->sensor = SEN_SAA7111A; - } - - // FIXME: Fix this for OV518(+) - /* Latch to negative edge of clock. Otherwise, we get incorrect - * colors and jitter in the digital signal. */ - if (ov->bclass == BCL_OV511) - reg_w(ov, 0x11, 0x00); - else - warn("SAA7111A not yet supported with OV518/OV518+"); - - return 0; -} - -/* This initializes the OV511/OV511+ and the sensor */ -static int -ov511_configure(struct usb_ov511 *ov) -{ - static struct ov511_regvals aRegvalsInit511[] = { - { OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, - { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, - { OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, - { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, - { OV511_REG_BUS, R51x_SYS_RESET, 0x3f }, - { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, - { OV511_REG_BUS, R51x_SYS_RESET, 0x3d }, - { OV511_DONE_BUS, 0x0, 0x00}, - }; - - static struct ov511_regvals aRegvalsNorm511[] = { - { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0x01 }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, - { OV511_REG_BUS, R511_FIFO_OPTS, 0x1f }, - { OV511_REG_BUS, R511_COMP_EN, 0x00 }, - { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 }, - { OV511_DONE_BUS, 0x0, 0x00 }, - }; - - static struct ov511_regvals aRegvalsNorm511Plus[] = { - { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0xff }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, - { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, - { OV511_REG_BUS, R511_FIFO_OPTS, 0xff }, - { OV511_REG_BUS, R511_COMP_EN, 0x00 }, - { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 }, - { OV511_DONE_BUS, 0x0, 0x00 }, - }; - - PDEBUG(4, ""); - - ov->customid = reg_r(ov, R511_SYS_CUST_ID); - if (ov->customid < 0) { - err("Unable to read camera bridge registers"); - goto error; - } - - PDEBUG (1, "CustomID = %d", ov->customid); - ov->desc = symbolic(camlist, ov->customid); - info("model: %s", ov->desc); - - if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) { - err("Camera type (%d) not recognized", ov->customid); - err("Please notify " EMAIL " of the name,"); - err("manufacturer, model, and this number of your camera."); - err("Also include the output of the detection process."); - } - - if (ov->customid == 70) /* USB Life TV (PAL/SECAM) */ - ov->pal = 1; - - if (write_regvals(ov, aRegvalsInit511)) - goto error; - - if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO) - ov51x_led_control(ov, 0); - - /* The OV511+ has undocumented bits in the flow control register. - * Setting it to 0xff fixes the corruption with moving objects. */ - if (ov->bridge == BRG_OV511) { - if (write_regvals(ov, aRegvalsNorm511)) - goto error; - } else if (ov->bridge == BRG_OV511PLUS) { - if (write_regvals(ov, aRegvalsNorm511Plus)) - goto error; - } else { - err("Invalid bridge"); - } - - if (ov511_init_compression(ov)) - goto error; - - ov->packet_numbering = 1; - ov511_set_packet_size(ov, 0); - - ov->snap_enabled = snapshot; - - /* Test for 7xx0 */ - PDEBUG(3, "Testing for 0V7xx0"); - ov->primary_i2c_slave = OV7xx0_SID; - if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) - goto error; - - if (i2c_w(ov, 0x12, 0x80) < 0) { - /* Test for 6xx0 */ - PDEBUG(3, "Testing for 0V6xx0"); - ov->primary_i2c_slave = OV6xx0_SID; - if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0) - goto error; - - if (i2c_w(ov, 0x12, 0x80) < 0) { - /* Test for 8xx0 */ - PDEBUG(3, "Testing for 0V8xx0"); - ov->primary_i2c_slave = OV8xx0_SID; - if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0) - goto error; - - if (i2c_w(ov, 0x12, 0x80) < 0) { - /* Test for SAA7111A */ - PDEBUG(3, "Testing for SAA7111A"); - ov->primary_i2c_slave = SAA7111A_SID; - if (ov51x_set_slave_ids(ov, SAA7111A_SID) < 0) - goto error; - - if (i2c_w(ov, 0x0d, 0x00) < 0) { - /* Test for KS0127 */ - PDEBUG(3, "Testing for KS0127"); - ov->primary_i2c_slave = KS0127_SID; - if (ov51x_set_slave_ids(ov, KS0127_SID) < 0) - goto error; - - if (i2c_w(ov, 0x10, 0x00) < 0) { - err("Can't determine sensor slave IDs"); - goto error; - } else { - if (ks0127_configure(ov) < 0) { - err("Failed to configure KS0127"); - goto error; - } - } - } else { - if (saa7111a_configure(ov) < 0) { - err("Failed to configure SAA7111A"); - goto error; - } - } - } else { - err("Detected unsupported OV8xx0 sensor"); - goto error; - } - } else { - if (ov6xx0_configure(ov) < 0) { - err("Failed to configure OV6xx0"); - goto error; - } - } - } else { - if (ov7xx0_configure(ov) < 0) { - err("Failed to configure OV7xx0"); - goto error; - } - } - - return 0; - -error: - err("OV511 Config failed"); - - return -EBUSY; -} - -/* This initializes the OV518/OV518+ and the sensor */ -static int -ov518_configure(struct usb_ov511 *ov) -{ - /* For 518 and 518+ */ - static struct ov511_regvals aRegvalsInit518[] = { - { OV511_REG_BUS, R51x_SYS_RESET, 0x40 }, - { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, - { OV511_REG_BUS, R51x_SYS_RESET, 0x3e }, - { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, - { OV511_REG_BUS, R51x_SYS_RESET, 0x00 }, - { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, - { OV511_REG_BUS, 0x46, 0x00 }, - { OV511_REG_BUS, 0x5d, 0x03 }, - { OV511_DONE_BUS, 0x0, 0x00}, - }; - - static struct ov511_regvals aRegvalsNorm518[] = { - { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */ - { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */ - { OV511_REG_BUS, 0x31, 0x0f }, - { OV511_REG_BUS, 0x5d, 0x03 }, - { OV511_REG_BUS, 0x24, 0x9f }, - { OV511_REG_BUS, 0x25, 0x90 }, - { OV511_REG_BUS, 0x20, 0x00 }, - { OV511_REG_BUS, 0x51, 0x04 }, - { OV511_REG_BUS, 0x71, 0x19 }, - { OV511_DONE_BUS, 0x0, 0x00 }, - }; - - static struct ov511_regvals aRegvalsNorm518Plus[] = { - { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */ - { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */ - { OV511_REG_BUS, 0x31, 0x0f }, - { OV511_REG_BUS, 0x5d, 0x03 }, - { OV511_REG_BUS, 0x24, 0x9f }, - { OV511_REG_BUS, 0x25, 0x90 }, - { OV511_REG_BUS, 0x20, 0x60 }, - { OV511_REG_BUS, 0x51, 0x02 }, - { OV511_REG_BUS, 0x71, 0x19 }, - { OV511_REG_BUS, 0x40, 0xff }, - { OV511_REG_BUS, 0x41, 0x42 }, - { OV511_REG_BUS, 0x46, 0x00 }, - { OV511_REG_BUS, 0x33, 0x04 }, - { OV511_REG_BUS, 0x21, 0x19 }, - { OV511_REG_BUS, 0x3f, 0x10 }, - { OV511_DONE_BUS, 0x0, 0x00 }, - }; - - PDEBUG(4, ""); - - /* First 5 bits of custom ID reg are a revision ID on OV518 */ - info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID)); - - /* Give it the default description */ - ov->desc = symbolic(camlist, 0); - - if (write_regvals(ov, aRegvalsInit518)) - goto error; - - /* Set LED GPIO pin to output mode */ - if (reg_w_mask(ov, 0x57, 0x00, 0x02) < 0) - goto error; - - /* LED is off by default with OV518; have to explicitly turn it on */ - if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO) - ov51x_led_control(ov, 0); - else - ov51x_led_control(ov, 1); - - /* Don't require compression if dumppix is enabled; otherwise it's - * required. OV518 has no uncompressed mode, to save RAM. */ - if (!dumppix && !ov->compress) { - ov->compress = 1; - warn("Compression required with OV518...enabling"); - } - - if (ov->bridge == BRG_OV518) { - if (write_regvals(ov, aRegvalsNorm518)) - goto error; - } else if (ov->bridge == BRG_OV518PLUS) { - if (write_regvals(ov, aRegvalsNorm518Plus)) - goto error; - } else { - err("Invalid bridge"); - } - - if (reg_w(ov, 0x2f, 0x80) < 0) - goto error; - - if (ov518_init_compression(ov)) - goto error; - - if (ov->bridge == BRG_OV518) - { - struct usb_interface *ifp; - struct usb_host_interface *alt; - __u16 mxps = 0; - - ifp = usb_ifnum_to_if(ov->dev, 0); - if (ifp) { - alt = usb_altnum_to_altsetting(ifp, 7); - if (alt) - mxps = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - } - - /* Some OV518s have packet numbering by default, some don't */ - if (mxps == 897) - ov->packet_numbering = 1; - else - ov->packet_numbering = 0; - } else { - /* OV518+ has packet numbering turned on by default */ - ov->packet_numbering = 1; - } - - ov518_set_packet_size(ov, 0); - - ov->snap_enabled = snapshot; - - /* Test for 76xx */ - ov->primary_i2c_slave = OV7xx0_SID; - if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) - goto error; - - /* The OV518 must be more aggressive about sensor detection since - * I2C write will never fail if the sensor is not present. We have - * to try to initialize the sensor to detect its presence */ - - if (init_ov_sensor(ov) < 0) { - /* Test for 6xx0 */ - ov->primary_i2c_slave = OV6xx0_SID; - if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0) - goto error; - - if (init_ov_sensor(ov) < 0) { - /* Test for 8xx0 */ - ov->primary_i2c_slave = OV8xx0_SID; - if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0) - goto error; - - if (init_ov_sensor(ov) < 0) { - err("Can't determine sensor slave IDs"); - goto error; - } else { - err("Detected unsupported OV8xx0 sensor"); - goto error; - } - } else { - if (ov6xx0_configure(ov) < 0) { - err("Failed to configure OV6xx0"); - goto error; - } - } - } else { - if (ov7xx0_configure(ov) < 0) { - err("Failed to configure OV7xx0"); - goto error; - } - } - - ov->maxwidth = 352; - ov->maxheight = 288; - - // The OV518 cannot go as low as the sensor can - ov->minwidth = 160; - ov->minheight = 120; - - return 0; - -error: - err("OV518 Config failed"); - - return -EBUSY; -} - -/**************************************************************************** - * sysfs - ***************************************************************************/ - -static inline struct usb_ov511 *cd_to_ov(struct class_device *cd) -{ - struct video_device *vdev = to_video_device(cd); - return video_get_drvdata(vdev); -} - -static ssize_t show_custom_id(struct class_device *cd, char *buf) -{ - struct usb_ov511 *ov = cd_to_ov(cd); - return sprintf(buf, "%d\n", ov->customid); -} -static CLASS_DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL); - -static ssize_t show_model(struct class_device *cd, char *buf) -{ - struct usb_ov511 *ov = cd_to_ov(cd); - return sprintf(buf, "%s\n", ov->desc); -} -static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); - -static ssize_t show_bridge(struct class_device *cd, char *buf) -{ - struct usb_ov511 *ov = cd_to_ov(cd); - return sprintf(buf, "%s\n", symbolic(brglist, ov->bridge)); -} -static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL); - -static ssize_t show_sensor(struct class_device *cd, char *buf) -{ - struct usb_ov511 *ov = cd_to_ov(cd); - return sprintf(buf, "%s\n", symbolic(senlist, ov->sensor)); -} -static CLASS_DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL); - -static ssize_t show_brightness(struct class_device *cd, char *buf) -{ - struct usb_ov511 *ov = cd_to_ov(cd); - unsigned short x; - - if (!ov->dev) - return -ENODEV; - sensor_get_brightness(ov, &x); - return sprintf(buf, "%d\n", x >> 8); -} -static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); - -static ssize_t show_saturation(struct class_device *cd, char *buf) -{ - struct usb_ov511 *ov = cd_to_ov(cd); - unsigned short x; - - if (!ov->dev) - return -ENODEV; - sensor_get_saturation(ov, &x); - return sprintf(buf, "%d\n", x >> 8); -} -static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); - -static ssize_t show_contrast(struct class_device *cd, char *buf) -{ - struct usb_ov511 *ov = cd_to_ov(cd); - unsigned short x; - - if (!ov->dev) - return -ENODEV; - sensor_get_contrast(ov, &x); - return sprintf(buf, "%d\n", x >> 8); -} -static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); - -static ssize_t show_hue(struct class_device *cd, char *buf) -{ - struct usb_ov511 *ov = cd_to_ov(cd); - unsigned short x; - - if (!ov->dev) - return -ENODEV; - sensor_get_hue(ov, &x); - return sprintf(buf, "%d\n", x >> 8); -} -static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); - -static ssize_t show_exposure(struct class_device *cd, char *buf) -{ - struct usb_ov511 *ov = cd_to_ov(cd); - unsigned char exp = 0; - - if (!ov->dev) - return -ENODEV; - sensor_get_exposure(ov, &exp); - return sprintf(buf, "%d\n", exp >> 8); -} -static CLASS_DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL); - -static void ov_create_sysfs(struct video_device *vdev) -{ - video_device_create_file(vdev, &class_device_attr_custom_id); - video_device_create_file(vdev, &class_device_attr_model); - video_device_create_file(vdev, &class_device_attr_bridge); - video_device_create_file(vdev, &class_device_attr_sensor); - video_device_create_file(vdev, &class_device_attr_brightness); - video_device_create_file(vdev, &class_device_attr_saturation); - video_device_create_file(vdev, &class_device_attr_contrast); - video_device_create_file(vdev, &class_device_attr_hue); - video_device_create_file(vdev, &class_device_attr_exposure); -} - -/**************************************************************************** - * USB routines - ***************************************************************************/ - -static int -ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_interface_descriptor *idesc; - struct usb_ov511 *ov; - int i; - - PDEBUG(1, "probing for device..."); - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - idesc = &intf->cur_altsetting->desc; - - if (idesc->bInterfaceClass != 0xFF) - return -ENODEV; - if (idesc->bInterfaceSubClass != 0x00) - return -ENODEV; - - if ((ov = kzalloc(sizeof(*ov), GFP_KERNEL)) == NULL) { - err("couldn't kmalloc ov struct"); - goto error_out; - } - - ov->dev = dev; - ov->iface = idesc->bInterfaceNumber; - ov->led_policy = led; - ov->compress = compress; - ov->lightfreq = lightfreq; - ov->num_inputs = 1; /* Video decoder init functs. change this */ - ov->stop_during_set = !fastset; - ov->backlight = backlight; - ov->mirror = mirror; - ov->auto_brt = autobright; - ov->auto_gain = autogain; - ov->auto_exp = autoexp; - - switch (le16_to_cpu(dev->descriptor.idProduct)) { - case PROD_OV511: - ov->bridge = BRG_OV511; - ov->bclass = BCL_OV511; - break; - case PROD_OV511PLUS: - ov->bridge = BRG_OV511PLUS; - ov->bclass = BCL_OV511; - break; - case PROD_OV518: - ov->bridge = BRG_OV518; - ov->bclass = BCL_OV518; - break; - case PROD_OV518PLUS: - ov->bridge = BRG_OV518PLUS; - ov->bclass = BCL_OV518; - break; - case PROD_ME2CAM: - if (le16_to_cpu(dev->descriptor.idVendor) != VEND_MATTEL) - goto error; - ov->bridge = BRG_OV511PLUS; - ov->bclass = BCL_OV511; - break; - default: - err("Unknown product ID 0x%04x", le16_to_cpu(dev->descriptor.idProduct)); - goto error; - } - - info("USB %s video device found", symbolic(brglist, ov->bridge)); - - init_waitqueue_head(&ov->wq); - - mutex_init(&ov->lock); /* to 1 == available */ - mutex_init(&ov->buf_lock); - mutex_init(&ov->i2c_lock); - mutex_init(&ov->cbuf_lock); - - ov->buf_state = BUF_NOT_ALLOCATED; - - if (usb_make_path(dev, ov->usb_path, OV511_USB_PATH_LEN) < 0) { - err("usb_make_path error"); - goto error; - } - - /* Allocate control transfer buffer. */ - /* Must be kmalloc()'ed, for DMA compatibility */ - ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL); - if (!ov->cbuf) - goto error; - - if (ov->bclass == BCL_OV518) { - if (ov518_configure(ov) < 0) - goto error; - } else { - if (ov511_configure(ov) < 0) - goto error; - } - - for (i = 0; i < OV511_NUMFRAMES; i++) { - ov->frame[i].framenum = i; - init_waitqueue_head(&ov->frame[i].wq); - } - - for (i = 0; i < OV511_NUMSBUF; i++) { - ov->sbuf[i].ov = ov; - spin_lock_init(&ov->sbuf[i].lock); - ov->sbuf[i].n = i; - } - - /* Unnecessary? (This is done on open(). Need to make sure variables - * are properly initialized without this before removing it, though). */ - if (ov51x_set_default_params(ov) < 0) - goto error; - -#ifdef OV511_DEBUG - if (dump_bridge) { - if (ov->bclass == BCL_OV511) - ov511_dump_regs(ov); - else - ov518_dump_regs(ov); - } -#endif - - ov->vdev = video_device_alloc(); - if (!ov->vdev) - goto error; - - memcpy(ov->vdev, &vdev_template, sizeof(*ov->vdev)); - ov->vdev->dev = &dev->dev; - video_set_drvdata(ov->vdev, ov); - - for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) { - /* Minor 0 cannot be specified; assume user wants autodetect */ - if (unit_video[i] == 0) - break; - - if (video_register_device(ov->vdev, VFL_TYPE_GRABBER, - unit_video[i]) >= 0) { - break; - } - } - - /* Use the next available one */ - if ((ov->vdev->minor == -1) && - video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1) < 0) { - err("video_register_device failed"); - goto error; - } - - info("Device at %s registered to minor %d", ov->usb_path, - ov->vdev->minor); - - usb_set_intfdata(intf, ov); - ov_create_sysfs(ov->vdev); - return 0; - -error: - if (ov->vdev) { - if (-1 == ov->vdev->minor) - video_device_release(ov->vdev); - else - video_unregister_device(ov->vdev); - ov->vdev = NULL; - } - - if (ov->cbuf) { - mutex_lock(&ov->cbuf_lock); - kfree(ov->cbuf); - ov->cbuf = NULL; - mutex_unlock(&ov->cbuf_lock); - } - - kfree(ov); - ov = NULL; - -error_out: - err("Camera initialization failed"); - return -EIO; -} - -static void -ov51x_disconnect(struct usb_interface *intf) -{ - struct usb_ov511 *ov = usb_get_intfdata(intf); - int n; - - PDEBUG(3, ""); - - usb_set_intfdata (intf, NULL); - - if (!ov) - return; - - if (ov->vdev) - video_unregister_device(ov->vdev); - - for (n = 0; n < OV511_NUMFRAMES; n++) - ov->frame[n].grabstate = FRAME_ERROR; - - ov->curframe = -1; - - /* This will cause the process to request another frame */ - for (n = 0; n < OV511_NUMFRAMES; n++) - wake_up_interruptible(&ov->frame[n].wq); - - wake_up_interruptible(&ov->wq); - - ov->streaming = 0; - ov51x_unlink_isoc(ov); - - ov->dev = NULL; - - /* Free the memory */ - if (ov && !ov->user) { - mutex_lock(&ov->cbuf_lock); - kfree(ov->cbuf); - ov->cbuf = NULL; - mutex_unlock(&ov->cbuf_lock); - - ov51x_dealloc(ov); - kfree(ov); - ov = NULL; - } - - PDEBUG(3, "Disconnect complete"); -} - -static struct usb_driver ov511_driver = { - .name = "ov511", - .id_table = device_table, - .probe = ov51x_probe, - .disconnect = ov51x_disconnect -}; - -/**************************************************************************** - * - * Module routines - * - ***************************************************************************/ - -static int __init -usb_ov511_init(void) -{ - int retval; - - retval = usb_register(&ov511_driver); - if (retval) - goto out; - - info(DRIVER_VERSION " : " DRIVER_DESC); - -out: - return retval; -} - -static void __exit -usb_ov511_exit(void) -{ - usb_deregister(&ov511_driver); - info("driver deregistered"); - -} - -module_init(usb_ov511_init); -module_exit(usb_ov511_exit); - diff --git a/drivers/usb/media/ov511.h b/drivers/usb/media/ov511.h deleted file mode 100644 index bce9b3633889..000000000000 --- a/drivers/usb/media/ov511.h +++ /dev/null @@ -1,568 +0,0 @@ -#ifndef __LINUX_OV511_H -#define __LINUX_OV511_H - -#include -#include -#include -#include -#include - -#define OV511_DEBUG /* Turn on debug messages */ - -#ifdef OV511_DEBUG - #define PDEBUG(level, fmt, args...) \ - if (debug >= (level)) info("[%s:%d] " fmt, \ - __FUNCTION__, __LINE__ , ## args) -#else - #define PDEBUG(level, fmt, args...) do {} while(0) -#endif - -/* This macro restricts an int variable to an inclusive range */ -#define RESTRICT_TO_RANGE(v,mi,ma) { \ - if ((v) < (mi)) (v) = (mi); \ - else if ((v) > (ma)) (v) = (ma); \ -} - -/* --------------------------------- */ -/* DEFINES FOR OV511 AND OTHER CHIPS */ -/* --------------------------------- */ - -/* USB IDs */ -#define VEND_OMNIVISION 0x05A9 -#define PROD_OV511 0x0511 -#define PROD_OV511PLUS 0xA511 -#define PROD_OV518 0x0518 -#define PROD_OV518PLUS 0xA518 - -#define VEND_MATTEL 0x0813 -#define PROD_ME2CAM 0x0002 - -/* --------------------------------- */ -/* OV51x REGISTER MNEMONICS */ -/* --------------------------------- */ - -/* Camera interface register numbers */ -#define R511_CAM_DELAY 0x10 -#define R511_CAM_EDGE 0x11 -#define R511_CAM_PXCNT 0x12 -#define R511_CAM_LNCNT 0x13 -#define R511_CAM_PXDIV 0x14 -#define R511_CAM_LNDIV 0x15 -#define R511_CAM_UV_EN 0x16 -#define R511_CAM_LINE_MODE 0x17 -#define R511_CAM_OPTS 0x18 - -/* Snapshot mode camera interface register numbers */ -#define R511_SNAP_FRAME 0x19 -#define R511_SNAP_PXCNT 0x1A -#define R511_SNAP_LNCNT 0x1B -#define R511_SNAP_PXDIV 0x1C -#define R511_SNAP_LNDIV 0x1D -#define R511_SNAP_UV_EN 0x1E -#define R511_SNAP_OPTS 0x1F - -/* DRAM register numbers */ -#define R511_DRAM_FLOW_CTL 0x20 -#define R511_DRAM_ARCP 0x21 -#define R511_DRAM_MRC 0x22 -#define R511_DRAM_RFC 0x23 - -/* ISO FIFO register numbers */ -#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ -#define R511_FIFO_OPTS 0x31 - -/* Parallel IO register numbers */ -#define R511_PIO_OPTS 0x38 -#define R511_PIO_DATA 0x39 -#define R511_PIO_BIST 0x3E -#define R518_GPIO_IN 0x55 /* OV518(+) only */ -#define R518_GPIO_OUT 0x56 /* OV518(+) only */ -#define R518_GPIO_CTL 0x57 /* OV518(+) only */ -#define R518_GPIO_PULSE_IN 0x58 /* OV518(+) only */ -#define R518_GPIO_PULSE_CLEAR 0x59 /* OV518(+) only */ -#define R518_GPIO_PULSE_POL 0x5a /* OV518(+) only */ -#define R518_GPIO_PULSE_EN 0x5b /* OV518(+) only */ -#define R518_GPIO_RESET 0x5c /* OV518(+) only */ - -/* I2C registers */ -#define R511_I2C_CTL 0x40 -#define R518_I2C_CTL 0x47 /* OV518(+) only */ -#define R51x_I2C_W_SID 0x41 -#define R51x_I2C_SADDR_3 0x42 -#define R51x_I2C_SADDR_2 0x43 -#define R51x_I2C_R_SID 0x44 -#define R51x_I2C_DATA 0x45 -#define R51x_I2C_CLOCK 0x46 -#define R51x_I2C_TIMEOUT 0x47 - -/* I2C snapshot registers */ -#define R511_SI2C_SADDR_3 0x48 -#define R511_SI2C_DATA 0x49 - -/* System control registers */ -#define R51x_SYS_RESET 0x50 - /* Reset type definitions */ -#define OV511_RESET_UDC 0x01 -#define OV511_RESET_I2C 0x02 -#define OV511_RESET_FIFO 0x04 -#define OV511_RESET_OMNICE 0x08 -#define OV511_RESET_DRAM 0x10 -#define OV511_RESET_CAM_INT 0x20 -#define OV511_RESET_OV511 0x40 -#define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */ -#define OV511_RESET_ALL 0x7F - -#define R511_SYS_CLOCK_DIV 0x51 -#define R51x_SYS_SNAP 0x52 -#define R51x_SYS_INIT 0x53 -#define R511_SYS_PWR_CLK 0x54 /* OV511+/OV518(+) only */ -#define R511_SYS_LED_CTL 0x55 /* OV511+ only */ -#define R511_SYS_USER 0x5E -#define R511_SYS_CUST_ID 0x5F - -/* OmniCE (compression) registers */ -#define R511_COMP_PHY 0x70 -#define R511_COMP_PHUV 0x71 -#define R511_COMP_PVY 0x72 -#define R511_COMP_PVUV 0x73 -#define R511_COMP_QHY 0x74 -#define R511_COMP_QHUV 0x75 -#define R511_COMP_QVY 0x76 -#define R511_COMP_QVUV 0x77 -#define R511_COMP_EN 0x78 -#define R511_COMP_LUT_EN 0x79 -#define R511_COMP_LUT_BEGIN 0x80 - -/* --------------------------------- */ -/* ALTERNATE NUMBERS */ -/* --------------------------------- */ - -/* Alternate numbers for various max packet sizes (OV511 only) */ -#define OV511_ALT_SIZE_992 0 -#define OV511_ALT_SIZE_993 1 -#define OV511_ALT_SIZE_768 2 -#define OV511_ALT_SIZE_769 3 -#define OV511_ALT_SIZE_512 4 -#define OV511_ALT_SIZE_513 5 -#define OV511_ALT_SIZE_257 6 -#define OV511_ALT_SIZE_0 7 - -/* Alternate numbers for various max packet sizes (OV511+ only) */ -#define OV511PLUS_ALT_SIZE_0 0 -#define OV511PLUS_ALT_SIZE_33 1 -#define OV511PLUS_ALT_SIZE_129 2 -#define OV511PLUS_ALT_SIZE_257 3 -#define OV511PLUS_ALT_SIZE_385 4 -#define OV511PLUS_ALT_SIZE_513 5 -#define OV511PLUS_ALT_SIZE_769 6 -#define OV511PLUS_ALT_SIZE_961 7 - -/* Alternate numbers for various max packet sizes (OV518(+) only) */ -#define OV518_ALT_SIZE_0 0 -#define OV518_ALT_SIZE_128 1 -#define OV518_ALT_SIZE_256 2 -#define OV518_ALT_SIZE_384 3 -#define OV518_ALT_SIZE_512 4 -#define OV518_ALT_SIZE_640 5 -#define OV518_ALT_SIZE_768 6 -#define OV518_ALT_SIZE_896 7 - -/* --------------------------------- */ -/* OV7610 REGISTER MNEMONICS */ -/* --------------------------------- */ - -/* OV7610 registers */ -#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */ -#define OV7610_REG_BLUE 0x01 /* blue channel balance */ -#define OV7610_REG_RED 0x02 /* red channel balance */ -#define OV7610_REG_SAT 0x03 /* saturation */ - /* 04 reserved */ -#define OV7610_REG_CNT 0x05 /* Y contrast */ -#define OV7610_REG_BRT 0x06 /* Y brightness */ - /* 08-0b reserved */ -#define OV7610_REG_BLUE_BIAS 0x0C /* blue channel bias (5:0) */ -#define OV7610_REG_RED_BIAS 0x0D /* read channel bias (5:0) */ -#define OV7610_REG_GAMMA_COEFF 0x0E /* gamma settings */ -#define OV7610_REG_WB_RANGE 0x0F /* AEC/ALC/S-AWB settings */ -#define OV7610_REG_EXP 0x10 /* manual exposure setting */ -#define OV7610_REG_CLOCK 0x11 /* polarity/clock prescaler */ -#define OV7610_REG_COM_A 0x12 /* misc common regs */ -#define OV7610_REG_COM_B 0x13 /* misc common regs */ -#define OV7610_REG_COM_C 0x14 /* misc common regs */ -#define OV7610_REG_COM_D 0x15 /* misc common regs */ -#define OV7610_REG_FIELD_DIVIDE 0x16 /* field interval/mode settings */ -#define OV7610_REG_HWIN_START 0x17 /* horizontal window start */ -#define OV7610_REG_HWIN_END 0x18 /* horizontal window end */ -#define OV7610_REG_VWIN_START 0x19 /* vertical window start */ -#define OV7610_REG_VWIN_END 0x1A /* vertical window end */ -#define OV7610_REG_PIXEL_SHIFT 0x1B /* pixel shift */ -#define OV7610_REG_ID_HIGH 0x1C /* manufacturer ID MSB */ -#define OV7610_REG_ID_LOW 0x1D /* manufacturer ID LSB */ - /* 0e-0f reserved */ -#define OV7610_REG_COM_E 0x20 /* misc common regs */ -#define OV7610_REG_YOFFSET 0x21 /* Y channel offset */ -#define OV7610_REG_UOFFSET 0x22 /* U channel offset */ - /* 23 reserved */ -#define OV7610_REG_ECW 0x24 /* Exposure white level for AEC */ -#define OV7610_REG_ECB 0x25 /* Exposure black level for AEC */ -#define OV7610_REG_COM_F 0x26 /* misc settings */ -#define OV7610_REG_COM_G 0x27 /* misc settings */ -#define OV7610_REG_COM_H 0x28 /* misc settings */ -#define OV7610_REG_COM_I 0x29 /* misc settings */ -#define OV7610_REG_FRAMERATE_H 0x2A /* frame rate MSB + misc */ -#define OV7610_REG_FRAMERATE_L 0x2B /* frame rate LSB */ -#define OV7610_REG_ALC 0x2C /* Auto Level Control settings */ -#define OV7610_REG_COM_J 0x2D /* misc settings */ -#define OV7610_REG_VOFFSET 0x2E /* V channel offset adjustment */ -#define OV7610_REG_ARRAY_BIAS 0x2F /* Array bias -- don't change */ - /* 30-32 reserved */ -#define OV7610_REG_YGAMMA 0x33 /* misc gamma settings (7:6) */ -#define OV7610_REG_BIAS_ADJUST 0x34 /* misc bias settings */ -#define OV7610_REG_COM_L 0x35 /* misc settings */ - /* 36-37 reserved */ -#define OV7610_REG_COM_K 0x38 /* misc registers */ - -/* --------------------------------- */ -/* I2C ADDRESSES */ -/* --------------------------------- */ - -#define OV7xx0_SID 0x42 -#define OV6xx0_SID 0xC0 -#define OV8xx0_SID 0xA0 -#define KS0127_SID 0xD8 -#define SAA7111A_SID 0x48 - -/* --------------------------------- */ -/* MISCELLANEOUS DEFINES */ -/* --------------------------------- */ - -#define I2C_CLOCK_PRESCALER 0x03 - -#define FRAMES_PER_DESC 10 /* FIXME - What should this be? */ -#define MAX_FRAME_SIZE_PER_DESC 993 /* For statically allocated stuff */ -#define PIXELS_PER_SEG 256 /* Pixels per segment */ - -#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ - -#define OV511_NUMFRAMES 2 -#if OV511_NUMFRAMES > VIDEO_MAX_FRAME - #error "OV511_NUMFRAMES is too high" -#endif - -#define OV511_NUMSBUF 2 - -/* Control transfers use up to 4 bytes */ -#define OV511_CBUF_SIZE 4 - -/* Size of usb_make_path() buffer */ -#define OV511_USB_PATH_LEN 64 - -/* Bridge types */ -enum { - BRG_UNKNOWN, - BRG_OV511, - BRG_OV511PLUS, - BRG_OV518, - BRG_OV518PLUS, -}; - -/* Bridge classes */ -enum { - BCL_UNKNOWN, - BCL_OV511, - BCL_OV518, -}; - -/* Sensor types */ -enum { - SEN_UNKNOWN, - SEN_OV76BE, - SEN_OV7610, - SEN_OV7620, - SEN_OV7620AE, - SEN_OV6620, - SEN_OV6630, - SEN_OV6630AE, - SEN_OV6630AF, - SEN_OV8600, - SEN_KS0127, - SEN_KS0127B, - SEN_SAA7111A, -}; - -enum { - STATE_SCANNING, /* Scanning for start */ - STATE_HEADER, /* Parsing header */ - STATE_LINES, /* Parsing lines */ -}; - -/* Buffer states */ -enum { - BUF_NOT_ALLOCATED, - BUF_ALLOCATED, -}; - -/* --------- Definition of ioctl interface --------- */ - -#define OV511_INTERFACE_VER 101 - -/* LED options */ -enum { - LED_OFF, - LED_ON, - LED_AUTO, -}; - -/* Raw frame formats */ -enum { - RAWFMT_INVALID, - RAWFMT_YUV400, - RAWFMT_YUV420, - RAWFMT_YUV422, - RAWFMT_GBR422, -}; - -struct ov511_i2c_struct { - unsigned char slave; /* Write slave ID (read ID - 1) */ - unsigned char reg; /* Index of register */ - unsigned char value; /* User sets this w/ write, driver does w/ read */ - unsigned char mask; /* Bits to be changed. Not used with read ops */ -}; - -/* ioctls */ -#define OV511IOC_WI2C _IOW('v', BASE_VIDIOCPRIVATE + 5, \ - struct ov511_i2c_struct) -#define OV511IOC_RI2C _IOWR('v', BASE_VIDIOCPRIVATE + 6, \ - struct ov511_i2c_struct) -/* ------------- End IOCTL interface -------------- */ - -struct usb_ov511; /* Forward declaration */ - -struct ov511_sbuf { - struct usb_ov511 *ov; - unsigned char *data; - struct urb *urb; - spinlock_t lock; - int n; -}; - -enum { - FRAME_UNUSED, /* Unused (no MCAPTURE) */ - FRAME_READY, /* Ready to start grabbing */ - FRAME_GRABBING, /* In the process of being grabbed into */ - FRAME_DONE, /* Finished grabbing, but not been synced yet */ - FRAME_ERROR, /* Something bad happened while processing */ -}; - -struct ov511_regvals { - enum { - OV511_DONE_BUS, - OV511_REG_BUS, - OV511_I2C_BUS, - } bus; - unsigned char reg; - unsigned char val; -}; - -struct ov511_frame { - int framenum; /* Index of this frame */ - unsigned char *data; /* Frame buffer */ - unsigned char *tempdata; /* Temp buffer for multi-stage conversions */ - unsigned char *rawdata; /* Raw camera data buffer */ - unsigned char *compbuf; /* Temp buffer for decompressor */ - - int depth; /* Bytes per pixel */ - int width; /* Width application is expecting */ - int height; /* Height application is expecting */ - - int rawwidth; /* Actual width of frame sent from camera */ - int rawheight; /* Actual height of frame sent from camera */ - - int sub_flag; /* Sub-capture mode for this frame? */ - unsigned int format; /* Format for this frame */ - int compressed; /* Is frame compressed? */ - - volatile int grabstate; /* State of grabbing */ - int scanstate; /* State of scanning */ - - int bytes_recvd; /* Number of image bytes received from camera */ - - long bytes_read; /* Amount that has been read() */ - - wait_queue_head_t wq; /* Processes waiting */ - - int snapshot; /* True if frame was a snapshot */ -}; - -#define DECOMP_INTERFACE_VER 4 - -/* Compression module operations */ -struct ov51x_decomp_ops { - int (*decomp_400)(unsigned char *, unsigned char *, unsigned char *, - int, int, int); - int (*decomp_420)(unsigned char *, unsigned char *, unsigned char *, - int, int, int); - int (*decomp_422)(unsigned char *, unsigned char *, unsigned char *, - int, int, int); - struct module *owner; -}; - -struct usb_ov511 { - struct video_device *vdev; - struct usb_device *dev; - - int customid; - char *desc; - unsigned char iface; - char usb_path[OV511_USB_PATH_LEN]; - - /* Determined by sensor type */ - int maxwidth; - int maxheight; - int minwidth; - int minheight; - - int brightness; - int colour; - int contrast; - int hue; - int whiteness; - int exposure; - int auto_brt; /* Auto brightness enabled flag */ - int auto_gain; /* Auto gain control enabled flag */ - int auto_exp; /* Auto exposure enabled flag */ - int backlight; /* Backlight exposure algorithm flag */ - int mirror; /* Image is reversed horizontally */ - - int led_policy; /* LED: off|on|auto; OV511+ only */ - - struct mutex lock; /* Serializes user-accessible operations */ - int user; /* user count for exclusive use */ - - int streaming; /* Are we streaming Isochronous? */ - int grabbing; /* Are we grabbing? */ - - int compress; /* Should the next frame be compressed? */ - int compress_inited; /* Are compression params uploaded? */ - - int lightfreq; /* Power (lighting) frequency */ - int bandfilt; /* Banding filter enabled flag */ - - unsigned char *fbuf; /* Videodev buffer area */ - unsigned char *tempfbuf; /* Temporary (intermediate) buffer area */ - unsigned char *rawfbuf; /* Raw camera data buffer area */ - - int sub_flag; /* Pix Array subcapture on flag */ - int subx; /* Pix Array subcapture x offset */ - int suby; /* Pix Array subcapture y offset */ - int subw; /* Pix Array subcapture width */ - int subh; /* Pix Array subcapture height */ - - int curframe; /* Current receiving sbuf */ - struct ov511_frame frame[OV511_NUMFRAMES]; - - struct ov511_sbuf sbuf[OV511_NUMSBUF]; - - wait_queue_head_t wq; /* Processes waiting */ - - int snap_enabled; /* Snapshot mode enabled */ - - int bridge; /* Type of bridge (BRG_*) */ - int bclass; /* Class of bridge (BCL_*) */ - int sensor; /* Type of image sensor chip (SEN_*) */ - - int packet_size; /* Frame size per isoc desc */ - int packet_numbering; /* Is ISO frame numbering enabled? */ - - /* Framebuffer/sbuf management */ - int buf_state; - struct mutex buf_lock; - - struct ov51x_decomp_ops *decomp_ops; - - /* Stop streaming while changing picture settings */ - int stop_during_set; - - int stopped; /* Streaming is temporarily paused */ - - /* Video decoder stuff */ - int input; /* Composite, S-VIDEO, etc... */ - int num_inputs; /* Number of inputs */ - int norm; /* NTSC / PAL / SECAM */ - int has_decoder; /* Device has a video decoder */ - int pal; /* Device is designed for PAL resolution */ - - /* I2C interface */ - struct mutex i2c_lock; /* Protect I2C controller regs */ - unsigned char primary_i2c_slave; /* I2C write id of sensor */ - - /* Control transaction stuff */ - unsigned char *cbuf; /* Buffer for payload */ - struct mutex cbuf_lock; -}; - -/* Used to represent a list of values and their respective symbolic names */ -struct symbolic_list { - int num; - char *name; -}; - -#define NOT_DEFINED_STR "Unknown" - -/* Returns the name of the matching element in the symbolic_list array. The - * end of the list must be marked with an element that has a NULL name. - */ -static inline char * -symbolic(struct symbolic_list list[], int num) -{ - int i; - - for (i = 0; list[i].name != NULL; i++) - if (list[i].num == num) - return (list[i].name); - - return (NOT_DEFINED_STR); -} - -/* Compression stuff */ - -#define OV511_QUANTABLESIZE 64 -#define OV518_QUANTABLESIZE 32 - -#define OV511_YQUANTABLE { \ - 0, 1, 1, 2, 2, 3, 3, 4, \ - 1, 1, 1, 2, 2, 3, 4, 4, \ - 1, 1, 2, 2, 3, 4, 4, 4, \ - 2, 2, 2, 3, 4, 4, 4, 4, \ - 2, 2, 3, 4, 4, 5, 5, 5, \ - 3, 3, 4, 4, 5, 5, 5, 5, \ - 3, 4, 4, 4, 5, 5, 5, 5, \ - 4, 4, 4, 4, 5, 5, 5, 5 \ -} - -#define OV511_UVQUANTABLE { \ - 0, 2, 2, 3, 4, 4, 4, 4, \ - 2, 2, 2, 4, 4, 4, 4, 4, \ - 2, 2, 3, 4, 4, 4, 4, 4, \ - 3, 4, 4, 4, 4, 4, 4, 4, \ - 4, 4, 4, 4, 4, 4, 4, 4, \ - 4, 4, 4, 4, 4, 4, 4, 4, \ - 4, 4, 4, 4, 4, 4, 4, 4, \ - 4, 4, 4, 4, 4, 4, 4, 4 \ -} - -#define OV518_YQUANTABLE { \ - 5, 4, 5, 6, 6, 7, 7, 7, \ - 5, 5, 5, 5, 6, 7, 7, 7, \ - 6, 6, 6, 6, 7, 7, 7, 8, \ - 7, 7, 6, 7, 7, 7, 8, 8 \ -} - -#define OV518_UVQUANTABLE { \ - 6, 6, 6, 7, 7, 7, 7, 7, \ - 6, 6, 6, 7, 7, 7, 7, 7, \ - 6, 6, 6, 7, 7, 7, 7, 8, \ - 7, 7, 7, 7, 7, 7, 8, 8 \ -} - -#endif diff --git a/drivers/usb/media/pwc/Makefile b/drivers/usb/media/pwc/Makefile deleted file mode 100644 index 2d93a775011a..000000000000 --- a/drivers/usb/media/pwc/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -ifneq ($(KERNELRELEASE),) - -pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o - -obj-$(CONFIG_USB_PWC) += pwc.o - -else - -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) - -default: - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules - -endif - -clean: - rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c - rm -rf .tmp_versions - diff --git a/drivers/usb/media/pwc/philips.txt b/drivers/usb/media/pwc/philips.txt deleted file mode 100644 index 04a640d723ed..000000000000 --- a/drivers/usb/media/pwc/philips.txt +++ /dev/null @@ -1,236 +0,0 @@ -This file contains some additional information for the Philips and OEM webcams. -E-mail: webcam@smcc.demon.nl Last updated: 2004-01-19 -Site: http://www.smcc.demon.nl/webcam/ - -As of this moment, the following cameras are supported: - * Philips PCA645 - * Philips PCA646 - * Philips PCVC675 - * Philips PCVC680 - * Philips PCVC690 - * Philips PCVC720/40 - * Philips PCVC730 - * Philips PCVC740 - * Philips PCVC750 - * Askey VC010 - * Creative Labs Webcam 5 - * Creative Labs Webcam Pro Ex - * Logitech QuickCam 3000 Pro - * Logitech QuickCam 4000 Pro - * Logitech QuickCam Notebook Pro - * Logitech QuickCam Zoom - * Logitech QuickCam Orbit - * Logitech QuickCam Sphere - * Samsung MPC-C10 - * Samsung MPC-C30 - * Sotec Afina Eye - * AME CU-001 - * Visionite VCS-UM100 - * Visionite VCS-UC300 - -The main webpage for the Philips driver is at the address above. It contains -a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin -contains decompression routines that allow you to use higher image sizes and -framerates; in addition the webcam uses less bandwidth on the USB bus (handy -if you want to run more than 1 camera simultaneously). These routines fall -under a NDA, and may therefor not be distributed as source; however, its use -is completely optional. - -You can build this code either into your kernel, or as a module. I recommend -the latter, since it makes troubleshooting a lot easier. The built-in -microphone is supported through the USB Audio class. - -When you load the module you can set some default settings for the -camera; some programs depend on a particular image-size or -format and -don't know how to set it properly in the driver. The options are: - -size - Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or - 'vga', for an image size of resp. 128x96, 160x120, 176x144, - 320x240, 352x288 and 640x480 (of course, only for those cameras that - support these resolutions). - -fps - Specifies the desired framerate. Is an integer in the range of 4-30. - -fbufs - This paramter specifies the number of internal buffers to use for storing - frames from the cam. This will help if the process that reads images from - the cam is a bit slow or momentarely busy. However, on slow machines it - only introduces lag, so choose carefully. The default is 3, which is - reasonable. You can set it between 2 and 5. - -mbufs - This is an integer between 1 and 10. It will tell the module the number of - buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends. - The default is 2, which is adequate for most applications (double - buffering). - - Should you experience a lot of 'Dumping frame...' messages during - grabbing with a tool that uses mmap(), you might want to increase if. - However, it doesn't really buffer images, it just gives you a bit more - slack when your program is behind. But you need a multi-threaded or - forked program to really take advantage of these buffers. - - The absolute maximum is 10, but don't set it too high! Every buffer takes - up 460 KB of RAM, so unless you have a lot of memory setting this to - something more than 4 is an absolute waste. This memory is only - allocated during open(), so nothing is wasted when the camera is not in - use. - -power_save - When power_save is enabled (set to 1), the module will try to shut down - the cam on close() and re-activate on open(). This will save power and - turn off the LED. Not all cameras support this though (the 645 and 646 - don't have power saving at all), and some models don't work either (they - will shut down, but never wake up). Consider this experimental. By - default this option is disabled. - -compression (only useful with the plugin) - With this option you can control the compression factor that the camera - uses to squeeze the image through the USB bus. You can set the - parameter between 0 and 3: - 0 = prefer uncompressed images; if the requested mode is not available - in an uncompressed format, the driver will silently switch to low - compression. - 1 = low compression. - 2 = medium compression. - 3 = high compression. - - High compression takes less bandwidth of course, but it could also - introduce some unwanted artefacts. The default is 2, medium compression. - See the FAQ on the website for an overview of which modes require - compression. - - The compression parameter does not apply to the 645 and 646 cameras - and OEM models derived from those (only a few). Most cams honour this - parameter. - -leds - This settings takes 2 integers, that define the on/off time for the LED - (in milliseconds). One of the interesting things that you can do with - this is let the LED blink while the camera is in use. This: - - leds=500,500 - - will blink the LED once every second. But with: - - leds=0,0 - - the LED never goes on, making it suitable for silent surveillance. - - By default the camera's LED is on solid while in use, and turned off - when the camera is not used anymore. - - This parameter works only with the ToUCam range of cameras (720, 730, 740, - 750) and OEMs. For other cameras this command is silently ignored, and - the LED cannot be controlled. - - Finally: this parameters does not take effect UNTIL the first time you - open the camera device. Until then, the LED remains on. - -dev_hint - A long standing problem with USB devices is their dynamic nature: you - never know what device a camera gets assigned; it depends on module load - order, the hub configuration, the order in which devices are plugged in, - and the phase of the moon (i.e. it can be random). With this option you - can give the driver a hint as to what video device node (/dev/videoX) it - should use with a specific camera. This is also handy if you have two - cameras of the same model. - - A camera is specified by its type (the number from the camera model, - like PCA645, PCVC750VC, etc) and optionally the serial number (visible - in /proc/bus/usb/devices). A hint consists of a string with the following - format: - - [type[.serialnumber]:]node - - The square brackets mean that both the type and the serialnumber are - optional, but a serialnumber cannot be specified without a type (which - would be rather pointless). The serialnumber is separated from the type - by a '.'; the node number by a ':'. - - This somewhat cryptic syntax is best explained by a few examples: - - dev_hint=3,5 The first detected cam gets assigned - /dev/video3, the second /dev/video5. Any - other cameras will get the first free - available slot (see below). - - dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1, - and a PCVC680 /dev/video2. - - dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber - 0123 goes to /dev/video3, the same - camera model with the 4567 serial - gets /dev/video0. - - dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the - next 3 Philips cams will use /dev/video4 - through /dev/video6. - - Some points worth knowing: - - Serialnumbers are case sensitive and must be written full, including - leading zeroes (it's treated as a string). - - If a device node is already occupied, registration will fail and - the webcam is not available. - - You can have up to 64 video devices; be sure to make enough device - nodes in /dev if you want to spread the numbers (this does not apply - to devfs). After /dev/video9 comes /dev/video10 (not /dev/videoA). - - If a camera does not match any dev_hint, it will simply get assigned - the first available device node, just as it used to be. - -trace - In order to better detect problems, it is now possible to turn on a - 'trace' of some of the calls the module makes; it logs all items in your - kernel log at debug level. - - The trace variable is a bitmask; each bit represents a certain feature. - If you want to trace something, look up the bit value(s) in the table - below, add the values together and supply that to the trace variable. - - Value Value Description Default - (dec) (hex) - 1 0x1 Module initialization; this will log messages On - while loading and unloading the module - - 2 0x2 probe() and disconnect() traces On - - 4 0x4 Trace open() and close() calls Off - - 8 0x8 read(), mmap() and associated ioctl() calls Off - - 16 0x10 Memory allocation of buffers, etc. Off - - 32 0x20 Showing underflow, overflow and Dumping frame On - messages - - 64 0x40 Show viewport and image sizes Off - - 128 0x80 PWCX debugging Off - - For example, to trace the open() & read() fuctions, sum 8 + 4 = 12, - so you would supply trace=12 during insmod or modprobe. If - you want to turn the initialization and probing tracing off, set trace=0. - The default value for trace is 35 (0x23). - - - -Example: - - # modprobe pwc size=cif fps=15 power_save=1 - -The fbufs, mbufs and trace parameters are global and apply to all connected -cameras. Each camera has its own set of buffers. - -size and fps only specify defaults when you open() the device; this is to -accommodate some tools that don't set the size. You can change these -settings after open() with the Video4Linux ioctl() calls. The default of -defaults is QCIF size at 10 fps. - -The compression parameter is semiglobal; it sets the initial compression -preference for all camera's, but this parameter can be set per camera with -the VIDIOCPWCSCQUAL ioctl() call. - -All parameters are optional. - diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c deleted file mode 100644 index 0398b812e0ce..000000000000 --- a/drivers/usb/media/pwc/pwc-ctrl.c +++ /dev/null @@ -1,1541 +0,0 @@ -/* Driver for Philips webcam - Functions that send various control messages to the webcam, including - video modes. - (C) 1999-2003 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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 -*/ - -/* - Changes - 2001/08/03 Alvarado Added methods for changing white balance and - red/green gains - */ - -/* Control functions for the cam; brightness, contrast, video mode, etc. */ - -#ifdef __KERNEL__ -#include -#endif -#include - -#include "pwc.h" -#include "pwc-ioctl.h" -#include "pwc-uncompress.h" -#include "pwc-kiara.h" -#include "pwc-timon.h" - -/* Request types: video */ -#define SET_LUM_CTL 0x01 -#define GET_LUM_CTL 0x02 -#define SET_CHROM_CTL 0x03 -#define GET_CHROM_CTL 0x04 -#define SET_STATUS_CTL 0x05 -#define GET_STATUS_CTL 0x06 -#define SET_EP_STREAM_CTL 0x07 -#define GET_EP_STREAM_CTL 0x08 -#define SET_MPT_CTL 0x0D -#define GET_MPT_CTL 0x0E - -/* Selectors for the Luminance controls [GS]ET_LUM_CTL */ -#define AGC_MODE_FORMATTER 0x2000 -#define PRESET_AGC_FORMATTER 0x2100 -#define SHUTTER_MODE_FORMATTER 0x2200 -#define PRESET_SHUTTER_FORMATTER 0x2300 -#define PRESET_CONTOUR_FORMATTER 0x2400 -#define AUTO_CONTOUR_FORMATTER 0x2500 -#define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600 -#define CONTRAST_FORMATTER 0x2700 -#define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800 -#define FLICKERLESS_MODE_FORMATTER 0x2900 -#define AE_CONTROL_SPEED 0x2A00 -#define BRIGHTNESS_FORMATTER 0x2B00 -#define GAMMA_FORMATTER 0x2C00 - -/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */ -#define WB_MODE_FORMATTER 0x1000 -#define AWB_CONTROL_SPEED_FORMATTER 0x1100 -#define AWB_CONTROL_DELAY_FORMATTER 0x1200 -#define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300 -#define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400 -#define COLOUR_MODE_FORMATTER 0x1500 -#define SATURATION_MODE_FORMATTER1 0x1600 -#define SATURATION_MODE_FORMATTER2 0x1700 - -/* Selectors for the Status controls [GS]ET_STATUS_CTL */ -#define SAVE_USER_DEFAULTS_FORMATTER 0x0200 -#define RESTORE_USER_DEFAULTS_FORMATTER 0x0300 -#define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400 -#define READ_AGC_FORMATTER 0x0500 -#define READ_SHUTTER_FORMATTER 0x0600 -#define READ_RED_GAIN_FORMATTER 0x0700 -#define READ_BLUE_GAIN_FORMATTER 0x0800 -#define SENSOR_TYPE_FORMATTER1 0x0C00 -#define READ_RAW_Y_MEAN_FORMATTER 0x3100 -#define SET_POWER_SAVE_MODE_FORMATTER 0x3200 -#define MIRROR_IMAGE_FORMATTER 0x3300 -#define LED_FORMATTER 0x3400 -#define SENSOR_TYPE_FORMATTER2 0x3700 - -/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ -#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100 - -/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */ -#define PT_RELATIVE_CONTROL_FORMATTER 0x01 -#define PT_RESET_CONTROL_FORMATTER 0x02 -#define PT_STATUS_FORMATTER 0x03 - -static const char *size2name[PSZ_MAX] = -{ - "subQCIF", - "QSIF", - "QCIF", - "SIF", - "CIF", - "VGA", -}; - -/********/ - -/* Entries for the Nala (645/646) camera; the Nala doesn't have compression - preferences, so you either get compressed or non-compressed streams. - - An alternate value of 0 means this mode is not available at all. - */ - -struct Nala_table_entry { - char alternate; /* USB alternate setting */ - int compressed; /* Compressed yes/no */ - - unsigned char mode[3]; /* precomputed mode table */ -}; - -static struct Nala_table_entry Nala_table[PSZ_MAX][8] = -{ -#include "pwc-nala.h" -}; - - -/****************************************************************************/ - - -#define SendControlMsg(request, value, buflen) \ - usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \ - request, \ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \ - value, \ - pdev->vcinterface, \ - &buf, buflen, 500) - -#define RecvControlMsg(request, value, buflen) \ - usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \ - request, \ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \ - value, \ - pdev->vcinterface, \ - &buf, buflen, 500) - - -#if PWC_DEBUG -void pwc_hexdump(void *p, int len) -{ - int i; - unsigned char *s; - char buf[100], *d; - - s = (unsigned char *)p; - d = buf; - *d = '\0'; - Debug("Doing hexdump @ %p, %d bytes.\n", p, len); - for (i = 0; i < len; i++) { - d += sprintf(d, "%02X ", *s++); - if ((i & 0xF) == 0xF) { - Debug("%s\n", buf); - d = buf; - *d = '\0'; - } - } - if ((i & 0xF) != 0) - Debug("%s\n", buf); -} -#endif - -static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen) -{ - return usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - SET_EP_STREAM_CTL, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - VIDEO_OUTPUT_CONTROL_FORMATTER, - index, - buf, buflen, 1000); -} - - - -static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) -{ - unsigned char buf[3]; - int ret, fps; - struct Nala_table_entry *pEntry; - int frames2frames[31] = - { /* closest match of framerate */ - 0, 0, 0, 0, 4, /* 0-4 */ - 5, 5, 7, 7, 10, /* 5-9 */ - 10, 10, 12, 12, 15, /* 10-14 */ - 15, 15, 15, 20, 20, /* 15-19 */ - 20, 20, 20, 24, 24, /* 20-24 */ - 24, 24, 24, 24, 24, /* 25-29 */ - 24 /* 30 */ - }; - int frames2table[31] = - { 0, 0, 0, 0, 0, /* 0-4 */ - 1, 1, 1, 2, 2, /* 5-9 */ - 3, 3, 4, 4, 4, /* 10-14 */ - 5, 5, 5, 5, 5, /* 15-19 */ - 6, 6, 6, 6, 7, /* 20-24 */ - 7, 7, 7, 7, 7, /* 25-29 */ - 7 /* 30 */ - }; - - if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25) - return -EINVAL; - frames = frames2frames[frames]; - fps = frames2table[frames]; - pEntry = &Nala_table[size][fps]; - if (pEntry->alternate == 0) - return -EINVAL; - - if (pEntry->compressed) - return -ENOENT; /* Not supported. */ - - memcpy(buf, pEntry->mode, 3); - ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); - if (ret < 0) { - Debug("Failed to send video command... %d\n", ret); - return ret; - } - if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW) - { - switch(pdev->type) { - case 645: - case 646: -/* pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ - break; - - case 675: - case 680: - case 690: - case 720: - case 730: - case 740: - case 750: -/* pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ - break; - } - } - - pdev->cmd_len = 3; - memcpy(pdev->cmd_buf, buf, 3); - - /* Set various parameters */ - pdev->vframes = frames; - pdev->vsize = size; - pdev->valternate = pEntry->alternate; - pdev->image = pwc_image_sizes[size]; - pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2; - if (pEntry->compressed) { - if (pdev->release < 5) { /* 4 fold compression */ - pdev->vbandlength = 528; - pdev->frame_size /= 4; - } - else { - pdev->vbandlength = 704; - pdev->frame_size /= 3; - } - } - else - pdev->vbandlength = 0; - return 0; -} - - -static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) -{ - unsigned char buf[13]; - const struct Timon_table_entry *pChoose; - int ret, fps; - - if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3) - return -EINVAL; - if (size == PSZ_VGA && frames > 15) - return -EINVAL; - fps = (frames / 5) - 1; - - /* Find a supported framerate with progressively higher compression ratios - if the preferred ratio is not available. - */ - pChoose = NULL; - while (compression <= 3) { - pChoose = &Timon_table[size][fps][compression]; - if (pChoose->alternate != 0) - break; - compression++; - } - if (pChoose == NULL || pChoose->alternate == 0) - return -ENOENT; /* Not supported. */ - - memcpy(buf, pChoose->mode, 13); - if (snapshot) - buf[0] |= 0x80; - ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13); - if (ret < 0) - return ret; - -/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) - pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ - - pdev->cmd_len = 13; - memcpy(pdev->cmd_buf, buf, 13); - - /* Set various parameters */ - pdev->vframes = frames; - pdev->vsize = size; - pdev->vsnapshot = snapshot; - pdev->valternate = pChoose->alternate; - pdev->image = pwc_image_sizes[size]; - pdev->vbandlength = pChoose->bandlength; - if (pChoose->bandlength > 0) - pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4; - else - pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; - return 0; -} - - -static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) -{ - const struct Kiara_table_entry *pChoose = NULL; - int fps, ret; - unsigned char buf[12]; - struct Kiara_table_entry RawEntry = {6, 773, 1272, {0xAD, 0xF4, 0x10, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}}; - - if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3) - return -EINVAL; - if (size == PSZ_VGA && frames > 15) - return -EINVAL; - fps = (frames / 5) - 1; - - /* special case: VGA @ 5 fps and snapshot is raw bayer mode */ - if (size == PSZ_VGA && frames == 5 && snapshot) - { - /* Only available in case the raw palette is selected or - we have the decompressor available. This mode is - only available in compressed form - */ - if (pdev->vpalette == VIDEO_PALETTE_RAW) - { - Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette); - pChoose = &RawEntry; - } - else - { - Info("VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.\n"); - } - } - else - { - /* Find a supported framerate with progressively higher compression ratios - if the preferred ratio is not available. - Skip this step when using RAW modes. - */ - while (compression <= 3) { - pChoose = &Kiara_table[size][fps][compression]; - if (pChoose->alternate != 0) - break; - compression++; - } - } - if (pChoose == NULL || pChoose->alternate == 0) - return -ENOENT; /* Not supported. */ - - Debug("Using alternate setting %d.\n", pChoose->alternate); - - /* usb_control_msg won't take staticly allocated arrays as argument?? */ - memcpy(buf, pChoose->mode, 12); - if (snapshot) - buf[0] |= 0x80; - - /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ - ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12); - if (ret < 0) - return ret; - -/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) - pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ - - pdev->cmd_len = 12; - memcpy(pdev->cmd_buf, buf, 12); - /* All set and go */ - pdev->vframes = frames; - pdev->vsize = size; - pdev->vsnapshot = snapshot; - pdev->valternate = pChoose->alternate; - pdev->image = pwc_image_sizes[size]; - pdev->vbandlength = pChoose->bandlength; - if (pdev->vbandlength > 0) - pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4; - else - pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; - return 0; -} - - - -static void pwc_set_image_buffer_size(struct pwc_device *pdev) -{ - int i, factor = 0, filler = 0; - - /* for PALETTE_YUV420P */ - switch(pdev->vpalette) - { - case VIDEO_PALETTE_YUV420P: - factor = 6; - filler = 128; - break; - case VIDEO_PALETTE_RAW: - factor = 6; /* can be uncompressed YUV420P */ - filler = 0; - break; - } - - /* Set sizes in bytes */ - pdev->image.size = pdev->image.x * pdev->image.y * factor / 4; - pdev->view.size = pdev->view.x * pdev->view.y * factor / 4; - - /* Align offset, or you'll get some very weird results in - YUV420 mode... x must be multiple of 4 (to get the Y's in - place), and y even (or you'll mixup U & V). This is less of a - problem for YUV420P. - */ - pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC; - pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE; - - /* Fill buffers with gray or black */ - for (i = 0; i < MAX_IMAGES; i++) { - if (pdev->image_ptr[i] != NULL) - memset(pdev->image_ptr[i], filler, pdev->view.size); - } -} - - - -/** - @pdev: device structure - @width: viewport width - @height: viewport height - @frame: framerate, in fps - @compression: preferred compression ratio - @snapshot: snapshot mode or streaming - */ -int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot) -{ - int ret, size; - - Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette); - size = pwc_decode_size(pdev, width, height); - if (size < 0) { - Debug("Could not find suitable size.\n"); - return -ERANGE; - } - Debug("decode_size = %d.\n", size); - - ret = -EINVAL; - switch(pdev->type) { - case 645: - case 646: - ret = set_video_mode_Nala(pdev, size, frames); - break; - - case 675: - case 680: - case 690: - ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot); - break; - - case 720: - case 730: - case 740: - case 750: - ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot); - break; - } - if (ret < 0) { - if (ret == -ENOENT) - Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames); - else { - Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); - } - return ret; - } - pdev->view.x = width; - pdev->view.y = height; - pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; - pwc_set_image_buffer_size(pdev); - Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y); - return 0; -} - - -/* BRIGHTNESS */ - -int pwc_get_brightness(struct pwc_device *pdev) -{ - char buf; - int ret; - - ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); - if (ret < 0) - return ret; - return buf << 9; -} - -int pwc_set_brightness(struct pwc_device *pdev, int value) -{ - char buf; - - if (value < 0) - value = 0; - if (value > 0xffff) - value = 0xffff; - buf = (value >> 9) & 0x7f; - return SendControlMsg(SET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); -} - -/* CONTRAST */ - -int pwc_get_contrast(struct pwc_device *pdev) -{ - char buf; - int ret; - - ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1); - if (ret < 0) - return ret; - return buf << 10; -} - -int pwc_set_contrast(struct pwc_device *pdev, int value) -{ - char buf; - - if (value < 0) - value = 0; - if (value > 0xffff) - value = 0xffff; - buf = (value >> 10) & 0x3f; - return SendControlMsg(SET_LUM_CTL, CONTRAST_FORMATTER, 1); -} - -/* GAMMA */ - -int pwc_get_gamma(struct pwc_device *pdev) -{ - char buf; - int ret; - - ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1); - if (ret < 0) - return ret; - return buf << 11; -} - -int pwc_set_gamma(struct pwc_device *pdev, int value) -{ - char buf; - - if (value < 0) - value = 0; - if (value > 0xffff) - value = 0xffff; - buf = (value >> 11) & 0x1f; - return SendControlMsg(SET_LUM_CTL, GAMMA_FORMATTER, 1); -} - - -/* SATURATION */ - -int pwc_get_saturation(struct pwc_device *pdev) -{ - char buf; - int ret; - - if (pdev->type < 675) - return -1; - ret = RecvControlMsg(GET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1); - if (ret < 0) - return ret; - return 32768 + buf * 327; -} - -int pwc_set_saturation(struct pwc_device *pdev, int value) -{ - char buf; - - if (pdev->type < 675) - return -EINVAL; - if (value < 0) - value = 0; - if (value > 0xffff) - value = 0xffff; - /* saturation ranges from -100 to +100 */ - buf = (value - 32768) / 327; - return SendControlMsg(SET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1); -} - -/* AGC */ - -static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value) -{ - char buf; - int ret; - - if (mode) - buf = 0x0; /* auto */ - else - buf = 0xff; /* fixed */ - - ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1); - - if (!mode && ret >= 0) { - if (value < 0) - value = 0; - if (value > 0xffff) - value = 0xffff; - buf = (value >> 10) & 0x3F; - ret = SendControlMsg(SET_LUM_CTL, PRESET_AGC_FORMATTER, 1); - } - if (ret < 0) - return ret; - return 0; -} - -static inline int pwc_get_agc(struct pwc_device *pdev, int *value) -{ - unsigned char buf; - int ret; - - ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1); - if (ret < 0) - return ret; - - if (buf != 0) { /* fixed */ - ret = RecvControlMsg(GET_LUM_CTL, PRESET_AGC_FORMATTER, 1); - if (ret < 0) - return ret; - if (buf > 0x3F) - buf = 0x3F; - *value = (buf << 10); - } - else { /* auto */ - ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1); - if (ret < 0) - return ret; - /* Gah... this value ranges from 0x00 ... 0x9F */ - if (buf > 0x9F) - buf = 0x9F; - *value = -(48 + buf * 409); - } - - return 0; -} - -static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) -{ - char buf[2]; - int speed, ret; - - - if (mode) - buf[0] = 0x0; /* auto */ - else - buf[0] = 0xff; /* fixed */ - - ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1); - - if (!mode && ret >= 0) { - if (value < 0) - value = 0; - if (value > 0xffff) - value = 0xffff; - switch(pdev->type) { - case 675: - case 680: - case 690: - /* speed ranges from 0x0 to 0x290 (656) */ - speed = (value / 100); - buf[1] = speed >> 8; - buf[0] = speed & 0xff; - break; - case 720: - case 730: - case 740: - case 750: - /* speed seems to range from 0x0 to 0xff */ - buf[1] = 0; - buf[0] = value >> 8; - break; - } - - ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2); - } - return ret; -} - - -/* POWER */ - -int pwc_camera_power(struct pwc_device *pdev, int power) -{ - char buf; - - if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6)) - return 0; /* Not supported by Nala or Timon < release 6 */ - - if (power) - buf = 0x00; /* active */ - else - buf = 0xFF; /* power save */ - return SendControlMsg(SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, 1); -} - - - -/* private calls */ - -static inline int pwc_restore_user(struct pwc_device *pdev) -{ - char buf; /* dummy */ - return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0); -} - -static inline int pwc_save_user(struct pwc_device *pdev) -{ - char buf; /* dummy */ - return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0); -} - -static inline int pwc_restore_factory(struct pwc_device *pdev) -{ - char buf; /* dummy */ - return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0); -} - - /* ************************************************* */ - /* Patch by Alvarado: (not in the original version */ - - /* - * the camera recognizes modes from 0 to 4: - * - * 00: indoor (incandescant lighting) - * 01: outdoor (sunlight) - * 02: fluorescent lighting - * 03: manual - * 04: auto - */ -static inline int pwc_set_awb(struct pwc_device *pdev, int mode) -{ - char buf; - int ret; - - if (mode < 0) - mode = 0; - - if (mode > 4) - mode = 4; - - buf = mode & 0x07; /* just the lowest three bits */ - - ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1); - - if (ret < 0) - return ret; - return 0; -} - -static inline int pwc_get_awb(struct pwc_device *pdev) -{ - unsigned char buf; - int ret; - - ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1); - - if (ret < 0) - return ret; - return buf; -} - -static inline int pwc_set_red_gain(struct pwc_device *pdev, int value) -{ - unsigned char buf; - - if (value < 0) - value = 0; - if (value > 0xffff) - value = 0xffff; - /* only the msb is considered */ - buf = value >> 8; - return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); -} - -static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value) -{ - unsigned char buf; - int ret; - - ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); - if (ret < 0) - return ret; - *value = buf << 8; - return 0; -} - - -static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value) -{ - unsigned char buf; - - if (value < 0) - value = 0; - if (value > 0xffff) - value = 0xffff; - /* only the msb is considered */ - buf = value >> 8; - return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); -} - -static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value) -{ - unsigned char buf; - int ret; - - ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); - if (ret < 0) - return ret; - *value = buf << 8; - return 0; -} - - -/* The following two functions are different, since they only read the - internal red/blue gains, which may be different from the manual - gains set or read above. - */ -static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value) -{ - unsigned char buf; - int ret; - - ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1); - if (ret < 0) - return ret; - *value = buf << 8; - return 0; -} - -static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value) -{ - unsigned char buf; - int ret; - - ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1); - if (ret < 0) - return ret; - *value = buf << 8; - return 0; -} - - -static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed) -{ - unsigned char buf; - - /* useful range is 0x01..0x20 */ - buf = speed / 0x7f0; - return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); -} - -static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value) -{ - unsigned char buf; - int ret; - - ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); - if (ret < 0) - return ret; - *value = buf * 0x7f0; - return 0; -} - - -static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay) -{ - unsigned char buf; - - /* useful range is 0x01..0x3F */ - buf = (delay >> 10); - return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); -} - -static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value) -{ - unsigned char buf; - int ret; - - ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); - if (ret < 0) - return ret; - *value = buf << 10; - return 0; -} - - -int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) -{ - unsigned char buf[2]; - - if (pdev->type < 730) - return 0; - on_value /= 100; - off_value /= 100; - if (on_value < 0) - on_value = 0; - if (on_value > 0xff) - on_value = 0xff; - if (off_value < 0) - off_value = 0; - if (off_value > 0xff) - off_value = 0xff; - - buf[0] = on_value; - buf[1] = off_value; - - return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2); -} - -static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) -{ - unsigned char buf[2]; - int ret; - - if (pdev->type < 730) { - *on_value = -1; - *off_value = -1; - return 0; - } - - ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2); - if (ret < 0) - return ret; - *on_value = buf[0] * 100; - *off_value = buf[1] * 100; - return 0; -} - -static inline int pwc_set_contour(struct pwc_device *pdev, int contour) -{ - unsigned char buf; - int ret; - - if (contour < 0) - buf = 0xff; /* auto contour on */ - else - buf = 0x0; /* auto contour off */ - ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); - if (ret < 0) - return ret; - - if (contour < 0) - return 0; - if (contour > 0xffff) - contour = 0xffff; - - buf = (contour >> 10); /* contour preset is [0..3f] */ - ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); - if (ret < 0) - return ret; - return 0; -} - -static inline int pwc_get_contour(struct pwc_device *pdev, int *contour) -{ - unsigned char buf; - int ret; - - ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); - if (ret < 0) - return ret; - - if (buf == 0) { - /* auto mode off, query current preset value */ - ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); - if (ret < 0) - return ret; - *contour = buf << 10; - } - else - *contour = -1; - return 0; -} - - -static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight) -{ - unsigned char buf; - - if (backlight) - buf = 0xff; - else - buf = 0x0; - return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); -} - -static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight) -{ - int ret; - unsigned char buf; - - ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); - if (ret < 0) - return ret; - *backlight = buf; - return 0; -} - - -static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker) -{ - unsigned char buf; - - if (flicker) - buf = 0xff; - else - buf = 0x0; - return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); -} - -static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker) -{ - int ret; - unsigned char buf; - - ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); - if (ret < 0) - return ret; - *flicker = buf; - return 0; -} - - -static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise) -{ - unsigned char buf; - - if (noise < 0) - noise = 0; - if (noise > 3) - noise = 3; - buf = noise; - return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); -} - -static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) -{ - int ret; - unsigned char buf; - - ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); - if (ret < 0) - return ret; - *noise = buf; - return 0; -} - -static int pwc_mpt_reset(struct pwc_device *pdev, int flags) -{ - unsigned char buf; - - buf = flags & 0x03; // only lower two bits are currently used - return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1); -} - -static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) -{ - unsigned char buf[4]; - - /* set new relative angle; angles are expressed in degrees * 100, - but cam as .5 degree resolution, hence divide by 200. Also - the angle must be multiplied by 64 before it's send to - the cam (??) - */ - pan = 64 * pan / 100; - tilt = -64 * tilt / 100; /* positive tilt is down, which is not what the user would expect */ - buf[0] = pan & 0xFF; - buf[1] = (pan >> 8) & 0xFF; - buf[2] = tilt & 0xFF; - buf[3] = (tilt >> 8) & 0xFF; - return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4); -} - -static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status) -{ - int ret; - unsigned char buf[5]; - - ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5); - if (ret < 0) - return ret; - status->status = buf[0] & 0x7; // 3 bits are used for reporting - status->time_pan = (buf[1] << 8) + buf[2]; - status->time_tilt = (buf[3] << 8) + buf[4]; - return 0; -} - - -int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) -{ - unsigned char buf; - int ret = -1, request; - - if (pdev->type < 675) - request = SENSOR_TYPE_FORMATTER1; - else if (pdev->type < 730) - return -1; /* The Vesta series doesn't have this call */ - else - request = SENSOR_TYPE_FORMATTER2; - - ret = RecvControlMsg(GET_STATUS_CTL, request, 1); - if (ret < 0) - return ret; - if (pdev->type < 675) - *sensor = buf | 0x100; - else - *sensor = buf; - return 0; -} - - - /* End of Add-Ons */ - /* ************************************************* */ - - -int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) -{ - int ret = 0; - - switch(cmd) { - case VIDIOCPWCRUSER: - { - if (pwc_restore_user(pdev)) - ret = -EINVAL; - break; - } - - case VIDIOCPWCSUSER: - { - if (pwc_save_user(pdev)) - ret = -EINVAL; - break; - } - - case VIDIOCPWCFACTORY: - { - if (pwc_restore_factory(pdev)) - ret = -EINVAL; - break; - } - - case VIDIOCPWCSCQUAL: - { - int *qual = arg; - - if (*qual < 0 || *qual > 3) - ret = -EINVAL; - else - ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot); - if (ret >= 0) - pdev->vcompression = *qual; - break; - } - - case VIDIOCPWCGCQUAL: - { - int *qual = arg; - *qual = pdev->vcompression; - break; - } - - case VIDIOCPWCPROBE: - { - struct pwc_probe *probe = arg; - strcpy(probe->name, pdev->vdev->name); - probe->type = pdev->type; - break; - } - - case VIDIOCPWCGSERIAL: - { - struct pwc_serial *serial = arg; - strcpy(serial->serial, pdev->serial); - break; - } - - case VIDIOCPWCSAGC: - { - int *agc = arg; - if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc)) - ret = -EINVAL; - break; - } - - case VIDIOCPWCGAGC: - { - int *agc = arg; - - if (pwc_get_agc(pdev, agc)) - ret = -EINVAL; - break; - } - - case VIDIOCPWCSSHUTTER: - { - int *shutter_speed = arg; - ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed); - break; - } - - case VIDIOCPWCSAWB: - { - struct pwc_whitebalance *wb = arg; - - ret = pwc_set_awb(pdev, wb->mode); - if (ret >= 0 && wb->mode == PWC_WB_MANUAL) { - pwc_set_red_gain(pdev, wb->manual_red); - pwc_set_blue_gain(pdev, wb->manual_blue); - } - break; - } - - case VIDIOCPWCGAWB: - { - struct pwc_whitebalance *wb = arg; - - memset(wb, 0, sizeof(struct pwc_whitebalance)); - wb->mode = pwc_get_awb(pdev); - if (wb->mode < 0) - ret = -EINVAL; - else { - if (wb->mode == PWC_WB_MANUAL) { - ret = pwc_get_red_gain(pdev, &wb->manual_red); - if (ret < 0) - break; - ret = pwc_get_blue_gain(pdev, &wb->manual_blue); - if (ret < 0) - break; - } - if (wb->mode == PWC_WB_AUTO) { - ret = pwc_read_red_gain(pdev, &wb->read_red); - if (ret < 0) - break; - ret = pwc_read_blue_gain(pdev, &wb->read_blue); - if (ret < 0) - break; - } - } - break; - } - - case VIDIOCPWCSAWBSPEED: - { - struct pwc_wb_speed *wbs = arg; - - if (wbs->control_speed > 0) { - ret = pwc_set_wb_speed(pdev, wbs->control_speed); - } - if (wbs->control_delay > 0) { - ret = pwc_set_wb_delay(pdev, wbs->control_delay); - } - break; - } - - case VIDIOCPWCGAWBSPEED: - { - struct pwc_wb_speed *wbs = arg; - - ret = pwc_get_wb_speed(pdev, &wbs->control_speed); - if (ret < 0) - break; - ret = pwc_get_wb_delay(pdev, &wbs->control_delay); - if (ret < 0) - break; - break; - } - - case VIDIOCPWCSLED: - { - struct pwc_leds *leds = arg; - ret = pwc_set_leds(pdev, leds->led_on, leds->led_off); - break; - } - - - case VIDIOCPWCGLED: - { - struct pwc_leds *leds = arg; - ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off); - break; - } - - case VIDIOCPWCSCONTOUR: - { - int *contour = arg; - ret = pwc_set_contour(pdev, *contour); - break; - } - - case VIDIOCPWCGCONTOUR: - { - int *contour = arg; - ret = pwc_get_contour(pdev, contour); - break; - } - - case VIDIOCPWCSBACKLIGHT: - { - int *backlight = arg; - ret = pwc_set_backlight(pdev, *backlight); - break; - } - - case VIDIOCPWCGBACKLIGHT: - { - int *backlight = arg; - ret = pwc_get_backlight(pdev, backlight); - break; - } - - case VIDIOCPWCSFLICKER: - { - int *flicker = arg; - ret = pwc_set_flicker(pdev, *flicker); - break; - } - - case VIDIOCPWCGFLICKER: - { - int *flicker = arg; - ret = pwc_get_flicker(pdev, flicker); - break; - } - - case VIDIOCPWCSDYNNOISE: - { - int *dynnoise = arg; - ret = pwc_set_dynamic_noise(pdev, *dynnoise); - break; - } - - case VIDIOCPWCGDYNNOISE: - { - int *dynnoise = arg; - ret = pwc_get_dynamic_noise(pdev, dynnoise); - break; - } - - case VIDIOCPWCGREALSIZE: - { - struct pwc_imagesize *size = arg; - size->width = pdev->image.x; - size->height = pdev->image.y; - break; - } - - case VIDIOCPWCMPTRESET: - { - if (pdev->features & FEATURE_MOTOR_PANTILT) - { - int *flags = arg; - - ret = pwc_mpt_reset(pdev, *flags); - if (ret >= 0) - { - pdev->pan_angle = 0; - pdev->tilt_angle = 0; - } - } - else - { - ret = -ENXIO; - } - break; - } - - case VIDIOCPWCMPTGRANGE: - { - if (pdev->features & FEATURE_MOTOR_PANTILT) - { - struct pwc_mpt_range *range = arg; - *range = pdev->angle_range; - } - else - { - ret = -ENXIO; - } - break; - } - - case VIDIOCPWCMPTSANGLE: - { - int new_pan, new_tilt; - - if (pdev->features & FEATURE_MOTOR_PANTILT) - { - struct pwc_mpt_angles *angles = arg; - /* The camera can only set relative angles, so - do some calculations when getting an absolute angle . - */ - if (angles->absolute) - { - new_pan = angles->pan; - new_tilt = angles->tilt; - } - else - { - new_pan = pdev->pan_angle + angles->pan; - new_tilt = pdev->tilt_angle + angles->tilt; - } - /* check absolute ranges */ - if (new_pan < pdev->angle_range.pan_min || - new_pan > pdev->angle_range.pan_max || - new_tilt < pdev->angle_range.tilt_min || - new_tilt > pdev->angle_range.tilt_max) - { - ret = -ERANGE; - } - else - { - /* go to relative range, check again */ - new_pan -= pdev->pan_angle; - new_tilt -= pdev->tilt_angle; - /* angles are specified in degrees * 100, thus the limit = 36000 */ - if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000) - ret = -ERANGE; - } - if (ret == 0) /* no errors so far */ - { - ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt); - if (ret >= 0) - { - pdev->pan_angle += new_pan; - pdev->tilt_angle += new_tilt; - } - if (ret == -EPIPE) /* stall -> out of range */ - ret = -ERANGE; - } - } - else - { - ret = -ENXIO; - } - break; - } - - case VIDIOCPWCMPTGANGLE: - { - - if (pdev->features & FEATURE_MOTOR_PANTILT) - { - struct pwc_mpt_angles *angles = arg; - - angles->absolute = 1; - angles->pan = pdev->pan_angle; - angles->tilt = pdev->tilt_angle; - } - else - { - ret = -ENXIO; - } - break; - } - - case VIDIOCPWCMPTSTATUS: - { - if (pdev->features & FEATURE_MOTOR_PANTILT) - { - struct pwc_mpt_status *status = arg; - ret = pwc_mpt_get_status(pdev, status); - } - else - { - ret = -ENXIO; - } - break; - } - - case VIDIOCPWCGVIDCMD: - { - struct pwc_video_command *cmd = arg; - - cmd->type = pdev->type; - cmd->release = pdev->release; - cmd->command_len = pdev->cmd_len; - memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len); - cmd->bandlength = pdev->vbandlength; - cmd->frame_size = pdev->frame_size; - break; - } - /* - case VIDIOCPWCGVIDTABLE: - { - struct pwc_table_init_buffer *table = arg; - table->len = pdev->cmd_len; - memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size); - break; - } - */ - - default: - ret = -ENOIOCTLCMD; - break; - } - - if (ret > 0) - return 0; - return ret; -} - - - diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c deleted file mode 100644 index 90eb26042817..000000000000 --- a/drivers/usb/media/pwc/pwc-if.c +++ /dev/null @@ -1,2205 +0,0 @@ -/* Linux driver for Philips webcam - USB and Video4Linux interface part. - (C) 1999-2004 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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 - -*/ - -/* - This code forms the interface between the USB layers and the Philips - specific stuff. Some adanved stuff of the driver falls under an - NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and - is thus not distributed in source form. The binary pwcx.o module - contains the code that falls under the NDA. - - In case you're wondering: 'pwc' stands for "Philips WebCam", but - I really didn't want to type 'philips_web_cam' every time (I'm lazy as - any Linux kernel hacker, but I don't like uncomprehensible abbreviations - without explanation). - - Oh yes, convention: to disctinguish between all the various pointers to - device-structures, I use these names for the pointer variables: - udev: struct usb_device * - vdev: struct video_device * - pdev: struct pwc_devive * -*/ - -/* Contributors: - - Alvarado: adding whitebalance code - - Alistar Moire: QuickCam 3000 Pro device/product ID - - Tony Hoyle: Creative Labs Webcam 5 device/product ID - - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged - - Jk Fang: Sotec Afina Eye ID - - Xavier Roche: QuickCam Pro 4000 ID - - Jens Knudsen: QuickCam Zoom ID - - J. Debert: QuickCam for Notebooks ID -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pwc.h" -#include "pwc-ioctl.h" -#include "pwc-kiara.h" -#include "pwc-timon.h" -#include "pwc-uncompress.h" - -/* Function prototypes and driver templates */ - -/* hotplug device table support */ -static struct usb_device_id pwc_device_table [] = { - { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */ - { USB_DEVICE(0x0471, 0x0303) }, - { USB_DEVICE(0x0471, 0x0304) }, - { USB_DEVICE(0x0471, 0x0307) }, - { USB_DEVICE(0x0471, 0x0308) }, - { USB_DEVICE(0x0471, 0x030C) }, - { USB_DEVICE(0x0471, 0x0310) }, - { USB_DEVICE(0x0471, 0x0311) }, - { USB_DEVICE(0x0471, 0x0312) }, - { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ - { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ - { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ - { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ - { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */ - { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */ - { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */ - { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */ - { USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */ - { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */ - { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */ - { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */ - { USB_DEVICE(0x055D, 0x9001) }, - { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ - { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */ - { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */ - { USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */ - { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */ - { USB_DEVICE(0x0d81, 0x1900) }, - { } -}; -MODULE_DEVICE_TABLE(usb, pwc_device_table); - -static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id); -static void usb_pwc_disconnect(struct usb_interface *intf); - -static struct usb_driver pwc_driver = { - .name = "Philips webcam", /* name */ - .id_table = pwc_device_table, - .probe = usb_pwc_probe, /* probe() */ - .disconnect = usb_pwc_disconnect, /* disconnect() */ -}; - -#define MAX_DEV_HINTS 20 -#define MAX_ISOC_ERRORS 20 - -static int default_size = PSZ_QCIF; -static int default_fps = 10; -static int default_fbufs = 3; /* Default number of frame buffers */ -static int default_mbufs = 2; /* Default number of mmap() buffers */ - int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX; -static int power_save = 0; -static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ -static int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */ -static struct { - int type; - char serial_number[30]; - int device_node; - struct pwc_device *pdev; -} device_hint[MAX_DEV_HINTS]; - -/***/ - -static int pwc_video_open(struct inode *inode, struct file *file); -static int pwc_video_close(struct inode *inode, struct file *file); -static ssize_t pwc_video_read(struct file *file, char __user * buf, - size_t count, loff_t *ppos); -static unsigned int pwc_video_poll(struct file *file, poll_table *wait); -static int pwc_video_ioctl(struct inode *inode, struct file *file, - unsigned int ioctlnr, unsigned long arg); -static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma); - -static struct file_operations pwc_fops = { - .owner = THIS_MODULE, - .open = pwc_video_open, - .release = pwc_video_close, - .read = pwc_video_read, - .poll = pwc_video_poll, - .mmap = pwc_video_mmap, - .ioctl = pwc_video_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, -}; -static struct video_device pwc_template = { - .owner = THIS_MODULE, - .name = "Philips Webcam", /* Filled in later */ - .type = VID_TYPE_CAPTURE, - .hardware = VID_HARDWARE_PWC, - .release = video_device_release, - .fops = &pwc_fops, - .minor = -1, -}; - -/***************************************************************************/ - -/* Okay, this is some magic that I worked out and the reasoning behind it... - - The biggest problem with any USB device is of course: "what to do - when the user unplugs the device while it is in use by an application?" - We have several options: - 1) Curse them with the 7 plagues when they do (requires divine intervention) - 2) Tell them not to (won't work: they'll do it anyway) - 3) Oops the kernel (this will have a negative effect on a user's uptime) - 4) Do something sensible. - - Of course, we go for option 4. - - It happens that this device will be linked to two times, once from - usb_device and once from the video_device in their respective 'private' - pointers. This is done when the device is probed() and all initialization - succeeded. The pwc_device struct links back to both structures. - - When a device is unplugged while in use it will be removed from the - list of known USB devices; I also de-register it as a V4L device, but - unfortunately I can't free the memory since the struct is still in use - by the file descriptor. This free-ing is then deferend until the first - opportunity. Crude, but it works. - - A small 'advantage' is that if a user unplugs the cam and plugs it back - in, it should get assigned the same video device minor, but unfortunately - it's non-trivial to re-link the cam back to the video device... (that - would surely be magic! :)) -*/ - -/***************************************************************************/ -/* Private functions */ - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - -static void * rvmalloc(unsigned long size) -{ - void * mem; - unsigned long adr; - - size=PAGE_ALIGN(size); - mem=vmalloc_32(size); - if (mem) - { - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr=(unsigned long) mem; - while (size > 0) - { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - } - return mem; -} - -static void rvfree(void * mem, unsigned long size) -{ - unsigned long adr; - - if (mem) - { - adr=(unsigned long) mem; - while ((long) size > 0) - { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - vfree(mem); - } -} - - - - -static int pwc_allocate_buffers(struct pwc_device *pdev) -{ - int i; - void *kbuf; - - Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev); - - if (pdev == NULL) - return -ENXIO; - -#ifdef PWC_MAGIC - if (pdev->magic != PWC_MAGIC) { - Err("allocate_buffers(): magic failed.\n"); - return -ENXIO; - } -#endif - /* Allocate Isochronous pipe buffers */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - if (pdev->sbuf[i].data == NULL) { - kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL); - if (kbuf == NULL) { - Err("Failed to allocate iso buffer %d.\n", i); - return -ENOMEM; - } - Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf); - pdev->sbuf[i].data = kbuf; - memset(kbuf, 0, ISO_BUFFER_SIZE); - } - } - - /* Allocate frame buffer structure */ - if (pdev->fbuf == NULL) { - kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL); - if (kbuf == NULL) { - Err("Failed to allocate frame buffer structure.\n"); - return -ENOMEM; - } - Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf); - pdev->fbuf = kbuf; - memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf)); - } - /* create frame buffers, and make circular ring */ - for (i = 0; i < default_fbufs; i++) { - if (pdev->fbuf[i].data == NULL) { - kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ - if (kbuf == NULL) { - Err("Failed to allocate frame buffer %d.\n", i); - return -ENOMEM; - } - Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf); - pdev->fbuf[i].data = kbuf; - memset(kbuf, 128, PWC_FRAME_SIZE); - } - } - - /* Allocate decompressor table space */ - kbuf = NULL; - switch (pdev->type) - { - case 675: - case 680: - case 690: - case 720: - case 730: - case 740: - case 750: -#if 0 - Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private)); - kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */ - break; - case 645: - case 646: - /* TODO & FIXME */ - kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); - break; -#endif - ; - } - pdev->decompress_data = kbuf; - - /* Allocate image buffer; double buffer for mmap() */ - kbuf = rvmalloc(default_mbufs * pdev->len_per_image); - if (kbuf == NULL) { - Err("Failed to allocate image buffer(s). needed (%d)\n",default_mbufs * pdev->len_per_image); - return -ENOMEM; - } - Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf); - pdev->image_data = kbuf; - for (i = 0; i < default_mbufs; i++) - pdev->image_ptr[i] = kbuf + i * pdev->len_per_image; - for (; i < MAX_IMAGES; i++) - pdev->image_ptr[i] = NULL; - - kbuf = NULL; - - Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n"); - return 0; -} - -static void pwc_free_buffers(struct pwc_device *pdev) -{ - int i; - - Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev); - - if (pdev == NULL) - return; -#ifdef PWC_MAGIC - if (pdev->magic != PWC_MAGIC) { - Err("free_buffers(): magic failed.\n"); - return; - } -#endif - - /* Release Iso-pipe buffers */ - for (i = 0; i < MAX_ISO_BUFS; i++) - if (pdev->sbuf[i].data != NULL) { - Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data); - kfree(pdev->sbuf[i].data); - pdev->sbuf[i].data = NULL; - } - - /* The same for frame buffers */ - if (pdev->fbuf != NULL) { - for (i = 0; i < default_fbufs; i++) { - if (pdev->fbuf[i].data != NULL) { - Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data); - vfree(pdev->fbuf[i].data); - pdev->fbuf[i].data = NULL; - } - } - kfree(pdev->fbuf); - pdev->fbuf = NULL; - } - - /* Intermediate decompression buffer & tables */ - if (pdev->decompress_data != NULL) { - Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data); - kfree(pdev->decompress_data); - pdev->decompress_data = NULL; - } - pdev->decompressor = NULL; - - /* Release image buffers */ - if (pdev->image_data != NULL) { - Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data); - rvfree(pdev->image_data, default_mbufs * pdev->len_per_image); - } - pdev->image_data = NULL; - - Trace(TRACE_MEMORY, "Leaving free_buffers().\n"); -} - -/* The frame & image buffer mess. - - Yes, this is a mess. Well, it used to be simple, but alas... In this - module, 3 buffers schemes are used to get the data from the USB bus to - the user program. The first scheme involves the ISO buffers (called thus - since they transport ISO data from the USB controller), and not really - interesting. Suffices to say the data from this buffer is quickly - gathered in an interrupt handler (pwc_isoc_handler) and placed into the - frame buffer. - - The frame buffer is the second scheme, and is the central element here. - It collects the data from a single frame from the camera (hence, the - name). Frames are delimited by the USB camera with a short USB packet, - so that's easy to detect. The frame buffers form a list that is filled - by the camera+USB controller and drained by the user process through - either read() or mmap(). - - The image buffer is the third scheme, in which frames are decompressed - and converted into planar format. For mmap() there is more than - one image buffer available. - - The frame buffers provide the image buffering. In case the user process - is a bit slow, this introduces lag and some undesired side-effects. - The problem arises when the frame buffer is full. I used to drop the last - frame, which makes the data in the queue stale very quickly. But dropping - the frame at the head of the queue proved to be a litte bit more difficult. - I tried a circular linked scheme, but this introduced more problems than - it solved. - - Because filling and draining are completely asynchronous processes, this - requires some fiddling with pointers and mutexes. - - Eventually, I came up with a system with 2 lists: an 'empty' frame list - and a 'full' frame list: - * Initially, all frame buffers but one are on the 'empty' list; the one - remaining buffer is our initial fill frame. - * If a frame is needed for filling, we try to take it from the 'empty' - list, unless that list is empty, in which case we take the buffer at - the head of the 'full' list. - * When our fill buffer has been filled, it is appended to the 'full' - list. - * If a frame is needed by read() or mmap(), it is taken from the head of - the 'full' list, handled, and then appended to the 'empty' list. If no - buffer is present on the 'full' list, we wait. - The advantage is that the buffer that is currently being decompressed/ - converted, is on neither list, and thus not in our way (any other scheme - I tried had the problem of old data lingering in the queue). - - Whatever strategy you choose, it always remains a tradeoff: with more - frame buffers the chances of a missed frame are reduced. On the other - hand, on slower machines it introduces lag because the queue will - always be full. - */ - -/** - \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first. - */ -static inline int pwc_next_fill_frame(struct pwc_device *pdev) -{ - int ret; - unsigned long flags; - - ret = 0; - spin_lock_irqsave(&pdev->ptrlock, flags); - if (pdev->fill_frame != NULL) { - /* append to 'full' list */ - if (pdev->full_frames == NULL) { - pdev->full_frames = pdev->fill_frame; - pdev->full_frames_tail = pdev->full_frames; - } - else { - pdev->full_frames_tail->next = pdev->fill_frame; - pdev->full_frames_tail = pdev->fill_frame; - } - } - if (pdev->empty_frames != NULL) { - /* We have empty frames available. That's easy */ - pdev->fill_frame = pdev->empty_frames; - pdev->empty_frames = pdev->empty_frames->next; - } - else { - /* Hmm. Take it from the full list */ -#if PWC_DEBUG - /* sanity check */ - if (pdev->full_frames == NULL) { - Err("Neither empty or full frames available!\n"); - spin_unlock_irqrestore(&pdev->ptrlock, flags); - return -EINVAL; - } -#endif - pdev->fill_frame = pdev->full_frames; - pdev->full_frames = pdev->full_frames->next; - ret = 1; - } - pdev->fill_frame->next = NULL; -#if PWC_DEBUG - Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence); - pdev->fill_frame->sequence = pdev->sequence++; -#endif - spin_unlock_irqrestore(&pdev->ptrlock, flags); - return ret; -} - - -/** - \brief Reset all buffers, pointers and lists, except for the image_used[] buffer. - - If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble. - */ -static void pwc_reset_buffers(struct pwc_device *pdev) -{ - int i; - unsigned long flags; - - spin_lock_irqsave(&pdev->ptrlock, flags); - pdev->full_frames = NULL; - pdev->full_frames_tail = NULL; - for (i = 0; i < default_fbufs; i++) { - pdev->fbuf[i].filled = 0; - if (i > 0) - pdev->fbuf[i].next = &pdev->fbuf[i - 1]; - else - pdev->fbuf->next = NULL; - } - pdev->empty_frames = &pdev->fbuf[default_fbufs - 1]; - pdev->empty_frames_tail = pdev->fbuf; - pdev->read_frame = NULL; - pdev->fill_frame = pdev->empty_frames; - pdev->empty_frames = pdev->empty_frames->next; - - pdev->image_read_pos = 0; - pdev->fill_image = 0; - spin_unlock_irqrestore(&pdev->ptrlock, flags); -} - - -/** - \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers. - */ -static int pwc_handle_frame(struct pwc_device *pdev) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&pdev->ptrlock, flags); - /* First grab our read_frame; this is removed from all lists, so - we can release the lock after this without problems */ - if (pdev->read_frame != NULL) { - /* This can't theoretically happen */ - Err("Huh? Read frame still in use?\n"); - } - else { - if (pdev->full_frames == NULL) { - Err("Woops. No frames ready.\n"); - } - else { - pdev->read_frame = pdev->full_frames; - pdev->full_frames = pdev->full_frames->next; - pdev->read_frame->next = NULL; - } - - if (pdev->read_frame != NULL) { -#if PWC_DEBUG - Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence); -#endif - /* Decompression is a lenghty process, so it's outside of the lock. - This gives the isoc_handler the opportunity to fill more frames - in the mean time. - */ - spin_unlock_irqrestore(&pdev->ptrlock, flags); - ret = pwc_decompress(pdev); - spin_lock_irqsave(&pdev->ptrlock, flags); - - /* We're done with read_buffer, tack it to the end of the empty buffer list */ - if (pdev->empty_frames == NULL) { - pdev->empty_frames = pdev->read_frame; - pdev->empty_frames_tail = pdev->empty_frames; - } - else { - pdev->empty_frames_tail->next = pdev->read_frame; - pdev->empty_frames_tail = pdev->read_frame; - } - pdev->read_frame = NULL; - } - } - spin_unlock_irqrestore(&pdev->ptrlock, flags); - return ret; -} - -/** - \brief Advance pointers of image buffer (after each user request) -*/ -static inline void pwc_next_image(struct pwc_device *pdev) -{ - pdev->image_used[pdev->fill_image] = 0; - pdev->fill_image = (pdev->fill_image + 1) % default_mbufs; -} - - -/* This gets called for the Isochronous pipe (video). This is done in - * interrupt time, so it has to be fast, not crash, and not stall. Neat. - */ -static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) -{ - struct pwc_device *pdev; - int i, fst, flen; - int awake; - struct pwc_frame_buf *fbuf; - unsigned char *fillptr = NULL, *iso_buf = NULL; - - awake = 0; - pdev = (struct pwc_device *)urb->context; - if (pdev == NULL) { - Err("isoc_handler() called with NULL device?!\n"); - return; - } -#ifdef PWC_MAGIC - if (pdev->magic != PWC_MAGIC) { - Err("isoc_handler() called with bad magic!\n"); - return; - } -#endif - if (urb->status == -ENOENT || urb->status == -ECONNRESET) { - Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); - return; - } - if (urb->status != -EINPROGRESS && urb->status != 0) { - const char *errmsg; - - errmsg = "Unknown"; - switch(urb->status) { - case -ENOSR: errmsg = "Buffer error (overrun)"; break; - case -EPIPE: errmsg = "Stalled (device not responding)"; break; - case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break; - case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break; - case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break; - case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break; - } - Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); - /* Give up after a number of contiguous errors on the USB bus. - Appearantly something is wrong so we simulate an unplug event. - */ - if (++pdev->visoc_errors > MAX_ISOC_ERRORS) - { - Info("Too many ISOC errors, bailing out.\n"); - pdev->error_status = EIO; - awake = 1; - wake_up_interruptible(&pdev->frameq); - } - goto handler_end; // ugly, but practical - } - - fbuf = pdev->fill_frame; - if (fbuf == NULL) { - Err("pwc_isoc_handler without valid fill frame.\n"); - awake = 1; - goto handler_end; - } - else { - fillptr = fbuf->data + fbuf->filled; - } - - /* Reset ISOC error counter. We did get here, after all. */ - pdev->visoc_errors = 0; - - /* vsync: 0 = don't copy data - 1 = sync-hunt - 2 = synched - */ - /* Compact data */ - for (i = 0; i < urb->number_of_packets; i++) { - fst = urb->iso_frame_desc[i].status; - flen = urb->iso_frame_desc[i].actual_length; - iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - if (fst == 0) { - if (flen > 0) { /* if valid data... */ - if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */ - pdev->vsync = 2; - - /* ...copy data to frame buffer, if possible */ - if (flen + fbuf->filled > pdev->frame_total_size) { - Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size); - pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */ - pdev->vframes_error++; - } - else { - memmove(fillptr, iso_buf, flen); - fillptr += flen; - } - } - fbuf->filled += flen; - } /* ..flen > 0 */ - - if (flen < pdev->vlast_packet_size) { - /* Shorter packet... We probably have the end of an image-frame; - wake up read() process and let select()/poll() do something. - Decompression is done in user time over there. - */ - if (pdev->vsync == 2) { - /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus - frames on the USB wire after an exposure change. This conditition is - however detected in the cam and a bit is set in the header. - */ - if (pdev->type == 730) { - unsigned char *ptr = (unsigned char *)fbuf->data; - - if (ptr[1] == 1 && ptr[0] & 0x10) { -#if PWC_DEBUG - Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence); -#endif - pdev->drop_frames += 2; - pdev->vframes_error++; - } - if ((ptr[0] ^ pdev->vmirror) & 0x01) { - if (ptr[0] & 0x01) - Info("Snapshot button pressed.\n"); - else - Info("Snapshot button released.\n"); - } - if ((ptr[0] ^ pdev->vmirror) & 0x02) { - if (ptr[0] & 0x02) - Info("Image is mirrored.\n"); - else - Info("Image is normal.\n"); - } - pdev->vmirror = ptr[0] & 0x03; - /* Sometimes the trailer of the 730 is still sent as a 4 byte packet - after a short frame; this condition is filtered out specifically. A 4 byte - frame doesn't make sense anyway. - So we get either this sequence: - drop_bit set -> 4 byte frame -> short frame -> good frame - Or this one: - drop_bit set -> short frame -> good frame - So we drop either 3 or 2 frames in all! - */ - if (fbuf->filled == 4) - pdev->drop_frames++; - } - - /* In case we were instructed to drop the frame, do so silently. - The buffer pointers are not updated either (but the counters are reset below). - */ - if (pdev->drop_frames > 0) - pdev->drop_frames--; - else { - /* Check for underflow first */ - if (fbuf->filled < pdev->frame_total_size) { - Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled); - pdev->vframes_error++; - } - else { - /* Send only once per EOF */ - awake = 1; /* delay wake_ups */ - - /* Find our next frame to fill. This will always succeed, since we - * nick a frame from either empty or full list, but if we had to - * take it from the full list, it means a frame got dropped. - */ - if (pwc_next_fill_frame(pdev)) { - pdev->vframes_dumped++; - if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) { - if (pdev->vframes_dumped < 20) - Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count); - if (pdev->vframes_dumped == 20) - Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count); - } - } - fbuf = pdev->fill_frame; - } - } /* !drop_frames */ - pdev->vframe_count++; - } - fbuf->filled = 0; - fillptr = fbuf->data; - pdev->vsync = 1; - } /* .. flen < last_packet_size */ - pdev->vlast_packet_size = flen; - } /* ..status == 0 */ -#if PWC_DEBUG - /* This is normally not interesting to the user, unless you are really debugging something */ - else { - static int iso_error = 0; - iso_error++; - if (iso_error < 20) - Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst); - } -#endif - } - -handler_end: - if (awake) - wake_up_interruptible(&pdev->frameq); - - urb->dev = pdev->udev; - i = usb_submit_urb(urb, GFP_ATOMIC); - if (i != 0) - Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i); -} - - -static int pwc_isoc_init(struct pwc_device *pdev) -{ - struct usb_device *udev; - struct urb *urb; - int i, j, ret; - - struct usb_interface *intf; - struct usb_host_interface *idesc = NULL; - - if (pdev == NULL) - return -EFAULT; - if (pdev->iso_init) - return 0; - pdev->vsync = 0; - udev = pdev->udev; - - /* Get the current alternate interface, adjust packet size */ - if (!udev->actconfig) - return -EFAULT; - - intf = usb_ifnum_to_if(udev, 0); - if (intf) - idesc = usb_altnum_to_altsetting(intf, pdev->valternate); - - if (!idesc) - return -EFAULT; - - /* Search video endpoint */ - pdev->vmax_packet_size = -1; - for (i = 0; i < idesc->desc.bNumEndpoints; i++) - if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) { - pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize); - break; - } - - if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { - Err("Failed to find packet size for video endpoint in current alternate setting.\n"); - return -ENFILE; /* Odd error, that should be noticeable */ - } - - /* Set alternate interface */ - ret = 0; - Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate); - ret = usb_set_interface(pdev->udev, 0, pdev->valternate); - if (ret < 0) - return ret; - - for (i = 0; i < MAX_ISO_BUFS; i++) { - urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); - if (urb == NULL) { - Err("Failed to allocate urb %d\n", i); - ret = -ENOMEM; - break; - } - pdev->sbuf[i].urb = urb; - Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb); - } - if (ret) { - /* De-allocate in reverse order */ - while (i >= 0) { - if (pdev->sbuf[i].urb != NULL) - usb_free_urb(pdev->sbuf[i].urb); - pdev->sbuf[i].urb = NULL; - i--; - } - return ret; - } - - /* init URB structure */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - urb = pdev->sbuf[i].urb; - - urb->interval = 1; // devik - urb->dev = udev; - urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint); - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = pdev->sbuf[i].data; - urb->transfer_buffer_length = ISO_BUFFER_SIZE; - urb->complete = pwc_isoc_handler; - urb->context = pdev; - urb->start_frame = 0; - urb->number_of_packets = ISO_FRAMES_PER_DESC; - for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { - urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; - urb->iso_frame_desc[j].length = pdev->vmax_packet_size; - } - } - - /* link */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL); - if (ret) - Err("isoc_init() submit_urb %d failed with error %d\n", i, ret); - else - Trace(TRACE_MEMORY, "URB 0x%p submitted.\n", pdev->sbuf[i].urb); - } - - /* All is done... */ - pdev->iso_init = 1; - Trace(TRACE_OPEN, "<< pwc_isoc_init()\n"); - return 0; -} - -static void pwc_isoc_cleanup(struct pwc_device *pdev) -{ - int i; - - Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n"); - if (pdev == NULL) - return; - - /* Unlinking ISOC buffers one by one */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - struct urb *urb; - - urb = pdev->sbuf[i].urb; - if (urb != 0) { - if (pdev->iso_init) { - Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb); - usb_kill_urb(urb); - } - Trace(TRACE_MEMORY, "Freeing URB\n"); - usb_free_urb(urb); - pdev->sbuf[i].urb = NULL; - } - } - - /* Stop camera, but only if we are sure the camera is still there (unplug - is signalled by EPIPE) - */ - if (pdev->error_status && pdev->error_status != EPIPE) { - Trace(TRACE_OPEN, "Setting alternate interface 0.\n"); - usb_set_interface(pdev->udev, 0, 0); - } - - pdev->iso_init = 0; - Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n"); -} - -int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot) -{ - int ret, start; - - /* Stop isoc stuff */ - pwc_isoc_cleanup(pdev); - /* Reset parameters */ - pwc_reset_buffers(pdev); - /* Try to set video mode... */ - start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); - if (ret) { - Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n"); - /* That failed... restore old mode (we know that worked) */ - start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); - if (start) { - Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n"); - } - } - if (start == 0) - { - if (pwc_isoc_init(pdev) < 0) - { - Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n"); - ret = -EAGAIN; /* let's try again, who knows if it works a second time */ - } - } - pdev->drop_frames++; /* try to avoid garbage during switch */ - return ret; /* Return original error code */ -} - - -/***************************************************************************/ -/* Video4Linux functions */ - -static int pwc_video_open(struct inode *inode, struct file *file) -{ - int i; - struct video_device *vdev = video_devdata(file); - struct pwc_device *pdev; - - Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev); - - pdev = (struct pwc_device *)vdev->priv; - if (pdev == NULL) - BUG(); - if (pdev->vopen) - return -EBUSY; - - down(&pdev->modlock); - if (!pdev->usb_init) { - Trace(TRACE_OPEN, "Doing first time initialization.\n"); - pdev->usb_init = 1; - - if (pwc_trace & TRACE_OPEN) - { - /* Query sensor type */ - const char *sensor_type = NULL; - int ret; - - ret = pwc_get_cmos_sensor(pdev, &i); - if (ret >= 0) - { - switch(i) { - case 0x00: sensor_type = "Hyundai CMOS sensor"; break; - case 0x20: sensor_type = "Sony CCD sensor + TDA8787"; break; - case 0x2E: sensor_type = "Sony CCD sensor + Exas 98L59"; break; - case 0x2F: sensor_type = "Sony CCD sensor + ADI 9804"; break; - case 0x30: sensor_type = "Sharp CCD sensor + TDA8787"; break; - case 0x3E: sensor_type = "Sharp CCD sensor + Exas 98L59"; break; - case 0x3F: sensor_type = "Sharp CCD sensor + ADI 9804"; break; - case 0x40: sensor_type = "UPA 1021 sensor"; break; - case 0x100: sensor_type = "VGA sensor"; break; - case 0x101: sensor_type = "PAL MR sensor"; break; - default: sensor_type = "unknown type of sensor"; break; - } - } - if (sensor_type != NULL) - Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i); - } - } - - /* Turn on camera */ - if (power_save) { - i = pwc_camera_power(pdev, 1); - if (i < 0) - Info("Failed to restore power to the camera! (%d)\n", i); - } - /* Set LED on/off time */ - if (pwc_set_leds(pdev, led_on, led_off) < 0) - Info("Failed to set LED on/off time.\n"); - - pwc_construct(pdev); /* set min/max sizes correct */ - - /* So far, so good. Allocate memory. */ - i = pwc_allocate_buffers(pdev); - if (i < 0) { - Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n"); - up(&pdev->modlock); - return i; - } - - /* Reset buffers & parameters */ - pwc_reset_buffers(pdev); - for (i = 0; i < default_mbufs; i++) - pdev->image_used[i] = 0; - pdev->vframe_count = 0; - pdev->vframes_dumped = 0; - pdev->vframes_error = 0; - pdev->visoc_errors = 0; - pdev->error_status = 0; -#if PWC_DEBUG - pdev->sequence = 0; -#endif - pwc_construct(pdev); /* set min/max sizes correct */ - - /* Set some defaults */ - pdev->vsnapshot = 0; - - /* Start iso pipe for video; first try the last used video size - (or the default one); if that fails try QCIF/10 or QSIF/10; - it that fails too, give up. - */ - i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0); - if (i) { - Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n"); - if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750) - i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0); - else - i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0); - } - if (i) { - Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n"); - up(&pdev->modlock); - return i; - } - - i = pwc_isoc_init(pdev); - if (i) { - Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i); - up(&pdev->modlock); - return i; - } - - pdev->vopen++; - file->private_data = vdev; - up(&pdev->modlock); - Trace(TRACE_OPEN, "<< video_open() returns 0.\n"); - return 0; -} - -/* Note that all cleanup is done in the reverse order as in _open */ -static int pwc_video_close(struct inode *inode, struct file *file) -{ - struct video_device *vdev = file->private_data; - struct pwc_device *pdev; - int i; - - Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev); - - pdev = (struct pwc_device *)vdev->priv; - if (pdev->vopen == 0) - Info("video_close() called on closed device?\n"); - - /* Dump statistics, but only if a reasonable amount of frames were - processed (to prevent endless log-entries in case of snap-shot - programs) - */ - if (pdev->vframe_count > 20) - Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error); - - switch (pdev->type) - { - case 675: - case 680: - case 690: - case 720: - case 730: - case 740: - case 750: -/* pwc_dec23_exit(); *//* Timon & Kiara */ - break; - case 645: - case 646: -/* pwc_dec1_exit(); */ - break; - } - - pwc_isoc_cleanup(pdev); - pwc_free_buffers(pdev); - - /* Turn off LEDS and power down camera, but only when not unplugged */ - if (pdev->error_status != EPIPE) { - /* Turn LEDs off */ - if (pwc_set_leds(pdev, 0, 0) < 0) - Info("Failed to set LED on/off time.\n"); - if (power_save) { - i = pwc_camera_power(pdev, 0); - if (i < 0) - Err("Failed to power down camera (%d)\n", i); - } - } - pdev->vopen = 0; - Trace(TRACE_OPEN, "<< video_close()\n"); - return 0; -} - -/* - * FIXME: what about two parallel reads ???? - * ANSWER: Not supported. You can't open the device more than once, - despite what the V4L1 interface says. First, I don't see - the need, second there's no mechanism of alerting the - 2nd/3rd/... process of events like changing image size. - And I don't see the point of blocking that for the - 2nd/3rd/... process. - In multi-threaded environments reading parallel from any - device is tricky anyhow. - */ - -static ssize_t pwc_video_read(struct file *file, char __user * buf, - size_t count, loff_t *ppos) -{ - struct video_device *vdev = file->private_data; - struct pwc_device *pdev; - int noblock = file->f_flags & O_NONBLOCK; - DECLARE_WAITQUEUE(wait, current); - int bytes_to_read; - - Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count); - if (vdev == NULL) - return -EFAULT; - pdev = vdev->priv; - if (pdev == NULL) - return -EFAULT; - if (pdev->error_status) - return -pdev->error_status; /* Something happened, report what. */ - - /* In case we're doing partial reads, we don't have to wait for a frame */ - if (pdev->image_read_pos == 0) { - /* Do wait queueing according to the (doc)book */ - add_wait_queue(&pdev->frameq, &wait); - while (pdev->full_frames == NULL) { - /* Check for unplugged/etc. here */ - if (pdev->error_status) { - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - return -pdev->error_status ; - } - if (noblock) { - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - return -EWOULDBLOCK; - } - if (signal_pending(current)) { - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - return -ERESTARTSYS; - } - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - } - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - - /* Decompress and release frame */ - if (pwc_handle_frame(pdev)) - return -EFAULT; - } - - Trace(TRACE_READ, "Copying data to user space.\n"); - if (pdev->vpalette == VIDEO_PALETTE_RAW) - bytes_to_read = pdev->frame_size; - else - bytes_to_read = pdev->view.size; - - /* copy bytes to user space; we allow for partial reads */ - if (count + pdev->image_read_pos > bytes_to_read) - count = bytes_to_read - pdev->image_read_pos; - if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count)) - return -EFAULT; - pdev->image_read_pos += count; - if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */ - pdev->image_read_pos = 0; - pwc_next_image(pdev); - } - return count; -} - -static unsigned int pwc_video_poll(struct file *file, poll_table *wait) -{ - struct video_device *vdev = file->private_data; - struct pwc_device *pdev; - - if (vdev == NULL) - return -EFAULT; - pdev = vdev->priv; - if (pdev == NULL) - return -EFAULT; - - poll_wait(file, &pdev->frameq, wait); - if (pdev->error_status) - return POLLERR; - if (pdev->full_frames != NULL) /* we have frames waiting */ - return (POLLIN | POLLRDNORM); - - return 0; -} - -static int pwc_video_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct video_device *vdev = file->private_data; - struct pwc_device *pdev; - DECLARE_WAITQUEUE(wait, current); - - if (vdev == NULL) - return -EFAULT; - pdev = vdev->priv; - if (pdev == NULL) - return -EFAULT; - - switch (cmd) { - /* Query cabapilities */ - case VIDIOCGCAP: - { - struct video_capability *caps = arg; - - strcpy(caps->name, vdev->name); - caps->type = VID_TYPE_CAPTURE; - caps->channels = 1; - caps->audios = 1; - caps->minwidth = pdev->view_min.x; - caps->minheight = pdev->view_min.y; - caps->maxwidth = pdev->view_max.x; - caps->maxheight = pdev->view_max.y; - break; - } - - /* Channel functions (simulate 1 channel) */ - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - v->flags = 0; - v->tuners = 0; - v->type = VIDEO_TYPE_CAMERA; - strcpy(v->name, "Webcam"); - return 0; - } - - case VIDIOCSCHAN: - { - /* The spec says the argument is an integer, but - the bttv driver uses a video_channel arg, which - makes sense becasue it also has the norm flag. - */ - struct video_channel *v = arg; - if (v->channel != 0) - return -EINVAL; - return 0; - } - - - /* Picture functions; contrast etc. */ - case VIDIOCGPICT: - { - struct video_picture *p = arg; - int val; - - val = pwc_get_brightness(pdev); - if (val >= 0) - p->brightness = val; - else - p->brightness = 0xffff; - val = pwc_get_contrast(pdev); - if (val >= 0) - p->contrast = val; - else - p->contrast = 0xffff; - /* Gamma, Whiteness, what's the difference? :) */ - val = pwc_get_gamma(pdev); - if (val >= 0) - p->whiteness = val; - else - p->whiteness = 0xffff; - val = pwc_get_saturation(pdev); - if (val >= 0) - p->colour = val; - else - p->colour = 0xffff; - p->depth = 24; - p->palette = pdev->vpalette; - p->hue = 0xFFFF; /* N/A */ - break; - } - - case VIDIOCSPICT: - { - struct video_picture *p = arg; - /* - * FIXME: Suppose we are mid read - ANSWER: No problem: the firmware of the camera - can handle brightness/contrast/etc - changes at _any_ time, and the palette - is used exactly once in the uncompress - routine. - */ - pwc_set_brightness(pdev, p->brightness); - pwc_set_contrast(pdev, p->contrast); - pwc_set_gamma(pdev, p->whiteness); - pwc_set_saturation(pdev, p->colour); - if (p->palette && p->palette != pdev->vpalette) { - switch (p->palette) { - case VIDEO_PALETTE_YUV420P: - case VIDEO_PALETTE_RAW: - pdev->vpalette = p->palette; - return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); - break; - default: - return -EINVAL; - break; - } - } - break; - } - - /* Window/size parameters */ - case VIDIOCGWIN: - { - struct video_window *vw = arg; - - vw->x = 0; - vw->y = 0; - vw->width = pdev->view.x; - vw->height = pdev->view.y; - vw->chromakey = 0; - vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | - (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0); - break; - } - - case VIDIOCSWIN: - { - struct video_window *vw = arg; - int fps, snapshot, ret; - - fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; - snapshot = vw->flags & PWC_FPS_SNAPSHOT; - if (fps == 0) - fps = pdev->vframes; - if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot) - return 0; - ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot); - if (ret) - return ret; - break; - } - - /* We don't have overlay support (yet) */ - case VIDIOCGFBUF: - { - struct video_buffer *vb = arg; - - memset(vb,0,sizeof(*vb)); - break; - } - - /* mmap() functions */ - case VIDIOCGMBUF: - { - /* Tell the user program how much memory is needed for a mmap() */ - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0, sizeof(*vm)); - vm->size = default_mbufs * pdev->len_per_image; - vm->frames = default_mbufs; /* double buffering should be enough for most applications */ - for (i = 0; i < default_mbufs; i++) - vm->offsets[i] = i * pdev->len_per_image; - break; - } - - case VIDIOCMCAPTURE: - { - /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */ - struct video_mmap *vm = arg; - - Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format); - if (vm->frame < 0 || vm->frame >= default_mbufs) - return -EINVAL; - - /* xawtv is nasty. It probes the available palettes - by setting a very small image size and trying - various palettes... The driver doesn't support - such small images, so I'm working around it. - */ - if (vm->format) - { - switch (vm->format) - { - case VIDEO_PALETTE_YUV420P: - case VIDEO_PALETTE_RAW: - break; - default: - return -EINVAL; - break; - } - } - - if ((vm->width != pdev->view.x || vm->height != pdev->view.y) && - (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) { - int ret; - - Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n"); - ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot); - if (ret) - return ret; - } /* ... size mismatch */ - - /* FIXME: should we lock here? */ - if (pdev->image_used[vm->frame]) - return -EBUSY; /* buffer wasn't available. Bummer */ - pdev->image_used[vm->frame] = 1; - - /* Okay, we're done here. In the SYNC call we wait until a - frame comes available, then expand image into the given - buffer. - In contrast to the CPiA cam the Philips cams deliver a - constant stream, almost like a grabber card. Also, - we have separate buffers for the rawdata and the image, - meaning we can nearly always expand into the requested buffer. - */ - Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n"); - break; - } - - case VIDIOCSYNC: - { - /* The doc says: "Whenever a buffer is used it should - call VIDIOCSYNC to free this frame up and continue." - - The only odd thing about this whole procedure is - that MCAPTURE flags the buffer as "in use", and - SYNC immediately unmarks it, while it isn't - after SYNC that you know that the buffer actually - got filled! So you better not start a CAPTURE in - the same frame immediately (use double buffering). - This is not a problem for this cam, since it has - extra intermediate buffers, but a hardware - grabber card will then overwrite the buffer - you're working on. - */ - int *mbuf = arg; - int ret; - - Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", *mbuf); - - /* bounds check */ - if (*mbuf < 0 || *mbuf >= default_mbufs) - return -EINVAL; - /* check if this buffer was requested anyway */ - if (pdev->image_used[*mbuf] == 0) - return -EINVAL; - - /* Add ourselves to the frame wait-queue. - - FIXME: needs auditing for safety. - QUESTION: In what respect? I think that using the - frameq is safe now. - */ - add_wait_queue(&pdev->frameq, &wait); - while (pdev->full_frames == NULL) { - if (pdev->error_status) { - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - return -pdev->error_status; - } - - if (signal_pending(current)) { - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - return -ERESTARTSYS; - } - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - } - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - - /* The frame is ready. Expand in the image buffer - requested by the user. I don't care if you - mmap() 5 buffers and request data in this order: - buffer 4 2 3 0 1 2 3 0 4 3 1 . . . - Grabber hardware may not be so forgiving. - */ - Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n"); - pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */ - /* Decompress, etc */ - ret = pwc_handle_frame(pdev); - pdev->image_used[*mbuf] = 0; - if (ret) - return -EFAULT; - break; - } - - case VIDIOCGAUDIO: - { - struct video_audio *v = arg; - - strcpy(v->name, "Microphone"); - v->audio = -1; /* unknown audio minor */ - v->flags = 0; - v->mode = VIDEO_SOUND_MONO; - v->volume = 0; - v->bass = 0; - v->treble = 0; - v->balance = 0x8000; - v->step = 1; - break; - } - - case VIDIOCSAUDIO: - { - /* Dummy: nothing can be set */ - break; - } - - case VIDIOCGUNIT: - { - struct video_unit *vu = arg; - - vu->video = pdev->vdev->minor & 0x3F; - vu->audio = -1; /* not known yet */ - vu->vbi = -1; - vu->radio = -1; - vu->teletext = -1; - break; - } - default: - return pwc_ioctl(pdev, cmd, arg); - } /* ..switch */ - return 0; -} - -static int pwc_video_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl); -} - - -static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct video_device *vdev = file->private_data; - struct pwc_device *pdev; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; - - Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size); - pdev = vdev->priv; - - vma->vm_flags |= VM_IO; - - pos = (unsigned long)pdev->image_data; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - return 0; -} - -/***************************************************************************/ -/* USB functions */ - -/* This function gets called when a new device is plugged in or the usb core - * is loaded. - */ - -static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct pwc_device *pdev = NULL; - int vendor_id, product_id, type_id; - int i, hint; - int features = 0; - int video_nr = -1; /* default: use next available device */ - char serial_number[30], *name; - - /* Check if we can handle this device */ - Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - intf->altsetting->desc.bInterfaceNumber); - - /* the interfaces are probed one by one. We are only interested in the - video interface (0) now. - Interface 1 is the Audio Control, and interface 2 Audio itself. - */ - if (intf->altsetting->desc.bInterfaceNumber > 0) - return -ENODEV; - - vendor_id = le16_to_cpu(udev->descriptor.idVendor); - product_id = le16_to_cpu(udev->descriptor.idProduct); - - if (vendor_id == 0x0471) { - switch (product_id) { - case 0x0302: - Info("Philips PCA645VC USB webcam detected.\n"); - name = "Philips 645 webcam"; - type_id = 645; - break; - case 0x0303: - Info("Philips PCA646VC USB webcam detected.\n"); - name = "Philips 646 webcam"; - type_id = 646; - break; - case 0x0304: - Info("Askey VC010 type 2 USB webcam detected.\n"); - name = "Askey VC010 webcam"; - type_id = 646; - break; - case 0x0307: - Info("Philips PCVC675K (Vesta) USB webcam detected.\n"); - name = "Philips 675 webcam"; - type_id = 675; - break; - case 0x0308: - Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n"); - name = "Philips 680 webcam"; - type_id = 680; - break; - case 0x030C: - Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n"); - name = "Philips 690 webcam"; - type_id = 690; - break; - case 0x0310: - Info("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n"); - name = "Philips 730 webcam"; - type_id = 730; - break; - case 0x0311: - Info("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n"); - name = "Philips 740 webcam"; - type_id = 740; - break; - case 0x0312: - Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n"); - name = "Philips 750 webcam"; - type_id = 750; - break; - case 0x0313: - Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n"); - name = "Philips 720K/40 webcam"; - type_id = 720; - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x069A) { - switch(product_id) { - case 0x0001: - Info("Askey VC010 type 1 USB webcam detected.\n"); - name = "Askey VC010 webcam"; - type_id = 645; - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x046d) { - switch(product_id) { - case 0x08b0: - Info("Logitech QuickCam Pro 3000 USB webcam detected.\n"); - name = "Logitech QuickCam Pro 3000"; - type_id = 740; /* CCD sensor */ - break; - case 0x08b1: - Info("Logitech QuickCam Notebook Pro USB webcam detected.\n"); - name = "Logitech QuickCam Notebook Pro"; - type_id = 740; /* CCD sensor */ - break; - case 0x08b2: - Info("Logitech QuickCam 4000 Pro USB webcam detected.\n"); - name = "Logitech QuickCam Pro 4000"; - type_id = 740; /* CCD sensor */ - break; - case 0x08b3: - Info("Logitech QuickCam Zoom USB webcam detected.\n"); - name = "Logitech QuickCam Zoom"; - type_id = 740; /* CCD sensor */ - break; - case 0x08B4: - Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n"); - name = "Logitech QuickCam Zoom"; - type_id = 740; /* CCD sensor */ - break; - case 0x08b5: - Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n"); - name = "Logitech QuickCam Orbit"; - type_id = 740; /* CCD sensor */ - features |= FEATURE_MOTOR_PANTILT; - break; - case 0x08b6: - case 0x08b7: - case 0x08b8: - Info("Logitech QuickCam detected (reserved ID).\n"); - name = "Logitech QuickCam (res.)"; - type_id = 730; /* Assuming CMOS */ - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x055d) { - /* I don't know the difference between the C10 and the C30; - I suppose the difference is the sensor, but both cameras - work equally well with a type_id of 675 - */ - switch(product_id) { - case 0x9000: - Info("Samsung MPC-C10 USB webcam detected.\n"); - name = "Samsung MPC-C10"; - type_id = 675; - break; - case 0x9001: - Info("Samsung MPC-C30 USB webcam detected.\n"); - name = "Samsung MPC-C30"; - type_id = 675; - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x041e) { - switch(product_id) { - case 0x400c: - Info("Creative Labs Webcam 5 detected.\n"); - name = "Creative Labs Webcam 5"; - type_id = 730; - break; - case 0x4011: - Info("Creative Labs Webcam Pro Ex detected.\n"); - name = "Creative Labs Webcam Pro Ex"; - type_id = 740; - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x04cc) { - switch(product_id) { - case 0x8116: - Info("Sotec Afina Eye USB webcam detected.\n"); - name = "Sotec Afina Eye"; - type_id = 730; - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x06be) { - switch(product_id) { - case 0x8116: - /* This is essentially the same cam as the Sotec Afina Eye */ - Info("AME Co. Afina Eye USB webcam detected.\n"); - name = "AME Co. Afina Eye"; - type_id = 750; - break; - default: - return -ENODEV; - break; - } - - } - else if (vendor_id == 0x0d81) { - switch(product_id) { - case 0x1900: - Info("Visionite VCS-UC300 USB webcam detected.\n"); - name = "Visionite VCS-UC300"; - type_id = 740; /* CCD sensor */ - break; - case 0x1910: - Info("Visionite VCS-UM100 USB webcam detected.\n"); - name = "Visionite VCS-UM100"; - type_id = 730; /* CMOS sensor */ - break; - default: - return -ENODEV; - break; - } - } - else - return -ENODEV; /* Not any of the know types; but the list keeps growing. */ - - memset(serial_number, 0, 30); - usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29); - Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number); - - if (udev->descriptor.bNumConfigurations > 1) - Info("Warning: more than 1 configuration available.\n"); - - /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */ - pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL); - if (pdev == NULL) { - Err("Oops, could not allocate memory for pwc_device.\n"); - return -ENOMEM; - } - pdev->type = type_id; - pdev->vsize = default_size; - pdev->vframes = default_fps; - strcpy(pdev->serial, serial_number); - pdev->features = features; - if (vendor_id == 0x046D && product_id == 0x08B5) - { - /* Logitech QuickCam Orbit - The ranges have been determined experimentally; they may differ from cam to cam. - Also, the exact ranges left-right and up-down are different for my cam - */ - pdev->angle_range.pan_min = -7000; - pdev->angle_range.pan_max = 7000; - pdev->angle_range.tilt_min = -3000; - pdev->angle_range.tilt_max = 2500; - } - - init_MUTEX(&pdev->modlock); - spin_lock_init(&pdev->ptrlock); - - pdev->udev = udev; - init_waitqueue_head(&pdev->frameq); - pdev->vcompression = pwc_preferred_compression; - - /* Allocate video_device structure */ - pdev->vdev = video_device_alloc(); - if (pdev->vdev == 0) - { - Err("Err, cannot allocate video_device struture. Failing probe."); - kfree(pdev); - return -ENOMEM; - } - memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template)); - strcpy(pdev->vdev->name, name); - pdev->vdev->owner = THIS_MODULE; - video_set_drvdata(pdev->vdev, pdev); - - pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); - Trace(TRACE_PROBE, "Release: %04x\n", pdev->release); - - /* Now search device_hint[] table for a match, so we can hint a node number. */ - for (hint = 0; hint < MAX_DEV_HINTS; hint++) { - if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) && - (device_hint[hint].pdev == NULL)) { - /* so far, so good... try serial number */ - if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) { - /* match! */ - video_nr = device_hint[hint].device_node; - Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr); - break; - } - } - } - - pdev->vdev->release = video_device_release; - i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); - if (i < 0) { - Err("Failed to register as video device (%d).\n", i); - video_device_release(pdev->vdev); /* Drip... drip... drip... */ - kfree(pdev); /* Oops, no memory leaks please */ - return -EIO; - } - else { - Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F); - } - - /* occupy slot */ - if (hint < MAX_DEV_HINTS) - device_hint[hint].pdev = pdev; - - Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev); - usb_set_intfdata (intf, pdev); - return 0; -} - -/* The user janked out the cable... */ -static void usb_pwc_disconnect(struct usb_interface *intf) -{ - struct pwc_device *pdev; - int hint; - - lock_kernel(); - pdev = usb_get_intfdata (intf); - usb_set_intfdata (intf, NULL); - if (pdev == NULL) { - Err("pwc_disconnect() Called without private pointer.\n"); - goto disconnect_out; - } - if (pdev->udev == NULL) { - Err("pwc_disconnect() already called for %p\n", pdev); - goto disconnect_out; - } - if (pdev->udev != interface_to_usbdev(intf)) { - Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n"); - goto disconnect_out; - } -#ifdef PWC_MAGIC - if (pdev->magic != PWC_MAGIC) { - Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n"); - goto disconnect_out; - } -#endif - - /* We got unplugged; this is signalled by an EPIPE error code */ - if (pdev->vopen) { - Info("Disconnected while webcam is in use!\n"); - pdev->error_status = EPIPE; - } - - /* Alert waiting processes */ - wake_up_interruptible(&pdev->frameq); - /* Wait until device is closed */ - while (pdev->vopen) - schedule(); - /* Device is now closed, so we can safely unregister it */ - Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n"); - video_unregister_device(pdev->vdev); - - /* Free memory (don't set pdev to 0 just yet) */ - kfree(pdev); - -disconnect_out: - /* search device_hint[] table if we occupy a slot, by any chance */ - for (hint = 0; hint < MAX_DEV_HINTS; hint++) - if (device_hint[hint].pdev == pdev) - device_hint[hint].pdev = NULL; - - unlock_kernel(); -} - - -/* *grunt* We have to do atoi ourselves :-( */ -static int pwc_atoi(const char *s) -{ - int k = 0; - - k = 0; - while (*s != '\0' && *s >= '0' && *s <= '9') { - k = 10 * k + (*s - '0'); - s++; - } - return k; -} - - -/* - * Initialization code & module stuff - */ - -static char size[10]; -static int fps = 0; -static int fbufs = 0; -static int mbufs = 0; -static int trace = -1; -static int compression = -1; -static int leds[2] = { -1, -1 }; -static char *dev_hint[MAX_DEV_HINTS] = { }; - -module_param_string(size, size, sizeof(size), 0); -MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga"); -module_param(fps, int, 0000); -MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); -module_param(fbufs, int, 0000); -MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve"); -module_param(mbufs, int, 0000); -MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers"); -module_param(trace, int, 0000); -MODULE_PARM_DESC(trace, "For debugging purposes"); -module_param(power_save, bool, 0000); -MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off"); -module_param(compression, int, 0000); -MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); -module_param_array(leds, int, NULL, 0000); -MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); -module_param_array(dev_hint, charp, NULL, 0000); -MODULE_PARM_DESC(dev_hint, "Device node hints"); - -MODULE_DESCRIPTION("Philips & OEM USB webcam driver"); -MODULE_AUTHOR("Luc Saillard "); -MODULE_LICENSE("GPL"); - -static int __init usb_pwc_init(void) -{ - int i, sz; - char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" }; - - Info("Philips webcam module version " PWC_VERSION " loaded.\n"); - Info("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n"); - Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n"); - Info("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n"); - - if (fps) { - if (fps < 4 || fps > 30) { - Err("Framerate out of bounds (4-30).\n"); - return -EINVAL; - } - default_fps = fps; - Info("Default framerate set to %d.\n", default_fps); - } - - if (size[0]) { - /* string; try matching with array */ - for (sz = 0; sz < PSZ_MAX; sz++) { - if (!strcmp(sizenames[sz], size)) { /* Found! */ - default_size = sz; - break; - } - } - if (sz == PSZ_MAX) { - Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n"); - return -EINVAL; - } - Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y); - } - if (mbufs) { - if (mbufs < 1 || mbufs > MAX_IMAGES) { - Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES); - return -EINVAL; - } - default_mbufs = mbufs; - Info("Number of image buffers set to %d.\n", default_mbufs); - } - if (fbufs) { - if (fbufs < 2 || fbufs > MAX_FRAMES) { - Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES); - return -EINVAL; - } - default_fbufs = fbufs; - Info("Number of frame buffers set to %d.\n", default_fbufs); - } - if (trace >= 0) { - Info("Trace options: 0x%04x\n", trace); - pwc_trace = trace; - } - if (compression >= 0) { - if (compression > 3) { - Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n"); - return -EINVAL; - } - pwc_preferred_compression = compression; - Info("Preferred compression set to %d.\n", pwc_preferred_compression); - } - if (power_save) - Info("Enabling power save on open/close.\n"); - if (leds[0] >= 0) - led_on = leds[0]; - if (leds[1] >= 0) - led_off = leds[1]; - - /* Big device node whoopla. Basically, it allows you to assign a - device node (/dev/videoX) to a camera, based on its type - & serial number. The format is [type[.serialnumber]:]node. - - Any camera that isn't matched by these rules gets the next - available free device node. - */ - for (i = 0; i < MAX_DEV_HINTS; i++) { - char *s, *colon, *dot; - - /* This loop also initializes the array */ - device_hint[i].pdev = NULL; - s = dev_hint[i]; - if (s != NULL && *s != '\0') { - device_hint[i].type = -1; /* wildcard */ - strcpy(device_hint[i].serial_number, "*"); - - /* parse string: chop at ':' & '/' */ - colon = dot = s; - while (*colon != '\0' && *colon != ':') - colon++; - while (*dot != '\0' && *dot != '.') - dot++; - /* Few sanity checks */ - if (*dot != '\0' && dot > colon) { - Err("Malformed camera hint: the colon must be after the dot.\n"); - return -EINVAL; - } - - if (*colon == '\0') { - /* No colon */ - if (*dot != '\0') { - Err("Malformed camera hint: no colon + device node given.\n"); - return -EINVAL; - } - else { - /* No type or serial number specified, just a number. */ - device_hint[i].device_node = pwc_atoi(s); - } - } - else { - /* There's a colon, so we have at least a type and a device node */ - device_hint[i].type = pwc_atoi(s); - device_hint[i].device_node = pwc_atoi(colon + 1); - if (*dot != '\0') { - /* There's a serial number as well */ - int k; - - dot++; - k = 0; - while (*dot != ':' && k < 29) { - device_hint[i].serial_number[k++] = *dot; - dot++; - } - device_hint[i].serial_number[k] = '\0'; - } - } -#if PWC_DEBUG - Debug("device_hint[%d]:\n", i); - Debug(" type : %d\n", device_hint[i].type); - Debug(" serial# : %s\n", device_hint[i].serial_number); - Debug(" node : %d\n", device_hint[i].device_node); -#endif - } - else - device_hint[i].type = 0; /* not filled */ - } /* ..for MAX_DEV_HINTS */ - - Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver); - return usb_register(&pwc_driver); -} - -static void __exit usb_pwc_exit(void) -{ - Trace(TRACE_MODULE, "Deregistering driver.\n"); - usb_deregister(&pwc_driver); - Info("Philips webcam module removed.\n"); -} - -module_init(usb_pwc_init); -module_exit(usb_pwc_exit); - diff --git a/drivers/usb/media/pwc/pwc-ioctl.h b/drivers/usb/media/pwc/pwc-ioctl.h deleted file mode 100644 index 5f9cb08bc02e..000000000000 --- a/drivers/usb/media/pwc/pwc-ioctl.h +++ /dev/null @@ -1,292 +0,0 @@ -#ifndef PWC_IOCTL_H -#define PWC_IOCTL_H - -/* (C) 2001-2004 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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 -*/ - -/* This is pwc-ioctl.h belonging to PWC 8.12.1 - It contains structures and defines to communicate from user space - directly to the driver. - */ - -/* - Changes - 2001/08/03 Alvarado Added ioctl constants to access methods for - changing white balance and red/blue gains - 2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE - 2003/12/13 Nemosft Unv. Some modifications to make interfacing to - PWCX easier - */ - -/* These are private ioctl() commands, specific for the Philips webcams. - They contain functions not found in other webcams, and settings not - specified in the Video4Linux API. - - The #define names are built up like follows: - VIDIOC VIDeo IOCtl prefix - PWC Philps WebCam - G optional: Get - S optional: Set - ... the function - */ - - - /* Enumeration of image sizes */ -#define PSZ_SQCIF 0x00 -#define PSZ_QSIF 0x01 -#define PSZ_QCIF 0x02 -#define PSZ_SIF 0x03 -#define PSZ_CIF 0x04 -#define PSZ_VGA 0x05 -#define PSZ_MAX 6 - - -/* The frame rate is encoded in the video_window.flags parameter using - the upper 16 bits, since some flags are defined nowadays. The following - defines provide a mask and shift to filter out this value. - - In 'Snapshot' mode the camera freezes its automatic exposure and colour - balance controls. - */ -#define PWC_FPS_SHIFT 16 -#define PWC_FPS_MASK 0x00FF0000 -#define PWC_FPS_FRMASK 0x003F0000 -#define PWC_FPS_SNAPSHOT 0x00400000 - - -/* structure for transferring x & y coordinates */ -struct pwc_coord -{ - int x, y; /* guess what */ - int size; /* size, or offset */ -}; - - -/* Used with VIDIOCPWCPROBE */ -struct pwc_probe -{ - char name[32]; - int type; -}; - -struct pwc_serial -{ - char serial[30]; /* String with serial number. Contains terminating 0 */ -}; - -/* pwc_whitebalance.mode values */ -#define PWC_WB_INDOOR 0 -#define PWC_WB_OUTDOOR 1 -#define PWC_WB_FL 2 -#define PWC_WB_MANUAL 3 -#define PWC_WB_AUTO 4 - -/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). - Set mode to one of the PWC_WB_* values above. - *red and *blue are the respective gains of these colour components inside - the camera; range 0..65535 - When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read; - otherwise undefined. - 'read_red' and 'read_blue' are read-only. -*/ -struct pwc_whitebalance -{ - int mode; - int manual_red, manual_blue; /* R/W */ - int read_red, read_blue; /* R/O */ -}; - -/* - 'control_speed' and 'control_delay' are used in automatic whitebalance mode, - and tell the camera how fast it should react to changes in lighting, and - with how much delay. Valid values are 0..65535. -*/ -struct pwc_wb_speed -{ - int control_speed; - int control_delay; - -}; - -/* Used with VIDIOCPWC[SG]LED */ -struct pwc_leds -{ - int led_on; /* Led on-time; range = 0..25000 */ - int led_off; /* Led off-time; range = 0..25000 */ -}; - -/* Image size (used with GREALSIZE) */ -struct pwc_imagesize -{ - int width; - int height; -}; - -/* Defines and structures for Motorized Pan & Tilt */ -#define PWC_MPT_PAN 0x01 -#define PWC_MPT_TILT 0x02 -#define PWC_MPT_TIMEOUT 0x04 /* for status */ - -/* Set angles; when absolute != 0, the angle is absolute and the - driver calculates the relative offset for you. This can only - be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns - absolute angles. - */ -struct pwc_mpt_angles -{ - int absolute; /* write-only */ - int pan; /* degrees * 100 */ - int tilt; /* degress * 100 */ -}; - -/* Range of angles of the camera, both horizontally and vertically. - */ -struct pwc_mpt_range -{ - int pan_min, pan_max; /* degrees * 100 */ - int tilt_min, tilt_max; -}; - -struct pwc_mpt_status -{ - int status; - int time_pan; - int time_tilt; -}; - - -/* This is used for out-of-kernel decompression. With it, you can get - all the necessary information to initialize and use the decompressor - routines in standalone applications. - */ -struct pwc_video_command -{ - int type; /* camera type (645, 675, 730, etc.) */ - int release; /* release number */ - - int size; /* one of PSZ_* */ - int alternate; - int command_len; /* length of USB video command */ - unsigned char command_buf[13]; /* Actual USB video command */ - int bandlength; /* >0 = compressed */ - int frame_size; /* Size of one (un)compressed frame */ -}; - -/* Flags for PWCX subroutines. Not all modules honour all flags. */ -#define PWCX_FLAG_PLANAR 0x0001 -#define PWCX_FLAG_BAYER 0x0008 - - -/* IOCTL definitions */ - - /* Restore user settings */ -#define VIDIOCPWCRUSER _IO('v', 192) - /* Save user settings */ -#define VIDIOCPWCSUSER _IO('v', 193) - /* Restore factory settings */ -#define VIDIOCPWCFACTORY _IO('v', 194) - - /* You can manipulate the compression factor. A compression preference of 0 - means use uncompressed modes when available; 1 is low compression, 2 is - medium and 3 is high compression preferred. Of course, the higher the - compression, the lower the bandwidth used but more chance of artefacts - in the image. The driver automatically chooses a higher compression when - the preferred mode is not available. - */ - /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */ -#define VIDIOCPWCSCQUAL _IOW('v', 195, int) - /* Get preferred compression quality */ -#define VIDIOCPWCGCQUAL _IOR('v', 195, int) - - -/* Retrieve serial number of camera */ -#define VIDIOCPWCGSERIAL _IOR('v', 198, struct pwc_serial) - - /* This is a probe function; since so many devices are supported, it - becomes difficult to include all the names in programs that want to - check for the enhanced Philips stuff. So in stead, try this PROBE; - it returns a structure with the original name, and the corresponding - Philips type. - To use, fill the structure with zeroes, call PROBE and if that succeeds, - compare the name with that returned from VIDIOCGCAP; they should be the - same. If so, you can be assured it is a Philips (OEM) cam and the type - is valid. - */ -#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe) - - /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */ -#define VIDIOCPWCSAGC _IOW('v', 200, int) - /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */ -#define VIDIOCPWCGAGC _IOR('v', 200, int) - /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */ -#define VIDIOCPWCSSHUTTER _IOW('v', 201, int) - - /* Color compensation (Auto White Balance) */ -#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance) -#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance) - - /* Auto WB speed */ -#define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed) -#define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed) - - /* LEDs on/off/blink; int range 0..65535 */ -#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds) -#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds) - - /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */ -#define VIDIOCPWCSCONTOUR _IOW('v', 206, int) -#define VIDIOCPWCGCONTOUR _IOR('v', 206, int) - - /* Backlight compensation; 0 = off, otherwise on */ -#define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int) -#define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int) - - /* Flickerless mode; = 0 off, otherwise on */ -#define VIDIOCPWCSFLICKER _IOW('v', 208, int) -#define VIDIOCPWCGFLICKER _IOR('v', 208, int) - - /* Dynamic noise reduction; 0 off, 3 = high noise reduction */ -#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int) -#define VIDIOCPWCGDYNNOISE _IOR('v', 209, int) - - /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */ -#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize) - - /* Motorized pan & tilt functions */ -#define VIDIOCPWCMPTRESET _IOW('v', 211, int) -#define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range) -#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles) -#define VIDIOCPWCMPTGANGLE _IOR('v', 212, struct pwc_mpt_angles) -#define VIDIOCPWCMPTSTATUS _IOR('v', 213, struct pwc_mpt_status) - - /* Get the USB set-video command; needed for initializing libpwcx */ -#define VIDIOCPWCGVIDCMD _IOR('v', 215, struct pwc_video_command) -struct pwc_table_init_buffer { - int len; - char *buffer; - -}; -#define VIDIOCPWCGVIDTABLE _IOR('v', 216, struct pwc_table_init_buffer) - -#endif diff --git a/drivers/usb/media/pwc/pwc-kiara.c b/drivers/usb/media/pwc/pwc-kiara.c deleted file mode 100644 index c498c68bace1..000000000000 --- a/drivers/usb/media/pwc/pwc-kiara.c +++ /dev/null @@ -1,318 +0,0 @@ -/* Linux driver for Philips webcam - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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 -*/ - - -/* This tables contains entries for the 730/740/750 (Kiara) camera, with - 4 different qualities (no compression, low, medium, high). - It lists the bandwidth requirements for said mode by its alternate interface - number. An alternate of 0 means that the mode is unavailable. - - There are 6 * 4 * 4 entries: - 6 different resolutions subqcif, qsif, qcif, sif, cif, vga - 6 framerates: 5, 10, 15, 20, 25, 30 - 4 compression modi: none, low, medium, high - - When an uncompressed mode is not available, the next available compressed mode - will be chosen (unless the decompressor is absent). Sometimes there are only - 1 or 2 compressed modes available; in that case entries are duplicated. -*/ - - -#include "pwc-kiara.h" -#include "pwc-uncompress.h" - -const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] = -{ - /* SQCIF */ - { - /* 5 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 10 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 15 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 20 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 25 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 30 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - }, - /* QSIF */ - { - /* 5 fps */ - { - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, - }, - /* 10 fps */ - { - {2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}}, - {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, - {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, - {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, - }, - /* 15 fps */ - { - {3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}}, - {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}}, - {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}}, - {1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}}, - }, - /* 20 fps */ - { - {4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}}, - {3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}}, - {2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}}, - {1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}}, - }, - /* 25 fps */ - { - {5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}}, - {3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}}, - {2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}}, - {1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}}, - }, - /* 30 fps */ - { - {8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}}, - {5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}}, - {3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}}, - {2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}}, - }, - }, - /* QCIF */ - { - /* 5 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 10 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 15 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 20 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 25 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 30 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - }, - /* SIF */ - { - /* 5 fps */ - { - {4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}}, - {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}}, - {2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}}, - {1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}}, - }, - /* 10 fps */ - { - {0, }, - {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}}, - {3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}}, - {2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}}, - }, - /* 15 fps */ - { - {0, }, - {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}}, - {4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}}, - {3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}}, - }, - /* 20 fps */ - { - {0, }, - {9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}}, - {5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}}, - {3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}}, - }, - /* 25 fps */ - { - {0, }, - {9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}}, - {6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}}, - {4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}}, - }, - /* 30 fps */ - { - {0, }, - {9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}}, - {6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}}, - {4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}}, - }, - }, - /* CIF */ - { - /* 5 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 10 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 15 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 20 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 25 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 30 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - }, - /* VGA */ - { - /* 5 fps */ - { - {0, }, - {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}}, - {4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}}, - {3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}}, - }, - /* 10 fps */ - { - {0, }, - {9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}}, - {6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}}, - {4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}}, - }, - /* 15 fps */ - { - {0, }, - {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}}, - {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}}, - {8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}}, - }, - /* 20 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 25 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 30 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - }, -}; - diff --git a/drivers/usb/media/pwc/pwc-kiara.h b/drivers/usb/media/pwc/pwc-kiara.h deleted file mode 100644 index 12929abbb1f0..000000000000 --- a/drivers/usb/media/pwc/pwc-kiara.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Linux driver for Philips webcam - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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 -*/ - -/* Entries for the Kiara (730/740/750) camera */ - -#ifndef PWC_KIARA_H -#define PWC_KIARA_H - -#include "pwc-ioctl.h" - -struct Kiara_table_entry -{ - char alternate; /* USB alternate interface */ - unsigned short packetsize; /* Normal packet size */ - unsigned short bandlength; /* Bandlength when decompressing */ - unsigned char mode[12]; /* precomputed mode settings for cam */ -}; - -const extern struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4]; -const extern unsigned int KiaraRomTable[8][2][16][8]; - -#endif - - diff --git a/drivers/usb/media/pwc/pwc-misc.c b/drivers/usb/media/pwc/pwc-misc.c deleted file mode 100644 index b7a4bd3524c7..000000000000 --- a/drivers/usb/media/pwc/pwc-misc.c +++ /dev/null @@ -1,140 +0,0 @@ -/* Linux driver for Philips webcam - Various miscellaneous functions and tables. - (C) 1999-2003 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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 "pwc.h" - -struct pwc_coord pwc_image_sizes[PSZ_MAX] = -{ - { 128, 96, 0 }, - { 160, 120, 0 }, - { 176, 144, 0 }, - { 320, 240, 0 }, - { 352, 288, 0 }, - { 640, 480, 0 }, -}; - -/* x,y -> PSZ_ */ -int pwc_decode_size(struct pwc_device *pdev, int width, int height) -{ - int i, find; - - /* Make sure we don't go beyond our max size. - NB: we have different limits for RAW and normal modes. In case - you don't have the decompressor loaded or use RAW mode, - the maximum viewable size is smaller. - */ - if (pdev->vpalette == VIDEO_PALETTE_RAW) - { - if (width > pdev->abs_max.x || height > pdev->abs_max.y) - { - Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n"); - return -1; - } - } - else - { - if (width > pdev->view_max.x || height > pdev->view_max.y) - { - Debug("VIDEO_PALETTE_ not RAW: going beyond view_max.\n"); - return -1; - } - } - - /* Find the largest size supported by the camera that fits into the - requested size. - */ - find = -1; - for (i = 0; i < PSZ_MAX; i++) { - if (pdev->image_mask & (1 << i)) { - if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height) - find = i; - } - } - return find; -} - -/* initialize variables depending on type and decompressor*/ -void pwc_construct(struct pwc_device *pdev) -{ - switch(pdev->type) { - case 645: - case 646: - pdev->view_min.x = 128; - pdev->view_min.y = 96; - pdev->view_max.x = 352; - pdev->view_max.y = 288; - pdev->abs_max.x = 352; - pdev->abs_max.y = 288; - pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF; - pdev->vcinterface = 2; - pdev->vendpoint = 4; - pdev->frame_header_size = 0; - pdev->frame_trailer_size = 0; - break; - case 675: - case 680: - case 690: - pdev->view_min.x = 128; - pdev->view_min.y = 96; - /* Anthill bug #38: PWC always reports max size, even without PWCX */ - pdev->view_max.x = 640; - pdev->view_max.y = 480; - pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA; - pdev->abs_max.x = 640; - pdev->abs_max.y = 480; - pdev->vcinterface = 3; - pdev->vendpoint = 4; - pdev->frame_header_size = 0; - pdev->frame_trailer_size = 0; - break; - case 720: - case 730: - case 740: - case 750: - pdev->view_min.x = 160; - pdev->view_min.y = 120; - pdev->view_max.x = 640; - pdev->view_max.y = 480; - pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; - pdev->abs_max.x = 640; - pdev->abs_max.y = 480; - pdev->vcinterface = 3; - pdev->vendpoint = 5; - pdev->frame_header_size = TOUCAM_HEADER_SIZE; - pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE; - break; - } - Debug("type = %d\n",pdev->type); - pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */ - pdev->view_min.size = pdev->view_min.x * pdev->view_min.y; - pdev->view_max.size = pdev->view_max.x * pdev->view_max.y; - /* length of image, in YUV format; always allocate enough memory. */ - pdev->len_per_image = (pdev->abs_max.x * pdev->abs_max.y * 3) / 2; -} - - diff --git a/drivers/usb/media/pwc/pwc-nala.h b/drivers/usb/media/pwc/pwc-nala.h deleted file mode 100644 index e6c5cb69d03b..000000000000 --- a/drivers/usb/media/pwc/pwc-nala.h +++ /dev/null @@ -1,66 +0,0 @@ - /* SQCIF */ - { - {0, 0, {0x04, 0x01, 0x03}}, - {8, 0, {0x05, 0x01, 0x03}}, - {7, 0, {0x08, 0x01, 0x03}}, - {7, 0, {0x0A, 0x01, 0x03}}, - {6, 0, {0x0C, 0x01, 0x03}}, - {5, 0, {0x0F, 0x01, 0x03}}, - {4, 0, {0x14, 0x01, 0x03}}, - {3, 0, {0x18, 0x01, 0x03}}, - }, - /* QSIF */ - { - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - }, - /* QCIF */ - { - {0, 0, {0x04, 0x01, 0x02}}, - {8, 0, {0x05, 0x01, 0x02}}, - {7, 0, {0x08, 0x01, 0x02}}, - {6, 0, {0x0A, 0x01, 0x02}}, - {5, 0, {0x0C, 0x01, 0x02}}, - {4, 0, {0x0F, 0x01, 0x02}}, - {1, 0, {0x14, 0x01, 0x02}}, - {1, 0, {0x18, 0x01, 0x02}}, - }, - /* SIF */ - { - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - }, - /* CIF */ - { - {4, 0, {0x04, 0x01, 0x01}}, - {7, 1, {0x05, 0x03, 0x01}}, - {6, 1, {0x08, 0x03, 0x01}}, - {4, 1, {0x0A, 0x03, 0x01}}, - {3, 1, {0x0C, 0x03, 0x01}}, - {2, 1, {0x0F, 0x03, 0x01}}, - {0}, - {0}, - }, - /* VGA */ - { - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - }, diff --git a/drivers/usb/media/pwc/pwc-timon.c b/drivers/usb/media/pwc/pwc-timon.c deleted file mode 100644 index dee967173d6c..000000000000 --- a/drivers/usb/media/pwc/pwc-timon.c +++ /dev/null @@ -1,316 +0,0 @@ -/* Linux driver for Philips webcam - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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 -*/ - - -/* This tables contains entries for the 675/680/690 (Timon) camera, with - 4 different qualities (no compression, low, medium, high). - It lists the bandwidth requirements for said mode by its alternate interface - number. An alternate of 0 means that the mode is unavailable. - - There are 6 * 4 * 4 entries: - 6 different resolutions subqcif, qsif, qcif, sif, cif, vga - 6 framerates: 5, 10, 15, 20, 25, 30 - 4 compression modi: none, low, medium, high - - When an uncompressed mode is not available, the next available compressed mode - will be chosen (unless the decompressor is absent). Sometimes there are only - 1 or 2 compressed modes available; in that case entries are duplicated. -*/ - -#include "pwc-timon.h" - -const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = -{ - /* SQCIF */ - { - /* 5 fps */ - { - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, - }, - /* 10 fps */ - { - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, - }, - /* 15 fps */ - { - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, - }, - /* 20 fps */ - { - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, - }, - /* 25 fps */ - { - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, - }, - /* 30 fps */ - { - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, - }, - }, - /* QSIF */ - { - /* 5 fps */ - { - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, - }, - /* 10 fps */ - { - {2, 291, 0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}}, - {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, - {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, - {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, - }, - /* 15 fps */ - { - {3, 437, 0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}}, - {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {1, 191, 420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, - }, - /* 20 fps */ - { - {4, 588, 0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}}, - {3, 447, 730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, - {1, 192, 312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}}, - }, - /* 25 fps */ - { - {5, 703, 0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}}, - {3, 447, 610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, - {1, 192, 262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}}, - }, - /* 30 fps */ - { - {8, 873, 0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}}, - {5, 704, 774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}}, - {3, 448, 492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}}, - {2, 291, 320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}}, - }, - }, - /* QCIF */ - { - /* 5 fps */ - { - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, - }, - /* 10 fps */ - { - {3, 385, 0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}}, - {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {1, 194, 532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}}, - }, - /* 15 fps */ - { - {4, 577, 0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}}, - {3, 447, 818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}}, - {1, 195, 356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}}, - }, - /* 20 fps */ - { - {6, 776, 0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}}, - {4, 591, 804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}}, - {3, 447, 608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 291, 396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}}, - }, - /* 25 fps */ - { - {9, 928, 0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}}, - {5, 703, 800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}}, - {3, 447, 508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, - }, - /* 30 fps */ - { - {0, }, - {9, 956, 876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}}, - {4, 592, 542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}}, - {2, 291, 266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}}, - }, - }, - /* SIF */ - { - /* 5 fps */ - { - {4, 582, 0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}}, - {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}}, - {2, 291, 960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}}, - {1, 191, 630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}}, - }, - /* 10 fps */ - { - {0, }, - {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}}, - {3, 447, 736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}}, - {2, 291, 480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}}, - }, - /* 15 fps */ - { - {0, }, - {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}}, - {4, 591, 650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}}, - {3, 448, 492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}}, - }, - /* 20 fps */ - { - {0, }, - {9, 958, 782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}}, - {5, 703, 574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}}, - {3, 446, 364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}}, - }, - /* 25 fps */ - { - {0, }, - {9, 958, 654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}}, - {6, 776, 530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}}, - {4, 592, 404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}}, - }, - /* 30 fps */ - { - {0, }, - {9, 957, 526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}}, - {6, 775, 426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}}, - {4, 590, 324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}}, - }, - }, - /* CIF */ - { - /* 5 fps */ - { - {6, 771, 0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}}, - {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}}, - {2, 291, 800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}}, - {1, 193, 528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}}, - }, - /* 10 fps */ - { - {0, }, - {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}}, - {4, 591, 812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}}, - {2, 291, 400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}}, - }, - /* 15 fps */ - { - {0, }, - {9, 956, 876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}}, - {5, 703, 644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}}, - {3, 448, 410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}}, - }, - /* 20 fps */ - { - {0, }, - {9, 956, 650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}}, - {6, 776, 528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}}, - {4, 591, 402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}}, - }, - /* 25 fps */ - { - {0, }, - {9, 956, 544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}}, - {7, 840, 478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}}, - {5, 703, 400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}}, - }, - /* 30 fps */ - { - {0, }, - {9, 956, 438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}}, - {7, 838, 384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}}, - {6, 773, 354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}}, - }, - }, - /* VGA */ - { - /* 5 fps */ - { - {0, }, - {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}}, - {4, 592, 976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}}, - {3, 448, 738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}}, - }, - /* 10 fps */ - { - {0, }, - {9, 956, 788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}}, - {6, 776, 640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}}, - {4, 592, 488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}}, - }, - /* 15 fps */ - { - {0, }, - {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}}, - {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}}, - {8, 895, 492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}}, - }, - /* 20 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 25 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 30 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - }, -}; - diff --git a/drivers/usb/media/pwc/pwc-timon.h b/drivers/usb/media/pwc/pwc-timon.h deleted file mode 100644 index a86b3782a081..000000000000 --- a/drivers/usb/media/pwc/pwc-timon.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Linux driver for Philips webcam - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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 -*/ - - - -/* This tables contains entries for the 675/680/690 (Timon) camera, with - 4 different qualities (no compression, low, medium, high). - It lists the bandwidth requirements for said mode by its alternate interface - number. An alternate of 0 means that the mode is unavailable. - - There are 6 * 4 * 4 entries: - 6 different resolutions subqcif, qsif, qcif, sif, cif, vga - 6 framerates: 5, 10, 15, 20, 25, 30 - 4 compression modi: none, low, medium, high - - When an uncompressed mode is not available, the next available compressed mode - will be chosen (unless the decompressor is absent). Sometimes there are only - 1 or 2 compressed modes available; in that case entries are duplicated. -*/ - -#ifndef PWC_TIMON_H -#define PWC_TIMON_H - -#include "pwc-ioctl.h" - -struct Timon_table_entry -{ - char alternate; /* USB alternate interface */ - unsigned short packetsize; /* Normal packet size */ - unsigned short bandlength; /* Bandlength when decompressing */ - unsigned char mode[13]; /* precomputed mode settings for cam */ -}; - -const extern struct Timon_table_entry Timon_table[PSZ_MAX][6][4]; -const extern unsigned int TimonRomTable [16][2][16][8]; - - -#endif - - diff --git a/drivers/usb/media/pwc/pwc-uncompress.c b/drivers/usb/media/pwc/pwc-uncompress.c deleted file mode 100644 index ef4204eab6c4..000000000000 --- a/drivers/usb/media/pwc/pwc-uncompress.c +++ /dev/null @@ -1,146 +0,0 @@ -/* Linux driver for Philips webcam - Decompression frontend. - (C) 1999-2003 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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 "pwc.h" -#include "pwc-uncompress.h" - -int pwc_decompress(struct pwc_device *pdev) -{ - struct pwc_frame_buf *fbuf; - int n, line, col, stride; - void *yuv, *image; - u16 *src; - u16 *dsty, *dstu, *dstv; - - if (pdev == NULL) - return -EFAULT; -#if defined(__KERNEL__) && defined(PWC_MAGIC) - if (pdev->magic != PWC_MAGIC) { - Err("pwc_decompress(): magic failed.\n"); - return -EFAULT; - } -#endif - - fbuf = pdev->read_frame; - if (fbuf == NULL) - return -EFAULT; - image = pdev->image_ptr[pdev->fill_image]; - if (!image) - return -EFAULT; - - yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ - - /* Raw format; that's easy... */ - if (pdev->vpalette == VIDEO_PALETTE_RAW) - { - memcpy(image, yuv, pdev->frame_size); - return 0; - } - - if (pdev->vbandlength == 0) { - /* Uncompressed mode. We copy the data into the output buffer, - using the viewport size (which may be larger than the image - size). Unfortunately we have to do a bit of byte stuffing - to get the desired output format/size. - */ - /* - * We do some byte shuffling here to go from the - * native format to YUV420P. - */ - src = (u16 *)yuv; - n = pdev->view.x * pdev->view.y; - - /* offset in Y plane */ - stride = pdev->view.x * pdev->offset.y + pdev->offset.x; - dsty = (u16 *)(image + stride); - - /* offsets in U/V planes */ - stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; - dstu = (u16 *)(image + n + stride); - dstv = (u16 *)(image + n + n / 4 + stride); - - /* increment after each line */ - stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ - - for (line = 0; line < pdev->image.y; line++) { - for (col = 0; col < pdev->image.x; col += 4) { - *dsty++ = *src++; - *dsty++ = *src++; - if (line & 1) - *dstv++ = *src++; - else - *dstu++ = *src++; - } - dsty += stride; - if (line & 1) - dstv += (stride >> 1); - else - dstu += (stride >> 1); - } - } - else { - /* Compressed; the decompressor routines will write the data - in planar format immediately. - */ - int flags; - - flags = PWCX_FLAG_PLANAR; - if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) - { - printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n"); - flags |= PWCX_FLAG_BAYER; - return -ENXIO; /* No such device or address: missing decompressor */ - } - -#if 0 - switch (pdev->type) - { - case 675: - case 680: - case 690: - case 720: - case 730: - case 740: - case 750: - pwc_dec23_decompress(&pdev->image, &pdev->view, - &pdev->offset, yuv, image, flags, - pdev->decompress_data, pdev->vbandlength); - break; - case 645: - case 646: - /* TODO & FIXME */ - return -ENXIO; /* Missing decompressor */ - break; - } -#endif - } - return 0; -} - - diff --git a/drivers/usb/media/pwc/pwc-uncompress.h b/drivers/usb/media/pwc/pwc-uncompress.h deleted file mode 100644 index d3b9250e4ed3..000000000000 --- a/drivers/usb/media/pwc/pwc-uncompress.h +++ /dev/null @@ -1,41 +0,0 @@ -/* (C) 1999-2003 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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 -*/ - -/* This file is the bridge between the kernel module and the plugin; it - describes the structures and datatypes used in both modules. Any - significant change should be reflected by increasing the - pwc_decompressor_version major number. - */ -#ifndef PWC_UNCOMPRESS_H -#define PWC_UNCOMPRESS_H - -#include - -#include "pwc-ioctl.h" - -/* from pwc-dec.h */ -#define PWCX_FLAG_PLANAR 0x0001 -/* */ - -#endif diff --git a/drivers/usb/media/pwc/pwc.h b/drivers/usb/media/pwc/pwc.h deleted file mode 100644 index 6dd76bb3dff1..000000000000 --- a/drivers/usb/media/pwc/pwc.h +++ /dev/null @@ -1,272 +0,0 @@ -/* (C) 1999-2003 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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 PWC_H -#define PWC_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pwc-uncompress.h" -#include "pwc-ioctl.h" - -/* Defines and structures for the Philips webcam */ -/* Used for checking memory corruption/pointer validation */ -#define PWC_MAGIC 0x89DC10ABUL -#undef PWC_MAGIC - -/* Turn some debugging options on/off */ -#define PWC_DEBUG 0 - -/* Trace certain actions in the driver */ -#define TRACE_MODULE 0x0001 -#define TRACE_PROBE 0x0002 -#define TRACE_OPEN 0x0004 -#define TRACE_READ 0x0008 -#define TRACE_MEMORY 0x0010 -#define TRACE_FLOW 0x0020 -#define TRACE_SIZE 0x0040 -#define TRACE_PWCX 0x0080 -#define TRACE_SEQUENCE 0x1000 - -#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A) -#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A) -#define Info(A...) printk(KERN_INFO PWC_NAME " " A) -#define Err(A...) printk(KERN_ERR PWC_NAME " " A) - - -/* Defines for ToUCam cameras */ -#define TOUCAM_HEADER_SIZE 8 -#define TOUCAM_TRAILER_SIZE 4 - -#define FEATURE_MOTOR_PANTILT 0x0001 - -/* Version block */ -#define PWC_MAJOR 9 -#define PWC_MINOR 0 -#define PWC_VERSION "9.0.2-unofficial" -#define PWC_NAME "pwc" - -/* Turn certain features on/off */ -#define PWC_INT_PIPE 0 - -/* Ignore errors in the first N frames, to allow for startup delays */ -#define FRAME_LOWMARK 5 - -/* Size and number of buffers for the ISO pipe. */ -#define MAX_ISO_BUFS 2 -#define ISO_FRAMES_PER_DESC 10 -#define ISO_MAX_FRAME_SIZE 960 -#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE) - -/* Frame buffers: contains compressed or uncompressed video data. */ -#define MAX_FRAMES 5 -/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */ -#define PWC_FRAME_SIZE (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE) - -/* Absolute maximum number of buffers available for mmap() */ -#define MAX_IMAGES 10 - -/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */ -struct pwc_iso_buf -{ - void *data; - int length; - int read; - struct urb *urb; -}; - -/* intermediate buffers with raw data from the USB cam */ -struct pwc_frame_buf -{ - void *data; - volatile int filled; /* number of bytes filled */ - struct pwc_frame_buf *next; /* list */ -#if PWC_DEBUG - int sequence; /* Sequence number */ -#endif -}; - -struct pwc_device -{ - struct video_device *vdev; -#ifdef PWC_MAGIC - int magic; -#endif - /* Pointer to our usb_device */ - struct usb_device *udev; - - int type; /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */ - int release; /* release number */ - int features; /* feature bits */ - char serial[30]; /* serial number (string) */ - int error_status; /* set when something goes wrong with the cam (unplugged, USB errors) */ - int usb_init; /* set when the cam has been initialized over USB */ - - /*** Video data ***/ - int vopen; /* flag */ - int vendpoint; /* video isoc endpoint */ - int vcinterface; /* video control interface */ - int valternate; /* alternate interface needed */ - int vframes, vsize; /* frames-per-second & size (see PSZ_*) */ - int vpalette; /* palette: 420P, RAW or RGBBAYER */ - int vframe_count; /* received frames */ - int vframes_dumped; /* counter for dumped frames */ - int vframes_error; /* frames received in error */ - int vmax_packet_size; /* USB maxpacket size */ - int vlast_packet_size; /* for frame synchronisation */ - int visoc_errors; /* number of contiguous ISOC errors */ - int vcompression; /* desired compression factor */ - int vbandlength; /* compressed band length; 0 is uncompressed */ - char vsnapshot; /* snapshot mode */ - char vsync; /* used by isoc handler */ - char vmirror; /* for ToUCaM series */ - - int cmd_len; - unsigned char cmd_buf[13]; - - /* The image acquisition requires 3 to 4 steps: - 1. data is gathered in short packets from the USB controller - 2. data is synchronized and packed into a frame buffer - 3a. in case data is compressed, decompress it directly into image buffer - 3b. in case data is uncompressed, copy into image buffer with viewport - 4. data is transferred to the user process - - Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES.... - We have in effect a back-to-back-double-buffer system. - */ - /* 1: isoc */ - struct pwc_iso_buf sbuf[MAX_ISO_BUFS]; - char iso_init; - - /* 2: frame */ - struct pwc_frame_buf *fbuf; /* all frames */ - struct pwc_frame_buf *empty_frames, *empty_frames_tail; /* all empty frames */ - struct pwc_frame_buf *full_frames, *full_frames_tail; /* all filled frames */ - struct pwc_frame_buf *fill_frame; /* frame currently being filled */ - struct pwc_frame_buf *read_frame; /* frame currently read by user process */ - int frame_header_size, frame_trailer_size; - int frame_size; - int frame_total_size; /* including header & trailer */ - int drop_frames; -#if PWC_DEBUG - int sequence; /* Debugging aid */ -#endif - - /* 3: decompression */ - struct pwc_decompressor *decompressor; /* function block with decompression routines */ - void *decompress_data; /* private data for decompression engine */ - - /* 4: image */ - /* We have an 'image' and a 'view', where 'image' is the fixed-size image - as delivered by the camera, and 'view' is the size requested by the - program. The camera image is centered in this viewport, laced with - a gray or black border. view_min <= image <= view <= view_max; - */ - int image_mask; /* bitmask of supported sizes */ - struct pwc_coord view_min, view_max; /* minimum and maximum viewable sizes */ - struct pwc_coord abs_max; /* maximum supported size with compression */ - struct pwc_coord image, view; /* image and viewport size */ - struct pwc_coord offset; /* offset within the viewport */ - - void *image_data; /* total buffer, which is subdivided into ... */ - void *image_ptr[MAX_IMAGES]; /* ...several images... */ - int fill_image; /* ...which are rotated. */ - int len_per_image; /* length per image */ - int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */ - int image_used[MAX_IMAGES]; /* For MCAPTURE and SYNC */ - - struct semaphore modlock; /* to prevent races in video_open(), etc */ - spinlock_t ptrlock; /* for manipulating the buffer pointers */ - - /*** motorized pan/tilt feature */ - struct pwc_mpt_range angle_range; - int pan_angle; /* in degrees * 100 */ - int tilt_angle; /* absolute angle; 0,0 is home position */ - - /*** Misc. data ***/ - wait_queue_head_t frameq; /* When waiting for a frame to finish... */ -#if PWC_INT_PIPE - void *usb_int_handler; /* for the interrupt endpoint */ -#endif -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Global variable */ -extern int pwc_trace; - -/** functions in pwc-if.c */ -int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot); - -/** Functions in pwc-misc.c */ -/* sizes in pixels */ -extern struct pwc_coord pwc_image_sizes[PSZ_MAX]; - -int pwc_decode_size(struct pwc_device *pdev, int width, int height); -void pwc_construct(struct pwc_device *pdev); - -/** Functions in pwc-ctrl.c */ -/* Request a certain video mode. Returns < 0 if not possible */ -extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot); - -/* Various controls; should be obvious. Value 0..65535, or < 0 on error */ -extern int pwc_get_brightness(struct pwc_device *pdev); -extern int pwc_set_brightness(struct pwc_device *pdev, int value); -extern int pwc_get_contrast(struct pwc_device *pdev); -extern int pwc_set_contrast(struct pwc_device *pdev, int value); -extern int pwc_get_gamma(struct pwc_device *pdev); -extern int pwc_set_gamma(struct pwc_device *pdev, int value); -extern int pwc_get_saturation(struct pwc_device *pdev); -extern int pwc_set_saturation(struct pwc_device *pdev, int value); -extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value); -extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor); - -/* Power down or up the camera; not supported by all models */ -extern int pwc_camera_power(struct pwc_device *pdev, int power); - -/* Private ioctl()s; see pwc-ioctl.h */ -extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg); - - -/** pwc-uncompress.c */ -/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */ -extern int pwc_decompress(struct pwc_device *pdev); - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c deleted file mode 100644 index f03ea7f89596..000000000000 --- a/drivers/usb/media/se401.c +++ /dev/null @@ -1,1435 +0,0 @@ -/* - * Endpoints (formerly known as AOX) se401 USB Camera Driver - * - * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) - * - * Still somewhat based on the Linux ov511 driver. - * - * 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. - * - * - * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on - * their chipset available and supporting me while writing this driver. - * - Jeroen Vreeken - */ - -static const char version[] = "0.24"; - -#include -#include -#include -#include -#include -#include -#include -#include "se401.h" - -static int flickerless=0; -static int video_nr = -1; - -static struct usb_device_id device_table [] = { - { USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */ - { USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */ - { USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */ - { USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */ - { USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */ - { } -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -MODULE_AUTHOR("Jeroen Vreeken "); -MODULE_DESCRIPTION("SE401 USB Camera Driver"); -MODULE_LICENSE("GPL"); -module_param(flickerless, int, 0); -MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)"); -module_param(video_nr, int, 0); - -static struct usb_driver se401_driver; - - -/********************************************************************** - * - * Memory management - * - **********************************************************************/ -static void *rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - - - -/**************************************************************************** - * - * se401 register read/write functions - * - ***************************************************************************/ - -static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req, - unsigned short value, unsigned char *cp, int size) -{ - return usb_control_msg ( - se401->dev, - set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0), - req, - (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - 0, - cp, - size, - 1000 - ); -} - -static int se401_set_feature(struct usb_se401 *se401, unsigned short selector, - unsigned short param) -{ - /* specs say that the selector (address) should go in the value field - and the param in index, but in the logs of the windows driver they do - this the other way around... - */ - return usb_control_msg ( - se401->dev, - usb_sndctrlpipe(se401->dev, 0), - SE401_REQ_SET_EXT_FEATURE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - param, - selector, - NULL, - 0, - 1000 - ); -} - -static unsigned short se401_get_feature(struct usb_se401 *se401, - unsigned short selector) -{ - /* For 'set' the selecetor should be in index, not sure if the spec is - wrong here to.... - */ - unsigned char cp[2]; - usb_control_msg ( - se401->dev, - usb_rcvctrlpipe(se401->dev, 0), - SE401_REQ_GET_EXT_FEATURE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, - selector, - cp, - 2, - 1000 - ); - return cp[0]+cp[1]*256; -} - -/**************************************************************************** - * - * Camera control - * - ***************************************************************************/ - - -static int se401_send_pict(struct usb_se401 *se401) -{ - se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */ - se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */ - se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */ - se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */ - se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */ - se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */ - se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */ - - return 0; -} - -static void se401_set_exposure(struct usb_se401 *se401, int brightness) -{ - int integration=brightness<<5; - - if (flickerless==50) { - integration=integration-integration%106667; - } - if (flickerless==60) { - integration=integration-integration%88889; - } - se401->brightness=integration>>5; - se401->expose_h=(integration>>16)&0xff; - se401->expose_m=(integration>>8)&0xff; - se401->expose_l=integration&0xff; -} - -static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p) -{ - p->brightness=se401->brightness; - if (se401->enhance) { - p->whiteness=32768; - } else { - p->whiteness=0; - } - p->colour=65535; - p->contrast=65535; - p->hue=se401->rgain<<10; - p->palette=se401->palette; - p->depth=3; /* rgb24 */ - return 0; -} - - -static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p) -{ - if (p->palette != VIDEO_PALETTE_RGB24) - return 1; - se401->palette=p->palette; - if (p->hue!=se401->hue) { - se401->rgain= p->hue>>10; - se401->bgain= 0x40-(p->hue>>10); - se401->hue=p->hue; - } - if (p->brightness!=se401->brightness) { - se401_set_exposure(se401, p->brightness); - } - if (p->whiteness>=32768) { - se401->enhance=1; - } else { - se401->enhance=0; - } - se401_send_pict(se401); - se401_send_pict(se401); - return 0; -} - -/* - Hyundai have some really nice docs about this and other sensor related - stuff on their homepage: www.hei.co.kr -*/ -static void se401_auto_resetlevel(struct usb_se401 *se401) -{ - unsigned int ahrc, alrc; - int oldreset=se401->resetlevel; - - /* For some reason this normally read-only register doesn't get reset - to zero after reading them just once... - */ - se401_get_feature(se401, HV7131_REG_HIREFNOH); - se401_get_feature(se401, HV7131_REG_HIREFNOL); - se401_get_feature(se401, HV7131_REG_LOREFNOH); - se401_get_feature(se401, HV7131_REG_LOREFNOL); - ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + - se401_get_feature(se401, HV7131_REG_HIREFNOL); - alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) + - se401_get_feature(se401, HV7131_REG_LOREFNOL); - - /* Not an exact science, but it seems to work pretty well... */ - if (alrc > 10) { - while (alrc>=10 && se401->resetlevel < 63) { - se401->resetlevel++; - alrc /=2; - } - } else if (ahrc > 20) { - while (ahrc>=20 && se401->resetlevel > 0) { - se401->resetlevel--; - ahrc /=2; - } - } - if (se401->resetlevel!=oldreset) - se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); - - return; -} - -/* irq handler for snapshot button */ -static void se401_button_irq(struct urb *urb, struct pt_regs *regs) -{ - struct usb_se401 *se401 = urb->context; - int status; - - if (!se401->dev) { - info("ohoh: device vapourished"); - return; - } - - switch (urb->status) { - case 0: - /* success */ - break; - 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; - } - - if (urb->actual_length >=2) { - if (se401->button) - se401->buttonpressed=1; - } -exit: - status = usb_submit_urb (urb, GFP_ATOMIC); - if (status) - err ("%s - usb_submit_urb failed with result %d", - __FUNCTION__, status); -} - -static void se401_video_irq(struct urb *urb, struct pt_regs *regs) -{ - struct usb_se401 *se401 = urb->context; - int length = urb->actual_length; - - /* ohoh... */ - if (!se401->streaming) - return; - - if (!se401->dev) { - info ("ohoh: device vapourished"); - return; - } - - /* 0 sized packets happen if we are to fast, but sometimes the camera - keeps sending them forever... - */ - if (length && !urb->status) { - se401->nullpackets=0; - switch(se401->scratch[se401->scratch_next].state) { - case BUFFER_READY: - case BUFFER_BUSY: { - se401->dropped++; - break; - } - case BUFFER_UNUSED: { - memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length); - se401->scratch[se401->scratch_next].state=BUFFER_READY; - se401->scratch[se401->scratch_next].offset=se401->bayeroffset; - se401->scratch[se401->scratch_next].length=length; - if (waitqueue_active(&se401->wq)) { - wake_up_interruptible(&se401->wq); - } - se401->scratch_overflow=0; - se401->scratch_next++; - if (se401->scratch_next>=SE401_NUMSCRATCH) - se401->scratch_next=0; - break; - } - } - se401->bayeroffset+=length; - if (se401->bayeroffset>=se401->cheight*se401->cwidth) { - se401->bayeroffset=0; - } - } else { - se401->nullpackets++; - if (se401->nullpackets > SE401_MAX_NULLPACKETS) { - if (waitqueue_active(&se401->wq)) { - wake_up_interruptible(&se401->wq); - } - } - } - - /* Resubmit urb for new data */ - urb->status=0; - urb->dev=se401->dev; - if(usb_submit_urb(urb, GFP_KERNEL)) - info("urb burned down"); - return; -} - -static void se401_send_size(struct usb_se401 *se401, int width, int height) -{ - int i=0; - int mode=0x03; /* No compression */ - int sendheight=height; - int sendwidth=width; - - /* JangGu compression can only be used with the camera supported sizes, - but bayer seems to work with any size that fits on the sensor. - We check if we can use compression with the current size with either - 4 or 16 times subcapturing, if not we use uncompressed bayer data - but this will result in cutouts of the maximum size.... - */ - while (isizes && !(se401->width[i]==width && se401->height[i]==height)) - i++; - while (isizes) { - if (se401->width[i]==width*2 && se401->height[i]==height*2) { - sendheight=se401->height[i]; - sendwidth=se401->width[i]; - mode=0x40; - } - if (se401->width[i]==width*4 && se401->height[i]==height*4) { - sendheight=se401->height[i]; - sendwidth=se401->width[i]; - mode=0x42; - } - i++; - } - - se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0); - se401_set_feature(se401, SE401_OPERATINGMODE, mode); - - if (mode==0x03) { - se401->format=FMT_BAYER; - } else { - se401->format=FMT_JANGGU; - } - - return; -} - -/* - In this function se401_send_pict is called several times, - for some reason (depending on the state of the sensor and the phase of - the moon :) doing this only in either place doesn't always work... -*/ -static int se401_start_stream(struct usb_se401 *se401) -{ - struct urb *urb; - int err=0, i; - se401->streaming=1; - - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - - /* Set picture settings */ - se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */ - se401_send_pict(se401); - - se401_send_size(se401, se401->cwidth, se401->cheight); - - se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0); - - /* Do some memory allocation */ - for (i=0; iframe[i].data=se401->fbuf + i * se401->maxframesize; - se401->frame[i].curpix=0; - } - for (i=0; isbuf[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL); - } - - se401->bayeroffset=0; - se401->scratch_next=0; - se401->scratch_use=0; - se401->scratch_overflow=0; - for (i=0; iscratch[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL); - se401->scratch[i].state=BUFFER_UNUSED; - } - - for (i=0; idev, - usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT), - se401->sbuf[i].data, SE401_PACKETSIZE, - se401_video_irq, - se401); - - se401->urb[i]=urb; - - err=usb_submit_urb(se401->urb[i], GFP_KERNEL); - if(err) - err("urb burned down"); - } - - se401->framecount=0; - - return 0; -} - -static int se401_stop_stream(struct usb_se401 *se401) -{ - int i; - - if (!se401->streaming || !se401->dev) - return 1; - - se401->streaming=0; - - se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0); - - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); - - for (i=0; iurb[i]) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i]=NULL; - kfree(se401->sbuf[i].data); - } - for (i=0; iscratch[i].data); - se401->scratch[i].data=NULL; - } - - return 0; -} - -static int se401_set_size(struct usb_se401 *se401, int width, int height) -{ - int wasstreaming=se401->streaming; - /* Check to see if we need to change */ - if (se401->cwidth==width && se401->cheight==height) - return 0; - - /* Check for a valid mode */ - if (!width || !height) - return 1; - if ((width & 1) || (height & 1)) - return 1; - if (width>se401->width[se401->sizes-1]) - return 1; - if (height>se401->height[se401->sizes-1]) - return 1; - - /* Stop a current stream and start it again at the new size */ - if (wasstreaming) - se401_stop_stream(se401); - se401->cwidth=width; - se401->cheight=height; - if (wasstreaming) - se401_start_stream(se401); - return 0; -} - - -/**************************************************************************** - * - * Video Decoding - * - ***************************************************************************/ - -/* - This shouldn't really be done in a v4l driver.... - But it does make the image look a lot more usable. - Basically it lifts the dark pixels more than the light pixels. -*/ -static inline void enhance_picture(unsigned char *frame, int len) -{ - while (len--) { - *frame=(((*frame^255)*(*frame^255))/255)^255; - frame++; - } -} - -static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data) -{ - struct se401_frame *frame=&se401->frame[se401->curframe]; - int linelength=se401->cwidth*3; - - if (frame->curlinepix >= linelength) { - frame->curlinepix=0; - frame->curline+=linelength; - } - - /* First three are absolute, all others relative. - * Format is rgb from right to left (mirrorred image), - * we flip it to get bgr from left to right. */ - if (frame->curlinepix < 3) { - *(frame->curline-frame->curlinepix)=1+data*4; - } else { - *(frame->curline-frame->curlinepix)= - *(frame->curline-frame->curlinepix+3)+data*4; - } - frame->curlinepix++; -} - -static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength) -{ - int pos=0; - int vlc_cod=0; - int vlc_size=0; - int vlc_data=0; - int bit_cur; - int bit; - data+=4; - while (pos < packetlength) { - bit_cur=8; - while (bit_cur && bit_exp) { - bit=((*data)>>(bit_cur-1))&1; - if (!vlc_cod) { - if (bit) { - vlc_size++; - } else { - if (!vlc_size) { - decode_JangGu_integrate(se401, 0); - } else { - vlc_cod=2; - vlc_data=0; - } - } - } else { - if (vlc_cod==2) { - if (!bit) - vlc_data = -(1<data; - int len=buffer->length; - int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size; - int datapos=0; - - /* New image? */ - if (!se401->frame[se401->curframe].curpix) { - se401->frame[se401->curframe].curlinepix=0; - se401->frame[se401->curframe].curline= - se401->frame[se401->curframe].data+ - se401->cwidth*3-1; - if (se401->frame[se401->curframe].grabstate==FRAME_READY) - se401->frame[se401->curframe].grabstate=FRAME_GRABBING; - se401->vlcdatapos=0; - } - while (datapos < len) { - size=1024-se401->vlcdatapos; - if (size+datapos > len) - size=len-datapos; - memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size); - se401->vlcdatapos+=size; - packetlength=0; - if (se401->vlcdatapos >= 4) { - bit_exp=se401->vlcdata[3]+(se401->vlcdata[2]<<8); - pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8); - frameinfo=se401->vlcdata[0]&0xc0; - packetlength=((bit_exp+47)>>4)<<1; - if (packetlength > 1024) { - se401->vlcdatapos=0; - datapos=len; - packetlength=0; - se401->error++; - se401->frame[se401->curframe].curpix=0; - } - } - if (packetlength && se401->vlcdatapos >= packetlength) { - decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength); - se401->frame[se401->curframe].curpix+=pix_exp*3; - datapos+=size-(se401->vlcdatapos-packetlength); - se401->vlcdatapos=0; - if (se401->frame[se401->curframe].curpix>=se401->cwidth*se401->cheight*3) { - if (se401->frame[se401->curframe].curpix==se401->cwidth*se401->cheight*3) { - if (se401->frame[se401->curframe].grabstate==FRAME_GRABBING) { - se401->frame[se401->curframe].grabstate=FRAME_DONE; - se401->framecount++; - se401->readcount++; - } - if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { - se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1); - } - } else { - se401->error++; - } - se401->frame[se401->curframe].curpix=0; - datapos=len; - } - } else { - datapos+=size; - } - } -} - -static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer) -{ - unsigned char *data=buffer->data; - int len=buffer->length; - int offset=buffer->offset; - int datasize=se401->cwidth*se401->cheight; - struct se401_frame *frame=&se401->frame[se401->curframe]; - - unsigned char *framedata=frame->data, *curline, *nextline; - int width=se401->cwidth; - int blineoffset=0, bline; - int linelength=width*3, i; - - - if (frame->curpix==0) { - if (frame->grabstate==FRAME_READY) { - frame->grabstate=FRAME_GRABBING; - } - frame->curline=framedata+linelength; - frame->curlinepix=0; - } - - if (offset!=frame->curpix) { - /* Regard frame as lost :( */ - frame->curpix=0; - se401->error++; - return; - } - - /* Check if we have to much data */ - if (frame->curpix+len > datasize) { - len=datasize-frame->curpix; - } - if (se401->cheight%4) - blineoffset=1; - bline=frame->curpix/se401->cwidth+blineoffset; - - curline=frame->curline; - nextline=curline+linelength; - if (nextline >= framedata+datasize*3) - nextline=curline; - while (len) { - if (frame->curlinepix>=width) { - frame->curlinepix-=width; - bline=frame->curpix/width+blineoffset; - curline+=linelength*2; - nextline+=linelength*2; - if (curline >= framedata+datasize*3) { - frame->curlinepix++; - curline-=3; - nextline-=3; - len--; - data++; - frame->curpix++; - } - if (nextline >= framedata+datasize*3) - nextline=curline; - } - if ((bline&1)) { - if ((frame->curlinepix&1)) { - *(curline+2)=*data; - *(curline-1)=*data; - *(nextline+2)=*data; - *(nextline-1)=*data; - } else { - *(curline+1)= - (*(curline+1)+*data)/2; - *(curline-2)= - (*(curline-2)+*data)/2; - *(nextline+1)=*data; - *(nextline-2)=*data; - } - } else { - if ((frame->curlinepix&1)) { - *(curline+1)= - (*(curline+1)+*data)/2; - *(curline-2)= - (*(curline-2)+*data)/2; - *(nextline+1)=*data; - *(nextline-2)=*data; - } else { - *curline=*data; - *(curline-3)=*data; - *nextline=*data; - *(nextline-3)=*data; - } - } - frame->curlinepix++; - curline-=3; - nextline-=3; - len--; - data++; - frame->curpix++; - } - frame->curline=curline; - - if (frame->curpix>=datasize) { - /* Fix the top line */ - framedata+=linelength; - for (i=0; icheight; i++) { - *framedata=*(framedata+3); - *(framedata+1)=*(framedata+4); - *(framedata+2)=*(framedata+5); - framedata+=linelength; - } - frame->curpix=0; - frame->grabstate=FRAME_DONE; - se401->framecount++; - se401->readcount++; - if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { - se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1); - } - } -} - -static int se401_newframe(struct usb_se401 *se401, int framenr) -{ - DECLARE_WAITQUEUE(wait, current); - int errors=0; - - while (se401->streaming && - (se401->frame[framenr].grabstate==FRAME_READY || - se401->frame[framenr].grabstate==FRAME_GRABBING) ) { - if(!se401->frame[framenr].curpix) { - errors++; - } - wait_interruptible( - se401->scratch[se401->scratch_use].state!=BUFFER_READY, - &se401->wq, - &wait - ); - if (se401->nullpackets > SE401_MAX_NULLPACKETS) { - se401->nullpackets=0; - info("to many null length packets, restarting capture"); - se401_stop_stream(se401); - se401_start_stream(se401); - } else { - if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) { - se401->frame[framenr].grabstate=FRAME_ERROR; - return -EIO; - } - se401->scratch[se401->scratch_use].state=BUFFER_BUSY; - if (se401->format==FMT_JANGGU) { - decode_JangGu(se401, &se401->scratch[se401->scratch_use]); - } else { - decode_bayer(se401, &se401->scratch[se401->scratch_use]); - } - se401->scratch[se401->scratch_use].state=BUFFER_UNUSED; - se401->scratch_use++; - if (se401->scratch_use>=SE401_NUMSCRATCH) - se401->scratch_use=0; - if (errors > SE401_MAX_ERRORS) { - errors=0; - info("to much errors, restarting capture"); - se401_stop_stream(se401); - se401_start_stream(se401); - } - } - } - - if (se401->frame[framenr].grabstate==FRAME_DONE) - if (se401->enhance) - enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3); - return 0; -} - -static void usb_se401_remove_disconnected (struct usb_se401 *se401) -{ - int i; - - se401->dev = NULL; - - for (i=0; iurb[i]) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - kfree(se401->sbuf[i].data); - } - for (i=0; iscratch[i].data); - } - if (se401->inturb) { - usb_kill_urb(se401->inturb); - usb_free_urb(se401->inturb); - } - info("%s disconnected", se401->camera_name); - - /* Free the memory */ - kfree(se401->width); - kfree(se401->height); - kfree(se401); -} - - - -/**************************************************************************** - * - * Video4Linux - * - ***************************************************************************/ - - -static int se401_open(struct inode *inode, struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct usb_se401 *se401 = (struct usb_se401 *)dev; - int err = 0; - - if (se401->user) - return -EBUSY; - se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); - if (se401->fbuf) - file->private_data = dev; - else - err = -ENOMEM; - se401->user = !err; - - return err; -} - -static int se401_close(struct inode *inode, struct file *file) -{ - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - int i; - - rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); - if (se401->removed) { - usb_se401_remove_disconnected(se401); - info("device unregistered"); - } else { - for (i=0; iframe[i].grabstate=FRAME_UNUSED; - if (se401->streaming) - se401_stop_stream(se401); - se401->user=0; - } - file->private_data = NULL; - return 0; -} - -static int se401_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct video_device *vdev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)vdev; - - if (!se401->dev) - return -EIO; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - strcpy(b->name, se401->camera_name); - b->type = VID_TYPE_CAPTURE; - b->channels = 1; - b->audios = 0; - b->maxwidth = se401->width[se401->sizes-1]; - b->maxheight = se401->height[se401->sizes-1]; - b->minwidth = se401->width[0]; - b->minheight = se401->height[0]; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - v->flags = 0; - v->tuners = 0; - v->type = VIDEO_TYPE_CAMERA; - strcpy(v->name, "Camera"); - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture *p = arg; - - se401_get_pict(se401, p); - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *p = arg; - - if (se401_set_pict(se401, p)) - return -EINVAL; - return 0; - } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (se401_set_size(se401, vw->width, vw->height)) - return -EINVAL; - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; - - vw->x = 0; /* FIXME */ - vw->y = 0; - vw->chromakey = 0; - vw->flags = 0; - vw->clipcount = 0; - vw->width = se401->cwidth; - vw->height = se401->cheight; - return 0; - } - case VIDIOCGMBUF: - { - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0, sizeof(*vm)); - vm->size = SE401_NUMFRAMES * se401->maxframesize; - vm->frames = SE401_NUMFRAMES; - for (i=0; ioffsets[i] = se401->maxframesize * i; - return 0; - } - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - - if (vm->format != VIDEO_PALETTE_RGB24) - return -EINVAL; - if (vm->frame >= SE401_NUMFRAMES) - return -EINVAL; - if (se401->frame[vm->frame].grabstate != FRAME_UNUSED) - return -EBUSY; - - /* Is this according to the v4l spec??? */ - if (se401_set_size(se401, vm->width, vm->height)) - return -EINVAL; - se401->frame[vm->frame].grabstate=FRAME_READY; - - if (!se401->streaming) - se401_start_stream(se401); - - /* Set the picture properties */ - if (se401->framecount==0) - se401_send_pict(se401); - /* Calibrate the reset level after a few frames. */ - if (se401->framecount%20==1) - se401_auto_resetlevel(se401); - - return 0; - } - case VIDIOCSYNC: - { - int *frame = arg; - int ret=0; - - if(*frame <0 || *frame >= SE401_NUMFRAMES) - return -EINVAL; - - ret=se401_newframe(se401, *frame); - se401->frame[*frame].grabstate=FRAME_UNUSED; - return ret; - } - case VIDIOCGFBUF: - { - struct video_buffer *vb = arg; - - memset(vb, 0, sizeof(*vb)); - return 0; - } - case VIDIOCKEY: - return 0; - case VIDIOCCAPTURE: - return -EINVAL; - case VIDIOCSFBUF: - return -EINVAL; - case VIDIOCGTUNER: - case VIDIOCSTUNER: - return -EINVAL; - case VIDIOCGFREQ: - case VIDIOCSFREQ: - return -EINVAL; - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; - } /* end switch */ - - return 0; -} - -static int se401_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, se401_do_ioctl); -} - -static ssize_t se401_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - int realcount=count, ret=0; - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - - - if (se401->dev == NULL) - return -EIO; - if (realcount > se401->cwidth*se401->cheight*3) - realcount=se401->cwidth*se401->cheight*3; - - /* Shouldn't happen: */ - if (se401->frame[0].grabstate==FRAME_GRABBING) - return -EBUSY; - se401->frame[0].grabstate=FRAME_READY; - se401->frame[1].grabstate=FRAME_UNUSED; - se401->curframe=0; - - if (!se401->streaming) - se401_start_stream(se401); - - /* Set the picture properties */ - if (se401->framecount==0) - se401_send_pict(se401); - /* Calibrate the reset level after a few frames. */ - if (se401->framecount%20==1) - se401_auto_resetlevel(se401); - - ret=se401_newframe(se401, 0); - - se401->frame[0].grabstate=FRAME_UNUSED; - if (ret) - return ret; - if (copy_to_user(buf, se401->frame[0].data, realcount)) - return -EFAULT; - - return realcount; -} - -static int se401_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; - - mutex_lock(&se401->lock); - - if (se401->dev == NULL) { - mutex_unlock(&se401->lock); - return -EIO; - } - if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { - mutex_unlock(&se401->lock); - return -EINVAL; - } - pos = (unsigned long)se401->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - mutex_unlock(&se401->lock); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - mutex_unlock(&se401->lock); - - return 0; -} - -static struct file_operations se401_fops = { - .owner = THIS_MODULE, - .open = se401_open, - .release = se401_close, - .read = se401_read, - .mmap = se401_mmap, - .ioctl = se401_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, -}; -static struct video_device se401_template = { - .owner = THIS_MODULE, - .name = "se401 USB camera", - .type = VID_TYPE_CAPTURE, - .hardware = VID_HARDWARE_SE401, - .fops = &se401_fops, -}; - - - -/***************************/ -static int se401_init(struct usb_se401 *se401, int button) -{ - int i=0, rc; - unsigned char cp[0x40]; - char temp[200]; - - /* led on */ - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - - /* get camera descriptor */ - rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp)); - if (cp[1]!=0x41) { - err("Wrong descriptor type"); - return 1; - } - sprintf (temp, "ExtraFeatures: %d", cp[3]); - - se401->sizes=cp[4]+cp[5]*256; - se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); - if (!se401->width) - return 1; - se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); - if (!se401->height) { - kfree(se401->width); - return 1; - } - for (i=0; isizes; i++) { - se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256; - se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256; - } - sprintf (temp, "%s Sizes:", temp); - for (i=0; isizes; i++) { - sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]); - } - info("%s", temp); - se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; - - rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); - se401->cwidth=cp[0]+cp[1]*256; - rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp)); - se401->cheight=cp[0]+cp[1]*256; - - if (!cp[2] && SE401_FORMAT_BAYER) { - err("Bayer format not supported!"); - return 1; - } - /* set output mode (BAYER) */ - se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0); - - rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); - se401->brightness=cp[0]+cp[1]*256; - /* some default values */ - se401->resetlevel=0x2d; - se401->rgain=0x20; - se401->ggain=0x20; - se401->bgain=0x20; - se401_set_exposure(se401, 20000); - se401->palette=VIDEO_PALETTE_RGB24; - se401->enhance=1; - se401->dropped=0; - se401->error=0; - se401->framecount=0; - se401->readcount=0; - - /* Start interrupt transfers for snapshot button */ - if (button) { - se401->inturb=usb_alloc_urb(0, GFP_KERNEL); - if (!se401->inturb) { - info("Allocation of inturb failed"); - return 1; - } - usb_fill_int_urb(se401->inturb, se401->dev, - usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT), - &se401->button, sizeof(se401->button), - se401_button_irq, - se401, - 8 - ); - if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { - info("int urb burned down"); - return 1; - } - } else - se401->inturb=NULL; - - /* Flash the led */ - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); - - return 0; -} - -static int se401_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_interface_descriptor *interface; - struct usb_se401 *se401; - char *camera_name=NULL; - int button=1; - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - interface = &intf->cur_altsetting->desc; - - /* Is it an se401? */ - if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 && - le16_to_cpu(dev->descriptor.idProduct) == 0x0004) { - camera_name="Endpoints/Aox SE401"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 && - le16_to_cpu(dev->descriptor.idProduct) == 0x030b) { - camera_name="Philips PCVC665K"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5001) { - camera_name="Kensington VideoCAM 67014"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5002) { - camera_name="Kensington VideoCAM 6701(5/7)"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5003) { - camera_name="Kensington VideoCAM 67016"; - button=0; - } else - return -ENODEV; - - /* Checking vendor/product should be enough, but what the hell */ - if (interface->bInterfaceClass != 0x00) - return -ENODEV; - if (interface->bInterfaceSubClass != 0x00) - return -ENODEV; - - /* We found one */ - info("SE401 camera found: %s", camera_name); - - if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { - err("couldn't kmalloc se401 struct"); - return -ENOMEM; - } - - se401->dev = dev; - se401->iface = interface->bInterfaceNumber; - se401->camera_name = camera_name; - - info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255); - - if (se401_init(se401, button)) { - kfree(se401); - return -EIO; - } - - memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); - memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name)); - init_waitqueue_head(&se401->wq); - mutex_init(&se401->lock); - wmb(); - - if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { - kfree(se401); - err("video_register_device failed"); - return -EIO; - } - info("registered new video device: video%d", se401->vdev.minor); - - usb_set_intfdata (intf, se401); - return 0; -} - -static void se401_disconnect(struct usb_interface *intf) -{ - struct usb_se401 *se401 = usb_get_intfdata (intf); - - usb_set_intfdata (intf, NULL); - if (se401) { - video_unregister_device(&se401->vdev); - if (!se401->user){ - usb_se401_remove_disconnected(se401); - } else { - se401->frame[0].grabstate = FRAME_ERROR; - se401->frame[0].grabstate = FRAME_ERROR; - - se401->streaming = 0; - - wake_up_interruptible(&se401->wq); - se401->removed = 1; - } - } -} - -static struct usb_driver se401_driver = { - .name = "se401", - .id_table = device_table, - .probe = se401_probe, - .disconnect = se401_disconnect, -}; - - - -/**************************************************************************** - * - * Module routines - * - ***************************************************************************/ - -static int __init usb_se401_init(void) -{ - info("SE401 usb camera driver version %s registering", version); - if (flickerless) - if (flickerless!=50 && flickerless!=60) { - info("Invallid flickerless value, use 0, 50 or 60."); - return -1; - } - return usb_register(&se401_driver); -} - -static void __exit usb_se401_exit(void) -{ - usb_deregister(&se401_driver); - info("SE401 driver deregistered"); -} - -module_init(usb_se401_init); -module_exit(usb_se401_exit); diff --git a/drivers/usb/media/se401.h b/drivers/usb/media/se401.h deleted file mode 100644 index e88a40d4c86a..000000000000 --- a/drivers/usb/media/se401.h +++ /dev/null @@ -1,234 +0,0 @@ - -#ifndef __LINUX_se401_H -#define __LINUX_se401_H - -#include -#include -#include -#include - -#define se401_DEBUG /* Turn on debug messages */ - -#ifdef se401_DEBUG -# define PDEBUG(level, fmt, args...) \ -if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) -#else -# define PDEBUG(level, fmt, args...) do {} while(0) -#endif - -/* An almost drop-in replacement for sleep_on_interruptible */ -#define wait_interruptible(test, queue, wait) \ -{ \ - add_wait_queue(queue, wait); \ - set_current_state(TASK_INTERRUPTIBLE); \ - if (test) \ - schedule(); \ - remove_wait_queue(queue, wait); \ - set_current_state(TASK_RUNNING); \ - if (signal_pending(current)) \ - break; \ -} - -#define SE401_REQ_GET_CAMERA_DESCRIPTOR 0x06 -#define SE401_REQ_START_CONTINUOUS_CAPTURE 0x41 -#define SE401_REQ_STOP_CONTINUOUS_CAPTURE 0x42 -#define SE401_REQ_CAPTURE_FRAME 0x43 -#define SE401_REQ_GET_BRT 0x44 -#define SE401_REQ_SET_BRT 0x45 -#define SE401_REQ_GET_WIDTH 0x4c -#define SE401_REQ_SET_WIDTH 0x4d -#define SE401_REQ_GET_HEIGHT 0x4e -#define SE401_REQ_SET_HEIGHT 0x4f -#define SE401_REQ_GET_OUTPUT_MODE 0x50 -#define SE401_REQ_SET_OUTPUT_MODE 0x51 -#define SE401_REQ_GET_EXT_FEATURE 0x52 -#define SE401_REQ_SET_EXT_FEATURE 0x53 -#define SE401_REQ_CAMERA_POWER 0x56 -#define SE401_REQ_LED_CONTROL 0x57 -#define SE401_REQ_BIOS 0xff - -#define SE401_BIOS_READ 0x07 - -#define SE401_FORMAT_BAYER 0x40 - -/* Hyundai hv7131b registers - 7121 and 7141 should be the same (haven't really checked...) */ -/* Mode registers: */ -#define HV7131_REG_MODE_A 0x00 -#define HV7131_REG_MODE_B 0x01 -#define HV7131_REG_MODE_C 0x02 -/* Frame registers: */ -#define HV7131_REG_FRSU 0x10 -#define HV7131_REG_FRSL 0x11 -#define HV7131_REG_FCSU 0x12 -#define HV7131_REG_FCSL 0x13 -#define HV7131_REG_FWHU 0x14 -#define HV7131_REG_FWHL 0x15 -#define HV7131_REG_FWWU 0x16 -#define HV7131_REG_FWWL 0x17 -/* Timing registers: */ -#define HV7131_REG_THBU 0x20 -#define HV7131_REG_THBL 0x21 -#define HV7131_REG_TVBU 0x22 -#define HV7131_REG_TVBL 0x23 -#define HV7131_REG_TITU 0x25 -#define HV7131_REG_TITM 0x26 -#define HV7131_REG_TITL 0x27 -#define HV7131_REG_TMCD 0x28 -/* Adjust Registers: */ -#define HV7131_REG_ARLV 0x30 -#define HV7131_REG_ARCG 0x31 -#define HV7131_REG_AGCG 0x32 -#define HV7131_REG_ABCG 0x33 -#define HV7131_REG_APBV 0x34 -#define HV7131_REG_ASLP 0x54 -/* Offset Registers: */ -#define HV7131_REG_OFSR 0x50 -#define HV7131_REG_OFSG 0x51 -#define HV7131_REG_OFSB 0x52 -/* REset level statistics registers: */ -#define HV7131_REG_LOREFNOH 0x57 -#define HV7131_REG_LOREFNOL 0x58 -#define HV7131_REG_HIREFNOH 0x59 -#define HV7131_REG_HIREFNOL 0x5a - -/* se401 registers */ -#define SE401_OPERATINGMODE 0x2000 - - -/* size of usb transfers */ -#define SE401_PACKETSIZE 4096 -/* number of queued bulk transfers to use, should be about 8 */ -#define SE401_NUMSBUF 1 -/* read the usb specs for this one :) */ -#define SE401_VIDEO_ENDPOINT 1 -#define SE401_BUTTON_ENDPOINT 2 -/* number of frames supported by the v4l part */ -#define SE401_NUMFRAMES 2 -/* scratch buffers for passing data to the decoders */ -#define SE401_NUMSCRATCH 32 -/* maximum amount of data in a JangGu packet */ -#define SE401_VLCDATALEN 1024 -/* number of nul sized packets to receive before kicking the camera */ -#define SE401_MAX_NULLPACKETS 4000 -/* number of decoding errors before kicking the camera */ -#define SE401_MAX_ERRORS 200 - -struct usb_device; - -struct se401_sbuf { - unsigned char *data; -}; - -enum { - FRAME_UNUSED, /* Unused (no MCAPTURE) */ - FRAME_READY, /* Ready to start grabbing */ - FRAME_GRABBING, /* In the process of being grabbed into */ - FRAME_DONE, /* Finished grabbing, but not been synced yet */ - FRAME_ERROR, /* Something bad happened while processing */ -}; - -enum { - FMT_BAYER, - FMT_JANGGU, -}; - -enum { - BUFFER_UNUSED, - BUFFER_READY, - BUFFER_BUSY, - BUFFER_DONE, -}; - -struct se401_scratch { - unsigned char *data; - volatile int state; - int offset; - int length; -}; - -struct se401_frame { - unsigned char *data; /* Frame buffer */ - - volatile int grabstate; /* State of grabbing */ - - unsigned char *curline; - int curlinepix; - int curpix; -}; - -struct usb_se401 { - struct video_device vdev; - - /* Device structure */ - struct usb_device *dev; - - unsigned char iface; - - char *camera_name; - - int change; - int brightness; - int hue; - int rgain; - int ggain; - int bgain; - int expose_h; - int expose_m; - int expose_l; - int resetlevel; - - int enhance; - - int format; - int sizes; - int *width; - int *height; - int cwidth; /* current width */ - int cheight; /* current height */ - int palette; - int maxframesize; - int cframesize; /* current framesize */ - - struct mutex lock; - int user; /* user count for exclusive use */ - int removed; /* device disconnected */ - - int streaming; /* Are we streaming video? */ - - char *fbuf; /* Videodev buffer area */ - - struct urb *urb[SE401_NUMSBUF]; - struct urb *inturb; - - int button; - int buttonpressed; - - int curframe; /* Current receiving frame */ - struct se401_frame frame[SE401_NUMFRAMES]; - int readcount; - int framecount; - int error; - int dropped; - - int scratch_next; - int scratch_use; - int scratch_overflow; - struct se401_scratch scratch[SE401_NUMSCRATCH]; - - /* Decoder specific data: */ - unsigned char vlcdata[SE401_VLCDATALEN]; - int vlcdatapos; - int bayeroffset; - - struct se401_sbuf sbuf[SE401_NUMSBUF]; - - wait_queue_head_t wq; /* Processes waiting */ - - int nullpackets; -}; - - - -#endif - diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h deleted file mode 100644 index 1d70a62b9f23..000000000000 --- a/drivers/usb/media/sn9c102.h +++ /dev/null @@ -1,218 +0,0 @@ -/*************************************************************************** - * V4L2 driver for SN9C10x PC Camera Controllers * - * * - * Copyright (C) 2004-2006 by Luca Risolia * - * * - * 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. * - ***************************************************************************/ - -#ifndef _SN9C102_H_ -#define _SN9C102_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sn9c102_sensor.h" - -/*****************************************************************************/ - -#define SN9C102_DEBUG -#define SN9C102_DEBUG_LEVEL 2 -#define SN9C102_MAX_DEVICES 64 -#define SN9C102_PRESERVE_IMGSCALE 0 -#define SN9C102_FORCE_MUNMAP 0 -#define SN9C102_MAX_FRAMES 32 -#define SN9C102_URBS 2 -#define SN9C102_ISO_PACKETS 7 -#define SN9C102_ALTERNATE_SETTING 8 -#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS) -#define SN9C102_CTRL_TIMEOUT 300 -#define SN9C102_FRAME_TIMEOUT 2 - -/*****************************************************************************/ - -enum sn9c102_bridge { - BRIDGE_SN9C101 = 0x01, - BRIDGE_SN9C102 = 0x02, - BRIDGE_SN9C103 = 0x04, -}; - -SN9C102_ID_TABLE -SN9C102_SENSOR_TABLE - -enum sn9c102_frame_state { - F_UNUSED, - F_QUEUED, - F_GRABBING, - F_DONE, - F_ERROR, -}; - -struct sn9c102_frame_t { - void* bufmem; - struct v4l2_buffer buf; - enum sn9c102_frame_state state; - struct list_head frame; - unsigned long vma_use_count; -}; - -enum sn9c102_dev_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04, -}; - -enum sn9c102_io_method { - IO_NONE, - IO_READ, - IO_MMAP, -}; - -enum sn9c102_stream_state { - STREAM_OFF, - STREAM_INTERRUPT, - STREAM_ON, -}; - -typedef char sn9c103_sof_header_t[18]; -typedef char sn9c102_sof_header_t[12]; -typedef char sn9c102_eof_header_t[4]; - -struct sn9c102_sysfs_attr { - u8 reg, i2c_reg; - sn9c103_sof_header_t frame_header; -}; - -struct sn9c102_module_param { - u8 force_munmap; - u16 frame_timeout; -}; - -static DEFINE_MUTEX(sn9c102_sysfs_lock); -static DECLARE_RWSEM(sn9c102_disconnect); - -struct sn9c102_device { - struct video_device* v4ldev; - - enum sn9c102_bridge bridge; - struct sn9c102_sensor sensor; - - struct usb_device* usbdev; - struct urb* urb[SN9C102_URBS]; - void* transfer_buffer[SN9C102_URBS]; - u8* control_buffer; - - struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES]; - struct list_head inqueue, outqueue; - u32 frame_count, nbuffers, nreadbuffers; - - enum sn9c102_io_method io; - enum sn9c102_stream_state stream; - - struct v4l2_jpegcompression compression; - - struct sn9c102_sysfs_attr sysfs; - sn9c103_sof_header_t sof_header; - u16 reg[63]; - - struct sn9c102_module_param module_param; - - enum sn9c102_dev_state state; - u8 users; - - struct mutex dev_mutex, fileop_mutex; - spinlock_t queue_lock; - wait_queue_head_t open, wait_frame, wait_stream; -}; - -/*****************************************************************************/ - -struct sn9c102_device* -sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) -{ - if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) - return cam; - - return NULL; -} - - -void -sn9c102_attach_sensor(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) -{ - memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); -} - -/*****************************************************************************/ - -#undef DBG -#undef KDBG -#ifdef SN9C102_DEBUG -# define DBG(level, fmt, args...) \ -do { \ - if (debug >= (level)) { \ - if ((level) == 1) \ - dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ - else if ((level) == 2) \ - dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ - else if ((level) >= 3) \ - dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ - } \ -} while (0) -# define V4LDBG(level, name, cmd) \ -do { \ - if (debug >= (level)) \ - v4l_print_ioctl(name, cmd); \ -} while (0) -# define KDBG(level, fmt, args...) \ -do { \ - if (debug >= (level)) { \ - if ((level) == 1 || (level) == 2) \ - pr_info("sn9c102: " fmt "\n", ## args); \ - else if ((level) == 3) \ - pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ - } \ -} while (0) -#else -# define DBG(level, fmt, args...) do {;} while(0) -# define V4LDBG(level, name, cmd) do {;} while(0) -# define KDBG(level, fmt, args...) do {;} while(0) -#endif - -#undef PDBG -#define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) - -#undef PDBGG -#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ - -#endif /* _SN9C102_H_ */ diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c deleted file mode 100644 index 4c6cc6395723..000000000000 --- a/drivers/usb/media/sn9c102_core.c +++ /dev/null @@ -1,2919 +0,0 @@ -/*************************************************************************** - * V4L2 driver for SN9C10x PC Camera Controllers * - * * - * Copyright (C) 2004-2006 by Luca Risolia * - * * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sn9c102.h" - -/*****************************************************************************/ - -#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers" -#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" -#define SN9C102_AUTHOR_EMAIL "" -#define SN9C102_MODULE_LICENSE "GPL" -#define SN9C102_MODULE_VERSION "1:1.27" -#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 27) - -/*****************************************************************************/ - -MODULE_DEVICE_TABLE(usb, sn9c102_id_table); - -MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL); -MODULE_DESCRIPTION(SN9C102_MODULE_NAME); -MODULE_VERSION(SN9C102_MODULE_VERSION); -MODULE_LICENSE(SN9C102_MODULE_LICENSE); - -static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1}; -module_param_array(video_nr, short, NULL, 0444); -MODULE_PARM_DESC(video_nr, - "\n<-1|n[,...]> Specify V4L2 minor mode number." - "\n -1 = use next available (default)" - "\n n = use minor number n (integer >= 0)" - "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES) - " cameras this way." - "\nFor example:" - "\nvideo_nr=-1,2,-1 would assign minor number 2 to" - "\nthe second camera and use auto for the first" - "\none and for every other camera." - "\n"); - -static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] = - SN9C102_FORCE_MUNMAP}; -module_param_array(force_munmap, bool, NULL, 0444); -MODULE_PARM_DESC(force_munmap, - "\n<0|1[,...]> Force the application to unmap previously" - "\nmapped buffer memory before calling any VIDIOC_S_CROP or" - "\nVIDIOC_S_FMT ioctl's. Not all the applications support" - "\nthis feature. This parameter is specific for each" - "\ndetected camera." - "\n 0 = do not force memory unmapping" - "\n 1 = force memory unmapping (save memory)" - "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." - "\n"); - -static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = - SN9C102_FRAME_TIMEOUT}; -module_param_array(frame_timeout, uint, NULL, 0644); -MODULE_PARM_DESC(frame_timeout, - "\n Timeout for a video frame in seconds." - "\nThis parameter is specific for each detected camera." - "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." - "\n"); - -#ifdef SN9C102_DEBUG -static unsigned short debug = SN9C102_DEBUG_LEVEL; -module_param(debug, ushort, 0644); -MODULE_PARM_DESC(debug, - "\n Debugging information level, from 0 to 3:" - "\n0 = none (use carefully)" - "\n1 = critical errors" - "\n2 = significant informations" - "\n3 = more verbose messages" - "\nLevel 3 is useful for testing only, when only " - "one device is used." - "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"." - "\n"); -#endif - -/*****************************************************************************/ - -static sn9c102_sof_header_t sn9c102_sof_header[] = { - {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00}, - {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01}, -}; - -static sn9c103_sof_header_t sn9c103_sof_header[] = { - {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x20}, -}; - -static sn9c102_eof_header_t sn9c102_eof_header[] = { - {0x00, 0x00, 0x00, 0x00}, - {0x40, 0x00, 0x00, 0x00}, - {0x80, 0x00, 0x00, 0x00}, - {0xc0, 0x00, 0x00, 0x00}, -}; - -/*****************************************************************************/ - -static u32 -sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, - enum sn9c102_io_method io) -{ - struct v4l2_pix_format* p = &(cam->sensor.pix_format); - struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); - const size_t imagesize = cam->module_param.force_munmap || - io == IO_READ ? - (p->width * p->height * p->priv) / 8 : - (r->width * r->height * p->priv) / 8; - void* buff = NULL; - u32 i; - - if (count > SN9C102_MAX_FRAMES) - count = SN9C102_MAX_FRAMES; - - cam->nbuffers = count; - while (cam->nbuffers > 0) { - if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) - break; - cam->nbuffers--; - } - - for (i = 0; i < cam->nbuffers; i++) { - cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); - cam->frame[i].buf.index = i; - cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); - cam->frame[i].buf.length = imagesize; - cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cam->frame[i].buf.sequence = 0; - cam->frame[i].buf.field = V4L2_FIELD_NONE; - cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; - cam->frame[i].buf.flags = 0; - } - - return cam->nbuffers; -} - - -static void sn9c102_release_buffers(struct sn9c102_device* cam) -{ - if (cam->nbuffers) { - vfree(cam->frame[0].bufmem); - cam->nbuffers = 0; - } - cam->frame_current = NULL; -} - - -static void sn9c102_empty_framequeues(struct sn9c102_device* cam) -{ - u32 i; - - INIT_LIST_HEAD(&cam->inqueue); - INIT_LIST_HEAD(&cam->outqueue); - - for (i = 0; i < SN9C102_MAX_FRAMES; i++) { - cam->frame[i].state = F_UNUSED; - cam->frame[i].buf.bytesused = 0; - } -} - - -static void sn9c102_requeue_outqueue(struct sn9c102_device* cam) -{ - struct sn9c102_frame_t *i; - - list_for_each_entry(i, &cam->outqueue, frame) { - i->state = F_QUEUED; - list_add(&i->frame, &cam->inqueue); - } - - INIT_LIST_HEAD(&cam->outqueue); -} - - -static void sn9c102_queue_unusedframes(struct sn9c102_device* cam) -{ - unsigned long lock_flags; - u32 i; - - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].state == F_UNUSED) { - cam->frame[i].state = F_QUEUED; - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_add_tail(&cam->frame[i].frame, &cam->inqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - } -} - -/*****************************************************************************/ - -int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index) -{ - struct usb_device* udev = cam->usbdev; - int i, res; - - if (index + sizeof(buff) >= ARRAY_SIZE(cam->reg)) - return -1; - - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - index, 0, buff, sizeof(buff), - SN9C102_CTRL_TIMEOUT*sizeof(buff)); - if (res < 0) { - DBG(3, "Failed to write registers (index 0x%02X, error %d)", - index, res); - return -1; - } - - for (i = 0; i < sizeof(buff); i++) - cam->reg[index+i] = buff[i]; - - return 0; -} - - -int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index) -{ - struct usb_device* udev = cam->usbdev; - u8* buff = cam->control_buffer; - int res; - - if (index >= ARRAY_SIZE(cam->reg)) - return -1; - - *buff = value; - - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); - if (res < 0) { - DBG(3, "Failed to write a register (value 0x%02X, index " - "0x%02X, error %d)", value, index, res); - return -1; - } - - cam->reg[index] = value; - - return 0; -} - - -/* NOTE: reading some registers always returns 0 */ -static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index) -{ - struct usb_device* udev = cam->usbdev; - u8* buff = cam->control_buffer; - int res; - - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); - if (res < 0) - DBG(3, "Failed to read a register (index 0x%02X, error %d)", - index, res); - - return (res >= 0) ? (int)(*buff) : -1; -} - - -int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index) -{ - if (index >= ARRAY_SIZE(cam->reg)) - return -1; - - return cam->reg[index]; -} - - -static int -sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor) -{ - int i, r; - - for (i = 1; i <= 5; i++) { - r = sn9c102_read_reg(cam, 0x08); - if (r < 0) - return -EIO; - if (r & 0x04) - return 0; - if (sensor->frequency & SN9C102_I2C_400KHZ) - udelay(5*16); - else - udelay(16*16); - } - return -EBUSY; -} - - -static int -sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) -{ - int r; - r = sn9c102_read_reg(cam, 0x08); - return (r < 0 || (r >= 0 && !(r & 0x08))) ? -EIO : 0; -} - - -static int -sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) -{ - int r; - r = sn9c102_read_reg(cam, 0x08); - return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0; -} - - -int -sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 data0, u8 data1, - u8 n, u8 buffer[]) -{ - struct usb_device* udev = cam->usbdev; - u8* data = cam->control_buffer; - int err = 0, res; - - /* Write cycle */ - data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10; - data[1] = data0; /* I2C slave id */ - data[2] = data1; /* address */ - data[7] = 0x10; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_wait(cam, sensor); - - /* Read cycle - n bytes */ - data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | - (n << 4) | 0x02; - data[1] = data0; - data[7] = 0x10; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_wait(cam, sensor); - - /* The first read byte will be placed in data[4] */ - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_detect_read_error(cam, sensor); - - PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1, - data[4]); - - if (err) { - DBG(3, "I2C read failed for %s image sensor", sensor->name); - return -1; - } - - if (buffer) - memcpy(buffer, data, sizeof(buffer)); - - return (int)data[4]; -} - - -int -sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 n, u8 data0, - u8 data1, u8 data2, u8 data3, u8 data4, u8 data5) -{ - struct usb_device* udev = cam->usbdev; - u8* data = cam->control_buffer; - int err = 0, res; - - /* Write cycle. It usually is address + value */ - data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) - | ((n - 1) << 4); - data[1] = data0; - data[2] = data1; - data[3] = data2; - data[4] = data3; - data[5] = data4; - data[6] = data5; - data[7] = 0x14; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_wait(cam, sensor); - err += sn9c102_i2c_detect_write_error(cam, sensor); - - if (err) - DBG(3, "I2C write failed for %s image sensor", sensor->name); - - PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, " - "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X", - n, data0, data1, data2, data3, data4, data5); - - return err ? -1 : 0; -} - - -int -sn9c102_i2c_try_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 address) -{ - return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id, - address, 1, NULL); -} - - -int -sn9c102_i2c_try_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 address, u8 value) -{ - return sn9c102_i2c_try_raw_write(cam, sensor, 3, - sensor->i2c_slave_id, address, - value, 0, 0, 0); -} - - -int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address) -{ - return sn9c102_i2c_try_read(cam, &cam->sensor, address); -} - - -int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value) -{ - return sn9c102_i2c_try_write(cam, &cam->sensor, address, value); -} - -/*****************************************************************************/ - -static void* -sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) -{ - size_t soflen = 0, i; - u8 j, n = 0; - - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - soflen = sizeof(sn9c102_sof_header_t); - n = sizeof(sn9c102_sof_header) / soflen; - break; - case BRIDGE_SN9C103: - soflen = sizeof(sn9c103_sof_header_t); - n = sizeof(sn9c103_sof_header) / soflen; - } - - for (i = 0; (len >= soflen) && (i <= len - soflen); i++) - for (j = 0; j < n; j++) - /* The invariable part of the header is 6 bytes long */ - if ((cam->bridge != BRIDGE_SN9C103 && - !memcmp(mem + i, sn9c102_sof_header[j], 6)) || - (cam->bridge == BRIDGE_SN9C103 && - !memcmp(mem + i, sn9c103_sof_header[j], 6))) { - memcpy(cam->sof_header, mem + i, soflen); - /* Skip the header */ - return mem + i + soflen; - } - - return NULL; -} - - -static void* -sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) -{ - size_t eoflen = sizeof(sn9c102_eof_header_t), i; - unsigned j, n = sizeof(sn9c102_eof_header) / eoflen; - - if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) - return NULL; /* EOF header does not exist in compressed data */ - - for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++) - for (j = 0; j < n; j++) - if (!memcmp(mem + i, sn9c102_eof_header[j], eoflen)) - return mem + i; - - return NULL; -} - - -static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) -{ - struct sn9c102_device* cam = urb->context; - struct sn9c102_frame_t** f; - size_t imagesize, soflen; - u8 i; - int err = 0; - - if (urb->status == -ENOENT) - return; - - f = &cam->frame_current; - - if (cam->stream == STREAM_INTERRUPT) { - cam->stream = STREAM_OFF; - if ((*f)) - (*f)->state = F_QUEUED; - DBG(3, "Stream interrupted"); - wake_up(&cam->wait_stream); - } - - if (cam->state & DEV_DISCONNECTED) - return; - - if (cam->state & DEV_MISCONFIGURED) { - wake_up_interruptible(&cam->wait_frame); - return; - } - - if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) - goto resubmit_urb; - - if (!(*f)) - (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t, - frame); - - imagesize = (cam->sensor.pix_format.width * - cam->sensor.pix_format.height * - cam->sensor.pix_format.priv) / 8; - - soflen = (cam->bridge) == BRIDGE_SN9C103 ? - sizeof(sn9c103_sof_header_t) : - sizeof(sn9c102_sof_header_t); - - for (i = 0; i < urb->number_of_packets; i++) { - unsigned int img, len, status; - void *pos, *sof, *eof; - - len = urb->iso_frame_desc[i].actual_length; - status = urb->iso_frame_desc[i].status; - pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; - - if (status) { - DBG(3, "Error in isochronous frame"); - (*f)->state = F_ERROR; - continue; - } - - PDBGG("Isochrnous frame: length %u, #%u i", len, i); - -redo: - sof = sn9c102_find_sof_header(cam, pos, len); - if (likely(!sof)) { - eof = sn9c102_find_eof_header(cam, pos, len); - if ((*f)->state == F_GRABBING) { -end_of_frame: - img = len; - - if (eof) - img = (eof > pos) ? eof - pos - 1 : 0; - - if ((*f)->buf.bytesused+img > imagesize) { - u32 b; - b = (*f)->buf.bytesused + img - - imagesize; - img = imagesize - (*f)->buf.bytesused; - DBG(3, "Expected EOF not found: " - "video frame cut"); - if (eof) - DBG(3, "Exceeded limit: +%u " - "bytes", (unsigned)(b)); - } - - memcpy((*f)->bufmem + (*f)->buf.bytesused, pos, - img); - - if ((*f)->buf.bytesused == 0) - do_gettimeofday(&(*f)->buf.timestamp); - - (*f)->buf.bytesused += img; - - if ((*f)->buf.bytesused == imagesize || - (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_SN9C10X && eof)) { - u32 b; - b = (*f)->buf.bytesused; - (*f)->state = F_DONE; - (*f)->buf.sequence= ++cam->frame_count; - spin_lock(&cam->queue_lock); - list_move_tail(&(*f)->frame, - &cam->outqueue); - if (!list_empty(&cam->inqueue)) - (*f) = list_entry( - cam->inqueue.next, - struct sn9c102_frame_t, - frame ); - else - (*f) = NULL; - spin_unlock(&cam->queue_lock); - memcpy(cam->sysfs.frame_header, - cam->sof_header, soflen); - DBG(3, "Video frame captured: %lu " - "bytes", (unsigned long)(b)); - - if (!(*f)) - goto resubmit_urb; - - } else if (eof) { - (*f)->state = F_ERROR; - DBG(3, "Not expected EOF after %lu " - "bytes of image data", - (unsigned long) - ((*f)->buf.bytesused)); - } - - if (sof) /* (1) */ - goto start_of_frame; - - } else if (eof) { - DBG(3, "EOF without SOF"); - continue; - - } else { - PDBGG("Ignoring pointless isochronous frame"); - continue; - } - - } else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) { -start_of_frame: - (*f)->state = F_GRABBING; - (*f)->buf.bytesused = 0; - len -= (sof - pos); - pos = sof; - DBG(3, "SOF detected: new video frame"); - if (len) - goto redo; - - } else if ((*f)->state == F_GRABBING) { - eof = sn9c102_find_eof_header(cam, pos, len); - if (eof && eof < sof) - goto end_of_frame; /* (1) */ - else { - if (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_SN9C10X) { - eof = sof - soflen; - goto end_of_frame; - } else { - DBG(3, "SOF before expected EOF after " - "%lu bytes of image data", - (unsigned long) - ((*f)->buf.bytesused)); - goto start_of_frame; - } - } - } - } - -resubmit_urb: - urb->dev = cam->usbdev; - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0 && err != -EPERM) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "usb_submit_urb() failed"); - } - - wake_up_interruptible(&cam->wait_frame); -} - - -static int sn9c102_start_transfer(struct sn9c102_device* cam) -{ - struct usb_device *udev = cam->usbdev; - struct urb* urb; - const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512, - 680, 800, 900, 1023}; - const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512, - 680, 800, 900, 1003}; - const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ? - sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] : - sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING]; - s8 i, j; - int err = 0; - - for (i = 0; i < SN9C102_URBS; i++) { - cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz, - GFP_KERNEL); - if (!cam->transfer_buffer[i]) { - err = -ENOMEM; - DBG(1, "Not enough memory"); - goto free_buffers; - } - } - - for (i = 0; i < SN9C102_URBS; i++) { - urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL); - cam->urb[i] = urb; - if (!urb) { - err = -ENOMEM; - DBG(1, "usb_alloc_urb() failed"); - goto free_urbs; - } - urb->dev = udev; - urb->context = cam; - urb->pipe = usb_rcvisocpipe(udev, 1); - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = SN9C102_ISO_PACKETS; - urb->complete = sn9c102_urb_complete; - urb->transfer_buffer = cam->transfer_buffer[i]; - urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS; - urb->interval = 1; - for (j = 0; j < SN9C102_ISO_PACKETS; j++) { - urb->iso_frame_desc[j].offset = psz * j; - urb->iso_frame_desc[j].length = psz; - } - } - - /* Enable video */ - if (!(cam->reg[0x01] & 0x04)) { - err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01); - if (err) { - err = -EIO; - DBG(1, "I/O hardware error"); - goto free_urbs; - } - } - - err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING); - if (err) { - DBG(1, "usb_set_interface() failed"); - goto free_urbs; - } - - cam->frame_current = NULL; - - for (i = 0; i < SN9C102_URBS; i++) { - err = usb_submit_urb(cam->urb[i], GFP_KERNEL); - if (err) { - for (j = i-1; j >= 0; j--) - usb_kill_urb(cam->urb[j]); - DBG(1, "usb_submit_urb() failed, error %d", err); - goto free_urbs; - } - } - - return 0; - -free_urbs: - for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++) - usb_free_urb(cam->urb[i]); - -free_buffers: - for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++) - kfree(cam->transfer_buffer[i]); - - return err; -} - - -static int sn9c102_stop_transfer(struct sn9c102_device* cam) -{ - struct usb_device *udev = cam->usbdev; - s8 i; - int err = 0; - - if (cam->state & DEV_DISCONNECTED) - return 0; - - for (i = SN9C102_URBS-1; i >= 0; i--) { - usb_kill_urb(cam->urb[i]); - usb_free_urb(cam->urb[i]); - kfree(cam->transfer_buffer[i]); - } - - err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ - if (err) - DBG(3, "usb_set_interface() failed"); - - return err; -} - - -static int sn9c102_stream_interrupt(struct sn9c102_device* cam) -{ - long timeout; - - cam->stream = STREAM_INTERRUPT; - timeout = wait_event_timeout(cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED), - SN9C102_URB_TIMEOUT); - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - else if (cam->stream != STREAM_OFF) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "URB timeout reached. The camera is misconfigured. " - "To use it, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -EIO; - } - - return 0; -} - -/*****************************************************************************/ - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count) -{ - char str[5]; - char* endp; - unsigned long val; - - if (len < 4) { - strncpy(str, buff, len); - str[len+1] = '\0'; - } else { - strncpy(str, buff, 4); - str[4] = '\0'; - } - - val = simple_strtoul(str, &endp, 0); - - *count = 0; - if (val <= 0xff) - *count = (ssize_t)(endp - str); - if ((*count) && (len == *count+1) && (buff[*count] == '\n')) - *count += 1; - - return (u8)val; -} - -/* - NOTE 1: being inside one of the following methods implies that the v4l - device exists for sure (see kobjects and reference counters) - NOTE 2: buffers are PAGE_SIZE long -*/ - -static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf) -{ - struct sn9c102_device* cam; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - count = sprintf(buf, "%u\n", cam->sysfs.reg); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) -{ - struct sn9c102_device* cam; - u8 index; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - index = sn9c102_strtou8(buf, len, &count); - if (index > 0x1f || !count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - cam->sysfs.reg = index; - - DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) -{ - struct sn9c102_device* cam; - ssize_t count; - int val; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - count = sprintf(buf, "%d\n", val); - - DBG(3, "Read bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) -{ - struct sn9c102_device* cam; - u8 value; - ssize_t count; - int err; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - value = sn9c102_strtou8(buf, len, &count); - if (!count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - err = sn9c102_write_reg(cam, value, cam->sysfs.reg); - if (err) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X", - cam->sysfs.reg, value); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf) -{ - struct sn9c102_device* cam; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg); - - DBG(3, "Read bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) -{ - struct sn9c102_device* cam; - u8 index; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - index = sn9c102_strtou8(buf, len, &count); - if (!count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - cam->sysfs.i2c_reg = index; - - DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) -{ - struct sn9c102_device* cam; - ssize_t count; - int val; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENOSYS; - } - - if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - count = sprintf(buf, "%d\n", val); - - DBG(3, "Read bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) -{ - struct sn9c102_device* cam; - u8 value; - ssize_t count; - int err; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENOSYS; - } - - value = sn9c102_strtou8(buf, len, &count); - if (!count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value); - if (err) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X", - cam->sysfs.i2c_reg, value); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) -{ - struct sn9c102_device* cam; - enum sn9c102_bridge bridge; - ssize_t res = 0; - u8 value; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - bridge = cam->bridge; - - mutex_unlock(&sn9c102_sysfs_lock); - - value = sn9c102_strtou8(buf, len, &count); - if (!count) - return -EINVAL; - - switch (bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - if (value > 0x0f) - return -EINVAL; - if ((res = sn9c102_store_reg(cd, "0x11", 4)) >= 0) - res = sn9c102_store_val(cd, buf, len); - break; - case BRIDGE_SN9C103: - if (value > 0x7f) - return -EINVAL; - if ((res = sn9c102_store_reg(cd, "0x04", 4)) >= 0) - res = sn9c102_store_val(cd, buf, len); - break; - } - - return res; -} - - -static ssize_t -sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len) -{ - ssize_t res = 0; - u8 value; - ssize_t count; - - value = sn9c102_strtou8(buf, len, &count); - if (!count || value > 0x7f) - return -EINVAL; - - if ((res = sn9c102_store_reg(cd, "0x06", 4)) >= 0) - res = sn9c102_store_val(cd, buf, len); - - return res; -} - - -static ssize_t -sn9c102_store_red(struct class_device* cd, const char* buf, size_t len) -{ - ssize_t res = 0; - u8 value; - ssize_t count; - - value = sn9c102_strtou8(buf, len, &count); - if (!count || value > 0x7f) - return -EINVAL; - - if ((res = sn9c102_store_reg(cd, "0x05", 4)) >= 0) - res = sn9c102_store_val(cd, buf, len); - - return res; -} - - -static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf) -{ - struct sn9c102_device* cam; - ssize_t count; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) - return -ENODEV; - - count = sizeof(cam->sysfs.frame_header); - memcpy(buf, cam->sysfs.frame_header, count); - - DBG(3, "Frame header, read bytes: %zd", count); - - return count; -} - - -static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, - sn9c102_show_reg, sn9c102_store_reg); -static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR, - sn9c102_show_val, sn9c102_store_val); -static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, - sn9c102_show_i2c_reg, sn9c102_store_i2c_reg); -static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, - sn9c102_show_i2c_val, sn9c102_store_i2c_val); -static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green); -static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue); -static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red); -static CLASS_DEVICE_ATTR(frame_header, S_IRUGO, - sn9c102_show_frame_header, NULL); - - -static void sn9c102_create_sysfs(struct sn9c102_device* cam) -{ - struct video_device *v4ldev = cam->v4ldev; - - video_device_create_file(v4ldev, &class_device_attr_reg); - video_device_create_file(v4ldev, &class_device_attr_val); - video_device_create_file(v4ldev, &class_device_attr_frame_header); - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) - video_device_create_file(v4ldev, &class_device_attr_green); - else if (cam->bridge == BRIDGE_SN9C103) { - video_device_create_file(v4ldev, &class_device_attr_blue); - video_device_create_file(v4ldev, &class_device_attr_red); - } - if (cam->sensor.sysfs_ops) { - video_device_create_file(v4ldev, &class_device_attr_i2c_reg); - video_device_create_file(v4ldev, &class_device_attr_i2c_val); - } -} -#endif /* CONFIG_VIDEO_ADV_DEBUG */ - -/*****************************************************************************/ - -static int -sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18); - else - err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18); - - return err ? -EIO : 0; -} - - -static int -sn9c102_set_compression(struct sn9c102_device* cam, - struct v4l2_jpegcompression* compression) -{ - int err = 0; - - if (compression->quality == 0) - err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17); - else if (compression->quality == 1) - err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17); - - return err ? -EIO : 0; -} - - -static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale) -{ - u8 r = 0; - int err = 0; - - if (scale == 1) - r = cam->reg[0x18] & 0xcf; - else if (scale == 2) { - r = cam->reg[0x18] & 0xcf; - r |= 0x10; - } else if (scale == 4) - r = cam->reg[0x18] | 0x20; - - err += sn9c102_write_reg(cam, r, 0x18); - if (err) - return -EIO; - - PDBGG("Scaling factor: %u", scale); - - return 0; -} - - -static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect) -{ - struct sn9c102_sensor* s = &cam->sensor; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left), - v_start = (u8)(rect->top - s->cropcap.bounds.top), - h_size = (u8)(rect->width / 16), - v_size = (u8)(rect->height / 16); - int err = 0; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - err += sn9c102_write_reg(cam, h_size, 0x15); - err += sn9c102_write_reg(cam, v_size, 0x16); - if (err) - return -EIO; - - PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size " - "%u %u %u %u", h_start, v_start, h_size, v_size); - - return 0; -} - - -static int sn9c102_init(struct sn9c102_device* cam) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - struct v4l2_queryctrl *qctrl; - struct v4l2_rect* rect; - u8 i = 0; - int err = 0; - - if (!(cam->state & DEV_INITIALIZED)) { - init_waitqueue_head(&cam->open); - qctrl = s->qctrl; - rect = &(s->cropcap.defrect); - } else { /* use current values */ - qctrl = s->_qctrl; - rect = &(s->_rect); - } - - err += sn9c102_set_scale(cam, rect->width / s->pix_format.width); - err += sn9c102_set_crop(cam, rect); - if (err) - return err; - - if (s->init) { - err = s->init(cam); - if (err) { - DBG(3, "Sensor initialization failed"); - return err; - } - } - - if (!(cam->state & DEV_INITIALIZED)) - cam->compression.quality = cam->reg[0x17] & 0x01 ? 0 : 1; - else - err += sn9c102_set_compression(cam, &cam->compression); - err += sn9c102_set_pix_format(cam, &s->pix_format); - if (s->set_pix_format) - err += s->set_pix_format(cam, &s->pix_format); - if (err) - return err; - - if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) - DBG(3, "Compressed video format is active, quality %d", - cam->compression.quality); - else - DBG(3, "Uncompressed video format is active"); - - if (s->set_crop) - if ((err = s->set_crop(cam, rect))) { - DBG(3, "set_crop() failed"); - return err; - } - - if (s->set_ctrl) { - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (s->qctrl[i].id != 0 && - !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { - ctrl.id = s->qctrl[i].id; - ctrl.value = qctrl[i].default_value; - err = s->set_ctrl(cam, &ctrl); - if (err) { - DBG(3, "Set %s control failed", - s->qctrl[i].name); - return err; - } - DBG(3, "Image sensor supports '%s' control", - s->qctrl[i].name); - } - } - - if (!(cam->state & DEV_INITIALIZED)) { - mutex_init(&cam->fileop_mutex); - spin_lock_init(&cam->queue_lock); - init_waitqueue_head(&cam->wait_frame); - init_waitqueue_head(&cam->wait_stream); - cam->nreadbuffers = 2; - memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); - memcpy(&(s->_rect), &(s->cropcap.defrect), - sizeof(struct v4l2_rect)); - cam->state |= DEV_INITIALIZED; - } - - DBG(2, "Initialization succeeded"); - return 0; -} - - -static void sn9c102_release_resources(struct sn9c102_device* cam) -{ - mutex_lock(&sn9c102_sysfs_lock); - - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); - video_set_drvdata(cam->v4ldev, NULL); - video_unregister_device(cam->v4ldev); - - usb_put_dev(cam->usbdev); - - mutex_unlock(&sn9c102_sysfs_lock); - - kfree(cam->control_buffer); -} - -/*****************************************************************************/ - -static int sn9c102_open(struct inode* inode, struct file* filp) -{ - struct sn9c102_device* cam; - int err = 0; - - /* - This is the only safe way to prevent race conditions with - disconnect - */ - if (!down_read_trylock(&sn9c102_disconnect)) - return -ERESTARTSYS; - - cam = video_get_drvdata(video_devdata(filp)); - - if (mutex_lock_interruptible(&cam->dev_mutex)) { - up_read(&sn9c102_disconnect); - return -ERESTARTSYS; - } - - if (cam->users) { - DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); - if ((filp->f_flags & O_NONBLOCK) || - (filp->f_flags & O_NDELAY)) { - err = -EWOULDBLOCK; - goto out; - } - mutex_unlock(&cam->dev_mutex); - err = wait_event_interruptible_exclusive(cam->open, - cam->state & DEV_DISCONNECTED - || !cam->users); - if (err) { - up_read(&sn9c102_disconnect); - return err; - } - if (cam->state & DEV_DISCONNECTED) { - up_read(&sn9c102_disconnect); - return -ENODEV; - } - mutex_lock(&cam->dev_mutex); - } - - - if (cam->state & DEV_MISCONFIGURED) { - err = sn9c102_init(cam); - if (err) { - DBG(1, "Initialization failed again. " - "I will retry on next open()."); - goto out; - } - cam->state &= ~DEV_MISCONFIGURED; - } - - if ((err = sn9c102_start_transfer(cam))) - goto out; - - filp->private_data = cam; - cam->users++; - cam->io = IO_NONE; - cam->stream = STREAM_OFF; - cam->nbuffers = 0; - cam->frame_count = 0; - sn9c102_empty_framequeues(cam); - - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); - -out: - mutex_unlock(&cam->dev_mutex); - up_read(&sn9c102_disconnect); - return err; -} - - -static int sn9c102_release(struct inode* inode, struct file* filp) -{ - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); - - mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ - - sn9c102_stop_transfer(cam); - - sn9c102_release_buffers(cam); - - if (cam->state & DEV_DISCONNECTED) { - sn9c102_release_resources(cam); - mutex_unlock(&cam->dev_mutex); - kfree(cam); - return 0; - } - - cam->users--; - wake_up_interruptible_nr(&cam->open, 1); - - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); - - mutex_unlock(&cam->dev_mutex); - - return 0; -} - - -static ssize_t -sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) -{ - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); - struct sn9c102_frame_t* f, * i; - unsigned long lock_flags; - long timeout; - int err = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io == IO_MMAP) { - DBG(3, "Close and open the device again to choose " - "the read method"); - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - if (cam->io == IO_NONE) { - if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) { - DBG(1, "read() failed, not enough memory"); - mutex_unlock(&cam->fileop_mutex); - return -ENOMEM; - } - cam->io = IO_READ; - cam->stream = STREAM_ON; - } - - if (list_empty(&cam->inqueue)) { - if (!list_empty(&cam->outqueue)) - sn9c102_empty_framequeues(cam); - sn9c102_queue_unusedframes(cam); - } - - if (!count) { - mutex_unlock(&cam->fileop_mutex); - return 0; - } - - if (list_empty(&cam->outqueue)) { - if (filp->f_flags & O_NONBLOCK) { - mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) { - mutex_unlock(&cam->fileop_mutex); - return timeout; - } - if (cam->state & DEV_DISCONNECTED) { - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - if (!timeout || (cam->state & DEV_MISCONFIGURED)) { - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - } - - f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame); - - if (count > f->buf.bytesused) - count = f->buf.bytesused; - - if (copy_to_user(buf, f->bufmem, count)) { - err = -EFAULT; - goto exit; - } - *f_pos += count; - -exit: - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_for_each_entry(i, &cam->outqueue, frame) - i->state = F_UNUSED; - INIT_LIST_HEAD(&cam->outqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - sn9c102_queue_unusedframes(cam); - - PDBGG("Frame #%lu, bytes read: %zu", - (unsigned long)f->buf.index, count); - - mutex_unlock(&cam->fileop_mutex); - - return count; -} - - -static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) -{ - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); - struct sn9c102_frame_t* f; - unsigned long lock_flags; - unsigned int mask = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return POLLERR; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - goto error; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - goto error; - } - - if (cam->io == IO_NONE) { - if (!sn9c102_request_buffers(cam, cam->nreadbuffers, - IO_READ)) { - DBG(1, "poll() failed, not enough memory"); - goto error; - } - cam->io = IO_READ; - cam->stream = STREAM_ON; - } - - if (cam->io == IO_READ) { - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_for_each_entry(f, &cam->outqueue, frame) - f->state = F_UNUSED; - INIT_LIST_HEAD(&cam->outqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - sn9c102_queue_unusedframes(cam); - } - - poll_wait(filp, &cam->wait_frame, wait); - - if (!list_empty(&cam->outqueue)) - mask |= POLLIN | POLLRDNORM; - - mutex_unlock(&cam->fileop_mutex); - - return mask; - -error: - mutex_unlock(&cam->fileop_mutex); - return POLLERR; -} - - -static void sn9c102_vm_open(struct vm_area_struct* vma) -{ - struct sn9c102_frame_t* f = vma->vm_private_data; - f->vma_use_count++; -} - - -static void sn9c102_vm_close(struct vm_area_struct* vma) -{ - /* NOTE: buffers are not freed here */ - struct sn9c102_frame_t* f = vma->vm_private_data; - f->vma_use_count--; -} - - -static struct vm_operations_struct sn9c102_vm_ops = { - .open = sn9c102_vm_open, - .close = sn9c102_vm_close, -}; - - -static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) -{ - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); - unsigned long size = vma->vm_end - vma->vm_start, - start = vma->vm_start; - void *pos; - u32 i; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || - size != PAGE_ALIGN(cam->frame[0].buf.length)) { - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - for (i = 0; i < cam->nbuffers; i++) { - if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) - break; - } - if (i == cam->nbuffers) { - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - vma->vm_flags |= VM_IO; - vma->vm_flags |= VM_RESERVED; - - pos = cam->frame[i].bufmem; - while (size > 0) { /* size is page-aligned */ - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { - mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vma->vm_ops = &sn9c102_vm_ops; - vma->vm_private_data = &cam->frame[i]; - - sn9c102_vm_open(vma); - - mutex_unlock(&cam->fileop_mutex); - - return 0; -} - -/*****************************************************************************/ - -static int -sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_capability cap = { - .driver = "sn9c102", - .version = SN9C102_MODULE_VERSION_CODE, - .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, - }; - - strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); - if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) - strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, - sizeof(cap.bus_info)); - - if (copy_to_user(arg, &cap, sizeof(cap))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_input i; - - if (copy_from_user(&i, arg, sizeof(i))) - return -EFAULT; - - if (i.index) - return -EINVAL; - - memset(&i, 0, sizeof(i)); - strcpy(i.name, "Camera"); - i.type = V4L2_INPUT_TYPE_CAMERA; - - if (copy_to_user(arg, &i, sizeof(i))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg) -{ - int index = 0; - - if (copy_to_user(arg, &index, sizeof(index))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg) -{ - int index; - - if (copy_from_user(&index, arg, sizeof(index))) - return -EFAULT; - - if (index != 0) - return -EINVAL; - - return 0; -} - - -static int -sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_queryctrl qc; - u8 i; - - if (copy_from_user(&qc, arg, sizeof(qc))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (qc.id && qc.id == s->qctrl[i].id) { - memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); - if (copy_to_user(arg, &qc, sizeof(qc))) - return -EFAULT; - return 0; - } - - return -EINVAL; -} - - -static int -sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - int err = 0; - u8 i; - - if (!s->get_ctrl && !s->set_ctrl) - return -EINVAL; - - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; - - if (!s->get_ctrl) { - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id && ctrl.id == s->qctrl[i].id) { - ctrl.value = s->_qctrl[i].default_value; - goto exit; - } - return -EINVAL; - } else - err = s->get_ctrl(cam, &ctrl); - -exit: - if (copy_to_user(arg, &ctrl, sizeof(ctrl))) - return -EFAULT; - - return err; -} - - -static int -sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - u8 i; - int err = 0; - - if (!s->set_ctrl) - return -EINVAL; - - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id == s->qctrl[i].id) { - if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) - return -EINVAL; - if (ctrl.value < s->qctrl[i].minimum || - ctrl.value > s->qctrl[i].maximum) - return -ERANGE; - ctrl.value -= ctrl.value % s->qctrl[i].step; - break; - } - - if ((err = s->set_ctrl(cam, &ctrl))) - return err; - - s->_qctrl[i].default_value = ctrl.value; - - PDBGG("VIDIOC_S_CTRL: id %lu, value %lu", - (unsigned long)ctrl.id, (unsigned long)ctrl.value); - - return 0; -} - - -static int -sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_cropcap* cc = &(cam->sensor.cropcap); - - cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cc->pixelaspect.numerator = 1; - cc->pixelaspect.denominator = 1; - - if (copy_to_user(arg, cc, sizeof(*cc))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_crop crop = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - }; - - memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); - - if (copy_to_user(arg, &crop, sizeof(crop))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_crop crop; - struct v4l2_rect* rect; - struct v4l2_rect* bounds = &(s->cropcap.bounds); - struct v4l2_pix_format* pix_format = &(s->pix_format); - u8 scale; - const enum sn9c102_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&crop, arg, sizeof(crop))) - return -EFAULT; - - rect = &(crop.c); - - if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_CROP failed. " - "Unmap the buffers first."); - return -EINVAL; - } - - /* Preserve R,G or B origin */ - rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; - rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; - - if (rect->width < 16) - rect->width = 16; - if (rect->height < 16) - rect->height = 16; - if (rect->width > bounds->width) - rect->width = bounds->width; - if (rect->height > bounds->height) - rect->height = bounds->height; - if (rect->left < bounds->left) - rect->left = bounds->left; - if (rect->top < bounds->top) - rect->top = bounds->top; - if (rect->left + rect->width > bounds->left + bounds->width) - rect->left = bounds->left+bounds->width - rect->width; - if (rect->top + rect->height > bounds->top + bounds->height) - rect->top = bounds->top+bounds->height - rect->height; - - rect->width &= ~15L; - rect->height &= ~15L; - - if (SN9C102_PRESERVE_IMGSCALE) { - /* Calculate the actual scaling factor */ - u32 a, b; - a = rect->width * rect->height; - b = pix_format->width * pix_format->height; - scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; - } else - scale = 1; - - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; - - if (copy_to_user(arg, &crop, sizeof(crop))) { - cam->stream = stream; - return -EFAULT; - } - - if (cam->module_param.force_munmap || cam->io == IO_READ) - sn9c102_release_buffers(cam); - - err = sn9c102_set_crop(cam, rect); - if (s->set_crop) - err += s->set_crop(cam, rect); - err += sn9c102_set_scale(cam, scale); - - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -EIO; - } - - s->pix_format.width = rect->width/scale; - s->pix_format.height = rect->height/scale; - memcpy(&(s->_rect), rect, sizeof(*rect)); - - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -ENOMEM; - } - - if (cam->io == IO_READ) - sn9c102_empty_framequeues(cam); - else if (cam->module_param.force_munmap) - sn9c102_requeue_outqueue(cam); - - cam->stream = stream; - - return 0; -} - - -static int -sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_fmtdesc fmtd; - - if (copy_from_user(&fmtd, arg, sizeof(fmtd))) - return -EFAULT; - - if (fmtd.index == 0) { - strcpy(fmtd.description, "bayer rgb"); - fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; - } else if (fmtd.index == 1) { - strcpy(fmtd.description, "compressed"); - fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; - fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; - } else - return -EINVAL; - - fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); - - if (copy_to_user(arg, &fmtd, sizeof(fmtd))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_format format; - struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; - - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X) - ? 0 : (pfmt->width * pfmt->priv) / 8; - pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); - pfmt->field = V4L2_FIELD_NONE; - memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); - - if (copy_to_user(arg, &format, sizeof(format))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, - void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_format format; - struct v4l2_pix_format* pix; - struct v4l2_pix_format* pfmt = &(s->pix_format); - struct v4l2_rect* bounds = &(s->cropcap.bounds); - struct v4l2_rect rect; - u8 scale; - const enum sn9c102_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; - - pix = &(format.fmt.pix); - - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - memcpy(&rect, &(s->_rect), sizeof(rect)); - - { /* calculate the actual scaling factor */ - u32 a, b; - a = rect.width * rect.height; - b = pix->width * pix->height; - scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; - } - - rect.width = scale * pix->width; - rect.height = scale * pix->height; - - if (rect.width < 16) - rect.width = 16; - if (rect.height < 16) - rect.height = 16; - if (rect.width > bounds->left + bounds->width - rect.left) - rect.width = bounds->left + bounds->width - rect.left; - if (rect.height > bounds->top + bounds->height - rect.top) - rect.height = bounds->top + bounds->height - rect.top; - - rect.width &= ~15L; - rect.height &= ~15L; - - { /* adjust the scaling factor */ - u32 a, b; - a = rect.width * rect.height; - b = pix->width * pix->height; - scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; - } - - pix->width = rect.width / scale; - pix->height = rect.height / scale; - - if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && - pix->pixelformat != V4L2_PIX_FMT_SBGGR8) - pix->pixelformat = pfmt->pixelformat; - pix->priv = pfmt->priv; /* bpp */ - pix->colorspace = pfmt->colorspace; - pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - ? 0 : (pix->width * pix->priv) / 8; - pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); - pix->field = V4L2_FIELD_NONE; - - if (cmd == VIDIOC_TRY_FMT) { - if (copy_to_user(arg, &format, sizeof(format))) - return -EFAULT; - return 0; - } - - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_FMT failed. Unmap the " - "buffers first."); - return -EINVAL; - } - - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; - - if (copy_to_user(arg, &format, sizeof(format))) { - cam->stream = stream; - return -EFAULT; - } - - if (cam->module_param.force_munmap || cam->io == IO_READ) - sn9c102_release_buffers(cam); - - err += sn9c102_set_pix_format(cam, pix); - err += sn9c102_set_crop(cam, &rect); - if (s->set_pix_format) - err += s->set_pix_format(cam, pix); - if (s->set_crop) - err += s->set_crop(cam, &rect); - err += sn9c102_set_scale(cam, scale); - - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -EIO; - } - - memcpy(pfmt, pix, sizeof(*pix)); - memcpy(&(s->_rect), &rect, sizeof(rect)); - - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -ENOMEM; - } - - if (cam->io == IO_READ) - sn9c102_empty_framequeues(cam); - else if (cam->module_param.force_munmap) - sn9c102_requeue_outqueue(cam); - - cam->stream = stream; - - return 0; -} - - -static int -sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg) -{ - if (copy_to_user(arg, &cam->compression, - sizeof(cam->compression))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_jpegcompression jc; - const enum sn9c102_stream_state stream = cam->stream; - int err = 0; - - if (copy_from_user(&jc, arg, sizeof(jc))) - return -EFAULT; - - if (jc.quality != 0 && jc.quality != 1) - return -EINVAL; - - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; - - err += sn9c102_set_compression(cam, &jc); - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " - "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->minor); - return -EIO; - } - - cam->compression.quality = jc.quality; - - cam->stream = stream; - - return 0; -} - - -static int -sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_requestbuffers rb; - u32 i; - int err; - - if (copy_from_user(&rb, arg, sizeof(rb))) - return -EFAULT; - - if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - rb.memory != V4L2_MEMORY_MMAP) - return -EINVAL; - - if (cam->io == IO_READ) { - DBG(3, "Close and open the device again to choose the mmap " - "I/O method"); - return -EINVAL; - } - - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are " - "still mapped."); - return -EINVAL; - } - - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; - - sn9c102_empty_framequeues(cam); - - sn9c102_release_buffers(cam); - if (rb.count) - rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP); - - if (copy_to_user(arg, &rb, sizeof(rb))) { - sn9c102_release_buffers(cam); - cam->io = IO_NONE; - return -EFAULT; - } - - cam->io = rb.count ? IO_MMAP : IO_NONE; - - return 0; -} - - -static int -sn9c102_vidioc_querybuf(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_buffer b; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; - - memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); - - if (cam->frame[b.index].vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; - - if (cam->frame[b.index].state == F_DONE) - b.flags |= V4L2_BUF_FLAG_DONE; - else if (cam->frame[b.index].state != F_UNUSED) - b.flags |= V4L2_BUF_FLAG_QUEUED; - - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_buffer b; - unsigned long lock_flags; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; - - if (cam->frame[b.index].state != F_UNUSED) - return -EINVAL; - - cam->frame[b.index].state = F_QUEUED; - - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - PDBGG("Frame #%lu queued", (unsigned long)b.index); - - return 0; -} - - -static int -sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, - void __user * arg) -{ - struct v4l2_buffer b; - struct sn9c102_frame_t *f; - unsigned long lock_flags; - long timeout; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - if (list_empty(&cam->outqueue)) { - if (cam->stream == STREAM_OFF) - return -EINVAL; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) - return timeout; - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - if (!timeout || (cam->state & DEV_MISCONFIGURED)) - return -EIO; - } - - spin_lock_irqsave(&cam->queue_lock, lock_flags); - f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame); - list_del(cam->outqueue.next); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - f->state = F_UNUSED; - - memcpy(&b, &f->buf, sizeof(b)); - if (f->vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; - - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - - PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); - - return 0; -} - - -static int -sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg) -{ - int type; - - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - if (list_empty(&cam->inqueue)) - return -EINVAL; - - cam->stream = STREAM_ON; - - DBG(3, "Stream on"); - - return 0; -} - - -static int -sn9c102_vidioc_streamoff(struct sn9c102_device* cam, void __user * arg) -{ - int type, err; - - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; - - sn9c102_empty_framequeues(cam); - - DBG(3, "Stream off"); - - return 0; -} - - -static int -sn9c102_vidioc_g_parm(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_streamparm sp; - - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; - - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - sp.parm.capture.extendedmode = 0; - sp.parm.capture.readbuffers = cam->nreadbuffers; - - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_streamparm sp; - - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; - - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - sp.parm.capture.extendedmode = 0; - - if (sp.parm.capture.readbuffers == 0) - sp.parm.capture.readbuffers = cam->nreadbuffers; - - if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES) - sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES; - - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; - - cam->nreadbuffers = sp.parm.capture.readbuffers; - - return 0; -} - - -static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) -{ - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); - - switch (cmd) { - - case VIDIOC_QUERYCAP: - return sn9c102_vidioc_querycap(cam, arg); - - case VIDIOC_ENUMINPUT: - return sn9c102_vidioc_enuminput(cam, arg); - - case VIDIOC_G_INPUT: - return sn9c102_vidioc_g_input(cam, arg); - - case VIDIOC_S_INPUT: - return sn9c102_vidioc_s_input(cam, arg); - - case VIDIOC_QUERYCTRL: - return sn9c102_vidioc_query_ctrl(cam, arg); - - case VIDIOC_G_CTRL: - return sn9c102_vidioc_g_ctrl(cam, arg); - - case VIDIOC_S_CTRL_OLD: - case VIDIOC_S_CTRL: - return sn9c102_vidioc_s_ctrl(cam, arg); - - case VIDIOC_CROPCAP_OLD: - case VIDIOC_CROPCAP: - return sn9c102_vidioc_cropcap(cam, arg); - - case VIDIOC_G_CROP: - return sn9c102_vidioc_g_crop(cam, arg); - - case VIDIOC_S_CROP: - return sn9c102_vidioc_s_crop(cam, arg); - - case VIDIOC_ENUM_FMT: - return sn9c102_vidioc_enum_fmt(cam, arg); - - case VIDIOC_G_FMT: - return sn9c102_vidioc_g_fmt(cam, arg); - - case VIDIOC_TRY_FMT: - case VIDIOC_S_FMT: - return sn9c102_vidioc_try_s_fmt(cam, cmd, arg); - - case VIDIOC_G_JPEGCOMP: - return sn9c102_vidioc_g_jpegcomp(cam, arg); - - case VIDIOC_S_JPEGCOMP: - return sn9c102_vidioc_s_jpegcomp(cam, arg); - - case VIDIOC_REQBUFS: - return sn9c102_vidioc_reqbufs(cam, arg); - - case VIDIOC_QUERYBUF: - return sn9c102_vidioc_querybuf(cam, arg); - - case VIDIOC_QBUF: - return sn9c102_vidioc_qbuf(cam, arg); - - case VIDIOC_DQBUF: - return sn9c102_vidioc_dqbuf(cam, filp, arg); - - case VIDIOC_STREAMON: - return sn9c102_vidioc_streamon(cam, arg); - - case VIDIOC_STREAMOFF: - return sn9c102_vidioc_streamoff(cam, arg); - - case VIDIOC_G_PARM: - return sn9c102_vidioc_g_parm(cam, arg); - - case VIDIOC_S_PARM_OLD: - case VIDIOC_S_PARM: - return sn9c102_vidioc_s_parm(cam, arg); - - case VIDIOC_G_STD: - case VIDIOC_S_STD: - case VIDIOC_QUERYSTD: - case VIDIOC_ENUMSTD: - case VIDIOC_QUERYMENU: - return -EINVAL; - - default: - return -EINVAL; - - } -} - - -static int sn9c102_ioctl(struct inode* inode, struct file* filp, - unsigned int cmd, unsigned long arg) -{ - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); - int err = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - V4LDBG(3, "sn9c102", cmd); - - err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); - - mutex_unlock(&cam->fileop_mutex); - - return err; -} - -/*****************************************************************************/ - -static struct file_operations sn9c102_fops = { - .owner = THIS_MODULE, - .open = sn9c102_open, - .release = sn9c102_release, - .ioctl = sn9c102_ioctl, - .read = sn9c102_read, - .poll = sn9c102_poll, - .mmap = sn9c102_mmap, - .llseek = no_llseek, -}; - -/*****************************************************************************/ - -/* It exists a single interface only. We do not need to validate anything. */ -static int -sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct sn9c102_device* cam; - static unsigned int dev_nr = 0; - unsigned int i; - int err = 0, r; - - if (!(cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL))) - return -ENOMEM; - - cam->usbdev = udev; - - if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { - DBG(1, "kmalloc() failed"); - err = -ENOMEM; - goto fail; - } - - if (!(cam->v4ldev = video_device_alloc())) { - DBG(1, "video_device_alloc() failed"); - err = -ENOMEM; - goto fail; - } - - mutex_init(&cam->dev_mutex); - - r = sn9c102_read_reg(cam, 0x00); - if (r < 0 || r != 0x10) { - DBG(1, "Sorry, this is not a SN9C10x based camera " - "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); - err = -ENODEV; - goto fail; - } - - cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ? - BRIDGE_SN9C103 : BRIDGE_SN9C102; - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - DBG(2, "SN9C10[12] PC Camera Controller detected " - "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); - break; - case BRIDGE_SN9C103: - DBG(2, "SN9C103 PC Camera Controller detected " - "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); - break; - } - - for (i = 0; sn9c102_sensor_table[i]; i++) { - err = sn9c102_sensor_table[i](cam); - if (!err) - break; - } - - if (!err) { - DBG(2, "%s image sensor detected", cam->sensor.name); - DBG(3, "Support for %s maintained by %s", - cam->sensor.name, cam->sensor.maintainer); - } else { - DBG(1, "No supported image sensor detected"); - err = -ENODEV; - goto fail; - } - - if (sn9c102_init(cam)) { - DBG(1, "Initialization failed. I will retry on open()."); - cam->state |= DEV_MISCONFIGURED; - } - - strcpy(cam->v4ldev->name, "SN9C10x PC Camera"); - cam->v4ldev->owner = THIS_MODULE; - cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; - cam->v4ldev->hardware = 0; - cam->v4ldev->fops = &sn9c102_fops; - cam->v4ldev->minor = video_nr[dev_nr]; - cam->v4ldev->release = video_device_release; - video_set_drvdata(cam->v4ldev, cam); - - mutex_lock(&cam->dev_mutex); - - err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); - if (err) { - DBG(1, "V4L2 device registration failed"); - if (err == -ENFILE && video_nr[dev_nr] == -1) - DBG(1, "Free /dev/videoX node not found"); - video_nr[dev_nr] = -1; - dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; - mutex_unlock(&cam->dev_mutex); - goto fail; - } - - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); - - cam->module_param.force_munmap = force_munmap[dev_nr]; - cam->module_param.frame_timeout = frame_timeout[dev_nr]; - - dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; - -#ifdef CONFIG_VIDEO_ADV_DEBUG - sn9c102_create_sysfs(cam); - DBG(2, "Optional device control through 'sysfs' interface ready"); -#endif - - usb_set_intfdata(intf, cam); - - mutex_unlock(&cam->dev_mutex); - - return 0; - -fail: - if (cam) { - kfree(cam->control_buffer); - if (cam->v4ldev) - video_device_release(cam->v4ldev); - kfree(cam); - } - return err; -} - - -static void sn9c102_usb_disconnect(struct usb_interface* intf) -{ - struct sn9c102_device* cam = usb_get_intfdata(intf); - - if (!cam) - return; - - down_write(&sn9c102_disconnect); - - mutex_lock(&cam->dev_mutex); - - DBG(2, "Disconnecting %s...", cam->v4ldev->name); - - wake_up_interruptible_all(&cam->open); - - if (cam->users) { - DBG(2, "Device /dev/video%d is open! Deregistration and " - "memory deallocation are deferred on close.", - cam->v4ldev->minor); - cam->state |= DEV_MISCONFIGURED; - sn9c102_stop_transfer(cam); - cam->state |= DEV_DISCONNECTED; - wake_up_interruptible(&cam->wait_frame); - wake_up(&cam->wait_stream); - usb_get_dev(cam->usbdev); - } else { - cam->state |= DEV_DISCONNECTED; - sn9c102_release_resources(cam); - } - - mutex_unlock(&cam->dev_mutex); - - if (!cam->users) - kfree(cam); - - up_write(&sn9c102_disconnect); -} - - -static struct usb_driver sn9c102_usb_driver = { - .name = "sn9c102", - .id_table = sn9c102_id_table, - .probe = sn9c102_usb_probe, - .disconnect = sn9c102_usb_disconnect, -}; - -/*****************************************************************************/ - -static int __init sn9c102_module_init(void) -{ - int err = 0; - - KDBG(2, SN9C102_MODULE_NAME " v" SN9C102_MODULE_VERSION); - KDBG(3, SN9C102_MODULE_AUTHOR); - - if ((err = usb_register(&sn9c102_usb_driver))) - KDBG(1, "usb_register() failed"); - - return err; -} - - -static void __exit sn9c102_module_exit(void) -{ - usb_deregister(&sn9c102_usb_driver); -} - - -module_init(sn9c102_module_init); -module_exit(sn9c102_module_exit); diff --git a/drivers/usb/media/sn9c102_hv7131d.c b/drivers/usb/media/sn9c102_hv7131d.c deleted file mode 100644 index 46c12ec3ca62..000000000000 --- a/drivers/usb/media/sn9c102_hv7131d.c +++ /dev/null @@ -1,271 +0,0 @@ -/*************************************************************************** - * Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera * - * Controllers * - * * - * Copyright (C) 2004-2006 by Luca Risolia * - * * - * 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 "sn9c102_sensor.h" - - -static struct sn9c102_sensor hv7131d; - - -static int hv7131d_init(struct sn9c102_device* cam) -{ - int err = 0; - - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x60, 0x17); - err += sn9c102_write_reg(cam, 0x0e, 0x18); - err += sn9c102_write_reg(cam, 0xf2, 0x19); - - err += sn9c102_i2c_write(cam, 0x01, 0x04); - err += sn9c102_i2c_write(cam, 0x02, 0x00); - err += sn9c102_i2c_write(cam, 0x28, 0x00); - - return err; -} - - -static int hv7131d_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - { - int r1 = sn9c102_i2c_read(cam, 0x26), - r2 = sn9c102_i2c_read(cam, 0x27); - if (r1 < 0 || r2 < 0) - return -EIO; - ctrl->value = (r1 << 8) | (r2 & 0xff); - } - return 0; - case V4L2_CID_RED_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0) - return -EIO; - ctrl->value = 0x3f - (ctrl->value & 0x3f); - return 0; - case V4L2_CID_BLUE_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0) - return -EIO; - ctrl->value = 0x3f - (ctrl->value & 0x3f); - return 0; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0) - return -EIO; - ctrl->value = 0x3f - (ctrl->value & 0x3f); - return 0; - case SN9C102_V4L2_CID_RESET_LEVEL: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0) - return -EIO; - ctrl->value &= 0x3f; - return 0; - case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x34)) < 0) - return -EIO; - ctrl->value &= 0x07; - return 0; - default: - return -EINVAL; - } -} - - -static int hv7131d_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8); - err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value); - break; - case SN9C102_V4L2_CID_RESET_LEVEL: - err += sn9c102_i2c_write(cam, 0x30, ctrl->value); - break; - case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE: - err += sn9c102_i2c_write(cam, 0x34, ctrl->value); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int hv7131d_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) -{ - struct sn9c102_sensor* s = &hv7131d; - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int hv7131d_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x42, 0x19); - else - err += sn9c102_write_reg(cam, 0xf2, 0x19); - - return err; -} - - -static struct sn9c102_sensor hv7131d = { - .name = "HV7131D", - .maintainer = "Luca Risolia ", - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x11, - .init = &hv7131d_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x0250, - .maximum = 0xffff, - .step = 0x0001, - .default_value = 0x0250, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x1e, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_RESET_LEVEL, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "reset level", - .minimum = 0x19, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x30, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "pixel bias voltage", - .minimum = 0x00, - .maximum = 0x07, - .step = 0x01, - .default_value = 0x02, - .flags = 0, - }, - }, - .get_ctrl = &hv7131d_get_ctrl, - .set_ctrl = &hv7131d_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &hv7131d_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &hv7131d_set_pix_format -}; - - -int sn9c102_probe_hv7131d(struct sn9c102_device* cam) -{ - int r0 = 0, r1 = 0, err = 0; - - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - err += sn9c102_write_reg(cam, 0x28, 0x17); - if (err) - return -EIO; - - r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00); - r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01); - if (r0 < 0 || r1 < 0) - return -EIO; - - if (r0 != 0x00 && r1 != 0x04) - return -ENODEV; - - sn9c102_attach_sensor(cam, &hv7131d); - - return 0; -} diff --git a/drivers/usb/media/sn9c102_mi0343.c b/drivers/usb/media/sn9c102_mi0343.c deleted file mode 100644 index d9aa7a61095d..000000000000 --- a/drivers/usb/media/sn9c102_mi0343.c +++ /dev/null @@ -1,363 +0,0 @@ -/*************************************************************************** - * Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera * - * Controllers * - * * - * Copyright (C) 2004-2006 by Luca Risolia * - * * - * 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 "sn9c102_sensor.h" - - -static struct sn9c102_sensor mi0343; -static u8 mi0343_i2c_data[5+1]; - - -static int mi0343_init(struct sn9c102_device* cam) -{ - int err = 0; - - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x0a, 0x14); - err += sn9c102_write_reg(cam, 0x40, 0x01); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x07, 0x18); - err += sn9c102_write_reg(cam, 0xa0, 0x19); - - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x0d, 0x00, 0x01, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x0d, 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x03, 0x01, 0xe1, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x04, 0x02, 0x81, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x05, 0x00, 0x17, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x06, 0x00, 0x11, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x62, 0x04, 0x9a, 0, 0); - - return err; -} - - -static int mi0343_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x09, 2+1, mi0343_i2c_data) < 0) - return -EIO; - ctrl->value = mi0343_i2c_data[2]; - return 0; - case V4L2_CID_GAIN: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x35, 2+1, mi0343_i2c_data) < 0) - return -EIO; - break; - case V4L2_CID_HFLIP: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x20, 2+1, mi0343_i2c_data) < 0) - return -EIO; - ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0; - return 0; - case V4L2_CID_VFLIP: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x20, 2+1, mi0343_i2c_data) < 0) - return -EIO; - ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0; - return 0; - case V4L2_CID_RED_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2d, 2+1, mi0343_i2c_data) < 0) - return -EIO; - break; - case V4L2_CID_BLUE_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2c, 2+1, mi0343_i2c_data) < 0) - return -EIO; - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2e, 2+1, mi0343_i2c_data) < 0) - return -EIO; - break; - default: - return -EINVAL; - } - - switch (ctrl->id) { - case V4L2_CID_GAIN: - case V4L2_CID_RED_BALANCE: - case V4L2_CID_BLUE_BALANCE: - case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = mi0343_i2c_data[3] | (mi0343_i2c_data[2] << 8); - if (ctrl->value >= 0x10 && ctrl->value <= 0x3f) - ctrl->value -= 0x10; - else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f) - ctrl->value -= 0x60; - else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff) - ctrl->value -= 0xe0; - } - - return 0; -} - - -static int mi0343_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - u16 reg = 0; - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_GAIN: - case V4L2_CID_RED_BALANCE: - case V4L2_CID_BLUE_BALANCE: - case SN9C102_V4L2_CID_GREEN_BALANCE: - if (ctrl->value <= (0x3f-0x10)) - reg = 0x10 + ctrl->value; - else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60))) - reg = 0x60 + (ctrl->value - (0x3f-0x10)); - else - reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60)); - break; - } - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x09, ctrl->value, 0x00, - 0, 0); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x35, reg >> 8, reg & 0xff, - 0, 0); - break; - case V4L2_CID_HFLIP: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x20, ctrl->value ? 0x40:0x00, - ctrl->value ? 0x20:0x00, - 0, 0); - break; - case V4L2_CID_VFLIP: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x20, ctrl->value ? 0x80:0x00, - ctrl->value ? 0x80:0x00, - 0, 0); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x2d, reg >> 8, reg & 0xff, - 0, 0); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x2c, reg >> 8, reg & 0xff, - 0, 0); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x2b, reg >> 8, reg & 0xff, - 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x2e, reg >> 8, reg & 0xff, - 0, 0); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int mi0343_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) -{ - struct sn9c102_sensor* s = &mi0343; - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int mi0343_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x0a, 0x00, 0x03, 0, 0); - err += sn9c102_write_reg(cam, 0x20, 0x19); - } else { - err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x0a, 0x00, 0x05, 0, 0); - err += sn9c102_write_reg(cam, 0xa0, 0x19); - } - - return err; -} - - -static struct sn9c102_sensor mi0343 = { - .name = "MI-0343", - .maintainer = "Luca Risolia ", - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x5d, - .init = &mi0343_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x06, - .flags = 0, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/ - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - .flags = 0, - }, - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0), - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0), - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)), - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - }, - .get_ctrl = &mi0343_get_ctrl, - .set_ctrl = &mi0343_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &mi0343_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &mi0343_set_pix_format -}; - - -int sn9c102_probe_mi0343(struct sn9c102_device* cam) -{ - int err = 0; - - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - err += sn9c102_write_reg(cam, 0x28, 0x17); - if (err) - return -EIO; - - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00, - 2, mi0343_i2c_data) < 0) - return -EIO; - - if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3) - return -ENODEV; - - sn9c102_attach_sensor(cam, &mi0343); - - return 0; -} diff --git a/drivers/usb/media/sn9c102_ov7630.c b/drivers/usb/media/sn9c102_ov7630.c deleted file mode 100644 index 42852b7cb042..000000000000 --- a/drivers/usb/media/sn9c102_ov7630.c +++ /dev/null @@ -1,401 +0,0 @@ -/*************************************************************************** - * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera * - * Controllers * - * * - * Copyright (C) 2005-2006 by Luca Risolia * - * * - * 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 "sn9c102_sensor.h" - - -static struct sn9c102_sensor ov7630; - - -static int ov7630_init(struct sn9c102_device* cam) -{ - int err = 0; - - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x60, 0x17); - err += sn9c102_write_reg(cam, 0x0f, 0x18); - err += sn9c102_write_reg(cam, 0x50, 0x19); - - err += sn9c102_i2c_write(cam, 0x12, 0x80); - err += sn9c102_i2c_write(cam, 0x11, 0x01); - err += sn9c102_i2c_write(cam, 0x15, 0x34); - err += sn9c102_i2c_write(cam, 0x16, 0x03); - err += sn9c102_i2c_write(cam, 0x17, 0x1c); - err += sn9c102_i2c_write(cam, 0x18, 0xbd); - err += sn9c102_i2c_write(cam, 0x19, 0x06); - err += sn9c102_i2c_write(cam, 0x1a, 0xf6); - err += sn9c102_i2c_write(cam, 0x1b, 0x04); - err += sn9c102_i2c_write(cam, 0x20, 0xf6); - err += sn9c102_i2c_write(cam, 0x23, 0xee); - err += sn9c102_i2c_write(cam, 0x26, 0xa0); - err += sn9c102_i2c_write(cam, 0x27, 0x9a); - err += sn9c102_i2c_write(cam, 0x28, 0xa0); - err += sn9c102_i2c_write(cam, 0x29, 0x30); - err += sn9c102_i2c_write(cam, 0x2a, 0xa0); - err += sn9c102_i2c_write(cam, 0x2b, 0x1f); - err += sn9c102_i2c_write(cam, 0x2f, 0x3d); - err += sn9c102_i2c_write(cam, 0x30, 0x24); - err += sn9c102_i2c_write(cam, 0x32, 0x86); - err += sn9c102_i2c_write(cam, 0x60, 0xa9); - err += sn9c102_i2c_write(cam, 0x61, 0x42); - err += sn9c102_i2c_write(cam, 0x65, 0x00); - err += sn9c102_i2c_write(cam, 0x69, 0x38); - err += sn9c102_i2c_write(cam, 0x6f, 0x88); - err += sn9c102_i2c_write(cam, 0x70, 0x0b); - err += sn9c102_i2c_write(cam, 0x71, 0x00); - err += sn9c102_i2c_write(cam, 0x74, 0x21); - err += sn9c102_i2c_write(cam, 0x7d, 0xf7); - - return err; -} - - -static int ov7630_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x10, ctrl->value >> 2); - err += sn9c102_i2c_write(cam, 0x76, ctrl->value & 0x03); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x02, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x01, ctrl->value); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x00, ctrl->value); - break; - case V4L2_CID_CONTRAST: - err += ctrl->value ? sn9c102_i2c_write(cam, 0x05, - (ctrl->value-1) | 0x20) - : sn9c102_i2c_write(cam, 0x05, 0x00); - break; - case V4L2_CID_BRIGHTNESS: - err += sn9c102_i2c_write(cam, 0x06, ctrl->value); - break; - case V4L2_CID_SATURATION: - err += sn9c102_i2c_write(cam, 0x03, ctrl->value << 4); - break; - case V4L2_CID_HUE: - err += ctrl->value ? sn9c102_i2c_write(cam, 0x04, - (ctrl->value-1) | 0x20) - : sn9c102_i2c_write(cam, 0x04, 0x00); - break; - case V4L2_CID_DO_WHITE_BALANCE: - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); - break; - case V4L2_CID_WHITENESS: - err += sn9c102_i2c_write(cam, 0x0d, ctrl->value); - break; - case V4L2_CID_AUTO_WHITE_BALANCE: - err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78); - break; - case V4L2_CID_AUTOGAIN: - err += sn9c102_i2c_write(cam, 0x13, ctrl->value); - break; - case V4L2_CID_VFLIP: - err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7)); - break; - case V4L2_CID_BLACK_LEVEL: - err += sn9c102_i2c_write(cam, 0x25, ctrl->value); - break; - case SN9C102_V4L2_CID_BRIGHT_LEVEL: - err += sn9c102_i2c_write(cam, 0x24, ctrl->value); - break; - case SN9C102_V4L2_CID_GAMMA: - err += sn9c102_i2c_write(cam, 0x14, (ctrl->value << 2) | 0x80); - break; - case SN9C102_V4L2_CID_BAND_FILTER: - err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int ov7630_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) -{ - struct sn9c102_sensor* s = &ov7630; - int err = 0; - u8 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; - - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int ov7630_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x20, 0x19); - else - err += sn9c102_write_reg(cam, 0x50, 0x19); - - return err; -} - - -static struct sn9c102_sensor ov7630 = { - .name = "OV7630", - .maintainer = "Luca Risolia ", - .sysfs_ops = SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x21, - .init = &ov7630_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x14, - .flags = 0, - }, - { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "hue", - .minimum = 0x00, - .maximum = 0x1f+1, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "saturation", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x08, - .flags = 0, - }, - { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "contrast", - .minimum = 0x00, - .maximum = 0x1f+1, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x000, - .maximum = 0x3ff, - .step = 0x001, - .default_value = 0x83<<2, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x3a, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x77, - .flags = 0, - }, - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "brightness", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0xa0, - .flags = 0, - }, - { - .id = V4L2_CID_DO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "white balance background: blue", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = V4L2_CID_WHITENESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "white balance background: red", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto white balance", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x01, - .flags = 0, - }, - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain & exposure mode", - .minimum = 0x00, - .maximum = 0x03, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x01, - .flags = 0, - }, - { - .id = V4L2_CID_BLACK_LEVEL, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "black pixel ratio", - .minimum = 0x01, - .maximum = 0x9a, - .step = 0x01, - .default_value = 0x8a, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_BRIGHT_LEVEL, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "bright pixel ratio", - .minimum = 0x01, - .maximum = 0x9a, - .step = 0x01, - .default_value = 0x10, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_BAND_FILTER, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "band filter", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GAMMA, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "rgb gamma", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - }, - .set_ctrl = &ov7630_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &ov7630_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &ov7630_set_pix_format -}; - - -int sn9c102_probe_ov7630(struct sn9c102_device* cam) -{ - const struct usb_device_id ov7630_id_table[] = { - { USB_DEVICE(0x0c45, 0x602c), }, - { USB_DEVICE(0x0c45, 0x602d), }, - { USB_DEVICE(0x0c45, 0x608f), }, - { USB_DEVICE(0x0c45, 0x60b0), }, - { } - }; - int err = 0; - - if (!sn9c102_match_id(cam, ov7630_id_table)) - return -ENODEV; - - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - err += sn9c102_write_reg(cam, 0x28, 0x17); - if (err) - return -EIO; - - err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0); - if (err) - return -ENODEV; - - sn9c102_attach_sensor(cam, &ov7630); - - return 0; -} diff --git a/drivers/usb/media/sn9c102_pas106b.c b/drivers/usb/media/sn9c102_pas106b.c deleted file mode 100644 index b1dee78abe04..000000000000 --- a/drivers/usb/media/sn9c102_pas106b.c +++ /dev/null @@ -1,307 +0,0 @@ -/*************************************************************************** - * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera * - * Controllers * - * * - * Copyright (C) 2004-2006 by Luca Risolia * - * * - * 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 "sn9c102_sensor.h" - - -static struct sn9c102_sensor pas106b; - - -static int pas106b_init(struct sn9c102_device* cam) -{ - int err = 0; - - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x20, 0x19); - err += sn9c102_write_reg(cam, 0x09, 0x18); - - err += sn9c102_i2c_write(cam, 0x02, 0x0c); - err += sn9c102_i2c_write(cam, 0x05, 0x5a); - err += sn9c102_i2c_write(cam, 0x06, 0x88); - err += sn9c102_i2c_write(cam, 0x07, 0x80); - err += sn9c102_i2c_write(cam, 0x10, 0x06); - err += sn9c102_i2c_write(cam, 0x11, 0x06); - err += sn9c102_i2c_write(cam, 0x12, 0x00); - err += sn9c102_i2c_write(cam, 0x14, 0x02); - err += sn9c102_i2c_write(cam, 0x13, 0x01); - - msleep(400); - - return err; -} - - -static int pas106b_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - { - int r1 = sn9c102_i2c_read(cam, 0x03), - r2 = sn9c102_i2c_read(cam, 0x04); - if (r1 < 0 || r2 < 0) - return -EIO; - ctrl->value = (r1 << 4) | (r2 & 0x0f); - } - return 0; - case V4L2_CID_RED_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case V4L2_CID_BLUE_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case V4L2_CID_GAIN: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0e)) < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case V4L2_CID_CONTRAST: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0) - return -EIO; - ctrl->value &= 0x07; - return 0; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0a)) < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x1f) << 1; - return 0; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0) - return -EIO; - ctrl->value &= 0xf8; - return 0; - default: - return -EINVAL; - } -} - - -static int pas106b_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4); - err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x09, ctrl->value); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x0e, ctrl->value); - break; - case V4L2_CID_CONTRAST: - err += sn9c102_i2c_write(cam, 0x0f, ctrl->value); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1); - err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1); - break; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3); - break; - default: - return -EINVAL; - } - err += sn9c102_i2c_write(cam, 0x13, 0x01); - - return err ? -EIO : 0; -} - - -static int pas106b_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) -{ - struct sn9c102_sensor* s = &pas106b; - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int pas106b_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x2c, 0x17); - else - err += sn9c102_write_reg(cam, 0x20, 0x17); - - return err; -} - - -static struct sn9c102_sensor pas106b = { - .name = "PAS106B", - .maintainer = "Luca Risolia ", - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x40, - .init = &pas106b_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x125, - .maximum = 0xfff, - .step = 0x001, - .default_value = 0x140, - .flags = 0, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x0d, - .flags = 0, - }, - { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "contrast", - .minimum = 0x00, - .maximum = 0x07, - .step = 0x01, - .default_value = 0x00, /* 0x00~0x03 have same effect */ - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x04, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x06, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x3e, - .step = 0x02, - .default_value = 0x02, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "DAC magnitude", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x01, - .flags = 0, - }, - }, - .get_ctrl = &pas106b_get_ctrl, - .set_ctrl = &pas106b_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - }, - .set_crop = &pas106b_set_crop, - .pix_format = { - .width = 352, - .height = 288, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, /* we use this field as 'bits per pixel' */ - }, - .set_pix_format = &pas106b_set_pix_format -}; - - -int sn9c102_probe_pas106b(struct sn9c102_device* cam) -{ - int r0 = 0, r1 = 0, err = 0; - unsigned int pid = 0; - - /* - Minimal initialization to enable the I2C communication - NOTE: do NOT change the values! - */ - err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ - err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */ - err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */ - if (err) - return -EIO; - - r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00); - r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01); - - if (r0 < 0 || r1 < 0) - return -EIO; - - pid = (r0 << 11) | ((r1 & 0xf0) >> 4); - if (pid != 0x007) - return -ENODEV; - - sn9c102_attach_sensor(cam, &pas106b); - - return 0; -} diff --git a/drivers/usb/media/sn9c102_pas202bca.c b/drivers/usb/media/sn9c102_pas202bca.c deleted file mode 100644 index 3453237055bb..000000000000 --- a/drivers/usb/media/sn9c102_pas202bca.c +++ /dev/null @@ -1,238 +0,0 @@ -/*************************************************************************** - * Plug-in for PAS202BCA image sensor connected to the SN9C10x PC Camera * - * Controllers * - * * - * Copyright (C) 2006 by Luca Risolia * - * * - * 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 "sn9c102_sensor.h" - - -static struct sn9c102_sensor pas202bca; - - -static int pas202bca_init(struct sn9c102_device* cam) -{ - int err = 0; - - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x30, 0x19); - err += sn9c102_write_reg(cam, 0x09, 0x18); - - err += sn9c102_i2c_write(cam, 0x02, 0x14); - err += sn9c102_i2c_write(cam, 0x03, 0x40); - err += sn9c102_i2c_write(cam, 0x0d, 0x2c); - err += sn9c102_i2c_write(cam, 0x0e, 0x01); - err += sn9c102_i2c_write(cam, 0x0f, 0xa9); - err += sn9c102_i2c_write(cam, 0x10, 0x08); - err += sn9c102_i2c_write(cam, 0x13, 0x63); - err += sn9c102_i2c_write(cam, 0x15, 0x70); - err += sn9c102_i2c_write(cam, 0x11, 0x01); - - msleep(400); - - return err; -} - - -static int pas202bca_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x24, 0x17); - else - err += sn9c102_write_reg(cam, 0x20, 0x17); - - return err; -} - - -static int pas202bca_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); - err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x09, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x07, ctrl->value); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x10, ctrl->value); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_write(cam, 0x08, ctrl->value); - break; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); - break; - default: - return -EINVAL; - } - err += sn9c102_i2c_write(cam, 0x11, 0x01); - - return err ? -EIO : 0; -} - - -static int pas202bca_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) -{ - struct sn9c102_sensor* s = &pas202bca; - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static struct sn9c102_sensor pas202bca = { - .name = "PAS202BCA", - .maintainer = "Luca Risolia ", - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x40, - .init = &pas202bca_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x01e5, - .maximum = 0x3fff, - .step = 0x0001, - .default_value = 0x01e5, - .flags = 0, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x0c, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x01, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x05, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "DAC magnitude", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x04, - .flags = 0, - }, - }, - .set_ctrl = &pas202bca_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &pas202bca_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &pas202bca_set_pix_format -}; - - -int sn9c102_probe_pas202bca(struct sn9c102_device* cam) -{ - const struct usb_device_id pas202bca_id_table[] = { - { USB_DEVICE(0x0c45, 0x60af), }, - { } - }; - int err = 0; - - if (!sn9c102_match_id(cam,pas202bca_id_table)) - return -ENODEV; - - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x40, 0x01); - err += sn9c102_write_reg(cam, 0x28, 0x17); - if (err) - return -EIO; - - if (sn9c102_i2c_try_write(cam, &pas202bca, 0x10, 0)) /* try to write */ - return -ENODEV; - - sn9c102_attach_sensor(cam, &pas202bca); - - return 0; -} diff --git a/drivers/usb/media/sn9c102_pas202bcb.c b/drivers/usb/media/sn9c102_pas202bcb.c deleted file mode 100644 index d068616ab337..000000000000 --- a/drivers/usb/media/sn9c102_pas202bcb.c +++ /dev/null @@ -1,293 +0,0 @@ -/*************************************************************************** - * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera * - * Controllers * - * * - * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio * - * * - * http://cadu.homelinux.com:8080/ * - * * - * DAC Magnitude, exposure and green gain controls added by * - * Luca Risolia * - * * - * 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 "sn9c102_sensor.h" - - -static struct sn9c102_sensor pas202bcb; - - -static int pas202bcb_init(struct sn9c102_device* cam) -{ - int err = 0; - - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x30, 0x19); - err += sn9c102_write_reg(cam, 0x09, 0x18); - - err += sn9c102_i2c_write(cam, 0x02, 0x14); - err += sn9c102_i2c_write(cam, 0x03, 0x40); - err += sn9c102_i2c_write(cam, 0x0d, 0x2c); - err += sn9c102_i2c_write(cam, 0x0e, 0x01); - err += sn9c102_i2c_write(cam, 0x0f, 0xa9); - err += sn9c102_i2c_write(cam, 0x10, 0x08); - err += sn9c102_i2c_write(cam, 0x13, 0x63); - err += sn9c102_i2c_write(cam, 0x15, 0x70); - err += sn9c102_i2c_write(cam, 0x11, 0x01); - - msleep(400); - - return err; -} - - -static int pas202bcb_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - { - int r1 = sn9c102_i2c_read(cam, 0x04), - r2 = sn9c102_i2c_read(cam, 0x05); - if (r1 < 0 || r2 < 0) - return -EIO; - ctrl->value = (r1 << 6) | (r2 & 0x3f); - } - return 0; - case V4L2_CID_RED_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case V4L2_CID_BLUE_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case V4L2_CID_GAIN: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) - return -EIO; - return 0; - default: - return -EINVAL; - } -} - - -static int pas202bcb_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x24, 0x17); - else - err += sn9c102_write_reg(cam, 0x20, 0x17); - - return err; -} - - -static int pas202bcb_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); - err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x09, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x07, ctrl->value); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x10, ctrl->value); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_write(cam, 0x08, ctrl->value); - break; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); - break; - default: - return -EINVAL; - } - err += sn9c102_i2c_write(cam, 0x11, 0x01); - - return err ? -EIO : 0; -} - - -static int pas202bcb_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) -{ - struct sn9c102_sensor* s = &pas202bcb; - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static struct sn9c102_sensor pas202bcb = { - .name = "PAS202BCB", - .maintainer = "Carlos Eduardo Medaglia Dyonisio " - "", - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x40, - .init = &pas202bcb_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x01e5, - .maximum = 0x3fff, - .step = 0x0001, - .default_value = 0x01e5, - .flags = 0, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x0c, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x01, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x05, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "DAC magnitude", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x04, - .flags = 0, - }, - }, - .get_ctrl = &pas202bcb_get_ctrl, - .set_ctrl = &pas202bcb_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &pas202bcb_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &pas202bcb_set_pix_format -}; - - -int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) -{ - int r0 = 0, r1 = 0, err = 0; - unsigned int pid = 0; - - /* - * Minimal initialization to enable the I2C communication - * NOTE: do NOT change the values! - */ - err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ - err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */ - err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */ - if (err) - return -EIO; - - r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00); - r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01); - - if (r0 < 0 || r1 < 0) - return -EIO; - - pid = (r0 << 4) | ((r1 & 0xf0) >> 4); - if (pid != 0x017) - return -ENODEV; - - sn9c102_attach_sensor(cam, &pas202bcb); - - return 0; -} diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h deleted file mode 100644 index 2afd9e9d09bb..000000000000 --- a/drivers/usb/media/sn9c102_sensor.h +++ /dev/null @@ -1,389 +0,0 @@ -/*************************************************************************** - * API for image sensors connected to the SN9C10x PC Camera Controllers * - * * - * Copyright (C) 2004-2006 by Luca Risolia * - * * - * 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. * - ***************************************************************************/ - -#ifndef _SN9C102_SENSOR_H_ -#define _SN9C102_SENSOR_H_ - -#include -#include -#include -#include -#include -#include - -struct sn9c102_device; -struct sn9c102_sensor; - -/*****************************************************************************/ - -/* - OVERVIEW. - This is a small interface that allows you to add support for any CCD/CMOS - image sensors connected to the SN9C10X bridges. The entire API is documented - below. In the most general case, to support a sensor there are three steps - you have to follow: - 1) define the main "sn9c102_sensor" structure by setting the basic fields; - 2) write a probing function to be called by the core module when the USB - camera is recognized, then add both the USB ids and the name of that - function to the two corresponding tables SENSOR_TABLE and ID_TABLE (see - below); - 3) implement the methods that you want/need (and fill the rest of the main - structure accordingly). - "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do - NOT need to touch the source code of the core module for the things to work - properly, unless you find bugs or flaws in it. Finally, do not forget to - read the V4L2 API for completeness. -*/ - -/*****************************************************************************/ - -/* - Probing functions: on success, you must attach the sensor to the camera - by calling sn9c102_attach_sensor() provided below. - To enable the I2C communication, you might need to perform a really basic - initialization of the SN9C10X chip by using the write function declared - ahead. - Functions must return 0 on success, the appropriate error otherwise. -*/ -extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); -extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); -extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); -extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); -extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam); -extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); -extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); -extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); - -/* - Add the above entries to this table. Be sure to add the entry in the right - place, since, on failure, the next probing routine is called according to - the order of the list below, from top to bottom. -*/ -#define SN9C102_SENSOR_TABLE \ -static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { \ - &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ \ - &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \ - &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \ - &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \ - &sn9c102_probe_pas202bca, /* detection mostly based on USB pid/vid */ \ - &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \ - &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \ - &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \ - NULL, \ -}; - -/* Device identification */ -extern struct sn9c102_device* -sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); - -/* Attach a probed sensor to the camera. */ -extern void -sn9c102_attach_sensor(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor); - -/* - Each SN9C10x camera has proper PID/VID identifiers. - SN9C103 supports multiple interfaces, but we only handle the video class - interface. -*/ -#define SN9C102_USB_DEVICE(vend, prod, intclass) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ - USB_DEVICE_ID_MATCH_INT_CLASS, \ - .idVendor = (vend), \ - .idProduct = (prod), \ - .bInterfaceClass = (intclass) - -#define SN9C102_ID_TABLE \ -static const struct usb_device_id sn9c102_id_table[] = { \ - { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \ - { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \ - { USB_DEVICE(0x0c45, 0x6007), }, \ - { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \ - { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \ - { USB_DEVICE(0x0c45, 0x6024), }, \ - { USB_DEVICE(0x0c45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */ \ - { USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */ \ - { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \ - { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */ \ - { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \ - { USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */ \ - { USB_DEVICE(0x0c45, 0x602d), }, \ - { USB_DEVICE(0x0c45, 0x602e), }, /* OV7630 */ \ - { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x6080, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x6082, 0xff), }, /* MI0343 & MI0360 */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x6083, 0xff), }, /* HV7131[D|E1] */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x60a2, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x60a3, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x60a8, 0xff), }, /* PAS106B */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x60aa, 0xff), }, /* TAS5130D1B */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x60ab, 0xff), }, /* TAS5110C1B */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x60ac, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x60ae, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x60af, 0xff), }, /* PAS202BCB */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x60b0, 0xff), }, /* OV7630 (?) */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x60b2, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x60b3, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x60b8, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x60ba, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x60bb, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x60bc, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x60be, 0xff), }, \ - { } \ -}; - -/*****************************************************************************/ - -/* - Read/write routines: they always return -1 on error, 0 or the read value - otherwise. NOTE that a real read operation is not supported by the SN9C10X - chip for some of its registers. To work around this problem, a pseudo-read - call is provided instead: it returns the last successfully written value - on the register (0 if it has never been written), the usual -1 on error. -*/ - -/* The "try" I2C I/O versions are used when probing the sensor */ -extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*, - u8 address, u8 value); -extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, - u8 address); - -/* - These must be used if and only if the sensor doesn't implement the standard - I2C protocol. There are a number of good reasons why you must use the - single-byte versions of these functions: do not abuse. The first function - writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C10X - chip. The second one programs the registers 0x09 and 0x10 with data0 and - data1, and places the n bytes read from the sensor register table in the - buffer pointed by 'buffer'. Both the functions return -1 on error; the write - version returns 0 on success, while the read version returns the first read - byte. -*/ -extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 n, - u8 data0, u8 data1, u8 data2, u8 data3, - u8 data4, u8 data5); -extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 data0, - u8 data1, u8 n, u8 buffer[]); - -/* To be used after the sensor struct has been attached to the camera struct */ -extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value); -extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address); - -/* I/O on registers in the bridge. Could be used by the sensor methods too */ -extern int sn9c102_write_regs(struct sn9c102_device*, u8* buff, u16 index); -extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); -extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); - -/* - NOTE: there are no exported debugging functions. To uniform the output you - must use the dev_info()/dev_warn()/dev_err() macros defined in device.h, - already included here, the argument being the struct device '&usbdev->dev' - of the sensor structure. Do NOT use these macros before the sensor is - attached or the kernel will crash! However, you should not need to notify - the user about common errors or other messages, since this is done by the - master module. -*/ - -/*****************************************************************************/ - -enum sn9c102_i2c_sysfs_ops { - SN9C102_I2C_READ = 0x01, - SN9C102_I2C_WRITE = 0x02, -}; - -enum sn9c102_i2c_frequency { /* sensors may support both the frequencies */ - SN9C102_I2C_100KHZ = 0x01, - SN9C102_I2C_400KHZ = 0x02, -}; - -enum sn9c102_i2c_interface { - SN9C102_I2C_2WIRES, - SN9C102_I2C_3WIRES, -}; - -#define SN9C102_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 - -struct sn9c102_sensor { - char name[32], /* sensor name */ - maintainer[64]; /* name of the mantainer */ - - /* Supported operations through the 'sysfs' interface */ - enum sn9c102_i2c_sysfs_ops sysfs_ops; - - /* - These sensor capabilities must be provided if the SN9C10X controller - needs to communicate through the sensor serial interface by using - at least one of the i2c functions available. - */ - enum sn9c102_i2c_frequency frequency; - enum sn9c102_i2c_interface interface; - - /* - This identifier must be provided if the image sensor implements - the standard I2C protocol. - */ - u8 i2c_slave_id; /* reg. 0x09 */ - - /* - NOTE: Where not noted,most of the functions below are not mandatory. - Set to null if you do not implement them. If implemented, - they must return 0 on success, the proper error otherwise. - */ - - int (*init)(struct sn9c102_device* cam); - /* - This function will be called after the sensor has been attached. - It should be used to initialize the sensor only, but may also - configure part of the SN9C10X chip if necessary. You don't need to - setup picture settings like brightness, contrast, etc.. here, if - the corrisponding controls are implemented (see below), since - they are adjusted in the core driver by calling the set_ctrl() - method after init(), where the arguments are the default values - specified in the v4l2_queryctrl list of supported controls; - Same suggestions apply for other settings, _if_ the corresponding - methods are present; if not, the initialization must configure the - sensor according to the default configuration structures below. - */ - - struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS]; - /* - Optional list of default controls, defined as indicated in the - V4L2 API. Menu type controls are not handled by this interface. - */ - - int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl); - int (*set_ctrl)(struct sn9c102_device* cam, - const struct v4l2_control* ctrl); - /* - You must implement at least the set_ctrl method if you have defined - the list above. The returned value must follow the V4L2 - specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER - are not supported by this driver, so do not implement them. Also, - you don't have to check whether the passed values are out of bounds, - given that this is done by the core module. - */ - - struct v4l2_cropcap cropcap; - /* - Think the image sensor as a grid of R,G,B monochromatic pixels - disposed according to a particular Bayer pattern, which describes - the complete array of pixels, from (0,0) to (xmax, ymax). We will - use this coordinate system from now on. It is assumed the sensor - chip can be programmed to capture/transmit a subsection of that - array of pixels: we will call this subsection "active window". - It is not always true that the largest achievable active window can - cover the whole array of pixels. The V4L2 API defines another - area called "source rectangle", which, in turn, is a subrectangle of - the active window. The SN9C10X chip is always programmed to read the - source rectangle. - The bounds of both the active window and the source rectangle are - specified in the cropcap substructures 'bounds' and 'defrect'. - By default, the source rectangle should cover the largest possible - area. Again, it is not always true that the largest source rectangle - can cover the entire active window, although it is a rare case for - the hardware we have. The bounds of the source rectangle _must_ be - multiple of 16 and must use the same coordinate system as indicated - before; their centers shall align initially. - If necessary, the sensor chip must be initialized during init() to - set the bounds of the active sensor window; however, by default, it - usually covers the largest achievable area (maxwidth x maxheight) - of pixels, so no particular initialization is needed, if you have - defined the correct default bounds in the structures. - See the V4L2 API for further details. - NOTE: once you have defined the bounds of the active window - (struct cropcap.bounds) you must not change them.anymore. - Only 'bounds' and 'defrect' fields are mandatory, other fields - will be ignored. - */ - - int (*set_crop)(struct sn9c102_device* cam, - const struct v4l2_rect* rect); - /* - To be called on VIDIOC_C_SETCROP. The core module always calls a - default routine which configures the appropriate SN9C10X regs (also - scaling), but you may need to override/adjust specific stuff. - 'rect' contains width and height values that are multiple of 16: in - case you override the default function, you always have to program - the chip to match those values; on error return the corresponding - error code without rolling back. - NOTE: in case, you must program the SN9C10X chip to get rid of - blank pixels or blank lines at the _start_ of each line or - frame after each HSYNC or VSYNC, so that the image starts with - real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, - V_SIZE you don't have to care about blank pixels or blank - lines at the end of each line or frame). - */ - - struct v4l2_pix_format pix_format; - /* - What you have to define here are: 1) initial 'width' and 'height' of - the target rectangle 2) the initial 'pixelformat', which can be - either V4L2_PIX_FMT_SN9C10X (for compressed video) or - V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate the - number of bits per pixel for uncompressed video, 8 or 9 (despite the - current value of 'pixelformat'). - NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4 - of cropcap.defrect.width and cropcap.defrect.height. I - suggest 1/1. - NOTE 2: The initial compression quality is defined by the first bit - of reg 0x17 during the initialization of the image sensor. - NOTE 3: as said above, you have to program the SN9C10X chip to get - rid of any blank pixels, so that the output of the sensor - matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). - */ - - int (*set_pix_format)(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix); - /* - To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to - SN9C10X pixel format or viceversa. On error return the corresponding - error code without rolling back. - */ - - /* - Do NOT write to the data below, it's READ ONLY. It is used by the - core module to store successfully updated values of the above - settings, for rollbacks..etc..in case of errors during atomic I/O - */ - struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS]; - struct v4l2_rect _rect; -}; - -/*****************************************************************************/ - -/* Private ioctl's for control settings supported by some image sensors */ -#define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE -#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1 -#define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2 -#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3 -#define SN9C102_V4L2_CID_GAMMA V4L2_CID_PRIVATE_BASE + 4 -#define SN9C102_V4L2_CID_BAND_FILTER V4L2_CID_PRIVATE_BASE + 5 -#define SN9C102_V4L2_CID_BRIGHT_LEVEL V4L2_CID_PRIVATE_BASE + 6 - -#endif /* _SN9C102_SENSOR_H_ */ diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c deleted file mode 100644 index 2e08c552f40a..000000000000 --- a/drivers/usb/media/sn9c102_tas5110c1b.c +++ /dev/null @@ -1,159 +0,0 @@ -/*************************************************************************** - * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera * - * Controllers * - * * - * Copyright (C) 2004-2006 by Luca Risolia * - * * - * 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 "sn9c102_sensor.h" - - -static struct sn9c102_sensor tas5110c1b; - - -static int tas5110c1b_init(struct sn9c102_device* cam) -{ - int err = 0; - - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x44, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x0a, 0x14); - err += sn9c102_write_reg(cam, 0x60, 0x17); - err += sn9c102_write_reg(cam, 0x06, 0x18); - err += sn9c102_write_reg(cam, 0xfb, 0x19); - - err += sn9c102_i2c_write(cam, 0xc0, 0x80); - - return err; -} - - -static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int tas5110c1b_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) -{ - struct sn9c102_sensor* s = &tas5110c1b; - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - /* Don't change ! */ - err += sn9c102_write_reg(cam, 0x14, 0x1a); - err += sn9c102_write_reg(cam, 0x0a, 0x1b); - err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19); - - return err; -} - - -static int tas5110c1b_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x2b, 0x19); - else - err += sn9c102_write_reg(cam, 0xfb, 0x19); - - return err; -} - - -static struct sn9c102_sensor tas5110c1b = { - .name = "TAS5110C1B", - .maintainer = "Luca Risolia ", - .sysfs_ops = SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_3WIRES, - .init = &tas5110c1b_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0xf6, - .step = 0x01, - .default_value = 0x40, - .flags = 0, - }, - }, - .set_ctrl = &tas5110c1b_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - }, - .set_crop = &tas5110c1b_set_crop, - .pix_format = { - .width = 352, - .height = 288, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &tas5110c1b_set_pix_format -}; - - -int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) -{ - const struct usb_device_id tas5110c1b_id_table[] = { - { USB_DEVICE(0x0c45, 0x6001), }, - { USB_DEVICE(0x0c45, 0x6005), }, - { USB_DEVICE(0x0c45, 0x60ab), }, - { } - }; - - /* Sensor detection is based on USB pid/vid */ - if (!sn9c102_match_id(cam, tas5110c1b_id_table)) - return -ENODEV; - - sn9c102_attach_sensor(cam, &tas5110c1b); - - return 0; -} diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c deleted file mode 100644 index c7b339740bbf..000000000000 --- a/drivers/usb/media/sn9c102_tas5130d1b.c +++ /dev/null @@ -1,169 +0,0 @@ -/*************************************************************************** - * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera * - * Controllers * - * * - * Copyright (C) 2004-2006 by Luca Risolia * - * * - * 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 "sn9c102_sensor.h" - - -static struct sn9c102_sensor tas5130d1b; - - -static int tas5130d1b_init(struct sn9c102_device* cam) -{ - int err = 0; - - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x04, 0x01); - err += sn9c102_write_reg(cam, 0x01, 0x10); - err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); - err += sn9c102_write_reg(cam, 0x60, 0x17); - err += sn9c102_write_reg(cam, 0x07, 0x18); - - return err; -} - - -static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value); - break; - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int tas5130d1b_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) -{ - struct sn9c102_sensor* s = &tas5130d1b; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12; - int err = 0; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - /* Do NOT change! */ - err += sn9c102_write_reg(cam, 0x1f, 0x1a); - err += sn9c102_write_reg(cam, 0x1a, 0x1b); - err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19); - - return err; -} - - -static int tas5130d1b_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x63, 0x19); - else - err += sn9c102_write_reg(cam, 0xf3, 0x19); - - return err; -} - - -static struct sn9c102_sensor tas5130d1b = { - .name = "TAS5130D1B", - .maintainer = "Luca Risolia ", - .sysfs_ops = SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_3WIRES, - .init = &tas5130d1b_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0xf6, - .step = 0x02, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0x47, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - }, - .set_ctrl = &tas5130d1b_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &tas5130d1b_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &tas5130d1b_set_pix_format -}; - - -int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) -{ - const struct usb_device_id tas5130d1b_id_table[] = { - { USB_DEVICE(0x0c45, 0x6025), }, - { USB_DEVICE(0x0c45, 0x60aa), }, - { } - }; - - /* Sensor detection is based on USB pid/vid */ - if (!sn9c102_match_id(cam, tas5130d1b_id_table)) - return -ENODEV; - - sn9c102_attach_sensor(cam, &tas5130d1b); - - return 0; -} diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c deleted file mode 100644 index 9636da20748d..000000000000 --- a/drivers/usb/media/stv680.c +++ /dev/null @@ -1,1508 +0,0 @@ -/* - * STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net) - * - * Thanks to STMicroelectronics for information on the usb commands, and - * to Steve Miller at STM for his help and encouragement while I was - * writing this driver. - * - * This driver is based heavily on the - * Endpoints (formerly known as AOX) se401 USB Camera Driver - * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) - * - * Still somewhat based on the Linux ov511 driver. - * - * 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. - * - * History: - * ver 0.1 October, 2001. Initial attempt. - * - * ver 0.2 November, 2001. Fixed asbility to resize, added brightness - * function, made more stable (?) - * - * ver 0.21 Nov, 2001. Added gamma correction and white balance, - * due to Alexander Schwartz. Still trying to - * improve stablility. Moved stuff into stv680.h - * - * ver 0.22 Nov, 2001. Added sharpen function (by Michael Sweet, - * mike@easysw.com) from GIMP, also used in pencam. - * Simple, fast, good integer math routine. - * - * ver 0.23 Dec, 2001 (gkh) - * Took out sharpen function, ran code through - * Lindent, and did other minor tweaks to get - * things to work properly with 2.5.1 - * - * ver 0.24 Jan, 2002 (kjs) - * Fixed the problem with webcam crashing after - * two pictures. Changed the way pic is halved to - * improve quality. Got rid of green line around - * frame. Fix brightness reset when changing size - * bug. Adjusted gamma filters slightly. - * - * ver 0.25 Jan, 2002 (kjs) - * Fixed a bug in which the driver sometimes attempted - * to set to a non-supported size. This allowed - * gnomemeeting to work. - * Fixed proc entry removal bug. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "stv680.h" - -static int video_nr = -1; -static int swapRGB = 0; /* default for auto sleect */ -static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */ - -static unsigned int debug = 0; - -#define PDEBUG(level, fmt, args...) \ - do { \ - if (debug >= level) \ - info("[%s:%d] " fmt, __FUNCTION__, __LINE__ , ## args); \ - } while (0) - - -/* - * Version Information - */ -#define DRIVER_VERSION "v0.25" -#define DRIVER_AUTHOR "Kevin Sisson " -#define DRIVER_DESC "STV0680 USB Camera Driver" - -MODULE_AUTHOR (DRIVER_AUTHOR); -MODULE_DESCRIPTION (DRIVER_DESC); -MODULE_LICENSE ("GPL"); -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC (debug, "Debug enabled or not"); -module_param(swapRGB_on, int, 0); -MODULE_PARM_DESC (swapRGB_on, "Red/blue swap: 1=always, 0=auto, -1=never"); -module_param(video_nr, int, 0); - -/******************************************************************** - * - * Memory management - * - * This is a shameless copy from the USB-cpia driver (linux kernel - * version 2.3.29 or so, I have no idea what this code actually does ;). - * Actually it seems to be a copy of a shameless copy of the bttv-driver. - * Or that is a copy of a shameless copy of ... (To the powers: is there - * no generic kernel-function to do this sort of stuff?) - * - * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says - * there will be one, but apparentely not yet -jerdfelt - * - * So I copied it again for the ov511 driver -claudio - * - * Same for the se401 driver -Jeroen - * - * And the STV0680 driver - Kevin - ********************************************************************/ -static void *rvmalloc (unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32 (size); - if (!mem) - return NULL; - - memset (mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - return mem; -} - -static void rvfree (void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree (mem); -} - - -/********************************************************************* - * pencam read/write functions - ********************************************************************/ - -static int stv_sndctrl (int set, struct usb_stv *stv680, unsigned short req, unsigned short value, unsigned char *buffer, int size) -{ - int ret = -1; - - switch (set) { - case 0: /* 0xc1 */ - ret = usb_control_msg (stv680->udev, - usb_rcvctrlpipe (stv680->udev, 0), - req, - (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT), - value, 0, buffer, size, PENCAM_TIMEOUT); - break; - - case 1: /* 0x41 */ - ret = usb_control_msg (stv680->udev, - usb_sndctrlpipe (stv680->udev, 0), - req, - (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT), - value, 0, buffer, size, PENCAM_TIMEOUT); - break; - - case 2: /* 0x80 */ - ret = usb_control_msg (stv680->udev, - usb_rcvctrlpipe (stv680->udev, 0), - req, - (USB_DIR_IN | USB_RECIP_DEVICE), - value, 0, buffer, size, PENCAM_TIMEOUT); - break; - - case 3: /* 0x40 */ - ret = usb_control_msg (stv680->udev, - usb_sndctrlpipe (stv680->udev, 0), - req, - (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE), - value, 0, buffer, size, PENCAM_TIMEOUT); - break; - - } - if ((ret < 0) && (req != 0x0a)) { - PDEBUG (1, "STV(e): usb_control_msg error %i, request = 0x%x, error = %i", set, req, ret); - } - return ret; -} - -static int stv_set_config (struct usb_stv *dev, int configuration, int interface, int alternate) -{ - - if (configuration != dev->udev->actconfig->desc.bConfigurationValue - || usb_reset_configuration (dev->udev) < 0) { - PDEBUG (1, "STV(e): FAILED to reset configuration %i", configuration); - return -1; - } - if (usb_set_interface (dev->udev, interface, alternate) < 0) { - PDEBUG (1, "STV(e): FAILED to set alternate interface %i", alternate); - return -1; - } - return 0; -} - -static int stv_stop_video (struct usb_stv *dev) -{ - int i; - unsigned char *buf; - - buf = kmalloc (40, GFP_KERNEL); - if (buf == NULL) { - PDEBUG (0, "STV(e): Out of (small buf) memory"); - return -1; - } - - /* this is a high priority command; it stops all lower order commands */ - if ((i = stv_sndctrl (1, dev, 0x04, 0x0000, buf, 0x0)) < 0) { - i = stv_sndctrl (0, dev, 0x80, 0, buf, 0x02); /* Get Last Error; 2 = busy */ - PDEBUG (1, "STV(i): last error: %i, command = 0x%x", buf[0], buf[1]); - } else { - PDEBUG (1, "STV(i): Camera reset to idle mode."); - } - - if ((i = stv_set_config (dev, 1, 0, 0)) < 0) - PDEBUG (1, "STV(e): Reset config during exit failed"); - - /* get current mode */ - buf[0] = 0xf0; - if ((i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08)) != 0x08) /* get mode */ - PDEBUG (0, "STV(e): Stop_video: problem setting original mode"); - if (dev->origMode != buf[0]) { - memset (buf, 0, 8); - buf[0] = (unsigned char) dev->origMode; - if ((i = stv_sndctrl (3, dev, 0x07, 0x0100, buf, 0x08)) != 0x08) { - PDEBUG (0, "STV(e): Stop_video: Set_Camera_Mode failed"); - i = -1; - } - buf[0] = 0xf0; - i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08); - if ((i != 0x08) || (buf[0] != dev->origMode)) { - PDEBUG (0, "STV(e): camera NOT set to original resolution."); - i = -1; - } else - PDEBUG (0, "STV(i): Camera set to original resolution"); - } - /* origMode */ - kfree(buf); - return i; -} - -static int stv_set_video_mode (struct usb_stv *dev) -{ - int i, stop_video = 1; - unsigned char *buf; - - buf = kmalloc (40, GFP_KERNEL); - if (buf == NULL) { - PDEBUG (0, "STV(e): Out of (small buf) memory"); - return -1; - } - - if ((i = stv_set_config (dev, 1, 0, 0)) < 0) { - kfree(buf); - return i; - } - - i = stv_sndctrl (2, dev, 0x06, 0x0100, buf, 0x12); - if (!(i > 0) && (buf[8] == 0x53) && (buf[9] == 0x05)) { - PDEBUG (1, "STV(e): Could not get descriptor 0100."); - goto error; - } - - /* set alternate interface 1 */ - if ((i = stv_set_config (dev, 1, 0, 1)) < 0) - goto error; - - if ((i = stv_sndctrl (0, dev, 0x85, 0, buf, 0x10)) != 0x10) - goto error; - PDEBUG (1, "STV(i): Setting video mode."); - /* Switch to Video mode: 0x0100 = VGA (640x480), 0x0000 = CIF (352x288) 0x0300 = QVGA (320x240) */ - if ((i = stv_sndctrl (1, dev, 0x09, dev->VideoMode, buf, 0x0)) < 0) { - stop_video = 0; - goto error; - } - goto exit; - -error: - kfree(buf); - if (stop_video == 1) - stv_stop_video (dev); - return -1; - -exit: - kfree(buf); - return 0; -} - -static int stv_init (struct usb_stv *stv680) -{ - int i = 0; - unsigned char *buffer; - unsigned long int bufsize; - - buffer = kzalloc (40, GFP_KERNEL); - if (buffer == NULL) { - PDEBUG (0, "STV(e): Out of (small buf) memory"); - return -1; - } - udelay (100); - - /* set config 1, interface 0, alternate 0 */ - if ((i = stv_set_config (stv680, 1, 0, 0)) < 0) { - kfree(buffer); - PDEBUG (0, "STV(e): set config 1,0,0 failed"); - return -1; - } - /* ping camera to be sure STV0680 is present */ - if ((i = stv_sndctrl (0, stv680, 0x88, 0x5678, buffer, 0x02)) != 0x02) - goto error; - if ((buffer[0] != 0x56) || (buffer[1] != 0x78)) { - PDEBUG (1, "STV(e): camera ping failed!!"); - goto error; - } - - /* get camera descriptor */ - if ((i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x09)) != 0x09) - goto error; - i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x22); - if (!(i >= 0) && (buffer[7] == 0xa0) && (buffer[8] == 0x23)) { - PDEBUG (1, "STV(e): Could not get descriptor 0200."); - goto error; - } - if ((i = stv_sndctrl (0, stv680, 0x8a, 0, buffer, 0x02)) != 0x02) - goto error; - if ((i = stv_sndctrl (0, stv680, 0x8b, 0, buffer, 0x24)) != 0x24) - goto error; - if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10) - goto error; - - stv680->SupportedModes = buffer[7]; - i = stv680->SupportedModes; - stv680->CIF = 0; - stv680->VGA = 0; - stv680->QVGA = 0; - if (i & 1) - stv680->CIF = 1; - if (i & 2) - stv680->VGA = 1; - if (i & 8) - stv680->QVGA = 1; - if (stv680->SupportedModes == 0) { - PDEBUG (0, "STV(e): There are NO supported STV680 modes!!"); - i = -1; - goto error; - } else { - if (stv680->CIF) - PDEBUG (0, "STV(i): CIF is supported"); - if (stv680->QVGA) - PDEBUG (0, "STV(i): QVGA is supported"); - } - /* FW rev, ASIC rev, sensor ID */ - PDEBUG (1, "STV(i): Firmware rev is %i.%i", buffer[0], buffer[1]); - PDEBUG (1, "STV(i): ASIC rev is %i.%i", buffer[2], buffer[3]); - PDEBUG (1, "STV(i): Sensor ID is %i", (buffer[4]*16) + (buffer[5]>>4)); - - /* set alternate interface 1 */ - if ((i = stv_set_config (stv680, 1, 0, 1)) < 0) - goto error; - - if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10) - goto error; - if ((i = stv_sndctrl (0, stv680, 0x8d, 0, buffer, 0x08)) != 0x08) - goto error; - i = buffer[3]; - PDEBUG (0, "STV(i): Camera has %i pictures.", i); - - /* get current mode */ - if ((i = stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08)) != 0x08) - goto error; - stv680->origMode = buffer[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */ - - /* This will attemp CIF mode, if supported. If not, set to QVGA */ - memset (buffer, 0, 8); - if (stv680->CIF) - buffer[0] = 0x00; - else if (stv680->QVGA) - buffer[0] = 0x03; - if ((i = stv_sndctrl (3, stv680, 0x07, 0x0100, buffer, 0x08)) != 0x08) { - PDEBUG (0, "STV(i): Set_Camera_Mode failed"); - i = -1; - goto error; - } - buffer[0] = 0xf0; - stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08); - if (((stv680->CIF == 1) && (buffer[0] != 0x00)) || ((stv680->QVGA == 1) && (buffer[0] != 0x03))) { - PDEBUG (0, "STV(e): Error setting camera video mode!"); - i = -1; - goto error; - } else { - if (buffer[0] == 0) { - stv680->VideoMode = 0x0000; - PDEBUG (0, "STV(i): Video Mode set to CIF"); - } - if (buffer[0] == 0x03) { - stv680->VideoMode = 0x0300; - PDEBUG (0, "STV(i): Video Mode set to QVGA"); - } - } - if ((i = stv_sndctrl (0, stv680, 0x8f, 0, buffer, 0x10)) != 0x10) - goto error; - bufsize = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3]); - stv680->cwidth = (buffer[4] << 8) | (buffer[5]); /* ->camera = 322, 356, 644 */ - stv680->cheight = (buffer[6] << 8) | (buffer[7]); /* ->camera = 242, 292, 484 */ - stv680->origGain = buffer[12]; - - goto exit; - -error: - i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02); /* Get Last Error */ - PDEBUG (1, "STV(i): last error: %i, command = 0x%x", buffer[0], buffer[1]); - kfree(buffer); - return -1; - -exit: - kfree(buffer); - - /* video = 320x240, 352x288 */ - if (stv680->CIF == 1) { - stv680->maxwidth = 352; - stv680->maxheight = 288; - stv680->vwidth = 352; - stv680->vheight = 288; - } - if (stv680->QVGA == 1) { - stv680->maxwidth = 320; - stv680->maxheight = 240; - stv680->vwidth = 320; - stv680->vheight = 240; - } - - stv680->rawbufsize = bufsize; /* must be ./. by 8 */ - stv680->maxframesize = bufsize * 3; /* RGB size */ - PDEBUG (2, "STV(i): cwidth = %i, cheight = %i", stv680->cwidth, stv680->cheight); - PDEBUG (1, "STV(i): width = %i, height = %i, rawbufsize = %li", stv680->vwidth, stv680->vheight, stv680->rawbufsize); - - /* some default values */ - stv680->bulk_in_endpointAddr = 0x82; - stv680->dropped = 0; - stv680->error = 0; - stv680->framecount = 0; - stv680->readcount = 0; - stv680->streaming = 0; - /* bright, white, colour, hue, contrast are set by software, not in stv0680 */ - stv680->brightness = 32767; - stv680->chgbright = 0; - stv680->whiteness = 0; /* only for greyscale */ - stv680->colour = 32767; - stv680->contrast = 32767; - stv680->hue = 32767; - stv680->palette = STV_VIDEO_PALETTE; - stv680->depth = 24; /* rgb24 bits */ - if ((swapRGB_on == 0) && (swapRGB == 0)) - PDEBUG (1, "STV(i): swapRGB is (auto) OFF"); - else if ((swapRGB_on == 0) && (swapRGB == 1)) - PDEBUG (1, "STV(i): swapRGB is (auto) ON"); - else if (swapRGB_on == 1) - PDEBUG (1, "STV(i): swapRGB is (forced) ON"); - else if (swapRGB_on == -1) - PDEBUG (1, "STV(i): swapRGB is (forced) OFF"); - - if (stv_set_video_mode (stv680) < 0) { - PDEBUG (0, "STV(e): Could not set video mode in stv_init"); - return -1; - } - - return 0; -} - -/***************** last of pencam routines *******************/ - -/**************************************************************************** - * sysfs - ***************************************************************************/ -#define stv680_file(name, variable, field) \ -static ssize_t show_##name(struct class_device *class_dev, char *buf) \ -{ \ - struct video_device *vdev = to_video_device(class_dev); \ - struct usb_stv *stv = video_get_drvdata(vdev); \ - return sprintf(buf, field, stv->variable); \ -} \ -static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); - -stv680_file(model, camera_name, "%s\n"); -stv680_file(in_use, user, "%d\n"); -stv680_file(streaming, streaming, "%d\n"); -stv680_file(palette, palette, "%i\n"); -stv680_file(frames_total, readcount, "%d\n"); -stv680_file(frames_read, framecount, "%d\n"); -stv680_file(packets_dropped, dropped, "%d\n"); -stv680_file(decoding_errors, error, "%d\n"); - -static void stv680_create_sysfs_files(struct video_device *vdev) -{ - video_device_create_file(vdev, &class_device_attr_model); - video_device_create_file(vdev, &class_device_attr_in_use); - video_device_create_file(vdev, &class_device_attr_streaming); - video_device_create_file(vdev, &class_device_attr_palette); - video_device_create_file(vdev, &class_device_attr_frames_total); - video_device_create_file(vdev, &class_device_attr_frames_read); - video_device_create_file(vdev, &class_device_attr_packets_dropped); - video_device_create_file(vdev, &class_device_attr_decoding_errors); -} - -static void stv680_remove_sysfs_files(struct video_device *vdev) -{ - video_device_remove_file(vdev, &class_device_attr_model); - video_device_remove_file(vdev, &class_device_attr_in_use); - video_device_remove_file(vdev, &class_device_attr_streaming); - video_device_remove_file(vdev, &class_device_attr_palette); - video_device_remove_file(vdev, &class_device_attr_frames_total); - video_device_remove_file(vdev, &class_device_attr_frames_read); - video_device_remove_file(vdev, &class_device_attr_packets_dropped); - video_device_remove_file(vdev, &class_device_attr_decoding_errors); -} - -/******************************************************************** - * Camera control - *******************************************************************/ - -static int stv680_get_pict (struct usb_stv *stv680, struct video_picture *p) -{ - /* This sets values for v4l interface. max/min = 65535/0 */ - - p->brightness = stv680->brightness; - p->whiteness = stv680->whiteness; /* greyscale */ - p->colour = stv680->colour; - p->contrast = stv680->contrast; - p->hue = stv680->hue; - p->palette = stv680->palette; - p->depth = stv680->depth; - return 0; -} - -static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p) -{ - /* See above stv680_get_pict */ - - if (p->palette != STV_VIDEO_PALETTE) { - PDEBUG (2, "STV(e): Palette set error in _set_pic"); - return 1; - } - - if (stv680->brightness != p->brightness) { - stv680->chgbright = 1; - stv680->brightness = p->brightness; - } - - stv680->whiteness = p->whiteness; /* greyscale */ - stv680->colour = p->colour; - stv680->contrast = p->contrast; - stv680->hue = p->hue; - stv680->palette = p->palette; - stv680->depth = p->depth; - - return 0; -} - -static void stv680_video_irq (struct urb *urb, struct pt_regs *regs) -{ - struct usb_stv *stv680 = urb->context; - int length = urb->actual_length; - - if (length < stv680->rawbufsize) - PDEBUG (2, "STV(i): Lost data in transfer: exp %li, got %i", stv680->rawbufsize, length); - - /* ohoh... */ - if (!stv680->streaming) - return; - - if (!stv680->udev) { - PDEBUG (0, "STV(e): device vapourished in video_irq"); - return; - } - - /* 0 sized packets happen if we are to fast, but sometimes the camera - keeps sending them forever... - */ - if (length && !urb->status) { - stv680->nullpackets = 0; - switch (stv680->scratch[stv680->scratch_next].state) { - case BUFFER_READY: - case BUFFER_BUSY: - stv680->dropped++; - break; - - case BUFFER_UNUSED: - memcpy (stv680->scratch[stv680->scratch_next].data, - (unsigned char *) urb->transfer_buffer, length); - stv680->scratch[stv680->scratch_next].state = BUFFER_READY; - stv680->scratch[stv680->scratch_next].length = length; - if (waitqueue_active (&stv680->wq)) { - wake_up_interruptible (&stv680->wq); - } - stv680->scratch_overflow = 0; - stv680->scratch_next++; - if (stv680->scratch_next >= STV680_NUMSCRATCH) - stv680->scratch_next = 0; - break; - } /* switch */ - } else { - stv680->nullpackets++; - if (stv680->nullpackets > STV680_MAX_NULLPACKETS) { - if (waitqueue_active (&stv680->wq)) { - wake_up_interruptible (&stv680->wq); - } - } - } /* if - else */ - - /* Resubmit urb for new data */ - urb->status = 0; - urb->dev = stv680->udev; - if (usb_submit_urb (urb, GFP_ATOMIC)) - PDEBUG (0, "STV(e): urb burned down in video irq"); - return; -} /* _video_irq */ - -static int stv680_start_stream (struct usb_stv *stv680) -{ - struct urb *urb; - int err = 0, i; - - stv680->streaming = 1; - - /* Do some memory allocation */ - for (i = 0; i < STV680_NUMFRAMES; i++) { - stv680->frame[i].data = stv680->fbuf + i * stv680->maxframesize; - stv680->frame[i].curpix = 0; - } - /* packet size = 4096 */ - for (i = 0; i < STV680_NUMSBUF; i++) { - stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); - if (stv680->sbuf[i].data == NULL) { - PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i); - return -1; - } - } - - stv680->scratch_next = 0; - stv680->scratch_use = 0; - stv680->scratch_overflow = 0; - for (i = 0; i < STV680_NUMSCRATCH; i++) { - stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); - if (stv680->scratch[i].data == NULL) { - PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i); - return -1; - } - stv680->scratch[i].state = BUFFER_UNUSED; - } - - for (i = 0; i < STV680_NUMSBUF; i++) { - urb = usb_alloc_urb (0, GFP_KERNEL); - if (!urb) - return -ENOMEM; - - /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */ - usb_fill_bulk_urb (urb, stv680->udev, - usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr), - stv680->sbuf[i].data, stv680->rawbufsize, - stv680_video_irq, stv680); - stv680->urb[i] = urb; - err = usb_submit_urb (stv680->urb[i], GFP_KERNEL); - if (err) - PDEBUG (0, "STV(e): urb burned down in start stream"); - } /* i STV680_NUMSBUF */ - - stv680->framecount = 0; - return 0; -} - -static int stv680_stop_stream (struct usb_stv *stv680) -{ - int i; - - if (!stv680->streaming || !stv680->udev) - return 1; - - stv680->streaming = 0; - - for (i = 0; i < STV680_NUMSBUF; i++) - if (stv680->urb[i]) { - usb_kill_urb (stv680->urb[i]); - usb_free_urb (stv680->urb[i]); - stv680->urb[i] = NULL; - kfree(stv680->sbuf[i].data); - } - for (i = 0; i < STV680_NUMSCRATCH; i++) { - kfree(stv680->scratch[i].data); - stv680->scratch[i].data = NULL; - } - - return 0; -} - -static int stv680_set_size (struct usb_stv *stv680, int width, int height) -{ - int wasstreaming = stv680->streaming; - - /* Check to see if we need to change */ - if ((stv680->vwidth == width) && (stv680->vheight == height)) - return 0; - - PDEBUG (1, "STV(i): size request for %i x %i", width, height); - /* Check for a valid mode */ - if ((!width || !height) || ((width & 1) || (height & 1))) { - PDEBUG (1, "STV(e): set_size error: request: v.width = %i, v.height = %i actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight); - return 1; - } - - if ((width < (stv680->maxwidth / 2)) || (height < (stv680->maxheight / 2))) { - width = stv680->maxwidth / 2; - height = stv680->maxheight / 2; - } else if ((width >= 158) && (width <= 166) && (stv680->QVGA == 1)) { - width = 160; - height = 120; - } else if ((width >= 172) && (width <= 180) && (stv680->CIF == 1)) { - width = 176; - height = 144; - } else if ((width >= 318) && (width <= 350) && (stv680->QVGA == 1)) { - width = 320; - height = 240; - } else if ((width >= 350) && (width <= 358) && (stv680->CIF == 1)) { - width = 352; - height = 288; - } else { - PDEBUG (1, "STV(e): request for non-supported size: request: v.width = %i, v.height = %i actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight); - return 1; - } - - /* Stop a current stream and start it again at the new size */ - if (wasstreaming) - stv680_stop_stream (stv680); - stv680->vwidth = width; - stv680->vheight = height; - PDEBUG (1, "STV(i): size set to %i x %i", stv680->vwidth, stv680->vheight); - if (wasstreaming) - stv680_start_stream (stv680); - - return 0; -} - -/********************************************************************** - * Video Decoding - **********************************************************************/ - -/******* routines from the pencam program; hey, they work! ********/ - -/* - * STV0680 Vision Camera Chipset Driver - * Copyright (C) 2000 Adam Harrison -*/ - -#define RED 0 -#define GREEN 1 -#define BLUE 2 -#define AD(x, y, w) (((y)*(w)+(x))*3) - -static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buffer) -{ - int x, y, i; - int w = stv680->cwidth; - int vw = stv680->cwidth, vh = stv680->cheight; - unsigned int p = 0; - int colour = 0, bayer = 0; - unsigned char *raw = buffer->data; - struct stv680_frame *frame = &stv680->frame[stv680->curframe]; - unsigned char *output = frame->data; - unsigned char *temp = frame->data; - int offset = buffer->offset; - - if (frame->curpix == 0) { - if (frame->grabstate == FRAME_READY) { - frame->grabstate = FRAME_GRABBING; - } - } - if (offset != frame->curpix) { /* Regard frame as lost :( */ - frame->curpix = 0; - stv680->error++; - return; - } - - if ((stv680->vwidth == 320) || (stv680->vwidth == 160)) { - vw = 320; - vh = 240; - } - if ((stv680->vwidth == 352) || (stv680->vwidth == 176)) { - vw = 352; - vh = 288; - } - - memset (output, 0, 3 * vw * vh); /* clear output matrix. */ - - for (y = 0; y < vh; y++) { - for (x = 0; x < vw; x++) { - if (x & 1) - p = *(raw + y * w + (x >> 1)); - else - p = *(raw + y * w + (x >> 1) + (w >> 1)); - - if (y & 1) - bayer = 2; - else - bayer = 0; - if (x & 1) - bayer++; - - switch (bayer) { - case 0: - case 3: - colour = 1; - break; - case 1: - colour = 0; - break; - case 2: - colour = 2; - break; - } - i = (y * vw + x) * 3; - *(output + i + colour) = (unsigned char) p; - } /* for x */ - - } /* for y */ - - /****** gamma correction plus hardcoded white balance */ - /* Thanks to Alexander Schwartx for this code. - Correction values red[], green[], blue[], are generated by - (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1> 1; - *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x, y - 1, vw) + RED) + (int) *(output + AD (x, y + 1, vw) + RED)) >> 1; - break; - - case 1: /* blue. green lrtb, red diagonals */ - *(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2; - *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y - 1, vw) + RED) + (int) *(output + AD (x - 1, y + 1, vw) + RED) + (int) *(output + AD (x + 1, y - 1, vw) + RED) + (int) *(output + AD (x + 1, y + 1, vw) + RED)) >> 2; - break; - - case 2: /* red. green lrtb, blue diagonals */ - *(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2; - *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y - 1, vw) + BLUE) + (int) *(output + AD (x + 1, y - 1, vw) + BLUE) + (int) *(output + AD (x - 1, y + 1, vw) + BLUE) + (int) *(output + AD (x + 1, y + 1, vw) + BLUE)) >> 2; - break; - - case 3: /* green. red lr, blue tb */ - *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y, vw) + RED) + (int) *(output + AD (x + 1, y, vw) + RED)) >> 1; - *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x, y - 1, vw) + BLUE) + (int) *(output + AD (x, y + 1, vw) + BLUE)) >> 1; - break; - } /* switch */ - } /* for x */ - } /* for y - end demosaic */ - - /* fix top and bottom row, left and right side */ - i = vw * 3; - memcpy (output, (output + i), i); - memcpy ((output + (vh * i)), (output + ((vh - 1) * i)), i); - for (y = 0; y < vh; y++) { - i = y * vw * 3; - memcpy ((output + i), (output + i + 3), 3); - memcpy ((output + i + (vw * 3)), (output + i + (vw - 1) * 3), 3); - } - - /* process all raw data, then trim to size if necessary */ - if ((stv680->vwidth == 160) || (stv680->vwidth == 176)) { - i = 0; - for (y = 0; y < vh; y++) { - if (!(y & 1)) { - for (x = 0; x < vw; x++) { - p = (y * vw + x) * 3; - if (!(x & 1)) { - *(output + i) = *(output + p); - *(output + i + 1) = *(output + p + 1); - *(output + i + 2) = *(output + p + 2); - i += 3; - } - } /* for x */ - } - } /* for y */ - } - /* reset to proper width */ - if ((stv680->vwidth == 160)) { - vw = 160; - vh = 120; - } - if ((stv680->vwidth == 176)) { - vw = 176; - vh = 144; - } - - /* output is RGB; some programs want BGR */ - /* swapRGB_on=0 -> program decides; swapRGB_on=1, always swap */ - /* swapRGB_on=-1, never swap */ - if (((swapRGB == 1) && (swapRGB_on != -1)) || (swapRGB_on == 1)) { - for (y = 0; y < vh; y++) { - for (x = 0; x < vw; x++) { - i = (y * vw + x) * 3; - *(temp) = *(output + i); - *(output + i) = *(output + i + 2); - *(output + i + 2) = *(temp); - } - } - } - /* brightness */ - if (stv680->chgbright == 1) { - if (stv680->brightness >= 32767) { - p = (stv680->brightness - 32767) / 256; - for (x = 0; x < (vw * vh * 3); x++) { - if ((*(output + x) + (unsigned char) p) > 255) - *(output + x) = 255; - else - *(output + x) += (unsigned char) p; - } /* for */ - } else { - p = (32767 - stv680->brightness) / 256; - for (x = 0; x < (vw * vh * 3); x++) { - if ((unsigned char) p > *(output + x)) - *(output + x) = 0; - else - *(output + x) -= (unsigned char) p; - } /* for */ - } /* else */ - } - /* if */ - frame->curpix = 0; - frame->curlinepix = 0; - frame->grabstate = FRAME_DONE; - stv680->framecount++; - stv680->readcount++; - if (stv680->frame[(stv680->curframe + 1) & (STV680_NUMFRAMES - 1)].grabstate == FRAME_READY) { - stv680->curframe = (stv680->curframe + 1) & (STV680_NUMFRAMES - 1); - } - -} /* bayer_unshuffle */ - -/******* end routines from the pencam program *********/ - -static int stv680_newframe (struct usb_stv *stv680, int framenr) -{ - int errors = 0; - - while (stv680->streaming && (stv680->frame[framenr].grabstate == FRAME_READY || stv680->frame[framenr].grabstate == FRAME_GRABBING)) { - if (!stv680->frame[framenr].curpix) { - errors++; - } - wait_event_interruptible (stv680->wq, (stv680->scratch[stv680->scratch_use].state == BUFFER_READY)); - - if (stv680->nullpackets > STV680_MAX_NULLPACKETS) { - stv680->nullpackets = 0; - PDEBUG (2, "STV(i): too many null length packets, restarting capture"); - stv680_stop_stream (stv680); - stv680_start_stream (stv680); - } else { - if (stv680->scratch[stv680->scratch_use].state != BUFFER_READY) { - stv680->frame[framenr].grabstate = FRAME_ERROR; - PDEBUG (2, "STV(e): FRAME_ERROR in _newframe"); - return -EIO; - } - stv680->scratch[stv680->scratch_use].state = BUFFER_BUSY; - - bayer_unshuffle (stv680, &stv680->scratch[stv680->scratch_use]); - - stv680->scratch[stv680->scratch_use].state = BUFFER_UNUSED; - stv680->scratch_use++; - if (stv680->scratch_use >= STV680_NUMSCRATCH) - stv680->scratch_use = 0; - if (errors > STV680_MAX_ERRORS) { - errors = 0; - PDEBUG (2, "STV(i): too many errors, restarting capture"); - stv680_stop_stream (stv680); - stv680_start_stream (stv680); - } - } /* else */ - } /* while */ - return 0; -} - -/********************************************************************* - * Video4Linux - *********************************************************************/ - -static int stv_open (struct inode *inode, struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct usb_stv *stv680 = video_get_drvdata(dev); - int err = 0; - - /* we are called with the BKL held */ - stv680->user = 1; - err = stv_init (stv680); /* main initialization routine for camera */ - - if (err >= 0) { - stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES); - if (!stv680->fbuf) { - PDEBUG (0, "STV(e): Could not rvmalloc frame bufer"); - err = -ENOMEM; - } - file->private_data = dev; - } - if (err) - stv680->user = 0; - - return err; -} - -static int stv_close (struct inode *inode, struct file *file) -{ - struct video_device *dev = file->private_data; - struct usb_stv *stv680 = video_get_drvdata(dev); - int i; - - for (i = 0; i < STV680_NUMFRAMES; i++) - stv680->frame[i].grabstate = FRAME_UNUSED; - if (stv680->streaming) - stv680_stop_stream (stv680); - - if ((i = stv_stop_video (stv680)) < 0) - PDEBUG (1, "STV(e): stop_video failed in stv_close"); - - rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES); - stv680->user = 0; - - if (stv680->removed) { - kfree(stv680); - stv680 = NULL; - PDEBUG (0, "STV(i): device unregistered"); - } - file->private_data = NULL; - return 0; -} - -static int stv680_do_ioctl (struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct video_device *vdev = file->private_data; - struct usb_stv *stv680 = video_get_drvdata(vdev); - - if (!stv680->udev) - return -EIO; - - switch (cmd) { - case VIDIOCGCAP:{ - struct video_capability *b = arg; - - strcpy (b->name, stv680->camera_name); - b->type = VID_TYPE_CAPTURE; - b->channels = 1; - b->audios = 0; - b->maxwidth = stv680->maxwidth; - b->maxheight = stv680->maxheight; - b->minwidth = stv680->maxwidth / 2; - b->minheight = stv680->maxheight / 2; - return 0; - } - case VIDIOCGCHAN:{ - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - v->flags = 0; - v->tuners = 0; - v->type = VIDEO_TYPE_CAMERA; - strcpy (v->name, "STV Camera"); - return 0; - } - case VIDIOCSCHAN:{ - struct video_channel *v = arg; - if (v->channel != 0) - return -EINVAL; - return 0; - } - case VIDIOCGPICT:{ - struct video_picture *p = arg; - - stv680_get_pict (stv680, p); - return 0; - } - case VIDIOCSPICT:{ - struct video_picture *p = arg; - - if (stv680_set_pict (stv680, p)) - return -EINVAL; - return 0; - } - case VIDIOCSWIN:{ - struct video_window *vw = arg; - - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (vw->width != stv680->vwidth) { - if (stv680_set_size (stv680, vw->width, vw->height)) { - PDEBUG (2, "STV(e): failed (from user) set size in VIDIOCSWIN"); - return -EINVAL; - } - } - return 0; - } - case VIDIOCGWIN:{ - struct video_window *vw = arg; - - vw->x = 0; /* FIXME */ - vw->y = 0; - vw->chromakey = 0; - vw->flags = 0; - vw->clipcount = 0; - vw->width = stv680->vwidth; - vw->height = stv680->vheight; - return 0; - } - case VIDIOCGMBUF:{ - struct video_mbuf *vm = arg; - int i; - - memset (vm, 0, sizeof (*vm)); - vm->size = STV680_NUMFRAMES * stv680->maxframesize; - vm->frames = STV680_NUMFRAMES; - for (i = 0; i < STV680_NUMFRAMES; i++) - vm->offsets[i] = stv680->maxframesize * i; - return 0; - } - case VIDIOCMCAPTURE:{ - struct video_mmap *vm = arg; - - if (vm->format != STV_VIDEO_PALETTE) { - PDEBUG (2, "STV(i): VIDIOCMCAPTURE vm.format (%i) != VIDEO_PALETTE (%i)", - vm->format, STV_VIDEO_PALETTE); - if ((vm->format == 3) && (swapRGB_on == 0)) { - PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is (auto) ON"); - /* this may fix those apps (e.g., xawtv) that want BGR */ - swapRGB = 1; - } - return -EINVAL; - } - if (vm->frame >= STV680_NUMFRAMES) { - PDEBUG (2, "STV(e): VIDIOCMCAPTURE vm.frame > NUMFRAMES"); - return -EINVAL; - } - if ((stv680->frame[vm->frame].grabstate == FRAME_ERROR) - || (stv680->frame[vm->frame].grabstate == FRAME_GRABBING)) { - PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate (%i) error", - stv680->frame[vm->frame].grabstate); - return -EBUSY; - } - /* Is this according to the v4l spec??? */ - if (stv680->vwidth != vm->width) { - if (stv680_set_size (stv680, vm->width, vm->height)) { - PDEBUG (2, "STV(e): VIDIOCMCAPTURE set_size failed"); - return -EINVAL; - } - } - stv680->frame[vm->frame].grabstate = FRAME_READY; - - if (!stv680->streaming) - stv680_start_stream (stv680); - - return 0; - } - case VIDIOCSYNC:{ - int *frame = arg; - int ret = 0; - - if (*frame < 0 || *frame >= STV680_NUMFRAMES) { - PDEBUG (2, "STV(e): Bad frame # in VIDIOCSYNC"); - return -EINVAL; - } - ret = stv680_newframe (stv680, *frame); - stv680->frame[*frame].grabstate = FRAME_UNUSED; - return ret; - } - case VIDIOCGFBUF:{ - struct video_buffer *vb = arg; - - memset (vb, 0, sizeof (*vb)); - return 0; - } - case VIDIOCKEY: - return 0; - case VIDIOCCAPTURE: - { - PDEBUG (2, "STV(e): VIDIOCCAPTURE failed"); - return -EINVAL; - } - case VIDIOCSFBUF: - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; - } /* end switch */ - - return 0; -} - -static int stv680_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, stv680_do_ioctl); -} - -static int stv680_mmap (struct file *file, struct vm_area_struct *vma) -{ - struct video_device *dev = file->private_data; - struct usb_stv *stv680 = video_get_drvdata(dev); - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; - - mutex_lock(&stv680->lock); - - if (stv680->udev == NULL) { - mutex_unlock(&stv680->lock); - return -EIO; - } - if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1) - & ~(PAGE_SIZE - 1))) { - mutex_unlock(&stv680->lock); - return -EINVAL; - } - pos = (unsigned long) stv680->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - mutex_unlock(&stv680->lock); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - mutex_unlock(&stv680->lock); - - return 0; -} - -static ssize_t stv680_read (struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct video_device *dev = file->private_data; - unsigned long int realcount = count; - int ret = 0; - struct usb_stv *stv680 = video_get_drvdata(dev); - unsigned long int i; - - if (STV680_NUMFRAMES != 2) { - PDEBUG (0, "STV(e): STV680_NUMFRAMES needs to be 2!"); - return -1; - } - if (stv680->udev == NULL) - return -EIO; - if (realcount > (stv680->vwidth * stv680->vheight * 3)) - realcount = stv680->vwidth * stv680->vheight * 3; - - /* Shouldn't happen: */ - if (stv680->frame[0].grabstate == FRAME_GRABBING) { - PDEBUG (2, "STV(e): FRAME_GRABBING in stv680_read"); - return -EBUSY; - } - stv680->frame[0].grabstate = FRAME_READY; - stv680->frame[1].grabstate = FRAME_UNUSED; - stv680->curframe = 0; - - if (!stv680->streaming) - stv680_start_stream (stv680); - - if (!stv680->streaming) { - ret = stv680_newframe (stv680, 0); /* ret should = 0 */ - } - - ret = stv680_newframe (stv680, 0); - - if (!ret) { - if ((i = copy_to_user (buf, stv680->frame[0].data, realcount)) != 0) { - PDEBUG (2, "STV(e): copy_to_user frame 0 failed, ret count = %li", i); - return -EFAULT; - } - } else { - realcount = ret; - } - stv680->frame[0].grabstate = FRAME_UNUSED; - return realcount; -} /* stv680_read */ - -static struct file_operations stv680_fops = { - .owner = THIS_MODULE, - .open = stv_open, - .release = stv_close, - .read = stv680_read, - .mmap = stv680_mmap, - .ioctl = stv680_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, -}; -static struct video_device stv680_template = { - .owner = THIS_MODULE, - .name = "STV0680 USB camera", - .type = VID_TYPE_CAPTURE, - .hardware = VID_HARDWARE_SE401, - .fops = &stv680_fops, - .release = video_device_release, - .minor = -1, -}; - -static int stv680_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_stv *stv680 = NULL; - char *camera_name = NULL; - int retval = 0; - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) { - PDEBUG (0, "STV(e): Number of Configurations != 1"); - return -ENODEV; - } - - interface = &intf->altsetting[0]; - /* Is it a STV680? */ - if ((le16_to_cpu(dev->descriptor.idVendor) == USB_PENCAM_VENDOR_ID) && - (le16_to_cpu(dev->descriptor.idProduct) == USB_PENCAM_PRODUCT_ID)) { - camera_name = "STV0680"; - PDEBUG (0, "STV(i): STV0680 camera found."); - } else if ((le16_to_cpu(dev->descriptor.idVendor) == USB_CREATIVEGOMINI_VENDOR_ID) && - (le16_to_cpu(dev->descriptor.idProduct) == USB_CREATIVEGOMINI_PRODUCT_ID)) { - camera_name = "Creative WebCam Go Mini"; - PDEBUG (0, "STV(i): Creative WebCam Go Mini found."); - } else { - PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 or Creative WebCam Go Mini values."); - PDEBUG (0, "STV(e): Check that the STV0680 or Creative WebCam Go Mini camera is connected to the computer."); - retval = -ENODEV; - goto error; - } - /* We found one */ - if ((stv680 = kzalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) { - PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct."); - retval = -ENOMEM; - goto error; - } - - stv680->udev = dev; - stv680->camera_name = camera_name; - - stv680->vdev = video_device_alloc(); - if (!stv680->vdev) { - retval = -ENOMEM; - goto error; - } - memcpy(stv680->vdev, &stv680_template, sizeof(stv680_template)); - stv680->vdev->dev = &intf->dev; - video_set_drvdata(stv680->vdev, stv680); - - memcpy (stv680->vdev->name, stv680->camera_name, strlen (stv680->camera_name)); - init_waitqueue_head (&stv680->wq); - mutex_init (&stv680->lock); - wmb (); - - if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { - PDEBUG (0, "STV(e): video_register_device failed"); - retval = -EIO; - goto error_vdev; - } - PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev->minor); - - usb_set_intfdata (intf, stv680); - stv680_create_sysfs_files(stv680->vdev); - return 0; - -error_vdev: - video_device_release(stv680->vdev); -error: - kfree(stv680); - return retval; -} - -static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680) -{ - int i; - - stv680->udev = NULL; - stv680->frame[0].grabstate = FRAME_ERROR; - stv680->frame[1].grabstate = FRAME_ERROR; - stv680->streaming = 0; - - wake_up_interruptible (&stv680->wq); - - for (i = 0; i < STV680_NUMSBUF; i++) - if (stv680->urb[i]) { - usb_kill_urb (stv680->urb[i]); - usb_free_urb (stv680->urb[i]); - stv680->urb[i] = NULL; - kfree(stv680->sbuf[i].data); - } - for (i = 0; i < STV680_NUMSCRATCH; i++) - kfree(stv680->scratch[i].data); - PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name); - - /* Free the memory */ - kfree(stv680); -} - -static void stv680_disconnect (struct usb_interface *intf) -{ - struct usb_stv *stv680 = usb_get_intfdata (intf); - - usb_set_intfdata (intf, NULL); - - if (stv680) { - /* We don't want people trying to open up the device */ - if (stv680->vdev) { - stv680_remove_sysfs_files(stv680->vdev); - video_unregister_device(stv680->vdev); - stv680->vdev = NULL; - } - if (!stv680->user) { - usb_stv680_remove_disconnected (stv680); - } else { - stv680->removed = 1; - } - } -} - -static struct usb_driver stv680_driver = { - .name = "stv680", - .probe = stv680_probe, - .disconnect = stv680_disconnect, - .id_table = device_table -}; - -/******************************************************************** - * Module routines - ********************************************************************/ - -static int __init usb_stv680_init (void) -{ - if (usb_register (&stv680_driver) < 0) { - PDEBUG (0, "STV(e): Could not setup STV0680 driver"); - return -1; - } - PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION); - - info(DRIVER_DESC " " DRIVER_VERSION); - return 0; -} - -static void __exit usb_stv680_exit (void) -{ - usb_deregister (&stv680_driver); - PDEBUG (0, "STV(i): driver deregistered"); -} - -module_init (usb_stv680_init); -module_exit (usb_stv680_exit); diff --git a/drivers/usb/media/stv680.h b/drivers/usb/media/stv680.h deleted file mode 100644 index ea46e0001e6d..000000000000 --- a/drivers/usb/media/stv680.h +++ /dev/null @@ -1,227 +0,0 @@ -/**************************************************************************** - * - * Filename: stv680.h - * - * Description: - * This is a USB driver for STV0680 based usb video cameras. - * - * 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. - * - ****************************************************************************/ - -/* size of usb transfers */ -#define STV680_PACKETSIZE 4096 - -/* number of queued bulk transfers to use, may have problems if > 1 */ -#define STV680_NUMSBUF 1 - -/* number of frames supported by the v4l part */ -#define STV680_NUMFRAMES 2 - -/* scratch buffers for passing data to the decoders: 2 or 4 are good */ -#define STV680_NUMSCRATCH 2 - -/* number of nul sized packets to receive before kicking the camera */ -#define STV680_MAX_NULLPACKETS 200 - -/* number of decoding errors before kicking the camera */ -#define STV680_MAX_ERRORS 100 - -#define USB_PENCAM_VENDOR_ID 0x0553 -#define USB_PENCAM_PRODUCT_ID 0x0202 - -#define USB_CREATIVEGOMINI_VENDOR_ID 0x041e -#define USB_CREATIVEGOMINI_PRODUCT_ID 0x4007 - -#define PENCAM_TIMEOUT 1000 -/* fmt 4 */ -#define STV_VIDEO_PALETTE VIDEO_PALETTE_RGB24 - -static struct usb_device_id device_table[] = { - {USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)}, - {USB_DEVICE (USB_CREATIVEGOMINI_VENDOR_ID, USB_CREATIVEGOMINI_PRODUCT_ID)}, - {} -}; -MODULE_DEVICE_TABLE (usb, device_table); - -struct stv680_sbuf { - unsigned char *data; -}; - -enum { - FRAME_UNUSED, /* Unused (no MCAPTURE) */ - FRAME_READY, /* Ready to start grabbing */ - FRAME_GRABBING, /* In the process of being grabbed into */ - FRAME_DONE, /* Finished grabbing, but not been synced yet */ - FRAME_ERROR, /* Something bad happened while processing */ -}; - -enum { - BUFFER_UNUSED, - BUFFER_READY, - BUFFER_BUSY, - BUFFER_DONE, -}; - -/* raw camera data <- sbuf (urb transfer buf) */ -struct stv680_scratch { - unsigned char *data; - volatile int state; - int offset; - int length; -}; - -/* processed data for display ends up here, after bayer */ -struct stv680_frame { - unsigned char *data; /* Frame buffer */ - volatile int grabstate; /* State of grabbing */ - unsigned char *curline; - int curlinepix; - int curpix; -}; - -/* this is almost the video structure uvd_t, with extra parameters for stv */ -struct usb_stv { - struct video_device *vdev; - - struct usb_device *udev; - - unsigned char bulk_in_endpointAddr; /* __u8 the address of the bulk in endpoint */ - char *camera_name; - - unsigned int VideoMode; /* 0x0100 = VGA, 0x0000 = CIF, 0x0300 = QVGA */ - int SupportedModes; - int CIF; - int VGA; - int QVGA; - int cwidth; /* camera width */ - int cheight; /* camera height */ - int maxwidth; /* max video width */ - int maxheight; /* max video height */ - int vwidth; /* current width for video window */ - int vheight; /* current height for video window */ - unsigned long int rawbufsize; - unsigned long int maxframesize; /* rawbufsize * 3 for RGB */ - - int origGain; - int origMode; /* original camera mode */ - - struct mutex lock; /* to lock the structure */ - int user; /* user count for exclusive use */ - int removed; /* device disconnected */ - int streaming; /* Are we streaming video? */ - char *fbuf; /* Videodev buffer area */ - struct urb *urb[STV680_NUMSBUF]; /* # of queued bulk transfers */ - int curframe; /* Current receiving frame */ - struct stv680_frame frame[STV680_NUMFRAMES]; /* # frames supported by v4l part */ - int readcount; - int framecount; - int error; - int dropped; - int scratch_next; - int scratch_use; - int scratch_overflow; - struct stv680_scratch scratch[STV680_NUMSCRATCH]; /* for decoders */ - struct stv680_sbuf sbuf[STV680_NUMSBUF]; - - unsigned int brightness; - unsigned int chgbright; - unsigned int whiteness; - unsigned int colour; - unsigned int contrast; - unsigned int hue; - unsigned int palette; - unsigned int depth; /* rgb24 in bits */ - - wait_queue_head_t wq; /* Processes waiting */ - - int nullpackets; -}; - - -static const unsigned char red[256] = { - 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42, - 44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69, - 71, 71, 73, 75, 77, 78, 80, 81, 82, 84, 85, 87, - 88, 89, 90, 91, 93, 94, 95, 97, 98, 98, 99, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134, - 134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, - 143, 143, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151, - 152, 152, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159, - 159, 160, 161, 161, 161, 162, 163, 163, 164, 165, 165, 166, - 167, 167, 168, 168, 169, 170, 170, 170, 171, 171, 172, 173, - 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 179, 179, - 180, 180, 181, 181, 182, 183, 183, 184, 184, 185, 185, 186, - 187, 187, 188, 188, 188, 188, 189, 190, 190, 191, 191, 192, - 192, 193, 193, 194, 195, 195, 196, 196, 197, 197, 197, 197, - 198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 203, 204, - 204, 205, 205, 206, 206, 206, 206, 207, 207, 208, 208, 209, - 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, - 215, 215, 215, 216, 216, 217, 217, 218, 218, 218, 219, 219, - 220, 220, 221, 221 -}; - -static const unsigned char green[256] = { - 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47, - 50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77, - 79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97, - 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113, - 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, - 150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159, - 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168, - 169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177, - 177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185, - 186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, - 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200, - 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, - 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, - 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, - 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, - 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, - 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, - 239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244, - 245, 245, 246, 246 -}; - -static const unsigned char blue[256] = { - 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51, - 55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84, - 86, 88, 90, 92, 94, 95, 97, 100, 101, 103, 104, 106, - 107, 110, 111, 112, 114, 115, 116, 118, 119, 121, 122, 124, - 125, 126, 127, 128, 129, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163, - 165, 166, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, - 176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184, - 185, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, - 194, 195, 196, 196, 198, 199, 200, 200, 201, 202, 202, 203, - 204, 204, 205, 205, 206, 207, 207, 209, 210, 210, 211, 212, - 212, 213, 213, 214, 215, 215, 216, 217, 217, 218, 218, 220, - 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, - 228, 228, 229, 229, 231, 231, 232, 233, 233, 234, 234, 235, - 235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 242, 242, - 243, 243, 244, 244, 245, 246, 246, 247, 247, 248, 248, 249, - 249, 250, 250, 251, 251, 253, 253, 254, 254, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255 -}; diff --git a/drivers/usb/media/ultracam.c b/drivers/usb/media/ultracam.c deleted file mode 100644 index 75ff755224df..000000000000 --- a/drivers/usb/media/ultracam.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * USB NB Camera driver - * - * HISTORY: - * 25-Dec-2002 Dmitri Removed lighting, sharpness parameters, methods. - */ - -#include -#include -#include -#include - -#include "usbvideo.h" - -#define ULTRACAM_VENDOR_ID 0x0461 -#define ULTRACAM_PRODUCT_ID 0x0813 - -#define MAX_CAMERAS 4 /* How many devices we allow to connect */ - -/* - * This structure lives in uvd_t->user field. - */ -typedef struct { - int initialized; /* Had we already sent init sequence? */ - int camera_model; /* What type of IBM camera we got? */ - int has_hdr; -} ultracam_t; -#define ULTRACAM_T(uvd) ((ultracam_t *)((uvd)->user_data)) - -static struct usbvideo *cams = NULL; - -static int debug = 0; - -static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ - -static const int min_canvasWidth = 8; -static const int min_canvasHeight = 4; - -#define FRAMERATE_MIN 0 -#define FRAMERATE_MAX 6 -static int framerate = -1; - -/* - * Here we define several initialization variables. They may - * be used to automatically set color, hue, brightness and - * contrast to desired values. This is particularly useful in - * case of webcams (which have no controls and no on-screen - * output) and also when a client V4L software is used that - * does not have some of those controls. In any case it's - * good to have startup values as options. - * - * These values are all in [0..255] range. This simplifies - * operation. Note that actual values of V4L variables may - * be scaled up (as much as << 8). User can see that only - * on overlay output, however, or through a V4L client. - */ -static int init_brightness = 128; -static int init_contrast = 192; -static int init_color = 128; -static int init_hue = 128; -static int hue_correction = 128; - -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); -module_param(flags, int, 0); -MODULE_PARM_DESC(flags, - "Bitfield: 0=VIDIOCSYNC, " - "1=B/W, " - "2=show hints, " - "3=show stats, " - "4=test pattern, " - "5=separate frames, " - "6=clean frames"); -module_param(framerate, int, 0); -MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); - -module_param(init_brightness, int, 0); -MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); -module_param(init_contrast, int, 0); -MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); -module_param(init_color, int, 0); -MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)"); -module_param(init_hue, int, 0); -MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); -module_param(hue_correction, int, 0); -MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); - -/* - * ultracam_ProcessIsocData() - * - * Generic routine to parse the ring queue data. It employs either - * ultracam_find_header() or ultracam_parse_lines() to do most - * of work. - * - * 02-Nov-2000 First (mostly dummy) version. - * 06-Nov-2000 Rewrote to dump all data into frame. - */ -static void ultracam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame) -{ - int n; - - assert(uvd != NULL); - assert(frame != NULL); - - /* Try to move data from queue into frame buffer */ - n = RingQueue_GetLength(&uvd->dp); - if (n > 0) { - int m; - /* See how much spare we have left */ - m = uvd->max_frame_size - frame->seqRead_Length; - if (n > m) - n = m; - /* Now move that much data into frame buffer */ - RingQueue_Dequeue( - &uvd->dp, - frame->data + frame->seqRead_Length, - m); - frame->seqRead_Length += m; - } - /* See if we filled the frame */ - if (frame->seqRead_Length >= uvd->max_frame_size) { - frame->frameState = FrameState_Done; - uvd->curframe = -1; - uvd->stats.frame_num++; - } -} - -/* - * ultracam_veio() - * - * History: - * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. - */ -static int ultracam_veio( - struct uvd *uvd, - unsigned char req, - unsigned short value, - unsigned short index, - int is_out) -{ - static const char proc[] = "ultracam_veio"; - unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */; - int i; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return 0; - - if (!is_out) { - i = usb_control_msg( - uvd->dev, - usb_rcvctrlpipe(uvd->dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - cp, - sizeof(cp), - 1000); -#if 1 - info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " - "(req=$%02x val=$%04x ind=$%04x)", - cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], - req, value, index); -#endif - } else { - i = usb_control_msg( - uvd->dev, - usb_sndctrlpipe(uvd->dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - NULL, - 0, - 1000); - } - if (i < 0) { - err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.", - proc, i); - uvd->last_error = i; - } - return i; -} - -/* - * ultracam_calculate_fps() - */ -static int ultracam_calculate_fps(struct uvd *uvd) -{ - return 3 + framerate*4 + framerate/2; -} - -/* - * ultracam_adjust_contrast() - */ -static void ultracam_adjust_contrast(struct uvd *uvd) -{ -} - -/* - * ultracam_set_brightness() - * - * This procedure changes brightness of the picture. - */ -static void ultracam_set_brightness(struct uvd *uvd) -{ -} - -static void ultracam_set_hue(struct uvd *uvd) -{ -} - -/* - * ultracam_adjust_picture() - * - * This procedure gets called from V4L interface to update picture settings. - * Here we change brightness and contrast. - */ -static void ultracam_adjust_picture(struct uvd *uvd) -{ - ultracam_adjust_contrast(uvd); - ultracam_set_brightness(uvd); - ultracam_set_hue(uvd); -} - -/* - * ultracam_video_stop() - * - * This code tells camera to stop streaming. The interface remains - * configured and bandwidth - claimed. - */ -static void ultracam_video_stop(struct uvd *uvd) -{ -} - -/* - * ultracam_reinit_iso() - * - * This procedure sends couple of commands to the camera and then - * resets the video pipe. This sequence was observed to reinit the - * camera or, at least, to initiate ISO data stream. - */ -static void ultracam_reinit_iso(struct uvd *uvd, int do_stop) -{ -} - -static void ultracam_video_start(struct uvd *uvd) -{ - ultracam_reinit_iso(uvd, 0); -} - -static int ultracam_resetPipe(struct uvd *uvd) -{ - usb_clear_halt(uvd->dev, uvd->video_endp); - return 0; -} - -static int ultracam_alternateSetting(struct uvd *uvd, int setting) -{ - static const char proc[] = "ultracam_alternateSetting"; - int i; - i = usb_set_interface(uvd->dev, uvd->iface, setting); - if (i < 0) { - err("%s: usb_set_interface error", proc); - uvd->last_error = i; - return -EBUSY; - } - return 0; -} - -/* - * Return negative code on failure, 0 on success. - */ -static int ultracam_setup_on_open(struct uvd *uvd) -{ - int setup_ok = 0; /* Success by default */ - /* Send init sequence only once, it's large! */ - if (!ULTRACAM_T(uvd)->initialized) { - ultracam_alternateSetting(uvd, 0x04); - ultracam_alternateSetting(uvd, 0x00); - ultracam_veio(uvd, 0x02, 0x0004, 0x000b, 1); - ultracam_veio(uvd, 0x02, 0x0001, 0x0005, 1); - ultracam_veio(uvd, 0x02, 0x8000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0002, 1); - ultracam_veio(uvd, 0x00, 0x000c, 0x0003, 1); - ultracam_veio(uvd, 0x00, 0x000b, 0x0004, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0005, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0006, 1); - ultracam_veio(uvd, 0x00, 0x0079, 0x0007, 1); - ultracam_veio(uvd, 0x00, 0x003b, 0x0008, 1); - ultracam_veio(uvd, 0x00, 0x0002, 0x000f, 1); - ultracam_veio(uvd, 0x00, 0x0001, 0x0010, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0011, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, 1); - ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, 1); - ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, 1); - ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0010, 0x0002, 1); - ultracam_veio(uvd, 0x01, 0x0066, 0x0007, 1); - ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1); - ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1); - ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1); - ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1); - ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1); - ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1); - ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1); - ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1); - ultracam_veio(uvd, 0x01, 0x000b, 0x0011, 1); - ultracam_veio(uvd, 0x01, 0x0001, 0x0012, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0013, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0014, 1); - ultracam_veio(uvd, 0x01, 0x0087, 0x0051, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0052, 1); - ultracam_veio(uvd, 0x01, 0x0058, 0x0053, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0054, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0040, 1); - ultracam_veio(uvd, 0x01, 0x0010, 0x0041, 1); - ultracam_veio(uvd, 0x01, 0x0020, 0x0042, 1); - ultracam_veio(uvd, 0x01, 0x0030, 0x0043, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0044, 1); - ultracam_veio(uvd, 0x01, 0x0050, 0x0045, 1); - ultracam_veio(uvd, 0x01, 0x0060, 0x0046, 1); - ultracam_veio(uvd, 0x01, 0x0070, 0x0047, 1); - ultracam_veio(uvd, 0x01, 0x0080, 0x0048, 1); - ultracam_veio(uvd, 0x01, 0x0090, 0x0049, 1); - ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, 1); - ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, 1); - ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, 1); - ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, 1); - ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, 1); - ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, 1); - ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0056, 1); - ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x02, 0xc040, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0008, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x0009, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000b, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000c, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000d, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000e, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000f, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x0010, 0); - ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1); - ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1); - ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1); - ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1); - ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1); - ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1); - ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1); - ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0001, 0); - ultracam_veio(uvd, 0x01, 0x0064, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0059, 0x0051, 1); - ultracam_veio(uvd, 0x01, 0x003f, 0x0052, 1); - ultracam_veio(uvd, 0x01, 0x0094, 0x0053, 1); - ultracam_veio(uvd, 0x01, 0x00ff, 0x0011, 1); - ultracam_veio(uvd, 0x01, 0x0003, 0x0012, 1); - ultracam_veio(uvd, 0x01, 0x00f7, 0x0013, 1); - ultracam_veio(uvd, 0x00, 0x0009, 0x0011, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_alternateSetting(uvd, 0x04); - ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x0006, 1); - ultracam_veio(uvd, 0x02, 0x9000, 0x0007, 1); - ultracam_veio(uvd, 0x02, 0x0042, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x000b, 0); - ultracam_resetPipe(uvd); - ULTRACAM_T(uvd)->initialized = (setup_ok != 0); - } - return setup_ok; -} - -static void ultracam_configure_video(struct uvd *uvd) -{ - if (uvd == NULL) - return; - - RESTRICT_TO_RANGE(init_brightness, 0, 255); - RESTRICT_TO_RANGE(init_contrast, 0, 255); - RESTRICT_TO_RANGE(init_color, 0, 255); - RESTRICT_TO_RANGE(init_hue, 0, 255); - RESTRICT_TO_RANGE(hue_correction, 0, 255); - - memset(&uvd->vpic, 0, sizeof(uvd->vpic)); - memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); - - uvd->vpic.colour = init_color << 8; - uvd->vpic.hue = init_hue << 8; - uvd->vpic.brightness = init_brightness << 8; - uvd->vpic.contrast = init_contrast << 8; - uvd->vpic.whiteness = 105 << 8; /* This one isn't used */ - uvd->vpic.depth = 24; - uvd->vpic.palette = VIDEO_PALETTE_RGB24; - - memset(&uvd->vcap, 0, sizeof(uvd->vcap)); - strcpy(uvd->vcap.name, "IBM Ultra Camera"); - uvd->vcap.type = VID_TYPE_CAPTURE; - uvd->vcap.channels = 1; - uvd->vcap.audios = 0; - uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas); - uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas); - uvd->vcap.minwidth = min_canvasWidth; - uvd->vcap.minheight = min_canvasHeight; - - memset(&uvd->vchan, 0, sizeof(uvd->vchan)); - uvd->vchan.flags = 0; - uvd->vchan.tuners = 0; - uvd->vchan.channel = 0; - uvd->vchan.type = VIDEO_TYPE_CAMERA; - strcpy(uvd->vchan.name, "Camera"); -} - -/* - * ultracam_probe() - * - * This procedure queries device descriptor and accepts the interface - * if it looks like our camera. - * - * History: - * 12-Nov-2000 Reworked to comply with new probe() signature. - * 23-Jan-2001 Added compatibility with 2.2.x kernels. - */ -static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id *devid) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct uvd *uvd = NULL; - int ix, i, nas; - int actInterface=-1, inactInterface=-1, maxPS=0; - unsigned char video_ep = 0; - - if (debug >= 1) - info("ultracam_probe(%p)", intf); - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - info("IBM Ultra camera found (rev. 0x%04x)", - le16_to_cpu(dev->descriptor.bcdDevice)); - - /* Validate found interface: must have one ISO endpoint */ - nas = intf->num_altsetting; - if (debug > 0) - info("Number of alternate settings=%d.", nas); - if (nas < 8) { - err("Too few alternate settings for this camera!"); - return -ENODEV; - } - /* Validate all alternate settings */ - for (ix=0; ix < nas; ix++) { - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - - interface = &intf->altsetting[ix]; - i = interface->desc.bAlternateSetting; - if (interface->desc.bNumEndpoints != 1) { - err("Interface %d. has %u. endpoints!", - interface->desc.bInterfaceNumber, - (unsigned)(interface->desc.bNumEndpoints)); - return -ENODEV; - } - endpoint = &interface->endpoint[0].desc; - if (video_ep == 0) - video_ep = endpoint->bEndpointAddress; - else if (video_ep != endpoint->bEndpointAddress) { - err("Alternate settings have different endpoint addresses!"); - return -ENODEV; - } - if ((endpoint->bmAttributes & 0x03) != 0x01) { - err("Interface %d. has non-ISO endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if ((endpoint->bEndpointAddress & 0x80) == 0) { - err("Interface %d. has ISO OUT endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { - if (inactInterface < 0) - inactInterface = i; - else { - err("More than one inactive alt. setting!"); - return -ENODEV; - } - } else { - if (actInterface < 0) { - actInterface = i; - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - if (debug > 0) - info("Active setting=%d. maxPS=%d.", i, maxPS); - } else { - /* Got another active alt. setting */ - if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) { - /* This one is better! */ - actInterface = i; - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - if (debug > 0) { - info("Even better ctive setting=%d. maxPS=%d.", - i, maxPS); - } - } - } - } - } - if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) { - err("Failed to recognize the camera!"); - return -ENODEV; - } - - uvd = usbvideo_AllocateDevice(cams); - if (uvd != NULL) { - /* Here uvd is a fully allocated uvd object */ - uvd->flags = flags; - uvd->debug = debug; - uvd->dev = dev; - uvd->iface = intf->altsetting->desc.bInterfaceNumber; - uvd->ifaceAltInactive = inactInterface; - uvd->ifaceAltActive = actInterface; - uvd->video_endp = video_ep; - uvd->iso_packet_len = maxPS; - uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; - uvd->defaultPalette = VIDEO_PALETTE_RGB24; - uvd->canvas = VIDEOSIZE(640, 480); /* FIXME */ - uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/ - - /* Initialize ibmcam-specific data */ - assert(ULTRACAM_T(uvd) != NULL); - ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */ - ULTRACAM_T(uvd)->initialized = 0; - - ultracam_configure_video(uvd); - - i = usbvideo_RegisterVideoDevice(uvd); - if (i != 0) { - err("usbvideo_RegisterVideoDevice() failed."); - uvd = NULL; - } - } - - if (uvd) { - usb_set_intfdata (intf, uvd); - return 0; - } - return -EIO; -} - - -static struct usb_device_id id_table[] = { - { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) }, - { } /* Terminating entry */ -}; - -/* - * ultracam_init() - * - * This code is run to initialize the driver. - */ -static int __init ultracam_init(void) -{ - struct usbvideo_cb cbTbl; - memset(&cbTbl, 0, sizeof(cbTbl)); - cbTbl.probe = ultracam_probe; - cbTbl.setupOnOpen = ultracam_setup_on_open; - cbTbl.videoStart = ultracam_video_start; - cbTbl.videoStop = ultracam_video_stop; - cbTbl.processData = ultracam_ProcessIsocData; - cbTbl.postProcess = usbvideo_DeinterlaceFrame; - cbTbl.adjustPicture = ultracam_adjust_picture; - cbTbl.getFPS = ultracam_calculate_fps; - return usbvideo_register( - &cams, - MAX_CAMERAS, - sizeof(ultracam_t), - "ultracam", - &cbTbl, - THIS_MODULE, - id_table); -} - -static void __exit ultracam_cleanup(void) -{ - usbvideo_Deregister(&cams); -} - -MODULE_DEVICE_TABLE(usb, id_table); -MODULE_LICENSE("GPL"); - -module_init(ultracam_init); -module_exit(ultracam_cleanup); diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c deleted file mode 100644 index 0b51fae720a9..000000000000 --- a/drivers/usb/media/usbvideo.c +++ /dev/null @@ -1,2190 +0,0 @@ -/* - * 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; 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 -#include - -#include - -#include "usbvideo.h" - -#if defined(MAP_NR) -#define virt_to_page(v) MAP_NR(v) /* Kernels 2.2.x */ -#endif - -static int video_nr = -1; -module_param(video_nr, int, 0); - -/* - * Local prototypes. - */ -static void usbvideo_Disconnect(struct usb_interface *intf); -static void usbvideo_CameraRelease(struct uvd *uvd); - -static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); -static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma); -static int usbvideo_v4l_open(struct inode *inode, struct file *file); -static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos); -static int usbvideo_v4l_close(struct inode *inode, struct file *file); - -static int usbvideo_StartDataPump(struct uvd *uvd); -static void usbvideo_StopDataPump(struct uvd *uvd); -static int usbvideo_GetFrame(struct uvd *uvd, int frameNum); -static int usbvideo_NewFrame(struct uvd *uvd, int framenum); -static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, - struct usbvideo_frame *frame); - -/*******************************/ -/* Memory management functions */ -/*******************************/ -static void *usbvideo_rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void usbvideo_rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - -static void RingQueue_Initialize(struct RingQueue *rq) -{ - assert(rq != NULL); - init_waitqueue_head(&rq->wqh); -} - -static void RingQueue_Allocate(struct RingQueue *rq, int rqLen) -{ - /* Make sure the requested size is a power of 2 and - round up if necessary. This allows index wrapping - using masks rather than modulo */ - - int i = 1; - assert(rq != NULL); - assert(rqLen > 0); - - while(rqLen >> i) - i++; - if(rqLen != 1 << (i-1)) - rqLen = 1 << i; - - rq->length = rqLen; - rq->ri = rq->wi = 0; - rq->queue = usbvideo_rvmalloc(rq->length); - assert(rq->queue != NULL); -} - -static int RingQueue_IsAllocated(const struct RingQueue *rq) -{ - if (rq == NULL) - return 0; - return (rq->queue != NULL) && (rq->length > 0); -} - -static void RingQueue_Free(struct RingQueue *rq) -{ - assert(rq != NULL); - if (RingQueue_IsAllocated(rq)) { - usbvideo_rvfree(rq->queue, rq->length); - rq->queue = NULL; - rq->length = 0; - } -} - -int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len) -{ - int rql, toread; - - assert(rq != NULL); - assert(dst != NULL); - - rql = RingQueue_GetLength(rq); - if(!rql) - return 0; - - /* Clip requested length to available data */ - if(len > rql) - len = rql; - - toread = len; - if(rq->ri > rq->wi) { - /* Read data from tail */ - int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri; - memcpy(dst, rq->queue + rq->ri, read); - toread -= read; - dst += read; - rq->ri = (rq->ri + read) & (rq->length-1); - } - if(toread) { - /* Read data from head */ - memcpy(dst, rq->queue + rq->ri, toread); - rq->ri = (rq->ri + toread) & (rq->length-1); - } - return len; -} - -EXPORT_SYMBOL(RingQueue_Dequeue); - -int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n) -{ - int enqueued = 0; - - assert(rq != NULL); - assert(cdata != NULL); - assert(rq->length > 0); - while (n > 0) { - int m, q_avail; - - /* Calculate the largest chunk that fits the tail of the ring */ - q_avail = rq->length - rq->wi; - if (q_avail <= 0) { - rq->wi = 0; - q_avail = rq->length; - } - m = n; - assert(q_avail > 0); - if (m > q_avail) - m = q_avail; - - memcpy(rq->queue + rq->wi, cdata, m); - RING_QUEUE_ADVANCE_INDEX(rq, wi, m); - cdata += m; - enqueued += m; - n -= m; - } - return enqueued; -} - -EXPORT_SYMBOL(RingQueue_Enqueue); - -static void RingQueue_InterruptibleSleepOn(struct RingQueue *rq) -{ - assert(rq != NULL); - interruptible_sleep_on(&rq->wqh); -} - -void RingQueue_WakeUpInterruptible(struct RingQueue *rq) -{ - assert(rq != NULL); - if (waitqueue_active(&rq->wqh)) - wake_up_interruptible(&rq->wqh); -} - -EXPORT_SYMBOL(RingQueue_WakeUpInterruptible); - -void RingQueue_Flush(struct RingQueue *rq) -{ - assert(rq != NULL); - rq->ri = 0; - rq->wi = 0; -} - -EXPORT_SYMBOL(RingQueue_Flush); - - -/* - * usbvideo_VideosizeToString() - * - * This procedure converts given videosize value to readable string. - * - * History: - * 07-Aug-2000 Created. - * 19-Oct-2000 Reworked for usbvideo module. - */ -static void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs) -{ - char tmp[40]; - int n; - - n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs)); - assert(n < sizeof(tmp)); - if ((buf == NULL) || (bufLen < n)) - err("usbvideo_VideosizeToString: buffer is too small."); - else - memmove(buf, tmp, n); -} - -/* - * usbvideo_OverlayChar() - * - * History: - * 01-Feb-2000 Created. - */ -static void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame, - int x, int y, int ch) -{ - static const unsigned short digits[16] = { - 0xF6DE, /* 0 */ - 0x2492, /* 1 */ - 0xE7CE, /* 2 */ - 0xE79E, /* 3 */ - 0xB792, /* 4 */ - 0xF39E, /* 5 */ - 0xF3DE, /* 6 */ - 0xF492, /* 7 */ - 0xF7DE, /* 8 */ - 0xF79E, /* 9 */ - 0x77DA, /* a */ - 0xD75C, /* b */ - 0xF24E, /* c */ - 0xD6DC, /* d */ - 0xF34E, /* e */ - 0xF348 /* f */ - }; - unsigned short digit; - int ix, iy; - - if ((uvd == NULL) || (frame == NULL)) - return; - - if (ch >= '0' && ch <= '9') - ch -= '0'; - else if (ch >= 'A' && ch <= 'F') - ch = 10 + (ch - 'A'); - else if (ch >= 'a' && ch <= 'f') - ch = 10 + (ch - 'a'); - else - return; - digit = digits[ch]; - - for (iy=0; iy < 5; iy++) { - for (ix=0; ix < 3; ix++) { - if (digit & 0x8000) { - if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) { -/* TODO */ RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF); - } - } - digit = digit << 1; - } - } -} - -/* - * usbvideo_OverlayString() - * - * History: - * 01-Feb-2000 Created. - */ -static void usbvideo_OverlayString(struct uvd *uvd, struct usbvideo_frame *frame, - int x, int y, const char *str) -{ - while (*str) { - usbvideo_OverlayChar(uvd, frame, x, y, *str); - str++; - x += 4; /* 3 pixels character + 1 space */ - } -} - -/* - * usbvideo_OverlayStats() - * - * Overlays important debugging information. - * - * History: - * 01-Feb-2000 Created. - */ -static void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame) -{ - const int y_diff = 8; - char tmp[16]; - int x = 10, y=10; - long i, j, barLength; - const int qi_x1 = 60, qi_y1 = 10; - const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10; - - /* Call the user callback, see if we may proceed after that */ - if (VALID_CALLBACK(uvd, overlayHook)) { - if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0) - return; - } - - /* - * We draw a (mostly) hollow rectangle with qi_xxx coordinates. - * Left edge symbolizes the queue index 0; right edge symbolizes - * the full capacity of the queue. - */ - barLength = qi_x2 - qi_x1 - 2; - if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) { -/* TODO */ long u_lo, u_hi, q_used; - long m_ri, m_wi, m_lo, m_hi; - - /* - * Determine fill zones (used areas of the queue): - * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length - * - * if u_lo < 0 then there is no first filler. - */ - - q_used = RingQueue_GetLength(&uvd->dp); - if ((uvd->dp.ri + q_used) >= uvd->dp.length) { - u_hi = uvd->dp.length; - u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1); - } else { - u_hi = (q_used + uvd->dp.ri); - u_lo = -1; - } - - /* Convert byte indices into screen units */ - m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length); - m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length); - m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1; - m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length); - - for (j=qi_y1; j < (qi_y1 + qi_h); j++) { - for (i=qi_x1; i < qi_x2; i++) { - /* Draw border lines */ - if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) || - (i == qi_x1) || (i == (qi_x2 - 1))) { - RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF); - continue; - } - /* For all other points the Y coordinate does not matter */ - if ((i >= m_ri) && (i <= (m_ri + 3))) { - RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00); - } else if ((i >= m_wi) && (i <= (m_wi + 3))) { - RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00); - } else if ((i < m_lo) || ((i > m_ri) && (i < m_hi))) - RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF); - } - } - } - - sprintf(tmp, "%8lx", uvd->stats.frame_num); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.urb_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.urb_length); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.data_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.header_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.iso_skip_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.iso_err_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.colour); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.hue); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.brightness >> 8); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.contrast >> 12); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; -} - -/* - * usbvideo_ReportStatistics() - * - * This procedure prints packet and transfer statistics. - * - * History: - * 14-Jan-2000 Corrected default multiplier. - */ -static void usbvideo_ReportStatistics(const struct uvd *uvd) -{ - if ((uvd != NULL) && (uvd->stats.urb_count > 0)) { - unsigned long allPackets, badPackets, goodPackets, percent; - allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES; - badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count; - goodPackets = allPackets - badPackets; - /* Calculate percentage wisely, remember integer limits */ - assert(allPackets != 0); - if (goodPackets < (((unsigned long)-1)/100)) - percent = (100 * goodPackets) / allPackets; - else - percent = goodPackets / (allPackets / 100); - info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%", - allPackets, badPackets, percent); - if (uvd->iso_packet_len > 0) { - unsigned long allBytes, xferBytes; - char multiplier = ' '; - allBytes = allPackets * uvd->iso_packet_len; - xferBytes = uvd->stats.data_count; - assert(allBytes != 0); - if (xferBytes < (((unsigned long)-1)/100)) - percent = (100 * xferBytes) / allBytes; - else - percent = xferBytes / (allBytes / 100); - /* Scale xferBytes for easy reading */ - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'K'; - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'M'; - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'G'; - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'T'; - } - } - } - } - info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%", - xferBytes, multiplier, percent); - } - } -} - -/* - * usbvideo_TestPattern() - * - * Procedure forms a test pattern (yellow grid on blue background). - * - * Parameters: - * fullframe: if TRUE then entire frame is filled, otherwise the procedure - * continues from the current scanline. - * pmode 0: fill the frame with solid blue color (like on VCR or TV) - * 1: Draw a colored grid - * - * History: - * 01-Feb-2000 Created. - */ -void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) -{ - struct usbvideo_frame *frame; - int num_cell = 0; - int scan_length = 0; - static int num_pass = 0; - - if (uvd == NULL) { - err("%s: uvd == NULL", __FUNCTION__); - return; - } - if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { - err("%s: uvd->curframe=%d.", __FUNCTION__, uvd->curframe); - return; - } - - /* Grab the current frame */ - frame = &uvd->frame[uvd->curframe]; - - /* Optionally start at the beginning */ - if (fullframe) { - frame->curline = 0; - frame->seqRead_Length = 0; - } -#if 0 - { /* For debugging purposes only */ - char tmp[20]; - usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); - info("testpattern: frame=%s", tmp); - } -#endif - /* Form every scan line */ - for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) { - int i; - unsigned char *f = frame->data + - (VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline); - for (i=0; i < VIDEOSIZE_X(frame->request); i++) { - unsigned char cb=0x80; - unsigned char cg = 0; - unsigned char cr = 0; - - if (pmode == 1) { - if (frame->curline % 32 == 0) - cb = 0, cg = cr = 0xFF; - else if (i % 32 == 0) { - if (frame->curline % 32 == 1) - num_cell++; - cb = 0, cg = cr = 0xFF; - } else { - cb = ((num_cell*7) + num_pass) & 0xFF; - cg = ((num_cell*5) + num_pass*2) & 0xFF; - cr = ((num_cell*3) + num_pass*3) & 0xFF; - } - } else { - /* Just the blue screen */ - } - - *f++ = cb; - *f++ = cg; - *f++ = cr; - scan_length += 3; - } - } - - frame->frameState = FrameState_Done; - frame->seqRead_Length += scan_length; - ++num_pass; - - /* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */ - usbvideo_OverlayStats(uvd, frame); -} - -EXPORT_SYMBOL(usbvideo_TestPattern); - - -#ifdef DEBUG -/* - * usbvideo_HexDump() - * - * A debugging tool. Prints hex dumps. - * - * History: - * 29-Jul-2000 Added printing of offsets. - */ -void usbvideo_HexDump(const unsigned char *data, int len) -{ - const int bytes_per_line = 32; - char tmp[128]; /* 32*3 + 5 */ - int i, k; - - for (i=k=0; len > 0; i++, len--) { - if (i > 0 && ((i % bytes_per_line) == 0)) { - printk("%s\n", tmp); - k=0; - } - if ((i % bytes_per_line) == 0) - k += sprintf(&tmp[k], "%04x: ", i); - k += sprintf(&tmp[k], "%02x ", data[i]); - } - if (k > 0) - printk("%s\n", tmp); -} - -EXPORT_SYMBOL(usbvideo_HexDump); - -#endif - -/* ******************************************************************** */ - -/* XXX: this piece of crap really wants some error handling.. */ -static void usbvideo_ClientIncModCount(struct uvd *uvd) -{ - if (uvd == NULL) { - err("%s: uvd == NULL", __FUNCTION__); - return; - } - if (uvd->handle == NULL) { - err("%s: uvd->handle == NULL", __FUNCTION__); - return; - } - if (uvd->handle->md_module == NULL) { - err("%s: uvd->handle->md_module == NULL", __FUNCTION__); - return; - } - if (!try_module_get(uvd->handle->md_module)) { - err("%s: try_module_get() == 0", __FUNCTION__); - return; - } -} - -static void usbvideo_ClientDecModCount(struct uvd *uvd) -{ - if (uvd == NULL) { - err("%s: uvd == NULL", __FUNCTION__); - return; - } - if (uvd->handle == NULL) { - err("%s: uvd->handle == NULL", __FUNCTION__); - return; - } - if (uvd->handle->md_module == NULL) { - err("%s: uvd->handle->md_module == NULL", __FUNCTION__); - return; - } - module_put(uvd->handle->md_module); -} - -int usbvideo_register( - struct usbvideo **pCams, - const int num_cams, - const int num_extra, - const char *driverName, - const struct usbvideo_cb *cbTbl, - struct module *md, - const struct usb_device_id *id_table) -{ - struct usbvideo *cams; - int i, base_size, result; - - /* Check parameters for sanity */ - if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) { - err("%s: Illegal call", __FUNCTION__); - return -EINVAL; - } - - /* Check registration callback - must be set! */ - if (cbTbl->probe == NULL) { - err("%s: probe() is required!", __FUNCTION__); - return -EINVAL; - } - - base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo); - cams = (struct usbvideo *) kzalloc(base_size, GFP_KERNEL); - if (cams == NULL) { - err("Failed to allocate %d. bytes for usbvideo struct", base_size); - return -ENOMEM; - } - dbg("%s: Allocated $%p (%d. bytes) for %d. cameras", - __FUNCTION__, cams, base_size, num_cams); - - /* Copy callbacks, apply defaults for those that are not set */ - memmove(&cams->cb, cbTbl, sizeof(cams->cb)); - if (cams->cb.getFrame == NULL) - cams->cb.getFrame = usbvideo_GetFrame; - if (cams->cb.disconnect == NULL) - cams->cb.disconnect = usbvideo_Disconnect; - if (cams->cb.startDataPump == NULL) - cams->cb.startDataPump = usbvideo_StartDataPump; - if (cams->cb.stopDataPump == NULL) - cams->cb.stopDataPump = usbvideo_StopDataPump; - - cams->num_cameras = num_cams; - cams->cam = (struct uvd *) &cams[1]; - cams->md_module = md; - if (cams->md_module == NULL) - warn("%s: module == NULL!", __FUNCTION__); - mutex_init(&cams->lock); /* to 1 == available */ - - for (i = 0; i < num_cams; i++) { - struct uvd *up = &cams->cam[i]; - - up->handle = cams; - - /* Allocate user_data separately because of kmalloc's limits */ - if (num_extra > 0) { - up->user_size = num_cams * num_extra; - up->user_data = kmalloc(up->user_size, GFP_KERNEL); - if (up->user_data == NULL) { - err("%s: Failed to allocate user_data (%d. bytes)", - __FUNCTION__, up->user_size); - while (i) { - up = &cams->cam[--i]; - kfree(up->user_data); - } - kfree(cams); - return -ENOMEM; - } - dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)", - __FUNCTION__, i, up->user_data, up->user_size); - } - } - - /* - * Register ourselves with USB stack. - */ - strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown"); - cams->usbdrv.name = cams->drvName; - cams->usbdrv.probe = cams->cb.probe; - cams->usbdrv.disconnect = cams->cb.disconnect; - cams->usbdrv.id_table = id_table; - - /* - * Update global handle to usbvideo. This is very important - * because probe() can be called before usb_register() returns. - * If the handle is not yet updated then the probe() will fail. - */ - *pCams = cams; - result = usb_register(&cams->usbdrv); - if (result) { - for (i = 0; i < num_cams; i++) { - struct uvd *up = &cams->cam[i]; - kfree(up->user_data); - } - kfree(cams); - } - - return result; -} - -EXPORT_SYMBOL(usbvideo_register); - -/* - * usbvideo_Deregister() - * - * Procedure frees all usbvideo and user data structures. Be warned that - * if you had some dynamically allocated components in ->user field then - * you should free them before calling here. - */ -void usbvideo_Deregister(struct usbvideo **pCams) -{ - struct usbvideo *cams; - int i; - - if (pCams == NULL) { - err("%s: pCams == NULL", __FUNCTION__); - return; - } - cams = *pCams; - if (cams == NULL) { - err("%s: cams == NULL", __FUNCTION__); - return; - } - - dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName); - usb_deregister(&cams->usbdrv); - - dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, cams, cams->num_cameras); - for (i=0; i < cams->num_cameras; i++) { - struct uvd *up = &cams->cam[i]; - int warning = 0; - - if (up->user_data != NULL) { - if (up->user_size <= 0) - ++warning; - } else { - if (up->user_size > 0) - ++warning; - } - if (warning) { - err("%s: Warning: user_data=$%p user_size=%d.", - __FUNCTION__, up->user_data, up->user_size); - } else { - dbg("%s: Freeing %d. $%p->user_data=$%p", - __FUNCTION__, i, up, up->user_data); - kfree(up->user_data); - } - } - /* Whole array was allocated in one chunk */ - dbg("%s: Freed %d uvd structures", - __FUNCTION__, cams->num_cameras); - kfree(cams); - *pCams = NULL; -} - -EXPORT_SYMBOL(usbvideo_Deregister); - -/* - * usbvideo_Disconnect() - * - * This procedure stops all driver activity. Deallocation of - * the interface-private structure (pointed by 'ptr') is done now - * (if we don't have any open files) or later, when those files - * are closed. After that driver should be removable. - * - * This code handles surprise removal. The uvd->user is a counter which - * increments on open() and decrements on close(). If we see here that - * this counter is not 0 then we have a client who still has us opened. - * We set uvd->remove_pending flag as early as possible, and after that - * all access to the camera will gracefully fail. These failures should - * prompt client to (eventually) close the video device, and then - in - * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter. - * - * History: - * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone. - * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close() - * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). - * 19-Oct-2000 Moved to usbvideo module. - */ -static void usbvideo_Disconnect(struct usb_interface *intf) -{ - struct uvd *uvd = usb_get_intfdata (intf); - int i; - - if (uvd == NULL) { - err("%s($%p): Illegal call.", __FUNCTION__, intf); - return; - } - - usb_set_intfdata (intf, NULL); - - usbvideo_ClientIncModCount(uvd); - if (uvd->debug > 0) - info("%s(%p.)", __FUNCTION__, intf); - - mutex_lock(&uvd->lock); - uvd->remove_pending = 1; /* Now all ISO data will be ignored */ - - /* At this time we ask to cancel outstanding URBs */ - GET_CALLBACK(uvd, stopDataPump)(uvd); - - for (i=0; i < USBVIDEO_NUMSBUF; i++) - usb_free_urb(uvd->sbuf[i].urb); - - usb_put_dev(uvd->dev); - uvd->dev = NULL; /* USB device is no more */ - - video_unregister_device(&uvd->vdev); - if (uvd->debug > 0) - info("%s: Video unregistered.", __FUNCTION__); - - if (uvd->user) - info("%s: In use, disconnect pending.", __FUNCTION__); - else - usbvideo_CameraRelease(uvd); - mutex_unlock(&uvd->lock); - info("USB camera disconnected."); - - usbvideo_ClientDecModCount(uvd); -} - -/* - * usbvideo_CameraRelease() - * - * This code does final release of uvd. This happens - * after the device is disconnected -and- all clients - * closed their files. - * - * History: - * 27-Jan-2000 Created. - */ -static void usbvideo_CameraRelease(struct uvd *uvd) -{ - if (uvd == NULL) { - err("%s: Illegal call", __FUNCTION__); - return; - } - - RingQueue_Free(&uvd->dp); - if (VALID_CALLBACK(uvd, userFree)) - GET_CALLBACK(uvd, userFree)(uvd); - uvd->uvd_used = 0; /* This is atomic, no need to take mutex */ -} - -/* - * usbvideo_find_struct() - * - * This code searches the array of preallocated (static) structures - * and returns index of the first one that isn't in use. Returns -1 - * if there are no free structures. - * - * History: - * 27-Jan-2000 Created. - */ -static int usbvideo_find_struct(struct usbvideo *cams) -{ - int u, rv = -1; - - if (cams == NULL) { - err("No usbvideo handle?"); - return -1; - } - mutex_lock(&cams->lock); - for (u = 0; u < cams->num_cameras; u++) { - struct uvd *uvd = &cams->cam[u]; - if (!uvd->uvd_used) /* This one is free */ - { - uvd->uvd_used = 1; /* In use now */ - mutex_init(&uvd->lock); /* to 1 == available */ - uvd->dev = NULL; - rv = u; - break; - } - } - mutex_unlock(&cams->lock); - return rv; -} - -static struct file_operations usbvideo_fops = { - .owner = THIS_MODULE, - .open = usbvideo_v4l_open, - .release =usbvideo_v4l_close, - .read = usbvideo_v4l_read, - .mmap = usbvideo_v4l_mmap, - .ioctl = usbvideo_v4l_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, -}; -static const struct video_device usbvideo_template = { - .owner = THIS_MODULE, - .type = VID_TYPE_CAPTURE, - .hardware = VID_HARDWARE_CPIA, - .fops = &usbvideo_fops, -}; - -struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams) -{ - int i, devnum; - struct uvd *uvd = NULL; - - if (cams == NULL) { - err("No usbvideo handle?"); - return NULL; - } - - devnum = usbvideo_find_struct(cams); - if (devnum == -1) { - err("IBM USB camera driver: Too many devices!"); - return NULL; - } - uvd = &cams->cam[devnum]; - dbg("Device entry #%d. at $%p", devnum, uvd); - - /* Not relying upon caller we increase module counter ourselves */ - usbvideo_ClientIncModCount(uvd); - - mutex_lock(&uvd->lock); - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); - if (uvd->sbuf[i].urb == NULL) { - err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC); - uvd->uvd_used = 0; - uvd = NULL; - goto allocate_done; - } - } - uvd->user=0; - uvd->remove_pending = 0; - uvd->last_error = 0; - RingQueue_Initialize(&uvd->dp); - - /* Initialize video device structure */ - uvd->vdev = usbvideo_template; - sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName); - /* - * The client is free to overwrite those because we - * return control to the client's probe function right now. - */ -allocate_done: - mutex_unlock(&uvd->lock); - usbvideo_ClientDecModCount(uvd); - return uvd; -} - -EXPORT_SYMBOL(usbvideo_AllocateDevice); - -int usbvideo_RegisterVideoDevice(struct uvd *uvd) -{ - char tmp1[20], tmp2[20]; /* Buffers for printing */ - - if (uvd == NULL) { - err("%s: Illegal call.", __FUNCTION__); - return -EINVAL; - } - if (uvd->video_endp == 0) { - info("%s: No video endpoint specified; data pump disabled.", __FUNCTION__); - } - if (uvd->paletteBits == 0) { - err("%s: No palettes specified!", __FUNCTION__); - return -EINVAL; - } - if (uvd->defaultPalette == 0) { - info("%s: No default palette!", __FUNCTION__); - } - - uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * - VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL; - usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize); - usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); - - if (uvd->debug > 0) { - info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx", - __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits); - } - if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { - err("%s: video_register_device failed", __FUNCTION__); - return -EPIPE; - } - if (uvd->debug > 1) { - info("%s: video_register_device() successful", __FUNCTION__); - } - if (uvd->dev == NULL) { - err("%s: uvd->dev == NULL", __FUNCTION__); - return -EINVAL; - } - - info("%s on /dev/video%d: canvas=%s videosize=%s", - (uvd->handle != NULL) ? uvd->handle->drvName : "???", - uvd->vdev.minor, tmp2, tmp1); - - usb_get_dev(uvd->dev); - return 0; -} - -EXPORT_SYMBOL(usbvideo_RegisterVideoDevice); - -/* ******************************************************************** */ - -static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct uvd *uvd = file->private_data; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return -EFAULT; - - if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) - return -EINVAL; - - pos = (unsigned long) uvd->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - return 0; -} - -/* - * usbvideo_v4l_open() - * - * This is part of Video 4 Linux API. The driver can be opened by one - * client only (checks internal counter 'uvdser'). The procedure - * then allocates buffers needed for video processing. - * - * History: - * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the - * camera is also initialized here (once per connect), at - * expense of V4L client (it waits on open() call). - * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. - * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). - */ -static int usbvideo_v4l_open(struct inode *inode, struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct uvd *uvd = (struct uvd *) dev; - const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len; - int i, errCode = 0; - - if (uvd->debug > 1) - info("%s($%p)", __FUNCTION__, dev); - - usbvideo_ClientIncModCount(uvd); - mutex_lock(&uvd->lock); - - if (uvd->user) { - err("%s: Someone tried to open an already opened device!", __FUNCTION__); - errCode = -EBUSY; - } else { - /* Clear statistics */ - memset(&uvd->stats, 0, sizeof(uvd->stats)); - - /* Clean pointers so we know if we allocated something */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) - uvd->sbuf[i].data = NULL; - - /* Allocate memory for the frame buffers */ - uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size; - uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size); - RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE); - if ((uvd->fbuf == NULL) || - (!RingQueue_IsAllocated(&uvd->dp))) { - err("%s: Failed to allocate fbuf or dp", __FUNCTION__); - errCode = -ENOMEM; - } else { - /* Allocate all buffers */ - for (i=0; i < USBVIDEO_NUMFRAMES; i++) { - uvd->frame[i].frameState = FrameState_Unused; - uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size); - /* - * Set default sizes in case IOCTL (VIDIOCMCAPTURE) - * is not used (using read() instead). - */ - uvd->frame[i].canvas = uvd->canvas; - uvd->frame[i].seqRead_Index = 0; - } - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL); - if (uvd->sbuf[i].data == NULL) { - errCode = -ENOMEM; - break; - } - } - } - if (errCode != 0) { - /* Have to free all that memory */ - if (uvd->fbuf != NULL) { - usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); - uvd->fbuf = NULL; - } - RingQueue_Free(&uvd->dp); - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - kfree(uvd->sbuf[i].data); - uvd->sbuf[i].data = NULL; - } - } - } - - /* If so far no errors then we shall start the camera */ - if (errCode == 0) { - /* Start data pump if we have valid endpoint */ - if (uvd->video_endp != 0) - errCode = GET_CALLBACK(uvd, startDataPump)(uvd); - if (errCode == 0) { - if (VALID_CALLBACK(uvd, setupOnOpen)) { - if (uvd->debug > 1) - info("%s: setupOnOpen callback", __FUNCTION__); - errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); - if (errCode < 0) { - err("%s: setupOnOpen callback failed (%d.).", - __FUNCTION__, errCode); - } else if (uvd->debug > 1) { - info("%s: setupOnOpen callback successful", __FUNCTION__); - } - } - if (errCode == 0) { - uvd->settingsAdjusted = 0; - if (uvd->debug > 1) - info("%s: Open succeeded.", __FUNCTION__); - uvd->user++; - file->private_data = uvd; - } - } - } - mutex_unlock(&uvd->lock); - if (errCode != 0) - usbvideo_ClientDecModCount(uvd); - if (uvd->debug > 0) - info("%s: Returning %d.", __FUNCTION__, errCode); - return errCode; -} - -/* - * usbvideo_v4l_close() - * - * This is part of Video 4 Linux API. The procedure - * stops streaming and deallocates all buffers that were earlier - * allocated in usbvideo_v4l_open(). - * - * History: - * 22-Jan-2000 Moved scratch buffer deallocation here. - * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. - * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep. - */ -static int usbvideo_v4l_close(struct inode *inode, struct file *file) -{ - struct video_device *dev = file->private_data; - struct uvd *uvd = (struct uvd *) dev; - int i; - - if (uvd->debug > 1) - info("%s($%p)", __FUNCTION__, dev); - - mutex_lock(&uvd->lock); - GET_CALLBACK(uvd, stopDataPump)(uvd); - usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); - uvd->fbuf = NULL; - RingQueue_Free(&uvd->dp); - - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - kfree(uvd->sbuf[i].data); - uvd->sbuf[i].data = NULL; - } - -#if USBVIDEO_REPORT_STATS - usbvideo_ReportStatistics(uvd); -#endif - - uvd->user--; - if (uvd->remove_pending) { - if (uvd->debug > 0) - info("usbvideo_v4l_close: Final disconnect."); - usbvideo_CameraRelease(uvd); - } - mutex_unlock(&uvd->lock); - usbvideo_ClientDecModCount(uvd); - - if (uvd->debug > 1) - info("%s: Completed.", __FUNCTION__); - file->private_data = NULL; - return 0; -} - -/* - * usbvideo_v4l_ioctl() - * - * This is part of Video 4 Linux API. The procedure handles ioctl() calls. - * - * History: - * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings. - */ -static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct uvd *uvd = file->private_data; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return -EIO; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - *b = uvd->vcap; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - *v = uvd->vchan; - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - if (v->channel != 0) - return -EINVAL; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture *pic = arg; - *pic = uvd->vpic; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *pic = arg; - /* - * Use temporary 'video_picture' structure to preserve our - * own settings (such as color depth, palette) that we - * aren't allowing everyone (V4L client) to change. - */ - uvd->vpic.brightness = pic->brightness; - uvd->vpic.hue = pic->hue; - uvd->vpic.colour = pic->colour; - uvd->vpic.contrast = pic->contrast; - uvd->settingsAdjusted = 0; /* Will force new settings */ - return 0; - } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - - if(VALID_CALLBACK(uvd, setVideoMode)) { - return GET_CALLBACK(uvd, setVideoMode)(uvd, vw); - } - - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (vw->width != VIDEOSIZE_X(uvd->canvas)) - return -EINVAL; - if (vw->height != VIDEOSIZE_Y(uvd->canvas)) - return -EINVAL; - - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; - - vw->x = 0; - vw->y = 0; - vw->width = VIDEOSIZE_X(uvd->videosize); - vw->height = VIDEOSIZE_Y(uvd->videosize); - vw->chromakey = 0; - if (VALID_CALLBACK(uvd, getFPS)) - vw->flags = GET_CALLBACK(uvd, getFPS)(uvd); - else - vw->flags = 10; /* FIXME: do better! */ - return 0; - } - case VIDIOCGMBUF: - { - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0, sizeof(*vm)); - vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES; - vm->frames = USBVIDEO_NUMFRAMES; - for(i = 0; i < USBVIDEO_NUMFRAMES; i++) - vm->offsets[i] = i * uvd->max_frame_size; - - return 0; - } - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - - if (uvd->debug >= 1) { - info("VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.", - vm->frame, vm->width, vm->height, vm->format); - } - /* - * Check if the requested size is supported. If the requestor - * requests too big a frame then we may be tricked into accessing - * outside of own preallocated frame buffer (in uvd->frame). - * This will cause oops or a security hole. Theoretically, we - * could only clamp the size down to acceptable bounds, but then - * we'd need to figure out how to insert our smaller buffer into - * larger caller's buffer... this is not an easy question. So we - * here just flatly reject too large requests, assuming that the - * caller will resubmit with smaller size. Callers should know - * what size we support (returned by VIDIOCGCAP). However vidcat, - * for one, does not care and allows to ask for any size. - */ - if ((vm->width > VIDEOSIZE_X(uvd->canvas)) || - (vm->height > VIDEOSIZE_Y(uvd->canvas))) { - if (uvd->debug > 0) { - info("VIDIOCMCAPTURE: Size=%dx%d too large; " - "allowed only up to %ldx%ld", vm->width, vm->height, - VIDEOSIZE_X(uvd->canvas), VIDEOSIZE_Y(uvd->canvas)); - } - return -EINVAL; - } - /* Check if the palette is supported */ - if (((1L << vm->format) & uvd->paletteBits) == 0) { - if (uvd->debug > 0) { - info("VIDIOCMCAPTURE: format=%d. not supported" - " (paletteBits=$%08lx)", - vm->format, uvd->paletteBits); - } - return -EINVAL; - } - if ((vm->frame < 0) || (vm->frame >= USBVIDEO_NUMFRAMES)) { - err("VIDIOCMCAPTURE: vm.frame=%d. !E [0-%d]", vm->frame, USBVIDEO_NUMFRAMES-1); - return -EINVAL; - } - if (uvd->frame[vm->frame].frameState == FrameState_Grabbing) { - /* Not an error - can happen */ - } - uvd->frame[vm->frame].request = VIDEOSIZE(vm->width, vm->height); - uvd->frame[vm->frame].palette = vm->format; - - /* Mark it as ready */ - uvd->frame[vm->frame].frameState = FrameState_Ready; - - return usbvideo_NewFrame(uvd, vm->frame); - } - case VIDIOCSYNC: - { - int *frameNum = arg; - int ret; - - if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES) - return -EINVAL; - - if (uvd->debug >= 1) - info("VIDIOCSYNC: syncing to frame %d.", *frameNum); - if (uvd->flags & FLAGS_NO_DECODING) - ret = usbvideo_GetFrame(uvd, *frameNum); - else if (VALID_CALLBACK(uvd, getFrame)) { - ret = GET_CALLBACK(uvd, getFrame)(uvd, *frameNum); - if ((ret < 0) && (uvd->debug >= 1)) { - err("VIDIOCSYNC: getFrame() returned %d.", ret); - } - } else { - err("VIDIOCSYNC: getFrame is not set"); - ret = -EFAULT; - } - - /* - * The frame is in FrameState_Done_Hold state. Release it - * right now because its data is already mapped into - * the user space and it's up to the application to - * make use of it until it asks for another frame. - */ - uvd->frame[*frameNum].frameState = FrameState_Unused; - return ret; - } - case VIDIOCGFBUF: - { - struct video_buffer *vb = arg; - - memset(vb, 0, sizeof(*vb)); - return 0; - } - case VIDIOCKEY: - return 0; - - case VIDIOCCAPTURE: - return -EINVAL; - - case VIDIOCSFBUF: - - case VIDIOCGTUNER: - case VIDIOCSTUNER: - - case VIDIOCGFREQ: - case VIDIOCSFREQ: - - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, usbvideo_v4l_do_ioctl); -} - -/* - * usbvideo_v4l_read() - * - * This is mostly boring stuff. We simply ask for a frame and when it - * arrives copy all the video data from it into user space. There is - * no obvious need to override this method. - * - * History: - * 20-Oct-2000 Created. - * 01-Nov-2000 Added mutex (uvd->lock). - */ -static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct uvd *uvd = file->private_data; - int noblock = file->f_flags & O_NONBLOCK; - int frmx = -1, i; - struct usbvideo_frame *frame; - - if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL)) - return -EFAULT; - - if (uvd->debug >= 1) - info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock); - - mutex_lock(&uvd->lock); - - /* See if a frame is completed, then use it. */ - for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { - if ((uvd->frame[i].frameState == FrameState_Done) || - (uvd->frame[i].frameState == FrameState_Done_Hold) || - (uvd->frame[i].frameState == FrameState_Error)) { - frmx = i; - break; - } - } - - /* FIXME: If we don't start a frame here then who ever does? */ - if (noblock && (frmx == -1)) { - count = -EAGAIN; - goto read_done; - } - - /* - * If no FrameState_Done, look for a FrameState_Grabbing state. - * See if a frame is in process (grabbing), then use it. - * We will need to wait until it becomes cooked, of course. - */ - if (frmx == -1) { - for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { - if (uvd->frame[i].frameState == FrameState_Grabbing) { - frmx = i; - break; - } - } - } - - /* - * If no frame is active, start one. We don't care which one - * it will be, so #0 is as good as any. - * In read access mode we don't have convenience of VIDIOCMCAPTURE - * to specify the requested palette (video format) on per-frame - * basis. This means that we have to return data in -some- format - * and just hope that the client knows what to do with it. - * The default format is configured in uvd->defaultPalette field - * as one of VIDEO_PALETTE_xxx values. We stuff it into the new - * frame and initiate the frame filling process. - */ - if (frmx == -1) { - if (uvd->defaultPalette == 0) { - err("%s: No default palette; don't know what to do!", __FUNCTION__); - count = -EFAULT; - goto read_done; - } - frmx = 0; - /* - * We have no per-frame control over video size. - * Therefore we only can use whatever size was - * specified as default. - */ - uvd->frame[frmx].request = uvd->videosize; - uvd->frame[frmx].palette = uvd->defaultPalette; - uvd->frame[frmx].frameState = FrameState_Ready; - usbvideo_NewFrame(uvd, frmx); - /* Now frame 0 is supposed to start filling... */ - } - - /* - * Get a pointer to the active frame. It is either previously - * completed frame or frame in progress but not completed yet. - */ - frame = &uvd->frame[frmx]; - - /* - * Sit back & wait until the frame gets filled and postprocessed. - * If we fail to get the picture [in time] then return the error. - * In this call we specify that we want the frame to be waited for, - * postprocessed and switched into FrameState_Done_Hold state. This - * state is used to hold the frame as "fully completed" between - * subsequent partial reads of the same frame. - */ - if (frame->frameState != FrameState_Done_Hold) { - long rv = -EFAULT; - if (uvd->flags & FLAGS_NO_DECODING) - rv = usbvideo_GetFrame(uvd, frmx); - else if (VALID_CALLBACK(uvd, getFrame)) - rv = GET_CALLBACK(uvd, getFrame)(uvd, frmx); - else - err("getFrame is not set"); - if ((rv != 0) || (frame->frameState != FrameState_Done_Hold)) { - count = rv; - goto read_done; - } - } - - /* - * Copy bytes to user space. We allow for partial reads, which - * means that the user application can request read less than - * the full frame size. It is up to the application to issue - * subsequent calls until entire frame is read. - * - * First things first, make sure we don't copy more than we - * have - even if the application wants more. That would be - * a big security embarassment! - */ - if ((count + frame->seqRead_Index) > frame->seqRead_Length) - count = frame->seqRead_Length - frame->seqRead_Index; - - /* - * Copy requested amount of data to user space. We start - * copying from the position where we last left it, which - * will be zero for a new frame (not read before). - */ - if (copy_to_user(buf, frame->data + frame->seqRead_Index, count)) { - count = -EFAULT; - goto read_done; - } - - /* Update last read position */ - frame->seqRead_Index += count; - if (uvd->debug >= 1) { - err("%s: {copy} count used=%Zd, new seqRead_Index=%ld", - __FUNCTION__, count, frame->seqRead_Index); - } - - /* Finally check if the frame is done with and "release" it */ - if (frame->seqRead_Index >= frame->seqRead_Length) { - /* All data has been read */ - frame->seqRead_Index = 0; - - /* Mark it as available to be used again. */ - uvd->frame[frmx].frameState = FrameState_Unused; - if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) { - err("%s: usbvideo_NewFrame failed.", __FUNCTION__); - } - } -read_done: - mutex_unlock(&uvd->lock); - return count; -} - -/* - * Make all of the blocks of data contiguous - */ -static int usbvideo_CompressIsochronous(struct uvd *uvd, struct urb *urb) -{ - char *cdata; - int i, totlen = 0; - - for (i = 0; i < urb->number_of_packets; i++) { - int n = urb->iso_frame_desc[i].actual_length; - int st = urb->iso_frame_desc[i].status; - - cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - /* Detect and ignore errored packets */ - if (st < 0) { - if (uvd->debug >= 1) - err("Data error: packet=%d. len=%d. status=%d.", i, n, st); - uvd->stats.iso_err_count++; - continue; - } - - /* Detect and ignore empty packets */ - if (n <= 0) { - uvd->stats.iso_skip_count++; - continue; - } - totlen += n; /* Little local accounting */ - RingQueue_Enqueue(&uvd->dp, cdata, n); - } - return totlen; -} - -static void usbvideo_IsocIrq(struct urb *urb, struct pt_regs *regs) -{ - int i, ret, len; - struct uvd *uvd = urb->context; - - /* We don't want to do anything if we are about to be removed! */ - if (!CAMERA_IS_OPERATIONAL(uvd)) - return; -#if 0 - if (urb->actual_length > 0) { - info("urb=$%p status=%d. errcount=%d. length=%d.", - urb, urb->status, urb->error_count, urb->actual_length); - } else { - static int c = 0; - if (c++ % 100 == 0) - info("No Isoc data"); - } -#endif - - if (!uvd->streaming) { - if (uvd->debug >= 1) - info("Not streaming, but interrupt!"); - return; - } - - uvd->stats.urb_count++; - if (urb->actual_length <= 0) - goto urb_done_with; - - /* Copy the data received into ring queue */ - len = usbvideo_CompressIsochronous(uvd, urb); - uvd->stats.urb_length = len; - if (len <= 0) - goto urb_done_with; - - /* Here we got some data */ - uvd->stats.data_count += len; - RingQueue_WakeUpInterruptible(&uvd->dp); - -urb_done_with: - for (i = 0; i < FRAMES_PER_DESC; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - urb->status = 0; - urb->dev = uvd->dev; - ret = usb_submit_urb (urb, GFP_KERNEL); - if(ret) - err("usb_submit_urb error (%d)", ret); - return; -} - -/* - * usbvideo_StartDataPump() - * - * History: - * 27-Jan-2000 Used ibmcam->iface, ibmcam->ifaceAltActive instead - * of hardcoded values. Simplified by using for loop, - * allowed any number of URBs. - */ -static int usbvideo_StartDataPump(struct uvd *uvd) -{ - struct usb_device *dev = uvd->dev; - int i, errFlag; - - if (uvd->debug > 1) - info("%s($%p)", __FUNCTION__, uvd); - - if (!CAMERA_IS_OPERATIONAL(uvd)) { - err("%s: Camera is not operational", __FUNCTION__); - return -EFAULT; - } - uvd->curframe = -1; - - /* Alternate interface 1 is is the biggest frame size */ - i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); - if (i < 0) { - err("%s: usb_set_interface error", __FUNCTION__); - uvd->last_error = i; - return -EBUSY; - } - if (VALID_CALLBACK(uvd, videoStart)) - GET_CALLBACK(uvd, videoStart)(uvd); - else - err("%s: videoStart not set", __FUNCTION__); - - /* We double buffer the Iso lists */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - int j, k; - struct urb *urb = uvd->sbuf[i].urb; - urb->dev = dev; - urb->context = uvd; - urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); - urb->interval = 1; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = uvd->sbuf[i].data; - urb->complete = usbvideo_IsocIrq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC; - for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = uvd->iso_packet_len; - } - } - - /* Submit all URBs */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); - if (errFlag) - err("%s: usb_submit_isoc(%d) ret %d", __FUNCTION__, i, errFlag); - } - - uvd->streaming = 1; - if (uvd->debug > 1) - info("%s: streaming=1 video_endp=$%02x", __FUNCTION__, uvd->video_endp); - return 0; -} - -/* - * usbvideo_StopDataPump() - * - * This procedure stops streaming and deallocates URBs. Then it - * activates zero-bandwidth alt. setting of the video interface. - * - * History: - * 22-Jan-2000 Corrected order of actions to work after surprise removal. - * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values. - */ -static void usbvideo_StopDataPump(struct uvd *uvd) -{ - int i, j; - - if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) - return; - - if (uvd->debug > 1) - info("%s($%p)", __FUNCTION__, uvd); - - /* Unschedule all of the iso td's */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - usb_kill_urb(uvd->sbuf[i].urb); - } - if (uvd->debug > 1) - info("%s: streaming=0", __FUNCTION__); - uvd->streaming = 0; - - if (!uvd->remove_pending) { - /* Invoke minidriver's magic to stop the camera */ - if (VALID_CALLBACK(uvd, videoStop)) - GET_CALLBACK(uvd, videoStop)(uvd); - else - err("%s: videoStop not set", __FUNCTION__); - - /* Set packet size to 0 */ - j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); - if (j < 0) { - err("%s: usb_set_interface() error %d.", __FUNCTION__, j); - uvd->last_error = j; - } - } -} - -/* - * usbvideo_NewFrame() - * - * History: - * 29-Mar-00 Added copying of previous frame into the current one. - * 6-Aug-00 Added model 3 video sizes, removed redundant width, height. - */ -static int usbvideo_NewFrame(struct uvd *uvd, int framenum) -{ - struct usbvideo_frame *frame; - int n; - - if (uvd->debug > 1) - info("usbvideo_NewFrame($%p,%d.)", uvd, framenum); - - /* If we're not grabbing a frame right now and the other frame is */ - /* ready to be grabbed into, then use it instead */ - if (uvd->curframe != -1) - return 0; - - /* If necessary we adjust picture settings between frames */ - if (!uvd->settingsAdjusted) { - if (VALID_CALLBACK(uvd, adjustPicture)) - GET_CALLBACK(uvd, adjustPicture)(uvd); - uvd->settingsAdjusted = 1; - } - - n = (framenum + 1) % USBVIDEO_NUMFRAMES; - if (uvd->frame[n].frameState == FrameState_Ready) - framenum = n; - - frame = &uvd->frame[framenum]; - - frame->frameState = FrameState_Grabbing; - frame->scanstate = ScanState_Scanning; - frame->seqRead_Length = 0; /* Accumulated in xxx_parse_data() */ - frame->deinterlace = Deinterlace_None; - frame->flags = 0; /* No flags yet, up to minidriver (or us) to set them */ - uvd->curframe = framenum; - - /* - * Normally we would want to copy previous frame into the current one - * before we even start filling it with data; this allows us to stop - * filling at any moment; top portion of the frame will be new and - * bottom portion will stay as it was in previous frame. If we don't - * do that then missing chunks of video stream will result in flickering - * portions of old data whatever it was before. - * - * If we choose not to copy previous frame (to, for example, save few - * bus cycles - the frame can be pretty large!) then we have an option - * to clear the frame before using. If we experience losses in this - * mode then missing picture will be black (no flickering). - * - * Finally, if user chooses not to clean the current frame before - * filling it with data then the old data will be visible if we fail - * to refill entire frame with new data. - */ - if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) { - /* This copies previous frame into this one to mask losses */ - int prev = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES; - memmove(frame->data, uvd->frame[prev].data, uvd->max_frame_size); - } else { - if (uvd->flags & FLAGS_CLEAN_FRAMES) { - /* This provides a "clean" frame but slows things down */ - memset(frame->data, 0, uvd->max_frame_size); - } - } - return 0; -} - -/* - * usbvideo_CollectRawData() - * - * This procedure can be used instead of 'processData' callback if you - * only want to dump the raw data from the camera into the output - * device (frame buffer). You can look at it with V4L client, but the - * image will be unwatchable. The main purpose of this code and of the - * mode FLAGS_NO_DECODING is debugging and capturing of datastreams from - * new, unknown cameras. This procedure will be automatically invoked - * instead of the specified callback handler when uvd->flags has bit - * FLAGS_NO_DECODING set. Therefore, any regular build of any driver - * based on usbvideo can use this feature at any time. - */ -static void usbvideo_CollectRawData(struct uvd *uvd, struct usbvideo_frame *frame) -{ - int n; - - assert(uvd != NULL); - assert(frame != NULL); - - /* Try to move data from queue into frame buffer */ - n = RingQueue_GetLength(&uvd->dp); - if (n > 0) { - int m; - /* See how much space we have left */ - m = uvd->max_frame_size - frame->seqRead_Length; - if (n > m) - n = m; - /* Now move that much data into frame buffer */ - RingQueue_Dequeue( - &uvd->dp, - frame->data + frame->seqRead_Length, - m); - frame->seqRead_Length += m; - } - /* See if we filled the frame */ - if (frame->seqRead_Length >= uvd->max_frame_size) { - frame->frameState = FrameState_Done; - uvd->curframe = -1; - uvd->stats.frame_num++; - } -} - -static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) -{ - struct usbvideo_frame *frame = &uvd->frame[frameNum]; - - if (uvd->debug >= 2) - info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum); - - switch (frame->frameState) { - case FrameState_Unused: - if (uvd->debug >= 2) - info("%s: FrameState_Unused", __FUNCTION__); - return -EINVAL; - case FrameState_Ready: - case FrameState_Grabbing: - case FrameState_Error: - { - int ntries, signalPending; - redo: - if (!CAMERA_IS_OPERATIONAL(uvd)) { - if (uvd->debug >= 2) - info("%s: Camera is not operational (1)", __FUNCTION__); - return -EIO; - } - ntries = 0; - do { - RingQueue_InterruptibleSleepOn(&uvd->dp); - signalPending = signal_pending(current); - if (!CAMERA_IS_OPERATIONAL(uvd)) { - if (uvd->debug >= 2) - info("%s: Camera is not operational (2)", __FUNCTION__); - return -EIO; - } - assert(uvd->fbuf != NULL); - if (signalPending) { - if (uvd->debug >= 2) - info("%s: Signal=$%08x", __FUNCTION__, signalPending); - if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { - usbvideo_TestPattern(uvd, 1, 0); - uvd->curframe = -1; - uvd->stats.frame_num++; - if (uvd->debug >= 2) - info("%s: Forced test pattern screen", __FUNCTION__); - return 0; - } else { - /* Standard answer: Interrupted! */ - if (uvd->debug >= 2) - info("%s: Interrupted!", __FUNCTION__); - return -EINTR; - } - } else { - /* No signals - we just got new data in dp queue */ - if (uvd->flags & FLAGS_NO_DECODING) - usbvideo_CollectRawData(uvd, frame); - else if (VALID_CALLBACK(uvd, processData)) - GET_CALLBACK(uvd, processData)(uvd, frame); - else - err("%s: processData not set", __FUNCTION__); - } - } while (frame->frameState == FrameState_Grabbing); - if (uvd->debug >= 2) { - info("%s: Grabbing done; state=%d. (%lu. bytes)", - __FUNCTION__, frame->frameState, frame->seqRead_Length); - } - if (frame->frameState == FrameState_Error) { - int ret = usbvideo_NewFrame(uvd, frameNum); - if (ret < 0) { - err("%s: usbvideo_NewFrame() failed (%d.)", __FUNCTION__, ret); - return ret; - } - goto redo; - } - /* Note that we fall through to meet our destiny below */ - } - case FrameState_Done: - /* - * Do all necessary postprocessing of data prepared in - * "interrupt" code and the collecting code above. The - * frame gets marked as FrameState_Done by queue parsing code. - * This status means that we collected enough data and - * most likely processed it as we went through. However - * the data may need postprocessing, such as deinterlacing - * or picture adjustments implemented in software (horror!) - * - * As soon as the frame becomes "final" it gets promoted to - * FrameState_Done_Hold status where it will remain until the - * caller consumed all the video data from the frame. Then - * the empty shell of ex-frame is thrown out for dogs to eat. - * But we, worried about pets, will recycle the frame! - */ - uvd->stats.frame_num++; - if ((uvd->flags & FLAGS_NO_DECODING) == 0) { - if (VALID_CALLBACK(uvd, postProcess)) - GET_CALLBACK(uvd, postProcess)(uvd, frame); - if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST) - usbvideo_SoftwareContrastAdjustment(uvd, frame); - } - frame->frameState = FrameState_Done_Hold; - if (uvd->debug >= 2) - info("%s: Entered FrameState_Done_Hold state.", __FUNCTION__); - return 0; - - case FrameState_Done_Hold: - /* - * We stay in this state indefinitely until someone external, - * like ioctl() or read() call finishes digesting the frame - * data. Then it will mark the frame as FrameState_Unused and - * it will be released back into the wild to roam freely. - */ - if (uvd->debug >= 2) - info("%s: FrameState_Done_Hold state.", __FUNCTION__); - return 0; - } - - /* Catch-all for other cases. We shall not be here. */ - err("%s: Invalid state %d.", __FUNCTION__, frame->frameState); - frame->frameState = FrameState_Unused; - return 0; -} - -/* - * usbvideo_DeinterlaceFrame() - * - * This procedure deinterlaces the given frame. Some cameras produce - * only half of scanlines - sometimes only even lines, sometimes only - * odd lines. The deinterlacing method is stored in frame->deinterlace - * variable. - * - * Here we scan the frame vertically and replace missing scanlines with - * average between surrounding ones - before and after. If we have no - * line above then we just copy next line. Similarly, if we need to - * create a last line then preceding line is used. - */ -void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame) -{ - if ((uvd == NULL) || (frame == NULL)) - return; - - if ((frame->deinterlace == Deinterlace_FillEvenLines) || - (frame->deinterlace == Deinterlace_FillOddLines)) - { - const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1; - - for (; i < VIDEOSIZE_Y(frame->request); i += 2) { - const unsigned char *fs1, *fs2; - unsigned char *fd; - int ip, in, j; /* Previous and next lines */ - - /* - * Need to average lines before and after 'i'. - * If we go out of bounds seeking those lines then - * we point back to existing line. - */ - ip = i - 1; /* First, get rough numbers */ - in = i + 1; - - /* Now validate */ - if (ip < 0) - ip = in; - if (in >= VIDEOSIZE_Y(frame->request)) - in = ip; - - /* Sanity check */ - if ((ip < 0) || (in < 0) || - (ip >= VIDEOSIZE_Y(frame->request)) || - (in >= VIDEOSIZE_Y(frame->request))) - { - err("Error: ip=%d. in=%d. req.height=%ld.", - ip, in, VIDEOSIZE_Y(frame->request)); - break; - } - - /* Now we need to average lines 'ip' and 'in' to produce line 'i' */ - fs1 = frame->data + (v4l_linesize * ip); - fs2 = frame->data + (v4l_linesize * in); - fd = frame->data + (v4l_linesize * i); - - /* Average lines around destination */ - for (j=0; j < v4l_linesize; j++) { - fd[j] = (unsigned char)((((unsigned) fs1[j]) + - ((unsigned)fs2[j])) >> 1); - } - } - } - - /* Optionally display statistics on the screen */ - if (uvd->flags & FLAGS_OVERLAY_STATS) - usbvideo_OverlayStats(uvd, frame); -} - -EXPORT_SYMBOL(usbvideo_DeinterlaceFrame); - -/* - * usbvideo_SoftwareContrastAdjustment() - * - * This code adjusts the contrast of the frame, assuming RGB24 format. - * As most software image processing, this job is CPU-intensive. - * Get a camera that supports hardware adjustment! - * - * History: - * 09-Feb-2001 Created. - */ -static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, - struct usbvideo_frame *frame) -{ - int i, j, v4l_linesize; - signed long adj; - const int ccm = 128; /* Color correction median - see below */ - - if ((uvd == NULL) || (frame == NULL)) { - err("%s: Illegal call.", __FUNCTION__); - return; - } - adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ - RESTRICT_TO_RANGE(adj, -ccm, ccm+1); - if (adj == 0) { - /* In rare case of no adjustment */ - return; - } - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - for (i=0; i < VIDEOSIZE_Y(frame->request); i++) { - unsigned char *fd = frame->data + (v4l_linesize * i); - for (j=0; j < v4l_linesize; j++) { - signed long v = (signed long) fd[j]; - /* Magnify up to 2 times, reduce down to zero */ - v = 128 + ((ccm + adj) * (v - 128)) / ccm; - RESTRICT_TO_RANGE(v, 0, 0xFF); /* Must flatten tails */ - fd[j] = (unsigned char) v; - } - } -} - -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/media/usbvideo.h b/drivers/usb/media/usbvideo.h deleted file mode 100644 index 135433c2680a..000000000000 --- a/drivers/usb/media/usbvideo.h +++ /dev/null @@ -1,394 +0,0 @@ -/* - * 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; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef usbvideo_h -#define usbvideo_h - -#include -#include -#include -#include - -/* Most helpful debugging aid */ -#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__)))) - -#define USBVIDEO_REPORT_STATS 1 /* Set to 0 to block statistics on close */ - -/* Bit flags (options) */ -#define FLAGS_RETRY_VIDIOCSYNC (1 << 0) -#define FLAGS_MONOCHROME (1 << 1) -#define FLAGS_DISPLAY_HINTS (1 << 2) -#define FLAGS_OVERLAY_STATS (1 << 3) -#define FLAGS_FORCE_TESTPATTERN (1 << 4) -#define FLAGS_SEPARATE_FRAMES (1 << 5) -#define FLAGS_CLEAN_FRAMES (1 << 6) -#define FLAGS_NO_DECODING (1 << 7) - -/* Bit flags for frames (apply to the frame where they are specified) */ -#define USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST (1 << 0) - -/* Camera capabilities (maximum) */ -#define CAMERA_URB_FRAMES 32 -#define CAMERA_MAX_ISO_PACKET 1023 /* 1022 actually sent by camera */ -#define FRAMES_PER_DESC (CAMERA_URB_FRAMES) -#define FRAME_SIZE_PER_DESC (CAMERA_MAX_ISO_PACKET) - -/* This macro restricts an int variable to an inclusive range */ -#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } - -#define V4L_BYTES_PER_PIXEL 3 /* Because we produce RGB24 */ - -/* - * Use this macro to construct constants for different video sizes. - * We have to deal with different video sizes that have to be - * configured in the device or compared against when we receive - * a data. Normally one would define a bunch of VIDEOSIZE_x_by_y - * #defines and that's the end of story. However this solution - * does not allow to convert between real pixel sizes and the - * constant (integer) value that may be used to tag a frame or - * whatever. The set of macros below constructs videosize constants - * from the pixel size and allows to reconstruct the pixel size - * from the combined value later. - */ -#define VIDEOSIZE(x,y) (((x) & 0xFFFFL) | (((y) & 0xFFFFL) << 16)) -#define VIDEOSIZE_X(vs) ((vs) & 0xFFFFL) -#define VIDEOSIZE_Y(vs) (((vs) >> 16) & 0xFFFFL) -typedef unsigned long videosize_t; - -/* - * This macro checks if the camera is still operational. The 'uvd' - * pointer must be valid, uvd->dev must be valid, we are not - * removing the device and the device has not erred on us. - */ -#define CAMERA_IS_OPERATIONAL(uvd) (\ - (uvd != NULL) && \ - ((uvd)->dev != NULL) && \ - ((uvd)->last_error == 0) && \ - (!(uvd)->remove_pending)) - -/* - * We use macros to do YUV -> RGB conversion because this is - * very important for speed and totally unimportant for size. - * - * YUV -> RGB Conversion - * --------------------- - * - * B = 1.164*(Y-16) + 2.018*(V-128) - * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) - * R = 1.164*(Y-16) + 1.596*(U-128) - * - * If you fancy integer arithmetics (as you should), hear this: - * - * 65536*B = 76284*(Y-16) + 132252*(V-128) - * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) - * 65536*R = 76284*(Y-16) + 104595*(U-128) - * - * Make sure the output values are within [0..255] range. - */ -#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) -#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ - int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ - mm_y = (my) - 16; \ - mm_u = (mu) - 128; \ - mm_v = (mv) - 128; \ - mm_yc= mm_y * 76284; \ - mm_b = (mm_yc + 132252*mm_v ) >> 16; \ - mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ - mm_r = (mm_yc + 104595*mm_u ) >> 16; \ - mb = LIMIT_RGB(mm_b); \ - mg = LIMIT_RGB(mm_g); \ - mr = LIMIT_RGB(mm_r); \ -} - -#define RING_QUEUE_SIZE (128*1024) /* Must be a power of 2 */ -#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1) -#define RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n) -#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)]) - -struct RingQueue { - unsigned char *queue; /* Data from the Isoc data pump */ - int length; /* How many bytes allocated for the queue */ - int wi; /* That's where we write */ - int ri; /* Read from here until you hit write index */ - wait_queue_head_t wqh; /* Processes waiting */ -}; - -enum ScanState { - ScanState_Scanning, /* Scanning for header */ - ScanState_Lines /* Parsing lines */ -}; - -/* Completion states of the data parser */ -enum ParseState { - scan_Continue, /* Just parse next item */ - scan_NextFrame, /* Frame done, send it to V4L */ - scan_Out, /* Not enough data for frame */ - scan_EndParse /* End parsing */ -}; - -enum FrameState { - FrameState_Unused, /* Unused (no MCAPTURE) */ - FrameState_Ready, /* Ready to start grabbing */ - FrameState_Grabbing, /* In the process of being grabbed into */ - FrameState_Done, /* Finished grabbing, but not been synced yet */ - FrameState_Done_Hold, /* Are syncing or reading */ - FrameState_Error, /* Something bad happened while processing */ -}; - -/* - * Some frames may contain only even or odd lines. This type - * specifies what type of deinterlacing is required. - */ -enum Deinterlace { - Deinterlace_None=0, - Deinterlace_FillOddLines, - Deinterlace_FillEvenLines -}; - -#define USBVIDEO_NUMFRAMES 2 /* How many frames we work with */ -#define USBVIDEO_NUMSBUF 2 /* How many URBs linked in a ring */ - -/* This structure represents one Isoc request - URB and buffer */ -struct usbvideo_sbuf { - char *data; - struct urb *urb; -}; - -struct usbvideo_frame { - char *data; /* Frame buffer */ - unsigned long header; /* Significant bits from the header */ - - videosize_t canvas; /* The canvas (max. image) allocated */ - videosize_t request; /* That's what the application asked for */ - unsigned short palette; /* The desired format */ - - enum FrameState frameState;/* State of grabbing */ - enum ScanState scanstate; /* State of scanning */ - enum Deinterlace deinterlace; - int flags; /* USBVIDEO_FRAME_FLAG_xxx bit flags */ - - int curline; /* Line of frame we're working on */ - - long seqRead_Length; /* Raw data length of frame */ - long seqRead_Index; /* Amount of data that has been already read */ - - void *user; /* Additional data that user may need */ -}; - -/* Statistics that can be overlaid on screen */ -struct usbvideo_statistics { - unsigned long frame_num; /* Sequential number of the frame */ - unsigned long urb_count; /* How many URBs we received so far */ - unsigned long urb_length; /* Length of last URB */ - unsigned long data_count; /* How many bytes we received */ - unsigned long header_count; /* How many frame headers we found */ - unsigned long iso_skip_count; /* How many empty ISO packets received */ - unsigned long iso_err_count; /* How many bad ISO packets received */ -}; - -struct usbvideo; - -struct uvd { - struct video_device vdev; /* Must be the first field! */ - struct usb_device *dev; - struct usbvideo *handle; /* Points back to the struct usbvideo */ - void *user_data; /* Camera-dependent data */ - int user_size; /* Size of that camera-dependent data */ - int debug; /* Debug level for usbvideo */ - unsigned char iface; /* Video interface number */ - unsigned char video_endp; - unsigned char ifaceAltActive; - unsigned char ifaceAltInactive; /* Alt settings */ - unsigned long flags; /* FLAGS_USBVIDEO_xxx */ - unsigned long paletteBits; /* Which palettes we accept? */ - unsigned short defaultPalette; /* What palette to use for read() */ - struct mutex lock; - int user; /* user count for exclusive use */ - - videosize_t videosize; /* Current setting */ - videosize_t canvas; /* This is the width,height of the V4L canvas */ - int max_frame_size; /* Bytes in one video frame */ - - int uvd_used; /* Is this structure in use? */ - int streaming; /* Are we streaming Isochronous? */ - int grabbing; /* Are we grabbing? */ - int settingsAdjusted; /* Have we adjusted contrast etc.? */ - int last_error; /* What calamity struck us? */ - - char *fbuf; /* Videodev buffer area */ - int fbuf_size; /* Videodev buffer size */ - - int curframe; - int iso_packet_len; /* Videomode-dependent, saves bus bandwidth */ - - struct RingQueue dp; /* Isoc data pump */ - struct usbvideo_frame frame[USBVIDEO_NUMFRAMES]; - struct usbvideo_sbuf sbuf[USBVIDEO_NUMSBUF]; - - volatile int remove_pending; /* If set then about to exit */ - - struct video_picture vpic, vpic_old; /* Picture settings */ - struct video_capability vcap; /* Video capabilities */ - struct video_channel vchan; /* May be used for tuner support */ - struct usbvideo_statistics stats; - char videoName[32]; /* Holds name like "video7" */ -}; - -/* - * usbvideo callbacks (virtual methods). They are set when usbvideo - * services are registered. All of these default to NULL, except those - * that default to usbvideo-provided methods. - */ -struct usbvideo_cb { - int (*probe)(struct usb_interface *, const struct usb_device_id *); - void (*userFree)(struct uvd *); - void (*disconnect)(struct usb_interface *); - int (*setupOnOpen)(struct uvd *); - void (*videoStart)(struct uvd *); - void (*videoStop)(struct uvd *); - void (*processData)(struct uvd *, struct usbvideo_frame *); - void (*postProcess)(struct uvd *, struct usbvideo_frame *); - void (*adjustPicture)(struct uvd *); - int (*getFPS)(struct uvd *); - int (*overlayHook)(struct uvd *, struct usbvideo_frame *); - int (*getFrame)(struct uvd *, int); - int (*startDataPump)(struct uvd *uvd); - void (*stopDataPump)(struct uvd *uvd); - int (*setVideoMode)(struct uvd *uvd, struct video_window *vw); -}; - -struct usbvideo { - int num_cameras; /* As allocated */ - struct usb_driver usbdrv; /* Interface to the USB stack */ - char drvName[80]; /* Driver name */ - struct mutex lock; /* Mutex protecting camera structures */ - struct usbvideo_cb cb; /* Table of callbacks (virtual methods) */ - struct video_device vdt; /* Video device template */ - struct uvd *cam; /* Array of camera structures */ - struct module *md_module; /* Minidriver module */ -}; - - -/* - * This macro retrieves callback address from the struct uvd object. - * No validity checks are done here, so be sure to check the - * callback beforehand with VALID_CALLBACK. - */ -#define GET_CALLBACK(uvd,cbName) ((uvd)->handle->cb.cbName) - -/* - * This macro returns either callback pointer or NULL. This is safe - * macro, meaning that most of components of data structures involved - * may be NULL - this only results in NULL being returned. You may - * wish to use this macro to make sure that the callback is callable. - * However keep in mind that those checks take time. - */ -#define VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \ - ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL) - -int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len); -int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n); -void RingQueue_WakeUpInterruptible(struct RingQueue *rq); -void RingQueue_Flush(struct RingQueue *rq); - -static inline int RingQueue_GetLength(const struct RingQueue *rq) -{ - return (rq->wi - rq->ri + rq->length) & (rq->length-1); -} - -static inline int RingQueue_GetFreeSpace(const struct RingQueue *rq) -{ - return rq->length - RingQueue_GetLength(rq); -} - -void usbvideo_DrawLine( - struct usbvideo_frame *frame, - int x1, int y1, - int x2, int y2, - unsigned char cr, unsigned char cg, unsigned char cb); -void usbvideo_HexDump(const unsigned char *data, int len); -void usbvideo_SayAndWait(const char *what); -void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode); - -/* Memory allocation routines */ -unsigned long usbvideo_kvirt_to_pa(unsigned long adr); - -int usbvideo_register( - struct usbvideo **pCams, - const int num_cams, - const int num_extra, - const char *driverName, - const struct usbvideo_cb *cbTable, - struct module *md, - const struct usb_device_id *id_table); -struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams); -int usbvideo_RegisterVideoDevice(struct uvd *uvd); -void usbvideo_Deregister(struct usbvideo **uvt); - -int usbvideo_v4l_initialize(struct video_device *dev); - -void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame); - -/* - * This code performs bounds checking - use it when working with - * new formats, or else you may get oopses all over the place. - * If pixel falls out of bounds then it gets shoved back (as close - * to place of offence as possible) and is painted bright red. - * - * There are two important concepts: frame width, height and - * V4L canvas width, height. The former is the area requested by - * the application -for this very frame-. The latter is the largest - * possible frame that we can serve (we advertise that via V4L ioctl). - * The frame data is expected to be formatted as lines of length - * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines. - */ -static inline void RGB24_PUTPIXEL( - struct usbvideo_frame *fr, - int ix, int iy, - unsigned char vr, - unsigned char vg, - unsigned char vb) -{ - register unsigned char *pf; - int limiter = 0, mx, my; - mx = ix; - my = iy; - if (mx < 0) { - mx=0; - limiter++; - } else if (mx >= VIDEOSIZE_X((fr)->request)) { - mx= VIDEOSIZE_X((fr)->request) - 1; - limiter++; - } - if (my < 0) { - my = 0; - limiter++; - } else if (my >= VIDEOSIZE_Y((fr)->request)) { - my = VIDEOSIZE_Y((fr)->request) - 1; - limiter++; - } - pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*VIDEOSIZE_X((fr)->request) + (ix)); - if (limiter) { - *pf++ = 0; - *pf++ = 0; - *pf++ = 0xFF; - } else { - *pf++ = (vb); - *pf++ = (vg); - *pf++ = (vr); - } -} - -#endif /* usbvideo_h */ diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c deleted file mode 100644 index 1d06e53ec7c5..000000000000 --- a/drivers/usb/media/vicam.c +++ /dev/null @@ -1,1411 +0,0 @@ -/* - * USB ViCam WebCam driver - * Copyright (c) 2002 Joe Burks (jburks@wavicle.org), - * Christopher L Cheney (ccheney@cheney.cx), - * Pavel Machek (pavel@suse.cz), - * John Tyner (jtyner@cs.ucr.edu), - * Monroe Williams (monroe@pobox.com) - * - * Supports 3COM HomeConnect PC Digital WebCam - * - * 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 source code is based heavily on the CPiA webcam driver which was - * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt - * - * Portions of this code were also copied from usbvideo.c - * - * Special thanks to the the whole team at Sourceforge for help making - * this driver become a reality. Notably: - * Andy Armstrong who reverse engineered the color encoding and - * Pavel Machek and Chris Cheney who worked on reverse engineering the - * camera controls and wrote the first generation driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "usbvideo.h" - -// #define VICAM_DEBUG - -#ifdef VICAM_DEBUG -#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args) -#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args) -#else -#define DBG(fmn,args...) do {} while(0) -#endif - -#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org" -#define DRIVER_DESC "ViCam WebCam Driver" - -/* Define these values to match your device */ -#define USB_VICAM_VENDOR_ID 0x04c1 -#define USB_VICAM_PRODUCT_ID 0x009d - -#define VICAM_BYTES_PER_PIXEL 3 -#define VICAM_MAX_READ_SIZE (512*242+128) -#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240) -#define VICAM_FRAMES 2 - -#define VICAM_HEADER_SIZE 64 - -#define clamp( x, l, h ) max_t( __typeof__( x ), \ - ( l ), \ - min_t( __typeof__( x ), \ - ( h ), \ - ( x ) ) ) - -/* Not sure what all the bytes in these char - * arrays do, but they're necessary to make - * the camera work. - */ - -static unsigned char setup1[] = { - 0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64, 0xE7, 0x67, - 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09, 0xDE, 0x00, - 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03, 0xC0, 0x17, - 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07, 0x00, 0x00, - 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00 -}; - -static unsigned char setup2[] = { - 0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64, 0x18, 0x00, - 0x00, 0x00 -}; - -static unsigned char setup3[] = { - 0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00 -}; - -static unsigned char setup4[] = { - 0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64, 0xE7, 0x07, - 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07, 0x00, 0x00, - 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01, 0xAA, 0x00, - 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00, 0xE7, 0x07, - 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07, 0x7C, 0x00, - 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00, 0x18, 0x00, - 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0, 0xE7, 0x07, - 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF, - 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00, 0x24, 0xC0, - 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0, 0xE7, 0x07, - 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87, 0x01, 0x00, - 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09, 0x00, 0xC0, - 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0, 0x09, 0xC1, - 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01, 0xE7, 0x09, - 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07, 0x07, 0x00, - 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0, 0xC0, 0xDF, - 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00, 0x17, 0x02, - 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00, - 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57, 0xFF, 0xFF, - 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57, 0x00, 0x00, - 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF, 0xC6, 0x00, - 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05, 0xC1, 0x05, - 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF, 0x27, 0xDA, - 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x0B, 0x06, - 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01, 0x9F, 0xAF, - 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09, 0xFC, 0x05, - 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06, 0x26, 0x01, - 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0, 0xE7, 0x09, - 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09, 0x02, 0x06, - 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06, 0xFC, 0x05, - 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06, 0x27, 0xDA, - 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00, 0xFA, 0x05, - 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, - 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07, 0x40, 0x00, - 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05, 0x9F, 0xAF, - 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17, 0x02, 0x00, - 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06, 0x9F, 0xA0, - 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00, 0x09, 0x06, - 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57, 0x01, 0x00, - 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03, 0xE7, 0x07, - 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF, 0x47, 0xAF, - 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07, 0x2E, 0x00, - 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06, - 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00, 0xC0, 0x57, - 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02, 0xC0, 0x57, - 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57, 0x55, 0x00, - 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00, 0x9F, 0xC0, - 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02, 0xC1, 0x0B, - 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90, 0x08, 0x06, - 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06, - 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF, 0x2F, 0x0E, - 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07, 0x08, 0x00, - 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05, - 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E, 0x02, 0x00, - 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06, - 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67, 0x7F, 0xFF, - 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD, 0x22, 0xC0, - 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0, 0xE7, 0x87, - 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF, 0xB8, 0x05, - 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0, 0x9F, 0xAF, - 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00, 0x24, 0xC0, - 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0, 0xC8, 0x07, - 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00, 0xC1, 0x07, - 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0x9F, 0xAF, - 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00, 0x9F, 0xAF, - 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0, - 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01, - 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02, 0x0F, 0xC1, - 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x67, - 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x08, 0x00, - 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1, 0xEF, 0x07, - 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF, 0xEF, 0x07, - 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF, 0xEF, 0x07, - 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07, 0x00, 0x00, - 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF, 0x09, 0x06, - 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xE7, 0x67, - 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67, 0x17, 0xD8, - 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0, - 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0, 0x97, 0xCF, - 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF, 0xDA, 0x02, - 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07, - 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0x0E, 0x06, - 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02, 0xF8, 0x05, - 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80, - 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C, 0x02, 0x00, - 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00, 0x06, 0x06, - 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07, - 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0xE2, 0x05, - 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02, 0xF8, 0x05, - 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80, - 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF, 0x66, 0x04, - 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF, 0x97, 0xCF, - 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B, 0x0C, 0x06, - 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, - 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0x68, 0x00, - 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF, 0x44, 0x05, - 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00, 0xE0, 0x07, - 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06, 0xE8, 0x07, - 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02, 0xE0, 0x07, - 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF, 0x97, 0xCF, - 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05, 0xEF, 0x07, - 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07, 0x0E, 0x06, - 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06, 0xFE, 0x05, - 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01, 0xE7, 0x07, - 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07, 0x07, 0x00, - 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07, 0x02, 0x00, - 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01, 0xEF, 0x77, - 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0, 0x14, 0x04, - 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06, 0x37, 0xC0, - 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06, 0x0F, 0xC1, - 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06, 0xC0, 0x07, - 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00, 0x9F, 0xAF, - 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, - 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07, - 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07, - 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x77, - 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA, 0x75, 0xC1, - 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1, 0xC0, 0x07, - 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF, - 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x06, 0x06, - 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, - 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07, - 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF, 0xEF, 0x07, - 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57, 0x01, 0x00, - 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07, 0x01, 0x00, - 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05, - 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00, - 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07, 0xFF, 0x4F, - 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07, 0x38, 0x00, - 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67, 0x03, 0x00, - 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0, 0x08, 0xDA, - 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, - 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00, 0x06, 0x06, - 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00, 0x9F, 0xAF, - 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00, 0xC1, 0x0B, - 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, - 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x09, - 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8, 0xFA, 0x05, - 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05, 0xE7, 0x07, - 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07, 0x40, 0x00, - 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05, 0x9F, 0xAF, - 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B, 0xE2, 0x05, - 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17, 0x23, 0x00, - 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07, 0x04, 0x00, - 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF, 0x28, 0x05, - 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09, 0xE6, 0x05, - 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x07, 0x00, - 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1, 0x9F, 0xAF, - 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00, 0xC1, 0x09, - 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, - 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05, 0xC1, 0xD1, - 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0D, 0x00, - 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF, 0x28, 0x05, - 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07, 0x32, 0x00, - 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0F, 0x00, - 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF, 0x28, 0x05, - 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9, 0x24, 0xC0, - 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00, 0xC0, 0x67, - 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0, 0xE7, 0x87, - 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xF9, - 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA, 0x72, 0xC1, - 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0, 0x97, 0xCF, - 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87, 0xFF, 0x00, - 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF, 0x24, 0xC0, - 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0xE7, 0x87, - 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, - 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0, 0xE7, 0x67, - 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, - 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, - 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x67, - 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, - 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0, - 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01, - 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07, 0x40, 0x00, - 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67, 0x00, 0xFF, - 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0, - 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x67, - 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA, 0xE8, 0x09, - 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, - 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, 0x00, 0xDA, - 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1, 0xE7, 0x87, - 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xE7, 0x07, - 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80, - 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0xE7, 0x07, - 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80, - 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0x09, 0x02, - 0x19, 0x00, 0x01, 0x01, 0x00, 0x80, 0x96, 0x09, - 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -static unsigned char setup5[] = { - 0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64, 0x0E, 0x00, - 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00, 0x26, 0x00, - 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00, 0x92, 0x00, - 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00, 0xB8, 0x00, - 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00, 0xCE, 0x00, - 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00, 0xE0, 0x00, - 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00, 0xEC, 0x00, - 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01, 0x0A, 0x01, - 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01, 0x22, 0x01, - 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01, 0x36, 0x01, - 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01, 0x72, 0x01, - 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01, 0x88, 0x01, - 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01, 0xA0, 0x01, - 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01, 0xB4, 0x01, - 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01, 0xF6, 0x01, - 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02, 0x3C, 0x02, - 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02, 0x56, 0x02, - 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02, 0x84, 0x02, - 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02, 0x8E, 0x02, - 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02, 0xAE, 0x02, - 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02, 0xC0, 0x02, - 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02, 0xD4, 0x02, - 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02, 0xF8, 0x02, - 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03, 0x24, 0x03, - 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03, 0x3C, 0x03, - 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03, 0x58, 0x03, - 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03, 0x7A, 0x03, - 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03, 0xB2, 0x03, - 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03, 0xD4, 0x03, - 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03, 0xFC, 0x03, - 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04, 0x32, 0x04, - 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04, 0x42, 0x04, - 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04, 0x54, 0x04, - 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04, 0x62, 0x04, - 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04, 0x80, 0x04, - 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04, 0x9A, 0x04, - 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04, 0xB4, 0x04, - 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04, 0x2A, 0x05, - 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00 -}; - -/* rvmalloc / rvfree copied from usbvideo.c - * - * Not sure why these are not yet non-statics which I can reference through - * usbvideo.h the same as it is in 2.4.20. I bet this will get fixed sometime - * in the future. - * -*/ -static void *rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - -struct vicam_camera { - u16 shutter_speed; // capture shutter speed - u16 gain; // capture gain - - u8 *raw_image; // raw data captured from the camera - u8 *framebuf; // processed data in RGB24 format - u8 *cntrlbuf; // area used to send control msgs - - struct video_device vdev; // v4l video device - struct usb_device *udev; // usb device - - /* guard against simultaneous accesses to the camera */ - struct mutex cam_lock; - - int is_initialized; - u8 open_count; - u8 bulkEndpoint; - int needsDummyRead; - -#if defined(CONFIG_VIDEO_PROC_FS) - struct proc_dir_entry *proc_dir; -#endif - -}; - -static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id); -static void vicam_disconnect(struct usb_interface *intf); -static void read_frame(struct vicam_camera *cam, int framenum); -static void vicam_decode_color(const u8 *, u8 *); - -static int __send_control_msg(struct vicam_camera *cam, - u8 request, - u16 value, - u16 index, - unsigned char *cp, - u16 size) -{ - int status; - - /* cp must be memory that has been allocated by kmalloc */ - - status = usb_control_msg(cam->udev, - usb_sndctrlpipe(cam->udev, 0), - request, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, - cp, size, 1000); - - status = min(status, 0); - - if (status < 0) { - printk(KERN_INFO "Failed sending control message, error %d.\n", - status); - } - - return status; -} - -static int send_control_msg(struct vicam_camera *cam, - u8 request, - u16 value, - u16 index, - unsigned char *cp, - u16 size) -{ - int status = -ENODEV; - mutex_lock(&cam->cam_lock); - if (cam->udev) { - status = __send_control_msg(cam, request, value, - index, cp, size); - } - mutex_unlock(&cam->cam_lock); - return status; -} -static int -initialize_camera(struct vicam_camera *cam) -{ - const struct { - u8 *data; - u32 size; - } firmware[] = { - { .data = setup1, .size = sizeof(setup1) }, - { .data = setup2, .size = sizeof(setup2) }, - { .data = setup3, .size = sizeof(setup3) }, - { .data = setup4, .size = sizeof(setup4) }, - { .data = setup5, .size = sizeof(setup5) }, - { .data = setup3, .size = sizeof(setup3) }, - { .data = NULL, .size = 0 } - }; - - int err, i; - - for (i = 0, err = 0; firmware[i].data && !err; i++) { - memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size); - - err = send_control_msg(cam, 0xff, 0, 0, - cam->cntrlbuf, firmware[i].size); - } - - return err; -} - -static int -set_camera_power(struct vicam_camera *cam, int state) -{ - int status; - - if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0) - return status; - - if (state) { - send_control_msg(cam, 0x55, 1, 0, NULL, 0); - } - - return 0; -} - -static int -vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg) -{ - void __user *user_arg = (void __user *)arg; - struct vicam_camera *cam = file->private_data; - int retval = 0; - - if (!cam) - return -ENODEV; - - switch (ioctlnr) { - /* query capabilities */ - case VIDIOCGCAP: - { - struct video_capability b; - - DBG("VIDIOCGCAP\n"); - memset(&b, 0, sizeof(b)); - strcpy(b.name, "ViCam-based Camera"); - b.type = VID_TYPE_CAPTURE; - b.channels = 1; - b.audios = 0; - b.maxwidth = 320; /* VIDEOSIZE_CIF */ - b.maxheight = 240; - b.minwidth = 320; /* VIDEOSIZE_48_48 */ - b.minheight = 240; - - if (copy_to_user(user_arg, &b, sizeof(b))) - retval = -EFAULT; - - break; - } - /* get/set video source - we are a camera and nothing else */ - case VIDIOCGCHAN: - { - struct video_channel v; - - DBG("VIDIOCGCHAN\n"); - if (copy_from_user(&v, user_arg, sizeof(v))) { - retval = -EFAULT; - break; - } - if (v.channel != 0) { - retval = -EINVAL; - break; - } - - v.channel = 0; - strcpy(v.name, "Camera"); - v.tuners = 0; - v.flags = 0; - v.type = VIDEO_TYPE_CAMERA; - v.norm = 0; - - if (copy_to_user(user_arg, &v, sizeof(v))) - retval = -EFAULT; - break; - } - - case VIDIOCSCHAN: - { - int v; - - if (copy_from_user(&v, user_arg, sizeof(v))) - retval = -EFAULT; - DBG("VIDIOCSCHAN %d\n", v); - - if (retval == 0 && v != 0) - retval = -EINVAL; - - break; - } - - /* image properties */ - case VIDIOCGPICT: - { - struct video_picture vp; - DBG("VIDIOCGPICT\n"); - memset(&vp, 0, sizeof (struct video_picture)); - vp.brightness = cam->gain << 8; - vp.depth = 24; - vp.palette = VIDEO_PALETTE_RGB24; - if (copy_to_user(user_arg, &vp, sizeof (struct video_picture))) - retval = -EFAULT; - break; - } - - case VIDIOCSPICT: - { - struct video_picture vp; - - if (copy_from_user(&vp, user_arg, sizeof(vp))) { - retval = -EFAULT; - break; - } - - DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth, - vp.palette); - - cam->gain = vp.brightness >> 8; - - if (vp.depth != 24 - || vp.palette != VIDEO_PALETTE_RGB24) - retval = -EINVAL; - - break; - } - - /* get/set capture window */ - case VIDIOCGWIN: - { - struct video_window vw; - vw.x = 0; - vw.y = 0; - vw.width = 320; - vw.height = 240; - vw.chromakey = 0; - vw.flags = 0; - vw.clips = NULL; - vw.clipcount = 0; - - DBG("VIDIOCGWIN\n"); - - if (copy_to_user(user_arg, (void *)&vw, sizeof(vw))) - retval = -EFAULT; - - // I'm not sure what the deal with a capture window is, it is very poorly described - // in the doc. So I won't support it now. - break; - } - - case VIDIOCSWIN: - { - - struct video_window vw; - - if (copy_from_user(&vw, user_arg, sizeof(vw))) { - retval = -EFAULT; - break; - } - - DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height); - - if ( vw.width != 320 || vw.height != 240 ) - retval = -EFAULT; - - break; - } - - /* mmap interface */ - case VIDIOCGMBUF: - { - struct video_mbuf vm; - int i; - - DBG("VIDIOCGMBUF\n"); - memset(&vm, 0, sizeof (vm)); - vm.size = - VICAM_MAX_FRAME_SIZE * VICAM_FRAMES; - vm.frames = VICAM_FRAMES; - for (i = 0; i < VICAM_FRAMES; i++) - vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i; - - if (copy_to_user(user_arg, (void *)&vm, sizeof(vm))) - retval = -EFAULT; - - break; - } - - case VIDIOCMCAPTURE: - { - struct video_mmap vm; - // int video_size; - - if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) { - retval = -EFAULT; - break; - } - - DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format); - - if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 ) - retval = -EINVAL; - - // in theory right here we'd start the image capturing - // (fill in a bulk urb and submit it asynchronously) - // - // Instead we're going to do a total hack job for now and - // retrieve the frame in VIDIOCSYNC - - break; - } - - case VIDIOCSYNC: - { - int frame; - - if (copy_from_user((void *)&frame, user_arg, sizeof(int))) { - retval = -EFAULT; - break; - } - DBG("VIDIOCSYNC: %d\n", frame); - - read_frame(cam, frame); - vicam_decode_color(cam->raw_image, - cam->framebuf + - frame * VICAM_MAX_FRAME_SIZE ); - - break; - } - - /* pointless to implement overlay with this camera */ - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCKEY: - retval = -EINVAL; - break; - - /* tuner interface - we have none */ - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - retval = -EINVAL; - break; - - /* audio interface - we have none */ - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - retval = -EINVAL; - break; - default: - retval = -ENOIOCTLCMD; - break; - } - - return retval; -} - -static int -vicam_open(struct inode *inode, struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct vicam_camera *cam = - (struct vicam_camera *) dev->priv; - DBG("open\n"); - - if (!cam) { - printk(KERN_ERR - "vicam video_device improperly initialized"); - return -EINVAL; - } - - /* the videodev_lock held above us protects us from - * simultaneous opens...for now. we probably shouldn't - * rely on this fact forever. - */ - - if (cam->open_count > 0) { - printk(KERN_INFO - "vicam_open called on already opened camera"); - return -EBUSY; - } - - cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); - if (!cam->raw_image) { - return -ENOMEM; - } - - cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); - if (!cam->framebuf) { - kfree(cam->raw_image); - return -ENOMEM; - } - - cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!cam->cntrlbuf) { - kfree(cam->raw_image); - rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); - return -ENOMEM; - } - - // First upload firmware, then turn the camera on - - if (!cam->is_initialized) { - initialize_camera(cam); - - cam->is_initialized = 1; - } - - set_camera_power(cam, 1); - - cam->needsDummyRead = 1; - cam->open_count++; - - file->private_data = cam; - - return 0; -} - -static int -vicam_close(struct inode *inode, struct file *file) -{ - struct vicam_camera *cam = file->private_data; - int open_count; - struct usb_device *udev; - - DBG("close\n"); - - /* it's not the end of the world if - * we fail to turn the camera off. - */ - - set_camera_power(cam, 0); - - kfree(cam->raw_image); - rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); - kfree(cam->cntrlbuf); - - mutex_lock(&cam->cam_lock); - - cam->open_count--; - open_count = cam->open_count; - udev = cam->udev; - - mutex_unlock(&cam->cam_lock); - - if (!open_count && !udev) { - kfree(cam); - } - - return 0; -} - -static void vicam_decode_color(const u8 *data, u8 *rgb) -{ - /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB - * Copyright (C) 2002 Monroe Williams (monroe@pobox.com) - */ - - int i, prevY, nextY; - - prevY = 512; - nextY = 512; - - data += VICAM_HEADER_SIZE; - - for( i = 0; i < 240; i++, data += 512 ) { - const int y = ( i * 242 ) / 240; - - int j, prevX, nextX; - int Y, Cr, Cb; - - if ( y == 242 - 1 ) { - nextY = -512; - } - - prevX = 1; - nextX = 1; - - for ( j = 0; j < 320; j++, rgb += 3 ) { - const int x = ( j * 512 ) / 320; - const u8 * const src = &data[x]; - - if ( x == 512 - 1 ) { - nextX = -1; - } - - Cr = ( src[prevX] - src[0] ) + - ( src[nextX] - src[0] ); - Cr /= 2; - - Cb = ( src[prevY] - src[prevX + prevY] ) + - ( src[prevY] - src[nextX + prevY] ) + - ( src[nextY] - src[prevX + nextY] ) + - ( src[nextY] - src[nextX + nextY] ); - Cb /= 4; - - Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 ); - - if ( i & 1 ) { - int Ct = Cr; - Cr = Cb; - Cb = Ct; - } - - if ( ( x ^ i ) & 1 ) { - Cr = -Cr; - Cb = -Cb; - } - - rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) + - 500 ) / 900, 0, 255 ); - rgb[1] = clamp( ( ( Y - ( 392 * Cb ) - - ( 813 * Cr ) ) + - 500 ) / 1000, 0, 255 ); - rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) + - 500 ) / 1300, 0, 255 ); - - prevX = -1; - } - - prevY = -512; - } -} - -static void -read_frame(struct vicam_camera *cam, int framenum) -{ - unsigned char *request = cam->cntrlbuf; - int realShutter; - int n; - int actual_length; - - if (cam->needsDummyRead) { - cam->needsDummyRead = 0; - read_frame(cam, framenum); - } - - memset(request, 0, 16); - request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain - - request[1] = 0; // 512x242 capture - - request[2] = 0x90; // the function of these two bytes - request[3] = 0x07; // is not yet understood - - if (cam->shutter_speed > 60) { - // Short exposure - realShutter = - ((-15631900 / cam->shutter_speed) + 260533) / 1000; - request[4] = realShutter & 0xFF; - request[5] = (realShutter >> 8) & 0xFF; - request[6] = 0x03; - request[7] = 0x01; - } else { - // Long exposure - realShutter = 15600 / cam->shutter_speed - 1; - request[4] = 0; - request[5] = 0; - request[6] = realShutter & 0xFF; - request[7] = realShutter >> 8; - } - - // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0 - request[8] = 0; - // bytes 9-15 do not seem to affect exposure or image quality - - mutex_lock(&cam->cam_lock); - - if (!cam->udev) { - goto done; - } - - n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16); - - if (n < 0) { - printk(KERN_ERR - " Problem sending frame capture control message"); - goto done; - } - - n = usb_bulk_msg(cam->udev, - usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint), - cam->raw_image, - 512 * 242 + 128, &actual_length, 10000); - - if (n < 0) { - printk(KERN_ERR "Problem during bulk read of frame data: %d\n", - n); - } - - done: - mutex_unlock(&cam->cam_lock); -} - -static ssize_t -vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos ) -{ - struct vicam_camera *cam = file->private_data; - - DBG("read %d bytes.\n", (int) count); - - if (*ppos >= VICAM_MAX_FRAME_SIZE) { - *ppos = 0; - return 0; - } - - if (*ppos == 0) { - read_frame(cam, 0); - vicam_decode_color(cam->raw_image, - cam->framebuf + - 0 * VICAM_MAX_FRAME_SIZE); - } - - count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos); - - if (copy_to_user(buf, &cam->framebuf[*ppos], count)) { - count = -EFAULT; - } else { - *ppos += count; - } - - if (count == VICAM_MAX_FRAME_SIZE) { - *ppos = 0; - } - - return count; -} - - -static int -vicam_mmap(struct file *file, struct vm_area_struct *vma) -{ - // TODO: allocate the raw frame buffer if necessary - unsigned long page, pos; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - struct vicam_camera *cam = file->private_data; - - if (!cam) - return -ENODEV; - - DBG("vicam_mmap: %ld\n", size); - - /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes - * to the size the application requested for mmap and it was screwing apps up. - if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE) - return -EINVAL; - */ - - pos = (unsigned long)cam->framebuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - return 0; -} - -#if defined(CONFIG_VIDEO_PROC_FS) - -static struct proc_dir_entry *vicam_proc_root = NULL; - -static int vicam_read_helper(char *page, char **start, off_t off, - int count, int *eof, int value) -{ - char *out = page; - int len; - - out += sprintf(out, "%d",value); - - 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 vicam_read_proc_shutter(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - return vicam_read_helper(page,start,off,count,eof, - ((struct vicam_camera *)data)->shutter_speed); -} - -static int vicam_read_proc_gain(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - return vicam_read_helper(page,start,off,count,eof, - ((struct vicam_camera *)data)->gain); -} - -static int -vicam_write_proc_shutter(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - u16 stmp; - char kbuf[8]; - struct vicam_camera *cam = (struct vicam_camera *) data; - - if (count > 6) - return -EINVAL; - - if (copy_from_user(kbuf, buffer, count)) - return -EFAULT; - - stmp = (u16) simple_strtoul(kbuf, NULL, 10); - if (stmp < 4 || stmp > 32000) - return -EINVAL; - - cam->shutter_speed = stmp; - - return count; -} - -static int -vicam_write_proc_gain(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - u16 gtmp; - char kbuf[8]; - - struct vicam_camera *cam = (struct vicam_camera *) data; - - if (count > 4) - return -EINVAL; - - if (copy_from_user(kbuf, buffer, count)) - return -EFAULT; - - gtmp = (u16) simple_strtoul(kbuf, NULL, 10); - if (gtmp > 255) - return -EINVAL; - cam->gain = gtmp; - - return count; -} - -static void -vicam_create_proc_root(void) -{ - vicam_proc_root = proc_mkdir("video/vicam", NULL); - - if (vicam_proc_root) - vicam_proc_root->owner = THIS_MODULE; - else - printk(KERN_ERR - "could not create /proc entry for vicam!"); -} - -static void -vicam_destroy_proc_root(void) -{ - if (vicam_proc_root) - remove_proc_entry("video/vicam", 0); -} - -static void -vicam_create_proc_entry(struct vicam_camera *cam) -{ - char name[64]; - struct proc_dir_entry *ent; - - DBG(KERN_INFO "vicam: creating proc entry\n"); - - if (!vicam_proc_root || !cam) { - printk(KERN_INFO - "vicam: could not create proc entry, %s pointer is null.\n", - (!cam ? "camera" : "root")); - return; - } - - sprintf(name, "video%d", cam->vdev.minor); - - cam->proc_dir = proc_mkdir(name, vicam_proc_root); - - if ( !cam->proc_dir ) - return; // FIXME: We should probably return an error here - - ent = create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR, - cam->proc_dir); - if (ent) { - ent->data = cam; - ent->read_proc = vicam_read_proc_shutter; - ent->write_proc = vicam_write_proc_shutter; - ent->size = 64; - } - - ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR, - cam->proc_dir); - if (ent) { - ent->data = cam; - ent->read_proc = vicam_read_proc_gain; - ent->write_proc = vicam_write_proc_gain; - ent->size = 64; - } -} - -static void -vicam_destroy_proc_entry(void *ptr) -{ - struct vicam_camera *cam = (struct vicam_camera *) ptr; - char name[16]; - - if ( !cam->proc_dir ) - return; - - sprintf(name, "video%d", cam->vdev.minor); - remove_proc_entry("shutter", cam->proc_dir); - remove_proc_entry("gain", cam->proc_dir); - remove_proc_entry(name,vicam_proc_root); - cam->proc_dir = NULL; - -} - -#else -static inline void vicam_create_proc_root(void) { } -static inline void vicam_destroy_proc_root(void) { } -static inline void vicam_create_proc_entry(struct vicam_camera *cam) { } -static inline void vicam_destroy_proc_entry(void *ptr) { } -#endif - -static struct file_operations vicam_fops = { - .owner = THIS_MODULE, - .open = vicam_open, - .release = vicam_close, - .read = vicam_read, - .mmap = vicam_mmap, - .ioctl = vicam_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, -}; - -static struct video_device vicam_template = { - .owner = THIS_MODULE, - .name = "ViCam-based USB Camera", - .type = VID_TYPE_CAPTURE, - .hardware = VID_HARDWARE_VICAM, - .fops = &vicam_fops, - .minor = -1, -}; - -/* table of devices that work with this driver */ -static struct usb_device_id vicam_table[] = { - {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)}, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, vicam_table); - -static struct usb_driver vicam_driver = { - .name = "vicam", - .probe = vicam_probe, - .disconnect = vicam_disconnect, - .id_table = vicam_table -}; - -/** - * vicam_probe - * @intf: the interface - * @id: the device id - * - * Called by the usb core when a new device is connected that it thinks - * this driver might be interested in. - */ -static int -vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - int bulkEndpoint = 0; - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - struct vicam_camera *cam; - - printk(KERN_INFO "ViCam based webcam connected\n"); - - interface = intf->cur_altsetting; - - DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n", - interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints)); - endpoint = &interface->endpoint[0].desc; - - if ((endpoint->bEndpointAddress & 0x80) && - ((endpoint->bmAttributes & 3) == 0x02)) { - /* we found a bulk in endpoint */ - bulkEndpoint = endpoint->bEndpointAddress; - } else { - printk(KERN_ERR - "No bulk in endpoint was found ?! (this is bad)\n"); - } - - if ((cam = - kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) { - printk(KERN_WARNING - "could not allocate kernel memory for vicam_camera struct\n"); - return -ENOMEM; - } - - memset(cam, 0, sizeof (struct vicam_camera)); - - cam->shutter_speed = 15; - - mutex_init(&cam->cam_lock); - - memcpy(&cam->vdev, &vicam_template, - sizeof (vicam_template)); - cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only - - cam->udev = dev; - cam->bulkEndpoint = bulkEndpoint; - - if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) { - kfree(cam); - printk(KERN_WARNING "video_register_device failed\n"); - return -EIO; - } - - vicam_create_proc_entry(cam); - - printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor); - - usb_set_intfdata (intf, cam); - - return 0; -} - -static void -vicam_disconnect(struct usb_interface *intf) -{ - int open_count; - struct vicam_camera *cam = usb_get_intfdata (intf); - usb_set_intfdata (intf, NULL); - - /* we must unregister the device before taking its - * cam_lock. This is because the video open call - * holds the same lock as video unregister. if we - * unregister inside of the cam_lock and open also - * uses the cam_lock, we get deadlock. - */ - - video_unregister_device(&cam->vdev); - - /* stop the camera from being used */ - - mutex_lock(&cam->cam_lock); - - /* mark the camera as gone */ - - cam->udev = NULL; - - vicam_destroy_proc_entry(cam); - - /* the only thing left to do is synchronize with - * our close/release function on who should release - * the camera memory. if there are any users using the - * camera, it's their job. if there are no users, - * it's ours. - */ - - open_count = cam->open_count; - - mutex_unlock(&cam->cam_lock); - - if (!open_count) { - kfree(cam); - } - - printk(KERN_DEBUG "ViCam-based WebCam disconnected\n"); -} - -/* - */ -static int __init -usb_vicam_init(void) -{ - int retval; - DBG(KERN_INFO "ViCam-based WebCam driver startup\n"); - vicam_create_proc_root(); - retval = usb_register(&vicam_driver); - if (retval) - printk(KERN_WARNING "usb_register failed!\n"); - return retval; -} - -static void __exit -usb_vicam_exit(void) -{ - DBG(KERN_INFO - "ViCam-based WebCam driver shutdown\n"); - - usb_deregister(&vicam_driver); - vicam_destroy_proc_root(); -} - -module_init(usb_vicam_init); -module_exit(usb_vicam_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c deleted file mode 100644 index b57dec3782e0..000000000000 --- a/drivers/usb/media/w9968cf.c +++ /dev/null @@ -1,3691 +0,0 @@ -/*************************************************************************** - * Video4Linux driver for W996[87]CF JPEG USB Dual Mode Camera Chip. * - * * - * Copyright (C) 2002-2004 by Luca Risolia * - * * - * - Memory management code from bttv driver by Ralph Metzler, * - * Marcus Metzler and Gerd Knorr. * - * - I2C interface to kernel, high-level image sensor control routines and * - * some symbolic names from OV511 driver by Mark W. McClelland. * - * - Low-level I2C fast write function by Piotr Czerczak. * - * - Low-level I2C read function by Frederic Jouault. * - * * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "w9968cf.h" -#include "w9968cf_decoder.h" - -static struct w9968cf_vpp_t* w9968cf_vpp; -static DECLARE_WAIT_QUEUE_HEAD(w9968cf_vppmod_wait); - -static LIST_HEAD(w9968cf_dev_list); /* head of V4L registered cameras list */ -static DEFINE_MUTEX(w9968cf_devlist_mutex); /* semaphore for list traversal */ - -static DECLARE_RWSEM(w9968cf_disconnect); /* prevent races with open() */ - - -/**************************************************************************** - * Module macros and parameters * - ****************************************************************************/ - -MODULE_DEVICE_TABLE(usb, winbond_id_table); - -MODULE_AUTHOR(W9968CF_MODULE_AUTHOR" "W9968CF_AUTHOR_EMAIL); -MODULE_DESCRIPTION(W9968CF_MODULE_NAME); -MODULE_VERSION(W9968CF_MODULE_VERSION); -MODULE_LICENSE(W9968CF_MODULE_LICENSE); -MODULE_SUPPORTED_DEVICE("Video"); - -static int ovmod_load = W9968CF_OVMOD_LOAD; -static unsigned short simcams = W9968CF_SIMCAMS; -static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/ -static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_PACKET_SIZE}; -static unsigned short max_buffers[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_BUFFERS}; -static int double_buffer[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_DOUBLE_BUFFER}; -static int clamping[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLAMPING}; -static unsigned short filter_type[]= {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_FILTER_TYPE}; -static int largeview[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_LARGEVIEW}; -static unsigned short decompression[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_DECOMPRESSION}; -static int upscaling[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_UPSCALING}; -static unsigned short force_palette[] = {[0 ... W9968CF_MAX_DEVICES-1] = 0}; -static int force_rgb[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_FORCE_RGB}; -static int autobright[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOBRIGHT}; -static int autoexp[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOEXP}; -static unsigned short lightfreq[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_LIGHTFREQ}; -static int bandingfilter[] = {[0 ... W9968CF_MAX_DEVICES-1]= - W9968CF_BANDINGFILTER}; -static short clockdiv[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLOCKDIV}; -static int backlight[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_BACKLIGHT}; -static int mirror[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_MIRROR}; -static int monochrome[] = {[0 ... W9968CF_MAX_DEVICES-1]=W9968CF_MONOCHROME}; -static unsigned int brightness[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_BRIGHTNESS}; -static unsigned int hue[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_HUE}; -static unsigned int colour[]={[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_COLOUR}; -static unsigned int contrast[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_CONTRAST}; -static unsigned int whiteness[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_WHITENESS}; -#ifdef W9968CF_DEBUG -static unsigned short debug = W9968CF_DEBUG_LEVEL; -static int specific_debug = W9968CF_SPECIFIC_DEBUG; -#endif - -static unsigned int param_nv[24]; /* number of values per parameter */ - -#ifdef CONFIG_KMOD -module_param(ovmod_load, bool, 0644); -#endif -module_param(simcams, ushort, 0644); -module_param_array(video_nr, short, ¶m_nv[0], 0444); -module_param_array(packet_size, uint, ¶m_nv[1], 0444); -module_param_array(max_buffers, ushort, ¶m_nv[2], 0444); -module_param_array(double_buffer, bool, ¶m_nv[3], 0444); -module_param_array(clamping, bool, ¶m_nv[4], 0444); -module_param_array(filter_type, ushort, ¶m_nv[5], 0444); -module_param_array(largeview, bool, ¶m_nv[6], 0444); -module_param_array(decompression, ushort, ¶m_nv[7], 0444); -module_param_array(upscaling, bool, ¶m_nv[8], 0444); -module_param_array(force_palette, ushort, ¶m_nv[9], 0444); -module_param_array(force_rgb, ushort, ¶m_nv[10], 0444); -module_param_array(autobright, bool, ¶m_nv[11], 0444); -module_param_array(autoexp, bool, ¶m_nv[12], 0444); -module_param_array(lightfreq, ushort, ¶m_nv[13], 0444); -module_param_array(bandingfilter, bool, ¶m_nv[14], 0444); -module_param_array(clockdiv, short, ¶m_nv[15], 0444); -module_param_array(backlight, bool, ¶m_nv[16], 0444); -module_param_array(mirror, bool, ¶m_nv[17], 0444); -module_param_array(monochrome, bool, ¶m_nv[18], 0444); -module_param_array(brightness, uint, ¶m_nv[19], 0444); -module_param_array(hue, uint, ¶m_nv[20], 0444); -module_param_array(colour, uint, ¶m_nv[21], 0444); -module_param_array(contrast, uint, ¶m_nv[22], 0444); -module_param_array(whiteness, uint, ¶m_nv[23], 0444); -#ifdef W9968CF_DEBUG -module_param(debug, ushort, 0644); -module_param(specific_debug, bool, 0644); -#endif - -#ifdef CONFIG_KMOD -MODULE_PARM_DESC(ovmod_load, - "\n<0|1> Automatic 'ovcamchip' module loading." - "\n0 disabled, 1 enabled." - "\nIf enabled,'insmod' searches for the required 'ovcamchip'" - "\nmodule in the system, according to its configuration, and" - "\nattempts to load that module automatically. This action is" - "\nperformed once as soon as the 'w9968cf' module is loaded" - "\ninto memory." - "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"." - "\n"); -#endif -MODULE_PARM_DESC(simcams, - "\n Number of cameras allowed to stream simultaneously." - "\nn may vary from 0 to " - __MODULE_STRING(W9968CF_MAX_DEVICES)"." - "\nDefault value is "__MODULE_STRING(W9968CF_SIMCAMS)"." - "\n"); -MODULE_PARM_DESC(video_nr, - "\n<-1|n[,...]> Specify V4L minor mode number." - "\n -1 = use next available (default)" - "\n n = use minor number n (integer >= 0)" - "\nYou can specify up to "__MODULE_STRING(W9968CF_MAX_DEVICES) - " cameras this way." - "\nFor example:" - "\nvideo_nr=-1,2,-1 would assign minor number 2 to" - "\nthe second camera and use auto for the first" - "\none and for every other camera." - "\n"); -MODULE_PARM_DESC(packet_size, - "\n Specify the maximum data payload" - "\nsize in bytes for alternate settings, for each device." - "\nn is scaled between 63 and 1023 " - "(default is "__MODULE_STRING(W9968CF_PACKET_SIZE)")." - "\n"); -MODULE_PARM_DESC(max_buffers, - "\n For advanced users." - "\nSpecify the maximum number of video frame buffers" - "\nto allocate for each device, from 2 to " - __MODULE_STRING(W9968CF_MAX_BUFFERS) - ". (default is "__MODULE_STRING(W9968CF_BUFFERS)")." - "\n"); -MODULE_PARM_DESC(double_buffer, - "\n<0|1[,...]> " - "Hardware double buffering: 0 disabled, 1 enabled." - "\nIt should be enabled if you want smooth video output: if" - "\nyou obtain out of sync. video, disable it, or try to" - "\ndecrease the 'clockdiv' module parameter value." - "\nDefault value is "__MODULE_STRING(W9968CF_DOUBLE_BUFFER) - " for every device." - "\n"); -MODULE_PARM_DESC(clamping, - "\n<0|1[,...]> Video data clamping: 0 disabled, 1 enabled." - "\nDefault value is "__MODULE_STRING(W9968CF_CLAMPING) - " for every device." - "\n"); -MODULE_PARM_DESC(filter_type, - "\n<0|1|2[,...]> Video filter type." - "\n0 none, 1 (1-2-1) 3-tap filter, " - "2 (2-3-6-3-2) 5-tap filter." - "\nDefault value is "__MODULE_STRING(W9968CF_FILTER_TYPE) - " for every device." - "\nThe filter is used to reduce noise and aliasing artifacts" - "\nproduced by the CCD or CMOS image sensor, and the scaling" - " process." - "\n"); -MODULE_PARM_DESC(largeview, - "\n<0|1[,...]> Large view: 0 disabled, 1 enabled." - "\nDefault value is "__MODULE_STRING(W9968CF_LARGEVIEW) - " for every device." - "\n"); -MODULE_PARM_DESC(upscaling, - "\n<0|1[,...]> Software scaling (for non-compressed video):" - "\n0 disabled, 1 enabled." - "\nDisable it if you have a slow CPU or you don't have" - " enough memory." - "\nDefault value is "__MODULE_STRING(W9968CF_UPSCALING) - " for every device." - "\nIf 'w9968cf-vpp' is not present, this parameter is" - " set to 0." - "\n"); -MODULE_PARM_DESC(decompression, - "\n<0|1|2[,...]> Software video decompression:" - "\n- 0 disables decompression (doesn't allow formats needing" - " decompression)" - "\n- 1 forces decompression (allows formats needing" - " decompression only);" - "\n- 2 allows any permitted formats." - "\nFormats supporting compressed video are YUV422P and" - " YUV420P/YUV420 " - "\nin any resolutions where both width and height are " - "a multiple of 16." - "\nDefault value is "__MODULE_STRING(W9968CF_DECOMPRESSION) - " for every device." - "\nIf 'w9968cf-vpp' is not present, forcing decompression is " - "\nnot allowed; in this case this parameter is set to 2." - "\n"); -MODULE_PARM_DESC(force_palette, - "\n<0" - "|" __MODULE_STRING(VIDEO_PALETTE_UYVY) - "|" __MODULE_STRING(VIDEO_PALETTE_YUV420) - "|" __MODULE_STRING(VIDEO_PALETTE_YUV422P) - "|" __MODULE_STRING(VIDEO_PALETTE_YUV420P) - "|" __MODULE_STRING(VIDEO_PALETTE_YUYV) - "|" __MODULE_STRING(VIDEO_PALETTE_YUV422) - "|" __MODULE_STRING(VIDEO_PALETTE_GREY) - "|" __MODULE_STRING(VIDEO_PALETTE_RGB555) - "|" __MODULE_STRING(VIDEO_PALETTE_RGB565) - "|" __MODULE_STRING(VIDEO_PALETTE_RGB24) - "|" __MODULE_STRING(VIDEO_PALETTE_RGB32) - "[,...]>" - " Force picture palette." - "\nIn order:" - "\n- 0 allows any of the following formats:" - "\n- UYVY 16 bpp - Original video, compression disabled" - "\n- YUV420 12 bpp - Original video, compression enabled" - "\n- YUV422P 16 bpp - Original video, compression enabled" - "\n- YUV420P 12 bpp - Original video, compression enabled" - "\n- YUVY 16 bpp - Software conversion from UYVY" - "\n- YUV422 16 bpp - Software conversion from UYVY" - "\n- GREY 8 bpp - Software conversion from UYVY" - "\n- RGB555 16 bpp - Software conversion from UYVY" - "\n- RGB565 16 bpp - Software conversion from UYVY" - "\n- RGB24 24 bpp - Software conversion from UYVY" - "\n- RGB32 32 bpp - Software conversion from UYVY" - "\nWhen not 0, this parameter will override 'decompression'." - "\nDefault value is 0 for every device." - "\nInitial palette is " - __MODULE_STRING(W9968CF_PALETTE_DECOMP_ON)"." - "\nIf 'w9968cf-vpp' is not present, this parameter is" - " set to 9 (UYVY)." - "\n"); -MODULE_PARM_DESC(force_rgb, - "\n<0|1[,...]> Read RGB video data instead of BGR:" - "\n 1 = use RGB component ordering." - "\n 0 = use BGR component ordering." - "\nThis parameter has effect when using RGBX palettes only." - "\nDefault value is "__MODULE_STRING(W9968CF_FORCE_RGB) - " for every device." - "\n"); -MODULE_PARM_DESC(autobright, - "\n<0|1[,...]> Image sensor automatically changes brightness:" - "\n 0 = no, 1 = yes" - "\nDefault value is "__MODULE_STRING(W9968CF_AUTOBRIGHT) - " for every device." - "\n"); -MODULE_PARM_DESC(autoexp, - "\n<0|1[,...]> Image sensor automatically changes exposure:" - "\n 0 = no, 1 = yes" - "\nDefault value is "__MODULE_STRING(W9968CF_AUTOEXP) - " for every device." - "\n"); -MODULE_PARM_DESC(lightfreq, - "\n<50|60[,...]> Light frequency in Hz:" - "\n 50 for European and Asian lighting," - " 60 for American lighting." - "\nDefault value is "__MODULE_STRING(W9968CF_LIGHTFREQ) - " for every device." - "\n"); -MODULE_PARM_DESC(bandingfilter, - "\n<0|1[,...]> Banding filter to reduce effects of" - " fluorescent lighting:" - "\n 0 disabled, 1 enabled." - "\nThis filter tries to reduce the pattern of horizontal" - "\nlight/dark bands caused by some (usually fluorescent)" - " lighting." - "\nDefault value is "__MODULE_STRING(W9968CF_BANDINGFILTER) - " for every device." - "\n"); -MODULE_PARM_DESC(clockdiv, - "\n<-1|n[,...]> " - "Force pixel clock divisor to a specific value (for experts):" - "\n n may vary from 0 to 127." - "\n -1 for automatic value." - "\nSee also the 'double_buffer' module parameter." - "\nDefault value is "__MODULE_STRING(W9968CF_CLOCKDIV) - " for every device." - "\n"); -MODULE_PARM_DESC(backlight, - "\n<0|1[,...]> Objects are lit from behind:" - "\n 0 = no, 1 = yes" - "\nDefault value is "__MODULE_STRING(W9968CF_BACKLIGHT) - " for every device." - "\n"); -MODULE_PARM_DESC(mirror, - "\n<0|1[,...]> Reverse image horizontally:" - "\n 0 = no, 1 = yes" - "\nDefault value is "__MODULE_STRING(W9968CF_MIRROR) - " for every device." - "\n"); -MODULE_PARM_DESC(monochrome, - "\n<0|1[,...]> Use image sensor as monochrome sensor:" - "\n 0 = no, 1 = yes" - "\nNot all the sensors support monochrome color." - "\nDefault value is "__MODULE_STRING(W9968CF_MONOCHROME) - " for every device." - "\n"); -MODULE_PARM_DESC(brightness, - "\n Set picture brightness (0-65535)." - "\nDefault value is "__MODULE_STRING(W9968CF_BRIGHTNESS) - " for every device." - "\nThis parameter has no effect if 'autobright' is enabled." - "\n"); -MODULE_PARM_DESC(hue, - "\n Set picture hue (0-65535)." - "\nDefault value is "__MODULE_STRING(W9968CF_HUE) - " for every device." - "\n"); -MODULE_PARM_DESC(colour, - "\n Set picture saturation (0-65535)." - "\nDefault value is "__MODULE_STRING(W9968CF_COLOUR) - " for every device." - "\n"); -MODULE_PARM_DESC(contrast, - "\n Set picture contrast (0-65535)." - "\nDefault value is "__MODULE_STRING(W9968CF_CONTRAST) - " for every device." - "\n"); -MODULE_PARM_DESC(whiteness, - "\n Set picture whiteness (0-65535)." - "\nDefault value is "__MODULE_STRING(W9968CF_WHITENESS) - " for every device." - "\n"); -#ifdef W9968CF_DEBUG -MODULE_PARM_DESC(debug, - "\n Debugging information level, from 0 to 6:" - "\n0 = none (use carefully)" - "\n1 = critical errors" - "\n2 = significant informations" - "\n3 = configuration or general messages" - "\n4 = warnings" - "\n5 = called functions" - "\n6 = function internals" - "\nLevel 5 and 6 are useful for testing only, when only " - "one device is used." - "\nDefault value is "__MODULE_STRING(W9968CF_DEBUG_LEVEL)"." - "\n"); -MODULE_PARM_DESC(specific_debug, - "\n<0|1> Enable or disable specific debugging messages:" - "\n0 = print messages concerning every level" - " <= 'debug' level." - "\n1 = print messages concerning the level" - " indicated by 'debug'." - "\nDefault value is " - __MODULE_STRING(W9968CF_SPECIFIC_DEBUG)"." - "\n"); -#endif /* W9968CF_DEBUG */ - - - -/**************************************************************************** - * Some prototypes * - ****************************************************************************/ - -/* Video4linux interface */ -static struct file_operations w9968cf_fops; -static int w9968cf_open(struct inode*, struct file*); -static int w9968cf_release(struct inode*, struct file*); -static int w9968cf_mmap(struct file*, struct vm_area_struct*); -static int w9968cf_ioctl(struct inode*, struct file*, unsigned, unsigned long); -static ssize_t w9968cf_read(struct file*, char __user *, size_t, loff_t*); -static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int, - void __user *); - -/* USB-specific */ -static int w9968cf_start_transfer(struct w9968cf_device*); -static int w9968cf_stop_transfer(struct w9968cf_device*); -static int w9968cf_write_reg(struct w9968cf_device*, u16 value, u16 index); -static int w9968cf_read_reg(struct w9968cf_device*, u16 index); -static int w9968cf_write_fsb(struct w9968cf_device*, u16* data); -static int w9968cf_write_sb(struct w9968cf_device*, u16 value); -static int w9968cf_read_sb(struct w9968cf_device*); -static int w9968cf_upload_quantizationtables(struct w9968cf_device*); -static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs); - -/* Low-level I2C (SMBus) I/O */ -static int w9968cf_smbus_start(struct w9968cf_device*); -static int w9968cf_smbus_stop(struct w9968cf_device*); -static int w9968cf_smbus_write_byte(struct w9968cf_device*, u8 v); -static int w9968cf_smbus_read_byte(struct w9968cf_device*, u8* v); -static int w9968cf_smbus_write_ack(struct w9968cf_device*); -static int w9968cf_smbus_read_ack(struct w9968cf_device*); -static int w9968cf_smbus_refresh_bus(struct w9968cf_device*); -static int w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam, - u16 address, u8* value); -static int w9968cf_i2c_adap_read_byte_data(struct w9968cf_device*, u16 address, - u8 subaddress, u8* value); -static int w9968cf_i2c_adap_write_byte(struct w9968cf_device*, - u16 address, u8 subaddress); -static int w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device*, - u16 address, u8 subaddress, - u8 value); - -/* I2C interface to kernel */ -static int w9968cf_i2c_init(struct w9968cf_device*); -static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data*); -static u32 w9968cf_i2c_func(struct i2c_adapter*); -static int w9968cf_i2c_attach_inform(struct i2c_client*); -static int w9968cf_i2c_detach_inform(struct i2c_client*); -static int w9968cf_i2c_control(struct i2c_adapter*, unsigned int cmd, - unsigned long arg); - -/* Memory management */ -static void* rvmalloc(unsigned long size); -static void rvfree(void *mem, unsigned long size); -static void w9968cf_deallocate_memory(struct w9968cf_device*); -static int w9968cf_allocate_memory(struct w9968cf_device*); - -/* High-level image sensor control functions */ -static int w9968cf_sensor_set_control(struct w9968cf_device*,int cid,int val); -static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val); -static int w9968cf_sensor_cmd(struct w9968cf_device*, - unsigned int cmd, void *arg); -static int w9968cf_sensor_init(struct w9968cf_device*); -static int w9968cf_sensor_update_settings(struct w9968cf_device*); -static int w9968cf_sensor_get_picture(struct w9968cf_device*); -static int w9968cf_sensor_update_picture(struct w9968cf_device*, - struct video_picture pict); - -/* Other helper functions */ -static void w9968cf_configure_camera(struct w9968cf_device*,struct usb_device*, - enum w9968cf_model_id, - const unsigned short dev_nr); -static void w9968cf_adjust_configuration(struct w9968cf_device*); -static int w9968cf_turn_on_led(struct w9968cf_device*); -static int w9968cf_init_chip(struct w9968cf_device*); -static inline u16 w9968cf_valid_palette(u16 palette); -static inline u16 w9968cf_valid_depth(u16 palette); -static inline u8 w9968cf_need_decompression(u16 palette); -static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture); -static int w9968cf_set_window(struct w9968cf_device*, struct video_window); -static int w9968cf_postprocess_frame(struct w9968cf_device*, - struct w9968cf_frame_t*); -static int w9968cf_adjust_window_size(struct w9968cf_device*, u16* w, u16* h); -static void w9968cf_init_framelist(struct w9968cf_device*); -static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num); -static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**); -static void w9968cf_release_resources(struct w9968cf_device*); - - - -/**************************************************************************** - * Symbolic names * - ****************************************************************************/ - -/* Used to represent a list of values and their respective symbolic names */ -struct w9968cf_symbolic_list { - const int num; - const char *name; -}; - -/*-------------------------------------------------------------------------- - Returns the name of the matching element in the symbolic_list array. The - end of the list must be marked with an element that has a NULL name. - --------------------------------------------------------------------------*/ -static inline const char * -symbolic(struct w9968cf_symbolic_list list[], const int num) -{ - int i; - - for (i = 0; list[i].name != NULL; i++) - if (list[i].num == num) - return (list[i].name); - - return "Unknown"; -} - -static struct w9968cf_symbolic_list camlist[] = { - { W9968CF_MOD_GENERIC, "W996[87]CF JPEG USB Dual Mode Camera" }, - { W9968CF_MOD_CLVBWGP, "Creative Labs Video Blaster WebCam Go Plus" }, - - /* Other cameras (having the same descriptors as Generic W996[87]CF) */ - { W9968CF_MOD_ADPVDMA, "Aroma Digi Pen VGA Dual Mode ADG-5000" }, - { W9986CF_MOD_AAU, "AVerMedia AVerTV USB" }, - { W9968CF_MOD_CLVBWG, "Creative Labs Video Blaster WebCam Go" }, - { W9968CF_MOD_LL, "Lebon LDC-035A" }, - { W9968CF_MOD_EEEMC, "Ezonics EZ-802 EZMega Cam" }, - { W9968CF_MOD_OOE, "OmniVision OV8610-EDE" }, - { W9968CF_MOD_ODPVDMPC, "OPCOM Digi Pen VGA Dual Mode Pen Camera" }, - { W9968CF_MOD_PDPII, "Pretec Digi Pen-II" }, - { W9968CF_MOD_PDP480, "Pretec DigiPen-480" }, - - { -1, NULL } -}; - -static struct w9968cf_symbolic_list senlist[] = { - { CC_OV76BE, "OV76BE" }, - { CC_OV7610, "OV7610" }, - { CC_OV7620, "OV7620" }, - { CC_OV7620AE, "OV7620AE" }, - { CC_OV6620, "OV6620" }, - { CC_OV6630, "OV6630" }, - { CC_OV6630AE, "OV6630AE" }, - { CC_OV6630AF, "OV6630AF" }, - { -1, NULL } -}; - -/* Video4Linux1 palettes */ -static struct w9968cf_symbolic_list v4l1_plist[] = { - { VIDEO_PALETTE_GREY, "GREY" }, - { VIDEO_PALETTE_HI240, "HI240" }, - { VIDEO_PALETTE_RGB565, "RGB565" }, - { VIDEO_PALETTE_RGB24, "RGB24" }, - { VIDEO_PALETTE_RGB32, "RGB32" }, - { VIDEO_PALETTE_RGB555, "RGB555" }, - { VIDEO_PALETTE_YUV422, "YUV422" }, - { VIDEO_PALETTE_YUYV, "YUYV" }, - { VIDEO_PALETTE_UYVY, "UYVY" }, - { VIDEO_PALETTE_YUV420, "YUV420" }, - { VIDEO_PALETTE_YUV411, "YUV411" }, - { VIDEO_PALETTE_RAW, "RAW" }, - { VIDEO_PALETTE_YUV422P, "YUV422P" }, - { VIDEO_PALETTE_YUV411P, "YUV411P" }, - { VIDEO_PALETTE_YUV420P, "YUV420P" }, - { VIDEO_PALETTE_YUV410P, "YUV410P" }, - { -1, NULL } -}; - -/* Decoder error codes: */ -static struct w9968cf_symbolic_list decoder_errlist[] = { - { W9968CF_DEC_ERR_CORRUPTED_DATA, "Corrupted data" }, - { W9968CF_DEC_ERR_BUF_OVERFLOW, "Buffer overflow" }, - { W9968CF_DEC_ERR_NO_SOI, "SOI marker not found" }, - { W9968CF_DEC_ERR_NO_SOF0, "SOF0 marker not found" }, - { W9968CF_DEC_ERR_NO_SOS, "SOS marker not found" }, - { W9968CF_DEC_ERR_NO_EOI, "EOI marker not found" }, - { -1, NULL } -}; - -/* URB error codes: */ -static struct w9968cf_symbolic_list urb_errlist[] = { - { -ENOMEM, "No memory for allocation of internal structures" }, - { -ENOSPC, "The host controller's bandwidth is already consumed" }, - { -ENOENT, "URB was canceled by unlink_urb" }, - { -EXDEV, "ISO transfer only partially completed" }, - { -EAGAIN, "Too match scheduled for the future" }, - { -ENXIO, "URB already queued" }, - { -EFBIG, "Too much ISO frames requested" }, - { -ENOSR, "Buffer error (overrun)" }, - { -EPIPE, "Specified endpoint is stalled (device not responding)"}, - { -EOVERFLOW, "Babble (bad cable?)" }, - { -EPROTO, "Bit-stuff error (bad cable?)" }, - { -EILSEQ, "CRC/Timeout" }, - { -ETIMEDOUT, "NAK (device does not respond)" }, - { -1, NULL } -}; - - - -/**************************************************************************** - * Memory management functions * - ****************************************************************************/ -static void* rvmalloc(unsigned long size) -{ - void* mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - - -static void rvfree(void* mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - - -/*-------------------------------------------------------------------------- - Deallocate previously allocated memory. - --------------------------------------------------------------------------*/ -static void w9968cf_deallocate_memory(struct w9968cf_device* cam) -{ - u8 i; - - /* Free the isochronous transfer buffers */ - for (i = 0; i < W9968CF_URBS; i++) { - kfree(cam->transfer_buffer[i]); - cam->transfer_buffer[i] = NULL; - } - - /* Free temporary frame buffer */ - if (cam->frame_tmp.buffer) { - rvfree(cam->frame_tmp.buffer, cam->frame_tmp.size); - cam->frame_tmp.buffer = NULL; - } - - /* Free helper buffer */ - if (cam->frame_vpp.buffer) { - rvfree(cam->frame_vpp.buffer, cam->frame_vpp.size); - cam->frame_vpp.buffer = NULL; - } - - /* Free video frame buffers */ - if (cam->frame[0].buffer) { - rvfree(cam->frame[0].buffer, cam->nbuffers*cam->frame[0].size); - cam->frame[0].buffer = NULL; - } - - cam->nbuffers = 0; - - DBG(5, "Memory successfully deallocated") -} - - -/*-------------------------------------------------------------------------- - Allocate memory buffers for USB transfers and video frames. - This function is called by open() only. - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_allocate_memory(struct w9968cf_device* cam) -{ - const u16 p_size = wMaxPacketSize[cam->altsetting-1]; - void* buff = NULL; - unsigned long hw_bufsize, vpp_bufsize; - u8 i, bpp; - - /* NOTE: Deallocation is done elsewhere in case of error */ - - /* Calculate the max amount of raw data per frame from the device */ - hw_bufsize = cam->maxwidth*cam->maxheight*2; - - /* Calculate the max buf. size needed for post-processing routines */ - bpp = (w9968cf_vpp) ? 4 : 2; - if (cam->upscaling) - vpp_bufsize = max(W9968CF_MAX_WIDTH*W9968CF_MAX_HEIGHT*bpp, - cam->maxwidth*cam->maxheight*bpp); - else - vpp_bufsize = cam->maxwidth*cam->maxheight*bpp; - - /* Allocate memory for the isochronous transfer buffers */ - for (i = 0; i < W9968CF_URBS; i++) { - if (!(cam->transfer_buffer[i] = - kzalloc(W9968CF_ISO_PACKETS*p_size, GFP_KERNEL))) { - DBG(1, "Couldn't allocate memory for the isochronous " - "transfer buffers (%u bytes)", - p_size * W9968CF_ISO_PACKETS) - return -ENOMEM; - } - } - - /* Allocate memory for the temporary frame buffer */ - if (!(cam->frame_tmp.buffer = rvmalloc(hw_bufsize))) { - DBG(1, "Couldn't allocate memory for the temporary " - "video frame buffer (%lu bytes)", hw_bufsize) - return -ENOMEM; - } - cam->frame_tmp.size = hw_bufsize; - cam->frame_tmp.number = -1; - - /* Allocate memory for the helper buffer */ - if (w9968cf_vpp) { - if (!(cam->frame_vpp.buffer = rvmalloc(vpp_bufsize))) { - DBG(1, "Couldn't allocate memory for the helper buffer" - " (%lu bytes)", vpp_bufsize) - return -ENOMEM; - } - cam->frame_vpp.size = vpp_bufsize; - } else - cam->frame_vpp.buffer = NULL; - - /* Allocate memory for video frame buffers */ - cam->nbuffers = cam->max_buffers; - while (cam->nbuffers >= 2) { - if ((buff = rvmalloc(cam->nbuffers * vpp_bufsize))) - break; - else - cam->nbuffers--; - } - - if (!buff) { - DBG(1, "Couldn't allocate memory for the video frame buffers") - cam->nbuffers = 0; - return -ENOMEM; - } - - if (cam->nbuffers != cam->max_buffers) - DBG(2, "Couldn't allocate memory for %u video frame buffers. " - "Only memory for %u buffers has been allocated", - cam->max_buffers, cam->nbuffers) - - for (i = 0; i < cam->nbuffers; i++) { - cam->frame[i].buffer = buff + i*vpp_bufsize; - cam->frame[i].size = vpp_bufsize; - cam->frame[i].number = i; - /* Circular list */ - if (i != cam->nbuffers-1) - cam->frame[i].next = &cam->frame[i+1]; - else - cam->frame[i].next = &cam->frame[0]; - cam->frame[i].status = F_UNUSED; - } - - DBG(5, "Memory successfully allocated") - return 0; -} - - - -/**************************************************************************** - * USB-specific functions * - ****************************************************************************/ - -/*-------------------------------------------------------------------------- - This is an handler function which is called after the URBs are completed. - It collects multiple data packets coming from the camera by putting them - into frame buffers: one or more zero data length data packets are used to - mark the end of a video frame; the first non-zero data packet is the start - of the next video frame; if an error is encountered in a packet, the entire - video frame is discarded and grabbed again. - If there are no requested frames in the FIFO list, packets are collected into - a temporary buffer. - --------------------------------------------------------------------------*/ -static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs) -{ - struct w9968cf_device* cam = (struct w9968cf_device*)urb->context; - struct w9968cf_frame_t** f; - unsigned int len, status; - void* pos; - u8 i; - int err = 0; - - if ((!cam->streaming) || cam->disconnected) { - DBG(4, "Got interrupt, but not streaming") - return; - } - - /* "(*f)" will be used instead of "cam->frame_current" */ - f = &cam->frame_current; - - /* If a frame has been requested and we are grabbing into - the temporary frame, we'll switch to that requested frame */ - if ((*f) == &cam->frame_tmp && *cam->requested_frame) { - if (cam->frame_tmp.status == F_GRABBING) { - w9968cf_pop_frame(cam, &cam->frame_current); - (*f)->status = F_GRABBING; - (*f)->length = cam->frame_tmp.length; - memcpy((*f)->buffer, cam->frame_tmp.buffer, - (*f)->length); - DBG(6, "Switched from temp. frame to frame #%d", - (*f)->number) - } - } - - for (i = 0; i < urb->number_of_packets; i++) { - len = urb->iso_frame_desc[i].actual_length; - status = urb->iso_frame_desc[i].status; - pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; - - if (status && len != 0) { - DBG(4, "URB failed, error in data packet " - "(error #%u, %s)", - status, symbolic(urb_errlist, status)) - (*f)->status = F_ERROR; - continue; - } - - if (len) { /* start of frame */ - - if ((*f)->status == F_UNUSED) { - (*f)->status = F_GRABBING; - (*f)->length = 0; - } - - /* Buffer overflows shouldn't happen, however...*/ - if ((*f)->length + len > (*f)->size) { - DBG(4, "Buffer overflow: bad data packets") - (*f)->status = F_ERROR; - } - - if ((*f)->status == F_GRABBING) { - memcpy((*f)->buffer + (*f)->length, pos, len); - (*f)->length += len; - } - - } else if ((*f)->status == F_GRABBING) { /* end of frame */ - - DBG(6, "Frame #%d successfully grabbed", (*f)->number) - - if (cam->vpp_flag & VPP_DECOMPRESSION) { - err = w9968cf_vpp->check_headers((*f)->buffer, - (*f)->length); - if (err) { - DBG(4, "Skip corrupted frame: %s", - symbolic(decoder_errlist, err)) - (*f)->status = F_UNUSED; - continue; /* grab this frame again */ - } - } - - (*f)->status = F_READY; - (*f)->queued = 0; - - /* Take a pointer to the new frame from the FIFO list. - If the list is empty,we'll use the temporary frame*/ - if (*cam->requested_frame) - w9968cf_pop_frame(cam, &cam->frame_current); - else { - cam->frame_current = &cam->frame_tmp; - (*f)->status = F_UNUSED; - } - - } else if ((*f)->status == F_ERROR) - (*f)->status = F_UNUSED; /* grab it again */ - - PDBGG("Frame length %lu | pack.#%u | pack.len. %u | state %d", - (unsigned long)(*f)->length, i, len, (*f)->status) - - } /* end for */ - - /* Resubmit this URB */ - urb->dev = cam->usbdev; - urb->status = 0; - spin_lock(&cam->urb_lock); - if (cam->streaming) - if ((err = usb_submit_urb(urb, GFP_ATOMIC))) { - cam->misconfigured = 1; - DBG(1, "Couldn't resubmit the URB: error %d, %s", - err, symbolic(urb_errlist, err)) - } - spin_unlock(&cam->urb_lock); - - /* Wake up the user process */ - wake_up_interruptible(&cam->wait_queue); -} - - -/*--------------------------------------------------------------------------- - Setup the URB structures for the isochronous transfer. - Submit the URBs so that the data transfer begins. - Return 0 on success, a negative number otherwise. - ---------------------------------------------------------------------------*/ -static int w9968cf_start_transfer(struct w9968cf_device* cam) -{ - struct usb_device *udev = cam->usbdev; - struct urb* urb; - const u16 p_size = wMaxPacketSize[cam->altsetting-1]; - u16 w, h, d; - int vidcapt; - u32 t_size; - int err = 0; - s8 i, j; - - for (i = 0; i < W9968CF_URBS; i++) { - urb = usb_alloc_urb(W9968CF_ISO_PACKETS, GFP_KERNEL); - cam->urb[i] = urb; - if (!urb) { - for (j = 0; j < i; j++) - usb_free_urb(cam->urb[j]); - DBG(1, "Couldn't allocate the URB structures") - return -ENOMEM; - } - - urb->dev = udev; - urb->context = (void*)cam; - urb->pipe = usb_rcvisocpipe(udev, 1); - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = W9968CF_ISO_PACKETS; - urb->complete = w9968cf_urb_complete; - urb->transfer_buffer = cam->transfer_buffer[i]; - urb->transfer_buffer_length = p_size*W9968CF_ISO_PACKETS; - urb->interval = 1; - for (j = 0; j < W9968CF_ISO_PACKETS; j++) { - urb->iso_frame_desc[j].offset = p_size*j; - urb->iso_frame_desc[j].length = p_size; - } - } - - /* Transfer size per frame, in WORD ! */ - d = cam->hw_depth; - w = cam->hw_width; - h = cam->hw_height; - - t_size = (w*h*d)/16; - - err = w9968cf_write_reg(cam, 0xbf17, 0x00); /* reset everything */ - err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* normal operation */ - - /* Transfer size */ - err += w9968cf_write_reg(cam, t_size & 0xffff, 0x3d); /* low bits */ - err += w9968cf_write_reg(cam, t_size >> 16, 0x3e); /* high bits */ - - if (cam->vpp_flag & VPP_DECOMPRESSION) - err += w9968cf_upload_quantizationtables(cam); - - vidcapt = w9968cf_read_reg(cam, 0x16); /* read picture settings */ - err += w9968cf_write_reg(cam, vidcapt|0x8000, 0x16); /* capt. enable */ - - err += usb_set_interface(udev, 0, cam->altsetting); - err += w9968cf_write_reg(cam, 0x8a05, 0x3c); /* USB FIFO enable */ - - if (err || (vidcapt < 0)) { - for (i = 0; i < W9968CF_URBS; i++) - usb_free_urb(cam->urb[i]); - DBG(1, "Couldn't tell the camera to start the data transfer") - return err; - } - - w9968cf_init_framelist(cam); - - /* Begin to grab into the temporary buffer */ - cam->frame_tmp.status = F_UNUSED; - cam->frame_tmp.queued = 0; - cam->frame_current = &cam->frame_tmp; - - if (!(cam->vpp_flag & VPP_DECOMPRESSION)) - DBG(5, "Isochronous transfer size: %lu bytes/frame", - (unsigned long)t_size*2) - - DBG(5, "Starting the isochronous transfer...") - - cam->streaming = 1; - - /* Submit the URBs */ - for (i = 0; i < W9968CF_URBS; i++) { - err = usb_submit_urb(cam->urb[i], GFP_KERNEL); - if (err) { - cam->streaming = 0; - for (j = i-1; j >= 0; j--) { - usb_kill_urb(cam->urb[j]); - usb_free_urb(cam->urb[j]); - } - DBG(1, "Couldn't send a transfer request to the " - "USB core (error #%d, %s)", err, - symbolic(urb_errlist, err)) - return err; - } - } - - return 0; -} - - -/*-------------------------------------------------------------------------- - Stop the isochronous transfer and set alternate setting to 0 (0Mb/s). - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_stop_transfer(struct w9968cf_device* cam) -{ - struct usb_device *udev = cam->usbdev; - unsigned long lock_flags; - int err = 0; - s8 i; - - if (!cam->streaming) - return 0; - - /* This avoids race conditions with usb_submit_urb() - in the URB completition handler */ - spin_lock_irqsave(&cam->urb_lock, lock_flags); - cam->streaming = 0; - spin_unlock_irqrestore(&cam->urb_lock, lock_flags); - - for (i = W9968CF_URBS-1; i >= 0; i--) - if (cam->urb[i]) { - usb_kill_urb(cam->urb[i]); - usb_free_urb(cam->urb[i]); - cam->urb[i] = NULL; - } - - if (cam->disconnected) - goto exit; - - err = w9968cf_write_reg(cam, 0x0a05, 0x3c); /* stop USB transfer */ - err += usb_set_interface(udev, 0, 0); /* 0 Mb/s */ - err += w9968cf_write_reg(cam, 0x0000, 0x39); /* disable JPEG encoder */ - err += w9968cf_write_reg(cam, 0x0000, 0x16); /* stop video capture */ - - if (err) { - DBG(2, "Failed to tell the camera to stop the isochronous " - "transfer. However this is not a critical error.") - return -EIO; - } - -exit: - DBG(5, "Isochronous transfer stopped") - return 0; -} - - -/*-------------------------------------------------------------------------- - Write a W9968CF register. - Return 0 on success, -1 otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_write_reg(struct w9968cf_device* cam, u16 value, u16 index) -{ - struct usb_device* udev = cam->usbdev; - int res; - - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - value, index, NULL, 0, W9968CF_USB_CTRL_TIMEOUT); - - if (res < 0) - DBG(4, "Failed to write a register " - "(value 0x%04X, index 0x%02X, error #%d, %s)", - value, index, res, symbolic(urb_errlist, res)) - - return (res >= 0) ? 0 : -1; -} - - -/*-------------------------------------------------------------------------- - Read a W9968CF register. - Return the register value on success, -1 otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_read_reg(struct w9968cf_device* cam, u16 index) -{ - struct usb_device* udev = cam->usbdev; - u16* buff = cam->control_buffer; - int res; - - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 1, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, buff, 2, W9968CF_USB_CTRL_TIMEOUT); - - if (res < 0) - DBG(4, "Failed to read a register " - "(index 0x%02X, error #%d, %s)", - index, res, symbolic(urb_errlist, res)) - - return (res >= 0) ? (int)(*buff) : -1; -} - - -/*-------------------------------------------------------------------------- - Write 64-bit data to the fast serial bus registers. - Return 0 on success, -1 otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_write_fsb(struct w9968cf_device* cam, u16* data) -{ - struct usb_device* udev = cam->usbdev; - u16 value; - int res; - - value = *data++; - - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - value, 0x06, data, 6, W9968CF_USB_CTRL_TIMEOUT); - - if (res < 0) - DBG(4, "Failed to write the FSB registers " - "(error #%d, %s)", res, symbolic(urb_errlist, res)) - - return (res >= 0) ? 0 : -1; -} - - -/*-------------------------------------------------------------------------- - Write data to the serial bus control register. - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_write_sb(struct w9968cf_device* cam, u16 value) -{ - int err = 0; - - err = w9968cf_write_reg(cam, value, 0x01); - udelay(W9968CF_I2C_BUS_DELAY); - - return err; -} - - -/*-------------------------------------------------------------------------- - Read data from the serial bus control register. - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_read_sb(struct w9968cf_device* cam) -{ - int v = 0; - - v = w9968cf_read_reg(cam, 0x01); - udelay(W9968CF_I2C_BUS_DELAY); - - return v; -} - - -/*-------------------------------------------------------------------------- - Upload quantization tables for the JPEG compression. - This function is called by w9968cf_start_transfer(). - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_upload_quantizationtables(struct w9968cf_device* cam) -{ - u16 a, b; - int err = 0, i, j; - - err += w9968cf_write_reg(cam, 0x0010, 0x39); /* JPEG clock enable */ - - for (i = 0, j = 0; i < 32; i++, j += 2) { - a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8); - b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8); - err += w9968cf_write_reg(cam, a, 0x40+i); - err += w9968cf_write_reg(cam, b, 0x60+i); - } - err += w9968cf_write_reg(cam, 0x0012, 0x39); /* JPEG encoder enable */ - - return err; -} - - - -/**************************************************************************** - * Low-level I2C I/O functions. * - * The adapter supports the following I2C transfer functions: * - * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) * - * i2c_adap_read_byte_data() * - * i2c_adap_read_byte() * - ****************************************************************************/ - -static int w9968cf_smbus_start(struct w9968cf_device* cam) -{ - int err = 0; - - err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ - err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ - - return err; -} - - -static int w9968cf_smbus_stop(struct w9968cf_device* cam) -{ - int err = 0; - - err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ - err += w9968cf_write_sb(cam, 0x0013); /* SDE=1, SDA=1, SCL=1 */ - - return err; -} - - -static int w9968cf_smbus_write_byte(struct w9968cf_device* cam, u8 v) -{ - u8 bit; - int err = 0, sda; - - for (bit = 0 ; bit < 8 ; bit++) { - sda = (v & 0x80) ? 2 : 0; - v <<= 1; - /* SDE=1, SDA=sda, SCL=0 */ - err += w9968cf_write_sb(cam, 0x10 | sda); - /* SDE=1, SDA=sda, SCL=1 */ - err += w9968cf_write_sb(cam, 0x11 | sda); - /* SDE=1, SDA=sda, SCL=0 */ - err += w9968cf_write_sb(cam, 0x10 | sda); - } - - return err; -} - - -static int w9968cf_smbus_read_byte(struct w9968cf_device* cam, u8* v) -{ - u8 bit; - int err = 0; - - *v = 0; - for (bit = 0 ; bit < 8 ; bit++) { - *v <<= 1; - err += w9968cf_write_sb(cam, 0x0013); - *v |= (w9968cf_read_sb(cam) & 0x0008) ? 1 : 0; - err += w9968cf_write_sb(cam, 0x0012); - } - - return err; -} - - -static int w9968cf_smbus_write_ack(struct w9968cf_device* cam) -{ - int err = 0; - - err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ - err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ - err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ - - return err; -} - - -static int w9968cf_smbus_read_ack(struct w9968cf_device* cam) -{ - int err = 0, sda; - - err += w9968cf_write_sb(cam, 0x0013); /* SDE=1, SDA=1, SCL=1 */ - sda = (w9968cf_read_sb(cam) & 0x08) ? 1 : 0; /* sda = SDA */ - err += w9968cf_write_sb(cam, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - if (sda < 0) - err += sda; - if (sda == 1) { - DBG(6, "Couldn't receive the ACK") - err += -1; - } - - return err; -} - - -/* This seems to refresh the communication through the serial bus */ -static int w9968cf_smbus_refresh_bus(struct w9968cf_device* cam) -{ - int err = 0, j; - - for (j = 1; j <= 10; j++) { - err = w9968cf_write_reg(cam, 0x0020, 0x01); - err += w9968cf_write_reg(cam, 0x0000, 0x01); - if (err) - break; - } - - return err; -} - - -/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ -static int -w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam, - u16 address, u8 subaddress,u8 value) -{ - u16* data = cam->data_buffer; - int err = 0; - - err += w9968cf_smbus_refresh_bus(cam); - - /* Enable SBUS outputs */ - err += w9968cf_write_sb(cam, 0x0020); - - data[0] = 0x082f | ((address & 0x80) ? 0x1500 : 0x0); - data[0] |= (address & 0x40) ? 0x4000 : 0x0; - data[1] = 0x2082 | ((address & 0x40) ? 0x0005 : 0x0); - data[1] |= (address & 0x20) ? 0x0150 : 0x0; - data[1] |= (address & 0x10) ? 0x5400 : 0x0; - data[2] = 0x8208 | ((address & 0x08) ? 0x0015 : 0x0); - data[2] |= (address & 0x04) ? 0x0540 : 0x0; - data[2] |= (address & 0x02) ? 0x5000 : 0x0; - data[3] = 0x1d20 | ((address & 0x02) ? 0x0001 : 0x0); - data[3] |= (address & 0x01) ? 0x0054 : 0x0; - - err += w9968cf_write_fsb(cam, data); - - data[0] = 0x8208 | ((subaddress & 0x80) ? 0x0015 : 0x0); - data[0] |= (subaddress & 0x40) ? 0x0540 : 0x0; - data[0] |= (subaddress & 0x20) ? 0x5000 : 0x0; - data[1] = 0x0820 | ((subaddress & 0x20) ? 0x0001 : 0x0); - data[1] |= (subaddress & 0x10) ? 0x0054 : 0x0; - data[1] |= (subaddress & 0x08) ? 0x1500 : 0x0; - data[1] |= (subaddress & 0x04) ? 0x4000 : 0x0; - data[2] = 0x2082 | ((subaddress & 0x04) ? 0x0005 : 0x0); - data[2] |= (subaddress & 0x02) ? 0x0150 : 0x0; - data[2] |= (subaddress & 0x01) ? 0x5400 : 0x0; - data[3] = 0x001d; - - err += w9968cf_write_fsb(cam, data); - - data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); - data[0] |= (value & 0x40) ? 0x0540 : 0x0; - data[0] |= (value & 0x20) ? 0x5000 : 0x0; - data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0); - data[1] |= (value & 0x10) ? 0x0054 : 0x0; - data[1] |= (value & 0x08) ? 0x1500 : 0x0; - data[1] |= (value & 0x04) ? 0x4000 : 0x0; - data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0); - data[2] |= (value & 0x02) ? 0x0150 : 0x0; - data[2] |= (value & 0x01) ? 0x5400 : 0x0; - data[3] = 0xfe1d; - - err += w9968cf_write_fsb(cam, data); - - /* Disable SBUS outputs */ - err += w9968cf_write_sb(cam, 0x0000); - - if (!err) - DBG(5, "I2C write byte data done, addr.0x%04X, subaddr.0x%02X " - "value 0x%02X", address, subaddress, value) - else - DBG(5, "I2C write byte data failed, addr.0x%04X, " - "subaddr.0x%02X, value 0x%02X", - address, subaddress, value) - - return err; -} - - -/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ -static int -w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam, - u16 address, u8 subaddress, - u8* value) -{ - int err = 0; - - /* Serial data enable */ - err += w9968cf_write_sb(cam, 0x0013); /* don't change ! */ - - err += w9968cf_smbus_start(cam); - err += w9968cf_smbus_write_byte(cam, address); - err += w9968cf_smbus_read_ack(cam); - err += w9968cf_smbus_write_byte(cam, subaddress); - err += w9968cf_smbus_read_ack(cam); - err += w9968cf_smbus_stop(cam); - err += w9968cf_smbus_start(cam); - err += w9968cf_smbus_write_byte(cam, address + 1); - err += w9968cf_smbus_read_ack(cam); - err += w9968cf_smbus_read_byte(cam, value); - err += w9968cf_smbus_write_ack(cam); - err += w9968cf_smbus_stop(cam); - - /* Serial data disable */ - err += w9968cf_write_sb(cam, 0x0000); - - if (!err) - DBG(5, "I2C read byte data done, addr.0x%04X, " - "subaddr.0x%02X, value 0x%02X", - address, subaddress, *value) - else - DBG(5, "I2C read byte data failed, addr.0x%04X, " - "subaddr.0x%02X, wrong value 0x%02X", - address, subaddress, *value) - - return err; -} - - -/* SMBus protocol: S Addr+1 Rd [A] [Value] NA P */ -static int -w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam, - u16 address, u8* value) -{ - int err = 0; - - /* Serial data enable */ - err += w9968cf_write_sb(cam, 0x0013); - - err += w9968cf_smbus_start(cam); - err += w9968cf_smbus_write_byte(cam, address + 1); - err += w9968cf_smbus_read_ack(cam); - err += w9968cf_smbus_read_byte(cam, value); - err += w9968cf_smbus_write_ack(cam); - err += w9968cf_smbus_stop(cam); - - /* Serial data disable */ - err += w9968cf_write_sb(cam, 0x0000); - - if (!err) - DBG(5, "I2C read byte done, addr.0x%04X, " - "value 0x%02X", address, *value) - else - DBG(5, "I2C read byte failed, addr.0x%04X, " - "wrong value 0x%02X", address, *value) - - return err; -} - - -/* SMBus protocol: S Addr Wr [A] Value [A] P */ -static int -w9968cf_i2c_adap_write_byte(struct w9968cf_device* cam, - u16 address, u8 value) -{ - DBG(4, "i2c_write_byte() is an unsupported transfer mode") - return -EINVAL; -} - - - -/**************************************************************************** - * I2C interface to kernel * - ****************************************************************************/ - -static int -w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) -{ - struct w9968cf_device* cam = i2c_get_adapdata(adapter); - u8 i; - int err = 0; - - switch (addr) { - case OV6xx0_SID: - case OV7xx0_SID: - break; - default: - DBG(4, "Rejected slave ID 0x%04X", addr) - return -EINVAL; - } - - if (size == I2C_SMBUS_BYTE) { - /* Why addr <<= 1? See OVXXX0_SID defines in ovcamchip.h */ - addr <<= 1; - - if (read_write == I2C_SMBUS_WRITE) - err = w9968cf_i2c_adap_write_byte(cam, addr, command); - else if (read_write == I2C_SMBUS_READ) - err = w9968cf_i2c_adap_read_byte(cam,addr,&data->byte); - - } else if (size == I2C_SMBUS_BYTE_DATA) { - addr <<= 1; - - if (read_write == I2C_SMBUS_WRITE) - err = w9968cf_i2c_adap_fastwrite_byte_data(cam, addr, - command, data->byte); - else if (read_write == I2C_SMBUS_READ) { - for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) { - err = w9968cf_i2c_adap_read_byte_data(cam,addr, - command, &data->byte); - if (err) { - if (w9968cf_smbus_refresh_bus(cam)) { - err = -EIO; - break; - } - } else - break; - } - - } else - return -EINVAL; - - } else { - DBG(4, "Unsupported I2C transfer mode (%d)", size) - return -EINVAL; - } - - return err; -} - - -static u32 w9968cf_i2c_func(struct i2c_adapter* adap) -{ - return I2C_FUNC_SMBUS_READ_BYTE | - I2C_FUNC_SMBUS_READ_BYTE_DATA | - I2C_FUNC_SMBUS_WRITE_BYTE_DATA; -} - - -static int w9968cf_i2c_attach_inform(struct i2c_client* client) -{ - struct w9968cf_device* cam = i2c_get_adapdata(client->adapter); - int id = client->driver->id, err = 0; - - if (id == I2C_DRIVERID_OVCAMCHIP) { - cam->sensor_client = client; - err = w9968cf_sensor_init(cam); - if (err) { - cam->sensor_client = NULL; - return err; - } - } else { - DBG(4, "Rejected client [%s] with driver [%s]", - client->name, client->driver->driver.name) - return -EINVAL; - } - - DBG(5, "I2C attach client [%s] with driver [%s]", - client->name, client->driver->driver.name) - - return 0; -} - - -static int w9968cf_i2c_detach_inform(struct i2c_client* client) -{ - struct w9968cf_device* cam = i2c_get_adapdata(client->adapter); - - if (cam->sensor_client == client) - cam->sensor_client = NULL; - - DBG(5, "I2C detach client [%s]", client->name) - - return 0; -} - - -static int -w9968cf_i2c_control(struct i2c_adapter* adapter, unsigned int cmd, - unsigned long arg) -{ - return 0; -} - - -static int w9968cf_i2c_init(struct w9968cf_device* cam) -{ - int err = 0; - - static struct i2c_algorithm algo = { - .smbus_xfer = w9968cf_i2c_smbus_xfer, - .algo_control = w9968cf_i2c_control, - .functionality = w9968cf_i2c_func, - }; - - static struct i2c_adapter adap = { - .id = I2C_HW_SMBUS_W9968CF, - .class = I2C_CLASS_CAM_DIGITAL, - .owner = THIS_MODULE, - .client_register = w9968cf_i2c_attach_inform, - .client_unregister = w9968cf_i2c_detach_inform, - .algo = &algo, - }; - - memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter)); - strcpy(cam->i2c_adapter.name, "w9968cf"); - i2c_set_adapdata(&cam->i2c_adapter, cam); - - DBG(6, "Registering I2C adapter with kernel...") - - err = i2c_add_adapter(&cam->i2c_adapter); - if (err) - DBG(1, "Failed to register the I2C adapter") - else - DBG(5, "I2C adapter registered") - - return err; -} - - - -/**************************************************************************** - * Helper functions * - ****************************************************************************/ - -/*-------------------------------------------------------------------------- - Turn on the LED on some webcams. A beep should be heard too. - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_turn_on_led(struct w9968cf_device* cam) -{ - int err = 0; - - err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power-down */ - err += w9968cf_write_reg(cam, 0xbf17, 0x00); /* reset everything */ - err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* normal operation */ - err += w9968cf_write_reg(cam, 0x0010, 0x01); /* serial bus, SDS high */ - err += w9968cf_write_reg(cam, 0x0000, 0x01); /* serial bus, SDS low */ - err += w9968cf_write_reg(cam, 0x0010, 0x01); /* ..high 'beep-beep' */ - - if (err) - DBG(2, "Couldn't turn on the LED") - - DBG(5, "LED turned on") - - return err; -} - - -/*-------------------------------------------------------------------------- - Write some registers for the device initialization. - This function is called once on open(). - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_init_chip(struct w9968cf_device* cam) -{ - unsigned long hw_bufsize = cam->maxwidth*cam->maxheight*2, - y0 = 0x0000, - u0 = y0 + hw_bufsize/2, - v0 = u0 + hw_bufsize/4, - y1 = v0 + hw_bufsize/4, - u1 = y1 + hw_bufsize/2, - v1 = u1 + hw_bufsize/4; - int err = 0; - - err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power off */ - err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* power on */ - - err += w9968cf_write_reg(cam, 0x405d, 0x03); /* DRAM timings */ - err += w9968cf_write_reg(cam, 0x0030, 0x04); /* SDRAM timings */ - - err += w9968cf_write_reg(cam, y0 & 0xffff, 0x20); /* Y buf.0, low */ - err += w9968cf_write_reg(cam, y0 >> 16, 0x21); /* Y buf.0, high */ - err += w9968cf_write_reg(cam, u0 & 0xffff, 0x24); /* U buf.0, low */ - err += w9968cf_write_reg(cam, u0 >> 16, 0x25); /* U buf.0, high */ - err += w9968cf_write_reg(cam, v0 & 0xffff, 0x28); /* V buf.0, low */ - err += w9968cf_write_reg(cam, v0 >> 16, 0x29); /* V buf.0, high */ - - err += w9968cf_write_reg(cam, y1 & 0xffff, 0x22); /* Y buf.1, low */ - err += w9968cf_write_reg(cam, y1 >> 16, 0x23); /* Y buf.1, high */ - err += w9968cf_write_reg(cam, u1 & 0xffff, 0x26); /* U buf.1, low */ - err += w9968cf_write_reg(cam, u1 >> 16, 0x27); /* U buf.1, high */ - err += w9968cf_write_reg(cam, v1 & 0xffff, 0x2a); /* V buf.1, low */ - err += w9968cf_write_reg(cam, v1 >> 16, 0x2b); /* V buf.1, high */ - - err += w9968cf_write_reg(cam, y1 & 0xffff, 0x32); /* JPEG buf 0 low */ - err += w9968cf_write_reg(cam, y1 >> 16, 0x33); /* JPEG buf 0 high */ - - err += w9968cf_write_reg(cam, y1 & 0xffff, 0x34); /* JPEG buf 1 low */ - err += w9968cf_write_reg(cam, y1 >> 16, 0x35); /* JPEG bug 1 high */ - - err += w9968cf_write_reg(cam, 0x0000, 0x36);/* JPEG restart interval */ - err += w9968cf_write_reg(cam, 0x0804, 0x37);/*JPEG VLE FIFO threshold*/ - err += w9968cf_write_reg(cam, 0x0000, 0x38);/* disable hw up-scaling */ - err += w9968cf_write_reg(cam, 0x0000, 0x3f); /* JPEG/MCTL test data */ - - err += w9968cf_set_picture(cam, cam->picture); /* this before */ - err += w9968cf_set_window(cam, cam->window); - - if (err) - DBG(1, "Chip initialization failed") - else - DBG(5, "Chip successfully initialized") - - return err; -} - - -/*-------------------------------------------------------------------------- - Return non-zero if the palette is supported, 0 otherwise. - --------------------------------------------------------------------------*/ -static inline u16 w9968cf_valid_palette(u16 palette) -{ - u8 i = 0; - while (w9968cf_formatlist[i].palette != 0) { - if (palette == w9968cf_formatlist[i].palette) - return palette; - i++; - } - return 0; -} - - -/*-------------------------------------------------------------------------- - Return the depth corresponding to the given palette. - Palette _must_ be supported ! - --------------------------------------------------------------------------*/ -static inline u16 w9968cf_valid_depth(u16 palette) -{ - u8 i=0; - while (w9968cf_formatlist[i].palette != palette) - i++; - - return w9968cf_formatlist[i].depth; -} - - -/*-------------------------------------------------------------------------- - Return non-zero if the format requires decompression, 0 otherwise. - --------------------------------------------------------------------------*/ -static inline u8 w9968cf_need_decompression(u16 palette) -{ - u8 i = 0; - while (w9968cf_formatlist[i].palette != 0) { - if (palette == w9968cf_formatlist[i].palette) - return w9968cf_formatlist[i].compression; - i++; - } - return 0; -} - - -/*-------------------------------------------------------------------------- - Change the picture settings of the camera. - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int -w9968cf_set_picture(struct w9968cf_device* cam, struct video_picture pict) -{ - u16 fmt, hw_depth, hw_palette, reg_v = 0x0000; - int err = 0; - - /* Make sure we are using a valid depth */ - pict.depth = w9968cf_valid_depth(pict.palette); - - fmt = pict.palette; - - hw_depth = pict.depth; /* depth used by the winbond chip */ - hw_palette = pict.palette; /* palette used by the winbond chip */ - - /* VS & HS polarities */ - reg_v = (cam->vs_polarity << 12) | (cam->hs_polarity << 11); - - switch (fmt) - { - case VIDEO_PALETTE_UYVY: - reg_v |= 0x0000; - cam->vpp_flag = VPP_NONE; - break; - case VIDEO_PALETTE_YUV422P: - reg_v |= 0x0002; - cam->vpp_flag = VPP_DECOMPRESSION; - break; - case VIDEO_PALETTE_YUV420: - case VIDEO_PALETTE_YUV420P: - reg_v |= 0x0003; - cam->vpp_flag = VPP_DECOMPRESSION; - break; - case VIDEO_PALETTE_YUYV: - case VIDEO_PALETTE_YUV422: - reg_v |= 0x0000; - cam->vpp_flag = VPP_SWAP_YUV_BYTES; - hw_palette = VIDEO_PALETTE_UYVY; - break; - /* Original video is used instead of RGBX palettes. - Software conversion later. */ - case VIDEO_PALETTE_GREY: - case VIDEO_PALETTE_RGB555: - case VIDEO_PALETTE_RGB565: - case VIDEO_PALETTE_RGB24: - case VIDEO_PALETTE_RGB32: - reg_v |= 0x0000; /* UYVY 16 bit is used */ - hw_depth = 16; - hw_palette = VIDEO_PALETTE_UYVY; - cam->vpp_flag = VPP_UYVY_TO_RGBX; - break; - } - - /* NOTE: due to memory issues, it is better to disable the hardware - double buffering during compression */ - if (cam->double_buffer && !(cam->vpp_flag & VPP_DECOMPRESSION)) - reg_v |= 0x0080; - - if (cam->clamping) - reg_v |= 0x0020; - - if (cam->filter_type == 1) - reg_v |= 0x0008; - else if (cam->filter_type == 2) - reg_v |= 0x000c; - - if ((err = w9968cf_write_reg(cam, reg_v, 0x16))) - goto error; - - if ((err = w9968cf_sensor_update_picture(cam, pict))) - goto error; - - /* If all went well, update the device data structure */ - memcpy(&cam->picture, &pict, sizeof(pict)); - cam->hw_depth = hw_depth; - cam->hw_palette = hw_palette; - - /* Settings changed, so we clear the frame buffers */ - memset(cam->frame[0].buffer, 0, cam->nbuffers*cam->frame[0].size); - - DBG(4, "Palette is %s, depth is %u bpp", - symbolic(v4l1_plist, pict.palette), pict.depth) - - return 0; - -error: - DBG(1, "Failed to change picture settings") - return err; -} - - -/*-------------------------------------------------------------------------- - Change the capture area size of the camera. - This function _must_ be called _after_ w9968cf_set_picture(). - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int -w9968cf_set_window(struct w9968cf_device* cam, struct video_window win) -{ - u16 x, y, w, h, scx, scy, cw, ch, ax, ay; - unsigned long fw, fh; - struct ovcamchip_window s_win; - int err = 0; - - /* Work around to avoid FP arithmetics */ - #define __SC(x) ((x) << 10) - #define __UNSC(x) ((x) >> 10) - - /* Make sure we are using a supported resolution */ - if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, - (u16*)&win.height))) - goto error; - - /* Scaling factors */ - fw = __SC(win.width) / cam->maxwidth; - fh = __SC(win.height) / cam->maxheight; - - /* Set up the width and height values used by the chip */ - if ((win.width > cam->maxwidth) || (win.height > cam->maxheight)) { - cam->vpp_flag |= VPP_UPSCALE; - /* Calculate largest w,h mantaining the same w/h ratio */ - w = (fw >= fh) ? cam->maxwidth : __SC(win.width)/fh; - h = (fw >= fh) ? __SC(win.height)/fw : cam->maxheight; - if (w < cam->minwidth) /* just in case */ - w = cam->minwidth; - if (h < cam->minheight) /* just in case */ - h = cam->minheight; - } else { - cam->vpp_flag &= ~VPP_UPSCALE; - w = win.width; - h = win.height; - } - - /* x,y offsets of the cropped area */ - scx = cam->start_cropx; - scy = cam->start_cropy; - - /* Calculate cropped area manteining the right w/h ratio */ - if (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE)) { - cw = (fw >= fh) ? cam->maxwidth : __SC(win.width)/fh; - ch = (fw >= fh) ? __SC(win.height)/fw : cam->maxheight; - } else { - cw = w; - ch = h; - } - - /* Setup the window of the sensor */ - s_win.format = VIDEO_PALETTE_UYVY; - s_win.width = cam->maxwidth; - s_win.height = cam->maxheight; - s_win.quarter = 0; /* full progressive video */ - - /* Center it */ - s_win.x = (s_win.width - cw) / 2; - s_win.y = (s_win.height - ch) / 2; - - /* Clock divisor */ - if (cam->clockdiv >= 0) - s_win.clockdiv = cam->clockdiv; /* manual override */ - else - switch (cam->sensor) { - case CC_OV6620: - s_win.clockdiv = 0; - break; - case CC_OV6630: - s_win.clockdiv = 0; - break; - case CC_OV76BE: - case CC_OV7610: - case CC_OV7620: - s_win.clockdiv = 0; - break; - default: - s_win.clockdiv = W9968CF_DEF_CLOCKDIVISOR; - } - - /* We have to scale win.x and win.y offsets */ - if ( (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE)) - || (cam->vpp_flag & VPP_UPSCALE) ) { - ax = __SC(win.x)/fw; - ay = __SC(win.y)/fh; - } else { - ax = win.x; - ay = win.y; - } - - if ((ax + cw) > cam->maxwidth) - ax = cam->maxwidth - cw; - - if ((ay + ch) > cam->maxheight) - ay = cam->maxheight - ch; - - /* Adjust win.x, win.y */ - if ( (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE)) - || (cam->vpp_flag & VPP_UPSCALE) ) { - win.x = __UNSC(ax*fw); - win.y = __UNSC(ay*fh); - } else { - win.x = ax; - win.y = ay; - } - - /* Offsets used by the chip */ - x = ax + s_win.x; - y = ay + s_win.y; - - /* Go ! */ - if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_MODE, &s_win))) - goto error; - - err += w9968cf_write_reg(cam, scx + x, 0x10); - err += w9968cf_write_reg(cam, scy + y, 0x11); - err += w9968cf_write_reg(cam, scx + x + cw, 0x12); - err += w9968cf_write_reg(cam, scy + y + ch, 0x13); - err += w9968cf_write_reg(cam, w, 0x14); - err += w9968cf_write_reg(cam, h, 0x15); - - /* JPEG width & height */ - err += w9968cf_write_reg(cam, w, 0x30); - err += w9968cf_write_reg(cam, h, 0x31); - - /* Y & UV frame buffer strides (in WORD) */ - if (cam->vpp_flag & VPP_DECOMPRESSION) { - err += w9968cf_write_reg(cam, w/2, 0x2c); - err += w9968cf_write_reg(cam, w/4, 0x2d); - } else - err += w9968cf_write_reg(cam, w, 0x2c); - - if (err) - goto error; - - /* If all went well, update the device data structure */ - memcpy(&cam->window, &win, sizeof(win)); - cam->hw_width = w; - cam->hw_height = h; - - /* Settings changed, so we clear the frame buffers */ - memset(cam->frame[0].buffer, 0, cam->nbuffers*cam->frame[0].size); - - DBG(4, "The capture area is %dx%d, Offset (x,y)=(%u,%u)", - win.width, win.height, win.x, win.y) - - PDBGG("x=%u ,y=%u, w=%u, h=%u, ax=%u, ay=%u, s_win.x=%u, s_win.y=%u, " - "cw=%u, ch=%u, win.x=%u, win.y=%u, win.width=%u, win.height=%u", - x, y, w, h, ax, ay, s_win.x, s_win.y, cw, ch, win.x, win.y, - win.width, win.height) - - return 0; - -error: - DBG(1, "Failed to change the capture area size") - return err; -} - - -/*-------------------------------------------------------------------------- - Adjust the asked values for window width and height. - Return 0 on success, -1 otherwise. - --------------------------------------------------------------------------*/ -static int -w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height) -{ - u16 maxw, maxh; - - if ((*width < cam->minwidth) || (*height < cam->minheight)) - return -ERANGE; - - maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && - w9968cf_vpp ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) - : cam->maxwidth; - maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && - w9968cf_vpp ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) - : cam->maxheight; - - if (*width > maxw) - *width = maxw; - if (*height > maxh) - *height = maxh; - - if (cam->vpp_flag & VPP_DECOMPRESSION) { - *width &= ~15L; /* multiple of 16 */ - *height &= ~15L; - } - - PDBGG("Window size adjusted w=%u, h=%u ", *width, *height) - - return 0; -} - - -/*-------------------------------------------------------------------------- - Initialize the FIFO list of requested frames. - --------------------------------------------------------------------------*/ -static void w9968cf_init_framelist(struct w9968cf_device* cam) -{ - u8 i; - - for (i = 0; i < cam->nbuffers; i++) { - cam->requested_frame[i] = NULL; - cam->frame[i].queued = 0; - cam->frame[i].status = F_UNUSED; - } -} - - -/*-------------------------------------------------------------------------- - Add a frame in the FIFO list of requested frames. - This function is called in process context. - --------------------------------------------------------------------------*/ -static void w9968cf_push_frame(struct w9968cf_device* cam, u8 f_num) -{ - u8 f; - unsigned long lock_flags; - - spin_lock_irqsave(&cam->flist_lock, lock_flags); - - for (f=0; cam->requested_frame[f] != NULL; f++); - cam->requested_frame[f] = &cam->frame[f_num]; - cam->frame[f_num].queued = 1; - cam->frame[f_num].status = F_UNUSED; /* clear the status */ - - spin_unlock_irqrestore(&cam->flist_lock, lock_flags); - - DBG(6, "Frame #%u pushed into the FIFO list. Position %u", f_num, f) -} - - -/*-------------------------------------------------------------------------- - Read, store and remove the first pointer in the FIFO list of requested - frames. This function is called in interrupt context. - --------------------------------------------------------------------------*/ -static void -w9968cf_pop_frame(struct w9968cf_device* cam, struct w9968cf_frame_t** framep) -{ - u8 i; - - spin_lock(&cam->flist_lock); - - *framep = cam->requested_frame[0]; - - /* Shift the list of pointers */ - for (i = 0; i < cam->nbuffers-1; i++) - cam->requested_frame[i] = cam->requested_frame[i+1]; - cam->requested_frame[i] = NULL; - - spin_unlock(&cam->flist_lock); - - DBG(6,"Popped frame #%d from the list", (*framep)->number) -} - - -/*-------------------------------------------------------------------------- - High-level video post-processing routine on grabbed frames. - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int -w9968cf_postprocess_frame(struct w9968cf_device* cam, - struct w9968cf_frame_t* fr) -{ - void *pIn = fr->buffer, *pOut = cam->frame_vpp.buffer, *tmp; - u16 w = cam->window.width, - h = cam->window.height, - d = cam->picture.depth, - fmt = cam->picture.palette, - rgb = cam->force_rgb, - hw_w = cam->hw_width, - hw_h = cam->hw_height, - hw_d = cam->hw_depth; - int err = 0; - - #define _PSWAP(pIn, pOut) {tmp = (pIn); (pIn) = (pOut); (pOut) = tmp;} - - if (cam->vpp_flag & VPP_DECOMPRESSION) { - memcpy(pOut, pIn, fr->length); - _PSWAP(pIn, pOut) - err = w9968cf_vpp->decode(pIn, fr->length, hw_w, hw_h, pOut); - PDBGG("Compressed frame length: %lu",(unsigned long)fr->length) - fr->length = (hw_w*hw_h*hw_d)/8; - _PSWAP(pIn, pOut) - if (err) { - DBG(4, "An error occurred while decoding the frame: " - "%s", symbolic(decoder_errlist, err)) - return err; - } else - DBG(6, "Frame decoded") - } - - if (cam->vpp_flag & VPP_SWAP_YUV_BYTES) { - w9968cf_vpp->swap_yuvbytes(pIn, fr->length); - DBG(6, "Original UYVY component ordering changed") - } - - if (cam->vpp_flag & VPP_UPSCALE) { - w9968cf_vpp->scale_up(pIn, pOut, hw_w, hw_h, hw_d, w, h); - fr->length = (w*h*hw_d)/8; - _PSWAP(pIn, pOut) - DBG(6, "Vertical up-scaling done: %u,%u,%ubpp->%u,%u", - hw_w, hw_h, hw_d, w, h) - } - - if (cam->vpp_flag & VPP_UYVY_TO_RGBX) { - w9968cf_vpp->uyvy_to_rgbx(pIn, fr->length, pOut, fmt, rgb); - fr->length = (w*h*d)/8; - _PSWAP(pIn, pOut) - DBG(6, "UYVY-16bit to %s conversion done", - symbolic(v4l1_plist, fmt)) - } - - if (pOut == fr->buffer) - memcpy(fr->buffer, cam->frame_vpp.buffer, fr->length); - - return 0; -} - - - -/**************************************************************************** - * Image sensor control routines * - ****************************************************************************/ - -static int -w9968cf_sensor_set_control(struct w9968cf_device* cam, int cid, int val) -{ - struct ovcamchip_control ctl; - int err; - - ctl.id = cid; - ctl.value = val; - - err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_CTRL, &ctl); - - return err; -} - - -static int -w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int* val) -{ - struct ovcamchip_control ctl; - int err; - - ctl.id = cid; - - err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_G_CTRL, &ctl); - if (!err) - *val = ctl.value; - - return err; -} - - -static int -w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg) -{ - struct i2c_client* c = cam->sensor_client; - int rc = 0; - - if (!c || !c->driver || !c->driver->command) - return -EINVAL; - - rc = c->driver->command(c, cmd, arg); - /* The I2C driver returns -EPERM on non-supported controls */ - return (rc < 0 && rc != -EPERM) ? rc : 0; -} - - -/*-------------------------------------------------------------------------- - Update some settings of the image sensor. - Returns: 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_sensor_update_settings(struct w9968cf_device* cam) -{ - int err = 0; - - /* Auto brightness */ - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOBRIGHT, - cam->auto_brt); - if (err) - return err; - - /* Auto exposure */ - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOEXP, - cam->auto_exp); - if (err) - return err; - - /* Banding filter */ - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BANDFILT, - cam->bandfilt); - if (err) - return err; - - /* Light frequency */ - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_FREQ, - cam->lightfreq); - if (err) - return err; - - /* Back light */ - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BACKLIGHT, - cam->backlight); - if (err) - return err; - - /* Mirror */ - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_MIRROR, - cam->mirror); - if (err) - return err; - - return 0; -} - - -/*-------------------------------------------------------------------------- - Get some current picture settings from the image sensor and update the - internal 'picture' structure of the camera. - Returns: 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_sensor_get_picture(struct w9968cf_device* cam) -{ - int err, v; - - err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_CONT, &v); - if (err) - return err; - cam->picture.contrast = v; - - err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_BRIGHT, &v); - if (err) - return err; - cam->picture.brightness = v; - - err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_SAT, &v); - if (err) - return err; - cam->picture.colour = v; - - err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_HUE, &v); - if (err) - return err; - cam->picture.hue = v; - - DBG(5, "Got picture settings from the image sensor") - - PDBGG("Brightness, contrast, hue, colour, whiteness are " - "%u,%u,%u,%u,%u", cam->picture.brightness,cam->picture.contrast, - cam->picture.hue, cam->picture.colour, cam->picture.whiteness) - - return 0; -} - - -/*-------------------------------------------------------------------------- - Update picture settings of the image sensor. - Returns: 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int -w9968cf_sensor_update_picture(struct w9968cf_device* cam, - struct video_picture pict) -{ - int err = 0; - - if ((!cam->sensor_initialized) - || pict.contrast != cam->picture.contrast) { - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_CONT, - pict.contrast); - if (err) - goto fail; - DBG(4, "Contrast changed from %u to %u", - cam->picture.contrast, pict.contrast) - cam->picture.contrast = pict.contrast; - } - - if (((!cam->sensor_initialized) || - pict.brightness != cam->picture.brightness) && (!cam->auto_brt)) { - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BRIGHT, - pict.brightness); - if (err) - goto fail; - DBG(4, "Brightness changed from %u to %u", - cam->picture.brightness, pict.brightness) - cam->picture.brightness = pict.brightness; - } - - if ((!cam->sensor_initialized) || pict.colour != cam->picture.colour) { - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_SAT, - pict.colour); - if (err) - goto fail; - DBG(4, "Colour changed from %u to %u", - cam->picture.colour, pict.colour) - cam->picture.colour = pict.colour; - } - - if ((!cam->sensor_initialized) || pict.hue != cam->picture.hue) { - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_HUE, - pict.hue); - if (err) - goto fail; - DBG(4, "Hue changed from %u to %u", - cam->picture.hue, pict.hue) - cam->picture.hue = pict.hue; - } - - return 0; - -fail: - DBG(4, "Failed to change sensor picture setting") - return err; -} - - - -/**************************************************************************** - * Camera configuration * - ****************************************************************************/ - -/*-------------------------------------------------------------------------- - This function is called when a supported image sensor is detected. - Return 0 if the initialization succeeds, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_sensor_init(struct w9968cf_device* cam) -{ - int err = 0; - - if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_INITIALIZE, - &cam->monochrome))) - goto error; - - if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_Q_SUBTYPE, - &cam->sensor))) - goto error; - - /* NOTE: Make sure width and height are a multiple of 16 */ - switch (cam->sensor_client->addr) { - case OV6xx0_SID: - cam->maxwidth = 352; - cam->maxheight = 288; - cam->minwidth = 64; - cam->minheight = 48; - break; - case OV7xx0_SID: - cam->maxwidth = 640; - cam->maxheight = 480; - cam->minwidth = 64; - cam->minheight = 48; - break; - default: - DBG(1, "Not supported image sensor detected for %s", - symbolic(camlist, cam->id)) - return -EINVAL; - } - - /* These values depend on the ones in the ovxxx0.c sources */ - switch (cam->sensor) { - case CC_OV7620: - cam->start_cropx = 287; - cam->start_cropy = 35; - /* Seems to work around a bug in the image sensor */ - cam->vs_polarity = 1; - cam->hs_polarity = 1; - break; - default: - cam->start_cropx = 320; - cam->start_cropy = 35; - cam->vs_polarity = 1; - cam->hs_polarity = 0; - } - - if ((err = w9968cf_sensor_update_settings(cam))) - goto error; - - if ((err = w9968cf_sensor_update_picture(cam, cam->picture))) - goto error; - - cam->sensor_initialized = 1; - - DBG(2, "%s image sensor initialized", symbolic(senlist, cam->sensor)) - return 0; - -error: - cam->sensor_initialized = 0; - cam->sensor = CC_UNKNOWN; - DBG(1, "Image sensor initialization failed for %s (/dev/video%d). " - "Try to detach and attach this device again", - symbolic(camlist, cam->id), cam->v4ldev->minor) - return err; -} - - -/*-------------------------------------------------------------------------- - Fill some basic fields in the main device data structure. - This function is called once on w9968cf_usb_probe() for each recognized - camera. - --------------------------------------------------------------------------*/ -static void -w9968cf_configure_camera(struct w9968cf_device* cam, - struct usb_device* udev, - enum w9968cf_model_id mod_id, - const unsigned short dev_nr) -{ - mutex_init(&cam->fileop_mutex); - init_waitqueue_head(&cam->open); - spin_lock_init(&cam->urb_lock); - spin_lock_init(&cam->flist_lock); - - cam->users = 0; - cam->disconnected = 0; - cam->id = mod_id; - cam->sensor = CC_UNKNOWN; - cam->sensor_initialized = 0; - - /* Calculate the alternate setting number (from 1 to 16) - according to the 'packet_size' module parameter */ - if (packet_size[dev_nr] < W9968CF_MIN_PACKET_SIZE) - packet_size[dev_nr] = W9968CF_MIN_PACKET_SIZE; - for (cam->altsetting = 1; - packet_size[dev_nr] < wMaxPacketSize[cam->altsetting-1]; - cam->altsetting++); - - cam->max_buffers = (max_buffers[dev_nr] < 2 || - max_buffers[dev_nr] > W9968CF_MAX_BUFFERS) - ? W9968CF_BUFFERS : (u8)max_buffers[dev_nr]; - - cam->double_buffer = (double_buffer[dev_nr] == 0 || - double_buffer[dev_nr] == 1) - ? (u8)double_buffer[dev_nr]:W9968CF_DOUBLE_BUFFER; - - cam->clamping = (clamping[dev_nr] == 0 || clamping[dev_nr] == 1) - ? (u8)clamping[dev_nr] : W9968CF_CLAMPING; - - cam->filter_type = (filter_type[dev_nr] == 0 || - filter_type[dev_nr] == 1 || - filter_type[dev_nr] == 2) - ? (u8)filter_type[dev_nr] : W9968CF_FILTER_TYPE; - - cam->capture = 1; - - cam->largeview = (largeview[dev_nr] == 0 || largeview[dev_nr] == 1) - ? (u8)largeview[dev_nr] : W9968CF_LARGEVIEW; - - cam->decompression = (decompression[dev_nr] == 0 || - decompression[dev_nr] == 1 || - decompression[dev_nr] == 2) - ? (u8)decompression[dev_nr]:W9968CF_DECOMPRESSION; - - cam->upscaling = (upscaling[dev_nr] == 0 || - upscaling[dev_nr] == 1) - ? (u8)upscaling[dev_nr] : W9968CF_UPSCALING; - - cam->auto_brt = (autobright[dev_nr] == 0 || autobright[dev_nr] == 1) - ? (u8)autobright[dev_nr] : W9968CF_AUTOBRIGHT; - - cam->auto_exp = (autoexp[dev_nr] == 0 || autoexp[dev_nr] == 1) - ? (u8)autoexp[dev_nr] : W9968CF_AUTOEXP; - - cam->lightfreq = (lightfreq[dev_nr] == 50 || lightfreq[dev_nr] == 60) - ? (u8)lightfreq[dev_nr] : W9968CF_LIGHTFREQ; - - cam->bandfilt = (bandingfilter[dev_nr] == 0 || - bandingfilter[dev_nr] == 1) - ? (u8)bandingfilter[dev_nr] : W9968CF_BANDINGFILTER; - - cam->backlight = (backlight[dev_nr] == 0 || backlight[dev_nr] == 1) - ? (u8)backlight[dev_nr] : W9968CF_BACKLIGHT; - - cam->clockdiv = (clockdiv[dev_nr] == -1 || clockdiv[dev_nr] >= 0) - ? (s8)clockdiv[dev_nr] : W9968CF_CLOCKDIV; - - cam->mirror = (mirror[dev_nr] == 0 || mirror[dev_nr] == 1) - ? (u8)mirror[dev_nr] : W9968CF_MIRROR; - - cam->monochrome = (monochrome[dev_nr] == 0 || monochrome[dev_nr] == 1) - ? monochrome[dev_nr] : W9968CF_MONOCHROME; - - cam->picture.brightness = (u16)brightness[dev_nr]; - cam->picture.hue = (u16)hue[dev_nr]; - cam->picture.colour = (u16)colour[dev_nr]; - cam->picture.contrast = (u16)contrast[dev_nr]; - cam->picture.whiteness = (u16)whiteness[dev_nr]; - if (w9968cf_valid_palette((u16)force_palette[dev_nr])) { - cam->picture.palette = (u16)force_palette[dev_nr]; - cam->force_palette = 1; - } else { - cam->force_palette = 0; - if (cam->decompression == 0) - cam->picture.palette = W9968CF_PALETTE_DECOMP_OFF; - else if (cam->decompression == 1) - cam->picture.palette = W9968CF_PALETTE_DECOMP_FORCE; - else - cam->picture.palette = W9968CF_PALETTE_DECOMP_ON; - } - cam->picture.depth = w9968cf_valid_depth(cam->picture.palette); - - cam->force_rgb = (force_rgb[dev_nr] == 0 || force_rgb[dev_nr] == 1) - ? (u8)force_rgb[dev_nr] : W9968CF_FORCE_RGB; - - cam->window.x = 0; - cam->window.y = 0; - cam->window.width = W9968CF_WIDTH; - cam->window.height = W9968CF_HEIGHT; - cam->window.chromakey = 0; - cam->window.clipcount = 0; - cam->window.flags = 0; - - DBG(3, "%s configured with settings #%u:", - symbolic(camlist, cam->id), dev_nr) - - DBG(3, "- Data packet size for USB isochrnous transfer: %u bytes", - wMaxPacketSize[cam->altsetting-1]) - - DBG(3, "- Number of requested video frame buffers: %u", - cam->max_buffers) - - if (cam->double_buffer) - DBG(3, "- Hardware double buffering enabled") - else - DBG(3, "- Hardware double buffering disabled") - - if (cam->filter_type == 0) - DBG(3, "- Video filtering disabled") - else if (cam->filter_type == 1) - DBG(3, "- Video filtering enabled: type 1-2-1") - else if (cam->filter_type == 2) - DBG(3, "- Video filtering enabled: type 2-3-6-3-2") - - if (cam->clamping) - DBG(3, "- Video data clamping (CCIR-601 format) enabled") - else - DBG(3, "- Video data clamping (CCIR-601 format) disabled") - - if (cam->largeview) - DBG(3, "- Large view enabled") - else - DBG(3, "- Large view disabled") - - if ((cam->decompression) == 0 && (!cam->force_palette)) - DBG(3, "- Decompression disabled") - else if ((cam->decompression) == 1 && (!cam->force_palette)) - DBG(3, "- Decompression forced") - else if ((cam->decompression) == 2 && (!cam->force_palette)) - DBG(3, "- Decompression allowed") - - if (cam->upscaling) - DBG(3, "- Software image scaling enabled") - else - DBG(3, "- Software image scaling disabled") - - if (cam->force_palette) - DBG(3, "- Image palette forced to %s", - symbolic(v4l1_plist, cam->picture.palette)) - - if (cam->force_rgb) - DBG(3, "- RGB component ordering will be used instead of BGR") - - if (cam->auto_brt) - DBG(3, "- Auto brightness enabled") - else - DBG(3, "- Auto brightness disabled") - - if (cam->auto_exp) - DBG(3, "- Auto exposure enabled") - else - DBG(3, "- Auto exposure disabled") - - if (cam->backlight) - DBG(3, "- Backlight exposure algorithm enabled") - else - DBG(3, "- Backlight exposure algorithm disabled") - - if (cam->mirror) - DBG(3, "- Mirror enabled") - else - DBG(3, "- Mirror disabled") - - if (cam->bandfilt) - DBG(3, "- Banding filter enabled") - else - DBG(3, "- Banding filter disabled") - - DBG(3, "- Power lighting frequency: %u", cam->lightfreq) - - if (cam->clockdiv == -1) - DBG(3, "- Automatic clock divisor enabled") - else - DBG(3, "- Clock divisor: %d", cam->clockdiv) - - if (cam->monochrome) - DBG(3, "- Image sensor used as monochrome") - else - DBG(3, "- Image sensor not used as monochrome") -} - - -/*-------------------------------------------------------------------------- - If the video post-processing module is not loaded, some parameters - must be overridden. - --------------------------------------------------------------------------*/ -static void w9968cf_adjust_configuration(struct w9968cf_device* cam) -{ - if (!w9968cf_vpp) { - if (cam->decompression == 1) { - cam->decompression = 2; - DBG(2, "Video post-processing module not found: " - "'decompression' parameter forced to 2") - } - if (cam->upscaling) { - cam->upscaling = 0; - DBG(2, "Video post-processing module not found: " - "'upscaling' parameter forced to 0") - } - if (cam->picture.palette != VIDEO_PALETTE_UYVY) { - cam->force_palette = 0; - DBG(2, "Video post-processing module not found: " - "'force_palette' parameter forced to 0") - } - cam->picture.palette = VIDEO_PALETTE_UYVY; - cam->picture.depth = w9968cf_valid_depth(cam->picture.palette); - } -} - - -/*-------------------------------------------------------------------------- - Release the resources used by the driver. - This function is called on disconnect - (or on close if deallocation has been deferred) - --------------------------------------------------------------------------*/ -static void w9968cf_release_resources(struct w9968cf_device* cam) -{ - mutex_lock(&w9968cf_devlist_mutex); - - DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->minor) - - video_unregister_device(cam->v4ldev); - list_del(&cam->v4llist); - i2c_del_adapter(&cam->i2c_adapter); - w9968cf_deallocate_memory(cam); - kfree(cam->control_buffer); - kfree(cam->data_buffer); - - mutex_unlock(&w9968cf_devlist_mutex); -} - - - -/**************************************************************************** - * Video4Linux interface * - ****************************************************************************/ - -static int w9968cf_open(struct inode* inode, struct file* filp) -{ - struct w9968cf_device* cam; - int err; - - /* This the only safe way to prevent race conditions with disconnect */ - if (!down_read_trylock(&w9968cf_disconnect)) - return -ERESTARTSYS; - - cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); - - mutex_lock(&cam->dev_mutex); - - if (cam->sensor == CC_UNKNOWN) { - DBG(2, "No supported image sensor has been detected by the " - "'ovcamchip' module for the %s (/dev/video%d). Make " - "sure it is loaded *before* (re)connecting the camera.", - symbolic(camlist, cam->id), cam->v4ldev->minor) - mutex_unlock(&cam->dev_mutex); - up_read(&w9968cf_disconnect); - return -ENODEV; - } - - if (cam->users) { - DBG(2, "%s (/dev/video%d) has been already occupied by '%s'", - symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command) - if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) { - mutex_unlock(&cam->dev_mutex); - up_read(&w9968cf_disconnect); - return -EWOULDBLOCK; - } - mutex_unlock(&cam->dev_mutex); - err = wait_event_interruptible_exclusive(cam->open, - cam->disconnected || - !cam->users); - if (err) { - up_read(&w9968cf_disconnect); - return err; - } - if (cam->disconnected) { - up_read(&w9968cf_disconnect); - return -ENODEV; - } - mutex_lock(&cam->dev_mutex); - } - - DBG(5, "Opening '%s', /dev/video%d ...", - symbolic(camlist, cam->id), cam->v4ldev->minor) - - cam->streaming = 0; - cam->misconfigured = 0; - - w9968cf_adjust_configuration(cam); - - if ((err = w9968cf_allocate_memory(cam))) - goto deallocate_memory; - - if ((err = w9968cf_init_chip(cam))) - goto deallocate_memory; - - if ((err = w9968cf_start_transfer(cam))) - goto deallocate_memory; - - filp->private_data = cam; - - cam->users++; - strcpy(cam->command, current->comm); - - init_waitqueue_head(&cam->wait_queue); - - DBG(5, "Video device is open") - - mutex_unlock(&cam->dev_mutex); - up_read(&w9968cf_disconnect); - - return 0; - -deallocate_memory: - w9968cf_deallocate_memory(cam); - DBG(2, "Failed to open the video device") - mutex_unlock(&cam->dev_mutex); - up_read(&w9968cf_disconnect); - return err; -} - - -static int w9968cf_release(struct inode* inode, struct file* filp) -{ - struct w9968cf_device* cam; - - cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); - - mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ - - w9968cf_stop_transfer(cam); - - if (cam->disconnected) { - w9968cf_release_resources(cam); - mutex_unlock(&cam->dev_mutex); - kfree(cam); - return 0; - } - - cam->users--; - w9968cf_deallocate_memory(cam); - wake_up_interruptible_nr(&cam->open, 1); - - DBG(5, "Video device closed") - mutex_unlock(&cam->dev_mutex); - return 0; -} - - -static ssize_t -w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) -{ - struct w9968cf_device* cam; - struct w9968cf_frame_t* fr; - int err = 0; - - cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); - - if (filp->f_flags & O_NONBLOCK) - return -EWOULDBLOCK; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->disconnected) { - DBG(2, "Device not present") - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->misconfigured) { - DBG(2, "The camera is misconfigured. Close and open it again.") - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (!cam->frame[0].queued) - w9968cf_push_frame(cam, 0); - - if (!cam->frame[1].queued) - w9968cf_push_frame(cam, 1); - - err = wait_event_interruptible(cam->wait_queue, - cam->frame[0].status == F_READY || - cam->frame[1].status == F_READY || - cam->disconnected); - if (err) { - mutex_unlock(&cam->fileop_mutex); - return err; - } - if (cam->disconnected) { - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - fr = (cam->frame[0].status == F_READY) ? &cam->frame[0]:&cam->frame[1]; - - if (w9968cf_vpp) - w9968cf_postprocess_frame(cam, fr); - - if (count > fr->length) - count = fr->length; - - if (copy_to_user(buf, fr->buffer, count)) { - fr->status = F_UNUSED; - mutex_unlock(&cam->fileop_mutex); - return -EFAULT; - } - *f_pos += count; - - fr->status = F_UNUSED; - - DBG(5, "%zu bytes read", count) - - mutex_unlock(&cam->fileop_mutex); - return count; -} - - -static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma) -{ - struct w9968cf_device* cam = (struct w9968cf_device*) - video_get_drvdata(video_devdata(filp)); - unsigned long vsize = vma->vm_end - vma->vm_start, - psize = cam->nbuffers * cam->frame[0].size, - start = vma->vm_start, - pos = (unsigned long)cam->frame[0].buffer, - page; - - if (cam->disconnected) { - DBG(2, "Device not present") - return -ENODEV; - } - - if (cam->misconfigured) { - DBG(2, "The camera is misconfigured. Close and open it again") - return -EIO; - } - - PDBGG("mmapping %lu bytes...", vsize) - - if (vsize > psize - (vma->vm_pgoff << PAGE_SHIFT)) - return -EINVAL; - - while (vsize > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page + vma->vm_pgoff, - PAGE_SIZE, vma->vm_page_prot)) - return -EAGAIN; - start += PAGE_SIZE; - pos += PAGE_SIZE; - vsize -= PAGE_SIZE; - } - - DBG(5, "mmap method successfully called") - return 0; -} - - -static int -w9968cf_ioctl(struct inode* inode, struct file* filp, - unsigned int cmd, unsigned long arg) -{ - struct w9968cf_device* cam; - int err; - - cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->disconnected) { - DBG(2, "Device not present") - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->misconfigured) { - DBG(2, "The camera is misconfigured. Close and open it again.") - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - err = w9968cf_v4l_ioctl(inode, filp, cmd, (void __user *)arg); - - mutex_unlock(&cam->fileop_mutex); - return err; -} - - -static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) -{ - struct w9968cf_device* cam; - const char* v4l1_ioctls[] = { - "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", - "GPICT", "SPICT", "CCAPTURE", "GWIN", "SWIN", "GFBUF", - "SFBUF", "KEY", "GFREQ", "SFREQ", "GAUDIO", "SAUDIO", - "SYNC", "MCAPTURE", "GMBUF", "GUNIT", "GCAPTURE", "SCAPTURE", - "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", "SMICROCODE", - "GVBIFMT", "SVBIFMT" - }; - - #define V4L1_IOCTL(cmd) \ - ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \ - v4l1_ioctls[_IOC_NR((cmd))] : "?") - - cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); - - switch (cmd) { - - case VIDIOCGCAP: /* get video capability */ - { - struct video_capability cap = { - .type = VID_TYPE_CAPTURE | VID_TYPE_SCALES, - .channels = 1, - .audios = 0, - .minwidth = cam->minwidth, - .minheight = cam->minheight, - }; - sprintf(cap.name, "W996[87]CF USB Camera #%d", - cam->v4ldev->minor); - cap.maxwidth = (cam->upscaling && w9968cf_vpp) - ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) - : cam->maxwidth; - cap.maxheight = (cam->upscaling && w9968cf_vpp) - ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) - : cam->maxheight; - - if (copy_to_user(arg, &cap, sizeof(cap))) - return -EFAULT; - - DBG(5, "VIDIOCGCAP successfully called") - return 0; - } - - case VIDIOCGCHAN: /* get video channel informations */ - { - struct video_channel chan; - if (copy_from_user(&chan, arg, sizeof(chan))) - return -EFAULT; - - if (chan.channel != 0) - return -EINVAL; - - strcpy(chan.name, "Camera"); - chan.tuners = 0; - chan.flags = 0; - chan.type = VIDEO_TYPE_CAMERA; - chan.norm = VIDEO_MODE_AUTO; - - if (copy_to_user(arg, &chan, sizeof(chan))) - return -EFAULT; - - DBG(5, "VIDIOCGCHAN successfully called") - return 0; - } - - case VIDIOCSCHAN: /* set active channel */ - { - struct video_channel chan; - - if (copy_from_user(&chan, arg, sizeof(chan))) - return -EFAULT; - - if (chan.channel != 0) - return -EINVAL; - - DBG(5, "VIDIOCSCHAN successfully called") - return 0; - } - - case VIDIOCGPICT: /* get image properties of the picture */ - { - if (w9968cf_sensor_get_picture(cam)) - return -EIO; - - if (copy_to_user(arg, &cam->picture, sizeof(cam->picture))) - return -EFAULT; - - DBG(5, "VIDIOCGPICT successfully called") - return 0; - } - - case VIDIOCSPICT: /* change picture settings */ - { - struct video_picture pict; - int err = 0; - - if (copy_from_user(&pict, arg, sizeof(pict))) - return -EFAULT; - - if ( (cam->force_palette || !w9968cf_vpp) - && pict.palette != cam->picture.palette ) { - DBG(4, "Palette %s rejected: only %s is allowed", - symbolic(v4l1_plist, pict.palette), - symbolic(v4l1_plist, cam->picture.palette)) - return -EINVAL; - } - - if (!w9968cf_valid_palette(pict.palette)) { - DBG(4, "Palette %s not supported. VIDIOCSPICT failed", - symbolic(v4l1_plist, pict.palette)) - return -EINVAL; - } - - if (!cam->force_palette) { - if (cam->decompression == 0) { - if (w9968cf_need_decompression(pict.palette)) { - DBG(4, "Decompression disabled: palette %s is not " - "allowed. VIDIOCSPICT failed", - symbolic(v4l1_plist, pict.palette)) - return -EINVAL; - } - } else if (cam->decompression == 1) { - if (!w9968cf_need_decompression(pict.palette)) { - DBG(4, "Decompression forced: palette %s is not " - "allowed. VIDIOCSPICT failed", - symbolic(v4l1_plist, pict.palette)) - return -EINVAL; - } - } - } - - if (pict.depth != w9968cf_valid_depth(pict.palette)) { - DBG(4, "Requested depth %u bpp is not valid for %s " - "palette: ignored and changed to %u bpp", - pict.depth, symbolic(v4l1_plist, pict.palette), - w9968cf_valid_depth(pict.palette)) - pict.depth = w9968cf_valid_depth(pict.palette); - } - - if (pict.palette != cam->picture.palette) { - if(*cam->requested_frame - || cam->frame_current->queued) { - err = wait_event_interruptible - ( cam->wait_queue, - cam->disconnected || - (!*cam->requested_frame && - !cam->frame_current->queued) ); - if (err) - return err; - if (cam->disconnected) - return -ENODEV; - } - - if (w9968cf_stop_transfer(cam)) - goto ioctl_fail; - - if (w9968cf_set_picture(cam, pict)) - goto ioctl_fail; - - if (w9968cf_start_transfer(cam)) - goto ioctl_fail; - - } else if (w9968cf_sensor_update_picture(cam, pict)) - return -EIO; - - - DBG(5, "VIDIOCSPICT successfully called") - return 0; - } - - case VIDIOCSWIN: /* set capture area */ - { - struct video_window win; - int err = 0; - - if (copy_from_user(&win, arg, sizeof(win))) - return -EFAULT; - - DBG(6, "VIDIOCSWIN called: clipcount=%d, flags=%u, " - "x=%u, y=%u, %ux%u", win.clipcount, win.flags, - win.x, win.y, win.width, win.height) - - if (win.clipcount != 0 || win.flags != 0) - return -EINVAL; - - if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, - (u16*)&win.height))) { - DBG(4, "Resolution not supported (%ux%u). " - "VIDIOCSWIN failed", win.width, win.height) - return err; - } - - if (win.x != cam->window.x || - win.y != cam->window.y || - win.width != cam->window.width || - win.height != cam->window.height) { - if(*cam->requested_frame - || cam->frame_current->queued) { - err = wait_event_interruptible - ( cam->wait_queue, - cam->disconnected || - (!*cam->requested_frame && - !cam->frame_current->queued) ); - if (err) - return err; - if (cam->disconnected) - return -ENODEV; - } - - if (w9968cf_stop_transfer(cam)) - goto ioctl_fail; - - /* This _must_ be called before set_window() */ - if (w9968cf_set_picture(cam, cam->picture)) - goto ioctl_fail; - - if (w9968cf_set_window(cam, win)) - goto ioctl_fail; - - if (w9968cf_start_transfer(cam)) - goto ioctl_fail; - } - - DBG(5, "VIDIOCSWIN successfully called. ") - return 0; - } - - case VIDIOCGWIN: /* get current window properties */ - { - if (copy_to_user(arg,&cam->window,sizeof(struct video_window))) - return -EFAULT; - - DBG(5, "VIDIOCGWIN successfully called") - return 0; - } - - case VIDIOCGMBUF: /* request for memory (mapped) buffer */ - { - struct video_mbuf mbuf; - u8 i; - - mbuf.size = cam->nbuffers * cam->frame[0].size; - mbuf.frames = cam->nbuffers; - for (i = 0; i < cam->nbuffers; i++) - mbuf.offsets[i] = (unsigned long)cam->frame[i].buffer - - (unsigned long)cam->frame[0].buffer; - - if (copy_to_user(arg, &mbuf, sizeof(mbuf))) - return -EFAULT; - - DBG(5, "VIDIOCGMBUF successfully called") - return 0; - } - - case VIDIOCMCAPTURE: /* start the capture to a frame */ - { - struct video_mmap mmap; - struct w9968cf_frame_t* fr; - int err = 0; - - if (copy_from_user(&mmap, arg, sizeof(mmap))) - return -EFAULT; - - DBG(6, "VIDIOCMCAPTURE called: frame #%u, format=%s, %dx%d", - mmap.frame, symbolic(v4l1_plist, mmap.format), - mmap.width, mmap.height) - - if (mmap.frame >= cam->nbuffers) { - DBG(4, "Invalid frame number (%u). " - "VIDIOCMCAPTURE failed", mmap.frame) - return -EINVAL; - } - - if (mmap.format!=cam->picture.palette && - (cam->force_palette || !w9968cf_vpp)) { - DBG(4, "Palette %s rejected: only %s is allowed", - symbolic(v4l1_plist, mmap.format), - symbolic(v4l1_plist, cam->picture.palette)) - return -EINVAL; - } - - if (!w9968cf_valid_palette(mmap.format)) { - DBG(4, "Palette %s not supported. " - "VIDIOCMCAPTURE failed", - symbolic(v4l1_plist, mmap.format)) - return -EINVAL; - } - - if (!cam->force_palette) { - if (cam->decompression == 0) { - if (w9968cf_need_decompression(mmap.format)) { - DBG(4, "Decompression disabled: palette %s is not " - "allowed. VIDIOCSPICT failed", - symbolic(v4l1_plist, mmap.format)) - return -EINVAL; - } - } else if (cam->decompression == 1) { - if (!w9968cf_need_decompression(mmap.format)) { - DBG(4, "Decompression forced: palette %s is not " - "allowed. VIDIOCSPICT failed", - symbolic(v4l1_plist, mmap.format)) - return -EINVAL; - } - } - } - - if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width, - (u16*)&mmap.height))) { - DBG(4, "Resolution not supported (%dx%d). " - "VIDIOCMCAPTURE failed", - mmap.width, mmap.height) - return err; - } - - fr = &cam->frame[mmap.frame]; - - if (mmap.width != cam->window.width || - mmap.height != cam->window.height || - mmap.format != cam->picture.palette) { - - struct video_window win; - struct video_picture pict; - - if(*cam->requested_frame - || cam->frame_current->queued) { - DBG(6, "VIDIOCMCAPTURE. Change settings for " - "frame #%u: %dx%d, format %s. Wait...", - mmap.frame, mmap.width, mmap.height, - symbolic(v4l1_plist, mmap.format)) - err = wait_event_interruptible - ( cam->wait_queue, - cam->disconnected || - (!*cam->requested_frame && - !cam->frame_current->queued) ); - if (err) - return err; - if (cam->disconnected) - return -ENODEV; - } - - memcpy(&win, &cam->window, sizeof(win)); - memcpy(&pict, &cam->picture, sizeof(pict)); - win.width = mmap.width; - win.height = mmap.height; - pict.palette = mmap.format; - - if (w9968cf_stop_transfer(cam)) - goto ioctl_fail; - - /* This before set_window */ - if (w9968cf_set_picture(cam, pict)) - goto ioctl_fail; - - if (w9968cf_set_window(cam, win)) - goto ioctl_fail; - - if (w9968cf_start_transfer(cam)) - goto ioctl_fail; - - } else if (fr->queued) { - - DBG(6, "Wait until frame #%u is free", mmap.frame) - - err = wait_event_interruptible(cam->wait_queue, - cam->disconnected || - (!fr->queued)); - if (err) - return err; - if (cam->disconnected) - return -ENODEV; - } - - w9968cf_push_frame(cam, mmap.frame); - DBG(5, "VIDIOCMCAPTURE(%u): successfully called", mmap.frame) - return 0; - } - - case VIDIOCSYNC: /* wait until the capture of a frame is finished */ - { - unsigned int f_num; - struct w9968cf_frame_t* fr; - int err = 0; - - if (copy_from_user(&f_num, arg, sizeof(f_num))) - return -EFAULT; - - if (f_num >= cam->nbuffers) { - DBG(4, "Invalid frame number (%u). " - "VIDIOCMCAPTURE failed", f_num) - return -EINVAL; - } - - DBG(6, "VIDIOCSYNC called for frame #%u", f_num) - - fr = &cam->frame[f_num]; - - switch (fr->status) { - case F_UNUSED: - if (!fr->queued) { - DBG(4, "VIDIOSYNC: Frame #%u not requested!", - f_num) - return -EFAULT; - } - case F_ERROR: - case F_GRABBING: - err = wait_event_interruptible(cam->wait_queue, - (fr->status == F_READY) - || cam->disconnected); - if (err) - return err; - if (cam->disconnected) - return -ENODEV; - break; - case F_READY: - break; - } - - if (w9968cf_vpp) - w9968cf_postprocess_frame(cam, fr); - - fr->status = F_UNUSED; - - DBG(5, "VIDIOCSYNC(%u) successfully called", f_num) - return 0; - } - - case VIDIOCGUNIT:/* report the unit numbers of the associated devices*/ - { - struct video_unit unit = { - .video = cam->v4ldev->minor, - .vbi = VIDEO_NO_UNIT, - .radio = VIDEO_NO_UNIT, - .audio = VIDEO_NO_UNIT, - .teletext = VIDEO_NO_UNIT, - }; - - if (copy_to_user(arg, &unit, sizeof(unit))) - return -EFAULT; - - DBG(5, "VIDIOCGUNIT successfully called") - return 0; - } - - case VIDIOCKEY: - return 0; - - case VIDIOCGFBUF: - { - if (clear_user(arg, sizeof(struct video_buffer))) - return -EFAULT; - - DBG(5, "VIDIOCGFBUF successfully called") - return 0; - } - - case VIDIOCGTUNER: - { - struct video_tuner tuner; - if (copy_from_user(&tuner, arg, sizeof(tuner))) - return -EFAULT; - - if (tuner.tuner != 0) - return -EINVAL; - - strcpy(tuner.name, "no_tuner"); - tuner.rangelow = 0; - tuner.rangehigh = 0; - tuner.flags = VIDEO_TUNER_NORM; - tuner.mode = VIDEO_MODE_AUTO; - tuner.signal = 0xffff; - - if (copy_to_user(arg, &tuner, sizeof(tuner))) - return -EFAULT; - - DBG(5, "VIDIOCGTUNER successfully called") - return 0; - } - - case VIDIOCSTUNER: - { - struct video_tuner tuner; - if (copy_from_user(&tuner, arg, sizeof(tuner))) - return -EFAULT; - - if (tuner.tuner != 0) - return -EINVAL; - - if (tuner.mode != VIDEO_MODE_AUTO) - return -EINVAL; - - DBG(5, "VIDIOCSTUNER successfully called") - return 0; - } - - case VIDIOCSFBUF: - case VIDIOCCAPTURE: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - case VIDIOCSPLAYMODE: - case VIDIOCSWRITEMODE: - case VIDIOCGPLAYINFO: - case VIDIOCSMICROCODE: - case VIDIOCGVBIFMT: - case VIDIOCSVBIFMT: - DBG(4, "Unsupported V4L1 IOCtl: VIDIOC%s " - "(type 0x%01X, " - "n. 0x%01X, " - "dir. 0x%01X, " - "size 0x%02X)", - V4L1_IOCTL(cmd), - _IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd)) - - return -EINVAL; - - default: - DBG(4, "Invalid V4L1 IOCtl: VIDIOC%s " - "type 0x%01X, " - "n. 0x%01X, " - "dir. 0x%01X, " - "size 0x%02X", - V4L1_IOCTL(cmd), - _IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd)) - - return -ENOIOCTLCMD; - - } /* end of switch */ - -ioctl_fail: - cam->misconfigured = 1; - DBG(1, "VIDIOC%s failed because of hardware problems. " - "To use the camera, close and open it again.", V4L1_IOCTL(cmd)) - return -EFAULT; -} - - -static struct file_operations w9968cf_fops = { - .owner = THIS_MODULE, - .open = w9968cf_open, - .release = w9968cf_release, - .read = w9968cf_read, - .ioctl = w9968cf_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .mmap = w9968cf_mmap, - .llseek = no_llseek, -}; - - - -/**************************************************************************** - * USB probe and V4L registration, disconnect and id_table[] definition * - ****************************************************************************/ - -static int -w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct w9968cf_device* cam; - int err = 0; - enum w9968cf_model_id mod_id; - struct list_head* ptr; - u8 sc = 0; /* number of simultaneous cameras */ - static unsigned short dev_nr = 0; /* we are handling device number n */ - - if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor && - le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct) - mod_id = W9968CF_MOD_CLVBWGP; /* see camlist[] table */ - else if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[1].idVendor && - le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[1].idProduct) - mod_id = W9968CF_MOD_GENERIC; /* see camlist[] table */ - else - return -ENODEV; - - cam = (struct w9968cf_device*) - kzalloc(sizeof(struct w9968cf_device), GFP_KERNEL); - if (!cam) - return -ENOMEM; - - mutex_init(&cam->dev_mutex); - mutex_lock(&cam->dev_mutex); - - cam->usbdev = udev; - /* NOTE: a local copy is used to avoid possible race conditions */ - memcpy(&cam->dev, &udev->dev, sizeof(struct device)); - - DBG(2, "%s detected", symbolic(camlist, mod_id)) - - if (simcams > W9968CF_MAX_DEVICES) - simcams = W9968CF_SIMCAMS; - - /* How many cameras are connected ? */ - mutex_lock(&w9968cf_devlist_mutex); - list_for_each(ptr, &w9968cf_dev_list) - sc++; - mutex_unlock(&w9968cf_devlist_mutex); - - if (sc >= simcams) { - DBG(2, "Device rejected: too many connected cameras " - "(max. %u)", simcams) - err = -EPERM; - goto fail; - } - - - /* Allocate 2 bytes of memory for camera control USB transfers */ - if (!(cam->control_buffer = kzalloc(2, GFP_KERNEL))) { - DBG(1,"Couldn't allocate memory for camera control transfers") - err = -ENOMEM; - goto fail; - } - - /* Allocate 8 bytes of memory for USB data transfers to the FSB */ - if (!(cam->data_buffer = kzalloc(8, GFP_KERNEL))) { - DBG(1, "Couldn't allocate memory for data " - "transfers to the FSB") - err = -ENOMEM; - goto fail; - } - - /* Register the V4L device */ - cam->v4ldev = video_device_alloc(); - if (!cam->v4ldev) { - DBG(1, "Could not allocate memory for a V4L structure") - err = -ENOMEM; - goto fail; - } - - strcpy(cam->v4ldev->name, symbolic(camlist, mod_id)); - cam->v4ldev->owner = THIS_MODULE; - cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; - cam->v4ldev->hardware = VID_HARDWARE_W9968CF; - cam->v4ldev->fops = &w9968cf_fops; - cam->v4ldev->minor = video_nr[dev_nr]; - cam->v4ldev->release = video_device_release; - video_set_drvdata(cam->v4ldev, cam); - cam->v4ldev->dev = &cam->dev; - - err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); - if (err) { - DBG(1, "V4L device registration failed") - if (err == -ENFILE && video_nr[dev_nr] == -1) - DBG(2, "Couldn't find a free /dev/videoX node") - video_nr[dev_nr] = -1; - dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0; - goto fail; - } - - DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->minor) - - /* Set some basic constants */ - w9968cf_configure_camera(cam, udev, mod_id, dev_nr); - - /* Add a new entry into the list of V4L registered devices */ - mutex_lock(&w9968cf_devlist_mutex); - list_add(&cam->v4llist, &w9968cf_dev_list); - mutex_unlock(&w9968cf_devlist_mutex); - dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0; - - w9968cf_turn_on_led(cam); - - w9968cf_i2c_init(cam); - - usb_set_intfdata(intf, cam); - mutex_unlock(&cam->dev_mutex); - return 0; - -fail: /* Free unused memory */ - kfree(cam->control_buffer); - kfree(cam->data_buffer); - if (cam->v4ldev) - video_device_release(cam->v4ldev); - mutex_unlock(&cam->dev_mutex); - kfree(cam); - return err; -} - - -static void w9968cf_usb_disconnect(struct usb_interface* intf) -{ - struct w9968cf_device* cam = - (struct w9968cf_device*)usb_get_intfdata(intf); - - down_write(&w9968cf_disconnect); - - if (cam) { - /* Prevent concurrent accesses to data */ - mutex_lock(&cam->dev_mutex); - - cam->disconnected = 1; - - DBG(2, "Disconnecting %s...", symbolic(camlist, cam->id)) - - wake_up_interruptible_all(&cam->open); - - if (cam->users) { - DBG(2, "The device is open (/dev/video%d)! " - "Process name: %s. Deregistration and memory " - "deallocation are deferred on close.", - cam->v4ldev->minor, cam->command) - cam->misconfigured = 1; - w9968cf_stop_transfer(cam); - wake_up_interruptible(&cam->wait_queue); - } else - w9968cf_release_resources(cam); - - mutex_unlock(&cam->dev_mutex); - - if (!cam->users) - kfree(cam); - } - - up_write(&w9968cf_disconnect); -} - - -static struct usb_driver w9968cf_usb_driver = { - .name = "w9968cf", - .id_table = winbond_id_table, - .probe = w9968cf_usb_probe, - .disconnect = w9968cf_usb_disconnect, -}; - - - -/**************************************************************************** - * Module init, exit and intermodule communication * - ****************************************************************************/ - -static int __init w9968cf_module_init(void) -{ - int err; - - KDBG(2, W9968CF_MODULE_NAME" "W9968CF_MODULE_VERSION) - KDBG(3, W9968CF_MODULE_AUTHOR) - - if (ovmod_load) - request_module("ovcamchip"); - - if ((err = usb_register(&w9968cf_usb_driver))) - return err; - - return 0; -} - - -static void __exit w9968cf_module_exit(void) -{ - /* w9968cf_usb_disconnect() will be called */ - usb_deregister(&w9968cf_usb_driver); - - KDBG(2, W9968CF_MODULE_NAME" deregistered") -} - - -module_init(w9968cf_module_init); -module_exit(w9968cf_module_exit); - diff --git a/drivers/usb/media/w9968cf.h b/drivers/usb/media/w9968cf.h deleted file mode 100644 index a87be719a281..000000000000 --- a/drivers/usb/media/w9968cf.h +++ /dev/null @@ -1,330 +0,0 @@ -/*************************************************************************** - * Video4Linux driver for W996[87]CF JPEG USB Dual Mode Camera Chip. * - * * - * Copyright (C) 2002-2004 by Luca Risolia * - * * - * 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. * - ***************************************************************************/ - -#ifndef _W9968CF_H_ -#define _W9968CF_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "w9968cf_vpp.h" - - -/**************************************************************************** - * Default values * - ****************************************************************************/ - -#define W9968CF_OVMOD_LOAD 1 /* automatic 'ovcamchip' module loading */ -#define W9968CF_VPPMOD_LOAD 1 /* automatic 'w9968cf-vpp' module loading */ - -/* Comment/uncomment the following line to enable/disable debugging messages */ -#define W9968CF_DEBUG - -/* These have effect only if W9968CF_DEBUG is defined */ -#define W9968CF_DEBUG_LEVEL 2 /* from 0 to 6. 0 for no debug informations */ -#define W9968CF_SPECIFIC_DEBUG 0 /* 0 or 1 */ - -#define W9968CF_MAX_DEVICES 32 -#define W9968CF_SIMCAMS W9968CF_MAX_DEVICES /* simultaneous cameras */ - -#define W9968CF_MAX_BUFFERS 32 -#define W9968CF_BUFFERS 2 /* n. of frame buffers from 2 to MAX_BUFFERS */ - -/* Maximum data payload sizes in bytes for alternate settings */ -static const u16 wMaxPacketSize[] = {1023, 959, 895, 831, 767, 703, 639, 575, - 511, 447, 383, 319, 255, 191, 127, 63}; -#define W9968CF_PACKET_SIZE 1023 /* according to wMaxPacketSizes[] */ -#define W9968CF_MIN_PACKET_SIZE 63 /* minimum value */ -#define W9968CF_ISO_PACKETS 5 /* n.of packets for isochronous transfers */ -#define W9968CF_USB_CTRL_TIMEOUT 1000 /* timeout (ms) for usb control commands */ -#define W9968CF_URBS 2 /* n. of scheduled URBs for ISO transfer */ - -#define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ -#define W9968CF_I2C_RW_RETRIES 15 /* number of max I2C r/w retries */ - -/* Available video formats */ -struct w9968cf_format { - const u16 palette; - const u16 depth; - const u8 compression; -}; - -static const struct w9968cf_format w9968cf_formatlist[] = { - { VIDEO_PALETTE_UYVY, 16, 0 }, /* original video */ - { VIDEO_PALETTE_YUV422P, 16, 1 }, /* with JPEG compression */ - { VIDEO_PALETTE_YUV420P, 12, 1 }, /* with JPEG compression */ - { VIDEO_PALETTE_YUV420, 12, 1 }, /* same as YUV420P */ - { VIDEO_PALETTE_YUYV, 16, 0 }, /* software conversion */ - { VIDEO_PALETTE_YUV422, 16, 0 }, /* software conversion */ - { VIDEO_PALETTE_GREY, 8, 0 }, /* software conversion */ - { VIDEO_PALETTE_RGB555, 16, 0 }, /* software conversion */ - { VIDEO_PALETTE_RGB565, 16, 0 }, /* software conversion */ - { VIDEO_PALETTE_RGB24, 24, 0 }, /* software conversion */ - { VIDEO_PALETTE_RGB32, 32, 0 }, /* software conversion */ - { 0, 0, 0 } /* 0 is a terminating entry */ -}; - -#define W9968CF_DECOMPRESSION 2 /* decomp:0=disable,1=force,2=any formats */ -#define W9968CF_PALETTE_DECOMP_OFF VIDEO_PALETTE_UYVY /* when decomp=0 */ -#define W9968CF_PALETTE_DECOMP_FORCE VIDEO_PALETTE_YUV420P /* when decomp=1 */ -#define W9968CF_PALETTE_DECOMP_ON VIDEO_PALETTE_UYVY /* when decomp=2 */ - -#define W9968CF_FORCE_RGB 0 /* read RGB instead of BGR, yes=1/no=0 */ - -#define W9968CF_MAX_WIDTH 800 /* Has effect if up-scaling is on */ -#define W9968CF_MAX_HEIGHT 600 /* Has effect if up-scaling is on */ -#define W9968CF_WIDTH 320 /* from 128 to 352, multiple of 16 */ -#define W9968CF_HEIGHT 240 /* from 96 to 288, multiple of 16 */ - -#define W9968CF_CLAMPING 0 /* 0 disable, 1 enable video data clamping */ -#define W9968CF_FILTER_TYPE 0 /* 0 disable 1 (1-2-1), 2 (2-3-6-3-2) */ -#define W9968CF_DOUBLE_BUFFER 1 /* 0 disable, 1 enable double buffer */ -#define W9968CF_LARGEVIEW 1 /* 0 disable, 1 enable */ -#define W9968CF_UPSCALING 0 /* 0 disable, 1 enable */ - -#define W9968CF_MONOCHROME 0 /* 0 not monochrome, 1 monochrome sensor */ -#define W9968CF_BRIGHTNESS 31000 /* from 0 to 65535 */ -#define W9968CF_HUE 32768 /* from 0 to 65535 */ -#define W9968CF_COLOUR 32768 /* from 0 to 65535 */ -#define W9968CF_CONTRAST 50000 /* from 0 to 65535 */ -#define W9968CF_WHITENESS 32768 /* from 0 to 65535 */ - -#define W9968CF_AUTOBRIGHT 0 /* 0 disable, 1 enable automatic brightness */ -#define W9968CF_AUTOEXP 1 /* 0 disable, 1 enable automatic exposure */ -#define W9968CF_LIGHTFREQ 50 /* light frequency. 50Hz (Europe) or 60Hz */ -#define W9968CF_BANDINGFILTER 0 /* 0 disable, 1 enable banding filter */ -#define W9968CF_BACKLIGHT 0 /* 0 or 1, 1=object is lit from behind */ -#define W9968CF_MIRROR 0 /* 0 or 1 [don't] reverse image horizontally*/ - -#define W9968CF_CLOCKDIV -1 /* -1 = automatic clock divisor */ -#define W9968CF_DEF_CLOCKDIVISOR 0 /* default sensor clock divisor value */ - - -/**************************************************************************** - * Globals * - ****************************************************************************/ - -#define W9968CF_MODULE_NAME "V4L driver for W996[87]CF JPEG USB " \ - "Dual Mode Camera Chip" -#define W9968CF_MODULE_VERSION "1:1.33-basic" -#define W9968CF_MODULE_AUTHOR "(C) 2002-2004 Luca Risolia" -#define W9968CF_AUTHOR_EMAIL "" -#define W9968CF_MODULE_LICENSE "GPL" - -static const struct usb_device_id winbond_id_table[] = { - { - /* Creative Labs Video Blaster WebCam Go Plus */ - USB_DEVICE(0x041e, 0x4003), - .driver_info = (unsigned long)"w9968cf", - }, - { - /* Generic W996[87]CF JPEG USB Dual Mode Camera */ - USB_DEVICE(0x1046, 0x9967), - .driver_info = (unsigned long)"w9968cf", - }, - { } /* terminating entry */ -}; - -/* W996[87]CF camera models, internal ids: */ -enum w9968cf_model_id { - W9968CF_MOD_GENERIC = 1, /* Generic W996[87]CF based device */ - W9968CF_MOD_CLVBWGP = 11,/*Creative Labs Video Blaster WebCam Go Plus*/ - W9968CF_MOD_ADPVDMA = 21, /* Aroma Digi Pen VGA Dual Mode ADG-5000 */ - W9986CF_MOD_AAU = 31, /* AVerMedia AVerTV USB */ - W9968CF_MOD_CLVBWG = 34, /* Creative Labs Video Blaster WebCam Go */ - W9968CF_MOD_LL = 37, /* Lebon LDC-035A */ - W9968CF_MOD_EEEMC = 40, /* Ezonics EZ-802 EZMega Cam */ - W9968CF_MOD_OOE = 42, /* OmniVision OV8610-EDE */ - W9968CF_MOD_ODPVDMPC = 43,/* OPCOM Digi Pen VGA Dual Mode Pen Camera */ - W9968CF_MOD_PDPII = 46, /* Pretec Digi Pen-II */ - W9968CF_MOD_PDP480 = 49, /* Pretec DigiPen-480 */ -}; - -enum w9968cf_frame_status { - F_READY, /* finished grabbing & ready to be read/synced */ - F_GRABBING, /* in the process of being grabbed into */ - F_ERROR, /* something bad happened while processing */ - F_UNUSED /* unused (no VIDIOCMCAPTURE) */ -}; - -struct w9968cf_frame_t { - void* buffer; - unsigned long size; - u32 length; - int number; - enum w9968cf_frame_status status; - struct w9968cf_frame_t* next; - u8 queued; -}; - -enum w9968cf_vpp_flag { - VPP_NONE = 0x00, - VPP_UPSCALE = 0x01, - VPP_SWAP_YUV_BYTES = 0x02, - VPP_DECOMPRESSION = 0x04, - VPP_UYVY_TO_RGBX = 0x08, -}; - -/* Main device driver structure */ -struct w9968cf_device { - struct device dev; /* device structure */ - - enum w9968cf_model_id id; /* private device identifier */ - - struct video_device* v4ldev; /* -> V4L structure */ - struct list_head v4llist; /* entry of the list of V4L cameras */ - - struct usb_device* usbdev; /* -> main USB structure */ - struct urb* urb[W9968CF_URBS]; /* -> USB request block structs */ - void* transfer_buffer[W9968CF_URBS]; /* -> ISO transfer buffers */ - u16* control_buffer; /* -> buffer for control req.*/ - u16* data_buffer; /* -> data to send to the FSB */ - - struct w9968cf_frame_t frame[W9968CF_MAX_BUFFERS]; - struct w9968cf_frame_t frame_tmp; /* temporary frame */ - struct w9968cf_frame_t frame_vpp; /* helper frame.*/ - struct w9968cf_frame_t* frame_current; /* -> frame being grabbed */ - struct w9968cf_frame_t* requested_frame[W9968CF_MAX_BUFFERS]; - - u8 max_buffers, /* number of requested buffers */ - force_palette, /* yes=1/no=0 */ - force_rgb, /* read RGB instead of BGR, yes=1, no=0 */ - double_buffer, /* hardware double buffering yes=1/no=0 */ - clamping, /* video data clamping yes=1/no=0 */ - filter_type, /* 0=disabled, 1=3 tap, 2=5 tap filter */ - capture, /* 0=disabled, 1=enabled */ - largeview, /* 0=disabled, 1=enabled */ - decompression, /* 0=disabled, 1=forced, 2=allowed */ - upscaling; /* software image scaling, 0=enabled, 1=disabled */ - - struct video_picture picture; /* current picture settings */ - struct video_window window; /* current window settings */ - - u16 hw_depth, /* depth (used by the chip) */ - hw_palette, /* palette (used by the chip) */ - hw_width, /* width (used by the chip) */ - hw_height, /* height (used by the chip) */ - hs_polarity, /* 0=negative sync pulse, 1=positive sync pulse */ - vs_polarity, /* 0=negative sync pulse, 1=positive sync pulse */ - start_cropx, /* pixels from HS inactive edge to 1st cropped pixel*/ - start_cropy; /* pixels from VS inactive edge to 1st cropped pixel*/ - - enum w9968cf_vpp_flag vpp_flag; /* post-processing routines in use */ - - u8 nbuffers, /* number of allocated frame buffers */ - altsetting, /* camera alternate setting */ - disconnected, /* flag: yes=1, no=0 */ - misconfigured, /* flag: yes=1, no=0 */ - users, /* flag: number of users holding the device */ - streaming; /* flag: yes=1, no=0 */ - - u8 sensor_initialized; /* flag: yes=1, no=0 */ - - /* Determined by the image sensor type: */ - int sensor, /* type of image sensor chip (CC_*) */ - monochrome; /* image sensor is (probably) monochrome */ - u16 maxwidth, /* maximum width supported by the image sensor */ - maxheight, /* maximum height supported by the image sensor */ - minwidth, /* minimum width supported by the image sensor */ - minheight; /* minimum height supported by the image sensor */ - u8 auto_brt, /* auto brightness enabled flag */ - auto_exp, /* auto exposure enabled flag */ - backlight, /* backlight exposure algorithm flag */ - mirror, /* image is reversed horizontally */ - lightfreq, /* power (lighting) frequency */ - bandfilt; /* banding filter enabled flag */ - s8 clockdiv; /* clock divisor */ - - /* I2C interface to kernel */ - struct i2c_adapter i2c_adapter; - struct i2c_client* sensor_client; - - /* Locks */ - struct mutex dev_mutex, /* for probe, disconnect,open and close */ - fileop_mutex; /* for read and ioctl */ - spinlock_t urb_lock, /* for submit_urb() and unlink_urb() */ - flist_lock; /* for requested frame list accesses */ - wait_queue_head_t open, wait_queue; - - char command[16]; /* name of the program holding the device */ -}; - - -/**************************************************************************** - * Macros for debugging * - ****************************************************************************/ - -#undef DBG -#undef KDBG -#ifdef W9968CF_DEBUG -/* For device specific debugging messages */ -# define DBG(level, fmt, args...) \ -{ \ - if ( ((specific_debug) && (debug == (level))) || \ - ((!specific_debug) && (debug >= (level))) ) { \ - if ((level) == 1) \ - dev_err(&cam->dev, fmt "\n", ## args); \ - else if ((level) == 2 || (level) == 3) \ - dev_info(&cam->dev, fmt "\n", ## args); \ - else if ((level) == 4) \ - dev_warn(&cam->dev, fmt "\n", ## args); \ - else if ((level) >= 5) \ - dev_info(&cam->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ - } \ -} -/* For generic kernel (not device specific) messages */ -# define KDBG(level, fmt, args...) \ -{ \ - if ( ((specific_debug) && (debug == (level))) || \ - ((!specific_debug) && (debug >= (level))) ) { \ - if ((level) >= 1 && (level) <= 4) \ - pr_info("w9968cf: " fmt "\n", ## args); \ - else if ((level) >= 5) \ - pr_debug("w9968cf: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ - } \ -} -#else - /* Not debugging: nothing */ -# define DBG(level, fmt, args...) do {;} while(0); -# define KDBG(level, fmt, args...) do {;} while(0); -#endif - -#undef PDBG -#define PDBG(fmt, args...) \ -dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args); - -#undef PDBGG -#define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */ - -#endif /* _W9968CF_H_ */ diff --git a/drivers/usb/media/w9968cf_decoder.h b/drivers/usb/media/w9968cf_decoder.h deleted file mode 100644 index 31faccbe8f03..000000000000 --- a/drivers/usb/media/w9968cf_decoder.h +++ /dev/null @@ -1,86 +0,0 @@ -/*************************************************************************** - * Video decoder for the W996[87]CF driver for Linux. * - * * - * Copyright (C) 2003 2004 by Luca Risolia * - * * - * 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. * - ***************************************************************************/ - -#ifndef _W9968CF_DECODER_H_ -#define _W9968CF_DECODER_H_ - -/* Comment/uncomment this for high/low quality of compressed video */ -#define W9968CF_DEC_FAST_LOWQUALITY_VIDEO - -#ifdef W9968CF_DEC_FAST_LOWQUALITY_VIDEO -static const unsigned char Y_QUANTABLE[64] = { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 56, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 -}; - -static const unsigned char UV_QUANTABLE[64] = { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 -}; -#else -static const unsigned char Y_QUANTABLE[64] = { - 8, 5, 5, 8, 12, 20, 25, 30, - 6, 6, 7, 9, 13, 29, 30, 27, - 7, 6, 8, 12, 20, 28, 34, 28, - 7, 8, 11, 14, 25, 43, 40, 31, - 9, 11, 18, 28, 34, 54, 51, 38, - 12, 17, 27, 32, 40, 52, 56, 46, - 24, 32, 39, 43, 51, 60, 60, 50, - 36, 46, 47, 49, 56, 50, 51, 49 -}; - -static const unsigned char UV_QUANTABLE[64] = { - 8, 9, 12, 23, 49, 49, 49, 49, - 9, 10, 13, 33, 49, 49, 49, 49, - 12, 13, 28, 49, 49, 49, 49, 49, - 23, 33, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49 -}; -#endif - -#define W9968CF_DEC_ERR_CORRUPTED_DATA -1 -#define W9968CF_DEC_ERR_BUF_OVERFLOW -2 -#define W9968CF_DEC_ERR_NO_SOI -3 -#define W9968CF_DEC_ERR_NO_SOF0 -4 -#define W9968CF_DEC_ERR_NO_SOS -5 -#define W9968CF_DEC_ERR_NO_EOI -6 - -extern void w9968cf_init_decoder(void); -extern int w9968cf_check_headers(const unsigned char* Pin, - const unsigned long BUF_SIZE); -extern int w9968cf_decode(const char* Pin, const unsigned long BUF_SIZE, - const unsigned W, const unsigned H, char* Pout); - -#endif /* _W9968CF_DECODER_H_ */ diff --git a/drivers/usb/media/w9968cf_vpp.h b/drivers/usb/media/w9968cf_vpp.h deleted file mode 100644 index f3b91b782671..000000000000 --- a/drivers/usb/media/w9968cf_vpp.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * Interface for video post-processing functions for the W996[87]CF driver * - * for Linux. * - * * - * Copyright (C) 2002-2004 by Luca Risolia * - * * - * 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. * - ***************************************************************************/ - -#ifndef _W9968CF_VPP_H_ -#define _W9968CF_VPP_H_ - -#include -#include - -struct w9968cf_vpp_t { - struct module* owner; - int (*check_headers)(const unsigned char*, const unsigned long); - int (*decode)(const char*, const unsigned long, const unsigned, - const unsigned, char*); - void (*swap_yuvbytes)(void*, unsigned long); - void (*uyvy_to_rgbx)(u8*, unsigned long, u8*, u16, u8); - void (*scale_up)(u8*, u8*, u16, u16, u16, u16, u16); - - u8 busy; /* read-only flag: module is/is not in use */ -}; - -#endif /* _W9968CF_VPP_H_ */ diff --git a/drivers/usb/media/zc0301.h b/drivers/usb/media/zc0301.h deleted file mode 100644 index 8e0655140e60..000000000000 --- a/drivers/usb/media/zc0301.h +++ /dev/null @@ -1,192 +0,0 @@ -/*************************************************************************** - * V4L2 driver for ZC0301 Image Processor and Control Chip * - * * - * Copyright (C) 2006 by Luca Risolia * - * * - * 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. * - ***************************************************************************/ - -#ifndef _ZC0301_H_ -#define _ZC0301_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "zc0301_sensor.h" - -/*****************************************************************************/ - -#define ZC0301_DEBUG -#define ZC0301_DEBUG_LEVEL 2 -#define ZC0301_MAX_DEVICES 64 -#define ZC0301_FORCE_MUNMAP 0 -#define ZC0301_MAX_FRAMES 32 -#define ZC0301_COMPRESSION_QUALITY 0 -#define ZC0301_URBS 2 -#define ZC0301_ISO_PACKETS 7 -#define ZC0301_ALTERNATE_SETTING 7 -#define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS) -#define ZC0301_CTRL_TIMEOUT 100 -#define ZC0301_FRAME_TIMEOUT 2 - -/*****************************************************************************/ - -ZC0301_ID_TABLE -ZC0301_SENSOR_TABLE - -enum zc0301_frame_state { - F_UNUSED, - F_QUEUED, - F_GRABBING, - F_DONE, - F_ERROR, -}; - -struct zc0301_frame_t { - void* bufmem; - struct v4l2_buffer buf; - enum zc0301_frame_state state; - struct list_head frame; - unsigned long vma_use_count; -}; - -enum zc0301_dev_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04, -}; - -enum zc0301_io_method { - IO_NONE, - IO_READ, - IO_MMAP, -}; - -enum zc0301_stream_state { - STREAM_OFF, - STREAM_INTERRUPT, - STREAM_ON, -}; - -struct zc0301_module_param { - u8 force_munmap; - u16 frame_timeout; -}; - -static DECLARE_RWSEM(zc0301_disconnect); - -struct zc0301_device { - struct video_device* v4ldev; - - struct zc0301_sensor sensor; - - struct usb_device* usbdev; - struct urb* urb[ZC0301_URBS]; - void* transfer_buffer[ZC0301_URBS]; - u8* control_buffer; - - struct zc0301_frame_t *frame_current, frame[ZC0301_MAX_FRAMES]; - struct list_head inqueue, outqueue; - u32 frame_count, nbuffers, nreadbuffers; - - enum zc0301_io_method io; - enum zc0301_stream_state stream; - - struct v4l2_jpegcompression compression; - - struct zc0301_module_param module_param; - - enum zc0301_dev_state state; - u8 users; - - struct mutex dev_mutex, fileop_mutex; - spinlock_t queue_lock; - wait_queue_head_t open, wait_frame, wait_stream; -}; - -/*****************************************************************************/ - -struct zc0301_device* -zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id) -{ - return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; -} - -void -zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor) -{ - memcpy(&cam->sensor, sensor, sizeof(struct zc0301_sensor)); -} - -/*****************************************************************************/ - -#undef DBG -#undef KDBG -#ifdef ZC0301_DEBUG -# define DBG(level, fmt, args...) \ -do { \ - if (debug >= (level)) { \ - if ((level) == 1) \ - dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ - else if ((level) == 2) \ - dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ - else if ((level) >= 3) \ - dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ - } \ -} while (0) -# define KDBG(level, fmt, args...) \ -do { \ - if (debug >= (level)) { \ - if ((level) == 1 || (level) == 2) \ - pr_info("zc0301: " fmt "\n", ## args); \ - else if ((level) == 3) \ - pr_debug("zc0301: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ - } \ -} while (0) -# define V4LDBG(level, name, cmd) \ -do { \ - if (debug >= (level)) \ - v4l_print_ioctl(name, cmd); \ -} while (0) -#else -# define DBG(level, fmt, args...) do {;} while(0) -# define KDBG(level, fmt, args...) do {;} while(0) -# define V4LDBG(level, name, cmd) do {;} while(0) -#endif - -#undef PDBG -#define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) - -#undef PDBGG -#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ - -#endif /* _ZC0301_H_ */ diff --git a/drivers/usb/media/zc0301_core.c b/drivers/usb/media/zc0301_core.c deleted file mode 100644 index 4036c6268bff..000000000000 --- a/drivers/usb/media/zc0301_core.c +++ /dev/null @@ -1,2055 +0,0 @@ -/*************************************************************************** - * Video4Linux2 driver for ZC0301 Image Processor and Control Chip * - * * - * Copyright (C) 2006 by Luca Risolia * - * * - * Informations about the chip internals needed to enable the I2C protocol * - * have been taken from the documentation of the ZC030x Video4Linux1 * - * driver written by Andrew Birkett * - * * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "zc0301.h" - -/*****************************************************************************/ - -#define ZC0301_MODULE_NAME "V4L2 driver for ZC0301 " \ - "Image Processor and Control Chip" -#define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" -#define ZC0301_AUTHOR_EMAIL "" -#define ZC0301_MODULE_LICENSE "GPL" -#define ZC0301_MODULE_VERSION "1:1.03" -#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 3) - -/*****************************************************************************/ - -MODULE_DEVICE_TABLE(usb, zc0301_id_table); - -MODULE_AUTHOR(ZC0301_MODULE_AUTHOR " " ZC0301_AUTHOR_EMAIL); -MODULE_DESCRIPTION(ZC0301_MODULE_NAME); -MODULE_VERSION(ZC0301_MODULE_VERSION); -MODULE_LICENSE(ZC0301_MODULE_LICENSE); - -static short video_nr[] = {[0 ... ZC0301_MAX_DEVICES-1] = -1}; -module_param_array(video_nr, short, NULL, 0444); -MODULE_PARM_DESC(video_nr, - "\n<-1|n[,...]> Specify V4L2 minor mode number." - "\n -1 = use next available (default)" - "\n n = use minor number n (integer >= 0)" - "\nYou can specify up to " - __MODULE_STRING(ZC0301_MAX_DEVICES) " cameras this way." - "\nFor example:" - "\nvideo_nr=-1,2,-1 would assign minor number 2 to" - "\nthe second registered camera and use auto for the first" - "\none and for every other camera." - "\n"); - -static short force_munmap[] = {[0 ... ZC0301_MAX_DEVICES-1] = - ZC0301_FORCE_MUNMAP}; -module_param_array(force_munmap, bool, NULL, 0444); -MODULE_PARM_DESC(force_munmap, - "\n<0|1[,...]> Force the application to unmap previously" - "\nmapped buffer memory before calling any VIDIOC_S_CROP or" - "\nVIDIOC_S_FMT ioctl's. Not all the applications support" - "\nthis feature. This parameter is specific for each" - "\ndetected camera." - "\n 0 = do not force memory unmapping" - "\n 1 = force memory unmapping (save memory)" - "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." - "\n"); - -static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] = - ZC0301_FRAME_TIMEOUT}; -module_param_array(frame_timeout, uint, NULL, 0644); -MODULE_PARM_DESC(frame_timeout, - "\n Timeout for a video frame in seconds." - "\nThis parameter is specific for each detected camera." - "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"." - "\n"); - -#ifdef ZC0301_DEBUG -static unsigned short debug = ZC0301_DEBUG_LEVEL; -module_param(debug, ushort, 0644); -MODULE_PARM_DESC(debug, - "\n Debugging information level, from 0 to 3:" - "\n0 = none (use carefully)" - "\n1 = critical errors" - "\n2 = significant informations" - "\n3 = more verbose messages" - "\nLevel 3 is useful for testing only, when only " - "one device is used." - "\nDefault value is "__MODULE_STRING(ZC0301_DEBUG_LEVEL)"." - "\n"); -#endif - -/*****************************************************************************/ - -static u32 -zc0301_request_buffers(struct zc0301_device* cam, u32 count, - enum zc0301_io_method io) -{ - struct v4l2_pix_format* p = &(cam->sensor.pix_format); - struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); - const size_t imagesize = cam->module_param.force_munmap || - io == IO_READ ? - (p->width * p->height * p->priv) / 8 : - (r->width * r->height * p->priv) / 8; - void* buff = NULL; - u32 i; - - if (count > ZC0301_MAX_FRAMES) - count = ZC0301_MAX_FRAMES; - - cam->nbuffers = count; - while (cam->nbuffers > 0) { - if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) - break; - cam->nbuffers--; - } - - for (i = 0; i < cam->nbuffers; i++) { - cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); - cam->frame[i].buf.index = i; - cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); - cam->frame[i].buf.length = imagesize; - cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cam->frame[i].buf.sequence = 0; - cam->frame[i].buf.field = V4L2_FIELD_NONE; - cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; - cam->frame[i].buf.flags = 0; - } - - return cam->nbuffers; -} - - -static void zc0301_release_buffers(struct zc0301_device* cam) -{ - if (cam->nbuffers) { - vfree(cam->frame[0].bufmem); - cam->nbuffers = 0; - } - cam->frame_current = NULL; -} - - -static void zc0301_empty_framequeues(struct zc0301_device* cam) -{ - u32 i; - - INIT_LIST_HEAD(&cam->inqueue); - INIT_LIST_HEAD(&cam->outqueue); - - for (i = 0; i < ZC0301_MAX_FRAMES; i++) { - cam->frame[i].state = F_UNUSED; - cam->frame[i].buf.bytesused = 0; - } -} - - -static void zc0301_requeue_outqueue(struct zc0301_device* cam) -{ - struct zc0301_frame_t *i; - - list_for_each_entry(i, &cam->outqueue, frame) { - i->state = F_QUEUED; - list_add(&i->frame, &cam->inqueue); - } - - INIT_LIST_HEAD(&cam->outqueue); -} - - -static void zc0301_queue_unusedframes(struct zc0301_device* cam) -{ - unsigned long lock_flags; - u32 i; - - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].state == F_UNUSED) { - cam->frame[i].state = F_QUEUED; - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_add_tail(&cam->frame[i].frame, &cam->inqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - } -} - -/*****************************************************************************/ - -int zc0301_write_reg(struct zc0301_device* cam, u16 index, u16 value) -{ - struct usb_device* udev = cam->usbdev; - int res; - - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0xa0, 0x40, - value, index, NULL, 0, ZC0301_CTRL_TIMEOUT); - if (res < 0) { - DBG(3, "Failed to write a register (index 0x%04X, " - "value 0x%02X, error %d)",index, value, res); - return -1; - } - - return 0; -} - - -int zc0301_read_reg(struct zc0301_device* cam, u16 index) -{ - struct usb_device* udev = cam->usbdev; - u8* buff = cam->control_buffer; - int res; - - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0xa1, 0xc0, - 0x0001, index, buff, 1, ZC0301_CTRL_TIMEOUT); - if (res < 0) - DBG(3, "Failed to read a register (index 0x%04X, error %d)", - index, res); - - PDBGG("Read: index 0x%04X, value: 0x%04X", index, (int)(*buff)); - - return (res >= 0) ? (int)(*buff) : -1; -} - - -int zc0301_i2c_read(struct zc0301_device* cam, u16 address, u8 length) -{ - int err = 0, res, r0, r1; - - err += zc0301_write_reg(cam, 0x0092, address); - err += zc0301_write_reg(cam, 0x0090, 0x02); - - msleep(1); - - res = zc0301_read_reg(cam, 0x0091); - if (res < 0) - err += res; - r0 = zc0301_read_reg(cam, 0x0095); - if (r0 < 0) - err += r0; - r1 = zc0301_read_reg(cam, 0x0096); - if (r1 < 0) - err += r1; - - res = (length <= 1) ? r0 : r0 | (r1 << 8); - - if (err) - DBG(3, "I2C read failed at address 0x%04X, value: 0x%04X", - address, res); - - - PDBGG("I2C read: address 0x%04X, value: 0x%04X", address, res); - - return err ? -1 : res; -} - - -int zc0301_i2c_write(struct zc0301_device* cam, u16 address, u16 value) -{ - int err = 0, res; - - err += zc0301_write_reg(cam, 0x0092, address); - err += zc0301_write_reg(cam, 0x0093, value & 0xff); - err += zc0301_write_reg(cam, 0x0094, value >> 8); - err += zc0301_write_reg(cam, 0x0090, 0x01); - - msleep(1); - - res = zc0301_read_reg(cam, 0x0091); - if (res < 0) - err += res; - - if (err) - DBG(3, "I2C write failed at address 0x%04X, value: 0x%04X", - address, value); - - PDBGG("I2C write: address 0x%04X, value: 0x%04X", address, value); - - return err ? -1 : 0; -} - -/*****************************************************************************/ - -static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs) -{ - struct zc0301_device* cam = urb->context; - struct zc0301_frame_t** f; - size_t imagesize; - u8 i; - int err = 0; - - if (urb->status == -ENOENT) - return; - - f = &cam->frame_current; - - if (cam->stream == STREAM_INTERRUPT) { - cam->stream = STREAM_OFF; - if ((*f)) - (*f)->state = F_QUEUED; - DBG(3, "Stream interrupted"); - wake_up(&cam->wait_stream); - } - - if (cam->state & DEV_DISCONNECTED) - return; - - if (cam->state & DEV_MISCONFIGURED) { - wake_up_interruptible(&cam->wait_frame); - return; - } - - if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) - goto resubmit_urb; - - if (!(*f)) - (*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t, - frame); - - imagesize = (cam->sensor.pix_format.width * - cam->sensor.pix_format.height * - cam->sensor.pix_format.priv) / 8; - - for (i = 0; i < urb->number_of_packets; i++) { - unsigned int len, status; - void *pos; - u16* soi; - u8 sof; - - len = urb->iso_frame_desc[i].actual_length; - status = urb->iso_frame_desc[i].status; - pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; - - if (status) { - DBG(3, "Error in isochronous frame"); - (*f)->state = F_ERROR; - continue; - } - - sof = (*(soi = pos) == 0xd8ff); - - PDBGG("Isochrnous frame: length %u, #%u i,", len, i); - - if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) -start_of_frame: - if (sof) { - (*f)->state = F_GRABBING; - (*f)->buf.bytesused = 0; - do_gettimeofday(&(*f)->buf.timestamp); - DBG(3, "SOF detected: new video frame"); - } - - if ((*f)->state == F_GRABBING) { - if (sof && (*f)->buf.bytesused) - goto end_of_frame; - - if ((*f)->buf.bytesused + len > imagesize) { - DBG(3, "Video frame size exceeded"); - (*f)->state = F_ERROR; - continue; - } - - memcpy((*f)->bufmem+(*f)->buf.bytesused, pos, len); - (*f)->buf.bytesused += len; - - if ((*f)->buf.bytesused == imagesize) { - u32 b; -end_of_frame: - b = (*f)->buf.bytesused; - (*f)->state = F_DONE; - (*f)->buf.sequence= ++cam->frame_count; - spin_lock(&cam->queue_lock); - list_move_tail(&(*f)->frame, &cam->outqueue); - if (!list_empty(&cam->inqueue)) - (*f) = list_entry(cam->inqueue.next, - struct zc0301_frame_t, - frame); - else - (*f) = NULL; - spin_unlock(&cam->queue_lock); - DBG(3, "Video frame captured: : %lu bytes", - (unsigned long)(b)); - - if (!(*f)) - goto resubmit_urb; - - if (sof) - goto start_of_frame; - } - } - } - -resubmit_urb: - urb->dev = cam->usbdev; - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0 && err != -EPERM) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "usb_submit_urb() failed"); - } - - wake_up_interruptible(&cam->wait_frame); -} - - -static int zc0301_start_transfer(struct zc0301_device* cam) -{ - struct usb_device *udev = cam->usbdev; - struct urb* urb; - const unsigned int wMaxPacketSize[] = {0, 128, 192, 256, 384, - 512, 768, 1023}; - const unsigned int psz = wMaxPacketSize[ZC0301_ALTERNATE_SETTING]; - s8 i, j; - int err = 0; - - for (i = 0; i < ZC0301_URBS; i++) { - cam->transfer_buffer[i] = kzalloc(ZC0301_ISO_PACKETS * psz, - GFP_KERNEL); - if (!cam->transfer_buffer[i]) { - err = -ENOMEM; - DBG(1, "Not enough memory"); - goto free_buffers; - } - } - - for (i = 0; i < ZC0301_URBS; i++) { - urb = usb_alloc_urb(ZC0301_ISO_PACKETS, GFP_KERNEL); - cam->urb[i] = urb; - if (!urb) { - err = -ENOMEM; - DBG(1, "usb_alloc_urb() failed"); - goto free_urbs; - } - urb->dev = udev; - urb->context = cam; - urb->pipe = usb_rcvisocpipe(udev, 1); - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = ZC0301_ISO_PACKETS; - urb->complete = zc0301_urb_complete; - urb->transfer_buffer = cam->transfer_buffer[i]; - urb->transfer_buffer_length = psz * ZC0301_ISO_PACKETS; - urb->interval = 1; - for (j = 0; j < ZC0301_ISO_PACKETS; j++) { - urb->iso_frame_desc[j].offset = psz * j; - urb->iso_frame_desc[j].length = psz; - } - } - - err = usb_set_interface(udev, 0, ZC0301_ALTERNATE_SETTING); - if (err) { - DBG(1, "usb_set_interface() failed"); - goto free_urbs; - } - - cam->frame_current = NULL; - - for (i = 0; i < ZC0301_URBS; i++) { - err = usb_submit_urb(cam->urb[i], GFP_KERNEL); - if (err) { - for (j = i-1; j >= 0; j--) - usb_kill_urb(cam->urb[j]); - DBG(1, "usb_submit_urb() failed, error %d", err); - goto free_urbs; - } - } - - return 0; - -free_urbs: - for (i = 0; (i < ZC0301_URBS) && cam->urb[i]; i++) - usb_free_urb(cam->urb[i]); - -free_buffers: - for (i = 0; (i < ZC0301_URBS) && cam->transfer_buffer[i]; i++) - kfree(cam->transfer_buffer[i]); - - return err; -} - - -static int zc0301_stop_transfer(struct zc0301_device* cam) -{ - struct usb_device *udev = cam->usbdev; - s8 i; - int err = 0; - - if (cam->state & DEV_DISCONNECTED) - return 0; - - for (i = ZC0301_URBS-1; i >= 0; i--) { - usb_kill_urb(cam->urb[i]); - usb_free_urb(cam->urb[i]); - kfree(cam->transfer_buffer[i]); - } - - err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ - if (err) - DBG(3, "usb_set_interface() failed"); - - return err; -} - - -static int zc0301_stream_interrupt(struct zc0301_device* cam) -{ - long timeout; - - cam->stream = STREAM_INTERRUPT; - timeout = wait_event_timeout(cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED), - ZC0301_URB_TIMEOUT); - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - else if (cam->stream != STREAM_OFF) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "URB timeout reached. The camera is misconfigured. To " - "use it, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -EIO; - } - - return 0; -} - -/*****************************************************************************/ - -static int -zc0301_set_compression(struct zc0301_device* cam, - struct v4l2_jpegcompression* compression) -{ - int r, err = 0; - - if ((r = zc0301_read_reg(cam, 0x0008)) < 0) - err += r; - err += zc0301_write_reg(cam, 0x0008, r | 0x11 | compression->quality); - - return err ? -EIO : 0; -} - - -static int zc0301_init(struct zc0301_device* cam) -{ - struct zc0301_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - struct v4l2_queryctrl *qctrl; - struct v4l2_rect* rect; - u8 i = 0; - int err = 0; - - if (!(cam->state & DEV_INITIALIZED)) { - init_waitqueue_head(&cam->open); - qctrl = s->qctrl; - rect = &(s->cropcap.defrect); - cam->compression.quality = ZC0301_COMPRESSION_QUALITY; - } else { /* use current values */ - qctrl = s->_qctrl; - rect = &(s->_rect); - } - - if (s->init) { - err = s->init(cam); - if (err) { - DBG(3, "Sensor initialization failed"); - return err; - } - } - - if ((err = zc0301_set_compression(cam, &cam->compression))) { - DBG(3, "set_compression() failed"); - return err; - } - - if (s->set_crop) - if ((err = s->set_crop(cam, rect))) { - DBG(3, "set_crop() failed"); - return err; - } - - if (s->set_ctrl) { - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (s->qctrl[i].id != 0 && - !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { - ctrl.id = s->qctrl[i].id; - ctrl.value = qctrl[i].default_value; - err = s->set_ctrl(cam, &ctrl); - if (err) { - DBG(3, "Set %s control failed", - s->qctrl[i].name); - return err; - } - DBG(3, "Image sensor supports '%s' control", - s->qctrl[i].name); - } - } - - if (!(cam->state & DEV_INITIALIZED)) { - mutex_init(&cam->fileop_mutex); - spin_lock_init(&cam->queue_lock); - init_waitqueue_head(&cam->wait_frame); - init_waitqueue_head(&cam->wait_stream); - cam->nreadbuffers = 2; - memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); - memcpy(&(s->_rect), &(s->cropcap.defrect), - sizeof(struct v4l2_rect)); - cam->state |= DEV_INITIALIZED; - } - - DBG(2, "Initialization succeeded"); - return 0; -} - - -static void zc0301_release_resources(struct zc0301_device* cam) -{ - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); - video_set_drvdata(cam->v4ldev, NULL); - video_unregister_device(cam->v4ldev); - kfree(cam->control_buffer); -} - -/*****************************************************************************/ - -static int zc0301_open(struct inode* inode, struct file* filp) -{ - struct zc0301_device* cam; - int err = 0; - - /* - This is the only safe way to prevent race conditions with - disconnect - */ - if (!down_read_trylock(&zc0301_disconnect)) - return -ERESTARTSYS; - - cam = video_get_drvdata(video_devdata(filp)); - - if (mutex_lock_interruptible(&cam->dev_mutex)) { - up_read(&zc0301_disconnect); - return -ERESTARTSYS; - } - - if (cam->users) { - DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); - if ((filp->f_flags & O_NONBLOCK) || - (filp->f_flags & O_NDELAY)) { - err = -EWOULDBLOCK; - goto out; - } - mutex_unlock(&cam->dev_mutex); - err = wait_event_interruptible_exclusive(cam->open, - cam->state & DEV_DISCONNECTED - || !cam->users); - if (err) { - up_read(&zc0301_disconnect); - return err; - } - if (cam->state & DEV_DISCONNECTED) { - up_read(&zc0301_disconnect); - return -ENODEV; - } - mutex_lock(&cam->dev_mutex); - } - - - if (cam->state & DEV_MISCONFIGURED) { - err = zc0301_init(cam); - if (err) { - DBG(1, "Initialization failed again. " - "I will retry on next open()."); - goto out; - } - cam->state &= ~DEV_MISCONFIGURED; - } - - if ((err = zc0301_start_transfer(cam))) - goto out; - - filp->private_data = cam; - cam->users++; - cam->io = IO_NONE; - cam->stream = STREAM_OFF; - cam->nbuffers = 0; - cam->frame_count = 0; - zc0301_empty_framequeues(cam); - - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); - -out: - mutex_unlock(&cam->dev_mutex); - up_read(&zc0301_disconnect); - return err; -} - - -static int zc0301_release(struct inode* inode, struct file* filp) -{ - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); - - mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ - - zc0301_stop_transfer(cam); - - zc0301_release_buffers(cam); - - if (cam->state & DEV_DISCONNECTED) { - zc0301_release_resources(cam); - usb_put_dev(cam->usbdev); - mutex_unlock(&cam->dev_mutex); - kfree(cam); - return 0; - } - - cam->users--; - wake_up_interruptible_nr(&cam->open, 1); - - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); - - mutex_unlock(&cam->dev_mutex); - - return 0; -} - - -static ssize_t -zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) -{ - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); - struct zc0301_frame_t* f, * i; - unsigned long lock_flags; - long timeout; - int err = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io == IO_MMAP) { - DBG(3, "Close and open the device again to choose the read " - "method"); - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - if (cam->io == IO_NONE) { - if (!zc0301_request_buffers(cam, cam->nreadbuffers, IO_READ)) { - DBG(1, "read() failed, not enough memory"); - mutex_unlock(&cam->fileop_mutex); - return -ENOMEM; - } - cam->io = IO_READ; - cam->stream = STREAM_ON; - } - - if (list_empty(&cam->inqueue)) { - if (!list_empty(&cam->outqueue)) - zc0301_empty_framequeues(cam); - zc0301_queue_unusedframes(cam); - } - - if (!count) { - mutex_unlock(&cam->fileop_mutex); - return 0; - } - - if (list_empty(&cam->outqueue)) { - if (filp->f_flags & O_NONBLOCK) { - mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) { - mutex_unlock(&cam->fileop_mutex); - return timeout; - } - if (cam->state & DEV_DISCONNECTED) { - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - if (!timeout || (cam->state & DEV_MISCONFIGURED)) { - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - } - - f = list_entry(cam->outqueue.prev, struct zc0301_frame_t, frame); - - if (count > f->buf.bytesused) - count = f->buf.bytesused; - - if (copy_to_user(buf, f->bufmem, count)) { - err = -EFAULT; - goto exit; - } - *f_pos += count; - -exit: - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_for_each_entry(i, &cam->outqueue, frame) - i->state = F_UNUSED; - INIT_LIST_HEAD(&cam->outqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - zc0301_queue_unusedframes(cam); - - PDBGG("Frame #%lu, bytes read: %zu", - (unsigned long)f->buf.index, count); - - mutex_unlock(&cam->fileop_mutex); - - return err ? err : count; -} - - -static unsigned int zc0301_poll(struct file *filp, poll_table *wait) -{ - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); - struct zc0301_frame_t* f; - unsigned long lock_flags; - unsigned int mask = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return POLLERR; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - goto error; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - goto error; - } - - if (cam->io == IO_NONE) { - if (!zc0301_request_buffers(cam, cam->nreadbuffers, IO_READ)) { - DBG(1, "poll() failed, not enough memory"); - goto error; - } - cam->io = IO_READ; - cam->stream = STREAM_ON; - } - - if (cam->io == IO_READ) { - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_for_each_entry(f, &cam->outqueue, frame) - f->state = F_UNUSED; - INIT_LIST_HEAD(&cam->outqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - zc0301_queue_unusedframes(cam); - } - - poll_wait(filp, &cam->wait_frame, wait); - - if (!list_empty(&cam->outqueue)) - mask |= POLLIN | POLLRDNORM; - - mutex_unlock(&cam->fileop_mutex); - - return mask; - -error: - mutex_unlock(&cam->fileop_mutex); - return POLLERR; -} - - -static void zc0301_vm_open(struct vm_area_struct* vma) -{ - struct zc0301_frame_t* f = vma->vm_private_data; - f->vma_use_count++; -} - - -static void zc0301_vm_close(struct vm_area_struct* vma) -{ - /* NOTE: buffers are not freed here */ - struct zc0301_frame_t* f = vma->vm_private_data; - f->vma_use_count--; -} - - -static struct vm_operations_struct zc0301_vm_ops = { - .open = zc0301_vm_open, - .close = zc0301_vm_close, -}; - - -static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) -{ - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); - unsigned long size = vma->vm_end - vma->vm_start, - start = vma->vm_start; - void *pos; - u32 i; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || - size != PAGE_ALIGN(cam->frame[0].buf.length)) { - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - for (i = 0; i < cam->nbuffers; i++) { - if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) - break; - } - if (i == cam->nbuffers) { - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - vma->vm_flags |= VM_IO; - vma->vm_flags |= VM_RESERVED; - - pos = cam->frame[i].bufmem; - while (size > 0) { /* size is page-aligned */ - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { - mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vma->vm_ops = &zc0301_vm_ops; - vma->vm_private_data = &cam->frame[i]; - - zc0301_vm_open(vma); - - mutex_unlock(&cam->fileop_mutex); - - return 0; -} - -/*****************************************************************************/ - -static int -zc0301_vidioc_querycap(struct zc0301_device* cam, void __user * arg) -{ - struct v4l2_capability cap = { - .driver = "zc0301", - .version = ZC0301_MODULE_VERSION_CODE, - .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, - }; - - strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); - if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) - strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, - sizeof(cap.bus_info)); - - if (copy_to_user(arg, &cap, sizeof(cap))) - return -EFAULT; - - return 0; -} - - -static int -zc0301_vidioc_enuminput(struct zc0301_device* cam, void __user * arg) -{ - struct v4l2_input i; - - if (copy_from_user(&i, arg, sizeof(i))) - return -EFAULT; - - if (i.index) - return -EINVAL; - - memset(&i, 0, sizeof(i)); - strcpy(i.name, "Camera"); - i.type = V4L2_INPUT_TYPE_CAMERA; - - if (copy_to_user(arg, &i, sizeof(i))) - return -EFAULT; - - return 0; -} - - -static int -zc0301_vidioc_g_input(struct zc0301_device* cam, void __user * arg) -{ - int index = 0; - - if (copy_to_user(arg, &index, sizeof(index))) - return -EFAULT; - - return 0; -} - - -static int -zc0301_vidioc_s_input(struct zc0301_device* cam, void __user * arg) -{ - int index; - - if (copy_from_user(&index, arg, sizeof(index))) - return -EFAULT; - - if (index != 0) - return -EINVAL; - - return 0; -} - - -static int -zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg) -{ - struct zc0301_sensor* s = &cam->sensor; - struct v4l2_queryctrl qc; - u8 i; - - if (copy_from_user(&qc, arg, sizeof(qc))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (qc.id && qc.id == s->qctrl[i].id) { - memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); - if (copy_to_user(arg, &qc, sizeof(qc))) - return -EFAULT; - return 0; - } - - return -EINVAL; -} - - -static int -zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg) -{ - struct zc0301_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - int err = 0; - u8 i; - - if (!s->get_ctrl && !s->set_ctrl) - return -EINVAL; - - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; - - if (!s->get_ctrl) { - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id == s->qctrl[i].id) { - ctrl.value = s->_qctrl[i].default_value; - goto exit; - } - return -EINVAL; - } else - err = s->get_ctrl(cam, &ctrl); - -exit: - if (copy_to_user(arg, &ctrl, sizeof(ctrl))) - return -EFAULT; - - return err; -} - - -static int -zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) -{ - struct zc0301_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - u8 i; - int err = 0; - - if (!s->set_ctrl) - return -EINVAL; - - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id == s->qctrl[i].id) { - if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) - return -EINVAL; - if (ctrl.value < s->qctrl[i].minimum || - ctrl.value > s->qctrl[i].maximum) - return -ERANGE; - ctrl.value -= ctrl.value % s->qctrl[i].step; - break; - } - - if ((err = s->set_ctrl(cam, &ctrl))) - return err; - - s->_qctrl[i].default_value = ctrl.value; - - return 0; -} - - -static int -zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg) -{ - struct v4l2_cropcap* cc = &(cam->sensor.cropcap); - - cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cc->pixelaspect.numerator = 1; - cc->pixelaspect.denominator = 1; - - if (copy_to_user(arg, cc, sizeof(*cc))) - return -EFAULT; - - return 0; -} - - -static int -zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg) -{ - struct zc0301_sensor* s = &cam->sensor; - struct v4l2_crop crop = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - }; - - memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); - - if (copy_to_user(arg, &crop, sizeof(crop))) - return -EFAULT; - - return 0; -} - - -static int -zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) -{ - struct zc0301_sensor* s = &cam->sensor; - struct v4l2_crop crop; - struct v4l2_rect* rect; - struct v4l2_rect* bounds = &(s->cropcap.bounds); - const enum zc0301_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&crop, arg, sizeof(crop))) - return -EFAULT; - - rect = &(crop.c); - - if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_CROP failed. " - "Unmap the buffers first."); - return -EINVAL; - } - - if (!s->set_crop) { - memcpy(rect, &(s->_rect), sizeof(*rect)); - if (copy_to_user(arg, &crop, sizeof(crop))) - return -EFAULT; - return 0; - } - - rect->left &= ~7L; - rect->top &= ~7L; - if (rect->width < 8) - rect->width = 8; - if (rect->height < 8) - rect->height = 8; - if (rect->width > bounds->width) - rect->width = bounds->width; - if (rect->height > bounds->height) - rect->height = bounds->height; - if (rect->left < bounds->left) - rect->left = bounds->left; - if (rect->top < bounds->top) - rect->top = bounds->top; - if (rect->left + rect->width > bounds->left + bounds->width) - rect->left = bounds->left+bounds->width - rect->width; - if (rect->top + rect->height > bounds->top + bounds->height) - rect->top = bounds->top+bounds->height - rect->height; - rect->width &= ~7L; - rect->height &= ~7L; - - if (cam->stream == STREAM_ON) - if ((err = zc0301_stream_interrupt(cam))) - return err; - - if (copy_to_user(arg, &crop, sizeof(crop))) { - cam->stream = stream; - return -EFAULT; - } - - if (cam->module_param.force_munmap || cam->io == IO_READ) - zc0301_release_buffers(cam); - - if (s->set_crop) - err += s->set_crop(cam, rect); - - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -EIO; - } - - s->pix_format.width = rect->width; - s->pix_format.height = rect->height; - memcpy(&(s->_rect), rect, sizeof(*rect)); - - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -ENOMEM; - } - - if (cam->io == IO_READ) - zc0301_empty_framequeues(cam); - else if (cam->module_param.force_munmap) - zc0301_requeue_outqueue(cam); - - cam->stream = stream; - - return 0; -} - - -static int -zc0301_vidioc_enum_fmt(struct zc0301_device* cam, void __user * arg) -{ - struct v4l2_fmtdesc fmtd; - - if (copy_from_user(&fmtd, arg, sizeof(fmtd))) - return -EFAULT; - - if (fmtd.index == 0) { - strcpy(fmtd.description, "JPEG"); - fmtd.pixelformat = V4L2_PIX_FMT_JPEG; - fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; - } else - return -EINVAL; - - fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); - - if (copy_to_user(arg, &fmtd, sizeof(fmtd))) - return -EFAULT; - - return 0; -} - - -static int -zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg) -{ - struct v4l2_format format; - struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; - - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - pfmt->bytesperline = 0; - pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); - pfmt->field = V4L2_FIELD_NONE; - memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); - - if (copy_to_user(arg, &format, sizeof(format))) - return -EFAULT; - - return 0; -} - - -static int -zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, - void __user * arg) -{ - struct zc0301_sensor* s = &cam->sensor; - struct v4l2_format format; - struct v4l2_pix_format* pix; - struct v4l2_pix_format* pfmt = &(s->pix_format); - struct v4l2_rect* bounds = &(s->cropcap.bounds); - struct v4l2_rect rect; - const enum zc0301_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; - - pix = &(format.fmt.pix); - - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - memcpy(&rect, &(s->_rect), sizeof(rect)); - - if (!s->set_crop) { - pix->width = rect.width; - pix->height = rect.height; - } else { - rect.width = pix->width; - rect.height = pix->height; - } - - if (rect.width < 8) - rect.width = 8; - if (rect.height < 8) - rect.height = 8; - if (rect.width > bounds->left + bounds->width - rect.left) - rect.width = bounds->left + bounds->width - rect.left; - if (rect.height > bounds->top + bounds->height - rect.top) - rect.height = bounds->top + bounds->height - rect.top; - rect.width &= ~7L; - rect.height &= ~7L; - - pix->width = rect.width; - pix->height = rect.height; - pix->pixelformat = pfmt->pixelformat; - pix->priv = pfmt->priv; - pix->colorspace = pfmt->colorspace; - pix->bytesperline = 0; - pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); - pix->field = V4L2_FIELD_NONE; - - if (cmd == VIDIOC_TRY_FMT) { - if (copy_to_user(arg, &format, sizeof(format))) - return -EFAULT; - return 0; - } - - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_FMT failed. " - "Unmap the buffers first."); - return -EINVAL; - } - - if (cam->stream == STREAM_ON) - if ((err = zc0301_stream_interrupt(cam))) - return err; - - if (copy_to_user(arg, &format, sizeof(format))) { - cam->stream = stream; - return -EFAULT; - } - - if (cam->module_param.force_munmap || cam->io == IO_READ) - zc0301_release_buffers(cam); - - if (s->set_crop) - err += s->set_crop(cam, &rect); - - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -EIO; - } - - memcpy(pfmt, pix, sizeof(*pix)); - memcpy(&(s->_rect), &rect, sizeof(rect)); - - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); - return -ENOMEM; - } - - if (cam->io == IO_READ) - zc0301_empty_framequeues(cam); - else if (cam->module_param.force_munmap) - zc0301_requeue_outqueue(cam); - - cam->stream = stream; - - return 0; -} - - -static int -zc0301_vidioc_g_jpegcomp(struct zc0301_device* cam, void __user * arg) -{ - if (copy_to_user(arg, &cam->compression, sizeof(cam->compression))) - return -EFAULT; - - return 0; -} - - -static int -zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg) -{ - struct v4l2_jpegcompression jc; - const enum zc0301_stream_state stream = cam->stream; - int err = 0; - - if (copy_from_user(&jc, arg, sizeof(jc))) - return -EFAULT; - - if (jc.quality != 0) - return -EINVAL; - - if (cam->stream == STREAM_ON) - if ((err = zc0301_stream_interrupt(cam))) - return err; - - err += zc0301_set_compression(cam, &jc); - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " - "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->minor); - return -EIO; - } - - cam->compression.quality = jc.quality; - - cam->stream = stream; - - return 0; -} - - -static int -zc0301_vidioc_reqbufs(struct zc0301_device* cam, void __user * arg) -{ - struct v4l2_requestbuffers rb; - u32 i; - int err; - - if (copy_from_user(&rb, arg, sizeof(rb))) - return -EFAULT; - - if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - rb.memory != V4L2_MEMORY_MMAP) - return -EINVAL; - - if (cam->io == IO_READ) { - DBG(3, "Close and open the device again to choose the mmap " - "I/O method"); - return -EINVAL; - } - - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_REQBUFS failed. " - "Previous buffers are still mapped."); - return -EINVAL; - } - - if (cam->stream == STREAM_ON) - if ((err = zc0301_stream_interrupt(cam))) - return err; - - zc0301_empty_framequeues(cam); - - zc0301_release_buffers(cam); - if (rb.count) - rb.count = zc0301_request_buffers(cam, rb.count, IO_MMAP); - - if (copy_to_user(arg, &rb, sizeof(rb))) { - zc0301_release_buffers(cam); - cam->io = IO_NONE; - return -EFAULT; - } - - cam->io = rb.count ? IO_MMAP : IO_NONE; - - return 0; -} - - -static int -zc0301_vidioc_querybuf(struct zc0301_device* cam, void __user * arg) -{ - struct v4l2_buffer b; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; - - memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); - - if (cam->frame[b.index].vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; - - if (cam->frame[b.index].state == F_DONE) - b.flags |= V4L2_BUF_FLAG_DONE; - else if (cam->frame[b.index].state != F_UNUSED) - b.flags |= V4L2_BUF_FLAG_QUEUED; - - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - - return 0; -} - - -static int -zc0301_vidioc_qbuf(struct zc0301_device* cam, void __user * arg) -{ - struct v4l2_buffer b; - unsigned long lock_flags; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; - - if (cam->frame[b.index].state != F_UNUSED) - return -EINVAL; - - cam->frame[b.index].state = F_QUEUED; - - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - PDBGG("Frame #%lu queued", (unsigned long)b.index); - - return 0; -} - - -static int -zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp, - void __user * arg) -{ - struct v4l2_buffer b; - struct zc0301_frame_t *f; - unsigned long lock_flags; - long timeout; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP) - return -EINVAL; - - if (list_empty(&cam->outqueue)) { - if (cam->stream == STREAM_OFF) - return -EINVAL; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) - return timeout; - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - if (!timeout || (cam->state & DEV_MISCONFIGURED)) - return -EIO; - } - - spin_lock_irqsave(&cam->queue_lock, lock_flags); - f = list_entry(cam->outqueue.next, struct zc0301_frame_t, frame); - list_del(cam->outqueue.next); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - f->state = F_UNUSED; - - memcpy(&b, &f->buf, sizeof(b)); - if (f->vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; - - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - - PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); - - return 0; -} - - -static int -zc0301_vidioc_streamon(struct zc0301_device* cam, void __user * arg) -{ - int type; - - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - if (list_empty(&cam->inqueue)) - return -EINVAL; - - cam->stream = STREAM_ON; - - DBG(3, "Stream on"); - - return 0; -} - - -static int -zc0301_vidioc_streamoff(struct zc0301_device* cam, void __user * arg) -{ - int type, err; - - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - if (cam->stream == STREAM_ON) - if ((err = zc0301_stream_interrupt(cam))) - return err; - - zc0301_empty_framequeues(cam); - - DBG(3, "Stream off"); - - return 0; -} - - -static int -zc0301_vidioc_g_parm(struct zc0301_device* cam, void __user * arg) -{ - struct v4l2_streamparm sp; - - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; - - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - sp.parm.capture.extendedmode = 0; - sp.parm.capture.readbuffers = cam->nreadbuffers; - - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; - - return 0; -} - - -static int -zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg) -{ - struct v4l2_streamparm sp; - - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; - - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - sp.parm.capture.extendedmode = 0; - - if (sp.parm.capture.readbuffers == 0) - sp.parm.capture.readbuffers = cam->nreadbuffers; - - if (sp.parm.capture.readbuffers > ZC0301_MAX_FRAMES) - sp.parm.capture.readbuffers = ZC0301_MAX_FRAMES; - - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; - - cam->nreadbuffers = sp.parm.capture.readbuffers; - - return 0; -} - - -static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) -{ - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); - - switch (cmd) { - - case VIDIOC_QUERYCAP: - return zc0301_vidioc_querycap(cam, arg); - - case VIDIOC_ENUMINPUT: - return zc0301_vidioc_enuminput(cam, arg); - - case VIDIOC_G_INPUT: - return zc0301_vidioc_g_input(cam, arg); - - case VIDIOC_S_INPUT: - return zc0301_vidioc_s_input(cam, arg); - - case VIDIOC_QUERYCTRL: - return zc0301_vidioc_query_ctrl(cam, arg); - - case VIDIOC_G_CTRL: - return zc0301_vidioc_g_ctrl(cam, arg); - - case VIDIOC_S_CTRL_OLD: - case VIDIOC_S_CTRL: - return zc0301_vidioc_s_ctrl(cam, arg); - - case VIDIOC_CROPCAP_OLD: - case VIDIOC_CROPCAP: - return zc0301_vidioc_cropcap(cam, arg); - - case VIDIOC_G_CROP: - return zc0301_vidioc_g_crop(cam, arg); - - case VIDIOC_S_CROP: - return zc0301_vidioc_s_crop(cam, arg); - - case VIDIOC_ENUM_FMT: - return zc0301_vidioc_enum_fmt(cam, arg); - - case VIDIOC_G_FMT: - return zc0301_vidioc_g_fmt(cam, arg); - - case VIDIOC_TRY_FMT: - case VIDIOC_S_FMT: - return zc0301_vidioc_try_s_fmt(cam, cmd, arg); - - case VIDIOC_G_JPEGCOMP: - return zc0301_vidioc_g_jpegcomp(cam, arg); - - case VIDIOC_S_JPEGCOMP: - return zc0301_vidioc_s_jpegcomp(cam, arg); - - case VIDIOC_REQBUFS: - return zc0301_vidioc_reqbufs(cam, arg); - - case VIDIOC_QUERYBUF: - return zc0301_vidioc_querybuf(cam, arg); - - case VIDIOC_QBUF: - return zc0301_vidioc_qbuf(cam, arg); - - case VIDIOC_DQBUF: - return zc0301_vidioc_dqbuf(cam, filp, arg); - - case VIDIOC_STREAMON: - return zc0301_vidioc_streamon(cam, arg); - - case VIDIOC_STREAMOFF: - return zc0301_vidioc_streamoff(cam, arg); - - case VIDIOC_G_PARM: - return zc0301_vidioc_g_parm(cam, arg); - - case VIDIOC_S_PARM_OLD: - case VIDIOC_S_PARM: - return zc0301_vidioc_s_parm(cam, arg); - - case VIDIOC_G_STD: - case VIDIOC_S_STD: - case VIDIOC_QUERYSTD: - case VIDIOC_ENUMSTD: - case VIDIOC_QUERYMENU: - return -EINVAL; - - default: - return -EINVAL; - - } -} - - -static int zc0301_ioctl(struct inode* inode, struct file* filp, - unsigned int cmd, unsigned long arg) -{ - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); - int err = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - V4LDBG(3, "zc0301", cmd); - - err = zc0301_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); - - mutex_unlock(&cam->fileop_mutex); - - return err; -} - - -static struct file_operations zc0301_fops = { - .owner = THIS_MODULE, - .open = zc0301_open, - .release = zc0301_release, - .ioctl = zc0301_ioctl, - .read = zc0301_read, - .poll = zc0301_poll, - .mmap = zc0301_mmap, - .llseek = no_llseek, -}; - -/*****************************************************************************/ - -static int -zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct zc0301_device* cam; - static unsigned int dev_nr = 0; - unsigned int i; - int err = 0; - - if (!(cam = kzalloc(sizeof(struct zc0301_device), GFP_KERNEL))) - return -ENOMEM; - - cam->usbdev = udev; - - if (!(cam->control_buffer = kzalloc(4, GFP_KERNEL))) { - DBG(1, "kmalloc() failed"); - err = -ENOMEM; - goto fail; - } - - if (!(cam->v4ldev = video_device_alloc())) { - DBG(1, "video_device_alloc() failed"); - err = -ENOMEM; - goto fail; - } - - mutex_init(&cam->dev_mutex); - - DBG(2, "ZC0301 Image Processor and Control Chip detected " - "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); - - for (i = 0; zc0301_sensor_table[i]; i++) { - err = zc0301_sensor_table[i](cam); - if (!err) - break; - } - - if (!err) - DBG(2, "%s image sensor detected", cam->sensor.name); - else { - DBG(1, "No supported image sensor detected"); - err = -ENODEV; - goto fail; - } - - if (zc0301_init(cam)) { - DBG(1, "Initialization failed. I will retry on open()."); - cam->state |= DEV_MISCONFIGURED; - } - - strcpy(cam->v4ldev->name, "ZC0301 PC Camera"); - cam->v4ldev->owner = THIS_MODULE; - cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; - cam->v4ldev->hardware = 0; - cam->v4ldev->fops = &zc0301_fops; - cam->v4ldev->minor = video_nr[dev_nr]; - cam->v4ldev->release = video_device_release; - video_set_drvdata(cam->v4ldev, cam); - - mutex_lock(&cam->dev_mutex); - - err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); - if (err) { - DBG(1, "V4L2 device registration failed"); - if (err == -ENFILE && video_nr[dev_nr] == -1) - DBG(1, "Free /dev/videoX node not found"); - video_nr[dev_nr] = -1; - dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; - mutex_unlock(&cam->dev_mutex); - goto fail; - } - - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); - - cam->module_param.force_munmap = force_munmap[dev_nr]; - cam->module_param.frame_timeout = frame_timeout[dev_nr]; - - dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; - - usb_set_intfdata(intf, cam); - - mutex_unlock(&cam->dev_mutex); - - return 0; - -fail: - if (cam) { - kfree(cam->control_buffer); - if (cam->v4ldev) - video_device_release(cam->v4ldev); - kfree(cam); - } - return err; -} - - -static void zc0301_usb_disconnect(struct usb_interface* intf) -{ - struct zc0301_device* cam = usb_get_intfdata(intf); - - if (!cam) - return; - - down_write(&zc0301_disconnect); - - mutex_lock(&cam->dev_mutex); - - DBG(2, "Disconnecting %s...", cam->v4ldev->name); - - wake_up_interruptible_all(&cam->open); - - if (cam->users) { - DBG(2, "Device /dev/video%d is open! Deregistration and " - "memory deallocation are deferred on close.", - cam->v4ldev->minor); - cam->state |= DEV_MISCONFIGURED; - zc0301_stop_transfer(cam); - cam->state |= DEV_DISCONNECTED; - wake_up_interruptible(&cam->wait_frame); - wake_up(&cam->wait_stream); - usb_get_dev(cam->usbdev); - } else { - cam->state |= DEV_DISCONNECTED; - zc0301_release_resources(cam); - } - - mutex_unlock(&cam->dev_mutex); - - if (!cam->users) - kfree(cam); - - up_write(&zc0301_disconnect); -} - - -static struct usb_driver zc0301_usb_driver = { - .name = "zc0301", - .id_table = zc0301_id_table, - .probe = zc0301_usb_probe, - .disconnect = zc0301_usb_disconnect, -}; - -/*****************************************************************************/ - -static int __init zc0301_module_init(void) -{ - int err = 0; - - KDBG(2, ZC0301_MODULE_NAME " v" ZC0301_MODULE_VERSION); - KDBG(3, ZC0301_MODULE_AUTHOR); - - if ((err = usb_register(&zc0301_usb_driver))) - KDBG(1, "usb_register() failed"); - - return err; -} - - -static void __exit zc0301_module_exit(void) -{ - usb_deregister(&zc0301_usb_driver); -} - - -module_init(zc0301_module_init); -module_exit(zc0301_module_exit); diff --git a/drivers/usb/media/zc0301_pas202bcb.c b/drivers/usb/media/zc0301_pas202bcb.c deleted file mode 100644 index 9d282a22c15f..000000000000 --- a/drivers/usb/media/zc0301_pas202bcb.c +++ /dev/null @@ -1,361 +0,0 @@ -/*************************************************************************** - * Plug-in for PAS202BCB image sensor connected to the ZC030! Image * - * Processor and Control Chip * - * * - * Copyright (C) 2006 by Luca Risolia * - * * - * Initialization values of the ZC0301 have been taken from the SPCA5XX * - * driver maintained by Michel Xhaard * - * * - * 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. * - ***************************************************************************/ - -/* - NOTE: Sensor controls are disabled for now, becouse changing them while - streaming sometimes results in out-of-sync video frames. We'll use - the default initialization, until we know how to stop and start video - in the chip. However, the image quality still looks good under various - light conditions. -*/ - -#include -#include "zc0301_sensor.h" - - -static struct zc0301_sensor pas202bcb; - - -static int pas202bcb_init(struct zc0301_device* cam) -{ - int err = 0; - - err += zc0301_write_reg(cam, 0x0002, 0x00); - err += zc0301_write_reg(cam, 0x0003, 0x02); - err += zc0301_write_reg(cam, 0x0004, 0x80); - err += zc0301_write_reg(cam, 0x0005, 0x01); - err += zc0301_write_reg(cam, 0x0006, 0xE0); - err += zc0301_write_reg(cam, 0x0098, 0x00); - err += zc0301_write_reg(cam, 0x009A, 0x03); - err += zc0301_write_reg(cam, 0x011A, 0x00); - err += zc0301_write_reg(cam, 0x011C, 0x03); - err += zc0301_write_reg(cam, 0x009B, 0x01); - err += zc0301_write_reg(cam, 0x009C, 0xE6); - err += zc0301_write_reg(cam, 0x009D, 0x02); - err += zc0301_write_reg(cam, 0x009E, 0x86); - - err += zc0301_i2c_write(cam, 0x02, 0x02); - err += zc0301_i2c_write(cam, 0x0A, 0x01); - err += zc0301_i2c_write(cam, 0x0B, 0x01); - err += zc0301_i2c_write(cam, 0x0D, 0x00); - err += zc0301_i2c_write(cam, 0x12, 0x05); - err += zc0301_i2c_write(cam, 0x13, 0x63); - err += zc0301_i2c_write(cam, 0x15, 0x70); - - err += zc0301_write_reg(cam, 0x0101, 0xB7); - err += zc0301_write_reg(cam, 0x0100, 0x0D); - err += zc0301_write_reg(cam, 0x0189, 0x06); - err += zc0301_write_reg(cam, 0x01AD, 0x00); - err += zc0301_write_reg(cam, 0x01C5, 0x03); - err += zc0301_write_reg(cam, 0x01CB, 0x13); - err += zc0301_write_reg(cam, 0x0250, 0x08); - err += zc0301_write_reg(cam, 0x0301, 0x08); - err += zc0301_write_reg(cam, 0x018D, 0x70); - err += zc0301_write_reg(cam, 0x0008, 0x03); - err += zc0301_write_reg(cam, 0x01C6, 0x04); - err += zc0301_write_reg(cam, 0x01CB, 0x07); - err += zc0301_write_reg(cam, 0x0120, 0x11); - err += zc0301_write_reg(cam, 0x0121, 0x37); - err += zc0301_write_reg(cam, 0x0122, 0x58); - err += zc0301_write_reg(cam, 0x0123, 0x79); - err += zc0301_write_reg(cam, 0x0124, 0x91); - err += zc0301_write_reg(cam, 0x0125, 0xA6); - err += zc0301_write_reg(cam, 0x0126, 0xB8); - err += zc0301_write_reg(cam, 0x0127, 0xC7); - err += zc0301_write_reg(cam, 0x0128, 0xD3); - err += zc0301_write_reg(cam, 0x0129, 0xDE); - err += zc0301_write_reg(cam, 0x012A, 0xE6); - err += zc0301_write_reg(cam, 0x012B, 0xED); - err += zc0301_write_reg(cam, 0x012C, 0xF3); - err += zc0301_write_reg(cam, 0x012D, 0xF8); - err += zc0301_write_reg(cam, 0x012E, 0xFB); - err += zc0301_write_reg(cam, 0x012F, 0xFF); - err += zc0301_write_reg(cam, 0x0130, 0x26); - err += zc0301_write_reg(cam, 0x0131, 0x23); - err += zc0301_write_reg(cam, 0x0132, 0x20); - err += zc0301_write_reg(cam, 0x0133, 0x1C); - err += zc0301_write_reg(cam, 0x0134, 0x16); - err += zc0301_write_reg(cam, 0x0135, 0x13); - err += zc0301_write_reg(cam, 0x0136, 0x10); - err += zc0301_write_reg(cam, 0x0137, 0x0D); - err += zc0301_write_reg(cam, 0x0138, 0x0B); - err += zc0301_write_reg(cam, 0x0139, 0x09); - err += zc0301_write_reg(cam, 0x013A, 0x07); - err += zc0301_write_reg(cam, 0x013B, 0x06); - err += zc0301_write_reg(cam, 0x013C, 0x05); - err += zc0301_write_reg(cam, 0x013D, 0x04); - err += zc0301_write_reg(cam, 0x013E, 0x03); - err += zc0301_write_reg(cam, 0x013F, 0x02); - err += zc0301_write_reg(cam, 0x010A, 0x4C); - err += zc0301_write_reg(cam, 0x010B, 0xF5); - err += zc0301_write_reg(cam, 0x010C, 0xFF); - err += zc0301_write_reg(cam, 0x010D, 0xF9); - err += zc0301_write_reg(cam, 0x010E, 0x51); - err += zc0301_write_reg(cam, 0x010F, 0xF5); - err += zc0301_write_reg(cam, 0x0110, 0xFB); - err += zc0301_write_reg(cam, 0x0111, 0xED); - err += zc0301_write_reg(cam, 0x0112, 0x5F); - err += zc0301_write_reg(cam, 0x0180, 0x00); - err += zc0301_write_reg(cam, 0x0019, 0x00); - err += zc0301_write_reg(cam, 0x0087, 0x20); - err += zc0301_write_reg(cam, 0x0088, 0x21); - - err += zc0301_i2c_write(cam, 0x20, 0x02); - err += zc0301_i2c_write(cam, 0x21, 0x1B); - err += zc0301_i2c_write(cam, 0x03, 0x44); - err += zc0301_i2c_write(cam, 0x0E, 0x01); - err += zc0301_i2c_write(cam, 0x0F, 0x00); - - err += zc0301_write_reg(cam, 0x01A9, 0x14); - err += zc0301_write_reg(cam, 0x01AA, 0x24); - err += zc0301_write_reg(cam, 0x0190, 0x00); - err += zc0301_write_reg(cam, 0x0191, 0x02); - err += zc0301_write_reg(cam, 0x0192, 0x1B); - err += zc0301_write_reg(cam, 0x0195, 0x00); - err += zc0301_write_reg(cam, 0x0196, 0x00); - err += zc0301_write_reg(cam, 0x0197, 0x4D); - err += zc0301_write_reg(cam, 0x018C, 0x10); - err += zc0301_write_reg(cam, 0x018F, 0x20); - err += zc0301_write_reg(cam, 0x001D, 0x44); - err += zc0301_write_reg(cam, 0x001E, 0x6F); - err += zc0301_write_reg(cam, 0x001F, 0xAD); - err += zc0301_write_reg(cam, 0x0020, 0xEB); - err += zc0301_write_reg(cam, 0x0087, 0x0F); - err += zc0301_write_reg(cam, 0x0088, 0x0E); - err += zc0301_write_reg(cam, 0x0180, 0x40); - err += zc0301_write_reg(cam, 0x0192, 0x1B); - err += zc0301_write_reg(cam, 0x0191, 0x02); - err += zc0301_write_reg(cam, 0x0190, 0x00); - err += zc0301_write_reg(cam, 0x0116, 0x1D); - err += zc0301_write_reg(cam, 0x0117, 0x40); - err += zc0301_write_reg(cam, 0x0118, 0x99); - err += zc0301_write_reg(cam, 0x0180, 0x42); - err += zc0301_write_reg(cam, 0x0116, 0x1D); - err += zc0301_write_reg(cam, 0x0117, 0x40); - err += zc0301_write_reg(cam, 0x0118, 0x99); - err += zc0301_write_reg(cam, 0x0007, 0x00); - - err += zc0301_i2c_write(cam, 0x11, 0x01); - - msleep(100); - - return err; -} - - -static int pas202bcb_get_ctrl(struct zc0301_device* cam, - struct v4l2_control* ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - { - int r1 = zc0301_i2c_read(cam, 0x04, 1), - r2 = zc0301_i2c_read(cam, 0x05, 1); - if (r1 < 0 || r2 < 0) - return -EIO; - ctrl->value = (r1 << 6) | (r2 & 0x3f); - } - return 0; - case V4L2_CID_RED_BALANCE: - if ((ctrl->value = zc0301_i2c_read(cam, 0x09, 1)) < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case V4L2_CID_BLUE_BALANCE: - if ((ctrl->value = zc0301_i2c_read(cam, 0x07, 1)) < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case V4L2_CID_GAIN: - if ((ctrl->value = zc0301_i2c_read(cam, 0x10, 1)) < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case ZC0301_V4L2_CID_GREEN_BALANCE: - if ((ctrl->value = zc0301_i2c_read(cam, 0x08, 1)) < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case ZC0301_V4L2_CID_DAC_MAGNITUDE: - if ((ctrl->value = zc0301_i2c_read(cam, 0x0c, 1)) < 0) - return -EIO; - return 0; - default: - return -EINVAL; - } -} - - -static int pas202bcb_set_ctrl(struct zc0301_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += zc0301_i2c_write(cam, 0x04, ctrl->value >> 6); - err += zc0301_i2c_write(cam, 0x05, ctrl->value & 0x3f); - break; - case V4L2_CID_RED_BALANCE: - err += zc0301_i2c_write(cam, 0x09, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += zc0301_i2c_write(cam, 0x07, ctrl->value); - break; - case V4L2_CID_GAIN: - err += zc0301_i2c_write(cam, 0x10, ctrl->value); - break; - case ZC0301_V4L2_CID_GREEN_BALANCE: - err += zc0301_i2c_write(cam, 0x08, ctrl->value); - break; - case ZC0301_V4L2_CID_DAC_MAGNITUDE: - err += zc0301_i2c_write(cam, 0x0c, ctrl->value); - break; - default: - return -EINVAL; - } - err += zc0301_i2c_write(cam, 0x11, 0x01); - - return err ? -EIO : 0; -} - - -static struct zc0301_sensor pas202bcb = { - .name = "PAS202BCB", - .init = &pas202bcb_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x01e5, - .maximum = 0x3fff, - .step = 0x0001, - .default_value = 0x01e5, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x0c, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = ZC0301_V4L2_CID_DAC_MAGNITUDE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "DAC magnitude", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x00, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x01, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x05, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = ZC0301_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x00, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - }, - .get_ctrl = &pas202bcb_get_ctrl, - .set_ctrl = &pas202bcb_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_JPEG, - .priv = 8, - }, -}; - - -int zc0301_probe_pas202bcb(struct zc0301_device* cam) -{ - int r0 = 0, r1 = 0, err = 0; - unsigned int pid = 0; - - err += zc0301_write_reg(cam, 0x0000, 0x01); - err += zc0301_write_reg(cam, 0x0010, 0x0e); - err += zc0301_write_reg(cam, 0x0001, 0x01); - err += zc0301_write_reg(cam, 0x0012, 0x03); - err += zc0301_write_reg(cam, 0x0012, 0x01); - err += zc0301_write_reg(cam, 0x008d, 0x08); - - msleep(10); - - r0 = zc0301_i2c_read(cam, 0x00, 1); - r1 = zc0301_i2c_read(cam, 0x01, 1); - - if (r0 < 0 || r1 < 0 || err) - return -EIO; - - pid = (r0 << 4) | ((r1 & 0xf0) >> 4); - if (pid != 0x017) - return -ENODEV; - - zc0301_attach_sensor(cam, &pas202bcb); - - return 0; -} diff --git a/drivers/usb/media/zc0301_sensor.h b/drivers/usb/media/zc0301_sensor.h deleted file mode 100644 index cf0965a81d01..000000000000 --- a/drivers/usb/media/zc0301_sensor.h +++ /dev/null @@ -1,103 +0,0 @@ -/*************************************************************************** - * API for image sensors connected to the ZC030! Image Processor and * - * Control Chip * - * * - * Copyright (C) 2006 by Luca Risolia * - * * - * 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. * - ***************************************************************************/ - -#ifndef _ZC0301_SENSOR_H_ -#define _ZC0301_SENSOR_H_ - -#include -#include -#include -#include -#include -#include - -struct zc0301_device; -struct zc0301_sensor; - -/*****************************************************************************/ - -extern int zc0301_probe_pas202bcb(struct zc0301_device* cam); - -#define ZC0301_SENSOR_TABLE \ -/* Weak detections must go at the end of the list */ \ -static int (*zc0301_sensor_table[])(struct zc0301_device*) = { \ - &zc0301_probe_pas202bcb, \ - NULL, \ -}; - -extern struct zc0301_device* -zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id); - -extern void -zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); - -#define ZC0301_USB_DEVICE(vend, prod, intclass) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ - USB_DEVICE_ID_MATCH_INT_CLASS, \ - .idVendor = (vend), \ - .idProduct = (prod), \ - .bInterfaceClass = (intclass) - -#define ZC0301_ID_TABLE \ -static const struct usb_device_id zc0301_id_table[] = { \ - { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, \ - { ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131B */ \ - { ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \ - { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \ - { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \ - { } \ -}; - -/*****************************************************************************/ - -extern int zc0301_write_reg(struct zc0301_device*, u16 index, u16 value); -extern int zc0301_read_reg(struct zc0301_device*, u16 index); -extern int zc0301_i2c_write(struct zc0301_device*, u16 address, u16 value); -extern int zc0301_i2c_read(struct zc0301_device*, u16 address, u8 length); - -/*****************************************************************************/ - -#define ZC0301_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 -#define ZC0301_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE -#define ZC0301_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1 - -struct zc0301_sensor { - char name[32]; - - struct v4l2_queryctrl qctrl[ZC0301_MAX_CTRLS]; - struct v4l2_cropcap cropcap; - struct v4l2_pix_format pix_format; - - int (*init)(struct zc0301_device*); - int (*get_ctrl)(struct zc0301_device*, struct v4l2_control* ctrl); - int (*set_ctrl)(struct zc0301_device*, - const struct v4l2_control* ctrl); - int (*set_crop)(struct zc0301_device*, const struct v4l2_rect* rect); - - /* Private */ - struct v4l2_queryctrl _qctrl[ZC0301_MAX_CTRLS]; - struct v4l2_rect _rect; -}; - -#endif /* _ZC0301_SENSOR_H_ */ -- cgit v1.2.3-59-g8ed1b From d56410e0a594150c5ca06319da7bc8901c4d455e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 25 Mar 2006 09:19:53 -0300 Subject: V4L/DVB (3599b): Whitespace cleanups under drivers/media Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 28 +- drivers/media/video/adv7170.c | 10 +- drivers/media/video/adv7175.c | 6 +- drivers/media/video/arv.c | 54 +- drivers/media/video/bt819.c | 10 +- drivers/media/video/bt856.c | 4 +- drivers/media/video/bw-qcam.c | 106 +-- drivers/media/video/c-qcam.c | 66 +- drivers/media/video/cpia.c | 656 +++++++-------- drivers/media/video/cpia.h | 52 +- drivers/media/video/cpia_pp.c | 106 +-- drivers/media/video/cpia_usb.c | 40 +- drivers/media/video/cs8420.h | 2 +- drivers/media/video/dabusb.c | 18 +- drivers/media/video/dabusb.h | 4 +- drivers/media/video/dsbr100.c | 44 +- drivers/media/video/et61x251/et61x251.h | 8 +- drivers/media/video/et61x251/et61x251_core.c | 210 ++--- drivers/media/video/et61x251/et61x251_sensor.h | 20 +- drivers/media/video/et61x251/et61x251_tas5130d1b.c | 10 +- drivers/media/video/ov511.c | 92 +- drivers/media/video/ov511.h | 8 +- drivers/media/video/ovcamchip/Makefile | 2 +- drivers/media/video/ovcamchip/ovcamchip_core.c | 6 +- drivers/media/video/ovcamchip/ovcamchip_priv.h | 2 +- drivers/media/video/planb.c | 128 +-- drivers/media/video/planb.h | 6 +- drivers/media/video/pms.c | 136 +-- drivers/media/video/pwc/Makefile | 2 +- drivers/media/video/pwc/philips.txt | 66 +- drivers/media/video/pwc/pwc-ctrl.c | 374 ++++----- drivers/media/video/pwc/pwc-if.c | 302 +++---- drivers/media/video/pwc/pwc-ioctl.h | 40 +- drivers/media/video/pwc/pwc-kiara.c | 288 +++---- drivers/media/video/pwc/pwc-misc.c | 26 +- drivers/media/video/pwc/pwc-nala.h | 2 +- drivers/media/video/pwc/pwc-timon.c | 288 +++---- drivers/media/video/pwc/pwc-uncompress.c | 6 +- drivers/media/video/pwc/pwc-uncompress.h | 2 +- drivers/media/video/pwc/pwc.h | 4 +- drivers/media/video/saa5249.c | 112 +-- drivers/media/video/saa7110.c | 4 +- drivers/media/video/saa7111.c | 4 +- drivers/media/video/saa7114.c | 12 +- drivers/media/video/saa7121.h | 6 +- drivers/media/video/saa7146.h | 10 +- drivers/media/video/saa7146reg.h | 4 +- drivers/media/video/saa7185.c | 4 +- drivers/media/video/saa7196.h | 4 +- drivers/media/video/se401.c | 216 ++--- drivers/media/video/se401.h | 6 +- drivers/media/video/sn9c102/Makefile | 6 +- drivers/media/video/sn9c102/sn9c102.h | 8 +- drivers/media/video/sn9c102/sn9c102_core.c | 264 +++--- drivers/media/video/sn9c102/sn9c102_hv7131d.c | 16 +- drivers/media/video/sn9c102/sn9c102_mi0343.c | 106 +-- drivers/media/video/sn9c102/sn9c102_ov7630.c | 14 +- drivers/media/video/sn9c102/sn9c102_pas106b.c | 16 +- drivers/media/video/sn9c102/sn9c102_pas202bca.c | 6 +- drivers/media/video/sn9c102/sn9c102_pas202bcb.c | 18 +- drivers/media/video/sn9c102/sn9c102_sensor.h | 70 +- drivers/media/video/sn9c102/sn9c102_tas5110c1b.c | 12 +- drivers/media/video/sn9c102/sn9c102_tas5130d1b.c | 12 +- drivers/media/video/stradis.c | 10 +- drivers/media/video/stv680.c | 48 +- drivers/media/video/stv680.h | 142 ++-- drivers/media/video/tda9840.c | 2 +- drivers/media/video/tea6415c.c | 2 +- drivers/media/video/tea6420.c | 2 +- drivers/media/video/tuner-3036.c | 50 +- drivers/media/video/usbvideo/ibmcam.c | 10 +- drivers/media/video/usbvideo/konicawc.c | 48 +- drivers/media/video/usbvideo/ultracam.c | 2 +- drivers/media/video/usbvideo/usbvideo.c | 42 +- drivers/media/video/usbvideo/usbvideo.h | 10 +- drivers/media/video/usbvideo/vicam.c | 28 +- drivers/media/video/videocodec.h | 52 +- drivers/media/video/vino.c | 4 +- drivers/media/video/vpx3220.c | 20 +- drivers/media/video/w9966.c | 102 +-- drivers/media/video/w9968cf.c | 930 ++++++++++----------- drivers/media/video/w9968cf.h | 12 +- drivers/media/video/w9968cf_decoder.h | 8 +- drivers/media/video/w9968cf_vpp.h | 2 +- drivers/media/video/zc0301/zc0301.h | 6 +- drivers/media/video/zc0301/zc0301_core.c | 148 ++-- drivers/media/video/zc0301/zc0301_pas202bcb.c | 12 +- drivers/media/video/zc0301/zc0301_sensor.h | 4 +- drivers/media/video/zoran.h | 2 +- drivers/media/video/zoran_card.c | 2 +- drivers/media/video/zoran_card.h | 2 +- drivers/media/video/zoran_device.c | 16 +- drivers/media/video/zoran_device.h | 2 +- drivers/media/video/zoran_driver.c | 16 +- drivers/media/video/zoran_procfs.c | 2 +- drivers/media/video/zoran_procfs.h | 2 +- drivers/media/video/zr36016.c | 22 +- drivers/media/video/zr36050.c | 16 +- drivers/media/video/zr36057.h | 10 +- drivers/media/video/zr36060.c | 20 +- drivers/media/video/zr36120.c | 46 +- drivers/media/video/zr36120.h | 6 +- 102 files changed, 3012 insertions(+), 3012 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 1f8a46b5916e..f31a19890b15 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -370,7 +370,7 @@ config VIDEO_SAA7127 # menu "V4L USB devices" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_DEV source "drivers/media/video/em28xx/Kconfig" @@ -528,17 +528,17 @@ config USB_W9968CF ---help--- Say Y here if you want support for cameras based on OV681 or Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. - + This driver has an optional plugin, which is distributed as a - separate module only (released under GPL). It allows to use higher - resolutions and framerates, but cannot be included in the official + separate module only (released under GPL). It allows to use higher + resolutions and framerates, but cannot be included in the official Linux kernel for performance purposes. See for more informations. This driver uses the Video For Linux and the I2C APIs. It needs the OmniVision Camera Chip support as well. You must say Y or M to - "Video For Linux", "I2C Support" and "OmniVision Camera Chip + "Video For Linux", "I2C Support" and "OmniVision Camera Chip support" to use this driver. To compile this driver as a module, choose M here: the @@ -564,20 +564,20 @@ config USB_PWC depends on USB && VIDEO_DEV ---help--- Say Y or M here if you want to use one of these Philips & OEM - webcams: - * Philips PCA645, PCA646 - * Philips PCVC675, PCVC680, PCVC690 - * Philips PCVC720/40, PCVC730, PCVC740, PCVC750 + webcams: + * Philips PCA645, PCA646 + * Philips PCVC675, PCVC680, PCVC690 + * Philips PCVC720/40, PCVC730, PCVC740, PCVC750 * Askey VC010 - * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' - and 'Orbit'/'Sphere' - * Samsung MPC-C10, MPC-C30 + * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' + and 'Orbit'/'Sphere' + * Samsung MPC-C10, MPC-C30 * Creative Webcam 5, Pro Ex * SOTEC Afina Eye * Visionite VCS-UC300, VCS-UM100 - + The PCA635, PCVC665 and PCVC720/20 are not supported by this driver - and never will be, but the 665 and 720/20 are supported by other + and never will be, but the 665 and 720/20 are supported by other drivers. See for more information and diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 671e36db224d..48709582a186 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -1,9 +1,9 @@ -/* +/* * adv7170 - adv7170, adv7171 video encoder driver version 0.0.1 * * Copyright (C) 2002 Maxim Yevtyushkin * - * Based on adv7176 driver by: + * Based on adv7176 driver by: * * Copyright (C) 1998 Dave Perks * Copyright (C) 1999 Wolfgang Scherr @@ -173,7 +173,7 @@ adv7170_write_block (struct i2c_client *client, static const unsigned char init_NTSC[] = { 0x00, 0x10, // MR0 0x01, 0x20, // MR1 - 0x02, 0x0e, // MR2 RTC control: bits 2 and 1 + 0x02, 0x0e, // MR2 RTC control: bits 2 and 1 0x03, 0x80, // MR3 0x04, 0x30, // MR4 0x05, 0x00, // Reserved @@ -196,7 +196,7 @@ static const unsigned char init_NTSC[] = { 0x16, 0x00, // CGMS_WSS_0 0x17, 0x00, // CGMS_WSS_1 0x18, 0x00, // CGMS_WSS_2 - 0x19, 0x00, // Teletext Ctl + 0x19, 0x00, // Teletext Ctl }; static const unsigned char init_PAL[] = { @@ -381,7 +381,7 @@ static unsigned short normal_i2c[] = }; static unsigned short ignore = I2C_CLIENT_END; - + static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = &ignore, diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 085e8863cacb..68e7d7aff5e6 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -1,4 +1,4 @@ -/* +/* * adv7175 - adv7175a video encoder driver version 0.0.3 * * Copyright (C) 1998 Dave Perks @@ -233,7 +233,7 @@ adv7175_command (struct i2c_client *client, sizeof(init_common)); adv7175_write(client, 0x07, TR0MODE | TR0RST); adv7175_write(client, 0x07, TR0MODE); - break; + break; case ENCODER_GET_CAPABILITIES: { @@ -399,7 +399,7 @@ static unsigned short normal_i2c[] = }; static unsigned short ignore = I2C_CLIENT_END; - + static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = &ignore, diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index c586f64b6b7f..dbe025170599 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -161,39 +161,39 @@ void iic(int n, unsigned long addr, unsigned long data1, unsigned long data2, { int i; - /* Slave Address */ - ar_outl(addr, PLDI2CDATA); + /* Slave Address */ + ar_outl(addr, PLDI2CDATA); wait_for_vsync(); - /* Start */ - ar_outl(1, PLDI2CCND); + /* Start */ + ar_outl(1, PLDI2CCND); wait_acknowledge(); /* Transfer data 1 */ - ar_outl(data1, PLDI2CDATA); + ar_outl(data1, PLDI2CDATA); wait_for_vsync(); - ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); + ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); wait_acknowledge(); /* Transfer data 2 */ - ar_outl(data2, PLDI2CDATA); + ar_outl(data2, PLDI2CDATA); wait_for_vsync(); - ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); + ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); wait_acknowledge(); if (n == 3) { /* Transfer data 3 */ - ar_outl(data3, PLDI2CDATA); + ar_outl(data3, PLDI2CDATA); wait_for_vsync(); - ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); + ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); wait_acknowledge(); - } + } - /* Stop */ + /* Stop */ for (i = 0; i < 100; i++) cpu_relax(); - ar_outl(2, PLDI2CCND); - ar_outl(2, PLDI2CCND); + ar_outl(2, PLDI2CCND); + ar_outl(2, PLDI2CCND); while (ar_inl(PLDI2CSTS) & PLDI2CSTS_BB) cpu_relax(); @@ -204,24 +204,24 @@ void init_iic(void) { DEBUG(1, "init_iic:\n"); - /* + /* * ICU Setting (iic) */ - /* I2C Setting */ - ar_outl(0x0, PLDI2CCR); /* I2CCR Disable */ - ar_outl(0x0300, PLDI2CMOD); /* I2CMOD ACK/8b-data/7b-addr/auto */ - ar_outl(0x1, PLDI2CACK); /* I2CACK ACK */ + /* I2C Setting */ + ar_outl(0x0, PLDI2CCR); /* I2CCR Disable */ + ar_outl(0x0300, PLDI2CMOD); /* I2CMOD ACK/8b-data/7b-addr/auto */ + ar_outl(0x1, PLDI2CACK); /* I2CACK ACK */ /* I2C CLK */ - /* 50MH-100k */ + /* 50MH-100k */ if (freq == 75) { - ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */ + ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */ } else if (freq == 50) { ar_outl(244, PLDI2CFREQ); /* BCLK = 50MHz */ } else { ar_outl(244, PLDI2CFREQ); /* default: BCLK = 50MHz */ } - ar_outl(0x1, PLDI2CCR); /* I2CCR Enable */ + ar_outl(0x1, PLDI2CCR); /* I2CCR Enable */ } /************************************************************************** @@ -253,7 +253,7 @@ static inline void wait_for_vertical_sync(int exp_line) /* * check HCOUNT because we cannot check vertical sync. - */ + */ for (; tmout >= 0; tmout--) { l = ar_inl(ARVHCOUNT); if (l == exp_line) @@ -562,8 +562,8 @@ static void ar_interrupt(int irq, void *dev, struct pt_regs *regs) /* operations for interlace mode */ if ( line_count < (AR_HEIGHT_VGA/2) ) /* even line */ line_number = (line_count << 1); - else /* odd line */ - line_number = + else /* odd line */ + line_number = (((line_count - (AR_HEIGHT_VGA/2)) << 1) + 1); } else { line_number = line_count; @@ -651,7 +651,7 @@ static int ar_initialize(struct video_device *dev) cr |= ARVCR1_NORMAL; ar_outl(cr, ARVCR1); - /* + /* * Initialize IIC so that CPU can communicate with AR LSI, * and send boot commands to AR LSI. */ @@ -846,7 +846,7 @@ static int __init ar_init(void) * so register video device as a frame grabber type. * device is named "video[0-64]". * video_register_device() initializes h/w using ar_initialize(). - */ + */ if (video_register_device(ar->vdev, VFL_TYPE_GRABBER, video_nr) != 0) { /* return -1, -ENFILE(full) or others */ printk("arv: register video (Colour AR) failed.\n"); diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index d8a18a6a5bee..e7b38fdd5e3c 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -1,4 +1,4 @@ -/* +/* * bt819 - BT819A VideoStream Decoder (Rockwell Part) * * Copyright (C) 1999 Mike Bernson @@ -6,7 +6,7 @@ * * Modifications for LML33/DC10plus unified driver * Copyright (C) 2000 Serguei Miridonov - * + * * Changes by Ronald Bultje * - moved over to linux>=2.4.x i2c protocol (9/9/2002) * @@ -206,9 +206,9 @@ bt819_init (struct i2c_client *client) Bug in the bt819 stepping on my board? */ 0x14, 0x00, /* 0x14 Vertial Scaling lsb */ - 0x16, 0x07, /* 0x16 Video Timing Polarity + 0x16, 0x07, /* 0x16 Video Timing Polarity ACTIVE=active low - FIELD: high=odd, + FIELD: high=odd, vreset=active high, hreset=active high */ 0x18, 0x68, /* 0x18 AGC Delay */ @@ -497,7 +497,7 @@ static unsigned short normal_i2c[] = { }; static unsigned short ignore = I2C_CLIENT_END; - + static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = &ignore, diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 4d47a0a0e974..af3b61d4fa7d 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -1,4 +1,4 @@ -/* +/* * bt856 - BT856A Digital Video Encoder (Rockwell Part) * * Copyright (C) 1999 Mike Bernson @@ -285,7 +285,7 @@ bt856_command (struct i2c_client *client, static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END }; static unsigned short ignore = I2C_CLIENT_END; - + static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = &ignore, diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index d97b7d8ac33d..cf61c590f4ad 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -150,7 +150,7 @@ static int qc_calibrate(struct qcam_device *q) static struct qcam_device *qcam_init(struct parport *port) { struct qcam_device *q; - + q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); if(q==NULL) return NULL; @@ -158,16 +158,16 @@ static struct qcam_device *qcam_init(struct parport *port) q->pport = port; q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL, NULL, 0, NULL); - if (q->pdev == NULL) + if (q->pdev == NULL) { printk(KERN_ERR "bw-qcam: couldn't register for %s.\n", port->name); kfree(q); return NULL; } - + memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); - + mutex_init(&q->lock); q->port_mode = (QC_ANY | QC_NOTSET); @@ -236,12 +236,12 @@ static int qc_waithand(struct qcam_device *q, int val) while (!((status = read_lpstatus(q)) & 8)) { /* 1000 is enough spins on the I/O for all normal - cases, at that point we start to poll slowly + cases, at that point we start to poll slowly until the camera wakes up. However, we are busy blocked until the camera responds, so setting it lower is much better for interactive response. */ - + if(runs++>maxpoll) { msleep_interruptible(5); @@ -255,12 +255,12 @@ static int qc_waithand(struct qcam_device *q, int val) while (((status = read_lpstatus(q)) & 8)) { /* 1000 is enough spins on the I/O for all normal - cases, at that point we start to poll slowly + cases, at that point we start to poll slowly until the camera wakes up. However, we are busy blocked until the camera responds, so setting it lower is much better for interactive response. */ - + if(runs++>maxpoll) { msleep_interruptible(5); @@ -282,17 +282,17 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val) { unsigned int status; int runs=0; - - do + + do { status = read_lpdata(q); /* 1000 is enough spins on the I/O for all normal - cases, at that point we start to poll slowly + cases, at that point we start to poll slowly until the camera wakes up. However, we are busy blocked until the camera responds, so setting it lower is much better for interactive response. */ - + if(runs++>maxpoll) { msleep_interruptible(5); @@ -321,7 +321,7 @@ static int qc_detect(struct qcam_device *q) lastreg = reg = read_lpstatus(q) & 0xf0; - for (i = 0; i < 500; i++) + for (i = 0; i < 500; i++) { reg = read_lpstatus(q) & 0xf0; if (reg != lastreg) @@ -357,7 +357,7 @@ static int qc_detect(struct qcam_device *q) static void qc_reset(struct qcam_device *q) { - switch (q->port_mode & QC_FORCE_MASK) + switch (q->port_mode & QC_FORCE_MASK) { case QC_FORCE_UNIDIR: q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; @@ -370,7 +370,7 @@ static void qc_reset(struct qcam_device *q) case QC_ANY: write_lpcontrol(q, 0x20); write_lpdata(q, 0x75); - + if (read_lpdata(q) != 0x75) { q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; } else { @@ -398,8 +398,8 @@ static void qc_reset(struct qcam_device *q) static int qc_setscanmode(struct qcam_device *q) { int old_mode = q->mode; - - switch (q->transfer_scale) + + switch (q->transfer_scale) { case 1: q->mode = 0; @@ -412,7 +412,7 @@ static int qc_setscanmode(struct qcam_device *q) break; } - switch (q->bpp) + switch (q->bpp) { case 4: break; @@ -421,7 +421,7 @@ static int qc_setscanmode(struct qcam_device *q) break; } - switch (q->port_mode & QC_MODE_MASK) + switch (q->port_mode & QC_MODE_MASK) { case QC_BIDIR: q->mode += 1; @@ -430,10 +430,10 @@ static int qc_setscanmode(struct qcam_device *q) case QC_UNIDIR: break; } - + if (q->mode != old_mode) q->status |= QC_PARAM_CHANGE; - + return 0; } @@ -451,7 +451,7 @@ static void qc_set(struct qcam_device *q) /* Set the brightness. Yes, this is repetitive, but it works. * Shorter versions seem to fail subtly. Feel free to try :-). */ /* I think the problem was in qc_command, not here -- bls */ - + qc_command(q, 0xb); qc_command(q, q->brightness); @@ -502,13 +502,13 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[]) unsigned int hi2, lo2; static int state = 0; - if (buffer == NULL) + if (buffer == NULL) { state = 0; return 0; } - - switch (q->port_mode & QC_MODE_MASK) + + switch (q->port_mode & QC_MODE_MASK) { case QC_BIDIR: /* Bi-directional Port */ write_lpcontrol(q, 0x26); @@ -517,7 +517,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[]) write_lpcontrol(q, 0x2e); lo2 = (qc_waithand2(q, 0) >> 1); hi2 = (read_lpstatus(q) >> 3) & 0x1f; - switch (q->bpp) + switch (q->bpp) { case 4: buffer[0] = lo & 0xf; @@ -544,7 +544,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[]) write_lpcontrol(q, 0xe); hi = (qc_waithand(q, 0) & 0xf0) >> 4; - switch (q->bpp) + switch (q->bpp) { case 4: buffer[0] = lo; @@ -552,7 +552,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[]) ret = 2; break; case 6: - switch (state) + switch (state) { case 0: buffer[0] = (lo << 2) | ((hi & 0xc) >> 2); @@ -604,13 +604,13 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l int shift=8-q->bpp; char invert; - if (q->mode == -1) + if (q->mode == -1) return -ENXIO; qc_command(q, 0x7); qc_command(q, q->mode); - if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) + if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) { write_lpcontrol(q, 0x2e); /* turn port around */ write_lpcontrol(q, 0x26); @@ -618,7 +618,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l write_lpcontrol(q, 0x2e); (void) qc_waithand(q, 0); } - + /* strange -- should be 15:63 below, but 4bpp is odd */ invert = (q->bpp == 4) ? 16 : 63; @@ -629,15 +629,15 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l q->transfer_scale; transperline = (transperline + divisor - 1) / divisor; - for (i = 0, yield = yieldlines; i < linestotrans; i++) + for (i = 0, yield = yieldlines; i < linestotrans; i++) { - for (pixels_read = j = 0; j < transperline; j++) + for (pixels_read = j = 0; j < transperline; j++) { bytes = qc_readbytes(q, buffer); - for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) + for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) { int o; - if (buffer[k] == 0 && invert == 16) + if (buffer[k] == 0 && invert == 16) { /* 4bpp is odd (again) -- inverter is 16, not 15, but output must be 0-15 -- bls */ @@ -653,7 +653,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l pixels_read += bytes; } (void) qc_readbytes(q, NULL); /* reset state machine */ - + /* Grabbing an entire frame from the quickcam is a lengthy process. We don't (usually) want to busy-block the processor for the entire frame. yieldlines is a module @@ -666,7 +666,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l } } - if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) + if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) { write_lpcontrol(q, 2); write_lpcontrol(q, 6); @@ -687,7 +687,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, { struct video_device *dev = video_devdata(file); struct qcam_device *qcam=(struct qcam_device *)dev; - + switch(cmd) { case VIDIOCGCAP: @@ -762,7 +762,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if(p->depth!=4 && p->depth!=6) return -EINVAL; - + /* * Now load the camera. */ @@ -790,11 +790,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if(vw->width<80||vw->width>320) return -EINVAL; - + qcam->width = 320; qcam->height = 240; qcam->transfer_scale = 4; - + if(vw->width>=160 && vw->height>=120) { qcam->transfer_scale = 2; @@ -808,11 +808,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, mutex_lock(&qcam->lock); qc_setscanmode(qcam); mutex_unlock(&qcam->lock); - + /* We must update the camera before we grab. We could just have changed the grab size */ qcam->status |= QC_PARAM_CHANGE; - + /* Ok we figured out what to use from our wide choice */ return 0; } @@ -853,9 +853,9 @@ static ssize_t qcam_read(struct file *file, char __user *buf, struct qcam_device *qcam=(struct qcam_device *)v; int len; parport_claim_or_block(qcam->pdev); - + mutex_lock(&qcam->lock); - + qc_reset(qcam); /* Update the camera parameters if we need to */ @@ -863,13 +863,13 @@ static ssize_t qcam_read(struct file *file, char __user *buf, qc_set(qcam); len=qc_capture(qcam, buf,count); - + mutex_unlock(&qcam->lock); - + parport_release(qcam->pdev); return len; } - + static struct file_operations qcam_fops = { .owner = THIS_MODULE, .open = video_exclusive_open, @@ -905,11 +905,11 @@ static int init_bwqcam(struct parport *port) qcam=qcam_init(port); if(qcam==NULL) return -ENODEV; - + parport_claim_or_block(qcam->pdev); qc_reset(qcam); - + if(qc_detect(qcam)==0) { parport_release(qcam->pdev); @@ -920,9 +920,9 @@ static int init_bwqcam(struct parport *port) qc_calibrate(qcam); parport_release(qcam->pdev); - + printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name); - + if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1) { parport_unregister_device(qcam->pdev); @@ -1013,7 +1013,7 @@ static int __init init_bw_qcams(void) printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n"); maxpoll = 5000; } - + if (yieldlines < 1) { printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n"); yieldlines = 1; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 8211fd8d7cbf..22a7386bbea6 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -16,7 +16,7 @@ * * The parport parameter controls which parports will be scanned. * Scanning all parports causes some printers to print a garbage page. - * -- March 14, 1999 Billy Donahue + * -- March 14, 1999 Billy Donahue * * Fixed data format to BGR, added force_rgb parameter. Added missing * parport_unregister_driver() on module removal. @@ -88,7 +88,7 @@ static inline unsigned int qcam_ready2(struct qcam_device *qcam) return (parport_read_data(qcam->pport) & 0x1)?1:0; } -static unsigned int qcam_await_ready1(struct qcam_device *qcam, +static unsigned int qcam_await_ready1(struct qcam_device *qcam, int value) { unsigned long oldjiffies = jiffies; @@ -98,7 +98,7 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam, if (qcam_ready1(qcam) == value) return 0; - /* If the camera didn't respond within 1/25 second, poll slowly + /* If the camera didn't respond within 1/25 second, poll slowly for a while. */ for (i = 0; i < 50; i++) { @@ -123,7 +123,7 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) if (qcam_ready2(qcam) == value) return 0; - /* If the camera didn't respond within 1/25 second, poll slowly + /* If the camera didn't respond within 1/25 second, poll slowly for a while. */ for (i = 0; i < 50; i++) { @@ -157,12 +157,12 @@ static int qcam_write_data(struct qcam_device *qcam, unsigned int data) unsigned int idata; parport_write_data(qcam->pport, data); idata = qcam_read_data(qcam); - if (data != idata) + if (data != idata) { - printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, + printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, idata); return 1; - } + } return 0; } @@ -193,12 +193,12 @@ static int qc_detect(struct qcam_device *qcam) no device was found". Fix this one day. */ if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA && qcam->pport->probe_info[0].model - && !strcmp(qcam->pdev->port->probe_info[0].model, + && !strcmp(qcam->pdev->port->probe_info[0].model, "Color QuickCam 2.0")) { printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n"); return 1; } - + if (probe < 2) return 0; @@ -206,11 +206,11 @@ static int qc_detect(struct qcam_device *qcam) /* look for a heartbeat */ ostat = stat = parport_read_status(qcam->pport); - for (i=0; i<250; i++) + for (i=0; i<250; i++) { mdelay(1); stat = parport_read_status(qcam->pport); - if (ostat != stat) + if (ostat != stat) { if (++count >= 3) return 1; ostat = stat; @@ -226,11 +226,11 @@ static int qc_detect(struct qcam_device *qcam) count = 0; ostat = stat = parport_read_status(qcam->pport); - for (i=0; i<250; i++) + for (i=0; i<250; i++) { mdelay(1); stat = parport_read_status(qcam->pport); - if (ostat != stat) + if (ostat != stat) { if (++count >= 3) return 1; ostat = stat; @@ -247,7 +247,7 @@ static void qc_reset(struct qcam_device *qcam) parport_write_control(qcam->pport, 0x8); mdelay(1); parport_write_control(qcam->pport, 0xc); - mdelay(1); + mdelay(1); } /* Reset the QuickCam and program for brightness, contrast, @@ -258,7 +258,7 @@ static void qc_setup(struct qcam_device *q) qc_reset(q); /* Set the brightness. */ - qcam_set(q, 11, q->brightness); + qcam_set(q, 11, q->brightness); /* Set the height and width. These refer to the actual CCD area *before* applying the selected decimation. */ @@ -272,12 +272,12 @@ static void qc_setup(struct qcam_device *q) /* Set contrast and white balance. */ qcam_set(q, 0x19, q->contrast); qcam_set(q, 0x1f, q->whitebal); - + /* Set the speed. */ qcam_set(q, 45, 2); } -/* Read some bytes from the camera and put them in the buffer. +/* Read some bytes from the camera and put them in the buffer. nbytes should be a multiple of 3, because bidirectional mode gives us three bytes at a time. */ @@ -383,7 +383,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1)) return -EIO; - + lines = q->height; pixelsperline = q->width; bitsperxfer = (is_bi_dir) ? 24 : 8; @@ -499,7 +499,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, { struct video_device *dev = video_devdata(file); struct qcam_device *qcam=(struct qcam_device *)dev; - + switch(cmd) { case VIDIOCGCAP: @@ -574,7 +574,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, */ if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24) return -EINVAL; - + /* * Now load the camera. */ @@ -584,7 +584,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, mutex_lock(&qcam->lock); parport_claim_or_block(qcam->pdev); - qc_setup(qcam); + qc_setup(qcam); parport_release(qcam->pdev); mutex_unlock(&qcam->lock); return 0; @@ -601,11 +601,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; if(vw->width<80||vw->width>320) return -EINVAL; - + qcam->width = 80; qcam->height = 60; qcam->mode = QC_DECIMATION_4; - + if(vw->width>=160 && vw->height>=120) { qcam->width = 160; @@ -627,7 +627,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, qcam->mode = QC_BILLIONS | QC_DECIMATION_1; } #endif - /* Ok we figured out what to use from our + /* Ok we figured out what to use from our wide choice */ mutex_lock(&qcam->lock); parport_claim_or_block(qcam->pdev); @@ -676,7 +676,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf, mutex_lock(&qcam->lock); parport_claim_or_block(qcam->pdev); /* Probably should have a semaphore against multiple users */ - len = qc_capture(qcam, buf,count); + len = qc_capture(qcam, buf,count); parport_release(qcam->pdev); mutex_unlock(&qcam->lock); return len; @@ -707,7 +707,7 @@ static struct video_device qcam_template= static struct qcam_device *qcam_init(struct parport *port) { struct qcam_device *q; - + q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); if(q==NULL) return NULL; @@ -718,14 +718,14 @@ static struct qcam_device *qcam_init(struct parport *port) q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE)?1:0; - if (q->pdev == NULL) + if (q->pdev == NULL) { printk(KERN_ERR "c-qcam: couldn't register for %s.\n", port->name); kfree(q); return NULL; } - + memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); mutex_init(&q->lock); @@ -766,11 +766,11 @@ static int init_cqcam(struct parport *port) qcam = qcam_init(port); if (qcam==NULL) return -ENODEV; - + parport_claim_or_block(qcam->pdev); qc_reset(qcam); - + if (probe && qc_detect(qcam)==0) { parport_release(qcam->pdev); @@ -782,7 +782,7 @@ static int init_cqcam(struct parport *port) qc_setup(qcam); parport_release(qcam->pdev); - + if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1) { printk(KERN_ERR "Unable to register Colour QuickCam on %s\n", @@ -792,9 +792,9 @@ static int init_cqcam(struct parport *port) return -ENODEV; } - printk(KERN_INFO "video%d: Colour QuickCam found on %s\n", + printk(KERN_INFO "video%d: Colour QuickCam found on %s\n", qcam->vdev.minor, qcam->pport->name); - + qcams[num_cams++] = qcam; return 0; diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 3cebfa91ca14..2227c5640c12 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -24,7 +24,7 @@ */ /* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ -/* #define _CPIA_DEBUG_ 1 */ +/* #define _CPIA_DEBUG_ 1 */ #include @@ -67,11 +67,11 @@ MODULE_SUPPORTED_DEVICE("video"); static unsigned short colorspace_conv = 0; module_param(colorspace_conv, ushort, 0444); MODULE_PARM_DESC(colorspace_conv, - "\n Colorspace conversion:" - "\n0 = disable" - "\n1 = enable" - "\nDefault value is 0" - "\n"); + "\n Colorspace conversion:" + "\n0 = disable" + "\n1 = enable" + "\nDefault value is 0" + "\n"); #define ABOUT "V4L-Driver for Vision CPiA based cameras" @@ -189,8 +189,8 @@ enum { #define TC 94 #define EXP_ACC_DARK 50 #define EXP_ACC_LIGHT 90 -#define HIGH_COMP_102 160 -#define MAX_COMP 239 +#define HIGH_COMP_102 160 +#define MAX_COMP 239 #define DARK_TIME 3 #define LIGHT_TIME 3 @@ -208,7 +208,7 @@ static u8 flicker_jumps[2][2][4] = static void reset_camera_struct(struct cam_data *cam); static int find_over_exposure(int brightness); static void set_flicker(struct cam_params *params, volatile u32 *command_flags, - int on); + int on); /********************************************************************** @@ -262,7 +262,7 @@ static void rvfree(void *mem, unsigned long size) static struct proc_dir_entry *cpia_proc_root=NULL; static int cpia_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) + int count, int *eof, void *data) { char *out = page; int len, tmp; @@ -276,58 +276,58 @@ static int cpia_read_proc(char *page, char **start, off_t off, out += sprintf(out, "V4L Driver version: %d.%d.%d\n", CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); out += sprintf(out, "CPIA Version: %d.%02d (%d.%d)\n", - cam->params.version.firmwareVersion, - cam->params.version.firmwareRevision, - cam->params.version.vcVersion, - cam->params.version.vcRevision); + cam->params.version.firmwareVersion, + cam->params.version.firmwareRevision, + cam->params.version.vcVersion, + cam->params.version.vcRevision); out += sprintf(out, "CPIA PnP-ID: %04x:%04x:%04x\n", - cam->params.pnpID.vendor, cam->params.pnpID.product, - cam->params.pnpID.deviceRevision); + cam->params.pnpID.vendor, cam->params.pnpID.product, + cam->params.pnpID.deviceRevision); out += sprintf(out, "VP-Version: %d.%d %04x\n", - cam->params.vpVersion.vpVersion, - cam->params.vpVersion.vpRevision, - cam->params.vpVersion.cameraHeadID); - + cam->params.vpVersion.vpVersion, + cam->params.vpVersion.vpRevision, + cam->params.vpVersion.cameraHeadID); + out += sprintf(out, "system_state: %#04x\n", - cam->params.status.systemState); + cam->params.status.systemState); out += sprintf(out, "grab_state: %#04x\n", - cam->params.status.grabState); + cam->params.status.grabState); out += sprintf(out, "stream_state: %#04x\n", - cam->params.status.streamState); + cam->params.status.streamState); out += sprintf(out, "fatal_error: %#04x\n", - cam->params.status.fatalError); + cam->params.status.fatalError); out += sprintf(out, "cmd_error: %#04x\n", - cam->params.status.cmdError); + cam->params.status.cmdError); out += sprintf(out, "debug_flags: %#04x\n", - cam->params.status.debugFlags); + cam->params.status.debugFlags); out += sprintf(out, "vp_status: %#04x\n", - cam->params.status.vpStatus); + cam->params.status.vpStatus); out += sprintf(out, "error_code: %#04x\n", - cam->params.status.errorCode); + cam->params.status.errorCode); /* QX3 specific entries */ if (cam->params.qx3.qx3_detected) { out += sprintf(out, "button: %4d\n", - cam->params.qx3.button); + cam->params.qx3.button); out += sprintf(out, "cradled: %4d\n", - cam->params.qx3.cradled); + cam->params.qx3.cradled); } out += sprintf(out, "video_size: %s\n", - cam->params.format.videoSize == VIDEOSIZE_CIF ? + cam->params.format.videoSize == VIDEOSIZE_CIF ? "CIF " : "QCIF"); out += sprintf(out, "roi: (%3d, %3d) to (%3d, %3d)\n", - cam->params.roi.colStart*8, - cam->params.roi.rowStart*4, - cam->params.roi.colEnd*8, - cam->params.roi.rowEnd*4); + cam->params.roi.colStart*8, + cam->params.roi.rowStart*4, + cam->params.roi.colEnd*8, + cam->params.roi.rowEnd*4); out += sprintf(out, "actual_fps: %3d\n", cam->fps); out += sprintf(out, "transfer_rate: %4dkB/s\n", - cam->transfer_rate); - + cam->transfer_rate); + out += sprintf(out, "\nread-write\n"); out += sprintf(out, "----------------------- current min" - " max default comment\n"); + " max default comment\n"); out += sprintf(out, "brightness: %8d %8d %8d %8d\n", - cam->params.colourParams.brightness, 0, 100, 50); + cam->params.colourParams.brightness, 0, 100, 50); if (cam->params.version.firmwareVersion == 1 && cam->params.version.firmwareRevision == 2) /* 1-02 firmware limits contrast to 80 */ @@ -336,26 +336,26 @@ static int cpia_read_proc(char *page, char **start, off_t off, tmp = 96; out += sprintf(out, "contrast: %8d %8d %8d %8d" - " steps of 8\n", - cam->params.colourParams.contrast, 0, tmp, 48); + " steps of 8\n", + cam->params.colourParams.contrast, 0, tmp, 48); out += sprintf(out, "saturation: %8d %8d %8d %8d\n", - cam->params.colourParams.saturation, 0, 100, 50); + cam->params.colourParams.saturation, 0, 100, 50); tmp = (25000+5000*cam->params.sensorFps.baserate)/ (1<params.sensorFps.divisor); out += sprintf(out, "sensor_fps: %4d.%03d %8d %8d %8d\n", - tmp/1000, tmp%1000, 3, 30, 15); + tmp/1000, tmp%1000, 3, 30, 15); out += sprintf(out, "stream_start_line: %8d %8d %8d %8d\n", - 2*cam->params.streamStartLine, 0, + 2*cam->params.streamStartLine, 0, cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144, cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120); out += sprintf(out, "sub_sample: %8s %8s %8s %8s\n", - cam->params.format.subSample == SUBSAMPLE_420 ? + cam->params.format.subSample == SUBSAMPLE_420 ? "420" : "422", "420", "422", "422"); out += sprintf(out, "yuv_order: %8s %8s %8s %8s\n", - cam->params.format.yuvOrder == YUVORDER_YUYV ? + cam->params.format.yuvOrder == YUVORDER_YUYV ? "YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV"); out += sprintf(out, "ecp_timing: %8s %8s %8s %8s\n", - cam->params.ecpTiming ? "slow" : "normal", "slow", + cam->params.ecpTiming ? "slow" : "normal", "slow", "normal", "normal"); if (cam->params.colourBalance.balanceMode == 2) { @@ -366,11 +366,11 @@ static int cpia_read_proc(char *page, char **start, off_t off, out += sprintf(out, "color_balance_mode: %8s %8s %8s" " %8s\n", tmpstr, "manual", "auto", "auto"); out += sprintf(out, "red_gain: %8d %8d %8d %8d\n", - cam->params.colourBalance.redGain, 0, 212, 32); + cam->params.colourBalance.redGain, 0, 212, 32); out += sprintf(out, "green_gain: %8d %8d %8d %8d\n", - cam->params.colourBalance.greenGain, 0, 212, 6); + cam->params.colourBalance.greenGain, 0, 212, 6); out += sprintf(out, "blue_gain: %8d %8d %8d %8d\n", - cam->params.colourBalance.blueGain, 0, 212, 92); + cam->params.colourBalance.blueGain, 0, 212, 92); if (cam->params.version.firmwareVersion == 1 && cam->params.version.firmwareRevision == 2) @@ -381,11 +381,11 @@ static int cpia_read_proc(char *page, char **start, off_t off, if (cam->params.exposure.gainMode == 0) out += sprintf(out, "max_gain: unknown %28s" - " powers of 2\n", tmpstr); + " powers of 2\n", tmpstr); else out += sprintf(out, "max_gain: %8d %28s" " 1,2,4 or 8 \n", - 1<<(cam->params.exposure.gainMode-1), tmpstr); + 1<<(cam->params.exposure.gainMode-1), tmpstr); switch(cam->params.exposure.expMode) { case 1: @@ -402,10 +402,10 @@ static int cpia_read_proc(char *page, char **start, off_t off, out += sprintf(out, "exposure_mode: %8s %8s %8s" " %8s\n", tmpstr, "manual", "auto", "auto"); out += sprintf(out, "centre_weight: %8s %8s %8s %8s\n", - (2-cam->params.exposure.centreWeight) ? "on" : "off", - "off", "on", "on"); + (2-cam->params.exposure.centreWeight) ? "on" : "off", + "off", "on", "on"); out += sprintf(out, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n", - 1<params.exposure.gain, 1, 1); + 1<params.exposure.gain, 1, 1); if (cam->params.version.firmwareVersion == 1 && cam->params.version.firmwareRevision == 2) /* 1-02 firmware limits fineExp/2 to 127 */ @@ -414,7 +414,7 @@ static int cpia_read_proc(char *page, char **start, off_t off, tmp = 510; out += sprintf(out, "fine_exp: %8d %8d %8d %8d\n", - cam->params.exposure.fineExp*2, 0, tmp, 0); + cam->params.exposure.fineExp*2, 0, tmp, 0); if (cam->params.version.firmwareVersion == 1 && cam->params.version.firmwareRevision == 2) /* 1-02 firmware limits coarseExpHi to 0 */ @@ -426,46 +426,46 @@ static int cpia_read_proc(char *page, char **start, off_t off, " %8d\n", cam->params.exposure.coarseExpLo+ 256*cam->params.exposure.coarseExpHi, 0, tmp, 185); out += sprintf(out, "red_comp: %8d %8d %8d %8d\n", - cam->params.exposure.redComp, COMP_RED, 255, COMP_RED); + cam->params.exposure.redComp, COMP_RED, 255, COMP_RED); out += sprintf(out, "green1_comp: %8d %8d %8d %8d\n", - cam->params.exposure.green1Comp, COMP_GREEN1, 255, + cam->params.exposure.green1Comp, COMP_GREEN1, 255, COMP_GREEN1); out += sprintf(out, "green2_comp: %8d %8d %8d %8d\n", - cam->params.exposure.green2Comp, COMP_GREEN2, 255, + cam->params.exposure.green2Comp, COMP_GREEN2, 255, COMP_GREEN2); out += sprintf(out, "blue_comp: %8d %8d %8d %8d\n", - cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE); - + cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE); + out += sprintf(out, "apcor_gain1: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain1, 0, 0xff, 0x1c); + cam->params.apcor.gain1, 0, 0xff, 0x1c); out += sprintf(out, "apcor_gain2: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain2, 0, 0xff, 0x1a); + cam->params.apcor.gain2, 0, 0xff, 0x1a); out += sprintf(out, "apcor_gain4: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain4, 0, 0xff, 0x2d); + cam->params.apcor.gain4, 0, 0xff, 0x2d); out += sprintf(out, "apcor_gain8: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain8, 0, 0xff, 0x2a); + cam->params.apcor.gain8, 0, 0xff, 0x2a); out += sprintf(out, "vl_offset_gain1: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain1, 0, 255, 24); + cam->params.vlOffset.gain1, 0, 255, 24); out += sprintf(out, "vl_offset_gain2: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain2, 0, 255, 28); + cam->params.vlOffset.gain2, 0, 255, 28); out += sprintf(out, "vl_offset_gain4: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain4, 0, 255, 30); + cam->params.vlOffset.gain4, 0, 255, 30); out += sprintf(out, "vl_offset_gain8: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain8, 0, 255, 30); + cam->params.vlOffset.gain8, 0, 255, 30); out += sprintf(out, "flicker_control: %8s %8s %8s %8s\n", - cam->params.flickerControl.flickerMode ? "on" : "off", + cam->params.flickerControl.flickerMode ? "on" : "off", "off", "on", "off"); out += sprintf(out, "mains_frequency: %8d %8d %8d %8d" - " only 50/60\n", - cam->mainsFreq ? 60 : 50, 50, 60, 50); + " only 50/60\n", + cam->mainsFreq ? 60 : 50, 50, 60, 50); if(cam->params.flickerControl.allowableOverExposure < 0) out += sprintf(out, "allowable_overexposure: %4dauto auto %8d auto\n", - -cam->params.flickerControl.allowableOverExposure, - 255); + -cam->params.flickerControl.allowableOverExposure, + 255); else out += sprintf(out, "allowable_overexposure: %8d auto %8d auto\n", - cam->params.flickerControl.allowableOverExposure, - 255); + cam->params.flickerControl.allowableOverExposure, + 255); out += sprintf(out, "compression_mode: "); switch(cam->params.compression.mode) { case CPIA_COMPRESSION_NONE: @@ -483,52 +483,52 @@ static int cpia_read_proc(char *page, char **start, off_t off, } out += sprintf(out, " none,auto,manual auto\n"); out += sprintf(out, "decimation_enable: %8s %8s %8s %8s\n", - cam->params.compression.decimation == - DECIMATION_ENAB ? "on":"off", "off", "on", + cam->params.compression.decimation == + DECIMATION_ENAB ? "on":"off", "off", "on", "off"); out += sprintf(out, "compression_target: %9s %9s %9s %9s\n", - cam->params.compressionTarget.frTargeting == + cam->params.compressionTarget.frTargeting == CPIA_COMPRESSION_TARGET_FRAMERATE ? "framerate":"quality", "framerate", "quality", "quality"); out += sprintf(out, "target_framerate: %8d %8d %8d %8d\n", - cam->params.compressionTarget.targetFR, 1, 30, 15); + cam->params.compressionTarget.targetFR, 1, 30, 15); out += sprintf(out, "target_quality: %8d %8d %8d %8d\n", - cam->params.compressionTarget.targetQ, 1, 64, 5); + cam->params.compressionTarget.targetQ, 1, 64, 5); out += sprintf(out, "y_threshold: %8d %8d %8d %8d\n", - cam->params.yuvThreshold.yThreshold, 0, 31, 6); + cam->params.yuvThreshold.yThreshold, 0, 31, 6); out += sprintf(out, "uv_threshold: %8d %8d %8d %8d\n", - cam->params.yuvThreshold.uvThreshold, 0, 31, 6); + cam->params.yuvThreshold.uvThreshold, 0, 31, 6); out += sprintf(out, "hysteresis: %8d %8d %8d %8d\n", - cam->params.compressionParams.hysteresis, 0, 255, 3); + cam->params.compressionParams.hysteresis, 0, 255, 3); out += sprintf(out, "threshold_max: %8d %8d %8d %8d\n", - cam->params.compressionParams.threshMax, 0, 255, 11); + cam->params.compressionParams.threshMax, 0, 255, 11); out += sprintf(out, "small_step: %8d %8d %8d %8d\n", - cam->params.compressionParams.smallStep, 0, 255, 1); + cam->params.compressionParams.smallStep, 0, 255, 1); out += sprintf(out, "large_step: %8d %8d %8d %8d\n", - cam->params.compressionParams.largeStep, 0, 255, 3); + cam->params.compressionParams.largeStep, 0, 255, 3); out += sprintf(out, "decimation_hysteresis: %8d %8d %8d %8d\n", - cam->params.compressionParams.decimationHysteresis, + cam->params.compressionParams.decimationHysteresis, 0, 255, 2); out += sprintf(out, "fr_diff_step_thresh: %8d %8d %8d %8d\n", - cam->params.compressionParams.frDiffStepThresh, + cam->params.compressionParams.frDiffStepThresh, 0, 255, 5); out += sprintf(out, "q_diff_step_thresh: %8d %8d %8d %8d\n", - cam->params.compressionParams.qDiffStepThresh, + cam->params.compressionParams.qDiffStepThresh, 0, 255, 3); out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n", - cam->params.compressionParams.decimationThreshMod, + cam->params.compressionParams.decimationThreshMod, 0, 255, 2); /* QX3 specific entries */ if (cam->params.qx3.qx3_detected) { - out += sprintf(out, "toplight: %8s %8s %8s %8s\n", - cam->params.qx3.toplight ? "on" : "off", + out += sprintf(out, "toplight: %8s %8s %8s %8s\n", + cam->params.qx3.toplight ? "on" : "off", "off", "on", "off"); - out += sprintf(out, "bottomlight: %8s %8s %8s %8s\n", - cam->params.qx3.bottomlight ? "on" : "off", + out += sprintf(out, "bottomlight: %8s %8s %8s %8s\n", + cam->params.qx3.bottomlight ? "on" : "off", "off", "on", "off"); } - + len = out - page; len -= off; if (len < count) { @@ -543,7 +543,7 @@ static int cpia_read_proc(char *page, char **start, off_t off, static int match(char *checkstr, char **buffer, unsigned long *count, - int *find_colon, int *err) + int *find_colon, int *err) { int ret, colon_found = 1; int len = strlen(checkstr); @@ -583,7 +583,7 @@ static unsigned long int value(char **buffer, unsigned long *count, int *err) } static int cpia_write_proc(struct file *file, const char __user *buf, - unsigned long count, void *data) + unsigned long count, void *data) { struct cam_data *cam = data; struct cam_params new_params; @@ -619,12 +619,12 @@ static int cpia_write_proc(struct file *file, const char __user *buf, retval = -EINVAL; goto out; } - + buffer = page; - + if (mutex_lock_interruptible(&cam->param_lock)) return -ERESTARTSYS; - + /* * Skip over leading whitespace */ @@ -632,15 +632,15 @@ static int cpia_write_proc(struct file *file, const char __user *buf, --count; ++buffer; } - + memcpy(&new_params, &cam->params, sizeof(struct cam_params)); new_mains = cam->mainsFreq; - + #define MATCH(x) (match(x, &buffer, &count, &find_colon, &retval)) #define VALUE (value(&buffer,&count, &retval)) #define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \ - new_params.version.firmwareRevision == (y)) - + new_params.version.firmwareRevision == (y)) + retval = 0; while (count && !retval) { find_colon = 1; @@ -656,7 +656,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, } command_flags |= COMMAND_SETCOLOURPARAMS; if(new_params.flickerControl.allowableOverExposure < 0) - new_params.flickerControl.allowableOverExposure = + new_params.flickerControl.allowableOverExposure = -find_over_exposure(new_params.colourParams.brightness); if(new_params.flickerControl.flickerMode != 0) command_flags |= COMMAND_SETFLICKERCTRL; @@ -721,7 +721,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, /* Either base rate would work here */ new_params.sensorFps.baserate = 1; } - new_params.flickerControl.coarseJump = + new_params.flickerControl.coarseJump = flicker_jumps[new_mains] [new_params.sensorFps.baserate] [new_params.sensorFps.divisor]; @@ -1085,7 +1085,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, } else if (MATCH("mains_frequency")) { if (!retval && MATCH("50")) { new_mains = 0; - new_params.flickerControl.coarseJump = + new_params.flickerControl.coarseJump = flicker_jumps[new_mains] [new_params.sensorFps.baserate] [new_params.sensorFps.divisor]; @@ -1093,7 +1093,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, command_flags |= COMMAND_SETFLICKERCTRL; } else if (!retval && MATCH("60")) { new_mains = 1; - new_params.flickerControl.coarseJump = + new_params.flickerControl.coarseJump = flicker_jumps[new_mains] [new_params.sensorFps.baserate] [new_params.sensorFps.divisor]; @@ -1103,7 +1103,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, retval = -EINVAL; } else if (MATCH("allowable_overexposure")) { if (!retval && MATCH("auto")) { - new_params.flickerControl.allowableOverExposure = + new_params.flickerControl.allowableOverExposure = -find_over_exposure(new_params.colourParams.brightness); if(new_params.flickerControl.flickerMode != 0) command_flags |= COMMAND_SETFLICKERCTRL; @@ -1146,10 +1146,10 @@ static int cpia_write_proc(struct file *file, const char __user *buf, command_flags |= COMMAND_SETCOMPRESSION; } else if (MATCH("compression_target")) { if (!retval && MATCH("quality")) - new_params.compressionTarget.frTargeting = + new_params.compressionTarget.frTargeting = CPIA_COMPRESSION_TARGET_QUALITY; else if (!retval && MATCH("framerate")) - new_params.compressionTarget.frTargeting = + new_params.compressionTarget.frTargeting = CPIA_COMPRESSION_TARGET_FRAMERATE; else retval = -EINVAL; @@ -1173,7 +1173,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, if (!retval) { if(val > 0 && val <= 64) new_params.compressionTarget.targetQ = val; - else + else retval = -EINVAL; } command_flags |= COMMAND_SETCOMPRESSIONTARGET; @@ -1288,19 +1288,19 @@ static int cpia_write_proc(struct file *file, const char __user *buf, } command_flags |= COMMAND_SETCOMPRESSIONPARAMS; } else if (MATCH("toplight")) { - if (!retval && MATCH("on")) + if (!retval && MATCH("on")) new_params.qx3.toplight = 1; else if (!retval && MATCH("off")) new_params.qx3.toplight = 0; - else + else retval = -EINVAL; command_flags |= COMMAND_SETLIGHTS; } else if (MATCH("bottomlight")) { - if (!retval && MATCH("on")) + if (!retval && MATCH("on")) new_params.qx3.bottomlight = 1; - else if (!retval && MATCH("off")) + else if (!retval && MATCH("off")) new_params.qx3.bottomlight = 0; - else + else retval = -EINVAL; command_flags |= COMMAND_SETLIGHTS; } else { @@ -1326,7 +1326,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, } } } -#undef MATCH +#undef MATCH #undef VALUE #undef FIRMWARE_VERSION if (!retval) { @@ -1349,24 +1349,24 @@ static int cpia_write_proc(struct file *file, const char __user *buf, retval = size; } else DBG("error: %d\n", retval); - + mutex_unlock(&cam->param_lock); - + out: free_page((unsigned long)page); - return retval; + return retval; } static void create_proc_cpia_cam(struct cam_data *cam) { char name[7]; struct proc_dir_entry *ent; - + if (!cpia_proc_root || !cam) return; sprintf(name, "video%d", cam->vdev.minor); - + ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root); if (!ent) return; @@ -1374,9 +1374,9 @@ static void create_proc_cpia_cam(struct cam_data *cam) ent->data = cam; ent->read_proc = cpia_read_proc; ent->write_proc = cpia_write_proc; - /* + /* size of the proc entry is 3736 bytes for the standard webcam; - the extra features of the QX3 microscope add 189 bytes. + the extra features of the QX3 microscope add 189 bytes. (we have not yet probed the camera to see which type it is). */ ent->size = 3736 + 189; @@ -1386,10 +1386,10 @@ static void create_proc_cpia_cam(struct cam_data *cam) static void destroy_proc_cpia_cam(struct cam_data *cam) { char name[7]; - + if (!cam || !cam->proc_entry) return; - + sprintf(name, "video%d", cam->vdev.minor); remove_proc_entry(name, cpia_proc_root); cam->proc_entry = NULL; @@ -1596,13 +1596,13 @@ static void set_vw_size(struct cam_data *cam) cam->vc.width = cam->vw.width; if(cam->vc.height == 0) cam->vc.height = cam->vw.height; - + cam->params.roi.colStart += cam->vc.x >> 3; cam->params.roi.colEnd = cam->params.roi.colStart + - (cam->vc.width >> 3); + (cam->vc.width >> 3); cam->params.roi.rowStart += cam->vc.y >> 2; cam->params.roi.rowEnd = cam->params.roi.rowStart + - (cam->vc.height >> 2); + (cam->vc.height >> 2); return; } @@ -1624,7 +1624,7 @@ static int allocate_frame_buf(struct cam_data *cam) static int free_frame_buf(struct cam_data *cam) { int i; - + rvfree(cam->frame_buf, FRAME_NUM*CPIA_MAX_FRAME_SIZE); cam->frame_buf = NULL; for (i=0; i < FRAME_NUM; i++) @@ -1667,7 +1667,7 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) mutex_lock(&cam->param_lock); datasize=8; break; - case CPIA_COMMAND_ReadMCPorts: + case CPIA_COMMAND_ReadMCPorts: case CPIA_COMMAND_ReadVCRegs: datasize = 4; break; @@ -1746,10 +1746,10 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) mutex_unlock(&cam->param_lock); break; - case CPIA_COMMAND_ReadMCPorts: - if (!cam->params.qx3.qx3_detected) + case CPIA_COMMAND_ReadMCPorts: + if (!cam->params.qx3.qx3_detected) break; - /* test button press */ + /* test button press */ cam->params.qx3.button = ((data[1] & 0x02) == 0); if (cam->params.qx3.button) { /* button pressed - unlock the latch */ @@ -1770,9 +1770,9 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) /* send a command to the camera with an additional data transaction */ static int do_command_extended(struct cam_data *cam, u16 command, - u8 a, u8 b, u8 c, u8 d, - u8 e, u8 f, u8 g, u8 h, - u8 i, u8 j, u8 k, u8 l) + u8 a, u8 b, u8 c, u8 d, + u8 e, u8 f, u8 g, u8 h, + u8 i, u8 j, u8 k, u8 l) { int retval; u8 cmd[8], data[8]; @@ -1809,10 +1809,10 @@ static int do_command_extended(struct cam_data *cam, u16 command, #define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16) static int convert420(unsigned char *yuv, unsigned char *rgb, int out_fmt, - int linesize, int mmap_kludge) + int linesize, int mmap_kludge) { int y, u, v, r, g, b, y1; - + /* Odd lines use the same u and v as the previous line. * Because of compression, it is necessary to get this * information from the decoded image. */ @@ -1925,7 +1925,7 @@ static int convert420(unsigned char *yuv, unsigned char *rgb, int out_fmt, static int yuvconvert(unsigned char *yuv, unsigned char *rgb, int out_fmt, - int in_uyvy, int mmap_kludge) + int in_uyvy, int mmap_kludge) { int y, u, v, r, g, b, y1; @@ -2078,21 +2078,21 @@ static int parse_picture(struct cam_data *cam, int size) mutex_unlock(&cam->param_lock); return -1; } - + if (ibuf[17] != SUBSAMPLE_420 && ibuf[17] != SUBSAMPLE_422) { LOG("illegal subtype %d\n",ibuf[17]); mutex_unlock(&cam->param_lock); return -1; } subsample_422 = ibuf[17] == SUBSAMPLE_422; - + if (ibuf[18] != YUVORDER_YUYV && ibuf[18] != YUVORDER_UYVY) { LOG("illegal yuvorder %d\n",ibuf[18]); mutex_unlock(&cam->param_lock); return -1; } in_uyvy = ibuf[18] == YUVORDER_UYVY; - + if ((ibuf[24] != cam->params.roi.colStart) || (ibuf[25] != cam->params.roi.colEnd) || (ibuf[26] != cam->params.roi.rowStart) || @@ -2104,20 +2104,20 @@ static int parse_picture(struct cam_data *cam, int size) cols = 8*(ibuf[25] - ibuf[24]); rows = 4*(ibuf[27] - ibuf[26]); - + if ((ibuf[28] != NOT_COMPRESSED) && (ibuf[28] != COMPRESSED)) { LOG("illegal compression %d\n",ibuf[28]); mutex_unlock(&cam->param_lock); return -1; } compressed = (ibuf[28] == COMPRESSED); - + if (ibuf[29] != NO_DECIMATION && ibuf[29] != DECIMATION_ENAB) { LOG("illegal decimation %d\n",ibuf[29]); mutex_unlock(&cam->param_lock); return -1; } - decimation = (ibuf[29] == DECIMATION_ENAB); + decimation = (ibuf[29] == DECIMATION_ENAB); cam->params.yuvThreshold.yThreshold = ibuf[30]; cam->params.yuvThreshold.uvThreshold = ibuf[31]; @@ -2131,7 +2131,7 @@ static int parse_picture(struct cam_data *cam, int size) cam->params.status.errorCode = ibuf[39]; cam->fps = ibuf[41]; mutex_unlock(&cam->param_lock); - + linesize = skipcount(cols, out_fmt); ibuf += FRAME_HEADER_SIZE; size -= FRAME_HEADER_SIZE; @@ -2150,14 +2150,14 @@ static int parse_picture(struct cam_data *cam, int size) if (!compressed || (compressed && !(*ibuf & 1))) { if(subsample_422 || even_line) { obuf += yuvconvert(ibuf, obuf, out_fmt, - in_uyvy, cam->mmap_kludge); + in_uyvy, cam->mmap_kludge); ibuf += 4; ll -= 4; } else { /* SUBSAMPLE_420 on an odd line */ obuf += convert420(ibuf, obuf, - out_fmt, linesize, - cam->mmap_kludge); + out_fmt, linesize, + cam->mmap_kludge); ibuf += 2; ll -= 2; } @@ -2183,7 +2183,7 @@ static int parse_picture(struct cam_data *cam, int size) if ((size > 3) && (ibuf[0] == EOI) && (ibuf[1] == EOI) && (ibuf[2] == EOI) && (ibuf[3] == EOI)) { - size -= 4; + size -= 4; break; } @@ -2204,7 +2204,7 @@ static int parse_picture(struct cam_data *cam, int size) return -1; } } - + if(decimation) { /* interpolate odd rows */ int i, j; @@ -2233,7 +2233,7 @@ static int parse_picture(struct cam_data *cam, int size) static inline int init_stream_cap(struct cam_data *cam) { return do_command(cam, CPIA_COMMAND_InitStreamCap, - 0, cam->params.streamStartLine, 0, 0); + 0, cam->params.streamStartLine, 0, 0); } @@ -2254,7 +2254,7 @@ static int find_over_exposure(int brightness) int MaxAllowableOverExposure, OverExposure; MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness - - FLICKER_BRIGHTNESS_CONSTANT; + FLICKER_BRIGHTNESS_CONSTANT; if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE) { OverExposure = MaxAllowableOverExposure; @@ -2280,62 +2280,62 @@ static void dispatch_commands(struct cam_data *cam) DEB_BYTE(cam->cmd_queue>>8); if (cam->cmd_queue & COMMAND_SETFORMAT) { do_command(cam, CPIA_COMMAND_SetFormat, - cam->params.format.videoSize, - cam->params.format.subSample, - cam->params.format.yuvOrder, 0); + cam->params.format.videoSize, + cam->params.format.subSample, + cam->params.format.yuvOrder, 0); do_command(cam, CPIA_COMMAND_SetROI, - cam->params.roi.colStart, cam->params.roi.colEnd, - cam->params.roi.rowStart, cam->params.roi.rowEnd); + cam->params.roi.colStart, cam->params.roi.colEnd, + cam->params.roi.rowStart, cam->params.roi.rowEnd); cam->first_frame = 1; } if (cam->cmd_queue & COMMAND_SETCOLOURPARAMS) do_command(cam, CPIA_COMMAND_SetColourParams, - cam->params.colourParams.brightness, - cam->params.colourParams.contrast, - cam->params.colourParams.saturation, 0); + cam->params.colourParams.brightness, + cam->params.colourParams.contrast, + cam->params.colourParams.saturation, 0); if (cam->cmd_queue & COMMAND_SETAPCOR) do_command(cam, CPIA_COMMAND_SetApcor, - cam->params.apcor.gain1, - cam->params.apcor.gain2, - cam->params.apcor.gain4, - cam->params.apcor.gain8); + cam->params.apcor.gain1, + cam->params.apcor.gain2, + cam->params.apcor.gain4, + cam->params.apcor.gain8); if (cam->cmd_queue & COMMAND_SETVLOFFSET) do_command(cam, CPIA_COMMAND_SetVLOffset, - cam->params.vlOffset.gain1, - cam->params.vlOffset.gain2, - cam->params.vlOffset.gain4, - cam->params.vlOffset.gain8); + cam->params.vlOffset.gain1, + cam->params.vlOffset.gain2, + cam->params.vlOffset.gain4, + cam->params.vlOffset.gain8); if (cam->cmd_queue & COMMAND_SETEXPOSURE) { do_command_extended(cam, CPIA_COMMAND_SetExposure, - cam->params.exposure.gainMode, - 1, - cam->params.exposure.compMode, - cam->params.exposure.centreWeight, - cam->params.exposure.gain, - cam->params.exposure.fineExp, - cam->params.exposure.coarseExpLo, - cam->params.exposure.coarseExpHi, - cam->params.exposure.redComp, - cam->params.exposure.green1Comp, - cam->params.exposure.green2Comp, - cam->params.exposure.blueComp); + cam->params.exposure.gainMode, + 1, + cam->params.exposure.compMode, + cam->params.exposure.centreWeight, + cam->params.exposure.gain, + cam->params.exposure.fineExp, + cam->params.exposure.coarseExpLo, + cam->params.exposure.coarseExpHi, + cam->params.exposure.redComp, + cam->params.exposure.green1Comp, + cam->params.exposure.green2Comp, + cam->params.exposure.blueComp); if(cam->params.exposure.expMode != 1) { do_command_extended(cam, CPIA_COMMAND_SetExposure, - 0, - cam->params.exposure.expMode, - 0, 0, - cam->params.exposure.gain, - cam->params.exposure.fineExp, - cam->params.exposure.coarseExpLo, - cam->params.exposure.coarseExpHi, - 0, 0, 0, 0); + 0, + cam->params.exposure.expMode, + 0, 0, + cam->params.exposure.gain, + cam->params.exposure.fineExp, + cam->params.exposure.coarseExpLo, + cam->params.exposure.coarseExpHi, + 0, 0, 0, 0); } } - + if (cam->cmd_queue & COMMAND_SETCOLOURBALANCE) { if (cam->params.colourBalance.balanceMode == 1) { do_command(cam, CPIA_COMMAND_SetColourBalance, @@ -2358,47 +2358,47 @@ static void dispatch_commands(struct cam_data *cam) if (cam->cmd_queue & COMMAND_SETCOMPRESSIONTARGET) do_command(cam, CPIA_COMMAND_SetCompressionTarget, - cam->params.compressionTarget.frTargeting, - cam->params.compressionTarget.targetFR, - cam->params.compressionTarget.targetQ, 0); + cam->params.compressionTarget.frTargeting, + cam->params.compressionTarget.targetFR, + cam->params.compressionTarget.targetQ, 0); if (cam->cmd_queue & COMMAND_SETYUVTHRESH) do_command(cam, CPIA_COMMAND_SetYUVThresh, - cam->params.yuvThreshold.yThreshold, - cam->params.yuvThreshold.uvThreshold, 0, 0); + cam->params.yuvThreshold.yThreshold, + cam->params.yuvThreshold.uvThreshold, 0, 0); if (cam->cmd_queue & COMMAND_SETCOMPRESSIONPARAMS) do_command_extended(cam, CPIA_COMMAND_SetCompressionParams, - 0, 0, 0, 0, - cam->params.compressionParams.hysteresis, - cam->params.compressionParams.threshMax, - cam->params.compressionParams.smallStep, - cam->params.compressionParams.largeStep, - cam->params.compressionParams.decimationHysteresis, - cam->params.compressionParams.frDiffStepThresh, - cam->params.compressionParams.qDiffStepThresh, - cam->params.compressionParams.decimationThreshMod); + 0, 0, 0, 0, + cam->params.compressionParams.hysteresis, + cam->params.compressionParams.threshMax, + cam->params.compressionParams.smallStep, + cam->params.compressionParams.largeStep, + cam->params.compressionParams.decimationHysteresis, + cam->params.compressionParams.frDiffStepThresh, + cam->params.compressionParams.qDiffStepThresh, + cam->params.compressionParams.decimationThreshMod); if (cam->cmd_queue & COMMAND_SETCOMPRESSION) do_command(cam, CPIA_COMMAND_SetCompression, - cam->params.compression.mode, + cam->params.compression.mode, cam->params.compression.decimation, 0, 0); if (cam->cmd_queue & COMMAND_SETSENSORFPS) do_command(cam, CPIA_COMMAND_SetSensorFPS, - cam->params.sensorFps.divisor, - cam->params.sensorFps.baserate, 0, 0); + cam->params.sensorFps.divisor, + cam->params.sensorFps.baserate, 0, 0); if (cam->cmd_queue & COMMAND_SETFLICKERCTRL) do_command(cam, CPIA_COMMAND_SetFlickerCtrl, - cam->params.flickerControl.flickerMode, - cam->params.flickerControl.coarseJump, - abs(cam->params.flickerControl.allowableOverExposure), - 0); + cam->params.flickerControl.flickerMode, + cam->params.flickerControl.coarseJump, + abs(cam->params.flickerControl.allowableOverExposure), + 0); if (cam->cmd_queue & COMMAND_SETECPTIMING) do_command(cam, CPIA_COMMAND_SetECPTiming, - cam->params.ecpTiming, 0, 0, 0); + cam->params.ecpTiming, 0, 0, 0); if (cam->cmd_queue & COMMAND_PAUSE) do_command(cam, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); @@ -2409,9 +2409,9 @@ static void dispatch_commands(struct cam_data *cam) if (cam->cmd_queue & COMMAND_SETLIGHTS && cam->params.qx3.qx3_detected) { int p1 = (cam->params.qx3.bottomlight == 0) << 1; - int p2 = (cam->params.qx3.toplight == 0) << 3; - do_command(cam, CPIA_COMMAND_WriteVCReg, 0x90, 0x8F, 0x50, 0); - do_command(cam, CPIA_COMMAND_WriteMCPort, 2, 0, (p1|p2|0xE0), 0); + int p2 = (cam->params.qx3.toplight == 0) << 3; + do_command(cam, CPIA_COMMAND_WriteVCReg, 0x90, 0x8F, 0x50, 0); + do_command(cam, CPIA_COMMAND_WriteMCPort, 2, 0, (p1|p2|0xE0), 0); } cam->cmd_queue = COMMAND_NONE; @@ -2422,11 +2422,11 @@ static void dispatch_commands(struct cam_data *cam) static void set_flicker(struct cam_params *params, volatile u32 *command_flags, - int on) + int on) { /* Everything in here is from the Windows driver */ #define FIRMWARE_VERSION(x,y) (params->version.firmwareVersion == (x) && \ - params->version.firmwareRevision == (y)) + params->version.firmwareRevision == (y)) /* define for compgain calculation */ #if 0 #define COMPGAIN(base, curexp, newexp) \ @@ -2441,7 +2441,7 @@ static void set_flicker(struct cam_params *params, volatile u32 *command_flags, (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128))) #endif - + int currentexp = params->exposure.coarseExpLo + params->exposure.coarseExpHi*256; int startexp; @@ -2482,7 +2482,7 @@ static void set_flicker(struct cam_params *params, volatile u32 *command_flags, } if(FIRMWARE_VERSION(1,2)) params->exposure.compMode = 0; - else + else params->exposure.compMode = 1; params->apcor.gain1 = 0x18; @@ -2533,14 +2533,14 @@ static void set_flicker(struct cam_params *params, volatile u32 *command_flags, } #define FIRMWARE_VERSION(x,y) (cam->params.version.firmwareVersion == (x) && \ - cam->params.version.firmwareRevision == (y)) + cam->params.version.firmwareRevision == (y)) /* monitor the exposure and adjust the sensor frame rate if needed */ static void monitor_exposure(struct cam_data *cam) { u8 exp_acc, bcomp, gain, coarseL, cmd[8], data[8]; int retval, light_exp, dark_exp, very_dark_exp; int old_exposure, new_exposure, framerate; - + /* get necessary stats and register settings from camera */ /* do_command can't handle this, so do it ourselves */ cmd[0] = CPIA_COMMAND_ReadVPRegs>>8; @@ -2564,17 +2564,17 @@ static void monitor_exposure(struct cam_data *cam) mutex_lock(&cam->param_lock); light_exp = cam->params.colourParams.brightness + - TC - 50 + EXP_ACC_LIGHT; + TC - 50 + EXP_ACC_LIGHT; if(light_exp > 255) light_exp = 255; dark_exp = cam->params.colourParams.brightness + - TC - 50 - EXP_ACC_DARK; + TC - 50 - EXP_ACC_DARK; if(dark_exp < 0) dark_exp = 0; very_dark_exp = dark_exp/2; - + old_exposure = cam->params.exposure.coarseExpHi * 256 + - cam->params.exposure.coarseExpLo; + cam->params.exposure.coarseExpLo; if(!cam->params.flickerControl.disabled) { /* Flicker control on */ @@ -2667,11 +2667,11 @@ static void monitor_exposure(struct cam_data *cam) cam->exposure_status = EXPOSURE_NORMAL; } } - + framerate = cam->fps; if(framerate > 30 || framerate < 1) framerate = 1; - + if(!cam->params.flickerControl.disabled) { /* Flicker control on */ if((cam->exposure_status == EXPOSURE_VERY_DARK || @@ -2683,10 +2683,10 @@ static void monitor_exposure(struct cam_data *cam) ++cam->params.sensorFps.divisor; cam->cmd_queue |= COMMAND_SETSENSORFPS; - cam->params.flickerControl.coarseJump = + cam->params.flickerControl.coarseJump = flicker_jumps[cam->mainsFreq] - [cam->params.sensorFps.baserate] - [cam->params.sensorFps.divisor]; + [cam->params.sensorFps.baserate] + [cam->params.sensorFps.divisor]; cam->cmd_queue |= COMMAND_SETFLICKERCTRL; new_exposure = cam->params.flickerControl.coarseJump-1; @@ -2704,15 +2704,15 @@ static void monitor_exposure(struct cam_data *cam) cam->params.sensorFps.divisor > 0) { /* light for too long */ - int max_exp = FIRMWARE_VERSION(1,2) ? MAX_EXP_102 : MAX_EXP ; + int max_exp = FIRMWARE_VERSION(1,2) ? MAX_EXP_102 : MAX_EXP ; --cam->params.sensorFps.divisor; cam->cmd_queue |= COMMAND_SETSENSORFPS; - cam->params.flickerControl.coarseJump = + cam->params.flickerControl.coarseJump = flicker_jumps[cam->mainsFreq] - [cam->params.sensorFps.baserate] - [cam->params.sensorFps.divisor]; + [cam->params.sensorFps.baserate] + [cam->params.sensorFps.divisor]; cam->cmd_queue |= COMMAND_SETFLICKERCTRL; new_exposure = cam->params.flickerControl.coarseJump-1; @@ -2772,7 +2772,7 @@ static void monitor_exposure(struct cam_data *cam) It also adjust the colour balance when an exposure step is detected - as long as flicker is running -*/ +*/ static void restart_flicker(struct cam_data *cam) { int cam_exposure, old_exp; @@ -2786,22 +2786,22 @@ static void restart_flicker(struct cam_data *cam) } cam_exposure = cam->raw_image[39]*2; old_exp = cam->params.exposure.coarseExpLo + - cam->params.exposure.coarseExpHi*256; - /* - see how far away camera exposure is from a valid - flicker exposure value - */ - cam_exposure %= cam->params.flickerControl.coarseJump; + cam->params.exposure.coarseExpHi*256; + /* + see how far away camera exposure is from a valid + flicker exposure value + */ + cam_exposure %= cam->params.flickerControl.coarseJump; if(!cam->params.flickerControl.disabled && - cam_exposure <= cam->params.flickerControl.coarseJump - 3) { + cam_exposure <= cam->params.flickerControl.coarseJump - 3) { /* Flicker control auto-disabled */ cam->params.flickerControl.disabled = 1; } - + if(cam->params.flickerControl.disabled && cam->params.flickerControl.flickerMode && old_exp > cam->params.flickerControl.coarseJump + - ROUND_UP_EXP_FOR_FLICKER) { + ROUND_UP_EXP_FOR_FLICKER) { /* exposure is now high enough to switch flicker control back on */ set_flicker(&cam->params, &cam->cmd_queue, 1); @@ -2818,7 +2818,7 @@ static int clear_stall(struct cam_data *cam) { /* FIXME: Does this actually work? */ LOG("Clearing stall\n"); - + cam->ops->streamRead(cam->lowlevel_data, cam->raw_image, 0); do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0); return cam->params.status.streamState != STREAM_PAUSED; @@ -2878,7 +2878,7 @@ static int fetch_frame(void *data) return -EINTR; do_command(cam, CPIA_COMMAND_GetCameraStatus, - 0, 0, 0, 0); + 0, 0, 0, 0); } if(cam->params.status.streamState != STREAM_READY) { continue; @@ -2903,18 +2903,18 @@ static int fetch_frame(void *data) /* Switch flicker control back on if it got turned off */ restart_flicker(cam); - + /* If AEC is enabled, monitor the exposure and adjust the sensor frame rate if needed */ if(cam->params.exposure.expMode == 2) monitor_exposure(cam); - + /* camera idle now so dispatch queued commands */ dispatch_commands(cam); /* Update our knowledge of the camera state */ - do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); - do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); + do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); + do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); do_command(cam, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0); /* decompress and convert image to by copying it from @@ -2933,7 +2933,7 @@ static int fetch_frame(void *data) uncompressed. */ cam->first_frame = 1; do_command(cam, CPIA_COMMAND_SetGrabMode, - CPIA_GRAB_SINGLE, 0, 0, 0); + CPIA_GRAB_SINGLE, 0, 0, 0); /* FIXME: Trial & error - need up to 70ms for the grab mode change to complete ? */ msleep_interruptible(70); @@ -2957,12 +2957,12 @@ static int fetch_frame(void *data) if (cam->first_frame) { cam->first_frame = 0; do_command(cam, CPIA_COMMAND_SetCompression, - cam->params.compression.mode, + cam->params.compression.mode, cam->params.compression.decimation, 0, 0); /* Switch from single-grab to continuous grab */ do_command(cam, CPIA_COMMAND_SetGrabMode, - CPIA_GRAB_CONTINUOUS, 0, 0, 0); + CPIA_GRAB_CONTINUOUS, 0, 0, 0); } return 0; } @@ -2977,12 +2977,12 @@ static int capture_frame(struct cam_data *cam, struct video_mmap *vm) if ((err = allocate_frame_buf(cam))) return err; } - + cam->curframe = vm->frame; cam->frame[cam->curframe].state = FRAME_READY; return fetch_frame(cam); } - + static int goto_high_power(struct cam_data *cam) { if (do_command(cam, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0)) @@ -3039,22 +3039,22 @@ static void save_camera_state(struct cam_data *cam) static int set_camera_state(struct cam_data *cam) { cam->cmd_queue = COMMAND_SETCOMPRESSION | - COMMAND_SETCOMPRESSIONTARGET | - COMMAND_SETCOLOURPARAMS | - COMMAND_SETFORMAT | - COMMAND_SETYUVTHRESH | - COMMAND_SETECPTIMING | - COMMAND_SETCOMPRESSIONPARAMS | - COMMAND_SETEXPOSURE | - COMMAND_SETCOLOURBALANCE | - COMMAND_SETSENSORFPS | - COMMAND_SETAPCOR | - COMMAND_SETFLICKERCTRL | - COMMAND_SETVLOFFSET; + COMMAND_SETCOMPRESSIONTARGET | + COMMAND_SETCOLOURPARAMS | + COMMAND_SETFORMAT | + COMMAND_SETYUVTHRESH | + COMMAND_SETECPTIMING | + COMMAND_SETCOMPRESSIONPARAMS | + COMMAND_SETEXPOSURE | + COMMAND_SETCOLOURBALANCE | + COMMAND_SETSENSORFPS | + COMMAND_SETAPCOR | + COMMAND_SETFLICKERCTRL | + COMMAND_SETVLOFFSET; do_command(cam, CPIA_COMMAND_SetGrabMode, CPIA_GRAB_SINGLE,0,0,0); dispatch_commands(cam); - + /* Wait 6 frames for the sensor to get all settings and AEC/ACB to settle */ msleep_interruptible(6*(cam->params.sensorFps.baserate ? 33 : 40) * @@ -3062,7 +3062,7 @@ static int set_camera_state(struct cam_data *cam) if(signal_pending(current)) return -EINTR; - + save_camera_state(cam); return 0; @@ -3094,9 +3094,9 @@ static int reset_camera(struct cam_data *cam) if (goto_low_power(cam)) return -ENODEV; } - + /* procedure described in developer's guide p3-28 */ - + /* Check the firmware version. */ cam->params.version.firmwareVersion = 0; get_version_information(cam); @@ -3113,14 +3113,14 @@ static int reset_camera(struct cam_data *cam) cam->params.qx3.qx3_detected = (cam->params.pnpID.vendor == 0x0813 && cam->params.pnpID.product == 0x0001); - /* The fatal error checking should be done after + /* The fatal error checking should be done after * the camera powers up (developer's guide p 3-38) */ /* Set streamState before transition to high power to avoid bug * in firmware 1-02 */ do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0, - STREAM_NOT_READY, 0); - + STREAM_NOT_READY, 0); + /* GotoHiPower */ err = goto_high_power(cam); if (err) @@ -3142,16 +3142,16 @@ static int reset_camera(struct cam_data *cam) /* Firmware 1-02 may do this for parallel port cameras, * just clear the flags (developer's guide p 3-38) */ do_command(cam, CPIA_COMMAND_ModifyCameraStatus, - FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0); + FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0); } } - + /* Check the camera status again */ if (cam->params.status.fatalError) { if (cam->params.status.fatalError) return -EIO; } - + /* VPVersion can't be retrieved before the camera is in HiPower, * so get it here instead of in get_version_information. */ do_command(cam, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0); @@ -3193,24 +3193,24 @@ static int cpia_open(struct inode *inode, struct file *file) if (!cam->raw_image) goto oops; } - + if (!cam->decompressed_frame.data) { cam->decompressed_frame.data = rvmalloc(CPIA_MAX_FRAME_SIZE); if (!cam->decompressed_frame.data) goto oops; } - + /* open cpia */ err = -ENODEV; if (cam->ops->open(cam->lowlevel_data)) goto oops; - + /* reset the camera */ if ((err = reset_camera(cam)) != 0) { cam->ops->close(cam->lowlevel_data); goto oops; } - + err = -EINTR; if(signal_pending(current)) goto oops; @@ -3224,7 +3224,7 @@ static int cpia_open(struct inode *inode, struct file *file) /* init it to something */ cam->mmap_kludge = 0; - + ++cam->open_count; file->private_data = dev; mutex_unlock(&cam->busy_lock); @@ -3250,10 +3250,10 @@ static int cpia_close(struct inode *inode, struct file *file) struct cam_data *cam = dev->priv; if (cam->ops) { - /* Return ownership of /proc/cpia/videoX to root */ + /* Return ownership of /proc/cpia/videoX to root */ if(cam->proc_entry) cam->proc_entry->uid = 0; - + /* save camera state for later open (developers guide ch 3.5.3) */ save_camera_state(cam); @@ -3342,7 +3342,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf, return -EFAULT; } if (copy_to_user(buf, cam->decompressed_frame.data, - cam->decompressed_frame.count)) { + cam->decompressed_frame.count)) { DBG("copy_to_user failed\n"); mutex_unlock(&cam->busy_lock); return -EFAULT; @@ -3361,7 +3361,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, if (!cam || !cam->ops) return -ENODEV; - + /* make this _really_ smp-safe */ if (mutex_lock_interruptible(&cam->busy_lock)) return -EINTR; @@ -3405,7 +3405,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, v->norm = 0; break; } - + case VIDIOCSCHAN: { struct video_channel *v = arg; @@ -3424,7 +3424,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, *pic = cam->vp; break; } - + case VIDIOCSPICT: { struct video_picture *vp = arg; @@ -3458,11 +3458,11 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, /* Adjust flicker control if necessary */ if(cam->params.flickerControl.allowableOverExposure < 0) - cam->params.flickerControl.allowableOverExposure = + cam->params.flickerControl.allowableOverExposure = -find_over_exposure(cam->params.colourParams.brightness); if(cam->params.flickerControl.flickerMode != 0) cam->cmd_queue |= COMMAND_SETFLICKERCTRL; - + /* queue command to update camera */ cam->cmd_queue |= COMMAND_SETCOLOURPARAMS; @@ -3482,7 +3482,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, *vw = cam->vw; break; } - + case VIDIOCSWIN: { /* copy_from_user, check validity, copy to internal structure */ @@ -3514,7 +3514,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, /* video size is changing, reset the subcapture area */ memset(&cam->vc, 0, sizeof(cam->vc)); - + set_vw_size(cam); DBG("%d / %d\n", cam->vw.width, cam->vw.height); cam->cmd_queue |= COMMAND_SETFORMAT; @@ -3547,7 +3547,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, vm->offsets[i] = CPIA_MAX_FRAME_SIZE * i; break; } - + case VIDIOCMCAPTURE: { struct video_mmap *vm = arg; @@ -3597,7 +3597,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, /* video size is changing, reset the subcapture area */ memset(&cam->vc, 0, sizeof(cam->vc)); - + set_vw_size(cam); cam->cmd_queue |= COMMAND_SETFORMAT; dispatch_commands(cam); @@ -3608,7 +3608,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, break; } - + case VIDIOCSYNC: { int *frame = arg; @@ -3649,7 +3649,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, *vc = cam->vc; break; - } + } case VIDIOCSCAPTURE: { @@ -3665,7 +3665,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, retval = -EINVAL; break; } - + /* Clip to the resolution we can set for the ROI (every 8 columns and 4 rows) */ vc->x = vc->x & ~(__u32)7; @@ -3681,14 +3681,14 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, } DBG("%d,%d/%dx%d\n", vc->x,vc->y,vc->width, vc->height); - + mutex_lock(&cam->param_lock); - + cam->vc.x = vc->x; cam->vc.y = vc->y; cam->vc.width = vc->width; cam->vc.height = vc->height; - + set_vw_size(cam); cam->cmd_queue |= COMMAND_SETFORMAT; @@ -3699,7 +3699,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, dispatch_commands(cam); break; } - + case VIDIOCGUNIT: { struct video_unit *vu = arg; @@ -3715,7 +3715,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, break; } - + /* pointless to implement overlay with this camera */ case VIDIOCCAPTURE: case VIDIOCGFBUF: @@ -3738,7 +3738,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, mutex_unlock(&cam->busy_lock); return retval; -} +} static int cpia_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -3759,7 +3759,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) if (!cam || !cam->ops) return -ENODEV; - + DBG("cpia_mmap: %ld\n", size); if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE) @@ -3767,7 +3767,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) if (!cam || !cam->ops) return -ENODEV; - + /* make this _really_ smp-safe */ if (mutex_lock_interruptible(&cam->busy_lock)) return -EINTR; @@ -3851,11 +3851,11 @@ static void reset_camera_struct(struct cam_data *cam) cam->params.flickerControl.flickerMode = 0; cam->params.flickerControl.disabled = 1; - cam->params.flickerControl.coarseJump = + cam->params.flickerControl.coarseJump = flicker_jumps[cam->mainsFreq] - [cam->params.sensorFps.baserate] - [cam->params.sensorFps.divisor]; - cam->params.flickerControl.allowableOverExposure = + [cam->params.sensorFps.baserate] + [cam->params.sensorFps.divisor]; + cam->params.flickerControl.allowableOverExposure = -find_over_exposure(cam->params.colourParams.brightness); cam->params.vlOffset.gain1 = 20; cam->params.vlOffset.gain2 = 24; @@ -3870,21 +3870,21 @@ static void reset_camera_struct(struct cam_data *cam) cam->params.compressionParams.qDiffStepThresh = 3; cam->params.compressionParams.decimationThreshMod = 2; /* End of default values from Software Developer's Guide */ - + cam->transfer_rate = 0; cam->exposure_status = EXPOSURE_NORMAL; - + /* Set Sensor FPS to 15fps. This seems better than 30fps * for indoor lighting. */ cam->params.sensorFps.divisor = 1; cam->params.sensorFps.baserate = 1; - + cam->params.yuvThreshold.yThreshold = 6; /* From windows driver */ cam->params.yuvThreshold.uvThreshold = 6; /* From windows driver */ - + cam->params.format.subSample = SUBSAMPLE_422; cam->params.format.yuvOrder = YUVORDER_YUYV; - + cam->params.compression.mode = CPIA_COMPRESSION_AUTO; cam->params.compressionTarget.frTargeting = CPIA_COMPRESSION_TARGET_QUALITY; @@ -3898,7 +3898,7 @@ static void reset_camera_struct(struct cam_data *cam) cam->params.qx3.cradled = 0; cam->video_size = VIDEOSIZE_CIF; - + cam->vp.colour = 32768; /* 50% */ cam->vp.hue = 32768; /* 50% */ cam->vp.brightness = 32768; /* 50% */ @@ -3911,7 +3911,7 @@ static void reset_camera_struct(struct cam_data *cam) cam->vc.y = 0; cam->vc.width = 0; cam->vc.height = 0; - + cam->vw.x = 0; cam->vw.y = 0; set_vw_size(cam); @@ -3928,7 +3928,7 @@ static void reset_camera_struct(struct cam_data *cam) /* initialize cam_data structure */ static void init_camera_struct(struct cam_data *cam, - struct cpia_camera_ops *ops ) + struct cpia_camera_ops *ops ) { int i; @@ -3945,7 +3945,7 @@ static void init_camera_struct(struct cam_data *cam, memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template)); cam->vdev.priv = cam; - + cam->curframe = 0; for (i = 0; i < FRAME_NUM; i++) { cam->frame[i].width = 0; @@ -3961,15 +3961,15 @@ static void init_camera_struct(struct cam_data *cam, struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel) { - struct cam_data *camera; - + struct cam_data *camera; + if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL) return NULL; - + init_camera_struct( camera, ops ); camera->lowlevel_data = lowlevel; - + /* register v4l device */ if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { kfree(camera); @@ -3982,7 +3982,7 @@ struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowleve /* open cpia */ if (camera->ops->open(camera->lowlevel_data)) return camera; - + /* reset the camera */ if (reset_camera(camera) != 0) { camera->ops->close(camera->lowlevel_data); @@ -4022,11 +4022,11 @@ void cpia_unregister_camera(struct cam_data *cam) DBG("camera open -- setting ops to NULL\n"); cam->ops = NULL; } - + #ifdef CONFIG_PROC_FS DBG("destroying /proc/cpia/video%d\n", cam->vdev.minor); destroy_proc_cpia_cam(cam); -#endif +#endif if (!cam->open_count) { DBG("freeing camera\n"); kfree(cam); diff --git a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h index de6678200a57..dde27a6a4a09 100644 --- a/drivers/media/video/cpia.h +++ b/drivers/media/video/cpia.h @@ -52,10 +52,10 @@ struct cpia_camera_ops { /* open sets privdata to point to structure for this camera. - * Returns negative value on error, otherwise 0. + * Returns negative value on error, otherwise 0. */ int (*open)(void *privdata); - + /* Registers callback function cb to be called with cbdata * when an image is ready. If cb is NULL, only single image grabs * should be used. cb should immediately call streamRead to read @@ -63,8 +63,8 @@ struct cpia_camera_ops * otherwise 0. */ int (*registerCallback)(void *privdata, void (*cb)(void *cbdata), - void *cbdata); - + void *cbdata); + /* transferCmd sends commands to the camera. command MUST point to * an 8 byte buffer in kernel space. data can be NULL if no extra * data is needed. The size of the data is given by the last 2 @@ -77,30 +77,30 @@ struct cpia_camera_ops * Returns negative value on error, otherwise 0. */ int (*streamStart)(void *privdata); - + /* streamStop terminates stream capture mode. * Returns negative value on error, otherwise 0. */ int (*streamStop)(void *privdata); - + /* streamRead reads a frame from the camera. buffer points to a - * buffer large enough to hold a complete frame in kernel space. - * noblock indicates if this should be a non blocking read. + * buffer large enough to hold a complete frame in kernel space. + * noblock indicates if this should be a non blocking read. * Returns the number of bytes read, or negative value on error. - */ + */ int (*streamRead)(void *privdata, u8 *buffer, int noblock); - + /* close disables the device until open() is called again. * Returns negative value on error, otherwise 0. */ int (*close)(void *privdata); - + /* If wait_for_stream_ready is non-zero, wait until the streamState * is STREAM_READY before calling streamRead. */ int wait_for_stream_ready; - /* + /* * Used to maintain lowlevel module usage counts */ struct module *owner; @@ -215,14 +215,14 @@ struct cam_params { u8 videoSize; /* CIF/QCIF */ u8 subSample; u8 yuvOrder; - } format; - struct { /* Intel QX3 specific data */ - u8 qx3_detected; /* a QX3 is present */ - u8 toplight; /* top light lit , R/W */ - u8 bottomlight; /* bottom light lit, R/W */ - u8 button; /* snapshot button pressed (R/O) */ - u8 cradled; /* microscope is in cradle (R/O) */ - } qx3; + } format; + struct { /* Intel QX3 specific data */ + u8 qx3_detected; /* a QX3 is present */ + u8 toplight; /* top light lit , R/W */ + u8 bottomlight; /* bottom light lit, R/W */ + u8 button; /* snapshot button pressed (R/O) */ + u8 cradled; /* microscope is in cradle (R/O) */ + } qx3; struct { u8 colStart; /* skip first 8*colStart pixels */ u8 colEnd; /* finish at 8*colEnd pixels */ @@ -247,13 +247,13 @@ enum v4l_camstates { struct cam_data { struct list_head cam_data_list; - struct mutex busy_lock; /* guard against SMP multithreading */ + struct mutex busy_lock; /* guard against SMP multithreading */ struct cpia_camera_ops *ops; /* lowlevel driver operations */ void *lowlevel_data; /* private data for lowlevel driver */ u8 *raw_image; /* buffer for raw image data */ struct cpia_frame decompressed_frame; - /* buffer to hold decompressed frame */ - int image_size; /* sizeof last decompressed image */ + /* buffer to hold decompressed frame */ + int image_size; /* sizeof last decompressed image */ int open_count; /* # of process that have camera open */ /* camera status */ @@ -265,7 +265,7 @@ struct cam_data { struct mutex param_lock; /* params lock for this camera */ struct cam_params params; /* camera settings */ struct proc_dir_entry *proc_entry; /* /proc/cpia/videoX */ - + /* v4l */ int video_size; /* VIDEO_SIZE_ */ volatile enum v4l_camstates camstate; /* v4l layer status */ @@ -277,7 +277,7 @@ struct cam_data { /* mmap interface */ int curframe; /* the current frame to grab into */ u8 *frame_buf; /* frame buffer data */ - struct cpia_frame frame[FRAME_NUM]; + struct cpia_frame frame[FRAME_NUM]; /* FRAME_NUM-buffering, so we need a array */ int first_frame; @@ -424,7 +424,7 @@ void cpia_unregister_camera(struct cam_data *cam); #define DEB_BYTE(p)\ DBG("%1d %1d %1d %1d %1d %1d %1d %1d \n",\ (p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\ - (p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0); + (p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0); #endif /* __KERNEL__ */ diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c index 74cff626e044..3021f21aae36 100644 --- a/drivers/media/video/cpia_pp.c +++ b/drivers/media/video/cpia_pp.c @@ -23,7 +23,7 @@ */ /* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ -/* #define _CPIA_DEBUG_ 1 */ +/* #define _CPIA_DEBUG_ 1 */ #include @@ -45,7 +45,7 @@ static int cpia_pp_open(void *privdata); static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata), - void *cbdata); + void *cbdata); static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data); static int cpia_pp_streamStart(void *privdata); static int cpia_pp_streamStop(void *privdata); @@ -93,7 +93,7 @@ struct pp_cam_entry { int stream_irq; }; -static struct cpia_camera_ops cpia_pp_ops = +static struct cpia_camera_ops cpia_pp_ops = { cpia_pp_open, cpia_pp_registerCallback, @@ -123,7 +123,7 @@ static void cpia_parport_disable_irq( struct parport *port ) { } /* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility - * Link Flag during negotiation */ + * Link Flag during negotiation */ #define UPLOAD_FLAG 0x08 #define NIBBLE_TRANSFER 0x01 #define ECP_TRANSFER 0x03 @@ -139,17 +139,17 @@ static void cpia_parport_disable_irq( struct parport *port ) { /* CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */ /* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */ -static size_t cpia_read_nibble (struct parport *port, - void *buffer, size_t len, +static size_t cpia_read_nibble (struct parport *port, + void *buffer, size_t len, int flags) { - /* adapted verbatim, with one change, from + /* adapted verbatim, with one change, from parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */ unsigned char *buf = buffer; int i; unsigned char byte = 0; - + len *= 2; /* in nibbles */ for (i=0; i < len; i++) { unsigned char nibble; @@ -158,12 +158,12 @@ static size_t cpia_read_nibble (struct parport *port, * after every second nibble to signal that more * data is available. (the total number of Bytes that * should be sent is known; if too few are received, an error - * will be recorded after a timeout). + * will be recorded after a timeout). * This is incompatible with parport_ieee1284_read_nibble(), * which expects to find nFault LO after every second nibble. */ - /* Solution: modify cpia_read_nibble to only check for + /* Solution: modify cpia_read_nibble to only check for * nDataAvail before the first nibble is sent. */ @@ -216,7 +216,7 @@ static size_t cpia_read_nibble (struct parport *port, /* Second nibble */ byte |= nibble << 4; *buf++ = byte; - } else + } else byte = nibble; } @@ -238,18 +238,18 @@ static size_t cpia_read_nibble (struct parport *port, } /* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1) - * (See CPiA Data sheet p. 31) - * - * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a - * nonstandard variant of nibble mode which allows the same (mediocre) - * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable + * (See CPiA Data sheet p. 31) + * + * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a + * nonstandard variant of nibble mode which allows the same (mediocre) + * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable * parallel ports, but works also for non-TRISTATE-capable ports. * (Standard nibble mode only send 4 bits per cycle) * */ -static size_t cpia_read_nibble_stream(struct parport *port, - void *buffer, size_t len, +static size_t cpia_read_nibble_stream(struct parport *port, + void *buffer, size_t len, int flags) { int i; @@ -260,7 +260,7 @@ static size_t cpia_read_nibble_stream(struct parport *port, unsigned char nibble[2], byte = 0; int j; - /* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */ + /* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */ if (endseen > 3 ) break; @@ -268,7 +268,7 @@ static size_t cpia_read_nibble_stream(struct parport *port, parport_frob_control (port, PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); - + /* Event 9: nAck goes low. */ port->ieee1284.phase = IEEE1284_PH_REV_DATA; if (parport_wait_peripheral (port, @@ -282,7 +282,7 @@ static size_t cpia_read_nibble_stream(struct parport *port, /* Read lower nibble */ nibble[0] = parport_read_status (port) >>3; - + /* Event 10: Set nAutoFd high. */ parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); @@ -295,10 +295,10 @@ static size_t cpia_read_nibble_stream(struct parport *port, port->name); break; } - + /* Read upper nibble */ nibble[1] = parport_read_status (port) >>3; - + /* reassemble the byte */ for (j = 0; j < 2 ; j++ ) { nibble[j] &= ~8; @@ -335,8 +335,8 @@ static void EndTransferMode(struct pp_cam_entry *cam) static int ForwardSetup(struct pp_cam_entry *cam) { int retry; - - /* The CPiA uses ECP protocol for Downloads from the Host to the camera. + + /* The CPiA uses ECP protocol for Downloads from the Host to the camera. * This will be software-emulated if ECP hardware is not present */ @@ -375,9 +375,9 @@ static int ReverseSetup(struct pp_cam_entry *cam, int extensibility) upload_mode = mode; if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK; - /* the usual camera maximum response time is 10ms, but after + /* the usual camera maximum response time is 10ms, but after * receiving some commands, it needs up to 40ms. */ - + for(retry = 0; retry < 4; ++retry) { if(!parport_negotiate(cam->port, mode)) { break; @@ -439,10 +439,10 @@ static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size) /* support for CPiA variant nibble reads */ if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) { - if(cpia_read_nibble(cam->port, packet, size, 0) != size) - retval = -EIO; + if(cpia_read_nibble(cam->port, packet, size, 0) != size) + retval = -EIO; } else { - if(parport_read(cam->port, packet, size) != size) + if(parport_read(cam->port, packet, size) != size) retval = -EIO; } EndTransferMode(cam); @@ -542,18 +542,18 @@ static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock) block_size = PARPORT_CHUNK_SIZE; while( !cam->image_complete ) { cond_resched(); - + new_bytes = cpia_pp_read(cam->port, buffer, block_size ); if( new_bytes <= 0 ) { break; } i=-1; while(++iopen_count == 0) { if (parport_claim(cam->pdev)) { DBG("failed to claim the port\n"); @@ -645,12 +645,12 @@ static int cpia_pp_open(void *privdata) parport_write_control(cam->port, PARPORT_CONTROL_SELECT); udelay(50); parport_write_control(cam->port, - PARPORT_CONTROL_SELECT - | PARPORT_CONTROL_INIT); + PARPORT_CONTROL_SELECT + | PARPORT_CONTROL_INIT); } - + ++cam->open_count; - + return 0; } @@ -663,7 +663,7 @@ static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), vo { struct pp_cam_entry *cam = privdata; int retval = 0; - + if(cam->port->irq != PARPORT_IRQ_NONE) { INIT_WORK(&cam->cb_task, cb, cbdata); } else { @@ -707,9 +707,9 @@ static int cpia_pp_register(struct parport *port) LOG("failed to allocate camera structure\n"); return -ENOMEM; } - + pdev = parport_register_device(port, "cpia_pp", NULL, NULL, - NULL, 0, cam); + NULL, 0, cam); if (!pdev) { LOG("failed to parport_register_device\n"); @@ -753,19 +753,19 @@ static void cpia_pp_detach (struct parport *port) } cpia = NULL; } - spin_unlock( &cam_list_lock_pp ); + spin_unlock( &cam_list_lock_pp ); if (!cpia) { DBG("cpia_pp_detach failed to find cam_data in cam_list\n"); return; } - - cam = (struct pp_cam_entry *) cpia->lowlevel_data; + + cam = (struct pp_cam_entry *) cpia->lowlevel_data; cpia_unregister_camera(cpia); - if(cam->open_count > 0) + if(cam->open_count > 0) cpia_pp_close(cam); parport_unregister_device(cam->pdev); - cpia->lowlevel_data = NULL; + cpia->lowlevel_data = NULL; kfree(cam); } @@ -805,14 +805,14 @@ static struct parport_driver cpia_pp_driver = { int cpia_pp_init(void) { - printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, + printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER); if(parport_nr[0] == PPCPIA_PARPORT_OFF) { printk(" disabled\n"); return 0; } - + spin_lock_init( &cam_list_lock_pp ); if (parport_register_driver (&cpia_pp_driver)) { diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c index 03275c37c5d3..9c49a4b00116 100644 --- a/drivers/media/video/cpia_usb.c +++ b/drivers/media/video/cpia_usb.c @@ -22,7 +22,7 @@ */ /* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ -/* #define _CPIA_DEBUG_ 1 */ +/* #define _CPIA_DEBUG_ 1 */ #include #include @@ -85,7 +85,7 @@ struct usb_cpia { static int cpia_usb_open(void *privdata); static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata), - void *cbdata); + void *cbdata); static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data); static int cpia_usb_streamStart(void *privdata); static int cpia_usb_streamStop(void *privdata); @@ -127,7 +127,7 @@ static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs) ucpia->workbuff->status = FRAME_READING; ucpia->workbuff->length = 0; } - + for (i = 0; i < urb->number_of_packets; i++) { int n = urb->iso_frame_desc[i].actual_length; int st = urb->iso_frame_desc[i].status; @@ -141,9 +141,9 @@ static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs) printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n", ucpia->workbuff->length, n); return; } - + if (n) { - if ((ucpia->workbuff->length > 0) || + if ((ucpia->workbuff->length > 0) || (0x19 == cdata[0] && 0x68 == cdata[1])) { memcpy(ucpia->workbuff->data + ucpia->workbuff->length, cdata, n); ucpia->workbuff->length += n; @@ -160,7 +160,7 @@ static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs) ucpia->workbuff = ucpia->workbuff->next; ucpia->workbuff->status = FRAME_EMPTY; ucpia->workbuff->length = 0; - + if (waitqueue_active(&ucpia->wq_stream)) wake_up_interruptible(&ucpia->wq_stream); } @@ -178,7 +178,7 @@ static int cpia_usb_open(void *privdata) struct usb_cpia *ucpia = (struct usb_cpia *) privdata; struct urb *urb; int ret, retval = 0, fx, err; - + if (!ucpia) return -EINVAL; @@ -191,7 +191,7 @@ static int cpia_usb_open(void *privdata) retval = -EINVAL; goto error_0; } - + ret = usb_set_interface(ucpia->dev, ucpia->iface, 3); if (ret < 0) { printk(KERN_ERR "cpia_usb_open: usb_set_interface error (ret = %d)\n", ret); @@ -286,7 +286,7 @@ error_1: error_0: kfree (ucpia->sbuf[0].data); ucpia->sbuf[0].data = NULL; - + return retval; } @@ -307,7 +307,7 @@ static int WritePacket(struct usb_device *udev, const u8 *packet, u8 *buf, size_ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), packet[1] + (packet[0] << 8), USB_TYPE_VENDOR | USB_RECIP_DEVICE, - packet[2] + (packet[3] << 8), + packet[2] + (packet[3] << 8), packet[4] + (packet[5] << 8), buf, size, 1000); } @@ -324,7 +324,7 @@ static int ReadPacket(struct usb_device *udev, u8 *packet, u8 *buf, size_t size) return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), packet[1] + (packet[0] << 8), USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - packet[2] + (packet[3] << 8), + packet[2] + (packet[3] << 8), packet[4] + (packet[5] << 8), buf, size, 1000); } @@ -393,7 +393,7 @@ static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock) if (!ucpia || !ucpia->present) return -1; - + if (ucpia->curbuff->status != FRAME_READY) interruptible_sleep_on(&ucpia->wq_stream); else @@ -403,7 +403,7 @@ static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock) if (!mybuff) return -1; - + if (mybuff->status != FRAME_READY || mybuff->length < 4) { DBG("Something went wrong!\n"); return -1; @@ -411,7 +411,7 @@ static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock) memcpy(frame, mybuff->data, mybuff->length); mybuff->status = FRAME_EMPTY; - + /* DBG("read done, %d bytes, Header: %x/%x, Footer: %x%x%x%x\n", */ /* mybuff->length, frame[0], frame[1], */ /* frame[mybuff->length-4], frame[mybuff->length-3], */ @@ -447,7 +447,7 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try) kfree(ucpia->sbuf[1].data); ucpia->sbuf[1].data = NULL; - + if (ucpia->sbuf[0].urb) { usb_kill_urb(ucpia->sbuf[0].urb); usb_free_urb(ucpia->sbuf[0].urb); @@ -490,7 +490,7 @@ static int cpia_probe(struct usb_interface *intf, struct usb_cpia *ucpia; struct cam_data *cam; int ret; - + /* A multi-config CPiA camera? */ if (udev->descriptor.bNumConfigurations != 1) return -ENODEV; @@ -539,7 +539,7 @@ static int cpia_probe(struct usb_interface *intf, /* Before register_camera, important */ ucpia->present = 1; - + cam = cpia_register_camera(&cpia_usb_ops, ucpia); if (!cam) { LOG("failed to cpia_register_camera\n"); @@ -591,7 +591,7 @@ static void cpia_disconnect(struct usb_interface *intf) struct cam_data *cam = usb_get_intfdata(intf); struct usb_cpia *ucpia; struct usb_device *udev; - + usb_set_intfdata(intf, NULL); if (!cam) return; @@ -600,7 +600,7 @@ static void cpia_disconnect(struct usb_interface *intf) spin_lock( &cam_list_lock_usb ); list_del(&cam->cam_data_list); spin_unlock( &cam_list_lock_usb ); - + ucpia->present = 0; cpia_unregister_camera(cam); @@ -631,7 +631,7 @@ static void cpia_disconnect(struct usb_interface *intf) static int __init usb_cpia_init(void) { - printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, + printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, CPIA_USB_MAJ_VER,CPIA_USB_MIN_VER,CPIA_USB_PATCH_VER); spin_lock_init(&cam_list_lock_usb); diff --git a/drivers/media/video/cs8420.h b/drivers/media/video/cs8420.h index 2b22f3a38de5..621c0c6678ea 100644 --- a/drivers/media/video/cs8420.h +++ b/drivers/media/video/cs8420.h @@ -20,7 +20,7 @@ #define __CS8420_H__ /* Initialization Sequence */ - + static __u8 init8420[] = { 1, 0x01, 2, 0x02, 3, 0x00, 4, 0x46, 5, 0x24, 6, 0x84, 18, 0x18, 19, 0x13, diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index 1774ab7a40d2..b9ba95f5e026 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c @@ -86,7 +86,7 @@ static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_ return ret; } /*-------------------------------------------------------------------*/ -#ifdef DEBUG +#ifdef DEBUG static void dump_urb (struct urb *urb) { dbg("urb :%p", urb); @@ -136,7 +136,7 @@ static int dabusb_free_queue (struct list_head *q) for (p = q->next; p != q;) { b = list_entry (p, buff_t, buff_list); -#ifdef DEBUG +#ifdef DEBUG dump_urb(b->purb); #endif kfree(b->purb->transfer_buffer); @@ -287,7 +287,7 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) } } - + if( ret == -EPIPE ) { warn("CLEAR_FEATURE request to remove STALL condition."); if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) @@ -328,7 +328,7 @@ static int dabusb_loadmem (pdabusb_t s, const char *fname) PINTEL_HEX_RECORD ptr = firmware; dbg("Enter dabusb_loadmem (internal)"); - + ret = dabusb_8051_reset (s, 1); while (ptr->Type == 0) { @@ -449,7 +449,7 @@ static int dabusb_startrek (pdabusb_t s) if (!list_empty (&s->free_buff_list)) { pbuff_t end; int ret; - + while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) { dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list); @@ -506,7 +506,7 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l err("error: rec_buf_list is empty"); goto err; } - + b = list_entry (s->rec_buff_list.next, buff_t, buff_list); purb = b->purb; @@ -783,9 +783,9 @@ static void dabusb_disconnect (struct usb_interface *intf) pdabusb_t s = usb_get_intfdata (intf); dbg("dabusb_disconnect"); - + init_waitqueue_entry(&__wait, current); - + usb_set_intfdata (intf, NULL); if (s) { usb_deregister_dev (intf, &dabusb_class); @@ -797,7 +797,7 @@ static void dabusb_disconnect (struct usb_interface *intf) schedule(); current->state = TASK_RUNNING; remove_wait_queue(&s->remove_ok, &__wait); - + s->usbdev = NULL; s->overruns = 0; } diff --git a/drivers/media/video/dabusb.h b/drivers/media/video/dabusb.h index 96b03e4af8b9..00eb34c863eb 100644 --- a/drivers/media/video/dabusb.h +++ b/drivers/media/video/dabusb.h @@ -10,7 +10,7 @@ typedef struct #define DABUSB_VERSION 0x1000 #define IOCTL_DAB_BULK _IOWR('d', 0x30, bulk_transfer_t) #define IOCTL_DAB_OVERRUNS _IOR('d', 0x15, int) -#define IOCTL_DAB_VERSION _IOR('d', 0x3f, int) +#define IOCTL_DAB_VERSION _IOR('d', 0x3f, int) #ifdef __KERNEL__ @@ -36,7 +36,7 @@ typedef struct struct list_head rec_buff_list; } dabusb_t,*pdabusb_t; -typedef struct +typedef struct { pdabusb_t s; struct urb *purb; diff --git a/drivers/media/video/dsbr100.c b/drivers/media/video/dsbr100.c index 25646804d5be..3b4e9985c3d7 100644 --- a/drivers/media/video/dsbr100.c +++ b/drivers/media/video/dsbr100.c @@ -37,28 +37,28 @@ Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing Version 0.30: - Markus: Updates for 2.5.x kernel and more ISO compliant source + Markus: Updates for 2.5.x kernel and more ISO compliant source Version 0.25: - PSL and Markus: Cleanup, radio now doesn't stop on device close + PSL and Markus: Cleanup, radio now doesn't stop on device close Version 0.24: - Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally + Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally right. Some minor cleanup, improved standalone compilation Version 0.23: - Markus: Sign extension bug fixed by declaring transfer_buffer unsigned + Markus: Sign extension bug fixed by declaring transfer_buffer unsigned Version 0.22: - Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns, + Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns, thanks to Mike Cox for pointing the problem out. Version 0.21: - Markus: Minor cleanup, warnings if something goes wrong, lame attempt + Markus: Minor cleanup, warnings if something goes wrong, lame attempt to adhere to Documentation/CodingStyle - Version 0.2: - Brad Hards : Fixes to make it work as non-module + Version 0.2: + Brad Hards : Fixes to make it work as non-module Markus: Copyright clarification Version 0.01: Markus: initial release @@ -163,11 +163,11 @@ static struct usb_driver usb_dsbr100_driver = { static int dsbr100_start(dsbr100_device *radio) { if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, + USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 || usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - DSB100_ONOFF, + DSB100_ONOFF, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x01, 0x00, radio->transfer_buffer, 8, 300)<0) return -1; @@ -179,11 +179,11 @@ static int dsbr100_start(dsbr100_device *radio) static int dsbr100_stop(dsbr100_device *radio) { if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, + USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 || usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - DSB100_ONOFF, + DSB100_ONOFF, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x00, 0x00, radio->transfer_buffer, 8, 300)<0) return -1; @@ -195,16 +195,16 @@ static int dsbr100_setfreq(dsbr100_device *radio, int freq) { freq = (freq/16*80)/1000+856; if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - DSB100_TUNE, + DSB100_TUNE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - (freq>>8)&0x00ff, freq&0xff, + (freq>>8)&0x00ff, freq&0xff, radio->transfer_buffer, 8, 300)<0 || usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, + USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 || usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, + USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) { radio->stereo = -1; @@ -219,7 +219,7 @@ sees a stereo signal or not. Pity. */ static void dsbr100_getstat(dsbr100_device *radio) { if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), - USB_REQ_GET_STATUS, + USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0) radio->stereo = -1; @@ -232,7 +232,7 @@ static void dsbr100_getstat(dsbr100_device *radio) /* check if the device is present and register with v4l and usb if it is */ -static int usb_dsbr100_probe(struct usb_interface *intf, +static int usb_dsbr100_probe(struct usb_interface *intf, const struct usb_device_id *id) { dsbr100_device *radio; @@ -243,7 +243,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf, kfree(radio); return -ENOMEM; } - memcpy(radio->videodev, &dsbr100_videodev_template, + memcpy(radio->videodev, &dsbr100_videodev_template, sizeof(dsbr100_videodev_template)); radio->removed = 0; radio->users = 0; @@ -310,7 +310,7 @@ static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, struct video_tuner *v = arg; dsbr100_getstat(radio); - if(v->tuner) /* Only 1 tuner */ + if(v->tuner) /* Only 1 tuner */ return -EINVAL; v->rangelow = FREQ_MIN*FREQ_MUL; v->rangehigh = FREQ_MAX*FREQ_MUL; @@ -355,12 +355,12 @@ static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, v->volume = 1; v->step = 1; strcpy(v->name, "Radio"); - return 0; + return 0; } case VIDIOCSAUDIO: { struct video_audio *v = arg; - if (v->audio) + if (v->audio) return -EINVAL; if (v->flags&VIDEO_AUDIO_MUTE) { if (dsbr100_stop(radio)==-1) diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h index eee8afc9be72..2e5ca4032489 100644 --- a/drivers/media/video/et61x251/et61x251.h +++ b/drivers/media/video/et61x251/et61x251.h @@ -180,7 +180,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) void et61x251_attach_sensor(struct et61x251_device* cam, - struct et61x251_sensor* sensor) + struct et61x251_sensor* sensor) { memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor)); } @@ -199,7 +199,7 @@ do { \ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ else if ((level) >= 3) \ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ + __FUNCTION__, __LINE__ , ## args); \ } \ } while (0) # define KDBG(level, fmt, args...) \ @@ -209,7 +209,7 @@ do { \ pr_info("et61x251: " fmt "\n", ## args); \ else if ((level) == 3) \ pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ + __LINE__ , ## args); \ } \ } while (0) # define V4LDBG(level, name, cmd) \ @@ -226,7 +226,7 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) + __FUNCTION__, __LINE__ , ## args) #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 7cc01b828b3d..dfc9dd732c9d 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -44,7 +44,7 @@ /*****************************************************************************/ #define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \ - "PC Camera Controllers" + "PC Camera Controllers" #define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" #define ET61X251_AUTHOR_EMAIL "" #define ET61X251_MODULE_LICENSE "GPL" @@ -63,68 +63,68 @@ MODULE_LICENSE(ET61X251_MODULE_LICENSE); static short video_nr[] = {[0 ... ET61X251_MAX_DEVICES-1] = -1}; module_param_array(video_nr, short, NULL, 0444); MODULE_PARM_DESC(video_nr, - "\n<-1|n[,...]> Specify V4L2 minor mode number." - "\n -1 = use next available (default)" - "\n n = use minor number n (integer >= 0)" - "\nYou can specify up to " - __MODULE_STRING(ET61X251_MAX_DEVICES) " cameras this way." - "\nFor example:" - "\nvideo_nr=-1,2,-1 would assign minor number 2 to" - "\nthe second registered camera and use auto for the first" - "\none and for every other camera." - "\n"); + "\n<-1|n[,...]> Specify V4L2 minor mode number." + "\n -1 = use next available (default)" + "\n n = use minor number n (integer >= 0)" + "\nYou can specify up to " + __MODULE_STRING(ET61X251_MAX_DEVICES) " cameras this way." + "\nFor example:" + "\nvideo_nr=-1,2,-1 would assign minor number 2 to" + "\nthe second registered camera and use auto for the first" + "\none and for every other camera." + "\n"); static short force_munmap[] = {[0 ... ET61X251_MAX_DEVICES-1] = - ET61X251_FORCE_MUNMAP}; + ET61X251_FORCE_MUNMAP}; module_param_array(force_munmap, bool, NULL, 0444); MODULE_PARM_DESC(force_munmap, - "\n<0|1[,...]> Force the application to unmap previously" - "\nmapped buffer memory before calling any VIDIOC_S_CROP or" - "\nVIDIOC_S_FMT ioctl's. Not all the applications support" - "\nthis feature. This parameter is specific for each" - "\ndetected camera." - "\n 0 = do not force memory unmapping" - "\n 1 = force memory unmapping (save memory)" - "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." - "\n"); + "\n<0|1[,...]> Force the application to unmap previously" + "\nmapped buffer memory before calling any VIDIOC_S_CROP or" + "\nVIDIOC_S_FMT ioctl's. Not all the applications support" + "\nthis feature. This parameter is specific for each" + "\ndetected camera." + "\n 0 = do not force memory unmapping" + "\n 1 = force memory unmapping (save memory)" + "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." + "\n"); static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] = - ET61X251_FRAME_TIMEOUT}; + ET61X251_FRAME_TIMEOUT}; module_param_array(frame_timeout, uint, NULL, 0644); MODULE_PARM_DESC(frame_timeout, - "\n Timeout for a video frame in seconds." - "\nThis parameter is specific for each detected camera." - "\nDefault value is " - __MODULE_STRING(ET61X251_FRAME_TIMEOUT)"." - "\n"); + "\n Timeout for a video frame in seconds." + "\nThis parameter is specific for each detected camera." + "\nDefault value is " + __MODULE_STRING(ET61X251_FRAME_TIMEOUT)"." + "\n"); #ifdef ET61X251_DEBUG static unsigned short debug = ET61X251_DEBUG_LEVEL; module_param(debug, ushort, 0644); MODULE_PARM_DESC(debug, - "\n Debugging information level, from 0 to 3:" - "\n0 = none (use carefully)" - "\n1 = critical errors" - "\n2 = significant informations" - "\n3 = more verbose messages" - "\nLevel 3 is useful for testing only, when only " - "one device is used." - "\nDefault value is "__MODULE_STRING(ET61X251_DEBUG_LEVEL)"." - "\n"); + "\n Debugging information level, from 0 to 3:" + "\n0 = none (use carefully)" + "\n1 = critical errors" + "\n2 = significant informations" + "\n3 = more verbose messages" + "\nLevel 3 is useful for testing only, when only " + "one device is used." + "\nDefault value is "__MODULE_STRING(ET61X251_DEBUG_LEVEL)"." + "\n"); #endif /*****************************************************************************/ static u32 et61x251_request_buffers(struct et61x251_device* cam, u32 count, - enum et61x251_io_method io) + enum et61x251_io_method io) { struct v4l2_pix_format* p = &(cam->sensor.pix_format); struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); const size_t imagesize = cam->module_param.force_munmap || - io == IO_READ ? - (p->width * p->height * p->priv) / 8 : - (r->width * r->height * p->priv) / 8; + io == IO_READ ? + (p->width * p->height * p->priv) / 8 : + (r->width * r->height * p->priv) / 8; void* buff = NULL; u32 i; @@ -216,7 +216,7 @@ int et61x251_write_reg(struct et61x251_device* cam, u8 value, u16 index) *buff = value; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, index, buff, 1, ET61X251_CTRL_TIMEOUT); + 0, index, buff, 1, ET61X251_CTRL_TIMEOUT); if (res < 0) { DBG(3, "Failed to write a register (value 0x%02X, index " "0x%02X, error %d)", value, index, res); @@ -234,7 +234,7 @@ int et61x251_read_reg(struct et61x251_device* cam, u16 index) int res; res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - 0, index, buff, 1, ET61X251_CTRL_TIMEOUT); + 0, index, buff, 1, ET61X251_CTRL_TIMEOUT); if (res < 0) DBG(3, "Failed to read a register (index 0x%02X, error %d)", index, res); @@ -269,7 +269,7 @@ et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor) int et61x251_i2c_try_read(struct et61x251_device* cam, - struct et61x251_sensor* sensor, u8 address) + struct et61x251_sensor* sensor, u8 address) { struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; @@ -280,14 +280,14 @@ et61x251_i2c_try_read(struct et61x251_device* cam, data[2] = cam->sensor.rsta | 0x10; data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02); res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); + 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); if (res < 0) err += res; err += et61x251_i2c_wait(cam, sensor); res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT); + 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT); if (res < 0) err += res; @@ -302,7 +302,7 @@ et61x251_i2c_try_read(struct et61x251_device* cam, int et61x251_i2c_try_write(struct et61x251_device* cam, - struct et61x251_sensor* sensor, u8 address, u8 value) + struct et61x251_sensor* sensor, u8 address, u8 value) { struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; @@ -312,13 +312,13 @@ et61x251_i2c_try_write(struct et61x251_device* cam, data[1] = cam->sensor.i2c_slave_id; data[2] = cam->sensor.rsta | 0x12; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); + 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); if (res < 0) err += res; data[0] = value; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); + 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); if (res < 0) err += res; @@ -335,8 +335,8 @@ et61x251_i2c_try_write(struct et61x251_device* cam, int et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, - u8 data3, u8 data4, u8 data5, u8 data6, u8 data7, - u8 data8, u8 address) + u8 data3, u8 data4, u8 data5, u8 data6, u8 data7, + u8 data8, u8 address) { struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; @@ -350,7 +350,7 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, data[5] = data7; data[6] = data8; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x81, data, n-1, ET61X251_CTRL_TIMEOUT); + 0, 0x81, data, n-1, ET61X251_CTRL_TIMEOUT); if (res < 0) err += res; @@ -358,14 +358,14 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, data[1] = cam->sensor.i2c_slave_id; data[2] = cam->sensor.rsta | 0x02 | (n << 4); res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); + 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); if (res < 0) err += res; /* Start writing through the serial interface */ data[0] = data1; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); + 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); if (res < 0) err += res; @@ -432,11 +432,11 @@ static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs) if (!(*f)) (*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t, - frame); + frame); imagesize = (cam->sensor.pix_format.width * - cam->sensor.pix_format.height * - cam->sensor.pix_format.priv) / 8; + cam->sensor.pix_format.height * + cam->sensor.pix_format.priv) / 8; for (i = 0; i < urb->number_of_packets; i++) { unsigned int len, status; @@ -476,7 +476,7 @@ start_of_frame: if ((*f)->state == F_GRABBING) { if (sof && (*f)->buf.bytesused) { if (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_ET61X251) + V4L2_PIX_FMT_ET61X251) goto end_of_frame; else { DBG(3, "Not expected SOF detected " @@ -508,8 +508,8 @@ end_of_frame: list_move_tail(&(*f)->frame, &cam->outqueue); if (!list_empty(&cam->inqueue)) (*f) = list_entry(cam->inqueue.next, - struct et61x251_frame_t, - frame); + struct et61x251_frame_t, + frame); else (*f) = NULL; spin_unlock(&cam->queue_lock); @@ -521,7 +521,7 @@ end_of_frame: if (sof && cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_ET61X251) + V4L2_PIX_FMT_ET61X251) goto start_of_frame; } } @@ -544,15 +544,15 @@ static int et61x251_start_transfer(struct et61x251_device* cam) struct usb_device *udev = cam->usbdev; struct urb* urb; const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832, - 864, 896, 920, 956, 980, 1000, - 1022}; + 864, 896, 920, 956, 980, 1000, + 1022}; const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING]; s8 i, j; int err = 0; for (i = 0; i < ET61X251_URBS; i++) { cam->transfer_buffer[i] = kzalloc(ET61X251_ISO_PACKETS * psz, - GFP_KERNEL); + GFP_KERNEL); if (!cam->transfer_buffer[i]) { err = -ENOMEM; DBG(1, "Not enough memory"); @@ -653,9 +653,9 @@ static int et61x251_stream_interrupt(struct et61x251_device* cam) cam->stream = STREAM_INTERRUPT; timeout = wait_event_timeout(cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED), - ET61X251_URB_TIMEOUT); + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + ET61X251_URB_TIMEOUT); if (cam->state & DEV_DISCONNECTED) return -ENODEV; else if (cam->stream != STREAM_OFF) { @@ -699,7 +699,7 @@ static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count) /* NOTE 1: being inside one of the following methods implies that the v4l - device exists for sure (see kobjects and reference counters) + device exists for sure (see kobjects and reference counters) NOTE 2: buffers are PAGE_SIZE long */ @@ -964,13 +964,13 @@ et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len) static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, - et61x251_show_reg, et61x251_store_reg); + et61x251_show_reg, et61x251_store_reg); static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR, - et61x251_show_val, et61x251_store_val); + et61x251_show_val, et61x251_store_val); static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, - et61x251_show_i2c_reg, et61x251_store_i2c_reg); + et61x251_show_i2c_reg, et61x251_store_i2c_reg); static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, - et61x251_show_i2c_val, et61x251_store_i2c_val); + et61x251_show_i2c_val, et61x251_store_i2c_val); static void et61x251_create_sysfs(struct et61x251_device* cam) @@ -990,7 +990,7 @@ static void et61x251_create_sysfs(struct et61x251_device* cam) static int et61x251_set_pix_format(struct et61x251_device* cam, - struct v4l2_pix_format* pix) + struct v4l2_pix_format* pix) { int r, err = 0; @@ -1007,7 +1007,7 @@ et61x251_set_pix_format(struct et61x251_device* cam, static int et61x251_set_compression(struct et61x251_device* cam, - struct v4l2_jpegcompression* compression) + struct v4l2_jpegcompression* compression) { int r, err = 0; @@ -1049,9 +1049,9 @@ et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect) { struct et61x251_sensor* s = &cam->sensor; u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left + - s->active_pixel.left), + s->active_pixel.left), fmw_sy = (u16)(rect->top - s->cropcap.bounds.top + - s->active_pixel.top), + s->active_pixel.top), fmw_length = (u16)(rect->width), fmw_height = (u16)(rect->height); int err = 0; @@ -1061,8 +1061,8 @@ et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect) err += et61x251_write_reg(cam, fmw_length & 0xff, 0x6b); err += et61x251_write_reg(cam, fmw_height & 0xff, 0x6c); err += et61x251_write_reg(cam, (fmw_sx >> 8) | ((fmw_sy & 0x300) >> 6) - | ((fmw_length & 0x300) >> 4) - | ((fmw_height & 0x300) >> 2), 0x6d); + | ((fmw_length & 0x300) >> 4) + | ((fmw_height & 0x300) >> 2), 0x6d); if (err) return -EIO; @@ -1203,8 +1203,8 @@ static int et61x251_open(struct inode* inode, struct file* filp) } mutex_unlock(&cam->dev_mutex); err = wait_event_interruptible_exclusive(cam->open, - cam->state & DEV_DISCONNECTED - || !cam->users); + cam->state & DEV_DISCONNECTED + || !cam->users); if (err) { up_read(&et61x251_disconnect); return err; @@ -1277,7 +1277,7 @@ static int et61x251_release(struct inode* inode, struct file* filp) static ssize_t et61x251_read(struct file* filp, char __user * buf, - size_t count, loff_t* f_pos) + size_t count, loff_t* f_pos) { struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); struct et61x251_frame_t* f, * i; @@ -1310,7 +1310,7 @@ et61x251_read(struct file* filp, char __user * buf, if (cam->io == IO_NONE) { if (!et61x251_request_buffers(cam, cam->nreadbuffers, - IO_READ)) { + IO_READ)) { DBG(1, "read() failed, not enough memory"); mutex_unlock(&cam->fileop_mutex); return -ENOMEM; @@ -1336,12 +1336,12 @@ et61x251_read(struct file* filp, char __user * buf, return -EAGAIN; } timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); if (timeout < 0) { mutex_unlock(&cam->fileop_mutex); return timeout; @@ -1408,7 +1408,7 @@ static unsigned int et61x251_poll(struct file *filp, poll_table *wait) if (cam->io == IO_NONE) { if (!et61x251_request_buffers(cam, cam->nreadbuffers, - IO_READ)) { + IO_READ)) { DBG(1, "poll() failed, not enough memory"); goto error; } @@ -1465,7 +1465,7 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) { struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); unsigned long size = vma->vm_end - vma->vm_start, - start = vma->vm_start; + start = vma->vm_start; void *pos; u32 i; @@ -1533,13 +1533,13 @@ et61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg) .driver = "et61x251", .version = ET61X251_MODULE_VERSION_CODE, .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, + V4L2_CAP_STREAMING, }; strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, - sizeof(cap.bus_info)); + sizeof(cap.bus_info)); if (copy_to_user(arg, &cap, sizeof(cap))) return -EFAULT; @@ -1871,7 +1871,7 @@ et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg) return -EINVAL; pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251) - ? 0 : (pfmt->width * pfmt->priv) / 8; + ? 0 : (pfmt->width * pfmt->priv) / 8; pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); pfmt->field = V4L2_FIELD_NONE; memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); @@ -1885,7 +1885,7 @@ et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg) static int et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, - void __user * arg) + void __user * arg) { struct et61x251_sensor* s = &cam->sensor; struct v4l2_format format; @@ -1947,7 +1947,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, pix->priv = pfmt->priv; /* bpp */ pix->colorspace = pfmt->colorspace; pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251) - ? 0 : (pix->width * pix->priv) / 8; + ? 0 : (pix->width * pix->priv) / 8; pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); pix->field = V4L2_FIELD_NONE; @@ -2020,7 +2020,7 @@ static int et61x251_vidioc_g_jpegcomp(struct et61x251_device* cam, void __user * arg) { if (copy_to_user(arg, &cam->compression, - sizeof(cam->compression))) + sizeof(cam->compression))) return -EFAULT; return 0; @@ -2169,7 +2169,7 @@ et61x251_vidioc_qbuf(struct et61x251_device* cam, void __user * arg) static int et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp, - void __user * arg) + void __user * arg) { struct v4l2_buffer b; struct et61x251_frame_t *f; @@ -2188,12 +2188,12 @@ et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp, if (filp->f_flags & O_NONBLOCK) return -EAGAIN; timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); if (timeout < 0) return timeout; if (cam->state & DEV_DISCONNECTED) @@ -2317,7 +2317,7 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg) static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) + unsigned int cmd, void __user * arg) { struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); @@ -2411,7 +2411,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, static int et61x251_ioctl(struct inode* inode, struct file* filp, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); int err = 0; @@ -2518,7 +2518,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) mutex_lock(&cam->dev_mutex); err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); + video_nr[dev_nr]); if (err) { DBG(1, "V4L2 device registration failed"); if (err == -ENFILE && video_nr[dev_nr] == -1) diff --git a/drivers/media/video/et61x251/et61x251_sensor.h b/drivers/media/video/et61x251/et61x251_sensor.h index 56841ae8a207..65edd08dc386 100644 --- a/drivers/media/video/et61x251/et61x251_sensor.h +++ b/drivers/media/video/et61x251/et61x251_sensor.h @@ -47,7 +47,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id); extern void et61x251_attach_sensor(struct et61x251_device* cam, - struct et61x251_sensor* sensor); + struct et61x251_sensor* sensor); /*****************************************************************************/ @@ -56,13 +56,13 @@ extern int et61x251_read_reg(struct et61x251_device*, u16 index); extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value); extern int et61x251_i2c_read(struct et61x251_device*, u8 address); extern int et61x251_i2c_try_write(struct et61x251_device*, - struct et61x251_sensor*, u8 address, - u8 value); + struct et61x251_sensor*, u8 address, + u8 value); extern int et61x251_i2c_try_read(struct et61x251_device*, - struct et61x251_sensor*, u8 address); + struct et61x251_sensor*, u8 address); extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1, - u8 data2, u8 data3, u8 data4, u8 data5, - u8 data6, u8 data7, u8 data8, u8 address); + u8 data2, u8 data3, u8 data4, u8 data5, + u8 data6, u8 data7, u8 data8, u8 address); /*****************************************************************************/ @@ -100,13 +100,13 @@ struct et61x251_sensor { int (*init)(struct et61x251_device* cam); int (*get_ctrl)(struct et61x251_device* cam, - struct v4l2_control* ctrl); + struct v4l2_control* ctrl); int (*set_ctrl)(struct et61x251_device* cam, - const struct v4l2_control* ctrl); + const struct v4l2_control* ctrl); int (*set_crop)(struct et61x251_device* cam, - const struct v4l2_rect* rect); + const struct v4l2_rect* rect); int (*set_pix_format)(struct et61x251_device* cam, - const struct v4l2_pix_format* pix); + const struct v4l2_pix_format* pix); /* Private */ struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS]; diff --git a/drivers/media/video/et61x251/et61x251_tas5130d1b.c b/drivers/media/video/et61x251/et61x251_tas5130d1b.c index 3998d76a307a..a7d65b82b2fb 100644 --- a/drivers/media/video/et61x251/et61x251_tas5130d1b.c +++ b/drivers/media/video/et61x251/et61x251_tas5130d1b.c @@ -46,20 +46,20 @@ static int tas5130d1b_init(struct et61x251_device* cam) static int tas5130d1b_set_ctrl(struct et61x251_device* cam, - const struct v4l2_control* ctrl) + const struct v4l2_control* ctrl) { int err = 0; switch (ctrl->id) { case V4L2_CID_GAIN: err += et61x251_i2c_raw_write(cam, 2, 0x20, - 0xf6-ctrl->value, 0, 0, 0, - 0, 0, 0, 0); + 0xf6-ctrl->value, 0, 0, 0, + 0, 0, 0, 0); break; case V4L2_CID_EXPOSURE: err += et61x251_i2c_raw_write(cam, 2, 0x40, - 0x47-ctrl->value, 0, 0, 0, - 0, 0, 0, 0); + 0x47-ctrl->value, 0, 0, 0, + 0, 0, 0, 0); break; default: return -EINVAL; diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index da44579d6f29..fdc8e3f13937 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -15,7 +15,7 @@ * * Based on the Linux CPiA driver written by Peter Pregler, * Scott J. Bertin and Johannes Erdfelt. - * + * * Please see the file: Documentation/usb/ov511.txt * and the website at: http://alpha.dyndns.org/ov511 * for more info. @@ -433,7 +433,7 @@ reg_w_mask(struct usb_ov511 *ov, return (reg_w(ov, reg, newval)); } -/* +/* * Writes multiple (n) byte value to a single register. Only valid with certain * registers (0x30 and 0xc4 - 0xce). */ @@ -629,7 +629,7 @@ ov511_i2c_write_internal(struct usb_ov511 *ov, /* Retry until idle */ do rc = reg_r(ov, R511_I2C_CTL); - while (rc > 0 && ((rc&1) == 0)); + while (rc > 0 && ((rc&1) == 0)); if (rc < 0) break; @@ -1752,7 +1752,7 @@ sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p) ov->whiteness = p->whiteness; /* Don't return error if a setting is unsupported, or rest of settings - * will not be performed */ + * will not be performed */ rc = sensor_set_contrast(ov, p->contrast); if (FATAL_ERROR(rc)) @@ -1781,7 +1781,7 @@ sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p) PDEBUG(4, "sensor_get_picture"); /* Don't return error if a setting is unsupported, or rest of settings - * will not be performed */ + * will not be performed */ rc = sensor_get_contrast(ov, &(p->contrast)); if (FATAL_ERROR(rc)) @@ -2251,7 +2251,7 @@ mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height, /******** Clock programming ********/ - /* The OV6620 needs special handling. This prevents the + /* The OV6620 needs special handling. This prevents the * severe banding that normally occurs */ if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) { @@ -2326,7 +2326,7 @@ set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode, int sub_flag) { int ret; - int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; + int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; int hoffset, voffset, hwscale = 0, vwscale = 0; /* The different sensor ICs handle setting up of window differently. @@ -2575,7 +2575,7 @@ ov518_mode_init_regs(struct usb_ov511 *ov, /* OV518 needs U and V swapped */ i2c_w_mask(ov, 0x15, 0x00, 0x01); - if (mode == VIDEO_PALETTE_GREY) { + if (mode == VIDEO_PALETTE_GREY) { /* Set 16-bit input format (UV data are ignored) */ reg_w_mask(ov, 0x20, 0x00, 0x08); @@ -2894,7 +2894,7 @@ make_8x8(unsigned char *pIn, unsigned char *pOut, int w) * ... ... ... * 56 57 ... 63 120 121 ... 127 248 249 ... 255 * - */ + */ static void yuv400raw_to_yuv400p(struct ov511_frame *frame, unsigned char *pIn0, unsigned char *pOut0) @@ -2923,7 +2923,7 @@ yuv400raw_to_yuv400p(struct ov511_frame *frame, * * 0 1 ... 7 * 8 9 ... 15 - * ... + * ... * 56 57 ... 63 * * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block). @@ -3034,7 +3034,7 @@ decompress(struct usb_ov511 *ov, struct ov511_frame *frame, */ static void deinterlace(struct ov511_frame *frame, int rawformat, - unsigned char *pIn0, unsigned char *pOut0) + unsigned char *pIn0, unsigned char *pOut0) { const int fieldheight = frame->rawheight / 2; const int fieldpix = fieldheight * frame->rawwidth; @@ -3112,7 +3112,7 @@ ov51x_postprocess_grey(struct usb_ov511 *ov, struct ov511_frame *frame) frame->tempdata); deinterlace(frame, RAWFMT_YUV400, frame->tempdata, - frame->data); + frame->data); } else { if (frame->compressed) decompress(ov, frame, frame->rawdata, @@ -3136,7 +3136,7 @@ ov51x_postprocess_yuv420(struct usb_ov511 *ov, struct ov511_frame *frame) frame->tempdata); deinterlace(frame, RAWFMT_YUV420, frame->tempdata, - frame->data); + frame->data); } else { if (frame->compressed) decompress(ov, frame, frame->rawdata, frame->data); @@ -3226,7 +3226,7 @@ ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n) frame->rawwidth = ((int)(in[9]) + 1) * 8; frame->rawheight = ((int)(in[10]) + 1) * 8; - PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d", + PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d", ov->curframe, pnum, frame->rawwidth, frame->rawheight, frame->bytes_recvd); @@ -3527,10 +3527,10 @@ ov51x_isoc_irq(struct urb *urb, struct pt_regs *regs) return; } - if (urb->status == -ENOENT || urb->status == -ECONNRESET) { - PDEBUG(4, "URB unlinked"); - return; - } + if (urb->status == -ENOENT || urb->status == -ECONNRESET) { + PDEBUG(4, "URB unlinked"); + return; + } if (urb->status != -EINPROGRESS && urb->status != 0) { err("ERROR: urb->status=%d: %s", urb->status, @@ -4627,8 +4627,8 @@ ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma) PDEBUG(4, "mmap: %ld (%lX) bytes", size, size); if (size > (((OV511_NUMFRAMES - * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight) - + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))) + * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight) + + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))) return -EINVAL; if (mutex_lock_interruptible(&ov->lock)) @@ -5062,7 +5062,7 @@ ov6xx0_configure(struct usb_ov511 *ov) } /* This initializes the KS0127 and KS0127B video decoders. */ -static int +static int ks0127_configure(struct usb_ov511 *ov) { int rc; @@ -5193,7 +5193,7 @@ saa7111a_configure(struct usb_ov511 *ov) return -1; /* Detect version of decoder. This must be done after writing the - * initial regs or the decoder will lock up. */ + * initial regs or the decoder will lock up. */ rc = i2c_r(ov, 0x00); if (rc < 0) { @@ -5216,13 +5216,13 @@ saa7111a_configure(struct usb_ov511 *ov) } /* This initializes the OV511/OV511+ and the sensor */ -static int +static int ov511_configure(struct usb_ov511 *ov) { static struct ov511_regvals aRegvalsInit511[] = { { OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, - { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, - { OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, + { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, { OV511_REG_BUS, R51x_SYS_RESET, 0x3f }, { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, @@ -5269,7 +5269,7 @@ ov511_configure(struct usb_ov511 *ov) err("Please notify " EMAIL " of the name,"); err("manufacturer, model, and this number of your camera."); err("Also include the output of the detection process."); - } + } if (ov->customid == 70) /* USB Life TV (PAL/SECAM) */ ov->pal = 1; @@ -5336,17 +5336,17 @@ ov511_configure(struct usb_ov511 *ov) if (i2c_w(ov, 0x10, 0x00) < 0) { err("Can't determine sensor slave IDs"); - goto error; + goto error; } else { if (ks0127_configure(ov) < 0) { err("Failed to configure KS0127"); - goto error; + goto error; } } } else { if (saa7111a_configure(ov) < 0) { err("Failed to configure SAA7111A"); - goto error; + goto error; } } } else { @@ -5356,13 +5356,13 @@ ov511_configure(struct usb_ov511 *ov) } else { if (ov6xx0_configure(ov) < 0) { err("Failed to configure OV6xx0"); - goto error; + goto error; } } } else { if (ov7xx0_configure(ov) < 0) { err("Failed to configure OV7xx0"); - goto error; + goto error; } } @@ -5381,12 +5381,12 @@ ov518_configure(struct usb_ov511 *ov) /* For 518 and 518+ */ static struct ov511_regvals aRegvalsInit518[] = { { OV511_REG_BUS, R51x_SYS_RESET, 0x40 }, - { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, - { OV511_REG_BUS, R51x_SYS_RESET, 0x3e }, + { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, + { OV511_REG_BUS, R51x_SYS_RESET, 0x3e }, { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, { OV511_REG_BUS, R51x_SYS_RESET, 0x00 }, { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, - { OV511_REG_BUS, 0x46, 0x00 }, + { OV511_REG_BUS, 0x46, 0x00 }, { OV511_REG_BUS, 0x5d, 0x03 }, { OV511_DONE_BUS, 0x0, 0x00}, }; @@ -5517,7 +5517,7 @@ ov518_configure(struct usb_ov511 *ov) if (init_ov_sensor(ov) < 0) { err("Can't determine sensor slave IDs"); - goto error; + goto error; } else { err("Detected unsupported OV8xx0 sensor"); goto error; @@ -5525,13 +5525,13 @@ ov518_configure(struct usb_ov511 *ov) } else { if (ov6xx0_configure(ov) < 0) { err("Failed to configure OV6xx0"); - goto error; + goto error; } } } else { if (ov7xx0_configure(ov) < 0) { err("Failed to configure OV7xx0"); - goto error; + goto error; } } @@ -5564,28 +5564,28 @@ static ssize_t show_custom_id(struct class_device *cd, char *buf) { struct usb_ov511 *ov = cd_to_ov(cd); return sprintf(buf, "%d\n", ov->customid); -} +} static CLASS_DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL); static ssize_t show_model(struct class_device *cd, char *buf) { struct usb_ov511 *ov = cd_to_ov(cd); return sprintf(buf, "%s\n", ov->desc); -} +} static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); static ssize_t show_bridge(struct class_device *cd, char *buf) { struct usb_ov511 *ov = cd_to_ov(cd); return sprintf(buf, "%s\n", symbolic(brglist, ov->bridge)); -} +} static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL); static ssize_t show_sensor(struct class_device *cd, char *buf) { struct usb_ov511 *ov = cd_to_ov(cd); return sprintf(buf, "%s\n", symbolic(senlist, ov->sensor)); -} +} static CLASS_DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL); static ssize_t show_brightness(struct class_device *cd, char *buf) @@ -5597,7 +5597,7 @@ static ssize_t show_brightness(struct class_device *cd, char *buf) return -ENODEV; sensor_get_brightness(ov, &x); return sprintf(buf, "%d\n", x >> 8); -} +} static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); static ssize_t show_saturation(struct class_device *cd, char *buf) @@ -5609,7 +5609,7 @@ static ssize_t show_saturation(struct class_device *cd, char *buf) return -ENODEV; sensor_get_saturation(ov, &x); return sprintf(buf, "%d\n", x >> 8); -} +} static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); static ssize_t show_contrast(struct class_device *cd, char *buf) @@ -5621,7 +5621,7 @@ static ssize_t show_contrast(struct class_device *cd, char *buf) return -ENODEV; sensor_get_contrast(ov, &x); return sprintf(buf, "%d\n", x >> 8); -} +} static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); static ssize_t show_hue(struct class_device *cd, char *buf) @@ -5633,7 +5633,7 @@ static ssize_t show_hue(struct class_device *cd, char *buf) return -ENODEV; sensor_get_hue(ov, &x); return sprintf(buf, "%d\n", x >> 8); -} +} static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); static ssize_t show_exposure(struct class_device *cd, char *buf) @@ -5645,7 +5645,7 @@ static ssize_t show_exposure(struct class_device *cd, char *buf) return -ENODEV; sensor_get_exposure(ov, &exp); return sprintf(buf, "%d\n", exp >> 8); -} +} static CLASS_DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL); static void ov_create_sysfs(struct video_device *vdev) diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h index bce9b3633889..12b3d51e1c34 100644 --- a/drivers/media/video/ov511.h +++ b/drivers/media/video/ov511.h @@ -130,7 +130,7 @@ #define R511_COMP_QVY 0x76 #define R511_COMP_QVUV 0x77 #define R511_COMP_EN 0x78 -#define R511_COMP_LUT_EN 0x79 +#define R511_COMP_LUT_EN 0x79 #define R511_COMP_LUT_BEGIN 0x80 /* --------------------------------- */ @@ -459,14 +459,14 @@ struct usb_ov511 { int subh; /* Pix Array subcapture height */ int curframe; /* Current receiving sbuf */ - struct ov511_frame frame[OV511_NUMFRAMES]; + struct ov511_frame frame[OV511_NUMFRAMES]; struct ov511_sbuf sbuf[OV511_NUMSBUF]; wait_queue_head_t wq; /* Processes waiting */ int snap_enabled; /* Snapshot mode enabled */ - + int bridge; /* Type of bridge (BRG_*) */ int bclass; /* Class of bridge (BCL_*) */ int sensor; /* Type of image sensor chip (SEN_*) */ @@ -512,7 +512,7 @@ struct symbolic_list { /* Returns the name of the matching element in the symbolic_list array. The * end of the list must be marked with an element that has a NULL name. */ -static inline char * +static inline char * symbolic(struct symbolic_list list[], int num) { int i; diff --git a/drivers/media/video/ovcamchip/Makefile b/drivers/media/video/ovcamchip/Makefile index bca41ad93de8..cba4cdf20f49 100644 --- a/drivers/media/video/ovcamchip/Makefile +++ b/drivers/media/video/ovcamchip/Makefile @@ -1,4 +1,4 @@ ovcamchip-objs := ovcamchip_core.o ov6x20.o ov6x30.o ov7x10.o ov7x20.o \ - ov76be.o + ov76be.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip.o diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c index e76b53d5909c..3fe9fa04cd84 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/drivers/media/video/ovcamchip/ovcamchip_core.c @@ -266,17 +266,17 @@ static int ovcamchip_detect(struct i2c_client *c) PDEBUG(3, "Testing for 0V6xx0"); c->addr = OV6xx0_SID; if (init_camchip(c) < 0) { - return -ENODEV; + return -ENODEV; } else { if (ov6xx0_detect(c) < 0) { PERROR("Failed to init OV6xx0"); - return -EIO; + return -EIO; } } } else { if (ov7xx0_detect(c) < 0) { PERROR("Failed to init OV7xx0"); - return -EIO; + return -EIO; } } diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h index 575e612a5546..1231335a9f4a 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_priv.h +++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h @@ -82,6 +82,6 @@ extern int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals); extern int ov_write_mask(struct i2c_client *c, unsigned char reg, - unsigned char value, unsigned char mask); + unsigned char value, unsigned char mask); #endif diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index 15fd85acabda..522e9ddeb089 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -1,4 +1,4 @@ -/* +/* planb - PlanB frame grabber driver PlanB is used in the 7x00/8x00 series of PowerMacintosh @@ -584,7 +584,7 @@ finish: wake_up_interruptible(&pb->suspendq); } -static void add_clip(struct planb *pb, struct video_clip *clip) +static void add_clip(struct planb *pb, struct video_clip *clip) { volatile unsigned char *base; int xc = clip->x, yc = clip->y; @@ -758,7 +758,7 @@ static void cmd_buff(struct planb *pb) PLANB_SET(CH_SYNC)); tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), PLANB_SET(DMA_ABORT)); - + /* odd field data: */ jump = virt_to_bus(c1 + nlines / 2); for (i=1; i < nlines; i += stepsize, c1++) @@ -1247,7 +1247,7 @@ static volatile struct dbdma_cmd *setup_grab_cmd(int fr, struct planb *pb) tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++; tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), PLANB_SET(DMA_ABORT)); - + /* odd field data: */ jump_addr = c1 + TAB_FACTOR * nlines / 2; jump = virt_to_bus(jump_addr); @@ -1383,7 +1383,7 @@ static int planb_open(struct video_device *dev, int mode) pb->user++; DEBUG("PlanB: device opened\n"); - return 0; + return 0; } static void planb_close(struct video_device *dev) @@ -1424,9 +1424,9 @@ static long planb_write(struct video_device *v, const char *buf, static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg) { struct planb *pb=(struct planb *)dev; - + switch (cmd) - { + { case VIDIOCGCAP: { struct video_capability b; @@ -1440,26 +1440,26 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg) b.channels = 2; /* composite & svhs */ b.audios = 0; b.maxwidth = PLANB_MAXPIXELS; - b.maxheight = PLANB_MAXLINES; - b.minwidth = 32; /* wild guess */ - b.minheight = 32; - if (copy_to_user(arg,&b,sizeof(b))) - return -EFAULT; + b.maxheight = PLANB_MAXLINES; + b.minwidth = 32; /* wild guess */ + b.minheight = 32; + if (copy_to_user(arg,&b,sizeof(b))) + return -EFAULT; return 0; } case VIDIOCSFBUF: { - struct video_buffer v; + struct video_buffer v; unsigned short bpp; unsigned int fmt; DEBUG("PlanB: IOCTL VIDIOCSFBUF\n"); - if (!capable(CAP_SYS_ADMIN) + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - return -EPERM; - if (copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; + return -EPERM; + if (copy_from_user(&v, arg,sizeof(v))) + return -EFAULT; planb_lock(pb); switch(v.depth) { case 8: @@ -1478,7 +1478,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg) break; default: planb_unlock(pb); - return -EINVAL; + return -EINVAL; } if (bpp * v.width > v.bytesperline) { planb_unlock(pb); @@ -1493,7 +1493,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg) pb->win.bpl = pb->win.bpp * pb->win.swidth; pb->win.pad = v.bytesperline - pb->win.bpl; - DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d," + DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d," " bpl %d (+ %d)\n", v.base, v.width,v.height, pb->win.bpp, pb->win.bpl, pb->win.pad); @@ -1504,11 +1504,11 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg) resume_overlay(pb); } planb_unlock(pb); - return 0; + return 0; } case VIDIOCGFBUF: { - struct video_buffer v; + struct video_buffer v; DEBUG("PlanB: IOCTL VIDIOCGFBUF\n"); @@ -1518,15 +1518,15 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg) v.depth = pb->win.depth; v.bytesperline = pb->win.bpl + pb->win.pad; if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; + return -EFAULT; return 0; } case VIDIOCCAPTURE: { int i; - if(copy_from_user(&i, arg, sizeof(i))) - return -EFAULT; + if(copy_from_user(&i, arg, sizeof(i))) + return -EFAULT; if(i==0) { DEBUG("PlanB: IOCTL VIDIOCCAPTURE Stop\n"); @@ -1695,7 +1695,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg) struct video_window vw; struct video_clip clip; int i; - + DEBUG("PlanB: IOCTL VIDIOCSWIN\n"); if(copy_from_user(&vw,arg,sizeof(vw))) @@ -1749,7 +1749,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -EFAULT; return 0; } - case VIDIOCSYNC: { + case VIDIOCSYNC: { int i; IDEBUG("PlanB: IOCTL VIDIOCSYNC\n"); @@ -1759,42 +1759,42 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg) IDEBUG("PlanB: sync to frame %d\n", i); - if(i > (MAX_GBUFFERS - 1) || i < 0) - return -EINVAL; + if(i > (MAX_GBUFFERS - 1) || i < 0) + return -EINVAL; chk_grab: - switch (pb->frame_stat[i]) { - case GBUFFER_UNUSED: - return -EINVAL; + switch (pb->frame_stat[i]) { + case GBUFFER_UNUSED: + return -EINVAL; case GBUFFER_GRABBING: IDEBUG("PlanB: waiting for grab" " done (%d)\n", i); - interruptible_sleep_on(&pb->capq); + interruptible_sleep_on(&pb->capq); if(signal_pending(current)) return -EINTR; goto chk_grab; - case GBUFFER_DONE: - pb->frame_stat[i] = GBUFFER_UNUSED; - break; - } - return 0; + case GBUFFER_DONE: + pb->frame_stat[i] = GBUFFER_UNUSED; + break; + } + return 0; } - case VIDIOCMCAPTURE: + case VIDIOCMCAPTURE: { - struct video_mmap vm; + struct video_mmap vm; volatile unsigned int status; IDEBUG("PlanB: IOCTL VIDIOCMCAPTURE\n"); if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm))) return -EFAULT; - status = pb->frame_stat[vm.frame]; - if (status != GBUFFER_UNUSED) - return -EBUSY; + status = pb->frame_stat[vm.frame]; + if (status != GBUFFER_UNUSED) + return -EBUSY; - return vgrab(pb, &vm); + return vgrab(pb, &vm); } - + case VIDIOCGMBUF: { int i; @@ -1811,7 +1811,7 @@ chk_grab: return -EFAULT; return 0; } - + case PLANBIOCGSAAREGS: { struct planb_saa_regs preg; @@ -1828,7 +1828,7 @@ chk_grab: return -EFAULT; return 0; } - + case PLANBIOCSSAAREGS: { struct planb_saa_regs preg; @@ -1842,7 +1842,7 @@ chk_grab: saa_set (preg.addr, preg.val, pb); return 0; } - + case PLANBIOCGSTAT: { struct planb_stat_regs pstat; @@ -1859,7 +1859,7 @@ chk_grab: return -EFAULT; return 0; } - + case PLANBIOCSMODE: { int v; @@ -1985,10 +1985,10 @@ static int planb_mmap(struct vm_area_struct *vma, struct video_device *dev, cons { int i; struct planb *pb = (struct planb *)dev; - unsigned long start = (unsigned long)adr; + unsigned long start = (unsigned long)adr; if (size > MAX_GBUFFERS * PLANB_MAX_FBUF) - return -EINVAL; + return -EINVAL; if (!pb->rawbuf) { int err; if((err=grabbuf_alloc(pb))) @@ -2091,10 +2091,10 @@ static int init_planb(struct planb *pb) /* clear interrupt mask */ pb->intr_mask = PLANB_CLR_IRQ; - result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb); - if (result < 0) { - if (result==-EINVAL) - printk(KERN_ERR "PlanB: Bad irq number (%d) " + result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb); + if (result < 0) { + if (result==-EINVAL) + printk(KERN_ERR "PlanB: Bad irq number (%d) " "or handler\n", (int)pb->irq); else if (result==-EBUSY) printk(KERN_ERR "PlanB: I don't know why, " @@ -2102,7 +2102,7 @@ static int init_planb(struct planb *pb) return result; } disable_irq(pb->irq); - + /* Now add the template and register the device unit. */ memcpy(&pb->video_dev,&planb_template,sizeof(planb_template)); @@ -2143,7 +2143,7 @@ static int init_planb(struct planb *pb) } /* - * Scan for a PlanB controller, request the irq and map the io memory + * Scan for a PlanB controller, request the irq and map the io memory */ static int find_planb(void) @@ -2171,9 +2171,9 @@ static int find_planb(void) pb = &planbs[0]; planb_num = 1; - if (planb_devices->n_addrs != 1) { - printk (KERN_WARNING "PlanB: expecting 1 address for planb " - "(got %d)", planb_devices->n_addrs); + if (planb_devices->n_addrs != 1) { + printk (KERN_WARNING "PlanB: expecting 1 address for planb " + "(got %d)", planb_devices->n_addrs); return 0; } @@ -2236,7 +2236,7 @@ static int find_planb(void) pb->planb_base = planb_regs; pb->planb_base_phys = (struct planb_registers *)new_base; pb->irq = irq; - + return planb_num; err_out_disable: @@ -2251,7 +2251,7 @@ static void release_planb(void) int i; struct planb *pb; - for (i=0;i - * - pms_capture: report back -EFAULT + * - pms_capture: report back -EFAULT */ #include @@ -66,14 +66,14 @@ static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ /* * I/O ports and Shared Memory */ - + static int io_port = 0x250; static int data_port = 0x251; static int mem_base = 0xC8000; static void __iomem *mem; static int video_nr = -1; - + static inline void mvv_write(u8 index, u8 value) { @@ -90,9 +90,9 @@ static int pms_i2c_stat(u8 slave) { int counter; int i; - + outb(0x28, io_port); - + counter=0; while((inb(data_port)&0x01)==0) if(counter++==256) @@ -101,9 +101,9 @@ static int pms_i2c_stat(u8 slave) while((inb(data_port)&0x01)!=0) if(counter++==256) break; - + outb(slave, io_port); - + counter=0; while((inb(data_port)&0x01)==0) if(counter++==256) @@ -112,7 +112,7 @@ static int pms_i2c_stat(u8 slave) while((inb(data_port)&0x01)!=0) if(counter++==256) break; - + for(i=0;i<12;i++) { char st=inb(data_port); @@ -122,7 +122,7 @@ static int pms_i2c_stat(u8 slave) break; } outb(0x29, io_port); - return inb(data_port); + return inb(data_port); } static int pms_i2c_write(u16 slave, u16 sub, u16 data) @@ -130,19 +130,19 @@ static int pms_i2c_write(u16 slave, u16 sub, u16 data) int skip=0; int count; int i; - + for(i=0;i255) @@ -167,9 +167,9 @@ static int pms_i2c_write(u16 slave, u16 sub, u16 data) while((inb(data_port)&1)!=0) if(count>255) break; - + count=inb(data_port); - + if(count&2) return -1; return count; @@ -189,8 +189,8 @@ static int pms_i2c_read(int slave, int sub) static void pms_i2c_andor(int slave, int sub, int and, int or) { - u8 tmp; - + u8 tmp; + tmp=pms_i2c_read(slave, sub); tmp = (tmp&and)|or; pms_i2c_write(slave, sub, tmp); @@ -199,7 +199,7 @@ static void pms_i2c_andor(int slave, int sub, int and, int or) /* * Control functions */ - + static void pms_videosource(short source) { @@ -234,8 +234,8 @@ static void pms_colour(short colour) break; } } - - + + static void pms_contrast(short contrast) { switch(decoder) @@ -269,14 +269,14 @@ static void pms_format(short format) { int target; standard = format; - + if(decoder==PHILIPS1) target=0x42; else if(decoder==PHILIPS2) target=0x8A; else return; - + switch(format) { case 0: /* Auto */ @@ -302,7 +302,7 @@ static void pms_format(short format) /* * These features of the PMS card are not currently exposes. They - * could become a private v4l ioctl for PMSCONFIG or somesuch if + * could become a private v4l ioctl for PMSCONFIG or somesuch if * people need it. We also don't yet use the PMS interrupt. */ @@ -324,7 +324,7 @@ static void pms_hstart(short start) /* * Bandpass filters */ - + static void pms_bandpass(short pass) { if(decoder==PHILIPS2) @@ -493,7 +493,7 @@ static void pms_vert(u8 deciden, u8 decinum) /* * Turn 16bit ratios into best small ratio the chipset can grok */ - + static void pms_vertdeci(unsigned short decinum, unsigned short deciden) { /* Knock it down by /5 once */ @@ -546,7 +546,7 @@ static void pms_horzdeci(short decinum, short deciden) decinum=512; deciden=640; /* 768 would be ideal */ } - + while(((decinum|deciden)&1)==0) { decinum>>=1; @@ -559,7 +559,7 @@ static void pms_horzdeci(short decinum, short deciden) } if(deciden==32) deciden--; - + mvv_write(0x24, 0x80|deciden); mvv_write(0x25, decinum); } @@ -567,14 +567,14 @@ static void pms_horzdeci(short decinum, short deciden) static void pms_resolution(short width, short height) { int fg_height; - + fg_height=height; if(fg_height>280) fg_height=280; - + mvv_write(0x18, fg_height); mvv_write(0x19, fg_height>>8); - + if(standard==1) { mvv_write(0x1A, 0xFC); @@ -598,7 +598,7 @@ static void pms_resolution(short width, short height) mvv_write(0x42, 0x00); mvv_write(0x43, 0x00); mvv_write(0x44, MVVMEMORYWIDTH); - + mvv_write(0x22, width+8); mvv_write(0x23, (width+8)>> 8); @@ -618,7 +618,7 @@ static void pms_resolution(short width, short height) /* * Set Input */ - + static void pms_vcrinput(short input) { if(decoder==PHILIPS2) @@ -643,20 +643,20 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */ /* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */ - - for (y = 0; y < dev->height; y++ ) + + for (y = 0; y < dev->height; y++ ) { writeb(0, mem); /* synchronisiert neue Zeile */ - + /* * This is in truth a fifo, be very careful as if you * forgot this odd things will occur 8) */ - + memcpy_fromio(tmp, mem, dw+32); /* discard 16 word */ cnt -= dev->height; - while (cnt <= 0) - { + while (cnt <= 0) + { /* * Don't copy too far */ @@ -666,7 +666,7 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int cnt += dev->height; if (copy_to_user(buf, tmp+32, dt)) return len ? len : -EFAULT; - buf += dt; + buf += dt; len += dt; } } @@ -683,7 +683,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, { struct video_device *dev = video_devdata(file); struct pms_device *pd=(struct pms_device *)dev; - + switch(cmd) { case VIDIOCGCAP: @@ -806,7 +806,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, ||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15))) return -EINVAL; pd->picture= *p; - + /* * Now load the card. */ @@ -815,7 +815,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, pms_brightness(p->brightness>>8); pms_hue(p->hue>>8); pms_colour(p->colour>>8); - pms_contrast(p->contrast>>8); + pms_contrast(p->contrast>>8); mutex_unlock(&pd->lock); return 0; } @@ -873,7 +873,7 @@ static ssize_t pms_read(struct file *file, char __user *buf, struct video_device *v = video_devdata(file); struct pms_device *pd=(struct pms_device *)v; int len; - + mutex_lock(&pd->lock); len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count); mutex_unlock(&pd->lock); @@ -905,13 +905,13 @@ static struct pms_device pms_device; /* * Probe for and initialise the Mediavision PMS */ - + static int init_mediavision(void) { int id; int idec, decst; int i; - + unsigned char i2c_defs[]={ 0x4C,0x30,0x00,0xE8, 0xB6,0xE2,0x00,0x00, @@ -925,7 +925,7 @@ static int init_mediavision(void) mem = ioremap(mem_base, 0x800); if (!mem) return -ENOMEM; - + if (!request_region(0x9A01, 1, "Mediavision PMS config")) { printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n"); @@ -941,18 +941,18 @@ static int init_mediavision(void) } outb(0xB8, 0x9A01); /* Unlock */ outb(io_port>>4, 0x9A01); /* Set IO port */ - - + + id=mvv_read(3); decst=pms_i2c_stat(0x43); - + if(decst!=-1) idec=2; else if(pms_i2c_stat(0xb9)!=-1) idec=3; else if(pms_i2c_stat(0x8b)!=-1) idec=1; - else + else idec=0; printk(KERN_INFO "PMS type is %d\n", idec); @@ -966,11 +966,11 @@ static int init_mediavision(void) /* * Ok we have a PMS of some sort */ - + mvv_write(0x04, mem_base>>12); /* Set the memory area */ - + /* Ok now load the defaults */ - + for(i=0;i<0x19;i++) { if(i2c_defs[i]==0xFF) @@ -978,7 +978,7 @@ static int init_mediavision(void) else pms_i2c_write(0x8A, i, i2c_defs[i]); } - + pms_i2c_write(0xB8,0x00,0x12); pms_i2c_write(0xB8,0x04,0x00); pms_i2c_write(0xB8,0x07,0x00); @@ -987,18 +987,18 @@ static int init_mediavision(void) pms_i2c_write(0xB8,0x0A,0x00); pms_i2c_write(0xB8,0x0B,0x10); pms_i2c_write(0xB8,0x10,0x03); - + mvv_write(0x01, 0x00); mvv_write(0x05, 0xA0); mvv_write(0x08, 0x25); mvv_write(0x09, 0x00); - mvv_write(0x0A, 0x20|MVVMEMORYWIDTH); - + mvv_write(0x0A, 0x20|MVVMEMORYWIDTH); + mvv_write(0x10, 0x02); mvv_write(0x1E, 0x0C); mvv_write(0x1F, 0x03); mvv_write(0x26, 0x06); - + mvv_write(0x2B, 0x00); mvv_write(0x2C, 0x20); mvv_write(0x2D, 0x00); @@ -1018,13 +1018,13 @@ static int init_mediavision(void) /* * Initialization and module stuff */ - + static int __init init_pms_cards(void) { printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n"); - + data_port = io_port +1; - + if(init_mediavision()) { printk(KERN_INFO "Board not found.\n"); diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile index 2d93a775011a..8326684f49f3 100644 --- a/drivers/media/video/pwc/Makefile +++ b/drivers/media/video/pwc/Makefile @@ -15,6 +15,6 @@ default: endif clean: - rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c + rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c rm -rf .tmp_versions diff --git a/drivers/media/video/pwc/philips.txt b/drivers/media/video/pwc/philips.txt index 04a640d723ed..11f751a6bda5 100644 --- a/drivers/media/video/pwc/philips.txt +++ b/drivers/media/video/pwc/philips.txt @@ -47,17 +47,17 @@ don't know how to set it properly in the driver. The options are: size Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or 'vga', for an image size of resp. 128x96, 160x120, 176x144, - 320x240, 352x288 and 640x480 (of course, only for those cameras that + 320x240, 352x288 and 640x480 (of course, only for those cameras that support these resolutions). fps Specifies the desired framerate. Is an integer in the range of 4-30. fbufs - This paramter specifies the number of internal buffers to use for storing - frames from the cam. This will help if the process that reads images from - the cam is a bit slow or momentarely busy. However, on slow machines it - only introduces lag, so choose carefully. The default is 3, which is + This paramter specifies the number of internal buffers to use for storing + frames from the cam. This will help if the process that reads images from + the cam is a bit slow or momentarely busy. However, on slow machines it + only introduces lag, so choose carefully. The default is 3, which is reasonable. You can set it between 2 and 5. mbufs @@ -65,9 +65,9 @@ mbufs buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends. The default is 2, which is adequate for most applications (double buffering). - + Should you experience a lot of 'Dumping frame...' messages during - grabbing with a tool that uses mmap(), you might want to increase if. + grabbing with a tool that uses mmap(), you might want to increase if. However, it doesn't really buffer images, it just gives you a bit more slack when your program is behind. But you need a multi-threaded or forked program to really take advantage of these buffers. @@ -88,15 +88,15 @@ power_save compression (only useful with the plugin) With this option you can control the compression factor that the camera - uses to squeeze the image through the USB bus. You can set the + uses to squeeze the image through the USB bus. You can set the parameter between 0 and 3: 0 = prefer uncompressed images; if the requested mode is not available - in an uncompressed format, the driver will silently switch to low - compression. + in an uncompressed format, the driver will silently switch to low + compression. 1 = low compression. 2 = medium compression. 3 = high compression. - + High compression takes less bandwidth of course, but it could also introduce some unwanted artefacts. The default is 2, medium compression. See the FAQ on the website for an overview of which modes require @@ -112,7 +112,7 @@ leds this is let the LED blink while the camera is in use. This: leds=500,500 - + will blink the LED once every second. But with: leds=0,0 @@ -123,7 +123,7 @@ leds when the camera is not used anymore. This parameter works only with the ToUCam range of cameras (720, 730, 740, - 750) and OEMs. For other cameras this command is silently ignored, and + 750) and OEMs. For other cameras this command is silently ignored, and the LED cannot be controlled. Finally: this parameters does not take effect UNTIL the first time you @@ -144,35 +144,35 @@ dev_hint format: [type[.serialnumber]:]node - + The square brackets mean that both the type and the serialnumber are optional, but a serialnumber cannot be specified without a type (which would be rather pointless). The serialnumber is separated from the type by a '.'; the node number by a ':'. - + This somewhat cryptic syntax is best explained by a few examples: dev_hint=3,5 The first detected cam gets assigned - /dev/video3, the second /dev/video5. Any - other cameras will get the first free - available slot (see below). + /dev/video3, the second /dev/video5. Any + other cameras will get the first free + available slot (see below). dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1, - and a PCVC680 /dev/video2. - - dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber - 0123 goes to /dev/video3, the same - camera model with the 4567 serial - gets /dev/video0. + and a PCVC680 /dev/video2. + + dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber + 0123 goes to /dev/video3, the same + camera model with the 4567 serial + gets /dev/video0. - dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the - next 3 Philips cams will use /dev/video4 - through /dev/video6. + dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the + next 3 Philips cams will use /dev/video4 + through /dev/video6. Some points worth knowing: - - Serialnumbers are case sensitive and must be written full, including + - Serialnumbers are case sensitive and must be written full, including leading zeroes (it's treated as a string). - - If a device node is already occupied, registration will fail and + - If a device node is already occupied, registration will fail and the webcam is not available. - You can have up to 64 video devices; be sure to make enough device nodes in /dev if you want to spread the numbers (this does not apply @@ -186,13 +186,13 @@ trace kernel log at debug level. The trace variable is a bitmask; each bit represents a certain feature. - If you want to trace something, look up the bit value(s) in the table + If you want to trace something, look up the bit value(s) in the table below, add the values together and supply that to the trace variable. Value Value Description Default (dec) (hex) 1 0x1 Module initialization; this will log messages On - while loading and unloading the module + while loading and unloading the module 2 0x2 probe() and disconnect() traces On @@ -203,7 +203,7 @@ trace 16 0x10 Memory allocation of buffers, etc. Off 32 0x20 Showing underflow, overflow and Dumping frame On - messages + messages 64 0x40 Show viewport and image sizes Off @@ -217,7 +217,7 @@ trace Example: - + # modprobe pwc size=cif fps=15 power_save=1 The fbufs, mbufs and trace parameters are global and apply to all connected diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 0398b812e0ce..4ba549bfa0e0 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c @@ -31,17 +31,17 @@ /* Changes - 2001/08/03 Alvarado Added methods for changing white balance and - red/green gains + 2001/08/03 Alvarado Added methods for changing white balance and + red/green gains */ /* Control functions for the cam; brightness, contrast, video mode, etc. */ #ifdef __KERNEL__ -#include +#include #endif #include - + #include "pwc.h" #include "pwc-ioctl.h" #include "pwc-uncompress.h" @@ -116,13 +116,13 @@ static const char *size2name[PSZ_MAX] = "SIF", "CIF", "VGA", -}; +}; /********/ -/* Entries for the Nala (645/646) camera; the Nala doesn't have compression +/* Entries for the Nala (645/646) camera; the Nala doesn't have compression preferences, so you either get compressed or non-compressed streams. - + An alternate value of 0 means this mode is not available at all. */ @@ -205,13 +205,13 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra { /* closest match of framerate */ 0, 0, 0, 0, 4, /* 0-4 */ 5, 5, 7, 7, 10, /* 5-9 */ - 10, 10, 12, 12, 15, /* 10-14 */ - 15, 15, 15, 20, 20, /* 15-19 */ - 20, 20, 20, 24, 24, /* 20-24 */ - 24, 24, 24, 24, 24, /* 25-29 */ - 24 /* 30 */ + 10, 10, 12, 12, 15, /* 10-14 */ + 15, 15, 15, 20, 20, /* 15-19 */ + 20, 20, 20, 24, 24, /* 20-24 */ + 24, 24, 24, 24, 24, /* 25-29 */ + 24 /* 30 */ }; - int frames2table[31] = + int frames2table[31] = { 0, 0, 0, 0, 0, /* 0-4 */ 1, 1, 1, 2, 2, /* 5-9 */ 3, 3, 4, 4, 4, /* 10-14 */ @@ -220,7 +220,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra 7, 7, 7, 7, 7, /* 25-29 */ 7 /* 30 */ }; - + if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25) return -EINVAL; frames = frames2frames[frames]; @@ -232,7 +232,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra if (pEntry->compressed) return -ENOENT; /* Not supported. */ - memcpy(buf, pEntry->mode, 3); + memcpy(buf, pEntry->mode, 3); ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); if (ret < 0) { Debug("Failed to send video command... %d\n", ret); @@ -257,7 +257,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra break; } } - + pdev->cmd_len = 3; memcpy(pdev->cmd_buf, buf, 3); @@ -352,13 +352,13 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr /* special case: VGA @ 5 fps and snapshot is raw bayer mode */ if (size == PSZ_VGA && frames == 5 && snapshot) { - /* Only available in case the raw palette is selected or - we have the decompressor available. This mode is - only available in compressed form + /* Only available in case the raw palette is selected or + we have the decompressor available. This mode is + only available in compressed form */ if (pdev->vpalette == VIDEO_PALETTE_RAW) { - Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette); + Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette); pChoose = &RawEntry; } else @@ -368,9 +368,9 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr } else { - /* Find a supported framerate with progressively higher compression ratios + /* Find a supported framerate with progressively higher compression ratios if the preferred ratio is not available. - Skip this step when using RAW modes. + Skip this step when using RAW modes. */ while (compression <= 3) { pChoose = &Kiara_table[size][fps][compression]; @@ -383,7 +383,7 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr return -ENOENT; /* Not supported. */ Debug("Using alternate setting %d.\n", pChoose->alternate); - + /* usb_control_msg won't take staticly allocated arrays as argument?? */ memcpy(buf, pChoose->mode, 12); if (snapshot) @@ -463,9 +463,9 @@ static void pwc_set_image_buffer_size(struct pwc_device *pdev) */ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot) { - int ret, size; + int ret, size; - Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette); + Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette); size = pwc_decode_size(pdev, width, height); if (size < 0) { Debug("Could not find suitable size.\n"); @@ -473,7 +473,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame } Debug("decode_size = %d.\n", size); - ret = -EINVAL; + ret = -EINVAL; switch(pdev->type) { case 645: case 646: @@ -485,7 +485,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame case 690: ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot); break; - + case 720: case 730: case 740: @@ -517,7 +517,7 @@ int pwc_get_brightness(struct pwc_device *pdev) char buf; int ret; - ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); + ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); if (ret < 0) return ret; return buf << 9; @@ -566,7 +566,7 @@ int pwc_get_gamma(struct pwc_device *pdev) { char buf; int ret; - + ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1); if (ret < 0) return ret; @@ -622,14 +622,14 @@ static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value) { char buf; int ret; - + if (mode) buf = 0x0; /* auto */ else buf = 0xff; /* fixed */ ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1); - + if (!mode && ret >= 0) { if (value < 0) value = 0; @@ -647,7 +647,7 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; - + ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1); if (ret < 0) return ret; @@ -658,7 +658,7 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value) return ret; if (buf > 0x3F) buf = 0x3F; - *value = (buf << 10); + *value = (buf << 10); } else { /* auto */ ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1); @@ -683,7 +683,7 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v buf[0] = 0x0; /* auto */ else buf[0] = 0xff; /* fixed */ - + ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1); if (!mode && ret >= 0) { @@ -713,7 +713,7 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2); } return ret; -} +} /* POWER */ @@ -765,22 +765,22 @@ static inline int pwc_restore_factory(struct pwc_device *pdev) * 02: fluorescent lighting * 03: manual * 04: auto - */ + */ static inline int pwc_set_awb(struct pwc_device *pdev, int mode) { char buf; int ret; - + if (mode < 0) mode = 0; - + if (mode > 4) mode = 4; - + buf = mode & 0x07; /* just the lowest three bits */ - + ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1); - + if (ret < 0) return ret; return 0; @@ -790,17 +790,17 @@ static inline int pwc_get_awb(struct pwc_device *pdev) { unsigned char buf; int ret; - + ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1); - if (ret < 0) + if (ret < 0) return ret; return buf; } static inline int pwc_set_red_gain(struct pwc_device *pdev, int value) { - unsigned char buf; + unsigned char buf; if (value < 0) value = 0; @@ -815,7 +815,7 @@ static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; - + ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); if (ret < 0) return ret; @@ -841,7 +841,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; - + ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); if (ret < 0) return ret; @@ -851,14 +851,14 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value) /* The following two functions are different, since they only read the - internal red/blue gains, which may be different from the manual + internal red/blue gains, which may be different from the manual gains set or read above. - */ + */ static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; - + ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1); if (ret < 0) return ret; @@ -870,7 +870,7 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; - + ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1); if (ret < 0) return ret; @@ -882,7 +882,7 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value) static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed) { unsigned char buf; - + /* useful range is 0x01..0x20 */ buf = speed / 0x7f0; return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); @@ -892,7 +892,7 @@ static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; - + ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); if (ret < 0) return ret; @@ -904,7 +904,7 @@ static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value) static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay) { unsigned char buf; - + /* useful range is 0x01..0x3F */ buf = (delay >> 10); return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); @@ -914,7 +914,7 @@ static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; - + ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); if (ret < 0) return ret; @@ -950,7 +950,7 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) { unsigned char buf[2]; int ret; - + if (pdev->type < 730) { *on_value = -1; *off_value = -1; @@ -969,7 +969,7 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour) { unsigned char buf; int ret; - + if (contour < 0) buf = 0xff; /* auto contour on */ else @@ -977,16 +977,16 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour) ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); if (ret < 0) return ret; - + if (contour < 0) return 0; if (contour > 0xffff) contour = 0xffff; - + buf = (contour >> 10); /* contour preset is [0..3f] */ ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); - if (ret < 0) - return ret; + if (ret < 0) + return ret; return 0; } @@ -994,7 +994,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour) { unsigned char buf; int ret; - + ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); if (ret < 0) return ret; @@ -1002,7 +1002,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour) if (buf == 0) { /* auto mode off, query current preset value */ ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); - if (ret < 0) + if (ret < 0) return ret; *contour = buf << 10; } @@ -1015,7 +1015,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour) static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight) { unsigned char buf; - + if (backlight) buf = 0xff; else @@ -1027,7 +1027,7 @@ static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight) { int ret; unsigned char buf; - + ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); if (ret < 0) return ret; @@ -1039,7 +1039,7 @@ static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight) static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker) { unsigned char buf; - + if (flicker) buf = 0xff; else @@ -1051,7 +1051,7 @@ static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker) { int ret; unsigned char buf; - + ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); if (ret < 0) return ret; @@ -1076,7 +1076,7 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) { int ret; unsigned char buf; - + ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); if (ret < 0) return ret; @@ -1087,7 +1087,7 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) static int pwc_mpt_reset(struct pwc_device *pdev, int flags) { unsigned char buf; - + buf = flags & 0x03; // only lower two bits are currently used return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1); } @@ -1095,7 +1095,7 @@ static int pwc_mpt_reset(struct pwc_device *pdev, int flags) static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) { unsigned char buf[4]; - + /* set new relative angle; angles are expressed in degrees * 100, but cam as .5 degree resolution, hence divide by 200. Also the angle must be multiplied by 64 before it's send to @@ -1114,7 +1114,7 @@ static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_sta { int ret; unsigned char buf[5]; - + ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5); if (ret < 0) return ret; @@ -1129,14 +1129,14 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) { unsigned char buf; int ret = -1, request; - + if (pdev->type < 675) request = SENSOR_TYPE_FORMATTER1; else if (pdev->type < 730) return -1; /* The Vesta series doesn't have this call */ else request = SENSOR_TYPE_FORMATTER2; - + ret = RecvControlMsg(GET_STATUS_CTL, request, 1); if (ret < 0) return ret; @@ -1163,23 +1163,23 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) ret = -EINVAL; break; } - + case VIDIOCPWCSUSER: { if (pwc_save_user(pdev)) ret = -EINVAL; break; } - + case VIDIOCPWCFACTORY: { if (pwc_restore_factory(pdev)) ret = -EINVAL; break; } - + case VIDIOCPWCSCQUAL: - { + { int *qual = arg; if (*qual < 0 || *qual > 3) @@ -1190,14 +1190,14 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) pdev->vcompression = *qual; break; } - + case VIDIOCPWCGCQUAL: { int *qual = arg; *qual = pdev->vcompression; break; } - + case VIDIOCPWCPROBE: { struct pwc_probe *probe = arg; @@ -1220,27 +1220,27 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) ret = -EINVAL; break; } - + case VIDIOCPWCGAGC: { int *agc = arg; - + if (pwc_get_agc(pdev, agc)) ret = -EINVAL; break; } - + case VIDIOCPWCSSHUTTER: { int *shutter_speed = arg; ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed); break; } - - case VIDIOCPWCSAWB: + + case VIDIOCPWCSAWB: { struct pwc_whitebalance *wb = arg; - + ret = pwc_set_awb(pdev, wb->mode); if (ret >= 0 && wb->mode == PWC_WB_MANUAL) { pwc_set_red_gain(pdev, wb->manual_red); @@ -1270,18 +1270,18 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) ret = pwc_read_red_gain(pdev, &wb->read_red); if (ret < 0) break; - ret = pwc_read_blue_gain(pdev, &wb->read_blue); - if (ret < 0) - break; + ret = pwc_read_blue_gain(pdev, &wb->read_blue); + if (ret < 0) + break; } } break; } - + case VIDIOCPWCSAWBSPEED: { struct pwc_wb_speed *wbs = arg; - + if (wbs->control_speed > 0) { ret = pwc_set_wb_speed(pdev, wbs->control_speed); } @@ -1290,11 +1290,11 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) } break; } - + case VIDIOCPWCGAWBSPEED: { struct pwc_wb_speed *wbs = arg; - + ret = pwc_get_wb_speed(pdev, &wbs->control_speed); if (ret < 0) break; @@ -1304,7 +1304,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) break; } - case VIDIOCPWCSLED: + case VIDIOCPWCSLED: { struct pwc_leds *leds = arg; ret = pwc_set_leds(pdev, leds->led_on, leds->led_off); @@ -1325,14 +1325,14 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) ret = pwc_set_contour(pdev, *contour); break; } - + case VIDIOCPWCGCONTOUR: { int *contour = arg; ret = pwc_get_contour(pdev, contour); break; } - + case VIDIOCPWCSBACKLIGHT: { int *backlight = arg; @@ -1346,7 +1346,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) ret = pwc_get_backlight(pdev, backlight); break; } - + case VIDIOCPWCSFLICKER: { int *flicker = arg; @@ -1360,14 +1360,14 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) ret = pwc_get_flicker(pdev, flicker); break; } - + case VIDIOCPWCSDYNNOISE: { int *dynnoise = arg; ret = pwc_set_dynamic_noise(pdev, *dynnoise); break; } - + case VIDIOCPWCGDYNNOISE: { int *dynnoise = arg; @@ -1381,61 +1381,61 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) size->width = pdev->image.x; size->height = pdev->image.y; break; - } - - case VIDIOCPWCMPTRESET: - { - if (pdev->features & FEATURE_MOTOR_PANTILT) - { - int *flags = arg; + } + + case VIDIOCPWCMPTRESET: + { + if (pdev->features & FEATURE_MOTOR_PANTILT) + { + int *flags = arg; ret = pwc_mpt_reset(pdev, *flags); - if (ret >= 0) - { - pdev->pan_angle = 0; - pdev->tilt_angle = 0; - } - } - else - { - ret = -ENXIO; - } - break; - } - - case VIDIOCPWCMPTGRANGE: - { - if (pdev->features & FEATURE_MOTOR_PANTILT) - { - struct pwc_mpt_range *range = arg; - *range = pdev->angle_range; - } - else - { - ret = -ENXIO; - } - break; - } - - case VIDIOCPWCMPTSANGLE: - { - int new_pan, new_tilt; - - if (pdev->features & FEATURE_MOTOR_PANTILT) - { - struct pwc_mpt_angles *angles = arg; + if (ret >= 0) + { + pdev->pan_angle = 0; + pdev->tilt_angle = 0; + } + } + else + { + ret = -ENXIO; + } + break; + } + + case VIDIOCPWCMPTGRANGE: + { + if (pdev->features & FEATURE_MOTOR_PANTILT) + { + struct pwc_mpt_range *range = arg; + *range = pdev->angle_range; + } + else + { + ret = -ENXIO; + } + break; + } + + case VIDIOCPWCMPTSANGLE: + { + int new_pan, new_tilt; + + if (pdev->features & FEATURE_MOTOR_PANTILT) + { + struct pwc_mpt_angles *angles = arg; /* The camera can only set relative angles, so do some calculations when getting an absolute angle . */ if (angles->absolute) { - new_pan = angles->pan; - new_tilt = angles->tilt; - } - else - { - new_pan = pdev->pan_angle + angles->pan; - new_tilt = pdev->tilt_angle + angles->tilt; + new_pan = angles->pan; + new_tilt = angles->tilt; + } + else + { + new_pan = pdev->pan_angle + angles->pan; + new_tilt = pdev->tilt_angle + angles->tilt; } /* check absolute ranges */ if (new_pan < pdev->angle_range.pan_min || @@ -1463,53 +1463,53 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) pdev->tilt_angle += new_tilt; } if (ret == -EPIPE) /* stall -> out of range */ - ret = -ERANGE; + ret = -ERANGE; } - } - else - { - ret = -ENXIO; - } - break; - } - - case VIDIOCPWCMPTGANGLE: - { - - if (pdev->features & FEATURE_MOTOR_PANTILT) - { - struct pwc_mpt_angles *angles = arg; - - angles->absolute = 1; - angles->pan = pdev->pan_angle; - angles->tilt = pdev->tilt_angle; - } - else - { - ret = -ENXIO; - } - break; - } - - case VIDIOCPWCMPTSTATUS: - { - if (pdev->features & FEATURE_MOTOR_PANTILT) - { - struct pwc_mpt_status *status = arg; - ret = pwc_mpt_get_status(pdev, status); - } - else - { - ret = -ENXIO; - } - break; + } + else + { + ret = -ENXIO; + } + break; + } + + case VIDIOCPWCMPTGANGLE: + { + + if (pdev->features & FEATURE_MOTOR_PANTILT) + { + struct pwc_mpt_angles *angles = arg; + + angles->absolute = 1; + angles->pan = pdev->pan_angle; + angles->tilt = pdev->tilt_angle; + } + else + { + ret = -ENXIO; + } + break; + } + + case VIDIOCPWCMPTSTATUS: + { + if (pdev->features & FEATURE_MOTOR_PANTILT) + { + struct pwc_mpt_status *status = arg; + ret = pwc_mpt_get_status(pdev, status); + } + else + { + ret = -ENXIO; + } + break; } case VIDIOCPWCGVIDCMD: { struct pwc_video_command *cmd = arg; - - cmd->type = pdev->type; + + cmd->type = pdev->type; cmd->release = pdev->release; cmd->command_len = pdev->cmd_len; memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len); @@ -1531,7 +1531,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) ret = -ENOIOCTLCMD; break; } - + if (ret > 0) return 0; return ret; diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 90eb26042817..41418294a32b 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -25,18 +25,18 @@ */ -/* +/* This code forms the interface between the USB layers and the Philips specific stuff. Some adanved stuff of the driver falls under an NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and - is thus not distributed in source form. The binary pwcx.o module + is thus not distributed in source form. The binary pwcx.o module contains the code that falls under the NDA. - - In case you're wondering: 'pwc' stands for "Philips WebCam", but + + In case you're wondering: 'pwc' stands for "Philips WebCam", but I really didn't want to type 'philips_web_cam' every time (I'm lazy as any Linux kernel hacker, but I don't like uncomprehensible abbreviations without explanation). - + Oh yes, convention: to disctinguish between all the various pointers to device-structures, I use these names for the pointer variables: udev: struct usb_device * @@ -170,14 +170,14 @@ static struct video_device pwc_template = { /* Okay, this is some magic that I worked out and the reasoning behind it... - The biggest problem with any USB device is of course: "what to do + The biggest problem with any USB device is of course: "what to do when the user unplugs the device while it is in use by an application?" We have several options: 1) Curse them with the 7 plagues when they do (requires divine intervention) 2) Tell them not to (won't work: they'll do it anyway) 3) Oops the kernel (this will have a negative effect on a user's uptime) 4) Do something sensible. - + Of course, we go for option 4. It happens that this device will be linked to two times, once from @@ -185,15 +185,15 @@ static struct video_device pwc_template = { pointers. This is done when the device is probed() and all initialization succeeded. The pwc_device struct links back to both structures. - When a device is unplugged while in use it will be removed from the - list of known USB devices; I also de-register it as a V4L device, but + When a device is unplugged while in use it will be removed from the + list of known USB devices; I also de-register it as a V4L device, but unfortunately I can't free the memory since the struct is still in use by the file descriptor. This free-ing is then deferend until the first opportunity. Crude, but it works. - + A small 'advantage' is that if a user unplugs the cam and plugs it back in, it should get assigned the same video device minor, but unfortunately - it's non-trivial to re-link the cam back to the video device... (that + it's non-trivial to re-link the cam back to the video device... (that would surely be magic! :)) */ @@ -203,14 +203,14 @@ static struct video_device pwc_template = { /* Here we want the physical address of the memory. * This is used when initializing the contents of the area. */ -static inline unsigned long kvirt_to_pa(unsigned long adr) +static inline unsigned long kvirt_to_pa(unsigned long adr) { - unsigned long kva, ret; + unsigned long kva, ret; kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); kva |= adr & (PAGE_SIZE-1); /* restore the offset */ ret = __pa(kva); - return ret; + return ret; } static void * rvmalloc(unsigned long size) @@ -219,13 +219,13 @@ static void * rvmalloc(unsigned long size) unsigned long adr; size=PAGE_ALIGN(size); - mem=vmalloc_32(size); - if (mem) + mem=vmalloc_32(size); + if (mem) { memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr=(unsigned long) mem; - while (size > 0) - { + adr=(unsigned long) mem; + while (size > 0) + { SetPageReserved(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; @@ -236,13 +236,13 @@ static void * rvmalloc(unsigned long size) static void rvfree(void * mem, unsigned long size) { - unsigned long adr; + unsigned long adr; - if (mem) + if (mem) { - adr=(unsigned long) mem; - while ((long) size > 0) - { + adr=(unsigned long) mem; + while ((long) size > 0) + { ClearPageReserved(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; @@ -263,13 +263,13 @@ static int pwc_allocate_buffers(struct pwc_device *pdev) if (pdev == NULL) return -ENXIO; - + #ifdef PWC_MAGIC if (pdev->magic != PWC_MAGIC) { Err("allocate_buffers(): magic failed.\n"); return -ENXIO; } -#endif +#endif /* Allocate Isochronous pipe buffers */ for (i = 0; i < MAX_ISO_BUFS; i++) { if (pdev->sbuf[i].data == NULL) { @@ -308,7 +308,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev) memset(kbuf, 128, PWC_FRAME_SIZE); } } - + /* Allocate decompressor table space */ kbuf = NULL; switch (pdev->type) @@ -320,7 +320,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev) case 730: case 740: case 750: -#if 0 +#if 0 Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private)); kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */ break; @@ -329,11 +329,11 @@ static int pwc_allocate_buffers(struct pwc_device *pdev) /* TODO & FIXME */ kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); break; -#endif +#endif ; } pdev->decompress_data = kbuf; - + /* Allocate image buffer; double buffer for mmap() */ kbuf = rvmalloc(default_mbufs * pdev->len_per_image); if (kbuf == NULL) { @@ -348,7 +348,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev) pdev->image_ptr[i] = NULL; kbuf = NULL; - + Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n"); return 0; } @@ -366,7 +366,7 @@ static void pwc_free_buffers(struct pwc_device *pdev) Err("free_buffers(): magic failed.\n"); return; } -#endif +#endif /* Release Iso-pipe buffers */ for (i = 0; i < MAX_ISO_BUFS; i++) @@ -403,17 +403,17 @@ static void pwc_free_buffers(struct pwc_device *pdev) rvfree(pdev->image_data, default_mbufs * pdev->len_per_image); } pdev->image_data = NULL; - + Trace(TRACE_MEMORY, "Leaving free_buffers().\n"); } -/* The frame & image buffer mess. +/* The frame & image buffer mess. Yes, this is a mess. Well, it used to be simple, but alas... In this module, 3 buffers schemes are used to get the data from the USB bus to the user program. The first scheme involves the ISO buffers (called thus since they transport ISO data from the USB controller), and not really - interesting. Suffices to say the data from this buffer is quickly + interesting. Suffices to say the data from this buffer is quickly gathered in an interrupt handler (pwc_isoc_handler) and placed into the frame buffer. @@ -443,8 +443,8 @@ static void pwc_free_buffers(struct pwc_device *pdev) and a 'full' frame list: * Initially, all frame buffers but one are on the 'empty' list; the one remaining buffer is our initial fill frame. - * If a frame is needed for filling, we try to take it from the 'empty' - list, unless that list is empty, in which case we take the buffer at + * If a frame is needed for filling, we try to take it from the 'empty' + list, unless that list is empty, in which case we take the buffer at the head of the 'full' list. * When our fill buffer has been filled, it is appended to the 'full' list. @@ -646,7 +646,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break; } Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); - /* Give up after a number of contiguous errors on the USB bus. + /* Give up after a number of contiguous errors on the USB bus. Appearantly something is wrong so we simulate an unplug event. */ if (++pdev->visoc_errors > MAX_ISOC_ERRORS) @@ -673,8 +673,8 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) pdev->visoc_errors = 0; /* vsync: 0 = don't copy data - 1 = sync-hunt - 2 = synched + 1 = sync-hunt + 2 = synched */ /* Compact data */ for (i = 0; i < urb->number_of_packets; i++) { @@ -701,18 +701,18 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) } /* ..flen > 0 */ if (flen < pdev->vlast_packet_size) { - /* Shorter packet... We probably have the end of an image-frame; + /* Shorter packet... We probably have the end of an image-frame; wake up read() process and let select()/poll() do something. Decompression is done in user time over there. */ if (pdev->vsync == 2) { - /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus - frames on the USB wire after an exposure change. This conditition is + /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus + frames on the USB wire after an exposure change. This conditition is however detected in the cam and a bit is set in the header. */ if (pdev->type == 730) { unsigned char *ptr = (unsigned char *)fbuf->data; - + if (ptr[1] == 1 && ptr[0] & 0x10) { #if PWC_DEBUG Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence); @@ -733,13 +733,13 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) Info("Image is normal.\n"); } pdev->vmirror = ptr[0] & 0x03; - /* Sometimes the trailer of the 730 is still sent as a 4 byte packet + /* Sometimes the trailer of the 730 is still sent as a 4 byte packet after a short frame; this condition is filtered out specifically. A 4 byte frame doesn't make sense anyway. - So we get either this sequence: - drop_bit set -> 4 byte frame -> short frame -> good frame + So we get either this sequence: + drop_bit set -> 4 byte frame -> short frame -> good frame Or this one: - drop_bit set -> short frame -> good frame + drop_bit set -> short frame -> good frame So we drop either 3 or 2 frames in all! */ if (fbuf->filled == 4) @@ -830,7 +830,7 @@ static int pwc_isoc_init(struct pwc_device *pdev) intf = usb_ifnum_to_if(udev, 0); if (intf) idesc = usb_altnum_to_altsetting(intf, pdev->valternate); - + if (!idesc) return -EFAULT; @@ -841,7 +841,7 @@ static int pwc_isoc_init(struct pwc_device *pdev) pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize); break; } - + if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { Err("Failed to find packet size for video endpoint in current alternate setting.\n"); return -ENFILE; /* Odd error, that should be noticeable */ @@ -875,18 +875,18 @@ static int pwc_isoc_init(struct pwc_device *pdev) return ret; } - /* init URB structure */ + /* init URB structure */ for (i = 0; i < MAX_ISO_BUFS; i++) { urb = pdev->sbuf[i].urb; urb->interval = 1; // devik urb->dev = udev; - urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint); + urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint); urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = pdev->sbuf[i].data; - urb->transfer_buffer_length = ISO_BUFFER_SIZE; - urb->complete = pwc_isoc_handler; - urb->context = pdev; + urb->transfer_buffer = pdev->sbuf[i].data; + urb->transfer_buffer_length = ISO_BUFFER_SIZE; + urb->complete = pwc_isoc_handler; + urb->context = pdev; urb->start_frame = 0; urb->number_of_packets = ISO_FRAMES_PER_DESC; for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { @@ -935,7 +935,7 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev) } /* Stop camera, but only if we are sure the camera is still there (unplug - is signalled by EPIPE) + is signalled by EPIPE) */ if (pdev->error_status && pdev->error_status != EPIPE) { Trace(TRACE_OPEN, "Setting alternate interface 0.\n"); @@ -956,12 +956,12 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f pwc_reset_buffers(pdev); /* Try to set video mode... */ start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); - if (ret) { - Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n"); + if (ret) { + Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n"); /* That failed... restore old mode (we know that worked) */ start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); if (start) { - Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n"); + Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n"); } } if (start == 0) @@ -987,18 +987,18 @@ static int pwc_video_open(struct inode *inode, struct file *file) struct pwc_device *pdev; Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev); - + pdev = (struct pwc_device *)vdev->priv; if (pdev == NULL) BUG(); if (pdev->vopen) return -EBUSY; - + down(&pdev->modlock); if (!pdev->usb_init) { Trace(TRACE_OPEN, "Doing first time initialization.\n"); pdev->usb_init = 1; - + if (pwc_trace & TRACE_OPEN) { /* Query sensor type */ @@ -1036,7 +1036,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) /* Set LED on/off time */ if (pwc_set_leds(pdev, led_on, led_off) < 0) Info("Failed to set LED on/off time.\n"); - + pwc_construct(pdev); /* set min/max sizes correct */ /* So far, so good. Allocate memory. */ @@ -1046,7 +1046,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) up(&pdev->modlock); return i; } - + /* Reset buffers & parameters */ pwc_reset_buffers(pdev); for (i = 0; i < default_mbufs; i++) @@ -1081,7 +1081,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) up(&pdev->modlock); return i; } - + i = pwc_isoc_init(pdev); if (i) { Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i); @@ -1155,13 +1155,13 @@ static int pwc_video_close(struct inode *inode, struct file *file) /* * FIXME: what about two parallel reads ???? * ANSWER: Not supported. You can't open the device more than once, - despite what the V4L1 interface says. First, I don't see - the need, second there's no mechanism of alerting the - 2nd/3rd/... process of events like changing image size. - And I don't see the point of blocking that for the - 2nd/3rd/... process. - In multi-threaded environments reading parallel from any - device is tricky anyhow. + despite what the V4L1 interface says. First, I don't see + the need, second there's no mechanism of alerting the + 2nd/3rd/... process of events like changing image size. + And I don't see the point of blocking that for the + 2nd/3rd/... process. + In multi-threaded environments reading parallel from any + device is tricky anyhow. */ static ssize_t pwc_video_read(struct file *file, char __user * buf, @@ -1171,7 +1171,7 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf, struct pwc_device *pdev; int noblock = file->f_flags & O_NONBLOCK; DECLARE_WAITQUEUE(wait, current); - int bytes_to_read; + int bytes_to_read; Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count); if (vdev == NULL) @@ -1193,22 +1193,22 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf, set_current_state(TASK_RUNNING); return -pdev->error_status ; } - if (noblock) { - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - return -EWOULDBLOCK; - } - if (signal_pending(current)) { - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - return -ERESTARTSYS; - } - schedule(); - set_current_state(TASK_INTERRUPTIBLE); + if (noblock) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -EWOULDBLOCK; + } + if (signal_pending(current)) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -ERESTARTSYS; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); } remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); - + /* Decompress and release frame */ if (pwc_handle_frame(pdev)) return -EFAULT; @@ -1218,7 +1218,7 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf, if (pdev->vpalette == VIDEO_PALETTE_RAW) bytes_to_read = pdev->frame_size; else - bytes_to_read = pdev->view.size; + bytes_to_read = pdev->view.size; /* copy bytes to user space; we allow for partial reads */ if (count + pdev->image_read_pos > bytes_to_read) @@ -1348,11 +1348,11 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file, struct video_picture *p = arg; /* * FIXME: Suppose we are mid read - ANSWER: No problem: the firmware of the camera - can handle brightness/contrast/etc - changes at _any_ time, and the palette - is used exactly once in the uncompress - routine. + ANSWER: No problem: the firmware of the camera + can handle brightness/contrast/etc + changes at _any_ time, and the palette + is used exactly once in the uncompress + routine. */ pwc_set_brightness(pdev, p->brightness); pwc_set_contrast(pdev, p->contrast); @@ -1373,21 +1373,21 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file, break; } - /* Window/size parameters */ + /* Window/size parameters */ case VIDIOCGWIN: { struct video_window *vw = arg; - + vw->x = 0; vw->y = 0; vw->width = pdev->view.x; vw->height = pdev->view.y; vw->chromakey = 0; - vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | - (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0); + vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | + (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0); break; } - + case VIDIOCSWIN: { struct video_window *vw = arg; @@ -1402,9 +1402,9 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file, ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot); if (ret) return ret; - break; + break; } - + /* We don't have overlay support (yet) */ case VIDIOCGFBUF: { @@ -1471,8 +1471,8 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file, return -EBUSY; /* buffer wasn't available. Bummer */ pdev->image_used[vm->frame] = 1; - /* Okay, we're done here. In the SYNC call we wait until a - frame comes available, then expand image into the given + /* Okay, we're done here. In the SYNC call we wait until a + frame comes available, then expand image into the given buffer. In contrast to the CPiA cam the Philips cams deliver a constant stream, almost like a grabber card. Also, @@ -1487,16 +1487,16 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file, { /* The doc says: "Whenever a buffer is used it should call VIDIOCSYNC to free this frame up and continue." - - The only odd thing about this whole procedure is + + The only odd thing about this whole procedure is that MCAPTURE flags the buffer as "in use", and - SYNC immediately unmarks it, while it isn't + SYNC immediately unmarks it, while it isn't after SYNC that you know that the buffer actually got filled! So you better not start a CAPTURE in - the same frame immediately (use double buffering). - This is not a problem for this cam, since it has - extra intermediate buffers, but a hardware - grabber card will then overwrite the buffer + the same frame immediately (use double buffering). + This is not a problem for this cam, since it has + extra intermediate buffers, but a hardware + grabber card will then overwrite the buffer you're working on. */ int *mbuf = arg; @@ -1512,10 +1512,10 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; /* Add ourselves to the frame wait-queue. - + FIXME: needs auditing for safety. QUESTION: In what respect? I think that using the - frameq is safe now. + frameq is safe now. */ add_wait_queue(&pdev->frameq, &wait); while (pdev->full_frames == NULL) { @@ -1524,21 +1524,21 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file, set_current_state(TASK_RUNNING); return -pdev->error_status; } - - if (signal_pending(current)) { - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - return -ERESTARTSYS; - } - schedule(); - set_current_state(TASK_INTERRUPTIBLE); + + if (signal_pending(current)) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -ERESTARTSYS; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); } remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); - - /* The frame is ready. Expand in the image buffer - requested by the user. I don't care if you - mmap() 5 buffers and request data in this order: + + /* The frame is ready. Expand in the image buffer + requested by the user. I don't care if you + mmap() 5 buffers and request data in this order: buffer 4 2 3 0 1 2 3 0 4 3 1 . . . Grabber hardware may not be so forgiving. */ @@ -1551,11 +1551,11 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file, return -EFAULT; break; } - + case VIDIOCGAUDIO: { struct video_audio *v = arg; - + strcpy(v->name, "Microphone"); v->audio = -1; /* unknown audio minor */ v->flags = 0; @@ -1565,19 +1565,19 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file, v->treble = 0; v->balance = 0x8000; v->step = 1; - break; + break; } - + case VIDIOCSAUDIO: { /* Dummy: nothing can be set */ break; } - + case VIDIOCGUNIT: { struct video_unit *vu = arg; - + vu->video = pdev->vdev->minor & 0x3F; vu->audio = -1; /* not known yet */ vu->vbi = -1; @@ -1589,7 +1589,7 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file, return pwc_ioctl(pdev, cmd, arg); } /* ..switch */ return 0; -} +} static int pwc_video_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -1605,10 +1605,10 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) unsigned long start = vma->vm_start; unsigned long size = vma->vm_end-vma->vm_start; unsigned long page, pos; - + Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size); pdev = vdev->priv; - + vma->vm_flags |= VM_IO; pos = (unsigned long)pdev->image_data; @@ -1646,7 +1646,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id char serial_number[30], *name; /* Check if we can handle this device */ - Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", + Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct), intf->altsetting->desc.bInterfaceNumber); @@ -1770,11 +1770,11 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id name = "Logitech QuickCam (res.)"; type_id = 730; /* Assuming CMOS */ break; - default: + default: return -ENODEV; - break; - } - } + break; + } + } else if (vendor_id == 0x055d) { /* I don't know the difference between the C10 and the C30; I suppose the difference is the sensor, but both cameras @@ -1837,7 +1837,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id return -ENODEV; break; } - + } else if (vendor_id == 0x0d81) { switch(product_id) { @@ -1856,7 +1856,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id break; } } - else + else return -ENODEV; /* Not any of the know types; but the list keeps growing. */ memset(serial_number, 0, 30); @@ -1880,9 +1880,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id if (vendor_id == 0x046D && product_id == 0x08B5) { /* Logitech QuickCam Orbit - The ranges have been determined experimentally; they may differ from cam to cam. - Also, the exact ranges left-right and up-down are different for my cam - */ + The ranges have been determined experimentally; they may differ from cam to cam. + Also, the exact ranges left-right and up-down are different for my cam + */ pdev->angle_range.pan_min = -7000; pdev->angle_range.pan_max = 7000; pdev->angle_range.tilt_min = -3000; @@ -1939,7 +1939,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id } /* occupy slot */ - if (hint < MAX_DEV_HINTS) + if (hint < MAX_DEV_HINTS) device_hint[hint].pdev = pdev; Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev); @@ -1968,13 +1968,13 @@ static void usb_pwc_disconnect(struct usb_interface *intf) Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n"); goto disconnect_out; } -#ifdef PWC_MAGIC +#ifdef PWC_MAGIC if (pdev->magic != PWC_MAGIC) { Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n"); goto disconnect_out; } #endif - + /* We got unplugged; this is signalled by an EPIPE error code */ if (pdev->vopen) { Info("Disconnected while webcam is in use!\n"); @@ -2017,8 +2017,8 @@ static int pwc_atoi(const char *s) } -/* - * Initialization code & module stuff +/* + * Initialization code & module stuff */ static char size[10]; @@ -2168,7 +2168,7 @@ static int __init usb_pwc_init(void) if (*dot != '\0') { /* There's a serial number as well */ int k; - + dot++; k = 0; while (*dot != ':' && k < 29) { @@ -2178,18 +2178,18 @@ static int __init usb_pwc_init(void) device_hint[i].serial_number[k] = '\0'; } } -#if PWC_DEBUG +#if PWC_DEBUG Debug("device_hint[%d]:\n", i); Debug(" type : %d\n", device_hint[i].type); Debug(" serial# : %s\n", device_hint[i].serial_number); Debug(" node : %d\n", device_hint[i].device_node); -#endif +#endif } else device_hint[i].type = 0; /* not filled */ } /* ..for MAX_DEV_HINTS */ - Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver); + Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver); return usb_register(&pwc_driver); } diff --git a/drivers/media/video/pwc/pwc-ioctl.h b/drivers/media/video/pwc/pwc-ioctl.h index 5f9cb08bc02e..784bc72521fa 100644 --- a/drivers/media/video/pwc/pwc-ioctl.h +++ b/drivers/media/video/pwc/pwc-ioctl.h @@ -33,10 +33,10 @@ /* Changes 2001/08/03 Alvarado Added ioctl constants to access methods for - changing white balance and red/blue gains + changing white balance and red/blue gains 2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE 2003/12/13 Nemosft Unv. Some modifications to make interfacing to - PWCX easier + PWCX easier */ /* These are private ioctl() commands, specific for the Philips webcams. @@ -45,10 +45,10 @@ The #define names are built up like follows: VIDIOC VIDeo IOCtl prefix - PWC Philps WebCam - G optional: Get - S optional: Set - ... the function + PWC Philps WebCam + G optional: Get + S optional: Set + ... the function */ @@ -94,7 +94,7 @@ struct pwc_serial { char serial[30]; /* String with serial number. Contains terminating 0 */ }; - + /* pwc_whitebalance.mode values */ #define PWC_WB_INDOOR 0 #define PWC_WB_OUTDOOR 1 @@ -102,14 +102,14 @@ struct pwc_serial #define PWC_WB_MANUAL 3 #define PWC_WB_AUTO 4 -/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). +/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). Set mode to one of the PWC_WB_* values above. - *red and *blue are the respective gains of these colour components inside + *red and *blue are the respective gains of these colour components inside the camera; range 0..65535 - When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read; + When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read; otherwise undefined. 'read_red' and 'read_blue' are read-only. -*/ +*/ struct pwc_whitebalance { int mode; @@ -117,9 +117,9 @@ struct pwc_whitebalance int read_red, read_blue; /* R/O */ }; -/* +/* 'control_speed' and 'control_delay' are used in automatic whitebalance mode, - and tell the camera how fast it should react to changes in lighting, and + and tell the camera how fast it should react to changes in lighting, and with how much delay. Valid values are 0..65535. */ struct pwc_wb_speed @@ -148,11 +148,11 @@ struct pwc_imagesize #define PWC_MPT_TILT 0x02 #define PWC_MPT_TIMEOUT 0x04 /* for status */ -/* Set angles; when absolute != 0, the angle is absolute and the +/* Set angles; when absolute != 0, the angle is absolute and the driver calculates the relative offset for you. This can only be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns absolute angles. - */ + */ struct pwc_mpt_angles { int absolute; /* write-only */ @@ -179,14 +179,14 @@ struct pwc_mpt_status /* This is used for out-of-kernel decompression. With it, you can get all the necessary information to initialize and use the decompressor routines in standalone applications. - */ + */ struct pwc_video_command { int type; /* camera type (645, 675, 730, etc.) */ int release; /* release number */ - int size; /* one of PSZ_* */ - int alternate; + int size; /* one of PSZ_* */ + int alternate; int command_len; /* length of USB video command */ unsigned char command_buf[13]; /* Actual USB video command */ int bandlength; /* >0 = compressed */ @@ -264,7 +264,7 @@ struct pwc_video_command /* Flickerless mode; = 0 off, otherwise on */ #define VIDIOCPWCSFLICKER _IOW('v', 208, int) -#define VIDIOCPWCGFLICKER _IOR('v', 208, int) +#define VIDIOCPWCGFLICKER _IOR('v', 208, int) /* Dynamic noise reduction; 0 off, 3 = high noise reduction */ #define VIDIOCPWCSDYNNOISE _IOW('v', 209, int) @@ -273,7 +273,7 @@ struct pwc_video_command /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */ #define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize) - /* Motorized pan & tilt functions */ + /* Motorized pan & tilt functions */ #define VIDIOCPWCMPTRESET _IOW('v', 211, int) #define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range) #define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles) diff --git a/drivers/media/video/pwc/pwc-kiara.c b/drivers/media/video/pwc/pwc-kiara.c index c498c68bace1..4c96037f7be5 100644 --- a/drivers/media/video/pwc/pwc-kiara.c +++ b/drivers/media/video/pwc/pwc-kiara.c @@ -48,270 +48,270 @@ const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] = { /* 5 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 10 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 15 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 20 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 25 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 30 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, }, /* QSIF */ { /* 5 fps */ { - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, + {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, + {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, + {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, + {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, }, /* 10 fps */ { - {2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}}, - {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, - {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, - {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, + {2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}}, + {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, + {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, + {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, }, /* 15 fps */ { - {3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}}, - {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}}, - {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}}, - {1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}}, + {3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}}, + {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}}, + {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}}, + {1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}}, }, /* 20 fps */ { - {4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}}, - {3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}}, - {2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}}, - {1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}}, + {4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}}, + {3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}}, + {2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}}, + {1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}}, }, /* 25 fps */ { - {5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}}, - {3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}}, - {2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}}, - {1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}}, + {5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}}, + {3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}}, + {2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}}, + {1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}}, }, /* 30 fps */ { - {8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}}, - {5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}}, - {3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}}, - {2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}}, + {8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}}, + {5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}}, + {3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}}, + {2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}}, }, }, /* QCIF */ { /* 5 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 10 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 15 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 20 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 25 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 30 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, }, /* SIF */ { /* 5 fps */ { - {4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}}, - {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}}, - {2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}}, - {1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}}, + {4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}}, + {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}}, + {2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}}, + {1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}}, }, /* 10 fps */ { - {0, }, - {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}}, - {3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}}, - {2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}}, + {0, }, + {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}}, + {3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}}, + {2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}}, }, /* 15 fps */ { - {0, }, - {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}}, - {4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}}, - {3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}}, + {0, }, + {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}}, + {4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}}, + {3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}}, }, /* 20 fps */ { - {0, }, - {9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}}, - {5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}}, - {3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}}, + {0, }, + {9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}}, + {5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}}, + {3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}}, }, /* 25 fps */ { - {0, }, - {9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}}, - {6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}}, - {4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}}, + {0, }, + {9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}}, + {6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}}, + {4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}}, }, /* 30 fps */ { - {0, }, - {9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}}, - {6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}}, - {4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}}, + {0, }, + {9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}}, + {6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}}, + {4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}}, }, }, /* CIF */ { /* 5 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 10 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 15 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 20 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 25 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 30 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, }, /* VGA */ { /* 5 fps */ { - {0, }, - {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}}, - {4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}}, - {3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}}, + {0, }, + {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}}, + {4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}}, + {3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}}, }, /* 10 fps */ { - {0, }, - {9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}}, - {6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}}, - {4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}}, + {0, }, + {9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}}, + {6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}}, + {4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}}, }, /* 15 fps */ { - {0, }, - {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}}, - {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}}, - {8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}}, + {0, }, + {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}}, + {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}}, + {8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}}, }, /* 20 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 25 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 30 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, }, }; diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c index b7a4bd3524c7..58fe79747992 100644 --- a/drivers/media/video/pwc/pwc-misc.c +++ b/drivers/media/video/pwc/pwc-misc.c @@ -1,4 +1,4 @@ -/* Linux driver for Philips webcam +/* Linux driver for Philips webcam Various miscellaneous functions and tables. (C) 1999-2003 Nemosoft Unv. (C) 2004 Luc Saillard (luc@saillard.org) @@ -44,17 +44,17 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height) int i, find; /* Make sure we don't go beyond our max size. - NB: we have different limits for RAW and normal modes. In case - you don't have the decompressor loaded or use RAW mode, - the maximum viewable size is smaller. - */ + NB: we have different limits for RAW and normal modes. In case + you don't have the decompressor loaded or use RAW mode, + the maximum viewable size is smaller. + */ if (pdev->vpalette == VIDEO_PALETTE_RAW) { if (width > pdev->abs_max.x || height > pdev->abs_max.y) { Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n"); - return -1; - } + return -1; + } } else { @@ -88,8 +88,8 @@ void pwc_construct(struct pwc_device *pdev) pdev->view_min.y = 96; pdev->view_max.x = 352; pdev->view_max.y = 288; - pdev->abs_max.x = 352; - pdev->abs_max.y = 288; + pdev->abs_max.x = 352; + pdev->abs_max.y = 288; pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF; pdev->vcinterface = 2; pdev->vendpoint = 4; @@ -105,8 +105,8 @@ void pwc_construct(struct pwc_device *pdev) pdev->view_max.x = 640; pdev->view_max.y = 480; pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA; - pdev->abs_max.x = 640; - pdev->abs_max.y = 480; + pdev->abs_max.x = 640; + pdev->abs_max.y = 480; pdev->vcinterface = 3; pdev->vendpoint = 4; pdev->frame_header_size = 0; @@ -121,8 +121,8 @@ void pwc_construct(struct pwc_device *pdev) pdev->view_max.x = 640; pdev->view_max.y = 480; pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; - pdev->abs_max.x = 640; - pdev->abs_max.y = 480; + pdev->abs_max.x = 640; + pdev->abs_max.y = 480; pdev->vcinterface = 3; pdev->vendpoint = 5; pdev->frame_header_size = TOUCAM_HEADER_SIZE; diff --git a/drivers/media/video/pwc/pwc-nala.h b/drivers/media/video/pwc/pwc-nala.h index e6c5cb69d03b..168c73ef75d8 100644 --- a/drivers/media/video/pwc/pwc-nala.h +++ b/drivers/media/video/pwc/pwc-nala.h @@ -54,7 +54,7 @@ {0}, }, /* VGA */ - { + { {0}, {0}, {0}, diff --git a/drivers/media/video/pwc/pwc-timon.c b/drivers/media/video/pwc/pwc-timon.c index dee967173d6c..175250d089cf 100644 --- a/drivers/media/video/pwc/pwc-timon.c +++ b/drivers/media/video/pwc/pwc-timon.c @@ -46,270 +46,270 @@ const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = { /* 5 fps */ { - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, + {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, + {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, + {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, + {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, }, /* 10 fps */ { - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, + {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, + {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, + {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, + {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, }, /* 15 fps */ { - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, + {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, + {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, + {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, + {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, }, /* 20 fps */ { - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, + {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, + {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, + {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, + {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, }, /* 25 fps */ { - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, + {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, + {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, + {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, + {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, }, /* 30 fps */ { - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, + {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, + {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, + {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, + {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, }, }, /* QSIF */ { /* 5 fps */ { - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, + {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, + {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, + {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, + {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, }, /* 10 fps */ { - {2, 291, 0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}}, - {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, - {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, - {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, + {2, 291, 0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}}, + {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, + {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, + {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, }, /* 15 fps */ { - {3, 437, 0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}}, - {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {1, 191, 420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, + {3, 437, 0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}}, + {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, + {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, + {1, 191, 420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, }, /* 20 fps */ { - {4, 588, 0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}}, - {3, 447, 730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, - {1, 192, 312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}}, + {4, 588, 0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}}, + {3, 447, 730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, + {2, 292, 476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, + {1, 192, 312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}}, }, /* 25 fps */ { - {5, 703, 0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}}, - {3, 447, 610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, - {1, 192, 262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}}, + {5, 703, 0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}}, + {3, 447, 610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, + {2, 292, 398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, + {1, 192, 262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}}, }, /* 30 fps */ { - {8, 873, 0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}}, - {5, 704, 774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}}, - {3, 448, 492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}}, - {2, 291, 320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}}, + {8, 873, 0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}}, + {5, 704, 774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}}, + {3, 448, 492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}}, + {2, 291, 320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}}, }, }, /* QCIF */ { /* 5 fps */ { - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, + {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, + {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, + {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, + {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, }, /* 10 fps */ { - {3, 385, 0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}}, - {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {1, 194, 532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}}, + {3, 385, 0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}}, + {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, + {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, + {1, 194, 532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}}, }, /* 15 fps */ { - {4, 577, 0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}}, - {3, 447, 818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}}, - {1, 195, 356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}}, + {4, 577, 0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}}, + {3, 447, 818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}}, + {2, 292, 534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}}, + {1, 195, 356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}}, }, /* 20 fps */ { - {6, 776, 0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}}, - {4, 591, 804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}}, - {3, 447, 608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 291, 396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}}, + {6, 776, 0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}}, + {4, 591, 804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}}, + {3, 447, 608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, + {2, 291, 396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}}, }, /* 25 fps */ { - {9, 928, 0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}}, - {5, 703, 800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}}, - {3, 447, 508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, + {9, 928, 0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}}, + {5, 703, 800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}}, + {3, 447, 508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, + {2, 292, 332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, }, /* 30 fps */ { - {0, }, - {9, 956, 876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}}, - {4, 592, 542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}}, - {2, 291, 266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}}, + {0, }, + {9, 956, 876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}}, + {4, 592, 542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}}, + {2, 291, 266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}}, }, }, /* SIF */ { /* 5 fps */ { - {4, 582, 0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}}, - {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}}, - {2, 291, 960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}}, - {1, 191, 630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}}, + {4, 582, 0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}}, + {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}}, + {2, 291, 960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}}, + {1, 191, 630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}}, }, /* 10 fps */ { - {0, }, - {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}}, - {3, 447, 736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}}, - {2, 291, 480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}}, + {0, }, + {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}}, + {3, 447, 736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}}, + {2, 291, 480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}}, }, /* 15 fps */ { - {0, }, - {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}}, - {4, 591, 650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}}, - {3, 448, 492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}}, + {0, }, + {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}}, + {4, 591, 650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}}, + {3, 448, 492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}}, }, /* 20 fps */ { - {0, }, - {9, 958, 782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}}, - {5, 703, 574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}}, - {3, 446, 364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}}, + {0, }, + {9, 958, 782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}}, + {5, 703, 574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}}, + {3, 446, 364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}}, }, /* 25 fps */ { - {0, }, - {9, 958, 654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}}, - {6, 776, 530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}}, - {4, 592, 404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}}, + {0, }, + {9, 958, 654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}}, + {6, 776, 530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}}, + {4, 592, 404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}}, }, /* 30 fps */ { - {0, }, - {9, 957, 526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}}, - {6, 775, 426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}}, - {4, 590, 324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}}, + {0, }, + {9, 957, 526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}}, + {6, 775, 426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}}, + {4, 590, 324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}}, }, }, /* CIF */ { /* 5 fps */ { - {6, 771, 0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}}, - {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}}, - {2, 291, 800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}}, - {1, 193, 528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}}, + {6, 771, 0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}}, + {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}}, + {2, 291, 800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}}, + {1, 193, 528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}}, }, /* 10 fps */ { - {0, }, - {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}}, - {4, 591, 812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}}, - {2, 291, 400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}}, + {0, }, + {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}}, + {4, 591, 812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}}, + {2, 291, 400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}}, }, /* 15 fps */ { - {0, }, - {9, 956, 876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}}, - {5, 703, 644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}}, - {3, 448, 410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}}, + {0, }, + {9, 956, 876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}}, + {5, 703, 644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}}, + {3, 448, 410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}}, }, /* 20 fps */ { - {0, }, - {9, 956, 650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}}, - {6, 776, 528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}}, - {4, 591, 402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}}, + {0, }, + {9, 956, 650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}}, + {6, 776, 528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}}, + {4, 591, 402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}}, }, /* 25 fps */ { - {0, }, - {9, 956, 544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}}, - {7, 840, 478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}}, - {5, 703, 400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}}, + {0, }, + {9, 956, 544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}}, + {7, 840, 478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}}, + {5, 703, 400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}}, }, /* 30 fps */ { - {0, }, - {9, 956, 438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}}, - {7, 838, 384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}}, - {6, 773, 354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}}, + {0, }, + {9, 956, 438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}}, + {7, 838, 384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}}, + {6, 773, 354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}}, }, }, /* VGA */ { /* 5 fps */ { - {0, }, - {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}}, - {4, 592, 976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}}, - {3, 448, 738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}}, + {0, }, + {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}}, + {4, 592, 976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}}, + {3, 448, 738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}}, }, /* 10 fps */ { - {0, }, - {9, 956, 788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}}, - {6, 776, 640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}}, - {4, 592, 488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}}, + {0, }, + {9, 956, 788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}}, + {6, 776, 640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}}, + {4, 592, 488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}}, }, /* 15 fps */ { - {0, }, - {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}}, - {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}}, - {8, 895, 492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}}, + {0, }, + {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}}, + {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}}, + {8, 895, 492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}}, }, /* 20 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 25 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, /* 30 fps */ { - {0, }, - {0, }, - {0, }, - {0, }, + {0, }, + {0, }, + {0, }, + {0, }, }, }, }; diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c index ef4204eab6c4..b37a89a163f9 100644 --- a/drivers/media/video/pwc/pwc-uncompress.c +++ b/drivers/media/video/pwc/pwc-uncompress.c @@ -109,9 +109,9 @@ int pwc_decompress(struct pwc_device *pdev) in planar format immediately. */ int flags; - - flags = PWCX_FLAG_PLANAR; - if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) + + flags = PWCX_FLAG_PLANAR; + if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) { printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n"); flags |= PWCX_FLAG_BAYER; diff --git a/drivers/media/video/pwc/pwc-uncompress.h b/drivers/media/video/pwc/pwc-uncompress.h index d3b9250e4ed3..f75e1b6cbe19 100644 --- a/drivers/media/video/pwc/pwc-uncompress.h +++ b/drivers/media/video/pwc/pwc-uncompress.h @@ -24,7 +24,7 @@ /* This file is the bridge between the kernel module and the plugin; it describes the structures and datatypes used in both modules. Any - significant change should be reflected by increasing the + significant change should be reflected by increasing the pwc_decompressor_version major number. */ #ifndef PWC_UNCOMPRESS_H diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 6dd76bb3dff1..1b0ee0ced0ed 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h @@ -123,7 +123,7 @@ struct pwc_device #endif /* Pointer to our usb_device */ struct usb_device *udev; - + int type; /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */ int release; /* release number */ int features; /* feature bits */ @@ -149,7 +149,7 @@ struct pwc_device char vsnapshot; /* snapshot mode */ char vsync; /* used by isoc handler */ char vmirror; /* for ToUCaM series */ - + int cmd_len; unsigned char cmd_buf[13]; diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index a9f3cf0b1e3c..531e9461cb66 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -71,7 +71,7 @@ #define NUM_BUFS 8 #define IF_NAME "SAA5249" -static const int disp_modes[8][3] = +static const int disp_modes[8][3] = { { 0x46, 0x03, 0x03 }, /* DISPOFF */ { 0x46, 0xcc, 0xcc }, /* DISPNORM */ @@ -150,8 +150,8 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) client=kmalloc(sizeof(*client), GFP_KERNEL); if(client==NULL) return -ENOMEM; - client_template.adapter = adap; - client_template.addr = addr; + client_template.adapter = adap; + client_template.addr = addr; memcpy(client, &client_template, sizeof(*client)); t = kzalloc(sizeof(*t), GFP_KERNEL); if(t==NULL) @@ -161,11 +161,11 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) } strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); mutex_init(&t->lock); - + /* * Now create a video4linux device */ - + vd = kmalloc(sizeof(struct video_device), GFP_KERNEL); if(vd==NULL) { @@ -175,8 +175,8 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) } i2c_set_clientdata(client, vd); memcpy(vd, &saa_template, sizeof(*vd)); - - for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) + + for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); @@ -186,9 +186,9 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) t->vdau[pgbuf].stopped = TRUE; t->is_searching[pgbuf] = FALSE; } - vd->priv=t; - - + vd->priv=t; + + /* * Register it */ @@ -208,7 +208,7 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) /* * We do most of the hard work when we become a device on the i2c. */ - + static int saa5249_probe(struct i2c_adapter *adap) { if (adap->class & I2C_CLASS_TV_ANALOG) @@ -229,7 +229,7 @@ static int saa5249_detach(struct i2c_client *client) /* new I2C driver support */ -static struct i2c_driver i2c_driver_videotext = +static struct i2c_driver i2c_driver_videotext = { .driver = { .name = IF_NAME, /* name */ @@ -249,7 +249,7 @@ static struct i2c_client client_template = { * delay may be longer. */ -static void jdelay(unsigned long delay) +static void jdelay(unsigned long delay) { sigset_t oldblocked = current->blocked; @@ -269,14 +269,14 @@ static void jdelay(unsigned long delay) /* * I2C interfaces */ - -static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data) + +static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data) { char buf[64]; - + buf[0] = reg; memcpy(buf+1, data, count); - + if(i2c_master_send(t->client, buf, count+1)==count+1) return 0; return -1; @@ -289,7 +289,7 @@ static int i2c_senddata(struct saa5249_device *t, ...) int ct=0; va_list argp; va_start(argp,t); - + while((v=va_arg(argp,int))!=-1) buf[ct++]=v; return i2c_sendbuf(t, buf[0], ct-1, buf+1); @@ -301,7 +301,7 @@ static int i2c_senddata(struct saa5249_device *t, ...) * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise */ -static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf) +static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf) { if(i2c_master_recv(t->client, buf, count)!=count) return -1; @@ -320,9 +320,9 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, struct video_device *vd = video_devdata(file); struct saa5249_device *t=vd->priv; - switch(cmd) + switch(cmd) { - case VTXIOCGETINFO: + case VTXIOCGETINFO: { vtx_info_t *info = arg; info->version_major = VTX_VER_MAJ; @@ -332,10 +332,10 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, return 0; } - case VTXIOCCLRPAGE: + case VTXIOCCLRPAGE: { vtx_pagereq_t *req = arg; - + if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) return -EINVAL; memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); @@ -343,17 +343,17 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, return 0; } - case VTXIOCCLRFOUND: + case VTXIOCCLRFOUND: { vtx_pagereq_t *req = arg; - + if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) return -EINVAL; t->vdau[req->pgbuf].clrfound = TRUE; return 0; } - case VTXIOCPAGEREQ: + case VTXIOCPAGEREQ: { vtx_pagereq_t *req = arg; if (!(req->pagemask & PGMASK_PAGE)) @@ -381,7 +381,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, return 0; } - case VTXIOCGETSTAT: + case VTXIOCGETSTAT: { vtx_pagereq_t *req = arg; u8 infobits[10]; @@ -390,7 +390,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) return -EINVAL; - if (!t->vdau[req->pgbuf].stopped) + if (!t->vdau[req->pgbuf].stopped) { if (i2c_senddata(t, 2, 0, -1) || i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) || @@ -403,7 +403,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, return -EIO; if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */ - (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) || + (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) || time_after_eq(jiffies, t->vdau[req->pgbuf].expire))) { /* check if new page arrived */ if (i2c_senddata(t, 8, 0, 0, 0, -1) || @@ -411,7 +411,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, return -EIO; t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE; memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE); - if (t->virtual_mode) + if (t->virtual_mode) { /* Packet X/24 */ if (i2c_senddata(t, 8, 0, 0x20, 0, -1) || @@ -459,9 +459,9 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, info.notfound = !!(infobits[8] & 0x10); info.pblf = !!(infobits[9] & 0x20); info.hamming = 0; - for (a = 0; a <= 7; a++) + for (a = 0; a <= 7; a++) { - if (infobits[a] & 0xf0) + if (infobits[a] & 0xf0) { info.hamming = 1; break; @@ -471,14 +471,14 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, info.notfound = 1; if(copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t))) return -EFAULT; - if (!info.hamming && !info.notfound) + if (!info.hamming && !info.notfound) { t->is_searching[req->pgbuf] = FALSE; } return 0; } - case VTXIOCGETPAGE: + case VTXIOCGETPAGE: { vtx_pagereq_t *req = arg; int start, end; @@ -488,15 +488,15 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, return -EINVAL; if(copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1)) return -EFAULT; - - /* + + /* * Always read the time directly from SAA5249 */ - - if (req->start <= 39 && req->end >= 32) + + if (req->start <= 39 && req->end >= 32) { int len; - char buf[16]; + char buf[16]; start = max(req->start, 32); end = min(req->end, 39); len=end-start+1; @@ -507,7 +507,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, return -EFAULT; } /* Insert the current header if DAU is still searching for a page */ - if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf]) + if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf]) { char buf[32]; int len; @@ -523,7 +523,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, return 0; } - case VTXIOCSTOPDAU: + case VTXIOCSTOPDAU: { vtx_pagereq_t *req = arg; @@ -534,12 +534,12 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, return 0; } - case VTXIOCPUTPAGE: - case VTXIOCSETDISP: - case VTXIOCPUTSTAT: + case VTXIOCPUTPAGE: + case VTXIOCSETDISP: + case VTXIOCPUTSTAT: return 0; - - case VTXIOCCLRCACHE: + + case VTXIOCCLRCACHE: { if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11, ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', @@ -551,7 +551,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, return 0; } - case VTXIOCSETVIRT: + case VTXIOCSETVIRT: { /* The SAA5249 has virtual-row reception turned on always */ t->virtual_mode = (int)(long)arg; @@ -612,14 +612,14 @@ static inline unsigned int vtx_fix_command(unsigned int cmd) /* * Handle the locking */ - + static int saa5249_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { struct video_device *vd = video_devdata(file); struct saa5249_device *t=vd->priv; int err; - + cmd = vtx_fix_command(cmd); mutex_lock(&t->lock); err = video_usercopy(inode,file,cmd,arg,do_saa5249_ioctl); @@ -627,7 +627,7 @@ static int saa5249_ioctl(struct inode *inode, struct file *file, return err; } -static int saa5249_open(struct inode *inode, struct file *file) +static int saa5249_open(struct inode *inode, struct file *file) { struct video_device *vd = video_devdata(file); struct saa5249_device *t=vd->priv; @@ -636,7 +636,7 @@ static int saa5249_open(struct inode *inode, struct file *file) err = video_exclusive_open(inode,file); if (err < 0) return err; - + if (t->client==NULL) { err = -ENODEV; goto fail; @@ -647,13 +647,13 @@ static int saa5249_open(struct inode *inode, struct file *file) i2c_senddata(t, 1, disp_modes[t->disp_mode][0], 0, -1) || /* Display TV-picture, no virtual rows */ i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1)) /* Set display to page 4 */ - + { err = -EIO; goto fail; } - for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) + for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); @@ -673,7 +673,7 @@ static int saa5249_open(struct inode *inode, struct file *file) -static int saa5249_release(struct inode *inode, struct file *file) +static int saa5249_release(struct inode *inode, struct file *file) { struct video_device *vd = video_devdata(file); struct saa5249_device *t=vd->priv; @@ -690,7 +690,7 @@ static int __init init_saa_5249 (void) return i2c_add_driver(&i2c_driver_videotext); } -static void __exit cleanup_saa_5249 (void) +static void __exit cleanup_saa_5249 (void) { i2c_del_driver(&i2c_driver_videotext); } diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index e18ea268384b..41d951db6ec0 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -139,7 +139,7 @@ saa7110_read (struct i2c_client *client) static int saa7110_selmux (struct i2c_client *client, - int chan) + int chan) { static const unsigned char modes[9][8] = { /* mode 0 */ @@ -457,7 +457,7 @@ static unsigned short normal_i2c[] = { }; static unsigned short ignore = I2C_CLIENT_END; - + static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = &ignore, diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index f9ba0c943adf..686fd4746205 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -1,4 +1,4 @@ -/* +/* * saa7111 - Philips SAA7111A video decoder driver version 0.0.3 * * Copyright (C) 1998 Dave Perks @@ -482,7 +482,7 @@ saa7111_command (struct i2c_client *client, static unsigned short normal_i2c[] = { I2C_SAA7111 >> 1, I2C_CLIENT_END }; static unsigned short ignore = I2C_CLIENT_END; - + static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = &ignore, diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index 4a1f841d0c77..90398ab8252e 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c @@ -1,4 +1,4 @@ -/* +/* * saa7114 - Philips SAA7114H video decoder driver version 0.0.1 * * Copyright (C) 2002 Maxim Yevtyushkin @@ -300,7 +300,7 @@ static const unsigned char init[] = { 0x55, 0xff, 0x56, 0xff, 0x57, 0xff, - 0x58, 0x40, // framing code + 0x58, 0x40, // framing code 0x59, 0x47, // horizontal offset 0x5a, 0x06, // vertical offset 0x5b, 0x83, // field offset @@ -345,7 +345,7 @@ static const unsigned char init[] = { 0x82, 0x00, 0x83, 0x00, 0x84, 0xc5, - 0x85, 0x0d, // hsync and vsync ? + 0x85, 0x0d, // hsync and vsync ? 0x86, 0x40, 0x87, 0x01, 0x88, 0x00, @@ -434,7 +434,7 @@ static const unsigned char init[] = { 0xd9, 0x04, 0xda, 0x00, // horizontal luminance phase offset 0xdb, 0x00, - 0xdc, 0x00, // horizontal chrominance scaling increment + 0xdc, 0x00, // horizontal chrominance scaling increment 0xdd, 0x02, 0xde, 0x00, // horizontal chrominance phase offset 0xdf, 0x00, @@ -754,7 +754,7 @@ saa7114_command (struct i2c_client *client, saa7114_write(client, 0x87, decoder->reg[REG_ADDR(0x87)]); saa7114_write(client, 0x88, 0xd8); // sw reset scaler - saa7114_write(client, 0x88, 0xf8); // sw reset scaler release + saa7114_write(client, 0x88, 0xf8); // sw reset scaler release saa7114_write(client, 0x80, 0x36); } @@ -813,7 +813,7 @@ static unsigned short normal_i2c[] = { I2C_SAA7114 >> 1, I2C_SAA7114A >> 1, I2C_CLIENT_END }; static unsigned short ignore = I2C_CLIENT_END; - + static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = &ignore, diff --git a/drivers/media/video/saa7121.h b/drivers/media/video/saa7121.h index 74e37d405208..66967ae37494 100644 --- a/drivers/media/video/saa7121.h +++ b/drivers/media/video/saa7121.h @@ -64,7 +64,7 @@ #define PAL_MSB_VERTICAL 0x40 /* 7c */ /* Initialization Sequence */ - + static __u8 init7121ntsc[] = { 0x26, 0x0, 0x27, 0x0, 0x28, NTSC_BURST_START, 0x29, NTSC_BURST_END, @@ -95,7 +95,7 @@ static __u8 init7121ntsc[] = { 0x78, 0x0, 0x79, 0x0, 0x7a, NTSC_FIRST_ACTIVE, 0x7b, NTSC_LAST_ACTIVE, 0x7c, NTSC_MSB_VERTICAL, 0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0 -}; +}; #define INIT7121LEN (sizeof(init7121ntsc)/2) static __u8 init7121pal[] = { @@ -128,5 +128,5 @@ static __u8 init7121pal[] = { 0x78, 0x0, 0x79, 0x0, 0x7a, PAL_FIRST_ACTIVE, 0x7b, PAL_LAST_ACTIVE, 0x7c, PAL_MSB_VERTICAL, 0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0 -}; +}; #endif diff --git a/drivers/media/video/saa7146.h b/drivers/media/video/saa7146.h index 756963f01bbd..2830b5e33aec 100644 --- a/drivers/media/video/saa7146.h +++ b/drivers/media/video/saa7146.h @@ -1,7 +1,7 @@ -/* +/* saa7146.h - definitions philips saa7146 based cards Copyright (C) 1999 Nathan Laredo (laredo@gnu.org) - + 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 @@ -27,7 +27,7 @@ #include -#ifndef O_NONCAP +#ifndef O_NONCAP #define O_NONCAP O_TRUNC #endif @@ -36,7 +36,7 @@ #ifdef __KERNEL__ -struct saa7146_window +struct saa7146_window { int x, y; ushort width, height; @@ -70,7 +70,7 @@ struct saa7146 int irqstate; /* irq routine is state driven */ int writemode; int playmode; - unsigned int nr; + unsigned int nr; unsigned long irq; /* IRQ used by SAA7146 card */ unsigned short id; unsigned char revision; diff --git a/drivers/media/video/saa7146reg.h b/drivers/media/video/saa7146reg.h index 6cc910f50a4b..80ec2c146b4c 100644 --- a/drivers/media/video/saa7146reg.h +++ b/drivers/media/video/saa7146reg.h @@ -1,7 +1,7 @@ -/* +/* saa7146.h - definitions philips saa7146 based cards Copyright (C) 1999 Nathan Laredo (laredo@gnu.org) - + 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 diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 9f99ee1303e0..9c308410856d 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -1,4 +1,4 @@ -/* +/* * saa7185 - Philips SAA7185B video encoder driver version 0.0.3 * * Copyright (C) 1998 Dave Perks @@ -377,7 +377,7 @@ saa7185_command (struct i2c_client *client, static unsigned short normal_i2c[] = { I2C_SAA7185 >> 1, I2C_CLIENT_END }; static unsigned short ignore = I2C_CLIENT_END; - + static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = &ignore, diff --git a/drivers/media/video/saa7196.h b/drivers/media/video/saa7196.h index f92f21cfbcac..cd4b6354a7b3 100644 --- a/drivers/media/video/saa7196.h +++ b/drivers/media/video/saa7196.h @@ -2,14 +2,14 @@ Definitions for the Philips SAA7196 digital video decoder, scaler, and clock generator circuit (DESCpro), as used in the PlanB video input of the Powermac 7x00/8x00 series. - + Copyright (C) 1998 Michel Lanners (mlan@cpu.lu) The register defines are shamelessly copied from the meteor driver out of NetBSD (with permission), and are copyrighted (c) 1995 Mark Tinguely and Jim Lowe (Thanks !) - + Additional debugging and coding by Takashi Oe (toe@unlinfo.unl.edu) The default values used for PlanB are my mistakes. diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index f03ea7f89596..a846ebc78cd7 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -4,7 +4,7 @@ * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) * * Still somewhat based on the Linux ov511 driver. - * + * * 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 @@ -114,16 +114,16 @@ static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req, unsigned short value, unsigned char *cp, int size) { return usb_control_msg ( - se401->dev, - set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0), - req, - (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - 0, - cp, - size, - 1000 - ); + se401->dev, + set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0), + req, + (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + 0, + cp, + size, + 1000 + ); } static int se401_set_feature(struct usb_se401 *se401, unsigned short selector, @@ -140,30 +140,30 @@ static int se401_set_feature(struct usb_se401 *se401, unsigned short selector, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, param, selector, - NULL, - 0, - 1000 - ); + NULL, + 0, + 1000 + ); } -static unsigned short se401_get_feature(struct usb_se401 *se401, - unsigned short selector) +static unsigned short se401_get_feature(struct usb_se401 *se401, + unsigned short selector) { /* For 'set' the selecetor should be in index, not sure if the spec is wrong here to.... */ unsigned char cp[2]; - usb_control_msg ( - se401->dev, - usb_rcvctrlpipe(se401->dev, 0), - SE401_REQ_GET_EXT_FEATURE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, - selector, - cp, - 2, - 1000 - ); + usb_control_msg ( + se401->dev, + usb_rcvctrlpipe(se401->dev, 0), + SE401_REQ_GET_EXT_FEATURE, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, + selector, + cp, + 2, + 1000 + ); return cp[0]+cp[1]*256; } @@ -183,14 +183,14 @@ static int se401_send_pict(struct usb_se401 *se401) se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */ se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */ se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */ - + return 0; } static void se401_set_exposure(struct usb_se401 *se401, int brightness) { int integration=brightness<<5; - + if (flickerless==50) { integration=integration-integration%106667; } @@ -255,11 +255,11 @@ static void se401_auto_resetlevel(struct usb_se401 *se401) /* For some reason this normally read-only register doesn't get reset to zero after reading them just once... */ - se401_get_feature(se401, HV7131_REG_HIREFNOH); + se401_get_feature(se401, HV7131_REG_HIREFNOH); se401_get_feature(se401, HV7131_REG_HIREFNOL); se401_get_feature(se401, HV7131_REG_LOREFNOH); se401_get_feature(se401, HV7131_REG_LOREFNOL); - ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + + ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + se401_get_feature(se401, HV7131_REG_HIREFNOL); alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) + se401_get_feature(se401, HV7131_REG_LOREFNOL); @@ -287,12 +287,12 @@ static void se401_button_irq(struct urb *urb, struct pt_regs *regs) { struct usb_se401 *se401 = urb->context; int status; - + if (!se401->dev) { info("ohoh: device vapourished"); return; } - + switch (urb->status) { case 0: /* success */ @@ -368,7 +368,7 @@ static void se401_video_irq(struct urb *urb, struct pt_regs *regs) if (se401->nullpackets > SE401_MAX_NULLPACKETS) { if (waitqueue_active(&se401->wq)) { wake_up_interruptible(&se401->wq); - } + } } } @@ -433,8 +433,8 @@ static int se401_start_stream(struct usb_se401 *se401) int err=0, i; se401->streaming=1; - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); /* Set picture settings */ se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */ @@ -571,7 +571,7 @@ static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data) } /* First three are absolute, all others relative. - * Format is rgb from right to left (mirrorred image), + * Format is rgb from right to left (mirrorred image), * we flip it to get bgr from left to right. */ if (frame->curlinepix < 3) { *(frame->curline-frame->curlinepix)=1+data*4; @@ -703,7 +703,7 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * int width=se401->cwidth; int blineoffset=0, bline; int linelength=width*3, i; - + if (frame->curpix==0) { if (frame->grabstate==FRAME_READY) { @@ -831,7 +831,7 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) se401->nullpackets=0; info("to many null length packets, restarting capture"); se401_stop_stream(se401); - se401_start_stream(se401); + se401_start_stream(se401); } else { if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) { se401->frame[framenr].grabstate=FRAME_ERROR; @@ -866,7 +866,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401) { int i; - se401->dev = NULL; + se401->dev = NULL; for (i=0; iurb[i]) { @@ -882,9 +882,9 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401) usb_kill_urb(se401->inturb); usb_free_urb(se401->inturb); } - info("%s disconnected", se401->camera_name); + info("%s disconnected", se401->camera_name); - /* Free the memory */ + /* Free the memory */ kfree(se401->width); kfree(se401->height); kfree(se401); @@ -910,7 +910,7 @@ static int se401_open(struct inode *inode, struct file *file) se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); if (se401->fbuf) file->private_data = dev; - else + else err = -ENOMEM; se401->user = !err; @@ -920,11 +920,11 @@ static int se401_open(struct inode *inode, struct file *file) static int se401_close(struct inode *inode, struct file *file) { struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; + struct usb_se401 *se401 = (struct usb_se401 *)dev; int i; rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); - if (se401->removed) { + if (se401->removed) { usb_se401_remove_disconnected(se401); info("device unregistered"); } else { @@ -942,12 +942,12 @@ static int se401_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)vdev; + struct usb_se401 *se401 = (struct usb_se401 *)vdev; - if (!se401->dev) - return -EIO; + if (!se401->dev) + return -EIO; - switch (cmd) { + switch (cmd) { case VIDIOCGCAP: { struct video_capability *b = arg; @@ -981,8 +981,8 @@ static int se401_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; return 0; } - case VIDIOCGPICT: - { + case VIDIOCGPICT: + { struct video_picture *p = arg; se401_get_pict(se401, p); @@ -1007,7 +1007,7 @@ static int se401_do_ioctl(struct inode *inode, struct file *file, if (se401_set_size(se401, vw->width, vw->height)) return -EINVAL; return 0; - } + } case VIDIOCGWIN: { struct video_window *vw = arg; @@ -1095,11 +1095,11 @@ static int se401_do_ioctl(struct inode *inode, struct file *file, case VIDIOCGAUDIO: case VIDIOCSAUDIO: return -EINVAL; - default: - return -ENOIOCTLCMD; - } /* end switch */ + default: + return -ENOIOCTLCMD; + } /* end switch */ - return 0; + return 0; } static int se401_ioctl(struct inode *inode, struct file *file, @@ -1142,7 +1142,7 @@ static ssize_t se401_read(struct file *file, char __user *buf, se401->frame[0].grabstate=FRAME_UNUSED; if (ret) - return ret; + return ret; if (copy_to_user(buf, se401->frame[0].data, realcount)) return -EFAULT; @@ -1183,24 +1183,24 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma) } mutex_unlock(&se401->lock); - return 0; + return 0; } static struct file_operations se401_fops = { .owner = THIS_MODULE, - .open = se401_open, - .release = se401_close, - .read = se401_read, - .mmap = se401_mmap, + .open = se401_open, + .release = se401_close, + .read = se401_read, + .mmap = se401_mmap, .ioctl = se401_ioctl, .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; static struct video_device se401_template = { .owner = THIS_MODULE, - .name = "se401 USB camera", - .type = VID_TYPE_CAPTURE, - .hardware = VID_HARDWARE_SE401, + .name = "se401 USB camera", + .type = VID_TYPE_CAPTURE, + .hardware = VID_HARDWARE_SE401, .fops = &se401_fops, }; @@ -1209,12 +1209,12 @@ static struct video_device se401_template = { /***************************/ static int se401_init(struct usb_se401 *se401, int button) { - int i=0, rc; - unsigned char cp[0x40]; + int i=0, rc; + unsigned char cp[0x40]; char temp[200]; /* led on */ - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); /* get camera descriptor */ rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp)); @@ -1254,7 +1254,7 @@ static int se401_init(struct usb_se401 *se401, int button) return 1; } /* set output mode (BAYER) */ - se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0); rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); se401->brightness=cp[0]+cp[1]*256; @@ -1292,71 +1292,71 @@ static int se401_init(struct usb_se401 *se401, int button) } else se401->inturb=NULL; - /* Flash the led */ - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); + /* Flash the led */ + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); - return 0; + return 0; } static int se401_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); - struct usb_interface_descriptor *interface; - struct usb_se401 *se401; - char *camera_name=NULL; + struct usb_interface_descriptor *interface; + struct usb_se401 *se401; + char *camera_name=NULL; int button=1; - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) + return -ENODEV; - interface = &intf->cur_altsetting->desc; + interface = &intf->cur_altsetting->desc; - /* Is it an se401? */ - if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 && - le16_to_cpu(dev->descriptor.idProduct) == 0x0004) { - camera_name="Endpoints/Aox SE401"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 && - le16_to_cpu(dev->descriptor.idProduct) == 0x030b) { - camera_name="Philips PCVC665K"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + /* Is it an se401? */ + if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 && + le16_to_cpu(dev->descriptor.idProduct) == 0x0004) { + camera_name="Endpoints/Aox SE401"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 && + le16_to_cpu(dev->descriptor.idProduct) == 0x030b) { + camera_name="Philips PCVC665K"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && le16_to_cpu(dev->descriptor.idProduct) == 0x5001) { camera_name="Kensington VideoCAM 67014"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && le16_to_cpu(dev->descriptor.idProduct) == 0x5002) { camera_name="Kensington VideoCAM 6701(5/7)"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && le16_to_cpu(dev->descriptor.idProduct) == 0x5003) { camera_name="Kensington VideoCAM 67016"; button=0; } else return -ENODEV; - /* Checking vendor/product should be enough, but what the hell */ - if (interface->bInterfaceClass != 0x00) + /* Checking vendor/product should be enough, but what the hell */ + if (interface->bInterfaceClass != 0x00) return -ENODEV; - if (interface->bInterfaceSubClass != 0x00) + if (interface->bInterfaceSubClass != 0x00) return -ENODEV; - /* We found one */ - info("SE401 camera found: %s", camera_name); + /* We found one */ + info("SE401 camera found: %s", camera_name); - if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { - err("couldn't kmalloc se401 struct"); + if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { + err("couldn't kmalloc se401 struct"); return -ENOMEM; - } + } - se401->dev = dev; - se401->iface = interface->bInterfaceNumber; - se401->camera_name = camera_name; + se401->dev = dev; + se401->iface = interface->bInterfaceNumber; + se401->camera_name = camera_name; info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255); - if (se401_init(se401, button)) { + if (se401_init(se401, button)) { kfree(se401); return -EIO; } @@ -1375,7 +1375,7 @@ static int se401_probe(struct usb_interface *intf, info("registered new video device: video%d", se401->vdev.minor); usb_set_intfdata (intf, se401); - return 0; + return 0; } static void se401_disconnect(struct usb_interface *intf) @@ -1400,10 +1400,10 @@ static void se401_disconnect(struct usb_interface *intf) } static struct usb_driver se401_driver = { - .name = "se401", - .id_table = device_table, + .name = "se401", + .id_table = device_table, .probe = se401_probe, - .disconnect = se401_disconnect, + .disconnect = se401_disconnect, }; diff --git a/drivers/media/video/se401.h b/drivers/media/video/se401.h index e88a40d4c86a..a7a216bd4413 100644 --- a/drivers/media/video/se401.h +++ b/drivers/media/video/se401.h @@ -177,7 +177,7 @@ struct usb_se401 { int expose_m; int expose_l; int resetlevel; - + int enhance; int format; @@ -200,12 +200,12 @@ struct usb_se401 { struct urb *urb[SE401_NUMSBUF]; struct urb *inturb; - + int button; int buttonpressed; int curframe; /* Current receiving frame */ - struct se401_frame frame[SE401_NUMFRAMES]; + struct se401_frame frame[SE401_NUMFRAMES]; int readcount; int framecount; int error; diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile index 8bcb0f71d69f..536ad3098da4 100644 --- a/drivers/media/video/sn9c102/Makefile +++ b/drivers/media/video/sn9c102/Makefile @@ -1,7 +1,7 @@ sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ - sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \ - sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ - sn9c102_tas5130d1b.o + sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \ + sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ + sn9c102_tas5130d1b.o obj-$(CONFIG_USB_SN9C102) += sn9c102.o diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h index 1d70a62b9f23..2c6ff396dafc 100644 --- a/drivers/media/video/sn9c102/sn9c102.h +++ b/drivers/media/video/sn9c102/sn9c102.h @@ -164,7 +164,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) void sn9c102_attach_sensor(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) + struct sn9c102_sensor* sensor) { memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); } @@ -183,7 +183,7 @@ do { \ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ else if ((level) >= 3) \ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ + __FUNCTION__, __LINE__ , ## args); \ } \ } while (0) # define V4LDBG(level, name, cmd) \ @@ -198,7 +198,7 @@ do { \ pr_info("sn9c102: " fmt "\n", ## args); \ else if ((level) == 3) \ pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ + __LINE__ , ## args); \ } \ } while (0) #else @@ -210,7 +210,7 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) + __FUNCTION__, __LINE__ , ## args) #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 4c6cc6395723..ea4394dc9415 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -62,53 +62,53 @@ MODULE_LICENSE(SN9C102_MODULE_LICENSE); static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1}; module_param_array(video_nr, short, NULL, 0444); MODULE_PARM_DESC(video_nr, - "\n<-1|n[,...]> Specify V4L2 minor mode number." - "\n -1 = use next available (default)" - "\n n = use minor number n (integer >= 0)" - "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES) - " cameras this way." - "\nFor example:" - "\nvideo_nr=-1,2,-1 would assign minor number 2 to" - "\nthe second camera and use auto for the first" - "\none and for every other camera." - "\n"); - -static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] = - SN9C102_FORCE_MUNMAP}; + "\n<-1|n[,...]> Specify V4L2 minor mode number." + "\n -1 = use next available (default)" + "\n n = use minor number n (integer >= 0)" + "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES) + " cameras this way." + "\nFor example:" + "\nvideo_nr=-1,2,-1 would assign minor number 2 to" + "\nthe second camera and use auto for the first" + "\none and for every other camera." + "\n"); + +static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] = + SN9C102_FORCE_MUNMAP}; module_param_array(force_munmap, bool, NULL, 0444); MODULE_PARM_DESC(force_munmap, - "\n<0|1[,...]> Force the application to unmap previously" - "\nmapped buffer memory before calling any VIDIOC_S_CROP or" - "\nVIDIOC_S_FMT ioctl's. Not all the applications support" - "\nthis feature. This parameter is specific for each" - "\ndetected camera." - "\n 0 = do not force memory unmapping" - "\n 1 = force memory unmapping (save memory)" - "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." - "\n"); + "\n<0|1[,...]> Force the application to unmap previously" + "\nmapped buffer memory before calling any VIDIOC_S_CROP or" + "\nVIDIOC_S_FMT ioctl's. Not all the applications support" + "\nthis feature. This parameter is specific for each" + "\ndetected camera." + "\n 0 = do not force memory unmapping" + "\n 1 = force memory unmapping (save memory)" + "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." + "\n"); static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = - SN9C102_FRAME_TIMEOUT}; + SN9C102_FRAME_TIMEOUT}; module_param_array(frame_timeout, uint, NULL, 0644); MODULE_PARM_DESC(frame_timeout, - "\n Timeout for a video frame in seconds." - "\nThis parameter is specific for each detected camera." - "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." - "\n"); + "\n Timeout for a video frame in seconds." + "\nThis parameter is specific for each detected camera." + "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." + "\n"); #ifdef SN9C102_DEBUG static unsigned short debug = SN9C102_DEBUG_LEVEL; module_param(debug, ushort, 0644); MODULE_PARM_DESC(debug, - "\n Debugging information level, from 0 to 3:" - "\n0 = none (use carefully)" - "\n1 = critical errors" - "\n2 = significant informations" - "\n3 = more verbose messages" - "\nLevel 3 is useful for testing only, when only " - "one device is used." - "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"." - "\n"); + "\n Debugging information level, from 0 to 3:" + "\n0 = none (use carefully)" + "\n1 = critical errors" + "\n2 = significant informations" + "\n3 = more verbose messages" + "\nLevel 3 is useful for testing only, when only " + "one device is used." + "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"." + "\n"); #endif /*****************************************************************************/ @@ -131,16 +131,16 @@ static sn9c102_eof_header_t sn9c102_eof_header[] = { /*****************************************************************************/ -static u32 -sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, - enum sn9c102_io_method io) +static u32 +sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, + enum sn9c102_io_method io) { struct v4l2_pix_format* p = &(cam->sensor.pix_format); struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); const size_t imagesize = cam->module_param.force_munmap || - io == IO_READ ? - (p->width * p->height * p->priv) / 8 : - (r->width * r->height * p->priv) / 8; + io == IO_READ ? + (p->width * p->height * p->priv) / 8 : + (r->width * r->height * p->priv) / 8; void* buff = NULL; u32 i; @@ -232,8 +232,8 @@ int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index) return -1; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - index, 0, buff, sizeof(buff), - SN9C102_CTRL_TIMEOUT*sizeof(buff)); + index, 0, buff, sizeof(buff), + SN9C102_CTRL_TIMEOUT*sizeof(buff)); if (res < 0) { DBG(3, "Failed to write registers (index 0x%02X, error %d)", index, res); @@ -259,7 +259,7 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index) *buff = value; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); + index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); if (res < 0) { DBG(3, "Failed to write a register (value 0x%02X, index " "0x%02X, error %d)", value, index, res); @@ -280,7 +280,7 @@ static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index) int res; res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); + index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); if (res < 0) DBG(3, "Failed to read a register (index 0x%02X, error %d)", index, res); @@ -319,8 +319,8 @@ sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor) static int -sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) +sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor) { int r; r = sn9c102_read_reg(cam, 0x08); @@ -329,8 +329,8 @@ sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, static int -sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) +sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, + struct sn9c102_sensor* sensor) { int r; r = sn9c102_read_reg(cam, 0x08); @@ -338,10 +338,10 @@ sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, } -int +int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 data0, u8 data1, - u8 n, u8 buffer[]) + struct sn9c102_sensor* sensor, u8 data0, u8 data1, + u8 n, u8 buffer[]) { struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; @@ -349,12 +349,12 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, /* Write cycle */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10; + ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10; data[1] = data0; /* I2C slave id */ data[2] = data1; /* address */ data[7] = 0x10; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); + 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; @@ -362,12 +362,12 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, /* Read cycle - n bytes */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | - (n << 4) | 0x02; + ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | + (n << 4) | 0x02; data[1] = data0; data[7] = 0x10; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); + 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; @@ -375,7 +375,7 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, /* The first read byte will be placed in data[4] */ res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT); + 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; @@ -396,10 +396,10 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, } -int +int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 n, u8 data0, - u8 data1, u8 data2, u8 data3, u8 data4, u8 data5) + struct sn9c102_sensor* sensor, u8 n, u8 data0, + u8 data1, u8 data2, u8 data3, u8 data4, u8 data5) { struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; @@ -407,8 +407,8 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, /* Write cycle. It usually is address + value */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) - | ((n - 1) << 4); + ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) + | ((n - 1) << 4); data[1] = data0; data[2] = data1; data[3] = data2; @@ -417,7 +417,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, data[6] = data5; data[7] = 0x14; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); + 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; @@ -437,20 +437,20 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, int sn9c102_i2c_try_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 address) + struct sn9c102_sensor* sensor, u8 address) { return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id, - address, 1, NULL); + address, 1, NULL); } int sn9c102_i2c_try_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 address, u8 value) + struct sn9c102_sensor* sensor, u8 address, u8 value) { - return sn9c102_i2c_try_raw_write(cam, sensor, 3, - sensor->i2c_slave_id, address, - value, 0, 0, 0); + return sn9c102_i2c_try_raw_write(cam, sensor, 3, + sensor->i2c_slave_id, address, + value, 0, 0, 0); } @@ -484,7 +484,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) n = sizeof(sn9c103_sof_header) / soflen; } - for (i = 0; (len >= soflen) && (i <= len - soflen); i++) + for (i = 0; (len >= soflen) && (i <= len - soflen); i++) for (j = 0; j < n; j++) /* The invariable part of the header is 6 bytes long */ if ((cam->bridge != BRIDGE_SN9C103 && @@ -552,15 +552,15 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) if (!(*f)) (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t, - frame); + frame); imagesize = (cam->sensor.pix_format.width * - cam->sensor.pix_format.height * - cam->sensor.pix_format.priv) / 8; + cam->sensor.pix_format.height * + cam->sensor.pix_format.priv) / 8; soflen = (cam->bridge) == BRIDGE_SN9C103 ? - sizeof(sn9c103_sof_header_t) : - sizeof(sn9c102_sof_header_t); + sizeof(sn9c103_sof_header_t) : + sizeof(sn9c102_sof_header_t); for (i = 0; i < urb->number_of_packets; i++) { unsigned int img, len, status; @@ -611,19 +611,19 @@ end_of_frame: if ((*f)->buf.bytesused == imagesize || (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_SN9C10X && eof)) { + V4L2_PIX_FMT_SN9C10X && eof)) { u32 b; b = (*f)->buf.bytesused; (*f)->state = F_DONE; (*f)->buf.sequence= ++cam->frame_count; spin_lock(&cam->queue_lock); list_move_tail(&(*f)->frame, - &cam->outqueue); + &cam->outqueue); if (!list_empty(&cam->inqueue)) (*f) = list_entry( - cam->inqueue.next, - struct sn9c102_frame_t, - frame ); + cam->inqueue.next, + struct sn9c102_frame_t, + frame ); else (*f) = NULL; spin_unlock(&cam->queue_lock); @@ -638,7 +638,7 @@ end_of_frame: } else if (eof) { (*f)->state = F_ERROR; DBG(3, "Not expected EOF after %lu " - "bytes of image data", + "bytes of image data", (unsigned long) ((*f)->buf.bytesused)); } @@ -676,7 +676,7 @@ start_of_frame: goto end_of_frame; } else { DBG(3, "SOF before expected EOF after " - "%lu bytes of image data", + "%lu bytes of image data", (unsigned long) ((*f)->buf.bytesused)); goto start_of_frame; @@ -702,18 +702,18 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) struct usb_device *udev = cam->usbdev; struct urb* urb; const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512, - 680, 800, 900, 1023}; + 680, 800, 900, 1023}; const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512, - 680, 800, 900, 1003}; + 680, 800, 900, 1003}; const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ? - sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] : - sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING]; + sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] : + sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING]; s8 i, j; int err = 0; for (i = 0; i < SN9C102_URBS; i++) { cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz, - GFP_KERNEL); + GFP_KERNEL); if (!cam->transfer_buffer[i]) { err = -ENOMEM; DBG(1, "Not enough memory"); @@ -815,9 +815,9 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam) cam->stream = STREAM_INTERRUPT; timeout = wait_event_timeout(cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED), - SN9C102_URB_TIMEOUT); + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + SN9C102_URB_TIMEOUT); if (cam->state & DEV_DISCONNECTED) return -ENODEV; else if (cam->stream != STREAM_OFF) { @@ -861,7 +861,7 @@ static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count) /* NOTE 1: being inside one of the following methods implies that the v4l - device exists for sure (see kobjects and reference counters) + device exists for sure (see kobjects and reference counters) NOTE 2: buffers are PAGE_SIZE long */ @@ -884,10 +884,10 @@ static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf) mutex_unlock(&sn9c102_sysfs_lock); return count; -} +} -static ssize_t +static ssize_t sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) { struct sn9c102_device* cam; @@ -947,7 +947,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) mutex_unlock(&sn9c102_sysfs_lock); return count; -} +} static ssize_t @@ -1013,7 +1013,7 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf) } -static ssize_t +static ssize_t sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) { struct sn9c102_device* cam; @@ -1078,7 +1078,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) mutex_unlock(&sn9c102_sysfs_lock); return count; -} +} static ssize_t @@ -1222,22 +1222,22 @@ static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf) DBG(3, "Frame header, read bytes: %zd", count); return count; -} +} static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, - sn9c102_show_reg, sn9c102_store_reg); + sn9c102_show_reg, sn9c102_store_reg); static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR, - sn9c102_show_val, sn9c102_store_val); + sn9c102_show_val, sn9c102_store_val); static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, - sn9c102_show_i2c_reg, sn9c102_store_i2c_reg); + sn9c102_show_i2c_reg, sn9c102_store_i2c_reg); static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, - sn9c102_show_i2c_val, sn9c102_store_i2c_val); + sn9c102_show_i2c_val, sn9c102_store_i2c_val); static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green); static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue); static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red); static CLASS_DEVICE_ATTR(frame_header, S_IRUGO, - sn9c102_show_frame_header, NULL); + sn9c102_show_frame_header, NULL); static void sn9c102_create_sysfs(struct sn9c102_device* cam) @@ -1278,7 +1278,7 @@ sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix) static int sn9c102_set_compression(struct sn9c102_device* cam, - struct v4l2_jpegcompression* compression) + struct v4l2_jpegcompression* compression) { int err = 0; @@ -1469,8 +1469,8 @@ static int sn9c102_open(struct inode* inode, struct file* filp) } mutex_unlock(&cam->dev_mutex); err = wait_event_interruptible_exclusive(cam->open, - cam->state & DEV_DISCONNECTED - || !cam->users); + cam->state & DEV_DISCONNECTED + || !cam->users); if (err) { up_read(&sn9c102_disconnect); return err; @@ -1600,12 +1600,12 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) return -EAGAIN; } timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); if (timeout < 0) { mutex_unlock(&cam->fileop_mutex); return timeout; @@ -1672,7 +1672,7 @@ static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) if (cam->io == IO_NONE) { if (!sn9c102_request_buffers(cam, cam->nreadbuffers, - IO_READ)) { + IO_READ)) { DBG(1, "poll() failed, not enough memory"); goto error; } @@ -1729,7 +1729,7 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) { struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); unsigned long size = vma->vm_end - vma->vm_start, - start = vma->vm_start; + start = vma->vm_start; void *pos; u32 i; @@ -1797,13 +1797,13 @@ sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg) .driver = "sn9c102", .version = SN9C102_MODULE_VERSION_CODE, .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, + V4L2_CAP_STREAMING, }; strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, - sizeof(cap.bus_info)); + sizeof(cap.bus_info)); if (copy_to_user(arg, &cap, sizeof(cap))) return -EFAULT; @@ -2138,7 +2138,7 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) return -EINVAL; pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X) - ? 0 : (pfmt->width * pfmt->priv) / 8; + ? 0 : (pfmt->width * pfmt->priv) / 8; pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); pfmt->field = V4L2_FIELD_NONE; memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); @@ -2152,7 +2152,7 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) static int sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, - void __user * arg) + void __user * arg) { struct sn9c102_sensor* s = &cam->sensor; struct v4l2_format format; @@ -2214,7 +2214,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, pix->priv = pfmt->priv; /* bpp */ pix->colorspace = pfmt->colorspace; pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - ? 0 : (pix->width * pix->priv) / 8; + ? 0 : (pix->width * pix->priv) / 8; pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); pix->field = V4L2_FIELD_NONE; @@ -2287,7 +2287,7 @@ static int sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg) { if (copy_to_user(arg, &cam->compression, - sizeof(cam->compression))) + sizeof(cam->compression))) return -EFAULT; return 0; @@ -2436,7 +2436,7 @@ sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg) static int sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, - void __user * arg) + void __user * arg) { struct v4l2_buffer b; struct sn9c102_frame_t *f; @@ -2455,12 +2455,12 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, if (filp->f_flags & O_NONBLOCK) return -EAGAIN; timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); if (timeout < 0) return timeout; if (cam->state & DEV_DISCONNECTED) @@ -2584,7 +2584,7 @@ sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg) static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) + unsigned int cmd, void __user * arg) { struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); @@ -2678,7 +2678,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, static int sn9c102_ioctl(struct inode* inode, struct file* filp, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); int err = 0; @@ -2761,7 +2761,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) } cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ? - BRIDGE_SN9C103 : BRIDGE_SN9C102; + BRIDGE_SN9C103 : BRIDGE_SN9C102; switch (cam->bridge) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: @@ -2807,7 +2807,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) mutex_lock(&cam->dev_mutex); err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); + video_nr[dev_nr]); if (err) { DBG(1, "V4L2 device registration failed"); if (err == -ENFILE && video_nr[dev_nr] == -1) diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c index 46c12ec3ca62..c4117bf64b69 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c @@ -44,8 +44,8 @@ static int hv7131d_init(struct sn9c102_device* cam) } -static int hv7131d_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) +static int hv7131d_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) { switch (ctrl->id) { case V4L2_CID_EXPOSURE: @@ -88,8 +88,8 @@ static int hv7131d_get_ctrl(struct sn9c102_device* cam, } -static int hv7131d_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) +static int hv7131d_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) { int err = 0; @@ -121,8 +121,8 @@ static int hv7131d_set_ctrl(struct sn9c102_device* cam, } -static int hv7131d_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) +static int hv7131d_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) { struct sn9c102_sensor* s = &hv7131d; int err = 0; @@ -136,8 +136,8 @@ static int hv7131d_set_crop(struct sn9c102_device* cam, } -static int hv7131d_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) +static int hv7131d_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) { int err = 0; diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c index d9aa7a61095d..4169ea4a2e20 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0343.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c @@ -39,64 +39,64 @@ static int mi0343_init(struct sn9c102_device* cam) err += sn9c102_write_reg(cam, 0xa0, 0x19); err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x0d, 0x00, 0x01, 0, 0); + 0x0d, 0x00, 0x01, 0, 0); err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x0d, 0x00, 0x00, 0, 0); + 0x0d, 0x00, 0x00, 0, 0); err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x03, 0x01, 0xe1, 0, 0); + 0x03, 0x01, 0xe1, 0, 0); err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x04, 0x02, 0x81, 0, 0); + 0x04, 0x02, 0x81, 0, 0); err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x05, 0x00, 0x17, 0, 0); + 0x05, 0x00, 0x17, 0, 0); err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x06, 0x00, 0x11, 0, 0); + 0x06, 0x00, 0x11, 0, 0); err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, - 0x62, 0x04, 0x9a, 0, 0); + 0x62, 0x04, 0x9a, 0, 0); return err; } -static int mi0343_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) +static int mi0343_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) { switch (ctrl->id) { case V4L2_CID_EXPOSURE: if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x09, 2+1, mi0343_i2c_data) < 0) + 0x09, 2+1, mi0343_i2c_data) < 0) return -EIO; ctrl->value = mi0343_i2c_data[2]; return 0; case V4L2_CID_GAIN: if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x35, 2+1, mi0343_i2c_data) < 0) + 0x35, 2+1, mi0343_i2c_data) < 0) return -EIO; break; case V4L2_CID_HFLIP: if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x20, 2+1, mi0343_i2c_data) < 0) + 0x20, 2+1, mi0343_i2c_data) < 0) return -EIO; ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0; return 0; case V4L2_CID_VFLIP: if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x20, 2+1, mi0343_i2c_data) < 0) + 0x20, 2+1, mi0343_i2c_data) < 0) return -EIO; ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0; return 0; case V4L2_CID_RED_BALANCE: if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2d, 2+1, mi0343_i2c_data) < 0) + 0x2d, 2+1, mi0343_i2c_data) < 0) return -EIO; break; case V4L2_CID_BLUE_BALANCE: if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2c, 2+1, mi0343_i2c_data) < 0) + 0x2c, 2+1, mi0343_i2c_data) < 0) return -EIO; break; case SN9C102_V4L2_CID_GREEN_BALANCE: if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, - 0x2e, 2+1, mi0343_i2c_data) < 0) + 0x2e, 2+1, mi0343_i2c_data) < 0) return -EIO; break; default: @@ -121,8 +121,8 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam, } -static int mi0343_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) +static int mi0343_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) { u16 reg = 0; int err = 0; @@ -144,51 +144,51 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam, switch (ctrl->id) { case V4L2_CID_EXPOSURE: err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x09, ctrl->value, 0x00, - 0, 0); + mi0343.i2c_slave_id, + 0x09, ctrl->value, 0x00, + 0, 0); break; case V4L2_CID_GAIN: err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x35, reg >> 8, reg & 0xff, - 0, 0); + mi0343.i2c_slave_id, + 0x35, reg >> 8, reg & 0xff, + 0, 0); break; case V4L2_CID_HFLIP: err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x20, ctrl->value ? 0x40:0x00, - ctrl->value ? 0x20:0x00, - 0, 0); + mi0343.i2c_slave_id, + 0x20, ctrl->value ? 0x40:0x00, + ctrl->value ? 0x20:0x00, + 0, 0); break; case V4L2_CID_VFLIP: err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x20, ctrl->value ? 0x80:0x00, - ctrl->value ? 0x80:0x00, - 0, 0); + mi0343.i2c_slave_id, + 0x20, ctrl->value ? 0x80:0x00, + ctrl->value ? 0x80:0x00, + 0, 0); break; case V4L2_CID_RED_BALANCE: err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x2d, reg >> 8, reg & 0xff, - 0, 0); + mi0343.i2c_slave_id, + 0x2d, reg >> 8, reg & 0xff, + 0, 0); break; case V4L2_CID_BLUE_BALANCE: err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x2c, reg >> 8, reg & 0xff, - 0, 0); + mi0343.i2c_slave_id, + 0x2c, reg >> 8, reg & 0xff, + 0, 0); break; case SN9C102_V4L2_CID_GREEN_BALANCE: err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x2b, reg >> 8, reg & 0xff, - 0, 0); + mi0343.i2c_slave_id, + 0x2b, reg >> 8, reg & 0xff, + 0, 0); err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x2e, reg >> 8, reg & 0xff, - 0, 0); + mi0343.i2c_slave_id, + 0x2e, reg >> 8, reg & 0xff, + 0, 0); break; default: return -EINVAL; @@ -198,8 +198,8 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam, } -static int mi0343_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) +static int mi0343_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) { struct sn9c102_sensor* s = &mi0343; int err = 0; @@ -213,20 +213,20 @@ static int mi0343_set_crop(struct sn9c102_device* cam, } -static int mi0343_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) +static int mi0343_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) { int err = 0; if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x0a, 0x00, 0x03, 0, 0); + mi0343.i2c_slave_id, + 0x0a, 0x00, 0x03, 0, 0); err += sn9c102_write_reg(cam, 0x20, 0x19); } else { err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, - mi0343.i2c_slave_id, - 0x0a, 0x00, 0x05, 0, 0); + mi0343.i2c_slave_id, + 0x0a, 0x00, 0x05, 0, 0); err += sn9c102_write_reg(cam, 0xa0, 0x19); } @@ -351,7 +351,7 @@ int sn9c102_probe_mi0343(struct sn9c102_device* cam) return -EIO; if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00, - 2, mi0343_i2c_data) < 0) + 2, mi0343_i2c_data) < 0) return -EIO; if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3) diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c index 42852b7cb042..3da042021787 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c @@ -69,7 +69,7 @@ static int ov7630_init(struct sn9c102_device* cam) static int ov7630_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) + const struct v4l2_control* ctrl) { int err = 0; @@ -89,8 +89,8 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam, break; case V4L2_CID_CONTRAST: err += ctrl->value ? sn9c102_i2c_write(cam, 0x05, - (ctrl->value-1) | 0x20) - : sn9c102_i2c_write(cam, 0x05, 0x00); + (ctrl->value-1) | 0x20) + : sn9c102_i2c_write(cam, 0x05, 0x00); break; case V4L2_CID_BRIGHTNESS: err += sn9c102_i2c_write(cam, 0x06, ctrl->value); @@ -100,8 +100,8 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam, break; case V4L2_CID_HUE: err += ctrl->value ? sn9c102_i2c_write(cam, 0x04, - (ctrl->value-1) | 0x20) - : sn9c102_i2c_write(cam, 0x04, 0x00); + (ctrl->value-1) | 0x20) + : sn9c102_i2c_write(cam, 0x04, 0x00); break; case V4L2_CID_DO_WHITE_BALANCE: err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); @@ -139,7 +139,7 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam, static int ov7630_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) + const struct v4l2_rect* rect) { struct sn9c102_sensor* s = &ov7630; int err = 0; @@ -152,7 +152,7 @@ static int ov7630_set_crop(struct sn9c102_device* cam, static int ov7630_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) + const struct v4l2_pix_format* pix) { int err = 0; diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c index b1dee78abe04..9915944235e8 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas106b.c +++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c @@ -53,8 +53,8 @@ static int pas106b_init(struct sn9c102_device* cam) } -static int pas106b_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) +static int pas106b_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) { switch (ctrl->id) { case V4L2_CID_EXPOSURE: @@ -102,8 +102,8 @@ static int pas106b_get_ctrl(struct sn9c102_device* cam, } -static int pas106b_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) +static int pas106b_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) { int err = 0; @@ -140,8 +140,8 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam, } -static int pas106b_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) +static int pas106b_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) { struct sn9c102_sensor* s = &pas106b; int err = 0; @@ -155,8 +155,8 @@ static int pas106b_set_crop(struct sn9c102_device* cam, } -static int pas106b_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) +static int pas106b_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) { int err = 0; diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bca.c b/drivers/media/video/sn9c102/sn9c102_pas202bca.c index 3453237055bb..c8f1ae2152b8 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas202bca.c +++ b/drivers/media/video/sn9c102/sn9c102_pas202bca.c @@ -54,7 +54,7 @@ static int pas202bca_init(struct sn9c102_device* cam) static int pas202bca_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) + const struct v4l2_pix_format* pix) { int err = 0; @@ -68,7 +68,7 @@ static int pas202bca_set_pix_format(struct sn9c102_device* cam, static int pas202bca_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) + const struct v4l2_control* ctrl) { int err = 0; @@ -102,7 +102,7 @@ static int pas202bca_set_ctrl(struct sn9c102_device* cam, static int pas202bca_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) + const struct v4l2_rect* rect) { struct sn9c102_sensor* s = &pas202bca; int err = 0; diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c index d068616ab337..e3c1178e339c 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c +++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c @@ -58,8 +58,8 @@ static int pas202bcb_init(struct sn9c102_device* cam) } -static int pas202bcb_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) +static int pas202bcb_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) { switch (ctrl->id) { case V4L2_CID_EXPOSURE: @@ -101,8 +101,8 @@ static int pas202bcb_get_ctrl(struct sn9c102_device* cam, } -static int pas202bcb_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) +static int pas202bcb_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) { int err = 0; @@ -115,8 +115,8 @@ static int pas202bcb_set_pix_format(struct sn9c102_device* cam, } -static int pas202bcb_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) +static int pas202bcb_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) { int err = 0; @@ -149,8 +149,8 @@ static int pas202bcb_set_ctrl(struct sn9c102_device* cam, } -static int pas202bcb_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) +static int pas202bcb_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) { struct sn9c102_sensor* s = &pas202bcb; int err = 0; @@ -167,7 +167,7 @@ static int pas202bcb_set_crop(struct sn9c102_device* cam, static struct sn9c102_sensor pas202bcb = { .name = "PAS202BCB", .maintainer = "Carlos Eduardo Medaglia Dyonisio " - "", + "", .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_2WIRES, diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h index 2afd9e9d09bb..2a874ee6f9f5 100644 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/drivers/media/video/sn9c102/sn9c102_sensor.h @@ -58,7 +58,7 @@ struct sn9c102_sensor; Probing functions: on success, you must attach the sensor to the camera by calling sn9c102_attach_sensor() provided below. To enable the I2C communication, you might need to perform a really basic - initialization of the SN9C10X chip by using the write function declared + initialization of the SN9C10X chip by using the write function declared ahead. Functions must return 0 on success, the appropriate error otherwise. */ @@ -73,7 +73,7 @@ extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); /* Add the above entries to this table. Be sure to add the entry in the right - place, since, on failure, the next probing routine is called according to + place, since, on failure, the next probing routine is called according to the order of the list below, from top to bottom. */ #define SN9C102_SENSOR_TABLE \ @@ -94,9 +94,9 @@ extern struct sn9c102_device* sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); /* Attach a probed sensor to the camera. */ -extern void +extern void sn9c102_attach_sensor(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor); + struct sn9c102_sensor* sensor); /* Each SN9C10x camera has proper PID/VID identifiers. @@ -105,7 +105,7 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, */ #define SN9C102_USB_DEVICE(vend, prod, intclass) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ - USB_DEVICE_ID_MATCH_INT_CLASS, \ + USB_DEVICE_ID_MATCH_INT_CLASS, \ .idVendor = (vend), \ .idProduct = (prod), \ .bInterfaceClass = (intclass) @@ -162,19 +162,19 @@ static const struct usb_device_id sn9c102_id_table[] = { \ Read/write routines: they always return -1 on error, 0 or the read value otherwise. NOTE that a real read operation is not supported by the SN9C10X chip for some of its registers. To work around this problem, a pseudo-read - call is provided instead: it returns the last successfully written value + call is provided instead: it returns the last successfully written value on the register (0 if it has never been written), the usual -1 on error. */ /* The "try" I2C I/O versions are used when probing the sensor */ extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*, - u8 address, u8 value); + u8 address, u8 value); extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, - u8 address); + u8 address); /* These must be used if and only if the sensor doesn't implement the standard - I2C protocol. There are a number of good reasons why you must use the + I2C protocol. There are a number of good reasons why you must use the single-byte versions of these functions: do not abuse. The first function writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C10X chip. The second one programs the registers 0x09 and 0x10 with data0 and @@ -184,12 +184,12 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, byte. */ extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 n, - u8 data0, u8 data1, u8 data2, u8 data3, - u8 data4, u8 data5); + struct sn9c102_sensor* sensor, u8 n, + u8 data0, u8 data1, u8 data2, u8 data3, + u8 data4, u8 data5); extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 data0, - u8 data1, u8 n, u8 buffer[]); + struct sn9c102_sensor* sensor, u8 data0, + u8 data1, u8 n, u8 buffer[]); /* To be used after the sensor struct has been attached to the camera struct */ extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value); @@ -252,17 +252,17 @@ struct sn9c102_sensor { /* NOTE: Where not noted,most of the functions below are not mandatory. - Set to null if you do not implement them. If implemented, - they must return 0 on success, the proper error otherwise. + Set to null if you do not implement them. If implemented, + they must return 0 on success, the proper error otherwise. */ int (*init)(struct sn9c102_device* cam); /* - This function will be called after the sensor has been attached. + This function will be called after the sensor has been attached. It should be used to initialize the sensor only, but may also configure part of the SN9C10X chip if necessary. You don't need to setup picture settings like brightness, contrast, etc.. here, if - the corrisponding controls are implemented (see below), since + the corrisponding controls are implemented (see below), since they are adjusted in the core driver by calling the set_ctrl() method after init(), where the arguments are the default values specified in the v4l2_queryctrl list of supported controls; @@ -273,13 +273,13 @@ struct sn9c102_sensor { struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS]; /* - Optional list of default controls, defined as indicated in the + Optional list of default controls, defined as indicated in the V4L2 API. Menu type controls are not handled by this interface. */ int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl); int (*set_ctrl)(struct sn9c102_device* cam, - const struct v4l2_control* ctrl); + const struct v4l2_control* ctrl); /* You must implement at least the set_ctrl method if you have defined the list above. The returned value must follow the V4L2 @@ -306,7 +306,7 @@ struct sn9c102_sensor { specified in the cropcap substructures 'bounds' and 'defrect'. By default, the source rectangle should cover the largest possible area. Again, it is not always true that the largest source rectangle - can cover the entire active window, although it is a rare case for + can cover the entire active window, although it is a rare case for the hardware we have. The bounds of the source rectangle _must_ be multiple of 16 and must use the same coordinate system as indicated before; their centers shall align initially. @@ -317,13 +317,13 @@ struct sn9c102_sensor { defined the correct default bounds in the structures. See the V4L2 API for further details. NOTE: once you have defined the bounds of the active window - (struct cropcap.bounds) you must not change them.anymore. + (struct cropcap.bounds) you must not change them.anymore. Only 'bounds' and 'defrect' fields are mandatory, other fields will be ignored. */ int (*set_crop)(struct sn9c102_device* cam, - const struct v4l2_rect* rect); + const struct v4l2_rect* rect); /* To be called on VIDIOC_C_SETCROP. The core module always calls a default routine which configures the appropriate SN9C10X regs (also @@ -332,12 +332,12 @@ struct sn9c102_sensor { case you override the default function, you always have to program the chip to match those values; on error return the corresponding error code without rolling back. - NOTE: in case, you must program the SN9C10X chip to get rid of - blank pixels or blank lines at the _start_ of each line or - frame after each HSYNC or VSYNC, so that the image starts with - real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, - V_SIZE you don't have to care about blank pixels or blank - lines at the end of each line or frame). + NOTE: in case, you must program the SN9C10X chip to get rid of + blank pixels or blank lines at the _start_ of each line or + frame after each HSYNC or VSYNC, so that the image starts with + real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, + V_SIZE you don't have to care about blank pixels or blank + lines at the end of each line or frame). */ struct v4l2_pix_format pix_format; @@ -349,17 +349,17 @@ struct sn9c102_sensor { number of bits per pixel for uncompressed video, 8 or 9 (despite the current value of 'pixelformat'). NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4 - of cropcap.defrect.width and cropcap.defrect.height. I - suggest 1/1. + of cropcap.defrect.width and cropcap.defrect.height. I + suggest 1/1. NOTE 2: The initial compression quality is defined by the first bit - of reg 0x17 during the initialization of the image sensor. + of reg 0x17 during the initialization of the image sensor. NOTE 3: as said above, you have to program the SN9C10X chip to get - rid of any blank pixels, so that the output of the sensor - matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). + rid of any blank pixels, so that the output of the sensor + matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). */ int (*set_pix_format)(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix); + const struct v4l2_pix_format* pix); /* To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to SN9C10X pixel format or viceversa. On error return the corresponding diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c index 2e08c552f40a..294eb02fbd88 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c @@ -44,8 +44,8 @@ static int tas5110c1b_init(struct sn9c102_device* cam) } -static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) +static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) { int err = 0; @@ -61,8 +61,8 @@ static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, } -static int tas5110c1b_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) +static int tas5110c1b_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) { struct sn9c102_sensor* s = &tas5110c1b; int err = 0; @@ -81,8 +81,8 @@ static int tas5110c1b_set_crop(struct sn9c102_device* cam, } -static int tas5110c1b_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) +static int tas5110c1b_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) { int err = 0; diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c index c7b339740bbf..9ecb09032b68 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c @@ -42,8 +42,8 @@ static int tas5130d1b_init(struct sn9c102_device* cam) } -static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) +static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) { int err = 0; @@ -62,8 +62,8 @@ static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, } -static int tas5130d1b_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) +static int tas5130d1b_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) { struct sn9c102_sensor* s = &tas5130d1b; u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104, @@ -82,8 +82,8 @@ static int tas5130d1b_set_crop(struct sn9c102_device* cam, } -static int tas5130d1b_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) +static int tas5130d1b_set_pix_format(struct sn9c102_device* cam, + const struct v4l2_pix_format* pix) { int err = 0; diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 9d769264a329..07476c71174a 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -1,4 +1,4 @@ -/* +/* * stradis.c - stradis 4:2:2 mpeg decoder driver * * Stradis 4:2:2 MPEG-2 Decoder Driver @@ -1191,9 +1191,9 @@ static void saa7146_set_winsize(struct saa7146 *saa) } /* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area - * bitmap is fixed width, 128 bytes (1024 pixels represented) - * arranged most-sigificant-bit-left in 32-bit words - * based on saa7146 clipping hardware, it swaps bytes if LE + * bitmap is fixed width, 128 bytes (1024 pixels represented) + * arranged most-sigificant-bit-left in 32-bit words + * based on saa7146 clipping hardware, it swaps bytes if LE * much of this makes up for egcs brain damage -- so if you * are wondering "why did he do this?" it is because the C * was adjusted to generate the optimal asm output without @@ -1259,7 +1259,7 @@ static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr) clip_draw_rectangle(clipmap, cr[i].x, cr[i].y, cr[i].width, cr[i].height); } - /* clip against viewing window AND screen + /* clip against viewing window AND screen so we do not have to rely on the user program */ clip_draw_rectangle(clipmap, (saa->win.x + width > saa->win.swidth) ? diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 9636da20748d..b38bda83a7c5 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -1,16 +1,16 @@ /* * STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net) - * - * Thanks to STMicroelectronics for information on the usb commands, and - * to Steve Miller at STM for his help and encouragement while I was + * + * Thanks to STMicroelectronics for information on the usb commands, and + * to Steve Miller at STM for his help and encouragement while I was * writing this driver. * - * This driver is based heavily on the + * This driver is based heavily on the * Endpoints (formerly known as AOX) se401 USB Camera Driver * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) * * Still somewhat based on the Linux ov511 driver. - * + * * 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 @@ -25,18 +25,18 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * History: - * ver 0.1 October, 2001. Initial attempt. + * History: + * ver 0.1 October, 2001. Initial attempt. * * ver 0.2 November, 2001. Fixed asbility to resize, added brightness * function, made more stable (?) * - * ver 0.21 Nov, 2001. Added gamma correction and white balance, - * due to Alexander Schwartz. Still trying to + * ver 0.21 Nov, 2001. Added gamma correction and white balance, + * due to Alexander Schwartz. Still trying to * improve stablility. Moved stuff into stv680.h * - * ver 0.22 Nov, 2001. Added sharpen function (by Michael Sweet, - * mike@easysw.com) from GIMP, also used in pencam. + * ver 0.22 Nov, 2001. Added sharpen function (by Michael Sweet, + * mike@easysw.com) from GIMP, also used in pencam. * Simple, fast, good integer math routine. * * ver 0.23 Dec, 2001 (gkh) @@ -44,11 +44,11 @@ * Lindent, and did other minor tweaks to get * things to work properly with 2.5.1 * - * ver 0.24 Jan, 2002 (kjs) + * ver 0.24 Jan, 2002 (kjs) * Fixed the problem with webcam crashing after - * two pictures. Changed the way pic is halved to - * improve quality. Got rid of green line around - * frame. Fix brightness reset when changing size + * two pictures. Changed the way pic is halved to + * improve quality. Got rid of green line around + * frame. Fix brightness reset when changing size * bug. Adjusted gamma filters slightly. * * ver 0.25 Jan, 2002 (kjs) @@ -484,7 +484,7 @@ exit: PDEBUG (1, "STV(i): swapRGB is (forced) ON"); else if (swapRGB_on == -1) PDEBUG (1, "STV(i): swapRGB is (forced) OFF"); - + if (stv_set_video_mode (stv680) < 0) { PDEBUG (0, "STV(e): Could not set video mode in stv_init"); return -1; @@ -570,7 +570,7 @@ static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p) if (stv680->brightness != p->brightness) { stv680->chgbright = 1; stv680->brightness = p->brightness; - } + } stv680->whiteness = p->whiteness; /* greyscale */ stv680->colour = p->colour; @@ -612,7 +612,7 @@ static void stv680_video_irq (struct urb *urb, struct pt_regs *regs) case BUFFER_UNUSED: memcpy (stv680->scratch[stv680->scratch_next].data, - (unsigned char *) urb->transfer_buffer, length); + (unsigned char *) urb->transfer_buffer, length); stv680->scratch[stv680->scratch_next].state = BUFFER_READY; stv680->scratch[stv680->scratch_next].length = length; if (waitqueue_active (&stv680->wq)) { @@ -752,7 +752,7 @@ static int stv680_set_size (struct usb_stv *stv680, int width, int height) PDEBUG (1, "STV(e): request for non-supported size: request: v.width = %i, v.height = %i actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight); return 1; } - + /* Stop a current stream and start it again at the new size */ if (wasstreaming) stv680_stop_stream (stv680); @@ -773,7 +773,7 @@ static int stv680_set_size (struct usb_stv *stv680, int width, int height) /* * STV0680 Vision Camera Chipset Driver - * Copyright (C) 2000 Adam Harrison + * Copyright (C) 2000 Adam Harrison */ #define RED 0 @@ -842,7 +842,7 @@ static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buff colour = 2; break; } - i = (y * vw + x) * 3; + i = (y * vw + x) * 3; *(output + i + colour) = (unsigned char) p; } /* for x */ @@ -850,9 +850,9 @@ static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buff /****** gamma correction plus hardcoded white balance */ /* Thanks to Alexander Schwartx for this code. - Correction values red[], green[], blue[], are generated by - (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1>8) & 0x7f); buffer[1] = div & 0xff; if (i2c_master_send(c, buffer, 2) != 2) printk("tuner: i2c i/o error 2\n"); - + while (!tuner_islocked(c) && time_before(jiffies, give_up)) schedule(); - + if (!tuner_islocked(c)) printk(KERN_WARNING "tuner: failed to achieve PLL lock\n"); - + /* Select low tuning current and engage AFC */ buffer[0] = 0x29; buffer[1] = 0xb2; @@ -106,7 +106,7 @@ set_tv_freq(struct i2c_client *c, int freq) /* ---------------------------------------------------------------------- */ -static int +static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) { static unsigned char buffer[] = { 0x29, 0x32, 0x2a, 0, 0x2b, 0 }; @@ -116,18 +116,18 @@ tuner_attach(struct i2c_adapter *adap, int addr, int kind) if (this_adap > 0) return -1; this_adap++; - - client_template.adapter = adap; - client_template.addr = addr; + + client_template.adapter = adap; + client_template.addr = addr; client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &client_template, sizeof(struct i2c_client)); + if (client == NULL) + return -ENOMEM; + memcpy(client, &client_template, sizeof(struct i2c_client)); printk("tuner: SAB3036 found, status %02x\n", tuner_getstatus(client)); - i2c_attach_client(client); + i2c_attach_client(client); if (i2c_master_send(client, buffer, 2) != 2) printk("tuner: i2c i/o error 1\n"); @@ -138,30 +138,30 @@ tuner_attach(struct i2c_adapter *adap, int addr, int kind) return 0; } -static int +static int tuner_detach(struct i2c_client *c) { return 0; } -static int +static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { int *iarg = (int*)arg; - switch (cmd) + switch (cmd) { case VIDIOCSFREQ: set_tv_freq(client, *iarg); break; - + default: return -EINVAL; } return 0; } -static int +static int tuner_probe(struct i2c_adapter *adap) { this_adap = 0; @@ -172,8 +172,8 @@ tuner_probe(struct i2c_adapter *adap) /* ----------------------------------------------------------------------- */ -static struct i2c_driver -i2c_driver_tuner = +static struct i2c_driver +i2c_driver_tuner = { .driver = { .name = "sab3036", @@ -186,7 +186,7 @@ i2c_driver_tuner = static struct i2c_client client_template = { - .driver = &i2c_driver_tuner, + .driver = &i2c_driver_tuner, .name = "SAB3036", }; diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index a42c22294124..76f771b6a32f 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c @@ -1300,11 +1300,11 @@ static void ibmcam_model2_Packet1(struct uvd *uvd, unsigned short v1, unsigned s /* * ibmcam_model3_Packet1() * - * 00_0078_012d + * 00_0078_012d * 00_0097_012f - * 00_d141_0124 + * 00_d141_0124 * 00_0096_0127 - * 00_fea8_0124 + * 00_fea8_0124 */ static void ibmcam_model3_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2) { @@ -2687,7 +2687,7 @@ static void ibmcam_model4_setup_after_video_if(struct uvd *uvd) ibmcam_veio(uvd, 0, 0x0004, 0x0127); ibmcam_veio(uvd, 0, 0xfea8, 0x0124); ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; + break; } usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); } @@ -3238,7 +3238,7 @@ static void ibmcam_model3_setup_after_video_if(struct uvd *uvd) {0, 0x0062, 0x0107}, {0, 0x0003, 0x0111}, }; -#define NUM_INIT_DATA +#define NUM_INIT_DATA unsigned short compression = 0; /* 0=none, 7=best frame rate */ int f_rate; /* 0=Fastest 7=slowest */ diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index e2ede583518f..c11f5d46b114 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c @@ -36,7 +36,7 @@ enum ctrl_req { SetWhitebal = 0x01, SetBrightness = 0x02, - SetSharpness = 0x03, + SetSharpness = 0x03, SetContrast = 0x04, SetSaturation = 0x05, }; @@ -47,7 +47,7 @@ enum frame_sizes { SIZE_160X136 = 1, SIZE_176X144 = 2, SIZE_320X240 = 3, - + }; #define MAX_FRAME_SIZE SIZE_320X240 @@ -69,7 +69,7 @@ static const int debug = 0; /* Some default values for initial camera settings, can be set by modprobe */ -static int size; +static int size; static int speed = 6; /* Speed (fps) 0 (slowest) to 6 (fastest) */ static int brightness = MAX_BRIGHTNESS/2; static int contrast = MAX_CONTRAST/2; @@ -132,24 +132,24 @@ struct konicawc { static int konicawc_ctrl_msg(struct uvd *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len) { - int retval = usb_control_msg(uvd->dev, + int retval = usb_control_msg(uvd->dev, dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0), request, 0x40 | dir, value, index, buf, len, 1000); - return retval < 0 ? retval : 0; + return retval < 0 ? retval : 0; } static inline void konicawc_camera_on(struct uvd *uvd) { - DEBUG(0, "camera on"); - konicawc_set_misc(uvd, 0x2, 1, 0x0b); + DEBUG(0, "camera on"); + konicawc_set_misc(uvd, 0x2, 1, 0x0b); } static inline void konicawc_camera_off(struct uvd *uvd) { - DEBUG(0, "camera off"); - konicawc_set_misc(uvd, 0x2, 0, 0x0b); + DEBUG(0, "camera off"); + konicawc_set_misc(uvd, 0x2, 0, 0x0b); } @@ -317,7 +317,7 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur button = !!(sts & 0x40); sts &= ~0x40; } - + /* work out the button status, but don't do anything with it for now */ @@ -331,7 +331,7 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur discard++; continue; } - + if((sts > 0x01) && (sts < 0x80)) { info("unknown status %2.2x", sts); bad++; @@ -350,7 +350,7 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur DEBUG(2, "found initial image"); cam->lastframe = -1; } - + marker[3] = sts & 0x7F; RingQueue_Enqueue(&uvd->dp, marker, 4); totlen += 4; @@ -367,16 +367,16 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur static void resubmit_urb(struct uvd *uvd, struct urb *urb) { - int i, ret; - for (i = 0; i < FRAMES_PER_DESC; i++) { - urb->iso_frame_desc[i].status = 0; - } - urb->dev = uvd->dev; - urb->status = 0; + int i, ret; + for (i = 0; i < FRAMES_PER_DESC; i++) { + urb->iso_frame_desc[i].status = 0; + } + urb->dev = uvd->dev; + urb->status = 0; ret = usb_submit_urb(urb, GFP_ATOMIC); DEBUG(3, "submitting urb of length %d", urb->transfer_buffer_length); - if(ret) - err("usb_submit_urb error (%d)", ret); + if(ret) + err("usb_submit_urb error (%d)", ret); } @@ -490,7 +490,7 @@ static int konicawc_start_data(struct uvd *uvd) } cam->last_data_urb = NULL; - + /* Submit all URBs */ for (i=0; i < USBVIDEO_NUMSBUF; i++) { errFlag = usb_submit_urb(cam->sts_urb[i], GFP_KERNEL); @@ -539,7 +539,7 @@ static void konicawc_stop_data(struct uvd *uvd) static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) -{ +{ struct konicawc *cam = (struct konicawc *)uvd->user_data; int maxline = cam->maxline; int yplanesz = cam->yplanesz; @@ -583,13 +583,13 @@ static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) if(frame->scanstate == ScanState_Scanning) return; - + /* Try to move data from queue into frame buffer * We get data in blocks of 384 bytes made up of: * 256 Y, 64 U, 64 V. * This needs to be written out as a Y plane, a U plane and a V plane. */ - + while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) { /* Y */ RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256); diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c index 75ff755224df..10c58b4a2e5b 100644 --- a/drivers/media/video/usbvideo/ultracam.c +++ b/drivers/media/video/usbvideo/ultracam.c @@ -23,7 +23,7 @@ typedef struct { int initialized; /* Had we already sent init sequence? */ int camera_model; /* What type of IBM camera we got? */ - int has_hdr; + int has_hdr; } ultracam_t; #define ULTRACAM_T(uvd) ((ultracam_t *)((uvd)->user_data)) diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index 0b51fae720a9..13b37c8c0d56 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -574,7 +574,7 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) } else { /* Just the blue screen */ } - + *f++ = cb; *f++ = cg; *f++ = cr; @@ -1243,7 +1243,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file) #if USBVIDEO_REPORT_STATS usbvideo_ReportStatistics(uvd); -#endif +#endif uvd->user--; if (uvd->remove_pending) { @@ -1290,7 +1290,7 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, return 0; } case VIDIOCSCHAN: - { + { struct video_channel *v = arg; if (v->channel != 0) return -EINVAL; @@ -1347,7 +1347,7 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, vw->chromakey = 0; if (VALID_CALLBACK(uvd, getFPS)) vw->flags = GET_CALLBACK(uvd, getFPS)(uvd); - else + else vw->flags = 10; /* FIXME: do better! */ return 0; } @@ -1359,7 +1359,7 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, memset(vm, 0, sizeof(*vm)); vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES; vm->frames = USBVIDEO_NUMFRAMES; - for(i = 0; i < USBVIDEO_NUMFRAMES; i++) + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) vm->offsets[i] = i * uvd->max_frame_size; return 0; @@ -1425,7 +1425,7 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES) return -EINVAL; - + if (uvd->debug >= 1) info("VIDIOCSYNC: syncing to frame %d.", *frameNum); if (uvd->flags & FLAGS_NO_DECODING) @@ -1454,8 +1454,8 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, struct video_buffer *vb = arg; memset(vb, 0, sizeof(*vb)); - return 0; - } + return 0; + } case VIDIOCKEY: return 0; @@ -1704,7 +1704,7 @@ static void usbvideo_IsocIrq(struct urb *urb, struct pt_regs *regs) info("Not streaming, but interrupt!"); return; } - + uvd->stats.urb_count++; if (urb->actual_length <= 0) goto urb_done_with; @@ -1763,7 +1763,7 @@ static int usbvideo_StartDataPump(struct uvd *uvd) } if (VALID_CALLBACK(uvd, videoStart)) GET_CALLBACK(uvd, videoStart)(uvd); - else + else err("%s: videoStart not set", __FUNCTION__); /* We double buffer the Iso lists */ @@ -1830,7 +1830,7 @@ static void usbvideo_StopDataPump(struct uvd *uvd) /* Invoke minidriver's magic to stop the camera */ if (VALID_CALLBACK(uvd, videoStop)) GET_CALLBACK(uvd, videoStop)(uvd); - else + else err("%s: videoStop not set", __FUNCTION__); /* Set packet size to 0 */ @@ -1963,14 +1963,14 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum); switch (frame->frameState) { - case FrameState_Unused: + case FrameState_Unused: if (uvd->debug >= 2) info("%s: FrameState_Unused", __FUNCTION__); return -EINVAL; - case FrameState_Ready: - case FrameState_Grabbing: - case FrameState_Error: - { + case FrameState_Ready: + case FrameState_Grabbing: + case FrameState_Error: + { int ntries, signalPending; redo: if (!CAMERA_IS_OPERATIONAL(uvd)) { @@ -1978,7 +1978,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) info("%s: Camera is not operational (1)", __FUNCTION__); return -EIO; } - ntries = 0; + ntries = 0; do { RingQueue_InterruptibleSleepOn(&uvd->dp); signalPending = signal_pending(current); @@ -2010,7 +2010,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) usbvideo_CollectRawData(uvd, frame); else if (VALID_CALLBACK(uvd, processData)) GET_CALLBACK(uvd, processData)(uvd, frame); - else + else err("%s: processData not set", __FUNCTION__); } } while (frame->frameState == FrameState_Grabbing); @@ -2027,8 +2027,8 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) goto redo; } /* Note that we fall through to meet our destiny below */ - } - case FrameState_Done: + } + case FrameState_Done: /* * Do all necessary postprocessing of data prepared in * "interrupt" code and the collecting code above. The @@ -2157,7 +2157,7 @@ EXPORT_SYMBOL(usbvideo_DeinterlaceFrame); * History: * 09-Feb-2001 Created. */ -static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, +static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, struct usbvideo_frame *frame) { int i, j, v4l_linesize; diff --git a/drivers/media/video/usbvideo/usbvideo.h b/drivers/media/video/usbvideo/usbvideo.h index 135433c2680a..3cbf4fc499a3 100644 --- a/drivers/media/video/usbvideo/usbvideo.h +++ b/drivers/media/video/usbvideo/usbvideo.h @@ -189,11 +189,11 @@ struct usbvideo_frame { /* Statistics that can be overlaid on screen */ struct usbvideo_statistics { - unsigned long frame_num; /* Sequential number of the frame */ - unsigned long urb_count; /* How many URBs we received so far */ - unsigned long urb_length; /* Length of last URB */ - unsigned long data_count; /* How many bytes we received */ - unsigned long header_count; /* How many frame headers we found */ + unsigned long frame_num; /* Sequential number of the frame */ + unsigned long urb_count; /* How many URBs we received so far */ + unsigned long urb_length; /* Length of last URB */ + unsigned long data_count; /* How many bytes we received */ + unsigned long header_count; /* How many frame headers we found */ unsigned long iso_skip_count; /* How many empty ISO packets received */ unsigned long iso_err_count; /* How many bad ISO packets received */ }; diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 1d06e53ec7c5..90d48e8510ba 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -69,10 +69,10 @@ #define VICAM_HEADER_SIZE 64 #define clamp( x, l, h ) max_t( __typeof__( x ), \ - ( l ), \ - min_t( __typeof__( x ), \ - ( h ), \ - ( x ) ) ) + ( l ), \ + min_t( __typeof__( x ), \ + ( h ), \ + ( x ) ) ) /* Not sure what all the bytes in these char * arrays do, but they're necessary to make @@ -357,7 +357,7 @@ static unsigned char setup5[] = { * Not sure why these are not yet non-statics which I can reference through * usbvideo.h the same as it is in 2.4.20. I bet this will get fixed sometime * in the future. - * + * */ static void *rvmalloc(unsigned long size) { @@ -603,12 +603,12 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign case VIDIOCSPICT: { struct video_picture vp; - + if (copy_from_user(&vp, user_arg, sizeof(vp))) { retval = -EFAULT; break; } - + DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth, vp.palette); @@ -655,7 +655,7 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign } DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height); - + if ( vw.width != 320 || vw.height != 240 ) retval = -EFAULT; @@ -809,12 +809,12 @@ vicam_open(struct inode *inode, struct file *file) cam->needsDummyRead = 1; cam->open_count++; - file->private_data = cam; - + file->private_data = cam; + return 0; } -static int +static int vicam_close(struct inode *inode, struct file *file) { struct vicam_camera *cam = file->private_data; @@ -1187,7 +1187,7 @@ vicam_create_proc_entry(struct vicam_camera *cam) if ( !cam->proc_dir ) return; // FIXME: We should probably return an error here - + ent = create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR, cam->proc_dir); if (ent) { @@ -1282,7 +1282,7 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) const struct usb_host_interface *interface; const struct usb_endpoint_descriptor *endpoint; struct vicam_camera *cam; - + printk(KERN_INFO "ViCam based webcam connected\n"); interface = intf->cur_altsetting; @@ -1331,7 +1331,7 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor); usb_set_intfdata (intf, cam); - + return 0; } diff --git a/drivers/media/video/videocodec.h b/drivers/media/video/videocodec.h index b1239ac7f371..8c233720b6a5 100644 --- a/drivers/media/video/videocodec.h +++ b/drivers/media/video/videocodec.h @@ -57,7 +57,7 @@ therfor they may not be initialized. The other fuctions are just for convenience, as they are for sure used by - most/all of the codecs. The last ones may be ommited, too. + most/all of the codecs. The last ones may be ommited, too. See the structure declaration below for more information and which data has to be set up for the master and the slave. @@ -75,52 +75,52 @@ /* ========================================== */ /* - ==== master setup ==== + ==== master setup ==== name -> name of the device structure for reference and debugging master_data -> data ref. for the master (e.g. the zr36055,57,67) readreg -> ref. to read-fn from register (setup by master, used by slave) writereg -> ref. to write-fn to register (setup by master, used by slave) - this two functions do the lowlevel I/O job + this two functions do the lowlevel I/O job - ==== slave functionality setup ==== - slave_data -> data ref. for the slave (e.g. the zr36050,60) + ==== slave functionality setup ==== + slave_data -> data ref. for the slave (e.g. the zr36050,60) check -> fn-ref. checks availability of an device, returns -EIO on failure or - the type on success - this makes espcecially sense if a driver module supports more than - one codec which may be quite similar to access, nevertheless it - is good for a first functionality check + the type on success + this makes espcecially sense if a driver module supports more than + one codec which may be quite similar to access, nevertheless it + is good for a first functionality check - -- main functions you always need for compression/decompression -- + -- main functions you always need for compression/decompression -- set_mode -> this fn-ref. resets the entire codec, and sets up the mode - with the last defined norm/size (or device default if not - available) - it returns 0 if the mode is possible + with the last defined norm/size (or device default if not + available) - it returns 0 if the mode is possible set_size -> this fn-ref. sets the norm and image size for - compression/decompression (returns 0 on success) - the norm param is defined in videodev.h (VIDEO_MODE_*) + compression/decompression (returns 0 on success) + the norm param is defined in videodev.h (VIDEO_MODE_*) additional setup may be available, too - but the codec should work with - some default values even without this + some default values even without this - set_data -> sets device-specific data (tables, quality etc.) - get_data -> query device-specific data (tables, quality etc.) + set_data -> sets device-specific data (tables, quality etc.) + get_data -> query device-specific data (tables, quality etc.) - if the device delivers interrupts, they may be setup/handled here - setup_interrupt -> codec irq setup (not needed for 36050/60) - handle_interrupt -> codec irq handling (not needed for 36050/60) + if the device delivers interrupts, they may be setup/handled here + setup_interrupt -> codec irq setup (not needed for 36050/60) + handle_interrupt -> codec irq handling (not needed for 36050/60) - if the device delivers pictures, they may be handled here - put_image -> puts image data to the codec (not needed for 36050/60) - get_image -> gets image data from the codec (not needed for 36050/60) - the calls include frame numbers and flags (even/odd/...) - if needed and a flag which allows blocking until its ready + if the device delivers pictures, they may be handled here + put_image -> puts image data to the codec (not needed for 36050/60) + get_image -> gets image data from the codec (not needed for 36050/60) + the calls include frame numbers and flags (even/odd/...) + if needed and a flag which allows blocking until its ready */ /* ============== */ /* user interface */ /* ============== */ -/* +/* Currently there is only a information display planned, as the layer is not visible for the user space at all. diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 0229819d0aac..a8c101494cf5 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -1555,12 +1555,12 @@ static void vino_update_line_size(struct vino_channel_settings *vcs) unsigned int w = vcs->clipping.right - vcs->clipping.left; unsigned int d = vcs->decimation; unsigned int bpp = vino_data_formats[vcs->data_format].bpp; - unsigned int lsize; + unsigned int lsize; dprintk("update_line_size(): before: w = %d, d = %d, " "line_size = %d\n", w, d, vcs->line_size); - /* line size must be multiple of 8 bytes */ + /* line size must be multiple of 8 bytes */ lsize = (bpp * (w / d)) & ~7; w = (lsize / bpp) * d; diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 4cd579967487..40b205b91481 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -1,4 +1,4 @@ -/* +/* * vpx3220a, vpx3216b & vpx3214c video decoder driver version 0.0.1 * * Copyright (C) 2001 Laurent Pinchart @@ -176,8 +176,8 @@ vpx3220_write_block (struct i2c_client *client, static int vpx3220_write_fp_block (struct i2c_client *client, - const u16 *data, - unsigned int len) + const u16 *data, + unsigned int len) { u8 reg; int ret = 0; @@ -316,7 +316,7 @@ vpx3220_command (struct i2c_client *client, vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1); switch (decoder->norm) { - + case VIDEO_MODE_NTSC: vpx3220_write_fp_block(client, init_ntsc, sizeof(init_ntsc) >> 1); @@ -324,7 +324,7 @@ vpx3220_command (struct i2c_client *client, case VIDEO_MODE_PAL: vpx3220_write_fp_block(client, init_pal, - sizeof(init_pal) >> 1); + sizeof(init_pal) >> 1); break; case VIDEO_MODE_SECAM: vpx3220_write_fp_block(client, init_secam, @@ -332,10 +332,10 @@ vpx3220_command (struct i2c_client *client, break; default: vpx3220_write_fp_block(client, init_pal, - sizeof(init_pal) >> 1); + sizeof(init_pal) >> 1); break; } - } + } break; case DECODER_DUMP: @@ -411,7 +411,7 @@ vpx3220_command (struct i2c_client *client, /* Here we back up the input selection because it gets overwritten when we fill the registers with the - choosen video norm */ + choosen video norm */ temp_input = vpx3220_fp_read(client, 0xf2); dprintk(1, KERN_DEBUG "%s: DECODER_SET_NORM %d\n", @@ -578,7 +578,7 @@ static unsigned short normal_i2c[] = }; static unsigned short ignore = I2C_CLIENT_END; - + static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = &ignore, @@ -661,7 +661,7 @@ vpx3220_detect_client (struct i2c_adapter *adapter, break; default: dprintk(1, - KERN_INFO + KERN_INFO "%s: Wrong part number (0x%04x)\n", __func__, pn); kfree(client); diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index b7b0afffd214..80ef8a1b8f63 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -26,7 +26,7 @@ Does any other model using the w9966 interface chip exist ? Todo: - + *Add a working EPP mode, since DMA ECP read isn't implemented in the parport drivers. (That's why it's so sloow) @@ -47,9 +47,9 @@ *Probably some bugs that I don't know of Please support me by sending feedback! - + Changes: - + Alan Cox: Removed RGB mode for kernel merge, added THIS_MODULE and owner support for newer module locks */ @@ -204,7 +204,7 @@ static struct video_device w9966_template = { */ -// Set camera phase flags, so we know what to uninit when terminating +// Set camera phase flags, so we know what to uninit when terminating static inline void w9966_setState(struct w9966_dev* cam, int mask, int val) { cam->dev_state = (cam->dev_state & ~mask) ^ val; @@ -233,7 +233,7 @@ static inline void w9966_pdev_release(struct w9966_dev* cam) parport_release(cam->pdev); w9966_setState(cam, W9966_STATE_CLAIMED, 0); } - + // Read register from W9966 interface-chip // Expects a claimed pdev // -1 on error, else register data (byte) @@ -242,7 +242,7 @@ static int w9966_rReg(struct w9966_dev* cam, int reg) // ECP, read, regtransfer, REG, REG, REG, REG, REG const unsigned char addr = 0x80 | (reg & 0x1f); unsigned char val; - + if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0) return -1; if (parport_write(cam->pport, &addr, 1) != 1) @@ -263,7 +263,7 @@ static int w9966_wReg(struct w9966_dev* cam, int reg, int data) // ECP, write, regtransfer, REG, REG, REG, REG, REG const unsigned char addr = 0xc0 | (reg & 0x1f); const unsigned char val = data; - + if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0) return -1; if (parport_write(cam->pport, &addr, 1) != 1) @@ -284,7 +284,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) { if (cam->dev_state != 0) return -1; - + cam->pport = port; cam->brightness = 128; cam->contrast = 64; @@ -302,7 +302,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) cam->ppmode = IEEE1284_MODE_EPP; else cam->ppmode = IEEE1284_MODE_ECP; - break; + break; case 1: // hw- or sw-ecp cam->ppmode = IEEE1284_MODE_ECP; break; @@ -310,7 +310,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) cam->ppmode = IEEE1284_MODE_EPP; break; } - + // Tell the parport driver that we exists cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL); if (cam->pdev == NULL) { @@ -320,7 +320,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) w9966_setState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV); w9966_pdev_claim(cam); - + // Setup a default capture mode if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) { DPRINTF("w9966_setup() failed.\n"); @@ -333,11 +333,11 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); cam->vdev.priv = cam; - if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) + if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) return -1; - + w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV); - + // All ok printk( "w9966cf: Found and initialized a webcam on %s.\n", @@ -391,7 +391,7 @@ static int w9966_findlen(int near, int size, int maxlen) // Only continue as long as we keep getting better values if (err > besterr) break; - + besterr = err; bestlen = len; } @@ -399,7 +399,7 @@ static int w9966_findlen(int near, int size, int maxlen) return bestlen; } -// Modify capture window (if necessary) +// Modify capture window (if necessary) // and calculate downscaling // Return -1 on error static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsigned char* factor) @@ -407,7 +407,7 @@ static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsig int maxlen = max - min; int len = *end - *beg + 1; int newlen = w9966_findlen(len, size, maxlen); - int err = newlen - len; + int err = newlen - len; // Check for bad format if (newlen > maxlen || newlen < size) @@ -452,8 +452,8 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0 }; - - + + if (w*h*2 > W9966_SRAMSIZE) { DPRINTF("capture window exceeds SRAM size!.\n"); @@ -469,9 +469,9 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in cam->width = w; cam->height = h; - enh_s = 0; + enh_s = 0; enh_e = w*h*2; - + // Modify capture window if necessary and calculate downscaling if ( w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 || @@ -482,14 +482,14 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in "%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n", w, h, x1, x2, y1, y2, scale_x&~0x80, scale_y&~0x80 ); - + // Setup registers regs[0x00] = 0x00; // Set normal operation regs[0x01] = 0x18; // Capture mode regs[0x02] = scale_y; // V-scaling regs[0x03] = scale_x; // H-scaling - - // Capture window + + // Capture window regs[0x04] = (x1 & 0x0ff); // X-start (8 low bits) regs[0x05] = (x1 & 0x300)>>8; // X-start (2 high bits) regs[0x06] = (y1 & 0x0ff); // Y-start (8 low bits) @@ -499,7 +499,7 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in regs[0x0a] = (y2 & 0x0ff); // Y-end (8 low bits) regs[0x0c] = W9966_SRAMID; // SRAM-banks (1x 128kb) - + // Enhancement layer regs[0x0d] = (enh_s& 0x000ff); // Enh. start (0-7) regs[0x0e] = (enh_s& 0x0ff00)>>8; // Enh. start (8-15) @@ -515,7 +515,7 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in regs[0x19] = 0xff; // I/O port direction control regs[0x1a] = 0xff; // I/O port data register regs[0x1b] = 0x10; // ??? - + // SAA7111 chip settings saa7111_regs[0x0a] = cam->brightness; saa7111_regs[0x0b] = cam->contrast; @@ -551,7 +551,7 @@ static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state) cam->i2c_state |= W9966_I2C_W_DATA; else cam->i2c_state &= ~W9966_I2C_W_DATA; - + w9966_wReg(cam, 0x18, cam->i2c_state); udelay(5); } @@ -577,7 +577,7 @@ static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state) w9966_wReg(cam, 0x18, cam->i2c_state); udelay(5); - + // we go to high, we also expect the peripheral to ack. if (state) { timeout = jiffies + 100; @@ -607,16 +607,16 @@ static int w9966_i2c_wbyte(struct w9966_dev* cam, int data) w9966_i2c_setsda(cam, (data >> i) & 0x01); if (w9966_i2c_setscl(cam, 1) == -1) - return -1; + return -1; w9966_i2c_setscl(cam, 0); } w9966_i2c_setsda(cam, 1); - + if (w9966_i2c_setscl(cam, 1) == -1) return -1; w9966_i2c_setscl(cam, 0); - + return 0; } @@ -626,8 +626,8 @@ static int w9966_i2c_wbyte(struct w9966_dev* cam, int data) static int w9966_i2c_rbyte(struct w9966_dev* cam) { unsigned char data = 0x00; - int i; - + int i; + w9966_i2c_setsda(cam, 1); for (i = 0; i < 8; i++) @@ -637,7 +637,7 @@ static int w9966_i2c_rbyte(struct w9966_dev* cam) data = data << 1; if (w9966_i2c_getsda(cam)) data |= 0x01; - + w9966_i2c_setscl(cam, 0); } return data; @@ -673,11 +673,11 @@ static int w9966_rReg_i2c(struct w9966_dev* cam, int reg) return -1; w9966_i2c_setsda(cam, 0); - + if (w9966_i2c_setscl(cam, 1) == -1) return -1; w9966_i2c_setsda(cam, 1); - + return data; } #endif @@ -699,7 +699,7 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data) w9966_i2c_setsda(cam, 0); if (w9966_i2c_setscl(cam, 1) == -1) return -1; - + w9966_i2c_setsda(cam, 1); return 0; @@ -714,7 +714,7 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, { struct video_device *vdev = video_devdata(file); struct w9966_dev *cam = vdev->priv; - + switch(cmd) { case VIDIOCGCAP: @@ -790,14 +790,14 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, struct video_picture *vpic = arg; if (vpic->depth != 16 || vpic->palette != VIDEO_PALETTE_YUV422) return -EINVAL; - + cam->brightness = vpic->brightness >> 8; cam->hue = (vpic->hue >> 8) - 128; cam->color = vpic->colour >> 9; cam->contrast = vpic->contrast >> 9; w9966_pdev_claim(cam); - + if ( w9966_wReg_i2c(cam, 0x0a, cam->brightness) == -1 || w9966_wReg_i2c(cam, 0x0b, cam->contrast) == -1 || @@ -807,7 +807,7 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, w9966_pdev_release(cam); return -EIO; } - + w9966_pdev_release(cam); return 0; } @@ -815,13 +815,13 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, { int ret; struct video_window *vwin = arg; - + if (vwin->flags != 0) return -EINVAL; if (vwin->clipcount != 0) return -EINVAL; if (vwin->width < 2 || vwin->width > W9966_WND_MAX_W) - return -EINVAL; + return -EINVAL; if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H) return -EINVAL; @@ -829,12 +829,12 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, w9966_pdev_claim(cam); ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height); w9966_pdev_release(cam); - + if (ret != 0) { DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n"); return -EIO; } - + return 0; } case VIDIOCGWIN: @@ -846,7 +846,7 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, return 0; } // Unimplemented - case VIDIOCCAPTURE: + case VIDIOCCAPTURE: case VIDIOCGFBUF: case VIDIOCSFBUF: case VIDIOCKEY: @@ -877,17 +877,17 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, unsigned char __user *dest = (unsigned char __user *)buf; unsigned long dleft = count; unsigned char *tbuf; - + // Why would anyone want more than this?? if (count > cam->width * cam->height * 2) return -EINVAL; - + w9966_pdev_claim(cam); w9966_wReg(cam, 0x00, 0x02); // Reset ECP-FIFO buffer w9966_wReg(cam, 0x00, 0x00); // Return to normal operation w9966_wReg(cam, 0x01, 0x98); // Enable capture - // write special capture-addr and negotiate into data transfer + // write special capture-addr and negotiate into data transfer if ( (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0 )|| (parport_write(cam->pport, &addr, 1) != 1 )|| @@ -906,7 +906,7 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, while(dleft > 0) { unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft; - + if (parport_read(cam->pport, tbuf, tsize) < tsize) { count = -EFAULT; goto out; @@ -933,7 +933,7 @@ out: static void w9966_attach(struct parport *port) { int i; - + for (i = 0; i < W9966_MAXCAMS; i++) { if (w9966_cams[i].dev_state != 0) // Cam is already assigned diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index b57dec3782e0..20f211b55ad4 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -71,39 +71,39 @@ MODULE_SUPPORTED_DEVICE("Video"); static int ovmod_load = W9968CF_OVMOD_LOAD; static unsigned short simcams = W9968CF_SIMCAMS; static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/ -static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_PACKET_SIZE}; -static unsigned short max_buffers[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_BUFFERS}; -static int double_buffer[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_DOUBLE_BUFFER}; +static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_PACKET_SIZE}; +static unsigned short max_buffers[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_BUFFERS}; +static int double_buffer[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_DOUBLE_BUFFER}; static int clamping[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLAMPING}; -static unsigned short filter_type[]= {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_FILTER_TYPE}; +static unsigned short filter_type[]= {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_FILTER_TYPE}; static int largeview[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_LARGEVIEW}; -static unsigned short decompression[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_DECOMPRESSION}; +static unsigned short decompression[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_DECOMPRESSION}; static int upscaling[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_UPSCALING}; static unsigned short force_palette[] = {[0 ... W9968CF_MAX_DEVICES-1] = 0}; static int force_rgb[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_FORCE_RGB}; static int autobright[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOBRIGHT}; static int autoexp[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOEXP}; -static unsigned short lightfreq[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_LIGHTFREQ}; +static unsigned short lightfreq[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_LIGHTFREQ}; static int bandingfilter[] = {[0 ... W9968CF_MAX_DEVICES-1]= - W9968CF_BANDINGFILTER}; + W9968CF_BANDINGFILTER}; static short clockdiv[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLOCKDIV}; static int backlight[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_BACKLIGHT}; static int mirror[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_MIRROR}; static int monochrome[] = {[0 ... W9968CF_MAX_DEVICES-1]=W9968CF_MONOCHROME}; -static unsigned int brightness[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_BRIGHTNESS}; +static unsigned int brightness[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_BRIGHTNESS}; static unsigned int hue[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_HUE}; static unsigned int colour[]={[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_COLOUR}; -static unsigned int contrast[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_CONTRAST}; -static unsigned int whiteness[] = {[0 ... W9968CF_MAX_DEVICES-1] = - W9968CF_WHITENESS}; +static unsigned int contrast[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_CONTRAST}; +static unsigned int whiteness[] = {[0 ... W9968CF_MAX_DEVICES-1] = + W9968CF_WHITENESS}; #ifdef W9968CF_DEBUG static unsigned short debug = W9968CF_DEBUG_LEVEL; static int specific_debug = W9968CF_SPECIFIC_DEBUG; @@ -145,251 +145,251 @@ module_param(specific_debug, bool, 0644); #endif #ifdef CONFIG_KMOD -MODULE_PARM_DESC(ovmod_load, - "\n<0|1> Automatic 'ovcamchip' module loading." - "\n0 disabled, 1 enabled." - "\nIf enabled,'insmod' searches for the required 'ovcamchip'" - "\nmodule in the system, according to its configuration, and" - "\nattempts to load that module automatically. This action is" - "\nperformed once as soon as the 'w9968cf' module is loaded" - "\ninto memory." - "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"." - "\n"); +MODULE_PARM_DESC(ovmod_load, + "\n<0|1> Automatic 'ovcamchip' module loading." + "\n0 disabled, 1 enabled." + "\nIf enabled,'insmod' searches for the required 'ovcamchip'" + "\nmodule in the system, according to its configuration, and" + "\nattempts to load that module automatically. This action is" + "\nperformed once as soon as the 'w9968cf' module is loaded" + "\ninto memory." + "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"." + "\n"); #endif -MODULE_PARM_DESC(simcams, - "\n Number of cameras allowed to stream simultaneously." - "\nn may vary from 0 to " - __MODULE_STRING(W9968CF_MAX_DEVICES)"." - "\nDefault value is "__MODULE_STRING(W9968CF_SIMCAMS)"." - "\n"); +MODULE_PARM_DESC(simcams, + "\n Number of cameras allowed to stream simultaneously." + "\nn may vary from 0 to " + __MODULE_STRING(W9968CF_MAX_DEVICES)"." + "\nDefault value is "__MODULE_STRING(W9968CF_SIMCAMS)"." + "\n"); MODULE_PARM_DESC(video_nr, - "\n<-1|n[,...]> Specify V4L minor mode number." - "\n -1 = use next available (default)" - "\n n = use minor number n (integer >= 0)" - "\nYou can specify up to "__MODULE_STRING(W9968CF_MAX_DEVICES) - " cameras this way." - "\nFor example:" - "\nvideo_nr=-1,2,-1 would assign minor number 2 to" - "\nthe second camera and use auto for the first" - "\none and for every other camera." - "\n"); + "\n<-1|n[,...]> Specify V4L minor mode number." + "\n -1 = use next available (default)" + "\n n = use minor number n (integer >= 0)" + "\nYou can specify up to "__MODULE_STRING(W9968CF_MAX_DEVICES) + " cameras this way." + "\nFor example:" + "\nvideo_nr=-1,2,-1 would assign minor number 2 to" + "\nthe second camera and use auto for the first" + "\none and for every other camera." + "\n"); MODULE_PARM_DESC(packet_size, - "\n Specify the maximum data payload" - "\nsize in bytes for alternate settings, for each device." - "\nn is scaled between 63 and 1023 " - "(default is "__MODULE_STRING(W9968CF_PACKET_SIZE)")." - "\n"); + "\n Specify the maximum data payload" + "\nsize in bytes for alternate settings, for each device." + "\nn is scaled between 63 and 1023 " + "(default is "__MODULE_STRING(W9968CF_PACKET_SIZE)")." + "\n"); MODULE_PARM_DESC(max_buffers, - "\n For advanced users." - "\nSpecify the maximum number of video frame buffers" - "\nto allocate for each device, from 2 to " - __MODULE_STRING(W9968CF_MAX_BUFFERS) - ". (default is "__MODULE_STRING(W9968CF_BUFFERS)")." - "\n"); -MODULE_PARM_DESC(double_buffer, - "\n<0|1[,...]> " - "Hardware double buffering: 0 disabled, 1 enabled." - "\nIt should be enabled if you want smooth video output: if" - "\nyou obtain out of sync. video, disable it, or try to" - "\ndecrease the 'clockdiv' module parameter value." - "\nDefault value is "__MODULE_STRING(W9968CF_DOUBLE_BUFFER) - " for every device." - "\n"); -MODULE_PARM_DESC(clamping, - "\n<0|1[,...]> Video data clamping: 0 disabled, 1 enabled." - "\nDefault value is "__MODULE_STRING(W9968CF_CLAMPING) - " for every device." - "\n"); -MODULE_PARM_DESC(filter_type, - "\n<0|1|2[,...]> Video filter type." - "\n0 none, 1 (1-2-1) 3-tap filter, " - "2 (2-3-6-3-2) 5-tap filter." - "\nDefault value is "__MODULE_STRING(W9968CF_FILTER_TYPE) - " for every device." - "\nThe filter is used to reduce noise and aliasing artifacts" - "\nproduced by the CCD or CMOS image sensor, and the scaling" - " process." - "\n"); -MODULE_PARM_DESC(largeview, - "\n<0|1[,...]> Large view: 0 disabled, 1 enabled." - "\nDefault value is "__MODULE_STRING(W9968CF_LARGEVIEW) - " for every device." - "\n"); -MODULE_PARM_DESC(upscaling, - "\n<0|1[,...]> Software scaling (for non-compressed video):" - "\n0 disabled, 1 enabled." - "\nDisable it if you have a slow CPU or you don't have" - " enough memory." - "\nDefault value is "__MODULE_STRING(W9968CF_UPSCALING) - " for every device." - "\nIf 'w9968cf-vpp' is not present, this parameter is" - " set to 0." - "\n"); + "\n For advanced users." + "\nSpecify the maximum number of video frame buffers" + "\nto allocate for each device, from 2 to " + __MODULE_STRING(W9968CF_MAX_BUFFERS) + ". (default is "__MODULE_STRING(W9968CF_BUFFERS)")." + "\n"); +MODULE_PARM_DESC(double_buffer, + "\n<0|1[,...]> " + "Hardware double buffering: 0 disabled, 1 enabled." + "\nIt should be enabled if you want smooth video output: if" + "\nyou obtain out of sync. video, disable it, or try to" + "\ndecrease the 'clockdiv' module parameter value." + "\nDefault value is "__MODULE_STRING(W9968CF_DOUBLE_BUFFER) + " for every device." + "\n"); +MODULE_PARM_DESC(clamping, + "\n<0|1[,...]> Video data clamping: 0 disabled, 1 enabled." + "\nDefault value is "__MODULE_STRING(W9968CF_CLAMPING) + " for every device." + "\n"); +MODULE_PARM_DESC(filter_type, + "\n<0|1|2[,...]> Video filter type." + "\n0 none, 1 (1-2-1) 3-tap filter, " + "2 (2-3-6-3-2) 5-tap filter." + "\nDefault value is "__MODULE_STRING(W9968CF_FILTER_TYPE) + " for every device." + "\nThe filter is used to reduce noise and aliasing artifacts" + "\nproduced by the CCD or CMOS image sensor, and the scaling" + " process." + "\n"); +MODULE_PARM_DESC(largeview, + "\n<0|1[,...]> Large view: 0 disabled, 1 enabled." + "\nDefault value is "__MODULE_STRING(W9968CF_LARGEVIEW) + " for every device." + "\n"); +MODULE_PARM_DESC(upscaling, + "\n<0|1[,...]> Software scaling (for non-compressed video):" + "\n0 disabled, 1 enabled." + "\nDisable it if you have a slow CPU or you don't have" + " enough memory." + "\nDefault value is "__MODULE_STRING(W9968CF_UPSCALING) + " for every device." + "\nIf 'w9968cf-vpp' is not present, this parameter is" + " set to 0." + "\n"); MODULE_PARM_DESC(decompression, - "\n<0|1|2[,...]> Software video decompression:" - "\n- 0 disables decompression (doesn't allow formats needing" - " decompression)" - "\n- 1 forces decompression (allows formats needing" - " decompression only);" - "\n- 2 allows any permitted formats." - "\nFormats supporting compressed video are YUV422P and" - " YUV420P/YUV420 " - "\nin any resolutions where both width and height are " - "a multiple of 16." - "\nDefault value is "__MODULE_STRING(W9968CF_DECOMPRESSION) - " for every device." - "\nIf 'w9968cf-vpp' is not present, forcing decompression is " - "\nnot allowed; in this case this parameter is set to 2." - "\n"); + "\n<0|1|2[,...]> Software video decompression:" + "\n- 0 disables decompression (doesn't allow formats needing" + " decompression)" + "\n- 1 forces decompression (allows formats needing" + " decompression only);" + "\n- 2 allows any permitted formats." + "\nFormats supporting compressed video are YUV422P and" + " YUV420P/YUV420 " + "\nin any resolutions where both width and height are " + "a multiple of 16." + "\nDefault value is "__MODULE_STRING(W9968CF_DECOMPRESSION) + " for every device." + "\nIf 'w9968cf-vpp' is not present, forcing decompression is " + "\nnot allowed; in this case this parameter is set to 2." + "\n"); MODULE_PARM_DESC(force_palette, - "\n<0" - "|" __MODULE_STRING(VIDEO_PALETTE_UYVY) - "|" __MODULE_STRING(VIDEO_PALETTE_YUV420) - "|" __MODULE_STRING(VIDEO_PALETTE_YUV422P) - "|" __MODULE_STRING(VIDEO_PALETTE_YUV420P) - "|" __MODULE_STRING(VIDEO_PALETTE_YUYV) - "|" __MODULE_STRING(VIDEO_PALETTE_YUV422) - "|" __MODULE_STRING(VIDEO_PALETTE_GREY) - "|" __MODULE_STRING(VIDEO_PALETTE_RGB555) - "|" __MODULE_STRING(VIDEO_PALETTE_RGB565) - "|" __MODULE_STRING(VIDEO_PALETTE_RGB24) - "|" __MODULE_STRING(VIDEO_PALETTE_RGB32) - "[,...]>" - " Force picture palette." - "\nIn order:" - "\n- 0 allows any of the following formats:" - "\n- UYVY 16 bpp - Original video, compression disabled" - "\n- YUV420 12 bpp - Original video, compression enabled" - "\n- YUV422P 16 bpp - Original video, compression enabled" - "\n- YUV420P 12 bpp - Original video, compression enabled" - "\n- YUVY 16 bpp - Software conversion from UYVY" - "\n- YUV422 16 bpp - Software conversion from UYVY" - "\n- GREY 8 bpp - Software conversion from UYVY" - "\n- RGB555 16 bpp - Software conversion from UYVY" - "\n- RGB565 16 bpp - Software conversion from UYVY" - "\n- RGB24 24 bpp - Software conversion from UYVY" - "\n- RGB32 32 bpp - Software conversion from UYVY" - "\nWhen not 0, this parameter will override 'decompression'." - "\nDefault value is 0 for every device." - "\nInitial palette is " - __MODULE_STRING(W9968CF_PALETTE_DECOMP_ON)"." - "\nIf 'w9968cf-vpp' is not present, this parameter is" - " set to 9 (UYVY)." - "\n"); -MODULE_PARM_DESC(force_rgb, - "\n<0|1[,...]> Read RGB video data instead of BGR:" - "\n 1 = use RGB component ordering." - "\n 0 = use BGR component ordering." - "\nThis parameter has effect when using RGBX palettes only." - "\nDefault value is "__MODULE_STRING(W9968CF_FORCE_RGB) - " for every device." - "\n"); + "\n<0" + "|" __MODULE_STRING(VIDEO_PALETTE_UYVY) + "|" __MODULE_STRING(VIDEO_PALETTE_YUV420) + "|" __MODULE_STRING(VIDEO_PALETTE_YUV422P) + "|" __MODULE_STRING(VIDEO_PALETTE_YUV420P) + "|" __MODULE_STRING(VIDEO_PALETTE_YUYV) + "|" __MODULE_STRING(VIDEO_PALETTE_YUV422) + "|" __MODULE_STRING(VIDEO_PALETTE_GREY) + "|" __MODULE_STRING(VIDEO_PALETTE_RGB555) + "|" __MODULE_STRING(VIDEO_PALETTE_RGB565) + "|" __MODULE_STRING(VIDEO_PALETTE_RGB24) + "|" __MODULE_STRING(VIDEO_PALETTE_RGB32) + "[,...]>" + " Force picture palette." + "\nIn order:" + "\n- 0 allows any of the following formats:" + "\n- UYVY 16 bpp - Original video, compression disabled" + "\n- YUV420 12 bpp - Original video, compression enabled" + "\n- YUV422P 16 bpp - Original video, compression enabled" + "\n- YUV420P 12 bpp - Original video, compression enabled" + "\n- YUVY 16 bpp - Software conversion from UYVY" + "\n- YUV422 16 bpp - Software conversion from UYVY" + "\n- GREY 8 bpp - Software conversion from UYVY" + "\n- RGB555 16 bpp - Software conversion from UYVY" + "\n- RGB565 16 bpp - Software conversion from UYVY" + "\n- RGB24 24 bpp - Software conversion from UYVY" + "\n- RGB32 32 bpp - Software conversion from UYVY" + "\nWhen not 0, this parameter will override 'decompression'." + "\nDefault value is 0 for every device." + "\nInitial palette is " + __MODULE_STRING(W9968CF_PALETTE_DECOMP_ON)"." + "\nIf 'w9968cf-vpp' is not present, this parameter is" + " set to 9 (UYVY)." + "\n"); +MODULE_PARM_DESC(force_rgb, + "\n<0|1[,...]> Read RGB video data instead of BGR:" + "\n 1 = use RGB component ordering." + "\n 0 = use BGR component ordering." + "\nThis parameter has effect when using RGBX palettes only." + "\nDefault value is "__MODULE_STRING(W9968CF_FORCE_RGB) + " for every device." + "\n"); MODULE_PARM_DESC(autobright, - "\n<0|1[,...]> Image sensor automatically changes brightness:" - "\n 0 = no, 1 = yes" - "\nDefault value is "__MODULE_STRING(W9968CF_AUTOBRIGHT) - " for every device." - "\n"); + "\n<0|1[,...]> Image sensor automatically changes brightness:" + "\n 0 = no, 1 = yes" + "\nDefault value is "__MODULE_STRING(W9968CF_AUTOBRIGHT) + " for every device." + "\n"); MODULE_PARM_DESC(autoexp, - "\n<0|1[,...]> Image sensor automatically changes exposure:" - "\n 0 = no, 1 = yes" - "\nDefault value is "__MODULE_STRING(W9968CF_AUTOEXP) - " for every device." - "\n"); + "\n<0|1[,...]> Image sensor automatically changes exposure:" + "\n 0 = no, 1 = yes" + "\nDefault value is "__MODULE_STRING(W9968CF_AUTOEXP) + " for every device." + "\n"); MODULE_PARM_DESC(lightfreq, - "\n<50|60[,...]> Light frequency in Hz:" - "\n 50 for European and Asian lighting," - " 60 for American lighting." - "\nDefault value is "__MODULE_STRING(W9968CF_LIGHTFREQ) - " for every device." - "\n"); + "\n<50|60[,...]> Light frequency in Hz:" + "\n 50 for European and Asian lighting," + " 60 for American lighting." + "\nDefault value is "__MODULE_STRING(W9968CF_LIGHTFREQ) + " for every device." + "\n"); MODULE_PARM_DESC(bandingfilter, - "\n<0|1[,...]> Banding filter to reduce effects of" - " fluorescent lighting:" - "\n 0 disabled, 1 enabled." - "\nThis filter tries to reduce the pattern of horizontal" - "\nlight/dark bands caused by some (usually fluorescent)" - " lighting." - "\nDefault value is "__MODULE_STRING(W9968CF_BANDINGFILTER) - " for every device." - "\n"); + "\n<0|1[,...]> Banding filter to reduce effects of" + " fluorescent lighting:" + "\n 0 disabled, 1 enabled." + "\nThis filter tries to reduce the pattern of horizontal" + "\nlight/dark bands caused by some (usually fluorescent)" + " lighting." + "\nDefault value is "__MODULE_STRING(W9968CF_BANDINGFILTER) + " for every device." + "\n"); MODULE_PARM_DESC(clockdiv, - "\n<-1|n[,...]> " - "Force pixel clock divisor to a specific value (for experts):" - "\n n may vary from 0 to 127." - "\n -1 for automatic value." - "\nSee also the 'double_buffer' module parameter." - "\nDefault value is "__MODULE_STRING(W9968CF_CLOCKDIV) - " for every device." - "\n"); + "\n<-1|n[,...]> " + "Force pixel clock divisor to a specific value (for experts):" + "\n n may vary from 0 to 127." + "\n -1 for automatic value." + "\nSee also the 'double_buffer' module parameter." + "\nDefault value is "__MODULE_STRING(W9968CF_CLOCKDIV) + " for every device." + "\n"); MODULE_PARM_DESC(backlight, - "\n<0|1[,...]> Objects are lit from behind:" - "\n 0 = no, 1 = yes" - "\nDefault value is "__MODULE_STRING(W9968CF_BACKLIGHT) - " for every device." - "\n"); + "\n<0|1[,...]> Objects are lit from behind:" + "\n 0 = no, 1 = yes" + "\nDefault value is "__MODULE_STRING(W9968CF_BACKLIGHT) + " for every device." + "\n"); MODULE_PARM_DESC(mirror, - "\n<0|1[,...]> Reverse image horizontally:" - "\n 0 = no, 1 = yes" - "\nDefault value is "__MODULE_STRING(W9968CF_MIRROR) - " for every device." - "\n"); + "\n<0|1[,...]> Reverse image horizontally:" + "\n 0 = no, 1 = yes" + "\nDefault value is "__MODULE_STRING(W9968CF_MIRROR) + " for every device." + "\n"); MODULE_PARM_DESC(monochrome, - "\n<0|1[,...]> Use image sensor as monochrome sensor:" - "\n 0 = no, 1 = yes" - "\nNot all the sensors support monochrome color." - "\nDefault value is "__MODULE_STRING(W9968CF_MONOCHROME) - " for every device." - "\n"); -MODULE_PARM_DESC(brightness, - "\n Set picture brightness (0-65535)." - "\nDefault value is "__MODULE_STRING(W9968CF_BRIGHTNESS) - " for every device." - "\nThis parameter has no effect if 'autobright' is enabled." - "\n"); -MODULE_PARM_DESC(hue, - "\n Set picture hue (0-65535)." - "\nDefault value is "__MODULE_STRING(W9968CF_HUE) - " for every device." - "\n"); -MODULE_PARM_DESC(colour, - "\n Set picture saturation (0-65535)." - "\nDefault value is "__MODULE_STRING(W9968CF_COLOUR) - " for every device." - "\n"); -MODULE_PARM_DESC(contrast, - "\n Set picture contrast (0-65535)." - "\nDefault value is "__MODULE_STRING(W9968CF_CONTRAST) - " for every device." - "\n"); -MODULE_PARM_DESC(whiteness, - "\n Set picture whiteness (0-65535)." - "\nDefault value is "__MODULE_STRING(W9968CF_WHITENESS) - " for every device." - "\n"); + "\n<0|1[,...]> Use image sensor as monochrome sensor:" + "\n 0 = no, 1 = yes" + "\nNot all the sensors support monochrome color." + "\nDefault value is "__MODULE_STRING(W9968CF_MONOCHROME) + " for every device." + "\n"); +MODULE_PARM_DESC(brightness, + "\n Set picture brightness (0-65535)." + "\nDefault value is "__MODULE_STRING(W9968CF_BRIGHTNESS) + " for every device." + "\nThis parameter has no effect if 'autobright' is enabled." + "\n"); +MODULE_PARM_DESC(hue, + "\n Set picture hue (0-65535)." + "\nDefault value is "__MODULE_STRING(W9968CF_HUE) + " for every device." + "\n"); +MODULE_PARM_DESC(colour, + "\n Set picture saturation (0-65535)." + "\nDefault value is "__MODULE_STRING(W9968CF_COLOUR) + " for every device." + "\n"); +MODULE_PARM_DESC(contrast, + "\n Set picture contrast (0-65535)." + "\nDefault value is "__MODULE_STRING(W9968CF_CONTRAST) + " for every device." + "\n"); +MODULE_PARM_DESC(whiteness, + "\n Set picture whiteness (0-65535)." + "\nDefault value is "__MODULE_STRING(W9968CF_WHITENESS) + " for every device." + "\n"); #ifdef W9968CF_DEBUG MODULE_PARM_DESC(debug, - "\n Debugging information level, from 0 to 6:" - "\n0 = none (use carefully)" - "\n1 = critical errors" - "\n2 = significant informations" - "\n3 = configuration or general messages" - "\n4 = warnings" - "\n5 = called functions" - "\n6 = function internals" - "\nLevel 5 and 6 are useful for testing only, when only " - "one device is used." - "\nDefault value is "__MODULE_STRING(W9968CF_DEBUG_LEVEL)"." - "\n"); + "\n Debugging information level, from 0 to 6:" + "\n0 = none (use carefully)" + "\n1 = critical errors" + "\n2 = significant informations" + "\n3 = configuration or general messages" + "\n4 = warnings" + "\n5 = called functions" + "\n6 = function internals" + "\nLevel 5 and 6 are useful for testing only, when only " + "one device is used." + "\nDefault value is "__MODULE_STRING(W9968CF_DEBUG_LEVEL)"." + "\n"); MODULE_PARM_DESC(specific_debug, - "\n<0|1> Enable or disable specific debugging messages:" - "\n0 = print messages concerning every level" - " <= 'debug' level." - "\n1 = print messages concerning the level" - " indicated by 'debug'." - "\nDefault value is " - __MODULE_STRING(W9968CF_SPECIFIC_DEBUG)"." - "\n"); + "\n<0|1> Enable or disable specific debugging messages:" + "\n0 = print messages concerning every level" + " <= 'debug' level." + "\n1 = print messages concerning the level" + " indicated by 'debug'." + "\nDefault value is " + __MODULE_STRING(W9968CF_SPECIFIC_DEBUG)"." + "\n"); #endif /* W9968CF_DEBUG */ @@ -406,7 +406,7 @@ static int w9968cf_mmap(struct file*, struct vm_area_struct*); static int w9968cf_ioctl(struct inode*, struct file*, unsigned, unsigned long); static ssize_t w9968cf_read(struct file*, char __user *, size_t, loff_t*); static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int, - void __user *); + void __user *); /* USB-specific */ static int w9968cf_start_transfer(struct w9968cf_device*); @@ -428,25 +428,25 @@ static int w9968cf_smbus_write_ack(struct w9968cf_device*); static int w9968cf_smbus_read_ack(struct w9968cf_device*); static int w9968cf_smbus_refresh_bus(struct w9968cf_device*); static int w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam, - u16 address, u8* value); -static int w9968cf_i2c_adap_read_byte_data(struct w9968cf_device*, u16 address, - u8 subaddress, u8* value); + u16 address, u8* value); +static int w9968cf_i2c_adap_read_byte_data(struct w9968cf_device*, u16 address, + u8 subaddress, u8* value); static int w9968cf_i2c_adap_write_byte(struct w9968cf_device*, - u16 address, u8 subaddress); + u16 address, u8 subaddress); static int w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device*, - u16 address, u8 subaddress, - u8 value); + u16 address, u8 subaddress, + u8 value); /* I2C interface to kernel */ static int w9968cf_i2c_init(struct w9968cf_device*); -static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data*); +static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data*); static u32 w9968cf_i2c_func(struct i2c_adapter*); static int w9968cf_i2c_attach_inform(struct i2c_client*); static int w9968cf_i2c_detach_inform(struct i2c_client*); static int w9968cf_i2c_control(struct i2c_adapter*, unsigned int cmd, - unsigned long arg); + unsigned long arg); /* Memory management */ static void* rvmalloc(unsigned long size); @@ -458,17 +458,17 @@ static int w9968cf_allocate_memory(struct w9968cf_device*); static int w9968cf_sensor_set_control(struct w9968cf_device*,int cid,int val); static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val); static int w9968cf_sensor_cmd(struct w9968cf_device*, - unsigned int cmd, void *arg); + unsigned int cmd, void *arg); static int w9968cf_sensor_init(struct w9968cf_device*); static int w9968cf_sensor_update_settings(struct w9968cf_device*); static int w9968cf_sensor_get_picture(struct w9968cf_device*); -static int w9968cf_sensor_update_picture(struct w9968cf_device*, - struct video_picture pict); +static int w9968cf_sensor_update_picture(struct w9968cf_device*, + struct video_picture pict); /* Other helper functions */ static void w9968cf_configure_camera(struct w9968cf_device*,struct usb_device*, - enum w9968cf_model_id, - const unsigned short dev_nr); + enum w9968cf_model_id, + const unsigned short dev_nr); static void w9968cf_adjust_configuration(struct w9968cf_device*); static int w9968cf_turn_on_led(struct w9968cf_device*); static int w9968cf_init_chip(struct w9968cf_device*); @@ -477,8 +477,8 @@ static inline u16 w9968cf_valid_depth(u16 palette); static inline u8 w9968cf_need_decompression(u16 palette); static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture); static int w9968cf_set_window(struct w9968cf_device*, struct video_window); -static int w9968cf_postprocess_frame(struct w9968cf_device*, - struct w9968cf_frame_t*); +static int w9968cf_postprocess_frame(struct w9968cf_device*, + struct w9968cf_frame_t*); static int w9968cf_adjust_window_size(struct w9968cf_device*, u16* w, u16* h); static void w9968cf_init_framelist(struct w9968cf_device*); static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num); @@ -497,11 +497,11 @@ struct w9968cf_symbolic_list { const char *name; }; -/*-------------------------------------------------------------------------- +/*-------------------------------------------------------------------------- Returns the name of the matching element in the symbolic_list array. The end of the list must be marked with an element that has a NULL name. --------------------------------------------------------------------------*/ -static inline const char * +static inline const char * symbolic(struct w9968cf_symbolic_list list[], const int num) { int i; @@ -568,7 +568,7 @@ static struct w9968cf_symbolic_list v4l1_plist[] = { static struct w9968cf_symbolic_list decoder_errlist[] = { { W9968CF_DEC_ERR_CORRUPTED_DATA, "Corrupted data" }, { W9968CF_DEC_ERR_BUF_OVERFLOW, "Buffer overflow" }, - { W9968CF_DEC_ERR_NO_SOI, "SOI marker not found" }, + { W9968CF_DEC_ERR_NO_SOI, "SOI marker not found" }, { W9968CF_DEC_ERR_NO_SOF0, "SOF0 marker not found" }, { W9968CF_DEC_ERR_NO_SOS, "SOS marker not found" }, { W9968CF_DEC_ERR_NO_EOI, "EOI marker not found" }, @@ -695,7 +695,7 @@ static int w9968cf_allocate_memory(struct w9968cf_device* cam) bpp = (w9968cf_vpp) ? 4 : 2; if (cam->upscaling) vpp_bufsize = max(W9968CF_MAX_WIDTH*W9968CF_MAX_HEIGHT*bpp, - cam->maxwidth*cam->maxheight*bpp); + cam->maxwidth*cam->maxheight*bpp); else vpp_bufsize = cam->maxwidth*cam->maxheight*bpp; @@ -704,7 +704,7 @@ static int w9968cf_allocate_memory(struct w9968cf_device* cam) if (!(cam->transfer_buffer[i] = kzalloc(W9968CF_ISO_PACKETS*p_size, GFP_KERNEL))) { DBG(1, "Couldn't allocate memory for the isochronous " - "transfer buffers (%u bytes)", + "transfer buffers (%u bytes)", p_size * W9968CF_ISO_PACKETS) return -ENOMEM; } @@ -780,7 +780,7 @@ static int w9968cf_allocate_memory(struct w9968cf_device* cam) of the next video frame; if an error is encountered in a packet, the entire video frame is discarded and grabbed again. If there are no requested frames in the FIFO list, packets are collected into - a temporary buffer. + a temporary buffer. --------------------------------------------------------------------------*/ static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs) { @@ -799,7 +799,7 @@ static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs) /* "(*f)" will be used instead of "cam->frame_current" */ f = &cam->frame_current; - /* If a frame has been requested and we are grabbing into + /* If a frame has been requested and we are grabbing into the temporary frame, we'll switch to that requested frame */ if ((*f) == &cam->frame_tmp && *cam->requested_frame) { if (cam->frame_tmp.status == F_GRABBING) { @@ -808,7 +808,7 @@ static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs) (*f)->length = cam->frame_tmp.length; memcpy((*f)->buffer, cam->frame_tmp.buffer, (*f)->length); - DBG(6, "Switched from temp. frame to frame #%d", + DBG(6, "Switched from temp. frame to frame #%d", (*f)->number) } } @@ -850,7 +850,7 @@ static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs) if (cam->vpp_flag & VPP_DECOMPRESSION) { err = w9968cf_vpp->check_headers((*f)->buffer, - (*f)->length); + (*f)->length); if (err) { DBG(4, "Skip corrupted frame: %s", symbolic(decoder_errlist, err)) @@ -975,7 +975,7 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam) cam->frame_current = &cam->frame_tmp; if (!(cam->vpp_flag & VPP_DECOMPRESSION)) - DBG(5, "Isochronous transfer size: %lu bytes/frame", + DBG(5, "Isochronous transfer size: %lu bytes/frame", (unsigned long)t_size*2) DBG(5, "Starting the isochronous transfer...") @@ -992,7 +992,7 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam) usb_free_urb(cam->urb[j]); } DBG(1, "Couldn't send a transfer request to the " - "USB core (error #%d, %s)", err, + "USB core (error #%d, %s)", err, symbolic(urb_errlist, err)) return err; } @@ -1016,7 +1016,7 @@ static int w9968cf_stop_transfer(struct w9968cf_device* cam) if (!cam->streaming) return 0; - /* This avoids race conditions with usb_submit_urb() + /* This avoids race conditions with usb_submit_urb() in the URB completition handler */ spin_lock_irqsave(&cam->urb_lock, lock_flags); cam->streaming = 0; @@ -1050,7 +1050,7 @@ exit: /*-------------------------------------------------------------------------- - Write a W9968CF register. + Write a W9968CF register. Return 0 on success, -1 otherwise. --------------------------------------------------------------------------*/ static int w9968cf_write_reg(struct w9968cf_device* cam, u16 value, u16 index) @@ -1059,8 +1059,8 @@ static int w9968cf_write_reg(struct w9968cf_device* cam, u16 value, u16 index) int res; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - value, index, NULL, 0, W9968CF_USB_CTRL_TIMEOUT); + USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, + value, index, NULL, 0, W9968CF_USB_CTRL_TIMEOUT); if (res < 0) DBG(4, "Failed to write a register " @@ -1072,7 +1072,7 @@ static int w9968cf_write_reg(struct w9968cf_device* cam, u16 value, u16 index) /*-------------------------------------------------------------------------- - Read a W9968CF register. + Read a W9968CF register. Return the register value on success, -1 otherwise. --------------------------------------------------------------------------*/ static int w9968cf_read_reg(struct w9968cf_device* cam, u16 index) @@ -1082,8 +1082,8 @@ static int w9968cf_read_reg(struct w9968cf_device* cam, u16 index) int res; res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 1, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, buff, 2, W9968CF_USB_CTRL_TIMEOUT); + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, index, buff, 2, W9968CF_USB_CTRL_TIMEOUT); if (res < 0) DBG(4, "Failed to read a register " @@ -1107,8 +1107,8 @@ static int w9968cf_write_fsb(struct w9968cf_device* cam, u16* data) value = *data++; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - value, 0x06, data, 6, W9968CF_USB_CTRL_TIMEOUT); + USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, + value, 0x06, data, 6, W9968CF_USB_CTRL_TIMEOUT); if (res < 0) DBG(4, "Failed to write the FSB registers " @@ -1287,9 +1287,9 @@ static int w9968cf_smbus_refresh_bus(struct w9968cf_device* cam) /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ -static int -w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam, - u16 address, u8 subaddress,u8 value) +static int +w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam, + u16 address, u8 subaddress,u8 value) { u16* data = cam->data_buffer; int err = 0; @@ -1348,7 +1348,7 @@ w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam, "value 0x%02X", address, subaddress, value) else DBG(5, "I2C write byte data failed, addr.0x%04X, " - "subaddr.0x%02X, value 0x%02X", + "subaddr.0x%02X, value 0x%02X", address, subaddress, value) return err; @@ -1356,10 +1356,10 @@ w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam, /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ -static int -w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam, - u16 address, u8 subaddress, - u8* value) +static int +w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam, + u16 address, u8 subaddress, + u8* value) { int err = 0; @@ -1384,7 +1384,7 @@ w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam, if (!err) DBG(5, "I2C read byte data done, addr.0x%04X, " - "subaddr.0x%02X, value 0x%02X", + "subaddr.0x%02X, value 0x%02X", address, subaddress, *value) else DBG(5, "I2C read byte data failed, addr.0x%04X, " @@ -1396,9 +1396,9 @@ w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam, /* SMBus protocol: S Addr+1 Rd [A] [Value] NA P */ -static int +static int w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam, - u16 address, u8* value) + u16 address, u8* value) { int err = 0; @@ -1411,7 +1411,7 @@ w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam, err += w9968cf_smbus_read_byte(cam, value); err += w9968cf_smbus_write_ack(cam); err += w9968cf_smbus_stop(cam); - + /* Serial data disable */ err += w9968cf_write_sb(cam, 0x0000); @@ -1427,9 +1427,9 @@ w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam, /* SMBus protocol: S Addr Wr [A] Value [A] P */ -static int +static int w9968cf_i2c_adap_write_byte(struct w9968cf_device* cam, - u16 address, u8 value) + u16 address, u8 value) { DBG(4, "i2c_write_byte() is an unsupported transfer mode") return -EINVAL; @@ -1442,13 +1442,13 @@ w9968cf_i2c_adap_write_byte(struct w9968cf_device* cam, ****************************************************************************/ static int -w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) +w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data *data) { struct w9968cf_device* cam = i2c_get_adapdata(adapter); u8 i; - int err = 0; + int err = 0; switch (addr) { case OV6xx0_SID: @@ -1464,20 +1464,20 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, addr <<= 1; if (read_write == I2C_SMBUS_WRITE) - err = w9968cf_i2c_adap_write_byte(cam, addr, command); - else if (read_write == I2C_SMBUS_READ) + err = w9968cf_i2c_adap_write_byte(cam, addr, command); + else if (read_write == I2C_SMBUS_READ) err = w9968cf_i2c_adap_read_byte(cam,addr,&data->byte); } else if (size == I2C_SMBUS_BYTE_DATA) { addr <<= 1; if (read_write == I2C_SMBUS_WRITE) - err = w9968cf_i2c_adap_fastwrite_byte_data(cam, addr, - command, data->byte); + err = w9968cf_i2c_adap_fastwrite_byte_data(cam, addr, + command, data->byte); else if (read_write == I2C_SMBUS_READ) { for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) { err = w9968cf_i2c_adap_read_byte_data(cam,addr, - command, &data->byte); + command, &data->byte); if (err) { if (w9968cf_smbus_refresh_bus(cam)) { err = -EIO; @@ -1520,7 +1520,7 @@ static int w9968cf_i2c_attach_inform(struct i2c_client* client) return err; } } else { - DBG(4, "Rejected client [%s] with driver [%s]", + DBG(4, "Rejected client [%s] with driver [%s]", client->name, client->driver->driver.name) return -EINVAL; } @@ -1545,9 +1545,9 @@ static int w9968cf_i2c_detach_inform(struct i2c_client* client) } -static int +static int w9968cf_i2c_control(struct i2c_adapter* adapter, unsigned int cmd, - unsigned long arg) + unsigned long arg) { return 0; } @@ -1625,12 +1625,12 @@ static int w9968cf_turn_on_led(struct w9968cf_device* cam) static int w9968cf_init_chip(struct w9968cf_device* cam) { unsigned long hw_bufsize = cam->maxwidth*cam->maxheight*2, - y0 = 0x0000, - u0 = y0 + hw_bufsize/2, - v0 = u0 + hw_bufsize/4, - y1 = v0 + hw_bufsize/4, - u1 = y1 + hw_bufsize/2, - v1 = u1 + hw_bufsize/4; + y0 = 0x0000, + u0 = y0 + hw_bufsize/2, + v0 = u0 + hw_bufsize/4, + y1 = v0 + hw_bufsize/4, + u1 = y1 + hw_bufsize/2, + v1 = u1 + hw_bufsize/4; int err = 0; err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power off */ @@ -1762,7 +1762,7 @@ w9968cf_set_picture(struct w9968cf_device* cam, struct video_picture pict) cam->vpp_flag = VPP_SWAP_YUV_BYTES; hw_palette = VIDEO_PALETTE_UYVY; break; - /* Original video is used instead of RGBX palettes. + /* Original video is used instead of RGBX palettes. Software conversion later. */ case VIDEO_PALETTE_GREY: case VIDEO_PALETTE_RGB555: @@ -1777,7 +1777,7 @@ w9968cf_set_picture(struct w9968cf_device* cam, struct video_picture pict) } /* NOTE: due to memory issues, it is better to disable the hardware - double buffering during compression */ + double buffering during compression */ if (cam->double_buffer && !(cam->vpp_flag & VPP_DECOMPRESSION)) reg_v |= 0x0080; @@ -1832,8 +1832,8 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win) #define __UNSC(x) ((x) >> 10) /* Make sure we are using a supported resolution */ - if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, - (u16*)&win.height))) + if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, + (u16*)&win.height))) goto error; /* Scaling factors */ @@ -1962,7 +1962,7 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win) /* Settings changed, so we clear the frame buffers */ memset(cam->frame[0].buffer, 0, cam->nbuffers*cam->frame[0].size); - DBG(4, "The capture area is %dx%d, Offset (x,y)=(%u,%u)", + DBG(4, "The capture area is %dx%d, Offset (x,y)=(%u,%u)", win.width, win.height, win.x, win.y) PDBGG("x=%u ,y=%u, w=%u, h=%u, ax=%u, ay=%u, s_win.x=%u, s_win.y=%u, " @@ -1978,11 +1978,11 @@ error: } -/*-------------------------------------------------------------------------- +/*-------------------------------------------------------------------------- Adjust the asked values for window width and height. Return 0 on success, -1 otherwise. --------------------------------------------------------------------------*/ -static int +static int w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height) { u16 maxw, maxh; @@ -1992,10 +1992,10 @@ w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height) maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && w9968cf_vpp ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) - : cam->maxwidth; + : cam->maxwidth; maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && w9968cf_vpp ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) - : cam->maxheight; + : cam->maxheight; if (*width > maxw) *width = maxw; @@ -2054,7 +2054,7 @@ static void w9968cf_push_frame(struct w9968cf_device* cam, u8 f_num) Read, store and remove the first pointer in the FIFO list of requested frames. This function is called in interrupt context. --------------------------------------------------------------------------*/ -static void +static void w9968cf_pop_frame(struct w9968cf_device* cam, struct w9968cf_frame_t** framep) { u8 i; @@ -2078,9 +2078,9 @@ w9968cf_pop_frame(struct w9968cf_device* cam, struct w9968cf_frame_t** framep) High-level video post-processing routine on grabbed frames. Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/ -static int -w9968cf_postprocess_frame(struct w9968cf_device* cam, - struct w9968cf_frame_t* fr) +static int +w9968cf_postprocess_frame(struct w9968cf_device* cam, + struct w9968cf_frame_t* fr) { void *pIn = fr->buffer, *pOut = cam->frame_vpp.buffer, *tmp; u16 w = cam->window.width, @@ -2127,7 +2127,7 @@ w9968cf_postprocess_frame(struct w9968cf_device* cam, w9968cf_vpp->uyvy_to_rgbx(pIn, fr->length, pOut, fmt, rgb); fr->length = (w*h*d)/8; _PSWAP(pIn, pOut) - DBG(6, "UYVY-16bit to %s conversion done", + DBG(6, "UYVY-16bit to %s conversion done", symbolic(v4l1_plist, fmt)) } @@ -2143,7 +2143,7 @@ w9968cf_postprocess_frame(struct w9968cf_device* cam, * Image sensor control routines * ****************************************************************************/ -static int +static int w9968cf_sensor_set_control(struct w9968cf_device* cam, int cid, int val) { struct ovcamchip_control ctl; @@ -2158,7 +2158,7 @@ w9968cf_sensor_set_control(struct w9968cf_device* cam, int cid, int val) } -static int +static int w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int* val) { struct ovcamchip_control ctl; @@ -2198,38 +2198,38 @@ static int w9968cf_sensor_update_settings(struct w9968cf_device* cam) int err = 0; /* Auto brightness */ - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOBRIGHT, - cam->auto_brt); + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOBRIGHT, + cam->auto_brt); if (err) return err; /* Auto exposure */ - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOEXP, - cam->auto_exp); + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOEXP, + cam->auto_exp); if (err) return err; /* Banding filter */ - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BANDFILT, - cam->bandfilt); + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BANDFILT, + cam->bandfilt); if (err) return err; /* Light frequency */ err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_FREQ, - cam->lightfreq); + cam->lightfreq); if (err) return err; /* Back light */ err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BACKLIGHT, - cam->backlight); + cam->backlight); if (err) return err; /* Mirror */ err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_MIRROR, - cam->mirror); + cam->mirror); if (err) return err; @@ -2281,15 +2281,15 @@ static int w9968cf_sensor_get_picture(struct w9968cf_device* cam) Returns: 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/ static int -w9968cf_sensor_update_picture(struct w9968cf_device* cam, - struct video_picture pict) +w9968cf_sensor_update_picture(struct w9968cf_device* cam, + struct video_picture pict) { int err = 0; if ((!cam->sensor_initialized) || pict.contrast != cam->picture.contrast) { err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_CONT, - pict.contrast); + pict.contrast); if (err) goto fail; DBG(4, "Contrast changed from %u to %u", @@ -2297,10 +2297,10 @@ w9968cf_sensor_update_picture(struct w9968cf_device* cam, cam->picture.contrast = pict.contrast; } - if (((!cam->sensor_initialized) || + if (((!cam->sensor_initialized) || pict.brightness != cam->picture.brightness) && (!cam->auto_brt)) { - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BRIGHT, - pict.brightness); + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BRIGHT, + pict.brightness); if (err) goto fail; DBG(4, "Brightness changed from %u to %u", @@ -2309,8 +2309,8 @@ w9968cf_sensor_update_picture(struct w9968cf_device* cam, } if ((!cam->sensor_initialized) || pict.colour != cam->picture.colour) { - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_SAT, - pict.colour); + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_SAT, + pict.colour); if (err) goto fail; DBG(4, "Colour changed from %u to %u", @@ -2319,8 +2319,8 @@ w9968cf_sensor_update_picture(struct w9968cf_device* cam, } if ((!cam->sensor_initialized) || pict.hue != cam->picture.hue) { - err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_HUE, - pict.hue); + err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_HUE, + pict.hue); if (err) goto fail; DBG(4, "Hue changed from %u to %u", @@ -2349,12 +2349,12 @@ static int w9968cf_sensor_init(struct w9968cf_device* cam) { int err = 0; - if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_INITIALIZE, - &cam->monochrome))) + if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_INITIALIZE, + &cam->monochrome))) goto error; - if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_Q_SUBTYPE, - &cam->sensor))) + if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_Q_SUBTYPE, + &cam->sensor))) goto error; /* NOTE: Make sure width and height are a multiple of 16 */ @@ -2416,14 +2416,14 @@ error: /*-------------------------------------------------------------------------- Fill some basic fields in the main device data structure. - This function is called once on w9968cf_usb_probe() for each recognized + This function is called once on w9968cf_usb_probe() for each recognized camera. --------------------------------------------------------------------------*/ static void w9968cf_configure_camera(struct w9968cf_device* cam, - struct usb_device* udev, - enum w9968cf_model_id mod_id, - const unsigned short dev_nr) + struct usb_device* udev, + enum w9968cf_model_id mod_id, + const unsigned short dev_nr) { mutex_init(&cam->fileop_mutex); init_waitqueue_head(&cam->open); @@ -2444,60 +2444,60 @@ w9968cf_configure_camera(struct w9968cf_device* cam, packet_size[dev_nr] < wMaxPacketSize[cam->altsetting-1]; cam->altsetting++); - cam->max_buffers = (max_buffers[dev_nr] < 2 || - max_buffers[dev_nr] > W9968CF_MAX_BUFFERS) - ? W9968CF_BUFFERS : (u8)max_buffers[dev_nr]; + cam->max_buffers = (max_buffers[dev_nr] < 2 || + max_buffers[dev_nr] > W9968CF_MAX_BUFFERS) + ? W9968CF_BUFFERS : (u8)max_buffers[dev_nr]; - cam->double_buffer = (double_buffer[dev_nr] == 0 || - double_buffer[dev_nr] == 1) - ? (u8)double_buffer[dev_nr]:W9968CF_DOUBLE_BUFFER; + cam->double_buffer = (double_buffer[dev_nr] == 0 || + double_buffer[dev_nr] == 1) + ? (u8)double_buffer[dev_nr]:W9968CF_DOUBLE_BUFFER; cam->clamping = (clamping[dev_nr] == 0 || clamping[dev_nr] == 1) - ? (u8)clamping[dev_nr] : W9968CF_CLAMPING; - + ? (u8)clamping[dev_nr] : W9968CF_CLAMPING; + cam->filter_type = (filter_type[dev_nr] == 0 || - filter_type[dev_nr] == 1 || - filter_type[dev_nr] == 2) - ? (u8)filter_type[dev_nr] : W9968CF_FILTER_TYPE; + filter_type[dev_nr] == 1 || + filter_type[dev_nr] == 2) + ? (u8)filter_type[dev_nr] : W9968CF_FILTER_TYPE; cam->capture = 1; cam->largeview = (largeview[dev_nr] == 0 || largeview[dev_nr] == 1) - ? (u8)largeview[dev_nr] : W9968CF_LARGEVIEW; + ? (u8)largeview[dev_nr] : W9968CF_LARGEVIEW; - cam->decompression = (decompression[dev_nr] == 0 || - decompression[dev_nr] == 1 || - decompression[dev_nr] == 2) - ? (u8)decompression[dev_nr]:W9968CF_DECOMPRESSION; + cam->decompression = (decompression[dev_nr] == 0 || + decompression[dev_nr] == 1 || + decompression[dev_nr] == 2) + ? (u8)decompression[dev_nr]:W9968CF_DECOMPRESSION; - cam->upscaling = (upscaling[dev_nr] == 0 || - upscaling[dev_nr] == 1) - ? (u8)upscaling[dev_nr] : W9968CF_UPSCALING; + cam->upscaling = (upscaling[dev_nr] == 0 || + upscaling[dev_nr] == 1) + ? (u8)upscaling[dev_nr] : W9968CF_UPSCALING; cam->auto_brt = (autobright[dev_nr] == 0 || autobright[dev_nr] == 1) - ? (u8)autobright[dev_nr] : W9968CF_AUTOBRIGHT; + ? (u8)autobright[dev_nr] : W9968CF_AUTOBRIGHT; cam->auto_exp = (autoexp[dev_nr] == 0 || autoexp[dev_nr] == 1) - ? (u8)autoexp[dev_nr] : W9968CF_AUTOEXP; + ? (u8)autoexp[dev_nr] : W9968CF_AUTOEXP; cam->lightfreq = (lightfreq[dev_nr] == 50 || lightfreq[dev_nr] == 60) - ? (u8)lightfreq[dev_nr] : W9968CF_LIGHTFREQ; + ? (u8)lightfreq[dev_nr] : W9968CF_LIGHTFREQ; - cam->bandfilt = (bandingfilter[dev_nr] == 0 || - bandingfilter[dev_nr] == 1) - ? (u8)bandingfilter[dev_nr] : W9968CF_BANDINGFILTER; + cam->bandfilt = (bandingfilter[dev_nr] == 0 || + bandingfilter[dev_nr] == 1) + ? (u8)bandingfilter[dev_nr] : W9968CF_BANDINGFILTER; cam->backlight = (backlight[dev_nr] == 0 || backlight[dev_nr] == 1) - ? (u8)backlight[dev_nr] : W9968CF_BACKLIGHT; + ? (u8)backlight[dev_nr] : W9968CF_BACKLIGHT; cam->clockdiv = (clockdiv[dev_nr] == -1 || clockdiv[dev_nr] >= 0) - ? (s8)clockdiv[dev_nr] : W9968CF_CLOCKDIV; + ? (s8)clockdiv[dev_nr] : W9968CF_CLOCKDIV; cam->mirror = (mirror[dev_nr] == 0 || mirror[dev_nr] == 1) - ? (u8)mirror[dev_nr] : W9968CF_MIRROR; + ? (u8)mirror[dev_nr] : W9968CF_MIRROR; cam->monochrome = (monochrome[dev_nr] == 0 || monochrome[dev_nr] == 1) - ? monochrome[dev_nr] : W9968CF_MONOCHROME; + ? monochrome[dev_nr] : W9968CF_MONOCHROME; cam->picture.brightness = (u16)brightness[dev_nr]; cam->picture.hue = (u16)hue[dev_nr]; @@ -2519,7 +2519,7 @@ w9968cf_configure_camera(struct w9968cf_device* cam, cam->picture.depth = w9968cf_valid_depth(cam->picture.palette); cam->force_rgb = (force_rgb[dev_nr] == 0 || force_rgb[dev_nr] == 1) - ? (u8)force_rgb[dev_nr] : W9968CF_FORCE_RGB; + ? (u8)force_rgb[dev_nr] : W9968CF_FORCE_RGB; cam->window.x = 0; cam->window.y = 0; @@ -2531,16 +2531,16 @@ w9968cf_configure_camera(struct w9968cf_device* cam, DBG(3, "%s configured with settings #%u:", symbolic(camlist, cam->id), dev_nr) - + DBG(3, "- Data packet size for USB isochrnous transfer: %u bytes", wMaxPacketSize[cam->altsetting-1]) - + DBG(3, "- Number of requested video frame buffers: %u", cam->max_buffers) if (cam->double_buffer) DBG(3, "- Hardware double buffering enabled") - else + else DBG(3, "- Hardware double buffering disabled") if (cam->filter_type == 0) @@ -2648,7 +2648,7 @@ static void w9968cf_adjust_configuration(struct w9968cf_device* cam) /*-------------------------------------------------------------------------- Release the resources used by the driver. - This function is called on disconnect + This function is called on disconnect (or on close if deallocation has been deferred) --------------------------------------------------------------------------*/ static void w9968cf_release_resources(struct w9968cf_device* cam) @@ -2706,8 +2706,8 @@ static int w9968cf_open(struct inode* inode, struct file* filp) } mutex_unlock(&cam->dev_mutex); err = wait_event_interruptible_exclusive(cam->open, - cam->disconnected || - !cam->users); + cam->disconnected || + !cam->users); if (err) { up_read(&w9968cf_disconnect); return err; @@ -2820,9 +2820,9 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) w9968cf_push_frame(cam, 1); err = wait_event_interruptible(cam->wait_queue, - cam->frame[0].status == F_READY || - cam->frame[1].status == F_READY || - cam->disconnected); + cam->frame[0].status == F_READY || + cam->frame[1].status == F_READY || + cam->disconnected); if (err) { mutex_unlock(&cam->fileop_mutex); return err; @@ -2859,12 +2859,12 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma) { struct w9968cf_device* cam = (struct w9968cf_device*) - video_get_drvdata(video_devdata(filp)); + video_get_drvdata(video_devdata(filp)); unsigned long vsize = vma->vm_end - vma->vm_start, - psize = cam->nbuffers * cam->frame[0].size, - start = vma->vm_start, - pos = (unsigned long)cam->frame[0].buffer, - page; + psize = cam->nbuffers * cam->frame[0].size, + start = vma->vm_start, + pos = (unsigned long)cam->frame[0].buffer, + page; if (cam->disconnected) { DBG(2, "Device not present") @@ -2898,7 +2898,7 @@ static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma) static int w9968cf_ioctl(struct inode* inode, struct file* filp, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { struct w9968cf_device* cam; int err; @@ -2928,21 +2928,21 @@ w9968cf_ioctl(struct inode* inode, struct file* filp, static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) + unsigned int cmd, void __user * arg) { struct w9968cf_device* cam; const char* v4l1_ioctls[] = { - "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", + "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT", "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ", "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT", "GCAPTURE", "SCAPTURE", - "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", "SMICROCODE", - "GVBIFMT", "SVBIFMT" + "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", "SMICROCODE", + "GVBIFMT", "SVBIFMT" }; #define V4L1_IOCTL(cmd) \ - ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \ - v4l1_ioctls[_IOC_NR((cmd))] : "?") + ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \ + v4l1_ioctls[_IOC_NR((cmd))] : "?") cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); @@ -2957,14 +2957,14 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, .minwidth = cam->minwidth, .minheight = cam->minheight, }; - sprintf(cap.name, "W996[87]CF USB Camera #%d", - cam->v4ldev->minor); + sprintf(cap.name, "W996[87]CF USB Camera #%d", + cam->v4ldev->minor); cap.maxwidth = (cam->upscaling && w9968cf_vpp) - ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) - : cam->maxwidth; + ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) + : cam->maxwidth; cap.maxheight = (cam->upscaling && w9968cf_vpp) - ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) - : cam->maxheight; + ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) + : cam->maxheight; if (copy_to_user(arg, &cap, sizeof(cap))) return -EFAULT; @@ -3029,7 +3029,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, if (copy_from_user(&pict, arg, sizeof(pict))) return -EFAULT; - if ( (cam->force_palette || !w9968cf_vpp) + if ( (cam->force_palette || !w9968cf_vpp) && pict.palette != cam->picture.palette ) { DBG(4, "Palette %s rejected: only %s is allowed", symbolic(v4l1_plist, pict.palette), @@ -3046,24 +3046,24 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, if (!cam->force_palette) { if (cam->decompression == 0) { if (w9968cf_need_decompression(pict.palette)) { - DBG(4, "Decompression disabled: palette %s is not " - "allowed. VIDIOCSPICT failed", - symbolic(v4l1_plist, pict.palette)) - return -EINVAL; + DBG(4, "Decompression disabled: palette %s is not " + "allowed. VIDIOCSPICT failed", + symbolic(v4l1_plist, pict.palette)) + return -EINVAL; } } else if (cam->decompression == 1) { if (!w9968cf_need_decompression(pict.palette)) { - DBG(4, "Decompression forced: palette %s is not " - "allowed. VIDIOCSPICT failed", - symbolic(v4l1_plist, pict.palette)) - return -EINVAL; + DBG(4, "Decompression forced: palette %s is not " + "allowed. VIDIOCSPICT failed", + symbolic(v4l1_plist, pict.palette)) + return -EINVAL; } } } if (pict.depth != w9968cf_valid_depth(pict.palette)) { DBG(4, "Requested depth %u bpp is not valid for %s " - "palette: ignored and changed to %u bpp", + "palette: ignored and changed to %u bpp", pict.depth, symbolic(v4l1_plist, pict.palette), w9968cf_valid_depth(pict.palette)) pict.depth = w9968cf_valid_depth(pict.palette); @@ -3074,9 +3074,9 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, || cam->frame_current->queued) { err = wait_event_interruptible ( cam->wait_queue, - cam->disconnected || - (!*cam->requested_frame && - !cam->frame_current->queued) ); + cam->disconnected || + (!*cam->requested_frame && + !cam->frame_current->queued) ); if (err) return err; if (cam->disconnected) @@ -3116,7 +3116,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, return -EINVAL; if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, - (u16*)&win.height))) { + (u16*)&win.height))) { DBG(4, "Resolution not supported (%ux%u). " "VIDIOCSWIN failed", win.width, win.height) return err; @@ -3130,9 +3130,9 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, || cam->frame_current->queued) { err = wait_event_interruptible ( cam->wait_queue, - cam->disconnected || - (!*cam->requested_frame && - !cam->frame_current->queued) ); + cam->disconnected || + (!*cam->requested_frame && + !cam->frame_current->queued) ); if (err) return err; if (cam->disconnected) @@ -3175,7 +3175,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, mbuf.frames = cam->nbuffers; for (i = 0; i < cam->nbuffers; i++) mbuf.offsets[i] = (unsigned long)cam->frame[i].buffer - - (unsigned long)cam->frame[0].buffer; + (unsigned long)cam->frame[0].buffer; if (copy_to_user(arg, &mbuf, sizeof(mbuf))) return -EFAULT; @@ -3194,7 +3194,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, return -EFAULT; DBG(6, "VIDIOCMCAPTURE called: frame #%u, format=%s, %dx%d", - mmap.frame, symbolic(v4l1_plist, mmap.format), + mmap.frame, symbolic(v4l1_plist, mmap.format), mmap.width, mmap.height) if (mmap.frame >= cam->nbuffers) { @@ -3203,7 +3203,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, return -EINVAL; } - if (mmap.format!=cam->picture.palette && + if (mmap.format!=cam->picture.palette && (cam->force_palette || !w9968cf_vpp)) { DBG(4, "Palette %s rejected: only %s is allowed", symbolic(v4l1_plist, mmap.format), @@ -3213,7 +3213,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, if (!w9968cf_valid_palette(mmap.format)) { DBG(4, "Palette %s not supported. " - "VIDIOCMCAPTURE failed", + "VIDIOCMCAPTURE failed", symbolic(v4l1_plist, mmap.format)) return -EINVAL; } @@ -3221,23 +3221,23 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, if (!cam->force_palette) { if (cam->decompression == 0) { if (w9968cf_need_decompression(mmap.format)) { - DBG(4, "Decompression disabled: palette %s is not " - "allowed. VIDIOCSPICT failed", - symbolic(v4l1_plist, mmap.format)) - return -EINVAL; + DBG(4, "Decompression disabled: palette %s is not " + "allowed. VIDIOCSPICT failed", + symbolic(v4l1_plist, mmap.format)) + return -EINVAL; } } else if (cam->decompression == 1) { if (!w9968cf_need_decompression(mmap.format)) { - DBG(4, "Decompression forced: palette %s is not " - "allowed. VIDIOCSPICT failed", - symbolic(v4l1_plist, mmap.format)) - return -EINVAL; + DBG(4, "Decompression forced: palette %s is not " + "allowed. VIDIOCSPICT failed", + symbolic(v4l1_plist, mmap.format)) + return -EINVAL; } } } - if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width, - (u16*)&mmap.height))) { + if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width, + (u16*)&mmap.height))) { DBG(4, "Resolution not supported (%dx%d). " "VIDIOCMCAPTURE failed", mmap.width, mmap.height) @@ -3258,12 +3258,12 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, DBG(6, "VIDIOCMCAPTURE. Change settings for " "frame #%u: %dx%d, format %s. Wait...", mmap.frame, mmap.width, mmap.height, - symbolic(v4l1_plist, mmap.format)) + symbolic(v4l1_plist, mmap.format)) err = wait_event_interruptible ( cam->wait_queue, - cam->disconnected || - (!*cam->requested_frame && - !cam->frame_current->queued) ); + cam->disconnected || + (!*cam->requested_frame && + !cam->frame_current->queued) ); if (err) return err; if (cam->disconnected) @@ -3280,7 +3280,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, goto ioctl_fail; /* This before set_window */ - if (w9968cf_set_picture(cam, pict)) + if (w9968cf_set_picture(cam, pict)) goto ioctl_fail; if (w9968cf_set_window(cam, win)) @@ -3292,10 +3292,10 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, } else if (fr->queued) { DBG(6, "Wait until frame #%u is free", mmap.frame) - - err = wait_event_interruptible(cam->wait_queue, - cam->disconnected || - (!fr->queued)); + + err = wait_event_interruptible(cam->wait_queue, + cam->disconnected || + (!fr->queued)); if (err) return err; if (cam->disconnected) @@ -3335,9 +3335,9 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, } case F_ERROR: case F_GRABBING: - err = wait_event_interruptible(cam->wait_queue, - (fr->status == F_READY) - || cam->disconnected); + err = wait_event_interruptible(cam->wait_queue, + (fr->status == F_READY) + || cam->disconnected); if (err) return err; if (cam->disconnected) @@ -3439,7 +3439,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, DBG(4, "Unsupported V4L1 IOCtl: VIDIOC%s " "(type 0x%01X, " "n. 0x%01X, " - "dir. 0x%01X, " + "dir. 0x%01X, " "size 0x%02X)", V4L1_IOCTL(cmd), _IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd)) @@ -3499,13 +3499,13 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct) mod_id = W9968CF_MOD_CLVBWGP; /* see camlist[] table */ else if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[1].idVendor && - le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[1].idProduct) + le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[1].idProduct) mod_id = W9968CF_MOD_GENERIC; /* see camlist[] table */ else return -ENODEV; cam = (struct w9968cf_device*) - kzalloc(sizeof(struct w9968cf_device), GFP_KERNEL); + kzalloc(sizeof(struct w9968cf_device), GFP_KERNEL); if (!cam) return -ENOMEM; @@ -3569,7 +3569,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->v4ldev->dev = &cam->dev; err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); + video_nr[dev_nr]); if (err) { DBG(1, "V4L device registration failed") if (err == -ENFILE && video_nr[dev_nr] == -1) @@ -3611,7 +3611,7 @@ fail: /* Free unused memory */ static void w9968cf_usb_disconnect(struct usb_interface* intf) { - struct w9968cf_device* cam = + struct w9968cf_device* cam = (struct w9968cf_device*)usb_get_intfdata(intf); down_write(&w9968cf_disconnect); diff --git a/drivers/media/video/w9968cf.h b/drivers/media/video/w9968cf.h index a87be719a281..2836b45ec206 100644 --- a/drivers/media/video/w9968cf.h +++ b/drivers/media/video/w9968cf.h @@ -61,7 +61,7 @@ /* Maximum data payload sizes in bytes for alternate settings */ static const u16 wMaxPacketSize[] = {1023, 959, 895, 831, 767, 703, 639, 575, - 511, 447, 383, 319, 255, 191, 127, 63}; + 511, 447, 383, 319, 255, 191, 127, 63}; #define W9968CF_PACKET_SIZE 1023 /* according to wMaxPacketSizes[] */ #define W9968CF_MIN_PACKET_SIZE 63 /* minimum value */ #define W9968CF_ISO_PACKETS 5 /* n.of packets for isochronous transfers */ @@ -134,7 +134,7 @@ static const struct w9968cf_format w9968cf_formatlist[] = { ****************************************************************************/ #define W9968CF_MODULE_NAME "V4L driver for W996[87]CF JPEG USB " \ - "Dual Mode Camera Chip" + "Dual Mode Camera Chip" #define W9968CF_MODULE_VERSION "1:1.33-basic" #define W9968CF_MODULE_AUTHOR "(C) 2002-2004 Luca Risolia" #define W9968CF_AUTHOR_EMAIL "" @@ -270,9 +270,9 @@ struct w9968cf_device { /* Locks */ struct mutex dev_mutex, /* for probe, disconnect,open and close */ - fileop_mutex; /* for read and ioctl */ + fileop_mutex; /* for read and ioctl */ spinlock_t urb_lock, /* for submit_urb() and unlink_urb() */ - flist_lock; /* for requested frame list accesses */ + flist_lock; /* for requested frame list accesses */ wait_queue_head_t open, wait_queue; char command[16]; /* name of the program holding the device */ @@ -299,7 +299,7 @@ struct w9968cf_device { dev_warn(&cam->dev, fmt "\n", ## args); \ else if ((level) >= 5) \ dev_info(&cam->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ + __FUNCTION__, __LINE__ , ## args); \ } \ } /* For generic kernel (not device specific) messages */ @@ -311,7 +311,7 @@ struct w9968cf_device { pr_info("w9968cf: " fmt "\n", ## args); \ else if ((level) >= 5) \ pr_debug("w9968cf: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ + __LINE__ , ## args); \ } \ } #else diff --git a/drivers/media/video/w9968cf_decoder.h b/drivers/media/video/w9968cf_decoder.h index 31faccbe8f03..59decbfc540a 100644 --- a/drivers/media/video/w9968cf_decoder.h +++ b/drivers/media/video/w9968cf_decoder.h @@ -78,9 +78,9 @@ static const unsigned char UV_QUANTABLE[64] = { #define W9968CF_DEC_ERR_NO_EOI -6 extern void w9968cf_init_decoder(void); -extern int w9968cf_check_headers(const unsigned char* Pin, - const unsigned long BUF_SIZE); -extern int w9968cf_decode(const char* Pin, const unsigned long BUF_SIZE, - const unsigned W, const unsigned H, char* Pout); +extern int w9968cf_check_headers(const unsigned char* Pin, + const unsigned long BUF_SIZE); +extern int w9968cf_decode(const char* Pin, const unsigned long BUF_SIZE, + const unsigned W, const unsigned H, char* Pout); #endif /* _W9968CF_DECODER_H_ */ diff --git a/drivers/media/video/w9968cf_vpp.h b/drivers/media/video/w9968cf_vpp.h index f3b91b782671..88c9b6c0cc36 100644 --- a/drivers/media/video/w9968cf_vpp.h +++ b/drivers/media/video/w9968cf_vpp.h @@ -29,7 +29,7 @@ struct w9968cf_vpp_t { struct module* owner; int (*check_headers)(const unsigned char*, const unsigned long); int (*decode)(const char*, const unsigned long, const unsigned, - const unsigned, char*); + const unsigned, char*); void (*swap_yuvbytes)(void*, unsigned long); void (*uyvy_to_rgbx)(u8*, unsigned long, u8*, u16, u8); void (*scale_up)(u8*, u8*, u16, u16, u16, u16, u16); diff --git a/drivers/media/video/zc0301/zc0301.h b/drivers/media/video/zc0301/zc0301.h index 8e0655140e60..b9c93b8c16f7 100644 --- a/drivers/media/video/zc0301/zc0301.h +++ b/drivers/media/video/zc0301/zc0301.h @@ -157,7 +157,7 @@ do { \ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ else if ((level) >= 3) \ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ + __FUNCTION__, __LINE__ , ## args); \ } \ } while (0) # define KDBG(level, fmt, args...) \ @@ -167,7 +167,7 @@ do { \ pr_info("zc0301: " fmt "\n", ## args); \ else if ((level) == 3) \ pr_debug("zc0301: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ + __LINE__ , ## args); \ } \ } while (0) # define V4LDBG(level, name, cmd) \ @@ -184,7 +184,7 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) + __FUNCTION__, __LINE__ , ## args) #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 4036c6268bff..0fad39754f7a 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -48,7 +48,7 @@ /*****************************************************************************/ #define ZC0301_MODULE_NAME "V4L2 driver for ZC0301 " \ - "Image Processor and Control Chip" + "Image Processor and Control Chip" #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" #define ZC0301_AUTHOR_EMAIL "" #define ZC0301_MODULE_LICENSE "GPL" @@ -67,67 +67,67 @@ MODULE_LICENSE(ZC0301_MODULE_LICENSE); static short video_nr[] = {[0 ... ZC0301_MAX_DEVICES-1] = -1}; module_param_array(video_nr, short, NULL, 0444); MODULE_PARM_DESC(video_nr, - "\n<-1|n[,...]> Specify V4L2 minor mode number." - "\n -1 = use next available (default)" - "\n n = use minor number n (integer >= 0)" - "\nYou can specify up to " - __MODULE_STRING(ZC0301_MAX_DEVICES) " cameras this way." - "\nFor example:" - "\nvideo_nr=-1,2,-1 would assign minor number 2 to" - "\nthe second registered camera and use auto for the first" - "\none and for every other camera." - "\n"); + "\n<-1|n[,...]> Specify V4L2 minor mode number." + "\n -1 = use next available (default)" + "\n n = use minor number n (integer >= 0)" + "\nYou can specify up to " + __MODULE_STRING(ZC0301_MAX_DEVICES) " cameras this way." + "\nFor example:" + "\nvideo_nr=-1,2,-1 would assign minor number 2 to" + "\nthe second registered camera and use auto for the first" + "\none and for every other camera." + "\n"); static short force_munmap[] = {[0 ... ZC0301_MAX_DEVICES-1] = - ZC0301_FORCE_MUNMAP}; + ZC0301_FORCE_MUNMAP}; module_param_array(force_munmap, bool, NULL, 0444); MODULE_PARM_DESC(force_munmap, - "\n<0|1[,...]> Force the application to unmap previously" - "\nmapped buffer memory before calling any VIDIOC_S_CROP or" - "\nVIDIOC_S_FMT ioctl's. Not all the applications support" - "\nthis feature. This parameter is specific for each" - "\ndetected camera." - "\n 0 = do not force memory unmapping" - "\n 1 = force memory unmapping (save memory)" - "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." - "\n"); + "\n<0|1[,...]> Force the application to unmap previously" + "\nmapped buffer memory before calling any VIDIOC_S_CROP or" + "\nVIDIOC_S_FMT ioctl's. Not all the applications support" + "\nthis feature. This parameter is specific for each" + "\ndetected camera." + "\n 0 = do not force memory unmapping" + "\n 1 = force memory unmapping (save memory)" + "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." + "\n"); static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] = - ZC0301_FRAME_TIMEOUT}; + ZC0301_FRAME_TIMEOUT}; module_param_array(frame_timeout, uint, NULL, 0644); MODULE_PARM_DESC(frame_timeout, - "\n Timeout for a video frame in seconds." - "\nThis parameter is specific for each detected camera." - "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"." - "\n"); + "\n Timeout for a video frame in seconds." + "\nThis parameter is specific for each detected camera." + "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"." + "\n"); #ifdef ZC0301_DEBUG static unsigned short debug = ZC0301_DEBUG_LEVEL; module_param(debug, ushort, 0644); MODULE_PARM_DESC(debug, - "\n Debugging information level, from 0 to 3:" - "\n0 = none (use carefully)" - "\n1 = critical errors" - "\n2 = significant informations" - "\n3 = more verbose messages" - "\nLevel 3 is useful for testing only, when only " - "one device is used." - "\nDefault value is "__MODULE_STRING(ZC0301_DEBUG_LEVEL)"." - "\n"); + "\n Debugging information level, from 0 to 3:" + "\n0 = none (use carefully)" + "\n1 = critical errors" + "\n2 = significant informations" + "\n3 = more verbose messages" + "\nLevel 3 is useful for testing only, when only " + "one device is used." + "\nDefault value is "__MODULE_STRING(ZC0301_DEBUG_LEVEL)"." + "\n"); #endif /*****************************************************************************/ static u32 zc0301_request_buffers(struct zc0301_device* cam, u32 count, - enum zc0301_io_method io) + enum zc0301_io_method io) { struct v4l2_pix_format* p = &(cam->sensor.pix_format); struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); const size_t imagesize = cam->module_param.force_munmap || - io == IO_READ ? - (p->width * p->height * p->priv) / 8 : - (r->width * r->height * p->priv) / 8; + io == IO_READ ? + (p->width * p->height * p->priv) / 8 : + (r->width * r->height * p->priv) / 8; void* buff = NULL; u32 i; @@ -216,7 +216,7 @@ int zc0301_write_reg(struct zc0301_device* cam, u16 index, u16 value) int res; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0xa0, 0x40, - value, index, NULL, 0, ZC0301_CTRL_TIMEOUT); + value, index, NULL, 0, ZC0301_CTRL_TIMEOUT); if (res < 0) { DBG(3, "Failed to write a register (index 0x%04X, " "value 0x%02X, error %d)",index, value, res); @@ -234,7 +234,7 @@ int zc0301_read_reg(struct zc0301_device* cam, u16 index) int res; res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0xa1, 0xc0, - 0x0001, index, buff, 1, ZC0301_CTRL_TIMEOUT); + 0x0001, index, buff, 1, ZC0301_CTRL_TIMEOUT); if (res < 0) DBG(3, "Failed to read a register (index 0x%04X, error %d)", index, res); @@ -337,11 +337,11 @@ static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs) if (!(*f)) (*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t, - frame); + frame); imagesize = (cam->sensor.pix_format.width * - cam->sensor.pix_format.height * - cam->sensor.pix_format.priv) / 8; + cam->sensor.pix_format.height * + cam->sensor.pix_format.priv) / 8; for (i = 0; i < urb->number_of_packets; i++) { unsigned int len, status; @@ -395,8 +395,8 @@ end_of_frame: list_move_tail(&(*f)->frame, &cam->outqueue); if (!list_empty(&cam->inqueue)) (*f) = list_entry(cam->inqueue.next, - struct zc0301_frame_t, - frame); + struct zc0301_frame_t, + frame); else (*f) = NULL; spin_unlock(&cam->queue_lock); @@ -429,14 +429,14 @@ static int zc0301_start_transfer(struct zc0301_device* cam) struct usb_device *udev = cam->usbdev; struct urb* urb; const unsigned int wMaxPacketSize[] = {0, 128, 192, 256, 384, - 512, 768, 1023}; + 512, 768, 1023}; const unsigned int psz = wMaxPacketSize[ZC0301_ALTERNATE_SETTING]; s8 i, j; int err = 0; for (i = 0; i < ZC0301_URBS; i++) { cam->transfer_buffer[i] = kzalloc(ZC0301_ISO_PACKETS * psz, - GFP_KERNEL); + GFP_KERNEL); if (!cam->transfer_buffer[i]) { err = -ENOMEM; DBG(1, "Not enough memory"); @@ -528,9 +528,9 @@ static int zc0301_stream_interrupt(struct zc0301_device* cam) cam->stream = STREAM_INTERRUPT; timeout = wait_event_timeout(cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED), - ZC0301_URB_TIMEOUT); + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + ZC0301_URB_TIMEOUT); if (cam->state & DEV_DISCONNECTED) return -ENODEV; else if (cam->stream != STREAM_OFF) { @@ -548,7 +548,7 @@ static int zc0301_stream_interrupt(struct zc0301_device* cam) static int zc0301_set_compression(struct zc0301_device* cam, - struct v4l2_jpegcompression* compression) + struct v4l2_jpegcompression* compression) { int r, err = 0; @@ -670,8 +670,8 @@ static int zc0301_open(struct inode* inode, struct file* filp) } mutex_unlock(&cam->dev_mutex); err = wait_event_interruptible_exclusive(cam->open, - cam->state & DEV_DISCONNECTED - || !cam->users); + cam->state & DEV_DISCONNECTED + || !cam->users); if (err) { up_read(&zc0301_disconnect); return err; @@ -802,12 +802,12 @@ zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) return -EAGAIN; } timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); if (timeout < 0) { mutex_unlock(&cam->fileop_mutex); return timeout; @@ -930,7 +930,7 @@ static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) { struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); unsigned long size = vma->vm_end - vma->vm_start, - start = vma->vm_start; + start = vma->vm_start; void *pos; u32 i; @@ -998,13 +998,13 @@ zc0301_vidioc_querycap(struct zc0301_device* cam, void __user * arg) .driver = "zc0301", .version = ZC0301_MODULE_VERSION_CODE, .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, + V4L2_CAP_STREAMING, }; strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, - sizeof(cap.bus_info)); + sizeof(cap.bus_info)); if (copy_to_user(arg, &cap, sizeof(cap))) return -EFAULT; @@ -1337,7 +1337,7 @@ zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg) static int zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, - void __user * arg) + void __user * arg) { struct zc0301_sensor* s = &cam->sensor; struct v4l2_format format; @@ -1600,7 +1600,7 @@ zc0301_vidioc_qbuf(struct zc0301_device* cam, void __user * arg) static int zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp, - void __user * arg) + void __user * arg) { struct v4l2_buffer b; struct zc0301_frame_t *f; @@ -1619,12 +1619,12 @@ zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp, if (filp->f_flags & O_NONBLOCK) return -EAGAIN; timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1) ); + ( cam->wait_frame, + (!list_empty(&cam->outqueue)) || + (cam->state & DEV_DISCONNECTED) || + (cam->state & DEV_MISCONFIGURED), + cam->module_param.frame_timeout * + 1000 * msecs_to_jiffies(1) ); if (timeout < 0) return timeout; if (cam->state & DEV_DISCONNECTED) @@ -1748,7 +1748,7 @@ zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg) static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, - unsigned int cmd, void __user * arg) + unsigned int cmd, void __user * arg) { struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); @@ -1842,7 +1842,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, static int zc0301_ioctl(struct inode* inode, struct file* filp, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); int err = 0; @@ -1948,7 +1948,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) mutex_lock(&cam->dev_mutex); err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); + video_nr[dev_nr]); if (err) { DBG(1, "V4L2 device registration failed"); if (err == -ENFILE && video_nr[dev_nr] == -1) diff --git a/drivers/media/video/zc0301/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c index 9d282a22c15f..eaadf0252049 100644 --- a/drivers/media/video/zc0301/zc0301_pas202bcb.c +++ b/drivers/media/video/zc0301/zc0301_pas202bcb.c @@ -24,10 +24,10 @@ /* NOTE: Sensor controls are disabled for now, becouse changing them while - streaming sometimes results in out-of-sync video frames. We'll use - the default initialization, until we know how to stop and start video - in the chip. However, the image quality still looks good under various - light conditions. + streaming sometimes results in out-of-sync video frames. We'll use + the default initialization, until we know how to stop and start video + in the chip. However, the image quality still looks good under various + light conditions. */ #include @@ -165,7 +165,7 @@ static int pas202bcb_init(struct zc0301_device* cam) static int pas202bcb_get_ctrl(struct zc0301_device* cam, - struct v4l2_control* ctrl) + struct v4l2_control* ctrl) { switch (ctrl->id) { case V4L2_CID_EXPOSURE: @@ -208,7 +208,7 @@ static int pas202bcb_get_ctrl(struct zc0301_device* cam, static int pas202bcb_set_ctrl(struct zc0301_device* cam, - const struct v4l2_control* ctrl) + const struct v4l2_control* ctrl) { int err = 0; diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h index cf0965a81d01..1f95c28b1015 100644 --- a/drivers/media/video/zc0301/zc0301_sensor.h +++ b/drivers/media/video/zc0301/zc0301_sensor.h @@ -51,7 +51,7 @@ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); #define ZC0301_USB_DEVICE(vend, prod, intclass) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ - USB_DEVICE_ID_MATCH_INT_CLASS, \ + USB_DEVICE_ID_MATCH_INT_CLASS, \ .idVendor = (vend), \ .idProduct = (prod), \ .bInterfaceClass = (intclass) @@ -92,7 +92,7 @@ struct zc0301_sensor { int (*init)(struct zc0301_device*); int (*get_ctrl)(struct zc0301_device*, struct v4l2_control* ctrl); int (*set_ctrl)(struct zc0301_device*, - const struct v4l2_control* ctrl); + const struct v4l2_control* ctrl); int (*set_crop)(struct zc0301_device*, const struct v4l2_rect* rect); /* Private */ diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index ad04a129499d..0166f555a5ca 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran.h @@ -1,4 +1,4 @@ -/* +/* * zoran - Iomega Buz driver * * Copyright (C) 1999 Rainer Johanni diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index b22dbb6d18f6..0a85c9e7fb48 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c @@ -4,7 +4,7 @@ * Media Labs LML33/LML33R10. * * This part handles card-specific data and detection - * + * * Copyright (C) 2000 Serguei Miridonov * * Currently maintained by: diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran_card.h index e5b6acd3eedc..ad997c30bee5 100644 --- a/drivers/media/video/zoran_card.h +++ b/drivers/media/video/zoran_card.h @@ -4,7 +4,7 @@ * Media Labs LML33/LML33R10. * * This part handles card-specific data and detection - * + * * Copyright (C) 2000 Serguei Miridonov * * Currently maintained by: diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index 4e15afdec4c9..c690b2ee880a 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -4,7 +4,7 @@ * Media Labs LML33/LML33R10. * * This part handles device access (PCI/I2C/codec/...) - * + * * Copyright (C) 2000 Serguei Miridonov * * Currently maintained by: @@ -492,7 +492,7 @@ zr36057_set_vfe (struct zoran *zr, /* (Ronald) don't write this if overlay_mask = NULL */ if (zr->overlay_mask) { /* Write overlay clipping mask data, but don't enable overlay clipping */ - /* RJ: since this makes only sense on the screen, we use + /* RJ: since this makes only sense on the screen, we use * zr->overlay_settings.width instead of video_width */ mask_line_size = (BUZ_MAX_WIDTH + 31) / 32; @@ -819,12 +819,12 @@ zr36057_set_jpg (struct zoran *zr, if (zr->card.vfe_pol.hsync_pol) btor(ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR); else - btand(~ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR); + btand(~ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR); reg = ((tvn->HSyncStart) << ZR36057_HSP_HsyncStart) | (tvn->Wt << ZR36057_HSP_LineTot); btwrite(reg, ZR36057_HSP); reg = ((zr->jpg_settings.img_x + - tvn->HStart + 4) << ZR36057_FHAP_NAX) | + tvn->HStart + 4) << ZR36057_FHAP_NAX) | (zr->jpg_settings.img_width << ZR36057_FHAP_PAX); btwrite(reg, ZR36057_FHAP); @@ -1272,15 +1272,15 @@ error_handler (struct zoran *zr, if (zr->JPEG_error != 1) { /* * First entry: error just happened during normal operation - * + * * In BUZ_MODE_MOTION_COMPRESS: - * + * * Possible glitch in TV signal. In this case we should * stop the codec and wait for good quality signal before * restarting it to avoid further problems - * + * * In BUZ_MODE_MOTION_DECOMPRESS: - * + * * Bad JPEG frame: we have to mark it as processed (codec crashed * and was not able to do it itself), and to remove it from queue. */ diff --git a/drivers/media/video/zoran_device.h b/drivers/media/video/zoran_device.h index f315203d7105..f19705cbdb39 100644 --- a/drivers/media/video/zoran_device.h +++ b/drivers/media/video/zoran_device.h @@ -4,7 +4,7 @@ * Media Labs LML33/LML33R10. * * This part handles card-specific data and detection - * + * * Copyright (C) 2000 Serguei Miridonov * * Currently maintained by: diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index b2c6e01e3923..b5a576a37fd2 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -94,7 +94,7 @@ V4L2_CAP_VIDEO_CAPTURE |\ V4L2_CAP_VIDEO_OUTPUT |\ V4L2_CAP_VIDEO_OVERLAY \ - ) + ) #endif #include @@ -165,7 +165,7 @@ const struct zoran_format zoran_formats[] = { #endif .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | - ZORAN_FORMAT_OVERLAY, + ZORAN_FORMAT_OVERLAY, }, { .name = "Hardware-encoded Motion-JPEG", .palette = -1, @@ -670,7 +670,7 @@ jpg_fbuffer_free (struct file *file) j])))); free_page((unsigned long) bus_to_virt - (le32_to_cpu + (le32_to_cpu (fh->jpg_buffers. buffer[i]. frag_tab[2 * j]))); @@ -1871,7 +1871,7 @@ zoran_v4l2_buffer_status (struct file *file, static int zoran_set_norm (struct zoran *zr, - int norm) /* VIDEO_MODE_* */ + int norm) /* VIDEO_MODE_* */ { int norm_encoder, on; @@ -2006,9 +2006,9 @@ zoran_set_input (struct zoran *zr, static int zoran_do_ioctl (struct inode *inode, - struct file *file, - unsigned int cmd, - void *arg) + struct file *file, + unsigned int cmd, + void *arg) { struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; @@ -2095,7 +2095,7 @@ zoran_do_ioctl (struct inode *inode, break; /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says: - * + * * * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input." * * ^^^^^^^ * * The famos BTTV driver has it implemented with a struct video_channel argument diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c index f0d9b13c3c6c..a00fae90229a 100644 --- a/drivers/media/video/zoran_procfs.c +++ b/drivers/media/video/zoran_procfs.c @@ -4,7 +4,7 @@ * Media Labs LML33/LML33R10. * * This part handles the procFS entries (/proc/ZORAN[%d]) - * + * * Copyright (C) 2000 Serguei Miridonov * * Currently maintained by: diff --git a/drivers/media/video/zoran_procfs.h b/drivers/media/video/zoran_procfs.h index 8904fc959555..f2d5b1ba448f 100644 --- a/drivers/media/video/zoran_procfs.h +++ b/drivers/media/video/zoran_procfs.h @@ -4,7 +4,7 @@ * Media Labs LML33/LML33R10. * * This part handles card-specific data and detection - * + * * Copyright (C) 2000 Serguei Miridonov * * Currently maintained by: diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c index 10130ef67ea7..62f77584fb85 100644 --- a/drivers/media/video/zr36016.c +++ b/drivers/media/video/zr36016.c @@ -34,7 +34,7 @@ #include #include -/* includes for structures and defines regarding video +/* includes for structures and defines regarding video #include */ /* I/O commands, error codes */ @@ -143,8 +143,8 @@ zr36016_readi (struct zr36016 *ptr, static void zr36016_writei (struct zr36016 *ptr, - u16 reg, - u8 value) + u16 reg, + u8 value) { dprintk(4, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name, value, reg); @@ -192,7 +192,7 @@ zr36016_basic_test (struct zr36016 *ptr) dprintk(1, "\n"); } // for testing just write 0, then the default value to a register and read - // it back in both cases + // it back in both cases zr36016_writei(ptr, ZR016I_PAX_LO, 0x00); if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) { dprintk(1, @@ -232,17 +232,17 @@ zr36016_basic_test (struct zr36016 *ptr) static int zr36016_pushit (struct zr36016 *ptr, u16 startreg, u16 len, - const char *data) + const char *data) { - int i=0; + int i=0; - dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", + dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name, startreg,len); - while (i #include -/* includes for structures and defines regarding video +/* includes for structures and defines regarding video #include */ /* I/O commands, error codes */ @@ -171,7 +171,7 @@ zr36050_wait_end (struct zr36050 *ptr) /* ========================================================================= Local helper function: - basic test of "connectivity", writes/reads to/from memory the SOF marker + basic test of "connectivity", writes/reads to/from memory the SOF marker ========================================================================= */ static int @@ -218,9 +218,9 @@ zr36050_basic_test (struct zr36050 *ptr) static int zr36050_pushit (struct zr36050 *ptr, - u16 startreg, - u16 len, - const char *data) + u16 startreg, + u16 len, + const char *data) { int i = 0; @@ -345,7 +345,7 @@ static const char zr36050_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 }; /* ------------------------------------------------------------------------- */ /* SOF (start of frame) segment depends on width, height and sampling ratio - of each color component */ + of each color component */ static int zr36050_set_sof (struct zr36050 *ptr) @@ -376,8 +376,8 @@ zr36050_set_sof (struct zr36050 *ptr) /* ------------------------------------------------------------------------- */ -/* SOS (start of scan) segment depends on the used scan components - of each color component */ +/* SOS (start of scan) segment depends on the used scan components + of each color component */ static int zr36050_set_sos (struct zr36050 *ptr) diff --git a/drivers/media/video/zr36057.h b/drivers/media/video/zr36057.h index 159abfa034d9..54c9362aa980 100644 --- a/drivers/media/video/zr36057.h +++ b/drivers/media/video/zr36057.h @@ -1,4 +1,4 @@ -/* +/* * zr36057.h - zr36057 register offsets * * Copyright (C) 1998 Dave Perks @@ -27,14 +27,14 @@ #define ZR36057_VFEHCR 0x000 /* Video Front End, Horizontal Configuration Register */ #define ZR36057_VFEHCR_HSPol (1<<30) #define ZR36057_VFEHCR_HStart 10 -#define ZR36057_VFEHCR_HEnd 0 -#define ZR36057_VFEHCR_Hmask 0x3ff +#define ZR36057_VFEHCR_HEnd 0 +#define ZR36057_VFEHCR_Hmask 0x3ff #define ZR36057_VFEVCR 0x004 /* Video Front End, Vertical Configuration Register */ #define ZR36057_VFEVCR_VSPol (1<<30) #define ZR36057_VFEVCR_VStart 10 -#define ZR36057_VFEVCR_VEnd 0 -#define ZR36057_VFEVCR_Vmask 0x3ff +#define ZR36057_VFEVCR_VEnd 0 +#define ZR36057_VFEVCR_Vmask 0x3ff #define ZR36057_VFESPFR 0x008 /* Video Front End, Scaler and Pixel Format Register */ #define ZR36057_VFESPFR_ExtFl (1<<26) diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c index d8dd003a7aad..97c8f9b9dc12 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zr36060.c @@ -34,7 +34,7 @@ #include #include -/* includes for structures and defines regarding video +/* includes for structures and defines regarding video #include */ /* I/O commands, error codes */ @@ -173,7 +173,7 @@ zr36060_wait_end (struct zr36060 *ptr) /* ========================================================================= Local helper function: - basic test of "connectivity", writes/reads to/from memory the SOF marker + basic test of "connectivity", writes/reads to/from memory the SOF marker ========================================================================= */ static int @@ -208,9 +208,9 @@ zr36060_basic_test (struct zr36060 *ptr) static int zr36060_pushit (struct zr36060 *ptr, - u16 startreg, - u16 len, - const char *data) + u16 startreg, + u16 len, + const char *data) { int i = 0; @@ -335,7 +335,7 @@ static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 }; /* ------------------------------------------------------------------------- */ /* SOF (start of frame) segment depends on width, height and sampling ratio - of each color component */ + of each color component */ static int zr36060_set_sof (struct zr36060 *ptr) @@ -367,8 +367,8 @@ zr36060_set_sof (struct zr36060 *ptr) /* ------------------------------------------------------------------------- */ -/* SOS (start of scan) segment depends on the used scan components - of each color component */ +/* SOS (start of scan) segment depends on the used scan components + of each color component */ static int zr36060_set_sos (struct zr36060 *ptr) @@ -385,7 +385,7 @@ zr36060_set_sos (struct zr36060 *ptr) for (i = 0; i < NO_OF_COMPONENTS; i++) { sos_data[5 + (i * 2)] = i; // index sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) | - zr36060_ta[i]; // AC/DC tbl.sel. + zr36060_ta[i]; // AC/DC tbl.sel. } sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00; // scan start sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f; @@ -999,7 +999,7 @@ zr36060_cleanup_module (void) dprintk(1, "zr36060: something's wrong - %d codecs left somehow.\n", zr36060_codecs); - } + } /* however, we can't just stay alive */ videocodec_unregister(&zr36060_codec); diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c index d4c633b8a7f5..9d340aa443c3 100644 --- a/drivers/media/video/zr36120.c +++ b/drivers/media/video/zr36120.c @@ -316,7 +316,7 @@ DEBUG(printk(CARD_DEBUG "%p added to queue\n",CARD,item)); item->status = FBUFFER_BUSY; if (!lastitem) ztv->workqueue = item; - else + else lastitem->next = item; lastitem = item; } @@ -516,7 +516,7 @@ DEBUG(printk(KERN_DEBUG " %d: clip(%d,%d,%d,%d)\n", i,vp->x,vp->y,vp->widt zraor((ztv->vidInterlace*ystep)<<0,~ZORAN_OCR_MASKSTRIDE,ZORAN_OCR); } -struct tvnorm +struct tvnorm { u16 Wt, Wa, Ht, Ha, HStart, VStart; }; @@ -660,7 +660,7 @@ DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Hstart, Hend)); int HorDcm = 64-X; int hcrop1 = 2*(Wa-We)/4; /* - * BUGFIX: Juha Nurmela + * BUGFIX: Juha Nurmela * found the solution to the color phase shift. * See ChangeLog for the full explanation) */ @@ -812,12 +812,12 @@ void zoran_close(struct video_device* dev) zoran_common_close(ztv); - /* - * This is sucky but right now I can't find a good way to - * be sure its safe to free the buffer. We wait 5-6 fields - * which is more than sufficient to be sure. - */ - msleep(100); /* Wait 1/10th of a second */ + /* + * This is sucky but right now I can't find a good way to + * be sure its safe to free the buffer. We wait 5-6 fields + * which is more than sufficient to be sure. + */ + msleep(100); /* Wait 1/10th of a second */ /* free the allocated framebuffer */ bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE); @@ -1436,7 +1436,7 @@ int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg) /* Why isn't this in the API? * And why doesn't it take a buffer number? - case BTTV_FIELDNR: + case BTTV_FIELDNR: { unsigned long v = ztv->lastfieldnr; if (copy_to_user(arg,&v,sizeof(v))) @@ -1557,12 +1557,12 @@ void vbi_close(struct video_device *dev) zoran_common_close(ztv); - /* - * This is sucky but right now I can't find a good way to - * be sure its safe to free the buffer. We wait 5-6 fields - * which is more than sufficient to be sure. - */ - msleep(100); /* Wait 1/10th of a second */ + /* + * This is sucky but right now I can't find a good way to + * be sure its safe to free the buffer. We wait 5-6 fields + * which is more than sufficient to be sure. + */ + msleep(100); /* Wait 1/10th of a second */ for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) { @@ -1620,7 +1620,7 @@ long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonb write_unlock_irq(&ztv->lock); return -EWOULDBLOCK; } - + /* mark the unused buffer as wanted */ unused->status = FBUFFER_BUSY; unused->next = 0; @@ -1671,7 +1671,7 @@ long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonb if (count == 2*19*2048) { /* * Extreme HACK, old VBI programs expect 2048 points - * of data, and we only got 864 orso. Double each + * of data, and we only got 864 orso. Double each * datapoint and clear the rest of the line. * This way we have appear to have a * sample_frequency of 29.5 Mc. @@ -1956,7 +1956,7 @@ int __init init_zoran(int card) zrand(~ZORAN_VDC_TRICOM, ZORAN_VDC); /* external FL determines TOP frame */ - zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC); + zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC); /* set HSpol */ if (ztv->card->hsync_pos) @@ -2012,7 +2012,7 @@ void release_zoran(int max) struct zoran *ztv; int i; - for (i=0;idev->irq,ztv); - + /* unregister i2c_bus */ i2c_unregister_bus((&ztv->i2c)); @@ -2050,7 +2050,7 @@ void __exit zr36120_exit(void) int __init zr36120_init(void) { int card; - + handle_chipset(); zoran_cards = find_zoran(); if (zoran_cards<0) @@ -2063,7 +2063,7 @@ int __init zr36120_init(void) /* only release the zorans we have registered */ release_zoran(card); return -EIO; - } + } } return 0; } diff --git a/drivers/media/video/zr36120.h b/drivers/media/video/zr36120.h index 571f8e84b58a..a71e485b0f98 100644 --- a/drivers/media/video/zr36120.h +++ b/drivers/media/video/zr36120.h @@ -1,4 +1,4 @@ -/* +/* zr36120.h - Zoran 36120/36125 based framegrabbers Copyright (C) 1998-1999 Pauline Middelink (middelin@polyware.nl) @@ -89,7 +89,7 @@ struct vidinfo { ulong* overlay; /* kernel addr of overlay mask */ }; -struct zoran +struct zoran { struct video_device video_dev; #define CARD_DEBUG KERN_DEBUG "%s(%lu): " @@ -106,7 +106,7 @@ struct zoran uint norm; /* 0=PAL, 1=NTSC, 2=SECAM */ uint tuner_freq; /* Current freq in kHz */ struct video_picture picture; /* Current picture params */ - + /* videocard details */ uint swidth; /* screen width */ uint sheight; /* screen height */ -- cgit v1.2.3-59-g8ed1b From 22fe087f0139e2f5cbe004f24f84cb1c08b4711e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 25 Mar 2006 09:24:19 -0300 Subject: V4L/DVB (3604): V4l printk fix drivers/media/video/v4l2-common.c: In function `v4l_printk_ioctl_arg': drivers/media/video/v4l2-common.c:477: warning: `0' flag used with `%p' printf format Someone went and "improved" my patch ;) Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 6824ee045fe6..11a97f30b876 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -472,7 +472,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) prt_names(p->memory,v4l2_memory_names), p->m.userptr); printk ("%s: timecode= %02d:%02d:%02d type=%d, " - "flags=0x%08x, frames=%d, userbits=0x%08p\n", + "flags=0x%08x, frames=%d, userbits=0x%p\n", s,tc->hours,tc->minutes,tc->seconds, tc->type, tc->flags, tc->frames, tc->userbits); break; -- cgit v1.2.3-59-g8ed1b From f52ac8fec8a13e207f675b0c16e0d5f800c1c204 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Sat, 25 Mar 2006 03:06:37 -0800 Subject: [PATCH] cirrus ep93xx watchdog driver Add a driver for the on-chip watchdog on the cirrus ep93xx series of ARM CPUs. Signed-off-by: Lennert Buytenhek Cc: Wim Van Sebroeck Cc: Russell King Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/watchdog/Kconfig | 10 ++ drivers/char/watchdog/Makefile | 1 + drivers/char/watchdog/ep93xx_wdt.c | 257 +++++++++++++++++++++++++++++++++++++ 3 files changed, 268 insertions(+) create mode 100644 drivers/char/watchdog/ep93xx_wdt.c (limited to 'drivers') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index c0dfcf273f0a..16e99db2e12d 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -148,6 +148,16 @@ config MPCORE_WATCHDOG To compile this driver as a module, choose M here: the module will be called mpcore_wdt. +config EP93XX_WATCHDOG + tristate "EP93xx Watchdog" + depends on WATCHDOG && ARCH_EP93XX + help + Say Y here if to include support for the watchdog timer + embedded in the Cirrus Logic EP93xx family of devices. + + To compile this driver as a module, choose M here: the + module will be called ep93xx_wdt. + # X86 (i386 + ia64 + x86_64) Architecture config ACQUIRE_WDT diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 36c0b282b8ba..d6f27fde9905 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o +obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o # X86 (i386 + ia64 + x86_64) Architecture obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/char/watchdog/ep93xx_wdt.c new file mode 100644 index 000000000000..9021dbb78299 --- /dev/null +++ b/drivers/char/watchdog/ep93xx_wdt.c @@ -0,0 +1,257 @@ +/* + * Watchdog driver for Cirrus Logic EP93xx family of devices. + * + * Copyright (c) 2004 Ray Lehtiniemi + * Copyright (c) 2006 Tower Technologies + * Based on ep93xx driver, bits from alim7101_wdt.c + * + * Authors: Ray Lehtiniemi , + * Alessandro Zummo + * + * 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. + * + * This watchdog fires after 250msec, which is a too short interval + * for us to rely on the user space daemon alone. So we ping the + * wdt each ~200msec and eventually stop doing it if the user space + * daemon dies. + * + * TODO: + * + * - Test last reset from watchdog status + * - Add a few missing ioctls + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define WDT_VERSION "0.3" +#define PFX "ep93xx_wdt: " + +/* default timeout (secs) */ +#define WDT_TIMEOUT 30 + +static int nowayout = WATCHDOG_NOWAYOUT; +static int timeout = WDT_TIMEOUT; + +static struct timer_list timer; +static unsigned long next_heartbeat; +static unsigned long wdt_status; +static unsigned long boot_status; + +#define WDT_IN_USE 0 +#define WDT_OK_TO_CLOSE 1 + +#define EP93XX_WDT_REG(x) (EP93XX_WATCHDOG_BASE + (x)) +#define EP93XX_WDT_WATCHDOG EP93XX_WDT_REG(0x00) +#define EP93XX_WDT_WDSTATUS EP93XX_WDT_REG(0x04) + +/* reset the wdt every ~200ms */ +#define WDT_INTERVAL (HZ/5) + +static void wdt_enable(void) +{ + __raw_writew(0xaaaa, EP93XX_WDT_WATCHDOG); +} + +static void wdt_disable(void) +{ + __raw_writew(0xaa55, EP93XX_WDT_WATCHDOG); +} + +static inline void wdt_ping(void) +{ + __raw_writew(0x5555, EP93XX_WDT_WATCHDOG); +} + +static void wdt_startup(void) +{ + next_heartbeat = jiffies + (timeout * HZ); + + wdt_enable(); + mod_timer(&timer, jiffies + WDT_INTERVAL); +} + +static void wdt_shutdown(void) +{ + del_timer_sync(&timer); + wdt_disable(); +} + +static void wdt_keepalive(void) +{ + /* user land ping */ + next_heartbeat = jiffies + (timeout * HZ); +} + +static int ep93xx_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(WDT_IN_USE, &wdt_status)) + return -EBUSY; + + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + + wdt_startup(); + + return nonseekable_open(inode, file); +} + +static ssize_t +ep93xx_wdt_write(struct file *file, const char __user *data, size_t len, + loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (*ppos != file->f_pos) + return -ESPIPE; + + if (len) { + if (!nowayout) { + size_t i; + + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) + return -EFAULT; + + if (c == 'V') + set_bit(WDT_OK_TO_CLOSE, &wdt_status); + else + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + } + } + wdt_keepalive(); + } + + return len; +} + +static struct watchdog_info ident = { + .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE, + .identity = "EP93xx Watchdog", +}; + +static int +ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret = -ENOIOCTLCMD; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = copy_to_user((struct watchdog_info __user *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + break; + + case WDIOC_GETSTATUS: + ret = put_user(0, (int __user *)arg); + break; + + case WDIOC_GETBOOTSTATUS: + ret = put_user(boot_status, (int __user *)arg); + break; + + case WDIOC_GETTIMEOUT: + /* actually, it is 0.250 seconds.... */ + ret = put_user(1, (int __user *)arg); + break; + + case WDIOC_KEEPALIVE: + wdt_keepalive(); + ret = 0; + break; + } + return ret; +} + +static int ep93xx_wdt_release(struct inode *inode, struct file *file) +{ + if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) + wdt_shutdown(); + else + printk(KERN_CRIT PFX "Device closed unexpectedly - " + "timer will not stop\n"); + + clear_bit(WDT_IN_USE, &wdt_status); + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + + return 0; +} + +static struct file_operations ep93xx_wdt_fops = { + .owner = THIS_MODULE, + .write = ep93xx_wdt_write, + .ioctl = ep93xx_wdt_ioctl, + .open = ep93xx_wdt_open, + .release = ep93xx_wdt_release, +}; + +static struct miscdevice ep93xx_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &ep93xx_wdt_fops, +}; + +static void ep93xx_timer_ping(unsigned long data) +{ + if (time_before(jiffies, next_heartbeat)) + wdt_ping(); + + /* Re-set the timer interval */ + mod_timer(&timer, jiffies + WDT_INTERVAL); +} + +static int __init ep93xx_wdt_init(void) +{ + int err; + + err = misc_register(&ep93xx_wdt_miscdev); + + boot_status = __raw_readl(EP93XX_WDT_WATCHDOG) & 0x01 ? 1 : 0; + + printk(KERN_INFO PFX "EP93XX watchdog, driver version " + WDT_VERSION "%s\n", + (__raw_readl(EP93XX_WDT_WATCHDOG) & 0x08) + ? " (nCS1 disable detected)" : ""); + + if (timeout < 1 || timeout > 3600) { + timeout = WDT_TIMEOUT; + printk(KERN_INFO PFX + "timeout value must be 1<=x<=3600, using %d\n", + timeout); + } + + setup_timer(&timer, ep93xx_timer_ping, 1); + return err; +} + +static void __exit ep93xx_wdt_exit(void) +{ + wdt_shutdown(); + misc_deregister(&ep93xx_wdt_miscdev); +} + +module_init(ep93xx_wdt_init); +module_exit(ep93xx_wdt_exit); + +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); + +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +MODULE_AUTHOR("Ray Lehtiniemi ," + "Alessandro Zummo "); +MODULE_DESCRIPTION("EP93xx Watchdog"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(WDT_VERSION); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.3-59-g8ed1b From c41a24ce1fe13638732885859011321af862960a Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 25 Mar 2006 03:07:02 -0800 Subject: [PATCH] ISDN: fix copy_to_user() unused result warning in isdn_ppp drivers/isdn/i4l/isdn_ppp.c:785: warning: ignoring return value of `copy_to_user', declared with attribute warn_unused_result Signed-off-by: Jesper Juhl Signed-off-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/i4l/isdn_ppp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 1a19a0f89428..b9fed8a3bcc6 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -782,7 +782,8 @@ isdn_ppp_read(int min, struct file *file, char __user *buf, int count) is->first = b; spin_unlock_irqrestore(&is->buflock, flags); - copy_to_user(buf, save_buf, count); + if (copy_to_user(buf, save_buf, count)) + count = -EFAULT; kfree(save_buf); return count; -- cgit v1.2.3-59-g8ed1b From 1aef821a6b3aeca8c19d06aee012ed9db617d1e3 Mon Sep 17 00:00:00 2001 From: Thomas Koeller Date: Sat, 25 Mar 2006 03:07:03 -0800 Subject: [PATCH] constify tty flip buffer handling Add a couple of 'const' qualifiers to the TTY flip buffer APIs, where appropriate. Signed-off-by: Thomas Koeller Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 4 ++-- include/linux/tty_flip.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 76592ee1fb38..48d795bb8c4b 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -354,7 +354,7 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) EXPORT_SYMBOL_GPL(tty_buffer_request_room); -int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size) +int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size) { int copied = 0; do { @@ -378,7 +378,7 @@ int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t EXPORT_SYMBOL_GPL(tty_insert_flip_string); -int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size) +int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size) { int copied = 0; do { diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 0c6169fff366..0976a163b459 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -2,8 +2,8 @@ #define _LINUX_TTY_FLIP_H extern int tty_buffer_request_room(struct tty_struct *tty, size_t size); -extern int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size); -extern int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size); +extern int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size); +extern int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size); extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size); extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size); -- cgit v1.2.3-59-g8ed1b From 5b7b18ccdeb17dcc4a2ddbf4ce87094c7365f4b9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 25 Mar 2006 03:07:04 -0800 Subject: [PATCH] drivers/block/nbd.c: don't defer compile error to runtime If we can detect a problem at compile time, the compilation should fail. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/nbd.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index a9bde30dadad..8bca4905d7f7 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -639,10 +639,7 @@ static int __init nbd_init(void) int err = -ENOMEM; int i; - if (sizeof(struct nbd_request) != 28) { - printk(KERN_CRIT "nbd: sizeof nbd_request needs to be 28 in order to work!\n" ); - return -EIO; - } + BUILD_BUG_ON(sizeof(struct nbd_request) != 28); if (nbds_max > MAX_NBD) { printk(KERN_CRIT "nbd: cannot allocate more than %u nbds; %u requested.\n", MAX_NBD, -- cgit v1.2.3-59-g8ed1b From c721bccece2b3abca4f7b0b95108e68b78445cec Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 25 Mar 2006 03:07:04 -0800 Subject: [PATCH] hysdn: remove custom types hysdn defines its own types: ulong, uint, uchar and word. Problem is, the module_param macros rely upon some of those identifiers having special meanings too. The net effect is that module_param() and friends cannot be used in ISDN because of this namespace clash. So remove the hysdn-private defines and open-code them all. Cc: Karsten Keil Cc: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/hysdn/boardergo.c | 31 ++++++++-------- drivers/isdn/hysdn/boardergo.h | 46 ++++++++++++------------ drivers/isdn/hysdn/hycapi.c | 2 +- drivers/isdn/hysdn/hysdn_boot.c | 28 +++++++-------- drivers/isdn/hysdn/hysdn_defs.h | 71 ++++++++++++++++++------------------- drivers/isdn/hysdn/hysdn_init.c | 4 +-- drivers/isdn/hysdn/hysdn_net.c | 6 ++-- drivers/isdn/hysdn/hysdn_pof.h | 12 +++---- drivers/isdn/hysdn/hysdn_procconf.c | 14 ++++---- drivers/isdn/hysdn/hysdn_proclog.c | 10 +++--- drivers/isdn/hysdn/hysdn_sched.c | 11 +++--- drivers/isdn/hysdn/ince1pc.h | 18 +++++----- 12 files changed, 127 insertions(+), 126 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c index e19a01a305a9..48d134be9908 100644 --- a/drivers/isdn/hysdn/boardergo.c +++ b/drivers/isdn/hysdn/boardergo.c @@ -38,8 +38,8 @@ ergo_interrupt(int intno, void *dev_id, struct pt_regs *regs) { hysdn_card *card = dev_id; /* parameter from irq */ tErgDpram *dpr; - ulong flags; - uchar volatile b; + unsigned long flags; + unsigned char volatile b; if (!card) return IRQ_NONE; /* error -> spurious interrupt */ @@ -77,7 +77,7 @@ ergo_irq_bh(hysdn_card * card) { tErgDpram *dpr; int again; - ulong flags; + unsigned long flags; if (card->state != CARD_STATE_RUN) return; /* invalid call */ @@ -131,8 +131,8 @@ ergo_irq_bh(hysdn_card * card) static void ergo_stopcard(hysdn_card * card) { - ulong flags; - uchar val; + unsigned long flags; + unsigned char val; hysdn_net_release(card); /* first release the net device if existing */ #ifdef CONFIG_HYSDN_CAPI @@ -157,7 +157,7 @@ ergo_stopcard(hysdn_card * card) static void ergo_set_errlog_state(hysdn_card * card, int on) { - ulong flags; + unsigned long flags; if (card->state != CARD_STATE_RUN) { card->err_log_state = ERRLOG_STATE_OFF; /* must be off */ @@ -217,9 +217,10 @@ ergo_testram(hysdn_card * card) /* Negative return values are interpreted as errors. */ /*****************************************************************************/ static int -ergo_writebootimg(struct HYSDN_CARD *card, uchar * buf, ulong offs) +ergo_writebootimg(struct HYSDN_CARD *card, unsigned char *buf, + unsigned long offs) { - uchar *dst; + unsigned char *dst; tErgDpram *dpram; int cnt = (BOOT_IMG_SIZE >> 2); /* number of words to move and swap (byte order!) */ @@ -264,14 +265,14 @@ ergo_writebootimg(struct HYSDN_CARD *card, uchar * buf, ulong offs) /* case of errors a negative error value is returned. */ /********************************************************************************/ static int -ergo_writebootseq(struct HYSDN_CARD *card, uchar * buf, int len) +ergo_writebootseq(struct HYSDN_CARD *card, unsigned char *buf, int len) { tDpramBootSpooler *sp = (tDpramBootSpooler *) card->dpram; - uchar *dst; - uchar buflen; + unsigned char *dst; + unsigned char buflen; int nr_write; - uchar tmp_rdptr; - uchar wr_mirror; + unsigned char tmp_rdptr; + unsigned char wr_mirror; int i; if (card->debug_flags & LOG_POF_CARD) @@ -330,7 +331,7 @@ ergo_waitpofready(struct HYSDN_CARD *card) { tErgDpram *dpr = card->dpram; /* pointer to DPRAM structure */ int timecnt = 10000 / 50; /* timeout is 10 secs max. */ - ulong flags; + unsigned long flags; int msg_size; int i; @@ -345,7 +346,7 @@ ergo_waitpofready(struct HYSDN_CARD *card) if ((dpr->ToPcChannel != CHAN_SYSTEM) || (dpr->ToPcSize < MIN_RDY_MSG_SIZE) || (dpr->ToPcSize > MAX_RDY_MSG_SIZE) || - ((*(ulong *) dpr->ToPcBuf) != RDY_MAGIC)) + ((*(unsigned long *) dpr->ToPcBuf) != RDY_MAGIC)) break; /* an error occurred */ /* Check for additional data delivered during SysReady */ diff --git a/drivers/isdn/hysdn/boardergo.h b/drivers/isdn/hysdn/boardergo.h index b56ff0889ead..c59422aa8c3f 100644 --- a/drivers/isdn/hysdn/boardergo.h +++ b/drivers/isdn/hysdn/boardergo.h @@ -23,36 +23,36 @@ /* following DPRAM layout copied from OS2-driver boarderg.h */ typedef struct ErgDpram_tag { -/*0000 */ uchar ToHyBuf[ERG_TO_HY_BUF_SIZE]; -/*0E00 */ uchar ToPcBuf[ERG_TO_PC_BUF_SIZE]; +/*0000 */ unsigned char ToHyBuf[ERG_TO_HY_BUF_SIZE]; +/*0E00 */ unsigned char ToPcBuf[ERG_TO_PC_BUF_SIZE]; - /*1C00 */ uchar bSoftUart[SIZE_RSV_SOFT_UART]; + /*1C00 */ unsigned char bSoftUart[SIZE_RSV_SOFT_UART]; /* size 0x1B0 */ - /*1DB0 *//* tErrLogEntry */ uchar volatile ErrLogMsg[64]; + /*1DB0 *//* tErrLogEntry */ unsigned char volatile ErrLogMsg[64]; /* size 64 bytes */ - /*1DB0 ulong ulErrType; */ - /*1DB4 ulong ulErrSubtype; */ - /*1DB8 ulong ucTextSize; */ - /*1DB9 ulong ucText[ERRLOG_TEXT_SIZE]; *//* ASCIIZ of len ucTextSize-1 */ + /*1DB0 unsigned long ulErrType; */ + /*1DB4 unsigned long ulErrSubtype; */ + /*1DB8 unsigned long ucTextSize; */ + /*1DB9 unsigned long ucText[ERRLOG_TEXT_SIZE]; *//* ASCIIZ of len ucTextSize-1 */ /*1DF0 */ -/*1DF0 */ word volatile ToHyChannel; -/*1DF2 */ word volatile ToHySize; - /*1DF4 */ uchar volatile ToHyFlag; +/*1DF0 */ unsigned short volatile ToHyChannel; +/*1DF2 */ unsigned short volatile ToHySize; + /*1DF4 */ unsigned char volatile ToHyFlag; /* !=0: msg for Hy waiting */ - /*1DF5 */ uchar volatile ToPcFlag; + /*1DF5 */ unsigned char volatile ToPcFlag; /* !=0: msg for PC waiting */ -/*1DF6 */ word volatile ToPcChannel; -/*1DF8 */ word volatile ToPcSize; - /*1DFA */ uchar bRes1DBA[0x1E00 - 0x1DFA]; +/*1DF6 */ unsigned short volatile ToPcChannel; +/*1DF8 */ unsigned short volatile ToPcSize; + /*1DFA */ unsigned char bRes1DBA[0x1E00 - 0x1DFA]; /* 6 bytes */ -/*1E00 */ uchar bRestOfEntryTbl[0x1F00 - 0x1E00]; -/*1F00 */ ulong TrapTable[62]; - /*1FF8 */ uchar bRes1FF8[0x1FFB - 0x1FF8]; +/*1E00 */ unsigned char bRestOfEntryTbl[0x1F00 - 0x1E00]; +/*1F00 */ unsigned long TrapTable[62]; + /*1FF8 */ unsigned char bRes1FF8[0x1FFB - 0x1FF8]; /* low part of reset vetor */ -/*1FFB */ uchar ToPcIntMetro; +/*1FFB */ unsigned char ToPcIntMetro; /* notes: * - metro has 32-bit boot ram - accessing * ToPcInt and ToHyInt would be the same; @@ -65,16 +65,16 @@ typedef struct ErgDpram_tag { * so E1 side should NOT change this byte * when writing! */ -/*1FFC */ uchar volatile ToHyNoDpramErrLog; +/*1FFC */ unsigned char volatile ToHyNoDpramErrLog; /* note: ToHyNoDpramErrLog is used to inform * boot loader, not to use DPRAM based * ErrLog; when DOS driver is rewritten * this becomes obsolete */ -/*1FFD */ uchar bRes1FFD; - /*1FFE */ uchar ToPcInt; +/*1FFD */ unsigned char bRes1FFD; + /*1FFE */ unsigned char ToPcInt; /* E1_intclear; on CHAMP2: E1_intset */ - /*1FFF */ uchar ToHyInt; + /*1FFF */ unsigned char ToHyInt; /* E1_intset; on CHAMP2: E1_intclear */ } tErgDpram; diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index acc1d3cceebb..55fbea0b6ac8 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -523,7 +523,7 @@ New nccis are created if necessary. *******************************************************************/ void -hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len) +hycapi_rx_capipkt(hysdn_card * card, unsigned char *buf, unsigned short len) { struct sk_buff *skb; hycapictrl_info *cinfo = card->hyctrlinfo; diff --git a/drivers/isdn/hysdn/hysdn_boot.c b/drivers/isdn/hysdn/hysdn_boot.c index 7bfba196f315..6d0eb0f42fca 100644 --- a/drivers/isdn/hysdn/hysdn_boot.c +++ b/drivers/isdn/hysdn/hysdn_boot.c @@ -30,17 +30,17 @@ /* needed during boot and so allocated dynamically. */ /************************************************************/ struct boot_data { - word Cryptor; /* for use with Decrypt function */ - word Nrecs; /* records remaining in file */ - uchar pof_state; /* actual state of read handler */ - uchar is_crypted; /* card data is crypted */ + unsigned short Cryptor; /* for use with Decrypt function */ + unsigned short Nrecs; /* records remaining in file */ + unsigned char pof_state;/* actual state of read handler */ + unsigned char is_crypted;/* card data is crypted */ int BufSize; /* actual number of bytes bufferd */ int last_error; /* last occurred error */ - word pof_recid; /* actual pof recid */ - ulong pof_reclen; /* total length of pof record data */ - ulong pof_recoffset; /* actual offset inside pof record */ + unsigned short pof_recid;/* actual pof recid */ + unsigned long pof_reclen;/* total length of pof record data */ + unsigned long pof_recoffset;/* actual offset inside pof record */ union { - uchar BootBuf[BOOT_BUF_SIZE]; /* buffer as byte count */ + unsigned char BootBuf[BOOT_BUF_SIZE];/* buffer as byte count */ tPofRecHdr PofRecHdr; /* header for actual record/chunk */ tPofFileHdr PofFileHdr; /* header from POF file */ tPofTimeStamp PofTime; /* time information */ @@ -69,11 +69,11 @@ StartDecryption(struct boot_data *boot) static void DecryptBuf(struct boot_data *boot, int cnt) { - uchar *bufp = boot->buf.BootBuf; + unsigned char *bufp = boot->buf.BootBuf; while (cnt--) { boot->Cryptor = (boot->Cryptor >> 1) ^ ((boot->Cryptor & 1U) ? CRYPT_FEEDTERM : 0); - *bufp++ ^= (uchar) boot->Cryptor; + *bufp++ ^= (unsigned char)boot->Cryptor; } } /* DecryptBuf */ @@ -86,7 +86,7 @@ pof_handle_data(hysdn_card * card, int datlen) { struct boot_data *boot = card->boot; /* pointer to boot specific data */ long l; - uchar *imgp; + unsigned char *imgp; int img_len; /* handle the different record types */ @@ -197,7 +197,7 @@ pof_write_buffer(hysdn_card * card, int datlen) break; } /* Setup the new state and vars */ - boot->Nrecs = (word) (boot->buf.PofFileHdr.N_PofRecs); /* limited to 65535 */ + boot->Nrecs = (unsigned short)(boot->buf.PofFileHdr.N_PofRecs); /* limited to 65535 */ boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ boot->last_error = sizeof(tPofRecHdr); /* new length */ break; @@ -268,7 +268,7 @@ pof_write_buffer(hysdn_card * card, int datlen) /* occurred. Additionally the pointer to the buffer data area is set on success */ /*******************************************************************************/ int -pof_write_open(hysdn_card * card, uchar ** bufp) +pof_write_open(hysdn_card * card, unsigned char **bufp) { struct boot_data *boot; /* pointer to boot specific data */ @@ -335,7 +335,7 @@ pof_write_close(hysdn_card * card) /* when POF has been booted. A return value of 0 is used if no error occurred. */ /*********************************************************************************/ int -EvalSysrTokData(hysdn_card * card, uchar * cp, int len) +EvalSysrTokData(hysdn_card *card, unsigned char *cp, int len) { u_char *p; u_char crc; diff --git a/drivers/isdn/hysdn/hysdn_defs.h b/drivers/isdn/hysdn/hysdn_defs.h index 432f6f99089e..3a9b29b38bc4 100644 --- a/drivers/isdn/hysdn/hysdn_defs.h +++ b/drivers/isdn/hysdn/hysdn_defs.h @@ -20,14 +20,6 @@ #include #include -/****************************/ -/* storage type definitions */ -/****************************/ -#define uchar unsigned char -#define uint unsigned int -#define ulong unsigned long -#define word unsigned short - #include "ince1pc.h" #ifdef CONFIG_HYSDN_CAPI @@ -147,18 +139,18 @@ typedef struct HYSDN_CARD { /* general variables for the cards */ int myid; /* own driver card id */ - uchar bus; /* pci bus the card is connected to */ - uchar devfn; /* slot+function bit encoded */ - word subsysid; /* PCI subsystem id */ - uchar brdtype; /* type of card */ - uint bchans; /* number of available B-channels */ - uint faxchans; /* number of available fax-channels */ - uchar mac_addr[6]; /* MAC Address read from card */ - uint irq; /* interrupt number */ - uint iobase; /* IO-port base address */ - ulong plxbase; /* PLX memory base */ - ulong membase; /* DPRAM memory base */ - ulong memend; /* DPRAM memory end */ + unsigned char bus; /* pci bus the card is connected to */ + unsigned char devfn; /* slot+function bit encoded */ + unsigned short subsysid;/* PCI subsystem id */ + unsigned char brdtype; /* type of card */ + unsigned int bchans; /* number of available B-channels */ + unsigned int faxchans; /* number of available fax-channels */ + unsigned char mac_addr[6];/* MAC Address read from card */ + unsigned int irq; /* interrupt number */ + unsigned int iobase; /* IO-port base address */ + unsigned long plxbase; /* PLX memory base */ + unsigned long membase; /* DPRAM memory base */ + unsigned long memend; /* DPRAM memory end */ void *dpram; /* mapped dpram */ int state; /* actual state of card -> CARD_STATE_** */ struct HYSDN_CARD *next; /* pointer to next card */ @@ -168,26 +160,26 @@ typedef struct HYSDN_CARD { void *procconf; /* pointer to procconf filesystem specific data */ /* debugging and logging */ - uchar err_log_state; /* actual error log state of the card */ - ulong debug_flags; /* tells what should be debugged and where */ + unsigned char err_log_state;/* actual error log state of the card */ + unsigned long debug_flags;/* tells what should be debugged and where */ void (*set_errlog_state) (struct HYSDN_CARD *, int); /* interrupt handler + interrupt synchronisation */ struct work_struct irq_queue; /* interrupt task queue */ - uchar volatile irq_enabled; /* interrupt enabled if != 0 */ - uchar volatile hw_lock; /* hardware is currently locked -> no access */ + unsigned char volatile irq_enabled;/* interrupt enabled if != 0 */ + unsigned char volatile hw_lock;/* hardware is currently locked -> no access */ /* boot process */ void *boot; /* pointer to boot private data */ - int (*writebootimg) (struct HYSDN_CARD *, uchar *, ulong); - int (*writebootseq) (struct HYSDN_CARD *, uchar *, int); + int (*writebootimg) (struct HYSDN_CARD *, unsigned char *, unsigned long); + int (*writebootseq) (struct HYSDN_CARD *, unsigned char *, int); int (*waitpofready) (struct HYSDN_CARD *); int (*testram) (struct HYSDN_CARD *); /* scheduler for data transfer (only async parts) */ - uchar async_data[256]; /* async data to be sent (normally for config) */ - word volatile async_len; /* length of data to sent */ - word volatile async_channel; /* channel number for async transfer */ + unsigned char async_data[256];/* async data to be sent (normally for config) */ + unsigned short volatile async_len;/* length of data to sent */ + unsigned short volatile async_channel;/* channel number for async transfer */ int volatile async_busy; /* flag != 0 sending in progress */ int volatile net_tx_busy; /* a network packet tx is in progress */ @@ -251,15 +243,18 @@ extern int ergo_inithardware(hysdn_card * card); /* get hardware -> module init /* hysdn_boot.c */ extern int pof_write_close(hysdn_card *); /* close proc file after writing pof */ -extern int pof_write_open(hysdn_card *, uchar **); /* open proc file for writing pof */ +extern int pof_write_open(hysdn_card *, unsigned char **); /* open proc file for writing pof */ extern int pof_write_buffer(hysdn_card *, int); /* write boot data to card */ -extern int EvalSysrTokData(hysdn_card *, uchar *, int); /* Check Sysready Token Data */ +extern int EvalSysrTokData(hysdn_card *, unsigned char *, int); /* Check Sysready Token Data */ /* hysdn_sched.c */ -extern int hysdn_sched_tx(hysdn_card *, uchar *, word volatile *, word volatile *, - word); -extern int hysdn_sched_rx(hysdn_card *, uchar *, word, word); -extern int hysdn_tx_cfgline(hysdn_card *, uchar *, word); /* send one cfg line */ +extern int hysdn_sched_tx(hysdn_card *, unsigned char *, + unsigned short volatile *, unsigned short volatile *, + unsigned short); +extern int hysdn_sched_rx(hysdn_card *, unsigned char *, unsigned short, + unsigned short); +extern int hysdn_tx_cfgline(hysdn_card *, unsigned char *, + unsigned short); /* send one cfg line */ /* hysdn_net.c */ extern unsigned int hynet_enable; @@ -269,14 +264,16 @@ extern int hysdn_net_release(hysdn_card *); /* delete the device */ extern char *hysdn_net_getname(hysdn_card *); /* get name of net interface */ extern void hysdn_tx_netack(hysdn_card *); /* acknowledge a packet tx */ extern struct sk_buff *hysdn_tx_netget(hysdn_card *); /* get next network packet */ -extern void hysdn_rx_netpkt(hysdn_card *, uchar *, word); /* rxed packet from network */ +extern void hysdn_rx_netpkt(hysdn_card *, unsigned char *, + unsigned short); /* rxed packet from network */ #ifdef CONFIG_HYSDN_CAPI extern unsigned int hycapi_enable; extern int hycapi_capi_create(hysdn_card *); /* create a new capi device */ extern int hycapi_capi_release(hysdn_card *); /* delete the device */ extern int hycapi_capi_stop(hysdn_card *card); /* suspend */ -extern void hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len); +extern void hycapi_rx_capipkt(hysdn_card * card, unsigned char * buf, + unsigned short len); extern void hycapi_tx_capiack(hysdn_card * card); extern struct sk_buff *hycapi_tx_capiget(hysdn_card *card); extern int hycapi_init(void); diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c index cb791f8e793a..b75ac5af236a 100644 --- a/drivers/isdn/hysdn/hysdn_init.c +++ b/drivers/isdn/hysdn/hysdn_init.c @@ -41,8 +41,8 @@ hysdn_card *card_root = NULL; /* pointer to first card */ /* the last entry contains all 0 */ /**********************************************/ static struct { - word subid; /* PCI sub id */ - uchar cardtyp; /* card type assigned */ + unsigned short subid; /* PCI sub id */ + unsigned char cardtyp; /* card type assigned */ } pci_subid_map[] = { { diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c index aa01628d74c6..683647b1f2bc 100644 --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -83,12 +83,12 @@ net_open(struct net_device *dev) /* Fill in the MAC-level header (if not already set) */ if (!card->mac_addr[0]) { - for (i = 0; i < ETH_ALEN - sizeof(ulong); i++) + for (i = 0; i < ETH_ALEN - sizeof(unsigned long); i++) dev->dev_addr[i] = 0xfc; if ((in_dev = dev->ip_ptr) != NULL) { struct in_ifaddr *ifa = in_dev->ifa_list; if (ifa != NULL) - memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ulong)), &ifa->ifa_local, sizeof(ulong)); + memcpy(dev->dev_addr + (ETH_ALEN - sizeof(unsigned long)), &ifa->ifa_local, sizeof(unsigned long)); } } else memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN); @@ -197,7 +197,7 @@ hysdn_tx_netack(hysdn_card * card) /* we got a packet from the network, go and queue it */ /*****************************************************/ void -hysdn_rx_netpkt(hysdn_card * card, uchar * buf, word len) +hysdn_rx_netpkt(hysdn_card * card, unsigned char *buf, unsigned short len) { struct net_local *lp = card->netif; struct sk_buff *skb; diff --git a/drivers/isdn/hysdn/hysdn_pof.h b/drivers/isdn/hysdn/hysdn_pof.h index 6cd81b9b08bc..a368d6caca0e 100644 --- a/drivers/isdn/hysdn/hysdn_pof.h +++ b/drivers/isdn/hysdn/hysdn_pof.h @@ -47,20 +47,20 @@ /*--------------------------------------POF file record structs------------*/ typedef struct PofFileHdr_tag { /* Pof file header */ -/*00 */ ulong Magic __attribute__((packed)); -/*04 */ ulong N_PofRecs __attribute__((packed)); +/*00 */ unsigned long Magic __attribute__((packed)); +/*04 */ unsigned long N_PofRecs __attribute__((packed)); /*08 */ } tPofFileHdr; typedef struct PofRecHdr_tag { /* Pof record header */ -/*00 */ word PofRecId __attribute__((packed)); -/*02 */ ulong PofRecDataLen __attribute__((packed)); +/*00 */ unsigned short PofRecId __attribute__((packed)); +/*02 */ unsigned long PofRecDataLen __attribute__((packed)); /*06 */ } tPofRecHdr; typedef struct PofTimeStamp_tag { -/*00 */ ulong UnixTime __attribute__((packed)); - /*04 */ uchar DateTimeText[0x28] __attribute__((packed)); +/*00 */ unsigned long UnixTime __attribute__((packed)); + /*04 */ unsigned char DateTimeText[0x28] __attribute__((packed)); /* =40 */ /*2C */ } tPofTimeStamp; diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c index 40e56143c768..8e2b03889f3c 100644 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -36,9 +36,9 @@ struct conf_writedata { int buf_size; /* actual number of bytes in the buffer */ int needed_size; /* needed size when reading pof */ int state; /* actual interface states from above constants */ - uchar conf_line[CONF_LINE_LEN]; /* buffered conf line */ - word channel; /* active channel number */ - uchar *pof_buffer; /* buffer when writing pof */ + unsigned char conf_line[CONF_LINE_LEN]; /* buffered conf line */ + unsigned short channel; /* active channel number */ + unsigned char *pof_buffer; /* buffer when writing pof */ }; /***********************************************************************/ @@ -49,7 +49,7 @@ struct conf_writedata { static int process_line(struct conf_writedata *cnf) { - uchar *cp = cnf->conf_line; + unsigned char *cp = cnf->conf_line; int i; if (cnf->card->debug_flags & LOG_CNF_LINE) @@ -92,7 +92,7 @@ hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t { struct conf_writedata *cnf; int i; - uchar ch, *cp; + unsigned char ch, *cp; if (!count) return (0); /* nothing to handle */ @@ -390,7 +390,7 @@ int hysdn_procconf_init(void) { hysdn_card *card; - uchar conf_name[20]; + unsigned char conf_name[20]; hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, proc_net); if (!hysdn_proc_entry) { @@ -423,7 +423,7 @@ void hysdn_procconf_release(void) { hysdn_card *card; - uchar conf_name[20]; + unsigned char conf_name[20]; card = card_root; /* start with first card */ while (card) { diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index 6c26f1efabd5..c4301e8338ef 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -28,7 +28,7 @@ static void put_log_buffer(hysdn_card * card, char *cp); /*************************************************/ struct log_data { struct log_data *next; - ulong usage_cnt; /* number of files still to work */ + unsigned long usage_cnt;/* number of files still to work */ void *proc_ctrl; /* pointer to own control procdata structure */ char log_start[2]; /* log string start (final len aligned by size) */ }; @@ -42,7 +42,7 @@ struct procdata { struct log_data *log_head, *log_tail; /* head and tail for queue */ int if_used; /* open count for interface */ int volatile del_lock; /* lock for delete operations */ - uchar logtmp[LOG_MAX_LINELEN]; + unsigned char logtmp[LOG_MAX_LINELEN]; wait_queue_head_t rd_queue; }; @@ -153,9 +153,9 @@ put_log_buffer(hysdn_card * card, char *cp) static ssize_t hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t * off) { - ulong u = 0; + unsigned long u = 0; int found = 0; - uchar *cp, valbuf[128]; + unsigned char *cp, valbuf[128]; long base = 10; hysdn_card *card = (hysdn_card *) file->private_data; @@ -249,7 +249,7 @@ hysdn_log_open(struct inode *ino, struct file *filep) { hysdn_card *card; struct procdata *pd = NULL; - ulong flags; + unsigned long flags; lock_kernel(); card = card_root; diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c index 4fa3b01707cd..133032920ff8 100644 --- a/drivers/isdn/hysdn/hysdn_sched.c +++ b/drivers/isdn/hysdn/hysdn_sched.c @@ -30,7 +30,8 @@ /* to keep the data until later. */ /*****************************************************************************/ int -hysdn_sched_rx(hysdn_card * card, uchar * buf, word len, word chan) +hysdn_sched_rx(hysdn_card *card, unsigned char *buf, unsigned short len, + unsigned short chan) { switch (chan) { @@ -72,7 +73,9 @@ hysdn_sched_rx(hysdn_card * card, uchar * buf, word len, word chan) /* sending. */ /*****************************************************************************/ int -hysdn_sched_tx(hysdn_card * card, uchar * buf, word volatile *len, word volatile *chan, word maxlen) +hysdn_sched_tx(hysdn_card *card, unsigned char *buf, + unsigned short volatile *len, unsigned short volatile *chan, + unsigned short maxlen) { struct sk_buff *skb; @@ -145,10 +148,10 @@ hysdn_sched_tx(hysdn_card * card, uchar * buf, word volatile *len, word volatile /* are to be sent and this happens very seldom. */ /*****************************************************************************/ int -hysdn_tx_cfgline(hysdn_card * card, uchar * line, word chan) +hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan) { int cnt = 50; /* timeout intervalls */ - ulong flags; + unsigned long flags; if (card->debug_flags & LOG_SCHED_ASYN) hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1); diff --git a/drivers/isdn/hysdn/ince1pc.h b/drivers/isdn/hysdn/ince1pc.h index 4a115a87c782..7a36694df6d7 100644 --- a/drivers/isdn/hysdn/ince1pc.h +++ b/drivers/isdn/hysdn/ince1pc.h @@ -62,7 +62,7 @@ * s. RotlCRC algorithm * * RotlCRC algorithm: - * ucSum= 0 1 uchar + * ucSum= 0 1 unsigned char * for all NonEndTokenChunk bytes: * ROTL(ucSum,1) rotate left by 1 * ucSum += Char; add current byte with swap around @@ -85,13 +85,13 @@ typedef struct ErrLogEntry_tag { -/*00 */ ulong ulErrType; +/*00 */ unsigned long ulErrType; -/*04 */ ulong ulErrSubtype; +/*04 */ unsigned long ulErrSubtype; -/*08 */ uchar ucTextSize; +/*08 */ unsigned char ucTextSize; - /*09 */ uchar ucText[ERRLOG_TEXT_SIZE]; + /*09 */ unsigned char ucText[ERRLOG_TEXT_SIZE]; /* ASCIIZ of len ucTextSize-1 */ /*40 */ @@ -111,13 +111,13 @@ typedef struct ErrLogEntry_tag { #define DPRAM_SPOOLER_DATA_SIZE 0x20 typedef struct DpramBootSpooler_tag { -/*00 */ uchar Len; +/*00 */ unsigned char Len; -/*01 */ volatile uchar RdPtr; +/*01 */ volatile unsigned char RdPtr; -/*02 */ uchar WrPtr; +/*02 */ unsigned char WrPtr; -/*03 */ uchar Data[DPRAM_SPOOLER_DATA_SIZE]; +/*03 */ unsigned char Data[DPRAM_SPOOLER_DATA_SIZE]; /*23 */ } tDpramBootSpooler; -- cgit v1.2.3-59-g8ed1b From 8d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 25 Mar 2006 03:07:05 -0800 Subject: [PATCH] Remove MODULE_PARM MODULE_PARM was actually breaking: recent gcc version optimize them out as unused. It's time to replace the last users, which are generally in the most unloved drivers anyway. Signed-off-by: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/networking/ray_cs.txt | 2 +- Documentation/sound/oss/Introduction | 2 +- Documentation/sound/oss/cs46xx | 16 +-- arch/ppc/8xx_io/cs4218_tdm.c | 10 +- drivers/block/ataflop.c | 4 +- drivers/cdrom/cm206.c | 8 +- drivers/cdrom/sbpcd.c | 10 +- drivers/char/istallion.c | 8 +- drivers/char/mxser.c | 8 +- drivers/char/riscom8.c | 8 +- drivers/isdn/hardware/avm/b1dma.c | 2 +- drivers/isdn/hardware/avm/b1isa.c | 4 +- drivers/isdn/hardware/avm/c4.c | 2 +- drivers/isdn/hardware/avm/t1isa.c | 6 +- drivers/isdn/hysdn/hycapi.c | 2 +- drivers/isdn/hysdn/hysdn_net.c | 2 +- drivers/isdn/isdnloop/isdnloop.c | 2 +- drivers/media/video/zr36120.c | 8 +- drivers/mmc/au1xmmc.c | 2 +- drivers/mtd/maps/pcmciamtd.c | 14 +-- drivers/net/atari_bionet.c | 2 +- drivers/net/atari_pamsnet.c | 2 +- drivers/net/atarilance.c | 2 +- drivers/net/cassini.c | 11 ++- drivers/net/chelsio/cxgb2.c | 2 +- drivers/net/fec_8xx/fec_main.c | 4 +- drivers/net/fs_enet/fs_enet-main.c | 4 +- drivers/net/gt96100eth.c | 4 +- drivers/net/hamradio/dmascc.c | 2 +- drivers/net/hamradio/mkiss.c | 2 +- drivers/net/irda/irport.c | 4 +- drivers/net/lasi_82596.c | 6 +- drivers/net/mac89x0.c | 2 +- drivers/net/mace.c | 2 +- drivers/net/meth.c | 2 +- drivers/net/ne-h8300.c | 6 +- drivers/net/ni5010.c | 4 +- drivers/net/sun3lance.c | 2 +- drivers/s390/block/dasd.c | 1 - drivers/s390/block/dasd_devmap.c | 3 + drivers/scsi/arm/cumana_2.c | 2 +- drivers/scsi/arm/eesox.c | 2 +- drivers/scsi/arm/powertec.c | 2 +- drivers/scsi/atari_scsi.c | 10 +- drivers/video/pm3fb.c | 18 ++-- include/linux/module.h | 19 ---- include/video/pm3fb.h | 3 - init/Kconfig | 9 -- kernel/module.c | 183 +++-------------------------------- kernel/rcutorture.c | 10 +- sound/oss/au1000.c | 2 +- sound/oss/au1550_ac97.c | 2 +- sound/oss/dmasound/dmasound_core.c | 10 +- sound/oss/ite8172.c | 4 +- sound/oss/swarm_cs4297a.c | 4 +- sound/oss/waveartist.c | 8 +- 56 files changed, 146 insertions(+), 329 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/ray_cs.txt b/Documentation/networking/ray_cs.txt index 5427f8c7df95..145d27a52395 100644 --- a/Documentation/networking/ray_cs.txt +++ b/Documentation/networking/ray_cs.txt @@ -25,7 +25,7 @@ the essid= string parameter is available via the kernel command line. This will change after the method of sorting out parameters for all the PCMCIA drivers is agreed upon. If you must have a built in driver with nondefault parameters, they can be edited in -/usr/src/linux/drivers/net/pcmcia/ray_cs.c. Searching for MODULE_PARM +/usr/src/linux/drivers/net/pcmcia/ray_cs.c. Searching for module_param will find them all. Information on card services is available at: diff --git a/Documentation/sound/oss/Introduction b/Documentation/sound/oss/Introduction index 15d4fb975ac0..f04ba6bb7395 100644 --- a/Documentation/sound/oss/Introduction +++ b/Documentation/sound/oss/Introduction @@ -69,7 +69,7 @@ are available, for example IRQ, address, DMA. Warning, the options for different cards sometime use different names for the same or a similar feature (dma1= versus dma16=). As a last -resort, inspect the code (search for MODULE_PARM). +resort, inspect the code (search for module_param). Notes: diff --git a/Documentation/sound/oss/cs46xx b/Documentation/sound/oss/cs46xx index 88d6cf8b39f3..b54432709863 100644 --- a/Documentation/sound/oss/cs46xx +++ b/Documentation/sound/oss/cs46xx @@ -88,7 +88,7 @@ parameters. for a copy email: twoller@crystal.cirrus.com MODULE_PARMS definitions ------------------------ -MODULE_PARM(defaultorder, "i"); +module_param(defaultorder, ulong, 0); defaultorder=N where N is a value from 1 to 12 The buffer order determines the size of the dma buffer for the driver. @@ -98,18 +98,18 @@ to not underrun the dma buffer as easily. As default, use 32k (order=3) rather than 64k as some of the games work more responsively. (2^N) * PAGE_SIZE = allocated buffer size -MODULE_PARM(cs_debuglevel, "i"); -MODULE_PARM(cs_debugmask, "i"); +module_param(cs_debuglevel, ulong, 0644); +module_param(cs_debugmask, ulong, 0644); cs_debuglevel=N cs_debugmask=0xMMMMMMMM where N is a value from 0 (no debug printfs), to 9 (maximum) 0xMMMMMMMM is a debug mask corresponding to the CS_xxx bits (see driver source). -MODULE_PARM(hercules_egpio_disable, "i"); +module_param(hercules_egpio_disable, ulong, 0); hercules_egpio_disable=N where N is a 0 (enable egpio), or a 1 (disable egpio support) -MODULE_PARM(initdelay, "i"); +module_param(initdelay, ulong, 0); initdelay=N This value is used to determine the millescond delay during the initialization code prior to powering up the PLL. On laptops this value can be used to @@ -118,19 +118,19 @@ system is booted under battery power then the mdelay()/udelay() functions fail t properly delay the required time. Also, if the system is booted under AC power and then the power removed, the mdelay()/udelay() functions will not delay properly. -MODULE_PARM(powerdown, "i"); +module_param(powerdown, ulong, 0); powerdown=N where N is 0 (disable any powerdown of the internal blocks) or 1 (enable powerdown) -MODULE_PARM(external_amp, "i"); +module_param(external_amp, bool, 0); external_amp=1 if N is set to 1, then force enabling the EAPD support in the primary AC97 codec. override the detection logic and force the external amp bit in the AC97 0x26 register to be reset (0). EAPD should be 0 for powerup, and 1 for powerdown. The VTB Santa Cruz card has inverted logic, so there is a special function for these cards. -MODULE_PARM(thinkpad, "i"); +module_param(thinkpad, bool, 0); thinkpad=1 if N is set to 1, then force enabling the clkrun functionality. Currently, when the part is being used, then clkrun is disabled for the entire system, diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c index 49eb2a7e65c0..a892356d5c3b 100644 --- a/arch/ppc/8xx_io/cs4218_tdm.c +++ b/arch/ppc/8xx_io/cs4218_tdm.c @@ -126,11 +126,11 @@ static int numReadBufs = 4, readbufSize = 32; */ static volatile cbd_t *rx_base, *rx_cur, *tx_base, *tx_cur; -MODULE_PARM(catchRadius, "i"); -MODULE_PARM(numBufs, "i"); -MODULE_PARM(bufSize, "i"); -MODULE_PARM(numreadBufs, "i"); -MODULE_PARM(readbufSize, "i"); +module_param(catchRadius, int, 0); +module_param(numBufs, int, 0); +module_param(bufSize, int, 0); +module_param(numreadBufs, int, 0); +module_param(readbufSize, int, 0); #define arraysize(x) (sizeof(x)/sizeof(*(x))) #define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff)) diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index f8ce235ccfc3..c39650920bdf 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -271,7 +271,7 @@ unsigned char *DMABuffer; /* buffer for writes */ static unsigned long PhysDMABuffer; /* physical address */ static int UseTrackbuffer = -1; /* Do track buffering? */ -MODULE_PARM(UseTrackbuffer, "i"); +module_param(UseTrackbuffer, int, 0); unsigned char *TrackBuffer; /* buffer for reads */ static unsigned long PhysTrackBuffer; /* physical address */ @@ -296,7 +296,7 @@ static int MotorOn = 0, MotorOffTrys; static int IsFormatting = 0, FormatError; static int UserSteprate[FD_MAX_UNITS] = { -1, -1 }; -MODULE_PARM(UserSteprate, "1-" __MODULE_STRING(FD_MAX_UNITS) "i"); +module_param_array(UserSteprate, int, NULL, 0); /* Synchronization of FDC access. */ static volatile int fdc_busy = 0; diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c index fad27a87ce35..f43a988dd413 100644 --- a/drivers/cdrom/cm206.c +++ b/drivers/cdrom/cm206.c @@ -218,12 +218,12 @@ static int cm206_base = CM206_BASE; static int cm206_irq = CM206_IRQ; #ifdef MODULE static int cm206[2] = { 0, 0 }; /* for compatible `insmod' parameter passing */ +module_param_array(cm206, int, NULL, 0); /* base,irq or irq,base */ #endif -MODULE_PARM(cm206_base, "i"); /* base */ -MODULE_PARM(cm206_irq, "i"); /* irq */ -MODULE_PARM(cm206, "1-2i"); /* base,irq or irq,base */ -MODULE_PARM(auto_probe, "i"); /* auto probe base and irq */ +module_param(cm206_base, int, 0); /* base */ +module_param(cm206_irq, int, 0); /* irq */ +module_param(auto_probe, bool, 0); /* auto probe base and irq */ MODULE_LICENSE("GPL"); #define POLLOOP 100 /* milliseconds */ diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 4760f515f591..05c9e865ecaf 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -464,8 +464,13 @@ static int sbpcd[] = static __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock); static struct request_queue *sbpcd_queue; -MODULE_PARM(sbpcd, "2i"); -MODULE_PARM(max_drives, "i"); +/* You can only set the first pair, from old MODULE_PARM code. */ +static int sbpcd_set(const char *val, struct kernel_param *kp) +{ + get_options((char *)val, 2, (int *)sbpcd); + return 0; +} +module_param_call(sbpcd, sbpcd_set, NULL, NULL, 0); #define NUM_PROBE (sizeof(sbpcd) / sizeof(int)) @@ -553,6 +558,7 @@ static unsigned char msgnum; static char msgbuf[80]; static int max_drives = MAX_DRIVES; +module_param(max_drives, int, 0); #ifndef MODULE static unsigned char setup_done; static const char *str_sb_l = "soundblaster"; diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index ede128356af2..e5247f85a446 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -378,13 +378,13 @@ MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(board0, "1-3s"); +module_param_array(board0, charp, NULL, 0); MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]"); -MODULE_PARM(board1, "1-3s"); +module_param_array(board1, charp, NULL, 0); MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]"); -MODULE_PARM(board2, "1-3s"); +module_param_array(board2, charp, NULL, 0); MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]"); -MODULE_PARM(board3, "1-3s"); +module_param_array(board3, charp, NULL, 0); MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]"); #endif diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index ea725a9964e2..0fb2fb9fb024 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -243,10 +243,10 @@ static int verbose = 0; MODULE_AUTHOR("Casper Yang"); MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); -MODULE_PARM(ioaddr, "1-4i"); -MODULE_PARM(ttymajor, "i"); -MODULE_PARM(calloutmajor, "i"); -MODULE_PARM(verbose, "i"); +module_param_array(ioaddr, int, NULL, 0); +module_param(ttymajor, int, 0); +module_param(calloutmajor, int, 0); +module_param(verbose, bool, 0); MODULE_LICENSE("GPL"); struct mxser_log { diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 119e629656b7..657c0d88f48c 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1743,10 +1743,10 @@ static int iobase; static int iobase1; static int iobase2; static int iobase3; -MODULE_PARM(iobase, "i"); -MODULE_PARM(iobase1, "i"); -MODULE_PARM(iobase2, "i"); -MODULE_PARM(iobase3, "i"); +module_param(iobase, int, 0); +module_param(iobase1, int, 0); +module_param(iobase2, int, 0); +module_param(iobase3, int, 0); MODULE_LICENSE("GPL"); #endif /* MODULE */ diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c index 91dd0551fc7c..4d64e5cbcdbf 100644 --- a/drivers/isdn/hardware/avm/b1dma.c +++ b/drivers/isdn/hardware/avm/b1dma.c @@ -39,7 +39,7 @@ MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); static int suppress_pollack = 0; -MODULE_PARM(suppress_pollack, "0-1i"); +module_param(suppress_pollack, bool, 0); /* ------------------------------------------------------------- */ diff --git a/drivers/isdn/hardware/avm/b1isa.c b/drivers/isdn/hardware/avm/b1isa.c index 38bd4dfecbd1..80fb488848b8 100644 --- a/drivers/isdn/hardware/avm/b1isa.c +++ b/drivers/isdn/hardware/avm/b1isa.c @@ -169,8 +169,8 @@ static struct pci_dev isa_dev[MAX_CARDS]; static int io[MAX_CARDS]; static int irq[MAX_CARDS]; -MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i"); -MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i"); +module_param_array(io, int, NULL, 0); +module_param_array(irq, int, NULL, 0); MODULE_PARM_DESC(io, "I/O base address(es)"); MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c index 724aac2c1cca..f7253b2136ea 100644 --- a/drivers/isdn/hardware/avm/c4.c +++ b/drivers/isdn/hardware/avm/c4.c @@ -50,7 +50,7 @@ MODULE_DEVICE_TABLE(pci, c4_pci_tbl); MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -MODULE_PARM(suppress_pollack, "0-1i"); +module_param(suppress_pollack, bool, 0); /* ------------------------------------------------------------- */ diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c index 3b701d97bdf1..5a2f854d55b5 100644 --- a/drivers/isdn/hardware/avm/t1isa.c +++ b/drivers/isdn/hardware/avm/t1isa.c @@ -519,9 +519,9 @@ static int io[MAX_CARDS]; static int irq[MAX_CARDS]; static int cardnr[MAX_CARDS]; -MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i"); -MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i"); -MODULE_PARM(cardnr, "1-" __MODULE_STRING(MAX_CARDS) "i"); +module_param_array(io, int, NULL, 0); +module_param_array(irq, int, NULL, 0); +module_param_array(cardnr, int, NULL, 0); MODULE_PARM_DESC(io, "I/O base address(es)"); MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); MODULE_PARM_DESC(cardnr, "Card number(s) (as jumpered)"); diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index 55fbea0b6ac8..6bac43cc91bd 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -31,7 +31,7 @@ static char hycapi_revision[]="$Revision: 1.8.6.4 $"; unsigned int hycapi_enable = 0xffffffff; -MODULE_PARM(hycapi_enable, "i"); +module_param(hycapi_enable, uint, 0); typedef struct _hycapi_appl { unsigned int ctrl_mask; diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c index 683647b1f2bc..d205249a1242 100644 --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -24,7 +24,7 @@ #include "hysdn_defs.h" unsigned int hynet_enable = 0xffffffff; -MODULE_PARM(hynet_enable, "i"); +module_param(hynet_enable, uint, 0); /* store the actual version for log reporting */ char *hysdn_net_revision = "$Revision: 1.8.6.4 $"; diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index 33d339700411..a67d31af797a 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -22,7 +22,7 @@ static char *isdnloop_id = "loop0"; MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card"); MODULE_AUTHOR("Fritz Elfert"); MODULE_LICENSE("GPL"); -MODULE_PARM(isdnloop_id, "s"); +module_param(isdnloop_id, charp, 0); MODULE_PARM_DESC(isdnloop_id, "ID-String of first card"); static int isdnloop_addcard(char *); diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c index d4c633b8a7f5..417a999afee3 100644 --- a/drivers/media/video/zr36120.c +++ b/drivers/media/video/zr36120.c @@ -70,10 +70,10 @@ MODULE_AUTHOR("Pauline Middelink "); MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber"); MODULE_LICENSE("GPL"); -MODULE_PARM(triton1,"i"); -MODULE_PARM(cardtype,"1-" __MODULE_STRING(ZORAN_MAX) "i"); -MODULE_PARM(video_nr,"i"); -MODULE_PARM(vbi_nr,"i"); +module_param(triton1, uint, 0); +module_param_array(cardtype, uint, NULL, 0); +module_param(video_nr, int, 0); +module_param(vbi_nr, int, 0); static int zoran_cards; static struct zoran zorans[ZORAN_MAX]; diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c index 8d84b045bc83..85e89c77bdea 100644 --- a/drivers/mmc/au1xmmc.c +++ b/drivers/mmc/au1xmmc.c @@ -87,7 +87,7 @@ struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT]; static int dma = 1; #ifdef MODULE -MODULE_PARM(dma, "i"); +module_param(dma, bool, 0); MODULE_PARM_DESC(dma, "Use DMA engine for data transfers (0 = disabled)"); #endif diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index f0f8916da7ad..f988c817e196 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -28,7 +28,7 @@ #ifdef CONFIG_MTD_DEBUG static int debug = CONFIG_MTD_DEBUG_VERBOSE; -MODULE_PARM(debug, "i"); +module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy"); #undef DEBUG #define DEBUG(n, format, arg...) \ @@ -89,17 +89,17 @@ static int mem_type; MODULE_LICENSE("GPL"); MODULE_AUTHOR("Simon Evans "); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_PARM(bankwidth, "i"); +module_param(bankwidth, int, 0); MODULE_PARM_DESC(bankwidth, "Set bankwidth (1=8 bit, 2=16 bit, default=2)"); -MODULE_PARM(mem_speed, "i"); +module_param(mem_speed, int, 0); MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns"); -MODULE_PARM(force_size, "i"); +module_param(force_size, int, 0); MODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)"); -MODULE_PARM(setvpp, "i"); +module_param(setvpp, int, 0); MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)"); -MODULE_PARM(vpp, "i"); +module_param(vpp, int, 0); MODULE_PARM_DESC(vpp, "Vpp value in 1/10ths eg 33=3.3V 120=12V (Dangerous)"); -MODULE_PARM(mem_type, "i"); +module_param(mem_type, int, 0); MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)"); diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c index 0095384ff454..5e5f80b99b9e 100644 --- a/drivers/net/atari_bionet.c +++ b/drivers/net/atari_bionet.c @@ -123,7 +123,7 @@ static char version[] = * Global variable 'bionet_debug'. Can be set at load time by 'insmod' */ unsigned int bionet_debug = NET_DEBUG; -MODULE_PARM(bionet_debug, "i"); +module_param(bionet_debug, int, 0); MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c index 8b997809f9de..d6039e62d832 100644 --- a/drivers/net/atari_pamsnet.c +++ b/drivers/net/atari_pamsnet.c @@ -119,7 +119,7 @@ static char *version = * Global variable 'pamsnet_debug'. Can be set at load time by 'insmod' */ unsigned int pamsnet_debug = NET_DEBUG; -MODULE_PARM(pamsnet_debug, "i"); +module_param(pamsnet_debug, int, 0); MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c index e01b6a78ec63..442b2cbeb58a 100644 --- a/drivers/net/atarilance.c +++ b/drivers/net/atarilance.c @@ -78,7 +78,7 @@ static int lance_debug = LANCE_DEBUG; #else static int lance_debug = 1; #endif -MODULE_PARM(lance_debug, "i"); +module_param(lance_debug, int, 0); MODULE_PARM_DESC(lance_debug, "atarilance debug level (0-3)"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 8f1573e658a5..ac48f7543500 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -192,12 +192,15 @@ static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; +static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */ +static int link_mode; + MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)"); MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(cassini_debug, "i"); +module_param(cassini_debug, int, 0); MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value"); -MODULE_PARM(link_mode, "i"); +module_param(link_mode, int, 0); MODULE_PARM_DESC(link_mode, "default link mode"); /* @@ -209,7 +212,7 @@ MODULE_PARM_DESC(link_mode, "default link mode"); * Value in seconds, for user input. */ static int linkdown_timeout = DEFAULT_LINKDOWN_TIMEOUT; -MODULE_PARM(linkdown_timeout, "i"); +module_param(linkdown_timeout, int, 0); MODULE_PARM_DESC(linkdown_timeout, "min reset interval in sec. for PCS linkdown issue; disabled if not positive"); @@ -221,8 +224,6 @@ MODULE_PARM_DESC(linkdown_timeout, static int link_transition_timeout; -static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */ -static int link_mode; static u16 link_modes[] __devinitdata = { BMCR_ANENABLE, /* 0 : autoneg */ diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 349ebe783ed6..7fe2638ae06d 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -124,7 +124,7 @@ MODULE_LICENSE("GPL"); static int dflt_msg_enable = DFLT_MSG_ENABLE; -MODULE_PARM(dflt_msg_enable, "i"); +module_param(dflt_msg_enable, int, 0); MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 message enable bitmap"); diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c index b4f3a9f8a535..7e4338097139 100644 --- a/drivers/net/fec_8xx/fec_main.c +++ b/drivers/net/fec_8xx/fec_main.c @@ -55,11 +55,11 @@ MODULE_AUTHOR("Pantelis Antoniou "); MODULE_DESCRIPTION("Motorola 8xx FEC ethernet driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(fec_8xx_debug, "i"); +int fec_8xx_debug = -1; /* -1 == use FEC_8XX_DEF_MSG_ENABLE as value */ +module_param(fec_8xx_debug, int, 0); MODULE_PARM_DESC(fec_8xx_debug, "FEC 8xx bitmapped debugging message enable value"); -int fec_8xx_debug = -1; /* -1 == use FEC_8XX_DEF_MSG_ENABLE as value */ /*************************************************/ diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index f5d49a110654..196298f33db8 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -58,11 +58,11 @@ MODULE_DESCRIPTION("Freescale Ethernet Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); -MODULE_PARM(fs_enet_debug, "i"); +int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */ +module_param(fs_enet_debug, int, 0); MODULE_PARM_DESC(fs_enet_debug, "Freescale bitmapped debugging message enable value"); -int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */ static void fs_set_multicast_list(struct net_device *dev) { diff --git a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c index 5958a6314723..2d2435404614 100644 --- a/drivers/net/gt96100eth.c +++ b/drivers/net/gt96100eth.c @@ -114,8 +114,8 @@ static int max_interrupt_work = 32; static char mac0[18] = "00.02.03.04.05.06"; static char mac1[18] = "00.01.02.03.04.05"; -MODULE_PARM(mac0, "c18"); -MODULE_PARM(mac1, "c18"); +module_param_string(mac0, mac0, 18, 0); +module_param_string(mac1, mac0, 18, 0); MODULE_PARM_DESC(mac0, "MAC address for GT96100 ethernet port 0"); MODULE_PARM_DESC(mac1, "MAC address for GT96100 ethernet port 1"); diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index c8dc40214a08..79a8fbcf5f93 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -280,7 +280,7 @@ static unsigned long rand; MODULE_AUTHOR("Klaus Kudielka"); MODULE_DESCRIPTION("Driver for high-speed SCC boards"); -MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i"); +module_param_array(io, int, NULL, 0); MODULE_LICENSE("GPL"); static void __exit dmascc_exit(void) diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index dc5e9d59deed..d81a8e1eeb8d 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -1012,7 +1012,7 @@ static void __exit mkiss_exit_driver(void) MODULE_AUTHOR("Ralf Baechle DL5RB "); MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs"); -MODULE_PARM(crc_force, "i"); +module_param(crc_force, int, 0); MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]"); MODULE_LICENSE("GPL"); MODULE_ALIAS_LDISC(N_AX25); diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index 6070195b87bd..98fa5319e5cc 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -1118,9 +1118,9 @@ static void __exit irport_cleanup(void) } } -MODULE_PARM(io, "1-4i"); +module_param_array(io, int, NULL, 0); MODULE_PARM_DESC(io, "Base I/O addresses"); -MODULE_PARM(irq, "1-4i"); +module_param_array(irq, int, NULL, 0); MODULE_PARM_DESC(irq, "IRQ lines"); MODULE_AUTHOR("Dag Brattli "); diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index f7b7238d8352..957888de3d7e 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -177,7 +177,7 @@ static int i596_debug = (DEB_SERIOUS|DEB_PROBE); MODULE_AUTHOR("Richard Hirst"); MODULE_DESCRIPTION("i82596 driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(i596_debug, "i"); +module_param(i596_debug, int, 0); MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask"); /* Copy frames shorter than rx_copybreak, otherwise pass on up in @@ -1520,9 +1520,9 @@ static void set_multicast_list(struct net_device *dev) } } -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "lasi_82596 debug mask"); static int debug = -1; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "lasi_82596 debug mask"); static int num_drivers; static struct net_device *netdevs[MAX_DRIVERS]; diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c index f65b0db111b8..cd3c9a5a98b2 100644 --- a/drivers/net/mac89x0.c +++ b/drivers/net/mac89x0.c @@ -629,7 +629,7 @@ static int set_mac_address(struct net_device *dev, void *addr) static struct net_device *dev_cs89x0; static int debug; -MODULE_PARM(debug, "i"); +module_param(debug, int, 0); MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/mace.c b/drivers/net/mace.c index 2a5add257b8f..77792b286027 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -1042,7 +1042,7 @@ static void __exit mace_cleanup(void) MODULE_AUTHOR("Paul Mackerras"); MODULE_DESCRIPTION("PowerMac MACE driver."); -MODULE_PARM(port_aaui, "i"); +module_param(port_aaui, int, 0); MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/meth.c b/drivers/net/meth.c index e23655f5049f..d644bf3a933c 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -62,7 +62,7 @@ MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver"); #ifdef HAVE_TX_TIMEOUT static int timeout = TX_TIMEOUT; -MODULE_PARM(timeout, "i"); +module_param(timeout, int, 0); #endif /* diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c index aaebd28a1920..7ea3d596ac3b 100644 --- a/drivers/net/ne-h8300.c +++ b/drivers/net/ne-h8300.c @@ -601,9 +601,9 @@ static int io[MAX_NE_CARDS]; static int irq[MAX_NE_CARDS]; static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */ -MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); +module_param_array(io, int, NULL, 0); +module_param_array(irq, int, NULL, 0); +module_param_array(bad, int, NULL, 0); MODULE_PARM_DESC(io, "I/O base address(es)"); MODULE_PARM_DESC(irq, "IRQ number(s)"); MODULE_DESCRIPTION("H8/300 NE2000 Ethernet driver"); diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c index 2ab01a5d1d22..a68bf474f6ed 100644 --- a/drivers/net/ni5010.c +++ b/drivers/net/ni5010.c @@ -766,8 +766,8 @@ static void ni5010_show_registers(struct net_device *dev) #ifdef MODULE static struct net_device *dev_ni5010; -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); +module_param(io, int, 0); +module_param(irq, int, 0); MODULE_PARM_DESC(io, "ni5010 I/O base address"); MODULE_PARM_DESC(irq, "ni5010 IRQ number"); diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index 01bdb2334058..d4c0002b43db 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -71,7 +71,7 @@ static int lance_debug = LANCE_DEBUG; #else static int lance_debug = 1; #endif -MODULE_PARM(lance_debug, "i"); +module_param(lance_debug, int, 0); MODULE_PARM_DESC(lance_debug, "SUN3 Lance debug level (0-3)"); MODULE_LICENSE("GPL"); diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index dfe542b206cc..7967916bda18 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -43,7 +43,6 @@ MODULE_AUTHOR("Holger Smolinski "); MODULE_DESCRIPTION("Linux on S/390 DASD device driver," " Copyright 2000 IBM Corporation"); MODULE_SUPPORTED_DEVICE("dasd"); -MODULE_PARM(dasd, "1-" __MODULE_STRING(256) "s"); MODULE_LICENSE("GPL"); /* diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index f576f243cd93..2f720108a7e0 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,8 @@ int dasd_autodetect = 0; /* is true, when autodetection is active */ * strings when running as a module. */ static char *dasd[256]; +module_param_array(dasd, charp, NULL, 0); + /* * Single spinlock to protect devmap structures and lists. */ diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index 583d2d8c8335..fad2109268bb 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -550,6 +550,6 @@ module_exit(cumanascsi2_exit); MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("Cumana SCSI-2 driver for Acorn machines"); -MODULE_PARM(term, "1-8i"); +module_param_array(term, int, NULL, 0); MODULE_PARM_DESC(term, "SCSI bus termination"); MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index 3ffec7efc9d5..dcbb4b2b3fe0 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -674,6 +674,6 @@ module_exit(eesox_exit); MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("EESOX 'Fast' SCSI driver for Acorn machines"); -MODULE_PARM(term, "1-8i"); +module_param_array(term, int, NULL, 0); MODULE_PARM_DESC(term, "SCSI bus termination"); MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index 3113bdcedb13..3d69f6c45a6b 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -466,6 +466,6 @@ module_exit(powertecscsi_exit); MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("Powertec SCSI driver"); -MODULE_PARM(term, "1-8i"); +module_param_array(term, int, NULL, 0); MODULE_PARM_DESC(term, "SCSI bus termination"); MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index f4c1ca7c1572..f677c5a32a68 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -239,17 +239,17 @@ static int atari_read_overruns = 0; #endif static int setup_can_queue = -1; -MODULE_PARM(setup_can_queue, "i"); +module_param(setup_can_queue, int, 0); static int setup_cmd_per_lun = -1; -MODULE_PARM(setup_cmd_per_lun, "i"); +module_param(setup_cmd_per_lun, int, 0); static int setup_sg_tablesize = -1; -MODULE_PARM(setup_sg_tablesize, "i"); +module_param(setup_sg_tablesize, int, 0); #ifdef SUPPORT_TAGS static int setup_use_tagged_queuing = -1; -MODULE_PARM(setup_use_tagged_queuing, "i"); +module_param(setup_use_tagged_queuing, int, 0); #endif static int setup_hostid = -1; -MODULE_PARM(setup_hostid, "i"); +module_param(setup_hostid, int, 0); #if defined(CONFIG_TT_DMA_EMUL) diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 0e78ddc81583..52c18a35fb41 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c @@ -3532,26 +3532,26 @@ int __init pm3fb_init(void) MODULE_AUTHOR("Romain Dolbeau"); MODULE_DESCRIPTION("Permedia3 framebuffer device driver"); static char *mode[PM3_MAX_BOARD]; -MODULE_PARM(mode,PM3_MAX_BOARD_MODULE_ARRAY_STRING); +module_param_array(mode, charp, NULL, 0); MODULE_PARM_DESC(mode,"video mode"); -MODULE_PARM(disable,PM3_MAX_BOARD_MODULE_ARRAY_SHORT); +module_param_array(disable, short, NULL, 0); MODULE_PARM_DESC(disable,"disable board"); static short off[PM3_MAX_BOARD]; -MODULE_PARM(off,PM3_MAX_BOARD_MODULE_ARRAY_SHORT); +module_param_array(off, short, NULL, 0); MODULE_PARM_DESC(off,"disable board"); static char *pciid[PM3_MAX_BOARD]; -MODULE_PARM(pciid,PM3_MAX_BOARD_MODULE_ARRAY_STRING); +module_param_array(pciid, charp, NULL, 0); MODULE_PARM_DESC(pciid,"board PCI Id"); -MODULE_PARM(noaccel,PM3_MAX_BOARD_MODULE_ARRAY_SHORT); +module_param_array(noaccel, short, NULL, 0); MODULE_PARM_DESC(noaccel,"disable accel"); static char *font[PM3_MAX_BOARD]; -MODULE_PARM(font,PM3_MAX_BOARD_MODULE_ARRAY_STRING); +module_param_array(font, charp, NULL, 0); MODULE_PARM_DESC(font,"choose font"); -MODULE_PARM(depth,PM3_MAX_BOARD_MODULE_ARRAY_SHORT); +module_param(depth, short, NULL, 0); MODULE_PARM_DESC(depth,"boot-time depth"); -MODULE_PARM(printtimings, "h"); +module_param(printtimings, short, NULL, 0); MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)"); -MODULE_PARM(forcesize, PM3_MAX_BOARD_MODULE_ARRAY_SHORT); +module_param(forcesize, short, NULL, 0); MODULE_PARM_DESC(forcesize, "force specified memory size"); /* MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards") diff --git a/include/linux/module.h b/include/linux/module.h index 70bd843c71cb..e144309836af 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -554,25 +554,6 @@ static inline void module_remove_driver(struct device_driver *driver) /* BELOW HERE ALL THESE ARE OBSOLETE AND WILL VANISH */ -struct obsolete_modparm { - char name[64]; - char type[64-sizeof(void *)]; - void *addr; -}; - -static inline void MODULE_PARM_(void) { } -#ifdef MODULE -/* DEPRECATED: Do not use. */ -#define MODULE_PARM(var,type) \ -extern struct obsolete_modparm __parm_##var \ -__attribute__((section("__obsparm"))); \ -struct obsolete_modparm __parm_##var = \ -{ __stringify(var), type, &MODULE_PARM_ }; \ -__MODULE_PARM_TYPE(var, type); -#else -#define MODULE_PARM(var,type) static void __attribute__((__unused__)) *__parm_##var = &MODULE_PARM_; -#endif - #define __MODULE_STRING(x) __stringify(x) /* Use symbol_get and symbol_put instead. You'll thank me. */ diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h index 6f4ea808cf74..ac021379ac40 100644 --- a/include/video/pm3fb.h +++ b/include/video/pm3fb.h @@ -1128,10 +1128,7 @@ #endif /* max number of simultaneous board */ -/* warning : make sure module array def's are coherent with PM3_MAX_BOARD */ #define PM3_MAX_BOARD 4 -#define PM3_MAX_BOARD_MODULE_ARRAY_SHORT "1-4h" -#define PM3_MAX_BOARD_MODULE_ARRAY_STRING "1-4s" /* max size of options */ #define PM3_OPTIONS_SIZE 256 diff --git a/init/Kconfig b/init/Kconfig index 1d19fd25204b..05951c1d654e 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -470,15 +470,6 @@ config MODULE_FORCE_UNLOAD rmmod). This is mainly for kernel developers and desperate users. If unsure, say N. -config OBSOLETE_MODPARM - bool - default y - depends on MODULES - help - You need this option to use module parameters on modules which - have not been converted to the new module parameter system yet. - If unsure, say Y. - config MODVERSIONS bool "Module versioning support" depends on MODULES diff --git a/kernel/module.c b/kernel/module.c index 54623c714bba..ddfe45ac2fd1 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -233,24 +233,6 @@ static unsigned long __find_symbol(const char *name, return 0; } -/* Find a symbol in this elf symbol table */ -static unsigned long find_local_symbol(Elf_Shdr *sechdrs, - unsigned int symindex, - const char *strtab, - const char *name) -{ - unsigned int i; - Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr; - - /* Search (defined) internal symbols first. */ - for (i = 1; i < sechdrs[symindex].sh_size/sizeof(*sym); i++) { - if (sym[i].st_shndx != SHN_UNDEF - && strcmp(name, strtab + sym[i].st_name) == 0) - return sym[i].st_value; - } - return 0; -} - /* Search for module by name: must hold module_mutex. */ static struct module *find_module(const char *name) { @@ -785,139 +767,6 @@ static struct module_attribute *modinfo_attrs[] = { NULL, }; -#ifdef CONFIG_OBSOLETE_MODPARM -/* Bounds checking done below */ -static int obsparm_copy_string(const char *val, struct kernel_param *kp) -{ - strcpy(kp->arg, val); - return 0; -} - -static int set_obsolete(const char *val, struct kernel_param *kp) -{ - unsigned int min, max; - unsigned int size, maxsize; - int dummy; - char *endp; - const char *p; - struct obsolete_modparm *obsparm = kp->arg; - - if (!val) { - printk(KERN_ERR "Parameter %s needs an argument\n", kp->name); - return -EINVAL; - } - - /* type is: [min[-max]]{b,h,i,l,s} */ - p = obsparm->type; - min = simple_strtol(p, &endp, 10); - if (endp == obsparm->type) - min = max = 1; - else if (*endp == '-') { - p = endp+1; - max = simple_strtol(p, &endp, 10); - } else - max = min; - switch (*endp) { - case 'b': - return param_array(kp->name, val, min, max, obsparm->addr, - 1, param_set_byte, &dummy); - case 'h': - return param_array(kp->name, val, min, max, obsparm->addr, - sizeof(short), param_set_short, &dummy); - case 'i': - return param_array(kp->name, val, min, max, obsparm->addr, - sizeof(int), param_set_int, &dummy); - case 'l': - return param_array(kp->name, val, min, max, obsparm->addr, - sizeof(long), param_set_long, &dummy); - case 's': - return param_array(kp->name, val, min, max, obsparm->addr, - sizeof(char *), param_set_charp, &dummy); - - case 'c': - /* Undocumented: 1-5c50 means 1-5 strings of up to 49 chars, - and the decl is "char xxx[5][50];" */ - p = endp+1; - maxsize = simple_strtol(p, &endp, 10); - /* We check lengths here (yes, this is a hack). */ - p = val; - while (p[size = strcspn(p, ",")]) { - if (size >= maxsize) - goto oversize; - p += size+1; - } - if (size >= maxsize) - goto oversize; - return param_array(kp->name, val, min, max, obsparm->addr, - maxsize, obsparm_copy_string, &dummy); - } - printk(KERN_ERR "Unknown obsolete parameter type %s\n", obsparm->type); - return -EINVAL; - oversize: - printk(KERN_ERR - "Parameter %s doesn't fit in %u chars.\n", kp->name, maxsize); - return -EINVAL; -} - -static int obsolete_params(const char *name, - char *args, - struct obsolete_modparm obsparm[], - unsigned int num, - Elf_Shdr *sechdrs, - unsigned int symindex, - const char *strtab) -{ - struct kernel_param *kp; - unsigned int i; - int ret; - - kp = kmalloc(sizeof(kp[0]) * num, GFP_KERNEL); - if (!kp) - return -ENOMEM; - - for (i = 0; i < num; i++) { - char sym_name[128 + sizeof(MODULE_SYMBOL_PREFIX)]; - - snprintf(sym_name, sizeof(sym_name), "%s%s", - MODULE_SYMBOL_PREFIX, obsparm[i].name); - - kp[i].name = obsparm[i].name; - kp[i].perm = 000; - kp[i].set = set_obsolete; - kp[i].get = NULL; - obsparm[i].addr - = (void *)find_local_symbol(sechdrs, symindex, strtab, - sym_name); - if (!obsparm[i].addr) { - printk("%s: falsely claims to have parameter %s\n", - name, obsparm[i].name); - ret = -EINVAL; - goto out; - } - kp[i].arg = &obsparm[i]; - } - - ret = parse_args(name, args, kp, num, NULL); - out: - kfree(kp); - return ret; -} -#else -static int obsolete_params(const char *name, - char *args, - struct obsolete_modparm obsparm[], - unsigned int num, - Elf_Shdr *sechdrs, - unsigned int symindex, - const char *strtab) -{ - if (num != 0) - printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", - name); - return 0; -} -#endif /* CONFIG_OBSOLETE_MODPARM */ - static const char vermagic[] = VERMAGIC_STRING; #ifdef CONFIG_MODVERSIONS @@ -1874,27 +1723,17 @@ static struct module *load_module(void __user *umod, set_fs(old_fs); mod->args = args; - if (obsparmindex) { - err = obsolete_params(mod->name, mod->args, - (struct obsolete_modparm *) - sechdrs[obsparmindex].sh_addr, - sechdrs[obsparmindex].sh_size - / sizeof(struct obsolete_modparm), - sechdrs, symindex, - (char *)sechdrs[strindex].sh_addr); - if (setupindex) - printk(KERN_WARNING "%s: Ignoring new-style " - "parameters in presence of obsolete ones\n", - mod->name); - } else { - /* Size of section 0 is 0, so this works well if no params */ - err = parse_args(mod->name, mod->args, - (struct kernel_param *) - sechdrs[setupindex].sh_addr, - sechdrs[setupindex].sh_size - / sizeof(struct kernel_param), - NULL); - } + if (obsparmindex) + printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", + mod->name); + + /* Size of section 0 is 0, so this works well if no params */ + err = parse_args(mod->name, mod->args, + (struct kernel_param *) + sechdrs[setupindex].sh_addr, + sechdrs[setupindex].sh_size + / sizeof(struct kernel_param), + NULL); if (err < 0) goto arch_cleanup; diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 9a1fa8894b95..b4b362b5baf5 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -54,15 +54,15 @@ static int verbose; /* Print more debug info. */ static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */ static int shuffle_interval = 5; /* Interval between shuffles (in sec)*/ -MODULE_PARM(nreaders, "i"); +module_param(nreaders, int, 0); MODULE_PARM_DESC(nreaders, "Number of RCU reader threads"); -MODULE_PARM(stat_interval, "i"); +module_param(stat_interval, int, 0); MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s"); -MODULE_PARM(verbose, "i"); +module_param(verbose, bool, 0); MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s"); -MODULE_PARM(test_no_idle_hz, "i"); +module_param(test_no_idle_hz, bool, 0); MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs"); -MODULE_PARM(shuffle_interval, "i"); +module_param(shuffle_interval, int, 0); MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles"); #define TORTURE_FLAG "rcutorture: " #define PRINTK_STRING(s) \ diff --git a/sound/oss/au1000.c b/sound/oss/au1000.c index fe54de25aafc..eacb0aef21e1 100644 --- a/sound/oss/au1000.c +++ b/sound/oss/au1000.c @@ -100,7 +100,7 @@ /* Boot options */ static int vra = 0; // 0 = no VRA, 1 = use VRA if codec supports it -MODULE_PARM(vra, "i"); +module_param(vra, bool, 0); MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it"); diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index 6a4956b8025d..c1168fae6be6 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c @@ -79,7 +79,7 @@ * 0 = no VRA, 1 = use VRA if codec supports it */ static int vra = 1; -MODULE_PARM(vra, "i"); +module_param(vra, bool, 0); MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it"); static struct au1550_state { diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index c9302a1e515b..87bd3100aef3 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -195,18 +195,18 @@ */ int dmasound_catchRadius = 0; -MODULE_PARM(dmasound_catchRadius, "i"); +module_param(dmasound_catchRadius, int, 0); static unsigned int numWriteBufs = DEFAULT_N_BUFFERS; -MODULE_PARM(numWriteBufs, "i"); +module_param(numWriteBufs, int, 0); static unsigned int writeBufSize = DEFAULT_BUFF_SIZE ; /* in bytes */ -MODULE_PARM(writeBufSize, "i"); +module_param(writeBufSize, int, 0); #ifdef HAS_RECORD static unsigned int numReadBufs = DEFAULT_N_BUFFERS; -MODULE_PARM(numReadBufs, "i"); +module_param(numReadBufs, int, 0); static unsigned int readBufSize = DEFAULT_BUFF_SIZE; /* in bytes */ -MODULE_PARM(readBufSize, "i"); +module_param(readBufSize, int, 0); #endif MODULE_LICENSE("GPL"); diff --git a/sound/oss/ite8172.c b/sound/oss/ite8172.c index ffcb910f5c3e..00ac1c95a429 100644 --- a/sound/oss/ite8172.c +++ b/sound/oss/ite8172.c @@ -1968,9 +1968,9 @@ static int i2s_fmt[NR_DEVICE]; static unsigned int devindex; -MODULE_PARM(spdif, "1-" __MODULE_STRING(NR_DEVICE) "i"); +module_param_array(spdif, int, NULL, 0); MODULE_PARM_DESC(spdif, "if 1 the S/PDIF digital output is enabled"); -MODULE_PARM(i2s_fmt, "1-" __MODULE_STRING(NR_DEVICE) "i"); +module_param_array(i2s_fmt, int, NULL, 0); MODULE_PARM_DESC(i2s_fmt, "the format of I2S"); MODULE_AUTHOR("Monta Vista Software, stevel@mvista.com"); diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index dce9016cbcfd..eb5ea32fd1b0 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c @@ -154,8 +154,8 @@ static void start_adc(struct cs4297a_state *s); #if CSDEBUG static unsigned long cs_debuglevel = 4; // levels range from 1-9 static unsigned long cs_debugmask = CS_INIT /*| CS_IOCTL*/; -MODULE_PARM(cs_debuglevel, "i"); -MODULE_PARM(cs_debugmask, "i"); +module_param(cs_debuglevel, int, 0); +module_param(cs_debugmask, int, 0); #endif #define CS_TRUE 1 #define CS_FALSE 0 diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c index 99d04ad3ca13..afcb524a40eb 100644 --- a/sound/oss/waveartist.c +++ b/sound/oss/waveartist.c @@ -2028,8 +2028,8 @@ __setup("waveartist=", setup_waveartist); #endif MODULE_DESCRIPTION("Rockwell WaveArtist RWA-010 sound driver"); -MODULE_PARM(io, "i"); /* IO base */ -MODULE_PARM(irq, "i"); /* IRQ */ -MODULE_PARM(dma, "i"); /* DMA */ -MODULE_PARM(dma2, "i"); /* DMA2 */ +module_param(io, int, 0); /* IO base */ +module_param(irq, int, 0); /* IRQ */ +module_param(dma, int, 0); /* DMA */ +module_param(dma2, int, 0); /* DMA2 */ MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From bf36b9011e3c5b2739f9da2f6de8a6fa3edded32 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 25 Mar 2006 03:07:08 -0800 Subject: [PATCH] sysrq cleanup sysrq.c is fairly revolting. Fix. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/sysrq.c | 250 ++++++++++++++++++++++++--------------------------- 1 file changed, 115 insertions(+), 135 deletions(-) (limited to 'drivers') diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index d58f82318853..35082dc12eae 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -42,16 +42,15 @@ /* Whether we react on sysrq keys or just ignore them */ int sysrq_enabled = 1; -/* Loglevel sysrq handler */ static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { int i; i = key - '0'; console_loglevel = 7; printk("Loglevel set to %d\n", i); console_loglevel = i; -} +} static struct sysrq_key_op sysrq_loglevel_op = { .handler = sysrq_handle_loglevel, .help_msg = "loglevel0-8", @@ -59,11 +58,9 @@ static struct sysrq_key_op sysrq_loglevel_op = { .enable_mask = SYSRQ_ENABLE_LOG, }; - -/* SAK sysrq handler */ #ifdef CONFIG_VT static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { if (tty) do_SAK(tty); @@ -75,12 +72,13 @@ static struct sysrq_key_op sysrq_SAK_op = { .action_msg = "SAK", .enable_mask = SYSRQ_ENABLE_KEYBOARD, }; +#else +#define sysrq_SAK_op (*(struct sysrq_key_op *)0) #endif #ifdef CONFIG_VT -/* unraw sysrq handler */ static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { struct kbd_struct *kbd = &kbd_table[fg_console]; @@ -93,10 +91,11 @@ static struct sysrq_key_op sysrq_unraw_op = { .action_msg = "Keyboard mode set to XLATE", .enable_mask = SYSRQ_ENABLE_KEYBOARD, }; +#else +#define sysrq_unraw_op (*(struct sysrq_key_op *)0) #endif /* CONFIG_VT */ #ifdef CONFIG_KEXEC -/* crashdump sysrq handler */ static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { @@ -108,16 +107,16 @@ static struct sysrq_key_op sysrq_crashdump_op = { .action_msg = "Trigger a crashdump", .enable_mask = SYSRQ_ENABLE_DUMP, }; +#else +#define sysrq_crashdump_op (*(struct sysrq_key_op *)0) #endif -/* reboot sysrq handler */ static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { local_irq_enable(); emergency_restart(); } - static struct sysrq_key_op sysrq_reboot_op = { .handler = sysrq_handle_reboot, .help_msg = "reBoot", @@ -126,11 +125,10 @@ static struct sysrq_key_op sysrq_reboot_op = { }; static void sysrq_handle_sync(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { emergency_sync(); } - static struct sysrq_key_op sysrq_sync_op = { .handler = sysrq_handle_sync, .help_msg = "Sync", @@ -139,11 +137,10 @@ static struct sysrq_key_op sysrq_sync_op = { }; static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { emergency_remount(); } - static struct sysrq_key_op sysrq_mountro_op = { .handler = sysrq_handle_mountro, .help_msg = "Unmount", @@ -151,28 +148,23 @@ static struct sysrq_key_op sysrq_mountro_op = { .enable_mask = SYSRQ_ENABLE_REMOUNT, }; -/* END SYNC SYSRQ HANDLERS BLOCK */ - #ifdef CONFIG_DEBUG_MUTEXES - -static void -sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, struct tty_struct *tty) +static void sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, + struct tty_struct *tty) { mutex_debug_show_all_locks(); } - static struct sysrq_key_op sysrq_showlocks_op = { .handler = sysrq_handle_showlocks, .help_msg = "show-all-locks(D)", .action_msg = "Show Locks Held", }; - +#else +#define sysrq_showlocks_op (*(struct sysrq_key_op *)0) #endif -/* SHOW SYSRQ HANDLERS BLOCK */ - static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { if (pt_regs) show_regs(pt_regs); @@ -184,9 +176,8 @@ static struct sysrq_key_op sysrq_showregs_op = { .enable_mask = SYSRQ_ENABLE_DUMP, }; - static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { show_state(); } @@ -197,9 +188,8 @@ static struct sysrq_key_op sysrq_showstate_op = { .enable_mask = SYSRQ_ENABLE_DUMP, }; - static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { show_mem(); } @@ -210,13 +200,9 @@ static struct sysrq_key_op sysrq_showmem_op = { .enable_mask = SYSRQ_ENABLE_DUMP, }; -/* SHOW SYSRQ HANDLERS BLOCK */ - - -/* SIGNAL SYSRQ HANDLERS BLOCK */ - -/* signal sysrq helper function - * Sends a signal to all user processes */ +/* + * Signal sysrq helper function. Sends a signal to all user processes. + */ static void send_sig_all(int sig) { struct task_struct *p; @@ -229,7 +215,7 @@ static void send_sig_all(int sig) } static void sysrq_handle_term(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { send_sig_all(SIGTERM); console_loglevel = 8; @@ -243,7 +229,8 @@ static struct sysrq_key_op sysrq_term_op = { static void moom_callback(void *ignored) { - out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0); + out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], + GFP_KERNEL, 0); } static DECLARE_WORK(moom_work, moom_callback, NULL); @@ -260,7 +247,7 @@ static struct sysrq_key_op sysrq_moom_op = { }; static void sysrq_handle_kill(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { send_sig_all(SIGKILL); console_loglevel = 8; @@ -272,8 +259,6 @@ static struct sysrq_key_op sysrq_kill_op = { .enable_mask = SYSRQ_ENABLE_SIGNAL, }; -/* END SIGNAL SYSRQ HANDLERS BLOCK */ - static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { @@ -288,110 +273,99 @@ static struct sysrq_key_op sysrq_unrt_op = { /* Key Operations table and lock */ static DEFINE_SPINLOCK(sysrq_key_table_lock); -#define SYSRQ_KEY_TABLE_LENGTH 36 -static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = { -/* 0 */ &sysrq_loglevel_op, -/* 1 */ &sysrq_loglevel_op, -/* 2 */ &sysrq_loglevel_op, -/* 3 */ &sysrq_loglevel_op, -/* 4 */ &sysrq_loglevel_op, -/* 5 */ &sysrq_loglevel_op, -/* 6 */ &sysrq_loglevel_op, -/* 7 */ &sysrq_loglevel_op, -/* 8 */ &sysrq_loglevel_op, -/* 9 */ &sysrq_loglevel_op, -/* a */ NULL, /* Don't use for system provided sysrqs, - it is handled specially on the sparc - and will never arrive */ -/* b */ &sysrq_reboot_op, -#ifdef CONFIG_KEXEC -/* c */ &sysrq_crashdump_op, -#else -/* c */ NULL, -#endif -#ifdef CONFIG_DEBUG_MUTEXES -/* d */ &sysrq_showlocks_op, -#else -/* d */ NULL, -#endif -/* e */ &sysrq_term_op, -/* f */ &sysrq_moom_op, -/* g */ NULL, -/* h */ NULL, -/* i */ &sysrq_kill_op, -/* j */ NULL, -#ifdef CONFIG_VT -/* k */ &sysrq_SAK_op, -#else -/* k */ NULL, -#endif -/* l */ NULL, -/* m */ &sysrq_showmem_op, -/* n */ &sysrq_unrt_op, -/* o */ NULL, /* This will often be registered - as 'Off' at init time */ -/* p */ &sysrq_showregs_op, -/* q */ NULL, -#ifdef CONFIG_VT -/* r */ &sysrq_unraw_op, -#else -/* r */ NULL, -#endif -/* s */ &sysrq_sync_op, -/* t */ &sysrq_showstate_op, -/* u */ &sysrq_mountro_op, -/* v */ NULL, /* May be assigned at init time by SMP VOYAGER */ -/* w */ NULL, -/* x */ NULL, -/* y */ NULL, -/* z */ NULL + +static struct sysrq_key_op *sysrq_key_table[36] = { + &sysrq_loglevel_op, /* 0 */ + &sysrq_loglevel_op, /* 1 */ + &sysrq_loglevel_op, /* 2 */ + &sysrq_loglevel_op, /* 3 */ + &sysrq_loglevel_op, /* 4 */ + &sysrq_loglevel_op, /* 5 */ + &sysrq_loglevel_op, /* 6 */ + &sysrq_loglevel_op, /* 7 */ + &sysrq_loglevel_op, /* 8 */ + &sysrq_loglevel_op, /* 9 */ + + /* + * Don't use for system provided sysrqs, it is handled specially on + * sparc and will never arrive + */ + NULL, /* a */ + &sysrq_reboot_op, /* b */ + &sysrq_crashdump_op, /* c */ + &sysrq_showlocks_op, /* d */ + &sysrq_term_op, /* e */ + &sysrq_moom_op, /* f */ + NULL, /* g */ + NULL, /* h */ + &sysrq_kill_op, /* i */ + NULL, /* j */ + &sysrq_SAK_op, /* k */ + NULL, /* l */ + &sysrq_showmem_op, /* m */ + &sysrq_unrt_op, /* n */ + /* This will often be registered as 'Off' at init time */ + NULL, /* o */ + &sysrq_showregs_op, /* p */ + NULL, /* q */ + &sysrq_unraw_op, /* r */ + &sysrq_sync_op, /* s */ + &sysrq_showstate_op, /* t */ + &sysrq_mountro_op, /* u */ + /* May be assigned at init time by SMP VOYAGER */ + NULL, /* v */ + NULL, /* w */ + NULL, /* x */ + NULL, /* y */ + NULL /* z */ }; /* key2index calculation, -1 on invalid index */ -static int sysrq_key_table_key2index(int key) { +static int sysrq_key_table_key2index(int key) +{ int retval; - if ((key >= '0') && (key <= '9')) { + + if ((key >= '0') && (key <= '9')) retval = key - '0'; - } else if ((key >= 'a') && (key <= 'z')) { + else if ((key >= 'a') && (key <= 'z')) retval = key + 10 - 'a'; - } else { + else retval = -1; - } return retval; } /* * get and put functions for the table, exposed to modules. */ - -struct sysrq_key_op *__sysrq_get_key_op (int key) { - struct sysrq_key_op *op_p; +struct sysrq_key_op *__sysrq_get_key_op(int key) +{ + struct sysrq_key_op *op_p = NULL; int i; - + i = sysrq_key_table_key2index(key); - op_p = (i == -1) ? NULL : sysrq_key_table[i]; + if (i != -1) + op_p = sysrq_key_table[i]; return op_p; } -static void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) { - int i; +static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p) +{ + int i = sysrq_key_table_key2index(key); - i = sysrq_key_table_key2index(key); if (i != -1) sysrq_key_table[i] = op_p; } /* - * This is the non-locking version of handle_sysrq - * It must/can only be called by sysrq key handlers, - * as they are inside of the lock + * This is the non-locking version of handle_sysrq. It must/can only be called + * by sysrq key handlers, as they are inside of the lock */ - -void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, int check_mask) +void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, + int check_mask) { struct sysrq_key_op *op_p; int orig_log_level; - int i, j; + int i; unsigned long flags; spin_lock_irqsave(&sysrq_key_table_lock, flags); @@ -401,26 +375,34 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, in op_p = __sysrq_get_key_op(key); if (op_p) { - /* Should we check for enabled operations (/proc/sysrq-trigger should not) - * and is the invoked operation enabled? */ + /* + * Should we check for enabled operations (/proc/sysrq-trigger + * should not) and is the invoked operation enabled? + */ if (!check_mask || sysrq_enabled == 1 || (sysrq_enabled & op_p->enable_mask)) { - printk ("%s\n", op_p->action_msg); + printk("%s\n", op_p->action_msg); console_loglevel = orig_log_level; op_p->handler(key, pt_regs, tty); - } - else + } else { printk("This sysrq operation is disabled.\n"); + } } else { printk("HELP : "); /* Only print the help msg once per handler */ - for (i=0; ihelp_msg); + for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) { + if (sysrq_key_table[i]) { + int j; + + for (j = 0; sysrq_key_table[i] != + sysrq_key_table[j]; j++) + ; + if (j != i) + continue; + printk("%s ", sysrq_key_table[i]->help_msg); + } } - printk ("\n"); + printk("\n"); console_loglevel = orig_log_level; } spin_unlock_irqrestore(&sysrq_key_table_lock, flags); @@ -430,16 +412,17 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, in * This function is called by the keyboard handler when SysRq is pressed * and any other keycode arrives. */ - void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { if (!sysrq_enabled) return; __handle_sysrq(key, pt_regs, tty, 1); } +EXPORT_SYMBOL(handle_sysrq); static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, - struct sysrq_key_op *remove_op_p) { + struct sysrq_key_op *remove_op_p) +{ int retval; unsigned long flags; @@ -452,7 +435,6 @@ static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, retval = -1; } spin_unlock_irqrestore(&sysrq_key_table_lock, flags); - return retval; } @@ -460,12 +442,10 @@ int register_sysrq_key(int key, struct sysrq_key_op *op_p) { return __sysrq_swap_key_ops(key, op_p, NULL); } +EXPORT_SYMBOL(register_sysrq_key); int unregister_sysrq_key(int key, struct sysrq_key_op *op_p) { return __sysrq_swap_key_ops(key, NULL, op_p); } - -EXPORT_SYMBOL(handle_sysrq); -EXPORT_SYMBOL(register_sysrq_key); EXPORT_SYMBOL(unregister_sysrq_key); -- cgit v1.2.3-59-g8ed1b From fbd8ad30596409070801832335d3ea8cf1513ded Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 25 Mar 2006 03:07:11 -0800 Subject: [PATCH] ide: fix section mismatch warning In latest -mm ide-code.o gave a number of warnings like the following: WARNING: drivers/ide/ide-core.o - Section mismatch: reference to \ .init.text: from .text between 'init_module' (at offset 0x1f97) and \ 'cleanup_module' The warning was caused by init_module() calling parse_option() and ide_init() both declared __init. Declaring init_module() __init fixes the warnings. Signed-off-by: Sam Ravnborg Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index b2cc43702f65..3fdab563fec2 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -2058,7 +2058,7 @@ static void __init parse_options (char *line) } } -int init_module (void) +int __init init_module (void) { parse_options(options); return ide_init(); -- cgit v1.2.3-59-g8ed1b From 1efa64696bc55cc396eefa9838a90d106dfab6bf Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 25 Mar 2006 03:07:13 -0800 Subject: [PATCH] block/floppy: fix section mismatch warnings In latest -mm a number of section mismatch warnings are generated for floppy.o like the following: WARNING: drivers/block/floppy.o - Section mismatch: reference to \ .init.data: from .text between 'init_module' (at offset 0x6976) and \ 'cleanup_module' The warning are caused by a reference to floppy_init() which is __init from init_module() which is not declared __init. Declaring init_module() _init fixes this. Signed-off-by: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/floppy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index fb2d0be7cdeb..840919bba76c 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4594,7 +4594,7 @@ static void __init parse_floppy_cfg_string(char *cfg) } } -int init_module(void) +int __init init_module(void) { if (floppy) parse_floppy_cfg_string(floppy); -- cgit v1.2.3-59-g8ed1b From e6a6784627483381d012b507bb0d49809658a1fa Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Sat, 25 Mar 2006 03:07:13 -0800 Subject: [PATCH] parport: move PP_MAJOR from ppdev.h to major.h Today I wondered about /dev/parport after not seeing anything in drivers/parport register char-major-99. Having PP_MAJOR in include/linux/major.h would've allowed me to more quickly determine that it was the ppdev driver driving these. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ppdev.c | 3 ++- include/linux/major.h | 1 + include/linux/ppdev.h | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 306ee0f091a4..bee6c47b45bd 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -65,10 +65,11 @@ #include #include #include -#include +#include #include #include #include +#include #define PP_VERSION "ppdev: user-space parallel port driver" #define CHRDEV "ppdev" diff --git a/include/linux/major.h b/include/linux/major.h index e36a46702d94..0a74c52924c9 100644 --- a/include/linux/major.h +++ b/include/linux/major.h @@ -113,6 +113,7 @@ #define UBD_MAJOR 98 +#define PP_MAJOR 99 #define JSFD_MAJOR 99 #define PHONE_MAJOR 100 diff --git a/include/linux/ppdev.h b/include/linux/ppdev.h index 141c96586824..f376a7598a78 100644 --- a/include/linux/ppdev.h +++ b/include/linux/ppdev.h @@ -14,8 +14,6 @@ * Added PPGETMODES/PPGETMODE/PPGETPHASE, Fred Barnes , 03/01/2001 */ -#define PP_MAJOR 99 - #define PP_IOCTL 'p' /* Set mode for read/write (e.g. IEEE1284_MODE_EPP) */ -- cgit v1.2.3-59-g8ed1b From e51c01b08474ea454a965a937fff0407ab6714c7 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 25 Mar 2006 03:07:17 -0800 Subject: [PATCH] hp300: fix driver_register() return handling, remove dio_module_init() Remove the assumption that driver_register() returns the number of devices bound to the driver. In fact, it returns zero for success or a negative error value. dio_module_init() used the device count to automatically unregister and unload drivers that found no devices. That might have worked at one time, but has been broken for some time because dio_register_driver() returned either a negative error or a positive count (never zero). So it could only unregister on failure, when it's not needed anyway. This functionality could be resurrected in individual drivers by counting devices in their .probe() methods. Signed-off-by: Bjorn Helgaas Cc: Philip Blundell Cc: Jochen Friedrich Cc: "Antonino A. Daplas" Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/dio/dio-driver.c | 9 ++------- drivers/net/hplance.c | 2 +- drivers/serial/8250_hp300.c | 10 +++++----- drivers/video/hpfb.c | 4 +++- include/linux/dio.h | 32 -------------------------------- 5 files changed, 11 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/dio/dio-driver.c b/drivers/dio/dio-driver.c index ca8e69d2f64d..e4c48e329367 100644 --- a/drivers/dio/dio-driver.c +++ b/drivers/dio/dio-driver.c @@ -71,22 +71,17 @@ static int dio_device_probe(struct device *dev) * @drv: the driver structure to register * * Adds the driver structure to the list of registered drivers - * Returns the number of DIO devices which were claimed by the driver - * during registration. The driver remains registered even if the - * return value is zero. + * Returns zero or a negative error value. */ int dio_register_driver(struct dio_driver *drv) { - int count = 0; - /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &dio_bus_type; /* register with core */ - count = driver_register(&drv->driver); - return count ? count : 1; + return driver_register(&drv->driver); } diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c index d8410634bcaf..685693464605 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c @@ -217,7 +217,7 @@ static int hplance_close(struct net_device *dev) int __init hplance_init_module(void) { - return dio_module_init(&hplance_driver); + return dio_register_driver(&hplance_driver); } void __exit hplance_cleanup_module(void) diff --git a/drivers/serial/8250_hp300.c b/drivers/serial/8250_hp300.c index 4315afe9c080..53e81a44c1a3 100644 --- a/drivers/serial/8250_hp300.c +++ b/drivers/serial/8250_hp300.c @@ -55,6 +55,8 @@ static struct dio_driver hpdca_driver = { #endif +static unsigned int num_ports; + extern int hp300_uart_scode; /* Offset to UART registers from base of DCA */ @@ -199,6 +201,8 @@ static int __devinit hpdca_init_one(struct dio_dev *d, out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff); udelay(100); + num_ports++; + return 0; } #endif @@ -206,7 +210,6 @@ static int __devinit hpdca_init_one(struct dio_dev *d, static int __init hp300_8250_init(void) { static int called = 0; - int num_ports; #ifdef CONFIG_HPAPCI int line; unsigned long base; @@ -221,11 +224,8 @@ static int __init hp300_8250_init(void) if (!MACH_IS_HP300) return -ENODEV; - num_ports = 0; - #ifdef CONFIG_HPDCA - if (dio_module_init(&hpdca_driver) == 0) - num_ports++; + dio_register_driver(&hpdca_driver); #endif #ifdef CONFIG_HPAPCI if (hp300_model < HP_400) { diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index bebdac59d231..abd920a663a0 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -386,7 +386,9 @@ int __init hpfb_init(void) if (fb_get_options("hpfb", NULL)) return -ENODEV; - dio_module_init(&hpfb_driver); + err = dio_register_driver(&hpfb_driver); + if (err) + return err; fs = get_fs(); set_fs(KERNEL_DS); diff --git a/include/linux/dio.h b/include/linux/dio.h index fae9395fcf4f..1e65ebc2a3db 100644 --- a/include/linux/dio.h +++ b/include/linux/dio.h @@ -276,37 +276,5 @@ static inline void dio_set_drvdata (struct dio_dev *d, void *data) dev_set_drvdata(&d->dev, data); } -/* - * A helper function which helps ensure correct dio_driver - * setup and cleanup for commonly-encountered hotplug/modular cases - * - * This MUST stay in a header, as it checks for -DMODULE - */ -static inline int dio_module_init(struct dio_driver *drv) -{ - int rc = dio_register_driver(drv); - - if (rc > 0) - return 0; - - /* iff CONFIG_HOTPLUG and built into kernel, we should - * leave the driver around for future hotplug events. - * For the module case, a hotplug daemon of some sort - * should load a module in response to an insert event. */ -#if defined(CONFIG_HOTPLUG) && !defined(MODULE) - if (rc == 0) - return 0; -#else - if (rc == 0) - rc = -ENODEV; -#endif - - /* if we get here, we need to clean up DIO driver instance - * and return some sort of error */ - dio_unregister_driver(drv); - - return rc; -} - #endif /* __KERNEL__ */ #endif /* ndef _LINUX_DIO_H */ -- cgit v1.2.3-59-g8ed1b From c2f6fabb2ed3b869bc254c6cdc73d6beaaaf700f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 25 Mar 2006 03:07:19 -0800 Subject: [PATCH] EISA: tidy-up driver_register() return value Remove the assumption that driver_register() returns the number of devices bound to the driver. In fact, it returns zero for success or a negative error value. Signed-off-by: Bjorn Helgaas Acked-by: Jeff Garzik Acked-by: Marc Zyngier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/eisa/eisa-bus.c | 7 +------ drivers/net/3c59x.c | 20 ++++++++++++-------- drivers/net/dgrs.c | 14 +++++++------- 3 files changed, 20 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 4196137e66de..6078e2f58817 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -135,13 +135,8 @@ struct bus_type eisa_bus_type = { int eisa_driver_register (struct eisa_driver *edrv) { - int r; - edrv->driver.bus = &eisa_bus_type; - if ((r = driver_register (&edrv->driver)) < 0) - return r; - - return 0; + return driver_register (&edrv->driver); } void eisa_driver_unregister (struct eisa_driver *edrv) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 5d11a06ecb2c..d339308539fa 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1096,14 +1096,18 @@ static int __init vortex_eisa_init (void) int orig_cards_found = vortex_cards_found; #ifdef CONFIG_EISA - if (eisa_driver_register (&vortex_eisa_driver) >= 0) { - /* Because of the way EISA bus is probed, we cannot assume - * any device have been found when we exit from - * eisa_driver_register (the bus root driver may not be - * initialized yet). So we blindly assume something was - * found, and let the sysfs magic happend... */ - - eisa_found = 1; + int err; + + err = eisa_driver_register (&vortex_eisa_driver); + if (!err) { + /* + * Because of the way EISA bus is probed, we cannot assume + * any device have been found when we exit from + * eisa_driver_register (the bus root driver may not be + * initialized yet). So we blindly assume something was + * found, and let the sysfs magic happend... + */ + eisa_found = 1; } #endif diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 32d13166c6e8..e175d4876682 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -1551,7 +1551,7 @@ MODULE_PARM_DESC(nicmode, "Digi RightSwitch operating mode (1: switch, 2: multi- static int __init dgrs_init_module (void) { int i; - int cardcount = 0; + int err; /* * Command line variable overrides @@ -1593,13 +1593,13 @@ static int __init dgrs_init_module (void) * Find and configure all the cards */ #ifdef CONFIG_EISA - cardcount = eisa_driver_register(&dgrs_eisa_driver); - if (cardcount < 0) - return cardcount; + err = eisa_driver_register(&dgrs_eisa_driver); + if (err) + return err; #endif - cardcount = pci_register_driver(&dgrs_pci_driver); - if (cardcount) - return cardcount; + err = pci_register_driver(&dgrs_pci_driver); + if (err) + return err; return 0; } -- cgit v1.2.3-59-g8ed1b From 33d8675ea66e79d21da3ed64ce88dfb2a18bc6a7 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 25 Mar 2006 03:07:20 -0800 Subject: [PATCH] amiga: fix driver_register() return handling, remove zorro_module_init() Remove the assumption that driver_register() returns the number of devices bound to the driver. In fact, it returns zero for success or a negative error value. zorro_module_init() used the device count to automatically unregister and unload drivers that found no devices. That might have worked at one time, but has been broken for some time because zorro_register_driver() returned either a negative error or a positive count (never zero). So it could only unregister on failure, when it's not needed anyway. This functionality could be resurrected in individual drivers by counting devices in their .probe() methods. Signed-off-by: Bjorn Helgaas Cc: Geert Uytterhoeven Cc: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/a2065.c | 2 +- drivers/net/ariadne.c | 2 +- drivers/net/hydra.c | 2 +- drivers/net/zorro8390.c | 2 +- drivers/video/cirrusfb.c | 2 +- drivers/zorro/zorro-driver.c | 9 ++------- include/linux/zorro.h | 33 --------------------------------- 7 files changed, 7 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 8e538a6d7d97..79bb56b8dcef 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -829,7 +829,7 @@ static void __devexit a2065_remove_one(struct zorro_dev *z) static int __init a2065_init_module(void) { - return zorro_module_init(&a2065_driver); + return zorro_register_driver(&a2065_driver); } static void __exit a2065_cleanup_module(void) diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index 9fe93acfc8ef..d1b6b1f794e2 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -864,7 +864,7 @@ static void __devexit ariadne_remove_one(struct zorro_dev *z) static int __init ariadne_init_module(void) { - return zorro_module_init(&ariadne_driver); + return zorro_register_driver(&ariadne_driver); } static void __exit ariadne_cleanup_module(void) diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 6e0ca7340a8f..d9fb8e74e631 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -242,7 +242,7 @@ static void __devexit hydra_remove_one(struct zorro_dev *z) static int __init hydra_init_module(void) { - return zorro_module_init(&hydra_driver); + return zorro_register_driver(&hydra_driver); } static void __exit hydra_cleanup_module(void) diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index 761021603597..8037e5806d0a 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -426,7 +426,7 @@ static void __devexit zorro8390_remove_one(struct zorro_dev *z) static int __init zorro8390_init_module(void) { - return zorro_module_init(&zorro8390_driver); + return zorro_register_driver(&zorro8390_driver); } static void __exit zorro8390_cleanup_module(void) diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index e0dbdfc0c8b4..66d6f2f0a219 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2622,7 +2622,7 @@ static int __init cirrusfb_init(void) #endif #ifdef CONFIG_ZORRO - error |= zorro_module_init(&cirrusfb_zorro_driver); + error |= zorro_register_driver(&cirrusfb_zorro_driver); #endif #ifdef CONFIG_PCI error |= pci_register_driver(&cirrusfb_pci_driver); diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index fcbee748c592..067c07be928c 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c @@ -65,22 +65,17 @@ static int zorro_device_probe(struct device *dev) * @drv: the driver structure to register * * Adds the driver structure to the list of registered drivers - * Returns the number of Zorro devices which were claimed by the driver - * during registration. The driver remains registered even if the - * return value is zero. + * Returns zero or a negative error value. */ int zorro_register_driver(struct zorro_driver *drv) { - int count = 0; - /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &zorro_bus_type; /* register with core */ - count = driver_register(&drv->driver); - return count ? count : 1; + return driver_register(&drv->driver); } diff --git a/include/linux/zorro.h b/include/linux/zorro.h index ba5b72768bbe..2f135cf6eef1 100644 --- a/include/linux/zorro.h +++ b/include/linux/zorro.h @@ -271,39 +271,6 @@ static inline void zorro_set_drvdata (struct zorro_dev *z, void *data) } -/* - * A helper function which helps ensure correct zorro_driver - * setup and cleanup for commonly-encountered hotplug/modular cases - * - * This MUST stay in a header, as it checks for -DMODULE - */ -static inline int zorro_module_init(struct zorro_driver *drv) -{ - int rc = zorro_register_driver(drv); - - if (rc > 0) - return 0; - - /* iff CONFIG_HOTPLUG and built into kernel, we should - * leave the driver around for future hotplug events. - * For the module case, a hotplug daemon of some sort - * should load a module in response to an insert event. */ -#if defined(CONFIG_HOTPLUG) && !defined(MODULE) - if (rc == 0) - return 0; -#else - if (rc == 0) - rc = -ENODEV; -#endif - - /* if we get here, we need to clean up Zorro driver instance - * and return some sort of error */ - zorro_unregister_driver(drv); - - return rc; -} - - /* * Bitmask indicating portions of available Zorro II RAM that are unused * by the system. Every bit represents a 64K chunk, for a maximum of 8MB -- cgit v1.2.3-59-g8ed1b From c654d60e8f0ea13e35b15cff54c0e473b8b162be Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Sat, 25 Mar 2006 03:07:31 -0800 Subject: [PATCH] adjust /dev/{kmem,mem,port} write handlers The /dev/mem and /dev/kmem write handlers weren't fully POSIX compliant in that they wouldn't always force the file pointer to be updated when returning success status. The /dev/port write handler was inconsistent with the /dev/mem and /dev/kmem handlers in that when encountering a -EFAULT condition after already having written a number of items it would return -EFAULT rather than the number of bytes written. Signed-off-by: Jan Beulich Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/mem.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 29c41f4418c0..26d0116b48d4 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -216,11 +216,9 @@ static ssize_t write_mem(struct file * file, const char __user * buf, copied = copy_from_user(ptr, buf, sz); if (copied) { - ssize_t ret; - - ret = written + (sz - copied); - if (ret) - return ret; + written += sz - copied; + if (written) + break; return -EFAULT; } buf += sz; @@ -456,11 +454,9 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf, copied = copy_from_user(ptr, buf, sz); if (copied) { - ssize_t ret; - - ret = written + (sz - copied); - if (ret) - return ret; + written += sz - copied; + if (written) + break; return -EFAULT; } buf += sz; @@ -514,11 +510,10 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, if (len) { written = copy_from_user(kbuf, buf, len); if (written) { - ssize_t ret; - + if (wrote + virtr) + break; free_page((unsigned long)kbuf); - ret = wrote + virtr + (len - written); - return ret ? ret : -EFAULT; + return -EFAULT; } } len = vwrite(kbuf, (char *)p, len); @@ -563,8 +558,11 @@ static ssize_t write_port(struct file * file, const char __user * buf, return -EFAULT; while (count-- > 0 && i < 65536) { char c; - if (__get_user(c, tmp)) + if (__get_user(c, tmp)) { + if (tmp > buf) + break; return -EFAULT; + } outb(c,i); i++; tmp++; -- cgit v1.2.3-59-g8ed1b From 36a95bf5cd2c33280282da18eff0180a99cff201 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sat, 25 Mar 2006 03:07:33 -0800 Subject: [PATCH] fix hardcoded values in collie frontlight In frontlight support, we should really use values from flash-ROM instead of hardcoding our own. Cleanup includes. Signed-off-by: Pavel Machek Acked-by: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/locomolcd.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c index ada6e75eb048..60831bb23685 100644 --- a/drivers/video/backlight/locomolcd.c +++ b/drivers/video/backlight/locomolcd.c @@ -20,14 +20,10 @@ #include #include +#include +#include -#ifdef CONFIG_SA1100_COLLIE -#include -#else -#include -#endif - -extern void (*sa1100fb_lcd_power)(int on); +#include "../../../arch/arm/mach-sa1100/generic.h" static struct locomo_dev *locomolcd_dev; @@ -82,7 +78,7 @@ static void locomolcd_off(int comadj) void locomolcd_power(int on) { - int comadj = 118; + int comadj = sharpsl_param.comadj; unsigned long flags; local_irq_save(flags); @@ -93,11 +89,12 @@ void locomolcd_power(int on) } /* read comadj */ -#ifdef CONFIG_MACH_POODLE - comadj = 118; -#else - comadj = 128; -#endif + if (comadj == -1) { + if (machine_is_poodle()) + comadj = 118; + if (machine_is_collie()) + comadj = 128; + } if (on) locomolcd_on(comadj); -- cgit v1.2.3-59-g8ed1b From 276ad0c109e69a32b634f0550d096f9381135b7d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 25 Mar 2006 03:07:35 -0800 Subject: [PATCH] tpm: sparc32 build fix In file included from drivers/char/tpm/tpm_nsc.c:23: drivers/char/tpm/tpm.h: In function `tpm_read_index': drivers/char/tpm/tpm.h:92: warning: implicit declaration of function `outb' drivers/char/tpm/tpm.h:93: warning: implicit declaration of function `inb' Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tpm/tpm.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index fd3a4beaa53d..dec0224b4478 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -24,6 +24,7 @@ #include #include #include +#include enum tpm_timeout { TPM_TIMEOUT = 5, /* msecs */ -- cgit v1.2.3-59-g8ed1b From 4cae59d2e85c1ee2ab1ee284db1945c5394cd965 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 25 Mar 2006 03:07:35 -0800 Subject: [PATCH] ads7846 build fix sparc32: drivers/input/touchscreen/ads7846.c: In function `ads7846_read12_ser': drivers/input/touchscreen/ads7846.c:206: warning: implicit declaration of function `disable_irq' drivers/input/touchscreen/ads7846.c:208: warning: implicit declaration of function `enable_irq' Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/touchscreen/ads7846.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 8c12a974b411..a81f987978c8 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef CONFIG_ARM #include -- cgit v1.2.3-59-g8ed1b From 340e48e662dc9bf79cdd9dc755cb2eb2bad580cd Mon Sep 17 00:00:00 2001 From: Zdenek Pavlas Date: Sat, 25 Mar 2006 03:07:49 -0800 Subject: [PATCH] BLK_DEV_INITRD: do not require BLK_DEV_RAM=y Initramfs initrd images do not need a ramdisk device, so remove this restriction in Kconfig. BLK_DEV_RAM=n saves about 13k on i386. Also without ramdisk device there's no need for "dry run", so initramfs unpacks much faster. People using cramfs, squashfs, or gzipped ext2/minix initrd images are probably smart enough not to turn off ramdisk support by accident. Cc: Al Viro Cc: Christoph Hellwig Cc: "H. Peter Anvin" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/Kconfig | 1 - init/initramfs.c | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 8b1331677407..e57ac5a43246 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -401,7 +401,6 @@ config BLK_DEV_RAM_SIZE config BLK_DEV_INITRD bool "Initial RAM disk (initrd) support" - depends on BLK_DEV_RAM=y help The initial RAM disk is a RAM disk that is loaded by the boot loader (loadlin or lilo) and that is mounted as root before the normal boot diff --git a/init/initramfs.c b/init/initramfs.c index 637344b05981..77b934cccefe 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -506,6 +506,7 @@ void __init populate_rootfs(void) panic(err); #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) { +#ifdef CONFIG_BLK_DEV_RAM int fd; printk(KERN_INFO "checking if image is initramfs..."); err = unpack_to_rootfs((char *)initrd_start, @@ -525,6 +526,15 @@ void __init populate_rootfs(void) sys_close(fd); free_initrd(); } +#else + printk(KERN_INFO "Unpacking initramfs..."); + err = unpack_to_rootfs((char *)initrd_start, + initrd_end - initrd_start, 0); + if (err) + panic(err); + printk(" done\n"); + free_initrd(); +#endif } #endif } -- cgit v1.2.3-59-g8ed1b From 7e3176555003a45318010d9820eb5ad1abb596bf Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 25 Mar 2006 03:07:51 -0800 Subject: [PATCH] md/bitmap.c:bitmap_mask_state(): fix inconsequent NULL checking We dereference bitmap both one line above and one line below this check rendering this check quite useless. Spotted by the Coverity checker. Signed-off-by: Adrian Bunk Cc: Alasdair G Kergon Cc: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index eae4473eadde..670eb01a5a23 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -556,7 +556,7 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits, unsigned long flags; spin_lock_irqsave(&bitmap->lock, flags); - if (!bitmap || !bitmap->sb_page) { /* can't set the state */ + if (!bitmap->sb_page) { /* can't set the state */ spin_unlock_irqrestore(&bitmap->lock, flags); return; } -- cgit v1.2.3-59-g8ed1b From 5c98d29ae4d8cb0e2ce78b82b2c1957bcfd7dbd3 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 25 Mar 2006 03:07:52 -0800 Subject: [PATCH] drivers/char/ipmi/ipmi_msghandler.c: fix a memory leak The Coverity checker found this memory leak. Signed-off-by: Adrian Bunk Acked-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index d745004281d0..abd4c5118a1b 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -736,7 +736,8 @@ int ipmi_create_user(unsigned int if_num, intf = ipmi_interfaces[if_num]; if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) { spin_unlock_irqrestore(&interfaces_lock, flags); - return -EINVAL; + rv = -EINVAL; + goto out_kfree; } /* Note that each existing user holds a refcount to the interface. */ @@ -751,14 +752,14 @@ int ipmi_create_user(unsigned int if_num, if (!try_module_get(intf->handlers->owner)) { rv = -ENODEV; - goto out_err; + goto out_kref; } if (intf->handlers->inc_usecount) { rv = intf->handlers->inc_usecount(intf->send_info); if (rv) { module_put(intf->handlers->owner); - goto out_err; + goto out_kref; } } @@ -769,9 +770,10 @@ int ipmi_create_user(unsigned int if_num, *user = new_user; return 0; - out_err: - kfree(new_user); +out_kref: kref_put(&intf->refcount, intf_free); +out_kfree: + kfree(new_user); return rv; } -- cgit v1.2.3-59-g8ed1b From 30087baf8810cd96b0ca2858993f29a89965ffff Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Sat, 25 Mar 2006 03:08:03 -0800 Subject: [PATCH] i2o_dump_hrt() output cleanup This patch fixes i2o_dump_hrt output from dmesg: iop0: HRT has 1 entries of 16 bytes each. Adapter 00000012: <7>TID 0000:[<7>H<7>P<7>C<7>*<7>]:<7>PCI 1: Bus 1 Device 22 Function 0<7> Signed-off-by: Vasily Averin Cc: Markus Lidel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/i2o/debug.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c index 40d4ea898dbc..5a6cca8e8c45 100644 --- a/drivers/message/i2o/debug.c +++ b/drivers/message/i2o/debug.c @@ -419,58 +419,53 @@ void i2o_dump_hrt(struct i2o_controller *c) d = (u8 *) (rows + 2); state = p[1] << 8 | p[0]; - printk(KERN_DEBUG "TID %04X:[", state & 0xFFF); + printk("TID %04X:[", state & 0xFFF); state >>= 12; if (state & (1 << 0)) - printk(KERN_DEBUG "H"); /* Hidden */ + printk("H"); /* Hidden */ if (state & (1 << 2)) { - printk(KERN_DEBUG "P"); /* Present */ + printk("P"); /* Present */ if (state & (1 << 1)) - printk(KERN_DEBUG "C"); /* Controlled */ + printk("C"); /* Controlled */ } if (state > 9) - printk(KERN_DEBUG "*"); /* Hard */ + printk("*"); /* Hard */ - printk(KERN_DEBUG "]:"); + printk("]:"); switch (p[3] & 0xFFFF) { case 0: /* Adapter private bus - easy */ - printk(KERN_DEBUG - "Local bus %d: I/O at 0x%04X Mem 0x%08X", p[2], + printk("Local bus %d: I/O at 0x%04X Mem 0x%08X", p[2], d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 1: /* ISA bus */ - printk(KERN_DEBUG - "ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", p[2], + printk("ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", p[2], d[2], d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 2: /* EISA bus */ - printk(KERN_DEBUG - "EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X", + printk("EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 3: /* MCA bus */ - printk(KERN_DEBUG - "MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2], + printk("MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 4: /* PCI bus */ - printk(KERN_DEBUG - "PCI %d: Bus %d Device %d Function %d", p[2], + printk("PCI %d: Bus %d Device %d Function %d", p[2], d[2], d[1], d[0]); break; case 0x80: /* Other */ default: - printk(KERN_DEBUG "Unsupported bus type."); + printk("Unsupported bus type."); break; } - printk(KERN_DEBUG "\n"); + printk("\n"); rows += length; } } -- cgit v1.2.3-59-g8ed1b From 1f4d4a80fbcb1e09cfb95660bcd2b677ea6d04c1 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 25 Mar 2006 03:08:06 -0800 Subject: [PATCH] i4l/isdn_tty.c: fix a check-after-use Fix a check-after-use spotted by the Coverity checker. Signed-off-by: Adrian Bunk Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/i4l/isdn_tty.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index aeaa1db74bd8..3585fb1f3344 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -2345,12 +2345,15 @@ isdn_tty_at_cout(char *msg, modem_info * info) u_long flags; struct sk_buff *skb = NULL; char *sp = NULL; - int l = strlen(msg); + int l; if (!msg) { printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n"); return; } + + l = strlen(msg); + spin_lock_irqsave(&info->readlock, flags); tty = info->tty; if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) { -- cgit v1.2.3-59-g8ed1b From 64b91379439ff0fb007bde90eb496299c14a9b2a Mon Sep 17 00:00:00 2001 From: Pat Gefre Date: Sat, 25 Mar 2006 03:08:07 -0800 Subject: [PATCH] Altix: rs422 support for ioc4 serial driver Add rs422 support to the Altix ioc4 serial driver. Signed-off-by: Patrick Gefre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/ioc4_serial.c | 387 ++++++++++++++++++++++++++++--------------- 1 file changed, 249 insertions(+), 138 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index a37579ce6d76..c620209d7b9a 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.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. */ @@ -323,9 +323,12 @@ static unsigned int Num_of_ioc4_cards; #define IOC4_FIFO_CHARS 255 /* Device name we're using */ -#define DEVICE_NAME "ttyIOC" -#define DEVICE_MAJOR 204 -#define DEVICE_MINOR 50 +#define DEVICE_NAME_RS232 "ttyIOC" +#define DEVICE_NAME_RS422 "ttyAIOC" +#define DEVICE_MAJOR 204 +#define DEVICE_MINOR_RS232 50 +#define DEVICE_MINOR_RS422 84 + /* register offsets */ #define IOC4_SERIAL_OFFSET 0x300 @@ -341,10 +344,8 @@ static unsigned int Num_of_ioc4_cards; #define MAX_BAUD_SUPPORTED 115200 /* protocol types supported */ -enum sio_proto { - PROTO_RS232, - PROTO_RS422 -}; +#define PROTO_RS232 3 +#define PROTO_RS422 7 /* Notification types */ #define N_DATA_READY 0x01 @@ -395,11 +396,17 @@ enum sio_proto { /* * This is the entry saved by the driver - one per card */ + +#define UART_PORT_MIN 0 +#define UART_PORT_RS232 UART_PORT_MIN +#define UART_PORT_RS422 1 +#define UART_PORT_COUNT 2 /* one for each mode */ + struct ioc4_control { int ic_irq; struct { - /* uart ports are allocated here */ - struct uart_port icp_uart_port; + /* uart ports are allocated here - 1 for rs232, 1 for rs422 */ + struct uart_port icp_uart_port[UART_PORT_COUNT]; /* Handy reference material */ struct ioc4_port *icp_port; } ic_port[IOC4_NUM_SERIAL_PORTS]; @@ -443,7 +450,9 @@ struct ioc4_soft { /* Local port info for each IOC4 serial ports */ struct ioc4_port { - struct uart_port *ip_port; + struct uart_port *ip_port; /* current active port ptr */ + /* Ptrs for all ports */ + struct uart_port *ip_all_ports[UART_PORT_COUNT]; /* Back ptrs for this port */ struct ioc4_control *ip_control; struct pci_dev *ip_pdev; @@ -502,6 +511,9 @@ struct ioc4_port { #define DCD_ON 0x02 #define LOWAT_WRITTEN 0x04 #define READ_ABORTED 0x08 +#define PORT_ACTIVE 0x10 +#define PORT_INACTIVE 0 /* This is the value when "off" */ + /* Since each port has different register offsets and bitmasks * for everything, we'll store those that we need in tables so we @@ -623,6 +635,23 @@ struct ring_buffer { static void receive_chars(struct uart_port *); static void handle_intr(void *arg, uint32_t sio_ir); +/* + * port_is_active - determines if this port is currently active + * @port: ptr to soft struct for this port + * @uart_port: uart port to test for + */ +static inline int port_is_active(struct ioc4_port *port, + struct uart_port *uart_port) +{ + if (port) { + if ((port->ip_flags & PORT_ACTIVE) + && (port->ip_port == uart_port)) + return 1; + } + return 0; +} + + /** * write_ireg - write the interrupt regs * @ioc4_soft: ptr to soft struct for this port @@ -708,19 +737,33 @@ static int set_baud(struct ioc4_port *port, int baud) /** * get_ioc4_port - given a uart port, return the control structure * @port: uart port + * @set: set this port as current */ -static struct ioc4_port *get_ioc4_port(struct uart_port *the_port) +static struct ioc4_port *get_ioc4_port(struct uart_port *the_port, int set) { struct ioc4_driver_data *idd = dev_get_drvdata(the_port->dev); struct ioc4_control *control = idd->idd_serial_data; - int ii; + struct ioc4_port *port; + int port_num, port_type; if (control) { - for ( ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++ ) { - if (!control->ic_port[ii].icp_port) + for ( port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; + port_num++ ) { + port = control->ic_port[port_num].icp_port; + if (!port) continue; - if (the_port == control->ic_port[ii].icp_port->ip_port) - return control->ic_port[ii].icp_port; + for (port_type = UART_PORT_MIN; + port_type < UART_PORT_COUNT; + port_type++) { + if (the_port == port->ip_all_ports + [port_type]) { + /* set local copy */ + if (set) { + port->ip_port = the_port; + } + return port; + } + } } } return NULL; @@ -946,6 +989,7 @@ intr_connect(struct ioc4_soft *soft, int type, * @arg: handler arg * @regs: registers */ + static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) { struct ioc4_soft *soft; @@ -953,7 +997,7 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) int xx, num_intrs = 0; int intr_type; int handled = 0; - struct ioc4_intr_info *ii; + struct ioc4_intr_info *intr_info; soft = arg; for (intr_type = 0; intr_type < IOC4_NUM_INTR_TYPES; intr_type++) { @@ -966,13 +1010,13 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) * which interrupt bits are set. */ for (xx = 0; xx < num_intrs; xx++) { - ii = &soft->is_intr_type[intr_type].is_intr_info[xx]; - if ((this_mir = this_ir & ii->sd_bits)) { + intr_info = &soft->is_intr_type[intr_type].is_intr_info[xx]; + if ((this_mir = this_ir & intr_info->sd_bits)) { /* Disable owned interrupts, call handler */ handled++; - write_ireg(soft, ii->sd_bits, IOC4_W_IEC, + write_ireg(soft, intr_info->sd_bits, IOC4_W_IEC, intr_type); - ii->sd_intr(ii->sd_info, this_mir); + intr_info->sd_intr(intr_info->sd_info, this_mir); this_ir &= ~this_mir; } } @@ -980,7 +1024,6 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) #ifdef DEBUG_INTERRUPTS { struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr; - spinlock_t *lp = &soft->is_ir_lock; unsigned long flag; spin_lock_irqsave(&soft->is_ir_lock, flag); @@ -1177,7 +1220,7 @@ static inline int local_open(struct ioc4_port *port) { int spiniter = 0; - port->ip_flags = 0; + port->ip_flags = PORT_ACTIVE; /* Pause the DMA interface if necessary */ if (port->ip_sscr & IOC4_SSCR_DMA_EN) { @@ -1187,6 +1230,7 @@ static inline int local_open(struct ioc4_port *port) & IOC4_SSCR_PAUSE_STATE) == 0) { spiniter++; if (spiniter > MAXITER) { + port->ip_flags = PORT_INACTIVE; return -1; } } @@ -1506,14 +1550,13 @@ static int set_notification(struct ioc4_port *port, int mask, int set_on) /** * set_mcr - set the master control reg * @the_port: port to use - * @set: set ? * @mask1: mcr mask * @mask2: shadow mask */ -static inline int set_mcr(struct uart_port *the_port, int set, +static inline int set_mcr(struct uart_port *the_port, int mask1, int mask2) { - struct ioc4_port *port = get_ioc4_port(the_port); + struct ioc4_port *port = get_ioc4_port(the_port, 0); uint32_t shadow; int spiniter = 0; char mcr; @@ -1536,13 +1579,9 @@ static inline int set_mcr(struct uart_port *the_port, int set, mcr = (shadow & 0xff000000) >> 24; /* Set new value */ - if (set) { - mcr |= mask1; - shadow |= mask2; - } else { - mcr &= ~mask1; - shadow &= ~mask2; - } + mcr |= mask1; + shadow |= mask2; + writeb(mcr, &port->ip_uart_regs->i4u_mcr); writel(shadow, &port->ip_serial_regs->shadow); @@ -1558,7 +1597,7 @@ static inline int set_mcr(struct uart_port *the_port, int set, * @port: port to use * @proto: protocol to use */ -static int ioc4_set_proto(struct ioc4_port *port, enum sio_proto proto) +static int ioc4_set_proto(struct ioc4_port *port, int proto) { struct hooks *hooks = port->ip_hooks; @@ -1589,7 +1628,7 @@ static void transmit_chars(struct uart_port *the_port) int result; char *start; struct tty_struct *tty; - struct ioc4_port *port = get_ioc4_port(the_port); + struct ioc4_port *port = get_ioc4_port(the_port, 0); struct uart_info *info; if (!the_port) @@ -1645,7 +1684,7 @@ static void ioc4_change_speed(struct uart_port *the_port, struct termios *new_termios, struct termios *old_termios) { - struct ioc4_port *port = get_ioc4_port(the_port); + struct ioc4_port *port = get_ioc4_port(the_port, 0); int baud, bits; unsigned cflag; int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; @@ -1752,7 +1791,7 @@ static inline int ic4_startup_local(struct uart_port *the_port) if (!the_port) return -1; - port = get_ioc4_port(the_port); + port = get_ioc4_port(the_port, 0); if (!port) return -1; @@ -1760,6 +1799,9 @@ static inline int ic4_startup_local(struct uart_port *the_port) local_open(port); + /* set the protocol - mapbase has the port type */ + ioc4_set_proto(port, the_port->mapbase); + /* set the speed of the serial port */ ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0); @@ -1768,17 +1810,17 @@ static inline int ic4_startup_local(struct uart_port *the_port) /* * ioc4_cb_output_lowat - called when the output low water mark is hit - * @port: port to output + * @the_port: port to output */ -static void ioc4_cb_output_lowat(struct ioc4_port *port) +static void ioc4_cb_output_lowat(struct uart_port *the_port) { unsigned long pflags; /* ip_lock is set on the call here */ - if (port->ip_port) { - spin_lock_irqsave(&port->ip_port->lock, pflags); - transmit_chars(port->ip_port); - spin_unlock_irqrestore(&port->ip_port->lock, pflags); + if (the_port) { + spin_lock_irqsave(&the_port->lock, pflags); + transmit_chars(the_port); + spin_unlock_irqrestore(&the_port->lock, pflags); } } @@ -1923,7 +1965,7 @@ static void handle_intr(void *arg, uint32_t sio_ir) &port->ip_mem->sio_ir.raw); if (port->ip_notify & N_OUTPUT_LOWAT) - ioc4_cb_output_lowat(port); + ioc4_cb_output_lowat(port->ip_port); } /* Handle tx_mt. Must come after tx_explicit. */ @@ -1936,7 +1978,7 @@ static void handle_intr(void *arg, uint32_t sio_ir) * So send the notification now. */ if (port->ip_notify & N_OUTPUT_LOWAT) { - ioc4_cb_output_lowat(port); + ioc4_cb_output_lowat(port->ip_port); /* We need to reload the sio_ir since the lowat * call may have caused another write to occur, @@ -2023,7 +2065,7 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf, int len) { int prod_ptr, cons_ptr, total; - struct ioc4_port *port = get_ioc4_port(the_port); + struct ioc4_port *port = get_ioc4_port(the_port, 0); struct ring *inring; struct ring_entry *entry; struct hooks *hooks = port->ip_hooks; @@ -2335,17 +2377,27 @@ static void receive_chars(struct uart_port *the_port) */ static const char *ic4_type(struct uart_port *the_port) { - return "SGI IOC4 Serial"; + if (the_port->mapbase == PROTO_RS232) + return "SGI IOC4 Serial [rs232]"; + else + return "SGI IOC4 Serial [rs422]"; } /** - * ic4_tx_empty - Is the transmitter empty? We pretend we're always empty - * @port: Port to operate on (we ignore since we always return 1) + * ic4_tx_empty - Is the transmitter empty? + * @port: Port to operate on * */ static unsigned int ic4_tx_empty(struct uart_port *the_port) { - return 1; + struct ioc4_port *port = get_ioc4_port(the_port, 0); + unsigned int ret = 0; + + if (port_is_active(port, the_port)) { + if (readl(&port->ip_serial_regs->shadow) & IOC4_SHADOW_TEMT) + ret = TIOCSER_TEMT; + } + return ret; } /** @@ -2355,6 +2407,10 @@ static unsigned int ic4_tx_empty(struct uart_port *the_port) */ static void ic4_stop_tx(struct uart_port *the_port) { + struct ioc4_port *port = get_ioc4_port(the_port, 0); + + if (port_is_active(port, the_port)) + set_notification(port, N_OUTPUT_LOWAT, 0); } /** @@ -2377,11 +2433,12 @@ static void ic4_shutdown(struct uart_port *the_port) struct ioc4_port *port; struct uart_info *info; - port = get_ioc4_port(the_port); + port = get_ioc4_port(the_port, 0); if (!port) return; info = the_port->info; + port->ip_port = NULL; wake_up_interruptible(&info->delta_msr_wait); @@ -2390,6 +2447,7 @@ static void ic4_shutdown(struct uart_port *the_port) spin_lock_irqsave(&the_port->lock, port_flags); set_notification(port, N_ALL, 0); + port->ip_flags = PORT_INACTIVE; spin_unlock_irqrestore(&the_port->lock, port_flags); } @@ -2402,6 +2460,11 @@ static void ic4_shutdown(struct uart_port *the_port) static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl) { unsigned char mcr = 0; + struct ioc4_port *port; + + port = get_ioc4_port(the_port, 0); + if (!port_is_active(port, the_port)) + return; if (mctrl & TIOCM_RTS) mcr |= UART_MCR_RTS; @@ -2414,7 +2477,7 @@ static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl) if (mctrl & TIOCM_LOOP) mcr |= UART_MCR_LOOP; - set_mcr(the_port, 1, mcr, IOC4_SHADOW_DTR); + set_mcr(the_port, mcr, IOC4_SHADOW_DTR); } /** @@ -2424,11 +2487,11 @@ static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl) */ static unsigned int ic4_get_mctrl(struct uart_port *the_port) { - struct ioc4_port *port = get_ioc4_port(the_port); + struct ioc4_port *port = get_ioc4_port(the_port, 0); uint32_t shadow; unsigned int ret = 0; - if (!port) + if (!port_is_active(port, the_port)) return 0; shadow = readl(&port->ip_serial_regs->shadow); @@ -2448,9 +2511,9 @@ static unsigned int ic4_get_mctrl(struct uart_port *the_port) */ static void ic4_start_tx(struct uart_port *the_port) { - struct ioc4_port *port = get_ioc4_port(the_port); + struct ioc4_port *port = get_ioc4_port(the_port, 0); - if (port) { + if (port_is_active(port, the_port)) { set_notification(port, N_OUTPUT_LOWAT, 1); enable_intrs(port, port->ip_hooks->intr_tx_mt); } @@ -2467,7 +2530,7 @@ static void ic4_break_ctl(struct uart_port *the_port, int break_state) } /** - * ic4_startup - Start up the serial port - always return 0 (We're always on) + * ic4_startup - Start up the serial port * @port: Port to operate on * */ @@ -2479,17 +2542,16 @@ static int ic4_startup(struct uart_port *the_port) struct uart_info *info; unsigned long port_flags; - if (!the_port) { + if (!the_port) return -ENODEV; - } - port = get_ioc4_port(the_port); - if (!port) { + port = get_ioc4_port(the_port, 1); + if (!port) return -ENODEV; - } info = the_port->info; control = port->ip_control; if (!control) { + port->ip_port = NULL; return -ENODEV; } @@ -2551,28 +2613,104 @@ static struct uart_ops ioc4_ops = { * Boot-time initialization code */ -static struct uart_driver ioc4_uart = { +static struct uart_driver ioc4_uart_rs232 = { .owner = THIS_MODULE, - .driver_name = "ioc4_serial", - .dev_name = DEVICE_NAME, + .driver_name = "ioc4_serial_rs232", + .dev_name = DEVICE_NAME_RS232, .major = DEVICE_MAJOR, - .minor = DEVICE_MINOR, + .minor = DEVICE_MINOR_RS232, .nr = IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS, }; +static struct uart_driver ioc4_uart_rs422 = { + .owner = THIS_MODULE, + .driver_name = "ioc4_serial_rs422", + .dev_name = DEVICE_NAME_RS422, + .major = DEVICE_MAJOR, + .minor = DEVICE_MINOR_RS422, + .nr = IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS, +}; + + /** - * ioc4_serial_core_attach - register with serial core + * ioc4_serial_remove_one - detach function + * + * @idd: IOC4 master module data for this IOC4 + */ + +static int ioc4_serial_remove_one(struct ioc4_driver_data *idd) +{ + int port_num, port_type; + struct ioc4_control *control; + struct uart_port *the_port; + struct ioc4_port *port; + struct ioc4_soft *soft; + + control = idd->idd_serial_data; + + for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) { + for (port_type = UART_PORT_MIN; + port_type < UART_PORT_COUNT; + port_type++) { + the_port = &control->ic_port[port_num].icp_uart_port + [port_type]; + if (the_port) { + switch (port_type) { + case UART_PORT_RS422: + uart_remove_one_port(&ioc4_uart_rs422, + the_port); + break; + default: + case UART_PORT_RS232: + uart_remove_one_port(&ioc4_uart_rs232, + the_port); + break; + } + } + } + port = control->ic_port[port_num].icp_port; + /* we allocate in pairs */ + if (!(port_num & 1) && port) { + pci_free_consistent(port->ip_pdev, + TOTAL_RING_BUF_SIZE, + port->ip_cpu_ringbuf, + port->ip_dma_ringbuf); + kfree(port); + } + } + soft = control->ic_soft; + if (soft) { + free_irq(control->ic_irq, soft); + if (soft->is_ioc4_serial_addr) { + release_region((unsigned long) + soft->is_ioc4_serial_addr, + sizeof(struct ioc4_serial)); + } + kfree(soft); + } + kfree(control); + idd->idd_serial_data = NULL; + + return 0; +} + + +/** + * ioc4_serial_core_attach_rs232 - register with serial core * This is done during pci probing * @pdev: handle for this card */ static inline int -ioc4_serial_core_attach(struct pci_dev *pdev) +ioc4_serial_core_attach(struct pci_dev *pdev, int port_type) { struct ioc4_port *port; struct uart_port *the_port; struct ioc4_driver_data *idd = pci_get_drvdata(pdev); struct ioc4_control *control = idd->idd_serial_data; - int ii; + int port_num; + int port_type_idx; + struct uart_driver *u_driver; + DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n", __FUNCTION__, pdev, (void *)control)); @@ -2580,28 +2718,36 @@ ioc4_serial_core_attach(struct pci_dev *pdev) if (!control) return -ENODEV; + port_type_idx = (port_type == PROTO_RS232) ? UART_PORT_RS232 + : UART_PORT_RS422; + + u_driver = (port_type == PROTO_RS232) ? &ioc4_uart_rs232 + : &ioc4_uart_rs422; + /* once around for each port on this card */ - for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) { - the_port = &control->ic_port[ii].icp_uart_port; - port = control->ic_port[ii].icp_port; - port->ip_port = the_port; + for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) { + the_port = &control->ic_port[port_num].icp_uart_port + [port_type_idx]; + port = control->ic_port[port_num].icp_port; + port->ip_all_ports[port_type_idx] = the_port; - DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p\n", + DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p : type %s\n", __FUNCTION__, (void *)the_port, - (void *)port)); + (void *)port, + port_type == PROTO_RS232 ? "rs232" : "rs422")); /* membase, iobase and mapbase just need to be non-0 */ the_port->membase = (unsigned char __iomem *)1; - the_port->iobase = (pdev->bus->number << 16) | ii; - the_port->line = (Num_of_ioc4_cards << 2) | ii; - the_port->mapbase = 1; + the_port->iobase = (pdev->bus->number << 16) | port_num; + the_port->line = (Num_of_ioc4_cards << 2) | port_num; + the_port->mapbase = port_type; the_port->type = PORT_16550A; the_port->fifosize = IOC4_FIFO_CHARS; the_port->ops = &ioc4_ops; the_port->irq = control->ic_irq; the_port->dev = &pdev->dev; spin_lock_init(&the_port->lock); - if (uart_add_one_port(&ioc4_uart, the_port) < 0) { + if (uart_add_one_port(u_driver, the_port) < 0) { printk(KERN_WARNING "%s: unable to add port %d bus %d\n", __FUNCTION__, the_port->line, pdev->bus->number); @@ -2610,8 +2756,6 @@ ioc4_serial_core_attach(struct pci_dev *pdev) ("IOC4 serial port %d irq = %d, bus %d\n", the_port->line, the_port->irq, pdev->bus->number)); } - /* all ports are rs232 for now */ - ioc4_set_proto(port, PROTO_RS232); } return 0; } @@ -2631,7 +2775,8 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) int ret = 0; - DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, idd->idd_pci_id)); + DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, + idd->idd_pci_id)); /* request serial registers */ tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET; @@ -2653,11 +2798,11 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) goto out2; } DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n", - __FUNCTION__, (void *)idd->idd_misc_regs, (void *)serial)); + __FUNCTION__, (void *)idd->idd_misc_regs, + (void *)serial)); /* Get memory for the new card */ - control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS, - GFP_KERNEL); + control = kmalloc(sizeof(struct ioc4_control), GFP_KERNEL); if (!control) { printk(KERN_WARNING "ioc4_attach_one" @@ -2702,7 +2847,7 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) /* Hook up interrupt handler */ if (!request_irq(idd->idd_pdev->irq, ioc4_intr, SA_SHIRQ, - "sgi-ioc4serial", (void *)soft)) { + "sgi-ioc4serial", soft)) { control->ic_irq = idd->idd_pdev->irq; } else { printk(KERN_WARNING @@ -2713,16 +2858,21 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) if (ret) goto out4; - /* register port with the serial core */ + /* register port with the serial core - 1 rs232, 1 rs422 */ - if ((ret = ioc4_serial_core_attach(idd->idd_pdev))) + if ((ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS232))) goto out4; + if ((ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS422))) + goto out5; + Num_of_ioc4_cards++; return ret; /* error exits that give back resources */ +out5: + ioc4_serial_remove_one(idd); out4: kfree(soft); out3: @@ -2735,52 +2885,6 @@ out1: } -/** - * ioc4_serial_remove_one - detach function - * - * @idd: IOC4 master module data for this IOC4 - */ - -int ioc4_serial_remove_one(struct ioc4_driver_data *idd) -{ - int ii; - struct ioc4_control *control; - struct uart_port *the_port; - struct ioc4_port *port; - struct ioc4_soft *soft; - - control = idd->idd_serial_data; - - for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) { - the_port = &control->ic_port[ii].icp_uart_port; - if (the_port) { - uart_remove_one_port(&ioc4_uart, the_port); - } - port = control->ic_port[ii].icp_port; - if (!(ii & 1) && port) { - pci_free_consistent(port->ip_pdev, - TOTAL_RING_BUF_SIZE, - (void *)port->ip_cpu_ringbuf, - port->ip_dma_ringbuf); - kfree(port); - } - } - soft = control->ic_soft; - if (soft) { - free_irq(control->ic_irq, (void *)soft); - if (soft->is_ioc4_serial_addr) { - release_region((unsigned long) - soft->is_ioc4_serial_addr, - sizeof(struct ioc4_serial)); - } - kfree(soft); - } - kfree(control); - idd->idd_serial_data = NULL; - - return 0; -} - static struct ioc4_submodule ioc4_serial_submodule = { .is_name = "IOC4_serial", .is_owner = THIS_MODULE, @@ -2796,9 +2900,15 @@ int ioc4_serial_init(void) int ret; /* register with serial core */ - if ((ret = uart_register_driver(&ioc4_uart)) < 0) { + if ((ret = uart_register_driver(&ioc4_uart_rs232)) < 0) { + printk(KERN_WARNING + "%s: Couldn't register rs232 IOC4 serial driver\n", + __FUNCTION__); + return ret; + } + if ((ret = uart_register_driver(&ioc4_uart_rs422)) < 0) { printk(KERN_WARNING - "%s: Couldn't register IOC4 serial driver\n", + "%s: Couldn't register rs422 IOC4 serial driver\n", __FUNCTION__); return ret; } @@ -2810,7 +2920,8 @@ int ioc4_serial_init(void) static void __devexit ioc4_serial_exit(void) { ioc4_unregister_submodule(&ioc4_serial_submodule); - uart_unregister_driver(&ioc4_uart); + uart_unregister_driver(&ioc4_uart_rs232); + uart_unregister_driver(&ioc4_uart_rs422); } module_init(ioc4_serial_init); -- cgit v1.2.3-59-g8ed1b From 656bde5728b824ca23fcab8bc5800b309ea48d64 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 25 Mar 2006 03:08:12 -0800 Subject: [PATCH] Fix memory leak in isapnp Spotted by the Coverity checker as bug #666 akpm; there are several other `return 1;'s in there which aren't freeing `dev'. (A fix which converts this function to single-exit would be preferred..) Signed-off-by: Jesper Juhl Cc: Adam Belay Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pnp/isapnp/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 57fd60314d59..b1b4b683cbdd 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -646,8 +646,10 @@ static int __init isapnp_create_device(struct pnp_card *card, size = 0; skip = 0; option = pnp_register_independent_option(dev); - if (!option) + if (!option) { + kfree(dev); return 1; + } pnp_add_card_device(card,dev); } else { skip = 1; -- cgit v1.2.3-59-g8ed1b From 34f361ade2fb4a869f6a7714d01c04ce4cfa75d9 Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Sat, 25 Mar 2006 03:08:18 -0800 Subject: [PATCH] Check if cpu can be onlined before calling smp_prepare_cpu() - Moved check for online cpu out of smp_prepare_cpu() - Moved default declaration of smp_prepare_cpu() to kernel/cpu.c - Removed lock_cpu_hotplug() from smp_prepare_cpu() to around it, since its called from cpu_up() as well now. - Removed clearing from cpu_present_map during cpu_offline as it breaks using cpu_up() directly during a subsequent online operation. Signed-off-by: Ashok Raj Cc: Srivatsa Vaddagiri Cc: "Li, Shaohua" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/smpboot.c | 33 ++++++++++++++++++--------------- drivers/base/cpu.c | 9 +-------- include/linux/cpu.h | 1 - kernel/power/smp.c | 4 +--- 4 files changed, 20 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 4c470e99a742..82371d83bfa9 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1003,7 +1003,6 @@ void cpu_exit_clear(void) cpu_clear(cpu, cpu_callout_map); cpu_clear(cpu, cpu_callin_map); - cpu_clear(cpu, cpu_present_map); cpu_clear(cpu, smp_commenced_mask); unmap_cpu_to_logical_apicid(cpu); @@ -1015,31 +1014,20 @@ struct warm_boot_cpu_info { int cpu; }; -static void __devinit do_warm_boot_cpu(void *p) +static void __cpuinit do_warm_boot_cpu(void *p) { struct warm_boot_cpu_info *info = p; do_boot_cpu(info->apicid, info->cpu); complete(info->complete); } -int __devinit smp_prepare_cpu(int cpu) +static int __cpuinit __smp_prepare_cpu(int cpu) { DECLARE_COMPLETION(done); struct warm_boot_cpu_info info; struct work_struct task; int apicid, ret; - lock_cpu_hotplug(); - - /* - * On x86, CPU0 is never offlined. Trying to bring up an - * already-booted CPU will hang. So check for that case. - */ - if (cpu_online(cpu)) { - ret = -EINVAL; - goto exit; - } - apicid = x86_cpu_to_apicid[cpu]; if (apicid == BAD_APICID) { ret = -ENODEV; @@ -1064,7 +1052,6 @@ int __devinit smp_prepare_cpu(int cpu) zap_low_mappings(); ret = 0; exit: - unlock_cpu_hotplug(); return ret; } #endif @@ -1392,6 +1379,22 @@ void __cpu_die(unsigned int cpu) int __devinit __cpu_up(unsigned int cpu) { +#ifdef CONFIG_HOTPLUG_CPU + int ret=0; + + /* + * We do warm boot only on cpus that had booted earlier + * Otherwise cold boot is all handled from smp_boot_cpus(). + * cpu_callin_map is set during AP kickstart process. Its reset + * when a cpu is taken offline from cpu_exit_clear(). + */ + if (!cpu_isset(cpu, cpu_callin_map)) + ret = __smp_prepare_cpu(cpu); + + if (ret) + return -EIO; +#endif + /* In case one didn't come up */ if (!cpu_isset(cpu, cpu_callin_map)) { printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu); diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 29f3d7504da1..dd712b24ec91 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -19,11 +19,6 @@ EXPORT_SYMBOL(cpu_sysdev_class); static struct sys_device *cpu_sys_devices[NR_CPUS]; #ifdef CONFIG_HOTPLUG_CPU -int __attribute__((weak)) smp_prepare_cpu (int cpu) -{ - return 0; -} - static ssize_t show_online(struct sys_device *dev, char *buf) { struct cpu *cpu = container_of(dev, struct cpu, sysdev); @@ -44,9 +39,7 @@ static ssize_t store_online(struct sys_device *dev, const char *buf, kobject_uevent(&dev->kobj, KOBJ_OFFLINE); break; case '1': - ret = smp_prepare_cpu(cpu->sysdev.id); - if (!ret) - ret = cpu_up(cpu->sysdev.id); + ret = cpu_up(cpu->sysdev.id); if (!ret) kobject_uevent(&dev->kobj, KOBJ_ONLINE); break; diff --git a/include/linux/cpu.h b/include/linux/cpu.h index d612b89dce33..08d50c53aab4 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -74,7 +74,6 @@ extern int lock_cpu_hotplug_interruptible(void); register_cpu_notifier(&fn##_nb); \ } int cpu_down(unsigned int cpu); -extern int __attribute__((weak)) smp_prepare_cpu(int cpu); #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu)) #else #define lock_cpu_hotplug() do { } while (0) diff --git a/kernel/power/smp.c b/kernel/power/smp.c index 911fc62b8225..5957312b2d68 100644 --- a/kernel/power/smp.c +++ b/kernel/power/smp.c @@ -49,9 +49,7 @@ void enable_nonboot_cpus(void) printk("Thawing cpus ...\n"); for_each_cpu_mask(cpu, frozen_cpus) { - error = smp_prepare_cpu(cpu); - if (!error) - error = cpu_up(cpu); + error = cpu_up(cpu); if (!error) { printk("CPU%d is up\n", cpu); continue; -- cgit v1.2.3-59-g8ed1b From 1e0a91ad52c741d09288450674fc7c7f1695200a Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 25 Mar 2006 03:08:19 -0800 Subject: [PATCH] EISA: Ignore generated file drivers/eisa/devlist.h Signed-off-by: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/eisa/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 drivers/eisa/.gitignore (limited to 'drivers') diff --git a/drivers/eisa/.gitignore b/drivers/eisa/.gitignore new file mode 100644 index 000000000000..4b335c0aedb0 --- /dev/null +++ b/drivers/eisa/.gitignore @@ -0,0 +1 @@ +devlist.h -- cgit v1.2.3-59-g8ed1b From a30ff2e348af9d3a1782103130c88960550a773f Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Sat, 25 Mar 2006 03:08:26 -0800 Subject: [PATCH] serial: mpsc driver passes bad devname to request_irq() The devname passed to request_irq() contained a '/' which is wrong. At a minimum, the '/' prevented the devname from showing up in /proc/irq//. This patch replaces the '/' with a '-' to fixes that problem. Reported-by: Stephane Chazelas Signed-off-by: Mark A. Greer Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/mpsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index 0ca83ac31d07..ba30e2363cc0 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -1165,7 +1165,7 @@ mpsc_startup(struct uart_port *port) flag = SA_SHIRQ; if (request_irq(pi->port.irq, mpsc_sdma_intr, flag, - "mpsc/sdma", pi)) + "mpsc-sdma", pi)) printk(KERN_ERR "MPSC: Can't get SDMA IRQ %d\n", pi->port.irq); -- cgit v1.2.3-59-g8ed1b From 6261c8e34f07f09270b37e14c05962c952cbeebe Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Sat, 25 Mar 2006 03:08:27 -0800 Subject: [PATCH] serial: mpsc driver has definition of SUPPORT_SYSRQ below include of serial_core.h The definition of SUPPORT_SYSRQ must come before #include of serial_core.h. This patch moves the definition of SUPPORT_SYSRQ to be just after the #include of config.h to make it consistent with 8250.c. Reported-by: Stephane Chazelas Signed-off-by: Mark A. Greer Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/mpsc.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/mpsc.h b/drivers/serial/mpsc.h index 678dbcf06c8f..15913300cea7 100644 --- a/drivers/serial/mpsc.h +++ b/drivers/serial/mpsc.h @@ -13,6 +13,11 @@ #define __MPSC_H__ #include + +#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include #include #include @@ -31,10 +36,6 @@ #include #include -#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #define MPSC_NUM_CTLRS 2 /* -- cgit v1.2.3-59-g8ed1b From e4294b3ecd1da9abeb66709c89f71b1ba888b3b1 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Sat, 25 Mar 2006 03:08:28 -0800 Subject: [PATCH] serial: merge mpsc.h into mpsc.c Merge mpsc.h into mpsc.c because its the only file that #include's mpsc.h. Signed-off-by: Mark A. Greer Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/mpsc.c | 258 +++++++++++++++++++++++++++++++++++++++++++- drivers/serial/mpsc.h | 290 -------------------------------------------------- 2 files changed, 255 insertions(+), 293 deletions(-) delete mode 100644 drivers/serial/mpsc.h (limited to 'drivers') diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index ba30e2363cc0..94681922ea0a 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -1,6 +1,4 @@ /* - * drivers/serial/mpsc.c - * * Generic driver for the MPSC (UART mode) on Marvell parts (e.g., GT64240, * GT64260, MV64340, MV64360, GT96100, ... ). * @@ -52,9 +50,263 @@ * 4) AFAICT, hardware flow control isn't supported by the controller --MAG. */ +#include + +#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include "mpsc.h" +#include +#include + +#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#define MPSC_NUM_CTLRS 2 + +/* + * Descriptors and buffers must be cache line aligned. + * Buffers lengths must be multiple of cache line size. + * Number of Tx & Rx descriptors must be powers of 2. + */ +#define MPSC_RXR_ENTRIES 32 +#define MPSC_RXRE_SIZE dma_get_cache_alignment() +#define MPSC_RXR_SIZE (MPSC_RXR_ENTRIES * MPSC_RXRE_SIZE) +#define MPSC_RXBE_SIZE dma_get_cache_alignment() +#define MPSC_RXB_SIZE (MPSC_RXR_ENTRIES * MPSC_RXBE_SIZE) + +#define MPSC_TXR_ENTRIES 32 +#define MPSC_TXRE_SIZE dma_get_cache_alignment() +#define MPSC_TXR_SIZE (MPSC_TXR_ENTRIES * MPSC_TXRE_SIZE) +#define MPSC_TXBE_SIZE dma_get_cache_alignment() +#define MPSC_TXB_SIZE (MPSC_TXR_ENTRIES * MPSC_TXBE_SIZE) + +#define MPSC_DMA_ALLOC_SIZE (MPSC_RXR_SIZE + MPSC_RXB_SIZE + \ + MPSC_TXR_SIZE + MPSC_TXB_SIZE + \ + dma_get_cache_alignment() /* for alignment */) + +/* Rx and Tx Ring entry descriptors -- assume entry size is <= cacheline size */ +struct mpsc_rx_desc { + u16 bufsize; + u16 bytecnt; + u32 cmdstat; + u32 link; + u32 buf_ptr; +} __attribute((packed)); + +struct mpsc_tx_desc { + u16 bytecnt; + u16 shadow; + u32 cmdstat; + u32 link; + u32 buf_ptr; +} __attribute((packed)); + +/* + * Some regs that have the erratum that you can't read them are are shared + * between the two MPSC controllers. This struct contains those shared regs. + */ +struct mpsc_shared_regs { + phys_addr_t mpsc_routing_base_p; + phys_addr_t sdma_intr_base_p; + + void __iomem *mpsc_routing_base; + void __iomem *sdma_intr_base; + + u32 MPSC_MRR_m; + u32 MPSC_RCRR_m; + u32 MPSC_TCRR_m; + u32 SDMA_INTR_CAUSE_m; + u32 SDMA_INTR_MASK_m; +}; + +/* The main driver data structure */ +struct mpsc_port_info { + struct uart_port port; /* Overlay uart_port structure */ + + /* Internal driver state for this ctlr */ + u8 ready; + u8 rcv_data; + tcflag_t c_iflag; /* save termios->c_iflag */ + tcflag_t c_cflag; /* save termios->c_cflag */ + + /* Info passed in from platform */ + u8 mirror_regs; /* Need to mirror regs? */ + u8 cache_mgmt; /* Need manual cache mgmt? */ + u8 brg_can_tune; /* BRG has baud tuning? */ + u32 brg_clk_src; + u16 mpsc_max_idle; + int default_baud; + int default_bits; + int default_parity; + int default_flow; + + /* Physical addresses of various blocks of registers (from platform) */ + phys_addr_t mpsc_base_p; + phys_addr_t sdma_base_p; + phys_addr_t brg_base_p; + + /* Virtual addresses of various blocks of registers (from platform) */ + void __iomem *mpsc_base; + void __iomem *sdma_base; + void __iomem *brg_base; + + /* Descriptor ring and buffer allocations */ + void *dma_region; + dma_addr_t dma_region_p; + + dma_addr_t rxr; /* Rx descriptor ring */ + dma_addr_t rxr_p; /* Phys addr of rxr */ + u8 *rxb; /* Rx Ring I/O buf */ + u8 *rxb_p; /* Phys addr of rxb */ + u32 rxr_posn; /* First desc w/ Rx data */ + + dma_addr_t txr; /* Tx descriptor ring */ + dma_addr_t txr_p; /* Phys addr of txr */ + u8 *txb; /* Tx Ring I/O buf */ + u8 *txb_p; /* Phys addr of txb */ + int txr_head; /* Where new data goes */ + int txr_tail; /* Where sent data comes off */ + + /* Mirrored values of regs we can't read (if 'mirror_regs' set) */ + u32 MPSC_MPCR_m; + u32 MPSC_CHR_1_m; + u32 MPSC_CHR_2_m; + u32 MPSC_CHR_10_m; + u32 BRG_BCR_m; + struct mpsc_shared_regs *shared_regs; +}; + +/* Hooks to platform-specific code */ +int mpsc_platform_register_driver(void); +void mpsc_platform_unregister_driver(void); + +/* Hooks back in to mpsc common to be called by platform-specific code */ +struct mpsc_port_info *mpsc_device_probe(int index); +struct mpsc_port_info *mpsc_device_remove(int index); + +/* Main MPSC Configuration Register Offsets */ +#define MPSC_MMCRL 0x0000 +#define MPSC_MMCRH 0x0004 +#define MPSC_MPCR 0x0008 +#define MPSC_CHR_1 0x000c +#define MPSC_CHR_2 0x0010 +#define MPSC_CHR_3 0x0014 +#define MPSC_CHR_4 0x0018 +#define MPSC_CHR_5 0x001c +#define MPSC_CHR_6 0x0020 +#define MPSC_CHR_7 0x0024 +#define MPSC_CHR_8 0x0028 +#define MPSC_CHR_9 0x002c +#define MPSC_CHR_10 0x0030 +#define MPSC_CHR_11 0x0034 + +#define MPSC_MPCR_FRZ (1 << 9) +#define MPSC_MPCR_CL_5 0 +#define MPSC_MPCR_CL_6 1 +#define MPSC_MPCR_CL_7 2 +#define MPSC_MPCR_CL_8 3 +#define MPSC_MPCR_SBL_1 0 +#define MPSC_MPCR_SBL_2 1 + +#define MPSC_CHR_2_TEV (1<<1) +#define MPSC_CHR_2_TA (1<<7) +#define MPSC_CHR_2_TTCS (1<<9) +#define MPSC_CHR_2_REV (1<<17) +#define MPSC_CHR_2_RA (1<<23) +#define MPSC_CHR_2_CRD (1<<25) +#define MPSC_CHR_2_EH (1<<31) +#define MPSC_CHR_2_PAR_ODD 0 +#define MPSC_CHR_2_PAR_SPACE 1 +#define MPSC_CHR_2_PAR_EVEN 2 +#define MPSC_CHR_2_PAR_MARK 3 + +/* MPSC Signal Routing */ +#define MPSC_MRR 0x0000 +#define MPSC_RCRR 0x0004 +#define MPSC_TCRR 0x0008 + +/* Serial DMA Controller Interface Registers */ +#define SDMA_SDC 0x0000 +#define SDMA_SDCM 0x0008 +#define SDMA_RX_DESC 0x0800 +#define SDMA_RX_BUF_PTR 0x0808 +#define SDMA_SCRDP 0x0810 +#define SDMA_TX_DESC 0x0c00 +#define SDMA_SCTDP 0x0c10 +#define SDMA_SFTDP 0x0c14 + +#define SDMA_DESC_CMDSTAT_PE (1<<0) +#define SDMA_DESC_CMDSTAT_CDL (1<<1) +#define SDMA_DESC_CMDSTAT_FR (1<<3) +#define SDMA_DESC_CMDSTAT_OR (1<<6) +#define SDMA_DESC_CMDSTAT_BR (1<<9) +#define SDMA_DESC_CMDSTAT_MI (1<<10) +#define SDMA_DESC_CMDSTAT_A (1<<11) +#define SDMA_DESC_CMDSTAT_AM (1<<12) +#define SDMA_DESC_CMDSTAT_CT (1<<13) +#define SDMA_DESC_CMDSTAT_C (1<<14) +#define SDMA_DESC_CMDSTAT_ES (1<<15) +#define SDMA_DESC_CMDSTAT_L (1<<16) +#define SDMA_DESC_CMDSTAT_F (1<<17) +#define SDMA_DESC_CMDSTAT_P (1<<18) +#define SDMA_DESC_CMDSTAT_EI (1<<23) +#define SDMA_DESC_CMDSTAT_O (1<<31) + +#define SDMA_DESC_DFLT (SDMA_DESC_CMDSTAT_O | \ + SDMA_DESC_CMDSTAT_EI) + +#define SDMA_SDC_RFT (1<<0) +#define SDMA_SDC_SFM (1<<1) +#define SDMA_SDC_BLMR (1<<6) +#define SDMA_SDC_BLMT (1<<7) +#define SDMA_SDC_POVR (1<<8) +#define SDMA_SDC_RIFB (1<<9) + +#define SDMA_SDCM_ERD (1<<7) +#define SDMA_SDCM_AR (1<<15) +#define SDMA_SDCM_STD (1<<16) +#define SDMA_SDCM_TXD (1<<23) +#define SDMA_SDCM_AT (1<<31) + +#define SDMA_0_CAUSE_RXBUF (1<<0) +#define SDMA_0_CAUSE_RXERR (1<<1) +#define SDMA_0_CAUSE_TXBUF (1<<2) +#define SDMA_0_CAUSE_TXEND (1<<3) +#define SDMA_1_CAUSE_RXBUF (1<<8) +#define SDMA_1_CAUSE_RXERR (1<<9) +#define SDMA_1_CAUSE_TXBUF (1<<10) +#define SDMA_1_CAUSE_TXEND (1<<11) + +#define SDMA_CAUSE_RX_MASK (SDMA_0_CAUSE_RXBUF | SDMA_0_CAUSE_RXERR | \ + SDMA_1_CAUSE_RXBUF | SDMA_1_CAUSE_RXERR) +#define SDMA_CAUSE_TX_MASK (SDMA_0_CAUSE_TXBUF | SDMA_0_CAUSE_TXEND | \ + SDMA_1_CAUSE_TXBUF | SDMA_1_CAUSE_TXEND) + +/* SDMA Interrupt registers */ +#define SDMA_INTR_CAUSE 0x0000 +#define SDMA_INTR_MASK 0x0080 + +/* Baud Rate Generator Interface Registers */ +#define BRG_BCR 0x0000 +#define BRG_BTR 0x0004 /* * Define how this driver is known to the outside (we've been assigned a diff --git a/drivers/serial/mpsc.h b/drivers/serial/mpsc.h deleted file mode 100644 index 15913300cea7..000000000000 --- a/drivers/serial/mpsc.h +++ /dev/null @@ -1,290 +0,0 @@ -/* - * drivers/serial/mpsc.h - * - * Author: Mark A. Greer - * - * 2004 (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 __MPSC_H__ -#define __MPSC_H__ - -#include - -#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define MPSC_NUM_CTLRS 2 - -/* - * Descriptors and buffers must be cache line aligned. - * Buffers lengths must be multiple of cache line size. - * Number of Tx & Rx descriptors must be powers of 2. - */ -#define MPSC_RXR_ENTRIES 32 -#define MPSC_RXRE_SIZE dma_get_cache_alignment() -#define MPSC_RXR_SIZE (MPSC_RXR_ENTRIES * MPSC_RXRE_SIZE) -#define MPSC_RXBE_SIZE dma_get_cache_alignment() -#define MPSC_RXB_SIZE (MPSC_RXR_ENTRIES * MPSC_RXBE_SIZE) - -#define MPSC_TXR_ENTRIES 32 -#define MPSC_TXRE_SIZE dma_get_cache_alignment() -#define MPSC_TXR_SIZE (MPSC_TXR_ENTRIES * MPSC_TXRE_SIZE) -#define MPSC_TXBE_SIZE dma_get_cache_alignment() -#define MPSC_TXB_SIZE (MPSC_TXR_ENTRIES * MPSC_TXBE_SIZE) - -#define MPSC_DMA_ALLOC_SIZE (MPSC_RXR_SIZE + MPSC_RXB_SIZE + \ - MPSC_TXR_SIZE + MPSC_TXB_SIZE + \ - dma_get_cache_alignment() /* for alignment */) - -/* Rx and Tx Ring entry descriptors -- assume entry size is <= cacheline size */ -struct mpsc_rx_desc { - u16 bufsize; - u16 bytecnt; - u32 cmdstat; - u32 link; - u32 buf_ptr; -} __attribute((packed)); - -struct mpsc_tx_desc { - u16 bytecnt; - u16 shadow; - u32 cmdstat; - u32 link; - u32 buf_ptr; -} __attribute((packed)); - -/* - * Some regs that have the erratum that you can't read them are are shared - * between the two MPSC controllers. This struct contains those shared regs. - */ -struct mpsc_shared_regs { - phys_addr_t mpsc_routing_base_p; - phys_addr_t sdma_intr_base_p; - - void __iomem *mpsc_routing_base; - void __iomem *sdma_intr_base; - - u32 MPSC_MRR_m; - u32 MPSC_RCRR_m; - u32 MPSC_TCRR_m; - u32 SDMA_INTR_CAUSE_m; - u32 SDMA_INTR_MASK_m; -}; - -/* The main driver data structure */ -struct mpsc_port_info { - struct uart_port port; /* Overlay uart_port structure */ - - /* Internal driver state for this ctlr */ - u8 ready; - u8 rcv_data; - tcflag_t c_iflag; /* save termios->c_iflag */ - tcflag_t c_cflag; /* save termios->c_cflag */ - - /* Info passed in from platform */ - u8 mirror_regs; /* Need to mirror regs? */ - u8 cache_mgmt; /* Need manual cache mgmt? */ - u8 brg_can_tune; /* BRG has baud tuning? */ - u32 brg_clk_src; - u16 mpsc_max_idle; - int default_baud; - int default_bits; - int default_parity; - int default_flow; - - /* Physical addresses of various blocks of registers (from platform) */ - phys_addr_t mpsc_base_p; - phys_addr_t sdma_base_p; - phys_addr_t brg_base_p; - - /* Virtual addresses of various blocks of registers (from platform) */ - void __iomem *mpsc_base; - void __iomem *sdma_base; - void __iomem *brg_base; - - /* Descriptor ring and buffer allocations */ - void *dma_region; - dma_addr_t dma_region_p; - - dma_addr_t rxr; /* Rx descriptor ring */ - dma_addr_t rxr_p; /* Phys addr of rxr */ - u8 *rxb; /* Rx Ring I/O buf */ - u8 *rxb_p; /* Phys addr of rxb */ - u32 rxr_posn; /* First desc w/ Rx data */ - - dma_addr_t txr; /* Tx descriptor ring */ - dma_addr_t txr_p; /* Phys addr of txr */ - u8 *txb; /* Tx Ring I/O buf */ - u8 *txb_p; /* Phys addr of txb */ - int txr_head; /* Where new data goes */ - int txr_tail; /* Where sent data comes off */ - - /* Mirrored values of regs we can't read (if 'mirror_regs' set) */ - u32 MPSC_MPCR_m; - u32 MPSC_CHR_1_m; - u32 MPSC_CHR_2_m; - u32 MPSC_CHR_10_m; - u32 BRG_BCR_m; - struct mpsc_shared_regs *shared_regs; -}; - -/* Hooks to platform-specific code */ -int mpsc_platform_register_driver(void); -void mpsc_platform_unregister_driver(void); - -/* Hooks back in to mpsc common to be called by platform-specific code */ -struct mpsc_port_info *mpsc_device_probe(int index); -struct mpsc_port_info *mpsc_device_remove(int index); - -/* - ***************************************************************************** - * - * Multi-Protocol Serial Controller Interface Registers - * - ***************************************************************************** - */ - -/* Main Configuratino Register Offsets */ -#define MPSC_MMCRL 0x0000 -#define MPSC_MMCRH 0x0004 -#define MPSC_MPCR 0x0008 -#define MPSC_CHR_1 0x000c -#define MPSC_CHR_2 0x0010 -#define MPSC_CHR_3 0x0014 -#define MPSC_CHR_4 0x0018 -#define MPSC_CHR_5 0x001c -#define MPSC_CHR_6 0x0020 -#define MPSC_CHR_7 0x0024 -#define MPSC_CHR_8 0x0028 -#define MPSC_CHR_9 0x002c -#define MPSC_CHR_10 0x0030 -#define MPSC_CHR_11 0x0034 - -#define MPSC_MPCR_FRZ (1 << 9) -#define MPSC_MPCR_CL_5 0 -#define MPSC_MPCR_CL_6 1 -#define MPSC_MPCR_CL_7 2 -#define MPSC_MPCR_CL_8 3 -#define MPSC_MPCR_SBL_1 0 -#define MPSC_MPCR_SBL_2 1 - -#define MPSC_CHR_2_TEV (1<<1) -#define MPSC_CHR_2_TA (1<<7) -#define MPSC_CHR_2_TTCS (1<<9) -#define MPSC_CHR_2_REV (1<<17) -#define MPSC_CHR_2_RA (1<<23) -#define MPSC_CHR_2_CRD (1<<25) -#define MPSC_CHR_2_EH (1<<31) -#define MPSC_CHR_2_PAR_ODD 0 -#define MPSC_CHR_2_PAR_SPACE 1 -#define MPSC_CHR_2_PAR_EVEN 2 -#define MPSC_CHR_2_PAR_MARK 3 - -/* MPSC Signal Routing */ -#define MPSC_MRR 0x0000 -#define MPSC_RCRR 0x0004 -#define MPSC_TCRR 0x0008 - -/* - ***************************************************************************** - * - * Serial DMA Controller Interface Registers - * - ***************************************************************************** - */ - -#define SDMA_SDC 0x0000 -#define SDMA_SDCM 0x0008 -#define SDMA_RX_DESC 0x0800 -#define SDMA_RX_BUF_PTR 0x0808 -#define SDMA_SCRDP 0x0810 -#define SDMA_TX_DESC 0x0c00 -#define SDMA_SCTDP 0x0c10 -#define SDMA_SFTDP 0x0c14 - -#define SDMA_DESC_CMDSTAT_PE (1<<0) -#define SDMA_DESC_CMDSTAT_CDL (1<<1) -#define SDMA_DESC_CMDSTAT_FR (1<<3) -#define SDMA_DESC_CMDSTAT_OR (1<<6) -#define SDMA_DESC_CMDSTAT_BR (1<<9) -#define SDMA_DESC_CMDSTAT_MI (1<<10) -#define SDMA_DESC_CMDSTAT_A (1<<11) -#define SDMA_DESC_CMDSTAT_AM (1<<12) -#define SDMA_DESC_CMDSTAT_CT (1<<13) -#define SDMA_DESC_CMDSTAT_C (1<<14) -#define SDMA_DESC_CMDSTAT_ES (1<<15) -#define SDMA_DESC_CMDSTAT_L (1<<16) -#define SDMA_DESC_CMDSTAT_F (1<<17) -#define SDMA_DESC_CMDSTAT_P (1<<18) -#define SDMA_DESC_CMDSTAT_EI (1<<23) -#define SDMA_DESC_CMDSTAT_O (1<<31) - -#define SDMA_DESC_DFLT (SDMA_DESC_CMDSTAT_O | \ - SDMA_DESC_CMDSTAT_EI) - -#define SDMA_SDC_RFT (1<<0) -#define SDMA_SDC_SFM (1<<1) -#define SDMA_SDC_BLMR (1<<6) -#define SDMA_SDC_BLMT (1<<7) -#define SDMA_SDC_POVR (1<<8) -#define SDMA_SDC_RIFB (1<<9) - -#define SDMA_SDCM_ERD (1<<7) -#define SDMA_SDCM_AR (1<<15) -#define SDMA_SDCM_STD (1<<16) -#define SDMA_SDCM_TXD (1<<23) -#define SDMA_SDCM_AT (1<<31) - -#define SDMA_0_CAUSE_RXBUF (1<<0) -#define SDMA_0_CAUSE_RXERR (1<<1) -#define SDMA_0_CAUSE_TXBUF (1<<2) -#define SDMA_0_CAUSE_TXEND (1<<3) -#define SDMA_1_CAUSE_RXBUF (1<<8) -#define SDMA_1_CAUSE_RXERR (1<<9) -#define SDMA_1_CAUSE_TXBUF (1<<10) -#define SDMA_1_CAUSE_TXEND (1<<11) - -#define SDMA_CAUSE_RX_MASK (SDMA_0_CAUSE_RXBUF | SDMA_0_CAUSE_RXERR | \ - SDMA_1_CAUSE_RXBUF | SDMA_1_CAUSE_RXERR) -#define SDMA_CAUSE_TX_MASK (SDMA_0_CAUSE_TXBUF | SDMA_0_CAUSE_TXEND | \ - SDMA_1_CAUSE_TXBUF | SDMA_1_CAUSE_TXEND) - -/* SDMA Interrupt registers */ -#define SDMA_INTR_CAUSE 0x0000 -#define SDMA_INTR_MASK 0x0080 - -/* - ***************************************************************************** - * - * Baud Rate Generator Interface Registers - * - ***************************************************************************** - */ - -#define BRG_BCR 0x0000 -#define BRG_BTR 0x0004 - -#endif /* __MPSC_H__ */ -- cgit v1.2.3-59-g8ed1b From a9312fb839e90668d05a90024f3a7e7ff646a4a3 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 25 Mar 2006 03:08:30 -0800 Subject: [PATCH] git-scsi-misc: min() warning fix drivers/scsi/sd.c: In function `sd_store_cache_type': drivers/scsi/sd.c:193: warning: comparison of distinct pointer types lacks a cast Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 024ef86c5242..c647d85d97d1 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -190,7 +190,7 @@ static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf, if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT, SD_MAX_RETRIES, &data, NULL)) return -EINVAL; - len = min(sizeof(buffer), data.length - data.header_length - + len = min_t(size_t, sizeof(buffer), data.length - data.header_length - data.block_descriptor_length); buffer_data = buffer + data.header_length + data.block_descriptor_length; -- cgit v1.2.3-59-g8ed1b From b2b978f98036717e2508cf3288aecb8f9c7d724e Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Sat, 25 Mar 2006 16:29:52 +0100 Subject: [PATCH] x86_64: Fix wrong PCI ID for ALI M1695 AGP bridge [description by AK] Made a cut'n'paste error when adding the entry for the ALI M1695 AGP bridge and added a second entry for the 1689 Cc: Dave Jones Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- drivers/char/agp/amd64-agp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 1251b2515bbe..7c6c7268e236 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -725,7 +725,7 @@ static struct pci_device_id agp_amd64_pci_table[] = { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_AL, - .device = 0x1689, + .device = 0x1695, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, -- cgit v1.2.3-59-g8ed1b From 4bc32c4d5cde5c57edcc9c2fe5057da8a4dd0153 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 25 Mar 2006 16:30:07 +0100 Subject: [PATCH] x86_64: Implement compat code for raw1394 read/write Not for the ioctls so far because I was too lazy. Cc: bcollins@debian.org Cc: dan@dennedy.org Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- drivers/ieee1394/raw1394.c | 96 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index b05235639918..19f26c5c9479 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "csr1212.h" #include "ieee1394.h" @@ -406,6 +407,65 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction, queue_complete_req(req); } +#ifdef CONFIG_COMPAT +struct compat_raw1394_req { + __u32 type; + __s32 error; + __u32 misc; + + __u32 generation; + __u32 length; + + __u64 address; + + __u64 tag; + + __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 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)) + return ERR_PTR(-EFAULT); + return (const char __user *)r; +} +#undef C + +#define P(x) __put_user(r->x, &cr->x) + +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)) || + P(type) || + P(error) || + P(misc) || + P(generation) || + P(length) || + P(address) || + P(tag) || + P(sendb) || + P(recvb)) + return -EFAULT; + return sizeof(struct compat_raw1394_req); +} +#undef P + +#endif + + static ssize_t raw1394_read(struct file *file, char __user * buffer, size_t count, loff_t * offset_is_ignored) { @@ -415,6 +475,11 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer, struct pending_request *req; ssize_t ret; +#ifdef CONFIG_COMPAT + if (count == sizeof(struct compat_raw1394_req)) { + /* ok */ + } else +#endif if (count != sizeof(struct raw1394_request)) { return -EINVAL; } @@ -446,12 +511,22 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer, req->req.error = RAW1394_ERROR_MEMFAULT; } } - if (copy_to_user(buffer, &req->req, sizeof(req->req))) { - ret = -EFAULT; - goto out; - } - ret = (ssize_t) sizeof(struct raw1394_request); +#ifdef CONFIG_COMPAT + if (count == sizeof(struct compat_raw1394_req) && + sizeof(struct compat_raw1394_req) != + sizeof(struct raw1394_request)) { + ret = raw1394_compat_read(buffer, &req->req); + + } else +#endif + { + if (copy_to_user(buffer, &req->req, sizeof(req->req))) { + ret = -EFAULT; + goto out; + } + ret = (ssize_t) sizeof(struct raw1394_request); + } out: free_pending_request(req); return ret; @@ -2274,6 +2349,7 @@ 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) { @@ -2281,6 +2357,15 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, struct pending_request *req; ssize_t retval = 0; +#ifdef CONFIG_COMPAT + 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); + } else +#endif if (count != sizeof(struct raw1394_request)) { return -EINVAL; } @@ -2893,6 +2978,7 @@ static struct file_operations raw1394_fops = { .write = raw1394_write, .mmap = raw1394_mmap, .ioctl = raw1394_ioctl, + // .compat_ioctl = ... someone needs to do this .poll = raw1394_poll, .open = raw1394_open, .release = raw1394_release, -- cgit v1.2.3-59-g8ed1b From f083a329e63d471a5e9238e837772b1b76c218db Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 25 Mar 2006 16:30:19 +0100 Subject: [PATCH] x86_64: Clean up and tweak ACPI blacklist year code - Move the core parser into dmi_scan.c. It can be useful for other subsystems too. - Differentiate between field doesn't exist and field is 0 or unparseable. The first case is likely an old BIOS with broken ACPI, the later is likely a slightly buggy BIOS where someone forget to edit the date. Don't blacklist in the later case. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/i386/kernel/dmi_scan.c | 30 ++++++++++++++++++++++++++++++ drivers/acpi/blacklist.c | 27 ++++++--------------------- include/linux/dmi.h | 2 ++ 3 files changed, 38 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c index ca2a0cbcac04..d2dfd9c8d691 100644 --- a/arch/i386/kernel/dmi_scan.c +++ b/arch/i386/kernel/dmi_scan.c @@ -299,3 +299,33 @@ struct dmi_device * dmi_find_device(int type, const char *name, return NULL; } EXPORT_SYMBOL(dmi_find_device); + +/** + * dmi_get_year - Return year of a DMI date + * @field: data index (like dmi_get_system_info) + * + * Returns -1 when the field doesn't exist. 0 when it is broken. + */ +int dmi_get_year(int field) +{ + int year; + char *s = dmi_get_system_info(field); + + if (!s) + return -1; + if (*s == '\0') + return 0; + s = strrchr(s, '/'); + if (!s) + return 0; + + s += 1; + year = simple_strtoul(s, NULL, 0); + if (year && year < 100) { /* 2-digit year */ + year += 1900; + if (year < 1996) /* no dates < spec 1.0 */ + year += 100; + } + + return year; +} diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 9824f679a910..f9c972b26f4f 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -77,28 +77,13 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = { static int __init blacklist_by_year(void) { - int year; - char *s = dmi_get_system_info(DMI_BIOS_DATE); - - if (!s) - return 0; - if (!*s) - return 0; - - s = strrchr(s, '/'); - if (!s) + int year = dmi_get_year(DMI_BIOS_DATE); + /* Doesn't exist? Likely an old system */ + if (year == -1) + return 1; + /* 0? Likely a buggy new BIOS */ + if (year == 0) return 0; - - s += 1; - - year = simple_strtoul(s, NULL, 0); - - if (year < 100) { /* 2-digit year */ - year += 1900; - if (year < 1996) /* no dates < spec 1.0 */ - year += 100; - } - if (year < CONFIG_ACPI_BLACKLIST_YEAR) { printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), " "acpi=force is required to enable ACPI\n", diff --git a/include/linux/dmi.h b/include/linux/dmi.h index 2e6bbe014157..64fd6c366604 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -68,6 +68,7 @@ extern char * dmi_get_system_info(int field); extern struct dmi_device * dmi_find_device(int type, const char *name, struct dmi_device *from); extern void dmi_scan_machine(void); +extern int dmi_get_year(int field); #else @@ -75,6 +76,7 @@ static inline int dmi_check_system(struct dmi_system_id *list) { return 0; } static inline char * dmi_get_system_info(int field) { return NULL; } static inline struct dmi_device * dmi_find_device(int type, const char *name, struct dmi_device *from) { return NULL; } +static inline int dmi_get_year(int year) { return 0; } #endif -- cgit v1.2.3-59-g8ed1b From bd6633476922b7b51227f7f704c2546e763ae5ed Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 25 Mar 2006 16:31:07 +0100 Subject: [PATCH] x86_64: Force broadcast timer on AMD systems with C3 too. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- drivers/acpi/processor_idle.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index eb730a80952c..2be895895943 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -876,14 +876,11 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) { unsigned int i; unsigned int working = 0; - -#ifdef ARCH_APICTIMER_STOPS_ON_C3 - struct cpuinfo_x86 *c = cpu_data + pr->id; + int timer_broadcast = 0; cpumask_t mask = cpumask_of_cpu(pr->id); - if (c->x86_vendor == X86_VENDOR_INTEL) { - on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1); - } +#ifdef ARCH_APICTIMER_STOPS_ON_C3 + on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1); #endif for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { @@ -896,15 +893,20 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) case ACPI_STATE_C2: acpi_processor_power_verify_c2(cx); +#ifdef ARCH_APICTIMER_STOPS_ON_C3 + /* Some AMD systems fake C3 as C2, but still + have timer troubles */ + if (cx->valid && + boot_cpu_data.x86_vendor == X86_VENDOR_AMD) + timer_broadcast++; +#endif break; case ACPI_STATE_C3: acpi_processor_power_verify_c3(pr, cx); #ifdef ARCH_APICTIMER_STOPS_ON_C3 - if (cx->valid && c->x86_vendor == X86_VENDOR_INTEL) { - on_each_cpu(switch_APIC_timer_to_ipi, - &mask, 1, 1); - } + if (cx->valid) + timer_broadcast++; #endif break; } @@ -913,6 +915,9 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) working++; } + if (timer_broadcast) + on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1); + return (working); } -- cgit v1.2.3-59-g8ed1b From cb2fc532d0a304631c92b175f886934654c60907 Mon Sep 17 00:00:00 2001 From: maximilian attems Date: Sat, 25 Mar 2006 17:44:20 +0000 Subject: [SERIAL] icom: select FW_LOADER The icom driver uses request_firmware() and thus needs to select FW_LOADER. Signed-off-by: maximilian attems Signed-off-by: Russell King --- drivers/serial/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index c66ef96c71b4..d0a10faed143 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -827,6 +827,7 @@ config SERIAL_ICOM tristate "IBM Multiport Serial Adapter" depends on PCI && (PPC_ISERIES || PPC_PSERIES) select SERIAL_CORE + select FW_LOADER help This driver is for a family of multiport serial adapters including 2 port RVX, 2 port internal modem, 4 port internal -- cgit v1.2.3-59-g8ed1b From 111c9bf8c5cfa92363b3719c8956d29368b5b9de Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 25 Mar 2006 17:49:47 +0000 Subject: [SERIAL] remove 8250_acpi (replaced by 8250_pnp and PNPACPI) With the combination of PNPACPI and 8250_pnp, we no longer need 8250_acpi. Signed-off-by: Bjorn Helgaas Signed-off-by: Russell King --- drivers/serial/8250_acpi.c | 183 --------------------------------------------- drivers/serial/Kconfig | 8 -- drivers/serial/Makefile | 1 - 3 files changed, 192 deletions(-) delete mode 100644 drivers/serial/8250_acpi.c (limited to 'drivers') diff --git a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c deleted file mode 100644 index 809f89ab965c..000000000000 --- a/drivers/serial/8250_acpi.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard - * Copyright (C) 2004 Hewlett-Packard Co - * Bjorn Helgaas - * - * 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 "8250.h" - -struct serial_private { - int line; -}; - -static acpi_status acpi_serial_mmio(struct uart_port *port, - struct acpi_resource_address64 *addr) -{ - port->mapbase = addr->minimum; - port->iotype = UPIO_MEM; - port->flags |= UPF_IOREMAP; - return AE_OK; -} - -static acpi_status acpi_serial_port(struct uart_port *port, - struct acpi_resource_io *io) -{ - if (io->address_length) { - port->iobase = io->minimum; - port->iotype = UPIO_PORT; - } else - printk(KERN_ERR "%s: zero-length IO port range?\n", __FUNCTION__); - return AE_OK; -} - -static acpi_status acpi_serial_ext_irq(struct uart_port *port, - struct acpi_resource_extended_irq *ext_irq) -{ - int rc; - - if (ext_irq->interrupt_count > 0) { - rc = acpi_register_gsi(ext_irq->interrupts[0], - ext_irq->triggering, ext_irq->polarity); - if (rc < 0) - return AE_ERROR; - port->irq = rc; - } - return AE_OK; -} - -static acpi_status acpi_serial_irq(struct uart_port *port, - struct acpi_resource_irq *irq) -{ - int rc; - - if (irq->interrupt_count > 0) { - rc = acpi_register_gsi(irq->interrupts[0], - irq->triggering, irq->polarity); - if (rc < 0) - return AE_ERROR; - port->irq = rc; - } - return AE_OK; -} - -static acpi_status acpi_serial_resource(struct acpi_resource *res, void *data) -{ - struct uart_port *port = (struct uart_port *) data; - struct acpi_resource_address64 addr; - acpi_status status; - - status = acpi_resource_to_address64(res, &addr); - if (ACPI_SUCCESS(status)) - return acpi_serial_mmio(port, &addr); - else if (res->type == ACPI_RESOURCE_TYPE_IO) - return acpi_serial_port(port, &res->data.io); - else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) - return acpi_serial_ext_irq(port, &res->data.extended_irq); - else if (res->type == ACPI_RESOURCE_TYPE_IRQ) - return acpi_serial_irq(port, &res->data.irq); - return AE_OK; -} - -static int acpi_serial_add(struct acpi_device *device) -{ - struct serial_private *priv; - acpi_status status; - struct uart_port port; - int result; - - memset(&port, 0, sizeof(struct uart_port)); - - port.uartclk = 1843200; - port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; - - priv = kmalloc(sizeof(struct serial_private), GFP_KERNEL); - if (!priv) { - result = -ENOMEM; - goto fail; - } - memset(priv, 0, sizeof(*priv)); - - status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, - acpi_serial_resource, &port); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto fail; - } - - if (!port.mapbase && !port.iobase) { - printk(KERN_ERR "%s: no iomem or port address in %s _CRS\n", - __FUNCTION__, device->pnp.bus_id); - result = -ENODEV; - goto fail; - } - - priv->line = serial8250_register_port(&port); - if (priv->line < 0) { - printk(KERN_WARNING "Couldn't register serial port %s: %d\n", - device->pnp.bus_id, priv->line); - result = -ENODEV; - goto fail; - } - - acpi_driver_data(device) = priv; - return 0; - -fail: - kfree(priv); - - return result; -} - -static int acpi_serial_remove(struct acpi_device *device, int type) -{ - struct serial_private *priv; - - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - priv = acpi_driver_data(device); - serial8250_unregister_port(priv->line); - kfree(priv); - - return 0; -} - -static struct acpi_driver acpi_serial_driver = { - .name = "serial", - .class = "", - .ids = "PNP0501", - .ops = { - .add = acpi_serial_add, - .remove = acpi_serial_remove, - }, -}; - -static int __init acpi_serial_init(void) -{ - return acpi_bus_register_driver(&acpi_serial_driver); -} - -static void __exit acpi_serial_exit(void) -{ - acpi_bus_unregister_driver(&acpi_serial_driver); -} - -module_init(acpi_serial_init); -module_exit(acpi_serial_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Generic 8250/16x50 ACPI serial driver"); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index d0a10faed143..ceb3697bf84d 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -77,14 +77,6 @@ config SERIAL_8250_CS If unsure, say N. -config SERIAL_8250_ACPI - bool "8250/16550 device discovery via ACPI namespace" - default y if IA64 - depends on ACPI && SERIAL_8250 - ---help--- - If you wish to enable serial port discovery via the ACPI - namespace, say Y here. If unsure, say N. - config SERIAL_8250_NR_UARTS int "Maximum number of 8250/16550 serial ports" depends on SERIAL_8250 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 50c221af9e6d..a3a4323d9c86 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -5,7 +5,6 @@ # serial-8250-y := -serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o serial-8250-$(CONFIG_PNP) += 8250_pnp.o serial-8250-$(CONFIG_GSC) += 8250_gsc.o serial-8250-$(CONFIG_PCI) += 8250_pci.o -- cgit v1.2.3-59-g8ed1b From 98639a67a9482fbfc4f9c91b4b59bf0d06b1f6c1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 25 Mar 2006 21:30:11 +0000 Subject: [SERIAL] amba-pl010: Remove accessor macros Remove unnecessary accessor macros, using readb/writel directly instead. Signed-off-by: Russell King --- drivers/serial/amba-pl010.c | 110 ++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index e04d5e82d9ae..127d6cd5de7f 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -62,26 +62,8 @@ #define AMBA_ISR_PASS_LIMIT 256 -/* - * Access macros for the AMBA UARTs - */ -#define UART_GET_INT_STATUS(p) readb((p)->membase + UART010_IIR) -#define UART_PUT_ICR(p, c) writel((c), (p)->membase + UART010_ICR) -#define UART_GET_FR(p) readb((p)->membase + UART01x_FR) -#define UART_GET_CHAR(p) readb((p)->membase + UART01x_DR) -#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + UART01x_DR) -#define UART_GET_RSR(p) readb((p)->membase + UART01x_RSR) -#define UART_GET_CR(p) readb((p)->membase + UART010_CR) -#define UART_PUT_CR(p,c) writel((c), (p)->membase + UART010_CR) -#define UART_GET_LCRL(p) readb((p)->membase + UART010_LCRL) -#define UART_PUT_LCRL(p,c) writel((c), (p)->membase + UART010_LCRL) -#define UART_GET_LCRM(p) readb((p)->membase + UART010_LCRM) -#define UART_PUT_LCRM(p,c) writel((c), (p)->membase + UART010_LCRM) -#define UART_GET_LCRH(p) readb((p)->membase + UART010_LCRH) -#define UART_PUT_LCRH(p,c) writel((c), (p)->membase + UART010_LCRH) #define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0) #define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0) -#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART01x_FR_TMSK) == 0) #define UART_DUMMY_RSR_RX /*256*/0 #define UART_PORT_SIZE 64 @@ -110,36 +92,36 @@ static void pl010_stop_tx(struct uart_port *port) { unsigned int cr; - cr = UART_GET_CR(port); + cr = readb(port->membase + UART010_CR); cr &= ~UART010_CR_TIE; - UART_PUT_CR(port, cr); + writel(cr, port->membase + UART010_CR); } static void pl010_start_tx(struct uart_port *port) { unsigned int cr; - cr = UART_GET_CR(port); + cr = readb(port->membase + UART010_CR); cr |= UART010_CR_TIE; - UART_PUT_CR(port, cr); + writel(cr, port->membase + UART010_CR); } static void pl010_stop_rx(struct uart_port *port) { unsigned int cr; - cr = UART_GET_CR(port); + cr = readb(port->membase + UART010_CR); cr &= ~(UART010_CR_RIE | UART010_CR_RTIE); - UART_PUT_CR(port, cr); + writel(cr, port->membase + UART010_CR); } static void pl010_enable_ms(struct uart_port *port) { unsigned int cr; - cr = UART_GET_CR(port); + cr = readb(port->membase + UART010_CR); cr |= UART010_CR_MSIE; - UART_PUT_CR(port, cr); + writel(cr, port->membase + UART010_CR); } static void @@ -152,9 +134,9 @@ pl010_rx_chars(struct uart_port *port) struct tty_struct *tty = port->info->tty; unsigned int status, ch, flag, rsr, max_count = 256; - status = UART_GET_FR(port); + status = readb(port->membase + UART01x_FR); while (UART_RX_DATA(status) && max_count--) { - ch = UART_GET_CHAR(port); + ch = readb(port->membase + UART01x_DR); flag = TTY_NORMAL; port->icount.rx++; @@ -163,7 +145,7 @@ pl010_rx_chars(struct uart_port *port) * Note that the error handling code is * out of the main execution path */ - rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX; + rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX; if (unlikely(rsr & UART01x_RSR_ANY)) { if (rsr & UART01x_RSR_BE) { rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); @@ -193,7 +175,7 @@ pl010_rx_chars(struct uart_port *port) uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag); ignore_char: - status = UART_GET_FR(port); + status = readb(port->membase + UART01x_FR); } tty_flip_buffer_push(tty); return; @@ -205,7 +187,7 @@ static void pl010_tx_chars(struct uart_port *port) int count; if (port->x_char) { - UART_PUT_CHAR(port, port->x_char); + writel(port->x_char, port->membase + UART01x_DR); port->icount.tx++; port->x_char = 0; return; @@ -217,7 +199,7 @@ static void pl010_tx_chars(struct uart_port *port) count = port->fifosize >> 1; do { - UART_PUT_CHAR(port, xmit->buf[xmit->tail]); + writel(xmit->buf[xmit->tail], port->membase + UART01x_DR); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; if (uart_circ_empty(xmit)) @@ -236,9 +218,9 @@ static void pl010_modem_status(struct uart_port *port) struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int status, delta; - UART_PUT_ICR(&uap->port, 0); + writel(0, uap->port.membase + UART010_ICR); - status = UART_GET_FR(&uap->port) & UART01x_FR_MODEM_ANY; + status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; delta = status ^ uap->old_status; uap->old_status = status; @@ -266,7 +248,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) spin_lock(&port->lock); - status = UART_GET_INT_STATUS(port); + status = readb(port->membase + UART010_IIR); if (status) { do { if (status & (UART010_IIR_RTIS | UART010_IIR_RIS)) @@ -283,7 +265,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) if (pass_counter-- == 0) break; - status = UART_GET_INT_STATUS(port); + status = readb(port->membase + UART010_IIR); } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS | UART010_IIR_TIS)); handled = 1; @@ -296,7 +278,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) static unsigned int pl010_tx_empty(struct uart_port *port) { - return UART_GET_FR(port) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; + return readb(port->membase + UART01x_FR) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; } static unsigned int pl010_get_mctrl(struct uart_port *port) @@ -304,7 +286,7 @@ static unsigned int pl010_get_mctrl(struct uart_port *port) unsigned int result = 0; unsigned int status; - status = UART_GET_FR(port); + status = readb(port->membase + UART01x_FR); if (status & UART01x_FR_DCD) result |= TIOCM_CAR; if (status & UART01x_FR_DSR) @@ -340,12 +322,12 @@ static void pl010_break_ctl(struct uart_port *port, int break_state) unsigned int lcr_h; spin_lock_irqsave(&port->lock, flags); - lcr_h = UART_GET_LCRH(port); + lcr_h = readb(port->membase + UART010_LCRH); if (break_state == -1) lcr_h |= UART01x_LCRH_BRK; else lcr_h &= ~UART01x_LCRH_BRK; - UART_PUT_LCRH(port, lcr_h); + writel(lcr_h, port->membase + UART010_LCRH); spin_unlock_irqrestore(&port->lock, flags); } @@ -364,13 +346,13 @@ static int pl010_startup(struct uart_port *port) /* * initialise the old status of the modem signals */ - uap->old_status = UART_GET_FR(port) & UART01x_FR_MODEM_ANY; + uap->old_status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY; /* * Finally, enable interrupts */ - UART_PUT_CR(port, UART01x_CR_UARTEN | UART010_CR_RIE | - UART010_CR_RTIE); + writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE, + port->membase + UART010_CR); return 0; } @@ -385,11 +367,12 @@ static void pl010_shutdown(struct uart_port *port) /* * disable all interrupts, disable the port */ - UART_PUT_CR(port, 0); + writel(0, port->membase + UART010_CR); /* disable break condition and fifos */ - UART_PUT_LCRH(port, UART_GET_LCRH(port) & - ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN)); + writel(readb(port->membase + UART010_LCRH) & + ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN), + port->membase + UART010_LCRH); } static void @@ -466,25 +449,25 @@ pl010_set_termios(struct uart_port *port, struct termios *termios, port->ignore_status_mask |= UART_DUMMY_RSR_RX; /* first, disable everything */ - old_cr = UART_GET_CR(port) & ~UART010_CR_MSIE; + old_cr = readb(port->membase + UART010_CR) & ~UART010_CR_MSIE; if (UART_ENABLE_MS(port, termios->c_cflag)) old_cr |= UART010_CR_MSIE; - UART_PUT_CR(port, 0); + writel(0, port->membase + UART010_CR); /* Set baud rate */ quot -= 1; - UART_PUT_LCRM(port, ((quot & 0xf00) >> 8)); - UART_PUT_LCRL(port, (quot & 0xff)); + writel((quot & 0xf00) >> 8, port->membase + UART010_LCRM); + writel(quot & 0xff, port->membase + UART010_LCRL); /* * ----------v----------v----------v----------v----- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L * ----------^----------^----------^----------^----- */ - UART_PUT_LCRH(port, lcr_h); - UART_PUT_CR(port, old_cr); + writel(lcr_h, port->membase + UART010_LCRH); + writel(old_cr, port->membase + UART010_CR); spin_unlock_irqrestore(&port->lock, flags); } @@ -593,9 +576,13 @@ static struct uart_amba_port amba_ports[UART_NR] = { static void pl010_console_putchar(struct uart_port *port, int ch) { - while (!UART_TX_READY(UART_GET_FR(port))) + unsigned int status; + + do { + status = readb(port->membase + UART01x_FR); barrier(); - UART_PUT_CHAR(port, ch); + } while (!UART_TX_READY(status)); + writel(ch, port->membase + UART01x_DR); } static void @@ -607,8 +594,8 @@ pl010_console_write(struct console *co, const char *s, unsigned int count) /* * First save the CR then disable the interrupts */ - old_cr = UART_GET_CR(port); - UART_PUT_CR(port, UART01x_CR_UARTEN); + old_cr = readb(port->membase + UART010_CR); + writel(UART01x_CR_UARTEN, port->membase + UART010_CR); uart_console_write(port, s, count, pl010_console_putchar); @@ -617,18 +604,19 @@ pl010_console_write(struct console *co, const char *s, unsigned int count) * and restore the TCR */ do { - status = UART_GET_FR(port); + status = readb(port->membase + UART01x_FR); + barrier(); } while (status & UART01x_FR_BUSY); - UART_PUT_CR(port, old_cr); + writel(old_cr, port->membase + UART010_CR); } static void __init pl010_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { - if (UART_GET_CR(port) & UART01x_CR_UARTEN) { + if (readb(port->membase + UART010_CR) & UART01x_CR_UARTEN) { unsigned int lcr_h, quot; - lcr_h = UART_GET_LCRH(port); + lcr_h = readb(port->membase + UART010_LCRH); *parity = 'n'; if (lcr_h & UART01x_LCRH_PEN) { @@ -643,7 +631,7 @@ pl010_console_get_options(struct uart_port *port, int *baud, else *bits = 8; - quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8; + quot = readb(port->membase + UART010_LCRL) | readb(port->membase + UART010_LCRM) << 8; *baud = port->uartclk / (16 * (quot + 1)); } } -- cgit v1.2.3-59-g8ed1b From 0b5c59a1e41636afa77b90d34e8c394d8d929733 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sun, 26 Mar 2006 02:24:07 +0100 Subject: [PATCH] Fix compilation of processor_idle.c on IA64 Broken earlier by me by a x86-64 patch. The code was optimized away, but the compiler still complained about an undeclared function. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- drivers/acpi/processor_idle.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2be895895943..80fa43471f48 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -876,10 +876,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) { unsigned int i; unsigned int working = 0; - int timer_broadcast = 0; - cpumask_t mask = cpumask_of_cpu(pr->id); #ifdef ARCH_APICTIMER_STOPS_ON_C3 + int timer_broadcast = 0; + cpumask_t mask = cpumask_of_cpu(pr->id); on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1); #endif @@ -915,8 +915,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) working++; } +#ifdef ARCH_APICTIMER_STOPS_ON_C3 if (timer_broadcast) on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1); +#endif return (working); } -- cgit v1.2.3-59-g8ed1b From 2c906b317b2d9c7e32b0d513e102bd68a2c49112 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Wed, 22 Mar 2006 09:54:10 +0000 Subject: [PATCH] cpufreq_conservative: aligning of codebase with ondemand Since the conservative govenor was released its codebase has drifted from the the direction and updates that have been applied to the ondemand govornor. This patch addresses the lack of updates in that period and brings conservative back up to date. The resulting diff file between cpufreq_ondemand.c and cpufreq_conservative.c is now much smaller and shows more clearly the differences between the two. Another reason to do this is ages ago, knowingly, I did a piss poor attempt at making conservative less responsive by knocking up DEF_SAMPLING_RATE_LATENCY_MULTIPLIER by two orders of magnitude. I did fix this ages ago but in my dis-organisation I must have toasted the diff and left it the way it was. About two weeks ago a user contacted me saying he was having problems with the conservative governor with his AMD Athlon XP-M 2800+ as /sys/devices/system/cpu/cpu0/cpufreq/conservative showed sampling_rate_min 9950000 sampling_rate_max 1360065408 Nine seconds to decide about changing the frequency....not too responsive :) Signed-off-by: Alexander Clouter Signed-off-by: Dominik Brodowski --- drivers/cpufreq/cpufreq_conservative.c | 53 +++++++++++++++++----------------- 1 file changed, 27 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index ac38766b2583..adecd31f6156 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -35,12 +35,7 @@ */ #define DEF_FREQUENCY_UP_THRESHOLD (80) -#define MIN_FREQUENCY_UP_THRESHOLD (0) -#define MAX_FREQUENCY_UP_THRESHOLD (100) - #define DEF_FREQUENCY_DOWN_THRESHOLD (20) -#define MIN_FREQUENCY_DOWN_THRESHOLD (0) -#define MAX_FREQUENCY_DOWN_THRESHOLD (100) /* * The polling frequency of this governor depends on the capability of @@ -53,10 +48,14 @@ * All times here are in uS. */ static unsigned int def_sampling_rate; -#define MIN_SAMPLING_RATE (def_sampling_rate / 2) +#define MIN_SAMPLING_RATE_RATIO (2) +/* for correct statistics, we need at least 10 ticks between each measure */ +#define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) +#define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) #define MAX_SAMPLING_RATE (500 * def_sampling_rate) -#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (100000) -#define DEF_SAMPLING_DOWN_FACTOR (5) +#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) +#define DEF_SAMPLING_DOWN_FACTOR (1) +#define MAX_SAMPLING_DOWN_FACTOR (10) #define TRANSITION_LATENCY_LIMIT (10 * 1000) static void do_dbs_timer(void *data); @@ -136,7 +135,7 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, unsigned int input; int ret; ret = sscanf (buf, "%u", &input); - if (ret != 1 ) + if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) return -EINVAL; mutex_lock(&dbs_mutex); @@ -173,8 +172,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, ret = sscanf (buf, "%u", &input); mutex_lock(&dbs_mutex); - if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || - input < MIN_FREQUENCY_UP_THRESHOLD || + if (ret != 1 || input > 100 || input < 0 || input <= dbs_tuners_ins.down_threshold) { mutex_unlock(&dbs_mutex); return -EINVAL; @@ -194,8 +192,7 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused, ret = sscanf (buf, "%u", &input); mutex_lock(&dbs_mutex); - if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD || - input < MIN_FREQUENCY_DOWN_THRESHOLD || + if (ret != 1 || input > 100 || input < 0 || input >= dbs_tuners_ins.up_threshold) { mutex_unlock(&dbs_mutex); return -EINVAL; @@ -337,7 +334,6 @@ static void dbs_check_cpu(int cpu) */ /* Check for frequency increase */ - idle_ticks = UINT_MAX; for_each_cpu_mask(j, policy->cpus) { unsigned int tmp_idle_ticks, total_idle_ticks; @@ -357,7 +353,7 @@ static void dbs_check_cpu(int cpu) /* Scale idle ticks by 100 and compare with up and down ticks */ idle_ticks *= 100; up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) * - usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + usecs_to_jiffies(dbs_tuners_ins.sampling_rate); if (idle_ticks < up_idle_ticks) { down_skip[cpu] = 0; @@ -398,6 +394,7 @@ static void dbs_check_cpu(int cpu) struct cpu_dbs_info_s *j_dbs_info; j_dbs_info = &per_cpu(cpu_dbs_info, j); + /* Check for frequency decrease */ total_idle_ticks = j_dbs_info->prev_cpu_idle_up; tmp_idle_ticks = total_idle_ticks - j_dbs_info->prev_cpu_idle_down; @@ -414,12 +411,14 @@ static void dbs_check_cpu(int cpu) freq_down_sampling_rate = dbs_tuners_ins.sampling_rate * dbs_tuners_ins.sampling_down_factor; down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) * - usecs_to_jiffies(freq_down_sampling_rate); + usecs_to_jiffies(freq_down_sampling_rate); if (idle_ticks > down_idle_ticks) { - /* if we are already at the lowest speed then break out early + /* + * if we are already at the lowest speed then break out early * or if we 'cannot' reduce the speed as the user might want - * freq_step to be zero */ + * freq_step to be zero + */ if (requested_freq[cpu] == policy->min || dbs_tuners_ins.freq_step == 0) return; @@ -434,9 +433,8 @@ static void dbs_check_cpu(int cpu) if (requested_freq[cpu] < policy->min) requested_freq[cpu] = policy->min; - __cpufreq_driver_target(policy, - requested_freq[cpu], - CPUFREQ_RELATION_H); + __cpufreq_driver_target(policy, requested_freq[cpu], + CPUFREQ_RELATION_H); return; } } @@ -507,13 +505,16 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (dbs_enable == 1) { unsigned int latency; /* policy latency is in nS. Convert it to uS first */ + latency = policy->cpuinfo.transition_latency / 1000; + if (latency == 0) + latency = 1; - latency = policy->cpuinfo.transition_latency; - if (latency < 1000) - latency = 1000; - - def_sampling_rate = (latency / 1000) * + def_sampling_rate = latency * DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; + + if (def_sampling_rate < MIN_STAT_SAMPLING_RATE) + def_sampling_rate = MIN_STAT_SAMPLING_RATE; + dbs_tuners_ins.sampling_rate = def_sampling_rate; dbs_tuners_ins.ignore_nice = 0; dbs_tuners_ins.freq_step = 5; -- cgit v1.2.3-59-g8ed1b From e8a02572252f9115c2b8296c40fd8b985f06f872 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Wed, 22 Mar 2006 09:56:23 +0000 Subject: [PATCH] cpufreq_conservative: alter default responsiveness The sensible approach to making conservative less responsive than ondemand :) As mentioned in patch [1/4]. We do not want conservative to shoot through all the frequencies, its point (by default) is to slowly move through them. By default its ten times less responsive. Signed-off-by: Alexander Clouter Signed-off-by: Dominik Brodowski --- drivers/cpufreq/cpufreq_conservative.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index adecd31f6156..3ca3cf061642 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -509,7 +509,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (latency == 0) latency = 1; - def_sampling_rate = latency * + def_sampling_rate = 10 * latency * DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; if (def_sampling_rate < MIN_STAT_SAMPLING_RATE) -- cgit v1.2.3-59-g8ed1b From 08a28e2e98aa821cf6f15f8a267beb2f33377bb9 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Wed, 22 Mar 2006 09:59:16 +0000 Subject: [PATCH] cpufreq_conservative: make for_each_cpu() safe All these changes should make cpufreq_conservative safe in regards to the x86 for_each_cpu cpumask.h changes and whatnot. Whilst making it safe a number of pointless for loops related to the cpu mask's were removed. I was never comfortable with all those for loops, especially as the iteration is over the same data again and again for each CPU you had in a single poll, an O(n^2) outcome to frequency scaling. The approach I use is to assume by default no CPU's exist and it sets the requested_freq to zero as a kind of flag, the reasoning is in the source ;) If the CPU is queried and requested_freq is zero then it initialises the variable to current_freq and then continues as if nothing happened which should be the same net effect as before? Signed-off-by: Alexander Clouter Signed-off-by: Dominik Brodowski --- drivers/cpufreq/cpufreq_conservative.c | 91 ++++++++++++++++------------------ 1 file changed, 42 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 3ca3cf061642..7498f2506ade 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -294,31 +294,40 @@ static struct attribute_group dbs_attr_group = { static void dbs_check_cpu(int cpu) { unsigned int idle_ticks, up_idle_ticks, down_idle_ticks; + unsigned int tmp_idle_ticks, total_idle_ticks; unsigned int freq_step; unsigned int freq_down_sampling_rate; - static int down_skip[NR_CPUS]; - static int requested_freq[NR_CPUS]; - static unsigned short init_flag = 0; - struct cpu_dbs_info_s *this_dbs_info; - struct cpu_dbs_info_s *dbs_info; - + static unsigned short down_skip[NR_CPUS]; + static unsigned int requested_freq[NR_CPUS]; + static unsigned int init_flag = NR_CPUS; + struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info, cpu); struct cpufreq_policy *policy; - unsigned int j; - this_dbs_info = &per_cpu(cpu_dbs_info, cpu); if (!this_dbs_info->enable) return; - policy = this_dbs_info->cur_policy; - - if ( init_flag == 0 ) { - for_each_online_cpu(j) { - dbs_info = &per_cpu(cpu_dbs_info, j); - requested_freq[j] = dbs_info->cur_policy->cur; + if ( init_flag != 0 ) { + for_each_cpu(init_flag) { + down_skip[init_flag] = 0; + /* I doubt a CPU exists with a freq of 0hz :) */ + requested_freq[init_flag] = 0; } - init_flag = 1; + init_flag = 0; } + /* + * If its a freshly initialised cpu we setup requested_freq. This + * check could be avoided if we did not care about a first time + * stunted increase in CPU speed when there is a load. I feel we + * should be initialising this to something. The removal of a CPU + * is not a problem, after a short time the CPU should settle down + * to a 'natural' frequency. + */ + if (requested_freq[cpu] == 0) + requested_freq[cpu] = this_dbs_info->cur_policy->cur; + + policy = this_dbs_info->cur_policy; + /* * The default safe range is 20% to 80% * Every sampling_rate, we check @@ -335,20 +344,15 @@ static void dbs_check_cpu(int cpu) /* Check for frequency increase */ idle_ticks = UINT_MAX; - for_each_cpu_mask(j, policy->cpus) { - unsigned int tmp_idle_ticks, total_idle_ticks; - struct cpu_dbs_info_s *j_dbs_info; - j_dbs_info = &per_cpu(cpu_dbs_info, j); - /* Check for frequency increase */ - total_idle_ticks = get_cpu_idle_time(j); - tmp_idle_ticks = total_idle_ticks - - j_dbs_info->prev_cpu_idle_up; - j_dbs_info->prev_cpu_idle_up = total_idle_ticks; - - if (tmp_idle_ticks < idle_ticks) - idle_ticks = tmp_idle_ticks; - } + /* Check for frequency increase */ + total_idle_ticks = get_cpu_idle_time(cpu); + tmp_idle_ticks = total_idle_ticks - + this_dbs_info->prev_cpu_idle_up; + this_dbs_info->prev_cpu_idle_up = total_idle_ticks; + + if (tmp_idle_ticks < idle_ticks) + idle_ticks = tmp_idle_ticks; /* Scale idle ticks by 100 and compare with up and down ticks */ idle_ticks *= 100; @@ -357,13 +361,9 @@ static void dbs_check_cpu(int cpu) if (idle_ticks < up_idle_ticks) { down_skip[cpu] = 0; - for_each_cpu_mask(j, policy->cpus) { - struct cpu_dbs_info_s *j_dbs_info; + this_dbs_info->prev_cpu_idle_down = + this_dbs_info->prev_cpu_idle_up; - j_dbs_info = &per_cpu(cpu_dbs_info, j); - j_dbs_info->prev_cpu_idle_down = - j_dbs_info->prev_cpu_idle_up; - } /* if we are already at full speed then break out early */ if (requested_freq[cpu] == policy->max) return; @@ -388,21 +388,14 @@ static void dbs_check_cpu(int cpu) if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor) return; - idle_ticks = UINT_MAX; - for_each_cpu_mask(j, policy->cpus) { - unsigned int tmp_idle_ticks, total_idle_ticks; - struct cpu_dbs_info_s *j_dbs_info; + /* Check for frequency decrease */ + total_idle_ticks = this_dbs_info->prev_cpu_idle_up; + tmp_idle_ticks = total_idle_ticks - + this_dbs_info->prev_cpu_idle_down; + this_dbs_info->prev_cpu_idle_down = total_idle_ticks; - j_dbs_info = &per_cpu(cpu_dbs_info, j); - /* Check for frequency decrease */ - total_idle_ticks = j_dbs_info->prev_cpu_idle_up; - tmp_idle_ticks = total_idle_ticks - - j_dbs_info->prev_cpu_idle_down; - j_dbs_info->prev_cpu_idle_down = total_idle_ticks; - - if (tmp_idle_ticks < idle_ticks) - idle_ticks = tmp_idle_ticks; - } + if (tmp_idle_ticks < idle_ticks) + idle_ticks = tmp_idle_ticks; /* Scale idle ticks by 100 and compare with up and down ticks */ idle_ticks *= 100; @@ -491,7 +484,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, j_dbs_info = &per_cpu(cpu_dbs_info, j); j_dbs_info->cur_policy = policy; - j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j); + j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(cpu); j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; } -- cgit v1.2.3-59-g8ed1b From a159b82770ab84e1b5e0306fa65e158188492b16 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Wed, 22 Mar 2006 10:00:18 +0000 Subject: [PATCH] cpufreq_conservative: alternative initialise approach Venki, author of cpufreq_ondemand, came up with a neater way to remove the initialiser code from the main loop of my code and out to the point when the governor is actually initialised. Not only does it look but it also feels cleaner, plus its simpler to understand. It also saves a bunch of pointless conditional statements in the main loop. Signed-off-by: Alexander Clouter Signed-off-by: Dominik Brodowski --- drivers/cpufreq/cpufreq_conservative.c | 55 +++++++++++----------------------- 1 file changed, 18 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 7498f2506ade..a152d2c46be7 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -65,6 +65,8 @@ struct cpu_dbs_info_s { unsigned int prev_cpu_idle_up; unsigned int prev_cpu_idle_down; unsigned int enable; + unsigned int down_skip; + unsigned int requested_freq; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); @@ -297,35 +299,12 @@ static void dbs_check_cpu(int cpu) unsigned int tmp_idle_ticks, total_idle_ticks; unsigned int freq_step; unsigned int freq_down_sampling_rate; - static unsigned short down_skip[NR_CPUS]; - static unsigned int requested_freq[NR_CPUS]; - static unsigned int init_flag = NR_CPUS; struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info, cpu); struct cpufreq_policy *policy; if (!this_dbs_info->enable) return; - if ( init_flag != 0 ) { - for_each_cpu(init_flag) { - down_skip[init_flag] = 0; - /* I doubt a CPU exists with a freq of 0hz :) */ - requested_freq[init_flag] = 0; - } - init_flag = 0; - } - - /* - * If its a freshly initialised cpu we setup requested_freq. This - * check could be avoided if we did not care about a first time - * stunted increase in CPU speed when there is a load. I feel we - * should be initialising this to something. The removal of a CPU - * is not a problem, after a short time the CPU should settle down - * to a 'natural' frequency. - */ - if (requested_freq[cpu] == 0) - requested_freq[cpu] = this_dbs_info->cur_policy->cur; - policy = this_dbs_info->cur_policy; /* @@ -360,12 +339,12 @@ static void dbs_check_cpu(int cpu) usecs_to_jiffies(dbs_tuners_ins.sampling_rate); if (idle_ticks < up_idle_ticks) { - down_skip[cpu] = 0; + this_dbs_info->down_skip = 0; this_dbs_info->prev_cpu_idle_down = this_dbs_info->prev_cpu_idle_up; /* if we are already at full speed then break out early */ - if (requested_freq[cpu] == policy->max) + if (this_dbs_info->requested_freq == policy->max) return; freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100; @@ -374,18 +353,18 @@ static void dbs_check_cpu(int cpu) if (unlikely(freq_step == 0)) freq_step = 5; - requested_freq[cpu] += freq_step; - if (requested_freq[cpu] > policy->max) - requested_freq[cpu] = policy->max; + this_dbs_info->requested_freq += freq_step; + if (this_dbs_info->requested_freq > policy->max) + this_dbs_info->requested_freq = policy->max; - __cpufreq_driver_target(policy, requested_freq[cpu], + __cpufreq_driver_target(policy, this_dbs_info->requested_freq, CPUFREQ_RELATION_H); return; } /* Check for frequency decrease */ - down_skip[cpu]++; - if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor) + this_dbs_info->down_skip++; + if (this_dbs_info->down_skip < dbs_tuners_ins.sampling_down_factor) return; /* Check for frequency decrease */ @@ -399,7 +378,7 @@ static void dbs_check_cpu(int cpu) /* Scale idle ticks by 100 and compare with up and down ticks */ idle_ticks *= 100; - down_skip[cpu] = 0; + this_dbs_info->down_skip = 0; freq_down_sampling_rate = dbs_tuners_ins.sampling_rate * dbs_tuners_ins.sampling_down_factor; @@ -412,7 +391,7 @@ static void dbs_check_cpu(int cpu) * or if we 'cannot' reduce the speed as the user might want * freq_step to be zero */ - if (requested_freq[cpu] == policy->min + if (this_dbs_info->requested_freq == policy->min || dbs_tuners_ins.freq_step == 0) return; @@ -422,11 +401,11 @@ static void dbs_check_cpu(int cpu) if (unlikely(freq_step == 0)) freq_step = 5; - requested_freq[cpu] -= freq_step; - if (requested_freq[cpu] < policy->min) - requested_freq[cpu] = policy->min; + this_dbs_info->requested_freq -= freq_step; + if (this_dbs_info->requested_freq < policy->min) + this_dbs_info->requested_freq = policy->min; - __cpufreq_driver_target(policy, requested_freq[cpu], + __cpufreq_driver_target(policy, this_dbs_info->requested_freq, CPUFREQ_RELATION_H); return; } @@ -489,6 +468,8 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, = j_dbs_info->prev_cpu_idle_up; } this_dbs_info->enable = 1; + this_dbs_info->down_skip = 0; + this_dbs_info->requested_freq = policy->cur; sysfs_create_group(&policy->kobj, &dbs_attr_group); dbs_enable++; /* -- cgit v1.2.3-59-g8ed1b From ff8c288d7d1a368b663058cdee1ea0adcdef2fa2 Mon Sep 17 00:00:00 2001 From: Eric Piel Date: Fri, 10 Mar 2006 11:34:16 +0200 Subject: [PATCH] cpufreq_ondemand: Warn if it cannot run due to too long transition latency Display a warning if the ondemand governor can not be selected due to a transition latency of the cpufreq driver which is too long. Signed-off-by: Eric Piel Acked-by: Venkatesh Pallipadi Signed-off-by: Dominik Brodowski --- drivers/cpufreq/cpufreq_ondemand.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 69aa1db8336c..6430489db6f4 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -395,8 +395,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, return -EINVAL; if (policy->cpuinfo.transition_latency > - (TRANSITION_LATENCY_LIMIT * 1000)) + (TRANSITION_LATENCY_LIMIT * 1000)) { + printk(KERN_WARNING "ondemand governor failed to load " + "due to too long transition latency\n"); return -EINVAL; + } if (this_dbs_info->enable) /* Already enabled */ break; -- cgit v1.2.3-59-g8ed1b From 9cbad61b41f0b6f0a4c600fe96d8292ffd592b50 Mon Sep 17 00:00:00 2001 From: Eric Piel Date: Fri, 10 Mar 2006 11:35:27 +0200 Subject: [PATCH] cpufreq_ondemand: keep ignore_nice_load value when it is reselected Keep the value of ignore_nice_load of the ondemand governor even after the governor has been deselected and selected back. This is the behavior of the other exported values of the ondemand governor and it's much more user-friendly. Signed-off-by: Eric Piel Acked-by: Venkatesh Pallipadi Signed-off-by: Dominik Brodowski --- drivers/cpufreq/cpufreq_ondemand.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 6430489db6f4..cd846f57147e 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -84,6 +84,7 @@ struct dbs_tuners { static struct dbs_tuners dbs_tuners_ins = { .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, + .ignore_nice = 0, }; static inline unsigned int get_cpu_idle_time(unsigned int cpu) @@ -434,8 +435,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, def_sampling_rate = MIN_STAT_SAMPLING_RATE; dbs_tuners_ins.sampling_rate = def_sampling_rate; - dbs_tuners_ins.ignore_nice = 0; - dbs_timer_init(); } -- cgit v1.2.3-59-g8ed1b From 7c9d8c0e84d395a01289ebd1597758939a875a86 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 26 Mar 2006 11:11:03 +0200 Subject: [PATCH] cpufreq_ondemand: add range check Assert that cpufreq_target is, at least, called with the minimum frequency allowed by this policy, not something lower. It triggered problems on ARM. Signed-off-by: Dominik Brodowski --- drivers/cpufreq/cpufreq_ondemand.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index cd846f57147e..956d121cb161 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -351,6 +351,9 @@ static void dbs_check_cpu(int cpu) freq_next = (freq_next * policy->cur) / (dbs_tuners_ins.up_threshold - 10); + if (freq_next < policy->min) + freq_next = policy->min; + if (freq_next <= ((policy->cur * 95) / 100)) __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); } -- cgit v1.2.3-59-g8ed1b From 373ebfbf17a8ecad304f65cb92c4d2d10adc0a19 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Sun, 26 Mar 2006 18:15:12 +0200 Subject: BUG_ON() Conversion in drivers/mtd/ this changes if() BUG(); constructs to BUG_ON() which is cleaner, contains unlikely() and can better optimized away. Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/mtd/maps/dilnetpc.c | 8 ++++---- drivers/mtd/mtd_blkdevs.c | 3 +-- drivers/mtd/mtdconcat.c | 6 ++---- 3 files changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c index b51c757817d8..efb221692641 100644 --- a/drivers/mtd/maps/dilnetpc.c +++ b/drivers/mtd/maps/dilnetpc.c @@ -218,8 +218,8 @@ static void dnp_set_vpp(struct map_info *not_used, int on) { if(--vpp_counter == 0) setcsc(CSC_RBWR, getcsc(CSC_RBWR) | 0x4); - else if(vpp_counter < 0) - BUG(); + else + BUG_ON(vpp_counter < 0); } spin_unlock_irq(&dnpc_spin); } @@ -240,8 +240,8 @@ static void adnp_set_vpp(struct map_info *not_used, int on) { if(--vpp_counter == 0) setcsc(CSC_RBWR, getcsc(CSC_RBWR) | 0x8); - else if(vpp_counter < 0) - BUG(); + else + BUG_ON(vpp_counter < 0); } spin_unlock_irq(&dnpc_spin); } diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 7f3ff500b68e..840dd66ce2dc 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -450,8 +450,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) kfree(tr->blkcore_priv); - if (!list_empty(&tr->devs)) - BUG(); + BUG_ON(!list_empty(&tr->devs)); return 0; } diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index b1bf8c411de7..9af840364a74 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -477,8 +477,7 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) } /* must never happen since size limit has been verified above */ - if (i >= concat->num_subdev) - BUG(); + BUG_ON(i >= concat->num_subdev); /* now do the erase: */ err = 0; @@ -500,8 +499,7 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) if ((err = concat_dev_erase(subdev, erase))) { /* sanity check: should never happen since * block alignment has been checked above */ - if (err == -EINVAL) - BUG(); + BUG_ON(err == -EINVAL); if (erase->fail_addr != 0xffffffff) instr->fail_addr = erase->fail_addr + offset; break; -- cgit v1.2.3-59-g8ed1b From 56ee48277fa214b3b7b0fd91e7fd3464e12597de Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Sun, 26 Mar 2006 18:17:21 +0200 Subject: BUG_ON() Conversion in drivers/char this changes if() BUG(); constructs to BUG_ON() which is cleaner, contains unlikely() and can better optimized away. Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/char/epca.c | 3 +-- drivers/char/tty_io.c | 11 ++++------- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 765c5c108bf4..9cad8501d62c 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -486,8 +486,7 @@ static void pc_close(struct tty_struct * tty, struct file * filp) } /* End channel is open more than once */ /* Port open only once go ahead with shutdown & reset */ - if (ch->count < 0) - BUG(); + BUG_ON(ch->count < 0); /* --------------------------------------------------------------- Let the rest of the driver know the channel is being closed. diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 48d795bb8c4b..811dadb9ce3e 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -543,14 +543,12 @@ void tty_ldisc_put(int disc) struct tty_ldisc *ld; unsigned long flags; - if (disc < N_TTY || disc >= NR_LDISCS) - BUG(); + BUG_ON(disc < N_TTY || disc >= NR_LDISCS); spin_lock_irqsave(&tty_ldisc_lock, flags); ld = &tty_ldiscs[disc]; - if(ld->refcount == 0) - BUG(); - ld->refcount --; + BUG_ON(ld->refcount == 0); + ld->refcount--; module_put(ld->owner); spin_unlock_irqrestore(&tty_ldisc_lock, flags); } @@ -645,8 +643,7 @@ void tty_ldisc_deref(struct tty_ldisc *ld) { unsigned long flags; - if(ld == NULL) - BUG(); + BUG_ON(ld == NULL); spin_lock_irqsave(&tty_ldisc_lock, flags); if(ld->refcount == 0) -- cgit v1.2.3-59-g8ed1b From 6dd44a74469c203c5106ada2082c46267b4ac674 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Sun, 26 Mar 2006 18:19:26 +0200 Subject: BUG_ON() Conversion in drivers/isdn this changes if() BUG(); constructs to BUG_ON() which is cleaner, contains unlikely() and can better optimized away. Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/isdn/hisax/hisax_fcpcipnp.c | 7 ++----- drivers/isdn/hisax/hisax_isac.c | 9 +++------ drivers/isdn/hisax/st5481_b.c | 4 +--- drivers/isdn/hisax/st5481_d.c | 4 +--- drivers/isdn/i4l/isdn_ppp.c | 6 ++---- 5 files changed, 9 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c index dc7ef957e897..dbcca287ee2c 100644 --- a/drivers/isdn/hisax/hisax_fcpcipnp.c +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c @@ -387,8 +387,7 @@ static void hdlc_fill_fifo(struct fritz_bcs *bcs) DBG(0x40, "hdlc_fill_fifo"); - if (skb->len == 0) - BUG(); + BUG_ON(skb->len == 0); bcs->ctrl.sr.cmd &= ~HDLC_CMD_XME; if (bcs->tx_skb->len > bcs->fifo_size) { @@ -630,9 +629,7 @@ static void fritz_b_l2l1(struct hisax_if *ifc, int pr, void *arg) switch (pr) { case PH_DATA | REQUEST: - if (bcs->tx_skb) - BUG(); - + BUG_ON(bcs->tx_skb); bcs->tx_skb = skb; DBG_SKB(1, skb); hdlc_fill_fifo(bcs); diff --git a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c index f4972f6c1f5d..81eac344bb03 100644 --- a/drivers/isdn/hisax/hisax_isac.c +++ b/drivers/isdn/hisax/hisax_isac.c @@ -476,12 +476,10 @@ static void isac_fill_fifo(struct isac *isac) unsigned char cmd; u_char *ptr; - if (!isac->tx_skb) - BUG(); + BUG_ON(!isac->tx_skb); count = isac->tx_skb->len; - if (count <= 0) - BUG(); + BUG_ON(count <= 0); DBG(DBG_IRQ, "count %d", count); @@ -859,8 +857,7 @@ void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) dev_kfree_skb(skb); break; } - if (isac->tx_skb) - BUG(); + BUG_ON(isac->tx_skb); isac->tx_skb = skb; isac_fill_fifo(isac); diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index 657817a591fe..22fd5db18d48 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c @@ -356,9 +356,7 @@ void st5481_b_l2l1(struct hisax_if *ifc, int pr, void *arg) switch (pr) { case PH_DATA | REQUEST: - if (bcs->b_out.tx_skb) - BUG(); - + BUG_ON(bcs->b_out.tx_skb); bcs->b_out.tx_skb = skb; break; case PH_ACTIVATE | REQUEST: diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c index 941f7022ada1..493dc94992e5 100644 --- a/drivers/isdn/hisax/st5481_d.c +++ b/drivers/isdn/hisax/st5481_d.c @@ -596,9 +596,7 @@ void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) break; case PH_DATA | REQUEST: DBG(2, "PH_DATA REQUEST len %d", skb->len); - if (adapter->d_out.tx_skb) - BUG(); - + BUG_ON(adapter->d_out.tx_skb); adapter->d_out.tx_skb = skb; FsmEvent(&adapter->d_out.fsm, EV_DOUT_START_XMIT, NULL); break; diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index b9fed8a3bcc6..a0927d1b7a0c 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -974,8 +974,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf int slot; int proto; - if (net_dev->local->master) - BUG(); // we're called with the master device always + BUG_ON(net_dev->local->master); // we're called with the master device always slot = lp->ppp_slot; if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { @@ -2527,8 +2526,7 @@ static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struc printk(KERN_DEBUG "ippp: no decompressor defined!\n"); return skb; } - if (!stat) // if we have a compressor, stat has been set as well - BUG(); + BUG_ON(!stat); // if we have a compressor, stat has been set as well if((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG) ) { // compressed packets are compressed by their protocol type -- cgit v1.2.3-59-g8ed1b From c163c7293eb68bf6c0c824d122a2192b9f129193 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Sun, 26 Mar 2006 18:21:58 +0200 Subject: BUG_ON() Conversion in md/dm-path-selector.c this changes if() BUG(); constructs to BUG_ON() which is cleaner and can better optimized away Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/md/dm-path-selector.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-path-selector.c b/drivers/md/dm-path-selector.c index a28c1c2b4ef5..f10a0c89b3f4 100644 --- a/drivers/md/dm-path-selector.c +++ b/drivers/md/dm-path-selector.c @@ -86,8 +86,7 @@ void dm_put_path_selector(struct path_selector_type *pst) if (--psi->use == 0) module_put(psi->pst.module); - if (psi->use < 0) - BUG(); + BUG_ON(psi->use < 0); out: up_read(&_ps_lock); -- cgit v1.2.3-59-g8ed1b From 547bc92649345af6014578a64b27cc5787617935 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Sun, 26 Mar 2006 18:22:50 +0200 Subject: BUG_ON() Conversion in md/dm-table.c this changes if() BUG(); constructs to BUG_ON() which is cleaner and can better optimized away Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/md/dm-table.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 9b1e2f5ca630..907b08ddb783 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -352,8 +352,7 @@ static int open_dev(struct dm_dev *d, dev_t dev) int r; - if (d->bdev) - BUG(); + BUG_ON(d->bdev); bdev = open_by_devnum(dev, d->mode); if (IS_ERR(bdev)) @@ -427,8 +426,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, struct dm_dev *dd; unsigned int major, minor; - if (!t) - BUG(); + BUG_ON(!t); if (sscanf(path, "%u:%u", &major, &minor) == 2) { /* Extract the major/minor numbers */ -- cgit v1.2.3-59-g8ed1b From fddaaae16ba4d9f4d392a9ef94616d9d22485571 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Sun, 26 Mar 2006 18:23:47 +0200 Subject: BUG_ON() Conversion in input/serio/hp_sdc_mlc.c this changes if() BUG(); constructs to BUG_ON() which is cleaner and can better optimized away Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/input/serio/hp_sdc_mlc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c index 1c9426fd5205..aa4a8a4ccfdb 100644 --- a/drivers/input/serio/hp_sdc_mlc.c +++ b/drivers/input/serio/hp_sdc_mlc.c @@ -270,9 +270,10 @@ static void hp_sdc_mlc_out (hil_mlc *mlc) { do_control: priv->emtestmode = mlc->opacket & HIL_CTRL_TEST; - if ((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE) { - BUG(); /* we cannot emulate this, it should not be used. */ - } + + /* we cannot emulate this, it should not be used. */ + BUG_ON((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE); + if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only; if (mlc->opacket & HIL_CTRL_APE) { BUG(); /* Should not send command/data after engaging APE */ -- cgit v1.2.3-59-g8ed1b From 606f44228e257ea1e35557c2fec7133cca634096 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Sun, 26 Mar 2006 18:33:07 +0200 Subject: BUG_ON() Conversion in drivers/s390/block/dasd_devmap.c this changes if() BUG(); constructs to BUG_ON() which is cleaner, contains unlikely() and can better optimized away. Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/s390/block/dasd_devmap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 2f720108a7e0..c1c6f1381150 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -437,8 +437,7 @@ dasd_forget_ranges(void) spin_lock(&dasd_devmap_lock); for (i = 0; i < 256; i++) { list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) { - if (devmap->device != NULL) - BUG(); + BUG_ON(devmap->device != NULL); list_del(&devmap->list); kfree(devmap); } @@ -547,8 +546,7 @@ dasd_delete_device(struct dasd_device *device) /* First remove device pointer from devmap. */ devmap = dasd_find_busid(device->cdev->dev.bus_id); - if (IS_ERR(devmap)) - BUG(); + BUG_ON(IS_ERR(devmap)); spin_lock(&dasd_devmap_lock); if (devmap->device != device) { spin_unlock(&dasd_devmap_lock); -- cgit v1.2.3-59-g8ed1b From 6dc659d813fdd1789e605d69d0b8762d284e8c60 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 26 Mar 2006 01:36:54 -0800 Subject: [PATCH] drivers/block/floppy.c: dont free_irq() from irq context free_irq() should not be executed from softirq context. Found by the lock validator. The fix is to push fd_free_irq() into keventd. The code validates fine with this patch applied. (akpm: this is revolting, but so is floppy.c) [akpm@osdl.org: added flush_scheduled_work()] Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/floppy.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 840919bba76c..d3ad9081697e 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -250,6 +250,18 @@ static int irqdma_allocated; #include /* for the compatibility eject ioctl */ #include +/* + * Interrupt freeing also means /proc VFS work - dont do it + * from interrupt context. We push this work into keventd: + */ +static void fd_free_irq_fn(void *data) +{ + fd_free_irq(); +} + +static DECLARE_WORK(fd_free_irq_work, fd_free_irq_fn, NULL); + + static struct request *current_req; static struct request_queue *floppy_queue; static void do_fd_request(request_queue_t * q); @@ -4433,6 +4445,13 @@ static int floppy_grab_irq_and_dma(void) return 0; } spin_unlock_irqrestore(&floppy_usage_lock, flags); + + /* + * We might have scheduled a free_irq(), wait it to + * drain first: + */ + flush_scheduled_work(); + if (fd_request_irq()) { DPRINT("Unable to grab IRQ%d for the floppy driver\n", FLOPPY_IRQ); @@ -4522,7 +4541,7 @@ static void floppy_release_irq_and_dma(void) if (irqdma_allocated) { fd_disable_dma(); fd_free_dma(); - fd_free_irq(); + schedule_work(&fd_free_irq_work); irqdma_allocated = 0; } set_dor(0, ~0, 8); @@ -4633,6 +4652,8 @@ void cleanup_module(void) /* eject disk, if any */ fd_eject(0); + flush_scheduled_work(); /* fd_free_irq() might be pending */ + wait_for_completion(&device_release); } -- cgit v1.2.3-59-g8ed1b From 136939a2b5aa4302281215745ccd567e1df2e8d4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sun, 26 Mar 2006 01:37:05 -0800 Subject: [PATCH] EFI, /dev/mem: simplify efi_mem_attribute_range() Pass the size, not a pointer to the size, to efi_mem_attribute_range(). This function validates memory regions for the /dev/mem read/write/mmap paths. The pointer allows arches to reduce the size of the range, but I think that's unnecessary complexity. Simplifying it will let me use efi_mem_attribute_range() to improve the ia64 ioremap() implementation. Signed-off-by: Bjorn Helgaas Cc: Matt Domsch Cc: "Tolentino, Matthew E" Cc: "Brown, Len" Cc: Andi Kleen Acked-by: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/kernel/efi.c | 41 ++++++++++++++++++++--------------------- drivers/char/mem.c | 18 ++++++------------ include/asm-ia64/io.h | 4 ++-- include/linux/efi.h | 2 ++ 4 files changed, 30 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 9990320b6f9a..2993748c13df 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -677,27 +677,34 @@ 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. + * access size bytes at phys_addr with the specified attribute. */ -static int -efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr) +int +efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, u64 attr) { + unsigned long end = phys_addr + size; efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); - unsigned long md_end; - if (!md || (md->attribute & attr) != 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. + */ + if (!md || (md->attribute & attr) != attr) { + if (attr == EFI_MEMORY_UC && !efi_memmap_has_mmio()) + return 1; return 0; + } do { - md_end = efi_md_end(md); - if (phys_addr + *size <= md_end) + unsigned long md_end = efi_md_end(md); + + if (end <= md_end) return 1; md = efi_memory_descriptor(md_end); - if (!md || (md->attribute & attr) != attr) { - *size = md_end - phys_addr; - return 1; - } + if (!md || (md->attribute & attr) != attr) + return 0; } while (md); return 0; } @@ -708,7 +715,7 @@ efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr) * control access size. */ int -valid_phys_addr_range (unsigned long phys_addr, unsigned long *size) +valid_phys_addr_range (unsigned long phys_addr, unsigned long size) { return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB); } @@ -723,7 +730,7 @@ valid_phys_addr_range (unsigned long phys_addr, unsigned long *size) * 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) +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; @@ -731,14 +738,6 @@ valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size) if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC)) return 1; - /* - * Some firmware doesn't report MMIO regions in the EFI memory map. - * The Intel BigSur (a.k.a. HP i2000) has this problem. In this - * case, we can't use the EFI memory map to validate mmap requests. - */ - if (!efi_memmap_has_mmio()) - return 1; - return 0; } diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 26d0116b48d4..5245ba1649ed 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -88,21 +88,15 @@ static inline int uncached_access(struct file *file, unsigned long addr) } #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE -static inline int valid_phys_addr_range(unsigned long addr, size_t *count) +static inline int valid_phys_addr_range(unsigned long addr, size_t count) { - unsigned long end_mem; - - end_mem = __pa(high_memory); - if (addr >= end_mem) + if (addr + count > __pa(high_memory)) return 0; - if (*count > end_mem - addr) - *count = end_mem - addr; - return 1; } -static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t *size) +static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t size) { return 1; } @@ -119,7 +113,7 @@ static ssize_t read_mem(struct file * file, char __user * buf, ssize_t read, sz; char *ptr; - if (!valid_phys_addr_range(p, &count)) + if (!valid_phys_addr_range(p, count)) return -EFAULT; read = 0; #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED @@ -177,7 +171,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf, unsigned long copied; void *ptr; - if (!valid_phys_addr_range(p, &count)) + if (!valid_phys_addr_range(p, count)) return -EFAULT; written = 0; @@ -249,7 +243,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) { size_t size = vma->vm_end - vma->vm_start; - if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, &size)) + if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, size)) return -EINVAL; vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h index 0d9bcc36f2a9..acba019b08e9 100644 --- a/include/asm-ia64/io.h +++ b/include/asm-ia64/io.h @@ -88,8 +88,8 @@ phys_to_virt (unsigned long address) } #define ARCH_HAS_VALID_PHYS_ADDR_RANGE -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); +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); /* * The following two macros are deprecated and scheduled for removal. diff --git a/include/linux/efi.h b/include/linux/efi.h index c7c5dd316182..d15725470aa4 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -292,6 +292,8 @@ 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 int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, + u64 attr); extern int __init efi_uart_console_only (void); extern void efi_initialize_iomem_resources(struct resource *code_resource, struct resource *data_resource); -- cgit v1.2.3-59-g8ed1b From b2c99e3c70d77fb194df5aa1642030080d28ea48 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sun, 26 Mar 2006 01:37:08 -0800 Subject: [PATCH] EFI: keep physical table addresses in efi structure Almost all users of the table addresses from the EFI system table want physical addresses. So rather than doing the pa->va->pa conversion, just keep physical addresses in struct efi. This fixes a DMI bug: the efi structure contained the physical SMBIOS address on x86 but the virtual address on ia64, so dmi_scan_machine() used ioremap() on a virtual address on ia64. This is essentially the same as an earlier patch by Matt Tolentino: http://marc.theaimsgroup.com/?l=linux-kernel&m=112130292316281&w=2 except that this changes all table addresses, not just ACPI addresses. Matt's original patch was backed out because it caused MCAs on HP sx1000 systems. That problem is resolved by the ioremap() attribute checking added for ia64. Signed-off-by: Bjorn Helgaas Cc: Matt Domsch Cc: "Tolentino, Matthew E" Cc: "Brown, Len" Cc: Andi Kleen Acked-by: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/acpi/boot.c | 8 ++++---- arch/i386/kernel/dmi_scan.c | 4 ++-- arch/i386/kernel/efi.c | 21 +++++++++++++++------ arch/ia64/kernel/acpi.c | 6 +++--- arch/ia64/kernel/efi.c | 21 +++++++++++++++------ arch/ia64/kernel/setup.c | 2 +- arch/ia64/sn/kernel/setup.c | 5 +++-- drivers/acpi/osl.c | 10 ++++------ drivers/firmware/efivars.c | 28 ++++++++++++++-------------- drivers/firmware/pcdp.c | 19 ++++++++++++------- include/asm-ia64/sn/sn_sal.h | 2 +- include/linux/efi.h | 18 ++++++++++-------- 12 files changed, 84 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index f1a21945963d..033066176b3e 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -668,10 +668,10 @@ unsigned long __init acpi_find_rsdp(void) unsigned long rsdp_phys = 0; if (efi_enabled) { - if (efi.acpi20) - return __pa(efi.acpi20); - else if (efi.acpi) - return __pa(efi.acpi); + if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) + return efi.acpi20; + else if (efi.acpi != EFI_INVALID_TABLE_ADDR) + return efi.acpi; } /* * Scan memory looking for the RSDP signature. First search EBDA (low diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c index c032f9e06bb6..170d4c9f9bc3 100644 --- a/arch/i386/kernel/dmi_scan.c +++ b/arch/i386/kernel/dmi_scan.c @@ -217,14 +217,14 @@ void __init dmi_scan_machine(void) int rc; if (efi_enabled) { - if (!efi.smbios) + if (efi.smbios == EFI_INVALID_TABLE_ADDR) goto out; /* This is called as a core_initcall() because it isn't * needed during early boot. This also means we can * iounmap the space when we're done with it. */ - p = dmi_ioremap((unsigned long)efi.smbios, 32); + p = dmi_ioremap(efi.smbios, 32); if (p == NULL) goto out; diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index 7ec6cfa01fb3..c224c2aebbab 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c @@ -381,29 +381,38 @@ void __init efi_init(void) if (config_tables == NULL) printk(KERN_ERR PFX "Could not map EFI Configuration Table!\n"); + efi.mps = EFI_INVALID_TABLE_ADDR; + efi.acpi = EFI_INVALID_TABLE_ADDR; + efi.acpi20 = EFI_INVALID_TABLE_ADDR; + efi.smbios = EFI_INVALID_TABLE_ADDR; + efi.sal_systab = EFI_INVALID_TABLE_ADDR; + efi.boot_info = EFI_INVALID_TABLE_ADDR; + efi.hcdp = EFI_INVALID_TABLE_ADDR; + efi.uga = EFI_INVALID_TABLE_ADDR; + for (i = 0; i < num_config_tables; i++) { if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { - efi.mps = (void *)config_tables[i].table; + efi.mps = config_tables[i].table; printk(KERN_INFO " MPS=0x%lx ", config_tables[i].table); } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { - efi.acpi20 = __va(config_tables[i].table); + efi.acpi20 = config_tables[i].table; printk(KERN_INFO " ACPI 2.0=0x%lx ", config_tables[i].table); } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { - efi.acpi = __va(config_tables[i].table); + efi.acpi = config_tables[i].table; printk(KERN_INFO " ACPI=0x%lx ", config_tables[i].table); } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { - efi.smbios = (void *) config_tables[i].table; + efi.smbios = config_tables[i].table; printk(KERN_INFO " SMBIOS=0x%lx ", config_tables[i].table); } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { - efi.hcdp = (void *)config_tables[i].table; + efi.hcdp = config_tables[i].table; printk(KERN_INFO " HCDP=0x%lx ", config_tables[i].table); } else if (efi_guidcmp(config_tables[i].guid, UGA_IO_PROTOCOL_GUID) == 0) { - efi.uga = (void *)config_tables[i].table; + efi.uga = config_tables[i].table; printk(KERN_INFO " UGA=0x%lx ", config_tables[i].table); } } diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index a4e218ce2edb..58c93a30348c 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -651,9 +651,9 @@ unsigned long __init acpi_find_rsdp(void) { unsigned long rsdp_phys = 0; - if (efi.acpi20) - rsdp_phys = __pa(efi.acpi20); - else if (efi.acpi) + if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) + rsdp_phys = efi.acpi20; + else if (efi.acpi != EFI_INVALID_TABLE_ADDR) printk(KERN_WARNING PREFIX "v1.0/r0.71 tables no longer supported\n"); return rsdp_phys; diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 2993748c13df..12cfedce73b1 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -458,24 +458,33 @@ efi_init (void) printk(KERN_INFO "EFI v%u.%.02u by %s:", efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); + efi.mps = EFI_INVALID_TABLE_ADDR; + efi.acpi = EFI_INVALID_TABLE_ADDR; + efi.acpi20 = EFI_INVALID_TABLE_ADDR; + efi.smbios = EFI_INVALID_TABLE_ADDR; + efi.sal_systab = EFI_INVALID_TABLE_ADDR; + efi.boot_info = EFI_INVALID_TABLE_ADDR; + efi.hcdp = EFI_INVALID_TABLE_ADDR; + efi.uga = EFI_INVALID_TABLE_ADDR; + for (i = 0; i < (int) efi.systab->nr_tables; i++) { if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { - efi.mps = __va(config_tables[i].table); + efi.mps = config_tables[i].table; printk(" MPS=0x%lx", config_tables[i].table); } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { - efi.acpi20 = __va(config_tables[i].table); + efi.acpi20 = config_tables[i].table; printk(" ACPI 2.0=0x%lx", config_tables[i].table); } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { - efi.acpi = __va(config_tables[i].table); + efi.acpi = config_tables[i].table; printk(" ACPI=0x%lx", config_tables[i].table); } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { - efi.smbios = __va(config_tables[i].table); + efi.smbios = config_tables[i].table; printk(" SMBIOS=0x%lx", config_tables[i].table); } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { - efi.sal_systab = __va(config_tables[i].table); + efi.sal_systab = config_tables[i].table; printk(" SALsystab=0x%lx", config_tables[i].table); } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { - efi.hcdp = __va(config_tables[i].table); + efi.hcdp = config_tables[i].table; printk(" HCDP=0x%lx", config_tables[i].table); } } diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index a4421a66ea5b..e4dfda1eb7dd 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -434,7 +434,7 @@ setup_arch (char **cmdline_p) find_memory(); /* process SAL system table: */ - ia64_sal_init(efi.sal_systab); + ia64_sal_init(__va(efi.sal_systab)); ia64_setup_printk_clock(); diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 8b6d5c844708..30988dfbddff 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -327,10 +327,11 @@ sn_scan_pcdp(void) struct pcdp_interface_pci if_pci; extern struct efi efi; - pcdp = efi.hcdp; - if (! pcdp) + if (efi.hcdp == EFI_INVALID_TABLE_ADDR) return; /* no hcdp/pcdp table */ + pcdp = __va(efi.hcdp); + if (pcdp->rev < 3) return; /* only support PCDP (rev >= 3) */ diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index ac5bbaedac1b..fc8a3bce6cbb 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -156,12 +156,10 @@ acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr) { if (efi_enabled) { addr->pointer_type = ACPI_PHYSICAL_POINTER; - if (efi.acpi20) - addr->pointer.physical = - (acpi_physical_address) virt_to_phys(efi.acpi20); - else if (efi.acpi) - addr->pointer.physical = - (acpi_physical_address) virt_to_phys(efi.acpi); + if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) + addr->pointer.physical = efi.acpi20; + else if (efi.acpi != EFI_INVALID_TABLE_ADDR) + addr->pointer.physical = efi.acpi; else { printk(KERN_ERR PREFIX "System description tables not found\n"); diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 343379f23a53..9b7e4d52ffd4 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -568,20 +568,20 @@ systab_read(struct subsystem *entry, char *buf) if (!entry || !buf) return -EINVAL; - if (efi.mps) - str += sprintf(str, "MPS=0x%lx\n", __pa(efi.mps)); - if (efi.acpi20) - str += sprintf(str, "ACPI20=0x%lx\n", __pa(efi.acpi20)); - if (efi.acpi) - str += sprintf(str, "ACPI=0x%lx\n", __pa(efi.acpi)); - if (efi.smbios) - str += sprintf(str, "SMBIOS=0x%lx\n", __pa(efi.smbios)); - if (efi.hcdp) - str += sprintf(str, "HCDP=0x%lx\n", __pa(efi.hcdp)); - if (efi.boot_info) - str += sprintf(str, "BOOTINFO=0x%lx\n", __pa(efi.boot_info)); - if (efi.uga) - str += sprintf(str, "UGA=0x%lx\n", __pa(efi.uga)); + if (efi.mps != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "MPS=0x%lx\n", efi.mps); + if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20); + if (efi.acpi != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); + if (efi.smbios != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); + if (efi.hcdp != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); + if (efi.boot_info != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info); + if (efi.uga != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "UGA=0x%lx\n", efi.uga); return str - buf; } diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c index ae1fb45dbb40..c37baf9448bc 100644 --- a/drivers/firmware/pcdp.c +++ b/drivers/firmware/pcdp.c @@ -89,19 +89,20 @@ efi_setup_pcdp_console(char *cmdline) struct pcdp_uart *uart; struct pcdp_device *dev, *end; int i, serial = 0; + int rc = -ENODEV; - pcdp = efi.hcdp; - if (!pcdp) + if (efi.hcdp == EFI_INVALID_TABLE_ADDR) return -ENODEV; - printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, __pa(pcdp)); + pcdp = ioremap(efi.hcdp, 4096); + printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp); if (strstr(cmdline, "console=hcdp")) { if (pcdp->rev < 3) serial = 1; } else if (strstr(cmdline, "console=")) { printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n"); - return -ENODEV; + goto out; } if (pcdp->rev < 3 && efi_uart_console_only()) @@ -110,7 +111,8 @@ efi_setup_pcdp_console(char *cmdline) for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) { if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) { if (uart->type == PCDP_CONSOLE_UART) { - return setup_serial_console(uart); + rc = setup_serial_console(uart); + goto out; } } } @@ -121,10 +123,13 @@ efi_setup_pcdp_console(char *cmdline) dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) { if (dev->flags & PCDP_PRIMARY_CONSOLE) { if (dev->type == PCDP_CONSOLE_VGA) { - return setup_vga_console(dev); + rc = setup_vga_console(dev); + goto out; } } } - return -ENODEV; +out: + iounmap(pcdp); + return rc; } diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 244449df7411..bf4cc867a698 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -159,7 +159,7 @@ static inline u32 sn_sal_rev(void) { - struct ia64_sal_systab *systab = efi.sal_systab; + struct ia64_sal_systab *systab = __va(efi.sal_systab); return (u32)(systab->sal_b_rev_major << 8 | systab->sal_b_rev_minor); } diff --git a/include/linux/efi.h b/include/linux/efi.h index d15725470aa4..e203613d3aec 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -240,19 +240,21 @@ struct efi_memory_map { unsigned long desc_size; }; +#define EFI_INVALID_TABLE_ADDR (~0UL) + /* * All runtime access to EFI goes through this structure: */ extern struct efi { efi_system_table_t *systab; /* EFI system table */ - void *mps; /* MPS table */ - void *acpi; /* ACPI table (IA64 ext 0.71) */ - void *acpi20; /* ACPI table (ACPI 2.0) */ - void *smbios; /* SM BIOS table */ - void *sal_systab; /* SAL system table */ - void *boot_info; /* boot info table */ - void *hcdp; /* HCDP table */ - void *uga; /* UGA table */ + unsigned long mps; /* MPS table */ + unsigned long acpi; /* ACPI table (IA64 ext 0.71) */ + unsigned long acpi20; /* ACPI table (ACPI 2.0) */ + unsigned long smbios; /* SM BIOS table */ + unsigned long sal_systab; /* SAL system table */ + unsigned long boot_info; /* boot info table */ + unsigned long hcdp; /* HCDP table */ + unsigned long uga; /* UGA table */ efi_get_time_t *get_time; efi_set_time_t *set_time; efi_get_wakeup_time_t *get_wakeup_time; -- cgit v1.2.3-59-g8ed1b From 23dd842c0033dbb05248c42929c3c526c55386de Mon Sep 17 00:00:00 2001 From: "Tolentino, Matthew E" Date: Sun, 26 Mar 2006 01:37:09 -0800 Subject: [PATCH] EFI fixes Here's a patch that fixes EFI boot for x86 on 2.6.16-rc5-mm3. The off-by-one is admittedly my fault, but the other two fix up the rest. Cc: Bjorn Helgaas Cc: Matt Domsch Cc: "Tolentino, Matthew E" Cc: "Brown, Len" Cc: Andi Kleen Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/dmi_scan.c | 2 +- arch/i386/kernel/setup.c | 6 +++--- drivers/acpi/tables.c | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c index 170d4c9f9bc3..5efceebc48dc 100644 --- a/arch/i386/kernel/dmi_scan.c +++ b/arch/i386/kernel/dmi_scan.c @@ -229,7 +229,7 @@ void __init dmi_scan_machine(void) goto out; rc = dmi_present(p + 0x10); /* offset of _DMI_ string */ - iounmap(p); + dmi_iounmap(p, 32); if (!rc) return; } diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index cec3c925ef99..6917daa159ab 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -1058,10 +1058,10 @@ static int __init free_available_memory(unsigned long start, unsigned long end, void *arg) { /* check max_low_pfn */ - if (start >= ((max_low_pfn + 1) << PAGE_SHIFT)) + if (start >= (max_low_pfn << PAGE_SHIFT)) return 0; - if (end >= ((max_low_pfn + 1) << PAGE_SHIFT)) - end = (max_low_pfn + 1) << PAGE_SHIFT; + if (end >= (max_low_pfn << PAGE_SHIFT)) + end = max_low_pfn << PAGE_SHIFT; if (start < end) free_bootmem(start, end - start); diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 31d4f3ffc265..7f37c7cc5ef1 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -587,7 +587,8 @@ int __init acpi_table_init(void) return -ENODEV; } - rsdp = (struct acpi_table_rsdp *)__va(rsdp_phys); + rsdp = (struct acpi_table_rsdp *)__acpi_map_table(rsdp_phys, + sizeof(struct acpi_table_rsdp)); if (!rsdp) { printk(KERN_WARNING PREFIX "Unable to map RSDP\n"); return -ENODEV; -- cgit v1.2.3-59-g8ed1b From 9f4fd61fa7c13ea905dac18b9baa766a35b88485 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sun, 26 Mar 2006 01:37:10 -0800 Subject: [PATCH] ACPI: clean up memory attribute checking for map/read/write ia64 ioremap is now smart enough to use the correct memory attributes, so remove the EFI checks from osl.c. Signed-off-by: Bjorn Helgaas Cc: Matt Domsch Cc: "Tolentino, Matthew E" Cc: "Brown, Len" Cc: Andi Kleen Acked-by: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/osl.c | 54 +++++++++++------------------------------------------- 1 file changed, 11 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index fc8a3bce6cbb..13b5fd5854a8 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -180,22 +180,14 @@ acpi_status acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem ** virt) { - if (efi_enabled) { - if (EFI_MEMORY_WB & efi_mem_attributes(phys)) { - *virt = (void __iomem *)phys_to_virt(phys); - } else { - *virt = ioremap(phys, size); - } - } else { - if (phys > ULONG_MAX) { - printk(KERN_ERR PREFIX "Cannot map memory that high\n"); - return AE_BAD_PARAMETER; - } - /* - * ioremap checks to ensure this is in reserved space - */ - *virt = ioremap((unsigned long)phys, size); + if (phys > ULONG_MAX) { + printk(KERN_ERR PREFIX "Cannot map memory that high\n"); + return AE_BAD_PARAMETER; } + /* + * ioremap checks to ensure this is in reserved space + */ + *virt = ioremap((unsigned long)phys, size); if (!*virt) return AE_NO_MEMORY; @@ -407,18 +399,8 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) { u32 dummy; void __iomem *virt_addr; - int iomem = 0; - if (efi_enabled) { - if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) { - /* HACK ALERT! We can use readb/w/l on real memory too.. */ - virt_addr = (void __iomem *)phys_to_virt(phys_addr); - } else { - iomem = 1; - virt_addr = ioremap(phys_addr, width); - } - } else - virt_addr = (void __iomem *)phys_to_virt(phys_addr); + virt_addr = ioremap(phys_addr, width); if (!value) value = &dummy; @@ -436,10 +418,7 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) BUG(); } - if (efi_enabled) { - if (iomem) - iounmap(virt_addr); - } + iounmap(virt_addr); return AE_OK; } @@ -448,18 +427,8 @@ acpi_status acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) { void __iomem *virt_addr; - int iomem = 0; - if (efi_enabled) { - if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) { - /* HACK ALERT! We can use writeb/w/l on real memory too */ - virt_addr = (void __iomem *)phys_to_virt(phys_addr); - } else { - iomem = 1; - virt_addr = ioremap(phys_addr, width); - } - } else - virt_addr = (void __iomem *)phys_to_virt(phys_addr); + virt_addr = ioremap(phys_addr, width); switch (width) { case 8: @@ -475,8 +444,7 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) BUG(); } - if (iomem) - iounmap(virt_addr); + iounmap(virt_addr); return AE_OK; } -- cgit v1.2.3-59-g8ed1b From 14cc3e2b633bb64063698980974df4535368e98f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 26 Mar 2006 01:37:14 -0800 Subject: [PATCH] sem2mutex: misc static one-file mutexes 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 Cc: Dave Jones Cc: Paul Mackerras Cc: Ralf Baechle Cc: Jens Axboe Cc: Neil Brown Acked-by: Alasdair G Kergon Cc: Greg KH Cc: Dominik Brodowski Cc: Adam Belay Cc: Martin Schwidefsky Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm26/kernel/traps.c | 12 +++--- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 9 ++-- arch/i386/kernel/cpu/mtrr/main.c | 13 +++--- arch/i386/kernel/microcode.c | 7 ++-- arch/mips/lasat/sysctl.c | 63 ++++++++++++++-------------- arch/powerpc/mm/imalloc.c | 18 ++++---- arch/powerpc/platforms/cell/spu_base.c | 22 +++++----- arch/powerpc/platforms/powermac/cpufreq_64.c | 7 ++-- drivers/macintosh/smu.c | 9 ++-- drivers/md/kcopyd.c | 16 +++---- drivers/net/wan/dscc4.c | 7 ++-- drivers/parport/share.c | 19 +++++---- drivers/pci/hotplug/rpadlpar_core.c | 12 +++--- drivers/pci/hotplug/sgi_hotplug.c | 19 +++++---- drivers/pnp/isapnp/core.c | 7 ++-- drivers/s390/char/raw3270.c | 39 ++++++++--------- drivers/telephony/phonedev.c | 21 +++++----- net/ipv4/ipvs/ip_vs_ctl.c | 11 ++--- net/ipv4/netfilter/ipt_hashlimit.c | 9 ++-- net/netlink/genetlink.c | 9 ++-- 20 files changed, 172 insertions(+), 157 deletions(-) (limited to 'drivers') diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c index 5847ea5d7747..a79de041b50e 100644 --- a/arch/arm26/kernel/traps.c +++ b/arch/arm26/kernel/traps.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include "ptrace.h" @@ -207,19 +207,19 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int err) die(str, regs, err); } -static DECLARE_MUTEX(undef_sem); +static DEFINE_MUTEX(undef_mutex); static int (*undef_hook)(struct pt_regs *); int request_undef_hook(int (*fn)(struct pt_regs *)) { int ret = -EBUSY; - down(&undef_sem); + mutex_lock(&undef_mutex); if (undef_hook == NULL) { undef_hook = fn; ret = 0; } - up(&undef_sem); + mutex_unlock(&undef_mutex); return ret; } @@ -228,12 +228,12 @@ int release_undef_hook(int (*fn)(struct pt_regs *)) { int ret = -EINVAL; - down(&undef_sem); + mutex_lock(&undef_mutex); if (undef_hook == fn) { undef_hook = NULL; ret = 0; } - up(&undef_sem); + mutex_unlock(&undef_mutex); return ret; } diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index e5bc06480ff9..1e70823e1cb5 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -40,6 +40,7 @@ #ifdef CONFIG_X86_POWERNOW_K8_ACPI #include +#include #include #endif @@ -49,7 +50,7 @@ #include "powernow-k8.h" /* serialize freq changes */ -static DECLARE_MUTEX(fidvid_sem); +static DEFINE_MUTEX(fidvid_mutex); static struct powernow_k8_data *powernow_data[NR_CPUS]; @@ -943,17 +944,17 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) goto err_out; - down(&fidvid_sem); + mutex_lock(&fidvid_mutex); powernow_k8_acpi_pst_values(data, newstate); if (transition_frequency(data, newstate)) { printk(KERN_ERR PFX "transition frequency failed\n"); ret = 1; - up(&fidvid_sem); + mutex_unlock(&fidvid_mutex); goto err_out; } - up(&fidvid_sem); + mutex_unlock(&fidvid_mutex); pol->cur = find_khz_freq_from_fid(data->currfid); ret = 0; diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c index 3b4618bed70d..fff90bda4733 100644 --- a/arch/i386/kernel/cpu/mtrr/main.c +++ b/arch/i386/kernel/cpu/mtrr/main.c @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -47,7 +48,7 @@ u32 num_var_ranges = 0; unsigned int *usage_table; -static DECLARE_MUTEX(mtrr_sem); +static DEFINE_MUTEX(mtrr_mutex); u32 size_or_mask, size_and_mask; @@ -333,7 +334,7 @@ int mtrr_add_page(unsigned long base, unsigned long size, /* No CPU hotplug when we change MTRR entries */ lock_cpu_hotplug(); /* Search for existing MTRR */ - down(&mtrr_sem); + mutex_lock(&mtrr_mutex); for (i = 0; i < num_var_ranges; ++i) { mtrr_if->get(i, &lbase, &lsize, <ype); if (base >= lbase + lsize) @@ -371,7 +372,7 @@ int mtrr_add_page(unsigned long base, unsigned long size, printk(KERN_INFO "mtrr: no more MTRRs available\n"); error = i; out: - up(&mtrr_sem); + mutex_unlock(&mtrr_mutex); unlock_cpu_hotplug(); return error; } @@ -464,7 +465,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) max = num_var_ranges; /* No CPU hotplug when we change MTRR entries */ lock_cpu_hotplug(); - down(&mtrr_sem); + mutex_lock(&mtrr_mutex); if (reg < 0) { /* Search for existing MTRR */ for (i = 0; i < max; ++i) { @@ -503,7 +504,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) set_mtrr(reg, 0, 0, 0); error = reg; out: - up(&mtrr_sem); + mutex_unlock(&mtrr_mutex); unlock_cpu_hotplug(); return error; } @@ -685,7 +686,7 @@ void mtrr_ap_init(void) if (!mtrr_if || !use_intel()) return; /* - * Ideally we should hold mtrr_sem here to avoid mtrr entries changed, + * Ideally we should hold mtrr_mutex here to avoid mtrr entries changed, * but this routine will be called in cpu boot time, holding the lock * breaks it. This routine is called in two cases: 1.very earily time * of software resume, when there absolutely isn't mtrr entry changes; diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index 55bc365b8753..dd780a00553f 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -81,6 +81,7 @@ #include #include #include +#include #include #include @@ -114,7 +115,7 @@ MODULE_LICENSE("GPL"); static DEFINE_SPINLOCK(microcode_update_lock); /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ -static DECLARE_MUTEX(microcode_sem); +static DEFINE_MUTEX(microcode_mutex); static void __user *user_buffer; /* user area microcode data buffer */ static unsigned int user_buffer_size; /* it's size */ @@ -444,7 +445,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_ return -EINVAL; } - down(µcode_sem); + mutex_lock(µcode_mutex); user_buffer = (void __user *) buf; user_buffer_size = (int) len; @@ -453,7 +454,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_ if (!ret) ret = (ssize_t)len; - up(µcode_sem); + mutex_unlock(µcode_mutex); return ret; } diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c index 8ff43a1c1e99..e3d5aaa90f0d 100644 --- a/arch/mips/lasat/sysctl.c +++ b/arch/mips/lasat/sysctl.c @@ -30,12 +30,13 @@ #include #include #include +#include #include #include "sysctl.h" #include "ds1603.h" -static DECLARE_MUTEX(lasat_info_sem); +static DEFINE_MUTEX(lasat_info_mutex); /* Strategy function to write EEPROM after changing string entry */ int sysctl_lasatstring(ctl_table *table, int *name, int nlen, @@ -43,17 +44,17 @@ int sysctl_lasatstring(ctl_table *table, int *name, int nlen, void *newval, size_t newlen, void **context) { int r; - down(&lasat_info_sem); + mutex_lock(&lasat_info_mutex); r = sysctl_string(table, name, nlen, oldval, oldlenp, newval, newlen, context); if (r < 0) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return r; } if (newval && newlen) { lasat_write_eeprom_info(); } - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return 1; } @@ -63,14 +64,14 @@ int proc_dolasatstring(ctl_table *table, int write, struct file *filp, void *buffer, size_t *lenp, loff_t *ppos) { int r; - down(&lasat_info_sem); + mutex_lock(&lasat_info_mutex); r = proc_dostring(table, write, filp, buffer, lenp, ppos); if ( (!write) || r) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return r; } lasat_write_eeprom_info(); - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return 0; } @@ -79,14 +80,14 @@ int proc_dolasatint(ctl_table *table, int write, struct file *filp, void *buffer, size_t *lenp, loff_t *ppos) { int r; - down(&lasat_info_sem); + mutex_lock(&lasat_info_mutex); r = proc_dointvec(table, write, filp, buffer, lenp, ppos); if ( (!write) || r) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return r; } lasat_write_eeprom_info(); - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return 0; } @@ -98,7 +99,7 @@ int proc_dolasatrtc(ctl_table *table, int write, struct file *filp, void *buffer, size_t *lenp, loff_t *ppos) { int r; - down(&lasat_info_sem); + mutex_lock(&lasat_info_mutex); if (!write) { rtctmp = ds1603_read(); /* check for time < 0 and set to 0 */ @@ -107,11 +108,11 @@ int proc_dolasatrtc(ctl_table *table, int write, struct file *filp, } r = proc_dointvec(table, write, filp, buffer, lenp, ppos); if ( (!write) || r) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return r; } ds1603_set(rtctmp); - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return 0; } #endif @@ -122,16 +123,16 @@ int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen, void *newval, size_t newlen, void **context) { int r; - down(&lasat_info_sem); + mutex_lock(&lasat_info_mutex); r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); if (r < 0) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return r; } if (newval && newlen) { lasat_write_eeprom_info(); } - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return 1; } @@ -142,19 +143,19 @@ int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen, void *newval, size_t newlen, void **context) { int r; - down(&lasat_info_sem); + mutex_lock(&lasat_info_mutex); rtctmp = ds1603_read(); if (rtctmp < 0) rtctmp = 0; r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); if (r < 0) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return r; } if (newval && newlen) { ds1603_set(rtctmp); } - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return 1; } #endif @@ -192,13 +193,13 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp, return 0; } - down(&lasat_info_sem); + mutex_lock(&lasat_info_mutex); if (write) { len = 0; p = buffer; while (len < *lenp) { if(get_user(c, p++)) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return -EFAULT; } if (c == 0 || c == '\n') @@ -209,7 +210,7 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp, len = sizeof(proc_lasat_ipbuf) - 1; if (copy_from_user(proc_lasat_ipbuf, buffer, len)) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return -EFAULT; } proc_lasat_ipbuf[len] = 0; @@ -230,12 +231,12 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp, len = *lenp; if (len) if(copy_to_user(buffer, proc_lasat_ipbuf, len)) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return -EFAULT; } if (len < *lenp) { if(put_user('\n', ((char *) buffer) + len)) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return -EFAULT; } len++; @@ -244,7 +245,7 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp, *ppos += len; } update_bcastaddr(); - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return 0; } #endif /* defined(CONFIG_INET) */ @@ -256,10 +257,10 @@ static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen, { int r; - down(&lasat_info_sem); + mutex_lock(&lasat_info_mutex); r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); if (r < 0) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return r; } @@ -271,7 +272,7 @@ static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen, lasat_write_eeprom_info(); lasat_init_board_info(); } - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return 0; } @@ -280,10 +281,10 @@ int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp, void *buffer, size_t *lenp, loff_t *ppos) { int r; - down(&lasat_info_sem); + mutex_lock(&lasat_info_mutex); r = proc_dointvec(table, write, filp, buffer, lenp, ppos); if ( (!write) || r) { - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return r; } if (filp && filp->f_dentry) @@ -294,7 +295,7 @@ int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp, lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess; } lasat_write_eeprom_info(); - up(&lasat_info_sem); + mutex_unlock(&lasat_info_mutex); return 0; } diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c index 8b0c132bc163..add8c1a9af68 100644 --- a/arch/powerpc/mm/imalloc.c +++ b/arch/powerpc/mm/imalloc.c @@ -13,12 +13,12 @@ #include #include #include -#include +#include #include #include "mmu_decl.h" -static DECLARE_MUTEX(imlist_sem); +static DEFINE_MUTEX(imlist_mutex); struct vm_struct * imlist = NULL; static int get_free_im_addr(unsigned long size, unsigned long *im_addr) @@ -257,7 +257,7 @@ struct vm_struct * im_get_free_area(unsigned long size) struct vm_struct *area; unsigned long addr; - down(&imlist_sem); + mutex_lock(&imlist_mutex); if (get_free_im_addr(size, &addr)) { printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n", __FUNCTION__, size); @@ -272,7 +272,7 @@ struct vm_struct * im_get_free_area(unsigned long size) __FUNCTION__, addr, size); } next_im_done: - up(&imlist_sem); + mutex_unlock(&imlist_mutex); return area; } @@ -281,9 +281,9 @@ struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, { struct vm_struct *area; - down(&imlist_sem); + mutex_lock(&imlist_mutex); area = __im_get_area(v_addr, size, criteria); - up(&imlist_sem); + mutex_unlock(&imlist_mutex); return area; } @@ -297,17 +297,17 @@ void im_free(void * addr) printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr); return; } - down(&imlist_sem); + mutex_lock(&imlist_mutex); for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { if (tmp->addr == addr) { *p = tmp->next; unmap_vm_area(tmp); kfree(tmp); - up(&imlist_sem); + mutex_unlock(&imlist_mutex); return; } } - up(&imlist_sem); + mutex_unlock(&imlist_mutex); printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, addr); } diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d75ae03df686..a8fa1eeeb174 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include @@ -342,7 +342,7 @@ spu_free_irqs(struct spu *spu) } static LIST_HEAD(spu_list); -static DECLARE_MUTEX(spu_mutex); +static DEFINE_MUTEX(spu_mutex); static void spu_init_channels(struct spu *spu) { @@ -382,7 +382,7 @@ struct spu *spu_alloc(void) { struct spu *spu; - down(&spu_mutex); + mutex_lock(&spu_mutex); if (!list_empty(&spu_list)) { spu = list_entry(spu_list.next, struct spu, list); list_del_init(&spu->list); @@ -391,7 +391,7 @@ struct spu *spu_alloc(void) pr_debug("No SPU left\n"); spu = NULL; } - up(&spu_mutex); + mutex_unlock(&spu_mutex); if (spu) spu_init_channels(spu); @@ -402,9 +402,9 @@ EXPORT_SYMBOL_GPL(spu_alloc); void spu_free(struct spu *spu) { - down(&spu_mutex); + mutex_lock(&spu_mutex); list_add_tail(&spu->list, &spu_list); - up(&spu_mutex); + mutex_unlock(&spu_mutex); } EXPORT_SYMBOL_GPL(spu_free); @@ -633,14 +633,14 @@ static int __init create_spu(struct device_node *spe) spu->wbox_callback = NULL; spu->stop_callback = NULL; - down(&spu_mutex); + mutex_lock(&spu_mutex); spu->number = number++; ret = spu_request_irqs(spu); if (ret) goto out_unmap; list_add(&spu->list, &spu_list); - up(&spu_mutex); + mutex_unlock(&spu_mutex); pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n", spu->name, spu->isrc, spu->local_store, @@ -648,7 +648,7 @@ static int __init create_spu(struct device_node *spe) goto out; out_unmap: - up(&spu_mutex); + mutex_unlock(&spu_mutex); spu_unmap(spu); out_free: kfree(spu); @@ -668,10 +668,10 @@ static void destroy_spu(struct spu *spu) static void cleanup_spu_base(void) { struct spu *spu, *tmp; - down(&spu_mutex); + mutex_lock(&spu_mutex); list_for_each_entry_safe(spu, tmp, &spu_list, list) destroy_spu(spu); - up(&spu_mutex); + mutex_unlock(&spu_mutex); } module_exit(cleanup_spu_base); diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index a415e8d2f7af..b57e465a1b71 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -90,7 +91,7 @@ static void (*g5_switch_volt)(int speed_mode); static int (*g5_switch_freq)(int speed_mode); static int (*g5_query_freq)(void); -static DECLARE_MUTEX(g5_switch_mutex); +static DEFINE_MUTEX(g5_switch_mutex); static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ @@ -327,7 +328,7 @@ static int g5_cpufreq_target(struct cpufreq_policy *policy, if (g5_pmode_cur == newstate) return 0; - down(&g5_switch_mutex); + mutex_lock(&g5_switch_mutex); freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency; freqs.new = g5_cpu_freqs[newstate].frequency; @@ -337,7 +338,7 @@ static int g5_cpufreq_target(struct cpufreq_policy *policy, rc = g5_switch_freq(newstate); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - up(&g5_switch_mutex); + mutex_unlock(&g5_switch_mutex); return rc; } diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 4eb05d7143d8..f4516ca7aa3a 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -92,7 +93,7 @@ struct smu_device { * for now, just hard code that */ static struct smu_device *smu; -static DECLARE_MUTEX(smu_part_access); +static DEFINE_MUTEX(smu_part_access); static void smu_i2c_retry(unsigned long data); @@ -976,11 +977,11 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, if (interruptible) { int rc; - rc = down_interruptible(&smu_part_access); + rc = mutex_lock_interruptible(&smu_part_access); if (rc) return ERR_PTR(rc); } else - down(&smu_part_access); + mutex_lock(&smu_part_access); part = (struct smu_sdbp_header *)get_property(smu->of_node, pname, size); @@ -990,7 +991,7 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, if (part != NULL && size) *size = part->len << 2; } - up(&smu_part_access); + mutex_unlock(&smu_part_access); return part; } diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index 8b3515f394a6..0d54e8b7d9de 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c @@ -590,51 +590,51 @@ static void client_del(struct kcopyd_client *kc) up(&_client_lock); } -static DECLARE_MUTEX(kcopyd_init_lock); +static DEFINE_MUTEX(kcopyd_init_lock); static int kcopyd_clients = 0; static int kcopyd_init(void) { int r; - down(&kcopyd_init_lock); + mutex_lock(&kcopyd_init_lock); if (kcopyd_clients) { /* Already initialized. */ kcopyd_clients++; - up(&kcopyd_init_lock); + mutex_unlock(&kcopyd_init_lock); return 0; } r = jobs_init(); if (r) { - up(&kcopyd_init_lock); + mutex_unlock(&kcopyd_init_lock); return r; } _kcopyd_wq = create_singlethread_workqueue("kcopyd"); if (!_kcopyd_wq) { jobs_exit(); - up(&kcopyd_init_lock); + mutex_unlock(&kcopyd_init_lock); return -ENOMEM; } kcopyd_clients++; INIT_WORK(&_kcopyd_work, do_work, NULL); - up(&kcopyd_init_lock); + mutex_unlock(&kcopyd_init_lock); return 0; } static void kcopyd_exit(void) { - down(&kcopyd_init_lock); + mutex_lock(&kcopyd_init_lock); kcopyd_clients--; if (!kcopyd_clients) { jobs_exit(); destroy_workqueue(_kcopyd_wq); _kcopyd_wq = NULL; } - up(&kcopyd_init_lock); + mutex_unlock(&kcopyd_init_lock); } int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result) diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 1ff5de076d21..4505540e3c59 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -105,6 +105,7 @@ #include #include #include +#include /* Version */ static const char version[] = "$Id: dscc4.c,v 1.173 2003/09/20 23:55:34 romieu Exp $ for Linux\n"; @@ -112,7 +113,7 @@ static int debug; static int quartz; #ifdef CONFIG_DSCC4_PCI_RST -static DECLARE_MUTEX(dscc4_sem); +static DEFINE_MUTEX(dscc4_mutex); static u32 dscc4_pci_config_store[16]; #endif @@ -1018,7 +1019,7 @@ static void dscc4_pci_reset(struct pci_dev *pdev, void __iomem *ioaddr) { int i; - down(&dscc4_sem); + mutex_lock(&dscc4_mutex); for (i = 0; i < 16; i++) pci_read_config_dword(pdev, i << 2, dscc4_pci_config_store + i); @@ -1039,7 +1040,7 @@ static void dscc4_pci_reset(struct pci_dev *pdev, void __iomem *ioaddr) for (i = 0; i < 16; i++) pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]); - up(&dscc4_sem); + mutex_unlock(&dscc4_mutex); } #else #define dscc4_pci_reset(pdev,ioaddr) do {} while (0) diff --git a/drivers/parport/share.c b/drivers/parport/share.c index ea62bed6bc83..bbbfd79adbaf 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -32,6 +32,7 @@ #include #include +#include #include #undef PARPORT_PARANOID @@ -50,7 +51,7 @@ static DEFINE_SPINLOCK(full_list_lock); static LIST_HEAD(drivers); -static DECLARE_MUTEX(registration_lock); +static DEFINE_MUTEX(registration_lock); /* What you can do to a port that's gone away.. */ static void dead_write_lines (struct parport *p, unsigned char b){} @@ -158,11 +159,11 @@ int parport_register_driver (struct parport_driver *drv) if (list_empty(&portlist)) get_lowlevel_driver (); - down(®istration_lock); + mutex_lock(®istration_lock); list_for_each_entry(port, &portlist, list) drv->attach(port); list_add(&drv->list, &drivers); - up(®istration_lock); + mutex_unlock(®istration_lock); return 0; } @@ -188,11 +189,11 @@ void parport_unregister_driver (struct parport_driver *drv) { struct parport *port; - down(®istration_lock); + mutex_lock(®istration_lock); list_del_init(&drv->list); list_for_each_entry(port, &portlist, list) drv->detach(port); - up(®istration_lock); + mutex_unlock(®istration_lock); } static void free_port (struct parport *port) @@ -366,7 +367,7 @@ void parport_announce_port (struct parport *port) #endif parport_proc_register(port); - down(®istration_lock); + mutex_lock(®istration_lock); spin_lock_irq(&parportlist_lock); list_add_tail(&port->list, &portlist); for (i = 1; i < 3; i++) { @@ -383,7 +384,7 @@ void parport_announce_port (struct parport *port) if (slave) attach_driver_chain(slave); } - up(®istration_lock); + mutex_unlock(®istration_lock); } /** @@ -409,7 +410,7 @@ void parport_remove_port(struct parport *port) { int i; - down(®istration_lock); + mutex_lock(®istration_lock); /* Spread the word. */ detach_driver_chain (port); @@ -436,7 +437,7 @@ void parport_remove_port(struct parport *port) } spin_unlock(&parportlist_lock); - up(®istration_lock); + mutex_unlock(®istration_lock); parport_proc_unregister(port); diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 3eefe2cec72d..46825fee3ae4 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -27,7 +27,7 @@ #include "rpaphp.h" #include "rpadlpar.h" -static DECLARE_MUTEX(rpadlpar_sem); +static DEFINE_MUTEX(rpadlpar_mutex); #define DLPAR_MODULE_NAME "rpadlpar_io" @@ -300,7 +300,7 @@ int dlpar_add_slot(char *drc_name) int node_type; int rc = -EIO; - if (down_interruptible(&rpadlpar_sem)) + if (mutex_lock_interruptible(&rpadlpar_mutex)) return -ERESTARTSYS; /* Find newly added node */ @@ -324,7 +324,7 @@ int dlpar_add_slot(char *drc_name) printk(KERN_INFO "%s: slot %s added\n", DLPAR_MODULE_NAME, drc_name); exit: - up(&rpadlpar_sem); + mutex_unlock(&rpadlpar_mutex); return rc; } @@ -417,7 +417,7 @@ int dlpar_remove_slot(char *drc_name) int node_type; int rc = 0; - if (down_interruptible(&rpadlpar_sem)) + if (mutex_lock_interruptible(&rpadlpar_mutex)) return -ERESTARTSYS; dn = find_dlpar_node(drc_name, &node_type); @@ -439,7 +439,7 @@ int dlpar_remove_slot(char *drc_name) } printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name); exit: - up(&rpadlpar_sem); + mutex_unlock(&rpadlpar_mutex); return rc; } diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index c402da8e78ae..8cb9abde736b 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -81,7 +82,7 @@ static struct hotplug_slot_ops sn_hotplug_slot_ops = { .get_power_status = get_power_status, }; -static DECLARE_MUTEX(sn_hotplug_sem); +static DEFINE_MUTEX(sn_hotplug_mutex); static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot, char *buf) @@ -346,7 +347,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) int rc; /* Serialize the Linux PCI infrastructure */ - down(&sn_hotplug_sem); + mutex_lock(&sn_hotplug_mutex); /* * Power-on and initialize the slot in the SN @@ -354,7 +355,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) */ rc = sn_slot_enable(bss_hotplug_slot, slot->device_num); if (rc) { - up(&sn_hotplug_sem); + mutex_unlock(&sn_hotplug_mutex); return rc; } @@ -362,7 +363,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) PCI_DEVFN(slot->device_num + 1, 0)); if (!num_funcs) { dev_dbg(slot->pci_bus->self, "no device in slot\n"); - up(&sn_hotplug_sem); + mutex_unlock(&sn_hotplug_mutex); return -ENODEV; } @@ -402,7 +403,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) if (new_ppb) pci_bus_add_devices(new_bus); - up(&sn_hotplug_sem); + mutex_unlock(&sn_hotplug_mutex); if (rc == 0) dev_dbg(slot->pci_bus->self, @@ -422,7 +423,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) int rc; /* Acquire update access to the bus */ - down(&sn_hotplug_sem); + mutex_lock(&sn_hotplug_mutex); /* is it okay to bring this slot down? */ rc = sn_slot_disable(bss_hotplug_slot, slot->device_num, @@ -450,7 +451,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) PCI_REQ_SLOT_DISABLE); leaving: /* Release the bus lock */ - up(&sn_hotplug_sem); + mutex_unlock(&sn_hotplug_mutex); return rc; } @@ -462,9 +463,9 @@ static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot, struct pcibus_info *pcibus_info; pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); - down(&sn_hotplug_sem); + mutex_lock(&sn_hotplug_mutex); *value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num); - up(&sn_hotplug_sem); + mutex_unlock(&sn_hotplug_mutex); return 0; } diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index b1b4b683cbdd..ac7c2bb6c69e 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #if 0 @@ -92,7 +93,7 @@ MODULE_LICENSE("GPL"); #define _LTAG_FIXEDMEM32RANGE 0x86 static unsigned char isapnp_checksum_value; -static DECLARE_MUTEX(isapnp_cfg_mutex); +static DEFINE_MUTEX(isapnp_cfg_mutex); static int isapnp_detected; static int isapnp_csn_count; @@ -903,7 +904,7 @@ int isapnp_cfg_begin(int csn, int logdev) { if (csn < 1 || csn > isapnp_csn_count || logdev > 10) return -EINVAL; - down(&isapnp_cfg_mutex); + mutex_lock(&isapnp_cfg_mutex); isapnp_wait(); isapnp_key(); isapnp_wake(csn); @@ -929,7 +930,7 @@ int isapnp_cfg_begin(int csn, int logdev) int isapnp_cfg_end(void) { isapnp_wait(); - up(&isapnp_cfg_mutex); + mutex_unlock(&isapnp_cfg_mutex); return 0; } diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index bd06607a5dcc..eecb2afad5c2 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -28,6 +28,7 @@ #include #include #include +#include struct class *class3270; @@ -59,7 +60,7 @@ struct raw3270 { #define RAW3270_FLAGS_CONSOLE 8 /* Device is the console. */ /* Semaphore to protect global data of raw3270 (devices, views, etc). */ -static DECLARE_MUTEX(raw3270_sem); +static DEFINE_MUTEX(raw3270_mutex); /* List of 3270 devices. */ static struct list_head raw3270_devices = LIST_HEAD_INIT(raw3270_devices); @@ -815,7 +816,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc) * number for it. Note: there is no device with minor 0, * see special case for fs3270.c:fs3270_open(). */ - down(&raw3270_sem); + mutex_lock(&raw3270_mutex); /* Keep the list sorted. */ minor = RAW3270_FIRSTMINOR; rp->minor = -1; @@ -832,7 +833,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc) rp->minor = minor; list_add_tail(&rp->list, &raw3270_devices); } - up(&raw3270_sem); + mutex_unlock(&raw3270_mutex); /* No free minor number? Then give up. */ if (rp->minor == -1) return -EUSERS; @@ -1003,7 +1004,7 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor) if (minor <= 0) return -ENODEV; - down(&raw3270_sem); + mutex_lock(&raw3270_mutex); rc = -ENODEV; list_for_each_entry(rp, &raw3270_devices, list) { if (rp->minor != minor) @@ -1024,7 +1025,7 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor) spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); break; } - up(&raw3270_sem); + mutex_unlock(&raw3270_mutex); return rc; } @@ -1038,7 +1039,7 @@ raw3270_find_view(struct raw3270_fn *fn, int minor) struct raw3270_view *view, *tmp; unsigned long flags; - down(&raw3270_sem); + mutex_lock(&raw3270_mutex); view = ERR_PTR(-ENODEV); list_for_each_entry(rp, &raw3270_devices, list) { if (rp->minor != minor) @@ -1057,7 +1058,7 @@ raw3270_find_view(struct raw3270_fn *fn, int minor) spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); break; } - up(&raw3270_sem); + mutex_unlock(&raw3270_mutex); return view; } @@ -1104,7 +1105,7 @@ raw3270_delete_device(struct raw3270 *rp) struct ccw_device *cdev; /* Remove from device chain. */ - down(&raw3270_sem); + mutex_lock(&raw3270_mutex); if (rp->clttydev) class_device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor)); @@ -1112,7 +1113,7 @@ raw3270_delete_device(struct raw3270 *rp) class_device_destroy(class3270, MKDEV(IBM_FS3270_MAJOR, rp->minor)); list_del_init(&rp->list); - up(&raw3270_sem); + mutex_unlock(&raw3270_mutex); /* Disconnect from ccw_device. */ cdev = rp->cdev; @@ -1208,13 +1209,13 @@ int raw3270_register_notifier(void (*notifier)(int, int)) if (!np) return -ENOMEM; np->notifier = notifier; - down(&raw3270_sem); + mutex_lock(&raw3270_mutex); list_add_tail(&np->list, &raw3270_notifier); list_for_each_entry(rp, &raw3270_devices, list) { get_device(&rp->cdev->dev); notifier(rp->minor, 1); } - up(&raw3270_sem); + mutex_unlock(&raw3270_mutex); return 0; } @@ -1222,14 +1223,14 @@ void raw3270_unregister_notifier(void (*notifier)(int, int)) { struct raw3270_notifier *np; - down(&raw3270_sem); + mutex_lock(&raw3270_mutex); list_for_each_entry(np, &raw3270_notifier, list) if (np->notifier == notifier) { list_del(&np->list); kfree(np); break; } - up(&raw3270_sem); + mutex_unlock(&raw3270_mutex); } /* @@ -1256,10 +1257,10 @@ raw3270_set_online (struct ccw_device *cdev) goto failure; raw3270_create_attributes(rp); set_bit(RAW3270_FLAGS_READY, &rp->flags); - down(&raw3270_sem); + mutex_lock(&raw3270_mutex); list_for_each_entry(np, &raw3270_notifier, list) np->notifier(rp->minor, 1); - up(&raw3270_sem); + mutex_unlock(&raw3270_mutex); return 0; failure: @@ -1307,10 +1308,10 @@ raw3270_remove (struct ccw_device *cdev) } spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); - down(&raw3270_sem); + mutex_lock(&raw3270_mutex); list_for_each_entry(np, &raw3270_notifier, list) np->notifier(rp->minor, 0); - up(&raw3270_sem); + mutex_unlock(&raw3270_mutex); /* Reset 3270 device. */ raw3270_reset_device(rp); @@ -1370,13 +1371,13 @@ raw3270_init(void) rc = ccw_driver_register(&raw3270_ccw_driver); if (rc == 0) { /* Create attributes for early (= console) device. */ - down(&raw3270_sem); + mutex_lock(&raw3270_mutex); class3270 = class_create(THIS_MODULE, "3270"); list_for_each_entry(rp, &raw3270_devices, list) { get_device(&rp->cdev->dev); raw3270_create_attributes(rp); } - up(&raw3270_sem); + mutex_unlock(&raw3270_mutex); } return rc; } diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c index 3c987f49f6b4..7a6db1c5c8c5 100644 --- a/drivers/telephony/phonedev.c +++ b/drivers/telephony/phonedev.c @@ -29,6 +29,7 @@ #include #include #include +#include #define PHONE_NUM_DEVICES 256 @@ -37,7 +38,7 @@ */ static struct phone_device *phone_device[PHONE_NUM_DEVICES]; -static DECLARE_MUTEX(phone_lock); +static DEFINE_MUTEX(phone_lock); /* * Open a phone device. @@ -53,14 +54,14 @@ static int phone_open(struct inode *inode, struct file *file) if (minor >= PHONE_NUM_DEVICES) return -ENODEV; - down(&phone_lock); + mutex_lock(&phone_lock); p = phone_device[minor]; if (p) new_fops = fops_get(p->f_op); if (!new_fops) { - up(&phone_lock); + mutex_unlock(&phone_lock); request_module("char-major-%d-%d", PHONE_MAJOR, minor); - down(&phone_lock); + mutex_lock(&phone_lock); p = phone_device[minor]; if (p == NULL || (new_fops = fops_get(p->f_op)) == NULL) { @@ -78,7 +79,7 @@ static int phone_open(struct inode *inode, struct file *file) } fops_put(old_fops); end: - up(&phone_lock); + mutex_unlock(&phone_lock); return err; } @@ -100,18 +101,18 @@ int phone_register_device(struct phone_device *p, int unit) end = unit + 1; /* enter the loop at least one time */ } - down(&phone_lock); + mutex_lock(&phone_lock); for (i = base; i < end; i++) { if (phone_device[i] == NULL) { phone_device[i] = p; p->minor = i; devfs_mk_cdev(MKDEV(PHONE_MAJOR,i), S_IFCHR|S_IRUSR|S_IWUSR, "phone/%d", i); - up(&phone_lock); + mutex_unlock(&phone_lock); return 0; } } - up(&phone_lock); + mutex_unlock(&phone_lock); return -ENFILE; } @@ -121,12 +122,12 @@ int phone_register_device(struct phone_device *p, int unit) void phone_unregister_device(struct phone_device *pfd) { - down(&phone_lock); + mutex_lock(&phone_lock); if (phone_device[pfd->minor] != pfd) panic("phone: bad unregister"); devfs_remove("phone/%d", pfd->minor); phone_device[pfd->minor] = NULL; - up(&phone_lock); + mutex_unlock(&phone_lock); } diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 7f0288b25fa1..f28ec6882162 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -44,7 +45,7 @@ #include /* semaphore for IPVS sockopts. And, [gs]etsockopt may sleep. */ -static DECLARE_MUTEX(__ip_vs_mutex); +static DEFINE_MUTEX(__ip_vs_mutex); /* lock for service table */ static DEFINE_RWLOCK(__ip_vs_svc_lock); @@ -1950,7 +1951,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) /* increase the module use count */ ip_vs_use_count_inc(); - if (down_interruptible(&__ip_vs_mutex)) { + if (mutex_lock_interruptible(&__ip_vs_mutex)) { ret = -ERESTARTSYS; goto out_dec; } @@ -2041,7 +2042,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) ip_vs_service_put(svc); out_unlock: - up(&__ip_vs_mutex); + mutex_unlock(&__ip_vs_mutex); out_dec: /* decrease the module use count */ ip_vs_use_count_dec(); @@ -2211,7 +2212,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) if (copy_from_user(arg, user, get_arglen[GET_CMDID(cmd)]) != 0) return -EFAULT; - if (down_interruptible(&__ip_vs_mutex)) + if (mutex_lock_interruptible(&__ip_vs_mutex)) return -ERESTARTSYS; switch (cmd) { @@ -2330,7 +2331,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) } out: - up(&__ip_vs_mutex); + mutex_unlock(&__ip_vs_mutex); return ret; } diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c index dc1521c5aa81..ba5e23505e88 100644 --- a/net/ipv4/netfilter/ipt_hashlimit.c +++ b/net/ipv4/netfilter/ipt_hashlimit.c @@ -40,6 +40,7 @@ /* FIXME: this is just for IP_NF_ASSERRT */ #include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte "); @@ -92,7 +93,7 @@ struct ipt_hashlimit_htable { }; static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */ -static DECLARE_MUTEX(hlimit_mutex); /* additional checkentry protection */ +static DEFINE_MUTEX(hlimit_mutex); /* additional checkentry protection */ static HLIST_HEAD(hashlimit_htables); static kmem_cache_t *hashlimit_cachep __read_mostly; @@ -542,13 +543,13 @@ hashlimit_checkentry(const char *tablename, * call vmalloc, and that can sleep. And we cannot just re-search * the list of htable's in htable_create(), since then we would * create duplicate proc files. -HW */ - down(&hlimit_mutex); + mutex_lock(&hlimit_mutex); r->hinfo = htable_find_get(r->name); if (!r->hinfo && (htable_create(r) != 0)) { - up(&hlimit_mutex); + mutex_unlock(&hlimit_mutex); return 0; } - up(&hlimit_mutex); + mutex_unlock(&hlimit_mutex); /* Ugly hack: For SMP, we only want to use one set */ r->u.master = r; diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 43e72419c868..f329b72578f5 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -13,26 +13,27 @@ #include #include #include +#include #include #include struct sock *genl_sock = NULL; -static DECLARE_MUTEX(genl_sem); /* serialization of message processing */ +static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ static void genl_lock(void) { - down(&genl_sem); + mutex_lock(&genl_mutex); } static int genl_trylock(void) { - return down_trylock(&genl_sem); + return !mutex_trylock(&genl_mutex); } static void genl_unlock(void) { - up(&genl_sem); + mutex_unlock(&genl_mutex); if (genl_sock && genl_sock->sk_receive_queue.qlen) genl_sock->sk_data_ready(genl_sock, 0); -- cgit v1.2.3-59-g8ed1b From b0defcdbd2b7da7694e2645da92716cea0a3c0ff Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Sun, 26 Mar 2006 01:37:20 -0800 Subject: [PATCH] ipmi: add generic PCI handling Modify the PCI hanling code for the IPMI driver to use the new method of tables and registering, and adds more generic PCI handling for IPMI. Unfortunately, this required a rather large rework of the way the driver did detection so it would be more event-driven. [bunk@stusta.de: make a struct static] Signed-off-by: Corey Minyard Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 947 ++++++++++++++++++++------------------- drivers/char/ipmi/ipmi_si_sm.h | 3 +- 2 files changed, 496 insertions(+), 454 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index e59b638766ef..f3b3b23c5330 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_HIGH_RES_TIMERS @@ -109,6 +110,7 @@ enum si_intf_state { enum si_type { SI_KCS, SI_SMIC, SI_BT }; +static char *si_to_str[] = { "KCS", "SMIC", "BT" }; struct ipmi_device_id { unsigned char device_id; @@ -147,6 +149,9 @@ struct smi_info int (*irq_setup)(struct smi_info *info); void (*irq_cleanup)(struct smi_info *info); unsigned int io_size; + char *addr_source; /* ACPI, PCI, SMBIOS, hardcode, default. */ + void (*addr_source_cleanup)(struct smi_info *info); + void *addr_source_data; /* Per-OEM handler, called from handle_flags(). Returns 1 when handle_flags() needs to be re-run @@ -224,8 +229,12 @@ struct smi_info unsigned long incoming_messages; struct task_struct *thread; + + struct list_head link; }; +static int try_smi_init(struct smi_info *smi); + static struct notifier_block *xaction_notifier_list; static int register_xaction_notifier(struct notifier_block * nb) { @@ -271,13 +280,13 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) spin_lock(&(smi_info->msg_lock)); /* Pick the high priority queue first. */ - if (! list_empty(&(smi_info->hp_xmit_msgs))) { + if (!list_empty(&(smi_info->hp_xmit_msgs))) { entry = smi_info->hp_xmit_msgs.next; - } else if (! list_empty(&(smi_info->xmit_msgs))) { + } else if (!list_empty(&(smi_info->xmit_msgs))) { entry = smi_info->xmit_msgs.next; } - if (! entry) { + if (!entry) { smi_info->curr_msg = NULL; rv = SI_SM_IDLE; } else { @@ -344,7 +353,7 @@ static void start_clear_flags(struct smi_info *smi_info) memory, we will re-enable the interrupt. */ static inline void disable_si_irq(struct smi_info *smi_info) { - if ((smi_info->irq) && (! smi_info->interrupt_disabled)) { + if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { disable_irq_nosync(smi_info->irq); smi_info->interrupt_disabled = 1; } @@ -375,7 +384,7 @@ static void handle_flags(struct smi_info *smi_info) } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { /* Messages available. */ smi_info->curr_msg = ipmi_alloc_smi_msg(); - if (! smi_info->curr_msg) { + if (!smi_info->curr_msg) { disable_si_irq(smi_info); smi_info->si_state = SI_NORMAL; return; @@ -394,7 +403,7 @@ static void handle_flags(struct smi_info *smi_info) } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { /* Events available. */ smi_info->curr_msg = ipmi_alloc_smi_msg(); - if (! smi_info->curr_msg) { + if (!smi_info->curr_msg) { disable_si_irq(smi_info); smi_info->si_state = SI_NORMAL; return; @@ -430,7 +439,7 @@ static void handle_transaction_done(struct smi_info *smi_info) #endif switch (smi_info->si_state) { case SI_NORMAL: - if (! smi_info->curr_msg) + if (!smi_info->curr_msg) break; smi_info->curr_msg->rsp_size @@ -880,7 +889,7 @@ static void smi_timeout(unsigned long data) smi_info->last_timeout_jiffies = jiffies_now; - if ((smi_info->irq) && (! smi_info->interrupt_disabled)) { + if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { /* Running with interrupts, only do long timeouts. */ smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; spin_lock_irqsave(&smi_info->count_lock, flags); @@ -974,15 +983,12 @@ static struct ipmi_smi_handlers handlers = a default IO port, and 1 ACPI/SPMI address. That sets SI_MAX_DRIVERS */ #define SI_MAX_PARMS 4 -#define SI_MAX_DRIVERS ((SI_MAX_PARMS * 2) + 2) -static struct smi_info *smi_infos[SI_MAX_DRIVERS] = -{ NULL, NULL, NULL, NULL }; +static LIST_HEAD(smi_infos); +static DECLARE_MUTEX(smi_infos_lock); +static int smi_num; /* Used to sequence the SMIs */ #define DEVICE_NAME "ipmi_si" -#define DEFAULT_KCS_IO_PORT 0xca2 -#define DEFAULT_SMIC_IO_PORT 0xca9 -#define DEFAULT_BT_IO_PORT 0xe4 #define DEFAULT_REGSPACING 1 static int si_trydefaults = 1; @@ -1053,38 +1059,23 @@ MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for" " by interface number."); +#define IPMI_IO_ADDR_SPACE 0 #define IPMI_MEM_ADDR_SPACE 1 -#define IPMI_IO_ADDR_SPACE 2 +static char *addr_space_to_str[] = { "I/O", "memory" }; -#if defined(CONFIG_ACPI) || defined(CONFIG_DMI) || defined(CONFIG_PCI) -static int is_new_interface(int intf, u8 addr_space, unsigned long base_addr) +static void std_irq_cleanup(struct smi_info *info) { - int i; - - for (i = 0; i < SI_MAX_PARMS; ++i) { - /* Don't check our address. */ - if (i == intf) - continue; - if (si_type[i] != NULL) { - if ((addr_space == IPMI_MEM_ADDR_SPACE && - base_addr == addrs[i]) || - (addr_space == IPMI_IO_ADDR_SPACE && - base_addr == ports[i])) - return 0; - } - else - break; - } - - return 1; + if (info->si_type == SI_BT) + /* Disable the interrupt in the BT interface. */ + info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, 0); + free_irq(info->irq, info); } -#endif static int std_irq_setup(struct smi_info *info) { int rv; - if (! info->irq) + if (!info->irq) return 0; if (info->si_type == SI_BT) { @@ -1093,7 +1084,7 @@ static int std_irq_setup(struct smi_info *info) SA_INTERRUPT, DEVICE_NAME, info); - if (! rv) + if (!rv) /* Enable the interrupt in the BT interface. */ info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, IPMI_BT_INTMASK_ENABLE_IRQ_BIT); @@ -1110,88 +1101,78 @@ static int std_irq_setup(struct smi_info *info) DEVICE_NAME, info->irq); info->irq = 0; } else { + info->irq_cleanup = std_irq_cleanup; printk(" Using irq %d\n", info->irq); } return rv; } -static void std_irq_cleanup(struct smi_info *info) -{ - if (! info->irq) - return; - - if (info->si_type == SI_BT) - /* Disable the interrupt in the BT interface. */ - info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, 0); - free_irq(info->irq, info); -} - static unsigned char port_inb(struct si_sm_io *io, unsigned int offset) { - unsigned int *addr = io->info; + unsigned int addr = io->addr_data; - return inb((*addr)+(offset*io->regspacing)); + return inb(addr + (offset * io->regspacing)); } static void port_outb(struct si_sm_io *io, unsigned int offset, unsigned char b) { - unsigned int *addr = io->info; + unsigned int addr = io->addr_data; - outb(b, (*addr)+(offset * io->regspacing)); + outb(b, addr + (offset * io->regspacing)); } static unsigned char port_inw(struct si_sm_io *io, unsigned int offset) { - unsigned int *addr = io->info; + unsigned int addr = io->addr_data; - return (inw((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff; + return (inw(addr + (offset * io->regspacing)) >> io->regshift) & 0xff; } static void port_outw(struct si_sm_io *io, unsigned int offset, unsigned char b) { - unsigned int *addr = io->info; + unsigned int addr = io->addr_data; - outw(b << io->regshift, (*addr)+(offset * io->regspacing)); + outw(b << io->regshift, addr + (offset * io->regspacing)); } static unsigned char port_inl(struct si_sm_io *io, unsigned int offset) { - unsigned int *addr = io->info; + unsigned int addr = io->addr_data; - return (inl((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff; + return (inl(addr + (offset * io->regspacing)) >> io->regshift) & 0xff; } static void port_outl(struct si_sm_io *io, unsigned int offset, unsigned char b) { - unsigned int *addr = io->info; + unsigned int addr = io->addr_data; - outl(b << io->regshift, (*addr)+(offset * io->regspacing)); + outl(b << io->regshift, addr+(offset * io->regspacing)); } static void port_cleanup(struct smi_info *info) { - unsigned int *addr = info->io.info; - int mapsize; + unsigned int addr = info->io.addr_data; + int mapsize; - if (addr && (*addr)) { + if (addr) { mapsize = ((info->io_size * info->io.regspacing) - (info->io.regspacing - info->io.regsize)); - release_region (*addr, mapsize); + release_region (addr, mapsize); } kfree(info); } static int port_setup(struct smi_info *info) { - unsigned int *addr = info->io.info; - int mapsize; + unsigned int addr = info->io.addr_data; + int mapsize; - if (! addr || (! *addr)) + if (!addr) return -ENODEV; info->io_cleanup = port_cleanup; @@ -1225,51 +1206,11 @@ static int port_setup(struct smi_info *info) mapsize = ((info->io_size * info->io.regspacing) - (info->io.regspacing - info->io.regsize)); - if (request_region(*addr, mapsize, DEVICE_NAME) == NULL) + if (request_region(addr, mapsize, DEVICE_NAME) == NULL) return -EIO; return 0; } -static int try_init_port(int intf_num, struct smi_info **new_info) -{ - struct smi_info *info; - - if (! ports[intf_num]) - return -ENODEV; - - if (! is_new_interface(intf_num, IPMI_IO_ADDR_SPACE, - ports[intf_num])) - return -ENODEV; - - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (! info) { - printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n"); - return -ENOMEM; - } - memset(info, 0, sizeof(*info)); - - info->io_setup = port_setup; - info->io.info = &(ports[intf_num]); - info->io.addr = NULL; - info->io.regspacing = regspacings[intf_num]; - if (! info->io.regspacing) - info->io.regspacing = DEFAULT_REGSPACING; - info->io.regsize = regsizes[intf_num]; - if (! info->io.regsize) - info->io.regsize = DEFAULT_REGSPACING; - info->io.regshift = regshifts[intf_num]; - info->irq = 0; - info->irq_setup = NULL; - *new_info = info; - - if (si_type[intf_num] == NULL) - si_type[intf_num] = "kcs"; - - printk("ipmi_si: Trying \"%s\" at I/O port 0x%x\n", - si_type[intf_num], ports[intf_num]); - return 0; -} - static unsigned char intf_mem_inb(struct si_sm_io *io, unsigned int offset) { return readb((io->addr)+(offset * io->regspacing)); @@ -1321,7 +1262,7 @@ static void mem_outq(struct si_sm_io *io, unsigned int offset, static void mem_cleanup(struct smi_info *info) { - unsigned long *addr = info->io.info; + unsigned long addr = info->io.addr_data; int mapsize; if (info->io.addr) { @@ -1330,17 +1271,17 @@ static void mem_cleanup(struct smi_info *info) mapsize = ((info->io_size * info->io.regspacing) - (info->io.regspacing - info->io.regsize)); - release_mem_region(*addr, mapsize); + release_mem_region(addr, mapsize); } kfree(info); } static int mem_setup(struct smi_info *info) { - unsigned long *addr = info->io.info; + unsigned long addr = info->io.addr_data; int mapsize; - if (! addr || (! *addr)) + if (!addr) return -ENODEV; info->io_cleanup = mem_cleanup; @@ -1380,57 +1321,83 @@ static int mem_setup(struct smi_info *info) mapsize = ((info->io_size * info->io.regspacing) - (info->io.regspacing - info->io.regsize)); - if (request_mem_region(*addr, mapsize, DEVICE_NAME) == NULL) + if (request_mem_region(addr, mapsize, DEVICE_NAME) == NULL) return -EIO; - info->io.addr = ioremap(*addr, mapsize); + info->io.addr = ioremap(addr, mapsize); if (info->io.addr == NULL) { - release_mem_region(*addr, mapsize); + release_mem_region(addr, mapsize); return -EIO; } return 0; } -static int try_init_mem(int intf_num, struct smi_info **new_info) + +static __devinit void hardcode_find_bmc(void) { + int i; struct smi_info *info; - if (! addrs[intf_num]) - return -ENODEV; + for (i = 0; i < SI_MAX_PARMS; i++) { + if (!ports[i] && !addrs[i]) + continue; - if (! is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE, - addrs[intf_num])) - return -ENODEV; + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return; - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (! info) { - printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n"); - return -ENOMEM; - } - memset(info, 0, sizeof(*info)); + info->addr_source = "hardcoded"; - info->io_setup = mem_setup; - info->io.info = &addrs[intf_num]; - info->io.addr = NULL; - info->io.regspacing = regspacings[intf_num]; - if (! info->io.regspacing) - info->io.regspacing = DEFAULT_REGSPACING; - info->io.regsize = regsizes[intf_num]; - if (! info->io.regsize) - info->io.regsize = DEFAULT_REGSPACING; - info->io.regshift = regshifts[intf_num]; - info->irq = 0; - info->irq_setup = NULL; - *new_info = info; + if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { + info->si_type = SI_KCS; + } else if (strcmp(si_type[i], "smic") == 0) { + info->si_type = SI_SMIC; + } else if (strcmp(si_type[i], "bt") == 0) { + info->si_type = SI_BT; + } else { + printk(KERN_WARNING + "ipmi_si: Interface type specified " + "for interface %d, was invalid: %s\n", + i, si_type[i]); + kfree(info); + continue; + } - if (si_type[intf_num] == NULL) - si_type[intf_num] = "kcs"; + if (ports[i]) { + /* An I/O port */ + info->io_setup = port_setup; + info->io.addr_data = ports[i]; + info->io.addr_type = IPMI_IO_ADDR_SPACE; + } else if (addrs[i]) { + /* A memory port */ + info->io_setup = mem_setup; + info->io.addr_data = addrs[i]; + info->io.addr_type = IPMI_MEM_ADDR_SPACE; + } else { + printk(KERN_WARNING + "ipmi_si: Interface type specified " + "for interface %d, " + "but port and address were not set or " + "set to zero.\n", i); + kfree(info); + continue; + } - printk("ipmi_si: Trying \"%s\" at memory address 0x%lx\n", - si_type[intf_num], addrs[intf_num]); - return 0; -} + info->io.addr = NULL; + info->io.regspacing = regspacings[i]; + if (!info->io.regspacing) + info->io.regspacing = DEFAULT_REGSPACING; + info->io.regsize = regsizes[i]; + if (!info->io.regsize) + info->io.regsize = DEFAULT_REGSPACING; + info->io.regshift = regshifts[i]; + info->irq = irqs[i]; + if (info->irq) + info->irq_setup = std_irq_setup; + try_smi_init(info); + } +} #ifdef CONFIG_ACPI @@ -1470,11 +1437,19 @@ static u32 ipmi_acpi_gpe(void *context) return ACPI_INTERRUPT_HANDLED; } +static void acpi_gpe_irq_cleanup(struct smi_info *info) +{ + if (!info->irq) + return; + + acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); +} + static int acpi_gpe_irq_setup(struct smi_info *info) { acpi_status status; - if (! info->irq) + if (!info->irq) return 0; /* FIXME - is level triggered right? */ @@ -1491,19 +1466,12 @@ static int acpi_gpe_irq_setup(struct smi_info *info) info->irq = 0; return -EINVAL; } else { + info->irq_cleanup = acpi_gpe_irq_cleanup; printk(" Using ACPI GPE %d\n", info->irq); return 0; } } -static void acpi_gpe_irq_cleanup(struct smi_info *info) -{ - if (! info->irq) - return; - - acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); -} - /* * Defined at * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/Docs/TechPapers/IA64/hpspmi.pdf @@ -1546,28 +1514,12 @@ struct SPMITable { s8 spmi_id[1]; /* A '\0' terminated array starts here. */ }; -static int try_init_acpi(int intf_num, struct smi_info **new_info) +static __devinit int try_init_acpi(struct SPMITable *spmi) { struct smi_info *info; - acpi_status status; - struct SPMITable *spmi; char *io_type; u8 addr_space; - if (acpi_disabled) - return -ENODEV; - - if (acpi_failure) - return -ENODEV; - - status = acpi_get_firmware_table("SPMI", intf_num+1, - ACPI_LOGICAL_ADDRESSING, - (struct acpi_table_header **) &spmi); - if (status != AE_OK) { - acpi_failure = 1; - return -ENODEV; - } - if (spmi->IPMIlegacy != 1) { printk(KERN_INFO "IPMI: Bad SPMI legacy %d\n", spmi->IPMIlegacy); return -ENODEV; @@ -1577,47 +1529,42 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) addr_space = IPMI_MEM_ADDR_SPACE; else addr_space = IPMI_IO_ADDR_SPACE; - if (! is_new_interface(-1, addr_space, spmi->addr.address)) - return -ENODEV; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); + return -ENOMEM; + } + + info->addr_source = "ACPI"; /* Figure out the interface type. */ switch (spmi->InterfaceType) { case 1: /* KCS */ - si_type[intf_num] = "kcs"; + info->si_type = SI_KCS; break; - case 2: /* SMIC */ - si_type[intf_num] = "smic"; + info->si_type = SI_SMIC; break; - case 3: /* BT */ - si_type[intf_num] = "bt"; + info->si_type = SI_BT; break; - default: printk(KERN_INFO "ipmi_si: Unknown ACPI/SPMI SI type %d\n", spmi->InterfaceType); + kfree(info); return -EIO; } - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (! info) { - printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); - return -ENOMEM; - } - memset(info, 0, sizeof(*info)); - if (spmi->InterruptType & 1) { /* We've got a GPE interrupt. */ info->irq = spmi->GPE; info->irq_setup = acpi_gpe_irq_setup; - info->irq_cleanup = acpi_gpe_irq_cleanup; } else if (spmi->InterruptType & 2) { /* We've got an APIC/SAPIC interrupt. */ info->irq = spmi->GlobalSystemInterrupt; info->irq_setup = std_irq_setup; - info->irq_cleanup = std_irq_cleanup; } else { /* Use the default interrupt setting. */ info->irq = 0; @@ -1626,43 +1573,60 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) if (spmi->addr.register_bit_width) { /* A (hopefully) properly formed register bit width. */ - regspacings[intf_num] = spmi->addr.register_bit_width / 8; info->io.regspacing = spmi->addr.register_bit_width / 8; } else { - regspacings[intf_num] = DEFAULT_REGSPACING; info->io.regspacing = DEFAULT_REGSPACING; } - regsizes[intf_num] = regspacings[intf_num]; - info->io.regsize = regsizes[intf_num]; - regshifts[intf_num] = spmi->addr.register_bit_offset; - info->io.regshift = regshifts[intf_num]; + info->io.regsize = info->io.regspacing; + info->io.regshift = spmi->addr.register_bit_offset; if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { io_type = "memory"; info->io_setup = mem_setup; - addrs[intf_num] = spmi->addr.address; - info->io.info = &(addrs[intf_num]); + info->io.addr_type = IPMI_IO_ADDR_SPACE; } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { io_type = "I/O"; info->io_setup = port_setup; - ports[intf_num] = spmi->addr.address; - info->io.info = &(ports[intf_num]); + info->io.addr_type = IPMI_MEM_ADDR_SPACE; } else { kfree(info); printk("ipmi_si: Unknown ACPI I/O Address type\n"); return -EIO; } + info->io.addr_data = spmi->addr.address; - *new_info = info; + try_smi_init(info); - printk("ipmi_si: ACPI/SPMI specifies \"%s\" %s SI @ 0x%lx\n", - si_type[intf_num], io_type, (unsigned long) spmi->addr.address); return 0; } + +static __devinit void acpi_find_bmc(void) +{ + acpi_status status; + struct SPMITable *spmi; + int i; + + if (acpi_disabled) + return; + + if (acpi_failure) + return; + + for (i = 0; ; i++) { + status = acpi_get_firmware_table("SPMI", i+1, + ACPI_LOGICAL_ADDRESSING, + (struct acpi_table_header **) + &spmi); + if (status != AE_OK) + return; + + try_init_acpi(spmi); + } +} #endif #ifdef CONFIG_DMI -typedef struct dmi_ipmi_data +struct dmi_ipmi_data { u8 type; u8 addr_space; @@ -1670,49 +1634,46 @@ typedef struct dmi_ipmi_data u8 irq; u8 offset; u8 slave_addr; -} dmi_ipmi_data_t; - -static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; -static int dmi_data_entries; +}; -static int __init decode_dmi(struct dmi_header *dm, int intf_num) +static int __devinit decode_dmi(struct dmi_header *dm, + struct dmi_ipmi_data *dmi) { u8 *data = (u8 *)dm; unsigned long base_addr; u8 reg_spacing; u8 len = dm->length; - dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; - ipmi_data->type = data[4]; + dmi->type = data[4]; memcpy(&base_addr, data+8, sizeof(unsigned long)); if (len >= 0x11) { if (base_addr & 1) { /* I/O */ base_addr &= 0xFFFE; - ipmi_data->addr_space = IPMI_IO_ADDR_SPACE; + dmi->addr_space = IPMI_IO_ADDR_SPACE; } else { /* Memory */ - ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE; + dmi->addr_space = IPMI_MEM_ADDR_SPACE; } /* If bit 4 of byte 0x10 is set, then the lsb for the address is odd. */ - ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); + dmi->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); - ipmi_data->irq = data[0x11]; + dmi->irq = data[0x11]; /* The top two bits of byte 0x10 hold the register spacing. */ reg_spacing = (data[0x10] & 0xC0) >> 6; switch(reg_spacing){ case 0x00: /* Byte boundaries */ - ipmi_data->offset = 1; + dmi->offset = 1; break; case 0x01: /* 32-bit boundaries */ - ipmi_data->offset = 4; + dmi->offset = 4; break; case 0x02: /* 16-byte boundaries */ - ipmi_data->offset = 16; + dmi->offset = 16; break; default: /* Some other interface, just ignore it. */ @@ -1726,205 +1687,213 @@ static int __init decode_dmi(struct dmi_header *dm, int intf_num) * wrong (and all that I have seen are I/O) so we just * ignore that bit and assume I/O. Systems that use * memory should use the newer spec, anyway. */ - ipmi_data->base_addr = base_addr & 0xfffe; - ipmi_data->addr_space = IPMI_IO_ADDR_SPACE; - ipmi_data->offset = 1; - } - - ipmi_data->slave_addr = data[6]; - - if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) { - dmi_data_entries++; - return 0; + dmi->base_addr = base_addr & 0xfffe; + dmi->addr_space = IPMI_IO_ADDR_SPACE; + dmi->offset = 1; } - memset(ipmi_data, 0, sizeof(dmi_ipmi_data_t)); + dmi->slave_addr = data[6]; - return -1; + return 0; } -static void __init dmi_find_bmc(void) +static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) { - struct dmi_device *dev = NULL; - int intf_num = 0; - - while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { - if (intf_num >= SI_MAX_DRIVERS) - break; + struct smi_info *info; - decode_dmi((struct dmi_header *) dev->device_data, intf_num++); + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + printk(KERN_ERR + "ipmi_si: Could not allocate SI data\n"); + return; } -} - -static int try_init_smbios(int intf_num, struct smi_info **new_info) -{ - struct smi_info *info; - dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; - char *io_type; - if (intf_num >= dmi_data_entries) - return -ENODEV; + info->addr_source = "SMBIOS"; switch (ipmi_data->type) { - case 0x01: /* KCS */ - si_type[intf_num] = "kcs"; - break; - case 0x02: /* SMIC */ - si_type[intf_num] = "smic"; - break; - case 0x03: /* BT */ - si_type[intf_num] = "bt"; - break; - default: - return -EIO; - } - - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (! info) { - printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n"); - return -ENOMEM; + case 0x01: /* KCS */ + info->si_type = SI_KCS; + break; + case 0x02: /* SMIC */ + info->si_type = SI_SMIC; + break; + case 0x03: /* BT */ + info->si_type = SI_BT; + break; + default: + return; } - memset(info, 0, sizeof(*info)); - if (ipmi_data->addr_space == 1) { - io_type = "memory"; + switch (ipmi_data->addr_space) { + case IPMI_MEM_ADDR_SPACE: info->io_setup = mem_setup; - addrs[intf_num] = ipmi_data->base_addr; - info->io.info = &(addrs[intf_num]); - } else if (ipmi_data->addr_space == 2) { - io_type = "I/O"; + info->io.addr_type = IPMI_MEM_ADDR_SPACE; + break; + + case IPMI_IO_ADDR_SPACE: info->io_setup = port_setup; - ports[intf_num] = ipmi_data->base_addr; - info->io.info = &(ports[intf_num]); - } else { + info->io.addr_type = IPMI_IO_ADDR_SPACE; + break; + + default: kfree(info); - printk("ipmi_si: Unknown SMBIOS I/O Address type.\n"); - return -EIO; + printk(KERN_WARNING + "ipmi_si: Unknown SMBIOS I/O Address type: %d.\n", + ipmi_data->addr_space); + return; } + info->io.addr_data = ipmi_data->base_addr; - regspacings[intf_num] = ipmi_data->offset; - info->io.regspacing = regspacings[intf_num]; - if (! info->io.regspacing) + info->io.regspacing = ipmi_data->offset; + if (!info->io.regspacing) info->io.regspacing = DEFAULT_REGSPACING; info->io.regsize = DEFAULT_REGSPACING; - info->io.regshift = regshifts[intf_num]; + info->io.regshift = 0; info->slave_addr = ipmi_data->slave_addr; - irqs[intf_num] = ipmi_data->irq; + info->irq = ipmi_data->irq; + if (info->irq) + info->irq_setup = std_irq_setup; - *new_info = info; + try_smi_init(info); +} - printk("ipmi_si: Found SMBIOS-specified state machine at %s" - " address 0x%lx, slave address 0x%x\n", - io_type, (unsigned long)ipmi_data->base_addr, - ipmi_data->slave_addr); - return 0; +static void __devinit dmi_find_bmc(void) +{ + struct dmi_device *dev = NULL; + struct dmi_ipmi_data data; + int rv; + + while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { + rv = decode_dmi((struct dmi_header *) dev->device_data, &data); + if (!rv) + try_init_dmi(&data); + } } #endif /* CONFIG_DMI */ #ifdef CONFIG_PCI -#define PCI_ERMC_CLASSCODE 0x0C0700 +#define PCI_ERMC_CLASSCODE 0x0C0700 +#define PCI_ERMC_CLASSCODE_MASK 0xffffff00 +#define PCI_ERMC_CLASSCODE_TYPE_MASK 0xff +#define PCI_ERMC_CLASSCODE_TYPE_SMIC 0x00 +#define PCI_ERMC_CLASSCODE_TYPE_KCS 0x01 +#define PCI_ERMC_CLASSCODE_TYPE_BT 0x02 + #define PCI_HP_VENDOR_ID 0x103C #define PCI_MMC_DEVICE_ID 0x121A #define PCI_MMC_ADDR_CW 0x10 -/* Avoid more than one attempt to probe pci smic. */ -static int pci_smic_checked = 0; +static void ipmi_pci_cleanup(struct smi_info *info) +{ + struct pci_dev *pdev = info->addr_source_data; + + pci_disable_device(pdev); +} -static int find_pci_smic(int intf_num, struct smi_info **new_info) +static int __devinit ipmi_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - struct smi_info *info; - int error; - struct pci_dev *pci_dev = NULL; - u16 base_addr; - int fe_rmc = 0; + int rv; + int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; + struct smi_info *info; + int first_reg_offset = 0; - if (pci_smic_checked) - return -ENODEV; + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return ENOMEM; - pci_smic_checked = 1; + info->addr_source = "PCI"; - pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL); - if (! pci_dev) { - pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL); - if (pci_dev && (pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID)) - fe_rmc = 1; - else - return -ENODEV; - } + switch (class_type) { + case PCI_ERMC_CLASSCODE_TYPE_SMIC: + info->si_type = SI_SMIC; + break; - error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); - if (error) - { - pci_dev_put(pci_dev); - printk(KERN_ERR - "ipmi_si: pci_read_config_word() failed (%d).\n", - error); - return -ENODEV; + case PCI_ERMC_CLASSCODE_TYPE_KCS: + info->si_type = SI_KCS; + break; + + case PCI_ERMC_CLASSCODE_TYPE_BT: + info->si_type = SI_BT; + break; + + default: + kfree(info); + printk(KERN_INFO "ipmi_si: %s: Unknown IPMI type: %d\n", + pci_name(pdev), class_type); + return ENOMEM; } - /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ - if (! (base_addr & 0x0001)) - { - pci_dev_put(pci_dev); - printk(KERN_ERR - "ipmi_si: memory mapped I/O not supported for PCI" - " smic.\n"); - return -ENODEV; + rv = pci_enable_device(pdev); + if (rv) { + printk(KERN_ERR "ipmi_si: %s: couldn't enable PCI device\n", + pci_name(pdev)); + kfree(info); + return rv; } - base_addr &= 0xFFFE; - if (! fe_rmc) - /* Data register starts at base address + 1 in eRMC */ - ++base_addr; + info->addr_source_cleanup = ipmi_pci_cleanup; + info->addr_source_data = pdev; - if (! is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { - pci_dev_put(pci_dev); - return -ENODEV; - } + if (pdev->subsystem_vendor == PCI_HP_VENDOR_ID) + first_reg_offset = 1; - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (! info) { - pci_dev_put(pci_dev); - printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); - return -ENOMEM; + if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { + info->io_setup = port_setup; + info->io.addr_type = IPMI_IO_ADDR_SPACE; + } else { + info->io_setup = mem_setup; + info->io.addr_type = IPMI_MEM_ADDR_SPACE; } - memset(info, 0, sizeof(*info)); + info->io.addr_data = pci_resource_start(pdev, 0); - info->io_setup = port_setup; - ports[intf_num] = base_addr; - info->io.info = &(ports[intf_num]); - info->io.regspacing = regspacings[intf_num]; - if (! info->io.regspacing) - info->io.regspacing = DEFAULT_REGSPACING; + info->io.regspacing = DEFAULT_REGSPACING; info->io.regsize = DEFAULT_REGSPACING; - info->io.regshift = regshifts[intf_num]; + info->io.regshift = 0; - *new_info = info; + info->irq = pdev->irq; + if (info->irq) + info->irq_setup = std_irq_setup; - irqs[intf_num] = pci_dev->irq; - si_type[intf_num] = "smic"; + return try_smi_init(info); +} - printk("ipmi_si: Found PCI SMIC at I/O address 0x%lx\n", - (long unsigned int) base_addr); +static void __devexit ipmi_pci_remove(struct pci_dev *pdev) +{ +} - pci_dev_put(pci_dev); +#ifdef CONFIG_PM +static int ipmi_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ return 0; } -#endif /* CONFIG_PCI */ -static int try_init_plug_and_play(int intf_num, struct smi_info **new_info) +static int ipmi_pci_resume(struct pci_dev *pdev) { -#ifdef CONFIG_PCI - if (find_pci_smic(intf_num, new_info) == 0) - return 0; + return 0; +} #endif - /* Include other methods here. */ - return -ENODEV; -} +static struct pci_device_id ipmi_pci_devices[] = { + { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) }, + { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE) } +}; +MODULE_DEVICE_TABLE(pci, ipmi_pci_devices); + +static struct pci_driver ipmi_pci_driver = { + .name = DEVICE_NAME, + .id_table = ipmi_pci_devices, + .probe = ipmi_pci_probe, + .remove = __devexit_p(ipmi_pci_remove), +#ifdef CONFIG_PM + .suspend = ipmi_pci_suspend, + .resume = ipmi_pci_resume, +#endif +}; +#endif /* CONFIG_PCI */ static int try_get_dev_id(struct smi_info *smi_info) @@ -1936,7 +1905,7 @@ static int try_get_dev_id(struct smi_info *smi_info) int rv = 0; resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); - if (! resp) + if (!resp) return -ENOMEM; /* Do a Get Device ID command, since it comes back with some @@ -2018,7 +1987,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off, struct smi_info *smi = data; out += sprintf(out, "interrupts_enabled: %d\n", - smi->irq && ! smi->interrupt_disabled); + smi->irq && !smi->interrupt_disabled); out += sprintf(out, "short_timeouts: %ld\n", smi->short_timeouts); out += sprintf(out, "long_timeouts: %ld\n", @@ -2094,7 +2063,7 @@ static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info) { struct ipmi_device_id *id = &smi_info->device_id; const char mfr[3]=DELL_IANA_MFR_ID; - if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr))) { + if (!memcmp(mfr, id->manufacturer_id, sizeof(mfr))) { if (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID && id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV && id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) { @@ -2170,7 +2139,7 @@ setup_dell_poweredge_bt_xaction_handler(struct smi_info *smi_info) { struct ipmi_device_id *id = &smi_info->device_id; const char mfr[3]=DELL_IANA_MFR_ID; - if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr)) && + if (!memcmp(mfr, id->manufacturer_id, sizeof(mfr)) && smi_info->si_type == SI_BT) register_xaction_notifier(&dell_poweredge_bt_xaction_notifier); } @@ -2200,62 +2169,110 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info) del_timer_sync(&smi_info->si_timer); } -/* Returns 0 if initialized, or negative on an error. */ -static int init_one_smi(int intf_num, struct smi_info **smi) +static struct ipmi_default_vals +{ + int type; + int port; +} __devinit ipmi_defaults[] = +{ + { .type = SI_KCS, .port = 0xca2 }, + { .type = SI_SMIC, .port = 0xca9 }, + { .type = SI_BT, .port = 0xe4 }, + { .port = 0 } +}; + +static __devinit void default_find_bmc(void) +{ + struct smi_info *info; + int i; + + for (i = 0; ; i++) { + if (!ipmi_defaults[i].port) + break; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return; + + info->addr_source = NULL; + + info->si_type = ipmi_defaults[i].type; + info->io_setup = port_setup; + info->io.addr_data = ipmi_defaults[i].port; + info->io.addr_type = IPMI_IO_ADDR_SPACE; + + info->io.addr = NULL; + info->io.regspacing = DEFAULT_REGSPACING; + info->io.regsize = DEFAULT_REGSPACING; + info->io.regshift = 0; + + if (try_smi_init(info) == 0) { + /* Found one... */ + printk(KERN_INFO "ipmi_si: Found default %s state" + " machine at %s address 0x%lx\n", + si_to_str[info->si_type], + addr_space_to_str[info->io.addr_type], + info->io.addr_data); + return; + } + } +} + +static int is_new_interface(struct smi_info *info) { - int rv; - struct smi_info *new_smi; + struct smi_info *e; + list_for_each_entry(e, &smi_infos, link) { + if (e->io.addr_type != info->io.addr_type) + continue; + if (e->io.addr_data == info->io.addr_data) + return 0; + } - rv = try_init_mem(intf_num, &new_smi); - if (rv) - rv = try_init_port(intf_num, &new_smi); -#ifdef CONFIG_ACPI - if (rv && si_trydefaults) - rv = try_init_acpi(intf_num, &new_smi); -#endif -#ifdef CONFIG_DMI - if (rv && si_trydefaults) - rv = try_init_smbios(intf_num, &new_smi); -#endif - if (rv && si_trydefaults) - rv = try_init_plug_and_play(intf_num, &new_smi); + return 1; +} - if (rv) - return rv; +static int try_smi_init(struct smi_info *new_smi) +{ + int rv; + + if (new_smi->addr_source) { + printk(KERN_INFO "ipmi_si: Trying %s-specified %s state" + " machine at %s address 0x%lx, slave address 0x%x," + " irq %d\n", + new_smi->addr_source, + si_to_str[new_smi->si_type], + addr_space_to_str[new_smi->io.addr_type], + new_smi->io.addr_data, + new_smi->slave_addr, new_smi->irq); + } + + down(&smi_infos_lock); + if (!is_new_interface(new_smi)) { + printk(KERN_WARNING "ipmi_si: duplicate interface\n"); + rv = -EBUSY; + goto out_err; + } /* So we know not to free it unless we have allocated one. */ new_smi->intf = NULL; new_smi->si_sm = NULL; new_smi->handlers = NULL; - if (! new_smi->irq_setup) { - new_smi->irq = irqs[intf_num]; - new_smi->irq_setup = std_irq_setup; - new_smi->irq_cleanup = std_irq_cleanup; - } - - /* Default to KCS if no type is specified. */ - if (si_type[intf_num] == NULL) { - if (si_trydefaults) - si_type[intf_num] = "kcs"; - else { - rv = -EINVAL; - goto out_err; - } - } - - /* Set up the state machine to use. */ - if (strcmp(si_type[intf_num], "kcs") == 0) { + switch (new_smi->si_type) { + case SI_KCS: new_smi->handlers = &kcs_smi_handlers; - new_smi->si_type = SI_KCS; - } else if (strcmp(si_type[intf_num], "smic") == 0) { + break; + + case SI_SMIC: new_smi->handlers = &smic_smi_handlers; - new_smi->si_type = SI_SMIC; - } else if (strcmp(si_type[intf_num], "bt") == 0) { + break; + + case SI_BT: new_smi->handlers = &bt_smi_handlers; - new_smi->si_type = SI_BT; - } else { + break; + + default: /* No support for anything else yet. */ rv = -EIO; goto out_err; @@ -2263,7 +2280,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) /* Allocate the state machine's data and initialize it. */ new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); - if (! new_smi->si_sm) { + if (!new_smi->si_sm) { printk(" Could not allocate state machine memory\n"); rv = -ENOMEM; goto out_err; @@ -2284,21 +2301,29 @@ static int init_one_smi(int intf_num, struct smi_info **smi) /* Do low-level detection first. */ if (new_smi->handlers->detect(new_smi->si_sm)) { + if (new_smi->addr_source) + printk(KERN_INFO "ipmi_si: Interface detection" + " failed\n"); rv = -ENODEV; goto out_err; } /* Attempt a get device id command. If it fails, we probably - don't have a SMI here. */ + don't have a BMC here. */ rv = try_get_dev_id(new_smi); - if (rv) + if (rv) { + if (new_smi->addr_source) + printk(KERN_INFO "ipmi_si: There appears to be no BMC" + " at this location\n"); goto out_err; + } setup_oem_data_handler(new_smi); setup_xaction_handlers(new_smi); /* Try to claim any interrupts. */ - new_smi->irq_setup(new_smi); + if (new_smi->irq_setup) + new_smi->irq_setup(new_smi); INIT_LIST_HEAD(&(new_smi->xmit_msgs)); INIT_LIST_HEAD(&(new_smi->hp_xmit_msgs)); @@ -2308,7 +2333,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) new_smi->interrupt_disabled = 0; atomic_set(&new_smi->stop_operation, 0); - new_smi->intf_num = intf_num; + new_smi->intf_num = smi_num; + smi_num++; /* Start clearing the flags before we enable interrupts or the timer to avoid racing with the timer. */ @@ -2365,9 +2391,11 @@ static int init_one_smi(int intf_num, struct smi_info **smi) goto out_err_stop_timer; } - *smi = new_smi; + list_add_tail(&new_smi->link, &smi_infos); + + up(&smi_infos_lock); - printk(" IPMI %s interface initialized\n", si_type[intf_num]); + printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]); return 0; @@ -2379,7 +2407,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) if (new_smi->intf) ipmi_unregister_smi(new_smi->intf); - new_smi->irq_cleanup(new_smi); + if (new_smi->irq_cleanup) + new_smi->irq_cleanup(new_smi); /* Wait until we know that we are out of any interrupt handlers might have been running before we freed the @@ -2391,16 +2420,18 @@ static int init_one_smi(int intf_num, struct smi_info **smi) new_smi->handlers->cleanup(new_smi->si_sm); kfree(new_smi->si_sm); } + if (new_smi->addr_source_cleanup) + new_smi->addr_source_cleanup(new_smi); if (new_smi->io_cleanup) new_smi->io_cleanup(new_smi); + up(&smi_infos_lock); + return rv; } -static __init int init_ipmi_si(void) +static __devinit int init_ipmi_si(void) { - int rv = 0; - int pos = 0; int i; char *str; @@ -2425,63 +2456,66 @@ static __init int init_ipmi_si(void) printk(KERN_INFO "IPMI System Interface driver.\n"); + hardcode_find_bmc(); + #ifdef CONFIG_DMI dmi_find_bmc(); #endif - rv = init_one_smi(0, &(smi_infos[pos])); - if (rv && ! ports[0] && si_trydefaults) { - /* If we are trying defaults and the initial port is - not set, then set it. */ - si_type[0] = "kcs"; - ports[0] = DEFAULT_KCS_IO_PORT; - rv = init_one_smi(0, &(smi_infos[pos])); - if (rv) { - /* No KCS - try SMIC */ - si_type[0] = "smic"; - ports[0] = DEFAULT_SMIC_IO_PORT; - rv = init_one_smi(0, &(smi_infos[pos])); - } - if (rv) { - /* No SMIC - try BT */ - si_type[0] = "bt"; - ports[0] = DEFAULT_BT_IO_PORT; - rv = init_one_smi(0, &(smi_infos[pos])); - } - } - if (rv == 0) - pos++; +#ifdef CONFIG_ACPI + if (si_trydefaults) + acpi_find_bmc(); +#endif - for (i = 1; i < SI_MAX_PARMS; i++) { - rv = init_one_smi(i, &(smi_infos[pos])); - if (rv == 0) - pos++; +#ifdef CONFIG_PCI + pci_module_init(&ipmi_pci_driver); +#endif + + if (si_trydefaults) { + down(&smi_infos_lock); + if (list_empty(&smi_infos)) { + /* No BMC was found, try defaults. */ + up(&smi_infos_lock); + default_find_bmc(); + } else { + up(&smi_infos_lock); + } } - if (smi_infos[0] == NULL) { + down(&smi_infos_lock); + if (list_empty(&smi_infos)) { + up(&smi_infos_lock); +#ifdef CONFIG_PCI + pci_unregister_driver(&ipmi_pci_driver); +#endif printk("ipmi_si: Unable to find any System Interface(s)\n"); return -ENODEV; + } else { + up(&smi_infos_lock); + return 0; } - - return 0; } module_init(init_ipmi_si); -static void __exit cleanup_one_si(struct smi_info *to_clean) +static void __devexit cleanup_one_si(struct smi_info *to_clean) { int rv; unsigned long flags; - if (! to_clean) + if (!to_clean) return; + list_del(&to_clean->link); + /* Tell the timer and interrupt handlers that we are shutting down. */ spin_lock_irqsave(&(to_clean->si_lock), flags); spin_lock(&(to_clean->msg_lock)); atomic_inc(&to_clean->stop_operation); - to_clean->irq_cleanup(to_clean); + + if (to_clean->irq_cleanup) + to_clean->irq_cleanup(to_clean); spin_unlock(&(to_clean->msg_lock)); spin_unlock_irqrestore(&(to_clean->si_lock), flags); @@ -2511,20 +2545,27 @@ static void __exit cleanup_one_si(struct smi_info *to_clean) kfree(to_clean->si_sm); + if (to_clean->addr_source_cleanup) + to_clean->addr_source_cleanup(to_clean); if (to_clean->io_cleanup) to_clean->io_cleanup(to_clean); } static __exit void cleanup_ipmi_si(void) { - int i; + struct smi_info *e, *tmp_e; - if (! initialized) + if (!initialized) return; - for (i = 0; i < SI_MAX_DRIVERS; i++) { - cleanup_one_si(smi_infos[i]); - } +#ifdef CONFIG_PCI + pci_unregister_driver(&ipmi_pci_driver); +#endif + + down(&smi_infos_lock); + list_for_each_entry_safe(e, tmp_e, &smi_infos, link) + cleanup_one_si(e); + up(&smi_infos_lock); } module_exit(cleanup_ipmi_si); diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h index bf3d4962d6a5..4b731b24dc16 100644 --- a/drivers/char/ipmi/ipmi_si_sm.h +++ b/drivers/char/ipmi/ipmi_si_sm.h @@ -50,11 +50,12 @@ struct si_sm_io /* Generic info used by the actual handling routines, the state machine shouldn't touch these. */ - void *info; void __iomem *addr; int regspacing; int regsize; int regshift; + int addr_type; + long addr_data; }; /* Results of SMI events. */ -- cgit v1.2.3-59-g8ed1b From 50c812b2b9513e3df34eae8c30cb2c221b79b2cb Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Sun, 26 Mar 2006 01:37:21 -0800 Subject: [PATCH] ipmi: add full sysfs support Add full driver model support for the IPMI driver. It links in the proper bus and device support. It adds an "ipmi" driver interface that has each BMC discovered by the driver (as a device). These BMCs appear in the devices/platform directory. If there are multiple interfaces to the same BMC, the driver should discover this and will only have one BMC entry. The BMC entry will have pointers to each interface device that connects to it. The device information (statistics and config information) has not yet been ported over to the driver model from proc, that will come later. This work was based on work by Yani Ioannou. I basically rewrote it using that code as a guide, but he still deserves credit :). [bunk@stusta.de: make ipmi_find_bmc_guid() static] Signed-off-by: Corey Minyard Signed-off-by: Yani Ioannou Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_devintf.c | 48 +++- drivers/char/ipmi/ipmi_msghandler.c | 552 +++++++++++++++++++++++++++++++++++- drivers/char/ipmi/ipmi_poweroff.c | 2 +- drivers/char/ipmi/ipmi_si_intf.c | 114 +++++--- drivers/char/ipmi/ipmi_watchdog.c | 2 +- include/linux/ipmi.h | 3 +- include/linux/ipmi_msgdefs.h | 1 + include/linux/ipmi_smi.h | 47 ++- 8 files changed, 712 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 7c0684deea06..932feedda262 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -90,7 +90,7 @@ static unsigned int ipmi_poll(struct file *file, poll_table *wait) spin_lock_irqsave(&priv->recv_msg_lock, flags); - if (! list_empty(&(priv->recv_msgs))) + if (!list_empty(&(priv->recv_msgs))) mask |= (POLLIN | POLLRDNORM); spin_unlock_irqrestore(&priv->recv_msg_lock, flags); @@ -789,21 +789,53 @@ MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By" " interface. Other values will set the major device number" " to that value."); +/* Keep track of the devices that are registered. */ +struct ipmi_reg_list { + dev_t dev; + struct list_head link; +}; +static LIST_HEAD(reg_list); +static DEFINE_MUTEX(reg_list_mutex); + static struct class *ipmi_class; -static void ipmi_new_smi(int if_num) +static void ipmi_new_smi(int if_num, struct device *device) { dev_t dev = MKDEV(ipmi_major, if_num); + struct ipmi_reg_list *entry; devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, "ipmidev/%d", if_num); - class_device_create(ipmi_class, NULL, dev, NULL, "ipmi%d", if_num); + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + printk(KERN_ERR "ipmi_devintf: Unable to create the" + " ipmi class device link\n"); + return; + } + entry->dev = dev; + + mutex_lock(®_list_mutex); + class_device_create(ipmi_class, NULL, dev, device, "ipmi%d", if_num); + list_add(&entry->link, ®_list); + mutex_unlock(®_list_mutex); } static void ipmi_smi_gone(int if_num) { - class_device_destroy(ipmi_class, MKDEV(ipmi_major, if_num)); + dev_t dev = MKDEV(ipmi_major, if_num); + struct ipmi_reg_list *entry; + + mutex_lock(®_list_mutex); + list_for_each_entry(entry, ®_list, link) { + if (entry->dev == dev) { + list_del(&entry->link); + kfree(entry); + break; + } + } + class_device_destroy(ipmi_class, dev); + mutex_unlock(®_list_mutex); devfs_remove("ipmidev/%d", if_num); } @@ -856,6 +888,14 @@ module_init(init_ipmi_devintf); static __exit void cleanup_ipmi(void) { + struct ipmi_reg_list *entry, *entry2; + mutex_lock(®_list_mutex); + list_for_each_entry_safe(entry, entry2, ®_list, link) { + list_del(&entry->link); + class_device_destroy(ipmi_class, entry->dev); + kfree(entry); + } + mutex_unlock(®_list_mutex); class_destroy(ipmi_class); ipmi_smi_watcher_unregister(&smi_watcher); devfs_remove(DEVICE_NAME); diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index abd4c5118a1b..f553b7a86841 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -162,6 +162,28 @@ struct ipmi_proc_entry }; #endif +struct bmc_device +{ + struct platform_device *dev; + struct ipmi_device_id id; + unsigned char guid[16]; + int guid_set; + + struct kref refcount; + + /* bmc device attributes */ + struct device_attribute device_id_attr; + struct device_attribute provides_dev_sdrs_attr; + struct device_attribute revision_attr; + struct device_attribute firmware_rev_attr; + struct device_attribute version_attr; + struct device_attribute add_dev_support_attr; + struct device_attribute manufacturer_id_attr; + struct device_attribute product_id_attr; + struct device_attribute guid_attr; + struct device_attribute aux_firmware_rev_attr; +}; + #define IPMI_IPMB_NUM_SEQ 64 #define IPMI_MAX_CHANNELS 16 struct ipmi_smi @@ -178,9 +200,8 @@ struct ipmi_smi /* Used for wake ups at startup. */ wait_queue_head_t waitq; - /* The IPMI version of the BMC on the other end. */ - unsigned char version_major; - unsigned char version_minor; + struct bmc_device *bmc; + char *my_dev_name; /* This is the lower-layer's sender routine. */ struct ipmi_smi_handlers *handlers; @@ -194,6 +215,9 @@ struct ipmi_smi struct ipmi_proc_entry *proc_entries; #endif + /* Driver-model device for the system interface. */ + struct device *si_dev; + /* A table of sequence numbers for this interface. We use the sequence numbers for IPMB messages that go out of the interface to match them up with their responses. A routine @@ -312,6 +336,7 @@ struct ipmi_smi /* Events that were received with the proper format. */ unsigned int events; }; +#define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev) /* Used to mark an interface entry that cannot be used but is not a * free entry, either, primarily used at creation and deletion time so @@ -320,6 +345,15 @@ struct ipmi_smi #define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \ || (i == IPMI_INVALID_INTERFACE_ENTRY)) +/** + * The driver model view of the IPMI messaging driver. + */ +static struct device_driver ipmidriver = { + .name = "ipmi", + .bus = &platform_bus_type +}; +static DEFINE_MUTEX(ipmidriver_mutex); + #define MAX_IPMI_INTERFACES 4 static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; @@ -393,7 +427,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) if (IPMI_INVALID_INTERFACE(intf)) continue; spin_unlock_irqrestore(&interfaces_lock, flags); - watcher->new_smi(i); + watcher->new_smi(i, intf->si_dev); spin_lock_irqsave(&interfaces_lock, flags); } spin_unlock_irqrestore(&interfaces_lock, flags); @@ -409,14 +443,14 @@ int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher) } static void -call_smi_watchers(int i) +call_smi_watchers(int i, struct device *dev) { struct ipmi_smi_watcher *w; down_read(&smi_watchers_sem); list_for_each_entry(w, &smi_watchers, link) { if (try_module_get(w->owner)) { - w->new_smi(i); + w->new_smi(i, dev); module_put(w->owner); } } @@ -844,8 +878,8 @@ void ipmi_get_version(ipmi_user_t user, unsigned char *major, unsigned char *minor) { - *major = user->intf->version_major; - *minor = user->intf->version_minor; + *major = ipmi_version_major(&user->intf->bmc->id); + *minor = ipmi_version_minor(&user->intf->bmc->id); } int ipmi_set_my_address(ipmi_user_t user, @@ -1553,7 +1587,8 @@ static int version_file_read_proc(char *page, char **start, off_t off, ipmi_smi_t intf = data; return sprintf(out, "%d.%d\n", - intf->version_major, intf->version_minor); + ipmi_version_major(&intf->bmc->id), + ipmi_version_minor(&intf->bmc->id)); } static int stat_file_read_proc(char *page, char **start, off_t off, @@ -1712,6 +1747,470 @@ static void remove_proc_entries(ipmi_smi_t smi) #endif /* CONFIG_PROC_FS */ } +static int __find_bmc_guid(struct device *dev, void *data) +{ + unsigned char *id = data; + struct bmc_device *bmc = dev_get_drvdata(dev); + return memcmp(bmc->guid, id, 16) == 0; +} + +static struct bmc_device *ipmi_find_bmc_guid(struct device_driver *drv, + unsigned char *guid) +{ + struct device *dev; + + dev = driver_find_device(drv, NULL, guid, __find_bmc_guid); + if (dev) + return dev_get_drvdata(dev); + else + return NULL; +} + +struct prod_dev_id { + unsigned int product_id; + unsigned char device_id; +}; + +static int __find_bmc_prod_dev_id(struct device *dev, void *data) +{ + struct prod_dev_id *id = data; + struct bmc_device *bmc = dev_get_drvdata(dev); + + return (bmc->id.product_id == id->product_id + && bmc->id.product_id == id->product_id + && bmc->id.device_id == id->device_id); +} + +static struct bmc_device *ipmi_find_bmc_prod_dev_id( + struct device_driver *drv, + unsigned char product_id, unsigned char device_id) +{ + struct prod_dev_id id = { + .product_id = product_id, + .device_id = device_id, + }; + struct device *dev; + + dev = driver_find_device(drv, NULL, &id, __find_bmc_prod_dev_id); + if (dev) + return dev_get_drvdata(dev); + else + return NULL; +} + +static ssize_t device_id_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bmc_device *bmc = dev_get_drvdata(dev); + + return snprintf(buf, 10, "%u\n", bmc->id.device_id); +} + +static ssize_t provides_dev_sdrs_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bmc_device *bmc = dev_get_drvdata(dev); + + return snprintf(buf, 10, "%u\n", + bmc->id.device_revision && 0x80 >> 7); +} + +static ssize_t revision_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct bmc_device *bmc = dev_get_drvdata(dev); + + return snprintf(buf, 20, "%u\n", + bmc->id.device_revision && 0x0F); +} + +static ssize_t firmware_rev_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bmc_device *bmc = dev_get_drvdata(dev); + + return snprintf(buf, 20, "%u.%x\n", bmc->id.firmware_revision_1, + bmc->id.firmware_revision_2); +} + +static ssize_t ipmi_version_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bmc_device *bmc = dev_get_drvdata(dev); + + return snprintf(buf, 20, "%u.%u\n", + ipmi_version_major(&bmc->id), + ipmi_version_minor(&bmc->id)); +} + +static ssize_t add_dev_support_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bmc_device *bmc = dev_get_drvdata(dev); + + return snprintf(buf, 10, "0x%02x\n", + bmc->id.additional_device_support); +} + +static ssize_t manufacturer_id_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bmc_device *bmc = dev_get_drvdata(dev); + + return snprintf(buf, 20, "0x%6.6x\n", bmc->id.manufacturer_id); +} + +static ssize_t product_id_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bmc_device *bmc = dev_get_drvdata(dev); + + return snprintf(buf, 10, "0x%4.4x\n", bmc->id.product_id); +} + +static ssize_t aux_firmware_rev_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bmc_device *bmc = dev_get_drvdata(dev); + + return snprintf(buf, 21, "0x%02x 0x%02x 0x%02x 0x%02x\n", + bmc->id.aux_firmware_revision[3], + bmc->id.aux_firmware_revision[2], + bmc->id.aux_firmware_revision[1], + bmc->id.aux_firmware_revision[0]); +} + +static ssize_t guid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct bmc_device *bmc = dev_get_drvdata(dev); + + return snprintf(buf, 100, "%Lx%Lx\n", + (long long) bmc->guid[0], + (long long) bmc->guid[8]); +} + +static void +cleanup_bmc_device(struct kref *ref) +{ + struct bmc_device *bmc; + + bmc = container_of(ref, struct bmc_device, refcount); + + device_remove_file(&bmc->dev->dev, + &bmc->device_id_attr); + device_remove_file(&bmc->dev->dev, + &bmc->provides_dev_sdrs_attr); + device_remove_file(&bmc->dev->dev, + &bmc->revision_attr); + device_remove_file(&bmc->dev->dev, + &bmc->firmware_rev_attr); + device_remove_file(&bmc->dev->dev, + &bmc->version_attr); + device_remove_file(&bmc->dev->dev, + &bmc->add_dev_support_attr); + device_remove_file(&bmc->dev->dev, + &bmc->manufacturer_id_attr); + device_remove_file(&bmc->dev->dev, + &bmc->product_id_attr); + if (bmc->id.aux_firmware_revision_set) + device_remove_file(&bmc->dev->dev, + &bmc->aux_firmware_rev_attr); + if (bmc->guid_set) + device_remove_file(&bmc->dev->dev, + &bmc->guid_attr); + platform_device_unregister(bmc->dev); + kfree(bmc); +} + +static void ipmi_bmc_unregister(ipmi_smi_t intf) +{ + struct bmc_device *bmc = intf->bmc; + + sysfs_remove_link(&intf->si_dev->kobj, "bmc"); + if (intf->my_dev_name) { + sysfs_remove_link(&bmc->dev->dev.kobj, intf->my_dev_name); + kfree(intf->my_dev_name); + intf->my_dev_name = NULL; + } + + mutex_lock(&ipmidriver_mutex); + kref_put(&bmc->refcount, cleanup_bmc_device); + mutex_unlock(&ipmidriver_mutex); +} + +static int ipmi_bmc_register(ipmi_smi_t intf) +{ + int rv; + struct bmc_device *bmc = intf->bmc; + struct bmc_device *old_bmc; + int size; + char dummy[1]; + + mutex_lock(&ipmidriver_mutex); + + /* + * Try to find if there is an bmc_device struct + * representing the interfaced BMC already + */ + if (bmc->guid_set) + old_bmc = ipmi_find_bmc_guid(&ipmidriver, bmc->guid); + else + old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver, + bmc->id.product_id, + bmc->id.device_id); + + /* + * If there is already an bmc_device, free the new one, + * otherwise register the new BMC device + */ + if (old_bmc) { + kfree(bmc); + intf->bmc = old_bmc; + bmc = old_bmc; + + kref_get(&bmc->refcount); + mutex_unlock(&ipmidriver_mutex); + + printk(KERN_INFO + "ipmi: interfacing existing BMC (man_id: 0x%6.6x," + " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", + bmc->id.manufacturer_id, + bmc->id.product_id, + bmc->id.device_id); + } else { + bmc->dev = platform_device_alloc("ipmi_bmc", + bmc->id.device_id); + if (! bmc->dev) { + printk(KERN_ERR + "ipmi_msghandler:" + " Unable to allocate platform device\n"); + return -ENOMEM; + } + bmc->dev->dev.driver = &ipmidriver; + dev_set_drvdata(&bmc->dev->dev, bmc); + kref_init(&bmc->refcount); + + rv = platform_device_register(bmc->dev); + mutex_unlock(&ipmidriver_mutex); + if (rv) { + printk(KERN_ERR + "ipmi_msghandler:" + " Unable to register bmc device: %d\n", + rv); + /* Don't go to out_err, you can only do that if + the device is registered already. */ + return rv; + } + + bmc->device_id_attr.attr.name = "device_id"; + bmc->device_id_attr.attr.owner = THIS_MODULE; + bmc->device_id_attr.attr.mode = S_IRUGO; + bmc->device_id_attr.show = device_id_show; + + bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; + bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE; + bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; + bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; + + + bmc->revision_attr.attr.name = "revision"; + bmc->revision_attr.attr.owner = THIS_MODULE; + bmc->revision_attr.attr.mode = S_IRUGO; + bmc->revision_attr.show = revision_show; + + bmc->firmware_rev_attr.attr.name = "firmware_revision"; + bmc->firmware_rev_attr.attr.owner = THIS_MODULE; + bmc->firmware_rev_attr.attr.mode = S_IRUGO; + bmc->firmware_rev_attr.show = firmware_rev_show; + + bmc->version_attr.attr.name = "ipmi_version"; + bmc->version_attr.attr.owner = THIS_MODULE; + bmc->version_attr.attr.mode = S_IRUGO; + bmc->version_attr.show = ipmi_version_show; + + bmc->add_dev_support_attr.attr.name + = "additional_device_support"; + bmc->add_dev_support_attr.attr.owner = THIS_MODULE; + bmc->add_dev_support_attr.attr.mode = S_IRUGO; + bmc->add_dev_support_attr.show = add_dev_support_show; + + bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; + bmc->manufacturer_id_attr.attr.owner = THIS_MODULE; + bmc->manufacturer_id_attr.attr.mode = S_IRUGO; + bmc->manufacturer_id_attr.show = manufacturer_id_show; + + bmc->product_id_attr.attr.name = "product_id"; + bmc->product_id_attr.attr.owner = THIS_MODULE; + bmc->product_id_attr.attr.mode = S_IRUGO; + bmc->product_id_attr.show = product_id_show; + + bmc->guid_attr.attr.name = "guid"; + bmc->guid_attr.attr.owner = THIS_MODULE; + bmc->guid_attr.attr.mode = S_IRUGO; + bmc->guid_attr.show = guid_show; + + bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; + bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE; + bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; + bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; + + device_create_file(&bmc->dev->dev, + &bmc->device_id_attr); + device_create_file(&bmc->dev->dev, + &bmc->provides_dev_sdrs_attr); + device_create_file(&bmc->dev->dev, + &bmc->revision_attr); + device_create_file(&bmc->dev->dev, + &bmc->firmware_rev_attr); + device_create_file(&bmc->dev->dev, + &bmc->version_attr); + device_create_file(&bmc->dev->dev, + &bmc->add_dev_support_attr); + device_create_file(&bmc->dev->dev, + &bmc->manufacturer_id_attr); + device_create_file(&bmc->dev->dev, + &bmc->product_id_attr); + if (bmc->id.aux_firmware_revision_set) + device_create_file(&bmc->dev->dev, + &bmc->aux_firmware_rev_attr); + if (bmc->guid_set) + device_create_file(&bmc->dev->dev, + &bmc->guid_attr); + + printk(KERN_INFO + "ipmi: Found new BMC (man_id: 0x%6.6x, " + " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", + bmc->id.manufacturer_id, + bmc->id.product_id, + bmc->id.device_id); + } + + /* + * create symlink from system interface device to bmc device + * and back. + */ + rv = sysfs_create_link(&intf->si_dev->kobj, + &bmc->dev->dev.kobj, "bmc"); + if (rv) { + printk(KERN_ERR + "ipmi_msghandler: Unable to create bmc symlink: %d\n", + rv); + goto out_err; + } + + size = snprintf(dummy, 0, "ipmi%d", intf->intf_num); + intf->my_dev_name = kmalloc(size+1, GFP_KERNEL); + if (!intf->my_dev_name) { + rv = -ENOMEM; + printk(KERN_ERR + "ipmi_msghandler: allocate link from BMC: %d\n", + rv); + goto out_err; + } + snprintf(intf->my_dev_name, size+1, "ipmi%d", intf->intf_num); + + rv = sysfs_create_link(&bmc->dev->dev.kobj, &intf->si_dev->kobj, + intf->my_dev_name); + if (rv) { + kfree(intf->my_dev_name); + intf->my_dev_name = NULL; + printk(KERN_ERR + "ipmi_msghandler:" + " Unable to create symlink to bmc: %d\n", + rv); + goto out_err; + } + + return 0; + +out_err: + ipmi_bmc_unregister(intf); + return rv; +} + +static int +send_guid_cmd(ipmi_smi_t intf, int chan) +{ + struct kernel_ipmi_msg msg; + struct ipmi_system_interface_addr si; + + si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + si.channel = IPMI_BMC_CHANNEL; + si.lun = 0; + + msg.netfn = IPMI_NETFN_APP_REQUEST; + msg.cmd = IPMI_GET_DEVICE_GUID_CMD; + msg.data = NULL; + msg.data_len = 0; + return i_ipmi_request(NULL, + intf, + (struct ipmi_addr *) &si, + 0, + &msg, + intf, + NULL, + NULL, + 0, + intf->channels[0].address, + intf->channels[0].lun, + -1, 0); +} + +static void +guid_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) +{ + if ((msg->addr.addr_type != IPMI_SYSTEM_INTERFACE_ADDR_TYPE) + || (msg->msg.netfn != IPMI_NETFN_APP_RESPONSE) + || (msg->msg.cmd != IPMI_GET_DEVICE_GUID_CMD)) + /* Not for me */ + return; + + if (msg->msg.data[0] != 0) { + /* Error from getting the GUID, the BMC doesn't have one. */ + intf->bmc->guid_set = 0; + goto out; + } + + if (msg->msg.data_len < 17) { + intf->bmc->guid_set = 0; + printk(KERN_WARNING PFX + "guid_handler: The GUID response from the BMC was too" + " short, it was %d but should have been 17. Assuming" + " GUID is not available.\n", + msg->msg.data_len); + goto out; + } + + memcpy(intf->bmc->guid, msg->msg.data, 16); + intf->bmc->guid_set = 1; + out: + wake_up(&intf->waitq); +} + +static void +get_guid(ipmi_smi_t intf) +{ + int rv; + + intf->bmc->guid_set = 0x2; + intf->null_user_handler = guid_handler; + rv = send_guid_cmd(intf, 0); + if (rv) + /* Send failed, no GUID available. */ + intf->bmc->guid_set = 0; + wait_event(intf->waitq, intf->bmc->guid_set != 2); + intf->null_user_handler = NULL; +} + static int send_channel_info_cmd(ipmi_smi_t intf, int chan) { @@ -1804,8 +2303,8 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) int ipmi_register_smi(struct ipmi_smi_handlers *handlers, void *send_info, - unsigned char version_major, - unsigned char version_minor, + struct ipmi_device_id *device_id, + struct device *si_dev, unsigned char slave_addr, ipmi_smi_t *new_intf) { @@ -1813,7 +2312,11 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, int rv; ipmi_smi_t intf; unsigned long flags; + int version_major; + int version_minor; + version_major = ipmi_version_major(device_id); + version_minor = ipmi_version_minor(device_id); /* Make sure the driver is actually initialized, this handles problems with initialization order. */ @@ -1831,10 +2334,15 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, if (!intf) return -ENOMEM; memset(intf, 0, sizeof(*intf)); + intf->bmc = kzalloc(sizeof(*intf->bmc), GFP_KERNEL); + if (!intf->bmc) { + kfree(intf); + return -ENOMEM; + } intf->intf_num = -1; kref_init(&intf->refcount); - intf->version_major = version_major; - intf->version_minor = version_minor; + intf->bmc->id = *device_id; + intf->si_dev = si_dev; for (j = 0; j < IPMI_MAX_CHANNELS; j++) { intf->channels[j].address = IPMI_BMC_SLAVE_ADDR; intf->channels[j].lun = 2; @@ -1884,6 +2392,8 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, caller before sending any messages with it. */ *new_intf = intf; + get_guid(intf); + if ((version_major > 1) || ((version_major == 1) && (version_minor >= 5))) { @@ -1898,6 +2408,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, /* Wait for the channel info to be read. */ wait_event(intf->waitq, intf->curr_channel >= IPMI_MAX_CHANNELS); + intf->null_user_handler = NULL; } else { /* Assume a single IPMB channel at zero. */ intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; @@ -1907,6 +2418,8 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, if (rv == 0) rv = add_proc_entries(intf, i); + rv = ipmi_bmc_register(intf); + out: if (rv) { if (intf->proc_dir) @@ -1921,7 +2434,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, spin_lock_irqsave(&interfaces_lock, flags); ipmi_interfaces[i] = intf; spin_unlock_irqrestore(&interfaces_lock, flags); - call_smi_watchers(i); + call_smi_watchers(i, intf->si_dev); } return rv; @@ -1933,6 +2446,8 @@ int ipmi_unregister_smi(ipmi_smi_t intf) struct ipmi_smi_watcher *w; unsigned long flags; + ipmi_bmc_unregister(intf); + spin_lock_irqsave(&interfaces_lock, flags); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { if (ipmi_interfaces[i] == intf) { @@ -3196,10 +3711,17 @@ static struct notifier_block panic_block = { static int ipmi_init_msghandler(void) { int i; + int rv; if (initialized) return 0; + rv = driver_register(&ipmidriver); + if (rv) { + printk(KERN_ERR PFX "Could not register IPMI driver\n"); + return rv; + } + printk(KERN_INFO "ipmi message handler version " IPMI_DRIVER_VERSION "\n"); @@ -3256,6 +3778,8 @@ static __exit void cleanup_ipmi(void) remove_proc_entry(proc_ipmi_root->name, &proc_root); #endif /* CONFIG_PROC_FS */ + driver_unregister(&ipmidriver); + initialized = 0; /* Check for buffer leaks. */ diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index e8ed26b77d4c..786a2802ca34 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -464,7 +464,7 @@ static void ipmi_poweroff_function (void) /* Wait for an IPMI interface to be installed, the first one installed will be grabbed by this code and used to perform the powerdown. */ -static void ipmi_po_new_smi(int if_num) +static void ipmi_po_new_smi(int if_num, struct device *device) { struct ipmi_system_interface_addr smi_addr; struct kernel_ipmi_msg send_msg; diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index f3b3b23c5330..12f858dc9994 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -112,20 +112,13 @@ enum si_type { }; static char *si_to_str[] = { "KCS", "SMIC", "BT" }; -struct ipmi_device_id { - unsigned char device_id; - unsigned char device_revision; - unsigned char firmware_revision_1; - unsigned char firmware_revision_2; - unsigned char ipmi_version; - unsigned char additional_device_support; - unsigned char manufacturer_id[3]; - unsigned char product_id[2]; - unsigned char aux_firmware_revision[4]; -} __attribute__((packed)); - -#define ipmi_version_major(v) ((v)->ipmi_version & 0xf) -#define ipmi_version_minor(v) ((v)->ipmi_version >> 4) +#define DEVICE_NAME "ipmi_si" + +static struct device_driver ipmi_driver = +{ + .name = DEVICE_NAME, + .bus = &platform_bus_type +}; struct smi_info { @@ -208,8 +201,17 @@ struct smi_info interrupts. */ int interrupt_disabled; + /* From the get device id response... */ struct ipmi_device_id device_id; + /* Driver model stuff. */ + struct device *dev; + struct platform_device *pdev; + + /* True if we allocated the device, false if it came from + * someplace else (like PCI). */ + int dev_registered; + /* Slave address, could be reported from DMI. */ unsigned char slave_addr; @@ -987,8 +989,6 @@ static LIST_HEAD(smi_infos); static DECLARE_MUTEX(smi_infos_lock); static int smi_num; /* Used to sequence the SMIs */ -#define DEVICE_NAME "ipmi_si" - #define DEFAULT_REGSPACING 1 static int si_trydefaults = 1; @@ -1164,7 +1164,6 @@ static void port_cleanup(struct smi_info *info) release_region (addr, mapsize); } - kfree(info); } static int port_setup(struct smi_info *info) @@ -1273,7 +1272,6 @@ static void mem_cleanup(struct smi_info *info) release_mem_region(addr, mapsize); } - kfree(info); } static int mem_setup(struct smi_info *info) @@ -1858,6 +1856,8 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, if (info->irq) info->irq_setup = std_irq_setup; + info->dev = &pdev->dev; + return try_smi_init(info); } @@ -1898,11 +1898,11 @@ static struct pci_driver ipmi_pci_driver = { static int try_get_dev_id(struct smi_info *smi_info) { - unsigned char msg[2]; - unsigned char *resp; - unsigned long resp_len; - enum si_sm_result smi_result; - int rv = 0; + unsigned char msg[2]; + unsigned char *resp; + unsigned long resp_len; + enum si_sm_result smi_result; + int rv = 0; resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); if (!resp) @@ -1941,7 +1941,7 @@ static int try_get_dev_id(struct smi_info *smi_info) /* Otherwise, we got some data. */ resp_len = smi_info->handlers->get_result(smi_info->si_sm, resp, IPMI_MAX_MSG_LENGTH); - if (resp_len < 6) { + if (resp_len < 14) { /* That's odd, it should be longer. */ rv = -EINVAL; goto out; @@ -1954,8 +1954,7 @@ static int try_get_dev_id(struct smi_info *smi_info) } /* Record info from the get device id, in case we need it. */ - memcpy(&smi_info->device_id, &resp[3], - min_t(unsigned long, resp_len-3, sizeof(smi_info->device_id))); + ipmi_demangle_device_id(resp+3, resp_len-3, &smi_info->device_id); out: kfree(resp); @@ -2058,15 +2057,14 @@ static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info) #define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20 #define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80 #define DELL_POWEREDGE_8G_BMC_IPMI_VERSION 0x51 -#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00} +#define DELL_IANA_MFR_ID 0x0002a2 static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info) { struct ipmi_device_id *id = &smi_info->device_id; - const char mfr[3]=DELL_IANA_MFR_ID; - if (!memcmp(mfr, id->manufacturer_id, sizeof(mfr))) { + if (id->manufacturer_id == DELL_IANA_MFR_ID) { if (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID && id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV && - id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) { + id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) { smi_info->oem_data_avail_handler = oem_data_avail_to_receive_msg_avail; } @@ -2138,8 +2136,7 @@ static void setup_dell_poweredge_bt_xaction_handler(struct smi_info *smi_info) { struct ipmi_device_id *id = &smi_info->device_id; - const char mfr[3]=DELL_IANA_MFR_ID; - if (!memcmp(mfr, id->manufacturer_id, sizeof(mfr)) && + if (id->manufacturer_id == DELL_IANA_MFR_ID && smi_info->si_type == SI_BT) register_xaction_notifier(&dell_poweredge_bt_xaction_notifier); } @@ -2358,10 +2355,36 @@ static int try_smi_init(struct smi_info *new_smi) new_smi->thread = kthread_run(ipmi_thread, new_smi, "kipmi%d", new_smi->intf_num); + if (!new_smi->dev) { + /* If we don't already have a device from something + * else (like PCI), then register a new one. */ + new_smi->pdev = platform_device_alloc("ipmi_si", + new_smi->intf_num); + if (rv) { + printk(KERN_ERR + "ipmi_si_intf:" + " Unable to allocate platform device\n"); + goto out_err_stop_timer; + } + new_smi->dev = &new_smi->pdev->dev; + new_smi->dev->driver = &ipmi_driver; + + rv = platform_device_register(new_smi->pdev); + if (rv) { + printk(KERN_ERR + "ipmi_si_intf:" + " Unable to register system interface device:" + " %d\n", + rv); + goto out_err_stop_timer; + } + new_smi->dev_registered = 1; + } + rv = ipmi_register_smi(&handlers, new_smi, - ipmi_version_major(&new_smi->device_id), - ipmi_version_minor(&new_smi->device_id), + &new_smi->device_id, + new_smi->dev, new_smi->slave_addr, &(new_smi->intf)); if (rv) { @@ -2425,6 +2448,11 @@ static int try_smi_init(struct smi_info *new_smi) if (new_smi->io_cleanup) new_smi->io_cleanup(new_smi); + if (new_smi->dev_registered) + platform_device_unregister(new_smi->pdev); + + kfree(new_smi); + up(&smi_infos_lock); return rv; @@ -2434,11 +2462,22 @@ static __devinit int init_ipmi_si(void) { int i; char *str; + int rv; if (initialized) return 0; initialized = 1; + /* Register the device drivers. */ + rv = driver_register(&ipmi_driver); + if (rv) { + printk(KERN_ERR + "init_ipmi_si: Unable to register driver: %d\n", + rv); + return rv; + } + + /* Parse out the si_type string into its components. */ str = si_type_str; if (*str != '\0') { @@ -2549,6 +2588,11 @@ static void __devexit cleanup_one_si(struct smi_info *to_clean) to_clean->addr_source_cleanup(to_clean); if (to_clean->io_cleanup) to_clean->io_cleanup(to_clean); + + if (to_clean->dev_registered) + platform_device_unregister(to_clean->pdev); + + kfree(to_clean); } static __exit void cleanup_ipmi_si(void) @@ -2566,6 +2610,8 @@ static __exit void cleanup_ipmi_si(void) list_for_each_entry_safe(e, tmp_e, &smi_infos, link) cleanup_one_si(e); up(&smi_infos_lock); + + driver_unregister(&ipmi_driver); } module_exit(cleanup_ipmi_si); diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 1f3159eb1ede..616539310d9a 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -996,7 +996,7 @@ static struct notifier_block wdog_panic_notifier = { }; -static void ipmi_new_smi(int if_num) +static void ipmi_new_smi(int if_num, struct device *device) { ipmi_register_watchdog(if_num); } diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index d6276e60b3bf..0a84b56935c2 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h @@ -36,6 +36,7 @@ #include #include +#include /* * This file describes an interface to an IPMI driver. You have to @@ -397,7 +398,7 @@ struct ipmi_smi_watcher the watcher list. So you can add and remove users from the IPMI interface, send messages, etc., but you cannot add or remove SMI watchers or SMI interfaces. */ - void (*new_smi)(int if_num); + void (*new_smi)(int if_num, struct device *dev); void (*smi_gone)(int if_num); }; diff --git a/include/linux/ipmi_msgdefs.h b/include/linux/ipmi_msgdefs.h index 03bc64dc2ec1..22f5e2afda4f 100644 --- a/include/linux/ipmi_msgdefs.h +++ b/include/linux/ipmi_msgdefs.h @@ -47,6 +47,7 @@ #define IPMI_NETFN_APP_RESPONSE 0x07 #define IPMI_GET_DEVICE_ID_CMD 0x01 #define IPMI_CLEAR_MSG_FLAGS_CMD 0x30 +#define IPMI_GET_DEVICE_GUID_CMD 0x08 #define IPMI_GET_MSG_FLAGS_CMD 0x31 #define IPMI_SEND_MSG_CMD 0x34 #define IPMI_GET_MSG_CMD 0x33 diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index e36ee157ad67..53571288a9fc 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h @@ -37,6 +37,9 @@ #include #include #include +#include +#include +#include /* This files describes the interface for IPMI system management interface drivers to bind into the IPMI message handler. */ @@ -113,12 +116,52 @@ struct ipmi_smi_handlers void (*dec_usecount)(void *send_info); }; +struct ipmi_device_id { + unsigned char device_id; + unsigned char device_revision; + unsigned char firmware_revision_1; + unsigned char firmware_revision_2; + unsigned char ipmi_version; + unsigned char additional_device_support; + unsigned int manufacturer_id; + unsigned int product_id; + unsigned char aux_firmware_revision[4]; + unsigned int aux_firmware_revision_set : 1; +}; + +#define ipmi_version_major(v) ((v)->ipmi_version & 0xf) +#define ipmi_version_minor(v) ((v)->ipmi_version >> 4) + +/* Take a pointer to a raw data buffer and a length and extract device + id information from it. The first byte of data must point to the + byte from the get device id response after the completion code. + The caller is responsible for making sure the length is at least + 11 and the command completed without error. */ +static inline void ipmi_demangle_device_id(unsigned char *data, + unsigned int data_len, + struct ipmi_device_id *id) +{ + id->device_id = data[0]; + id->device_revision = data[1]; + id->firmware_revision_1 = data[2]; + id->firmware_revision_2 = data[3]; + id->ipmi_version = data[4]; + id->additional_device_support = data[5]; + id->manufacturer_id = data[6] | (data[7] << 8) | (data[8] << 16); + id->product_id = data[9] | (data[10] << 8); + if (data_len >= 15) { + memcpy(id->aux_firmware_revision, data+11, 4); + id->aux_firmware_revision_set = 1; + } else + id->aux_firmware_revision_set = 0; +} + /* Add a low-level interface to the IPMI driver. Note that if the interface doesn't know its slave address, it should pass in zero. */ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, void *send_info, - unsigned char version_major, - unsigned char version_minor, + struct ipmi_device_id *device_id, + struct device *dev, unsigned char slave_addr, ipmi_smi_t *intf); -- cgit v1.2.3-59-g8ed1b From a23f9a3cfeb1d37ad090a751777665fd03bc067a Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Sun, 26 Mar 2006 01:37:22 -0800 Subject: [PATCH] ipmi: Increment driver version to v39.0 Need to increment the version number because of the new PCI and sysfs capabilities of the driver. People maintaining things for distros have asked that I do this after interface or major functional changes. Signed-off-by: Corey Minyard Acked-by: Matt Domsch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index f553b7a86841..b8fb87c6c29f 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -48,7 +48,7 @@ #define PFX "IPMI message handler: " -#define IPMI_DRIVER_VERSION "38.0" +#define IPMI_DRIVER_VERSION "39.0" static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); static int ipmi_init_msghandler(void); -- cgit v1.2.3-59-g8ed1b From 3e88c17d404c5787afd5bd1763380317f5ccbf84 Mon Sep 17 00:00:00 2001 From: Herbert Poetzl Date: Sun, 26 Mar 2006 01:37:30 -0800 Subject: [PATCH] loop: potential kernel hang waiting for kthread Check that kernel_thread() succeeded, so we don't wait for something which cannot happen. Signed-off-by: Herbert Poetzl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/loop.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 74bf0255e98f..9c3b94e8f03b 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -839,7 +839,9 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, set_blocksize(bdev, lo_blocksize); - kernel_thread(loop_thread, lo, CLONE_KERNEL); + error = kernel_thread(loop_thread, lo, CLONE_KERNEL); + if (error < 0) + goto out_putf; wait_for_completion(&lo->lo_done); return 0; -- cgit v1.2.3-59-g8ed1b From 222b9f933a76b127a073f45278d2b0199587e8ce Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 26 Mar 2006 01:37:31 -0800 Subject: [PATCH] tlclk: fix handling of device major tlclk calls register_chrdev() and permits register_chrdev() to allocate the major, but it promptly forgets what that major was. So if there's no hardware present you still get "telco_clock" appearing in /proc/devices and, I assume, an oops reading /proc/devices if tlclk was a module. Fix. Mark, I'd suggest that that we not call register_chrdev() until _after_ we've established that the hardware is present. Cc: Mark Gross Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tlclk.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 4c272189cd42..2546637a55c0 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c @@ -767,6 +767,7 @@ static int __init tlclk_init(void) printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major); return ret; } + tlclk_major = ret; alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL); if (!alarm_events) goto out1; -- cgit v1.2.3-59-g8ed1b From 3ac8bf077d0f13b9c3131dd61f9f76c78c322858 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 26 Mar 2006 01:37:33 -0800 Subject: [PATCH] ads7846: sparc32 warning fix drivers/input/touchscreen/ads7846.c: In function `ads7846_read12_ser': drivers/input/touchscreen/ads7846.c:207: warning: implicit declaration of function `disable_irq' drivers/input/touchscreen/ads7846.c:209: warning: implicit declaration of function `enable_irq' Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/touchscreen/ads7846.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index a81f987978c8..46d1fec2cfd8 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #ifdef CONFIG_ARM #include -- cgit v1.2.3-59-g8ed1b From 5ff2a7e25ddd648e9096d45cdc5e7d656a8bb0ff Mon Sep 17 00:00:00 2001 From: maximilian attems Date: Sun, 26 Mar 2006 01:37:35 -0800 Subject: [PATCH] isicom: select FW_LOADER The isicom driver uses request_firmware() and thus needs to select FW_LOADER. Signed-off-by: maximilian attems Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 5980f3e886fc..facc3f1d9e37 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -187,6 +187,7 @@ config MOXA_SMARTIO config ISI tristate "Multi-Tech multiport card support (EXPERIMENTAL)" depends on SERIAL_NONSTANDARD + select FW_LOADER help This is a driver for the Multi-Tech cards which provide several serial ports. The driver is experimental and can currently only be -- cgit v1.2.3-59-g8ed1b From 1751ace034bba6b423c1de4668f0e65cc9ef2b84 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 26 Mar 2006 01:37:36 -0800 Subject: [PATCH] Update documentation for BLK_DEV_INITRD to match current usage Cc: Al Viro Cc: Christoph Hellwig Cc: Zdenek Pavlas Signed-off-by: H. Peter Anvin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/Kconfig | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index e57ac5a43246..875ae7699025 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -400,13 +400,16 @@ config BLK_DEV_RAM_SIZE 8192. config BLK_DEV_INITRD - bool "Initial RAM disk (initrd) support" + bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support" help - The initial RAM disk is a RAM disk that is loaded by the boot loader - (loadlin or lilo) and that is mounted as root before the normal boot - procedure. It is typically used to load modules needed to mount the - "real" root file system, etc. See - for details. + The initial RAM filesystem is a ramfs which is loaded by the + boot loader (loadlin or lilo) and that is mounted as root + before the normal boot procedure. It is typically used to + load modules needed to mount the "real" root file system, + etc. See for details. + + If RAM disk support (BLK_DEV_RAM) is also included, this + also enables initial RAM disk (initrd) support. config CDROM_PKTCDVD -- cgit v1.2.3-59-g8ed1b From 125d5ce8a4e9e4babaed52518fecc9eb6958455d Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 26 Mar 2006 01:37:39 -0800 Subject: [PATCH] 3c59x: use mii_check_media Check for media changes and netif_carrier by using mii_check_media() if mii is used. Signed-off-by: Steffen Klassert Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 126 ++++++++++++++++++++-------------------------------- 1 file changed, 49 insertions(+), 77 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index d339308539fa..4ae78bf377cd 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1335,7 +1335,7 @@ static int __devinit vortex_probe1(struct device *gendev, vp->enable_wol = 1; } - vp->force_fd = vp->full_duplex; + vp->mii.force_media = vp->full_duplex; vp->options = option; /* Read the station address from the EEPROM. */ EL3WINDOW(0); @@ -1624,6 +1624,46 @@ issue_and_wait(struct net_device *dev, int cmd) dev->name, cmd, ioread16(ioaddr + EL3_STATUS)); } +static void +vortex_set_duplex(struct net_device *dev) +{ + struct vortex_private *vp = netdev_priv(dev); + void __iomem *ioaddr = vp->ioaddr; + + printk(KERN_INFO "%s: setting %s-duplex.\n", + dev->name, (vp->full_duplex) ? "full" : "half"); + + EL3WINDOW(3); + /* Set the full-duplex bit. */ + iowrite16(((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) | + (vp->large_frames ? 0x40 : 0) | + ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? + 0x100 : 0), + ioaddr + Wn3_MAC_Ctrl); + + issue_and_wait(dev, TxReset); + /* + * Don't reset the PHY - that upsets autonegotiation during DHCP operations. + */ + issue_and_wait(dev, RxReset|0x04); +} + +static void vortex_check_media(struct net_device *dev, unsigned int init) +{ + struct vortex_private *vp = netdev_priv(dev); + unsigned int ok_to_print = 0; + + if (vortex_debug > 3) + ok_to_print = 1; + + if (mii_check_media(&vp->mii, ok_to_print, init)) { + vp->full_duplex = vp->mii.full_duplex; + vortex_set_duplex(dev); + } else if (init) { + vortex_set_duplex(dev); + } +} + static void vortex_up(struct net_device *dev) { @@ -1684,53 +1724,20 @@ vortex_up(struct net_device *dev) printk(KERN_DEBUG "%s: Initial media type %s.\n", dev->name, media_tbl[dev->if_port].name); - vp->full_duplex = vp->force_fd; + vp->full_duplex = vp->mii.force_media; config = BFINS(config, dev->if_port, 20, 4); if (vortex_debug > 6) printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config); iowrite32(config, ioaddr + Wn3_Config); + netif_carrier_off(dev); if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { - int mii_reg1, mii_reg5; EL3WINDOW(4); - /* Read BMSR (reg1) only to clear old status. */ - mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR); - mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA); - if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) { - netif_carrier_off(dev); /* No MII device or no link partner report */ - } else { - mii_reg5 &= vp->advertising; - if ((mii_reg5 & 0x0100) != 0 /* 100baseTx-FD */ - || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */ - vp->full_duplex = 1; - netif_carrier_on(dev); - } - vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0); - if (vortex_debug > 1) - printk(KERN_INFO "%s: MII #%d status %4.4x, link partner capability %4.4x," - " info1 %04x, setting %s-duplex.\n", - dev->name, vp->phys[0], - mii_reg1, mii_reg5, - vp->info1, ((vp->info1 & 0x8000) || vp->full_duplex) ? "full" : "half"); - EL3WINDOW(3); + vortex_check_media(dev, 1); } + else + vortex_set_duplex(dev); - /* Set the full-duplex bit. */ - iowrite16( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) | - (vp->large_frames ? 0x40 : 0) | - ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), - ioaddr + Wn3_MAC_Ctrl); - - if (vortex_debug > 1) { - printk(KERN_DEBUG "%s: vortex_up() InternalConfig %8.8x.\n", - dev->name, config); - } - - issue_and_wait(dev, TxReset); - /* - * Don't reset the PHY - that upsets autonegotiation during DHCP operations. - */ - issue_and_wait(dev, RxReset|0x04); iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD); @@ -1892,7 +1899,7 @@ vortex_timer(unsigned long data) void __iomem *ioaddr = vp->ioaddr; int next_tick = 60*HZ; int ok = 0; - int media_status, mii_status, old_window; + int media_status, old_window; if (vortex_debug > 2) { printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n", @@ -1924,44 +1931,9 @@ vortex_timer(unsigned long data) break; case XCVR_MII: case XCVR_NWAY: { - spin_lock_bh(&vp->lock); - mii_status = mdio_read(dev, vp->phys[0], MII_BMSR); - if (!(mii_status & BMSR_LSTATUS)) { - /* Re-read to get actual link status */ - mii_status = mdio_read(dev, vp->phys[0], MII_BMSR); - } ok = 1; - if (vortex_debug > 2) - printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n", - dev->name, mii_status); - if (mii_status & BMSR_LSTATUS) { - int mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA); - if (! vp->force_fd && mii_reg5 != 0xffff) { - int duplex; - - mii_reg5 &= vp->advertising; - duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040; - if (vp->full_duplex != duplex) { - vp->full_duplex = duplex; - printk(KERN_INFO "%s: Setting %s-duplex based on MII " - "#%d link partner capability of %4.4x.\n", - dev->name, vp->full_duplex ? "full" : "half", - vp->phys[0], mii_reg5); - /* Set the full-duplex bit. */ - EL3WINDOW(3); - iowrite16( (vp->full_duplex ? 0x20 : 0) | - (vp->large_frames ? 0x40 : 0) | - ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), - ioaddr + Wn3_MAC_Ctrl); - if (vortex_debug > 1) - printk(KERN_DEBUG "Setting duplex in Wn3_MAC_Ctrl\n"); - /* AKPM: bug: should reset Tx and Rx after setting Duplex. Page 180 */ - } - } - netif_carrier_on(dev); - } else { - netif_carrier_off(dev); - } + spin_lock_bh(&vp->lock); + vortex_check_media(dev, 0); spin_unlock_bh(&vp->lock); } break; -- cgit v1.2.3-59-g8ed1b From b4ff6450f5336c492d1e2f184d3b8186e0716b7a Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 26 Mar 2006 01:37:40 -0800 Subject: [PATCH] 3c59x: decrease polling interval Set the polling interval for media changes to 5 seconds if link is down and 60 seconds if link is up. Signed-off-by: Steffen Klassert Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 4ae78bf377cd..3343cbda4197 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1943,6 +1943,10 @@ vortex_timer(unsigned long data) dev->name, media_tbl[dev->if_port].name, media_status); ok = 1; } + + if (!netif_carrier_ok(dev)) + next_tick = 5*HZ; + if ( ! ok) { unsigned int config; -- cgit v1.2.3-59-g8ed1b From e94d10eb0d77ae70378f9218631a7be91e0aecff Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 26 Mar 2006 01:37:41 -0800 Subject: [PATCH] 3c59x: carriercheck for forced media Handle netif_carrier_{on,of} also if media is forced to 10baseT/100baseTx. Signed-off-by: Steffen Klassert Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 3343cbda4197..4655662453ba 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1907,8 +1907,6 @@ vortex_timer(unsigned long data) printk(KERN_DEBUG "dev->watchdog_timeo=%d\n", dev->watchdog_timeo); } - if (vp->medialock) - goto leave_media_alone; disable_irq(dev->irq); old_window = ioread16(ioaddr + EL3_CMD) >> 13; EL3WINDOW(4); @@ -1947,6 +1945,9 @@ vortex_timer(unsigned long data) if (!netif_carrier_ok(dev)) next_tick = 5*HZ; + if (vp->medialock) + goto leave_media_alone; + if ( ! ok) { unsigned int config; @@ -1980,14 +1981,14 @@ vortex_timer(unsigned long data) printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config); /* AKPM: FIXME: Should reset Rx & Tx here. P60 of 3c90xc.pdf */ } - EL3WINDOW(old_window); - enable_irq(dev->irq); leave_media_alone: if (vortex_debug > 2) printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n", dev->name, media_tbl[dev->if_port].name); + EL3WINDOW(old_window); + enable_irq(dev->irq); mod_timer(&vp->timer, RUN_AT(next_tick)); if (vp->deferred) iowrite16(FakeIntr, ioaddr + EL3_CMD); -- cgit v1.2.3-59-g8ed1b From 373a688742d7ba31cafc4c7b9bc09eba257860bd Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 26 Mar 2006 01:37:41 -0800 Subject: [PATCH] 3c59x: use ethtool_op_get_link Use ethtool_op_get_link instead of vortex_get_link. Signed-off-by: Steffen Klassert Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 4655662453ba..1352eb66c742 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -2960,20 +2960,6 @@ static int vortex_nway_reset(struct net_device *dev) return rc; } -static u32 vortex_get_link(struct net_device *dev) -{ - struct vortex_private *vp = netdev_priv(dev); - void __iomem *ioaddr = vp->ioaddr; - unsigned long flags; - int rc; - - spin_lock_irqsave(&vp->lock, flags); - EL3WINDOW(4); - rc = mii_link_ok(&vp->mii); - spin_unlock_irqrestore(&vp->lock, flags); - return rc; -} - static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct vortex_private *vp = netdev_priv(dev); @@ -3075,7 +3061,7 @@ static struct ethtool_ops vortex_ethtool_ops = { .get_stats_count = vortex_get_stats_count, .get_settings = vortex_get_settings, .set_settings = vortex_set_settings, - .get_link = vortex_get_link, + .get_link = ethtool_op_get_link, .nway_reset = vortex_nway_reset, .get_perm_addr = ethtool_op_get_perm_addr, }; -- cgit v1.2.3-59-g8ed1b From 61238602622c965db052927c89901aa08f88d933 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 26 Mar 2006 01:37:42 -0800 Subject: [PATCH] 3c59x: remove per-driver versioning Remove per-driver versioning. Signed-off-by: Steffen Klassert Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 1352eb66c742..51ac35966b2d 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -196,8 +196,6 @@ #define DRV_NAME "3c59x" -#define DRV_VERSION "LK1.1.19" -#define DRV_RELDATE "10 Nov 2002" @@ -275,10 +273,8 @@ static char version[] __devinitdata = DRV_NAME ": Donald Becker and others. www.scyld.com/network/vortex.html\n"; MODULE_AUTHOR("Donald Becker "); -MODULE_DESCRIPTION("3Com 3c59x/3c9xx ethernet driver " - DRV_VERSION " " DRV_RELDATE); +MODULE_DESCRIPTION("3Com 3c59x/3c9xx ethernet driver "); MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); /* Operational parameter that usually are not changed. */ @@ -1236,7 +1232,7 @@ static int __devinit vortex_probe1(struct device *gendev, if (print_info) printk (KERN_INFO "See Documentation/networking/vortex.txt\n"); - printk(KERN_INFO "%s: 3Com %s %s at %p. Vers " DRV_VERSION "\n", + printk(KERN_INFO "%s: 3Com %s %s at %p.\n", print_name, pdev ? "PCI" : "EISA", vci->name, @@ -3040,7 +3036,6 @@ static void vortex_get_drvinfo(struct net_device *dev, struct vortex_private *vp = netdev_priv(dev); strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); if (VORTEX_PCI(vp)) { strcpy(info->bus_info, pci_name(VORTEX_PCI(vp))); } else { -- cgit v1.2.3-59-g8ed1b From a880c4cd2538293be59121a3658b8de8e3a058e5 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 26 Mar 2006 01:37:43 -0800 Subject: [PATCH] 3c59x: minor cleanups Remove some whitespaces and codingstyle issues. Signed-off-by: Steffen Klassert Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 81 ++++++++++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 51ac35966b2d..70f63891b19c 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -900,7 +900,6 @@ static void acpi_set_WOL(struct net_device *dev); static struct ethtool_ops vortex_ethtool_ops; static void set_8021q_mode(struct net_device *dev, int enable); - /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */ /* Option count limit only -- unlimited interfaces are supported. */ #define MAX_UNITS 8 @@ -915,8 +914,6 @@ static int global_full_duplex = -1; static int global_enable_wol = -1; static int global_use_mmio = -1; -/* #define dev_alloc_skb dev_alloc_skb_debug */ - /* Variables to work-around the Compaq PCI BIOS32 problem. */ static int compaq_ioaddr, compaq_irq, compaq_device_id = 0x5900; static struct net_device *compaq_net_device; @@ -972,7 +969,7 @@ static void poll_vortex(struct net_device *dev) #ifdef CONFIG_PM -static int vortex_suspend (struct pci_dev *pdev, pm_message_t state) +static int vortex_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); @@ -990,7 +987,7 @@ static int vortex_suspend (struct pci_dev *pdev, pm_message_t state) return 0; } -static int vortex_resume (struct pci_dev *pdev) +static int vortex_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct vortex_private *vp = netdev_priv(dev); @@ -1023,8 +1020,8 @@ static struct eisa_device_id vortex_eisa_ids[] = { { "" } }; -static int vortex_eisa_probe (struct device *device); -static int vortex_eisa_remove (struct device *device); +static int vortex_eisa_probe(struct device *device); +static int vortex_eisa_remove(struct device *device); static struct eisa_driver vortex_eisa_driver = { .id_table = vortex_eisa_ids, @@ -1035,12 +1032,12 @@ static struct eisa_driver vortex_eisa_driver = { } }; -static int vortex_eisa_probe (struct device *device) +static int vortex_eisa_probe(struct device *device) { void __iomem *ioaddr; struct eisa_device *edev; - edev = to_eisa_device (device); + edev = to_eisa_device(device); if (!request_region(edev->base_addr, VORTEX_TOTAL_SIZE, DRV_NAME)) return -EBUSY; @@ -1049,7 +1046,7 @@ static int vortex_eisa_probe (struct device *device) if (vortex_probe1(device, ioaddr, ioread16(ioaddr + 0xC88) >> 12, edev->id.driver_data, vortex_cards_found)) { - release_region (edev->base_addr, VORTEX_TOTAL_SIZE); + release_region(edev->base_addr, VORTEX_TOTAL_SIZE); return -ENODEV; } @@ -1058,15 +1055,15 @@ static int vortex_eisa_probe (struct device *device) return 0; } -static int vortex_eisa_remove (struct device *device) +static int vortex_eisa_remove(struct device *device) { struct eisa_device *edev; struct net_device *dev; struct vortex_private *vp; void __iomem *ioaddr; - edev = to_eisa_device (device); - dev = eisa_get_drvdata (edev); + edev = to_eisa_device(device); + dev = eisa_get_drvdata(edev); if (!dev) { printk("vortex_eisa_remove called for Compaq device!\n"); @@ -1076,17 +1073,17 @@ static int vortex_eisa_remove (struct device *device) vp = netdev_priv(dev); ioaddr = vp->ioaddr; - unregister_netdev (dev); - iowrite16 (TotalReset|0x14, ioaddr + EL3_CMD); - release_region (dev->base_addr, VORTEX_TOTAL_SIZE); + unregister_netdev(dev); + iowrite16(TotalReset|0x14, ioaddr + EL3_CMD); + release_region(dev->base_addr, VORTEX_TOTAL_SIZE); - free_netdev (dev); + free_netdev(dev); return 0; } #endif /* returns count found (>= 0), or negative on error */ -static int __init vortex_eisa_init (void) +static int __init vortex_eisa_init(void) { int eisa_found = 0; int orig_cards_found = vortex_cards_found; @@ -1117,7 +1114,7 @@ static int __init vortex_eisa_init (void) } /* returns count (>= 0), or negative on error */ -static int __devinit vortex_init_one (struct pci_dev *pdev, +static int __devinit vortex_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc, unit, pci_bar; @@ -1125,7 +1122,7 @@ static int __devinit vortex_init_one (struct pci_dev *pdev, void __iomem *ioaddr; /* wake up and enable device */ - rc = pci_enable_device (pdev); + rc = pci_enable_device(pdev); if (rc < 0) goto out; @@ -1147,7 +1144,7 @@ static int __devinit vortex_init_one (struct pci_dev *pdev, rc = vortex_probe1(&pdev->dev, ioaddr, pdev->irq, ent->driver_data, unit); if (rc < 0) { - pci_disable_device (pdev); + pci_disable_device(pdev); goto out; } @@ -1262,7 +1259,7 @@ static int __devinit vortex_probe1(struct device *gendev, /* enable bus-mastering if necessary */ if (vci->flags & PCI_USES_MASTER) - pci_set_master (pdev); + pci_set_master(pdev); if (vci->drv_flags & IS_VORTEX) { u8 pci_latency; @@ -1306,7 +1303,7 @@ static int __devinit vortex_probe1(struct device *gendev, if (pdev) pci_set_drvdata(pdev, dev); if (edev) - eisa_set_drvdata (edev, dev); + eisa_set_drvdata(edev, dev); vp->media_override = 7; if (option >= 0) { @@ -1808,7 +1805,6 @@ vortex_up(struct net_device *dev) set_8021q_mode(dev, 1); iowrite16(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ -// issue_and_wait(dev, SetTxStart|0x07ff); iowrite16(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ iowrite16(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ /* Allow status bits to be seen. */ @@ -1944,7 +1940,7 @@ vortex_timer(unsigned long data) if (vp->medialock) goto leave_media_alone; - if ( ! ok) { + if (!ok) { unsigned int config; do { @@ -2179,7 +2175,7 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) if (vp->bus_master) { /* Set the bus-master controller to transfer the packet. */ int len = (skb->len + 3) & ~3; - iowrite32( vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, PCI_DMA_TODEVICE), + iowrite32(vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, PCI_DMA_TODEVICE), ioaddr + Wn7_MasterAddr); iowrite16(len, ioaddr + Wn7_MasterLen); vp->tx_skb = skb; @@ -3058,7 +3054,7 @@ static struct ethtool_ops vortex_ethtool_ops = { .set_settings = vortex_set_settings, .get_link = ethtool_op_get_link, .nway_reset = vortex_nway_reset, - .get_perm_addr = ethtool_op_get_perm_addr, + .get_perm_addr = ethtool_op_get_perm_addr, }; #ifdef CONFIG_PCI @@ -3259,7 +3255,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val } return; } - + /* ACPI: Advanced Configuration and Power Interface. */ /* Set Wake-On-LAN mode and put the board into D3 (power-down) state. */ static void acpi_set_WOL(struct net_device *dev) @@ -3283,7 +3279,7 @@ static void acpi_set_WOL(struct net_device *dev) } -static void __devexit vortex_remove_one (struct pci_dev *pdev) +static void __devexit vortex_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct vortex_private *vp; @@ -3339,7 +3335,7 @@ static int vortex_have_pci; static int vortex_have_eisa; -static int __init vortex_init (void) +static int __init vortex_init(void) { int pci_rc, eisa_rc; @@ -3355,14 +3351,14 @@ static int __init vortex_init (void) } -static void __exit vortex_eisa_cleanup (void) +static void __exit vortex_eisa_cleanup(void) { struct vortex_private *vp; void __iomem *ioaddr; #ifdef CONFIG_EISA /* Take care of the EISA devices */ - eisa_driver_unregister (&vortex_eisa_driver); + eisa_driver_unregister(&vortex_eisa_driver); #endif if (compaq_net_device) { @@ -3370,33 +3366,24 @@ static void __exit vortex_eisa_cleanup (void) ioaddr = ioport_map(compaq_net_device->base_addr, VORTEX_TOTAL_SIZE); - unregister_netdev (compaq_net_device); - iowrite16 (TotalReset, ioaddr + EL3_CMD); + unregister_netdev(compaq_net_device); + iowrite16(TotalReset, ioaddr + EL3_CMD); release_region(compaq_net_device->base_addr, VORTEX_TOTAL_SIZE); - free_netdev (compaq_net_device); + free_netdev(compaq_net_device); } } -static void __exit vortex_cleanup (void) +static void __exit vortex_cleanup(void) { if (vortex_have_pci) - pci_unregister_driver (&vortex_driver); + pci_unregister_driver(&vortex_driver); if (vortex_have_eisa) - vortex_eisa_cleanup (); + vortex_eisa_cleanup(); } module_init(vortex_init); module_exit(vortex_cleanup); - - -/* - * Local variables: - * c-indent-level: 4 - * c-basic-offset: 4 - * tab-width: 4 - * End: - */ -- cgit v1.2.3-59-g8ed1b From a19b27ce3847c3a5d4ea6b6c91b6f7154759af23 Mon Sep 17 00:00:00 2001 From: Matthew Dobson Date: Sun, 26 Mar 2006 01:37:45 -0800 Subject: [PATCH] mempool: use common mempool page allocator Convert two mempool users that currently use their own mempool-backed page allocators to use the generic mempool page allocator. Also included are 2 trivial whitespace fixes. Signed-off-by: Matthew Dobson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-crypt.c | 17 +---------------- mm/highmem.c | 23 +++++++---------------- 2 files changed, 8 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index e7a650f9ca07..d88b8eda3903 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -93,20 +93,6 @@ struct crypt_config { static kmem_cache_t *_crypt_io_pool; -/* - * Mempool alloc and free functions for the page - */ -static void *mempool_alloc_page(gfp_t gfp_mask, void *data) -{ - return alloc_page(gfp_mask); -} - -static void mempool_free_page(void *page, void *data) -{ - __free_page(page); -} - - /* * Different IV generation algorithms: * @@ -637,8 +623,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad3; } - cc->page_pool = mempool_create(MIN_POOL_PAGES, mempool_alloc_page, - mempool_free_page, NULL); + cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0); if (!cc->page_pool) { ti->error = PFX "Cannot allocate page mempool"; goto bad4; diff --git a/mm/highmem.c b/mm/highmem.c index d0ea1eec6a9a..55885f64af40 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -31,14 +31,9 @@ static mempool_t *page_pool, *isa_page_pool; -static void *page_pool_alloc_isa(gfp_t gfp_mask, void *data) +static void *mempool_alloc_pages_isa(gfp_t gfp_mask, void *data) { - return alloc_page(gfp_mask | GFP_DMA); -} - -static void page_pool_free(void *page, void *data) -{ - __free_page(page); + return mempool_alloc_pages(gfp_mask | GFP_DMA, data); } /* @@ -51,11 +46,6 @@ static void page_pool_free(void *page, void *data) */ #ifdef CONFIG_HIGHMEM -static void *page_pool_alloc(gfp_t gfp_mask, void *data) -{ - return alloc_page(gfp_mask); -} - static int pkmap_count[LAST_PKMAP]; static unsigned int last_pkmap_nr; static __cacheline_aligned_in_smp DEFINE_SPINLOCK(kmap_lock); @@ -229,7 +219,7 @@ static __init int init_emergency_pool(void) if (!i.totalhigh) return 0; - page_pool = mempool_create(POOL_SIZE, page_pool_alloc, page_pool_free, NULL); + page_pool = mempool_create_page_pool(POOL_SIZE, 0); if (!page_pool) BUG(); printk("highmem bounce pool size: %d pages\n", POOL_SIZE); @@ -272,7 +262,8 @@ int init_emergency_isa_pool(void) if (isa_page_pool) return 0; - isa_page_pool = mempool_create(ISA_POOL_SIZE, page_pool_alloc_isa, page_pool_free, NULL); + isa_page_pool = mempool_create(ISA_POOL_SIZE, mempool_alloc_pages_isa, + mempool_free_pages, (void *) 0); if (!isa_page_pool) BUG(); @@ -337,7 +328,7 @@ static void bounce_end_io(struct bio *bio, mempool_t *pool, int err) bio_put(bio); } -static int bounce_end_io_write(struct bio *bio, unsigned int bytes_done,int err) +static int bounce_end_io_write(struct bio *bio, unsigned int bytes_done, int err) { if (bio->bi_size) return 1; @@ -384,7 +375,7 @@ static int bounce_end_io_read_isa(struct bio *bio, unsigned int bytes_done, int } static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig, - mempool_t *pool) + mempool_t *pool) { struct page *page; struct bio *bio = NULL; -- cgit v1.2.3-59-g8ed1b From 0eaae62abaa1ad1f231932b6cdd9fb1b91df6651 Mon Sep 17 00:00:00 2001 From: Matthew Dobson Date: Sun, 26 Mar 2006 01:37:47 -0800 Subject: [PATCH] mempool: use common mempool kmalloc allocator This patch changes several mempool users, all of which are basically just wrappers around kmalloc(), to use the common mempool_kmalloc/kfree, rather than their own wrapper function, removing a bunch of duplicated code. Signed-off-by: Matthew Dobson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/pktcdvd.c | 26 +++---------------- drivers/md/bitmap.c | 14 ++--------- drivers/md/dm-io.c | 13 ++-------- drivers/md/dm-raid1.c | 14 ++--------- drivers/s390/scsi/zfcp_aux.c | 60 +++++++++++++------------------------------- drivers/scsi/lpfc/lpfc_mem.c | 22 +++------------- fs/bio.c | 14 ++--------- 7 files changed, 34 insertions(+), 129 deletions(-) (limited to 'drivers') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 1d261f985f31..a04f60693c39 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -230,16 +230,6 @@ static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets) return 1; } -static void *pkt_rb_alloc(gfp_t gfp_mask, void *data) -{ - return kmalloc(sizeof(struct pkt_rb_node), gfp_mask); -} - -static void pkt_rb_free(void *ptr, void *data) -{ - kfree(ptr); -} - static inline struct pkt_rb_node *pkt_rbtree_next(struct pkt_rb_node *node) { struct rb_node *n = rb_next(&node->rb_node); @@ -2073,16 +2063,6 @@ static int pkt_close(struct inode *inode, struct file *file) } -static void *psd_pool_alloc(gfp_t gfp_mask, void *data) -{ - return kmalloc(sizeof(struct packet_stacked_data), gfp_mask); -} - -static void psd_pool_free(void *ptr, void *data) -{ - kfree(ptr); -} - static int pkt_end_io_read_cloned(struct bio *bio, unsigned int bytes_done, int err) { struct packet_stacked_data *psd = bio->bi_private; @@ -2475,7 +2455,8 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) if (!pd) return ret; - pd->rb_pool = mempool_create(PKT_RB_POOL_SIZE, pkt_rb_alloc, pkt_rb_free, NULL); + pd->rb_pool = mempool_create_kmalloc_pool(PKT_RB_POOL_SIZE, + sizeof(struct pkt_rb_node)); if (!pd->rb_pool) goto out_mem; @@ -2639,7 +2620,8 @@ static int __init pkt_init(void) { int ret; - psd_pool = mempool_create(PSD_POOL_SIZE, psd_pool_alloc, psd_pool_free, NULL); + psd_pool = mempool_create_kmalloc_pool(PSD_POOL_SIZE, + sizeof(struct packet_stacked_data)); if (!psd_pool) return -ENOMEM; diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index e1c18aa1d712..f8ffaee20ff8 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -89,16 +89,6 @@ int bitmap_active(struct bitmap *bitmap) } #define WRITE_POOL_SIZE 256 -/* mempool for queueing pending writes on the bitmap file */ -static void *write_pool_alloc(gfp_t gfp_flags, void *data) -{ - return kmalloc(sizeof(struct page_list), gfp_flags); -} - -static void write_pool_free(void *ptr, void *data) -{ - kfree(ptr); -} /* * just a placeholder - calls kmalloc for bitmap pages @@ -1564,8 +1554,8 @@ int bitmap_create(mddev_t *mddev) spin_lock_init(&bitmap->write_lock); INIT_LIST_HEAD(&bitmap->complete_pages); init_waitqueue_head(&bitmap->write_wait); - bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc, - write_pool_free, NULL); + bitmap->write_pool = mempool_create_kmalloc_pool(WRITE_POOL_SIZE, + sizeof(struct page_list)); err = -ENOMEM; if (!bitmap->write_pool) goto error; diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 4809b209fbb1..da663d2ff552 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -32,16 +32,6 @@ struct io { static unsigned _num_ios; static mempool_t *_io_pool; -static void *alloc_io(gfp_t gfp_mask, void *pool_data) -{ - return kmalloc(sizeof(struct io), gfp_mask); -} - -static void free_io(void *element, void *pool_data) -{ - kfree(element); -} - static unsigned int pages_to_ios(unsigned int pages) { return 4 * pages; /* too many ? */ @@ -65,7 +55,8 @@ static int resize_pool(unsigned int new_ios) } else { /* create new pool */ - _io_pool = mempool_create(new_ios, alloc_io, free_io, NULL); + _io_pool = mempool_create_kmalloc_pool(new_ios, + sizeof(struct io)); if (!_io_pool) return -ENOMEM; diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 6cfa8d435d55..4e90f231fbfb 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -122,16 +122,6 @@ static inline sector_t region_to_sector(struct region_hash *rh, region_t region) /* FIXME move this */ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw); -static void *region_alloc(gfp_t gfp_mask, void *pool_data) -{ - return kmalloc(sizeof(struct region), gfp_mask); -} - -static void region_free(void *element, void *pool_data) -{ - kfree(element); -} - #define MIN_REGIONS 64 #define MAX_RECOVERY 1 static int rh_init(struct region_hash *rh, struct mirror_set *ms, @@ -173,8 +163,8 @@ static int rh_init(struct region_hash *rh, struct mirror_set *ms, INIT_LIST_HEAD(&rh->quiesced_regions); INIT_LIST_HEAD(&rh->recovered_regions); - rh->region_pool = mempool_create(MIN_REGIONS, region_alloc, - region_free, NULL); + rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS, + sizeof(struct region)); if (!rh->region_pool) { vfree(rh->buckets); rh->buckets = NULL; diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 95b92f317b6f..395cfc6a344f 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -829,18 +829,6 @@ zfcp_unit_dequeue(struct zfcp_unit *unit) device_unregister(&unit->sysfs_device); } -static void * -zfcp_mempool_alloc(gfp_t gfp_mask, void *size) -{ - return kmalloc((size_t) size, gfp_mask); -} - -static void -zfcp_mempool_free(void *element, void *size) -{ - kfree(element); -} - /* * Allocates a combined QTCB/fsf_req buffer for erp actions and fcp/SCSI * commands. @@ -853,51 +841,39 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) { adapter->pool.fsf_req_erp = - mempool_create(ZFCP_POOL_FSF_REQ_ERP_NR, - zfcp_mempool_alloc, zfcp_mempool_free, (void *) - sizeof(struct zfcp_fsf_req_pool_element)); - - if (NULL == adapter->pool.fsf_req_erp) + mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ERP_NR, + sizeof(struct zfcp_fsf_req_pool_element)); + if (!adapter->pool.fsf_req_erp) return -ENOMEM; adapter->pool.fsf_req_scsi = - mempool_create(ZFCP_POOL_FSF_REQ_SCSI_NR, - zfcp_mempool_alloc, zfcp_mempool_free, (void *) - sizeof(struct zfcp_fsf_req_pool_element)); - - if (NULL == adapter->pool.fsf_req_scsi) + mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_SCSI_NR, + sizeof(struct zfcp_fsf_req_pool_element)); + if (!adapter->pool.fsf_req_scsi) return -ENOMEM; adapter->pool.fsf_req_abort = - mempool_create(ZFCP_POOL_FSF_REQ_ABORT_NR, - zfcp_mempool_alloc, zfcp_mempool_free, (void *) - sizeof(struct zfcp_fsf_req_pool_element)); - - if (NULL == adapter->pool.fsf_req_abort) + mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ABORT_NR, + sizeof(struct zfcp_fsf_req_pool_element)); + if (!adapter->pool.fsf_req_abort) return -ENOMEM; adapter->pool.fsf_req_status_read = - mempool_create(ZFCP_POOL_STATUS_READ_NR, - zfcp_mempool_alloc, zfcp_mempool_free, - (void *) sizeof(struct zfcp_fsf_req)); - - if (NULL == adapter->pool.fsf_req_status_read) + mempool_create_kmalloc_pool(ZFCP_POOL_STATUS_READ_NR, + sizeof(struct zfcp_fsf_req)); + if (!adapter->pool.fsf_req_status_read) return -ENOMEM; adapter->pool.data_status_read = - mempool_create(ZFCP_POOL_STATUS_READ_NR, - zfcp_mempool_alloc, zfcp_mempool_free, - (void *) sizeof(struct fsf_status_read_buffer)); - - if (NULL == adapter->pool.data_status_read) + mempool_create_kmalloc_pool(ZFCP_POOL_STATUS_READ_NR, + sizeof(struct fsf_status_read_buffer)); + if (!adapter->pool.data_status_read) return -ENOMEM; adapter->pool.data_gid_pn = - mempool_create(ZFCP_POOL_DATA_GID_PN_NR, - zfcp_mempool_alloc, zfcp_mempool_free, (void *) - sizeof(struct zfcp_gid_pn_data)); - - if (NULL == adapter->pool.data_gid_pn) + mempool_create_kmalloc_pool(ZFCP_POOL_DATA_GID_PN_NR, + sizeof(struct zfcp_gid_pn_data)); + if (!adapter->pool.data_gid_pn) return -ENOMEM; return 0; diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 352df47bcaca..07017658ac56 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -38,18 +38,6 @@ #define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */ #define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */ -static void * -lpfc_pool_kmalloc(gfp_t gfp_flags, void *data) -{ - return kmalloc((unsigned long)data, gfp_flags); -} - -static void -lpfc_pool_kfree(void *obj, void *data) -{ - kfree(obj); -} - int lpfc_mem_alloc(struct lpfc_hba * phba) { @@ -79,15 +67,13 @@ lpfc_mem_alloc(struct lpfc_hba * phba) pool->current_count++; } - phba->mbox_mem_pool = mempool_create(LPFC_MEM_POOL_SIZE, - lpfc_pool_kmalloc, lpfc_pool_kfree, - (void *)(unsigned long)sizeof(LPFC_MBOXQ_t)); + phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, + sizeof(LPFC_MBOXQ_t)); if (!phba->mbox_mem_pool) goto fail_free_mbuf_pool; - phba->nlp_mem_pool = mempool_create(LPFC_MEM_POOL_SIZE, - lpfc_pool_kmalloc, lpfc_pool_kfree, - (void *)(unsigned long)sizeof(struct lpfc_nodelist)); + phba->nlp_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, + sizeof(struct lpfc_nodelist)); if (!phba->nlp_mem_pool) goto fail_free_mbox_pool; diff --git a/fs/bio.c b/fs/bio.c index 49db9286a3b4..377046d82945 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1125,16 +1125,6 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) return bp; } -static void *bio_pair_alloc(gfp_t gfp_flags, void *data) -{ - return kmalloc(sizeof(struct bio_pair), gfp_flags); -} - -static void bio_pair_free(void *bp, void *data) -{ - kfree(bp); -} - /* * create memory pools for biovec's in a bio_set. @@ -1254,8 +1244,8 @@ static int __init init_bio(void) if (!fs_bio_set) panic("bio: can't allocate bios\n"); - bio_split_pool = mempool_create(BIO_SPLIT_ENTRIES, - bio_pair_alloc, bio_pair_free, NULL); + bio_split_pool = mempool_create_kmalloc_pool(BIO_SPLIT_ENTRIES, + sizeof(struct bio_pair)); if (!bio_split_pool) panic("bio: can't create split pool\n"); -- cgit v1.2.3-59-g8ed1b From 26b6e051bc36b968a0b5ac96903b99e050d20b87 Mon Sep 17 00:00:00 2001 From: Matthew Dobson Date: Sun, 26 Mar 2006 01:37:48 -0800 Subject: [PATCH] mempool: use common mempool kzalloc allocator This patch changes a mempool user, which is basically just a wrapper around kzalloc(), to use the common mempool_kmalloc/kfree, rather than its own wrapper function, removing duplicated code. Signed-off-by: Matthew Dobson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/multipath.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 96f7af4ae400..1cc9de44ce86 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -35,18 +35,6 @@ #define NR_RESERVED_BUFS 32 -static void *mp_pool_alloc(gfp_t gfp_flags, void *data) -{ - struct multipath_bh *mpb; - mpb = kzalloc(sizeof(*mpb), gfp_flags); - return mpb; -} - -static void mp_pool_free(void *mpb, void *data) -{ - kfree(mpb); -} - static int multipath_map (multipath_conf_t *conf) { int i, disks = conf->raid_disks; @@ -494,9 +482,8 @@ static int multipath_run (mddev_t *mddev) } mddev->degraded = conf->raid_disks = conf->working_disks; - conf->pool = mempool_create(NR_RESERVED_BUFS, - mp_pool_alloc, mp_pool_free, - NULL); + conf->pool = mempool_create_kzalloc_pool(NR_RESERVED_BUFS, + sizeof(struct multipath_bh)); if (conf->pool == NULL) { printk(KERN_ERR "multipath: couldn't allocate memory for %s\n", -- cgit v1.2.3-59-g8ed1b From 93d2341c750cda0df48a6cc67b35fe25f1ec47df Mon Sep 17 00:00:00 2001 From: Matthew Dobson Date: Sun, 26 Mar 2006 01:37:50 -0800 Subject: [PATCH] mempool: use mempool_create_slab_pool() Modify well over a dozen mempool users to call mempool_create_slab_pool() rather than calling mempool_create() with extra arguments, saving about 30 lines of code and increasing readability. Signed-off-by: Matthew Dobson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/cfq-iosched.c | 2 +- drivers/block/aoe/aoeblk.c | 4 +--- drivers/md/dm-crypt.c | 3 +-- drivers/md/dm-mpath.c | 3 +-- drivers/md/dm-snap.c | 3 +-- drivers/md/dm.c | 6 ++---- drivers/md/kcopyd.c | 3 +-- drivers/message/i2o/i2o_block.c | 7 +++---- drivers/scsi/iscsi_tcp.c | 4 ++-- drivers/scsi/qla2xxx/qla_os.c | 3 +-- drivers/scsi/scsi_lib.c | 5 ++--- fs/bio.c | 7 ++----- fs/cifs/cifsfs.c | 18 ++++++------------ fs/jfs/jfs_metapage.c | 4 ++-- fs/nfs/read.c | 6 ++---- fs/nfs/write.c | 12 ++++-------- fs/xfs/linux-2.6/xfs_super.c | 5 ++--- include/linux/i2o.h | 4 +--- net/sunrpc/sched.c | 12 ++++-------- 19 files changed, 39 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index c4a0d5d8d7f0..bde40a6ae665 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -2191,7 +2191,7 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e) if (!cfqd->cfq_hash) goto out_cfqhash; - cfqd->crq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, crq_pool); + cfqd->crq_pool = mempool_create_slab_pool(BLKDEV_MIN_RQ, crq_pool); if (!cfqd->crq_pool) goto out_crqpool; diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 32fea55fac48..393b86a3dbf8 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -211,9 +211,7 @@ aoeblk_gdalloc(void *vp) return; } - d->bufpool = mempool_create(MIN_BUFS, - mempool_alloc_slab, mempool_free_slab, - buf_pool_cache); + d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); if (d->bufpool == NULL) { printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate bufpool " "for %ld.%ld\n", d->aoemajor, d->aoeminor); diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index d88b8eda3903..259e86f26549 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -616,8 +616,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) } } - cc->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab, - mempool_free_slab, _crypt_io_pool); + cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool); if (!cc->io_pool) { ti->error = PFX "Cannot allocate crypt io mempool"; goto bad3; diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index f72a82fb9434..1816f30678ed 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -179,8 +179,7 @@ static struct multipath *alloc_multipath(void) m->queue_io = 1; INIT_WORK(&m->process_queued_ios, process_queued_ios, m); INIT_WORK(&m->trigger_event, trigger_event, m); - m->mpio_pool = mempool_create(MIN_IOS, mempool_alloc_slab, - mempool_free_slab, _mpio_cache); + m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache); if (!m->mpio_pool) { kfree(m); return NULL; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index f3759dd7828e..7401540086df 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -1174,8 +1174,7 @@ static int __init dm_snapshot_init(void) goto bad4; } - pending_pool = mempool_create(128, mempool_alloc_slab, - mempool_free_slab, pending_cache); + pending_pool = mempool_create_slab_pool(128, pending_cache); if (!pending_pool) { DMERR("Couldn't create pending pool."); r = -ENOMEM; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 8c82373f7ff3..a64798ef481e 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -823,13 +823,11 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) md->queue->unplug_fn = dm_unplug_all; md->queue->issue_flush_fn = dm_flush_all; - md->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab, - mempool_free_slab, _io_cache); + md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache); if (!md->io_pool) goto bad2; - md->tio_pool = mempool_create(MIN_IOS, mempool_alloc_slab, - mempool_free_slab, _tio_cache); + md->tio_pool = mempool_create_slab_pool(MIN_IOS, _tio_cache); if (!md->tio_pool) goto bad3; diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index 0d54e8b7d9de..9dcb2c8a3853 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c @@ -227,8 +227,7 @@ static int jobs_init(void) if (!_job_cache) return -ENOMEM; - _job_pool = mempool_create(MIN_JOBS, mempool_alloc_slab, - mempool_free_slab, _job_cache); + _job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache); if (!_job_pool) { kmem_cache_destroy(_job_cache); return -ENOMEM; diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index b09fb6307153..7d4c5497785b 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -1179,10 +1179,9 @@ static int __init i2o_block_init(void) goto exit; } - i2o_blk_req_pool.pool = mempool_create(I2O_BLOCK_REQ_MEMPOOL_SIZE, - mempool_alloc_slab, - mempool_free_slab, - i2o_blk_req_pool.slab); + i2o_blk_req_pool.pool = + mempool_create_slab_pool(I2O_BLOCK_REQ_MEMPOOL_SIZE, + i2o_blk_req_pool.slab); if (!i2o_blk_req_pool.pool) { osm_err("can't init request mempool\n"); rc = -ENOMEM; diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 7b82ff090d42..2068b66822b7 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -3200,8 +3200,8 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) * Data-Out PDU's within R2T-sequence can be quite big; * using mempool */ - ctask->datapool = mempool_create(ISCSI_DTASK_DEFAULT_MAX, - mempool_alloc_slab, mempool_free_slab, taskcache); + 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); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 029bbf461bb2..017729c59a49 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2154,8 +2154,7 @@ qla2x00_allocate_sp_pool(scsi_qla_host_t *ha) int rval; rval = QLA_SUCCESS; - ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab, - mempool_free_slab, srb_cachep); + ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep); if (ha->srb_mempool == NULL) { qla_printk(KERN_INFO, ha, "Unable to allocate SRB mempool.\n"); rval = QLA_FUNCTION_FAILED; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ede158d08d9d..8f010a314a3d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1787,9 +1787,8 @@ int __init scsi_init_queue(void) sgp->name); } - sgp->pool = mempool_create(SG_MEMPOOL_SIZE, - mempool_alloc_slab, mempool_free_slab, - sgp->slab); + sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE, + sgp->slab); if (!sgp->pool) { printk(KERN_ERR "SCSI: can't init sg mempool %s\n", sgp->name); diff --git a/fs/bio.c b/fs/bio.c index 377046d82945..eb8fbc53f2cd 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1141,8 +1141,7 @@ static int biovec_create_pools(struct bio_set *bs, int pool_entries, int scale) if (i >= scale) pool_entries >>= 1; - *bvp = mempool_create(pool_entries, mempool_alloc_slab, - mempool_free_slab, bp->slab); + *bvp = mempool_create_slab_pool(pool_entries, bp->slab); if (!*bvp) return -ENOMEM; } @@ -1179,9 +1178,7 @@ struct bio_set *bioset_create(int bio_pool_size, int bvec_pool_size, int scale) if (!bs) return NULL; - bs->bio_pool = mempool_create(bio_pool_size, mempool_alloc_slab, - mempool_free_slab, bio_slab); - + bs->bio_pool = mempool_create_slab_pool(bio_pool_size, bio_slab); if (!bs->bio_pool) goto bad; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 221b3334b737..6b99b51d6694 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -738,10 +738,8 @@ cifs_init_request_bufs(void) cERROR(1,("cifs_min_rcv set to maximum (64)")); } - cifs_req_poolp = mempool_create(cifs_min_rcv, - mempool_alloc_slab, - mempool_free_slab, - cifs_req_cachep); + cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv, + cifs_req_cachep); if(cifs_req_poolp == NULL) { kmem_cache_destroy(cifs_req_cachep); @@ -771,10 +769,8 @@ cifs_init_request_bufs(void) cFYI(1,("cifs_min_small set to maximum (256)")); } - cifs_sm_req_poolp = mempool_create(cifs_min_small, - mempool_alloc_slab, - mempool_free_slab, - cifs_sm_req_cachep); + cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small, + cifs_sm_req_cachep); if(cifs_sm_req_poolp == NULL) { mempool_destroy(cifs_req_poolp); @@ -808,10 +804,8 @@ cifs_init_mids(void) if (cifs_mid_cachep == NULL) return -ENOMEM; - cifs_mid_poolp = mempool_create(3 /* a reasonable min simultan opers */, - mempool_alloc_slab, - mempool_free_slab, - cifs_mid_cachep); + /* 3 is a reasonable minimum number of simultaneous operations */ + cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep); if(cifs_mid_poolp == NULL) { kmem_cache_destroy(cifs_mid_cachep); return -ENOMEM; diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 8508043849f3..f28696f235c4 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -220,8 +220,8 @@ int __init metapage_init(void) if (metapage_cache == NULL) return -ENOMEM; - metapage_mempool = mempool_create(METAPOOL_MIN_PAGES, mempool_alloc_slab, - mempool_free_slab, metapage_cache); + metapage_mempool = mempool_create_slab_pool(METAPOOL_MIN_PAGES, + metapage_cache); if (metapage_mempool == NULL) { kmem_cache_destroy(metapage_cache); diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 3961524fd4ab..624ca7146b6b 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -663,10 +663,8 @@ int nfs_init_readpagecache(void) if (nfs_rdata_cachep == NULL) return -ENOMEM; - nfs_rdata_mempool = mempool_create(MIN_POOL_READ, - mempool_alloc_slab, - mempool_free_slab, - nfs_rdata_cachep); + nfs_rdata_mempool = mempool_create_slab_pool(MIN_POOL_READ, + nfs_rdata_cachep); if (nfs_rdata_mempool == NULL) return -ENOMEM; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 3f5225404c97..4cfada2cc09f 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1521,17 +1521,13 @@ int nfs_init_writepagecache(void) if (nfs_wdata_cachep == NULL) return -ENOMEM; - nfs_wdata_mempool = mempool_create(MIN_POOL_WRITE, - mempool_alloc_slab, - mempool_free_slab, - nfs_wdata_cachep); + nfs_wdata_mempool = mempool_create_slab_pool(MIN_POOL_WRITE, + nfs_wdata_cachep); if (nfs_wdata_mempool == NULL) return -ENOMEM; - nfs_commit_mempool = mempool_create(MIN_POOL_COMMIT, - mempool_alloc_slab, - mempool_free_slab, - nfs_wdata_cachep); + nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT, + nfs_wdata_cachep); if (nfs_commit_mempool == NULL) return -ENOMEM; diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 8355faf8ffde..1884300417e3 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -375,9 +375,8 @@ xfs_init_zones(void) if (!xfs_ioend_zone) goto out_destroy_vnode_zone; - xfs_ioend_pool = mempool_create(4 * MAX_BUF_PER_PAGE, - mempool_alloc_slab, mempool_free_slab, - xfs_ioend_zone); + xfs_ioend_pool = mempool_create_slab_pool(4 * MAX_BUF_PER_PAGE, + xfs_ioend_zone); if (!xfs_ioend_pool) goto out_free_ioend_zone; return 0; diff --git a/include/linux/i2o.h b/include/linux/i2o.h index 5a9d8c599171..dd7d627bf66f 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -950,9 +950,7 @@ static inline int i2o_pool_alloc(struct i2o_pool *pool, const char *name, if (!pool->slab) goto free_name; - pool->mempool = - mempool_create(min_nr, mempool_alloc_slab, mempool_free_slab, - pool->slab); + pool->mempool = mempool_create_slab_pool(min_nr, pool->slab); if (!pool->mempool) goto free_slab; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index b9969b91a9f7..5c3eee768504 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -1167,16 +1167,12 @@ rpc_init_mempool(void) NULL, NULL); if (!rpc_buffer_slabp) goto err_nomem; - rpc_task_mempool = mempool_create(RPC_TASK_POOLSIZE, - mempool_alloc_slab, - mempool_free_slab, - rpc_task_slabp); + rpc_task_mempool = mempool_create_slab_pool(RPC_TASK_POOLSIZE, + rpc_task_slabp); if (!rpc_task_mempool) goto err_nomem; - rpc_buffer_mempool = mempool_create(RPC_BUFFER_POOLSIZE, - mempool_alloc_slab, - mempool_free_slab, - rpc_buffer_slabp); + rpc_buffer_mempool = mempool_create_slab_pool(RPC_BUFFER_POOLSIZE, + rpc_buffer_slabp); if (!rpc_buffer_mempool) goto err_nomem; return 0; -- cgit v1.2.3-59-g8ed1b From 0a34eb8f55a71678c379b47c25f562050c80efcc Mon Sep 17 00:00:00 2001 From: Hansjoerg Lipp Date: Sun, 26 Mar 2006 01:38:28 -0800 Subject: [PATCH] isdn4linux: Siemens Gigaset drivers - Kconfigs and Makefiles And: Tilman Schmidt The following patches add drivers for the Siemens Gigaset 3070 family of ISDN DECT PABXes connected via USB, either directly or over a DECT link using a Gigaset M105 or compatible DECT data adapter. The devices are integrated as ISDN adapters within the isdn4linux framework, supporting incoming and outgoing voice and data connections, and also as tty devices providing access to device specific AT commands. Supported devices include models 3070, 3075, 4170, 4175, SX205, SX255, and SX353 from the Siemens Gigaset product family, as well as the technically identical models 45isdn and 721X from the Deutsche Telekom Sinus series. Supported DECT adapters are the Gigaset M105 data and the technically identical Gigaset USB Adapter DECT, Sinus 45 data 2, and Sinus 721 data (but not the Gigaset M34 and Sinus 702 data which advertise themselves as CDC-ACM devices). These drivers have been developed over the last four years within the SourceForge project http://sourceforge.net/projects/gigaset307x/. They are being used successfully in several installations for dial-in Internet access and for voice call switching with Asterisk. This is our second attempt at submitting these drivers, taking into account the comments we received to our first submission on 2005-12-11. The patch set adds three kernel modules: - a common module "gigaset" encapsulating the common logic for controlling the PABX and the interfaces to userspace and the isdn4linux subsystem. - a connection-specific module "bas_gigaset" which handles communication with the PABX over a direct USB connection. - a connection-specific module "usb_gigaset" which does the same for a DECT connection using the Gigaset M105 USB DECT adapter. We also have a module "ser_gigaset" which supports the Gigaset M101 RS232 DECT adapter, but we didn't judge it fit for inclusion in the kernel, as it does direct programming of a i8250 serial port. It should probably be rewritten as a serial line discipline but so far we lack the neccessary knowledge about writing a line discipline for that. The drivers have been working with kernel releases 2.2 and 2.4 as well as 2.6, and although we took efforts to remove the compatibility code for this submission, it probably still shows in places. Please make allowances. This patch: Prepare the kernel build infrastructure for addition of the Gigaset ISDN drivers. It creates a Makefile and Kconfig file for the Gigaset driver and hooks them into those of the isdn4linux subsystem. It also adds a MAINTAINERS entry for the driver. This patch depends on patches 2 to 9 of the present set, as without the actual source files, activating the options added here will cause the kernel build to fail. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Cc: Karsten Keil Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 9 +++++++++ drivers/isdn/Makefile | 1 + drivers/isdn/gigaset/Kconfig | 42 ++++++++++++++++++++++++++++++++++++++++++ drivers/isdn/gigaset/Makefile | 6 ++++++ drivers/isdn/i4l/Kconfig | 1 + 5 files changed, 59 insertions(+) create mode 100644 drivers/isdn/gigaset/Kconfig create mode 100644 drivers/isdn/gigaset/Makefile (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 4e8fbbc5566d..e09341698025 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1039,6 +1039,15 @@ M: khc@pm.waw.pl W: http://www.kernel.org/pub/linux/utils/net/hdlc/ S: Maintained +GIGASET ISDN DRIVERS +P: Hansjoerg Lipp +M: hjlipp@web.de +P: Tilman Schmidt +M: tilman@imap.cc +L: gigaset307x-common@lists.sourceforge.net +W: http://gigaset307x.sourceforge.net/ +S: Maintained + HARDWARE MONITORING P: Jean Delvare M: khali@linux-fr.org diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile index 03d8ccd51955..988142c30a6d 100644 --- a/drivers/isdn/Makefile +++ b/drivers/isdn/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_ISDN_DRV_SC) += sc/ obj-$(CONFIG_ISDN_DRV_LOOP) += isdnloop/ obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000/ obj-$(CONFIG_HYSDN) += hysdn/ +obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset/ diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig new file mode 100644 index 000000000000..53c4fb62ed85 --- /dev/null +++ b/drivers/isdn/gigaset/Kconfig @@ -0,0 +1,42 @@ +menu "Siemens Gigaset" + depends on ISDN_I4L + +config ISDN_DRV_GIGASET + tristate "Siemens Gigaset support (isdn)" + depends on ISDN_I4L && m +# depends on ISDN_I4L && MODULES + help + Say m here if you have a Gigaset or Sinus isdn device. + +if ISDN_DRV_GIGASET!=n + +config GIGASET_BASE + tristate "Gigaset base station support" + depends on ISDN_DRV_GIGASET && USB + help + Say m here if you need to communicate with the base + directly via USB. + +config GIGASET_M105 + tristate "Gigaset M105 support" + depends on ISDN_DRV_GIGASET && USB + help + Say m here if you need the driver for the Gigaset M105 device. + +config GIGASET_DEBUG + bool "Gigaset debugging" + help + This enables debugging code in the Gigaset drivers. + If in doubt, say yes. + +config GIGASET_UNDOCREQ + bool "Support for undocumented USB requests" + help + This enables support for USB requests we only know from + reverse engineering (currently M105 only). If you need + features like configuration mode of M105, say yes. If you + care about your device, say no. + +endif + +endmenu diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile new file mode 100644 index 000000000000..9b9acf1a21ad --- /dev/null +++ b/drivers/isdn/gigaset/Makefile @@ -0,0 +1,6 @@ +gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o +usb_gigaset-y := usb-gigaset.o asyncdata.o +bas_gigaset-y := bas-gigaset.o isocdata.o + +obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o gigaset.o +obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o gigaset.o diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index 1789b607f090..a4f7288a1fc8 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig @@ -139,3 +139,4 @@ source "drivers/isdn/hysdn/Kconfig" endmenu +source "drivers/isdn/gigaset/Kconfig" -- cgit v1.2.3-59-g8ed1b From 6fd5ea63f85e30fda55b80939b4f379ea5db62b1 Mon Sep 17 00:00:00 2001 From: Hansjoerg Lipp Date: Sun, 26 Mar 2006 01:38:29 -0800 Subject: [PATCH] isdn4linux: Siemens Gigaset drivers - common module And: Tilman Schmidt This patch adds the common include file for the Siemens Gigaset drivers, providing definitions used by all of the Gigaset ISDN driver source files. It also adds the main source file of the gigaset module which manages common functions not specific to the type of connection to the device. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Cc: Karsten Keil Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/gigaset/common.c | 1203 ++++++++++++++++++++++++++++++++++++++++ drivers/isdn/gigaset/gigaset.h | 938 +++++++++++++++++++++++++++++++ 2 files changed, 2141 insertions(+) create mode 100644 drivers/isdn/gigaset/common.c create mode 100644 drivers/isdn/gigaset/gigaset.h (limited to 'drivers') diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c new file mode 100644 index 000000000000..64371995c1a9 --- /dev/null +++ b/drivers/isdn/gigaset/common.c @@ -0,0 +1,1203 @@ +/* + * Stuff used by all variants of the driver + * + * Copyright (c) 2001 by Stefan Eilers , + * Hansjoerg Lipp , + * Tilman Schmidt . + * + * ===================================================================== + * 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. + * ===================================================================== + * ToDo: ... + * ===================================================================== + * Version: $Id: common.c,v 1.104.4.22 2006/02/04 18:28:16 hjlipp Exp $ + * ===================================================================== + */ + +#include "gigaset.h" +#include +#include +#include + +/* Version Information */ +#define DRIVER_AUTHOR "Hansjoerg Lipp , Tilman Schmidt , Stefan Eilers " +#define DRIVER_DESC "Driver for Gigaset 307x" + +/* Module parameters */ +int gigaset_debuglevel = DEBUG_DEFAULT; +EXPORT_SYMBOL_GPL(gigaset_debuglevel); +module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(debug, "debug level"); + +/*====================================================================== + Prototypes of internal functions + */ + +//static void gigaset_process_response(int resp_code, int parameter, +// struct at_state_t *at_state, +// unsigned char ** pstring); +static struct cardstate *alloc_cs(struct gigaset_driver *drv); +static void free_cs(struct cardstate *cs); +static void make_valid(struct cardstate *cs, unsigned mask); +static void make_invalid(struct cardstate *cs, unsigned mask); + +#define VALID_MINOR 0x01 +#define VALID_ID 0x02 +#define ASSIGNED 0x04 + +/* bitwise byte inversion table */ +__u8 gigaset_invtab[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; +EXPORT_SYMBOL_GPL(gigaset_invtab); + +void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, + size_t len, const unsigned char *buf, int from_user) +{ + unsigned char outbuf[80]; + unsigned char inbuf[80 - 1]; + size_t numin; + const unsigned char *in; + size_t space = sizeof outbuf - 1; + unsigned char *out = outbuf; + + if (!from_user) { + in = buf; + numin = len; + } else { + numin = len < sizeof inbuf ? len : sizeof inbuf; + in = inbuf; + if (copy_from_user(inbuf, (const unsigned char __user *) buf, numin)) { + strncpy(inbuf, "", sizeof inbuf); + numin = sizeof "" - 1; + } + } + + for (; numin && space; --numin, ++in) { + --space; + if (*in >= 32) + *out++ = *in; + else { + *out++ = '^'; + if (space) { + *out++ = '@' + *in; + --space; + } + } + } + *out = 0; + + dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf); +} +EXPORT_SYMBOL_GPL(gigaset_dbg_buffer); + +static int setflags(struct cardstate *cs, unsigned flags, unsigned delay) +{ + int r; + + r = cs->ops->set_modem_ctrl(cs, cs->control_state, flags); + cs->control_state = flags; + if (r < 0) + return r; + + if (delay) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(delay * HZ / 1000); + } + + return 0; +} + +int gigaset_enterconfigmode(struct cardstate *cs) +{ + int i, r; + + if (!atomic_read(&cs->connected)) { + err("not connected!"); + return -1; + } + + cs->control_state = TIOCM_RTS; //FIXME + + r = setflags(cs, TIOCM_DTR, 200); + if (r < 0) + goto error; + r = setflags(cs, 0, 200); + if (r < 0) + goto error; + for (i = 0; i < 5; ++i) { + r = setflags(cs, TIOCM_RTS, 100); + if (r < 0) + goto error; + r = setflags(cs, 0, 100); + if (r < 0) + goto error; + } + r = setflags(cs, TIOCM_RTS|TIOCM_DTR, 800); + if (r < 0) + goto error; + + return 0; + +error: + err("error %d on setuartbits!\n", -r); + cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value? + cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR); + + return -1; //r +} + +static int test_timeout(struct at_state_t *at_state) +{ + if (!at_state->timer_expires) + return 0; + + if (--at_state->timer_expires) { + dbg(DEBUG_MCMD, "decreased timer of %p to %lu", + at_state, at_state->timer_expires); + return 0; + } + + if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, + atomic_read(&at_state->timer_index), NULL)) { + //FIXME what should we do? + } + + return 1; +} + +static void timer_tick(unsigned long data) +{ + struct cardstate *cs = (struct cardstate *) data; + unsigned long flags; + unsigned channel; + struct at_state_t *at_state; + int timeout = 0; + + spin_lock_irqsave(&cs->lock, flags); + + for (channel = 0; channel < cs->channels; ++channel) + if (test_timeout(&cs->bcs[channel].at_state)) + timeout = 1; + + if (test_timeout(&cs->at_state)) + timeout = 1; + + list_for_each_entry(at_state, &cs->temp_at_states, list) + if (test_timeout(at_state)) + timeout = 1; + + if (atomic_read(&cs->running)) { + mod_timer(&cs->timer, jiffies + GIG_TICK); + if (timeout) { + dbg(DEBUG_CMD, "scheduling timeout"); + tasklet_schedule(&cs->event_tasklet); + } + } + + spin_unlock_irqrestore(&cs->lock, flags); +} + +int gigaset_get_channel(struct bc_state *bcs) +{ + unsigned long flags; + + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->use_count) { + dbg(DEBUG_ANY, "could not allocate channel %d", bcs->channel); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + return 0; + } + ++bcs->use_count; + bcs->busy = 1; + dbg(DEBUG_ANY, "allocated channel %d", bcs->channel); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + return 1; +} + +void gigaset_free_channel(struct bc_state *bcs) +{ + unsigned long flags; + + spin_lock_irqsave(&bcs->cs->lock, flags); + if (!bcs->busy) { + dbg(DEBUG_ANY, "could not free channel %d", bcs->channel); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + return; + } + --bcs->use_count; + bcs->busy = 0; + dbg(DEBUG_ANY, "freed channel %d", bcs->channel); + spin_unlock_irqrestore(&bcs->cs->lock, flags); +} + +int gigaset_get_channels(struct cardstate *cs) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&cs->lock, flags); + for (i = 0; i < cs->channels; ++i) + if (cs->bcs[i].use_count) { + spin_unlock_irqrestore(&cs->lock, flags); + dbg(DEBUG_ANY, "could not allocated all channels"); + return 0; + } + for (i = 0; i < cs->channels; ++i) + ++cs->bcs[i].use_count; + spin_unlock_irqrestore(&cs->lock, flags); + + dbg(DEBUG_ANY, "allocated all channels"); + + return 1; +} + +void gigaset_free_channels(struct cardstate *cs) +{ + unsigned long flags; + int i; + + dbg(DEBUG_ANY, "unblocking all channels"); + spin_lock_irqsave(&cs->lock, flags); + for (i = 0; i < cs->channels; ++i) + --cs->bcs[i].use_count; + spin_unlock_irqrestore(&cs->lock, flags); +} + +void gigaset_block_channels(struct cardstate *cs) +{ + unsigned long flags; + int i; + + dbg(DEBUG_ANY, "blocking all channels"); + spin_lock_irqsave(&cs->lock, flags); + for (i = 0; i < cs->channels; ++i) + ++cs->bcs[i].use_count; + spin_unlock_irqrestore(&cs->lock, flags); +} + +static void clear_events(struct cardstate *cs) +{ + struct event_t *ev; + unsigned head, tail; + + /* no locking needed (no reader/writer allowed) */ + + head = atomic_read(&cs->ev_head); + tail = atomic_read(&cs->ev_tail); + + while (tail != head) { + ev = cs->events + head; + kfree(ev->ptr); + + head = (head + 1) % MAX_EVENTS; + } + + atomic_set(&cs->ev_head, tail); +} + +struct event_t *gigaset_add_event(struct cardstate *cs, + struct at_state_t *at_state, int type, + void *ptr, int parameter, void *arg) +{ + unsigned long flags; + unsigned next, tail; + struct event_t *event = NULL; + + spin_lock_irqsave(&cs->ev_lock, flags); + + tail = atomic_read(&cs->ev_tail); + next = (tail + 1) % MAX_EVENTS; + if (unlikely(next == atomic_read(&cs->ev_head))) + err("event queue full"); + else { + event = cs->events + tail; + event->type = type; + event->at_state = at_state; + event->cid = -1; + event->ptr = ptr; + event->arg = arg; + event->parameter = parameter; + atomic_set(&cs->ev_tail, next); + } + + spin_unlock_irqrestore(&cs->ev_lock, flags); + + return event; +} +EXPORT_SYMBOL_GPL(gigaset_add_event); + +static void free_strings(struct at_state_t *at_state) +{ + int i; + + for (i = 0; i < STR_NUM; ++i) { + kfree(at_state->str_var[i]); + at_state->str_var[i] = NULL; + } +} + +static void clear_at_state(struct at_state_t *at_state) +{ + free_strings(at_state); +} + +static void dealloc_at_states(struct cardstate *cs) +{ + struct at_state_t *cur, *next; + + list_for_each_entry_safe(cur, next, &cs->temp_at_states, list) { + list_del(&cur->list); + free_strings(cur); + kfree(cur); + } +} + +static void gigaset_freebcs(struct bc_state *bcs) +{ + int i; + + dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); + if (!bcs->cs->ops->freebcshw(bcs)) { + dbg(DEBUG_INIT, "failed"); + } + + dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); + clear_at_state(&bcs->at_state); + dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); + + if (bcs->skb) + dev_kfree_skb(bcs->skb); + for (i = 0; i < AT_NUM; ++i) { + kfree(bcs->commands[i]); + bcs->commands[i] = NULL; + } +} + +void gigaset_freecs(struct cardstate *cs) +{ + int i; + unsigned long flags; + + if (!cs) + return; + + down(&cs->sem); + + if (!cs->bcs) + goto f_cs; + if (!cs->inbuf) + goto f_bcs; + + spin_lock_irqsave(&cs->lock, flags); + atomic_set(&cs->running, 0); + spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are not rescheduled below */ + + tasklet_kill(&cs->event_tasklet); + del_timer_sync(&cs->timer); + + switch (cs->cs_init) { + default: + gigaset_if_free(cs); + + dbg(DEBUG_INIT, "clearing hw"); + cs->ops->freecshw(cs); + + //FIXME cmdbuf + + /* fall through */ + case 2: /* error in initcshw */ + /* Deregister from LL */ + make_invalid(cs, VALID_ID); + dbg(DEBUG_INIT, "clearing iif"); + gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); + + /* fall through */ + case 1: /* error when regestering to LL */ + dbg(DEBUG_INIT, "clearing at_state"); + clear_at_state(&cs->at_state); + dealloc_at_states(cs); + + /* fall through */ + case 0: /* error in one call to initbcs */ + for (i = 0; i < cs->channels; ++i) { + dbg(DEBUG_INIT, "clearing bcs[%d]", i); + gigaset_freebcs(cs->bcs + i); + } + + clear_events(cs); + dbg(DEBUG_INIT, "freeing inbuf"); + kfree(cs->inbuf); + } +f_bcs: dbg(DEBUG_INIT, "freeing bcs[]"); + kfree(cs->bcs); +f_cs: dbg(DEBUG_INIT, "freeing cs"); + up(&cs->sem); + free_cs(cs); +} +EXPORT_SYMBOL_GPL(gigaset_freecs); + +void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, + struct cardstate *cs, int cid) +{ + int i; + + INIT_LIST_HEAD(&at_state->list); + at_state->waiting = 0; + at_state->getstring = 0; + at_state->pending_commands = 0; + at_state->timer_expires = 0; + at_state->timer_active = 0; + atomic_set(&at_state->timer_index, 0); + atomic_set(&at_state->seq_index, 0); + at_state->ConState = 0; + for (i = 0; i < STR_NUM; ++i) + at_state->str_var[i] = NULL; + at_state->int_var[VAR_ZDLE] = 0; + at_state->int_var[VAR_ZCTP] = -1; + at_state->int_var[VAR_ZSAU] = ZSAU_NULL; + at_state->cs = cs; + at_state->bcs = bcs; + at_state->cid = cid; + if (!cid) + at_state->replystruct = cs->tabnocid; + else + at_state->replystruct = cs->tabcid; +} + + +static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, + struct cardstate *cs, int inputstate) +/* inbuf->read must be allocated before! */ +{ + atomic_set(&inbuf->head, 0); + atomic_set(&inbuf->tail, 0); + inbuf->cs = cs; + inbuf->bcs = bcs; /*base driver: NULL*/ + inbuf->rcvbuf = NULL; //FIXME + inbuf->inputstate = inputstate; +} + +/* Initialize the b-channel structure */ +static struct bc_state *gigaset_initbcs(struct bc_state *bcs, + struct cardstate *cs, int channel) +{ + int i; + + bcs->tx_skb = NULL; //FIXME -> hw part + + skb_queue_head_init(&bcs->squeue); + + bcs->corrupted = 0; + bcs->trans_down = 0; + bcs->trans_up = 0; + + dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel); + gigaset_at_init(&bcs->at_state, bcs, cs, -1); + + bcs->rcvbytes = 0; + +#ifdef CONFIG_GIGASET_DEBUG + bcs->emptycount = 0; +#endif + + dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); + bcs->fcs = PPP_INITFCS; + bcs->inputstate = 0; + if (cs->ignoreframes) { + bcs->inputstate |= INS_skip_frame; + bcs->skb = NULL; + } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) + skb_reserve(bcs->skb, HW_HDR_LEN); + else { + warn("could not allocate skb"); + bcs->inputstate |= INS_skip_frame; + } + + bcs->channel = channel; + bcs->cs = cs; + + bcs->chstate = 0; + bcs->use_count = 1; + bcs->busy = 0; + bcs->ignore = cs->ignoreframes; + + for (i = 0; i < AT_NUM; ++i) + bcs->commands[i] = NULL; + + dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel); + if (cs->ops->initbcshw(bcs)) + return bcs; + +//error: + dbg(DEBUG_INIT, " failed"); + + dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); + if (bcs->skb) + dev_kfree_skb(bcs->skb); + + return NULL; +} + +/* gigaset_initcs + * Allocate and initialize cardstate structure for Gigaset driver + * Calls hardware dependent gigaset_initcshw() function + * Calls B channel initialization function gigaset_initbcs() for each B channel + * parameters: + * drv hardware driver the device belongs to + * channels number of B channels supported by device + * onechannel !=0: B channel data and AT commands share one communication channel + * ==0: B channels have separate communication channels + * ignoreframes number of frames to ignore after setting up B channel + * cidmode !=0: start in CallID mode + * modulename name of driver module (used for I4L registration) + * return value: + * pointer to cardstate structure + */ +struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, + int onechannel, int ignoreframes, + int cidmode, const char *modulename) +{ + struct cardstate *cs = NULL; + int i; + + dbg(DEBUG_INIT, "allocating cs"); + cs = alloc_cs(drv); + if (!cs) + goto error; + dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1); + cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL); + if (!cs->bcs) + goto error; + dbg(DEBUG_INIT, "allocating inbuf"); + cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL); + if (!cs->inbuf) + goto error; + + cs->cs_init = 0; + cs->channels = channels; + cs->onechannel = onechannel; + cs->ignoreframes = ignoreframes; + INIT_LIST_HEAD(&cs->temp_at_states); + atomic_set(&cs->running, 0); + init_timer(&cs->timer); /* clear next & prev */ + spin_lock_init(&cs->ev_lock); + atomic_set(&cs->ev_tail, 0); + atomic_set(&cs->ev_head, 0); + init_MUTEX_LOCKED(&cs->sem); + tasklet_init(&cs->event_tasklet, &gigaset_handle_event, (unsigned long) cs); + atomic_set(&cs->commands_pending, 0); + cs->cur_at_seq = 0; + cs->gotfwver = -1; + cs->open_count = 0; + cs->tty = NULL; + atomic_set(&cs->cidmode, cidmode != 0); + + //if(onechannel) { //FIXME + cs->tabnocid = gigaset_tab_nocid_m10x; + cs->tabcid = gigaset_tab_cid_m10x; + //} else { + // cs->tabnocid = gigaset_tab_nocid; + // cs->tabcid = gigaset_tab_cid; + //} + + init_waitqueue_head(&cs->waitqueue); + cs->waiting = 0; + + atomic_set(&cs->mode, M_UNKNOWN); + atomic_set(&cs->mstate, MS_UNINITIALIZED); + + for (i = 0; i < channels; ++i) { + dbg(DEBUG_INIT, "setting up bcs[%d].read", i); + if (!gigaset_initbcs(cs->bcs + i, cs, i)) + goto error; + } + + ++cs->cs_init; + + dbg(DEBUG_INIT, "setting up at_state"); + spin_lock_init(&cs->lock); + gigaset_at_init(&cs->at_state, NULL, cs, 0); + cs->dle = 0; + cs->cbytes = 0; + + dbg(DEBUG_INIT, "setting up inbuf"); + if (onechannel) { //FIXME distinction necessary? + gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command); + } else + gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command); + + atomic_set(&cs->connected, 0); + + dbg(DEBUG_INIT, "setting up cmdbuf"); + cs->cmdbuf = cs->lastcmdbuf = NULL; + spin_lock_init(&cs->cmdlock); + cs->curlen = 0; + cs->cmdbytes = 0; + + /* + * Tell the ISDN4Linux subsystem (the LL) that + * a driver for a USB-Device is available ! + * If this is done, "isdnctrl" is able to bind a device for this driver even + * if no physical usb-device is currently connected. + * But this device will just be accessable if a physical USB device is connected + * (via "gigaset_probe") . + */ + dbg(DEBUG_INIT, "setting up iif"); + if (!gigaset_register_to_LL(cs, modulename)) { + err("register_isdn=>error"); + goto error; + } + + make_valid(cs, VALID_ID); + ++cs->cs_init; + dbg(DEBUG_INIT, "setting up hw"); + if (!cs->ops->initcshw(cs)) + goto error; + + ++cs->cs_init; + + gigaset_if_init(cs); + + atomic_set(&cs->running, 1); + cs->timer.data = (unsigned long) cs; + cs->timer.function = timer_tick; + cs->timer.expires = jiffies + GIG_TICK; + /* FIXME: can jiffies increase too much until the timer is added? + * Same problem(?) with mod_timer() in timer_tick(). */ + add_timer(&cs->timer); + + dbg(DEBUG_INIT, "cs initialized!"); + up(&cs->sem); + return cs; + +error: if (cs) + up(&cs->sem); + dbg(DEBUG_INIT, "failed"); + gigaset_freecs(cs); + return NULL; +} +EXPORT_SYMBOL_GPL(gigaset_initcs); + +/* ReInitialize the b-channel structure */ /* e.g. called on hangup, disconnect */ +void gigaset_bcs_reinit(struct bc_state *bcs) +{ + struct sk_buff *skb; + struct cardstate *cs = bcs->cs; + unsigned long flags; + + while ((skb = skb_dequeue(&bcs->squeue)) != NULL) + dev_kfree_skb(skb); + + spin_lock_irqsave(&cs->lock, flags); //FIXME + clear_at_state(&bcs->at_state); + bcs->at_state.ConState = 0; + bcs->at_state.timer_active = 0; + bcs->at_state.timer_expires = 0; + bcs->at_state.cid = -1; /* No CID defined */ + spin_unlock_irqrestore(&cs->lock, flags); + + bcs->inputstate = 0; + +#ifdef CONFIG_GIGASET_DEBUG + bcs->emptycount = 0; +#endif + + bcs->fcs = PPP_INITFCS; + bcs->chstate = 0; + + bcs->ignore = cs->ignoreframes; + if (bcs->ignore) + bcs->inputstate |= INS_skip_frame; + + + cs->ops->reinitbcshw(bcs); +} + +static void cleanup_cs(struct cardstate *cs) +{ + struct cmdbuf_t *cb, *tcb; + int i; + unsigned long flags; + + spin_lock_irqsave(&cs->lock, flags); + + atomic_set(&cs->mode, M_UNKNOWN); + atomic_set(&cs->mstate, MS_UNINITIALIZED); + + clear_at_state(&cs->at_state); + dealloc_at_states(cs); + free_strings(&cs->at_state); + gigaset_at_init(&cs->at_state, NULL, cs, 0); + + kfree(cs->inbuf->rcvbuf); + cs->inbuf->rcvbuf = NULL; + cs->inbuf->inputstate = INS_command; + atomic_set(&cs->inbuf->head, 0); + atomic_set(&cs->inbuf->tail, 0); + + cb = cs->cmdbuf; + while (cb) { + tcb = cb; + cb = cb->next; + kfree(tcb); + } + cs->cmdbuf = cs->lastcmdbuf = NULL; + cs->curlen = 0; + cs->cmdbytes = 0; + cs->gotfwver = -1; + cs->dle = 0; + cs->cur_at_seq = 0; + atomic_set(&cs->commands_pending, 0); + cs->cbytes = 0; + + spin_unlock_irqrestore(&cs->lock, flags); + + for (i = 0; i < cs->channels; ++i) { + gigaset_freebcs(cs->bcs + i); + if (!gigaset_initbcs(cs->bcs + i, cs, i)) + break; //FIXME error handling + } + + if (cs->waiting) { + cs->cmd_result = -ENODEV; + cs->waiting = 0; + wake_up_interruptible(&cs->waitqueue); + } +} + + +int gigaset_start(struct cardstate *cs) +{ + if (down_interruptible(&cs->sem)) + return 0; + //info("USB device for Gigaset 307x now attached to Dev %d", ucs->minor); + + atomic_set(&cs->connected, 1); + + if (atomic_read(&cs->mstate) != MS_LOCKED) { + cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); + cs->ops->baud_rate(cs, B115200); + cs->ops->set_line_ctrl(cs, CS8); + cs->control_state = TIOCM_DTR|TIOCM_RTS; + } else { + //FIXME use some saved values? + } + + cs->waiting = 1; + + if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) { + cs->waiting = 0; + //FIXME what should we do? + goto error; + } + + dbg(DEBUG_CMD, "scheduling START"); + gigaset_schedule_event(cs); + + wait_event(cs->waitqueue, !cs->waiting); + + up(&cs->sem); + return 1; + +error: + up(&cs->sem); + return 0; +} +EXPORT_SYMBOL_GPL(gigaset_start); + +void gigaset_shutdown(struct cardstate *cs) +{ + down(&cs->sem); + + cs->waiting = 1; + + if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { + //FIXME what should we do? + goto exit; + } + + dbg(DEBUG_CMD, "scheduling SHUTDOWN"); + gigaset_schedule_event(cs); + + if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) { + warn("aborted"); + //FIXME + } + + if (atomic_read(&cs->mstate) != MS_LOCKED) { + //FIXME? + //gigaset_baud_rate(cs, B115200); + //gigaset_set_line_ctrl(cs, CS8); + //gigaset_set_modem_ctrl(cs, TIOCM_DTR|TIOCM_RTS, 0); + //cs->control_state = 0; + } else { + //FIXME use some saved values? + } + + cleanup_cs(cs); + +exit: + up(&cs->sem); +} +EXPORT_SYMBOL_GPL(gigaset_shutdown); + +void gigaset_stop(struct cardstate *cs) +{ + down(&cs->sem); + + atomic_set(&cs->connected, 0); + + cs->waiting = 1; + + if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) { + //FIXME what should we do? + goto exit; + } + + dbg(DEBUG_CMD, "scheduling STOP"); + gigaset_schedule_event(cs); + + if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) { + warn("aborted"); + //FIXME + } + + /* Tell the LL that the device is not available .. */ + gigaset_i4l_cmd(cs, ISDN_STAT_STOP); // FIXME move to event layer? + + cleanup_cs(cs); + +exit: + up(&cs->sem); +} +EXPORT_SYMBOL_GPL(gigaset_stop); + +static LIST_HEAD(drivers); +static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED; + +struct cardstate *gigaset_get_cs_by_id(int id) +{ + unsigned long flags; + static struct cardstate *ret = NULL; + static struct cardstate *cs; + struct gigaset_driver *drv; + unsigned i; + + spin_lock_irqsave(&driver_lock, flags); + list_for_each_entry(drv, &drivers, list) { + spin_lock(&drv->lock); + for (i = 0; i < drv->minors; ++i) { + if (drv->flags[i] & VALID_ID) { + cs = drv->cs + i; + if (cs->myid == id) + ret = cs; + } + if (ret) + break; + } + spin_unlock(&drv->lock); + if (ret) + break; + } + spin_unlock_irqrestore(&driver_lock, flags); + return ret; +} + +void gigaset_debugdrivers(void) +{ + unsigned long flags; + static struct cardstate *cs; + struct gigaset_driver *drv; + unsigned i; + + spin_lock_irqsave(&driver_lock, flags); + list_for_each_entry(drv, &drivers, list) { + dbg(DEBUG_DRIVER, "driver %p", drv); + spin_lock(&drv->lock); + for (i = 0; i < drv->minors; ++i) { + dbg(DEBUG_DRIVER, " index %u", i); + dbg(DEBUG_DRIVER, " flags 0x%02x", drv->flags[i]); + cs = drv->cs + i; + dbg(DEBUG_DRIVER, " cardstate %p", cs); + dbg(DEBUG_DRIVER, " minor_index %u", cs->minor_index); + dbg(DEBUG_DRIVER, " driver %p", cs->driver); + dbg(DEBUG_DRIVER, " i4l id %d", cs->myid); + } + spin_unlock(&drv->lock); + } + spin_unlock_irqrestore(&driver_lock, flags); +} +EXPORT_SYMBOL_GPL(gigaset_debugdrivers); + +struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) +{ + if (tty->index < 0 || tty->index >= tty->driver->num) + return NULL; + return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); +} + +struct cardstate *gigaset_get_cs_by_minor(unsigned minor) +{ + unsigned long flags; + static struct cardstate *ret = NULL; + struct gigaset_driver *drv; + unsigned index; + + spin_lock_irqsave(&driver_lock, flags); + list_for_each_entry(drv, &drivers, list) { + if (minor < drv->minor || minor >= drv->minor + drv->minors) + continue; + index = minor - drv->minor; + spin_lock(&drv->lock); + if (drv->flags[index] & VALID_MINOR) + ret = drv->cs + index; + spin_unlock(&drv->lock); + if (ret) + break; + } + spin_unlock_irqrestore(&driver_lock, flags); + return ret; +} + +void gigaset_freedriver(struct gigaset_driver *drv) +{ + unsigned long flags; + + spin_lock_irqsave(&driver_lock, flags); + list_del(&drv->list); + spin_unlock_irqrestore(&driver_lock, flags); + + gigaset_if_freedriver(drv); + module_put(drv->owner); + + kfree(drv->cs); + kfree(drv->flags); + kfree(drv); +} +EXPORT_SYMBOL_GPL(gigaset_freedriver); + +/* gigaset_initdriver + * Allocate and initialize gigaset_driver structure. Initialize interface. + * parameters: + * minor First minor number + * minors Number of minors this driver can handle + * procname Name of the driver (e.g. for /proc/tty/drivers, path in /proc/driver) + * devname Name of the device files (prefix without minor number) + * devfsname Devfs name of the device files without %d + * return value: + * Pointer to the gigaset_driver structure on success, NULL on failure. + */ +struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, + const char *procname, + const char *devname, + const char *devfsname, + const struct gigaset_ops *ops, + struct module *owner) +{ + struct gigaset_driver *drv; + unsigned long flags; + unsigned i; + + drv = kmalloc(sizeof *drv, GFP_KERNEL); + if (!drv) + return NULL; + if (!try_module_get(owner)) + return NULL; + + drv->cs = NULL; + drv->have_tty = 0; + drv->minor = minor; + drv->minors = minors; + spin_lock_init(&drv->lock); + drv->blocked = 0; + drv->ops = ops; + drv->owner = owner; + INIT_LIST_HEAD(&drv->list); + + drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL); + if (!drv->cs) + goto out1; + drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL); + if (!drv->flags) + goto out2; + + for (i = 0; i < minors; ++i) { + drv->flags[i] = 0; + drv->cs[i].driver = drv; + drv->cs[i].ops = drv->ops; + drv->cs[i].minor_index = i; + } + + gigaset_if_initdriver(drv, procname, devname, devfsname); + + spin_lock_irqsave(&driver_lock, flags); + list_add(&drv->list, &drivers); + spin_unlock_irqrestore(&driver_lock, flags); + + return drv; + +out2: + kfree(drv->cs); +out1: + kfree(drv); + module_put(owner); + return NULL; +} +EXPORT_SYMBOL_GPL(gigaset_initdriver); + +static struct cardstate *alloc_cs(struct gigaset_driver *drv) +{ + unsigned long flags; + unsigned i; + static struct cardstate *ret = NULL; + + spin_lock_irqsave(&drv->lock, flags); + for (i = 0; i < drv->minors; ++i) { + if (!(drv->flags[i] & VALID_MINOR)) { + drv->flags[i] = VALID_MINOR; + ret = drv->cs + i; + } + if (ret) + break; + } + spin_unlock_irqrestore(&drv->lock, flags); + return ret; +} + +static void free_cs(struct cardstate *cs) +{ + unsigned long flags; + struct gigaset_driver *drv = cs->driver; + spin_lock_irqsave(&drv->lock, flags); + drv->flags[cs->minor_index] = 0; + spin_unlock_irqrestore(&drv->lock, flags); +} + +static void make_valid(struct cardstate *cs, unsigned mask) +{ + unsigned long flags; + struct gigaset_driver *drv = cs->driver; + spin_lock_irqsave(&drv->lock, flags); + drv->flags[cs->minor_index] |= mask; + spin_unlock_irqrestore(&drv->lock, flags); +} + +static void make_invalid(struct cardstate *cs, unsigned mask) +{ + unsigned long flags; + struct gigaset_driver *drv = cs->driver; + spin_lock_irqsave(&drv->lock, flags); + drv->flags[cs->minor_index] &= ~mask; + spin_unlock_irqrestore(&drv->lock, flags); +} + +/* For drivers without fixed assignment device<->cardstate (usb) */ +struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv) +{ + unsigned long flags; + struct cardstate *cs = NULL; + unsigned i; + + spin_lock_irqsave(&drv->lock, flags); + if (drv->blocked) + goto exit; + for (i = 0; i < drv->minors; ++i) { + if ((drv->flags[i] & VALID_MINOR) && + !(drv->flags[i] & ASSIGNED)) { + drv->flags[i] |= ASSIGNED; + cs = drv->cs + i; + break; + } + } +exit: + spin_unlock_irqrestore(&drv->lock, flags); + return cs; +} +EXPORT_SYMBOL_GPL(gigaset_getunassignedcs); + +void gigaset_unassign(struct cardstate *cs) +{ + unsigned long flags; + unsigned *minor_flags; + struct gigaset_driver *drv; + + if (!cs) + return; + drv = cs->driver; + spin_lock_irqsave(&drv->lock, flags); + minor_flags = drv->flags + cs->minor_index; + if (*minor_flags & VALID_MINOR) + *minor_flags &= ~ASSIGNED; + spin_unlock_irqrestore(&drv->lock, flags); +} +EXPORT_SYMBOL_GPL(gigaset_unassign); + +void gigaset_blockdriver(struct gigaset_driver *drv) +{ + unsigned long flags; + spin_lock_irqsave(&drv->lock, flags); + drv->blocked = 1; + spin_unlock_irqrestore(&drv->lock, flags); +} +EXPORT_SYMBOL_GPL(gigaset_blockdriver); + +static int __init gigaset_init_module(void) +{ + /* in accordance with the principle of least astonishment, + * setting the 'debug' parameter to 1 activates a sensible + * set of default debug levels + */ + if (gigaset_debuglevel == 1) + gigaset_debuglevel = DEBUG_DEFAULT; + + info(DRIVER_AUTHOR); + info(DRIVER_DESC); + return 0; +} + +static void __exit gigaset_exit_module(void) +{ +} + +module_init(gigaset_init_module); +module_exit(gigaset_exit_module); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); + +MODULE_LICENSE("GPL"); diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h new file mode 100644 index 000000000000..729edcdb6dac --- /dev/null +++ b/drivers/isdn/gigaset/gigaset.h @@ -0,0 +1,938 @@ +/* Siemens Gigaset 307x driver + * Common header file for all connection variants + * + * Written by Stefan Eilers + * and Hansjoerg Lipp + * + * Version: $Id: gigaset.h,v 1.97.4.26 2006/02/04 18:28:16 hjlipp Exp $ + * =========================================================================== + */ + +#ifndef GIGASET_H +#define GIGASET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GIG_VERSION {0,5,0,0} +#define GIG_COMPAT {0,4,0,0} + +#define MAX_REC_PARAMS 10 /* Max. number of params in response string */ +#define MAX_RESP_SIZE 512 /* Max. size of a response string */ +#define HW_HDR_LEN 2 /* Header size used to store ack info */ + +#define MAX_EVENTS 64 /* size of event queue */ + +#define RBUFSIZE 8192 +#define SBUFSIZE 4096 /* sk_buff payload size */ + +#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */ +#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */ + +/* compile time options */ +#define GIG_MAJOR 0 + +#define GIG_MAYINITONDIAL +#define GIG_RETRYCID +#define GIG_X75 + +#define MAX_TIMER_INDEX 1000 +#define MAX_SEQ_INDEX 1000 + +#define GIG_TICK (HZ / 10) + +/* timeout values (unit: 1 sec) */ +#define INIT_TIMEOUT 1 + +/* timeout values (unit: 0.1 sec) */ +#define RING_TIMEOUT 3 /* for additional parameters to RING */ +#define BAS_TIMEOUT 20 /* for response to Base USB ops */ +#define ATRDY_TIMEOUT 3 /* for HD_READY_SEND_ATDATA */ + +#define BAS_RETRY 3 /* max. retries for base USB ops */ + +#define MAXACT 3 + +#define IFNULL(a) if (unlikely(!(a))) +#define IFNULLRET(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return; } +#define IFNULLRETVAL(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return (b); } +#define IFNULLCONT(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); continue; } +#define IFNULLGOTO(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); goto b; } + +extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */ + +/* any combination of these can be given with the 'debug=' parameter to insmod, e.g. + * 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and DEBUG_INTR. */ +enum debuglevel { /* up to 24 bits (atomic_t) */ + DEBUG_REG = 0x0002, /* serial port I/O register operations */ + DEBUG_OPEN = 0x0004, /* open/close serial port */ + DEBUG_INTR = 0x0008, /* interrupt processing */ + DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on interrupt + requests, not available as run-time option */ + DEBUG_CMD = 0x00020, /* sent/received LL commands */ + DEBUG_STREAM = 0x00040, /* application data stream I/O events */ + DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ + DEBUG_LLDATA = 0x00100, /* sent/received LL data */ + DEBUG_INTR_0 = 0x00200, /* serial port output interrupt processing */ + DEBUG_DRIVER = 0x00400, /* driver structure */ + DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ + DEBUG_WRITE = 0x01000, /* M105 data write */ + DEBUG_TRANSCMD = 0x02000, /*AT-COMMANDS+RESPONSES*/ + DEBUG_MCMD = 0x04000, /*COMMANDS THAT ARE SENT VERY OFTEN*/ + DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data structures */ + DEBUG_LOCK = 0x10000, /* semaphore operations */ + DEBUG_OUTPUT = 0x20000, /* output to device */ + DEBUG_ISO = 0x40000, /* isochronous transfers */ + DEBUG_IF = 0x80000, /* character device operations */ + DEBUG_USBREQ = 0x100000, /* USB communication (except payload data) */ + DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when MS_LOCKED */ + + DEBUG_ANY = 0x3fffff, /* print message if any of the others is activated */ +}; + +#ifdef CONFIG_GIGASET_DEBUG +#define DEBUG_DEFAULT (DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ) +//#define DEBUG_DEFAULT (DEBUG_LOCK | DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUF_IF | DEBUG_DRIVER | DEBUG_OUTPUT | DEBUG_INTR) +#else +#define DEBUG_DEFAULT 0 +#endif + +/* redefine syslog macros to prepend module name instead of entire source path */ +/* The space before the comma in ", ##" is needed by gcc 2.95 */ +#undef info +#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) + +#undef notice +#define notice(format, arg...) printk(KERN_NOTICE "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) + +#undef warn +#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) + +#undef err +#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) + +#undef dbg +#ifdef CONFIG_GIGASET_DEBUG +#define dbg(level, format, arg...) do { if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \ + printk(KERN_DEBUG "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg); } while (0) +#else +#define dbg(level, format, arg...) do {} while (0) +#endif + +void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, + size_t len, const unsigned char *buf, int from_user); + +/* connection state */ +#define ZSAU_NONE 0 +#define ZSAU_DISCONNECT_IND 4 +#define ZSAU_OUTGOING_CALL_PROCEEDING 1 +#define ZSAU_PROCEEDING 1 +#define ZSAU_CALL_DELIVERED 2 +#define ZSAU_ACTIVE 3 +#define ZSAU_NULL 5 +#define ZSAU_DISCONNECT_REQ 6 +#define ZSAU_UNKNOWN -1 + +/* USB control transfer requests */ +#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) +#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) + +/* int-in-events 3070 */ +#define HD_B1_FLOW_CONTROL 0x80 +#define HD_B2_FLOW_CONTROL 0x81 +#define HD_RECEIVEATDATA_ACK (0x35) // 3070 // att: HD_RECEIVE>>AT< ignore */ + int max_ConState; /* <0 => ignore */ + int parameter; /* e.g. ZSAU_XXXX <0: ignore*/ + int new_ConState; /* <0 => ignore */ + int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/ + int action[MAXACT]; /* ACT_XXXX */ + char *command; /* NULL==none */ +}; + +extern struct reply_t gigaset_tab_cid_m10x[]; +extern struct reply_t gigaset_tab_nocid_m10x[]; + +struct inbuf_t { + unsigned char *rcvbuf; /* usb-gigaset receive buffer */ + struct bc_state *bcs; + struct cardstate *cs; + int inputstate; + + atomic_t head, tail; + unsigned char data[RBUFSIZE]; +}; + +/* isochronous write buffer structure + * circular buffer with pad area for extraction of complete USB frames + * - data[read..nextread-1] is valid data already submitted to the USB subsystem + * - data[nextread..write-1] is valid data yet to be sent + * - data[write] is the next byte to write to + * - in byte-oriented L2 procotols, it is completely free + * - in bit-oriented L2 procotols, it may contain a partial byte of valid data + * - data[write+1..read-1] is free + * - wbits is the number of valid data bits in data[write], starting at the LSB + * - writesem is the semaphore for writing to the buffer: + * if writesem <= 0, data[write..read-1] is currently being written to + * - idle contains the byte value to repeat when the end of valid data is + * reached; if nextread==write (buffer contains no data to send), either the + * BAS_OUTBUFPAD bytes immediately before data[write] (if write>=BAS_OUTBUFPAD) + * or those of the pad area (if write for modem reponses (and incomming data for M10x) + * -> on timeout + * -> after setting bits in xxx.at_state.pending_command + * (e.g. command from LL) */ + struct tasklet_struct write_tasklet; /* tasklet for serial output + * (not used in base driver) */ + + /* event queue */ + struct event_t events[MAX_EVENTS]; + atomic_t ev_tail, ev_head; + spinlock_t ev_lock; + + /* current modem response */ + unsigned char respdata[MAX_RESP_SIZE]; + unsigned cbytes; + + /* hardware drivers */ + union { + struct usb_cardstate *usb; /* private data of USB hardware driver */ + struct ser_cardstate *ser; /* private data of serial hardware driver */ + struct bas_cardstate *bas; /* private data of base hardware driver */ + } hw; +}; + +struct gigaset_driver { + struct list_head list; + spinlock_t lock; /* locks minor tables and blocked */ + //struct semaphore sem; /* locks this structure */ + struct tty_driver *tty; + unsigned have_tty; + unsigned minor; + unsigned minors; + struct cardstate *cs; + unsigned *flags; + int blocked; + + const struct gigaset_ops *ops; + struct module *owner; +}; + +struct cmdbuf_t { + struct cmdbuf_t *next, *prev; + int len, offset; + struct tasklet_struct *wake_tasklet; + unsigned char buf[0]; +}; + +struct bas_bc_state { + /* isochronous output state */ + atomic_t running; + atomic_t corrbytes; + spinlock_t isooutlock; + struct isow_urbctx_t isoouturbs[BAS_OUTURBS]; + struct isow_urbctx_t *isooutdone, *isooutfree, *isooutovfl; + struct isowbuf_t *isooutbuf; + unsigned numsub; /* submitted URB counter (for diagnostic messages only) */ + struct tasklet_struct sent_tasklet; + + /* isochronous input state */ + spinlock_t isoinlock; + struct urb *isoinurbs[BAS_INURBS]; + unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS]; + struct urb *isoindone; /* completed isoc read URB */ + int loststatus; /* status of dropped URB */ + unsigned isoinlost; /* number of bytes lost */ + /* state of bit unstuffing algorithm (in addition to BC_state.inputstate) */ + unsigned seqlen; /* number of '1' bits not yet unstuffed */ + unsigned inbyte, inbits; /* collected bits for next byte */ + /* statistics */ + unsigned goodbytes; /* bytes correctly received */ + unsigned alignerrs; /* frames with incomplete byte at end */ + unsigned fcserrs; /* FCS errors */ + unsigned frameerrs; /* framing errors */ + unsigned giants; /* long frames */ + unsigned runts; /* short frames */ + unsigned aborts; /* HDLC aborts */ + unsigned shared0s; /* '0' bits shared between flags */ + unsigned stolen0s; /* '0' stuff bits also serving as leading flag bits */ + struct tasklet_struct rcvd_tasklet; +}; + +struct gigaset_ops { + /* Called from ev-layer.c/interface.c for sending AT commands to the device */ + int (*write_cmd)(struct cardstate *cs, + const unsigned char *buf, int len, + struct tasklet_struct *wake_tasklet); + + /* Called from interface.c for additional device control */ + int (*write_room)(struct cardstate *cs); + int (*chars_in_buffer)(struct cardstate *cs); + int (*brkchars)(struct cardstate *cs, const unsigned char buf[6]); + + /* Called from ev-layer.c after setting up connection + * Should call gigaset_bchannel_up(), when finished. */ + int (*init_bchannel)(struct bc_state *bcs); + + /* Called from ev-layer.c after hanging up + * Should call gigaset_bchannel_down(), when finished. */ + int (*close_bchannel)(struct bc_state *bcs); + + /* Called by gigaset_initcs() for setting up bcs->hw.xxx */ + int (*initbcshw)(struct bc_state *bcs); + + /* Called by gigaset_freecs() for freeing bcs->hw.xxx */ + int (*freebcshw)(struct bc_state *bcs); + + /* Called by gigaset_stop() or gigaset_bchannel_down() for resetting bcs->hw.xxx */ + void (*reinitbcshw)(struct bc_state *bcs); + + /* Called by gigaset_initcs() for setting up cs->hw.xxx */ + int (*initcshw)(struct cardstate *cs); + + /* Called by gigaset_freecs() for freeing cs->hw.xxx */ + void (*freecshw)(struct cardstate *cs); + + ///* Called by gigaset_stop() for killing URBs, shutting down the device, ... + // hardwareup: ==0: don't try to shut down the device, hardware is really not accessible + // !=0: hardware still up */ + //void (*stophw)(struct cardstate *cs, int hardwareup); + + /* Called from common.c/interface.c for additional serial port control */ + int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state, unsigned new_state); + int (*baud_rate)(struct cardstate *cs, unsigned cflag); + int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag); + + /* Called from i4l.c to put an skb into the send-queue. */ + int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb); + + /* Called from ev-layer.c to process a block of data + * received through the common/control channel. */ + void (*handle_input)(struct inbuf_t *inbuf); + +}; + +/* = Common structures and definitions ======================================= */ + +/* Parser states for DLE-Event: + * : "X" "." + * : 0x10 + * : ((a-z)* | (A-Z)* | (0-10)*)+ + */ +#define DLE_FLAG 0x10 + +/* =========================================================================== + * Functions implemented in asyncdata.c + */ + +/* Called from i4l.c to put an skb into the send-queue. + * After sending gigaset_skb_sent() should be called. */ +int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb); + +/* Called from ev-layer.c to process a block of data + * received through the common/control channel. */ +void gigaset_m10x_input(struct inbuf_t *inbuf); + +/* =========================================================================== + * Functions implemented in isocdata.c + */ + +/* Called from i4l.c to put an skb into the send-queue. + * After sending gigaset_skb_sent() should be called. */ +int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb); + +/* Called from ev-layer.c to process a block of data + * received through the common/control channel. */ +void gigaset_isoc_input(struct inbuf_t *inbuf); + +/* Called from bas-gigaset.c to process a block of data + * received through the isochronous channel */ +void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs); + +/* Called from bas-gigaset.c to put a block of data + * into the isochronous output buffer */ +int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len); + +/* Called from bas-gigaset.c to initialize the isochronous output buffer */ +void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle); + +/* Called from bas-gigaset.c to retrieve a block of bytes for sending */ +int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size); + +/* =========================================================================== + * Functions implemented in i4l.c/gigaset.h + */ + +/* Called by gigaset_initcs() for setting up with the isdn4linux subsystem */ +int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid); + +/* Called from xxx-gigaset.c to indicate completion of sending an skb */ +void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); + +/* Called from common.c/ev-layer.c to indicate events relevant to the LL */ +int gigaset_isdn_icall(struct at_state_t *at_state); +int gigaset_isdn_setup_accept(struct at_state_t *at_state); +int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data); + +void gigaset_i4l_cmd(struct cardstate *cs, int cmd); +void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd); + + +static inline void gigaset_isdn_rcv_err(struct bc_state *bcs) +{ + isdn_ctrl response; + + /* error -> LL */ + dbg(DEBUG_CMD, "sending L1ERR"); + response.driver = bcs->cs->myid; + response.command = ISDN_STAT_L1ERR; + response.arg = bcs->channel; + response.parm.errcode = ISDN_STAT_L1ERR_RECV; + bcs->cs->iif.statcallb(&response); +} + +/* =========================================================================== + * Functions implemented in ev-layer.c + */ + +/* tasklet called from common.c to process queued events */ +void gigaset_handle_event(unsigned long data); + +/* called from isocdata.c / asyncdata.c + * when a complete modem response line has been received */ +void gigaset_handle_modem_response(struct cardstate *cs); + +/* =========================================================================== + * Functions implemented in proc.c + */ + +/* initialize sysfs for device */ +void gigaset_init_dev_sysfs(struct usb_interface *interface); +void gigaset_free_dev_sysfs(struct usb_interface *interface); + +/* =========================================================================== + * Functions implemented in common.c/gigaset.h + */ + +void gigaset_bcs_reinit(struct bc_state *bcs); +void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, + struct cardstate *cs, int cid); +int gigaset_get_channel(struct bc_state *bcs); +void gigaset_free_channel(struct bc_state *bcs); +int gigaset_get_channels(struct cardstate *cs); +void gigaset_free_channels(struct cardstate *cs); +void gigaset_block_channels(struct cardstate *cs); + +/* Allocate and initialize driver structure. */ +struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, + const char *procname, + const char *devname, + const char *devfsname, + const struct gigaset_ops *ops, + struct module *owner); + +/* Deallocate driver structure. */ +void gigaset_freedriver(struct gigaset_driver *drv); +void gigaset_debugdrivers(void); +struct cardstate *gigaset_get_cs_by_minor(unsigned minor); +struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty); +struct cardstate *gigaset_get_cs_by_id(int id); + +/* For drivers without fixed assignment device<->cardstate (usb) */ +struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv); +void gigaset_unassign(struct cardstate *cs); +void gigaset_blockdriver(struct gigaset_driver *drv); + +/* Allocate and initialize card state. Calls hardware dependent gigaset_init[b]cs(). */ +struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, + int onechannel, int ignoreframes, + int cidmode, const char *modulename); + +/* Free card state. Calls hardware dependent gigaset_free[b]cs(). */ +void gigaset_freecs(struct cardstate *cs); + +/* Tell common.c that hardware and driver are ready. */ +int gigaset_start(struct cardstate *cs); + +/* Tell common.c that the device is not present any more. */ +void gigaset_stop(struct cardstate *cs); + +/* Tell common.c that the driver is being unloaded. */ +void gigaset_shutdown(struct cardstate *cs); + +/* Tell common.c that an skb has been sent. */ +void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); + +/* Append event to the queue. + * Returns NULL on failure or a pointer to the event on success. + * ptr must be kmalloc()ed (and not be freed by the caller). + */ +struct event_t *gigaset_add_event(struct cardstate *cs, + struct at_state_t *at_state, int type, + void *ptr, int parameter, void *arg); + +/* Called on CONFIG1 command from frontend. */ +int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode + +/* cs->lock must not be locked */ +static inline void gigaset_schedule_event(struct cardstate *cs) +{ + unsigned long flags; + spin_lock_irqsave(&cs->lock, flags); + if (atomic_read(&cs->running)) + tasklet_schedule(&cs->event_tasklet); + spin_unlock_irqrestore(&cs->lock, flags); +} + +/* Tell common.c that B channel has been closed. */ +/* cs->lock must not be locked */ +static inline void gigaset_bchannel_down(struct bc_state *bcs) +{ + gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL); + + dbg(DEBUG_CMD, "scheduling BC_CLOSED"); + gigaset_schedule_event(bcs->cs); +} + +/* Tell common.c that B channel has been opened. */ +/* cs->lock must not be locked */ +static inline void gigaset_bchannel_up(struct bc_state *bcs) +{ + gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL); + + dbg(DEBUG_CMD, "scheduling BC_OPEN"); + gigaset_schedule_event(bcs->cs); +} + +/* handling routines for sk_buff */ +/* ============================= */ + +/* private version of __skb_put() + * append 'len' bytes to the content of 'skb', already knowing that the + * existing buffer can accomodate them + * returns a pointer to the location where the new bytes should be copied to + * This function does not take any locks so it must be called with the + * appropriate locks held only. + */ +static inline unsigned char *gigaset_skb_put_quick(struct sk_buff *skb, + unsigned int len) +{ + unsigned char *tmp = skb->tail; + /*SKB_LINEAR_ASSERT(skb);*/ /* not needed here */ + skb->tail += len; + skb->len += len; + return tmp; +} + +/* pass received skb to LL + * Warning: skb must not be accessed anymore! + */ +static inline void gigaset_rcv_skb(struct sk_buff *skb, + struct cardstate *cs, + struct bc_state *bcs) +{ + cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb); + bcs->trans_down++; +} + +/* handle reception of corrupted skb + * Warning: skb must not be accessed anymore! + */ +static inline void gigaset_rcv_error(struct sk_buff *procskb, + struct cardstate *cs, + struct bc_state *bcs) +{ + if (procskb) + dev_kfree_skb(procskb); + + if (bcs->ignore) + --bcs->ignore; + else { + ++bcs->corrupted; + gigaset_isdn_rcv_err(bcs); + } +} + + +/* bitwise byte inversion table */ +extern __u8 gigaset_invtab[]; /* in common.c */ + + +/* append received bytes to inbuf */ +static inline int gigaset_fill_inbuf(struct inbuf_t *inbuf, + const unsigned char *src, + unsigned numbytes) +{ + unsigned n, head, tail, bytesleft; + + dbg(DEBUG_INTR, "received %u bytes", numbytes); + + if (!numbytes) + return 0; + + bytesleft = numbytes; + tail = atomic_read(&inbuf->tail); + head = atomic_read(&inbuf->head); + dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); + + while (bytesleft) { + if (head > tail) + n = head - 1 - tail; + else if (head == 0) + n = (RBUFSIZE-1) - tail; + else + n = RBUFSIZE - tail; + if (!n) { + err("buffer overflow (%u bytes lost)", bytesleft); + break; + } + if (n > bytesleft) + n = bytesleft; + memcpy(inbuf->data + tail, src, n); + bytesleft -= n; + tail = (tail + n) % RBUFSIZE; + src += n; + } + dbg(DEBUG_INTR, "setting tail to %u", tail); + atomic_set(&inbuf->tail, tail); + return numbytes != bytesleft; +} + +/* =========================================================================== + * Functions implemented in interface.c + */ + +/* initialize interface */ +void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, + const char *devname, const char *devfsname); +/* release interface */ +void gigaset_if_freedriver(struct gigaset_driver *drv); +/* add minor */ +void gigaset_if_init(struct cardstate *cs); +/* remove minor */ +void gigaset_if_free(struct cardstate *cs); +/* device received data */ +void gigaset_if_receive(struct cardstate *cs, + unsigned char *buffer, size_t len); + +#endif -- cgit v1.2.3-59-g8ed1b From 14fa73a75df6a0ffe866f750e8dcd218d0171f51 Mon Sep 17 00:00:00 2001 From: Hansjoerg Lipp Date: Sun, 26 Mar 2006 01:38:30 -0800 Subject: [PATCH] isdn4linux: Siemens Gigaset drivers - event layer And: Tilman Schmidt This patch adds the event layer to the gigaset module. The event layer serializes events from hardware, userspace, and other kernel subsystems. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Cc: Karsten Keil Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/gigaset/ev-layer.c | 1983 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1983 insertions(+) create mode 100644 drivers/isdn/gigaset/ev-layer.c (limited to 'drivers') diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c new file mode 100644 index 000000000000..fdcb80bb21c7 --- /dev/null +++ b/drivers/isdn/gigaset/ev-layer.c @@ -0,0 +1,1983 @@ +/* + * Stuff used by all variants of the driver + * + * Copyright (c) 2001 by Stefan Eilers , + * Hansjoerg Lipp , + * Tilman Schmidt . + * + * ===================================================================== + * 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. + * ===================================================================== + * ToDo: ... + * ===================================================================== + * Version: $Id: ev-layer.c,v 1.4.2.18 2006/02/04 18:28:16 hjlipp Exp $ + * ===================================================================== + */ + +#include "gigaset.h" + +/* ========================================================== */ +/* bit masks for pending commands */ +#define PC_INIT 0x004 +#define PC_DLE0 0x008 +#define PC_DLE1 0x010 +#define PC_CID 0x080 +#define PC_NOCID 0x100 +#define PC_HUP 0x002 +#define PC_DIAL 0x001 +#define PC_ACCEPT 0x040 +#define PC_SHUTDOWN 0x020 +#define PC_CIDMODE 0x200 +#define PC_UMMODE 0x400 + +/* types of modem responses */ +#define RT_NOTHING 0 +#define RT_ZSAU 1 +#define RT_RING 2 +#define RT_NUMBER 3 +#define RT_STRING 4 +#define RT_HEX 5 +#define RT_ZCAU 6 + +/* Possible ASCII responses */ +#define RSP_OK 0 +//#define RSP_BUSY 1 +//#define RSP_CONNECT 2 +#define RSP_ZGCI 3 +#define RSP_RING 4 +#define RSP_ZAOC 5 +#define RSP_ZCSTR 6 +#define RSP_ZCFGT 7 +#define RSP_ZCFG 8 +#define RSP_ZCCR 9 +#define RSP_EMPTY 10 +#define RSP_ZLOG 11 +#define RSP_ZCAU 12 +#define RSP_ZMWI 13 +#define RSP_ZABINFO 14 +#define RSP_ZSMLSTCHG 15 +#define RSP_VAR 100 +#define RSP_ZSAU (RSP_VAR + VAR_ZSAU) +#define RSP_ZDLE (RSP_VAR + VAR_ZDLE) +#define RSP_ZVLS (RSP_VAR + VAR_ZVLS) +#define RSP_ZCTP (RSP_VAR + VAR_ZCTP) +#define RSP_STR (RSP_VAR + VAR_NUM) +#define RSP_NMBR (RSP_STR + STR_NMBR) +#define RSP_ZCPN (RSP_STR + STR_ZCPN) +#define RSP_ZCON (RSP_STR + STR_ZCON) +#define RSP_ZBC (RSP_STR + STR_ZBC) +#define RSP_ZHLC (RSP_STR + STR_ZHLC) +#define RSP_ERROR -1 /* ERROR */ +#define RSP_WRONG_CID -2 /* unknown cid in cmd */ +//#define RSP_EMPTY -3 +#define RSP_UNKNOWN -4 /* unknown response */ +#define RSP_FAIL -5 /* internal error */ +#define RSP_INVAL -6 /* invalid response */ + +#define RSP_NONE -19 +#define RSP_STRING -20 +#define RSP_NULL -21 +//#define RSP_RETRYFAIL -22 +//#define RSP_RETRY -23 +//#define RSP_SKIP -24 +#define RSP_INIT -27 +#define RSP_ANY -26 +#define RSP_LAST -28 +#define RSP_NODEV -9 + +/* actions for process_response */ +#define ACT_NOTHING 0 +#define ACT_SETDLE1 1 +#define ACT_SETDLE0 2 +#define ACT_FAILINIT 3 +#define ACT_HUPMODEM 4 +#define ACT_CONFIGMODE 5 +#define ACT_INIT 6 +#define ACT_DLE0 7 +#define ACT_DLE1 8 +#define ACT_FAILDLE0 9 +#define ACT_FAILDLE1 10 +#define ACT_RING 11 +#define ACT_CID 12 +#define ACT_FAILCID 13 +#define ACT_SDOWN 14 +#define ACT_FAILSDOWN 15 +#define ACT_DEBUG 16 +#define ACT_WARN 17 +#define ACT_DIALING 18 +#define ACT_ABORTDIAL 19 +#define ACT_DISCONNECT 20 +#define ACT_CONNECT 21 +#define ACT_REMOTEREJECT 22 +#define ACT_CONNTIMEOUT 23 +#define ACT_REMOTEHUP 24 +#define ACT_ABORTHUP 25 +#define ACT_ICALL 26 +#define ACT_ACCEPTED 27 +#define ACT_ABORTACCEPT 28 +#define ACT_TIMEOUT 29 +#define ACT_GETSTRING 30 +#define ACT_SETVER 31 +#define ACT_FAILVER 32 +#define ACT_GOTVER 33 +#define ACT_TEST 34 +#define ACT_ERROR 35 +#define ACT_ABORTCID 36 +#define ACT_ZCAU 37 +#define ACT_NOTIFY_BC_DOWN 38 +#define ACT_NOTIFY_BC_UP 39 +#define ACT_DIAL 40 +#define ACT_ACCEPT 41 +#define ACT_PROTO_L2 42 +#define ACT_HUP 43 +#define ACT_IF_LOCK 44 +#define ACT_START 45 +#define ACT_STOP 46 +#define ACT_FAKEDLE0 47 +#define ACT_FAKEHUP 48 +#define ACT_FAKESDOWN 49 +#define ACT_SHUTDOWN 50 +#define ACT_PROC_CIDMODE 51 +#define ACT_UMODESET 52 +#define ACT_FAILUMODE 53 +#define ACT_CMODESET 54 +#define ACT_FAILCMODE 55 +#define ACT_IF_VER 56 +#define ACT_CMD 100 + +/* at command sequences */ +#define SEQ_NONE 0 +#define SEQ_INIT 100 +#define SEQ_DLE0 200 +#define SEQ_DLE1 250 +#define SEQ_CID 300 +#define SEQ_NOCID 350 +#define SEQ_HUP 400 +#define SEQ_DIAL 600 +#define SEQ_ACCEPT 720 +#define SEQ_SHUTDOWN 500 +#define SEQ_CIDMODE 10 +#define SEQ_UMMODE 11 + + +// 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring +struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */ +{ + /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ + + /* initialize device, set cid mode if possible */ + //{RSP_INIT, -1, -1,100, 900, 0, {ACT_TEST}}, + //{RSP_ERROR, 900,900, -1, 0, 0, {ACT_FAILINIT}}, + //{RSP_OK, 900,900, -1, 100, INIT_TIMEOUT, + // {ACT_TIMEOUT}}, + + {RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT, + {ACT_TIMEOUT}}, /* wait until device is ready */ + + {EV_TIMEOUT, 100,100, -1, 101, 3, {0}, "Z\r"}, /* device in transparent mode? try to initialize it. */ + {RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */ + + {EV_TIMEOUT, 101,101, -1, 102, 5, {0}, "Z\r"}, /* timeout => try once again. */ + {RSP_ERROR, 101,101, -1, 102, 5, {0}, "Z\r"}, /* error => try once again. */ + + {EV_TIMEOUT, 102,102, -1, 108, 5, {ACT_SETDLE1}, "^SDLE=0\r"}, /* timeout => try again in DLE mode. */ + {RSP_OK, 108,108, -1, 104,-1}, + {RSP_ZDLE, 104,104, 0, 103, 5, {0}, "Z\r"}, + {EV_TIMEOUT, 104,104, -1, 0, 0, {ACT_FAILINIT}}, + {RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}}, + + {EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0, + ACT_HUPMODEM, + ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */ + {EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"}, + + {RSP_ERROR, 102,102, -1, 107, 5, {0}, "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */ + {RSP_OK, 107,107, -1, 0, 0, {ACT_CONFIGMODE}}, + {RSP_ERROR, 107,107, -1, 0, 0, {ACT_FAILINIT}}, + {EV_TIMEOUT, 107,107, -1, 0, 0, {ACT_FAILINIT}}, + + {RSP_ERROR, 103,103, -1, 0, 0, {ACT_FAILINIT}}, + {EV_TIMEOUT, 103,103, -1, 0, 0, {ACT_FAILINIT}}, + + {RSP_STRING, 120,120, -1, 121,-1, {ACT_SETVER}}, + + {EV_TIMEOUT, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}}, + {RSP_ERROR, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}}, + {RSP_OK, 121,121, -1, 0, 0, {ACT_GOTVER, ACT_INIT}}, +#if 0 + {EV_TIMEOUT, 120,121, -1, 130, 5, {ACT_FAILVER}, "^SGCI=1\r"}, + {RSP_ERROR, 120,121, -1, 130, 5, {ACT_FAILVER}, "^SGCI=1\r"}, + {RSP_OK, 121,121, -1, 130, 5, {ACT_GOTVER}, "^SGCI=1\r"}, + + {RSP_OK, 130,130, -1, 0, 0, {ACT_INIT}}, + {RSP_ERROR, 130,130, -1, 0, 0, {ACT_FAILINIT}}, + {EV_TIMEOUT, 130,130, -1, 0, 0, {ACT_FAILINIT}}, +#endif + + /* leave dle mode */ + {RSP_INIT, 0, 0,SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, + {RSP_OK, 201,201, -1, 202,-1}, + //{RSP_ZDLE, 202,202, 0, 202, 0, {ACT_ERROR}},//DELETE + {RSP_ZDLE, 202,202, 0, 0, 0, {ACT_DLE0}}, + {RSP_NODEV, 200,249, -1, 0, 0, {ACT_FAKEDLE0}}, + {RSP_ERROR, 200,249, -1, 0, 0, {ACT_FAILDLE0}}, + {EV_TIMEOUT, 200,249, -1, 0, 0, {ACT_FAILDLE0}}, + + /* enter dle mode */ + {RSP_INIT, 0, 0,SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"}, + {RSP_OK, 251,251, -1, 252,-1}, + {RSP_ZDLE, 252,252, 1, 0, 0, {ACT_DLE1}}, + {RSP_ERROR, 250,299, -1, 0, 0, {ACT_FAILDLE1}}, + {EV_TIMEOUT, 250,299, -1, 0, 0, {ACT_FAILDLE1}}, + + /* incoming call */ + {RSP_RING, -1, -1, -1, -1,-1, {ACT_RING}}, + + /* get cid */ + //{RSP_INIT, 0, 0,300, 901, 0, {ACT_TEST}}, + //{RSP_ERROR, 901,901, -1, 0, 0, {ACT_FAILCID}}, + //{RSP_OK, 901,901, -1, 301, 5, {0}, "^SGCI?\r"}, + + {RSP_INIT, 0, 0,SEQ_CID, 301, 5, {0}, "^SGCI?\r"}, + {RSP_OK, 301,301, -1, 302,-1}, + {RSP_ZGCI, 302,302, -1, 0, 0, {ACT_CID}}, + {RSP_ERROR, 301,349, -1, 0, 0, {ACT_FAILCID}}, + {EV_TIMEOUT, 301,349, -1, 0, 0, {ACT_FAILCID}}, + + /* enter cid mode */ + {RSP_INIT, 0, 0,SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"}, + {RSP_OK, 150,150, -1, 0, 0, {ACT_CMODESET}}, + {RSP_ERROR, 150,150, -1, 0, 0, {ACT_FAILCMODE}}, + {EV_TIMEOUT, 150,150, -1, 0, 0, {ACT_FAILCMODE}}, + + /* leave cid mode */ + //{RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "^SGCI=0\r"}, + {RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "Z\r"}, + {RSP_OK, 160,160, -1, 0, 0, {ACT_UMODESET}}, + {RSP_ERROR, 160,160, -1, 0, 0, {ACT_FAILUMODE}}, + {EV_TIMEOUT, 160,160, -1, 0, 0, {ACT_FAILUMODE}}, + + /* abort getting cid */ + {RSP_INIT, 0, 0,SEQ_NOCID, 0, 0, {ACT_ABORTCID}}, + + /* reset */ +#if 0 + {RSP_INIT, 0, 0,SEQ_SHUTDOWN, 503, 5, {0}, "^SGCI=0\r"}, + {RSP_OK, 503,503, -1, 504, 5, {0}, "Z\r"}, +#endif + {RSP_INIT, 0, 0,SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"}, + {RSP_OK, 504,504, -1, 0, 0, {ACT_SDOWN}}, + {RSP_ERROR, 501,599, -1, 0, 0, {ACT_FAILSDOWN}}, + {EV_TIMEOUT, 501,599, -1, 0, 0, {ACT_FAILSDOWN}}, + {RSP_NODEV, 501,599, -1, 0, 0, {ACT_FAKESDOWN}}, + + {EV_PROC_CIDMODE,-1, -1, -1, -1,-1, {ACT_PROC_CIDMODE}}, //FIXME + {EV_IF_LOCK, -1, -1, -1, -1,-1, {ACT_IF_LOCK}}, //FIXME + {EV_IF_VER, -1, -1, -1, -1,-1, {ACT_IF_VER}}, //FIXME + {EV_START, -1, -1, -1, -1,-1, {ACT_START}}, //FIXME + {EV_STOP, -1, -1, -1, -1,-1, {ACT_STOP}}, //FIXME + {EV_SHUTDOWN, -1, -1, -1, -1,-1, {ACT_SHUTDOWN}}, //FIXME + + /* misc. */ + {RSP_EMPTY, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME + {RSP_ZCFGT, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME + {RSP_ZCFG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME + {RSP_ZLOG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME + {RSP_ZMWI, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME + {RSP_ZABINFO, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME + {RSP_ZSMLSTCHG,-1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME + + {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}}, + {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}}, + {RSP_LAST} +}; + +// 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, 400: hup, 750: accepted icall +struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */ +{ + /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ + + /* dial */ + {EV_DIAL, -1, -1, -1, -1,-1, {ACT_DIAL}}, //FIXME + {RSP_INIT, 0, 0,SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC}}, + {RSP_OK, 601,601, -1, 602, 5, {ACT_CMD+AT_HLC}}, + {RSP_NULL, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, + {RSP_OK, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, + {RSP_OK, 603,603, -1, 604, 5, {ACT_CMD+AT_TYPE}}, + {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, + {RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, + {RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, + {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */ + {RSP_OK, 607,607, -1, 608,-1}, + //{RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 608, 0, {ACT_ERROR}},//DELETE + {RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}}, + {RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}}, + + {RSP_ZVLS, 608,608, 17, -1,-1, {ACT_DEBUG}}, + {RSP_ZCTP, 609,609, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ZCPN, 609,609, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, + {EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, + + /* dialing */ + {RSP_ZCTP, 650,650, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ZCPN, 650,650, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ZSAU, 650,650,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, /* some devices don't send this */ + + /* connection established */ + {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1 + {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1 + + {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, //FIXME new constate + timeout + + /* remote hangup */ + {RSP_ZSAU, 650,650,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, + {RSP_ZSAU, 750,750,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, + {RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, + + /* hangup */ + {EV_HUP, -1, -1, -1, -1,-1, {ACT_HUP}}, //FIXME + {RSP_INIT, -1, -1,SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, /* hang up */ //-1,-1? + {RSP_OK, 401,401, -1, 402, 5}, + {RSP_ZVLS, 402,402, 0, 403, 5}, + {RSP_ZSAU, 403,403,ZSAU_DISCONNECT_REQ, -1,-1, {ACT_DEBUG}}, /* if not remote hup */ + //{RSP_ZSAU, 403,403,ZSAU_NULL, 401, 0, {ACT_ERROR}}, //DELETE//FIXME -> DLE0 // should we do this _before_ hanging up for base driver? + {RSP_ZSAU, 403,403,ZSAU_NULL, 0, 0, {ACT_DISCONNECT}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver? + {RSP_NODEV, 401,403, -1, 0, 0, {ACT_FAKEHUP}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver? + {RSP_ERROR, 401,401, -1, 0, 0, {ACT_ABORTHUP}}, + {EV_TIMEOUT, 401,403, -1, 0, 0, {ACT_ABORTHUP}}, + + {EV_BC_CLOSED, 0, 0, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME new constate + timeout + + /* ring */ + {RSP_ZBC, 700,700, -1, -1,-1, {0}}, + {RSP_ZHLC, 700,700, -1, -1,-1, {0}}, + {RSP_NMBR, 700,700, -1, -1,-1, {0}}, + {RSP_ZCPN, 700,700, -1, -1,-1, {0}}, + {RSP_ZCTP, 700,700, -1, -1,-1, {0}}, + {EV_TIMEOUT, 700,700, -1, 720,720, {ACT_ICALL}}, + {EV_BC_CLOSED,720,720, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, + + /*accept icall*/ + {EV_ACCEPT, -1, -1, -1, -1,-1, {ACT_ACCEPT}}, //FIXME + {RSP_INIT, 720,720,SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO}}, + {RSP_OK, 721,721, -1, 722, 5, {ACT_CMD+AT_ISO}}, + {RSP_OK, 722,722, -1, 723, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */ + {RSP_OK, 723,723, -1, 724, 5, {0}}, + {RSP_ZVLS, 724,724, 17, 750,50, {ACT_ACCEPTED}}, + {RSP_ERROR, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}}, + {EV_TIMEOUT, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}}, + {RSP_ZSAU, 700,729,ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT}}, + {RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}}, + {RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}}, + + {EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}}, + + /* misc. */ + {EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME + + {RSP_ZCON, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME + {RSP_ZCCR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME + {RSP_ZAOC, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME + {RSP_ZCSTR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME + + {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}}, + {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}}, + {RSP_LAST} +}; + + +#if 0 +static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME aenderungen uebernehmen +{ + /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ + + {RSP_ANY, -1, -1, -1, -1,-1, ACT_WARN, NULL}, + {RSP_LAST,0,0,0,0,0,0} +}; + +static struct reply_t tab_cid[] = /* no dle mode */ //FIXME aenderungen uebernehmen +{ + /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ + + {RSP_ANY, -1, -1, -1, -1,-1, ACT_WARN, NULL}, + {RSP_LAST,0,0,0,0,0,0} +}; +#endif + +static struct resp_type_t resp_type[]= +{ + /*{"", RSP_EMPTY, RT_NOTHING},*/ + {"OK", RSP_OK, RT_NOTHING}, + {"ERROR", RSP_ERROR, RT_NOTHING}, + {"ZSAU", RSP_ZSAU, RT_ZSAU}, + {"ZCAU", RSP_ZCAU, RT_ZCAU}, + {"RING", RSP_RING, RT_RING}, + {"ZGCI", RSP_ZGCI, RT_NUMBER}, + {"ZVLS", RSP_ZVLS, RT_NUMBER}, + {"ZCTP", RSP_ZCTP, RT_NUMBER}, + {"ZDLE", RSP_ZDLE, RT_NUMBER}, + {"ZCFGT", RSP_ZCFGT, RT_NUMBER}, + {"ZCCR", RSP_ZCCR, RT_NUMBER}, + {"ZMWI", RSP_ZMWI, RT_NUMBER}, + {"ZHLC", RSP_ZHLC, RT_STRING}, + {"ZBC", RSP_ZBC, RT_STRING}, + {"NMBR", RSP_NMBR, RT_STRING}, + {"ZCPN", RSP_ZCPN, RT_STRING}, + {"ZCON", RSP_ZCON, RT_STRING}, + {"ZAOC", RSP_ZAOC, RT_STRING}, + {"ZCSTR", RSP_ZCSTR, RT_STRING}, + {"ZCFG", RSP_ZCFG, RT_HEX}, + {"ZLOG", RSP_ZLOG, RT_NOTHING}, + {"ZABINFO", RSP_ZABINFO, RT_NOTHING}, + {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING}, + {NULL,0,0} +}; + +/* + * Get integer from char-pointer + */ +static int isdn_getnum(char *p) +{ + int v = -1; + + IFNULLRETVAL(p, -1); + + dbg(DEBUG_TRANSCMD, "string: %s", p); + + while (*p >= '0' && *p <= '9') + v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0'); + if (*p) + v = -1; /* invalid Character */ + return v; +} + +/* + * Get integer from char-pointer + */ +static int isdn_gethex(char *p) +{ + int v = 0; + int c; + + IFNULLRETVAL(p, -1); + + dbg(DEBUG_TRANSCMD, "string: %s", p); + + if (!*p) + return -1; + + do { + if (v > (INT_MAX - 15) / 16) + return -1; + c = *p; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else + return -1; + v = v * 16 + c; + } while (*++p); + + return v; +} + +static inline void new_index(atomic_t *index, int max) +{ + if (atomic_read(index) == max) //FIXME race? + atomic_set(index, 0); + else + atomic_inc(index); +} + +/* retrieve CID from parsed response + * returns 0 if no CID, -1 if invalid CID, or CID value 1..65535 + */ +static int cid_of_response(char *s) +{ + int cid; + + if (s[-1] != ';') + return 0; /* no CID separator */ + cid = isdn_getnum(s); + if (cid < 0) + return 0; /* CID not numeric */ + if (cid < 1 || cid > 65535) + return -1; /* CID out of range */ + return cid; + //FIXME is ;+ at end of non-CID response really impossible? +} + +/* This function will be called via task queue from the callback handler. + * We received a modem response and have to handle it.. + */ +void gigaset_handle_modem_response(struct cardstate *cs) +{ + unsigned char *argv[MAX_REC_PARAMS + 1]; + int params; + int i, j; + struct resp_type_t *rt; + int curarg; + unsigned long flags; + unsigned next, tail, head; + struct event_t *event; + int resp_code; + int param_type; + int abort; + size_t len; + int cid; + int rawstring; + + IFNULLRET(cs); + + len = cs->cbytes; + if (!len) { + /* ignore additional LFs/CRs (M10x config mode or cx100) */ + dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]); + return; + } + cs->respdata[len] = 0; + dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata); + argv[0] = cs->respdata; + params = 1; + if (cs->at_state.getstring) { + /* getstring only allowed without cid at the moment */ + cs->at_state.getstring = 0; + rawstring = 1; + cid = 0; + } else { + /* parse line */ + for (i = 0; i < len; i++) + switch (cs->respdata[i]) { + case ';': + case ',': + case '=': + if (params > MAX_REC_PARAMS) { + warn("too many parameters in response"); + /* need last parameter (might be CID) */ + params--; + } + argv[params++] = cs->respdata + i + 1; + } + + rawstring = 0; + cid = params > 1 ? cid_of_response(argv[params-1]) : 0; + if (cid < 0) { + gigaset_add_event(cs, &cs->at_state, RSP_INVAL, + NULL, 0, NULL); + return; + } + + for (j = 1; j < params; ++j) + argv[j][-1] = 0; + + dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]); + if (cid) { + --params; + dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]); + } + dbg(DEBUG_TRANSCMD, "available params: %d", params - 1); + for (j = 1; j < params; j++) + dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]); + } + + spin_lock_irqsave(&cs->ev_lock, flags); + head = atomic_read(&cs->ev_head); + tail = atomic_read(&cs->ev_tail); + + abort = 1; + curarg = 0; + while (curarg < params) { + next = (tail + 1) % MAX_EVENTS; + if (unlikely(next == head)) { + err("event queue full"); + break; + } + + event = cs->events + tail; + event->at_state = NULL; + event->cid = cid; + event->ptr = NULL; + event->arg = NULL; + tail = next; + + if (rawstring) { + resp_code = RSP_STRING; + param_type = RT_STRING; + } else { + for (rt = resp_type; rt->response; ++rt) + if (!strcmp(argv[curarg], rt->response)) + break; + + if (!rt->response) { + event->type = RSP_UNKNOWN; + warn("unknown modem response: %s", + argv[curarg]); + break; + } + + resp_code = rt->resp_code; + param_type = rt->type; + ++curarg; + } + + event->type = resp_code; + + switch (param_type) { + case RT_NOTHING: + break; + case RT_RING: + if (!cid) { + err("received RING without CID!"); + event->type = RSP_INVAL; + abort = 1; + } else { + event->cid = 0; + event->parameter = cid; + abort = 0; + } + break; + case RT_ZSAU: + if (curarg >= params) { + event->parameter = ZSAU_NONE; + break; + } + if (!strcmp(argv[curarg], "OUTGOING_CALL_PROCEEDING")) + event->parameter = ZSAU_OUTGOING_CALL_PROCEEDING; + else if (!strcmp(argv[curarg], "CALL_DELIVERED")) + event->parameter = ZSAU_CALL_DELIVERED; + else if (!strcmp(argv[curarg], "ACTIVE")) + event->parameter = ZSAU_ACTIVE; + else if (!strcmp(argv[curarg], "DISCONNECT_IND")) + event->parameter = ZSAU_DISCONNECT_IND; + else if (!strcmp(argv[curarg], "NULL")) + event->parameter = ZSAU_NULL; + else if (!strcmp(argv[curarg], "DISCONNECT_REQ")) + event->parameter = ZSAU_DISCONNECT_REQ; + else { + event->parameter = ZSAU_UNKNOWN; + warn("%s: unknown parameter %s after ZSAU", + __func__, argv[curarg]); + } + ++curarg; + break; + case RT_STRING: + if (curarg < params) { + len = strlen(argv[curarg]) + 1; + event->ptr = kmalloc(len, GFP_ATOMIC); + if (event->ptr) + memcpy(event->ptr, argv[curarg], len); + else + err("no memory for string!"); + ++curarg; + } +#ifdef CONFIG_GIGASET_DEBUG + if (!event->ptr) + dbg(DEBUG_CMD, "string==NULL"); + else + dbg(DEBUG_CMD, + "string==%s", (char *) event->ptr); +#endif + break; + case RT_ZCAU: + event->parameter = -1; + if (curarg + 1 < params) { + i = isdn_gethex(argv[curarg]); + j = isdn_gethex(argv[curarg + 1]); + if (i >= 0 && i < 256 && j >= 0 && j < 256) + event->parameter = (unsigned) i << 8 + | j; + curarg += 2; + } else + curarg = params - 1; + break; + case RT_NUMBER: + case RT_HEX: + if (curarg < params) { + if (param_type == RT_HEX) + event->parameter = + isdn_gethex(argv[curarg]); + else + event->parameter = + isdn_getnum(argv[curarg]); + ++curarg; + } else + event->parameter = -1; +#ifdef CONFIG_GIGASET_DEBUG + dbg(DEBUG_CMD, "parameter==%d", event->parameter); +#endif + break; + } + + if (resp_code == RSP_ZDLE) + cs->dle = event->parameter; + + if (abort) + break; + } + + atomic_set(&cs->ev_tail, tail); + spin_unlock_irqrestore(&cs->ev_lock, flags); + + if (curarg != params) + dbg(DEBUG_ANY, "invalid number of processed parameters: %d/%d", + curarg, params); +} +EXPORT_SYMBOL_GPL(gigaset_handle_modem_response); + +/* disconnect + * process closing of connection associated with given AT state structure + */ +static void disconnect(struct at_state_t **at_state_p) +{ + unsigned long flags; + struct bc_state *bcs; + struct cardstate *cs; + + IFNULLRET(at_state_p); + IFNULLRET(*at_state_p); + bcs = (*at_state_p)->bcs; + cs = (*at_state_p)->cs; + IFNULLRET(cs); + + new_index(&(*at_state_p)->seq_index, MAX_SEQ_INDEX); + + /* revert to selected idle mode */ + if (!atomic_read(&cs->cidmode)) { + cs->at_state.pending_commands |= PC_UMMODE; + atomic_set(&cs->commands_pending, 1); //FIXME + dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); + } + + if (bcs) { + /* B channel assigned: invoke hardware specific handler */ + cs->ops->close_bchannel(bcs); + } else { + /* no B channel assigned: just deallocate */ + spin_lock_irqsave(&cs->lock, flags); + list_del(&(*at_state_p)->list); + kfree(*at_state_p); + *at_state_p = NULL; + spin_unlock_irqrestore(&cs->lock, flags); + } +} + +/* get_free_channel + * get a free AT state structure: either one of those associated with the + * B channels of the Gigaset device, or if none of those is available, + * a newly allocated one with bcs=NULL + * The structure should be freed by calling disconnect() after use. + */ +static inline struct at_state_t *get_free_channel(struct cardstate *cs, + int cid) +/* cids: >0: siemens-cid + 0: without cid + -1: no cid assigned yet +*/ +{ + unsigned long flags; + int i; + struct at_state_t *ret; + + for (i = 0; i < cs->channels; ++i) + if (gigaset_get_channel(cs->bcs + i)) { + ret = &cs->bcs[i].at_state; + ret->cid = cid; + return ret; + } + + spin_lock_irqsave(&cs->lock, flags); + ret = kmalloc(sizeof(struct at_state_t), GFP_ATOMIC); + if (ret) { + gigaset_at_init(ret, NULL, cs, cid); + list_add(&ret->list, &cs->temp_at_states); + } + spin_unlock_irqrestore(&cs->lock, flags); + return ret; +} + +static void init_failed(struct cardstate *cs, int mode) +{ + int i; + struct at_state_t *at_state; + + cs->at_state.pending_commands &= ~PC_INIT; + atomic_set(&cs->mode, mode); + atomic_set(&cs->mstate, MS_UNINITIALIZED); + gigaset_free_channels(cs); + for (i = 0; i < cs->channels; ++i) { + at_state = &cs->bcs[i].at_state; + if (at_state->pending_commands & PC_CID) { + at_state->pending_commands &= ~PC_CID; + at_state->pending_commands |= PC_NOCID; + atomic_set(&cs->commands_pending, 1); + } + } +} + +static void schedule_init(struct cardstate *cs, int state) +{ + if (cs->at_state.pending_commands & PC_INIT) { + dbg(DEBUG_CMD, "not scheduling PC_INIT again"); + return; + } + atomic_set(&cs->mstate, state); + atomic_set(&cs->mode, M_UNKNOWN); + gigaset_block_channels(cs); + cs->at_state.pending_commands |= PC_INIT; + atomic_set(&cs->commands_pending, 1); + dbg(DEBUG_CMD, "Scheduling PC_INIT"); +} + +/* Add "AT" to a command, add the cid, dle encode it, send the result to the hardware. */ +static void send_command(struct cardstate *cs, const char *cmd, int cid, + int dle, gfp_t kmallocflags) +{ + size_t cmdlen, buflen; + char *cmdpos, *cmdbuf, *cmdtail; + + cmdlen = strlen(cmd); + buflen = 11 + cmdlen; + + if (likely(buflen > cmdlen)) { + cmdbuf = kmalloc(buflen, kmallocflags); + if (likely(cmdbuf != NULL)) { + cmdpos = cmdbuf + 9; + cmdtail = cmdpos + cmdlen; + memcpy(cmdpos, cmd, cmdlen); + + if (cid > 0 && cid <= 65535) { + do { + *--cmdpos = '0' + cid % 10; + cid /= 10; + ++cmdlen; + } while (cid); + } + + cmdlen += 2; + *--cmdpos = 'T'; + *--cmdpos = 'A'; + + if (dle) { + cmdlen += 4; + *--cmdpos = '('; + *--cmdpos = 0x10; + *cmdtail++ = 0x10; + *cmdtail++ = ')'; + } + + cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL); + kfree(cmdbuf); + } else + err("no memory for command buffer"); + } else + err("overflow in buflen"); +} + +static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid) +{ + struct at_state_t *at_state; + int i; + unsigned long flags; + + if (cid == 0) + return &cs->at_state; + + for (i = 0; i < cs->channels; ++i) + if (cid == cs->bcs[i].at_state.cid) + return &cs->bcs[i].at_state; + + spin_lock_irqsave(&cs->lock, flags); + + list_for_each_entry(at_state, &cs->temp_at_states, list) + if (cid == at_state->cid) { + spin_unlock_irqrestore(&cs->lock, flags); + return at_state; + } + + spin_unlock_irqrestore(&cs->lock, flags); + + return NULL; +} + +static void bchannel_down(struct bc_state *bcs) +{ + IFNULLRET(bcs); + IFNULLRET(bcs->cs); + + if (bcs->chstate & CHS_B_UP) { + bcs->chstate &= ~CHS_B_UP; + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); + } + + if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { + bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); + } + + gigaset_free_channel(bcs); + + gigaset_bcs_reinit(bcs); +} + +static void bchannel_up(struct bc_state *bcs) +{ + IFNULLRET(bcs); + + if (!(bcs->chstate & CHS_D_UP)) { + notice("%s: D channel not up", __func__); + bcs->chstate |= CHS_D_UP; + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); + } + + if (bcs->chstate & CHS_B_UP) { + notice("%s: B channel already up", __func__); + return; + } + + bcs->chstate |= CHS_B_UP; + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); +} + +static void start_dial(struct at_state_t *at_state, void *data, int seq_index) +{ + struct bc_state *bcs = at_state->bcs; + struct cardstate *cs = at_state->cs; + int retval; + + bcs->chstate |= CHS_NOTIFY_LL; + //atomic_set(&bcs->status, BCS_INIT); + + if (atomic_read(&at_state->seq_index) != seq_index) + goto error; + + retval = gigaset_isdn_setup_dial(at_state, data); + if (retval != 0) + goto error; + + + at_state->pending_commands |= PC_CID; + dbg(DEBUG_CMD, "Scheduling PC_CID"); +//#ifdef GIG_MAYINITONDIAL +// if (atomic_read(&cs->MState) == MS_UNKNOWN) { +// cs->at_state.pending_commands |= PC_INIT; +// dbg(DEBUG_CMD, "Scheduling PC_INIT"); +// } +//#endif + atomic_set(&cs->commands_pending, 1); //FIXME + return; + +error: + at_state->pending_commands |= PC_NOCID; + dbg(DEBUG_CMD, "Scheduling PC_NOCID"); + atomic_set(&cs->commands_pending, 1); //FIXME + return; +} + +static void start_accept(struct at_state_t *at_state) +{ + struct cardstate *cs = at_state->cs; + int retval; + + retval = gigaset_isdn_setup_accept(at_state); + + if (retval == 0) { + at_state->pending_commands |= PC_ACCEPT; + dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); + atomic_set(&cs->commands_pending, 1); //FIXME + } else { + //FIXME + at_state->pending_commands |= PC_HUP; + dbg(DEBUG_CMD, "Scheduling PC_HUP"); + atomic_set(&cs->commands_pending, 1); //FIXME + } +} + +static void do_start(struct cardstate *cs) +{ + gigaset_free_channels(cs); + + if (atomic_read(&cs->mstate) != MS_LOCKED) + schedule_init(cs, MS_INIT); + + gigaset_i4l_cmd(cs, ISDN_STAT_RUN); + // FIXME: not in locked mode + // FIXME 2: only after init sequence + + cs->waiting = 0; + wake_up(&cs->waitqueue); +} + +static void finish_shutdown(struct cardstate *cs) +{ + if (atomic_read(&cs->mstate) != MS_LOCKED) { + atomic_set(&cs->mstate, MS_UNINITIALIZED); + atomic_set(&cs->mode, M_UNKNOWN); + } + + /* The rest is done by cleanup_cs () in user mode. */ + + cs->cmd_result = -ENODEV; + cs->waiting = 0; + wake_up_interruptible(&cs->waitqueue); +} + +static void do_shutdown(struct cardstate *cs) +{ + gigaset_block_channels(cs); + + if (atomic_read(&cs->mstate) == MS_READY) { + atomic_set(&cs->mstate, MS_SHUTDOWN); + cs->at_state.pending_commands |= PC_SHUTDOWN; + atomic_set(&cs->commands_pending, 1); //FIXME + dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); //FIXME + //gigaset_schedule_event(cs); //FIXME + } else + finish_shutdown(cs); +} + +static void do_stop(struct cardstate *cs) +{ + do_shutdown(cs); +} + +/* Entering cid mode or getting a cid failed: + * try to initialize the device and try again. + * + * channel >= 0: getting cid for the channel failed + * channel < 0: entering cid mode failed + * + * returns 0 on failure + */ +static int reinit_and_retry(struct cardstate *cs, int channel) +{ + int i; + + if (--cs->retry_count <= 0) + return 0; + + for (i = 0; i < cs->channels; ++i) + if (cs->bcs[i].at_state.cid > 0) + return 0; + + if (channel < 0) + warn("Could not enter cid mode. Reinit device and try again."); + else { + warn("Could not get a call id. Reinit device and try again."); + cs->bcs[channel].at_state.pending_commands |= PC_CID; + } + schedule_init(cs, MS_INIT); + return 1; +} + +static int at_state_invalid(struct cardstate *cs, + struct at_state_t *test_ptr) +{ + unsigned long flags; + unsigned channel; + struct at_state_t *at_state; + int retval = 0; + + spin_lock_irqsave(&cs->lock, flags); + + if (test_ptr == &cs->at_state) + goto exit; + + list_for_each_entry(at_state, &cs->temp_at_states, list) + if (at_state == test_ptr) + goto exit; + + for (channel = 0; channel < cs->channels; ++channel) + if (&cs->bcs[channel].at_state == test_ptr) + goto exit; + + retval = 1; +exit: + spin_unlock_irqrestore(&cs->lock, flags); + return retval; +} + +static void handle_icall(struct cardstate *cs, struct bc_state *bcs, + struct at_state_t **p_at_state) +{ + int retval; + struct at_state_t *at_state = *p_at_state; + + retval = gigaset_isdn_icall(at_state); + switch (retval) { + case ICALL_ACCEPT: + break; + default: + err("internal error: disposition=%d", retval); + /* --v-- fall through --v-- */ + case ICALL_IGNORE: + case ICALL_REJECT: + /* hang up actively + * Device doc says that would reject the call. + * In fact it doesn't. + */ + at_state->pending_commands |= PC_HUP; + atomic_set(&cs->commands_pending, 1); + break; + } +} + +static int do_lock(struct cardstate *cs) +{ + int mode; + int i; + + switch (atomic_read(&cs->mstate)) { + case MS_UNINITIALIZED: + case MS_READY: + if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) || + cs->at_state.pending_commands) + return -EBUSY; + + for (i = 0; i < cs->channels; ++i) + if (cs->bcs[i].at_state.pending_commands) + return -EBUSY; + + if (!gigaset_get_channels(cs)) + return -EBUSY; + + break; + case MS_LOCKED: + //retval = -EACCES; + break; + default: + return -EBUSY; + } + + mode = atomic_read(&cs->mode); + atomic_set(&cs->mstate, MS_LOCKED); + atomic_set(&cs->mode, M_UNKNOWN); + //FIXME reset card state / at states / bcs states + + return mode; +} + +static int do_unlock(struct cardstate *cs) +{ + if (atomic_read(&cs->mstate) != MS_LOCKED) + return -EINVAL; + + atomic_set(&cs->mstate, MS_UNINITIALIZED); + atomic_set(&cs->mode, M_UNKNOWN); + gigaset_free_channels(cs); + //FIXME reset card state / at states / bcs states + if (atomic_read(&cs->connected)) + schedule_init(cs, MS_INIT); + + return 0; +} + +static void do_action(int action, struct cardstate *cs, + struct bc_state *bcs, + struct at_state_t **p_at_state, char **pp_command, + int *p_genresp, int *p_resp_code, + struct event_t *ev) +{ + struct at_state_t *at_state = *p_at_state; + struct at_state_t *at_state2; + unsigned long flags; + + int channel; + + unsigned char *s, *e; + int i; + unsigned long val; + + switch (action) { + case ACT_NOTHING: + break; + case ACT_TIMEOUT: + at_state->waiting = 1; + break; + case ACT_INIT: + //FIXME setup everything + cs->at_state.pending_commands &= ~PC_INIT; + cs->cur_at_seq = SEQ_NONE; + atomic_set(&cs->mode, M_UNIMODEM); + if (!atomic_read(&cs->cidmode)) { + gigaset_free_channels(cs); + atomic_set(&cs->mstate, MS_READY); + break; + } + cs->at_state.pending_commands |= PC_CIDMODE; + atomic_set(&cs->commands_pending, 1); //FIXME + dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + break; + case ACT_FAILINIT: + warn("Could not initialize the device."); + cs->dle = 0; + init_failed(cs, M_UNKNOWN); + cs->cur_at_seq = SEQ_NONE; + break; + case ACT_CONFIGMODE: + init_failed(cs, M_CONFIG); + cs->cur_at_seq = SEQ_NONE; + break; + case ACT_SETDLE1: + cs->dle = 1; + /* cs->inbuf[0].inputstate |= INS_command | INS_DLE_command; */ + cs->inbuf[0].inputstate &= + ~(INS_command | INS_DLE_command); + break; + case ACT_SETDLE0: + cs->dle = 0; + cs->inbuf[0].inputstate = + (cs->inbuf[0].inputstate & ~INS_DLE_command) + | INS_command; + break; + case ACT_CMODESET: + if (atomic_read(&cs->mstate) == MS_INIT || + atomic_read(&cs->mstate) == MS_RECOVER) { + gigaset_free_channels(cs); + atomic_set(&cs->mstate, MS_READY); + } + atomic_set(&cs->mode, M_CID); + cs->cur_at_seq = SEQ_NONE; + break; + case ACT_UMODESET: + atomic_set(&cs->mode, M_UNIMODEM); + cs->cur_at_seq = SEQ_NONE; + break; + case ACT_FAILCMODE: + cs->cur_at_seq = SEQ_NONE; + if (atomic_read(&cs->mstate) == MS_INIT || + atomic_read(&cs->mstate) == MS_RECOVER) { + init_failed(cs, M_UNKNOWN); + break; + } + if (!reinit_and_retry(cs, -1)) + schedule_init(cs, MS_RECOVER); + break; + case ACT_FAILUMODE: + cs->cur_at_seq = SEQ_NONE; + schedule_init(cs, MS_RECOVER); + break; + case ACT_HUPMODEM: + /* send "+++" (hangup in unimodem mode) */ + cs->ops->write_cmd(cs, "+++", 3, NULL); + break; + case ACT_RING: + /* get fresh AT state structure for new CID */ + at_state2 = get_free_channel(cs, ev->parameter); + if (!at_state2) { + warn("RING ignored: " + "could not allocate channel structure"); + break; + } + + /* initialize AT state structure + * note that bcs may be NULL if no B channel is free + */ + at_state2->ConState = 700; + kfree(at_state2->str_var[STR_NMBR]); + at_state2->str_var[STR_NMBR] = NULL; + kfree(at_state2->str_var[STR_ZCPN]); + at_state2->str_var[STR_ZCPN] = NULL; + kfree(at_state2->str_var[STR_ZBC]); + at_state2->str_var[STR_ZBC] = NULL; + kfree(at_state2->str_var[STR_ZHLC]); + at_state2->str_var[STR_ZHLC] = NULL; + at_state2->int_var[VAR_ZCTP] = -1; + + spin_lock_irqsave(&cs->lock, flags); + at_state2->timer_expires = RING_TIMEOUT; + at_state2->timer_active = 1; + spin_unlock_irqrestore(&cs->lock, flags); + break; + case ACT_ICALL: + handle_icall(cs, bcs, p_at_state); + at_state = *p_at_state; + break; + case ACT_FAILSDOWN: + warn("Could not shut down the device."); + /* fall through */ + case ACT_FAKESDOWN: + case ACT_SDOWN: + cs->cur_at_seq = SEQ_NONE; + finish_shutdown(cs); + break; + case ACT_CONNECT: + if (cs->onechannel) { + at_state->pending_commands |= PC_DLE1; + atomic_set(&cs->commands_pending, 1); + break; + } + bcs->chstate |= CHS_D_UP; + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); + cs->ops->init_bchannel(bcs); + break; + case ACT_DLE1: + cs->cur_at_seq = SEQ_NONE; + bcs = cs->bcs + cs->curchannel; + + bcs->chstate |= CHS_D_UP; + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); + cs->ops->init_bchannel(bcs); + break; + case ACT_FAKEHUP: + at_state->int_var[VAR_ZSAU] = ZSAU_NULL; + /* fall through */ + case ACT_DISCONNECT: + cs->cur_at_seq = SEQ_NONE; + at_state->cid = -1; + if (bcs && cs->onechannel && cs->dle) { + /* Check for other open channels not needed: + * DLE only used for M10x with one B channel. + */ + at_state->pending_commands |= PC_DLE0; + atomic_set(&cs->commands_pending, 1); + } else { + disconnect(p_at_state); + at_state = *p_at_state; + } + break; + case ACT_FAKEDLE0: + at_state->int_var[VAR_ZDLE] = 0; + cs->dle = 0; + /* fall through */ + case ACT_DLE0: + cs->cur_at_seq = SEQ_NONE; + at_state2 = &cs->bcs[cs->curchannel].at_state; + disconnect(&at_state2); + break; + case ACT_ABORTHUP: + cs->cur_at_seq = SEQ_NONE; + warn("Could not hang up."); + at_state->cid = -1; + if (bcs && cs->onechannel) + at_state->pending_commands |= PC_DLE0; + else { + disconnect(p_at_state); + at_state = *p_at_state; + } + schedule_init(cs, MS_RECOVER); + break; + case ACT_FAILDLE0: + cs->cur_at_seq = SEQ_NONE; + warn("Could not leave DLE mode."); + at_state2 = &cs->bcs[cs->curchannel].at_state; + disconnect(&at_state2); + schedule_init(cs, MS_RECOVER); + break; + case ACT_FAILDLE1: + cs->cur_at_seq = SEQ_NONE; + warn("Could not enter DLE mode. Try to hang up."); + channel = cs->curchannel; + cs->bcs[channel].at_state.pending_commands |= PC_HUP; + atomic_set(&cs->commands_pending, 1); + break; + + case ACT_CID: /* got cid; start dialing */ + cs->cur_at_seq = SEQ_NONE; + channel = cs->curchannel; + if (ev->parameter > 0 && ev->parameter <= 65535) { + cs->bcs[channel].at_state.cid = ev->parameter; + cs->bcs[channel].at_state.pending_commands |= + PC_DIAL; + atomic_set(&cs->commands_pending, 1); + break; + } + /* fall through */ + case ACT_FAILCID: + cs->cur_at_seq = SEQ_NONE; + channel = cs->curchannel; + if (!reinit_and_retry(cs, channel)) { + warn("Could not get a call id. Dialing not possible"); + at_state2 = &cs->bcs[channel].at_state; + disconnect(&at_state2); + } + break; + case ACT_ABORTCID: + cs->cur_at_seq = SEQ_NONE; + at_state2 = &cs->bcs[cs->curchannel].at_state; + disconnect(&at_state2); + break; + + case ACT_DIALING: + case ACT_ACCEPTED: + cs->cur_at_seq = SEQ_NONE; + break; + + case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL processing */ + disconnect(p_at_state); + at_state = *p_at_state; + break; + + case ACT_ABORTDIAL: /* error/timeout during dial preparation */ + cs->cur_at_seq = SEQ_NONE; + at_state->pending_commands |= PC_HUP; + atomic_set(&cs->commands_pending, 1); + break; + + case ACT_REMOTEREJECT: /* DISCONNECT_IND after dialling */ + case ACT_CONNTIMEOUT: /* timeout waiting for ZSAU=ACTIVE */ + case ACT_REMOTEHUP: /* DISCONNECT_IND with established connection */ + at_state->pending_commands |= PC_HUP; + atomic_set(&cs->commands_pending, 1); + break; + case ACT_GETSTRING: /* warning: RING, ZDLE, ... are not handled properly any more */ + at_state->getstring = 1; + break; + case ACT_SETVER: + if (!ev->ptr) { + *p_genresp = 1; + *p_resp_code = RSP_ERROR; + break; + } + s = ev->ptr; + + if (!strcmp(s, "OK")) { + *p_genresp = 1; + *p_resp_code = RSP_ERROR; + break; + } + + for (i = 0; i < 4; ++i) { + val = simple_strtoul(s, (char **) &e, 10); + if (val > INT_MAX || e == s) + break; + if (i == 3) { + if (*e) + break; + } else if (*e != '.') + break; + else + s = e + 1; + cs->fwver[i] = val; + } + if (i != 4) { + *p_genresp = 1; + *p_resp_code = RSP_ERROR; + break; + } + /*at_state->getstring = 1;*/ + cs->gotfwver = 0; + break; + case ACT_GOTVER: + if (cs->gotfwver == 0) { + cs->gotfwver = 1; + dbg(DEBUG_ANY, + "firmware version %02d.%03d.%02d.%02d", + cs->fwver[0], cs->fwver[1], + cs->fwver[2], cs->fwver[3]); + break; + } + /* fall through */ + case ACT_FAILVER: + cs->gotfwver = -1; + err("could not read firmware version."); + break; +#ifdef CONFIG_GIGASET_DEBUG + case ACT_ERROR: + *p_genresp = 1; + *p_resp_code = RSP_ERROR; + break; + case ACT_TEST: + { + static int count = 3; //2; //1; + *p_genresp = 1; + *p_resp_code = count ? RSP_ERROR : RSP_OK; + if (count > 0) + --count; + } + break; +#endif + case ACT_DEBUG: + dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", + __func__, ev->type, at_state->ConState); + break; + case ACT_WARN: + warn("%s: resp_code %d in ConState %d!", + __func__, ev->type, at_state->ConState); + break; + case ACT_ZCAU: + warn("cause code %04x in connection state %d.", + ev->parameter, at_state->ConState); + break; + + /* events from the LL */ + case ACT_DIAL: + start_dial(at_state, ev->ptr, ev->parameter); + break; + case ACT_ACCEPT: + start_accept(at_state); + break; + case ACT_PROTO_L2: + dbg(DEBUG_CMD, + "set protocol to %u", (unsigned) ev->parameter); + at_state->bcs->proto2 = ev->parameter; + break; + case ACT_HUP: + at_state->pending_commands |= PC_HUP; + atomic_set(&cs->commands_pending, 1); //FIXME + dbg(DEBUG_CMD, "Scheduling PC_HUP"); + break; + + /* hotplug events */ + case ACT_STOP: + do_stop(cs); + break; + case ACT_START: + do_start(cs); + break; + + /* events from the interface */ // FIXME without ACT_xxxx? + case ACT_IF_LOCK: + cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs); + cs->waiting = 0; + wake_up(&cs->waitqueue); + break; + case ACT_IF_VER: + if (ev->parameter != 0) + cs->cmd_result = -EINVAL; + else if (cs->gotfwver != 1) { + cs->cmd_result = -ENOENT; + } else { + memcpy(ev->arg, cs->fwver, sizeof cs->fwver); + cs->cmd_result = 0; + } + cs->waiting = 0; + wake_up(&cs->waitqueue); + break; + + /* events from the proc file system */ // FIXME without ACT_xxxx? + case ACT_PROC_CIDMODE: + if (ev->parameter != atomic_read(&cs->cidmode)) { + atomic_set(&cs->cidmode, ev->parameter); + if (ev->parameter) { + cs->at_state.pending_commands |= PC_CIDMODE; + dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + } else { + cs->at_state.pending_commands |= PC_UMMODE; + dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); + } + atomic_set(&cs->commands_pending, 1); + } + cs->waiting = 0; + wake_up(&cs->waitqueue); + break; + + /* events from the hardware drivers */ + case ACT_NOTIFY_BC_DOWN: + bchannel_down(bcs); + break; + case ACT_NOTIFY_BC_UP: + bchannel_up(bcs); + break; + case ACT_SHUTDOWN: + do_shutdown(cs); + break; + + + default: + if (action >= ACT_CMD && action < ACT_CMD + AT_NUM) { + *pp_command = at_state->bcs->commands[action - ACT_CMD]; + if (!*pp_command) { + *p_genresp = 1; + *p_resp_code = RSP_NULL; + } + } else + err("%s: action==%d!", __func__, action); + } +} + +/* State machine to do the calling and hangup procedure */ +static void process_event(struct cardstate *cs, struct event_t *ev) +{ + struct bc_state *bcs; + char *p_command = NULL; + struct reply_t *rep; + int rcode; + int genresp = 0; + int resp_code = RSP_ERROR; + int sendcid; + struct at_state_t *at_state; + int index; + int curact; + unsigned long flags; + + IFNULLRET(cs); + IFNULLRET(ev); + + if (ev->cid >= 0) { + at_state = at_state_from_cid(cs, ev->cid); + if (!at_state) { + gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID, + NULL, 0, NULL); + return; + } + } else { + at_state = ev->at_state; + if (at_state_invalid(cs, at_state)) { + dbg(DEBUG_ANY, + "event for invalid at_state %p", at_state); + return; + } + } + + dbg(DEBUG_CMD, + "connection state %d, event %d", at_state->ConState, ev->type); + + bcs = at_state->bcs; + sendcid = at_state->cid; + + /* Setting the pointer to the dial array */ + rep = at_state->replystruct; + IFNULLRET(rep); + + if (ev->type == EV_TIMEOUT) { + if (ev->parameter != atomic_read(&at_state->timer_index) + || !at_state->timer_active) { + ev->type = RSP_NONE; /* old timeout */ + dbg(DEBUG_ANY, "old timeout"); + } else if (!at_state->waiting) + dbg(DEBUG_ANY, "timeout occured"); + else + dbg(DEBUG_ANY, "stopped waiting"); + } + + /* if the response belongs to a variable in at_state->int_var[VAR_XXXX] or at_state->str_var[STR_XXXX], set it */ + if (ev->type >= RSP_VAR && ev->type < RSP_VAR + VAR_NUM) { + index = ev->type - RSP_VAR; + at_state->int_var[index] = ev->parameter; + } else if (ev->type >= RSP_STR && ev->type < RSP_STR + STR_NUM) { + index = ev->type - RSP_STR; + kfree(at_state->str_var[index]); + at_state->str_var[index] = ev->ptr; + ev->ptr = NULL; /* prevent process_events() from deallocating ptr */ + } + + if (ev->type == EV_TIMEOUT || ev->type == RSP_STRING) + at_state->getstring = 0; + + /* Search row in dial array which matches modem response and current constate */ + for (;; rep++) { + rcode = rep->resp_code; + /* dbg (DEBUG_ANY, "rcode %d", rcode); */ + if (rcode == RSP_LAST) { + /* found nothing...*/ + warn("%s: rcode=RSP_LAST: resp_code %d in ConState %d!", + __func__, ev->type, at_state->ConState); + return; + } + if ((rcode == RSP_ANY || rcode == ev->type) + && ((int) at_state->ConState >= rep->min_ConState) + && (rep->max_ConState < 0 + || (int) at_state->ConState <= rep->max_ConState) + && (rep->parameter < 0 || rep->parameter == ev->parameter)) + break; + } + + p_command = rep->command; + + at_state->waiting = 0; + for (curact = 0; curact < MAXACT; ++curact) { + /* The row tells us what we should do .. + */ + do_action(rep->action[curact], cs, bcs, &at_state, &p_command, &genresp, &resp_code, ev); + if (!at_state) + break; /* may be freed after disconnect */ + } + + if (at_state) { + /* Jump to the next con-state regarding the array */ + if (rep->new_ConState >= 0) + at_state->ConState = rep->new_ConState; + + if (genresp) { + spin_lock_irqsave(&cs->lock, flags); + at_state->timer_expires = 0; //FIXME + at_state->timer_active = 0; //FIXME + spin_unlock_irqrestore(&cs->lock, flags); + gigaset_add_event(cs, at_state, resp_code, NULL, 0, NULL); + } else { + /* Send command to modem if not NULL... */ + if (p_command/*rep->command*/) { + if (atomic_read(&cs->connected)) + send_command(cs, p_command, + sendcid, cs->dle, + GFP_ATOMIC); + else + gigaset_add_event(cs, at_state, + RSP_NODEV, + NULL, 0, NULL); + } + + spin_lock_irqsave(&cs->lock, flags); + if (!rep->timeout) { + at_state->timer_expires = 0; + at_state->timer_active = 0; + } else if (rep->timeout > 0) { /* new timeout */ + at_state->timer_expires = rep->timeout * 10; + at_state->timer_active = 1; + new_index(&at_state->timer_index, + MAX_TIMER_INDEX); + } + spin_unlock_irqrestore(&cs->lock, flags); + } + } +} + +static void schedule_sequence(struct cardstate *cs, + struct at_state_t *at_state, int sequence) +{ + cs->cur_at_seq = sequence; + gigaset_add_event(cs, at_state, RSP_INIT, NULL, sequence, NULL); +} + +static void process_command_flags(struct cardstate *cs) +{ + struct at_state_t *at_state = NULL; + struct bc_state *bcs; + int i; + int sequence; + + IFNULLRET(cs); + + atomic_set(&cs->commands_pending, 0); + + if (cs->cur_at_seq) { + dbg(DEBUG_CMD, "not searching scheduled commands: busy"); + return; + } + + dbg(DEBUG_CMD, "searching scheduled commands"); + + sequence = SEQ_NONE; + + /* clear pending_commands and hangup channels on shutdown */ + if (cs->at_state.pending_commands & PC_SHUTDOWN) { + cs->at_state.pending_commands &= ~PC_CIDMODE; + for (i = 0; i < cs->channels; ++i) { + bcs = cs->bcs + i; + at_state = &bcs->at_state; + at_state->pending_commands &= + ~(PC_DLE1 | PC_ACCEPT | PC_DIAL); + if (at_state->cid > 0) + at_state->pending_commands |= PC_HUP; + if (at_state->pending_commands & PC_CID) { + at_state->pending_commands |= PC_NOCID; + at_state->pending_commands &= ~PC_CID; + } + } + } + + /* clear pending_commands and hangup channels on reset */ + if (cs->at_state.pending_commands & PC_INIT) { + cs->at_state.pending_commands &= ~PC_CIDMODE; + for (i = 0; i < cs->channels; ++i) { + bcs = cs->bcs + i; + at_state = &bcs->at_state; + at_state->pending_commands &= + ~(PC_DLE1 | PC_ACCEPT | PC_DIAL); + if (at_state->cid > 0) + at_state->pending_commands |= PC_HUP; + if (atomic_read(&cs->mstate) == MS_RECOVER) { + if (at_state->pending_commands & PC_CID) { + at_state->pending_commands |= PC_NOCID; + at_state->pending_commands &= ~PC_CID; + } + } + } + } + + /* only switch back to unimodem mode, if no commands are pending and no channels are up */ + if (cs->at_state.pending_commands == PC_UMMODE + && !atomic_read(&cs->cidmode) + && list_empty(&cs->temp_at_states) + && atomic_read(&cs->mode) == M_CID) { + sequence = SEQ_UMMODE; + at_state = &cs->at_state; + for (i = 0; i < cs->channels; ++i) { + bcs = cs->bcs + i; + if (bcs->at_state.pending_commands || + bcs->at_state.cid > 0) { + sequence = SEQ_NONE; + break; + } + } + } + cs->at_state.pending_commands &= ~PC_UMMODE; + if (sequence != SEQ_NONE) { + schedule_sequence(cs, at_state, sequence); + return; + } + + for (i = 0; i < cs->channels; ++i) { + bcs = cs->bcs + i; + if (bcs->at_state.pending_commands & PC_HUP) { + bcs->at_state.pending_commands &= ~PC_HUP; + if (bcs->at_state.pending_commands & PC_CID) { + /* not yet dialing: PC_NOCID is sufficient */ + bcs->at_state.pending_commands |= PC_NOCID; + bcs->at_state.pending_commands &= ~PC_CID; + } else { + schedule_sequence(cs, &bcs->at_state, SEQ_HUP); + return; + } + } + if (bcs->at_state.pending_commands & PC_NOCID) { + bcs->at_state.pending_commands &= ~PC_NOCID; + cs->curchannel = bcs->channel; + schedule_sequence(cs, &cs->at_state, SEQ_NOCID); + return; + } else if (bcs->at_state.pending_commands & PC_DLE0) { + bcs->at_state.pending_commands &= ~PC_DLE0; + cs->curchannel = bcs->channel; + schedule_sequence(cs, &cs->at_state, SEQ_DLE0); + return; + } + } + + list_for_each_entry(at_state, &cs->temp_at_states, list) + if (at_state->pending_commands & PC_HUP) { + at_state->pending_commands &= ~PC_HUP; + schedule_sequence(cs, at_state, SEQ_HUP); + return; + } + + if (cs->at_state.pending_commands & PC_INIT) { + cs->at_state.pending_commands &= ~PC_INIT; + cs->dle = 0; //FIXME + cs->inbuf->inputstate = INS_command; + //FIXME reset card state (or -> LOCK0)? + schedule_sequence(cs, &cs->at_state, SEQ_INIT); + return; + } + if (cs->at_state.pending_commands & PC_SHUTDOWN) { + cs->at_state.pending_commands &= ~PC_SHUTDOWN; + schedule_sequence(cs, &cs->at_state, SEQ_SHUTDOWN); + return; + } + if (cs->at_state.pending_commands & PC_CIDMODE) { + cs->at_state.pending_commands &= ~PC_CIDMODE; + if (atomic_read(&cs->mode) == M_UNIMODEM) { +#if 0 + cs->retry_count = 2; +#else + cs->retry_count = 1; +#endif + schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE); + return; + } + } + + for (i = 0; i < cs->channels; ++i) { + bcs = cs->bcs + i; + if (bcs->at_state.pending_commands & PC_DLE1) { + bcs->at_state.pending_commands &= ~PC_DLE1; + cs->curchannel = bcs->channel; + schedule_sequence(cs, &cs->at_state, SEQ_DLE1); + return; + } + if (bcs->at_state.pending_commands & PC_ACCEPT) { + bcs->at_state.pending_commands &= ~PC_ACCEPT; + schedule_sequence(cs, &bcs->at_state, SEQ_ACCEPT); + return; + } + if (bcs->at_state.pending_commands & PC_DIAL) { + bcs->at_state.pending_commands &= ~PC_DIAL; + schedule_sequence(cs, &bcs->at_state, SEQ_DIAL); + return; + } + if (bcs->at_state.pending_commands & PC_CID) { + switch (atomic_read(&cs->mode)) { + case M_UNIMODEM: + cs->at_state.pending_commands |= PC_CIDMODE; + dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + atomic_set(&cs->commands_pending, 1); + return; +#ifdef GIG_MAYINITONDIAL + case M_UNKNOWN: + schedule_init(cs, MS_INIT); + return; +#endif + } + bcs->at_state.pending_commands &= ~PC_CID; + cs->curchannel = bcs->channel; +#ifdef GIG_RETRYCID + cs->retry_count = 2; +#else + cs->retry_count = 1; +#endif + schedule_sequence(cs, &cs->at_state, SEQ_CID); + return; + } + } +} + +static void process_events(struct cardstate *cs) +{ + struct event_t *ev; + unsigned head, tail; + int i; + int check_flags = 0; + int was_busy; + + /* no locking needed (only one reader) */ + head = atomic_read(&cs->ev_head); + + for (i = 0; i < 2 * MAX_EVENTS; ++i) { + tail = atomic_read(&cs->ev_tail); + if (tail == head) { + if (!check_flags && !atomic_read(&cs->commands_pending)) + break; + check_flags = 0; + process_command_flags(cs); + tail = atomic_read(&cs->ev_tail); + if (tail == head) { + if (!atomic_read(&cs->commands_pending)) + break; + continue; + } + } + + ev = cs->events + head; + was_busy = cs->cur_at_seq != SEQ_NONE; + process_event(cs, ev); + kfree(ev->ptr); + ev->ptr = NULL; + if (was_busy && cs->cur_at_seq == SEQ_NONE) + check_flags = 1; + + head = (head + 1) % MAX_EVENTS; + atomic_set(&cs->ev_head, head); + } + + if (i == 2 * MAX_EVENTS) { + err("infinite loop in process_events; aborting."); + } +} + +/* tasklet scheduled on any event received from the Gigaset device + * parameter: + * data ISDN controller state structure + */ +void gigaset_handle_event(unsigned long data) +{ + struct cardstate *cs = (struct cardstate *) data; + + IFNULLRET(cs); + IFNULLRET(cs->inbuf); + + /* handle incoming data on control/common channel */ + if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) { + dbg(DEBUG_INTR, "processing new data"); + cs->ops->handle_input(cs->inbuf); + } + + process_events(cs); +} -- cgit v1.2.3-59-g8ed1b From 3c66a22545dd88356bbf4efa45a7b178df8154e9 Mon Sep 17 00:00:00 2001 From: Hansjoerg Lipp Date: Sun, 26 Mar 2006 01:38:31 -0800 Subject: [PATCH] isdn4linux: Siemens Gigaset drivers - isdn4linux interface And: Tilman Schmidt This patch adds the isdn4linux subsystem interface to the gigaset module. The isdn4linux subsystem interface handles requests from and notifications to the isdn4linux subsystem. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Cc: Karsten Keil Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/gigaset/i4l.c | 567 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 567 insertions(+) create mode 100644 drivers/isdn/gigaset/i4l.c (limited to 'drivers') diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c new file mode 100644 index 000000000000..731a675f21b0 --- /dev/null +++ b/drivers/isdn/gigaset/i4l.c @@ -0,0 +1,567 @@ +/* + * Stuff used by all variants of the driver + * + * Copyright (c) 2001 by Stefan Eilers (Eilers.Stefan@epost.de), + * Hansjoerg Lipp (hjlipp@web.de), + * Tilman Schmidt (tilman@imap.cc). + * + * ===================================================================== + * 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. + * ===================================================================== + * ToDo: ... + * ===================================================================== + * Version: $Id: i4l.c,v 1.3.2.9 2006/02/04 18:28:16 hjlipp Exp $ + * ===================================================================== + */ + +#include "gigaset.h" + +/* == Handling of I4L IO ============================================================================*/ + +/* writebuf_from_LL + * called by LL to transmit data on an open channel + * inserts the buffer data into the send queue and starts the transmission + * Note that this operation must not sleep! + * When the buffer is processed completely, gigaset_skb_sent() should be called. + * parameters: + * driverID driver ID as assigned by LL + * channel channel number + * ack if != 0 LL wants to be notified on completion via statcallb(ISDN_STAT_BSENT) + * skb skb containing data to send + * return value: + * number of accepted bytes + * 0 if temporarily unable to accept data (out of buffer space) + * <0 on error (eg. -EINVAL) + */ +static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff *skb) +{ + struct cardstate *cs; + struct bc_state *bcs; + unsigned len; + unsigned skblen; + + if (!(cs = gigaset_get_cs_by_id(driverID))) { + err("%s: invalid driver ID (%d)", __func__, driverID); + return -ENODEV; + } + if (channel < 0 || channel >= cs->channels) { + err("%s: invalid channel ID (%d)", __func__, channel); + return -ENODEV; + } + bcs = &cs->bcs[channel]; + len = skb->len; + + dbg(DEBUG_LLDATA, + "Receiving data from LL (id: %d, channel: %d, ack: %d, size: %d)", + driverID, channel, ack, len); + + if (!len) { + if (ack) + warn("not ACKing empty packet from LL"); + return 0; + } + if (len > MAX_BUF_SIZE) { + err("%s: packet too large (%d bytes)", __func__, channel); + return -EINVAL; + } + + if (!atomic_read(&cs->connected)) + return -ENODEV; + + skblen = ack ? len : 0; + skb->head[0] = skblen & 0xff; + skb->head[1] = skblen >> 8; + dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", len, skblen, + (unsigned) skb->head[0], (unsigned) skb->head[1]); + + /* pass to device-specific module */ + return cs->ops->send_skb(bcs, skb); +} + +void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) +{ + unsigned len; + isdn_ctrl response; + + ++bcs->trans_up; + + if (skb->len) + warn("%s: skb->len==%d", __func__, skb->len); + + len = (unsigned char) skb->head[0] | + (unsigned) (unsigned char) skb->head[1] << 8; + if (len) { + dbg(DEBUG_MCMD, + "Acknowledge sending to LL (id: %d, channel: %d size: %u)", + bcs->cs->myid, bcs->channel, len); + + response.driver = bcs->cs->myid; + response.command = ISDN_STAT_BSENT; + response.arg = bcs->channel; + response.parm.length = len; + bcs->cs->iif.statcallb(&response); + } +} +EXPORT_SYMBOL_GPL(gigaset_skb_sent); + +/* This function will be called by LL to send commands + * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL, + * so don't put too much effort into it. + */ +static int command_from_LL(isdn_ctrl *cntrl) +{ + struct cardstate *cs = gigaset_get_cs_by_id(cntrl->driver); + //isdn_ctrl response; + //unsigned long flags; + struct bc_state *bcs; + int retval = 0; + struct setup_parm *sp; + + //dbg(DEBUG_ANY, "Gigaset_HW: Receiving command"); + gigaset_debugdrivers(); + + /* Terminate this call if no device is present. Bt if the command is "ISDN_CMD_LOCK" or + * "ISDN_CMD_UNLOCK" then execute it due to the fact that they are device independent ! + */ + //FIXME "remove test for &connected" + if ((!cs || !atomic_read(&cs->connected))) { + warn("LL tried to access unknown device with nr. %d", + cntrl->driver); + return -ENODEV; + } + + switch (cntrl->command) { + case ISDN_CMD_IOCTL: + + dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver:%d,arg: %ld)", + cntrl->driver, cntrl->arg); + + warn("ISDN_CMD_IOCTL is not supported."); + return -EINVAL; + + case ISDN_CMD_DIAL: + dbg(DEBUG_ANY, "ISDN_CMD_DIAL (driver: %d, channel: %ld, " + "phone: %s,ownmsn: %s, si1: %d, si2: %d)", + cntrl->driver, cntrl->arg, + cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, + cntrl->parm.setup.si1, cntrl->parm.setup.si2); + + if (cntrl->arg >= cs->channels) { + err("invalid channel (%d)", (int) cntrl->arg); + return -EINVAL; + } + + bcs = cs->bcs + cntrl->arg; + + if (!gigaset_get_channel(bcs)) { + err("channel not free"); + return -EBUSY; + } + + sp = kmalloc(sizeof *sp, GFP_ATOMIC); + if (!sp) { + gigaset_free_channel(bcs); + err("ISDN_CMD_DIAL: out of memory"); + return -ENOMEM; + } + *sp = cntrl->parm.setup; + + if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, + atomic_read(&bcs->at_state.seq_index), + NULL)) { + //FIXME what should we do? + kfree(sp); + gigaset_free_channel(bcs); + return -ENOMEM; + } + + dbg(DEBUG_CMD, "scheduling DIAL"); + gigaset_schedule_event(cs); + break; + case ISDN_CMD_ACCEPTD: //FIXME + dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD"); + + if (cntrl->arg >= cs->channels) { + err("invalid channel (%d)", (int) cntrl->arg); + return -EINVAL; + } + + if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, + EV_ACCEPT, NULL, 0, NULL)) { + //FIXME what should we do? + return -ENOMEM; + } + + dbg(DEBUG_CMD, "scheduling ACCEPT"); + gigaset_schedule_event(cs); + + break; + case ISDN_CMD_ACCEPTB: + dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB"); + break; + case ISDN_CMD_HANGUP: + dbg(DEBUG_ANY, + "ISDN_CMD_HANGUP (channel: %d)", (int) cntrl->arg); + + if (cntrl->arg >= cs->channels) { + err("ISDN_CMD_HANGUP: invalid channel (%u)", + (unsigned) cntrl->arg); + return -EINVAL; + } + + if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, + EV_HUP, NULL, 0, NULL)) { + //FIXME what should we do? + return -ENOMEM; + } + + dbg(DEBUG_CMD, "scheduling HUP"); + gigaset_schedule_event(cs); + + break; + case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME + dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ"); + break; + case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME + dbg(DEBUG_ANY, + "ISDN_CMD_SETEAZ (id:%d, channel: %ld, number: %s)", + cntrl->driver, cntrl->arg, cntrl->parm.num); + break; + case ISDN_CMD_SETL2: /* Set L2 to given protocol */ + dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (Channel: %ld, Proto: %lx)", + cntrl->arg & 0xff, (cntrl->arg >> 8)); + + if ((cntrl->arg & 0xff) >= cs->channels) { + err("invalid channel (%u)", + (unsigned) cntrl->arg & 0xff); + return -EINVAL; + } + + if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state, + EV_PROTO_L2, NULL, cntrl->arg >> 8, + NULL)) { + //FIXME what should we do? + return -ENOMEM; + } + + dbg(DEBUG_CMD, "scheduling PROTO_L2"); + gigaset_schedule_event(cs); + break; + case ISDN_CMD_SETL3: /* Set L3 to given protocol */ + dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (Channel: %ld, Proto: %lx)", + cntrl->arg & 0xff, (cntrl->arg >> 8)); + + if ((cntrl->arg & 0xff) >= cs->channels) { + err("invalid channel (%u)", + (unsigned) cntrl->arg & 0xff); + return -EINVAL; + } + + if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) { + err("invalid protocol %lu", cntrl->arg >> 8); + return -EINVAL; + } + + break; + case ISDN_CMD_PROCEED: + dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME + break; + case ISDN_CMD_ALERT: + dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME + if (cntrl->arg >= cs->channels) { + err("invalid channel (%d)", (int) cntrl->arg); + return -EINVAL; + } + //bcs = cs->bcs + cntrl->arg; + //bcs->proto2 = -1; + // FIXME + break; + case ISDN_CMD_REDIR: + dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME + break; + case ISDN_CMD_PROT_IO: + dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); + break; + case ISDN_CMD_FAXCMD: + dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD"); + break; + case ISDN_CMD_GETL2: + dbg(DEBUG_ANY, "ISDN_CMD_GETL2"); + break; + case ISDN_CMD_GETL3: + dbg(DEBUG_ANY, "ISDN_CMD_GETL3"); + break; + case ISDN_CMD_GETEAZ: + dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ"); + break; + case ISDN_CMD_SETSIL: + dbg(DEBUG_ANY, "ISDN_CMD_SETSIL"); + break; + case ISDN_CMD_GETSIL: + dbg(DEBUG_ANY, "ISDN_CMD_GETSIL"); + break; + default: + err("unknown command %d from LL", + cntrl->command); + return -EINVAL; + } + + return retval; +} + +void gigaset_i4l_cmd(struct cardstate *cs, int cmd) +{ + isdn_ctrl command; + + command.driver = cs->myid; + command.command = cmd; + command.arg = 0; + cs->iif.statcallb(&command); +} + +void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd) +{ + isdn_ctrl command; + + command.driver = bcs->cs->myid; + command.command = cmd; + command.arg = bcs->channel; + bcs->cs->iif.statcallb(&command); +} + +int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data) +{ + struct bc_state *bcs = at_state->bcs; + unsigned proto; + const char *bc; + size_t length[AT_NUM]; + size_t l; + int i; + struct setup_parm *sp = data; + + switch (bcs->proto2) { + case ISDN_PROTO_L2_HDLC: + proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */ + break; + case ISDN_PROTO_L2_TRANS: + proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ + break; + default: + err("invalid protocol: %u", bcs->proto2); + return -EINVAL; + } + + switch (sp->si1) { + case 1: /* audio */ + bc = "9090A3"; /* 3.1 kHz audio, A-law */ + break; + case 7: /* data */ + default: /* hope the app knows what it is doing */ + bc = "8890"; /* unrestricted digital information */ + } + //FIXME add missing si1 values from 1TR6, inspect si2, set HLC/LLC + + length[AT_DIAL ] = 1 + strlen(sp->phone) + 1 + 1; + l = strlen(sp->eazmsn); + length[AT_MSN ] = l ? 6 + l + 1 + 1 : 0; + length[AT_BC ] = 5 + strlen(bc) + 1 + 1; + length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */ + length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */ + length[AT_TYPE ] = 6 + 1 + 1 + 1; /* call type: 1 character */ + length[AT_HLC ] = 0; + + for (i = 0; i < AT_NUM; ++i) { + kfree(bcs->commands[i]); + bcs->commands[i] = NULL; + if (length[i] && + !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { + err("out of memory"); + return -ENOMEM; + } + } + + /* type = 1: extern, 0: intern, 2: recall, 3: door, 4: centrex */ + if (sp->phone[0] == '*' && sp->phone[1] == '*') { + /* internal call: translate ** prefix to CTP value */ + snprintf(bcs->commands[AT_DIAL], length[AT_DIAL], + "D%s\r", sp->phone+2); + strncpy(bcs->commands[AT_TYPE], "^SCTP=0\r", length[AT_TYPE]); + } else { + snprintf(bcs->commands[AT_DIAL], length[AT_DIAL], + "D%s\r", sp->phone); + strncpy(bcs->commands[AT_TYPE], "^SCTP=1\r", length[AT_TYPE]); + } + + if (bcs->commands[AT_MSN]) + snprintf(bcs->commands[AT_MSN], length[AT_MSN], "^SMSN=%s\r", sp->eazmsn); + snprintf(bcs->commands[AT_BC ], length[AT_BC ], "^SBC=%s\r", bc); + snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto); + snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned)bcs->channel + 1); + + return 0; +} + +int gigaset_isdn_setup_accept(struct at_state_t *at_state) +{ + unsigned proto; + size_t length[AT_NUM]; + int i; + struct bc_state *bcs = at_state->bcs; + + switch (bcs->proto2) { + case ISDN_PROTO_L2_HDLC: + proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */ + break; + case ISDN_PROTO_L2_TRANS: + proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ + break; + default: + err("invalid protocol: %u", bcs->proto2); + return -EINVAL; + } + + length[AT_DIAL ] = 0; + length[AT_MSN ] = 0; + length[AT_BC ] = 0; + length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */ + length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */ + length[AT_TYPE ] = 0; + length[AT_HLC ] = 0; + + for (i = 0; i < AT_NUM; ++i) { + kfree(bcs->commands[i]); + bcs->commands[i] = NULL; + if (length[i] && + !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { + err("out of memory"); + return -ENOMEM; + } + } + + snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto); + snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned) bcs->channel + 1); + + return 0; +} + +int gigaset_isdn_icall(struct at_state_t *at_state) +{ + struct cardstate *cs = at_state->cs; + struct bc_state *bcs = at_state->bcs; + isdn_ctrl response; + int retval; + + /* fill ICALL structure */ + response.parm.setup.si1 = 0; /* default: unknown */ + response.parm.setup.si2 = 0; + response.parm.setup.screen = 0; //FIXME how to set these? + response.parm.setup.plan = 0; + if (!at_state->str_var[STR_ZBC]) { + /* no BC (internal call): assume speech, A-law */ + response.parm.setup.si1 = 1; + } else if (!strcmp(at_state->str_var[STR_ZBC], "8890")) { + /* unrestricted digital information */ + response.parm.setup.si1 = 7; + } else if (!strcmp(at_state->str_var[STR_ZBC], "8090A3")) { + /* speech, A-law */ + response.parm.setup.si1 = 1; + } else if (!strcmp(at_state->str_var[STR_ZBC], "9090A3")) { + /* 3,1 kHz audio, A-law */ + response.parm.setup.si1 = 1; + response.parm.setup.si2 = 2; + } else { + warn("RING ignored - unsupported BC %s", + at_state->str_var[STR_ZBC]); + return ICALL_IGNORE; + } + if (at_state->str_var[STR_NMBR]) { + strncpy(response.parm.setup.phone, at_state->str_var[STR_NMBR], + sizeof response.parm.setup.phone - 1); + response.parm.setup.phone[sizeof response.parm.setup.phone - 1] = 0; + } else + response.parm.setup.phone[0] = 0; + if (at_state->str_var[STR_ZCPN]) { + strncpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN], + sizeof response.parm.setup.eazmsn - 1); + response.parm.setup.eazmsn[sizeof response.parm.setup.eazmsn - 1] = 0; + } else + response.parm.setup.eazmsn[0] = 0; + + if (!bcs) { + notice("no channel for incoming call"); + dbg(DEBUG_CMD, "Sending ICALLW"); + response.command = ISDN_STAT_ICALLW; + response.arg = 0; //FIXME + } else { + dbg(DEBUG_CMD, "Sending ICALL"); + response.command = ISDN_STAT_ICALL; + response.arg = bcs->channel; //FIXME + } + response.driver = cs->myid; + retval = cs->iif.statcallb(&response); + dbg(DEBUG_CMD, "Response: %d", retval); + switch (retval) { + case 0: /* no takers */ + return ICALL_IGNORE; + case 1: /* alerting */ + bcs->chstate |= CHS_NOTIFY_LL; + return ICALL_ACCEPT; + case 2: /* reject */ + return ICALL_REJECT; + case 3: /* incomplete */ + warn("LL requested unsupported feature: Incomplete Number"); + return ICALL_IGNORE; + case 4: /* proceeding */ + /* Gigaset will send ALERTING anyway. + * There doesn't seem to be a way to avoid this. + */ + return ICALL_ACCEPT; + case 5: /* deflect */ + warn("LL requested unsupported feature: Call Deflection"); + return ICALL_IGNORE; + default: + err("LL error %d on ICALL", retval); + return ICALL_IGNORE; + } +} + +/* Set Callback function pointer */ +int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) +{ + isdn_if *iif = &cs->iif; + + dbg(DEBUG_ANY, "Register driver capabilities to LL"); + + //iif->id[sizeof(iif->id) - 1]=0; + //strncpy(iif->id, isdnid, sizeof(iif->id) - 1); + if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index) + >= sizeof iif->id) + return -ENOMEM; //FIXME EINVAL/...?? + + iif->owner = THIS_MODULE; + iif->channels = cs->channels; /* I am supporting just one channel *//* I was supporting...*/ + iif->maxbufsize = MAX_BUF_SIZE; + iif->features = ISDN_FEATURE_L2_TRANS | /* Our device is very advanced, therefore */ + ISDN_FEATURE_L2_HDLC | +#ifdef GIG_X75 + ISDN_FEATURE_L2_X75I | +#endif + ISDN_FEATURE_L3_TRANS | + ISDN_FEATURE_P_EURO; + iif->hl_hdrlen = HW_HDR_LEN; /* Area for storing ack */ + iif->command = command_from_LL; + iif->writebuf_skb = writebuf_from_LL; + iif->writecmd = NULL; /* Don't support isdnctrl */ + iif->readstat = NULL; /* Don't support isdnctrl */ + iif->rcvcallb_skb = NULL; /* Will be set by LL */ + iif->statcallb = NULL; /* Will be set by LL */ + + if (!register_isdn(iif)) + return 0; + + cs->myid = iif->channels; /* Set my device id */ + return 1; +} -- cgit v1.2.3-59-g8ed1b From ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0 Mon Sep 17 00:00:00 2001 From: Hansjoerg Lipp Date: Sun, 26 Mar 2006 01:38:32 -0800 Subject: [PATCH] isdn4linux: Siemens Gigaset drivers - tty interface And: Tilman Schmidt This patch adds the tty interface to the gigaset module. The tty interface provides direct access to the AT command set of the Gigaset devices. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Cc: Karsten Keil Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/gigaset/interface.c | 718 +++++++++++++++++++++++++++++++++++++++ include/linux/gigaset_dev.h | 32 ++ 2 files changed, 750 insertions(+) create mode 100644 drivers/isdn/gigaset/interface.c create mode 100644 include/linux/gigaset_dev.h (limited to 'drivers') diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c new file mode 100644 index 000000000000..3a81d9c65141 --- /dev/null +++ b/drivers/isdn/gigaset/interface.c @@ -0,0 +1,718 @@ +/* + * interface to user space for the gigaset driver + * + * Copyright (c) 2004 by Hansjoerg Lipp + * + * ===================================================================== + * 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. + * ===================================================================== + * Version: $Id: interface.c,v 1.14.4.15 2006/02/04 18:28:16 hjlipp Exp $ + * ===================================================================== + */ + +#include "gigaset.h" +#include +#include +#include + +/*** our ioctls ***/ + +static int if_lock(struct cardstate *cs, int *arg) +{ + int cmd = *arg; + + dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd); + + if (cmd > 1) + return -EINVAL; + + if (cmd < 0) { + *arg = atomic_read(&cs->mstate) == MS_LOCKED; //FIXME remove? + return 0; + } + + if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED + && atomic_read(&cs->connected)) { + cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); + cs->ops->baud_rate(cs, B115200); + cs->ops->set_line_ctrl(cs, CS8); + cs->control_state = TIOCM_DTR|TIOCM_RTS; + } + + cs->waiting = 1; + if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK, + NULL, cmd, NULL)) { + cs->waiting = 0; + return -ENOMEM; + } + + dbg(DEBUG_CMD, "scheduling IF_LOCK"); + gigaset_schedule_event(cs); + + wait_event(cs->waitqueue, !cs->waiting); + + if (cs->cmd_result >= 0) { + *arg = cs->cmd_result; + return 0; + } + + return cs->cmd_result; +} + +static int if_version(struct cardstate *cs, unsigned arg[4]) +{ + static const unsigned version[4] = GIG_VERSION; + static const unsigned compat[4] = GIG_COMPAT; + unsigned cmd = arg[0]; + + dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd); + + switch (cmd) { + case GIGVER_DRIVER: + memcpy(arg, version, sizeof version); + return 0; + case GIGVER_COMPAT: + memcpy(arg, compat, sizeof compat); + return 0; + case GIGVER_FWBASE: + cs->waiting = 1; + if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER, + NULL, 0, arg)) { + cs->waiting = 0; + return -ENOMEM; + } + + dbg(DEBUG_CMD, "scheduling IF_VER"); + gigaset_schedule_event(cs); + + wait_event(cs->waitqueue, !cs->waiting); + + if (cs->cmd_result >= 0) + return 0; + + return cs->cmd_result; + default: + return -EINVAL; + } +} + +static int if_config(struct cardstate *cs, int *arg) +{ + dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg); + + if (*arg != 1) + return -EINVAL; + + if (atomic_read(&cs->mstate) != MS_LOCKED) + return -EBUSY; + + *arg = 0; + return gigaset_enterconfigmode(cs); +} + +/*** the terminal driver ***/ +/* stolen from usbserial and some other tty drivers */ + +static int if_open(struct tty_struct *tty, struct file *filp); +static void if_close(struct tty_struct *tty, struct file *filp); +static int if_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); +static int if_write_room(struct tty_struct *tty); +static int if_chars_in_buffer(struct tty_struct *tty); +static void if_throttle(struct tty_struct *tty); +static void if_unthrottle(struct tty_struct *tty); +static void if_set_termios(struct tty_struct *tty, struct termios *old); +static int if_tiocmget(struct tty_struct *tty, struct file *file); +static int if_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); +static int if_write(struct tty_struct *tty, + const unsigned char *buf, int count); + +static struct tty_operations if_ops = { + .open = if_open, + .close = if_close, + .ioctl = if_ioctl, + .write = if_write, + .write_room = if_write_room, + .chars_in_buffer = if_chars_in_buffer, + .set_termios = if_set_termios, + .throttle = if_throttle, + .unthrottle = if_unthrottle, +#if 0 + .break_ctl = serial_break, +#endif + .tiocmget = if_tiocmget, + .tiocmset = if_tiocmset, +}; + +static int if_open(struct tty_struct *tty, struct file *filp) +{ + struct cardstate *cs; + unsigned long flags; + + dbg(DEBUG_IF, "%d+%d: %s()", tty->driver->minor_start, tty->index, + __FUNCTION__); + + tty->driver_data = NULL; + + cs = gigaset_get_cs_by_tty(tty); + if (!cs) + return -ENODEV; + + if (down_interruptible(&cs->sem)) + return -ERESTARTSYS; // FIXME -EINTR? + tty->driver_data = cs; + + ++cs->open_count; + + if (cs->open_count == 1) { + spin_lock_irqsave(&cs->lock, flags); + cs->tty = tty; + spin_unlock_irqrestore(&cs->lock, flags); + tty->low_latency = 1; //FIXME test + //FIXME + } + + up(&cs->sem); + return 0; +} + +static void if_close(struct tty_struct *tty, struct file *filp) +{ + struct cardstate *cs; + unsigned long flags; + + cs = (struct cardstate *) tty->driver_data; + if (!cs) { + err("cs==NULL in %s", __FUNCTION__); + return; + } + + dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + + down(&cs->sem); + + if (!cs->open_count) + warn("%s: device not opened", __FUNCTION__); + else { + if (!--cs->open_count) { + spin_lock_irqsave(&cs->lock, flags); + cs->tty = NULL; + spin_unlock_irqrestore(&cs->lock, flags); + //FIXME + } + } + + up(&cs->sem); +} + +static int if_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct cardstate *cs; + int retval = -ENODEV; + int int_arg; + unsigned char buf[6]; + unsigned version[4]; + + cs = (struct cardstate *) tty->driver_data; + if (!cs) { + err("cs==NULL in %s", __FUNCTION__); + return -ENODEV; + } + + dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __FUNCTION__, cmd); + + if (down_interruptible(&cs->sem)) + return -ERESTARTSYS; // FIXME -EINTR? + + if (!cs->open_count) + warn("%s: device not opened", __FUNCTION__); + else { + retval = 0; + switch (cmd) { + case GIGASET_REDIR: + retval = get_user(int_arg, (int __user *) arg); + if (retval >= 0) + retval = if_lock(cs, &int_arg); + if (retval >= 0) + retval = put_user(int_arg, (int __user *) arg); + break; + case GIGASET_CONFIG: + retval = get_user(int_arg, (int __user *) arg); + if (retval >= 0) + retval = if_config(cs, &int_arg); + if (retval >= 0) + retval = put_user(int_arg, (int __user *) arg); + break; + case GIGASET_BRKCHARS: + //FIXME test if MS_LOCKED + gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS", + 6, (const unsigned char *) arg, 1); + if (!atomic_read(&cs->connected)) { + dbg(DEBUG_ANY, "can't communicate with unplugged device"); + retval = -ENODEV; + break; + } + retval = copy_from_user(&buf, + (const unsigned char __user *) arg, 6) + ? -EFAULT : 0; + if (retval >= 0) + retval = cs->ops->brkchars(cs, buf); + break; + case GIGASET_VERSION: + retval = copy_from_user(version, (unsigned __user *) arg, + sizeof version) ? -EFAULT : 0; + if (retval >= 0) + retval = if_version(cs, version); + if (retval >= 0) + retval = copy_to_user((unsigned __user *) arg, version, + sizeof version) + ? -EFAULT : 0; + break; + default: + dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x", + __FUNCTION__, cmd); + retval = -ENOIOCTLCMD; + } + } + + up(&cs->sem); + + return retval; +} + +static int if_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct cardstate *cs; + int retval; + + cs = (struct cardstate *) tty->driver_data; + if (!cs) { + err("cs==NULL in %s", __FUNCTION__); + return -ENODEV; + } + + dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + + if (down_interruptible(&cs->sem)) + return -ERESTARTSYS; // FIXME -EINTR? + + // FIXME read from device? + retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR); + + up(&cs->sem); + + return retval; +} + +static int if_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct cardstate *cs; + int retval; + unsigned mc; + + cs = (struct cardstate *) tty->driver_data; + if (!cs) { + err("cs==NULL in %s", __FUNCTION__); + return -ENODEV; + } + + dbg(DEBUG_IF, + "%u: %s(0x%x, 0x%x)", cs->minor_index, __FUNCTION__, set, clear); + + if (down_interruptible(&cs->sem)) + return -ERESTARTSYS; // FIXME -EINTR? + + if (!atomic_read(&cs->connected)) { + dbg(DEBUG_ANY, "can't communicate with unplugged device"); + retval = -ENODEV; + } else { + mc = (cs->control_state | set) & ~clear & (TIOCM_RTS|TIOCM_DTR); + retval = cs->ops->set_modem_ctrl(cs, cs->control_state, mc); + cs->control_state = mc; + } + + up(&cs->sem); + + return retval; +} + +static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + struct cardstate *cs; + int retval = -ENODEV; + + cs = (struct cardstate *) tty->driver_data; + if (!cs) { + err("cs==NULL in %s", __FUNCTION__); + return -ENODEV; + } + + dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + + if (down_interruptible(&cs->sem)) + return -ERESTARTSYS; // FIXME -EINTR? + + if (!cs->open_count) + warn("%s: device not opened", __FUNCTION__); + else if (atomic_read(&cs->mstate) != MS_LOCKED) { + warn("can't write to unlocked device"); + retval = -EBUSY; + } else if (!atomic_read(&cs->connected)) { + dbg(DEBUG_ANY, "can't write to unplugged device"); + retval = -EBUSY; //FIXME + } else { + retval = cs->ops->write_cmd(cs, buf, count, + &cs->if_wake_tasklet); + } + + up(&cs->sem); + + return retval; +} + +static int if_write_room(struct tty_struct *tty) +{ + struct cardstate *cs; + int retval = -ENODEV; + + cs = (struct cardstate *) tty->driver_data; + if (!cs) { + err("cs==NULL in %s", __FUNCTION__); + return -ENODEV; + } + + dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + + if (down_interruptible(&cs->sem)) + return -ERESTARTSYS; // FIXME -EINTR? + + if (!cs->open_count) + warn("%s: device not opened", __FUNCTION__); + else if (atomic_read(&cs->mstate) != MS_LOCKED) { + warn("can't write to unlocked device"); + retval = -EBUSY; //FIXME + } else if (!atomic_read(&cs->connected)) { + dbg(DEBUG_ANY, "can't write to unplugged device"); + retval = -EBUSY; //FIXME + } else + retval = cs->ops->write_room(cs); + + up(&cs->sem); + + return retval; +} + +static int if_chars_in_buffer(struct tty_struct *tty) +{ + struct cardstate *cs; + int retval = -ENODEV; + + cs = (struct cardstate *) tty->driver_data; + if (!cs) { + err("cs==NULL in %s", __FUNCTION__); + return -ENODEV; + } + + dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + + if (down_interruptible(&cs->sem)) + return -ERESTARTSYS; // FIXME -EINTR? + + if (!cs->open_count) + warn("%s: device not opened", __FUNCTION__); + else if (atomic_read(&cs->mstate) != MS_LOCKED) { + warn("can't write to unlocked device"); + retval = -EBUSY; + } else if (!atomic_read(&cs->connected)) { + dbg(DEBUG_ANY, "can't write to unplugged device"); + retval = -EBUSY; //FIXME + } else + retval = cs->ops->chars_in_buffer(cs); + + up(&cs->sem); + + return retval; +} + +static void if_throttle(struct tty_struct *tty) +{ + struct cardstate *cs; + + cs = (struct cardstate *) tty->driver_data; + if (!cs) { + err("cs==NULL in %s", __FUNCTION__); + return; + } + + dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + + down(&cs->sem); + + if (!cs->open_count) + warn("%s: device not opened", __FUNCTION__); + else { + //FIXME + } + + up(&cs->sem); +} + +static void if_unthrottle(struct tty_struct *tty) +{ + struct cardstate *cs; + + cs = (struct cardstate *) tty->driver_data; + if (!cs) { + err("cs==NULL in %s", __FUNCTION__); + return; + } + + dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + + down(&cs->sem); + + if (!cs->open_count) + warn("%s: device not opened", __FUNCTION__); + else { + //FIXME + } + + up(&cs->sem); +} + +static void if_set_termios(struct tty_struct *tty, struct termios *old) +{ + struct cardstate *cs; + unsigned int iflag; + unsigned int cflag; + unsigned int old_cflag; + unsigned int control_state, new_state; + + cs = (struct cardstate *) tty->driver_data; + if (!cs) { + err("cs==NULL in %s", __FUNCTION__); + return; + } + + dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + + down(&cs->sem); + + if (!cs->open_count) { + warn("%s: device not opened", __FUNCTION__); + goto out; + } + + if (!atomic_read(&cs->connected)) { + dbg(DEBUG_ANY, "can't communicate with unplugged device"); + goto out; + } + + // stolen from mct_u232.c + iflag = tty->termios->c_iflag; + cflag = tty->termios->c_cflag; + old_cflag = old ? old->c_cflag : cflag; //FIXME? + dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", cs->minor_index, + iflag, cflag, old_cflag); + + /* get a local copy of the current port settings */ + control_state = cs->control_state; + + /* + * Update baud rate. + * Do not attempt to cache old rates and skip settings, + * disconnects screw such tricks up completely. + * Premature optimization is the root of all evil. + */ + + /* reassert DTR and (maybe) RTS on transition from B0 */ + if ((old_cflag & CBAUD) == B0) { + new_state = control_state | TIOCM_DTR; + /* don't set RTS if using hardware flow control */ + if (!(old_cflag & CRTSCTS)) + new_state |= TIOCM_RTS; + dbg(DEBUG_IF, "%u: from B0 - set DTR%s", cs->minor_index, + (new_state & TIOCM_RTS) ? " only" : "/RTS"); + cs->ops->set_modem_ctrl(cs, control_state, new_state); + control_state = new_state; + } + + cs->ops->baud_rate(cs, cflag & CBAUD); + + if ((cflag & CBAUD) == B0) { + /* Drop RTS and DTR */ + dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index); + new_state = control_state & ~(TIOCM_DTR | TIOCM_RTS); + cs->ops->set_modem_ctrl(cs, control_state, new_state); + control_state = new_state; + } + + /* + * Update line control register (LCR) + */ + + cs->ops->set_line_ctrl(cs, cflag); + +#if 0 + //FIXME this hangs M101 [ts 2005-03-09] + //FIXME do we need this? + /* + * Set flow control: well, I do not really now how to handle DTR/RTS. + * Just do what we have seen with SniffUSB on Win98. + */ + /* Drop DTR/RTS if no flow control otherwise assert */ + dbg(DEBUG_IF, "%u: control_state %x", cs->minor_index, control_state); + new_state = control_state; + if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS)) + new_state |= TIOCM_DTR | TIOCM_RTS; + else + new_state &= ~(TIOCM_DTR | TIOCM_RTS); + if (new_state != control_state) { + dbg(DEBUG_IF, "%u: new_state %x", cs->minor_index, new_state); + gigaset_set_modem_ctrl(cs, control_state, new_state); // FIXME: mct_u232.c sets the old state here. is this a bug? + control_state = new_state; + } +#endif + + /* save off the modified port settings */ + cs->control_state = control_state; + +out: + up(&cs->sem); +} + + +/* wakeup tasklet for the write operation */ +static void if_wake(unsigned long data) +{ + struct cardstate *cs = (struct cardstate *) data; + struct tty_struct *tty; + + tty = cs->tty; + if (!tty) + return; + + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) { + dbg(DEBUG_IF, "write wakeup call"); + tty->ldisc.write_wakeup(tty); + } + + wake_up_interruptible(&tty->write_wait); +} + +/*** interface to common ***/ + +void gigaset_if_init(struct cardstate *cs) +{ + struct gigaset_driver *drv; + + drv = cs->driver; + if (!drv->have_tty) + return; + + tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs); + tty_register_device(drv->tty, cs->minor_index, NULL); +} + +void gigaset_if_free(struct cardstate *cs) +{ + struct gigaset_driver *drv; + + drv = cs->driver; + if (!drv->have_tty) + return; + + tasklet_disable(&cs->if_wake_tasklet); + tasklet_kill(&cs->if_wake_tasklet); + tty_unregister_device(drv->tty, cs->minor_index); +} + +void gigaset_if_receive(struct cardstate *cs, + unsigned char *buffer, size_t len) +{ + unsigned long flags; + struct tty_struct *tty; + + spin_lock_irqsave(&cs->lock, flags); + if ((tty = cs->tty) == NULL) + dbg(DEBUG_ANY, "receive on closed device"); + else { + tty_buffer_request_room(tty, len); + tty_insert_flip_string(tty, buffer, len); + tty_flip_buffer_push(tty); + } + spin_unlock_irqrestore(&cs->lock, flags); +} +EXPORT_SYMBOL_GPL(gigaset_if_receive); + +/* gigaset_if_initdriver + * Initialize tty interface. + * parameters: + * drv Driver + * procname Name of the driver (e.g. for /proc/tty/drivers) + * devname Name of the device files (prefix without minor number) + * devfsname Devfs name of the device files without %d + */ +void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, + const char *devname, const char *devfsname) +{ + unsigned minors = drv->minors; + int ret; + struct tty_driver *tty; + + drv->have_tty = 0; + + if ((drv->tty = alloc_tty_driver(minors)) == NULL) + goto enomem; + tty = drv->tty; + + tty->magic = TTY_DRIVER_MAGIC, + tty->major = GIG_MAJOR, + tty->type = TTY_DRIVER_TYPE_SERIAL, + tty->subtype = SERIAL_TYPE_NORMAL, + tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS, + + tty->driver_name = procname; + tty->name = devname; + tty->minor_start = drv->minor; + tty->num = drv->minors; + + tty->owner = THIS_MODULE; + tty->devfs_name = devfsname; + + tty->init_termios = tty_std_termios; //FIXME + tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; //FIXME + tty_set_operations(tty, &if_ops); + + ret = tty_register_driver(tty); + if (ret < 0) { + warn("failed to register tty driver (error %d)", ret); + goto error; + } + dbg(DEBUG_IF, "tty driver initialized"); + drv->have_tty = 1; + return; + +enomem: + warn("could not allocate tty structures"); +error: + if (drv->tty) + put_tty_driver(drv->tty); +} + +void gigaset_if_freedriver(struct gigaset_driver *drv) +{ + if (!drv->have_tty) + return; + + drv->have_tty = 0; + tty_unregister_driver(drv->tty); + put_tty_driver(drv->tty); +} diff --git a/include/linux/gigaset_dev.h b/include/linux/gigaset_dev.h new file mode 100644 index 000000000000..70ad09c8ad1e --- /dev/null +++ b/include/linux/gigaset_dev.h @@ -0,0 +1,32 @@ +/* + * interface to user space for the gigaset driver + * + * Copyright (c) 2004 by Hansjoerg Lipp + * + * ===================================================================== + * 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. + * ===================================================================== + * Version: $Id: gigaset_dev.h,v 1.4.4.4 2005/11/21 22:28:09 hjlipp Exp $ + * ===================================================================== + */ + +#ifndef GIGASET_INTERFACE_H +#define GIGASET_INTERFACE_H + +#include + +#define GIGASET_IOCTL 0x47 + +#define GIGVER_DRIVER 0 +#define GIGVER_COMPAT 1 +#define GIGVER_FWBASE 2 + +#define GIGASET_REDIR _IOWR (GIGASET_IOCTL, 0, int) +#define GIGASET_CONFIG _IOWR (GIGASET_IOCTL, 1, int) +#define GIGASET_BRKCHARS _IOW (GIGASET_IOCTL, 2, unsigned char[6]) //FIXME [6] okay? +#define GIGASET_VERSION _IOWR (GIGASET_IOCTL, 3, unsigned[4]) + +#endif -- cgit v1.2.3-59-g8ed1b From 982da5a196a0859eedc5ca1ff88feaf1bc6d6e4e Mon Sep 17 00:00:00 2001 From: Hansjoerg Lipp Date: Sun, 26 Mar 2006 01:38:33 -0800 Subject: [PATCH] isdn4linux: Siemens Gigaset drivers - procfs interface And: Tilman Schmidt This patch adds the procfs interface to the gigaset module. The procfs interface provides access to status information and statistics about the Gigaset devices. If the drivers are built with the debugging option it also allows to change the amount of debugging output on the fly. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Cc: Karsten Keil Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/gigaset/proc.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 drivers/isdn/gigaset/proc.c (limited to 'drivers') diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c new file mode 100644 index 000000000000..c6915fa2be6c --- /dev/null +++ b/drivers/isdn/gigaset/proc.c @@ -0,0 +1,81 @@ +/* + * Stuff used by all variants of the driver + * + * Copyright (c) 2001 by Stefan Eilers , + * Hansjoerg Lipp , + * Tilman Schmidt . + * + * ===================================================================== + * 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. + * ===================================================================== + * ToDo: ... + * ===================================================================== + * Version: $Id: proc.c,v 1.5.2.13 2006/02/04 18:28:16 hjlipp Exp $ + * ===================================================================== + */ + +#include "gigaset.h" +#include + +static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct cardstate *cs = usb_get_intfdata(intf); + return sprintf(buf, "%d\n", atomic_read(&cs->cidmode)); // FIXME use scnprintf for 13607 bit architectures (if PAGE_SIZE==4096) +} + +static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct cardstate *cs = usb_get_intfdata(intf); + long int value; + char *end; + + value = simple_strtol(buf, &end, 0); + while (*end) + if (!isspace(*end++)) + return -EINVAL; + if (value < 0 || value > 1) + return -EINVAL; + + if (down_interruptible(&cs->sem)) + return -ERESTARTSYS; // FIXME -EINTR? + + cs->waiting = 1; + if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE, + NULL, value, NULL)) { + cs->waiting = 0; + up(&cs->sem); + return -ENOMEM; + } + + dbg(DEBUG_CMD, "scheduling PROC_CIDMODE"); + gigaset_schedule_event(cs); + + wait_event(cs->waitqueue, !cs->waiting); + + up(&cs->sem); + + return count; +} + +static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode); + +/* free sysfs for device */ +void gigaset_free_dev_sysfs(struct usb_interface *interface) +{ + dbg(DEBUG_INIT, "removing sysfs entries"); + device_remove_file(&interface->dev, &dev_attr_cidmode); +} +EXPORT_SYMBOL_GPL(gigaset_free_dev_sysfs); + +/* initialize sysfs for device */ +void gigaset_init_dev_sysfs(struct usb_interface *interface) +{ + dbg(DEBUG_INIT, "setting up sysfs"); + device_create_file(&interface->dev, &dev_attr_cidmode); +} +EXPORT_SYMBOL_GPL(gigaset_init_dev_sysfs); -- cgit v1.2.3-59-g8ed1b From cf7776dc05b89885a7ec6beff8409d48b077a3ac Mon Sep 17 00:00:00 2001 From: Hansjoerg Lipp Date: Sun, 26 Mar 2006 01:38:34 -0800 Subject: [PATCH] isdn4linux: Siemens Gigaset drivers - direct USB connection And: Tilman Schmidt This patch adds the main source file of the connection-specific module "bas_gigaset", the hardware driver for Gigaset base stations connected directly to the computer via USB. It contains the code for handling probe/disconnect, AT command/response transmission, and call setup and termination. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Cc: Karsten Keil Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/gigaset/bas-gigaset.c | 2365 ++++++++++++++++++++++++++++++++++++ 1 file changed, 2365 insertions(+) create mode 100644 drivers/isdn/gigaset/bas-gigaset.c (limited to 'drivers') diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c new file mode 100644 index 000000000000..31f0f07832bc --- /dev/null +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -0,0 +1,2365 @@ +/* + * USB driver for Gigaset 307x base via direct USB connection. + * + * Copyright (c) 2001 by Hansjoerg Lipp , + * Tilman Schmidt , + * Stefan Eilers . + * + * Based on usb-gigaset.c. + * + * ===================================================================== + * 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. + * ===================================================================== + * ToDo: ... + * ===================================================================== + * Version: $Id: bas-gigaset.c,v 1.52.4.19 2006/02/04 18:28:16 hjlipp Exp $ + * ===================================================================== + */ + +#include "gigaset.h" + +#include +#include +#include +#include +#include +#include +#include + +/* Version Information */ +#define DRIVER_AUTHOR "Tilman Schmidt , Hansjoerg Lipp , Stefan Eilers " +#define DRIVER_DESC "USB Driver for Gigaset 307x" + + +/* Module parameters */ + +static int startmode = SM_ISDN; +static int cidmode = 1; + +module_param(startmode, int, S_IRUGO); +module_param(cidmode, int, S_IRUGO); +MODULE_PARM_DESC(startmode, "start in isdn4linux mode"); +MODULE_PARM_DESC(cidmode, "Call-ID mode"); + +#define GIGASET_MINORS 1 +#define GIGASET_MINOR 16 +#define GIGASET_MODULENAME "bas_gigaset" +#define GIGASET_DEVFSNAME "gig/bas/" +#define GIGASET_DEVNAME "ttyGB" + +#define IF_WRITEBUF 256 //FIXME + +/* Values for the Gigaset 307x */ +#define USB_GIGA_VENDOR_ID 0x0681 +#define USB_GIGA_PRODUCT_ID 0x0001 +#define USB_4175_PRODUCT_ID 0x0002 +#define USB_SX303_PRODUCT_ID 0x0021 +#define USB_SX353_PRODUCT_ID 0x0022 + +/* table of devices that work with this driver */ +static struct usb_device_id gigaset_table [] = { + { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_GIGA_PRODUCT_ID) }, + { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_4175_PRODUCT_ID) }, + { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, + { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, gigaset_table); + +/* Get a minor range for your devices from the usb maintainer */ +#define USB_SKEL_MINOR_BASE 200 + +/*======================= local function prototypes =============================*/ + +/* This function is called if a new device is connected to the USB port. It + * checks whether this new device belongs to this driver. + */ +static int gigaset_probe(struct usb_interface *interface, + const struct usb_device_id *id); + +/* Function will be called if the device is unplugged */ +static void gigaset_disconnect(struct usb_interface *interface); + + +/*==============================================================================*/ + +struct bas_cardstate { + struct usb_device *udev; /* USB device pointer */ + struct usb_interface *interface; /* interface for this device */ + unsigned char minor; /* starting minor number */ + + struct urb *urb_ctrl; /* control pipe default URB */ + struct usb_ctrlrequest dr_ctrl; + struct timer_list timer_ctrl; /* control request timeout */ + + struct timer_list timer_atrdy; /* AT command ready timeout */ + struct urb *urb_cmd_out; /* for sending AT commands */ + struct usb_ctrlrequest dr_cmd_out; + int retry_cmd_out; + + struct urb *urb_cmd_in; /* for receiving AT replies */ + struct usb_ctrlrequest dr_cmd_in; + struct timer_list timer_cmd_in; /* receive request timeout */ + unsigned char *rcvbuf; /* AT reply receive buffer */ + + struct urb *urb_int_in; /* URB for interrupt pipe */ + unsigned char int_in_buf[3]; + + spinlock_t lock; /* locks all following */ + atomic_t basstate; /* bitmap (BS_*) */ + int pending; /* uncompleted base request */ + int rcvbuf_size; /* size of AT receive buffer */ + /* 0: no receive in progress */ + int retry_cmd_in; /* receive req retry count */ +}; + +/* status of direct USB connection to 307x base (bits in basstate) */ +#define BS_ATOPEN 0x001 +#define BS_B1OPEN 0x002 +#define BS_B2OPEN 0x004 +#define BS_ATREADY 0x008 +#define BS_INIT 0x010 +#define BS_ATTIMER 0x020 + + +static struct gigaset_driver *driver = NULL; +static struct cardstate *cardstate = NULL; + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver gigaset_usb_driver = { + .name = GIGASET_MODULENAME, + .probe = gigaset_probe, + .disconnect = gigaset_disconnect, + .id_table = gigaset_table, +}; + +/* get message text for USB status code + */ +static char *get_usb_statmsg(int status) +{ + static char unkmsg[28]; + + switch (status) { + case 0: + return "success"; + case -ENOENT: + return "canceled"; + case -ECONNRESET: + return "canceled (async)"; + case -EINPROGRESS: + return "pending"; + case -EPROTO: + return "bit stuffing or unknown USB error"; + case -EILSEQ: + return "Illegal byte sequence (CRC mismatch)"; + case -EPIPE: + return "babble detect or endpoint stalled"; + case -ENOSR: + return "buffer error"; + case -ETIMEDOUT: + return "timed out"; + case -ENODEV: + return "device not present"; + case -EREMOTEIO: + return "short packet detected"; + case -EXDEV: + return "partial isochronous transfer"; + case -EINVAL: + return "invalid argument"; + case -ENXIO: + return "URB already queued"; + case -EAGAIN: + return "isochronous start frame too early or too much scheduled"; + case -EFBIG: + return "too many isochronous frames requested"; + case -EMSGSIZE: + return "endpoint message size zero"; + case -ESHUTDOWN: + return "endpoint shutdown"; + case -EBUSY: + return "another request pending"; + default: + snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", status); + return unkmsg; + } +} + +/* usb_pipetype_str + * retrieve string representation of USB pipe type + */ +static inline char *usb_pipetype_str(int pipe) +{ + if (usb_pipeisoc(pipe)) + return "Isoc"; + if (usb_pipeint(pipe)) + return "Int"; + if (usb_pipecontrol(pipe)) + return "Ctrl"; + if (usb_pipebulk(pipe)) + return "Bulk"; + return "?"; +} + +/* dump_urb + * write content of URB to syslog for debugging + */ +static inline void dump_urb(enum debuglevel level, const char *tag, + struct urb *urb) +{ +#ifdef CONFIG_GIGASET_DEBUG + int i; + IFNULLRET(tag); + dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb); + if (urb) { + dbg(level, + " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " + "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,", + (unsigned long) urb->dev, + usb_pipetype_str(urb->pipe), + usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + urb->status, (unsigned long) urb->hcpriv, + urb->transfer_flags); + dbg(level, + " transfer_buffer=0x%08lx[%d], actual_length=%d, " + "bandwidth=%d, setup_packet=0x%08lx,", + (unsigned long) urb->transfer_buffer, + urb->transfer_buffer_length, urb->actual_length, + urb->bandwidth, (unsigned long) urb->setup_packet); + dbg(level, + " start_frame=%d, number_of_packets=%d, interval=%d, " + "error_count=%d,", + urb->start_frame, urb->number_of_packets, urb->interval, + urb->error_count); + dbg(level, + " context=0x%08lx, complete=0x%08lx, iso_frame_desc[]={", + (unsigned long) urb->context, + (unsigned long) urb->complete); + for (i = 0; i < urb->number_of_packets; i++) { + struct usb_iso_packet_descriptor *pifd = &urb->iso_frame_desc[i]; + dbg(level, + " {offset=%u, length=%u, actual_length=%u, " + "status=%u}", + pifd->offset, pifd->length, pifd->actual_length, + pifd->status); + } + } + dbg(level, "}}"); +#endif +} + +/* read/set modem control bits etc. (m10x only) */ +static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, + unsigned new_state) +{ + return -EINVAL; +} + +static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) +{ + return -EINVAL; +} + +static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) +{ + return -EINVAL; +} + +/* error_hangup + * hang up any existing connection because of an unrecoverable error + * This function may be called from any context and takes care of scheduling + * the necessary actions for execution outside of interrupt context. + * argument: + * B channel control structure + */ +static inline void error_hangup(struct bc_state *bcs) +{ + struct cardstate *cs = bcs->cs; + + dbg(DEBUG_ANY, + "%s: scheduling HUP for channel %d", __func__, bcs->channel); + + if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { + //FIXME what should we do? + return; + } + + gigaset_schedule_event(cs); +} + +/* error_reset + * reset Gigaset device because of an unrecoverable error + * This function may be called from any context and takes care of scheduling + * the necessary actions for execution outside of interrupt context. + * argument: + * controller state structure + */ +static inline void error_reset(struct cardstate *cs) +{ + //FIXME try to recover without bothering the user + err("unrecoverable error - please disconnect the Gigaset base to reset"); +} + +/* check_pending + * check for completion of pending control request + * parameter: + * urb USB request block of completed request + * urb->context = hardware specific controller state structure + */ +static void check_pending(struct bas_cardstate *ucs) +{ + unsigned long flags; + + IFNULLRET(ucs); + IFNULLRET(cardstate); + + spin_lock_irqsave(&ucs->lock, flags); + switch (ucs->pending) { + case 0: + break; + case HD_OPEN_ATCHANNEL: + if (atomic_read(&ucs->basstate) & BS_ATOPEN) + ucs->pending = 0; + break; + case HD_OPEN_B1CHANNEL: + if (atomic_read(&ucs->basstate) & BS_B1OPEN) + ucs->pending = 0; + break; + case HD_OPEN_B2CHANNEL: + if (atomic_read(&ucs->basstate) & BS_B2OPEN) + ucs->pending = 0; + break; + case HD_CLOSE_ATCHANNEL: + if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) + ucs->pending = 0; + //wake_up_interruptible(cs->initwait); + //FIXME need own wait queue? + break; + case HD_CLOSE_B1CHANNEL: + if (!(atomic_read(&ucs->basstate) & BS_B1OPEN)) + ucs->pending = 0; + break; + case HD_CLOSE_B2CHANNEL: + if (!(atomic_read(&ucs->basstate) & BS_B2OPEN)) + ucs->pending = 0; + break; + case HD_DEVICE_INIT_ACK: /* no reply expected */ + ucs->pending = 0; + break; + /* HD_READ_ATMESSAGE, HD_WRITE_ATMESSAGE, HD_RESET_INTERRUPTPIPE + * are handled separately and should never end up here + */ + default: + warn("unknown pending request 0x%02x cleared", ucs->pending); + ucs->pending = 0; + } + + if (!ucs->pending) + del_timer(&ucs->timer_ctrl); + + spin_unlock_irqrestore(&ucs->lock, flags); +} + +/* cmd_in_timeout + * timeout routine for command input request + * argument: + * controller state structure + */ +static void cmd_in_timeout(unsigned long data) +{ + struct cardstate *cs = (struct cardstate *) data; + struct bas_cardstate *ucs; + unsigned long flags; + + IFNULLRET(cs); + ucs = cs->hw.bas; + IFNULLRET(ucs); + + spin_lock_irqsave(&cs->lock, flags); + if (!atomic_read(&cs->connected)) { + dbg(DEBUG_USBREQ, "%s: disconnected", __func__); + spin_unlock_irqrestore(&cs->lock, flags); + return; + } + if (!ucs->rcvbuf_size) { + dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); + spin_unlock_irqrestore(&cs->lock, flags); + return; + } + spin_unlock_irqrestore(&cs->lock, flags); + + err("timeout reading AT response"); + error_reset(cs); //FIXME retry? +} + + +static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs); + +/* atread_submit + * submit an HD_READ_ATMESSAGE command URB + * parameters: + * cs controller state structure + * timeout timeout in 1/10 sec., 0: none + * return value: + * 0 on success + * -EINVAL if a NULL pointer is encountered somewhere + * -EBUSY if another request is pending + * any URB submission error code + */ +static int atread_submit(struct cardstate *cs, int timeout) +{ + struct bas_cardstate *ucs; + int ret; + + IFNULLRETVAL(cs, -EINVAL); + ucs = cs->hw.bas; + IFNULLRETVAL(ucs, -EINVAL); + IFNULLRETVAL(ucs->urb_cmd_in, -EINVAL); + + dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", ucs->rcvbuf_size); + + if (ucs->urb_cmd_in->status == -EINPROGRESS) { + err("could not submit HD_READ_ATMESSAGE: URB busy"); + return -EBUSY; + } + + ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ; + ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE; + ucs->dr_cmd_in.wValue = 0; + ucs->dr_cmd_in.wIndex = 0; + ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size); + usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev, + usb_rcvctrlpipe(ucs->udev, 0), + (unsigned char*) & ucs->dr_cmd_in, + ucs->rcvbuf, ucs->rcvbuf_size, + read_ctrl_callback, cs->inbuf); + + if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) { + err("could not submit HD_READ_ATMESSAGE: %s", + get_usb_statmsg(ret)); + return ret; + } + + if (timeout > 0) { + dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); + ucs->timer_cmd_in.expires = jiffies + timeout * HZ / 10; + ucs->timer_cmd_in.data = (unsigned long) cs; + ucs->timer_cmd_in.function = cmd_in_timeout; + add_timer(&ucs->timer_cmd_in); + } + return 0; +} + +static void stopurbs(struct bas_bc_state *); +static int start_cbsend(struct cardstate *); + +/* set/clear bits in base connection state + */ +inline static void update_basstate(struct bas_cardstate *ucs, + int set, int clear) +{ + unsigned long flags; + int state; + + spin_lock_irqsave(&ucs->lock, flags); + state = atomic_read(&ucs->basstate); + state &= ~clear; + state |= set; + atomic_set(&ucs->basstate, state); + spin_unlock_irqrestore(&ucs->lock, flags); +} + + +/* read_int_callback + * USB completion handler for interrupt pipe input + * called by the USB subsystem in interrupt context + * parameter: + * urb USB request block + * urb->context = controller state structure + */ +static void read_int_callback(struct urb *urb, struct pt_regs *regs) +{ + struct cardstate *cs; + struct bas_cardstate *ucs; + struct bc_state *bcs; + unsigned long flags; + int status; + unsigned l; + int channel; + + IFNULLRET(urb); + cs = (struct cardstate *) urb->context; + IFNULLRET(cs); + ucs = cs->hw.bas; + IFNULLRET(ucs); + + if (unlikely(!atomic_read(&cs->connected))) { + warn("%s: disconnected", __func__); + return; + } + + switch (urb->status) { + case 0: /* success */ + break; + case -ENOENT: /* canceled */ + case -ECONNRESET: /* canceled (async) */ + case -EINPROGRESS: /* pending */ + /* ignore silently */ + dbg(DEBUG_USBREQ, + "%s: %s", __func__, get_usb_statmsg(urb->status)); + return; + default: /* severe trouble */ + warn("interrupt read: %s", get_usb_statmsg(urb->status)); + //FIXME corrective action? resubmission always ok? + goto resubmit; + } + + l = (unsigned) ucs->int_in_buf[1] + + (((unsigned) ucs->int_in_buf[2]) << 8); + + dbg(DEBUG_USBREQ, + "<-------%d: 0x%02x (%u [0x%02x 0x%02x])", urb->actual_length, + (int)ucs->int_in_buf[0], l, + (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]); + + channel = 0; + + switch (ucs->int_in_buf[0]) { + case HD_DEVICE_INIT_OK: + update_basstate(ucs, BS_INIT, 0); + break; + + case HD_READY_SEND_ATDATA: + del_timer(&ucs->timer_atrdy); + update_basstate(ucs, BS_ATREADY, BS_ATTIMER); + start_cbsend(cs); + break; + + case HD_OPEN_B2CHANNEL_ACK: + ++channel; + case HD_OPEN_B1CHANNEL_ACK: + bcs = cs->bcs + channel; + update_basstate(ucs, BS_B1OPEN << channel, 0); + gigaset_bchannel_up(bcs); + break; + + case HD_OPEN_ATCHANNEL_ACK: + update_basstate(ucs, BS_ATOPEN, 0); + start_cbsend(cs); + break; + + case HD_CLOSE_B2CHANNEL_ACK: + ++channel; + case HD_CLOSE_B1CHANNEL_ACK: + bcs = cs->bcs + channel; + update_basstate(ucs, 0, BS_B1OPEN << channel); + stopurbs(bcs->hw.bas); + gigaset_bchannel_down(bcs); + break; + + case HD_CLOSE_ATCHANNEL_ACK: + update_basstate(ucs, 0, BS_ATOPEN); + break; + + case HD_B2_FLOW_CONTROL: + ++channel; + case HD_B1_FLOW_CONTROL: + bcs = cs->bcs + channel; + atomic_add((l - BAS_NORMFRAME) * BAS_CORRFRAMES, + &bcs->hw.bas->corrbytes); + dbg(DEBUG_ISO, + "Flow control (channel %d, sub %d): 0x%02x => %d", + channel, bcs->hw.bas->numsub, l, + atomic_read(&bcs->hw.bas->corrbytes)); + break; + + case HD_RECEIVEATDATA_ACK: /* AT response ready to be received */ + if (!l) { + warn("HD_RECEIVEATDATA_ACK with length 0 ignored"); + break; + } + spin_lock_irqsave(&cs->lock, flags); + if (ucs->rcvbuf_size) { + spin_unlock_irqrestore(&cs->lock, flags); + err("receive AT data overrun, %d bytes lost", l); + error_reset(cs); //FIXME reschedule + break; + } + if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) { + spin_unlock_irqrestore(&cs->lock, flags); + err("%s: out of memory, %d bytes lost", __func__, l); + error_reset(cs); //FIXME reschedule + break; + } + ucs->rcvbuf_size = l; + ucs->retry_cmd_in = 0; + if ((status = atread_submit(cs, BAS_TIMEOUT)) < 0) { + kfree(ucs->rcvbuf); + ucs->rcvbuf = NULL; + ucs->rcvbuf_size = 0; + error_reset(cs); //FIXME reschedule + } + spin_unlock_irqrestore(&cs->lock, flags); + break; + + case HD_RESET_INTERRUPT_PIPE_ACK: + dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK"); + break; + + case HD_SUSPEND_END: + dbg(DEBUG_USBREQ, "HD_SUSPEND_END"); + break; + + default: + warn("unknown Gigaset signal 0x%02x (%u) ignored", + (int) ucs->int_in_buf[0], l); + } + + check_pending(ucs); + +resubmit: + status = usb_submit_urb(urb, SLAB_ATOMIC); + if (unlikely(status)) { + err("could not resubmit interrupt URB: %s", + get_usb_statmsg(status)); + error_reset(cs); + } +} + +/* read_ctrl_callback + * USB completion handler for control pipe input + * called by the USB subsystem in interrupt context + * parameter: + * urb USB request block + * urb->context = inbuf structure for controller state + */ +static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) +{ + struct cardstate *cs; + struct bas_cardstate *ucs; + unsigned numbytes; + unsigned long flags; + struct inbuf_t *inbuf; + int have_data = 0; + + IFNULLRET(urb); + inbuf = (struct inbuf_t *) urb->context; + IFNULLRET(inbuf); + cs = inbuf->cs; + IFNULLRET(cs); + ucs = cs->hw.bas; + IFNULLRET(ucs); + + spin_lock_irqsave(&cs->lock, flags); + if (!atomic_read(&cs->connected)) { + warn("%s: disconnected", __func__); + spin_unlock_irqrestore(&cs->lock, flags); + return; + } + + if (!ucs->rcvbuf_size) { + warn("%s: no receive in progress", __func__); + spin_unlock_irqrestore(&cs->lock, flags); + return; + } + + del_timer(&ucs->timer_cmd_in); + + switch (urb->status) { + case 0: /* normal completion */ + numbytes = urb->actual_length; + if (unlikely(numbytes == 0)) { + warn("control read: empty block received"); + goto retry; + } + if (unlikely(numbytes != ucs->rcvbuf_size)) { + warn("control read: received %d chars, expected %d", + numbytes, ucs->rcvbuf_size); + if (numbytes > ucs->rcvbuf_size) + numbytes = ucs->rcvbuf_size; + } + + /* copy received bytes to inbuf */ + have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes); + + if (unlikely(numbytes < ucs->rcvbuf_size)) { + /* incomplete - resubmit for remaining bytes */ + ucs->rcvbuf_size -= numbytes; + ucs->retry_cmd_in = 0; + goto retry; + } + break; + + case -ENOENT: /* canceled */ + case -ECONNRESET: /* canceled (async) */ + case -EINPROGRESS: /* pending */ + /* no action necessary */ + dbg(DEBUG_USBREQ, + "%s: %s", __func__, get_usb_statmsg(urb->status)); + break; + + default: /* severe trouble */ + warn("control read: %s", get_usb_statmsg(urb->status)); + retry: + if (ucs->retry_cmd_in++ < BAS_RETRY) { + notice("control read: retry %d", ucs->retry_cmd_in); + if (atread_submit(cs, BAS_TIMEOUT) >= 0) { + /* resubmitted - bypass regular exit block */ + spin_unlock_irqrestore(&cs->lock, flags); + return; + } + } else { + err("control read: giving up after %d tries", + ucs->retry_cmd_in); + } + error_reset(cs); + } + + kfree(ucs->rcvbuf); + ucs->rcvbuf = NULL; + ucs->rcvbuf_size = 0; + spin_unlock_irqrestore(&cs->lock, flags); + if (have_data) { + dbg(DEBUG_INTR, "%s-->BH", __func__); + gigaset_schedule_event(cs); + } +} + +/* read_iso_callback + * USB completion handler for B channel isochronous input + * called by the USB subsystem in interrupt context + * parameter: + * urb USB request block of completed request + * urb->context = bc_state structure + */ +static void read_iso_callback(struct urb *urb, struct pt_regs *regs) +{ + struct bc_state *bcs; + struct bas_bc_state *ubc; + unsigned long flags; + int i, rc; + + IFNULLRET(urb); + IFNULLRET(urb->context); + IFNULLRET(cardstate); + + /* status codes not worth bothering the tasklet with */ + if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || + urb->status == -EINPROGRESS)) { + dbg(DEBUG_ISO, + "%s: %s", __func__, get_usb_statmsg(urb->status)); + return; + } + + bcs = (struct bc_state *) urb->context; + ubc = bcs->hw.bas; + IFNULLRET(ubc); + + spin_lock_irqsave(&ubc->isoinlock, flags); + if (likely(ubc->isoindone == NULL)) { + /* pass URB to tasklet */ + ubc->isoindone = urb; + tasklet_schedule(&ubc->rcvd_tasklet); + } else { + /* tasklet still busy, drop data and resubmit URB */ + ubc->loststatus = urb->status; + for (i = 0; i < BAS_NUMFRAMES; i++) { + ubc->isoinlost += urb->iso_frame_desc[i].actual_length; + if (unlikely(urb->iso_frame_desc[i].status != 0 && + urb->iso_frame_desc[i].status != -EINPROGRESS)) { + ubc->loststatus = urb->iso_frame_desc[i].status; + } + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + if (likely(atomic_read(&ubc->running))) { + urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */ + urb->transfer_flags = URB_ISO_ASAP; + urb->number_of_packets = BAS_NUMFRAMES; + dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", __func__); + rc = usb_submit_urb(urb, SLAB_ATOMIC); + if (unlikely(rc != 0)) { + err("could not resubmit isochronous read URB: %s", + get_usb_statmsg(rc)); + dump_urb(DEBUG_ISO, "isoc read", urb); + error_hangup(bcs); + } + } + } + spin_unlock_irqrestore(&ubc->isoinlock, flags); +} + +/* write_iso_callback + * USB completion handler for B channel isochronous output + * called by the USB subsystem in interrupt context + * parameter: + * urb USB request block of completed request + * urb->context = isow_urbctx_t structure + */ +static void write_iso_callback(struct urb *urb, struct pt_regs *regs) +{ + struct isow_urbctx_t *ucx; + struct bas_bc_state *ubc; + unsigned long flags; + + IFNULLRET(urb); + IFNULLRET(urb->context); + IFNULLRET(cardstate); + + /* status codes not worth bothering the tasklet with */ + if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || + urb->status == -EINPROGRESS)) { + dbg(DEBUG_ISO, + "%s: %s", __func__, get_usb_statmsg(urb->status)); + return; + } + + /* pass URB context to tasklet */ + ucx = (struct isow_urbctx_t *) urb->context; + IFNULLRET(ucx->bcs); + ubc = ucx->bcs->hw.bas; + IFNULLRET(ubc); + + spin_lock_irqsave(&ubc->isooutlock, flags); + ubc->isooutovfl = ubc->isooutdone; + ubc->isooutdone = ucx; + spin_unlock_irqrestore(&ubc->isooutlock, flags); + tasklet_schedule(&ubc->sent_tasklet); +} + +/* starturbs + * prepare and submit USB request blocks for isochronous input and output + * argument: + * B channel control structure + * return value: + * 0 on success + * < 0 on error (no URBs submitted) + */ +static int starturbs(struct bc_state *bcs) +{ + struct urb *urb; + struct bas_bc_state *ubc; + int j, k; + int rc; + + IFNULLRETVAL(bcs, -EFAULT); + ubc = bcs->hw.bas; + IFNULLRETVAL(ubc, -EFAULT); + + /* initialize L2 reception */ + if (bcs->proto2 == ISDN_PROTO_L2_HDLC) + bcs->inputstate |= INS_flag_hunt; + + /* submit all isochronous input URBs */ + atomic_set(&ubc->running, 1); + for (k = 0; k < BAS_INURBS; k++) { + urb = ubc->isoinurbs[k]; + if (!urb) { + err("isoinurbs[%d]==NULL", k); + rc = -EFAULT; + goto error; + } + + urb->dev = bcs->cs->hw.bas->udev; + urb->pipe = usb_rcvisocpipe(urb->dev, 3 + 2 * bcs->channel); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = ubc->isoinbuf + k * BAS_INBUFSIZE; + urb->transfer_buffer_length = BAS_INBUFSIZE; + urb->number_of_packets = BAS_NUMFRAMES; + urb->interval = BAS_FRAMETIME; + urb->complete = read_iso_callback; + urb->context = bcs; + for (j = 0; j < BAS_NUMFRAMES; j++) { + urb->iso_frame_desc[j].offset = j * BAS_MAXFRAME; + urb->iso_frame_desc[j].length = BAS_MAXFRAME; + urb->iso_frame_desc[j].status = 0; + urb->iso_frame_desc[j].actual_length = 0; + } + + dump_urb(DEBUG_ISO, "Initial isoc read", urb); + if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) { + err("could not submit isochronous read URB %d: %s", + k, get_usb_statmsg(rc)); + goto error; + } + } + + /* initialize L2 transmission */ + gigaset_isowbuf_init(ubc->isooutbuf, PPP_FLAG); + + /* set up isochronous output URBs for flag idling */ + for (k = 0; k < BAS_OUTURBS; ++k) { + urb = ubc->isoouturbs[k].urb; + if (!urb) { + err("isoouturbs[%d].urb==NULL", k); + rc = -EFAULT; + goto error; + } + urb->dev = bcs->cs->hw.bas->udev; + urb->pipe = usb_sndisocpipe(urb->dev, 4 + 2 * bcs->channel); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = ubc->isooutbuf->data; + urb->transfer_buffer_length = sizeof(ubc->isooutbuf->data); + urb->number_of_packets = BAS_NUMFRAMES; + urb->interval = BAS_FRAMETIME; + urb->complete = write_iso_callback; + urb->context = &ubc->isoouturbs[k]; + for (j = 0; j < BAS_NUMFRAMES; ++j) { + urb->iso_frame_desc[j].offset = BAS_OUTBUFSIZE; + urb->iso_frame_desc[j].length = BAS_NORMFRAME; + urb->iso_frame_desc[j].status = 0; + urb->iso_frame_desc[j].actual_length = 0; + } + ubc->isoouturbs[k].limit = -1; + } + + /* submit two URBs, keep third one */ + for (k = 0; k < 2; ++k) { + dump_urb(DEBUG_ISO, "Initial isoc write", urb); + rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC); + if (rc != 0) { + err("could not submit isochronous write URB %d: %s", + k, get_usb_statmsg(rc)); + goto error; + } + } + dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); + ubc->isooutfree = &ubc->isoouturbs[2]; + ubc->isooutdone = ubc->isooutovfl = NULL; + return 0; + error: + stopurbs(ubc); + return rc; +} + +/* stopurbs + * cancel the USB request blocks for isochronous input and output + * errors are silently ignored + * argument: + * B channel control structure + */ +static void stopurbs(struct bas_bc_state *ubc) +{ + int k, rc; + + IFNULLRET(ubc); + + atomic_set(&ubc->running, 0); + + for (k = 0; k < BAS_INURBS; ++k) { + rc = usb_unlink_urb(ubc->isoinurbs[k]); + dbg(DEBUG_ISO, "%s: isoc input URB %d unlinked, result = %d", + __func__, k, rc); + } + + for (k = 0; k < BAS_OUTURBS; ++k) { + rc = usb_unlink_urb(ubc->isoouturbs[k].urb); + dbg(DEBUG_ISO, "%s: isoc output URB %d unlinked, result = %d", + __func__, k, rc); + } +} + +/* Isochronous Write - Bottom Half */ +/* =============================== */ + +/* submit_iso_write_urb + * fill and submit the next isochronous write URB + * parameters: + * bcs B channel state structure + * return value: + * number of frames submitted in URB + * 0 if URB not submitted because no data available (isooutbuf busy) + * error code < 0 on error + */ +static int submit_iso_write_urb(struct isow_urbctx_t *ucx) +{ + struct urb *urb; + struct bas_bc_state *ubc; + struct usb_iso_packet_descriptor *ifd; + int corrbytes, nframe, rc; + + IFNULLRETVAL(ucx, -EFAULT); + urb = ucx->urb; + IFNULLRETVAL(urb, -EFAULT); + IFNULLRETVAL(ucx->bcs, -EFAULT); + ubc = ucx->bcs->hw.bas; + IFNULLRETVAL(ubc, -EFAULT); + + urb->dev = ucx->bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */ + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = ubc->isooutbuf->data; + urb->transfer_buffer_length = sizeof(ubc->isooutbuf->data); + + for (nframe = 0; nframe < BAS_NUMFRAMES; nframe++) { + ifd = &urb->iso_frame_desc[nframe]; + + /* compute frame length according to flow control */ + ifd->length = BAS_NORMFRAME; + if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) { + dbg(DEBUG_ISO, "%s: corrbytes=%d", __func__, corrbytes); + if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME) + corrbytes = BAS_HIGHFRAME - BAS_NORMFRAME; + else if (corrbytes < BAS_LOWFRAME - BAS_NORMFRAME) + corrbytes = BAS_LOWFRAME - BAS_NORMFRAME; + ifd->length += corrbytes; + atomic_add(-corrbytes, &ubc->corrbytes); + } + //dbg(DEBUG_ISO, "%s: frame %d length=%d", __func__, nframe, ifd->length); + + /* retrieve block of data to send */ + ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length); + if (ifd->offset < 0) { + if (ifd->offset == -EBUSY) { + dbg(DEBUG_ISO, "%s: buffer busy at frame %d", + __func__, nframe); + /* tasklet will be restarted from gigaset_send_skb() */ + } else { + err("%s: buffer error %d at frame %d", + __func__, ifd->offset, nframe); + return ifd->offset; + } + break; + } + ucx->limit = atomic_read(&ubc->isooutbuf->nextread); + ifd->status = 0; + ifd->actual_length = 0; + } + if ((urb->number_of_packets = nframe) > 0) { + if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) { + err("could not submit isochronous write URB: %s", + get_usb_statmsg(rc)); + dump_urb(DEBUG_ISO, "isoc write", urb); + return rc; + } + ++ubc->numsub; + } + return nframe; +} + +/* write_iso_tasklet + * tasklet scheduled when an isochronous output URB from the Gigaset device + * has completed + * parameter: + * data B channel state structure + */ +static void write_iso_tasklet(unsigned long data) +{ + struct bc_state *bcs; + struct bas_bc_state *ubc; + struct cardstate *cs; + struct isow_urbctx_t *done, *next, *ovfl; + struct urb *urb; + struct usb_iso_packet_descriptor *ifd; + int offset; + unsigned long flags; + int i; + struct sk_buff *skb; + int len; + + bcs = (struct bc_state *) data; + IFNULLRET(bcs); + ubc = bcs->hw.bas; + IFNULLRET(ubc); + cs = bcs->cs; + IFNULLRET(cs); + + /* loop while completed URBs arrive in time */ + for (;;) { + if (unlikely(!atomic_read(&cs->connected))) { + warn("%s: disconnected", __func__); + return; + } + + if (unlikely(!(atomic_read(&ubc->running)))) { + dbg(DEBUG_ISO, "%s: not running", __func__); + return; + } + + /* retrieve completed URBs */ + spin_lock_irqsave(&ubc->isooutlock, flags); + done = ubc->isooutdone; + ubc->isooutdone = NULL; + ovfl = ubc->isooutovfl; + ubc->isooutovfl = NULL; + spin_unlock_irqrestore(&ubc->isooutlock, flags); + if (ovfl) { + err("isochronous write buffer underrun - buy a faster machine :-)"); + error_hangup(bcs); + break; + } + if (!done) + break; + + /* submit free URB if available */ + spin_lock_irqsave(&ubc->isooutlock, flags); + next = ubc->isooutfree; + ubc->isooutfree = NULL; + spin_unlock_irqrestore(&ubc->isooutlock, flags); + if (next) { + if (submit_iso_write_urb(next) <= 0) { + /* could not submit URB, put it back */ + spin_lock_irqsave(&ubc->isooutlock, flags); + if (ubc->isooutfree == NULL) { + ubc->isooutfree = next; + next = NULL; + } + spin_unlock_irqrestore(&ubc->isooutlock, flags); + if (next) { + /* couldn't put it back */ + err("losing isochronous write URB"); + error_hangup(bcs); + } + } + } + + /* process completed URB */ + urb = done->urb; + switch (urb->status) { + case 0: /* normal completion */ + break; + case -EXDEV: /* inspect individual frames */ + /* assumptions (for lack of documentation): + * - actual_length bytes of the frame in error are successfully sent + * - all following frames are not sent at all + */ + dbg(DEBUG_ISO, "%s: URB partially completed", __func__); + offset = done->limit; /* just in case */ + for (i = 0; i < BAS_NUMFRAMES; i++) { + ifd = &urb->iso_frame_desc[i]; + if (ifd->status || + ifd->actual_length != ifd->length) { + warn("isochronous write: frame %d: %s, " + "only %d of %d bytes sent", + i, get_usb_statmsg(ifd->status), + ifd->actual_length, ifd->length); + offset = (ifd->offset + + ifd->actual_length) + % BAS_OUTBUFSIZE; + break; + } + } +#ifdef CONFIG_GIGASET_DEBUG + /* check assumption on remaining frames */ + for (; i < BAS_NUMFRAMES; i++) { + ifd = &urb->iso_frame_desc[i]; + if (ifd->status != -EINPROGRESS + || ifd->actual_length != 0) { + warn("isochronous write: frame %d: %s, " + "%d of %d bytes sent", + i, get_usb_statmsg(ifd->status), + ifd->actual_length, ifd->length); + offset = (ifd->offset + + ifd->actual_length) + % BAS_OUTBUFSIZE; + break; + } + } +#endif + break; + case -EPIPE: //FIXME is this the code for "underrun"? + err("isochronous write stalled"); + error_hangup(bcs); + break; + default: /* severe trouble */ + warn("isochronous write: %s", + get_usb_statmsg(urb->status)); + } + + /* mark the write buffer area covered by this URB as free */ + if (done->limit >= 0) + atomic_set(&ubc->isooutbuf->read, done->limit); + + /* mark URB as free */ + spin_lock_irqsave(&ubc->isooutlock, flags); + next = ubc->isooutfree; + ubc->isooutfree = done; + spin_unlock_irqrestore(&ubc->isooutlock, flags); + if (next) { + /* only one URB still active - resubmit one */ + if (submit_iso_write_urb(next) <= 0) { + /* couldn't submit */ + error_hangup(bcs); + } + } + } + + /* process queued SKBs */ + while ((skb = skb_dequeue(&bcs->squeue))) { + /* copy to output buffer, doing L2 encapsulation */ + len = skb->len; + if (gigaset_isoc_buildframe(bcs, skb->data, len) == -EAGAIN) { + /* insufficient buffer space, push back onto queue */ + skb_queue_head(&bcs->squeue, skb); + dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d", + __func__, skb_queue_len(&bcs->squeue)); + break; + } + skb_pull(skb, len); + gigaset_skb_sent(bcs, skb); + dev_kfree_skb_any(skb); + } +} + +/* Isochronous Read - Bottom Half */ +/* ============================== */ + +/* read_iso_tasklet + * tasklet scheduled when an isochronous input URB from the Gigaset device + * has completed + * parameter: + * data B channel state structure + */ +static void read_iso_tasklet(unsigned long data) +{ + struct bc_state *bcs; + struct bas_bc_state *ubc; + struct cardstate *cs; + struct urb *urb; + char *rcvbuf; + unsigned long flags; + int totleft, numbytes, offset, frame, rc; + + bcs = (struct bc_state *) data; + IFNULLRET(bcs); + ubc = bcs->hw.bas; + IFNULLRET(ubc); + cs = bcs->cs; + IFNULLRET(cs); + + /* loop while more completed URBs arrive in the meantime */ + for (;;) { + if (!atomic_read(&cs->connected)) { + warn("%s: disconnected", __func__); + return; + } + + /* retrieve URB */ + spin_lock_irqsave(&ubc->isoinlock, flags); + if (!(urb = ubc->isoindone)) { + spin_unlock_irqrestore(&ubc->isoinlock, flags); + return; + } + ubc->isoindone = NULL; + if (unlikely(ubc->loststatus != -EINPROGRESS)) { + warn("isochronous read overrun, dropped URB with status: %s, %d bytes lost", + get_usb_statmsg(ubc->loststatus), ubc->isoinlost); + ubc->loststatus = -EINPROGRESS; + } + spin_unlock_irqrestore(&ubc->isoinlock, flags); + + if (unlikely(!(atomic_read(&ubc->running)))) { + dbg(DEBUG_ISO, "%s: channel not running, dropped URB with status: %s", + __func__, get_usb_statmsg(urb->status)); + return; + } + + switch (urb->status) { + case 0: /* normal completion */ + break; + case -EXDEV: /* inspect individual frames (we do that anyway) */ + dbg(DEBUG_ISO, "%s: URB partially completed", __func__); + break; + case -ENOENT: + case -ECONNRESET: + dbg(DEBUG_ISO, "%s: URB canceled", __func__); + continue; /* -> skip */ + case -EINPROGRESS: /* huh? */ + dbg(DEBUG_ISO, "%s: URB still pending", __func__); + continue; /* -> skip */ + case -EPIPE: + err("isochronous read stalled"); + error_hangup(bcs); + continue; /* -> skip */ + default: /* severe trouble */ + warn("isochronous read: %s", + get_usb_statmsg(urb->status)); + goto error; + } + + rcvbuf = urb->transfer_buffer; + totleft = urb->actual_length; + for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) { + if (unlikely(urb->iso_frame_desc[frame].status)) { + warn("isochronous read: frame %d: %s", + frame, get_usb_statmsg(urb->iso_frame_desc[frame].status)); + break; + } + numbytes = urb->iso_frame_desc[frame].actual_length; + if (unlikely(numbytes > BAS_MAXFRAME)) { + warn("isochronous read: frame %d: numbytes (%d) > BAS_MAXFRAME", + frame, numbytes); + break; + } + if (unlikely(numbytes > totleft)) { + warn("isochronous read: frame %d: numbytes (%d) > totleft (%d)", + frame, numbytes, totleft); + break; + } + offset = urb->iso_frame_desc[frame].offset; + if (unlikely(offset + numbytes > BAS_INBUFSIZE)) { + warn("isochronous read: frame %d: offset (%d) + numbytes (%d) > BAS_INBUFSIZE", + frame, offset, numbytes); + break; + } + gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs); + totleft -= numbytes; + } + if (unlikely(totleft > 0)) + warn("isochronous read: %d data bytes missing", + totleft); + + error: + /* URB processed, resubmit */ + for (frame = 0; frame < BAS_NUMFRAMES; frame++) { + urb->iso_frame_desc[frame].status = 0; + urb->iso_frame_desc[frame].actual_length = 0; + } + urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */ + urb->transfer_flags = URB_ISO_ASAP; + urb->number_of_packets = BAS_NUMFRAMES; + if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) { + err("could not resubmit isochronous read URB: %s", + get_usb_statmsg(rc)); + dump_urb(DEBUG_ISO, "resubmit iso read", urb); + error_hangup(bcs); + } + } +} + +/* Channel Operations */ +/* ================== */ + +/* req_timeout + * timeout routine for control output request + * argument: + * B channel control structure + */ +static void req_timeout(unsigned long data) +{ + struct bc_state *bcs = (struct bc_state *) data; + struct bas_cardstate *ucs; + int pending; + unsigned long flags; + + IFNULLRET(bcs); + IFNULLRET(bcs->cs); + ucs = bcs->cs->hw.bas; + IFNULLRET(ucs); + + check_pending(ucs); + + spin_lock_irqsave(&ucs->lock, flags); + pending = ucs->pending; + ucs->pending = 0; + spin_unlock_irqrestore(&ucs->lock, flags); + + switch (pending) { + case 0: /* no pending request */ + dbg(DEBUG_USBREQ, "%s: no request pending", __func__); + break; + + case HD_OPEN_ATCHANNEL: + err("timeout opening AT channel"); + error_reset(bcs->cs); + break; + + case HD_OPEN_B2CHANNEL: + case HD_OPEN_B1CHANNEL: + err("timeout opening channel %d", bcs->channel + 1); + error_hangup(bcs); + break; + + case HD_CLOSE_ATCHANNEL: + err("timeout closing AT channel"); + //wake_up_interruptible(cs->initwait); + //FIXME need own wait queue? + break; + + case HD_CLOSE_B2CHANNEL: + case HD_CLOSE_B1CHANNEL: + err("timeout closing channel %d", bcs->channel + 1); + break; + + default: + warn("request 0x%02x timed out, clearing", pending); + } +} + +/* write_ctrl_callback + * USB completion handler for control pipe output + * called by the USB subsystem in interrupt context + * parameter: + * urb USB request block of completed request + * urb->context = hardware specific controller state structure + */ +static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs) +{ + struct bas_cardstate *ucs; + unsigned long flags; + + IFNULLRET(urb); + IFNULLRET(urb->context); + IFNULLRET(cardstate); + + ucs = (struct bas_cardstate *) urb->context; + spin_lock_irqsave(&ucs->lock, flags); + if (urb->status && ucs->pending) { + err("control request 0x%02x failed: %s", + ucs->pending, get_usb_statmsg(urb->status)); + del_timer(&ucs->timer_ctrl); + ucs->pending = 0; + } + /* individual handling of specific request types */ + switch (ucs->pending) { + case HD_DEVICE_INIT_ACK: /* no reply expected */ + ucs->pending = 0; + break; + } + spin_unlock_irqrestore(&ucs->lock, flags); +} + +/* req_submit + * submit a control output request without message buffer to the Gigaset base + * and optionally start a timeout + * parameters: + * bcs B channel control structure + * req control request code (HD_*) + * val control request parameter value (set to 0 if unused) + * timeout timeout in seconds (0: no timeout) + * return value: + * 0 on success + * -EINVAL if a NULL pointer is encountered somewhere + * -EBUSY if another request is pending + * any URB submission error code + */ +static int req_submit(struct bc_state *bcs, int req, int val, int timeout) +{ + struct bas_cardstate *ucs; + int ret; + unsigned long flags; + + IFNULLRETVAL(bcs, -EINVAL); + IFNULLRETVAL(bcs->cs, -EINVAL); + ucs = bcs->cs->hw.bas; + IFNULLRETVAL(ucs, -EINVAL); + IFNULLRETVAL(ucs->urb_ctrl, -EINVAL); + + dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val); + + spin_lock_irqsave(&ucs->lock, flags); + if (ucs->pending) { + spin_unlock_irqrestore(&ucs->lock, flags); + err("submission of request 0x%02x failed: request 0x%02x still pending", + req, ucs->pending); + return -EBUSY; + } + if (ucs->urb_ctrl->status == -EINPROGRESS) { + spin_unlock_irqrestore(&ucs->lock, flags); + err("could not submit request 0x%02x: URB busy", req); + return -EBUSY; + } + + ucs->dr_ctrl.bRequestType = OUT_VENDOR_REQ; + ucs->dr_ctrl.bRequest = req; + ucs->dr_ctrl.wValue = cpu_to_le16(val); + ucs->dr_ctrl.wIndex = 0; + ucs->dr_ctrl.wLength = 0; + usb_fill_control_urb(ucs->urb_ctrl, ucs->udev, + usb_sndctrlpipe(ucs->udev, 0), + (unsigned char*) &ucs->dr_ctrl, NULL, 0, + write_ctrl_callback, ucs); + if ((ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC)) != 0) { + err("could not submit request 0x%02x: %s", + req, get_usb_statmsg(ret)); + spin_unlock_irqrestore(&ucs->lock, flags); + return ret; + } + ucs->pending = req; + + if (timeout > 0) { + dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); + ucs->timer_ctrl.expires = jiffies + timeout * HZ / 10; + ucs->timer_ctrl.data = (unsigned long) bcs; + ucs->timer_ctrl.function = req_timeout; + add_timer(&ucs->timer_ctrl); + } + + spin_unlock_irqrestore(&ucs->lock, flags); + return 0; +} + +/* gigaset_init_bchannel + * called by common.c to connect a B channel + * initialize isochronous I/O and tell the Gigaset base to open the channel + * argument: + * B channel control structure + * return value: + * 0 on success, error code < 0 on error + */ +static int gigaset_init_bchannel(struct bc_state *bcs) +{ + int req, ret; + + IFNULLRETVAL(bcs, -EINVAL); + + if ((ret = starturbs(bcs)) < 0) { + err("could not start isochronous I/O for channel %d", + bcs->channel + 1); + error_hangup(bcs); + return ret; + } + + req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; + if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { + err("could not open channel %d: %s", + bcs->channel + 1, get_usb_statmsg(ret)); + stopurbs(bcs->hw.bas); + error_hangup(bcs); + } + return ret; +} + +/* gigaset_close_bchannel + * called by common.c to disconnect a B channel + * tell the Gigaset base to close the channel + * stopping isochronous I/O and LL notification will be done when the + * acknowledgement for the close arrives + * argument: + * B channel control structure + * return value: + * 0 on success, error code < 0 on error + */ +static int gigaset_close_bchannel(struct bc_state *bcs) +{ + int req, ret; + + IFNULLRETVAL(bcs, -EINVAL); + + if (!(atomic_read(&bcs->cs->hw.bas->basstate) & + (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { + /* channel not running: just signal common.c */ + gigaset_bchannel_down(bcs); + return 0; + } + + req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; + if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) + err("could not submit HD_CLOSE_BxCHANNEL request: %s", + get_usb_statmsg(ret)); + return ret; +} + +/* Device Operations */ +/* ================= */ + +/* complete_cb + * unqueue first command buffer from queue, waking any sleepers + * must be called with cs->cmdlock held + * parameter: + * cs controller state structure + */ +static void complete_cb(struct cardstate *cs) +{ + struct cmdbuf_t *cb; + + IFNULLRET(cs); + cb = cs->cmdbuf; + IFNULLRET(cb); + + /* unqueue completed buffer */ + cs->cmdbytes -= cs->curlen; + dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD, + "write_command: sent %u bytes, %u left", + cs->curlen, cs->cmdbytes); + if ((cs->cmdbuf = cb->next) != NULL) { + cs->cmdbuf->prev = NULL; + cs->curlen = cs->cmdbuf->len; + } else { + cs->lastcmdbuf = NULL; + cs->curlen = 0; + } + + if (cb->wake_tasklet) + tasklet_schedule(cb->wake_tasklet); + + kfree(cb); +} + +static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len); + +/* write_command_callback + * USB completion handler for AT command transmission + * called by the USB subsystem in interrupt context + * parameter: + * urb USB request block of completed request + * urb->context = controller state structure + */ +static void write_command_callback(struct urb *urb, struct pt_regs *regs) +{ + struct cardstate *cs; + unsigned long flags; + struct bas_cardstate *ucs; + + IFNULLRET(urb); + cs = (struct cardstate *) urb->context; + IFNULLRET(cs); + ucs = cs->hw.bas; + IFNULLRET(ucs); + + /* check status */ + switch (urb->status) { + case 0: /* normal completion */ + break; + case -ENOENT: /* canceled */ + case -ECONNRESET: /* canceled (async) */ + case -EINPROGRESS: /* pending */ + /* ignore silently */ + dbg(DEBUG_USBREQ, + "%s: %s", __func__, get_usb_statmsg(urb->status)); + return; + default: /* any failure */ + if (++ucs->retry_cmd_out > BAS_RETRY) { + warn("command write: %s, giving up after %d retries", + get_usb_statmsg(urb->status), ucs->retry_cmd_out); + break; + } + if (cs->cmdbuf == NULL) { + warn("command write: %s, cannot retry - cmdbuf gone", + get_usb_statmsg(urb->status)); + break; + } + notice("command write: %s, retry %d", + get_usb_statmsg(urb->status), ucs->retry_cmd_out); + if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) + /* resubmitted - bypass regular exit block */ + return; + /* command send failed, assume base still waiting */ + update_basstate(ucs, BS_ATREADY, 0); + } + + spin_lock_irqsave(&cs->cmdlock, flags); + if (cs->cmdbuf != NULL) + complete_cb(cs); + spin_unlock_irqrestore(&cs->cmdlock, flags); +} + +/* atrdy_timeout + * timeout routine for AT command transmission + * argument: + * controller state structure + */ +static void atrdy_timeout(unsigned long data) +{ + struct cardstate *cs = (struct cardstate *) data; + struct bas_cardstate *ucs; + + IFNULLRET(cs); + ucs = cs->hw.bas; + IFNULLRET(ucs); + + warn("timeout waiting for HD_READY_SEND_ATDATA"); + + /* fake the missing signal - what else can I do? */ + update_basstate(ucs, BS_ATREADY, BS_ATTIMER); + start_cbsend(cs); +} + +/* atwrite_submit + * submit an HD_WRITE_ATMESSAGE command URB + * parameters: + * cs controller state structure + * buf buffer containing command to send + * len length of command to send + * return value: + * 0 on success + * -EFAULT if a NULL pointer is encountered somewhere + * -EBUSY if another request is pending + * any URB submission error code + */ +static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) +{ + struct bas_cardstate *ucs; + int ret; + + IFNULLRETVAL(cs, -EFAULT); + ucs = cs->hw.bas; + IFNULLRETVAL(ucs, -EFAULT); + IFNULLRETVAL(ucs->urb_cmd_out, -EFAULT); + + dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len); + + if (ucs->urb_cmd_out->status == -EINPROGRESS) { + err("could not submit HD_WRITE_ATMESSAGE: URB busy"); + return -EBUSY; + } + + ucs->dr_cmd_out.bRequestType = OUT_VENDOR_REQ; + ucs->dr_cmd_out.bRequest = HD_WRITE_ATMESSAGE; + ucs->dr_cmd_out.wValue = 0; + ucs->dr_cmd_out.wIndex = 0; + ucs->dr_cmd_out.wLength = cpu_to_le16(len); + usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev, + usb_sndctrlpipe(ucs->udev, 0), + (unsigned char*) &ucs->dr_cmd_out, buf, len, + write_command_callback, cs); + + if ((ret = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC)) != 0) { + err("could not submit HD_WRITE_ATMESSAGE: %s", + get_usb_statmsg(ret)); + return ret; + } + + /* submitted successfully */ + update_basstate(ucs, 0, BS_ATREADY); + + /* start timeout if necessary */ + if (!(atomic_read(&ucs->basstate) & BS_ATTIMER)) { + dbg(DEBUG_OUTPUT, + "setting ATREADY timeout of %d/10 secs", ATRDY_TIMEOUT); + ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10; + ucs->timer_atrdy.data = (unsigned long) cs; + ucs->timer_atrdy.function = atrdy_timeout; + add_timer(&ucs->timer_atrdy); + update_basstate(ucs, BS_ATTIMER, 0); + } + return 0; +} + +/* start_cbsend + * start transmission of AT command queue if necessary + * parameter: + * cs controller state structure + * return value: + * 0 on success + * error code < 0 on error + */ +static int start_cbsend(struct cardstate *cs) +{ + struct cmdbuf_t *cb; + struct bas_cardstate *ucs; + unsigned long flags; + int rc; + int retval = 0; + + IFNULLRETVAL(cs, -EFAULT); + ucs = cs->hw.bas; + IFNULLRETVAL(ucs, -EFAULT); + + /* check if AT channel is open */ + if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) { + dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD, "AT channel not open"); + rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); + if (rc < 0) { + err("could not open AT channel"); + /* flush command queue */ + spin_lock_irqsave(&cs->cmdlock, flags); + while (cs->cmdbuf != NULL) + complete_cb(cs); + spin_unlock_irqrestore(&cs->cmdlock, flags); + } + return rc; + } + + /* try to send first command in queue */ + spin_lock_irqsave(&cs->cmdlock, flags); + + while ((cb = cs->cmdbuf) != NULL && + atomic_read(&ucs->basstate) & BS_ATREADY) { + ucs->retry_cmd_out = 0; + rc = atwrite_submit(cs, cb->buf, cb->len); + if (unlikely(rc)) { + retval = rc; + complete_cb(cs); + } + } + + spin_unlock_irqrestore(&cs->cmdlock, flags); + return retval; +} + +/* gigaset_write_cmd + * This function is called by the device independent part of the driver + * to transmit an AT command string to the Gigaset device. + * It encapsulates the device specific method for transmission over the + * direct USB connection to the base. + * The command string is added to the queue of commands to send, and + * USB transmission is started if necessary. + * parameters: + * cs controller state structure + * buf command string to send + * len number of bytes to send (max. IF_WRITEBUF) + * wake_tasklet tasklet to run when transmission is completed (NULL if none) + * return value: + * number of bytes queued on success + * error code < 0 on error + */ +static int gigaset_write_cmd(struct cardstate *cs, + const unsigned char *buf, int len, + struct tasklet_struct *wake_tasklet) +{ + struct cmdbuf_t *cb; + unsigned long flags; + int status; + + gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? + DEBUG_TRANSCMD : DEBUG_LOCKCMD, + "CMD Transmit", len, buf, 0); + + if (!atomic_read(&cs->connected)) { + err("%s: not connected", __func__); + return -ENODEV; + } + + if (len <= 0) + return 0; /* nothing to do */ + + if (len > IF_WRITEBUF) + len = IF_WRITEBUF; + if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { + err("%s: out of memory", __func__); + return -ENOMEM; + } + + memcpy(cb->buf, buf, len); + cb->len = len; + cb->offset = 0; + cb->next = NULL; + cb->wake_tasklet = wake_tasklet; + + spin_lock_irqsave(&cs->cmdlock, flags); + cb->prev = cs->lastcmdbuf; + if (cs->lastcmdbuf) + cs->lastcmdbuf->next = cb; + else { + cs->cmdbuf = cb; + cs->curlen = len; + } + cs->cmdbytes += len; + cs->lastcmdbuf = cb; + spin_unlock_irqrestore(&cs->cmdlock, flags); + + status = start_cbsend(cs); + + return status < 0 ? status : len; +} + +/* gigaset_write_room + * tty_driver.write_room interface routine + * return number of characters the driver will accept to be written via gigaset_write_cmd + * parameter: + * controller state structure + * return value: + * number of characters + */ +static int gigaset_write_room(struct cardstate *cs) +{ + return IF_WRITEBUF; +} + +/* gigaset_chars_in_buffer + * tty_driver.chars_in_buffer interface routine + * return number of characters waiting to be sent + * parameter: + * controller state structure + * return value: + * number of characters + */ +static int gigaset_chars_in_buffer(struct cardstate *cs) +{ + unsigned long flags; + unsigned bytes; + + spin_lock_irqsave(&cs->cmdlock, flags); + bytes = cs->cmdbytes; + spin_unlock_irqrestore(&cs->cmdlock, flags); + + return bytes; +} + +/* gigaset_brkchars + * implementation of ioctl(GIGASET_BRKCHARS) + * parameter: + * controller state structure + * return value: + * -EINVAL (unimplemented function) + */ +static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) +{ + return -EINVAL; +} + + +/* Device Initialization/Shutdown */ +/* ============================== */ + +/* Free hardware dependent part of the B channel structure + * parameter: + * bcs B channel structure + * return value: + * !=0 on success + */ +static int gigaset_freebcshw(struct bc_state *bcs) +{ + if (!bcs->hw.bas) + return 0; + + if (bcs->hw.bas->isooutbuf) + kfree(bcs->hw.bas->isooutbuf); + kfree(bcs->hw.bas); + bcs->hw.bas = NULL; + return 1; +} + +/* Initialize hardware dependent part of the B channel structure + * parameter: + * bcs B channel structure + * return value: + * !=0 on success + */ +static int gigaset_initbcshw(struct bc_state *bcs) +{ + int i; + struct bas_bc_state *ubc; + + bcs->hw.bas = ubc = kmalloc(sizeof(struct bas_bc_state), GFP_KERNEL); + if (!ubc) { + err("could not allocate bas_bc_state"); + return 0; + } + + atomic_set(&ubc->running, 0); + atomic_set(&ubc->corrbytes, 0); + spin_lock_init(&ubc->isooutlock); + for (i = 0; i < BAS_OUTURBS; ++i) { + ubc->isoouturbs[i].urb = NULL; + ubc->isoouturbs[i].bcs = bcs; + } + ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL; + ubc->numsub = 0; + if (!(ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL))) { + err("could not allocate isochronous output buffer"); + kfree(ubc); + bcs->hw.bas = NULL; + return 0; + } + tasklet_init(&ubc->sent_tasklet, + &write_iso_tasklet, (unsigned long) bcs); + + spin_lock_init(&ubc->isoinlock); + for (i = 0; i < BAS_INURBS; ++i) + ubc->isoinurbs[i] = NULL; + ubc->isoindone = NULL; + ubc->loststatus = -EINPROGRESS; + ubc->isoinlost = 0; + ubc->seqlen = 0; + ubc->inbyte = 0; + ubc->inbits = 0; + ubc->goodbytes = 0; + ubc->alignerrs = 0; + ubc->fcserrs = 0; + ubc->frameerrs = 0; + ubc->giants = 0; + ubc->runts = 0; + ubc->aborts = 0; + ubc->shared0s = 0; + ubc->stolen0s = 0; + tasklet_init(&ubc->rcvd_tasklet, + &read_iso_tasklet, (unsigned long) bcs); + return 1; +} + +static void gigaset_reinitbcshw(struct bc_state *bcs) +{ + struct bas_bc_state *ubc = bcs->hw.bas; + + atomic_set(&bcs->hw.bas->running, 0); + atomic_set(&bcs->hw.bas->corrbytes, 0); + bcs->hw.bas->numsub = 0; + spin_lock_init(&ubc->isooutlock); + spin_lock_init(&ubc->isoinlock); + ubc->loststatus = -EINPROGRESS; +} + +static void gigaset_freecshw(struct cardstate *cs) +{ + struct bas_cardstate *ucs = cs->hw.bas; + + del_timer(&ucs->timer_ctrl); + del_timer(&ucs->timer_atrdy); + del_timer(&ucs->timer_cmd_in); + + kfree(cs->hw.bas); +} + +static int gigaset_initcshw(struct cardstate *cs) +{ + struct bas_cardstate *ucs; + + cs->hw.bas = ucs = kmalloc(sizeof *ucs, GFP_KERNEL); + if (!ucs) + return 0; + + ucs->urb_cmd_in = NULL; + ucs->urb_cmd_out = NULL; + ucs->rcvbuf = NULL; + ucs->rcvbuf_size = 0; + + spin_lock_init(&ucs->lock); + ucs->pending = 0; + + atomic_set(&ucs->basstate, 0); + init_timer(&ucs->timer_ctrl); + init_timer(&ucs->timer_atrdy); + init_timer(&ucs->timer_cmd_in); + + return 1; +} + +/* freeurbs + * unlink and deallocate all URBs unconditionally + * caller must make sure that no commands are still in progress + * parameter: + * cs controller state structure + */ +static void freeurbs(struct cardstate *cs) +{ + struct bas_cardstate *ucs; + struct bas_bc_state *ubc; + int i, j; + + IFNULLRET(cs); + ucs = cs->hw.bas; + IFNULLRET(ucs); + + for (j = 0; j < 2; ++j) { + ubc = cs->bcs[j].hw.bas; + IFNULLCONT(ubc); + for (i = 0; i < BAS_OUTURBS; ++i) + if (ubc->isoouturbs[i].urb) { + usb_kill_urb(ubc->isoouturbs[i].urb); + dbg(DEBUG_INIT, + "%s: isoc output URB %d/%d unlinked", + __func__, j, i); + usb_free_urb(ubc->isoouturbs[i].urb); + ubc->isoouturbs[i].urb = NULL; + } + for (i = 0; i < BAS_INURBS; ++i) + if (ubc->isoinurbs[i]) { + usb_kill_urb(ubc->isoinurbs[i]); + dbg(DEBUG_INIT, + "%s: isoc input URB %d/%d unlinked", + __func__, j, i); + usb_free_urb(ubc->isoinurbs[i]); + ubc->isoinurbs[i] = NULL; + } + } + if (ucs->urb_int_in) { + usb_kill_urb(ucs->urb_int_in); + dbg(DEBUG_INIT, "%s: interrupt input URB unlinked", __func__); + usb_free_urb(ucs->urb_int_in); + ucs->urb_int_in = NULL; + } + if (ucs->urb_cmd_out) { + usb_kill_urb(ucs->urb_cmd_out); + dbg(DEBUG_INIT, "%s: command output URB unlinked", __func__); + usb_free_urb(ucs->urb_cmd_out); + ucs->urb_cmd_out = NULL; + } + if (ucs->urb_cmd_in) { + usb_kill_urb(ucs->urb_cmd_in); + dbg(DEBUG_INIT, "%s: command input URB unlinked", __func__); + usb_free_urb(ucs->urb_cmd_in); + ucs->urb_cmd_in = NULL; + } + if (ucs->urb_ctrl) { + usb_kill_urb(ucs->urb_ctrl); + dbg(DEBUG_INIT, "%s: control output URB unlinked", __func__); + usb_free_urb(ucs->urb_ctrl); + ucs->urb_ctrl = NULL; + } +} + +/* gigaset_probe + * This function is called when a new USB device is connected. + * It checks whether the new device is handled by this driver. + */ +static int gigaset_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_host_interface *hostif; + struct usb_device *udev = interface_to_usbdev(interface); + struct cardstate *cs = NULL; + struct bas_cardstate *ucs = NULL; + struct bas_bc_state *ubc; + struct usb_endpoint_descriptor *endpoint; + int i, j; + int ret; + + IFNULLRETVAL(udev, -ENODEV); + + dbg(DEBUG_ANY, + "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", + __func__, le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); + + /* See if the device offered us matches what we can accept */ + if ((le16_to_cpu(udev->descriptor.idVendor) != USB_GIGA_VENDOR_ID) || + (le16_to_cpu(udev->descriptor.idProduct) != USB_GIGA_PRODUCT_ID && + le16_to_cpu(udev->descriptor.idProduct) != USB_4175_PRODUCT_ID && + le16_to_cpu(udev->descriptor.idProduct) != USB_SX303_PRODUCT_ID && + le16_to_cpu(udev->descriptor.idProduct) != USB_SX353_PRODUCT_ID)) { + dbg(DEBUG_ANY, "%s: unmatched ID - exiting", __func__); + return -ENODEV; + } + + /* set required alternate setting */ + hostif = interface->cur_altsetting; + if (hostif->desc.bAlternateSetting != 3) { + dbg(DEBUG_ANY, + "%s: wrong alternate setting %d - trying to switch", + __func__, hostif->desc.bAlternateSetting); + if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) { + warn("usb_set_interface failed, device %d interface %d altsetting %d", + udev->devnum, hostif->desc.bInterfaceNumber, + hostif->desc.bAlternateSetting); + return -ENODEV; + } + hostif = interface->cur_altsetting; + } + + /* Reject application specific interfaces + */ + if (hostif->desc.bInterfaceClass != 255) { + warn("%s: bInterfaceClass == %d", + __func__, hostif->desc.bInterfaceClass); + return -ENODEV; + } + + info("%s: Device matched (Vendor: 0x%x, Product: 0x%x)", + __func__, le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); + + cs = gigaset_getunassignedcs(driver); + if (!cs) { + err("%s: no free cardstate", __func__); + return -ENODEV; + } + ucs = cs->hw.bas; + ucs->udev = udev; + ucs->interface = interface; + + /* allocate URBs: + * - one for the interrupt pipe + * - three for the different uses of the default control pipe + * - three for each isochronous pipe + */ + ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL); + if (!ucs->urb_int_in) { + err("No free urbs available"); + goto error; + } + ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL); + if (!ucs->urb_cmd_in) { + err("No free urbs available"); + goto error; + } + ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL); + if (!ucs->urb_cmd_out) { + err("No free urbs available"); + goto error; + } + ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL); + if (!ucs->urb_ctrl) { + err("No free urbs available"); + goto error; + } + + for (j = 0; j < 2; ++j) { + ubc = cs->bcs[j].hw.bas; + for (i = 0; i < BAS_OUTURBS; ++i) { + ubc->isoouturbs[i].urb = + usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL); + if (!ubc->isoouturbs[i].urb) { + err("No free urbs available"); + goto error; + } + } + for (i = 0; i < BAS_INURBS; ++i) { + ubc->isoinurbs[i] = + usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL); + if (!ubc->isoinurbs[i]) { + err("No free urbs available"); + goto error; + } + } + } + + ucs->rcvbuf = NULL; + ucs->rcvbuf_size = 0; + + /* Fill the interrupt urb and send it to the core */ + endpoint = &hostif->endpoint[0].desc; + usb_fill_int_urb(ucs->urb_int_in, udev, + usb_rcvintpipe(udev, + (endpoint->bEndpointAddress) & 0x0f), + ucs->int_in_buf, 3, read_int_callback, cs, + endpoint->bInterval); + ret = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL); + if (ret) { + err("could not submit interrupt URB: %s", get_usb_statmsg(ret)); + goto error; + } + + /* tell the device that the driver is ready */ + if ((ret = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0) + goto error; + + /* tell common part that the device is ready */ + if (startmode == SM_LOCKED) + atomic_set(&cs->mstate, MS_LOCKED); + if (!gigaset_start(cs)) + goto error; + + /* save address of controller structure */ + usb_set_intfdata(interface, cs); + + /* set up device sysfs */ + gigaset_init_dev_sysfs(interface); + return 0; + +error: + freeurbs(cs); + gigaset_unassign(cs); + return -ENODEV; +} + +/* gigaset_disconnect + * This function is called when the Gigaset base is unplugged. + */ +static void gigaset_disconnect(struct usb_interface *interface) +{ + struct cardstate *cs; + struct bas_cardstate *ucs; + + /* clear device sysfs */ + gigaset_free_dev_sysfs(interface); + + cs = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + IFNULLRET(cs); + ucs = cs->hw.bas; + IFNULLRET(ucs); + + info("disconnecting GigaSet base"); + gigaset_stop(cs); + freeurbs(cs); + kfree(ucs->rcvbuf); + ucs->rcvbuf = NULL; + ucs->rcvbuf_size = 0; + atomic_set(&ucs->basstate, 0); + gigaset_unassign(cs); +} + +static struct gigaset_ops gigops = { + gigaset_write_cmd, + gigaset_write_room, + gigaset_chars_in_buffer, + gigaset_brkchars, + gigaset_init_bchannel, + gigaset_close_bchannel, + gigaset_initbcshw, + gigaset_freebcshw, + gigaset_reinitbcshw, + gigaset_initcshw, + gigaset_freecshw, + gigaset_set_modem_ctrl, + gigaset_baud_rate, + gigaset_set_line_ctrl, + gigaset_isoc_send_skb, + gigaset_isoc_input, +}; + +/* bas_gigaset_init + * This function is called after the kernel module is loaded. + */ +static int __init bas_gigaset_init(void) +{ + int result; + + /* allocate memory for our driver state and intialize it */ + if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, + GIGASET_MODULENAME, GIGASET_DEVNAME, + GIGASET_DEVFSNAME, &gigops, + THIS_MODULE)) == NULL) + goto error; + + /* allocate memory for our device state and intialize it */ + cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, GIGASET_MODULENAME); + if (!cardstate) + goto error; + + /* register this driver with the USB subsystem */ + result = usb_register(&gigaset_usb_driver); + if (result < 0) { + err("usb_register failed (error %d)", -result); + goto error; + } + + info(DRIVER_AUTHOR); + info(DRIVER_DESC); + return 0; + +error: if (cardstate) + gigaset_freecs(cardstate); + cardstate = NULL; + if (driver) + gigaset_freedriver(driver); + driver = NULL; + return -1; +} + +/* bas_gigaset_exit + * This function is called before the kernel module is unloaded. + */ +static void __exit bas_gigaset_exit(void) +{ + gigaset_blockdriver(driver); /* => probe will fail + * => no gigaset_start any more + */ + + gigaset_shutdown(cardstate); + /* from now on, no isdn callback should be possible */ + + if (atomic_read(&cardstate->hw.bas->basstate) & BS_ATOPEN) { + dbg(DEBUG_ANY, "closing AT channel"); + if (req_submit(cardstate->bcs, + HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT) >= 0) { + /* successfully submitted - wait for completion */ + //wait_event_interruptible(cs->initwait, !cs->hw.bas->pending); + //FIXME need own wait queue? wakeup? + } + } + + /* deregister this driver with the USB subsystem */ + usb_deregister(&gigaset_usb_driver); + /* this will call the disconnect-callback */ + /* from now on, no disconnect/probe callback should be running */ + + gigaset_freecs(cardstate); + cardstate = NULL; + gigaset_freedriver(driver); + driver = NULL; +} + + +module_init(bas_gigaset_init); +module_exit(bas_gigaset_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 76bb4685bff8781b5dbcd7080171d1e1f8c82f5b Mon Sep 17 00:00:00 2001 From: Hansjoerg Lipp Date: Sun, 26 Mar 2006 01:38:36 -0800 Subject: [PATCH] isdn4linux: Siemens Gigaset drivers - isochronous data handler And: Tilman Schmidt This patch adds the payload data handler for the connection-specific module "bas_gigaset". It contains the code for handling isochronous data transfers, HDLC framing and flow control. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Cc: Karsten Keil Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/gigaset/isocdata.c | 1009 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1009 insertions(+) create mode 100644 drivers/isdn/gigaset/isocdata.c (limited to 'drivers') diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c new file mode 100644 index 000000000000..5744eb91b315 --- /dev/null +++ b/drivers/isdn/gigaset/isocdata.c @@ -0,0 +1,1009 @@ +/* + * Common data handling layer for bas_gigaset + * + * Copyright (c) 2005 by Tilman Schmidt , + * Hansjoerg Lipp . + * + * ===================================================================== + * 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. + * ===================================================================== + * ToDo: ... + * ===================================================================== + * Version: $Id: isocdata.c,v 1.2.2.5 2005/11/13 23:05:19 hjlipp Exp $ + * ===================================================================== + */ + +#include "gigaset.h" +#include + +/* access methods for isowbuf_t */ +/* ============================ */ + +/* initialize buffer structure + */ +void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle) +{ + atomic_set(&iwb->read, 0); + atomic_set(&iwb->nextread, 0); + atomic_set(&iwb->write, 0); + atomic_set(&iwb->writesem, 1); + iwb->wbits = 0; + iwb->idle = idle; + memset(iwb->data + BAS_OUTBUFSIZE, idle, BAS_OUTBUFPAD); +} + +/* compute number of bytes which can be appended to buffer + * so that there is still room to append a maximum frame of flags + */ +static inline int isowbuf_freebytes(struct isowbuf_t *iwb) +{ + int read, write, freebytes; + + read = atomic_read(&iwb->read); + write = atomic_read(&iwb->write); + if ((freebytes = read - write) > 0) { + /* no wraparound: need padding space within regular area */ + return freebytes - BAS_OUTBUFPAD; + } else if (read < BAS_OUTBUFPAD) { + /* wraparound: can use space up to end of regular area */ + return BAS_OUTBUFSIZE - write; + } else { + /* following the wraparound yields more space */ + return freebytes + BAS_OUTBUFSIZE - BAS_OUTBUFPAD; + } +} + +/* compare two offsets within the buffer + * The buffer is seen as circular, with the read position as start + * returns -1/0/1 if position a position b without crossing 'read' + */ +static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b) +{ + int read; + if (a == b) + return 0; + read = atomic_read(&iwb->read); + if (a < b) { + if (a < read && read <= b) + return +1; + else + return -1; + } else { + if (b < read && read <= a) + return -1; + else + return +1; + } +} + +/* start writing + * acquire the write semaphore + * return true if acquired, false if busy + */ +static inline int isowbuf_startwrite(struct isowbuf_t *iwb) +{ + if (!atomic_dec_and_test(&iwb->writesem)) { + atomic_inc(&iwb->writesem); + dbg(DEBUG_ISO, + "%s: couldn't acquire iso write semaphore", __func__); + return 0; + } +#ifdef CONFIG_GIGASET_DEBUG + dbg(DEBUG_ISO, + "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", + __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits); +#endif + return 1; +} + +/* finish writing + * release the write semaphore and update the maximum buffer fill level + * returns the current write position + */ +static inline int isowbuf_donewrite(struct isowbuf_t *iwb) +{ + int write = atomic_read(&iwb->write); + atomic_inc(&iwb->writesem); + return write; +} + +/* append bits to buffer without any checks + * - data contains bits to append, starting at LSB + * - nbits is number of bits to append (0..24) + * must be called with the write semaphore held + * If more than nbits bits are set in data, the extraneous bits are set in the + * buffer too, but the write position is only advanced by nbits. + */ +static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits) +{ + int write = atomic_read(&iwb->write); + data <<= iwb->wbits; + data |= iwb->data[write]; + nbits += iwb->wbits; + while (nbits >= 8) { + iwb->data[write++] = data & 0xff; + write %= BAS_OUTBUFSIZE; + data >>= 8; + nbits -= 8; + } + iwb->wbits = nbits; + iwb->data[write] = data & 0xff; + atomic_set(&iwb->write, write); +} + +/* put final flag on HDLC bitstream + * also sets the idle fill byte to the correspondingly shifted flag pattern + * must be called with the write semaphore held + */ +static inline void isowbuf_putflag(struct isowbuf_t *iwb) +{ + int write; + + /* add two flags, thus reliably covering one byte */ + isowbuf_putbits(iwb, 0x7e7e, 8); + /* recover the idle flag byte */ + write = atomic_read(&iwb->write); + iwb->idle = iwb->data[write]; + dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); + /* mask extraneous bits in buffer */ + iwb->data[write] &= (1 << iwb->wbits) - 1; +} + +/* retrieve a block of bytes for sending + * The requested number of bytes is provided as a contiguous block. + * If necessary, the frame is filled to the requested number of bytes + * with the idle value. + * returns offset to frame, < 0 on busy or error + */ +int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) +{ + int read, write, limit, src, dst; + unsigned char pbyte; + + read = atomic_read(&iwb->nextread); + write = atomic_read(&iwb->write); + if (likely(read == write)) { + //dbg(DEBUG_STREAM, "%s: send buffer empty", __func__); + /* return idle frame */ + return read < BAS_OUTBUFPAD ? + BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD; + } + + limit = read + size; + dbg(DEBUG_STREAM, + "%s: read=%d write=%d limit=%d", __func__, read, write, limit); +#ifdef CONFIG_GIGASET_DEBUG + if (unlikely(size < 0 || size > BAS_OUTBUFPAD)) { + err("invalid size %d", size); + return -EINVAL; + } + src = atomic_read(&iwb->read); + if (unlikely(limit > BAS_OUTBUFSIZE + BAS_OUTBUFPAD || + (read < src && limit >= src))) { + err("isoc write buffer frame reservation violated"); + return -EFAULT; + } +#endif + + if (read < write) { + /* no wraparound in valid data */ + if (limit >= write) { + /* append idle frame */ + if (!isowbuf_startwrite(iwb)) + return -EBUSY; + /* write position could have changed */ + if (limit >= (write = atomic_read(&iwb->write))) { + pbyte = iwb->data[write]; /* save partial byte */ + limit = write + BAS_OUTBUFPAD; + dbg(DEBUG_STREAM, + "%s: filling %d->%d with %02x", + __func__, write, limit, iwb->idle); + if (write + BAS_OUTBUFPAD < BAS_OUTBUFSIZE) + memset(iwb->data + write, iwb->idle, + BAS_OUTBUFPAD); + else { + /* wraparound, fill entire pad area */ + memset(iwb->data + write, iwb->idle, + BAS_OUTBUFSIZE + BAS_OUTBUFPAD + - write); + limit = 0; + } + dbg(DEBUG_STREAM, "%s: restoring %02x at %d", + __func__, pbyte, limit); + iwb->data[limit] = pbyte; /* restore partial byte */ + atomic_set(&iwb->write, limit); + } + isowbuf_donewrite(iwb); + } + } else { + /* valid data wraparound */ + if (limit >= BAS_OUTBUFSIZE) { + /* copy wrapped part into pad area */ + src = 0; + dst = BAS_OUTBUFSIZE; + while (dst < limit && src < write) + iwb->data[dst++] = iwb->data[src++]; + if (dst <= limit) { + /* fill pad area with idle byte */ + memset(iwb->data + dst, iwb->idle, + BAS_OUTBUFSIZE + BAS_OUTBUFPAD - dst); + } + limit = src; + } + } + atomic_set(&iwb->nextread, limit); + return read; +} + +/* dump_bytes + * write hex bytes to syslog for debugging + */ +static inline void dump_bytes(enum debuglevel level, const char *tag, + unsigned char *bytes, int count) +{ +#ifdef CONFIG_GIGASET_DEBUG + unsigned char c; + static char dbgline[3 * 32 + 1]; + static const char hexdigit[] = "0123456789abcdef"; + int i = 0; + IFNULLRET(tag); + IFNULLRET(bytes); + while (count-- > 0) { + if (i > sizeof(dbgline) - 4) { + dbgline[i] = '\0'; + dbg(level, "%s:%s", tag, dbgline); + i = 0; + } + c = *bytes++; + dbgline[i] = (i && !(i % 12)) ? '-' : ' '; + i++; + dbgline[i++] = hexdigit[(c >> 4) & 0x0f]; + dbgline[i++] = hexdigit[c & 0x0f]; + } + dbgline[i] = '\0'; + dbg(level, "%s:%s", tag, dbgline); +#endif +} + +/*============================================================================*/ + +/* bytewise HDLC bitstuffing via table lookup + * lookup table: 5 subtables for 0..4 preceding consecutive '1' bits + * index: 256*(number of preceding '1' bits) + (next byte to stuff) + * value: bit 9.. 0 = result bits + * bit 12..10 = number of trailing '1' bits in result + * bit 14..13 = number of bits added by stuffing + */ +static u16 stufftab[5 * 256] = { +// previous 1s = 0: + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x205f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x209f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20df, + 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f, + 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x251f, + 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af, + 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x255f, + 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x08cf, + 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x299f, + 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef, + 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf, + +// previous 1s = 1: + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x206f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x208f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20af, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20cf, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20ef, + 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x250f, + 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x252f, + 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x254f, + 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x256f, + 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x298f, + 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29af, + 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf, + 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef, + +// previous 1s = 2: + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x2067, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x2077, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x2087, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x2097, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x20a7, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20b7, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x20c7, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20d7, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x20e7, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20f7, + 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x2507, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x2517, + 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x2527, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x2537, + 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x2547, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x2557, + 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x2567, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x2577, + 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x2987, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x2997, + 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x29a7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29b7, + 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7, + 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7, + +// previous 1s = 3: + 0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b, + 0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b, + 0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b, + 0x0030, 0x0031, 0x0032, 0x2063, 0x0034, 0x0035, 0x0036, 0x206b, 0x0038, 0x0039, 0x003a, 0x2073, 0x003c, 0x003d, 0x203e, 0x207b, + 0x0040, 0x0041, 0x0042, 0x2083, 0x0044, 0x0045, 0x0046, 0x208b, 0x0048, 0x0049, 0x004a, 0x2093, 0x004c, 0x004d, 0x004e, 0x209b, + 0x0050, 0x0051, 0x0052, 0x20a3, 0x0054, 0x0055, 0x0056, 0x20ab, 0x0058, 0x0059, 0x005a, 0x20b3, 0x005c, 0x005d, 0x005e, 0x20bb, + 0x0060, 0x0061, 0x0062, 0x20c3, 0x0064, 0x0065, 0x0066, 0x20cb, 0x0068, 0x0069, 0x006a, 0x20d3, 0x006c, 0x006d, 0x006e, 0x20db, + 0x0070, 0x0071, 0x0072, 0x20e3, 0x0074, 0x0075, 0x0076, 0x20eb, 0x0078, 0x0079, 0x007a, 0x20f3, 0x207c, 0x207d, 0x20be, 0x40fb, + 0x0480, 0x0481, 0x0482, 0x2503, 0x0484, 0x0485, 0x0486, 0x250b, 0x0488, 0x0489, 0x048a, 0x2513, 0x048c, 0x048d, 0x048e, 0x251b, + 0x0490, 0x0491, 0x0492, 0x2523, 0x0494, 0x0495, 0x0496, 0x252b, 0x0498, 0x0499, 0x049a, 0x2533, 0x049c, 0x049d, 0x049e, 0x253b, + 0x04a0, 0x04a1, 0x04a2, 0x2543, 0x04a4, 0x04a5, 0x04a6, 0x254b, 0x04a8, 0x04a9, 0x04aa, 0x2553, 0x04ac, 0x04ad, 0x04ae, 0x255b, + 0x04b0, 0x04b1, 0x04b2, 0x2563, 0x04b4, 0x04b5, 0x04b6, 0x256b, 0x04b8, 0x04b9, 0x04ba, 0x2573, 0x04bc, 0x04bd, 0x253e, 0x257b, + 0x08c0, 0x08c1, 0x08c2, 0x2983, 0x08c4, 0x08c5, 0x08c6, 0x298b, 0x08c8, 0x08c9, 0x08ca, 0x2993, 0x08cc, 0x08cd, 0x08ce, 0x299b, + 0x08d0, 0x08d1, 0x08d2, 0x29a3, 0x08d4, 0x08d5, 0x08d6, 0x29ab, 0x08d8, 0x08d9, 0x08da, 0x29b3, 0x08dc, 0x08dd, 0x08de, 0x29bb, + 0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb, + 0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb, + +// previous 1s = 4: + 0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d, + 0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d, + 0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d, + 0x0030, 0x2061, 0x0032, 0x2065, 0x0034, 0x2069, 0x0036, 0x206d, 0x0038, 0x2071, 0x003a, 0x2075, 0x003c, 0x2079, 0x203e, 0x407d, + 0x0040, 0x2081, 0x0042, 0x2085, 0x0044, 0x2089, 0x0046, 0x208d, 0x0048, 0x2091, 0x004a, 0x2095, 0x004c, 0x2099, 0x004e, 0x209d, + 0x0050, 0x20a1, 0x0052, 0x20a5, 0x0054, 0x20a9, 0x0056, 0x20ad, 0x0058, 0x20b1, 0x005a, 0x20b5, 0x005c, 0x20b9, 0x005e, 0x20bd, + 0x0060, 0x20c1, 0x0062, 0x20c5, 0x0064, 0x20c9, 0x0066, 0x20cd, 0x0068, 0x20d1, 0x006a, 0x20d5, 0x006c, 0x20d9, 0x006e, 0x20dd, + 0x0070, 0x20e1, 0x0072, 0x20e5, 0x0074, 0x20e9, 0x0076, 0x20ed, 0x0078, 0x20f1, 0x007a, 0x20f5, 0x207c, 0x40f9, 0x20be, 0x417d, + 0x0480, 0x2501, 0x0482, 0x2505, 0x0484, 0x2509, 0x0486, 0x250d, 0x0488, 0x2511, 0x048a, 0x2515, 0x048c, 0x2519, 0x048e, 0x251d, + 0x0490, 0x2521, 0x0492, 0x2525, 0x0494, 0x2529, 0x0496, 0x252d, 0x0498, 0x2531, 0x049a, 0x2535, 0x049c, 0x2539, 0x049e, 0x253d, + 0x04a0, 0x2541, 0x04a2, 0x2545, 0x04a4, 0x2549, 0x04a6, 0x254d, 0x04a8, 0x2551, 0x04aa, 0x2555, 0x04ac, 0x2559, 0x04ae, 0x255d, + 0x04b0, 0x2561, 0x04b2, 0x2565, 0x04b4, 0x2569, 0x04b6, 0x256d, 0x04b8, 0x2571, 0x04ba, 0x2575, 0x04bc, 0x2579, 0x253e, 0x467d, + 0x08c0, 0x2981, 0x08c2, 0x2985, 0x08c4, 0x2989, 0x08c6, 0x298d, 0x08c8, 0x2991, 0x08ca, 0x2995, 0x08cc, 0x2999, 0x08ce, 0x299d, + 0x08d0, 0x29a1, 0x08d2, 0x29a5, 0x08d4, 0x29a9, 0x08d6, 0x29ad, 0x08d8, 0x29b1, 0x08da, 0x29b5, 0x08dc, 0x29b9, 0x08de, 0x29bd, + 0x0ce0, 0x2dc1, 0x0ce2, 0x2dc5, 0x0ce4, 0x2dc9, 0x0ce6, 0x2dcd, 0x0ce8, 0x2dd1, 0x0cea, 0x2dd5, 0x0cec, 0x2dd9, 0x0cee, 0x2ddd, + 0x10f0, 0x31e1, 0x10f2, 0x31e5, 0x10f4, 0x31e9, 0x10f6, 0x31ed, 0x20f8, 0x41f1, 0x20fa, 0x41f5, 0x257c, 0x46f9, 0x29be, 0x4b7d +}; + +/* hdlc_bitstuff_byte + * perform HDLC bitstuffing for one input byte (8 bits, LSB first) + * parameters: + * cin input byte + * ones number of trailing '1' bits in result before this step + * iwb pointer to output buffer structure (write semaphore must be held) + * return value: + * number of trailing '1' bits in result after this step + */ + +static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin, + int ones) +{ + u16 stuff; + int shiftinc, newones; + + /* get stuffing information for input byte + * value: bit 9.. 0 = result bits + * bit 12..10 = number of trailing '1' bits in result + * bit 14..13 = number of bits added by stuffing + */ + stuff = stufftab[256 * ones + cin]; + shiftinc = (stuff >> 13) & 3; + newones = (stuff >> 10) & 7; + stuff &= 0x3ff; + + /* append stuffed byte to output stream */ + isowbuf_putbits(iwb, stuff, 8 + shiftinc); + return newones; +} + +/* hdlc_buildframe + * Perform HDLC framing with bitstuffing on a byte buffer + * The input buffer is regarded as a sequence of bits, starting with the least + * significant bit of the first byte and ending with the most significant bit + * of the last byte. A 16 bit FCS is appended as defined by RFC 1662. + * Whenever five consecutive '1' bits appear in the resulting bit sequence, a + * '0' bit is inserted after them. + * The resulting bit string and a closing flag pattern (PPP_FLAG, '01111110') + * are appended to the output buffer starting at the given bit position, which + * is assumed to already contain a leading flag. + * The output buffer must have sufficient length; count + count/5 + 6 bytes + * starting at *out are safe and are verified to be present. + * parameters: + * in input buffer + * count number of bytes in input buffer + * iwb pointer to output buffer structure (write semaphore must be held) + * return value: + * position of end of packet in output buffer on success, + * -EAGAIN if write semaphore busy or buffer full + */ + +static inline int hdlc_buildframe(struct isowbuf_t *iwb, + unsigned char *in, int count) +{ + int ones; + u16 fcs; + int end; + unsigned char c; + + if (isowbuf_freebytes(iwb) < count + count / 5 + 6 || + !isowbuf_startwrite(iwb)) { + dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN", + __func__, isowbuf_freebytes(iwb)); + return -EAGAIN; + } + + dump_bytes(DEBUG_STREAM, "snd data", in, count); + + /* bitstuff and checksum input data */ + fcs = PPP_INITFCS; + ones = 0; + while (count-- > 0) { + c = *in++; + ones = hdlc_bitstuff_byte(iwb, c, ones); + fcs = crc_ccitt_byte(fcs, c); + } + + /* bitstuff and append FCS (complemented, least significant byte first) */ + fcs ^= 0xffff; + ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones); + ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones); + + /* put closing flag and repeat byte for flag idle */ + isowbuf_putflag(iwb); + end = isowbuf_donewrite(iwb); + dump_bytes(DEBUG_STREAM_DUMP, "isowbuf", iwb->data, end + 1); + return end; +} + +/* trans_buildframe + * Append a block of 'transparent' data to the output buffer, + * inverting the bytes. + * The output buffer must have sufficient length; count bytes + * starting at *out are safe and are verified to be present. + * parameters: + * in input buffer + * count number of bytes in input buffer + * iwb pointer to output buffer structure (write semaphore must be held) + * return value: + * position of end of packet in output buffer on success, + * -EAGAIN if write semaphore busy or buffer full + */ + +static inline int trans_buildframe(struct isowbuf_t *iwb, + unsigned char *in, int count) +{ + int write; + unsigned char c; + + if (unlikely(count <= 0)) + return atomic_read(&iwb->write); /* better ideas? */ + + if (isowbuf_freebytes(iwb) < count || + !isowbuf_startwrite(iwb)) { + dbg(DEBUG_ISO, "can't put %d bytes", count); + return -EAGAIN; + } + + dbg(DEBUG_STREAM, "put %d bytes", count); + write = atomic_read(&iwb->write); + do { + c = gigaset_invtab[*in++]; + iwb->data[write++] = c; + write %= BAS_OUTBUFSIZE; + } while (--count > 0); + atomic_set(&iwb->write, write); + iwb->idle = c; + + return isowbuf_donewrite(iwb); +} + +int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) +{ + int result; + + switch (bcs->proto2) { + case ISDN_PROTO_L2_HDLC: + result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len); + dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", __func__, len, result); + break; + default: /* assume transparent */ + result = trans_buildframe(bcs->hw.bas->isooutbuf, in, len); + dbg(DEBUG_ISO, "%s: %d bytes trans -> %d", __func__, len, result); + } + return result; +} + +/* hdlc_putbyte + * append byte c to current skb of B channel structure *bcs, updating fcs + */ +static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) +{ + bcs->fcs = crc_ccitt_byte(bcs->fcs, c); + if (unlikely(bcs->skb == NULL)) { + /* skipping */ + return; + } + if (unlikely(bcs->skb->len == SBUFSIZE)) { + warn("received oversized packet discarded"); + bcs->hw.bas->giants++; + dev_kfree_skb_any(bcs->skb); + bcs->skb = NULL; + return; + } + *gigaset_skb_put_quick(bcs->skb, 1) = c; +} + +/* hdlc_flush + * drop partial HDLC data packet + */ +static inline void hdlc_flush(struct bc_state *bcs) +{ + /* clear skb or allocate new if not skipping */ + if (likely(bcs->skb != NULL)) + skb_trim(bcs->skb, 0); + else if (!bcs->ignore) { + if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) + skb_reserve(bcs->skb, HW_HDR_LEN); + else + err("could not allocate skb"); + } + + /* reset packet state */ + bcs->fcs = PPP_INITFCS; +} + +/* hdlc_done + * process completed HDLC data packet + */ +static inline void hdlc_done(struct bc_state *bcs) +{ + struct sk_buff *procskb; + + if (unlikely(bcs->ignore)) { + bcs->ignore--; + hdlc_flush(bcs); + return; + } + + if ((procskb = bcs->skb) == NULL) { + /* previous error */ + dbg(DEBUG_ISO, "%s: skb=NULL", __func__); + gigaset_rcv_error(NULL, bcs->cs, bcs); + } else if (procskb->len < 2) { + notice("received short frame (%d octets)", procskb->len); + bcs->hw.bas->runts++; + gigaset_rcv_error(procskb, bcs->cs, bcs); + } else if (bcs->fcs != PPP_GOODFCS) { + notice("frame check error (0x%04x)", bcs->fcs); + bcs->hw.bas->fcserrs++; + gigaset_rcv_error(procskb, bcs->cs, bcs); + } else { + procskb->len -= 2; /* subtract FCS */ + procskb->tail -= 2; + dbg(DEBUG_ISO, + "%s: good frame (%d octets)", __func__, procskb->len); + dump_bytes(DEBUG_STREAM, + "rcv data", procskb->data, procskb->len); + bcs->hw.bas->goodbytes += procskb->len; + gigaset_rcv_skb(procskb, bcs->cs, bcs); + } + + if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) + skb_reserve(bcs->skb, HW_HDR_LEN); + else + err("could not allocate skb"); + bcs->fcs = PPP_INITFCS; +} + +/* hdlc_frag + * drop HDLC data packet with non-integral last byte + */ +static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) +{ + if (unlikely(bcs->ignore)) { + bcs->ignore--; + hdlc_flush(bcs); + return; + } + + notice("received partial byte (%d bits)", inbits); + bcs->hw.bas->alignerrs++; + gigaset_rcv_error(bcs->skb, bcs->cs, bcs); + + if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) + skb_reserve(bcs->skb, HW_HDR_LEN); + else + err("could not allocate skb"); + bcs->fcs = PPP_INITFCS; +} + +/* bit counts lookup table for HDLC bit unstuffing + * index: input byte + * value: bit 0..3 = number of consecutive '1' bits starting from LSB + * bit 4..6 = number of consecutive '1' bits starting from MSB + * (replacing 8 by 7 to make it fit; the algorithm won't care) + * bit 7 set if there are 5 or more "interior" consecutive '1' bits + */ +static unsigned char bitcounts[256] = { + 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x80, 0x06, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x80, 0x81, 0x80, 0x07, + 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14, + 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x15, + 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14, + 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x90, 0x16, + 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x24, + 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x25, + 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x34, + 0x40, 0x41, 0x40, 0x42, 0x40, 0x41, 0x40, 0x43, 0x50, 0x51, 0x50, 0x52, 0x60, 0x61, 0x70, 0x78 +}; + +/* hdlc_unpack + * perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation) + * on a sequence of received data bytes (8 bits each, LSB first) + * pass on successfully received, complete frames as SKBs via gigaset_rcv_skb + * notify of errors via gigaset_rcv_error + * tally frames, errors etc. in BC structure counters + * parameters: + * src received data + * count number of received bytes + * bcs receiving B channel structure + */ +static inline void hdlc_unpack(unsigned char *src, unsigned count, + struct bc_state *bcs) +{ + struct bas_bc_state *ubc; + int inputstate; + unsigned seqlen, inbyte, inbits; + + IFNULLRET(bcs); + ubc = bcs->hw.bas; + IFNULLRET(ubc); + + /* load previous state: + * inputstate = set of flag bits: + * - INS_flag_hunt: no complete opening flag received since connection setup or last abort + * - INS_have_data: at least one complete data byte received since last flag + * seqlen = number of consecutive '1' bits in last 7 input stream bits (0..7) + * inbyte = accumulated partial data byte (if !INS_flag_hunt) + * inbits = number of valid bits in inbyte, starting at LSB (0..6) + */ + inputstate = bcs->inputstate; + seqlen = ubc->seqlen; + inbyte = ubc->inbyte; + inbits = ubc->inbits; + + /* bit unstuffing a byte a time + * Take your time to understand this; it's straightforward but tedious. + * The "bitcounts" lookup table is used to speed up the counting of + * leading and trailing '1' bits. + */ + while (count--) { + unsigned char c = *src++; + unsigned char tabentry = bitcounts[c]; + unsigned lead1 = tabentry & 0x0f; + unsigned trail1 = (tabentry >> 4) & 0x0f; + + seqlen += lead1; + + if (unlikely(inputstate & INS_flag_hunt)) { + if (c == PPP_FLAG) { + /* flag-in-one */ + inputstate &= ~(INS_flag_hunt | INS_have_data); + inbyte = 0; + inbits = 0; + } else if (seqlen == 6 && trail1 != 7) { + /* flag completed & not followed by abort */ + inputstate &= ~(INS_flag_hunt | INS_have_data); + inbyte = c >> (lead1 + 1); + inbits = 7 - lead1; + if (trail1 >= 8) { + /* interior stuffing: omitting the MSB handles most cases */ + inbits--; + /* correct the incorrectly handled cases individually */ + switch (c) { + case 0xbe: + inbyte = 0x3f; + break; + } + } + } + /* else: continue flag-hunting */ + } else if (likely(seqlen < 5 && trail1 < 7)) { + /* streamlined case: 8 data bits, no stuffing */ + inbyte |= c << inbits; + hdlc_putbyte(inbyte & 0xff, bcs); + inputstate |= INS_have_data; + inbyte >>= 8; + /* inbits unchanged */ + } else if (likely(seqlen == 6 && inbits == 7 - lead1 && + trail1 + 1 == inbits && + !(inputstate & INS_have_data))) { + /* streamlined case: flag idle - state unchanged */ + } else if (unlikely(seqlen > 6)) { + /* abort sequence */ + ubc->aborts++; + hdlc_flush(bcs); + inputstate |= INS_flag_hunt; + } else if (seqlen == 6) { + /* closing flag, including (6 - lead1) '1's and one '0' from inbits */ + if (inbits > 7 - lead1) { + hdlc_frag(bcs, inbits + lead1 - 7); + inputstate &= ~INS_have_data; + } else { + if (inbits < 7 - lead1) + ubc->stolen0s ++; + if (inputstate & INS_have_data) { + hdlc_done(bcs); + inputstate &= ~INS_have_data; + } + } + + if (c == PPP_FLAG) { + /* complete flag, LSB overlaps preceding flag */ + ubc->shared0s ++; + inbits = 0; + inbyte = 0; + } else if (trail1 != 7) { + /* remaining bits */ + inbyte = c >> (lead1 + 1); + inbits = 7 - lead1; + if (trail1 >= 8) { + /* interior stuffing: omitting the MSB handles most cases */ + inbits--; + /* correct the incorrectly handled cases individually */ + switch (c) { + case 0xbe: + inbyte = 0x3f; + break; + } + } + } else { + /* abort sequence follows, skb already empty anyway */ + ubc->aborts++; + inputstate |= INS_flag_hunt; + } + } else { /* (seqlen < 6) && (seqlen == 5 || trail1 >= 7) */ + + if (c == PPP_FLAG) { + /* complete flag */ + if (seqlen == 5) + ubc->stolen0s++; + if (inbits) { + hdlc_frag(bcs, inbits); + inbits = 0; + inbyte = 0; + } else if (inputstate & INS_have_data) + hdlc_done(bcs); + inputstate &= ~INS_have_data; + } else if (trail1 == 7) { + /* abort sequence */ + ubc->aborts++; + hdlc_flush(bcs); + inputstate |= INS_flag_hunt; + } else { + /* stuffed data */ + if (trail1 < 7) { /* => seqlen == 5 */ + /* stuff bit at position lead1, no interior stuffing */ + unsigned char mask = (1 << lead1) - 1; + c = (c & mask) | ((c & ~mask) >> 1); + inbyte |= c << inbits; + inbits += 7; + } else if (seqlen < 5) { /* trail1 >= 8 */ + /* interior stuffing: omitting the MSB handles most cases */ + /* correct the incorrectly handled cases individually */ + switch (c) { + case 0xbe: + c = 0x7e; + break; + } + inbyte |= c << inbits; + inbits += 7; + } else { /* seqlen == 5 && trail1 >= 8 */ + + /* stuff bit at lead1 *and* interior stuffing */ + switch (c) { /* unstuff individually */ + case 0x7d: + c = 0x3f; + break; + case 0xbe: + c = 0x3f; + break; + case 0x3e: + c = 0x1f; + break; + case 0x7c: + c = 0x3e; + break; + } + inbyte |= c << inbits; + inbits += 6; + } + if (inbits >= 8) { + inbits -= 8; + hdlc_putbyte(inbyte & 0xff, bcs); + inputstate |= INS_have_data; + inbyte >>= 8; + } + } + } + seqlen = trail1 & 7; + } + + /* save new state */ + bcs->inputstate = inputstate; + ubc->seqlen = seqlen; + ubc->inbyte = inbyte; + ubc->inbits = inbits; +} + +/* trans_receive + * pass on received USB frame transparently as SKB via gigaset_rcv_skb + * invert bytes + * tally frames, errors etc. in BC structure counters + * parameters: + * src received data + * count number of received bytes + * bcs receiving B channel structure + */ +static inline void trans_receive(unsigned char *src, unsigned count, + struct bc_state *bcs) +{ + struct sk_buff *skb; + int dobytes; + unsigned char *dst; + + if (unlikely(bcs->ignore)) { + bcs->ignore--; + hdlc_flush(bcs); + return; + } + if (unlikely((skb = bcs->skb) == NULL)) { + bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); + if (!skb) { + err("could not allocate skb"); + return; + } + skb_reserve(skb, HW_HDR_LEN); + } + bcs->hw.bas->goodbytes += skb->len; + dobytes = TRANSBUFSIZE - skb->len; + while (count > 0) { + dst = skb_put(skb, count < dobytes ? count : dobytes); + while (count > 0 && dobytes > 0) { + *dst++ = gigaset_invtab[*src++]; + count--; + dobytes--; + } + if (dobytes == 0) { + gigaset_rcv_skb(skb, bcs->cs, bcs); + bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); + if (!skb) { + err("could not allocate skb"); + return; + } + skb_reserve(bcs->skb, HW_HDR_LEN); + dobytes = TRANSBUFSIZE; + } + } +} + +void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs) +{ + switch (bcs->proto2) { + case ISDN_PROTO_L2_HDLC: + hdlc_unpack(src, count, bcs); + break; + default: /* assume transparent */ + trans_receive(src, count, bcs); + } +} + +/* == data input =========================================================== */ + +static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) +{ + struct cardstate *cs = inbuf->cs; + unsigned cbytes = cs->cbytes; + + while (numbytes--) { + /* copy next character, check for end of line */ + switch (cs->respdata[cbytes] = *src++) { + case '\r': + case '\n': + /* end of line */ + dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", + __func__, cbytes); + cs->cbytes = cbytes; + gigaset_handle_modem_response(cs); + cbytes = 0; + break; + default: + /* advance in line buffer, checking for overflow */ + if (cbytes < MAX_RESP_SIZE - 1) + cbytes++; + else + warn("response too large"); + } + } + + /* save state */ + cs->cbytes = cbytes; +} + + +/* process a block of data received through the control channel + */ +void gigaset_isoc_input(struct inbuf_t *inbuf) +{ + struct cardstate *cs = inbuf->cs; + unsigned tail, head, numbytes; + unsigned char *src; + + head = atomic_read(&inbuf->head); + while (head != (tail = atomic_read(&inbuf->tail))) { + dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); + if (head > tail) + tail = RBUFSIZE; + src = inbuf->data + head; + numbytes = tail - head; + dbg(DEBUG_INTR, "processing %u bytes", numbytes); + + if (atomic_read(&cs->mstate) == MS_LOCKED) { + gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", + numbytes, src, 0); + gigaset_if_receive(inbuf->cs, src, numbytes); + } else { + gigaset_dbg_buffer(DEBUG_CMD, "received response", + numbytes, src, 0); + cmd_loop(src, numbytes, inbuf); + } + + head += numbytes; + if (head == RBUFSIZE) + head = 0; + dbg(DEBUG_INTR, "setting head to %u", head); + atomic_set(&inbuf->head, head); + } +} + + +/* == data output ========================================================== */ + +/* gigaset_send_skb + * called by common.c to queue an skb for sending + * and start transmission if necessary + * parameters: + * B Channel control structure + * skb + * return value: + * number of bytes accepted for sending + * (skb->len if ok, 0 if out of buffer space) + * or error code (< 0, eg. -EINVAL) + */ +int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb) +{ + int len; + + IFNULLRETVAL(bcs, -EFAULT); + IFNULLRETVAL(skb, -EFAULT); + len = skb->len; + + skb_queue_tail(&bcs->squeue, skb); + dbg(DEBUG_ISO, + "%s: skb queued, qlen=%d", __func__, skb_queue_len(&bcs->squeue)); + + /* tasklet submits URB if necessary */ + tasklet_schedule(&bcs->hw.bas->sent_tasklet); + + return len; /* ok so far */ +} -- cgit v1.2.3-59-g8ed1b From 07dc1f9f2f80f67823dc9ab4ebe3b1b3b071b911 Mon Sep 17 00:00:00 2001 From: Hansjoerg Lipp Date: Sun, 26 Mar 2006 01:38:37 -0800 Subject: [PATCH] isdn4linux: Siemens Gigaset drivers - M105 USB DECT adapter And: Tilman Schmidt This patch adds the connection-specific module "usb_gigaset", the hardware driver for Gigaset base stations connected via the M105 USB DECT adapter. It contains the code for handling probe/disconnect, AT command/response transmission, and call setup and termination, as well as handling asynchronous data transfers, PPP framing, byte stuffing, and flow control. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Cc: Karsten Keil Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/gigaset/asyncdata.c | 597 +++++++++++++++++++++ drivers/isdn/gigaset/usb-gigaset.c | 1008 ++++++++++++++++++++++++++++++++++++ 2 files changed, 1605 insertions(+) create mode 100644 drivers/isdn/gigaset/asyncdata.c create mode 100644 drivers/isdn/gigaset/usb-gigaset.c (limited to 'drivers') diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c new file mode 100644 index 000000000000..171f8b703d61 --- /dev/null +++ b/drivers/isdn/gigaset/asyncdata.c @@ -0,0 +1,597 @@ +/* + * Common data handling layer for ser_gigaset and usb_gigaset + * + * Copyright (c) 2005 by Tilman Schmidt , + * Hansjoerg Lipp , + * Stefan Eilers . + * + * ===================================================================== + * 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. + * ===================================================================== + * ToDo: ... + * ===================================================================== + * Version: $Id: asyncdata.c,v 1.2.2.7 2005/11/13 23:05:18 hjlipp Exp $ + * ===================================================================== + */ + +#include "gigaset.h" +#include + +//#define GIG_M10x_STUFF_VOICE_DATA + +/* check if byte must be stuffed/escaped + * I'm not sure which data should be encoded. + * Therefore I will go the hard way and decode every value + * less than 0x20, the flag sequence and the control escape char. + */ +static inline int muststuff(unsigned char c) +{ + if (c < PPP_TRANS) return 1; + if (c == PPP_FLAG) return 1; + if (c == PPP_ESCAPE) return 1; + /* other possible candidates: */ + /* 0x91: XON with parity set */ + /* 0x93: XOFF with parity set */ + return 0; +} + +/* == data input =========================================================== */ + +/* process a block of received bytes in command mode (modem response) + * Return value: + * number of processed bytes + */ +static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, + struct inbuf_t *inbuf) +{ + struct cardstate *cs = inbuf->cs; + unsigned cbytes = cs->cbytes; + int inputstate = inbuf->inputstate; + int startbytes = numbytes; + + for (;;) { + cs->respdata[cbytes] = c; + if (c == 10 || c == 13) { + dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", + __func__, cbytes); + cs->cbytes = cbytes; + gigaset_handle_modem_response(cs); /* can change cs->dle */ + cbytes = 0; + + if (cs->dle && + !(inputstate & INS_DLE_command)) { + inputstate &= ~INS_command; + break; + } + } else { + /* advance in line buffer, checking for overflow */ + if (cbytes < MAX_RESP_SIZE - 1) + cbytes++; + else + warn("response too large"); + } + + if (!numbytes) + break; + c = *src++; + --numbytes; + if (c == DLE_FLAG && + (cs->dle || inputstate & INS_DLE_command)) { + inputstate |= INS_DLE_char; + break; + } + } + + cs->cbytes = cbytes; + inbuf->inputstate = inputstate; + + return startbytes - numbytes; +} + +/* process a block of received bytes in lock mode (tty i/f) + * Return value: + * number of processed bytes + */ +static inline int lock_loop(unsigned char *src, int numbytes, + struct inbuf_t *inbuf) +{ + struct cardstate *cs = inbuf->cs; + + gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src, 0); + gigaset_if_receive(cs, src, numbytes); + + return numbytes; +} + +/* process a block of received bytes in HDLC data mode + * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. + * When a frame is complete, check the FCS and pass valid frames to the LL. + * If DLE is encountered, return immediately to let the caller handle it. + * Return value: + * number of processed bytes + * numbytes (all bytes processed) on error --FIXME + */ +static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, + struct inbuf_t *inbuf) +{ + struct cardstate *cs = inbuf->cs; + struct bc_state *bcs = inbuf->bcs; + int inputstate; + __u16 fcs; + struct sk_buff *skb; + unsigned char error; + struct sk_buff *compskb; + int startbytes = numbytes; + int l; + + IFNULLRETVAL(bcs, numbytes); + inputstate = bcs->inputstate; + fcs = bcs->fcs; + skb = bcs->skb; + IFNULLRETVAL(skb, numbytes); + + if (unlikely(inputstate & INS_byte_stuff)) { + inputstate &= ~INS_byte_stuff; + goto byte_stuff; + } + for (;;) { + if (unlikely(c == PPP_ESCAPE)) { + if (unlikely(!numbytes)) { + inputstate |= INS_byte_stuff; + break; + } + c = *src++; + --numbytes; + if (unlikely(c == DLE_FLAG && + (cs->dle || + inbuf->inputstate & INS_DLE_command))) { + inbuf->inputstate |= INS_DLE_char; + inputstate |= INS_byte_stuff; + break; + } +byte_stuff: + c ^= PPP_TRANS; +#ifdef CONFIG_GIGASET_DEBUG + if (unlikely(!muststuff(c))) + dbg(DEBUG_HDLC, + "byte stuffed: 0x%02x", c); +#endif + } else if (unlikely(c == PPP_FLAG)) { + if (unlikely(inputstate & INS_skip_frame)) { + if (!(inputstate & INS_have_data)) { /* 7E 7E */ + //dbg(DEBUG_HDLC, "(7e)7e------------------------"); +#ifdef CONFIG_GIGASET_DEBUG + ++bcs->emptycount; +#endif + } else + dbg(DEBUG_HDLC, + "7e----------------------------"); + + /* end of frame */ + error = 1; + gigaset_rcv_error(NULL, cs, bcs); + } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ + //dbg(DEBUG_HDLC, "(7e)7e------------------------"); +#ifdef CONFIG_GIGASET_DEBUG + ++bcs->emptycount; +#endif + break; + } else { + dbg(DEBUG_HDLC, + "7e----------------------------"); + + /* end of frame */ + error = 0; + + if (unlikely(fcs != PPP_GOODFCS)) { + err("Packet checksum at %lu failed, " + "packet is corrupted (%u bytes)!", + bcs->rcvbytes, skb->len); + compskb = NULL; + gigaset_rcv_error(compskb, cs, bcs); + error = 1; + } else { + if (likely((l = skb->len) > 2)) { + skb->tail -= 2; + skb->len -= 2; + } else { + dev_kfree_skb(skb); + skb = NULL; + inputstate |= INS_skip_frame; + if (l == 1) { + err("invalid packet size (1)!"); + error = 1; + gigaset_rcv_error(NULL, cs, bcs); + } + } + if (likely(!(error || + (inputstate & + INS_skip_frame)))) { + gigaset_rcv_skb(skb, cs, bcs); + } + } + } + + if (unlikely(error)) + if (skb) + dev_kfree_skb(skb); + + fcs = PPP_INITFCS; + inputstate &= ~(INS_have_data | INS_skip_frame); + if (unlikely(bcs->ignore)) { + inputstate |= INS_skip_frame; + skb = NULL; + } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) { + skb_reserve(skb, HW_HDR_LEN); + } else { + warn("could not allocate new skb"); + inputstate |= INS_skip_frame; + } + + break; +#ifdef CONFIG_GIGASET_DEBUG + } else if (unlikely(muststuff(c))) { + /* Should not happen. Possible after ZDLE=1. */ + dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); +#endif + } + + /* add character */ + +#ifdef CONFIG_GIGASET_DEBUG + if (unlikely(!(inputstate & INS_have_data))) { + dbg(DEBUG_HDLC, + "7e (%d x) ================", bcs->emptycount); + bcs->emptycount = 0; + } +#endif + + inputstate |= INS_have_data; + + if (likely(!(inputstate & INS_skip_frame))) { + if (unlikely(skb->len == SBUFSIZE)) { + warn("received packet too long"); + dev_kfree_skb_any(skb); + skb = NULL; + inputstate |= INS_skip_frame; + break; + } + *gigaset_skb_put_quick(skb, 1) = c; + /* *__skb_put (skb, 1) = c; */ + fcs = crc_ccitt_byte(fcs, c); + } + + if (unlikely(!numbytes)) + break; + c = *src++; + --numbytes; + if (unlikely(c == DLE_FLAG && + (cs->dle || + inbuf->inputstate & INS_DLE_command))) { + inbuf->inputstate |= INS_DLE_char; + break; + } + } + bcs->inputstate = inputstate; + bcs->fcs = fcs; + bcs->skb = skb; + return startbytes - numbytes; +} + +/* process a block of received bytes in transparent data mode + * Invert bytes, undoing byte stuffing and watching for DLE escapes. + * If DLE is encountered, return immediately to let the caller handle it. + * Return value: + * number of processed bytes + * numbytes (all bytes processed) on error --FIXME + */ +static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, + struct inbuf_t *inbuf) +{ + struct cardstate *cs = inbuf->cs; + struct bc_state *bcs = inbuf->bcs; + int inputstate; + struct sk_buff *skb; + int startbytes = numbytes; + + IFNULLRETVAL(bcs, numbytes); + inputstate = bcs->inputstate; + skb = bcs->skb; + IFNULLRETVAL(skb, numbytes); + + for (;;) { + /* add character */ + inputstate |= INS_have_data; + + if (likely(!(inputstate & INS_skip_frame))) { + if (unlikely(skb->len == SBUFSIZE)) { + //FIXME just pass skb up and allocate a new one + warn("received packet too long"); + dev_kfree_skb_any(skb); + skb = NULL; + inputstate |= INS_skip_frame; + break; + } + *gigaset_skb_put_quick(skb, 1) = gigaset_invtab[c]; + } + + if (unlikely(!numbytes)) + break; + c = *src++; + --numbytes; + if (unlikely(c == DLE_FLAG && + (cs->dle || + inbuf->inputstate & INS_DLE_command))) { + inbuf->inputstate |= INS_DLE_char; + break; + } + } + + /* pass data up */ + if (likely(inputstate & INS_have_data)) { + if (likely(!(inputstate & INS_skip_frame))) { + gigaset_rcv_skb(skb, cs, bcs); + } + inputstate &= ~(INS_have_data | INS_skip_frame); + if (unlikely(bcs->ignore)) { + inputstate |= INS_skip_frame; + skb = NULL; + } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) + != NULL)) { + skb_reserve(skb, HW_HDR_LEN); + } else { + warn("could not allocate new skb"); + inputstate |= INS_skip_frame; + } + } + + bcs->inputstate = inputstate; + bcs->skb = skb; + return startbytes - numbytes; +} + +/* process a block of data received from the device + */ +void gigaset_m10x_input(struct inbuf_t *inbuf) +{ + struct cardstate *cs; + unsigned tail, head, numbytes; + unsigned char *src, c; + int procbytes; + + head = atomic_read(&inbuf->head); + tail = atomic_read(&inbuf->tail); + dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); + + if (head != tail) { + cs = inbuf->cs; + src = inbuf->data + head; + numbytes = (head > tail ? RBUFSIZE : tail) - head; + dbg(DEBUG_INTR, "processing %u bytes", numbytes); + + while (numbytes) { + if (atomic_read(&cs->mstate) == MS_LOCKED) { + procbytes = lock_loop(src, numbytes, inbuf); + src += procbytes; + numbytes -= procbytes; + } else { + c = *src++; + --numbytes; + if (c == DLE_FLAG && (cs->dle || + inbuf->inputstate & INS_DLE_command)) { + if (!(inbuf->inputstate & INS_DLE_char)) { + inbuf->inputstate |= INS_DLE_char; + goto nextbyte; + } + /* => in data stream */ + inbuf->inputstate &= ~INS_DLE_char; + } + + if (!(inbuf->inputstate & INS_DLE_char)) { + + /* FIXME Einfach je nach Modus Funktionszeiger in cs setzen [hier+hdlc_loop]? */ + /* FIXME Spart folgendes "if" und ermoeglicht andere Protokolle */ + if (inbuf->inputstate & INS_command) + procbytes = cmd_loop(c, src, numbytes, inbuf); + else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC) + procbytes = hdlc_loop(c, src, numbytes, inbuf); + else + procbytes = iraw_loop(c, src, numbytes, inbuf); + + src += procbytes; + numbytes -= procbytes; + } else { /* DLE-char */ + inbuf->inputstate &= ~INS_DLE_char; + switch (c) { + case 'X': /*begin of command*/ +#ifdef CONFIG_GIGASET_DEBUG + if (inbuf->inputstate & INS_command) + err("received 'X' in command mode"); +#endif + inbuf->inputstate |= + INS_command | INS_DLE_command; + break; + case '.': /*end of command*/ +#ifdef CONFIG_GIGASET_DEBUG + if (!(inbuf->inputstate & INS_command)) + err("received '.' in hdlc mode"); +#endif + inbuf->inputstate &= cs->dle ? + ~(INS_DLE_command|INS_command) + : ~INS_DLE_command; + break; + //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */ + default: + err("received 0x10 0x%02x!", (int) c); + /* FIXME: reset driver?? */ + } + } + } +nextbyte: + if (!numbytes) { + /* end of buffer, check for wrap */ + if (head > tail) { + head = 0; + src = inbuf->data; + numbytes = tail; + } else { + head = tail; + break; + } + } + } + + dbg(DEBUG_INTR, "setting head to %u", head); + atomic_set(&inbuf->head, head); + } +} + + +/* == data output ========================================================== */ + +/* Encoding of a PPP packet into an octet stuffed HDLC frame + * with FCS, opening and closing flags. + * parameters: + * skb skb containing original packet (freed upon return) + * head number of headroom bytes to allocate in result skb + * tail number of tailroom bytes to allocate in result skb + * Return value: + * pointer to newly allocated skb containing the result frame + */ +static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) +{ + struct sk_buff *hdlc_skb; + __u16 fcs; + unsigned char c; + unsigned char *cp; + int len; + unsigned int stuf_cnt; + + stuf_cnt = 0; + fcs = PPP_INITFCS; + cp = skb->data; + len = skb->len; + while (len--) { + if (muststuff(*cp)) + stuf_cnt++; + fcs = crc_ccitt_byte(fcs, *cp++); + } + fcs ^= 0xffff; /* complement */ + + /* size of new buffer: original size + number of stuffing bytes + * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes + */ + hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head); + if (!hdlc_skb) { + err("unable to allocate memory for HDLC encoding!"); + dev_kfree_skb(skb); + return NULL; + } + skb_reserve(hdlc_skb, head); + + /* Copy acknowledge request into new skb */ + memcpy(hdlc_skb->head, skb->head, 2); + + /* Add flag sequence in front of everything.. */ + *(skb_put(hdlc_skb, 1)) = PPP_FLAG; + + /* Perform byte stuffing while copying data. */ + while (skb->len--) { + if (muststuff(*skb->data)) { + *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE; + *(skb_put(hdlc_skb, 1)) = (*skb->data++) ^ PPP_TRANS; + } else + *(skb_put(hdlc_skb, 1)) = *skb->data++; + } + + /* Finally add FCS (byte stuffed) and flag sequence */ + c = (fcs & 0x00ff); /* least significant byte first */ + if (muststuff(c)) { + *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE; + c ^= PPP_TRANS; + } + *(skb_put(hdlc_skb, 1)) = c; + + c = ((fcs >> 8) & 0x00ff); + if (muststuff(c)) { + *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE; + c ^= PPP_TRANS; + } + *(skb_put(hdlc_skb, 1)) = c; + + *(skb_put(hdlc_skb, 1)) = PPP_FLAG; + + dev_kfree_skb(skb); + return hdlc_skb; +} + +/* Encoding of a raw packet into an octet stuffed bit inverted frame + * parameters: + * skb skb containing original packet (freed upon return) + * head number of headroom bytes to allocate in result skb + * tail number of tailroom bytes to allocate in result skb + * Return value: + * pointer to newly allocated skb containing the result frame + */ +static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) +{ + struct sk_buff *iraw_skb; + unsigned char c; + unsigned char *cp; + int len; + + /* worst case: every byte must be stuffed */ + iraw_skb = dev_alloc_skb(2*skb->len + tail + head); + if (!iraw_skb) { + err("unable to allocate memory for HDLC encoding!"); + dev_kfree_skb(skb); + return NULL; + } + skb_reserve(iraw_skb, head); + + cp = skb->data; + len = skb->len; + while (len--) { + c = gigaset_invtab[*cp++]; + if (c == DLE_FLAG) + *(skb_put(iraw_skb, 1)) = c; + *(skb_put(iraw_skb, 1)) = c; + } + dev_kfree_skb(skb); + return iraw_skb; +} + +/* gigaset_send_skb + * called by common.c to queue an skb for sending + * and start transmission if necessary + * parameters: + * B Channel control structure + * skb + * Return value: + * number of bytes accepted for sending + * (skb->len if ok, 0 if out of buffer space) + * or error code (< 0, eg. -EINVAL) + */ +int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) +{ + unsigned len; + + IFNULLRETVAL(bcs, -EFAULT); + IFNULLRETVAL(skb, -EFAULT); + len = skb->len; + + if (bcs->proto2 == ISDN_PROTO_L2_HDLC) + skb = HDLC_Encode(skb, HW_HDR_LEN, 0); + else + skb = iraw_encode(skb, HW_HDR_LEN, 0); + if (!skb) + return -ENOMEM; + + skb_queue_tail(&bcs->squeue, skb); + tasklet_schedule(&bcs->cs->write_tasklet); + + return len; /* ok so far */ +} diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c new file mode 100644 index 000000000000..323fc7349dec --- /dev/null +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -0,0 +1,1008 @@ +/* + * USB driver for Gigaset 307x directly or using M105 Data. + * + * Copyright (c) 2001 by Stefan Eilers + * and Hansjoerg Lipp . + * + * This driver was derived from the USB skeleton driver by + * Greg Kroah-Hartman + * + * ===================================================================== + * 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. + * ===================================================================== + * ToDo: ... + * ===================================================================== + * Version: $Id: usb-gigaset.c,v 1.85.4.18 2006/02/04 18:28:16 hjlipp Exp $ + * ===================================================================== + */ + +#include "gigaset.h" + +#include +#include +#include +#include +#include +#include + +/* Version Information */ +#define DRIVER_AUTHOR "Hansjoerg Lipp , Stefan Eilers " +#define DRIVER_DESC "USB Driver for Gigaset 307x using M105" + +/* Module parameters */ + +static int startmode = SM_ISDN; +static int cidmode = 1; + +module_param(startmode, int, S_IRUGO); +module_param(cidmode, int, S_IRUGO); +MODULE_PARM_DESC(startmode, "start in isdn4linux mode"); +MODULE_PARM_DESC(cidmode, "Call-ID mode"); + +#define GIGASET_MINORS 1 +#define GIGASET_MINOR 8 +#define GIGASET_MODULENAME "usb_gigaset" +#define GIGASET_DEVFSNAME "gig/usb/" +#define GIGASET_DEVNAME "ttyGU" + +#define IF_WRITEBUF 2000 //FIXME // WAKEUP_CHARS: 256 + +/* Values for the Gigaset M105 Data */ +#define USB_M105_VENDOR_ID 0x0681 +#define USB_M105_PRODUCT_ID 0x0009 + +/* table of devices that work with this driver */ +static struct usb_device_id gigaset_table [] = { + { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, gigaset_table); + +/* Get a minor range for your devices from the usb maintainer */ +#define USB_SKEL_MINOR_BASE 200 + + +/* + * Control requests (empty fields: 00) + * + * RT|RQ|VALUE|INDEX|LEN |DATA + * In: + * C1 08 01 + * Get flags (1 byte). Bits: 0=dtr,1=rts,3-7:? + * C1 0F ll ll + * Get device information/status (llll: 0x200 and 0x40 seen). + * Real size: I only saw MIN(llll,0x64). + * Contents: seems to be always the same... + * offset 0x00: Length of this structure (0x64) (len: 1,2,3 bytes) + * offset 0x3c: String (16 bit chars): "MCCI USB Serial V2.0" + * rest: ? + * Out: + * 41 11 + * Initialize/reset device ? + * 41 00 xx 00 + * ? (xx=00 or 01; 01 on start, 00 on close) + * 41 07 vv mm + * Set/clear flags vv=value, mm=mask (see RQ 08) + * 41 12 xx + * Used before the following configuration requests are issued + * (with xx=0x0f). I've seen other values<0xf, though. + * 41 01 xx xx + * Set baud rate. xxxx=ceil(0x384000/rate)=trunc(0x383fff/rate)+1. + * 41 03 ps bb + * Set byte size and parity. p: 0x20=even,0x10=odd,0x00=no parity + * [ 0x30: m, 0x40: s ] + * [s: 0: 1 stop bit; 1: 1.5; 2: 2] + * bb: bits/byte (seen 7 and 8) + * 41 13 -- -- -- -- 10 00 ww 00 00 00 xx 00 00 00 yy 00 00 00 zz 00 00 00 + * ?? + * Initialization: 01, 40, 00, 00 + * Open device: 00 40, 00, 00 + * yy and zz seem to be equal, either 0x00 or 0x0a + * (ww,xx) pairs seen: (00,00), (00,40), (01,40), (09,80), (19,80) + * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13 + * Used after every "configuration sequence" (RQ 12, RQs 01/03/13). + * xx is usually 0x00 but was 0x7e before starting data transfer + * in unimodem mode. So, this might be an array of characters that need + * special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. + * + * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two + * flags per packet. + */ + +static int gigaset_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void gigaset_disconnect(struct usb_interface *interface); + +static struct gigaset_driver *driver = NULL; +static struct cardstate *cardstate = NULL; + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver gigaset_usb_driver = { + .name = GIGASET_MODULENAME, + .probe = gigaset_probe, + .disconnect = gigaset_disconnect, + .id_table = gigaset_table, +}; + +struct usb_cardstate { + struct usb_device *udev; /* save off the usb device pointer */ + struct usb_interface *interface; /* the interface for this device */ + atomic_t busy; /* bulk output in progress */ + + /* Output buffer for commands (M105: and data)*/ + unsigned char *bulk_out_buffer; /* the buffer to send data */ + int bulk_out_size; /* the size of the send buffer */ + __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ + struct urb *bulk_out_urb; /* the urb used to transmit data */ + + /* Input buffer for command responses (M105: and data)*/ + int rcvbuf_size; /* the size of the receive buffer */ + struct urb *read_urb; /* the urb used to receive data */ + __u8 int_in_endpointAddr; /* the address of the bulk in endpoint */ + + char bchars[6]; /* req. 0x19 */ +}; + +struct usb_bc_state {}; + +static inline unsigned tiocm_to_gigaset(unsigned state) +{ + return ((state & TIOCM_DTR) ? 1 : 0) | ((state & TIOCM_RTS) ? 2 : 0); +} + +#ifdef CONFIG_GIGASET_UNDOCREQ +/* WARNING: EXPERIMENTAL! */ +static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, + unsigned new_state) +{ + unsigned mask, val; + int r; + + mask = tiocm_to_gigaset(old_state ^ new_state); + val = tiocm_to_gigaset(new_state); + + dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); + r = usb_control_msg(cs->hw.usb->udev, + usb_sndctrlpipe(cs->hw.usb->udev, 0), 7, 0x41, + (val & 0xff) | ((mask & 0xff) << 8), 0, + NULL, 0, 2000 /*timeout??*/); // don't use this in an interrupt/BH + if (r < 0) + return r; + //.. + return 0; +} + +static int set_value(struct cardstate *cs, u8 req, u16 val) +{ + int r, r2; + + dbg(DEBUG_USBREQ, "request %02x (%04x)", (unsigned)req, (unsigned)val); + r = usb_control_msg(cs->hw.usb->udev, + usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x12, 0x41, + 0xf /*?*/, 0, + NULL, 0, 2000 /*?*/); /* no idea, what this does */ + if (r < 0) { + err("error %d on request 0x12", -r); + return r; + } + + r = usb_control_msg(cs->hw.usb->udev, + usb_sndctrlpipe(cs->hw.usb->udev, 0), req, 0x41, + val, 0, + NULL, 0, 2000 /*?*/); + if (r < 0) + err("error %d on request 0x%02x", -r, (unsigned)req); + + r2 = usb_control_msg(cs->hw.usb->udev, + usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41, + 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/); + if (r2 < 0) + err("error %d on request 0x19", -r2); + + return r < 0 ? r : (r2 < 0 ? r2 : 0); +} + +/* WARNING: HIGHLY EXPERIMENTAL! */ +// don't use this in an interrupt/BH +static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) +{ + u16 val; + u32 rate; + + cflag &= CBAUD; + + switch (cflag) { + //FIXME more values? + case B300: rate = 300; break; + case B600: rate = 600; break; + case B1200: rate = 1200; break; + case B2400: rate = 2400; break; + case B4800: rate = 4800; break; + case B9600: rate = 9600; break; + case B19200: rate = 19200; break; + case B38400: rate = 38400; break; + case B57600: rate = 57600; break; + case B115200: rate = 115200; break; + default: + rate = 9600; + err("unsupported baudrate request 0x%x," + " using default of B9600", cflag); + } + + val = 0x383fff / rate + 1; + + return set_value(cs, 1, val); +} + +/* WARNING: HIGHLY EXPERIMENTAL! */ +// don't use this in an interrupt/BH +static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) +{ + u16 val = 0; + + /* set the parity */ + if (cflag & PARENB) + val |= (cflag & PARODD) ? 0x10 : 0x20; + + /* set the number of data bits */ + switch (cflag & CSIZE) { + case CS5: + val |= 5 << 8; break; + case CS6: + val |= 6 << 8; break; + case CS7: + val |= 7 << 8; break; + case CS8: + val |= 8 << 8; break; + default: + err("CSIZE was not CS5-CS8, using default of 8"); + val |= 8 << 8; + break; + } + + /* set the number of stop bits */ + if (cflag & CSTOPB) { + if ((cflag & CSIZE) == CS5) + val |= 1; /* 1.5 stop bits */ //FIXME is this okay? + else + val |= 2; /* 2 stop bits */ + } + + return set_value(cs, 3, val); +} + +#else +static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, + unsigned new_state) +{ + return -EINVAL; +} + +static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) +{ + return -EINVAL; +} + +static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) +{ + return -EINVAL; +} +#endif + + + /*================================================================================================================*/ +static int gigaset_init_bchannel(struct bc_state *bcs) +{ + /* nothing to do for M10x */ + gigaset_bchannel_up(bcs); + return 0; +} + +static int gigaset_close_bchannel(struct bc_state *bcs) +{ + /* nothing to do for M10x */ + gigaset_bchannel_down(bcs); + return 0; +} + +//void send_ack_to_LL(void *data); +static int write_modem(struct cardstate *cs); +static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb); + + +/* Handling of send queue. If there is already a skb opened, put data to + * the transfer buffer by calling "write_modem". Otherwise take a new skb out of the queue. + * This function will be called by the ISR via "transmit_chars" (USB: B-Channel Bulk callback handler + * via immediate task queue) or by writebuf_from_LL if the LL wants to transmit data. + */ +static void gigaset_modem_fill(unsigned long data) +{ + struct cardstate *cs = (struct cardstate *) data; + struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ + struct cmdbuf_t *cb; + unsigned long flags; + int again; + + dbg(DEBUG_OUTPUT, "modem_fill"); + + if (atomic_read(&cs->hw.usb->busy)) { + dbg(DEBUG_OUTPUT, "modem_fill: busy"); + return; + } + + do { + again = 0; + if (!bcs->tx_skb) { /* no skb is being sent */ + spin_lock_irqsave(&cs->cmdlock, flags); + cb = cs->cmdbuf; + spin_unlock_irqrestore(&cs->cmdlock, flags); + if (cb) { /* commands to send? */ + dbg(DEBUG_OUTPUT, "modem_fill: cb"); + if (send_cb(cs, cb) < 0) { + dbg(DEBUG_OUTPUT, + "modem_fill: send_cb failed"); + again = 1; /* no callback will be called! */ + } + } else { /* skbs to send? */ + bcs->tx_skb = skb_dequeue(&bcs->squeue); + if (bcs->tx_skb) + dbg(DEBUG_INTR, + "Dequeued skb (Adr: %lx)!", + (unsigned long) bcs->tx_skb); + } + } + + if (bcs->tx_skb) { + dbg(DEBUG_OUTPUT, "modem_fill: tx_skb"); + if (write_modem(cs) < 0) { + dbg(DEBUG_OUTPUT, + "modem_fill: write_modem failed"); + // FIXME should we tell the LL? + again = 1; /* no callback will be called! */ + } + } + } while (again); +} + +/** + * gigaset_read_int_callback + * + * It is called if the data was received from the device. This is almost similiar to + * the interrupt service routine in the serial device. + */ +static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs) +{ + int resubmit = 0; + int r; + struct cardstate *cs; + unsigned numbytes; + unsigned char *src; + //unsigned long flags; + struct inbuf_t *inbuf; + + IFNULLRET(urb); + inbuf = (struct inbuf_t *) urb->context; + IFNULLRET(inbuf); + //spin_lock_irqsave(&inbuf->lock, flags); + cs = inbuf->cs; + IFNULLGOTO(cs, exit); + IFNULLGOTO(cardstate, exit); + + if (!atomic_read(&cs->connected)) { + err("%s: disconnected", __func__); + goto exit; + } + + if (!urb->status) { + numbytes = urb->actual_length; + + if (numbytes) { + src = inbuf->rcvbuf; + if (unlikely(*src)) + warn("%s: There was no leading 0, but 0x%02x!", + __func__, (unsigned) *src); + ++src; /* skip leading 0x00 */ + --numbytes; + if (gigaset_fill_inbuf(inbuf, src, numbytes)) { + dbg(DEBUG_INTR, "%s-->BH", __func__); + gigaset_schedule_event(inbuf->cs); + } + } else + dbg(DEBUG_INTR, "Received zero block length"); + resubmit = 1; + } else { + /* The urb might have been killed. */ + dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", + __func__, urb->status); + if (urb->status != -ENOENT) /* not killed */ + resubmit = 1; + } +exit: + //spin_unlock_irqrestore(&inbuf->lock, flags); + if (resubmit) { + r = usb_submit_urb(urb, SLAB_ATOMIC); + if (r) + err("error %d when resubmitting urb.", -r); + } +} + + +/* This callback routine is called when data was transmitted to a B-Channel. + * Therefore it has to check if there is still data to transmit. This + * happens by calling modem_fill via task queue. + * + */ +static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs) +{ + struct cardstate *cs = (struct cardstate *) urb->context; + + IFNULLRET(cs); +#ifdef CONFIG_GIGASET_DEBUG + if (!atomic_read(&cs->connected)) { + err("%s:not connected", __func__); + return; + } +#endif + if (urb->status) + err("bulk transfer failed (status %d)", -urb->status); /* That's all we can do. Communication problems + are handeled by timeouts or network protocols */ + + atomic_set(&cs->hw.usb->busy, 0); + tasklet_schedule(&cs->write_tasklet); +} + +static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) +{ + struct cmdbuf_t *tcb; + unsigned long flags; + int count; + int status = -ENOENT; // FIXME + struct usb_cardstate *ucs = cs->hw.usb; + + do { + if (!cb->len) { + tcb = cb; + + spin_lock_irqsave(&cs->cmdlock, flags); + cs->cmdbytes -= cs->curlen; + dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left", + cs->curlen, cs->cmdbytes); + cs->cmdbuf = cb = cb->next; + if (cb) { + cb->prev = NULL; + cs->curlen = cb->len; + } else { + cs->lastcmdbuf = NULL; + cs->curlen = 0; + } + spin_unlock_irqrestore(&cs->cmdlock, flags); + + if (tcb->wake_tasklet) + tasklet_schedule(tcb->wake_tasklet); + kfree(tcb); + } + if (cb) { + count = min(cb->len, ucs->bulk_out_size); + usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, + usb_sndbulkpipe(ucs->udev, + ucs->bulk_out_endpointAddr & 0x0f), + cb->buf + cb->offset, count, + gigaset_write_bulk_callback, cs); + + cb->offset += count; + cb->len -= count; + atomic_set(&ucs->busy, 1); + dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count); + + status = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); + if (status) { + atomic_set(&ucs->busy, 0); + err("could not submit urb (error %d).", + -status); + cb->len = 0; /* skip urb => remove cb+wakeup in next loop cycle */ + } + } + } while (cb && status); /* bei Fehler naechster Befehl //FIXME: ist das OK? */ + + return status; +} + +/* Write string into transbuf and send it to modem. + */ +static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, + int len, struct tasklet_struct *wake_tasklet) +{ + struct cmdbuf_t *cb; + unsigned long flags; + + gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? + DEBUG_TRANSCMD : DEBUG_LOCKCMD, + "CMD Transmit", len, buf, 0); + + if (!atomic_read(&cs->connected)) { + err("%s: not connected", __func__); + return -ENODEV; + } + + if (len <= 0) + return 0; + + if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { + err("%s: out of memory", __func__); + return -ENOMEM; + } + + memcpy(cb->buf, buf, len); + cb->len = len; + cb->offset = 0; + cb->next = NULL; + cb->wake_tasklet = wake_tasklet; + + spin_lock_irqsave(&cs->cmdlock, flags); + cb->prev = cs->lastcmdbuf; + if (cs->lastcmdbuf) + cs->lastcmdbuf->next = cb; + else { + cs->cmdbuf = cb; + cs->curlen = len; + } + cs->cmdbytes += len; + cs->lastcmdbuf = cb; + spin_unlock_irqrestore(&cs->cmdlock, flags); + + tasklet_schedule(&cs->write_tasklet); + return len; +} + +static int gigaset_write_room(struct cardstate *cs) +{ + unsigned long flags; + unsigned bytes; + + spin_lock_irqsave(&cs->cmdlock, flags); + bytes = cs->cmdbytes; + spin_unlock_irqrestore(&cs->cmdlock, flags); + + return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0; +} + +static int gigaset_chars_in_buffer(struct cardstate *cs) +{ + return cs->cmdbytes; +} + +static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) +{ +#ifdef CONFIG_GIGASET_UNDOCREQ + gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf, 0); + memcpy(cs->hw.usb->bchars, buf, 6); + return usb_control_msg(cs->hw.usb->udev, + usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41, + 0, 0, &buf, 6, 2000); +#else + return -EINVAL; +#endif +} + +static int gigaset_freebcshw(struct bc_state *bcs) +{ + if (!bcs->hw.usb) + return 0; + //FIXME + kfree(bcs->hw.usb); + return 1; +} + +/* Initialize the b-channel structure */ +static int gigaset_initbcshw(struct bc_state *bcs) +{ + bcs->hw.usb = kmalloc(sizeof(struct usb_bc_state), GFP_KERNEL); + if (!bcs->hw.usb) + return 0; + + //bcs->hw.usb->trans_flg = READY_TO_TRNSMIT; /* B-Channel ready to transmit */ + return 1; +} + +static void gigaset_reinitbcshw(struct bc_state *bcs) +{ +} + +static void gigaset_freecshw(struct cardstate *cs) +{ + //FIXME + tasklet_kill(&cs->write_tasklet); + kfree(cs->hw.usb); +} + +static int gigaset_initcshw(struct cardstate *cs) +{ + struct usb_cardstate *ucs; + + cs->hw.usb = ucs = + kmalloc(sizeof(struct usb_cardstate), GFP_KERNEL); + if (!ucs) + return 0; + + ucs->bchars[0] = 0; + ucs->bchars[1] = 0; + ucs->bchars[2] = 0; + ucs->bchars[3] = 0; + ucs->bchars[4] = 0x11; + ucs->bchars[5] = 0x13; + ucs->bulk_out_buffer = NULL; + ucs->bulk_out_urb = NULL; + //ucs->urb_cmd_out = NULL; + ucs->read_urb = NULL; + tasklet_init(&cs->write_tasklet, + &gigaset_modem_fill, (unsigned long) cs); + + return 1; +} + +/* Writes the data of the current open skb into the modem. + * We have to protect against multiple calls until the + * callback handler () is called , due to the fact that we + * are just allowed to send data once to an endpoint. Therefore + * we using "trans_flg" to synchonize ... + */ +static int write_modem(struct cardstate *cs) +{ + int ret; + int count; + struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ + struct usb_cardstate *ucs = cs->hw.usb; + //unsigned long flags; + + IFNULLRETVAL(bcs->tx_skb, -EINVAL); + + dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); + + ret = -ENODEV; + IFNULLGOTO(ucs->bulk_out_buffer, error); + IFNULLGOTO(ucs->bulk_out_urb, error); + ret = 0; + + if (!bcs->tx_skb->len) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + return -EINVAL; + } + + /* Copy data to bulk out buffer and // FIXME copying not necessary + * transmit data + */ + count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); + memcpy(ucs->bulk_out_buffer, bcs->tx_skb->data, count); + skb_pull(bcs->tx_skb, count); + + usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, + usb_sndbulkpipe(ucs->udev, + ucs->bulk_out_endpointAddr & 0x0f), + ucs->bulk_out_buffer, count, + gigaset_write_bulk_callback, cs); + atomic_set(&ucs->busy, 1); + dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); + + ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); + if (ret) { + err("could not submit urb (error %d).", -ret); + atomic_set(&ucs->busy, 0); + } + if (!bcs->tx_skb->len) { + /* skb sent completely */ + gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0? + + dbg(DEBUG_INTR, + "kfree skb (Adr: %lx)!", (unsigned long) bcs->tx_skb); + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + } + + return ret; +error: + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + return ret; + +} + +static int gigaset_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + int retval; + struct usb_device *udev = interface_to_usbdev(interface); + unsigned int ifnum; + struct usb_host_interface *hostif; + struct cardstate *cs = NULL; + struct usb_cardstate *ucs = NULL; + //struct usb_interface_descriptor *iface_desc; + struct usb_endpoint_descriptor *endpoint; + //isdn_ctrl command; + int buffer_size; + int alt; + //unsigned long flags; + + info("%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", + __func__, le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); + + retval = -ENODEV; //FIXME + + /* See if the device offered us matches what we can accept */ + if ((le16_to_cpu(udev->descriptor.idVendor != USB_M105_VENDOR_ID)) || + (le16_to_cpu(udev->descriptor.idProduct != USB_M105_PRODUCT_ID))) + return -ENODEV; + + /* this starts to become ascii art... */ + hostif = interface->cur_altsetting; + alt = hostif->desc.bAlternateSetting; + ifnum = hostif->desc.bInterfaceNumber; // FIXME ? + + if (alt != 0 || ifnum != 0) { + warn("ifnum %d, alt %d", ifnum, alt); + return -ENODEV; + } + + /* Reject application specific intefaces + * + */ + if (hostif->desc.bInterfaceClass != 255) { + info("%s: Device matched, but iface_desc[%d]->bInterfaceClass==%d !", + __func__, ifnum, hostif->desc.bInterfaceClass); + return -ENODEV; + } + + info("%s: Device matched ... !", __func__); + + cs = gigaset_getunassignedcs(driver); + if (!cs) { + warn("No free cardstate!"); + return -ENODEV; + } + ucs = cs->hw.usb; + +#if 0 + if (usb_set_configuration(udev, udev->config[0].desc.bConfigurationValue) < 0) { + warn("set_configuration failed"); + goto error; + } + + + if (usb_set_interface(udev, ifnum/*==0*/, alt/*==0*/) < 0) { + warn("usb_set_interface failed, device %d interface %d altsetting %d", + udev->devnum, ifnum, alt); + goto error; + } +#endif + + /* set up the endpoint information */ + /* check out the endpoints */ + /* We will get 2 endpoints: One for sending commands to the device (bulk out) and one to + * poll messages from the device(int in). + * Therefore we will have an almost similiar situation as with our serial port handler. + * If an connection will be established, we will have to create data in/out pipes + * dynamically... + */ + + endpoint = &hostif->endpoint[0].desc; + + buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + ucs->bulk_out_size = buffer_size; + ucs->bulk_out_endpointAddr = endpoint->bEndpointAddress; + ucs->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!ucs->bulk_out_buffer) { + err("Couldn't allocate bulk_out_buffer"); + retval = -ENOMEM; + goto error; + } + + ucs->bulk_out_urb = usb_alloc_urb(0, SLAB_KERNEL); + if (!ucs->bulk_out_urb) { + err("Couldn't allocate bulk_out_buffer"); + retval = -ENOMEM; + goto error; + } + + endpoint = &hostif->endpoint[1].desc; + + atomic_set(&ucs->busy, 0); + ucs->udev = udev; + ucs->interface = interface; + + ucs->read_urb = usb_alloc_urb(0, SLAB_KERNEL); + if (!ucs->read_urb) { + err("No free urbs available"); + retval = -ENOMEM; + goto error; + } + buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + ucs->rcvbuf_size = buffer_size; + ucs->int_in_endpointAddr = endpoint->bEndpointAddress; + cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL); + if (!cs->inbuf[0].rcvbuf) { + err("Couldn't allocate rcvbuf"); + retval = -ENOMEM; + goto error; + } + /* Fill the interrupt urb and send it to the core */ + usb_fill_int_urb(ucs->read_urb, udev, + usb_rcvintpipe(udev, + endpoint->bEndpointAddress & 0x0f), + cs->inbuf[0].rcvbuf, buffer_size, + gigaset_read_int_callback, + cs->inbuf + 0, endpoint->bInterval); + + retval = usb_submit_urb(ucs->read_urb, SLAB_KERNEL); + if (retval) { + err("Could not submit URB!"); + goto error; + } + + /* tell common part that the device is ready */ + if (startmode == SM_LOCKED) + atomic_set(&cs->mstate, MS_LOCKED); + if (!gigaset_start(cs)) { + tasklet_kill(&cs->write_tasklet); + retval = -ENODEV; //FIXME + goto error; + } + + /* save address of controller structure */ + usb_set_intfdata(interface, cs); + + /* set up device sysfs */ + gigaset_init_dev_sysfs(interface); + return 0; + +error: + if (ucs->read_urb) + usb_kill_urb(ucs->read_urb); + kfree(ucs->bulk_out_buffer); + if (ucs->bulk_out_urb != NULL) + usb_free_urb(ucs->bulk_out_urb); + kfree(cs->inbuf[0].rcvbuf); + if (ucs->read_urb != NULL) + usb_free_urb(ucs->read_urb); + ucs->read_urb = ucs->bulk_out_urb = NULL; + cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + gigaset_unassign(cs); + return retval; +} + +/** + * skel_disconnect + */ +static void gigaset_disconnect(struct usb_interface *interface) +{ + struct cardstate *cs; + struct usb_cardstate *ucs; + + cs = usb_get_intfdata(interface); + + /* clear device sysfs */ + gigaset_free_dev_sysfs(interface); + + usb_set_intfdata(interface, NULL); + ucs = cs->hw.usb; + usb_kill_urb(ucs->read_urb); + //info("GigaSet USB device #%d will be disconnected", minor); + + gigaset_stop(cs); + + tasklet_kill(&cs->write_tasklet); + + usb_kill_urb(ucs->bulk_out_urb); /* FIXME: nur, wenn noetig */ + //usb_kill_urb(ucs->urb_cmd_out); /* FIXME: nur, wenn noetig */ + + kfree(ucs->bulk_out_buffer); + if (ucs->bulk_out_urb != NULL) + usb_free_urb(ucs->bulk_out_urb); + //if(ucs->urb_cmd_out != NULL) + // usb_free_urb(ucs->urb_cmd_out); + kfree(cs->inbuf[0].rcvbuf); + if (ucs->read_urb != NULL) + usb_free_urb(ucs->read_urb); + ucs->read_urb = ucs->bulk_out_urb/*=ucs->urb_cmd_out*/=NULL; + cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + + gigaset_unassign(cs); +} + +static struct gigaset_ops ops = { + gigaset_write_cmd, + gigaset_write_room, + gigaset_chars_in_buffer, + gigaset_brkchars, + gigaset_init_bchannel, + gigaset_close_bchannel, + gigaset_initbcshw, + gigaset_freebcshw, + gigaset_reinitbcshw, + gigaset_initcshw, + gigaset_freecshw, + gigaset_set_modem_ctrl, + gigaset_baud_rate, + gigaset_set_line_ctrl, + gigaset_m10x_send_skb, + gigaset_m10x_input, +}; + +/** + * usb_gigaset_init + * This function is called while kernel-module is loaded + */ +static int __init usb_gigaset_init(void) +{ + int result; + + /* allocate memory for our driver state and intialize it */ + if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, + GIGASET_MODULENAME, GIGASET_DEVNAME, + GIGASET_DEVFSNAME, &ops, + THIS_MODULE)) == NULL) + goto error; + + /* allocate memory for our device state and intialize it */ + cardstate = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); + if (!cardstate) + goto error; + + /* register this driver with the USB subsystem */ + result = usb_register(&gigaset_usb_driver); + if (result < 0) { + err("usb_gigaset: usb_register failed (error %d)", + -result); + goto error; + } + + info(DRIVER_AUTHOR); + info(DRIVER_DESC); + return 0; + +error: if (cardstate) + gigaset_freecs(cardstate); + cardstate = NULL; + if (driver) + gigaset_freedriver(driver); + driver = NULL; + return -1; +} + + +/** + * usb_gigaset_exit + * This function is called while unloading the kernel-module + */ +static void __exit usb_gigaset_exit(void) +{ + gigaset_blockdriver(driver); /* => probe will fail + * => no gigaset_start any more + */ + + gigaset_shutdown(cardstate); + /* from now on, no isdn callback should be possible */ + + /* deregister this driver with the USB subsystem */ + usb_deregister(&gigaset_usb_driver); + /* this will call the disconnect-callback */ + /* from now on, no disconnect/probe callback should be running */ + + gigaset_freecs(cardstate); + cardstate = NULL; + gigaset_freedriver(driver); + driver = NULL; +} + + +module_init(usb_gigaset_init); +module_exit(usb_gigaset_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); + +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From dac5bafa3521a10a42a470ab612cd2bbc12d4203 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Sun, 26 Mar 2006 01:38:38 -0800 Subject: [PATCH] Dead code in drivers/isdn/avm/avmcard.h This fixes coverity id #2. the if (i==0) is pretty useless, since we assing i=0, just the line before. Signed-off-by: Eric Sesterhenn Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/hardware/avm/avmcard.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hardware/avm/avmcard.h b/drivers/isdn/hardware/avm/avmcard.h index 296d6a6f749f..3b431723c7cb 100644 --- a/drivers/isdn/hardware/avm/avmcard.h +++ b/drivers/isdn/hardware/avm/avmcard.h @@ -437,9 +437,7 @@ static inline unsigned int t1_get_slice(unsigned int base, #endif dp += i; i = 0; - if (i == 0) - break; - /* fall through */ + break; default: *dp++ = b1_get_byte(base); i--; -- cgit v1.2.3-59-g8ed1b From f2fe42abbf0d99a8c4b96f1cc55db10ac35d2fb9 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:38 -0800 Subject: [PATCH] EDAC: switch to kthread_ API This patch was originally posted by Christoph Hellwig (see http://lkml.org/lkml/2006/2/14/331): "Christoph Hellwig" wrote: > Use the kthread_ API instead of opencoding lots of hairy code for kernel > thread creation and teardown, including tasklist_lock abuse. > Signed-off-by: Christoph Hellwig Signed-off-by: David S. Peterson Cc: Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/edac_mc.c | 88 ++++++-------------------------------------------- 1 file changed, 10 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 9c205274c1cb..8a7a3ab745aa 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -64,6 +65,8 @@ static atomic_t pci_parity_count = ATOMIC_INIT(0); static DECLARE_MUTEX(mem_ctls_mutex); static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices); +static struct task_struct *edac_thread; + /* Structure of the whitelist and blacklist arrays */ struct edac_pci_device_list { unsigned int vendor; /* Vendor ID */ @@ -2073,7 +2076,6 @@ static inline void check_mc_devices (void) */ static void do_edac_check(void) { - debugf3("MC: " __FILE__ ": %s()\n", __func__); check_mc_devices(); @@ -2081,62 +2083,16 @@ static void do_edac_check(void) do_pci_parity_check(); } - -/* - * EDAC thread state information - */ -struct bs_thread_info -{ - struct task_struct *task; - struct completion *event; - char *name; - void (*run)(void); -}; - -static struct bs_thread_info bs_thread; - -/* - * edac_kernel_thread - * This the kernel thread that processes edac operations - * in a normal thread environment - */ static int edac_kernel_thread(void *arg) { - struct bs_thread_info *thread = (struct bs_thread_info *) arg; - - /* detach thread */ - daemonize(thread->name); - - current->exit_signal = SIGCHLD; - allow_signal(SIGKILL); - thread->task = current; - - /* indicate to starting task we have started */ - complete(thread->event); - - /* loop forever, until we are told to stop */ - while(thread->run != NULL) { - void (*run)(void); - - /* call the function to check the memory controllers */ - run = thread->run; - if (run) - run(); - - if (signal_pending(current)) - flush_signals(current); - - /* ensure we are interruptable */ - set_current_state(TASK_INTERRUPTIBLE); + while (!kthread_should_stop()) { + do_edac_check(); /* goto sleep for the interval */ - schedule_timeout((HZ * poll_msec) / 1000); + schedule_timeout_interruptible((HZ * poll_msec) / 1000); try_to_freeze(); } - /* notify waiter that we are exiting */ - complete(thread->event); - return 0; } @@ -2146,9 +2102,6 @@ static int edac_kernel_thread(void *arg) */ static int __init edac_mc_init(void) { - int ret; - struct completion event; - printk(KERN_INFO "MC: " __FILE__ " version " EDAC_MC_VERSION "\n"); /* @@ -2176,24 +2129,15 @@ static int __init edac_mc_init(void) return -ENODEV; } - /* Create our kernel thread */ - init_completion(&event); - bs_thread.event = &event; - bs_thread.name = "kedac"; - bs_thread.run = do_edac_check; - /* create our kernel thread */ - ret = kernel_thread(edac_kernel_thread, &bs_thread, CLONE_KERNEL); - if (ret < 0) { + edac_thread = kthread_run(edac_kernel_thread, NULL, "kedac"); + if (IS_ERR(edac_thread)) { /* remove the sysfs entries */ edac_sysfs_memctrl_teardown(); edac_sysfs_pci_teardown(); - return -ENOMEM; + return PTR_ERR(edac_thread); } - /* wait for our kernel theard ack that it is up and running */ - wait_for_completion(&event); - return 0; } @@ -2204,21 +2148,9 @@ static int __init edac_mc_init(void) */ static void __exit edac_mc_exit(void) { - struct completion event; - debugf0("MC: " __FILE__ ": %s()\n", __func__); - init_completion(&event); - bs_thread.event = &event; - - /* As soon as ->run is set to NULL, the task could disappear, - * so we need to hold tasklist_lock until we have sent the signal - */ - read_lock(&tasklist_lock); - bs_thread.run = NULL; - send_sig(SIGKILL, bs_thread.task, 1); - read_unlock(&tasklist_lock); - wait_for_completion(&event); + kthread_stop(edac_thread); /* tear down the sysfs device */ edac_sysfs_memctrl_teardown(); -- cgit v1.2.3-59-g8ed1b From 537fba28928c01b7db1580627450691a4bb0b9b3 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:40 -0800 Subject: [PATCH] EDAC: printk cleanup This implements the following idea: On Monday 30 January 2006 19:22, Eric W. Biederman wrote: > One piece missing from this conversation is the issue that we need errors > in a uniform format. That is why edac_mc has helper functions. > > However there will always be errors that don't fit any particular model. > Could we add a edac_printk(dev, ); That is similar to dev_printk but > prints out an EDAC header and the device on which the error was found? > Letting the rest of the string be user specified. > > For actual control that interface may be to blunt, but at least for people > looking in the logs it allows all of the errors to be detected and > harvested. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/amd76x_edac.c | 23 ++++-- drivers/edac/e752x_edac.c | 90 +++++++++++---------- drivers/edac/e7xxx_edac.c | 62 ++++++++------- drivers/edac/edac_mc.c | 186 ++++++++++++++++++++------------------------ drivers/edac/edac_mc.h | 23 +++++- drivers/edac/i82860_edac.c | 32 ++++---- drivers/edac/i82875p_edac.c | 51 ++++++------ drivers/edac/r82600_edac.c | 48 ++++++------ 8 files changed, 275 insertions(+), 240 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 2fcc8120b53c..60535bb9275f 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -25,6 +25,14 @@ #include "edac_mc.h" +#define amd76x_printk(level, fmt, arg...) \ + edac_printk(level, "amd76x", fmt, ##arg) + + +#define amd76x_mc_printk(mci, level, fmt, arg...) \ + edac_mc_chipset_printk(mci, level, "amd76x", fmt, ##arg) + + #define AMD76X_NR_CSROWS 8 #define AMD76X_NR_CHANS 1 #define AMD76X_NR_DIMMS 4 @@ -174,7 +182,7 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci, static void amd76x_check(struct mem_ctl_info *mci) { struct amd76x_error_info info; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); amd76x_get_error_info(mci, &info); amd76x_process_error_info(mci, &info, 1); } @@ -204,7 +212,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) u32 ems; u32 ems_mode; - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems); ems_mode = (ems >> 10) & 0x3; @@ -216,7 +224,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) goto fail; } - debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); + debugf0("%s(): mci = %p\n", __func__, mci); mci->pdev = pci_dev_get(pdev); mci->mtype_cap = MEM_FLAG_RDDR; @@ -267,13 +275,12 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) (u32) (0x3 << 8)); if (edac_mc_add_mc(mci)) { - debugf3("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", __func__); + debugf3("%s(): failed edac_mc_add_mc()\n", __func__); goto fail; } /* get this far and it's successful */ - debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + debugf3("%s(): success\n", __func__); return 0; fail: @@ -289,7 +296,7 @@ fail: static int __devinit amd76x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); /* don't need to call pci_device_enable() */ return amd76x_probe1(pdev, ent->driver_data); @@ -309,7 +316,7 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0(__FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) return; diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index c454ded2b060..25edba55b18c 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -30,6 +30,14 @@ #include "edac_mc.h" +#define e752x_printk(level, fmt, arg...) \ + edac_printk(level, "e752x", fmt, ##arg) + + +#define e752x_mc_printk(mci, level, fmt, arg...) \ + edac_mc_chipset_printk(mci, level, "e752x", fmt, ##arg) + + #ifndef PCI_DEVICE_ID_INTEL_7520_0 #define PCI_DEVICE_ID_INTEL_7520_0 0x3590 #endif /* PCI_DEVICE_ID_INTEL_7520_0 */ @@ -215,7 +223,7 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, u32 remap; struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); if (page < pvt->tolm) return page; @@ -224,7 +232,7 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, remap = (page - pvt->tolm) + pvt->remapbase; if (remap < pvt->remaplimit) return remap; - printk(KERN_ERR "Invalid page %lx - out of range\n", page); + e752x_printk(KERN_ERR, "Invalid page %lx - out of range\n", page); return pvt->tolm - 1; } @@ -237,7 +245,7 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, int i; struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); /* convert the addr to 4k page */ page = sec1_add >> (PAGE_SHIFT - 4); @@ -246,24 +254,23 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, if (pvt->mc_symmetric) { /* chip select are bits 14 & 13 */ row = ((page >> 1) & 3); - printk(KERN_WARNING - "Test row %d Table %d %d %d %d %d %d %d %d\n", - row, pvt->map[0], pvt->map[1], pvt->map[2], - pvt->map[3], pvt->map[4], pvt->map[5], - pvt->map[6], pvt->map[7]); + e752x_printk(KERN_WARNING, + "Test row %d Table %d %d %d %d %d %d %d %d\n", + row, pvt->map[0], pvt->map[1], pvt->map[2], + pvt->map[3], pvt->map[4], pvt->map[5], + pvt->map[6], pvt->map[7]); /* test for channel remapping */ for (i = 0; i < 8; i++) { if (pvt->map[i] == row) break; } - printk(KERN_WARNING "Test computed row %d\n", i); + e752x_printk(KERN_WARNING, "Test computed row %d\n", i); if (i < 8) row = i; else - printk(KERN_WARNING - "MC%d: row %d not found in remap table\n", - mci->mc_idx, row); + e752x_mc_printk(mci, KERN_WARNING, + "row %d not found in remap table\n", row); } else row = edac_mc_find_csrow_by_page(mci, page); /* 0 = channel A, 1 = channel B */ @@ -293,7 +300,7 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add, int row; struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); if (error_one & 0x0202) { error_2b = ded_add; @@ -336,7 +343,7 @@ static inline void process_ue_no_info_wr(struct mem_ctl_info *mci, if (!handle_error) return; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); edac_mc_handle_ue_no_info(mci, "e752x UE log memory write"); } @@ -352,9 +359,9 @@ static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error, row = pvt->mc_symmetric ? ((page >> 1) & 3) : /* chip select are bits 14 & 13 */ edac_mc_find_csrow_by_page(mci, page); - printk(KERN_WARNING - "MC%d: CE page 0x%lx, row %d : Memory read retry\n", - mci->mc_idx, (long unsigned int) page, row); + e752x_mc_printk(mci, KERN_WARNING, + "CE page 0x%lx, row %d : Memory read retry\n", + (long unsigned int) page, row); } static inline void process_ded_retry(struct mem_ctl_info *mci, u16 error, @@ -372,8 +379,7 @@ static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error, *error_found = 1; if (handle_error) - printk(KERN_WARNING "MC%d: Memory threshold CE\n", - mci->mc_idx); + e752x_mc_printk(mci, KERN_WARNING, "Memory threshold CE\n"); } static char *global_message[11] = { @@ -391,7 +397,7 @@ static void do_global_error(int fatal, u32 errors) for (i = 0; i < 11; i++) { if (errors & (1 << i)) - printk(KERN_WARNING "%sError %s\n", + e752x_printk(KERN_WARNING, "%sError %s\n", fatal_message[fatal], global_message[i]); } } @@ -418,7 +424,7 @@ static void do_hub_error(int fatal, u8 errors) for (i = 0; i < 7; i++) { if (errors & (1 << i)) - printk(KERN_WARNING "%sError %s\n", + e752x_printk(KERN_WARNING, "%sError %s\n", fatal_message[fatal], hub_message[i]); } } @@ -445,7 +451,7 @@ static void do_membuf_error(u8 errors) for (i = 0; i < 4; i++) { if (errors & (1 << i)) - printk(KERN_WARNING "Non-Fatal Error %s\n", + e752x_printk(KERN_WARNING, "Non-Fatal Error %s\n", membuf_message[i]); } } @@ -478,7 +484,7 @@ static void do_sysbus_error(int fatal, u32 errors) for (i = 0; i < 10; i++) { if (errors & (1 << i)) - printk(KERN_WARNING "%sError System Bus %s\n", + e752x_printk(KERN_WARNING, "%sError System Bus %s\n", fatal_message[fatal], global_message[i]); } } @@ -727,7 +733,7 @@ static int e752x_process_error_info (struct mem_ctl_info *mci, static void e752x_check(struct mem_ctl_info *mci) { struct e752x_error_info info; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); e752x_get_error_info(mci, &info); e752x_process_error_info(mci, &info, 1); } @@ -752,7 +758,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) struct pci_dev *pres_dev; struct pci_dev *dev = NULL; - debugf0("MC: " __FILE__ ": %s(): mci\n", __func__); + debugf0("%s(): mci\n", __func__); debugf0("Starting Probe1\n"); /* enable device 0 function 1 */ @@ -776,7 +782,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) goto fail; } - debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__); + debugf3("%s(): init mci\n", __func__); mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | @@ -786,7 +792,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) mci->mod_ver = "$Revision: 1.5.2.11 $"; mci->pdev = pdev; - debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__); + debugf3("%s(): init pvt\n", __func__); pvt = (struct e752x_pvt *) mci->pvt_info; pvt->dev_info = &e752x_devs[dev_idx]; pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, @@ -796,14 +802,14 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pvt->bridge_ck = pci_scan_single_device(pdev->bus, PCI_DEVFN(0, 1)); if (pvt->bridge_ck == NULL) { - printk(KERN_ERR "MC: error reporting device not found:" + e752x_printk(KERN_ERR, "error reporting device not found:" "vendor %x device 0x%x (broken BIOS?)\n", PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev); goto fail; } pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); - debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__); + debugf3("%s(): more mci init\n", __func__); mci->ctl_name = pvt->dev_info->ctl_name; mci->edac_check = e752x_check; mci->ctl_page_to_phys = ctl_page_to_phys; @@ -828,8 +834,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pci_read_config_byte(mci->pdev, E752X_DRB + index, &value); /* convert a 128 or 64 MiB DRB to a page size. */ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); - debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n", - __func__, index, cumul_size); + debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, + cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -897,8 +903,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap |= EDAC_FLAG_NONE; - debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n", - __func__); + debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); /* load the top of low memory, remap base, and remap limit vars */ pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data); pvt->tolm = ((u32) pci_data) << 4; @@ -906,13 +911,12 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pvt->remapbase = ((u32) pci_data) << 14; pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data); pvt->remaplimit = ((u32) pci_data) << 14; - printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, - pvt->remapbase, pvt->remaplimit); + e752x_printk(KERN_INFO, + "tolm = %x, remapbase = %x, remaplimit = %x\n", + pvt->tolm, pvt->remapbase, pvt->remaplimit); if (edac_mc_add_mc(mci)) { - debugf3("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", - __func__); + debugf3("%s(): failed edac_mc_add_mc()\n", __func__); goto fail; } @@ -975,7 +979,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pci_write_config_word(dev, E752X_DRAM_NERR, stat16); /* get this far and it's successful */ - debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + debugf3("%s(): success\n", __func__); return 0; fail: @@ -995,7 +999,7 @@ fail: static int __devinit e752x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); /* wake up and enable device */ if(pci_enable_device(pdev) < 0) @@ -1009,7 +1013,7 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct e752x_pvt *pvt; - debugf0(__FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) return; @@ -1050,7 +1054,7 @@ static int __init e752x_init(void) { int pci_rc; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); pci_rc = pci_register_driver(&e752x_driver); return (pci_rc < 0) ? pci_rc : 0; } @@ -1058,7 +1062,7 @@ static int __init e752x_init(void) static void __exit e752x_exit(void) { - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); pci_unregister_driver(&e752x_driver); } diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index d5e320dfc66f..e7537413cad2 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -32,6 +32,14 @@ #include "edac_mc.h" +#define e7xxx_printk(level, fmt, arg...) \ + edac_printk(level, "e7xxx", fmt, ##arg) + + +#define e7xxx_mc_printk(mci, level, fmt, arg...) \ + edac_mc_chipset_printk(mci, level, "e7xxx", fmt, ##arg) + + #ifndef PCI_DEVICE_ID_INTEL_7205_0 #define PCI_DEVICE_ID_INTEL_7205_0 0x255d #endif /* PCI_DEVICE_ID_INTEL_7205_0 */ @@ -161,7 +169,7 @@ static const struct e7xxx_dev_info e7xxx_devs[] = { /* FIXME - is this valid for both SECDED and S4ECD4ED? */ static inline int e7xxx_find_channel(u16 syndrome) { - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); if ((syndrome & 0xff00) == 0) return 0; @@ -179,7 +187,7 @@ ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page) u32 remap; struct e7xxx_pvt *pvt = (struct e7xxx_pvt *) mci->pvt_info; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); if ((page < pvt->tolm) || ((page >= 0x100000) && (page < pvt->remapbase))) @@ -187,7 +195,7 @@ ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page) remap = (page - pvt->tolm) + pvt->remapbase; if (remap < pvt->remaplimit) return remap; - printk(KERN_ERR "Invalid page %lx - out of range\n", page); + e7xxx_printk(KERN_ERR, "Invalid page %lx - out of range\n", page); return pvt->tolm - 1; } @@ -199,7 +207,7 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) int row; int channel; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); /* read the error address */ error_1b = info->dram_celog_add; @@ -218,7 +226,7 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) static void process_ce_no_info(struct mem_ctl_info *mci) { - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow"); } @@ -228,7 +236,7 @@ static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) u32 error_2b, block_page; int row; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); /* read the error address */ error_2b = info->dram_uelog_add; @@ -241,7 +249,7 @@ static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) static void process_ue_no_info(struct mem_ctl_info *mci) { - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow"); } @@ -330,7 +338,7 @@ static void e7xxx_check(struct mem_ctl_info *mci) { struct e7xxx_error_info info; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); e7xxx_get_error_info(mci, &info); e7xxx_process_error_info(mci, &info, 1); } @@ -351,7 +359,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) unsigned long last_cumul_size; - debugf0("MC: " __FILE__ ": %s(): mci\n", __func__); + debugf0("%s(): mci\n", __func__); /* need to find out the number of channels */ pci_read_config_dword(pdev, E7XXX_DRC, &drc); @@ -369,7 +377,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) goto fail; } - debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__); + debugf3("%s(): init mci\n", __func__); mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = @@ -379,21 +387,21 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) mci->mod_ver = "$Revision: 1.5.2.9 $"; mci->pdev = pdev; - debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__); + debugf3("%s(): init pvt\n", __func__); pvt = (struct e7xxx_pvt *) mci->pvt_info; pvt->dev_info = &e7xxx_devs[dev_idx]; pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, pvt->dev_info->err_dev, pvt->bridge_ck); if (!pvt->bridge_ck) { - printk(KERN_ERR - "MC: error reporting device not found:" - "vendor %x device 0x%x (broken BIOS?)\n", - PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev); + e7xxx_printk(KERN_ERR, "error reporting device not found:" + "vendor %x device 0x%x (broken BIOS?)\n", + PCI_VENDOR_ID_INTEL, + e7xxx_devs[dev_idx].err_dev); goto fail; } - debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__); + debugf3("%s(): more mci init\n", __func__); mci->ctl_name = pvt->dev_info->ctl_name; mci->edac_check = e7xxx_check; @@ -418,8 +426,8 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) pci_read_config_byte(mci->pdev, E7XXX_DRB + index, &value); /* convert a 64 or 32 MiB DRB to a page size. */ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); - debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n", - __func__, index, cumul_size); + debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, + cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -449,8 +457,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap |= EDAC_FLAG_NONE; - debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n", - __func__); + debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); /* load the top of low memory, remap base, and remap limit vars */ pci_read_config_word(mci->pdev, E7XXX_TOLM, &pci_data); pvt->tolm = ((u32) pci_data) << 4; @@ -458,22 +465,21 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) pvt->remapbase = ((u32) pci_data) << 14; pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data); pvt->remaplimit = ((u32) pci_data) << 14; - printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, - pvt->remapbase, pvt->remaplimit); + e7xxx_printk(KERN_INFO, + "tolm = %x, remapbase = %x, remaplimit = %x\n", + pvt->tolm, pvt->remapbase, pvt->remaplimit); /* clear any pending errors, or initial state bits */ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03); pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03); if (edac_mc_add_mc(mci) != 0) { - debugf3("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", - __func__); + debugf3("%s(): failed edac_mc_add_mc()\n", __func__); goto fail; } /* get this far and it's successful */ - debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + debugf3("%s(): success\n", __func__); return 0; fail: @@ -490,7 +496,7 @@ fail: static int __devinit e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); /* wake up and enable device */ return pci_enable_device(pdev) ? @@ -503,7 +509,7 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct e7xxx_pvt *pvt; - debugf0(__FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); if (((mci = edac_mc_find_mci_by_pdev(pdev)) != 0) && edac_mc_del_mc(mci)) { diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 8a7a3ab745aa..499ac90ad67e 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -37,7 +37,7 @@ #include "edac_mc.h" -#define EDAC_MC_VERSION "edac_mc Ver: 2.0.0 " __DATE__ +#define EDAC_MC_VERSION "Ver: 2.0.0 " __DATE__ /* For now, disable the EDAC sysfs code. The sysfs interface that EDAC * presents to user space needs more thought, and is likely to change @@ -243,7 +243,7 @@ static struct memctrl_dev_attribute *memctrl_attr[] = { /* Main MC kobject release() function */ static void edac_memctrl_master_release(struct kobject *kobj) { - debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__); + debugf1("%s()\n", __func__); } static struct kobj_type ktype_memctrl = { @@ -271,7 +271,7 @@ static int edac_sysfs_memctrl_setup(void) { int err=0; - debugf1("MC: " __FILE__ ": %s()\n", __func__); + debugf1("%s()\n", __func__); /* create the /sys/devices/system/edac directory */ err = sysdev_class_register(&edac_class); @@ -295,7 +295,7 @@ static int edac_sysfs_memctrl_setup(void) } } } else { - debugf1(KERN_WARNING "__FILE__ %s() error=%d\n", __func__,err); + debugf1("%s() error=%d\n", __func__, err); } return err; @@ -567,7 +567,7 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = { /* No memory to release */ static void edac_pci_release(struct kobject *kobj) { - debugf1("EDAC PCI: " __FILE__ ": %s()\n", __func__); + debugf1("%s()\n", __func__); } static struct kobj_type ktype_edac_pci = { @@ -591,7 +591,7 @@ static int edac_sysfs_pci_setup(void) { int err; - debugf1("MC: " __FILE__ ": %s()\n", __func__); + debugf1("%s()\n", __func__); memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj)); @@ -616,7 +616,7 @@ static int edac_sysfs_pci_setup(void) static void edac_sysfs_pci_teardown(void) { #ifndef DISABLE_EDAC_SYSFS - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); kobject_unregister(&edac_pci_kobj); kobject_put(&edac_pci_kobj); @@ -808,7 +808,7 @@ static struct csrowdev_attribute *csrow_attr[] = { /* No memory to release */ static void edac_csrow_instance_release(struct kobject *kobj) { - debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__); + debugf1("%s()\n", __func__); } static struct kobj_type ktype_csrow = { @@ -823,7 +823,7 @@ static int edac_create_csrow_object(struct kobject *edac_mci_kobj, { int err = 0; - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); memset(&csrow->kobj, 0, sizeof(csrow->kobj)); @@ -1066,8 +1066,7 @@ static void edac_mci_instance_release(struct kobject *kobj) struct mem_ctl_info *mci; mci = container_of(kobj,struct mem_ctl_info,edac_mci_kobj); - debugf0("MC: " __FILE__ ": %s() idx=%d calling kfree\n", - __func__, mci->mc_idx); + debugf0("%s() idx=%d calling kfree\n", __func__, mci->mc_idx); kfree(mci); } @@ -1102,7 +1101,7 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) struct csrow_info *csrow; struct kobject *edac_mci_kobj=&mci->edac_mci_kobj; - debugf0("MC: " __FILE__ ": %s() idx=%d\n", __func__, mci->mc_idx); + debugf0("%s() idx=%d\n", __func__, mci->mc_idx); memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj)); kobject_init(edac_mci_kobj); @@ -1174,7 +1173,7 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) #ifndef DISABLE_EDAC_SYSFS int i; - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); /* remove all csrow kobjects */ for (i = 0; i < mci->nr_csrows; i++) { @@ -1396,7 +1395,7 @@ struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev *pdev) struct mem_ctl_info *mci; struct list_head *item; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); list_for_each(item, &mc_devices) { mci = list_entry(item, struct mem_ctl_info, link); @@ -1419,10 +1418,11 @@ static int add_mc_to_global_list (struct mem_ctl_info *mci) insert_before = &mc_devices; } else { if (edac_mc_find_mci_by_pdev(mci->pdev)) { - printk(KERN_WARNING - "EDAC MC: %s (%s) %s %s already assigned %d\n", - mci->pdev->dev.bus_id, pci_name(mci->pdev), - mci->mod_name, mci->ctl_name, mci->mc_idx); + edac_printk(KERN_WARNING, EDAC_MC, + "%s (%s) %s %s already assigned %d\n", + mci->pdev->dev.bus_id, + pci_name(mci->pdev), mci->mod_name, + mci->ctl_name, mci->mc_idx); return 1; } @@ -1468,7 +1468,7 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) { int rc = 1; - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); #ifdef CONFIG_EDAC_DEBUG if (edac_debug_level >= 3) edac_mc_dump_mci(mci); @@ -1493,19 +1493,15 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) mci->start_time = jiffies; if (edac_create_sysfs_mci_device(mci)) { - printk(KERN_WARNING - "EDAC MC%d: failed to create sysfs device\n", - mci->mc_idx); + edac_mc_printk(mci, KERN_WARNING, + "failed to create sysfs device\n"); /* FIXME - should there be an error code and unwind? */ goto finish; } /* Report action taken */ - printk(KERN_INFO - "EDAC MC%d: Giving out device to %s %s: PCI %s\n", - mci->mc_idx, mci->mod_name, mci->ctl_name, - pci_name(mci->pdev)); - + edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: PCI %s\n", + mci->mod_name, mci->ctl_name, pci_name(mci->pdev)); rc = 0; @@ -1547,13 +1543,12 @@ int edac_mc_del_mc(struct mem_ctl_info *mci) { int rc = 1; - debugf0("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + debugf0("MC%d: %s()\n", mci->mc_idx, __func__); down(&mem_ctls_mutex); del_mc_from_global_list(mci); - printk(KERN_INFO - "EDAC MC%d: Removed device %d for %s %s: PCI %s\n", - mci->mc_idx, mci->mc_idx, mci->mod_name, mci->ctl_name, - pci_name(mci->pdev)); + edac_printk(KERN_INFO, EDAC_MC, + "Removed device %d for %s %s: PCI %s\n", mci->mc_idx, + mci->mod_name, mci->ctl_name, pci_name(mci->pdev)); rc = 0; up(&mem_ctls_mutex); @@ -1570,7 +1565,7 @@ void edac_mc_scrub_block(unsigned long page, unsigned long offset, void *virt_addr; unsigned long flags = 0; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); /* ECC error page was not in our memory. Ignore it. */ if(!pfn_valid(page)) @@ -1604,8 +1599,7 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, struct csrow_info *csrows = mci->csrows; int row, i; - debugf1("MC%d: " __FILE__ ": %s(): 0x%lx\n", mci->mc_idx, __func__, - page); + debugf1("MC%d: %s(): 0x%lx\n", mci->mc_idx, __func__, page); row = -1; for (i = 0; i < mci->nr_csrows; i++) { @@ -1614,11 +1608,10 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, if (csrow->nr_pages == 0) continue; - debugf3("MC%d: " __FILE__ - ": %s(): first(0x%lx) page(0x%lx)" - " last(0x%lx) mask(0x%lx)\n", mci->mc_idx, - __func__, csrow->first_page, page, - csrow->last_page, csrow->page_mask); + debugf3("MC%d: %s(): first(0x%lx) page(0x%lx) last(0x%lx) " + "mask(0x%lx)\n", mci->mc_idx, __func__, + csrow->first_page, page, csrow->last_page, + csrow->page_mask); if ((page >= csrow->first_page) && (page <= csrow->last_page) && @@ -1630,9 +1623,9 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, } if (row == -1) - printk(KERN_ERR - "EDAC MC%d: could not look up page error address %lx\n", - mci->mc_idx, (unsigned long) page); + edac_mc_printk(mci, KERN_ERR, + "could not look up page error address %lx\n", + (unsigned long) page); return row; } @@ -1650,36 +1643,35 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, { unsigned long remapped_page; - debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + debugf3("MC%d: %s()\n", mci->mc_idx, __func__); /* FIXME - maybe make panic on INTERNAL ERROR an option */ if (row >= mci->nr_csrows || row < 0) { /* something is wrong */ - printk(KERN_ERR - "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n", - mci->mc_idx, row, mci->nr_csrows); + edac_mc_printk(mci, KERN_ERR, + "INTERNAL ERROR: row out of range " + "(%d >= %d)\n", row, mci->nr_csrows); edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); return; } if (channel >= mci->csrows[row].nr_channels || channel < 0) { /* something is wrong */ - printk(KERN_ERR - "EDAC MC%d: INTERNAL ERROR: channel out of range " - "(%d >= %d)\n", - mci->mc_idx, channel, mci->csrows[row].nr_channels); + edac_mc_printk(mci, KERN_ERR, + "INTERNAL ERROR: channel out of range " + "(%d >= %d)\n", channel, + mci->csrows[row].nr_channels); edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); return; } if (log_ce) /* FIXME - put in DIMM location */ - printk(KERN_WARNING - "EDAC MC%d: CE page 0x%lx, offset 0x%lx," - " grain %d, syndrome 0x%lx, row %d, channel %d," - " label \"%s\": %s\n", mci->mc_idx, - page_frame_number, offset_in_page, - mci->csrows[row].grain, syndrome, row, channel, - mci->csrows[row].channels[channel].label, msg); + edac_mc_printk(mci, KERN_WARNING, + "CE page 0x%lx, offset 0x%lx, grain %d, syndrome " + "0x%lx, row %d, channel %d, label \"%s\": %s\n", + page_frame_number, offset_in_page, + mci->csrows[row].grain, syndrome, row, channel, + mci->csrows[row].channels[channel].label, msg); mci->ce_count++; mci->csrows[row].ce_count++; @@ -1711,9 +1703,8 @@ void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg) { if (log_ce) - printk(KERN_WARNING - "EDAC MC%d: CE - no information available: %s\n", - mci->mc_idx, msg); + edac_mc_printk(mci, KERN_WARNING, + "CE - no information available: %s\n", msg); mci->ce_noinfo_count++; mci->ce_count++; } @@ -1732,14 +1723,14 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci, int chan; int chars; - debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + debugf3("MC%d: %s()\n", mci->mc_idx, __func__); /* FIXME - maybe make panic on INTERNAL ERROR an option */ if (row >= mci->nr_csrows || row < 0) { /* something is wrong */ - printk(KERN_ERR - "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n", - mci->mc_idx, row, mci->nr_csrows); + edac_mc_printk(mci, KERN_ERR, + "INTERNAL ERROR: row out of range " + "(%d >= %d)\n", row, mci->nr_csrows); edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); return; } @@ -1757,11 +1748,11 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci, } if (log_ue) - printk(KERN_EMERG - "EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d," - " labels \"%s\": %s\n", mci->mc_idx, - page_frame_number, offset_in_page, - mci->csrows[row].grain, row, labels, msg); + edac_mc_printk(mci, KERN_EMERG, + "UE page 0x%lx, offset 0x%lx, grain %d, row %d, " + "labels \"%s\": %s\n", page_frame_number, + offset_in_page, mci->csrows[row].grain, row, labels, + msg); if (panic_on_ue) panic @@ -1784,9 +1775,8 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, panic("EDAC MC%d: Uncorrected Error", mci->mc_idx); if (log_ue) - printk(KERN_WARNING - "EDAC MC%d: UE - no information available: %s\n", - mci->mc_idx, msg); + edac_mc_printk(mci, KERN_WARNING, + "UE - no information available: %s\n", msg); mci->ue_noinfo_count++; mci->ue_count++; } @@ -1856,25 +1846,22 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) /* check the status reg for errors */ if (status) { if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) - printk(KERN_CRIT - "EDAC PCI- " + edac_printk(KERN_CRIT, EDAC_PCI, "Signaled System Error on %s\n", - pci_name (dev)); + pci_name(dev)); if (status & (PCI_STATUS_PARITY)) { - printk(KERN_CRIT - "EDAC PCI- " + edac_printk(KERN_CRIT, EDAC_PCI, "Master Data Parity Error on %s\n", - pci_name (dev)); + pci_name(dev)); atomic_inc(&pci_parity_count); } if (status & (PCI_STATUS_DETECTED_PARITY)) { - printk(KERN_CRIT - "EDAC PCI- " + edac_printk(KERN_CRIT, EDAC_PCI, "Detected Parity Error on %s\n", - pci_name (dev)); + pci_name(dev)); atomic_inc(&pci_parity_count); } @@ -1895,25 +1882,22 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) /* check the secondary status reg for errors */ if (status) { if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) - printk(KERN_CRIT - "EDAC PCI-Bridge- " + edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " "Signaled System Error on %s\n", - pci_name (dev)); + pci_name(dev)); if (status & (PCI_STATUS_PARITY)) { - printk(KERN_CRIT - "EDAC PCI-Bridge- " - "Master Data Parity Error on %s\n", - pci_name (dev)); + edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " + "Master Data Parity Error on " + "%s\n", pci_name(dev)); atomic_inc(&pci_parity_count); } if (status & (PCI_STATUS_DETECTED_PARITY)) { - printk(KERN_CRIT - "EDAC PCI-Bridge- " + edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " "Detected Parity Error on %s\n", - pci_name (dev)); + pci_name(dev)); atomic_inc(&pci_parity_count); } @@ -1992,7 +1976,7 @@ static void do_pci_parity_check(void) unsigned long flags; int before_count; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); if (!check_pci_parity) return; @@ -2050,7 +2034,7 @@ static inline void check_mc_devices (void) struct list_head *item; struct mem_ctl_info *mci; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); /* during poll, have interrupts off */ local_irq_save(flags); @@ -2076,10 +2060,8 @@ static inline void check_mc_devices (void) */ static void do_edac_check(void) { - debugf3("MC: " __FILE__ ": %s()\n", __func__); - + debugf3("%s()\n", __func__); check_mc_devices(); - do_pci_parity_check(); } @@ -2102,7 +2084,7 @@ static int edac_kernel_thread(void *arg) */ static int __init edac_mc_init(void) { - printk(KERN_INFO "MC: " __FILE__ " version " EDAC_MC_VERSION "\n"); + edac_printk(KERN_INFO, EDAC_MC, EDAC_MC_VERSION "\n"); /* * Harvest and clear any boot/initialization PCI parity errors @@ -2118,14 +2100,16 @@ static int __init edac_mc_init(void) /* Create the MC sysfs entires */ if (edac_sysfs_memctrl_setup()) { - printk(KERN_ERR "EDAC MC: Error initializing sysfs code\n"); + edac_printk(KERN_ERR, EDAC_MC, + "Error initializing sysfs code\n"); return -ENODEV; } /* Create the PCI parity sysfs entries */ if (edac_sysfs_pci_setup()) { edac_sysfs_memctrl_teardown(); - printk(KERN_ERR "EDAC PCI: Error initializing sysfs code\n"); + edac_printk(KERN_ERR, EDAC_MC, + "EDAC PCI: Error initializing sysfs code\n"); return -ENODEV; } @@ -2148,7 +2132,7 @@ static int __init edac_mc_init(void) */ static void __exit edac_mc_exit(void) { - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); kthread_stop(edac_thread); diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h index 75ecf484a43a..4bd8375a8d7e 100644 --- a/drivers/edac/edac_mc.h +++ b/drivers/edac/edac_mc.h @@ -43,10 +43,29 @@ #define PAGES_TO_MiB( pages ) ( ( pages ) << ( PAGE_SHIFT - 20 ) ) #endif +#define edac_printk(level, prefix, fmt, arg...) \ + printk(level "EDAC " prefix ": " fmt, ##arg) + +#define edac_mc_printk(mci, level, fmt, arg...) \ + printk(level "EDAC MC%d: " fmt, mci->mc_idx, ##arg) + +#define edac_mc_chipset_printk(mci, level, prefix, fmt, arg...) \ + printk(level "EDAC " prefix " MC%d: " fmt, mci->mc_idx, ##arg) + +/* prefixes for edac_printk() and edac_mc_printk() */ +#define EDAC_MC "MC" +#define EDAC_PCI "PCI" +#define EDAC_DEBUG "DEBUG" + #ifdef CONFIG_EDAC_DEBUG extern int edac_debug_level; -#define edac_debug_printk(level, fmt, args...) \ -do { if (level <= edac_debug_level) printk(KERN_DEBUG fmt, ##args); } while(0) + +#define edac_debug_printk(level, fmt, arg...) \ + do { \ + if (level <= edac_debug_level) \ + edac_printk(KERN_DEBUG, EDAC_DEBUG, fmt, ##arg); \ + } while(0) + #define debugf0( ... ) edac_debug_printk(0, __VA_ARGS__ ) #define debugf1( ... ) edac_debug_printk(1, __VA_ARGS__ ) #define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ ) diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 52596e75f9c2..fa9ab84fa5c9 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -19,6 +19,14 @@ #include "edac_mc.h" +#define i82860_printk(level, fmt, arg...) \ + edac_printk(level, "i82860", fmt, ##arg) + + +#define i82860_mc_printk(mci, level, fmt, arg...) \ + edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg) + + #ifndef PCI_DEVICE_ID_INTEL_82860_0 #define PCI_DEVICE_ID_INTEL_82860_0 0x2531 #endif /* PCI_DEVICE_ID_INTEL_82860_0 */ @@ -117,7 +125,7 @@ static void i82860_check(struct mem_ctl_info *mci) { struct i82860_error_info info; - debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + debugf1("MC%d: %s()\n", mci->mc_idx, __func__); i82860_get_error_info(mci, &info); i82860_process_error_info(mci, &info, 1); } @@ -143,7 +151,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__); + debugf3("%s(): init mci\n", __func__); mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_DDR; @@ -179,8 +187,8 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) cumul_size = (value & I82860_GBA_MASK) << (I82860_GBA_SHIFT - PAGE_SHIFT); - debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n", - __func__, index, cumul_size); + debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, + cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -198,13 +206,11 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003); if (edac_mc_add_mc(mci)) { - debugf3("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", - __func__); + debugf3("%s(): failed edac_mc_add_mc()\n", __func__); edac_mc_free(mci); } else { /* get this far and it's successful */ - debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + debugf3("%s(): success\n", __func__); rc = 0; } return rc; @@ -216,9 +222,9 @@ static int __devinit i82860_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); - printk(KERN_INFO "i82860 init one\n"); + i82860_printk(KERN_INFO, "i82860 init one\n"); if(pci_enable_device(pdev) < 0) return -EIO; rc = i82860_probe1(pdev, ent->driver_data); @@ -231,7 +237,7 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0(__FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); mci = edac_mc_find_mci_by_pdev(pdev); if ((mci != NULL) && (edac_mc_del_mc(mci) == 0)) @@ -257,7 +263,7 @@ static int __init i82860_init(void) { int pci_rc; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); if ((pci_rc = pci_register_driver(&i82860_driver)) < 0) return pci_rc; @@ -281,7 +287,7 @@ static int __init i82860_init(void) static void __exit i82860_exit(void) { - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); pci_unregister_driver(&i82860_driver); if (!i82860_registered) { diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 1991f94af753..0e22c66ee36c 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -26,6 +26,14 @@ #include "edac_mc.h" +#define i82875p_printk(level, fmt, arg...) \ + edac_printk(level, "i82875p", fmt, ##arg) + + +#define i82875p_mc_printk(mci, level, fmt, arg...) \ + edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg) + + #ifndef PCI_DEVICE_ID_INTEL_82875_0 #define PCI_DEVICE_ID_INTEL_82875_0 0x2578 #endif /* PCI_DEVICE_ID_INTEL_82875_0 */ @@ -254,7 +262,7 @@ static void i82875p_check(struct mem_ctl_info *mci) { struct i82875p_error_info info; - debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + debugf1("MC%d: %s()\n", mci->mc_idx, __func__); i82875p_get_error_info(mci, &info); i82875p_process_error_info(mci, &info, 1); } @@ -279,7 +287,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) u32 nr_chans; u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); ovrfl_pdev = pci_find_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); @@ -298,16 +306,16 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) } #ifdef CONFIG_PROC_FS if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) { - printk(KERN_ERR "MC: " __FILE__ - ": %s(): Failed to attach overflow device\n", - __func__); + i82875p_printk(KERN_ERR, + "%s(): Failed to attach overflow device\n", + __func__); goto fail; } #endif /* CONFIG_PROC_FS */ if (pci_enable_device(ovrfl_pdev)) { - printk(KERN_ERR "MC: " __FILE__ - ": %s(): Failed to enable overflow device\n", - __func__); + i82875p_printk(KERN_ERR, + "%s(): Failed to enable overflow device\n", + __func__); goto fail; } @@ -321,8 +329,8 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) pci_resource_len(ovrfl_pdev, 0)); if (!ovrfl_window) { - printk(KERN_ERR "MC: " __FILE__ - ": %s(): Failed to ioremap bar6\n", __func__); + i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n", + __func__); goto fail; } @@ -340,7 +348,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) goto fail; } - debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__); + debugf3("%s(): init mci\n", __func__); mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_DDR; @@ -355,7 +363,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_check = i82875p_check; mci->ctl_page_to_phys = NULL; - debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__); + debugf3("%s(): init pvt\n", __func__); pvt = (struct i82875p_pvt *) mci->pvt_info; pvt->ovrfl_pdev = ovrfl_pdev; @@ -374,8 +382,8 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) value = readb(ovrfl_window + I82875P_DRB + index); cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); - debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n", - __func__, index, cumul_size); + debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, + cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -393,13 +401,12 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081); if (edac_mc_add_mc(mci)) { - debugf3("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", __func__); + debugf3("%s(): failed edac_mc_add_mc()\n", __func__); goto fail; } /* get this far and it's successful */ - debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + debugf3("%s(): success\n", __func__); return 0; fail: @@ -425,9 +432,9 @@ static int __devinit i82875p_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); - printk(KERN_INFO "i82875p init one\n"); + i82875p_printk(KERN_INFO, "i82875p init one\n"); if(pci_enable_device(pdev) < 0) return -EIO; rc = i82875p_probe1(pdev, ent->driver_data); @@ -442,7 +449,7 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct i82875p_pvt *pvt = NULL; - debugf0(__FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) return; @@ -487,7 +494,7 @@ static int __init i82875p_init(void) { int pci_rc; - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); pci_rc = pci_register_driver(&i82875p_driver); if (pci_rc < 0) return pci_rc; @@ -513,7 +520,7 @@ static int __init i82875p_init(void) static void __exit i82875p_exit(void) { - debugf3("MC: " __FILE__ ": %s()\n", __func__); + debugf3("%s()\n", __func__); pci_unregister_driver(&i82875p_driver); if (!i82875p_registered) { diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index e90892831b90..27d16dc2f11d 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -26,6 +26,12 @@ #include "edac_mc.h" +#define r82600_printk(level, fmt, arg...) \ + edac_printk(level, "r82600", fmt, ##arg) + +#define r82600_mc_printk(mci, level, fmt, arg...) \ + edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg) + /* Radisys say "The 82600 integrates a main memory SDRAM controller that * supports up to four banks of memory. The four banks can support a mix of * sizes of 64 bit wide (72 bits with ECC) Synchronous DRAM (SDRAM) DIMMs, @@ -196,7 +202,7 @@ static void r82600_check(struct mem_ctl_info *mci) { struct r82600_error_info info; - debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); + debugf1("MC%d: %s()\n", mci->mc_idx, __func__); r82600_get_error_info(mci, &info); r82600_process_error_info(mci, &info, 1); } @@ -215,7 +221,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) u32 row_high_limit_last = 0; u32 eap_init_bits; - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); @@ -226,11 +232,10 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) scrub_disabled = eapr & BIT(31); sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); - debugf2("MC: " __FILE__ ": %s(): sdram refresh rate = %#0x\n", - __func__, sdram_refresh_rate); + debugf2("%s(): sdram refresh rate = %#0x\n", __func__, + sdram_refresh_rate); - debugf2("MC: " __FILE__ ": %s(): DRAMC register = %#0x\n", __func__, - dramcr); + debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr); mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS); @@ -239,7 +244,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) goto fail; } - debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); + debugf0("%s(): mci = %p\n", __func__, mci); mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; @@ -255,9 +260,8 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; if (ecc_on) { if (scrub_disabled) - debugf3("MC: " __FILE__ ": %s(): mci = %p - " - "Scrubbing disabled! EAP: %#0x\n", __func__, - mci, eapr); + debugf3("%s(): mci = %p - Scrubbing disabled! EAP: " + "%#0x\n", __func__, mci, eapr); } else mci->edac_cap = EDAC_FLAG_NONE; @@ -276,16 +280,15 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) /* find the DRAM Chip Select Base address and mask */ pci_read_config_byte(mci->pdev, R82600_DRBA + index, &drbar); - debugf1("MC%d: " __FILE__ ": %s() Row=%d DRBA = %#0x\n", - mci->mc_idx, __func__, index, drbar); + debugf1("MC%d: %s() Row=%d DRBA = %#0x\n", mci->mc_idx, + __func__, index, drbar); row_high_limit = ((u32) drbar << 24); /* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */ - debugf1("MC%d: " __FILE__ ": %s() Row=%d, " - "Boundry Address=%#0x, Last = %#0x \n", - mci->mc_idx, __func__, index, row_high_limit, - row_high_limit_last); + debugf1("MC%d: %s() Row=%d, Boundry Address=%#0x, Last = " + "%#0x \n", mci->mc_idx, __func__, index, + row_high_limit, row_high_limit_last); /* Empty row [p.57] */ if (row_high_limit == row_high_limit_last) @@ -312,8 +315,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) /* FIXME should we? */ if (edac_mc_add_mc(mci)) { - debugf3("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", __func__); + debugf3("%s(): failed edac_mc_add_mc()\n", __func__); goto fail; } @@ -325,14 +327,14 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) eap_init_bits = BIT(0) & BIT(1); if (disable_hardware_scrub) { eap_init_bits |= BIT(31); - debugf3("MC: " __FILE__ ": %s(): Disabling Hardware Scrub " - "(scrub on error)\n", __func__); + debugf3("%s(): Disabling Hardware Scrub (scrub on error)\n", + __func__); } pci_write_bits32(mci->pdev, R82600_EAP, eap_init_bits, eap_init_bits); - debugf3("MC: " __FILE__ ": %s(): success\n", __func__); + debugf3("%s(): success\n", __func__); return 0; fail: @@ -346,7 +348,7 @@ fail: static int __devinit r82600_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("MC: " __FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); /* don't need to call pci_device_enable() */ return r82600_probe1(pdev, ent->driver_data); @@ -357,7 +359,7 @@ static void __devexit r82600_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0(__FILE__ ": %s()\n", __func__); + debugf0("%s()\n", __func__); if (((mci = edac_mc_find_mci_by_pdev(pdev)) != NULL) && !edac_mc_del_mc(mci)) -- cgit v1.2.3-59-g8ed1b From 680cbbbb0e336b04b74be48b8ddd870537f1e226 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:41 -0800 Subject: [PATCH] EDAC: name cleanup Perform the following name substitutions on all source files: sed 's/BS_MOD_STR/EDAC_MOD_STR/g' sed 's/bs_thread_info/edac_thread_info/g' sed 's/bs_thread/edac_thread/g' sed 's/bs_xstr/edac_xstr/g' sed 's/bs_str/edac_str/g' The names that start with BS_ or bs_ are artifacts of when the code was called "bluesmoke". Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/amd76x_edac.c | 4 ++-- drivers/edac/e752x_edac.c | 4 ++-- drivers/edac/e7xxx_edac.c | 4 ++-- drivers/edac/edac_mc.h | 6 +++--- drivers/edac/i82860_edac.c | 4 ++-- drivers/edac/i82875p_edac.c | 4 ++-- drivers/edac/r82600_edac.c | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 60535bb9275f..da171a56b636 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -233,7 +233,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = ems_mode ? (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE; - mci->mod_name = BS_MOD_STR; + mci->mod_name = EDAC_MOD_STR; mci->mod_ver = "$Revision: 1.4.2.5 $"; mci->ctl_name = amd76x_devs[dev_idx].ctl_name; mci->edac_check = amd76x_check; @@ -339,7 +339,7 @@ MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl); static struct pci_driver amd76x_driver = { - .name = BS_MOD_STR, + .name = EDAC_MOD_STR, .probe = amd76x_init_one, .remove = __devexit_p(amd76x_remove_one), .id_table = amd76x_pci_tbl, diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 25edba55b18c..48373fdc6343 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -788,7 +788,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED; /* FIXME - what if different memory types are in different csrows? */ - mci->mod_name = BS_MOD_STR; + mci->mod_name = EDAC_MOD_STR; mci->mod_ver = "$Revision: 1.5.2.11 $"; mci->pdev = pdev; @@ -1043,7 +1043,7 @@ MODULE_DEVICE_TABLE(pci, e752x_pci_tbl); static struct pci_driver e752x_driver = { - .name = BS_MOD_STR, + .name = EDAC_MOD_STR, .probe = e752x_init_one, .remove = __devexit_p(e752x_remove_one), .id_table = e752x_pci_tbl, diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index e7537413cad2..8001797a6bc5 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -383,7 +383,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED; /* FIXME - what if different memory types are in different csrows? */ - mci->mod_name = BS_MOD_STR; + mci->mod_name = EDAC_MOD_STR; mci->mod_ver = "$Revision: 1.5.2.9 $"; mci->pdev = pdev; @@ -536,7 +536,7 @@ MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl); static struct pci_driver e7xxx_driver = { - .name = BS_MOD_STR, + .name = EDAC_MOD_STR, .probe = e7xxx_init_one, .remove = __devexit_p(e7xxx_remove_one), .id_table = e7xxx_pci_tbl, diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h index 4bd8375a8d7e..0bcc3797c753 100644 --- a/drivers/edac/edac_mc.h +++ b/drivers/edac/edac_mc.h @@ -80,9 +80,9 @@ extern int edac_debug_level; #endif /* !CONFIG_EDAC_DEBUG */ -#define bs_xstr(s) bs_str(s) -#define bs_str(s) #s -#define BS_MOD_STR bs_xstr(KBUILD_BASENAME) +#define edac_xstr(s) edac_str(s) +#define edac_str(s) #s +#define EDAC_MOD_STR edac_xstr(KBUILD_BASENAME) #define BIT(x) (1 << (x)) diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index fa9ab84fa5c9..b0c05ad73067 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -162,7 +162,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = EDAC_FLAG_SECDED; /* adjust FLAGS */ - mci->mod_name = BS_MOD_STR; + mci->mod_name = EDAC_MOD_STR; mci->mod_ver = "$Revision: 1.1.2.6 $"; mci->ctl_name = i82860_devs[dev_idx].ctl_name; mci->edac_check = i82860_check; @@ -253,7 +253,7 @@ static const struct pci_device_id i82860_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, i82860_pci_tbl); static struct pci_driver i82860_driver = { - .name = BS_MOD_STR, + .name = EDAC_MOD_STR, .probe = i82860_init_one, .remove = __devexit_p(i82860_remove_one), .id_table = i82860_pci_tbl, diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 0e22c66ee36c..a547c30473e4 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -357,7 +357,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = EDAC_FLAG_UNKNOWN; /* adjust FLAGS */ - mci->mod_name = BS_MOD_STR; + mci->mod_name = EDAC_MOD_STR; mci->mod_ver = "$Revision: 1.5.2.11 $"; mci->ctl_name = i82875p_devs[dev_idx].ctl_name; mci->edac_check = i82875p_check; @@ -483,7 +483,7 @@ MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl); static struct pci_driver i82875p_driver = { - .name = BS_MOD_STR, + .name = EDAC_MOD_STR, .probe = i82875p_init_one, .remove = __devexit_p(i82875p_remove_one), .id_table = i82875p_pci_tbl, diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 27d16dc2f11d..ac1359828e78 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -265,7 +265,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) } else mci->edac_cap = EDAC_FLAG_NONE; - mci->mod_name = BS_MOD_STR; + mci->mod_name = EDAC_MOD_STR; mci->mod_ver = "$Revision: 1.1.2.6 $"; mci->ctl_name = "R82600"; mci->edac_check = r82600_check; @@ -376,7 +376,7 @@ MODULE_DEVICE_TABLE(pci, r82600_pci_tbl); static struct pci_driver r82600_driver = { - .name = BS_MOD_STR, + .name = EDAC_MOD_STR, .probe = r82600_init_one, .remove = __devexit_p(r82600_remove_one), .id_table = r82600_pci_tbl, -- cgit v1.2.3-59-g8ed1b From 225159bd0a349bfd8cd9ae7c6bf39d75df09304a Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:41 -0800 Subject: [PATCH] EDAC: amd76x pci_dev_get/pci_dev_put fixes Eliminate unnecessary calls to pci_dev_get() and pci_dev_put() from amd76x driver. Signed-off-by: David S. Peterson Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/amd76x_edac.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index da171a56b636..6b7a441f0482 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -226,7 +226,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) debugf0("%s(): mci = %p\n", __func__, mci); - mci->pdev = pci_dev_get(pdev); + mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; @@ -284,11 +284,8 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) return 0; fail: - if (mci) { - if(mci->pdev) - pci_dev_put(mci->pdev); + if (mci != NULL) edac_mc_free(mci); - } return rc; } @@ -322,7 +319,6 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev) return; if (edac_mc_del_mc(mci)) return; - pci_dev_put(mci->pdev); edac_mc_free(mci); } -- cgit v1.2.3-59-g8ed1b From 3847bccce80c8a01d7adbad9961564252207302a Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:42 -0800 Subject: [PATCH] EDAC: e752x cleanup - Add ctl_dev field to "struct e752x_dev_info". Then we can eliminate ugly switch statement from e752x_probe1(). - Remove code from e752x_probe1() that clears initial PCI bus parity errors. The core EDAC module already does this. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/e752x_edac.c | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 48373fdc6343..f31725a55e54 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -181,6 +181,7 @@ struct e752x_pvt { struct e752x_dev_info { u16 err_dev; + u16 ctl_dev; const char *ctl_name; }; @@ -207,12 +208,15 @@ struct e752x_error_info { static const struct e752x_dev_info e752x_devs[] = { [E7520] = { .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR, + .ctl_dev = PCI_DEVICE_ID_INTEL_7520_0, .ctl_name = "E7520"}, [E7525] = { .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR, + .ctl_dev = PCI_DEVICE_ID_INTEL_7525_0, .ctl_name = "E7525"}, [E7320] = { .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR, + .ctl_dev = PCI_DEVICE_ID_INTEL_7320_0, .ctl_name = "E7320"}, }; @@ -742,7 +746,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) { int rc = -ENODEV; int index; - u16 pci_data, stat; + u16 pci_data; u32 stat32; u16 stat16; u8 stat8; @@ -755,7 +759,6 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ u32 dra; unsigned long last_cumul_size; - struct pci_dev *pres_dev; struct pci_dev *dev = NULL; debugf0("%s(): mci\n", __func__); @@ -920,33 +923,9 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) goto fail; } - /* Walk through the PCI table and clear errors */ - switch (dev_idx) { - case E7520: - dev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_7520_0, NULL); - break; - case E7525: - dev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_7525_0, NULL); - break; - case E7320: - dev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_7320_0, NULL); - break; - } - - + dev = pci_get_device(PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].ctl_dev, + NULL); pvt->dev_d0f0 = dev; - for (pres_dev = dev; - ((struct pci_dev *) pres_dev->global_list.next != dev); - pres_dev = (struct pci_dev *) pres_dev->global_list.next) { - pci_read_config_dword(pres_dev, PCI_COMMAND, &stat32); - stat = (u16) (stat32 >> 16); - /* clear any error bits */ - if (stat32 & ((1 << 6) + (1 << 8))) - pci_write_config_word(pres_dev, PCI_STATUS, stat); - } /* find the error reporting device and clear errors */ dev = pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck); /* Turn off error disable & SMI in case the BIOS turned it on */ -- cgit v1.2.3-59-g8ed1b From e8a491b401dbbc5af9fe6483dc558d76343bfbb3 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:43 -0800 Subject: [PATCH] EDAC: i82860 cleanup - Fix i82860_init() so it cleans up properly on failure. - Fix i82860_exit() so it cleans up properly. - Fix typo in comment (i.e. www.redhat.com.com). Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/i82860_edac.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index b0c05ad73067..e832778fc603 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -62,8 +62,6 @@ static const struct i82860_dev_info i82860_devs[] = { static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code has already registered driver */ -static int i82860_registered = 1; - static void i82860_get_error_info (struct mem_ctl_info *mci, struct i82860_error_info *info) { @@ -265,24 +263,33 @@ static int __init i82860_init(void) debugf3("%s()\n", __func__); if ((pci_rc = pci_register_driver(&i82860_driver)) < 0) - return pci_rc; + goto fail0; if (!mci_pdev) { - i82860_registered = 0; mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82860_0, NULL); if (mci_pdev == NULL) { debugf0("860 pci_get_device fail\n"); - return -ENODEV; + pci_rc = -ENODEV; + goto fail1; } pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl); if (pci_rc < 0) { debugf0("860 init fail\n"); - pci_dev_put(mci_pdev); - return -ENODEV; + pci_rc = -ENODEV; + goto fail1; } } return 0; + +fail1: + pci_unregister_driver(&i82860_driver); + +fail0: + if (mci_pdev != NULL) + pci_dev_put(mci_pdev); + + return pci_rc; } static void __exit i82860_exit(void) @@ -290,10 +297,9 @@ static void __exit i82860_exit(void) debugf3("%s()\n", __func__); pci_unregister_driver(&i82860_driver); - if (!i82860_registered) { - i82860_remove_one(mci_pdev); + + if (mci_pdev != NULL) pci_dev_put(mci_pdev); - } } module_init(i82860_init); @@ -301,5 +307,5 @@ module_exit(i82860_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR - ("Red Hat Inc. (http://www.redhat.com.com) Ben Woodard "); + ("Red Hat Inc. (http://www.redhat.com) Ben Woodard "); MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers"); -- cgit v1.2.3-59-g8ed1b From 637beb697b8dc7b9d7a35c2b6488332e77963ded Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:44 -0800 Subject: [PATCH] EDAC: i82875p cleanup - Fix i82875p_probe1() so it calls pci_get_device() instead of pci_find_device(). - Fix i82875p_probe1() so it cleans up properly on failure. - Fix i82875p_init() so it cleans up properly on failure. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/i82875p_edac.c | 54 +++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index a547c30473e4..c521178183de 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -289,7 +289,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) debugf0("%s()\n", __func__); - ovrfl_pdev = pci_find_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); + ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); if (!ovrfl_pdev) { /* @@ -302,26 +302,26 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) ovrfl_pdev = pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0)); if (!ovrfl_pdev) - goto fail; + return -ENODEV; } #ifdef CONFIG_PROC_FS if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) { i82875p_printk(KERN_ERR, "%s(): Failed to attach overflow device\n", __func__); - goto fail; + return -ENODEV; } #endif /* CONFIG_PROC_FS */ if (pci_enable_device(ovrfl_pdev)) { i82875p_printk(KERN_ERR, "%s(): Failed to enable overflow device\n", __func__); - goto fail; + return -ENODEV; } if (pci_request_regions(ovrfl_pdev, pci_name(ovrfl_pdev))) { #ifdef CORRECT_BIOS - goto fail; + goto fail0; #endif } /* cache is irrelevant for PCI bus reads/writes */ @@ -331,7 +331,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) if (!ovrfl_window) { i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n", __func__); - goto fail; + goto fail1; } /* need to find out the number of channels */ @@ -345,7 +345,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) { rc = -ENOMEM; - goto fail; + goto fail2; } debugf3("%s(): init mci\n", __func__); @@ -402,25 +402,26 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) if (edac_mc_add_mc(mci)) { debugf3("%s(): failed edac_mc_add_mc()\n", __func__); - goto fail; + goto fail3; } /* get this far and it's successful */ debugf3("%s(): success\n", __func__); return 0; - fail: - if (mci) - edac_mc_free(mci); +fail3: + edac_mc_free(mci); - if (ovrfl_window) - iounmap(ovrfl_window); +fail2: + iounmap(ovrfl_window); - if (ovrfl_pdev) { - pci_release_regions(ovrfl_pdev); - pci_disable_device(ovrfl_pdev); - } +fail1: + pci_release_regions(ovrfl_pdev); +#ifdef CORRECT_BIOS +fail0: +#endif + pci_disable_device(ovrfl_pdev); /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */ return rc; } @@ -497,24 +498,33 @@ static int __init i82875p_init(void) debugf3("%s()\n", __func__); pci_rc = pci_register_driver(&i82875p_driver); if (pci_rc < 0) - return pci_rc; + goto fail0; if (mci_pdev == NULL) { - i82875p_registered = 0; mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_0, NULL); if (!mci_pdev) { debugf0("875p pci_get_device fail\n"); - return -ENODEV; + pci_rc = -ENODEV; + goto fail1; } pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl); if (pci_rc < 0) { debugf0("875p init fail\n"); - pci_dev_put(mci_pdev); - return -ENODEV; + pci_rc = -ENODEV; + goto fail1; } } return 0; + +fail1: + pci_unregister_driver(&i82875p_driver); + +fail0: + if (mci_pdev != NULL) + pci_dev_put(mci_pdev); + + return pci_rc; } -- cgit v1.2.3-59-g8ed1b From d38fde84f7521973fdfa5c3d03d62f014b42cd03 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:45 -0800 Subject: [PATCH] EDAC: e7xxx fix minor logic bug Fix minor logic bug in e7xxx_remove_one(). Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/e7xxx_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 8001797a6bc5..ec6eb77edaed 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -512,7 +512,7 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev) debugf0("%s()\n", __func__); if (((mci = edac_mc_find_mci_by_pdev(pdev)) != 0) && - edac_mc_del_mc(mci)) { + !edac_mc_del_mc(mci)) { pvt = (struct e7xxx_pvt *) mci->pvt_info; pci_dev_put(pvt->bridge_ck); edac_mc_free(mci); -- cgit v1.2.3-59-g8ed1b From 749ede57443b2a7ede2db105145f21047efcea6a Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:45 -0800 Subject: [PATCH] EDAC: cleanup code for clearing initial errors Fix xxx_probe1() functions so they call xxx_get_error_info() functions to clear initial errors. This is simpler and cleaner than duplicating the low-level code for accessing PCI config space. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/amd76x_edac.c | 5 ++--- drivers/edac/e752x_edac.c | 22 ++-------------------- drivers/edac/e7xxx_edac.c | 5 ++--- drivers/edac/edac_mc.c | 3 --- drivers/edac/i82860_edac.c | 4 ++-- drivers/edac/i82875p_edac.c | 4 ++-- drivers/edac/r82600_edac.c | 14 +++----------- 7 files changed, 13 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 6b7a441f0482..821c252d414c 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -211,6 +211,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) }; u32 ems; u32 ems_mode; + struct amd76x_error_info discard; debugf0("%s()\n", __func__); @@ -270,9 +271,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) csrow->edac_mode = ems_modes[ems_mode]; } - /* clear counters */ - pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, (u32) (0x3 << 8), - (u32) (0x3 << 8)); + amd76x_get_error_info(mci, &discard); /* clear counters */ if (edac_mc_add_mc(mci)) { debugf3("%s(): failed edac_mc_add_mc()\n", __func__); diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index f31725a55e54..24446542d8d6 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -747,8 +747,6 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) int rc = -ENODEV; int index; u16 pci_data; - u32 stat32; - u16 stat16; u8 stat8; struct mem_ctl_info *mci = NULL; struct e752x_pvt *pvt = NULL; @@ -760,6 +758,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) u32 dra; unsigned long last_cumul_size; struct pci_dev *dev = NULL; + struct e752x_error_info discard; debugf0("%s(): mci\n", __func__); debugf0("Starting Probe1\n"); @@ -938,24 +937,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00); pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00); /* clear other MCH errors */ - pci_read_config_dword(dev, E752X_FERR_GLOBAL, &stat32); - pci_write_config_dword(dev, E752X_FERR_GLOBAL, stat32); - pci_read_config_dword(dev, E752X_NERR_GLOBAL, &stat32); - pci_write_config_dword(dev, E752X_NERR_GLOBAL, stat32); - pci_read_config_byte(dev, E752X_HI_FERR, &stat8); - pci_write_config_byte(dev, E752X_HI_FERR, stat8); - pci_read_config_byte(dev, E752X_HI_NERR, &stat8); - pci_write_config_byte(dev, E752X_HI_NERR, stat8); - pci_read_config_dword(dev, E752X_SYSBUS_FERR, &stat32); - pci_write_config_dword(dev, E752X_SYSBUS_FERR, stat32); - pci_read_config_byte(dev, E752X_BUF_FERR, &stat8); - pci_write_config_byte(dev, E752X_BUF_FERR, stat8); - pci_read_config_byte(dev, E752X_BUF_NERR, &stat8); - pci_write_config_byte(dev, E752X_BUF_NERR, stat8); - pci_read_config_word(dev, E752X_DRAM_FERR, &stat16); - pci_write_config_word(dev, E752X_DRAM_FERR, stat16); - pci_read_config_word(dev, E752X_DRAM_NERR, &stat16); - pci_write_config_word(dev, E752X_DRAM_NERR, stat16); + e752x_get_error_info(mci, &discard); /* get this far and it's successful */ debugf3("%s(): success\n", __func__); diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index ec6eb77edaed..8b0da35ae47c 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -357,7 +357,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ u32 dra; unsigned long last_cumul_size; - + struct e7xxx_error_info discard; debugf0("%s(): mci\n", __func__); @@ -470,8 +470,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) pvt->tolm, pvt->remapbase, pvt->remaplimit); /* clear any pending errors, or initial state bits */ - pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03); - pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03); + e7xxx_get_error_info(mci, &discard); if (edac_mc_add_mc(mci) != 0) { debugf3("%s(): failed edac_mc_add_mc()\n", __func__); diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 499ac90ad67e..eac09cc86aac 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -2095,9 +2095,6 @@ static int __init edac_mc_init(void) */ clear_pci_parity_errors(); - /* perform check for first time to harvest boot leftovers */ - do_edac_check(); - /* Create the MC sysfs entires */ if (edac_sysfs_memctrl_setup()) { edac_printk(KERN_ERR, EDAC_MC, diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index e832778fc603..942129df0212 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -134,6 +134,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) int index; struct mem_ctl_info *mci = NULL; unsigned long last_cumul_size; + struct i82860_error_info discard; u16 mchcfg_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ @@ -200,8 +201,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE; } - /* clear counters */ - pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003); + i82860_get_error_info(mci, &discard); /* clear counters */ if (edac_mc_add_mc(mci)) { debugf3("%s(): failed edac_mc_add_mc()\n", __func__); diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index c521178183de..40ba2be6169a 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -286,6 +286,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) u32 drc_chan; /* Number of channels 0=1chan,1=2chan */ u32 nr_chans; u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ + struct i82875p_error_info discard; debugf0("%s()\n", __func__); @@ -397,8 +398,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE; } - /* clear counters */ - pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081); + i82875p_get_error_info(mci, &discard); /* clear counters */ if (edac_mc_add_mc(mci)) { debugf3("%s(): failed edac_mc_add_mc()\n", __func__); diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index ac1359828e78..787a7652c7ef 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -219,7 +219,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) u32 scrub_disabled; u32 sdram_refresh_rate; u32 row_high_limit_last = 0; - u32 eap_init_bits; + struct r82600_error_info discard; debugf0("%s()\n", __func__); @@ -311,8 +311,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) row_high_limit_last = row_high_limit; } - /* clear counters */ - /* FIXME should we? */ + r82600_get_error_info(mci, &discard); /* clear counters */ if (edac_mc_add_mc(mci)) { debugf3("%s(): failed edac_mc_add_mc()\n", __func__); @@ -321,19 +320,12 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) /* get this far and it's successful */ - /* Clear error flags to allow next error to be reported [p.62] */ - /* Test systems seem to always have the UE flag raised on boot */ - - eap_init_bits = BIT(0) & BIT(1); if (disable_hardware_scrub) { - eap_init_bits |= BIT(31); debugf3("%s(): Disabling Hardware Scrub (scrub on error)\n", __func__); + pci_write_bits32(mci->pdev, R82600_EAP, BIT(31), BIT(31)); } - pci_write_bits32(mci->pdev, R82600_EAP, eap_init_bits, - eap_init_bits); - debugf3("%s(): success\n", __func__); return 0; -- cgit v1.2.3-59-g8ed1b From a1d03fcc1399b1e23922bcc3af1772b128aa6e93 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:46 -0800 Subject: [PATCH] EDAC: edac_mc_add_mc fix [1/2] This is part 1 of a 2-part patch set. The code changes are split into two parts to make the patches more readable. Move complete_mc_list_del() and del_mc_from_global_list() so we can call del_mc_from_global_list() from edac_mc_add_mc() without forward declarations. Perhaps using forward declarations would be better? I'm doing things this way because the rest of the code is missing them. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/edac_mc.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index eac09cc86aac..226d4fdb15fd 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -1451,6 +1451,24 @@ static int add_mc_to_global_list (struct mem_ctl_info *mci) } +static void complete_mc_list_del (struct rcu_head *head) +{ + struct mem_ctl_info *mci; + + mci = container_of(head, struct mem_ctl_info, rcu); + INIT_LIST_HEAD(&mci->link); + complete(&mci->complete); +} + + +static void del_mc_from_global_list (struct mem_ctl_info *mci) +{ + list_del_rcu(&mci->link); + init_completion(&mci->complete); + call_rcu(&mci->rcu, complete_mc_list_del); + wait_for_completion(&mci->complete); +} + EXPORT_SYMBOL(edac_mc_add_mc); @@ -1511,24 +1529,6 @@ finish: } - -static void complete_mc_list_del (struct rcu_head *head) -{ - struct mem_ctl_info *mci; - - mci = container_of(head, struct mem_ctl_info, rcu); - INIT_LIST_HEAD(&mci->link); - complete(&mci->complete); -} - -static void del_mc_from_global_list (struct mem_ctl_info *mci) -{ - list_del_rcu(&mci->link); - init_completion(&mci->complete); - call_rcu(&mci->rcu, complete_mc_list_del); - wait_for_completion(&mci->complete); -} - EXPORT_SYMBOL(edac_mc_del_mc); /** -- cgit v1.2.3-59-g8ed1b From 028a7b6d3d9fa2cc41d76d45575345cca8d00a4c Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:47 -0800 Subject: [PATCH] EDAC: edac_mc_add_mc fix [2/2] This is part 2 of a 2-part patch set. Fix edac_mc_add_mc() so it cleans up properly if call to edac_create_sysfs_mci_device() fails. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/edac_mc.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 226d4fdb15fd..d37a4c4a3125 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -1484,8 +1484,6 @@ EXPORT_SYMBOL(edac_mc_add_mc); /* FIXME - should a warning be printed if no error detection? correction? */ int edac_mc_add_mc(struct mem_ctl_info *mci) { - int rc = 1; - debugf0("%s()\n", __func__); #ifdef CONFIG_EDAC_DEBUG if (edac_debug_level >= 3) @@ -1505,7 +1503,7 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) down(&mem_ctls_mutex); if (add_mc_to_global_list(mci)) - goto finish; + goto fail0; /* set load time so that error rate can be tracked */ mci->start_time = jiffies; @@ -1513,19 +1511,22 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) if (edac_create_sysfs_mci_device(mci)) { edac_mc_printk(mci, KERN_WARNING, "failed to create sysfs device\n"); - /* FIXME - should there be an error code and unwind? */ - goto finish; + goto fail1; } /* Report action taken */ edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: PCI %s\n", mci->mod_name, mci->ctl_name, pci_name(mci->pdev)); - rc = 0; + up(&mem_ctls_mutex); + return 0; -finish: +fail1: + del_mc_from_global_list(mci); + +fail0: up(&mem_ctls_mutex); - return rc; + return 1; } -- cgit v1.2.3-59-g8ed1b From 6e5a8748507dea83386d1d76c58aeaed1ff5a1ec Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:48 -0800 Subject: [PATCH] EDAC: kobject_init/kobject_put fixes - Remove calls to kobject_init(). These are unnecessary because kobject_register() calls kobject_init(). - Remove extra calls to kobject_put(). When we call kobject_unregister(), this releases our reference to the kobject. The extra calls to kobject_put() may cause the reference count to drop to 0 while a kobject is still in use. Signed-off-by: David S. Peterson Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/edac_mc.c | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index d37a4c4a3125..e6ecc7da38a5 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -278,8 +278,6 @@ static int edac_sysfs_memctrl_setup(void) if (!err) { /* Init the MC's kobject */ memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj)); - kobject_init(&edac_memctrl_kobj); - edac_memctrl_kobj.parent = &edac_class.kset.kobj; edac_memctrl_kobj.ktype = &ktype_memctrl; @@ -314,9 +312,6 @@ static void edac_sysfs_memctrl_teardown(void) /* Unregister the MC's kobject */ kobject_unregister(&edac_memctrl_kobj); - /* release the master edac mc kobject */ - kobject_put(&edac_memctrl_kobj); - /* Unregister the 'edac' object */ sysdev_class_unregister(&edac_class); #endif /* DISABLE_EDAC_SYSFS */ @@ -594,8 +589,6 @@ static int edac_sysfs_pci_setup(void) debugf1("%s()\n", __func__); memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj)); - - kobject_init(&edac_pci_kobj); edac_pci_kobj.parent = &edac_class.kset.kobj; edac_pci_kobj.ktype = &ktype_edac_pci; @@ -619,7 +612,6 @@ static void edac_sysfs_pci_teardown(void) debugf0("%s()\n", __func__); kobject_unregister(&edac_pci_kobj); - kobject_put(&edac_pci_kobj); #endif } @@ -829,7 +821,6 @@ static int edac_create_csrow_object(struct kobject *edac_mci_kobj, /* generate ..../edac/mc/mc/csrow */ - kobject_init(&csrow->kobj); csrow->kobj.parent = edac_mci_kobj; csrow->kobj.ktype = &ktype_csrow; @@ -1104,7 +1095,6 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) debugf0("%s() idx=%d\n", __func__, mci->mc_idx); memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj)); - kobject_init(edac_mci_kobj); /* set the name of the mc object */ err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx); @@ -1123,10 +1113,8 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) /* create a symlink for the device */ err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj, EDAC_DEVICE_SYMLINK); - if (err) { - kobject_unregister(edac_mci_kobj); - return err; - } + if (err) + goto fail0; /* Make directories for each CSROW object * under the mc kobject @@ -1139,7 +1127,7 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) if (csrow->nr_pages > 0) { err = edac_create_csrow_object(edac_mci_kobj,csrow,i); if (err) - goto fail; + goto fail1; } } @@ -1150,16 +1138,14 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) /* CSROW error: backout what has already been registered, */ -fail: +fail1: for ( i--; i >= 0; i--) { - if (csrow->nr_pages > 0) { + if (csrow->nr_pages > 0) kobject_unregister(&mci->csrows[i].kobj); - kobject_put(&mci->csrows[i].kobj); - } } +fail0: kobject_unregister(edac_mci_kobj); - kobject_put(edac_mci_kobj); return err; } @@ -1177,16 +1163,13 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) /* remove all csrow kobjects */ for (i = 0; i < mci->nr_csrows; i++) { - if (mci->csrows[i].nr_pages > 0) { + if (mci->csrows[i].nr_pages > 0) kobject_unregister(&mci->csrows[i].kobj); - kobject_put(&mci->csrows[i].kobj); - } } sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK); kobject_unregister(&mci->edac_mci_kobj); - kobject_put(&mci->edac_mci_kobj); #endif /* DISABLE_EDAC_SYSFS */ } -- cgit v1.2.3-59-g8ed1b From 472678ebd30d87cbe8d97562dcc0e46d1076040f Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:49 -0800 Subject: [PATCH] EDAC: kobject/sysfs fixes - After we unregister a kobject, wait for our kobject release method to call complete(). This causes us to wait until the kobject reference count reaches 0. Otherwise, a task accessing the EDAC sysfs interface can hold the reference count above 0 until after the EDAC module has been unloaded. When the reference count finally drops to 0, this will result in an attempt to call our release method inside the EDAC module after the module has already been unloaded. This isn't the best fix, since a process can get stuck sleeping forever uninterruptibly if the user does the following: rmmod my_module < /sys/my_sysfs/file I'll go back and implement a better fix later. However this should be ok for now. - Call edac_remove_sysfs_mci_device() from edac_mc_del_mc() rather than from edac_mc_free(). Since edac_mc_add_mc() calls edac_create_sysfs_mci_device(), edac_mc_del_mc() should call edac_remove_sysfs_mci_device(). Signed-off-by: David S. Peterson Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/edac_mc.c | 76 ++++++++++++++++++++++++++------------------------ drivers/edac/edac_mc.h | 9 ++---- 2 files changed, 42 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index e6ecc7da38a5..7ee9419234aa 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -139,6 +139,12 @@ static struct sysdev_class edac_class = { static struct kobject edac_memctrl_kobj; static struct kobject edac_pci_kobj; +/* We use these to wait for the reference counts on edac_memctrl_kobj and + * edac_pci_kobj to reach 0. + */ +static struct completion edac_memctrl_kobj_complete; +static struct completion edac_pci_kobj_complete; + /* * /sys/devices/system/edac/mc; * data structures and methods @@ -244,6 +250,7 @@ static struct memctrl_dev_attribute *memctrl_attr[] = { static void edac_memctrl_master_release(struct kobject *kobj) { debugf1("%s()\n", __func__); + complete(&edac_memctrl_kobj_complete); } static struct kobj_type ktype_memctrl = { @@ -309,8 +316,12 @@ static void edac_sysfs_memctrl_teardown(void) #ifndef DISABLE_EDAC_SYSFS debugf0("MC: " __FILE__ ": %s()\n", __func__); - /* Unregister the MC's kobject */ + /* Unregister the MC's kobject and wait for reference count to reach + * 0. + */ + init_completion(&edac_memctrl_kobj_complete); kobject_unregister(&edac_memctrl_kobj); + wait_for_completion(&edac_memctrl_kobj_complete); /* Unregister the 'edac' object */ sysdev_class_unregister(&edac_class); @@ -563,6 +574,7 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = { static void edac_pci_release(struct kobject *kobj) { debugf1("%s()\n", __func__); + complete(&edac_pci_kobj_complete); } static struct kobj_type ktype_edac_pci = { @@ -610,8 +622,9 @@ static void edac_sysfs_pci_teardown(void) { #ifndef DISABLE_EDAC_SYSFS debugf0("%s()\n", __func__); - + init_completion(&edac_pci_kobj_complete); kobject_unregister(&edac_pci_kobj); + wait_for_completion(&edac_pci_kobj_complete); #endif } @@ -800,7 +813,11 @@ static struct csrowdev_attribute *csrow_attr[] = { /* No memory to release */ static void edac_csrow_instance_release(struct kobject *kobj) { + struct csrow_info *cs; + debugf1("%s()\n", __func__); + cs = container_of(kobj, struct csrow_info, kobj); + complete(&cs->kobj_complete); } static struct kobj_type ktype_csrow = { @@ -1055,11 +1072,10 @@ static struct mcidev_attribute *mci_attr[] = { static void edac_mci_instance_release(struct kobject *kobj) { struct mem_ctl_info *mci; - mci = container_of(kobj,struct mem_ctl_info,edac_mci_kobj); - debugf0("%s() idx=%d calling kfree\n", __func__, mci->mc_idx); - - kfree(mci); + mci = to_mci(kobj); + debugf0("%s() idx=%d\n", __func__, mci->mc_idx); + complete(&mci->kobj_complete); } static struct kobj_type ktype_mci = { @@ -1131,21 +1147,23 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) } } - /* Mark this MCI instance as having sysfs entries */ - mci->sysfs_active = MCI_SYSFS_ACTIVE; - return 0; /* CSROW error: backout what has already been registered, */ fail1: for ( i--; i >= 0; i--) { - if (csrow->nr_pages > 0) + if (csrow->nr_pages > 0) { + init_completion(&csrow->kobj_complete); kobject_unregister(&mci->csrows[i].kobj); + wait_for_completion(&csrow->kobj_complete); + } } fail0: + init_completion(&mci->kobj_complete); kobject_unregister(edac_mci_kobj); + wait_for_completion(&mci->kobj_complete); return err; } @@ -1163,13 +1181,17 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) /* remove all csrow kobjects */ for (i = 0; i < mci->nr_csrows; i++) { - if (mci->csrows[i].nr_pages > 0) + if (mci->csrows[i].nr_pages > 0) { + init_completion(&mci->csrows[i].kobj_complete); kobject_unregister(&mci->csrows[i].kobj); + wait_for_completion(&mci->csrows[i].kobj_complete); + } } sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK); - + init_completion(&mci->kobj_complete); kobject_unregister(&mci->edac_mci_kobj); + wait_for_completion(&mci->kobj_complete); #endif /* DISABLE_EDAC_SYSFS */ } @@ -1342,31 +1364,10 @@ EXPORT_SYMBOL(edac_mc_free); /** * edac_mc_free: Free a previously allocated 'mci' structure * @mci: pointer to a struct mem_ctl_info structure - * - * Free up a previously allocated mci structure - * A MCI structure can be in 2 states after being allocated - * by edac_mc_alloc(). - * 1) Allocated in a MC driver's probe, but not yet committed - * 2) Allocated and committed, by a call to edac_mc_add_mc() - * edac_mc_add_mc() is the function that adds the sysfs entries - * thus, this free function must determine which state the 'mci' - * structure is in, then either free it directly or - * perform kobject cleanup by calling edac_remove_sysfs_mci_device(). - * - * VOID Return */ void edac_mc_free(struct mem_ctl_info *mci) { - /* only if sysfs entries for this mci instance exist - * do we remove them and defer the actual kfree via - * the kobject 'release()' callback. - * - * Otherwise, do a straight kfree now. - */ - if (mci->sysfs_active == MCI_SYSFS_ACTIVE) - edac_remove_sysfs_mci_device(mci); - else - kfree(mci); + kfree(mci); } @@ -1456,7 +1457,8 @@ static void del_mc_from_global_list (struct mem_ctl_info *mci) EXPORT_SYMBOL(edac_mc_add_mc); /** - * edac_mc_add_mc: Insert the 'mci' structure into the mci global list + * edac_mc_add_mc: Insert the 'mci' structure into the mci global list and + * create sysfs entries associated with mci structure * @mci: pointer to the mci structure to be added to the list * * Return: @@ -1516,7 +1518,8 @@ fail0: EXPORT_SYMBOL(edac_mc_del_mc); /** - * edac_mc_del_mc: Remove the specified mci structure from global list + * edac_mc_del_mc: Remove sysfs entries for specified mci structure and + * remove mci structure from global list * @mci: Pointer to struct mem_ctl_info structure * * Returns: @@ -1528,6 +1531,7 @@ int edac_mc_del_mc(struct mem_ctl_info *mci) int rc = 1; debugf0("MC%d: %s()\n", mci->mc_idx, __func__); + edac_remove_sysfs_mci_device(mci); down(&mem_ctls_mutex); del_mc_from_global_list(mci); edac_printk(KERN_INFO, EDAC_MC, diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h index 0bcc3797c753..c9c1590db721 100644 --- a/drivers/edac/edac_mc.h +++ b/drivers/edac/edac_mc.h @@ -185,11 +185,6 @@ enum scrub_type { #define SCRUB_FLAG_HW_PROG_SRC BIT(SCRUB_HW_PROG_SRC_CORR) #define SCRUB_FLAG_HW_TUN BIT(SCRUB_HW_TUNABLE) -enum mci_sysfs_status { - MCI_SYSFS_INACTIVE = 0, /* sysfs entries NOT registered */ - MCI_SYSFS_ACTIVE /* sysfs entries ARE registered */ -}; - /* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */ /* @@ -299,6 +294,7 @@ struct csrow_info { struct mem_ctl_info *mci; /* the parent */ struct kobject kobj; /* sysfs kobject for this csrow */ + struct completion kobj_complete; /* FIXME the number of CHANNELs might need to become dynamic */ u32 nr_channels; @@ -320,8 +316,6 @@ struct mem_ctl_info { unsigned long scrub_cap; /* chipset scrub capabilities */ enum scrub_type scrub_mode; /* current scrub mode */ - enum mci_sysfs_status sysfs_active; /* status of sysfs */ - /* pointer to edac checking routine */ void (*edac_check) (struct mem_ctl_info * mci); /* @@ -359,6 +353,7 @@ struct mem_ctl_info { /* edac sysfs device control */ struct kobject edac_mci_kobj; + struct completion kobj_complete; }; -- cgit v1.2.3-59-g8ed1b From 18dbc337af5d6efd30cb9291e74722c8ad134fd3 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:50 -0800 Subject: [PATCH] EDAC: protect memory controller list - Fix code so we always hold mem_ctls_mutex while we are stepping through the list of mem_ctl_info structures. Otherwise bad things may happen if one task is stepping through the list while another task is modifying it. We may eventually want to use reference counting to manage the mem_ctl_info structures. In the meantime we may as well fix this bug. - Don't disable interrupts while we are walking the list of mem_ctl_info structures in check_mc_devices(). This is unnecessary. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/amd76x_edac.c | 5 ++--- drivers/edac/e752x_edac.c | 5 +---- drivers/edac/e7xxx_edac.c | 12 ++++++------ drivers/edac/edac_mc.c | 40 ++++++++++++++++++---------------------- drivers/edac/edac_mc.h | 5 +---- drivers/edac/i82860_edac.c | 7 ++++--- drivers/edac/i82875p_edac.c | 5 +---- drivers/edac/r82600_edac.c | 7 ++++--- 8 files changed, 37 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 821c252d414c..87bd8b4d561f 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -314,10 +314,9 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev) debugf0("%s()\n", __func__); - if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) - return; - if (edac_mc_del_mc(mci)) + if ((mci = edac_mc_del_mc(pdev)) == NULL) return; + edac_mc_free(mci); } diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 24446542d8d6..c86db23d3af3 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -976,10 +976,7 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev) debugf0("%s()\n", __func__); - if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) - return; - - if (edac_mc_del_mc(mci)) + if ((mci = edac_mc_del_mc(pdev)) == NULL) return; pvt = (struct e752x_pvt *) mci->pvt_info; diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 8b0da35ae47c..9b59c661f45e 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -510,12 +510,12 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev) debugf0("%s()\n", __func__); - if (((mci = edac_mc_find_mci_by_pdev(pdev)) != 0) && - !edac_mc_del_mc(mci)) { - pvt = (struct e7xxx_pvt *) mci->pvt_info; - pci_dev_put(pvt->bridge_ck); - edac_mc_free(mci); - } + if ((mci = edac_mc_del_mc(pdev)) == NULL) + return; + + pvt = (struct e7xxx_pvt *) mci->pvt_info; + pci_dev_put(pvt->bridge_ck); + edac_mc_free(mci); } diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 7ee9419234aa..ad812a4f8c99 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -1370,11 +1370,7 @@ void edac_mc_free(struct mem_ctl_info *mci) kfree(mci); } - - -EXPORT_SYMBOL(edac_mc_find_mci_by_pdev); - -struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev *pdev) +static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev) { struct mem_ctl_info *mci; struct list_head *item; @@ -1401,7 +1397,7 @@ static int add_mc_to_global_list (struct mem_ctl_info *mci) mci->mc_idx = 0; insert_before = &mc_devices; } else { - if (edac_mc_find_mci_by_pdev(mci->pdev)) { + if (find_mci_by_pdev(mci->pdev)) { edac_printk(KERN_WARNING, EDAC_MC, "%s (%s) %s %s already assigned %d\n", mci->pdev->dev.bus_id, @@ -1520,27 +1516,29 @@ EXPORT_SYMBOL(edac_mc_del_mc); /** * edac_mc_del_mc: Remove sysfs entries for specified mci structure and * remove mci structure from global list - * @mci: Pointer to struct mem_ctl_info structure + * @pdev: Pointer to 'struct pci_dev' representing mci structure to remove. * - * Returns: - * 0 Success - * 1 Failure + * Return pointer to removed mci structure, or NULL if device not found. */ -int edac_mc_del_mc(struct mem_ctl_info *mci) +struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev) { - int rc = 1; + struct mem_ctl_info *mci; - debugf0("MC%d: %s()\n", mci->mc_idx, __func__); - edac_remove_sysfs_mci_device(mci); + debugf0("MC: %s()\n", __func__); down(&mem_ctls_mutex); + + if ((mci = find_mci_by_pdev(pdev)) == NULL) { + up(&mem_ctls_mutex); + return NULL; + } + + edac_remove_sysfs_mci_device(mci); del_mc_from_global_list(mci); + up(&mem_ctls_mutex); edac_printk(KERN_INFO, EDAC_MC, "Removed device %d for %s %s: PCI %s\n", mci->mc_idx, mci->mod_name, mci->ctl_name, pci_name(mci->pdev)); - rc = 0; - up(&mem_ctls_mutex); - - return rc; + return mci; } @@ -2018,14 +2016,12 @@ static inline void clear_pci_parity_errors(void) */ static inline void check_mc_devices (void) { - unsigned long flags; struct list_head *item; struct mem_ctl_info *mci; debugf3("%s()\n", __func__); - /* during poll, have interrupts off */ - local_irq_save(flags); + down(&mem_ctls_mutex); list_for_each(item, &mc_devices) { mci = list_entry(item, struct mem_ctl_info, link); @@ -2034,7 +2030,7 @@ static inline void check_mc_devices (void) mci->edac_check(mci); } - local_irq_restore(flags); + up(&mem_ctls_mutex); } diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h index c9c1590db721..2cec157aaeba 100644 --- a/drivers/edac/edac_mc.h +++ b/drivers/edac/edac_mc.h @@ -410,14 +410,11 @@ void edac_mc_dump_csrow(struct csrow_info *csrow); #endif /* CONFIG_EDAC_DEBUG */ extern int edac_mc_add_mc(struct mem_ctl_info *mci); -extern int edac_mc_del_mc(struct mem_ctl_info *mci); +extern struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev); extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page); -extern struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev - *pdev); - extern void edac_mc_scrub_block(unsigned long page, unsigned long offset, u32 size); diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 942129df0212..688854260a0e 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -237,9 +237,10 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev) debugf0("%s()\n", __func__); - mci = edac_mc_find_mci_by_pdev(pdev); - if ((mci != NULL) && (edac_mc_del_mc(mci) == 0)) - edac_mc_free(mci); + if ((mci = edac_mc_del_mc(pdev)) == NULL) + return; + + edac_mc_free(mci); } static const struct pci_device_id i82860_pci_tbl[] __devinitdata = { diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 40ba2be6169a..aad1900a4689 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -452,7 +452,7 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev) debugf0("%s()\n", __func__); - if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) + if ((mci = edac_mc_del_mc(pdev)) == NULL) return; pvt = (struct i82875p_pvt *) mci->pvt_info; @@ -467,9 +467,6 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev) pci_dev_put(pvt->ovrfl_pdev); } - if (edac_mc_del_mc(mci)) - return; - edac_mc_free(mci); } diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 787a7652c7ef..5966916d02bd 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -353,9 +353,10 @@ static void __devexit r82600_remove_one(struct pci_dev *pdev) debugf0("%s()\n", __func__); - if (((mci = edac_mc_find_mci_by_pdev(pdev)) != NULL) && - !edac_mc_del_mc(mci)) - edac_mc_free(mci); + if ((mci = edac_mc_del_mc(pdev)) == NULL) + return; + + edac_mc_free(mci); } -- cgit v1.2.3-59-g8ed1b From 39f1d8d38aa3f757889a09855b241b6a23e2cac5 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:50 -0800 Subject: [PATCH] EDAC: Kconfig dependency changes - Add x86 dependency in drivers/edac/Kconfig for all current platform-specific modules. - Add PCI dependency to Radisys 82600 driver Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/Kconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 52f3eb45d2b9..b582d0cdc24f 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -64,35 +64,35 @@ config EDAC_AMD76X config EDAC_E7XXX tristate "Intel e7xxx (e7205, e7500, e7501, e7505)" - depends on EDAC_MM_EDAC && PCI + depends on EDAC_MM_EDAC && PCI && X86_32 help Support for error detection and correction on the Intel E7205, E7500, E7501 and E7505 server chipsets. config EDAC_E752X tristate "Intel e752x (e7520, e7525, e7320)" - depends on EDAC_MM_EDAC && PCI + depends on EDAC_MM_EDAC && PCI && X86 help Support for error detection and correction on the Intel E7520, E7525, E7320 server chipsets. config EDAC_I82875P tristate "Intel 82875p (D82875P, E7210)" - depends on EDAC_MM_EDAC && PCI + depends on EDAC_MM_EDAC && PCI && X86_32 help Support for error detection and correction on the Intel DP82785P and E7210 server chipsets. config EDAC_I82860 tristate "Intel 82860" - depends on EDAC_MM_EDAC && PCI + depends on EDAC_MM_EDAC && PCI && X86_32 help Support for error detection and correction on the Intel 82860 chipset. config EDAC_R82600 tristate "Radisys 82600 embedded chipset" - depends on EDAC_MM_EDAC + depends on EDAC_MM_EDAC && PCI && X86_32 help Support for error detection and correction on the Radisys 82600 embedded chipset. -- cgit v1.2.3-59-g8ed1b From 54933dddc3e8ccd9db48966d8ada11951cb8a558 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:51 -0800 Subject: [PATCH] EDAC: reorder EXPORT_SYMBOL macros Fix EDAC code so EXPORT_SYMBOL comes after the function that is being exported. This is to maintain consistency with the rest of the kernel. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/edac_mc.c | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index ad812a4f8c99..f67a4d6f8974 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -1199,7 +1199,6 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) #ifdef CONFIG_EDAC_DEBUG -EXPORT_SYMBOL(edac_mc_dump_channel); void edac_mc_dump_channel(struct channel_info *chan) { @@ -1209,10 +1208,9 @@ void edac_mc_dump_channel(struct channel_info *chan) debugf4("\tchannel->label = '%s'\n", chan->label); debugf4("\tchannel->csrow = %p\n\n", chan->csrow); } +EXPORT_SYMBOL(edac_mc_dump_channel); -EXPORT_SYMBOL(edac_mc_dump_csrow); - void edac_mc_dump_csrow(struct csrow_info *csrow) { debugf4("\tcsrow = %p\n", csrow); @@ -1227,10 +1225,9 @@ void edac_mc_dump_csrow(struct csrow_info *csrow) debugf4("\tcsrow->channels = %p\n", csrow->channels); debugf4("\tcsrow->mci = %p\n\n", csrow->mci); } +EXPORT_SYMBOL(edac_mc_dump_csrow); -EXPORT_SYMBOL(edac_mc_dump_mci); - void edac_mc_dump_mci(struct mem_ctl_info *mci) { debugf3("\tmci = %p\n", mci); @@ -1245,6 +1242,7 @@ void edac_mc_dump_mci(struct mem_ctl_info *mci) mci->mod_name, mci->ctl_name); debugf3("\tpvt_info = %p\n\n", mci->pvt_info); } +EXPORT_SYMBOL(edac_mc_dump_mci); #endif /* CONFIG_EDAC_DEBUG */ @@ -1284,8 +1282,6 @@ static inline char * align_ptr (void *ptr, unsigned size) } -EXPORT_SYMBOL(edac_mc_alloc); - /** * edac_mc_alloc: Allocate a struct mem_ctl_info structure * @size_pvt: size of private storage needed @@ -1357,10 +1353,9 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, return mci; } +EXPORT_SYMBOL(edac_mc_alloc); -EXPORT_SYMBOL(edac_mc_free); - /** * edac_mc_free: Free a previously allocated 'mci' structure * @mci: pointer to a struct mem_ctl_info structure @@ -1369,6 +1364,7 @@ void edac_mc_free(struct mem_ctl_info *mci) { kfree(mci); } +EXPORT_SYMBOL(edac_mc_free); static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev) { @@ -1450,8 +1446,6 @@ static void del_mc_from_global_list (struct mem_ctl_info *mci) } -EXPORT_SYMBOL(edac_mc_add_mc); - /** * edac_mc_add_mc: Insert the 'mci' structure into the mci global list and * create sysfs entries associated with mci structure @@ -1509,10 +1503,9 @@ fail0: up(&mem_ctls_mutex); return 1; } +EXPORT_SYMBOL(edac_mc_add_mc); -EXPORT_SYMBOL(edac_mc_del_mc); - /** * edac_mc_del_mc: Remove sysfs entries for specified mci structure and * remove mci structure from global list @@ -1540,10 +1533,9 @@ struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev) mci->mod_name, mci->ctl_name, pci_name(mci->pdev)); return mci; } +EXPORT_SYMBOL(edac_mc_del_mc); -EXPORT_SYMBOL(edac_mc_scrub_block); - void edac_mc_scrub_block(unsigned long page, unsigned long offset, u32 size) { @@ -1574,11 +1566,10 @@ void edac_mc_scrub_block(unsigned long page, unsigned long offset, if (PageHighMem(pg)) local_irq_restore(flags); } +EXPORT_SYMBOL(edac_mc_scrub_block); /* FIXME - should return -1 */ -EXPORT_SYMBOL(edac_mc_find_csrow_by_page); - int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) { @@ -1615,10 +1606,9 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, return row; } +EXPORT_SYMBOL(edac_mc_find_csrow_by_page); -EXPORT_SYMBOL(edac_mc_handle_ce); - /* FIXME - setable log (warning/emerg) levels */ /* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */ void edac_mc_handle_ce(struct mem_ctl_info *mci, @@ -1681,10 +1671,9 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, mci->csrows[row].grain); } } +EXPORT_SYMBOL(edac_mc_handle_ce); -EXPORT_SYMBOL(edac_mc_handle_ce_no_info); - void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg) { @@ -1694,10 +1683,9 @@ void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, mci->ce_noinfo_count++; mci->ce_count++; } +EXPORT_SYMBOL(edac_mc_handle_ce_no_info); -EXPORT_SYMBOL(edac_mc_handle_ue); - void edac_mc_handle_ue(struct mem_ctl_info *mci, unsigned long page_frame_number, unsigned long offset_in_page, int row, @@ -1750,10 +1738,9 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci, mci->ue_count++; mci->csrows[row].ue_count++; } +EXPORT_SYMBOL(edac_mc_handle_ue); -EXPORT_SYMBOL(edac_mc_handle_ue_no_info); - void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) { @@ -1766,6 +1753,7 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, mci->ue_noinfo_count++; mci->ue_count++; } +EXPORT_SYMBOL(edac_mc_handle_ue_no_info); #ifdef CONFIG_PCI -- cgit v1.2.3-59-g8ed1b From e7ecd8910293564d357dbaf18eb179e06fa35fd0 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:52 -0800 Subject: [PATCH] EDAC: formatting cleanup Cosmetic indentation/formatting cleanup for EDAC code. Make sure we are using tabs rather than spaces to indent, etc. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/amd76x_edac.c | 91 +++++-------- drivers/edac/e752x_edac.c | 234 +++++++++++++++++-------------- drivers/edac/e7xxx_edac.c | 165 +++++++++++----------- drivers/edac/edac_mc.c | 325 ++++++++++++++++++++------------------------ drivers/edac/edac_mc.h | 96 ++++++------- drivers/edac/i82860_edac.c | 66 +++++---- drivers/edac/i82875p_edac.c | 112 +++++++-------- drivers/edac/r82600_edac.c | 71 ++++------ 8 files changed, 558 insertions(+), 602 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 87bd8b4d561f..53423ad6d4a3 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -12,33 +12,26 @@ * */ - #include #include #include - #include #include - #include - #include "edac_mc.h" - #define amd76x_printk(level, fmt, arg...) \ - edac_printk(level, "amd76x", fmt, ##arg) - + edac_printk(level, "amd76x", fmt, ##arg) #define amd76x_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "amd76x", fmt, ##arg) - + edac_mc_chipset_printk(mci, level, "amd76x", fmt, ##arg) #define AMD76X_NR_CSROWS 8 #define AMD76X_NR_CHANS 1 #define AMD76X_NR_DIMMS 4 - /* AMD 76x register addresses - device 0 function 0 - PCI bridge */ + #define AMD76X_ECC_MODE_STATUS 0x48 /* Mode and status of ECC (32b) * * 31:16 reserved @@ -50,6 +43,7 @@ * 7:4 UE cs row * 3:0 CE cs row */ + #define AMD76X_DRAM_MODE_STATUS 0x58 /* DRAM Mode and status (32b) * * 31:26 clock disable 5 - 0 @@ -64,6 +58,7 @@ * 15:8 reserved * 7:0 x4 mode enable 7 - 0 */ + #define AMD76X_MEM_BASE_ADDR 0xC0 /* Memory base address (8 x 32b) * * 31:23 chip-select base @@ -74,29 +69,28 @@ * 0 chip-select enable */ - struct amd76x_error_info { u32 ecc_mode_status; }; - enum amd76x_chips { AMD761 = 0, AMD762 }; - struct amd76x_dev_info { const char *ctl_name; }; - static const struct amd76x_dev_info amd76x_devs[] = { - [AMD761] = {.ctl_name = "AMD761"}, - [AMD762] = {.ctl_name = "AMD762"}, + [AMD761] = { + .ctl_name = "AMD761" + }, + [AMD762] = { + .ctl_name = "AMD762" + }, }; - /** * amd76x_get_error_info - fetch error information * @mci: Memory controller @@ -105,23 +99,21 @@ static const struct amd76x_dev_info amd76x_devs[] = { * Fetch and store the AMD76x ECC status. Clear pending status * on the chip so that further errors will be reported */ - -static void amd76x_get_error_info (struct mem_ctl_info *mci, - struct amd76x_error_info *info) +static void amd76x_get_error_info(struct mem_ctl_info *mci, + struct amd76x_error_info *info) { pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS, &info->ecc_mode_status); if (info->ecc_mode_status & BIT(8)) pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, - (u32) BIT(8), (u32) BIT(8)); + (u32) BIT(8), (u32) BIT(8)); if (info->ecc_mode_status & BIT(9)) pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, - (u32) BIT(9), (u32) BIT(9)); + (u32) BIT(9), (u32) BIT(9)); } - /** * amd76x_process_error_info - Error check * @mci: Memory controller @@ -132,8 +124,7 @@ static void amd76x_get_error_info (struct mem_ctl_info *mci, * A return of 1 indicates an error. Also if handle_errors is true * then attempt to handle and clean up after the error */ - -static int amd76x_process_error_info (struct mem_ctl_info *mci, +static int amd76x_process_error_info(struct mem_ctl_info *mci, struct amd76x_error_info *info, int handle_errors) { int error_found; @@ -149,9 +140,8 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci, if (handle_errors) { row = (info->ecc_mode_status >> 4) & 0xf; - edac_mc_handle_ue(mci, - mci->csrows[row].first_page, 0, row, - mci->ctl_name); + edac_mc_handle_ue(mci, mci->csrows[row].first_page, 0, + row, mci->ctl_name); } } @@ -163,11 +153,11 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci, if (handle_errors) { row = info->ecc_mode_status & 0xf; - edac_mc_handle_ce(mci, - mci->csrows[row].first_page, 0, 0, row, 0, - mci->ctl_name); + edac_mc_handle_ce(mci, mci->csrows[row].first_page, 0, + 0, row, 0, mci->ctl_name); } } + return error_found; } @@ -178,7 +168,6 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci, * Called by the poll handlers this function reads the status * from the controller and checks for errors. */ - static void amd76x_check(struct mem_ctl_info *mci) { struct amd76x_error_info info; @@ -187,7 +176,6 @@ static void amd76x_check(struct mem_ctl_info *mci) amd76x_process_error_info(mci, &info, 1); } - /** * amd76x_probe1 - Perform set up for detected device * @pdev; PCI device detected @@ -197,7 +185,6 @@ static void amd76x_check(struct mem_ctl_info *mci) * controller status reporting. We configure and set up the * memory controller reporting and claim the device. */ - static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) { int rc = -ENODEV; @@ -214,10 +201,8 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) struct amd76x_error_info discard; debugf0("%s()\n", __func__); - pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems); ems_mode = (ems >> 10) & 0x3; - mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS); if (mci == NULL) { @@ -226,14 +211,11 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) } debugf0("%s(): mci = %p\n", __func__, mci); - mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_RDDR; - mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; mci->edac_cap = ems_mode ? - (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE; - + (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE; mci->mod_name = EDAC_MOD_STR; mci->mod_ver = "$Revision: 1.4.2.5 $"; mci->ctl_name = amd76x_devs[dev_idx].ctl_name; @@ -249,18 +231,15 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) /* find the DRAM Chip Select Base address and mask */ pci_read_config_dword(mci->pdev, - AMD76X_MEM_BASE_ADDR + (index * 4), - &mba); + AMD76X_MEM_BASE_ADDR + (index * 4), &mba); if (!(mba & BIT(0))) continue; mba_base = mba & 0xff800000UL; mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL; - pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS, - &dms); - + &dms); csrow->first_page = mba_base >> PAGE_SHIFT; csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT; csrow->last_page = csrow->first_page + csrow->nr_pages - 1; @@ -290,7 +269,7 @@ fail: /* returns count (>= 0), or negative on error */ static int __devinit amd76x_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { debugf0("%s()\n", __func__); @@ -298,7 +277,6 @@ static int __devinit amd76x_init_one(struct pci_dev *pdev, return amd76x_probe1(pdev, ent->driver_data); } - /** * amd76x_remove_one - driver shutdown * @pdev: PCI device being handed back @@ -307,7 +285,6 @@ static int __devinit amd76x_init_one(struct pci_dev *pdev, * structure for the device then delete the mci and free the * resources. */ - static void __devexit amd76x_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -320,18 +297,22 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } - static const struct pci_device_id amd76x_pci_tbl[] __devinitdata = { - {PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - AMD762}, - {PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - AMD761}, - {0,} /* 0 terminated list. */ + { + PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + AMD762 + }, + { + PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + AMD761 + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl); - static struct pci_driver amd76x_driver = { .name = EDAC_MOD_STR, .probe = amd76x_init_one, diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index c86db23d3af3..265cce72497c 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -17,26 +17,19 @@ * */ - #include #include #include - #include #include - #include - #include "edac_mc.h" - #define e752x_printk(level, fmt, arg...) \ - edac_printk(level, "e752x", fmt, ##arg) - + edac_printk(level, "e752x", fmt, ##arg) #define e752x_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "e752x", fmt, ##arg) - + edac_mc_chipset_printk(mci, level, "e752x", fmt, ##arg) #ifndef PCI_DEVICE_ID_INTEL_7520_0 #define PCI_DEVICE_ID_INTEL_7520_0 0x3590 @@ -64,7 +57,6 @@ #define E752X_NR_CSROWS 8 /* number of csrows */ - /* E752X register addresses - device 0 function 0 */ #define E752X_DRB 0x60 /* DRAM row boundary register (8b) */ #define E752X_DRA 0x70 /* DRAM row attribute register (8b) */ @@ -164,7 +156,6 @@ enum e752x_chips { E7320 = 2 }; - struct e752x_pvt { struct pci_dev *bridge_ck; struct pci_dev *dev_d0f0; @@ -178,7 +169,6 @@ struct e752x_pvt { const struct e752x_dev_info *dev_info; }; - struct e752x_dev_info { u16 err_dev; u16 ctl_dev; @@ -207,22 +197,24 @@ struct e752x_error_info { static const struct e752x_dev_info e752x_devs[] = { [E7520] = { - .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR, - .ctl_dev = PCI_DEVICE_ID_INTEL_7520_0, - .ctl_name = "E7520"}, + .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR, + .ctl_dev = PCI_DEVICE_ID_INTEL_7520_0, + .ctl_name = "E7520" + }, [E7525] = { - .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR, - .ctl_dev = PCI_DEVICE_ID_INTEL_7525_0, - .ctl_name = "E7525"}, + .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR, + .ctl_dev = PCI_DEVICE_ID_INTEL_7525_0, + .ctl_name = "E7525" + }, [E7320] = { - .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR, - .ctl_dev = PCI_DEVICE_ID_INTEL_7320_0, - .ctl_name = "E7320"}, + .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR, + .ctl_dev = PCI_DEVICE_ID_INTEL_7320_0, + .ctl_name = "E7320" + }, }; - static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, - unsigned long page) + unsigned long page) { u32 remap; struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; @@ -231,17 +223,21 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, if (page < pvt->tolm) return page; + if ((page >= 0x100000) && (page < pvt->remapbase)) return page; + remap = (page - pvt->tolm) + pvt->remapbase; + if (remap < pvt->remaplimit) return remap; + e752x_printk(KERN_ERR, "Invalid page %lx - out of range\n", page); return pvt->tolm - 1; } static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, - u32 sec1_add, u16 sec1_syndrome) + u32 sec1_add, u16 sec1_syndrome) { u32 page; int row; @@ -259,34 +255,36 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, /* chip select are bits 14 & 13 */ row = ((page >> 1) & 3); e752x_printk(KERN_WARNING, - "Test row %d Table %d %d %d %d %d %d %d %d\n", - row, pvt->map[0], pvt->map[1], pvt->map[2], - pvt->map[3], pvt->map[4], pvt->map[5], - pvt->map[6], pvt->map[7]); + "Test row %d Table %d %d %d %d %d %d %d %d\n", row, + pvt->map[0], pvt->map[1], pvt->map[2], pvt->map[3], + pvt->map[4], pvt->map[5], pvt->map[6], pvt->map[7]); /* test for channel remapping */ for (i = 0; i < 8; i++) { if (pvt->map[i] == row) break; } + e752x_printk(KERN_WARNING, "Test computed row %d\n", i); + if (i < 8) row = i; else e752x_mc_printk(mci, KERN_WARNING, - "row %d not found in remap table\n", row); + "row %d not found in remap table\n", row); } else row = edac_mc_find_csrow_by_page(mci, page); + /* 0 = channel A, 1 = channel B */ channel = !(error_one & 1); if (!pvt->map_type) row = 7 - row; + edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel, - "e752x CE"); + "e752x CE"); } - static inline void process_ce(struct mem_ctl_info *mci, u16 error_one, u32 sec1_add, u16 sec1_syndrome, int *error_found, int handle_error) @@ -297,8 +295,8 @@ static inline void process_ce(struct mem_ctl_info *mci, u16 error_one, do_process_ce(mci, error_one, sec1_add, sec1_syndrome); } -static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add, - u32 scrb_add) +static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, + u32 ded_add, u32 scrb_add) { u32 error_2b, block_page; int row; @@ -308,25 +306,31 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add, if (error_one & 0x0202) { error_2b = ded_add; + /* convert to 4k address */ block_page = error_2b >> (PAGE_SHIFT - 4); + row = pvt->mc_symmetric ? - /* chip select are bits 14 & 13 */ - ((block_page >> 1) & 3) : - edac_mc_find_csrow_by_page(mci, block_page); + /* chip select are bits 14 & 13 */ + ((block_page >> 1) & 3) : + edac_mc_find_csrow_by_page(mci, block_page); + edac_mc_handle_ue(mci, block_page, 0, row, - "e752x UE from Read"); + "e752x UE from Read"); } if (error_one & 0x0404) { error_2b = scrb_add; + /* convert to 4k address */ block_page = error_2b >> (PAGE_SHIFT - 4); + row = pvt->mc_symmetric ? - /* chip select are bits 14 & 13 */ - ((block_page >> 1) & 3) : - edac_mc_find_csrow_by_page(mci, block_page); + /* chip select are bits 14 & 13 */ + ((block_page >> 1) & 3) : + edac_mc_find_csrow_by_page(mci, block_page); + edac_mc_handle_ue(mci, block_page, 0, row, - "e752x UE from Scruber"); + "e752x UE from Scruber"); } } @@ -359,13 +363,13 @@ static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error, struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; error_1b = retry_add; - page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */ + page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */ row = pvt->mc_symmetric ? - ((page >> 1) & 3) : /* chip select are bits 14 & 13 */ - edac_mc_find_csrow_by_page(mci, page); + ((page >> 1) & 3) : /* chip select are bits 14 & 13 */ + edac_mc_find_csrow_by_page(mci, page); e752x_mc_printk(mci, KERN_WARNING, - "CE page 0x%lx, row %d : Memory read retry\n", - (long unsigned int) page, row); + "CE page 0x%lx, row %d : Memory read retry\n", + (long unsigned int) page, row); } static inline void process_ded_retry(struct mem_ctl_info *mci, u16 error, @@ -402,7 +406,7 @@ static void do_global_error(int fatal, u32 errors) for (i = 0; i < 11; i++) { if (errors & (1 << i)) e752x_printk(KERN_WARNING, "%sError %s\n", - fatal_message[fatal], global_message[i]); + fatal_message[fatal], global_message[i]); } } @@ -429,7 +433,7 @@ static void do_hub_error(int fatal, u8 errors) for (i = 0; i < 7; i++) { if (errors & (1 << i)) e752x_printk(KERN_WARNING, "%sError %s\n", - fatal_message[fatal], hub_message[i]); + fatal_message[fatal], hub_message[i]); } } @@ -456,7 +460,7 @@ static void do_membuf_error(u8 errors) for (i = 0; i < 4; i++) { if (errors & (1 << i)) e752x_printk(KERN_WARNING, "Non-Fatal Error %s\n", - membuf_message[i]); + membuf_message[i]); } } @@ -489,7 +493,7 @@ static void do_sysbus_error(int fatal, u32 errors) for (i = 0; i < 10; i++) { if (errors & (1 << i)) e752x_printk(KERN_WARNING, "%sError System Bus %s\n", - fatal_message[fatal], global_message[i]); + fatal_message[fatal], global_message[i]); } } @@ -502,33 +506,42 @@ static inline void sysbus_error(int fatal, u32 errors, int *error_found, do_sysbus_error(fatal, errors); } -static void e752x_check_hub_interface (struct e752x_error_info *info, +static void e752x_check_hub_interface(struct e752x_error_info *info, int *error_found, int handle_error) { u8 stat8; //pci_read_config_byte(dev,E752X_HI_FERR,&stat8); + stat8 = info->hi_ferr; + if(stat8 & 0x7f) { /* Error, so process */ stat8 &= 0x7f; + if(stat8 & 0x2b) hub_error(1, stat8 & 0x2b, error_found, handle_error); + if(stat8 & 0x54) hub_error(0, stat8 & 0x54, error_found, handle_error); } + //pci_read_config_byte(dev,E752X_HI_NERR,&stat8); + stat8 = info->hi_nerr; + if(stat8 & 0x7f) { /* Error, so process */ stat8 &= 0x7f; + if (stat8 & 0x2b) hub_error(1, stat8 & 0x2b, error_found, handle_error); + if(stat8 & 0x54) hub_error(0, stat8 & 0x54, error_found, handle_error); } } -static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found, - int handle_error) +static void e752x_check_sysbus(struct e752x_error_info *info, + int *error_found, int handle_error) { u32 stat32, error32; @@ -540,27 +553,34 @@ static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found, error32 = (stat32 >> 16) & 0x3ff; stat32 = stat32 & 0x3ff; + if(stat32 & 0x083) sysbus_error(1, stat32 & 0x083, error_found, handle_error); + if(stat32 & 0x37c) sysbus_error(0, stat32 & 0x37c, error_found, handle_error); + if(error32 & 0x083) sysbus_error(1, error32 & 0x083, error_found, handle_error); + if(error32 & 0x37c) sysbus_error(0, error32 & 0x37c, error_found, handle_error); } -static void e752x_check_membuf (struct e752x_error_info *info, int *error_found, - int handle_error) +static void e752x_check_membuf (struct e752x_error_info *info, + int *error_found, int handle_error) { u8 stat8; stat8 = info->buf_ferr; + if (stat8 & 0x0f) { /* Error, so process */ stat8 &= 0x0f; membuf_error(stat8, error_found, handle_error); } + stat8 = info->buf_nerr; + if (stat8 & 0x0f) { /* Error, so process */ stat8 &= 0x0f; membuf_error(stat8, error_found, handle_error); @@ -568,7 +588,8 @@ static void e752x_check_membuf (struct e752x_error_info *info, int *error_found, } static void e752x_check_dram (struct mem_ctl_info *mci, - struct e752x_error_info *info, int *error_found, int handle_error) + struct e752x_error_info *info, int *error_found, + int handle_error) { u16 error_one, error_next; @@ -618,7 +639,7 @@ static void e752x_check_dram (struct mem_ctl_info *mci, } static void e752x_get_error_info (struct mem_ctl_info *mci, - struct e752x_error_info *info) + struct e752x_error_info *info) { struct pci_dev *dev; struct e752x_pvt *pvt; @@ -626,7 +647,6 @@ static void e752x_get_error_info (struct mem_ctl_info *mci, memset(info, 0, sizeof(*info)); pvt = (struct e752x_pvt *) mci->pvt_info; dev = pvt->dev_d0f1; - pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global); if (info->ferr_global) { @@ -737,6 +757,7 @@ static int e752x_process_error_info (struct mem_ctl_info *mci, static void e752x_check(struct mem_ctl_info *mci) { struct e752x_error_info info; + debugf3("%s()\n", __func__); e752x_get_error_info(mci, &info); e752x_process_error_info(mci, &info, 1); @@ -752,9 +773,9 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) struct e752x_pvt *pvt = NULL; u16 ddrcsr; u32 drc; - int drc_chan; /* Number of channels 0=1chan,1=2chan */ - int drc_drbg; /* DRB granularity 0=64mb,1=128mb */ - int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ + int drc_chan; /* Number of channels 0=1chan,1=2chan */ + int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */ + int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ u32 dra; unsigned long last_cumul_size; struct pci_dev *dev = NULL; @@ -785,7 +806,6 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) } debugf3("%s(): init mci\n", __func__); - mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED; @@ -798,19 +818,21 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pvt = (struct e752x_pvt *) mci->pvt_info; pvt->dev_info = &e752x_devs[dev_idx]; pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, - pvt->dev_info->err_dev, - pvt->bridge_ck); + pvt->dev_info->err_dev, + pvt->bridge_ck); + if (pvt->bridge_ck == NULL) pvt->bridge_ck = pci_scan_single_device(pdev->bus, - PCI_DEVFN(0, 1)); + PCI_DEVFN(0, 1)); + if (pvt->bridge_ck == NULL) { e752x_printk(KERN_ERR, "error reporting device not found:" - "vendor %x device 0x%x (broken BIOS?)\n", - PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev); + "vendor %x device 0x%x (broken BIOS?)\n", + PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev); goto fail; } - pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); + pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); debugf3("%s(): more mci init\n", __func__); mci->ctl_name = pvt->dev_info->ctl_name; mci->edac_check = e752x_check; @@ -828,6 +850,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { u8 value; u32 cumul_size; + /* mem_dev 0=x8, 1=x4 */ int mem_dev = (dra >> (index * 4 + 2)) & 0x3; struct csrow_info *csrow = &mci->csrows[index]; @@ -838,15 +861,16 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, cumul_size); + if (cumul_size == last_cumul_size) - continue; /* not populated */ + continue; /* not populated */ csrow->first_page = last_cumul_size; csrow->last_page = cumul_size - 1; csrow->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; - csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ - csrow->mtype = MEM_RDDR; /* only one type supported */ + csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ + csrow->mtype = MEM_RDDR; /* only one type supported */ csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; /* @@ -870,29 +894,32 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) u8 value; u8 last = 0; u8 row = 0; - for (index = 0; index < 8; index += 2) { + for (index = 0; index < 8; index += 2) { pci_read_config_byte(mci->pdev, E752X_DRB + index, - &value); + &value); + /* test if there is a dimm in this slot */ if (value == last) { /* no dimm in the slot, so flag it as empty */ pvt->map[index] = 0xff; pvt->map[index + 1] = 0xff; - } else { /* there is a dimm in the slot */ + } else { /* there is a dimm in the slot */ pvt->map[index] = row; row++; last = value; /* test the next value to see if the dimm is double sided */ pci_read_config_byte(mci->pdev, - E752X_DRB + index + 1, - &value); + E752X_DRB + index + 1, + &value); pvt->map[index + 1] = (value == last) ? - 0xff : /* the dimm is single sided, - so flag as empty */ - row; /* this is a double sided dimm - to save the next row # */ + 0xff : /* the dimm is single sided, + * so flag as empty + */ + row; /* this is a double sided dimm + * to save the next row # + */ row++; last = value; } @@ -904,8 +931,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f)); mci->edac_cap |= EDAC_FLAG_NONE; - debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); + /* load the top of low memory, remap base, and remap limit vars */ pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data); pvt->tolm = ((u32) pci_data) << 4; @@ -914,8 +941,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data); pvt->remaplimit = ((u32) pci_data) << 14; e752x_printk(KERN_INFO, - "tolm = %x, remapbase = %x, remaplimit = %x\n", - pvt->tolm, pvt->remapbase, pvt->remaplimit); + "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, + pvt->remapbase, pvt->remaplimit); if (edac_mc_add_mc(mci)) { debugf3("%s(): failed edac_mc_add_mc()\n", __func__); @@ -923,7 +950,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) } dev = pci_get_device(PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].ctl_dev, - NULL); + NULL); pvt->dev_d0f0 = dev; /* find the error reporting device and clear errors */ dev = pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck); @@ -936,8 +963,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00); pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00); pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00); - /* clear other MCH errors */ - e752x_get_error_info(mci, &discard); + + e752x_get_error_info(mci, &discard); /* clear other MCH errors */ /* get this far and it's successful */ debugf3("%s(): success\n", __func__); @@ -947,28 +974,32 @@ fail: if (mci) { if (pvt->dev_d0f0) pci_dev_put(pvt->dev_d0f0); + if (pvt->dev_d0f1) pci_dev_put(pvt->dev_d0f1); + if (pvt->bridge_ck) pci_dev_put(pvt->bridge_ck); + edac_mc_free(mci); } + return rc; } /* returns count (>= 0), or negative on error */ static int __devinit e752x_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { debugf0("%s()\n", __func__); /* wake up and enable device */ if(pci_enable_device(pdev) < 0) return -EIO; + return e752x_probe1(pdev, ent->driver_data); } - static void __devexit e752x_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -986,20 +1017,26 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } - static const struct pci_device_id e752x_pci_tbl[] __devinitdata = { - {PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7520}, - {PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7525}, - {PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7320}, - {0,} /* 0 terminated list. */ + { + PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7520 + }, + { + PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7525 + }, + { + PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7320 + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, e752x_pci_tbl); - static struct pci_driver e752x_driver = { .name = EDAC_MOD_STR, .probe = e752x_init_one, @@ -1007,7 +1044,6 @@ static struct pci_driver e752x_driver = { .id_table = e752x_pci_tbl, }; - static int __init e752x_init(void) { int pci_rc; @@ -1017,14 +1053,12 @@ static int __init e752x_init(void) return (pci_rc < 0) ? pci_rc : 0; } - static void __exit e752x_exit(void) { debugf3("%s()\n", __func__); pci_unregister_driver(&e752x_driver); } - module_init(e752x_init); module_exit(e752x_exit); diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 9b59c661f45e..a9518d3e4be4 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -11,9 +11,9 @@ * http://www.anime.net/~goemon/linux-ecc/ * * Contributors: - * Eric Biederman (Linux Networx) - * Tom Zimmerman (Linux Networx) - * Jim Garlick (Lawrence Livermore National Labs) + * Eric Biederman (Linux Networx) + * Tom Zimmerman (Linux Networx) + * Jim Garlick (Lawrence Livermore National Labs) * Dave Peterson (Lawrence Livermore National Labs) * That One Guy (Some other place) * Wang Zhenyu (intel.com) @@ -22,7 +22,6 @@ * */ - #include #include #include @@ -31,14 +30,11 @@ #include #include "edac_mc.h" - #define e7xxx_printk(level, fmt, arg...) \ - edac_printk(level, "e7xxx", fmt, ##arg) - + edac_printk(level, "e7xxx", fmt, ##arg) #define e7xxx_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "e7xxx", fmt, ##arg) - + edac_mc_chipset_printk(mci, level, "e7xxx", fmt, ##arg) #ifndef PCI_DEVICE_ID_INTEL_7205_0 #define PCI_DEVICE_ID_INTEL_7205_0 0x255d @@ -72,11 +68,9 @@ #define PCI_DEVICE_ID_INTEL_7505_1_ERR 0x2551 #endif /* PCI_DEVICE_ID_INTEL_7505_1_ERR */ - #define E7XXX_NR_CSROWS 8 /* number of csrows */ #define E7XXX_NR_DIMMS 8 /* FIXME - is this correct? */ - /* E7XXX register addresses - device 0 function 0 */ #define E7XXX_DRB 0x60 /* DRAM row boundary register (8b) */ #define E7XXX_DRA 0x70 /* DRAM row attribute register (8b) */ @@ -126,7 +120,6 @@ enum e7xxx_chips { E7205, }; - struct e7xxx_pvt { struct pci_dev *bridge_ck; u32 tolm; @@ -135,13 +128,11 @@ struct e7xxx_pvt { const struct e7xxx_dev_info *dev_info; }; - struct e7xxx_dev_info { u16 err_dev; const char *ctl_name; }; - struct e7xxx_error_info { u8 dram_ferr; u8 dram_nerr; @@ -152,20 +143,23 @@ struct e7xxx_error_info { static const struct e7xxx_dev_info e7xxx_devs[] = { [E7500] = { - .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR, - .ctl_name = "E7500"}, + .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR, + .ctl_name = "E7500" + }, [E7501] = { - .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR, - .ctl_name = "E7501"}, + .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR, + .ctl_name = "E7501" + }, [E7505] = { - .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR, - .ctl_name = "E7505"}, + .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR, + .ctl_name = "E7505" + }, [E7205] = { - .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR, - .ctl_name = "E7205"}, + .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR, + .ctl_name = "E7205" + }, }; - /* FIXME - is this valid for both SECDED and S4ECD4ED? */ static inline int e7xxx_find_channel(u16 syndrome) { @@ -173,16 +167,18 @@ static inline int e7xxx_find_channel(u16 syndrome) if ((syndrome & 0xff00) == 0) return 0; + if ((syndrome & 0x00ff) == 0) return 1; + if ((syndrome & 0xf000) == 0 || (syndrome & 0x0f00) == 0) return 0; + return 1; } - -static unsigned long -ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page) +static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, + unsigned long page) { u32 remap; struct e7xxx_pvt *pvt = (struct e7xxx_pvt *) mci->pvt_info; @@ -190,17 +186,20 @@ ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page) debugf3("%s()\n", __func__); if ((page < pvt->tolm) || - ((page >= 0x100000) && (page < pvt->remapbase))) + ((page >= 0x100000) && (page < pvt->remapbase))) return page; + remap = (page - pvt->tolm) + pvt->remapbase; + if (remap < pvt->remaplimit) return remap; + e7xxx_printk(KERN_ERR, "Invalid page %lx - out of range\n", page); return pvt->tolm - 1; } - -static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) +static void process_ce(struct mem_ctl_info *mci, + struct e7xxx_error_info *info) { u32 error_1b, page; u16 syndrome; @@ -208,52 +207,46 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) int channel; debugf3("%s()\n", __func__); - /* read the error address */ error_1b = info->dram_celog_add; /* FIXME - should use PAGE_SHIFT */ - page = error_1b >> 6; /* convert the address to 4k page */ + page = error_1b >> 6; /* convert the address to 4k page */ /* read the syndrome */ syndrome = info->dram_celog_syndrome; /* FIXME - check for -1 */ row = edac_mc_find_csrow_by_page(mci, page); /* convert syndrome to channel */ channel = e7xxx_find_channel(syndrome); - edac_mc_handle_ce(mci, page, 0, syndrome, row, channel, - "e7xxx CE"); + edac_mc_handle_ce(mci, page, 0, syndrome, row, channel, "e7xxx CE"); } - static void process_ce_no_info(struct mem_ctl_info *mci) { debugf3("%s()\n", __func__); edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow"); } - -static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) +static void process_ue(struct mem_ctl_info *mci, + struct e7xxx_error_info *info) { u32 error_2b, block_page; int row; debugf3("%s()\n", __func__); - /* read the error address */ error_2b = info->dram_uelog_add; /* FIXME - should use PAGE_SHIFT */ - block_page = error_2b >> 6; /* convert to 4k address */ + block_page = error_2b >> 6; /* convert to 4k address */ row = edac_mc_find_csrow_by_page(mci, block_page); edac_mc_handle_ue(mci, block_page, 0, row, "e7xxx UE"); } - static void process_ue_no_info(struct mem_ctl_info *mci) { debugf3("%s()\n", __func__); edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow"); } - static void e7xxx_get_error_info (struct mem_ctl_info *mci, struct e7xxx_error_info *info) { @@ -261,31 +254,29 @@ static void e7xxx_get_error_info (struct mem_ctl_info *mci, pvt = (struct e7xxx_pvt *) mci->pvt_info; pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_FERR, - &info->dram_ferr); + &info->dram_ferr); pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_NERR, - &info->dram_nerr); + &info->dram_nerr); if ((info->dram_ferr & 1) || (info->dram_nerr & 1)) { pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_CELOG_ADD, - &info->dram_celog_add); + &info->dram_celog_add); pci_read_config_word(pvt->bridge_ck, - E7XXX_DRAM_CELOG_SYNDROME, &info->dram_celog_syndrome); + E7XXX_DRAM_CELOG_SYNDROME, + &info->dram_celog_syndrome); } if ((info->dram_ferr & 2) || (info->dram_nerr & 2)) pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_UELOG_ADD, - &info->dram_uelog_add); + &info->dram_uelog_add); if (info->dram_ferr & 3) - pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, - 0x03); + pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03); if (info->dram_nerr & 3) - pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, - 0x03); + pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03); } - static int e7xxx_process_error_info (struct mem_ctl_info *mci, struct e7xxx_error_info *info, int handle_errors) { @@ -333,7 +324,6 @@ static int e7xxx_process_error_info (struct mem_ctl_info *mci, return error_found; } - static void e7xxx_check(struct mem_ctl_info *mci) { struct e7xxx_error_info info; @@ -343,7 +333,6 @@ static void e7xxx_check(struct mem_ctl_info *mci) e7xxx_process_error_info(mci, &info, 1); } - static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) { int rc = -ENODEV; @@ -363,13 +352,14 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) /* need to find out the number of channels */ pci_read_config_dword(pdev, E7XXX_DRC, &drc); + /* only e7501 can be single channel */ if (dev_idx == E7501) { drc_chan = ((drc >> 22) & 0x1); drc_drbg = (drc >> 18) & 0x3; } - drc_ddim = (drc >> 20) & 0x3; + drc_ddim = (drc >> 20) & 0x3; mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1); if (mci == NULL) { @@ -378,10 +368,9 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) } debugf3("%s(): init mci\n", __func__); - mci->mtype_cap = MEM_FLAG_RDDR; - mci->edac_ctl_cap = - EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED; + mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | + EDAC_FLAG_S4ECD4ED; /* FIXME - what if different memory types are in different csrows? */ mci->mod_name = EDAC_MOD_STR; mci->mod_ver = "$Revision: 1.5.2.9 $"; @@ -391,19 +380,18 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) pvt = (struct e7xxx_pvt *) mci->pvt_info; pvt->dev_info = &e7xxx_devs[dev_idx]; pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, - pvt->dev_info->err_dev, - pvt->bridge_ck); + pvt->dev_info->err_dev, + pvt->bridge_ck); + if (!pvt->bridge_ck) { e7xxx_printk(KERN_ERR, "error reporting device not found:" - "vendor %x device 0x%x (broken BIOS?)\n", - PCI_VENDOR_ID_INTEL, - e7xxx_devs[dev_idx].err_dev); + "vendor %x device 0x%x (broken BIOS?)\n", + PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev); goto fail; } debugf3("%s(): more mci init\n", __func__); mci->ctl_name = pvt->dev_info->ctl_name; - mci->edac_check = e7xxx_check; mci->ctl_page_to_phys = ctl_page_to_phys; @@ -428,15 +416,16 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, cumul_size); + if (cumul_size == last_cumul_size) - continue; /* not populated */ + continue; /* not populated */ csrow->first_page = last_cumul_size; csrow->last_page = cumul_size - 1; csrow->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; - csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ - csrow->mtype = MEM_RDDR; /* only one type supported */ + csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ + csrow->mtype = MEM_RDDR; /* only one type supported */ csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; /* @@ -466,8 +455,8 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data); pvt->remaplimit = ((u32) pci_data) << 14; e7xxx_printk(KERN_INFO, - "tolm = %x, remapbase = %x, remaplimit = %x\n", - pvt->tolm, pvt->remapbase, pvt->remaplimit); + "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, + pvt->remapbase, pvt->remaplimit); /* clear any pending errors, or initial state bits */ e7xxx_get_error_info(mci, &discard); @@ -492,17 +481,16 @@ fail: } /* returns count (>= 0), or negative on error */ -static int __devinit -e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit e7xxx_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { debugf0("%s()\n", __func__); /* wake up and enable device */ return pci_enable_device(pdev) ? - -EIO : e7xxx_probe1(pdev, ent->driver_data); + -EIO : e7xxx_probe1(pdev, ent->driver_data); } - static void __devexit e7xxx_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -518,22 +506,30 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } - static const struct pci_device_id e7xxx_pci_tbl[] __devinitdata = { - {PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7205}, - {PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7500}, - {PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7501}, - {PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7505}, - {0,} /* 0 terminated list. */ + { + PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7205 + }, + { + PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7500 + }, + { + PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7501 + }, + { + PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7505 + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl); - static struct pci_driver e7xxx_driver = { .name = EDAC_MOD_STR, .probe = e7xxx_init_one, @@ -541,13 +537,11 @@ static struct pci_driver e7xxx_driver = { .id_table = e7xxx_pci_tbl, }; - static int __init e7xxx_init(void) { return pci_register_driver(&e7xxx_driver); } - static void __exit e7xxx_exit(void) { pci_unregister_driver(&e7xxx_driver); @@ -556,8 +550,7 @@ static void __exit e7xxx_exit(void) module_init(e7xxx_init); module_exit(e7xxx_exit); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n" - "Based on.work by Dan Hollis et al"); + "Based on.work by Dan Hollis et al"); MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers"); diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index f67a4d6f8974..bb3460457fa3 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -12,7 +12,6 @@ * */ - #include #include #include @@ -30,14 +29,12 @@ #include #include #include - #include #include #include - #include "edac_mc.h" -#define EDAC_MC_VERSION "Ver: 2.0.0 " __DATE__ +#define EDAC_MC_VERSION "Ver: 2.0.0 " __DATE__ /* For now, disable the EDAC sysfs code. The sysfs interface that EDAC * presents to user space needs more thought, and is likely to change @@ -73,7 +70,6 @@ struct edac_pci_device_list { unsigned int device; /* Deviice ID */ }; - #define MAX_LISTED_PCI_DEVICES 32 /* List of PCI devices (vendor-id:device-id) that should be skipped */ @@ -126,7 +122,6 @@ static const char *edac_caps[] = { [EDAC_S16ECD16ED] = "S16ECD16ED" }; - /* sysfs object: /sys/devices/system/edac */ static struct sysdev_class edac_class = { set_kset_name("edac"), @@ -147,7 +142,7 @@ static struct completion edac_pci_kobj_complete; /* * /sys/devices/system/edac/mc; - * data structures and methods + * data structures and methods */ #if 0 static ssize_t memctrl_string_show(void *ptr, char *buffer) @@ -174,33 +169,34 @@ static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count) } struct memctrl_dev_attribute { - struct attribute attr; - void *value; + struct attribute attr; + void *value; ssize_t (*show)(void *,char *); ssize_t (*store)(void *, const char *, size_t); }; /* Set of show/store abstract level functions for memory control object */ -static ssize_t -memctrl_dev_show(struct kobject *kobj, struct attribute *attr, char *buffer) +static ssize_t memctrl_dev_show(struct kobject *kobj, + struct attribute *attr, char *buffer) { struct memctrl_dev_attribute *memctrl_dev; memctrl_dev = (struct memctrl_dev_attribute*)attr; if (memctrl_dev->show) return memctrl_dev->show(memctrl_dev->value, buffer); + return -EIO; } -static ssize_t -memctrl_dev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) +static ssize_t memctrl_dev_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) { struct memctrl_dev_attribute *memctrl_dev; memctrl_dev = (struct memctrl_dev_attribute*)attr; if (memctrl_dev->store) return memctrl_dev->store(memctrl_dev->value, buffer, count); + return -EIO; } @@ -236,7 +232,6 @@ MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); MEMCTRL_ATTR(log_ce,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); MEMCTRL_ATTR(poll_msec,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); - /* Base Attributes of the memory ECC object */ static struct memctrl_dev_attribute *memctrl_attr[] = { &attr_panic_on_ue, @@ -254,9 +249,9 @@ static void edac_memctrl_master_release(struct kobject *kobj) } static struct kobj_type ktype_memctrl = { - .release = edac_memctrl_master_release, - .sysfs_ops = &memctrlfs_ops, - .default_attrs = (struct attribute **) memctrl_attr, + .release = edac_memctrl_master_release, + .sysfs_ops = &memctrlfs_ops, + .default_attrs = (struct attribute **) memctrl_attr, }; #endif /* DISABLE_EDAC_SYSFS */ @@ -282,6 +277,7 @@ static int edac_sysfs_memctrl_setup(void) /* create the /sys/devices/system/edac directory */ err = sysdev_class_register(&edac_class); + if (!err) { /* Init the MC's kobject */ memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj)); @@ -290,18 +286,18 @@ static int edac_sysfs_memctrl_setup(void) /* generate sysfs "..../edac/mc" */ err = kobject_set_name(&edac_memctrl_kobj,"mc"); + if (!err) { /* FIXME: maybe new sysdev_create_subdir() */ err = kobject_register(&edac_memctrl_kobj); - if (err) { + + if (err) debugf1("Failed to register '.../edac/mc'\n"); - } else { + else debugf1("Registered '.../edac/mc' kobject\n"); - } } - } else { + } else debugf1("%s() error=%d\n", __func__, err); - } return err; } @@ -340,7 +336,6 @@ struct list_control { int *count; }; - #if 0 /* Output the list as: vendor_id:device:id<,vendor_id:device_id> */ static ssize_t edac_pci_list_string_show(void *ptr, char *buffer) @@ -365,7 +360,6 @@ static ssize_t edac_pci_list_string_show(void *ptr, char *buffer) } len += snprintf(p + len,(PAGE_SIZE-len), "\n"); - return (ssize_t) len; } @@ -387,7 +381,7 @@ static int parse_one_device(const char **s,const char **e, /* if null byte, we are done */ if (!**s) { - (*s)++; /* keep *s moving */ + (*s)++; /* keep *s moving */ return 0; } @@ -404,6 +398,7 @@ static int parse_one_device(const char **s,const char **e, /* parse vendor_id */ runner = *s; + while (runner < *e) { /* scan for vendor:device delimiter */ if (*runner == ':') { @@ -411,6 +406,7 @@ static int parse_one_device(const char **s,const char **e, runner = p + 1; break; } + runner++; } @@ -426,12 +422,11 @@ static int parse_one_device(const char **s,const char **e, } *s = runner; - return 1; } static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer, - size_t count) + size_t count) { struct list_control *listctl; struct edac_pci_device_list *list; @@ -441,14 +436,12 @@ static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer, s = (char*)buffer; e = s + count; - listctl = ptr; list = listctl->list; index = listctl->count; - *index = 0; - while (*index < MAX_LISTED_PCI_DEVICES) { + while (*index < MAX_LISTED_PCI_DEVICES) { if (parse_one_device(&s,&e,&vendor_id,&device_id)) { list[ *index ].vendor = vendor_id; list[ *index ].device = device_id; @@ -481,15 +474,15 @@ static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count) } struct edac_pci_dev_attribute { - struct attribute attr; - void *value; + struct attribute attr; + void *value; ssize_t (*show)(void *,char *); ssize_t (*store)(void *, const char *,size_t); }; /* Set of show/store abstract level functions for PCI Parity object */ static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr, - char *buffer) + char *buffer) { struct edac_pci_dev_attribute *edac_pci_dev; edac_pci_dev= (struct edac_pci_dev_attribute*)attr; @@ -499,8 +492,8 @@ static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr, return -EIO; } -static ssize_t edac_pci_dev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) +static ssize_t edac_pci_dev_store(struct kobject *kobj, + struct attribute *attr, const char *buffer, size_t count) { struct edac_pci_dev_attribute *edac_pci_dev; edac_pci_dev= (struct edac_pci_dev_attribute*)attr; @@ -515,7 +508,6 @@ static struct sysfs_ops edac_pci_sysfs_ops = { .store = edac_pci_dev_store }; - #define EDAC_PCI_ATTR(_name,_mode,_show,_store) \ struct edac_pci_dev_attribute edac_pci_attr_##_name = { \ .attr = {.name = __stringify(_name), .mode = _mode }, \ @@ -558,9 +550,11 @@ EDAC_PCI_STRING_ATTR(pci_parity_blacklist, #endif /* PCI Parity control files */ -EDAC_PCI_ATTR(check_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store); -EDAC_PCI_ATTR(panic_on_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store); -EDAC_PCI_ATTR(pci_parity_count,S_IRUGO,edac_pci_int_show,NULL); +EDAC_PCI_ATTR(check_pci_parity, S_IRUGO|S_IWUSR, edac_pci_int_show, + edac_pci_int_store); +EDAC_PCI_ATTR(panic_on_pci_parity, S_IRUGO|S_IWUSR, edac_pci_int_show, + edac_pci_int_store); +EDAC_PCI_ATTR(pci_parity_count, S_IRUGO, edac_pci_int_show, NULL); /* Base Attributes of the memory ECC object */ static struct edac_pci_dev_attribute *edac_pci_attr[] = { @@ -578,9 +572,9 @@ static void edac_pci_release(struct kobject *kobj) } static struct kobj_type ktype_edac_pci = { - .release = edac_pci_release, - .sysfs_ops = &edac_pci_sysfs_ops, - .default_attrs = (struct attribute **) edac_pci_attr, + .release = edac_pci_release, + .sysfs_ops = &edac_pci_sysfs_ops, + .default_attrs = (struct attribute **) edac_pci_attr, }; #endif /* DISABLE_EDAC_SYSFS */ @@ -603,17 +597,19 @@ static int edac_sysfs_pci_setup(void) memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj)); edac_pci_kobj.parent = &edac_class.kset.kobj; edac_pci_kobj.ktype = &ktype_edac_pci; - err = kobject_set_name(&edac_pci_kobj, "pci"); + if (!err) { /* Instanstiate the csrow object */ /* FIXME: maybe new sysdev_create_subdir() */ err = kobject_register(&edac_pci_kobj); + if (err) debugf1("Failed to register '.../edac/pci'\n"); else debugf1("Registered '.../edac/pci' kobject\n"); } + return err; } #endif /* DISABLE_EDAC_SYSFS */ @@ -641,6 +637,7 @@ static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data) size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n", csrow->channels[0].label); } + return size; } @@ -652,11 +649,12 @@ static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data) size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n", csrow->channels[1].label); } + return size; } static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow, - const char *data, size_t size) + const char *data, size_t size) { ssize_t max_size = 0; @@ -665,11 +663,12 @@ static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow, strncpy(csrow->channels[0].label, data, max_size); csrow->channels[0].label[max_size] = '\0'; } + return size; } static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow, - const char *data, size_t size) + const char *data, size_t size) { ssize_t max_size = 0; @@ -678,6 +677,7 @@ static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow, strncpy(csrow->channels[1].label, data, max_size); csrow->channels[1].label[max_size] = '\0'; } + return max_size; } @@ -698,6 +698,7 @@ static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data) if (csrow->nr_channels > 0) { size = sprintf(data,"%u\n", csrow->channels[0].ce_count); } + return size; } @@ -708,6 +709,7 @@ static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data) if (csrow->nr_channels > 1) { size = sprintf(data,"%u\n", csrow->channels[1].ce_count); } + return size; } @@ -732,7 +734,7 @@ static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data) } struct csrowdev_attribute { - struct attribute attr; + struct attribute attr; ssize_t (*show)(struct csrow_info *,char *); ssize_t (*store)(struct csrow_info *, const char *,size_t); }; @@ -742,24 +744,26 @@ struct csrowdev_attribute { /* Set of show/store higher level functions for csrow objects */ static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr, - char *buffer) + char *buffer) { struct csrow_info *csrow = to_csrow(kobj); struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr); if (csrowdev_attr->show) return csrowdev_attr->show(csrow, buffer); + return -EIO; } static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) + const char *buffer, size_t count) { struct csrow_info *csrow = to_csrow(kobj); struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr); if (csrowdev_attr->store) return csrowdev_attr->store(csrow, buffer, count); + return -EIO; } @@ -793,7 +797,6 @@ CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR, csrow_ch1_dimm_label_show, csrow_ch1_dimm_label_store); - /* Attributes of the CSROW object */ static struct csrowdev_attribute *csrow_attr[] = { &attr_dev_type, @@ -809,7 +812,6 @@ static struct csrowdev_attribute *csrow_attr[] = { NULL, }; - /* No memory to release */ static void edac_csrow_instance_release(struct kobject *kobj) { @@ -821,19 +823,18 @@ static void edac_csrow_instance_release(struct kobject *kobj) } static struct kobj_type ktype_csrow = { - .release = edac_csrow_instance_release, - .sysfs_ops = &csrowfs_ops, - .default_attrs = (struct attribute **) csrow_attr, + .release = edac_csrow_instance_release, + .sysfs_ops = &csrowfs_ops, + .default_attrs = (struct attribute **) csrow_attr, }; /* Create a CSROW object under specifed edac_mc_device */ static int edac_create_csrow_object(struct kobject *edac_mci_kobj, - struct csrow_info *csrow, int index ) + struct csrow_info *csrow, int index) { int err = 0; debugf0("%s()\n", __func__); - memset(&csrow->kobj, 0, sizeof(csrow->kobj)); /* generate ..../edac/mc/mc/csrow */ @@ -843,9 +844,11 @@ static int edac_create_csrow_object(struct kobject *edac_mci_kobj, /* name this instance of csrow */ err = kobject_set_name(&csrow->kobj,"csrow%d",index); + if (!err) { /* Instanstiate the csrow object */ err = kobject_register(&csrow->kobj); + if (err) debugf0("Failed to register CSROW%d\n",index); else @@ -857,8 +860,8 @@ static int edac_create_csrow_object(struct kobject *edac_mci_kobj, /* sysfs data structures and methods for the MCI kobjects */ -static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, - const char *data, size_t count ) +static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, + const char *data, size_t count) { int row, chan; @@ -866,16 +869,18 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, mci->ce_noinfo_count = 0; mci->ue_count = 0; mci->ce_count = 0; + for (row = 0; row < mci->nr_csrows; row++) { struct csrow_info *ri = &mci->csrows[row]; ri->ue_count = 0; ri->ce_count = 0; + for (chan = 0; chan < ri->nr_channels; chan++) ri->channels[chan].ce_count = 0; } - mci->start_time = jiffies; + mci->start_time = jiffies; return count; } @@ -933,18 +938,16 @@ static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data) p += mci_output_edac_cap(p,mci->edac_ctl_cap); p += sprintf(p, "\n"); - return p - data; } static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci, - char *data) + char *data) { char *p = data; p += mci_output_edac_cap(p,mci->edac_cap); p += sprintf(p, "\n"); - return p - data; } @@ -961,13 +964,13 @@ static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap) return p - buf; } -static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, + char *data) { char *p = data; p += mci_output_mtype_cap(p,mci->mtype_cap); p += sprintf(p, "\n"); - return p - data; } @@ -981,6 +984,7 @@ static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) if (!csrow->nr_pages) continue; + total_pages += csrow->nr_pages; } @@ -988,7 +992,7 @@ static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) } struct mcidev_attribute { - struct attribute attr; + struct attribute attr; ssize_t (*show)(struct mem_ctl_info *,char *); ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); }; @@ -997,30 +1001,32 @@ struct mcidev_attribute { #define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr) static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr, - char *buffer) + char *buffer) { struct mem_ctl_info *mem_ctl_info = to_mci(kobj); struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr); if (mcidev_attr->show) return mcidev_attr->show(mem_ctl_info, buffer); + return -EIO; } static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) + const char *buffer, size_t count) { struct mem_ctl_info *mem_ctl_info = to_mci(kobj); struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr); if (mcidev_attr->store) return mcidev_attr->store(mem_ctl_info, buffer, count); + return -EIO; } static struct sysfs_ops mci_ops = { - .show = mcidev_show, - .store = mcidev_store + .show = mcidev_show, + .store = mcidev_store }; #define MCIDEV_ATTR(_name,_mode,_show,_store) \ @@ -1048,7 +1054,6 @@ MCIDEV_ATTR(edac_current_capability,S_IRUGO, MCIDEV_ATTR(supported_mem_type,S_IRUGO, mci_supported_mem_type_show,NULL); - static struct mcidev_attribute *mci_attr[] = { &mci_attr_reset_counters, &mci_attr_module_name, @@ -1065,7 +1070,6 @@ static struct mcidev_attribute *mci_attr[] = { NULL }; - /* * Release of a MC controlling instance */ @@ -1079,9 +1083,9 @@ static void edac_mci_instance_release(struct kobject *kobj) } static struct kobj_type ktype_mci = { - .release = edac_mci_instance_release, - .sysfs_ops = &mci_ops, - .default_attrs = (struct attribute **) mci_attr, + .release = edac_mci_instance_release, + .sysfs_ops = &mci_ops, + .default_attrs = (struct attribute **) mci_attr, }; #endif /* DISABLE_EDAC_SYSFS */ @@ -1109,11 +1113,11 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) struct kobject *edac_mci_kobj=&mci->edac_mci_kobj; debugf0("%s() idx=%d\n", __func__, mci->mc_idx); - memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj)); /* set the name of the mc object */ err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx); + if (err) return err; @@ -1123,12 +1127,14 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) /* register the mc kobject */ err = kobject_register(edac_mci_kobj); + if (err) return err; /* create a symlink for the device */ err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj, EDAC_DEVICE_SYMLINK); + if (err) goto fail0; @@ -1136,12 +1142,12 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) * under the mc kobject */ for (i = 0; i < mci->nr_csrows; i++) { - csrow = &mci->csrows[i]; /* Only expose populated CSROWs */ if (csrow->nr_pages > 0) { err = edac_create_csrow_object(edac_mci_kobj,csrow,i); + if (err) goto fail1; } @@ -1149,7 +1155,6 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) return 0; - /* CSROW error: backout what has already been registered, */ fail1: for ( i--; i >= 0; i--) { @@ -1164,7 +1169,6 @@ fail0: init_completion(&mci->kobj_complete); kobject_unregister(edac_mci_kobj); wait_for_completion(&mci->kobj_complete); - return err; } #endif /* DISABLE_EDAC_SYSFS */ @@ -1199,7 +1203,6 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) #ifdef CONFIG_EDAC_DEBUG - void edac_mc_dump_channel(struct channel_info *chan) { debugf4("\tchannel = %p\n", chan); @@ -1210,7 +1213,6 @@ void edac_mc_dump_channel(struct channel_info *chan) } EXPORT_SYMBOL(edac_mc_dump_channel); - void edac_mc_dump_csrow(struct csrow_info *csrow) { debugf4("\tcsrow = %p\n", csrow); @@ -1227,7 +1229,6 @@ void edac_mc_dump_csrow(struct csrow_info *csrow) } EXPORT_SYMBOL(edac_mc_dump_csrow); - void edac_mc_dump_mci(struct mem_ctl_info *mci) { debugf3("\tmci = %p\n", mci); @@ -1244,8 +1245,7 @@ void edac_mc_dump_mci(struct mem_ctl_info *mci) } EXPORT_SYMBOL(edac_mc_dump_mci); - -#endif /* CONFIG_EDAC_DEBUG */ +#endif /* CONFIG_EDAC_DEBUG */ /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'. * Adjust 'ptr' so that its alignment is at least as stringent as what the @@ -1254,7 +1254,7 @@ EXPORT_SYMBOL(edac_mc_dump_mci); * If 'size' is a constant, the compiler will optimize this whole function * down to either a no-op or the addition of a constant to the value of 'ptr'. */ -static inline char * align_ptr (void *ptr, unsigned size) +static inline char * align_ptr(void *ptr, unsigned size) { unsigned align, r; @@ -1281,7 +1281,6 @@ static inline char * align_ptr (void *ptr, unsigned size) return (char *) (((unsigned long) ptr) + align - r); } - /** * edac_mc_alloc: Allocate a struct mem_ctl_info structure * @size_pvt: size of private storage needed @@ -1299,7 +1298,7 @@ static inline char * align_ptr (void *ptr, unsigned size) * struct mem_ctl_info pointer */ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, - unsigned nr_chans) + unsigned nr_chans) { struct mem_ctl_info *mci; struct csrow_info *csi, *csrow; @@ -1330,8 +1329,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, chi = (struct channel_info *) (((char *) mci) + ((unsigned long) chi)); pvt = sz_pvt ? (((char *) mci) + ((unsigned long) pvt)) : NULL; - memset(mci, 0, size); /* clear all fields */ - + memset(mci, 0, size); /* clear all fields */ mci->csrows = csi; mci->pvt_info = pvt; mci->nr_csrows = nr_csrows; @@ -1355,7 +1353,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, } EXPORT_SYMBOL(edac_mc_alloc); - /** * edac_mc_free: Free a previously allocated 'mci' structure * @mci: pointer to a struct mem_ctl_info structure @@ -1383,7 +1380,7 @@ static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev) return NULL; } -static int add_mc_to_global_list (struct mem_ctl_info *mci) +static int add_mc_to_global_list(struct mem_ctl_info *mci) { struct list_head *item, *insert_before; struct mem_ctl_info *p; @@ -1426,8 +1423,7 @@ static int add_mc_to_global_list (struct mem_ctl_info *mci) return 0; } - -static void complete_mc_list_del (struct rcu_head *head) +static void complete_mc_list_del(struct rcu_head *head) { struct mem_ctl_info *mci; @@ -1436,8 +1432,7 @@ static void complete_mc_list_del (struct rcu_head *head) complete(&mci->complete); } - -static void del_mc_from_global_list (struct mem_ctl_info *mci) +static void del_mc_from_global_list(struct mem_ctl_info *mci) { list_del_rcu(&mci->link); init_completion(&mci->complete); @@ -1445,7 +1440,6 @@ static void del_mc_from_global_list (struct mem_ctl_info *mci) wait_for_completion(&mci->complete); } - /** * edac_mc_add_mc: Insert the 'mci' structure into the mci global list and * create sysfs entries associated with mci structure @@ -1463,15 +1457,17 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) #ifdef CONFIG_EDAC_DEBUG if (edac_debug_level >= 3) edac_mc_dump_mci(mci); + if (edac_debug_level >= 4) { int i; for (i = 0; i < mci->nr_csrows; i++) { int j; + edac_mc_dump_csrow(&mci->csrows[i]); for (j = 0; j < mci->csrows[i].nr_channels; j++) - edac_mc_dump_channel(&mci->csrows[i]. - channels[j]); + edac_mc_dump_channel( + &mci->csrows[i].channels[j]); } } #endif @@ -1505,7 +1501,6 @@ fail0: } EXPORT_SYMBOL(edac_mc_add_mc); - /** * edac_mc_del_mc: Remove sysfs entries for specified mci structure and * remove mci structure from global list @@ -1535,9 +1530,7 @@ struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev) } EXPORT_SYMBOL(edac_mc_del_mc); - -void edac_mc_scrub_block(unsigned long page, unsigned long offset, - u32 size) +void edac_mc_scrub_block(unsigned long page, unsigned long offset, u32 size) { struct page *pg; void *virt_addr; @@ -1568,10 +1561,8 @@ void edac_mc_scrub_block(unsigned long page, unsigned long offset, } EXPORT_SYMBOL(edac_mc_scrub_block); - /* FIXME - should return -1 */ -int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, - unsigned long page) +int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) { struct csrow_info *csrows = mci->csrows; int row, i; @@ -1608,14 +1599,11 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, } EXPORT_SYMBOL(edac_mc_find_csrow_by_page); - /* FIXME - setable log (warning/emerg) levels */ /* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */ void edac_mc_handle_ce(struct mem_ctl_info *mci, - unsigned long page_frame_number, - unsigned long offset_in_page, - unsigned long syndrome, int row, int channel, - const char *msg) + unsigned long page_frame_number, unsigned long offset_in_page, + unsigned long syndrome, int row, int channel, const char *msg) { unsigned long remapped_page; @@ -1630,6 +1618,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); return; } + if (channel >= mci->csrows[row].nr_channels || channel < 0) { /* something is wrong */ edac_mc_printk(mci, KERN_ERR, @@ -1668,28 +1657,25 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, page_frame_number; edac_mc_scrub_block(remapped_page, offset_in_page, - mci->csrows[row].grain); + mci->csrows[row].grain); } } EXPORT_SYMBOL(edac_mc_handle_ce); - -void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, - const char *msg) +void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg) { if (log_ce) edac_mc_printk(mci, KERN_WARNING, "CE - no information available: %s\n", msg); + mci->ce_noinfo_count++; mci->ce_count++; } EXPORT_SYMBOL(edac_mc_handle_ce_no_info); - void edac_mc_handle_ue(struct mem_ctl_info *mci, - unsigned long page_frame_number, - unsigned long offset_in_page, int row, - const char *msg) + unsigned long page_frame_number, unsigned long offset_in_page, + int row, const char *msg) { int len = EDAC_MC_LABEL_LEN * 4; char labels[len + 1]; @@ -1710,13 +1696,14 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci, } chars = snprintf(pos, len + 1, "%s", - mci->csrows[row].channels[0].label); + mci->csrows[row].channels[0].label); len -= chars; pos += chars; + for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0); chan++) { chars = snprintf(pos, len + 1, ":%s", - mci->csrows[row].channels[chan].label); + mci->csrows[row].channels[chan].label); len -= chars; pos += chars; } @@ -1729,20 +1716,17 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci, msg); if (panic_on_ue) - panic - ("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d," - " labels \"%s\": %s\n", mci->mc_idx, - page_frame_number, offset_in_page, - mci->csrows[row].grain, row, labels, msg); + panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, " + "row %d, labels \"%s\": %s\n", mci->mc_idx, + page_frame_number, offset_in_page, + mci->csrows[row].grain, row, labels, msg); mci->ue_count++; mci->csrows[row].ue_count++; } EXPORT_SYMBOL(edac_mc_handle_ue); - -void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, - const char *msg) +void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) { if (panic_on_ue) panic("EDAC MC%d: Uncorrected Error", mci->mc_idx); @@ -1755,7 +1739,6 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, } EXPORT_SYMBOL(edac_mc_handle_ue_no_info); - #ifdef CONFIG_PCI static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) @@ -1766,18 +1749,22 @@ static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) where = secondary ? PCI_SEC_STATUS : PCI_STATUS; pci_read_config_word(dev, where, &status); - /* If we get back 0xFFFF then we must suspect that the card has been pulled but - the Linux PCI layer has not yet finished cleaning up. We don't want to report - on such devices */ + /* If we get back 0xFFFF then we must suspect that the card has been + * pulled but the Linux PCI layer has not yet finished cleaning up. + * We don't want to report on such devices + */ if (status == 0xFFFF) { u32 sanity; + pci_read_config_dword(dev, 0, &sanity); + if (sanity == 0xFFFFFFFF) return 0; } + status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR | - PCI_STATUS_PARITY; + PCI_STATUS_PARITY; if (status) /* reset only the bits we are interested in */ @@ -1789,7 +1776,7 @@ static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev); /* Clear any PCI parity errors logged by this device. */ -static void edac_pci_dev_parity_clear( struct pci_dev *dev ) +static void edac_pci_dev_parity_clear(struct pci_dev *dev) { u8 header_type; @@ -1890,58 +1877,55 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) * Returns: 0 not found * 1 found on list */ -static int check_dev_on_list(struct edac_pci_device_list *list, int free_index, - struct pci_dev *dev) -{ - int i; - int rc = 0; /* Assume not found */ - unsigned short vendor=dev->vendor; - unsigned short device=dev->device; - - /* Scan the list, looking for a vendor/device match - */ - for (i = 0; i < free_index; i++, list++ ) { - if ( (list->vendor == vendor ) && - (list->device == device )) { - rc = 1; - break; - } - } +static int check_dev_on_list(struct edac_pci_device_list *list, + int free_index, struct pci_dev *dev) +{ + int i; + int rc = 0; /* Assume not found */ + unsigned short vendor=dev->vendor; + unsigned short device=dev->device; + + /* Scan the list, looking for a vendor/device match */ + for (i = 0; i < free_index; i++, list++ ) { + if ((list->vendor == vendor ) && (list->device == device )) { + rc = 1; + break; + } + } - return rc; + return rc; } /* * pci_dev parity list iterator - * Scan the PCI device list for one iteration, looking for SERRORs + * Scan the PCI device list for one iteration, looking for SERRORs * Master Parity ERRORS or Parity ERRORs on primary or secondary devices */ static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) { - struct pci_dev *dev=NULL; + struct pci_dev *dev = NULL; /* request for kernel access to the next PCI device, if any, * and while we are looking at it have its reference count * bumped until we are done with it */ while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - - /* if whitelist exists then it has priority, so only scan those - * devices on the whitelist - */ - if (pci_whitelist_count > 0 ) { - if (check_dev_on_list(pci_whitelist, + /* if whitelist exists then it has priority, so only scan + * those devices on the whitelist + */ + if (pci_whitelist_count > 0 ) { + if (check_dev_on_list(pci_whitelist, pci_whitelist_count, dev)) fn(dev); - } else { + } else { /* * if no whitelist, then check if this devices is * blacklisted */ - if (!check_dev_on_list(pci_blacklist, + if (!check_dev_on_list(pci_blacklist, pci_blacklist_count, dev)) fn(dev); - } + } } } @@ -1972,7 +1956,6 @@ static void do_pci_parity_check(void) } } - static inline void clear_pci_parity_errors(void) { /* Clear any PCI bus parity errors that devices initially have logged @@ -1981,34 +1964,29 @@ static inline void clear_pci_parity_errors(void) edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear); } - #else /* CONFIG_PCI */ - static inline void do_pci_parity_check(void) { /* no-op */ } - static inline void clear_pci_parity_errors(void) { /* no-op */ } - #endif /* CONFIG_PCI */ /* * Iterate over all MC instances and check for ECC, et al, errors */ -static inline void check_mc_devices (void) +static inline void check_mc_devices(void) { struct list_head *item; struct mem_ctl_info *mci; debugf3("%s()\n", __func__); - down(&mem_ctls_mutex); list_for_each(item, &mc_devices) { @@ -2021,7 +1999,6 @@ static inline void check_mc_devices (void) up(&mem_ctls_mutex); } - /* * Check MC status every poll_msec. * Check PCI status every poll_msec as well. @@ -2084,6 +2061,7 @@ static int __init edac_mc_init(void) /* create our kernel thread */ edac_thread = kthread_run(edac_kernel_thread, NULL, "kedac"); + if (IS_ERR(edac_thread)) { /* remove the sysfs entries */ edac_sysfs_memctrl_teardown(); @@ -2094,7 +2072,6 @@ static int __init edac_mc_init(void) return 0; } - /* * edac_mc_exit() * module exit/termination functioni @@ -2102,7 +2079,6 @@ static int __init edac_mc_init(void) static void __exit edac_mc_exit(void) { debugf0("%s()\n", __func__); - kthread_stop(edac_thread); /* tear down the sysfs device */ @@ -2110,15 +2086,12 @@ static void __exit edac_mc_exit(void) edac_sysfs_pci_teardown(); } - - - module_init(edac_mc_init); module_exit(edac_mc_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n" - "Based on.work by Dan Hollis et al"); + "Based on work by Dan Hollis et al"); MODULE_DESCRIPTION("Core library routines for MC reporting"); module_param(panic_on_ue, int, 0644); diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h index 2cec157aaeba..8d9e83909b9c 100644 --- a/drivers/edac/edac_mc.h +++ b/drivers/edac/edac_mc.h @@ -15,11 +15,9 @@ * */ - #ifndef _EDAC_MC_H_ #define _EDAC_MC_H_ - #include #include #include @@ -33,7 +31,6 @@ #include #include - #define EDAC_MC_LABEL_LEN 31 #define MC_PROC_NAME_MAX_LEN 7 @@ -44,13 +41,13 @@ #endif #define edac_printk(level, prefix, fmt, arg...) \ - printk(level "EDAC " prefix ": " fmt, ##arg) + printk(level "EDAC " prefix ": " fmt, ##arg) #define edac_mc_printk(mci, level, fmt, arg...) \ - printk(level "EDAC MC%d: " fmt, mci->mc_idx, ##arg) + printk(level "EDAC MC%d: " fmt, mci->mc_idx, ##arg) #define edac_mc_chipset_printk(mci, level, prefix, fmt, arg...) \ - printk(level "EDAC " prefix " MC%d: " fmt, mci->mc_idx, ##arg) + printk(level "EDAC " prefix " MC%d: " fmt, mci->mc_idx, ##arg) /* prefixes for edac_printk() and edac_mc_printk() */ #define EDAC_MC "MC" @@ -71,14 +68,16 @@ extern int edac_debug_level; #define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ ) #define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ ) #define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ ) -#else /* !CONFIG_EDAC_DEBUG */ + +#else /* !CONFIG_EDAC_DEBUG */ + #define debugf0( ... ) #define debugf1( ... ) #define debugf2( ... ) #define debugf3( ... ) #define debugf4( ... ) -#endif /* !CONFIG_EDAC_DEBUG */ +#endif /* !CONFIG_EDAC_DEBUG */ #define edac_xstr(s) edac_str(s) #define edac_str(s) #s @@ -86,7 +85,8 @@ extern int edac_debug_level; #define BIT(x) (1 << (x)) -#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, PCI_DEVICE_ID_ ## vend ## _ ## dev +#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \ + PCI_DEVICE_ID_ ## vend ## _ ## dev /* memory devices */ enum dev_type { @@ -136,7 +136,6 @@ enum mem_type { #define MEM_FLAG_RDDR BIT(MEM_RDDR) #define MEM_FLAG_RMBS BIT(MEM_RMBS) - /* chipset Error Detection and Correction capabilities and mode */ enum edac_type { EDAC_UNKNOWN = 0, /* Unknown if ECC is available */ @@ -161,7 +160,6 @@ enum edac_type { #define EDAC_FLAG_S8ECD8ED BIT(EDAC_S8ECD8ED) #define EDAC_FLAG_S16ECD16ED BIT(EDAC_S16ECD16ED) - /* scrubbing capabilities */ enum scrub_type { SCRUB_UNKNOWN = 0, /* Unknown if scrubber is available */ @@ -269,20 +267,19 @@ enum scrub_type { * PS - I enjoyed writing all that about as much as you enjoyed reading it. */ - struct channel_info { int chan_idx; /* channel index */ u32 ce_count; /* Correctable Errors for this CHANNEL */ - char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */ + char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */ struct csrow_info *csrow; /* the parent */ }; - struct csrow_info { unsigned long first_page; /* first page number in dimm */ unsigned long last_page; /* last page number in dimm */ unsigned long page_mask; /* used for interleaving - - 0UL for non intlv */ + * 0UL for non intlv + */ u32 nr_pages; /* number of pages in csrow */ u32 grain; /* granularity of reported error in bytes */ int csrow_idx; /* the chip-select row */ @@ -301,18 +298,18 @@ struct csrow_info { struct channel_info *channels; }; - struct mem_ctl_info { struct list_head link; /* for global list of mem_ctl_info structs */ unsigned long mtype_cap; /* memory types supported by mc */ unsigned long edac_ctl_cap; /* Mem controller EDAC capabilities */ unsigned long edac_cap; /* configuration capabilities - this is - closely related to edac_ctl_cap. The - difference is that the controller - may be capable of s4ecd4ed which would - be listed in edac_ctl_cap, but if - channels aren't capable of s4ecd4ed then the - edac_cap would not have that capability. */ + * closely related to edac_ctl_cap. The + * difference is that the controller may be + * capable of s4ecd4ed which would be listed + * in edac_ctl_cap, but if channels aren't + * capable of s4ecd4ed then the edac_cap would + * not have that capability. + */ unsigned long scrub_cap; /* chipset scrub capabilities */ enum scrub_type scrub_mode; /* current scrub mode */ @@ -324,7 +321,7 @@ struct mem_ctl_info { */ /* FIXME - why not send the phys page to begin with? */ unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci, - unsigned long page); + unsigned long page); int mc_idx; int nr_csrows; struct csrow_info *csrows; @@ -356,67 +353,66 @@ struct mem_ctl_info { struct completion kobj_complete; }; - - /* write all or some bits in a byte-register*/ -static inline void pci_write_bits8(struct pci_dev *pdev, int offset, - u8 value, u8 mask) +static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value, + u8 mask) { if (mask != 0xff) { u8 buf; + pci_read_config_byte(pdev, offset, &buf); value &= mask; buf &= ~mask; value |= buf; } + pci_write_config_byte(pdev, offset, value); } - /* write all or some bits in a word-register*/ static inline void pci_write_bits16(struct pci_dev *pdev, int offset, - u16 value, u16 mask) + u16 value, u16 mask) { if (mask != 0xffff) { u16 buf; + pci_read_config_word(pdev, offset, &buf); value &= mask; buf &= ~mask; value |= buf; } + pci_write_config_word(pdev, offset, value); } - /* write all or some bits in a dword-register*/ static inline void pci_write_bits32(struct pci_dev *pdev, int offset, - u32 value, u32 mask) + u32 value, u32 mask) { if (mask != 0xffff) { u32 buf; + pci_read_config_dword(pdev, offset, &buf); value &= mask; buf &= ~mask; value |= buf; } + pci_write_config_dword(pdev, offset, value); } - #ifdef CONFIG_EDAC_DEBUG void edac_mc_dump_channel(struct channel_info *chan); void edac_mc_dump_mci(struct mem_ctl_info *mci); void edac_mc_dump_csrow(struct csrow_info *csrow); -#endif /* CONFIG_EDAC_DEBUG */ +#endif /* CONFIG_EDAC_DEBUG */ extern int edac_mc_add_mc(struct mem_ctl_info *mci); extern struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev); - extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, - unsigned long page); - -extern void edac_mc_scrub_block(unsigned long page, - unsigned long offset, u32 size); + unsigned long page); +extern void edac_mc_scrub_block(unsigned long page, unsigned long offset, + u32 size); /* * The no info errors are used when error overflows are reported. @@ -429,31 +425,25 @@ extern void edac_mc_scrub_block(unsigned long page, * statement clutter and extra function arguments. */ extern void edac_mc_handle_ce(struct mem_ctl_info *mci, - unsigned long page_frame_number, - unsigned long offset_in_page, - unsigned long syndrome, - int row, int channel, const char *msg); - + unsigned long page_frame_number, unsigned long offset_in_page, + unsigned long syndrome, int row, int channel, + const char *msg); extern void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, - const char *msg); - + const char *msg); extern void edac_mc_handle_ue(struct mem_ctl_info *mci, - unsigned long page_frame_number, - unsigned long offset_in_page, - int row, const char *msg); - + unsigned long page_frame_number, unsigned long offset_in_page, + int row, const char *msg); extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, - const char *msg); + const char *msg); /* * This kmalloc's and initializes all the structures. * Can't be used if all structures don't have the same lifetime. */ -extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, - unsigned nr_csrows, unsigned nr_chans); +extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, + unsigned nr_chans); /* Free an mc previously allocated by edac_mc_alloc() */ extern void edac_mc_free(struct mem_ctl_info *mci); - #endif /* _EDAC_MC_H_ */ diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 688854260a0e..fd342163cf97 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -9,7 +9,6 @@ * by Thayne Harbaugh of Linux Networx. (http://lnxi.com) */ - #include #include #include @@ -18,14 +17,11 @@ #include #include "edac_mc.h" - #define i82860_printk(level, fmt, arg...) \ - edac_printk(level, "i82860", fmt, ##arg) - + edac_printk(level, "i82860", fmt, ##arg) #define i82860_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg) - + edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg) #ifndef PCI_DEVICE_ID_INTEL_82860_0 #define PCI_DEVICE_ID_INTEL_82860_0 0x2531 @@ -56,13 +52,15 @@ struct i82860_error_info { static const struct i82860_dev_info i82860_devs[] = { [I82860] = { - .ctl_name = "i82860"}, + .ctl_name = "i82860" + }, }; static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code - has already registered driver */ + * has already registered driver + */ -static void i82860_get_error_info (struct mem_ctl_info *mci, +static void i82860_get_error_info(struct mem_ctl_info *mci, struct i82860_error_info *info) { /* @@ -84,14 +82,15 @@ static void i82860_get_error_info (struct mem_ctl_info *mci, */ if (!(info->errsts2 & 0x0003)) return; + if ((info->errsts ^ info->errsts2) & 0x0003) { pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap); pci_read_config_word(mci->pdev, I82860_DERRCTL_STS, - &info->derrsyn); + &info->derrsyn); } } -static int i82860_process_error_info (struct mem_ctl_info *mci, +static int i82860_process_error_info(struct mem_ctl_info *mci, struct i82860_error_info *info, int handle_errors) { int row; @@ -113,8 +112,8 @@ static int i82860_process_error_info (struct mem_ctl_info *mci, if (info->errsts & 0x0002) edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE"); else - edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, - 0, "i82860 UE"); + edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, 0, + "i82860 UE"); return 1; } @@ -147,15 +146,14 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) going to make 1 channel for group. */ mci = edac_mc_alloc(0, 16, 1); + if (!mci) return -ENOMEM; debugf3("%s(): init mci\n", __func__); - mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_DDR; - mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; /* I"m not sure about this but I think that all RDRAM is SECDED */ mci->edac_cap = EDAC_FLAG_SECDED; @@ -182,12 +180,13 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) struct csrow_info *csrow = &mci->csrows[index]; pci_read_config_word(mci->pdev, I82860_GBA + index * 2, - &value); + &value); cumul_size = (value & I82860_GBA_MASK) << (I82860_GBA_SHIFT - PAGE_SHIFT); debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, cumul_size); + if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -195,7 +194,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) csrow->last_page = cumul_size - 1; csrow->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; - csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ + csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ csrow->mtype = MEM_RMBS; csrow->dtype = DEV_UNKNOWN; csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE; @@ -211,23 +210,27 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) debugf3("%s(): success\n", __func__); rc = 0; } + return rc; } /* returns count (>= 0), or negative on error */ static int __devinit i82860_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { int rc; debugf0("%s()\n", __func__); - i82860_printk(KERN_INFO, "i82860 init one\n"); - if(pci_enable_device(pdev) < 0) + + if (pci_enable_device(pdev) < 0) return -EIO; + rc = i82860_probe1(pdev, ent->driver_data); - if(rc == 0) + + if (rc == 0) mci_pdev = pci_dev_get(pdev); + return rc; } @@ -244,9 +247,13 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev) } static const struct pci_device_id i82860_pci_tbl[] __devinitdata = { - {PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - I82860}, - {0,} /* 0 terminated list. */ + { + PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + I82860 + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, i82860_pci_tbl); @@ -263,24 +270,29 @@ static int __init i82860_init(void) int pci_rc; debugf3("%s()\n", __func__); + if ((pci_rc = pci_register_driver(&i82860_driver)) < 0) goto fail0; if (!mci_pdev) { mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82860_0, NULL); + PCI_DEVICE_ID_INTEL_82860_0, NULL); + if (mci_pdev == NULL) { debugf0("860 pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } + pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl); + if (pci_rc < 0) { debugf0("860 init fail\n"); pci_rc = -ENODEV; goto fail1; } } + return 0; fail1: @@ -307,6 +319,6 @@ module_init(i82860_init); module_exit(i82860_exit); MODULE_LICENSE("GPL"); -MODULE_AUTHOR - ("Red Hat Inc. (http://www.redhat.com) Ben Woodard "); +MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) " + "Ben Woodard "); MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers"); diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index aad1900a4689..0aec92698f17 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -13,26 +13,19 @@ * Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com */ - #include #include #include - #include #include - #include - #include "edac_mc.h" - #define i82875p_printk(level, fmt, arg...) \ - edac_printk(level, "i82875p", fmt, ##arg) - + edac_printk(level, "i82875p", fmt, ##arg) #define i82875p_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg) - + edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg) #ifndef PCI_DEVICE_ID_INTEL_82875_0 #define PCI_DEVICE_ID_INTEL_82875_0 0x2578 @@ -42,11 +35,9 @@ #define PCI_DEVICE_ID_INTEL_82875_6 0x257e #endif /* PCI_DEVICE_ID_INTEL_82875_6 */ - /* four csrows in dual channel, eight in single channel */ #define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans)) - /* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */ #define I82875P_EAP 0x58 /* Error Address Pointer (32b) * @@ -95,7 +86,6 @@ * 0 reserved */ - /* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */ #define I82875P_PCICMD6 0x04 /* PCI Command Register (16b) * @@ -159,23 +149,19 @@ * 1:0 DRAM type 01=DDR */ - enum i82875p_chips { I82875P = 0, }; - struct i82875p_pvt { struct pci_dev *ovrfl_pdev; void __iomem *ovrfl_window; }; - struct i82875p_dev_info { const char *ctl_name; }; - struct i82875p_error_info { u16 errsts; u32 eap; @@ -184,17 +170,19 @@ struct i82875p_error_info { u16 errsts2; }; - static const struct i82875p_dev_info i82875p_devs[] = { [I82875P] = { - .ctl_name = "i82875p"}, + .ctl_name = "i82875p" + }, }; -static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code - has already registered driver */ +static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code has + * already registered driver + */ + static int i82875p_registered = 1; -static void i82875p_get_error_info (struct mem_ctl_info *mci, +static void i82875p_get_error_info(struct mem_ctl_info *mci, struct i82875p_error_info *info) { /* @@ -218,15 +206,16 @@ static void i82875p_get_error_info (struct mem_ctl_info *mci, */ if (!(info->errsts2 & 0x0081)) return; + if ((info->errsts ^ info->errsts2) & 0x0081) { pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap); pci_read_config_byte(mci->pdev, I82875P_DES, &info->des); pci_read_config_byte(mci->pdev, I82875P_DERRSYN, - &info->derrsyn); + &info->derrsyn); } } -static int i82875p_process_error_info (struct mem_ctl_info *mci, +static int i82875p_process_error_info(struct mem_ctl_info *mci, struct i82875p_error_info *info, int handle_errors) { int row, multi_chan; @@ -251,13 +240,12 @@ static int i82875p_process_error_info (struct mem_ctl_info *mci, edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE"); else edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, - multi_chan ? (info->des & 0x1) : 0, - "i82875p CE"); + multi_chan ? (info->des & 0x1) : 0, + "i82875p CE"); return 1; } - static void i82875p_check(struct mem_ctl_info *mci) { struct i82875p_error_info info; @@ -267,7 +255,6 @@ static void i82875p_check(struct mem_ctl_info *mci) i82875p_process_error_info(mci, &info, 1); } - #ifdef CONFIG_PROC_FS extern int pci_proc_attach_device(struct pci_dev *); #endif @@ -281,7 +268,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) unsigned long last_cumul_size; struct pci_dev *ovrfl_pdev; void __iomem *ovrfl_window = NULL; - u32 drc; u32 drc_chan; /* Number of channels 0=1chan,1=2chan */ u32 nr_chans; @@ -289,7 +275,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) struct i82875p_error_info discard; debugf0("%s()\n", __func__); - ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); if (!ovrfl_pdev) { @@ -301,22 +286,23 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) */ pci_write_bits8(pdev, 0xf4, 0x2, 0x2); ovrfl_pdev = - pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0)); + pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0)); + if (!ovrfl_pdev) return -ENODEV; } + #ifdef CONFIG_PROC_FS if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) { i82875p_printk(KERN_ERR, - "%s(): Failed to attach overflow device\n", - __func__); + "%s(): Failed to attach overflow device\n", __func__); return -ENODEV; } -#endif /* CONFIG_PROC_FS */ +#endif + /* CONFIG_PROC_FS */ if (pci_enable_device(ovrfl_pdev)) { i82875p_printk(KERN_ERR, - "%s(): Failed to enable overflow device\n", - __func__); + "%s(): Failed to enable overflow device\n", __func__); return -ENODEV; } @@ -325,13 +311,14 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) goto fail0; #endif } + /* cache is irrelevant for PCI bus reads/writes */ ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0), - pci_resource_len(ovrfl_pdev, 0)); + pci_resource_len(ovrfl_pdev, 0)); if (!ovrfl_window) { i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n", - __func__); + __func__); goto fail1; } @@ -339,10 +326,10 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) drc = readl(ovrfl_window + I82875P_DRC); drc_chan = ((drc >> 21) & 0x1); nr_chans = drc_chan + 1; - drc_ddim = (drc >> 18) & 0x1; + drc_ddim = (drc >> 18) & 0x1; mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans), - nr_chans); + nr_chans); if (!mci) { rc = -ENOMEM; @@ -350,10 +337,8 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) } debugf3("%s(): init mci\n", __func__); - mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_DDR; - mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_UNKNOWN; /* adjust FLAGS */ @@ -363,9 +348,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) mci->ctl_name = i82875p_devs[dev_idx].ctl_name; mci->edac_check = i82875p_check; mci->ctl_page_to_phys = NULL; - debugf3("%s(): init pvt\n", __func__); - pvt = (struct i82875p_pvt *) mci->pvt_info; pvt->ovrfl_pdev = ovrfl_pdev; pvt->ovrfl_window = ovrfl_window; @@ -385,6 +368,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, cumul_size); + if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -392,7 +376,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) csrow->last_page = cumul_size - 1; csrow->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; - csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ + csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ csrow->mtype = MEM_DDR; csrow->dtype = DEV_UNKNOWN; csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE; @@ -426,25 +410,26 @@ fail0: return rc; } - /* returns count (>= 0), or negative on error */ static int __devinit i82875p_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { int rc; debugf0("%s()\n", __func__); - i82875p_printk(KERN_INFO, "i82875p init one\n"); - if(pci_enable_device(pdev) < 0) + + if (pci_enable_device(pdev) < 0) return -EIO; + rc = i82875p_probe1(pdev, ent->driver_data); + if (mci_pdev == NULL) mci_pdev = pci_dev_get(pdev); + return rc; } - static void __devexit i82875p_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -456,6 +441,7 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev) return; pvt = (struct i82875p_pvt *) mci->pvt_info; + if (pvt->ovrfl_window) iounmap(pvt->ovrfl_window); @@ -470,16 +456,18 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } - static const struct pci_device_id i82875p_pci_tbl[] __devinitdata = { - {PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - I82875P}, - {0,} /* 0 terminated list. */ + { + PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + I82875P + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl); - static struct pci_driver i82875p_driver = { .name = EDAC_MOD_STR, .probe = i82875p_init_one, @@ -487,31 +475,35 @@ static struct pci_driver i82875p_driver = { .id_table = i82875p_pci_tbl, }; - static int __init i82875p_init(void) { int pci_rc; debugf3("%s()\n", __func__); pci_rc = pci_register_driver(&i82875p_driver); + if (pci_rc < 0) goto fail0; + if (mci_pdev == NULL) { - mci_pdev = - pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82875_0, NULL); + mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82875_0, NULL); + if (!mci_pdev) { debugf0("875p pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } + pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl); + if (pci_rc < 0) { debugf0("875p init fail\n"); pci_rc = -ENODEV; goto fail1; } } + return 0; fail1: @@ -524,23 +516,21 @@ fail0: return pci_rc; } - static void __exit i82875p_exit(void) { debugf3("%s()\n", __func__); pci_unregister_driver(&i82875p_driver); + if (!i82875p_registered) { i82875p_remove_one(mci_pdev); pci_dev_put(mci_pdev); } } - module_init(i82875p_init); module_exit(i82875p_exit); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh"); MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers"); diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 5966916d02bd..2c29fafe67c7 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -18,19 +18,16 @@ #include #include #include - #include #include - #include - #include "edac_mc.h" #define r82600_printk(level, fmt, arg...) \ - edac_printk(level, "r82600", fmt, ##arg) + edac_printk(level, "r82600", fmt, ##arg) #define r82600_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg) + edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg) /* Radisys say "The 82600 integrates a main memory SDRAM controller that * supports up to four banks of memory. The four banks can support a mix of @@ -132,10 +129,8 @@ struct r82600_error_info { u32 eapr; }; - static unsigned int disable_hardware_scrub = 0; - static void r82600_get_error_info (struct mem_ctl_info *mci, struct r82600_error_info *info) { @@ -144,17 +139,16 @@ static void r82600_get_error_info (struct mem_ctl_info *mci, if (info->eapr & BIT(0)) /* Clear error to allow next error to be reported [p.62] */ pci_write_bits32(mci->pdev, R82600_EAP, - ((u32) BIT(0) & (u32) BIT(1)), - ((u32) BIT(0) & (u32) BIT(1))); + ((u32) BIT(0) & (u32) BIT(1)), + ((u32) BIT(0) & (u32) BIT(1))); if (info->eapr & BIT(1)) /* Clear error to allow next error to be reported [p.62] */ pci_write_bits32(mci->pdev, R82600_EAP, - ((u32) BIT(0) & (u32) BIT(1)), - ((u32) BIT(0) & (u32) BIT(1))); + ((u32) BIT(0) & (u32) BIT(1)), + ((u32) BIT(0) & (u32) BIT(1))); } - static int r82600_process_error_info (struct mem_ctl_info *mci, struct r82600_error_info *info, int handle_errors) { @@ -173,26 +167,25 @@ static int r82600_process_error_info (struct mem_ctl_info *mci, * granularity (upper 19 bits only) */ page = eapaddr >> PAGE_SHIFT; - if (info->eapr & BIT(0)) { /* CE? */ + if (info->eapr & BIT(0)) { /* CE? */ error_found = 1; if (handle_errors) - edac_mc_handle_ce( - mci, page, 0, /* not avail */ - syndrome, - edac_mc_find_csrow_by_page(mci, page), - 0, /* channel */ - mci->ctl_name); + edac_mc_handle_ce(mci, page, 0, /* not avail */ + syndrome, + edac_mc_find_csrow_by_page(mci, page), + 0, /* channel */ + mci->ctl_name); } - if (info->eapr & BIT(1)) { /* UE? */ + if (info->eapr & BIT(1)) { /* UE? */ error_found = 1; if (handle_errors) /* 82600 doesn't give enough info */ edac_mc_handle_ue(mci, page, 0, - edac_mc_find_csrow_by_page(mci, page), - mci->ctl_name); + edac_mc_find_csrow_by_page(mci, page), + mci->ctl_name); } return error_found; @@ -222,21 +215,15 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) struct r82600_error_info discard; debugf0("%s()\n", __func__); - - pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); pci_read_config_dword(pdev, R82600_EAP, &eapr); - ecc_on = dramcr & BIT(5); reg_sdram = dramcr & BIT(4); scrub_disabled = eapr & BIT(31); sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); - debugf2("%s(): sdram refresh rate = %#0x\n", __func__, sdram_refresh_rate); - debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr); - mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS); if (mci == NULL) { @@ -245,19 +232,19 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) } debugf0("%s(): mci = %p\n", __func__, mci); - mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; - mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; - /* FIXME try to work out if the chip leads have been * - * used for COM2 instead on this board? [MA6?] MAYBE: */ + /* FIXME try to work out if the chip leads have been used for COM2 + * instead on this board? [MA6?] MAYBE: + */ /* On the R82600, the pins for memory bits 72:65 - i.e. the * * EC bits are shared with the pins for COM2 (!), so if COM2 * * is enabled, we assume COM2 is wired up, and thus no EDAC * * is possible. */ mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; + if (ecc_on) { if (scrub_disabled) debugf3("%s(): mci = %p - Scrubbing disabled! EAP: " @@ -295,7 +282,6 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) continue; row_base = row_high_limit_last; - csrow->first_page = row_base >> PAGE_SHIFT; csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1; csrow->nr_pages = csrow->last_page - csrow->first_page + 1; @@ -338,7 +324,7 @@ fail: /* returns count (>= 0), or negative on error */ static int __devinit r82600_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { debugf0("%s()\n", __func__); @@ -346,7 +332,6 @@ static int __devinit r82600_init_one(struct pci_dev *pdev, return r82600_probe1(pdev, ent->driver_data); } - static void __devexit r82600_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -359,15 +344,17 @@ static void __devexit r82600_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } - static const struct pci_device_id r82600_pci_tbl[] __devinitdata = { - {PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)}, - {0,} /* 0 terminated list. */ + { + PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID) + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, r82600_pci_tbl); - static struct pci_driver r82600_driver = { .name = EDAC_MOD_STR, .probe = r82600_init_one, @@ -375,26 +362,22 @@ static struct pci_driver r82600_driver = { .id_table = r82600_pci_tbl, }; - static int __init r82600_init(void) { return pci_register_driver(&r82600_driver); } - static void __exit r82600_exit(void) { pci_unregister_driver(&r82600_driver); } - module_init(r82600_init); module_exit(r82600_exit); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tim Small - WPAD Ltd. " - "on behalf of EADS Astrium"); + "on behalf of EADS Astrium"); MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers"); module_param(disable_hardware_scrub, bool, 0644); -- cgit v1.2.3-59-g8ed1b From e009356f738634d8a137cca35503b9b33322c858 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:54 -0800 Subject: [PATCH] EDAC: use sysbus_message in e752x code Patch from Dave Jiang : Fix EDAC e752x driver so it outputs sysbus-specific error message when sysbus error detected. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/e752x_edac.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 265cce72497c..66572c5323ad 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -472,8 +472,7 @@ static inline void membuf_error(u8 errors, int *error_found, int handle_error) do_membuf_error(errors); } -#if 0 -char *sysbus_message[10] = { +static char *sysbus_message[10] = { "Addr or Request Parity", "Data Strobe Glitch", "Addr Strobe Glitch", @@ -484,7 +483,6 @@ char *sysbus_message[10] = { "Memory Parity", "IO Subsystem Parity" }; -#endif /* 0 */ static void do_sysbus_error(int fatal, u32 errors) { @@ -493,7 +491,7 @@ static void do_sysbus_error(int fatal, u32 errors) for (i = 0; i < 10; i++) { if (errors & (1 << i)) e752x_printk(KERN_WARNING, "%sError System Bus %s\n", - fatal_message[fatal], global_message[i]); + fatal_message[fatal], sysbus_message[i]); } } -- cgit v1.2.3-59-g8ed1b From 9110540f7f2bbcc3577d2580a696fbb7af68c892 Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Sun, 26 Mar 2006 01:38:55 -0800 Subject: [PATCH] EDAC: use EXPORT_SYMBOL_GPL Change all instances of EXPORT_SYMBOL() in the core EDAC module to EXPORT_SYMBOL_GPL(). Signed-off-by: David S. Peterson Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/edac_mc.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index bb3460457fa3..905f58ba8e16 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -45,7 +45,7 @@ #ifdef CONFIG_EDAC_DEBUG /* Values of 0 to 4 will generate output */ int edac_debug_level = 1; -EXPORT_SYMBOL(edac_debug_level); +EXPORT_SYMBOL_GPL(edac_debug_level); #endif /* EDAC Controls, setable by module parameter, and sysfs */ @@ -1211,7 +1211,7 @@ void edac_mc_dump_channel(struct channel_info *chan) debugf4("\tchannel->label = '%s'\n", chan->label); debugf4("\tchannel->csrow = %p\n\n", chan->csrow); } -EXPORT_SYMBOL(edac_mc_dump_channel); +EXPORT_SYMBOL_GPL(edac_mc_dump_channel); void edac_mc_dump_csrow(struct csrow_info *csrow) { @@ -1227,7 +1227,7 @@ void edac_mc_dump_csrow(struct csrow_info *csrow) debugf4("\tcsrow->channels = %p\n", csrow->channels); debugf4("\tcsrow->mci = %p\n\n", csrow->mci); } -EXPORT_SYMBOL(edac_mc_dump_csrow); +EXPORT_SYMBOL_GPL(edac_mc_dump_csrow); void edac_mc_dump_mci(struct mem_ctl_info *mci) { @@ -1243,7 +1243,7 @@ void edac_mc_dump_mci(struct mem_ctl_info *mci) mci->mod_name, mci->ctl_name); debugf3("\tpvt_info = %p\n\n", mci->pvt_info); } -EXPORT_SYMBOL(edac_mc_dump_mci); +EXPORT_SYMBOL_GPL(edac_mc_dump_mci); #endif /* CONFIG_EDAC_DEBUG */ @@ -1351,7 +1351,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, return mci; } -EXPORT_SYMBOL(edac_mc_alloc); +EXPORT_SYMBOL_GPL(edac_mc_alloc); /** * edac_mc_free: Free a previously allocated 'mci' structure @@ -1361,7 +1361,7 @@ void edac_mc_free(struct mem_ctl_info *mci) { kfree(mci); } -EXPORT_SYMBOL(edac_mc_free); +EXPORT_SYMBOL_GPL(edac_mc_free); static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev) { @@ -1499,7 +1499,7 @@ fail0: up(&mem_ctls_mutex); return 1; } -EXPORT_SYMBOL(edac_mc_add_mc); +EXPORT_SYMBOL_GPL(edac_mc_add_mc); /** * edac_mc_del_mc: Remove sysfs entries for specified mci structure and @@ -1528,7 +1528,7 @@ struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev) mci->mod_name, mci->ctl_name, pci_name(mci->pdev)); return mci; } -EXPORT_SYMBOL(edac_mc_del_mc); +EXPORT_SYMBOL_GPL(edac_mc_del_mc); void edac_mc_scrub_block(unsigned long page, unsigned long offset, u32 size) { @@ -1559,7 +1559,7 @@ void edac_mc_scrub_block(unsigned long page, unsigned long offset, u32 size) if (PageHighMem(pg)) local_irq_restore(flags); } -EXPORT_SYMBOL(edac_mc_scrub_block); +EXPORT_SYMBOL_GPL(edac_mc_scrub_block); /* FIXME - should return -1 */ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) @@ -1597,7 +1597,7 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) return row; } -EXPORT_SYMBOL(edac_mc_find_csrow_by_page); +EXPORT_SYMBOL_GPL(edac_mc_find_csrow_by_page); /* FIXME - setable log (warning/emerg) levels */ /* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */ @@ -1660,7 +1660,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, mci->csrows[row].grain); } } -EXPORT_SYMBOL(edac_mc_handle_ce); +EXPORT_SYMBOL_GPL(edac_mc_handle_ce); void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg) { @@ -1671,7 +1671,7 @@ void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg) mci->ce_noinfo_count++; mci->ce_count++; } -EXPORT_SYMBOL(edac_mc_handle_ce_no_info); +EXPORT_SYMBOL_GPL(edac_mc_handle_ce_no_info); void edac_mc_handle_ue(struct mem_ctl_info *mci, unsigned long page_frame_number, unsigned long offset_in_page, @@ -1724,7 +1724,7 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci, mci->ue_count++; mci->csrows[row].ue_count++; } -EXPORT_SYMBOL(edac_mc_handle_ue); +EXPORT_SYMBOL_GPL(edac_mc_handle_ue); void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) { @@ -1737,7 +1737,7 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) mci->ue_noinfo_count++; mci->ue_count++; } -EXPORT_SYMBOL(edac_mc_handle_ue_no_info); +EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); #ifdef CONFIG_PCI -- cgit v1.2.3-59-g8ed1b From 0b28002fdf2d5b6ce3135a544c04940a16c5b0ba Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 26 Mar 2006 01:38:58 -0800 Subject: [PATCH] more s/fucn/func/ typo fixes s/fucntion/function/ typo fixes Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 2 +- arch/m68k/bvme6000/config.c | 2 +- arch/s390/crypto/crypt_s390_query.c | 2 +- drivers/acpi/processor_core.c | 2 +- drivers/net/sis900.c | 4 ++-- include/linux/gameport.h | 4 ++-- include/linux/serio.h | 6 +++--- 7 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 6dc9d9f622ca..6feef9e82b63 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -2836,7 +2836,7 @@ struct _snd_pcm_runtime { Note that this callback became non-atomic since the recent version. - You can use schedule-related fucntions safely in this callback now. + You can use schedule-related functions safely in this callback now. diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c index 3ffc84f9c291..c90cb5fcc8ef 100644 --- a/arch/m68k/bvme6000/config.c +++ b/arch/m68k/bvme6000/config.c @@ -142,7 +142,7 @@ void __init config_bvme6000(void) /* Now do the PIT configuration */ pit->pgcr = 0x00; /* Unidirectional 8 bit, no handshake for now */ - pit->psrr = 0x18; /* PIACK and PIRQ fucntions enabled */ + pit->psrr = 0x18; /* PIACK and PIRQ functions enabled */ pit->pacr = 0x00; /* Sub Mode 00, H2 i/p, no DMA */ pit->padr = 0x00; /* Just to be tidy! */ pit->paddr = 0x00; /* All inputs for now (safest) */ diff --git a/arch/s390/crypto/crypt_s390_query.c b/arch/s390/crypto/crypt_s390_query.c index def02bdc44a4..54fb11d7fadd 100644 --- a/arch/s390/crypto/crypt_s390_query.c +++ b/arch/s390/crypto/crypt_s390_query.c @@ -55,7 +55,7 @@ static void query_available_functions(void) printk(KERN_INFO "KMC_AES_256: %d\n", crypt_s390_func_available(KMC_AES_256_ENCRYPT)); - /* query available KIMD fucntions */ + /* query available KIMD functions */ printk(KERN_INFO "KIMD_QUERY: %d\n", crypt_s390_func_available(KIMD_QUERY)); printk(KERN_INFO "KIMD_SHA_1: %d\n", diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 99a3a28594da..713b763884a9 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -246,7 +246,7 @@ static int acpi_processor_errata(struct acpi_processor *pr) } /* -------------------------------------------------------------------------- - Common ACPI processor fucntions + Common ACPI processor functions -------------------------------------------------------------------------- */ /* diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 253440a98022..8429ceb01389 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -1693,7 +1693,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance, struct pt_regs * * Process receive interrupt events, * put buffer to higher layer and refill buffer pool - * Note: This fucntion is called by interrupt handler, + * Note: This function is called by interrupt handler, * don't do "too much" work here */ @@ -1840,7 +1840,7 @@ static int sis900_rx(struct net_device *net_dev) * * Check for error condition and free socket buffer etc * schedule for more transmission as needed - * Note: This fucntion is called by interrupt handler, + * Note: This function is called by interrupt handler, * don't do "too much" work here */ diff --git a/include/linux/gameport.h b/include/linux/gameport.h index 2401dea2b867..9c8e6da2393b 100644 --- a/include/linux/gameport.h +++ b/include/linux/gameport.h @@ -119,7 +119,7 @@ static inline void gameport_set_name(struct gameport *gameport, const char *name } /* - * Use the following fucntions to manipulate gameport's per-port + * Use the following functions to manipulate gameport's per-port * driver-specific data. */ static inline void *gameport_get_drvdata(struct gameport *gameport) @@ -133,7 +133,7 @@ static inline void gameport_set_drvdata(struct gameport *gameport, void *data) } /* - * Use the following fucntions to pin gameport's driver in process context + * Use the following functions to pin gameport's driver in process context */ static inline int gameport_pin_driver(struct gameport *gameport) { diff --git a/include/linux/serio.h b/include/linux/serio.h index aa4d6493a034..690aabca8ed0 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h @@ -119,7 +119,7 @@ static inline void serio_cleanup(struct serio *serio) } /* - * Use the following fucntions to manipulate serio's per-port + * Use the following functions to manipulate serio's per-port * driver-specific data. */ static inline void *serio_get_drvdata(struct serio *serio) @@ -133,7 +133,7 @@ static inline void serio_set_drvdata(struct serio *serio, void *data) } /* - * Use the following fucntions to protect critical sections in + * Use the following functions to protect critical sections in * driver code from port's interrupt handler */ static inline void serio_pause_rx(struct serio *serio) @@ -147,7 +147,7 @@ static inline void serio_continue_rx(struct serio *serio) } /* - * Use the following fucntions to pin serio's driver in process context + * Use the following functions to pin serio's driver in process context */ static inline int serio_pin_driver(struct serio *serio) { -- cgit v1.2.3-59-g8ed1b From 37d54111c133bea05fbae9dfe6d3d61a1b19c09b Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 26 Mar 2006 01:39:56 -0800 Subject: [PATCH] bitops: hweight() related cleanup By defining generic hweight*() routines - hweight64() will be defined on all architectures - hweight_long() will use architecture optimized hweight32() or hweight64() I found two possible cleanups by these reasons. Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ieee1394/highlevel.c | 3 +-- lib/bitmap.c | 19 ++----------------- 2 files changed, 3 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 734b121a0554..491e6032bdec 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -306,8 +306,7 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, u64 align_mask = ~(alignment - 1); if ((alignment & 3) || (alignment > 0x800000000000ULL) || - ((hweight32(alignment >> 32) + - hweight32(alignment & 0xffffffff) != 1))) { + (hweight64(alignment) != 1)) { HPSB_ERR("%s called with invalid alignment: 0x%048llx", __FUNCTION__, (unsigned long long)alignment); return retval; diff --git a/lib/bitmap.c b/lib/bitmap.c index 8acab0e176ef..ed2ae3b0cd06 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -253,33 +253,18 @@ int __bitmap_subset(const unsigned long *bitmap1, } EXPORT_SYMBOL(__bitmap_subset); -#if BITS_PER_LONG == 32 int __bitmap_weight(const unsigned long *bitmap, int bits) { int k, w = 0, lim = bits/BITS_PER_LONG; for (k = 0; k < lim; k++) - w += hweight32(bitmap[k]); + w += hweight_long(bitmap[k]); if (bits % BITS_PER_LONG) - w += hweight32(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); + w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); return w; } -#else -int __bitmap_weight(const unsigned long *bitmap, int bits) -{ - int k, w = 0, lim = bits/BITS_PER_LONG; - - for (k = 0; k < lim; k++) - w += hweight64(bitmap[k]); - - if (bits % BITS_PER_LONG) - w += hweight64(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); - - return w; -} -#endif EXPORT_SYMBOL(__bitmap_weight); /* -- cgit v1.2.3-59-g8ed1b From 8917f6f70b01ac6e4d534f8a387900caec11bf54 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 26 Mar 2006 19:15:03 +0200 Subject: Kconfig help: MTD_JEDECPROBE already supports Intel Intel chips are already supported. Signed-off-by: Adrian Bunk Acked-by: David Woodhouse --- drivers/mtd/chips/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 205bb7083335..0f6bb2e625d8 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig @@ -25,9 +25,8 @@ config MTD_JEDECPROBE compatible with the Common Flash Interface, but will use the common CFI-targetted flash drivers for any chips which are identified which are in fact compatible in all but the probe method. This actually - covers most AMD/Fujitsu-compatible chips, and will shortly cover also - non-CFI Intel chips (that code is in MTD CVS and should shortly be sent - for inclusion in Linus' tree) + covers most AMD/Fujitsu-compatible chips and also non-CFI + Intel chips. config MTD_GEN_PROBE tristate -- cgit v1.2.3-59-g8ed1b From e9415777b1cd0eaf4d1d3d61772f0e6d5c2551ad Mon Sep 17 00:00:00 2001 From: Bastien Roucaries Date: Sun, 26 Mar 2006 19:18:07 +0200 Subject: drivers/char/ftape/lowlevel/fdc-io.c: Correct a comment This patch correct a comment about cli(). Signed-off-by: Bastien Roucaries Signed-off-by: Adrian Bunk --- drivers/char/ftape/lowlevel/fdc-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c index b2e0928e8428..093fdf98b19a 100644 --- a/drivers/char/ftape/lowlevel/fdc-io.c +++ b/drivers/char/ftape/lowlevel/fdc-io.c @@ -607,7 +607,7 @@ void fdc_reset(void) fdc_mode = fdc_idle; - /* maybe the cli()/sti() pair is not necessary, BUT: + /* maybe the spin_lock_irq* pair is not necessary, BUT: * the following line MUST be here. Otherwise fdc_interrupt_wait() * won't wait. Note that fdc_reset() is called from * ftape_dumb_stop() when the fdc is busy transferring data. In this -- cgit v1.2.3-59-g8ed1b From 8faaea3faa5ed0b2a15afb7b4e57ce0cd8dbe4ef Mon Sep 17 00:00:00 2001 From: Freddy Spierenburg Date: Sun, 26 Mar 2006 21:22:51 +0100 Subject: [SERIAL] Small time UART configuration fix for AU1100 processor The AU1100 processor does not have an internal UART2. Only UART0, UART1 and UART3 exist. This patch removes the non existing UART2 and replaces it with a descriptive comment. Signed-off-by: Freddy Spierenburg Signed-off-by: Russell King --- drivers/serial/8250_au1x00.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c index 8d8d7a70d03e..3d1bfd07208d 100644 --- a/drivers/serial/8250_au1x00.c +++ b/drivers/serial/8250_au1x00.c @@ -51,7 +51,7 @@ static struct plat_serial8250_port au1x00_data[] = { #elif defined(CONFIG_SOC_AU1100) PORT(UART0_ADDR, AU1100_UART0_INT), PORT(UART1_ADDR, AU1100_UART1_INT), - PORT(UART2_ADDR, AU1100_UART2_INT), + /* The internal UART2 does not exist on the AU1100 processor. */ PORT(UART3_ADDR, AU1100_UART3_INT), #elif defined(CONFIG_SOC_AU1550) PORT(UART0_ADDR, AU1550_UART0_INT), -- cgit v1.2.3-59-g8ed1b From 335bd9dff31d042b773591933d3ee5bd62d5ea27 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 26 Mar 2006 21:25:57 +0100 Subject: [SERIAL] Remove obsoleted au1x00_uart driver As announced in feature-removal-schedule.txt. Signed-off-by: Ralf Baechle Signed-off-by: Russell King --- arch/mips/au1000/common/setup.c | 2 +- drivers/serial/Kconfig | 16 - drivers/serial/Makefile | 1 - drivers/serial/au1x00_uart.c | 1287 --------------------------------------- include/asm-mips/serial.h | 85 +-- 5 files changed, 2 insertions(+), 1389 deletions(-) delete mode 100644 drivers/serial/au1x00_uart.c (limited to 'drivers') diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c index 1080558c8100..307e98c29ddc 100644 --- a/arch/mips/au1000/common/setup.c +++ b/arch/mips/au1000/common/setup.c @@ -94,7 +94,7 @@ void __init plat_setup(void) argptr = prom_getcmdline(); -#if defined(CONFIG_SERIAL_AU1X00_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) +#ifdef CONFIG_SERIAL_8250_CONSOLE if ((argptr = strstr(argptr, "console=")) == NULL) { argptr = prom_getcmdline(); strcat(argptr, " console=ttyS0,115200"); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ceb3697bf84d..fe0d8b8e91c8 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -620,22 +620,6 @@ config SERIAL_SH_SCI_CONSOLE depends on SERIAL_SH_SCI=y select SERIAL_CORE_CONSOLE -config SERIAL_AU1X00 - bool "Enable Au1x00 UART Support" - depends on MIPS && SOC_AU1X00 - select SERIAL_CORE - help - If you have an Alchemy AU1X00 processor (MIPS based) and you want - to use serial ports, say Y. Otherwise, say N. - -config SERIAL_AU1X00_CONSOLE - bool "Enable Au1x00 serial console" - depends on SERIAL_AU1X00 - select SERIAL_CORE_CONSOLE - help - If you have an Alchemy AU1X00 processor (MIPS based) and you want - to use a console on a serial port, say Y. Otherwise, say N. - config SERIAL_CORE tristate diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index a3a4323d9c86..d2b4c214876b 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -41,7 +41,6 @@ obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o obj-$(CONFIG_V850E_UART) += v850e_uart.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o -obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o obj-$(CONFIG_SERIAL_DZ) += dz.o obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c deleted file mode 100644 index 948880ac5878..000000000000 --- a/drivers/serial/au1x00_uart.c +++ /dev/null @@ -1,1287 +0,0 @@ -/* - * Driver for 8250/16550-type serial ports - * - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. - * - * Copyright (C) 2001 Russell King. - * - * 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. - * - * A note about mapbase / membase - * - * mapbase is the physical address of the IO port. Currently, we don't - * support this very well, and it may well be dropped from this driver - * in future. As such, mapbase should be NULL. - * - * membase is an 'ioremapped' cookie. This is compatible with the old - * serial.c driver, and is currently the preferred form. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#if defined(CONFIG_SERIAL_AU1X00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include -#include "8250.h" - -/* - * Debugging. - */ -#if 0 -#define DEBUG_AUTOCONF(fmt...) printk(fmt) -#else -#define DEBUG_AUTOCONF(fmt...) do { } while (0) -#endif - -#if 0 -#define DEBUG_INTR(fmt...) printk(fmt) -#else -#define DEBUG_INTR(fmt...) do { } while (0) -#endif - -#define PASS_LIMIT 256 - -/* - * We default to IRQ0 for the "no irq" hack. Some - * machine types want others as well - they're free - * to redefine this in their header file. - */ -#define is_real_interrupt(irq) ((irq) != 0) - -static struct old_serial_port old_serial_port[] = { - { .baud_base = 0, - .iomem_base = (u8 *)UART0_ADDR, - .irq = AU1000_UART0_INT, - .flags = STD_COM_FLAGS, - .iomem_reg_shift = 2, - }, { - .baud_base = 0, - .iomem_base = (u8 *)UART1_ADDR, - .irq = AU1000_UART1_INT, - .flags = STD_COM_FLAGS, - .iomem_reg_shift = 2 - }, { - .baud_base = 0, - .iomem_base = (u8 *)UART2_ADDR, - .irq = AU1000_UART2_INT, - .flags = STD_COM_FLAGS, - .iomem_reg_shift = 2 - }, { - .baud_base = 0, - .iomem_base = (u8 *)UART3_ADDR, - .irq = AU1000_UART3_INT, - .flags = STD_COM_FLAGS, - .iomem_reg_shift = 2 - } -}; - -#define UART_NR ARRAY_SIZE(old_serial_port) - -struct uart_8250_port { - struct uart_port port; - struct timer_list timer; /* "no irq" timer */ - struct list_head list; /* ports on this IRQ */ - unsigned short rev; - unsigned char acr; - unsigned char ier; - unsigned char lcr; - unsigned char mcr_mask; /* mask of user bits */ - unsigned char mcr_force; /* mask of forced bits */ - unsigned char lsr_break_flag; - - /* - * We provide a per-port pm hook. - */ - void (*pm)(struct uart_port *port, - unsigned int state, unsigned int old); -}; - -struct irq_info { - spinlock_t lock; - struct list_head *head; -}; - -static struct irq_info irq_lists[NR_IRQS]; - -/* - * Here we define the default xmit fifo size used for each type of UART. - */ -static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = { - { "unknown", 1, 0 }, - { "8250", 1, 0 }, - { "16450", 1, 0 }, - { "16550", 1, 0 }, - /* PORT_16550A */ - { "AU1X00_UART",16, UART_CLEAR_FIFO | UART_USE_FIFO }, -}; - -static unsigned int serial_in(struct uart_8250_port *up, int offset) -{ - return au_readl((unsigned long)up->port.membase + offset); -} - -static void serial_out(struct uart_8250_port *up, int offset, int value) -{ - au_writel(value, (unsigned long)up->port.membase + offset); -} - -#define serial_inp(up, offset) serial_in(up, offset) -#define serial_outp(up, offset, value) serial_out(up, offset, value) - -/* - * This routine is called by rs_init() to initialize a specific serial - * port. It determines what type of UART chip this serial port is - * using: 8250, 16450, 16550, 16550A. The important question is - * whether or not this UART is a 16550A or not, since this will - * determine whether or not we can use its FIFO features or not. - */ -static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) -{ - unsigned char save_lcr, save_mcr; - unsigned long flags; - - if (!up->port.iobase && !up->port.mapbase && !up->port.membase) - return; - - DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%08lx): ", - up->port.line, up->port.iobase, up->port.membase); - - /* - * We really do need global IRQs disabled here - we're going to - * be frobbing the chips IRQ enable register to see if it exists. - */ - spin_lock_irqsave(&up->port.lock, flags); -// save_flags(flags); cli(); - - save_mcr = serial_in(up, UART_MCR); - save_lcr = serial_in(up, UART_LCR); - - up->port.type = PORT_16550A; - serial_outp(up, UART_LCR, save_lcr); - - up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; - - if (up->port.type == PORT_UNKNOWN) - goto out; - - /* - * Reset the UART. - */ - serial_outp(up, UART_MCR, save_mcr); - serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT)); - serial_outp(up, UART_FCR, 0); - (void)serial_in(up, UART_RX); - serial_outp(up, UART_IER, 0); - - out: - spin_unlock_irqrestore(&up->port.lock, flags); -// restore_flags(flags); - DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name); -} - -static void serial8250_stop_tx(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - - if (up->ier & UART_IER_THRI) { - up->ier &= ~UART_IER_THRI; - serial_out(up, UART_IER, up->ier); - } -} - -static void serial8250_start_tx(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - - if (!(up->ier & UART_IER_THRI)) { - up->ier |= UART_IER_THRI; - serial_out(up, UART_IER, up->ier); - } -} - -static void serial8250_stop_rx(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - - up->ier &= ~UART_IER_RLSI; - up->port.read_status_mask &= ~UART_LSR_DR; - serial_out(up, UART_IER, up->ier); -} - -static void serial8250_enable_ms(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - - up->ier |= UART_IER_MSI; - serial_out(up, UART_IER, up->ier); -} - -static void -receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) -{ - struct tty_struct *tty = up->port.info->tty; - unsigned char ch, flag; - int max_count = 256; - - do { - ch = serial_inp(up, UART_RX); - flag = TTY_NORMAL; - up->port.icount.rx++; - - if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | - UART_LSR_FE | UART_LSR_OE))) { - /* - * For statistics only - */ - if (*status & UART_LSR_BI) { - *status &= ~(UART_LSR_FE | UART_LSR_PE); - up->port.icount.brk++; - /* - * We do the SysRQ and SAK checking - * here because otherwise the break - * may get masked by ignore_status_mask - * or read_status_mask. - */ - if (uart_handle_break(&up->port)) - goto ignore_char; - } else if (*status & UART_LSR_PE) - up->port.icount.parity++; - else if (*status & UART_LSR_FE) - up->port.icount.frame++; - if (*status & UART_LSR_OE) - up->port.icount.overrun++; - - /* - * Mask off conditions which should be ingored. - */ - *status &= up->port.read_status_mask; - -#ifdef CONFIG_SERIAL_AU1X00_CONSOLE - if (up->port.line == up->port.cons->index) { - /* Recover the break flag from console xmit */ - *status |= up->lsr_break_flag; - up->lsr_break_flag = 0; - } -#endif - if (*status & UART_LSR_BI) { - DEBUG_INTR("handling break...."); - flag = TTY_BREAK; - } else if (*status & UART_LSR_PE) - flag = TTY_PARITY; - else if (*status & UART_LSR_FE) - flag = TTY_FRAME; - } - if (uart_handle_sysrq_char(&up->port, ch, regs)) - goto ignore_char; - if ((*status & up->port.ignore_status_mask) == 0) - tty_insert_flip_char(tty, ch, flag); - if (*status & UART_LSR_OE) - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } - ignore_char: - *status = serial_inp(up, UART_LSR); - } while ((*status & UART_LSR_DR) && (max_count-- > 0)); - spin_unlock(&up->port.lock); - tty_flip_buffer_push(tty); - spin_lock(&up->port.lock); -} - -static void transmit_chars(struct uart_8250_port *up) -{ - struct circ_buf *xmit = &up->port.info->xmit; - int count; - - if (up->port.x_char) { - serial_outp(up, UART_TX, up->port.x_char); - up->port.icount.tx++; - up->port.x_char = 0; - return; - } - if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { - serial8250_stop_tx(&up->port); - return; - } - - count = up->port.fifosize; - do { - serial_out(up, UART_TX, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - up->port.icount.tx++; - if (uart_circ_empty(xmit)) - break; - } while (--count > 0); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&up->port); - - DEBUG_INTR("THRE..."); - - if (uart_circ_empty(xmit)) - serial8250_stop_tx(&up->port); -} - -static void check_modem_status(struct uart_8250_port *up) -{ - int status; - - status = serial_in(up, UART_MSR); - - if ((status & UART_MSR_ANY_DELTA) == 0) - return; - - if (status & UART_MSR_TERI) - up->port.icount.rng++; - if (status & UART_MSR_DDSR) - up->port.icount.dsr++; - if (status & UART_MSR_DDCD) - uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); - if (status & UART_MSR_DCTS) - uart_handle_cts_change(&up->port, status & UART_MSR_CTS); - - wake_up_interruptible(&up->port.info->delta_msr_wait); -} - -/* - * This handles the interrupt from one port. - */ -static inline void -serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs) -{ - unsigned int status = serial_inp(up, UART_LSR); - - DEBUG_INTR("status = %x...", status); - - if (status & UART_LSR_DR) - receive_chars(up, &status, regs); - check_modem_status(up); - if (status & UART_LSR_THRE) - transmit_chars(up); -} - -/* - * This is the serial driver's interrupt routine. - * - * Arjan thinks the old way was overly complex, so it got simplified. - * Alan disagrees, saying that need the complexity to handle the weird - * nature of ISA shared interrupts. (This is a special exception.) - * - * In order to handle ISA shared interrupts properly, we need to check - * that all ports have been serviced, and therefore the ISA interrupt - * line has been de-asserted. - * - * This means we need to loop through all ports. checking that they - * don't have an interrupt pending. - */ -static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct irq_info *i = dev_id; - struct list_head *l, *end = NULL; - int pass_counter = 0; - - DEBUG_INTR("serial8250_interrupt(%d)...", irq); - - spin_lock(&i->lock); - - l = i->head; - do { - struct uart_8250_port *up; - unsigned int iir; - - up = list_entry(l, struct uart_8250_port, list); - - iir = serial_in(up, UART_IIR); - if (!(iir & UART_IIR_NO_INT)) { - spin_lock(&up->port.lock); - serial8250_handle_port(up, regs); - spin_unlock(&up->port.lock); - - end = NULL; - } else if (end == NULL) - end = l; - - l = l->next; - - if (l == i->head && pass_counter++ > PASS_LIMIT) { - /* If we hit this, we're dead. */ - printk(KERN_ERR "serial8250: too much work for " - "irq%d\n", irq); - break; - } - } while (l != end); - - spin_unlock(&i->lock); - - DEBUG_INTR("end.\n"); - /* FIXME! Was it really ours? */ - return IRQ_HANDLED; -} - -/* - * To support ISA shared interrupts, we need to have one interrupt - * handler that ensures that the IRQ line has been deasserted - * before returning. Failing to do this will result in the IRQ - * line being stuck active, and, since ISA irqs are edge triggered, - * no more IRQs will be seen. - */ -static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up) -{ - spin_lock_irq(&i->lock); - - if (!list_empty(i->head)) { - if (i->head == &up->list) - i->head = i->head->next; - list_del(&up->list); - } else { - BUG_ON(i->head != &up->list); - i->head = NULL; - } - - spin_unlock_irq(&i->lock); -} - -static int serial_link_irq_chain(struct uart_8250_port *up) -{ - struct irq_info *i = irq_lists + up->port.irq; - int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0; - - spin_lock_irq(&i->lock); - - if (i->head) { - list_add(&up->list, i->head); - spin_unlock_irq(&i->lock); - - ret = 0; - } else { - INIT_LIST_HEAD(&up->list); - i->head = &up->list; - spin_unlock_irq(&i->lock); - - ret = request_irq(up->port.irq, serial8250_interrupt, - irq_flags, "serial", i); - if (ret < 0) - serial_do_unlink(i, up); - } - - return ret; -} - -static void serial_unlink_irq_chain(struct uart_8250_port *up) -{ - struct irq_info *i = irq_lists + up->port.irq; - - BUG_ON(i->head == NULL); - - if (list_empty(i->head)) - free_irq(up->port.irq, i); - - serial_do_unlink(i, up); -} - -/* - * This function is used to handle ports that do not have an - * interrupt. This doesn't work very well for 16450's, but gives - * barely passable results for a 16550A. (Although at the expense - * of much CPU overhead). - */ -static void serial8250_timeout(unsigned long data) -{ - struct uart_8250_port *up = (struct uart_8250_port *)data; - unsigned int timeout; - unsigned int iir; - - iir = serial_in(up, UART_IIR); - if (!(iir & UART_IIR_NO_INT)) { - spin_lock(&up->port.lock); - serial8250_handle_port(up, NULL); - spin_unlock(&up->port.lock); - } - - timeout = up->port.timeout; - timeout = timeout > 6 ? (timeout / 2 - 2) : 1; - mod_timer(&up->timer, jiffies + timeout); -} - -static unsigned int serial8250_tx_empty(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned long flags; - unsigned int ret; - - spin_lock_irqsave(&up->port.lock, flags); - ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; - spin_unlock_irqrestore(&up->port.lock, flags); - - return ret; -} - -static unsigned int serial8250_get_mctrl(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned char status; - unsigned int ret; - - status = serial_in(up, UART_MSR); - - ret = 0; - if (status & UART_MSR_DCD) - ret |= TIOCM_CAR; - if (status & UART_MSR_RI) - ret |= TIOCM_RNG; - if (status & UART_MSR_DSR) - ret |= TIOCM_DSR; - if (status & UART_MSR_CTS) - ret |= TIOCM_CTS; - return ret; -} - -static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned char mcr = 0; - - if (mctrl & TIOCM_RTS) - mcr |= UART_MCR_RTS; - if (mctrl & TIOCM_DTR) - mcr |= UART_MCR_DTR; - if (mctrl & TIOCM_OUT1) - mcr |= UART_MCR_OUT1; - if (mctrl & TIOCM_OUT2) - mcr |= UART_MCR_OUT2; - if (mctrl & TIOCM_LOOP) - mcr |= UART_MCR_LOOP; - - mcr = (mcr & up->mcr_mask) | up->mcr_force; - - serial_out(up, UART_MCR, mcr); -} - -static void serial8250_break_ctl(struct uart_port *port, int break_state) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned long flags; - - spin_lock_irqsave(&up->port.lock, flags); - if (break_state == -1) - up->lcr |= UART_LCR_SBC; - else - up->lcr &= ~UART_LCR_SBC; - serial_out(up, UART_LCR, up->lcr); - spin_unlock_irqrestore(&up->port.lock, flags); -} - -static int serial8250_startup(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned long flags; - int retval; - - /* - * Clear the FIFO buffers and disable them. - * (they will be reeanbled in set_termios()) - */ - if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) { - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - serial_outp(up, UART_FCR, 0); - } - - /* - * Clear the interrupt registers. - */ - (void) serial_inp(up, UART_LSR); - (void) serial_inp(up, UART_RX); - (void) serial_inp(up, UART_IIR); - (void) serial_inp(up, UART_MSR); - - /* - * At this point, there's no way the LSR could still be 0xff; - * if it is, then bail out, because there's likely no UART - * here. - */ - if (!(up->port.flags & UPF_BUGGY_UART) && - (serial_inp(up, UART_LSR) == 0xff)) { - printk("ttyS%d: LSR safety check engaged!\n", up->port.line); - return -ENODEV; - } - - retval = serial_link_irq_chain(up); - if (retval) - return retval; - - /* - * Now, initialize the UART - */ - serial_outp(up, UART_LCR, UART_LCR_WLEN8); - - spin_lock_irqsave(&up->port.lock, flags); - if (up->port.flags & UPF_FOURPORT) { - if (!is_real_interrupt(up->port.irq)) - up->port.mctrl |= TIOCM_OUT1; - } else - /* - * Most PC uarts need OUT2 raised to enable interrupts. - */ - if (is_real_interrupt(up->port.irq)) - up->port.mctrl |= TIOCM_OUT2; - - serial8250_set_mctrl(&up->port, up->port.mctrl); - spin_unlock_irqrestore(&up->port.lock, flags); - - /* - * Finally, enable interrupts. Note: Modem status interrupts - * are set via set_termios(), which will be occurring imminently - * anyway, so we don't enable them here. - */ - up->ier = UART_IER_RLSI | UART_IER_RDI; - serial_outp(up, UART_IER, up->ier); - - if (up->port.flags & UPF_FOURPORT) { - unsigned int icp; - /* - * Enable interrupts on the AST Fourport board - */ - icp = (up->port.iobase & 0xfe0) | 0x01f; - outb_p(0x80, icp); - (void) inb_p(icp); - } - - /* - * And clear the interrupt registers again for luck. - */ - (void) serial_inp(up, UART_LSR); - (void) serial_inp(up, UART_RX); - (void) serial_inp(up, UART_IIR); - (void) serial_inp(up, UART_MSR); - - return 0; -} - -static void serial8250_shutdown(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned long flags; - - /* - * Disable interrupts from this port - */ - up->ier = 0; - serial_outp(up, UART_IER, 0); - - spin_lock_irqsave(&up->port.lock, flags); - if (up->port.flags & UPF_FOURPORT) { - /* reset interrupts on the AST Fourport board */ - inb((up->port.iobase & 0xfe0) | 0x1f); - up->port.mctrl |= TIOCM_OUT1; - } else - up->port.mctrl &= ~TIOCM_OUT2; - - serial8250_set_mctrl(&up->port, up->port.mctrl); - spin_unlock_irqrestore(&up->port.lock, flags); - - /* - * Disable break condition and FIFOs - */ - serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT); - serial_outp(up, UART_FCR, 0); - - /* - * Read data port to reset things, and then unlink from - * the IRQ chain. - */ - (void) serial_in(up, UART_RX); - - if (!is_real_interrupt(up->port.irq)) - del_timer_sync(&up->timer); - else - serial_unlink_irq_chain(up); -} - -static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud) -{ - unsigned int quot; - - /* - * Handle magic divisors for baud rates above baud_base on - * SMSC SuperIO chips. - */ - if ((port->flags & UPF_MAGIC_MULTIPLIER) && - baud == (port->uartclk/4)) - quot = 0x8001; - else if ((port->flags & UPF_MAGIC_MULTIPLIER) && - baud == (port->uartclk/8)) - quot = 0x8002; - else - quot = uart_get_divisor(port, baud); - - return quot; -} - -static void -serial8250_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned char cval, fcr = 0; - unsigned long flags; - unsigned int baud, quot; - - switch (termios->c_cflag & CSIZE) { - case CS5: - cval = UART_LCR_WLEN5; - break; - case CS6: - cval = UART_LCR_WLEN6; - break; - case CS7: - cval = UART_LCR_WLEN7; - break; - default: - case CS8: - cval = UART_LCR_WLEN8; - break; - } - - if (termios->c_cflag & CSTOPB) - cval |= UART_LCR_STOP; - if (termios->c_cflag & PARENB) - cval |= UART_LCR_PARITY; - if (!(termios->c_cflag & PARODD)) - cval |= UART_LCR_EPAR; -#ifdef CMSPAR - if (termios->c_cflag & CMSPAR) - cval |= UART_LCR_SPAR; -#endif - - /* - * Ask the core to calculate the divisor for us. - */ - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); - quot = serial8250_get_divisor(port, baud); - quot = 0x35; /* FIXME */ - - /* - * Work around a bug in the Oxford Semiconductor 952 rev B - * chip which causes it to seriously miscalculate baud rates - * when DLL is 0. - */ - if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 && - up->rev == 0x5201) - quot ++; - - if (uart_config[up->port.type].flags & UART_USE_FIFO) { - if (baud < 2400) - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_1; - else - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_8; - } - - /* - * Ok, we're now changing the port state. Do it with - * interrupts disabled. - */ - spin_lock_irqsave(&up->port.lock, flags); - - /* - * Update the per-port timeout. - */ - uart_update_timeout(port, termios->c_cflag, baud); - - up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; - if (termios->c_iflag & INPCK) - up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; - if (termios->c_iflag & (BRKINT | PARMRK)) - up->port.read_status_mask |= UART_LSR_BI; - - /* - * Characteres to ignore - */ - up->port.ignore_status_mask = 0; - if (termios->c_iflag & IGNPAR) - up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; - if (termios->c_iflag & IGNBRK) { - up->port.ignore_status_mask |= UART_LSR_BI; - /* - * If we're ignoring parity and break indicators, - * ignore overruns too (for real raw support). - */ - if (termios->c_iflag & IGNPAR) - up->port.ignore_status_mask |= UART_LSR_OE; - } - - /* - * ignore all characters if CREAD is not set - */ - if ((termios->c_cflag & CREAD) == 0) - up->port.ignore_status_mask |= UART_LSR_DR; - - /* - * CTS flow control flag and modem status interrupts - */ - up->ier &= ~UART_IER_MSI; - if (UART_ENABLE_MS(&up->port, termios->c_cflag)) - up->ier |= UART_IER_MSI; - - serial_out(up, UART_IER, up->ier); - serial_outp(up, 0x28, quot & 0xffff); - up->lcr = cval; /* Save LCR */ - if (up->port.type != PORT_16750) { - if (fcr & UART_FCR_ENABLE_FIFO) { - /* emulated UARTs (Lucent Venus 167x) need two steps */ - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); - } - serial_outp(up, UART_FCR, fcr); /* set fcr */ - } - spin_unlock_irqrestore(&up->port.lock, flags); -} - -static void -serial8250_pm(struct uart_port *port, unsigned int state, - unsigned int oldstate) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - if (state) { - /* sleep */ - if (up->pm) - up->pm(port, state, oldstate); - } else { - /* wake */ - if (up->pm) - up->pm(port, state, oldstate); - } -} - -/* - * Resource handling. This is complicated by the fact that resources - * depend on the port type. Maybe we should be claiming the standard - * 8250 ports, and then trying to get other resources as necessary? - */ -static int -serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res) -{ - unsigned int size = 8 << up->port.regshift; - int ret = 0; - - switch (up->port.iotype) { - case UPIO_MEM: - if (up->port.mapbase) { - *res = request_mem_region(up->port.mapbase, size, "serial"); - if (!*res) - ret = -EBUSY; - } - break; - - case UPIO_HUB6: - case UPIO_PORT: - *res = request_region(up->port.iobase, size, "serial"); - if (!*res) - ret = -EBUSY; - break; - } - return ret; -} - - -static void serial8250_release_port(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned long start, offset = 0, size = 0; - - size <<= up->port.regshift; - - switch (up->port.iotype) { - case UPIO_MEM: - if (up->port.mapbase) { - /* - * Unmap the area. - */ - iounmap(up->port.membase); - up->port.membase = NULL; - - start = up->port.mapbase; - - if (size) - release_mem_region(start + offset, size); - release_mem_region(start, 8 << up->port.regshift); - } - break; - - case UPIO_HUB6: - case UPIO_PORT: - start = up->port.iobase; - - if (size) - release_region(start + offset, size); - release_region(start + offset, 8 << up->port.regshift); - break; - - default: - break; - } -} - -static int serial8250_request_port(struct uart_port *port) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - struct resource *res = NULL, *res_rsa = NULL; - int ret = 0; - - ret = serial8250_request_std_resource(up, &res); - - /* - * If we have a mapbase, then request that as well. - */ - if (ret == 0 && up->port.flags & UPF_IOREMAP) { - int size = res->end - res->start + 1; - - up->port.membase = ioremap(up->port.mapbase, size); - if (!up->port.membase) - ret = -ENOMEM; - } - - if (ret < 0) { - if (res_rsa) - release_resource(res_rsa); - if (res) - release_resource(res); - } - return ret; -} - -static void serial8250_config_port(struct uart_port *port, int flags) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - struct resource *res_std = NULL, *res_rsa = NULL; - int probeflags = PROBE_ANY; - - probeflags &= ~PROBE_RSA; - - if (flags & UART_CONFIG_TYPE) - autoconfig(up, probeflags); - - /* - * If the port wasn't an RSA port, release the resource. - */ - if (up->port.type != PORT_RSA && res_rsa) - release_resource(res_rsa); - - if (up->port.type == PORT_UNKNOWN && res_std) - release_resource(res_std); -} - -static int -serial8250_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - if (ser->irq >= NR_IRQS || ser->irq < 0 || - ser->baud_base < 9600 || ser->type < PORT_UNKNOWN || - ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS || - ser->type == PORT_STARTECH) - return -EINVAL; - return 0; -} - -static const char * -serial8250_type(struct uart_port *port) -{ - int type = port->type; - - if (type >= ARRAY_SIZE(uart_config)) - type = 0; - return uart_config[type].name; -} - -static struct uart_ops serial8250_pops = { - .tx_empty = serial8250_tx_empty, - .set_mctrl = serial8250_set_mctrl, - .get_mctrl = serial8250_get_mctrl, - .stop_tx = serial8250_stop_tx, - .start_tx = serial8250_start_tx, - .stop_rx = serial8250_stop_rx, - .enable_ms = serial8250_enable_ms, - .break_ctl = serial8250_break_ctl, - .startup = serial8250_startup, - .shutdown = serial8250_shutdown, - .set_termios = serial8250_set_termios, - .pm = serial8250_pm, - .type = serial8250_type, - .release_port = serial8250_release_port, - .request_port = serial8250_request_port, - .config_port = serial8250_config_port, - .verify_port = serial8250_verify_port, -}; - -static struct uart_8250_port serial8250_ports[UART_NR]; - -static void __init serial8250_isa_init_ports(void) -{ - struct uart_8250_port *up; - static int first = 1; - int i; - - if (!first) - return; - first = 0; - - for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port); - i++, up++) { - up->port.iobase = old_serial_port[i].port; - up->port.irq = old_serial_port[i].irq; - up->port.uartclk = get_au1x00_uart_baud_base(); - up->port.flags = old_serial_port[i].flags; - up->port.hub6 = old_serial_port[i].hub6; - up->port.membase = old_serial_port[i].iomem_base; - up->port.iotype = old_serial_port[i].io_type; - up->port.regshift = old_serial_port[i].iomem_reg_shift; - up->port.ops = &serial8250_pops; - } -} - -static void __init serial8250_register_ports(struct uart_driver *drv) -{ - int i; - - serial8250_isa_init_ports(); - - for (i = 0; i < UART_NR; i++) { - struct uart_8250_port *up = &serial8250_ports[i]; - - up->port.line = i; - up->port.ops = &serial8250_pops; - init_timer(&up->timer); - up->timer.function = serial8250_timeout; - - /* - * ALPHA_KLUDGE_MCR needs to be killed. - */ - up->mcr_mask = ~ALPHA_KLUDGE_MCR; - up->mcr_force = ALPHA_KLUDGE_MCR; - - uart_add_one_port(drv, &up->port); - } -} - -#ifdef CONFIG_SERIAL_AU1X00_CONSOLE - -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - -/* - * Wait for transmitter & holding register to empty - */ -static inline void wait_for_xmitr(struct uart_8250_port *up) -{ - unsigned int status, tmout = 10000; - - /* Wait up to 10ms for the character(s) to be sent. */ - do { - status = serial_in(up, UART_LSR); - - if (status & UART_LSR_BI) - up->lsr_break_flag = UART_LSR_BI; - - if (--tmout == 0) - break; - udelay(1); - } while ((status & BOTH_EMPTY) != BOTH_EMPTY); - - /* Wait up to 1s for flow control if necessary */ - if (up->port.flags & UPF_CONS_FLOW) { - tmout = 1000000; - while (--tmout && - ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) - udelay(1); - } -} - -static void au1x00_console_putchar(struct uart_port *port, int ch) -{ - struct uart_8250_port *up = (struct uart_8250_port *)port; - - wait_for_xmitr(up); - serial_out(up, UART_TX, ch); -} - -/* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - * - * The console_lock must be held when we get here. - */ -static void -serial8250_console_write(struct console *co, const char *s, unsigned int count) -{ - struct uart_8250_port *up = &serial8250_ports[co->index]; - unsigned int ier; - - /* - * First save the UER then disable the interrupts - */ - ier = serial_in(up, UART_IER); - serial_out(up, UART_IER, 0); - - uart_console_write(&up->port, s, count, au1x00_console_putchar); - - /* - * Finally, wait for transmitter to become empty - * and restore the IER - */ - wait_for_xmitr(up); - serial_out(up, UART_IER, ier); -} - -static int __init serial8250_console_setup(struct console *co, char *options) -{ - struct uart_port *port; - 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 >= UART_NR) - co->index = 0; - port = &serial8250_ports[co->index].port; - - /* - * Temporary fix. - */ - spin_lock_init(&port->lock); - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - - return uart_set_options(port, co, baud, parity, bits, flow); -} - -extern struct uart_driver serial8250_reg; -static struct console serial8250_console = { - .name = "ttyS", - .write = serial8250_console_write, - .device = uart_console_device, - .setup = serial8250_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &serial8250_reg, -}; - -static int __init serial8250_console_init(void) -{ - serial8250_isa_init_ports(); - register_console(&serial8250_console); - return 0; -} -console_initcall(serial8250_console_init); - -#define SERIAL8250_CONSOLE &serial8250_console -#else -#define SERIAL8250_CONSOLE NULL -#endif - -static struct uart_driver serial8250_reg = { - .owner = THIS_MODULE, - .driver_name = "serial", - .devfs_name = "tts/", - .dev_name = "ttyS", - .major = TTY_MAJOR, - .minor = 64, - .nr = UART_NR, - .cons = SERIAL8250_CONSOLE, -}; - -int __init early_serial_setup(struct uart_port *port) -{ - serial8250_isa_init_ports(); - serial8250_ports[port->line].port = *port; - serial8250_ports[port->line].port.ops = &serial8250_pops; - return 0; -} - -/** - * serial8250_suspend_port - suspend one serial port - * @line: serial line number - * @level: the level of port suspension, as per uart_suspend_port - * - * Suspend one serial port. - */ -void serial8250_suspend_port(int line) -{ - uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port); -} - -/** - * serial8250_resume_port - resume one serial port - * @line: serial line number - * @level: the level of port resumption, as per uart_resume_port - * - * Resume one serial port. - */ -void serial8250_resume_port(int line) -{ - uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); -} - -static int __init serial8250_init(void) -{ - int ret, i; - - printk(KERN_INFO "Serial: Au1x00 driver\n"); - - for (i = 0; i < NR_IRQS; i++) - spin_lock_init(&irq_lists[i].lock); - - ret = uart_register_driver(&serial8250_reg); - if (ret >= 0) - serial8250_register_ports(&serial8250_reg); - - return ret; -} - -static void __exit serial8250_exit(void) -{ - int i; - - for (i = 0; i < UART_NR; i++) - uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port); - - uart_unregister_driver(&serial8250_reg); -} - -module_init(serial8250_init); -module_exit(serial8250_exit); - -EXPORT_SYMBOL(serial8250_suspend_port); -EXPORT_SYMBOL(serial8250_resume_port); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Au1x00 serial driver\n"); diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h index e796d75f027e..7b2366412203 100644 --- a/include/asm-mips/serial.h +++ b/include/asm-mips/serial.h @@ -103,88 +103,6 @@ #define IVR_SERIAL_PORT_DEFNS #endif -#ifdef CONFIG_SERIAL_AU1X00 -#include -#ifdef CONFIG_SOC_AU1000 -#define AU1000_SERIAL_PORT_DEFNS \ - { .baud_base = 0, .port = UART0_ADDR, \ - .iomem_base = (unsigned char *)UART0_ADDR, \ - .irq = AU1000_UART0_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, \ - { .baud_base = 0, .port = UART1_ADDR, \ - .iomem_base = (unsigned char *)UART1_ADDR, \ - .irq = AU1000_UART1_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, \ - { .baud_base = 0, .port = UART2_ADDR, \ - .iomem_base = (unsigned char *)UART2_ADDR, \ - .irq = AU1000_UART2_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, \ - { .baud_base = 0, .port = UART3_ADDR, \ - .iomem_base = (unsigned char *)UART3_ADDR, \ - .irq = AU1000_UART3_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, -#endif - -#ifdef CONFIG_SOC_AU1500 -#define AU1000_SERIAL_PORT_DEFNS \ - { .baud_base = 0, .port = UART0_ADDR, \ - .iomem_base = (unsigned char *)UART0_ADDR, \ - .irq = AU1500_UART0_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, \ - { .baud_base = 0, .port = UART3_ADDR, \ - .iomem_base = (unsigned char *)UART3_ADDR, \ - .irq = AU1500_UART3_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, -#endif - -#ifdef CONFIG_SOC_AU1100 -#define AU1000_SERIAL_PORT_DEFNS \ - { .baud_base = 0, .port = UART0_ADDR, \ - .iomem_base = (unsigned char *)UART0_ADDR, \ - .irq = AU1100_UART0_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, \ - { .baud_base = 0, .port = UART1_ADDR, \ - .iomem_base = (unsigned char *)UART1_ADDR, \ - .irq = AU1100_UART1_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, \ - { .baud_base = 0, .port = UART3_ADDR, \ - .iomem_base = (unsigned char *)UART3_ADDR, \ - .irq = AU1100_UART3_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, -#endif - -#ifdef CONFIG_SOC_AU1550 -#define AU1000_SERIAL_PORT_DEFNS \ - { .baud_base = 0, .port = UART0_ADDR, \ - .iomem_base = (unsigned char *)UART0_ADDR, \ - .irq = AU1550_UART0_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, \ - { .baud_base = 0, .port = UART1_ADDR, \ - .iomem_base = (unsigned char *)UART1_ADDR, \ - .irq = AU1550_UART1_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, \ - { .baud_base = 0, .port = UART3_ADDR, \ - .iomem_base = (unsigned char *)UART3_ADDR, \ - .irq = AU1550_UART3_INT, .flags = STD_COM_FLAGS,\ - .iomem_reg_shift = 2 }, -#endif - -#ifdef CONFIG_SOC_AU1200 -#define AU1000_SERIAL_PORT_DEFNS \ - { .baud_base = 0, .port = UART0_ADDR, \ - .iomem_base = (unsigned char *)UART0_ADDR, \ - .irq = AU1200_UART0_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, \ - { .baud_base = 0, .port = UART1_ADDR, \ - .iomem_base = (unsigned char *)UART1_ADDR, \ - .irq = AU1200_UART1_INT, .flags = STD_COM_FLAGS, \ - .iomem_reg_shift = 2 }, -#endif - -#else -#define AU1000_SERIAL_PORT_DEFNS -#endif - #ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT #define STD_SERIAL_PORT_DEFNS \ /* UART CLK PORT IRQ FLAGS */ \ @@ -331,7 +249,6 @@ MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS \ MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \ MOMENCO_OCELOT_SERIAL_PORT_DEFNS \ - MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS \ - AU1000_SERIAL_PORT_DEFNS + MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS #endif /* _ASM_SERIAL_H */ -- cgit v1.2.3-59-g8ed1b From fbb18a277a6f192404aa20ece49529acb1e1e76d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 26 Mar 2006 23:13:39 +0100 Subject: [SERIAL] amba-pl010: allow platforms to specify modem control method The amba-pl010 hardware does not provide RTS and DTR control lines; it is expected that these will be implemented using GPIO. Allow platforms to supply a function to implement manipulation of modem control lines. Signed-off-by: Russell King --- arch/arm/mach-integrator/core.c | 46 ++++++++++++ drivers/serial/amba-pl010.c | 160 +++++++++++++++++----------------------- include/linux/amba/serial.h | 6 ++ 3 files changed, 119 insertions(+), 93 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 20071a2767cc..576a5e979c00 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -15,7 +15,9 @@ #include #include #include +#include #include +#include #include #include @@ -28,6 +30,8 @@ #include "common.h" +static struct amba_pl010_data integrator_uart_data; + static struct amba_device rtc_device = { .dev = { .bus_id = "mb:15", @@ -44,6 +48,7 @@ static struct amba_device rtc_device = { static struct amba_device uart0_device = { .dev = { .bus_id = "mb:16", + .platform_data = &integrator_uart_data, }, .res = { .start = INTEGRATOR_UART0_BASE, @@ -57,6 +62,7 @@ static struct amba_device uart0_device = { static struct amba_device uart1_device = { .dev = { .bus_id = "mb:17", + .platform_data = &integrator_uart_data, }, .res = { .start = INTEGRATOR_UART1_BASE, @@ -115,6 +121,46 @@ static int __init integrator_init(void) arch_initcall(integrator_init); +/* + * On the Integrator platform, the port RTS and DTR are provided by + * bits in the following SC_CTRLS register bits: + * RTS DTR + * UART0 7 6 + * UART1 5 4 + */ +#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) +#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) + +static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl) +{ + unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask; + + if (dev == &uart0_device) { + rts_mask = 1 << 4; + dtr_mask = 1 << 5; + } else { + rts_mask = 1 << 6; + dtr_mask = 1 << 7; + } + + if (mctrl & TIOCM_RTS) + ctrlc |= rts_mask; + else + ctrls |= rts_mask; + + if (mctrl & TIOCM_DTR) + ctrlc |= dtr_mask; + else + ctrls |= dtr_mask; + + __raw_writel(ctrls, SC_CTRLS); + __raw_writel(ctrlc, SC_CTRLC); +} + +static struct amba_pl010_data integrator_uart_data = { + .set_mctrl = integrator_uart_set_mctrl, +}; + #define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_CTRL_OFFSET static DEFINE_SPINLOCK(cm_lock); diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 127d6cd5de7f..1631414000a2 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -51,8 +51,6 @@ #include #include -#include -#include #define UART_NR 2 @@ -65,26 +63,16 @@ #define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0) #define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0) -#define UART_DUMMY_RSR_RX /*256*/0 +#define UART_DUMMY_RSR_RX 256 #define UART_PORT_SIZE 64 -/* - * On the Integrator platform, the port RTS and DTR are provided by - * bits in the following SC_CTRLS register bits: - * RTS DTR - * UART0 7 6 - * UART1 5 4 - */ -#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) -#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) - /* * We wrap our port structure around the generic uart_port. */ struct uart_amba_port { struct uart_port port; - unsigned int dtr_mask; - unsigned int rts_mask; + struct amba_device *dev; + struct amba_pl010_data *data; unsigned int old_status; }; @@ -300,20 +288,9 @@ static unsigned int pl010_get_mctrl(struct uart_port *port) static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_amba_port *uap = (struct uart_amba_port *)port; - unsigned int ctrls = 0, ctrlc = 0; - - if (mctrl & TIOCM_RTS) - ctrlc |= uap->rts_mask; - else - ctrls |= uap->rts_mask; - if (mctrl & TIOCM_DTR) - ctrlc |= uap->dtr_mask; - else - ctrls |= uap->dtr_mask; - - __raw_writel(ctrls, SC_CTRLS); - __raw_writel(ctrlc, SC_CTRLC); + if (uap->data) + uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl); } static void pl010_break_ctl(struct uart_port *port, int break_state) @@ -539,38 +516,7 @@ static struct uart_ops amba_pl010_pops = { .verify_port = pl010_verify_port, }; -static struct uart_amba_port amba_ports[UART_NR] = { - { - .port = { - .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), - .mapbase = INTEGRATOR_UART0_BASE, - .iotype = UPIO_MEM, - .irq = IRQ_UARTINT0, - .uartclk = 14745600, - .fifosize = 16, - .ops = &amba_pl010_pops, - .flags = UPF_BOOT_AUTOCONF, - .line = 0, - }, - .dtr_mask = 1 << 5, - .rts_mask = 1 << 4, - }, - { - .port = { - .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), - .mapbase = INTEGRATOR_UART1_BASE, - .iotype = UPIO_MEM, - .irq = IRQ_UARTINT1, - .uartclk = 14745600, - .fifosize = 16, - .ops = &amba_pl010_pops, - .flags = UPF_BOOT_AUTOCONF, - .line = 1, - }, - .dtr_mask = 1 << 7, - .rts_mask = 1 << 6, - } -}; +static struct uart_amba_port *amba_ports[UART_NR]; #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE @@ -588,7 +534,7 @@ static void pl010_console_putchar(struct uart_port *port, int ch) static void pl010_console_write(struct console *co, const char *s, unsigned int count) { - struct uart_port *port = &amba_ports[co->index].port; + struct uart_port *port = &amba_ports[co->index]->port; unsigned int status, old_cr; /* @@ -651,7 +597,7 @@ static int __init pl010_console_setup(struct console *co, char *options) */ if (co->index >= UART_NR) co->index = 0; - port = &amba_ports[co->index].port; + port = &amba_ports[co->index]->port; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -672,24 +618,6 @@ static struct console amba_console = { .data = &amba_reg, }; -static int __init amba_console_init(void) -{ - /* - * All port initializations are done statically - */ - register_console(&amba_console); - return 0; -} -console_initcall(amba_console_init); - -static int __init amba_late_console_init(void) -{ - if (!(amba_console.flags & CON_ENABLED)) - register_console(&amba_console); - return 0; -} -late_initcall(amba_late_console_init); - #define AMBA_CONSOLE &amba_console #else #define AMBA_CONSOLE NULL @@ -707,30 +635,76 @@ static struct uart_driver amba_reg = { static int pl010_probe(struct amba_device *dev, void *id) { - int i; + struct uart_amba_port *port; + void __iomem *base; + int i, ret; - for (i = 0; i < UART_NR; i++) { - if (amba_ports[i].port.mapbase != dev->res.start) - continue; + for (i = 0; i < ARRAY_SIZE(amba_ports); i++) + if (amba_ports[i] == NULL) + break; - amba_ports[i].port.dev = &dev->dev; - uart_add_one_port(&amba_reg, &amba_ports[i].port); - amba_set_drvdata(dev, &amba_ports[i]); - break; + if (i == ARRAY_SIZE(amba_ports)) { + ret = -EBUSY; + goto out; } - return 0; + port = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL); + if (!port) { + ret = -ENOMEM; + goto out; + } + + base = ioremap(dev->res.start, PAGE_SIZE); + if (!base) { + ret = -ENOMEM; + goto free; + } + + port->port.dev = &dev->dev; + port->port.mapbase = dev->res.start; + port->port.membase = base; + port->port.iotype = UPIO_MEM; + port->port.irq = dev->irq[0]; + port->port.uartclk = 14745600; + port->port.fifosize = 16; + port->port.ops = &amba_pl010_pops; + port->port.flags = UPF_BOOT_AUTOCONF; + port->port.line = i; + port->dev = dev; + port->data = dev->dev.platform_data; + + amba_ports[i] = port; + + amba_set_drvdata(dev, port); + ret = uart_add_one_port(&amba_reg, &port->port); + if (ret) { + amba_set_drvdata(dev, NULL); + amba_ports[i] = NULL; + iounmap(base); + free: + kfree(port); + } + + out: + return ret; } static int pl010_remove(struct amba_device *dev) { - struct uart_amba_port *uap = amba_get_drvdata(dev); - - if (uap) - uart_remove_one_port(&amba_reg, &uap->port); + struct uart_amba_port *port = amba_get_drvdata(dev); + int i; amba_set_drvdata(dev, NULL); + uart_remove_one_port(&amba_reg, &port->port); + + for (i = 0; i < ARRAY_SIZE(amba_ports); i++) + if (amba_ports[i] == port) + amba_ports[i] = NULL; + + iounmap(port->port.membase); + kfree(port); + return 0; } diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h index dc726ffccebd..48ee32a18ac5 100644 --- a/include/linux/amba/serial.h +++ b/include/linux/amba/serial.h @@ -158,4 +158,10 @@ #define UART01x_RSR_ANY (UART01x_RSR_OE|UART01x_RSR_BE|UART01x_RSR_PE|UART01x_RSR_FE) #define UART01x_FR_MODEM_ANY (UART01x_FR_DCD|UART01x_FR_DSR|UART01x_FR_CTS) +#ifndef __ASSEMBLY__ +struct amba_pl010_data { + void (*set_mctrl)(struct amba_device *dev, void __iomem *base, unsigned int mctrl); +}; +#endif + #endif -- cgit v1.2.3-59-g8ed1b From b8c7b976a570aede21327e7d64781801e1641606 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 25 Mar 2006 17:31:30 +1100 Subject: [PATCH] powerpc: Compile warning in hvcs driver We ended up with an unused variable after the tty updates went in. Fix it. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- drivers/char/hvcs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index f7ac31856572..327b00c3c45e 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -439,7 +439,6 @@ static int hvcs_io(struct hvcs_struct *hvcsd) char buf[HVCS_BUFF_LEN] __ALIGNED__; unsigned long flags; int got = 0; - int i; spin_lock_irqsave(&hvcsd->lock, flags); -- cgit v1.2.3-59-g8ed1b From 55aab8cd3a498201b769a19de861c77516bdfd45 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Sat, 25 Mar 2006 17:30:00 +1100 Subject: [PATCH] powerpc: HVC init race I've been hitting a crash on boot where tty_open is being called before the hvc console driver setup is complete. This fixes the problem. Thanks to benh for his help on this. Signed-off-by: Michael Neuling Acked-by: Anton Blanchard Signed-off-by: Paul Mackerras --- drivers/char/hvc_console.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index f65b2e14a485..a94c5b0cac52 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -823,34 +823,38 @@ EXPORT_SYMBOL(hvc_remove); * interfaces start to become available. */ int __init hvc_init(void) { + struct tty_driver *drv; + /* We need more than hvc_count adapters due to hotplug additions. */ - hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS); - if (!hvc_driver) + drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS); + if (!drv) return -ENOMEM; - hvc_driver->owner = THIS_MODULE; - hvc_driver->devfs_name = "hvc/"; - hvc_driver->driver_name = "hvc"; - hvc_driver->name = "hvc"; - hvc_driver->major = HVC_MAJOR; - hvc_driver->minor_start = HVC_MINOR; - hvc_driver->type = TTY_DRIVER_TYPE_SYSTEM; - hvc_driver->init_termios = tty_std_termios; - hvc_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(hvc_driver, &hvc_ops); + drv->owner = THIS_MODULE; + drv->devfs_name = "hvc/"; + drv->driver_name = "hvc"; + drv->name = "hvc"; + drv->major = HVC_MAJOR; + drv->minor_start = HVC_MINOR; + drv->type = TTY_DRIVER_TYPE_SYSTEM; + drv->init_termios = tty_std_termios; + drv->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(drv, &hvc_ops); /* Always start the kthread because there can be hotplug vty adapters * added later. */ hvc_task = kthread_run(khvcd, NULL, "khvcd"); if (IS_ERR(hvc_task)) { panic("Couldn't create kthread for console.\n"); - put_tty_driver(hvc_driver); + put_tty_driver(drv); return -EIO; } - if (tty_register_driver(hvc_driver)) + if (tty_register_driver(drv)) panic("Couldn't register hvc console driver\n"); + mb(); + hvc_driver = drv; return 0; } module_init(hvc_init); -- cgit v1.2.3-59-g8ed1b From 06ff37ffb4ba8bcbda0e9d19c712c954ef7b8a0a Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Wed, 8 Mar 2006 11:21:52 +0100 Subject: [PATCH] kzalloc() conversion in drivers/block this patch converts drivers/block to kzalloc usage. Compile tested with allyesconfig. Signed-off-by: Eric Sesterhenn Signed-off-by: Jens Axboe --- drivers/block/DAC960.c | 7 ++----- drivers/block/cciss.c | 10 +++------- drivers/block/cciss_scsi.c | 3 +-- drivers/block/paride/bpck6.c | 3 +-- 4 files changed, 7 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 9bdea2a5cf0e..49c7cd558ddf 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -311,11 +311,10 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller) CommandsRemaining = CommandAllocationGroupSize; CommandGroupByteCount = CommandsRemaining * CommandAllocationLength; - AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC); + AllocationPointer = kzalloc(CommandGroupByteCount, GFP_ATOMIC); if (AllocationPointer == NULL) return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION"); - memset(AllocationPointer, 0, CommandGroupByteCount); } Command = (DAC960_Command_T *) AllocationPointer; AllocationPointer += CommandAllocationLength; @@ -2709,14 +2708,12 @@ DAC960_DetectController(struct pci_dev *PCI_Device, void __iomem *BaseAddress; int i; - Controller = (DAC960_Controller_T *) - kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); + Controller = kzalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); if (Controller == NULL) { DAC960_Error("Unable to allocate Controller structure for " "Controller at\n", NULL); return NULL; } - memset(Controller, 0, sizeof(DAC960_Controller_T)); Controller->ControllerNumber = DAC960_ControllerCount; DAC960_Controllers[DAC960_ControllerCount++] = Controller; Controller->Bus = PCI_Device->bus->number; diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 71ec9e664383..168da0c9ed3d 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -996,13 +996,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, status = -EINVAL; goto cleanup1; } - buff = (unsigned char **) kmalloc(MAXSGENTRIES * - sizeof(char *), GFP_KERNEL); + buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL); if (!buff) { status = -ENOMEM; goto cleanup1; } - memset(buff, 0, MAXSGENTRIES); buff_size = (int *) kmalloc(MAXSGENTRIES * sizeof(int), GFP_KERNEL); if (!buff_size) { @@ -2940,13 +2938,12 @@ static void cciss_getgeometry(int cntl_num) int block_size; int total_size; - ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL); + ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); if (ld_buff == NULL) { printk(KERN_ERR "cciss: out of memory\n"); return; } - memset(ld_buff, 0, sizeof(ReportLunData_struct)); size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); if (size_buff == NULL) { @@ -3060,10 +3057,9 @@ static int alloc_cciss_hba(void) for(i=0; i< MAX_CTLR; i++) { if (!hba[i]) { ctlr_info_t *p; - p = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL); + p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL); if (!p) goto Enomem; - memset(p, 0, sizeof(ctlr_info_t)); for (n = 0; n < NWD; n++) p->gendisk[n] = disk[n]; hba[i] = p; diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 0e66e904bd8c..597c007fe81b 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -1027,12 +1027,11 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) int i; c = (ctlr_info_t *) hba[cntl_num]; - ld_buff = kmalloc(reportlunsize, GFP_KERNEL); + ld_buff = kzalloc(reportlunsize, GFP_KERNEL); if (ld_buff == NULL) { printk(KERN_ERR "cciss: out of memory\n"); return; } - memset(ld_buff, 0, reportlunsize); inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); if (inq_buff == NULL) { printk(KERN_ERR "cciss: out of memory\n"); diff --git a/drivers/block/paride/bpck6.c b/drivers/block/paride/bpck6.c index 08d858ad64db..41a237c5957d 100644 --- a/drivers/block/paride/bpck6.c +++ b/drivers/block/paride/bpck6.c @@ -224,10 +224,9 @@ static void bpck6_log_adapter( PIA *pi, char * scratch, int verbose ) static int bpck6_init_proto(PIA *pi) { - Interface *p = kmalloc(sizeof(Interface), GFP_KERNEL); + Interface *p = kzalloc(sizeof(Interface), GFP_KERNEL); if (p) { - memset(p, 0, sizeof(Interface)); pi->private = (unsigned long)p; return 0; } -- cgit v1.2.3-59-g8ed1b From b8fca1c7682105c843319728d8e37b42b19092bb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 21 Mar 2006 15:24:37 +0100 Subject: [PATCH] ide-cd: quiet down GPCMD_READ_CDVD_CAPACITY failure Some drives like to throw a: ATAPI device hdc: Error: Not ready -- (Sense key=0x02) Incompatible medium installed -- (asc=0x30, ascq=0x00) The failed "Read Cd/Dvd Capacity" packet command was: "25 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " warning on incompatible media, so quiet down this error. Signed-off-by: Jens Axboe --- drivers/ide/ide-cd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index c7671e188017..b4a41d6d0714 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -2143,6 +2143,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, req.cmd[0] = GPCMD_READ_CDVD_CAPACITY; req.data = (char *)&capbuf; req.data_len = sizeof(capbuf); + req.flags |= REQ_QUIET; stat = cdrom_queue_packet_command(drive, &req); if (stat == 0) { -- cgit v1.2.3-59-g8ed1b From 89a7689e5c039090d99cbdc3625252c3dee50f7f Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 24 Mar 2006 10:00:57 +0100 Subject: [PATCH] unused label in drivers/block/cciss. this patch removes a warning about an unused label, by moving the label into the ifdef. Signed-off-by: Eric Sesterhenn Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 168da0c9ed3d..1b0fd31c57c3 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2727,9 +2727,9 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *c, struct pci_dev *pdev, return; } } +default_int_mode: #endif /* CONFIG_PCI_MSI */ /* if we get here we're going to use the default interrupt mode */ -default_int_mode: c->intr[SIMPLE_MODE_INT] = pdev->irq; return; } -- cgit v1.2.3-59-g8ed1b From f222313a61a5e134de80767b35c672b91e78383c Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 23 Jan 2006 16:59:58 -0500 Subject: [PATCH] wireless: import bcm43xx sources Import the bcm43xx driver from the upstream sources here: ftp://ftp.berlios.de/pub/bcm43xx/snapshots/bcm43xx/bcm43xx-20060123.tar.bz2 Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/COPYING | 340 ++ drivers/net/wireless/bcm43xx/Makefile | 87 + drivers/net/wireless/bcm43xx/README | 36 + drivers/net/wireless/bcm43xx/bcm43xx.h | 961 +++++ drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 503 +++ drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h | 117 + drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 1009 ++++++ drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 176 + drivers/net/wireless/bcm43xx/bcm43xx_ilt.c | 367 ++ drivers/net/wireless/bcm43xx/bcm43xx_ilt.h | 34 + drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 261 ++ drivers/net/wireless/bcm43xx/bcm43xx_leds.h | 47 + drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4597 ++++++++++++++++++++++++ drivers/net/wireless/bcm43xx/bcm43xx_main.h | 283 ++ drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 2122 +++++++++++ drivers/net/wireless/bcm43xx/bcm43xx_phy.h | 74 + drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 592 +++ drivers/net/wireless/bcm43xx/bcm43xx_pio.h | 88 + drivers/net/wireless/bcm43xx/bcm43xx_power.c | 358 ++ drivers/net/wireless/bcm43xx/bcm43xx_power.h | 47 + drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 1766 +++++++++ drivers/net/wireless/bcm43xx/bcm43xx_radio.h | 93 + drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 1099 ++++++ drivers/net/wireless/bcm43xx/bcm43xx_wx.h | 36 + 24 files changed, 15093 insertions(+) create mode 100644 drivers/net/wireless/bcm43xx/COPYING create mode 100644 drivers/net/wireless/bcm43xx/Makefile create mode 100644 drivers/net/wireless/bcm43xx/README create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_dma.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_dma.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ilt.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ilt.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_leds.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_leds.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_main.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_main.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_phy.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_phy.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_pio.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_pio.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_power.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_power.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_radio.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_radio.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_wx.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_wx.h (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/COPYING b/drivers/net/wireless/bcm43xx/COPYING new file mode 100644 index 000000000000..5b6e7c66c276 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile new file mode 100644 index 000000000000..98d4efb1d12a --- /dev/null +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -0,0 +1,87 @@ +# Makefile for bcm43xx driver + +VERSION := 0.0.1 +RELEASE_NAME := bcm43xx-$(VERSION) + +# Optional path, where the SoftMAC subsystem is located. +# You may set SOFTMAC_DIR in your bashrc, for example. +SOFTMAC_DIR ?= + +KVER := $(shell uname -r) +KDIR ?= /lib/modules/$(KVER)/build +PWD := $(shell pwd) +MODPATH := $(DESTDIR)/lib/modules/$(KVER)/kernel/drivers/net/bcm43xx + +# Comment/uncomment to enable/disable debugging +DEBUG = y + + +ifeq ($(DEBUG),y) +DEBUGFS_OBJ = bcm43xx_debugfs.o +CFLAGS += -O2 -DCONFIG_BCM43XX_DEBUG +else +DEBUGFS_OBJ = +CFLAGS += -O2 +endif + +CFLAGS += -DBCM43xx_VERSION=$(VERSION) -I/lib/modules/$(KVER)/include +ifneq ($(SOFTMAC_DIR),) +CPPFLAGS := -I$(SOFTMAC_DIR) $(CPPFLAGS) +endif + +ifneq ($(KERNELRELEASE),) +# call from kernel build system + +obj-m := bcm43xx.o +bcm43xx-objs := bcm43xx_main.o bcm43xx_dma.o $(DEBUGFS_OBJ) \ + bcm43xx_radio.o bcm43xx_phy.o \ + bcm43xx_power.o bcm43xx_wx.o \ + bcm43xx_pio.o bcm43xx_ilt.o \ + bcm43xx_leds.o + +else + +default: modules + +modules: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +install: bcm43xx.ko + install -d $(MODPATH) + install -m 644 -c bcm43xx.ko $(MODPATH) + /sbin/depmod -a + +uninstall: + rm -rf $(MODPATH) + /sbin/depmod -a + +endif + +clean: + find . \( -name '*.ko' -o -name '*.o' -o -name '.tmp_versions' -o -name '*~' -o -name '.*.cmd' \ + -o -name '*.mod.c' -o -name '*.tar.bz2' -o -name '*.rej' -o -name '*.orig' \)\ + -print | xargs rm -Rf + +depend .depend dep: + $(CC) $(CFLAGS) -M *.c > .depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + +DISTFILES = $(shell find . \( -not -name '.' \) -print | grep -v "\.tar\.bz2" | grep -v "\/\." ) +DISTDIR = $(RELEASE_NAME) + +release: clean + @rm -rf $(DISTDIR) + @mkdir $(DISTDIR) + @chmod 777 $(DISTDIR) + @for file in $(DISTFILES); do \ + if test -d $$file; then \ + mkdir $(DISTDIR)/$$file; \ + else \ + cp -p $$file $(DISTDIR)/$$file; \ + fi; \ + done + @tar -c $(DISTDIR) | bzip2 -9 > $(RELEASE_NAME).tar.bz2 + @rm -rf $(DISTDIR) diff --git a/drivers/net/wireless/bcm43xx/README b/drivers/net/wireless/bcm43xx/README new file mode 100644 index 000000000000..64d9022de7fe --- /dev/null +++ b/drivers/net/wireless/bcm43xx/README @@ -0,0 +1,36 @@ + + BCM43xx Linux Driver Project + ============================ + +About this software +------------------- + +The goal of this project is to develop a linux driver for Broadcom +BCM43xx chips, based on the specification at +http://bcm-specs.sipsolutions.net/ + +The project page is http://bcm43xx.berlios.de/ + + +Requirements +------------ + +1) Linux Kernel 2.6.15 or later + http://www.kernel.org/ + + You may want to configure your kernel with: + + CONFIG_DEBUG_FS (optional): + -> Kernel hacking + -> Debug Filesystem + +2) SoftMAC IEEE 802.11 Networking Stack extension and patched ieee80211 + modules: + http://softmac.sipsolutions.net/ + +3) Firmware Files + + Please try fwcutter. Fwcutter can extract the firmware from various + binary driver files. It supports driver files from Windows, MacOS and + Linux. You can get fwcutter from http://bcm43xx.berlios.de/. + Also, fwcutter comes with a README file for further instructions. diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h new file mode 100644 index 000000000000..aca1601e5b4f --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -0,0 +1,961 @@ +#ifndef BCM43xx_H_ +#define BCM43xx_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "bcm43xx_debugfs.h" +#include "bcm43xx_leds.h" + + +#define DRV_NAME __stringify(KBUILD_MODNAME) +#define DRV_VERSION __stringify(BCM43xx_VERSION) +#define BCM43xx_DRIVER_NAME DRV_NAME " driver " DRV_VERSION +#define PFX DRV_NAME ": " + +#define BCM43xx_SWITCH_CORE_MAX_RETRIES 10 +#define BCM43xx_IRQWAIT_MAX_RETRIES 50 +#define BCM43xx_TX_TIMEOUT (10 * HZ) + +#define BCM43xx_IO_SIZE 8192 +#define BCM43xx_REG_ACTIVE_CORE 0x80 + +/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */ +#define BCM43xx_PCICFG_ICR 0x94 +/* SPROM control register. */ +#define BCM43xx_PCICFG_SPROMCTL 0x88 + +/* MMIO offsets */ +#define BCM43xx_MMIO_DMA1_REASON 0x20 +#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x24 +#define BCM43xx_MMIO_DMA2_REASON 0x28 +#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x2C +#define BCM43xx_MMIO_DMA3_REASON 0x30 +#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x34 +#define BCM43xx_MMIO_DMA4_REASON 0x38 +#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x3C +#define BCM43xx_MMIO_STATUS_BITFIELD 0x120 +#define BCM43xx_MMIO_STATUS2_BITFIELD 0x124 +#define BCM43xx_MMIO_GEN_IRQ_REASON 0x128 +#define BCM43xx_MMIO_GEN_IRQ_MASK 0x12C +#define BCM43xx_MMIO_RAM_CONTROL 0x130 +#define BCM43xx_MMIO_RAM_DATA 0x134 +#define BCM43xx_MMIO_PS_STATUS 0x140 +#define BCM43xx_MMIO_RADIO_HWENABLED_HI 0x158 +#define BCM43xx_MMIO_SHM_CONTROL 0x160 +#define BCM43xx_MMIO_SHM_DATA 0x164 +#define BCM43xx_MMIO_SHM_DATA_UNALIGNED 0x166 +#define BCM43xx_MMIO_XMITSTAT_0 0x170 +#define BCM43xx_MMIO_XMITSTAT_1 0x174 +#define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ +#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ +#define BCM43xx_MMIO_DMA1_BASE 0x200 +#define BCM43xx_MMIO_DMA2_BASE 0x220 +#define BCM43xx_MMIO_DMA3_BASE 0x240 +#define BCM43xx_MMIO_DMA4_BASE 0x260 +#define BCM43xx_MMIO_PIO1_BASE 0x300 +#define BCM43xx_MMIO_PIO2_BASE 0x310 +#define BCM43xx_MMIO_PIO3_BASE 0x320 +#define BCM43xx_MMIO_PIO4_BASE 0x330 +#define BCM43xx_MMIO_PHY_VER 0x3E0 +#define BCM43xx_MMIO_PHY_RADIO 0x3E2 +#define BCM43xx_MMIO_ANTENNA 0x3E8 +#define BCM43xx_MMIO_CHANNEL 0x3F0 +#define BCM43xx_MMIO_CHANNEL_EXT 0x3F4 +#define BCM43xx_MMIO_RADIO_CONTROL 0x3F6 +#define BCM43xx_MMIO_RADIO_DATA_HIGH 0x3F8 +#define BCM43xx_MMIO_RADIO_DATA_LOW 0x3FA +#define BCM43xx_MMIO_PHY_CONTROL 0x3FC +#define BCM43xx_MMIO_PHY_DATA 0x3FE +#define BCM43xx_MMIO_MACFILTER_CONTROL 0x420 +#define BCM43xx_MMIO_MACFILTER_DATA 0x422 +#define BCM43xx_MMIO_RADIO_HWENABLED_LO 0x49A +#define BCM43xx_MMIO_GPIO_CONTROL 0x49C +#define BCM43xx_MMIO_GPIO_MASK 0x49E +#define BCM43xx_MMIO_TSF_0 0x632 /* core rev < 3 only */ +#define BCM43xx_MMIO_TSF_1 0x634 /* core rev < 3 only */ +#define BCM43xx_MMIO_TSF_2 0x636 /* core rev < 3 only */ +#define BCM43xx_MMIO_TSF_3 0x638 /* core rev < 3 only */ +#define BCM43xx_MMIO_POWERUP_DELAY 0x6A8 + +/* SPROM offsets. */ +#define BCM43xx_SPROM_BASE 0x1000 +#define BCM43xx_SPROM_BOARDFLAGS2 0x1c +#define BCM43xx_SPROM_IL0MACADDR 0x24 +#define BCM43xx_SPROM_ET0MACADDR 0x27 +#define BCM43xx_SPROM_ET1MACADDR 0x2a +#define BCM43xx_SPROM_ETHPHY 0x2d +#define BCM43xx_SPROM_BOARDREV 0x2e +#define BCM43xx_SPROM_PA0B0 0x2f +#define BCM43xx_SPROM_PA0B1 0x30 +#define BCM43xx_SPROM_PA0B2 0x31 +#define BCM43xx_SPROM_WL0GPIO0 0x32 +#define BCM43xx_SPROM_WL0GPIO2 0x33 +#define BCM43xx_SPROM_MAXPWR 0x34 +#define BCM43xx_SPROM_PA1B0 0x35 +#define BCM43xx_SPROM_PA1B1 0x36 +#define BCM43xx_SPROM_PA1B2 0x37 +#define BCM43xx_SPROM_IDL_TSSI_TGT 0x38 +#define BCM43xx_SPROM_BOARDFLAGS 0x39 +#define BCM43xx_SPROM_ANTENNA_GAIN 0x3a +#define BCM43xx_SPROM_VERSION 0x3f + +/* BCM43xx_SPROM_BOARDFLAGS values */ +#define BCM43xx_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */ +#define BCM43xx_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */ +#define BCM43xx_BFL_AIRLINEMODE 0x0004 /* implements GPIO 13 radio disable indication */ +#define BCM43xx_BFL_RSSI 0x0008 /* software calculates nrssi slope. */ +#define BCM43xx_BFL_ENETSPI 0x0010 /* has ephy roboswitch spi */ +#define BCM43xx_BFL_XTAL_NOSLOW 0x0020 /* no slow clock available */ +#define BCM43xx_BFL_CCKHIPWR 0x0040 /* can do high power CCK transmission */ +#define BCM43xx_BFL_ENETADM 0x0080 /* has ADMtek switch */ +#define BCM43xx_BFL_ENETVLAN 0x0100 /* can do vlan */ +#define BCM43xx_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */ +#define BCM43xx_BFL_NOPCI 0x0400 /* leaves PCI floating */ +#define BCM43xx_BFL_FEM 0x0800 /* supports the Front End Module */ + +/* GPIO register offset, in both ChipCommon and PCI core. */ +#define BCM43xx_GPIO_CONTROL 0x6c + +/* SHM Routing */ +#define BCM43xx_SHM_SHARED 0x0001 +#define BCM43xx_SHM_WIRELESS 0x0002 +#define BCM43xx_SHM_PCM 0x0003 +#define BCM43xx_SHM_HWMAC 0x0004 +#define BCM43xx_SHM_UCODE 0x0300 + +/* MacFilter offsets. */ +#define BCM43xx_MACFILTER_SELF 0x0000 +#define BCM43xx_MACFILTER_ASSOC 0x0003 + +/* Chipcommon registers. */ +#define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04 +#define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0 +#define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4 +#define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8 +#define BCM43xx_CHIPCOMMON_SYSCLKCTL 0xC0 + +/* PCI core specific registers. */ +#define BCM43xx_PCICORE_BCAST_ADDR 0x50 +#define BCM43xx_PCICORE_BCAST_DATA 0x54 +#define BCM43xx_PCICORE_SBTOPCI2 0x108 + +/* SBTOPCI2 values. */ +#define BCM43xx_SBTOPCI2_PREFETCH 0x4 +#define BCM43xx_SBTOPCI2_BURST 0x8 + +/* Chipcommon capabilities. */ +#define BCM43xx_CAPABILITIES_PCTL 0x00040000 +#define BCM43xx_CAPABILITIES_PLLMASK 0x00030000 +#define BCM43xx_CAPABILITIES_PLLSHIFT 16 +#define BCM43xx_CAPABILITIES_FLASHMASK 0x00000700 +#define BCM43xx_CAPABILITIES_FLASHSHIFT 8 +#define BCM43xx_CAPABILITIES_EXTBUSPRESENT 0x00000040 +#define BCM43xx_CAPABILITIES_UARTGPIO 0x00000020 +#define BCM43xx_CAPABILITIES_UARTCLOCKMASK 0x00000018 +#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT 3 +#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN 0x00000004 +#define BCM43xx_CAPABILITIES_NRUARTSMASK 0x00000003 + +/* PowerControl */ +#define BCM43xx_PCTL_IN 0xB0 +#define BCM43xx_PCTL_OUT 0xB4 +#define BCM43xx_PCTL_OUTENABLE 0xB8 +#define BCM43xx_PCTL_XTAL_POWERUP 0x40 +#define BCM43xx_PCTL_PLL_POWERDOWN 0x80 + +/* PowerControl Clock Modes */ +#define BCM43xx_PCTL_CLK_FAST 0x00 +#define BCM43xx_PCTL_CLK_SLOW 0x01 +#define BCM43xx_PCTL_CLK_DYNAMIC 0x02 + +#define BCM43xx_PCTL_FORCE_SLOW 0x0800 +#define BCM43xx_PCTL_FORCE_PLL 0x1000 +#define BCM43xx_PCTL_DYN_XTAL 0x2000 + +/* COREIDs */ +#define BCM43xx_COREID_CHIPCOMMON 0x800 +#define BCM43xx_COREID_ILINE20 0x801 +#define BCM43xx_COREID_SDRAM 0x803 +#define BCM43xx_COREID_PCI 0x804 +#define BCM43xx_COREID_MIPS 0x805 +#define BCM43xx_COREID_ETHERNET 0x806 +#define BCM43xx_COREID_V90 0x807 +#define BCM43xx_COREID_USB11_HOSTDEV 0x80a +#define BCM43xx_COREID_IPSEC 0x80b +#define BCM43xx_COREID_PCMCIA 0x80d +#define BCM43xx_COREID_EXT_IF 0x80f +#define BCM43xx_COREID_80211 0x812 +#define BCM43xx_COREID_MIPS_3302 0x816 +#define BCM43xx_COREID_USB11_HOST 0x817 +#define BCM43xx_COREID_USB11_DEV 0x818 +#define BCM43xx_COREID_USB20_HOST 0x819 +#define BCM43xx_COREID_USB20_DEV 0x81a +#define BCM43xx_COREID_SDIO_HOST 0x81b + +/* Core Information Registers */ +#define BCM43xx_CIR_BASE 0xf00 +#define BCM43xx_CIR_SBTPSFLAG (BCM43xx_CIR_BASE + 0x18) +#define BCM43xx_CIR_SBIMSTATE (BCM43xx_CIR_BASE + 0x90) +#define BCM43xx_CIR_SBINTVEC (BCM43xx_CIR_BASE + 0x94) +#define BCM43xx_CIR_SBTMSTATELOW (BCM43xx_CIR_BASE + 0x98) +#define BCM43xx_CIR_SBTMSTATEHIGH (BCM43xx_CIR_BASE + 0x9c) +#define BCM43xx_CIR_SBIMCONFIGLOW (BCM43xx_CIR_BASE + 0xa8) +#define BCM43xx_CIR_SB_ID_HI (BCM43xx_CIR_BASE + 0xfc) + +/* Mask to get the Backplane Flag Number from SBTPSFLAG. */ +#define BCM43xx_BACKPLANE_FLAG_NR_MASK 0x3f + +/* SBIMCONFIGLOW values/masks. */ +#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK 0x00000007 +#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT 0 +#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK 0x00000070 +#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT 4 +#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK 0x00ff0000 +#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT 16 + +/* sbtmstatelow state flags */ +#define BCM43xx_SBTMSTATELOW_RESET 0x01 +#define BCM43xx_SBTMSTATELOW_REJECT 0x02 +#define BCM43xx_SBTMSTATELOW_CLOCK 0x10000 +#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000 + +/* sbtmstatehigh state flags */ +#define BCM43xx_SBTMSTATEHIGH_SERROR 0x1 +#define BCM43xx_SBTMSTATEHIGH_BUSY 0x4 + +/* sbimstate flags */ +#define BCM43xx_SBIMSTATE_IB_ERROR 0x20000 +#define BCM43xx_SBIMSTATE_TIMEOUT 0x40000 + +/* PHYVersioning */ +#define BCM43xx_PHYTYPE_A 0x00 +#define BCM43xx_PHYTYPE_B 0x01 +#define BCM43xx_PHYTYPE_G 0x02 + +/* PHYRegisters */ +#define BCM43xx_PHY_ILT_A_CTRL 0x0072 +#define BCM43xx_PHY_ILT_A_DATA1 0x0073 +#define BCM43xx_PHY_ILT_A_DATA2 0x0074 +#define BCM43xx_PHY_G_LO_CONTROL 0x0810 +#define BCM43xx_PHY_ILT_G_CTRL 0x0472 +#define BCM43xx_PHY_ILT_G_DATA1 0x0473 +#define BCM43xx_PHY_ILT_G_DATA2 0x0474 +#define BCM43xx_PHY_A_PCTL 0x007B +#define BCM43xx_PHY_G_PCTL 0x0029 +#define BCM43xx_PHY_A_CRS 0x0029 +#define BCM43xx_PHY_RADIO_BITFIELD 0x0401 +#define BCM43xx_PHY_G_CRS 0x0429 +#define BCM43xx_PHY_NRSSILT_CTRL 0x0803 +#define BCM43xx_PHY_NRSSILT_DATA 0x0804 + +/* RadioRegisters */ +#define BCM43xx_RADIOCTL_ID 0x01 + +/* StatusBitField */ +#define BCM43xx_SBF_MAC_ENABLED 0x00000001 +#define BCM43xx_SBF_2 0x00000002 /*FIXME: fix name*/ +#define BCM43xx_SBF_CORE_READY 0x00000004 +#define BCM43xx_SBF_400 0x00000400 /*FIXME: fix name*/ +#define BCM43xx_SBF_4000 0x00004000 /*FIXME: fix name*/ +#define BCM43xx_SBF_8000 0x00008000 /*FIXME: fix name*/ +#define BCM43xx_SBF_XFER_REG_BYTESWAP 0x00010000 +#define BCM43xx_SBF_MODE_NOTADHOC 0x00020000 +#define BCM43xx_SBF_MODE_AP 0x00040000 +#define BCM43xx_SBF_RADIOREG_LOCK 0x00080000 +#define BCM43xx_SBF_MODE_MONITOR 0x00400000 +#define BCM43xx_SBF_MODE_PROMISC 0x01000000 +#define BCM43xx_SBF_PS1 0x02000000 +#define BCM43xx_SBF_PS2 0x04000000 +#define BCM43xx_SBF_NO_SSID_BCAST 0x08000000 +#define BCM43xx_SBF_TIME_UPDATE 0x10000000 +#define BCM43xx_SBF_80000000 0x80000000 /*FIXME: fix name*/ + +/* MicrocodeFlagsBitfield (addr + lo-word values?)*/ +#define BCM43xx_UCODEFLAGS_OFFSET 0x005E + +#define BCM43xx_UCODEFLAG_AUTODIV 0x0001 +#define BCM43xx_UCODEFLAG_UNKBGPHY 0x0002 +#define BCM43xx_UCODEFLAG_UNKBPHY 0x0004 +#define BCM43xx_UCODEFLAG_UNKGPHY 0x0020 +#define BCM43xx_UCODEFLAG_UNKPACTRL 0x0040 +#define BCM43xx_UCODEFLAG_JAPAN 0x0080 + +/* Generic-Interrupt reasons. */ +#define BCM43xx_IRQ_READY (1 << 0) +#define BCM43xx_IRQ_BEACON (1 << 1) +#define BCM43xx_IRQ_PS (1 << 2) +#define BCM43xx_IRQ_REG124 (1 << 5) +#define BCM43xx_IRQ_PMQ (1 << 6) +#define BCM43xx_IRQ_PIO_WORKAROUND (1 << 8) +#define BCM43xx_IRQ_XMIT_ERROR (1 << 11) +#define BCM43xx_IRQ_RX (1 << 15) +#define BCM43xx_IRQ_SCAN (1 << 16) +#define BCM43xx_IRQ_NOISE (1 << 18) +#define BCM43xx_IRQ_XMIT_STATUS (1 << 29) + +#define BCM43xx_IRQ_ALL 0xffffffff +#define BCM43xx_IRQ_INITIAL (BCM43xx_IRQ_PS | \ + BCM43xx_IRQ_REG124 | \ + BCM43xx_IRQ_PMQ | \ + BCM43xx_IRQ_XMIT_ERROR | \ + BCM43xx_IRQ_RX | \ + BCM43xx_IRQ_SCAN | \ + BCM43xx_IRQ_NOISE | \ + BCM43xx_IRQ_XMIT_STATUS) + + +/* Initial default iw_mode */ +#define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA + +/* Values/Masks for the device TX header */ +#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001 +#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008 +#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020 +#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100 +#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800 + +#define BCM43xx_TXHDRCTL_OFDM 0x0001 +#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010 +#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030 +#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8 + +#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0 +#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4 +#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003 +#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0 + +/* Bus type PCI. */ +#define BCM43xx_BUSTYPE_PCI 0 +/* Bus type Silicone Backplane Bus. */ +#define BCM43xx_BUSTYPE_SB 1 +/* Bus type PCMCIA. */ +#define BCM43xx_BUSTYPE_PCMCIA 2 + +/* Threshold values. */ +#define BCM43xx_MIN_RTS_THRESHOLD 1U +#define BCM43xx_MAX_RTS_THRESHOLD 2304U +#define BCM43xx_DEFAULT_RTS_THRESHOLD BCM43xx_MAX_RTS_THRESHOLD + +#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT 7 +#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT 4 + +/* Max size of a security key */ +#define BCM43xx_SEC_KEYSIZE 16 +/* Security algorithms. */ +enum { + BCM43xx_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */ + BCM43xx_SEC_ALGO_WEP, + BCM43xx_SEC_ALGO_UNKNOWN, + BCM43xx_SEC_ALGO_AES, + BCM43xx_SEC_ALGO_WEP104, + BCM43xx_SEC_ALGO_TKIP, +}; + +#ifdef assert +# undef assert +#endif +#ifdef CONFIG_BCM43XX_DEBUG +#define assert(expr) \ + do { \ + if (unlikely(!(expr))) { \ + printk(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", \ + #expr, __FILE__, __LINE__, __FUNCTION__); \ + } \ + } while (0) +#else +#define assert(expr) do { /* nothing */ } while (0) +#endif + +/* rate limited printk(). */ +#ifdef printkl +# undef printkl +#endif +#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0) +/* rate limited printk() for debugging */ +#ifdef dprintkl +# undef dprintkl +#endif +#ifdef CONFIG_BCM43XX_DEBUG +# define dprintkl printkl +#else +# define dprintkl(f, x...) do { /* nothing */ } while (0) +#endif + +/* Helper macro for if branches. + * An if branch marked with this macro is only taken in DEBUG mode. + * Example: + * if (DEBUG_ONLY(foo == bar)) { + * do something + * } + * In DEBUG mode, the branch will be taken if (foo == bar). + * In non-DEBUG mode, the branch will never be taken. + */ +#ifdef DEBUG_ONLY +# undef DEBUG_ONLY +#endif +#ifdef CONFIG_BCM43XX_DEBUG +# define DEBUG_ONLY(x) (x) +#else +# define DEBUG_ONLY(x) 0 +#endif + +/* debugging printk() */ +#ifdef dprintk +# undef dprintk +#endif +#ifdef CONFIG_BCM43XX_DEBUG +# define dprintk(f, x...) do { printk(f ,##x); } while (0) +#else +# define dprintk(f, x...) do { /* nothing */ } while (0) +#endif + + +struct net_device; +struct pci_dev; +struct workqueue_struct; +struct bcm43xx_dmaring; +struct bcm43xx_pioqueue; + +struct bcm43xx_initval { + u16 offset; + u16 size; + u32 value; +} __attribute__((__packed__)); + +/* Values for bcm430x_sprominfo.locale */ +enum { + BCM43xx_LOCALE_WORLD = 0, + BCM43xx_LOCALE_THAILAND, + BCM43xx_LOCALE_ISRAEL, + BCM43xx_LOCALE_JORDAN, + BCM43xx_LOCALE_CHINA, + BCM43xx_LOCALE_JAPAN, + BCM43xx_LOCALE_USA_CANADA_ANZ, + BCM43xx_LOCALE_EUROPE, + BCM43xx_LOCALE_USA_LOW, + BCM43xx_LOCALE_JAPAN_HIGH, + BCM43xx_LOCALE_ALL, + BCM43xx_LOCALE_NONE, +}; + +#define BCM43xx_SPROM_SIZE 64 /* in 16-bit words. */ +struct bcm43xx_sprominfo { + u16 boardflags2; + u8 il0macaddr[6]; + u8 et0macaddr[6]; + u8 et1macaddr[6]; + u8 et0phyaddr:5; + u8 et1phyaddr:5; + u8 et0mdcport:1; + u8 et1mdcport:1; + u8 boardrev; + u8 locale:4; + u8 antennas_aphy:2; + u8 antennas_bgphy:2; + u16 pa0b0; + u16 pa0b1; + u16 pa0b2; + u8 wl0gpio0; + u8 wl0gpio1; + u8 wl0gpio2; + u8 wl0gpio3; + u8 maxpower_aphy; + u8 maxpower_bgphy; + u16 pa1b0; + u16 pa1b1; + u16 pa1b2; + u8 idle_tssi_tgt_aphy; + u8 idle_tssi_tgt_bgphy; + u16 boardflags; + u16 antennagain_aphy; + u16 antennagain_bgphy; +}; + +/* Value pair to measure the LocalOscillator. */ +struct bcm43xx_lopair { + s8 low; + s8 high; + u8 used:1; +}; +#define BCM43xx_LO_COUNT (14*4) + +struct bcm43xx_phyinfo { + /* Hardware Data */ + u8 version; + u8 type; + u8 rev; + u16 antenna_diversity; + u16 savedpctlreg; + u16 minlowsig[2]; + u16 minlowsigpos[2]; + u8 connected:1, + calibrated:1, + is_locked:1, /* used in bcm43xx_phy_{un}lock() */ + dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */ + /* LO Measurement Data. + * Use bcm43xx_get_lopair() to get a value. + */ + struct bcm43xx_lopair *_lo_pairs; + + /* TSSI to dBm table in use */ + const s8 *tssi2dbm; + /* idle TSSI value */ + s8 idle_tssi; + /* PHY lock for core.rev < 3 + * This lock is only used by bcm43xx_phy_{un}lock() + */ + spinlock_t lock; +}; + + +struct bcm43xx_radioinfo { + u16 manufact; + u16 version; + u8 revision; + + /* 0: baseband attenuation, + * 1: radio attenuation, + * 2: tx_CTL1 + * 3: tx_CTL2 + */ + u16 txpower[4]; + /* Current Interference Mitigation mode */ + int interfmode; + /* Stack of saved values from the Interference Mitigation code */ + u16 interfstack[20]; + /* Saved values from the NRSSI Slope calculation */ + s16 nrssi[2]; + s32 nrssislope; + /* In memory nrssi lookup table. */ + s8 nrssi_lt[64]; + + /* current channel */ + u8 channel; + u8 initial_channel; + + u16 lofcal; + + u16 initval; + + u8 enabled:1; + /* ACI (adjacent channel interference) flags. */ + u8 aci_enable:1, + aci_wlan_automatic:1, + aci_hw_rssi:1; +}; + +/* Data structures for DMA transmission, per 80211 core. */ +struct bcm43xx_dma { + struct bcm43xx_dmaring *tx_ring0; + struct bcm43xx_dmaring *tx_ring1; + struct bcm43xx_dmaring *tx_ring2; + struct bcm43xx_dmaring *tx_ring3; + struct bcm43xx_dmaring *rx_ring0; + struct bcm43xx_dmaring *rx_ring1; /* only available on core.rev < 5 */ +}; + +/* Data structures for PIO transmission, per 80211 core. */ +struct bcm43xx_pio { + struct bcm43xx_pioqueue *queue0; + struct bcm43xx_pioqueue *queue1; + struct bcm43xx_pioqueue *queue2; + struct bcm43xx_pioqueue *queue3; +}; + +#define BCM43xx_MAX_80211_CORES 2 + +#define BCM43xx_COREFLAG_AVAILABLE (1 << 0) +#define BCM43xx_COREFLAG_ENABLED (1 << 1) +#define BCM43xx_COREFLAG_INITIALIZED (1 << 2) + +#ifdef CONFIG_BCM947XX +#define core_offset(bcm) (bcm)->current_core_offset +#else +#define core_offset(bcm) 0 +#endif + +struct bcm43xx_coreinfo { + /** Driver internal flags. See BCM43xx_COREFLAG_* */ + u32 flags; + /** core_id ID number */ + u16 id; + /** core_rev revision number */ + u8 rev; + /** Index number for _switch_core() */ + u8 index; + /* Pointer to the PHYinfo, which belongs to this core (if 80211 core) */ + struct bcm43xx_phyinfo *phy; + /* Pointer to the RadioInfo, which belongs to this core (if 80211 core) */ + struct bcm43xx_radioinfo *radio; + /* Pointer to the DMA rings, which belong to this core (if 80211 core) */ + struct bcm43xx_dma *dma; + /* Pointer to the PIO queues, which belong to this core (if 80211 core) */ + struct bcm43xx_pio *pio; +}; + +/* Context information for a noise calculation (Link Quality). */ +struct bcm43xx_noise_calculation { + struct bcm43xx_coreinfo *core_at_start; + u8 channel_at_start; + u8 calculation_running:1; + u8 nr_samples; + s8 samples[8][4]; +}; + +struct bcm43xx_stats { + u8 link_quality; + /* Store the last TX/RX times here for updating the leds. */ + unsigned long last_tx; + unsigned long last_rx; +}; + +struct bcm43xx_key { + u8 enabled:1; + u8 algorithm; +}; + +struct bcm43xx_private { + struct ieee80211_device *ieee; + struct ieee80211softmac_device *softmac; + + struct net_device *net_dev; + struct pci_dev *pci_dev; + unsigned int irq; + + void __iomem *mmio_addr; + unsigned int mmio_len; + + spinlock_t lock; + + /* Driver status flags. */ + u32 initialized:1, /* init_board() succeed */ + was_initialized:1, /* for PCI suspend/resume. */ + shutting_down:1, /* free_board() in progress */ + pio_mode:1, /* PIO (if true), or DMA (if false) used. */ + 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. */ + + struct bcm43xx_stats stats; + + /* Bus type we are connected to. + * This is currently always BCM43xx_BUSTYPE_PCI + */ + u8 bustype; + + u16 board_vendor; + u16 board_type; + u16 board_revision; + + u16 chip_id; + u8 chip_rev; + + struct bcm43xx_sprominfo sprom; +#define BCM43xx_NR_LEDS 4 + struct bcm43xx_led leds[BCM43xx_NR_LEDS]; + + /* The currently active core. NULL if not initialized, yet. */ + struct bcm43xx_coreinfo *current_core; +#ifdef CONFIG_BCM947XX + /** current core memory offset */ + u32 current_core_offset; +#endif + struct bcm43xx_coreinfo *active_80211_core; + /* coreinfo structs for all possible cores follow. + * Note that a core might not exist. + * So check the coreinfo flags before using it. + */ + struct bcm43xx_coreinfo core_chipcommon; + struct bcm43xx_coreinfo core_pci; + struct bcm43xx_coreinfo core_v90; + struct bcm43xx_coreinfo core_pcmcia; + struct bcm43xx_coreinfo core_ethernet; + struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ]; + /* Info about the PHY for each 80211 core. */ + struct bcm43xx_phyinfo phy[ BCM43xx_MAX_80211_CORES ]; + /* Info about the Radio for each 80211 core. */ + struct bcm43xx_radioinfo radio[ BCM43xx_MAX_80211_CORES ]; + /* DMA */ + struct bcm43xx_dma dma[ BCM43xx_MAX_80211_CORES ]; + /* PIO */ + struct bcm43xx_pio pio[ BCM43xx_MAX_80211_CORES ]; + + u32 chipcommon_capabilities; + + /* Reason code of the last interrupt. */ + u32 irq_reason; + u32 dma_reason[4]; + /* saved irq enable/disable state bitfield. */ + u32 irq_savedstate; + /* Link Quality calculation context. */ + struct bcm43xx_noise_calculation noisecalc; + + /* Threshold values. */ + //TODO: The RTS thr has to be _used_. Currently, it is only set via WX. + u32 rts_threshold; + + /* Interrupt Service Routine tasklet (bottom-half) */ + struct tasklet_struct isr_tasklet; + /* Custom driver work queue. */ + struct workqueue_struct *workqueue; + + /* Periodic tasks */ + struct work_struct periodic_work0; +#define BCM43xx_PERIODIC_0_DELAY (HZ * 15) + struct work_struct periodic_work1; +#define BCM43xx_PERIODIC_1_DELAY ((HZ * 60) + HZ / 2) + struct work_struct periodic_work2; +#define BCM43xx_PERIODIC_2_DELAY ((HZ * 120) + HZ) + struct work_struct periodic_work3; +#define BCM43xx_PERIODIC_3_DELAY ((HZ * 30) + HZ / 5) + + struct work_struct restart_work; + + /* Informational stuff. */ + char nick[IW_ESSID_MAX_SIZE + 1]; + + /* encryption/decryption */ + u16 security_offset; + struct bcm43xx_key key[54]; + u8 default_key_idx; + + /* Firmware. */ + const struct firmware *ucode; + const struct firmware *pcm; + const struct firmware *initvals0; + const struct firmware *initvals1; + + /* Debugging stuff follows. */ +#ifdef CONFIG_BCM43XX_DEBUG + struct bcm43xx_dfsentry *dfsentry; + atomic_t mmio_print_cnt; + atomic_t pcicfg_print_cnt; +#endif +}; + +static inline +struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) +{ + return ieee80211softmac_priv(dev); +} + +static inline +int bcm43xx_num_80211_cores(struct bcm43xx_private *bcm) +{ + int i, cnt = 0; + + for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { + if (bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE) + cnt++; + } + + return cnt; +} + +/* 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, + u16 radio_attenuation, + u16 baseband_attenuation) +{ + return phy->_lo_pairs + (radio_attenuation + 14 * (baseband_attenuation / 2)); +} + + +/* MMIO read/write functions. Debug and non-debug variants. */ +#ifdef CONFIG_BCM43XX_DEBUG + +static inline +u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset) +{ + u16 value; + + value = ioread16(bcm->mmio_addr + core_offset(bcm) + offset); + if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { + printk(KERN_INFO PFX "ioread16 offset: 0x%04x, value: 0x%04x\n", + offset, value); + } + + return value; +} + +static inline +void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value) +{ + iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset); + if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { + printk(KERN_INFO PFX "iowrite16 offset: 0x%04x, value: 0x%04x\n", + offset, value); + } +} + +static inline +u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset) +{ + u32 value; + + value = ioread32(bcm->mmio_addr + core_offset(bcm) + offset); + if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { + printk(KERN_INFO PFX "ioread32 offset: 0x%04x, value: 0x%08x\n", + offset, value); + } + + return value; +} + +static inline +void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value) +{ + iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset); + if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { + printk(KERN_INFO PFX "iowrite32 offset: 0x%04x, value: 0x%08x\n", + offset, value); + } +} + +static inline +int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value) +{ + int err; + + err = pci_read_config_word(bcm->pci_dev, offset, value); + if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { + printk(KERN_INFO PFX "pciread16 offset: 0x%08x, value: 0x%04x, err: %d\n", + offset, *value, err); + } + + return err; +} + +static inline +int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value) +{ + int err; + + err = pci_read_config_dword(bcm->pci_dev, offset, value); + if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { + printk(KERN_INFO PFX "pciread32 offset: 0x%08x, value: 0x%08x, err: %d\n", + offset, *value, err); + } + + return err; +} + +static inline +int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value) +{ + int err; + + err = pci_write_config_word(bcm->pci_dev, offset, value); + if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { + printk(KERN_INFO PFX "pciwrite16 offset: 0x%08x, value: 0x%04x, err: %d\n", + offset, value, err); + } + + return err; +} + +static inline +int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value) +{ + int err; + + err = pci_write_config_dword(bcm->pci_dev, offset, value); + if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { + printk(KERN_INFO PFX "pciwrite32 offset: 0x%08x, value: 0x%08x, err: %d\n", + offset, value, err); + } + + return err; +} + +#define bcm43xx_mmioprint_initial(bcm, value) atomic_set(&(bcm)->mmio_print_cnt, (value)) +#define bcm43xx_mmioprint_enable(bcm) atomic_inc(&(bcm)->mmio_print_cnt) +#define bcm43xx_mmioprint_disable(bcm) atomic_dec(&(bcm)->mmio_print_cnt) +#define bcm43xx_pciprint_initial(bcm, value) atomic_set(&(bcm)->pcicfg_print_cnt, (value)) +#define bcm43xx_pciprint_enable(bcm) atomic_inc(&(bcm)->pcicfg_print_cnt) +#define bcm43xx_pciprint_disable(bcm) atomic_dec(&(bcm)->pcicfg_print_cnt) + +#else /* CONFIG_BCM43XX_DEBUG*/ + +#define bcm43xx_read16(bcm, offset) ioread16((bcm)->mmio_addr + core_offset(bcm) + (offset)) +#define bcm43xx_write16(bcm, offset, value) iowrite16((value), (bcm)->mmio_addr + core_offset(bcm) + (offset)) +#define bcm43xx_read32(bcm, offset) ioread32((bcm)->mmio_addr + core_offset(bcm) + (offset)) +#define bcm43xx_write32(bcm, offset, value) iowrite32((value), (bcm)->mmio_addr + core_offset(bcm) + (offset)) +#define bcm43xx_pci_read_config16(bcm, o, v) pci_read_config_word((bcm)->pci_dev, (o), (v)) +#define bcm43xx_pci_read_config32(bcm, o, v) pci_read_config_dword((bcm)->pci_dev, (o), (v)) +#define bcm43xx_pci_write_config16(bcm, o, v) pci_write_config_word((bcm)->pci_dev, (o), (v)) +#define bcm43xx_pci_write_config32(bcm, o, v) pci_write_config_dword((bcm)->pci_dev, (o), (v)) + +#define bcm43xx_mmioprint_initial(x, y) do { /* nothing */ } while (0) +#define bcm43xx_mmioprint_enable(x) do { /* nothing */ } while (0) +#define bcm43xx_mmioprint_disable(x) do { /* nothing */ } while (0) +#define bcm43xx_pciprint_initial(bcm, value) do { /* nothing */ } while (0) +#define bcm43xx_pciprint_enable(bcm) do { /* nothing */ } while (0) +#define bcm43xx_pciprint_disable(bcm) do { /* nothing */ } while (0) + +#endif /* CONFIG_BCM43XX_DEBUG*/ + + +/** Limit a value between two limits */ +#ifdef limit_value +# undef limit_value +#endif +#define limit_value(value, min, max) \ + ({ \ + typeof(value) __value = (value); \ + typeof(value) __min = (min); \ + typeof(value) __max = (max); \ + if (__value < __min) \ + __value = __min; \ + else if (__value > __max) \ + __value = __max; \ + __value; \ + }) + + +/* + * Compatibility stuff follows + */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) +# error "The bcm43xx driver does not support kernels < 2.6.15" +# error "The driver will _NOT_ compile on your kernel. Please upgrade to the latest 2.6 kernel." +# error "DO NOT COMPLAIN ABOUT BUGS. UPDATE FIRST AND TRY AGAIN." +#else +# if !defined(CONFIG_IEEE80211_MODULE) && !defined(CONFIG_IEEE80211) +# error "Generic IEEE 802.11 Networking Stack (CONFIG_IEEE80211) not available." +# endif +#endif +#ifdef IEEE80211SOFTMAC_API +# if IEEE80211SOFTMAC_API != 0 +# warning "Incompatible SoftMAC subsystem installed." +# endif +#else +# error "The bcm43xx driver requires the SoftMAC subsystem." +# error "SEE >>>>>> http://softmac.sipsolutions.net/ <<<<<<" +#endif + +#endif /* BCM43xx_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c new file mode 100644 index 000000000000..f8cfc84ca0da --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -0,0 +1,503 @@ +/* + + Broadcom BCM43xx wireless driver + + debugfs driver debugging code + + Copyright (c) 2005 Michael Buesch + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + + + +#include +#include +#include +#include +#include +#include + +#include "bcm43xx.h" +#include "bcm43xx_main.h" +#include "bcm43xx_debugfs.h" +#include "bcm43xx_dma.h" +#include "bcm43xx_pio.h" + +#define REALLY_BIG_BUFFER_SIZE (1024*256) + +static struct bcm43xx_debugfs fs; +static char really_big_buffer[REALLY_BIG_BUFFER_SIZE]; +static DECLARE_MUTEX(big_buffer_sem); + + +static ssize_t write_file_dummy(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + return count; +} + +static int open_file_generic(struct inode *inode, struct file *file) +{ + file->private_data = inode->u.generic_ip; + return 0; +} + +#define fappend(fmt, x...) pos += snprintf(buf + pos, len - pos, fmt , ##x) + +static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + const size_t len = REALLY_BIG_BUFFER_SIZE; + + struct bcm43xx_private *bcm = file->private_data; + char *buf = really_big_buffer; + size_t pos = 0; + ssize_t res; + struct net_device *net_dev; + struct pci_dev *pci_dev; + unsigned long flags; + u16 tmp16; + int i; + + down(&big_buffer_sem); + + spin_lock_irqsave(&bcm->lock, flags); + if (!bcm->initialized) { + fappend("Board not initialized.\n"); + goto out; + } + net_dev = bcm->net_dev; + pci_dev = bcm->pci_dev; + + /* This is where the information is written to the "devinfo" file */ + fappend("*** %s devinfo ***\n", net_dev->name); + fappend("vendor: 0x%04x device: 0x%04x\n", + pci_dev->vendor, pci_dev->device); + fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n", + pci_dev->subsystem_vendor, pci_dev->subsystem_device); + fappend("IRQ: %d\n", bcm->irq); + fappend("mmio_addr: 0x%p mmio_len: %u\n", bcm->mmio_addr, bcm->mmio_len); + fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev); + if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16))) + fappend("Radio disabled by hardware!\n"); + if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4))) + fappend("Radio disabled by hardware!\n"); + fappend("board_vendor: 0x%04x board_type: 0x%04x\n", bcm->board_vendor, + bcm->board_type); + + fappend("\nCores:\n"); +#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, " \ + "rev: 0x%02x, index: 0x%02x\n", \ + (info).flags & BCM43xx_COREFLAG_AVAILABLE \ + ? "available" : "nonavailable", \ + (info).flags & BCM43xx_COREFLAG_ENABLED \ + ? "enabled" : "disabled", \ + (info).id, (info).rev, (info).index) + fappend_core("CHIPCOMMON", bcm->core_chipcommon); + fappend_core("PCI", bcm->core_pci); + fappend_core("V90", bcm->core_v90); + fappend_core("PCMCIA", bcm->core_pcmcia); + fappend_core("ETHERNET", bcm->core_ethernet); + fappend_core("first 80211", bcm->core_80211[0]); + fappend_core("second 80211", bcm->core_80211[1]); +#undef fappend_core + tmp16 = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); + fappend("LEDs: "); + for (i = 0; i < BCM43xx_NR_LEDS; i++) + fappend("%d ", !!(tmp16 & (1 << i))); + fappend("\n"); + +out: + spin_unlock_irqrestore(&bcm->lock, flags); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + up(&big_buffer_sem); + return res; +} + +static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + const size_t len = REALLY_BIG_BUFFER_SIZE; + + char *buf = really_big_buffer; + size_t pos = 0; + ssize_t res; + + down(&big_buffer_sem); + + /* This is where the information is written to the "driver" file */ + fappend(BCM43xx_DRIVER_NAME "\n"); + fappend("Compiled at: %s %s\n", __DATE__, __TIME__); + + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + up(&big_buffer_sem); + return res; +} + +static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + const size_t len = REALLY_BIG_BUFFER_SIZE; + + struct bcm43xx_private *bcm = file->private_data; + char *buf = really_big_buffer; + size_t pos = 0; + ssize_t res; + unsigned long flags; + + down(&big_buffer_sem); + spin_lock_irqsave(&bcm->lock, flags); + if (!bcm->initialized) { + fappend("Board not initialized.\n"); + goto out; + } + + /* This is where the information is written to the "sprom_dump" file */ + fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); + +out: + spin_unlock_irqrestore(&bcm->lock, flags); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + up(&big_buffer_sem); + return res; +} + +static ssize_t tsf_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + const size_t len = REALLY_BIG_BUFFER_SIZE; + + struct bcm43xx_private *bcm = file->private_data; + char *buf = really_big_buffer; + size_t pos = 0; + ssize_t res; + unsigned long flags; + u64 tsf; + + down(&big_buffer_sem); + spin_lock_irqsave(&bcm->lock, flags); + if (!bcm->initialized) { + fappend("Board not initialized.\n"); + goto out; + } + bcm43xx_tsf_read(bcm, &tsf); + fappend("0x%08x%08x\n", + (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32), + (unsigned int)(tsf & 0xFFFFFFFFULL)); + +out: + spin_unlock_irqrestore(&bcm->lock, flags); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + up(&big_buffer_sem); + return res; +} + +static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct bcm43xx_private *bcm = file->private_data; + char *buf = really_big_buffer; + ssize_t buf_size; + ssize_t res; + unsigned long flags; + u64 tsf; + + buf_size = min(count, sizeof (really_big_buffer) - 1); + down(&big_buffer_sem); + if (copy_from_user(buf, user_buf, buf_size)) { + res = -EFAULT; + goto out_up; + } + spin_lock_irqsave(&bcm->lock, flags); + if (!bcm->initialized) { + printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); + res = -EFAULT; + goto out_unlock; + } + if (sscanf(buf, "%lli", &tsf) != 1) { + printk(KERN_INFO PFX "debugfs: invalid values for \"tsf\"\n"); + res = -EINVAL; + goto out_unlock; + } + bcm43xx_tsf_write(bcm, tsf); + res = buf_size; + +out_unlock: + spin_unlock_irqrestore(&bcm->lock, flags); +out_up: + up(&big_buffer_sem); + return res; +} + +static ssize_t txstat_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + const size_t len = REALLY_BIG_BUFFER_SIZE; + + struct bcm43xx_private *bcm = file->private_data; + char *buf = really_big_buffer; + size_t pos = 0; + ssize_t res; + unsigned long flags; + struct bcm43xx_dfsentry *e; + struct bcm43xx_xmitstatus *status; + int i, cnt, j = 0; + + down(&big_buffer_sem); + spin_lock_irqsave(&bcm->lock, flags); + + fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", + BCM43xx_NR_LOGGED_XMITSTATUS); + e = bcm->dfsentry; + if (e->xmitstatus_printing == 0) { + /* At the beginning, make a copy of all data to avoid + * concurrency, as this function is called multiple + * times for big logs. Without copying, the data might + * change between reads. This would result in total trash. + */ + e->xmitstatus_printing = 1; + e->saved_xmitstatus_ptr = e->xmitstatus_ptr; + e->saved_xmitstatus_cnt = e->xmitstatus_cnt; + memcpy(e->xmitstatus_print_buffer, e->xmitstatus_buffer, + BCM43xx_NR_LOGGED_XMITSTATUS * sizeof(*(e->xmitstatus_buffer))); + } + i = e->saved_xmitstatus_ptr - 1; + if (i < 0) + i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; + cnt = e->saved_xmitstatus_cnt; + while (cnt) { + status = e->xmitstatus_print_buffer + i; + fappend("0x%02x: cookie: 0x%04x, flags: 0x%02x, " + "cnt1: 0x%02x, cnt2: 0x%02x, seq: 0x%04x, " + "unk: 0x%04x\n", j, + status->cookie, status->flags, + status->cnt1, status->cnt2, status->seq, + status->unknown); + j++; + cnt--; + i--; + if (i < 0) + i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; + } + + spin_unlock_irqrestore(&bcm->lock, flags); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + spin_lock_irqsave(&bcm->lock, flags); + if (*ppos == pos) { + /* Done. Drop the copied data. */ + e->xmitstatus_printing = 0; + } + spin_unlock_irqrestore(&bcm->lock, flags); + up(&big_buffer_sem); + return res; +} + +#undef fappend + + +static struct file_operations devinfo_fops = { + .read = devinfo_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations spromdump_fops = { + .read = spromdump_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations drvinfo_fops = { + .read = drvinfo_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations tsf_fops = { + .read = tsf_read_file, + .write = tsf_write_file, + .open = open_file_generic, +}; + +static struct file_operations txstat_fops = { + .read = txstat_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + + +void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) +{ + struct bcm43xx_dfsentry *e; + char devdir[IFNAMSIZ]; + + assert(bcm); + e = kzalloc(sizeof(*e), GFP_KERNEL); + if (!e) { + printk(KERN_ERR PFX "out of memory\n"); + return; + } + e->bcm = bcm; + e->xmitstatus_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS + * sizeof(*(e->xmitstatus_buffer)), + GFP_KERNEL); + if (!e->xmitstatus_buffer) { + printk(KERN_ERR PFX "out of memory\n"); + kfree(e); + return; + } + e->xmitstatus_print_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS + * sizeof(*(e->xmitstatus_buffer)), + GFP_KERNEL); + if (!e->xmitstatus_print_buffer) { + printk(KERN_ERR PFX "out of memory\n"); + kfree(e); + return; + } + + + bcm->dfsentry = e; + + strncpy(devdir, bcm->net_dev->name, ARRAY_SIZE(devdir)); + e->subdir = debugfs_create_dir(devdir, fs.root); + e->dentry_devinfo = debugfs_create_file("devinfo", 0444, e->subdir, + bcm, &devinfo_fops); + if (!e->dentry_devinfo) + printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir); + e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir, + bcm, &spromdump_fops); + if (!e->dentry_spromdump) + printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir); + e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir, + bcm, &tsf_fops); + if (!e->dentry_tsf) + printk(KERN_ERR PFX "debugfs: creating \"tsf\" for \"%s\" failed!\n", devdir); + e->dentry_txstat = debugfs_create_file("tx_status", 0444, e->subdir, + bcm, &txstat_fops); + if (!e->dentry_txstat) + printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir); +} + +void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) +{ + struct bcm43xx_dfsentry *e; + + if (!bcm) + return; + + e = bcm->dfsentry; + assert(e); + debugfs_remove(e->dentry_spromdump); + debugfs_remove(e->dentry_devinfo); + debugfs_remove(e->dentry_tsf); + debugfs_remove(e->dentry_txstat); + debugfs_remove(e->subdir); + kfree(e->xmitstatus_buffer); + kfree(e->xmitstatus_print_buffer); + kfree(e); +} + +void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) +{ + struct bcm43xx_dfsentry *e; + struct bcm43xx_xmitstatus *savedstatus; + + /* This is protected by bcm->lock */ + e = bcm->dfsentry; + assert(e); + savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr; + memcpy(savedstatus, status, sizeof(*status)); + e->xmitstatus_ptr++; + if (e->xmitstatus_ptr >= BCM43xx_NR_LOGGED_XMITSTATUS) + e->xmitstatus_ptr = 0; + if (e->xmitstatus_cnt < BCM43xx_NR_LOGGED_XMITSTATUS) + e->xmitstatus_cnt++; +} + +void bcm43xx_debugfs_init(void) +{ + memset(&fs, 0, sizeof(fs)); + fs.root = debugfs_create_dir(DRV_NAME, NULL); + if (!fs.root) + printk(KERN_ERR PFX "debugfs: creating \"" DRV_NAME "\" subdir failed!\n"); + fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops); + if (!fs.dentry_driverinfo) + printk(KERN_ERR PFX "debugfs: creating \"" DRV_NAME "/driver\" failed!\n"); +} + +void bcm43xx_debugfs_exit(void) +{ + debugfs_remove(fs.dentry_driverinfo); + debugfs_remove(fs.root); +} + +void bcm43xx_printk_dump(const char *data, + size_t size, + const char *description) +{ + size_t i; + char c; + + printk(KERN_INFO PFX "Data dump (%s, %u bytes):", + description, size); + for (i = 0; i < size; i++) { + c = data[i]; + if (i % 8 == 0) + printk("\n" KERN_INFO PFX "0x%08x: 0x%02x, ", i, c & 0xff); + else + printk("0x%02x, ", c & 0xff); + } + printk("\n"); +} + +void bcm43xx_printk_bitdump(const unsigned char *data, + size_t bytes, int msb_to_lsb, + const char *description) +{ + size_t i; + int j; + const unsigned char *d; + + printk(KERN_INFO PFX "*** Bitdump (%s, %u bytes, %s) ***", + description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB"); + for (i = 0; i < bytes; i++) { + d = data + i; + if (i % 8 == 0) + printk("\n" KERN_INFO PFX "0x%08x: ", i); + if (msb_to_lsb) { + for (j = 7; j >= 0; j--) { + if (*d & (1 << j)) + printk("1"); + else + printk("0"); + } + } else { + for (j = 0; j < 8; j++) { + if (*d & (1 << j)) + printk("1"); + else + printk("0"); + } + } + printk(" "); + } + printk("\n"); +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h new file mode 100644 index 000000000000..50ce267f794d --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h @@ -0,0 +1,117 @@ +#ifndef BCM43xx_DEBUGFS_H_ +#define BCM43xx_DEBUGFS_H_ + +struct bcm43xx_private; +struct bcm43xx_xmitstatus; + +#ifdef CONFIG_BCM43XX_DEBUG + +#include +#include + +struct dentry; + +/* limited by the size of the "really_big_buffer" */ +#define BCM43xx_NR_LOGGED_XMITSTATUS 100 + +struct bcm43xx_dfsentry { + struct dentry *subdir; + struct dentry *dentry_devinfo; + struct dentry *dentry_spromdump; + struct dentry *dentry_tsf; + struct dentry *dentry_txstat; + + struct bcm43xx_private *bcm; + + /* saved xmitstatus. */ + struct bcm43xx_xmitstatus *xmitstatus_buffer; + int xmitstatus_ptr; + int xmitstatus_cnt; + /* We need a seperate buffer while printing to avoid + * concurrency issues. (New xmitstatus can arrive + * while we are printing). + */ + struct bcm43xx_xmitstatus *xmitstatus_print_buffer; + int saved_xmitstatus_ptr; + int saved_xmitstatus_cnt; + int xmitstatus_printing; +}; + +struct bcm43xx_debugfs { + struct dentry *root; + struct dentry *dentry_driverinfo; +}; + +void bcm43xx_debugfs_init(void); +void bcm43xx_debugfs_exit(void); +void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm); +void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm); +void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status); + +/* Debug helper: Dump binary data through printk. */ +void bcm43xx_printk_dump(const char *data, + size_t size, + const char *description); +/* Debug helper: Dump bitwise binary data through printk. */ +void bcm43xx_printk_bitdump(const unsigned char *data, + size_t bytes, int msb_to_lsb, + const char *description); +#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) \ + do { \ + bcm43xx_printk_bitdump((const unsigned char *)(pointer), \ + sizeof(*(pointer)), \ + (msb_to_lsb), \ + (description)); \ + } while (0) + +#else /* CONFIG_BCM43XX_DEBUG*/ + +static inline +void bcm43xx_debugfs_init(void) { } +static inline +void bcm43xx_debugfs_exit(void) { } +static inline +void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) { } +static inline +void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) { } +static inline +void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) { } + +static inline +void bcm43xx_printk_dump(const char *data, + size_t size, + const char *description) +{ +} +static inline +void bcm43xx_printk_bitdump(const unsigned char *data, + size_t bytes, int msb_to_lsb, + const char *description) +{ +} +#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) do { /* nothing */ } while (0) + +#endif /* CONFIG_BCM43XX_DEBUG*/ + +/* Ugly helper macros to make incomplete code more verbose on runtime */ +#ifdef TODO +# undef TODO +#endif +#define TODO() \ + do { \ + printk(KERN_INFO PFX "TODO: Incomplete code in %s() at %s:%d\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + } while (0) + +#ifdef FIXME +# undef FIXME +#endif +#define FIXME() \ + do { \ + printk(KERN_INFO PFX "FIXME: Possibly broken code in %s() at %s:%d\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + } while (0) + +#endif /* BCM43xx_DEBUGFS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c new file mode 100644 index 000000000000..df19fbfa9ea1 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -0,0 +1,1009 @@ +/* + + Broadcom BCM43xx wireless driver + + DMA ringbuffer and descriptor allocation/management + + Copyright (c) 2005 Michael Buesch + + Some code in this file is derived from the b44.c driver + Copyright (C) 2002 David S. Miller + Copyright (C) Pekka Pietikainen + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx.h" +#include "bcm43xx_dma.h" +#include "bcm43xx_main.h" +#include "bcm43xx_debugfs.h" +#include "bcm43xx_power.h" + +#include +#include +#include +#include +#include + + +static inline int free_slots(struct bcm43xx_dmaring *ring) +{ + return (ring->nr_slots - ring->used_slots); +} + +static inline int next_slot(struct bcm43xx_dmaring *ring, int slot) +{ + assert(slot >= -1 && slot <= ring->nr_slots - 1); + if (slot == ring->nr_slots - 1) + return 0; + return slot + 1; +} + +static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot) +{ + assert(slot >= 0 && slot <= ring->nr_slots - 1); + if (slot == 0) + return ring->nr_slots - 1; + return slot - 1; +} + +/* Request a slot for usage. */ +static inline +int request_slot(struct bcm43xx_dmaring *ring) +{ + int slot; + + assert(ring->tx); + assert(!ring->suspended); + assert(free_slots(ring) != 0); + + slot = next_slot(ring, ring->current_slot); + ring->current_slot = slot; + ring->used_slots++; + + /* Check the number of available slots and suspend TX, + * if we are running low on free slots. + */ + if (unlikely(free_slots(ring) < ring->suspend_mark)) { + netif_stop_queue(ring->bcm->net_dev); + ring->suspended = 1; + } +#ifdef CONFIG_BCM43XX_DEBUG + if (ring->used_slots > ring->max_used_slots) + ring->max_used_slots = ring->used_slots; +#endif /* CONFIG_BCM43XX_DEBUG*/ + + return slot; +} + +/* Return a slot to the free slots. */ +static inline +void return_slot(struct bcm43xx_dmaring *ring, int slot) +{ + assert(ring->tx); + + ring->used_slots--; + + /* Check if TX is suspended and check if we have + * enough free slots to resume it again. + */ + if (unlikely(ring->suspended)) { + if (free_slots(ring) >= ring->resume_mark) { + ring->suspended = 0; + netif_wake_queue(ring->bcm->net_dev); + } + } +} + +static inline +dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring, + unsigned char *buf, + size_t len, + int tx) +{ + dma_addr_t dmaaddr; + + if (tx) { + dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev, + buf, len, + DMA_TO_DEVICE); + } else { + dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev, + buf, len, + DMA_FROM_DEVICE); + } + + return dmaaddr; +} + +static inline +void unmap_descbuffer(struct bcm43xx_dmaring *ring, + dma_addr_t addr, + size_t len, + int tx) +{ + if (tx) { + dma_unmap_single(&ring->bcm->pci_dev->dev, + addr, len, + DMA_TO_DEVICE); + } else { + dma_unmap_single(&ring->bcm->pci_dev->dev, + addr, len, + DMA_FROM_DEVICE); + } +} + +static inline +void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring, + dma_addr_t addr, + size_t len) +{ + assert(!ring->tx); + + dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev, + addr, len, DMA_FROM_DEVICE); +} + +static inline +void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring, + dma_addr_t addr, + size_t len) +{ + assert(!ring->tx); + + dma_sync_single_for_device(&ring->bcm->pci_dev->dev, + addr, len, DMA_FROM_DEVICE); +} + +static inline +void mark_skb_mustfree(struct sk_buff *skb, + char mustfree) +{ + skb->cb[0] = mustfree; +} + +static inline +int skb_mustfree(struct sk_buff *skb) +{ + return (skb->cb[0] != 0); +} + +/* Unmap and free a descriptor buffer. */ +static inline +void free_descriptor_buffer(struct bcm43xx_dmaring *ring, + struct bcm43xx_dmadesc *desc, + struct bcm43xx_dmadesc_meta *meta, + int irq_context) +{ + assert(meta->skb); + if (skb_mustfree(meta->skb)) { + if (irq_context) + dev_kfree_skb_irq(meta->skb); + else + dev_kfree_skb(meta->skb); + } + meta->skb = NULL; + if (meta->txb) { + ieee80211_txb_free(meta->txb); + meta->txb = NULL; + } +} + +static int alloc_ringmemory(struct bcm43xx_dmaring *ring) +{ + struct device *dev = &(ring->bcm->pci_dev->dev); + + ring->vbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, + &(ring->dmabase), GFP_KERNEL); + if (!ring->vbase) { + printk(KERN_ERR PFX "DMA ringmemory allocation failed\n"); + return -ENOMEM; + } + if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) { + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G\n"); + dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, + ring->vbase, ring->dmabase); + return -ENOMEM; + } + assert(!(ring->dmabase & 0x000003FF)); + memset(ring->vbase, 0, BCM43xx_DMA_RINGMEMSIZE); + + return 0; +} + +static void free_ringmemory(struct bcm43xx_dmaring *ring) +{ + struct device *dev = &(ring->bcm->pci_dev->dev); + + dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, + ring->vbase, ring->dmabase); +} + +/* Reset the RX DMA channel */ +int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, + u16 mmio_base) +{ + int i; + u32 value; + + bcm43xx_write32(bcm, + mmio_base + BCM43xx_DMA_RX_CONTROL, + 0x00000000); + for (i = 0; i < 1000; i++) { + value = bcm43xx_read32(bcm, + mmio_base + BCM43xx_DMA_RX_STATUS); + value &= BCM43xx_DMA_RXSTAT_STAT_MASK; + if (value == BCM43xx_DMA_RXSTAT_STAT_DISABLED) { + i = -1; + break; + } + udelay(10); + } + if (i != -1) { + printk(KERN_ERR PFX "Error: Wait on DMA RX status timed out.\n"); + return -ENODEV; + } + + return 0; +} + +static inline int dmacontroller_rx_reset(struct bcm43xx_dmaring *ring) +{ + assert(!ring->tx); + + return bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base); +} + +/* Reset the RX DMA channel */ +int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, + u16 mmio_base) +{ + int i; + u32 value; + + for (i = 0; i < 1000; i++) { + value = bcm43xx_read32(bcm, + mmio_base + BCM43xx_DMA_TX_STATUS); + value &= BCM43xx_DMA_TXSTAT_STAT_MASK; + if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED || + value == BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT || + value == BCM43xx_DMA_TXSTAT_STAT_STOPPED) + break; + udelay(10); + } + bcm43xx_write32(bcm, + mmio_base + BCM43xx_DMA_TX_CONTROL, + 0x00000000); + for (i = 0; i < 1000; i++) { + value = bcm43xx_read32(bcm, + mmio_base + BCM43xx_DMA_TX_STATUS); + value &= BCM43xx_DMA_TXSTAT_STAT_MASK; + if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED) { + i = -1; + break; + } + udelay(10); + } + if (i != -1) { + printk(KERN_ERR PFX "Error: Wait on DMA TX status timed out.\n"); + return -ENODEV; + } + /* ensure the reset is completed. */ + udelay(300); + + return 0; +} + +static inline int dmacontroller_tx_reset(struct bcm43xx_dmaring *ring) +{ + assert(ring->tx); + + return bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base); +} + +static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, + struct bcm43xx_dmadesc *desc, + struct bcm43xx_dmadesc_meta *meta, + gfp_t gfp_flags) +{ + struct bcm43xx_rxhdr *rxhdr; + dma_addr_t dmaaddr; + u32 desc_addr; + u32 desc_ctl; + const int slot = (int)(desc - ring->vbase); + struct sk_buff *skb; + + assert(slot >= 0 && slot < ring->nr_slots); + assert(!ring->tx); + + skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); + if (unlikely(!skb)) + return -ENOMEM; + dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); + if (unlikely(dmaaddr + ring->rx_buffersize > BCM43xx_DMA_BUSADDRMAX)) { + unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); + dev_kfree_skb_any(skb); + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G\n"); + return -ENOMEM; + } + meta->skb = skb; + meta->dmaaddr = dmaaddr; + skb->dev = ring->bcm->net_dev; + mark_skb_mustfree(skb, 1); + desc_addr = (u32)(dmaaddr + ring->memoffset); + desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK & + (u32)(ring->rx_buffersize - ring->frameoffset)); + if (slot == ring->nr_slots - 1) + desc_ctl |= BCM43xx_DMADTOR_DTABLEEND; + set_desc_addr(desc, desc_addr); + set_desc_ctl(desc, desc_ctl); + + rxhdr = (struct bcm43xx_rxhdr *)(skb->data); + rxhdr->frame_length = 0; + rxhdr->flags1 = 0; + + return 0; +} + +/* Allocate the initial descbuffers. + * This is used for an RX ring only. + */ +static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring) +{ + int i, err = -ENOMEM; + struct bcm43xx_dmadesc *desc = NULL; + struct bcm43xx_dmadesc_meta *meta; + + for (i = 0; i < ring->nr_slots; i++) { + desc = ring->vbase + i; + meta = ring->meta + i; + + err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); + if (err) + goto err_unwind; + + assert(ring->used_slots <= ring->nr_slots); + } + ring->used_slots = ring->nr_slots; + + err = 0; +out: + return err; + +err_unwind: + for ( ; i >= 0; i--) { + desc = ring->vbase + i; + meta = ring->meta + i; + + unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); + dev_kfree_skb(meta->skb); + } + ring->used_slots = 0; + goto out; +} + +/* Do initial setup of the DMA controller. + * Reset the controller, write the ring busaddress + * and switch the "enable" bit on. + */ +static int dmacontroller_setup(struct bcm43xx_dmaring *ring) +{ + int err = 0; + u32 value; + + if (ring->tx) { + /* Set Transmit Control register to "transmit enable" */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_TX_CONTROL, + BCM43xx_DMA_TXCTRL_ENABLE); + /* Set Transmit Descriptor ring address. */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_TX_DESC_RING, + ring->dmabase + ring->memoffset); + } else { + err = alloc_initial_descbuffers(ring); + if (err) + goto out; + /* Set Receive Control "receive enable" and frame offset */ + value = (ring->frameoffset << BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT); + value |= BCM43xx_DMA_RXCTRL_ENABLE; + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_RX_CONTROL, + value); + /* Set Receive Descriptor ring address. */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_RX_DESC_RING, + ring->dmabase + ring->memoffset); + /* Init the descriptor pointer. */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_RX_DESC_INDEX, + 200); + } + +out: + return err; +} + +/* Shutdown the DMA controller. */ +static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring) +{ + if (ring->tx) { + dmacontroller_tx_reset(ring); + /* Zero out Transmit Descriptor ring address. */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_TX_DESC_RING, + 0x00000000); + } else { + dmacontroller_rx_reset(ring); + /* Zero out Receive Descriptor ring address. */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_RX_DESC_RING, + 0x00000000); + } +} + +static void free_all_descbuffers(struct bcm43xx_dmaring *ring) +{ + struct bcm43xx_dmadesc *desc; + struct bcm43xx_dmadesc_meta *meta; + int i; + + if (!ring->used_slots) + return; + for (i = 0; i < ring->nr_slots; i++) { + desc = ring->vbase + i; + meta = ring->meta + i; + + if (!meta->skb) { + assert(ring->tx); + assert(!meta->txb); + continue; + } + if (ring->tx) { + unmap_descbuffer(ring, meta->dmaaddr, + meta->skb->len, 1); + } else { + unmap_descbuffer(ring, meta->dmaaddr, + ring->rx_buffersize, 0); + } + free_descriptor_buffer(ring, desc, meta, 0); + } +} + +/* Main initialization function. */ +static +struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm, + u16 dma_controller_base, + int nr_descriptor_slots, + int tx) +{ + struct bcm43xx_dmaring *ring; + int err; + + ring = kzalloc(sizeof(*ring), GFP_KERNEL); + if (!ring) + goto out; + + ring->meta = kzalloc(sizeof(*ring->meta) * nr_descriptor_slots, + GFP_KERNEL); + if (!ring->meta) + goto err_kfree_ring; + + ring->memoffset = BCM43xx_DMA_DMABUSADDROFFSET; +#ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) + ring->memoffset = 0; +#endif + + + spin_lock_init(&ring->lock); + ring->bcm = bcm; + ring->nr_slots = nr_descriptor_slots; + ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100; + ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100; + assert(ring->suspend_mark < ring->resume_mark); + ring->mmio_base = dma_controller_base; + if (tx) { + ring->tx = 1; + ring->current_slot = -1; + } else { + switch (dma_controller_base) { + case BCM43xx_MMIO_DMA1_BASE: + ring->rx_buffersize = BCM43xx_DMA1_RXBUFFERSIZE; + ring->frameoffset = BCM43xx_DMA1_RX_FRAMEOFFSET; + break; + case BCM43xx_MMIO_DMA4_BASE: + ring->rx_buffersize = BCM43xx_DMA4_RXBUFFERSIZE; + ring->frameoffset = BCM43xx_DMA4_RX_FRAMEOFFSET; + break; + default: + assert(0); + } + } + + err = alloc_ringmemory(ring); + if (err) + goto err_kfree_meta; + err = dmacontroller_setup(ring); + if (err) + goto err_free_ringmemory; + +out: + return ring; + +err_free_ringmemory: + free_ringmemory(ring); +err_kfree_meta: + kfree(ring->meta); +err_kfree_ring: + kfree(ring); + ring = NULL; + goto out; +} + +/* Main cleanup function. */ +static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring) +{ + if (!ring) + return; + + dprintk(KERN_INFO PFX "DMA 0x%04x (%s) max used slots: %d/%d\n", + ring->mmio_base, + (ring->tx) ? "TX" : "RX", + ring->max_used_slots, ring->nr_slots); + /* Device IRQs are disabled prior entering this function, + * so no need to take care of concurrency with rx handler stuff. + */ + dmacontroller_cleanup(ring); + free_all_descbuffers(ring); + free_ringmemory(ring); + + kfree(ring->meta); + kfree(ring); +} + +void bcm43xx_dma_free(struct bcm43xx_private *bcm) +{ + bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring1); + bcm->current_core->dma->rx_ring1 = NULL; + bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring0); + bcm->current_core->dma->rx_ring0 = NULL; + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring3); + bcm->current_core->dma->tx_ring3 = NULL; + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring2); + bcm->current_core->dma->tx_ring2 = NULL; + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring1); + bcm->current_core->dma->tx_ring1 = NULL; + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring0); + bcm->current_core->dma->tx_ring0 = NULL; +} + +int bcm43xx_dma_init(struct bcm43xx_private *bcm) +{ + struct bcm43xx_dmaring *ring; + int err = -ENOMEM; + + /* setup TX DMA channels. */ + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE, + BCM43xx_TXRING_SLOTS, 1); + if (!ring) + goto out; + bcm->current_core->dma->tx_ring0 = ring; + + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA2_BASE, + BCM43xx_TXRING_SLOTS, 1); + if (!ring) + goto err_destroy_tx0; + bcm->current_core->dma->tx_ring1 = ring; + + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA3_BASE, + BCM43xx_TXRING_SLOTS, 1); + if (!ring) + goto err_destroy_tx1; + bcm->current_core->dma->tx_ring2 = ring; + + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, + BCM43xx_TXRING_SLOTS, 1); + if (!ring) + goto err_destroy_tx2; + bcm->current_core->dma->tx_ring3 = ring; + + /* setup RX DMA channels. */ + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE, + BCM43xx_RXRING_SLOTS, 0); + if (!ring) + goto err_destroy_tx3; + bcm->current_core->dma->rx_ring0 = ring; + + if (bcm->current_core->rev < 5) { + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, + BCM43xx_RXRING_SLOTS, 0); + if (!ring) + goto err_destroy_rx0; + bcm->current_core->dma->rx_ring1 = ring; + } + + dprintk(KERN_INFO PFX "DMA initialized\n"); + err = 0; +out: + return err; + +err_destroy_rx0: + bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring0); + bcm->current_core->dma->rx_ring0 = NULL; +err_destroy_tx3: + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring3); + bcm->current_core->dma->tx_ring3 = NULL; +err_destroy_tx2: + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring2); + bcm->current_core->dma->tx_ring2 = NULL; +err_destroy_tx1: + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring1); + bcm->current_core->dma->tx_ring1 = NULL; +err_destroy_tx0: + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring0); + bcm->current_core->dma->tx_ring0 = NULL; + goto out; +} + +/* Generate a cookie for the TX header. */ +static inline +u16 generate_cookie(struct bcm43xx_dmaring *ring, + int slot) +{ + u16 cookie = 0x0000; + + /* Use the upper 4 bits of the cookie as + * DMA controller ID and store the slot number + * in the lower 12 bits + */ + switch (ring->mmio_base) { + default: + assert(0); + case BCM43xx_MMIO_DMA1_BASE: + break; + case BCM43xx_MMIO_DMA2_BASE: + cookie = 0x1000; + break; + case BCM43xx_MMIO_DMA3_BASE: + cookie = 0x2000; + break; + case BCM43xx_MMIO_DMA4_BASE: + cookie = 0x3000; + break; + } + assert(((u16)slot & 0xF000) == 0x0000); + cookie |= (u16)slot; + + return cookie; +} + +/* Inspect a cookie and find out to which controller/slot it belongs. */ +static inline +struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, + u16 cookie, int *slot) +{ + struct bcm43xx_dmaring *ring = NULL; + + switch (cookie & 0xF000) { + case 0x0000: + ring = bcm->current_core->dma->tx_ring0; + break; + case 0x1000: + ring = bcm->current_core->dma->tx_ring1; + break; + case 0x2000: + ring = bcm->current_core->dma->tx_ring2; + break; + case 0x3000: + ring = bcm->current_core->dma->tx_ring3; + break; + default: + assert(0); + } + *slot = (cookie & 0x0FFF); + assert(*slot >= 0 && *slot < ring->nr_slots); + + return ring; +} + +static inline void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, + int slot) +{ + /* Everything is ready to start. Buffers are DMA mapped and + * associated with slots. + * "slot" is the last slot of the new frame we want to transmit. + * Close your seat belts now, please. + */ + wmb(); + slot = next_slot(ring, slot); + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_TX_DESC_INDEX, + (u32)(slot * sizeof(struct bcm43xx_dmadesc))); +} + +static inline +int dma_tx_fragment(struct bcm43xx_dmaring *ring, + struct sk_buff *skb, + struct ieee80211_txb *txb, + u8 cur_frag) +{ + int slot; + struct bcm43xx_dmadesc *desc; + struct bcm43xx_dmadesc_meta *meta; + u32 desc_ctl; + u32 desc_addr; + + assert(skb_shinfo(skb)->nr_frags == 0); + + slot = request_slot(ring); + desc = ring->vbase + slot; + meta = ring->meta + slot; + + if (cur_frag == 0) { + /* Save the txb pointer for freeing in xmitstatus IRQ */ + meta->txb = txb; + } + + /* Add a device specific TX header. */ + assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); + /* Reserve enough headroom for the device tx header. */ + __skb_push(skb, sizeof(struct bcm43xx_txhdr)); + /* Now calculate and add the tx header. + * The tx header includes the PLCP header. + */ + bcm43xx_generate_txhdr(ring->bcm, + (struct bcm43xx_txhdr *)skb->data, + skb->data + sizeof(struct bcm43xx_txhdr), + skb->len - sizeof(struct bcm43xx_txhdr), + (cur_frag == 0), + generate_cookie(ring, slot)); + + meta->skb = skb; + meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); + if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) { + return_slot(ring, slot); + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G\n"); + return -ENOMEM; + } + + desc_addr = (u32)(meta->dmaaddr + ring->memoffset); + desc_ctl = BCM43xx_DMADTOR_FRAMESTART | BCM43xx_DMADTOR_FRAMEEND; + desc_ctl |= BCM43xx_DMADTOR_COMPIRQ; + desc_ctl |= (BCM43xx_DMADTOR_BYTECNT_MASK & + (u32)(meta->skb->len - ring->frameoffset)); + if (slot == ring->nr_slots - 1) + desc_ctl |= BCM43xx_DMADTOR_DTABLEEND; + + set_desc_ctl(desc, desc_ctl); + set_desc_addr(desc, desc_addr); + /* Now transfer the whole frame. */ + dmacontroller_poke_tx(ring, slot); + + return 0; +} + +static inline int dma_transfer_txb(struct bcm43xx_dmaring *ring, + struct ieee80211_txb *txb) +{ + /* We just received a packet from the kernel network subsystem. + * Add headers and DMA map the memory. Poke + * the device to send the stuff. + * Note that this is called from atomic context. + */ + u8 i; + struct sk_buff *skb; + + assert(ring->tx); + if (unlikely(free_slots(ring) < txb->nr_frags)) { + /* The queue should be stopped, + * if we are low on free slots. + * If this ever triggers, we have to lower the suspend_mark. + */ + dprintkl(KERN_ERR PFX "Out of DMA descriptor slots!\n"); + return -ENOMEM; + } + + assert(irqs_disabled()); + spin_lock(&ring->lock); + for (i = 0; i < txb->nr_frags; i++) { + skb = txb->fragments[i]; + /* We do not free the skb, as it is freed as + * part of the txb freeing. + */ + mark_skb_mustfree(skb, 0); + dma_tx_fragment(ring, skb, txb, i); + //TODO: handle failure of dma_tx_fragment + } + spin_unlock(&ring->lock); + + return 0; +} + +int fastcall +bcm43xx_dma_transfer_txb(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) +{ + return dma_transfer_txb(bcm->current_core->dma->tx_ring1, + txb); +} + +void fastcall +bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) +{ + struct bcm43xx_dmaring *ring; + struct bcm43xx_dmadesc *desc; + struct bcm43xx_dmadesc_meta *meta; + int is_last_fragment; + int slot; + + ring = parse_cookie(bcm, status->cookie, &slot); + assert(ring); + assert(ring->tx); + assert(irqs_disabled()); + spin_lock(&ring->lock); + + assert(get_desc_ctl(ring->vbase + slot) & BCM43xx_DMADTOR_FRAMESTART); + while (1) { + assert(slot >= 0 && slot < ring->nr_slots); + desc = ring->vbase + slot; + meta = ring->meta + slot; + + is_last_fragment = !!(get_desc_ctl(desc) & BCM43xx_DMADTOR_FRAMEEND); + unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); + free_descriptor_buffer(ring, desc, meta, 1); + /* Everything belonging to the slot is unmapped + * and freed, so we can return it. + */ + return_slot(ring, slot); + + if (is_last_fragment) + break; + slot = next_slot(ring, slot); + } + bcm->stats.last_tx = jiffies; + + spin_unlock(&ring->lock); +} + +static inline +void dma_rx(struct bcm43xx_dmaring *ring, + int *slot) +{ + struct bcm43xx_dmadesc *desc; + struct bcm43xx_dmadesc_meta *meta; + struct bcm43xx_rxhdr *rxhdr; + struct sk_buff *skb; + u16 len; + int err; + dma_addr_t dmaaddr; + + desc = ring->vbase + *slot; + meta = ring->meta + *slot; + + sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); + skb = meta->skb; + + if (ring->mmio_base == BCM43xx_MMIO_DMA4_BASE) { + /* We received an xmit status. */ + struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data; + struct bcm43xx_xmitstatus stat; + + stat.cookie = le16_to_cpu(hw->cookie); + stat.flags = hw->flags; + stat.cnt1 = hw->cnt1; + stat.cnt2 = hw->cnt2; + stat.seq = le16_to_cpu(hw->seq); + stat.unknown = le16_to_cpu(hw->unknown); + + bcm43xx_debugfs_log_txstat(ring->bcm, &stat); + bcm43xx_dma_handle_xmitstatus(ring->bcm, &stat); + /* recycle the descriptor buffer. */ + sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize); + + return; + } + rxhdr = (struct bcm43xx_rxhdr *)skb->data; + len = le16_to_cpu(rxhdr->frame_length); + if (len == 0) { + int i = 0; + + do { + udelay(2); + barrier(); + len = le16_to_cpu(rxhdr->frame_length); + } while (len == 0 && i++ < 5); + if (len == 0) + goto drop; + } + if (unlikely(len > ring->rx_buffersize)) { + /* The data did not fit into one descriptor buffer + * and is split over multiple buffers. + * This should never happen, as we try to allocate buffers + * big enough. So simply ignore this packet. + */ + int cnt = 1; + s32 tmp = len - ring->rx_buffersize; + + for ( ; tmp > 0; tmp -= ring->rx_buffersize) { + *slot = next_slot(ring, *slot); + cnt++; + } + printkl(KERN_ERR PFX "DMA RX buffer too small. %d dropped.\n", + cnt); + goto drop; + } + len -= IEEE80211_FCS_LEN; + + dmaaddr = meta->dmaaddr; + err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC); + if (unlikely(err)) { + dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n"); + goto drop; + } + + unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); + skb_put(skb, len + ring->frameoffset); + skb_pull(skb, ring->frameoffset); + + err = bcm43xx_rx(ring->bcm, skb, rxhdr); + if (err) { + dev_kfree_skb_irq(skb); + goto drop; + } + +drop: + return; +} + +void fastcall +bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) +{ + u32 status; + u16 descptr; + int slot, current_slot; +#ifdef CONFIG_BCM43XX_DEBUG + int used_slots = 0; +#endif + + assert(!ring->tx); + assert(irqs_disabled()); + spin_lock(&ring->lock); + + status = bcm43xx_read32(ring->bcm, ring->mmio_base + BCM43xx_DMA_RX_STATUS); + descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK); + current_slot = descptr / sizeof(struct bcm43xx_dmadesc); + assert(current_slot >= 0 && current_slot < ring->nr_slots); + + slot = ring->current_slot; + for ( ; slot != current_slot; slot = next_slot(ring, slot)) { + dma_rx(ring, &slot); +#ifdef CONFIG_BCM43XX_DEBUG + if (++used_slots > ring->max_used_slots) + ring->max_used_slots = used_slots; +#endif + } + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_RX_DESC_INDEX, + (u32)(slot * sizeof(struct bcm43xx_dmadesc))); + ring->current_slot = slot; + + spin_unlock(&ring->lock); +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h new file mode 100644 index 000000000000..e32cf68f8e1d --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -0,0 +1,176 @@ +#ifndef BCM43xx_DMA_H_ +#define BCM43xx_DMA_H_ + +#include +#include +#include +#include +#include + + +/* DMA-Interrupt reasons. */ +/*TODO: add the missing ones. */ +#define BCM43xx_DMAIRQ_ERR0 (1 << 10) +#define BCM43xx_DMAIRQ_ERR1 (1 << 11) +#define BCM43xx_DMAIRQ_ERR2 (1 << 12) +#define BCM43xx_DMAIRQ_ERR3 (1 << 13) +#define BCM43xx_DMAIRQ_ERR4 (1 << 14) +#define BCM43xx_DMAIRQ_ERR5 (1 << 15) +#define BCM43xx_DMAIRQ_RX_DONE (1 << 16) +/* helpers */ +#define BCM43xx_DMAIRQ_ANYERR (BCM43xx_DMAIRQ_ERR0 | \ + BCM43xx_DMAIRQ_ERR1 | \ + BCM43xx_DMAIRQ_ERR2 | \ + BCM43xx_DMAIRQ_ERR3 | \ + BCM43xx_DMAIRQ_ERR4 | \ + BCM43xx_DMAIRQ_ERR5) +#define BCM43xx_DMAIRQ_FATALERR (BCM43xx_DMAIRQ_ERR0 | \ + BCM43xx_DMAIRQ_ERR1 | \ + BCM43xx_DMAIRQ_ERR2 | \ + BCM43xx_DMAIRQ_ERR4 | \ + BCM43xx_DMAIRQ_ERR5) +#define BCM43xx_DMAIRQ_NONFATALERR BCM43xx_DMAIRQ_ERR3 + +/* DMA controller register offsets. (relative to BCM43xx_DMA#_BASE) */ +#define BCM43xx_DMA_TX_CONTROL 0x00 +#define BCM43xx_DMA_TX_DESC_RING 0x04 +#define BCM43xx_DMA_TX_DESC_INDEX 0x08 +#define BCM43xx_DMA_TX_STATUS 0x0c +#define BCM43xx_DMA_RX_CONTROL 0x10 +#define BCM43xx_DMA_RX_DESC_RING 0x14 +#define BCM43xx_DMA_RX_DESC_INDEX 0x18 +#define BCM43xx_DMA_RX_STATUS 0x1c + +/* DMA controller channel control word values. */ +#define BCM43xx_DMA_TXCTRL_ENABLE (1 << 0) +#define BCM43xx_DMA_TXCTRL_SUSPEND (1 << 1) +#define BCM43xx_DMA_TXCTRL_LOOPBACK (1 << 2) +#define BCM43xx_DMA_TXCTRL_FLUSH (1 << 4) +#define BCM43xx_DMA_RXCTRL_ENABLE (1 << 0) +#define BCM43xx_DMA_RXCTRL_FRAMEOFF_MASK 0x000000fe +#define BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT 1 +#define BCM43xx_DMA_RXCTRL_PIO (1 << 8) +/* DMA controller channel status word values. */ +#define BCM43xx_DMA_TXSTAT_DPTR_MASK 0x00000fff +#define BCM43xx_DMA_TXSTAT_STAT_MASK 0x0000f000 +#define BCM43xx_DMA_TXSTAT_STAT_DISABLED 0x00000000 +#define BCM43xx_DMA_TXSTAT_STAT_ACTIVE 0x00001000 +#define BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT 0x00002000 +#define BCM43xx_DMA_TXSTAT_STAT_STOPPED 0x00003000 +#define BCM43xx_DMA_TXSTAT_STAT_SUSP 0x00004000 +#define BCM43xx_DMA_TXSTAT_ERROR_MASK 0x000f0000 +#define BCM43xx_DMA_TXSTAT_FLUSHED (1 << 20) +#define BCM43xx_DMA_RXSTAT_DPTR_MASK 0x00000fff +#define BCM43xx_DMA_RXSTAT_STAT_MASK 0x0000f000 +#define BCM43xx_DMA_RXSTAT_STAT_DISABLED 0x00000000 +#define BCM43xx_DMA_RXSTAT_STAT_ACTIVE 0x00001000 +#define BCM43xx_DMA_RXSTAT_STAT_IDLEWAIT 0x00002000 +#define BCM43xx_DMA_RXSTAT_STAT_RESERVED 0x00003000 +#define BCM43xx_DMA_RXSTAT_STAT_ERRORS 0x00004000 +#define BCM43xx_DMA_RXSTAT_ERROR_MASK 0x000f0000 + +/* DMA descriptor control field values. */ +#define BCM43xx_DMADTOR_BYTECNT_MASK 0x00001fff +#define BCM43xx_DMADTOR_DTABLEEND (1 << 28) /* End of descriptor table */ +#define BCM43xx_DMADTOR_COMPIRQ (1 << 29) /* IRQ on completion request */ +#define BCM43xx_DMADTOR_FRAMEEND (1 << 30) +#define BCM43xx_DMADTOR_FRAMESTART (1 << 31) + +/* Misc DMA constants */ +#define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE +#define BCM43xx_DMA_BUSADDRMAX 0x3FFFFFFF +#define BCM43xx_DMA_DMABUSADDROFFSET (1 << 30) +#define BCM43xx_DMA1_RX_FRAMEOFFSET 30 +#define BCM43xx_DMA4_RX_FRAMEOFFSET 0 + +/* DMA engine tuning knobs */ +#define BCM43xx_TXRING_SLOTS 512 +#define BCM43xx_RXRING_SLOTS 64 +#define BCM43xx_DMA1_RXBUFFERSIZE (2304 + 100) +#define BCM43xx_DMA4_RXBUFFERSIZE 16 +/* Suspend the tx queue, if less than this percent slots are free. */ +#define BCM43xx_TXSUSPEND_PERCENT 20 +/* Resume the tx queue, if more than this percent slots are free. */ +#define BCM43xx_TXRESUME_PERCENT 50 + + +struct sk_buff; +struct bcm43xx_private; +struct bcm43xx_xmitstatus; + + +struct bcm43xx_dmadesc { + __le32 _control; + __le32 _address; +} __attribute__((__packed__)); + +/* Macros to access the bcm43xx_dmadesc struct */ +#define get_desc_ctl(desc) le32_to_cpu((desc)->_control) +#define set_desc_ctl(desc, ctl) do { (desc)->_control = cpu_to_le32(ctl); } while (0) +#define get_desc_addr(desc) le32_to_cpu((desc)->_address) +#define set_desc_addr(desc, addr) do { (desc)->_address = cpu_to_le32(addr); } while (0) + +struct bcm43xx_dmadesc_meta { + /* The kernel DMA-able buffer. */ + struct sk_buff *skb; + /* DMA base bus-address of the descriptor buffer. */ + dma_addr_t dmaaddr; + /* Pointer to our txb (can be NULL). + * This should be freed in completion IRQ. + */ + struct ieee80211_txb *txb; +}; + +struct bcm43xx_dmaring { + spinlock_t lock; + struct bcm43xx_private *bcm; + /* Kernel virtual base address of the ring memory. */ + struct bcm43xx_dmadesc *vbase; + /* DMA memory offset */ + dma_addr_t memoffset; + /* (Unadjusted) DMA base bus-address of the ring memory. */ + dma_addr_t dmabase; + /* Meta data about all descriptors. */ + struct bcm43xx_dmadesc_meta *meta; + /* Number of descriptor slots in the ring. */ + int nr_slots; + /* Number of used descriptor slots. */ + int used_slots; + /* Currently used slot in the ring. */ + int current_slot; + /* Marks to suspend/resume the queue. */ + int suspend_mark; + int resume_mark; + /* Frameoffset in octets. */ + u32 frameoffset; + /* Descriptor buffer size. */ + u16 rx_buffersize; + /* The MMIO base register of the DMA controller, this + * ring is posted to. + */ + u16 mmio_base; + u8 tx:1, /* TRUE, if this is a TX ring. */ + suspended:1; /* TRUE, if transfers are suspended on this ring. */ +#ifdef CONFIG_BCM43XX_DEBUG + /* Maximum number of used slots. */ + int max_used_slots; +#endif /* CONFIG_BCM43XX_DEBUG*/ +}; + + +int bcm43xx_dma_init(struct bcm43xx_private *bcm); +void bcm43xx_dma_free(struct bcm43xx_private *bcm); + +int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, + u16 dmacontroller_mmio_base); +int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, + u16 dmacontroller_mmio_base); + +int FASTCALL(bcm43xx_dma_transfer_txb(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb)); +void FASTCALL(bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status)); + +void FASTCALL(bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)); + +#endif /* BCM43xx_DMA_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c new file mode 100644 index 000000000000..22587e0e1a05 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c @@ -0,0 +1,367 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx.h" +#include "bcm43xx_ilt.h" +#include "bcm43xx_phy.h" + + +/**** Initial Internal Lookup Tables ****/ + +const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE] = { + 0xFEB93FFD, 0xFEC63FFD, /* 0 */ + 0xFED23FFD, 0xFEDF3FFD, + 0xFEEC3FFE, 0xFEF83FFE, + 0xFF053FFE, 0xFF113FFE, + 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */ + 0xFF373FFF, 0xFF443FFF, + 0xFF503FFF, 0xFF5D3FFF, + 0xFF693FFF, 0xFF763FFF, + 0xFF824000, 0xFF8F4000, /* 16 */ + 0xFF9B4000, 0xFFA84000, + 0xFFB54000, 0xFFC14000, + 0xFFCE4000, 0xFFDA4000, + 0xFFE74000, 0xFFF34000, /* 24 */ + 0x00004000, 0x000D4000, + 0x00194000, 0x00264000, + 0x00324000, 0x003F4000, + 0x004B4000, 0x00584000, /* 32 */ + 0x00654000, 0x00714000, + 0x007E4000, 0x008A3FFF, + 0x00973FFF, 0x00A33FFF, + 0x00B03FFF, 0x00BC3FFF, /* 40 */ + 0x00C93FFF, 0x00D63FFF, + 0x00E23FFE, 0x00EF3FFE, + 0x00FB3FFE, 0x01083FFE, + 0x01143FFE, 0x01213FFD, /* 48 */ + 0x012E3FFD, 0x013A3FFD, + 0x01473FFD, +}; + +const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE] = { + 0xDB93CB87, 0xD666CF64, /* 0 */ + 0xD1FDD358, 0xCDA6D826, + 0xCA38DD9F, 0xC729E2B4, + 0xC469E88E, 0xC26AEE2B, + 0xC0DEF46C, 0xC073FA62, /* 8 */ + 0xC01D00D5, 0xC0760743, + 0xC1560D1E, 0xC2E51369, + 0xC4ED18FF, 0xC7AC1ED7, + 0xCB2823B2, 0xCEFA28D9, /* 16 */ + 0xD2F62D3F, 0xD7BB3197, + 0xDCE53568, 0xE1FE3875, + 0xE7D13B35, 0xED663D35, + 0xF39B3EC4, 0xF98E3FA7, /* 24 */ + 0x00004000, 0x06723FA7, + 0x0C653EC4, 0x129A3D35, + 0x182F3B35, 0x1E023875, + 0x231B3568, 0x28453197, /* 32 */ + 0x2D0A2D3F, 0x310628D9, + 0x34D823B2, 0x38541ED7, + 0x3B1318FF, 0x3D1B1369, + 0x3EAA0D1E, 0x3F8A0743, /* 40 */ + 0x3FE300D5, 0x3F8DFA62, + 0x3F22F46C, 0x3D96EE2B, + 0x3B97E88E, 0x38D7E2B4, + 0x35C8DD9F, 0x325AD826, /* 48 */ + 0x2E03D358, 0x299ACF64, + 0x246DCB87, +}; + +const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE] = { + 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */ + 0x0202, 0x0282, 0x0302, 0x0382, + 0x0402, 0x0482, 0x0502, 0x0582, + 0x05E2, 0x0662, 0x06E2, 0x0762, + 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */ + 0x09C2, 0x0A22, 0x0AA2, 0x0B02, + 0x0B82, 0x0BE2, 0x0C62, 0x0CC2, + 0x0D42, 0x0DA2, 0x0E02, 0x0E62, + 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */ + 0x1062, 0x10C2, 0x1122, 0x1182, + 0x11E2, 0x1242, 0x12A2, 0x12E2, + 0x1342, 0x13A2, 0x1402, 0x1442, + 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */ + 0x15E2, 0x1622, 0x1662, 0x16C1, + 0x1701, 0x1741, 0x1781, 0x17E1, + 0x1821, 0x1861, 0x18A1, 0x18E1, + 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */ + 0x1A21, 0x1A61, 0x1AA1, 0x1AC1, + 0x1B01, 0x1B41, 0x1B81, 0x1BA1, + 0x1BE1, 0x1C21, 0x1C41, 0x1C81, + 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */ + 0x1D61, 0x1DA1, 0x1DC1, 0x1E01, + 0x1E21, 0x1E61, 0x1E81, 0x1EA1, + 0x1EE1, 0x1F01, 0x1F21, 0x1F41, + 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */ + 0x2001, 0x2041, 0x2061, 0x2081, + 0x20A1, 0x20C1, 0x20E1, 0x2101, + 0x2121, 0x2141, 0x2161, 0x2181, + 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */ + 0x2221, 0x2241, 0x2261, 0x2281, + 0x22A1, 0x22C1, 0x22C1, 0x22E1, + 0x2301, 0x2321, 0x2341, 0x2361, + 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */ + 0x23E1, 0x23E1, 0x2401, 0x2421, + 0x2441, 0x2441, 0x2461, 0x2481, + 0x2481, 0x24A1, 0x24C1, 0x24C1, + 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */ + 0x2541, 0x2541, 0x2561, 0x2561, + 0x2581, 0x25A1, 0x25A1, 0x25C1, + 0x25C1, 0x25E1, 0x2601, 0x2601, + 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */ + 0x2661, 0x2661, 0x2681, 0x2681, + 0x26A1, 0x26A1, 0x26C1, 0x26C1, + 0x26E1, 0x26E1, 0x2701, 0x2701, + 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */ + 0x2760, 0x2760, 0x2780, 0x2780, + 0x2780, 0x27A0, 0x27A0, 0x27C0, + 0x27C0, 0x27E0, 0x27E0, 0x27E0, + 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */ + 0x2820, 0x2840, 0x2840, 0x2840, + 0x2860, 0x2860, 0x2880, 0x2880, + 0x2880, 0x28A0, 0x28A0, 0x28A0, + 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */ + 0x28E0, 0x28E0, 0x2900, 0x2900, + 0x2900, 0x2920, 0x2920, 0x2920, + 0x2940, 0x2940, 0x2940, 0x2960, + 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */ + 0x2980, 0x2980, 0x29A0, 0x29A0, + 0x29A0, 0x29A0, 0x29C0, 0x29C0, + 0x29C0, 0x29E0, 0x29E0, 0x29E0, + 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */ + 0x2A00, 0x2A20, 0x2A20, 0x2A20, + 0x2A20, 0x2A40, 0x2A40, 0x2A40, + 0x2A40, 0x2A60, 0x2A60, 0x2A60, +}; + +const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE] = { + 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */ + 0x05A9, 0x0669, 0x0709, 0x0789, + 0x0829, 0x08A9, 0x0929, 0x0989, + 0x0A09, 0x0A69, 0x0AC9, 0x0B29, + 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */ + 0x0D09, 0x0D69, 0x0DA9, 0x0E09, + 0x0E69, 0x0EA9, 0x0F09, 0x0F49, + 0x0FA9, 0x0FE9, 0x1029, 0x1089, + 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */ + 0x11E9, 0x1229, 0x1289, 0x12C9, + 0x1309, 0x1349, 0x1389, 0x13C9, + 0x1409, 0x1449, 0x14A9, 0x14E9, + 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */ + 0x1629, 0x1669, 0x16A9, 0x16E8, + 0x1728, 0x1768, 0x17A8, 0x17E8, + 0x1828, 0x1868, 0x18A8, 0x18E8, + 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */ + 0x1A28, 0x1A68, 0x1AA8, 0x1AE8, + 0x1B28, 0x1B68, 0x1BA8, 0x1BE8, + 0x1C28, 0x1C68, 0x1CA8, 0x1CE8, + 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */ + 0x1E48, 0x1E88, 0x1EC8, 0x1F08, + 0x1F48, 0x1F88, 0x1FE8, 0x2028, + 0x2068, 0x20A8, 0x2108, 0x2148, + 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */ + 0x22C8, 0x2308, 0x2348, 0x23A8, + 0x23E8, 0x2448, 0x24A8, 0x24E8, + 0x2548, 0x25A8, 0x2608, 0x2668, + 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */ + 0x2847, 0x28C7, 0x2947, 0x29A7, + 0x2A27, 0x2AC7, 0x2B47, 0x2BE7, + 0x2CA7, 0x2D67, 0x2E47, 0x2F67, + 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */ + 0x3806, 0x38A6, 0x3946, 0x39E6, + 0x3A66, 0x3AE6, 0x3B66, 0x3BC6, + 0x3C45, 0x3CA5, 0x3D05, 0x3D85, + 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */ + 0x3F45, 0x3FA5, 0x4005, 0x4045, + 0x40A5, 0x40E5, 0x4145, 0x4185, + 0x41E5, 0x4225, 0x4265, 0x42C5, + 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */ + 0x4424, 0x4464, 0x44C4, 0x4504, + 0x4544, 0x4584, 0x45C4, 0x4604, + 0x4644, 0x46A4, 0x46E4, 0x4724, + 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */ + 0x4864, 0x48A4, 0x48E4, 0x4924, + 0x4964, 0x49A4, 0x49E4, 0x4A24, + 0x4A64, 0x4AA4, 0x4AE4, 0x4B23, + 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */ + 0x4C63, 0x4CA3, 0x4CE3, 0x4D23, + 0x4D63, 0x4DA3, 0x4DE3, 0x4E23, + 0x4E63, 0x4EA3, 0x4EE3, 0x4F23, + 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */ + 0x5083, 0x50C3, 0x5103, 0x5143, + 0x5183, 0x51E2, 0x5222, 0x5262, + 0x52A2, 0x52E2, 0x5342, 0x5382, + 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */ + 0x5502, 0x5542, 0x55A2, 0x55E2, + 0x5642, 0x5682, 0x56E2, 0x5722, + 0x5782, 0x57E1, 0x5841, 0x58A1, + 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */ + 0x5AA1, 0x5B01, 0x5B81, 0x5BE1, + 0x5C61, 0x5D01, 0x5D80, 0x5E20, + 0x5EE0, 0x5FA0, 0x6080, 0x61C0, +}; + +const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE] = { + 0x0001, 0x0001, 0x0001, 0xFFFE, + 0xFFFE, 0x3FFF, 0x1000, 0x0393, +}; + +const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE] = { + 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, + 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, +}; + +const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE] = { + 0x013C, 0x01F5, 0x031A, 0x0631, + 0x0001, 0x0001, 0x0001, 0x0001, +}; + +const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE] = { + 0x5484, 0x3C40, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, +}; + +const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE] = { + 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */ + 0x2F2D, 0x2A2A, 0x2527, 0x1F21, + 0x1A1D, 0x1719, 0x1616, 0x1414, + 0x1414, 0x1400, 0x1414, 0x1614, + 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */ + 0x2A27, 0x2F2A, 0x332D, 0x3B35, + 0x5140, 0x6C62, 0x0077, +}; + +const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE] = { + 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */ + 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1, + 0x969B, 0x9195, 0x8F8F, 0x8A8A, + 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A, + 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */ + 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7, + 0xCBC0, 0xD8D4, 0x00DD, +}; + +const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE] = { + 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */ + 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, + 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, + 0xA4A4, 0xA400, 0xA4A4, 0xA4A4, + 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */ + 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, + 0xA4A4, 0xA4A4, 0x00A4, +}; + +const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE] = { + 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */ + 0x0067, 0x0063, 0x005E, 0x0059, + 0x0054, 0x0050, 0x004B, 0x0046, + 0x0042, 0x003D, 0x003D, 0x003D, + 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */ + 0x003D, 0x003D, 0x003D, 0x003D, + 0x003D, 0x003D, 0x0000, 0x003D, + 0x003D, 0x003D, 0x003D, 0x003D, + 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */ + 0x003D, 0x003D, 0x003D, 0x003D, + 0x0042, 0x0046, 0x004B, 0x0050, + 0x0054, 0x0059, 0x005E, 0x0063, + 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */ + 0x007A, +}; + +const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = { + 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */ + 0x00D6, 0x00D4, 0x00D2, 0x00CF, + 0x00CD, 0x00CA, 0x00C7, 0x00C4, + 0x00C1, 0x00BE, 0x00BE, 0x00BE, + 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */ + 0x00BE, 0x00BE, 0x00BE, 0x00BE, + 0x00BE, 0x00BE, 0x0000, 0x00BE, + 0x00BE, 0x00BE, 0x00BE, 0x00BE, + 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */ + 0x00BE, 0x00BE, 0x00BE, 0x00BE, + 0x00C1, 0x00C4, 0x00C7, 0x00CA, + 0x00CD, 0x00CF, 0x00D2, 0x00D4, + 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */ + 0x00DE, +}; + +/**** Helper functions to access the device Internal Lookup Tables ****/ + +void bcm43xx_ilt_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) +{ + if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val); + } else { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val); + } +} + +u16 bcm43xx_ilt_read16(struct bcm43xx_private *bcm, u16 offset) +{ + if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); + return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); + } else { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); + return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1); + } +} + +void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val) +{ + if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (u16)(val >> 16)); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, (u16)(val & 0x0000FFFF)); + } else { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (u16)(val >> 16)); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, (u16)(val & 0x0000FFFF)); + } +} + +u32 bcm43xx_ilt_read32(struct bcm43xx_private *bcm, u16 offset) +{ + u32 ret; + + if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); + ret = bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA2); + ret <<= 16; + ret |= bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); + } else { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); + ret = bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA2); + ret <<= 16; + ret |= bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1); + } + + return ret; +} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h new file mode 100644 index 000000000000..d92527fd83e9 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h @@ -0,0 +1,34 @@ +#ifndef BCM43xx_ILT_H_ +#define BCM43xx_ILT_H_ + +#define BCM43xx_ILT_ROTOR_SIZE 53 +extern const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE]; +#define BCM43xx_ILT_RETARD_SIZE 53 +extern const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE]; +#define BCM43xx_ILT_FINEFREQA_SIZE 256 +extern const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE]; +#define BCM43xx_ILT_FINEFREQG_SIZE 256 +extern const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE]; +#define BCM43xx_ILT_NOISEA2_SIZE 8 +extern const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE]; +#define BCM43xx_ILT_NOISEA3_SIZE 8 +extern const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE]; +#define BCM43xx_ILT_NOISEG1_SIZE 8 +extern const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE]; +#define BCM43xx_ILT_NOISEG2_SIZE 8 +extern const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE]; +#define BCM43xx_ILT_NOISESCALEG_SIZE 27 +extern const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE]; +extern const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE]; +extern const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE]; +#define BCM43xx_ILT_SIGMASQR_SIZE 53 +extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE]; +extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE]; + + +void bcm43xx_ilt_write16(struct bcm43xx_private *bcm, u16 offset, u16 val); +u16 bcm43xx_ilt_read16(struct bcm43xx_private *bcm, u16 offset); +void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val); +u32 bcm43xx_ilt_read32(struct bcm43xx_private *bcm, u16 offset); + +#endif /* BCM43xx_ILT_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c new file mode 100644 index 000000000000..455a0c743f73 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -0,0 +1,261 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx_leds.h" +#include "bcm43xx.h" + +#include + + +static void bcm43xx_led_changestate(struct bcm43xx_led *led) +{ + struct bcm43xx_private *bcm = led->bcm; + const int index = bcm43xx_led_index(led); + u16 ledctl; + + assert(index >= 0 && index < BCM43xx_NR_LEDS); + assert(led->blink_interval); + ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); + __change_bit(index, (unsigned long *)(&ledctl)); + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); +} + +static void bcm43xx_led_blink(unsigned long d) +{ + struct bcm43xx_led *led = (struct bcm43xx_led *)d; + struct bcm43xx_private *bcm = led->bcm; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + if (led->blink_interval) { + bcm43xx_led_changestate(led); + mod_timer(&led->blink_timer, jiffies + led->blink_interval); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +static void bcm43xx_led_blink_start(struct bcm43xx_led *led, + unsigned long interval) +{ + led->blink_interval = interval; + bcm43xx_led_changestate(led); + led->blink_timer.expires = jiffies + interval; + add_timer(&led->blink_timer); +} + +static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync) +{ + struct bcm43xx_private *bcm = led->bcm; + const int index = bcm43xx_led_index(led); + u16 ledctl; + + if (!led->blink_interval) + return; + if (unlikely(sync)) + del_timer_sync(&led->blink_timer); + else + del_timer(&led->blink_timer); + led->blink_interval = 0; + + /* Make sure the LED is turned off. */ + assert(index >= 0 && index < BCM43xx_NR_LEDS); + ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); + if (led->activelow) + ledctl |= (1 << index); + else + ledctl &= ~(1 << index); + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); +} + +int bcm43xx_leds_init(struct bcm43xx_private *bcm) +{ + struct bcm43xx_led *led; + u8 sprom[4]; + int i; + + sprom[0] = bcm->sprom.wl0gpio0; + sprom[1] = bcm->sprom.wl0gpio1; + sprom[2] = bcm->sprom.wl0gpio2; + sprom[3] = bcm->sprom.wl0gpio3; + + for (i = 0; i < BCM43xx_NR_LEDS; i++) { + led = &(bcm->leds[i]); + led->bcm = bcm; + init_timer(&led->blink_timer); + led->blink_timer.data = (unsigned long)led; + led->blink_timer.function = bcm43xx_led_blink; + + if (sprom[i] == 0xFF) { + /* SPROM information not set. */ + switch (i) { + case 0: + if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ) + led->behaviour = BCM43xx_LED_RADIO_ALL; + else + led->behaviour = BCM43xx_LED_ACTIVITY; + break; + case 1: + led->behaviour = BCM43xx_LED_RADIO_B; + break; + case 2: + led->behaviour = BCM43xx_LED_RADIO_A; + break; + case 3: + led->behaviour = BCM43xx_LED_OFF; + break; + default: + assert(0); + } + } else { + led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR; + led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW); + } + } + + return 0; +} + +void bcm43xx_leds_exit(struct bcm43xx_private *bcm) +{ + struct bcm43xx_led *led; + int i; + + for (i = 0; i < BCM43xx_NR_LEDS; i++) { + led = &(bcm->leds[i]); + bcm43xx_led_blink_stop(led, 1); + } + bcm43xx_leds_turn_off(bcm); +} + +void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) +{ + struct bcm43xx_led *led; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES; + int i, turn_on = 0; + unsigned long interval = 0; + u16 ledctl; + + ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); + for (i = 0; i < BCM43xx_NR_LEDS; i++) { + led = &(bcm->leds[i]); + if (led->behaviour == BCM43xx_LED_INACTIVE) + continue; + + switch (led->behaviour) { + case BCM43xx_LED_OFF: + turn_on = 0; + break; + case BCM43xx_LED_ON: + turn_on = 1; + break; + case BCM43xx_LED_ACTIVITY: + turn_on = activity; + break; + case BCM43xx_LED_RADIO_ALL: + turn_on = radio->enabled; + break; + case BCM43xx_LED_RADIO_A: + turn_on = (radio->enabled && phy->type == BCM43xx_PHYTYPE_A); + break; + case BCM43xx_LED_RADIO_B: + turn_on = (radio->enabled && + (phy->type == BCM43xx_PHYTYPE_B || + phy->type == BCM43xx_PHYTYPE_G)); + break; + case BCM43xx_LED_MODE_BG: + turn_on = 0; + if (phy->type == BCM43xx_PHYTYPE_G && + 1/*FIXME: using G rates.*/) + turn_on = 1; + break; + case BCM43xx_LED_TRANSFER: + if (transferring) + bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM); + else + bcm43xx_led_blink_stop(led, 0); + continue; + case BCM43xx_LED_APTRANSFER: + if (bcm->ieee->iw_mode == IW_MODE_MASTER) { + if (transferring) { + interval = BCM43xx_LEDBLINK_FAST; + turn_on = 1; + } + } else { + turn_on = 1; + if (0/*TODO: not assoc*/) + interval = BCM43xx_LEDBLINK_SLOW; + else if (transferring) + interval = BCM43xx_LEDBLINK_FAST; + else + turn_on = 0; + } + if (turn_on) + bcm43xx_led_blink_start(led, interval); + else + bcm43xx_led_blink_stop(led, 0); + continue; + case BCM43xx_LED_WEIRD: + //TODO + turn_on = 0; + break; + case BCM43xx_LED_ASSOC: + if (1/*TODO: associated*/) + turn_on = 1; + break; + default: + assert(0); + }; + + if (led->activelow) + turn_on = !turn_on; + if (turn_on) + ledctl |= (1 << i); + else + ledctl &= ~(1 << i); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); +} + +void bcm43xx_leds_turn_off(struct bcm43xx_private *bcm) +{ + struct bcm43xx_led *led; + u16 ledctl = 0; + int i; + + for (i = 0; i < BCM43xx_NR_LEDS; i++) { + led = &(bcm->leds[i]); + if (led->behaviour == BCM43xx_LED_INACTIVE) + continue; + if (led->activelow) + ledctl |= (1 << i); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h new file mode 100644 index 000000000000..489a2b1e9068 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h @@ -0,0 +1,47 @@ +#ifndef BCM43xx_LEDS_H_ +#define BCM43xx_LEDS_H_ + +#include +#include + + +struct bcm43xx_led { + u8 behaviour:7; + u8 activelow:1; + + struct bcm43xx_private *bcm; + struct timer_list blink_timer; + unsigned long blink_interval; +}; +#define bcm43xx_led_index(led) ((int)((led) - (led)->bcm->leds)) + +/* Delay between state changes when blinking in jiffies */ +#define BCM43xx_LEDBLINK_SLOW (HZ / 2) +#define BCM43xx_LEDBLINK_MEDIUM (HZ / 4) +#define BCM43xx_LEDBLINK_FAST (HZ / 8) + +#define BCM43xx_LED_XFER_THRES (HZ / 100) + +#define BCM43xx_LED_BEHAVIOUR 0x7F +#define BCM43xx_LED_ACTIVELOW 0x80 +enum { /* LED behaviour values */ + BCM43xx_LED_OFF, + BCM43xx_LED_ON, + BCM43xx_LED_ACTIVITY, + BCM43xx_LED_RADIO_ALL, + BCM43xx_LED_RADIO_A, + BCM43xx_LED_RADIO_B, + BCM43xx_LED_MODE_BG, + BCM43xx_LED_TRANSFER, + BCM43xx_LED_APTRANSFER, + BCM43xx_LED_WEIRD,//FIXME + BCM43xx_LED_ASSOC, + BCM43xx_LED_INACTIVE, +}; + +int bcm43xx_leds_init(struct bcm43xx_private *bcm); +void bcm43xx_leds_exit(struct bcm43xx_private *bcm); +void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity); +void bcm43xx_leds_turn_off(struct bcm43xx_private *bcm); + +#endif /* BCM43xx_LEDS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c new file mode 100644 index 000000000000..be60a6509f20 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -0,0 +1,4597 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bcm43xx.h" +#include "bcm43xx_main.h" +#include "bcm43xx_debugfs.h" +#include "bcm43xx_radio.h" +#include "bcm43xx_phy.h" +#include "bcm43xx_dma.h" +#include "bcm43xx_pio.h" +#include "bcm43xx_power.h" +#include "bcm43xx_wx.h" + + +MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); +MODULE_AUTHOR("Martin Langer"); +MODULE_AUTHOR("Stefano Brivio"); +MODULE_AUTHOR("Michael Buesch"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_BCM947XX +extern char *nvram_get(char *name); +#endif + +/* Module parameters */ +static int modparam_pio; +module_param_named(pio, modparam_pio, int, 0444); +MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); + +static int modparam_bad_frames_preempt; +module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); +MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption"); + +static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT; +module_param_named(short_retry, modparam_short_retry, int, 0444); +MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)"); + +static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT; +module_param_named(long_retry, modparam_long_retry, int, 0444); +MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)"); + +static int modparam_locale = -1; +module_param_named(locale, modparam_locale, int, 0444); +MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)"); + +static int modparam_outdoor; +module_param_named(outdoor, modparam_outdoor, int, 0444); +MODULE_PARM_DESC(outdoor, "Set to 1, if you are using the device outdoor, 0 otherwise."); + +static int modparam_noleds; +module_param_named(noleds, modparam_noleds, int, 0444); +MODULE_PARM_DESC(noleds, "Turn off all LED activity"); + +#ifdef CONFIG_BCM43XX_DEBUG +static char modparam_fwpostfix[64]; +module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444); +MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging."); +#else +# define modparam_fwpostfix "" +#endif /* CONFIG_BCM43XX_DEBUG*/ + + +/* If you want to debug with just a single device, enable this, + * where the string is the pci device ID (as given by the kernel's + * pci_name function) of the device to be used. + */ +//#define DEBUG_SINGLE_DEVICE_ONLY "0001:11:00.0" + +/* If you want to enable printing of each MMIO access, enable this. */ +//#define DEBUG_ENABLE_MMIO_PRINT + +/* If you want to enable printing of MMIO access within + * ucode/pcm upload, initvals write, enable this. + */ +//#define DEBUG_ENABLE_UCODE_MMIO_PRINT + +/* If you want to enable printing of PCI Config Space access, enable this */ +//#define DEBUG_ENABLE_PCILOG + + +static struct pci_device_id bcm43xx_pci_tbl[] = { + + /* Detailed list maintained at: + * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices + */ + +#ifdef CONFIG_BCM947XX + /* SB bus on BCM947xx */ + { PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif + + /* Broadcom 4303 802.11b */ + { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 4307 802.11b */ + { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 4318 802.11b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 4306 802.11b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 4306 802.11a */ +// { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 4309 802.11a/b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 43XG 802.11b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* required last entry */ + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl); + +static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val) +{ + u32 status; + + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP)) + val = swab32(val); + + bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset); + bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val); +} + +static inline +void bcm43xx_shm_control_word(struct bcm43xx_private *bcm, + u16 routing, u16 offset) +{ + u32 control; + + /* "offset" is the WORD offset. */ + + control = routing; + control <<= 16; + control |= offset; + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control); +} + +u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm, + u16 routing, u16 offset) +{ + u32 ret; + + if (routing == BCM43xx_SHM_SHARED) { + if (offset & 0x0003) { + /* Unaligned access */ + bcm43xx_shm_control_word(bcm, routing, offset >> 2); + ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED); + ret <<= 16; + bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1); + ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA); + + return ret; + } + offset >>= 2; + } + bcm43xx_shm_control_word(bcm, routing, offset); + ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA); + + return ret; +} + +u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm, + u16 routing, u16 offset) +{ + u16 ret; + + if (routing == BCM43xx_SHM_SHARED) { + if (offset & 0x0003) { + /* Unaligned access */ + bcm43xx_shm_control_word(bcm, routing, offset >> 2); + ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED); + + return ret; + } + offset >>= 2; + } + bcm43xx_shm_control_word(bcm, routing, offset); + ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA); + + return ret; +} + +void bcm43xx_shm_write32(struct bcm43xx_private *bcm, + u16 routing, u16 offset, + u32 value) +{ + if (routing == BCM43xx_SHM_SHARED) { + if (offset & 0x0003) { + /* Unaligned access */ + bcm43xx_shm_control_word(bcm, routing, offset >> 2); + bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, + (value >> 16) & 0xffff); + bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1); + bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, + value & 0xffff); + return; + } + offset >>= 2; + } + bcm43xx_shm_control_word(bcm, routing, offset); + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value); +} + +void bcm43xx_shm_write16(struct bcm43xx_private *bcm, + u16 routing, u16 offset, + u16 value) +{ + if (routing == BCM43xx_SHM_SHARED) { + if (offset & 0x0003) { + /* Unaligned access */ + bcm43xx_shm_control_word(bcm, routing, offset >> 2); + bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, + value); + return; + } + offset >>= 2; + } + bcm43xx_shm_control_word(bcm, routing, offset); + bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value); +} + +void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf) +{ + /* We need to be careful. As we read the TSF from multiple + * registers, we should take care of register overflows. + * In theory, the whole tsf read process should be atomic. + * We try to be atomic here, by restaring the read process, + * if any of the high registers changed (overflew). + */ + if (bcm->current_core->rev >= 3) { + u32 low, high, high2; + + do { + high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH); + low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW); + high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH); + } while (unlikely(high != high2)); + + *tsf = high; + *tsf <<= 32; + *tsf |= low; + } else { + u64 tmp; + u16 v0, v1, v2, v3; + u16 test1, test2, test3; + + do { + v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3); + v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2); + v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1); + v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0); + + test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3); + test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2); + test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1); + } while (v3 != test3 || v2 != test2 || v1 != test1); + + *tsf = v3; + *tsf <<= 48; + tmp = v2; + tmp <<= 32; + *tsf |= tmp; + tmp = v1; + tmp <<= 16; + *tsf |= tmp; + *tsf |= v0; + } +} + +void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) +{ + u32 status; + + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + status |= BCM43xx_SBF_TIME_UPDATE; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + + /* Be careful with the in-progress timer. + * First zero out the low register, so we have a full + * register-overflow duration to complete the operation. + */ + if (bcm->current_core->rev >= 3) { + u32 lo = (tsf & 0x00000000FFFFFFFFULL); + u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32; + + barrier(); + bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0); + bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi); + bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo); + } else { + u16 v0 = (tsf & 0x000000000000FFFFULL); + u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16; + u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32; + u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48; + + barrier(); + bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0); + bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3); + bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2); + bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1); + bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0); + } + + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + status &= ~BCM43xx_SBF_TIME_UPDATE; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); +} + +static inline +u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp, + const int ofdm_modulation) +{ + u8 rate; + + if (ofdm_modulation) { + switch (plcp->raw[0] & 0xF) { + case 0xB: + rate = IEEE80211_OFDM_RATE_6MB; + break; + case 0xF: + rate = IEEE80211_OFDM_RATE_9MB; + break; + case 0xA: + rate = IEEE80211_OFDM_RATE_12MB; + break; + case 0xE: + rate = IEEE80211_OFDM_RATE_18MB; + break; + case 0x9: + rate = IEEE80211_OFDM_RATE_24MB; + break; + case 0xD: + rate = IEEE80211_OFDM_RATE_36MB; + break; + case 0x8: + rate = IEEE80211_OFDM_RATE_48MB; + break; + case 0xC: + rate = IEEE80211_OFDM_RATE_54MB; + break; + default: + rate = 0; + assert(0); + } + } else { + switch (plcp->raw[0]) { + case 0x0A: + rate = IEEE80211_CCK_RATE_1MB; + break; + case 0x14: + rate = IEEE80211_CCK_RATE_2MB; + break; + case 0x37: + rate = IEEE80211_CCK_RATE_5MB; + break; + case 0x6E: + rate = IEEE80211_CCK_RATE_11MB; + break; + default: + rate = 0; + assert(0); + } + } + + return rate; +} + +static inline +u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) +{ + switch (bitrate) { + case IEEE80211_CCK_RATE_1MB: + return 0x0A; + case IEEE80211_CCK_RATE_2MB: + return 0x14; + case IEEE80211_CCK_RATE_5MB: + return 0x37; + case IEEE80211_CCK_RATE_11MB: + return 0x6E; + } + assert(0); + return 0; +} + +static inline +u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) +{ + switch (bitrate) { + case IEEE80211_OFDM_RATE_6MB: + return 0xB; + case IEEE80211_OFDM_RATE_9MB: + return 0xF; + case IEEE80211_OFDM_RATE_12MB: + return 0xA; + case IEEE80211_OFDM_RATE_18MB: + return 0xE; + case IEEE80211_OFDM_RATE_24MB: + return 0x9; + case IEEE80211_OFDM_RATE_36MB: + return 0xD; + case IEEE80211_OFDM_RATE_48MB: + return 0x8; + case IEEE80211_OFDM_RATE_54MB: + return 0xC; + } + assert(0); + return 0; +} + +static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, + u16 octets, const u8 bitrate, + const int ofdm_modulation) +{ + __le32 *data = &(plcp->data); + __u8 *raw = plcp->raw; + + /* Account for hardware-appended FCS. */ + octets += IEEE80211_FCS_LEN; + + if (ofdm_modulation) { + *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate); + assert(!(octets & 0xF000)); + *data |= (octets << 5); + *data = cpu_to_le32(*data); + } else { + u32 plen; + + plen = octets * 16 / bitrate; + if ((octets * 16 % bitrate) > 0) { + plen++; + if ((bitrate == IEEE80211_CCK_RATE_11MB) + && ((octets * 8 % 11) < 4)) { + raw[1] = 0x84; + } else + raw[1] = 0x04; + } else + raw[1] = 0x04; + *data |= cpu_to_le32(plen << 16); + raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate); + } + +//bcm43xx_printk_bitdump(raw, 4, 0, "PLCP"); +} + +void fastcall +bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie) +{ + const struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + const struct ieee80211_hdr_1addr *wireless_header = (const struct ieee80211_hdr_1addr *)fragment_data; + const struct ieee80211_security *secinfo = &bcm->ieee->sec; + u8 bitrate; + int ofdm_modulation; + u8 fallback_bitrate; + int fallback_ofdm_modulation; + u16 tmp; + u16 encrypt_frame; + + /* Now construct the TX header. */ + memset(txhdr, 0, sizeof(*txhdr)); + + //TODO: Some RTS/CTS stuff has to be done. + //TODO: Encryption stuff. + //TODO: others? + + bitrate = bcm->softmac->txrates.default_rate; + ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); + fallback_bitrate = bcm->softmac->txrates.default_fallback; + fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); + + /* Set Frame Control from 80211 header. */ + txhdr->frame_control = wireless_header->frame_ctl; + /* Copy address1 from 80211 header. */ + memcpy(txhdr->mac1, wireless_header->addr1, 6); + /* Set the fallback duration ID. */ + //FIXME: We use the original durid for now. + txhdr->fallback_dur_id = wireless_header->duration_id; + + /* Set the cookie (used as driver internal ID for the frame) */ + txhdr->cookie = cpu_to_le16(cookie); + + encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED; + if (encrypt_frame && !bcm->ieee->host_encrypt) { + const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header; + if (fragment_len <= sizeof(struct ieee80211_hdr_3addr)+4) { + dprintkl(KERN_ERR PFX "invalid packet with PROTECTED" + "flag set discarded"); + return; + } + memcpy(txhdr->wep_iv, hdr->payload, 4); + /* Hardware appends ICV. */ + fragment_len += 4; + } + + /* Generate the PLCP header and the fallback PLCP header. */ + bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp), + fragment_len, + bitrate, ofdm_modulation); + bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, fragment_len, + fallback_bitrate, fallback_ofdm_modulation); + + /* Set the CONTROL field */ + tmp = 0; + if (ofdm_modulation) + tmp |= BCM43xx_TXHDRCTL_OFDM; + if (bcm->short_preamble) //FIXME: could be the other way around, please test + tmp |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE; + tmp |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT) + & BCM43xx_TXHDRCTL_ANTENNADIV_MASK; + txhdr->control = cpu_to_le16(tmp); + + /* Set the FLAGS field */ + tmp = 0; + if (!is_multicast_ether_addr(wireless_header->addr1) && + !is_broadcast_ether_addr(wireless_header->addr1)) + tmp |= BCM43xx_TXHDRFLAG_EXPECTACK; + if (1 /* FIXME: PS poll?? */) + tmp |= 0x10; // FIXME: unknown meaning. + if (fallback_ofdm_modulation) + tmp |= BCM43xx_TXHDRFLAG_FALLBACKOFDM; + if (is_first_fragment) + tmp |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT; + txhdr->flags = cpu_to_le16(tmp); + + /* Set WSEC/RATE field */ + if (encrypt_frame && !bcm->ieee->host_encrypt) { + tmp = (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT) + & BCM43xx_TXHDR_WSEC_ALGO_MASK; + tmp |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT) + & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK; + txhdr->wsec_rate = cpu_to_le16(tmp); + } + +//bcm43xx_printk_bitdump((const unsigned char *)txhdr, sizeof(*txhdr), 1, "TX header"); +} + +static +void bcm43xx_macfilter_set(struct bcm43xx_private *bcm, + u16 offset, + const u8 *mac) +{ + u16 data; + + offset |= 0x0020; + bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset); + + data = mac[0]; + data |= mac[1] << 8; + bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); + data = mac[2]; + data |= mac[3] << 8; + bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); + data = mac[4]; + data |= mac[5] << 8; + bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); +} + +static inline +void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm, + u16 offset) +{ + const u8 zero_addr[ETH_ALEN] = { 0 }; + + bcm43xx_macfilter_set(bcm, offset, zero_addr); +} + +static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm) +{ + const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr); + const u8 *bssid = (const u8 *)(bcm->ieee->bssid); + u8 mac_bssid[ETH_ALEN * 2]; + int i; + + memcpy(mac_bssid, mac, ETH_ALEN); + memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN); + + /* Write our MAC address and BSSID to template ram */ + for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) + bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i))); + for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) + bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i))); + for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) + bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i))); +} + +static inline +void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) +{ + /* slot_time is in usec. */ + if (bcm->current_core->phy->type != BCM43xx_PHYTYPE_G) + return; + bcm43xx_write16(bcm, 0x684, 510 + slot_time); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time); +} + +static inline +void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm) +{ + bcm43xx_set_slot_time(bcm, 9); +} + +static inline +void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm) +{ + bcm43xx_set_slot_time(bcm, 20); +} + +//FIXME: rename this func? +static void bcm43xx_disassociate(struct bcm43xx_private *bcm) +{ + bcm43xx_mac_suspend(bcm); + bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); + + bcm43xx_ram_write(bcm, 0x0026, 0x0000); + bcm43xx_ram_write(bcm, 0x0028, 0x0000); + bcm43xx_ram_write(bcm, 0x007E, 0x0000); + bcm43xx_ram_write(bcm, 0x0080, 0x0000); + bcm43xx_ram_write(bcm, 0x047E, 0x0000); + bcm43xx_ram_write(bcm, 0x0480, 0x0000); + + if (bcm->current_core->rev < 3) { + bcm43xx_write16(bcm, 0x0610, 0x8000); + bcm43xx_write16(bcm, 0x060E, 0x0000); + } else + bcm43xx_write32(bcm, 0x0188, 0x80000000); + + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff); + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && + ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate)) + bcm43xx_short_slot_timing_enable(bcm); + + bcm43xx_mac_enable(bcm); +} + +//FIXME: rename this func? +static void bcm43xx_associate(struct bcm43xx_private *bcm, + const u8 *mac) +{ + memcpy(bcm->ieee->bssid, mac, ETH_ALEN); + + bcm43xx_mac_suspend(bcm); + bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac); + bcm43xx_write_mac_bssid_templates(bcm); + bcm43xx_mac_enable(bcm); +} + +/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. + * Returns the _previously_ enabled IRQ mask. + */ +static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask) +{ + u32 old_mask; + + old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask); + + return old_mask; +} + +/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable. + * Returns the _previously_ enabled IRQ mask. + */ +static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask) +{ + u32 old_mask; + + old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask); + + return old_mask; +} + +/* 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; + + spin_lock_irqsave(&bcm->lock, flags); + if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) { + spin_unlock_irqrestore(&bcm->lock, flags); + return -EBUSY; + } + old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + tasklet_disable(&bcm->isr_tasklet); + spin_unlock_irqrestore(&bcm->lock, flags); + if (oldstate) + *oldstate = old; + + return 0; +} + +static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) +{ + u32 radio_id; + u16 manufact; + u16 version; + u8 revision; + s8 i; + + if (bcm->chip_id == 0x4317) { + if (bcm->chip_rev == 0x00) + radio_id = 0x3205017F; + else if (bcm->chip_rev == 0x01) + radio_id = 0x4205017F; + else + radio_id = 0x5205017F; + } else { + bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID); + radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH); + radio_id <<= 16; + bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID); + radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW); + } + + manufact = (radio_id & 0x00000FFF); + version = (radio_id & 0x0FFFF000) >> 12; + revision = (radio_id & 0xF0000000) >> 28; + + dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n", + radio_id, manufact, version, revision); + + switch (bcm->current_core->phy->type) { + case BCM43xx_PHYTYPE_A: + if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f)) + goto err_unsupported_radio; + break; + case BCM43xx_PHYTYPE_B: + if ((version & 0xFFF0) != 0x2050) + goto err_unsupported_radio; + break; + case BCM43xx_PHYTYPE_G: + if (version != 0x2050) + goto err_unsupported_radio; + break; + } + + bcm->current_core->radio->manufact = manufact; + bcm->current_core->radio->version = version; + bcm->current_core->radio->revision = revision; + + /* Set default attenuation values. */ + bcm->current_core->radio->txpower[0] = 2; + bcm->current_core->radio->txpower[1] = 2; + if (revision == 1) + bcm->current_core->radio->txpower[2] = 3; + else + bcm->current_core->radio->txpower[2] = 0; + + /* Initialize the in-memory nrssi Lookup Table. */ + for (i = 0; i < 64; i++) + bcm->current_core->radio->nrssi_lt[i] = i; + + return 0; + +err_unsupported_radio: + printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n"); + return -ENODEV; +} + +static const char * bcm43xx_locale_iso(u8 locale) +{ + /* ISO 3166-1 country codes. + * Note that there aren't ISO 3166-1 codes for + * all or locales. (Not all locales are countries) + */ + switch (locale) { + case BCM43xx_LOCALE_WORLD: + case BCM43xx_LOCALE_ALL: + return "XX"; + case BCM43xx_LOCALE_THAILAND: + return "TH"; + case BCM43xx_LOCALE_ISRAEL: + return "IL"; + case BCM43xx_LOCALE_JORDAN: + return "JO"; + case BCM43xx_LOCALE_CHINA: + return "CN"; + case BCM43xx_LOCALE_JAPAN: + case BCM43xx_LOCALE_JAPAN_HIGH: + return "JP"; + case BCM43xx_LOCALE_USA_CANADA_ANZ: + case BCM43xx_LOCALE_USA_LOW: + return "US"; + case BCM43xx_LOCALE_EUROPE: + return "EU"; + case BCM43xx_LOCALE_NONE: + return " "; + } + assert(0); + return " "; +} + +static const char * bcm43xx_locale_string(u8 locale) +{ + switch (locale) { + case BCM43xx_LOCALE_WORLD: + return "World"; + case BCM43xx_LOCALE_THAILAND: + return "Thailand"; + case BCM43xx_LOCALE_ISRAEL: + return "Israel"; + case BCM43xx_LOCALE_JORDAN: + return "Jordan"; + case BCM43xx_LOCALE_CHINA: + return "China"; + case BCM43xx_LOCALE_JAPAN: + return "Japan"; + case BCM43xx_LOCALE_USA_CANADA_ANZ: + return "USA/Canada/ANZ"; + case BCM43xx_LOCALE_EUROPE: + return "Europe"; + case BCM43xx_LOCALE_USA_LOW: + return "USAlow"; + case BCM43xx_LOCALE_JAPAN_HIGH: + return "JapanHigh"; + case BCM43xx_LOCALE_ALL: + return "All"; + case BCM43xx_LOCALE_NONE: + return "None"; + } + assert(0); + return ""; +} + +static inline u8 bcm43xx_crc8(u8 crc, u8 data) +{ + static const u8 t[] = { + 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, + 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, + 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, + 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, + 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, + 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, + 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, + 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, + 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, + 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, + 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, + 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, + 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, + 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, + 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, + 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, + 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, + 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, + 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, + 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, + 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, + 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, + 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, + 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, + 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, + 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, + 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, + 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, + 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, + 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, + 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, + 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, + }; + return t[crc ^ data]; +} + +u8 bcm43xx_sprom_crc(const u16 *sprom) +{ + int word; + u8 crc = 0xFF; + + for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) { + crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF); + crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8); + } + crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF); + crc ^= 0xFF; + + return crc; +} + + +static int bcm43xx_read_sprom(struct bcm43xx_private *bcm) +{ + int i; + u16 value; + u16 *sprom; + u8 crc, expected_crc; +#ifdef CONFIG_BCM947XX + char *c; +#endif + + sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16), + GFP_KERNEL); + if (!sprom) { + printk(KERN_ERR PFX "read_sprom OOM\n"); + return -ENOMEM; + } +#ifdef CONFIG_BCM947XX + sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2")); + sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags")); + + if ((c = nvram_get("il0macaddr")) != NULL) + e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR])); + + if ((c = nvram_get("et1macaddr")) != NULL) + e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR])); + + sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0")); + sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1")); + sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2")); + + sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0")); + sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1")); + sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2")); + + sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev")); +#else + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) + sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); + + /* CRC-8 check. */ + crc = bcm43xx_sprom_crc(sprom); + expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; + if (crc != expected_crc) { + printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum " + "(0x%02X, expected: 0x%02X)\n", + crc, expected_crc); + } +#endif + + /* boardflags2 */ + value = sprom[BCM43xx_SPROM_BOARDFLAGS2]; + bcm->sprom.boardflags2 = value; + + /* il0macaddr */ + value = sprom[BCM43xx_SPROM_IL0MACADDR + 0]; + *(((u16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_IL0MACADDR + 1]; + *(((u16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_IL0MACADDR + 2]; + *(((u16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value); + + /* et0macaddr */ + value = sprom[BCM43xx_SPROM_ET0MACADDR + 0]; + *(((u16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_ET0MACADDR + 1]; + *(((u16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_ET0MACADDR + 2]; + *(((u16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value); + + /* et1macaddr */ + value = sprom[BCM43xx_SPROM_ET1MACADDR + 0]; + *(((u16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_ET1MACADDR + 1]; + *(((u16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_ET1MACADDR + 2]; + *(((u16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value); + + /* ethernet phy settings */ + value = sprom[BCM43xx_SPROM_ETHPHY]; + bcm->sprom.et0phyaddr = (value & 0x001F); + bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5; + bcm->sprom.et0mdcport = (value & (1 << 14)) >> 14; + bcm->sprom.et1mdcport = (value & (1 << 15)) >> 15; + + /* boardrev, antennas, locale */ + value = sprom[BCM43xx_SPROM_BOARDREV]; + bcm->sprom.boardrev = (value & 0x00FF); + bcm->sprom.locale = (value & 0x0F00) >> 8; + bcm->sprom.antennas_aphy = (value & 0x3000) >> 12; + bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14; + if (modparam_locale != -1) { + if (modparam_locale >= 0 && modparam_locale <= 11) { + bcm->sprom.locale = modparam_locale; + printk(KERN_WARNING PFX "Operating with modified " + "LocaleCode %u (%s)\n", + bcm->sprom.locale, + bcm43xx_locale_string(bcm->sprom.locale)); + } else { + printk(KERN_WARNING PFX "Module parameter \"locale\" " + "invalid value. (0 - 11)\n"); + } + } + + /* pa0b* */ + value = sprom[BCM43xx_SPROM_PA0B0]; + bcm->sprom.pa0b0 = value; + value = sprom[BCM43xx_SPROM_PA0B1]; + bcm->sprom.pa0b1 = value; + value = sprom[BCM43xx_SPROM_PA0B2]; + bcm->sprom.pa0b2 = value; + + /* wl0gpio* */ + value = sprom[BCM43xx_SPROM_WL0GPIO0]; + if (value == 0x0000) + value = 0xFFFF; + bcm->sprom.wl0gpio0 = value & 0x00FF; + bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8; + value = sprom[BCM43xx_SPROM_WL0GPIO2]; + if (value == 0x0000) + value = 0xFFFF; + bcm->sprom.wl0gpio2 = value & 0x00FF; + bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8; + + /* maxpower */ + value = sprom[BCM43xx_SPROM_MAXPWR]; + bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8; + bcm->sprom.maxpower_bgphy = value & 0x00FF; + + /* pa1b* */ + value = sprom[BCM43xx_SPROM_PA1B0]; + bcm->sprom.pa1b0 = value; + value = sprom[BCM43xx_SPROM_PA1B1]; + bcm->sprom.pa1b1 = value; + value = sprom[BCM43xx_SPROM_PA1B2]; + bcm->sprom.pa1b2 = value; + + /* idle tssi target */ + value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT]; + bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF; + bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8; + + /* boardflags */ + value = sprom[BCM43xx_SPROM_BOARDFLAGS]; + if (value == 0xFFFF) + value = 0x0000; + bcm->sprom.boardflags = value; + + /* antenna gain */ + value = sprom[BCM43xx_SPROM_ANTENNA_GAIN]; + if (value == 0x0000 || value == 0xFFFF) + value = 0x0202; + /* convert values to Q5.2 */ + bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4; + bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4; + + kfree(sprom); + + return 0; +} + +static int bcm43xx_channel_is_allowed(struct bcm43xx_private *bcm, u8 channel, + u8 *max_power, u8 *flags) +{ + /* THIS FUNCTION DOES _NOT_ ENFORCE REGULATORY DOMAIN COMPLIANCE. + * It is only a helper function to make life easier to + * select legal channels and transmission powers. + */ + + u8 phytype = bcm->current_core->phy->type; + int allowed = 0; + + *max_power = 0; + *flags = 0; + + //FIXME: Set max_power and maybe flags + /*FIXME: Allowed channels are sometimes different for outdoor + * or indoor use. See modparam_outdoor. + */ + /* From b specs Max Power BPHY: + * USA: 1000mW + * Europe: 100mW + * Japan: 10mW/MHz + */ + + switch (bcm->sprom.locale) { + case BCM43xx_LOCALE_WORLD: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 13) + allowed = 1; + } else { + if (channel >= 1 && channel <= 13) + allowed = 1; + } + break; + case BCM43xx_LOCALE_THAILAND: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 14) + allowed = 1; + } else { + if (channel >= 1 && channel <= 14) + allowed = 1; + } + break; + case BCM43xx_LOCALE_ISRAEL: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 5 && channel <= 7) + allowed = 1; + } else { + if (channel >= 5 && channel <= 7) + allowed = 1; + } + break; + case BCM43xx_LOCALE_JORDAN: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 10 && channel <= 13) + allowed = 1; + } else { + if (channel >= 10 && channel <= 13) + allowed = 1; + } + break; + case BCM43xx_LOCALE_CHINA: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 13) + allowed = 1; + } else { + if (channel >= 1 && channel <= 13) + allowed = 1; + } + break; + case BCM43xx_LOCALE_JAPAN: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + //FIXME: This seems to be wrong. + if (channel >= 1 && channel <= 14) + allowed = 1; + } else { + //FIXME: This seems to be wrong. + if (channel >= 1 && channel <= 14) + allowed = 1; + } + break; + case BCM43xx_LOCALE_USA_CANADA_ANZ: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 13) + allowed = 1; + } else { + if (channel >= 1 && channel <= 11) + allowed = 1; + } + break; + case BCM43xx_LOCALE_EUROPE: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 13) + allowed = 1; + } else { + if (channel >= 1 && channel <= 13) + allowed = 1; + } + break; + case BCM43xx_LOCALE_USA_LOW: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 13) + allowed = 1; + } else { + if (channel >= 1 && channel <= 11) + allowed = 1; + } + break; + case BCM43xx_LOCALE_JAPAN_HIGH: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + //FIXME? + if (channel >= 1 && channel <= 14) + allowed = 1; + } else { + if (channel >= 1 && channel <= 14) + allowed = 1; + } + break; + case BCM43xx_LOCALE_ALL: + allowed = 1; + break; + case BCM43xx_LOCALE_NONE: + break; + default: + assert(0); + } + + return allowed; +} + +static void bcm43xx_geo_init(struct bcm43xx_private *bcm) +{ + struct ieee80211_geo geo; + struct ieee80211_channel *chan; + int have_a = 0, have_bg = 0; + int i, num80211; + u8 channel, flags, max_power; + struct bcm43xx_phyinfo *phy; + const char *iso_country; + + memset(&geo, 0, sizeof(geo)); + num80211 = bcm43xx_num_80211_cores(bcm); + for (i = 0; i < num80211; i++) { + phy = bcm->phy + i; + switch (phy->type) { + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + have_bg = 1; + break; + case BCM43xx_PHYTYPE_A: + have_a = 1; + break; + default: + assert(0); + } + } + iso_country = bcm43xx_locale_iso(bcm->sprom.locale); + + if (have_a) { + for (i = 0, channel = 0; channel < 201; channel++) { + if (!bcm43xx_channel_is_allowed(bcm, channel, + &max_power, &flags)) + continue; + chan = &geo.a[i++]; + chan->freq = bcm43xx_channel_to_freq(bcm, channel); + chan->channel = channel; + chan->flags = flags; + chan->max_power = max_power; + } + geo.a_channels = i; + } + if (have_bg) { + for (i = 0, channel = 1; channel < 15; channel++) { + if (!bcm43xx_channel_is_allowed(bcm, channel, + &max_power, &flags)) + continue; + chan = &geo.bg[i++]; + chan->freq = bcm43xx_channel_to_freq(bcm, channel); + chan->channel = channel; + chan->flags = flags; + chan->max_power = max_power; + } + geo.bg_channels = i; + } + memcpy(geo.name, iso_country, 2); + if (0 /*TODO: Outdoor use only */) + geo.name[2] = 'O'; + else if (0 /*TODO: Indoor use only */) + geo.name[2] = 'I'; + else + geo.name[2] = ' '; + geo.name[3] = '\0'; + + ieee80211_set_geo(bcm->ieee, &geo); +} + +/* DummyTransmission function, as documented on + * http://bcm-specs.sipsolutions.net/DummyTransmission + */ +void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) +{ + unsigned int i, max_loop; + u16 value = 0; + u32 buffer[5] = { + 0x00000000, + 0x0000D400, + 0x00000000, + 0x00000001, + 0x00000000, + }; + + switch (bcm->current_core->phy->type) { + case BCM43xx_PHYTYPE_A: + max_loop = 0x1E; + buffer[0] = 0xCC010200; + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + max_loop = 0xFA; + buffer[0] = 0x6E840B00; + break; + default: + assert(0); + return; + } + + for (i = 0; i < 5; i++) + bcm43xx_ram_write(bcm, i * 4, buffer[i]); + + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ + + bcm43xx_write16(bcm, 0x0568, 0x0000); + bcm43xx_write16(bcm, 0x07C0, 0x0000); + bcm43xx_write16(bcm, 0x050C, ((bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0)); + bcm43xx_write16(bcm, 0x0508, 0x0000); + bcm43xx_write16(bcm, 0x050A, 0x0000); + bcm43xx_write16(bcm, 0x054C, 0x0000); + bcm43xx_write16(bcm, 0x056A, 0x0014); + bcm43xx_write16(bcm, 0x0568, 0x0826); + bcm43xx_write16(bcm, 0x0500, 0x0000); + bcm43xx_write16(bcm, 0x0502, 0x0030); + + for (i = 0x00; i < max_loop; i++) { + value = bcm43xx_read16(bcm, 0x050E); + if ((value & 0x0080) != 0) + break; + udelay(10); + } + for (i = 0x00; i < 0x0A; i++) { + value = bcm43xx_read16(bcm, 0x050E); + if ((value & 0x0400) != 0) + break; + udelay(10); + } + for (i = 0x00; i < 0x0A; i++) { + value = bcm43xx_read16(bcm, 0x0690); + if ((value & 0x0100) == 0) + break; + udelay(10); + } +} + +static void key_write(struct bcm43xx_private *bcm, + u8 index, u8 algorithm, const u16 *key) +{ + unsigned int i, basic_wep = 0; + u32 offset; + u16 value; + + /* Write associated key information */ + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2), + ((index << 4) | (algorithm & 0x0F))); + + /* The first 4 WEP keys need extra love */ + if (((algorithm == BCM43xx_SEC_ALGO_WEP) || + (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4)) + basic_wep = 1; + + /* Write key payload, 8 little endian words */ + offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE); + for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) { + value = cpu_to_le16(key[i]); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, + offset + (i * 2), value); + + if (!basic_wep) + continue; + + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, + offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE, + value); + } +} + +static void keymac_write(struct bcm43xx_private *bcm, + u8 index, const u32 *addr) +{ + /* for keys 0-3 there is no associated mac address */ + if (index < 4) + return; + + index -= 4; + if (bcm->current_core->rev >= 5) { + bcm43xx_shm_write32(bcm, + BCM43xx_SHM_HWMAC, + index * 2, + cpu_to_be32(*addr)); + bcm43xx_shm_write16(bcm, + BCM43xx_SHM_HWMAC, + (index * 2) + 1, + cpu_to_be16(*((u16 *)(addr + 1)))); + } else { + if (index < 8) { + TODO(); /* Put them in the macaddress filter */ + } else { + TODO(); + /* Put them BCM43xx_SHM_SHARED, stating index 0x0120. + Keep in mind to update the count of keymacs in 0x003E as well! */ + } + } +} + +static int bcm43xx_key_write(struct bcm43xx_private *bcm, + u8 index, u8 algorithm, + const u8 *_key, int key_len, + const u8 *mac_addr) +{ + u8 key[BCM43xx_SEC_KEYSIZE] = { 0 }; + + if (index >= ARRAY_SIZE(bcm->key)) + return -EINVAL; + if (key_len > ARRAY_SIZE(key)) + return -EINVAL; + if (algorithm < 1 || algorithm > 5) + return -EINVAL; + + memcpy(key, _key, key_len); + key_write(bcm, index, algorithm, (const u16 *)key); + keymac_write(bcm, index, (const u32 *)mac_addr); + + bcm->key[index].algorithm = algorithm; + + return 0; +} + +static void bcm43xx_clear_keys(struct bcm43xx_private *bcm) +{ + static const u32 zero_mac[2] = { 0 }; + unsigned int i,j, nr_keys = 54; + u16 offset; + + if (bcm->current_core->rev < 5) + nr_keys = 16; + assert(nr_keys <= ARRAY_SIZE(bcm->key)); + + for (i = 0; i < nr_keys; i++) { + bcm->key[i].enabled = 0; + /* returns for i < 4 immediately */ + keymac_write(bcm, i, zero_mac); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, + 0x100 + (i * 2), 0x0000); + for (j = 0; j < 8; j++) { + offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, + offset, 0x0000); + } + } + dprintk(KERN_INFO PFX "Keys cleared\n"); +} + +/* Puts the index of the current core into user supplied core variable. + * This function reads the value from the device. + * Almost always you don't want to call this, but use bcm->current_core + */ +static inline +int _get_current_core(struct bcm43xx_private *bcm, int *core) +{ + int err; + + err = bcm43xx_pci_read_config32(bcm, BCM43xx_REG_ACTIVE_CORE, core); + if (unlikely(err)) { + dprintk(KERN_ERR PFX "BCM43xx_REG_ACTIVE_CORE read failed!\n"); + return -ENODEV; + } + *core = (*core - 0x18000000) / 0x1000; + + return 0; +} + +/* Lowlevel core-switch function. This is only to be used in + * bcm43xx_switch_core() and bcm43xx_probe_cores() + */ +static int _switch_core(struct bcm43xx_private *bcm, int core) +{ + int err; + int attempts = 0; + int current_core = -1; + + assert(core >= 0); + + err = _get_current_core(bcm, ¤t_core); + if (unlikely(err)) + goto out; + + /* Write the computed value to the register. This doesn't always + succeed so we retry BCM43xx_SWITCH_CORE_MAX_RETRIES times */ + while (current_core != core) { + if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES)) { + err = -ENODEV; + printk(KERN_ERR PFX + "unable to switch to core %u, retried %i times\n", + core, attempts); + goto out; + } + err = bcm43xx_pci_write_config32(bcm, BCM43xx_REG_ACTIVE_CORE, + (core * 0x1000) + 0x18000000); + if (unlikely(err)) { + dprintk(KERN_ERR PFX "BCM43xx_REG_ACTIVE_CORE write failed!\n"); + continue; + } + _get_current_core(bcm, ¤t_core); +#ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) + bcm->current_core_offset = 0x1000 * core; + else + bcm->current_core_offset = 0; +#endif + } + + assert(err == 0); +out: + return err; +} + +int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core) +{ + int err; + + if (!new_core) + return 0; + + if (!(new_core->flags & BCM43xx_COREFLAG_AVAILABLE)) + return -ENODEV; + if (bcm->current_core == new_core) + return 0; + err = _switch_core(bcm, new_core->index); + if (!err) + bcm->current_core = new_core; + + return err; +} + +static inline int bcm43xx_core_enabled(struct bcm43xx_private *bcm) +{ + u32 value; + + value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET + | BCM43xx_SBTMSTATELOW_REJECT; + + return (value == BCM43xx_SBTMSTATELOW_CLOCK); +} + +/* disable current core */ +static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags) +{ + u32 sbtmstatelow; + u32 sbtmstatehigh; + int i; + + /* fetch sbtmstatelow from core information registers */ + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + + /* core is already in reset */ + if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET) + goto out; + + if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) { + sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | + BCM43xx_SBTMSTATELOW_REJECT; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + + for (i = 0; i < 1000; i++) { + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) { + i = -1; + break; + } + udelay(10); + } + if (i != -1) { + printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n"); + return -EBUSY; + } + + for (i = 0; i < 1000; i++) { + sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); + if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) { + i = -1; + break; + } + udelay(10); + } + if (i != -1) { + printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n"); + return -EBUSY; + } + + sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | + BCM43xx_SBTMSTATELOW_REJECT | + BCM43xx_SBTMSTATELOW_RESET | + BCM43xx_SBTMSTATELOW_CLOCK | + core_flags; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(10); + } + + sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET | + BCM43xx_SBTMSTATELOW_REJECT | + core_flags; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + +out: + bcm->current_core->flags &= ~ BCM43xx_COREFLAG_ENABLED; + return 0; +} + +/* enable (reset) current core */ +static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags) +{ + u32 sbtmstatelow; + u32 sbtmstatehigh; + u32 sbimstate; + int err; + + err = bcm43xx_core_disable(bcm, core_flags); + if (err) + goto out; + + sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | + BCM43xx_SBTMSTATELOW_RESET | + BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | + core_flags; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); + + sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); + if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) { + sbtmstatehigh = 0x00000000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh); + } + + sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE); + if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) { + sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT); + bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate); + } + + sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | + BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | + core_flags; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); + + sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); + + bcm->current_core->flags |= BCM43xx_COREFLAG_ENABLED; + assert(err == 0); +out: + return err; +} + +/* http://bcm-specs.sipsolutions.net/80211CoreReset */ +void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) +{ + u32 flags = 0x00040000; + + if ((bcm43xx_core_enabled(bcm)) && (!bcm->pio_mode)) { +//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here? +#ifndef CONFIG_BCM947XX + /* reset all used DMA controllers. */ + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); + bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE); + if (bcm->current_core->rev < 5) + bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); +#endif + } + if (bcm->shutting_down) { + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002)); + } else { + if (connect_phy) + flags |= 0x20000000; + bcm43xx_phy_connect(bcm, connect_phy); + bcm43xx_core_enable(bcm, flags); + bcm43xx_write16(bcm, 0x03E6, 0x0000); + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + | BCM43xx_SBF_400); + } +} + +static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm) +{ + bcm43xx_radio_turn_off(bcm); + bcm43xx_write16(bcm, 0x03E6, 0x00F4); + bcm43xx_core_disable(bcm, 0); +} + +/* Mark the current 80211 core inactive. + * "active_80211_core" is the other 80211 core, which is used. + */ +static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm, + struct bcm43xx_coreinfo *active_80211_core) +{ + u32 sbtmstatelow; + struct bcm43xx_coreinfo *old_core; + int err = 0; + + bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + bcm43xx_radio_turn_off(bcm); + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + sbtmstatelow &= ~0x200a0000; + sbtmstatelow |= 0xa0000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + sbtmstatelow &= ~0xa0000; + sbtmstatelow |= 0x80000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, active_80211_core); + if (err) + goto out; + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + sbtmstatelow &= ~0x20000000; + sbtmstatelow |= 0x20000000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + err = bcm43xx_switch_core(bcm, old_core); + } + +out: + return err; +} + +static inline void handle_irq_transmit_status(struct bcm43xx_private *bcm) +{ + u32 v0, v1; + u16 tmp; + struct bcm43xx_xmitstatus stat; + + assert(bcm->current_core->id == BCM43xx_COREID_80211); + assert(bcm->current_core->rev >= 5); + + while (1) { + v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0); + if (!v0) + break; + v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1); + + stat.cookie = (v0 >> 16) & 0x0000FFFF; + tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1)); + stat.flags = tmp & 0xFF; + stat.cnt1 = (tmp & 0x0F00) >> 8; + stat.cnt2 = (tmp & 0xF000) >> 12; + stat.seq = (u16)(v1 & 0xFFFF); + stat.unknown = (u16)((v1 >> 16) & 0xFF); + + bcm43xx_debugfs_log_txstat(bcm, &stat); + + if (stat.flags & BCM43xx_TXSTAT_FLAG_IGNORE) + continue; + if (!(stat.flags & BCM43xx_TXSTAT_FLAG_ACK)) { + //TODO: packet was not acked (was lost) + } + //TODO: There are more (unknown) flags to test. see bcm43xx_main.h + + if (bcm->pio_mode) + bcm43xx_pio_handle_xmitstatus(bcm, &stat); + else + bcm43xx_dma_handle_xmitstatus(bcm, &stat); + } +} + +static inline void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) +{ + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F); + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4)); + assert(bcm->noisecalc.core_at_start == bcm->current_core); + assert(bcm->noisecalc.channel_at_start == bcm->current_core->radio->channel); +} + +static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) +{ + /* Top half of Link Quality calculation. */ + + if (bcm->noisecalc.calculation_running) + return; + bcm->noisecalc.core_at_start = bcm->current_core; + bcm->noisecalc.channel_at_start = bcm->current_core->radio->channel; + bcm->noisecalc.calculation_running = 1; + bcm->noisecalc.nr_samples = 0; + + bcm43xx_generate_noise_sample(bcm); +} + +static inline void handle_irq_noise(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 tmp; + u8 noise[4]; + u8 i, j; + s32 average; + + /* Bottom half of Link Quality calculation. */ + + assert(bcm->noisecalc.calculation_running); + if (bcm->noisecalc.core_at_start != bcm->current_core || + bcm->noisecalc.channel_at_start != radio->channel) + goto drop_calculation; + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408); + noise[0] = (tmp & 0x00FF); + noise[1] = (tmp & 0xFF00) >> 8; + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A); + noise[2] = (tmp & 0x00FF); + noise[3] = (tmp & 0xFF00) >> 8; + if (noise[0] == 0x7F || noise[1] == 0x7F || + noise[2] == 0x7F || noise[3] == 0x7F) + goto generate_new; + + /* Get the noise samples. */ + assert(bcm->noisecalc.nr_samples <= 8); + i = bcm->noisecalc.nr_samples; + noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); + noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); + noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); + noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); + bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]]; + bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]]; + bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]]; + bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]]; + bcm->noisecalc.nr_samples++; + if (bcm->noisecalc.nr_samples == 8) { + /* Calculate the Link Quality by the noise samples. */ + average = 0; + for (i = 0; i < 8; i++) { + for (j = 0; j < 4; j++) + average += bcm->noisecalc.samples[i][j]; + } + average /= (8 * 4); + average *= 125; + average += 64; + average /= 128; + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C); + tmp = (tmp / 128) & 0x1F; + if (tmp >= 8) + average += 2; + else + average -= 25; + if (tmp == 8) + average -= 72; + else + average -= 48; + + if (average > -65) + bcm->stats.link_quality = 0; + else if (average > -75) + bcm->stats.link_quality = 1; + else if (average > -85) + bcm->stats.link_quality = 2; + else + bcm->stats.link_quality = 3; +// dprintk(KERN_INFO PFX "Link Quality: %u (avg was %d)\n", bcm->stats.link_quality, average); +drop_calculation: + bcm->noisecalc.calculation_running = 0; + return; + } +generate_new: + bcm43xx_generate_noise_sample(bcm); +} + +static inline +void handle_irq_ps(struct bcm43xx_private *bcm) +{ + if (bcm->ieee->iw_mode == IW_MODE_MASTER) { + ///TODO: PS TBTT + } else { + if (1/*FIXME: the last PSpoll frame was sent successfully */) + bcm43xx_power_saving_ctl_bits(bcm, -1, -1); + } + if (bcm->ieee->iw_mode == IW_MODE_ADHOC) + bcm->reg124_set_0x4 = 1; + //FIXME else set to false? +} + +static inline +void handle_irq_reg124(struct bcm43xx_private *bcm) +{ + if (!bcm->reg124_set_0x4) + return; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) + | 0x4); + //FIXME: reset reg124_set_0x4 to false? +} + +static inline +void handle_irq_pmq(struct bcm43xx_private *bcm) +{ + u32 tmp; + + //TODO: AP mode. + + while (1) { + tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS); + if (!(tmp & 0x00000008)) + break; + } + /* 16bit write is odd, but correct. */ + bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002); +} + +static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm, + u16 ram_offset, u16 shm_size_offset) +{ + u32 value; + u16 size = 0; + + /* Timestamp. */ + //FIXME: assumption: The chip sets the timestamp + value = 0; + bcm43xx_ram_write(bcm, ram_offset++, value); + bcm43xx_ram_write(bcm, ram_offset++, value); + size += 8; + + /* Beacon Interval / Capability Information */ + value = 0x0000;//FIXME: Which interval? + value |= (1 << 0) << 16; /* ESS */ + value |= (1 << 2) << 16; /* CF Pollable */ //FIXME? + value |= (1 << 3) << 16; /* CF Poll Request */ //FIXME? + if (!bcm->ieee->open_wep) + value |= (1 << 4) << 16; /* Privacy */ + bcm43xx_ram_write(bcm, ram_offset++, value); + size += 4; + + /* SSID */ + //TODO + + /* FH Parameter Set */ + //TODO + + /* DS Parameter Set */ + //TODO + + /* CF Parameter Set */ + //TODO + + /* TIM */ + //TODO + + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size); +} + +static inline +void handle_irq_beacon(struct bcm43xx_private *bcm) +{ + u32 status; + + bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON; + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD); + + if ((status & 0x1) && (status & 0x2)) { + /* ACK beacon IRQ. */ + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, + BCM43xx_IRQ_BEACON); + bcm->irq_savedstate |= BCM43xx_IRQ_BEACON; + return; + } + if (!(status & 0x1)) { + bcm43xx_generate_beacon_template(bcm, 0x68, 0x18); + status |= 0x1; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status); + } + if (!(status & 0x2)) { + bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A); + status |= 0x2; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status); + } +} + +/* Debug helper for irq bottom-half to print all reason registers. */ +#define bcmirq_print_reasons(description) \ + do { \ + dprintkl(KERN_ERR PFX description "\n" \ + KERN_ERR PFX " Generic Reason: 0x%08x\n" \ + KERN_ERR PFX " DMA reasons: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n" \ + KERN_ERR PFX " DMA TX status: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", \ + reason, \ + dma_reason[0], dma_reason[1], \ + dma_reason[2], dma_reason[3], \ + bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_BASE + BCM43xx_DMA_TX_STATUS), \ + bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_BASE + BCM43xx_DMA_TX_STATUS), \ + bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_BASE + BCM43xx_DMA_TX_STATUS), \ + bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_BASE + BCM43xx_DMA_TX_STATUS)); \ + } while (0) + +/* Interrupt handler bottom-half */ +static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) +{ + u32 reason; + u32 dma_reason[4]; + int activity = 0; + unsigned long flags; + +#ifdef CONFIG_BCM43XX_DEBUG + u32 _handled = 0x00000000; +# define bcmirq_handled(irq) do { _handled |= (irq); } while (0) +#else +# define bcmirq_handled(irq) do { /* nothing */ } while (0) +#endif /* CONFIG_BCM43XX_DEBUG*/ + + spin_lock_irqsave(&bcm->lock, flags); + reason = bcm->irq_reason; + dma_reason[0] = bcm->dma_reason[0]; + dma_reason[1] = bcm->dma_reason[1]; + dma_reason[2] = bcm->dma_reason[2]; + dma_reason[3] = bcm->dma_reason[3]; + + if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) { + /* TX error. We get this when Template Ram is written in wrong endianess + * in dummy_tx(). We also get this if something is wrong with the TX header + * on DMA or PIO queues. + * Maybe we get this in other error conditions, too. + */ + bcmirq_print_reasons("XMIT ERROR"); + bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR); + } + + if (reason & BCM43xx_IRQ_PS) { + handle_irq_ps(bcm); + bcmirq_handled(BCM43xx_IRQ_PS); + } + + if (reason & BCM43xx_IRQ_REG124) { + handle_irq_reg124(bcm); + bcmirq_handled(BCM43xx_IRQ_REG124); + } + + if (reason & BCM43xx_IRQ_BEACON) { + if (bcm->ieee->iw_mode == IW_MODE_MASTER) + handle_irq_beacon(bcm); + bcmirq_handled(BCM43xx_IRQ_BEACON); + } + + if (reason & BCM43xx_IRQ_PMQ) { + handle_irq_pmq(bcm); + bcmirq_handled(BCM43xx_IRQ_PMQ); + } + + if (reason & BCM43xx_IRQ_SCAN) { + /*TODO*/ + //bcmirq_handled(BCM43xx_IRQ_SCAN); + } + + if (reason & BCM43xx_IRQ_NOISE) { + handle_irq_noise(bcm); + bcmirq_handled(BCM43xx_IRQ_NOISE); + } + + /* Check the DMA reason registers for received data. */ + assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE)); + assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); + if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { + if (bcm->pio_mode) + bcm43xx_pio_rx(bcm->current_core->pio->queue0); + else + bcm43xx_dma_rx(bcm->current_core->dma->rx_ring0); + activity = 1; + } + if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { + if (likely(bcm->current_core->rev < 5)) { + if (bcm->pio_mode) + bcm43xx_pio_rx(bcm->current_core->pio->queue3); + else + bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1); + activity = 1; + } else + assert(0); + } + bcmirq_handled(BCM43xx_IRQ_RX); + + if (reason & BCM43xx_IRQ_XMIT_STATUS) { + if (bcm->current_core->rev >= 5) { + handle_irq_transmit_status(bcm); + activity = 1; + } + //TODO: In AP mode, this also causes sending of powersave responses. + bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS); + } + + /* We get spurious IRQs, althought they are masked. + * Assume they are void and ignore them. + */ + bcmirq_handled(~(bcm->irq_savedstate)); + /* IRQ_PIO_WORKAROUND is handled in the top-half. */ + bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND); +#ifdef CONFIG_BCM43XX_DEBUG + if (unlikely(reason & ~_handled)) { + printkl(KERN_WARNING PFX + "Unhandled IRQ! Reason: 0x%08x, Unhandled: 0x%08x, " + "DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + reason, (reason & ~_handled), + dma_reason[0], dma_reason[1], + dma_reason[2], dma_reason[3]); + } +#endif +#undef bcmirq_handled + + if (!modparam_noleds) + bcm43xx_leds_update(bcm, activity); + bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); + spin_unlock_irqrestore(&bcm->lock, flags); +} + +#undef bcmirq_print_reasons + +static inline +void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, + u32 reason, u32 mask) +{ + bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) + & 0x0001dc00; + bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) + & 0x0000dc00; + bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) + & 0x0000dc00; + bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) + & 0x0001dc00; + + if ((bcm->pio_mode) && + (bcm->current_core->rev < 3) && + (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) { + /* Apply a PIO specific workaround to the dma_reasons */ + +#define apply_pio_workaround(BASE, QNUM) \ + do { \ + if (bcm43xx_read16(bcm, BASE + BCM43xx_PIO_RXCTL) & BCM43xx_PIO_RXCTL_DATAAVAILABLE) \ + bcm->dma_reason[QNUM] |= 0x00010000; \ + else \ + bcm->dma_reason[QNUM] &= ~0x00010000; \ + } while (0) + + apply_pio_workaround(BCM43xx_MMIO_PIO1_BASE, 0); + apply_pio_workaround(BCM43xx_MMIO_PIO2_BASE, 1); + apply_pio_workaround(BCM43xx_MMIO_PIO3_BASE, 2); + apply_pio_workaround(BCM43xx_MMIO_PIO4_BASE, 3); + +#undef apply_pio_workaround + } + + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, + reason & mask); + + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON, + bcm->dma_reason[0]); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON, + bcm->dma_reason[1]); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON, + bcm->dma_reason[2]); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON, + bcm->dma_reason[3]); +} + +/* Interrupt handler top-half */ +static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + struct bcm43xx_private *bcm = dev_id; + u32 reason, mask; + + if (!bcm) + return IRQ_NONE; + + spin_lock(&bcm->lock); + + reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + if (reason == 0xffffffff) { + /* irq not for us (shared irq) */ + spin_unlock(&bcm->lock); + return IRQ_NONE; + } + mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); + if (!(reason & mask)) { + spin_unlock(&bcm->lock); + return IRQ_HANDLED; + } + + bcm43xx_interrupt_ack(bcm, reason, mask); + + /* 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. */ + bcm->irq_reason = reason; + tasklet_schedule(&bcm->isr_tasklet); + + spin_unlock(&bcm->lock); + + return IRQ_HANDLED; +} + +static void bcm43xx_release_firmware(struct bcm43xx_private *bcm) +{ + if (bcm->firmware_norelease) + return; /* Suspending or controller reset. */ + release_firmware(bcm->ucode); + bcm->ucode = NULL; + release_firmware(bcm->pcm); + bcm->pcm = NULL; + release_firmware(bcm->initvals0); + bcm->initvals0 = NULL; + release_firmware(bcm->initvals1); + bcm->initvals1 = NULL; +} + +static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u8 rev = bcm->current_core->rev; + int err = 0; + int nr; + char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 }; + + if (!bcm->ucode) { + snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw", + (rev >= 5 ? 5 : rev), + modparam_fwpostfix); + err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: Microcode \"%s\" not available or load failed.\n", + buf); + goto error; + } + } + + if (!bcm->pcm) { + snprintf(buf, ARRAY_SIZE(buf), + "bcm43xx_pcm%d%s.fw", + (rev < 5 ? 4 : 5), + modparam_fwpostfix); + err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: PCM \"%s\" not available or load failed.\n", + buf); + goto error; + } + } + + if (!bcm->initvals0) { + if (rev == 2 || rev == 4) { + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + nr = 3; + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + nr = 1; + break; + default: + goto err_noinitval; + } + + } else if (rev >= 5) { + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + nr = 7; + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + nr = 5; + break; + default: + goto err_noinitval; + } + } else + goto err_noinitval; + snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", + nr, modparam_fwpostfix); + + err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: InitVals \"%s\" not available or load failed.\n", + buf); + goto error; + } + if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) { + printk(KERN_ERR PFX "InitVals fileformat error.\n"); + goto error; + } + } + + if (!bcm->initvals1) { + if (rev >= 5) { + u32 sbtmstatehigh; + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); + if (sbtmstatehigh & 0x00010000) + nr = 9; + else + nr = 10; + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + nr = 6; + break; + default: + goto err_noinitval; + } + snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", + nr, modparam_fwpostfix); + + err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: InitVals \"%s\" not available or load failed.\n", + buf); + goto error; + } + if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) { + printk(KERN_ERR PFX "InitVals fileformat error.\n"); + goto error; + } + } + } + +out: + return err; +error: + bcm43xx_release_firmware(bcm); + goto out; +err_noinitval: + printk(KERN_ERR PFX "Error: No InitVals available!\n"); + err = -ENOENT; + goto error; +} + +static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) +{ + const u32 *data; + unsigned int i, len; + +#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT + bcm43xx_mmioprint_enable(bcm); +#else + bcm43xx_mmioprint_disable(bcm); +#endif + + /* Upload Microcode. */ + data = (u32 *)(bcm->ucode->data); + len = bcm->ucode->size / sizeof(u32); + bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000); + for (i = 0; i < len; i++) { + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, + be32_to_cpu(data[i])); + udelay(10); + } + + /* Upload PCM data. */ + data = (u32 *)(bcm->pcm->data); + len = bcm->pcm->size / sizeof(u32); + bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea); + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000); + bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb); + for (i = 0; i < len; i++) { + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, + be32_to_cpu(data[i])); + udelay(10); + } + +#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT + bcm43xx_mmioprint_disable(bcm); +#else + bcm43xx_mmioprint_enable(bcm); +#endif +} + +static void bcm43xx_write_initvals(struct bcm43xx_private *bcm, + const struct bcm43xx_initval *data, + const unsigned int len) +{ + u16 offset, size; + u32 value; + unsigned int i; + + for (i = 0; i < len; i++) { + offset = be16_to_cpu(data[i].offset); + size = be16_to_cpu(data[i].size); + value = be32_to_cpu(data[i].value); + + if (size == 2) + bcm43xx_write16(bcm, offset, value); + else if (size == 4) + bcm43xx_write32(bcm, offset, value); + else + printk(KERN_ERR PFX "InitVals fileformat error.\n"); + } +} + +static void bcm43xx_upload_initvals(struct bcm43xx_private *bcm) +{ +#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT + bcm43xx_mmioprint_enable(bcm); +#else + bcm43xx_mmioprint_disable(bcm); +#endif + + bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, + bcm->initvals0->size / sizeof(struct bcm43xx_initval)); + if (bcm->initvals1) { + bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data, + bcm->initvals1->size / sizeof(struct bcm43xx_initval)); + } + +#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT + bcm43xx_mmioprint_disable(bcm); +#else + bcm43xx_mmioprint_enable(bcm); +#endif +} + +static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) +{ + int res; + unsigned int i; + u32 data; + + 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; + } + } +#endif + res = request_irq(bcm->irq, bcm43xx_interrupt_handler, + SA_SHIRQ, DRV_NAME, bcm); + if (res) { + printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); + return -EFAULT; + } + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff); + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402); + i = 0; + while (1) { + data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + if (data == BCM43xx_IRQ_READY) + break; + i++; + if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) { + printk(KERN_ERR PFX "Card IRQ register not responding. " + "Giving up.\n"); + free_irq(bcm->irq, bcm); + return -ENODEV; + } + udelay(10); + } + // dummy read + bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + + return 0; +} + +/* Switch to the core used to write the GPIO register. + * This is either the ChipCommon, or the PCI core. + */ +static inline int switch_to_gpio_core(struct bcm43xx_private *bcm) +{ + int err; + + /* Where to find the GPIO register depends on the chipset. + * If it has a ChipCommon, its register at offset 0x6c is the GPIO + * control register. Otherwise the register at offset 0x6c in the + * PCI core is the GPIO control register. + */ + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err == -ENODEV) { + err = bcm43xx_switch_core(bcm, &bcm->core_pci); + if (err == -ENODEV) { + printk(KERN_ERR PFX "gpio error: " + "Neither ChipCommon nor PCI core available!\n"); + return -ENODEV; + } else if (err != 0) + return -ENODEV; + } else if (err != 0) + return -ENODEV; + + return 0; +} + +/* Initialize the GPIOs + * http://bcm-specs.sipsolutions.net/GPIO + */ +static int bcm43xx_gpio_init(struct bcm43xx_private *bcm) +{ + struct bcm43xx_coreinfo *old_core; + int err; + u32 mask, value; + + value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value &= ~0xc000; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); + + mask = 0x0000001F; + value = 0x0000000F; + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, + bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL) & 0xFFF0); + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, + bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F); + + old_core = bcm->current_core; + + err = switch_to_gpio_core(bcm); + if (err) + return err; + + if (bcm->current_core->rev >= 2){ + mask |= 0x10; + value |= 0x10; + } + if (bcm->chip_id == 0x4301) { + mask |= 0x60; + value |= 0x60; + } + if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) { + mask |= 0x200; + value |= 0x200; + } + + bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, + (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | value); + + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + + return 0; +} + +/* Turn off all GPIO stuff. Call this on module unload, for example. */ +static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm) +{ + struct bcm43xx_coreinfo *old_core; + int err; + + old_core = bcm->current_core; + err = switch_to_gpio_core(bcm); + if (err) + return err; + bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000); + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + + return 0; +} + +/* http://bcm-specs.sipsolutions.net/EnableMac */ +void bcm43xx_mac_enable(struct bcm43xx_private *bcm) +{ + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + | BCM43xx_SBF_MAC_ENABLED); + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY); + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ + bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ + bcm43xx_power_saving_ctl_bits(bcm, -1, -1); +} + +/* http://bcm-specs.sipsolutions.net/SuspendMAC */ +void bcm43xx_mac_suspend(struct bcm43xx_private *bcm) +{ + int i; + u32 tmp; + + bcm43xx_power_saving_ctl_bits(bcm, -1, 1); + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + & ~BCM43xx_SBF_MAC_ENABLED); + bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ + for (i = 1000; i > 0; i--) { + tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + if (tmp & BCM43xx_IRQ_READY) { + i = -1; + break; + } + udelay(10); + } + if (!i) + printkl(KERN_ERR PFX "Failed to suspend mac!\n"); +} + +void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, + int iw_mode) +{ + unsigned long flags; + u32 status; + + spin_lock_irqsave(&bcm->ieee->lock, flags); + bcm->ieee->iw_mode = iw_mode; + spin_unlock_irqrestore(&bcm->ieee->lock, flags); + if (iw_mode == IW_MODE_MONITOR) + bcm->net_dev->type = ARPHRD_IEEE80211; + else + bcm->net_dev->type = ARPHRD_ETHER; + + if (!bcm->initialized) + return; + + bcm43xx_mac_suspend(bcm); + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + /* Reset status to infrastructured mode */ + status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR); + /*FIXME: We actually set promiscuous mode as well, until we don't + * get the HW mac filter working */ + status |= BCM43xx_SBF_MODE_NOTADHOC | BCM43xx_SBF_MODE_PROMISC; + + switch (iw_mode) { + case IW_MODE_MONITOR: + status |= (BCM43xx_SBF_MODE_PROMISC | + BCM43xx_SBF_MODE_MONITOR); + break; + case IW_MODE_ADHOC: + status &= ~BCM43xx_SBF_MODE_NOTADHOC; + break; + case IW_MODE_MASTER: + case IW_MODE_SECOND: + case IW_MODE_REPEAT: + /* TODO: No AP/Repeater mode for now :-/ */ + TODO(); + break; + case IW_MODE_INFRA: + /* nothing to be done here... */ + break; + default: + printk(KERN_ERR PFX "Unknown iwmode %d\n", iw_mode); + } + + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + bcm43xx_mac_enable(bcm); +} + +/* This is the opposite of bcm43xx_chip_init() */ +static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm) +{ + bcm43xx_radio_turn_off(bcm); + if (!modparam_noleds) + bcm43xx_leds_exit(bcm); + bcm43xx_gpio_cleanup(bcm); + free_irq(bcm->irq, bcm); + bcm43xx_release_firmware(bcm); +} + +/* Initialize the chip + * http://bcm-specs.sipsolutions.net/ChipInit + */ +static int bcm43xx_chip_init(struct bcm43xx_private *bcm) +{ + int err; + int iw_mode = bcm->ieee->iw_mode; + int tmp; + u32 value32; + u16 value16; + + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + BCM43xx_SBF_CORE_READY + | BCM43xx_SBF_400); + + err = bcm43xx_request_firmware(bcm); + if (err) + goto out; + bcm43xx_upload_microcode(bcm); + + err = bcm43xx_initialize_irq(bcm); + if (err) + goto out; + + err = bcm43xx_gpio_init(bcm); + if (err) + goto err_free_irq; + + bcm43xx_upload_initvals(bcm); + bcm43xx_radio_turn_on(bcm); + + if (modparam_noleds) + bcm43xx_leds_turn_off(bcm); + else + bcm43xx_leds_update(bcm, 0); + + bcm43xx_write16(bcm, 0x03E6, 0x0000); + err = bcm43xx_phy_init(bcm); + if (err) + goto err_radio_off; + + /* Select initial Interference Mitigation. */ + tmp = bcm->current_core->radio->interfmode; + bcm->current_core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; + bcm43xx_radio_set_interference_mitigation(bcm, tmp); + + bcm43xx_phy_set_antenna_diversity(bcm); + bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT); + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) { + value16 = bcm43xx_read16(bcm, 0x005E); + value16 |= 0x0004; + bcm43xx_write16(bcm, 0x005E, value16); + } + bcm43xx_write32(bcm, 0x0100, 0x01000000); + if (bcm->current_core->rev < 5) + bcm43xx_write32(bcm, 0x010C, 0x01000000); + + value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); + value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value32 |= BCM43xx_SBF_MODE_NOTADHOC; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); + /*FIXME: For now, use promiscuous mode at all times; otherwise we don't + get broadcast or multicast packets */ + value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value32 |= BCM43xx_SBF_MODE_PROMISC; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); + + if (iw_mode == IW_MODE_MONITOR) { + value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value32 |= BCM43xx_SBF_MODE_PROMISC; + value32 |= BCM43xx_SBF_MODE_MONITOR; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); + } + value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value32 |= 0x100000; //FIXME: What's this? Is this correct? + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); + + if (bcm->pio_mode) { + bcm43xx_write32(bcm, 0x0210, 0x00000100); + bcm43xx_write32(bcm, 0x0230, 0x00000100); + bcm43xx_write32(bcm, 0x0250, 0x00000100); + bcm43xx_write32(bcm, 0x0270, 0x00000100); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000); + } + + /* Probe Response Timeout value */ + /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000); + + if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) { + if ((bcm->chip_id == 0x4306) && (bcm->chip_rev == 3)) + bcm43xx_write16(bcm, 0x0612, 0x0064); + else + bcm43xx_write16(bcm, 0x0612, 0x0032); + } else + bcm43xx_write16(bcm, 0x0612, 0x0002); + + if (bcm->current_core->rev < 3) { + bcm43xx_write16(bcm, 0x060E, 0x0000); + bcm43xx_write16(bcm, 0x0610, 0x8000); + bcm43xx_write16(bcm, 0x0604, 0x0000); + bcm43xx_write16(bcm, 0x0606, 0x0200); + } else { + bcm43xx_write32(bcm, 0x0188, 0x80000000); + bcm43xx_write32(bcm, 0x018C, 0x02000000); + } + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0001DC00); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0000DC00); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0001DC00); + + value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + value32 |= 0x00100000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32); + + bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm)); + + assert(err == 0); + dprintk(KERN_INFO PFX "Chip initialized\n"); +out: + return err; + +err_radio_off: + bcm43xx_radio_turn_off(bcm); + bcm43xx_gpio_cleanup(bcm); +err_free_irq: + free_irq(bcm->irq, bcm); + goto out; +} + +/* Validate chip access + * http://bcm-specs.sipsolutions.net/ValidateChipAccess */ +static int bcm43xx_validate_chip(struct bcm43xx_private *bcm) +{ + int err = -ENODEV; + u32 value; + u32 shm_backup; + + shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA); + if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA) { + printk(KERN_ERR PFX "Error: SHM mismatch (1) validating chip\n"); + goto out; + } + + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55); + if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55) { + printk(KERN_ERR PFX "Error: SHM mismatch (2) validating chip\n"); + goto out; + } + + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup); + + value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + if ((value | 0x80000000) != 0x80000400) { + printk(KERN_ERR PFX "Error: Bad Status Bitfield while validating chip\n"); + goto out; + } + + value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + if (value != 0x00000000) { + printk(KERN_ERR PFX "Error: Bad interrupt reason code while validating chip\n"); + goto out; + } + + err = 0; +out: + return err; +} + +static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) +{ + int err, i; + int current_core; + u32 core_vendor, core_id, core_rev; + u32 sb_id_hi, chip_id_32 = 0; + u16 pci_device, chip_id_16; + u8 core_count; + + memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo)); + memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo)); + memset(&bcm->core_v90, 0, sizeof(struct bcm43xx_coreinfo)); + memset(&bcm->core_pcmcia, 0, sizeof(struct bcm43xx_coreinfo)); + memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo) + * BCM43xx_MAX_80211_CORES); + + memset(&bcm->phy, 0, sizeof(struct bcm43xx_phyinfo) + * BCM43xx_MAX_80211_CORES); + memset(&bcm->radio, 0, sizeof(struct bcm43xx_radioinfo) + * BCM43xx_MAX_80211_CORES); + + /* map core 0 */ + err = _switch_core(bcm, 0); + if (err) + goto out; + + /* fetch sb_id_hi from core information registers */ + sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI); + + core_id = (sb_id_hi & 0xFFF0) >> 4; + core_rev = (sb_id_hi & 0xF); + core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; + + /* if present, chipcommon is always core 0; read the chipid from it */ + if (core_id == BCM43xx_COREID_CHIPCOMMON) { + chip_id_32 = bcm43xx_read32(bcm, 0); + chip_id_16 = chip_id_32 & 0xFFFF; + bcm->core_chipcommon.flags |= BCM43xx_COREFLAG_AVAILABLE; + bcm->core_chipcommon.id = core_id; + bcm->core_chipcommon.rev = core_rev; + bcm->core_chipcommon.index = 0; + /* While we are at it, also read the capabilities. */ + bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES); + } else { + /* without a chipCommon, use a hard coded table. */ + pci_device = bcm->pci_dev->device; + if (pci_device == 0x4301) + chip_id_16 = 0x4301; + else if ((pci_device >= 0x4305) && (pci_device <= 0x4307)) + chip_id_16 = 0x4307; + else if ((pci_device >= 0x4402) && (pci_device <= 0x4403)) + chip_id_16 = 0x4402; + else if ((pci_device >= 0x4610) && (pci_device <= 0x4615)) + chip_id_16 = 0x4610; + else if ((pci_device >= 0x4710) && (pci_device <= 0x4715)) + chip_id_16 = 0x4710; +#ifdef CONFIG_BCM947XX + else if ((pci_device >= 0x4320) && (pci_device <= 0x4325)) + chip_id_16 = 0x4309; +#endif + else { + printk(KERN_ERR PFX "Could not determine Chip ID\n"); + return -ENODEV; + } + } + + /* ChipCommon with Core Rev >=4 encodes number of cores, + * otherwise consult hardcoded table */ + if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) { + core_count = (chip_id_32 & 0x0F000000) >> 24; + } else { + switch (chip_id_16) { + case 0x4610: + case 0x4704: + case 0x4710: + core_count = 9; + break; + case 0x4310: + core_count = 8; + break; + case 0x5365: + core_count = 7; + break; + case 0x4306: + core_count = 6; + break; + case 0x4301: + case 0x4307: + core_count = 5; + break; + case 0x4402: + core_count = 3; + break; + default: + /* SOL if we get here */ + assert(0); + core_count = 1; + } + } + + bcm->chip_id = chip_id_16; + bcm->chip_rev = (chip_id_32 & 0x000f0000) >> 16; + + dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n", + bcm->chip_id, bcm->chip_rev); + dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count); + if (bcm->core_chipcommon.flags & BCM43xx_COREFLAG_AVAILABLE) { + dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n", + core_id, core_rev, core_vendor, + bcm43xx_core_enabled(bcm) ? "enabled" : "disabled"); + } + + if (bcm->core_chipcommon.flags & BCM43xx_COREFLAG_AVAILABLE) + current_core = 1; + else + current_core = 0; + for ( ; current_core < core_count; current_core++) { + struct bcm43xx_coreinfo *core; + + err = _switch_core(bcm, current_core); + if (err) + goto out; + /* Gather information */ + /* fetch sb_id_hi from core information registers */ + sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI); + + /* extract core_id, core_rev, core_vendor */ + core_id = (sb_id_hi & 0xFFF0) >> 4; + core_rev = (sb_id_hi & 0xF); + core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; + + dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n", + current_core, core_id, core_rev, core_vendor, + bcm43xx_core_enabled(bcm) ? "enabled" : "disabled" ); + + core = NULL; + switch (core_id) { + case BCM43xx_COREID_PCI: + core = &bcm->core_pci; + if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { + printk(KERN_WARNING PFX "Multiple PCI cores found.\n"); + continue; + } + break; + case BCM43xx_COREID_V90: + core = &bcm->core_v90; + if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { + printk(KERN_WARNING PFX "Multiple V90 cores found.\n"); + continue; + } + break; + case BCM43xx_COREID_PCMCIA: + core = &bcm->core_pcmcia; + if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { + printk(KERN_WARNING PFX "Multiple PCMCIA cores found.\n"); + continue; + } + break; + case BCM43xx_COREID_ETHERNET: + core = &bcm->core_ethernet; + if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { + printk(KERN_WARNING PFX "Multiple Ethernet cores found.\n"); + continue; + } + break; + case BCM43xx_COREID_80211: + for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { + core = &(bcm->core_80211[i]); + if (!(core->flags & BCM43xx_COREFLAG_AVAILABLE)) + break; + core = NULL; + } + if (!core) { + printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n", + BCM43xx_MAX_80211_CORES); + continue; + } + if (i != 0) { + /* More than one 80211 core is only supported + * by special chips. + * There are chips with two 80211 cores, but with + * dangling pins on the second core. Be careful + * and ignore these cores here. + */ + if (bcm->pci_dev->device != 0x4324) { + dprintk(KERN_INFO PFX "Ignoring additional 802.11 core.\n"); + continue; + } + } + switch (core_rev) { + case 2: + case 4: + case 5: + case 6: + case 7: + case 9: + break; + default: + printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n", + core_rev); + err = -ENODEV; + goto out; + } + core->phy = &bcm->phy[i]; + core->phy->antenna_diversity = 0xffff; + core->phy->savedpctlreg = 0xFFFF; + core->phy->minlowsig[0] = 0xFFFF; + core->phy->minlowsig[1] = 0xFFFF; + core->phy->minlowsigpos[0] = 0; + core->phy->minlowsigpos[1] = 0; + spin_lock_init(&core->phy->lock); + core->radio = &bcm->radio[i]; + core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; + core->radio->channel = 0xFF; + core->radio->initial_channel = 0xFF; + core->radio->lofcal = 0xFFFF; + core->radio->initval = 0xFFFF; + core->radio->nrssi[0] = -1000; + core->radio->nrssi[1] = -1000; + core->dma = &bcm->dma[i]; + core->pio = &bcm->pio[i]; + break; + case BCM43xx_COREID_CHIPCOMMON: + printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n"); + break; + default: + printk(KERN_WARNING PFX "Unknown core found (ID 0x%x)\n", core_id); + } + if (core) { + core->flags |= BCM43xx_COREFLAG_AVAILABLE; + core->id = core_id; + core->rev = core_rev; + core->index = current_core; + } + } + + if (!(bcm->core_80211[0].flags & BCM43xx_COREFLAG_AVAILABLE)) { + printk(KERN_ERR PFX "Error: No 80211 core found!\n"); + err = -ENODEV; + goto out; + } + + err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]); + + assert(err == 0); +out: + return err; +} + +static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm) +{ + const u8 *mac = (const u8*)(bcm->net_dev->dev_addr); + u8 *bssid = bcm->ieee->bssid; + + switch (bcm->ieee->iw_mode) { + case IW_MODE_ADHOC: + random_ether_addr(bssid); + break; + case IW_MODE_MASTER: + case IW_MODE_INFRA: + case IW_MODE_REPEAT: + case IW_MODE_SECOND: + case IW_MODE_MONITOR: + memcpy(bssid, mac, ETH_ALEN); + break; + default: + assert(0); + } +} + +static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm, + u16 rate, + int is_ofdm) +{ + u16 offset; + + if (is_ofdm) { + offset = 0x480; + offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2; + } + else { + offset = 0x4C0; + offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2; + } + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20, + bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset)); +} + +static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm) +{ + switch (bcm->current_core->phy->type) { + case BCM43xx_PHYTYPE_A: + case BCM43xx_PHYTYPE_G: + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1); + case BCM43xx_PHYTYPE_B: + bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0); + bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0); + bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0); + bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0); + break; + default: + assert(0); + } +} + +static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm) +{ + bcm43xx_chip_cleanup(bcm); + bcm43xx_pio_free(bcm); + bcm43xx_dma_free(bcm); + + bcm->current_core->flags &= ~ BCM43xx_COREFLAG_INITIALIZED; +} + +/* http://bcm-specs.sipsolutions.net/80211Init */ +static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) +{ + u32 ucodeflags; + int err; + u32 sbimconfiglow; + u8 limit; + + if (bcm->chip_rev < 5) { + sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); + sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; + sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; + if (bcm->bustype == BCM43xx_BUSTYPE_PCI) + sbimconfiglow |= 0x32; + else if (bcm->bustype == BCM43xx_BUSTYPE_SB) + sbimconfiglow |= 0x53; + else + assert(0); + bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow); + } + + bcm43xx_phy_calibrate(bcm); + err = bcm43xx_chip_init(bcm); + if (err) + goto out; + + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev); + ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET); + + if (0 /*FIXME: which condition has to be used here? */) + ucodeflags |= 0x00000010; + + /* HW decryption needs to be set now */ + ucodeflags |= 0x40000000; + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; + if (bcm->current_core->phy->rev == 1) + ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY; + if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) + ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL; + } else if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) { + ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; + if ((bcm->current_core->phy->rev >= 2) && + (bcm->current_core->radio->version == 0x2050)) + ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY; + } + + if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET)) { + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, ucodeflags); + } + + /* Short/Long Retry Limit. + * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing + * the chip-internal counter. + */ + limit = limit_value(modparam_short_retry, 0, 0xF); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit); + limit = limit_value(modparam_long_retry, 0, 0xF); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit); + + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2); + + bcm43xx_rate_memory_init(bcm); + + /* Minimum Contention Window */ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f); + else + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f); + /* Maximum Contention Window */ + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff); + + bcm43xx_gen_bssid(bcm); + bcm43xx_write_mac_bssid_templates(bcm); + + if (bcm->current_core->rev >= 5) + bcm43xx_write16(bcm, 0x043C, 0x000C); + + if (!bcm->pio_mode) { + err = bcm43xx_dma_init(bcm); + if (err) + goto err_chip_cleanup; + } else { + err = bcm43xx_pio_init(bcm); + if (err) + goto err_chip_cleanup; + } + bcm43xx_write16(bcm, 0x0612, 0x0050); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); + + bcm43xx_mac_enable(bcm); + bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); + + bcm->current_core->flags |= BCM43xx_COREFLAG_INITIALIZED; +out: + return err; + +err_chip_cleanup: + bcm43xx_chip_cleanup(bcm); + goto out; +} + +static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm) +{ + int err; + u16 pci_status; + + err = bcm43xx_pctl_set_crystal(bcm, 1); + if (err) + goto out; + bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status); + bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT); + +out: + return err; +} + +static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm) +{ + bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); + bcm43xx_pctl_set_crystal(bcm, 0); +} + +static inline void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm, + u32 address, + u32 data) +{ + bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address); + bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data); +} + +static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm) +{ + int err; + struct bcm43xx_coreinfo *old_core; + + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_pci); + if (err) + goto out; + + bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); + + bcm43xx_switch_core(bcm, old_core); + assert(err == 0); +out: + return err; +} + +/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable. + * To enable core 0, pass a core_mask of 1<<0 + */ +static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm, + u32 core_mask) +{ + u32 backplane_flag_nr; + u32 value; + struct bcm43xx_coreinfo *old_core; + int err = 0; + + value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG); + backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK; + + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_pci); + if (err) + goto out; + + if (bcm->core_pci.rev < 6) { + value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC); + value |= (1 << backplane_flag_nr); + bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value); + } else { + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value); + if (err) { + printk(KERN_ERR PFX "Error: ICR setup failure!\n"); + goto out_switch_back; + } + value |= core_mask << 8; + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value); + if (err) { + printk(KERN_ERR PFX "Error: ICR setup failure!\n"); + goto out_switch_back; + } + } + + value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); + value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST; + bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); + + if (bcm->core_pci.rev < 5) { + value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); + value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT) + & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; + value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT) + & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; + bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value); + err = bcm43xx_pcicore_commit_settings(bcm); + assert(err == 0); + } + +out_switch_back: + err = bcm43xx_switch_core(bcm, old_core); +out: + return err; +} + +static void bcm43xx_softmac_init(struct bcm43xx_private *bcm) +{ + ieee80211softmac_start(bcm->net_dev); +} + +static void bcm43xx_periodic_work0_handler(void *d) +{ + struct bcm43xx_private *bcm = d; + unsigned long flags; + //TODO: unsigned int aci_average; + + spin_lock_irqsave(&bcm->lock, flags); + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + //FIXME: aci_average = bcm43xx_update_aci_average(bcm); + if (bcm->current_core->radio->aci_enable && bcm->current_core->radio->aci_wlan_automatic) { + bcm43xx_mac_suspend(bcm); + if (!bcm->current_core->radio->aci_enable && + 1 /*FIXME: We are not scanning? */) { + /*FIXME: First add bcm43xx_update_aci_average() before + * uncommenting this: */ + //if (bcm43xx_radio_aci_scan) + // bcm43xx_radio_set_interference_mitigation(bcm, + // BCM43xx_RADIO_INTERFMODE_MANUALWLAN); + } else if (1/*FIXME*/) { + //if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) + // bcm43xx_radio_set_interference_mitigation(bcm, + // BCM43xx_RADIO_INTERFMODE_MANUALWLAN); + } + bcm43xx_mac_enable(bcm); + } else if (bcm->current_core->radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) { + if (bcm->current_core->phy->rev == 1) { + //FIXME: implement rev1 workaround + } + } + } + bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning? + //TODO for APHY (temperature?) + + if (likely(!bcm->shutting_down)) { + queue_delayed_work(bcm->workqueue, &bcm->periodic_work0, + BCM43xx_PERIODIC_0_DELAY); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +static void bcm43xx_periodic_work1_handler(void *d) +{ + struct bcm43xx_private *bcm = d; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + + bcm43xx_phy_lo_mark_all_unused(bcm); + if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { + bcm43xx_mac_suspend(bcm); + bcm43xx_calc_nrssi_slope(bcm); + bcm43xx_mac_enable(bcm); + } + + if (likely(!bcm->shutting_down)) { + queue_delayed_work(bcm->workqueue, &bcm->periodic_work1, + BCM43xx_PERIODIC_1_DELAY); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +static void bcm43xx_periodic_work2_handler(void *d) +{ + struct bcm43xx_private *bcm = d; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + + assert(bcm->current_core->phy->type == BCM43xx_PHYTYPE_G); + assert(bcm->current_core->phy->rev >= 2); + + bcm43xx_mac_suspend(bcm); + bcm43xx_phy_lo_g_measure(bcm); + bcm43xx_mac_enable(bcm); + + if (likely(!bcm->shutting_down)) { + queue_delayed_work(bcm->workqueue, &bcm->periodic_work2, + BCM43xx_PERIODIC_2_DELAY); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +static void bcm43xx_periodic_work3_handler(void *d) +{ + struct bcm43xx_private *bcm = d; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + + /* Update device statistics. */ + bcm43xx_calculate_link_quality(bcm); + + if (likely(!bcm->shutting_down)) { + queue_delayed_work(bcm->workqueue, &bcm->periodic_work3, + BCM43xx_PERIODIC_3_DELAY); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +/* Delete all periodic tasks and make + * sure they are not running any longer + */ +static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) +{ + cancel_delayed_work(&bcm->periodic_work0); + cancel_delayed_work(&bcm->periodic_work1); + cancel_delayed_work(&bcm->periodic_work2); + cancel_delayed_work(&bcm->periodic_work3); + flush_workqueue(bcm->workqueue); +} + +/* Setup all periodic tasks. */ +static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) +{ + INIT_WORK(&bcm->periodic_work0, bcm43xx_periodic_work0_handler, bcm); + INIT_WORK(&bcm->periodic_work1, bcm43xx_periodic_work1_handler, bcm); + INIT_WORK(&bcm->periodic_work2, bcm43xx_periodic_work2_handler, bcm); + INIT_WORK(&bcm->periodic_work3, bcm43xx_periodic_work3_handler, bcm); + + /* Periodic task 0: Delay ~15sec */ + queue_delayed_work(bcm->workqueue, &bcm->periodic_work0, + BCM43xx_PERIODIC_0_DELAY); + + /* Periodic task 1: Delay ~60sec */ + queue_delayed_work(bcm->workqueue, &bcm->periodic_work1, + BCM43xx_PERIODIC_1_DELAY); + + /* Periodic task 2: Delay ~120sec */ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && + bcm->current_core->phy->rev >= 2) { + queue_delayed_work(bcm->workqueue, &bcm->periodic_work2, + BCM43xx_PERIODIC_2_DELAY); + } + + /* Periodic task 3: Delay ~30sec */ + queue_delayed_work(bcm->workqueue, &bcm->periodic_work3, + BCM43xx_PERIODIC_3_DELAY); +} + +static void bcm43xx_security_init(struct bcm43xx_private *bcm) +{ + bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, + 0x0056) * 2; + bcm43xx_clear_keys(bcm); +} + +/* This is the opposite of bcm43xx_init_board() */ +static void bcm43xx_free_board(struct bcm43xx_private *bcm) +{ + int i, err; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + bcm->initialized = 0; + bcm->shutting_down = 1; + spin_unlock_irqrestore(&bcm->lock, flags); + + bcm43xx_periodic_tasks_delete(bcm); + + for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { + if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE)) + continue; + if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_INITIALIZED)) + continue; + + err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); + assert(err == 0); + bcm43xx_wireless_core_cleanup(bcm); + } + + bcm43xx_pctl_set_crystal(bcm, 0); + + spin_lock_irqsave(&bcm->lock, flags); + bcm->shutting_down = 0; + spin_unlock_irqrestore(&bcm->lock, flags); +} + +static int bcm43xx_init_board(struct bcm43xx_private *bcm) +{ + int i, err; + int num_80211_cores; + int connect_phy; + unsigned long flags; + + might_sleep(); + + spin_lock_irqsave(&bcm->lock, flags); + bcm->initialized = 0; + bcm->shutting_down = 0; + spin_unlock_irqrestore(&bcm->lock, flags); + + err = bcm43xx_pctl_set_crystal(bcm, 1); + if (err) + goto out; + err = bcm43xx_pctl_init(bcm); + if (err) + goto err_crystal_off; + err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST); + if (err) + goto err_crystal_off; + + tasklet_enable(&bcm->isr_tasklet); + num_80211_cores = bcm43xx_num_80211_cores(bcm); + for (i = 0; i < num_80211_cores; i++) { + err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); + assert(err != -ENODEV); + if (err) + goto err_80211_unwind; + + /* Enable the selected wireless core. + * Connect PHY only on the first core. + */ + if (!bcm43xx_core_enabled(bcm)) { + if (num_80211_cores == 1) { + connect_phy = bcm->current_core->phy->connected; + } else { + if (i == 0) + connect_phy = 1; + else + connect_phy = 0; + } + bcm43xx_wireless_core_reset(bcm, connect_phy); + } + + if (i != 0) + bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]); + + err = bcm43xx_wireless_core_init(bcm); + if (err) + goto err_80211_unwind; + + if (i != 0) { + bcm43xx_mac_suspend(bcm); + bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + bcm43xx_radio_turn_off(bcm); + } + } + bcm->active_80211_core = &bcm->core_80211[0]; + if (num_80211_cores >= 2) { + bcm43xx_switch_core(bcm, &bcm->core_80211[0]); + bcm43xx_mac_enable(bcm); + } + bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); + bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); + dprintk(KERN_INFO PFX "80211 cores initialized\n"); + bcm43xx_security_init(bcm); + bcm43xx_softmac_init(bcm); + + bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); + + spin_lock_irqsave(&bcm->lock, flags); + bcm->initialized = 1; + spin_unlock_irqrestore(&bcm->lock, flags); + + if (bcm->current_core->radio->initial_channel != 0xFF) { + bcm43xx_mac_suspend(bcm); + bcm43xx_radio_selectchannel(bcm, bcm->current_core->radio->initial_channel, 0); + bcm43xx_mac_enable(bcm); + } + bcm43xx_periodic_tasks_setup(bcm); + + assert(err == 0); +out: + return err; + +err_80211_unwind: + tasklet_disable(&bcm->isr_tasklet); + /* unwind all 80211 initialization */ + for (i = 0; i < num_80211_cores; i++) { + if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_INITIALIZED)) + continue; + bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + bcm43xx_wireless_core_cleanup(bcm); + } +err_crystal_off: + bcm43xx_pctl_set_crystal(bcm, 0); + goto out; +} + +static void bcm43xx_detach_board(struct bcm43xx_private *bcm) +{ + struct pci_dev *pci_dev = bcm->pci_dev; + int i; + + bcm43xx_chipset_detach(bcm); + /* Do _not_ access the chip, after it is detached. */ + iounmap(bcm->mmio_addr); + + pci_release_regions(pci_dev); + pci_disable_device(pci_dev); + + /* Free allocated structures/fields */ + for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { + kfree(bcm->phy[i]._lo_pairs); + if (bcm->phy[i].dyn_tssi_tbl) + kfree(bcm->phy[i].tssi2dbm); + } +} + +static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) +{ + u16 value; + u8 phy_version; + u8 phy_type; + u8 phy_rev; + int phy_rev_ok = 1; + void *p; + + value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); + + phy_version = (value & 0xF000) >> 12; + phy_type = (value & 0x0F00) >> 8; + phy_rev = (value & 0x000F); + + dprintk(KERN_INFO PFX "Detected PHY: Version: %x, Type %x, Revision %x\n", + phy_version, phy_type, phy_rev); + + switch (phy_type) { + case BCM43xx_PHYTYPE_A: + if (phy_rev >= 4) + phy_rev_ok = 0; + /*FIXME: We need to switch the ieee->modulation, etc.. flags, + * if we switch 80211 cores after init is done. + * As we do not implement on the fly switching between + * wireless cores, I will leave this as a future task. + */ + bcm->ieee->modulation = IEEE80211_OFDM_MODULATION; + bcm->ieee->mode = IEEE_A; + bcm->ieee->freq_band = IEEE80211_52GHZ_BAND | + IEEE80211_24GHZ_BAND; + break; + case BCM43xx_PHYTYPE_B: + if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7) + phy_rev_ok = 0; + bcm->ieee->modulation = IEEE80211_CCK_MODULATION; + bcm->ieee->mode = IEEE_B; + bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; + break; + case BCM43xx_PHYTYPE_G: + if (phy_rev > 7) + phy_rev_ok = 0; + bcm->ieee->modulation = IEEE80211_OFDM_MODULATION | + IEEE80211_CCK_MODULATION; + bcm->ieee->mode = IEEE_G; + bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; + break; + default: + printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n", + phy_type); + return -ENODEV; + }; + if (!phy_rev_ok) { + printk(KERN_WARNING PFX "Invalid PHY Revision %x\n", + phy_rev); + } + + bcm->current_core->phy->version = phy_version; + bcm->current_core->phy->type = phy_type; + bcm->current_core->phy->rev = phy_rev; + if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) { + p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT, + GFP_KERNEL); + if (!p) + return -ENOMEM; + bcm->current_core->phy->_lo_pairs = p; + } + + return 0; +} + +static int bcm43xx_attach_board(struct bcm43xx_private *bcm) +{ + struct pci_dev *pci_dev = bcm->pci_dev; + struct net_device *net_dev = bcm->net_dev; + int err; + int i; + void __iomem *ioaddr; + unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; + int num_80211_cores; + u32 coremask; + + err = pci_enable_device(pci_dev); + if (err) { + printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err); + err = -ENODEV; + goto out; + } + + mmio_start = pci_resource_start(pci_dev, 0); + mmio_end = pci_resource_end(pci_dev, 0); + mmio_flags = pci_resource_flags(pci_dev, 0); + mmio_len = pci_resource_len(pci_dev, 0); + + /* make sure PCI base addr is MMIO */ + if (!(mmio_flags & IORESOURCE_MEM)) { + printk(KERN_ERR PFX + "%s, region #0 not an MMIO resource, aborting\n", + pci_name(pci_dev)); + err = -ENODEV; + goto err_pci_disable; + } +//FIXME: Why is this check disabled for BCM947XX? What is the IO_SIZE there? +#ifndef CONFIG_BCM947XX + if (mmio_len != BCM43xx_IO_SIZE) { + printk(KERN_ERR PFX + "%s: invalid PCI mem region size(s), aborting\n", + pci_name(pci_dev)); + err = -ENODEV; + goto err_pci_disable; + } +#endif + + err = pci_request_regions(pci_dev, DRV_NAME); + if (err) { + printk(KERN_ERR PFX + "could not access PCI resources (%i)\n", err); + goto err_pci_disable; + } + + /* enable PCI bus-mastering */ + pci_set_master(pci_dev); + + /* ioremap MMIO region */ + ioaddr = ioremap(mmio_start, mmio_len); + if (!ioaddr) { + printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", + pci_name(pci_dev)); + err = -EIO; + goto err_pci_release; + } + + net_dev->base_addr = (unsigned long)ioaddr; + bcm->mmio_addr = ioaddr; + bcm->mmio_len = mmio_len; + + bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID, + &bcm->board_vendor); + bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID, + &bcm->board_type); + bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID, + &bcm->board_revision); + + err = bcm43xx_chipset_attach(bcm); + if (err) + goto err_iounmap; + err = bcm43xx_pctl_init(bcm); + if (err) + goto err_chipset_detach; + err = bcm43xx_probe_cores(bcm); + if (err) + goto err_chipset_detach; + + num_80211_cores = bcm43xx_num_80211_cores(bcm); + + /* Attach all IO cores to the backplane. */ + coremask = 0; + for (i = 0; i < num_80211_cores; i++) + coremask |= (1 << bcm->core_80211[i].index); + //FIXME: Also attach some non80211 cores? + err = bcm43xx_setup_backplane_pci_connection(bcm, coremask); + if (err) { + printk(KERN_ERR PFX "Backplane->PCI connection failed!\n"); + goto err_chipset_detach; + } + + err = bcm43xx_read_sprom(bcm); + if (err) + goto err_chipset_detach; + err = bcm43xx_leds_init(bcm); + if (err) + goto err_chipset_detach; + + for (i = 0; i < num_80211_cores; i++) { + err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); + assert(err != -ENODEV); + if (err) + goto err_80211_unwind; + + /* Enable the selected wireless core. + * Connect PHY only on the first core. + */ + bcm43xx_wireless_core_reset(bcm, (i == 0)); + + err = bcm43xx_read_phyinfo(bcm); + if (err && (i == 0)) + goto err_80211_unwind; + + err = bcm43xx_read_radioinfo(bcm); + if (err && (i == 0)) + goto err_80211_unwind; + + err = bcm43xx_validate_chip(bcm); + if (err && (i == 0)) + goto err_80211_unwind; + + bcm43xx_radio_turn_off(bcm); + err = bcm43xx_phy_init_tssi2dbm_table(bcm); + if (err) + goto err_80211_unwind; + bcm43xx_wireless_core_disable(bcm); + } + bcm43xx_pctl_set_crystal(bcm, 0); + + /* Set the MAC address in the networking subsystem */ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6); + else + memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6); + + bcm43xx_geo_init(bcm); + + snprintf(bcm->nick, IW_ESSID_MAX_SIZE, + "Broadcom %04X", bcm->chip_id); + + assert(err == 0); +out: + return err; + +err_80211_unwind: + for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { + kfree(bcm->phy[i]._lo_pairs); + if (bcm->phy[i].dyn_tssi_tbl) + kfree(bcm->phy[i].tssi2dbm); + } +err_chipset_detach: + bcm43xx_chipset_detach(bcm); +err_iounmap: + iounmap(bcm->mmio_addr); +err_pci_release: + pci_release_regions(pci_dev); +err_pci_disable: + pci_disable_device(pci_dev); + goto out; +} + +static inline +s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, u8 in_rssi, + int ofdm, int adjust_2053, int adjust_2050) +{ + s32 tmp; + + switch (bcm->current_core->radio->version) { + case 0x2050: + if (ofdm) { + tmp = in_rssi; + if (tmp > 127) + tmp -= 256; + tmp *= 73; + tmp /= 64; + if (adjust_2050) + tmp += 25; + else + tmp -= 3; + } else { + if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { + if (in_rssi > 63) + in_rssi = 63; + tmp = bcm->current_core->radio->nrssi_lt[in_rssi]; + tmp = 31 - tmp; + tmp *= -131; + tmp /= 128; + tmp -= 57; + } else { + tmp = in_rssi; + tmp = 31 - tmp; + tmp *= -149; + tmp /= 128; + tmp -= 68; + } + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && + adjust_2050) + tmp += 25; + } + break; + case 0x2060: + if (in_rssi > 127) + tmp = in_rssi - 256; + else + tmp = in_rssi; + break; + default: + tmp = in_rssi; + tmp -= 11; + tmp *= 103; + tmp /= 64; + if (adjust_2053) + tmp -= 109; + else + tmp -= 83; + } + + return (s8)tmp; +} + +static inline +s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, u8 in_rssi) +{ + s8 ret; + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + //TODO: Incomplete specs. + ret = 0; + } else + ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1); + + return ret; +} + +static inline +int bcm43xx_rx_packet(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct ieee80211_rx_stats *stats) +{ + int err; + + err = ieee80211_rx(bcm->ieee, skb, stats); + if (unlikely(err == 0)) + return -EINVAL; + return 0; +} + +int fastcall bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr) +{ + struct bcm43xx_plcp_hdr4 *plcp; + struct ieee80211_rx_stats stats; + struct ieee80211_hdr_4addr *wlhdr; + u16 frame_ctl; + int is_packet_for_us = 0; + int err = -EINVAL; + const u16 rxflags1 = le16_to_cpu(rxhdr->flags1); + const u16 rxflags2 = le16_to_cpu(rxhdr->flags2); + const u16 rxflags3 = le16_to_cpu(rxhdr->flags3); + const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM); + + if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) { + plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2); + /* Skip two unknown bytes and the PLCP header. */ + skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6)); + } else { + plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data); + /* Skip the PLCP header. */ + skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6)); + } + /* The SKB contains the PAYLOAD (wireless header + data) + * at this point. The FCS at the end is stripped. + */ + + memset(&stats, 0, sizeof(stats)); + stats.mac_time = le16_to_cpu(rxhdr->mactime); + stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, + !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), + !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); + stats.signal = rxhdr->signal_quality; //FIXME +//TODO stats.noise = + stats.rate = bcm43xx_plcp_get_bitrate(plcp, is_ofdm); +//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate); + stats.received_channel = bcm->current_core->radio->channel; +//TODO stats.control = + stats.mask = IEEE80211_STATMASK_SIGNAL | +//TODO IEEE80211_STATMASK_NOISE | + IEEE80211_STATMASK_RATE | + IEEE80211_STATMASK_RSSI; + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + stats.freq = IEEE80211_52GHZ_BAND; + else + stats.freq = IEEE80211_24GHZ_BAND; + stats.len = skb->len; + + bcm->stats.last_rx = jiffies; + if (bcm->ieee->iw_mode == IW_MODE_MONITOR) + return bcm43xx_rx_packet(bcm, skb, &stats); + + wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); + + switch (bcm->ieee->iw_mode) { + case IW_MODE_ADHOC: + if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || + memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || + is_broadcast_ether_addr(wlhdr->addr1) || + is_multicast_ether_addr(wlhdr->addr1) || + bcm->net_dev->flags & IFF_PROMISC) + is_packet_for_us = 1; + break; + case IW_MODE_INFRA: + default: + /* When receiving multicast or broadcast packets, filter out + the packets we send ourself; we shouldn't see those */ + if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || + memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || + (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) && + (is_broadcast_ether_addr(wlhdr->addr1) || + is_multicast_ether_addr(wlhdr->addr1) || + bcm->net_dev->flags & IFF_PROMISC))) + is_packet_for_us = 1; + break; + } + + frame_ctl = le16_to_cpu(wlhdr->frame_ctl); + + if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { + frame_ctl &= ~IEEE80211_FCTL_PROTECTED; + wlhdr->frame_ctl = cpu_to_le16(frame_ctl); + /* trim IV and ICV */ + /* FIXME: this must be done only for WEP encrypted packets */ + if (skb->len < 32) { + dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag " + "set and length < 32)\n"); + return -EINVAL; + } else { + memmove(skb->data + 4, skb->data, 24); + skb_pull(skb, 4); + skb_trim(skb, skb->len - 4); + stats.len -= 8; + } + /* do _not_ use wlhdr again without reassigning it */ + } + + switch (WLAN_FC_GET_TYPE(frame_ctl)) { + case IEEE80211_FTYPE_MGMT: + ieee80211_rx_mgt(bcm->ieee, skb->data, &stats); + break; + case IEEE80211_FTYPE_DATA: + if (is_packet_for_us) + err = bcm43xx_rx_packet(bcm, skb, &stats); + break; + case IEEE80211_FTYPE_CTL: + break; + default: + assert(0); + return -EINVAL; + } + + return err; +} + +/* Do the Hardware IO operations to send the txb */ +static inline int bcm43xx_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) +{ + int err = -ENODEV; + + if (bcm->pio_mode) + err = bcm43xx_pio_transfer_txb(bcm, txb); + else + err = bcm43xx_dma_transfer_txb(bcm, txb); + + return err; +} + +static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, + u8 channel) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_mac_suspend(bcm); + bcm43xx_radio_selectchannel(bcm, channel, 0); + bcm43xx_mac_enable(bcm); + spin_unlock_irqrestore(&bcm->lock, flags); +} + +/* set_security() callback in struct ieee80211_device */ +static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, + struct ieee80211_security *sec) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct ieee80211_security *secinfo = &bcm->ieee->sec; + unsigned long flags; + int keyidx; + + dprintk(KERN_INFO PFX "set security called\n"); + + spin_lock_irqsave(&bcm->lock, flags); + + for (keyidx = 0; keyidxflags & (1<encode_alg[keyidx] = sec->encode_alg[keyidx]; + secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx]; + memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN); + } + + if (sec->flags & SEC_ACTIVE_KEY) { + secinfo->active_key = sec->active_key; + dprintk(KERN_INFO PFX " .active_key = %d\n", sec->active_key); + } + if (sec->flags & SEC_UNICAST_GROUP) { + secinfo->unicast_uses_group = sec->unicast_uses_group; + dprintk(KERN_INFO PFX " .unicast_uses_group = %d\n", sec->unicast_uses_group); + } + if (sec->flags & SEC_LEVEL) { + secinfo->level = sec->level; + dprintk(KERN_INFO PFX " .level = %d\n", sec->level); + } + if (sec->flags & SEC_ENABLED) { + secinfo->enabled = sec->enabled; + dprintk(KERN_INFO PFX " .enabled = %d\n", sec->enabled); + } + if (sec->flags & SEC_ENCRYPT) { + secinfo->encrypt = sec->encrypt; + dprintk(KERN_INFO PFX " .encrypt = %d\n", sec->encrypt); + } + if (bcm->initialized && !bcm->ieee->host_encrypt) { + if (secinfo->enabled) { + /* upload WEP keys to hardware */ + char null_address[6] = { 0 }; + u8 algorithm = 0; + for (keyidx = 0; keyidxflags & (1<encode_alg[keyidx]) { + case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break; + case SEC_ALG_WEP: + algorithm = BCM43xx_SEC_ALGO_WEP; + if (secinfo->key_sizes[keyidx] == 13) + algorithm = BCM43xx_SEC_ALGO_WEP104; + break; + case SEC_ALG_TKIP: + FIXME(); + algorithm = BCM43xx_SEC_ALGO_TKIP; + break; + case SEC_ALG_CCMP: + FIXME(); + algorithm = BCM43xx_SEC_ALGO_AES; + break; + default: + assert(0); + break; + } + bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]); + bcm->key[keyidx].enabled = 1; + bcm->key[keyidx].algorithm = algorithm; + } + } else + bcm43xx_clear_keys(bcm); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +/* hard_start_xmit() callback in struct ieee80211_device */ +static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, + struct net_device *net_dev, + int pri) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err = -ENODEV; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + if (likely(bcm->initialized)) + err = bcm43xx_tx(bcm, txb); + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev) +{ + return &(bcm43xx_priv(net_dev)->ieee->stats); +} + +static void bcm43xx_net_tx_timeout(struct net_device *net_dev) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + + bcm43xx_controller_restart(bcm, "TX timeout"); +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void bcm43xx_net_poll_controller(struct net_device *net_dev) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + local_irq_save(flags); + bcm43xx_interrupt_handler(bcm->irq, bcm, NULL); + local_irq_restore(flags); +} +#endif /* CONFIG_NET_POLL_CONTROLLER */ + +static int bcm43xx_net_open(struct net_device *net_dev) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + + return bcm43xx_init_board(bcm); +} + +static int bcm43xx_net_stop(struct net_device *net_dev) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + + ieee80211softmac_stop(net_dev); + bcm43xx_disable_interrupts_sync(bcm, NULL); + bcm43xx_free_board(bcm); + + return 0; +} + +static void bcm43xx_init_private(struct bcm43xx_private *bcm, + struct net_device *net_dev, + struct pci_dev *pci_dev, + struct workqueue_struct *wq) +{ + bcm->ieee = netdev_priv(net_dev); + bcm->softmac = ieee80211_priv(net_dev); + bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; + bcm->workqueue = wq; + +#ifdef DEBUG_ENABLE_MMIO_PRINT + bcm43xx_mmioprint_initial(bcm, 1); +#else + bcm43xx_mmioprint_initial(bcm, 0); +#endif +#ifdef DEBUG_ENABLE_PCILOG + bcm43xx_pciprint_initial(bcm, 1); +#else + bcm43xx_pciprint_initial(bcm, 0); +#endif + + bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; + bcm->pci_dev = pci_dev; + bcm->net_dev = net_dev; + if (modparam_bad_frames_preempt) + bcm->bad_frames_preempt = 1; + spin_lock_init(&bcm->lock); + tasklet_init(&bcm->isr_tasklet, + (void (*)(unsigned long))bcm43xx_interrupt_tasklet, + (unsigned long)bcm); + tasklet_disable_nosync(&bcm->isr_tasklet); + if (modparam_pio) { + bcm->pio_mode = 1; + } else { + if (pci_set_dma_mask(pci_dev, DMA_30BIT_MASK) == 0) { + bcm->pio_mode = 0; + } else { + printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n"); + bcm->pio_mode = 1; + } + } + bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; + + /* default to sw encryption for now */ + bcm->ieee->host_build_iv = 0; + bcm->ieee->host_encrypt = 1; + bcm->ieee->host_decrypt = 1; + + bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE; + bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr); + bcm->ieee->set_security = bcm43xx_ieee80211_set_security; + bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit; +} + +static int __devinit bcm43xx_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *net_dev; + struct bcm43xx_private *bcm; + struct workqueue_struct *wq; + int err; + +#ifdef CONFIG_BCM947XX + if ((pdev->bus->number == 0) && (pdev->device != 0x0800)) + return -ENODEV; +#endif + +#ifdef DEBUG_SINGLE_DEVICE_ONLY + if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY)) + return -ENODEV; +#endif + + net_dev = alloc_ieee80211softmac(sizeof(*bcm)); + if (!net_dev) { + printk(KERN_ERR PFX + "could not allocate ieee80211 device %s\n", + pci_name(pdev)); + err = -ENOMEM; + goto out; + } + /* initialize the net_device struct */ + SET_MODULE_OWNER(net_dev); + SET_NETDEV_DEV(net_dev, &pdev->dev); + + net_dev->open = bcm43xx_net_open; + net_dev->stop = bcm43xx_net_stop; + net_dev->get_stats = bcm43xx_net_get_stats; + net_dev->tx_timeout = bcm43xx_net_tx_timeout; +#ifdef CONFIG_NET_POLL_CONTROLLER + net_dev->poll_controller = bcm43xx_net_poll_controller; +#endif + net_dev->wireless_handlers = &bcm43xx_wx_handlers_def; + net_dev->irq = pdev->irq; + net_dev->watchdog_timeo = BCM43xx_TX_TIMEOUT; + + /* initialize the bcm43xx_private struct */ + bcm = bcm43xx_priv(net_dev); + memset(bcm, 0, sizeof(*bcm)); + wq = create_workqueue(DRV_NAME "_wq"); + if (!wq) { + err = -ENOMEM; + goto err_free_netdev; + } + bcm43xx_init_private(bcm, net_dev, pdev, wq); + + pci_set_drvdata(pdev, net_dev); + + err = bcm43xx_attach_board(bcm); + if (err) + goto err_destroy_wq; + + err = register_netdev(net_dev); + if (err) { + printk(KERN_ERR PFX "Cannot register net device, " + "aborting.\n"); + err = -ENOMEM; + goto err_detach_board; + } + + bcm43xx_debugfs_add_device(bcm); + + assert(err == 0); +out: + return err; + +err_detach_board: + bcm43xx_detach_board(bcm); +err_destroy_wq: + destroy_workqueue(wq); +err_free_netdev: + free_ieee80211softmac(net_dev); + goto out; +} + +static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) +{ + struct net_device *net_dev = pci_get_drvdata(pdev); + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + + bcm43xx_debugfs_remove_device(bcm); + unregister_netdev(net_dev); + bcm43xx_detach_board(bcm); + assert(bcm->ucode == NULL); + destroy_workqueue(bcm->workqueue); + free_ieee80211softmac(net_dev); +} + +/* Hard-reset the chip. Do not call this directly. + * Use bcm43xx_controller_restart() + */ +static void bcm43xx_chip_reset(void *_bcm) +{ + struct bcm43xx_private *bcm = _bcm; + struct net_device *net_dev = bcm->net_dev; + struct pci_dev *pci_dev = bcm->pci_dev; + struct workqueue_struct *wq = bcm->workqueue; + int err; + int was_initialized = bcm->initialized; + + netif_stop_queue(bcm->net_dev); + tasklet_disable(&bcm->isr_tasklet); + + bcm->firmware_norelease = 1; + if (was_initialized) + bcm43xx_free_board(bcm); + bcm->firmware_norelease = 0; + bcm43xx_detach_board(bcm); + bcm43xx_init_private(bcm, net_dev, pci_dev, wq); + err = bcm43xx_attach_board(bcm); + if (err) + goto failure; + if (was_initialized) { + err = bcm43xx_init_board(bcm); + if (err) + goto failure; + } + netif_wake_queue(bcm->net_dev); + printk(KERN_INFO PFX "Controller restarted\n"); + + return; +failure: + printk(KERN_ERR PFX "Controller restart failed\n"); +} + +/* Hard-reset the chip. + * This can be called from interrupt or process context. + * Make sure to _not_ re-enable device interrupts after this has been called. +*/ +void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) +{ + bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); + INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); + queue_work(bcm->workqueue, &bcm->restart_work); +} + +#ifdef CONFIG_PM + +static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *net_dev = pci_get_drvdata(pdev); + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int try_to_shutdown = 0, err; + + dprintk(KERN_INFO PFX "Suspending...\n"); + + spin_lock_irqsave(&bcm->lock, flags); + bcm->was_initialized = bcm->initialized; + if (bcm->initialized) + try_to_shutdown = 1; + spin_unlock_irqrestore(&bcm->lock, flags); + + netif_device_detach(net_dev); + if (try_to_shutdown) { + ieee80211softmac_stop(net_dev); + err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate); + if (unlikely(err)) { + dprintk(KERN_ERR PFX "Suspend failed.\n"); + return -EAGAIN; + } + bcm->firmware_norelease = 1; + bcm43xx_free_board(bcm); + bcm->firmware_norelease = 0; + } + bcm43xx_chipset_detach(bcm); + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + dprintk(KERN_INFO PFX "Device suspended.\n"); + + return 0; +} + +static int bcm43xx_resume(struct pci_dev *pdev) +{ + struct net_device *net_dev = pci_get_drvdata(pdev); + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err = 0; + + dprintk(KERN_INFO PFX "Resuming...\n"); + + pci_set_power_state(pdev, 0); + pci_enable_device(pdev); + pci_restore_state(pdev); + + bcm43xx_chipset_attach(bcm); + if (bcm->was_initialized) { + bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; + err = bcm43xx_init_board(bcm); + } + if (err) { + printk(KERN_ERR PFX "Resume failed!\n"); + return err; + } + + netif_device_attach(net_dev); + + /*FIXME: This should be handled by softmac instead. */ + schedule_work(&bcm->softmac->associnfo.work); + + dprintk(KERN_INFO PFX "Device resumed.\n"); + + return 0; +} + +#endif /* CONFIG_PM */ + +static struct pci_driver bcm43xx_pci_driver = { + .name = BCM43xx_DRIVER_NAME, + .id_table = bcm43xx_pci_tbl, + .probe = bcm43xx_init_one, + .remove = __devexit_p(bcm43xx_remove_one), +#ifdef CONFIG_PM + .suspend = bcm43xx_suspend, + .resume = bcm43xx_resume, +#endif /* CONFIG_PM */ +}; + +static int __init bcm43xx_init(void) +{ + printk(KERN_INFO BCM43xx_DRIVER_NAME "\n"); + bcm43xx_debugfs_init(); + return pci_register_driver(&bcm43xx_pci_driver); +} + +static void __exit bcm43xx_exit(void) +{ + pci_unregister_driver(&bcm43xx_pci_driver); + bcm43xx_debugfs_exit(); +} + +module_init(bcm43xx_init) +module_exit(bcm43xx_exit) + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h new file mode 100644 index 000000000000..1d3eddd314bc --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -0,0 +1,283 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef BCM43xx_MAIN_H_ +#define BCM43xx_MAIN_H_ + +#include "bcm43xx.h" + +#ifdef CONFIG_BCM947XX +#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0) + +static inline void e_aton(char *str, char *dest) +{ + int i = 0; + u16 *d = (u16 *) dest; + + for (;;) { + dest[i++] = (char) simple_strtoul(str, NULL, 16); + str += 2; + if (!*str++ || i == 6) + break; + } + for (i = 0; i < 3; i++) + d[i] = cpu_to_be16(d[i]); +} +#endif + + +#define _bcm43xx_declare_plcp_hdr(size) \ + struct bcm43xx_plcp_hdr##size { \ + union { \ + __le32 data; \ + __u8 raw[size]; \ + } __attribute__((__packed__)); \ + } __attribute__((__packed__)) + +/* struct bcm43xx_plcp_hdr4 */ +_bcm43xx_declare_plcp_hdr(4); +/* struct bcm430c_plcp_hdr6 */ +_bcm43xx_declare_plcp_hdr(6); + +#undef _bcm43xx_declare_plcp_hdr + + +#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] +#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) +/* Magic helper macro to pad structures. Ignore those above. It's magic. */ +#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) + + +/* Device specific TX header. To be prepended to TX frames. */ +struct bcm43xx_txhdr { + union { + struct { + u16 flags; + u16 wsec_rate; + u16 frame_control; + u16 unknown_zeroed_0; + u16 control; + unsigned char wep_iv[10]; + unsigned char unknown_wsec_tkip_data[3]; //FIXME + PAD_BYTES(3); + unsigned char mac1[6]; + u16 unknown_zeroed_1; + struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp; + u16 rts_cts_dur_fallback; + struct bcm43xx_plcp_hdr4 fallback_plcp; + u16 fallback_dur_id; + PAD_BYTES(2); + u16 cookie; + u16 unknown_scb_stuff; //FIXME + struct bcm43xx_plcp_hdr6 rts_cts_plcp; + u16 rts_cts_frame_type; + u16 rts_cts_dur; + unsigned char rts_cts_mac1[6]; + unsigned char rts_cts_mac2[6]; + PAD_BYTES(2); + struct bcm43xx_plcp_hdr6 plcp; + } __attribute__((__packed__)); + + unsigned char raw[82]; + } __attribute__((__packed__)); +} __attribute__((__packed__)); + +struct sk_buff; + +void FASTCALL(bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + const unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie)); + +/* RX header as received from the hardware. */ +struct bcm43xx_rxhdr { + /* Frame Length. Must be generated explicitely in PIO mode. */ + __le16 frame_length; + PAD_BYTES(2); + /* Flags field 1 */ + __le16 flags1; + u8 rssi; + u8 signal_quality; + PAD_BYTES(2); + /* Flags field 3 */ + __le16 flags3; + /* Flags field 2 */ + __le16 flags2; + /* Lower 16bits of the TSF at the time the frame started. */ + __le16 mactime; + PAD_BYTES(14); +} __attribute__((__packed__)); + +#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0) +/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */ +#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7) +#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14) + +#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0) +#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2) +/*FIXME: WEP related flags */ + +#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10) + +/* Transmit Status as received from the hardware. */ +struct bcm43xx_hwxmitstatus { + PAD_BYTES(4); + __le16 cookie; + u8 flags; + u8 cnt1:4, + cnt2:4; + PAD_BYTES(2); + __le16 seq; + __le16 unknown; //FIXME +} __attribute__((__packed__)); + +/* Transmit Status in CPU byteorder. */ +struct bcm43xx_xmitstatus { + u16 cookie; + u8 flags; + u8 cnt1:4, + cnt2:4; + u16 seq; + u16 unknown; //FIXME +}; + +#define BCM43xx_TXSTAT_FLAG_ACK 0x01 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x02 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x04 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x08 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x10 +#define BCM43xx_TXSTAT_FLAG_IGNORE 0x20 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80 + +struct bcm43xx_xmitstatus_queue { + struct list_head list; + struct bcm43xx_hwxmitstatus status; +}; + + +/* Lightweight function to convert a frequency (in Mhz) to a channel number. */ +static inline +u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm, + int freq) +{ + u8 channel; + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + channel = (freq - 5000) / 5; + } else { + if (freq == 2484) + channel = 14; + else + channel = (freq - 2407) / 5; + } + + return channel; +} + +/* Lightweight function to convert a channel number to a frequency (in Mhz). */ +static inline +int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm, + u8 channel) +{ + int freq; + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + freq = 5000 + (5 * channel); + } else { + if (channel == 14) + freq = 2484; + else + freq = 2407 + (5 * channel); + } + + return freq; +} + +/* Lightweight function to check if a channel number is valid. + * Note that this does _NOT_ check for geographical restrictions! + */ +static inline +int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, + u8 channel) +{ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + if (channel <= 200) + return 1; + } else { + if (channel >= 1 && channel <= 14) + return 1; + } + + return 0; +} + +void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); +void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf); + +int FASTCALL(bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr)); + +void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, + int iw_mode); + +u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm, + u16 routing, u16 offset); +u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm, + u16 routing, u16 offset); +void bcm43xx_shm_write32(struct bcm43xx_private *bcm, + u16 routing, u16 offset, + u32 value); +void bcm43xx_shm_write16(struct bcm43xx_private *bcm, + u16 routing, u16 offset, + u16 value); + +void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm); + +int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core); + +void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); + +int bcm43xx_pci_read_config_16(struct pci_dev *pdev, u16 offset, u16 *val); +int bcm43xx_pci_read_config_32(struct pci_dev *pdev, u16 offset, u32 *val); +int bcm43xx_pci_write_config_16(struct pci_dev *pdev, int offset, u16 val); +int bcm43xx_pci_write_config_32(struct pci_dev *pdev, int offset, u32 val); + +void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); +void bcm43xx_mac_enable(struct bcm43xx_private *bcm); + +u8 bcm43xx_sprom_crc(const u16 *sprom); + +void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); + +#endif /* BCM43xx_MAIN_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c new file mode 100644 index 000000000000..41b9cd7fc9e2 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -0,0 +1,2122 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include + +#include "bcm43xx.h" +#include "bcm43xx_phy.h" +#include "bcm43xx_main.h" +#include "bcm43xx_radio.h" +#include "bcm43xx_ilt.h" +#include "bcm43xx_power.h" + + +static const s8 bcm43xx_tssi2dbm_b_table[] = { + 0x4D, 0x4C, 0x4B, 0x4A, + 0x4A, 0x49, 0x48, 0x47, + 0x47, 0x46, 0x45, 0x45, + 0x44, 0x43, 0x42, 0x42, + 0x41, 0x40, 0x3F, 0x3E, + 0x3D, 0x3C, 0x3B, 0x3A, + 0x39, 0x38, 0x37, 0x36, + 0x35, 0x34, 0x32, 0x31, + 0x30, 0x2F, 0x2D, 0x2C, + 0x2B, 0x29, 0x28, 0x26, + 0x25, 0x23, 0x21, 0x1F, + 0x1D, 0x1A, 0x17, 0x14, + 0x10, 0x0C, 0x06, 0x00, + -7, -7, -7, -7, + -7, -7, -7, -7, + -7, -7, -7, -7, +}; + +static const s8 bcm43xx_tssi2dbm_g_table[] = { + 77, 77, 77, 76, + 76, 76, 75, 75, + 74, 74, 73, 73, + 73, 72, 72, 71, + 71, 70, 70, 69, + 68, 68, 67, 67, + 66, 65, 65, 64, + 63, 63, 62, 61, + 60, 59, 58, 57, + 56, 55, 54, 53, + 52, 50, 49, 47, + 45, 43, 40, 37, + 33, 28, 22, 14, + 5, -7, -20, -20, + -20, -20, -20, -20, + -20, -20, -20, -20, +}; + +static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); + + +void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + + assert(irqs_disabled()); + if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) { + phy->is_locked = 0; + return; + } + if (bcm->current_core->rev < 3) { + bcm43xx_mac_suspend(bcm); + spin_lock(&phy->lock); + } else { + if (bcm->ieee->iw_mode != IW_MODE_MASTER) + bcm43xx_power_saving_ctl_bits(bcm, -1, 1); + } + phy->is_locked = 1; +} + +void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + + assert(irqs_disabled()); + if (bcm->current_core->rev < 3) { + if (phy->is_locked) { + spin_unlock(&phy->lock); + bcm43xx_mac_enable(bcm); + } + } else { + if (bcm->ieee->iw_mode != IW_MODE_MASTER) + bcm43xx_power_saving_ctl_bits(bcm, -1, -1); + } + phy->is_locked = 0; +} + +u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset) +{ + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset); + return bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_DATA); +} + +void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val) +{ + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset); + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val); +} + +void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + unsigned long flags; + + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ + if (phy->calibrated) + return; + if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) { + /* We do not want to be preempted while calibrating + * the hardware. + */ + local_irq_save(flags); + + bcm43xx_wireless_core_reset(bcm, 0); + bcm43xx_phy_initg(bcm); + bcm43xx_wireless_core_reset(bcm, 1); + + local_irq_restore(flags); + } + phy->calibrated = 1; +} + +/* Connect the PHY + * http://bcm-specs.sipsolutions.net/SetPHY + */ +int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect) +{ + u32 flags; + + if (bcm->current_core->rev < 5) { + if (connect) { + bcm->current_core->phy->connected = 1; + dprintk(KERN_INFO PFX "PHY connected\n"); + } else { + bcm->current_core->phy->connected = 0; + dprintk(KERN_INFO PFX "PHY disconnected\n"); + } + return 0; + } + + flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); + if (connect) { + if (!(flags & 0x00010000)) + return -ENODEV; + bcm->current_core->phy->connected = 1; + + flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + flags |= (0x800 << 18); + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); + dprintk(KERN_INFO PFX "PHY connected\n"); + } else { + if (!(flags & 0x00020000)) + return -ENODEV; + bcm->current_core->phy->connected = 0; + + flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + flags &= ~(0x800 << 18); + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); + dprintk(KERN_INFO PFX "PHY disconnected\n"); + } + + return 0; +} + +/* intialize B PHY power control + * as described in http://bcm-specs.sipsolutions.net/InitPowerControl + */ +static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0; + int must_reset_txpower = 0; + + assert(phy->type != BCM43xx_PHYTYPE_A); + if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && + (bcm->board_type == 0x0416)) + return; + + bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF); + bcm43xx_phy_write(bcm, 0x0028, 0x8018); + + if (phy->type == BCM43xx_PHYTYPE_G) { + if (!phy->connected) + return; + bcm43xx_phy_write(bcm, 0x047A, 0xC111); + } + if (phy->savedpctlreg != 0xFFFF) + return; + + if (phy->type == BCM43xx_PHYTYPE_B && + phy->rev >= 2 && + radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x0076, + bcm43xx_radio_read16(bcm, 0x0076) | 0x0084); + } else { + saved_batt = radio->txpower[0]; + saved_ratt = radio->txpower[1]; + saved_txctl1 = radio->txpower[2]; + if ((radio->revision >= 6) && (radio->revision <= 8) + && /*FIXME: incomplete specs for 5 < revision < 9 */ 0) + bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0); + else + bcm43xx_radio_set_txpower_bg(bcm, 0xB, 9, 0); + must_reset_txpower = 1; + } + bcm43xx_dummy_transmission(bcm); + + phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_PCTL); + + if (must_reset_txpower) + bcm43xx_radio_set_txpower_bg(bcm, saved_batt, saved_ratt, saved_txctl1); + else + bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) & 0xFF7B); + bcm43xx_radio_clear_tssi(bcm); +} + +static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 offset = 0x0000; + + if (phy->rev == 1) + offset = 0x4C00; + + bcm43xx_ilt_write16(bcm, offset, 0x00FE); + bcm43xx_ilt_write16(bcm, offset + 1, 0x000D); + bcm43xx_ilt_write16(bcm, offset + 2, 0x0013); + bcm43xx_ilt_write16(bcm, offset + 3, 0x0019); + + if (phy->rev == 1) { + bcm43xx_ilt_write16(bcm, 0x1800, 0x2710); + bcm43xx_ilt_write16(bcm, 0x1801, 0x9B83); + bcm43xx_ilt_write16(bcm, 0x1802, 0x9B83); + bcm43xx_ilt_write16(bcm, 0x1803, 0x0F8D); + bcm43xx_phy_write(bcm, 0x0455, 0x0004); + } + + bcm43xx_phy_write(bcm, 0x04A5, (bcm43xx_phy_read(bcm, 0x04A5) & 0x00FF) | 0x5700); + bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xFF80) | 0x000F); + bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xC07F) | 0x2B80); + bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xF0FF) | 0x0300); + + bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0008); + + bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFF0) | 0x0008); + bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xF0FF) | 0x0600); + bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0700); + bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0100); + + if (phy->rev == 1) + bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x0007); + + bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xFF00) | 0x001C); + bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xC0FF) | 0x0200); + bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0xFF00) | 0x001C); + bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xFF00) | 0x0020); + bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xC0FF) | 0x0200); + bcm43xx_phy_write(bcm, 0x0482, (bcm43xx_phy_read(bcm, 0x0482) & 0xFF00) | 0x002E); + bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0x00FF) | 0x1A00); + bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0xFF00) | 0x0028); + bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0x00FF) | 0x2C00); + + if (phy->rev == 1) { + bcm43xx_phy_write(bcm, 0x0430, 0x092B); + bcm43xx_phy_write(bcm, 0x041B, (bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1) | 0x0002); + } else { + bcm43xx_phy_write(bcm, 0x041B, bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1); + bcm43xx_phy_write(bcm, 0x041F, 0x287A); + bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0xFFF0) | 0x0004); + } + + if (phy->rev > 2) { + bcm43xx_phy_write(bcm, 0x0422, 0x287A); + bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0x0FFF) | 0x3000); + } + + bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0x8080) | 0x7874); + bcm43xx_phy_write(bcm, 0x048E, 0x1C00); + + if (phy->rev == 1) { + bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) & 0xF0FF) | 0x0600); + bcm43xx_phy_write(bcm, 0x048B, 0x005E); + bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xFF00) | 0x001E); + bcm43xx_phy_write(bcm, 0x048D, 0x0002); + } + + bcm43xx_ilt_write16(bcm, offset + 0x0800, 0); + bcm43xx_ilt_write16(bcm, offset + 0x0801, 7); + bcm43xx_ilt_write16(bcm, offset + 0x0802, 16); + bcm43xx_ilt_write16(bcm, offset + 0x0803, 28); +} + +static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 i; + + assert(phy->type == BCM43xx_PHYTYPE_G); + if (phy->rev == 1) { + bcm43xx_phy_write(bcm, 0x0406, 0x4F19); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xFC3F) | 0x0340); + bcm43xx_phy_write(bcm, 0x042C, 0x005A); + bcm43xx_phy_write(bcm, 0x0427, 0x001A); + + for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]); + for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]); + for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); + } else { + /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */ + bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654); + + if (phy->rev == 2) { + bcm43xx_phy_write(bcm, 0x04C0, 0x1861); + bcm43xx_phy_write(bcm, 0x04C1, 0x0271); + } else if (phy->rev > 2) { + bcm43xx_phy_write(bcm, 0x04C0, 0x0098); + bcm43xx_phy_write(bcm, 0x04C1, 0x0070); + bcm43xx_phy_write(bcm, 0x04C9, 0x0080); + } + bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800); + + for (i = 0; i < 64; i++) + bcm43xx_ilt_write16(bcm, 0x4000 + i, i); + for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]); + } + + if (phy->rev <= 2) + for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]); + else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200)) + for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]); + else + for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]); + + if (phy->rev == 2) + for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); + else if ((phy->rev > 2) && (phy->rev <= 7)) + for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]); + + if (phy->rev == 1) { + for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); + for (i = 0; i < 4; i++) { + bcm43xx_ilt_write16(bcm, 0x5404 + i, 0x0020); + bcm43xx_ilt_write16(bcm, 0x5408 + i, 0x0020); + bcm43xx_ilt_write16(bcm, 0x540C + i, 0x0020); + bcm43xx_ilt_write16(bcm, 0x5410 + i, 0x0020); + } + bcm43xx_phy_agcsetup(bcm); + + if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && + (bcm->board_type == 0x0416) && + (bcm->board_revision == 0x0017)) + return; + + bcm43xx_ilt_write16(bcm, 0x5001, 0x0002); + bcm43xx_ilt_write16(bcm, 0x5002, 0x0001); + } else { + for (i = 0; i <= 0x2F; i++) + bcm43xx_ilt_write16(bcm, 0x1000 + i, 0x0820); + bcm43xx_phy_agcsetup(bcm); + bcm43xx_phy_read(bcm, 0x0400); /* dummy read */ + bcm43xx_phy_write(bcm, 0x0403, 0x1000); + bcm43xx_ilt_write16(bcm, 0x3C02, 0x000F); + bcm43xx_ilt_write16(bcm, 0x3C03, 0x0014); + + if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && + (bcm->board_type == 0x0416) && + (bcm->board_revision == 0x0017)) + return; + + bcm43xx_ilt_write16(bcm, 0x0401, 0x0002); + bcm43xx_ilt_write16(bcm, 0x0402, 0x0001); + } +} + +/* Initialize the noisescaletable for APHY */ +static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + int i; + + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400); + for (i = 0; i < 12; i++) { + if (phy->rev == 2) + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767); + else + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323); + } + if (phy->rev == 2) + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6700); + else + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2300); + for (i = 0; i < 11; i++) { + if (phy->rev == 2) + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767); + else + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323); + } + if (phy->rev == 2) + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0067); + else + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0023); +} + +static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) +{ + u16 i; + + assert(bcm->current_core->phy->type == BCM43xx_PHYTYPE_A); + switch (bcm->current_core->phy->rev) { + case 2: + bcm43xx_phy_write(bcm, 0x008E, 0x3800); + bcm43xx_phy_write(bcm, 0x0035, 0x03FF); + bcm43xx_phy_write(bcm, 0x0036, 0x0400); + + bcm43xx_ilt_write16(bcm, 0x3807, 0x0051); + + bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); + bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); + bcm43xx_ilt_write16(bcm, 0x3C0C, 0x07BF); + bcm43xx_radio_write16(bcm, 0x0002, 0x07BF); + + bcm43xx_phy_write(bcm, 0x0024, 0x4680); + bcm43xx_phy_write(bcm, 0x0020, 0x0003); + bcm43xx_phy_write(bcm, 0x001D, 0x0F40); + bcm43xx_phy_write(bcm, 0x001F, 0x1C00); + + bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400); + bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF); + bcm43xx_phy_write(bcm, 0x008E, 0x58C1); + + bcm43xx_ilt_write16(bcm, 0x0803, 0x000F); + bcm43xx_ilt_write16(bcm, 0x0804, 0x001F); + bcm43xx_ilt_write16(bcm, 0x0805, 0x002A); + bcm43xx_ilt_write16(bcm, 0x0805, 0x0030); + bcm43xx_ilt_write16(bcm, 0x0807, 0x003A); + + bcm43xx_ilt_write16(bcm, 0x0000, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0001, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0002, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0003, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0004, 0x0015); + bcm43xx_ilt_write16(bcm, 0x0005, 0x0015); + bcm43xx_ilt_write16(bcm, 0x0006, 0x0019); + + bcm43xx_ilt_write16(bcm, 0x0404, 0x0003); + bcm43xx_ilt_write16(bcm, 0x0405, 0x0003); + bcm43xx_ilt_write16(bcm, 0x0406, 0x0007); + + for (i = 0; i < 16; i++) + bcm43xx_ilt_write16(bcm, 0x4000 + i, (0x8 + i) & 0x000F); + + bcm43xx_ilt_write16(bcm, 0x3003, 0x1044); + bcm43xx_ilt_write16(bcm, 0x3004, 0x7201); + bcm43xx_ilt_write16(bcm, 0x3006, 0x0040); + bcm43xx_ilt_write16(bcm, 0x3001, (bcm43xx_ilt_read16(bcm, 0x3001) & 0x0010) | 0x0008); + + for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]); + for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]); + for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); + bcm43xx_phy_init_noisescaletbl(bcm); + for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); + break; + case 3: + for (i = 0; i < 64; i++) + bcm43xx_ilt_write16(bcm, 0x4000 + i, i); + + bcm43xx_ilt_write16(bcm, 0x3807, 0x0051); + + bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); + bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); + bcm43xx_radio_write16(bcm, 0x0002, 0x07BF); + + bcm43xx_phy_write(bcm, 0x0024, 0x4680); + bcm43xx_phy_write(bcm, 0x0020, 0x0003); + bcm43xx_phy_write(bcm, 0x001D, 0x0F40); + bcm43xx_phy_write(bcm, 0x001F, 0x1C00); + bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400); + + bcm43xx_ilt_write16(bcm, 0x3001, (bcm43xx_ilt_read16(bcm, 0x3001) & 0x0010) | 0x0008); + for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]); + bcm43xx_phy_init_noisescaletbl(bcm); + for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); + + bcm43xx_phy_write(bcm, 0x0003, 0x1808); + + bcm43xx_ilt_write16(bcm, 0x0803, 0x000F); + bcm43xx_ilt_write16(bcm, 0x0804, 0x001F); + bcm43xx_ilt_write16(bcm, 0x0805, 0x002A); + bcm43xx_ilt_write16(bcm, 0x0805, 0x0030); + bcm43xx_ilt_write16(bcm, 0x0807, 0x003A); + + bcm43xx_ilt_write16(bcm, 0x0000, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0001, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0002, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0003, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0004, 0x0015); + bcm43xx_ilt_write16(bcm, 0x0005, 0x0015); + bcm43xx_ilt_write16(bcm, 0x0006, 0x0019); + + bcm43xx_ilt_write16(bcm, 0x0404, 0x0003); + bcm43xx_ilt_write16(bcm, 0x0405, 0x0003); + bcm43xx_ilt_write16(bcm, 0x0406, 0x0007); + + bcm43xx_ilt_write16(bcm, 0x3C02, 0x000F); + bcm43xx_ilt_write16(bcm, 0x3C03, 0x0014); + break; + default: + assert(0); + } +} + +/* Initialize APHY. This is also called for the GPHY in some cases. */ +static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 tval; + + if (phy->type == BCM43xx_PHYTYPE_A) { + bcm43xx_phy_setupa(bcm); + } else { + bcm43xx_phy_setupg(bcm); + if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) + bcm43xx_phy_write(bcm, 0x046E, 0x03CF); + return; + } + + bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS, + (bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340); + bcm43xx_phy_write(bcm, 0x0034, 0x0001); + + TODO();//TODO: RSSI AGC + bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) | (1 << 14)); + bcm43xx_radio_init2060(bcm); + + if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) + && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) { + if (bcm->current_core->radio->lofcal == 0xFFFF) { + TODO();//TODO: LOF Cal + bcm43xx_radio_set_tx_iq(bcm); + } else + bcm43xx_radio_write16(bcm, 0x001E, bcm->current_core->radio->lofcal); + } + + bcm43xx_phy_write(bcm, 0x007A, 0xF111); + + if (phy->savedpctlreg == 0xFFFF) { + bcm43xx_radio_write16(bcm, 0x0019, 0x0000); + bcm43xx_radio_write16(bcm, 0x0017, 0x0020); + + tval = bcm43xx_ilt_read16(bcm, 0x3001); + if (phy->rev == 1) { + bcm43xx_ilt_write16(bcm, 0x3001, + (bcm43xx_ilt_read16(bcm, 0x3001) & 0xFF87) + | 0x0058); + } else { + bcm43xx_ilt_write16(bcm, 0x3001, + (bcm43xx_ilt_read16(bcm, 0x3001) & 0xFFC3) + | 0x002C); + } + bcm43xx_dummy_transmission(bcm); + phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL); + bcm43xx_ilt_write16(bcm, 0x3001, tval); + + bcm43xx_radio_set_txpower_a(bcm, 0x0018); + } + bcm43xx_radio_clear_tssi(bcm); +} + +static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 offset, val; + + bcm43xx_write16(bcm, 0x03EC, 0x3F22); + bcm43xx_phy_write(bcm, 0x0020, 0x301C); + bcm43xx_phy_write(bcm, 0x0026, 0x0000); + bcm43xx_phy_write(bcm, 0x0030, 0x00C6); + bcm43xx_phy_write(bcm, 0x0088, 0x3E00); + val = 0x3C3D; + for (offset = 0x0089; offset < 0x00A7; offset++) { + bcm43xx_phy_write(bcm, offset, val); + val -= 0x0202; + } + bcm43xx_phy_write(bcm, 0x03E4, 0x3000); + if (radio->channel == 0xFF) + bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); + else + bcm43xx_radio_selectchannel(bcm, radio->channel, 0); + if (radio->version != 0x2050) { + bcm43xx_radio_write16(bcm, 0x0075, 0x0080); + bcm43xx_radio_write16(bcm, 0x0079, 0x0081); + } + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x0050, 0x0023); + if (radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x005A, 0x0070); + bcm43xx_radio_write16(bcm, 0x005B, 0x007B); + bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); + bcm43xx_radio_write16(bcm, 0x007A, 0x000F); + bcm43xx_phy_write(bcm, 0x0038, 0x0677); + bcm43xx_radio_init2050(bcm); + } + bcm43xx_phy_write(bcm, 0x0014, 0x0080); + bcm43xx_phy_write(bcm, 0x0032, 0x00CA); + bcm43xx_phy_write(bcm, 0x0032, 0x00CC); + bcm43xx_phy_write(bcm, 0x0035, 0x07C2); + bcm43xx_phy_lo_b_measure(bcm); + bcm43xx_phy_write(bcm, 0x0026, 0xCC00); + if (radio->version != 0x2050) + bcm43xx_phy_write(bcm, 0x0026, 0xCE00); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1000); + bcm43xx_phy_write(bcm, 0x002A, 0x88A3); + if (radio->version != 0x2050) + bcm43xx_phy_write(bcm, 0x002A, 0x88C2); + bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); + bcm43xx_phy_init_pctl(bcm); +} + +static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 offset, val; + + bcm43xx_write16(bcm, 0x03EC, 0x3F22); + bcm43xx_phy_write(bcm, 0x0020, 0x301C); + bcm43xx_phy_write(bcm, 0x0026, 0x0000); + bcm43xx_phy_write(bcm, 0x0030, 0x00C6); + bcm43xx_phy_write(bcm, 0x0088, 0x3E00); + val = 0x3C3D; + for (offset = 0x0089; offset < 0x00A7; offset++) { + bcm43xx_phy_write(bcm, offset, val); + val -= 0x0202; + } + bcm43xx_phy_write(bcm, 0x03E4, 0x3000); + if (radio->channel == 0xFF) + bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); + else + bcm43xx_radio_selectchannel(bcm, radio->channel, 0); + if (radio->version != 0x2050) { + bcm43xx_radio_write16(bcm, 0x0075, 0x0080); + bcm43xx_radio_write16(bcm, 0x0079, 0x0081); + } + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x0050, 0x0023); + if (radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x005A, 0x0070); + bcm43xx_radio_write16(bcm, 0x005B, 0x007B); + bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); + bcm43xx_radio_write16(bcm, 0x007A, 0x000F); + bcm43xx_phy_write(bcm, 0x0038, 0x0677); + bcm43xx_radio_init2050(bcm); + } + bcm43xx_phy_write(bcm, 0x0014, 0x0080); + bcm43xx_phy_write(bcm, 0x0032, 0x00CA); + if (radio->version == 0x2050) + bcm43xx_phy_write(bcm, 0x0032, 0x00E0); + bcm43xx_phy_write(bcm, 0x0035, 0x07C2); + + bcm43xx_phy_lo_b_measure(bcm); + + bcm43xx_phy_write(bcm, 0x0026, 0xCC00); + if (radio->version == 0x2050) + bcm43xx_phy_write(bcm, 0x0026, 0xCE00); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1100); + bcm43xx_phy_write(bcm, 0x002A, 0x88A3); + if (radio->version == 0x2050) + bcm43xx_phy_write(bcm, 0x002A, 0x88C2); + bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); + if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { + bcm43xx_calc_nrssi_slope(bcm); + bcm43xx_calc_nrssi_threshold(bcm); + } + bcm43xx_phy_init_pctl(bcm); +} + +static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 offset; + + if (phy->version == 1 && + radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) + | 0x0050); + } + if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) && + (bcm->board_type != 0x0416)) { + for (offset = 0x00A8 ; offset < 0x00C7; offset++) { + bcm43xx_phy_write(bcm, offset, + (bcm43xx_phy_read(bcm, offset) + 0x2020) + & 0x3F3F); + } + } + bcm43xx_phy_write(bcm, 0x0035, + (bcm43xx_phy_read(bcm, 0x0035) & 0xF0FF) + | 0x0700); + if (radio->version == 0x2050) + bcm43xx_phy_write(bcm, 0x0038, 0x0667); + + if (phy->connected) { + if (radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) + | 0x0020); + bcm43xx_radio_write16(bcm, 0x0051, + bcm43xx_radio_read16(bcm, 0x0051) + | 0x0004); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, 0x0000); + + bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x0100); + bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000); + + bcm43xx_phy_write(bcm, 0x001C, 0x186A); + + bcm43xx_phy_write(bcm, 0x0013, (bcm43xx_phy_read(bcm, 0x0013) & 0x00FF) | 0x1900); + bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFFC0) | 0x0064); + bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) & 0xFF80) | 0x000A); + } + + if (bcm->bad_frames_preempt) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11)); + } + + if (phy->version == 1 && radio->version == 0x2050) { + bcm43xx_phy_write(bcm, 0x0026, 0xCE00); + bcm43xx_phy_write(bcm, 0x0021, 0x3763); + bcm43xx_phy_write(bcm, 0x0022, 0x1BC3); + bcm43xx_phy_write(bcm, 0x0023, 0x06F9); + bcm43xx_phy_write(bcm, 0x0024, 0x037E); + } else + bcm43xx_phy_write(bcm, 0x0026, 0xCC00); + bcm43xx_phy_write(bcm, 0x0030, 0x00C6); + bcm43xx_write16(bcm, 0x03EC, 0x3F22); + + if (phy->version == 1 && radio->version == 0x2050) + bcm43xx_phy_write(bcm, 0x0020, 0x3E1C); + else + bcm43xx_phy_write(bcm, 0x0020, 0x301C); + + if (phy->version == 0) + bcm43xx_write16(bcm, 0x03E4, 0x3000); + + /* Force to channel 7, even if not supported. */ + bcm43xx_radio_selectchannel(bcm, 7, 0); + + if (radio->version != 0x2050) { + bcm43xx_radio_write16(bcm, 0x0075, 0x0080); + bcm43xx_radio_write16(bcm, 0x0079, 0x0081); + } + + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x0050, 0x0023); + + if (radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x005A, 0x0070); + } + + bcm43xx_radio_write16(bcm, 0x005B, 0x007B); + bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); + + bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007); + + bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); + + bcm43xx_phy_write(bcm, 0x0014, 0x0080); + bcm43xx_phy_write(bcm, 0x0032, 0x00CA); + bcm43xx_phy_write(bcm, 0x88A3, 0x002A); + + bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); + + if (radio->version == 0x2050) + bcm43xx_radio_write16(bcm, 0x005D, 0x000D); + + bcm43xx_write16(bcm, 0x03E4, (bcm43xx_read16(bcm, 0x03E4) & 0xFFC0) | 0x0004); +} + +static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 offset, val; + + bcm43xx_phy_write(bcm, 0x003E, 0x817A); + bcm43xx_radio_write16(bcm, 0x007A, + (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058)); + if ((radio->manufact == 0x17F) && + (radio->version == 0x2050) && + (radio->revision == 3 || + radio->revision == 4 || + radio->revision == 5)) { + bcm43xx_radio_write16(bcm, 0x0051, 0x001F); + bcm43xx_radio_write16(bcm, 0x0052, 0x0040); + bcm43xx_radio_write16(bcm, 0x0053, 0x005B); + bcm43xx_radio_write16(bcm, 0x0054, 0x0098); + bcm43xx_radio_write16(bcm, 0x005A, 0x0088); + bcm43xx_radio_write16(bcm, 0x005B, 0x0088); + bcm43xx_radio_write16(bcm, 0x005D, 0x0088); + bcm43xx_radio_write16(bcm, 0x005E, 0x0088); + bcm43xx_radio_write16(bcm, 0x007D, 0x0088); + } + if ((radio->manufact == 0x17F) && + (radio->version == 0x2050) && + (radio->revision == 6)) { + bcm43xx_radio_write16(bcm, 0x0051, 0x0000); + bcm43xx_radio_write16(bcm, 0x0052, 0x0040); + bcm43xx_radio_write16(bcm, 0x0053, 0x00B7); + bcm43xx_radio_write16(bcm, 0x0054, 0x0098); + bcm43xx_radio_write16(bcm, 0x005A, 0x0088); + bcm43xx_radio_write16(bcm, 0x005B, 0x008B); + bcm43xx_radio_write16(bcm, 0x005C, 0x00B5); + bcm43xx_radio_write16(bcm, 0x005D, 0x0088); + bcm43xx_radio_write16(bcm, 0x005E, 0x0088); + bcm43xx_radio_write16(bcm, 0x007D, 0x0088); + bcm43xx_radio_write16(bcm, 0x007C, 0x0001); + bcm43xx_radio_write16(bcm, 0x007E, 0x0008); + } + if ((radio->manufact == 0x17F) && + (radio->version == 0x2050) && + (radio->revision == 7)) { + bcm43xx_radio_write16(bcm, 0x0051, 0x0000); + bcm43xx_radio_write16(bcm, 0x0052, 0x0040); + bcm43xx_radio_write16(bcm, 0x0053, 0x00B7); + bcm43xx_radio_write16(bcm, 0x0054, 0x0098); + bcm43xx_radio_write16(bcm, 0x005A, 0x0088); + bcm43xx_radio_write16(bcm, 0x005B, 0x00A8); + bcm43xx_radio_write16(bcm, 0x005C, 0x0075); + bcm43xx_radio_write16(bcm, 0x005D, 0x00F5); + bcm43xx_radio_write16(bcm, 0x005E, 0x00B8); + bcm43xx_radio_write16(bcm, 0x007D, 0x00E8); + bcm43xx_radio_write16(bcm, 0x007C, 0x0001); + bcm43xx_radio_write16(bcm, 0x007E, 0x0008); + bcm43xx_radio_write16(bcm, 0x007B, 0x0000); + } + if ((radio->manufact == 0x17F) && + (radio->version == 0x2050) && + (radio->revision == 8)) { + bcm43xx_radio_write16(bcm, 0x0051, 0x0000); + bcm43xx_radio_write16(bcm, 0x0052, 0x0040); + bcm43xx_radio_write16(bcm, 0x0053, 0x00B7); + bcm43xx_radio_write16(bcm, 0x0054, 0x0098); + bcm43xx_radio_write16(bcm, 0x005A, 0x0088); + bcm43xx_radio_write16(bcm, 0x005B, 0x006B); + bcm43xx_radio_write16(bcm, 0x005C, 0x000F); + if (bcm->sprom.boardflags & 0x8000) { + bcm43xx_radio_write16(bcm, 0x005D, 0x00FA); + bcm43xx_radio_write16(bcm, 0x005E, 0x00D8); + } else { + bcm43xx_radio_write16(bcm, 0x005D, 0x00F5); + bcm43xx_radio_write16(bcm, 0x005E, 0x00B8); + } + bcm43xx_radio_write16(bcm, 0x0073, 0x0003); + bcm43xx_radio_write16(bcm, 0x007D, 0x00A8); + bcm43xx_radio_write16(bcm, 0x007C, 0x0001); + bcm43xx_radio_write16(bcm, 0x007E, 0x0008); + } + val = 0x1E1F; + for (offset = 0x0088; offset < 0x0098; offset++) { + bcm43xx_phy_write(bcm, offset, val); + val -= 0x0202; + } + val = 0x3E3F; + for (offset = 0x0098; offset < 0x00A8; offset++) { + bcm43xx_phy_write(bcm, offset, val); + val -= 0x0202; + } + val = 0x2120; + for (offset = 0x00A8; offset < 0x00C8; offset++) { + bcm43xx_phy_write(bcm, offset, (val & 0x3F3F)); + val += 0x0202; + } + if (phy->type == BCM43xx_PHYTYPE_G) { + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0020); + bcm43xx_radio_write16(bcm, 0x0051, + bcm43xx_radio_read16(bcm, 0x0051) | 0x0004); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) | 0x0100); + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) | 0x2000); + } + + /* Force to channel 7, even if not supported. */ + bcm43xx_radio_selectchannel(bcm, 7, 0); + + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x0050, 0x0023); + udelay(40); + bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) | 0x0002)); + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + if ((bcm->current_core->radio->manufact == 0x17F) && + (bcm->current_core->radio->version == 0x2050) && + (bcm->current_core->radio->revision == 2)) { + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x005A, 0x0070); + bcm43xx_radio_write16(bcm, 0x005B, 0x007B); + bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); + } + bcm43xx_radio_write16(bcm, 0x007A, + (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007); + + bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); + + bcm43xx_phy_write(bcm, 0x0014, 0x0200); + if (radio->version == 0x2050){ + if (radio->revision == 3 || + radio->revision == 4 || + radio->revision == 5) + bcm43xx_phy_write(bcm, 0x002A, 0x8AC0); + else + bcm43xx_phy_write(bcm, 0x002A, 0x88C2); + } + bcm43xx_phy_write(bcm, 0x0038, 0x0668); + bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); + if (radio->version == 0x2050) { + if (radio->revision == 3 || + radio->revision == 4 || + radio->revision == 5) + bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003); + else if (radio->revision <= 2) + bcm43xx_radio_write16(bcm, 0x005D, 0x000D); + } + + if (phy->rev == 4) + bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004); + else + bcm43xx_write16(bcm, 0x03E4, 0x0009); + if (phy->type == BCM43xx_PHYTYPE_B) { + bcm43xx_write16(bcm, 0x03E6, 0x8140); + bcm43xx_phy_write(bcm, 0x0016, 0x5410); + bcm43xx_phy_write(bcm, 0x0017, 0xA820); + bcm43xx_phy_write(bcm, 0x0007, 0x0062); + TODO();//TODO: calibrate stuff. + bcm43xx_phy_init_pctl(bcm); + } else + bcm43xx_write16(bcm, 0x03E6, 0x0); +} + +static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 tmp; + + if (phy->rev == 1) + bcm43xx_phy_initb5(bcm); + else if (phy->rev >= 2 && phy->rev <= 7) + bcm43xx_phy_initb6(bcm); + if (phy->rev >= 2 || phy->connected) + bcm43xx_phy_inita(bcm); + + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0814, 0x0000); + bcm43xx_phy_write(bcm, 0x0815, 0x0000); + if (phy->rev == 2) + bcm43xx_phy_write(bcm, 0x0811, 0x0000); + else if (phy->rev >= 3) + bcm43xx_phy_write(bcm, 0x0811, 0x0400); + bcm43xx_phy_write(bcm, 0x0015, 0x00C0); + tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; + if (tmp == 3) { + bcm43xx_phy_write(bcm, 0x04C2, 0x1816); + bcm43xx_phy_write(bcm, 0x04C3, 0x8606); + } else if (tmp == 4 || tmp == 5) { + bcm43xx_phy_write(bcm, 0x04C2, 0x1816); + bcm43xx_phy_write(bcm, 0x04C3, 0x8006); + bcm43xx_phy_write(bcm, 0x04CC, (bcm43xx_phy_read(bcm, 0x04CC) + & 0x00FF) | 0x1F00); + } + } + if (radio->revision <= 3 && phy->connected) + bcm43xx_phy_write(bcm, 0x047E, 0x0078); + if (radio->revision >= 6 && radio->revision <= 8) { + bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080); + bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004); + } + if (radio->initval == 0xFFFF) { + radio->initval = bcm43xx_radio_init2050(bcm); + bcm43xx_phy_lo_g_measure(bcm); + } else { + bcm43xx_radio_write16(bcm, 0x0078, radio->initval); + bcm43xx_radio_write16(bcm, 0x0052, + (bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0) + | radio->txpower[3]); + } + + if (phy->connected) { + bcm43xx_phy_lo_adjust(bcm, 0); + bcm43xx_phy_write(bcm, 0x080F, 0x8078); + + if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) + bcm43xx_phy_write(bcm, 0x002E, 0x807F); + else + bcm43xx_phy_write(bcm, 0x002E, 0x8075); + + if (phy->rev < 2) + bcm43xx_phy_write(bcm, 0x002F, 0x0101); + else + bcm43xx_phy_write(bcm, 0x002F, 0x0202); + } + + if ((bcm->sprom.boardflags & BCM43xx_BFL_RSSI) == 0) { + FIXME();//FIXME: 0x7FFFFFFF should be 16-bit ! + bcm43xx_nrssi_hw_update(bcm, (u16)0x7FFFFFFF); + bcm43xx_calc_nrssi_threshold(bcm); + } else if (phy->connected) { + if (radio->nrssi[0] == -1000) { + assert(radio->nrssi[1] == -1000); + bcm43xx_calc_nrssi_slope(bcm); + } else + bcm43xx_calc_nrssi_threshold(bcm); + } + bcm43xx_phy_init_pctl(bcm); +} + +static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) +{ + int i; + u16 ret = 0; + + for (i = 0; i < 10; i++){ + bcm43xx_phy_write(bcm, 0x0015, 0xAFA0); + udelay(1); + bcm43xx_phy_write(bcm, 0x0015, 0xEFA0); + udelay(10); + bcm43xx_phy_write(bcm, 0x0015, 0xFFA0); + udelay(40); + ret += bcm43xx_phy_read(bcm, 0x002C); + } + + return ret; +} + +void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 regstack[12] = { 0 }; + u16 mls; + u16 fval; + int i, j; + + regstack[0] = bcm43xx_phy_read(bcm, 0x0015); + regstack[1] = bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0; + + if (radio->version == 0x2053) { + regstack[2] = bcm43xx_phy_read(bcm, 0x000A); + regstack[3] = bcm43xx_phy_read(bcm, 0x002A); + regstack[4] = bcm43xx_phy_read(bcm, 0x0035); + regstack[5] = bcm43xx_phy_read(bcm, 0x0003); + regstack[6] = bcm43xx_phy_read(bcm, 0x0001); + regstack[7] = bcm43xx_phy_read(bcm, 0x0030); + + regstack[8] = bcm43xx_radio_read16(bcm, 0x0043); + regstack[9] = bcm43xx_radio_read16(bcm, 0x007A); + regstack[10] = bcm43xx_read16(bcm, 0x03EC); + regstack[11] = bcm43xx_radio_read16(bcm, 0x0052) & 0x00F0; + + bcm43xx_phy_write(bcm, 0x0030, 0x00FF); + bcm43xx_write16(bcm, 0x03EC, 0x3F3F); + bcm43xx_phy_write(bcm, 0x0035, regstack[4] & 0xFF7F); + bcm43xx_radio_write16(bcm, 0x007A, regstack[9] & 0xFFF0); + } + bcm43xx_phy_write(bcm, 0x0015, 0xB000); + bcm43xx_phy_write(bcm, 0x002B, 0x0004); + + if (radio->version == 0x2053) { + bcm43xx_phy_write(bcm, 0x002B, 0x0203); + bcm43xx_phy_write(bcm, 0x002A, 0x08A3); + } + + phy->minlowsig[0] = 0xFFFF; + + for (i = 0; i < 4; i++) { + bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i); + bcm43xx_phy_lo_b_r15_loop(bcm); + } + for (i = 0; i < 10; i++) { + bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i); + mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10; + if (mls < phy->minlowsig[0]) { + phy->minlowsig[0] = mls; + phy->minlowsigpos[0] = i; + } + } + bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | phy->minlowsigpos[0]); + + phy->minlowsig[1] = 0xFFFF; + + for (i = -4; i < 5; i += 2) { + for (j = -4; j < 5; j += 2) { + if (j < 0) + fval = (0x0100 * i) + j + 0x0100; + else + fval = (0x0100 * i) + j; + bcm43xx_phy_write(bcm, 0x002F, fval); + mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10; + if (mls < phy->minlowsig[1]) { + phy->minlowsig[1] = mls; + phy->minlowsigpos[1] = fval; + } + } + } + phy->minlowsigpos[1] += 0x0101; + + bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]); + if (radio->version == 2053) { + bcm43xx_phy_write(bcm, 0x000A, regstack[2]); + bcm43xx_phy_write(bcm, 0x002A, regstack[3]); + bcm43xx_phy_write(bcm, 0x0035, regstack[4]); + bcm43xx_phy_write(bcm, 0x0003, regstack[5]); + bcm43xx_phy_write(bcm, 0x0001, regstack[6]); + bcm43xx_phy_write(bcm, 0x0030, regstack[7]); + + bcm43xx_radio_write16(bcm, 0x0043, regstack[8]); + bcm43xx_radio_write16(bcm, 0x007A, regstack[9]); + + bcm43xx_radio_write16(bcm, 0x0052, + (bcm43xx_radio_read16(bcm, 0x0052) & 0x000F) + | regstack[11]); + + bcm43xx_write16(bcm, 0x03EC, regstack[10]); + } + bcm43xx_phy_write(bcm, 0x0015, regstack[0]); +} + +static inline +u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) +{ + if (bcm->current_core->phy->connected) { + bcm43xx_phy_write(bcm, 0x15, 0xE300); + control <<= 8; + bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0); + udelay(5); + bcm43xx_phy_write(bcm, 0x0812, control | 0x00B2); + udelay(2); + bcm43xx_phy_write(bcm, 0x0812, control | 0x00B3); + udelay(4); + bcm43xx_phy_write(bcm, 0x0015, 0xF300); + udelay(8); + } else { + bcm43xx_phy_write(bcm, 0x0015, control | 0xEFA0); + udelay(2); + bcm43xx_phy_write(bcm, 0x0015, control | 0xEFE0); + udelay(4); + bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0); + udelay(8); + } + + return bcm43xx_phy_read(bcm, 0x002D); +} + +static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control) +{ + int i; + u32 ret = 0; + + for (i = 0; i < 8; i++) + ret += bcm43xx_phy_lo_g_deviation_subval(bcm, control); + + return ret; +} + +/* Write the LocalOscillator CONTROL */ +static inline +void bcm43xx_lo_write(struct bcm43xx_private *bcm, + struct bcm43xx_lopair *pair) +{ + u16 value; + + value = (u8)(pair->low); + value |= ((u8)(pair->high)) << 8; + +#ifdef CONFIG_BCM43XX_DEBUG + /* Sanity check. */ + if (pair->low < -8 || pair->low > 8 || + pair->high < -8 || pair->high > 8) { + printk(KERN_WARNING PFX + "WARNING: Writing invalid LOpair " + "(low: %d, high: %d, index: %lu)\n", + pair->low, pair->high, + (unsigned long)(pair - bcm->current_core->phy->_lo_pairs)); + dump_stack(); + } +#endif + + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, value); +} + +static inline +struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm, + u16 baseband_attenuation, + u16 radio_attenuation, + u16 tx) +{ + static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 }; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + + if (baseband_attenuation > 6) + baseband_attenuation = 6; + assert(radio_attenuation < 10); + assert(tx == 0 || tx == 3); + + if (tx == 3) { + return bcm43xx_get_lopair(phy, + radio_attenuation, + baseband_attenuation); + } + return bcm43xx_get_lopair(phy, dict[radio_attenuation], baseband_attenuation); +} + +static inline +struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm) +{ + return bcm43xx_find_lopair(bcm, + bcm->current_core->radio->txpower[0], + bcm->current_core->radio->txpower[1], + bcm->current_core->radio->txpower[2]); +} + +/* Adjust B/G LO */ +void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed) +{ + struct bcm43xx_lopair *pair; + + if (fixed) { + /* Use fixed values. Only for initialization. */ + pair = bcm43xx_find_lopair(bcm, 2, 3, 0); + } else + pair = bcm43xx_current_lopair(bcm); + bcm43xx_lo_write(bcm, pair); +} + +static inline +void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) +{ + u16 txctl2 = 0, i; + u32 smallest, tmp; + + bcm43xx_radio_write16(bcm, 0x0052, 0x0000); + udelay(10); + smallest = bcm43xx_phy_lo_g_singledeviation(bcm, 0); + for (i = 0; i < 16; i++) { + bcm43xx_radio_write16(bcm, 0x0052, i); + udelay(10); + tmp = bcm43xx_phy_lo_g_singledeviation(bcm, 0); + if (tmp < smallest) { + smallest = tmp; + txctl2 = i; + } + } + bcm->current_core->radio->txpower[3] = txctl2; +} + +static +void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm, + const struct bcm43xx_lopair *in_pair, + struct bcm43xx_lopair *out_pair, + u16 r27) +{ + static const struct bcm43xx_lopair transitions[8] = { + { .high = 1, .low = 1, }, + { .high = 1, .low = 0, }, + { .high = 1, .low = -1, }, + { .high = 0, .low = -1, }, + { .high = -1, .low = -1, }, + { .high = -1, .low = 0, }, + { .high = -1, .low = 1, }, + { .high = 0, .low = 1, }, + }; + struct bcm43xx_lopair lowest_transition = { + .high = in_pair->high, + .low = in_pair->low, + }; + struct bcm43xx_lopair tmp_pair; + struct bcm43xx_lopair transition; + int i = 12; + int state = 0; + int found_lower; + int j, begin, end; + u32 lowest_deviation; + u32 tmp; + + /* Note that in_pair and out_pair can point to the same pair. Be careful. */ + + bcm43xx_lo_write(bcm, &lowest_transition); + lowest_deviation = bcm43xx_phy_lo_g_singledeviation(bcm, r27); + do { + found_lower = 0; + assert(state >= 0 && state <= 8); + if (state == 0) { + begin = 1; + end = 8; + } else if (state % 2 == 0) { + begin = state - 1; + end = state + 1; + } else { + begin = state - 2; + end = state + 2; + } + if (begin < 1) + begin += 8; + if (end > 8) + end -= 8; + + j = begin; + tmp_pair.high = lowest_transition.high; + tmp_pair.low = lowest_transition.low; + while (1) { + assert(j >= 1 && j <= 8); + transition.high = tmp_pair.high + transitions[j - 1].high; + transition.low = tmp_pair.low + transitions[j - 1].low; + if ((abs(transition.low) < 9) && (abs(transition.high) < 9)) { + bcm43xx_lo_write(bcm, &transition); + tmp = bcm43xx_phy_lo_g_singledeviation(bcm, r27); + if (tmp < lowest_deviation) { + lowest_deviation = tmp; + state = j; + found_lower = 1; + + lowest_transition.high = transition.high; + lowest_transition.low = transition.low; + } + } + if (j == end) + break; + if (j == 8) + j = 1; + else + j++; + } + } while (i-- && found_lower); + + out_pair->high = lowest_transition.high; + out_pair->low = lowest_transition.low; +} + +/* Set the baseband attenuation value on chip. */ +void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, + u16 baseband_attenuation) +{ + u16 value; + + if (bcm->current_core->phy->version == 0) { + value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0); + value |= (baseband_attenuation & 0x000F); + bcm43xx_write16(bcm, 0x03E6, value); + return; + } + + if (bcm->current_core->phy->version > 1) { + value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C; + value |= (baseband_attenuation << 2) & 0x003C; + } else { + value = bcm43xx_phy_read(bcm, 0x0060) & ~0x0078; + value |= (baseband_attenuation << 3) & 0x0078; + } + bcm43xx_phy_write(bcm, 0x0060, value); +} + +/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */ +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); + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 h, i, oldi = 0, j; + struct bcm43xx_lopair control; + struct bcm43xx_lopair *tmp_control; + u16 tmp; + u16 regstack[16] = { 0 }; + u8 oldchannel; + + //XXX: What are these? + u8 r27 = 0, r31; + + oldchannel = radio->channel; + /* Setup */ + if (phy->connected) { + regstack[0] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS); + regstack[1] = bcm43xx_phy_read(bcm, 0x0802); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF); + bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC); + } + regstack[3] = bcm43xx_read16(bcm, 0x03E2); + bcm43xx_write16(bcm, 0x03E2, regstack[3] | 0x8000); + regstack[4] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); + regstack[5] = bcm43xx_phy_read(bcm, 0x15); + regstack[6] = bcm43xx_phy_read(bcm, 0x2A); + regstack[7] = bcm43xx_phy_read(bcm, 0x35); + regstack[8] = bcm43xx_phy_read(bcm, 0x60); + regstack[9] = bcm43xx_radio_read16(bcm, 0x43); + regstack[10] = bcm43xx_radio_read16(bcm, 0x7A); + regstack[11] = bcm43xx_radio_read16(bcm, 0x52); + if (phy->connected) { + regstack[12] = bcm43xx_phy_read(bcm, 0x0811); + regstack[13] = bcm43xx_phy_read(bcm, 0x0812); + regstack[14] = bcm43xx_phy_read(bcm, 0x0814); + regstack[15] = bcm43xx_phy_read(bcm, 0x0815); + } + bcm43xx_radio_selectchannel(bcm, 6, 0); + if (phy->connected) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF); + bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC); + bcm43xx_dummy_transmission(bcm); + } + bcm43xx_radio_write16(bcm, 0x0043, 0x0006); + + bcm43xx_phy_set_baseband_attenuation(bcm, 2); + + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x0000); + bcm43xx_phy_write(bcm, 0x002E, 0x007F); + bcm43xx_phy_write(bcm, 0x080F, 0x0078); + bcm43xx_phy_write(bcm, 0x0035, regstack[7] & ~(1 << 7)); + bcm43xx_radio_write16(bcm, 0x007A, regstack[10] & 0xFFF0); + bcm43xx_phy_write(bcm, 0x002B, 0x0203); + bcm43xx_phy_write(bcm, 0x002A, 0x08A3); + if (phy->connected) { + bcm43xx_phy_write(bcm, 0x0814, regstack[14] | 0x0003); + bcm43xx_phy_write(bcm, 0x0815, regstack[15] & 0xFFFC); + bcm43xx_phy_write(bcm, 0x0811, 0x01B3); + bcm43xx_phy_write(bcm, 0x0812, 0x00B2); + } + if (is_initializing) + bcm43xx_phy_lo_g_measure_txctl2(bcm); + bcm43xx_phy_write(bcm, 0x080F, 0x8078); + + /* Measure */ + control.low = 0; + control.high = 0; + for (h = 0; h < 10; h++) { + /* Loop over each possible RadioAttenuation (0-9) */ + i = pairorder[h]; + if (is_initializing) { + if (i == 3) { + control.low = 0; + control.high = 0; + } else if (((i % 2 == 1) && (oldi % 2 == 1)) || + ((i % 2 == 0) && (oldi % 2 == 0))) { + tmp_control = bcm43xx_get_lopair(phy, oldi, 0); + memcpy(&control, tmp_control, sizeof(control)); + } else { + tmp_control = bcm43xx_get_lopair(phy, 3, 0); + memcpy(&control, tmp_control, sizeof(control)); + } + } + /* Loop over each possible BasebandAttenuation/2 */ + for (j = 0; j < 4; j++) { + if (is_initializing) { + tmp = i * 2 + j; + r27 = 0; + r31 = 0; + if (tmp > 14) { + r31 = 1; + if (tmp > 17) + r27 = 1; + if (tmp > 19) + r27 = 2; + } + } else { + tmp_control = bcm43xx_get_lopair(phy, i, j * 2); + if (!tmp_control->used) + continue; + memcpy(&control, tmp_control, sizeof(control)); + r27 = 3; + r31 = 0; + } + bcm43xx_radio_write16(bcm, 0x43, i); + bcm43xx_radio_write16(bcm, 0x52, + radio->txpower[3]); + udelay(10); + + bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); + + tmp = (regstack[10] & 0xFFF0); + if (r31) + tmp |= 0x0008; + bcm43xx_radio_write16(bcm, 0x007A, tmp); + + tmp_control = bcm43xx_get_lopair(phy, i, j * 2); + bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27); + } + oldi = i; + } + /* Loop over each possible RadioAttenuation (10-13) */ + for (i = 10; i < 14; i++) { + /* Loop over each possible BasebandAttenuation/2 */ + for (j = 0; j < 4; j++) { + if (is_initializing) { + tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2); + memcpy(&control, tmp_control, sizeof(control)); + tmp = (i - 9) * 2 + j - 5;//FIXME: This is wrong, as the following if statement can never trigger. + r27 = 0; + r31 = 0; + if (tmp > 14) { + r31 = 1; + if (tmp > 17) + r27 = 1; + if (tmp > 19) + r27 = 2; + } + } else { + tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2); + if (!tmp_control->used) + continue; + memcpy(&control, tmp_control, sizeof(control)); + r27 = 3; + r31 = 0; + } + bcm43xx_radio_write16(bcm, 0x43, i - 9); + bcm43xx_radio_write16(bcm, 0x52, + radio->txpower[3] + | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? + udelay(10); + + bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); + + tmp = (regstack[10] & 0xFFF0); + if (r31) + tmp |= 0x0008; + bcm43xx_radio_write16(bcm, 0x7A, tmp); + + tmp_control = bcm43xx_get_lopair(phy, i, j * 2); + bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27); + } + } + + /* Restoration */ + if (phy->connected) { + bcm43xx_phy_write(bcm, 0x0015, 0xE300); + bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA0); + udelay(5); + bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2); + udelay(2); + bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3); + } else + bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0); + bcm43xx_phy_lo_adjust(bcm, is_initializing); + bcm43xx_phy_write(bcm, 0x002E, 0x807F); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x002F, 0x0202); + else + bcm43xx_phy_write(bcm, 0x002F, 0x0101); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, regstack[4]); + bcm43xx_phy_write(bcm, 0x0015, regstack[5]); + bcm43xx_phy_write(bcm, 0x002A, regstack[6]); + bcm43xx_phy_write(bcm, 0x0035, regstack[7]); + bcm43xx_phy_write(bcm, 0x0060, regstack[8]); + bcm43xx_radio_write16(bcm, 0x0043, regstack[9]); + bcm43xx_radio_write16(bcm, 0x007A, regstack[10]); + regstack[11] &= 0x00F0; + regstack[11] |= (bcm43xx_radio_read16(bcm, 0x52) & 0x000F); + bcm43xx_radio_write16(bcm, 0x52, regstack[11]); + bcm43xx_write16(bcm, 0x03E2, regstack[3]); + if (phy->connected) { + bcm43xx_phy_write(bcm, 0x0811, regstack[12]); + bcm43xx_phy_write(bcm, 0x0812, regstack[13]); + bcm43xx_phy_write(bcm, 0x0814, regstack[14]); + bcm43xx_phy_write(bcm, 0x0815, regstack[15]); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0]); + bcm43xx_phy_write(bcm, 0x0802, regstack[1]); + } + bcm43xx_radio_selectchannel(bcm, oldchannel, 1); + +#ifdef CONFIG_BCM43XX_DEBUG + { + /* Sanity check for all lopairs. */ + for (i = 0; i < BCM43xx_LO_COUNT; i++) { + tmp_control = phy->_lo_pairs + i; + if (tmp_control->low < -8 || tmp_control->low > 8 || + tmp_control->high < -8 || tmp_control->high > 8) { + printk(KERN_WARNING PFX + "WARNING: Invalid LOpair (low: %d, high: %d, index: %d)\n", + tmp_control->low, tmp_control->high, i); + } + } + } +#endif /* CONFIG_BCM43XX_DEBUG */ +} + +static +void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm) +{ + struct bcm43xx_lopair *pair; + + pair = bcm43xx_current_lopair(bcm); + pair->used = 1; +} + +void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_lopair *pair; + int i; + + for (i = 0; i < BCM43xx_LO_COUNT; i++) { + pair = phy->_lo_pairs + i; + pair->used = 0; + } +} + +/* http://bcm-specs.sipsolutions.net/EstimatePowerOut + * This function converts a TSSI value to dBm in Q5.2 + */ +static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + s8 dbm = 0; + s32 tmp; + + tmp = phy->idle_tssi; + tmp += tssi; + tmp -= phy->savedpctlreg; + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + tmp += 0x80; + tmp = limit_value(tmp, 0x00, 0xFF); + dbm = phy->tssi2dbm[tmp]; + TODO(); //TODO: There's a FIXME on the specs + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + tmp = limit_value(tmp, 0x00, 0x3F); + dbm = phy->tssi2dbm[tmp]; + break; + default: + assert(0); + } + + return dbm; +} + +/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */ +void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + + if (phy->savedpctlreg == 0xFFFF) + return; + if ((bcm->board_type == 0x0416) && + (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM)) + return; + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: { + + TODO(); //TODO: Nothing for A PHYs yet :-/ + + break; + } + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: { + u16 tmp; + u16 txpower; + s8 v0, v1, v2, v3; + s8 average; + u8 max_pwr; + s16 desired_pwr, estimated_pwr, pwr_adjust; + s16 radio_att_delta, baseband_att_delta; + s16 radio_attenuation, baseband_attenuation; + unsigned long phylock_flags; + + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0058); + v0 = (s8)(tmp & 0x00FF); + v1 = (s8)((tmp & 0xFF00) >> 8); + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005A); + v2 = (s8)(tmp & 0x00FF); + v3 = (s8)((tmp & 0xFF00) >> 8); + tmp = 0; + + if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) { + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0070); + v0 = (s8)(tmp & 0x00FF); + v1 = (s8)((tmp & 0xFF00) >> 8); + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0072); + v2 = (s8)(tmp & 0x00FF); + v3 = (s8)((tmp & 0xFF00) >> 8); + if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) + return; + v0 = (v0 + 0x20) & 0x3F; + v1 = (v1 + 0x20) & 0x3F; + v2 = (v2 + 0x20) & 0x3F; + v3 = (v3 + 0x20) & 0x3F; + tmp = 1; + } + bcm43xx_radio_clear_tssi(bcm); + + average = (v0 + v1 + v2 + v3 + 2) / 4; + + if (tmp && (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005E) & 0x8)) + average -= 13; + + estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average); + + max_pwr = bcm->sprom.maxpower_bgphy; + + if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) && + (phy->type == BCM43xx_PHYTYPE_G)) + max_pwr -= 0x3; + + /*TODO: + max_pwr = min(REG - bcm->sprom.antennagain_bgphy - 0x6, max_pwr) + where REG is the max power as per the regulatory domain + */ + + /*TODO: Get desired_pwr from wx_handlers or the stack + limit_value(desired_pwr, 0, max_pwr); + */ + + desired_pwr = max_pwr; /* remove this when we have a real desired_pwr */ + + pwr_adjust = desired_pwr - estimated_pwr; + + radio_att_delta = -(pwr_adjust + 7) >> 3; + baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta); + if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { + bcm43xx_phy_lo_mark_current_used(bcm); + return; + } + + /* Calculate the new attenuation values. */ + baseband_attenuation = radio->txpower[0]; + baseband_attenuation += baseband_att_delta; + radio_attenuation = radio->txpower[1]; + radio_attenuation += radio_att_delta; + + /* Get baseband and radio attenuation values into their permitted ranges. + * baseband 0-11, radio 0-9. + * Radio attenuation affects power level 4 times as much as baseband. + */ + if (radio_attenuation < 0) { + baseband_attenuation -= (4 * -radio_attenuation); + radio_attenuation = 0; + } else if (radio_attenuation > 9) { + baseband_attenuation += (4 * (radio_attenuation - 9)); + radio_attenuation = 9; + } else { + while (baseband_attenuation < 0 && radio_attenuation > 0) { + baseband_attenuation += 4; + radio_attenuation--; + } + while (baseband_attenuation > 11 && radio_attenuation < 9) { + baseband_attenuation -= 4; + radio_attenuation++; + } + } + baseband_attenuation = limit_value(baseband_attenuation, 0, 11); + + txpower = radio->txpower[2]; + if ((radio->version == 0x2050) && (radio->revision == 2)) { + if (radio_attenuation <= 1) { + if (txpower == 0) { + txpower = 3; + radio_attenuation += 2; + baseband_attenuation += 2; + } else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) { + baseband_attenuation += 4 * (radio_attenuation - 2); + radio_attenuation = 2; + } + } else if (radio_attenuation > 4 && txpower != 0) { + txpower = 0; + if (baseband_attenuation < 3) { + radio_attenuation -= 3; + baseband_attenuation += 2; + } else { + radio_attenuation -= 2; + baseband_attenuation -= 2; + } + } + } + radio->txpower[2] = txpower; + baseband_attenuation = limit_value(baseband_attenuation, 0, 11); + radio_attenuation = limit_value(radio_attenuation, 0, 9); + + bcm43xx_phy_lock(bcm, phylock_flags); + bcm43xx_radio_lock(bcm); + bcm43xx_radio_set_txpower_bg(bcm, baseband_attenuation, + radio_attenuation, txpower); + bcm43xx_phy_lo_mark_current_used(bcm); + bcm43xx_radio_unlock(bcm); + bcm43xx_phy_unlock(bcm, phylock_flags); + break; + } + default: + assert(0); + } +} + +static inline +s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den) +{ + if (num < 0) + return num/den; + else + return (num+den/2)/den; +} + +static inline +s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2) +{ + s32 m1, m2, f = 256, q, delta; + s8 i = 0; + + m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32); + m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1); + do { + if (i > 15) + return -EINVAL; + q = bcm43xx_tssi2dbm_ad(f * 4096 - + bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048); + delta = abs(q - f); + f = q; + i++; + } while (delta >= 2); + entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128); + return 0; +} + +/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */ +int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + s16 pab0, pab1, pab2; + u8 idx; + s8 *dyn_tssi2dbm; + + if (phy->type == BCM43xx_PHYTYPE_A) { + pab0 = (s16)(bcm->sprom.pa1b0); + pab1 = (s16)(bcm->sprom.pa1b1); + pab2 = (s16)(bcm->sprom.pa1b2); + } else { + pab0 = (s16)(bcm->sprom.pa0b0); + pab1 = (s16)(bcm->sprom.pa0b1); + pab2 = (s16)(bcm->sprom.pa0b2); + } + + if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) { + phy->idle_tssi = 0x34; + phy->tssi2dbm = bcm43xx_tssi2dbm_b_table; + return 0; + } + + if (pab0 != 0 && pab1 != 0 && pab2 != 0 && + pab0 != -1 && pab1 != -1 && pab2 != -1) { + /* The pabX values are set in SPROM. Use them. */ + if (phy->type == BCM43xx_PHYTYPE_A) { + if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 && + (s8)bcm->sprom.idle_tssi_tgt_aphy != -1) + phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy); + else + phy->idle_tssi = 62; + } else { + if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 && + (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1) + phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy); + else + phy->idle_tssi = 62; + } + dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); + if (dyn_tssi2dbm == NULL) { + printk(KERN_ERR PFX "Could not allocate memory" + "for tssi2dbm table\n"); + return -ENOMEM; + } + for (idx = 0; idx < 64; idx++) + if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) { + phy->tssi2dbm = NULL; + printk(KERN_ERR PFX "Could not generate " + "tssi2dBm table\n"); + return -ENODEV; + } + phy->tssi2dbm = dyn_tssi2dbm; + phy->dyn_tssi_tbl = 1; + } else { + /* pabX values not set in SPROM. */ + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + /* APHY needs a generated table. */ + phy->tssi2dbm = NULL; + printk(KERN_ERR PFX "Could not generate tssi2dBm " + "table (wrong SPROM info)!\n"); + return -ENODEV; + case BCM43xx_PHYTYPE_B: + phy->idle_tssi = 0x34; + phy->tssi2dbm = bcm43xx_tssi2dbm_b_table; + break; + case BCM43xx_PHYTYPE_G: + phy->idle_tssi = 0x34; + phy->tssi2dbm = bcm43xx_tssi2dbm_g_table; + break; + } + } + + return 0; +} + +int bcm43xx_phy_init(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + int err = -ENODEV; + unsigned long flags; + + /* We do not want to be preempted while calibrating + * the hardware. + */ + local_irq_save(flags); + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + if (phy->rev == 2 || phy->rev == 3) { + bcm43xx_phy_inita(bcm); + err = 0; + } + break; + case BCM43xx_PHYTYPE_B: + switch (phy->rev) { + case 2: + bcm43xx_phy_initb2(bcm); + err = 0; + break; + case 4: + bcm43xx_phy_initb4(bcm); + err = 0; + break; + case 5: + bcm43xx_phy_initb5(bcm); + err = 0; + break; + case 6: + bcm43xx_phy_initb6(bcm); + err = 0; + break; + } + break; + case BCM43xx_PHYTYPE_G: + bcm43xx_phy_initg(bcm); + err = 0; + break; + } + local_irq_restore(flags); + if (err) + printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n"); + + return err; +} + +void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 antennadiv; + u16 offset; + u16 value; + u32 ucodeflags; + + antennadiv = phy->antenna_diversity; + + if (antennadiv == 0xFFFF) + antennadiv = 3; + assert(antennadiv <= 3); + + ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + ucodeflags & ~BCM43xx_UCODEFLAG_AUTODIV); + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + case BCM43xx_PHYTYPE_G: + if (phy->type == BCM43xx_PHYTYPE_A) + offset = 0x0000; + else + offset = 0x0400; + + if (antennadiv == 2) + value = (3/*automatic*/ << 7); + else + value = (antennadiv << 7); + bcm43xx_phy_write(bcm, offset + 1, + (bcm43xx_phy_read(bcm, offset + 1) + & 0x7E7F) | value); + + if (antennadiv >= 2) { + if (antennadiv == 2) + value = (antennadiv << 7); + else + value = (0/*force0*/ << 7); + bcm43xx_phy_write(bcm, offset + 0x2B, + (bcm43xx_phy_read(bcm, offset + 0x2B) + & 0xFEFF) | value); + } + + if (phy->type == BCM43xx_PHYTYPE_G) { + if (antennadiv >= 2) + bcm43xx_phy_write(bcm, 0x048C, + bcm43xx_phy_read(bcm, 0x048C) + | 0x2000); + else + bcm43xx_phy_write(bcm, 0x048C, + bcm43xx_phy_read(bcm, 0x048C) + & ~0x2000); + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0461, + bcm43xx_phy_read(bcm, 0x0461) + | 0x0010); + bcm43xx_phy_write(bcm, 0x04AD, + (bcm43xx_phy_read(bcm, 0x04AD) + & 0x00FF) | 0x0015); + if (phy->rev == 2) + bcm43xx_phy_write(bcm, 0x0427, 0x0008); + else + bcm43xx_phy_write(bcm, 0x0427, + (bcm43xx_phy_read(bcm, 0x0427) + & 0x00FF) | 0x0008); + } + else if (phy->rev >= 6) + bcm43xx_phy_write(bcm, 0x049B, 0x00DC); + } else { + if (phy->rev < 3) + bcm43xx_phy_write(bcm, 0x002B, + (bcm43xx_phy_read(bcm, 0x002B) + & 0x00FF) | 0x0024); + else { + bcm43xx_phy_write(bcm, 0x0061, + bcm43xx_phy_read(bcm, 0x0061) + | 0x0010); + if (phy->rev == 3) { + bcm43xx_phy_write(bcm, 0x0093, 0x001D); + bcm43xx_phy_write(bcm, 0x0027, 0x0008); + } else { + bcm43xx_phy_write(bcm, 0x0093, 0x003A); + bcm43xx_phy_write(bcm, 0x0027, + (bcm43xx_phy_read(bcm, 0x0027) + & 0x00FF) | 0x0008); + } + } + } + break; + case BCM43xx_PHYTYPE_B: + if (bcm->current_core->rev == 2) + value = (3/*automatic*/ << 7); + else + value = (antennadiv << 7); + bcm43xx_phy_write(bcm, 0x03E2, + (bcm43xx_phy_read(bcm, 0x03E2) + & 0xFE7F) | value); + break; + default: + assert(0); + } + + if (antennadiv >= 2) { + ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + ucodeflags | BCM43xx_UCODEFLAG_AUTODIV); + } + + phy->antenna_diversity = antennadiv; +} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h new file mode 100644 index 000000000000..1f321ef42be8 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h @@ -0,0 +1,74 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef BCM43xx_PHY_H_ +#define BCM43xx_PHY_H_ + +#include + +struct bcm43xx_private; + +void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm); +#define bcm43xx_phy_lock(bcm, flags) \ + do { \ + local_irq_save(flags); \ + bcm43xx_raw_phy_lock(bcm); \ + } while (0) +void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm); +#define bcm43xx_phy_unlock(bcm, flags) \ + do { \ + bcm43xx_raw_phy_unlock(bcm); \ + local_irq_restore(flags); \ + } while (0) + +u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset); +void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val); + +int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm); +int bcm43xx_phy_init(struct bcm43xx_private *bcm); + +void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm); +void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm); +int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect); + +void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm); +void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm); +void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm); + +/* Adjust the LocalOscillator to the saved values. + * "fixed" is only set to 1 once in initialization. Set to 0 otherwise. + */ +void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed); +void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm); + +void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, + u16 baseband_attenuation); + +#endif /* BCM43xx_PHY_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c new file mode 100644 index 000000000000..9a55e9d00528 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -0,0 +1,592 @@ +/* + + Broadcom BCM43xx wireless driver + + PIO Transmission + + Copyright (c) 2005 Michael Buesch + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx.h" +#include "bcm43xx_pio.h" +#include "bcm43xx_main.h" + +#include + + +static inline +u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue, + u16 offset) +{ + return bcm43xx_read16(queue->bcm, queue->mmio_base + offset); +} + +static inline +void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, + u16 offset, u16 value) +{ + bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); +} + +static inline +void tx_start(struct bcm43xx_pioqueue *queue) +{ + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_INIT); +} + +static inline +void tx_octet(struct bcm43xx_pioqueue *queue, + u8 octet) +{ + if (queue->bcm->current_core->rev < 3) { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, octet); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_WRITEHI); + } else { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_WRITEHI); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, octet); + } +} + +static inline +void tx_data(struct bcm43xx_pioqueue *queue, + u8 *packet, + unsigned int octets) +{ + u16 data; + unsigned int i = 0; + + if (queue->bcm->current_core->rev < 3) { + data = be16_to_cpu( *((u16 *)packet) ); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); + i += 2; + } + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_WRITELO | BCM43xx_PIO_TXCTL_WRITEHI); + for ( ; i < octets - 1; i += 2) { + data = be16_to_cpu( *((u16 *)(packet + i)) ); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); + } + if (octets % 2) + tx_octet(queue, packet[octets - 1]); +} + +static inline +void tx_complete(struct bcm43xx_pioqueue *queue, + struct sk_buff *skb) +{ + u16 data; + + if (queue->bcm->current_core->rev < 3) { + data = be16_to_cpu( *((u16 *)(skb->data + skb->len - 2)) ); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_WRITEHI | BCM43xx_PIO_TXCTL_COMPLETE); + } else { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_COMPLETE); + } +} + +static inline +u16 generate_cookie(struct bcm43xx_pioqueue *queue, + int packetindex) +{ + u16 cookie = 0x0000; + + /* We use the upper 4 bits for the PIO + * controller ID and the lower 12 bits + * for the packet index (in the cache). + */ + switch (queue->mmio_base) { + default: + assert(0); + case BCM43xx_MMIO_PIO1_BASE: + break; + case BCM43xx_MMIO_PIO2_BASE: + cookie = 0x1000; + break; + case BCM43xx_MMIO_PIO3_BASE: + cookie = 0x2000; + break; + case BCM43xx_MMIO_PIO4_BASE: + cookie = 0x3000; + break; + } + assert(((u16)packetindex & 0xF000) == 0x0000); + cookie |= (u16)packetindex; + + return cookie; +} + +static inline +struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm, + u16 cookie, + struct bcm43xx_pio_txpacket **packet) +{ + struct bcm43xx_pioqueue *queue = NULL; + int packetindex; + + switch (cookie & 0xF000) { + case 0x0000: + queue = bcm->current_core->pio->queue0; + break; + case 0x1000: + queue = bcm->current_core->pio->queue1; + break; + case 0x2000: + queue = bcm->current_core->pio->queue2; + break; + case 0x3000: + queue = bcm->current_core->pio->queue3; + break; + default: + assert(0); + } + + packetindex = (cookie & 0x0FFF); + assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS); + *packet = queue->__tx_packets_cache + packetindex; + + return queue; +} + +static inline +void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, + struct sk_buff *skb, + struct bcm43xx_pio_txpacket *packet) +{ + unsigned int octets; + + assert(skb_shinfo(skb)->nr_frags == 0); + assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); + + __skb_push(skb, sizeof(struct bcm43xx_txhdr)); + bcm43xx_generate_txhdr(queue->bcm, + (struct bcm43xx_txhdr *)skb->data, + skb->data + sizeof(struct bcm43xx_txhdr), + skb->len - sizeof(struct bcm43xx_txhdr), + (packet->xmitted_frags == 0), + generate_cookie(queue, pio_txpacket_getindex(packet))); + + tx_start(queue); + octets = skb->len; + if (queue->bcm->current_core->rev < 3) //FIXME: && this is the last packet in the queue. + octets -= 2; + tx_data(queue, (u8 *)skb->data, octets); + tx_complete(queue, skb); +} + +static inline +int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) +{ + struct bcm43xx_pioqueue *queue = packet->queue; + struct ieee80211_txb *txb = packet->txb; + struct sk_buff *skb; + u16 octets; + int i; + + for (i = packet->xmitted_frags; i < txb->nr_frags; i++) { + skb = txb->fragments[i]; + + octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr); + + assert(queue->tx_devq_size >= octets); + assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS); + assert(queue->tx_devq_used <= queue->tx_devq_size); + /* Check if there is sufficient free space on the device + * TX queue. If not, return and let the TX-work-handler + * retry later. + */ + if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS) + return -EBUSY; + if (queue->tx_devq_used + octets > queue->tx_devq_size) + return -EBUSY; + /* Now poke the device. */ + pio_tx_write_fragment(queue, skb, packet); + + /* Account for the packet size. + * (We must not overflow the device TX queue) + */ + queue->tx_devq_packets++; + queue->tx_devq_used += octets; + + assert(packet->xmitted_frags <= packet->txb->nr_frags); + packet->xmitted_frags++; + packet->xmitted_octets += octets; + } + list_move_tail(&packet->list, &queue->txrunning); + + return 0; +} + +static void free_txpacket(struct bcm43xx_pio_txpacket *packet) +{ + struct bcm43xx_pioqueue *queue = packet->queue; + + ieee80211_txb_free(packet->txb); + + list_move(&packet->list, &packet->queue->txfree); + + assert(queue->tx_devq_used >= packet->xmitted_octets); + queue->tx_devq_used -= packet->xmitted_octets; + assert(queue->tx_devq_packets >= packet->xmitted_frags); + queue->tx_devq_packets -= packet->xmitted_frags; +} + +static void txwork_handler(void *d) +{ + struct bcm43xx_pioqueue *queue = d; + unsigned long flags; + struct bcm43xx_pio_txpacket *packet, *tmp_packet; + int err; + + spin_lock_irqsave(&queue->txlock, flags); + list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { + assert(packet->xmitted_frags < packet->txb->nr_frags); + if (packet->xmitted_frags == 0) { + int i; + struct sk_buff *skb; + + /* Check if the device queue is big + * enough for every fragment. If not, drop the + * whole packet. + */ + for (i = 0; i < packet->txb->nr_frags; i++) { + skb = packet->txb->fragments[i]; + if (unlikely(skb->len > queue->tx_devq_size)) { + dprintkl(KERN_ERR PFX "PIO TX device queue too small. " + "Dropping packet...\n"); + free_txpacket(packet); + goto next_packet; + } + } + } + /* Now try to transmit the packet. + * This may not completely succeed. + */ + err = pio_tx_packet(packet); + if (err) + break; +next_packet: + continue; + } + spin_unlock_irqrestore(&queue->txlock, flags); +} + +static void setup_txqueues(struct bcm43xx_pioqueue *queue) +{ + struct bcm43xx_pio_txpacket *packet; + int i; + + for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) { + packet = queue->__tx_packets_cache + i; + + packet->queue = queue; + INIT_LIST_HEAD(&packet->list); + + list_add(&packet->list, &queue->txfree); + } +} + +static +struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, + u16 pio_mmio_base) +{ + struct bcm43xx_pioqueue *queue; + u32 value; + u16 qsize; + + queue = kmalloc(sizeof(*queue), GFP_KERNEL); + if (!queue) + goto out; + memset(queue, 0, sizeof(*queue)); + + queue->bcm = bcm; + queue->mmio_base = pio_mmio_base; + + INIT_LIST_HEAD(&queue->txfree); + INIT_LIST_HEAD(&queue->txqueue); + INIT_LIST_HEAD(&queue->txrunning); + spin_lock_init(&queue->txlock); + INIT_WORK(&queue->txwork, txwork_handler, queue); + + value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value |= BCM43xx_SBF_XFER_REG_BYTESWAP; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); + + qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); + if (qsize <= BCM43xx_PIO_TXQADJUST) { + printk(KERN_ERR PFX "PIO tx queue too small (%u)\n", qsize); + goto err_freequeue; + } + qsize -= BCM43xx_PIO_TXQADJUST; + queue->tx_devq_size = qsize; + + setup_txqueues(queue); + +out: + return queue; + +err_freequeue: + kfree(queue); + queue = NULL; + goto out; +} + +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); + cancel_delayed_work(&queue->txwork); + flush_workqueue(queue->bcm->workqueue); + + list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) + free_txpacket(packet); + list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) + free_txpacket(packet); +} + +static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) +{ + if (!queue) + return; + + cancel_transfers(queue); + kfree(queue); +} + +void bcm43xx_pio_free(struct bcm43xx_private *bcm) +{ + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue3); + bcm->current_core->pio->queue3 = NULL; + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue2); + bcm->current_core->pio->queue2 = NULL; + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue1); + bcm->current_core->pio->queue1 = NULL; + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue0); + bcm->current_core->pio->queue0 = NULL; +} + +int bcm43xx_pio_init(struct bcm43xx_private *bcm) +{ + struct bcm43xx_pioqueue *queue; + int err = -ENOMEM; + + queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE); + if (!queue) + goto out; + bcm->current_core->pio->queue0 = queue; + + queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE); + if (!queue) + goto err_destroy0; + bcm->current_core->pio->queue1 = queue; + + queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE); + if (!queue) + goto err_destroy1; + bcm->current_core->pio->queue2 = queue; + + queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE); + if (!queue) + goto err_destroy2; + bcm->current_core->pio->queue3 = queue; + + if (bcm->current_core->rev < 3) + bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND; + + dprintk(KERN_INFO PFX "PIO initialized\n"); + err = 0; +out: + return err; + +err_destroy2: + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue2); + bcm->current_core->pio->queue2 = NULL; +err_destroy1: + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue1); + bcm->current_core->pio->queue1 = NULL; +err_destroy0: + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue0); + bcm->current_core->pio->queue0 = NULL; + goto out; +} + +static inline +int pio_transfer_txb(struct bcm43xx_pioqueue *queue, + struct ieee80211_txb *txb) +{ + struct bcm43xx_pio_txpacket *packet; + unsigned long flags; + u16 tmp; + + spin_lock_irqsave(&queue->txlock, flags); + assert(!queue->tx_suspended); + assert(!list_empty(&queue->txfree)); + + tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); + if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) { + spin_unlock_irqrestore(&queue->txlock, flags); + return -EBUSY; + } + + packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); + + packet->txb = txb; + list_move_tail(&packet->list, &queue->txqueue); + packet->xmitted_octets = 0; + packet->xmitted_frags = 0; + + /* Suspend TX, if we are out of packets in the "free" queue. */ + if (unlikely(list_empty(&queue->txfree))) { + netif_stop_queue(queue->bcm->net_dev); + queue->tx_suspended = 1; + } + + spin_unlock_irqrestore(&queue->txlock, flags); + queue_work(queue->bcm->workqueue, &queue->txwork); + + return 0; +} + +int fastcall bcm43xx_pio_transfer_txb(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) +{ + return pio_transfer_txb(bcm->current_core->pio->queue1, txb); +} + +void fastcall +bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) +{ + struct bcm43xx_pioqueue *queue; + struct bcm43xx_pio_txpacket *packet; + unsigned long flags; + + queue = parse_cookie(bcm, status->cookie, &packet); + assert(queue); + spin_lock_irqsave(&queue->txlock, flags); + free_txpacket(packet); + if (unlikely(queue->tx_suspended)) { + queue->tx_suspended = 0; + netif_wake_queue(queue->bcm->net_dev); + } + + /* If there are packets on the txqueue, + * start the work handler again. + */ + if (!list_empty(&queue->txqueue)) { + queue_work(queue->bcm->workqueue, + &queue->txwork); + } + spin_unlock_irqrestore(&queue->txlock, flags); +} + +static void pio_rx_error(struct bcm43xx_pioqueue *queue, + const char *error) +{ + printk("PIO RX error: %s\n", error); + bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, BCM43xx_PIO_RXCTL_READY); +} + +void fastcall +bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) +{ + u16 preamble[21] = { 0 }; + struct bcm43xx_rxhdr *rxhdr; + u16 tmp; + u16 len; + int i, err; + int preamble_readwords; + struct sk_buff *skb; + + tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); + if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) { + dprintkl(KERN_ERR PFX "PIO RX: No data available\n"); + return; + } + bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, BCM43xx_PIO_RXCTL_DATAAVAILABLE); + + for (i = 0; i < 10; i++) { + tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); + if (tmp & BCM43xx_PIO_RXCTL_READY) + goto data_ready; + udelay(10); + } + dprintkl(KERN_ERR PFX "PIO RX timed out\n"); + return; +data_ready: + + len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); + if (unlikely(len > 0x700)) { + pio_rx_error(queue, "len > 0x700"); + return; + } + if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) { + pio_rx_error(queue, "len == 0"); + return; + } + preamble[0] = cpu_to_le16(len); + if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) + preamble_readwords = 14 / sizeof(u16); + else + preamble_readwords = 18 / sizeof(u16); + for (i = 0; i < preamble_readwords; i++) { + tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); + preamble[i + 1] = cpu_to_be16(tmp); + } + rxhdr = (struct bcm43xx_rxhdr *)preamble; + if (unlikely(rxhdr->flags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) { + pio_rx_error(queue, "invalid frame"); + if (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE) { + for (i = 0; i < 15; i++) + bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); /* dummy read. */ + } + return; + } +//FIXME +#if 0 + if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) { + bcm43xx_rx_transmitstatus(queue->bcm, + (const struct bcm43xx_hwxmitstatus *)(preamble + 1)); + return; + } +#endif + skb = dev_alloc_skb(len); + if (unlikely(!skb)) { + pio_rx_error(queue, "out of memory"); + return; + } + skb_put(skb, len); + for (i = 0; i < len - 1; i += 2) { + tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); + *((u16 *)(skb->data + i)) = tmp; + } + if (len % 2) { + tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); + skb->data[len - 1] = (tmp & 0x00FF); + skb->data[0] = (tmp & 0xFF00) >> 8; + } + err = bcm43xx_rx(queue->bcm, skb, rxhdr); + if (unlikely(err)) + dev_kfree_skb_irq(skb); +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h new file mode 100644 index 000000000000..71b92ee34169 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h @@ -0,0 +1,88 @@ +#ifndef BCM43xx_PIO_H_ +#define BCM43xx_PIO_H_ + +#include "bcm43xx.h" + +#include +#include +#include +#include + + +#define BCM43xx_PIO_TXCTL 0x00 +#define BCM43xx_PIO_TXDATA 0x02 +#define BCM43xx_PIO_TXQBUFSIZE 0x04 +#define BCM43xx_PIO_RXCTL 0x08 +#define BCM43xx_PIO_RXDATA 0x0A + +#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 0) +#define BCM43xx_PIO_TXCTL_WRITELO (1 << 1) +#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) +#define BCM43xx_PIO_TXCTL_INIT (1 << 3) +#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) + +#define BCM43xx_PIO_RXCTL_DATAAVAILABLE (1 << 0) +#define BCM43xx_PIO_RXCTL_READY (1 << 1) + +/* PIO constants */ +#define BCM43xx_PIO_MAXTXDEVQPACKETS 31 +#define BCM43xx_PIO_TXQADJUST 80 + +/* PIO tuning knobs */ +#define BCM43xx_PIO_MAXTXPACKETS 256 + + +struct bcm43xx_pioqueue; +struct bcm43xx_xmitstatus; + +struct bcm43xx_pio_txpacket { + struct bcm43xx_pioqueue *queue; + struct ieee80211_txb *txb; + struct list_head list; + + u8 xmitted_frags; + u16 xmitted_octets; +}; + +#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->__tx_packets_cache)) + +struct bcm43xx_pioqueue { + struct bcm43xx_private *bcm; + u16 mmio_base; + + u8 tx_suspended:1; + + /* Adjusted size of the device internal TX buffer. */ + u16 tx_devq_size; + /* Used octets of the device internal TX buffer. */ + u16 tx_devq_used; + /* Used packet slots in the device internal TX buffer. */ + u8 tx_devq_packets; + /* Packets from the txfree list can + * be taken on incoming TX requests. + */ + struct list_head txfree; + /* Packets on the txqueue are queued, + * but not completely written to the chip, yet. + */ + struct list_head txqueue; + /* Packets on the txrunning queue are completely + * posted to the device. We are waiting for the txstatus. + */ + struct list_head txrunning; + /* Locking of the TX queues and the accounting. */ + spinlock_t txlock; + struct work_struct txwork; + struct bcm43xx_pio_txpacket __tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS]; +}; + +int bcm43xx_pio_init(struct bcm43xx_private *bcm); +void bcm43xx_pio_free(struct bcm43xx_private *bcm); + +int FASTCALL(bcm43xx_pio_transfer_txb(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb)); +void FASTCALL(bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status)); + +void FASTCALL(bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)); +#endif /* BCM43xx_PIO_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c new file mode 100644 index 000000000000..3c92b62807c5 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c @@ -0,0 +1,358 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include + +#include "bcm43xx.h" +#include "bcm43xx_power.h" +#include "bcm43xx_main.h" + + +/* Get max/min slowclock frequency + * as described in http://bcm-specs.sipsolutions.net/PowerControl + */ +static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm, + int get_max) +{ + int limit = 0; + int divisor; + int selection; + int err; + u32 tmp; + struct bcm43xx_coreinfo *old_core; + + if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) + goto out; + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err) + goto out; + + if (bcm->current_core->rev < 6) { + if ((bcm->bustype == BCM43xx_BUSTYPE_PCMCIA) || + (bcm->bustype == BCM43xx_BUSTYPE_SB)) { + selection = 1; + divisor = 32; + } else { + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp); + if (err) { + printk(KERN_ERR PFX "clockfreqlimit pcicfg read failure\n"); + goto out_switchback; + } + if (tmp & 0x10) { + /* PCI */ + selection = 2; + divisor = 64; + } else { + /* XTAL */ + selection = 1; + divisor = 32; + } + } + } else if (bcm->current_core->rev < 10) { + selection = (tmp & 0x07); + if (selection) { + tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); + divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16)); + } else + divisor = 1; + } else { + tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL); + divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16)); + selection = 1; + } + + switch (selection) { + case 0: + /* LPO */ + if (get_max) + limit = 43000; + else + limit = 25000; + break; + case 1: + /* XTAL */ + if (get_max) + limit = 20200000; + else + limit = 19800000; + break; + case 2: + /* PCI */ + if (get_max) + limit = 34000000; + else + limit = 25000000; + break; + default: + assert(0); + } + limit /= divisor; + +out_switchback: + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + +out: + return limit; +} + +/* init power control + * as described in http://bcm-specs.sipsolutions.net/PowerControl + */ +int bcm43xx_pctl_init(struct bcm43xx_private *bcm) +{ + int err, maxfreq; + struct bcm43xx_coreinfo *old_core; + + if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) + return 0; + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err == -ENODEV) + return 0; + if (err) + goto out; + + maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1); + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY, + (maxfreq * 150 + 999999) / 1000000); + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY, + (maxfreq * 15 + 999999) / 1000000); + + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + +out: + return err; +} + +u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm) +{ + u16 delay = 0; + int err; + u32 pll_on_delay; + struct bcm43xx_coreinfo *old_core; + int minfreq; + + if (bcm->bustype != BCM43xx_BUSTYPE_PCI) + goto out; + if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) + goto out; + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err == -ENODEV) + goto out; + + minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0); + pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY); + delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq; + + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + +out: + return delay; +} + +/* set the powercontrol clock + * as described in http://bcm-specs.sipsolutions.net/PowerControl + */ +int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode) +{ + int err; + struct bcm43xx_coreinfo *old_core; + u32 tmp; + + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err == -ENODEV) + return 0; + if (err) + goto out; + + if (bcm->core_chipcommon.rev < 6) { + if (mode == BCM43xx_PCTL_CLK_FAST) { + err = bcm43xx_pctl_set_crystal(bcm, 1); + if (err) + goto out; + } + } else { + if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) && + (bcm->core_chipcommon.rev < 10)) { + switch (mode) { + case BCM43xx_PCTL_CLK_FAST: + tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); + tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL; + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); + break; + case BCM43xx_PCTL_CLK_SLOW: + tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); + tmp |= BCM43xx_PCTL_FORCE_SLOW; + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); + break; + case BCM43xx_PCTL_CLK_DYNAMIC: + tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); + tmp &= ~BCM43xx_PCTL_FORCE_SLOW; + tmp |= BCM43xx_PCTL_FORCE_PLL; + tmp &= ~BCM43xx_PCTL_DYN_XTAL; + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); + } + } + } + + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + +out: + return err; +} + +int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on) +{ + int err; + u32 in, out, outenable; + + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in); + if (err) + goto err_pci; + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &out); + if (err) + goto err_pci; + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUTENABLE, &outenable); + if (err) + goto err_pci; + + outenable |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN); + + if (on) { + if (in & 0x40) + return 0; + + out |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN); + + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); + if (err) + goto err_pci; + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable); + if (err) + goto err_pci; + udelay(1000); + + out &= ~BCM43xx_PCTL_PLL_POWERDOWN; + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); + if (err) + goto err_pci; + udelay(5000); + } else { + if (bcm->current_core->rev < 5) + return 0; + if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW) + return 0; + +/* XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time? + * err = bcm43xx_switch_core(bcm, bcm->active_80211_core); + * if (err) + * return err; + * if (((bcm->current_core->rev >= 3) && + * (bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) || + * ((bcm->current_core->rev < 3) && + * !(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4)))) + * return 0; + * err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + * if (err) + * return err; + */ + + err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); + if (err) + goto out; + out &= ~BCM43xx_PCTL_XTAL_POWERUP; + out |= BCM43xx_PCTL_PLL_POWERDOWN; + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); + if (err) + goto err_pci; + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable); + if (err) + goto err_pci; + } + +out: + return err; + +err_pci: + printk(KERN_ERR PFX "Error: pctl_set_clock() could not access PCI config space!\n"); + err = -EBUSY; + goto out; +} + +/* Set the PowerSavingControlBits. + * Bitvalues: + * 0 => unset the bit + * 1 => set the bit + * -1 => calculate the bit + */ +void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm, + int bit25, int bit26) +{ + int i; + u32 status; + +//FIXME: Force 25 to off and 26 to on for now: +bit25 = 0; +bit26 = 1; + + if (bit25 == -1) { + //TODO: If powersave is not off and FIXME is not set and we are not in adhoc + // and thus is not an AP and we are associated, set bit 25 + } + if (bit26 == -1) { + //TODO: If the device is awake or this is an AP, or we are scanning, or FIXME, + // or we are associated, or FIXME, or the latest PS-Poll packet sent was + // successful, set bit26 + } + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + if (bit25) + status |= BCM43xx_SBF_PS1; + else + status &= ~BCM43xx_SBF_PS1; + if (bit26) + status |= BCM43xx_SBF_PS2; + else + status &= ~BCM43xx_SBF_PS2; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + if (bit26 && bcm->current_core->rev >= 5) { + for (i = 0; i < 100; i++) { + if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4) + break; + udelay(10); + } + } +} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h new file mode 100644 index 000000000000..5f63640810bd --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.h @@ -0,0 +1,47 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef BCM43xx_POWER_H_ +#define BCM43xx_POWER_H_ + +#include + + +struct bcm43xx_private; + +int bcm43xx_pctl_init(struct bcm43xx_private *bcm); +int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode); +int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on); +u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm); + +void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm, + int bit25, int bit26); + +#endif /* BCM43xx_POWER_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c new file mode 100644 index 000000000000..1e65658552b0 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -0,0 +1,1766 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include + +#include "bcm43xx.h" +#include "bcm43xx_main.h" +#include "bcm43xx_phy.h" +#include "bcm43xx_radio.h" +#include "bcm43xx_ilt.h" + + +/* Table for bcm43xx_radio_calibrationvalue() */ +static const u16 rcc_table[16] = { + 0x0002, 0x0003, 0x0001, 0x000F, + 0x0006, 0x0007, 0x0005, 0x000F, + 0x000A, 0x000B, 0x0009, 0x000F, + 0x000E, 0x000F, 0x000D, 0x000F, +}; + +/* Reverse the bits of a 4bit value. + * Example: 1101 is flipped 1011 + */ +static u16 flip_4bit(u16 value) +{ + u16 flipped = 0x0000; + + assert((value & ~0x000F) == 0x0000); + + flipped |= (value & 0x0001) << 3; + flipped |= (value & 0x0002) << 1; + flipped |= (value & 0x0004) >> 1; + flipped |= (value & 0x0008) >> 3; + + return flipped; +} + +/* Get the freq, as it has to be written to the device. */ +static inline +u16 channel2freq_bg(u8 channel) +{ + /* Frequencies are given as frequencies_bg[index] + 2.4GHz + * Starting with channel 1 + */ + static const u16 frequencies_bg[14] = { + 12, 17, 22, 27, + 32, 37, 42, 47, + 52, 57, 62, 67, + 72, 84, + }; + + assert(channel >= 1 && channel <= 14); + + return frequencies_bg[channel - 1]; +} + +/* Get the freq, as it has to be written to the device. */ +static inline +u16 channel2freq_a(u8 channel) +{ + assert(channel <= 200); + + return (5000 + 5 * channel); +} + +void bcm43xx_radio_lock(struct bcm43xx_private *bcm) +{ + u32 status; + + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + status |= BCM43xx_SBF_RADIOREG_LOCK; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + udelay(10); +} + +void bcm43xx_radio_unlock(struct bcm43xx_private *bcm) +{ + u32 status; + + bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); /* dummy read */ + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + status &= ~BCM43xx_SBF_RADIOREG_LOCK; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); +} + +u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + offset |= 0x0040; + break; + case BCM43xx_PHYTYPE_B: + if (radio->version == 0x2053) { + if (offset < 0x70) + offset += 0x80; + else if (offset < 0x80) + offset += 0x70; + } else if (radio->version == 0x2050) { + offset |= 0x80; + } else + assert(0); + break; + case BCM43xx_PHYTYPE_G: + offset |= 0x80; + break; + } + + bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset); + return bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW); +} + +void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) +{ + bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset); + bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val); +} + +static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm, + s16 first, s16 second, s16 third) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 i; + u16 start = 0x08, end = 0x18; + u16 offset = 0x0400; + u16 tmp; + + if (phy->rev <= 1) { + offset = 0x5000; + start = 0x10; + end = 0x20; + } + + for (i = 0; i < 4; i++) + bcm43xx_ilt_write16(bcm, offset + i, first); + + for (i = start; i < end; i++) + bcm43xx_ilt_write16(bcm, offset + i, second); + + if (third != -1) { + tmp = ((u16)third << 14) | ((u16)third << 6); + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | tmp); + bcm43xx_phy_write(bcm, 0x04A1, + (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | tmp); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | tmp); + } + bcm43xx_dummy_transmission(bcm); +} + +static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 i, tmp; + u16 offset = 0x0400; + u16 start = 0x0008, end = 0x0018; + + if (phy->rev <= 1) { + offset = 0x5000; + start = 0x0010; + end = 0x0020; + } + + for (i = 0; i < 4; i++) { + tmp = (i & 0xFFFC); + tmp |= (i & 0x0001) << 1; + tmp |= (i & 0x0002) >> 1; + + bcm43xx_ilt_write16(bcm, offset + i, tmp); + } + + for (i = start; i < end; i++) + bcm43xx_ilt_write16(bcm, offset + i, i - start); + + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040); + bcm43xx_phy_write(bcm, 0x04A1, + (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | 0x4040); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | 0x4000); + bcm43xx_dummy_transmission(bcm); +} + +/* Synthetic PU workaround */ +static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + + if (radio->version != 0x2050 || radio->revision >= 6) { + /* We do not need the workaround. */ + return; + } + + if (channel <= 10) { + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, + channel2freq_bg(channel + 4)); + } else { + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, + channel2freq_bg(1)); + } + udelay(100); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, + channel2freq_bg(channel)); +} + +u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u8 ret = 0; + u16 saved, rssi, temp; + int i, j = 0; + + saved = bcm43xx_phy_read(bcm, 0x0403); + bcm43xx_radio_selectchannel(bcm, channel, 0); + bcm43xx_phy_write(bcm, 0x0403, (saved & 0xFFF8) | 5); + if (radio->aci_hw_rssi) + rssi = bcm43xx_phy_read(bcm, 0x048A) & 0x3F; + else + rssi = saved & 0x3F; + /* clamp temp to signed 5bit */ + if (rssi > 32) + rssi -= 64; + for (i = 0;i < 100; i++) { + temp = (bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x3F; + if (temp > 32) + temp -= 64; + if (temp < rssi) + j++; + if (j >= 20) + ret = 1; + } + bcm43xx_phy_write(bcm, 0x0403, saved); + + return ret; +} + +u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u8 ret[13]; + unsigned int channel = radio->channel; + unsigned int i, j, start, end; + unsigned long phylock_flags; + + if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0))) + return 0; + + bcm43xx_phy_lock(bcm, phylock_flags); + bcm43xx_radio_lock(bcm); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF); + bcm43xx_set_all_gains(bcm, 3, 8, 1); + + start = (channel - 5 > 0) ? channel - 5 : 1; + end = (channel + 5 < 14) ? channel + 5 : 13; + + for (i = start; i <= end; i++) { + if (abs(channel - i) > 2) + ret[i-1] = bcm43xx_radio_aci_detect(bcm, i); + } + bcm43xx_radio_selectchannel(bcm, channel, 0); + bcm43xx_phy_write(bcm, 0x0802, + (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC) | 0x0003); + bcm43xx_phy_write(bcm, 0x0403, + bcm43xx_phy_read(bcm, 0x0403) & 0xFFF8); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000); + bcm43xx_set_original_gains(bcm); + for (i = 0; i < 13; i++) { + if (!ret[i]) + continue; + end = (i + 5 < 13) ? i + 5 : 13; + for (j = i; j < end; j++) + ret[j] = 1; + } + bcm43xx_radio_unlock(bcm); + bcm43xx_phy_unlock(bcm, phylock_flags); + + return ret[channel - 1]; +} + +/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ +void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val) +{ + bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset); + bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val); +} + +/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ +s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset) +{ + u16 val; + + bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset); + val = bcm43xx_phy_read(bcm, BCM43xx_PHY_NRSSILT_DATA); + + return (s16)val; +} + +/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ +void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val) +{ + u16 i; + s16 tmp; + + for (i = 0; i < 64; i++) { + tmp = bcm43xx_nrssi_hw_read(bcm, i); + tmp -= val; + tmp = limit_value(tmp, -32, 31); + bcm43xx_nrssi_hw_write(bcm, i, tmp); + } +} + +/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ +void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm) +{ + s16 i, delta; + s32 tmp; + + delta = 0x1F - bcm->current_core->radio->nrssi[0]; + for (i = 0; i < 64; i++) { + tmp = (i - delta) * bcm->current_core->radio->nrssislope; + tmp /= 0x10000; + tmp += 0x3A; + tmp = limit_value(tmp, 0, 0x3F); + bcm->current_core->radio->nrssi_lt[i] = tmp; + } +} + +static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 backup[20] = { 0 }; + s16 v47F; + u16 i; + u16 saved = 0xFFFF; + + backup[0] = bcm43xx_phy_read(bcm, 0x0001); + backup[1] = bcm43xx_phy_read(bcm, 0x0811); + backup[2] = bcm43xx_phy_read(bcm, 0x0812); + backup[3] = bcm43xx_phy_read(bcm, 0x0814); + backup[4] = bcm43xx_phy_read(bcm, 0x0815); + backup[5] = bcm43xx_phy_read(bcm, 0x005A); + backup[6] = bcm43xx_phy_read(bcm, 0x0059); + backup[7] = bcm43xx_phy_read(bcm, 0x0058); + backup[8] = bcm43xx_phy_read(bcm, 0x000A); + backup[9] = bcm43xx_phy_read(bcm, 0x0003); + backup[10] = bcm43xx_radio_read16(bcm, 0x007A); + backup[11] = bcm43xx_radio_read16(bcm, 0x0043); + + bcm43xx_phy_write(bcm, 0x0429, + bcm43xx_phy_read(bcm, 0x0429) & 0x7FFF); + bcm43xx_phy_write(bcm, 0x0001, + (bcm43xx_phy_read(bcm, 0x0001) & 0x3FFF) | 0x4000); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x000C); + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) & 0xFFF3) | 0x0004); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) & ~(0x1 | 0x2)); + if (phy->rev >= 6) { + backup[12] = bcm43xx_phy_read(bcm, 0x002E); + backup[13] = bcm43xx_phy_read(bcm, 0x002F); + backup[14] = bcm43xx_phy_read(bcm, 0x080F); + backup[15] = bcm43xx_phy_read(bcm, 0x0810); + backup[16] = bcm43xx_phy_read(bcm, 0x0801); + backup[17] = bcm43xx_phy_read(bcm, 0x0060); + backup[18] = bcm43xx_phy_read(bcm, 0x0014); + backup[19] = bcm43xx_phy_read(bcm, 0x0478); + + bcm43xx_phy_write(bcm, 0x002E, 0); + bcm43xx_phy_write(bcm, 0x002F, 0); + bcm43xx_phy_write(bcm, 0x080F, 0); + bcm43xx_phy_write(bcm, 0x0810, 0); + bcm43xx_phy_write(bcm, 0x0478, + bcm43xx_phy_read(bcm, 0x0478) | 0x0100); + bcm43xx_phy_write(bcm, 0x0801, + bcm43xx_phy_read(bcm, 0x0801) | 0x0040); + bcm43xx_phy_write(bcm, 0x0060, + bcm43xx_phy_read(bcm, 0x0060) | 0x0040); + bcm43xx_phy_write(bcm, 0x0014, + bcm43xx_phy_read(bcm, 0x0014) | 0x0200); + } + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0070); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); + udelay(30); + + v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (v47F >= 0x20) + v47F -= 0x40; + if (v47F == 31) { + for (i = 7; i >= 4; i--) { + bcm43xx_radio_write16(bcm, 0x007B, i); + udelay(20); + v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (v47F >= 0x20) + v47F -= 0x40; + if (v47F < 31 && saved == 0xFFFF) + saved = i; + } + if (saved == 0xFFFF) + saved = 4; + } else { + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0001); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x000C); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) | 0x000C); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x0030); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) | 0x0030); + bcm43xx_phy_write(bcm, 0x005A, 0x0480); + bcm43xx_phy_write(bcm, 0x0059, 0x0810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + if (phy->rev == 0) { + bcm43xx_phy_write(bcm, 0x0003, 0x0122); + } else { + bcm43xx_phy_write(bcm, 0x000A, + bcm43xx_phy_read(bcm, 0x000A) + | 0x2000); + } + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0004); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); + bcm43xx_phy_write(bcm, 0x0003, + (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) + | 0x0040); + bcm43xx_phy_write(bcm, 0x007A, + bcm43xx_phy_read(bcm, 0x007A) | 0x000F); + bcm43xx_set_all_gains(bcm, 3, 0, 1); + bcm43xx_radio_write16(bcm, 0x0043, + (bcm43xx_radio_read16(bcm, 0x0043) + & 0x00F0) | 0x000F); + udelay(30); + v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (v47F >= 0x20) + v47F -= 0x40; + if (v47F == -32) { + for (i = 0; i < 4; i++) { + bcm43xx_radio_write16(bcm, 0x007B, i); + udelay(20); + v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (v47F >= 0x20) + v47F -= 0x40; + if (v47F > -31 && saved == 0xFFFF) + saved = i; + } + if (saved == 0xFFFF) + saved = 3; + } else + saved = 0; + } + bcm43xx_radio_write16(bcm, 0x007B, saved); + + if (phy->rev >= 6) { + bcm43xx_phy_write(bcm, 0x002E, backup[12]); + bcm43xx_phy_write(bcm, 0x002F, backup[13]); + bcm43xx_phy_write(bcm, 0x080F, backup[14]); + bcm43xx_phy_write(bcm, 0x0810, backup[15]); + } + bcm43xx_phy_write(bcm, 0x0814, backup[3]); + bcm43xx_phy_write(bcm, 0x0815, backup[4]); + bcm43xx_phy_write(bcm, 0x005A, backup[5]); + bcm43xx_phy_write(bcm, 0x0059, backup[6]); + bcm43xx_phy_write(bcm, 0x0058, backup[7]); + bcm43xx_phy_write(bcm, 0x000A, backup[8]); + bcm43xx_phy_write(bcm, 0x0003, backup[9]); + bcm43xx_radio_write16(bcm, 0x0043, backup[11]); + bcm43xx_radio_write16(bcm, 0x007A, backup[10]); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2); + bcm43xx_phy_write(bcm, 0x0429, + bcm43xx_phy_read(bcm, 0x0429) | 0x8000); + bcm43xx_set_original_gains(bcm); + if (phy->rev >= 6) { + bcm43xx_phy_write(bcm, 0x0801, backup[16]); + bcm43xx_phy_write(bcm, 0x0060, backup[17]); + bcm43xx_phy_write(bcm, 0x0014, backup[18]); + bcm43xx_phy_write(bcm, 0x0478, backup[19]); + } + bcm43xx_phy_write(bcm, 0x0001, backup[0]); + bcm43xx_phy_write(bcm, 0x0812, backup[2]); + bcm43xx_phy_write(bcm, 0x0811, backup[1]); +} + +void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 backup[18] = { 0 }; + u16 tmp; + s16 nrssi0, nrssi1; + + switch (phy->type) { + case BCM43xx_PHYTYPE_B: + backup[0] = bcm43xx_radio_read16(bcm, 0x007A); + backup[1] = bcm43xx_radio_read16(bcm, 0x0052); + backup[2] = bcm43xx_radio_read16(bcm, 0x0043); + backup[3] = bcm43xx_phy_read(bcm, 0x0030); + backup[4] = bcm43xx_phy_read(bcm, 0x0026); + backup[5] = bcm43xx_phy_read(bcm, 0x0015); + backup[6] = bcm43xx_phy_read(bcm, 0x002A); + backup[7] = bcm43xx_phy_read(bcm, 0x0020); + backup[8] = bcm43xx_phy_read(bcm, 0x005A); + backup[9] = bcm43xx_phy_read(bcm, 0x0059); + backup[10] = bcm43xx_phy_read(bcm, 0x0058); + backup[11] = bcm43xx_read16(bcm, 0x03E2); + backup[12] = bcm43xx_read16(bcm, 0x03E6); + backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); + + tmp = bcm43xx_radio_read16(bcm, 0x007A); + tmp &= (phy->rev >= 5) ? 0x007F : 0x000F; + bcm43xx_radio_write16(bcm, 0x007A, tmp); + bcm43xx_phy_write(bcm, 0x0030, 0x00FF); + bcm43xx_write16(bcm, 0x03EC, 0x7F7F); + bcm43xx_phy_write(bcm, 0x0026, 0x0000); + bcm43xx_phy_write(bcm, 0x0015, + bcm43xx_phy_read(bcm, 0x0015) | 0x0020); + bcm43xx_phy_write(bcm, 0x002A, 0x08A3); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); + + nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); + if (phy->rev >= 2) { + bcm43xx_write16(bcm, 0x03E6, 0x0040); + } else if (phy->rev == 0) { + bcm43xx_write16(bcm, 0x03E6, 0x0122); + } else { + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, + bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000); + } + bcm43xx_phy_write(bcm, 0x0020, 0x3F3F); + bcm43xx_phy_write(bcm, 0x0015, 0xF330); + bcm43xx_radio_write16(bcm, 0x005A, 0x0060); + bcm43xx_radio_write16(bcm, 0x0043, + bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0); + bcm43xx_phy_write(bcm, 0x005A, 0x0480); + bcm43xx_phy_write(bcm, 0x0059, 0x0810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + udelay(20); + + nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027); + bcm43xx_phy_write(bcm, 0x0030, backup[3]); + bcm43xx_radio_write16(bcm, 0x007A, backup[0]); + bcm43xx_write16(bcm, 0x03E2, backup[11]); + bcm43xx_phy_write(bcm, 0x0026, backup[4]); + bcm43xx_phy_write(bcm, 0x0015, backup[5]); + bcm43xx_phy_write(bcm, 0x002A, backup[6]); + bcm43xx_synth_pu_workaround(bcm, radio->channel); + if (phy->rev != 0) + bcm43xx_write16(bcm, 0x03F4, backup[13]); + + bcm43xx_phy_write(bcm, 0x0020, backup[7]); + bcm43xx_phy_write(bcm, 0x005A, backup[8]); + bcm43xx_phy_write(bcm, 0x0059, backup[9]); + bcm43xx_phy_write(bcm, 0x0058, backup[10]); + bcm43xx_radio_write16(bcm, 0x0052, backup[1]); + bcm43xx_radio_write16(bcm, 0x0043, backup[2]); + + if (nrssi0 == nrssi1) + radio->nrssislope = 0x00010000; + else + radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1); + + if (nrssi0 <= -4) { + radio->nrssi[0] = nrssi0; + radio->nrssi[1] = nrssi1; + } + break; + case BCM43xx_PHYTYPE_G: +//FIXME: Something is broken here. This is called when enabling WLAN interfmode. +// If this is done at runtime, I get an XMIT ERROR and transmission is +// broken. I guess some important register is overwritten by accident. +// The XMIT ERROR comes from the dummy_transmissions in set_gains. + if (radio->revision >= 9) + return; + if (radio->revision == 8) + bcm43xx_calc_nrssi_offset(bcm); + + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC); + backup[7] = bcm43xx_read16(bcm, 0x03E2); + bcm43xx_write16(bcm, 0x03E2, + bcm43xx_read16(bcm, 0x03E2) | 0x8000); + backup[0] = bcm43xx_radio_read16(bcm, 0x007A); + backup[1] = bcm43xx_radio_read16(bcm, 0x0052); + backup[2] = bcm43xx_radio_read16(bcm, 0x0043); + backup[3] = bcm43xx_phy_read(bcm, 0x0015); + backup[4] = bcm43xx_phy_read(bcm, 0x005A); + backup[5] = bcm43xx_phy_read(bcm, 0x0059); + backup[6] = bcm43xx_phy_read(bcm, 0x0058); + backup[8] = bcm43xx_read16(bcm, 0x03E6); + backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); + if (phy->rev >= 3) { + backup[10] = bcm43xx_phy_read(bcm, 0x002E); + backup[11] = bcm43xx_phy_read(bcm, 0x002F); + backup[12] = bcm43xx_phy_read(bcm, 0x080F); + backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL); + backup[14] = bcm43xx_phy_read(bcm, 0x0801); + backup[15] = bcm43xx_phy_read(bcm, 0x0060); + backup[16] = bcm43xx_phy_read(bcm, 0x0014); + backup[17] = bcm43xx_phy_read(bcm, 0x0478); + bcm43xx_phy_write(bcm, 0x002E, 0); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0); + switch (phy->rev) { + case 4: case 6: case 7: + bcm43xx_phy_write(bcm, 0x0478, + bcm43xx_phy_read(bcm, 0x0478) + | 0x0100); + bcm43xx_phy_write(bcm, 0x0801, + bcm43xx_phy_read(bcm, 0x0801) + | 0x0040); + break; + case 3: case 5: + bcm43xx_phy_write(bcm, 0x0801, + bcm43xx_phy_read(bcm, 0x0801) + & 0xFFBF); + break; + } + bcm43xx_phy_write(bcm, 0x0060, + bcm43xx_phy_read(bcm, 0x0060) + | 0x0040); + bcm43xx_phy_write(bcm, 0x0014, + bcm43xx_phy_read(bcm, 0x0014) + | 0x0200); + } + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0070); + bcm43xx_set_all_gains(bcm, 0, 8, 0); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7); + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0811, + (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030); + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010); + } + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); + udelay(20); + + nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (nrssi0 >= 0x0020) + nrssi0 -= 0x0040; + + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0003, + (bcm43xx_phy_read(bcm, 0x0003) + & 0xFF9F) | 0x0040); + } + + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, + bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) + | 0x2000); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x000F); + bcm43xx_phy_write(bcm, 0x0015, 0xF330); + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020); + bcm43xx_phy_write(bcm, 0x0811, + (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020); + } + + bcm43xx_set_all_gains(bcm, 3, 0, 1); + if (radio->revision == 8) { + bcm43xx_radio_write16(bcm, 0x0043, 0x001F); + } else { + tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F; + bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060); + tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0; + bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009); + } + bcm43xx_phy_write(bcm, 0x005A, 0x0480); + bcm43xx_phy_write(bcm, 0x0059, 0x0810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + udelay(20); + nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (nrssi1 >= 0x0020) + nrssi1 -= 0x0040; + if (nrssi0 == nrssi1) + radio->nrssislope = 0x00010000; + else + radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1); + if (nrssi0 >= -4) { + radio->nrssi[0] = nrssi1; + radio->nrssi[1] = nrssi0; + } + if (phy->rev >= 3) { + bcm43xx_phy_write(bcm, 0x002E, backup[10]); + bcm43xx_phy_write(bcm, 0x002F, backup[11]); + bcm43xx_phy_write(bcm, 0x080F, backup[12]); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]); + } + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF); + } + + bcm43xx_radio_write16(bcm, 0x007A, backup[0]); + bcm43xx_radio_write16(bcm, 0x0052, backup[1]); + bcm43xx_radio_write16(bcm, 0x0043, backup[2]); + bcm43xx_write16(bcm, 0x03E2, backup[7]); + bcm43xx_write16(bcm, 0x03E6, backup[8]); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]); + bcm43xx_phy_write(bcm, 0x0015, backup[3]); + bcm43xx_phy_write(bcm, 0x005A, backup[4]); + bcm43xx_phy_write(bcm, 0x0059, backup[5]); + bcm43xx_phy_write(bcm, 0x0058, backup[6]); + bcm43xx_synth_pu_workaround(bcm, radio->channel); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002)); + bcm43xx_set_original_gains(bcm); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) | 0x8000); + if (phy->rev >= 3) { + bcm43xx_phy_write(bcm, 0x0801, backup[14]); + bcm43xx_phy_write(bcm, 0x0060, backup[15]); + bcm43xx_phy_write(bcm, 0x0014, backup[16]); + bcm43xx_phy_write(bcm, 0x0478, backup[17]); + } + bcm43xx_nrssi_mem_update(bcm); + bcm43xx_calc_nrssi_threshold(bcm); + break; + default: + assert(0); + } +} + +void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + s16 threshold; + s32 a, b; + int tmp; + s16 tmp16; + u16 tmp_u16; + + switch (phy->type) { + case BCM43xx_PHYTYPE_B: { + int radiotype = 0; + + if (phy->rev < 2) + return; + if (radio->version != 0x2050) + return; + if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) + return; + + tmp = radio->revision; + if ((radio->manufact == 0x175 && tmp == 5) || + (radio->manufact == 0x17F && (tmp == 3 || tmp == 4))) + radiotype = 1; + + if (radiotype == 1) { + threshold = bcm->current_core->radio->nrssi[1] - 5; + } else { + threshold = 40 * radio->nrssi[0]; + threshold += 33 * (radio->nrssi[1] - radio->nrssi[0]); + threshold += 20; + threshold /= 10; + } + threshold = limit_value(threshold, 0, 0x3E); + bcm43xx_phy_read(bcm, 0x0020); /* dummy read */ + bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C); + + if (radiotype == 1) { + bcm43xx_phy_write(bcm, 0x0087, 0x0E0D); + bcm43xx_phy_write(bcm, 0x0086, 0x0C0B); + bcm43xx_phy_write(bcm, 0x0085, 0x0A09); + bcm43xx_phy_write(bcm, 0x0084, 0x0808); + bcm43xx_phy_write(bcm, 0x0083, 0x0808); + bcm43xx_phy_write(bcm, 0x0082, 0x0604); + bcm43xx_phy_write(bcm, 0x0081, 0x0302); + bcm43xx_phy_write(bcm, 0x0080, 0x0100); + } + break; + } + case BCM43xx_PHYTYPE_G: + if (!phy->connected || + !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) { + tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20); + if (tmp16 >= 0x20) + tmp16 -= 0x40; + if (tmp16 < 3) { + bcm43xx_phy_write(bcm, 0x048A, + (bcm43xx_phy_read(bcm, 0x048A) + & 0xF000) | 0x09EB); + } else { + bcm43xx_phy_write(bcm, 0x048A, + (bcm43xx_phy_read(bcm, 0x048A) + & 0xF000) | 0x0AED); + } + } else { + tmp = radio->interfmode; + if (tmp == BCM43xx_RADIO_INTERFMODE_NONWLAN) { + a = -13; + b = -17; + } else if (tmp == BCM43xx_RADIO_INTERFMODE_NONE && + !radio->aci_enable) { + a = -13; + b = -10; + } else { + a = -8; + b = -9; + } + a += 0x1B; + a *= radio->nrssi[1] - radio->nrssi[0]; + a += radio->nrssi[0] * 0x40; + a /= 64; + b += 0x1B; + b *= radio->nrssi[1] - radio->nrssi[0]; + b += radio->nrssi[0] * 0x40; + b /= 64; + + a = limit_value(a, -31, 31); + b = limit_value(b, -31, 31); + + tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000; + tmp_u16 |= ((u32)a & 0x003F); + tmp_u16 |= (((u32)b & 0x003F) << 6); + bcm43xx_phy_write(bcm, 0x048A, tmp_u16); + } + break; + default: + assert(0); + } +} + +/* Helper macros to save on and restore values from the radio->interfstack */ +#ifdef stack_save +# undef stack_save +#endif +#ifdef stack_restore +# undef stack_restore +#endif +#define stack_save(value) \ + do { \ + assert(i < ARRAY_SIZE(radio->interfstack)); \ + stack[i++] = (value); \ + } while (0) + +#define stack_restore() \ + ({ \ + assert(i < ARRAY_SIZE(radio->interfstack)); \ + stack[i++]; \ + }) + +static void +bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, + int mode) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + int i = 0; + u16 *stack = radio->interfstack; + u16 tmp, flipped; + + switch (mode) { + case BCM43xx_RADIO_INTERFMODE_NONWLAN: + if (phy->rev != 1) { + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) & 0x0800); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000); + break; + } + tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); + flipped = flip_4bit(tmp); + if ((flipped >> 1) >= 4) + tmp = flipped - 3; + tmp = flip_4bit(tmp); + bcm43xx_radio_write16(bcm, 0x0078, tmp << 1); + + bcm43xx_calc_nrssi_threshold(bcm); + + if (bcm->current_core->rev < 5) { + stack_save(bcm43xx_phy_read(bcm, 0x0406)); + bcm43xx_phy_write(bcm, 0x0406, 0x7E28); + } else { + stack_save(bcm43xx_phy_read(bcm, 0x04C0)); + stack_save(bcm43xx_phy_read(bcm, 0x04C1)); + bcm43xx_phy_write(bcm, 0x04C0, 0x3E04); + bcm43xx_phy_write(bcm, 0x04C1, 0x0640); + } + + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) | 0x0800); + bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000); + + stack_save(bcm43xx_phy_read(bcm, 0x04A0)); + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008); + stack_save(bcm43xx_phy_read(bcm, 0x04A1)); + bcm43xx_phy_write(bcm, 0x04A1, + (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605); + stack_save(bcm43xx_phy_read(bcm, 0x04A2)); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204); + stack_save(bcm43xx_phy_read(bcm, 0x04A8)); + bcm43xx_phy_write(bcm, 0x04A8, + (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0403); + stack_save(bcm43xx_phy_read(bcm, 0x04AB)); + bcm43xx_phy_write(bcm, 0x04AB, + (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0504); + + stack_save(bcm43xx_phy_read(bcm, 0x04A7)); + bcm43xx_phy_write(bcm, 0x04A7, 0x0002); + stack_save(bcm43xx_phy_read(bcm, 0x04A3)); + bcm43xx_phy_write(bcm, 0x04A3, 0x287A); + stack_save(bcm43xx_phy_read(bcm, 0x04A9)); + bcm43xx_phy_write(bcm, 0x04A9, 0x2027); + stack_save(bcm43xx_phy_read(bcm, 0x0493)); + bcm43xx_phy_write(bcm, 0x0493, 0x32F5); + stack_save(bcm43xx_phy_read(bcm, 0x04AA)); + bcm43xx_phy_write(bcm, 0x04AA, 0x2027); + stack_save(bcm43xx_phy_read(bcm, 0x04AC)); + bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); + break; + case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: + if (bcm43xx_phy_read(bcm, 0x0033) == 0x0800) + break; + + radio->aci_enable = 1; + + stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)); + stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)); + if (bcm->current_core->rev < 5) { + stack_save(bcm43xx_phy_read(bcm, 0x0406)); + } else { + stack_save(bcm43xx_phy_read(bcm, 0x04C0)); + stack_save(bcm43xx_phy_read(bcm, 0x04C1)); + } + stack_save(bcm43xx_phy_read(bcm, 0x0033)); + stack_save(bcm43xx_phy_read(bcm, 0x04A7)); + stack_save(bcm43xx_phy_read(bcm, 0x04A3)); + stack_save(bcm43xx_phy_read(bcm, 0x04A9)); + stack_save(bcm43xx_phy_read(bcm, 0x04AA)); + stack_save(bcm43xx_phy_read(bcm, 0x04AC)); + stack_save(bcm43xx_phy_read(bcm, 0x0493)); + stack_save(bcm43xx_phy_read(bcm, 0x04A1)); + stack_save(bcm43xx_phy_read(bcm, 0x04A0)); + stack_save(bcm43xx_phy_read(bcm, 0x04A2)); + stack_save(bcm43xx_phy_read(bcm, 0x048A)); + stack_save(bcm43xx_phy_read(bcm, 0x04A8)); + stack_save(bcm43xx_phy_read(bcm, 0x04AB)); + + bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & 0xEFFF); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xEFFF) | 0x0002); + + bcm43xx_phy_write(bcm, 0x04A7, 0x0800); + bcm43xx_phy_write(bcm, 0x04A3, 0x287A); + bcm43xx_phy_write(bcm, 0x04A9, 0x2027); + bcm43xx_phy_write(bcm, 0x0493, 0x32F5); + bcm43xx_phy_write(bcm, 0x04AA, 0x2027); + bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); + + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFC0) | 0x001A); + if (bcm->current_core->rev < 5) { + bcm43xx_phy_write(bcm, 0x0406, 0x280D); + } else { + bcm43xx_phy_write(bcm, 0x04C0, 0x0640); + bcm43xx_phy_write(bcm, 0x04C1, 0x00A9); + } + + bcm43xx_phy_write(bcm, 0x04A1, + (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0FF) | 0x1800); + bcm43xx_phy_write(bcm, 0x04A1, + (bcm43xx_phy_read(bcm, 0x04A1) & 0xFFC0) | 0x0016); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0900); + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0700); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x000D); + bcm43xx_phy_write(bcm, 0x04A8, + (bcm43xx_phy_read(bcm, 0x04A8) & 0xCFFF) | 0x1000); + bcm43xx_phy_write(bcm, 0x04A8, + (bcm43xx_phy_read(bcm, 0x04A8) & 0xF0FF) | 0x0A00); + bcm43xx_phy_write(bcm, 0x04AB, + (bcm43xx_phy_read(bcm, 0x04AB) & 0xCFFF) | 0x1000); + bcm43xx_phy_write(bcm, 0x04AB, + (bcm43xx_phy_read(bcm, 0x04AB) & 0xF0FF) | 0x0800); + bcm43xx_phy_write(bcm, 0x04AB, + (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFCF) | 0x0010); + bcm43xx_phy_write(bcm, 0x04AB, + (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFF0) | 0x0006); + + bcm43xx_calc_nrssi_slope(bcm); + break; + default: + assert(0); + } +} + +static void +bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, + int mode) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + int i = 0; + u16 *stack = radio->interfstack; + u16 tmp, flipped; + + switch (mode) { + case BCM43xx_RADIO_INTERFMODE_NONWLAN: + if (phy->rev != 1) { + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); + break; + } + tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); + flipped = flip_4bit(tmp); + if ((flipped >> 1) >= 0x000C) + tmp = flipped + 3; + tmp = flip_4bit(tmp); + bcm43xx_radio_write16(bcm, 0x0078, tmp << 1); + + bcm43xx_calc_nrssi_threshold(bcm); + + if (bcm->current_core->rev < 5) { + bcm43xx_phy_write(bcm, 0x0406, stack_restore()); + } else { + bcm43xx_phy_write(bcm, 0x04C0, stack_restore()); + bcm43xx_phy_write(bcm, 0x04C1, stack_restore()); + } + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); + + if (!bcm->bad_frames_preempt) + bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & ~(1 << 11)); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); + bcm43xx_phy_write(bcm, 0x04A0, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A1, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A2, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A8, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AB, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A7, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A3, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A9, stack_restore()); + bcm43xx_phy_write(bcm, 0x0493, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AA, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AC, stack_restore()); + break; + case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: + if (bcm43xx_phy_read(bcm, 0x0033) != 0x0800) + break; + + radio->aci_enable = 0; + + bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, stack_restore()); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, stack_restore()); + if (bcm->current_core->rev < 5) { + bcm43xx_phy_write(bcm, 0x0406, stack_restore()); + } else { + bcm43xx_phy_write(bcm, 0x04C0, stack_restore()); + bcm43xx_phy_write(bcm, 0x04C1, stack_restore()); + } + bcm43xx_phy_write(bcm, 0x0033, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A7, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A3, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A9, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AA, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AC, stack_restore()); + bcm43xx_phy_write(bcm, 0x0493, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A1, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A0, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A2, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A8, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AB, stack_restore()); + + bcm43xx_calc_nrssi_slope(bcm); + break; + default: + assert(0); + } +} + +#undef stack_save +#undef stack_restore + +int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, + int mode) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + int currentmode; + + if ((phy->type != BCM43xx_PHYTYPE_G) || + (phy->rev == 0) || + (!phy->connected)) + return -ENODEV; + + radio->aci_wlan_automatic = 0; + switch (mode) { + case BCM43xx_RADIO_INTERFMODE_AUTOWLAN: + radio->aci_wlan_automatic = 1; + if (radio->aci_enable) + mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; + else + mode = BCM43xx_RADIO_INTERFMODE_NONE; + break; + case BCM43xx_RADIO_INTERFMODE_NONE: + case BCM43xx_RADIO_INTERFMODE_NONWLAN: + case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: + break; + default: + return -EINVAL; + } + + currentmode = radio->interfmode; + if (currentmode == mode) + return 0; + if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE) + bcm43xx_radio_interference_mitigation_disable(bcm, currentmode); + + if (mode == BCM43xx_RADIO_INTERFMODE_NONE) { + radio->aci_enable = 0; + radio->aci_hw_rssi = 0; + } else + bcm43xx_radio_interference_mitigation_enable(bcm, mode); + radio->interfmode = mode; + + return 0; +} + +static u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm) +{ + u16 reg, index, ret; + + reg = bcm43xx_radio_read16(bcm, 0x0060); + index = (reg & 0x001E) >> 1; + ret = rcc_table[index] << 1; + ret |= (reg & 0x0001); + ret |= 0x0020; + + return ret; +} + +u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 backup[19] = { 0 }; + u16 ret; + u16 i, j; + u32 tmp1 = 0, tmp2 = 0; + + backup[0] = bcm43xx_radio_read16(bcm, 0x0043); + backup[14] = bcm43xx_radio_read16(bcm, 0x0051); + backup[15] = bcm43xx_radio_read16(bcm, 0x0052); + backup[1] = bcm43xx_phy_read(bcm, 0x0015); + backup[16] = bcm43xx_phy_read(bcm, 0x005A); + backup[17] = bcm43xx_phy_read(bcm, 0x0059); + backup[18] = bcm43xx_phy_read(bcm, 0x0058); + if (phy->type == BCM43xx_PHYTYPE_B) { + backup[2] = bcm43xx_phy_read(bcm, 0x0030); + backup[3] = bcm43xx_read16(bcm, 0x03EC); + bcm43xx_phy_write(bcm, 0x0030, 0x00FF); + bcm43xx_write16(bcm, 0x03EC, 0x3F3F); + } else { + if (phy->connected) { + backup[4] = bcm43xx_phy_read(bcm, 0x0811); + backup[5] = bcm43xx_phy_read(bcm, 0x0812); + backup[6] = bcm43xx_phy_read(bcm, 0x0814); + backup[7] = bcm43xx_phy_read(bcm, 0x0815); + backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS); + backup[9] = bcm43xx_phy_read(bcm, 0x0802); + bcm43xx_phy_write(bcm, 0x0814, + (bcm43xx_phy_read(bcm, 0x0814) | 0x0003)); + bcm43xx_phy_write(bcm, 0x0815, + (bcm43xx_phy_read(bcm, 0x0815) & 0xFFFC)); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF)); + bcm43xx_phy_write(bcm, 0x0802, + (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC)); + bcm43xx_phy_write(bcm, 0x0811, 0x01B3); + bcm43xx_phy_write(bcm, 0x0812, 0x0FB2); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, + (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000)); + } + backup[10] = bcm43xx_phy_read(bcm, 0x0035); + bcm43xx_phy_write(bcm, 0x0035, + (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F)); + backup[11] = bcm43xx_read16(bcm, 0x03E6); + backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); + + // Initialization + if (phy->version == 0) { + bcm43xx_write16(bcm, 0x03E6, 0x0122); + } else { + if (phy->version >= 2) + bcm43xx_write16(bcm, 0x03E6, 0x0040); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, + (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000)); + } + + ret = bcm43xx_radio_calibrationvalue(bcm); + + if (phy->type == BCM43xx_PHYTYPE_B) + bcm43xx_radio_write16(bcm, 0x0078, 0x0003); + + bcm43xx_phy_write(bcm, 0x0015, 0xBFAF); + bcm43xx_phy_write(bcm, 0x002B, 0x1403); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x00B2); + bcm43xx_phy_write(bcm, 0x0015, 0xBFA0); + bcm43xx_radio_write16(bcm, 0x0051, + (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004)); + bcm43xx_radio_write16(bcm, 0x0052, 0x0000); + bcm43xx_radio_write16(bcm, 0x0043, + bcm43xx_radio_read16(bcm, 0x0043) | 0x0009); + bcm43xx_phy_write(bcm, 0x0058, 0x0000); + + for (i = 0; i < 16; i++) { + bcm43xx_phy_write(bcm, 0x005A, 0x0480); + bcm43xx_phy_write(bcm, 0x0059, 0xC810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); + udelay(10); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); + udelay(10); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); + udelay(10); + tmp1 += bcm43xx_phy_read(bcm, 0x002D); + bcm43xx_phy_write(bcm, 0x0058, 0x0000); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); + } + + tmp1++; + tmp1 >>= 9; + udelay(10); + bcm43xx_phy_write(bcm, 0x0058, 0x0000); + + for (i = 0; i < 16; i++) { + bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020); + backup[13] = bcm43xx_radio_read16(bcm, 0x0078); + udelay(10); + for (j = 0; j < 16; j++) { + bcm43xx_phy_write(bcm, 0x005A, 0x0D80); + bcm43xx_phy_write(bcm, 0x0059, 0xC810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); + udelay(10); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); + udelay(10); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B3); /* 0x30B3 is not a typo */ + bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); + udelay(10); + tmp2 += bcm43xx_phy_read(bcm, 0x002D); + bcm43xx_phy_write(bcm, 0x0058, 0x0000); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); + } + tmp2++; + tmp2 >>= 8; + if (tmp1 < tmp2) + break; + } + + /* Restore the registers */ + bcm43xx_phy_write(bcm, 0x0015, backup[1]); + bcm43xx_radio_write16(bcm, 0x0051, backup[14]); + bcm43xx_radio_write16(bcm, 0x0052, backup[15]); + bcm43xx_radio_write16(bcm, 0x0043, backup[0]); + bcm43xx_phy_write(bcm, 0x005A, backup[16]); + bcm43xx_phy_write(bcm, 0x0059, backup[17]); + bcm43xx_phy_write(bcm, 0x0058, backup[18]); + bcm43xx_write16(bcm, 0x03E6, backup[11]); + if (phy->version != 0) + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]); + bcm43xx_phy_write(bcm, 0x0035, backup[10]); + bcm43xx_radio_selectchannel(bcm, radio->channel, 1); + if (phy->type == BCM43xx_PHYTYPE_B) { + bcm43xx_phy_write(bcm, 0x0030, backup[2]); + bcm43xx_write16(bcm, 0x03EC, backup[3]); + } else { + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, + (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) & 0x7FFF)); + if (phy->connected) { + bcm43xx_phy_write(bcm, 0x0811, backup[4]); + bcm43xx_phy_write(bcm, 0x0812, backup[5]); + bcm43xx_phy_write(bcm, 0x0814, backup[6]); + bcm43xx_phy_write(bcm, 0x0815, backup[7]); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]); + bcm43xx_phy_write(bcm, 0x0802, backup[9]); + } + } + if (i >= 15) + ret = backup[13]; + + return ret; +} + +void bcm43xx_radio_init2060(struct bcm43xx_private *bcm) +{ + int err; + + bcm43xx_radio_write16(bcm, 0x0004, 0x00C0); + bcm43xx_radio_write16(bcm, 0x0005, 0x0008); + bcm43xx_radio_write16(bcm, 0x0009, 0x0040); + bcm43xx_radio_write16(bcm, 0x0005, 0x00AA); + bcm43xx_radio_write16(bcm, 0x0032, 0x008F); + bcm43xx_radio_write16(bcm, 0x0006, 0x008F); + bcm43xx_radio_write16(bcm, 0x0034, 0x008F); + bcm43xx_radio_write16(bcm, 0x002C, 0x0007); + bcm43xx_radio_write16(bcm, 0x0082, 0x0080); + bcm43xx_radio_write16(bcm, 0x0080, 0x0000); + bcm43xx_radio_write16(bcm, 0x003F, 0x00DA); + bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008); + bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010); + bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020); + bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020); + udelay(400); + + bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010); + udelay(400); + + bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008); + bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010); + bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008); + bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040); + bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040); + bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008); + bcm43xx_phy_write(bcm, 0x0063, 0xDDC6); + bcm43xx_phy_write(bcm, 0x0069, 0x07BE); + bcm43xx_phy_write(bcm, 0x006A, 0x0000); + + err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0); + assert(err == 0); + udelay(1000); +} + +static inline +u16 freq_r3A_value(u16 frequency) +{ + u16 value; + + if (frequency < 5091) + value = 0x0040; + else if (frequency < 5321) + value = 0x0000; + else if (frequency < 5806) + value = 0x0080; + else + value = 0x0040; + + return value; +} + +void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm) +{ + static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; + static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; + u16 tmp = bcm43xx_radio_read16(bcm, 0x001E); + int i, j; + + for (i = 0; i < 5; i++) { + for (j = 0; j < 5; j++) { + if (tmp == (data_high[i] << 4 | data_low[j])) { + bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0); + return; + } + } + } +} + +int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, + u8 channel, + int synthetic_pu_workaround) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 r8, tmp; + u16 freq; + + if ((radio->manufact == 0x17F) && + (radio->version == 0x2060) && + (radio->revision == 1)) { + if (channel > 200) + return -EINVAL; + freq = channel2freq_a(channel); + + r8 = bcm43xx_radio_read16(bcm, 0x0008); + bcm43xx_write16(bcm, 0x03F0, freq); + bcm43xx_radio_write16(bcm, 0x0008, r8); + + TODO();//TODO: write max channel TX power? to Radio 0x2D + tmp = bcm43xx_radio_read16(bcm, 0x002E); + tmp &= 0x0080; + TODO();//TODO: OR tmp with the Power out estimation for this channel? + bcm43xx_radio_write16(bcm, 0x002E, tmp); + + if (freq >= 4920 && freq <= 5500) { + /* + * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F; + * = (freq * 0.025862069 + */ + r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */ + } + bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8); + bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8); + bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8); + bcm43xx_radio_write16(bcm, 0x0022, + (bcm43xx_radio_read16(bcm, 0x0022) + & 0x000F) | (r8 << 4)); + bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4)); + bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4)); + bcm43xx_radio_write16(bcm, 0x0008, + (bcm43xx_radio_read16(bcm, 0x0008) + & 0x00F0) | (r8 << 4)); + bcm43xx_radio_write16(bcm, 0x0029, + (bcm43xx_radio_read16(bcm, 0x0029) + & 0xFF0F) | 0x00B0); + bcm43xx_radio_write16(bcm, 0x0035, 0x00AA); + bcm43xx_radio_write16(bcm, 0x0036, 0x0085); + bcm43xx_radio_write16(bcm, 0x003A, + (bcm43xx_radio_read16(bcm, 0x003A) + & 0xFF20) | freq_r3A_value(freq)); + bcm43xx_radio_write16(bcm, 0x003D, + bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF); + bcm43xx_radio_write16(bcm, 0x0081, + (bcm43xx_radio_read16(bcm, 0x0081) + & 0xFF7F) | 0x0080); + bcm43xx_radio_write16(bcm, 0x0035, + bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF); + bcm43xx_radio_write16(bcm, 0x0035, + (bcm43xx_radio_read16(bcm, 0x0035) + & 0xFFEF) | 0x0010); + bcm43xx_radio_set_tx_iq(bcm); + TODO(); //TODO: TSSI2dbm workaround + bcm43xx_phy_xmitpower(bcm);//FIXME correct? + } else { + if ((channel < 1) || (channel > 14)) + return -EINVAL; + + if (synthetic_pu_workaround) + bcm43xx_synth_pu_workaround(bcm, channel); + + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, + channel2freq_bg(channel)); + + if (channel == 14) { + if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) { + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET) + & ~(1 << 7)); + } else { + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET) + | (1 << 7)); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, + bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) + | (1 << 11)); + } else { + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, + bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) + & 0xF7BF); + } + } + + radio->channel = channel; + //XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states + // that 2000 usecs might suffice. + udelay(8000); + + return 0; +} + +void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val) +{ + u16 tmp; + + val <<= 8; + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF; + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val); + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF; + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val); + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF; + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val); +} + +/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */ +static u16 bcm43xx_get_txgain_base_band(u16 txpower) +{ + u16 ret; + + assert(txpower <= 63); + + if (txpower >= 54) + ret = 2; + else if (txpower >= 49) + ret = 4; + else if (txpower >= 44) + ret = 5; + else + ret = 6; + + return ret; +} + +/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */ +static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower) +{ + u16 ret; + + assert(txpower <= 63); + + if (txpower >= 32) + ret = 0; + else if (txpower >= 25) + ret = 1; + else if (txpower >= 20) + ret = 2; + else if (txpower >= 12) + ret = 3; + else + ret = 4; + + return ret; +} + +/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */ +static u16 bcm43xx_get_txgain_dac(u16 txpower) +{ + u16 ret; + + assert(txpower <= 63); + + if (txpower >= 54) + ret = txpower - 53; + else if (txpower >= 49) + ret = txpower - 42; + else if (txpower >= 44) + ret = txpower - 37; + else if (txpower >= 32) + ret = txpower - 32; + else if (txpower >= 25) + ret = txpower - 20; + else if (txpower >= 20) + ret = txpower - 13; + else if (txpower >= 12) + ret = txpower - 8; + else + ret = txpower; + + return ret; +} + +void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) +{ + u16 pamp, base, dac, ilt; + + txpower = limit_value(txpower, 0, 63); + + pamp = bcm43xx_get_txgain_freq_power_amp(txpower); + pamp <<= 5; + pamp &= 0x00E0; + bcm43xx_phy_write(bcm, 0x0019, pamp); + + base = bcm43xx_get_txgain_base_band(txpower); + base &= 0x000F; + bcm43xx_phy_write(bcm, 0x0017, base | 0x0020); + + ilt = bcm43xx_ilt_read16(bcm, 0x3001); + ilt &= 0x0007; + + dac = bcm43xx_get_txgain_dac(txpower); + dac <<= 3; + dac |= ilt; + + bcm43xx_ilt_write16(bcm, 0x3001, dac); + + bcm->current_core->radio->txpower[0] = txpower; + + TODO(); + //TODO: FuncPlaceholder (Adjust BB loft cancel) +} + +void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, + u16 baseband_attenuation, u16 radio_attenuation, + u16 txpower) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + + if (baseband_attenuation == 0xFFFF) + baseband_attenuation = radio->txpower[0]; + else + radio->txpower[0] = baseband_attenuation; + if (radio_attenuation == 0xFFFF) + radio_attenuation = radio->txpower[1]; + else + radio->txpower[1] = radio_attenuation; + if (txpower == 0xFFFF) + txpower = radio->txpower[2]; + else + radio->txpower[2] = txpower; + + assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11); + if (radio->revision < 6) + assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9); + else + assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31); + assert(/*txpower >= 0 &&*/ txpower <= 7); + + bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation); + bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation); + if (radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x0052, + (bcm43xx_radio_read16(bcm, 0x0052) & 0xFF8F) + | (txpower << 4)); + } + if (phy->type == BCM43xx_PHYTYPE_G) + bcm43xx_phy_lo_adjust(bcm, 0); +} + + +void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + int err; + + if (radio->enabled) + return; + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + bcm43xx_radio_write16(bcm, 0x0004, 0x00C0); + bcm43xx_radio_write16(bcm, 0x0005, 0x0008); + bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7); + bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7); + bcm43xx_radio_init2060(bcm); + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + bcm43xx_phy_write(bcm, 0x0015, 0x8000); + bcm43xx_phy_write(bcm, 0x0015, 0xCC00); + bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000)); + err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1); + assert(err == 0); + break; + default: + assert(0); + } + radio->enabled = 1; + dprintk(KERN_INFO PFX "Radio turned on\n"); +} + +void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + + if (phy->type == BCM43xx_PHYTYPE_A) { + bcm43xx_radio_write16(bcm, 0x0004, 0x00FF); + bcm43xx_radio_write16(bcm, 0x0005, 0x00FB); + bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008); + bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008); + } + if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) { + bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C); + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73); + } else + bcm43xx_phy_write(bcm, 0x0015, 0xAA00); + radio->enabled = 0; + dprintk(KERN_INFO PFX "Radio turned off\n"); +} + +void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm) +{ + switch (bcm->current_core->phy->type) { + case BCM43xx_PHYTYPE_A: + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F); + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F); + break; + } +} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h new file mode 100644 index 000000000000..89fe29282140 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h @@ -0,0 +1,93 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef BCM43xx_RADIO_H_ +#define BCM43xx_RADIO_H_ + +#include "bcm43xx.h" + + +#define BCM43xx_RADIO_DEFAULT_CHANNEL_A 36 +#define BCM43xx_RADIO_DEFAULT_CHANNEL_BG 6 + +/* Force antenna 0. */ +#define BCM43xx_RADIO_TXANTENNA_0 0 +/* Force antenna 1. */ +#define BCM43xx_RADIO_TXANTENNA_1 1 +/* Use the RX antenna, that was selected for the most recently + * received good PLCP header. + */ +#define BCM43xx_RADIO_TXANTENNA_LASTPLCP 3 +#define BCM43xx_RADIO_TXANTENNA_DEFAULT BCM43xx_RADIO_TXANTENNA_LASTPLCP + +#define BCM43xx_RADIO_INTERFMODE_NONE 0 +#define BCM43xx_RADIO_INTERFMODE_NONWLAN 1 +#define BCM43xx_RADIO_INTERFMODE_MANUALWLAN 2 +#define BCM43xx_RADIO_INTERFMODE_AUTOWLAN 3 + + +void bcm43xx_radio_lock(struct bcm43xx_private *bcm); +void bcm43xx_radio_unlock(struct bcm43xx_private *bcm); + +u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset); +void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val); + +u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm); +void bcm43xx_radio_init2060(struct bcm43xx_private *bcm); + +void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm); +void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm); + +int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel, + int synthetic_pu_workaround); + +void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower); +void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, + u16 baseband_attenuation, u16 attenuation, + u16 txpower); +void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val); + +void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm); + +u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel); +u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm); + +int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode); + +void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm); +void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm); +s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset); +void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val); +void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val); +void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm); + +void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm); + +#endif /* BCM43xx_RADIO_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c new file mode 100644 index 000000000000..fe6409a90901 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -0,0 +1,1099 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include +#include +#include +#include /* for capable() */ +#include + +#include "bcm43xx.h" +#include "bcm43xx_wx.h" +#include "bcm43xx_main.h" +#include "bcm43xx_radio.h" + +/* Define to enable a printk on each wx handler function invocation */ +//#define BCM43xx_WX_DEBUG + + +#ifdef BCM43xx_WX_DEBUG +# define printk_wx printk +#else +# define printk_wx(x...) do { /* nothing */ } while (0) +#endif +#define wx_enter() printk_wx(KERN_INFO PFX "WX handler called: %s\n", __FUNCTION__); + +#define MAX_WX_STRING 80 + + +static int bcm43xx_wx_get_name(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int i, nr_80211; + struct bcm43xx_phyinfo *phy; + char suffix[7] = { 0 }; + int have_a = 0, have_b = 0, have_g = 0; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + nr_80211 = bcm43xx_num_80211_cores(bcm); + for (i = 0; i < nr_80211; i++) { + phy = bcm->phy + i; + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + have_a = 1; + break; + case BCM43xx_PHYTYPE_G: + have_g = 1; + case BCM43xx_PHYTYPE_B: + have_b = 1; + break; + default: + assert(0); + } + } + spin_unlock_irqrestore(&bcm->lock, flags); + + i = 0; + if (have_a) { + suffix[i++] = 'a'; + suffix[i++] = '/'; + } + if (have_b) { + suffix[i++] = 'b'; + suffix[i++] = '/'; + } + if (have_g) { + suffix[i++] = 'g'; + suffix[i++] = '/'; + } + if (i != 0) + suffix[i - 1] = '\0'; + + snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix); + + return 0; +} + +static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct ieee80211softmac_device *softmac = bcm->softmac; + unsigned long flags; + u8 channel; + int freq; + int err = 0; + + wx_enter(); + + if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { + channel = data->freq.m; + freq = bcm43xx_channel_to_freq(bcm, channel); + } else { + channel = bcm43xx_freq_to_channel(bcm, data->freq.m); + freq = data->freq.m; + } + if (!bcm43xx_is_valid_channel(bcm, channel)) + return -EINVAL; + + spin_lock_irqsave(&bcm->lock, flags); + if (bcm->initialized) { + //ieee80211softmac_disassoc(softmac, $REASON); + bcm43xx_mac_suspend(bcm); + err = bcm43xx_radio_selectchannel(bcm, channel, 0); + bcm43xx_mac_enable(bcm); + } else + bcm->current_core->radio->initial_channel = channel; + spin_unlock_irqrestore(&bcm->lock, flags); + if (!err) + printk_wx(KERN_INFO PFX "Selected channel: %d\n", channel); + + return err; +} + +static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int err = -ENODEV; + u16 channel; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + channel = bcm->current_core->radio->channel; + if (channel == 0xFF) { + assert(!bcm->initialized); + channel = bcm->current_core->radio->initial_channel; + if (channel == 0xFF) + goto out_unlock; + } + assert(channel > 0 && channel <= 1000); + data->freq.e = 1; + data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000; + data->freq.flags = 1; + + err = 0; +out_unlock: + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static int bcm43xx_wx_set_mode(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int mode; + + wx_enter(); + + mode = data->mode; + if (mode == IW_MODE_AUTO) + mode = BCM43xx_INITIAL_IWMODE; + + spin_lock_irqsave(&bcm->lock, flags); + if (bcm->ieee->iw_mode != mode) + bcm43xx_set_iwmode(bcm, mode); + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_get_mode(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + data->mode = bcm->ieee->iw_mode; + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_sensitivity(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_get_sensitivity(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct iw_range *range = (struct iw_range *)extra; + const struct ieee80211_geo *geo; + unsigned long flags; + int i, j; + + wx_enter(); + + data->data.length = sizeof(*range); + memset(range, 0, sizeof(*range)); + + //TODO: What about 802.11b? + /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */ + range->throughput = 27 * 1000 * 1000; + + range->max_qual.qual = 100; + /* TODO: Real max RSSI */ + range->max_qual.level = 0; + range->max_qual.noise = 0; + range->max_qual.updated = 7; + + range->avg_qual.qual = 70; + range->avg_qual.level = 0; + range->avg_qual.noise = 0; + range->avg_qual.updated = 7; + + range->min_rts = BCM43xx_MIN_RTS_THRESHOLD; + range->max_rts = BCM43xx_MAX_RTS_THRESHOLD; + range->min_frag = MIN_FRAG_THRESHOLD; + range->max_frag = MAX_FRAG_THRESHOLD; + + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + range->num_encoding_sizes = 2; + range->max_encoding_tokens = WEP_KEYS; + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 16; + + spin_lock_irqsave(&bcm->lock, flags); + + range->num_bitrates = 0; + i = 0; + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A || + bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + range->num_bitrates = 8; + range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB; + } + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B || + bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + range->num_bitrates += 4; + range->bitrate[i++] = IEEE80211_CCK_RATE_1MB; + range->bitrate[i++] = IEEE80211_CCK_RATE_2MB; + range->bitrate[i++] = IEEE80211_CCK_RATE_5MB; + range->bitrate[i++] = IEEE80211_CCK_RATE_11MB; + } + + geo = ieee80211_get_geo(bcm->ieee); + range->num_channels = geo->a_channels + geo->bg_channels; + j = 0; + for (i = 0; i < geo->a_channels; i++) { + if (j == IW_MAX_FREQUENCIES) + break; + range->freq[j].i = j + 1; + range->freq[j].m = geo->a[i].freq;//FIXME? + range->freq[j].e = 1; + j++; + } + for (i = 0; i < geo->bg_channels; i++) { + if (j == IW_MAX_FREQUENCIES) + break; + range->freq[j].i = j + 1; + range->freq[j].m = geo->bg[i].freq;//FIXME? + range->freq[j].e = 1; + j++; + } + range->num_frequency = j; + + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_nick(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + size_t len; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); + memcpy(bcm->nick, extra, len); + bcm->nick[len] = '\0'; + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_get_nick(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + size_t len; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + len = strlen(bcm->nick) + 1; + memcpy(extra, bcm->nick, len); + data->data.length = (__u16)len; + data->data.flags = 1; + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_rts(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int err = -EINVAL; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + if (data->rts.disabled) { + bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; + err = 0; + } else { + if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD && + data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) { + bcm->rts_threshold = data->rts.value; + err = 0; + } + } + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static int bcm43xx_wx_get_rts(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + data->rts.value = bcm->rts_threshold; + data->rts.fixed = 0; + data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_frag(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int err = -EINVAL; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + if (data->frag.disabled) { + bcm->ieee->fts = MAX_FRAG_THRESHOLD; + err = 0; + } else { + if (data->frag.value >= MIN_FRAG_THRESHOLD && + data->frag.value <= MAX_FRAG_THRESHOLD) { + bcm->ieee->fts = data->frag.value & ~0x1; + err = 0; + } + } + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static int bcm43xx_wx_get_frag(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + data->frag.value = bcm->ieee->fts; + data->frag.fixed = 0; + data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int err = -ENODEV; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + if (!bcm->initialized) + goto out_unlock; + if (data->power.disabled != (!(bcm->current_core->radio->enabled))) { + if (data->power.disabled) + bcm43xx_radio_turn_off(bcm); + else + bcm43xx_radio_turn_on(bcm); + } + //TODO: set txpower. + err = 0; + +out_unlock: + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); +//TODO data->power.value = ??? + data->power.fixed = 1; + data->power.flags = IW_TXPOW_DBM; + data->power.disabled = !(bcm->current_core->radio->enabled); + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_retry(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_get_retry(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_set_encoding(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err; + + wx_enter(); + + err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra); + + return err; +} + +static int bcm43xx_wx_set_encodingext(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err; + + wx_enter(); + + err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra); + + return err; +} + +static int bcm43xx_wx_get_encoding(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err; + + wx_enter(); + + err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra); + + return err; +} + +static int bcm43xx_wx_get_encodingext(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err; + + wx_enter(); + + err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra); + + return err; +} + +static int bcm43xx_wx_set_power(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_get_power(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int mode, err = 0; + + wx_enter(); + + mode = *((int *)extra); + switch (mode) { + case 0: + mode = BCM43xx_RADIO_INTERFMODE_NONE; + break; + case 1: + mode = BCM43xx_RADIO_INTERFMODE_NONWLAN; + break; + case 2: + mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; + break; + case 3: + mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; + break; + default: + printk(KERN_ERR PFX "set_interfmode allowed parameters are: " + "0 => None, 1 => Non-WLAN, 2 => WLAN, " + "3 => Auto-WLAN\n"); + return -EINVAL; + } + + spin_lock_irqsave(&bcm->lock, flags); + if (bcm->initialized) { + err = bcm43xx_radio_set_interference_mitigation(bcm, mode); + if (err) { + printk(KERN_ERR PFX "Interference Mitigation not " + "supported by device\n"); + } + } else { + if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) { + printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN " + "not supported while the interface is down.\n"); + err = -ENODEV; + } else + bcm->current_core->radio->interfmode = mode; + } + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int mode; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + mode = bcm->current_core->radio->interfmode; + spin_unlock_irqrestore(&bcm->lock, flags); + + switch (mode) { + case BCM43xx_RADIO_INTERFMODE_NONE: + strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING); + break; + case BCM43xx_RADIO_INTERFMODE_NONWLAN: + strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING); + break; + case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: + strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING); + break; + default: + assert(0); + } + data->data.length = strlen(extra) + 1; + + return 0; +} + +static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int on; + + wx_enter(); + + on = *((int *)extra); + spin_lock_irqsave(&bcm->lock, flags); + bcm->short_preamble = !!on; + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int on; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + on = bcm->short_preamble; + spin_unlock_irqrestore(&bcm->lock, flags); + + if (on) + strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); + else + strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING); + data->data.length = strlen(extra) + 1; + + return 0; +} + +static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int on; + + wx_enter(); + + on = *((int *)extra); + spin_lock_irqsave(&bcm->lock, flags); + bcm->ieee->host_encrypt = !!on; + bcm->ieee->host_decrypt = !!on; + bcm->ieee->host_build_iv = !on; + + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int on; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + on = bcm->ieee->host_encrypt; + spin_unlock_irqrestore(&bcm->lock, flags); + + if (on) + strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); + else + strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING); + data->data.length = strlen(extra + 1); + + return 0; +} + +/* Enough buffer to hold a hexdump of the sprom data. */ +#define SPROM_BUFFERSIZE 512 + +static int sprom2hex(const u16 *sprom, char *dump) +{ + int i, pos = 0; + + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { + pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1, + "%04X", swab16(sprom[i]) & 0xFFFF); + } + + return pos + 1; +} + +static int hex2sprom(u16 *sprom, const char *dump, unsigned int len) +{ + char tmp[5] = { 0 }; + int cnt = 0; + unsigned long parsed; + u8 crc, expected_crc; + + if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2) + return -EINVAL; + while (cnt < BCM43xx_SPROM_SIZE) { + memcpy(tmp, dump, 4); + dump += 4; + parsed = simple_strtoul(tmp, NULL, 16); + sprom[cnt++] = swab16((u16)parsed); + } + + crc = bcm43xx_sprom_crc(sprom); + expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; + if (crc != expected_crc) { + printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n"); + return -EINVAL; + } + + return 0; +} + +static int bcm43xx_wx_sprom_read(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err = -EPERM, i; + u16 *sprom; + unsigned long flags; + + if (!capable(CAP_SYS_RAWIO)) + goto out; + + err = -ENOMEM; + sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), + GFP_KERNEL); + if (!sprom) + goto out; + + spin_lock_irqsave(&bcm->lock, flags); + err = -ENODEV; + if (!bcm->initialized) { + spin_unlock_irqrestore(&bcm->lock, flags); + goto out_kfree; + } + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) + sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); + spin_unlock_irqrestore(&bcm->lock, flags); + + data->data.length = sprom2hex(sprom, extra); + + err = 0; +out_kfree: + kfree(sprom); +out: + return err; +} + +static int bcm43xx_wx_sprom_write(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err = -EPERM; + u16 *sprom; + unsigned long flags; + char *input; + unsigned int len; + u32 spromctl; + int i; + + if (!capable(CAP_SYS_RAWIO)) + goto out; + + err = -ENOMEM; + sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), + GFP_KERNEL); + if (!sprom) + goto out; + + len = data->data.length; + extra[len - 1] = '\0'; + input = strchr(extra, ':'); + if (input) { + input++; + len -= input - extra; + } else + input = extra; + err = hex2sprom(sprom, input, len); + if (err) + goto out_kfree; + + spin_lock_irqsave(&bcm->lock, flags); + err = -ENODEV; + if (!bcm->initialized) { + spin_unlock_irqrestore(&bcm->lock, flags); + goto out_kfree; + } + + printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl); + if (err) { + printk(KERN_ERR PFX "Could not access SPROM control register.\n"); + goto out_unlock; + } + spromctl |= 0x10; /* SPROM WRITE enable. */ + bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); + if (err) { + printk(KERN_ERR PFX "Could not access SPROM control register.\n"); + goto out_unlock; + } + /* We must burn lots of CPU cycles here, but that does not + * really matter as one does not write the SPROM every other minute... + */ + printk(KERN_INFO PFX "[ 0%%"); + mdelay(500); + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { + if (i == 16) + printk("25%%"); + else if (i == 32) + printk("50%%"); + else if (i == 48) + printk("75%%"); + else if (i % 2) + printk("."); +//TODO bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); + mdelay(20); + } + spromctl &= ~0x10; /* SPROM WRITE enable. */ + bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); + if (err) { + printk(KERN_ERR PFX "Could not access SPROM control register.\n"); + goto out_unlock; + } + mdelay(500); + printk("100%% ]\n"); + printk(KERN_INFO PFX "SPROM written.\n"); + err = 0; +out_unlock: + spin_unlock_irqrestore(&bcm->lock, flags); +out_kfree: + kfree(sprom); +out: + return err; +} + + +#ifdef WX +# undef WX +#endif +#define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT] +static const iw_handler bcm43xx_wx_handlers[] = { + /* Wireless Identification */ + WX(SIOCGIWNAME) = bcm43xx_wx_get_name, + /* Basic operations */ + WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq, + WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq, + WX(SIOCSIWMODE) = bcm43xx_wx_set_mode, + WX(SIOCGIWMODE) = bcm43xx_wx_get_mode, + /* Informative stuff */ + WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams, + /* Access Point manipulation */ + WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap, + WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap, + WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan, + WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results, + /* 802.11 specific support */ + WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid, + WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid, + WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick, + WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick, + /* Other parameters */ + WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate, + WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate, + WX(SIOCSIWRTS) = bcm43xx_wx_set_rts, + WX(SIOCGIWRTS) = bcm43xx_wx_get_rts, + WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag, + WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag, + WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower, + WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower, +//TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry, +//TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry, + /* Encoding */ + WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding, + WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding, + WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext, + WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext, + /* Power saving */ +//TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power, +//TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power, + WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie, + WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie, + WX(SIOCSIWAUTH) = ieee80211_wx_set_auth, + WX(SIOCGIWAUTH) = ieee80211_wx_get_auth, +}; +#undef WX + +static const iw_handler bcm43xx_priv_wx_handlers[] = { + /* Set Interference Mitigation Mode. */ + bcm43xx_wx_set_interfmode, + /* Get Interference Mitigation Mode. */ + bcm43xx_wx_get_interfmode, + /* Enable/Disable Short Preamble mode. */ + bcm43xx_wx_set_shortpreamble, + /* Get Short Preamble mode. */ + bcm43xx_wx_get_shortpreamble, + /* Enable/Disable Software Encryption mode */ + bcm43xx_wx_set_swencryption, + /* Get Software Encryption mode */ + bcm43xx_wx_get_swencryption, + /* Write SRPROM data. */ + bcm43xx_wx_sprom_write, + /* Read SPROM data. */ + bcm43xx_wx_sprom_read, +}; + +#define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0) +#define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1) +#define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2) +#define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3) +#define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4) +#define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5) +#define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6) +#define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7) + +#define PRIV_WX_DUMMY(ioctl) \ + { \ + .cmd = (ioctl), \ + .name = "__unused" \ + } + +static const struct iw_priv_args bcm43xx_priv_wx_args[] = { + { + .cmd = PRIV_WX_SET_INTERFMODE, + .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + .name = "set_interfmode", + }, + { + .cmd = PRIV_WX_GET_INTERFMODE, + .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, + .name = "get_interfmode", + }, + { + .cmd = PRIV_WX_SET_SHORTPREAMBLE, + .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + .name = "set_shortpreambl", + }, + { + .cmd = PRIV_WX_GET_SHORTPREAMBLE, + .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, + .name = "get_shortpreambl", + }, + { + .cmd = PRIV_WX_SET_SWENCRYPTION, + .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + .name = "set_swencryption", + }, + { + .cmd = PRIV_WX_GET_SWENCRYPTION, + .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, + .name = "get_swencryption", + }, + { + .cmd = PRIV_WX_SPROM_WRITE, + .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE, + .name = "write_sprom", + }, + { + .cmd = PRIV_WX_SPROM_READ, + .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE, + .name = "read_sprom", + }, +}; + +const struct iw_handler_def bcm43xx_wx_handlers_def = { + .standard = bcm43xx_wx_handlers, + .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers), + .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers), + .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args), + .private = bcm43xx_priv_wx_handlers, + .private_args = bcm43xx_priv_wx_args, +}; + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h new file mode 100644 index 000000000000..1f29ff3aa4c3 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h @@ -0,0 +1,36 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef BCM43xx_WX_H_ +#define BCM43xx_WX_H_ + +extern const struct iw_handler_def bcm43xx_wx_handlers_def; + +#endif /* BCM43xx_WX_H_ */ -- cgit v1.2.3-59-g8ed1b From 70e5e983f8a3f801a96bfeb0682cd2955ec3c8ce Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 23 Jan 2006 17:00:39 -0500 Subject: [PATCH] bcm43xx: patch Kconfig and wireless/Makefile for import Patch Kconfig and wireless/Makefile to merge bcm43xx 'properly' Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 8 ++++++++ drivers/net/wireless/Makefile | 1 + 2 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index fd17aa8491b6..7c7dca112bf5 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -501,6 +501,14 @@ config PRISM54 source "drivers/net/wireless/hostap/Kconfig" +config BCM43XX + tristate "Broadcom BCM43xx wireless support" + depends on PCI && IEEE80211 && NET_RADIO && IEEE80211_SOFTMAC && EXPERIMENTAL + select FW_LOADER + ---help--- + This is an experimental driver for the Broadcom 43xx wireless chip, + found in the Apple Airport Extreme and various other devices. + # yes, this works even when no drivers are selected config NET_WIRELESS bool diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 3a6f7ba326ca..c86779879361 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o obj-$(CONFIG_PRISM54) += prism54/ obj-$(CONFIG_HOSTAP) += hostap/ +obj-$(CONFIG_BCM43XX) += bcm43xx/ # 16-bit wireless PCMCIA client drivers obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o -- cgit v1.2.3-59-g8ed1b From ea72ab229fe9cdfe3d3f70a6e64d98c725294b24 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 27 Jan 2006 17:26:20 +0100 Subject: [PATCH] bcm43xx: sync with svn.berlios.de Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 198 ++++++++++++--------------- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 11 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 7 +- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 8 +- 5 files changed, 102 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index df19fbfa9ea1..af5c27f9bfda 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -214,7 +214,9 @@ static int alloc_ringmemory(struct bcm43xx_dmaring *ring) return -ENOMEM; } if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) { - printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G\n"); + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G " + "(0x%08x, len: %lu)\n", + ring->dmabase, BCM43xx_DMA_RINGMEMSIZE); dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, ring->vbase, ring->dmabase); return -ENOMEM; @@ -261,13 +263,6 @@ int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, return 0; } -static inline int dmacontroller_rx_reset(struct bcm43xx_dmaring *ring) -{ - assert(!ring->tx); - - return bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base); -} - /* Reset the RX DMA channel */ int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, u16 mmio_base) @@ -308,13 +303,6 @@ int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, return 0; } -static inline int dmacontroller_tx_reset(struct bcm43xx_dmaring *ring) -{ - assert(ring->tx); - - return bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base); -} - static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, struct bcm43xx_dmadesc *desc, struct bcm43xx_dmadesc_meta *meta, @@ -337,7 +325,9 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, if (unlikely(dmaaddr + ring->rx_buffersize > BCM43xx_DMA_BUSADDRMAX)) { unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); dev_kfree_skb_any(skb); - printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G\n"); + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G " + "(0x%08x, len: %u)\n", + dmaaddr, ring->rx_buffersize); return -ENOMEM; } meta->skb = skb; @@ -365,7 +355,7 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring) { int i, err = -ENOMEM; - struct bcm43xx_dmadesc *desc = NULL; + struct bcm43xx_dmadesc *desc; struct bcm43xx_dmadesc_meta *meta; for (i = 0; i < ring->nr_slots; i++) { @@ -375,24 +365,20 @@ static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring) err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); if (err) goto err_unwind; - - assert(ring->used_slots <= ring->nr_slots); } ring->used_slots = ring->nr_slots; - err = 0; out: return err; err_unwind: - for ( ; i >= 0; i--) { + for (i--; i >= 0; i--) { desc = ring->vbase + i; meta = ring->meta + i; unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); dev_kfree_skb(meta->skb); } - ring->used_slots = 0; goto out; } @@ -442,13 +428,13 @@ out: static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring) { if (ring->tx) { - dmacontroller_tx_reset(ring); + bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base); /* Zero out Transmit Descriptor ring address. */ bcm43xx_write32(ring->bcm, ring->mmio_base + BCM43xx_DMA_TX_DESC_RING, 0x00000000); } else { - dmacontroller_rx_reset(ring); + bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base); /* Zero out Receive Descriptor ring address. */ bcm43xx_write32(ring->bcm, ring->mmio_base + BCM43xx_DMA_RX_DESC_RING, @@ -508,9 +494,7 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm, if (bcm->pci_dev->bus->number == 0) ring->memoffset = 0; #endif - - - spin_lock_init(&ring->lock); + ring->bcm = bcm; ring->nr_slots = nr_descriptor_slots; ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100; @@ -578,22 +562,25 @@ static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring) void bcm43xx_dma_free(struct bcm43xx_private *bcm) { - bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring1); - bcm->current_core->dma->rx_ring1 = NULL; - bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring0); - bcm->current_core->dma->rx_ring0 = NULL; - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring3); - bcm->current_core->dma->tx_ring3 = NULL; - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring2); - bcm->current_core->dma->tx_ring2 = NULL; - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring1); - bcm->current_core->dma->tx_ring1 = NULL; - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring0); - bcm->current_core->dma->tx_ring0 = NULL; + struct bcm43xx_dma *dma = bcm->current_core->dma; + + bcm43xx_destroy_dmaring(dma->rx_ring1); + dma->rx_ring1 = NULL; + bcm43xx_destroy_dmaring(dma->rx_ring0); + dma->rx_ring0 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring3); + dma->tx_ring3 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring2); + dma->tx_ring2 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring1); + dma->tx_ring1 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring0); + dma->tx_ring0 = NULL; } int bcm43xx_dma_init(struct bcm43xx_private *bcm) { + struct bcm43xx_dma *dma = bcm->current_core->dma; struct bcm43xx_dmaring *ring; int err = -ENOMEM; @@ -602,39 +589,39 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm) BCM43xx_TXRING_SLOTS, 1); if (!ring) goto out; - bcm->current_core->dma->tx_ring0 = ring; + dma->tx_ring0 = ring; ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA2_BASE, BCM43xx_TXRING_SLOTS, 1); if (!ring) goto err_destroy_tx0; - bcm->current_core->dma->tx_ring1 = ring; + dma->tx_ring1 = ring; ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA3_BASE, BCM43xx_TXRING_SLOTS, 1); if (!ring) goto err_destroy_tx1; - bcm->current_core->dma->tx_ring2 = ring; + dma->tx_ring2 = ring; ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, BCM43xx_TXRING_SLOTS, 1); if (!ring) goto err_destroy_tx2; - bcm->current_core->dma->tx_ring3 = ring; + dma->tx_ring3 = ring; /* setup RX DMA channels. */ ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE, BCM43xx_RXRING_SLOTS, 0); if (!ring) goto err_destroy_tx3; - bcm->current_core->dma->rx_ring0 = ring; + dma->rx_ring0 = ring; if (bcm->current_core->rev < 5) { ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, BCM43xx_RXRING_SLOTS, 0); if (!ring) goto err_destroy_rx0; - bcm->current_core->dma->rx_ring1 = ring; + dma->rx_ring1 = ring; } dprintk(KERN_INFO PFX "DMA initialized\n"); @@ -643,27 +630,26 @@ out: return err; err_destroy_rx0: - bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring0); - bcm->current_core->dma->rx_ring0 = NULL; + bcm43xx_destroy_dmaring(dma->rx_ring0); + dma->rx_ring0 = NULL; err_destroy_tx3: - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring3); - bcm->current_core->dma->tx_ring3 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring3); + dma->tx_ring3 = NULL; err_destroy_tx2: - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring2); - bcm->current_core->dma->tx_ring2 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring2); + dma->tx_ring2 = NULL; err_destroy_tx1: - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring1); - bcm->current_core->dma->tx_ring1 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring1); + dma->tx_ring1 = NULL; err_destroy_tx0: - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring0); - bcm->current_core->dma->tx_ring0 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring0); + dma->tx_ring0 = NULL; goto out; } /* Generate a cookie for the TX header. */ -static inline -u16 generate_cookie(struct bcm43xx_dmaring *ring, - int slot) +static u16 generate_cookie(struct bcm43xx_dmaring *ring, + int slot) { u16 cookie = 0x0000; @@ -693,24 +679,25 @@ u16 generate_cookie(struct bcm43xx_dmaring *ring, } /* Inspect a cookie and find out to which controller/slot it belongs. */ -static inline +static struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, u16 cookie, int *slot) { + struct bcm43xx_dma *dma = bcm->current_core->dma; struct bcm43xx_dmaring *ring = NULL; switch (cookie & 0xF000) { case 0x0000: - ring = bcm->current_core->dma->tx_ring0; + ring = dma->tx_ring0; break; case 0x1000: - ring = bcm->current_core->dma->tx_ring1; + ring = dma->tx_ring1; break; case 0x2000: - ring = bcm->current_core->dma->tx_ring2; + ring = dma->tx_ring2; break; case 0x3000: - ring = bcm->current_core->dma->tx_ring3; + ring = dma->tx_ring3; break; default: assert(0); @@ -721,8 +708,8 @@ struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, return ring; } -static inline void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, - int slot) +static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, + int slot) { /* Everything is ready to start. Buffers are DMA mapped and * associated with slots. @@ -736,11 +723,10 @@ static inline void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, (u32)(slot * sizeof(struct bcm43xx_dmadesc))); } -static inline -int dma_tx_fragment(struct bcm43xx_dmaring *ring, - struct sk_buff *skb, - struct ieee80211_txb *txb, - u8 cur_frag) +static int dma_tx_fragment(struct bcm43xx_dmaring *ring, + struct sk_buff *skb, + struct ieee80211_txb *txb, + u8 cur_frag) { int slot; struct bcm43xx_dmadesc *desc; @@ -777,7 +763,9 @@ int dma_tx_fragment(struct bcm43xx_dmaring *ring, meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) { return_slot(ring, slot); - printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G\n"); + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G " + "(0x%08x, len: %u)\n", + meta->dmaaddr, skb->len); return -ENOMEM; } @@ -797,14 +785,15 @@ int dma_tx_fragment(struct bcm43xx_dmaring *ring, return 0; } -static inline int dma_transfer_txb(struct bcm43xx_dmaring *ring, - struct ieee80211_txb *txb) +int bcm43xx_dma_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) { /* We just received a packet from the kernel network subsystem. * Add headers and DMA map the memory. Poke * the device to send the stuff. * Note that this is called from atomic context. */ + struct bcm43xx_dmaring *ring = bcm->current_core->dma->tx_ring1; u8 i; struct sk_buff *skb; @@ -818,8 +807,6 @@ static inline int dma_transfer_txb(struct bcm43xx_dmaring *ring, return -ENOMEM; } - assert(irqs_disabled()); - spin_lock(&ring->lock); for (i = 0; i < txb->nr_frags; i++) { skb = txb->fragments[i]; /* We do not free the skb, as it is freed as @@ -829,22 +816,12 @@ static inline int dma_transfer_txb(struct bcm43xx_dmaring *ring, dma_tx_fragment(ring, skb, txb, i); //TODO: handle failure of dma_tx_fragment } - spin_unlock(&ring->lock); return 0; } -int fastcall -bcm43xx_dma_transfer_txb(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - return dma_transfer_txb(bcm->current_core->dma->tx_ring1, - txb); -} - -void fastcall -bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) +void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) { struct bcm43xx_dmaring *ring; struct bcm43xx_dmadesc *desc; @@ -855,9 +832,6 @@ bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, ring = parse_cookie(bcm, status->cookie, &slot); assert(ring); assert(ring->tx); - assert(irqs_disabled()); - spin_lock(&ring->lock); - assert(get_desc_ctl(ring->vbase + slot) & BCM43xx_DMADTOR_FRAMESTART); while (1) { assert(slot >= 0 && slot < ring->nr_slots); @@ -877,13 +851,10 @@ bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, slot = next_slot(ring, slot); } bcm->stats.last_tx = jiffies; - - spin_unlock(&ring->lock); } -static inline -void dma_rx(struct bcm43xx_dmaring *ring, - int *slot) +static void dma_rx(struct bcm43xx_dmaring *ring, + int *slot) { struct bcm43xx_dmadesc *desc; struct bcm43xx_dmadesc_meta *meta; @@ -928,8 +899,12 @@ void dma_rx(struct bcm43xx_dmaring *ring, barrier(); len = le16_to_cpu(rxhdr->frame_length); } while (len == 0 && i++ < 5); - if (len == 0) + if (unlikely(len == 0)) { + /* recycle the descriptor buffer. */ + sync_descbuffer_for_device(ring, meta->dmaaddr, + ring->rx_buffersize); goto drop; + } } if (unlikely(len > ring->rx_buffersize)) { /* The data did not fit into one descriptor buffer @@ -937,15 +912,24 @@ void dma_rx(struct bcm43xx_dmaring *ring, * This should never happen, as we try to allocate buffers * big enough. So simply ignore this packet. */ - int cnt = 1; - s32 tmp = len - ring->rx_buffersize; - - for ( ; tmp > 0; tmp -= ring->rx_buffersize) { + int cnt = 0; + s32 tmp = len; + + while (1) { + desc = ring->vbase + *slot; + meta = ring->meta + *slot; + /* recycle the descriptor buffer. */ + sync_descbuffer_for_device(ring, meta->dmaaddr, + ring->rx_buffersize); *slot = next_slot(ring, *slot); cnt++; + tmp -= ring->rx_buffersize; + if (tmp <= 0) + break; } - printkl(KERN_ERR PFX "DMA RX buffer too small. %d dropped.\n", - cnt); + printkl(KERN_ERR PFX "DMA RX buffer too small " + "(len: %u, buffer: %u, nr-dropped: %d)\n", + len, ring->rx_buffersize, cnt); goto drop; } len -= IEEE80211_FCS_LEN; @@ -954,6 +938,8 @@ void dma_rx(struct bcm43xx_dmaring *ring, err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC); if (unlikely(err)) { dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n"); + sync_descbuffer_for_device(ring, dmaaddr, + ring->rx_buffersize); goto drop; } @@ -971,8 +957,7 @@ drop: return; } -void fastcall -bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) +void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) { u32 status; u16 descptr; @@ -982,9 +967,6 @@ bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) #endif assert(!ring->tx); - assert(irqs_disabled()); - spin_lock(&ring->lock); - status = bcm43xx_read32(ring->bcm, ring->mmio_base + BCM43xx_DMA_RX_STATUS); descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK); current_slot = descptr / sizeof(struct bcm43xx_dmadesc); @@ -1002,8 +984,6 @@ bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) ring->mmio_base + BCM43xx_DMA_RX_DESC_INDEX, (u32)(slot * sizeof(struct bcm43xx_dmadesc))); ring->current_slot = slot; - - spin_unlock(&ring->lock); } /* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index e32cf68f8e1d..93e99d61f2e1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -122,7 +122,6 @@ struct bcm43xx_dmadesc_meta { }; struct bcm43xx_dmaring { - spinlock_t lock; struct bcm43xx_private *bcm; /* Kernel virtual base address of the ring memory. */ struct bcm43xx_dmadesc *vbase; @@ -166,11 +165,11 @@ int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, u16 dmacontroller_mmio_base); -int FASTCALL(bcm43xx_dma_transfer_txb(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb)); -void FASTCALL(bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status)); +void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status); -void FASTCALL(bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)); +int bcm43xx_dma_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb); +void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); #endif /* BCM43xx_DMA_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index be60a6509f20..4b4e60a22c0b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -4097,7 +4097,6 @@ int fastcall bcm43xx_rx(struct bcm43xx_private *bcm, } frame_ctl = le16_to_cpu(wlhdr->frame_ctl); - if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { frame_ctl &= ~IEEE80211_FCTL_PROTECTED; wlhdr->frame_ctl = cpu_to_le16(frame_ctl); @@ -4113,12 +4112,12 @@ int fastcall bcm43xx_rx(struct bcm43xx_private *bcm, skb_trim(skb, skb->len - 4); stats.len -= 8; } - /* do _not_ use wlhdr again without reassigning it */ + wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); } switch (WLAN_FC_GET_TYPE(frame_ctl)) { case IEEE80211_FTYPE_MGMT: - ieee80211_rx_mgt(bcm->ieee, skb->data, &stats); + ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); break; case IEEE80211_FTYPE_DATA: if (is_packet_for_us) @@ -4143,7 +4142,7 @@ static inline int bcm43xx_tx(struct bcm43xx_private *bcm, if (bcm->pio_mode) err = bcm43xx_pio_transfer_txb(bcm, txb); else - err = bcm43xx_dma_transfer_txb(bcm, txb); + err = bcm43xx_dma_tx(bcm, txb); return err; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 41b9cd7fc9e2..f5e7a6ab93cb 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -1161,7 +1161,7 @@ void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm) phy->minlowsigpos[1] += 0x0101; bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]); - if (radio->version == 2053) { + if (radio->version == 0x2053) { bcm43xx_phy_write(bcm, 0x000A, regstack[2]); bcm43xx_phy_write(bcm, 0x002A, regstack[3]); bcm43xx_phy_write(bcm, 0x0035, regstack[4]); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 1e65658552b0..5ce6acef2c4a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -467,8 +467,8 @@ static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) | 0x0040); - bcm43xx_phy_write(bcm, 0x007A, - bcm43xx_phy_read(bcm, 0x007A) | 0x000F); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x000F); bcm43xx_set_all_gains(bcm, 3, 0, 1); bcm43xx_radio_write16(bcm, 0x0043, (bcm43xx_radio_read16(bcm, 0x0043) @@ -761,8 +761,8 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002)); bcm43xx_set_original_gains(bcm); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) | 0x8000); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000); if (phy->rev >= 3) { bcm43xx_phy_write(bcm, 0x0801, backup[14]); bcm43xx_phy_write(bcm, 0x0060, backup[15]); -- cgit v1.2.3-59-g8ed1b From 4a2a2792d0cb3f2797ff179beef7b8c2981979c2 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 27 Jan 2006 17:33:15 +0100 Subject: [PATCH] bcm43xx: remove linux version compatibility code. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index aca1601e5b4f..38e75ed2b654 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -935,27 +935,4 @@ int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 valu __value; \ }) - -/* - * Compatibility stuff follows - */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) -# error "The bcm43xx driver does not support kernels < 2.6.15" -# error "The driver will _NOT_ compile on your kernel. Please upgrade to the latest 2.6 kernel." -# error "DO NOT COMPLAIN ABOUT BUGS. UPDATE FIRST AND TRY AGAIN." -#else -# if !defined(CONFIG_IEEE80211_MODULE) && !defined(CONFIG_IEEE80211) -# error "Generic IEEE 802.11 Networking Stack (CONFIG_IEEE80211) not available." -# endif -#endif -#ifdef IEEE80211SOFTMAC_API -# if IEEE80211SOFTMAC_API != 0 -# warning "Incompatible SoftMAC subsystem installed." -# endif -#else -# error "The bcm43xx driver requires the SoftMAC subsystem." -# error "SEE >>>>>> http://softmac.sipsolutions.net/ <<<<<<" -#endif - #endif /* BCM43xx_H_ */ -- cgit v1.2.3-59-g8ed1b From 08ccd883f536d81d380522106c67bd5d7043fa4a Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 27 Jan 2006 17:37:05 +0100 Subject: [PATCH] bcm43xx: Move README file to Documentation directory. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- Documentation/networking/bcm43xx.txt | 36 ++++++++++++++++++++++++++++++++++++ drivers/net/wireless/bcm43xx/README | 36 ------------------------------------ 2 files changed, 36 insertions(+), 36 deletions(-) create mode 100644 Documentation/networking/bcm43xx.txt delete mode 100644 drivers/net/wireless/bcm43xx/README (limited to 'drivers') diff --git a/Documentation/networking/bcm43xx.txt b/Documentation/networking/bcm43xx.txt new file mode 100644 index 000000000000..64d9022de7fe --- /dev/null +++ b/Documentation/networking/bcm43xx.txt @@ -0,0 +1,36 @@ + + BCM43xx Linux Driver Project + ============================ + +About this software +------------------- + +The goal of this project is to develop a linux driver for Broadcom +BCM43xx chips, based on the specification at +http://bcm-specs.sipsolutions.net/ + +The project page is http://bcm43xx.berlios.de/ + + +Requirements +------------ + +1) Linux Kernel 2.6.15 or later + http://www.kernel.org/ + + You may want to configure your kernel with: + + CONFIG_DEBUG_FS (optional): + -> Kernel hacking + -> Debug Filesystem + +2) SoftMAC IEEE 802.11 Networking Stack extension and patched ieee80211 + modules: + http://softmac.sipsolutions.net/ + +3) Firmware Files + + Please try fwcutter. Fwcutter can extract the firmware from various + binary driver files. It supports driver files from Windows, MacOS and + Linux. You can get fwcutter from http://bcm43xx.berlios.de/. + Also, fwcutter comes with a README file for further instructions. diff --git a/drivers/net/wireless/bcm43xx/README b/drivers/net/wireless/bcm43xx/README deleted file mode 100644 index 64d9022de7fe..000000000000 --- a/drivers/net/wireless/bcm43xx/README +++ /dev/null @@ -1,36 +0,0 @@ - - BCM43xx Linux Driver Project - ============================ - -About this software -------------------- - -The goal of this project is to develop a linux driver for Broadcom -BCM43xx chips, based on the specification at -http://bcm-specs.sipsolutions.net/ - -The project page is http://bcm43xx.berlios.de/ - - -Requirements ------------- - -1) Linux Kernel 2.6.15 or later - http://www.kernel.org/ - - You may want to configure your kernel with: - - CONFIG_DEBUG_FS (optional): - -> Kernel hacking - -> Debug Filesystem - -2) SoftMAC IEEE 802.11 Networking Stack extension and patched ieee80211 - modules: - http://softmac.sipsolutions.net/ - -3) Firmware Files - - Please try fwcutter. Fwcutter can extract the firmware from various - binary driver files. It supports driver files from Windows, MacOS and - Linux. You can get fwcutter from http://bcm43xx.berlios.de/. - Also, fwcutter comes with a README file for further instructions. -- cgit v1.2.3-59-g8ed1b From dda207ae2da37032524bbdd7a0133c37f2907ae8 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 27 Jan 2006 17:39:44 +0100 Subject: [PATCH] bcm43xx: remove redundant COPYING file. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/COPYING | 340 ----------------------------------- 1 file changed, 340 deletions(-) delete mode 100644 drivers/net/wireless/bcm43xx/COPYING (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/COPYING b/drivers/net/wireless/bcm43xx/COPYING deleted file mode 100644 index 5b6e7c66c276..000000000000 --- a/drivers/net/wireless/bcm43xx/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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 - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. -- cgit v1.2.3-59-g8ed1b From 6f3e2045cabd952a86bc819181d8a190cd0689c3 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 30 Jan 2006 17:43:20 +0100 Subject: [PATCH] bcm43xx: add DEBUG Kconfig option. Also fix indention. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 7c7dca112bf5..3b1363c97191 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -502,12 +502,21 @@ config PRISM54 source "drivers/net/wireless/hostap/Kconfig" config BCM43XX - tristate "Broadcom BCM43xx wireless support" - depends on PCI && IEEE80211 && NET_RADIO && IEEE80211_SOFTMAC && EXPERIMENTAL + tristate "Broadcom BCM43xx wireless support" + depends on PCI && IEEE80211 && NET_RADIO && IEEE80211_SOFTMAC && EXPERIMENTAL select FW_LOADER - ---help--- - This is an experimental driver for the Broadcom 43xx wireless chip, - found in the Apple Airport Extreme and various other devices. + ---help--- + This is an experimental driver for the Broadcom 43xx wireless chip, + found in the Apple Airport Extreme and various other devices. + +config BCM43XX_DEBUG + bool "Broadcom BCM43xx debugging (RECOMMENDED)" + depends on BCM43XX + default y + ---help--- + Broadcom 43xx debugging messages. + Say Y, because the driver is still very experimental and + this will help you get it running. # yes, this works even when no drivers are selected config NET_WIRELESS -- cgit v1.2.3-59-g8ed1b From 65f3f19120cf32233f537562e69893b88727b634 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 31 Jan 2006 20:11:38 +0100 Subject: [PATCH] bcm43xx: Fix makefile. Remove all the "out-of-tree" stuff. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Makefile | 87 ++------------------------ drivers/net/wireless/bcm43xx/bcm43xx.h | 6 +- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 8 +-- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 11 ++-- 4 files changed, 14 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile index 98d4efb1d12a..3e5ed77835e2 100644 --- a/drivers/net/wireless/bcm43xx/Makefile +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -1,87 +1,8 @@ -# Makefile for bcm43xx driver +obj-$(CONFIG_BCM43XX) += bcm43xx.o +bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o -VERSION := 0.0.1 -RELEASE_NAME := bcm43xx-$(VERSION) - -# Optional path, where the SoftMAC subsystem is located. -# You may set SOFTMAC_DIR in your bashrc, for example. -SOFTMAC_DIR ?= - -KVER := $(shell uname -r) -KDIR ?= /lib/modules/$(KVER)/build -PWD := $(shell pwd) -MODPATH := $(DESTDIR)/lib/modules/$(KVER)/kernel/drivers/net/bcm43xx - -# Comment/uncomment to enable/disable debugging -DEBUG = y - - -ifeq ($(DEBUG),y) -DEBUGFS_OBJ = bcm43xx_debugfs.o -CFLAGS += -O2 -DCONFIG_BCM43XX_DEBUG -else -DEBUGFS_OBJ = -CFLAGS += -O2 -endif - -CFLAGS += -DBCM43xx_VERSION=$(VERSION) -I/lib/modules/$(KVER)/include -ifneq ($(SOFTMAC_DIR),) -CPPFLAGS := -I$(SOFTMAC_DIR) $(CPPFLAGS) -endif - -ifneq ($(KERNELRELEASE),) -# call from kernel build system - -obj-m := bcm43xx.o -bcm43xx-objs := bcm43xx_main.o bcm43xx_dma.o $(DEBUGFS_OBJ) \ +bcm43xx-objs := bcm43xx_main.o bcm43xx_dma.o \ bcm43xx_radio.o bcm43xx_phy.o \ bcm43xx_power.o bcm43xx_wx.o \ bcm43xx_pio.o bcm43xx_ilt.o \ - bcm43xx_leds.o - -else - -default: modules - -modules: - $(MAKE) -C $(KDIR) M=$(PWD) modules - -install: bcm43xx.ko - install -d $(MODPATH) - install -m 644 -c bcm43xx.ko $(MODPATH) - /sbin/depmod -a - -uninstall: - rm -rf $(MODPATH) - /sbin/depmod -a - -endif - -clean: - find . \( -name '*.ko' -o -name '*.o' -o -name '.tmp_versions' -o -name '*~' -o -name '.*.cmd' \ - -o -name '*.mod.c' -o -name '*.tar.bz2' -o -name '*.rej' -o -name '*.orig' \)\ - -print | xargs rm -Rf - -depend .depend dep: - $(CC) $(CFLAGS) -M *.c > .depend - -ifeq (.depend,$(wildcard .depend)) -include .depend -endif - -DISTFILES = $(shell find . \( -not -name '.' \) -print | grep -v "\.tar\.bz2" | grep -v "\/\." ) -DISTDIR = $(RELEASE_NAME) - -release: clean - @rm -rf $(DISTDIR) - @mkdir $(DISTDIR) - @chmod 777 $(DISTDIR) - @for file in $(DISTFILES); do \ - if test -d $$file; then \ - mkdir $(DISTDIR)/$$file; \ - else \ - cp -p $$file $(DISTDIR)/$$file; \ - fi; \ - done - @tar -c $(DISTDIR) | bzip2 -9 > $(RELEASE_NAME).tar.bz2 - @rm -rf $(DISTDIR) + bcm43xx_leds.o $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 38e75ed2b654..7b97d8bf79ed 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -17,14 +17,10 @@ #include "bcm43xx_leds.h" -#define DRV_NAME __stringify(KBUILD_MODNAME) -#define DRV_VERSION __stringify(BCM43xx_VERSION) -#define BCM43xx_DRIVER_NAME DRV_NAME " driver " DRV_VERSION -#define PFX DRV_NAME ": " +#define PFX KBUILD_MODNAME ": " #define BCM43xx_SWITCH_CORE_MAX_RETRIES 10 #define BCM43xx_IRQWAIT_MAX_RETRIES 50 -#define BCM43xx_TX_TIMEOUT (10 * HZ) #define BCM43xx_IO_SIZE 8192 #define BCM43xx_REG_ACTIVE_CORE 0x80 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index f8cfc84ca0da..5a7dc43cd676 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -141,7 +141,7 @@ static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf, down(&big_buffer_sem); /* This is where the information is written to the "driver" file */ - fappend(BCM43xx_DRIVER_NAME "\n"); + fappend(KBUILD_MODNAME " driver\n"); fappend("Compiled at: %s %s\n", __DATE__, __TIME__); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); @@ -433,12 +433,12 @@ void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, void bcm43xx_debugfs_init(void) { memset(&fs, 0, sizeof(fs)); - fs.root = debugfs_create_dir(DRV_NAME, NULL); + fs.root = debugfs_create_dir(KBUILD_MODNAME, NULL); if (!fs.root) - printk(KERN_ERR PFX "debugfs: creating \"" DRV_NAME "\" subdir failed!\n"); + printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "\" subdir failed!\n"); fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops); if (!fs.dentry_driverinfo) - printk(KERN_ERR PFX "debugfs: creating \"" DRV_NAME "/driver\" failed!\n"); + printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "/driver\" failed!\n"); } void bcm43xx_debugfs_exit(void) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 4b4e60a22c0b..cfb0f0a485a7 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2471,7 +2471,7 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) } #endif res = request_irq(bcm->irq, bcm43xx_interrupt_handler, - SA_SHIRQ, DRV_NAME, bcm); + SA_SHIRQ, KBUILD_MODNAME, bcm); if (res) { printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); return -EFAULT; @@ -3809,7 +3809,7 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) } #endif - err = pci_request_regions(pci_dev, DRV_NAME); + err = pci_request_regions(pci_dev, KBUILD_MODNAME); if (err) { printk(KERN_ERR PFX "could not access PCI resources (%i)\n", err); @@ -4389,12 +4389,11 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, #endif net_dev->wireless_handlers = &bcm43xx_wx_handlers_def; net_dev->irq = pdev->irq; - net_dev->watchdog_timeo = BCM43xx_TX_TIMEOUT; /* initialize the bcm43xx_private struct */ bcm = bcm43xx_priv(net_dev); memset(bcm, 0, sizeof(*bcm)); - wq = create_workqueue(DRV_NAME "_wq"); + wq = create_workqueue(KBUILD_MODNAME "_wq"); if (!wq) { err = -ENOMEM; goto err_free_netdev; @@ -4567,7 +4566,7 @@ static int bcm43xx_resume(struct pci_dev *pdev) #endif /* CONFIG_PM */ static struct pci_driver bcm43xx_pci_driver = { - .name = BCM43xx_DRIVER_NAME, + .name = KBUILD_MODNAME, .id_table = bcm43xx_pci_tbl, .probe = bcm43xx_init_one, .remove = __devexit_p(bcm43xx_remove_one), @@ -4579,7 +4578,7 @@ static struct pci_driver bcm43xx_pci_driver = { static int __init bcm43xx_init(void) { - printk(KERN_INFO BCM43xx_DRIVER_NAME "\n"); + printk(KERN_INFO KBUILD_MODNAME " driver\n"); bcm43xx_debugfs_init(); return pci_register_driver(&bcm43xx_pci_driver); } -- cgit v1.2.3-59-g8ed1b From a4a600d3e17f450666a9086465122103e96140d7 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 1 Feb 2006 22:09:52 +0100 Subject: [PATCH] bcm43xx: Add more initvals sanity checks and error out, if one sanity check fails. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 62 ++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index cfb0f0a485a7..521777f56a3d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2229,9 +2229,9 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re return IRQ_HANDLED; } -static void bcm43xx_release_firmware(struct bcm43xx_private *bcm) +static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) { - if (bcm->firmware_norelease) + if (bcm->firmware_norelease && !force) return; /* Suspending or controller reset. */ release_firmware(bcm->ucode); bcm->ucode = NULL; @@ -2361,7 +2361,7 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) out: return err; error: - bcm43xx_release_firmware(bcm); + bcm43xx_release_firmware(bcm, 1); goto out; err_noinitval: printk(KERN_ERR PFX "Error: No InitVals available!\n"); @@ -2409,9 +2409,9 @@ static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) #endif } -static void bcm43xx_write_initvals(struct bcm43xx_private *bcm, - const struct bcm43xx_initval *data, - const unsigned int len) +static int bcm43xx_write_initvals(struct bcm43xx_private *bcm, + const struct bcm43xx_initval *data, + const unsigned int len) { u16 offset, size; u32 value; @@ -2422,35 +2422,54 @@ static void bcm43xx_write_initvals(struct bcm43xx_private *bcm, size = be16_to_cpu(data[i].size); value = be32_to_cpu(data[i].value); - if (size == 2) - bcm43xx_write16(bcm, offset, value); - else if (size == 4) + if (unlikely(offset >= 0x1000)) + goto err_format; + if (size == 2) { + if (unlikely(value & 0xFFFF0000)) + goto err_format; + bcm43xx_write16(bcm, offset, (u16)value); + } else if (size == 4) { bcm43xx_write32(bcm, offset, value); - else - printk(KERN_ERR PFX "InitVals fileformat error.\n"); + } else + goto err_format; } + + return 0; + +err_format: + printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. " + "Please fix your bcm43xx firmware files.\n"); + return -EPROTO; } -static void bcm43xx_upload_initvals(struct bcm43xx_private *bcm) +static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) { + int err; + #ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT bcm43xx_mmioprint_enable(bcm); #else bcm43xx_mmioprint_disable(bcm); #endif - bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, - bcm->initvals0->size / sizeof(struct bcm43xx_initval)); + err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, + bcm->initvals0->size / sizeof(struct bcm43xx_initval)); + if (err) + goto out; if (bcm->initvals1) { - bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data, - bcm->initvals1->size / sizeof(struct bcm43xx_initval)); + err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data, + bcm->initvals1->size / sizeof(struct bcm43xx_initval)); + if (err) + goto out; } +out: #ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT bcm43xx_mmioprint_disable(bcm); #else bcm43xx_mmioprint_enable(bcm); #endif + return err; } static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) @@ -2683,7 +2702,7 @@ static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm) bcm43xx_leds_exit(bcm); bcm43xx_gpio_cleanup(bcm); free_irq(bcm->irq, bcm); - bcm43xx_release_firmware(bcm); + bcm43xx_release_firmware(bcm, 0); } /* Initialize the chip @@ -2708,13 +2727,15 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) err = bcm43xx_initialize_irq(bcm); if (err) - goto out; + goto err_release_fw; err = bcm43xx_gpio_init(bcm); if (err) goto err_free_irq; - bcm43xx_upload_initvals(bcm); + err = bcm43xx_upload_initvals(bcm); + if (err) + goto err_gpio_cleanup; bcm43xx_radio_turn_on(bcm); if (modparam_noleds) @@ -2813,9 +2834,12 @@ out: err_radio_off: bcm43xx_radio_turn_off(bcm); +err_gpio_cleanup: bcm43xx_gpio_cleanup(bcm); err_free_irq: free_irq(bcm->irq, bcm); +err_release_fw: + bcm43xx_release_firmware(bcm, 1); goto out; } -- cgit v1.2.3-59-g8ed1b From 9e4a375b15c9940b13e66e224570b35c471c0128 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 2 Feb 2006 18:43:25 +0100 Subject: [PATCH] bcm43xx: Remove function bcm43xx_channel_is_allowed() Geographical restriction should become part of the 80211 stack, so every driver does not have to duplicate it. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 166 +--------------------------- 1 file changed, 1 insertion(+), 165 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 521777f56a3d..c0ec503102c8 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -82,10 +82,6 @@ static int modparam_locale = -1; module_param_named(locale, modparam_locale, int, 0444); MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)"); -static int modparam_outdoor; -module_param_named(outdoor, modparam_outdoor, int, 0444); -MODULE_PARM_DESC(outdoor, "Set to 1, if you are using the device outdoor, 0 otherwise."); - static int modparam_noleds; module_param_named(noleds, modparam_noleds, int, 0444); MODULE_PARM_DESC(noleds, "Turn off all LED activity"); @@ -1088,163 +1084,13 @@ static int bcm43xx_read_sprom(struct bcm43xx_private *bcm) return 0; } -static int bcm43xx_channel_is_allowed(struct bcm43xx_private *bcm, u8 channel, - u8 *max_power, u8 *flags) -{ - /* THIS FUNCTION DOES _NOT_ ENFORCE REGULATORY DOMAIN COMPLIANCE. - * It is only a helper function to make life easier to - * select legal channels and transmission powers. - */ - - u8 phytype = bcm->current_core->phy->type; - int allowed = 0; - - *max_power = 0; - *flags = 0; - - //FIXME: Set max_power and maybe flags - /*FIXME: Allowed channels are sometimes different for outdoor - * or indoor use. See modparam_outdoor. - */ - /* From b specs Max Power BPHY: - * USA: 1000mW - * Europe: 100mW - * Japan: 10mW/MHz - */ - - switch (bcm->sprom.locale) { - case BCM43xx_LOCALE_WORLD: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 13) - allowed = 1; - } else { - if (channel >= 1 && channel <= 13) - allowed = 1; - } - break; - case BCM43xx_LOCALE_THAILAND: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 14) - allowed = 1; - } else { - if (channel >= 1 && channel <= 14) - allowed = 1; - } - break; - case BCM43xx_LOCALE_ISRAEL: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 5 && channel <= 7) - allowed = 1; - } else { - if (channel >= 5 && channel <= 7) - allowed = 1; - } - break; - case BCM43xx_LOCALE_JORDAN: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 10 && channel <= 13) - allowed = 1; - } else { - if (channel >= 10 && channel <= 13) - allowed = 1; - } - break; - case BCM43xx_LOCALE_CHINA: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 13) - allowed = 1; - } else { - if (channel >= 1 && channel <= 13) - allowed = 1; - } - break; - case BCM43xx_LOCALE_JAPAN: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - //FIXME: This seems to be wrong. - if (channel >= 1 && channel <= 14) - allowed = 1; - } else { - //FIXME: This seems to be wrong. - if (channel >= 1 && channel <= 14) - allowed = 1; - } - break; - case BCM43xx_LOCALE_USA_CANADA_ANZ: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 13) - allowed = 1; - } else { - if (channel >= 1 && channel <= 11) - allowed = 1; - } - break; - case BCM43xx_LOCALE_EUROPE: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 13) - allowed = 1; - } else { - if (channel >= 1 && channel <= 13) - allowed = 1; - } - break; - case BCM43xx_LOCALE_USA_LOW: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 13) - allowed = 1; - } else { - if (channel >= 1 && channel <= 11) - allowed = 1; - } - break; - case BCM43xx_LOCALE_JAPAN_HIGH: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - //FIXME? - if (channel >= 1 && channel <= 14) - allowed = 1; - } else { - if (channel >= 1 && channel <= 14) - allowed = 1; - } - break; - case BCM43xx_LOCALE_ALL: - allowed = 1; - break; - case BCM43xx_LOCALE_NONE: - break; - default: - assert(0); - } - - return allowed; -} - static void bcm43xx_geo_init(struct bcm43xx_private *bcm) { struct ieee80211_geo geo; struct ieee80211_channel *chan; int have_a = 0, have_bg = 0; int i, num80211; - u8 channel, flags, max_power; + u8 channel; struct bcm43xx_phyinfo *phy; const char *iso_country; @@ -1268,27 +1114,17 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) if (have_a) { for (i = 0, channel = 0; channel < 201; channel++) { - if (!bcm43xx_channel_is_allowed(bcm, channel, - &max_power, &flags)) - continue; chan = &geo.a[i++]; chan->freq = bcm43xx_channel_to_freq(bcm, channel); chan->channel = channel; - chan->flags = flags; - chan->max_power = max_power; } geo.a_channels = i; } if (have_bg) { for (i = 0, channel = 1; channel < 15; channel++) { - if (!bcm43xx_channel_is_allowed(bcm, channel, - &max_power, &flags)) - continue; chan = &geo.bg[i++]; chan->freq = bcm43xx_channel_to_freq(bcm, channel); chan->channel = channel; - chan->flags = flags; - chan->max_power = max_power; } geo.bg_channels = i; } -- cgit v1.2.3-59-g8ed1b From 6465ce1bbf7fede82dccec342417105b10793b51 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 2 Feb 2006 19:11:08 +0100 Subject: [PATCH] bcm43xx: basic ethtool support This patch contains the beginnings of ethtool support for bcm43xx. It only implements get_drvinfo and get_link, but that's enough for ifplugd to use ethtool to know whether we're associated or not and then start or stop dhcp as necessary. Signed-off-by: Jason Lunz Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Makefile | 3 +- drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c | 50 ++++++++++++++++++++++++++ drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h | 8 +++++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 2 ++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile index 3e5ed77835e2..e025e9f052b2 100644 --- a/drivers/net/wireless/bcm43xx/Makefile +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -5,4 +5,5 @@ bcm43xx-objs := bcm43xx_main.o bcm43xx_dma.o \ bcm43xx_radio.o bcm43xx_phy.o \ bcm43xx_power.o bcm43xx_wx.o \ bcm43xx_pio.o bcm43xx_ilt.o \ - bcm43xx_leds.o $(bcm43xx-obj-y) + bcm43xx_leds.o bcm43xx_ethtool.o \ + $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c new file mode 100644 index 000000000000..b3ffcf501311 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c @@ -0,0 +1,50 @@ +/* + + Broadcom BCM43xx wireless driver + + ethtool support + + Copyright (c) 2006 Jason Lunz + + Some code in this file is derived from the 8139too.c driver + Copyright (C) 2002 Jeff Garzik + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx.h" +#include "bcm43xx_ethtool.h" + +#include +#include +#include +#include + + +static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(dev); + + strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); + strncpy(info->version, UTS_RELEASE, sizeof(info->version)); + strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN); +} + +struct ethtool_ops bcm43xx_ethtool_ops = { + .get_drvinfo = bcm43xx_get_drvinfo, + .get_link = ethtool_op_get_link, +}; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h new file mode 100644 index 000000000000..813704991f62 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h @@ -0,0 +1,8 @@ +#ifndef BCM43xx_ETHTOOL_H_ +#define BCM43xx_ETHTOOL_H_ + +#include + +extern struct ethtool_ops bcm43xx_ethtool_ops; + +#endif /* BCM43xx_ETHTOOL_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index c0ec503102c8..1051a49ddafe 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -49,6 +49,7 @@ #include "bcm43xx_pio.h" #include "bcm43xx_power.h" #include "bcm43xx_wx.h" +#include "bcm43xx_ethtool.h" MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); @@ -4249,6 +4250,7 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, #endif net_dev->wireless_handlers = &bcm43xx_wx_handlers_def; net_dev->irq = pdev->irq; + SET_ETHTOOL_OPS(net_dev, &bcm43xx_ethtool_ops); /* initialize the bcm43xx_private struct */ bcm = bcm43xx_priv(net_dev); -- cgit v1.2.3-59-g8ed1b From 8fa252d099d864f8848a9890f26d1a51a9c7ad32 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 2 Feb 2006 19:49:15 +0100 Subject: [PATCH] bcm43xx: Wireless Ext update Wireless Ext update: update we_version_source set enc_capa Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index fe6409a90901..c1d788d50f49 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -41,6 +41,11 @@ #include "bcm43xx_main.h" #include "bcm43xx_radio.h" + +/* The WIRELESS_EXT version, which is implemented by this driver. */ +#define BCM43xx_WX_VERSION 18 + + /* Define to enable a printk on each wx handler function invocation */ //#define BCM43xx_WX_DEBUG @@ -282,7 +287,12 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, range->max_encoding_tokens = WEP_KEYS; range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 16; + range->we_version_source = BCM43xx_WX_VERSION; + + range->enc_capa = IW_ENC_CAPA_WPA | + IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | + IW_ENC_CAPA_CIPHER_CCMP; spin_lock_irqsave(&bcm->lock, flags); -- cgit v1.2.3-59-g8ed1b From 67093a65c08dc45374f642b1ec1b86e7095a4dc8 Mon Sep 17 00:00:00 2001 From: Danny van Dyk Date: Wed, 1 Feb 2006 00:43:05 +0100 Subject: [PATCH] Sync bcm43xx_phy_initb6() with specs Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 15 ++++++++++----- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_radio.h | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index f5e7a6ab93cb..d90f207b2473 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -947,7 +947,7 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x0050, 0x0020); if ((bcm->current_core->radio->manufact == 0x17F) && (bcm->current_core->radio->version == 0x2050) && - (bcm->current_core->radio->revision == 2)) { + (bcm->current_core->radio->revision <= 2)) { bcm43xx_radio_write16(bcm, 0x0050, 0x0020); bcm43xx_radio_write16(bcm, 0x005A, 0x0070); bcm43xx_radio_write16(bcm, 0x005B, 0x007B); @@ -984,10 +984,15 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) bcm43xx_write16(bcm, 0x03E4, 0x0009); if (phy->type == BCM43xx_PHYTYPE_B) { bcm43xx_write16(bcm, 0x03E6, 0x8140); - bcm43xx_phy_write(bcm, 0x0016, 0x5410); - bcm43xx_phy_write(bcm, 0x0017, 0xA820); - bcm43xx_phy_write(bcm, 0x0007, 0x0062); - TODO();//TODO: calibrate stuff. + bcm43xx_phy_write(bcm, 0x0016, 0x0410); + bcm43xx_phy_write(bcm, 0x0017, 0x0820); + bcm43xx_phy_write(bcm, 0x0062, 0x0007); + (void) bcm43xx_radio_calibrationvalue(bcm); + bcm43xx_phy_lo_b_measure(bcm); + if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { + bcm43xx_calc_nrssi_slope(bcm); + bcm43xx_calc_nrssi_threshold(bcm); + } bcm43xx_phy_init_pctl(bcm); } else bcm43xx_write16(bcm, 0x03E6, 0x0); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 5ce6acef2c4a..3901aa994666 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -1184,7 +1184,7 @@ int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, return 0; } -static u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm) +u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm) { u16 reg, index, ret; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h index 89fe29282140..a5d2e10d5d98 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h @@ -89,5 +89,6 @@ void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val); void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm); void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm); +u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm); #endif /* BCM43xx_RADIO_H_ */ -- cgit v1.2.3-59-g8ed1b From 393344f67b598aaed594b9006e9eaa44ab62caa0 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 5 Feb 2006 15:28:20 +0100 Subject: [PATCH] bcm43xx: fix txpower reporting in WE. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 2 ++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4 +++ drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 9 ++---- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 44 +++++++++++++++++++++++------ 4 files changed, 44 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 7b97d8bf79ed..981d563f5738 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -525,6 +525,8 @@ struct bcm43xx_radioinfo { * 3: tx_CTL2 */ u16 txpower[4]; + /* Desired TX power in dBm Q5.2 */ + u16 txpower_desired; /* Current Interference Mitigation mode */ int interfmode; /* Stack of saved values from the Interference Mitigation code */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 1051a49ddafe..8e08c41f86de 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -793,6 +793,10 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) bcm->current_core->radio->txpower[2] = 3; else bcm->current_core->radio->txpower[2] = 0; + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + bcm->current_core->radio->txpower_desired = bcm->sprom.maxpower_aphy; + else + bcm->current_core->radio->txpower_desired = bcm->sprom.maxpower_bgphy; /* Initialize the in-memory nrssi Lookup Table. */ for (i = 0; i < 64; i++) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index d90f207b2473..d3c2fc1df375 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -1768,14 +1768,9 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) where REG is the max power as per the regulatory domain */ - /*TODO: Get desired_pwr from wx_handlers or the stack - limit_value(desired_pwr, 0, max_pwr); - */ - - desired_pwr = max_pwr; /* remove this when we have a real desired_pwr */ - + desired_pwr = limit_value(radio->txpower_desired, 0, max_pwr); + /* Check if we need to adjust the current power. */ pwr_adjust = desired_pwr - estimated_pwr; - radio_att_delta = -(pwr_adjust + 7) >> 3; baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta); if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index c1d788d50f49..bed7cfbe81d3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -484,21 +484,40 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct bcm43xx_radioinfo *radio; + struct bcm43xx_phyinfo *phy; unsigned long flags; int err = -ENODEV; + u16 maxpower; wx_enter(); + if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { + printk(PFX KERN_ERR "TX power not in dBm.\n"); + return -EOPNOTSUPP; + } + spin_lock_irqsave(&bcm->lock, flags); if (!bcm->initialized) goto out_unlock; - if (data->power.disabled != (!(bcm->current_core->radio->enabled))) { - if (data->power.disabled) + radio = bcm->current_core->radio; + phy = bcm->current_core->phy; + if (data->txpower.disabled != (!(radio->enabled))) { + if (data->txpower.disabled) bcm43xx_radio_turn_off(bcm); else bcm43xx_radio_turn_on(bcm); } - //TODO: set txpower. + if (data->txpower.value > 0) { + /* desired and maxpower dBm values are in Q5.2 */ + if (phy->type == BCM43xx_PHYTYPE_A) + maxpower = bcm->sprom.maxpower_aphy; + else + maxpower = bcm->sprom.maxpower_bgphy; + radio->txpower_desired = limit_value(data->txpower.value << 2, + 0, maxpower); + bcm43xx_phy_xmitpower(bcm); + } err = 0; out_unlock: @@ -513,18 +532,27 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct bcm43xx_radioinfo *radio; unsigned long flags; + int err = -ENODEV; wx_enter(); spin_lock_irqsave(&bcm->lock, flags); -//TODO data->power.value = ??? - data->power.fixed = 1; - data->power.flags = IW_TXPOW_DBM; - data->power.disabled = !(bcm->current_core->radio->enabled); + if (!bcm->initialized) + goto out_unlock; + radio = bcm->current_core->radio; + /* desired dBm value is in Q5.2 */ + data->txpower.value = radio->txpower_desired >> 2; + data->txpower.fixed = 1; + data->txpower.flags = IW_TXPOW_DBM; + data->txpower.disabled = !(radio->enabled); + + err = 0; +out_unlock: spin_unlock_irqrestore(&bcm->lock, flags); - return 0; + return err; } static int bcm43xx_wx_set_retry(struct net_device *net_dev, -- cgit v1.2.3-59-g8ed1b From 62b7f0dfab0508a45a93045d49eda26d5285188d Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 8 Feb 2006 17:36:46 +0100 Subject: [PATCH] bcm43xx: enable SPROM writing. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index bed7cfbe81d3..6f6f19aed305 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -976,7 +976,7 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, printk("75%%"); else if (i % 2) printk("."); -//TODO bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); + bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); mdelay(20); } spromctl &= ~0x10; /* SPROM WRITE enable. */ -- cgit v1.2.3-59-g8ed1b From 921e485f98b11656cdcc39a37605e116e34cb315 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 8 Feb 2006 17:55:55 +0100 Subject: [PATCH] bcm43xx: heavily increase mac_suspend timeout. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 8e08c41f86de..4c4a2d71ca04 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2473,16 +2473,13 @@ void bcm43xx_mac_suspend(struct bcm43xx_private *bcm) bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) & ~BCM43xx_SBF_MAC_ENABLED); bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ - for (i = 1000; i > 0; i--) { + for (i = 100000; i; i--) { tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (tmp & BCM43xx_IRQ_READY) { - i = -1; - break; - } + if (tmp & BCM43xx_IRQ_READY) + return; udelay(10); } - if (!i) - printkl(KERN_ERR PFX "Failed to suspend mac!\n"); + printkl(KERN_ERR PFX "MAC suspend failed\n"); } void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, -- cgit v1.2.3-59-g8ed1b From b5488beba8030b791e035c4da0122f98c42e355b Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 8 Feb 2006 18:00:30 +0100 Subject: [PATCH] bcm43xx: fix compiletime warning (phy_xmitpower) Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 6f6f19aed305..d383337db998 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -40,6 +40,7 @@ #include "bcm43xx_wx.h" #include "bcm43xx_main.h" #include "bcm43xx_radio.h" +#include "bcm43xx_phy.h" /* The WIRELESS_EXT version, which is implemented by this driver. */ -- cgit v1.2.3-59-g8ed1b From 5c57807afcc28a6b8fb579ef2c79e49f0b688425 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 8 Feb 2006 18:04:02 +0100 Subject: [PATCH] bcm43xx: remove WX debugging. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 68 ------------------------------- 1 file changed, 68 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index d383337db998..4c972cdc0a24 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -46,18 +46,6 @@ /* The WIRELESS_EXT version, which is implemented by this driver. */ #define BCM43xx_WX_VERSION 18 - -/* Define to enable a printk on each wx handler function invocation */ -//#define BCM43xx_WX_DEBUG - - -#ifdef BCM43xx_WX_DEBUG -# define printk_wx printk -#else -# define printk_wx(x...) do { /* nothing */ } while (0) -#endif -#define wx_enter() printk_wx(KERN_INFO PFX "WX handler called: %s\n", __FUNCTION__); - #define MAX_WX_STRING 80 @@ -73,8 +61,6 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, char suffix[7] = { 0 }; int have_a = 0, have_b = 0, have_g = 0; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); nr_80211 = bcm43xx_num_80211_cores(bcm); for (i = 0; i < nr_80211; i++) { @@ -127,8 +113,6 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, int freq; int err = 0; - wx_enter(); - if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { channel = data->freq.m; freq = bcm43xx_channel_to_freq(bcm, channel); @@ -148,8 +132,6 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, } else bcm->current_core->radio->initial_channel = channel; spin_unlock_irqrestore(&bcm->lock, flags); - if (!err) - printk_wx(KERN_INFO PFX "Selected channel: %d\n", channel); return err; } @@ -164,8 +146,6 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, int err = -ENODEV; u16 channel; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); channel = bcm->current_core->radio->channel; if (channel == 0xFF) { @@ -195,8 +175,6 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev, unsigned long flags; int mode; - wx_enter(); - mode = data->mode; if (mode == IW_MODE_AUTO) mode = BCM43xx_INITIAL_IWMODE; @@ -217,8 +195,6 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); data->mode = bcm->ieee->iw_mode; spin_unlock_irqrestore(&bcm->lock, flags); @@ -231,7 +207,6 @@ static int bcm43xx_wx_set_sensitivity(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -241,7 +216,6 @@ static int bcm43xx_wx_get_sensitivity(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -257,8 +231,6 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, unsigned long flags; int i, j; - wx_enter(); - data->data.length = sizeof(*range); memset(range, 0, sizeof(*range)); @@ -355,8 +327,6 @@ static int bcm43xx_wx_set_nick(struct net_device *net_dev, unsigned long flags; size_t len; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); memcpy(bcm->nick, extra, len); @@ -375,8 +345,6 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev, unsigned long flags; size_t len; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); len = strlen(bcm->nick) + 1; memcpy(extra, bcm->nick, len); @@ -396,8 +364,6 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); if (data->rts.disabled) { bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; @@ -422,8 +388,6 @@ static int bcm43xx_wx_get_rts(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); data->rts.value = bcm->rts_threshold; data->rts.fixed = 0; @@ -442,8 +406,6 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); if (data->frag.disabled) { bcm->ieee->fts = MAX_FRAG_THRESHOLD; @@ -468,8 +430,6 @@ static int bcm43xx_wx_get_frag(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); data->frag.value = bcm->ieee->fts; data->frag.fixed = 0; @@ -491,8 +451,6 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, int err = -ENODEV; u16 maxpower; - wx_enter(); - if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { printk(PFX KERN_ERR "TX power not in dBm.\n"); return -EOPNOTSUPP; @@ -537,8 +495,6 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, unsigned long flags; int err = -ENODEV; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); if (!bcm->initialized) goto out_unlock; @@ -561,7 +517,6 @@ static int bcm43xx_wx_set_retry(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -571,7 +526,6 @@ static int bcm43xx_wx_get_retry(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -584,8 +538,6 @@ static int bcm43xx_wx_set_encoding(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); int err; - wx_enter(); - err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra); return err; @@ -599,8 +551,6 @@ static int bcm43xx_wx_set_encodingext(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); int err; - wx_enter(); - err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra); return err; @@ -614,8 +564,6 @@ static int bcm43xx_wx_get_encoding(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); int err; - wx_enter(); - err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra); return err; @@ -629,8 +577,6 @@ static int bcm43xx_wx_get_encodingext(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); int err; - wx_enter(); - err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra); return err; @@ -641,7 +587,6 @@ static int bcm43xx_wx_set_power(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -651,7 +596,6 @@ static int bcm43xx_wx_get_power(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -665,8 +609,6 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, unsigned long flags; int mode, err = 0; - wx_enter(); - mode = *((int *)extra); switch (mode) { case 0: @@ -717,8 +659,6 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, unsigned long flags; int mode; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); mode = bcm->current_core->radio->interfmode; spin_unlock_irqrestore(&bcm->lock, flags); @@ -750,8 +690,6 @@ static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, unsigned long flags; int on; - wx_enter(); - on = *((int *)extra); spin_lock_irqsave(&bcm->lock, flags); bcm->short_preamble = !!on; @@ -769,8 +707,6 @@ static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, unsigned long flags; int on; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); on = bcm->short_preamble; spin_unlock_irqrestore(&bcm->lock, flags); @@ -793,8 +729,6 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, unsigned long flags; int on; - wx_enter(); - on = *((int *)extra); spin_lock_irqsave(&bcm->lock, flags); bcm->ieee->host_encrypt = !!on; @@ -815,8 +749,6 @@ static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, unsigned long flags; int on; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); on = bcm->ieee->host_encrypt; spin_unlock_irqrestore(&bcm->lock, flags); -- cgit v1.2.3-59-g8ed1b From 77db31ea4322f2dd12dc814d6664ae96517604c0 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Feb 2006 16:47:44 +0100 Subject: [PATCH] bcm43xx: Partially fix PIO code. Add Kconfig option for PIO or DMA mode (or both). Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 18 +- drivers/net/wireless/bcm43xx/Kconfig | 57 +++++ drivers/net/wireless/bcm43xx/Makefile | 6 +- drivers/net/wireless/bcm43xx/bcm43xx.h | 29 ++- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 46 ++++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 69 +++-- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 383 ++++++++++++++-------------- drivers/net/wireless/bcm43xx/bcm43xx_pio.h | 78 +++++- 8 files changed, 438 insertions(+), 248 deletions(-) create mode 100644 drivers/net/wireless/bcm43xx/Kconfig (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 3b1363c97191..5c4d7b4ece5e 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -500,23 +500,7 @@ config PRISM54 will be called prism54.ko. source "drivers/net/wireless/hostap/Kconfig" - -config BCM43XX - tristate "Broadcom BCM43xx wireless support" - depends on PCI && IEEE80211 && NET_RADIO && IEEE80211_SOFTMAC && EXPERIMENTAL - select FW_LOADER - ---help--- - This is an experimental driver for the Broadcom 43xx wireless chip, - found in the Apple Airport Extreme and various other devices. - -config BCM43XX_DEBUG - bool "Broadcom BCM43xx debugging (RECOMMENDED)" - depends on BCM43XX - default y - ---help--- - Broadcom 43xx debugging messages. - Say Y, because the driver is still very experimental and - this will help you get it running. +source "drivers/net/wireless/bcm43xx/Kconfig" # yes, this works even when no drivers are selected config NET_WIRELESS diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig new file mode 100644 index 000000000000..d8d23155ee3c --- /dev/null +++ b/drivers/net/wireless/bcm43xx/Kconfig @@ -0,0 +1,57 @@ +config BCM43XX + tristate "Broadcom BCM43xx wireless support" + depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL + select FW_LOADER + ---help--- + This is an experimental driver for the Broadcom 43xx wireless chip, + found in the Apple Airport Extreme and various other devices. + +config BCM43XX_DEBUG + bool "Broadcom BCM43xx debugging (RECOMMENDED)" + depends on BCM43XX + default y + ---help--- + Broadcom 43xx debugging messages. + Say Y, because the driver is still very experimental and + this will help you get it running. + +config BCM43XX_DMA + bool +config BCM43XX_PIO + bool + +choice + prompt "BCM43xx data transfer mode" + depends on BCM43XX + default BCM43XX_DMA_AND_PIO + +config BCM43XX_DMA_AND_PIO_MODE + bool "DMA + PIO" + select BCM43XX_DMA + select BCM43XX_PIO + ---help--- + Include both, Direct Memory Access (DMA) and Programmed I/O (PIO) + data transfer modes. + The actually used mode is selectable through the module + parameter "pio". If the module parameter is pio=0, DMA is used. + Otherwise PIO is used. DMA is default. + + If unsure, choose this option. + +config BCM43XX_DMA_MODE + bool "DMA (Direct Memory Access) only" + select BCM43XX_DMA + ---help--- + Only include Direct Memory Access (DMA). + This reduces the size of the driver module, by omitting the PIO code. + +config BCM43XX_PIO_MODE + bool "PIO (Programmed I/O) only" + select BCM43XX_PIO + ---help--- + Only include Programmed I/O (PIO). + This reduces the size of the driver module, by omitting the DMA code. + Please note that PIO transfers are slow (compared to DMA). + Only use PIO, if DMA does not work for you. + +endchoice diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile index e025e9f052b2..c87c1525b39f 100644 --- a/drivers/net/wireless/bcm43xx/Makefile +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -1,9 +1,11 @@ obj-$(CONFIG_BCM43XX) += bcm43xx.o bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o -bcm43xx-objs := bcm43xx_main.o bcm43xx_dma.o \ +bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o +bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o + +bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \ bcm43xx_radio.o bcm43xx_phy.o \ bcm43xx_power.o bcm43xx_wx.o \ - bcm43xx_pio.o bcm43xx_ilt.o \ bcm43xx_leds.o bcm43xx_ethtool.o \ $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 981d563f5738..3d8ac7e952cc 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -639,7 +639,7 @@ struct bcm43xx_private { u32 initialized:1, /* init_board() succeed */ was_initialized:1, /* for PCI suspend/resume. */ shutting_down:1, /* free_board() in progress */ - pio_mode:1, /* PIO (if true), or DMA (if false) used. */ + __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. */ @@ -749,6 +749,33 @@ struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) return ieee80211softmac_priv(dev); } + +/* Helper function, which returns a boolean. + * TRUE, if PIO is used; FALSE, if DMA is used. + */ +#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO) +static inline +int bcm43xx_using_pio(struct bcm43xx_private *bcm) +{ + return bcm->__using_pio; +} +#elif defined(CONFIG_BCM43XX_DMA) +static inline +int bcm43xx_using_pio(struct bcm43xx_private *bcm) +{ + return 0; +} +#elif defined(CONFIG_BCM43XX_PIO) +static inline +int bcm43xx_using_pio(struct bcm43xx_private *bcm) +{ + return 1; +} +#else +# error "Using neither DMA nor PIO? Confused..." +#endif + + static inline int bcm43xx_num_80211_cores(struct bcm43xx_private *bcm) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index 93e99d61f2e1..88ad34dff2f2 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -94,6 +94,10 @@ #define BCM43xx_TXRESUME_PERCENT 50 + +#ifdef CONFIG_BCM43XX_DMA + + struct sk_buff; struct bcm43xx_private; struct bcm43xx_xmitstatus; @@ -172,4 +176,46 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, struct ieee80211_txb *txb); void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); + +#else /* CONFIG_BCM43XX_DMA */ + + +static inline +int bcm43xx_dma_init(struct bcm43xx_private *bcm) +{ + return 0; +} +static inline +void bcm43xx_dma_free(struct bcm43xx_private *bcm) +{ +} +static inline +int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, + u16 dmacontroller_mmio_base) +{ + return 0; +} +static inline +int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, + u16 dmacontroller_mmio_base) +{ + return 0; +} +static inline +int bcm43xx_dma_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) +{ + return 0; +} +static inline +void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) +{ +} +static inline +void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) +{ +} + +#endif /* CONFIG_BCM43XX_DMA */ #endif /* BCM43xx_DMA_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 4c4a2d71ca04..4e49da99818d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -62,10 +62,15 @@ MODULE_LICENSE("GPL"); extern char *nvram_get(char *name); #endif -/* Module parameters */ +#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO) static int modparam_pio; module_param_named(pio, modparam_pio, int, 0444); MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); +#elif defined(CONFIG_BCM43XX_DMA) +# define modparam_pio 0 +#elif defined(CONFIG_BCM43XX_PIO) +# define modparam_pio 1 +#endif static int modparam_bad_frames_preempt; module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); @@ -1528,7 +1533,8 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) { u32 flags = 0x00040000; - if ((bcm43xx_core_enabled(bcm)) && (!bcm->pio_mode)) { + if ((bcm43xx_core_enabled(bcm)) && + !bcm43xx_using_pio(bcm)) { //FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here? #ifndef CONFIG_BCM947XX /* reset all used DMA controllers. */ @@ -1635,7 +1641,7 @@ static inline void handle_irq_transmit_status(struct bcm43xx_private *bcm) } //TODO: There are more (unknown) flags to test. see bcm43xx_main.h - if (bcm->pio_mode) + if (bcm43xx_using_pio(bcm)) bcm43xx_pio_handle_xmitstatus(bcm, &stat); else bcm43xx_dma_handle_xmitstatus(bcm, &stat); @@ -1933,7 +1939,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE)); assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { - if (bcm->pio_mode) + if (bcm43xx_using_pio(bcm)) bcm43xx_pio_rx(bcm->current_core->pio->queue0); else bcm43xx_dma_rx(bcm->current_core->dma->rx_ring0); @@ -1941,7 +1947,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) } if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { if (likely(bcm->current_core->rev < 5)) { - if (bcm->pio_mode) + if (bcm43xx_using_pio(bcm)) bcm43xx_pio_rx(bcm->current_core->pio->queue3); else bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1); @@ -1999,7 +2005,7 @@ void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) & 0x0001dc00; - if ((bcm->pio_mode) && + if (bcm43xx_using_pio(bcm) && (bcm->current_core->rev < 3) && (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) { /* Apply a PIO specific workaround to the dma_reasons */ @@ -2624,7 +2630,7 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) value32 |= 0x100000; //FIXME: What's this? Is this correct? bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - if (bcm->pio_mode) { + if (bcm43xx_using_pio(bcm)) { bcm43xx_write32(bcm, 0x0210, 0x00000100); bcm43xx_write32(bcm, 0x0230, 0x00000100); bcm43xx_write32(bcm, 0x0250, 0x00000100); @@ -3123,15 +3129,12 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) if (bcm->current_core->rev >= 5) bcm43xx_write16(bcm, 0x043C, 0x000C); - if (!bcm->pio_mode) { - err = bcm43xx_dma_init(bcm); - if (err) - goto err_chip_cleanup; - } else { + if (bcm43xx_using_pio(bcm)) err = bcm43xx_pio_init(bcm); - if (err) - goto err_chip_cleanup; - } + else + err = bcm43xx_dma_init(bcm); + if (err) + goto err_chip_cleanup; bcm43xx_write16(bcm, 0x0612, 0x0050); bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); @@ -4001,8 +4004,8 @@ static inline int bcm43xx_tx(struct bcm43xx_private *bcm, { int err = -ENODEV; - if (bcm->pio_mode) - err = bcm43xx_pio_transfer_txb(bcm, txb); + if (bcm43xx_using_pio(bcm)) + err = bcm43xx_pio_tx(bcm, txb); else err = bcm43xx_dma_tx(bcm, txb); @@ -4158,10 +4161,10 @@ static int bcm43xx_net_stop(struct net_device *net_dev) return 0; } -static void bcm43xx_init_private(struct bcm43xx_private *bcm, - struct net_device *net_dev, - struct pci_dev *pci_dev, - struct workqueue_struct *wq) +static int bcm43xx_init_private(struct bcm43xx_private *bcm, + struct net_device *net_dev, + struct pci_dev *pci_dev, + struct workqueue_struct *wq) { bcm->ieee = netdev_priv(net_dev); bcm->softmac = ieee80211_priv(net_dev); @@ -4190,13 +4193,17 @@ static void bcm43xx_init_private(struct bcm43xx_private *bcm, (unsigned long)bcm); tasklet_disable_nosync(&bcm->isr_tasklet); if (modparam_pio) { - bcm->pio_mode = 1; + bcm->__using_pio = 1; } else { - if (pci_set_dma_mask(pci_dev, DMA_30BIT_MASK) == 0) { - bcm->pio_mode = 0; - } else { + if (pci_set_dma_mask(pci_dev, DMA_30BIT_MASK)) { +#ifdef CONFIG_BCM43XX_PIO printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n"); - bcm->pio_mode = 1; + bcm->__using_pio = 1; +#else + printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. " + "Recompile the driver with PIO support, please.\n"); + return -ENODEV; +#endif /* CONFIG_BCM43XX_PIO */ } } bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; @@ -4210,6 +4217,8 @@ static void bcm43xx_init_private(struct bcm43xx_private *bcm, bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr); bcm->ieee->set_security = bcm43xx_ieee80211_set_security; bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit; + + return 0; } static int __devinit bcm43xx_init_one(struct pci_dev *pdev, @@ -4261,7 +4270,9 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, err = -ENOMEM; goto err_free_netdev; } - bcm43xx_init_private(bcm, net_dev, pdev, wq); + err = bcm43xx_init_private(bcm, net_dev, pdev, wq); + if (err) + goto err_destroy_wq; pci_set_drvdata(pdev, net_dev); @@ -4325,7 +4336,9 @@ static void bcm43xx_chip_reset(void *_bcm) bcm43xx_free_board(bcm); bcm->firmware_norelease = 0; bcm43xx_detach_board(bcm); - bcm43xx_init_private(bcm, net_dev, pci_dev, wq); + err = bcm43xx_init_private(bcm, net_dev, pci_dev, wq); + if (err) + goto failure; err = bcm43xx_attach_board(bcm); if (err) goto failure; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 9a55e9d00528..0bf4b3e26f9d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -30,81 +30,88 @@ #include -static inline -u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue, - u16 offset) +static void tx_start(struct bcm43xx_pioqueue *queue) { - return bcm43xx_read16(queue->bcm, queue->mmio_base + offset); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_INIT); } -static inline -void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, - u16 offset, u16 value) +static void tx_octet(struct bcm43xx_pioqueue *queue, + u8 octet) { - bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); + if (queue->need_workarounds) { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, + octet); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_WRITEHI); + } else { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_WRITEHI); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, + octet); + } } -static inline -void tx_start(struct bcm43xx_pioqueue *queue) +static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr, + const u8 *packet, + unsigned int *pos) { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_INIT); -} + const u8 *source; + unsigned int i = *pos; + u16 ret; -static inline -void tx_octet(struct bcm43xx_pioqueue *queue, - u8 octet) -{ - if (queue->bcm->current_core->rev < 3) { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, octet); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_WRITEHI); + if (i < sizeof(*txhdr)) { + source = (const u8 *)txhdr; } else { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_WRITEHI); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, octet); + source = packet; + i -= sizeof(*txhdr); } + ret = le16_to_cpu( *((u16 *)(source + i)) ); + *pos += 2; + + return ret; } -static inline -void tx_data(struct bcm43xx_pioqueue *queue, - u8 *packet, - unsigned int octets) +static void tx_data(struct bcm43xx_pioqueue *queue, + struct bcm43xx_txhdr *txhdr, + const u8 *packet, + unsigned int octets) { u16 data; unsigned int i = 0; - if (queue->bcm->current_core->rev < 3) { - data = be16_to_cpu( *((u16 *)packet) ); + if (queue->need_workarounds) { + data = tx_get_next_word(txhdr, packet, &i); bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); - i += 2; } bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITELO | BCM43xx_PIO_TXCTL_WRITEHI); - for ( ; i < octets - 1; i += 2) { - data = be16_to_cpu( *((u16 *)(packet + i)) ); + BCM43xx_PIO_TXCTL_WRITELO | + BCM43xx_PIO_TXCTL_WRITEHI); + while (i < octets - 1) { + data = tx_get_next_word(txhdr, packet, &i); bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); } if (octets % 2) - tx_octet(queue, packet[octets - 1]); + tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]); } -static inline -void tx_complete(struct bcm43xx_pioqueue *queue, - struct sk_buff *skb) +static void tx_complete(struct bcm43xx_pioqueue *queue, + struct sk_buff *skb) { - u16 data; - - if (queue->bcm->current_core->rev < 3) { - data = be16_to_cpu( *((u16 *)(skb->data + skb->len - 2)) ); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); + if (queue->need_workarounds) { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, + skb->data[skb->len - 1]); bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITEHI | BCM43xx_PIO_TXCTL_COMPLETE); + BCM43xx_PIO_TXCTL_WRITEHI | + BCM43xx_PIO_TXCTL_COMPLETE); } else { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_COMPLETE); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_COMPLETE); } } -static inline -u16 generate_cookie(struct bcm43xx_pioqueue *queue, - int packetindex) +static u16 generate_cookie(struct bcm43xx_pioqueue *queue, + int packetindex) { u16 cookie = 0x0000; @@ -113,8 +120,6 @@ u16 generate_cookie(struct bcm43xx_pioqueue *queue, * for the packet index (in the cache). */ switch (queue->mmio_base) { - default: - assert(0); case BCM43xx_MMIO_PIO1_BASE: break; case BCM43xx_MMIO_PIO2_BASE: @@ -126,6 +131,8 @@ u16 generate_cookie(struct bcm43xx_pioqueue *queue, case BCM43xx_MMIO_PIO4_BASE: cookie = 0x3000; break; + default: + assert(0); } assert(((u16)packetindex & 0xF000) == 0x0000); cookie |= (u16)packetindex; @@ -133,66 +140,75 @@ u16 generate_cookie(struct bcm43xx_pioqueue *queue, return cookie; } -static inline +static struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm, u16 cookie, struct bcm43xx_pio_txpacket **packet) { + struct bcm43xx_pio *pio = bcm->current_core->pio; struct bcm43xx_pioqueue *queue = NULL; int packetindex; switch (cookie & 0xF000) { case 0x0000: - queue = bcm->current_core->pio->queue0; + queue = pio->queue0; break; case 0x1000: - queue = bcm->current_core->pio->queue1; + queue = pio->queue1; break; case 0x2000: - queue = bcm->current_core->pio->queue2; + queue = pio->queue2; break; case 0x3000: - queue = bcm->current_core->pio->queue3; + queue = pio->queue3; break; default: assert(0); } - packetindex = (cookie & 0x0FFF); assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS); - *packet = queue->__tx_packets_cache + packetindex; + *packet = &(queue->tx_packets_cache[packetindex]); return queue; } -static inline -void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, - struct sk_buff *skb, - struct bcm43xx_pio_txpacket *packet) +static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, + struct sk_buff *skb, + struct bcm43xx_pio_txpacket *packet) { + struct bcm43xx_txhdr txhdr; unsigned int octets; assert(skb_shinfo(skb)->nr_frags == 0); - assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); - - __skb_push(skb, sizeof(struct bcm43xx_txhdr)); bcm43xx_generate_txhdr(queue->bcm, - (struct bcm43xx_txhdr *)skb->data, - skb->data + sizeof(struct bcm43xx_txhdr), - skb->len - sizeof(struct bcm43xx_txhdr), + &txhdr, skb->data, skb->len, (packet->xmitted_frags == 0), generate_cookie(queue, pio_txpacket_getindex(packet))); tx_start(queue); - octets = skb->len; - if (queue->bcm->current_core->rev < 3) //FIXME: && this is the last packet in the queue. - octets -= 2; - tx_data(queue, (u8 *)skb->data, octets); + octets = skb->len + sizeof(txhdr); + if (queue->need_workarounds) + octets--; + tx_data(queue, &txhdr, (u8 *)skb->data, octets); tx_complete(queue, skb); } -static inline -int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) +static void free_txpacket(struct bcm43xx_pio_txpacket *packet, + int irq_context) +{ + struct bcm43xx_pioqueue *queue = packet->queue; + + ieee80211_txb_free(packet->txb); + list_move(&packet->list, &queue->txfree); + queue->nr_txfree++; + + assert(queue->tx_devq_used >= packet->xmitted_octets); + assert(queue->tx_devq_packets >= packet->xmitted_frags); + queue->tx_devq_used -= packet->xmitted_octets; + queue->tx_devq_packets -= packet->xmitted_frags; +} + +static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) { struct bcm43xx_pioqueue *queue = packet->queue; struct ieee80211_txb *txb = packet->txb; @@ -204,12 +220,11 @@ int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) skb = txb->fragments[i]; octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr); - assert(queue->tx_devq_size >= octets); assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS); assert(queue->tx_devq_used <= queue->tx_devq_size); /* Check if there is sufficient free space on the device - * TX queue. If not, return and let the TX-work-handler + * TX queue. If not, return and let the TX tasklet * retry later. */ if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS) @@ -234,28 +249,15 @@ int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) return 0; } -static void free_txpacket(struct bcm43xx_pio_txpacket *packet) +static void tx_tasklet(unsigned long d) { - struct bcm43xx_pioqueue *queue = packet->queue; - - ieee80211_txb_free(packet->txb); - - list_move(&packet->list, &packet->queue->txfree); - - assert(queue->tx_devq_used >= packet->xmitted_octets); - queue->tx_devq_used -= packet->xmitted_octets; - assert(queue->tx_devq_packets >= packet->xmitted_frags); - queue->tx_devq_packets -= packet->xmitted_frags; -} - -static void txwork_handler(void *d) -{ - struct bcm43xx_pioqueue *queue = d; + struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d; + struct bcm43xx_private *bcm = queue->bcm; unsigned long flags; struct bcm43xx_pio_txpacket *packet, *tmp_packet; int err; - spin_lock_irqsave(&queue->txlock, flags); + spin_lock_irqsave(&bcm->lock, flags); list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { assert(packet->xmitted_frags < packet->txb->nr_frags); if (packet->xmitted_frags == 0) { @@ -270,22 +272,22 @@ static void txwork_handler(void *d) skb = packet->txb->fragments[i]; if (unlikely(skb->len > queue->tx_devq_size)) { dprintkl(KERN_ERR PFX "PIO TX device queue too small. " - "Dropping packet...\n"); - free_txpacket(packet); + "Dropping packet.\n"); + free_txpacket(packet, 1); goto next_packet; } } } - /* Now try to transmit the packet. + /* Try to transmit the packet. * This may not completely succeed. */ err = pio_tx_packet(packet); if (err) break; -next_packet: + next_packet: continue; } - spin_unlock_irqrestore(&queue->txlock, flags); + spin_unlock_irqrestore(&bcm->lock, flags); } static void setup_txqueues(struct bcm43xx_pioqueue *queue) @@ -293,8 +295,9 @@ static void setup_txqueues(struct bcm43xx_pioqueue *queue) struct bcm43xx_pio_txpacket *packet; int i; + queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS; for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) { - packet = queue->__tx_packets_cache + i; + packet = &(queue->tx_packets_cache[i]); packet->queue = queue; INIT_LIST_HEAD(&packet->list); @@ -311,19 +314,19 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, u32 value; u16 qsize; - queue = kmalloc(sizeof(*queue), GFP_KERNEL); + queue = kzalloc(sizeof(*queue), GFP_KERNEL); if (!queue) goto out; - memset(queue, 0, sizeof(*queue)); queue->bcm = bcm; queue->mmio_base = pio_mmio_base; + queue->need_workarounds = (bcm->current_core->rev < 3); INIT_LIST_HEAD(&queue->txfree); INIT_LIST_HEAD(&queue->txqueue); INIT_LIST_HEAD(&queue->txrunning); - spin_lock_init(&queue->txlock); - INIT_WORK(&queue->txwork, txwork_handler, queue); + tasklet_init(&queue->txtask, tx_tasklet, + (unsigned long)queue); value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); value |= BCM43xx_SBF_XFER_REG_BYTESWAP; @@ -331,7 +334,7 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); if (qsize <= BCM43xx_PIO_TXQADJUST) { - printk(KERN_ERR PFX "PIO tx queue too small (%u)\n", qsize); + printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize); goto err_freequeue; } qsize -= BCM43xx_PIO_TXQADJUST; @@ -354,13 +357,12 @@ static void cancel_transfers(struct bcm43xx_pioqueue *queue) netif_tx_disable(queue->bcm->net_dev); assert(queue->bcm->shutting_down); - cancel_delayed_work(&queue->txwork); - flush_workqueue(queue->bcm->workqueue); + tasklet_disable(&queue->txtask); list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) - free_txpacket(packet); + free_txpacket(packet, 0); list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) - free_txpacket(packet); + free_txpacket(packet, 0); } static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) @@ -374,40 +376,43 @@ static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) void bcm43xx_pio_free(struct bcm43xx_private *bcm) { - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue3); - bcm->current_core->pio->queue3 = NULL; - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue2); - bcm->current_core->pio->queue2 = NULL; - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue1); - bcm->current_core->pio->queue1 = NULL; - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue0); - bcm->current_core->pio->queue0 = NULL; + struct bcm43xx_pio *pio = bcm->current_core->pio; + + bcm43xx_destroy_pioqueue(pio->queue3); + pio->queue3 = NULL; + bcm43xx_destroy_pioqueue(pio->queue2); + pio->queue2 = NULL; + bcm43xx_destroy_pioqueue(pio->queue1); + pio->queue1 = NULL; + bcm43xx_destroy_pioqueue(pio->queue0); + pio->queue0 = NULL; } int bcm43xx_pio_init(struct bcm43xx_private *bcm) { + struct bcm43xx_pio *pio = bcm->current_core->pio; struct bcm43xx_pioqueue *queue; int err = -ENOMEM; queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE); if (!queue) goto out; - bcm->current_core->pio->queue0 = queue; + pio->queue0 = queue; queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE); if (!queue) goto err_destroy0; - bcm->current_core->pio->queue1 = queue; + pio->queue1 = queue; queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE); if (!queue) goto err_destroy1; - bcm->current_core->pio->queue2 = queue; + pio->queue2 = queue; queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE); if (!queue) goto err_destroy2; - bcm->current_core->pio->queue3 = queue; + pio->queue3 = queue; if (bcm->current_core->rev < 3) bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND; @@ -418,41 +423,38 @@ out: return err; err_destroy2: - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue2); - bcm->current_core->pio->queue2 = NULL; + bcm43xx_destroy_pioqueue(pio->queue2); + pio->queue2 = NULL; err_destroy1: - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue1); - bcm->current_core->pio->queue1 = NULL; + bcm43xx_destroy_pioqueue(pio->queue1); + pio->queue1 = NULL; err_destroy0: - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue0); - bcm->current_core->pio->queue0 = NULL; + bcm43xx_destroy_pioqueue(pio->queue0); + pio->queue0 = NULL; goto out; } -static inline -int pio_transfer_txb(struct bcm43xx_pioqueue *queue, - struct ieee80211_txb *txb) +int bcm43xx_pio_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) { + struct bcm43xx_pioqueue *queue = bcm->current_core->pio->queue1; struct bcm43xx_pio_txpacket *packet; - unsigned long flags; u16 tmp; - spin_lock_irqsave(&queue->txlock, flags); assert(!queue->tx_suspended); assert(!list_empty(&queue->txfree)); tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); - if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) { - spin_unlock_irqrestore(&queue->txlock, flags); + if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) return -EBUSY; - } packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); - packet->txb = txb; - list_move_tail(&packet->list, &queue->txqueue); - packet->xmitted_octets = 0; packet->xmitted_frags = 0; + packet->xmitted_octets = 0; + list_move_tail(&packet->list, &queue->txqueue); + queue->nr_txfree--; + assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); /* Suspend TX, if we are out of packets in the "free" queue. */ if (unlikely(list_empty(&queue->txfree))) { @@ -460,69 +462,66 @@ int pio_transfer_txb(struct bcm43xx_pioqueue *queue, queue->tx_suspended = 1; } - spin_unlock_irqrestore(&queue->txlock, flags); - queue_work(queue->bcm->workqueue, &queue->txwork); + tasklet_schedule(&queue->txtask); return 0; } -int fastcall bcm43xx_pio_transfer_txb(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - return pio_transfer_txb(bcm->current_core->pio->queue1, txb); -} - -void fastcall -bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) +void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) { struct bcm43xx_pioqueue *queue; struct bcm43xx_pio_txpacket *packet; - unsigned long flags; queue = parse_cookie(bcm, status->cookie, &packet); assert(queue); - spin_lock_irqsave(&queue->txlock, flags); - free_txpacket(packet); +//TODO +if (!queue) +return; + free_txpacket(packet, 1); if (unlikely(queue->tx_suspended)) { queue->tx_suspended = 0; netif_wake_queue(queue->bcm->net_dev); } - - /* If there are packets on the txqueue, - * start the work handler again. - */ - if (!list_empty(&queue->txqueue)) { - queue_work(queue->bcm->workqueue, - &queue->txwork); - } - spin_unlock_irqrestore(&queue->txlock, flags); + /* If there are packets on the txqueue, poke the tasklet. */ + if (!list_empty(&queue->txqueue)) + tasklet_schedule(&queue->txtask); } static void pio_rx_error(struct bcm43xx_pioqueue *queue, + int clear_buffers, const char *error) { - printk("PIO RX error: %s\n", error); - bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, BCM43xx_PIO_RXCTL_READY); + int i; + + printkl("PIO RX error: %s\n", error); + bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, + BCM43xx_PIO_RXCTL_READY); + if (clear_buffers) { + assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE); + for (i = 0; i < 15; i++) { + /* Dummy read. */ + bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); + } + } } -void fastcall -bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) +void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) { u16 preamble[21] = { 0 }; struct bcm43xx_rxhdr *rxhdr; - u16 tmp; - u16 len; - int i, err; - int preamble_readwords; + u16 tmp, len, rxflags2; + int i, preamble_readwords; struct sk_buff *skb; +return; tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) { - dprintkl(KERN_ERR PFX "PIO RX: No data available\n"); + dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk. return; } - bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, BCM43xx_PIO_RXCTL_DATAAVAILABLE); + bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, + BCM43xx_PIO_RXCTL_DATAAVAILABLE); for (i = 0; i < 10; i++) { tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); @@ -534,13 +533,14 @@ bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) return; data_ready: +//FIXME: endianess in this function. len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); if (unlikely(len > 0x700)) { - pio_rx_error(queue, "len > 0x700"); + pio_rx_error(queue, 0, "len > 0x700"); return; } if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) { - pio_rx_error(queue, "len == 0"); + pio_rx_error(queue, 0, "len == 0"); return; } preamble[0] = cpu_to_le16(len); @@ -550,28 +550,38 @@ data_ready: preamble_readwords = 18 / sizeof(u16); for (i = 0; i < preamble_readwords; i++) { tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - preamble[i + 1] = cpu_to_be16(tmp); + preamble[i + 1] = cpu_to_be16(tmp);//FIXME? } rxhdr = (struct bcm43xx_rxhdr *)preamble; - if (unlikely(rxhdr->flags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) { - pio_rx_error(queue, "invalid frame"); - if (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE) { - for (i = 0; i < 15; i++) - bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); /* dummy read. */ - } + rxflags2 = le16_to_cpu(rxhdr->flags2); + if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) { + pio_rx_error(queue, + (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE), + "invalid frame"); return; } -//FIXME -#if 0 if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) { - bcm43xx_rx_transmitstatus(queue->bcm, - (const struct bcm43xx_hwxmitstatus *)(preamble + 1)); + /* We received an xmit status. */ + struct bcm43xx_hwxmitstatus *hw; + struct bcm43xx_xmitstatus stat; + + hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1); + stat.cookie = le16_to_cpu(hw->cookie); + stat.flags = hw->flags; + stat.cnt1 = hw->cnt1; + stat.cnt2 = hw->cnt2; + stat.seq = le16_to_cpu(hw->seq); + stat.unknown = le16_to_cpu(hw->unknown); + + bcm43xx_debugfs_log_txstat(queue->bcm, &stat); + bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat); + return; } -#endif + skb = dev_alloc_skb(len); if (unlikely(!skb)) { - pio_rx_error(queue, "out of memory"); + pio_rx_error(queue, 1, "OOM"); return; } skb_put(skb, len); @@ -580,13 +590,14 @@ data_ready: *((u16 *)(skb->data + i)) = tmp; } if (len % 2) { - tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); + tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); skb->data[len - 1] = (tmp & 0x00FF); - skb->data[0] = (tmp & 0xFF00) >> 8; + if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) + skb->data[0x20] = (tmp & 0xFF00) >> 8; + else + skb->data[0x1E] = (tmp & 0xFF00) >> 8; } - err = bcm43xx_rx(queue->bcm, skb, rxhdr); - if (unlikely(err)) - dev_kfree_skb_irq(skb); + bcm43xx_rx(queue->bcm, skb, rxhdr); } /* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h index 71b92ee34169..970627bc1769 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h @@ -3,9 +3,8 @@ #include "bcm43xx.h" +#include #include -#include -#include #include @@ -32,6 +31,10 @@ #define BCM43xx_PIO_MAXTXPACKETS 256 + +#ifdef CONFIG_BCM43XX_PIO + + struct bcm43xx_pioqueue; struct bcm43xx_xmitstatus; @@ -44,13 +47,14 @@ struct bcm43xx_pio_txpacket { u16 xmitted_octets; }; -#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->__tx_packets_cache)) +#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache)) struct bcm43xx_pioqueue { struct bcm43xx_private *bcm; u16 mmio_base; - u8 tx_suspended:1; + u8 tx_suspended:1, + need_workarounds:1; /* Workarounds needed for core.rev < 3 */ /* Adjusted size of the device internal TX buffer. */ u16 tx_devq_size; @@ -62,6 +66,7 @@ struct bcm43xx_pioqueue { * be taken on incoming TX requests. */ struct list_head txfree; + unsigned int nr_txfree; /* Packets on the txqueue are queued, * but not completely written to the chip, yet. */ @@ -70,19 +75,64 @@ struct bcm43xx_pioqueue { * posted to the device. We are waiting for the txstatus. */ struct list_head txrunning; - /* Locking of the TX queues and the accounting. */ - spinlock_t txlock; - struct work_struct txwork; - struct bcm43xx_pio_txpacket __tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS]; + /* Total number or packets sent. + * (This counter can obviously wrap). + */ + unsigned int nr_tx_packets; + struct tasklet_struct txtask; + struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS]; }; +static inline +u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue, + u16 offset) +{ + return bcm43xx_read16(queue->bcm, queue->mmio_base + offset); +} + +static inline +void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, + u16 offset, u16 value) +{ + bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); +} + + int bcm43xx_pio_init(struct bcm43xx_private *bcm); void bcm43xx_pio_free(struct bcm43xx_private *bcm); -int FASTCALL(bcm43xx_pio_transfer_txb(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb)); -void FASTCALL(bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status)); - -void FASTCALL(bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)); +int bcm43xx_pio_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb); +void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status); +void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); + +#else /* CONFIG_BCM43XX_PIO */ + +static inline +int bcm43xx_pio_init(struct bcm43xx_private *bcm) +{ + return 0; +} +static inline +void bcm43xx_pio_free(struct bcm43xx_private *bcm) +{ +} +static inline +int bcm43xx_pio_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) +{ + return 0; +} +static inline +void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) +{ +} +static inline +void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) +{ +} + +#endif /* CONFIG_BCM43XX_PIO */ #endif /* BCM43xx_PIO_H_ */ -- cgit v1.2.3-59-g8ed1b From 8bcab3f55982cf28310f2303bef741424ad0f563 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Feb 2006 16:52:10 +0100 Subject: [PATCH] bcm43xx: add a note that not all devices support PIO. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig index d8d23155ee3c..1d677c15b21c 100644 --- a/drivers/net/wireless/bcm43xx/Kconfig +++ b/drivers/net/wireless/bcm43xx/Kconfig @@ -52,6 +52,11 @@ config BCM43XX_PIO_MODE Only include Programmed I/O (PIO). This reduces the size of the driver module, by omitting the DMA code. Please note that PIO transfers are slow (compared to DMA). + + Also note that not all devices of the 43xx series support PIO. + The 4306 (Apple Airport Extreme and others) supports PIO, while + the 4318 is known to _not_ support PIO. + Only use PIO, if DMA does not work for you. endchoice -- cgit v1.2.3-59-g8ed1b From f1f566236dcc4cb57cfae89b539e19c1290e7f34 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Feb 2006 16:55:06 +0100 Subject: [PATCH] Apple Airport: Add Kconfig note that the bcm43xx driver has to be used for Airport Extreme cards. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 5c4d7b4ece5e..9c01fb26c8f3 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -309,7 +309,10 @@ config APPLE_AIRPORT Say Y here to support the Airport 802.11b wireless Ethernet hardware built into the Macintosh iBook and other recent PowerPC-based Macintosh machines. This is essentially a Lucent Orinoco card with - a non-standard interface + a non-standard interface. + + This driver does not support the Airport Extreme (802.11b/g). Use + the BCM43xx driver for Airport Extreme cards. config PLX_HERMES tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)" -- cgit v1.2.3-59-g8ed1b From dcfd720bd733544606b053e8e68b7419211ace72 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Feb 2006 20:25:55 +0100 Subject: [PATCH] bcm43xx: fix LED code. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 88 +++++++++++++++++++---------- drivers/net/wireless/bcm43xx/bcm43xx_leds.h | 11 +++- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 2 +- 3 files changed, 68 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 455a0c743f73..8f550c1a92ed 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -35,12 +35,13 @@ static void bcm43xx_led_changestate(struct bcm43xx_led *led) { struct bcm43xx_private *bcm = led->bcm; const int index = bcm43xx_led_index(led); + const u16 mask = (1 << index); u16 ledctl; assert(index >= 0 && index < BCM43xx_NR_LEDS); assert(led->blink_interval); ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - __change_bit(index, (unsigned long *)(&ledctl)); + ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask); bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); } @@ -61,6 +62,8 @@ static void bcm43xx_led_blink(unsigned long d) static void bcm43xx_led_blink_start(struct bcm43xx_led *led, unsigned long interval) { + if (led->blink_interval) + return; led->blink_interval = interval; bcm43xx_led_changestate(led); led->blink_timer.expires = jiffies + interval; @@ -91,6 +94,39 @@ static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync) bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); } +static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm, + struct bcm43xx_led *led, + int led_index) +{ + /* This function is called, if the behaviour (and activelow) + * information for a LED is missing in the SPROM. + * We hardcode the behaviour values for various devices here. + * Note that the BCM43xx_LED_TEST_XXX behaviour values can + * be used to figure out which led is mapped to which index. + */ + + switch (led_index) { + case 0: + led->behaviour = BCM43xx_LED_ACTIVITY; + if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ) + led->behaviour = BCM43xx_LED_RADIO_ALL; + break; + case 1: + led->behaviour = BCM43xx_LED_RADIO_B; + if (bcm->board_vendor == PCI_VENDOR_ID_ASUSTEK) + led->behaviour = BCM43xx_LED_ASSOC; + break; + case 2: + led->behaviour = BCM43xx_LED_RADIO_A; + break; + case 3: + led->behaviour = BCM43xx_LED_OFF; + break; + default: + assert(0); + } +} + int bcm43xx_leds_init(struct bcm43xx_private *bcm) { struct bcm43xx_led *led; @@ -105,31 +141,12 @@ int bcm43xx_leds_init(struct bcm43xx_private *bcm) for (i = 0; i < BCM43xx_NR_LEDS; i++) { led = &(bcm->leds[i]); led->bcm = bcm; - init_timer(&led->blink_timer); - led->blink_timer.data = (unsigned long)led; - led->blink_timer.function = bcm43xx_led_blink; + setup_timer(&led->blink_timer, + bcm43xx_led_blink, + (unsigned long)led); if (sprom[i] == 0xFF) { - /* SPROM information not set. */ - switch (i) { - case 0: - if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ) - led->behaviour = BCM43xx_LED_RADIO_ALL; - else - led->behaviour = BCM43xx_LED_ACTIVITY; - break; - case 1: - led->behaviour = BCM43xx_LED_RADIO_B; - break; - case 2: - led->behaviour = BCM43xx_LED_RADIO_A; - break; - case 3: - led->behaviour = BCM43xx_LED_OFF; - break; - default: - assert(0); - } + bcm43xx_led_init_hardcoded(bcm, led, i); } else { led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR; led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW); @@ -157,19 +174,19 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) struct bcm43xx_radioinfo *radio = bcm->current_core->radio; struct bcm43xx_phyinfo *phy = bcm->current_core->phy; const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES; - int i, turn_on = 0; + int i, turn_on; unsigned long interval = 0; u16 ledctl; ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); for (i = 0; i < BCM43xx_NR_LEDS; i++) { led = &(bcm->leds[i]); - if (led->behaviour == BCM43xx_LED_INACTIVE) - continue; + turn_on = 0; switch (led->behaviour) { + case BCM43xx_LED_INACTIVE: + continue; case BCM43xx_LED_OFF: - turn_on = 0; break; case BCM43xx_LED_ON: turn_on = 1; @@ -189,7 +206,6 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) phy->type == BCM43xx_PHYTYPE_G)); break; case BCM43xx_LED_MODE_BG: - turn_on = 0; if (phy->type == BCM43xx_PHYTYPE_G && 1/*FIXME: using G rates.*/) turn_on = 1; @@ -222,12 +238,22 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) continue; case BCM43xx_LED_WEIRD: //TODO - turn_on = 0; break; case BCM43xx_LED_ASSOC: - if (1/*TODO: associated*/) + if (bcm->softmac->associated) turn_on = 1; break; +#ifdef CONFIG_BCM43XX_DEBUG + case BCM43xx_LED_TEST_BLINKSLOW: + bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_SLOW); + continue; + case BCM43xx_LED_TEST_BLINKMEDIUM: + bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM); + continue; + case BCM43xx_LED_TEST_BLINKFAST: + bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_FAST); + continue; +#endif /* CONFIG_BCM43XX_DEBUG */ default: assert(0); }; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h index 489a2b1e9068..6f18e2f95db4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h @@ -16,7 +16,7 @@ struct bcm43xx_led { #define bcm43xx_led_index(led) ((int)((led) - (led)->bcm->leds)) /* Delay between state changes when blinking in jiffies */ -#define BCM43xx_LEDBLINK_SLOW (HZ / 2) +#define BCM43xx_LEDBLINK_SLOW (HZ / 1) #define BCM43xx_LEDBLINK_MEDIUM (HZ / 4) #define BCM43xx_LEDBLINK_FAST (HZ / 8) @@ -37,6 +37,15 @@ enum { /* LED behaviour values */ BCM43xx_LED_WEIRD,//FIXME BCM43xx_LED_ASSOC, BCM43xx_LED_INACTIVE, + + /* Behaviour values for testing. + * With these values it is easier to figure out + * the real behaviour of leds, in case the SPROM + * is missing information. + */ + BCM43xx_LED_TEST_BLINKSLOW, + BCM43xx_LED_TEST_BLINKMEDIUM, + BCM43xx_LED_TEST_BLINKFAST, }; int bcm43xx_leds_init(struct bcm43xx_private *bcm); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 4e49da99818d..fbf931d4a135 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1943,7 +1943,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) bcm43xx_pio_rx(bcm->current_core->pio->queue0); else bcm43xx_dma_rx(bcm->current_core->dma->rx_ring0); - activity = 1; + /* We intentionally don't set "activity" to 1, here. */ } if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { if (likely(bcm->current_core->rev < 5)) { -- cgit v1.2.3-59-g8ed1b From ab4977f881fc23cb02ef6f20d1e8ebbdcfef75ad Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Feb 2006 22:40:39 +0100 Subject: [PATCH] bcm43xx: rewrite and simplify the periodic task handling. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 13 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 194 ++++++++++------------------ 2 files changed, 73 insertions(+), 134 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 3d8ac7e952cc..99b2e72281ea 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -418,7 +418,6 @@ enum { struct net_device; struct pci_dev; -struct workqueue_struct; struct bcm43xx_dmaring; struct bcm43xx_pioqueue; @@ -706,18 +705,10 @@ struct bcm43xx_private { /* Interrupt Service Routine tasklet (bottom-half) */ struct tasklet_struct isr_tasklet; - /* Custom driver work queue. */ - struct workqueue_struct *workqueue; /* Periodic tasks */ - struct work_struct periodic_work0; -#define BCM43xx_PERIODIC_0_DELAY (HZ * 15) - struct work_struct periodic_work1; -#define BCM43xx_PERIODIC_1_DELAY ((HZ * 60) + HZ / 2) - struct work_struct periodic_work2; -#define BCM43xx_PERIODIC_2_DELAY ((HZ * 120) + HZ) - struct work_struct periodic_work3; -#define BCM43xx_PERIODIC_3_DELAY ((HZ * 30) + HZ / 5) + struct timer_list periodic_tasks; + unsigned int periodic_state; struct work_struct restart_work; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index fbf931d4a135..18152b0b2dd5 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2939,7 +2939,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) core->phy->minlowsigpos[1] = 0; spin_lock_init(&core->phy->lock); core->radio = &bcm->radio[i]; - core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; + core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; core->radio->channel = 0xFF; core->radio->initial_channel = 0xFF; core->radio->lofcal = 0xFFFF; @@ -3261,144 +3261,104 @@ static void bcm43xx_softmac_init(struct bcm43xx_private *bcm) ieee80211softmac_start(bcm->net_dev); } -static void bcm43xx_periodic_work0_handler(void *d) +static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) { - struct bcm43xx_private *bcm = d; - unsigned long flags; - //TODO: unsigned int aci_average; - - spin_lock_irqsave(&bcm->lock, flags); + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { - //FIXME: aci_average = bcm43xx_update_aci_average(bcm); - if (bcm->current_core->radio->aci_enable && bcm->current_core->radio->aci_wlan_automatic) { - bcm43xx_mac_suspend(bcm); - if (!bcm->current_core->radio->aci_enable && - 1 /*FIXME: We are not scanning? */) { - /*FIXME: First add bcm43xx_update_aci_average() before - * uncommenting this: */ - //if (bcm43xx_radio_aci_scan) - // bcm43xx_radio_set_interference_mitigation(bcm, - // BCM43xx_RADIO_INTERFMODE_MANUALWLAN); - } else if (1/*FIXME*/) { - //if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) - // bcm43xx_radio_set_interference_mitigation(bcm, - // BCM43xx_RADIO_INTERFMODE_MANUALWLAN); - } - bcm43xx_mac_enable(bcm); - } else if (bcm->current_core->radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) { - if (bcm->current_core->phy->rev == 1) { - //FIXME: implement rev1 workaround - } - } - } - bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning? - //TODO for APHY (temperature?) + if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2) + return; - if (likely(!bcm->shutting_down)) { - queue_delayed_work(bcm->workqueue, &bcm->periodic_work0, - BCM43xx_PERIODIC_0_DELAY); - } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_mac_suspend(bcm); + bcm43xx_phy_lo_g_measure(bcm); + bcm43xx_mac_enable(bcm); } -static void bcm43xx_periodic_work1_handler(void *d) +static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm) { - struct bcm43xx_private *bcm = d; - unsigned long flags; - - spin_lock_irqsave(&bcm->lock, flags); - bcm43xx_phy_lo_mark_all_unused(bcm); if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { bcm43xx_mac_suspend(bcm); bcm43xx_calc_nrssi_slope(bcm); bcm43xx_mac_enable(bcm); } - - if (likely(!bcm->shutting_down)) { - queue_delayed_work(bcm->workqueue, &bcm->periodic_work1, - BCM43xx_PERIODIC_1_DELAY); - } - spin_unlock_irqrestore(&bcm->lock, flags); } -static void bcm43xx_periodic_work2_handler(void *d) +static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm) { - struct bcm43xx_private *bcm = d; - unsigned long flags; - - spin_lock_irqsave(&bcm->lock, flags); - - assert(bcm->current_core->phy->type == BCM43xx_PHYTYPE_G); - assert(bcm->current_core->phy->rev >= 2); + /* Update device statistics. */ + bcm43xx_calculate_link_quality(bcm); +} - bcm43xx_mac_suspend(bcm); - bcm43xx_phy_lo_g_measure(bcm); - bcm43xx_mac_enable(bcm); +static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - if (likely(!bcm->shutting_down)) { - queue_delayed_work(bcm->workqueue, &bcm->periodic_work2, - BCM43xx_PERIODIC_2_DELAY); + if (phy->type == BCM43xx_PHYTYPE_G) { + //TODO: update_aci_moving_average + if (radio->aci_enable && radio->aci_wlan_automatic) { + bcm43xx_mac_suspend(bcm); + if (!radio->aci_enable && 1 /*TODO: not scanning? */) { + if (0 /*TODO: bunch of conditions*/) { + bcm43xx_radio_set_interference_mitigation(bcm, + BCM43xx_RADIO_INTERFMODE_MANUALWLAN); + } + } else if (1/*TODO*/) { + /* + if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) { + bcm43xx_radio_set_interference_mitigation(bcm, + BCM43xx_RADIO_INTERFMODE_NONE); + } + */ + } + bcm43xx_mac_enable(bcm); + } else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN && + phy->rev == 1) { + //TODO: implement rev1 workaround + } } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning? + //TODO for APHY (temperature?) } -static void bcm43xx_periodic_work3_handler(void *d) +static void bcm43xx_periodic_task_handler(unsigned long d) { - struct bcm43xx_private *bcm = d; + struct bcm43xx_private *bcm = (struct bcm43xx_private *)d; unsigned long flags; + unsigned int state; spin_lock_irqsave(&bcm->lock, flags); - /* Update device statistics. */ - bcm43xx_calculate_link_quality(bcm); + assert(bcm->initialized); + state = bcm->periodic_state; + if (state % 8 == 0) + bcm43xx_periodic_every120sec(bcm); + if (state % 4 == 0) + bcm43xx_periodic_every60sec(bcm); + if (state % 2 == 0) + bcm43xx_periodic_every30sec(bcm); + bcm43xx_periodic_every15sec(bcm); + bcm->periodic_state = state + 1; + + mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15)); - if (likely(!bcm->shutting_down)) { - queue_delayed_work(bcm->workqueue, &bcm->periodic_work3, - BCM43xx_PERIODIC_3_DELAY); - } spin_unlock_irqrestore(&bcm->lock, flags); } -/* Delete all periodic tasks and make - * sure they are not running any longer - */ static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) { - cancel_delayed_work(&bcm->periodic_work0); - cancel_delayed_work(&bcm->periodic_work1); - cancel_delayed_work(&bcm->periodic_work2); - cancel_delayed_work(&bcm->periodic_work3); - flush_workqueue(bcm->workqueue); + del_timer_sync(&bcm->periodic_tasks); } -/* Setup all periodic tasks. */ static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) { - INIT_WORK(&bcm->periodic_work0, bcm43xx_periodic_work0_handler, bcm); - INIT_WORK(&bcm->periodic_work1, bcm43xx_periodic_work1_handler, bcm); - INIT_WORK(&bcm->periodic_work2, bcm43xx_periodic_work2_handler, bcm); - INIT_WORK(&bcm->periodic_work3, bcm43xx_periodic_work3_handler, bcm); - - /* Periodic task 0: Delay ~15sec */ - queue_delayed_work(bcm->workqueue, &bcm->periodic_work0, - BCM43xx_PERIODIC_0_DELAY); - - /* Periodic task 1: Delay ~60sec */ - queue_delayed_work(bcm->workqueue, &bcm->periodic_work1, - BCM43xx_PERIODIC_1_DELAY); + struct timer_list *timer = &(bcm->periodic_tasks); - /* Periodic task 2: Delay ~120sec */ - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && - bcm->current_core->phy->rev >= 2) { - queue_delayed_work(bcm->workqueue, &bcm->periodic_work2, - BCM43xx_PERIODIC_2_DELAY); - } - - /* Periodic task 3: Delay ~30sec */ - queue_delayed_work(bcm->workqueue, &bcm->periodic_work3, - BCM43xx_PERIODIC_3_DELAY); + setup_timer(timer, + bcm43xx_periodic_task_handler, + (unsigned long)bcm); + timer->expires = jiffies; + add_timer(timer); } static void bcm43xx_security_init(struct bcm43xx_private *bcm) @@ -3414,13 +3374,13 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) int i, err; unsigned long flags; + bcm43xx_periodic_tasks_delete(bcm); + spin_lock_irqsave(&bcm->lock, flags); bcm->initialized = 0; bcm->shutting_down = 1; spin_unlock_irqrestore(&bcm->lock, flags); - bcm43xx_periodic_tasks_delete(bcm); - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE)) continue; @@ -4163,13 +4123,11 @@ static int bcm43xx_net_stop(struct net_device *net_dev) static int bcm43xx_init_private(struct bcm43xx_private *bcm, struct net_device *net_dev, - struct pci_dev *pci_dev, - struct workqueue_struct *wq) + struct pci_dev *pci_dev) { bcm->ieee = netdev_priv(net_dev); bcm->softmac = ieee80211_priv(net_dev); bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; - bcm->workqueue = wq; #ifdef DEBUG_ENABLE_MMIO_PRINT bcm43xx_mmioprint_initial(bcm, 1); @@ -4226,7 +4184,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, { struct net_device *net_dev; struct bcm43xx_private *bcm; - struct workqueue_struct *wq; int err; #ifdef CONFIG_BCM947XX @@ -4265,20 +4222,15 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, /* initialize the bcm43xx_private struct */ bcm = bcm43xx_priv(net_dev); memset(bcm, 0, sizeof(*bcm)); - wq = create_workqueue(KBUILD_MODNAME "_wq"); - if (!wq) { - err = -ENOMEM; - goto err_free_netdev; - } - err = bcm43xx_init_private(bcm, net_dev, pdev, wq); + err = bcm43xx_init_private(bcm, net_dev, pdev); if (err) - goto err_destroy_wq; + goto err_free_netdev; pci_set_drvdata(pdev, net_dev); err = bcm43xx_attach_board(bcm); if (err) - goto err_destroy_wq; + goto err_free_netdev; err = register_netdev(net_dev); if (err) { @@ -4296,8 +4248,6 @@ out: err_detach_board: bcm43xx_detach_board(bcm); -err_destroy_wq: - destroy_workqueue(wq); err_free_netdev: free_ieee80211softmac(net_dev); goto out; @@ -4312,7 +4262,6 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) unregister_netdev(net_dev); bcm43xx_detach_board(bcm); assert(bcm->ucode == NULL); - destroy_workqueue(bcm->workqueue); free_ieee80211softmac(net_dev); } @@ -4324,7 +4273,6 @@ static void bcm43xx_chip_reset(void *_bcm) struct bcm43xx_private *bcm = _bcm; struct net_device *net_dev = bcm->net_dev; struct pci_dev *pci_dev = bcm->pci_dev; - struct workqueue_struct *wq = bcm->workqueue; int err; int was_initialized = bcm->initialized; @@ -4336,7 +4284,7 @@ static void bcm43xx_chip_reset(void *_bcm) bcm43xx_free_board(bcm); bcm->firmware_norelease = 0; bcm43xx_detach_board(bcm); - err = bcm43xx_init_private(bcm, net_dev, pci_dev, wq); + err = bcm43xx_init_private(bcm, net_dev, pci_dev); if (err) goto failure; err = bcm43xx_attach_board(bcm); @@ -4364,7 +4312,7 @@ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); - queue_work(bcm->workqueue, &bcm->restart_work); + schedule_work(&bcm->restart_work); } #ifdef CONFIG_PM -- cgit v1.2.3-59-g8ed1b From 489423c8d0ba2b4311530502f7b5a331da9a60f9 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 13 Feb 2006 00:11:07 +0100 Subject: [PATCH] bcm43xx: Code cleanups. This removes various "inline" statements and reduces codesize. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 9 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 281 +++++++++++----------------- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 18 +- 3 files changed, 127 insertions(+), 181 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 99b2e72281ea..848717513b5f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -19,16 +19,17 @@ #define PFX KBUILD_MODNAME ": " -#define BCM43xx_SWITCH_CORE_MAX_RETRIES 10 +#define BCM43xx_SWITCH_CORE_MAX_RETRIES 50 #define BCM43xx_IRQWAIT_MAX_RETRIES 50 #define BCM43xx_IO_SIZE 8192 -#define BCM43xx_REG_ACTIVE_CORE 0x80 -/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */ -#define BCM43xx_PCICFG_ICR 0x94 +/* Active Core PCI Configuration Register. */ +#define BCM43xx_PCICFG_ACTIVE_CORE 0x80 /* SPROM control register. */ #define BCM43xx_PCICFG_SPROMCTL 0x88 +/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */ +#define BCM43xx_PCICFG_ICR 0x94 /* MMIO offsets */ #define BCM43xx_MMIO_DMA1_REASON 0x20 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 18152b0b2dd5..3443bd3c23e4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -119,40 +119,29 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging."); //#define DEBUG_ENABLE_PCILOG -static struct pci_device_id bcm43xx_pci_tbl[] = { - - /* Detailed list maintained at: - * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices - */ - -#ifdef CONFIG_BCM947XX - /* SB bus on BCM947xx */ - { PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -#endif - +/* Detailed list maintained at: + * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices + */ + static struct pci_device_id bcm43xx_pci_tbl[] = { /* Broadcom 4303 802.11b */ { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - - /* Broadcom 4307 802.11b */ + /* Broadcom 4307 802.11b */ { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - - /* Broadcom 4318 802.11b/g */ + /* Broadcom 4318 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4306 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - - /* Broadcom 4306 802.11a */ + /* Broadcom 4306 802.11a */ // { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4309 802.11a/b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 43XG 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - - /* required last entry */ - { 0, }, +#ifdef CONFIG_BCM947XX + /* SB bus on BCM947xx */ + { PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif + { 0 }, }; MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl); @@ -353,9 +342,8 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); } -static inline -u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp, - const int ofdm_modulation) +static u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp, + const int ofdm_modulation) { u8 rate; @@ -412,8 +400,7 @@ u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp, return rate; } -static inline -u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) +static u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) { switch (bitrate) { case IEEE80211_CCK_RATE_1MB: @@ -429,8 +416,7 @@ u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) return 0; } -static inline -u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) +static u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) { switch (bitrate) { case IEEE80211_OFDM_RATE_6MB: @@ -489,13 +475,12 @@ static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, //bcm43xx_printk_bitdump(raw, 4, 0, "PLCP"); } -void fastcall -bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie) +void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie) { const struct bcm43xx_phyinfo *phy = bcm->current_core->phy; const struct ieee80211_hdr_1addr *wireless_header = (const struct ieee80211_hdr_1addr *)fragment_data; @@ -606,9 +591,8 @@ void bcm43xx_macfilter_set(struct bcm43xx_private *bcm, bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); } -static inline -void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm, - u16 offset) +static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm, + u16 offset) { const u8 zero_addr[ETH_ALEN] = { 0 }; @@ -634,8 +618,7 @@ static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm) bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i))); } -static inline -void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) +static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) { /* slot_time is in usec. */ if (bcm->current_core->phy->type != BCM43xx_PHYTYPE_G) @@ -644,14 +627,12 @@ void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time); } -static inline -void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm) +static void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm) { bcm43xx_set_slot_time(bcm, 9); } -static inline -void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm) +static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm) { bcm43xx_set_slot_time(bcm, 20); } @@ -744,6 +725,8 @@ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *old static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) { + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; u32 radio_id; u16 manufact; u16 version; @@ -769,10 +752,10 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) version = (radio_id & 0x0FFFF000) >> 12; revision = (radio_id & 0xF0000000) >> 28; - dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n", + dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n", radio_id, manufact, version, revision); - switch (bcm->current_core->phy->type) { + switch (phy->type) { case BCM43xx_PHYTYPE_A: if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f)) goto err_unsupported_radio; @@ -787,25 +770,25 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) break; } - bcm->current_core->radio->manufact = manufact; - bcm->current_core->radio->version = version; - bcm->current_core->radio->revision = revision; + radio->manufact = manufact; + radio->version = version; + radio->revision = revision; /* Set default attenuation values. */ - bcm->current_core->radio->txpower[0] = 2; - bcm->current_core->radio->txpower[1] = 2; + radio->txpower[0] = 2; + radio->txpower[1] = 2; if (revision == 1) - bcm->current_core->radio->txpower[2] = 3; + radio->txpower[2] = 3; else - bcm->current_core->radio->txpower[2] = 0; + radio->txpower[2] = 0; if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) - bcm->current_core->radio->txpower_desired = bcm->sprom.maxpower_aphy; + radio->txpower_desired = bcm->sprom.maxpower_aphy; else bcm->current_core->radio->txpower_desired = bcm->sprom.maxpower_bgphy; /* Initialize the in-memory nrssi Lookup Table. */ for (i = 0; i < 64; i++) - bcm->current_core->radio->nrssi_lt[i] = i; + radio->nrssi_lt[i] = i; return 0; @@ -1155,6 +1138,7 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) */ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) { + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; unsigned int i, max_loop; u16 value = 0; u32 buffer[5] = { @@ -1165,7 +1149,7 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) 0x00000000, }; - switch (bcm->current_core->phy->type) { + switch (phy->type) { case BCM43xx_PHYTYPE_A: max_loop = 0x1E; buffer[0] = 0xCC010200; @@ -1187,7 +1171,7 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) bcm43xx_write16(bcm, 0x0568, 0x0000); bcm43xx_write16(bcm, 0x07C0, 0x0000); - bcm43xx_write16(bcm, 0x050C, ((bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0)); + bcm43xx_write16(bcm, 0x050C, ((phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0)); bcm43xx_write16(bcm, 0x0508, 0x0000); bcm43xx_write16(bcm, 0x050A, 0x0000); bcm43xx_write16(bcm, 0x054C, 0x0000); @@ -1324,25 +1308,6 @@ static void bcm43xx_clear_keys(struct bcm43xx_private *bcm) dprintk(KERN_INFO PFX "Keys cleared\n"); } -/* Puts the index of the current core into user supplied core variable. - * This function reads the value from the device. - * Almost always you don't want to call this, but use bcm->current_core - */ -static inline -int _get_current_core(struct bcm43xx_private *bcm, int *core) -{ - int err; - - err = bcm43xx_pci_read_config32(bcm, BCM43xx_REG_ACTIVE_CORE, core); - if (unlikely(err)) { - dprintk(KERN_ERR PFX "BCM43xx_REG_ACTIVE_CORE read failed!\n"); - return -ENODEV; - } - *core = (*core - 0x18000000) / 0x1000; - - return 0; -} - /* Lowlevel core-switch function. This is only to be used in * bcm43xx_switch_core() and bcm43xx_probe_cores() */ @@ -1350,63 +1315,57 @@ static int _switch_core(struct bcm43xx_private *bcm, int core) { int err; int attempts = 0; - int current_core = -1; + u32 current_core; assert(core >= 0); - - err = _get_current_core(bcm, ¤t_core); - if (unlikely(err)) - goto out; - - /* Write the computed value to the register. This doesn't always - succeed so we retry BCM43xx_SWITCH_CORE_MAX_RETRIES times */ - while (current_core != core) { - if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES)) { - err = -ENODEV; - printk(KERN_ERR PFX - "unable to switch to core %u, retried %i times\n", - core, attempts); - goto out; - } - err = bcm43xx_pci_write_config32(bcm, BCM43xx_REG_ACTIVE_CORE, + while (1) { + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE, (core * 0x1000) + 0x18000000); - if (unlikely(err)) { - dprintk(KERN_ERR PFX "BCM43xx_REG_ACTIVE_CORE write failed!\n"); - continue; - } - _get_current_core(bcm, ¤t_core); + if (unlikely(err)) + goto error; + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE, + ¤t_core); + if (unlikely(err)) + goto error; + current_core = (current_core - 0x18000000) / 0x1000; + if (current_core == core) + break; + + if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES)) + goto error; + udelay(10); + } #ifdef CONFIG_BCM947XX - if (bcm->pci_dev->bus->number == 0) - bcm->current_core_offset = 0x1000 * core; - else - bcm->current_core_offset = 0; + if (bcm->pci_dev->bus->number == 0) + bcm->current_core_offset = 0x1000 * core; + else + bcm->current_core_offset = 0; #endif - } - assert(err == 0); -out: - return err; + return 0; +error: + printk(KERN_ERR PFX "Failed to switch to core %d\n", core); + return -ENODEV; } int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core) { int err; - if (!new_core) + if (unlikely(!new_core)) return 0; - if (!(new_core->flags & BCM43xx_COREFLAG_AVAILABLE)) return -ENODEV; if (bcm->current_core == new_core) return 0; err = _switch_core(bcm, new_core->index); - if (!err) + if (likely(!err)) bcm->current_core = new_core; return err; } -static inline int bcm43xx_core_enabled(struct bcm43xx_private *bcm) +static int bcm43xx_core_enabled(struct bcm43xx_private *bcm) { u32 value; @@ -1609,7 +1568,7 @@ out: return err; } -static inline void handle_irq_transmit_status(struct bcm43xx_private *bcm) +static void handle_irq_transmit_status(struct bcm43xx_private *bcm) { u32 v0, v1; u16 tmp; @@ -1648,7 +1607,7 @@ static inline void handle_irq_transmit_status(struct bcm43xx_private *bcm) } } -static inline void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) +static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) { bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F); bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F); @@ -1672,7 +1631,7 @@ static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) bcm43xx_generate_noise_sample(bcm); } -static inline void handle_irq_noise(struct bcm43xx_private *bcm) +static void handle_irq_noise(struct bcm43xx_private *bcm) { struct bcm43xx_radioinfo *radio = bcm->current_core->radio; u16 tmp; @@ -1747,8 +1706,7 @@ generate_new: bcm43xx_generate_noise_sample(bcm); } -static inline -void handle_irq_ps(struct bcm43xx_private *bcm) +static void handle_irq_ps(struct bcm43xx_private *bcm) { if (bcm->ieee->iw_mode == IW_MODE_MASTER) { ///TODO: PS TBTT @@ -1761,8 +1719,7 @@ void handle_irq_ps(struct bcm43xx_private *bcm) //FIXME else set to false? } -static inline -void handle_irq_reg124(struct bcm43xx_private *bcm) +static void handle_irq_reg124(struct bcm43xx_private *bcm) { if (!bcm->reg124_set_0x4) return; @@ -1772,8 +1729,7 @@ void handle_irq_reg124(struct bcm43xx_private *bcm) //FIXME: reset reg124_set_0x4 to false? } -static inline -void handle_irq_pmq(struct bcm43xx_private *bcm) +static void handle_irq_pmq(struct bcm43xx_private *bcm) { u32 tmp; @@ -1829,8 +1785,7 @@ static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm, bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size); } -static inline -void handle_irq_beacon(struct bcm43xx_private *bcm) +static void handle_irq_beacon(struct bcm43xx_private *bcm) { u32 status; @@ -1992,9 +1947,8 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) #undef bcmirq_print_reasons -static inline -void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, - u32 reason, u32 mask) +static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, + u32 reason, u32 mask) { bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) & 0x0001dc00; @@ -2340,7 +2294,7 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) SA_SHIRQ, KBUILD_MODNAME, bcm); if (res) { printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); - return -EFAULT; + return -ENODEV; } bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff); bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402); @@ -2367,7 +2321,7 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) /* Switch to the core used to write the GPIO register. * This is either the ChipCommon, or the PCI core. */ -static inline int switch_to_gpio_core(struct bcm43xx_private *bcm) +static int switch_to_gpio_core(struct bcm43xx_private *bcm) { int err; @@ -2379,13 +2333,13 @@ static inline int switch_to_gpio_core(struct bcm43xx_private *bcm) err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); if (err == -ENODEV) { err = bcm43xx_switch_core(bcm, &bcm->core_pci); - if (err == -ENODEV) { + if (unlikely(err == -ENODEV)) { printk(KERN_ERR PFX "gpio error: " "Neither ChipCommon nor PCI core available!\n"); return -ENODEV; - } else if (err != 0) + } else if (unlikely(err != 0)) return -ENODEV; - } else if (err != 0) + } else if (unlikely(err != 0)) return -ENODEV; return 0; @@ -2691,40 +2645,30 @@ err_release_fw: * http://bcm-specs.sipsolutions.net/ValidateChipAccess */ static int bcm43xx_validate_chip(struct bcm43xx_private *bcm) { - int err = -ENODEV; u32 value; u32 shm_backup; shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000); bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA); - if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA) { - printk(KERN_ERR PFX "Error: SHM mismatch (1) validating chip\n"); - goto out; - } - + if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA) + goto error; bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55); - if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55) { - printk(KERN_ERR PFX "Error: SHM mismatch (2) validating chip\n"); - goto out; - } - + if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55) + goto error; bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup); value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - if ((value | 0x80000000) != 0x80000400) { - printk(KERN_ERR PFX "Error: Bad Status Bitfield while validating chip\n"); - goto out; - } + if ((value | 0x80000000) != 0x80000400) + goto error; value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (value != 0x00000000) { - printk(KERN_ERR PFX "Error: Bad interrupt reason code while validating chip\n"); - goto out; - } + if (value != 0x00000000) + goto error; - err = 0; -out: - return err; + return 0; +error: + printk(KERN_ERR PFX "Failed to validate the chipaccess\n"); + return -ENODEV; } static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) @@ -3172,9 +3116,9 @@ static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm) bcm43xx_pctl_set_crystal(bcm, 0); } -static inline void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm, - u32 address, - u32 data) +static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm, + u32 address, + u32 data) { bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address); bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data); @@ -3523,6 +3467,7 @@ static void bcm43xx_detach_board(struct bcm43xx_private *bcm) static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) { + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; u16 value; u8 phy_version; u8 phy_type; @@ -3578,15 +3523,15 @@ static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) phy_rev); } - bcm->current_core->phy->version = phy_version; - bcm->current_core->phy->type = phy_type; - bcm->current_core->phy->rev = phy_rev; + phy->version = phy_version; + phy->type = phy_type; + phy->rev = phy_rev; if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) { p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT, GFP_KERNEL); if (!p) return -ENOMEM; - bcm->current_core->phy->_lo_pairs = p; + phy->_lo_pairs = p; } return 0; @@ -3757,9 +3702,9 @@ err_pci_disable: goto out; } -static inline -s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, u8 in_rssi, - int ofdm, int adjust_2053, int adjust_2050) +static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, + u8 in_rssi, int ofdm, + int adjust_2053, int adjust_2050) { s32 tmp; @@ -3816,8 +3761,8 @@ s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, u8 in_rssi, return (s8)tmp; } -static inline -s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, u8 in_rssi) +static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, + u8 in_rssi) { s8 ret; @@ -3843,9 +3788,9 @@ int bcm43xx_rx_packet(struct bcm43xx_private *bcm, return 0; } -int fastcall bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr) +int bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr) { struct bcm43xx_plcp_hdr4 *plcp; struct ieee80211_rx_stats stats; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 1d3eddd314bc..298e24b4ab64 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -111,12 +111,12 @@ struct bcm43xx_txhdr { struct sk_buff; -void FASTCALL(bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - const unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie)); +void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + const unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie); /* RX header as received from the hardware. */ struct bcm43xx_rxhdr { @@ -244,9 +244,9 @@ int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf); -int FASTCALL(bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr)); +int bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr); void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, int iw_mode); -- cgit v1.2.3-59-g8ed1b From ea0922b067a0863f9a4198740651fd47a22af7f1 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Feb 2006 14:09:20 +0100 Subject: [PATCH] bcm43xx: Move sprom lowlevel reading/writing to its own functions. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 93 ++++++++++++++++++++++++----- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 3 + drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 66 ++------------------ 3 files changed, 86 insertions(+), 76 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 3443bd3c23e4..bcbd009a5339 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -916,13 +916,84 @@ u8 bcm43xx_sprom_crc(const u16 *sprom) return crc; } - -static int bcm43xx_read_sprom(struct bcm43xx_private *bcm) +int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom) { int i; + u8 crc, expected_crc; + + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) + sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); + /* CRC-8 check. */ + crc = bcm43xx_sprom_crc(sprom); + expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; + if (crc != expected_crc) { + printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum " + "(0x%02X, expected: 0x%02X)\n", + crc, expected_crc); + return -EINVAL; + } + + return 0; +} + +int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom) +{ + int i, err; + u8 crc, expected_crc; + u32 spromctl; + + /* CRC-8 validation of the input data. */ + crc = bcm43xx_sprom_crc(sprom); + expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; + if (crc != expected_crc) { + printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n"); + return -EINVAL; + } + + printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl); + if (err) + goto err_ctlreg; + spromctl |= 0x10; /* SPROM WRITE enable. */ + bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); + if (err) + goto err_ctlreg; + /* We must burn lots of CPU cycles here, but that does not + * really matter as one does not write the SPROM every other minute... + */ + printk(KERN_INFO PFX "[ 0%%"); + mdelay(500); + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { + if (i == 16) + printk("25%%"); + else if (i == 32) + printk("50%%"); + else if (i == 48) + printk("75%%"); + else if (i % 2) + printk("."); + bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); + mdelay(20); + } + spromctl &= ~0x10; /* SPROM WRITE enable. */ + bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); + if (err) + goto err_ctlreg; + mdelay(500); + printk("100%% ]\n"); + printk(KERN_INFO PFX "SPROM written.\n"); + bcm43xx_controller_restart(bcm, "SPROM update"); + + return 0; +err_ctlreg: + printk(KERN_ERR PFX "Could not access SPROM control register.\n"); + return -ENODEV; +} + +static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) +{ u16 value; u16 *sprom; - u8 crc, expected_crc; #ifdef CONFIG_BCM947XX char *c; #endif @@ -930,7 +1001,7 @@ static int bcm43xx_read_sprom(struct bcm43xx_private *bcm) sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16), GFP_KERNEL); if (!sprom) { - printk(KERN_ERR PFX "read_sprom OOM\n"); + printk(KERN_ERR PFX "sprom_extract OOM\n"); return -ENOMEM; } #ifdef CONFIG_BCM947XX @@ -953,17 +1024,7 @@ static int bcm43xx_read_sprom(struct bcm43xx_private *bcm) sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev")); #else - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) - sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); - - /* CRC-8 check. */ - crc = bcm43xx_sprom_crc(sprom); - expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; - if (crc != expected_crc) { - printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum " - "(0x%02X, expected: 0x%02X)\n", - crc, expected_crc); - } + bcm43xx_sprom_read(bcm, sprom); #endif /* boardflags2 */ @@ -3632,7 +3693,7 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) goto err_chipset_detach; } - err = bcm43xx_read_sprom(bcm); + err = bcm43xx_sprom_extract(bcm); if (err) goto err_chipset_detach; err = bcm43xx_leds_init(bcm); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 298e24b4ab64..0c4bd08568c5 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -280,4 +280,7 @@ u8 bcm43xx_sprom_crc(const u16 *sprom); void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); +int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom); +int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom); + #endif /* BCM43xx_MAIN_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 4c972cdc0a24..df37d28996c9 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -782,7 +782,6 @@ static int hex2sprom(u16 *sprom, const char *dump, unsigned int len) char tmp[5] = { 0 }; int cnt = 0; unsigned long parsed; - u8 crc, expected_crc; if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2) return -EINVAL; @@ -793,13 +792,6 @@ static int hex2sprom(u16 *sprom, const char *dump, unsigned int len) sprom[cnt++] = swab16((u16)parsed); } - crc = bcm43xx_sprom_crc(sprom); - expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; - if (crc != expected_crc) { - printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n"); - return -EINVAL; - } - return 0; } @@ -809,7 +801,7 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err = -EPERM, i; + int err = -EPERM; u16 *sprom; unsigned long flags; @@ -828,13 +820,10 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev, spin_unlock_irqrestore(&bcm->lock, flags); goto out_kfree; } - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) - sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); + err = bcm43xx_sprom_read(bcm, sprom); spin_unlock_irqrestore(&bcm->lock, flags); - - data->data.length = sprom2hex(sprom, extra); - - err = 0; + if (!err) + data->data.length = sprom2hex(sprom, extra); out_kfree: kfree(sprom); out: @@ -852,8 +841,6 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, unsigned long flags; char *input; unsigned int len; - u32 spromctl; - int i; if (!capable(CAP_SYS_RAWIO)) goto out; @@ -878,50 +865,9 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, spin_lock_irqsave(&bcm->lock, flags); err = -ENODEV; - if (!bcm->initialized) { - spin_unlock_irqrestore(&bcm->lock, flags); - goto out_kfree; - } - - printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl); - if (err) { - printk(KERN_ERR PFX "Could not access SPROM control register.\n"); - goto out_unlock; - } - spromctl |= 0x10; /* SPROM WRITE enable. */ - bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); - if (err) { - printk(KERN_ERR PFX "Could not access SPROM control register.\n"); - goto out_unlock; - } - /* We must burn lots of CPU cycles here, but that does not - * really matter as one does not write the SPROM every other minute... - */ - printk(KERN_INFO PFX "[ 0%%"); - mdelay(500); - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { - if (i == 16) - printk("25%%"); - else if (i == 32) - printk("50%%"); - else if (i == 48) - printk("75%%"); - else if (i % 2) - printk("."); - bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); - mdelay(20); - } - spromctl &= ~0x10; /* SPROM WRITE enable. */ - bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); - if (err) { - printk(KERN_ERR PFX "Could not access SPROM control register.\n"); + if (!bcm->initialized) goto out_unlock; - } - mdelay(500); - printk("100%% ]\n"); - printk(KERN_INFO PFX "SPROM written.\n"); - err = 0; + err = bcm43xx_sprom_write(bcm, sprom); out_unlock: spin_unlock_irqrestore(&bcm->lock, flags); out_kfree: -- cgit v1.2.3-59-g8ed1b From ad3f086c49aa682e493c935cda76f3850ee4a80e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Feb 2006 14:12:22 +0100 Subject: [PATCH] bcm43xx: make bcm43xx_sprom_crc() static. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index bcbd009a5339..b4767e42e8f4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -901,7 +901,7 @@ static inline u8 bcm43xx_crc8(u8 crc, u8 data) return t[crc ^ data]; } -u8 bcm43xx_sprom_crc(const u16 *sprom) +static u8 bcm43xx_sprom_crc(const u16 *sprom) { int word; u8 crc = 0xFF; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 0c4bd08568c5..0a22e833915d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -276,8 +276,6 @@ int bcm43xx_pci_write_config_32(struct pci_dev *pdev, int offset, u32 val); void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); void bcm43xx_mac_enable(struct bcm43xx_private *bcm); -u8 bcm43xx_sprom_crc(const u16 *sprom); - void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom); -- cgit v1.2.3-59-g8ed1b From 10d8dd88dcc2c8ebe8ac7dcf75a2da7c9f9ee0f3 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Feb 2006 22:08:48 +0100 Subject: [PATCH] bcm43xx: split the channel helper functions, so that they can be used without a valid running core. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 80 ++++++++++++++++++----------- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 12 +++-- 3 files changed, 59 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index b4767e42e8f4..6195c2a1516d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1169,7 +1169,7 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) if (have_a) { for (i = 0, channel = 0; channel < 201; channel++) { chan = &geo.a[i++]; - chan->freq = bcm43xx_channel_to_freq(bcm, channel); + chan->freq = bcm43xx_channel_to_freq_a(channel); chan->channel = channel; } geo.a_channels = i; @@ -1177,7 +1177,7 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) if (have_bg) { for (i = 0, channel = 1; channel < 15; channel++) { chan = &geo.bg[i++]; - chan->freq = bcm43xx_channel_to_freq(bcm, channel); + chan->freq = bcm43xx_channel_to_freq_bg(channel); chan->channel = channel; } geo.bg_channels = i; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 0a22e833915d..7d696d257f7a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -187,58 +187,78 @@ struct bcm43xx_xmitstatus_queue { /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ static inline -u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm, - int freq) +u8 bcm43xx_freq_to_channel_a(int freq) +{ + return ((freq - 5000) / 5); +} +static inline +u8 bcm43xx_freq_to_channel_bg(int freq) { u8 channel; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { - channel = (freq - 5000) / 5; - } else { - if (freq == 2484) - channel = 14; - else - channel = (freq - 2407) / 5; - } + if (freq == 2484) + channel = 14; + else + channel = (freq - 2407) / 5; return channel; } +static inline +u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm, + int freq) +{ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + return bcm43xx_freq_to_channel_a(freq); + return bcm43xx_freq_to_channel_bg(freq); +} /* Lightweight function to convert a channel number to a frequency (in Mhz). */ static inline -int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm, - u8 channel) +int bcm43xx_channel_to_freq_a(u8 channel) +{ + return (5000 + (5 * channel)); +} +static inline +int bcm43xx_channel_to_freq_bg(u8 channel) { int freq; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { - freq = 5000 + (5 * channel); - } else { - if (channel == 14) - freq = 2484; - else - freq = 2407 + (5 * channel); - } + if (channel == 14) + freq = 2484; + else + freq = 2407 + (5 * channel); return freq; } +static inline +int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm, + u8 channel) +{ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + return bcm43xx_channel_to_freq_a(channel); + return bcm43xx_channel_to_freq_bg(channel); +} /* Lightweight function to check if a channel number is valid. * Note that this does _NOT_ check for geographical restrictions! */ static inline +int bcm43xx_is_valid_channel_a(u8 channel) +{ + return (channel <= 200); +} +static inline +int bcm43xx_is_valid_channel_bg(u8 channel) +{ + return (channel >= 1 && channel <= 14); +} +static inline int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, - u8 channel) + u8 channel) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { - if (channel <= 200) - return 1; - } else { - if (channel >= 1 && channel <= 14) - return 1; - } - - return 0; + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + return bcm43xx_is_valid_channel_a(channel); + return bcm43xx_is_valid_channel_bg(channel); } void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index df37d28996c9..aa2d9930c436 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -111,8 +111,9 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, unsigned long flags; u8 channel; int freq; - int err = 0; + int err = -EINVAL; + spin_lock_irqsave(&bcm->lock, flags); if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { channel = data->freq.m; freq = bcm43xx_channel_to_freq(bcm, channel); @@ -121,16 +122,17 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, freq = data->freq.m; } if (!bcm43xx_is_valid_channel(bcm, channel)) - return -EINVAL; - - spin_lock_irqsave(&bcm->lock, flags); + goto out_unlock; if (bcm->initialized) { //ieee80211softmac_disassoc(softmac, $REASON); bcm43xx_mac_suspend(bcm); err = bcm43xx_radio_selectchannel(bcm, channel, 0); bcm43xx_mac_enable(bcm); - } else + } else { bcm->current_core->radio->initial_channel = channel; + err = 0; + } +out_unlock: spin_unlock_irqrestore(&bcm->lock, flags); return err; -- cgit v1.2.3-59-g8ed1b From 26533e7e292075df1daf94965a7f3f0d91bd08a8 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Feb 2006 22:25:09 +0100 Subject: [PATCH] bcm43xx: remove old unused struct. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 7d696d257f7a..d460393ed343 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -179,11 +179,6 @@ struct bcm43xx_xmitstatus { //TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40 //TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80 -struct bcm43xx_xmitstatus_queue { - struct list_head list; - struct bcm43xx_hwxmitstatus status; -}; - /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ static inline -- cgit v1.2.3-59-g8ed1b From c4c3beb7d70ae9d1fe97b7b49bc5a10ad26c2b01 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 20 Feb 2006 22:48:55 +0100 Subject: [PATCH] bcm43xx: Fix Kconfig typo (transfer mode default) Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig index 1d677c15b21c..418465600a77 100644 --- a/drivers/net/wireless/bcm43xx/Kconfig +++ b/drivers/net/wireless/bcm43xx/Kconfig @@ -23,7 +23,7 @@ config BCM43XX_PIO choice prompt "BCM43xx data transfer mode" depends on BCM43XX - default BCM43XX_DMA_AND_PIO + default BCM43XX_DMA_AND_PIO_MODE config BCM43XX_DMA_AND_PIO_MODE bool "DMA + PIO" -- cgit v1.2.3-59-g8ed1b From bf7b876043e6e1390b1234d740f4fd9af20b3b9e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 21 Feb 2006 17:58:18 +0100 Subject: [PATCH] bcm43xx: Workaround init_board vs IRQ race. The proper fix for this is to move IRQ enabling to the end of init_board. But this is nontrivial and needs to be done with care. Stay with this cheap workaround for now. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 6195c2a1516d..57306a658407 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2079,12 +2079,19 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re bcm43xx_interrupt_ack(bcm, reason, mask); - /* 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. */ - bcm->irq_reason = reason; - tasklet_schedule(&bcm->isr_tasklet); + /* Only accept IRQs, if we are initialized properly. + * This avoids an RX race while initializing. + * We should probably not enable IRQs before we are initialized + * 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)) { + /* 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. */ + bcm->irq_reason = reason; + tasklet_schedule(&bcm->isr_tasklet); + } spin_unlock(&bcm->lock); -- cgit v1.2.3-59-g8ed1b From cad2b31a76763d06048fb23a17b062acd5d46639 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 21 Feb 2006 18:08:55 +0100 Subject: [PATCH] bcm43xx: move initialized = 1 to the end of init_board. Note that the periodic work has to be started with initialized==1 Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 57306a658407..4a7d88d28211 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3484,15 +3484,17 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); - spin_lock_irqsave(&bcm->lock, flags); - bcm->initialized = 1; - spin_unlock_irqrestore(&bcm->lock, flags); - if (bcm->current_core->radio->initial_channel != 0xFF) { bcm43xx_mac_suspend(bcm); bcm43xx_radio_selectchannel(bcm, bcm->current_core->radio->initial_channel, 0); bcm43xx_mac_enable(bcm); } + + /* Initialization of the board is done. Flag it as such. */ + spin_lock_irqsave(&bcm->lock, flags); + bcm->initialized = 1; + spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_periodic_tasks_setup(bcm); assert(err == 0); -- cgit v1.2.3-59-g8ed1b From 1d1a73ccdc618168f2a5c962aab250605c93e517 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 21 Feb 2006 18:19:59 +0100 Subject: [PATCH] bcm43xx: add assert(bcm->initialized) to periodic_tasks_setup(). Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 4a7d88d28211..899c06fe0bf5 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3366,6 +3366,7 @@ static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) { struct timer_list *timer = &(bcm->periodic_tasks); + assert(bcm->initialized); setup_timer(timer, bcm43xx_periodic_task_handler, (unsigned long)bcm); -- cgit v1.2.3-59-g8ed1b From f398f02d12cdc372e16c5e86246b10acf7211abc Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 23 Feb 2006 21:15:39 +0100 Subject: [PATCH] bcm43xx: Move TX/RX related functions to its own file. Add basic RTS/CTS code. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Makefile | 1 + drivers/net/wireless/bcm43xx/bcm43xx.h | 23 +- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 1 + drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 1 + drivers/net/wireless/bcm43xx/bcm43xx_main.c | 430 +----------------- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 131 ------ drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 1 + drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 579 +++++++++++++++++++++++++ drivers/net/wireless/bcm43xx/bcm43xx_xmit.h | 156 +++++++ 9 files changed, 746 insertions(+), 577 deletions(-) create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_xmit.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_xmit.h (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile index c87c1525b39f..2962b5f9e3e7 100644 --- a/drivers/net/wireless/bcm43xx/Makefile +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -8,4 +8,5 @@ bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \ bcm43xx_radio.o bcm43xx_phy.o \ bcm43xx_power.o bcm43xx_wx.o \ bcm43xx_leds.o bcm43xx_ethtool.o \ + bcm43xx_xmit.o \ $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 848717513b5f..21c75cae14bf 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -314,23 +314,6 @@ /* Initial default iw_mode */ #define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA -/* Values/Masks for the device TX header */ -#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001 -#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008 -#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020 -#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100 -#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800 - -#define BCM43xx_TXHDRCTL_OFDM 0x0001 -#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010 -#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030 -#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8 - -#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0 -#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4 -#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003 -#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0 - /* Bus type PCI. */ #define BCM43xx_BUSTYPE_PCI 0 /* Bus type Silicone Backplane Bus. */ @@ -952,4 +935,10 @@ int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 valu __value; \ }) +/** Helpers to print MAC addresses. */ +#define BCM43xx_MACFMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define BCM43xx_MACARG(x) ((u8*)(x))[0], ((u8*)(x))[1], \ + ((u8*)(x))[2], ((u8*)(x))[3], \ + ((u8*)(x))[4], ((u8*)(x))[5] + #endif /* BCM43xx_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index 5a7dc43cd676..0bae0be4be2e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -37,6 +37,7 @@ #include "bcm43xx_debugfs.h" #include "bcm43xx_dma.h" #include "bcm43xx_pio.h" +#include "bcm43xx_xmit.h" #define REALLY_BIG_BUFFER_SIZE (1024*256) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index af5c27f9bfda..e20fbaf29e0b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -32,6 +32,7 @@ #include "bcm43xx_main.h" #include "bcm43xx_debugfs.h" #include "bcm43xx_power.h" +#include "bcm43xx_xmit.h" #include #include diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 899c06fe0bf5..f1ac9940f14c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -50,6 +50,7 @@ #include "bcm43xx_power.h" #include "bcm43xx_wx.h" #include "bcm43xx_ethtool.h" +#include "bcm43xx_xmit.h" MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); @@ -342,234 +343,6 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); } -static u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp, - const int ofdm_modulation) -{ - u8 rate; - - if (ofdm_modulation) { - switch (plcp->raw[0] & 0xF) { - case 0xB: - rate = IEEE80211_OFDM_RATE_6MB; - break; - case 0xF: - rate = IEEE80211_OFDM_RATE_9MB; - break; - case 0xA: - rate = IEEE80211_OFDM_RATE_12MB; - break; - case 0xE: - rate = IEEE80211_OFDM_RATE_18MB; - break; - case 0x9: - rate = IEEE80211_OFDM_RATE_24MB; - break; - case 0xD: - rate = IEEE80211_OFDM_RATE_36MB; - break; - case 0x8: - rate = IEEE80211_OFDM_RATE_48MB; - break; - case 0xC: - rate = IEEE80211_OFDM_RATE_54MB; - break; - default: - rate = 0; - assert(0); - } - } else { - switch (plcp->raw[0]) { - case 0x0A: - rate = IEEE80211_CCK_RATE_1MB; - break; - case 0x14: - rate = IEEE80211_CCK_RATE_2MB; - break; - case 0x37: - rate = IEEE80211_CCK_RATE_5MB; - break; - case 0x6E: - rate = IEEE80211_CCK_RATE_11MB; - break; - default: - rate = 0; - assert(0); - } - } - - return rate; -} - -static u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) -{ - switch (bitrate) { - case IEEE80211_CCK_RATE_1MB: - return 0x0A; - case IEEE80211_CCK_RATE_2MB: - return 0x14; - case IEEE80211_CCK_RATE_5MB: - return 0x37; - case IEEE80211_CCK_RATE_11MB: - return 0x6E; - } - assert(0); - return 0; -} - -static u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) -{ - switch (bitrate) { - case IEEE80211_OFDM_RATE_6MB: - return 0xB; - case IEEE80211_OFDM_RATE_9MB: - return 0xF; - case IEEE80211_OFDM_RATE_12MB: - return 0xA; - case IEEE80211_OFDM_RATE_18MB: - return 0xE; - case IEEE80211_OFDM_RATE_24MB: - return 0x9; - case IEEE80211_OFDM_RATE_36MB: - return 0xD; - case IEEE80211_OFDM_RATE_48MB: - return 0x8; - case IEEE80211_OFDM_RATE_54MB: - return 0xC; - } - assert(0); - return 0; -} - -static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, - u16 octets, const u8 bitrate, - const int ofdm_modulation) -{ - __le32 *data = &(plcp->data); - __u8 *raw = plcp->raw; - - /* Account for hardware-appended FCS. */ - octets += IEEE80211_FCS_LEN; - - if (ofdm_modulation) { - *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate); - assert(!(octets & 0xF000)); - *data |= (octets << 5); - *data = cpu_to_le32(*data); - } else { - u32 plen; - - plen = octets * 16 / bitrate; - if ((octets * 16 % bitrate) > 0) { - plen++; - if ((bitrate == IEEE80211_CCK_RATE_11MB) - && ((octets * 8 % 11) < 4)) { - raw[1] = 0x84; - } else - raw[1] = 0x04; - } else - raw[1] = 0x04; - *data |= cpu_to_le32(plen << 16); - raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate); - } - -//bcm43xx_printk_bitdump(raw, 4, 0, "PLCP"); -} - -void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie) -{ - const struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - const struct ieee80211_hdr_1addr *wireless_header = (const struct ieee80211_hdr_1addr *)fragment_data; - const struct ieee80211_security *secinfo = &bcm->ieee->sec; - u8 bitrate; - int ofdm_modulation; - u8 fallback_bitrate; - int fallback_ofdm_modulation; - u16 tmp; - u16 encrypt_frame; - - /* Now construct the TX header. */ - memset(txhdr, 0, sizeof(*txhdr)); - - //TODO: Some RTS/CTS stuff has to be done. - //TODO: Encryption stuff. - //TODO: others? - - bitrate = bcm->softmac->txrates.default_rate; - ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); - fallback_bitrate = bcm->softmac->txrates.default_fallback; - fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); - - /* Set Frame Control from 80211 header. */ - txhdr->frame_control = wireless_header->frame_ctl; - /* Copy address1 from 80211 header. */ - memcpy(txhdr->mac1, wireless_header->addr1, 6); - /* Set the fallback duration ID. */ - //FIXME: We use the original durid for now. - txhdr->fallback_dur_id = wireless_header->duration_id; - - /* Set the cookie (used as driver internal ID for the frame) */ - txhdr->cookie = cpu_to_le16(cookie); - - encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED; - if (encrypt_frame && !bcm->ieee->host_encrypt) { - const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header; - if (fragment_len <= sizeof(struct ieee80211_hdr_3addr)+4) { - dprintkl(KERN_ERR PFX "invalid packet with PROTECTED" - "flag set discarded"); - return; - } - memcpy(txhdr->wep_iv, hdr->payload, 4); - /* Hardware appends ICV. */ - fragment_len += 4; - } - - /* Generate the PLCP header and the fallback PLCP header. */ - bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp), - fragment_len, - bitrate, ofdm_modulation); - bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, fragment_len, - fallback_bitrate, fallback_ofdm_modulation); - - /* Set the CONTROL field */ - tmp = 0; - if (ofdm_modulation) - tmp |= BCM43xx_TXHDRCTL_OFDM; - if (bcm->short_preamble) //FIXME: could be the other way around, please test - tmp |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE; - tmp |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT) - & BCM43xx_TXHDRCTL_ANTENNADIV_MASK; - txhdr->control = cpu_to_le16(tmp); - - /* Set the FLAGS field */ - tmp = 0; - if (!is_multicast_ether_addr(wireless_header->addr1) && - !is_broadcast_ether_addr(wireless_header->addr1)) - tmp |= BCM43xx_TXHDRFLAG_EXPECTACK; - if (1 /* FIXME: PS poll?? */) - tmp |= 0x10; // FIXME: unknown meaning. - if (fallback_ofdm_modulation) - tmp |= BCM43xx_TXHDRFLAG_FALLBACKOFDM; - if (is_first_fragment) - tmp |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT; - txhdr->flags = cpu_to_le16(tmp); - - /* Set WSEC/RATE field */ - if (encrypt_frame && !bcm->ieee->host_encrypt) { - tmp = (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT) - & BCM43xx_TXHDR_WSEC_ALGO_MASK; - tmp |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT) - & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK; - txhdr->wsec_rate = cpu_to_le16(tmp); - } - -//bcm43xx_printk_bitdump((const unsigned char *)txhdr, sizeof(*txhdr), 1, "TX header"); -} - static void bcm43xx_macfilter_set(struct bcm43xx_private *bcm, u16 offset, @@ -3773,207 +3546,6 @@ err_pci_disable: goto out; } -static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, - u8 in_rssi, int ofdm, - int adjust_2053, int adjust_2050) -{ - s32 tmp; - - switch (bcm->current_core->radio->version) { - case 0x2050: - if (ofdm) { - tmp = in_rssi; - if (tmp > 127) - tmp -= 256; - tmp *= 73; - tmp /= 64; - if (adjust_2050) - tmp += 25; - else - tmp -= 3; - } else { - if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { - if (in_rssi > 63) - in_rssi = 63; - tmp = bcm->current_core->radio->nrssi_lt[in_rssi]; - tmp = 31 - tmp; - tmp *= -131; - tmp /= 128; - tmp -= 57; - } else { - tmp = in_rssi; - tmp = 31 - tmp; - tmp *= -149; - tmp /= 128; - tmp -= 68; - } - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && - adjust_2050) - tmp += 25; - } - break; - case 0x2060: - if (in_rssi > 127) - tmp = in_rssi - 256; - else - tmp = in_rssi; - break; - default: - tmp = in_rssi; - tmp -= 11; - tmp *= 103; - tmp /= 64; - if (adjust_2053) - tmp -= 109; - else - tmp -= 83; - } - - return (s8)tmp; -} - -static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, - u8 in_rssi) -{ - s8 ret; - - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { - //TODO: Incomplete specs. - ret = 0; - } else - ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1); - - return ret; -} - -static inline -int bcm43xx_rx_packet(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct ieee80211_rx_stats *stats) -{ - int err; - - err = ieee80211_rx(bcm->ieee, skb, stats); - if (unlikely(err == 0)) - return -EINVAL; - return 0; -} - -int bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr) -{ - struct bcm43xx_plcp_hdr4 *plcp; - struct ieee80211_rx_stats stats; - struct ieee80211_hdr_4addr *wlhdr; - u16 frame_ctl; - int is_packet_for_us = 0; - int err = -EINVAL; - const u16 rxflags1 = le16_to_cpu(rxhdr->flags1); - const u16 rxflags2 = le16_to_cpu(rxhdr->flags2); - const u16 rxflags3 = le16_to_cpu(rxhdr->flags3); - const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM); - - if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) { - plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2); - /* Skip two unknown bytes and the PLCP header. */ - skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6)); - } else { - plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data); - /* Skip the PLCP header. */ - skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6)); - } - /* The SKB contains the PAYLOAD (wireless header + data) - * at this point. The FCS at the end is stripped. - */ - - memset(&stats, 0, sizeof(stats)); - stats.mac_time = le16_to_cpu(rxhdr->mactime); - stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, - !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), - !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); - stats.signal = rxhdr->signal_quality; //FIXME -//TODO stats.noise = - stats.rate = bcm43xx_plcp_get_bitrate(plcp, is_ofdm); -//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate); - stats.received_channel = bcm->current_core->radio->channel; -//TODO stats.control = - stats.mask = IEEE80211_STATMASK_SIGNAL | -//TODO IEEE80211_STATMASK_NOISE | - IEEE80211_STATMASK_RATE | - IEEE80211_STATMASK_RSSI; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) - stats.freq = IEEE80211_52GHZ_BAND; - else - stats.freq = IEEE80211_24GHZ_BAND; - stats.len = skb->len; - - bcm->stats.last_rx = jiffies; - if (bcm->ieee->iw_mode == IW_MODE_MONITOR) - return bcm43xx_rx_packet(bcm, skb, &stats); - - wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); - - switch (bcm->ieee->iw_mode) { - case IW_MODE_ADHOC: - if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || - memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || - is_broadcast_ether_addr(wlhdr->addr1) || - is_multicast_ether_addr(wlhdr->addr1) || - bcm->net_dev->flags & IFF_PROMISC) - is_packet_for_us = 1; - break; - case IW_MODE_INFRA: - default: - /* When receiving multicast or broadcast packets, filter out - the packets we send ourself; we shouldn't see those */ - if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || - memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || - (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) && - (is_broadcast_ether_addr(wlhdr->addr1) || - is_multicast_ether_addr(wlhdr->addr1) || - bcm->net_dev->flags & IFF_PROMISC))) - is_packet_for_us = 1; - break; - } - - frame_ctl = le16_to_cpu(wlhdr->frame_ctl); - if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { - frame_ctl &= ~IEEE80211_FCTL_PROTECTED; - wlhdr->frame_ctl = cpu_to_le16(frame_ctl); - /* trim IV and ICV */ - /* FIXME: this must be done only for WEP encrypted packets */ - if (skb->len < 32) { - dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag " - "set and length < 32)\n"); - return -EINVAL; - } else { - memmove(skb->data + 4, skb->data, 24); - skb_pull(skb, 4); - skb_trim(skb, skb->len - 4); - stats.len -= 8; - } - wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); - } - - switch (WLAN_FC_GET_TYPE(frame_ctl)) { - case IEEE80211_FTYPE_MGMT: - ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); - break; - case IEEE80211_FTYPE_DATA: - if (is_packet_for_us) - err = bcm43xx_rx_packet(bcm, skb, &stats); - break; - case IEEE80211_FTYPE_CTL: - break; - default: - assert(0); - return -EINVAL; - } - - return err; -} - /* Do the Hardware IO operations to send the txb */ static inline int bcm43xx_tx(struct bcm43xx_private *bcm, struct ieee80211_txb *txb) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index d460393ed343..086136c3d01f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -52,134 +52,12 @@ static inline void e_aton(char *str, char *dest) } #endif - -#define _bcm43xx_declare_plcp_hdr(size) \ - struct bcm43xx_plcp_hdr##size { \ - union { \ - __le32 data; \ - __u8 raw[size]; \ - } __attribute__((__packed__)); \ - } __attribute__((__packed__)) - -/* struct bcm43xx_plcp_hdr4 */ -_bcm43xx_declare_plcp_hdr(4); -/* struct bcm430c_plcp_hdr6 */ -_bcm43xx_declare_plcp_hdr(6); - -#undef _bcm43xx_declare_plcp_hdr - - #define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] #define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) /* Magic helper macro to pad structures. Ignore those above. It's magic. */ #define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) -/* Device specific TX header. To be prepended to TX frames. */ -struct bcm43xx_txhdr { - union { - struct { - u16 flags; - u16 wsec_rate; - u16 frame_control; - u16 unknown_zeroed_0; - u16 control; - unsigned char wep_iv[10]; - unsigned char unknown_wsec_tkip_data[3]; //FIXME - PAD_BYTES(3); - unsigned char mac1[6]; - u16 unknown_zeroed_1; - struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp; - u16 rts_cts_dur_fallback; - struct bcm43xx_plcp_hdr4 fallback_plcp; - u16 fallback_dur_id; - PAD_BYTES(2); - u16 cookie; - u16 unknown_scb_stuff; //FIXME - struct bcm43xx_plcp_hdr6 rts_cts_plcp; - u16 rts_cts_frame_type; - u16 rts_cts_dur; - unsigned char rts_cts_mac1[6]; - unsigned char rts_cts_mac2[6]; - PAD_BYTES(2); - struct bcm43xx_plcp_hdr6 plcp; - } __attribute__((__packed__)); - - unsigned char raw[82]; - } __attribute__((__packed__)); -} __attribute__((__packed__)); - -struct sk_buff; - -void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - const unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie); - -/* RX header as received from the hardware. */ -struct bcm43xx_rxhdr { - /* Frame Length. Must be generated explicitely in PIO mode. */ - __le16 frame_length; - PAD_BYTES(2); - /* Flags field 1 */ - __le16 flags1; - u8 rssi; - u8 signal_quality; - PAD_BYTES(2); - /* Flags field 3 */ - __le16 flags3; - /* Flags field 2 */ - __le16 flags2; - /* Lower 16bits of the TSF at the time the frame started. */ - __le16 mactime; - PAD_BYTES(14); -} __attribute__((__packed__)); - -#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0) -/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */ -#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7) -#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14) - -#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0) -#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2) -/*FIXME: WEP related flags */ - -#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10) - -/* Transmit Status as received from the hardware. */ -struct bcm43xx_hwxmitstatus { - PAD_BYTES(4); - __le16 cookie; - u8 flags; - u8 cnt1:4, - cnt2:4; - PAD_BYTES(2); - __le16 seq; - __le16 unknown; //FIXME -} __attribute__((__packed__)); - -/* Transmit Status in CPU byteorder. */ -struct bcm43xx_xmitstatus { - u16 cookie; - u8 flags; - u8 cnt1:4, - cnt2:4; - u16 seq; - u16 unknown; //FIXME -}; - -#define BCM43xx_TXSTAT_FLAG_ACK 0x01 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x02 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x04 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x08 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x10 -#define BCM43xx_TXSTAT_FLAG_IGNORE 0x20 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80 - - /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ static inline u8 bcm43xx_freq_to_channel_a(int freq) @@ -259,10 +137,6 @@ int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf); -int bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr); - void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, int iw_mode); @@ -283,11 +157,6 @@ int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *ne void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); -int bcm43xx_pci_read_config_16(struct pci_dev *pdev, u16 offset, u16 *val); -int bcm43xx_pci_read_config_32(struct pci_dev *pdev, u16 offset, u32 *val); -int bcm43xx_pci_write_config_16(struct pci_dev *pdev, int offset, u16 val); -int bcm43xx_pci_write_config_32(struct pci_dev *pdev, int offset, u32 val); - void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); void bcm43xx_mac_enable(struct bcm43xx_private *bcm); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 0bf4b3e26f9d..7b45fa1314c1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -26,6 +26,7 @@ #include "bcm43xx.h" #include "bcm43xx_pio.h" #include "bcm43xx_main.h" +#include "bcm43xx_xmit.h" #include diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c new file mode 100644 index 000000000000..5ee572e79f61 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c @@ -0,0 +1,579 @@ +/* + + Broadcom BCM43xx wireless driver + + Transmission (TX/RX) related functions. + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx_xmit.h" + +#include + + +/* Extract the bitrate out of a CCK PLCP header. */ +static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp) +{ + switch (plcp->raw[0]) { + case 0x0A: + return IEEE80211_CCK_RATE_1MB; + case 0x14: + return IEEE80211_CCK_RATE_2MB; + case 0x37: + return IEEE80211_CCK_RATE_5MB; + case 0x6E: + return IEEE80211_CCK_RATE_11MB; + } + assert(0); + return 0; +} + +/* Extract the bitrate out of an OFDM PLCP header. */ +static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp) +{ + switch (plcp->raw[0] & 0xF) { + case 0xB: + return IEEE80211_OFDM_RATE_6MB; + case 0xF: + return IEEE80211_OFDM_RATE_9MB; + case 0xA: + return IEEE80211_OFDM_RATE_12MB; + case 0xE: + return IEEE80211_OFDM_RATE_18MB; + case 0x9: + return IEEE80211_OFDM_RATE_24MB; + case 0xD: + return IEEE80211_OFDM_RATE_36MB; + case 0x8: + return IEEE80211_OFDM_RATE_48MB; + case 0xC: + return IEEE80211_OFDM_RATE_54MB; + } + assert(0); + return 0; +} + +u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) +{ + switch (bitrate) { + case IEEE80211_CCK_RATE_1MB: + return 0x0A; + case IEEE80211_CCK_RATE_2MB: + return 0x14; + case IEEE80211_CCK_RATE_5MB: + return 0x37; + case IEEE80211_CCK_RATE_11MB: + return 0x6E; + } + assert(0); + return 0; +} + +u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) +{ + switch (bitrate) { + case IEEE80211_OFDM_RATE_6MB: + return 0xB; + case IEEE80211_OFDM_RATE_9MB: + return 0xF; + case IEEE80211_OFDM_RATE_12MB: + return 0xA; + case IEEE80211_OFDM_RATE_18MB: + return 0xE; + case IEEE80211_OFDM_RATE_24MB: + return 0x9; + case IEEE80211_OFDM_RATE_36MB: + return 0xD; + case IEEE80211_OFDM_RATE_48MB: + return 0x8; + case IEEE80211_OFDM_RATE_54MB: + return 0xC; + } + assert(0); + return 0; +} + +static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, + const u16 octets, const u8 bitrate, + const int ofdm_modulation) +{ + __le32 *data = &(plcp->data); + __u8 *raw = plcp->raw; + + if (ofdm_modulation) { + *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate); + assert(!(octets & 0xF000)); + *data |= (octets << 5); + *data = cpu_to_le32(*data); + } else { + u32 plen; + + plen = octets * 16 / bitrate; + if ((octets * 16 % bitrate) > 0) { + plen++; + if ((bitrate == IEEE80211_CCK_RATE_11MB) + && ((octets * 8 % 11) < 4)) { + raw[1] = 0x84; + } else + raw[1] = 0x04; + } else + raw[1] = 0x04; + *data |= cpu_to_le32(plen << 16); + raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate); + } +} + +static u8 bcm43xx_calc_fallback_rate(u8 bitrate) +{ + switch (bitrate) { + case IEEE80211_CCK_RATE_1MB: + return IEEE80211_CCK_RATE_1MB; + case IEEE80211_CCK_RATE_2MB: + return IEEE80211_CCK_RATE_1MB; + case IEEE80211_CCK_RATE_5MB: + return IEEE80211_CCK_RATE_2MB; + case IEEE80211_CCK_RATE_11MB: + return IEEE80211_CCK_RATE_5MB; + case IEEE80211_OFDM_RATE_6MB: + return IEEE80211_CCK_RATE_5MB; + case IEEE80211_OFDM_RATE_9MB: + return IEEE80211_OFDM_RATE_6MB; + case IEEE80211_OFDM_RATE_12MB: + return IEEE80211_OFDM_RATE_9MB; + case IEEE80211_OFDM_RATE_18MB: + return IEEE80211_OFDM_RATE_12MB; + case IEEE80211_OFDM_RATE_24MB: + return IEEE80211_OFDM_RATE_18MB; + case IEEE80211_OFDM_RATE_36MB: + return IEEE80211_OFDM_RATE_24MB; + case IEEE80211_OFDM_RATE_48MB: + return IEEE80211_OFDM_RATE_36MB; + case IEEE80211_OFDM_RATE_54MB: + return IEEE80211_OFDM_RATE_48MB; + } + assert(0); + return 0; +} + +static +__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header, + u8 bitrate) +{ + const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl); + __le16 duration_id = wireless_header->duration_id; + + switch (WLAN_FC_GET_TYPE(frame_ctl)) { + case IEEE80211_FTYPE_DATA: + case IEEE80211_FTYPE_MGMT: + //TODO: Steal the code from ieee80211, once it is completed there. + break; + case IEEE80211_FTYPE_CTL: + /* Use the original duration/id. */ + break; + default: + assert(0); + } + + return duration_id; +} + +static inline +u16 ceiling_div(u16 dividend, u16 divisor) +{ + return ((dividend + divisor - 1) / divisor); +} + +static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy, + struct bcm43xx_txhdr *txhdr, + u16 *flags, + u8 bitrate, + const struct ieee80211_hdr_4addr *wlhdr) +{ + u16 fctl; + u16 dur; + u8 fallback_bitrate; + int ofdm_modulation; + int fallback_ofdm_modulation; + u8 *sa, *da; + u16 flen; + +//FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr); +//FIXME da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr); + fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate); + ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); + fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); + + flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN, + bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp), + flen, bitrate, + !ieee80211_is_cck_rate(bitrate)); + bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp), + flen, fallback_bitrate, + !ieee80211_is_cck_rate(fallback_bitrate)); + fctl = IEEE80211_FTYPE_CTL; + fctl |= IEEE80211_STYPE_RTS; + dur = le16_to_cpu(wlhdr->duration_id); +/*FIXME: should we test for dur==0 here and let it unmodified in this case? + * The following assert checks for this case... + */ +assert(dur); +/*FIXME: The duration calculation is not really correct. + * I am not 100% sure which bitrate to use. We use the RTS rate here, + * but this is likely to be wrong. + */ + if (phy->type == BCM43xx_PHYTYPE_A) { + /* Three times SIFS */ + dur += 16 * 3; + /* Add ACK duration. */ + dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10, + bitrate * 4); + /* Add CTS duration. */ + dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10, + bitrate * 4); + } else { + /* Three times SIFS */ + dur += 10 * 3; + /* Add ACK duration. */ + dur += ceiling_div(8 * (14 /*bytes*/) * 10, + bitrate); + /* Add CTS duration. */ + dur += ceiling_div(8 * (14 /*bytes*/) * 10, + bitrate); + } + + txhdr->rts_cts_frame_control = cpu_to_le16(fctl); + txhdr->rts_cts_dur = cpu_to_le16(dur); +//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3)); +//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da)); + memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME! + memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN); + + *flags |= BCM43xx_TXHDRFLAG_RTSCTS; + *flags |= BCM43xx_TXHDRFLAG_RTS; + if (ofdm_modulation) + *flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM; + if (fallback_ofdm_modulation) + *flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM; +} + +void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + const unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie) +{ + const struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data; + const struct ieee80211_security *secinfo = &bcm->ieee->sec; + u8 bitrate; + u8 fallback_bitrate; + int ofdm_modulation; + int fallback_ofdm_modulation; + u16 plcp_fragment_len = fragment_len; + u16 flags = 0; + u16 control = 0; + u16 wsec_rate = 0; + u16 encrypt_frame; + + /* Now construct the TX header. */ + memset(txhdr, 0, sizeof(*txhdr)); + + bitrate = bcm->softmac->txrates.default_rate; + ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); + fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate); + fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); + + /* Set Frame Control from 80211 header. */ + txhdr->frame_control = wireless_header->frame_ctl; + /* Copy address1 from 80211 header. */ + memcpy(txhdr->mac1, wireless_header->addr1, 6); + /* Set the fallback duration ID. */ + txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header, + fallback_bitrate); + /* Set the cookie (used as driver internal ID for the frame) */ + txhdr->cookie = cpu_to_le16(cookie); + + /* Hardware appends FCS. */ + plcp_fragment_len += IEEE80211_FCS_LEN; + + /* Hardware encryption. */ + encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED; + if (encrypt_frame && !bcm->ieee->host_encrypt) { + const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header; + memcpy(txhdr->wep_iv, hdr->payload, 4); + /* Hardware appends ICV. */ + plcp_fragment_len += 4; + + wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT) + & BCM43xx_TXHDR_WSEC_ALGO_MASK; + wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT) + & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK; + } + + /* Generate the PLCP header and the fallback PLCP header. */ + bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp), + plcp_fragment_len, + bitrate, ofdm_modulation); + bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len, + fallback_bitrate, fallback_ofdm_modulation); + + /* Set the CONTROL field */ + if (ofdm_modulation) + control |= BCM43xx_TXHDRCTL_OFDM; + if (bcm->short_preamble) //FIXME: could be the other way around, please test + control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE; + control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT) + & BCM43xx_TXHDRCTL_ANTENNADIV_MASK; + + /* Set the FLAGS field */ + if (!is_multicast_ether_addr(wireless_header->addr1) && + !is_broadcast_ether_addr(wireless_header->addr1)) + flags |= BCM43xx_TXHDRFLAG_EXPECTACK; + if (1 /* FIXME: PS poll?? */) + flags |= 0x10; // FIXME: unknown meaning. + if (fallback_ofdm_modulation) + flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM; + if (is_first_fragment) + flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT; + + /* Set WSEC/RATE field */ + wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT) + & BCM43xx_TXHDR_RATE_MASK; + + /* Generate the RTS/CTS packet, if required. */ + /* FIXME: We should first try with CTS-to-self, + * if we are on 80211g. If we get too many + * failures (hidden nodes), we should switch back to RTS/CTS. + */ + if (0/*FIXME txctl->use_rts_cts*/) { + bcm43xx_generate_rts(phy, txhdr, &flags, + 0/*FIXME txctl->rts_cts_rate*/, + wireless_header); + } + + txhdr->flags = cpu_to_le16(flags); + txhdr->control = cpu_to_le16(control); + txhdr->wsec_rate = cpu_to_le16(wsec_rate); +} + +static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, + u8 in_rssi, int ofdm, + int adjust_2053, int adjust_2050) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + s32 tmp; + + switch (radio->version) { + case 0x2050: + if (ofdm) { + tmp = in_rssi; + if (tmp > 127) + tmp -= 256; + tmp *= 73; + tmp /= 64; + if (adjust_2050) + tmp += 25; + else + tmp -= 3; + } else { + if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { + if (in_rssi > 63) + in_rssi = 63; + tmp = radio->nrssi_lt[in_rssi]; + tmp = 31 - tmp; + tmp *= -131; + tmp /= 128; + tmp -= 57; + } else { + tmp = in_rssi; + tmp = 31 - tmp; + tmp *= -149; + tmp /= 128; + tmp -= 68; + } + if (phy->type == BCM43xx_PHYTYPE_G && + adjust_2050) + tmp += 25; + } + break; + case 0x2060: + if (in_rssi > 127) + tmp = in_rssi - 256; + else + tmp = in_rssi; + break; + default: + tmp = in_rssi; + tmp -= 11; + tmp *= 103; + tmp /= 64; + if (adjust_2053) + tmp -= 109; + else + tmp -= 83; + } + + return (s8)tmp; +} + +static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, + u8 in_rssi) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + s8 ret; + + if (phy->type == BCM43xx_PHYTYPE_A) { + //TODO: Incomplete specs. + ret = 0; + } else + ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1); + + return ret; +} + +int bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr) +{ + struct bcm43xx_plcp_hdr4 *plcp; + struct ieee80211_rx_stats stats; + struct ieee80211_hdr_4addr *wlhdr; + u16 frame_ctl; + int is_packet_for_us = 0; + int err = -EINVAL; + const u16 rxflags1 = le16_to_cpu(rxhdr->flags1); + const u16 rxflags2 = le16_to_cpu(rxhdr->flags2); + const u16 rxflags3 = le16_to_cpu(rxhdr->flags3); + const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM); + + if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) { + plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2); + /* Skip two unknown bytes and the PLCP header. */ + skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6)); + } else { + plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data); + /* Skip the PLCP header. */ + skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6)); + } + /* The SKB contains the PAYLOAD (wireless header + data) + * at this point. The FCS at the end is stripped. + */ + + memset(&stats, 0, sizeof(stats)); + stats.mac_time = le16_to_cpu(rxhdr->mactime); + stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, + !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), + !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); + stats.signal = rxhdr->signal_quality; //FIXME +//TODO stats.noise = + if (is_ofdm) + stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp); + else + stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp); +//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate); + stats.received_channel = bcm->current_core->radio->channel; +//TODO stats.control = + stats.mask = IEEE80211_STATMASK_SIGNAL | +//TODO IEEE80211_STATMASK_NOISE | + IEEE80211_STATMASK_RATE | + IEEE80211_STATMASK_RSSI; + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + stats.freq = IEEE80211_52GHZ_BAND; + else + stats.freq = IEEE80211_24GHZ_BAND; + stats.len = skb->len; + + bcm->stats.last_rx = jiffies; + if (bcm->ieee->iw_mode == IW_MODE_MONITOR) { + err = ieee80211_rx(bcm->ieee, skb, &stats); + return (err == 0) ? -EINVAL : 0; + } + + wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); + + switch (bcm->ieee->iw_mode) { + case IW_MODE_ADHOC: + if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || + memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || + is_broadcast_ether_addr(wlhdr->addr1) || + is_multicast_ether_addr(wlhdr->addr1) || + bcm->net_dev->flags & IFF_PROMISC) + is_packet_for_us = 1; + break; + case IW_MODE_INFRA: + default: + /* When receiving multicast or broadcast packets, filter out + the packets we send ourself; we shouldn't see those */ + if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || + memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || + (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) && + (is_broadcast_ether_addr(wlhdr->addr1) || + is_multicast_ether_addr(wlhdr->addr1) || + bcm->net_dev->flags & IFF_PROMISC))) + is_packet_for_us = 1; + break; + } + + frame_ctl = le16_to_cpu(wlhdr->frame_ctl); + if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { + frame_ctl &= ~IEEE80211_FCTL_PROTECTED; + wlhdr->frame_ctl = cpu_to_le16(frame_ctl); + /* trim IV and ICV */ + /* FIXME: this must be done only for WEP encrypted packets */ + if (skb->len < 32) { + dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag " + "set and length < 32)\n"); + return -EINVAL; + } else { + memmove(skb->data + 4, skb->data, 24); + skb_pull(skb, 4); + skb_trim(skb, skb->len - 4); + stats.len -= 8; + } + wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); + } + + switch (WLAN_FC_GET_TYPE(frame_ctl)) { + case IEEE80211_FTYPE_MGMT: + ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); + break; + case IEEE80211_FTYPE_DATA: + if (is_packet_for_us) { + err = ieee80211_rx(bcm->ieee, skb, &stats); + err = (err == 0) ? -EINVAL : 0; + } + break; + case IEEE80211_FTYPE_CTL: + break; + default: + assert(0); + return -EINVAL; + } + + return err; +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h new file mode 100644 index 000000000000..2aed19e35c77 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h @@ -0,0 +1,156 @@ +#ifndef BCM43xx_XMIT_H_ +#define BCM43xx_XMIT_H_ + +#include "bcm43xx_main.h" + + +#define _bcm43xx_declare_plcp_hdr(size) \ + struct bcm43xx_plcp_hdr##size { \ + union { \ + __le32 data; \ + __u8 raw[size]; \ + } __attribute__((__packed__)); \ + } __attribute__((__packed__)) + +/* struct bcm43xx_plcp_hdr4 */ +_bcm43xx_declare_plcp_hdr(4); +/* struct bcm43xx_plcp_hdr6 */ +_bcm43xx_declare_plcp_hdr(6); + +#undef _bcm43xx_declare_plcp_hdr + +/* Device specific TX header. To be prepended to TX frames. */ +struct bcm43xx_txhdr { + union { + struct { + __le16 flags; + __le16 wsec_rate; + __le16 frame_control; + u16 unknown_zeroed_0; + __le16 control; + u8 wep_iv[10]; + u8 unknown_wsec_tkip_data[3]; //FIXME + PAD_BYTES(3); + u8 mac1[6]; + u16 unknown_zeroed_1; + struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp; + __le16 rts_cts_dur_fallback; + struct bcm43xx_plcp_hdr4 fallback_plcp; + __le16 fallback_dur_id; + PAD_BYTES(2); + __le16 cookie; + __le16 unknown_scb_stuff; //FIXME + struct bcm43xx_plcp_hdr6 rts_cts_plcp; + __le16 rts_cts_frame_control; + __le16 rts_cts_dur; + u8 rts_cts_mac1[6]; + u8 rts_cts_mac2[6]; + PAD_BYTES(2); + struct bcm43xx_plcp_hdr6 plcp; + } __attribute__((__packed__)); + u8 raw[82]; + } __attribute__((__packed__)); +} __attribute__((__packed__)); + +/* Values/Masks for the device TX header */ +#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001 +#define BCM43xx_TXHDRFLAG_RTSCTS 0x0002 +#define BCM43xx_TXHDRFLAG_RTS 0x0004 +#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008 +#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020 +#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM 0x0080 +#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100 +#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM 0x0200 +#define BCM43xx_TXHDRFLAG_CTS 0x0400 +#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800 + +#define BCM43xx_TXHDRCTL_OFDM 0x0001 +#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010 +#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030 +#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8 + +#define BCM43xx_TXHDR_RATE_MASK 0x0F00 +#define BCM43xx_TXHDR_RATE_SHIFT 8 +#define BCM43xx_TXHDR_RTSRATE_MASK 0xF000 +#define BCM43xx_TXHDR_RTSRATE_SHIFT 12 +#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0 +#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4 +#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003 +#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0 + +void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + const unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie); + +/* RX header as received from the hardware. */ +struct bcm43xx_rxhdr { + /* Frame Length. Must be generated explicitely in PIO mode. */ + __le16 frame_length; + PAD_BYTES(2); + /* Flags field 1 */ + __le16 flags1; + u8 rssi; + u8 signal_quality; + PAD_BYTES(2); + /* Flags field 3 */ + __le16 flags3; + /* Flags field 2 */ + __le16 flags2; + /* Lower 16bits of the TSF at the time the frame started. */ + __le16 mactime; + PAD_BYTES(14); +} __attribute__((__packed__)); + +#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0) +/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */ +#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7) +#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14) + +#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0) +#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2) +/*FIXME: WEP related flags */ + +#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10) + +/* Transmit Status as received from the hardware. */ +struct bcm43xx_hwxmitstatus { + PAD_BYTES(4); + __le16 cookie; + u8 flags; + u8 cnt1:4, + cnt2:4; + PAD_BYTES(2); + __le16 seq; + __le16 unknown; //FIXME +} __attribute__((__packed__)); + +/* Transmit Status in CPU byteorder. */ +struct bcm43xx_xmitstatus { + u16 cookie; + u8 flags; + u8 cnt1:4, + cnt2:4; + u16 seq; + u16 unknown; //FIXME +}; + +#define BCM43xx_TXSTAT_FLAG_ACK 0x01 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x02 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x04 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x08 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x10 +#define BCM43xx_TXSTAT_FLAG_IGNORE 0x20 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80 + +u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate); +u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate); + +int bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr); + +#endif /* BCM43xx_XMIT_H_ */ -- cgit v1.2.3-59-g8ed1b From 367f899ac3b52cf4611cd291ec2bfbf774b15bc7 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 28 Feb 2006 15:32:19 +0100 Subject: [PATCH] bcm43xx: Add sysfs attributes for device specific tunables. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Makefile | 2 +- drivers/net/wireless/bcm43xx/bcm43xx.h | 3 + drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4 + drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 323 +++++++++++++++++++++++++++ drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h | 25 +++ 5 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile index 2962b5f9e3e7..bb5220c629d2 100644 --- a/drivers/net/wireless/bcm43xx/Makefile +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -8,5 +8,5 @@ bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \ bcm43xx_radio.o bcm43xx_phy.o \ bcm43xx_power.o bcm43xx_wx.o \ bcm43xx_leds.o bcm43xx_ethtool.o \ - bcm43xx_xmit.o \ + bcm43xx_xmit.o bcm43xx_sysfs.o \ $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 21c75cae14bf..fd9754b52951 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -15,6 +15,7 @@ #include "bcm43xx_debugfs.h" #include "bcm43xx_leds.h" +#include "bcm43xx_sysfs.h" #define PFX KBUILD_MODNAME ": " @@ -606,6 +607,8 @@ struct bcm43xx_key { }; struct bcm43xx_private { + struct bcm43xx_sysfs sysfs; + struct ieee80211_device *ieee; struct ieee80211softmac_device *softmac; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index f1ac9940f14c..1fe2fa9856e3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3160,6 +3160,8 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) int i, err; unsigned long flags; + bcm43xx_sysfs_unregister(bcm); + bcm43xx_periodic_tasks_delete(bcm); spin_lock_irqsave(&bcm->lock, flags); @@ -3270,6 +3272,8 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) spin_unlock_irqrestore(&bcm->lock, flags); bcm43xx_periodic_tasks_setup(bcm); + bcm43xx_sysfs_register(bcm); + //FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though... assert(err == 0); out: diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c new file mode 100644 index 000000000000..2d31737372fd --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -0,0 +1,323 @@ +/* + + Broadcom BCM43xx wireless driver + + SYSFS support routines + + Copyright (c) 2006 Michael Buesch + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx_sysfs.h" +#include "bcm43xx.h" +#include "bcm43xx_main.h" +#include "bcm43xx_radio.h" + +#include + + +#define GENERIC_FILESIZE 64 + + +static int get_integer(const char *buf, size_t count) +{ + char tmp[10 + 1] = { 0 }; + int ret = -EINVAL; + + if (count == 0) + goto out; + count = min(count, (size_t)10); + memcpy(tmp, buf, count); + ret = simple_strtol(tmp, NULL, 10); +out: + return ret; +} + +static int get_boolean(const char *buf, size_t count) +{ + if (count != 0) { + if (buf[0] == '1') + return 1; + if (buf[0] == '0') + return 0; + if (count >= 4 && memcmp(buf, "true", 4) == 0) + return 1; + if (count >= 5 && memcmp(buf, "false", 5) == 0) + return 0; + if (count >= 3 && memcmp(buf, "yes", 3) == 0) + return 1; + if (count >= 2 && memcmp(buf, "no", 2) == 0) + return 0; + if (count >= 2 && memcmp(buf, "on", 2) == 0) + return 1; + if (count >= 3 && memcmp(buf, "off", 3) == 0) + return 0; + } + return -EINVAL; +} + +static ssize_t bcm43xx_attr_sprom_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom); + u16 *sprom; + unsigned long flags; + int i, err; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE); + sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), + GFP_KERNEL); + if (!sprom) + return -ENOMEM; + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + err = bcm43xx_sprom_read(bcm, sprom); + if (!err) { + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { + buf[i * 2] = sprom[i] & 0x00FF; + buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8; + } + } + spin_unlock_irqrestore(&bcm->lock, flags); + kfree(sprom); + + return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16); +} + +static ssize_t bcm43xx_attr_sprom_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom); + u16 *sprom; + unsigned long flags; + int i, err; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (count != BCM43xx_SPROM_SIZE * sizeof(u16)) + return -EINVAL; + sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), + GFP_KERNEL); + if (!sprom) + return -ENOMEM; + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { + sprom[i] = buf[i * 2] & 0xFF; + sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8; + } + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + err = bcm43xx_sprom_write(bcm, sprom); + spin_unlock_irqrestore(&bcm->lock, flags); + kfree(sprom); + + return err ? err : count; + +} + +static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode); + unsigned long flags; + int err; + ssize_t count = 0; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + + switch (bcm->current_core->radio->interfmode) { + case BCM43xx_RADIO_INTERFMODE_NONE: + count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n"); + break; + case BCM43xx_RADIO_INTERFMODE_NONWLAN: + count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference Mitigation)\n"); + break; + case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: + count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference Mitigation)\n"); + break; + default: + assert(0); + } + err = 0; + + spin_unlock_irqrestore(&bcm->lock, flags); + return err ? err : count; + +} + +static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode); + unsigned long flags; + int err; + int mode; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + mode = get_integer(buf, count); + switch (mode) { + case 0: + mode = BCM43xx_RADIO_INTERFMODE_NONE; + break; + case 1: + mode = BCM43xx_RADIO_INTERFMODE_NONWLAN; + break; + case 2: + mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; + break; + case 3: + mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; + break; + default: + return -EINVAL; + } + + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + + err = bcm43xx_radio_set_interference_mitigation(bcm, mode); + if (err) { + printk(KERN_ERR PFX "Interference Mitigation not " + "supported by device\n"); + } + + spin_unlock_irqrestore(&bcm->lock, flags); + + return err ? err : count; +} + +static ssize_t bcm43xx_attr_preamble_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble); + unsigned long flags; + int err; + ssize_t count; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + + if (bcm->short_preamble) + count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); + else + count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); + + err = 0; + spin_unlock_irqrestore(&bcm->lock, flags); + + return err ? err : count; +} + +static ssize_t bcm43xx_attr_preamble_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble); + unsigned long flags; + int err; + int value; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + value = get_boolean(buf, count); + if (value < 0) + return value; + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + + bcm->short_preamble = !!value; + + err = 0; + spin_unlock_irqrestore(&bcm->lock, flags); + + return err ? err : count; +} + +int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) +{ + struct device *dev = &bcm->pci_dev->dev; + struct bcm43xx_sysfs *sysfs = &bcm->sysfs; + int err; + + assert(bcm->initialized); + + sysfs->attr_sprom.attr.name = "sprom"; + sysfs->attr_sprom.attr.owner = THIS_MODULE; + sysfs->attr_sprom.attr.mode = 0600; + sysfs->attr_sprom.show = bcm43xx_attr_sprom_show; + sysfs->attr_sprom.store = bcm43xx_attr_sprom_store; + err = device_create_file(dev, &sysfs->attr_sprom); + if (err) + goto out; + + sysfs->attr_interfmode.attr.name = "interference"; + sysfs->attr_interfmode.attr.owner = THIS_MODULE; + sysfs->attr_interfmode.attr.mode = 0600; + sysfs->attr_interfmode.show = bcm43xx_attr_interfmode_show; + sysfs->attr_interfmode.store = bcm43xx_attr_interfmode_store; + err = device_create_file(dev, &sysfs->attr_interfmode); + if (err) + goto err_remove_sprom; + + sysfs->attr_preamble.attr.name = "shortpreamble"; + sysfs->attr_preamble.attr.owner = THIS_MODULE; + sysfs->attr_preamble.attr.mode = 0600; + sysfs->attr_preamble.show = bcm43xx_attr_preamble_show; + sysfs->attr_preamble.store = bcm43xx_attr_preamble_store; + err = device_create_file(dev, &sysfs->attr_preamble); + if (err) + goto err_remove_interfmode; + +out: + return err; +err_remove_interfmode: + device_remove_file(dev, &sysfs->attr_interfmode); +err_remove_sprom: + device_remove_file(dev, &sysfs->attr_sprom); + goto out; +} + +void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm) +{ + struct device *dev = &bcm->pci_dev->dev; + struct bcm43xx_sysfs *sysfs = &bcm->sysfs; + + device_remove_file(dev, &sysfs->attr_preamble); + device_remove_file(dev, &sysfs->attr_interfmode); + device_remove_file(dev, &sysfs->attr_sprom); +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h new file mode 100644 index 000000000000..57f14514e3e0 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h @@ -0,0 +1,25 @@ +#ifndef BCM43xx_SYSFS_H_ +#define BCM43xx_SYSFS_H_ + +#include + + +struct bcm43xx_sysfs { + struct device_attribute attr_sprom; + struct device_attribute attr_interfmode; + struct device_attribute attr_preamble; +}; + +#define devattr_to_bcm(attr, attr_name) ({ \ + struct bcm43xx_sysfs *__s; struct bcm43xx_private *__p; \ + __s = container_of((attr), struct bcm43xx_sysfs, attr_name); \ + __p = container_of(__s, struct bcm43xx_private, sysfs); \ + __p; \ + }) + +struct bcm43xx_private; + +int bcm43xx_sysfs_register(struct bcm43xx_private *bcm); +void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm); + +#endif /* BCM43xx_SYSFS_H_ */ -- cgit v1.2.3-59-g8ed1b From 512a80916b8d04529c0915534c63529144f74e10 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Tue, 7 Mar 2006 01:37:51 +0100 Subject: [PATCH] bcm43xx: fix DMA TX skb freeing in case of fragmented packets. It seems to me that the today's wireless-2.6 git contains bcm43xx which does not free txb's correctly, if I understand it right. Consider a situation where a txb with two skb's is sent down. The dma_tx_fragment will save the pointer to meta->txb of the first fragment. If fragments are freed in order, ieee80211_txb_free frees both skb's when the first fragment is processed. This may result in reuse of the second skb's memory. This danger is rather remote, but it seems to me that the patch below not only fixes the problem, but also makes the code simpler, which is good, right? Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 44 ++++++------------------------ drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 4 --- 2 files changed, 8 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index e20fbaf29e0b..0cd292847954 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -170,19 +170,6 @@ void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring, addr, len, DMA_FROM_DEVICE); } -static inline -void mark_skb_mustfree(struct sk_buff *skb, - char mustfree) -{ - skb->cb[0] = mustfree; -} - -static inline -int skb_mustfree(struct sk_buff *skb) -{ - return (skb->cb[0] != 0); -} - /* Unmap and free a descriptor buffer. */ static inline void free_descriptor_buffer(struct bcm43xx_dmaring *ring, @@ -191,17 +178,11 @@ void free_descriptor_buffer(struct bcm43xx_dmaring *ring, int irq_context) { assert(meta->skb); - if (skb_mustfree(meta->skb)) { - if (irq_context) - dev_kfree_skb_irq(meta->skb); - else - dev_kfree_skb(meta->skb); - } + if (irq_context) + dev_kfree_skb_irq(meta->skb); + else + dev_kfree_skb(meta->skb); meta->skb = NULL; - if (meta->txb) { - ieee80211_txb_free(meta->txb); - meta->txb = NULL; - } } static int alloc_ringmemory(struct bcm43xx_dmaring *ring) @@ -334,7 +315,6 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, meta->skb = skb; meta->dmaaddr = dmaaddr; skb->dev = ring->bcm->net_dev; - mark_skb_mustfree(skb, 1); desc_addr = (u32)(dmaaddr + ring->memoffset); desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK & (u32)(ring->rx_buffersize - ring->frameoffset)); @@ -457,7 +437,6 @@ static void free_all_descbuffers(struct bcm43xx_dmaring *ring) if (!meta->skb) { assert(ring->tx); - assert(!meta->txb); continue; } if (ring->tx) { @@ -726,7 +705,6 @@ static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, static int dma_tx_fragment(struct bcm43xx_dmaring *ring, struct sk_buff *skb, - struct ieee80211_txb *txb, u8 cur_frag) { int slot; @@ -741,11 +719,6 @@ static int dma_tx_fragment(struct bcm43xx_dmaring *ring, desc = ring->vbase + slot; meta = ring->meta + slot; - if (cur_frag == 0) { - /* Save the txb pointer for freeing in xmitstatus IRQ */ - meta->txb = txb; - } - /* Add a device specific TX header. */ assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); /* Reserve enough headroom for the device tx header. */ @@ -810,13 +783,12 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, for (i = 0; i < txb->nr_frags; i++) { skb = txb->fragments[i]; - /* We do not free the skb, as it is freed as - * part of the txb freeing. - */ - mark_skb_mustfree(skb, 0); - dma_tx_fragment(ring, skb, txb, i); + /* Take skb from ieee80211_txb_free */ + txb->fragments[i] = NULL; + dma_tx_fragment(ring, skb, i); //TODO: handle failure of dma_tx_fragment } + ieee80211_txb_free(txb); return 0; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index 88ad34dff2f2..cab8e2ba4c7e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -119,10 +119,6 @@ struct bcm43xx_dmadesc_meta { struct sk_buff *skb; /* DMA base bus-address of the descriptor buffer. */ dma_addr_t dmaaddr; - /* Pointer to our txb (can be NULL). - * This should be freed in completion IRQ. - */ - struct ieee80211_txb *txb; }; struct bcm43xx_dmaring { -- cgit v1.2.3-59-g8ed1b From 4d5a9e0eeb7ec928c6bd55db410f09ed3779bc2a Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 11 Mar 2006 13:15:02 +0100 Subject: [PATCH] bcm43xx: Set both, the DMAmask and the coherent DMAmask. This has a potential to fix the >1G bug. But I can not test that, yet. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 1fe2fa9856e3..6da0beb0a933 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3717,6 +3717,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, struct net_device *net_dev, struct pci_dev *pci_dev) { + int err; + bcm->ieee = netdev_priv(net_dev); bcm->softmac = ieee80211_priv(net_dev); bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; @@ -3735,8 +3737,7 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; bcm->pci_dev = pci_dev; bcm->net_dev = net_dev; - if (modparam_bad_frames_preempt) - bcm->bad_frames_preempt = 1; + bcm->bad_frames_preempt = modparam_bad_frames_preempt; spin_lock_init(&bcm->lock); tasklet_init(&bcm->isr_tasklet, (void (*)(unsigned long))bcm43xx_interrupt_tasklet, @@ -3745,7 +3746,9 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, if (modparam_pio) { bcm->__using_pio = 1; } else { - if (pci_set_dma_mask(pci_dev, DMA_30BIT_MASK)) { + err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK); + err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK); + if (err) { #ifdef CONFIG_BCM43XX_PIO printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n"); bcm->__using_pio = 1; -- cgit v1.2.3-59-g8ed1b From efccb647f486ff8174b4db0ab8145df8dd42ce6d Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 11 Mar 2006 13:39:14 +0100 Subject: [PATCH] bcm43xx: Abstract the locking mechanism. This is the starting point to make the driver out-of-order-MMIO-stores safe. There are more mmiowb() needed. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 20 ++++- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 26 +++--- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 75 +++++++++-------- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 25 +++--- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 112 ++++++++++++------------- 7 files changed, 142 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index fd9754b52951..5f8c63fab836 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -619,7 +619,9 @@ struct bcm43xx_private { void __iomem *mmio_addr; unsigned int mmio_len; - spinlock_t lock; + /* Do not use the lock directly. Use the bcm43xx_lock* helper + * functions, to be MMIO-safe. */ + spinlock_t _lock; /* Driver status flags. */ u32 initialized:1, /* init_board() succeed */ @@ -721,6 +723,22 @@ 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. + */ +#define bcm43xx_lock_mmio(bcm, flags) bcm43xx_lock(bcm, flags) +#define bcm43xx_unlock_mmio(bcm, flags) do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0) + static inline struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index 0bae0be4be2e..bcfcebe28261 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -77,7 +77,7 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, down(&big_buffer_sem); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) { fappend("Board not initialized.\n"); goto out; @@ -124,7 +124,7 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, fappend("\n"); out: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -162,7 +162,7 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, unsigned long flags; down(&big_buffer_sem); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) { fappend("Board not initialized.\n"); goto out; @@ -172,7 +172,7 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); out: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -191,7 +191,7 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, u64 tsf; down(&big_buffer_sem); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) { fappend("Board not initialized.\n"); goto out; @@ -202,7 +202,7 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, (unsigned int)(tsf & 0xFFFFFFFFULL)); out: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -224,7 +224,7 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, res = -EFAULT; goto out_up; } - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) { printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); res = -EFAULT; @@ -239,7 +239,7 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, res = buf_size; out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); out_up: up(&big_buffer_sem); return res; @@ -260,7 +260,7 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, int i, cnt, j = 0; down(&big_buffer_sem); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", BCM43xx_NR_LOGGED_XMITSTATUS); @@ -296,14 +296,14 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); if (*ppos == pos) { /* Done. Drop the copied data. */ e->xmitstatus_printing = 0; } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); up(&big_buffer_sem); return res; } @@ -419,7 +419,7 @@ void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, struct bcm43xx_dfsentry *e; struct bcm43xx_xmitstatus *savedstatus; - /* This is protected by bcm->lock */ + /* This is protected by bcm->_lock */ e = bcm->dfsentry; assert(e); savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 8f550c1a92ed..949555da5aa9 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; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (led->blink_interval) { bcm43xx_led_changestate(led); mod_timer(&led->blink_timer, jiffies + led->blink_interval); } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(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 6da0beb0a933..b7192559833c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -482,14 +482,14 @@ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *old u32 old; unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) { - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return -EBUSY; } old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); tasklet_disable(&bcm->isr_tasklet); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); if (oldstate) *oldstate = old; @@ -746,6 +746,7 @@ int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom) else if (i % 2) printk("."); bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); + mmiowb(); mdelay(20); } spromctl &= ~0x10; /* SPROM WRITE enable. */ @@ -1676,7 +1677,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) # define bcmirq_handled(irq) do { /* nothing */ } while (0) #endif /* CONFIG_BCM43XX_DEBUG*/ - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); reason = bcm->irq_reason; dma_reason[0] = bcm->dma_reason[0]; dma_reason[1] = bcm->dma_reason[1]; @@ -1776,7 +1777,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) if (!modparam_noleds) bcm43xx_leds_update(bcm, activity); bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); } #undef bcmirq_print_reasons @@ -1830,25 +1831,24 @@ static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, /* Interrupt handler top-half */ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs) { + irqreturn_t ret = IRQ_HANDLED; struct bcm43xx_private *bcm = dev_id; u32 reason, mask; if (!bcm) return IRQ_NONE; - spin_lock(&bcm->lock); + spin_lock(&bcm->_lock); reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); if (reason == 0xffffffff) { /* irq not for us (shared irq) */ - spin_unlock(&bcm->lock); - return IRQ_NONE; + ret = IRQ_NONE; + goto out; } mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); - if (!(reason & mask)) { - spin_unlock(&bcm->lock); - return IRQ_HANDLED; - } + if (!(reason & mask)) + goto out; bcm43xx_interrupt_ack(bcm, reason, mask); @@ -1866,9 +1866,11 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re tasklet_schedule(&bcm->isr_tasklet); } - spin_unlock(&bcm->lock); +out: + mmiowb(); + spin_unlock(&bcm->_lock); - return IRQ_HANDLED; + return ret; } static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) @@ -3112,7 +3114,7 @@ static void bcm43xx_periodic_task_handler(unsigned long d) unsigned long flags; unsigned int state; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); assert(bcm->initialized); state = bcm->periodic_state; @@ -3127,7 +3129,7 @@ static void bcm43xx_periodic_task_handler(unsigned long d) mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15)); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); } static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) @@ -3164,10 +3166,10 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) bcm43xx_periodic_tasks_delete(bcm); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->initialized = 0; bcm->shutting_down = 1; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE)) @@ -3182,9 +3184,9 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) bcm43xx_pctl_set_crystal(bcm, 0); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->shutting_down = 0; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); } static int bcm43xx_init_board(struct bcm43xx_private *bcm) @@ -3196,10 +3198,10 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) might_sleep(); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->initialized = 0; bcm->shutting_down = 0; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); err = bcm43xx_pctl_set_crystal(bcm, 1); if (err) @@ -3267,9 +3269,9 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) } /* Initialization of the board is done. Flag it as such. */ - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->initialized = 1; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); bcm43xx_periodic_tasks_setup(bcm); bcm43xx_sysfs_register(bcm); @@ -3570,11 +3572,11 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); bcm43xx_mac_suspend(bcm); bcm43xx_radio_selectchannel(bcm, channel, 0); bcm43xx_mac_enable(bcm); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); } /* set_security() callback in struct ieee80211_device */ @@ -3587,9 +3589,9 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, int keyidx; dprintk(KERN_INFO PFX "set security called\n"); - - spin_lock_irqsave(&bcm->lock, flags); - + + bcm43xx_lock_mmio(bcm, flags); + for (keyidx = 0; keyidxflags & (1<encode_alg[keyidx] = sec->encode_alg[keyidx]; @@ -3651,7 +3653,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, } else bcm43xx_clear_keys(bcm); } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); } /* hard_start_xmit() callback in struct ieee80211_device */ @@ -3663,10 +3665,10 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, int err = -ENODEV; unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (likely(bcm->initialized)) err = bcm43xx_tx(bcm, txb); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return err; } @@ -3679,8 +3681,11 @@ static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_de 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_controller_restart(bcm, "TX timeout"); + bcm43xx_unlock_mmio(bcm, flags); } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -3738,7 +3743,7 @@ 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->_lock); tasklet_init(&bcm->isr_tasklet, (void (*)(unsigned long))bcm43xx_interrupt_tasklet, (unsigned long)bcm); @@ -3921,11 +3926,11 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state) dprintk(KERN_INFO PFX "Suspending...\n"); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->was_initialized = bcm->initialized; if (bcm->initialized) try_to_shutdown = 1; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); netif_device_detach(net_dev); if (try_to_shutdown) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 7b45fa1314c1..26dc6047d458 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -258,7 +258,7 @@ static void tx_tasklet(unsigned long d) struct bcm43xx_pio_txpacket *packet, *tmp_packet; int err; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { assert(packet->xmitted_frags < packet->txb->nr_frags); if (packet->xmitted_frags == 0) { @@ -288,7 +288,7 @@ static void tx_tasklet(unsigned long d) next_packet: continue; } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); } static void setup_txqueues(struct bcm43xx_pioqueue *queue) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index 2d31737372fd..713ec601c342 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -88,7 +88,7 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev, GFP_KERNEL); if (!sprom) return -ENOMEM; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); assert(bcm->initialized); err = bcm43xx_sprom_read(bcm, sprom); if (!err) { @@ -97,7 +97,7 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev, buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8; } } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); kfree(sprom); return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16); @@ -125,10 +125,10 @@ static ssize_t bcm43xx_attr_sprom_store(struct device *dev, sprom[i] = buf[i * 2] & 0xFF; sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8; } - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); assert(bcm->initialized); err = bcm43xx_sprom_write(bcm, sprom); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); kfree(sprom); return err ? err : count; @@ -147,7 +147,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); assert(bcm->initialized); switch (bcm->current_core->radio->interfmode) { @@ -165,7 +165,8 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, } err = 0; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); + return err ? err : count; } @@ -200,7 +201,7 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, return -EINVAL; } - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); assert(bcm->initialized); err = bcm43xx_radio_set_interference_mitigation(bcm, mode); @@ -209,7 +210,7 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, "supported by device\n"); } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return err ? err : count; } @@ -226,7 +227,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); assert(bcm->initialized); if (bcm->short_preamble) @@ -235,7 +236,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); err = 0; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err ? err : count; } @@ -255,13 +256,13 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, value = get_boolean(buf, count); if (value < 0) return value; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); assert(bcm->initialized); bcm->short_preamble = !!value; err = 0; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err ? err : count; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index aa2d9930c436..208193851e8e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -61,7 +61,7 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, char suffix[7] = { 0 }; int have_a = 0, have_b = 0, have_g = 0; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); nr_80211 = bcm43xx_num_80211_cores(bcm); for (i = 0; i < nr_80211; i++) { phy = bcm->phy + i; @@ -78,7 +78,7 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, assert(0); } } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); i = 0; if (have_a) { @@ -113,7 +113,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, int freq; int err = -EINVAL; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { channel = data->freq.m; freq = bcm43xx_channel_to_freq(bcm, channel); @@ -133,7 +133,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, err = 0; } out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return err; } @@ -148,7 +148,7 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, int err = -ENODEV; u16 channel; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); channel = bcm->current_core->radio->channel; if (channel == 0xFF) { assert(!bcm->initialized); @@ -163,7 +163,7 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, err = 0; out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err; } @@ -181,10 +181,10 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev, if (mode == IW_MODE_AUTO) mode = BCM43xx_INITIAL_IWMODE; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (bcm->ieee->iw_mode != mode) bcm43xx_set_iwmode(bcm, mode); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return 0; } @@ -197,9 +197,9 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); data->mode = bcm->ieee->iw_mode; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -269,7 +269,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); range->num_bitrates = 0; i = 0; @@ -315,7 +315,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, } range->num_frequency = j; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -329,11 +329,11 @@ static int bcm43xx_wx_set_nick(struct net_device *net_dev, unsigned long flags; size_t len; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); memcpy(bcm->nick, extra, len); bcm->nick[len] = '\0'; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -347,12 +347,12 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev, unsigned long flags; size_t len; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); len = strlen(bcm->nick) + 1; memcpy(extra, bcm->nick, len); data->data.length = (__u16)len; data->data.flags = 1; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -366,7 +366,7 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); if (data->rts.disabled) { bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; err = 0; @@ -377,7 +377,7 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, err = 0; } } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err; } @@ -390,11 +390,11 @@ static int bcm43xx_wx_get_rts(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); data->rts.value = bcm->rts_threshold; data->rts.fixed = 0; data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -408,7 +408,7 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); if (data->frag.disabled) { bcm->ieee->fts = MAX_FRAG_THRESHOLD; err = 0; @@ -419,7 +419,7 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, err = 0; } } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err; } @@ -432,11 +432,11 @@ static int bcm43xx_wx_get_frag(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); data->frag.value = bcm->ieee->fts; data->frag.fixed = 0; data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -458,7 +458,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, return -EOPNOTSUPP; } - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) goto out_unlock; radio = bcm->current_core->radio; @@ -482,7 +482,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, err = 0; out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return err; } @@ -497,7 +497,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, unsigned long flags; int err = -ENODEV; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); if (!bcm->initialized) goto out_unlock; radio = bcm->current_core->radio; @@ -509,7 +509,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, err = 0; out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err; } @@ -632,7 +632,7 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, return -EINVAL; } - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (bcm->initialized) { err = bcm43xx_radio_set_interference_mitigation(bcm, mode); if (err) { @@ -647,7 +647,7 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, } else bcm->current_core->radio->interfmode = mode; } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return err; } @@ -661,9 +661,9 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, unsigned long flags; int mode; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); mode = bcm->current_core->radio->interfmode; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); switch (mode) { case BCM43xx_RADIO_INTERFMODE_NONE: @@ -693,9 +693,9 @@ static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, int on; on = *((int *)extra); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->short_preamble = !!on; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -709,9 +709,9 @@ static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, unsigned long flags; int on; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); on = bcm->short_preamble; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); if (on) strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); @@ -732,13 +732,13 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, int on; on = *((int *)extra); - spin_lock_irqsave(&bcm->lock, flags); + + bcm43xx_lock(bcm, flags); bcm->ieee->host_encrypt = !!on; bcm->ieee->host_decrypt = !!on; bcm->ieee->host_build_iv = !on; - - spin_unlock_irqrestore(&bcm->lock, flags); - + bcm43xx_unlock(bcm, flags); + return 0; } @@ -750,17 +750,17 @@ static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; int on; - - spin_lock_irqsave(&bcm->lock, flags); + + bcm43xx_lock(bcm, flags); on = bcm->ieee->host_encrypt; - spin_unlock_irqrestore(&bcm->lock, flags); - + bcm43xx_unlock(bcm, flags); + if (on) strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); else strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING); data->data.length = strlen(extra + 1); - + return 0; } @@ -816,17 +816,13 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev, if (!sprom) goto out; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); err = -ENODEV; - if (!bcm->initialized) { - spin_unlock_irqrestore(&bcm->lock, flags); - goto out_kfree; - } - err = bcm43xx_sprom_read(bcm, sprom); - spin_unlock_irqrestore(&bcm->lock, flags); + if (bcm->initialized) + err = bcm43xx_sprom_read(bcm, sprom); + bcm43xx_unlock_mmio(bcm, flags); if (!err) data->data.length = sprom2hex(sprom, extra); -out_kfree: kfree(sprom); out: return err; @@ -865,13 +861,11 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, if (err) goto out_kfree; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); err = -ENODEV; - if (!bcm->initialized) - goto out_unlock; - err = bcm43xx_sprom_write(bcm, sprom); -out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + if (bcm->initialized) + err = bcm43xx_sprom_write(bcm, sprom); + bcm43xx_unlock_mmio(bcm, flags); out_kfree: kfree(sprom); out: -- cgit v1.2.3-59-g8ed1b From 7ce942d0ff5df145831631f4df391c7207e676bb Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 11 Mar 2006 13:43:06 +0100 Subject: [PATCH] bcm43xx: Remove the mmio access printing facility overhead. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 101 ++-------------------------- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 35 ---------- 2 files changed, 6 insertions(+), 130 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 5f8c63fab836..29c95b07122a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -718,8 +718,6 @@ struct bcm43xx_private { /* Debugging stuff follows. */ #ifdef CONFIG_BCM43XX_DEBUG struct bcm43xx_dfsentry *dfsentry; - atomic_t mmio_print_cnt; - atomic_t pcicfg_print_cnt; #endif }; @@ -805,141 +803,54 @@ struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy, } -/* MMIO read/write functions. Debug and non-debug variants. */ -#ifdef CONFIG_BCM43XX_DEBUG - static inline u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset) { - u16 value; - - value = ioread16(bcm->mmio_addr + core_offset(bcm) + offset); - if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { - printk(KERN_INFO PFX "ioread16 offset: 0x%04x, value: 0x%04x\n", - offset, value); - } - - return value; + return ioread16(bcm->mmio_addr + core_offset(bcm) + offset); } static inline void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value) { iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset); - if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { - printk(KERN_INFO PFX "iowrite16 offset: 0x%04x, value: 0x%04x\n", - offset, value); - } } static inline u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset) { - u32 value; - - value = ioread32(bcm->mmio_addr + core_offset(bcm) + offset); - if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { - printk(KERN_INFO PFX "ioread32 offset: 0x%04x, value: 0x%08x\n", - offset, value); - } - - return value; + return ioread32(bcm->mmio_addr + core_offset(bcm) + offset); } static inline void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value) { iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset); - if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { - printk(KERN_INFO PFX "iowrite32 offset: 0x%04x, value: 0x%08x\n", - offset, value); - } } static inline int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value) { - int err; - - err = pci_read_config_word(bcm->pci_dev, offset, value); - if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { - printk(KERN_INFO PFX "pciread16 offset: 0x%08x, value: 0x%04x, err: %d\n", - offset, *value, err); - } - - return err; + return pci_read_config_word(bcm->pci_dev, offset, value); } static inline int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value) { - int err; - - err = pci_read_config_dword(bcm->pci_dev, offset, value); - if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { - printk(KERN_INFO PFX "pciread32 offset: 0x%08x, value: 0x%08x, err: %d\n", - offset, *value, err); - } - - return err; + return pci_read_config_dword(bcm->pci_dev, offset, value); } static inline int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value) { - int err; - - err = pci_write_config_word(bcm->pci_dev, offset, value); - if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { - printk(KERN_INFO PFX "pciwrite16 offset: 0x%08x, value: 0x%04x, err: %d\n", - offset, value, err); - } - - return err; + return pci_write_config_word(bcm->pci_dev, offset, value); } static inline int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value) { - int err; - - err = pci_write_config_dword(bcm->pci_dev, offset, value); - if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { - printk(KERN_INFO PFX "pciwrite32 offset: 0x%08x, value: 0x%08x, err: %d\n", - offset, value, err); - } - - return err; + return pci_write_config_dword(bcm->pci_dev, offset, value); } -#define bcm43xx_mmioprint_initial(bcm, value) atomic_set(&(bcm)->mmio_print_cnt, (value)) -#define bcm43xx_mmioprint_enable(bcm) atomic_inc(&(bcm)->mmio_print_cnt) -#define bcm43xx_mmioprint_disable(bcm) atomic_dec(&(bcm)->mmio_print_cnt) -#define bcm43xx_pciprint_initial(bcm, value) atomic_set(&(bcm)->pcicfg_print_cnt, (value)) -#define bcm43xx_pciprint_enable(bcm) atomic_inc(&(bcm)->pcicfg_print_cnt) -#define bcm43xx_pciprint_disable(bcm) atomic_dec(&(bcm)->pcicfg_print_cnt) - -#else /* CONFIG_BCM43XX_DEBUG*/ - -#define bcm43xx_read16(bcm, offset) ioread16((bcm)->mmio_addr + core_offset(bcm) + (offset)) -#define bcm43xx_write16(bcm, offset, value) iowrite16((value), (bcm)->mmio_addr + core_offset(bcm) + (offset)) -#define bcm43xx_read32(bcm, offset) ioread32((bcm)->mmio_addr + core_offset(bcm) + (offset)) -#define bcm43xx_write32(bcm, offset, value) iowrite32((value), (bcm)->mmio_addr + core_offset(bcm) + (offset)) -#define bcm43xx_pci_read_config16(bcm, o, v) pci_read_config_word((bcm)->pci_dev, (o), (v)) -#define bcm43xx_pci_read_config32(bcm, o, v) pci_read_config_dword((bcm)->pci_dev, (o), (v)) -#define bcm43xx_pci_write_config16(bcm, o, v) pci_write_config_word((bcm)->pci_dev, (o), (v)) -#define bcm43xx_pci_write_config32(bcm, o, v) pci_write_config_dword((bcm)->pci_dev, (o), (v)) - -#define bcm43xx_mmioprint_initial(x, y) do { /* nothing */ } while (0) -#define bcm43xx_mmioprint_enable(x) do { /* nothing */ } while (0) -#define bcm43xx_mmioprint_disable(x) do { /* nothing */ } while (0) -#define bcm43xx_pciprint_initial(bcm, value) do { /* nothing */ } while (0) -#define bcm43xx_pciprint_enable(bcm) do { /* nothing */ } while (0) -#define bcm43xx_pciprint_disable(bcm) do { /* nothing */ } while (0) - -#endif /* CONFIG_BCM43XX_DEBUG*/ - - /** Limit a value between two limits */ #ifdef limit_value # undef limit_value diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index b7192559833c..f3cef345c8f9 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2018,12 +2018,6 @@ static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) const u32 *data; unsigned int i, len; -#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT - bcm43xx_mmioprint_enable(bcm); -#else - bcm43xx_mmioprint_disable(bcm); -#endif - /* Upload Microcode. */ data = (u32 *)(bcm->ucode->data); len = bcm->ucode->size / sizeof(u32); @@ -2045,12 +2039,6 @@ static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) be32_to_cpu(data[i])); udelay(10); } - -#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT - bcm43xx_mmioprint_disable(bcm); -#else - bcm43xx_mmioprint_enable(bcm); -#endif } static int bcm43xx_write_initvals(struct bcm43xx_private *bcm, @@ -2090,12 +2078,6 @@ static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) { int err; -#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT - bcm43xx_mmioprint_enable(bcm); -#else - bcm43xx_mmioprint_disable(bcm); -#endif - err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, bcm->initvals0->size / sizeof(struct bcm43xx_initval)); if (err) @@ -2106,13 +2088,7 @@ static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) if (err) goto out; } - out: -#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT - bcm43xx_mmioprint_disable(bcm); -#else - bcm43xx_mmioprint_enable(bcm); -#endif return err; } @@ -3728,17 +3704,6 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, bcm->softmac = ieee80211_priv(net_dev); bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; -#ifdef DEBUG_ENABLE_MMIO_PRINT - bcm43xx_mmioprint_initial(bcm, 1); -#else - bcm43xx_mmioprint_initial(bcm, 0); -#endif -#ifdef DEBUG_ENABLE_PCILOG - bcm43xx_pciprint_initial(bcm, 1); -#else - bcm43xx_pciprint_initial(bcm, 0); -#endif - bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; bcm->pci_dev = pci_dev; bcm->net_dev = net_dev; -- cgit v1.2.3-59-g8ed1b From 73733847beead47dc31b1f8e1532e5eea9f8ddd3 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Mar 2006 19:44:29 +0100 Subject: [PATCH] bcm43xx: fix some stuff, add a few missing mmiowb(), remove dead code. This may workaround the XMIT ERRORs some people are getting. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 23 +--- drivers/net/wireless/bcm43xx/bcm43xx_ilt.c | 42 +----- drivers/net/wireless/bcm43xx/bcm43xx_ilt.h | 6 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 76 +++++++---- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 187 ++++++++++++++------------- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 20 +-- 6 files changed, 167 insertions(+), 187 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index cab8e2ba4c7e..c07e34689be1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -9,27 +9,10 @@ /* DMA-Interrupt reasons. */ -/*TODO: add the missing ones. */ -#define BCM43xx_DMAIRQ_ERR0 (1 << 10) -#define BCM43xx_DMAIRQ_ERR1 (1 << 11) -#define BCM43xx_DMAIRQ_ERR2 (1 << 12) -#define BCM43xx_DMAIRQ_ERR3 (1 << 13) -#define BCM43xx_DMAIRQ_ERR4 (1 << 14) -#define BCM43xx_DMAIRQ_ERR5 (1 << 15) +#define BCM43xx_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ + | (1 << 14) | (1 << 15)) +#define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13) #define BCM43xx_DMAIRQ_RX_DONE (1 << 16) -/* helpers */ -#define BCM43xx_DMAIRQ_ANYERR (BCM43xx_DMAIRQ_ERR0 | \ - BCM43xx_DMAIRQ_ERR1 | \ - BCM43xx_DMAIRQ_ERR2 | \ - BCM43xx_DMAIRQ_ERR3 | \ - BCM43xx_DMAIRQ_ERR4 | \ - BCM43xx_DMAIRQ_ERR5) -#define BCM43xx_DMAIRQ_FATALERR (BCM43xx_DMAIRQ_ERR0 | \ - BCM43xx_DMAIRQ_ERR1 | \ - BCM43xx_DMAIRQ_ERR2 | \ - BCM43xx_DMAIRQ_ERR4 | \ - BCM43xx_DMAIRQ_ERR5) -#define BCM43xx_DMAIRQ_NONFATALERR BCM43xx_DMAIRQ_ERR3 /* DMA controller register offsets. (relative to BCM43xx_DMA#_BASE) */ #define BCM43xx_DMA_TX_CONTROL 0x00 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c index 22587e0e1a05..865ed5c33613 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c @@ -312,20 +312,22 @@ const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = { /**** Helper functions to access the device Internal Lookup Tables ****/ -void bcm43xx_ilt_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) +void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val) { - if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); + mmiowb(); bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val); } else { bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); + mmiowb(); bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val); } } -u16 bcm43xx_ilt_read16(struct bcm43xx_private *bcm, u16 offset) +u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset) { - if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); } else { @@ -333,35 +335,3 @@ u16 bcm43xx_ilt_read16(struct bcm43xx_private *bcm, u16 offset) return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1); } } - -void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val) -{ - if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (u16)(val >> 16)); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, (u16)(val & 0x0000FFFF)); - } else { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (u16)(val >> 16)); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, (u16)(val & 0x0000FFFF)); - } -} - -u32 bcm43xx_ilt_read32(struct bcm43xx_private *bcm, u16 offset) -{ - u32 ret; - - if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); - ret = bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA2); - ret <<= 16; - ret |= bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); - } else { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); - ret = bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA2); - ret <<= 16; - ret |= bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1); - } - - return ret; -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h index d92527fd83e9..464521abf73c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h @@ -26,9 +26,7 @@ extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE]; extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE]; -void bcm43xx_ilt_write16(struct bcm43xx_private *bcm, u16 offset, u16 val); -u16 bcm43xx_ilt_read16(struct bcm43xx_private *bcm, u16 offset); -void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val); -u32 bcm43xx_ilt_read32(struct bcm43xx_private *bcm, u16 offset); +void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val); +u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset); #endif /* BCM43xx_ILT_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index f3cef345c8f9..a563258cad3d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -155,6 +155,7 @@ static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val) val = swab32(val); bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset); + mmiowb(); bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val); } @@ -225,9 +226,12 @@ void bcm43xx_shm_write32(struct bcm43xx_private *bcm, if (offset & 0x0003) { /* Unaligned access */ bcm43xx_shm_control_word(bcm, routing, offset >> 2); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, (value >> 16) & 0xffff); + mmiowb(); bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value & 0xffff); return; @@ -235,6 +239,7 @@ void bcm43xx_shm_write32(struct bcm43xx_private *bcm, offset >>= 2; } bcm43xx_shm_control_word(bcm, routing, offset); + mmiowb(); bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value); } @@ -246,6 +251,7 @@ void bcm43xx_shm_write16(struct bcm43xx_private *bcm, if (offset & 0x0003) { /* Unaligned access */ bcm43xx_shm_control_word(bcm, routing, offset >> 2); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, value); return; @@ -253,6 +259,7 @@ void bcm43xx_shm_write16(struct bcm43xx_private *bcm, offset >>= 2; } bcm43xx_shm_control_word(bcm, routing, offset); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value); } @@ -311,6 +318,7 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); status |= BCM43xx_SBF_TIME_UPDATE; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + mmiowb(); /* Be careful with the in-progress timer. * First zero out the low register, so we have a full @@ -320,9 +328,10 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) u32 lo = (tsf & 0x00000000FFFFFFFFULL); u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32; - barrier(); bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0); + mmiowb(); bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi); + mmiowb(); bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo); } else { u16 v0 = (tsf & 0x000000000000FFFFULL); @@ -330,11 +339,14 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32; u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48; - barrier(); bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0); } @@ -974,6 +986,7 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; unsigned int i, max_loop; u16 value = 0; u32 buffer[5] = { @@ -984,6 +997,13 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) 0x00000000, }; +/* FIXME: It seems like a dummy_transmission corrupts the DMA engines, + * once they are initialized. So avoid doing a dummy_transmission, + * if the DMA engines are running. + */ +if (bcm->initialized) +return; + switch (phy->type) { case BCM43xx_PHYTYPE_A: max_loop = 0x1E; @@ -1015,24 +1035,28 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) bcm43xx_write16(bcm, 0x0500, 0x0000); bcm43xx_write16(bcm, 0x0502, 0x0030); + if (radio->version == 0x2050 && radio->revision <= 0x5) + bcm43xx_radio_write16(bcm, 0x0051, 0x0017); for (i = 0x00; i < max_loop; i++) { value = bcm43xx_read16(bcm, 0x050E); - if ((value & 0x0080) != 0) + if (value & 0x0080) break; udelay(10); } for (i = 0x00; i < 0x0A; i++) { value = bcm43xx_read16(bcm, 0x050E); - if ((value & 0x0400) != 0) + if (value & 0x0400) break; udelay(10); } for (i = 0x00; i < 0x0A; i++) { value = bcm43xx_read16(bcm, 0x0690); - if ((value & 0x0100) == 0) + if (!(value & 0x0100)) break; udelay(10); } + if (radio->version == 0x2050 && radio->revision <= 0x5) + bcm43xx_radio_write16(bcm, 0x0051, 0x0037); } static void key_write(struct bcm43xx_private *bcm, @@ -1646,22 +1670,6 @@ static void handle_irq_beacon(struct bcm43xx_private *bcm) } } -/* Debug helper for irq bottom-half to print all reason registers. */ -#define bcmirq_print_reasons(description) \ - do { \ - dprintkl(KERN_ERR PFX description "\n" \ - KERN_ERR PFX " Generic Reason: 0x%08x\n" \ - KERN_ERR PFX " DMA reasons: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n" \ - KERN_ERR PFX " DMA TX status: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", \ - reason, \ - dma_reason[0], dma_reason[1], \ - dma_reason[2], dma_reason[3], \ - bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_BASE + BCM43xx_DMA_TX_STATUS), \ - bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_BASE + BCM43xx_DMA_TX_STATUS), \ - bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_BASE + BCM43xx_DMA_TX_STATUS), \ - bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_BASE + BCM43xx_DMA_TX_STATUS)); \ - } while (0) - /* Interrupt handler bottom-half */ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) { @@ -1690,9 +1698,30 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) * on DMA or PIO queues. * Maybe we get this in other error conditions, too. */ - bcmirq_print_reasons("XMIT ERROR"); + printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n"); bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR); } + if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_FATALMASK) | + (dma_reason[1] & BCM43xx_DMAIRQ_FATALMASK) | + (dma_reason[2] & BCM43xx_DMAIRQ_FATALMASK) | + (dma_reason[3] & BCM43xx_DMAIRQ_FATALMASK))) { + printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: " + "0x%08X, 0x%08X, 0x%08X, 0x%08X\n", + dma_reason[0], dma_reason[1], + dma_reason[2], dma_reason[3]); + bcm43xx_controller_restart(bcm, "DMA error"); + bcm43xx_unlock_mmio(bcm, flags); + return; + } + if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) | + (dma_reason[1] & BCM43xx_DMAIRQ_NONFATALMASK) | + (dma_reason[2] & BCM43xx_DMAIRQ_NONFATALMASK) | + (dma_reason[3] & BCM43xx_DMAIRQ_NONFATALMASK))) { + printkl(KERN_ERR PFX "DMA error: " + "0x%08X, 0x%08X, 0x%08X, 0x%08X\n", + dma_reason[0], dma_reason[1], + dma_reason[2], dma_reason[3]); + } if (reason & BCM43xx_IRQ_PS) { handle_irq_ps(bcm); @@ -1780,8 +1809,6 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) bcm43xx_unlock_mmio(bcm, flags); } -#undef bcmirq_print_reasons - static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason, u32 mask) { @@ -3875,6 +3902,7 @@ failure: void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) { 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); INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); schedule_work(&bcm->restart_work); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index d3c2fc1df375..dbbef6ccd153 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -126,6 +126,7 @@ u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset) void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val) { bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val); } @@ -255,16 +256,16 @@ static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) if (phy->rev == 1) offset = 0x4C00; - bcm43xx_ilt_write16(bcm, offset, 0x00FE); - bcm43xx_ilt_write16(bcm, offset + 1, 0x000D); - bcm43xx_ilt_write16(bcm, offset + 2, 0x0013); - bcm43xx_ilt_write16(bcm, offset + 3, 0x0019); + bcm43xx_ilt_write(bcm, offset, 0x00FE); + bcm43xx_ilt_write(bcm, offset + 1, 0x000D); + bcm43xx_ilt_write(bcm, offset + 2, 0x0013); + bcm43xx_ilt_write(bcm, offset + 3, 0x0019); if (phy->rev == 1) { - bcm43xx_ilt_write16(bcm, 0x1800, 0x2710); - bcm43xx_ilt_write16(bcm, 0x1801, 0x9B83); - bcm43xx_ilt_write16(bcm, 0x1802, 0x9B83); - bcm43xx_ilt_write16(bcm, 0x1803, 0x0F8D); + bcm43xx_ilt_write(bcm, 0x1800, 0x2710); + bcm43xx_ilt_write(bcm, 0x1801, 0x9B83); + bcm43xx_ilt_write(bcm, 0x1802, 0x9B83); + bcm43xx_ilt_write(bcm, 0x1803, 0x0F8D); bcm43xx_phy_write(bcm, 0x0455, 0x0004); } @@ -317,10 +318,10 @@ static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x048D, 0x0002); } - bcm43xx_ilt_write16(bcm, offset + 0x0800, 0); - bcm43xx_ilt_write16(bcm, offset + 0x0801, 7); - bcm43xx_ilt_write16(bcm, offset + 0x0802, 16); - bcm43xx_ilt_write16(bcm, offset + 0x0803, 28); + bcm43xx_ilt_write(bcm, offset + 0x0800, 0); + bcm43xx_ilt_write(bcm, offset + 0x0801, 7); + bcm43xx_ilt_write(bcm, offset + 0x0802, 16); + bcm43xx_ilt_write(bcm, offset + 0x0803, 28); } static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) @@ -337,11 +338,11 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0427, 0x001A); for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]); + bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]); for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]); + bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]); for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); + bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); } else { /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */ bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654); @@ -357,36 +358,36 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800); for (i = 0; i < 64; i++) - bcm43xx_ilt_write16(bcm, 0x4000 + i, i); + bcm43xx_ilt_write(bcm, 0x4000 + i, i); for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]); + bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]); } if (phy->rev <= 2) for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]); + bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]); else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200)) for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]); + bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]); else for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]); + bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]); if (phy->rev == 2) for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); + bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); else if ((phy->rev > 2) && (phy->rev <= 7)) for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]); + bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]); if (phy->rev == 1) { for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); + bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); for (i = 0; i < 4; i++) { - bcm43xx_ilt_write16(bcm, 0x5404 + i, 0x0020); - bcm43xx_ilt_write16(bcm, 0x5408 + i, 0x0020); - bcm43xx_ilt_write16(bcm, 0x540C + i, 0x0020); - bcm43xx_ilt_write16(bcm, 0x5410 + i, 0x0020); + bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020); + bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020); + bcm43xx_ilt_write(bcm, 0x540C + i, 0x0020); + bcm43xx_ilt_write(bcm, 0x5410 + i, 0x0020); } bcm43xx_phy_agcsetup(bcm); @@ -395,24 +396,24 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) (bcm->board_revision == 0x0017)) return; - bcm43xx_ilt_write16(bcm, 0x5001, 0x0002); - bcm43xx_ilt_write16(bcm, 0x5002, 0x0001); + bcm43xx_ilt_write(bcm, 0x5001, 0x0002); + bcm43xx_ilt_write(bcm, 0x5002, 0x0001); } else { for (i = 0; i <= 0x2F; i++) - bcm43xx_ilt_write16(bcm, 0x1000 + i, 0x0820); + bcm43xx_ilt_write(bcm, 0x1000 + i, 0x0820); bcm43xx_phy_agcsetup(bcm); bcm43xx_phy_read(bcm, 0x0400); /* dummy read */ bcm43xx_phy_write(bcm, 0x0403, 0x1000); - bcm43xx_ilt_write16(bcm, 0x3C02, 0x000F); - bcm43xx_ilt_write16(bcm, 0x3C03, 0x0014); + bcm43xx_ilt_write(bcm, 0x3C02, 0x000F); + bcm43xx_ilt_write(bcm, 0x3C03, 0x0014); if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && (bcm->board_type == 0x0416) && (bcm->board_revision == 0x0017)) return; - bcm43xx_ilt_write16(bcm, 0x0401, 0x0002); - bcm43xx_ilt_write16(bcm, 0x0402, 0x0001); + bcm43xx_ilt_write(bcm, 0x0401, 0x0002); + bcm43xx_ilt_write(bcm, 0x0402, 0x0001); } } @@ -456,11 +457,11 @@ static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0035, 0x03FF); bcm43xx_phy_write(bcm, 0x0036, 0x0400); - bcm43xx_ilt_write16(bcm, 0x3807, 0x0051); + bcm43xx_ilt_write(bcm, 0x3807, 0x0051); bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); - bcm43xx_ilt_write16(bcm, 0x3C0C, 0x07BF); + bcm43xx_ilt_write(bcm, 0x3C0C, 0x07BF); bcm43xx_radio_write16(bcm, 0x0002, 0x07BF); bcm43xx_phy_write(bcm, 0x0024, 0x4680); @@ -472,47 +473,47 @@ static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF); bcm43xx_phy_write(bcm, 0x008E, 0x58C1); - bcm43xx_ilt_write16(bcm, 0x0803, 0x000F); - bcm43xx_ilt_write16(bcm, 0x0804, 0x001F); - bcm43xx_ilt_write16(bcm, 0x0805, 0x002A); - bcm43xx_ilt_write16(bcm, 0x0805, 0x0030); - bcm43xx_ilt_write16(bcm, 0x0807, 0x003A); + bcm43xx_ilt_write(bcm, 0x0803, 0x000F); + bcm43xx_ilt_write(bcm, 0x0804, 0x001F); + bcm43xx_ilt_write(bcm, 0x0805, 0x002A); + bcm43xx_ilt_write(bcm, 0x0805, 0x0030); + bcm43xx_ilt_write(bcm, 0x0807, 0x003A); - bcm43xx_ilt_write16(bcm, 0x0000, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0001, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0002, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0003, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0004, 0x0015); - bcm43xx_ilt_write16(bcm, 0x0005, 0x0015); - bcm43xx_ilt_write16(bcm, 0x0006, 0x0019); + bcm43xx_ilt_write(bcm, 0x0000, 0x0013); + bcm43xx_ilt_write(bcm, 0x0001, 0x0013); + bcm43xx_ilt_write(bcm, 0x0002, 0x0013); + bcm43xx_ilt_write(bcm, 0x0003, 0x0013); + bcm43xx_ilt_write(bcm, 0x0004, 0x0015); + bcm43xx_ilt_write(bcm, 0x0005, 0x0015); + bcm43xx_ilt_write(bcm, 0x0006, 0x0019); - bcm43xx_ilt_write16(bcm, 0x0404, 0x0003); - bcm43xx_ilt_write16(bcm, 0x0405, 0x0003); - bcm43xx_ilt_write16(bcm, 0x0406, 0x0007); + bcm43xx_ilt_write(bcm, 0x0404, 0x0003); + bcm43xx_ilt_write(bcm, 0x0405, 0x0003); + bcm43xx_ilt_write(bcm, 0x0406, 0x0007); for (i = 0; i < 16; i++) - bcm43xx_ilt_write16(bcm, 0x4000 + i, (0x8 + i) & 0x000F); + bcm43xx_ilt_write(bcm, 0x4000 + i, (0x8 + i) & 0x000F); - bcm43xx_ilt_write16(bcm, 0x3003, 0x1044); - bcm43xx_ilt_write16(bcm, 0x3004, 0x7201); - bcm43xx_ilt_write16(bcm, 0x3006, 0x0040); - bcm43xx_ilt_write16(bcm, 0x3001, (bcm43xx_ilt_read16(bcm, 0x3001) & 0x0010) | 0x0008); + bcm43xx_ilt_write(bcm, 0x3003, 0x1044); + bcm43xx_ilt_write(bcm, 0x3004, 0x7201); + bcm43xx_ilt_write(bcm, 0x3006, 0x0040); + bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008); for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]); + bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]); for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]); + bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]); for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); + bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); bcm43xx_phy_init_noisescaletbl(bcm); for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); + bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); break; case 3: for (i = 0; i < 64; i++) - bcm43xx_ilt_write16(bcm, 0x4000 + i, i); + bcm43xx_ilt_write(bcm, 0x4000 + i, i); - bcm43xx_ilt_write16(bcm, 0x3807, 0x0051); + bcm43xx_ilt_write(bcm, 0x3807, 0x0051); bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); @@ -524,35 +525,35 @@ static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x001F, 0x1C00); bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400); - bcm43xx_ilt_write16(bcm, 0x3001, (bcm43xx_ilt_read16(bcm, 0x3001) & 0x0010) | 0x0008); + bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008); for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]); + bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]); bcm43xx_phy_init_noisescaletbl(bcm); for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); + bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); bcm43xx_phy_write(bcm, 0x0003, 0x1808); - bcm43xx_ilt_write16(bcm, 0x0803, 0x000F); - bcm43xx_ilt_write16(bcm, 0x0804, 0x001F); - bcm43xx_ilt_write16(bcm, 0x0805, 0x002A); - bcm43xx_ilt_write16(bcm, 0x0805, 0x0030); - bcm43xx_ilt_write16(bcm, 0x0807, 0x003A); - - bcm43xx_ilt_write16(bcm, 0x0000, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0001, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0002, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0003, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0004, 0x0015); - bcm43xx_ilt_write16(bcm, 0x0005, 0x0015); - bcm43xx_ilt_write16(bcm, 0x0006, 0x0019); - - bcm43xx_ilt_write16(bcm, 0x0404, 0x0003); - bcm43xx_ilt_write16(bcm, 0x0405, 0x0003); - bcm43xx_ilt_write16(bcm, 0x0406, 0x0007); - - bcm43xx_ilt_write16(bcm, 0x3C02, 0x000F); - bcm43xx_ilt_write16(bcm, 0x3C03, 0x0014); + bcm43xx_ilt_write(bcm, 0x0803, 0x000F); + bcm43xx_ilt_write(bcm, 0x0804, 0x001F); + bcm43xx_ilt_write(bcm, 0x0805, 0x002A); + bcm43xx_ilt_write(bcm, 0x0805, 0x0030); + bcm43xx_ilt_write(bcm, 0x0807, 0x003A); + + bcm43xx_ilt_write(bcm, 0x0000, 0x0013); + bcm43xx_ilt_write(bcm, 0x0001, 0x0013); + bcm43xx_ilt_write(bcm, 0x0002, 0x0013); + bcm43xx_ilt_write(bcm, 0x0003, 0x0013); + bcm43xx_ilt_write(bcm, 0x0004, 0x0015); + bcm43xx_ilt_write(bcm, 0x0005, 0x0015); + bcm43xx_ilt_write(bcm, 0x0006, 0x0019); + + bcm43xx_ilt_write(bcm, 0x0404, 0x0003); + bcm43xx_ilt_write(bcm, 0x0405, 0x0003); + bcm43xx_ilt_write(bcm, 0x0406, 0x0007); + + bcm43xx_ilt_write(bcm, 0x3C02, 0x000F); + bcm43xx_ilt_write(bcm, 0x3C03, 0x0014); break; default: assert(0); @@ -598,19 +599,19 @@ static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x0019, 0x0000); bcm43xx_radio_write16(bcm, 0x0017, 0x0020); - tval = bcm43xx_ilt_read16(bcm, 0x3001); + tval = bcm43xx_ilt_read(bcm, 0x3001); if (phy->rev == 1) { - bcm43xx_ilt_write16(bcm, 0x3001, - (bcm43xx_ilt_read16(bcm, 0x3001) & 0xFF87) - | 0x0058); + bcm43xx_ilt_write(bcm, 0x3001, + (bcm43xx_ilt_read(bcm, 0x3001) & 0xFF87) + | 0x0058); } else { - bcm43xx_ilt_write16(bcm, 0x3001, - (bcm43xx_ilt_read16(bcm, 0x3001) & 0xFFC3) - | 0x002C); + bcm43xx_ilt_write(bcm, 0x3001, + (bcm43xx_ilt_read(bcm, 0x3001) & 0xFFC3) + | 0x002C); } bcm43xx_dummy_transmission(bcm); phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL); - bcm43xx_ilt_write16(bcm, 0x3001, tval); + bcm43xx_ilt_write(bcm, 0x3001, tval); bcm43xx_radio_set_txpower_a(bcm, 0x0018); } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 3901aa994666..4d3b0e85876c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -97,6 +97,7 @@ void bcm43xx_radio_lock(struct bcm43xx_private *bcm) status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); status |= BCM43xx_SBF_RADIOREG_LOCK; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + mmiowb(); udelay(10); } @@ -108,6 +109,7 @@ void bcm43xx_radio_unlock(struct bcm43xx_private *bcm) status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); status &= ~BCM43xx_SBF_RADIOREG_LOCK; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + mmiowb(); } u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset) @@ -142,6 +144,7 @@ u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset) void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) { bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val); } @@ -161,10 +164,10 @@ static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm, } for (i = 0; i < 4; i++) - bcm43xx_ilt_write16(bcm, offset + i, first); + bcm43xx_ilt_write(bcm, offset + i, first); for (i = start; i < end; i++) - bcm43xx_ilt_write16(bcm, offset + i, second); + bcm43xx_ilt_write(bcm, offset + i, second); if (third != -1) { tmp = ((u16)third << 14) | ((u16)third << 6); @@ -196,11 +199,11 @@ static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm) tmp |= (i & 0x0001) << 1; tmp |= (i & 0x0002) >> 1; - bcm43xx_ilt_write16(bcm, offset + i, tmp); + bcm43xx_ilt_write(bcm, offset + i, tmp); } for (i = start; i < end; i++) - bcm43xx_ilt_write16(bcm, offset + i, i - start); + bcm43xx_ilt_write(bcm, offset + i, i - start); bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040); @@ -316,6 +319,7 @@ u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm) void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val) { bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset); + mmiowb(); bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val); } @@ -612,10 +616,6 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) } break; case BCM43xx_PHYTYPE_G: -//FIXME: Something is broken here. This is called when enabling WLAN interfmode. -// If this is done at runtime, I get an XMIT ERROR and transmission is -// broken. I guess some important register is overwritten by accident. -// The XMIT ERROR comes from the dummy_transmissions in set_gains. if (radio->revision >= 9) return; if (radio->revision == 8) @@ -1641,14 +1641,14 @@ void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) base &= 0x000F; bcm43xx_phy_write(bcm, 0x0017, base | 0x0020); - ilt = bcm43xx_ilt_read16(bcm, 0x3001); + ilt = bcm43xx_ilt_read(bcm, 0x3001); ilt &= 0x0007; dac = bcm43xx_get_txgain_dac(txpower); dac <<= 3; dac |= ilt; - bcm43xx_ilt_write16(bcm, 0x3001, dac); + bcm43xx_ilt_write(bcm, 0x3001, dac); bcm->current_core->radio->txpower[0] = txpower; -- cgit v1.2.3-59-g8ed1b From e1b1b581b847a5ae9409a02a586476eaba2b3f89 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 13 Mar 2006 15:20:05 +0100 Subject: [PATCH] bcm43xx: receive TX status on MMIO or DMA unconditionally regarding the 80211 core rev. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index a563258cad3d..3ab02f4f8ec0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1765,22 +1765,17 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) /* We intentionally don't set "activity" to 1, here. */ } if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { - if (likely(bcm->current_core->rev < 5)) { - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_rx(bcm->current_core->pio->queue3); - else - bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1); - activity = 1; - } else - assert(0); + if (bcm43xx_using_pio(bcm)) + bcm43xx_pio_rx(bcm->current_core->pio->queue3); + else + bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1); + activity = 1; } bcmirq_handled(BCM43xx_IRQ_RX); if (reason & BCM43xx_IRQ_XMIT_STATUS) { - if (bcm->current_core->rev >= 5) { - handle_irq_transmit_status(bcm); - activity = 1; - } + handle_irq_transmit_status(bcm); + activity = 1; //TODO: In AP mode, this also causes sending of powersave responses. bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS); } -- cgit v1.2.3-59-g8ed1b From aae3778176ec7a57b1c4f539b7252acfd7d99a1b Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 13 Mar 2006 15:54:56 +0100 Subject: [PATCH] bcm43xx: add functions bcm43xx_dma_read/write, bcm43xx_dma_tx_suspend/resume. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 61 ++++++++++++++++-------------- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 18 +++++++++ 2 files changed, 51 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 0cd292847954..fbe19b922aa7 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -374,13 +374,11 @@ static int dmacontroller_setup(struct bcm43xx_dmaring *ring) if (ring->tx) { /* Set Transmit Control register to "transmit enable" */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_TX_CONTROL, - BCM43xx_DMA_TXCTRL_ENABLE); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, + BCM43xx_DMA_TXCTRL_ENABLE); /* Set Transmit Descriptor ring address. */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_TX_DESC_RING, - ring->dmabase + ring->memoffset); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, + ring->dmabase + ring->memoffset); } else { err = alloc_initial_descbuffers(ring); if (err) @@ -388,17 +386,12 @@ static int dmacontroller_setup(struct bcm43xx_dmaring *ring) /* Set Receive Control "receive enable" and frame offset */ value = (ring->frameoffset << BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT); value |= BCM43xx_DMA_RXCTRL_ENABLE; - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_RX_CONTROL, - value); + bcm43xx_dma_write(ring, BCM43xx_DMA_RX_CONTROL, value); /* Set Receive Descriptor ring address. */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_RX_DESC_RING, - ring->dmabase + ring->memoffset); + bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, + ring->dmabase + ring->memoffset); /* Init the descriptor pointer. */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_RX_DESC_INDEX, - 200); + bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, 200); } out: @@ -411,15 +404,11 @@ static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring) if (ring->tx) { bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base); /* Zero out Transmit Descriptor ring address. */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_TX_DESC_RING, - 0x00000000); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, 0); } else { bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base); /* Zero out Receive Descriptor ring address. */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_RX_DESC_RING, - 0x00000000); + bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, 0); } } @@ -698,9 +687,8 @@ static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, */ wmb(); slot = next_slot(ring, slot); - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_TX_DESC_INDEX, - (u32)(slot * sizeof(struct bcm43xx_dmadesc))); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_INDEX, + (u32)(slot * sizeof(struct bcm43xx_dmadesc))); } static int dma_tx_fragment(struct bcm43xx_dmaring *ring, @@ -940,7 +928,7 @@ void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) #endif assert(!ring->tx); - status = bcm43xx_read32(ring->bcm, ring->mmio_base + BCM43xx_DMA_RX_STATUS); + status = bcm43xx_dma_read(ring, BCM43xx_DMA_RX_STATUS); descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK); current_slot = descptr / sizeof(struct bcm43xx_dmadesc); assert(current_slot >= 0 && current_slot < ring->nr_slots); @@ -953,10 +941,27 @@ void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) ring->max_used_slots = used_slots; #endif } - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_RX_DESC_INDEX, - (u32)(slot * sizeof(struct bcm43xx_dmadesc))); + bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, + (u32)(slot * sizeof(struct bcm43xx_dmadesc))); ring->current_slot = slot; } +void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) +{ + assert(ring->tx); + bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, + bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL) + | BCM43xx_DMA_TXCTRL_SUSPEND); +} + +void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) +{ + assert(ring->tx); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, + bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL) + & ~BCM43xx_DMA_TXCTRL_SUSPEND); + bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1); +} + /* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index c07e34689be1..2d520e4b0276 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -140,6 +140,21 @@ struct bcm43xx_dmaring { }; +static inline +u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring, + u16 offset) +{ + return bcm43xx_read32(ring->bcm, ring->mmio_base + offset); +} + +static inline +void bcm43xx_dma_write(struct bcm43xx_dmaring *ring, + u16 offset, u32 value) +{ + bcm43xx_write32(ring->bcm, ring->mmio_base + offset, value); +} + + int bcm43xx_dma_init(struct bcm43xx_private *bcm); void bcm43xx_dma_free(struct bcm43xx_private *bcm); @@ -148,6 +163,9 @@ int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, u16 dmacontroller_mmio_base); +void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring); +void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring); + void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, struct bcm43xx_xmitstatus *status); -- cgit v1.2.3-59-g8ed1b From e9357c056c5e62516f0044e60591d41f00ca7cfa Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 13 Mar 2006 19:27:34 +0100 Subject: [PATCH] bcm43xx: reduce the size of bcm43xx_private by removing unneeded members. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 94 ++++++---- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 7 +- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 9 +- drivers/net/wireless/bcm43xx/bcm43xx_ilt.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 238 ++++++++++++------------- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 6 +- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 128 ++++++------- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 8 +- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 72 ++++---- drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 35 ++-- drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 14 +- 13 files changed, 320 insertions(+), 301 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 29c95b07122a..a358646ad3eb 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -556,33 +556,37 @@ struct bcm43xx_pio { #define BCM43xx_MAX_80211_CORES 2 -#define BCM43xx_COREFLAG_AVAILABLE (1 << 0) -#define BCM43xx_COREFLAG_ENABLED (1 << 1) -#define BCM43xx_COREFLAG_INITIALIZED (1 << 2) - #ifdef CONFIG_BCM947XX #define core_offset(bcm) (bcm)->current_core_offset #else #define core_offset(bcm) 0 #endif +/* Generic information about a core. */ struct bcm43xx_coreinfo { - /** Driver internal flags. See BCM43xx_COREFLAG_* */ - u32 flags; + u8 available:1, + enabled:1, + initialized:1; /** core_id ID number */ u16 id; /** core_rev revision number */ u8 rev; /** Index number for _switch_core() */ u8 index; - /* Pointer to the PHYinfo, which belongs to this core (if 80211 core) */ - struct bcm43xx_phyinfo *phy; - /* Pointer to the RadioInfo, which belongs to this core (if 80211 core) */ - struct bcm43xx_radioinfo *radio; - /* Pointer to the DMA rings, which belong to this core (if 80211 core) */ - struct bcm43xx_dma *dma; - /* Pointer to the PIO queues, which belong to this core (if 80211 core) */ - struct bcm43xx_pio *pio; +}; + +/* Additional information for each 80211 core. */ +struct bcm43xx_coreinfo_80211 { + /* PHY device. */ + struct bcm43xx_phyinfo phy; + /* Radio device. */ + struct bcm43xx_radioinfo radio; + union { + /* DMA context. */ + struct bcm43xx_dma dma; + /* PIO context. */ + struct bcm43xx_pio pio; + }; }; /* Context information for a noise calculation (Link Quality). */ @@ -652,7 +656,7 @@ struct bcm43xx_private { #define BCM43xx_NR_LEDS 4 struct bcm43xx_led leds[BCM43xx_NR_LEDS]; - /* The currently active core. NULL if not initialized, yet. */ + /* The currently active core. */ struct bcm43xx_coreinfo *current_core; #ifdef CONFIG_BCM947XX /** current core memory offset */ @@ -665,18 +669,15 @@ struct bcm43xx_private { */ struct bcm43xx_coreinfo core_chipcommon; struct bcm43xx_coreinfo core_pci; - struct bcm43xx_coreinfo core_v90; - struct bcm43xx_coreinfo core_pcmcia; - struct bcm43xx_coreinfo core_ethernet; struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ]; - /* Info about the PHY for each 80211 core. */ - struct bcm43xx_phyinfo phy[ BCM43xx_MAX_80211_CORES ]; - /* Info about the Radio for each 80211 core. */ - struct bcm43xx_radioinfo radio[ BCM43xx_MAX_80211_CORES ]; - /* DMA */ - struct bcm43xx_dma dma[ BCM43xx_MAX_80211_CORES ]; - /* PIO */ - struct bcm43xx_pio pio[ BCM43xx_MAX_80211_CORES ]; + /* Additional information, specific to the 80211 cores. */ + struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ]; + /* Index of the current 80211 core. If current_core is not + * an 80211 core, this is -1. + */ + int current_80211_core_idx; + /* Number of available 80211 cores. */ + int nr_80211_available; u32 chipcommon_capabilities; @@ -769,18 +770,39 @@ int bcm43xx_using_pio(struct bcm43xx_private *bcm) # error "Using neither DMA nor PIO? Confused..." #endif - +/* Helper functions to access data structures private to the 80211 cores. + * Note that we _must_ have an 80211 core mapped when calling + * any of these functions. + */ static inline -int bcm43xx_num_80211_cores(struct bcm43xx_private *bcm) +struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm) { - int i, cnt = 0; - - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - if (bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE) - cnt++; - } - - return cnt; + assert(bcm43xx_using_pio(bcm)); + assert(bcm->current_80211_core_idx >= 0); + assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); + return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio); +} +static inline +struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm) +{ + assert(!bcm43xx_using_pio(bcm)); + assert(bcm->current_80211_core_idx >= 0); + assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); + return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma); +} +static inline +struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm) +{ + assert(bcm->current_80211_core_idx >= 0); + assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); + return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy); +} +static inline +struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm) +{ + assert(bcm->current_80211_core_idx >= 0); + assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); + return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio); } /* Are we running in init_board() context? */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index bcfcebe28261..f73d36b8e0f4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -104,16 +104,13 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, fappend("\nCores:\n"); #define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, " \ "rev: 0x%02x, index: 0x%02x\n", \ - (info).flags & BCM43xx_COREFLAG_AVAILABLE \ + (info).available \ ? "available" : "nonavailable", \ - (info).flags & BCM43xx_COREFLAG_ENABLED \ + (info).enabled \ ? "enabled" : "disabled", \ (info).id, (info).rev, (info).index) fappend_core("CHIPCOMMON", bcm->core_chipcommon); fappend_core("PCI", bcm->core_pci); - fappend_core("V90", bcm->core_v90); - fappend_core("PCMCIA", bcm->core_pcmcia); - fappend_core("ETHERNET", bcm->core_ethernet); fappend_core("first 80211", bcm->core_80211[0]); fappend_core("second 80211", bcm->core_80211[1]); #undef fappend_core diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index fbe19b922aa7..7ed368a587f3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -531,7 +531,7 @@ static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring) void bcm43xx_dma_free(struct bcm43xx_private *bcm) { - struct bcm43xx_dma *dma = bcm->current_core->dma; + struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); bcm43xx_destroy_dmaring(dma->rx_ring1); dma->rx_ring1 = NULL; @@ -549,7 +549,7 @@ void bcm43xx_dma_free(struct bcm43xx_private *bcm) int bcm43xx_dma_init(struct bcm43xx_private *bcm) { - struct bcm43xx_dma *dma = bcm->current_core->dma; + struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); struct bcm43xx_dmaring *ring; int err = -ENOMEM; @@ -652,7 +652,7 @@ static struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, u16 cookie, int *slot) { - struct bcm43xx_dma *dma = bcm->current_core->dma; + struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); struct bcm43xx_dmaring *ring = NULL; switch (cookie & 0xF000) { @@ -755,7 +755,7 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, * the device to send the stuff. * Note that this is called from atomic context. */ - struct bcm43xx_dmaring *ring = bcm->current_core->dma->tx_ring1; + struct bcm43xx_dmaring *ring = bcm43xx_current_dma(bcm)->tx_ring1; u8 i; struct sk_buff *skb; @@ -784,6 +784,7 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, struct bcm43xx_xmitstatus *status) { + struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); struct bcm43xx_dmaring *ring; struct bcm43xx_dmadesc *desc; struct bcm43xx_dmadesc_meta *meta; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c index 865ed5c33613..ad8e569d1faf 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c @@ -314,7 +314,7 @@ const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = { void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); mmiowb(); bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val); @@ -327,7 +327,7 @@ void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val) u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); } else { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 949555da5aa9..72a243aac6cb 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -171,8 +171,8 @@ void bcm43xx_leds_exit(struct bcm43xx_private *bcm) void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) { struct bcm43xx_led *led; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES; int i, turn_on; unsigned long interval = 0; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 3ab02f4f8ec0..88e9a125c2d7 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -406,7 +406,7 @@ static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm) static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) { /* slot_time is in usec. */ - if (bcm->current_core->phy->type != BCM43xx_PHYTYPE_G) + if (bcm43xx_current_phy(bcm)->type != BCM43xx_PHYTYPE_G) return; bcm43xx_write16(bcm, 0x684, 510 + slot_time); bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time); @@ -443,7 +443,7 @@ static void bcm43xx_disassociate(struct bcm43xx_private *bcm) bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff); - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G && ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate)) bcm43xx_short_slot_timing_enable(bcm); @@ -510,8 +510,8 @@ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *old static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u32 radio_id; u16 manufact; u16 version; @@ -566,10 +566,10 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) radio->txpower[2] = 3; else radio->txpower[2] = 0; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (phy->type == BCM43xx_PHYTYPE_A) radio->txpower_desired = bcm->sprom.maxpower_aphy; else - bcm->current_core->radio->txpower_desired = bcm->sprom.maxpower_bgphy; + radio->txpower_desired = bcm->sprom.maxpower_bgphy; /* Initialize the in-memory nrssi Lookup Table. */ for (i = 0; i < 64; i++) @@ -929,15 +929,14 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) struct ieee80211_geo geo; struct ieee80211_channel *chan; int have_a = 0, have_bg = 0; - int i, num80211; + int i; u8 channel; struct bcm43xx_phyinfo *phy; const char *iso_country; memset(&geo, 0, sizeof(geo)); - num80211 = bcm43xx_num_80211_cores(bcm); - for (i = 0; i < num80211; i++) { - phy = bcm->phy + i; + for (i = 0; i < bcm->nr_80211_available; i++) { + phy = &(bcm->core_80211_ext[i].phy); switch (phy->type) { case BCM43xx_PHYTYPE_B: case BCM43xx_PHYTYPE_G: @@ -985,8 +984,8 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) */ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); unsigned int i, max_loop; u16 value = 0; u32 buffer[5] = { @@ -1213,14 +1212,20 @@ int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *ne if (unlikely(!new_core)) return 0; - if (!(new_core->flags & BCM43xx_COREFLAG_AVAILABLE)) + if (!new_core->available) return -ENODEV; if (bcm->current_core == new_core) return 0; err = _switch_core(bcm, new_core->index); - if (likely(!err)) - bcm->current_core = new_core; + if (unlikely(err)) + goto out; + bcm->current_core = new_core; + bcm->current_80211_core_idx = -1; + if (new_core->id == BCM43xx_COREID_80211) + bcm->current_80211_core_idx = (int)(new_core - &(bcm->core_80211[0])); + +out: return err; } @@ -1295,7 +1300,8 @@ static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags) bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); out: - bcm->current_core->flags &= ~ BCM43xx_COREFLAG_ENABLED; + bcm->current_core->enabled = 0; + return 0; } @@ -1340,7 +1346,7 @@ static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags) bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); udelay(1); - bcm->current_core->flags |= BCM43xx_COREFLAG_ENABLED; + bcm->current_core->enabled = 1; assert(err == 0); out: return err; @@ -1411,7 +1417,7 @@ static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm, bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); udelay(1); - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G) { old_core = bcm->current_core; err = bcm43xx_switch_core(bcm, active_80211_core); if (err) @@ -1433,9 +1439,6 @@ static void handle_irq_transmit_status(struct bcm43xx_private *bcm) u16 tmp; struct bcm43xx_xmitstatus stat; - assert(bcm->current_core->id == BCM43xx_COREID_80211); - assert(bcm->current_core->rev >= 5); - while (1) { v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0); if (!v0) @@ -1473,7 +1476,7 @@ static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4)); assert(bcm->noisecalc.core_at_start == bcm->current_core); - assert(bcm->noisecalc.channel_at_start == bcm->current_core->radio->channel); + assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel); } static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) @@ -1483,7 +1486,7 @@ static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) if (bcm->noisecalc.calculation_running) return; bcm->noisecalc.core_at_start = bcm->current_core; - bcm->noisecalc.channel_at_start = bcm->current_core->radio->channel; + bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel; bcm->noisecalc.calculation_running = 1; bcm->noisecalc.nr_samples = 0; @@ -1492,7 +1495,7 @@ static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) static void handle_irq_noise(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 tmp; u8 noise[4]; u8 i, j; @@ -1759,16 +1762,16 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_rx(bcm->current_core->pio->queue0); + bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0); else - bcm43xx_dma_rx(bcm->current_core->dma->rx_ring0); + bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0); /* We intentionally don't set "activity" to 1, here. */ } if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_rx(bcm->current_core->pio->queue3); + bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3); else - bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1); + bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring1); activity = 1; } bcmirq_handled(BCM43xx_IRQ_RX); @@ -1911,7 +1914,7 @@ static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u8 rev = bcm->current_core->rev; int err = 0; int nr; @@ -2349,6 +2352,8 @@ static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm) */ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); int err; int iw_mode = bcm->ieee->iw_mode; int tmp; @@ -2388,13 +2393,13 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) goto err_radio_off; /* Select initial Interference Mitigation. */ - tmp = bcm->current_core->radio->interfmode; - bcm->current_core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; + tmp = radio->interfmode; + radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; bcm43xx_radio_set_interference_mitigation(bcm, tmp); bcm43xx_phy_set_antenna_diversity(bcm); bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT); - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) { + if (phy->type == BCM43xx_PHYTYPE_B) { value16 = bcm43xx_read16(bcm, 0x005E); value16 |= 0x0004; bcm43xx_write16(bcm, 0x005E, value16); @@ -2512,6 +2517,32 @@ error: return -ENODEV; } +void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy) +{ + /* Initialize a "phyinfo" structure. The structure is already + * zeroed out. + */ + phy->antenna_diversity = 0xFFFF; + phy->savedpctlreg = 0xFFFF; + phy->minlowsig[0] = 0xFFFF; + phy->minlowsig[1] = 0xFFFF; + spin_lock_init(&phy->lock); +} + +void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio) +{ + /* Initialize a "radioinfo" structure. The structure is already + * zeroed out. + */ + radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; + radio->channel = 0xFF; + radio->initial_channel = 0xFF; + radio->lofcal = 0xFFFF; + radio->initval = 0xFFFF; + radio->nrssi[0] = -1000; + radio->nrssi[1] = -1000; +} + static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) { int err, i; @@ -2523,15 +2554,14 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo)); memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo)); - memset(&bcm->core_v90, 0, sizeof(struct bcm43xx_coreinfo)); - memset(&bcm->core_pcmcia, 0, sizeof(struct bcm43xx_coreinfo)); memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo) * BCM43xx_MAX_80211_CORES); - - memset(&bcm->phy, 0, sizeof(struct bcm43xx_phyinfo) - * BCM43xx_MAX_80211_CORES); - memset(&bcm->radio, 0, sizeof(struct bcm43xx_radioinfo) - * BCM43xx_MAX_80211_CORES); + memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211) + * BCM43xx_MAX_80211_CORES); + bcm->current_80211_core_idx = -1; + bcm->nr_80211_available = 0; + bcm->current_core = NULL; + bcm->active_80211_core = NULL; /* map core 0 */ err = _switch_core(bcm, 0); @@ -2549,7 +2579,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) if (core_id == BCM43xx_COREID_CHIPCOMMON) { chip_id_32 = bcm43xx_read32(bcm, 0); chip_id_16 = chip_id_32 & 0xFFFF; - bcm->core_chipcommon.flags |= BCM43xx_COREFLAG_AVAILABLE; + bcm->core_chipcommon.available = 1; bcm->core_chipcommon.id = core_id; bcm->core_chipcommon.rev = core_rev; bcm->core_chipcommon.index = 0; @@ -2618,18 +2648,19 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n", bcm->chip_id, bcm->chip_rev); dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count); - if (bcm->core_chipcommon.flags & BCM43xx_COREFLAG_AVAILABLE) { + if (bcm->core_chipcommon.available) { dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n", core_id, core_rev, core_vendor, bcm43xx_core_enabled(bcm) ? "enabled" : "disabled"); } - if (bcm->core_chipcommon.flags & BCM43xx_COREFLAG_AVAILABLE) + if (bcm->core_chipcommon.available) current_core = 1; else current_core = 0; for ( ; current_core < core_count; current_core++) { struct bcm43xx_coreinfo *core; + struct bcm43xx_coreinfo_80211 *ext_80211; err = _switch_core(bcm, current_core); if (err) @@ -2651,36 +2682,16 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) switch (core_id) { case BCM43xx_COREID_PCI: core = &bcm->core_pci; - if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { + if (core->available) { printk(KERN_WARNING PFX "Multiple PCI cores found.\n"); continue; } break; - case BCM43xx_COREID_V90: - core = &bcm->core_v90; - if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { - printk(KERN_WARNING PFX "Multiple V90 cores found.\n"); - continue; - } - break; - case BCM43xx_COREID_PCMCIA: - core = &bcm->core_pcmcia; - if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { - printk(KERN_WARNING PFX "Multiple PCMCIA cores found.\n"); - continue; - } - break; - case BCM43xx_COREID_ETHERNET: - core = &bcm->core_ethernet; - if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { - printk(KERN_WARNING PFX "Multiple Ethernet cores found.\n"); - continue; - } - break; case BCM43xx_COREID_80211: for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { core = &(bcm->core_80211[i]); - if (!(core->flags & BCM43xx_COREFLAG_AVAILABLE)) + ext_80211 = &(bcm->core_80211_ext[i]); + if (!core->available) break; core = NULL; } @@ -2715,40 +2726,23 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) err = -ENODEV; goto out; } - core->phy = &bcm->phy[i]; - core->phy->antenna_diversity = 0xffff; - core->phy->savedpctlreg = 0xFFFF; - core->phy->minlowsig[0] = 0xFFFF; - core->phy->minlowsig[1] = 0xFFFF; - core->phy->minlowsigpos[0] = 0; - core->phy->minlowsigpos[1] = 0; - spin_lock_init(&core->phy->lock); - core->radio = &bcm->radio[i]; - core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; - core->radio->channel = 0xFF; - core->radio->initial_channel = 0xFF; - core->radio->lofcal = 0xFFFF; - core->radio->initval = 0xFFFF; - core->radio->nrssi[0] = -1000; - core->radio->nrssi[1] = -1000; - core->dma = &bcm->dma[i]; - core->pio = &bcm->pio[i]; + bcm->nr_80211_available++; + bcm43xx_init_struct_phyinfo(&ext_80211->phy); + bcm43xx_init_struct_radioinfo(&ext_80211->radio); break; case BCM43xx_COREID_CHIPCOMMON: printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n"); break; - default: - printk(KERN_WARNING PFX "Unknown core found (ID 0x%x)\n", core_id); } if (core) { - core->flags |= BCM43xx_COREFLAG_AVAILABLE; + core->available = 1; core->id = core_id; core->rev = core_rev; core->index = current_core; } } - if (!(bcm->core_80211[0].flags & BCM43xx_COREFLAG_AVAILABLE)) { + if (!bcm->core_80211[0].available) { printk(KERN_ERR PFX "Error: No 80211 core found!\n"); err = -ENODEV; goto out; @@ -2802,7 +2796,7 @@ static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm, static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm) { - switch (bcm->current_core->phy->type) { + switch (bcm43xx_current_phy(bcm)->type) { case BCM43xx_PHYTYPE_A: case BCM43xx_PHYTYPE_G: bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1); @@ -2829,12 +2823,14 @@ static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm) bcm43xx_pio_free(bcm); bcm43xx_dma_free(bcm); - bcm->current_core->flags &= ~ BCM43xx_COREFLAG_INITIALIZED; + bcm->current_core->initialized = 0; } /* http://bcm-specs.sipsolutions.net/80211Init */ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u32 ucodeflags; int err; u32 sbimconfiglow; @@ -2867,16 +2863,15 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) /* HW decryption needs to be set now */ ucodeflags |= 0x40000000; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + if (phy->type == BCM43xx_PHYTYPE_G) { ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; - if (bcm->current_core->phy->rev == 1) + if (phy->rev == 1) ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY; if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL; - } else if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) { + } else if (phy->type == BCM43xx_PHYTYPE_B) { ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; - if ((bcm->current_core->phy->rev >= 2) && - (bcm->current_core->radio->version == 0x2050)) + if (phy->rev >= 2 && radio->version == 0x2050) ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY; } @@ -2901,7 +2896,7 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) bcm43xx_rate_memory_init(bcm); /* Minimum Contention Window */ - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) + if (phy->type == BCM43xx_PHYTYPE_B) bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f); else bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f); @@ -2927,7 +2922,7 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) bcm43xx_mac_enable(bcm); bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - bcm->current_core->flags |= BCM43xx_COREFLAG_INITIALIZED; + bcm->current_core->initialized = 1; out: return err; @@ -3048,7 +3043,7 @@ static void bcm43xx_softmac_init(struct bcm43xx_private *bcm) static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2) return; @@ -3076,8 +3071,8 @@ static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm) static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); if (phy->type == BCM43xx_PHYTYPE_G) { //TODO: update_aci_moving_average @@ -3170,9 +3165,9 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) bcm43xx_unlock(bcm, flags); for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE)) + if (!bcm->core_80211[i].available) continue; - if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_INITIALIZED)) + if (!bcm->core_80211[i].initialized) continue; err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); @@ -3190,7 +3185,6 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) static int bcm43xx_init_board(struct bcm43xx_private *bcm) { int i, err; - int num_80211_cores; int connect_phy; unsigned long flags; @@ -3212,8 +3206,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) goto err_crystal_off; tasklet_enable(&bcm->isr_tasklet); - num_80211_cores = bcm43xx_num_80211_cores(bcm); - for (i = 0; i < num_80211_cores; i++) { + for (i = 0; i < bcm->nr_80211_available; i++) { err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); assert(err != -ENODEV); if (err) @@ -3223,8 +3216,8 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) * Connect PHY only on the first core. */ if (!bcm43xx_core_enabled(bcm)) { - if (num_80211_cores == 1) { - connect_phy = bcm->current_core->phy->connected; + if (bcm->nr_80211_available == 1) { + connect_phy = bcm43xx_current_phy(bcm)->connected; } else { if (i == 0) connect_phy = 1; @@ -3248,7 +3241,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) } } bcm->active_80211_core = &bcm->core_80211[0]; - if (num_80211_cores >= 2) { + if (bcm->nr_80211_available >= 2) { bcm43xx_switch_core(bcm, &bcm->core_80211[0]); bcm43xx_mac_enable(bcm); } @@ -3260,9 +3253,9 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); - if (bcm->current_core->radio->initial_channel != 0xFF) { + if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) { bcm43xx_mac_suspend(bcm); - bcm43xx_radio_selectchannel(bcm, bcm->current_core->radio->initial_channel, 0); + bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0); bcm43xx_mac_enable(bcm); } @@ -3282,8 +3275,8 @@ out: err_80211_unwind: tasklet_disable(&bcm->isr_tasklet); /* unwind all 80211 initialization */ - for (i = 0; i < num_80211_cores; i++) { - if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_INITIALIZED)) + for (i = 0; i < bcm->nr_80211_available; i++) { + if (!bcm->core_80211[i].initialized) continue; bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); bcm43xx_wireless_core_cleanup(bcm); @@ -3307,15 +3300,15 @@ static void bcm43xx_detach_board(struct bcm43xx_private *bcm) /* Free allocated structures/fields */ for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - kfree(bcm->phy[i]._lo_pairs); - if (bcm->phy[i].dyn_tssi_tbl) - kfree(bcm->phy[i].tssi2dbm); + kfree(bcm->core_80211_ext[i].phy._lo_pairs); + if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl) + kfree(bcm->core_80211_ext[i].phy.tssi2dbm); } } static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 value; u8 phy_version; u8 phy_type; @@ -3393,7 +3386,6 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) int i; void __iomem *ioaddr; unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - int num_80211_cores; u32 coremask; err = pci_enable_device(pci_dev); @@ -3467,11 +3459,9 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) if (err) goto err_chipset_detach; - num_80211_cores = bcm43xx_num_80211_cores(bcm); - /* Attach all IO cores to the backplane. */ coremask = 0; - for (i = 0; i < num_80211_cores; i++) + for (i = 0; i < bcm->nr_80211_available; i++) coremask |= (1 << bcm->core_80211[i].index); //FIXME: Also attach some non80211 cores? err = bcm43xx_setup_backplane_pci_connection(bcm, coremask); @@ -3487,7 +3477,7 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) if (err) goto err_chipset_detach; - for (i = 0; i < num_80211_cores; i++) { + for (i = 0; i < bcm->nr_80211_available; i++) { err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); assert(err != -ENODEV); if (err) @@ -3519,7 +3509,7 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) bcm43xx_pctl_set_crystal(bcm, 0); /* Set the MAC address in the networking subsystem */ - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6); else memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6); @@ -3535,9 +3525,9 @@ out: err_80211_unwind: for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - kfree(bcm->phy[i]._lo_pairs); - if (bcm->phy[i].dyn_tssi_tbl) - kfree(bcm->phy[i].tssi2dbm); + kfree(bcm->core_80211_ext[i].phy._lo_pairs); + if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl) + kfree(bcm->core_80211_ext[i].phy.tssi2dbm); } err_chipset_detach: bcm43xx_chipset_detach(bcm); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 086136c3d01f..eca79a38594a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -80,7 +80,7 @@ static inline u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm, int freq) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) return bcm43xx_freq_to_channel_a(freq); return bcm43xx_freq_to_channel_bg(freq); } @@ -107,7 +107,7 @@ static inline int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm, u8 channel) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) return bcm43xx_channel_to_freq_a(channel); return bcm43xx_channel_to_freq_bg(channel); } @@ -129,7 +129,7 @@ static inline int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, u8 channel) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) return bcm43xx_is_valid_channel_a(channel); return bcm43xx_is_valid_channel_bg(channel); } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index dbbef6ccd153..1ce9a4599903 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -83,7 +83,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); assert(irqs_disabled()); if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) { @@ -102,7 +102,7 @@ void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); assert(irqs_disabled()); if (bcm->current_core->rev < 3) { @@ -132,7 +132,7 @@ void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val) void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); unsigned long flags; bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ @@ -158,39 +158,32 @@ void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) */ int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u32 flags; - if (bcm->current_core->rev < 5) { - if (connect) { - bcm->current_core->phy->connected = 1; - dprintk(KERN_INFO PFX "PHY connected\n"); - } else { - bcm->current_core->phy->connected = 0; - dprintk(KERN_INFO PFX "PHY disconnected\n"); - } - return 0; - } - + if (bcm->current_core->rev < 5) + goto out; + flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); if (connect) { if (!(flags & 0x00010000)) return -ENODEV; - bcm->current_core->phy->connected = 1; - flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); flags |= (0x800 << 18); bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); - dprintk(KERN_INFO PFX "PHY connected\n"); } else { if (!(flags & 0x00020000)) return -ENODEV; - bcm->current_core->phy->connected = 0; - flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); flags &= ~(0x800 << 18); bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); - dprintk(KERN_INFO PFX "PHY disconnected\n"); } +out: + phy->connected = connect; + if (connect) + dprintk(KERN_INFO PFX "PHY connected\n"); + else + dprintk(KERN_INFO PFX "PHY disconnected\n"); return 0; } @@ -200,8 +193,8 @@ int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect) */ static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0; int must_reset_txpower = 0; @@ -250,7 +243,7 @@ static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm) static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 offset = 0x0000; if (phy->rev == 1) @@ -326,7 +319,7 @@ static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 i; assert(phy->type == BCM43xx_PHYTYPE_G); @@ -420,7 +413,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) /* Initialize the noisescaletable for APHY */ static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); int i; bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400); @@ -448,10 +441,11 @@ static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm) static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 i; - assert(bcm->current_core->phy->type == BCM43xx_PHYTYPE_A); - switch (bcm->current_core->phy->rev) { + assert(phy->type == BCM43xx_PHYTYPE_A); + switch (phy->rev) { case 2: bcm43xx_phy_write(bcm, 0x008E, 0x3800); bcm43xx_phy_write(bcm, 0x0035, 0x03FF); @@ -563,7 +557,8 @@ static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) /* Initialize APHY. This is also called for the GPHY in some cases. */ static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 tval; if (phy->type == BCM43xx_PHYTYPE_A) { @@ -586,11 +581,11 @@ static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) { - if (bcm->current_core->radio->lofcal == 0xFFFF) { + if (radio->lofcal == 0xFFFF) { TODO();//TODO: LOF Cal bcm43xx_radio_set_tx_iq(bcm); } else - bcm43xx_radio_write16(bcm, 0x001E, bcm->current_core->radio->lofcal); + bcm43xx_radio_write16(bcm, 0x001E, radio->lofcal); } bcm43xx_phy_write(bcm, 0x007A, 0xF111); @@ -620,7 +615,7 @@ static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 offset, val; bcm43xx_write16(bcm, 0x03EC, 0x3F22); @@ -671,7 +666,7 @@ static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm) static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 offset, val; bcm43xx_write16(bcm, 0x03EC, 0x3F22); @@ -729,8 +724,8 @@ static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm) static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 offset; if (phy->version == 1 && @@ -835,8 +830,8 @@ static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm) static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 offset, val; bcm43xx_phy_write(bcm, 0x003E, 0x817A); @@ -946,9 +941,9 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) udelay(40); bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) | 0x0002)); bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - if ((bcm->current_core->radio->manufact == 0x17F) && - (bcm->current_core->radio->version == 0x2050) && - (bcm->current_core->radio->revision <= 2)) { + if (radio->manufact == 0x17F && + radio->version == 0x2050 && + radio->revision <= 2) { bcm43xx_radio_write16(bcm, 0x0050, 0x0020); bcm43xx_radio_write16(bcm, 0x005A, 0x0070); bcm43xx_radio_write16(bcm, 0x005B, 0x007B); @@ -1001,8 +996,8 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 tmp; if (phy->rev == 1) @@ -1096,8 +1091,8 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 regstack[12] = { 0 }; u16 mls; u16 fval; @@ -1190,7 +1185,9 @@ void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm) static inline u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) { - if (bcm->current_core->phy->connected) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + + if (phy->connected) { bcm43xx_phy_write(bcm, 0x15, 0xE300); control <<= 8; bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0); @@ -1242,7 +1239,7 @@ void bcm43xx_lo_write(struct bcm43xx_private *bcm, "WARNING: Writing invalid LOpair " "(low: %d, high: %d, index: %lu)\n", pair->low, pair->high, - (unsigned long)(pair - bcm->current_core->phy->_lo_pairs)); + (unsigned long)(pair - bcm43xx_current_phy(bcm)->_lo_pairs)); dump_stack(); } #endif @@ -1257,7 +1254,7 @@ struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm, u16 tx) { static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 }; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); if (baseband_attenuation > 6) baseband_attenuation = 6; @@ -1275,10 +1272,12 @@ struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm, static inline struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + return bcm43xx_find_lopair(bcm, - bcm->current_core->radio->txpower[0], - bcm->current_core->radio->txpower[1], - bcm->current_core->radio->txpower[2]); + radio->txpower[0], + radio->txpower[1], + radio->txpower[2]); } /* Adjust B/G LO */ @@ -1294,9 +1293,9 @@ void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed) bcm43xx_lo_write(bcm, pair); } -static inline -void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) +static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 txctl2 = 0, i; u32 smallest, tmp; @@ -1312,7 +1311,7 @@ void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) txctl2 = i; } } - bcm->current_core->radio->txpower[3] = txctl2; + radio->txpower[3] = txctl2; } static @@ -1402,16 +1401,17 @@ void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm, void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, u16 baseband_attenuation) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 value; - if (bcm->current_core->phy->version == 0) { + if (phy->version == 0) { value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0); value |= (baseband_attenuation & 0x000F); bcm43xx_write16(bcm, 0x03E6, value); return; } - if (bcm->current_core->phy->version > 1) { + if (phy->version > 1) { value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C; value |= (baseband_attenuation << 2) & 0x003C; } else { @@ -1426,8 +1426,8 @@ 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); - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 h, i, oldi = 0, j; struct bcm43xx_lopair control; struct bcm43xx_lopair *tmp_control; @@ -1653,7 +1653,7 @@ void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm) void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_lopair *pair; int i; @@ -1668,7 +1668,7 @@ void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm) */ static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); s8 dbm = 0; s32 tmp; @@ -1698,8 +1698,8 @@ static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi) /* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); if (phy->savedpctlreg == 0xFFFF) return; @@ -1880,8 +1880,8 @@ s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2) /* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */ int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); s16 pab0, pab1, pab2; u8 idx; s8 *dyn_tssi2dbm; @@ -1958,7 +1958,7 @@ int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) int bcm43xx_phy_init(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); int err = -ENODEV; unsigned long flags; @@ -2008,7 +2008,7 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm) void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 antennadiv; u16 offset; u16 value; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 26dc6047d458..7bddae910de9 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -146,7 +146,7 @@ struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm, u16 cookie, struct bcm43xx_pio_txpacket **packet) { - struct bcm43xx_pio *pio = bcm->current_core->pio; + struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); struct bcm43xx_pioqueue *queue = NULL; int packetindex; @@ -377,7 +377,7 @@ static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) void bcm43xx_pio_free(struct bcm43xx_private *bcm) { - struct bcm43xx_pio *pio = bcm->current_core->pio; + struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); bcm43xx_destroy_pioqueue(pio->queue3); pio->queue3 = NULL; @@ -391,7 +391,7 @@ void bcm43xx_pio_free(struct bcm43xx_private *bcm) int bcm43xx_pio_init(struct bcm43xx_private *bcm) { - struct bcm43xx_pio *pio = bcm->current_core->pio; + struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); struct bcm43xx_pioqueue *queue; int err = -ENOMEM; @@ -438,7 +438,7 @@ err_destroy0: int bcm43xx_pio_tx(struct bcm43xx_private *bcm, struct ieee80211_txb *txb) { - struct bcm43xx_pioqueue *queue = bcm->current_core->pio->queue1; + struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; struct bcm43xx_pio_txpacket *packet; u16 tmp; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 4d3b0e85876c..07a6169a0b34 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -114,8 +114,8 @@ void bcm43xx_radio_unlock(struct bcm43xx_private *bcm) u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); switch (phy->type) { case BCM43xx_PHYTYPE_A: @@ -151,7 +151,7 @@ void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm, s16 first, s16 second, s16 third) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 i; u16 start = 0x08, end = 0x18; u16 offset = 0x0400; @@ -183,7 +183,7 @@ static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm, static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 i, tmp; u16 offset = 0x0400; u16 start = 0x0008, end = 0x0018; @@ -217,7 +217,7 @@ static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm) /* Synthetic PU workaround */ static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); if (radio->version != 0x2050 || radio->revision >= 6) { /* We do not need the workaround. */ @@ -238,7 +238,7 @@ static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel) u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u8 ret = 0; u16 saved, rssi, temp; int i, j = 0; @@ -269,8 +269,8 @@ u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel) u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u8 ret[13]; unsigned int channel = radio->channel; unsigned int i, j, start, end; @@ -351,22 +351,23 @@ void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val) /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); s16 i, delta; s32 tmp; - delta = 0x1F - bcm->current_core->radio->nrssi[0]; + delta = 0x1F - radio->nrssi[0]; for (i = 0; i < 64; i++) { - tmp = (i - delta) * bcm->current_core->radio->nrssislope; + tmp = (i - delta) * radio->nrssislope; tmp /= 0x10000; tmp += 0x3A; tmp = limit_value(tmp, 0, 0x3F); - bcm->current_core->radio->nrssi_lt[i] = tmp; + radio->nrssi_lt[i] = tmp; } } static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 backup[20] = { 0 }; s16 v47F; u16 i; @@ -531,8 +532,8 @@ static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 backup[18] = { 0 }; u16 tmp; s16 nrssi0, nrssi1; @@ -779,8 +780,8 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); s16 threshold; s32 a, b; int tmp; @@ -804,7 +805,7 @@ void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) radiotype = 1; if (radiotype == 1) { - threshold = bcm->current_core->radio->nrssi[1] - 5; + threshold = radio->nrssi[1] - 5; } else { threshold = 40 * radio->nrssi[0]; threshold += 33 * (radio->nrssi[1] - radio->nrssi[0]); @@ -901,8 +902,8 @@ static void bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, int mode) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); int i = 0; u16 *stack = radio->interfstack; u16 tmp, flipped; @@ -1052,8 +1053,8 @@ static void bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, int mode) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); int i = 0; u16 *stack = radio->interfstack; u16 tmp, flipped; @@ -1142,8 +1143,8 @@ bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); int currentmode; if ((phy->type != BCM43xx_PHYTYPE_G) || @@ -1199,8 +1200,8 @@ u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm) u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 backup[19] = { 0 }; u16 ret; u16 i, j; @@ -1444,7 +1445,7 @@ int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel, int synthetic_pu_workaround) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 r8, tmp; u16 freq; @@ -1628,6 +1629,7 @@ static u16 bcm43xx_get_txgain_dac(u16 txpower) void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 pamp, base, dac, ilt; txpower = limit_value(txpower, 0, 63); @@ -1650,7 +1652,7 @@ void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) bcm43xx_ilt_write(bcm, 0x3001, dac); - bcm->current_core->radio->txpower[0] = txpower; + radio->txpower[0] = txpower; TODO(); //TODO: FuncPlaceholder (Adjust BB loft cancel) @@ -1660,8 +1662,8 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, u16 baseband_attenuation, u16 radio_attenuation, u16 txpower) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); if (baseband_attenuation == 0xFFFF) baseband_attenuation = radio->txpower[0]; @@ -1698,8 +1700,8 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); int err; if (radio->enabled) @@ -1730,8 +1732,8 @@ void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm) void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); if (phy->type == BCM43xx_PHYTYPE_A) { bcm43xx_radio_write16(bcm, 0x0004, 0x00FF); @@ -1750,7 +1752,9 @@ void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm) void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm) { - switch (bcm->current_core->phy->type) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + + switch (phy->type) { case BCM43xx_PHYTYPE_A: bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F); bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index 713ec601c342..35c3c9704c3c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -150,7 +150,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, bcm43xx_lock(bcm, flags); assert(bcm->initialized); - switch (bcm->current_core->radio->interfmode) { + switch (bcm43xx_current_radio(bcm)->interfmode) { case BCM43xx_RADIO_INTERFMODE_NONE: count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n"); break; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 208193851e8e..651ba6054957 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -56,15 +56,14 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - int i, nr_80211; + int i; struct bcm43xx_phyinfo *phy; char suffix[7] = { 0 }; int have_a = 0, have_b = 0, have_g = 0; bcm43xx_lock(bcm, flags); - nr_80211 = bcm43xx_num_80211_cores(bcm); - for (i = 0; i < nr_80211; i++) { - phy = bcm->phy + i; + for (i = 0; i < bcm->nr_80211_available; i++) { + phy = &(bcm->core_80211_ext[i].phy); switch (phy->type) { case BCM43xx_PHYTYPE_A: have_a = 1; @@ -129,7 +128,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, err = bcm43xx_radio_selectchannel(bcm, channel, 0); bcm43xx_mac_enable(bcm); } else { - bcm->current_core->radio->initial_channel = channel; + bcm43xx_current_radio(bcm)->initial_channel = channel; err = 0; } out_unlock: @@ -144,15 +143,17 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct bcm43xx_radioinfo *radio; unsigned long flags; int err = -ENODEV; u16 channel; bcm43xx_lock(bcm, flags); - channel = bcm->current_core->radio->channel; + radio = bcm43xx_current_radio(bcm); + channel = radio->channel; if (channel == 0xFF) { assert(!bcm->initialized); - channel = bcm->current_core->radio->initial_channel; + channel = radio->initial_channel; if (channel == 0xFF) goto out_unlock; } @@ -232,6 +233,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, const struct ieee80211_geo *geo; unsigned long flags; int i, j; + struct bcm43xx_phyinfo *phy; data->data.length = sizeof(*range); memset(range, 0, sizeof(*range)); @@ -270,11 +272,12 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, IW_ENC_CAPA_CIPHER_CCMP; bcm43xx_lock(bcm, flags); + phy = bcm43xx_current_phy(bcm); range->num_bitrates = 0; i = 0; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A || - bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + if (phy->type == BCM43xx_PHYTYPE_A || + phy->type == BCM43xx_PHYTYPE_G) { range->num_bitrates = 8; range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB; range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB; @@ -285,8 +288,8 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB; range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB; } - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B || - bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + if (phy->type == BCM43xx_PHYTYPE_B || + phy->type == BCM43xx_PHYTYPE_G) { range->num_bitrates += 4; range->bitrate[i++] = IEEE80211_CCK_RATE_1MB; range->bitrate[i++] = IEEE80211_CCK_RATE_2MB; @@ -461,8 +464,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) goto out_unlock; - radio = bcm->current_core->radio; - phy = bcm->current_core->phy; + radio = bcm43xx_current_radio(bcm); + phy = bcm43xx_current_phy(bcm); if (data->txpower.disabled != (!(radio->enabled))) { if (data->txpower.disabled) bcm43xx_radio_turn_off(bcm); @@ -500,7 +503,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, bcm43xx_lock(bcm, flags); if (!bcm->initialized) goto out_unlock; - radio = bcm->current_core->radio; + radio = bcm43xx_current_radio(bcm); /* desired dBm value is in Q5.2 */ data->txpower.value = radio->txpower_desired >> 2; data->txpower.fixed = 1; @@ -645,7 +648,7 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, "not supported while the interface is down.\n"); err = -ENODEV; } else - bcm->current_core->radio->interfmode = mode; + bcm43xx_current_radio(bcm)->interfmode = mode; } bcm43xx_unlock_mmio(bcm, flags); @@ -662,7 +665,7 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, int mode; bcm43xx_lock(bcm, flags); - mode = bcm->current_core->radio->interfmode; + mode = bcm43xx_current_radio(bcm)->interfmode; bcm43xx_unlock(bcm, flags); switch (mode) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c index 5ee572e79f61..c4809da8e9c7 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c @@ -284,7 +284,7 @@ void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, const int is_first_fragment, const u16 cookie) { - const struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data; const struct ieee80211_security *secinfo = &bcm->ieee->sec; u8 bitrate; @@ -382,8 +382,8 @@ static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, u8 in_rssi, int ofdm, int adjust_2053, int adjust_2050) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); s32 tmp; switch (radio->version) { @@ -442,7 +442,7 @@ static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, u8 in_rssi) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); s8 ret; if (phy->type == BCM43xx_PHYTYPE_A) { @@ -458,6 +458,8 @@ int bcm43xx_rx(struct bcm43xx_private *bcm, struct sk_buff *skb, struct bcm43xx_rxhdr *rxhdr) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_plcp_hdr4 *plcp; struct ieee80211_rx_stats stats; struct ieee80211_hdr_4addr *wlhdr; @@ -494,13 +496,13 @@ int bcm43xx_rx(struct bcm43xx_private *bcm, else stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp); //printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate); - stats.received_channel = bcm->current_core->radio->channel; + stats.received_channel = radio->channel; //TODO stats.control = stats.mask = IEEE80211_STATMASK_SIGNAL | //TODO IEEE80211_STATMASK_NOISE | IEEE80211_STATMASK_RATE | IEEE80211_STATMASK_RSSI; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (phy->type == BCM43xx_PHYTYPE_A) stats.freq = IEEE80211_52GHZ_BAND; else stats.freq = IEEE80211_24GHZ_BAND; -- cgit v1.2.3-59-g8ed1b From 49f29efa7f44a79b64c7882c68e171898d0495a0 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 14 Mar 2006 16:05:26 +0100 Subject: [PATCH] bcm43xx: Fix crash on ifdown, by being careful in pio/dma freeing. This bug was caused by the packing of the bcm43xx_dma and bcm43xx_pio structures into a union. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 6 +++++- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 7ed368a587f3..9c64438b767f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -531,7 +531,11 @@ static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring) void bcm43xx_dma_free(struct bcm43xx_private *bcm) { - struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); + struct bcm43xx_dma *dma; + + if (bcm43xx_using_pio(bcm)) + return; + dma = bcm43xx_current_dma(bcm); bcm43xx_destroy_dmaring(dma->rx_ring1); dma->rx_ring1 = NULL; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 7bddae910de9..5b6f0a84d017 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -377,7 +377,11 @@ static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) void bcm43xx_pio_free(struct bcm43xx_private *bcm) { - struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); + struct bcm43xx_pio *pio; + + if (!bcm43xx_using_pio(bcm)) + return; + pio = bcm43xx_current_pio(bcm); bcm43xx_destroy_pioqueue(pio->queue3); pio->queue3 = NULL; -- cgit v1.2.3-59-g8ed1b From 4cf6f03e067d6d416f5c9219471daf64703afae4 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 14 Mar 2006 18:23:43 +0100 Subject: [PATCH] bcm43xx: Remove the workaround in dummy_transmission, as it causes more trouble than it solves Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 88e9a125c2d7..cc8efe74f535 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -996,13 +996,6 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) 0x00000000, }; -/* FIXME: It seems like a dummy_transmission corrupts the DMA engines, - * once they are initialized. So avoid doing a dummy_transmission, - * if the DMA engines are running. - */ -if (bcm->initialized) -return; - switch (phy->type) { case BCM43xx_PHYTYPE_A: max_loop = 0x1E; -- cgit v1.2.3-59-g8ed1b From b3db5e553876c1743eefae5963aea431ec4d5ba6 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 15 Mar 2006 16:31:45 +0100 Subject: [PATCH] bcm43xx: Do boardflags workarounds for specific boards. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 4 ++++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 9 +++++++++ 2 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index a358646ad3eb..8820012b4b3a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -120,6 +120,10 @@ #define BCM43xx_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */ #define BCM43xx_BFL_NOPCI 0x0400 /* leaves PCI floating */ #define BCM43xx_BFL_FEM 0x0800 /* supports the Front End Module */ +#define BCM43xx_BFL_EXTLNA 0x1000 /* has an external LNA */ +#define BCM43xx_BFL_HGPA 0x2000 /* had high gain PA */ +#define BCM43xx_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */ +#define BCM43xx_BFL_ALTIQ 0x8000 /* alternate I/Q settings */ /* GPIO register offset, in both ChipCommon and PCI core. */ #define BCM43xx_GPIO_CONTROL 0x6c diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index cc8efe74f535..e26507b11f02 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -910,6 +910,15 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) if (value == 0xFFFF) value = 0x0000; bcm->sprom.boardflags = value; + /* boardflags workarounds */ + if (bcm->board_vendor == PCI_VENDOR_ID_DELL && + bcm->chip_id == 0x4301 && + bcm->board_revision == 0x74) + bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST; + if (bcm->board_vendor == PCI_VENDOR_ID_APPLE && + bcm->board_type == 0x4E && + bcm->board_revision > 0x40) + bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL; /* antenna gain */ value = sprom[BCM43xx_SPROM_ANTENNA_GAIN]; -- cgit v1.2.3-59-g8ed1b From 5808bbbdf8c095745f0cac9110b245102243b243 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 15 Mar 2006 18:13:53 +0100 Subject: [PATCH] bcm43xx: properly mask txctl1 before writing it to hardware. This should not make a difference, but be careful to not trash the register. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 07a6169a0b34..cac604bc0955 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -1690,8 +1690,8 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation); if (radio->version == 0x2050) { bcm43xx_radio_write16(bcm, 0x0052, - (bcm43xx_radio_read16(bcm, 0x0052) & 0xFF8F) - | (txpower << 4)); + (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070) + | ((txpower << 4) & 0x0070)); } if (phy->type == BCM43xx_PHYTYPE_G) bcm43xx_phy_lo_adjust(bcm, 0); -- cgit v1.2.3-59-g8ed1b From 4a1821e4c7a84569f788b7667affe2743317b63f Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 18 Mar 2006 20:19:12 +0100 Subject: [PATCH] bcm43xx: remove check for mmio length, as it differs among platforms. (especially embedded) Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 30 ++++------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index e26507b11f02..6a877df2ecf0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3386,23 +3386,17 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) struct net_device *net_dev = bcm->net_dev; int err; int i; - void __iomem *ioaddr; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; + unsigned long mmio_start, mmio_flags, mmio_len; u32 coremask; err = pci_enable_device(pci_dev); if (err) { printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err); - err = -ENODEV; goto out; } - mmio_start = pci_resource_start(pci_dev, 0); - mmio_end = pci_resource_end(pci_dev, 0); mmio_flags = pci_resource_flags(pci_dev, 0); mmio_len = pci_resource_len(pci_dev, 0); - - /* make sure PCI base addr is MMIO */ if (!(mmio_flags & IORESOURCE_MEM)) { printk(KERN_ERR PFX "%s, region #0 not an MMIO resource, aborting\n", @@ -3410,39 +3404,23 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) err = -ENODEV; goto err_pci_disable; } -//FIXME: Why is this check disabled for BCM947XX? What is the IO_SIZE there? -#ifndef CONFIG_BCM947XX - if (mmio_len != BCM43xx_IO_SIZE) { - printk(KERN_ERR PFX - "%s: invalid PCI mem region size(s), aborting\n", - pci_name(pci_dev)); - err = -ENODEV; - goto err_pci_disable; - } -#endif - err = pci_request_regions(pci_dev, KBUILD_MODNAME); if (err) { printk(KERN_ERR PFX "could not access PCI resources (%i)\n", err); goto err_pci_disable; } - /* enable PCI bus-mastering */ pci_set_master(pci_dev); - - /* ioremap MMIO region */ - ioaddr = ioremap(mmio_start, mmio_len); - if (!ioaddr) { + bcm->mmio_addr = ioremap(mmio_start, mmio_len); + if (!bcm->mmio_addr) { printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pci_dev)); err = -EIO; goto err_pci_release; } - - net_dev->base_addr = (unsigned long)ioaddr; - bcm->mmio_addr = ioaddr; bcm->mmio_len = mmio_len; + net_dev->base_addr = (unsigned long)bcm->mmio_addr; bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID, &bcm->board_vendor); -- cgit v1.2.3-59-g8ed1b From 714eece7c7c300bbc5e8285890e7374958ca37f4 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 18 Mar 2006 21:28:46 +0100 Subject: [PATCH] bcm43xx: fix some gpio register trashing (hopefully :D) Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 16 +++++-- drivers/net/wireless/bcm43xx/bcm43xx_leds.h | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 71 ++++++++++++++--------------- 3 files changed, 46 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 72a243aac6cb..c8f5ad75d2a6 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -165,7 +165,7 @@ void bcm43xx_leds_exit(struct bcm43xx_private *bcm) led = &(bcm->leds[i]); bcm43xx_led_blink_stop(led, 1); } - bcm43xx_leds_turn_off(bcm); + bcm43xx_leds_switch_all(bcm, 0); } void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) @@ -268,18 +268,26 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); } -void bcm43xx_leds_turn_off(struct bcm43xx_private *bcm) +void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) { struct bcm43xx_led *led; - u16 ledctl = 0; + u16 ledctl; int i; + int bit_on; + ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); for (i = 0; i < BCM43xx_NR_LEDS; i++) { led = &(bcm->leds[i]); if (led->behaviour == BCM43xx_LED_INACTIVE) continue; - if (led->activelow) + if (on) + bit_on = led->activelow ? 0 : 1; + else + bit_on = led->activelow ? 1 : 0; + if (bit_on) ledctl |= (1 << i); + else + ledctl &= ~(1 << i); } bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h index 6f18e2f95db4..d3716cf3aebc 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h @@ -51,6 +51,6 @@ enum { /* LED behaviour values */ int bcm43xx_leds_init(struct bcm43xx_private *bcm); void bcm43xx_leds_exit(struct bcm43xx_private *bcm); void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity); -void bcm43xx_leds_turn_off(struct bcm43xx_private *bcm); +void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on); #endif /* BCM43xx_LEDS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 6a877df2ecf0..eb8fca8279f4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2182,13 +2182,10 @@ static int switch_to_gpio_core(struct bcm43xx_private *bcm) if (unlikely(err == -ENODEV)) { printk(KERN_ERR PFX "gpio error: " "Neither ChipCommon nor PCI core available!\n"); - return -ENODEV; - } else if (unlikely(err != 0)) - return -ENODEV; - } else if (unlikely(err != 0)) - return -ENODEV; + } + } - return 0; + return err; } /* Initialize the GPIOs @@ -2198,45 +2195,48 @@ static int bcm43xx_gpio_init(struct bcm43xx_private *bcm) { struct bcm43xx_coreinfo *old_core; int err; - u32 mask, value; + u32 mask, set; - value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value &= ~0xc000; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + & 0xFFFF3FFF); - mask = 0x0000001F; - value = 0x0000000F; - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, - bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL) & 0xFFF0); + bcm43xx_leds_switch_all(bcm, 0); bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F); - old_core = bcm->current_core; - - err = switch_to_gpio_core(bcm); - if (err) - return err; - - if (bcm->current_core->rev >= 2){ - mask |= 0x10; - value |= 0x10; - } + mask = 0x0000001F; + set = 0x0000000F; if (bcm->chip_id == 0x4301) { - mask |= 0x60; - value |= 0x60; + mask |= 0x0060; + set |= 0x0060; + } + if (0 /* FIXME: conditional unknown */) { + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, + bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) + | 0x0100); + mask |= 0x0180; + set |= 0x0180; } if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) { - mask |= 0x200; - value |= 0x200; + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, + bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) + | 0x0200); + mask |= 0x0200; + set |= 0x0200; } + if (bcm->current_core->rev >= 2) + mask |= 0x0010; /* FIXME: This is redundant. */ + old_core = bcm->current_core; + err = switch_to_gpio_core(bcm); + if (err) + goto out; bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, - (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | value); - + (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set); err = bcm43xx_switch_core(bcm, old_core); - assert(err == 0); - - return 0; +out: + return err; } /* Turn off all GPIO stuff. Call this on module unload, for example. */ @@ -2384,11 +2384,6 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) goto err_gpio_cleanup; bcm43xx_radio_turn_on(bcm); - if (modparam_noleds) - bcm43xx_leds_turn_off(bcm); - else - bcm43xx_leds_update(bcm, 0); - bcm43xx_write16(bcm, 0x03E6, 0x0000); err = bcm43xx_phy_init(bcm); if (err) -- cgit v1.2.3-59-g8ed1b From 6ab5b8e670c4bb7ac0035ec3c6d6a161fae12009 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Mar 2006 17:18:48 +0100 Subject: [PATCH] bcm43xx: merge all iwmode code into the set_iwmode function. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 65 +++++++++++++---------------- 1 file changed, 29 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index eb8fca8279f4..a85176325e92 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2292,50 +2292,60 @@ void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, int iw_mode) { unsigned long flags; + struct net_device *net_dev = bcm->net_dev; u32 status; + u16 value; spin_lock_irqsave(&bcm->ieee->lock, flags); bcm->ieee->iw_mode = iw_mode; spin_unlock_irqrestore(&bcm->ieee->lock, flags); if (iw_mode == IW_MODE_MONITOR) - bcm->net_dev->type = ARPHRD_IEEE80211; + net_dev->type = ARPHRD_IEEE80211; else - bcm->net_dev->type = ARPHRD_ETHER; + net_dev->type = ARPHRD_ETHER; - if (!bcm->initialized) - return; - - bcm43xx_mac_suspend(bcm); status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Reset status to infrastructured mode */ status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR); - /*FIXME: We actually set promiscuous mode as well, until we don't - * get the HW mac filter working */ - status |= BCM43xx_SBF_MODE_NOTADHOC | BCM43xx_SBF_MODE_PROMISC; + status &= ~BCM43xx_SBF_MODE_PROMISC; + status |= BCM43xx_SBF_MODE_NOTADHOC; + +/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */ +status |= BCM43xx_SBF_MODE_PROMISC; switch (iw_mode) { case IW_MODE_MONITOR: - status |= (BCM43xx_SBF_MODE_PROMISC | - BCM43xx_SBF_MODE_MONITOR); + status |= BCM43xx_SBF_MODE_MONITOR; + status |= BCM43xx_SBF_MODE_PROMISC; break; case IW_MODE_ADHOC: status &= ~BCM43xx_SBF_MODE_NOTADHOC; break; case IW_MODE_MASTER: + status |= BCM43xx_SBF_MODE_AP; + break; case IW_MODE_SECOND: case IW_MODE_REPEAT: - /* TODO: No AP/Repeater mode for now :-/ */ - TODO(); + TODO(); /* TODO */ break; case IW_MODE_INFRA: /* nothing to be done here... */ break; default: - printk(KERN_ERR PFX "Unknown iwmode %d\n", iw_mode); + dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode); } - + if (net_dev->flags & IFF_PROMISC) + status |= BCM43xx_SBF_MODE_PROMISC; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - bcm43xx_mac_enable(bcm); + + value = 0x0002; + if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) { + if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3) + value = 0x0064; + else + value = 0x0032; + } + bcm43xx_write16(bcm, 0x0612, value); } /* This is the opposite of bcm43xx_chip_init() */ @@ -2357,7 +2367,6 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); int err; - int iw_mode = bcm->ieee->iw_mode; int tmp; u32 value32; u16 value16; @@ -2411,20 +2420,9 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); value32 |= BCM43xx_SBF_MODE_NOTADHOC; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - /*FIXME: For now, use promiscuous mode at all times; otherwise we don't - get broadcast or multicast packets */ - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 |= BCM43xx_SBF_MODE_PROMISC; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - if (iw_mode == IW_MODE_MONITOR) { - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 |= BCM43xx_SBF_MODE_PROMISC; - value32 |= BCM43xx_SBF_MODE_MONITOR; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - } value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 |= 0x100000; //FIXME: What's this? Is this correct? + value32 |= 0x100000; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); if (bcm43xx_using_pio(bcm)) { @@ -2439,13 +2437,8 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000); - if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) { - if ((bcm->chip_id == 0x4306) && (bcm->chip_rev == 3)) - bcm43xx_write16(bcm, 0x0612, 0x0064); - else - bcm43xx_write16(bcm, 0x0612, 0x0032); - } else - bcm43xx_write16(bcm, 0x0612, 0x0002); + /* Initially set the wireless operation mode. */ + bcm43xx_set_iwmode(bcm, bcm->ieee->iw_mode); if (bcm->current_core->rev < 3) { bcm43xx_write16(bcm, 0x060E, 0x0000); -- cgit v1.2.3-59-g8ed1b From 0ac59daee5f7fbaab25784a643edede669b5419e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Mar 2006 21:43:40 +0100 Subject: [PATCH] bcm43xx: some IRQ handler cleanups. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 65 +++++++++++++---------------- 1 file changed, 30 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index a85176325e92..12c93d274ae5 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1785,10 +1785,6 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS); } - /* We get spurious IRQs, althought they are masked. - * Assume they are void and ignore them. - */ - bcmirq_handled(~(bcm->irq_savedstate)); /* IRQ_PIO_WORKAROUND is handled in the top-half. */ bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND); #ifdef CONFIG_BCM43XX_DEBUG @@ -1809,41 +1805,31 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) bcm43xx_unlock_mmio(bcm, flags); } -static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, - u32 reason, u32 mask) +static void pio_irq_workaround(struct bcm43xx_private *bcm, + u16 base, int queueidx) { - bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) - & 0x0001dc00; - bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) - & 0x0000dc00; - bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) - & 0x0000dc00; - bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) - & 0x0001dc00; + u16 rxctl; + + rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL); + if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE) + bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE; + else + bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE; +} +static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason) +{ if (bcm43xx_using_pio(bcm) && (bcm->current_core->rev < 3) && (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) { /* Apply a PIO specific workaround to the dma_reasons */ - -#define apply_pio_workaround(BASE, QNUM) \ - do { \ - if (bcm43xx_read16(bcm, BASE + BCM43xx_PIO_RXCTL) & BCM43xx_PIO_RXCTL_DATAAVAILABLE) \ - bcm->dma_reason[QNUM] |= 0x00010000; \ - else \ - bcm->dma_reason[QNUM] &= ~0x00010000; \ - } while (0) - - apply_pio_workaround(BCM43xx_MMIO_PIO1_BASE, 0); - apply_pio_workaround(BCM43xx_MMIO_PIO2_BASE, 1); - apply_pio_workaround(BCM43xx_MMIO_PIO3_BASE, 2); - apply_pio_workaround(BCM43xx_MMIO_PIO4_BASE, 3); - -#undef apply_pio_workaround + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0); + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1); + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2); + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3); } - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, - reason & mask); + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason); bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON, bcm->dma_reason[0]); @@ -1860,7 +1846,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re { irqreturn_t ret = IRQ_HANDLED; struct bcm43xx_private *bcm = dev_id; - u32 reason, mask; + u32 reason; if (!bcm) return IRQ_NONE; @@ -1873,11 +1859,20 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re ret = IRQ_NONE; goto out; } - mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); - if (!(reason & mask)) + reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); + if (!reason) goto out; - bcm43xx_interrupt_ack(bcm, reason, mask); + bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) + & 0x0001dc00; + bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) + & 0x0000dc00; + bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) + & 0x0000dc00; + bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) + & 0x0001dc00; + + bcm43xx_interrupt_ack(bcm, reason); /* Only accept IRQs, if we are initialized properly. * This avoids an RX race while initializing. -- cgit v1.2.3-59-g8ed1b From 6ecb26904c9db15ca964d60b9483f19dc51bda5b Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 20 Mar 2006 00:01:04 +0100 Subject: [PATCH] bcm43xx: set default attenuation values. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 21 +++-- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 9 +- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 30 +++--- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 131 +++++++++++++++++++++++++-- drivers/net/wireless/bcm43xx/bcm43xx_radio.h | 5 + 5 files changed, 158 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 8820012b4b3a..1fca1f9c48fe 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -507,14 +507,23 @@ struct bcm43xx_radioinfo { u16 version; u8 revision; - /* 0: baseband attenuation, - * 1: radio attenuation, - * 2: tx_CTL1 - * 3: tx_CTL2 - */ - u16 txpower[4]; /* Desired TX power in dBm Q5.2 */ u16 txpower_desired; + /* TX Power control values. */ + union { + /* B/G PHY */ + struct { + u16 baseband_atten; + u16 radio_atten; + u16 txctl1; + u16 txctl2; + }; + /* A PHY */ + struct { + u16 txpwr_offset; + }; + }; + /* Current Interference Mitigation mode */ int interfmode; /* Stack of saved values from the Interference Mitigation code */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 12c93d274ae5..e680d2acc44b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -560,12 +560,9 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) radio->revision = revision; /* Set default attenuation values. */ - radio->txpower[0] = 2; - radio->txpower[1] = 2; - if (revision == 1) - radio->txpower[2] = 3; - else - radio->txpower[2] = 0; + radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm); + radio->radio_atten = bcm43xx_default_radio_attenuation(bcm); + radio->txctl1 = bcm43xx_default_txctl1(bcm); if (phy->type == BCM43xx_PHYTYPE_A) radio->txpower_desired = bcm->sprom.maxpower_aphy; else diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 1ce9a4599903..054c64e462fb 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -220,9 +220,9 @@ static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) | 0x0084); } else { - saved_batt = radio->txpower[0]; - saved_ratt = radio->txpower[1]; - saved_txctl1 = radio->txpower[2]; + saved_batt = radio->baseband_atten; + saved_ratt = radio->radio_atten; + saved_txctl1 = radio->txctl1; if ((radio->revision >= 6) && (radio->revision <= 8) && /*FIXME: incomplete specs for 5 < revision < 9 */ 0) bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0); @@ -1039,7 +1039,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x0078, radio->initval); bcm43xx_radio_write16(bcm, 0x0052, (bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0) - | radio->txpower[3]); + | radio->txctl2); } if (phy->connected) { @@ -1259,7 +1259,6 @@ struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm, if (baseband_attenuation > 6) baseband_attenuation = 6; assert(radio_attenuation < 10); - assert(tx == 0 || tx == 3); if (tx == 3) { return bcm43xx_get_lopair(phy, @@ -1275,9 +1274,9 @@ struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm) struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); return bcm43xx_find_lopair(bcm, - radio->txpower[0], - radio->txpower[1], - radio->txpower[2]); + radio->baseband_atten, + radio->radio_atten, + radio->txctl1); } /* Adjust B/G LO */ @@ -1311,7 +1310,7 @@ static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) txctl2 = i; } } - radio->txpower[3] = txctl2; + radio->txctl2 = txctl2; } static @@ -1530,8 +1529,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) r31 = 0; } bcm43xx_radio_write16(bcm, 0x43, i); - bcm43xx_radio_write16(bcm, 0x52, - radio->txpower[3]); + bcm43xx_radio_write16(bcm, 0x52, radio->txctl2); udelay(10); bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); @@ -1573,7 +1571,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) } bcm43xx_radio_write16(bcm, 0x43, i - 9); bcm43xx_radio_write16(bcm, 0x52, - radio->txpower[3] + radio->txctl2 | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? udelay(10); @@ -1780,9 +1778,9 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) } /* Calculate the new attenuation values. */ - baseband_attenuation = radio->txpower[0]; + baseband_attenuation = radio->baseband_atten; baseband_attenuation += baseband_att_delta; - radio_attenuation = radio->txpower[1]; + radio_attenuation = radio->radio_atten; radio_attenuation += radio_att_delta; /* Get baseband and radio attenuation values into their permitted ranges. @@ -1807,7 +1805,7 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) } baseband_attenuation = limit_value(baseband_attenuation, 0, 11); - txpower = radio->txpower[2]; + txpower = radio->txctl1; if ((radio->version == 0x2050) && (radio->revision == 2)) { if (radio_attenuation <= 1) { if (txpower == 0) { @@ -1829,7 +1827,7 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) } } } - radio->txpower[2] = txpower; + radio->txctl1 = txpower; baseband_attenuation = limit_value(baseband_attenuation, 0, 11); radio_attenuation = limit_value(radio_attenuation, 0, 9); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index cac604bc0955..4e8d8c936ab4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -1652,7 +1652,7 @@ void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) bcm43xx_ilt_write(bcm, 0x3001, dac); - radio->txpower[0] = txpower; + radio->txpwr_offset = txpower; TODO(); //TODO: FuncPlaceholder (Adjust BB loft cancel) @@ -1666,17 +1666,14 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); if (baseband_attenuation == 0xFFFF) - baseband_attenuation = radio->txpower[0]; - else - radio->txpower[0] = baseband_attenuation; + baseband_attenuation = radio->baseband_atten; if (radio_attenuation == 0xFFFF) - radio_attenuation = radio->txpower[1]; - else - radio->txpower[1] = radio_attenuation; + radio_attenuation = radio->radio_atten; if (txpower == 0xFFFF) - txpower = radio->txpower[2]; - else - radio->txpower[2] = txpower; + txpower = radio->txctl1; + radio->baseband_atten = baseband_attenuation; + radio->radio_atten = radio_attenuation; + radio->txctl1 = txpower; assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11); if (radio->revision < 6) @@ -1693,10 +1690,124 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070) | ((txpower << 4) & 0x0070)); } + //FIXME: The spec is very weird and unclear here. if (phy->type == BCM43xx_PHYTYPE_G) bcm43xx_phy_lo_adjust(bcm, 0); } +u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + + if (radio->version == 0x2050 && radio->revision < 6) + return 0; + return 2; +} + +u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + u16 att = 0xFFFF; + + if (phy->type == BCM43xx_PHYTYPE_A) + return 0x60; + + switch (radio->version) { + case 0x2053: + switch (radio->revision) { + case 1: + att = 6; + break; + } + break; + case 0x2050: + switch (radio->revision) { + case 0: + att = 5; + break; + case 1: + if (phy->type == BCM43xx_PHYTYPE_G) { + if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x421 && + bcm->board_revision >= 30) + att = 3; + else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x416) + att = 3; + else + att = 1; + } else { + if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x421 && + bcm->board_revision >= 30) + att = 7; + else + att = 6; + } + break; + case 2: + if (phy->type == BCM43xx_PHYTYPE_G) { + if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x421 && + bcm->board_revision >= 30) + att = 3; + else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x416) + att = 5; + else if (bcm->chip_id == 0x4320) + att = 4; + else + att = 3; + } else + att = 6; + break; + case 3: + att = 5; + break; + case 4: + case 5: + att = 1; + break; + case 6: + case 7: + att = 5; + break; + case 8: + att = 0x1A; + break; + case 9: + default: + att = 5; + } + } + if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x421) { + if (bcm->board_revision < 0x43) + att = 2; + else if (bcm->board_revision < 0x51) + att = 3; + } + if (att == 0xFFFF) + att = 5; + + return att; +} + +u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + + if (radio->version != 0x2050) + return 0; + if (radio->revision == 1) + return 3; + if (radio->revision < 6) + return 2; + if (radio->revision == 8) + return 1; + return 0; +} void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h index a5d2e10d5d98..9ed18039fa3e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h @@ -72,6 +72,11 @@ void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower); void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, u16 baseband_attenuation, u16 attenuation, u16 txpower); + +u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm); +u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm); +u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm); + void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val); void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm); -- cgit v1.2.3-59-g8ed1b From e382c234cbc6fcd76e9ed1168c77fe88d75df73c Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 21 Mar 2006 18:16:28 +0100 Subject: [PATCH] bcm43xx: sync interference mitigation code to the specs. This also includes a rewritten valuesave-stack. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 12 +- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 447 ++++++++++++++++++--------- 2 files changed, 309 insertions(+), 150 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 1fca1f9c48fe..57fcaafcf7dd 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -526,8 +526,16 @@ struct bcm43xx_radioinfo { /* Current Interference Mitigation mode */ int interfmode; - /* Stack of saved values from the Interference Mitigation code */ - u16 interfstack[20]; + /* Stack of saved values from the Interference Mitigation code. + * Each value in the stack is layed out as follows: + * bit 0-11: offset + * bit 12-15: register ID + * bit 16-32: value + * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT + */ +#define BCM43xx_INTERFSTACK_SIZE 26 + u32 interfstack[BCM43xx_INTERFSTACK_SIZE]; + /* Saved values from the NRSSI Slope calculation */ s16 nrssi[2]; s32 nrssislope; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 4e8d8c936ab4..63aae43ba838 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -879,24 +879,76 @@ void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) } } -/* Helper macros to save on and restore values from the radio->interfstack */ -#ifdef stack_save -# undef stack_save -#endif -#ifdef stack_restore -# undef stack_restore -#endif -#define stack_save(value) \ +/* Stack implementation to save/restore values from the + * interference mitigation code. + * It is save to restore values in random order. + */ +static void _stack_save(u32 *_stackptr, size_t *stackidx, + u8 id, u16 offset, u16 value) +{ + u32 *stackptr = &(_stackptr[*stackidx]); + + assert((offset & 0xF000) == 0x0000); + assert((id & 0xF0) == 0x00); + *stackptr = offset; + *stackptr |= ((u32)id) << 12; + *stackptr |= ((u32)value) << 16; + (*stackidx)++; + assert(*stackidx < BCM43xx_INTERFSTACK_SIZE); +} + +static u16 _stack_restore(u32 *stackptr, + u8 id, u16 offset) +{ + size_t i; + + assert((offset & 0xF000) == 0x0000); + assert((id & 0xF0) == 0x00); + for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) { + if ((*stackptr & 0x00000FFF) != offset) + continue; + if (((*stackptr & 0x0000F000) >> 12) != id) + continue; + return ((*stackptr & 0xFFFF0000) >> 16); + } + assert(0); + + return 0; +} + +#define phy_stacksave(offset) \ do { \ - assert(i < ARRAY_SIZE(radio->interfstack)); \ - stack[i++] = (value); \ + _stack_save(stack, &stackidx, 0x1, (offset), \ + bcm43xx_phy_read(bcm, (offset))); \ + } while (0) +#define phy_stackrestore(offset) \ + do { \ + bcm43xx_phy_write(bcm, (offset), \ + _stack_restore(stack, 0x1, \ + (offset))); \ + } while (0) +#define radio_stacksave(offset) \ + do { \ + _stack_save(stack, &stackidx, 0x2, (offset), \ + bcm43xx_radio_read16(bcm, (offset))); \ + } while (0) +#define radio_stackrestore(offset) \ + do { \ + bcm43xx_radio_write16(bcm, (offset), \ + _stack_restore(stack, 0x2, \ + (offset))); \ + } while (0) +#define ilt_stacksave(offset) \ + do { \ + _stack_save(stack, &stackidx, 0x3, (offset), \ + bcm43xx_ilt_read(bcm, (offset))); \ + } while (0) +#define ilt_stackrestore(offset) \ + do { \ + bcm43xx_ilt_write(bcm, (offset), \ + _stack_restore(stack, 0x3, \ + (offset))); \ } while (0) - -#define stack_restore() \ - ({ \ - assert(i < ARRAY_SIZE(radio->interfstack)); \ - stack[i++]; \ - }) static void bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, @@ -904,144 +956,231 @@ bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - int i = 0; - u16 *stack = radio->interfstack; u16 tmp, flipped; + u32 tmp32; + size_t stackidx = 0; + u32 *stack = radio->interfstack; switch (mode) { case BCM43xx_RADIO_INTERFMODE_NONWLAN: if (phy->rev != 1) { bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) & 0x0800); + bcm43xx_phy_read(bcm, 0x042B) | 0x0800); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000); break; } + radio_stacksave(0x0078); tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); flipped = flip_4bit(tmp); - if ((flipped >> 1) >= 4) - tmp = flipped - 3; - tmp = flip_4bit(tmp); - bcm43xx_radio_write16(bcm, 0x0078, tmp << 1); + if (flipped < 10 && flipped >= 8) + flipped = 7; + else if (flipped >= 10) + flipped -= 3; + flipped = flip_4bit(flipped); + flipped = (flipped << 1) | 0x0020; + bcm43xx_radio_write16(bcm, 0x0078, flipped); bcm43xx_calc_nrssi_threshold(bcm); - if (bcm->current_core->rev < 5) { - stack_save(bcm43xx_phy_read(bcm, 0x0406)); - bcm43xx_phy_write(bcm, 0x0406, 0x7E28); - } else { - stack_save(bcm43xx_phy_read(bcm, 0x04C0)); - stack_save(bcm43xx_phy_read(bcm, 0x04C1)); - bcm43xx_phy_write(bcm, 0x04C0, 0x3E04); - bcm43xx_phy_write(bcm, 0x04C1, 0x0640); - } + phy_stacksave(0x0406); + bcm43xx_phy_write(bcm, 0x0406, 0x7E28); bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x0800); bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000); - stack_save(bcm43xx_phy_read(bcm, 0x04A0)); + phy_stacksave(0x04A0); bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008); - stack_save(bcm43xx_phy_read(bcm, 0x04A1)); + phy_stacksave(0x04A1); bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605); - stack_save(bcm43xx_phy_read(bcm, 0x04A2)); + phy_stacksave(0x04A2); bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204); - stack_save(bcm43xx_phy_read(bcm, 0x04A8)); + phy_stacksave(0x04A8); bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0403); - stack_save(bcm43xx_phy_read(bcm, 0x04AB)); + (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803); + phy_stacksave(0x04AB); bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0504); + (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605); - stack_save(bcm43xx_phy_read(bcm, 0x04A7)); + phy_stacksave(0x04A7); bcm43xx_phy_write(bcm, 0x04A7, 0x0002); - stack_save(bcm43xx_phy_read(bcm, 0x04A3)); + phy_stacksave(0x04A3); bcm43xx_phy_write(bcm, 0x04A3, 0x287A); - stack_save(bcm43xx_phy_read(bcm, 0x04A9)); + phy_stacksave(0x04A9); bcm43xx_phy_write(bcm, 0x04A9, 0x2027); - stack_save(bcm43xx_phy_read(bcm, 0x0493)); + phy_stacksave(0x0493); bcm43xx_phy_write(bcm, 0x0493, 0x32F5); - stack_save(bcm43xx_phy_read(bcm, 0x04AA)); + phy_stacksave(0x04AA); bcm43xx_phy_write(bcm, 0x04AA, 0x2027); - stack_save(bcm43xx_phy_read(bcm, 0x04AC)); + phy_stacksave(0x04AC); bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); break; case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - if (bcm43xx_phy_read(bcm, 0x0033) == 0x0800) + if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800) break; radio->aci_enable = 1; - stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)); - stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)); - if (bcm->current_core->rev < 5) { - stack_save(bcm43xx_phy_read(bcm, 0x0406)); + phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD); + phy_stacksave(BCM43xx_PHY_G_CRS); + if (phy->rev < 2) { + phy_stacksave(0x0406); } else { - stack_save(bcm43xx_phy_read(bcm, 0x04C0)); - stack_save(bcm43xx_phy_read(bcm, 0x04C1)); + phy_stacksave(0x04C0); + phy_stacksave(0x04C1); } - stack_save(bcm43xx_phy_read(bcm, 0x0033)); - stack_save(bcm43xx_phy_read(bcm, 0x04A7)); - stack_save(bcm43xx_phy_read(bcm, 0x04A3)); - stack_save(bcm43xx_phy_read(bcm, 0x04A9)); - stack_save(bcm43xx_phy_read(bcm, 0x04AA)); - stack_save(bcm43xx_phy_read(bcm, 0x04AC)); - stack_save(bcm43xx_phy_read(bcm, 0x0493)); - stack_save(bcm43xx_phy_read(bcm, 0x04A1)); - stack_save(bcm43xx_phy_read(bcm, 0x04A0)); - stack_save(bcm43xx_phy_read(bcm, 0x04A2)); - stack_save(bcm43xx_phy_read(bcm, 0x048A)); - stack_save(bcm43xx_phy_read(bcm, 0x04A8)); - stack_save(bcm43xx_phy_read(bcm, 0x04AB)); + phy_stacksave(0x0033); + phy_stacksave(0x04A7); + phy_stacksave(0x04A3); + phy_stacksave(0x04A9); + phy_stacksave(0x04AA); + phy_stacksave(0x04AC); + phy_stacksave(0x0493); + phy_stacksave(0x04A1); + phy_stacksave(0x04A0); + phy_stacksave(0x04A2); + phy_stacksave(0x048A); + phy_stacksave(0x04A8); + phy_stacksave(0x04AB); + if (phy->rev == 2) { + phy_stacksave(0x04AD); + phy_stacksave(0x04AE); + } else if (phy->rev >= 3) { + phy_stacksave(0x04AD); + phy_stacksave(0x0415); + phy_stacksave(0x0416); + phy_stacksave(0x0417); + ilt_stacksave(0x1A00 + 0x2); + ilt_stacksave(0x1A00 + 0x3); + } + phy_stacksave(0x042B); + phy_stacksave(0x048C); bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & 0xEFFF); + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) + & ~0x1000); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xEFFF) | 0x0002); + (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) + & 0xFFFC) | 0x0002); - bcm43xx_phy_write(bcm, 0x04A7, 0x0800); - bcm43xx_phy_write(bcm, 0x04A3, 0x287A); - bcm43xx_phy_write(bcm, 0x04A9, 0x2027); - bcm43xx_phy_write(bcm, 0x0493, 0x32F5); - bcm43xx_phy_write(bcm, 0x04AA, 0x2027); - bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); + bcm43xx_phy_write(bcm, 0x0033, 0x0800); + bcm43xx_phy_write(bcm, 0x04A3, 0x2027); + bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8); + bcm43xx_phy_write(bcm, 0x0493, 0x287A); + bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8); + bcm43xx_phy_write(bcm, 0x04AC, 0x287A); bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFC0) | 0x001A); - if (bcm->current_core->rev < 5) { - bcm43xx_phy_write(bcm, 0x0406, 0x280D); - } else { - bcm43xx_phy_write(bcm, 0x04C0, 0x0640); + (bcm43xx_phy_read(bcm, 0x04A0) + & 0xFFC0) | 0x001A); + bcm43xx_phy_write(bcm, 0x04A7, 0x000D); + + if (phy->rev < 2) { + bcm43xx_phy_write(bcm, 0x0406, 0xFF0D); + } else if (phy->rev == 2) { + bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF); bcm43xx_phy_write(bcm, 0x04C1, 0x00A9); + } else { + bcm43xx_phy_write(bcm, 0x04C0, 0x00C1); + bcm43xx_phy_write(bcm, 0x04C1, 0x0059); } bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0FF) | 0x1800); + (bcm43xx_phy_read(bcm, 0x04A1) + & 0xC0FF) | 0x1800); bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) & 0xFFC0) | 0x0016); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0900); - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0700); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x000D); + (bcm43xx_phy_read(bcm, 0x04A1) + & 0xFFC0) | 0x0015); bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) & 0xCFFF) | 0x1000); + (bcm43xx_phy_read(bcm, 0x04A8) + & 0xCFFF) | 0x1000); bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) & 0xF0FF) | 0x0A00); + (bcm43xx_phy_read(bcm, 0x04A8) + & 0xF0FF) | 0x0A00); bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xCFFF) | 0x1000); + (bcm43xx_phy_read(bcm, 0x04AB) + & 0xCFFF) | 0x1000); bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xF0FF) | 0x0800); + (bcm43xx_phy_read(bcm, 0x04AB) + & 0xF0FF) | 0x0800); bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFCF) | 0x0010); + (bcm43xx_phy_read(bcm, 0x04AB) + & 0xFFCF) | 0x0010); bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFF0) | 0x0006); + (bcm43xx_phy_read(bcm, 0x04AB) + & 0xFFF0) | 0x0005); + bcm43xx_phy_write(bcm, 0x04A8, + (bcm43xx_phy_read(bcm, 0x04A8) + & 0xFFCF) | 0x0010); + bcm43xx_phy_write(bcm, 0x04A8, + (bcm43xx_phy_read(bcm, 0x04A8) + & 0xFFF0) | 0x0006); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) + & 0xF0FF) | 0x0800); + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) + & 0xF0FF) | 0x0500); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) + & 0xFFF0) | 0x000B); + if (phy->rev >= 3) { + bcm43xx_phy_write(bcm, 0x048A, + bcm43xx_phy_read(bcm, 0x048A) + & ~0x8000); + bcm43xx_phy_write(bcm, 0x0415, + (bcm43xx_phy_read(bcm, 0x0415) + & 0x8000) | 0x36D8); + bcm43xx_phy_write(bcm, 0x0416, + (bcm43xx_phy_read(bcm, 0x0416) + & 0x8000) | 0x36D8); + bcm43xx_phy_write(bcm, 0x0417, + (bcm43xx_phy_read(bcm, 0x0417) + & 0xFE00) | 0x016D); + } else { + bcm43xx_phy_write(bcm, 0x048A, + bcm43xx_phy_read(bcm, 0x048A) + | 0x1000); + bcm43xx_phy_write(bcm, 0x048A, + (bcm43xx_phy_read(bcm, 0x048A) + & 0x9FFF) | 0x2000); + tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET); + if (!(tmp32 & 0x800)) { + tmp32 |= 0x800; + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + tmp32); + } + } + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) + | 0x0800); + } + bcm43xx_phy_write(bcm, 0x048C, + (bcm43xx_phy_read(bcm, 0x048C) + & 0xF0FF) | 0x0200); + if (phy->rev == 2) { + bcm43xx_phy_write(bcm, 0x04AE, + (bcm43xx_phy_read(bcm, 0x04AE) + & 0xFF00) | 0x007F); + bcm43xx_phy_write(bcm, 0x04AD, + (bcm43xx_phy_read(bcm, 0x04AD) + & 0x00FF) | 0x1300); + } else if (phy->rev >= 6) { + bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F); + bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F); + bcm43xx_phy_write(bcm, 0x04AD, + bcm43xx_phy_read(bcm, 0x04AD) + & 0x00FF); + } bcm43xx_calc_nrssi_slope(bcm); break; default: @@ -1055,9 +1194,8 @@ bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - int i = 0; - u16 *stack = radio->interfstack; - u16 tmp, flipped; + u32 tmp32; + u32 *stack = radio->interfstack; switch (mode) { case BCM43xx_RADIO_INTERFMODE_NONWLAN: @@ -1065,71 +1203,80 @@ bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000); break; } - tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); - flipped = flip_4bit(tmp); - if ((flipped >> 1) >= 0x000C) - tmp = flipped + 3; - tmp = flip_4bit(tmp); - bcm43xx_radio_write16(bcm, 0x0078, tmp << 1); - + phy_stackrestore(0x0078); bcm43xx_calc_nrssi_threshold(bcm); - - if (bcm->current_core->rev < 5) { - bcm43xx_phy_write(bcm, 0x0406, stack_restore()); - } else { - bcm43xx_phy_write(bcm, 0x04C0, stack_restore()); - bcm43xx_phy_write(bcm, 0x04C1, stack_restore()); - } + phy_stackrestore(0x0406); bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); - - if (!bcm->bad_frames_preempt) + if (!bcm->bad_frames_preempt) { bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & ~(1 << 11)); + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) + & ~(1 << 11)); + } bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); - bcm43xx_phy_write(bcm, 0x04A0, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A1, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A2, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A8, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AB, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A7, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A3, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A9, stack_restore()); - bcm43xx_phy_write(bcm, 0x0493, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AA, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AC, stack_restore()); + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000); + phy_stackrestore(0x04A0); + phy_stackrestore(0x04A1); + phy_stackrestore(0x04A2); + phy_stackrestore(0x04A8); + phy_stackrestore(0x04AB); + phy_stackrestore(0x04A7); + phy_stackrestore(0x04A3); + phy_stackrestore(0x04A9); + phy_stackrestore(0x0493); + phy_stackrestore(0x04AA); + phy_stackrestore(0x04AC); break; case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - if (bcm43xx_phy_read(bcm, 0x0033) != 0x0800) + if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800)) break; radio->aci_enable = 0; - bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, stack_restore()); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, stack_restore()); - if (bcm->current_core->rev < 5) { - bcm43xx_phy_write(bcm, 0x0406, stack_restore()); - } else { - bcm43xx_phy_write(bcm, 0x04C0, stack_restore()); - bcm43xx_phy_write(bcm, 0x04C1, stack_restore()); + phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD); + phy_stackrestore(BCM43xx_PHY_G_CRS); + phy_stackrestore(0x0033); + phy_stackrestore(0x04A3); + phy_stackrestore(0x04A9); + phy_stackrestore(0x0493); + phy_stackrestore(0x04AA); + phy_stackrestore(0x04AC); + phy_stackrestore(0x04A0); + phy_stackrestore(0x04A7); + if (phy->rev >= 2) { + phy_stackrestore(0x04C0); + phy_stackrestore(0x04C1); + } else + phy_stackrestore(0x0406); + phy_stackrestore(0x04A1); + phy_stackrestore(0x04AB); + phy_stackrestore(0x04A8); + if (phy->rev == 2) { + phy_stackrestore(0x04AD); + phy_stackrestore(0x04AE); + } else if (phy->rev >= 3) { + phy_stackrestore(0x04AD); + phy_stackrestore(0x0415); + phy_stackrestore(0x0416); + phy_stackrestore(0x0417); + ilt_stackrestore(0x1A00 + 0x2); + ilt_stackrestore(0x1A00 + 0x3); + } + phy_stackrestore(0x04A2); + phy_stackrestore(0x04A8); + phy_stackrestore(0x042B); + phy_stackrestore(0x048C); + tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET); + if (tmp32 & 0x800) { + tmp32 &= ~0x800; + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + tmp32); } - bcm43xx_phy_write(bcm, 0x0033, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A7, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A3, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A9, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AA, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AC, stack_restore()); - bcm43xx_phy_write(bcm, 0x0493, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A1, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A0, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A2, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A8, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AB, stack_restore()); - bcm43xx_calc_nrssi_slope(bcm); break; default: @@ -1137,8 +1284,12 @@ bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, } } -#undef stack_save -#undef stack_restore +#undef phy_stacksave +#undef phy_stackrestore +#undef radio_stacksave +#undef radio_stackrestore +#undef ilt_stacksave +#undef ilt_stackrestore int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode) -- cgit v1.2.3-59-g8ed1b From cf017e1b6f625978288e2cd8ede04f8185b97c08 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 22 Mar 2006 17:58:47 +0100 Subject: [PATCH] bcm43xx: fix nrssi_threshold calculation. patch by doctorzoidberg. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 72 +++++++++++++--------------- 1 file changed, 33 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 63aae43ba838..af5c0bff1696 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -782,41 +782,30 @@ void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - s16 threshold; + s32 threshold; s32 a, b; - int tmp; s16 tmp16; u16 tmp_u16; switch (phy->type) { case BCM43xx_PHYTYPE_B: { - int radiotype = 0; - - if (phy->rev < 2) - return; if (radio->version != 0x2050) return; if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) return; - tmp = radio->revision; - if ((radio->manufact == 0x175 && tmp == 5) || - (radio->manufact == 0x17F && (tmp == 3 || tmp == 4))) - radiotype = 1; - - if (radiotype == 1) { + if (radio->revision >= 6) { + threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32; + threshold += 20 * (radio->nrssi[0] + 1); + threshold /= 40; + } else threshold = radio->nrssi[1] - 5; - } else { - threshold = 40 * radio->nrssi[0]; - threshold += 33 * (radio->nrssi[1] - radio->nrssi[0]); - threshold += 20; - threshold /= 10; - } + threshold = limit_value(threshold, 0, 0x3E); bcm43xx_phy_read(bcm, 0x0020); /* dummy read */ bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C); - if (radiotype == 1) { + if (radio->revision >= 6) { bcm43xx_phy_write(bcm, 0x0087, 0x0E0D); bcm43xx_phy_write(bcm, 0x0086, 0x0C0B); bcm43xx_phy_write(bcm, 0x0085, 0x0A09); @@ -844,33 +833,38 @@ void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) & 0xF000) | 0x0AED); } } else { - tmp = radio->interfmode; - if (tmp == BCM43xx_RADIO_INTERFMODE_NONWLAN) { - a = -13; - b = -17; - } else if (tmp == BCM43xx_RADIO_INTERFMODE_NONE && - !radio->aci_enable) { - a = -13; - b = -10; + if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) { + a = 0xE; + b = 0xA; + } else if (!radio->aci_wlan_automatic && radio->aci_enable) { + a = 0x13; + b = 0x12; } else { - a = -8; - b = -9; + a = 0xE; + b = 0x11; } - a += 0x1B; - a *= radio->nrssi[1] - radio->nrssi[0]; - a += radio->nrssi[0] * 0x40; - a /= 64; - b += 0x1B; - b *= radio->nrssi[1] - radio->nrssi[0]; - b += radio->nrssi[0] * 0x40; - b /= 64; + a = a * (radio->nrssi[1] - radio->nrssi[0]); + a += (radio->nrssi[0] << 6); + if (a < 32) + a += 31; + else + a += 32; + a = a >> 6; a = limit_value(a, -31, 31); + + b = b * (radio->nrssi[1] - radio->nrssi[0]); + b += (radio->nrssi[0] << 6); + if (b < 32) + b += 31; + else + b += 32; + b = b >> 6; b = limit_value(b, -31, 31); tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000; - tmp_u16 |= ((u32)a & 0x003F); - tmp_u16 |= (((u32)b & 0x003F) << 6); + tmp_u16 |= ((u32)b & 0x0000003F); + tmp_u16 |= (((u32)a & 0x0000003F) << 6); bcm43xx_phy_write(bcm, 0x048A, tmp_u16); } break; -- cgit v1.2.3-59-g8ed1b From 72fb851e971a416f47ad0a3ffca7342a424af37a Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 22 Mar 2006 18:10:19 +0100 Subject: [PATCH] bcm43xx: add useless and broken statistics stuff. People seem to want it. well... Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 2 ++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 3 ++ drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 52 ++++++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 57fcaafcf7dd..ae0fe5cf1d44 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -621,6 +621,8 @@ struct bcm43xx_noise_calculation { struct bcm43xx_stats { u8 link_quality; + u8 noise; + struct iw_statistics wstats; /* Store the last TX/RX times here for updating the leds. */ unsigned long last_tx; unsigned long last_rx; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index e680d2acc44b..15deaa508e55 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1539,6 +1539,7 @@ static void handle_irq_noise(struct bcm43xx_private *bcm) average *= 125; average += 64; average /= 128; + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C); tmp = (tmp / 128) & 0x1F; if (tmp >= 8) @@ -1550,6 +1551,8 @@ static void handle_irq_noise(struct bcm43xx_private *bcm) else average -= 48; +/* FIXME: This is wrong, but people want fancy stats. well... */ +bcm->stats.noise = average; if (average > -65) bcm->stats.link_quality = 0; else if (average > -75) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 651ba6054957..e92963402852 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -244,13 +244,13 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, range->max_qual.qual = 100; /* TODO: Real max RSSI */ - range->max_qual.level = 0; - range->max_qual.noise = 0; + range->max_qual.level = 3; + range->max_qual.noise = 100; range->max_qual.updated = 7; range->avg_qual.qual = 70; - range->avg_qual.level = 0; - range->avg_qual.noise = 0; + range->avg_qual.level = 2; + range->avg_qual.noise = 40; range->avg_qual.updated = 7; range->min_rts = BCM43xx_MIN_RTS_THRESHOLD; @@ -875,6 +875,49 @@ out: return err; } +/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */ + +static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); + struct iw_statistics *wstats; + + wstats = &bcm->stats.wstats; + if (!mac->associated) { + wstats->miss.beacon = 0; +// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here? + wstats->discard.retries = 0; +// bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question + wstats->discard.nwid = 0; +// bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto + wstats->discard.code = 0; +// bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here + wstats->discard.fragment = 0; + wstats->discard.misc = 0; + wstats->qual.qual = 0; + wstats->qual.level = 0; + wstats->qual.noise = 0; + wstats->qual.updated = 7; + wstats->qual.updated |= IW_QUAL_NOISE_INVALID | + IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; + return wstats; + } + /* fill in the real statistics when iface associated */ + wstats->qual.qual = 100; // TODO: get the real signal quality + wstats->qual.level = 3 - bcm->stats.link_quality; + wstats->qual.noise = bcm->stats.noise; + wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | + IW_QUAL_NOISE_UPDATED; + wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable; + wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded; + wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa; + wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments; + wstats->discard.misc = 0; // FIXME + wstats->miss.beacon = 0; // FIXME + return wstats; +} + #ifdef WX # undef WX @@ -1010,6 +1053,7 @@ const struct iw_handler_def bcm43xx_wx_handlers_def = { .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args), .private = bcm43xx_priv_wx_handlers, .private_args = bcm43xx_priv_wx_args, + .get_wireless_stats = bcm43xx_get_wireless_stats, }; /* vim: set ts=8 sw=8 sts=8: */ -- cgit v1.2.3-59-g8ed1b From 04b98f71e2e3facc15e73b7e3ae9516ecb737375 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 25 Mar 2006 15:37:53 +0100 Subject: [PATCH] bcm43xx: get rid of "/* vim: ..." lines at the end of several files. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 2 -- 8 files changed, 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index f73d36b8e0f4..d2c3401e9b70 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -497,5 +497,3 @@ void bcm43xx_printk_bitdump(const unsigned char *data, } printk("\n"); } - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 9c64438b767f..18928acedd7c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -968,5 +968,3 @@ void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) & ~BCM43xx_DMA_TXCTRL_SUSPEND); bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1); } - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index c8f5ad75d2a6..4b2c02c0b31e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -291,5 +291,3 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) } bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); } - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 15deaa508e55..281db642bd55 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3956,5 +3956,3 @@ static void __exit bcm43xx_exit(void) module_init(bcm43xx_init) module_exit(bcm43xx_exit) - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 5b6f0a84d017..c59ddd40680d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -604,5 +604,3 @@ data_ready: } bcm43xx_rx(queue->bcm, skb, rxhdr); } - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index 35c3c9704c3c..c44d890b949b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -320,5 +320,3 @@ void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm) device_remove_file(dev, &sysfs->attr_interfmode); device_remove_file(dev, &sysfs->attr_sprom); } - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index e92963402852..e72be32bda75 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -1055,5 +1055,3 @@ const struct iw_handler_def bcm43xx_wx_handlers_def = { .private_args = bcm43xx_priv_wx_args, .get_wireless_stats = bcm43xx_get_wireless_stats, }; - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c index c4809da8e9c7..9c37478c80d9 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c @@ -577,5 +577,3 @@ int bcm43xx_rx(struct bcm43xx_private *bcm, return err; } - -/* vim: set ts=8 sw=8 sts=8: */ -- cgit v1.2.3-59-g8ed1b From d1ca6c4ff6714826acb1a434e5d3862984eb26d5 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 25 Mar 2006 15:43:18 +0100 Subject: [PATCH] bcm43xx: fix "include" issues on some platforms. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 3 +-- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 18928acedd7c..bad5374b81b9 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -34,11 +34,10 @@ #include "bcm43xx_power.h" #include "bcm43xx_xmit.h" -#include +#include #include #include #include -#include static inline int free_slots(struct bcm43xx_dmaring *ring) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 281db642bd55..29df4f844c9b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "bcm43xx.h" -- cgit v1.2.3-59-g8ed1b From b5e868edbeaa5fd832d42563195c0da00edfd3c9 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 25 Mar 2006 16:27:32 +0100 Subject: [PATCH] bcm43xx: remove some compilerwarnings. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 1 - drivers/net/wireless/bcm43xx/bcm43xx_main.c | 10 ++++-- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 55 ----------------------------- drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 7 ++-- 4 files changed, 13 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index bad5374b81b9..c3681b8f09b4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -787,7 +787,6 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, struct bcm43xx_xmitstatus *status) { - struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); struct bcm43xx_dmaring *ring; struct bcm43xx_dmadesc *desc; struct bcm43xx_dmadesc_meta *meta; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 29df4f844c9b..ac9a8dd1ab8f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -404,6 +404,8 @@ static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm) bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i))); } +//FIXME: Well, we should probably call them from somewhere. +#if 0 static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) { /* slot_time is in usec. */ @@ -422,8 +424,12 @@ static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm) { bcm43xx_set_slot_time(bcm, 20); } +#endif -//FIXME: rename this func? +/* FIXME: To get the MAC-filter working, we need to implement the + * following functions (and rename them :) + */ +#if 0 static void bcm43xx_disassociate(struct bcm43xx_private *bcm) { bcm43xx_mac_suspend(bcm); @@ -451,7 +457,6 @@ static void bcm43xx_disassociate(struct bcm43xx_private *bcm) bcm43xx_mac_enable(bcm); } -//FIXME: rename this func? static void bcm43xx_associate(struct bcm43xx_private *bcm, const u8 *mac) { @@ -462,6 +467,7 @@ static void bcm43xx_associate(struct bcm43xx_private *bcm, bcm43xx_write_mac_bssid_templates(bcm); bcm43xx_mac_enable(bcm); } +#endif /* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. * Returns the _previously_ enabled IRQ mask. diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index e72be32bda75..3daee828ef4b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -106,7 +106,6 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct ieee80211softmac_device *softmac = bcm->softmac; unsigned long flags; u8 channel; int freq; @@ -205,24 +204,6 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev, return 0; } -static int bcm43xx_wx_set_sensitivity(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - -static int bcm43xx_wx_get_sensitivity(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, struct iw_request_info *info, union iwreq_data *data, @@ -517,24 +498,6 @@ out_unlock: return err; } -static int bcm43xx_wx_set_retry(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - -static int bcm43xx_wx_get_retry(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - static int bcm43xx_wx_set_encoding(struct net_device *net_dev, struct iw_request_info *info, union iwreq_data *data, @@ -587,24 +550,6 @@ static int bcm43xx_wx_get_encodingext(struct net_device *net_dev, return err; } -static int bcm43xx_wx_set_power(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - -static int bcm43xx_wx_get_power(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, struct iw_request_info *info, union iwreq_data *data, diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c index 9c37478c80d9..d8ece28c079f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c @@ -215,7 +215,7 @@ static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy, u8 fallback_bitrate; int ofdm_modulation; int fallback_ofdm_modulation; - u8 *sa, *da; +// u8 *sa, *da; u16 flen; //FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr); @@ -267,7 +267,7 @@ assert(dur); //printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3)); //printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da)); memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME! - memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN); +// memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN); *flags |= BCM43xx_TXHDRFLAG_RTSCTS; *flags |= BCM43xx_TXHDRFLAG_RTS; @@ -439,6 +439,8 @@ static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, return (s8)tmp; } +//TODO +#if 0 static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, u8 in_rssi) { @@ -453,6 +455,7 @@ static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, return ret; } +#endif int bcm43xx_rx(struct bcm43xx_private *bcm, struct sk_buff *skb, -- cgit v1.2.3-59-g8ed1b From 8afceb1e6a3b6361c7c2456ef488ee9c6db7b370 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 25 Mar 2006 17:04:41 +0100 Subject: [PATCH] bcm43xx: fix the remaining sparse warnings. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4 ++-- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index ac9a8dd1ab8f..7c1d72fc6289 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2509,7 +2509,7 @@ error: return -ENODEV; } -void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy) +static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy) { /* Initialize a "phyinfo" structure. The structure is already * zeroed out. @@ -2521,7 +2521,7 @@ void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy) spin_lock_init(&phy->lock); } -void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio) +static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio) { /* Initialize a "radioinfo" structure. The structure is already * zeroed out. diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 054c64e462fb..4ab17a7f7e91 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -1057,9 +1057,14 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x002F, 0x0202); } - if ((bcm->sprom.boardflags & BCM43xx_BFL_RSSI) == 0) { - FIXME();//FIXME: 0x7FFFFFFF should be 16-bit ! - bcm43xx_nrssi_hw_update(bcm, (u16)0x7FFFFFFF); + if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) { + /* The specs state to update the NRSSI LT with + * the value 0x7FFFFFFF here. I think that is some weird + * compiler optimization in the original driver. + * Essentially, what we do here is resetting all NRSSI LT + * entries to -32 (see the limit_value() in nrssi_hw_update()) + */ + bcm43xx_nrssi_hw_update(bcm, 0xFFFF); bcm43xx_calc_nrssi_threshold(bcm); } else if (phy->connected) { if (radio->nrssi[0] == -1000) { -- cgit v1.2.3-59-g8ed1b From adc40e9796d03d56e99bdac62492492a1098124b Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 25 Mar 2006 20:36:57 +0100 Subject: [PATCH] bcm43xx: sync GPHY init with the specs. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 5 + drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 275 +++++++++++++++++++++++++--- 3 files changed, 255 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index ae0fe5cf1d44..dcadd295de4f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -495,6 +495,10 @@ struct bcm43xx_phyinfo { const s8 *tssi2dbm; /* idle TSSI value */ s8 idle_tssi; + + /* Values from bcm43xx_calc_loopback_gain() */ + u16 loopback_gain[2]; + /* PHY lock for core.rev < 3 * This lock is only used by bcm43xx_phy_{un}lock() */ @@ -674,6 +678,7 @@ struct bcm43xx_private { u16 chip_id; u8 chip_rev; + u8 chip_package; struct bcm43xx_sprominfo sprom; #define BCM43xx_NR_LEDS 4 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 7c1d72fc6289..2b7ef9b46ccd 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -570,6 +570,7 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm); radio->radio_atten = bcm43xx_default_radio_attenuation(bcm); radio->txctl1 = bcm43xx_default_txctl1(bcm); + radio->txctl2 = 0xFFFF; if (phy->type == BCM43xx_PHYTYPE_A) radio->txpower_desired = bcm->sprom.maxpower_aphy; else @@ -2635,7 +2636,8 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) } bcm->chip_id = chip_id_16; - bcm->chip_rev = (chip_id_32 & 0x000f0000) >> 16; + bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16; + bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20; dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n", bcm->chip_id, bcm->chip_rev); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 4ab17a7f7e91..0a66f43ca0c0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -994,12 +994,205 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) bcm43xx_write16(bcm, 0x03E6, 0x0); } +static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + u16 backup_phy[15]; + u16 backup_radio[3]; + u16 backup_bband; + u16 i; + u16 loop1_cnt, loop1_done, loop1_omitted; + u16 loop2_done; + + backup_phy[0] = bcm43xx_phy_read(bcm, 0x0429); + backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001); + backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811); + backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812); + backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814); + backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815); + backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A); + backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059); + backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058); + backup_phy[9] = bcm43xx_phy_read(bcm, 0x000A); + backup_phy[10] = bcm43xx_phy_read(bcm, 0x0003); + backup_phy[11] = bcm43xx_phy_read(bcm, 0x080F); + backup_phy[12] = bcm43xx_phy_read(bcm, 0x0810); + backup_phy[13] = bcm43xx_phy_read(bcm, 0x002B); + backup_phy[14] = bcm43xx_phy_read(bcm, 0x0015); + bcm43xx_phy_read(bcm, 0x002D); /* dummy read */ + backup_bband = radio->baseband_atten; + backup_radio[0] = bcm43xx_radio_read16(bcm, 0x0052); + backup_radio[1] = bcm43xx_radio_read16(bcm, 0x0043); + backup_radio[2] = bcm43xx_radio_read16(bcm, 0x007A); + + bcm43xx_phy_write(bcm, 0x0429, + bcm43xx_phy_read(bcm, 0x0429) & 0x3FFF); + bcm43xx_phy_write(bcm, 0x0001, + bcm43xx_phy_read(bcm, 0x0001) & 0x8000); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x0002); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) & 0xFFFD); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x0001); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE); + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0001); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0002); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x000C); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) | 0x000C); + + bcm43xx_phy_write(bcm, 0x0811, + (bcm43xx_phy_read(bcm, 0x0811) + & 0xFFCF) | 0x0030); + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) + & 0xFFCF) | 0x0010); + + bcm43xx_phy_write(bcm, 0x005A, 0x0780); + bcm43xx_phy_write(bcm, 0x0059, 0xC810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + if (phy->version == 0) { + bcm43xx_phy_write(bcm, 0x0003, 0x0122); + } else { + bcm43xx_phy_write(bcm, 0x000A, + bcm43xx_phy_read(bcm, 0x000A) + | 0x2000); + } + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0004); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); + bcm43xx_phy_write(bcm, 0x0003, + (bcm43xx_phy_read(bcm, 0x0003) + & 0xFF9F) | 0x0040); + if (radio->version == 0x2050 && radio->revision == 2) { + bcm43xx_radio_write16(bcm, 0x0052, 0x0000); + bcm43xx_radio_write16(bcm, 0x0043, + (bcm43xx_radio_read16(bcm, 0x0043) + & 0xFFF0) | 0x0009); + loop1_cnt = 9; + } else if (radio->revision == 8) { + bcm43xx_radio_write16(bcm, 0x0043, 0x000F); + loop1_cnt = 15; + } else + loop1_cnt = 0; + + bcm43xx_phy_set_baseband_attenuation(bcm, 11); + + if (phy->rev >= 3) + bcm43xx_phy_write(bcm, 0x080F, 0xC020); + else + bcm43xx_phy_write(bcm, 0x080F, 0x8020); + bcm43xx_phy_write(bcm, 0x0810, 0x0000); + + bcm43xx_phy_write(bcm, 0x002B, + (bcm43xx_phy_read(bcm, 0x002B) + & 0xFFC0) | 0x0001); + bcm43xx_phy_write(bcm, 0x002B, + (bcm43xx_phy_read(bcm, 0x002B) + & 0xC0FF) | 0x0800); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x0100); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF); + if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) { + if (phy->rev >= 7) { + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) + | 0x0800); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) + | 0x8000); + } + } + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) + & 0x00F7); + + for (i = 0; i < loop1_cnt; i++) { + bcm43xx_radio_write16(bcm, 0x0043, loop1_cnt); + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) + & 0xF0FF) | (i << 8)); + bcm43xx_phy_write(bcm, 0x0015, + (bcm43xx_phy_read(bcm, 0x0015) + & 0x0FFF) | 0xA000); + bcm43xx_phy_write(bcm, 0x0015, + (bcm43xx_phy_read(bcm, 0x0015) + & 0x0FFF) | 0xF000); + udelay(20); + if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC) + break; + } + loop1_done = i; + loop1_omitted = loop1_cnt - loop1_done; + + loop2_done = 0; + if (loop1_done >= 8) { + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) + | 0x0030); + for (i = loop1_done - 8; i < 16; i++) { + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) + & 0xF0FF) | (i << 8)); + bcm43xx_phy_write(bcm, 0x0015, + (bcm43xx_phy_read(bcm, 0x0015) + & 0x0FFF) | 0xA000); + bcm43xx_phy_write(bcm, 0x0015, + (bcm43xx_phy_read(bcm, 0x0015) + & 0x0FFF) | 0xF000); + udelay(20); + if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC) + break; + } + } + + bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]); + bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]); + bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]); + bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]); + bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]); + bcm43xx_phy_write(bcm, 0x000A, backup_phy[9]); + bcm43xx_phy_write(bcm, 0x0003, backup_phy[10]); + bcm43xx_phy_write(bcm, 0x080F, backup_phy[11]); + bcm43xx_phy_write(bcm, 0x0810, backup_phy[12]); + bcm43xx_phy_write(bcm, 0x002B, backup_phy[13]); + bcm43xx_phy_write(bcm, 0x0015, backup_phy[14]); + + bcm43xx_phy_set_baseband_attenuation(bcm, backup_bband); + + bcm43xx_radio_write16(bcm, 0x0052, backup_radio[0]); + bcm43xx_radio_write16(bcm, 0x0043, backup_radio[1]); + bcm43xx_radio_write16(bcm, 0x007A, backup_radio[2]); + + bcm43xx_phy_write(bcm, 0x0811, backup_phy[2] | 0x0003); + udelay(10); + bcm43xx_phy_write(bcm, 0x0811, backup_phy[2]); + bcm43xx_phy_write(bcm, 0x0812, backup_phy[3]); + bcm43xx_phy_write(bcm, 0x0429, backup_phy[0]); + bcm43xx_phy_write(bcm, 0x0001, backup_phy[1]); + + phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11; + phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2; +} + static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 tmp; - + if (phy->rev == 1) bcm43xx_phy_initb5(bcm); else if (phy->rev >= 2 && phy->rev <= 7) @@ -1015,47 +1208,63 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) else if (phy->rev >= 3) bcm43xx_phy_write(bcm, 0x0811, 0x0400); bcm43xx_phy_write(bcm, 0x0015, 0x00C0); - tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; - if (tmp == 3) { - bcm43xx_phy_write(bcm, 0x04C2, 0x1816); - bcm43xx_phy_write(bcm, 0x04C3, 0x8606); - } else if (tmp == 4 || tmp == 5) { - bcm43xx_phy_write(bcm, 0x04C2, 0x1816); - bcm43xx_phy_write(bcm, 0x04C3, 0x8006); - bcm43xx_phy_write(bcm, 0x04CC, (bcm43xx_phy_read(bcm, 0x04CC) - & 0x00FF) | 0x1F00); + if (phy->connected) { + tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; + if (tmp < 6) { + bcm43xx_phy_write(bcm, 0x04C2, 0x1816); + bcm43xx_phy_write(bcm, 0x04C3, 0x8006); + if (tmp != 3) { + bcm43xx_phy_write(bcm, 0x04CC, + (bcm43xx_phy_read(bcm, 0x04CC) + & 0x00FF) | 0x1F00); + } + } } } - if (radio->revision <= 3 && phy->connected) + if (phy->rev < 3 && phy->connected) bcm43xx_phy_write(bcm, 0x047E, 0x0078); - if (radio->revision >= 6 && radio->revision <= 8) { + if (phy->rev >= 6 && phy->rev <= 8) { bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080); bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004); } - if (radio->initval == 0xFFFF) { - radio->initval = bcm43xx_radio_init2050(bcm); + if (phy->rev >= 2 && phy->connected) + bcm43xx_calc_loopback_gain(bcm); + if (radio->revision != 8) { + if (radio->initval == 0xFFFF) + radio->initval = bcm43xx_radio_init2050(bcm); + else + bcm43xx_radio_write16(bcm, 0x0078, radio->initval); + } + if (radio->txctl2 == 0xFFFF) { bcm43xx_phy_lo_g_measure(bcm); } else { - bcm43xx_radio_write16(bcm, 0x0078, radio->initval); - bcm43xx_radio_write16(bcm, 0x0052, - (bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0) - | radio->txctl2); - } - - if (phy->connected) { - bcm43xx_phy_lo_adjust(bcm, 0); - bcm43xx_phy_write(bcm, 0x080F, 0x8078); - + if (radio->version == 0x2050 && radio->revision == 8) { + //FIXME + } else { + bcm43xx_radio_write16(bcm, 0x0052, + (bcm43xx_radio_read16(bcm, 0x0052) + & 0xFFF0) | radio->txctl1); + } + if (phy->rev >= 6) { + /* + bcm43xx_phy_write(bcm, 0x0036, + (bcm43xx_phy_read(bcm, 0x0036) + & 0xF000) | (FIXME << 12)); + */ + } if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) - bcm43xx_phy_write(bcm, 0x002E, 0x807F); - else bcm43xx_phy_write(bcm, 0x002E, 0x8075); - + else + bcm43xx_phy_write(bcm, 0x003E, 0x807F); if (phy->rev < 2) bcm43xx_phy_write(bcm, 0x002F, 0x0101); else bcm43xx_phy_write(bcm, 0x002F, 0x0202); } + if (phy->connected) { + bcm43xx_phy_lo_adjust(bcm, 0); + bcm43xx_phy_write(bcm, 0x080F, 0x8078); + } if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) { /* The specs state to update the NRSSI LT with @@ -1070,10 +1279,20 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) if (radio->nrssi[0] == -1000) { assert(radio->nrssi[1] == -1000); bcm43xx_calc_nrssi_slope(bcm); - } else + } else { + assert(radio->nrssi[1] != -1000); bcm43xx_calc_nrssi_threshold(bcm); + } } + if (radio->revision == 8) + bcm43xx_phy_write(bcm, 0x0805, 0x3230); bcm43xx_phy_init_pctl(bcm); + if (bcm->chip_id == 0x4306 && bcm->chip_package != 2) { + bcm43xx_phy_write(bcm, 0x0429, + bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF); + bcm43xx_phy_write(bcm, 0x04C3, + bcm43xx_phy_read(bcm, 0x04C3) & 0x7FFF); + } } static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) -- cgit v1.2.3-59-g8ed1b From ec483781fe98bba92e00f4428f8d69dd5e071246 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 27 Mar 2006 11:49:51 +0200 Subject: [PATCH] bcm43xx: don't set the channel on a device, which is down. Initial patch by David Woodhouse and Michael Marineau. Locking fix by me. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 2b7ef9b46ccd..c37371fc9e01 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3530,12 +3530,18 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, u8 channel) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct bcm43xx_radioinfo *radio; unsigned long flags; bcm43xx_lock_mmio(bcm, flags); - bcm43xx_mac_suspend(bcm); - bcm43xx_radio_selectchannel(bcm, channel, 0); - bcm43xx_mac_enable(bcm); + if (bcm->initialized) { + bcm43xx_mac_suspend(bcm); + bcm43xx_radio_selectchannel(bcm, channel, 0); + bcm43xx_mac_enable(bcm); + } else { + radio = bcm43xx_current_radio(bcm); + radio->initial_channel = channel; + } bcm43xx_unlock_mmio(bcm, flags); } -- cgit v1.2.3-59-g8ed1b From e4a9af98bb0fab13be6e3adbe108d565b790158a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 24 Mar 2006 17:56:19 +0100 Subject: [PATCH] PCMCIA_SPECTRUM must select FW_LOADER PCMCIA_SPECTRUM must select FW_LOADER. Reported by "Alexander E. Patrakov" . Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 9c01fb26c8f3..f85e30190008 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -404,6 +404,7 @@ config PCMCIA_HERMES config PCMCIA_SPECTRUM tristate "Symbol Spectrum24 Trilogy PCMCIA card support" depends on NET_RADIO && PCMCIA && HERMES + select FW_LOADER ---help--- This is a driver for 802.11b cards using RAM-loadable Symbol -- cgit v1.2.3-59-g8ed1b From 0073602544954002e35699477dc59cdd5e9112e3 Mon Sep 17 00:00:00 2001 From: Jean Tourrilhes Date: Fri, 24 Mar 2006 16:45:24 -0800 Subject: [PATCH] zd1201 wireless stat update The "dev->get_wireless_stats" field is deprecated and slowly be surely going away. Most drivers have been updated months ago. Actually, there is an annoying message for driver still using it, but it seems that user of zd1201 were not annoyed enough ;-) Signed-off-by: Jean Tourrilhes Signed-off-by: John W. Linville --- drivers/usb/net/zd1201.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c index fe9b60cd8d95..9b1e4ed1d07e 100644 --- a/drivers/usb/net/zd1201.c +++ b/drivers/usb/net/zd1201.c @@ -1736,6 +1736,7 @@ static const struct iw_handler_def zd1201_iw_handlers = { .standard = (iw_handler *)zd1201_iw_handler, .private = (iw_handler *)zd1201_private_handler, .private_args = (struct iw_priv_args *) zd1201_private_args, + .get_wireless_stats = zd1201_get_wireless_stats, }; static int zd1201_probe(struct usb_interface *interface, @@ -1796,7 +1797,6 @@ static int zd1201_probe(struct usb_interface *interface, zd->dev->open = zd1201_net_open; zd->dev->stop = zd1201_net_stop; zd->dev->get_stats = zd1201_get_stats; - zd->dev->get_wireless_stats = zd1201_get_wireless_stats; zd->dev->wireless_handlers = (struct iw_handler_def *)&zd1201_iw_handlers; zd->dev->hard_start_xmit = zd1201_hard_start_xmit; -- cgit v1.2.3-59-g8ed1b From 79058acaf5b6d4bcc3056382619de3ca9cebc62f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Mar 2006 21:24:54 -0800 Subject: [PATCH] hostap: Make hostap_tx_encrypt() static hostap_tx_encrypt() is used only inside hostap_80211_tx.c and there are no plans to use it elsewhere in the future either, so let's make it static. As a bonus, this should silence Coverity scanner from complaining about bogus FORWARD_NULL case (CID: 274). Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_80211.h | 2 -- drivers/net/wireless/hostap/hostap_80211_tx.c | 7 +++---- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h index 1fc72fe511e9..cc1ee7f4f5f8 100644 --- a/drivers/net/wireless/hostap/hostap_80211.h +++ b/drivers/net/wireless/hostap/hostap_80211.h @@ -92,8 +92,6 @@ void hostap_dump_rx_80211(const char *name, struct sk_buff *skb, void hostap_dump_tx_80211(const char *name, struct sk_buff *skb); int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev); int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev); -struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, - struct ieee80211_crypt_data *crypt); int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev); #endif /* HOSTAP_80211_H */ diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c index 4a85e63906f1..a881212e1fae 100644 --- a/drivers/net/wireless/hostap/hostap_80211_tx.c +++ b/drivers/net/wireless/hostap/hostap_80211_tx.c @@ -299,8 +299,8 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Called only from software IRQ */ -struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, - struct ieee80211_crypt_data *crypt) +static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, + struct ieee80211_crypt_data *crypt) { struct hostap_interface *iface; local_info_t *local; @@ -317,7 +317,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, } if (local->tkip_countermeasures && - crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) { + strcmp(crypt->ops->name, "TKIP") == 0) { hdr = (struct ieee80211_hdr_4addr *) skb->data; if (net_ratelimit()) { printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " @@ -535,5 +535,4 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev) EXPORT_SYMBOL(hostap_dump_tx_80211); -EXPORT_SYMBOL(hostap_tx_encrypt); EXPORT_SYMBOL(hostap_master_start_xmit); -- cgit v1.2.3-59-g8ed1b From cfa146e4be274fd04bfdb26b3c96cdfe81a43dc2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Mar 2006 21:24:55 -0800 Subject: [PATCH] hostap: Fix EAPOL frame encryption Fixed encrypted of EAPOL frames from wlan#ap interface (hostapd). This was broken when moving to use new frame control field defines in net/ieee80211.h. hostapd uses Protected flag, not protocol version (which was cleared in this function anyway). This fixes WPA group key handshake and re-authentication. http://hostap.epitest.fi/bugz/show_bug.cgi?id=126 Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_80211_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c index a881212e1fae..06a5214145e3 100644 --- a/drivers/net/wireless/hostap/hostap_80211_tx.c +++ b/drivers/net/wireless/hostap/hostap_80211_tx.c @@ -469,7 +469,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev) } if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt && - !(fc & IEEE80211_FCTL_VERS)) { + !(fc & IEEE80211_FCTL_PROTECTED)) { no_encrypt = 1; PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing " "unencrypted EAPOL frame\n", dev->name); -- cgit v1.2.3-59-g8ed1b From e041c683412d5bf44dc2b109053e3b837b71742d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 27 Mar 2006 01:16:30 -0800 Subject: [PATCH] Notifier chain update: API changes The kernel's implementation of notifier chains is unsafe. There is no protection against entries being added to or removed from a chain while the chain is in use. The issues were discussed in this thread: http://marc.theaimsgroup.com/?l=linux-kernel&m=113018709002036&w=2 We noticed that notifier chains in the kernel fall into two basic usage classes: "Blocking" chains are always called from a process context and the callout routines are allowed to sleep; "Atomic" chains can be called from an atomic context and the callout routines are not allowed to sleep. We decided to codify this distinction and make it part of the API. Therefore this set of patches introduces three new, parallel APIs: one for blocking notifiers, one for atomic notifiers, and one for "raw" notifiers (which is really just the old API under a new name). New kinds of data structures are used for the heads of the chains, and new routines are defined for registration, unregistration, and calling a chain. The three APIs are explained in include/linux/notifier.h and their implementation is in kernel/sys.c. With atomic and blocking chains, the implementation guarantees that the chain links will not be corrupted and that chain callers will not get messed up by entries being added or removed. For raw chains the implementation provides no guarantees at all; users of this API must provide their own protections. (The idea was that situations may come up where the assumptions of the atomic and blocking APIs are not appropriate, so it should be possible for users to handle these things in their own way.) There are some limitations, which should not be too hard to live with. For atomic/blocking chains, registration and unregistration must always be done in a process context since the chain is protected by a mutex/rwsem. Also, a callout routine for a non-raw chain must not try to register or unregister entries on its own chain. (This did happen in a couple of places and the code had to be changed to avoid it.) Since atomic chains may be called from within an NMI handler, they cannot use spinlocks for synchronization. Instead we use RCU. The overhead falls almost entirely in the unregister routine, which is okay since unregistration is much less frequent that calling a chain. Here is the list of chains that we adjusted and their classifications. None of them use the raw API, so for the moment it is only a placeholder. ATOMIC CHAINS ------------- arch/i386/kernel/traps.c: i386die_chain arch/ia64/kernel/traps.c: ia64die_chain arch/powerpc/kernel/traps.c: powerpc_die_chain arch/sparc64/kernel/traps.c: sparc64die_chain arch/x86_64/kernel/traps.c: die_chain drivers/char/ipmi/ipmi_si_intf.c: xaction_notifier_list kernel/panic.c: panic_notifier_list kernel/profile.c: task_free_notifier net/bluetooth/hci_core.c: hci_notifier net/ipv4/netfilter/ip_conntrack_core.c: ip_conntrack_chain net/ipv4/netfilter/ip_conntrack_core.c: ip_conntrack_expect_chain net/ipv6/addrconf.c: inet6addr_chain net/netfilter/nf_conntrack_core.c: nf_conntrack_chain net/netfilter/nf_conntrack_core.c: nf_conntrack_expect_chain net/netlink/af_netlink.c: netlink_chain BLOCKING CHAINS --------------- arch/powerpc/platforms/pseries/reconfig.c: pSeries_reconfig_chain arch/s390/kernel/process.c: idle_chain arch/x86_64/kernel/process.c idle_notifier drivers/base/memory.c: memory_chain drivers/cpufreq/cpufreq.c cpufreq_policy_notifier_list drivers/cpufreq/cpufreq.c cpufreq_transition_notifier_list drivers/macintosh/adb.c: adb_client_list drivers/macintosh/via-pmu.c sleep_notifier_list drivers/macintosh/via-pmu68k.c sleep_notifier_list drivers/macintosh/windfarm_core.c wf_client_list drivers/usb/core/notify.c usb_notifier_list drivers/video/fbmem.c fb_notifier_list kernel/cpu.c cpu_chain kernel/module.c module_notify_list kernel/profile.c munmap_notifier kernel/profile.c task_exit_notifier kernel/sys.c reboot_notifier_list net/core/dev.c netdev_chain net/decnet/dn_dev.c: dnaddr_chain net/ipv4/devinet.c: inetaddr_chain It's possible that some of these classifications are wrong. If they are, please let us know or submit a patch to fix them. Note that any chain that gets called very frequently should be atomic, because the rwsem read-locking used for blocking chains is very likely to incur cache misses on SMP systems. (However, if the chain's callout routines may sleep then the chain cannot be atomic.) The patch set was written by Alan Stern and Chandra Seetharaman, incorporating material written by Keith Owens and suggestions from Paul McKenney and Andrew Morton. [jes@sgi.com: restructure the notifier chain initialization macros] Signed-off-by: Alan Stern Signed-off-by: Chandra Seetharaman Signed-off-by: Jes Sorensen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/setup.c | 5 +- arch/arm/mach-omap1/board-netstar.c | 2 +- arch/arm/mach-omap1/board-voiceblue.c | 2 +- arch/i386/kernel/traps.c | 17 +- arch/ia64/kernel/traps.c | 6 +- arch/mips/lasat/setup.c | 3 +- arch/mips/sgi-ip22/ip22-reset.c | 2 +- arch/mips/sgi-ip32/ip32-reset.c | 2 +- arch/parisc/kernel/pdc_chassis.c | 3 +- arch/powerpc/kernel/setup_64.c | 3 +- arch/powerpc/kernel/traps.c | 16 +- arch/powerpc/platforms/pseries/reconfig.c | 10 +- arch/ppc/platforms/prep_setup.c | 2 +- arch/s390/kernel/process.c | 11 +- arch/sparc64/kernel/traps.c | 17 +- arch/um/drivers/mconsole_kern.c | 3 +- arch/um/kernel/um_arch.c | 3 +- arch/x86_64/kernel/process.c | 17 +- arch/x86_64/kernel/traps.c | 18 +- arch/xtensa/platform-iss/setup.c | 2 +- drivers/base/memory.c | 8 +- drivers/char/ipmi/ipmi_msghandler.c | 4 +- drivers/char/ipmi/ipmi_si_intf.c | 7 +- drivers/char/ipmi/ipmi_watchdog.c | 6 +- drivers/cpufreq/cpufreq.c | 61 +++--- drivers/firmware/dcdbas.c | 19 +- drivers/macintosh/adb.c | 11 +- drivers/macintosh/adbhid.c | 3 +- drivers/macintosh/via-pmu.c | 2 +- drivers/macintosh/via-pmu68k.c | 7 +- drivers/macintosh/windfarm_core.c | 8 +- drivers/misc/ibmasm/heartbeat.c | 5 +- drivers/net/bonding/bond_main.c | 2 +- drivers/parisc/led.c | 14 +- drivers/parisc/power.c | 6 +- drivers/scsi/gdth.c | 9 +- drivers/usb/core/notify.c | 65 +----- drivers/video/fbmem.c | 31 +-- include/asm-i386/kdebug.h | 10 +- include/asm-ia64/kdebug.h | 4 +- include/asm-powerpc/kdebug.h | 12 +- include/asm-sparc64/kdebug.h | 11 +- include/asm-x86_64/kdebug.h | 23 +- include/linux/adb.h | 2 +- include/linux/kernel.h | 2 +- include/linux/memory.h | 1 - include/linux/netfilter_ipv4/ip_conntrack.h | 17 +- include/linux/notifier.h | 96 +++++++- include/net/netfilter/nf_conntrack.h | 17 +- kernel/cpu.c | 29 +-- kernel/module.c | 20 +- kernel/panic.c | 4 +- kernel/profile.c | 53 ++--- kernel/softlockup.c | 2 +- kernel/sys.c | 327 ++++++++++++++++++++++------ net/bluetooth/hci_core.c | 8 +- net/core/dev.c | 42 ++-- net/decnet/dn_dev.c | 10 +- net/ipv4/devinet.c | 16 +- net/ipv4/netfilter/ip_conntrack_core.c | 6 +- net/ipv6/addrconf.c | 10 +- net/netfilter/nf_conntrack_core.c | 6 +- net/netlink/af_netlink.c | 9 +- 63 files changed, 677 insertions(+), 472 deletions(-) (limited to 'drivers') diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 9402624453c2..dd8769670596 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -43,7 +43,7 @@ #include #include -extern struct notifier_block *panic_notifier_list; +extern struct atomic_notifier_head panic_notifier_list; static int alpha_panic_event(struct notifier_block *, unsigned long, void *); static struct notifier_block alpha_panic_block = { alpha_panic_event, @@ -500,7 +500,8 @@ setup_arch(char **cmdline_p) } /* Register a call for panic conditions. */ - notifier_chain_register(&panic_notifier_list, &alpha_panic_block); + atomic_notifier_chain_register(&panic_notifier_list, + &alpha_panic_block); #ifdef CONFIG_ALPHA_GENERIC /* Assume that we've booted from SRM if we haven't booted from MILO. diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c index 60d5f8a3339c..7520e602d7a2 100644 --- a/arch/arm/mach-omap1/board-netstar.c +++ b/arch/arm/mach-omap1/board-netstar.c @@ -141,7 +141,7 @@ static int __init netstar_late_init(void) /* TODO: Setup front panel switch here */ /* Setup panic notifier */ - notifier_chain_register(&panic_notifier_list, &panic_block); + atomic_notifier_chain_register(&panic_notifier_list, &panic_block); return 0; } diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index bfd5fdd1a875..52e4a9d69642 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c @@ -235,7 +235,7 @@ static struct notifier_block panic_block = { static int __init voiceblue_setup(void) { /* Setup panic notifier */ - notifier_chain_register(&panic_notifier_list, &panic_block); + atomic_notifier_chain_register(&panic_notifier_list, &panic_block); return 0; } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 4624f8ca2459..6b63a5aa1e46 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -92,22 +92,21 @@ asmlinkage void spurious_interrupt_bug(void); asmlinkage void machine_check(void); static int kstack_depth_to_print = 24; -struct notifier_block *i386die_chain; -static DEFINE_SPINLOCK(die_notifier_lock); +ATOMIC_NOTIFIER_HEAD(i386die_chain); int register_die_notifier(struct notifier_block *nb) { - int err = 0; - unsigned long flags; - vmalloc_sync_all(); - spin_lock_irqsave(&die_notifier_lock, flags); - err = notifier_chain_register(&i386die_chain, nb); - spin_unlock_irqrestore(&die_notifier_lock, flags); - return err; + return atomic_notifier_chain_register(&i386die_chain, nb); } EXPORT_SYMBOL(register_die_notifier); +int unregister_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&i386die_chain, nb); +} +EXPORT_SYMBOL(unregister_die_notifier); + static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) { return p > (void *)tinfo && diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index dabd6c32641e..7c1ddc8ac443 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -30,19 +30,19 @@ extern spinlock_t timerlist_lock; fpswa_interface_t *fpswa_interface; EXPORT_SYMBOL(fpswa_interface); -struct notifier_block *ia64die_chain; +ATOMIC_NOTIFIER_HEAD(ia64die_chain); int register_die_notifier(struct notifier_block *nb) { - return notifier_chain_register(&ia64die_chain, nb); + return atomic_notifier_chain_register(&ia64die_chain, nb); } EXPORT_SYMBOL_GPL(register_die_notifier); int unregister_die_notifier(struct notifier_block *nb) { - return notifier_chain_unregister(&ia64die_chain, nb); + return atomic_notifier_chain_unregister(&ia64die_chain, nb); } EXPORT_SYMBOL_GPL(unregister_die_notifier); diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c index 83eb08b7a072..e9e9a89c6741 100644 --- a/arch/mips/lasat/setup.c +++ b/arch/mips/lasat/setup.c @@ -165,7 +165,8 @@ void __init plat_setup(void) /* Set up panic notifier */ for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++) - notifier_chain_register(&panic_notifier_list, &lasat_panic_block[i]); + atomic_notifier_chain_register(&panic_notifier_list, + &lasat_panic_block[i]); lasat_reboot_setup(); diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c index 92a3b3c15ed3..a9c58e067b53 100644 --- a/arch/mips/sgi-ip22/ip22-reset.c +++ b/arch/mips/sgi-ip22/ip22-reset.c @@ -238,7 +238,7 @@ static int __init reboot_setup(void) request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL); init_timer(&blink_timer); blink_timer.function = blink_timeout; - notifier_chain_register(&panic_notifier_list, &panic_block); + atomic_notifier_chain_register(&panic_notifier_list, &panic_block); return 0; } diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index 0c948008b023..ab9d9cef089e 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c @@ -193,7 +193,7 @@ static __init int ip32_reboot_setup(void) init_timer(&blink_timer); blink_timer.function = blink_timeout; - notifier_chain_register(&panic_notifier_list, &panic_block); + atomic_notifier_chain_register(&panic_notifier_list, &panic_block); request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL); diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c index 2a01fe1bdc98..0cea6958f427 100644 --- a/arch/parisc/kernel/pdc_chassis.c +++ b/arch/parisc/kernel/pdc_chassis.c @@ -150,7 +150,8 @@ void __init parisc_pdc_chassis_init(void) if (handle) { /* initialize panic notifier chain */ - notifier_chain_register(&panic_notifier_list, &pdc_chassis_panic_block); + atomic_notifier_chain_register(&panic_notifier_list, + &pdc_chassis_panic_block); /* initialize reboot notifier chain */ register_reboot_notifier(&pdc_chassis_reboot_block); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 2f3fdad35594..e20c1fae3423 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -579,7 +579,8 @@ void __init setup_arch(char **cmdline_p) panic_timeout = 180; if (ppc_md.panic) - notifier_chain_register(&panic_notifier_list, &ppc64_panic_block); + atomic_notifier_chain_register(&panic_notifier_list, + &ppc64_panic_block); init_mm.start_code = PAGE_OFFSET; init_mm.end_code = (unsigned long) _etext; diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 98660aedeeb7..9763faab6739 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -74,19 +74,19 @@ EXPORT_SYMBOL(__debugger_dabr_match); EXPORT_SYMBOL(__debugger_fault_handler); #endif -struct notifier_block *powerpc_die_chain; -static DEFINE_SPINLOCK(die_notifier_lock); +ATOMIC_NOTIFIER_HEAD(powerpc_die_chain); int register_die_notifier(struct notifier_block *nb) { - int err = 0; - unsigned long flags; + return atomic_notifier_chain_register(&powerpc_die_chain, nb); +} +EXPORT_SYMBOL(register_die_notifier); - spin_lock_irqsave(&die_notifier_lock, flags); - err = notifier_chain_register(&powerpc_die_chain, nb); - spin_unlock_irqrestore(&die_notifier_lock, flags); - return err; +int unregister_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&powerpc_die_chain, nb); } +EXPORT_SYMBOL(unregister_die_notifier); /* * Trap & Exception support diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 86cfa6ecdcf3..5ad90676567a 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -94,16 +94,16 @@ static struct device_node *derive_parent(const char *path) return parent; } -static struct notifier_block *pSeries_reconfig_chain; +static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); int pSeries_reconfig_notifier_register(struct notifier_block *nb) { - return notifier_chain_register(&pSeries_reconfig_chain, nb); + return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb); } void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { - notifier_chain_unregister(&pSeries_reconfig_chain, nb); + blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb); } static int pSeries_reconfig_add_node(const char *path, struct property *proplist) @@ -131,7 +131,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist goto out_err; } - err = notifier_call_chain(&pSeries_reconfig_chain, + err = blocking_notifier_call_chain(&pSeries_reconfig_chain, PSERIES_RECONFIG_ADD, np); if (err == NOTIFY_BAD) { printk(KERN_ERR "Failed to add device node %s\n", path); @@ -171,7 +171,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np) remove_node_proc_entries(np); - notifier_call_chain(&pSeries_reconfig_chain, + blocking_notifier_call_chain(&pSeries_reconfig_chain, PSERIES_RECONFIG_REMOVE, np); of_detach_node(np); diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index a0fc628ffb1e..d95c05d9824d 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c @@ -736,7 +736,7 @@ ibm_statusled_progress(char *s, unsigned short hex) hex = 0xfff; if (!notifier_installed) { ++notifier_installed; - notifier_chain_register(&panic_notifier_list, + atomic_notifier_chain_register(&panic_notifier_list, &ibm_statusled_block); } } diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 99182a415fe7..4a0f5a1551ea 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -76,17 +76,17 @@ unsigned long thread_saved_pc(struct task_struct *tsk) /* * Need to know about CPUs going idle? */ -static struct notifier_block *idle_chain; +static ATOMIC_NOTIFIER_HEAD(idle_chain); int register_idle_notifier(struct notifier_block *nb) { - return notifier_chain_register(&idle_chain, nb); + return atomic_notifier_chain_register(&idle_chain, nb); } EXPORT_SYMBOL(register_idle_notifier); int unregister_idle_notifier(struct notifier_block *nb) { - return notifier_chain_unregister(&idle_chain, nb); + return atomic_notifier_chain_unregister(&idle_chain, nb); } EXPORT_SYMBOL(unregister_idle_notifier); @@ -95,7 +95,7 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code) /* disable monitor call class 0 */ __ctl_clear_bit(8, 15); - notifier_call_chain(&idle_chain, CPU_NOT_IDLE, + atomic_notifier_call_chain(&idle_chain, CPU_NOT_IDLE, (void *)(long) smp_processor_id()); } @@ -116,7 +116,8 @@ static void default_idle(void) return; } - rc = notifier_call_chain(&idle_chain, CPU_IDLE, (void *)(long) cpu); + rc = atomic_notifier_call_chain(&idle_chain, + CPU_IDLE, (void *)(long) cpu); if (rc != NOTIFY_OK && rc != NOTIFY_DONE) BUG(); if (rc != NOTIFY_OK) { diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index df612e4f75f9..ff090bb9734b 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -43,18 +43,19 @@ #include #endif -struct notifier_block *sparc64die_chain; -static DEFINE_SPINLOCK(die_notifier_lock); +ATOMIC_NOTIFIER_HEAD(sparc64die_chain); int register_die_notifier(struct notifier_block *nb) { - int err = 0; - unsigned long flags; - spin_lock_irqsave(&die_notifier_lock, flags); - err = notifier_chain_register(&sparc64die_chain, nb); - spin_unlock_irqrestore(&die_notifier_lock, flags); - return err; + return atomic_notifier_chain_register(&sparc64die_chain, nb); } +EXPORT_SYMBOL(register_die_notifier); + +int unregister_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&sparc64die_chain, nb); +} +EXPORT_SYMBOL(unregister_die_notifier); /* When an irrecoverable trap occurs at tl > 0, the trap entry * code logs the trap state registers at every level in the trap diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 54388d10bcf9..1488816588ea 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -762,7 +762,8 @@ static struct notifier_block panic_exit_notifier = { static int add_notifier(void) { - notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); + atomic_notifier_chain_register(&panic_notifier_list, + &panic_exit_notifier); return(0); } diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index bb1c87211ac1..7d51dd7201c3 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -477,7 +477,8 @@ static struct notifier_block panic_exit_notifier = { void __init setup_arch(char **cmdline_p) { - notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); + atomic_notifier_chain_register(&panic_notifier_list, + &panic_exit_notifier); paging_init(); strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 0370720515f1..70dd8e5c6889 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -66,24 +66,17 @@ EXPORT_SYMBOL(boot_option_idle_override); void (*pm_idle)(void); static DEFINE_PER_CPU(unsigned int, cpu_idle_state); -static struct notifier_block *idle_notifier; -static DEFINE_SPINLOCK(idle_notifier_lock); +static ATOMIC_NOTIFIER_HEAD(idle_notifier); void idle_notifier_register(struct notifier_block *n) { - unsigned long flags; - spin_lock_irqsave(&idle_notifier_lock, flags); - notifier_chain_register(&idle_notifier, n); - spin_unlock_irqrestore(&idle_notifier_lock, flags); + atomic_notifier_chain_register(&idle_notifier, n); } EXPORT_SYMBOL_GPL(idle_notifier_register); void idle_notifier_unregister(struct notifier_block *n) { - unsigned long flags; - spin_lock_irqsave(&idle_notifier_lock, flags); - notifier_chain_unregister(&idle_notifier, n); - spin_unlock_irqrestore(&idle_notifier_lock, flags); + atomic_notifier_chain_unregister(&idle_notifier, n); } EXPORT_SYMBOL(idle_notifier_unregister); @@ -93,13 +86,13 @@ static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE; void enter_idle(void) { __get_cpu_var(idle_state) = CPU_IDLE; - notifier_call_chain(&idle_notifier, IDLE_START, NULL); + atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL); } static void __exit_idle(void) { __get_cpu_var(idle_state) = CPU_NOT_IDLE; - notifier_call_chain(&idle_notifier, IDLE_END, NULL); + atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL); } /* Called from interrupts to signify idle end */ diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 7b148309c529..edaa9fe654dc 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -69,20 +69,20 @@ asmlinkage void alignment_check(void); asmlinkage void machine_check(void); asmlinkage void spurious_interrupt_bug(void); -struct notifier_block *die_chain; -static DEFINE_SPINLOCK(die_notifier_lock); +ATOMIC_NOTIFIER_HEAD(die_chain); int register_die_notifier(struct notifier_block *nb) { - int err = 0; - unsigned long flags; - vmalloc_sync_all(); - spin_lock_irqsave(&die_notifier_lock, flags); - err = notifier_chain_register(&die_chain, nb); - spin_unlock_irqrestore(&die_notifier_lock, flags); - return err; + return atomic_notifier_chain_register(&die_chain, nb); +} +EXPORT_SYMBOL(register_die_notifier); + +int unregister_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&die_chain, nb); } +EXPORT_SYMBOL(unregister_die_notifier); static inline void conditional_sti(struct pt_regs *regs) { diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platform-iss/setup.c index 2e6dcbf0cc04..23790a5610e2 100644 --- a/arch/xtensa/platform-iss/setup.c +++ b/arch/xtensa/platform-iss/setup.c @@ -108,5 +108,5 @@ static struct notifier_block iss_panic_block = { void __init platform_setup(char **p_cmdline) { - notifier_chain_register(&panic_notifier_list, &iss_panic_block); + atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block); } diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 105a0d61eb1f..dd547af4681a 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -47,16 +47,16 @@ static struct kset_uevent_ops memory_uevent_ops = { .uevent = memory_uevent, }; -static struct notifier_block *memory_chain; +static BLOCKING_NOTIFIER_HEAD(memory_chain); int register_memory_notifier(struct notifier_block *nb) { - return notifier_chain_register(&memory_chain, nb); + return blocking_notifier_chain_register(&memory_chain, nb); } void unregister_memory_notifier(struct notifier_block *nb) { - notifier_chain_unregister(&memory_chain, nb); + blocking_notifier_chain_unregister(&memory_chain, nb); } /* @@ -140,7 +140,7 @@ static ssize_t show_mem_state(struct sys_device *dev, char *buf) static inline int memory_notify(unsigned long val, void *v) { - return notifier_call_chain(&memory_chain, val, v); + return blocking_notifier_call_chain(&memory_chain, val, v); } /* diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index b8fb87c6c29f..40eb005b9d77 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -3744,7 +3744,7 @@ static int ipmi_init_msghandler(void) ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES; add_timer(&ipmi_timer); - notifier_chain_register(&panic_notifier_list, &panic_block); + atomic_notifier_chain_register(&panic_notifier_list, &panic_block); initialized = 1; @@ -3764,7 +3764,7 @@ static __exit void cleanup_ipmi(void) if (!initialized) return; - notifier_chain_unregister(&panic_notifier_list, &panic_block); + atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block); /* This can't be called if any interfaces exist, so no worry about shutting down the interfaces. */ diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 12f858dc9994..35fbd4d8ed4b 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -237,10 +237,10 @@ struct smi_info static int try_smi_init(struct smi_info *smi); -static struct notifier_block *xaction_notifier_list; +static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); static int register_xaction_notifier(struct notifier_block * nb) { - return notifier_chain_register(&xaction_notifier_list, nb); + return atomic_notifier_chain_register(&xaction_notifier_list, nb); } static void si_restart_short_timer(struct smi_info *smi_info); @@ -302,7 +302,8 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) do_gettimeofday(&t); printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec); #endif - err = notifier_call_chain(&xaction_notifier_list, 0, smi_info); + err = atomic_notifier_call_chain(&xaction_notifier_list, + 0, smi_info); if (err & NOTIFY_STOP_MASK) { rv = SI_SM_CALL_WITHOUT_DELAY; goto out; diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 616539310d9a..7ece9f3c8f70 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -1158,7 +1158,8 @@ static int __init ipmi_wdog_init(void) } register_reboot_notifier(&wdog_reboot_notifier); - notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier); + atomic_notifier_chain_register(&panic_notifier_list, + &wdog_panic_notifier); printk(KERN_INFO PFX "driver initialized\n"); @@ -1176,7 +1177,8 @@ static __exit void ipmi_unregister_watchdog(void) release_nmi(&ipmi_nmi_handler); #endif - notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier); + atomic_notifier_chain_unregister(&panic_notifier_list, + &wdog_panic_notifier); unregister_reboot_notifier(&wdog_reboot_notifier); if (! watchdog_user) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index aed80e6aec6d..9b6ae7dc8b8a 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -52,9 +52,8 @@ static void handle_update(void *data); * changes to devices when the CPU clock speed changes. * The mutex locks both lists. */ -static struct notifier_block *cpufreq_policy_notifier_list; -static struct notifier_block *cpufreq_transition_notifier_list; -static DECLARE_RWSEM (cpufreq_notifier_rwsem); +static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list); +static BLOCKING_NOTIFIER_HEAD(cpufreq_transition_notifier_list); static LIST_HEAD(cpufreq_governor_list); @@ -247,8 +246,6 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) dprintk("notification %u of frequency transition to %u kHz\n", state, freqs->new); - down_read(&cpufreq_notifier_rwsem); - policy = cpufreq_cpu_data[freqs->cpu]; switch (state) { @@ -266,20 +263,19 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) freqs->old = policy->cur; } } - notifier_call_chain(&cpufreq_transition_notifier_list, - CPUFREQ_PRECHANGE, freqs); + blocking_notifier_call_chain(&cpufreq_transition_notifier_list, + CPUFREQ_PRECHANGE, freqs); adjust_jiffies(CPUFREQ_PRECHANGE, freqs); break; case CPUFREQ_POSTCHANGE: adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); - notifier_call_chain(&cpufreq_transition_notifier_list, - CPUFREQ_POSTCHANGE, freqs); + blocking_notifier_call_chain(&cpufreq_transition_notifier_list, + CPUFREQ_POSTCHANGE, freqs); if (likely(policy) && likely(policy->cpu == freqs->cpu)) policy->cur = freqs->new; break; } - up_read(&cpufreq_notifier_rwsem); } EXPORT_SYMBOL_GPL(cpufreq_notify_transition); @@ -1007,7 +1003,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) freqs.old = cpu_policy->cur; freqs.new = cur_freq; - notifier_call_chain(&cpufreq_transition_notifier_list, + blocking_notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_SUSPENDCHANGE, &freqs); adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs); @@ -1088,7 +1084,8 @@ static int cpufreq_resume(struct sys_device * sysdev) freqs.old = cpu_policy->cur; freqs.new = cur_freq; - notifier_call_chain(&cpufreq_transition_notifier_list, + blocking_notifier_call_chain( + &cpufreq_transition_notifier_list, CPUFREQ_RESUMECHANGE, &freqs); adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); @@ -1125,24 +1122,24 @@ static struct sysdev_driver cpufreq_sysdev_driver = { * changes in cpufreq policy. * * This function may sleep, and has the same return conditions as - * notifier_chain_register. + * blocking_notifier_chain_register. */ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) { int ret; - down_write(&cpufreq_notifier_rwsem); switch (list) { case CPUFREQ_TRANSITION_NOTIFIER: - ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb); + ret = blocking_notifier_chain_register( + &cpufreq_transition_notifier_list, nb); break; case CPUFREQ_POLICY_NOTIFIER: - ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb); + ret = blocking_notifier_chain_register( + &cpufreq_policy_notifier_list, nb); break; default: ret = -EINVAL; } - up_write(&cpufreq_notifier_rwsem); return ret; } @@ -1157,24 +1154,24 @@ EXPORT_SYMBOL(cpufreq_register_notifier); * Remove a driver from the CPU frequency notifier list. * * This function may sleep, and has the same return conditions as - * notifier_chain_unregister. + * blocking_notifier_chain_unregister. */ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) { int ret; - down_write(&cpufreq_notifier_rwsem); switch (list) { case CPUFREQ_TRANSITION_NOTIFIER: - ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb); + ret = blocking_notifier_chain_unregister( + &cpufreq_transition_notifier_list, nb); break; case CPUFREQ_POLICY_NOTIFIER: - ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb); + ret = blocking_notifier_chain_unregister( + &cpufreq_policy_notifier_list, nb); break; default: ret = -EINVAL; } - up_write(&cpufreq_notifier_rwsem); return ret; } @@ -1346,29 +1343,23 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli if (ret) goto error_out; - down_read(&cpufreq_notifier_rwsem); - /* adjust if necessary - all reasons */ - notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST, - policy); + blocking_notifier_call_chain(&cpufreq_policy_notifier_list, + CPUFREQ_ADJUST, policy); /* adjust if necessary - hardware incompatibility*/ - notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE, - policy); + blocking_notifier_call_chain(&cpufreq_policy_notifier_list, + CPUFREQ_INCOMPATIBLE, policy); /* verify the cpu speed can be set within this limit, which might be different to the first one */ ret = cpufreq_driver->verify(policy); - if (ret) { - up_read(&cpufreq_notifier_rwsem); + if (ret) goto error_out; - } /* notification of the new policy */ - notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY, - policy); - - up_read(&cpufreq_notifier_rwsem); + blocking_notifier_call_chain(&cpufreq_policy_notifier_list, + CPUFREQ_NOTIFY, policy); data->min = policy->min; data->max = policy->max; diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index d6543fc4a923..339f405ff708 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -484,26 +484,15 @@ static void dcdbas_host_control(void) static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code, void *unused) { - static unsigned int notify_cnt = 0; - switch (code) { case SYS_DOWN: case SYS_HALT: case SYS_POWER_OFF: if (host_control_on_shutdown) { /* firmware is going to perform host control action */ - if (++notify_cnt == 2) { - printk(KERN_WARNING - "Please wait for shutdown " - "action to complete...\n"); - dcdbas_host_control(); - } - /* - * register again and initiate the host control - * action on the second notification to allow - * everyone that registered to be notified - */ - register_reboot_notifier(nb); + printk(KERN_WARNING "Please wait for shutdown " + "action to complete...\n"); + dcdbas_host_control(); } break; } @@ -514,7 +503,7 @@ static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code, static struct notifier_block dcdbas_reboot_nb = { .notifier_call = dcdbas_reboot_notify, .next = NULL, - .priority = 0 + .priority = INT_MIN }; static DCDBAS_BIN_ATTR_RW(smi_data); diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index d2ead1776c16..34fcabac5fdb 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -80,7 +80,7 @@ static struct adb_driver *adb_driver_list[] = { static struct class *adb_dev_class; struct adb_driver *adb_controller; -struct notifier_block *adb_client_list = NULL; +BLOCKING_NOTIFIER_HEAD(adb_client_list); static int adb_got_sleep; static int adb_inited; static pid_t adb_probe_task_pid; @@ -354,7 +354,8 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when) /* Stop autopoll */ if (adb_controller->autopoll) adb_controller->autopoll(0); - ret = notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL); + ret = blocking_notifier_call_chain(&adb_client_list, + ADB_MSG_POWERDOWN, NULL); if (ret & NOTIFY_STOP_MASK) { up(&adb_probe_mutex); return PBOOK_SLEEP_REFUSE; @@ -391,7 +392,8 @@ do_adb_reset_bus(void) if (adb_controller->autopoll) adb_controller->autopoll(0); - nret = notifier_call_chain(&adb_client_list, ADB_MSG_PRE_RESET, NULL); + nret = blocking_notifier_call_chain(&adb_client_list, + ADB_MSG_PRE_RESET, NULL); if (nret & NOTIFY_STOP_MASK) { if (adb_controller->autopoll) adb_controller->autopoll(autopoll_devs); @@ -426,7 +428,8 @@ do_adb_reset_bus(void) } up(&adb_handler_sem); - nret = notifier_call_chain(&adb_client_list, ADB_MSG_POST_RESET, NULL); + nret = blocking_notifier_call_chain(&adb_client_list, + ADB_MSG_POST_RESET, NULL); if (nret & NOTIFY_STOP_MASK) return -EBUSY; diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index c0b46bceb5df..f5779a73184d 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -1214,7 +1214,8 @@ static int __init adbhid_init(void) adbhid_probe(); - notifier_chain_register(&adb_client_list, &adbhid_adb_notifier); + blocking_notifier_chain_register(&adb_client_list, + &adbhid_adb_notifier); return 0; } diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 4f5f3abc9cb3..0b5ff553e39a 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -187,7 +187,7 @@ extern int disable_kernel_backlight; int __fake_sleep; int asleep; -struct notifier_block *sleep_notifier_list; +BLOCKING_NOTIFIER_HEAD(sleep_notifier_list); #ifdef CONFIG_ADB static int adb_dev_map = 0; diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c index f08e52f2107b..35b70323e7e3 100644 --- a/drivers/macintosh/via-pmu68k.c +++ b/drivers/macintosh/via-pmu68k.c @@ -102,7 +102,7 @@ static int pmu_kind = PMU_UNKNOWN; static int pmu_fully_inited = 0; int asleep; -struct notifier_block *sleep_notifier_list; +BLOCKING_NOTIFIER_HEAD(sleep_notifier_list); static int pmu_probe(void); static int pmu_init(void); @@ -913,7 +913,8 @@ int powerbook_sleep(void) struct adb_request sleep_req; /* Notify device drivers */ - ret = notifier_call_chain(&sleep_notifier_list, PBOOK_SLEEP, NULL); + ret = blocking_notifier_call_chain(&sleep_notifier_list, + PBOOK_SLEEP, NULL); if (ret & NOTIFY_STOP_MASK) return -EBUSY; @@ -984,7 +985,7 @@ int powerbook_sleep(void) enable_irq(i); /* Notify drivers */ - notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL); + blocking_notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL); /* reenable ADB autopoll */ pmu_adb_autopoll(adb_dev_map); diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 6c0ba04bc57a..ab3faa702d58 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c @@ -52,7 +52,7 @@ static LIST_HEAD(wf_controls); static LIST_HEAD(wf_sensors); static DEFINE_MUTEX(wf_lock); -static struct notifier_block *wf_client_list; +static BLOCKING_NOTIFIER_HEAD(wf_client_list); static int wf_client_count; static unsigned int wf_overtemp; static unsigned int wf_overtemp_counter; @@ -68,7 +68,7 @@ static struct platform_device wf_platform_device = { static inline void wf_notify(int event, void *param) { - notifier_call_chain(&wf_client_list, event, param); + blocking_notifier_call_chain(&wf_client_list, event, param); } int wf_critical_overtemp(void) @@ -398,7 +398,7 @@ int wf_register_client(struct notifier_block *nb) struct wf_sensor *sr; mutex_lock(&wf_lock); - rc = notifier_chain_register(&wf_client_list, nb); + rc = blocking_notifier_chain_register(&wf_client_list, nb); if (rc != 0) goto bail; wf_client_count++; @@ -417,7 +417,7 @@ EXPORT_SYMBOL_GPL(wf_register_client); int wf_unregister_client(struct notifier_block *nb) { mutex_lock(&wf_lock); - notifier_chain_unregister(&wf_client_list, nb); + blocking_notifier_chain_unregister(&wf_client_list, nb); wf_client_count++; if (wf_client_count == 0) wf_stop_thread(); diff --git a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c index f295401fac21..7fd7a43e38de 100644 --- a/drivers/misc/ibmasm/heartbeat.c +++ b/drivers/misc/ibmasm/heartbeat.c @@ -52,12 +52,13 @@ static struct notifier_block panic_notifier = { panic_happened, NULL, 1 }; void ibmasm_register_panic_notifier(void) { - notifier_chain_register(&panic_notifier_list, &panic_notifier); + atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier); } void ibmasm_unregister_panic_notifier(void) { - notifier_chain_unregister(&panic_notifier_list, &panic_notifier); + atomic_notifier_chain_unregister(&panic_notifier_list, + &panic_notifier); } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2d0ac169a86c..f13a539dc169 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3159,7 +3159,7 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave * bond_netdev_event: handle netdev notifier chain events. * * This function receives events for the netdev chain. The caller (an - * ioctl handler calling notifier_call_chain) holds the necessary + * ioctl handler calling blocking_notifier_call_chain) holds the necessary * locks for us to safely manipulate the slave devices (RTNL lock, * dev_probe_lock). */ diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 3627a2d7f79f..298f2ddb2c17 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -499,11 +499,16 @@ static int led_halt(struct notifier_block *, unsigned long, void *); static struct notifier_block led_notifier = { .notifier_call = led_halt, }; +static int notifier_disabled = 0; static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) { char *txt; - + + if (notifier_disabled) + return NOTIFY_OK; + + notifier_disabled = 1; switch (event) { case SYS_RESTART: txt = "SYSTEM RESTART"; break; @@ -527,7 +532,6 @@ static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) if (led_func_ptr) led_func_ptr(0xff); /* turn all LEDs ON */ - unregister_reboot_notifier(&led_notifier); return NOTIFY_OK; } @@ -758,6 +762,12 @@ not_found: return 1; } +static void __exit led_exit(void) +{ + unregister_reboot_notifier(&led_notifier); + return; +} + #ifdef CONFIG_PROC_FS module_init(led_create_procfs) #endif diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c index 54b2b7f20b96..0bcab83b4080 100644 --- a/drivers/parisc/power.c +++ b/drivers/parisc/power.c @@ -251,7 +251,8 @@ static int __init power_init(void) } /* Register a call for panic conditions. */ - notifier_chain_register(&panic_notifier_list, &parisc_panic_block); + atomic_notifier_chain_register(&panic_notifier_list, + &parisc_panic_block); tasklet_enable(&power_tasklet); @@ -264,7 +265,8 @@ static void __exit power_exit(void) return; tasklet_disable(&power_tasklet); - notifier_chain_unregister(&panic_notifier_list, &parisc_panic_block); + atomic_notifier_chain_unregister(&panic_notifier_list, + &parisc_panic_block); power_tasklet.func = NULL; pdc_soft_power_button(0); } diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 62e3cda859af..7f7013e80a88 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -671,7 +671,7 @@ static struct file_operations gdth_fops = { static struct notifier_block gdth_notifier = { gdth_halt, NULL, 0 }; - +static int notifier_disabled = 0; static void gdth_delay(int milliseconds) { @@ -4595,13 +4595,13 @@ static int __init gdth_detect(struct scsi_host_template *shtp) add_timer(&gdth_timer); #endif major = register_chrdev(0,"gdth",&gdth_fops); + notifier_disabled = 0; register_reboot_notifier(&gdth_notifier); } gdth_polling = FALSE; return gdth_ctr_vcount; } - static int gdth_release(struct Scsi_Host *shp) { int hanum; @@ -5632,10 +5632,14 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) char cmnd[MAX_COMMAND_SIZE]; #endif + if (notifier_disabled) + return NOTIFY_OK; + TRACE2(("gdth_halt() event %d\n",(int)event)); if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) return NOTIFY_DONE; + notifier_disabled = 1; printk("GDT-HA: Flushing all host drives .. "); for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { gdth_flush(hanum); @@ -5679,7 +5683,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) #ifdef GDTH_STATISTICS del_timer(&gdth_timer); #endif - unregister_reboot_notifier(&gdth_notifier); return NOTIFY_OK; } diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index 4b55285de9a0..fe0ed54fa0ae 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c @@ -16,57 +16,7 @@ #include #include "usb.h" - -static struct notifier_block *usb_notifier_list; -static DEFINE_MUTEX(usb_notifier_lock); - -static void usb_notifier_chain_register(struct notifier_block **list, - struct notifier_block *n) -{ - mutex_lock(&usb_notifier_lock); - while (*list) { - if (n->priority > (*list)->priority) - break; - list = &((*list)->next); - } - n->next = *list; - *list = n; - mutex_unlock(&usb_notifier_lock); -} - -static void usb_notifier_chain_unregister(struct notifier_block **nl, - struct notifier_block *n) -{ - mutex_lock(&usb_notifier_lock); - while ((*nl)!=NULL) { - if ((*nl)==n) { - *nl = n->next; - goto exit; - } - nl=&((*nl)->next); - } -exit: - mutex_unlock(&usb_notifier_lock); -} - -static int usb_notifier_call_chain(struct notifier_block **n, - unsigned long val, void *v) -{ - int ret=NOTIFY_DONE; - struct notifier_block *nb = *n; - - mutex_lock(&usb_notifier_lock); - while (nb) { - ret = nb->notifier_call(nb,val,v); - if (ret&NOTIFY_STOP_MASK) { - goto exit; - } - nb = nb->next; - } -exit: - mutex_unlock(&usb_notifier_lock); - return ret; -} +static BLOCKING_NOTIFIER_HEAD(usb_notifier_list); /** * usb_register_notify - register a notifier callback whenever a usb change happens @@ -76,7 +26,7 @@ exit: */ void usb_register_notify(struct notifier_block *nb) { - usb_notifier_chain_register(&usb_notifier_list, nb); + blocking_notifier_chain_register(&usb_notifier_list, nb); } EXPORT_SYMBOL_GPL(usb_register_notify); @@ -89,27 +39,28 @@ EXPORT_SYMBOL_GPL(usb_register_notify); */ void usb_unregister_notify(struct notifier_block *nb) { - usb_notifier_chain_unregister(&usb_notifier_list, nb); + blocking_notifier_chain_unregister(&usb_notifier_list, nb); } EXPORT_SYMBOL_GPL(usb_unregister_notify); void usb_notify_add_device(struct usb_device *udev) { - usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); + blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); } void usb_notify_remove_device(struct usb_device *udev) { - usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev); + blocking_notifier_call_chain(&usb_notifier_list, + USB_DEVICE_REMOVE, udev); } void usb_notify_add_bus(struct usb_bus *ubus) { - usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); + blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); } void usb_notify_remove_bus(struct usb_bus *ubus) { - usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); + blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); } diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 07d882b14396..b1a8dca76430 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -55,7 +55,7 @@ #define FBPIXMAPSIZE (1024 * 8) -static struct notifier_block *fb_notifier_list; +static BLOCKING_NOTIFIER_HEAD(fb_notifier_list); struct fb_info *registered_fb[FB_MAX]; int num_registered_fb; @@ -784,7 +784,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) event.info = info; event.data = &mode1; - ret = notifier_call_chain(&fb_notifier_list, + ret = blocking_notifier_call_chain(&fb_notifier_list, FB_EVENT_MODE_DELETE, &event); } @@ -830,8 +830,8 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) info->flags &= ~FBINFO_MISC_USEREVENT; event.info = info; - notifier_call_chain(&fb_notifier_list, evnt, - &event); + blocking_notifier_call_chain(&fb_notifier_list, + evnt, &event); } } } @@ -854,7 +854,8 @@ fb_blank(struct fb_info *info, int blank) event.info = info; event.data = ␣ - notifier_call_chain(&fb_notifier_list, FB_EVENT_BLANK, &event); + blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_BLANK, &event); } return ret; @@ -925,7 +926,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, con2fb.framebuffer = -1; event.info = info; event.data = &con2fb; - notifier_call_chain(&fb_notifier_list, + blocking_notifier_call_chain(&fb_notifier_list, FB_EVENT_GET_CONSOLE_MAP, &event); return copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; @@ -944,7 +945,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return -EINVAL; event.info = info; event.data = &con2fb; - return notifier_call_chain(&fb_notifier_list, + return blocking_notifier_call_chain(&fb_notifier_list, FB_EVENT_SET_CONSOLE_MAP, &event); case FBIOBLANK: @@ -1324,7 +1325,7 @@ register_framebuffer(struct fb_info *fb_info) devfs_mk_cdev(MKDEV(FB_MAJOR, i), S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i); event.info = fb_info; - notifier_call_chain(&fb_notifier_list, + blocking_notifier_call_chain(&fb_notifier_list, FB_EVENT_FB_REGISTERED, &event); return 0; } @@ -1366,7 +1367,7 @@ unregister_framebuffer(struct fb_info *fb_info) */ int fb_register_client(struct notifier_block *nb) { - return notifier_chain_register(&fb_notifier_list, nb); + return blocking_notifier_chain_register(&fb_notifier_list, nb); } /** @@ -1375,7 +1376,7 @@ int fb_register_client(struct notifier_block *nb) */ int fb_unregister_client(struct notifier_block *nb) { - return notifier_chain_unregister(&fb_notifier_list, nb); + return blocking_notifier_chain_unregister(&fb_notifier_list, nb); } /** @@ -1393,11 +1394,13 @@ void fb_set_suspend(struct fb_info *info, int state) event.info = info; if (state) { - notifier_call_chain(&fb_notifier_list, FB_EVENT_SUSPEND, &event); + blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_SUSPEND, &event); info->state = FBINFO_STATE_SUSPENDED; } else { info->state = FBINFO_STATE_RUNNING; - notifier_call_chain(&fb_notifier_list, FB_EVENT_RESUME, &event); + blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_RESUME, &event); } } @@ -1469,7 +1472,7 @@ int fb_new_modelist(struct fb_info *info) if (!list_empty(&info->modelist)) { event.info = info; - err = notifier_call_chain(&fb_notifier_list, + err = blocking_notifier_call_chain(&fb_notifier_list, FB_EVENT_NEW_MODELIST, &event); } @@ -1495,7 +1498,7 @@ int fb_con_duit(struct fb_info *info, int event, void *data) evnt.info = info; evnt.data = data; - return notifier_call_chain(&fb_notifier_list, event, &evnt); + return blocking_notifier_call_chain(&fb_notifier_list, event, &evnt); } EXPORT_SYMBOL(fb_con_duit); diff --git a/include/asm-i386/kdebug.h b/include/asm-i386/kdebug.h index 316138e89910..96d0828ce096 100644 --- a/include/asm-i386/kdebug.h +++ b/include/asm-i386/kdebug.h @@ -17,11 +17,9 @@ struct die_args { int signr; }; -/* Note - you should never unregister because that can race with NMIs. - If you really want to do it first unregister - then synchronize_sched - then free. - */ -int register_die_notifier(struct notifier_block *nb); -extern struct notifier_block *i386die_chain; +extern int register_die_notifier(struct notifier_block *); +extern int unregister_die_notifier(struct notifier_block *); +extern struct atomic_notifier_head i386die_chain; /* Grossly misnamed. */ @@ -51,7 +49,7 @@ static inline int notify_die(enum die_val val, const char *str, .trapnr = trap, .signr = sig }; - return notifier_call_chain(&i386die_chain, val, &args); + return atomic_notifier_call_chain(&i386die_chain, val, &args); } #endif diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h index 8b01a083dde6..218c458ab60c 100644 --- a/include/asm-ia64/kdebug.h +++ b/include/asm-ia64/kdebug.h @@ -40,7 +40,7 @@ struct die_args { extern int register_die_notifier(struct notifier_block *); extern int unregister_die_notifier(struct notifier_block *); -extern struct notifier_block *ia64die_chain; +extern struct atomic_notifier_head ia64die_chain; enum die_val { DIE_BREAK = 1, @@ -81,7 +81,7 @@ static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs, .signr = sig }; - return notifier_call_chain(&ia64die_chain, val, &args); + return atomic_notifier_call_chain(&ia64die_chain, val, &args); } #endif diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h index 7c16265568e0..c01786ab5fa6 100644 --- a/include/asm-powerpc/kdebug.h +++ b/include/asm-powerpc/kdebug.h @@ -16,13 +16,9 @@ struct die_args { int signr; }; -/* - Note - you should never unregister because that can race with NMIs. - If you really want to do it first unregister - then synchronize_sched - - then free. - */ -int register_die_notifier(struct notifier_block *nb); -extern struct notifier_block *powerpc_die_chain; +extern int register_die_notifier(struct notifier_block *); +extern int unregister_die_notifier(struct notifier_block *); +extern struct atomic_notifier_head powerpc_die_chain; /* Grossly misnamed. */ enum die_val { @@ -37,7 +33,7 @@ enum die_val { static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig) { struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig }; - return notifier_call_chain(&powerpc_die_chain, val, &args); + return atomic_notifier_call_chain(&powerpc_die_chain, val, &args); } #endif /* __KERNEL__ */ diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h index 6321f5a0198d..4040d127ac3e 100644 --- a/include/asm-sparc64/kdebug.h +++ b/include/asm-sparc64/kdebug.h @@ -15,12 +15,9 @@ struct die_args { int signr; }; -/* Note - you should never unregister because that can race with NMIs. - * If you really want to do it first unregister - then synchronize_sched - * - then free. - */ -int register_die_notifier(struct notifier_block *nb); -extern struct notifier_block *sparc64die_chain; +extern int register_die_notifier(struct notifier_block *); +extern int unregister_die_notifier(struct notifier_block *); +extern struct atomic_notifier_head sparc64die_chain; extern void bad_trap(struct pt_regs *, long); @@ -46,7 +43,7 @@ static inline int notify_die(enum die_val val,char *str, struct pt_regs *regs, .trapnr = trap, .signr = sig }; - return notifier_call_chain(&sparc64die_chain, val, &args); + return atomic_notifier_call_chain(&sparc64die_chain, val, &args); } #endif diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h index b9ed4c0c8783..cf795631d9b4 100644 --- a/include/asm-x86_64/kdebug.h +++ b/include/asm-x86_64/kdebug.h @@ -5,21 +5,20 @@ struct pt_regs; -struct die_args { +struct die_args { struct pt_regs *regs; const char *str; - long err; + long err; int trapnr; int signr; -}; +}; + +extern int register_die_notifier(struct notifier_block *); +extern int unregister_die_notifier(struct notifier_block *); +extern struct atomic_notifier_head die_chain; -/* Note - you should never unregister because that can race with NMIs. - If you really want to do it first unregister - then synchronize_sched - then free. - */ -int register_die_notifier(struct notifier_block *nb); -extern struct notifier_block *die_chain; /* Grossly misnamed. */ -enum die_val { +enum die_val { DIE_OOPS = 1, DIE_INT3, DIE_DEBUG, @@ -33,8 +32,8 @@ enum die_val { DIE_CALL, DIE_NMI_IPI, DIE_PAGE_FAULT, -}; - +}; + static inline int notify_die(enum die_val val, const char *str, struct pt_regs *regs, long err, int trap, int sig) { @@ -45,7 +44,7 @@ static inline int notify_die(enum die_val val, const char *str, .trapnr = trap, .signr = sig }; - return notifier_call_chain(&die_chain, val, &args); + return atomic_notifier_call_chain(&die_chain, val, &args); } extern int printk_address(unsigned long address); diff --git a/include/linux/adb.h b/include/linux/adb.h index e9fdc63483c7..b7305b178279 100644 --- a/include/linux/adb.h +++ b/include/linux/adb.h @@ -85,7 +85,7 @@ enum adb_message { ADB_MSG_POST_RESET /* Called after resetting the bus (re-do init & register) */ }; extern struct adb_driver *adb_controller; -extern struct notifier_block *adb_client_list; +extern struct blocking_notifier_head adb_client_list; int adb_request(struct adb_request *req, void (*done)(struct adb_request *), int flags, int nbytes, ...); diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 03d6cfaa5b8a..a3720f973ea5 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -87,7 +87,7 @@ extern int cond_resched(void); (__x < 0) ? -__x : __x; \ }) -extern struct notifier_block *panic_notifier_list; +extern struct atomic_notifier_head panic_notifier_list; extern long (*panic_blink)(long time); NORET_TYPE void panic(const char * fmt, ...) __attribute__ ((NORET_AND format (printf, 1, 2))); diff --git a/include/linux/memory.h b/include/linux/memory.h index e251dc43d0f5..8f04143ca363 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -77,7 +77,6 @@ extern int remove_memory_block(unsigned long, struct mem_section *, int); #define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION< +#include +#include -struct notifier_block -{ - int (*notifier_call)(struct notifier_block *self, unsigned long, void *); +/* + * Notifier chains are of three types: + * + * Atomic notifier chains: Chain callbacks run in interrupt/atomic + * context. Callouts are not allowed to block. + * Blocking notifier chains: Chain callbacks run in process context. + * Callouts are allowed to block. + * Raw notifier chains: There are no restrictions on callbacks, + * registration, or unregistration. All locking and protection + * must be provided by the caller. + * + * atomic_notifier_chain_register() may be called from an atomic context, + * but blocking_notifier_chain_register() must be called from a process + * context. Ditto for the corresponding _unregister() routines. + * + * atomic_notifier_chain_unregister() and blocking_notifier_chain_unregister() + * _must not_ be called from within the call chain. + */ + +struct notifier_block { + int (*notifier_call)(struct notifier_block *, unsigned long, void *); struct notifier_block *next; int priority; }; +struct atomic_notifier_head { + spinlock_t lock; + struct notifier_block *head; +}; + +struct blocking_notifier_head { + struct rw_semaphore rwsem; + struct notifier_block *head; +}; + +struct raw_notifier_head { + struct notifier_block *head; +}; + +#define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \ + spin_lock_init(&(name)->lock); \ + (name)->head = NULL; \ + } while (0) +#define BLOCKING_INIT_NOTIFIER_HEAD(name) do { \ + init_rwsem(&(name)->rwsem); \ + (name)->head = NULL; \ + } while (0) +#define RAW_INIT_NOTIFIER_HEAD(name) do { \ + (name)->head = NULL; \ + } while (0) + +#define ATOMIC_NOTIFIER_INIT(name) { \ + .lock = SPIN_LOCK_UNLOCKED, \ + .head = NULL } +#define BLOCKING_NOTIFIER_INIT(name) { \ + .rwsem = __RWSEM_INITIALIZER((name).rwsem), \ + .head = NULL } +#define RAW_NOTIFIER_INIT(name) { \ + .head = NULL } + +#define ATOMIC_NOTIFIER_HEAD(name) \ + struct atomic_notifier_head name = \ + ATOMIC_NOTIFIER_INIT(name) +#define BLOCKING_NOTIFIER_HEAD(name) \ + struct blocking_notifier_head name = \ + BLOCKING_NOTIFIER_INIT(name) +#define RAW_NOTIFIER_HEAD(name) \ + struct raw_notifier_head name = \ + RAW_NOTIFIER_INIT(name) #ifdef __KERNEL__ -extern int notifier_chain_register(struct notifier_block **list, struct notifier_block *n); -extern int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n); -extern int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v); +extern int atomic_notifier_chain_register(struct atomic_notifier_head *, + struct notifier_block *); +extern int blocking_notifier_chain_register(struct blocking_notifier_head *, + struct notifier_block *); +extern int raw_notifier_chain_register(struct raw_notifier_head *, + struct notifier_block *); + +extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *, + struct notifier_block *); +extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *, + struct notifier_block *); +extern int raw_notifier_chain_unregister(struct raw_notifier_head *, + struct notifier_block *); + +extern int atomic_notifier_call_chain(struct atomic_notifier_head *, + unsigned long val, void *v); +extern int blocking_notifier_call_chain(struct blocking_notifier_head *, + unsigned long val, void *v); +extern int raw_notifier_call_chain(struct raw_notifier_head *, + unsigned long val, void *v); #define NOTIFY_DONE 0x0000 /* Don't care */ #define NOTIFY_OK 0x0001 /* Suits me */ #define NOTIFY_STOP_MASK 0x8000 /* Don't call further */ -#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) /* Bad/Veto action */ +#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) + /* Bad/Veto action */ /* * Clean way to return from the notifier and stop further calls. */ diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index b6f0905a4ee2..916013ca4a5c 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -300,29 +300,30 @@ DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); #define CONNTRACK_ECACHE(x) (__get_cpu_var(nf_conntrack_ecache).x) -extern struct notifier_block *nf_conntrack_chain; -extern struct notifier_block *nf_conntrack_expect_chain; +extern struct atomic_notifier_head nf_conntrack_chain; +extern struct atomic_notifier_head nf_conntrack_expect_chain; static inline int nf_conntrack_register_notifier(struct notifier_block *nb) { - return notifier_chain_register(&nf_conntrack_chain, nb); + return atomic_notifier_chain_register(&nf_conntrack_chain, nb); } static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb) { - return notifier_chain_unregister(&nf_conntrack_chain, nb); + return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb); } static inline int nf_conntrack_expect_register_notifier(struct notifier_block *nb) { - return notifier_chain_register(&nf_conntrack_expect_chain, nb); + return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb); } static inline int nf_conntrack_expect_unregister_notifier(struct notifier_block *nb) { - return notifier_chain_unregister(&nf_conntrack_expect_chain, nb); + return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain, + nb); } extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); @@ -347,14 +348,14 @@ static inline void nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) { if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) - notifier_call_chain(&nf_conntrack_chain, event, ct); + atomic_notifier_call_chain(&nf_conntrack_chain, event, ct); } static inline void nf_conntrack_expect_event(enum ip_conntrack_expect_events event, struct nf_conntrack_expect *exp) { - notifier_call_chain(&nf_conntrack_expect_chain, event, exp); + atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp); } #else /* CONFIG_NF_CONNTRACK_EVENTS */ static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, diff --git a/kernel/cpu.c b/kernel/cpu.c index 8be22bd80933..fe2b8d0bfe4c 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -18,7 +18,7 @@ /* This protects CPUs going up and down... */ static DECLARE_MUTEX(cpucontrol); -static struct notifier_block *cpu_chain; +static BLOCKING_NOTIFIER_HEAD(cpu_chain); #ifdef CONFIG_HOTPLUG_CPU static struct task_struct *lock_cpu_hotplug_owner; @@ -71,21 +71,13 @@ EXPORT_SYMBOL_GPL(lock_cpu_hotplug_interruptible); /* Need to know about CPUs going up/down? */ int register_cpu_notifier(struct notifier_block *nb) { - int ret; - - if ((ret = lock_cpu_hotplug_interruptible()) != 0) - return ret; - ret = notifier_chain_register(&cpu_chain, nb); - unlock_cpu_hotplug(); - return ret; + return blocking_notifier_chain_register(&cpu_chain, nb); } EXPORT_SYMBOL(register_cpu_notifier); void unregister_cpu_notifier(struct notifier_block *nb) { - lock_cpu_hotplug(); - notifier_chain_unregister(&cpu_chain, nb); - unlock_cpu_hotplug(); + blocking_notifier_chain_unregister(&cpu_chain, nb); } EXPORT_SYMBOL(unregister_cpu_notifier); @@ -141,7 +133,7 @@ int cpu_down(unsigned int cpu) goto out; } - err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, + err = blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, (void *)(long)cpu); if (err == NOTIFY_BAD) { printk("%s: attempt to take down CPU %u failed\n", @@ -159,7 +151,7 @@ int cpu_down(unsigned int cpu) p = __stop_machine_run(take_cpu_down, NULL, cpu); if (IS_ERR(p)) { /* CPU didn't die: tell everyone. Can't complain. */ - if (notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED, + if (blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED, (void *)(long)cpu) == NOTIFY_BAD) BUG(); @@ -182,8 +174,8 @@ int cpu_down(unsigned int cpu) put_cpu(); /* CPU is completely dead: tell everyone. Too late to complain. */ - if (notifier_call_chain(&cpu_chain, CPU_DEAD, (void *)(long)cpu) - == NOTIFY_BAD) + if (blocking_notifier_call_chain(&cpu_chain, CPU_DEAD, + (void *)(long)cpu) == NOTIFY_BAD) BUG(); check_for_tasks(cpu); @@ -211,7 +203,7 @@ int __devinit cpu_up(unsigned int cpu) goto out; } - ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); + ret = blocking_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); if (ret == NOTIFY_BAD) { printk("%s: attempt to bring up CPU %u failed\n", __FUNCTION__, cpu); @@ -226,11 +218,12 @@ int __devinit cpu_up(unsigned int cpu) BUG_ON(!cpu_online(cpu)); /* Now call notifier in preparation. */ - notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu); + blocking_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu); out_notify: if (ret != 0) - notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu); + blocking_notifier_call_chain(&cpu_chain, + CPU_UP_CANCELED, hcpu); out: unlock_cpu_hotplug(); return ret; diff --git a/kernel/module.c b/kernel/module.c index ddfe45ac2fd1..4fafd58038a0 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -64,26 +64,17 @@ static DEFINE_SPINLOCK(modlist_lock); static DEFINE_MUTEX(module_mutex); static LIST_HEAD(modules); -static DEFINE_MUTEX(notify_mutex); -static struct notifier_block * module_notify_list; +static BLOCKING_NOTIFIER_HEAD(module_notify_list); int register_module_notifier(struct notifier_block * nb) { - int err; - mutex_lock(¬ify_mutex); - err = notifier_chain_register(&module_notify_list, nb); - mutex_unlock(¬ify_mutex); - return err; + return blocking_notifier_chain_register(&module_notify_list, nb); } EXPORT_SYMBOL(register_module_notifier); int unregister_module_notifier(struct notifier_block * nb) { - int err; - mutex_lock(¬ify_mutex); - err = notifier_chain_unregister(&module_notify_list, nb); - mutex_unlock(¬ify_mutex); - return err; + return blocking_notifier_chain_unregister(&module_notify_list, nb); } EXPORT_SYMBOL(unregister_module_notifier); @@ -1816,9 +1807,8 @@ sys_init_module(void __user *umod, /* Drop lock so they can recurse */ mutex_unlock(&module_mutex); - mutex_lock(¬ify_mutex); - notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod); - mutex_unlock(¬ify_mutex); + blocking_notifier_call_chain(&module_notify_list, + MODULE_STATE_COMING, mod); /* Start the module */ if (mod->init != NULL) diff --git a/kernel/panic.c b/kernel/panic.c index acd95adddb93..f895c7c01d5b 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -29,7 +29,7 @@ static DEFINE_SPINLOCK(pause_on_oops_lock); int panic_timeout; EXPORT_SYMBOL(panic_timeout); -struct notifier_block *panic_notifier_list; +ATOMIC_NOTIFIER_HEAD(panic_notifier_list); EXPORT_SYMBOL(panic_notifier_list); @@ -97,7 +97,7 @@ NORET_TYPE void panic(const char * fmt, ...) smp_send_stop(); #endif - notifier_call_chain(&panic_notifier_list, 0, buf); + atomic_notifier_call_chain(&panic_notifier_list, 0, buf); if (!panic_blink) panic_blink = no_blink; diff --git a/kernel/profile.c b/kernel/profile.c index ad81f799a9b4..5a730fdb1a2c 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -87,72 +87,52 @@ void __init profile_init(void) #ifdef CONFIG_PROFILING -static DECLARE_RWSEM(profile_rwsem); -static DEFINE_RWLOCK(handoff_lock); -static struct notifier_block * task_exit_notifier; -static struct notifier_block * task_free_notifier; -static struct notifier_block * munmap_notifier; +static BLOCKING_NOTIFIER_HEAD(task_exit_notifier); +static ATOMIC_NOTIFIER_HEAD(task_free_notifier); +static BLOCKING_NOTIFIER_HEAD(munmap_notifier); void profile_task_exit(struct task_struct * task) { - down_read(&profile_rwsem); - notifier_call_chain(&task_exit_notifier, 0, task); - up_read(&profile_rwsem); + blocking_notifier_call_chain(&task_exit_notifier, 0, task); } int profile_handoff_task(struct task_struct * task) { int ret; - read_lock(&handoff_lock); - ret = notifier_call_chain(&task_free_notifier, 0, task); - read_unlock(&handoff_lock); + ret = atomic_notifier_call_chain(&task_free_notifier, 0, task); return (ret == NOTIFY_OK) ? 1 : 0; } void profile_munmap(unsigned long addr) { - down_read(&profile_rwsem); - notifier_call_chain(&munmap_notifier, 0, (void *)addr); - up_read(&profile_rwsem); + blocking_notifier_call_chain(&munmap_notifier, 0, (void *)addr); } int task_handoff_register(struct notifier_block * n) { - int err = -EINVAL; - - write_lock(&handoff_lock); - err = notifier_chain_register(&task_free_notifier, n); - write_unlock(&handoff_lock); - return err; + return atomic_notifier_chain_register(&task_free_notifier, n); } int task_handoff_unregister(struct notifier_block * n) { - int err = -EINVAL; - - write_lock(&handoff_lock); - err = notifier_chain_unregister(&task_free_notifier, n); - write_unlock(&handoff_lock); - return err; + return atomic_notifier_chain_unregister(&task_free_notifier, n); } int profile_event_register(enum profile_type type, struct notifier_block * n) { int err = -EINVAL; - down_write(&profile_rwsem); - switch (type) { case PROFILE_TASK_EXIT: - err = notifier_chain_register(&task_exit_notifier, n); + err = blocking_notifier_chain_register( + &task_exit_notifier, n); break; case PROFILE_MUNMAP: - err = notifier_chain_register(&munmap_notifier, n); + err = blocking_notifier_chain_register( + &munmap_notifier, n); break; } - up_write(&profile_rwsem); - return err; } @@ -161,18 +141,17 @@ int profile_event_unregister(enum profile_type type, struct notifier_block * n) { int err = -EINVAL; - down_write(&profile_rwsem); - switch (type) { case PROFILE_TASK_EXIT: - err = notifier_chain_unregister(&task_exit_notifier, n); + err = blocking_notifier_chain_unregister( + &task_exit_notifier, n); break; case PROFILE_MUNMAP: - err = notifier_chain_unregister(&munmap_notifier, n); + err = blocking_notifier_chain_unregister( + &munmap_notifier, n); break; } - up_write(&profile_rwsem); return err; } diff --git a/kernel/softlockup.c b/kernel/softlockup.c index d9b3d5847ed8..ced91e1ff564 100644 --- a/kernel/softlockup.c +++ b/kernel/softlockup.c @@ -152,5 +152,5 @@ __init void spawn_softlockup_task(void) cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); register_cpu_notifier(&cpu_nfb); - notifier_chain_register(&panic_notifier_list, &panic_block); + atomic_notifier_chain_register(&panic_notifier_list, &panic_block); } diff --git a/kernel/sys.c b/kernel/sys.c index 38bc73ede2ba..c93d37f71aef 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -95,99 +95,304 @@ int cad_pid = 1; * and the like. */ -static struct notifier_block *reboot_notifier_list; -static DEFINE_RWLOCK(notifier_lock); +static BLOCKING_NOTIFIER_HEAD(reboot_notifier_list); + +/* + * Notifier chain core routines. The exported routines below + * are layered on top of these, with appropriate locking added. + */ + +static int notifier_chain_register(struct notifier_block **nl, + struct notifier_block *n) +{ + while ((*nl) != NULL) { + if (n->priority > (*nl)->priority) + break; + nl = &((*nl)->next); + } + n->next = *nl; + rcu_assign_pointer(*nl, n); + return 0; +} + +static int notifier_chain_unregister(struct notifier_block **nl, + struct notifier_block *n) +{ + while ((*nl) != NULL) { + if ((*nl) == n) { + rcu_assign_pointer(*nl, n->next); + return 0; + } + nl = &((*nl)->next); + } + return -ENOENT; +} + +static int __kprobes notifier_call_chain(struct notifier_block **nl, + unsigned long val, void *v) +{ + int ret = NOTIFY_DONE; + struct notifier_block *nb; + + nb = rcu_dereference(*nl); + while (nb) { + ret = nb->notifier_call(nb, val, v); + if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK) + break; + nb = rcu_dereference(nb->next); + } + return ret; +} + +/* + * Atomic notifier chain routines. Registration and unregistration + * use a mutex, and call_chain is synchronized by RCU (no locks). + */ /** - * notifier_chain_register - Add notifier to a notifier chain - * @list: Pointer to root list pointer + * atomic_notifier_chain_register - Add notifier to an atomic notifier chain + * @nh: Pointer to head of the atomic notifier chain * @n: New entry in notifier chain * - * Adds a notifier to a notifier chain. + * Adds a notifier to an atomic notifier chain. * * Currently always returns zero. */ + +int atomic_notifier_chain_register(struct atomic_notifier_head *nh, + struct notifier_block *n) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_register(&nh->head, n); + spin_unlock_irqrestore(&nh->lock, flags); + return ret; +} + +EXPORT_SYMBOL_GPL(atomic_notifier_chain_register); + +/** + * atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain + * @nh: Pointer to head of the atomic notifier chain + * @n: Entry to remove from notifier chain + * + * Removes a notifier from an atomic notifier chain. + * + * Returns zero on success or %-ENOENT on failure. + */ +int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, + struct notifier_block *n) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n); + spin_unlock_irqrestore(&nh->lock, flags); + synchronize_rcu(); + return ret; +} + +EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister); + +/** + * atomic_notifier_call_chain - Call functions in an atomic notifier chain + * @nh: Pointer to head of the atomic notifier chain + * @val: Value passed unmodified to notifier function + * @v: Pointer passed unmodified to notifier function + * + * Calls each function in a notifier chain in turn. The functions + * run in an atomic context, so they must not block. + * This routine uses RCU to synchronize with changes to the chain. + * + * If the return value of the notifier can be and'ed + * with %NOTIFY_STOP_MASK then atomic_notifier_call_chain + * will return immediately, with the return value of + * the notifier function which halted execution. + * Otherwise the return value is the return value + * of the last notifier function called. + */ -int notifier_chain_register(struct notifier_block **list, struct notifier_block *n) +int atomic_notifier_call_chain(struct atomic_notifier_head *nh, + unsigned long val, void *v) { - write_lock(¬ifier_lock); - while(*list) - { - if(n->priority > (*list)->priority) - break; - list= &((*list)->next); - } - n->next = *list; - *list=n; - write_unlock(¬ifier_lock); - return 0; + int ret; + + rcu_read_lock(); + ret = notifier_call_chain(&nh->head, val, v); + rcu_read_unlock(); + return ret; } -EXPORT_SYMBOL(notifier_chain_register); +EXPORT_SYMBOL_GPL(atomic_notifier_call_chain); + +/* + * Blocking notifier chain routines. All access to the chain is + * synchronized by an rwsem. + */ /** - * notifier_chain_unregister - Remove notifier from a notifier chain - * @nl: Pointer to root list pointer + * blocking_notifier_chain_register - Add notifier to a blocking notifier chain + * @nh: Pointer to head of the blocking notifier chain * @n: New entry in notifier chain * - * Removes a notifier from a notifier chain. + * Adds a notifier to a blocking notifier chain. + * Must be called in process context. * - * Returns zero on success, or %-ENOENT on failure. + * Currently always returns zero. */ -int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n) +int blocking_notifier_chain_register(struct blocking_notifier_head *nh, + struct notifier_block *n) { - write_lock(¬ifier_lock); - while((*nl)!=NULL) - { - if((*nl)==n) - { - *nl=n->next; - write_unlock(¬ifier_lock); - return 0; - } - nl=&((*nl)->next); - } - write_unlock(¬ifier_lock); - return -ENOENT; + int ret; + + /* + * This code gets used during boot-up, when task switching is + * not yet working and interrupts must remain disabled. At + * such times we must not call down_write(). + */ + if (unlikely(system_state == SYSTEM_BOOTING)) + return notifier_chain_register(&nh->head, n); + + down_write(&nh->rwsem); + ret = notifier_chain_register(&nh->head, n); + up_write(&nh->rwsem); + return ret; } -EXPORT_SYMBOL(notifier_chain_unregister); +EXPORT_SYMBOL_GPL(blocking_notifier_chain_register); /** - * notifier_call_chain - Call functions in a notifier chain - * @n: Pointer to root pointer of notifier chain + * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain + * @nh: Pointer to head of the blocking notifier chain + * @n: Entry to remove from notifier chain + * + * Removes a notifier from a blocking notifier chain. + * Must be called from process context. + * + * Returns zero on success or %-ENOENT on failure. + */ +int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, + struct notifier_block *n) +{ + int ret; + + /* + * This code gets used during boot-up, when task switching is + * not yet working and interrupts must remain disabled. At + * such times we must not call down_write(). + */ + if (unlikely(system_state == SYSTEM_BOOTING)) + return notifier_chain_unregister(&nh->head, n); + + down_write(&nh->rwsem); + ret = notifier_chain_unregister(&nh->head, n); + up_write(&nh->rwsem); + return ret; +} + +EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister); + +/** + * blocking_notifier_call_chain - Call functions in a blocking notifier chain + * @nh: Pointer to head of the blocking notifier chain * @val: Value passed unmodified to notifier function * @v: Pointer passed unmodified to notifier function * - * Calls each function in a notifier chain in turn. + * Calls each function in a notifier chain in turn. The functions + * run in a process context, so they are allowed to block. * - * If the return value of the notifier can be and'd - * with %NOTIFY_STOP_MASK, then notifier_call_chain + * If the return value of the notifier can be and'ed + * with %NOTIFY_STOP_MASK then blocking_notifier_call_chain * will return immediately, with the return value of * the notifier function which halted execution. - * Otherwise, the return value is the return value + * Otherwise the return value is the return value * of the last notifier function called. */ -int __kprobes notifier_call_chain(struct notifier_block **n, unsigned long val, void *v) +int blocking_notifier_call_chain(struct blocking_notifier_head *nh, + unsigned long val, void *v) { - int ret=NOTIFY_DONE; - struct notifier_block *nb = *n; + int ret; - while(nb) - { - ret=nb->notifier_call(nb,val,v); - if(ret&NOTIFY_STOP_MASK) - { - return ret; - } - nb=nb->next; - } + down_read(&nh->rwsem); + ret = notifier_call_chain(&nh->head, val, v); + up_read(&nh->rwsem); return ret; } -EXPORT_SYMBOL(notifier_call_chain); +EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); + +/* + * Raw notifier chain routines. There is no protection; + * the caller must provide it. Use at your own risk! + */ + +/** + * raw_notifier_chain_register - Add notifier to a raw notifier chain + * @nh: Pointer to head of the raw notifier chain + * @n: New entry in notifier chain + * + * Adds a notifier to a raw notifier chain. + * All locking must be provided by the caller. + * + * Currently always returns zero. + */ + +int raw_notifier_chain_register(struct raw_notifier_head *nh, + struct notifier_block *n) +{ + return notifier_chain_register(&nh->head, n); +} + +EXPORT_SYMBOL_GPL(raw_notifier_chain_register); + +/** + * raw_notifier_chain_unregister - Remove notifier from a raw notifier chain + * @nh: Pointer to head of the raw notifier chain + * @n: Entry to remove from notifier chain + * + * Removes a notifier from a raw notifier chain. + * All locking must be provided by the caller. + * + * Returns zero on success or %-ENOENT on failure. + */ +int raw_notifier_chain_unregister(struct raw_notifier_head *nh, + struct notifier_block *n) +{ + return notifier_chain_unregister(&nh->head, n); +} + +EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister); + +/** + * raw_notifier_call_chain - Call functions in a raw notifier chain + * @nh: Pointer to head of the raw notifier chain + * @val: Value passed unmodified to notifier function + * @v: Pointer passed unmodified to notifier function + * + * Calls each function in a notifier chain in turn. The functions + * run in an undefined context. + * All locking must be provided by the caller. + * + * If the return value of the notifier can be and'ed + * with %NOTIFY_STOP_MASK then raw_notifier_call_chain + * will return immediately, with the return value of + * the notifier function which halted execution. + * Otherwise the return value is the return value + * of the last notifier function called. + */ + +int raw_notifier_call_chain(struct raw_notifier_head *nh, + unsigned long val, void *v) +{ + return notifier_call_chain(&nh->head, val, v); +} + +EXPORT_SYMBOL_GPL(raw_notifier_call_chain); /** * register_reboot_notifier - Register function to be called at reboot time @@ -196,13 +401,13 @@ EXPORT_SYMBOL(notifier_call_chain); * Registers a function with the list of functions * to be called at reboot time. * - * Currently always returns zero, as notifier_chain_register + * Currently always returns zero, as blocking_notifier_chain_register * always returns zero. */ int register_reboot_notifier(struct notifier_block * nb) { - return notifier_chain_register(&reboot_notifier_list, nb); + return blocking_notifier_chain_register(&reboot_notifier_list, nb); } EXPORT_SYMBOL(register_reboot_notifier); @@ -219,7 +424,7 @@ EXPORT_SYMBOL(register_reboot_notifier); int unregister_reboot_notifier(struct notifier_block * nb) { - return notifier_chain_unregister(&reboot_notifier_list, nb); + return blocking_notifier_chain_unregister(&reboot_notifier_list, nb); } EXPORT_SYMBOL(unregister_reboot_notifier); @@ -380,7 +585,7 @@ EXPORT_SYMBOL_GPL(emergency_restart); void kernel_restart_prepare(char *cmd) { - notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); + blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); system_state = SYSTEM_RESTART; device_shutdown(); } @@ -430,7 +635,7 @@ EXPORT_SYMBOL_GPL(kernel_kexec); void kernel_shutdown_prepare(enum system_states state) { - notifier_call_chain(&reboot_notifier_list, + blocking_notifier_call_chain(&reboot_notifier_list, (state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL); system_state = state; device_shutdown(); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 9106354c781e..a49a6975092d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -73,23 +73,23 @@ DEFINE_RWLOCK(hci_cb_list_lock); struct hci_proto *hci_proto[HCI_MAX_PROTO]; /* HCI notifiers list */ -static struct notifier_block *hci_notifier; +static ATOMIC_NOTIFIER_HEAD(hci_notifier); /* ---- HCI notifications ---- */ int hci_register_notifier(struct notifier_block *nb) { - return notifier_chain_register(&hci_notifier, nb); + return atomic_notifier_chain_register(&hci_notifier, nb); } int hci_unregister_notifier(struct notifier_block *nb) { - return notifier_chain_unregister(&hci_notifier, nb); + return atomic_notifier_chain_unregister(&hci_notifier, nb); } static void hci_notify(struct hci_dev *hdev, int event) { - notifier_call_chain(&hci_notifier, event, hdev); + atomic_notifier_call_chain(&hci_notifier, event, hdev); } /* ---- HCI requests ---- */ diff --git a/net/core/dev.c b/net/core/dev.c index 8e1dc3051222..a3ab11f34153 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -193,7 +193,7 @@ static inline struct hlist_head *dev_index_hash(int ifindex) * Our notifier list */ -static struct notifier_block *netdev_chain; +static BLOCKING_NOTIFIER_HEAD(netdev_chain); /* * Device drivers call our routines to queue packets here. We empty the @@ -736,7 +736,8 @@ int dev_change_name(struct net_device *dev, char *newname) if (!err) { hlist_del(&dev->name_hlist); hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); - notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); + blocking_notifier_call_chain(&netdev_chain, + NETDEV_CHANGENAME, dev); } return err; @@ -750,7 +751,7 @@ int dev_change_name(struct net_device *dev, char *newname) */ void netdev_features_change(struct net_device *dev) { - notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev); + blocking_notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev); } EXPORT_SYMBOL(netdev_features_change); @@ -765,7 +766,8 @@ EXPORT_SYMBOL(netdev_features_change); void netdev_state_change(struct net_device *dev) { if (dev->flags & IFF_UP) { - notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev); + blocking_notifier_call_chain(&netdev_chain, + NETDEV_CHANGE, dev); rtmsg_ifinfo(RTM_NEWLINK, dev, 0); } } @@ -862,7 +864,7 @@ int dev_open(struct net_device *dev) /* * ... and announce new interface. */ - notifier_call_chain(&netdev_chain, NETDEV_UP, dev); + blocking_notifier_call_chain(&netdev_chain, NETDEV_UP, dev); } return ret; } @@ -885,7 +887,7 @@ int dev_close(struct net_device *dev) * Tell people we are going down, so that they can * prepare to death, when device is still operating. */ - notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev); + blocking_notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev); dev_deactivate(dev); @@ -922,7 +924,7 @@ int dev_close(struct net_device *dev) /* * Tell people we are down */ - notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev); + blocking_notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev); return 0; } @@ -953,7 +955,7 @@ int register_netdevice_notifier(struct notifier_block *nb) int err; rtnl_lock(); - err = notifier_chain_register(&netdev_chain, nb); + err = blocking_notifier_chain_register(&netdev_chain, nb); if (!err) { for (dev = dev_base; dev; dev = dev->next) { nb->notifier_call(nb, NETDEV_REGISTER, dev); @@ -981,7 +983,7 @@ int unregister_netdevice_notifier(struct notifier_block *nb) int err; rtnl_lock(); - err = notifier_chain_unregister(&netdev_chain, nb); + err = blocking_notifier_chain_unregister(&netdev_chain, nb); rtnl_unlock(); return err; } @@ -992,12 +994,12 @@ int unregister_netdevice_notifier(struct notifier_block *nb) * @v: pointer passed unmodified to notifier function * * Call all network notifier blocks. Parameters and return value - * are as for notifier_call_chain(). + * are as for blocking_notifier_call_chain(). */ int call_netdevice_notifiers(unsigned long val, void *v) { - return notifier_call_chain(&netdev_chain, val, v); + return blocking_notifier_call_chain(&netdev_chain, val, v); } /* When > 0 there are consumers of rx skb time stamps */ @@ -2242,7 +2244,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags) if (dev->flags & IFF_UP && ((old_flags ^ dev->flags) &~ (IFF_UP | IFF_PROMISC | IFF_ALLMULTI | IFF_VOLATILE))) - notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev); + blocking_notifier_call_chain(&netdev_chain, + NETDEV_CHANGE, dev); if ((flags ^ dev->gflags) & IFF_PROMISC) { int inc = (flags & IFF_PROMISC) ? +1 : -1; @@ -2286,8 +2289,8 @@ int dev_set_mtu(struct net_device *dev, int new_mtu) else dev->mtu = new_mtu; if (!err && dev->flags & IFF_UP) - notifier_call_chain(&netdev_chain, - NETDEV_CHANGEMTU, dev); + blocking_notifier_call_chain(&netdev_chain, + NETDEV_CHANGEMTU, dev); return err; } @@ -2303,7 +2306,8 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) return -ENODEV; err = dev->set_mac_address(dev, sa); if (!err) - notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev); + blocking_notifier_call_chain(&netdev_chain, + NETDEV_CHANGEADDR, dev); return err; } @@ -2359,7 +2363,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd) return -EINVAL; memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len)); - notifier_call_chain(&netdev_chain, + blocking_notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev); return 0; @@ -2813,7 +2817,7 @@ int register_netdevice(struct net_device *dev) write_unlock_bh(&dev_base_lock); /* Notify protocols, that a new device appeared. */ - notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev); + blocking_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev); /* Finish registration after unlock */ net_set_todo(dev); @@ -2892,7 +2896,7 @@ static void netdev_wait_allrefs(struct net_device *dev) rtnl_lock(); /* Rebroadcast unregister notification */ - notifier_call_chain(&netdev_chain, + blocking_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); if (test_bit(__LINK_STATE_LINKWATCH_PENDING, @@ -3148,7 +3152,7 @@ int unregister_netdevice(struct net_device *dev) /* Notify protocols, that we are about to destroy this device. They should clean all the things. */ - notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); + blocking_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); /* * Flush the multicast chain diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index cc7b9d9255ef..d2ae9893ca17 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -68,7 +68,7 @@ __le16 decnet_address = 0; static DEFINE_RWLOCK(dndev_lock); static struct net_device *decnet_default_device; -static struct notifier_block *dnaddr_chain; +static BLOCKING_NOTIFIER_HEAD(dnaddr_chain); static struct dn_dev *dn_dev_create(struct net_device *dev, int *err); static void dn_dev_delete(struct net_device *dev); @@ -446,7 +446,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de } rtmsg_ifa(RTM_DELADDR, ifa1); - notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1); + blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1); if (destroy) { dn_dev_free_ifa(ifa1); @@ -481,7 +481,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) dn_db->ifa_list = ifa; rtmsg_ifa(RTM_NEWADDR, ifa); - notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); + blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); return 0; } @@ -1285,12 +1285,12 @@ void dn_dev_devices_on(void) int register_dnaddr_notifier(struct notifier_block *nb) { - return notifier_chain_register(&dnaddr_chain, nb); + return blocking_notifier_chain_register(&dnaddr_chain, nb); } int unregister_dnaddr_notifier(struct notifier_block *nb) { - return notifier_chain_unregister(&dnaddr_chain, nb); + return blocking_notifier_chain_unregister(&dnaddr_chain, nb); } #ifdef CONFIG_PROC_FS diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 44fdf1413e2c..81c2f7885292 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -81,7 +81,7 @@ static struct ipv4_devconf ipv4_devconf_dflt = { static void rtmsg_ifa(int event, struct in_ifaddr *); -static struct notifier_block *inetaddr_chain; +static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy); #ifdef CONFIG_SYSCTL @@ -267,7 +267,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, *ifap1 = ifa->ifa_next; rtmsg_ifa(RTM_DELADDR, ifa); - notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); + blocking_notifier_call_chain(&inetaddr_chain, + NETDEV_DOWN, ifa); inet_free_ifa(ifa); } else { promote = ifa; @@ -291,7 +292,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, So that, this order is correct. */ rtmsg_ifa(RTM_DELADDR, ifa1); - notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); + blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); if (promote) { @@ -303,7 +304,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, promote->ifa_flags &= ~IFA_F_SECONDARY; rtmsg_ifa(RTM_NEWADDR, promote); - notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote); + blocking_notifier_call_chain(&inetaddr_chain, + NETDEV_UP, promote); for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { if (ifa1->ifa_mask != ifa->ifa_mask || !inet_ifa_match(ifa1->ifa_address, ifa)) @@ -366,7 +368,7 @@ static int inet_insert_ifa(struct in_ifaddr *ifa) Notifier will trigger FIB update, so that listeners of netlink will know about new ifaddr */ rtmsg_ifa(RTM_NEWADDR, ifa); - notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); + blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); return 0; } @@ -938,12 +940,12 @@ u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scop int register_inetaddr_notifier(struct notifier_block *nb) { - return notifier_chain_register(&inetaddr_chain, nb); + return blocking_notifier_chain_register(&inetaddr_chain, nb); } int unregister_inetaddr_notifier(struct notifier_block *nb) { - return notifier_chain_unregister(&inetaddr_chain, nb); + return blocking_notifier_chain_unregister(&inetaddr_chain, nb); } /* Rename ifa_labels for a device name change. Make some effort to preserve existing diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 9e34034729a6..ceaabc18202b 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -80,8 +80,8 @@ static int ip_conntrack_vmalloc; static unsigned int ip_conntrack_next_id; static unsigned int ip_conntrack_expect_next_id; #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS -struct notifier_block *ip_conntrack_chain; -struct notifier_block *ip_conntrack_expect_chain; +ATOMIC_NOTIFIER_HEAD(ip_conntrack_chain); +ATOMIC_NOTIFIER_HEAD(ip_conntrack_expect_chain); DEFINE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache); @@ -92,7 +92,7 @@ __ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ecache) { DEBUGP("ecache: delivering events for %p\n", ecache->ct); if (is_confirmed(ecache->ct) && !is_dying(ecache->ct) && ecache->events) - notifier_call_chain(&ip_conntrack_chain, ecache->events, + atomic_notifier_call_chain(&ip_conntrack_chain, ecache->events, ecache->ct); ecache->events = 0; ip_conntrack_put(ecache->ct); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 01c62a0d3742..445006ee4522 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -143,7 +143,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, struct prefix_info *pinfo); static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev); -static struct notifier_block *inet6addr_chain; +static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); struct ipv6_devconf ipv6_devconf = { .forwarding = 0, @@ -593,7 +593,7 @@ out2: read_unlock_bh(&addrconf_lock); if (likely(err == 0)) - notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); + atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); else { kfree(ifa); ifa = ERR_PTR(err); @@ -688,7 +688,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) ipv6_ifa_notify(RTM_DELADDR, ifp); - notifier_call_chain(&inet6addr_chain,NETDEV_DOWN,ifp); + atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp); addrconf_del_timer(ifp); @@ -3767,12 +3767,12 @@ static void addrconf_sysctl_unregister(struct ipv6_devconf *p) int register_inet6addr_notifier(struct notifier_block *nb) { - return notifier_chain_register(&inet6addr_chain, nb); + return atomic_notifier_chain_register(&inet6addr_chain, nb); } int unregister_inet6addr_notifier(struct notifier_block *nb) { - return notifier_chain_unregister(&inet6addr_chain,nb); + return atomic_notifier_chain_unregister(&inet6addr_chain,nb); } /* diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0ae281d9bfc3..56389c83557c 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -90,8 +90,8 @@ static int nf_conntrack_vmalloc; static unsigned int nf_conntrack_next_id; static unsigned int nf_conntrack_expect_next_id; #ifdef CONFIG_NF_CONNTRACK_EVENTS -struct notifier_block *nf_conntrack_chain; -struct notifier_block *nf_conntrack_expect_chain; +ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain); +ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain); DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); @@ -103,7 +103,7 @@ __nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache) DEBUGP("ecache: delivering events for %p\n", ecache->ct); if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct) && ecache->events) - notifier_call_chain(&nf_conntrack_chain, ecache->events, + atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events, ecache->ct); ecache->events = 0; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d00a9034cb5f..2a233ffcf618 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -123,7 +123,7 @@ static void netlink_destroy_callback(struct netlink_callback *cb); static DEFINE_RWLOCK(nl_table_lock); static atomic_t nl_table_users = ATOMIC_INIT(0); -static struct notifier_block *netlink_chain; +static ATOMIC_NOTIFIER_HEAD(netlink_chain); static u32 netlink_group_mask(u32 group) { @@ -469,7 +469,8 @@ static int netlink_release(struct socket *sock) .protocol = sk->sk_protocol, .pid = nlk->pid, }; - notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n); + atomic_notifier_call_chain(&netlink_chain, + NETLINK_URELEASE, &n); } if (nlk->module) @@ -1695,12 +1696,12 @@ static struct file_operations netlink_seq_fops = { int netlink_register_notifier(struct notifier_block *nb) { - return notifier_chain_register(&netlink_chain, nb); + return atomic_notifier_chain_register(&netlink_chain, nb); } int netlink_unregister_notifier(struct notifier_block *nb) { - return notifier_chain_unregister(&netlink_chain, nb); + return atomic_notifier_chain_unregister(&netlink_chain, nb); } static const struct proto_ops netlink_ops = { -- cgit v1.2.3-59-g8ed1b From c58411e95d7f5062dedd1a3064af4d359da1e633 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:34 -0800 Subject: [PATCH] RTC Subsystem: library functions RTC and date/time related functions. Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/rtc/Kconfig | 6 +++ drivers/rtc/Makefile | 5 +++ drivers/rtc/rtc-lib.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/rtc.h | 5 +++ 6 files changed, 120 insertions(+) create mode 100644 drivers/rtc/Kconfig create mode 100644 drivers/rtc/Makefile create mode 100644 drivers/rtc/rtc-lib.c (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index bddf431bbb72..9f5c0da57c90 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -70,4 +70,6 @@ source "drivers/sn/Kconfig" source "drivers/edac/Kconfig" +source "drivers/rtc/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 5c69b86db624..424955274e60 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_USB_GADGET) += usb/gadget/ obj-$(CONFIG_GAMEPORT) += input/gameport/ obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_I2O) += message/ +obj-$(CONFIG_RTC_LIB) += rtc/ obj-$(CONFIG_I2C) += i2c/ obj-$(CONFIG_W1) += w1/ obj-$(CONFIG_HWMON) += hwmon/ diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig new file mode 100644 index 000000000000..15df7c130fa6 --- /dev/null +++ b/drivers/rtc/Kconfig @@ -0,0 +1,6 @@ +# +# RTC class/drivers configuration +# + +config RTC_LIB + tristate \ No newline at end of file diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile new file mode 100644 index 000000000000..eb9ad77c3e95 --- /dev/null +++ b/drivers/rtc/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for RTC class/drivers. +# + +obj-$(CONFIG_RTC_LIB) += rtc-lib.o diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c new file mode 100644 index 000000000000..cfedc1d28ee1 --- /dev/null +++ b/drivers/rtc/rtc-lib.c @@ -0,0 +1,101 @@ +/* + * rtc and date/time utility functions + * + * Copyright (C) 2005-06 Tower Technologies + * Author: Alessandro Zummo + * + * based on arch/arm/common/rtctime.c and other bits + * + * 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 + +static const unsigned char rtc_days_in_month[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) +#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400)) + +int rtc_month_days(unsigned int month, unsigned int year) +{ + return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1); +} +EXPORT_SYMBOL(rtc_month_days); + +/* + * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. + */ +void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) +{ + register int days, month, year; + + days = time / 86400; + time -= days * 86400; + + /* day of the week, 1970-01-01 was a Thursday */ + tm->tm_wday = (days + 4) % 7; + + year = 1970 + days / 365; + days -= (year - 1970) * 365 + + LEAPS_THRU_END_OF(year - 1) + - LEAPS_THRU_END_OF(1970 - 1); + if (days < 0) { + year -= 1; + days += 365 + LEAP_YEAR(year); + } + tm->tm_year = year - 1900; + tm->tm_yday = days + 1; + + for (month = 0; month < 11; month++) { + int newdays; + + newdays = days - rtc_month_days(month, year); + if (newdays < 0) + break; + days = newdays; + } + tm->tm_mon = month; + tm->tm_mday = days + 1; + + tm->tm_hour = time / 3600; + time -= tm->tm_hour * 3600; + tm->tm_min = time / 60; + tm->tm_sec = time - tm->tm_min * 60; +} +EXPORT_SYMBOL(rtc_time_to_tm); + +/* + * Does the rtc_time represent a valid date/time? + */ +int rtc_valid_tm(struct rtc_time *tm) +{ + if (tm->tm_year < 70 + || tm->tm_mon >= 12 + || tm->tm_mday < 1 + || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900) + || tm->tm_hour >= 24 + || tm->tm_min >= 60 + || tm->tm_sec >= 60) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(rtc_valid_tm); + +/* + * Convert Gregorian date to seconds since 01-01-1970 00:00:00. + */ +int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) +{ + *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + return 0; +} +EXPORT_SYMBOL(rtc_tm_to_time); + +MODULE_LICENSE("GPL"); diff --git a/include/linux/rtc.h b/include/linux/rtc.h index b739ac1f7ca0..8454337c7058 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -95,6 +95,11 @@ struct rtc_pll_info { #include +extern int rtc_month_days(unsigned int month, unsigned int year); +extern int rtc_valid_tm(struct rtc_time *tm); +extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time); +extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm); + typedef struct rtc_task { void (*func)(void *private_data); void *private_data; -- cgit v1.2.3-59-g8ed1b From 12b824fb15a37cdcdfa3e92c9e912a07cc6f7a24 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:35 -0800 Subject: [PATCH] RTC subsystem: ARM cleanup This patch removes from the ARM subsytem some of the rtc-related functions that have been included in the RTC subsystem. It also fixes some naming collisions. Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/Kconfig | 3 ++ arch/arm/common/rtctime.c | 108 ++++++---------------------------------------- drivers/char/Kconfig | 2 +- include/asm-arm/rtc.h | 3 -- 4 files changed, 17 insertions(+), 99 deletions(-) (limited to 'drivers') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index bf2e72698d02..9731b3f826ab 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -8,6 +8,7 @@ mainmenu "Linux Kernel Configuration" config ARM bool default y + select RTC_LIB help The ARM series is a line of low-power-consumption RISC chip designs licensed by ARM Ltd and targeted at embedded applications and @@ -839,6 +840,8 @@ source "drivers/usb/Kconfig" source "drivers/mmc/Kconfig" +source "drivers/rtc/Kconfig" + endmenu source "fs/Kconfig" diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c index e851d86c212c..35c9a64ac14c 100644 --- a/arch/arm/common/rtctime.c +++ b/arch/arm/common/rtctime.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -42,89 +43,6 @@ static struct rtc_ops *rtc_ops; #define rtc_epoch 1900UL -static const unsigned char days_in_month[] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) -#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400)) - -static int month_days(unsigned int month, unsigned int year) -{ - return days_in_month[month] + (LEAP_YEAR(year) && month == 1); -} - -/* - * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. - */ -void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) -{ - int days, month, year; - - days = time / 86400; - time -= days * 86400; - - tm->tm_wday = (days + 4) % 7; - - year = 1970 + days / 365; - days -= (year - 1970) * 365 - + LEAPS_THRU_END_OF(year - 1) - - LEAPS_THRU_END_OF(1970 - 1); - if (days < 0) { - year -= 1; - days += 365 + LEAP_YEAR(year); - } - tm->tm_year = year - 1900; - tm->tm_yday = days + 1; - - for (month = 0; month < 11; month++) { - int newdays; - - newdays = days - month_days(month, year); - if (newdays < 0) - break; - days = newdays; - } - tm->tm_mon = month; - tm->tm_mday = days + 1; - - tm->tm_hour = time / 3600; - time -= tm->tm_hour * 3600; - tm->tm_min = time / 60; - tm->tm_sec = time - tm->tm_min * 60; -} -EXPORT_SYMBOL(rtc_time_to_tm); - -/* - * Does the rtc_time represent a valid date/time? - */ -int rtc_valid_tm(struct rtc_time *tm) -{ - if (tm->tm_year < 70 || - tm->tm_mon >= 12 || - tm->tm_mday < 1 || - tm->tm_mday > month_days(tm->tm_mon, tm->tm_year + 1900) || - tm->tm_hour >= 24 || - tm->tm_min >= 60 || - tm->tm_sec >= 60) - return -EINVAL; - - return 0; -} -EXPORT_SYMBOL(rtc_valid_tm); - -/* - * Convert Gregorian date to seconds since 01-01-1970 00:00:00. - */ -int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) -{ - *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - - return 0; -} -EXPORT_SYMBOL(rtc_tm_to_time); - /* * Calculate the next alarm time given the requested alarm time mask * and the current time. @@ -151,13 +69,13 @@ void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc } } -static inline int rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm) +static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm) { memset(tm, 0, sizeof(struct rtc_time)); return ops->read_time(tm); } -static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm) +static inline int rtc_arm_set_time(struct rtc_ops *ops, struct rtc_time *tm) { int ret; @@ -168,7 +86,7 @@ static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm) return ret; } -static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) +static inline int rtc_arm_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) { int ret = -EINVAL; if (ops->read_alarm) { @@ -178,7 +96,7 @@ static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) return ret; } -static inline int rtc_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) +static inline int rtc_arm_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) { int ret = -EINVAL; if (ops->set_alarm) @@ -266,7 +184,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, switch (cmd) { case RTC_ALM_READ: - ret = rtc_read_alarm(ops, &alrm); + ret = rtc_arm_read_alarm(ops, &alrm); if (ret) break; ret = copy_to_user(uarg, &alrm.time, sizeof(tm)); @@ -288,11 +206,11 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, alrm.time.tm_wday = -1; alrm.time.tm_yday = -1; alrm.time.tm_isdst = -1; - ret = rtc_set_alarm(ops, &alrm); + ret = rtc_arm_set_alarm(ops, &alrm); break; case RTC_RD_TIME: - ret = rtc_read_time(ops, &tm); + ret = rtc_arm_read_time(ops, &tm); if (ret) break; ret = copy_to_user(uarg, &tm, sizeof(tm)); @@ -310,7 +228,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ret = -EFAULT; break; } - ret = rtc_set_time(ops, &tm); + ret = rtc_arm_set_time(ops, &tm); break; case RTC_EPOCH_SET: @@ -341,11 +259,11 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ret = -EFAULT; break; } - ret = rtc_set_alarm(ops, &alrm); + ret = rtc_arm_set_alarm(ops, &alrm); break; case RTC_WKALM_RD: - ret = rtc_read_alarm(ops, &alrm); + ret = rtc_arm_read_alarm(ops, &alrm); if (ret) break; ret = copy_to_user(uarg, &alrm, sizeof(alrm)); @@ -435,7 +353,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo struct rtc_time tm; char *p = page; - if (rtc_read_time(ops, &tm) == 0) { + if (rtc_arm_read_time(ops, &tm) == 0) { p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n" "rtc_date\t: %04d-%02d-%02d\n" @@ -445,7 +363,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo rtc_epoch); } - if (rtc_read_alarm(ops, &alrm) == 0) { + if (rtc_arm_read_alarm(ops, &alrm) == 0) { p += sprintf(p, "alrm_time\t: "); if ((unsigned int)alrm.time.tm_hour <= 24) p += sprintf(p, "%02d:", alrm.time.tm_hour); diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index facc3f1d9e37..73d30bf01582 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -696,7 +696,7 @@ config NVRAM config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV + depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you diff --git a/include/asm-arm/rtc.h b/include/asm-arm/rtc.h index 370dfe77589d..1a5c9232a91e 100644 --- a/include/asm-arm/rtc.h +++ b/include/asm-arm/rtc.h @@ -25,9 +25,6 @@ struct rtc_ops { int (*proc)(char *buf); }; -void rtc_time_to_tm(unsigned long, struct rtc_time *); -int rtc_tm_to_time(struct rtc_time *, unsigned long *); -int rtc_valid_tm(struct rtc_time *); void rtc_next_alarm_time(struct rtc_time *, struct rtc_time *, struct rtc_time *); void rtc_update(unsigned long, unsigned long); int register_rtc(struct rtc_ops *); -- cgit v1.2.3-59-g8ed1b From 0c86edc0d4970649f39748c4ce4f2895f728468f Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:37 -0800 Subject: [PATCH] RTC subsystem: class Add the basic RTC subsystem infrastructure to the kernel. rtc/class.c - registration facilities for RTC drivers rtc/interface.c - kernel/rtc interface functions rtc/hctosys.c - snippet of code that copies hw clock to sw clock at bootup, if configured to do so. Signed-off-by: Alessandro Zummo Acked-by: Greg Kroah-Hartman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- CREDITS | 5 +- MAINTAINERS | 6 ++ drivers/rtc/Kconfig | 44 +++++++- drivers/rtc/Makefile | 5 +- drivers/rtc/class.c | 145 +++++++++++++++++++++++++ drivers/rtc/hctosys.c | 69 ++++++++++++ drivers/rtc/interface.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/rtc.h | 87 +++++++++++++++ 8 files changed, 633 insertions(+), 5 deletions(-) create mode 100644 drivers/rtc/class.c create mode 100644 drivers/rtc/hctosys.c create mode 100644 drivers/rtc/interface.c (limited to 'drivers') diff --git a/CREDITS b/CREDITS index c6d69bf10e15..35850d882c34 100644 --- a/CREDITS +++ b/CREDITS @@ -3741,10 +3741,11 @@ D: Mylex DAC960 PCI RAID driver D: Miscellaneous kernel fixes N: Alessandro Zummo -E: azummo@ita.flashnet.it -W: http://freepage.logicom.it/azummo/ +E: a.zummo@towertech.it D: CMI8330 support is sb_card.c D: ISAPnP fixes in sb_card.c +D: ZyXEL omni.net lcd plus driver +D: RTC subsystem S: Italy N: Marc Zyngier diff --git a/MAINTAINERS b/MAINTAINERS index f27846734b06..e5b051f0e27e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2233,6 +2233,12 @@ M: p_gortmaker@yahoo.com L: linux-kernel@vger.kernel.org S: Maintained +REAL TIME CLOCK (RTC) SUBSYSTEM +P: Alessandro Zummo +M: a.zummo@towertech.it +L: linux-kernel@vger.kernel.org +S: Maintained + REISERFS FILE SYSTEM P: Hans Reiser M: reiserfs-dev@namesys.com diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 15df7c130fa6..a256f67b78e4 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1,6 +1,46 @@ -# +\# # RTC class/drivers configuration # +menu "Real Time Clock" + config RTC_LIB - tristate \ No newline at end of file + tristate + +config RTC_CLASS + tristate "RTC class" + depends on EXPERIMENTAL + default n + select RTC_LIB + help + Generic RTC class support. If you say yes here, you will + be allowed to plug one or more RTCs to your system. You will + probably want to enable one of more of the interfaces below. + + This driver can also be built as a module. If so, the module + will be called rtc-class. + +config RTC_HCTOSYS + bool "Set system time from RTC on startup" + depends on RTC_CLASS = y + default y + help + If you say yes here, the system time will be set using + the value read from the specified RTC device. This is useful + in order to avoid unnecessary fschk runs. + +config RTC_HCTOSYS_DEVICE + string "The RTC to read the time from" + depends on RTC_HCTOSYS = y + default "rtc0" + help + The RTC device that will be used as the source for + the system time, usually rtc0. + +comment "RTC interfaces" + depends on RTC_CLASS + +comment "RTC drivers" + depends on RTC_CLASS + +endmenu diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index eb9ad77c3e95..7b87f3710dff 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -2,4 +2,7 @@ # Makefile for RTC class/drivers. # -obj-$(CONFIG_RTC_LIB) += rtc-lib.o +obj-$(CONFIG_RTC_LIB) += rtc-lib.o +obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o +obj-$(CONFIG_RTC_CLASS) += rtc-core.o +rtc-core-y := class.o interface.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c new file mode 100644 index 000000000000..8533936d50d8 --- /dev/null +++ b/drivers/rtc/class.c @@ -0,0 +1,145 @@ +/* + * RTC subsystem, base class + * + * Copyright (C) 2005 Tower Technologies + * Author: Alessandro Zummo + * + * class skeleton from drivers/hwmon/hwmon.c + * + * 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 +#include + +static DEFINE_IDR(rtc_idr); +static DEFINE_MUTEX(idr_lock); +struct class *rtc_class; + +static void rtc_device_release(struct class_device *class_dev) +{ + struct rtc_device *rtc = to_rtc_device(class_dev); + mutex_lock(&idr_lock); + idr_remove(&rtc_idr, rtc->id); + mutex_unlock(&idr_lock); + kfree(rtc); +} + +/** + * rtc_device_register - register w/ RTC class + * @dev: the device to register + * + * rtc_device_unregister() must be called when the class device is no + * longer needed. + * + * Returns the pointer to the new struct class device. + */ +struct rtc_device *rtc_device_register(const char *name, struct device *dev, + struct rtc_class_ops *ops, + struct module *owner) +{ + struct rtc_device *rtc; + int id, err; + + if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) { + err = -ENOMEM; + goto exit; + } + + + mutex_lock(&idr_lock); + err = idr_get_new(&rtc_idr, NULL, &id); + mutex_unlock(&idr_lock); + + if (err < 0) + goto exit; + + id = id & MAX_ID_MASK; + + rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); + if (rtc == NULL) { + err = -ENOMEM; + goto exit_idr; + } + + rtc->id = id; + rtc->ops = ops; + rtc->owner = owner; + rtc->class_dev.dev = dev; + rtc->class_dev.class = rtc_class; + rtc->class_dev.release = rtc_device_release; + + mutex_init(&rtc->ops_lock); + spin_lock_init(&rtc->irq_lock); + spin_lock_init(&rtc->irq_task_lock); + + strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); + snprintf(rtc->class_dev.class_id, BUS_ID_SIZE, "rtc%d", id); + + err = class_device_register(&rtc->class_dev); + if (err) + goto exit_kfree; + + dev_info(dev, "rtc core: registered %s as %s\n", + rtc->name, rtc->class_dev.class_id); + + return rtc; + +exit_kfree: + kfree(rtc); + +exit_idr: + idr_remove(&rtc_idr, id); + +exit: + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(rtc_device_register); + + +/** + * rtc_device_unregister - removes the previously registered RTC class device + * + * @rtc: the RTC class device to destroy + */ +void rtc_device_unregister(struct rtc_device *rtc) +{ + mutex_lock(&rtc->ops_lock); + rtc->ops = NULL; + mutex_unlock(&rtc->ops_lock); + class_device_unregister(&rtc->class_dev); +} +EXPORT_SYMBOL_GPL(rtc_device_unregister); + +int rtc_interface_register(struct class_interface *intf) +{ + intf->class = rtc_class; + return class_interface_register(intf); +} +EXPORT_SYMBOL_GPL(rtc_interface_register); + +static int __init rtc_init(void) +{ + rtc_class = class_create(THIS_MODULE, "rtc"); + if (IS_ERR(rtc_class)) { + printk(KERN_ERR "%s: couldn't create class\n", __FILE__); + return PTR_ERR(rtc_class); + } + return 0; +} + +static void __exit rtc_exit(void) +{ + class_destroy(rtc_class); +} + +module_init(rtc_init); +module_exit(rtc_exit); + +MODULE_AUTHOR("Alessandro Zummo "); +MODULE_DESCRIPTION("RTC class support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c new file mode 100644 index 000000000000..d02fe9a0001f --- /dev/null +++ b/drivers/rtc/hctosys.c @@ -0,0 +1,69 @@ +/* + * RTC subsystem, initialize system time on startup + * + * Copyright (C) 2005 Tower Technologies + * Author: Alessandro Zummo + * + * 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 + +/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary + * whether it stores the most close value or the value with partial + * seconds truncated. However, it is important that we use it to store + * the truncated value. This is because otherwise it is necessary, + * in an rtc sync function, to read both xtime.tv_sec and + * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read + * of >32bits is not possible. So storing the most close value would + * slow down the sync API. So here we have the truncated value and + * the best guess is to add 0.5s. + */ + +static int __init rtc_hctosys(void) +{ + int err; + struct rtc_time tm; + struct class_device *class_dev = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); + + if (class_dev == NULL) { + printk("%s: unable to open rtc device (%s)\n", + __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); + return -ENODEV; + } + + err = rtc_read_time(class_dev, &tm); + if (err == 0) { + err = rtc_valid_tm(&tm); + if (err == 0) { + struct timespec tv; + + tv.tv_nsec = NSEC_PER_SEC >> 1; + + rtc_tm_to_time(&tm, &tv.tv_sec); + + do_settimeofday(&tv); + + dev_info(class_dev->dev, + "setting the system clock to " + "%d-%02d-%02d %02d:%02d:%02d (%u)\n", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, + (unsigned int) tv.tv_sec); + } + else + dev_err(class_dev->dev, + "hctosys: invalid date/time\n"); + } + else + dev_err(class_dev->dev, + "hctosys: unable to read the hardware clock\n"); + + rtc_class_close(class_dev); + + return 0; +} + +late_initcall(rtc_hctosys); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c new file mode 100644 index 000000000000..56e490709b87 --- /dev/null +++ b/drivers/rtc/interface.c @@ -0,0 +1,277 @@ +/* + * RTC subsystem, interface functions + * + * Copyright (C) 2005 Tower Technologies + * Author: Alessandro Zummo + * + * based on arch/arm/common/rtctime.c + * + * 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 + +int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm) +{ + int err; + struct rtc_device *rtc = to_rtc_device(class_dev); + + err = mutex_lock_interruptible(&rtc->ops_lock); + if (err) + return -EBUSY; + + if (!rtc->ops) + err = -ENODEV; + else if (!rtc->ops->read_time) + err = -EINVAL; + else { + memset(tm, 0, sizeof(struct rtc_time)); + err = rtc->ops->read_time(class_dev->dev, tm); + } + + mutex_unlock(&rtc->ops_lock); + return err; +} +EXPORT_SYMBOL_GPL(rtc_read_time); + +int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm) +{ + int err; + struct rtc_device *rtc = to_rtc_device(class_dev); + + err = rtc_valid_tm(tm); + if (err != 0) + return err; + + err = mutex_lock_interruptible(&rtc->ops_lock); + if (err) + return -EBUSY; + + if (!rtc->ops) + err = -ENODEV; + else if (!rtc->ops->set_time) + err = -EINVAL; + else + err = rtc->ops->set_time(class_dev->dev, tm); + + mutex_unlock(&rtc->ops_lock); + return err; +} +EXPORT_SYMBOL_GPL(rtc_set_time); + +int rtc_set_mmss(struct class_device *class_dev, unsigned long secs) +{ + int err; + struct rtc_device *rtc = to_rtc_device(class_dev); + + err = mutex_lock_interruptible(&rtc->ops_lock); + if (err) + return -EBUSY; + + if (!rtc->ops) + err = -ENODEV; + else if (rtc->ops->set_mmss) + err = rtc->ops->set_mmss(class_dev->dev, secs); + else if (rtc->ops->read_time && rtc->ops->set_time) { + struct rtc_time new, old; + + err = rtc->ops->read_time(class_dev->dev, &old); + if (err == 0) { + rtc_time_to_tm(secs, &new); + + /* + * avoid writing when we're going to change the day of + * the month. We will retry in the next minute. This + * basically means that if the RTC must not drift + * by more than 1 minute in 11 minutes. + */ + if (!((old.tm_hour == 23 && old.tm_min == 59) || + (new.tm_hour == 23 && new.tm_min == 59))) + err = rtc->ops->set_time(class_dev->dev, &new); + } + } + else + err = -EINVAL; + + mutex_unlock(&rtc->ops_lock); + + return err; +} +EXPORT_SYMBOL_GPL(rtc_set_mmss); + +int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) +{ + int err; + struct rtc_device *rtc = to_rtc_device(class_dev); + + err = mutex_lock_interruptible(&rtc->ops_lock); + if (err) + return -EBUSY; + + if (rtc->ops == NULL) + err = -ENODEV; + else if (!rtc->ops->read_alarm) + err = -EINVAL; + else { + memset(alarm, 0, sizeof(struct rtc_wkalrm)); + err = rtc->ops->read_alarm(class_dev->dev, alarm); + } + + mutex_unlock(&rtc->ops_lock); + return err; +} +EXPORT_SYMBOL_GPL(rtc_read_alarm); + +int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) +{ + int err; + struct rtc_device *rtc = to_rtc_device(class_dev); + + err = mutex_lock_interruptible(&rtc->ops_lock); + if (err) + return -EBUSY; + + if (!rtc->ops) + err = -ENODEV; + else if (!rtc->ops->set_alarm) + err = -EINVAL; + else + err = rtc->ops->set_alarm(class_dev->dev, alarm); + + mutex_unlock(&rtc->ops_lock); + return err; +} +EXPORT_SYMBOL_GPL(rtc_set_alarm); + +void rtc_update_irq(struct class_device *class_dev, + unsigned long num, unsigned long events) +{ + struct rtc_device *rtc = to_rtc_device(class_dev); + + spin_lock(&rtc->irq_lock); + rtc->irq_data = (rtc->irq_data + (num << 8)) | events; + spin_unlock(&rtc->irq_lock); + + spin_lock(&rtc->irq_task_lock); + if (rtc->irq_task) + rtc->irq_task->func(rtc->irq_task->private_data); + spin_unlock(&rtc->irq_task_lock); + + wake_up_interruptible(&rtc->irq_queue); + kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); +} +EXPORT_SYMBOL_GPL(rtc_update_irq); + +struct class_device *rtc_class_open(char *name) +{ + struct class_device *class_dev = NULL, + *class_dev_tmp; + + down(&rtc_class->sem); + list_for_each_entry(class_dev_tmp, &rtc_class->children, node) { + if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) { + class_dev = class_dev_tmp; + break; + } + } + + if (class_dev) { + if (!try_module_get(to_rtc_device(class_dev)->owner)) + class_dev = NULL; + } + up(&rtc_class->sem); + + return class_dev; +} +EXPORT_SYMBOL_GPL(rtc_class_open); + +void rtc_class_close(struct class_device *class_dev) +{ + module_put(to_rtc_device(class_dev)->owner); +} +EXPORT_SYMBOL_GPL(rtc_class_close); + +int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task) +{ + int retval = -EBUSY; + struct rtc_device *rtc = to_rtc_device(class_dev); + + if (task == NULL || task->func == NULL) + return -EINVAL; + + spin_lock(&rtc->irq_task_lock); + if (rtc->irq_task == NULL) { + rtc->irq_task = task; + retval = 0; + } + spin_unlock(&rtc->irq_task_lock); + + return retval; +} +EXPORT_SYMBOL_GPL(rtc_irq_register); + +void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task) +{ + struct rtc_device *rtc = to_rtc_device(class_dev); + + spin_lock(&rtc->irq_task_lock); + if (rtc->irq_task == task) + rtc->irq_task = NULL; + spin_unlock(&rtc->irq_task_lock); +} +EXPORT_SYMBOL_GPL(rtc_irq_unregister); + +int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int enabled) +{ + int err = 0; + unsigned long flags; + struct rtc_device *rtc = to_rtc_device(class_dev); + + spin_lock_irqsave(&rtc->irq_task_lock, flags); + if (rtc->irq_task != task) + err = -ENXIO; + spin_unlock_irqrestore(&rtc->irq_task_lock, flags); + + if (err == 0) + err = rtc->ops->irq_set_state(class_dev->dev, enabled); + + return err; +} +EXPORT_SYMBOL_GPL(rtc_irq_set_state); + +int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq) +{ + int err = 0, tmp = 0; + unsigned long flags; + struct rtc_device *rtc = to_rtc_device(class_dev); + + /* allowed range is 2-8192 */ + if (freq < 2 || freq > 8192) + return -EINVAL; +/* + FIXME: this does not belong here, will move where appropriate + at a later stage. It cannot hurt right now, trust me :) + if ((freq > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE))) + return -EACCES; +*/ + /* check if freq is a power of 2 */ + while (freq > (1 << tmp)) + tmp++; + + if (freq != (1 << tmp)) + return -EINVAL; + + spin_lock_irqsave(&rtc->irq_task_lock, flags); + if (rtc->irq_task != task) + err = -ENXIO; + spin_unlock_irqrestore(&rtc->irq_task_lock, flags); + + if (err == 0) { + err = rtc->ops->irq_set_freq(class_dev->dev, freq); + if (err == 0) + rtc->irq_freq = freq; + } + return err; +} diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 8454337c7058..ab61cd1199f2 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -91,6 +91,12 @@ struct rtc_pll_info { #define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ #define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ +/* interrupt flags */ +#define RTC_IRQF 0x80 /* any of the following is active */ +#define RTC_PF 0x40 +#define RTC_AF 0x20 +#define RTC_UF 0x10 + #ifdef __KERNEL__ #include @@ -100,6 +106,87 @@ extern int rtc_valid_tm(struct rtc_time *tm); extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time); extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm); +#include +#include +#include +#include +#include + +extern struct class *rtc_class; + +struct rtc_class_ops { + int (*open)(struct device *); + void (*release)(struct device *); + int (*ioctl)(struct device *, unsigned int, unsigned long); + int (*read_time)(struct device *, struct rtc_time *); + int (*set_time)(struct device *, struct rtc_time *); + int (*read_alarm)(struct device *, struct rtc_wkalrm *); + int (*set_alarm)(struct device *, struct rtc_wkalrm *); + int (*proc)(struct device *, struct seq_file *); + int (*set_mmss)(struct device *, unsigned long secs); + int (*irq_set_state)(struct device *, int enabled); + int (*irq_set_freq)(struct device *, int freq); + int (*read_callback)(struct device *, int data); +}; + +#define RTC_DEVICE_NAME_SIZE 20 +struct rtc_task; + +struct rtc_device +{ + struct class_device class_dev; + struct module *owner; + + int id; + char name[RTC_DEVICE_NAME_SIZE]; + + struct rtc_class_ops *ops; + struct mutex ops_lock; + + struct class_device *rtc_dev; + struct cdev char_dev; + struct mutex char_lock; + + unsigned long irq_data; + spinlock_t irq_lock; + wait_queue_head_t irq_queue; + struct fasync_struct *async_queue; + + struct rtc_task *irq_task; + spinlock_t irq_task_lock; + int irq_freq; +}; +#define to_rtc_device(d) container_of(d, struct rtc_device, class_dev) + +extern struct rtc_device *rtc_device_register(const char *name, + struct device *dev, + struct rtc_class_ops *ops, + struct module *owner); +extern void rtc_device_unregister(struct rtc_device *rdev); +extern int rtc_interface_register(struct class_interface *intf); + +extern int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm); +extern int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm); +extern int rtc_set_mmss(struct class_device *class_dev, unsigned long secs); +extern int rtc_read_alarm(struct class_device *class_dev, + struct rtc_wkalrm *alrm); +extern int rtc_set_alarm(struct class_device *class_dev, + struct rtc_wkalrm *alrm); +extern void rtc_update_irq(struct class_device *class_dev, + unsigned long num, unsigned long events); + +extern struct class_device *rtc_class_open(char *name); +extern void rtc_class_close(struct class_device *class_dev); + +extern int rtc_irq_register(struct class_device *class_dev, + struct rtc_task *task); +extern void rtc_irq_unregister(struct class_device *class_dev, + struct rtc_task *task); +extern int rtc_irq_set_state(struct class_device *class_dev, + struct rtc_task *task, int enabled); +extern int rtc_irq_set_freq(struct class_device *class_dev, + struct rtc_task *task, int freq); + typedef struct rtc_task { void (*func)(void *private_data); void *private_data; -- cgit v1.2.3-59-g8ed1b From 6fc7f10cee28c7fa190920fefda8c696d5bf3074 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:37 -0800 Subject: [PATCH] RTC subsystem: I2C cleanup This patch, completely optional, removes from drivers/i2c/chips all the drivers that are implemented in the new RTC subsystem. It should be noted that none of the current driver is actually integrated, i.e. usable without further patches. Signed-off-by: Alessandro Zummo Acked-by: Greg Kroah-Hartman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/i2c/chips/Kconfig | 18 -- drivers/i2c/chips/Makefile | 2 - drivers/i2c/chips/rtc8564.c | 385 ------------------------ drivers/i2c/chips/rtc8564.h | 78 ----- drivers/i2c/chips/x1205.c | 698 -------------------------------------------- include/linux/x1205.h | 31 -- 6 files changed, 1212 deletions(-) delete mode 100644 drivers/i2c/chips/rtc8564.c delete mode 100644 drivers/i2c/chips/rtc8564.h delete mode 100644 drivers/i2c/chips/x1205.c delete mode 100644 include/linux/x1205.h (limited to 'drivers') diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index f9fae28f5612..7aa5c38f0855 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -65,15 +65,6 @@ config SENSORS_PCF8591 This driver can also be built as a module. If so, the module will be called pcf8591. -config SENSORS_RTC8564 - tristate "Epson 8564 RTC chip" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Epson 8564 RTC chip. - - This driver can also be built as a module. If so, the module - will be called i2c-rtc8564. - config ISP1301_OMAP tristate "Philips ISP1301 with OMAP OTG" depends on I2C && ARCH_OMAP_OTG @@ -126,13 +117,4 @@ config SENSORS_MAX6875 This driver can also be built as a module. If so, the module will be called max6875. -config RTC_X1205_I2C - tristate "Xicor X1205 RTC chip" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Xicor X1205 RTC chip. - - This driver can also be built as a module. If so, the module - will be called x1205. - endmenu diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index 46178b57b1f1..779868ef2e26 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -10,10 +10,8 @@ obj-$(CONFIG_SENSORS_M41T00) += m41t00.o obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o -obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TPS65010) += tps65010.o -obj-$(CONFIG_RTC_X1205_I2C) += x1205.o ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c deleted file mode 100644 index 0d8699b3f488..000000000000 --- a/drivers/i2c/chips/rtc8564.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * linux/drivers/i2c/chips/rtc8564.c - * - * Copyright (C) 2002-2004 Stefan Eletzhofer - * - * based on linux/drivers/acron/char/pcf8583.c - * Copyright (C) 2000 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. - * - * Driver for system3's EPSON RTC 8564 chip - */ -#include -#include -#include -#include -#include -#include -#include /* get the user-level API */ -#include - -#include "rtc8564.h" - -#ifdef DEBUG -# define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0); -#else -# define _DBG(x, fmt, args...) do { } while(0); -#endif - -#define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, " \ - "mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \ - (rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \ - (rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl); - -struct rtc8564_data { - struct i2c_client client; - u16 ctrl; -}; - -static inline u8 _rtc8564_ctrl1(struct i2c_client *client) -{ - struct rtc8564_data *data = i2c_get_clientdata(client); - return data->ctrl & 0xff; -} -static inline u8 _rtc8564_ctrl2(struct i2c_client *client) -{ - struct rtc8564_data *data = i2c_get_clientdata(client); - return (data->ctrl & 0xff00) >> 8; -} - -#define CTRL1(c) _rtc8564_ctrl1(c) -#define CTRL2(c) _rtc8564_ctrl2(c) - -static int debug; -module_param(debug, int, S_IRUGO | S_IWUSR); - -static struct i2c_driver rtc8564_driver; - -static unsigned short ignore[] = { I2C_CLIENT_END }; -static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END }; - -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_addr, - .probe = ignore, - .ignore = ignore, -}; - -static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem); -static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem); - -static int rtc8564_read(struct i2c_client *client, unsigned char adr, - unsigned char *buf, unsigned char len) -{ - int ret = -EIO; - unsigned char addr[1] = { adr }; - struct i2c_msg msgs[2] = { - {client->addr, 0, 1, addr}, - {client->addr, I2C_M_RD, len, buf} - }; - - _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len); - - if (!buf) { - ret = -EINVAL; - goto done; - } - - ret = i2c_transfer(client->adapter, msgs, 2); - if (ret == 2) { - ret = 0; - } - -done: - return ret; -} - -static int rtc8564_write(struct i2c_client *client, unsigned char adr, - unsigned char *data, unsigned char len) -{ - int ret = 0; - unsigned char _data[16]; - struct i2c_msg wr; - int i; - - if (!data || len > 15) { - ret = -EINVAL; - goto done; - } - - _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len); - - _data[0] = adr; - for (i = 0; i < len; i++) { - _data[i + 1] = data[i]; - _DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]); - } - - wr.addr = client->addr; - wr.flags = 0; - wr.len = len + 1; - wr.buf = _data; - - ret = i2c_transfer(client->adapter, &wr, 1); - if (ret == 1) { - ret = 0; - } - -done: - return ret; -} - -static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind) -{ - int ret; - struct i2c_client *new_client; - struct rtc8564_data *d; - unsigned char data[10]; - unsigned char ad[1] = { 0 }; - struct i2c_msg ctrl_wr[1] = { - {addr, 0, 2, data} - }; - struct i2c_msg ctrl_rd[2] = { - {addr, 0, 1, ad}, - {addr, I2C_M_RD, 2, data} - }; - - d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL); - if (!d) { - ret = -ENOMEM; - goto done; - } - new_client = &d->client; - - strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE); - i2c_set_clientdata(new_client, d); - new_client->addr = addr; - new_client->adapter = adap; - new_client->driver = &rtc8564_driver; - - _DBG(1, "client=%p", new_client); - - /* init ctrl1 reg */ - data[0] = 0; - data[1] = 0; - ret = i2c_transfer(new_client->adapter, ctrl_wr, 1); - if (ret != 1) { - printk(KERN_INFO "rtc8564: cant init ctrl1\n"); - ret = -ENODEV; - goto done; - } - - /* read back ctrl1 and ctrl2 */ - ret = i2c_transfer(new_client->adapter, ctrl_rd, 2); - if (ret != 2) { - printk(KERN_INFO "rtc8564: cant read ctrl\n"); - ret = -ENODEV; - goto done; - } - - d->ctrl = data[0] | (data[1] << 8); - - _DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x", - data[0], data[1]); - - ret = i2c_attach_client(new_client); -done: - if (ret) { - kfree(d); - } - return ret; -} - -static int rtc8564_probe(struct i2c_adapter *adap) -{ - return i2c_probe(adap, &addr_data, rtc8564_attach); -} - -static int rtc8564_detach(struct i2c_client *client) -{ - i2c_detach_client(client); - kfree(i2c_get_clientdata(client)); - return 0; -} - -static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt) -{ - int ret = -EIO; - unsigned char buf[15]; - - _DBG(1, "client=%p, dt=%p", client, dt); - - if (!dt) - return -EINVAL; - - memset(buf, 0, sizeof(buf)); - - ret = rtc8564_read(client, 0, buf, 15); - if (ret) - return ret; - - /* century stored in minute alarm reg */ - dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]); - dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f); - dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f); - dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7); - dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f); - - dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f); - dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80; - dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f); - dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f); - - _DBGRTCTM(2, *dt); - - return 0; -} - -static int -rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo) -{ - int ret, len = 5; - unsigned char buf[15]; - - _DBG(1, "client=%p, dt=%p", client, dt); - - if (!dt) - return -EINVAL; - - _DBGRTCTM(2, *dt); - - buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP; - buf[RTC8564_REG_CTRL2] = CTRL2(client); - buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs); - buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins); - buf[RTC8564_REG_HR] = BIN2BCD(dt->hours); - - if (datetoo) { - len += 5; - buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday); - buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday); - buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f; - /* century stored in minute alarm reg */ - buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100); - buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100); - } - - ret = rtc8564_write(client, 0, buf, len); - if (ret) { - _DBG(1, "error writing data! %d", ret); - } - - buf[RTC8564_REG_CTRL1] = CTRL1(client); - ret = rtc8564_write(client, 0, buf, 1); - if (ret) { - _DBG(1, "error writing data! %d", ret); - } - - return ret; -} - -static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl) -{ - struct rtc8564_data *data = i2c_get_clientdata(client); - - if (!ctrl) - return -1; - - *ctrl = data->ctrl; - return 0; -} - -static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl) -{ - struct rtc8564_data *data = i2c_get_clientdata(client); - unsigned char buf[2]; - - if (!ctrl) - return -1; - - buf[0] = *ctrl & 0xff; - buf[1] = (*ctrl & 0xff00) >> 8; - data->ctrl = *ctrl; - - return rtc8564_write(client, 0, buf, 2); -} - -static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem) -{ - - if (!mem) - return -EINVAL; - - return rtc8564_read(client, mem->loc, mem->data, mem->nr); -} - -static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem) -{ - - if (!mem) - return -EINVAL; - - return rtc8564_write(client, mem->loc, mem->data, mem->nr); -} - -static int -rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - - _DBG(1, "cmd=%d", cmd); - - switch (cmd) { - case RTC_GETDATETIME: - return rtc8564_get_datetime(client, arg); - - case RTC_SETTIME: - return rtc8564_set_datetime(client, arg, 0); - - case RTC_SETDATETIME: - return rtc8564_set_datetime(client, arg, 1); - - case RTC_GETCTRL: - return rtc8564_get_ctrl(client, arg); - - case RTC_SETCTRL: - return rtc8564_set_ctrl(client, arg); - - case MEM_READ: - return rtc8564_read_mem(client, arg); - - case MEM_WRITE: - return rtc8564_write_mem(client, arg); - - default: - return -EINVAL; - } -} - -static struct i2c_driver rtc8564_driver = { - .driver = { - .name = "RTC8564", - }, - .id = I2C_DRIVERID_RTC8564, - .attach_adapter = rtc8564_probe, - .detach_client = rtc8564_detach, - .command = rtc8564_command -}; - -static __init int rtc8564_init(void) -{ - return i2c_add_driver(&rtc8564_driver); -} - -static __exit void rtc8564_exit(void) -{ - i2c_del_driver(&rtc8564_driver); -} - -MODULE_AUTHOR("Stefan Eletzhofer "); -MODULE_DESCRIPTION("EPSON RTC8564 Driver"); -MODULE_LICENSE("GPL"); - -module_init(rtc8564_init); -module_exit(rtc8564_exit); diff --git a/drivers/i2c/chips/rtc8564.h b/drivers/i2c/chips/rtc8564.h deleted file mode 100644 index e5342d10b8fa..000000000000 --- a/drivers/i2c/chips/rtc8564.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * linux/drivers/i2c/chips/rtc8564.h - * - * Copyright (C) 2002-2004 Stefan Eletzhofer - * - * based on linux/drivers/acron/char/pcf8583.h - * Copyright (C) 2000 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. - */ -struct rtc_tm { - unsigned char secs; - unsigned char mins; - unsigned char hours; - unsigned char mday; - unsigned char mon; - unsigned short year; /* xxxx 4 digits :) */ - unsigned char wday; - unsigned char vl; -}; - -struct mem { - unsigned int loc; - unsigned int nr; - unsigned char *data; -}; - -#define RTC_GETDATETIME 0 -#define RTC_SETTIME 1 -#define RTC_SETDATETIME 2 -#define RTC_GETCTRL 3 -#define RTC_SETCTRL 4 -#define MEM_READ 5 -#define MEM_WRITE 6 - -#define RTC8564_REG_CTRL1 0x0 /* T 0 S 0 | T 0 0 0 */ -#define RTC8564_REG_CTRL2 0x1 /* 0 0 0 TI/TP | AF TF AIE TIE */ -#define RTC8564_REG_SEC 0x2 /* VL 4 2 1 | 8 4 2 1 */ -#define RTC8564_REG_MIN 0x3 /* x 4 2 1 | 8 4 2 1 */ -#define RTC8564_REG_HR 0x4 /* x x 2 1 | 8 4 2 1 */ -#define RTC8564_REG_DAY 0x5 /* x x 2 1 | 8 4 2 1 */ -#define RTC8564_REG_WDAY 0x6 /* x x x x | x 4 2 1 */ -#define RTC8564_REG_MON_CENT 0x7 /* C x x 1 | 8 4 2 1 */ -#define RTC8564_REG_YEAR 0x8 /* 8 4 2 1 | 8 4 2 1 */ -#define RTC8564_REG_AL_MIN 0x9 /* AE 4 2 1 | 8 4 2 1 */ -#define RTC8564_REG_AL_HR 0xa /* AE 4 2 1 | 8 4 2 1 */ -#define RTC8564_REG_AL_DAY 0xb /* AE x 2 1 | 8 4 2 1 */ -#define RTC8564_REG_AL_WDAY 0xc /* AE x x x | x 4 2 1 */ -#define RTC8564_REG_CLKOUT 0xd /* FE x x x | x x FD1 FD0 */ -#define RTC8564_REG_TCTL 0xe /* TE x x x | x x FD1 FD0 */ -#define RTC8564_REG_TIMER 0xf /* 8 bit binary */ - -/* Control reg */ -#define RTC8564_CTRL1_TEST1 (1<<3) -#define RTC8564_CTRL1_STOP (1<<5) -#define RTC8564_CTRL1_TEST2 (1<<7) - -#define RTC8564_CTRL2_TIE (1<<0) -#define RTC8564_CTRL2_AIE (1<<1) -#define RTC8564_CTRL2_TF (1<<2) -#define RTC8564_CTRL2_AF (1<<3) -#define RTC8564_CTRL2_TI_TP (1<<4) - -/* CLKOUT frequencies */ -#define RTC8564_FD_32768HZ (0x0) -#define RTC8564_FD_1024HZ (0x1) -#define RTC8564_FD_32 (0x2) -#define RTC8564_FD_1HZ (0x3) - -/* Timer CTRL */ -#define RTC8564_TD_4096HZ (0x0) -#define RTC8564_TD_64HZ (0x1) -#define RTC8564_TD_1HZ (0x2) -#define RTC8564_TD_1_60HZ (0x3) - -#define I2C_DRIVERID_RTC8564 0xf000 diff --git a/drivers/i2c/chips/x1205.c b/drivers/i2c/chips/x1205.c deleted file mode 100644 index 245fffa92dbd..000000000000 --- a/drivers/i2c/chips/x1205.c +++ /dev/null @@ -1,698 +0,0 @@ -/* - * x1205.c - An i2c driver for the Xicor X1205 RTC - * Copyright 2004 Karen Spearel - * Copyright 2005 Alessandro Zummo - * - * please send all reports to: - * kas11 at tampabay dot rr dot com - * a dot zummo at towertech dot it - * - * based on the other drivers in this same directory. - * - * 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 - -#define DRV_VERSION "0.9.9" - -/* Addresses to scan: none. This chip is located at - * 0x6f and uses a two bytes register addressing. - * Two bytes need to be written to read a single register, - * while most other chips just require one and take the second - * one as the data to be written. To prevent corrupting - * unknown chips, the user must explicitely set the probe parameter. - */ - -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; - -/* Insmod parameters */ -I2C_CLIENT_INSMOD; -I2C_CLIENT_MODULE_PARM(hctosys, - "Set the system time from the hardware clock upon initialization"); - -/* offsets into CCR area */ - -#define CCR_SEC 0 -#define CCR_MIN 1 -#define CCR_HOUR 2 -#define CCR_MDAY 3 -#define CCR_MONTH 4 -#define CCR_YEAR 5 -#define CCR_WDAY 6 -#define CCR_Y2K 7 - -#define X1205_REG_SR 0x3F /* status register */ -#define X1205_REG_Y2K 0x37 -#define X1205_REG_DW 0x36 -#define X1205_REG_YR 0x35 -#define X1205_REG_MO 0x34 -#define X1205_REG_DT 0x33 -#define X1205_REG_HR 0x32 -#define X1205_REG_MN 0x31 -#define X1205_REG_SC 0x30 -#define X1205_REG_DTR 0x13 -#define X1205_REG_ATR 0x12 -#define X1205_REG_INT 0x11 -#define X1205_REG_0 0x10 -#define X1205_REG_Y2K1 0x0F -#define X1205_REG_DWA1 0x0E -#define X1205_REG_YRA1 0x0D -#define X1205_REG_MOA1 0x0C -#define X1205_REG_DTA1 0x0B -#define X1205_REG_HRA1 0x0A -#define X1205_REG_MNA1 0x09 -#define X1205_REG_SCA1 0x08 -#define X1205_REG_Y2K0 0x07 -#define X1205_REG_DWA0 0x06 -#define X1205_REG_YRA0 0x05 -#define X1205_REG_MOA0 0x04 -#define X1205_REG_DTA0 0x03 -#define X1205_REG_HRA0 0x02 -#define X1205_REG_MNA0 0x01 -#define X1205_REG_SCA0 0x00 - -#define X1205_CCR_BASE 0x30 /* Base address of CCR */ -#define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */ - -#define X1205_SR_RTCF 0x01 /* Clock failure */ -#define X1205_SR_WEL 0x02 /* Write Enable Latch */ -#define X1205_SR_RWEL 0x04 /* Register Write Enable */ - -#define X1205_DTR_DTR0 0x01 -#define X1205_DTR_DTR1 0x02 -#define X1205_DTR_DTR2 0x04 - -#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */ - -/* Prototypes */ -static int x1205_attach(struct i2c_adapter *adapter); -static int x1205_detach(struct i2c_client *client); -static int x1205_probe(struct i2c_adapter *adapter, int address, int kind); -static int x1205_command(struct i2c_client *client, unsigned int cmd, - void *arg); - -static struct i2c_driver x1205_driver = { - .driver = { - .name = "x1205", - }, - .attach_adapter = &x1205_attach, - .detach_client = &x1205_detach, -}; - -struct x1205_data { - struct i2c_client client; - struct list_head list; - unsigned int epoch; -}; - -static const unsigned char days_in_mo[] = - { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -static LIST_HEAD(x1205_clients); - -/* Workaround until the I2C subsytem will allow to send - * commands to a specific client. This function will send the command - * to the first client. - */ -int x1205_do_command(unsigned int cmd, void *arg) -{ - struct list_head *walk; - struct list_head *tmp; - struct x1205_data *data; - - list_for_each_safe(walk, tmp, &x1205_clients) { - data = list_entry(walk, struct x1205_data, list); - return x1205_command(&data->client, cmd, arg); - } - - return -ENODEV; -} - -#define is_leap(year) \ - ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) - -/* make sure the rtc_time values are in bounds */ -static int x1205_validate_tm(struct rtc_time *tm) -{ - int year = tm->tm_year + 1900; - - if ((tm->tm_year < 70) || (tm->tm_year > 255)) - return -EINVAL; - - if ((tm->tm_mon > 11) || (tm->tm_mday == 0)) - return -EINVAL; - - if (tm->tm_mday > days_in_mo[tm->tm_mon] - + ((tm->tm_mon == 1) && is_leap(year))) - return -EINVAL; - - if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60)) - return -EINVAL; - - return 0; -} - -/* - * In the routines that deal directly with the x1205 hardware, we use - * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch - * Epoch is initialized as 2000. Time is set to UTC. - */ -static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, - u8 reg_base) -{ - unsigned char dt_addr[2] = { 0, reg_base }; - static unsigned char sr_addr[2] = { 0, X1205_REG_SR }; - - unsigned char buf[8], sr; - - struct i2c_msg msgs[] = { - { client->addr, 0, 2, sr_addr }, /* setup read ptr */ - { client->addr, I2C_M_RD, 1, &sr }, /* read status */ - { client->addr, 0, 2, dt_addr }, /* setup read ptr */ - { client->addr, I2C_M_RD, 8, buf }, /* read date */ - }; - - struct x1205_data *data = i2c_get_clientdata(client); - - /* read status register */ - if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { - dev_err(&client->dev, "%s: read error\n", __FUNCTION__); - return -EIO; - } - - /* check for battery failure */ - if (sr & X1205_SR_RTCF) { - dev_warn(&client->dev, - "Clock had a power failure, you must set the date.\n"); - return -EINVAL; - } - - /* read date registers */ - if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) { - dev_err(&client->dev, "%s: read error\n", __FUNCTION__); - return -EIO; - } - - dev_dbg(&client->dev, - "%s: raw read data - sec=%02x, min=%02x, hr=%02x, " - "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n", - __FUNCTION__, - buf[0], buf[1], buf[2], buf[3], - buf[4], buf[5], buf[6], buf[7]); - - tm->tm_sec = BCD2BIN(buf[CCR_SEC]); - tm->tm_min = BCD2BIN(buf[CCR_MIN]); - tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */ - tm->tm_mday = BCD2BIN(buf[CCR_MDAY]); - tm->tm_mon = BCD2BIN(buf[CCR_MONTH]); - data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100; - tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900; - tm->tm_wday = buf[CCR_WDAY]; - - dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " - "mday=%d, mon=%d, year=%d, wday=%d\n", - __FUNCTION__, - tm->tm_sec, tm->tm_min, tm->tm_hour, - tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - - return 0; -} - -static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, - int datetoo, u8 reg_base) -{ - int i, err, xfer; - - unsigned char buf[8]; - - static const unsigned char wel[3] = { 0, X1205_REG_SR, - X1205_SR_WEL }; - - static const unsigned char rwel[3] = { 0, X1205_REG_SR, - X1205_SR_WEL | X1205_SR_RWEL }; - - static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; - - struct x1205_data *data = i2c_get_clientdata(client); - - /* check if all values in the tm struct are correct */ - if ((err = x1205_validate_tm(tm)) < 0) - return err; - - dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " - "mday=%d, mon=%d, year=%d, wday=%d\n", - __FUNCTION__, - tm->tm_sec, tm->tm_min, tm->tm_hour, - tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - - buf[CCR_SEC] = BIN2BCD(tm->tm_sec); - buf[CCR_MIN] = BIN2BCD(tm->tm_min); - - /* set hour and 24hr bit */ - buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL; - - /* should we also set the date? */ - if (datetoo) { - buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); - - /* month, 0 - 11 */ - buf[CCR_MONTH] = BIN2BCD(tm->tm_mon); - - /* year, since 1900 */ - buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch); - buf[CCR_WDAY] = tm->tm_wday & 0x07; - buf[CCR_Y2K] = BIN2BCD(data->epoch / 100); - } - - /* this sequence is required to unlock the chip */ - xfer = i2c_master_send(client, wel, 3); - if (xfer != 3) { - dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer); - return -EIO; - } - - xfer = i2c_master_send(client, rwel, 3); - if (xfer != 3) { - dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer); - return -EIO; - } - - /* write register's data */ - for (i = 0; i < (datetoo ? 8 : 3); i++) { - unsigned char rdata[3] = { 0, reg_base + i, buf[i] }; - - xfer = i2c_master_send(client, rdata, 3); - if (xfer != 3) { - dev_err(&client->dev, - "%s: xfer=%d addr=%02x, data=%02x\n", - __FUNCTION__, - xfer, rdata[1], rdata[2]); - return -EIO; - } - }; - - /* disable further writes */ - xfer = i2c_master_send(client, diswe, 3); - if (xfer != 3) { - dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer); - return -EIO; - } - - return 0; -} - -static int x1205_get_dtrim(struct i2c_client *client, int *trim) -{ - unsigned char dtr; - static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR }; - - struct i2c_msg msgs[] = { - { client->addr, 0, 2, dtr_addr }, /* setup read ptr */ - { client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */ - }; - - /* read dtr register */ - if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { - dev_err(&client->dev, "%s: read error\n", __FUNCTION__); - return -EIO; - } - - dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr); - - *trim = 0; - - if (dtr & X1205_DTR_DTR0) - *trim += 20; - - if (dtr & X1205_DTR_DTR1) - *trim += 10; - - if (dtr & X1205_DTR_DTR2) - *trim = -*trim; - - return 0; -} - -static int x1205_get_atrim(struct i2c_client *client, int *trim) -{ - s8 atr; - static unsigned char atr_addr[2] = { 0, X1205_REG_ATR }; - - struct i2c_msg msgs[] = { - { client->addr, 0, 2, atr_addr }, /* setup read ptr */ - { client->addr, I2C_M_RD, 1, &atr }, /* read atr */ - }; - - /* read atr register */ - if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { - dev_err(&client->dev, "%s: read error\n", __FUNCTION__); - return -EIO; - } - - dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr); - - /* atr is a two's complement value on 6 bits, - * perform sign extension. The formula is - * Catr = (atr * 0.25pF) + 11.00pF. - */ - if (atr & 0x20) - atr |= 0xC0; - - dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr); - - *trim = (atr * 250) + 11000; - - dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim); - - return 0; -} - -static int x1205_hctosys(struct i2c_client *client) -{ - int err; - - struct rtc_time tm; - struct timespec tv; - - err = x1205_command(client, X1205_CMD_GETDATETIME, &tm); - - if (err) { - dev_err(&client->dev, - "Unable to set the system clock\n"); - return err; - } - - /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary - * whether it stores the most close value or the value with partial - * seconds truncated. However, it is important that we use it to store - * the truncated value. This is because otherwise it is necessary, - * in an rtc sync function, to read both xtime.tv_sec and - * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read - * of >32bits is not possible. So storing the most close value would - * slow down the sync API. So here we have the truncated value and - * the best guess is to add 0.5s. - */ - - tv.tv_nsec = NSEC_PER_SEC >> 1; - - /* WARNING: this is not the C library 'mktime' call, it is a built in - * inline function from include/linux/time.h. It expects (requires) - * the month to be in the range 1-12 - */ - - tv.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1, - tm.tm_mday, tm.tm_hour, - tm.tm_min, tm.tm_sec); - - do_settimeofday(&tv); - - dev_info(&client->dev, - "setting the system clock to %d-%d-%d %d:%d:%d\n", - tm.tm_year + 1900, tm.tm_mon + 1, - tm.tm_mday, tm.tm_hour, tm.tm_min, - tm.tm_sec); - - return 0; -} - -struct x1205_limit -{ - unsigned char reg; - unsigned char mask; - unsigned char min; - unsigned char max; -}; - -static int x1205_validate_client(struct i2c_client *client) -{ - int i, xfer; - - /* Probe array. We will read the register at the specified - * address and check if the given bits are zero. - */ - static const unsigned char probe_zero_pattern[] = { - /* register, mask */ - X1205_REG_SR, 0x18, - X1205_REG_DTR, 0xF8, - X1205_REG_ATR, 0xC0, - X1205_REG_INT, 0x18, - X1205_REG_0, 0xFF, - }; - - static const struct x1205_limit probe_limits_pattern[] = { - /* register, mask, min, max */ - { X1205_REG_Y2K, 0xFF, 19, 20 }, - { X1205_REG_DW, 0xFF, 0, 6 }, - { X1205_REG_YR, 0xFF, 0, 99 }, - { X1205_REG_MO, 0xFF, 0, 12 }, - { X1205_REG_DT, 0xFF, 0, 31 }, - { X1205_REG_HR, 0x7F, 0, 23 }, - { X1205_REG_MN, 0xFF, 0, 59 }, - { X1205_REG_SC, 0xFF, 0, 59 }, - { X1205_REG_Y2K1, 0xFF, 19, 20 }, - { X1205_REG_Y2K0, 0xFF, 19, 20 }, - }; - - /* check that registers have bits a 0 where expected */ - for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) { - unsigned char buf; - - unsigned char addr[2] = { 0, probe_zero_pattern[i] }; - - struct i2c_msg msgs[2] = { - { client->addr, 0, 2, addr }, - { client->addr, I2C_M_RD, 1, &buf }, - }; - - xfer = i2c_transfer(client->adapter, msgs, 2); - if (xfer != 2) { - dev_err(&client->adapter->dev, - "%s: could not read register %x\n", - __FUNCTION__, addr[1]); - - return -EIO; - } - - if ((buf & probe_zero_pattern[i+1]) != 0) { - dev_err(&client->adapter->dev, - "%s: register=%02x, zero pattern=%d, value=%x\n", - __FUNCTION__, addr[1], i, buf); - - return -ENODEV; - } - } - - /* check limits (only registers with bcd values) */ - for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) { - unsigned char reg, value; - - unsigned char addr[2] = { 0, probe_limits_pattern[i].reg }; - - struct i2c_msg msgs[2] = { - { client->addr, 0, 2, addr }, - { client->addr, I2C_M_RD, 1, ® }, - }; - - xfer = i2c_transfer(client->adapter, msgs, 2); - - if (xfer != 2) { - dev_err(&client->adapter->dev, - "%s: could not read register %x\n", - __FUNCTION__, addr[1]); - - return -EIO; - } - - value = BCD2BIN(reg & probe_limits_pattern[i].mask); - - if (value > probe_limits_pattern[i].max || - value < probe_limits_pattern[i].min) { - dev_dbg(&client->adapter->dev, - "%s: register=%x, lim pattern=%d, value=%d\n", - __FUNCTION__, addr[1], i, value); - - return -ENODEV; - } - } - - return 0; -} - -static int x1205_attach(struct i2c_adapter *adapter) -{ - dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); - - return i2c_probe(adapter, &addr_data, x1205_probe); -} - -int x1205_direct_attach(int adapter_id, - struct i2c_client_address_data *address_data) -{ - int err; - struct i2c_adapter *adapter = i2c_get_adapter(adapter_id); - - if (adapter) { - err = i2c_probe(adapter, - address_data, x1205_probe); - - i2c_put_adapter(adapter); - - return err; - } - - return -ENODEV; -} - -static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *client; - struct x1205_data *data; - - int err = 0; - - dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); - - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { - err = -ENODEV; - goto exit; - } - - if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - /* Initialize our structures */ - data->epoch = 2000; - - client = &data->client; - client->addr = address; - client->driver = &x1205_driver; - client->adapter = adapter; - - strlcpy(client->name, "x1205", I2C_NAME_SIZE); - - i2c_set_clientdata(client, data); - - /* Verify the chip is really an X1205 */ - if (kind < 0) { - if (x1205_validate_client(client) < 0) { - err = -ENODEV; - goto exit_kfree; - } - } - - /* Inform the i2c layer */ - if ((err = i2c_attach_client(client))) - goto exit_kfree; - - list_add(&data->list, &x1205_clients); - - dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - - /* If requested, set the system time */ - if (hctosys) - x1205_hctosys(client); - - return 0; - -exit_kfree: - kfree(data); - -exit: - return err; -} - -static int x1205_detach(struct i2c_client *client) -{ - int err; - struct x1205_data *data = i2c_get_clientdata(client); - - dev_dbg(&client->dev, "%s\n", __FUNCTION__); - - if ((err = i2c_detach_client(client))) - return err; - - list_del(&data->list); - - kfree(data); - - return 0; -} - -static int x1205_command(struct i2c_client *client, unsigned int cmd, - void *param) -{ - if (param == NULL) - return -EINVAL; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd); - - switch (cmd) { - case X1205_CMD_GETDATETIME: - return x1205_get_datetime(client, param, X1205_CCR_BASE); - - case X1205_CMD_SETTIME: - return x1205_set_datetime(client, param, 0, - X1205_CCR_BASE); - - case X1205_CMD_SETDATETIME: - return x1205_set_datetime(client, param, 1, - X1205_CCR_BASE); - - case X1205_CMD_GETALARM: - return x1205_get_datetime(client, param, X1205_ALM0_BASE); - - case X1205_CMD_SETALARM: - return x1205_set_datetime(client, param, 1, - X1205_ALM0_BASE); - - case X1205_CMD_GETDTRIM: - return x1205_get_dtrim(client, param); - - case X1205_CMD_GETATRIM: - return x1205_get_atrim(client, param); - - default: - return -EINVAL; - } -} - -static int __init x1205_init(void) -{ - return i2c_add_driver(&x1205_driver); -} - -static void __exit x1205_exit(void) -{ - i2c_del_driver(&x1205_driver); -} - -MODULE_AUTHOR( - "Karen Spearel , " - "Alessandro Zummo "); -MODULE_DESCRIPTION("Xicor X1205 RTC driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -EXPORT_SYMBOL_GPL(x1205_do_command); -EXPORT_SYMBOL_GPL(x1205_direct_attach); - -module_init(x1205_init); -module_exit(x1205_exit); diff --git a/include/linux/x1205.h b/include/linux/x1205.h deleted file mode 100644 index 64fd3af894a5..000000000000 --- a/include/linux/x1205.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * x1205.h - defines for drivers/i2c/chips/x1205.c - * Copyright 2004 Karen Spearel - * Copyright 2005 Alessandro Zummo - * - * 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 __LINUX_X1205_H__ -#define __LINUX_X1205_H__ - -/* commands */ - -#define X1205_CMD_GETDATETIME 0 -#define X1205_CMD_SETTIME 1 -#define X1205_CMD_SETDATETIME 2 -#define X1205_CMD_GETALARM 3 -#define X1205_CMD_SETALARM 4 -#define X1205_CMD_GETDTRIM 5 -#define X1205_CMD_SETDTRIM 6 -#define X1205_CMD_GETATRIM 7 -#define X1205_CMD_SETATRIM 8 - -extern int x1205_do_command(unsigned int cmd, void *arg); -extern int x1205_direct_attach(int adapter_id, - struct i2c_client_address_data *address_data); - -#endif /* __LINUX_X1205_H__ */ -- cgit v1.2.3-59-g8ed1b From c5c3e19225217536d90515c494e55e642a21e4fa Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:39 -0800 Subject: [PATCH] RTC subsystem: sysfs interface This patch adds the sysfs interface to the RTC subsystem. Each RTC client will have his own entry under /sys/classs/rtc/rtcN . Within this entry some attributes are exported by the subsystem, like date and time. Signed-off-by: Alessandro Zummo Acked-by: Greg Kroah-Hartman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 11 +++++ drivers/rtc/Makefile | 3 ++ drivers/rtc/rtc-sysfs.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 drivers/rtc/rtc-sysfs.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index a256f67b78e4..824499920485 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -40,6 +40,17 @@ config RTC_HCTOSYS_DEVICE comment "RTC interfaces" depends on RTC_CLASS +config RTC_INTF_SYSFS + tristate "sysfs" + depends on RTC_CLASS && SYSFS + default RTC_CLASS + help + Say yes here if you want to use your RTC using the sysfs + interface, /sys/class/rtc/rtcX . + + This driver can also be built as a module. If so, the module + will be called rtc-sysfs. + comment "RTC drivers" depends on RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 7b87f3710dff..c44363355c2b 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -6,3 +6,6 @@ obj-$(CONFIG_RTC_LIB) += rtc-lib.o obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o obj-$(CONFIG_RTC_CLASS) += rtc-core.o rtc-core-y := class.o interface.o + +obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o + diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c new file mode 100644 index 000000000000..7c1f3d2e53c4 --- /dev/null +++ b/drivers/rtc/rtc-sysfs.c @@ -0,0 +1,124 @@ +/* + * RTC subsystem, sysfs interface + * + * Copyright (C) 2005 Tower Technologies + * Author: Alessandro Zummo + * + * 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 + +/* device attributes */ + +static ssize_t rtc_sysfs_show_name(struct class_device *dev, char *buf) +{ + return sprintf(buf, "%s\n", to_rtc_device(dev)->name); +} +static CLASS_DEVICE_ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL); + +static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf) +{ + ssize_t retval; + struct rtc_time tm; + + retval = rtc_read_time(dev, &tm); + if (retval == 0) { + retval = sprintf(buf, "%04d-%02d-%02d\n", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + } + + return retval; +} +static CLASS_DEVICE_ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL); + +static ssize_t rtc_sysfs_show_time(struct class_device *dev, char *buf) +{ + ssize_t retval; + struct rtc_time tm; + + retval = rtc_read_time(dev, &tm); + if (retval == 0) { + retval = sprintf(buf, "%02d:%02d:%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec); + } + + return retval; +} +static CLASS_DEVICE_ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL); + +static ssize_t rtc_sysfs_show_since_epoch(struct class_device *dev, char *buf) +{ + ssize_t retval; + struct rtc_time tm; + + retval = rtc_read_time(dev, &tm); + if (retval == 0) { + unsigned long time; + rtc_tm_to_time(&tm, &time); + retval = sprintf(buf, "%lu\n", time); + } + + return retval; +} +static CLASS_DEVICE_ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL); + +static struct attribute *rtc_attrs[] = { + &class_device_attr_name.attr, + &class_device_attr_date.attr, + &class_device_attr_time.attr, + &class_device_attr_since_epoch.attr, + NULL, +}; + +static struct attribute_group rtc_attr_group = { + .attrs = rtc_attrs, +}; + +static int __devinit rtc_sysfs_add_device(struct class_device *class_dev, + struct class_interface *class_intf) +{ + int err; + + dev_info(class_dev->dev, "rtc intf: sysfs\n"); + + err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group); + if (err) + dev_err(class_dev->dev, + "failed to create sysfs attributes\n"); + + return err; +} + +static void rtc_sysfs_remove_device(struct class_device *class_dev, + struct class_interface *class_intf) +{ + sysfs_remove_group(&class_dev->kobj, &rtc_attr_group); +} + +/* interface registration */ + +static struct class_interface rtc_sysfs_interface = { + .add = &rtc_sysfs_add_device, + .remove = &rtc_sysfs_remove_device, +}; + +static int __init rtc_sysfs_init(void) +{ + return rtc_interface_register(&rtc_sysfs_interface); +} + +static void __exit rtc_sysfs_exit(void) +{ + class_interface_unregister(&rtc_sysfs_interface); +} + +module_init(rtc_sysfs_init); +module_exit(rtc_sysfs_exit); + +MODULE_AUTHOR("Alessandro Zummo "); +MODULE_DESCRIPTION("RTC class sysfs interface"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 728a294787b780130d8eb237518d4cac0afe760c Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:40 -0800 Subject: [PATCH] RTC subsystem: proc interface Add the proc interface to the RTC subsystem. The first RTC driver which registers with the class will be accessible by /proc/driver/rtc . This is required for compatibility with the standard RTC driver and to avoid breaking any user space application which may erroneusly rely on this. Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 11 ++++ drivers/rtc/Makefile | 2 +- drivers/rtc/rtc-proc.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 drivers/rtc/rtc-proc.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 824499920485..200fb06b788a 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -51,6 +51,17 @@ config RTC_INTF_SYSFS This driver can also be built as a module. If so, the module will be called rtc-sysfs. +config RTC_INTF_PROC + tristate "proc" + depends on RTC_CLASS && PROC_FS + default RTC_CLASS + help + Say yes here if you want to use your RTC using the proc + interface, /proc/driver/rtc . + + This driver can also be built as a module. If so, the module + will be called rtc-proc. + comment "RTC drivers" depends on RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index c44363355c2b..137aef0e29ab 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -8,4 +8,4 @@ obj-$(CONFIG_RTC_CLASS) += rtc-core.o rtc-core-y := class.o interface.o obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o - +obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c new file mode 100644 index 000000000000..90b8a97a0919 --- /dev/null +++ b/drivers/rtc/rtc-proc.c @@ -0,0 +1,162 @@ +/* + * RTC subsystem, proc interface + * + * Copyright (C) 2005-06 Tower Technologies + * Author: Alessandro Zummo + * + * based on arch/arm/common/rtctime.c + * + * 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 +#include + +static struct class_device *rtc_dev = NULL; +static DEFINE_MUTEX(rtc_lock); + +static int rtc_proc_show(struct seq_file *seq, void *offset) +{ + int err; + struct class_device *class_dev = seq->private; + struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops; + struct rtc_wkalrm alrm; + struct rtc_time tm; + + err = rtc_read_time(class_dev, &tm); + if (err == 0) { + seq_printf(seq, + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + } + + err = rtc_read_alarm(class_dev, &alrm); + if (err == 0) { + seq_printf(seq, "alrm_time\t: "); + if ((unsigned int)alrm.time.tm_hour <= 24) + seq_printf(seq, "%02d:", alrm.time.tm_hour); + else + seq_printf(seq, "**:"); + if ((unsigned int)alrm.time.tm_min <= 59) + seq_printf(seq, "%02d:", alrm.time.tm_min); + else + seq_printf(seq, "**:"); + if ((unsigned int)alrm.time.tm_sec <= 59) + seq_printf(seq, "%02d\n", alrm.time.tm_sec); + else + seq_printf(seq, "**\n"); + + seq_printf(seq, "alrm_date\t: "); + if ((unsigned int)alrm.time.tm_year <= 200) + seq_printf(seq, "%04d-", alrm.time.tm_year + 1900); + else + seq_printf(seq, "****-"); + if ((unsigned int)alrm.time.tm_mon <= 11) + seq_printf(seq, "%02d-", alrm.time.tm_mon + 1); + else + seq_printf(seq, "**-"); + if ((unsigned int)alrm.time.tm_mday <= 31) + seq_printf(seq, "%02d\n", alrm.time.tm_mday); + else + seq_printf(seq, "**\n"); + seq_printf(seq, "alrm_wakeup\t: %s\n", + alrm.enabled ? "yes" : "no"); + seq_printf(seq, "alrm_pending\t: %s\n", + alrm.pending ? "yes" : "no"); + } + + if (ops->proc) + ops->proc(class_dev->dev, seq); + + return 0; +} + +static int rtc_proc_open(struct inode *inode, struct file *file) +{ + struct class_device *class_dev = PDE(inode)->data; + + if (!try_module_get(THIS_MODULE)) + return -ENODEV; + + return single_open(file, rtc_proc_show, class_dev); +} + +static int rtc_proc_release(struct inode *inode, struct file *file) +{ + int res = single_release(inode, file); + module_put(THIS_MODULE); + return res; +} + +static struct file_operations rtc_proc_fops = { + .open = rtc_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = rtc_proc_release, +}; + +static int rtc_proc_add_device(struct class_device *class_dev, + struct class_interface *class_intf) +{ + mutex_lock(&rtc_lock); + if (rtc_dev == NULL) { + struct proc_dir_entry *ent; + + rtc_dev = class_dev; + + ent = create_proc_entry("driver/rtc", 0, NULL); + if (ent) { + struct rtc_device *rtc = to_rtc_device(class_dev); + + ent->proc_fops = &rtc_proc_fops; + ent->owner = rtc->owner; + ent->data = class_dev; + + dev_info(class_dev->dev, "rtc intf: proc\n"); + } + else + rtc_dev = NULL; + } + mutex_unlock(&rtc_lock); + + return 0; +} + +static void rtc_proc_remove_device(struct class_device *class_dev, + struct class_interface *class_intf) +{ + mutex_lock(&rtc_lock); + if (rtc_dev == class_dev) { + remove_proc_entry("driver/rtc", NULL); + rtc_dev = NULL; + } + mutex_unlock(&rtc_lock); +} + +static struct class_interface rtc_proc_interface = { + .add = &rtc_proc_add_device, + .remove = &rtc_proc_remove_device, +}; + +static int __init rtc_proc_init(void) +{ + return rtc_interface_register(&rtc_proc_interface); +} + +static void __exit rtc_proc_exit(void) +{ + class_interface_unregister(&rtc_proc_interface); +} + +module_init(rtc_proc_init); +module_exit(rtc_proc_exit); + +MODULE_AUTHOR("Alessandro Zummo "); +MODULE_DESCRIPTION("RTC class proc interface"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From e824290e5dcfaf2120da587b16d10dfdff8d5d3e Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:41 -0800 Subject: [PATCH] RTC subsystem: dev interface Add the dev interface to the RTC subsystem. Each RTC will be available under /dev/rtcX . A symlink from /dev/rtc0 to /dev/rtc cab be obtained with the following udev rule: KERNEL=="rtc0", SYMLINK+="rtc" Signed-off-by: Alessandro Zummo Acked-by: Greg Kroah-Hartman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 11 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-dev.c | 382 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 394 insertions(+) create mode 100644 drivers/rtc/rtc-dev.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 200fb06b788a..8e4dc32058d6 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -62,6 +62,17 @@ config RTC_INTF_PROC This driver can also be built as a module. If so, the module will be called rtc-proc. +config RTC_INTF_DEV + tristate "dev" + depends on RTC_CLASS + default RTC_CLASS + help + Say yes here if you want to use your RTC using the dev + interface, /dev/rtc . + + This driver can also be built as a module. If so, the module + will be called rtc-dev. + comment "RTC drivers" depends on RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 137aef0e29ab..38a9212a7f3b 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -9,3 +9,4 @@ rtc-core-y := class.o interface.o obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o +obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c new file mode 100644 index 000000000000..b1e3e6179e56 --- /dev/null +++ b/drivers/rtc/rtc-dev.c @@ -0,0 +1,382 @@ +/* + * RTC subsystem, dev interface + * + * Copyright (C) 2005 Tower Technologies + * Author: Alessandro Zummo + * + * based on arch/arm/common/rtctime.c + * + * 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 + +static struct class *rtc_dev_class; +static dev_t rtc_devt; + +#define RTC_DEV_MAX 16 /* 16 RTCs should be enough for everyone... */ + +static int rtc_dev_open(struct inode *inode, struct file *file) +{ + int err; + struct rtc_device *rtc = container_of(inode->i_cdev, + struct rtc_device, char_dev); + struct rtc_class_ops *ops = rtc->ops; + + /* We keep the lock as long as the device is in use + * and return immediately if busy + */ + if (!(mutex_trylock(&rtc->char_lock))) + return -EBUSY; + + file->private_data = &rtc->class_dev; + + err = ops->open ? ops->open(rtc->class_dev.dev) : 0; + if (err == 0) { + spin_lock_irq(&rtc->irq_lock); + rtc->irq_data = 0; + spin_unlock_irq(&rtc->irq_lock); + + return 0; + } + + /* something has gone wrong, release the lock */ + mutex_unlock(&rtc->char_lock); + return err; +} + + +static ssize_t +rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + struct rtc_device *rtc = to_rtc_device(file->private_data); + + DECLARE_WAITQUEUE(wait, current); + unsigned long data; + ssize_t ret; + + if (count < sizeof(unsigned long)) + return -EINVAL; + + add_wait_queue(&rtc->irq_queue, &wait); + do { + __set_current_state(TASK_INTERRUPTIBLE); + + spin_lock_irq(&rtc->irq_lock); + data = rtc->irq_data; + rtc->irq_data = 0; + spin_unlock_irq(&rtc->irq_lock); + + if (data != 0) { + ret = 0; + break; + } + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + break; + } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + schedule(); + } while (1); + set_current_state(TASK_RUNNING); + remove_wait_queue(&rtc->irq_queue, &wait); + + if (ret == 0) { + /* Check for any data updates */ + if (rtc->ops->read_callback) + data = rtc->ops->read_callback(rtc->class_dev.dev, data); + + ret = put_user(data, (unsigned long __user *)buf); + if (ret == 0) + ret = sizeof(unsigned long); + } + return ret; +} + +static unsigned int rtc_dev_poll(struct file *file, poll_table *wait) +{ + struct rtc_device *rtc = to_rtc_device(file->private_data); + unsigned long data; + + poll_wait(file, &rtc->irq_queue, wait); + + data = rtc->irq_data; + + return (data != 0) ? (POLLIN | POLLRDNORM) : 0; +} + +static int rtc_dev_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int err = 0; + struct class_device *class_dev = file->private_data; + struct rtc_device *rtc = to_rtc_device(class_dev); + struct rtc_class_ops *ops = rtc->ops; + struct rtc_time tm; + struct rtc_wkalrm alarm; + void __user *uarg = (void __user *) arg; + + /* avoid conflicting IRQ users */ + if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) { + spin_lock(&rtc->irq_task_lock); + if (rtc->irq_task) + err = -EBUSY; + spin_unlock(&rtc->irq_task_lock); + + if (err < 0) + return err; + } + + /* try the driver's ioctl interface */ + if (ops->ioctl) { + err = ops->ioctl(class_dev->dev, cmd, arg); + if (err != -EINVAL) + return err; + } + + /* if the driver does not provide the ioctl interface + * or if that particular ioctl was not implemented + * (-EINVAL), we will try to emulate here. + */ + + switch (cmd) { + case RTC_ALM_READ: + err = rtc_read_alarm(class_dev, &alarm); + if (err < 0) + return err; + + if (copy_to_user(uarg, &alarm.time, sizeof(tm))) + return -EFAULT; + break; + + case RTC_ALM_SET: + if (copy_from_user(&alarm.time, uarg, sizeof(tm))) + return -EFAULT; + + alarm.enabled = 0; + alarm.pending = 0; + alarm.time.tm_mday = -1; + alarm.time.tm_mon = -1; + alarm.time.tm_year = -1; + alarm.time.tm_wday = -1; + alarm.time.tm_yday = -1; + alarm.time.tm_isdst = -1; + err = rtc_set_alarm(class_dev, &alarm); + break; + + case RTC_RD_TIME: + err = rtc_read_time(class_dev, &tm); + if (err < 0) + return err; + + if (copy_to_user(uarg, &tm, sizeof(tm))) + return -EFAULT; + break; + + case RTC_SET_TIME: + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&tm, uarg, sizeof(tm))) + return -EFAULT; + + err = rtc_set_time(class_dev, &tm); + break; +#if 0 + case RTC_EPOCH_SET: +#ifndef rtc_epoch + /* + * There were no RTC clocks before 1900. + */ + if (arg < 1900) { + err = -EINVAL; + break; + } + if (!capable(CAP_SYS_TIME)) { + err = -EACCES; + break; + } + rtc_epoch = arg; + err = 0; +#endif + break; + + case RTC_EPOCH_READ: + err = put_user(rtc_epoch, (unsigned long __user *)uarg); + break; +#endif + case RTC_WKALM_SET: + if (copy_from_user(&alarm, uarg, sizeof(alarm))) + return -EFAULT; + + err = rtc_set_alarm(class_dev, &alarm); + break; + + case RTC_WKALM_RD: + err = rtc_read_alarm(class_dev, &alarm); + if (err < 0) + return err; + + if (copy_to_user(uarg, &alarm, sizeof(alarm))) + return -EFAULT; + break; + + default: + err = -EINVAL; + break; + } + + return err; +} + +static int rtc_dev_release(struct inode *inode, struct file *file) +{ + struct rtc_device *rtc = to_rtc_device(file->private_data); + + if (rtc->ops->release) + rtc->ops->release(rtc->class_dev.dev); + + mutex_unlock(&rtc->char_lock); + return 0; +} + +static int rtc_dev_fasync(int fd, struct file *file, int on) +{ + struct rtc_device *rtc = to_rtc_device(file->private_data); + return fasync_helper(fd, file, on, &rtc->async_queue); +} + +static struct file_operations rtc_dev_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = rtc_dev_read, + .poll = rtc_dev_poll, + .ioctl = rtc_dev_ioctl, + .open = rtc_dev_open, + .release = rtc_dev_release, + .fasync = rtc_dev_fasync, +}; + +/* insertion/removal hooks */ + +static int rtc_dev_add_device(struct class_device *class_dev, + struct class_interface *class_intf) +{ + int err = 0; + struct rtc_device *rtc = to_rtc_device(class_dev); + + if (rtc->id >= RTC_DEV_MAX) { + dev_err(class_dev->dev, "too many RTCs\n"); + return -EINVAL; + } + + mutex_init(&rtc->char_lock); + spin_lock_init(&rtc->irq_lock); + init_waitqueue_head(&rtc->irq_queue); + + cdev_init(&rtc->char_dev, &rtc_dev_fops); + rtc->char_dev.owner = rtc->owner; + + if (cdev_add(&rtc->char_dev, MKDEV(MAJOR(rtc_devt), rtc->id), 1)) { + cdev_del(&rtc->char_dev); + dev_err(class_dev->dev, + "failed to add char device %d:%d\n", + MAJOR(rtc_devt), rtc->id); + return -ENODEV; + } + + rtc->rtc_dev = class_device_create(rtc_dev_class, NULL, + MKDEV(MAJOR(rtc_devt), rtc->id), + class_dev->dev, "rtc%d", rtc->id); + if (IS_ERR(rtc->rtc_dev)) { + dev_err(class_dev->dev, "cannot create rtc_dev device\n"); + err = PTR_ERR(rtc->rtc_dev); + goto err_cdev_del; + } + + dev_info(class_dev->dev, "rtc intf: dev (%d:%d)\n", + MAJOR(rtc->rtc_dev->devt), + MINOR(rtc->rtc_dev->devt)); + + return 0; + +err_cdev_del: + + cdev_del(&rtc->char_dev); + return err; +} + +static void rtc_dev_remove_device(struct class_device *class_dev, + struct class_interface *class_intf) +{ + struct rtc_device *rtc = to_rtc_device(class_dev); + + if (rtc->rtc_dev) { + dev_dbg(class_dev->dev, "removing char %d:%d\n", + MAJOR(rtc->rtc_dev->devt), + MINOR(rtc->rtc_dev->devt)); + + class_device_unregister(rtc->rtc_dev); + cdev_del(&rtc->char_dev); + } +} + +/* interface registration */ + +static struct class_interface rtc_dev_interface = { + .add = &rtc_dev_add_device, + .remove = &rtc_dev_remove_device, +}; + +static int __init rtc_dev_init(void) +{ + int err; + + rtc_dev_class = class_create(THIS_MODULE, "rtc-dev"); + if (IS_ERR(rtc_dev_class)) + return PTR_ERR(rtc_dev_class); + + err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc"); + if (err < 0) { + printk(KERN_ERR "%s: failed to allocate char dev region\n", + __FILE__); + goto err_destroy_class; + } + + err = rtc_interface_register(&rtc_dev_interface); + if (err < 0) { + printk(KERN_ERR "%s: failed to register the interface\n", + __FILE__); + goto err_unregister_chrdev; + } + + return 0; + +err_unregister_chrdev: + unregister_chrdev_region(rtc_devt, RTC_DEV_MAX); + +err_destroy_class: + class_destroy(rtc_dev_class); + + return err; +} + +static void __exit rtc_dev_exit(void) +{ + class_interface_unregister(&rtc_dev_interface); + class_destroy(rtc_dev_class); + unregister_chrdev_region(rtc_devt, RTC_DEV_MAX); +} + +module_init(rtc_dev_init); +module_exit(rtc_dev_exit); + +MODULE_AUTHOR("Alessandro Zummo "); +MODULE_DESCRIPTION("RTC class dev interface"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 1fec7c66ba98fc3a04e15fd14fad6b404e56fc94 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:42 -0800 Subject: [PATCH] RTC subsystem: X1205 driver A port of the existing x1205 driver under the new RTC subsystem. It is actually under test within the NSLU2 project (http://www.nslu2-linux.org) and it is working quite well. It is the first driver under this new subsystem and should be used as a guide to port other drivers. Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 10 + drivers/rtc/Makefile | 3 + drivers/rtc/rtc-x1205.c | 619 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 632 insertions(+) create mode 100644 drivers/rtc/rtc-x1205.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8e4dc32058d6..3de823f2f055 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -76,4 +76,14 @@ config RTC_INTF_DEV comment "RTC drivers" depends on RTC_CLASS +config RTC_DRV_X1205 + tristate "Xicor/Intersil X1205" + depends on RTC_CLASS && I2C + help + If you say yes here you get support for the + Xicor/Intersil X1205 RTC chip. + + This driver can also be built as a module. If so, the module + will be called rtc-x1205. + endmenu diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 38a9212a7f3b..eaf89b22db7a 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -10,3 +10,6 @@ rtc-core-y := class.o interface.o obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o + +obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o + diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c new file mode 100644 index 000000000000..621d17afc0d9 --- /dev/null +++ b/drivers/rtc/rtc-x1205.c @@ -0,0 +1,619 @@ +/* + * An i2c driver for the Xicor/Intersil X1205 RTC + * Copyright 2004 Karen Spearel + * Copyright 2005 Alessandro Zummo + * + * please send all reports to: + * Karen Spearel + * Alessandro Zummo + * + * based on a lot of other RTC drivers. + * + * 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 +#include + +#define DRV_VERSION "1.0.6" + +/* Addresses to scan: none. This chip is located at + * 0x6f and uses a two bytes register addressing. + * Two bytes need to be written to read a single register, + * while most other chips just require one and take the second + * one as the data to be written. To prevent corrupting + * unknown chips, the user must explicitely set the probe parameter. + */ + +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD; + +/* offsets into CCR area */ + +#define CCR_SEC 0 +#define CCR_MIN 1 +#define CCR_HOUR 2 +#define CCR_MDAY 3 +#define CCR_MONTH 4 +#define CCR_YEAR 5 +#define CCR_WDAY 6 +#define CCR_Y2K 7 + +#define X1205_REG_SR 0x3F /* status register */ +#define X1205_REG_Y2K 0x37 +#define X1205_REG_DW 0x36 +#define X1205_REG_YR 0x35 +#define X1205_REG_MO 0x34 +#define X1205_REG_DT 0x33 +#define X1205_REG_HR 0x32 +#define X1205_REG_MN 0x31 +#define X1205_REG_SC 0x30 +#define X1205_REG_DTR 0x13 +#define X1205_REG_ATR 0x12 +#define X1205_REG_INT 0x11 +#define X1205_REG_0 0x10 +#define X1205_REG_Y2K1 0x0F +#define X1205_REG_DWA1 0x0E +#define X1205_REG_YRA1 0x0D +#define X1205_REG_MOA1 0x0C +#define X1205_REG_DTA1 0x0B +#define X1205_REG_HRA1 0x0A +#define X1205_REG_MNA1 0x09 +#define X1205_REG_SCA1 0x08 +#define X1205_REG_Y2K0 0x07 +#define X1205_REG_DWA0 0x06 +#define X1205_REG_YRA0 0x05 +#define X1205_REG_MOA0 0x04 +#define X1205_REG_DTA0 0x03 +#define X1205_REG_HRA0 0x02 +#define X1205_REG_MNA0 0x01 +#define X1205_REG_SCA0 0x00 + +#define X1205_CCR_BASE 0x30 /* Base address of CCR */ +#define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */ + +#define X1205_SR_RTCF 0x01 /* Clock failure */ +#define X1205_SR_WEL 0x02 /* Write Enable Latch */ +#define X1205_SR_RWEL 0x04 /* Register Write Enable */ + +#define X1205_DTR_DTR0 0x01 +#define X1205_DTR_DTR1 0x02 +#define X1205_DTR_DTR2 0x04 + +#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */ + +/* Prototypes */ +static int x1205_attach(struct i2c_adapter *adapter); +static int x1205_detach(struct i2c_client *client); +static int x1205_probe(struct i2c_adapter *adapter, int address, int kind); + +static struct i2c_driver x1205_driver = { + .driver = { + .name = "x1205", + }, + .id = I2C_DRIVERID_X1205, + .attach_adapter = &x1205_attach, + .detach_client = &x1205_detach, +}; + +/* + * In the routines that deal directly with the x1205 hardware, we use + * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch + * Epoch is initialized as 2000. Time is set to UTC. + */ +static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, + unsigned char reg_base) +{ + unsigned char dt_addr[2] = { 0, reg_base }; + + unsigned char buf[8]; + + struct i2c_msg msgs[] = { + { client->addr, 0, 2, dt_addr }, /* setup read ptr */ + { client->addr, I2C_M_RD, 8, buf }, /* read date */ + }; + + /* read date registers */ + if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + dev_err(&client->dev, "%s: read error\n", __FUNCTION__); + return -EIO; + } + + dev_dbg(&client->dev, + "%s: raw read data - sec=%02x, min=%02x, hr=%02x, " + "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n", + __FUNCTION__, + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7]); + + tm->tm_sec = BCD2BIN(buf[CCR_SEC]); + tm->tm_min = BCD2BIN(buf[CCR_MIN]); + tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */ + tm->tm_mday = BCD2BIN(buf[CCR_MDAY]); + tm->tm_mon = BCD2BIN(buf[CCR_MONTH]) - 1; /* mon is 0-11 */ + tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + + (BCD2BIN(buf[CCR_Y2K]) * 100) - 1900; + tm->tm_wday = buf[CCR_WDAY]; + + dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " + "mday=%d, mon=%d, year=%d, wday=%d\n", + __FUNCTION__, + tm->tm_sec, tm->tm_min, tm->tm_hour, + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + + return 0; +} + +static int x1205_get_status(struct i2c_client *client, unsigned char *sr) +{ + static unsigned char sr_addr[2] = { 0, X1205_REG_SR }; + + struct i2c_msg msgs[] = { + { client->addr, 0, 2, sr_addr }, /* setup read ptr */ + { client->addr, I2C_M_RD, 1, sr }, /* read status */ + }; + + /* read status register */ + if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + dev_err(&client->dev, "%s: read error\n", __FUNCTION__); + return -EIO; + } + + return 0; +} + +static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, + int datetoo, u8 reg_base) +{ + int i, xfer; + unsigned char buf[8]; + + static const unsigned char wel[3] = { 0, X1205_REG_SR, + X1205_SR_WEL }; + + static const unsigned char rwel[3] = { 0, X1205_REG_SR, + X1205_SR_WEL | X1205_SR_RWEL }; + + static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; + + dev_dbg(&client->dev, + "%s: secs=%d, mins=%d, hours=%d\n", + __FUNCTION__, + tm->tm_sec, tm->tm_min, tm->tm_hour); + + buf[CCR_SEC] = BIN2BCD(tm->tm_sec); + buf[CCR_MIN] = BIN2BCD(tm->tm_min); + + /* set hour and 24hr bit */ + buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL; + + /* should we also set the date? */ + if (datetoo) { + dev_dbg(&client->dev, + "%s: mday=%d, mon=%d, year=%d, wday=%d\n", + __FUNCTION__, + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + + buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); + + /* month, 1 - 12 */ + buf[CCR_MONTH] = BIN2BCD(tm->tm_mon + 1); + + /* year, since the rtc epoch*/ + buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100); + buf[CCR_WDAY] = tm->tm_wday & 0x07; + buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100); + } + + /* this sequence is required to unlock the chip */ + if ((xfer = i2c_master_send(client, wel, 3)) != 3) { + dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer); + return -EIO; + } + + if ((xfer = i2c_master_send(client, rwel, 3)) != 3) { + dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer); + return -EIO; + } + + /* write register's data */ + for (i = 0; i < (datetoo ? 8 : 3); i++) { + unsigned char rdata[3] = { 0, reg_base + i, buf[i] }; + + xfer = i2c_master_send(client, rdata, 3); + if (xfer != 3) { + dev_err(&client->dev, + "%s: xfer=%d addr=%02x, data=%02x\n", + __FUNCTION__, + xfer, rdata[1], rdata[2]); + return -EIO; + } + }; + + /* disable further writes */ + if ((xfer = i2c_master_send(client, diswe, 3)) != 3) { + dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer); + return -EIO; + } + + return 0; +} + +static int x1205_fix_osc(struct i2c_client *client) +{ + int err; + struct rtc_time tm; + + tm.tm_hour = tm.tm_min = tm.tm_sec = 0; + + if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0) + dev_err(&client->dev, + "unable to restart the oscillator\n"); + + return err; +} + +static int x1205_get_dtrim(struct i2c_client *client, int *trim) +{ + unsigned char dtr; + static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR }; + + struct i2c_msg msgs[] = { + { client->addr, 0, 2, dtr_addr }, /* setup read ptr */ + { client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */ + }; + + /* read dtr register */ + if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + dev_err(&client->dev, "%s: read error\n", __FUNCTION__); + return -EIO; + } + + dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr); + + *trim = 0; + + if (dtr & X1205_DTR_DTR0) + *trim += 20; + + if (dtr & X1205_DTR_DTR1) + *trim += 10; + + if (dtr & X1205_DTR_DTR2) + *trim = -*trim; + + return 0; +} + +static int x1205_get_atrim(struct i2c_client *client, int *trim) +{ + s8 atr; + static unsigned char atr_addr[2] = { 0, X1205_REG_ATR }; + + struct i2c_msg msgs[] = { + { client->addr, 0, 2, atr_addr }, /* setup read ptr */ + { client->addr, I2C_M_RD, 1, &atr }, /* read atr */ + }; + + /* read atr register */ + if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + dev_err(&client->dev, "%s: read error\n", __FUNCTION__); + return -EIO; + } + + dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr); + + /* atr is a two's complement value on 6 bits, + * perform sign extension. The formula is + * Catr = (atr * 0.25pF) + 11.00pF. + */ + if (atr & 0x20) + atr |= 0xC0; + + dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr); + + *trim = (atr * 250) + 11000; + + dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim); + + return 0; +} + +struct x1205_limit +{ + unsigned char reg, mask, min, max; +}; + +static int x1205_validate_client(struct i2c_client *client) +{ + int i, xfer; + + /* Probe array. We will read the register at the specified + * address and check if the given bits are zero. + */ + static const unsigned char probe_zero_pattern[] = { + /* register, mask */ + X1205_REG_SR, 0x18, + X1205_REG_DTR, 0xF8, + X1205_REG_ATR, 0xC0, + X1205_REG_INT, 0x18, + X1205_REG_0, 0xFF, + }; + + static const struct x1205_limit probe_limits_pattern[] = { + /* register, mask, min, max */ + { X1205_REG_Y2K, 0xFF, 19, 20 }, + { X1205_REG_DW, 0xFF, 0, 6 }, + { X1205_REG_YR, 0xFF, 0, 99 }, + { X1205_REG_MO, 0xFF, 0, 12 }, + { X1205_REG_DT, 0xFF, 0, 31 }, + { X1205_REG_HR, 0x7F, 0, 23 }, + { X1205_REG_MN, 0xFF, 0, 59 }, + { X1205_REG_SC, 0xFF, 0, 59 }, + { X1205_REG_Y2K1, 0xFF, 19, 20 }, + { X1205_REG_Y2K0, 0xFF, 19, 20 }, + }; + + /* check that registers have bits a 0 where expected */ + for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) { + unsigned char buf; + + unsigned char addr[2] = { 0, probe_zero_pattern[i] }; + + struct i2c_msg msgs[2] = { + { client->addr, 0, 2, addr }, + { client->addr, I2C_M_RD, 1, &buf }, + }; + + if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { + dev_err(&client->adapter->dev, + "%s: could not read register %x\n", + __FUNCTION__, probe_zero_pattern[i]); + + return -EIO; + } + + if ((buf & probe_zero_pattern[i+1]) != 0) { + dev_err(&client->adapter->dev, + "%s: register=%02x, zero pattern=%d, value=%x\n", + __FUNCTION__, probe_zero_pattern[i], i, buf); + + return -ENODEV; + } + } + + /* check limits (only registers with bcd values) */ + for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) { + unsigned char reg, value; + + unsigned char addr[2] = { 0, probe_limits_pattern[i].reg }; + + struct i2c_msg msgs[2] = { + { client->addr, 0, 2, addr }, + { client->addr, I2C_M_RD, 1, ® }, + }; + + if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { + dev_err(&client->adapter->dev, + "%s: could not read register %x\n", + __FUNCTION__, probe_limits_pattern[i].reg); + + return -EIO; + } + + value = BCD2BIN(reg & probe_limits_pattern[i].mask); + + if (value > probe_limits_pattern[i].max || + value < probe_limits_pattern[i].min) { + dev_dbg(&client->adapter->dev, + "%s: register=%x, lim pattern=%d, value=%d\n", + __FUNCTION__, probe_limits_pattern[i].reg, + i, value); + + return -ENODEV; + } + } + + return 0; +} + +static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + return x1205_get_datetime(to_i2c_client(dev), + &alrm->time, X1205_ALM0_BASE); +} + +static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + return x1205_set_datetime(to_i2c_client(dev), + &alrm->time, 1, X1205_ALM0_BASE); +} + +static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + return x1205_get_datetime(to_i2c_client(dev), + tm, X1205_CCR_BASE); +} + +static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return x1205_set_datetime(to_i2c_client(dev), + tm, 1, X1205_CCR_BASE); +} + +static int x1205_rtc_proc(struct device *dev, struct seq_file *seq) +{ + int err, dtrim, atrim; + + seq_printf(seq, "24hr\t\t: yes\n"); + + if ((err = x1205_get_dtrim(to_i2c_client(dev), &dtrim)) == 0) + seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim); + + if ((err = x1205_get_atrim(to_i2c_client(dev), &atrim)) == 0) + seq_printf(seq, "analog_trim\t: %d.%02d pF\n", + atrim / 1000, atrim % 1000); + return 0; +} + +static struct rtc_class_ops x1205_rtc_ops = { + .proc = x1205_rtc_proc, + .read_time = x1205_rtc_read_time, + .set_time = x1205_rtc_set_time, + .read_alarm = x1205_rtc_read_alarm, + .set_alarm = x1205_rtc_set_alarm, +}; + +static ssize_t x1205_sysfs_show_atrim(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int atrim; + + if (x1205_get_atrim(to_i2c_client(dev), &atrim) == 0) + return sprintf(buf, "%d.%02d pF\n", + atrim / 1000, atrim % 1000); + return 0; +} +static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL); + +static ssize_t x1205_sysfs_show_dtrim(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int dtrim; + + if (x1205_get_dtrim(to_i2c_client(dev), &dtrim) == 0) + return sprintf(buf, "%d ppm\n", dtrim); + + return 0; +} +static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL); + +static int x1205_attach(struct i2c_adapter *adapter) +{ + dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); + return i2c_probe(adapter, &addr_data, x1205_probe); +} + +static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) +{ + int err = 0; + unsigned char sr; + struct i2c_client *client; + struct rtc_device *rtc; + + dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); + + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { + err = -ENODEV; + goto exit; + } + + if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + /* I2C client */ + client->addr = address; + client->driver = &x1205_driver; + client->adapter = adapter; + + strlcpy(client->name, x1205_driver.driver.name, I2C_NAME_SIZE); + + /* Verify the chip is really an X1205 */ + if (kind < 0) { + if (x1205_validate_client(client) < 0) { + err = -ENODEV; + goto exit_kfree; + } + } + + /* Inform the i2c layer */ + if ((err = i2c_attach_client(client))) + goto exit_kfree; + + dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); + + rtc = rtc_device_register(x1205_driver.driver.name, &client->dev, + &x1205_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) { + err = PTR_ERR(rtc); + dev_err(&client->dev, + "unable to register the class device\n"); + goto exit_detach; + } + + i2c_set_clientdata(client, rtc); + + /* Check for power failures and eventualy enable the osc */ + if ((err = x1205_get_status(client, &sr)) == 0) { + if (sr & X1205_SR_RTCF) { + dev_err(&client->dev, + "power failure detected, " + "please set the clock\n"); + udelay(50); + x1205_fix_osc(client); + } + } + else + dev_err(&client->dev, "couldn't read status\n"); + + device_create_file(&client->dev, &dev_attr_atrim); + device_create_file(&client->dev, &dev_attr_dtrim); + + return 0; + +exit_detach: + i2c_detach_client(client); + +exit_kfree: + kfree(client); + +exit: + return err; +} + +static int x1205_detach(struct i2c_client *client) +{ + int err; + struct rtc_device *rtc = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "%s\n", __FUNCTION__); + + if (rtc) + rtc_device_unregister(rtc); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(client); + + return 0; +} + +static int __init x1205_init(void) +{ + return i2c_add_driver(&x1205_driver); +} + +static void __exit x1205_exit(void) +{ + i2c_del_driver(&x1205_driver); +} + +MODULE_AUTHOR( + "Karen Spearel , " + "Alessandro Zummo "); +MODULE_DESCRIPTION("Xicor/Intersil X1205 RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(x1205_init); +module_exit(x1205_exit); -- cgit v1.2.3-59-g8ed1b From a95579cd4b40a4e062e187d931f498145551ee29 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:42 -0800 Subject: [PATCH] RTC subsystem: test device/driver Interrupts can be generated by echo "alarm|tick|update" >/sys/class/rtc/rtcX/device/irq Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 15 ++++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-test.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 drivers/rtc/rtc-test.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 3de823f2f055..7eb1368d04f6 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -86,4 +86,19 @@ config RTC_DRV_X1205 This driver can also be built as a module. If so, the module will be called rtc-x1205. +config RTC_DRV_TEST + tristate "Test driver/device" + depends on RTC_CLASS + help + If you say yes here you get support for the + RTC test driver. It's a software RTC which can be + used to test the RTC subsystem APIs. It gets + the time from the system clock. + You want this driver only if you are doing development + on the RTC subsystem. Please read the source code + for further details. + + This driver can also be built as a module. If so, the module + will be called rtc-test. + endmenu diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index eaf89b22db7a..d5ea0ed81905 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -12,4 +12,5 @@ obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o +obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c new file mode 100644 index 000000000000..43d107487820 --- /dev/null +++ b/drivers/rtc/rtc-test.c @@ -0,0 +1,204 @@ +/* + * An RTC test device/driver + * Copyright (C) 2005 Tower Technologies + * Author: Alessandro Zummo + * + * 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 +#include + +static struct platform_device *test0 = NULL, *test1 = NULL; + +static int test_rtc_read_alarm(struct device *dev, + struct rtc_wkalrm *alrm) +{ + return 0; +} + +static int test_rtc_set_alarm(struct device *dev, + struct rtc_wkalrm *alrm) +{ + return 0; +} + +static int test_rtc_read_time(struct device *dev, + struct rtc_time *tm) +{ + rtc_time_to_tm(get_seconds(), tm); + return 0; +} + +static int test_rtc_set_time(struct device *dev, + struct rtc_time *tm) +{ + return 0; +} + +static int test_rtc_set_mmss(struct device *dev, unsigned long secs) +{ + return 0; +} + +static int test_rtc_proc(struct device *dev, struct seq_file *seq) +{ + struct platform_device *plat_dev = to_platform_device(dev); + + seq_printf(seq, "24hr\t\t: yes\n"); + seq_printf(seq, "test\t\t: yes\n"); + seq_printf(seq, "id\t\t: %d\n", plat_dev->id); + + return 0; +} + +static int test_rtc_ioctl(struct device *dev, unsigned int cmd, + unsigned long arg) +{ + /* We do support interrupts, they're generated + * using the sysfs interface. + */ + switch (cmd) { + case RTC_PIE_ON: + case RTC_PIE_OFF: + case RTC_UIE_ON: + case RTC_UIE_OFF: + case RTC_AIE_ON: + case RTC_AIE_OFF: + return 0; + + default: + return -EINVAL; + } +} + +static struct rtc_class_ops test_rtc_ops = { + .proc = test_rtc_proc, + .read_time = test_rtc_read_time, + .set_time = test_rtc_set_time, + .read_alarm = test_rtc_read_alarm, + .set_alarm = test_rtc_set_alarm, + .set_mmss = test_rtc_set_mmss, + .ioctl = test_rtc_ioctl, +}; + +static ssize_t test_irq_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", 42); +} +static ssize_t test_irq_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int retval; + struct platform_device *plat_dev = to_platform_device(dev); + struct rtc_device *rtc = platform_get_drvdata(plat_dev); + + retval = count; + if (strncmp(buf, "tick", 4) == 0) + rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF); + else if (strncmp(buf, "alarm", 5) == 0) + rtc_update_irq(&rtc->class_dev, 1, RTC_AF | RTC_IRQF); + else if (strncmp(buf, "update", 6) == 0) + rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF); + else + retval = -EINVAL; + + return retval; +} +static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store); + +static int test_probe(struct platform_device *plat_dev) +{ + int err; + struct rtc_device *rtc = rtc_device_register("test", &plat_dev->dev, + &test_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + err = PTR_ERR(rtc); + dev_err(&plat_dev->dev, + "unable to register the class device\n"); + return err; + } + device_create_file(&plat_dev->dev, &dev_attr_irq); + + platform_set_drvdata(plat_dev, rtc); + + return 0; +} + +static int __devexit test_remove(struct platform_device *plat_dev) +{ + struct rtc_device *rtc = platform_get_drvdata(plat_dev); + + rtc_device_unregister(rtc); + device_remove_file(&plat_dev->dev, &dev_attr_irq); + + return 0; +} + +static struct platform_driver test_drv = { + .probe = test_probe, + .remove = __devexit_p(test_remove), + .driver = { + .name = "rtc-test", + .owner = THIS_MODULE, + }, +}; + +static int __init test_init(void) +{ + int err; + + if ((err = platform_driver_register(&test_drv))) + return err; + + if ((test0 = platform_device_alloc("rtc-test", 0)) == NULL) { + err = -ENOMEM; + goto exit_driver_unregister; + } + + if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) { + err = -ENOMEM; + goto exit_free_test0; + } + + if ((err = platform_device_add(test0))) + goto exit_free_test1; + + if ((err = platform_device_add(test1))) + goto exit_device_unregister; + + return 0; + +exit_device_unregister: + platform_device_unregister(test0); + +exit_free_test1: + platform_device_put(test1); + +exit_free_test0: + platform_device_put(test0); + +exit_driver_unregister: + platform_driver_unregister(&test_drv); + return err; +} + +static void __exit test_exit(void) +{ + platform_device_unregister(test0); + platform_device_unregister(test1); + platform_driver_unregister(&test_drv); +} + +MODULE_AUTHOR("Alessandro Zummo "); +MODULE_DESCRIPTION("RTC test driver/device"); +MODULE_LICENSE("GPL"); + +module_init(test_init); +module_exit(test_exit); -- cgit v1.2.3-59-g8ed1b From edf1aaa31fc52ade0da7b6d1f2dffc17f0bdb9ff Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:43 -0800 Subject: [PATCH] RTC subsystem: DS1672 driver Driver for the Dallas/Maxim DS1672 chip, found on the Loft (http://www.giantshoulderinc.com). Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 10 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-ds1672.c | 233 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+) create mode 100644 drivers/rtc/rtc-ds1672.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 7eb1368d04f6..de3352658654 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -86,6 +86,16 @@ config RTC_DRV_X1205 This driver can also be built as a module. If so, the module will be called rtc-x1205. +config RTC_DRV_DS1672 + tristate "Dallas/Maxim DS1672" + depends on RTC_CLASS && I2C + help + If you say yes here you get support for the + Dallas/Maxim DS1672 timekeeping chip. + + This driver can also be built as a module. If so, the module + will be called rtc-ds1672. + config RTC_DRV_TEST tristate "Test driver/device" depends on RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index d5ea0ed81905..f3fd5b0cd735 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -13,4 +13,5 @@ obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o +obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c new file mode 100644 index 000000000000..358695a416f3 --- /dev/null +++ b/drivers/rtc/rtc-ds1672.c @@ -0,0 +1,233 @@ +/* + * An rtc/i2c driver for the Dallas DS1672 + * Copyright 2005 Alessandro Zummo + * + * 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 + +#define DRV_VERSION "0.2" + +/* Addresses to scan: none. This chip cannot be detected. */ +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD; + +/* Registers */ + +#define DS1672_REG_CNT_BASE 0 +#define DS1672_REG_CONTROL 4 +#define DS1672_REG_TRICKLE 5 + + +/* Prototypes */ +static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind); + +/* + * In the routines that deal directly with the ds1672 hardware, we use + * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch + * Epoch is initialized as 2000. Time is set to UTC. + */ +static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) +{ + unsigned long time; + unsigned char addr = DS1672_REG_CNT_BASE; + unsigned char buf[4]; + + struct i2c_msg msgs[] = { + { client->addr, 0, 1, &addr }, /* setup read ptr */ + { client->addr, I2C_M_RD, 4, buf }, /* read date */ + }; + + /* read date registers */ + if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + dev_err(&client->dev, "%s: read error\n", __FUNCTION__); + return -EIO; + } + + dev_dbg(&client->dev, + "%s: raw read data - counters=%02x,%02x,%02x,%02x\n" + __FUNCTION__, + buf[0], buf[1], buf[2], buf[3]); + + time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + + rtc_time_to_tm(time, tm); + + dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " + "mday=%d, mon=%d, year=%d, wday=%d\n", + __FUNCTION__, + tm->tm_sec, tm->tm_min, tm->tm_hour, + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + + return 0; +} + +static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) +{ + int xfer; + unsigned char buf[5]; + + buf[0] = DS1672_REG_CNT_BASE; + buf[1] = secs & 0x000000FF; + buf[2] = (secs & 0x0000FF00) >> 8; + buf[3] = (secs & 0x00FF0000) >> 16; + buf[4] = (secs & 0xFF000000) >> 24; + + xfer = i2c_master_send(client, buf, 5); + if (xfer != 5) { + dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer); + return -EIO; + } + + return 0; +} + +static int ds1672_set_datetime(struct i2c_client *client, struct rtc_time *tm) +{ + unsigned long secs; + + dev_dbg(&client->dev, + "%s: secs=%d, mins=%d, hours=%d, ", + "mday=%d, mon=%d, year=%d, wday=%d\n", + __FUNCTION__, + tm->tm_sec, tm->tm_min, tm->tm_hour, + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + + rtc_tm_to_time(tm, &secs); + + return ds1672_set_mmss(client, secs); +} + +static int ds1672_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + return ds1672_get_datetime(to_i2c_client(dev), tm); +} + +static int ds1672_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return ds1672_set_datetime(to_i2c_client(dev), tm); +} + +static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs) +{ + return ds1672_set_mmss(to_i2c_client(dev), secs); +} + +static struct rtc_class_ops ds1672_rtc_ops = { + .read_time = ds1672_rtc_read_time, + .set_time = ds1672_rtc_set_time, + .set_mmss = ds1672_rtc_set_mmss, +}; + +static int ds1672_attach(struct i2c_adapter *adapter) +{ + dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); + return i2c_probe(adapter, &addr_data, ds1672_probe); +} + +static int ds1672_detach(struct i2c_client *client) +{ + int err; + struct rtc_device *rtc = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "%s\n", __FUNCTION__); + + if (rtc) + rtc_device_unregister(rtc); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(client); + + return 0; +} + +static struct i2c_driver ds1672_driver = { + .driver = { + .name = "ds1672", + }, + .id = I2C_DRIVERID_DS1672, + .attach_adapter = &ds1672_attach, + .detach_client = &ds1672_detach, +}; + +static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) +{ + int err = 0; + struct i2c_client *client; + struct rtc_device *rtc; + + dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); + + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { + err = -ENODEV; + goto exit; + } + + if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + /* I2C client */ + client->addr = address; + client->driver = &ds1672_driver; + client->adapter = adapter; + + strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE); + + /* Inform the i2c layer */ + if ((err = i2c_attach_client(client))) + goto exit_kfree; + + dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); + + rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, + &ds1672_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) { + err = PTR_ERR(rtc); + dev_err(&client->dev, + "unable to register the class device\n"); + goto exit_detach; + } + + i2c_set_clientdata(client, rtc); + + return 0; + +exit_detach: + i2c_detach_client(client); + +exit_kfree: + kfree(client); + +exit: + return err; +} + +static int __init ds1672_init(void) +{ + return i2c_add_driver(&ds1672_driver); +} + +static void __exit ds1672_exit(void) +{ + i2c_del_driver(&ds1672_driver); +} + +MODULE_AUTHOR("Alessandro Zummo "); +MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(ds1672_init); +module_exit(ds1672_exit); -- cgit v1.2.3-59-g8ed1b From b5a82d628d4491558c109fbeabc2993d6686e89c Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:44 -0800 Subject: [PATCH] RTC subsystem: PCF8563 driver An RTC class aware driver for the Philips PCF8563 RTC and Epson RTC8564 chips. This chip is used on the Iomega NAS100D. Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 11 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-pcf8563.c | 353 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 365 insertions(+) create mode 100644 drivers/rtc/rtc-pcf8563.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index de3352658654..0309fb368758 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -96,6 +96,17 @@ config RTC_DRV_DS1672 This driver can also be built as a module. If so, the module will be called rtc-ds1672. +config RTC_DRV_PCF8563 + tristate "Philips PCF8563/Epson RTC8564" + depends on RTC_CLASS && I2C + help + If you say yes here you get support for the + Philips PCF8563 RTC chip. The Epson RTC8564 + should work as well. + + This driver can also be built as a module. If so, the module + will be called rtc-pcf8563. + config RTC_DRV_TEST tristate "Test driver/device" depends on RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index f3fd5b0cd735..bdf7e491d5ac 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -14,4 +14,5 @@ obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o +obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c new file mode 100644 index 000000000000..d857d45bdbe8 --- /dev/null +++ b/drivers/rtc/rtc-pcf8563.c @@ -0,0 +1,353 @@ +/* + * An I2C driver for the Philips PCF8563 RTC + * Copyright 2005-06 Tower Technologies + * + * Author: Alessandro Zummo + * Maintainers: http://www.nslu2-linux.org/ + * + * based on the other drivers in this same directory. + * + * http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf + * + * 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 + +#define DRV_VERSION "0.4.2" + +/* Addresses to scan: none + * This chip cannot be reliably autodetected. An empty eeprom + * located at 0x51 will pass the validation routine due to + * the way the registers are implemented. + */ +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Module parameters */ +I2C_CLIENT_INSMOD; + +#define PCF8563_REG_ST1 0x00 /* status */ +#define PCF8563_REG_ST2 0x01 + +#define PCF8563_REG_SC 0x02 /* datetime */ +#define PCF8563_REG_MN 0x03 +#define PCF8563_REG_HR 0x04 +#define PCF8563_REG_DM 0x05 +#define PCF8563_REG_DW 0x06 +#define PCF8563_REG_MO 0x07 +#define PCF8563_REG_YR 0x08 + +#define PCF8563_REG_AMN 0x09 /* alarm */ +#define PCF8563_REG_AHR 0x0A +#define PCF8563_REG_ADM 0x0B +#define PCF8563_REG_ADW 0x0C + +#define PCF8563_REG_CLKO 0x0D /* clock out */ +#define PCF8563_REG_TMRC 0x0E /* timer control */ +#define PCF8563_REG_TMR 0x0F /* timer */ + +#define PCF8563_SC_LV 0x80 /* low voltage */ +#define PCF8563_MO_C 0x80 /* century */ + +static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind); +static int pcf8563_detach(struct i2c_client *client); + +/* + * In the routines that deal directly with the pcf8563 hardware, we use + * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. + */ +static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) +{ + unsigned char buf[13] = { PCF8563_REG_ST1 }; + + struct i2c_msg msgs[] = { + { client->addr, 0, 1, buf }, /* setup read ptr */ + { client->addr, I2C_M_RD, 13, buf }, /* read status + date */ + }; + + /* read registers */ + if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { + dev_err(&client->dev, "%s: read error\n", __FUNCTION__); + return -EIO; + } + + if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) + dev_info(&client->dev, + "low voltage detected, date/time is not reliable.\n"); + + dev_dbg(&client->dev, + "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, " + "mday=%02x, wday=%02x, mon=%02x, year=%02x\n", + __FUNCTION__, + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7], + buf[8]); + + + tm->tm_sec = BCD2BIN(buf[PCF8563_REG_SC] & 0x7F); + tm->tm_min = BCD2BIN(buf[PCF8563_REG_MN] & 0x7F); + tm->tm_hour = BCD2BIN(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */ + tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F); + tm->tm_wday = buf[PCF8563_REG_DW] & 0x07; + tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ + tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]) + + (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 100 : 0); + + dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " + "mday=%d, mon=%d, year=%d, wday=%d\n", + __FUNCTION__, + tm->tm_sec, tm->tm_min, tm->tm_hour, + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + + /* the clock can give out invalid datetime, but we cannot return + * -EINVAL otherwise hwclock will refuse to set the time on bootup. + */ + if (rtc_valid_tm(tm) < 0) + dev_err(&client->dev, "retrieved date/time is not valid.\n"); + + return 0; +} + +static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) +{ + int i, err; + unsigned char buf[9]; + + dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " + "mday=%d, mon=%d, year=%d, wday=%d\n", + __FUNCTION__, + tm->tm_sec, tm->tm_min, tm->tm_hour, + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + + /* hours, minutes and seconds */ + buf[PCF8563_REG_SC] = BIN2BCD(tm->tm_sec); + buf[PCF8563_REG_MN] = BIN2BCD(tm->tm_min); + buf[PCF8563_REG_HR] = BIN2BCD(tm->tm_hour); + + buf[PCF8563_REG_DM] = BIN2BCD(tm->tm_mday); + + /* month, 1 - 12 */ + buf[PCF8563_REG_MO] = BIN2BCD(tm->tm_mon + 1); + + /* year and century */ + buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100); + if (tm->tm_year / 100) + buf[PCF8563_REG_MO] |= PCF8563_MO_C; + + buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; + + /* write register's data */ + for (i = 0; i < 7; i++) { + unsigned char data[2] = { PCF8563_REG_SC + i, + buf[PCF8563_REG_SC + i] }; + + err = i2c_master_send(client, data, sizeof(data)); + if (err != sizeof(data)) { + dev_err(&client->dev, + "%s: err=%d addr=%02x, data=%02x\n", + __FUNCTION__, err, data[0], data[1]); + return -EIO; + } + }; + + return 0; +} + +struct pcf8563_limit +{ + unsigned char reg; + unsigned char mask; + unsigned char min; + unsigned char max; +}; + +static int pcf8563_validate_client(struct i2c_client *client) +{ + int i; + + static const struct pcf8563_limit pattern[] = { + /* register, mask, min, max */ + { PCF8563_REG_SC, 0x7F, 0, 59 }, + { PCF8563_REG_MN, 0x7F, 0, 59 }, + { PCF8563_REG_HR, 0x3F, 0, 23 }, + { PCF8563_REG_DM, 0x3F, 0, 31 }, + { PCF8563_REG_MO, 0x1F, 0, 12 }, + }; + + /* check limits (only registers with bcd values) */ + for (i = 0; i < ARRAY_SIZE(pattern); i++) { + int xfer; + unsigned char value; + unsigned char buf = pattern[i].reg; + + struct i2c_msg msgs[] = { + { client->addr, 0, 1, &buf }, + { client->addr, I2C_M_RD, 1, &buf }, + }; + + xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + + if (xfer != ARRAY_SIZE(msgs)) { + dev_err(&client->adapter->dev, + "%s: could not read register 0x%02X\n", + __FUNCTION__, pattern[i].reg); + + return -EIO; + } + + value = BCD2BIN(buf & pattern[i].mask); + + if (value > pattern[i].max || + value < pattern[i].min) { + dev_dbg(&client->adapter->dev, + "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, " + "max=%d, value=%d, raw=0x%02X\n", + __FUNCTION__, i, pattern[i].reg, pattern[i].mask, + pattern[i].min, pattern[i].max, + value, buf); + + return -ENODEV; + } + } + + return 0; +} + +static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + return pcf8563_get_datetime(to_i2c_client(dev), tm); +} + +static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return pcf8563_set_datetime(to_i2c_client(dev), tm); +} + +static int pcf8563_rtc_proc(struct device *dev, struct seq_file *seq) +{ + seq_printf(seq, "24hr\t\t: yes\n"); + return 0; +} + +static struct rtc_class_ops pcf8563_rtc_ops = { + .proc = pcf8563_rtc_proc, + .read_time = pcf8563_rtc_read_time, + .set_time = pcf8563_rtc_set_time, +}; + +static int pcf8563_attach(struct i2c_adapter *adapter) +{ + return i2c_probe(adapter, &addr_data, pcf8563_probe); +} + +static struct i2c_driver pcf8563_driver = { + .driver = { + .name = "pcf8563", + }, + .id = I2C_DRIVERID_PCF8563, + .attach_adapter = &pcf8563_attach, + .detach_client = &pcf8563_detach, +}; + +static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct rtc_device *rtc; + + int err = 0; + + dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); + + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { + err = -ENODEV; + goto exit; + } + + if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client->addr = address; + client->driver = &pcf8563_driver; + client->adapter = adapter; + + strlcpy(client->name, pcf8563_driver.driver.name, I2C_NAME_SIZE); + + /* Verify the chip is really an PCF8563 */ + if (kind < 0) { + if (pcf8563_validate_client(client) < 0) { + err = -ENODEV; + goto exit_kfree; + } + } + + /* Inform the i2c layer */ + if ((err = i2c_attach_client(client))) + goto exit_kfree; + + dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); + + rtc = rtc_device_register(pcf8563_driver.driver.name, &client->dev, + &pcf8563_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) { + err = PTR_ERR(rtc); + dev_err(&client->dev, + "unable to register the class device\n"); + goto exit_detach; + } + + i2c_set_clientdata(client, rtc); + + return 0; + +exit_detach: + i2c_detach_client(client); + +exit_kfree: + kfree(client); + +exit: + return err; +} + +static int pcf8563_detach(struct i2c_client *client) +{ + int err; + struct rtc_device *rtc = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "%s\n", __FUNCTION__); + + if (rtc) + rtc_device_unregister(rtc); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(client); + + return 0; +} + +static int __init pcf8563_init(void) +{ + return i2c_add_driver(&pcf8563_driver); +} + +static void __exit pcf8563_exit(void) +{ + i2c_del_driver(&pcf8563_driver); +} + +MODULE_AUTHOR("Alessandro Zummo "); +MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(pcf8563_init); +module_exit(pcf8563_exit); -- cgit v1.2.3-59-g8ed1b From 7520b94debdc61620e1582fb4f5cca4a830f91cd Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:45 -0800 Subject: [PATCH] RTC subsystem: RS5C372 driver RTC class aware driver for the Ricoh RS5C372 chip used, among others, on the Synology DS101. Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 10 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-rs5c372.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 305 insertions(+) create mode 100644 drivers/rtc/rtc-rs5c372.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 0309fb368758..609f55593459 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -107,6 +107,16 @@ config RTC_DRV_PCF8563 This driver can also be built as a module. If so, the module will be called rtc-pcf8563. +config RTC_DRV_RS5C372 + tristate "Ricoh RS5C372A/B" + depends on RTC_CLASS && I2C + help + If you say yes here you get support for the + Ricoh RS5C372A and RS5C372B RTC chips. + + This driver can also be built as a module. If so, the module + will be called rtc-rs5c372. + config RTC_DRV_TEST tristate "Test driver/device" depends on RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index bdf7e491d5ac..d2b4b1735598 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -15,4 +15,5 @@ obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o +obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c new file mode 100644 index 000000000000..396c8681f66c --- /dev/null +++ b/drivers/rtc/rtc-rs5c372.c @@ -0,0 +1,294 @@ +/* + * An I2C driver for the Ricoh RS5C372 RTC + * + * Copyright (C) 2005 Pavel Mironchik + * Copyright (C) 2006 Tower Technologies + * + * 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 + +#define DRV_VERSION "0.2" + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD; + +#define RS5C372_REG_SECS 0 +#define RS5C372_REG_MINS 1 +#define RS5C372_REG_HOURS 2 +#define RS5C372_REG_WDAY 3 +#define RS5C372_REG_DAY 4 +#define RS5C372_REG_MONTH 5 +#define RS5C372_REG_YEAR 6 +#define RS5C372_REG_TRIM 7 + +#define RS5C372_TRIM_XSL 0x80 +#define RS5C372_TRIM_MASK 0x7F + +#define RS5C372_REG_BASE 0 + +static int rs5c372_attach(struct i2c_adapter *adapter); +static int rs5c372_detach(struct i2c_client *client); +static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind); + +static struct i2c_driver rs5c372_driver = { + .driver = { + .name = "rs5c372", + }, + .attach_adapter = &rs5c372_attach, + .detach_client = &rs5c372_detach, +}; + +static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) +{ + unsigned char buf[7] = { RS5C372_REG_BASE }; + + /* this implements the 1st reading method, according + * to the datasheet. buf[0] is initialized with + * address ptr and transmission format register. + */ + struct i2c_msg msgs[] = { + { client->addr, 0, 1, buf }, + { client->addr, I2C_M_RD, 7, buf }, + }; + + if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { + dev_err(&client->dev, "%s: read error\n", __FUNCTION__); + return -EIO; + } + + tm->tm_sec = BCD2BIN(buf[RS5C372_REG_SECS] & 0x7f); + tm->tm_min = BCD2BIN(buf[RS5C372_REG_MINS] & 0x7f); + tm->tm_hour = BCD2BIN(buf[RS5C372_REG_HOURS] & 0x3f); + tm->tm_wday = BCD2BIN(buf[RS5C372_REG_WDAY] & 0x07); + tm->tm_mday = BCD2BIN(buf[RS5C372_REG_DAY] & 0x3f); + + /* tm->tm_mon is zero-based */ + tm->tm_mon = BCD2BIN(buf[RS5C372_REG_MONTH] & 0x1f) - 1; + + /* year is 1900 + tm->tm_year */ + tm->tm_year = BCD2BIN(buf[RS5C372_REG_YEAR]) + 100; + + dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " + "mday=%d, mon=%d, year=%d, wday=%d\n", + __FUNCTION__, + tm->tm_sec, tm->tm_min, tm->tm_hour, + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + + return 0; +} + +static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) +{ + unsigned char buf[8] = { RS5C372_REG_BASE }; + + dev_dbg(&client->dev, + "%s: secs=%d, mins=%d, hours=%d ", + "mday=%d, mon=%d, year=%d, wday=%d\n", + __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour, + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + + buf[1] = BIN2BCD(tm->tm_sec); + buf[2] = BIN2BCD(tm->tm_min); + buf[3] = BIN2BCD(tm->tm_hour); + buf[4] = BIN2BCD(tm->tm_wday); + buf[5] = BIN2BCD(tm->tm_mday); + buf[6] = BIN2BCD(tm->tm_mon + 1); + buf[7] = BIN2BCD(tm->tm_year - 100); + + if ((i2c_master_send(client, buf, 8)) != 8) { + dev_err(&client->dev, "%s: write error\n", __FUNCTION__); + return -EIO; + } + + return 0; +} + +static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim) +{ + unsigned char buf = RS5C372_REG_TRIM; + + struct i2c_msg msgs[] = { + { client->addr, 0, 1, &buf }, + { client->addr, I2C_M_RD, 1, &buf }, + }; + + if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { + dev_err(&client->dev, "%s: read error\n", __FUNCTION__); + return -EIO; + } + + dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, trim); + + if (osc) + *osc = (buf & RS5C372_TRIM_XSL) ? 32000 : 32768; + + if (trim) + *trim = buf & RS5C372_TRIM_MASK; + + return 0; +} + +static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + return rs5c372_get_datetime(to_i2c_client(dev), tm); +} + +static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return rs5c372_set_datetime(to_i2c_client(dev), tm); +} + +static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq) +{ + int err, osc, trim; + + seq_printf(seq, "24hr\t\t: yes\n"); + + if ((err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim)) == 0) { + seq_printf(seq, "%d.%03d KHz\n", osc / 1000, osc % 1000); + seq_printf(seq, "trim\t: %d\n", trim); + } + + return 0; +} + +static struct rtc_class_ops rs5c372_rtc_ops = { + .proc = rs5c372_rtc_proc, + .read_time = rs5c372_rtc_read_time, + .set_time = rs5c372_rtc_set_time, +}; + +static ssize_t rs5c372_sysfs_show_trim(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int trim; + + if (rs5c372_get_trim(to_i2c_client(dev), NULL, &trim) == 0) + return sprintf(buf, "0x%2x\n", trim); + + return 0; +} +static DEVICE_ATTR(trim, S_IRUGO, rs5c372_sysfs_show_trim, NULL); + +static ssize_t rs5c372_sysfs_show_osc(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int osc; + + if (rs5c372_get_trim(to_i2c_client(dev), &osc, NULL) == 0) + return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000); + + return 0; +} +static DEVICE_ATTR(osc, S_IRUGO, rs5c372_sysfs_show_osc, NULL); + +static int rs5c372_attach(struct i2c_adapter *adapter) +{ + dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); + return i2c_probe(adapter, &addr_data, rs5c372_probe); +} + +static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) +{ + int err = 0; + struct i2c_client *client; + struct rtc_device *rtc; + + dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); + + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { + err = -ENODEV; + goto exit; + } + + if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + /* I2C client */ + client->addr = address; + client->driver = &rs5c372_driver; + client->adapter = adapter; + + strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE); + + /* Inform the i2c layer */ + if ((err = i2c_attach_client(client))) + goto exit_kfree; + + dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); + + rtc = rtc_device_register(rs5c372_driver.driver.name, &client->dev, + &rs5c372_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) { + err = PTR_ERR(rtc); + dev_err(&client->dev, + "unable to register the class device\n"); + goto exit_detach; + } + + i2c_set_clientdata(client, rtc); + + device_create_file(&client->dev, &dev_attr_trim); + device_create_file(&client->dev, &dev_attr_osc); + + return 0; + +exit_detach: + i2c_detach_client(client); + +exit_kfree: + kfree(client); + +exit: + return err; +} + +static int rs5c372_detach(struct i2c_client *client) +{ + int err; + struct rtc_device *rtc = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "%s\n", __FUNCTION__); + + if (rtc) + rtc_device_unregister(rtc); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(client); + + return 0; +} + +static __init int rs5c372_init(void) +{ + return i2c_add_driver(&rs5c372_driver); +} + +static __exit void rs5c372_exit(void) +{ + i2c_del_driver(&rs5c372_driver); +} + +module_init(rs5c372_init); +module_exit(rs5c372_exit); + +MODULE_AUTHOR( + "Pavel Mironchik , " + "Alessandro Zummo "); +MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); -- cgit v1.2.3-59-g8ed1b From fd507e2ff3a5adaccbefa05f4bc9f58f44e930db Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:45 -0800 Subject: [PATCH] RTC subsystem: EP93XX driver This patch adds a driver for the RTC embedded in the Cirrus Logic EP93XX family of processors. Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 11 ++++ drivers/rtc/Makefile | 2 +- drivers/rtc/rtc-ep93xx.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 drivers/rtc/rtc-ep93xx.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 609f55593459..b399259784e2 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -117,6 +117,17 @@ config RTC_DRV_RS5C372 This driver can also be built as a module. If so, the module will be called rtc-rs5c372. +config RTC_DRV_EP93XX + tristate "Cirrus Logic EP93XX" + depends on RTC_CLASS && ARCH_EP93XX + help + If you say yes here you get support for the + RTC embedded in the Cirrus Logic EP93XX processors. + + This driver can also be built as a module. If so, the module + will be called rtc-ep93xx. + + config RTC_DRV_TEST tristate "Test driver/device" depends on RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index d2b4b1735598..38b4d87939e1 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -16,4 +16,4 @@ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o - +obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c new file mode 100644 index 000000000000..0dd80ea686a9 --- /dev/null +++ b/drivers/rtc/rtc-ep93xx.c @@ -0,0 +1,162 @@ +/* + * A driver for the RTC embedded in the Cirrus Logic EP93XX processors + * Copyright (c) 2006 Tower Technologies + * + * Author: Alessandro Zummo + * + * 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 +#include + +#define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x)) +#define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000) +#define EP93XX_RTC_LOAD EP93XX_RTC_REG(0x000C) +#define EP93XX_RTC_SWCOMP EP93XX_RTC_REG(0x0108) + +#define DRV_VERSION "0.2" + +static int ep93xx_get_swcomp(struct device *dev, unsigned short *preload, + unsigned short *delete) +{ + unsigned short comp = __raw_readl(EP93XX_RTC_SWCOMP); + + if (preload) + *preload = comp & 0xffff; + + if (delete) + *delete = (comp >> 16) & 0x1f; + + return 0; +} + +static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + unsigned long time = __raw_readl(EP93XX_RTC_DATA); + + rtc_time_to_tm(time, tm); + return 0; +} + +static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs) +{ + __raw_writel(secs + 1, EP93XX_RTC_LOAD); + return 0; +} + +static int ep93xx_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + int err; + unsigned long secs; + + err = rtc_tm_to_time(tm, &secs); + if (err != 0) + return err; + + return ep93xx_rtc_set_mmss(dev, secs); +} + +static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq) +{ + unsigned short preload, delete; + + ep93xx_get_swcomp(dev, &preload, &delete); + + seq_printf(seq, "24hr\t\t: yes\n"); + seq_printf(seq, "preload\t\t: %d\n", preload); + seq_printf(seq, "delete\t\t: %d\n", delete); + + return 0; +} + +static struct rtc_class_ops ep93xx_rtc_ops = { + .read_time = ep93xx_rtc_read_time, + .set_time = ep93xx_rtc_set_time, + .set_mmss = ep93xx_rtc_set_mmss, + .proc = ep93xx_rtc_proc, +}; + +static ssize_t ep93xx_sysfs_show_comp_preload(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned short preload; + + ep93xx_get_swcomp(dev, &preload, NULL); + + return sprintf(buf, "%d\n", preload); +} +static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_sysfs_show_comp_preload, NULL); + +static ssize_t ep93xx_sysfs_show_comp_delete(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned short delete; + + ep93xx_get_swcomp(dev, NULL, &delete); + + return sprintf(buf, "%d\n", delete); +} +static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_sysfs_show_comp_delete, NULL); + + +static int __devinit ep93xx_rtc_probe(struct platform_device *dev) +{ + struct rtc_device *rtc = rtc_device_register("ep93xx", + &dev->dev, &ep93xx_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) { + dev_err(&dev->dev, "unable to register\n"); + return PTR_ERR(rtc); + } + + platform_set_drvdata(dev, rtc); + + device_create_file(&dev->dev, &dev_attr_comp_preload); + device_create_file(&dev->dev, &dev_attr_comp_delete); + + return 0; +} + +static int __devexit ep93xx_rtc_remove(struct platform_device *dev) +{ + struct rtc_device *rtc = platform_get_drvdata(dev); + + if (rtc) + rtc_device_unregister(rtc); + + platform_set_drvdata(dev, NULL); + + return 0; +} + +static struct platform_driver ep93xx_rtc_platform_driver = { + .driver = { + .name = "ep93xx-rtc", + .owner = THIS_MODULE, + }, + .probe = ep93xx_rtc_probe, + .remove = __devexit_p(ep93xx_rtc_remove), +}; + +static int __init ep93xx_rtc_init(void) +{ + return platform_driver_register(&ep93xx_rtc_platform_driver); +} + +static void __exit ep93xx_rtc_exit(void) +{ + platform_driver_unregister(&ep93xx_rtc_platform_driver); +} + +MODULE_AUTHOR("Alessandro Zummo "); +MODULE_DESCRIPTION("EP93XX RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(ep93xx_rtc_init); +module_exit(ep93xx_rtc_exit); -- cgit v1.2.3-59-g8ed1b From e842f1c8ff8a88f290e26d1139e89aad02c4e0c3 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Mon, 27 Mar 2006 01:16:46 -0800 Subject: [PATCH] RTC subsystem: SA1100/PXA2XX driver Add an RTC subsystem driver for the ARM SA1100/PXA2XX processor RTC. Signed-off-by: Richard Purdie Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-pxa/generic.c | 6 + arch/arm/mach-sa1100/generic.c | 6 + drivers/rtc/Kconfig | 9 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-sa1100.c | 388 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 410 insertions(+) create mode 100644 drivers/rtc/rtc-sa1100.c (limited to 'drivers') diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 9b48a90aefce..5efa84749f37 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -319,6 +319,11 @@ void __init pxa_set_ficp_info(struct pxaficp_platform_data *info) pxaficp_device.dev.platform_data = info; } +static struct platform_device pxartc_device = { + .name = "sa1100-rtc", + .id = -1, +}; + static struct platform_device *devices[] __initdata = { &pxamci_device, &udc_device, @@ -329,6 +334,7 @@ static struct platform_device *devices[] __initdata = { &pxaficp_device, &i2c_device, &i2s_device, + &pxartc_device, }; static int __init pxa_init(void) diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 2abdc419e984..9ea71551fc04 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -324,6 +324,11 @@ void sa11x0_set_irda_data(struct irda_platform_data *irda) sa11x0ir_device.dev.platform_data = irda; } +static struct platform_device sa11x0rtc_device = { + .name = "sa1100-rtc", + .id = -1, +}; + static struct platform_device *sa11x0_devices[] __initdata = { &sa11x0udc_device, &sa11x0uart1_device, @@ -333,6 +338,7 @@ static struct platform_device *sa11x0_devices[] __initdata = { &sa11x0pcmcia_device, &sa11x0fb_device, &sa11x0mtd_device, + &sa11x0rtc_device, }; static int __init sa1100_init(void) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index b399259784e2..166232a3f56b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -127,6 +127,15 @@ config RTC_DRV_EP93XX This driver can also be built as a module. If so, the module will be called rtc-ep93xx. +config RTC_DRV_SA1100 + tristate "SA11x0/PXA2xx" + depends on RTC_CLASS && (ARCH_SA1100 || ARCH_PXA) + help + If you say Y here you will get access to the real time clock + built into your SA11x0 or PXA2xx CPU. + + To compile this driver as a module, choose M here: the + module will be called rtc-sa1100. config RTC_DRV_TEST tristate "Test driver/device" diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 38b4d87939e1..56820d18161e 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o +obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c new file mode 100644 index 000000000000..83b2bb480a16 --- /dev/null +++ b/drivers/rtc/rtc-sa1100.c @@ -0,0 +1,388 @@ +/* + * Real Time Clock interface for StrongARM SA1x00 and XScale PXA2xx + * + * Copyright (c) 2000 Nils Faerber + * + * Based on rtc.c by Paul Gortmaker + * + * Original Driver by Nils Faerber + * + * Modifications from: + * CIH + * Nicolas Pitre + * Andrew Christian + * + * Converted to the RTC subsystem and Driver Model + * by Richard Purdie + * + * 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 + +#ifdef CONFIG_ARCH_PXA +#include +#endif + +#define TIMER_FREQ CLOCK_TICK_RATE +#define RTC_DEF_DIVIDER 32768 - 1 +#define RTC_DEF_TRIM 0 + +static unsigned long rtc_freq = 1024; +static struct rtc_time rtc_alarm; +static spinlock_t sa1100_rtc_lock = SPIN_LOCK_UNLOCKED; + +static int rtc_update_alarm(struct rtc_time *alrm) +{ + struct rtc_time alarm_tm, now_tm; + unsigned long now, time; + int ret; + + do { + now = RCNR; + rtc_time_to_tm(now, &now_tm); + rtc_next_alarm_time(&alarm_tm, &now_tm, alrm); + ret = rtc_tm_to_time(&alarm_tm, &time); + if (ret != 0) + break; + + RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); + RTAR = time; + } while (now != RCNR); + + return ret; +} + +static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct platform_device *pdev = to_platform_device(dev_id); + struct rtc_device *rtc = platform_get_drvdata(pdev); + unsigned int rtsr; + unsigned long events = 0; + + spin_lock(&sa1100_rtc_lock); + + rtsr = RTSR; + /* clear interrupt sources */ + RTSR = 0; + RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); + + /* clear alarm interrupt if it has occurred */ + if (rtsr & RTSR_AL) + rtsr &= ~RTSR_ALE; + RTSR = rtsr & (RTSR_ALE | RTSR_HZE); + + /* update irq data & counter */ + if (rtsr & RTSR_AL) + events |= RTC_AF | RTC_IRQF; + if (rtsr & RTSR_HZ) + events |= RTC_UF | RTC_IRQF; + + rtc_update_irq(&rtc->class_dev, 1, events); + + if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) + rtc_update_alarm(&rtc_alarm); + + spin_unlock(&sa1100_rtc_lock); + + return IRQ_HANDLED; +} + +static int rtc_timer1_count; + +static irqreturn_t timer1_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct platform_device *pdev = to_platform_device(dev_id); + struct rtc_device *rtc = platform_get_drvdata(pdev); + + /* + * If we match for the first time, rtc_timer1_count will be 1. + * Otherwise, we wrapped around (very unlikely but + * still possible) so compute the amount of missed periods. + * The match reg is updated only when the data is actually retrieved + * to avoid unnecessary interrupts. + */ + OSSR = OSSR_M1; /* clear match on timer1 */ + + rtc_update_irq(&rtc->class_dev, rtc_timer1_count, RTC_PF | RTC_IRQF); + + if (rtc_timer1_count == 1) + rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))); + + return IRQ_HANDLED; +} + +static int sa1100_rtc_read_callback(struct device *dev, int data) +{ + if (data & RTC_PF) { + /* interpolate missed periods and set match for the next */ + unsigned long period = TIMER_FREQ/rtc_freq; + unsigned long oscr = OSCR; + unsigned long osmr1 = OSMR1; + unsigned long missed = (oscr - osmr1)/period; + data += missed << 8; + OSSR = OSSR_M1; /* clear match on timer 1 */ + OSMR1 = osmr1 + (missed + 1)*period; + /* Ensure we didn't miss another match in the mean time. + * Here we compare (match - OSCR) 8 instead of 0 -- + * see comment in pxa_timer_interrupt() for explanation. + */ + while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) { + data += 0x100; + OSSR = OSSR_M1; /* clear match on timer 1 */ + OSMR1 = osmr1 + period; + } + } + return data; +} + +static int sa1100_rtc_open(struct device *dev) +{ + int ret; + + ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, SA_INTERRUPT, + "rtc 1Hz", dev); + if (ret) { + printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTC1Hz); + goto fail_ui; + } + ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, SA_INTERRUPT, + "rtc Alrm", dev); + if (ret) { + printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTCAlrm); + goto fail_ai; + } + ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT, + "rtc timer", dev); + if (ret) { + printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_OST1); + goto fail_pi; + } + return 0; + + fail_pi: + free_irq(IRQ_RTCAlrm, NULL); + fail_ai: + free_irq(IRQ_RTC1Hz, NULL); + fail_ui: + return ret; +} + +static void sa1100_rtc_release(struct device *dev) +{ + spin_lock_irq(&sa1100_rtc_lock); + RTSR = 0; + OIER &= ~OIER_E1; + OSSR = OSSR_M1; + spin_unlock_irq(&sa1100_rtc_lock); + + free_irq(IRQ_OST1, dev); + free_irq(IRQ_RTCAlrm, dev); + free_irq(IRQ_RTC1Hz, dev); +} + + +static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, + unsigned long arg) +{ + switch(cmd) { + case RTC_AIE_OFF: + spin_lock_irq(&sa1100_rtc_lock); + RTSR &= ~RTSR_ALE; + spin_unlock_irq(&sa1100_rtc_lock); + return 0; + case RTC_AIE_ON: + spin_lock_irq(&sa1100_rtc_lock); + RTSR |= RTSR_ALE; + spin_unlock_irq(&sa1100_rtc_lock); + return 0; + case RTC_UIE_OFF: + spin_lock_irq(&sa1100_rtc_lock); + RTSR &= ~RTSR_HZE; + spin_unlock_irq(&sa1100_rtc_lock); + return 0; + case RTC_UIE_ON: + spin_lock_irq(&sa1100_rtc_lock); + RTSR |= RTSR_HZE; + spin_unlock_irq(&sa1100_rtc_lock); + return 0; + case RTC_PIE_OFF: + spin_lock_irq(&sa1100_rtc_lock); + OIER &= ~OIER_E1; + spin_unlock_irq(&sa1100_rtc_lock); + return 0; + case RTC_PIE_ON: + if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE)) + return -EACCES; + spin_lock_irq(&sa1100_rtc_lock); + OSMR1 = TIMER_FREQ/rtc_freq + OSCR; + OIER |= OIER_E1; + rtc_timer1_count = 1; + spin_unlock_irq(&sa1100_rtc_lock); + return 0; + case RTC_IRQP_READ: + return put_user(rtc_freq, (unsigned long *)arg); + case RTC_IRQP_SET: + if (arg < 1 || arg > TIMER_FREQ) + return -EINVAL; + if ((arg > 64) && (!capable(CAP_SYS_RESOURCE))) + return -EACCES; + rtc_freq = arg; + return 0; + } + return -EINVAL; +} + +static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + rtc_time_to_tm(RCNR, tm); + return 0; +} + +static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + unsigned long time; + int ret; + + ret = rtc_tm_to_time(tm, &time); + if (ret == 0) + RCNR = time; + return ret; +} + +static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); + alrm->pending = RTSR & RTSR_AL ? 1 : 0; + return 0; +} + +static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + int ret; + + spin_lock_irq(&sa1100_rtc_lock); + ret = rtc_update_alarm(&alrm->time); + if (ret == 0) { + memcpy(&rtc_alarm, &alrm->time, sizeof(struct rtc_time)); + + if (alrm->enabled) + enable_irq_wake(IRQ_RTCAlrm); + else + disable_irq_wake(IRQ_RTCAlrm); + } + spin_unlock_irq(&sa1100_rtc_lock); + + return ret; +} + +static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) +{ + seq_printf(seq, "trim/divider\t: 0x%08x\n", RTTR); + seq_printf(seq, "alarm_IRQ\t: %s\n", + (RTSR & RTSR_ALE) ? "yes" : "no" ); + seq_printf(seq, "update_IRQ\t: %s\n", + (RTSR & RTSR_HZE) ? "yes" : "no"); + seq_printf(seq, "periodic_IRQ\t: %s\n", + (OIER & OIER_E1) ? "yes" : "no"); + seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq); + + return 0; +} + +static struct rtc_class_ops sa1100_rtc_ops = { + .open = sa1100_rtc_open, + .read_callback = sa1100_rtc_read_callback, + .release = sa1100_rtc_release, + .ioctl = sa1100_rtc_ioctl, + .read_time = sa1100_rtc_read_time, + .set_time = sa1100_rtc_set_time, + .read_alarm = sa1100_rtc_read_alarm, + .set_alarm = sa1100_rtc_set_alarm, + .proc = sa1100_rtc_proc, +}; + +static int sa1100_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtc; + + /* + * According to the manual we should be able to let RTTR be zero + * and then a default diviser for a 32.768KHz clock is used. + * Apparently this doesn't work, at least for my SA1110 rev 5. + * If the clock divider is uninitialized then reset it to the + * default value to get the 1Hz clock. + */ + if (RTTR == 0) { + RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); + printk(KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n"); + /* The current RTC value probably doesn't make sense either */ + RCNR = 0; + } + + rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, + THIS_MODULE); + + if (IS_ERR(rtc)) { + dev_err(&pdev->dev, "Unable to register the RTC device\n"); + return PTR_ERR(rtc); + } + + platform_set_drvdata(pdev, rtc); + + dev_info(&pdev->dev, "SA11xx/PXA2xx RTC Registered\n"); + + return 0; +} + +static int sa1100_rtc_remove(struct platform_device *pdev) +{ + struct rtc_device *rtc = platform_get_drvdata(pdev); + + if (rtc) + rtc_device_unregister(rtc); + + return 0; +} + +static struct platform_driver sa1100_rtc_driver = { + .probe = sa1100_rtc_probe, + .remove = sa1100_rtc_remove, + .driver = { + .name = "sa1100-rtc", + }, +}; + +static int __init sa1100_rtc_init(void) +{ + return platform_driver_register(&sa1100_rtc_driver); +} + +static void __exit sa1100_rtc_exit(void) +{ + platform_driver_unregister(&sa1100_rtc_driver); +} + +module_init(sa1100_rtc_init); +module_exit(sa1100_rtc_exit); + +MODULE_AUTHOR("Richard Purdie "); +MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 1d98af87270cc08bb8251e004b9dc63cc838f24b Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Mon, 27 Mar 2006 01:16:47 -0800 Subject: [PATCH] RTC subsystem: M48T86 driver Add a driver for the ST M48T86 / Dallas DS12887 RTC. This is a platform driver. The platform device must provide I/O routines to access the RTC. Signed-off-by: Alessandro Zummo Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 10 +++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-m48t86.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/m48t86.h | 16 ++++ 4 files changed, 236 insertions(+) create mode 100644 drivers/rtc/rtc-m48t86.c create mode 100644 include/linux/m48t86.h (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 166232a3f56b..929dd8090578 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -117,6 +117,16 @@ config RTC_DRV_RS5C372 This driver can also be built as a module. If so, the module will be called rtc-rs5c372. +config RTC_DRV_M48T86 + tristate "ST M48T86/Dallas DS12887" + depends on RTC_CLASS + help + If you say Y here you will get support for the + ST M48T86 and Dallas DS12887 RTC chips. + + This driver can also be built as a module. If so, the module + will be called rtc-m48t86. + config RTC_DRV_EP93XX tristate "Cirrus Logic EP93XX" depends on RTC_CLASS && ARCH_EP93XX diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 56820d18161e..8d4c7fe88d58 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -16,5 +16,6 @@ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o +obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c new file mode 100644 index 000000000000..db445c872b1b --- /dev/null +++ b/drivers/rtc/rtc-m48t86.c @@ -0,0 +1,209 @@ +/* + * ST M48T86 / Dallas DS12887 RTC driver + * Copyright (c) 2006 Tower Technologies + * + * Author: Alessandro Zummo + * + * 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 drivers only supports the clock running in BCD and 24H mode. + * If it will be ever adapted to binary and 12H mode, care must be taken + * to not introduce bugs. + */ + +#include +#include +#include +#include +#include + +#define M48T86_REG_SEC 0x00 +#define M48T86_REG_SECALRM 0x01 +#define M48T86_REG_MIN 0x02 +#define M48T86_REG_MINALRM 0x03 +#define M48T86_REG_HOUR 0x04 +#define M48T86_REG_HOURALRM 0x05 +#define M48T86_REG_DOW 0x06 /* 1 = sunday */ +#define M48T86_REG_DOM 0x07 +#define M48T86_REG_MONTH 0x08 /* 1 - 12 */ +#define M48T86_REG_YEAR 0x09 /* 0 - 99 */ +#define M48T86_REG_A 0x0A +#define M48T86_REG_B 0x0B +#define M48T86_REG_C 0x0C +#define M48T86_REG_D 0x0D + +#define M48T86_REG_B_H24 (1 << 1) +#define M48T86_REG_B_DM (1 << 2) +#define M48T86_REG_B_SET (1 << 7) +#define M48T86_REG_D_VRT (1 << 7) + +#define DRV_VERSION "0.1" + + +static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + unsigned char reg; + struct platform_device *pdev = to_platform_device(dev); + struct m48t86_ops *ops = pdev->dev.platform_data; + + reg = ops->readb(M48T86_REG_B); + + if (reg & M48T86_REG_B_DM) { + /* data (binary) mode */ + tm->tm_sec = ops->readb(M48T86_REG_SEC); + tm->tm_min = ops->readb(M48T86_REG_MIN); + tm->tm_hour = ops->readb(M48T86_REG_HOUR) & 0x3F; + tm->tm_mday = ops->readb(M48T86_REG_DOM); + /* tm_mon is 0-11 */ + tm->tm_mon = ops->readb(M48T86_REG_MONTH) - 1; + tm->tm_year = ops->readb(M48T86_REG_YEAR) + 100; + tm->tm_wday = ops->readb(M48T86_REG_DOW); + } else { + /* bcd mode */ + tm->tm_sec = BCD2BIN(ops->readb(M48T86_REG_SEC)); + tm->tm_min = BCD2BIN(ops->readb(M48T86_REG_MIN)); + tm->tm_hour = BCD2BIN(ops->readb(M48T86_REG_HOUR) & 0x3F); + tm->tm_mday = BCD2BIN(ops->readb(M48T86_REG_DOM)); + /* tm_mon is 0-11 */ + tm->tm_mon = BCD2BIN(ops->readb(M48T86_REG_MONTH)) - 1; + tm->tm_year = BCD2BIN(ops->readb(M48T86_REG_YEAR)) + 100; + tm->tm_wday = BCD2BIN(ops->readb(M48T86_REG_DOW)); + } + + /* correct the hour if the clock is in 12h mode */ + if (!(reg & M48T86_REG_B_H24)) + if (ops->readb(M48T86_REG_HOUR) & 0x80) + tm->tm_hour += 12; + + return 0; +} + +static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + unsigned char reg; + struct platform_device *pdev = to_platform_device(dev); + struct m48t86_ops *ops = pdev->dev.platform_data; + + reg = ops->readb(M48T86_REG_B); + + /* update flag and 24h mode */ + reg |= M48T86_REG_B_SET | M48T86_REG_B_H24; + ops->writeb(reg, M48T86_REG_B); + + if (reg & M48T86_REG_B_DM) { + /* data (binary) mode */ + ops->writeb(tm->tm_sec, M48T86_REG_SEC); + ops->writeb(tm->tm_min, M48T86_REG_MIN); + ops->writeb(tm->tm_hour, M48T86_REG_HOUR); + ops->writeb(tm->tm_mday, M48T86_REG_DOM); + ops->writeb(tm->tm_mon + 1, M48T86_REG_MONTH); + ops->writeb(tm->tm_year % 100, M48T86_REG_YEAR); + ops->writeb(tm->tm_wday, M48T86_REG_DOW); + } else { + /* bcd mode */ + ops->writeb(BIN2BCD(tm->tm_sec), M48T86_REG_SEC); + ops->writeb(BIN2BCD(tm->tm_min), M48T86_REG_MIN); + ops->writeb(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR); + ops->writeb(BIN2BCD(tm->tm_mday), M48T86_REG_DOM); + ops->writeb(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH); + ops->writeb(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR); + ops->writeb(BIN2BCD(tm->tm_wday), M48T86_REG_DOW); + } + + /* update ended */ + reg &= ~M48T86_REG_B_SET; + ops->writeb(reg, M48T86_REG_B); + + return 0; +} + +static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq) +{ + unsigned char reg; + struct platform_device *pdev = to_platform_device(dev); + struct m48t86_ops *ops = pdev->dev.platform_data; + + reg = ops->readb(M48T86_REG_B); + + seq_printf(seq, "24hr\t\t: %s\n", + (reg & M48T86_REG_B_H24) ? "yes" : "no"); + + seq_printf(seq, "mode\t\t: %s\n", + (reg & M48T86_REG_B_DM) ? "binary" : "bcd"); + + reg = ops->readb(M48T86_REG_D); + + seq_printf(seq, "battery\t\t: %s\n", + (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted"); + + return 0; +} + +static struct rtc_class_ops m48t86_rtc_ops = { + .read_time = m48t86_rtc_read_time, + .set_time = m48t86_rtc_set_time, + .proc = m48t86_rtc_proc, +}; + +static int __devinit m48t86_rtc_probe(struct platform_device *dev) +{ + unsigned char reg; + struct m48t86_ops *ops = dev->dev.platform_data; + struct rtc_device *rtc = rtc_device_register("m48t86", + &dev->dev, &m48t86_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) { + dev_err(&dev->dev, "unable to register\n"); + return PTR_ERR(rtc); + } + + platform_set_drvdata(dev, rtc); + + /* read battery status */ + reg = ops->readb(M48T86_REG_D); + dev_info(&dev->dev, "battery %s\n", + (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted"); + + return 0; +} + +static int __devexit m48t86_rtc_remove(struct platform_device *dev) +{ + struct rtc_device *rtc = platform_get_drvdata(dev); + + if (rtc) + rtc_device_unregister(rtc); + + platform_set_drvdata(dev, NULL); + + return 0; +} + +static struct platform_driver m48t86_rtc_platform_driver = { + .driver = { + .name = "rtc-m48t86", + .owner = THIS_MODULE, + }, + .probe = m48t86_rtc_probe, + .remove = __devexit_p(m48t86_rtc_remove), +}; + +static int __init m48t86_rtc_init(void) +{ + return platform_driver_register(&m48t86_rtc_platform_driver); +} + +static void __exit m48t86_rtc_exit(void) +{ + platform_driver_unregister(&m48t86_rtc_platform_driver); +} + +MODULE_AUTHOR("Alessandro Zummo "); +MODULE_DESCRIPTION("M48T86 RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(m48t86_rtc_init); +module_exit(m48t86_rtc_exit); diff --git a/include/linux/m48t86.h b/include/linux/m48t86.h new file mode 100644 index 000000000000..9065199319d0 --- /dev/null +++ b/include/linux/m48t86.h @@ -0,0 +1,16 @@ +/* + * ST M48T86 / Dallas DS12887 RTC driver + * Copyright (c) 2006 Tower Technologies + * + * Author: Alessandro Zummo + * + * 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. +*/ + +struct m48t86_ops +{ + void (*writeb)(unsigned char value, unsigned long addr); + unsigned char (*readb)(unsigned long addr); +}; -- cgit v1.2.3-59-g8ed1b From 7597fee389b18e5ed3c8bd58f0012674beb279ed Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 27 Mar 2006 01:17:02 -0800 Subject: [PATCH] pnp: parport: adjust pnp_register_driver signature Remove the assumption that pnp_register_driver() returns the number of devices claimed. parport_pc_init() does nothing with "count", so remove it. Then nobody uses the return value of parport_pc_find_ports(), so make it void. Finally, update pnp_register_driver() usage. Signed-off-by: Bjorn Helgaas Cc: Adam Belay Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/parport/parport_pc.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 9302b8fd7461..d5890027f8af 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -3126,9 +3126,9 @@ parport_pc_find_isa_ports (int autoirq, int autodma) * autoirq is PARPORT_IRQ_NONE, PARPORT_IRQ_AUTO, or PARPORT_IRQ_PROBEONLY * autodma is PARPORT_DMA_NONE or PARPORT_DMA_AUTO */ -static int __init parport_pc_find_ports (int autoirq, int autodma) +static void __init parport_pc_find_ports (int autoirq, int autodma) { - int count = 0, r; + int count = 0, err; #ifdef CONFIG_PARPORT_PC_SUPERIO detect_and_report_winbond (); @@ -3140,23 +3140,17 @@ static int __init parport_pc_find_ports (int autoirq, int autodma) /* PnP ports, skip detection if SuperIO already found them */ if (!count) { - r = pnp_register_driver (&parport_pc_pnp_driver); - if (r >= 0) { + err = pnp_register_driver (&parport_pc_pnp_driver); + if (!err) pnp_registered_parport = 1; - count += r; - } } /* ISA ports and whatever (see asm/parport.h). */ - count += parport_pc_find_nonpci_ports (autoirq, autodma); - - r = pci_register_driver (&parport_pc_pci_driver); - if (r) - return r; - pci_registered_parport = 1; - count += 1; + parport_pc_find_nonpci_ports (autoirq, autodma); - return count; + err = pci_register_driver (&parport_pc_pci_driver); + if (!err) + pci_registered_parport = 1; } /* @@ -3381,8 +3375,6 @@ __setup("parport_init_mode=",parport_init_mode_setup); static int __init parport_pc_init(void) { - int count = 0; - if (parse_parport_params()) return -EINVAL; @@ -3395,12 +3387,11 @@ static int __init parport_pc_init(void) break; if ((io_hi[i]) == PARPORT_IOHI_AUTO) io_hi[i] = 0x400 + io[i]; - if (parport_pc_probe_port(io[i], io_hi[i], - irqval[i], dmaval[i], NULL)) - count++; + parport_pc_probe_port(io[i], io_hi[i], + irqval[i], dmaval[i], NULL); } } else - count += parport_pc_find_ports (irqval[0], dmaval[0]); + parport_pc_find_ports (irqval[0], dmaval[0]); return 0; } -- cgit v1.2.3-59-g8ed1b From 803d0abb3dcfc93701c8a8dc7f2968a47271214c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 27 Mar 2006 01:17:06 -0800 Subject: [PATCH] pnp: IRDA: adjust pnp_register_driver signature Remove the assumption that pnp_register_driver() returns the number of devices claimed. Signed-off-by: Bjorn Helgaas Cc: Adam Belay Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/irda/nsc-ircc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 83141a3ff546..9aa074b44dd3 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -207,7 +207,7 @@ static int __init nsc_ircc_init(void) /* Register with PnP subsystem to detect disable ports */ ret = pnp_register_driver(&nsc_ircc_pnp_driver); - if (ret >= 0) + if (!ret) pnp_registered = 1; ret = -ENODEV; -- cgit v1.2.3-59-g8ed1b From 982c609448b9d724e1c3a0d5aeee388c064479f0 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 27 Mar 2006 01:17:08 -0800 Subject: [PATCH] pnp: PNP: adjust pnp_register_driver signature Remove the assumption that pnp_register_driver() returns the number of devices claimed. Returning the count is unreliable because devices may be hot-plugged in the future. This changes the convention to "zero for success, or a negative error value," which matches pci_register_driver(), acpi_bus_register_driver(), and platform_driver_register(). Signed-off-by: Bjorn Helgaas Cc: Adam Belay Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/pnp.txt | 3 +++ drivers/pnp/card.c | 16 +++++++--------- drivers/pnp/driver.c | 19 +------------------ 3 files changed, 11 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/Documentation/pnp.txt b/Documentation/pnp.txt index af0f6eabfa1c..9529c9c9fd59 100644 --- a/Documentation/pnp.txt +++ b/Documentation/pnp.txt @@ -115,6 +115,9 @@ pnp_unregister_protocol pnp_register_driver - adds a PnP driver to the Plug and Play Layer - this includes driver model integration +- returns zero for success or a negative error number for failure; count + calls to the .add() method if you need to know how many devices bind to + the driver pnp_unregister_driver - removes a PnP driver from the Plug and Play Layer diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index b68eef251614..bb19c64073c6 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -47,7 +47,7 @@ static void card_remove(struct pnp_dev * dev) { dev->card_link = NULL; } - + static void card_remove_first(struct pnp_dev * dev) { struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver); @@ -361,7 +361,7 @@ static int card_resume(struct pnp_dev *dev) int pnp_register_card_driver(struct pnp_card_driver * drv) { - int count; + int error; struct list_head *pos, *temp; drv->link.name = drv->name; @@ -372,21 +372,19 @@ int pnp_register_card_driver(struct pnp_card_driver * drv) drv->link.suspend = drv->suspend ? card_suspend : NULL; drv->link.resume = drv->resume ? card_resume : NULL; - count = pnp_register_driver(&drv->link); - if (count < 0) - return count; + error = pnp_register_driver(&drv->link); + if (error < 0) + return error; spin_lock(&pnp_lock); list_add_tail(&drv->global_list, &pnp_card_drivers); spin_unlock(&pnp_lock); - count = 0; - list_for_each_safe(pos,temp,&pnp_cards){ struct pnp_card *card = list_entry(pos, struct pnp_card, global_list); - count += card_probe(card,drv); + card_probe(card,drv); } - return count; + return 0; } /** diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 7cafacdd12b0..e54c15383193 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -201,31 +201,14 @@ struct bus_type pnp_bus_type = { .resume = pnp_bus_resume, }; - -static int count_devices(struct device * dev, void * c) -{ - int * count = c; - (*count)++; - return 0; -} - int pnp_register_driver(struct pnp_driver *drv) { - int count; - pnp_dbg("the driver '%s' has been registered", drv->name); drv->driver.name = drv->name; drv->driver.bus = &pnp_bus_type; - count = driver_register(&drv->driver); - - /* get the number of initial matches */ - if (count >= 0){ - count = 0; - driver_for_each_device(&drv->driver, NULL, &count, count_devices); - } - return count; + return driver_register(&drv->driver); } void pnp_unregister_driver(struct pnp_driver *drv) -- cgit v1.2.3-59-g8ed1b From 2115aea8185c8987b7688111953322742bd8795c Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 27 Mar 2006 01:17:19 -0800 Subject: [PATCH] vgacon: fix EGA cursor resize function This corrects cursor resize on ega boards: registers are write-only, so we shouldn't even try to read them. And on ega, 31/30 produces a flat cursor. Using 31/31 is better: except with 32 pixels high fonts, it shouldn't show up. Signed-off-by: Samuel Thibault Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/vgacon.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 5a86978537d2..61894d5bb219 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -433,17 +433,22 @@ static void vgacon_set_cursor_size(int xpos, int from, int to) cursor_size_lastto = to; spin_lock_irqsave(&vga_lock, flags); - outb_p(0x0a, vga_video_port_reg); /* Cursor start */ - curs = inb_p(vga_video_port_val); - outb_p(0x0b, vga_video_port_reg); /* Cursor end */ - cure = inb_p(vga_video_port_val); + if (vga_video_type >= VIDEO_TYPE_VGAC) { + outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg); + curs = inb_p(vga_video_port_val); + outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg); + cure = inb_p(vga_video_port_val); + } else { + curs = 0; + cure = 0; + } curs = (curs & 0xc0) | from; cure = (cure & 0xe0) | to; - outb_p(0x0a, vga_video_port_reg); /* Cursor start */ + outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg); outb_p(curs, vga_video_port_val); - outb_p(0x0b, vga_video_port_reg); /* Cursor end */ + outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg); outb_p(cure, vga_video_port_val); spin_unlock_irqrestore(&vga_lock, flags); } @@ -455,7 +460,10 @@ static void vgacon_cursor(struct vc_data *c, int mode) switch (mode) { case CM_ERASE: write_vga(14, (c->vc_pos - vga_vram_base) / 2); - vgacon_set_cursor_size(c->vc_x, 31, 30); + if (vga_video_type >= VIDEO_TYPE_VGAC) + vgacon_set_cursor_size(c->vc_x, 31, 30); + else + vgacon_set_cursor_size(c->vc_x, 31, 31); break; case CM_MOVE: @@ -493,7 +501,10 @@ static void vgacon_cursor(struct vc_data *c, int mode) 10 ? 1 : 2)); break; case CUR_NONE: - vgacon_set_cursor_size(c->vc_x, 31, 30); + if (vga_video_type >= VIDEO_TYPE_VGAC) + vgacon_set_cursor_size(c->vc_x, 31, 30); + else + vgacon_set_cursor_size(c->vc_x, 31, 31); break; default: vgacon_set_cursor_size(c->vc_x, 1, -- cgit v1.2.3-59-g8ed1b From 15bdab959c9bb909c0317480dd9b35748a8f7887 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 27 Mar 2006 01:17:20 -0800 Subject: [PATCH] vgacon: Add support for soft scrollback The scrollback buffer of the VGA console is located in VGA RAM. This RAM is fixed in size and is very small. To make the scrollback buffer larger, it must be placed instead in System RAM. This patch adds this feature. The feature and the size of the buffer are made as a kernel config option. Besides consuming kernel memory, this feature will slow down the console by approximately 20%. Signed-off-by: Antonino Daplas Signed-off-by: Jiri Slaby Cc: Jindrich Makovicka Cc: Martin Mares Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/Kconfig | 24 ++++ drivers/video/console/vgacon.c | 244 +++++++++++++++++++++++++++++++++-------- 2 files changed, 225 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 6ee449858a5c..4444bef68fba 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -26,6 +26,30 @@ config VGA_CONSOLE # fi # fi +config VGACON_SOFT_SCROLLBACK + bool "Enable Scrollback Buffer in System RAM" + depends on VGA_CONSOLE + default n + help + The scrollback buffer of the standard VGA console is located in + the VGA RAM. The size of this RAM is fixed and is quite small. + If you require a larger scrollback buffer, this can be placed in + System RAM which is dynamically allocated during intialization. + Placing the scrollback buffer in System RAM will slightly slow + down the console. + + If you want this feature, say 'Y' here and enter the amount of + RAM to allocate for this buffer. If unsure, say 'N'. + +config VGACON_SOFT_SCROLLBACK_SIZE + int "Scrollback Buffer Size (in KB)" + depends on VGACON_SOFT_SCROLLBACK + default "64" + help + Enter the amount of System RAM to allocate for the scrollback + buffer. Each 64KB will give you approximately 16 80x25 + screenfuls of scrollback buffer + config VIDEO_SELECT bool "Video mode selection support" depends on X86 && VGA_CONSOLE diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 61894d5bb219..d5a04b68c4d4 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -93,7 +93,6 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, static void vgacon_invert_region(struct vc_data *c, u16 * p, int count); static unsigned long vgacon_uni_pagedir[2]; - /* Description of the hardware situation */ static unsigned long vga_vram_base; /* Base of video memory */ static unsigned long vga_vram_end; /* End of video memory */ @@ -161,6 +160,201 @@ static inline void write_vga(unsigned char reg, unsigned int val) spin_unlock_irqrestore(&vga_lock, flags); } +static inline void vga_set_mem_top(struct vc_data *c) +{ + write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2); +} + +#ifdef CONFIG_VGACON_SOFT_SCROLLBACK +#include +/* software scrollback */ +static void *vgacon_scrollback; +static int vgacon_scrollback_tail; +static int vgacon_scrollback_size; +static int vgacon_scrollback_rows; +static int vgacon_scrollback_cnt; +static int vgacon_scrollback_cur; +static int vgacon_scrollback_save; +static int vgacon_scrollback_restore; + +static void vgacon_scrollback_init(int pitch) +{ + int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch; + + if (vgacon_scrollback) { + vgacon_scrollback_cnt = 0; + vgacon_scrollback_tail = 0; + vgacon_scrollback_cur = 0; + vgacon_scrollback_rows = rows - 1; + vgacon_scrollback_size = rows * pitch; + } +} + +static void __init vgacon_scrollback_startup(void) +{ + vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE + * 1024); + vgacon_scrollback_init(vga_video_num_columns * 2); +} + +static void vgacon_scrollback_update(struct vc_data *c, int t, int count) +{ + void *p; + + if (!vgacon_scrollback_size || c->vc_num != fg_console) + return; + + p = (void *) (c->vc_origin + t * c->vc_size_row); + + while (count--) { + scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail, + p, c->vc_size_row); + vgacon_scrollback_cnt++; + p += c->vc_size_row; + vgacon_scrollback_tail += c->vc_size_row; + + if (vgacon_scrollback_tail >= vgacon_scrollback_size) + vgacon_scrollback_tail = 0; + + if (vgacon_scrollback_cnt > vgacon_scrollback_rows) + vgacon_scrollback_cnt = vgacon_scrollback_rows; + + vgacon_scrollback_cur = vgacon_scrollback_cnt; + } +} + +static void vgacon_restore_screen(struct vc_data *c) +{ + vgacon_scrollback_save = 0; + + if (!vga_is_gfx && !vgacon_scrollback_restore) { + scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, + c->vc_screenbuf_size > vga_vram_size ? + vga_vram_size : c->vc_screenbuf_size); + vgacon_scrollback_restore = 1; + vgacon_scrollback_cur = vgacon_scrollback_cnt; + } +} + +static int vgacon_scrolldelta(struct vc_data *c, int lines) +{ + int start, end, count, soff, diff; + void *d, *s; + + if (!lines) { + c->vc_visible_origin = c->vc_origin; + vga_set_mem_top(c); + return 1; + } + + if (!vgacon_scrollback) + return 1; + + if (!vgacon_scrollback_save) { + vgacon_cursor(c, CM_ERASE); + vgacon_save_screen(c); + vgacon_scrollback_save = 1; + } + + vgacon_scrollback_restore = 0; + start = vgacon_scrollback_cur + lines; + end = start + abs(lines); + + if (start < 0) + start = 0; + + if (start > vgacon_scrollback_cnt) + start = vgacon_scrollback_cnt; + + if (end < 0) + end = 0; + + if (end > vgacon_scrollback_cnt) + end = vgacon_scrollback_cnt; + + vgacon_scrollback_cur = start; + count = end - start; + soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) * + c->vc_size_row); + soff -= count * c->vc_size_row; + + if (soff < 0) + soff += vgacon_scrollback_size; + + count = vgacon_scrollback_cnt - start; + + if (count > c->vc_rows) + count = c->vc_rows; + + diff = c->vc_rows - count; + + d = (void *) c->vc_origin; + s = (void *) c->vc_screenbuf; + + while (count--) { + scr_memcpyw(d, vgacon_scrollback + soff, c->vc_size_row); + d += c->vc_size_row; + soff += c->vc_size_row; + + if (soff >= vgacon_scrollback_size) + soff = 0; + } + + if (diff == c->vc_rows) { + vgacon_cursor(c, CM_MOVE); + } else { + while (diff--) { + scr_memcpyw(d, s, c->vc_size_row); + d += c->vc_size_row; + s += c->vc_size_row; + } + } + + return 1; +} +#else +#define vgacon_scrollback_startup(...) do { } while (0) +#define vgacon_scrollback_init(...) do { } while (0) +#define vgacon_scrollback_update(...) do { } while (0) + +static void vgacon_restore_screen(struct vc_data *c) +{ + if (c->vc_origin != c->vc_visible_origin) + vgacon_scrolldelta(c, 0); +} + +static int vgacon_scrolldelta(struct vc_data *c, int lines) +{ + if (!lines) /* Turn scrollback off */ + c->vc_visible_origin = c->vc_origin; + else { + int margin = c->vc_size_row * 4; + int ul, we, p, st; + + if (vga_rolled_over > + (c->vc_scr_end - vga_vram_base) + margin) { + ul = c->vc_scr_end - vga_vram_base; + we = vga_rolled_over + c->vc_size_row; + } else { + ul = 0; + we = vga_vram_size; + } + p = (c->vc_visible_origin - vga_vram_base - ul + we) % we + + lines * c->vc_size_row; + st = (c->vc_origin - vga_vram_base - ul + we) % we; + if (st < 2 * margin) + margin = 0; + if (p < margin) + p = 0; + if (p > st - margin) + p = st; + c->vc_visible_origin = vga_vram_base + (p + ul) % we; + } + vga_set_mem_top(c); + return 1; +} +#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */ + static const char __init *vgacon_startup(void) { const char *display_desc = NULL; @@ -330,7 +524,7 @@ static const char __init *vgacon_startup(void) vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH; vgacon_yres = vga_scan_lines; - + vgacon_scrollback_startup(); return display_desc; } @@ -357,11 +551,6 @@ static void vgacon_init(struct vc_data *c, int init) con_set_default_unimap(c); } -static inline void vga_set_mem_top(struct vc_data *c) -{ - write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2); -} - static void vgacon_deinit(struct vc_data *c) { /* When closing the last console, reset video origin */ @@ -455,8 +644,8 @@ static void vgacon_set_cursor_size(int xpos, int from, int to) static void vgacon_cursor(struct vc_data *c, int mode) { - if (c->vc_origin != c->vc_visible_origin) - vgacon_scrolldelta(c, 0); + vgacon_restore_screen(c); + switch (mode) { case CM_ERASE: write_vga(14, (c->vc_pos - vga_vram_base) / 2); @@ -606,6 +795,7 @@ static int vgacon_switch(struct vc_data *c) vgacon_doresize(c, c->vc_cols, c->vc_rows); } + vgacon_scrollback_init(c->vc_size_row); return 0; /* Redrawing not needed */ } @@ -1073,37 +1263,6 @@ static int vgacon_resize(struct vc_data *c, unsigned int width, return 0; } -static int vgacon_scrolldelta(struct vc_data *c, int lines) -{ - if (!lines) /* Turn scrollback off */ - c->vc_visible_origin = c->vc_origin; - else { - int margin = c->vc_size_row * 4; - int ul, we, p, st; - - if (vga_rolled_over > - (c->vc_scr_end - vga_vram_base) + margin) { - ul = c->vc_scr_end - vga_vram_base; - we = vga_rolled_over + c->vc_size_row; - } else { - ul = 0; - we = vga_vram_size; - } - p = (c->vc_visible_origin - vga_vram_base - ul + we) % we + - lines * c->vc_size_row; - st = (c->vc_origin - vga_vram_base - ul + we) % we; - if (st < 2 * margin) - margin = 0; - if (p < margin) - p = 0; - if (p > st - margin) - p = st; - c->vc_visible_origin = vga_vram_base + (p + ul) % we; - } - vga_set_mem_top(c); - return 1; -} - static int vgacon_set_origin(struct vc_data *c) { if (vga_is_gfx || /* We don't play origin tricks in graphic modes */ @@ -1146,15 +1305,14 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, if (t || b != c->vc_rows || vga_is_gfx) return 0; - if (c->vc_origin != c->vc_visible_origin) - vgacon_scrolldelta(c, 0); - if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2) return 0; + vgacon_restore_screen(c); oldo = c->vc_origin; delta = lines * c->vc_size_row; if (dir == SM_UP) { + vgacon_scrollback_update(c, t, lines); if (c->vc_scr_end + delta >= vga_vram_end) { scr_memcpyw((u16 *) vga_vram_base, (u16 *) (oldo + delta), -- cgit v1.2.3-59-g8ed1b From 7a07cd786dbd0111b9dd977e114438220cb4eee5 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 27 Mar 2006 01:17:22 -0800 Subject: [PATCH] nvidiafb: add suspend and resume hooks Add suspend and resume hooks to make software suspend more reliable. Resuming from standby should generally work. Resuming from mem and from disk requires that the GPU is disabled. Adding these to the suspend script... fbset -accel false -a /* suspend here */ fbset -accel true -a ... should generally work. In addition, resuming from mem requires that the video card has to be POSTed by the BIOS or some other utility. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nv_accel.c | 12 +++++ drivers/video/nvidia/nv_type.h | 1 + drivers/video/nvidia/nvidia.c | 115 +++++++++++++++++++++++++++++----------- 3 files changed, 97 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c index f377a29ec97a..4aefb8f41637 100644 --- a/drivers/video/nvidia/nv_accel.c +++ b/drivers/video/nvidia/nv_accel.c @@ -300,6 +300,9 @@ int nvidiafb_sync(struct fb_info *info) { struct nvidia_par *par = info->par; + if (info->state != FBINFO_STATE_RUNNING) + return 0; + if (!par->lockup) NVFlush(par); @@ -313,6 +316,9 @@ void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region) { struct nvidia_par *par = info->par; + if (info->state != FBINFO_STATE_RUNNING) + return; + if (par->lockup) return cfb_copyarea(info, region); @@ -329,6 +335,9 @@ void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) struct nvidia_par *par = info->par; u32 color; + if (info->state != FBINFO_STATE_RUNNING) + return; + if (par->lockup) return cfb_fillrect(info, rect); @@ -412,6 +421,9 @@ void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image) { struct nvidia_par *par = info->par; + if (info->state != FBINFO_STATE_RUNNING) + return; + if (image->depth == 1 && !par->lockup) nvidiafb_mono_color_expand(info, image); else diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h index e4a5b1da71c4..acdc26693402 100644 --- a/drivers/video/nvidia/nv_type.h +++ b/drivers/video/nvidia/nv_type.h @@ -129,6 +129,7 @@ struct nvidia_par { int fpHeight; int PanelTweak; int paneltweak; + int pm_state; u32 crtcSync_read; u32 fpSyncs; u32 dmaPut; diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index a7c4e5e8ead6..c758b386f146 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef CONFIG_MTRR #include #endif @@ -615,6 +616,30 @@ static int nvidia_panel_tweak(struct nvidia_par *par, return tweak; } +static void nvidia_vga_protect(struct nvidia_par *par, int on) +{ + unsigned char tmp; + + if (on) { + /* + * Turn off screen and disable sequencer. + */ + tmp = NVReadSeq(par, 0x01); + + NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */ + NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */ + } else { + /* + * Reenable sequencer, then turn on screen. + */ + + tmp = NVReadSeq(par, 0x01); + + NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */ + NVWriteSeq(par, 0x00, 0x03); /* End Reset */ + } +} + static void nvidia_save_vga(struct nvidia_par *par, struct _riva_hw_state *state) { @@ -643,9 +668,9 @@ static void nvidia_save_vga(struct nvidia_par *par, #undef DUMP_REG -static void nvidia_write_regs(struct nvidia_par *par) +static void nvidia_write_regs(struct nvidia_par *par, + struct _riva_hw_state *state) { - struct _riva_hw_state *state = &par->ModeReg; int i; NVTRACE_ENTER(); @@ -694,32 +719,6 @@ static void nvidia_write_regs(struct nvidia_par *par) NVTRACE_LEAVE(); } -static void nvidia_vga_protect(struct nvidia_par *par, int on) -{ - unsigned char tmp; - - if (on) { - /* - * Turn off screen and disable sequencer. - */ - tmp = NVReadSeq(par, 0x01); - - NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */ - NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */ - } else { - /* - * Reenable sequencer, then turn on screen. - */ - - tmp = NVReadSeq(par, 0x01); - - NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */ - NVWriteSeq(par, 0x00, 0x03); /* End Reset */ - } -} - - - static int nvidia_calc_regs(struct fb_info *info) { struct nvidia_par *par = info->par; @@ -1068,7 +1067,8 @@ static int nvidiafb_set_par(struct fb_info *info) nvidia_vga_protect(par, 1); - nvidia_write_regs(par); + nvidia_write_regs(par, &par->ModeReg); + NVSetStartAddress(par, 0); #if defined (__BIG_ENDIAN) /* turn on LFB swapping */ @@ -1377,6 +1377,57 @@ static struct fb_ops nvidia_fb_ops = { .fb_sync = nvidiafb_sync, }; +#ifdef CONFIG_PM +static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t state) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct nvidia_par *par = info->par; + + acquire_console_sem(); + par->pm_state = state.event; + + if (state.event == PM_EVENT_FREEZE) { + dev->dev.power.power_state = state; + } else { + fb_set_suspend(info, 1); + nvidiafb_blank(FB_BLANK_POWERDOWN, info); + nvidia_write_regs(par, &par->SavedReg); + pci_save_state(dev); + pci_disable_device(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); + } + + release_console_sem(); + return 0; +} + +static int nvidiafb_resume(struct pci_dev *dev) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct nvidia_par *par = info->par; + + acquire_console_sem(); + pci_set_power_state(dev, PCI_D0); + + if (par->pm_state != PM_EVENT_FREEZE) { + pci_restore_state(dev); + pci_enable_device(dev); + pci_set_master(dev); + } + + par->pm_state = PM_EVENT_ON; + nvidiafb_set_par(info); + fb_set_suspend (info, 0); + nvidiafb_blank(FB_BLANK_UNBLANK, info); + + release_console_sem(); + return 0; +} +#else +#define nvidiafb_suspend NULL +#define nvidiafb_resume NULL +#endif + static int __devinit nvidia_set_fbinfo(struct fb_info *info) { struct fb_monspecs *specs = &info->monspecs; @@ -1798,8 +1849,10 @@ static int __devinit nvidiafb_setup(char *options) static struct pci_driver nvidiafb_driver = { .name = "nvidiafb", .id_table = nvidiafb_pci_tbl, - .probe = nvidiafb_probe, - .remove = __exit_p(nvidiafb_remove), + .probe = nvidiafb_probe, + .suspend = nvidiafb_suspend, + .resume = nvidiafb_resume, + .remove = __exit_p(nvidiafb_remove), }; /* ------------------------------------------------------------------------- * -- cgit v1.2.3-59-g8ed1b From fc4effc7a98d0d320e478d1d42bc4a8a64380150 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Mon, 27 Mar 2006 01:17:23 -0800 Subject: [PATCH] fbdev: framebuffer driver for Geode GX A framebuffer driver for the display controller in AMD Geode GX processors (Geode GX533, Geode GX500 etc.). Tested at 640x480, 800x600, 1024x768 and 1280x1024 at 8, 16, and 24 bpp with both CRT and TFT. No accelerated features currently implemented and compression remains disabled. This driver requires that the BIOS (or the SoftVG/Firmbase code in the BIOS) has created an appropriate virtual PCI header. Signed-off-by: David Vrabel Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/geode/Kconfig | 17 +- drivers/video/geode/Makefile | 4 +- drivers/video/geode/display_gx.c | 156 +++++++++++++++ drivers/video/geode/display_gx.h | 96 +++++++++ drivers/video/geode/gxfb_core.c | 423 +++++++++++++++++++++++++++++++++++++++ drivers/video/geode/video_gx.c | 262 ++++++++++++++++++++++++ drivers/video/geode/video_gx.h | 47 +++++ 7 files changed, 1003 insertions(+), 2 deletions(-) create mode 100644 drivers/video/geode/display_gx.c create mode 100644 drivers/video/geode/display_gx.h create mode 100644 drivers/video/geode/gxfb_core.c create mode 100644 drivers/video/geode/video_gx.c create mode 100644 drivers/video/geode/video_gx.h (limited to 'drivers') diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index 42fb9a89a792..4e173ef20a7d 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig @@ -8,9 +8,24 @@ config FB_GEODE Say 'Y' here to allow you to select framebuffer drivers for the AMD Geode family of processors. +config FB_GEODE_GX + tristate "AMD Geode GX framebuffer support (EXPERIMENTAL)" + depends on FB && FB_GEODE && EXPERIMENTAL + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Framebuffer driver for the display controller integrated into the + AMD Geode GX processors. + + To compile this driver as a module, choose M here: the module will be + called gxfb. + + If unsure, say N. + config FB_GEODE_GX1 tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)" - depends on FB_GEODE && EXPERIMENTAL + depends on FB && FB_GEODE && EXPERIMENTAL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile index 13ad501ea990..f896565bc312 100644 --- a/drivers/video/geode/Makefile +++ b/drivers/video/geode/Makefile @@ -1,5 +1,7 @@ # Makefile for the Geode family framebuffer drivers obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o +obj-$(CONFIG_FB_GEODE_GX) += gxfb.o -gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o +gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o +gxfb-objs := gxfb_core.o display_gx.o video_gx.o diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c new file mode 100644 index 000000000000..825c3405f5c2 --- /dev/null +++ b/drivers/video/geode/display_gx.c @@ -0,0 +1,156 @@ +/* + * Geode GX display controller. + * + * Copyright (C) 2005 Arcom Control Systems Ltd. + * + * Portions from AMD's original 2.4 driver: + * Copyright (C) 2004 Advanced Micro Devices, 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 "geodefb.h" +#include "display_gx.h" + +int gx_frame_buffer_size(void) +{ + /* Assuming 16 MiB. */ + return 16*1024*1024; +} + +int gx_line_delta(int xres, int bpp) +{ + /* Must be a multiple of 8 bytes. */ + return (xres * (bpp >> 3) + 7) & ~0x7; +} + +static void gx_set_mode(struct fb_info *info) +{ + struct geodefb_par *par = info->par; + u32 gcfg, dcfg; + int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal; + int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; + + /* Unlock the display controller registers. */ + readl(par->dc_regs + DC_UNLOCK); + writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK); + + gcfg = readl(par->dc_regs + DC_GENERAL_CFG); + dcfg = readl(par->dc_regs + DC_DISPLAY_CFG); + + /* Disable the timing generator. */ + dcfg &= ~(DC_DCFG_TGEN); + writel(dcfg, par->dc_regs + DC_DISPLAY_CFG); + + /* Wait for pending memory requests before disabling the FIFO load. */ + udelay(100); + + /* Disable FIFO load and compression. */ + gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE); + writel(gcfg, par->dc_regs + DC_GENERAL_CFG); + + /* Setup DCLK and its divisor. */ + par->vid_ops->set_dclk(info); + + /* + * Setup new mode. + */ + + /* Clear all unused feature bits. */ + gcfg &= DC_GCFG_YUVM | DC_GCFG_VDSE; + dcfg = 0; + + /* Set FIFO priority (default 6/5) and enable. */ + /* FIXME: increase fifo priority for 1280x1024 and higher modes? */ + gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE; + + /* Framebuffer start offset. */ + writel(0, par->dc_regs + DC_FB_ST_OFFSET); + + /* Line delta and line buffer length. */ + writel(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH); + writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2, + par->dc_regs + DC_LINE_SIZE); + + /* Enable graphics and video data and unmask address lines. */ + dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M; + + /* Set pixel format. */ + switch (info->var.bits_per_pixel) { + case 8: + dcfg |= DC_DCFG_DISP_MODE_8BPP; + break; + case 16: + dcfg |= DC_DCFG_DISP_MODE_16BPP; + dcfg |= DC_DCFG_16BPP_MODE_565; + break; + case 32: + dcfg |= DC_DCFG_DISP_MODE_24BPP; + dcfg |= DC_DCFG_PALB; + break; + } + + /* Enable timing generator. */ + dcfg |= DC_DCFG_TGEN; + + /* Horizontal and vertical timings. */ + hactive = info->var.xres; + hblankstart = hactive; + hsyncstart = hblankstart + info->var.right_margin; + hsyncend = hsyncstart + info->var.hsync_len; + hblankend = hsyncend + info->var.left_margin; + htotal = hblankend; + + vactive = info->var.yres; + vblankstart = vactive; + vsyncstart = vblankstart + info->var.lower_margin; + vsyncend = vsyncstart + info->var.vsync_len; + vblankend = vsyncend + info->var.upper_margin; + vtotal = vblankend; + + writel((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING); + writel((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING); + writel((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING); + + writel((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING); + writel((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING); + writel((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING); + + /* Write final register values. */ + writel(dcfg, par->dc_regs + DC_DISPLAY_CFG); + writel(gcfg, par->dc_regs + DC_GENERAL_CFG); + + par->vid_ops->configure_display(info); + + /* Relock display controller registers */ + writel(0, par->dc_regs + DC_UNLOCK); +} + +static void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno, + unsigned red, unsigned green, unsigned blue) +{ + struct geodefb_par *par = info->par; + int val; + + /* Hardware palette is in RGB 8-8-8 format. */ + val = (red << 8) & 0xff0000; + val |= (green) & 0x00ff00; + val |= (blue >> 8) & 0x0000ff; + + writel(regno, par->dc_regs + DC_PAL_ADDRESS); + writel(val, par->dc_regs + DC_PAL_DATA); +} + +struct geode_dc_ops gx_dc_ops = { + .set_mode = gx_set_mode, + .set_palette_reg = gx_set_hw_palette_reg, +}; diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h new file mode 100644 index 000000000000..86c623361305 --- /dev/null +++ b/drivers/video/geode/display_gx.h @@ -0,0 +1,96 @@ +/* + * Geode GX display controller + * + * Copyright (C) 2006 Arcom Control Systems Ltd. + * + * 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 __DISPLAY_GX_H__ +#define __DISPLAY_GX_H__ + +int gx_frame_buffer_size(void); +int gx_line_delta(int xres, int bpp); + +extern struct geode_dc_ops gx_dc_ops; + +/* Display controller registers */ + +#define DC_UNLOCK 0x00 +# define DC_UNLOCK_CODE 0x00004758 + +#define DC_GENERAL_CFG 0x04 +# define DC_GCFG_DFLE 0x00000001 +# define DC_GCFG_CURE 0x00000002 +# define DC_GCFG_ICNE 0x00000004 +# define DC_GCFG_VIDE 0x00000008 +# define DC_GCFG_CMPE 0x00000020 +# define DC_GCFG_DECE 0x00000040 +# define DC_GCFG_VGAE 0x00000080 +# define DC_GCFG_DFHPSL_MASK 0x00000F00 +# define DC_GCFG_DFHPSL_POS 8 +# define DC_GCFG_DFHPEL_MASK 0x0000F000 +# define DC_GCFG_DFHPEL_POS 12 +# define DC_GCFG_STFM 0x00010000 +# define DC_GCFG_FDTY 0x00020000 +# define DC_GCFG_VGAFT 0x00040000 +# define DC_GCFG_VDSE 0x00080000 +# define DC_GCFG_YUVM 0x00100000 +# define DC_GCFG_VFSL 0x00800000 +# define DC_GCFG_SIGE 0x01000000 +# define DC_GCFG_SGRE 0x02000000 +# define DC_GCFG_SGFR 0x04000000 +# define DC_GCFG_CRC_MODE 0x08000000 +# define DC_GCFG_DIAG 0x10000000 +# define DC_GCFG_CFRW 0x20000000 + +#define DC_DISPLAY_CFG 0x08 +# define DC_DCFG_TGEN 0x00000001 +# define DC_DCFG_GDEN 0x00000008 +# define DC_DCFG_VDEN 0x00000010 +# define DC_DCFG_TRUP 0x00000040 +# define DC_DCFG_DISP_MODE_MASK 0x00000300 +# define DC_DCFG_DISP_MODE_8BPP 0x00000000 +# define DC_DCFG_DISP_MODE_16BPP 0x00000100 +# define DC_DCFG_DISP_MODE_24BPP 0x00000200 +# define DC_DCFG_16BPP_MODE_MASK 0x00000c00 +# define DC_DCFG_16BPP_MODE_565 0x00000000 +# define DC_DCFG_16BPP_MODE_555 0x00000100 +# define DC_DCFG_16BPP_MODE_444 0x00000200 +# define DC_DCFG_DCEN 0x00080000 +# define DC_DCFG_PALB 0x02000000 +# define DC_DCFG_FRLK 0x04000000 +# define DC_DCFG_VISL 0x08000000 +# define DC_DCFG_FRSL 0x20000000 +# define DC_DCFG_A18M 0x40000000 +# define DC_DCFG_A20M 0x80000000 + +#define DC_FB_ST_OFFSET 0x10 + +#define DC_LINE_SIZE 0x30 +# define DC_LINE_SIZE_FB_LINE_SIZE_MASK 0x000007ff +# define DC_LINE_SIZE_FB_LINE_SIZE_POS 0 +# define DC_LINE_SIZE_CB_LINE_SIZE_MASK 0x007f0000 +# define DC_LINE_SIZE_CB_LINE_SIZE_POS 16 +# define DC_LINE_SIZE_VID_LINE_SIZE_MASK 0xff000000 +# define DC_LINE_SIZE_VID_LINE_SIZE_POS 24 + +#define DC_GFX_PITCH 0x34 +# define DC_GFX_PITCH_FB_PITCH_MASK 0x0000ffff +# define DC_GFX_PITCH_FB_PITCH_POS 0 +# define DC_GFX_PITCH_CB_PITCH_MASK 0xffff0000 +# define DC_GFX_PITCH_CB_PITCH_POS 16 + +#define DC_H_ACTIVE_TIMING 0x40 +#define DC_H_BLANK_TIMING 0x44 +#define DC_H_SYNC_TIMING 0x48 +#define DC_V_ACTIVE_TIMING 0x50 +#define DC_V_BLANK_TIMING 0x54 +#define DC_V_SYNC_TIMING 0x58 + +#define DC_PAL_ADDRESS 0x70 +#define DC_PAL_DATA 0x74 + +#endif /* !__DISPLAY_GX1_H__ */ diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c new file mode 100644 index 000000000000..89c34b15f5d4 --- /dev/null +++ b/drivers/video/geode/gxfb_core.c @@ -0,0 +1,423 @@ +/* + * Geode GX framebuffer driver. + * + * Copyright (C) 2006 Arcom Control Systems Ltd. + * + * 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 driver assumes that the BIOS has created a virtual PCI device header + * for the video device. The PCI header is assumed to contain the following + * BARs: + * + * BAR0 - framebuffer memory + * BAR1 - graphics processor registers + * BAR2 - display controller registers + * BAR3 - video processor and flat panel control registers. + * + * 16 MiB of framebuffer memory is assumed to be available. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "geodefb.h" +#include "display_gx.h" +#include "video_gx.h" + +static char mode_option[32] = "640x480-16@60"; + +/* Modes relevant to the GX (taken from modedb.c) */ +static const struct fb_videomode __initdata gx_modedb[] = { + /* 640x480-60 VESA */ + { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 640x480-75 VESA */ + { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 640x480-85 VESA */ + { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 800x600-60 VESA */ + { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 800x600-75 VESA */ + { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 800x600-85 VESA */ + { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1024x768-60 VESA */ + { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1024x768-75 VESA */ + { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1024x768-85 VESA */ + { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1280x960-60 VESA */ + { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1280x960-85 VESA */ + { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1280x1024-60 VESA */ + { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1280x1024-75 VESA */ + { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1280x1024-85 VESA */ + { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1600x1200-60 VESA */ + { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1600x1200-75 VESA */ + { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + /* 1600x1200-85 VESA */ + { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, +}; + +static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + if (var->xres > 1600 || var->yres > 1200) + return -EINVAL; + if ((var->xres > 1280 || var->yres > 1024) && var->bits_per_pixel > 16) + return -EINVAL; + + if (var->bits_per_pixel == 32) { + var->red.offset = 16; var->red.length = 8; + var->green.offset = 8; var->green.length = 8; + var->blue.offset = 0; var->blue.length = 8; + } else if (var->bits_per_pixel == 16) { + var->red.offset = 11; var->red.length = 5; + var->green.offset = 5; var->green.length = 6; + var->blue.offset = 0; var->blue.length = 5; + } else if (var->bits_per_pixel == 8) { + var->red.offset = 0; var->red.length = 8; + var->green.offset = 0; var->green.length = 8; + var->blue.offset = 0; var->blue.length = 8; + } else + return -EINVAL; + var->transp.offset = 0; var->transp.length = 0; + + /* Enough video memory? */ + if (gx_line_delta(var->xres, var->bits_per_pixel) * var->yres > info->fix.smem_len) + return -EINVAL; + + /* FIXME: Check timing parameters here? */ + + return 0; +} + +static int gxfb_set_par(struct fb_info *info) +{ + struct geodefb_par *par = info->par; + + if (info->var.bits_per_pixel > 8) { + info->fix.visual = FB_VISUAL_TRUECOLOR; + fb_dealloc_cmap(&info->cmap); + } else { + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + fb_alloc_cmap(&info->cmap, 1<var.bits_per_pixel, 0); + } + + info->fix.line_length = gx_line_delta(info->var.xres, info->var.bits_per_pixel); + + par->dc_ops->set_mode(info); + + return 0; +} + +static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + struct geodefb_par *par = info->par; + + if (info->var.grayscale) { + /* grayscale = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; + } + + /* Truecolor has hardware independent palette */ + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 *pal = info->pseudo_palette; + u32 v; + + if (regno >= 16) + return -EINVAL; + + v = chan_to_field(red, &info->var.red); + v |= chan_to_field(green, &info->var.green); + v |= chan_to_field(blue, &info->var.blue); + + pal[regno] = v; + } else { + if (regno >= 256) + return -EINVAL; + + par->dc_ops->set_palette_reg(info, regno, red, green, blue); + } + + return 0; +} + +static int gxfb_blank(int blank_mode, struct fb_info *info) +{ + struct geodefb_par *par = info->par; + + return par->vid_ops->blank_display(info, blank_mode); +} + +static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev) +{ + struct geodefb_par *par = info->par; + int fb_len; + int ret; + + ret = pci_enable_device(dev); + if (ret < 0) + return ret; + + ret = pci_request_region(dev, 3, "gxfb (video processor)"); + if (ret < 0) + return ret; + par->vid_regs = ioremap(pci_resource_start(dev, 3), + pci_resource_len(dev, 3)); + if (!par->vid_regs) + return -ENOMEM; + + ret = pci_request_region(dev, 2, "gxfb (display controller)"); + if (ret < 0) + return ret; + par->dc_regs = ioremap(pci_resource_start(dev, 2), pci_resource_len(dev, 2)); + if (!par->dc_regs) + return -ENOMEM; + + ret = pci_request_region(dev, 0, "gxfb (framebuffer)"); + if (ret < 0) + return ret; + if ((fb_len = gx_frame_buffer_size()) < 0) + return -ENOMEM; + info->fix.smem_start = pci_resource_start(dev, 0); + info->fix.smem_len = fb_len; + info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); + if (!info->screen_base) + return -ENOMEM; + + dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n", + info->fix.smem_len / 1024, info->fix.smem_start); + + return 0; +} + +static struct fb_ops gxfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = gxfb_check_var, + .fb_set_par = gxfb_set_par, + .fb_setcolreg = gxfb_setcolreg, + .fb_blank = gxfb_blank, + /* No HW acceleration for now. */ + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static struct fb_info * __init gxfb_init_fbinfo(struct device *dev) +{ + struct geodefb_par *par; + struct fb_info *info; + + /* Alloc enough space for the pseudo palette. */ + info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev); + if (!info) + return NULL; + + par = info->par; + + strcpy(info->fix.id, "Geode GX"); + + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.type_aux = 0; + info->fix.xpanstep = 0; + info->fix.ypanstep = 0; + info->fix.ywrapstep = 0; + info->fix.accel = FB_ACCEL_NONE; + + info->var.nonstd = 0; + info->var.activate = FB_ACTIVATE_NOW; + info->var.height = -1; + info->var.width = -1; + info->var.accel_flags = 0; + info->var.vmode = FB_VMODE_NONINTERLACED; + + info->fbops = &gxfb_ops; + info->flags = FBINFO_DEFAULT; + info->node = -1; + + info->pseudo_palette = (void *)par + sizeof(struct geodefb_par); + + info->var.grayscale = 0; + + return info; +} + +static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct geodefb_par *par; + struct fb_info *info; + int ret; + + info = gxfb_init_fbinfo(&pdev->dev); + if (!info) + return -ENOMEM; + par = info->par; + + /* GX display controller and GX video device. */ + par->dc_ops = &gx_dc_ops; + par->vid_ops = &gx_vid_ops; + + if ((ret = gxfb_map_video_memory(info, pdev)) < 0) { + dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n"); + goto err; + } + + ret = fb_find_mode(&info->var, info, mode_option, + gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16); + if (ret == 0 || ret == 4) { + dev_err(&pdev->dev, "could not find valid video mode\n"); + ret = -EINVAL; + goto err; + } + + /* Clear the frame buffer of garbage. */ + memset_io(info->screen_base, 0, info->fix.smem_len); + + gxfb_check_var(&info->var, info); + gxfb_set_par(info); + + if (register_framebuffer(info) < 0) { + ret = -EINVAL; + goto err; + } + pci_set_drvdata(pdev, info); + printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); + return 0; + + err: + if (info->screen_base) { + iounmap(info->screen_base); + pci_release_region(pdev, 0); + } + if (par->vid_regs) { + iounmap(par->vid_regs); + pci_release_region(pdev, 3); + } + if (par->dc_regs) { + iounmap(par->dc_regs); + pci_release_region(pdev, 2); + } + + pci_disable_device(pdev); + + if (info) + framebuffer_release(info); + return ret; +} + +static void gxfb_remove(struct pci_dev *pdev) +{ + struct fb_info *info = pci_get_drvdata(pdev); + struct geodefb_par *par = info->par; + + unregister_framebuffer(info); + + iounmap((void __iomem *)info->screen_base); + pci_release_region(pdev, 0); + + iounmap(par->vid_regs); + pci_release_region(pdev, 3); + + iounmap(par->dc_regs); + pci_release_region(pdev, 2); + + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + + framebuffer_release(info); +} + +static struct pci_device_id gxfb_id_table[] = { + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_VIDEO, + PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, + 0xff0000, 0 }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, gxfb_id_table); + +static struct pci_driver gxfb_driver = { + .name = "gxfb", + .id_table = gxfb_id_table, + .probe = gxfb_probe, + .remove = gxfb_remove, +}; + +static int __init gxfb_init(void) +{ +#ifndef MODULE + if (fb_get_options("gxfb", NULL)) + return -ENODEV; +#endif + return pci_register_driver(&gxfb_driver); +} + +static void __exit gxfb_cleanup(void) +{ + pci_unregister_driver(&gxfb_driver); +} + +module_init(gxfb_init); +module_exit(gxfb_cleanup); + +module_param_string(mode, mode_option, sizeof(mode_option), 0444); +MODULE_PARM_DESC(mode, "video mode (x[-][@])"); + +MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c new file mode 100644 index 000000000000..2b2a7880ea75 --- /dev/null +++ b/drivers/video/geode/video_gx.c @@ -0,0 +1,262 @@ +/* + * Geode GX video processor device. + * + * Copyright (C) 2006 Arcom Control Systems Ltd. + * + * Portions from AMD's original 2.4 driver: + * Copyright (C) 2004 Advanced Micro Devices, 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 "geodefb.h" +#include "video_gx.h" + + +/* + * Tables of register settings for various DOTCLKs. + */ +struct gx_pll_entry { + long pixclock; /* ps */ + u32 sys_rstpll_bits; + u32 dotpll_value; +}; + +#define POSTDIV3 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3) +#define PREMULT2 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPREMULT2) +#define PREDIV2 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3) + +static const struct gx_pll_entry gx_pll_table_48MHz[] = { + { 40123, POSTDIV3, 0x00000BF2 }, /* 24.9230 */ + { 39721, 0, 0x00000037 }, /* 25.1750 */ + { 35308, POSTDIV3|PREMULT2, 0x00000B1A }, /* 28.3220 */ + { 31746, POSTDIV3, 0x000002D2 }, /* 31.5000 */ + { 27777, POSTDIV3|PREMULT2, 0x00000FE2 }, /* 36.0000 */ + { 26666, POSTDIV3, 0x0000057A }, /* 37.5000 */ + { 25000, POSTDIV3, 0x0000030A }, /* 40.0000 */ + { 22271, 0, 0x00000063 }, /* 44.9000 */ + { 20202, 0, 0x0000054B }, /* 49.5000 */ + { 20000, 0, 0x0000026E }, /* 50.0000 */ + { 19860, PREMULT2, 0x00000037 }, /* 50.3500 */ + { 18518, POSTDIV3|PREMULT2, 0x00000B0D }, /* 54.0000 */ + { 17777, 0, 0x00000577 }, /* 56.2500 */ + { 17733, 0, 0x000007F7 }, /* 56.3916 */ + { 17653, 0, 0x0000057B }, /* 56.6444 */ + { 16949, PREMULT2, 0x00000707 }, /* 59.0000 */ + { 15873, POSTDIV3|PREMULT2, 0x00000B39 }, /* 63.0000 */ + { 15384, POSTDIV3|PREMULT2, 0x00000B45 }, /* 65.0000 */ + { 14814, POSTDIV3|PREMULT2, 0x00000FC1 }, /* 67.5000 */ + { 14124, POSTDIV3, 0x00000561 }, /* 70.8000 */ + { 13888, POSTDIV3, 0x000007E1 }, /* 72.0000 */ + { 13426, PREMULT2, 0x00000F4A }, /* 74.4810 */ + { 13333, 0, 0x00000052 }, /* 75.0000 */ + { 12698, 0, 0x00000056 }, /* 78.7500 */ + { 12500, POSTDIV3|PREMULT2, 0x00000709 }, /* 80.0000 */ + { 11135, PREMULT2, 0x00000262 }, /* 89.8000 */ + { 10582, 0, 0x000002D2 }, /* 94.5000 */ + { 10101, PREMULT2, 0x00000B4A }, /* 99.0000 */ + { 10000, PREMULT2, 0x00000036 }, /* 100.0000 */ + { 9259, 0, 0x000007E2 }, /* 108.0000 */ + { 8888, 0, 0x000007F6 }, /* 112.5000 */ + { 7692, POSTDIV3|PREMULT2, 0x00000FB0 }, /* 130.0000 */ + { 7407, POSTDIV3|PREMULT2, 0x00000B50 }, /* 135.0000 */ + { 6349, 0, 0x00000055 }, /* 157.5000 */ + { 6172, 0, 0x000009C1 }, /* 162.0000 */ + { 5787, PREMULT2, 0x0000002D }, /* 172.798 */ + { 5698, 0, 0x000002C1 }, /* 175.5000 */ + { 5291, 0, 0x000002D1 }, /* 189.0000 */ + { 4938, 0, 0x00000551 }, /* 202.5000 */ + { 4357, 0, 0x0000057D }, /* 229.5000 */ +}; + +static const struct gx_pll_entry gx_pll_table_14MHz[] = { + { 39721, 0, 0x00000037 }, /* 25.1750 */ + { 35308, 0, 0x00000B7B }, /* 28.3220 */ + { 31746, 0, 0x000004D3 }, /* 31.5000 */ + { 27777, 0, 0x00000BE3 }, /* 36.0000 */ + { 26666, 0, 0x0000074F }, /* 37.5000 */ + { 25000, 0, 0x0000050B }, /* 40.0000 */ + { 22271, 0, 0x00000063 }, /* 44.9000 */ + { 20202, 0, 0x0000054B }, /* 49.5000 */ + { 20000, 0, 0x0000026E }, /* 50.0000 */ + { 19860, 0, 0x000007C3 }, /* 50.3500 */ + { 18518, 0, 0x000007E3 }, /* 54.0000 */ + { 17777, 0, 0x00000577 }, /* 56.2500 */ + { 17733, 0, 0x000002FB }, /* 56.3916 */ + { 17653, 0, 0x0000057B }, /* 56.6444 */ + { 16949, 0, 0x0000058B }, /* 59.0000 */ + { 15873, 0, 0x0000095E }, /* 63.0000 */ + { 15384, 0, 0x0000096A }, /* 65.0000 */ + { 14814, 0, 0x00000BC2 }, /* 67.5000 */ + { 14124, 0, 0x0000098A }, /* 70.8000 */ + { 13888, 0, 0x00000BE2 }, /* 72.0000 */ + { 13333, 0, 0x00000052 }, /* 75.0000 */ + { 12698, 0, 0x00000056 }, /* 78.7500 */ + { 12500, 0, 0x0000050A }, /* 80.0000 */ + { 11135, 0, 0x0000078E }, /* 89.8000 */ + { 10582, 0, 0x000002D2 }, /* 94.5000 */ + { 10101, 0, 0x000011F6 }, /* 99.0000 */ + { 10000, 0, 0x0000054E }, /* 100.0000 */ + { 9259, 0, 0x000007E2 }, /* 108.0000 */ + { 8888, 0, 0x000002FA }, /* 112.5000 */ + { 7692, 0, 0x00000BB1 }, /* 130.0000 */ + { 7407, 0, 0x00000975 }, /* 135.0000 */ + { 6349, 0, 0x00000055 }, /* 157.5000 */ + { 6172, 0, 0x000009C1 }, /* 162.0000 */ + { 5698, 0, 0x000002C1 }, /* 175.5000 */ + { 5291, 0, 0x00000539 }, /* 189.0000 */ + { 4938, 0, 0x00000551 }, /* 202.5000 */ + { 4357, 0, 0x0000057D }, /* 229.5000 */ +}; + +static void gx_set_dclk_frequency(struct fb_info *info) +{ + const struct gx_pll_entry *pll_table; + int pll_table_len; + int i, best_i; + long min, diff; + u64 dotpll, sys_rstpll; + int timeout = 1000; + + /* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */ + if (cpu_data->x86_mask == 1) { + pll_table = gx_pll_table_14MHz; + pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz); + } else { + pll_table = gx_pll_table_48MHz; + pll_table_len = ARRAY_SIZE(gx_pll_table_48MHz); + } + + /* Search the table for the closest pixclock. */ + best_i = 0; + min = abs(pll_table[0].pixclock - info->var.pixclock); + for (i = 1; i < pll_table_len; i++) { + diff = abs(pll_table[i].pixclock - info->var.pixclock); + if (diff < min) { + min = diff; + best_i = i; + } + } + + rdmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll); + rdmsrl(MSR_GLCP_DOTPLL, dotpll); + + /* Program new M, N and P. */ + dotpll &= 0x00000000ffffffffull; + dotpll |= (u64)pll_table[best_i].dotpll_value << 32; + dotpll |= MSR_GLCP_DOTPLL_DOTRESET; + dotpll &= ~MSR_GLCP_DOTPLL_BYPASS; + + wrmsrl(MSR_GLCP_DOTPLL, dotpll); + + /* Program dividers. */ + sys_rstpll &= ~( MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 + | MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 + | MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 ); + sys_rstpll |= pll_table[best_i].sys_rstpll_bits; + + wrmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll); + + /* Clear reset bit to start PLL. */ + dotpll &= ~(MSR_GLCP_DOTPLL_DOTRESET); + wrmsrl(MSR_GLCP_DOTPLL, dotpll); + + /* Wait for LOCK bit. */ + do { + rdmsrl(MSR_GLCP_DOTPLL, dotpll); + } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK)); +} + +static void gx_configure_display(struct fb_info *info) +{ + struct geodefb_par *par = info->par; + u32 dcfg, fp_pm; + + dcfg = readl(par->vid_regs + GX_DCFG); + + /* Clear bits from existing mode. */ + dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK + | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL + | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN); + + /* Set default sync skew. */ + dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT; + + /* Enable hsync and vsync. */ + dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN; + + /* Sync polarities. */ + if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) + dcfg |= GX_DCFG_CRT_HSYNC_POL; + if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) + dcfg |= GX_DCFG_CRT_VSYNC_POL; + + writel(dcfg, par->vid_regs + GX_DCFG); + + /* Power on flat panel. */ + fp_pm = readl(par->vid_regs + GX_FP_PM); + fp_pm |= GX_FP_PM_P; + writel(fp_pm, par->vid_regs + GX_FP_PM); +} + +static int gx_blank_display(struct fb_info *info, int blank_mode) +{ + struct geodefb_par *par = info->par; + u32 dcfg, fp_pm; + int blank, hsync, vsync; + + /* CRT power saving modes. */ + switch (blank_mode) { + case FB_BLANK_UNBLANK: + blank = 0; hsync = 1; vsync = 1; + break; + case FB_BLANK_NORMAL: + blank = 1; hsync = 1; vsync = 1; + break; + case FB_BLANK_VSYNC_SUSPEND: + blank = 1; hsync = 1; vsync = 0; + break; + case FB_BLANK_HSYNC_SUSPEND: + blank = 1; hsync = 0; vsync = 1; + break; + case FB_BLANK_POWERDOWN: + blank = 1; hsync = 0; vsync = 0; + break; + default: + return -EINVAL; + } + dcfg = readl(par->vid_regs + GX_DCFG); + dcfg &= ~(GX_DCFG_DAC_BL_EN + | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN); + if (!blank) + dcfg |= GX_DCFG_DAC_BL_EN; + if (hsync) + dcfg |= GX_DCFG_HSYNC_EN; + if (vsync) + dcfg |= GX_DCFG_VSYNC_EN; + writel(dcfg, par->vid_regs + GX_DCFG); + + /* Power on/off flat panel. */ + fp_pm = readl(par->vid_regs + GX_FP_PM); + if (blank_mode == FB_BLANK_POWERDOWN) + fp_pm &= ~GX_FP_PM_P; + else + fp_pm |= GX_FP_PM_P; + writel(fp_pm, par->vid_regs + GX_FP_PM); + + return 0; +} + +struct geode_vid_ops gx_vid_ops = { + .set_dclk = gx_set_dclk_frequency, + .configure_display = gx_configure_display, + .blank_display = gx_blank_display, +}; diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h new file mode 100644 index 000000000000..2d9211f3ed84 --- /dev/null +++ b/drivers/video/geode/video_gx.h @@ -0,0 +1,47 @@ +/* + * Geode GX video device + * + * Copyright (C) 2006 Arcom Control Systems Ltd. + * + * 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 __VIDEO_GX_H__ +#define __VIDEO_GX_H__ + +extern struct geode_vid_ops gx_vid_ops; + +/* Geode GX video processor registers */ + +#define GX_DCFG 0x0008 +# define GX_DCFG_CRT_EN 0x00000001 +# define GX_DCFG_HSYNC_EN 0x00000002 +# define GX_DCFG_VSYNC_EN 0x00000004 +# define GX_DCFG_DAC_BL_EN 0x00000008 +# define GX_DCFG_CRT_HSYNC_POL 0x00000100 +# define GX_DCFG_CRT_VSYNC_POL 0x00000200 +# define GX_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 +# define GX_DCFG_CRT_SYNC_SKW_DFLT 0x00010000 +# define GX_DCFG_VG_CK 0x00100000 +# define GX_DCFG_GV_GAM 0x00200000 +# define GX_DCFG_DAC_VREF 0x04000000 + +/* Geode GX flat panel display control registers */ +#define GX_FP_PM 0x410 +# define GX_FP_PM_P 0x01000000 + +/* Geode GX clock control MSRs */ + +#define MSR_GLCP_SYS_RSTPLL 0x4c000014 +# define MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 (0x0000000000000002ull) +# define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (0x0000000000000004ull) +# define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (0x0000000000000008ull) + +#define MSR_GLCP_DOTPLL 0x4c000015 +# define MSR_GLCP_DOTPLL_DOTRESET (0x0000000000000001ull) +# define MSR_GLCP_DOTPLL_BYPASS (0x0000000000008000ull) +# define MSR_GLCP_DOTPLL_LOCK (0x0000000002000000ull) + +#endif /* !__VIDEO_GX_H__ */ -- cgit v1.2.3-59-g8ed1b From 756e21a022aba5214bafcf803f114aed8a783b99 Mon Sep 17 00:00:00 2001 From: Arthur Othieno Date: Mon, 27 Mar 2006 01:17:24 -0800 Subject: [PATCH] matroxfb: simply return what i2c_add_driver() does insmod will tell us when the module failed to load. We do no further processing on the return from i2c_add_driver(), so just return what i2c_add_driver() did, instead of storing it. Add __init/__exit annotations while we're at it. Signed-off-by: Arthur Othieno Acked-by: Jean Delvare Acked-by: Petr Vandrovec Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/matrox/matroxfb_maven.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 6019710dc298..531a0c3b6ec1 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -1297,20 +1297,13 @@ static struct i2c_driver maven_driver={ .detach_client = maven_detach_client, }; -/* ************************** */ - -static int matroxfb_maven_init(void) { - int err; - - err = i2c_add_driver(&maven_driver); - if (err) { - printk(KERN_ERR "maven: Maven driver failed to register (%d).\n", err); - return err; - } - return 0; +static int __init matroxfb_maven_init(void) +{ + return i2c_add_driver(&maven_driver); } -static void matroxfb_maven_exit(void) { +static void __exit matroxfb_maven_exit(void) +{ i2c_del_driver(&maven_driver); } -- cgit v1.2.3-59-g8ed1b From d03c21ec0be7787ff6b75dcf56c0e96209ccbfbd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 27 Mar 2006 01:17:26 -0800 Subject: [PATCH] matrox maven: memory allocation and other cleanups A few cleanups which were done to almost all i2c drivers some times ago, but matroxfb_maven was forgotten: * Don't allocate two different structures at once. * Use kzalloc instead of kmalloc+memset. * Use strlcpy instead of strcpy. * Drop duplicate error message on client deregistration failure. Signed-off-by: Jean Delvare Acked-by: Petr Vandrovec Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/matrox/matroxfb_maven.c | 55 ++++++++++++++++------------------- 1 file changed, 25 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 531a0c3b6ec1..d8b3429cbed3 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -129,7 +129,7 @@ static int get_ctrl_id(__u32 v4l2_id) { struct maven_data { struct matrox_fb_info* primary_head; - struct i2c_client* client; + struct i2c_client client; int version; }; @@ -970,7 +970,7 @@ static inline int maven_compute_timming(struct maven_data* md, static int maven_program_timming(struct maven_data* md, const struct mavenregs* m) { - struct i2c_client* c = md->client; + struct i2c_client* c = &md->client; if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) { LR(0x80); @@ -1007,7 +1007,7 @@ static int maven_program_timming(struct maven_data* md, } static inline int maven_resync(struct maven_data* md) { - struct i2c_client* c = md->client; + struct i2c_client* c = &md->client; maven_set_reg(c, 0x95, 0x20); /* start whole thing */ return 0; } @@ -1065,48 +1065,48 @@ static int maven_set_control (struct maven_data* md, maven_compute_bwlevel(md, &blacklevel, &whitelevel); blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8); whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8); - maven_set_reg_pair(md->client, 0x0e, blacklevel); - maven_set_reg_pair(md->client, 0x1e, whitelevel); + maven_set_reg_pair(&md->client, 0x0e, blacklevel); + maven_set_reg_pair(&md->client, 0x1e, whitelevel); } break; case V4L2_CID_SATURATION: { - maven_set_reg(md->client, 0x20, p->value); - maven_set_reg(md->client, 0x22, p->value); + maven_set_reg(&md->client, 0x20, p->value); + maven_set_reg(&md->client, 0x22, p->value); } break; case V4L2_CID_HUE: { - maven_set_reg(md->client, 0x25, p->value); + maven_set_reg(&md->client, 0x25, p->value); } break; case V4L2_CID_GAMMA: { const struct maven_gamma* g; g = maven_compute_gamma(md); - maven_set_reg(md->client, 0x83, g->reg83); - maven_set_reg(md->client, 0x84, g->reg84); - maven_set_reg(md->client, 0x85, g->reg85); - maven_set_reg(md->client, 0x86, g->reg86); - maven_set_reg(md->client, 0x87, g->reg87); - maven_set_reg(md->client, 0x88, g->reg88); - maven_set_reg(md->client, 0x89, g->reg89); - maven_set_reg(md->client, 0x8a, g->reg8a); - maven_set_reg(md->client, 0x8b, g->reg8b); + maven_set_reg(&md->client, 0x83, g->reg83); + maven_set_reg(&md->client, 0x84, g->reg84); + maven_set_reg(&md->client, 0x85, g->reg85); + maven_set_reg(&md->client, 0x86, g->reg86); + maven_set_reg(&md->client, 0x87, g->reg87); + maven_set_reg(&md->client, 0x88, g->reg88); + maven_set_reg(&md->client, 0x89, g->reg89); + maven_set_reg(&md->client, 0x8a, g->reg8a); + maven_set_reg(&md->client, 0x8b, g->reg8b); } break; case MATROXFB_CID_TESTOUT: { unsigned char val - = maven_get_reg (md->client,0x8d); + = maven_get_reg(&md->client,0x8d); if (p->value) val |= 0x10; else val &= ~0x10; - maven_set_reg (md->client, 0x8d, val); + maven_set_reg(&md->client, 0x8d, val); } break; case MATROXFB_CID_DEFLICKER: { - maven_set_reg(md->client, 0x93, maven_compute_deflicker(md)); + maven_set_reg(&md->client, 0x93, maven_compute_deflicker(md)); } break; } @@ -1185,7 +1185,6 @@ static int maven_init_client(struct i2c_client* clnt) { MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo); md->primary_head = MINFO; - md->client = clnt; down_write(&ACCESS_FBINFO(altout.lock)); ACCESS_FBINFO(outputs[1]).output = &maven_altout; ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; @@ -1243,19 +1242,17 @@ static int maven_detect_client(struct i2c_adapter* adapter, int address, int kin I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_PROTOCOL_MANGLING)) goto ERROR0; - if (!(new_client = (struct i2c_client*)kmalloc(sizeof(*new_client) + sizeof(*data), - GFP_KERNEL))) { + if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) { err = -ENOMEM; goto ERROR0; } - memset(new_client, 0, sizeof(*new_client) + sizeof(*data)); - data = (struct maven_data*)(new_client + 1); + new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; new_client->adapter = adapter; new_client->driver = &maven_driver; new_client->flags = 0; - strcpy(new_client->name, "maven client"); + strlcpy(new_client->name, "maven", I2C_NAME_SIZE); if ((err = i2c_attach_client(new_client))) goto ERROR3; err = maven_init_client(new_client); @@ -1279,12 +1276,10 @@ static int maven_attach_adapter(struct i2c_adapter* adapter) { static int maven_detach_client(struct i2c_client* client) { int err; - if ((err = i2c_detach_client(client))) { - printk(KERN_ERR "maven: Cannot deregister client\n"); + if ((err = i2c_detach_client(client))) return err; - } maven_shutdown_client(client); - kfree(client); + kfree(i2c_get_clientdata(client)); return 0; } -- cgit v1.2.3-59-g8ed1b From f95ec3c6df271ae4e6290cd6b95c18a009c76dc9 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 27 Mar 2006 01:17:27 -0800 Subject: [PATCH] au1200fb: Alchemy Au1200 framebuffer driver Add support for Alchemy Au1200 framebuffer driver Signed-off-by: Ralf Baechle Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/Kconfig | 11 + drivers/video/Makefile | 1 + drivers/video/au1200fb.c | 3844 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/video/au1200fb.h | 572 +++++++ 4 files changed, 4428 insertions(+) create mode 100644 drivers/video/au1200fb.c create mode 100644 drivers/video/au1200fb.h (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index fdebd60a3250..3a890610ebe7 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1202,6 +1202,17 @@ config FB_AU1100 bool "Au1100 LCD Driver" depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y +config FB_AU1200 + bool "Au1200 LCD Driver" + depends on FB && MIPS && SOC_AU1200 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer driver for the AMD Au1200 SOC. It can drive + various panels and CRTs by passing in kernel cmd line option + au1200fb:panel=. + source "drivers/video/geode/Kconfig" config FB_FFB diff --git a/drivers/video/Makefile b/drivers/video/Makefile index aa434e725c0d..cb90218515ac 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -86,6 +86,7 @@ obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o obj-$(CONFIG_FB_PXA) += pxafb.o obj-$(CONFIG_FB_W100) += w100fb.o obj-$(CONFIG_FB_AU1100) += au1100fb.o +obj-$(CONFIG_FB_AU1200) += au1200fb.o obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c new file mode 100644 index 000000000000..b367de30b98c --- /dev/null +++ b/drivers/video/au1200fb.c @@ -0,0 +1,3844 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1200 LCD Driver. + * + * Copyright 2004-2005 AMD + * Author: AMD + * + * Based on: + * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device + * Created 28 Dec 1997 by Geert Uytterhoeven + * + * 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 SOFTWARE IS PROVIDED ``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 AUTHOR 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. + * + * 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 +#include +#include + +#include +#include "au1200fb.h" + +#ifdef CONFIG_PM +#include +#endif + +#ifndef CONFIG_FB_AU1200_DEVS +#define CONFIG_FB_AU1200_DEVS 4 +#endif + +#define DRIVER_NAME "au1200fb" +#define DRIVER_DESC "LCD controller driver for AU1200 processors" + +#define DEBUG 1 + +#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) +#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) +#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) + +#if DEBUG +#define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg) +#else +#define print_dbg(f, arg...) do {} while (0) +#endif + + +#define AU1200_LCD_FB_IOCTL 0x46FF + +#define AU1200_LCD_SET_SCREEN 1 +#define AU1200_LCD_GET_SCREEN 2 +#define AU1200_LCD_SET_WINDOW 3 +#define AU1200_LCD_GET_WINDOW 4 +#define AU1200_LCD_SET_PANEL 5 +#define AU1200_LCD_GET_PANEL 6 + +#define SCREEN_SIZE (1<< 1) +#define SCREEN_BACKCOLOR (1<< 2) +#define SCREEN_BRIGHTNESS (1<< 3) +#define SCREEN_COLORKEY (1<< 4) +#define SCREEN_MASK (1<< 5) + +struct au1200_lcd_global_regs_t { + unsigned int flags; + unsigned int xsize; + unsigned int ysize; + unsigned int backcolor; + unsigned int brightness; + unsigned int colorkey; + unsigned int mask; + unsigned int panel_choice; + char panel_desc[80]; + +}; + +#define WIN_POSITION (1<< 0) +#define WIN_ALPHA_COLOR (1<< 1) +#define WIN_ALPHA_MODE (1<< 2) +#define WIN_PRIORITY (1<< 3) +#define WIN_CHANNEL (1<< 4) +#define WIN_BUFFER_FORMAT (1<< 5) +#define WIN_COLOR_ORDER (1<< 6) +#define WIN_PIXEL_ORDER (1<< 7) +#define WIN_SIZE (1<< 8) +#define WIN_COLORKEY_MODE (1<< 9) +#define WIN_DOUBLE_BUFFER_MODE (1<< 10) +#define WIN_RAM_ARRAY_MODE (1<< 11) +#define WIN_BUFFER_SCALE (1<< 12) +#define WIN_ENABLE (1<< 13) + +struct au1200_lcd_window_regs_t { + unsigned int flags; + unsigned int xpos; + unsigned int ypos; + unsigned int alpha_color; + unsigned int alpha_mode; + unsigned int priority; + unsigned int channel; + unsigned int buffer_format; + unsigned int color_order; + unsigned int pixel_order; + unsigned int xsize; + unsigned int ysize; + unsigned int colorkey_mode; + unsigned int double_buffer_mode; + unsigned int ram_array_mode; + unsigned int xscale; + unsigned int yscale; + unsigned int enable; +}; + + +struct au1200_lcd_iodata_t { + unsigned int subcmd; + struct au1200_lcd_global_regs_t global; + struct au1200_lcd_window_regs_t window; +}; + +#if defined(__BIG_ENDIAN) +#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11 +#else +#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00 +#endif +#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565 + +/* Private, per-framebuffer management information (independent of the panel itself) */ +struct au1200fb_device { + struct fb_info fb_info; /* FB driver info record */ + + int plane; + unsigned char* fb_mem; /* FrameBuffer memory map */ + unsigned int fb_len; + dma_addr_t fb_phys; +}; + +static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; +/********************************************************************/ + +/* LCD controller restrictions */ +#define AU1200_LCD_MAX_XRES 1280 +#define AU1200_LCD_MAX_YRES 1024 +#define AU1200_LCD_MAX_BPP 32 +#define AU1200_LCD_MAX_CLK 96000000 /* fixme: this needs to go away ? */ +#define AU1200_LCD_NBR_PALETTE_ENTRIES 256 + +/* Default number of visible screen buffer to allocate */ +#define AU1200FB_NBR_VIDEO_BUFFERS 1 + +/********************************************************************/ + +static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; +static int window_index = 2; /* default is zero */ +static int panel_index = 2; /* default is zero */ +static struct window_settings *win; +static struct panel_settings *panel; +static int noblanking = 1; +static int nohwcursor = 0; + +struct window_settings { + unsigned char name[64]; + uint32 mode_backcolor; + uint32 mode_colorkey; + uint32 mode_colorkeymsk; + struct { + int xres; + int yres; + int xpos; + int ypos; + uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */ + uint32 mode_winenable; + } w[4]; +}; + +#if defined(__BIG_ENDIAN) +#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00 +#else +#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01 +#endif + +extern int board_au1200fb_panel_init (void); +extern int board_au1200fb_panel_shutdown (void); + +#ifdef CONFIG_PM +int au1200fb_pm_callback(au1xxx_power_dev_t *dev, + au1xxx_request_t request, void *data); +au1xxx_power_dev_t *LCD_pm_dev; +#endif + +/* + * Default window configurations + */ +static struct window_settings windows[] = { + { /* Index 0 */ + "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", + /* mode_backcolor */ 0x006600ff, + /* mode_colorkey,msk*/ 0, 0, + { + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP, + /* mode_winenable*/ LCD_WINENABLE_WEN0, + }, + { + /* xres, yres, xpos, ypos */ 100, 100, 100, 100, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP | + LCD_WINCTRL1_PIPE, + /* mode_winenable*/ LCD_WINENABLE_WEN1, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP, + /* mode_winenable*/ 0, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP | + LCD_WINCTRL1_PIPE, + /* mode_winenable*/ 0, + }, + }, + }, + + { /* Index 1 */ + "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", + /* mode_backcolor */ 0x006600ff, + /* mode_colorkey,msk*/ 0, 0, + { + { + /* xres, yres, xpos, ypos */ 320, 240, 5, 5, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP | + LCD_WINCTRL1_PO_00, + /* mode_winenable*/ LCD_WINENABLE_WEN0, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 + | LCD_WINCTRL1_PO_16BPP, + /* mode_winenable*/ 0, + }, + { + /* xres, yres, xpos, ypos */ 100, 100, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP | + LCD_WINCTRL1_PIPE, + /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, + }, + { + /* xres, yres, xpos, ypos */ 200, 25, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP | + LCD_WINCTRL1_PIPE, + /* mode_winenable*/ 0, + }, + }, + }, + { /* Index 2 */ + "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", + /* mode_backcolor */ 0x006600ff, + /* mode_colorkey,msk*/ 0, 0, + { + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP, + /* mode_winenable*/ LCD_WINENABLE_WEN0, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP, + /* mode_winenable*/ 0, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP | + LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE, + /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP | + LCD_WINCTRL1_PIPE, + /* mode_winenable*/ 0, + }, + }, + }, + /* Need VGA 640 @ 24bpp, @ 32bpp */ + /* Need VGA 800 @ 24bpp, @ 32bpp */ + /* Need VGA 1024 @ 24bpp, @ 32bpp */ +}; + +/* + * Controller configurations for various panels. + */ + +struct panel_settings +{ + const char name[25]; /* Full name _ */ + + struct fb_monspecs monspecs; /* FB monitor specs */ + + /* panel timings */ + uint32 mode_screen; + uint32 mode_horztiming; + uint32 mode_verttiming; + uint32 mode_clkcontrol; + uint32 mode_pwmdiv; + uint32 mode_pwmhi; + uint32 mode_outmask; + uint32 mode_fifoctrl; + uint32 mode_toyclksrc; + uint32 mode_backlight; + uint32 mode_auxpll; + int (*device_init)(void); + int (*device_shutdown)(void); +#define Xres min_xres +#define Yres min_yres + u32 min_xres; /* Minimum horizontal resolution */ + u32 max_xres; /* Maximum horizontal resolution */ + u32 min_yres; /* Minimum vertical resolution */ + u32 max_yres; /* Maximum vertical resolution */ +}; + +/********************************************************************/ +/* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */ + +/* List of panels known to work with the AU1200 LCD controller. + * To add a new panel, enter the same specifications as the + * Generic_TFT one, and MAKE SURE that it doesn't conflicts + * with the controller restrictions. Restrictions are: + * + * STN color panels: max_bpp <= 12 + * STN mono panels: max_bpp <= 4 + * TFT panels: max_bpp <= 16 + * max_xres <= 800 + * max_yres <= 600 + */ +static struct panel_settings known_lcd_panels[] = +{ + [0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */ + .name = "QVGA_320x240", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = LCD_SCREEN_SX_N(320) | + LCD_SCREEN_SY_N(240), + .mode_horztiming = 0x00c4623b, + .mode_verttiming = 0x00502814, + .mode_clkcontrol = 0x00020002, /* /4=24Mhz */ + .mode_pwmdiv = 0x00000000, + .mode_pwmhi = 0x00000000, + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = NULL, + .device_shutdown = NULL, + 320, 320, + 240, 240, + }, + + [1] = { /* VGA 640x480 H:30.3kHz V:58Hz */ + .name = "VGA_640x480", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = 0x13f9df80, + .mode_horztiming = 0x003c5859, + .mode_verttiming = 0x00741201, + .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ + .mode_pwmdiv = 0x00000000, + .mode_pwmhi = 0x00000000, + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = NULL, + .device_shutdown = NULL, + 640, 480, + 640, 480, + }, + + [2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */ + .name = "SVGA_800x600", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = 0x18fa5780, + .mode_horztiming = 0x00dc7e77, + .mode_verttiming = 0x00584805, + .mode_clkcontrol = 0x00020000, /* /2=48Mhz */ + .mode_pwmdiv = 0x00000000, + .mode_pwmhi = 0x00000000, + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = NULL, + .device_shutdown = NULL, + 800, 800, + 600, 600, + }, + + [3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */ + .name = "XVGA_1024x768", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = 0x1ffaff80, + .mode_horztiming = 0x007d0e57, + .mode_verttiming = 0x00740a01, + .mode_clkcontrol = 0x000A0000, /* /1 */ + .mode_pwmdiv = 0x00000000, + .mode_pwmhi = 0x00000000, + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 6, /* 72MHz AUXPLL */ + .device_init = NULL, + .device_shutdown = NULL, + 1024, 1024, + 768, 768, + }, + + [4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */ + .name = "XVGA_1280x1024", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = 0x27fbff80, + .mode_horztiming = 0x00cdb2c7, + .mode_verttiming = 0x00600002, + .mode_clkcontrol = 0x000A0000, /* /1 */ + .mode_pwmdiv = 0x00000000, + .mode_pwmhi = 0x00000000, + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 10, /* 120MHz AUXPLL */ + .device_init = NULL, + .device_shutdown = NULL, + 1280, 1280, + 1024, 1024, + }, + + [5] = { /* Samsung 1024x768 TFT */ + .name = "Samsung_1024x768_TFT", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = 0x1ffaff80, + .mode_horztiming = 0x018cc677, + .mode_verttiming = 0x00241217, + .mode_clkcontrol = 0x00000000, /* SCB 0x1 /4=24Mhz */ + .mode_pwmdiv = 0x8000063f, /* SCB 0x0 */ + .mode_pwmhi = 0x03400000, /* SCB 0x0 */ + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = board_au1200fb_panel_init, + .device_shutdown = board_au1200fb_panel_shutdown, + 1024, 1024, + 768, 768, + }, + + [6] = { /* Toshiba 640x480 TFT */ + .name = "Toshiba_640x480_TFT", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = LCD_SCREEN_SX_N(640) | + LCD_SCREEN_SY_N(480), + .mode_horztiming = LCD_HORZTIMING_HPW_N(96) | + LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51), + .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | + LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32), + .mode_clkcontrol = 0x00000000, /* /4=24Mhz */ + .mode_pwmdiv = 0x8000063f, + .mode_pwmhi = 0x03400000, + .mode_outmask = 0x00fcfcfc, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = board_au1200fb_panel_init, + .device_shutdown = board_au1200fb_panel_shutdown, + 640, 480, + 640, 480, + }, + + [7] = { /* Sharp 320x240 TFT */ + .name = "Sharp_320x240_TFT", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 12500, + .hfmax = 20000, + .vfmin = 38, + .vfmax = 81, + .dclkmin = 4500000, + .dclkmax = 6800000, + .input = FB_DISP_RGB, + }, + .mode_screen = LCD_SCREEN_SX_N(320) | + LCD_SCREEN_SY_N(240), + .mode_horztiming = LCD_HORZTIMING_HPW_N(60) | + LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2), + .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | + LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5), + .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/ + .mode_pwmdiv = 0x8000063f, + .mode_pwmhi = 0x03400000, + .mode_outmask = 0x00fcfcfc, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = board_au1200fb_panel_init, + .device_shutdown = board_au1200fb_panel_shutdown, + 320, 320, + 240, 240, + }, + + [8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */ + .name = "Toppoly_TD070WGCB2", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = LCD_SCREEN_SX_N(856) | + LCD_SCREEN_SY_N(480), + .mode_horztiming = LCD_HORZTIMING_HND2_N(43) | + LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114), + .mode_verttiming = LCD_VERTTIMING_VND2_N(20) | + LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4), + .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ + .mode_pwmdiv = 0x8000063f, + .mode_pwmhi = 0x03400000, + .mode_outmask = 0x00fcfcfc, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = board_au1200fb_panel_init, + .device_shutdown = board_au1200fb_panel_shutdown, + 856, 856, + 480, 480, + }, +}; + +#define NUM_PANELS (ARRAY_SIZE(known_lcd_panels)) + +/********************************************************************/ + +#ifdef CONFIG_PM +static int set_brightness(unsigned int brightness) +{ + unsigned int hi1, divider; + + /* limit brightness pwm duty to >= 30/1600 */ + if (brightness < 30) { + brightness = 30; + } + divider = (lcd->pwmdiv & 0x3FFFF) + 1; + hi1 = (lcd->pwmhi >> 16) + 1; + hi1 = (((brightness & 0xFF) + 1) * divider >> 8); + lcd->pwmhi &= 0xFFFF; + lcd->pwmhi |= (hi1 << 16); + + return brightness; +} +#endif /* CONFIG_PM */ + +static int winbpp (unsigned int winctrl1) +{ + int bits = 0; + + /* how many bits are needed for each pixel format */ + switch (winctrl1 & LCD_WINCTRL1_FRM) { + case LCD_WINCTRL1_FRM_1BPP: + bits = 1; + break; + case LCD_WINCTRL1_FRM_2BPP: + bits = 2; + break; + case LCD_WINCTRL1_FRM_4BPP: + bits = 4; + break; + case LCD_WINCTRL1_FRM_8BPP: + bits = 8; + break; + case LCD_WINCTRL1_FRM_12BPP: + case LCD_WINCTRL1_FRM_16BPP655: + case LCD_WINCTRL1_FRM_16BPP565: + case LCD_WINCTRL1_FRM_16BPP556: + case LCD_WINCTRL1_FRM_16BPPI1555: + case LCD_WINCTRL1_FRM_16BPPI5551: + case LCD_WINCTRL1_FRM_16BPPA1555: + case LCD_WINCTRL1_FRM_16BPPA5551: + bits = 16; + break; + case LCD_WINCTRL1_FRM_24BPP: + case LCD_WINCTRL1_FRM_32BPP: + bits = 32; + break; + } + + return bits; +} + +static int fbinfo2index (struct fb_info *fb_info) +{ + int i; + + for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { + if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info)) + return i; + } + printk("au1200fb: ERROR: fbinfo2index failed!\n"); + return -1; +} + +static int au1200_setlocation (struct au1200fb_device *fbdev, int plane, + int xpos, int ypos) +{ + uint32 winctrl0, winctrl1, winenable, fb_offset = 0; + int xsz, ysz; + + /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */ + + winctrl0 = lcd->window[plane].winctrl0; + winctrl1 = lcd->window[plane].winctrl1; + winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN); + winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY); + + /* Check for off-screen adjustments */ + xsz = win->w[plane].xres; + ysz = win->w[plane].yres; + if ((xpos + win->w[plane].xres) > panel->Xres) { + /* Off-screen to the right */ + xsz = panel->Xres - xpos; /* off by 1 ??? */ + /*printk("off screen right\n");*/ + } + + if ((ypos + win->w[plane].yres) > panel->Yres) { + /* Off-screen to the bottom */ + ysz = panel->Yres - ypos; /* off by 1 ??? */ + /*printk("off screen bottom\n");*/ + } + + if (xpos < 0) { + /* Off-screen to the left */ + xsz = win->w[plane].xres + xpos; + fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8); + xpos = 0; + /*printk("off screen left\n");*/ + } + + if (ypos < 0) { + /* Off-screen to the top */ + ysz = win->w[plane].yres + ypos; + /* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */ + ypos = 0; + /*printk("off screen top\n");*/ + } + + /* record settings */ + win->w[plane].xpos = xpos; + win->w[plane].ypos = ypos; + + xsz -= 1; + ysz -= 1; + winctrl0 |= (xpos << 21); + winctrl0 |= (ypos << 10); + winctrl1 |= (xsz << 11); + winctrl1 |= (ysz << 0); + + /* Disable the window while making changes, then restore WINEN */ + winenable = lcd->winenable & (1 << plane); + au_sync(); + lcd->winenable &= ~(1 << plane); + lcd->window[plane].winctrl0 = winctrl0; + lcd->window[plane].winctrl1 = winctrl1; + lcd->window[plane].winbuf0 = + lcd->window[plane].winbuf1 = fbdev->fb_phys; + lcd->window[plane].winbufctrl = 0; /* select winbuf0 */ + lcd->winenable |= winenable; + au_sync(); + + return 0; +} + +static void au1200_setpanel (struct panel_settings *newpanel) +{ + /* + * Perform global setup/init of LCD controller + */ + uint32 winenable; + + /* Make sure all windows disabled */ + winenable = lcd->winenable; + lcd->winenable = 0; + au_sync(); + /* + * Ensure everything is disabled before reconfiguring + */ + if (lcd->screen & LCD_SCREEN_SEN) { + /* Wait for vertical sync period */ + lcd->intstatus = LCD_INT_SS; + while ((lcd->intstatus & LCD_INT_SS) == 0) { + au_sync(); + } + + lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/ + + do { + lcd->intstatus = lcd->intstatus; /*clear interrupts*/ + au_sync(); + /*wait for controller to shut down*/ + } while ((lcd->intstatus & LCD_INT_SD) == 0); + + /* Call shutdown of current panel (if up) */ + /* this must occur last, because if an external clock is driving + the controller, the clock cannot be turned off before first + shutting down the controller. + */ + if (panel->device_shutdown != NULL) + panel->device_shutdown(); + } + + /* Newpanel == NULL indicates a shutdown operation only */ + if (newpanel == NULL) + return; + + panel = newpanel; + + printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres); + + /* + * Setup clocking if internal LCD clock source (assumes sys_auxpll valid) + */ + if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT)) + { + uint32 sys_clksrc; + au_writel(panel->mode_auxpll, SYS_AUXPLL); + sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f; + sys_clksrc |= panel->mode_toyclksrc; + au_writel(sys_clksrc, SYS_CLKSRC); + } + + /* + * Configure panel timings + */ + lcd->screen = panel->mode_screen; + lcd->horztiming = panel->mode_horztiming; + lcd->verttiming = panel->mode_verttiming; + lcd->clkcontrol = panel->mode_clkcontrol; + lcd->pwmdiv = panel->mode_pwmdiv; + lcd->pwmhi = panel->mode_pwmhi; + lcd->outmask = panel->mode_outmask; + lcd->fifoctrl = panel->mode_fifoctrl; + au_sync(); + + /* fixme: Check window settings to make sure still valid + * for new geometry */ +#if 0 + au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos); + au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos); + au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos); + au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos); +#endif + lcd->winenable = winenable; + + /* + * Re-enable screen now that it is configured + */ + lcd->screen |= LCD_SCREEN_SEN; + au_sync(); + + /* Call init of panel */ + if (panel->device_init != NULL) panel->device_init(); + + /* FIX!!!! not appropriate on panel change!!! Global setup/init */ + lcd->intenable = 0; + lcd->intstatus = ~0; + lcd->backcolor = win->mode_backcolor; + + /* Setup Color Key - FIX!!! */ + lcd->colorkey = win->mode_colorkey; + lcd->colorkeymsk = win->mode_colorkeymsk; + + /* Setup HWCursor - FIX!!! Need to support this eventually */ + lcd->hwc.cursorctrl = 0; + lcd->hwc.cursorpos = 0; + lcd->hwc.cursorcolor0 = 0; + lcd->hwc.cursorcolor1 = 0; + lcd->hwc.cursorcolor2 = 0; + lcd->hwc.cursorcolor3 = 0; + + +#if 0 +#define D(X) printk("%25s: %08X\n", #X, X) + D(lcd->screen); + D(lcd->horztiming); + D(lcd->verttiming); + D(lcd->clkcontrol); + D(lcd->pwmdiv); + D(lcd->pwmhi); + D(lcd->outmask); + D(lcd->fifoctrl); + D(lcd->window[0].winctrl0); + D(lcd->window[0].winctrl1); + D(lcd->window[0].winctrl2); + D(lcd->window[0].winbuf0); + D(lcd->window[0].winbuf1); + D(lcd->window[0].winbufctrl); + D(lcd->window[1].winctrl0); + D(lcd->window[1].winctrl1); + D(lcd->window[1].winctrl2); + D(lcd->window[1].winbuf0); + D(lcd->window[1].winbuf1); + D(lcd->window[1].winbufctrl); + D(lcd->window[2].winctrl0); + D(lcd->window[2].winctrl1); + D(lcd->window[2].winctrl2); + D(lcd->window[2].winbuf0); + D(lcd->window[2].winbuf1); + D(lcd->window[2].winbufctrl); + D(lcd->window[3].winctrl0); + D(lcd->window[3].winctrl1); + D(lcd->window[3].winctrl2); + D(lcd->window[3].winbuf0); + D(lcd->window[3].winbuf1); + D(lcd->window[3].winbufctrl); + D(lcd->winenable); + D(lcd->intenable); + D(lcd->intstatus); + D(lcd->backcolor); + D(lcd->winenable); + D(lcd->colorkey); + D(lcd->colorkeymsk); + D(lcd->hwc.cursorctrl); + D(lcd->hwc.cursorpos); + D(lcd->hwc.cursorcolor0); + D(lcd->hwc.cursorcolor1); + D(lcd->hwc.cursorcolor2); + D(lcd->hwc.cursorcolor3); +#endif +} + +static void au1200_setmode(struct au1200fb_device *fbdev) +{ + int plane = fbdev->plane; + /* Window/plane setup */ + lcd->window[plane].winctrl1 = ( 0 + | LCD_WINCTRL1_PRI_N(plane) + | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */ + ) ; + + au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos); + + lcd->window[plane].winctrl2 = ( 0 + | LCD_WINCTRL2_CKMODE_00 + | LCD_WINCTRL2_DBM + | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) + | LCD_WINCTRL2_SCX_1 + | LCD_WINCTRL2_SCY_1 + ) ; + lcd->winenable |= win->w[plane].mode_winenable; + au_sync(); +} + + +/* Inline helpers */ + +/*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ +/*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ + +#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN) + +/* Bitfields format supported by the controller. */ +static struct fb_bitfield rgb_bitfields[][4] = { + /* Red, Green, Blue, Transp */ + [LCD_WINCTRL1_FRM_16BPP655 >> 25] = + { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_16BPP565 >> 25] = + { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_16BPP556 >> 25] = + { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] = + { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] = + { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] = + { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } }, + + [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] = + { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } }, + + [LCD_WINCTRL1_FRM_24BPP >> 25] = + { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_32BPP >> 25] = + { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } }, +}; + +/*-------------------------------------------------------------------------*/ + +/* Helpers */ + +static void au1200fb_update_fbinfo(struct fb_info *fbi) +{ + /* FIX!!!! This also needs to take the window pixel format into account!!! */ + + /* Update var-dependent FB info */ + if (panel_is_color(panel)) { + if (fbi->var.bits_per_pixel <= 8) { + /* palettized */ + fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR; + fbi->fix.line_length = fbi->var.xres_virtual / + (8/fbi->var.bits_per_pixel); + } else { + /* non-palettized */ + fbi->fix.visual = FB_VISUAL_TRUECOLOR; + fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8); + } + } else { + /* mono FIX!!! mono 8 and 4 bits */ + fbi->fix.visual = FB_VISUAL_MONO10; + fbi->fix.line_length = fbi->var.xres_virtual / 8; + } + + fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual; + print_dbg("line length: %d\n", fbi->fix.line_length); + print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel); +} + +/*-------------------------------------------------------------------------*/ + +/* AU1200 framebuffer driver */ + +/* fb_check_var + * Validate var settings with hardware restrictions and modify it if necessary + */ +static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, + struct fb_info *fbi) +{ + struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; + u32 pixclock; + int screen_size, plane; + + plane = fbdev->plane; + + /* Make sure that the mode respect all LCD controller and + * panel restrictions. */ + var->xres = win->w[plane].xres; + var->yres = win->w[plane].yres; + + /* No need for virtual resolution support */ + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + + var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1); + + screen_size = var->xres_virtual * var->yres_virtual; + if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8); + else screen_size /= (8/var->bits_per_pixel); + + if (fbdev->fb_len < screen_size) + return -EINVAL; /* Virtual screen is to big, abort */ + + /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */ + /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel + * clock can only be obtain by dividing this value by an even integer. + * Fallback to a slower pixel clock if necessary. */ + pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); + pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2)); + + if (AU1200_LCD_MAX_CLK % pixclock) { + int diff = AU1200_LCD_MAX_CLK % pixclock; + pixclock -= diff; + } + + var->pixclock = KHZ2PICOS(pixclock/1000); +#if 0 + if (!panel_is_active(panel)) { + int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1; + + if (!panel_is_color(panel) + && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) { + /* STN 8bit mono panel support is up to 6MHz pixclock */ + var->pixclock = KHZ2PICOS(6000); + } else if (!pcd) { + /* Other STN panel support is up to 12MHz */ + var->pixclock = KHZ2PICOS(12000); + } + } +#endif + /* Set bitfield accordingly */ + switch (var->bits_per_pixel) { + case 16: + { + /* 16bpp True color. + * These must be set to MATCH WINCTRL[FORM] */ + int idx; + idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; + var->red = rgb_bitfields[idx][0]; + var->green = rgb_bitfields[idx][1]; + var->blue = rgb_bitfields[idx][2]; + var->transp = rgb_bitfields[idx][3]; + break; + } + + case 32: + { + /* 32bpp True color. + * These must be set to MATCH WINCTRL[FORM] */ + int idx; + idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; + var->red = rgb_bitfields[idx][0]; + var->green = rgb_bitfields[idx][1]; + var->blue = rgb_bitfields[idx][2]; + var->transp = rgb_bitfields[idx][3]; + break; + } + default: + print_dbg("Unsupported depth %dbpp", var->bits_per_pixel); + return -EINVAL; + } + + return 0; +} + +/* fb_set_par + * Set hardware with var settings. This will enable the controller with a + * specific mode, normally validated with the fb_check_var method + */ +static int au1200fb_fb_set_par(struct fb_info *fbi) +{ + struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; + + au1200fb_update_fbinfo(fbi); + au1200_setmode(fbdev); + + return 0; +} + +/* fb_setcolreg + * Set color in LCD palette. + */ +static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, struct fb_info *fbi) +{ + volatile u32 *palette = lcd->palette; + u32 value; + + if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1)) + return -EINVAL; + + if (fbi->var.grayscale) { + /* Convert color to grayscale */ + red = green = blue = + (19595 * red + 38470 * green + 7471 * blue) >> 16; + } + + if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) { + /* Place color in the pseudopalette */ + if (regno > 16) + return -EINVAL; + + palette = (u32*) fbi->pseudo_palette; + + red >>= (16 - fbi->var.red.length); + green >>= (16 - fbi->var.green.length); + blue >>= (16 - fbi->var.blue.length); + + value = (red << fbi->var.red.offset) | + (green << fbi->var.green.offset)| + (blue << fbi->var.blue.offset); + value &= 0xFFFF; + + } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) { + /* COLOR TFT PALLETTIZED (use RGB 565) */ + value = (red & 0xF800)|((green >> 5) & + 0x07E0)|((blue >> 11) & 0x001F); + value &= 0xFFFF; + + } else if (0 /*panel_is_color(fbdev->panel)*/) { + /* COLOR STN MODE */ + value = 0x1234; + value &= 0xFFF; + } else { + /* MONOCHROME MODE */ + value = (green >> 12) & 0x000F; + value &= 0xF; + } + + palette[regno] = value; + + return 0; +} + +/* fb_blank + * Blank the screen. Depending on the mode, the screen will be + * activated with the backlight color, or desactivated + */ +static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi) +{ + /* Short-circuit screen blanking */ + if (noblanking) + return 0; + + switch (blank_mode) { + + case FB_BLANK_UNBLANK: + case FB_BLANK_NORMAL: + /* printk("turn on panel\n"); */ + au1200_setpanel(panel); + break; + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_POWERDOWN: + /* printk("turn off panel\n"); */ + au1200_setpanel(NULL); + break; + default: + break; + + } + + /* FB_BLANK_NORMAL is a soft blank */ + return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0; +} + +/* fb_mmap + * Map video memory in user space. We don't use the generic fb_mmap + * method mainly to allow the use of the TLB streaming flag (CCA=6) + */ +static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) + +{ + unsigned int len; + unsigned long start=0, off; + struct au1200fb_device *fbdev = (struct au1200fb_device *) info; + +#ifdef CONFIG_PM + au1xxx_pm_access(LCD_pm_dev); +#endif + + if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { + return -EINVAL; + } + + start = fbdev->fb_phys & PAGE_MASK; + len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); + + off = vma->vm_pgoff << PAGE_SHIFT; + + if ((vma->vm_end - vma->vm_start + off) > len) { + return -EINVAL; + } + + off += start; + vma->vm_pgoff = off >> PAGE_SHIFT; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */ + + vma->vm_flags |= VM_IO; + + return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + + return 0; +} + +static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) +{ + + unsigned int hi1, divider; + + /* SCREEN_SIZE: user cannot reset size, must switch panel choice */ + + if (pdata->flags & SCREEN_BACKCOLOR) + lcd->backcolor = pdata->backcolor; + + if (pdata->flags & SCREEN_BRIGHTNESS) { + + // limit brightness pwm duty to >= 30/1600 + if (pdata->brightness < 30) { + pdata->brightness = 30; + } + divider = (lcd->pwmdiv & 0x3FFFF) + 1; + hi1 = (lcd->pwmhi >> 16) + 1; + hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8); + lcd->pwmhi &= 0xFFFF; + lcd->pwmhi |= (hi1 << 16); + } + + if (pdata->flags & SCREEN_COLORKEY) + lcd->colorkey = pdata->colorkey; + + if (pdata->flags & SCREEN_MASK) + lcd->colorkeymsk = pdata->mask; + au_sync(); +} + +static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) +{ + unsigned int hi1, divider; + + pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1; + pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1; + + pdata->backcolor = lcd->backcolor; + pdata->colorkey = lcd->colorkey; + pdata->mask = lcd->colorkeymsk; + + // brightness + hi1 = (lcd->pwmhi >> 16) + 1; + divider = (lcd->pwmdiv & 0x3FFFF) + 1; + pdata->brightness = ((hi1 << 8) / divider) - 1; + au_sync(); +} + +static void set_window(unsigned int plane, + struct au1200_lcd_window_regs_t *pdata) +{ + unsigned int val, bpp; + + /* Window control register 0 */ + if (pdata->flags & WIN_POSITION) { + val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX | + LCD_WINCTRL0_OY); + val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX); + val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY); + lcd->window[plane].winctrl0 = val; + } + if (pdata->flags & WIN_ALPHA_COLOR) { + val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A); + val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A); + lcd->window[plane].winctrl0 = val; + } + if (pdata->flags & WIN_ALPHA_MODE) { + val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN); + val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN); + lcd->window[plane].winctrl0 = val; + } + + /* Window control register 1 */ + if (pdata->flags & WIN_PRIORITY) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI); + val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI); + lcd->window[plane].winctrl1 = val; + } + if (pdata->flags & WIN_CHANNEL) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE); + val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE); + lcd->window[plane].winctrl1 = val; + } + if (pdata->flags & WIN_BUFFER_FORMAT) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM); + val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM); + lcd->window[plane].winctrl1 = val; + } + if (pdata->flags & WIN_COLOR_ORDER) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO); + val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO); + lcd->window[plane].winctrl1 = val; + } + if (pdata->flags & WIN_PIXEL_ORDER) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO); + val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO); + lcd->window[plane].winctrl1 = val; + } + if (pdata->flags & WIN_SIZE) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX | + LCD_WINCTRL1_SZY); + val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX); + val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY); + lcd->window[plane].winctrl1 = val; + /* program buffer line width */ + bpp = winbpp(val) / 8; + val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX); + val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX); + lcd->window[plane].winctrl2 = val; + } + + /* Window control register 2 */ + if (pdata->flags & WIN_COLORKEY_MODE) { + val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE); + val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE); + lcd->window[plane].winctrl2 = val; + } + if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) { + val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM); + val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM); + lcd->window[plane].winctrl2 = val; + } + if (pdata->flags & WIN_RAM_ARRAY_MODE) { + val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM); + val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM); + lcd->window[plane].winctrl2 = val; + } + + /* Buffer line width programmed with WIN_SIZE */ + + if (pdata->flags & WIN_BUFFER_SCALE) { + val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX | + LCD_WINCTRL2_SCY); + val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX); + val |= ((pdata->ysize) & LCD_WINCTRL2_SCY); + lcd->window[plane].winctrl2 = val; + } + + if (pdata->flags & WIN_ENABLE) { + val = lcd->winenable; + val &= ~(1<enable & 1) << plane; + lcd->winenable = val; + } + au_sync(); +} + +static void get_window(unsigned int plane, + struct au1200_lcd_window_regs_t *pdata) +{ + /* Window control register 0 */ + pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21; + pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10; + pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2; + pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1; + + /* Window control register 1 */ + pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30; + pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29; + pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25; + pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24; + pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22; + pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1; + pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1; + + /* Window control register 2 */ + pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24; + pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23; + pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21; + + pdata->enable = (lcd->winenable >> plane) & 1; + au_sync(); +} + +static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + int plane; + int val; + +#ifdef CONFIG_PM + au1xxx_pm_access(LCD_pm_dev); +#endif + + plane = fbinfo2index(info); + print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); + + if (cmd == AU1200_LCD_FB_IOCTL) { + struct au1200_lcd_iodata_t iodata; + + if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata))) + return -EFAULT; + + print_dbg("FB IOCTL called\n"); + + switch (iodata.subcmd) { + case AU1200_LCD_SET_SCREEN: + print_dbg("AU1200_LCD_SET_SCREEN\n"); + set_global(cmd, &iodata.global); + break; + + case AU1200_LCD_GET_SCREEN: + print_dbg("AU1200_LCD_GET_SCREEN\n"); + get_global(cmd, &iodata.global); + break; + + case AU1200_LCD_SET_WINDOW: + print_dbg("AU1200_LCD_SET_WINDOW\n"); + set_window(plane, &iodata.window); + break; + + case AU1200_LCD_GET_WINDOW: + print_dbg("AU1200_LCD_GET_WINDOW\n"); + get_window(plane, &iodata.window); + break; + + case AU1200_LCD_SET_PANEL: + print_dbg("AU1200_LCD_SET_PANEL\n"); + if ((iodata.global.panel_choice >= 0) && + (iodata.global.panel_choice < + NUM_PANELS)) + { + struct panel_settings *newpanel; + panel_index = iodata.global.panel_choice; + newpanel = &known_lcd_panels[panel_index]; + au1200_setpanel(newpanel); + } + break; + + case AU1200_LCD_GET_PANEL: + print_dbg("AU1200_LCD_GET_PANEL\n"); + iodata.global.panel_choice = panel_index; + break; + + default: + return -EINVAL; + } + + val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata)); + if (val) { + print_dbg("error: could not copy %d bytes\n", val); + return -EFAULT; + } + } + + return 0; +} + + +static struct fb_ops au1200fb_fb_ops = { + .owner = THIS_MODULE, + .fb_check_var = au1200fb_fb_check_var, + .fb_set_par = au1200fb_fb_set_par, + .fb_setcolreg = au1200fb_fb_setcolreg, + .fb_blank = au1200fb_fb_blank, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_sync = NULL, + .fb_ioctl = au1200fb_ioctl, + .fb_mmap = au1200fb_fb_mmap, +}; + +/*-------------------------------------------------------------------------*/ + +static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs) +{ + /* Nothing to do for now, just clear any pending interrupt */ + lcd->intstatus = lcd->intstatus; + au_sync(); + + return IRQ_HANDLED; +} + +/*-------------------------------------------------------------------------*/ + +/* AU1200 LCD device probe helpers */ + +static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) +{ + struct fb_info *fbi = &fbdev->fb_info; + int bpp; + + memset(fbi, 0, sizeof(struct fb_info)); + fbi->fbops = &au1200fb_fb_ops; + + bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); + + /* Copy monitor specs from panel data */ + /* fixme: we're setting up LCD controller windows, so these dont give a + damn as to what the monitor specs are (the panel itself does, but that + isnt done here...so maybe need a generic catchall monitor setting??? */ + memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs)); + + /* We first try the user mode passed in argument. If that failed, + * or if no one has been specified, we default to the first mode of the + * panel list. Note that after this call, var data will be set */ + if (!fb_find_mode(&fbi->var, + fbi, + NULL, /* drv_info.opt_mode, */ + fbi->monspecs.modedb, + fbi->monspecs.modedb_len, + fbi->monspecs.modedb, + bpp)) { + + print_err("Cannot find valid mode for panel %s", panel->name); + return -EFAULT; + } + + fbi->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); + if (!fbi->pseudo_palette) { + return -ENOMEM; + } + memset(fbi->pseudo_palette, 0, sizeof(u32) * 16); + + if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { + print_err("Fail to allocate colormap (%d entries)", + AU1200_LCD_NBR_PALETTE_ENTRIES); + kfree(fbi->pseudo_palette); + return -EFAULT; + } + + strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id)); + fbi->fix.smem_start = fbdev->fb_phys; + fbi->fix.smem_len = fbdev->fb_len; + fbi->fix.type = FB_TYPE_PACKED_PIXELS; + fbi->fix.xpanstep = 0; + fbi->fix.ypanstep = 0; + fbi->fix.mmio_start = 0; + fbi->fix.mmio_len = 0; + fbi->fix.accel = FB_ACCEL_NONE; + + fbi->screen_base = (char __iomem *) fbdev->fb_mem; + + au1200fb_update_fbinfo(fbi); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* AU1200 LCD controller device driver */ + +static int au1200fb_drv_probe(struct device *dev) +{ + struct au1200fb_device *fbdev; + unsigned long page; + int bpp, plane, ret; + + if (!dev) + return -EINVAL; + + for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { + bpp = winbpp(win->w[plane].mode_winctrl1); + if (win->w[plane].xres == 0) + win->w[plane].xres = panel->Xres; + if (win->w[plane].yres == 0) + win->w[plane].yres = panel->Yres; + + fbdev = &_au1200fb_devices[plane]; + memset(fbdev, 0, sizeof(struct au1200fb_device)); + fbdev->plane = plane; + + /* Allocate the framebuffer to the maximum screen size */ + fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; + + fbdev->fb_mem = dma_alloc_noncoherent(dev, + PAGE_ALIGN(fbdev->fb_len), + &fbdev->fb_phys, GFP_KERNEL); + if (!fbdev->fb_mem) { + print_err("fail to allocate frambuffer (size: %dK))", + fbdev->fb_len / 1024); + return -ENOMEM; + } + + /* + * Set page reserved so that mmap will work. This is necessary + * since we'll be remapping normal memory. + */ + for (page = (unsigned long)fbdev->fb_phys; + page < PAGE_ALIGN((unsigned long)fbdev->fb_phys + + fbdev->fb_len); + page += PAGE_SIZE) { + SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */ + } + print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); + print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); + + /* Init FB data */ + if ((ret = au1200fb_init_fbinfo(fbdev)) < 0) + goto failed; + + /* Register new framebuffer */ + if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) { + print_err("cannot register new framebuffer"); + goto failed; + } + + au1200fb_fb_set_par(&fbdev->fb_info); + +#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) + if (plane == 0) + if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) { + /* Start display and show logo on boot */ + fb_set_cmap(&fbdev->fb_info.cmap, + &fbdev->fb_info); + + fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR); + } +#endif + } + + /* Now hook interrupt too */ + if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq, + SA_INTERRUPT | SA_SHIRQ, "lcd", (void *)dev)) < 0) { + print_err("fail to request interrupt line %d (err: %d)", + AU1200_LCD_INT, ret); + goto failed; + } + + return 0; + +failed: + /* NOTE: This only does the current plane/window that failed; others are still active */ + if (fbdev->fb_mem) + dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), + fbdev->fb_mem, fbdev->fb_phys); + if (fbdev->fb_info.cmap.len != 0) + fb_dealloc_cmap(&fbdev->fb_info.cmap); + if (fbdev->fb_info.pseudo_palette) + kfree(fbdev->fb_info.pseudo_palette); + if (plane == 0) + free_irq(AU1200_LCD_INT, (void*)dev); + return ret; +} + +static int au1200fb_drv_remove(struct device *dev) +{ + struct au1200fb_device *fbdev; + int plane; + + if (!dev) + return -ENODEV; + + /* Turn off the panel */ + au1200_setpanel(NULL); + + for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) + { + fbdev = &_au1200fb_devices[plane]; + + /* Clean up all probe data */ + unregister_framebuffer(&fbdev->fb_info); + if (fbdev->fb_mem) + dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), + fbdev->fb_mem, fbdev->fb_phys); + if (fbdev->fb_info.cmap.len != 0) + fb_dealloc_cmap(&fbdev->fb_info.cmap); + if (fbdev->fb_info.pseudo_palette) + kfree(fbdev->fb_info.pseudo_palette); + } + + free_irq(AU1200_LCD_INT, (void *)dev); + + return 0; +} + +#ifdef CONFIG_PM +static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level) +{ + /* TODO */ + return 0; +} + +static int au1200fb_drv_resume(struct device *dev, u32 level) +{ + /* TODO */ + return 0; +} +#endif /* CONFIG_PM */ + +static struct device_driver au1200fb_driver = { + .name = "au1200-lcd", + .bus = &platform_bus_type, + .probe = au1200fb_drv_probe, + .remove = au1200fb_drv_remove, +#ifdef CONFIG_PM + .suspend = au1200fb_drv_suspend, + .resume = au1200fb_drv_resume, +#endif +}; + +/*-------------------------------------------------------------------------*/ + +/* Kernel driver */ + +static void au1200fb_setup(void) +{ + char* options = NULL; + char* this_opt; + int num_panels = ARRAY_SIZE(known_lcd_panels); + int panel_idx = -1; + + fb_get_options(DRIVER_NAME, &options); + + if (options) { + while ((this_opt = strsep(&options,",")) != NULL) { + /* Panel option - can be panel name, + * "bs" for board-switch, or number/index */ + if (!strncmp(this_opt, "panel:", 6)) { + int i; + long int li; + char *endptr; + this_opt += 6; + /* First check for index, which allows + * to short circuit this mess */ + li = simple_strtol(this_opt, &endptr, 0); + if (*endptr == '\0') { + panel_idx = (int)li; + } + else if (strcmp(this_opt, "bs") == 0) { + extern int board_au1200fb_panel(void); + panel_idx = board_au1200fb_panel(); + } + + else + for (i = 0; i < num_panels; i++) { + if (!strcmp(this_opt, known_lcd_panels[i].name)) { + panel_idx = i; + break; + } + } + + if ((panel_idx < 0) || (panel_idx >= num_panels)) { + print_warn("Panel %s not supported!", this_opt); + } + else + panel_index = panel_idx; + } + + else if (strncmp(this_opt, "nohwcursor", 10) == 0) { + nohwcursor = 1; + } + + /* Unsupported option */ + else { + print_warn("Unsupported option \"%s\"", this_opt); + } + } + } +} + +#ifdef CONFIG_PM +static int au1200fb_pm_callback(au1xxx_power_dev_t *dev, + au1xxx_request_t request, void *data) { + int retval = -1; + unsigned int d = 0; + unsigned int brightness = 0; + + if (request == AU1XXX_PM_SLEEP) { + board_au1200fb_panel_shutdown(); + } + else if (request == AU1XXX_PM_WAKEUP) { + if(dev->prev_state == SLEEP_STATE) + { + int plane; + au1200_setpanel(panel); + for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { + struct au1200fb_device *fbdev; + fbdev = &_au1200fb_devices[plane]; + au1200fb_fb_set_par(&fbdev->fb_info); + } + } + + d = *((unsigned int*)data); + if(d <=10) brightness = 26; + else if(d<=20) brightness = 51; + else if(d<=30) brightness = 77; + else if(d<=40) brightness = 102; + else if(d<=50) brightness = 128; + else if(d<=60) brightness = 153; + else if(d<=70) brightness = 179; + else if(d<=80) brightness = 204; + else if(d<=90) brightness = 230; + else brightness = 255; + set_brightness(brightness); + } else if (request == AU1XXX_PM_GETSTATUS) { + return dev->cur_state; + } else if (request == AU1XXX_PM_ACCESS) { + if (dev->cur_state != SLEEP_STATE) + return retval; + else { + au1200_setpanel(panel); + } + } else if (request == AU1XXX_PM_IDLE) { + } else if (request == AU1XXX_PM_CLEANUP) { + } + + return retval; +} +#endif + +static int __init au1200fb_init(void) +{ + print_info("" DRIVER_DESC ""); + + /* Setup driver with options */ + au1200fb_setup(); + + /* Point to the panel selected */ + panel = &known_lcd_panels[panel_index]; + win = &windows[window_index]; + + printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); + printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); + + /* Kickstart the panel, the framebuffers/windows come soon enough */ + au1200_setpanel(panel); + + #ifdef CONFIG_PM + LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL); + if ( LCD_pm_dev == NULL) + printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n"); + else + printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); + #endif + + return driver_register(&au1200fb_driver); +} + +static void __exit au1200fb_cleanup(void) +{ + driver_unregister(&au1200fb_driver); +} + +module_init(au1200fb_init); +module_exit(au1200fb_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); +/* + * BRIEF MODULE DESCRIPTION + * Au1200 LCD Driver. + * + * Copyright 2004-2005 AMD + * Author: AMD + * + * Based on: + * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device + * Created 28 Dec 1997 by Geert Uytterhoeven + * + * 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 SOFTWARE IS PROVIDED ``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 AUTHOR 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. + * + * 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 +#include +#include + +#include +#include "au1200fb.h" + +#ifdef CONFIG_PM +#include +#endif + +#ifndef CONFIG_FB_AU1200_DEVS +#define CONFIG_FB_AU1200_DEVS 4 +#endif + +#define DRIVER_NAME "au1200fb" +#define DRIVER_DESC "LCD controller driver for AU1200 processors" + +#define DEBUG 1 + +#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) +#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) +#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) + +#if DEBUG +#define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg) +#else +#define print_dbg(f, arg...) do {} while (0) +#endif + + +#define AU1200_LCD_FB_IOCTL 0x46FF + +#define AU1200_LCD_SET_SCREEN 1 +#define AU1200_LCD_GET_SCREEN 2 +#define AU1200_LCD_SET_WINDOW 3 +#define AU1200_LCD_GET_WINDOW 4 +#define AU1200_LCD_SET_PANEL 5 +#define AU1200_LCD_GET_PANEL 6 + +#define SCREEN_SIZE (1<< 1) +#define SCREEN_BACKCOLOR (1<< 2) +#define SCREEN_BRIGHTNESS (1<< 3) +#define SCREEN_COLORKEY (1<< 4) +#define SCREEN_MASK (1<< 5) + +struct au1200_lcd_global_regs_t { + unsigned int flags; + unsigned int xsize; + unsigned int ysize; + unsigned int backcolor; + unsigned int brightness; + unsigned int colorkey; + unsigned int mask; + unsigned int panel_choice; + char panel_desc[80]; + +}; + +#define WIN_POSITION (1<< 0) +#define WIN_ALPHA_COLOR (1<< 1) +#define WIN_ALPHA_MODE (1<< 2) +#define WIN_PRIORITY (1<< 3) +#define WIN_CHANNEL (1<< 4) +#define WIN_BUFFER_FORMAT (1<< 5) +#define WIN_COLOR_ORDER (1<< 6) +#define WIN_PIXEL_ORDER (1<< 7) +#define WIN_SIZE (1<< 8) +#define WIN_COLORKEY_MODE (1<< 9) +#define WIN_DOUBLE_BUFFER_MODE (1<< 10) +#define WIN_RAM_ARRAY_MODE (1<< 11) +#define WIN_BUFFER_SCALE (1<< 12) +#define WIN_ENABLE (1<< 13) + +struct au1200_lcd_window_regs_t { + unsigned int flags; + unsigned int xpos; + unsigned int ypos; + unsigned int alpha_color; + unsigned int alpha_mode; + unsigned int priority; + unsigned int channel; + unsigned int buffer_format; + unsigned int color_order; + unsigned int pixel_order; + unsigned int xsize; + unsigned int ysize; + unsigned int colorkey_mode; + unsigned int double_buffer_mode; + unsigned int ram_array_mode; + unsigned int xscale; + unsigned int yscale; + unsigned int enable; +}; + + +struct au1200_lcd_iodata_t { + unsigned int subcmd; + struct au1200_lcd_global_regs_t global; + struct au1200_lcd_window_regs_t window; +}; + +#if defined(__BIG_ENDIAN) +#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11 +#else +#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00 +#endif +#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565 + +/* Private, per-framebuffer management information (independent of the panel itself) */ +struct au1200fb_device { + struct fb_info fb_info; /* FB driver info record */ + + int plane; + unsigned char* fb_mem; /* FrameBuffer memory map */ + unsigned int fb_len; + dma_addr_t fb_phys; +}; + +static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; +/********************************************************************/ + +/* LCD controller restrictions */ +#define AU1200_LCD_MAX_XRES 1280 +#define AU1200_LCD_MAX_YRES 1024 +#define AU1200_LCD_MAX_BPP 32 +#define AU1200_LCD_MAX_CLK 96000000 /* fixme: this needs to go away ? */ +#define AU1200_LCD_NBR_PALETTE_ENTRIES 256 + +/* Default number of visible screen buffer to allocate */ +#define AU1200FB_NBR_VIDEO_BUFFERS 1 + +/********************************************************************/ + +static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; +static int window_index = 2; /* default is zero */ +static int panel_index = 2; /* default is zero */ +static struct window_settings *win; +static struct panel_settings *panel; +static int noblanking = 1; +static int nohwcursor = 0; + +struct window_settings { + unsigned char name[64]; + uint32 mode_backcolor; + uint32 mode_colorkey; + uint32 mode_colorkeymsk; + struct { + int xres; + int yres; + int xpos; + int ypos; + uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */ + uint32 mode_winenable; + } w[4]; +}; + +#if defined(__BIG_ENDIAN) +#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00 +#else +#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01 +#endif + +extern int board_au1200fb_panel_init (void); +extern int board_au1200fb_panel_shutdown (void); + +#ifdef CONFIG_PM +int au1200fb_pm_callback(au1xxx_power_dev_t *dev, + au1xxx_request_t request, void *data); +au1xxx_power_dev_t *LCD_pm_dev; +#endif + +/* + * Default window configurations + */ +static struct window_settings windows[] = { + { /* Index 0 */ + "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", + /* mode_backcolor */ 0x006600ff, + /* mode_colorkey,msk*/ 0, 0, + { + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP, + /* mode_winenable*/ LCD_WINENABLE_WEN0, + }, + { + /* xres, yres, xpos, ypos */ 100, 100, 100, 100, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP | + LCD_WINCTRL1_PIPE, + /* mode_winenable*/ LCD_WINENABLE_WEN1, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP, + /* mode_winenable*/ 0, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP | + LCD_WINCTRL1_PIPE, + /* mode_winenable*/ 0, + }, + }, + }, + + { /* Index 1 */ + "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", + /* mode_backcolor */ 0x006600ff, + /* mode_colorkey,msk*/ 0, 0, + { + { + /* xres, yres, xpos, ypos */ 320, 240, 5, 5, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP | + LCD_WINCTRL1_PO_00, + /* mode_winenable*/ LCD_WINENABLE_WEN0, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 + | LCD_WINCTRL1_PO_16BPP, + /* mode_winenable*/ 0, + }, + { + /* xres, yres, xpos, ypos */ 100, 100, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP | + LCD_WINCTRL1_PIPE, + /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, + }, + { + /* xres, yres, xpos, ypos */ 200, 25, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP | + LCD_WINCTRL1_PIPE, + /* mode_winenable*/ 0, + }, + }, + }, + { /* Index 2 */ + "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", + /* mode_backcolor */ 0x006600ff, + /* mode_colorkey,msk*/ 0, 0, + { + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP, + /* mode_winenable*/ LCD_WINENABLE_WEN0, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP, + /* mode_winenable*/ 0, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP | + LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE, + /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, + }, + { + /* xres, yres, xpos, ypos */ 0, 0, 0, 0, + /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | + LCD_WINCTRL1_PO_16BPP | + LCD_WINCTRL1_PIPE, + /* mode_winenable*/ 0, + }, + }, + }, + /* Need VGA 640 @ 24bpp, @ 32bpp */ + /* Need VGA 800 @ 24bpp, @ 32bpp */ + /* Need VGA 1024 @ 24bpp, @ 32bpp */ +}; + +/* + * Controller configurations for various panels. + */ + +struct panel_settings +{ + const char name[25]; /* Full name _ */ + + struct fb_monspecs monspecs; /* FB monitor specs */ + + /* panel timings */ + uint32 mode_screen; + uint32 mode_horztiming; + uint32 mode_verttiming; + uint32 mode_clkcontrol; + uint32 mode_pwmdiv; + uint32 mode_pwmhi; + uint32 mode_outmask; + uint32 mode_fifoctrl; + uint32 mode_toyclksrc; + uint32 mode_backlight; + uint32 mode_auxpll; + int (*device_init)(void); + int (*device_shutdown)(void); +#define Xres min_xres +#define Yres min_yres + u32 min_xres; /* Minimum horizontal resolution */ + u32 max_xres; /* Maximum horizontal resolution */ + u32 min_yres; /* Minimum vertical resolution */ + u32 max_yres; /* Maximum vertical resolution */ +}; + +/********************************************************************/ +/* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */ + +/* List of panels known to work with the AU1200 LCD controller. + * To add a new panel, enter the same specifications as the + * Generic_TFT one, and MAKE SURE that it doesn't conflicts + * with the controller restrictions. Restrictions are: + * + * STN color panels: max_bpp <= 12 + * STN mono panels: max_bpp <= 4 + * TFT panels: max_bpp <= 16 + * max_xres <= 800 + * max_yres <= 600 + */ +static struct panel_settings known_lcd_panels[] = +{ + [0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */ + .name = "QVGA_320x240", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = LCD_SCREEN_SX_N(320) | + LCD_SCREEN_SY_N(240), + .mode_horztiming = 0x00c4623b, + .mode_verttiming = 0x00502814, + .mode_clkcontrol = 0x00020002, /* /4=24Mhz */ + .mode_pwmdiv = 0x00000000, + .mode_pwmhi = 0x00000000, + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = NULL, + .device_shutdown = NULL, + 320, 320, + 240, 240, + }, + + [1] = { /* VGA 640x480 H:30.3kHz V:58Hz */ + .name = "VGA_640x480", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = 0x13f9df80, + .mode_horztiming = 0x003c5859, + .mode_verttiming = 0x00741201, + .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ + .mode_pwmdiv = 0x00000000, + .mode_pwmhi = 0x00000000, + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = NULL, + .device_shutdown = NULL, + 640, 480, + 640, 480, + }, + + [2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */ + .name = "SVGA_800x600", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = 0x18fa5780, + .mode_horztiming = 0x00dc7e77, + .mode_verttiming = 0x00584805, + .mode_clkcontrol = 0x00020000, /* /2=48Mhz */ + .mode_pwmdiv = 0x00000000, + .mode_pwmhi = 0x00000000, + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = NULL, + .device_shutdown = NULL, + 800, 800, + 600, 600, + }, + + [3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */ + .name = "XVGA_1024x768", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = 0x1ffaff80, + .mode_horztiming = 0x007d0e57, + .mode_verttiming = 0x00740a01, + .mode_clkcontrol = 0x000A0000, /* /1 */ + .mode_pwmdiv = 0x00000000, + .mode_pwmhi = 0x00000000, + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 6, /* 72MHz AUXPLL */ + .device_init = NULL, + .device_shutdown = NULL, + 1024, 1024, + 768, 768, + }, + + [4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */ + .name = "XVGA_1280x1024", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = 0x27fbff80, + .mode_horztiming = 0x00cdb2c7, + .mode_verttiming = 0x00600002, + .mode_clkcontrol = 0x000A0000, /* /1 */ + .mode_pwmdiv = 0x00000000, + .mode_pwmhi = 0x00000000, + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 10, /* 120MHz AUXPLL */ + .device_init = NULL, + .device_shutdown = NULL, + 1280, 1280, + 1024, 1024, + }, + + [5] = { /* Samsung 1024x768 TFT */ + .name = "Samsung_1024x768_TFT", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = 0x1ffaff80, + .mode_horztiming = 0x018cc677, + .mode_verttiming = 0x00241217, + .mode_clkcontrol = 0x00000000, /* SCB 0x1 /4=24Mhz */ + .mode_pwmdiv = 0x8000063f, /* SCB 0x0 */ + .mode_pwmhi = 0x03400000, /* SCB 0x0 */ + .mode_outmask = 0x00FFFFFF, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = board_au1200fb_panel_init, + .device_shutdown = board_au1200fb_panel_shutdown, + 1024, 1024, + 768, 768, + }, + + [6] = { /* Toshiba 640x480 TFT */ + .name = "Toshiba_640x480_TFT", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = LCD_SCREEN_SX_N(640) | + LCD_SCREEN_SY_N(480), + .mode_horztiming = LCD_HORZTIMING_HPW_N(96) | + LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51), + .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | + LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32), + .mode_clkcontrol = 0x00000000, /* /4=24Mhz */ + .mode_pwmdiv = 0x8000063f, + .mode_pwmhi = 0x03400000, + .mode_outmask = 0x00fcfcfc, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = board_au1200fb_panel_init, + .device_shutdown = board_au1200fb_panel_shutdown, + 640, 480, + 640, 480, + }, + + [7] = { /* Sharp 320x240 TFT */ + .name = "Sharp_320x240_TFT", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 12500, + .hfmax = 20000, + .vfmin = 38, + .vfmax = 81, + .dclkmin = 4500000, + .dclkmax = 6800000, + .input = FB_DISP_RGB, + }, + .mode_screen = LCD_SCREEN_SX_N(320) | + LCD_SCREEN_SY_N(240), + .mode_horztiming = LCD_HORZTIMING_HPW_N(60) | + LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2), + .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | + LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5), + .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/ + .mode_pwmdiv = 0x8000063f, + .mode_pwmhi = 0x03400000, + .mode_outmask = 0x00fcfcfc, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = board_au1200fb_panel_init, + .device_shutdown = board_au1200fb_panel_shutdown, + 320, 320, + 240, 240, + }, + + [8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */ + .name = "Toppoly_TD070WGCB2", + .monspecs = { + .modedb = NULL, + .modedb_len = 0, + .hfmin = 30000, + .hfmax = 70000, + .vfmin = 60, + .vfmax = 60, + .dclkmin = 6000000, + .dclkmax = 28000000, + .input = FB_DISP_RGB, + }, + .mode_screen = LCD_SCREEN_SX_N(856) | + LCD_SCREEN_SY_N(480), + .mode_horztiming = LCD_HORZTIMING_HND2_N(43) | + LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114), + .mode_verttiming = LCD_VERTTIMING_VND2_N(20) | + LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4), + .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ + .mode_pwmdiv = 0x8000063f, + .mode_pwmhi = 0x03400000, + .mode_outmask = 0x00fcfcfc, + .mode_fifoctrl = 0x2f2f2f2f, + .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ + .mode_backlight = 0x00000000, + .mode_auxpll = 8, /* 96MHz AUXPLL */ + .device_init = board_au1200fb_panel_init, + .device_shutdown = board_au1200fb_panel_shutdown, + 856, 856, + 480, 480, + }, +}; + +#define NUM_PANELS (ARRAY_SIZE(known_lcd_panels)) + +/********************************************************************/ + +#ifdef CONFIG_PM +static int set_brightness(unsigned int brightness) +{ + unsigned int hi1, divider; + + /* limit brightness pwm duty to >= 30/1600 */ + if (brightness < 30) { + brightness = 30; + } + divider = (lcd->pwmdiv & 0x3FFFF) + 1; + hi1 = (lcd->pwmhi >> 16) + 1; + hi1 = (((brightness & 0xFF) + 1) * divider >> 8); + lcd->pwmhi &= 0xFFFF; + lcd->pwmhi |= (hi1 << 16); + + return brightness; +} +#endif /* CONFIG_PM */ + +static int winbpp (unsigned int winctrl1) +{ + int bits = 0; + + /* how many bits are needed for each pixel format */ + switch (winctrl1 & LCD_WINCTRL1_FRM) { + case LCD_WINCTRL1_FRM_1BPP: + bits = 1; + break; + case LCD_WINCTRL1_FRM_2BPP: + bits = 2; + break; + case LCD_WINCTRL1_FRM_4BPP: + bits = 4; + break; + case LCD_WINCTRL1_FRM_8BPP: + bits = 8; + break; + case LCD_WINCTRL1_FRM_12BPP: + case LCD_WINCTRL1_FRM_16BPP655: + case LCD_WINCTRL1_FRM_16BPP565: + case LCD_WINCTRL1_FRM_16BPP556: + case LCD_WINCTRL1_FRM_16BPPI1555: + case LCD_WINCTRL1_FRM_16BPPI5551: + case LCD_WINCTRL1_FRM_16BPPA1555: + case LCD_WINCTRL1_FRM_16BPPA5551: + bits = 16; + break; + case LCD_WINCTRL1_FRM_24BPP: + case LCD_WINCTRL1_FRM_32BPP: + bits = 32; + break; + } + + return bits; +} + +static int fbinfo2index (struct fb_info *fb_info) +{ + int i; + + for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { + if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info)) + return i; + } + printk("au1200fb: ERROR: fbinfo2index failed!\n"); + return -1; +} + +static int au1200_setlocation (struct au1200fb_device *fbdev, int plane, + int xpos, int ypos) +{ + uint32 winctrl0, winctrl1, winenable, fb_offset = 0; + int xsz, ysz; + + /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */ + + winctrl0 = lcd->window[plane].winctrl0; + winctrl1 = lcd->window[plane].winctrl1; + winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN); + winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY); + + /* Check for off-screen adjustments */ + xsz = win->w[plane].xres; + ysz = win->w[plane].yres; + if ((xpos + win->w[plane].xres) > panel->Xres) { + /* Off-screen to the right */ + xsz = panel->Xres - xpos; /* off by 1 ??? */ + /*printk("off screen right\n");*/ + } + + if ((ypos + win->w[plane].yres) > panel->Yres) { + /* Off-screen to the bottom */ + ysz = panel->Yres - ypos; /* off by 1 ??? */ + /*printk("off screen bottom\n");*/ + } + + if (xpos < 0) { + /* Off-screen to the left */ + xsz = win->w[plane].xres + xpos; + fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8); + xpos = 0; + /*printk("off screen left\n");*/ + } + + if (ypos < 0) { + /* Off-screen to the top */ + ysz = win->w[plane].yres + ypos; + /* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */ + ypos = 0; + /*printk("off screen top\n");*/ + } + + /* record settings */ + win->w[plane].xpos = xpos; + win->w[plane].ypos = ypos; + + xsz -= 1; + ysz -= 1; + winctrl0 |= (xpos << 21); + winctrl0 |= (ypos << 10); + winctrl1 |= (xsz << 11); + winctrl1 |= (ysz << 0); + + /* Disable the window while making changes, then restore WINEN */ + winenable = lcd->winenable & (1 << plane); + au_sync(); + lcd->winenable &= ~(1 << plane); + lcd->window[plane].winctrl0 = winctrl0; + lcd->window[plane].winctrl1 = winctrl1; + lcd->window[plane].winbuf0 = + lcd->window[plane].winbuf1 = fbdev->fb_phys; + lcd->window[plane].winbufctrl = 0; /* select winbuf0 */ + lcd->winenable |= winenable; + au_sync(); + + return 0; +} + +static void au1200_setpanel (struct panel_settings *newpanel) +{ + /* + * Perform global setup/init of LCD controller + */ + uint32 winenable; + + /* Make sure all windows disabled */ + winenable = lcd->winenable; + lcd->winenable = 0; + au_sync(); + /* + * Ensure everything is disabled before reconfiguring + */ + if (lcd->screen & LCD_SCREEN_SEN) { + /* Wait for vertical sync period */ + lcd->intstatus = LCD_INT_SS; + while ((lcd->intstatus & LCD_INT_SS) == 0) { + au_sync(); + } + + lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/ + + do { + lcd->intstatus = lcd->intstatus; /*clear interrupts*/ + au_sync(); + /*wait for controller to shut down*/ + } while ((lcd->intstatus & LCD_INT_SD) == 0); + + /* Call shutdown of current panel (if up) */ + /* this must occur last, because if an external clock is driving + the controller, the clock cannot be turned off before first + shutting down the controller. + */ + if (panel->device_shutdown != NULL) + panel->device_shutdown(); + } + + /* Newpanel == NULL indicates a shutdown operation only */ + if (newpanel == NULL) + return; + + panel = newpanel; + + printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres); + + /* + * Setup clocking if internal LCD clock source (assumes sys_auxpll valid) + */ + if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT)) + { + uint32 sys_clksrc; + au_writel(panel->mode_auxpll, SYS_AUXPLL); + sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f; + sys_clksrc |= panel->mode_toyclksrc; + au_writel(sys_clksrc, SYS_CLKSRC); + } + + /* + * Configure panel timings + */ + lcd->screen = panel->mode_screen; + lcd->horztiming = panel->mode_horztiming; + lcd->verttiming = panel->mode_verttiming; + lcd->clkcontrol = panel->mode_clkcontrol; + lcd->pwmdiv = panel->mode_pwmdiv; + lcd->pwmhi = panel->mode_pwmhi; + lcd->outmask = panel->mode_outmask; + lcd->fifoctrl = panel->mode_fifoctrl; + au_sync(); + + /* fixme: Check window settings to make sure still valid + * for new geometry */ +#if 0 + au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos); + au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos); + au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos); + au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos); +#endif + lcd->winenable = winenable; + + /* + * Re-enable screen now that it is configured + */ + lcd->screen |= LCD_SCREEN_SEN; + au_sync(); + + /* Call init of panel */ + if (panel->device_init != NULL) panel->device_init(); + + /* FIX!!!! not appropriate on panel change!!! Global setup/init */ + lcd->intenable = 0; + lcd->intstatus = ~0; + lcd->backcolor = win->mode_backcolor; + + /* Setup Color Key - FIX!!! */ + lcd->colorkey = win->mode_colorkey; + lcd->colorkeymsk = win->mode_colorkeymsk; + + /* Setup HWCursor - FIX!!! Need to support this eventually */ + lcd->hwc.cursorctrl = 0; + lcd->hwc.cursorpos = 0; + lcd->hwc.cursorcolor0 = 0; + lcd->hwc.cursorcolor1 = 0; + lcd->hwc.cursorcolor2 = 0; + lcd->hwc.cursorcolor3 = 0; + + +#if 0 +#define D(X) printk("%25s: %08X\n", #X, X) + D(lcd->screen); + D(lcd->horztiming); + D(lcd->verttiming); + D(lcd->clkcontrol); + D(lcd->pwmdiv); + D(lcd->pwmhi); + D(lcd->outmask); + D(lcd->fifoctrl); + D(lcd->window[0].winctrl0); + D(lcd->window[0].winctrl1); + D(lcd->window[0].winctrl2); + D(lcd->window[0].winbuf0); + D(lcd->window[0].winbuf1); + D(lcd->window[0].winbufctrl); + D(lcd->window[1].winctrl0); + D(lcd->window[1].winctrl1); + D(lcd->window[1].winctrl2); + D(lcd->window[1].winbuf0); + D(lcd->window[1].winbuf1); + D(lcd->window[1].winbufctrl); + D(lcd->window[2].winctrl0); + D(lcd->window[2].winctrl1); + D(lcd->window[2].winctrl2); + D(lcd->window[2].winbuf0); + D(lcd->window[2].winbuf1); + D(lcd->window[2].winbufctrl); + D(lcd->window[3].winctrl0); + D(lcd->window[3].winctrl1); + D(lcd->window[3].winctrl2); + D(lcd->window[3].winbuf0); + D(lcd->window[3].winbuf1); + D(lcd->window[3].winbufctrl); + D(lcd->winenable); + D(lcd->intenable); + D(lcd->intstatus); + D(lcd->backcolor); + D(lcd->winenable); + D(lcd->colorkey); + D(lcd->colorkeymsk); + D(lcd->hwc.cursorctrl); + D(lcd->hwc.cursorpos); + D(lcd->hwc.cursorcolor0); + D(lcd->hwc.cursorcolor1); + D(lcd->hwc.cursorcolor2); + D(lcd->hwc.cursorcolor3); +#endif +} + +static void au1200_setmode(struct au1200fb_device *fbdev) +{ + int plane = fbdev->plane; + /* Window/plane setup */ + lcd->window[plane].winctrl1 = ( 0 + | LCD_WINCTRL1_PRI_N(plane) + | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */ + ) ; + + au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos); + + lcd->window[plane].winctrl2 = ( 0 + | LCD_WINCTRL2_CKMODE_00 + | LCD_WINCTRL2_DBM + | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) + | LCD_WINCTRL2_SCX_1 + | LCD_WINCTRL2_SCY_1 + ) ; + lcd->winenable |= win->w[plane].mode_winenable; + au_sync(); +} + + +/* Inline helpers */ + +/*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ +/*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ + +#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN) + +/* Bitfields format supported by the controller. */ +static struct fb_bitfield rgb_bitfields[][4] = { + /* Red, Green, Blue, Transp */ + [LCD_WINCTRL1_FRM_16BPP655 >> 25] = + { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_16BPP565 >> 25] = + { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_16BPP556 >> 25] = + { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] = + { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] = + { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] = + { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } }, + + [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] = + { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } }, + + [LCD_WINCTRL1_FRM_24BPP >> 25] = + { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } }, + + [LCD_WINCTRL1_FRM_32BPP >> 25] = + { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } }, +}; + +/*-------------------------------------------------------------------------*/ + +/* Helpers */ + +static void au1200fb_update_fbinfo(struct fb_info *fbi) +{ + /* FIX!!!! This also needs to take the window pixel format into account!!! */ + + /* Update var-dependent FB info */ + if (panel_is_color(panel)) { + if (fbi->var.bits_per_pixel <= 8) { + /* palettized */ + fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR; + fbi->fix.line_length = fbi->var.xres_virtual / + (8/fbi->var.bits_per_pixel); + } else { + /* non-palettized */ + fbi->fix.visual = FB_VISUAL_TRUECOLOR; + fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8); + } + } else { + /* mono FIX!!! mono 8 and 4 bits */ + fbi->fix.visual = FB_VISUAL_MONO10; + fbi->fix.line_length = fbi->var.xres_virtual / 8; + } + + fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual; + print_dbg("line length: %d\n", fbi->fix.line_length); + print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel); +} + +/*-------------------------------------------------------------------------*/ + +/* AU1200 framebuffer driver */ + +/* fb_check_var + * Validate var settings with hardware restrictions and modify it if necessary + */ +static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, + struct fb_info *fbi) +{ + struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; + u32 pixclock; + int screen_size, plane; + + plane = fbdev->plane; + + /* Make sure that the mode respect all LCD controller and + * panel restrictions. */ + var->xres = win->w[plane].xres; + var->yres = win->w[plane].yres; + + /* No need for virtual resolution support */ + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + + var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1); + + screen_size = var->xres_virtual * var->yres_virtual; + if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8); + else screen_size /= (8/var->bits_per_pixel); + + if (fbdev->fb_len < screen_size) + return -EINVAL; /* Virtual screen is to big, abort */ + + /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */ + /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel + * clock can only be obtain by dividing this value by an even integer. + * Fallback to a slower pixel clock if necessary. */ + pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); + pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2)); + + if (AU1200_LCD_MAX_CLK % pixclock) { + int diff = AU1200_LCD_MAX_CLK % pixclock; + pixclock -= diff; + } + + var->pixclock = KHZ2PICOS(pixclock/1000); +#if 0 + if (!panel_is_active(panel)) { + int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1; + + if (!panel_is_color(panel) + && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) { + /* STN 8bit mono panel support is up to 6MHz pixclock */ + var->pixclock = KHZ2PICOS(6000); + } else if (!pcd) { + /* Other STN panel support is up to 12MHz */ + var->pixclock = KHZ2PICOS(12000); + } + } +#endif + /* Set bitfield accordingly */ + switch (var->bits_per_pixel) { + case 16: + { + /* 16bpp True color. + * These must be set to MATCH WINCTRL[FORM] */ + int idx; + idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; + var->red = rgb_bitfields[idx][0]; + var->green = rgb_bitfields[idx][1]; + var->blue = rgb_bitfields[idx][2]; + var->transp = rgb_bitfields[idx][3]; + break; + } + + case 32: + { + /* 32bpp True color. + * These must be set to MATCH WINCTRL[FORM] */ + int idx; + idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; + var->red = rgb_bitfields[idx][0]; + var->green = rgb_bitfields[idx][1]; + var->blue = rgb_bitfields[idx][2]; + var->transp = rgb_bitfields[idx][3]; + break; + } + default: + print_dbg("Unsupported depth %dbpp", var->bits_per_pixel); + return -EINVAL; + } + + return 0; +} + +/* fb_set_par + * Set hardware with var settings. This will enable the controller with a + * specific mode, normally validated with the fb_check_var method + */ +static int au1200fb_fb_set_par(struct fb_info *fbi) +{ + struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; + + au1200fb_update_fbinfo(fbi); + au1200_setmode(fbdev); + + return 0; +} + +/* fb_setcolreg + * Set color in LCD palette. + */ +static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, struct fb_info *fbi) +{ + volatile u32 *palette = lcd->palette; + u32 value; + + if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1)) + return -EINVAL; + + if (fbi->var.grayscale) { + /* Convert color to grayscale */ + red = green = blue = + (19595 * red + 38470 * green + 7471 * blue) >> 16; + } + + if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) { + /* Place color in the pseudopalette */ + if (regno > 16) + return -EINVAL; + + palette = (u32*) fbi->pseudo_palette; + + red >>= (16 - fbi->var.red.length); + green >>= (16 - fbi->var.green.length); + blue >>= (16 - fbi->var.blue.length); + + value = (red << fbi->var.red.offset) | + (green << fbi->var.green.offset)| + (blue << fbi->var.blue.offset); + value &= 0xFFFF; + + } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) { + /* COLOR TFT PALLETTIZED (use RGB 565) */ + value = (red & 0xF800)|((green >> 5) & + 0x07E0)|((blue >> 11) & 0x001F); + value &= 0xFFFF; + + } else if (0 /*panel_is_color(fbdev->panel)*/) { + /* COLOR STN MODE */ + value = 0x1234; + value &= 0xFFF; + } else { + /* MONOCHROME MODE */ + value = (green >> 12) & 0x000F; + value &= 0xF; + } + + palette[regno] = value; + + return 0; +} + +/* fb_blank + * Blank the screen. Depending on the mode, the screen will be + * activated with the backlight color, or desactivated + */ +static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi) +{ + /* Short-circuit screen blanking */ + if (noblanking) + return 0; + + switch (blank_mode) { + + case FB_BLANK_UNBLANK: + case FB_BLANK_NORMAL: + /* printk("turn on panel\n"); */ + au1200_setpanel(panel); + break; + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_POWERDOWN: + /* printk("turn off panel\n"); */ + au1200_setpanel(NULL); + break; + default: + break; + + } + + /* FB_BLANK_NORMAL is a soft blank */ + return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0; +} + +/* fb_mmap + * Map video memory in user space. We don't use the generic fb_mmap + * method mainly to allow the use of the TLB streaming flag (CCA=6) + */ +static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) + +{ + unsigned int len; + unsigned long start=0, off; + struct au1200fb_device *fbdev = (struct au1200fb_device *) info; + +#ifdef CONFIG_PM + au1xxx_pm_access(LCD_pm_dev); +#endif + + if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { + return -EINVAL; + } + + start = fbdev->fb_phys & PAGE_MASK; + len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); + + off = vma->vm_pgoff << PAGE_SHIFT; + + if ((vma->vm_end - vma->vm_start + off) > len) { + return -EINVAL; + } + + off += start; + vma->vm_pgoff = off >> PAGE_SHIFT; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */ + + vma->vm_flags |= VM_IO; + + return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + + return 0; +} + +static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) +{ + + unsigned int hi1, divider; + + /* SCREEN_SIZE: user cannot reset size, must switch panel choice */ + + if (pdata->flags & SCREEN_BACKCOLOR) + lcd->backcolor = pdata->backcolor; + + if (pdata->flags & SCREEN_BRIGHTNESS) { + + // limit brightness pwm duty to >= 30/1600 + if (pdata->brightness < 30) { + pdata->brightness = 30; + } + divider = (lcd->pwmdiv & 0x3FFFF) + 1; + hi1 = (lcd->pwmhi >> 16) + 1; + hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8); + lcd->pwmhi &= 0xFFFF; + lcd->pwmhi |= (hi1 << 16); + } + + if (pdata->flags & SCREEN_COLORKEY) + lcd->colorkey = pdata->colorkey; + + if (pdata->flags & SCREEN_MASK) + lcd->colorkeymsk = pdata->mask; + au_sync(); +} + +static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) +{ + unsigned int hi1, divider; + + pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1; + pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1; + + pdata->backcolor = lcd->backcolor; + pdata->colorkey = lcd->colorkey; + pdata->mask = lcd->colorkeymsk; + + // brightness + hi1 = (lcd->pwmhi >> 16) + 1; + divider = (lcd->pwmdiv & 0x3FFFF) + 1; + pdata->brightness = ((hi1 << 8) / divider) - 1; + au_sync(); +} + +static void set_window(unsigned int plane, + struct au1200_lcd_window_regs_t *pdata) +{ + unsigned int val, bpp; + + /* Window control register 0 */ + if (pdata->flags & WIN_POSITION) { + val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX | + LCD_WINCTRL0_OY); + val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX); + val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY); + lcd->window[plane].winctrl0 = val; + } + if (pdata->flags & WIN_ALPHA_COLOR) { + val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A); + val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A); + lcd->window[plane].winctrl0 = val; + } + if (pdata->flags & WIN_ALPHA_MODE) { + val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN); + val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN); + lcd->window[plane].winctrl0 = val; + } + + /* Window control register 1 */ + if (pdata->flags & WIN_PRIORITY) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI); + val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI); + lcd->window[plane].winctrl1 = val; + } + if (pdata->flags & WIN_CHANNEL) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE); + val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE); + lcd->window[plane].winctrl1 = val; + } + if (pdata->flags & WIN_BUFFER_FORMAT) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM); + val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM); + lcd->window[plane].winctrl1 = val; + } + if (pdata->flags & WIN_COLOR_ORDER) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO); + val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO); + lcd->window[plane].winctrl1 = val; + } + if (pdata->flags & WIN_PIXEL_ORDER) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO); + val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO); + lcd->window[plane].winctrl1 = val; + } + if (pdata->flags & WIN_SIZE) { + val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX | + LCD_WINCTRL1_SZY); + val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX); + val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY); + lcd->window[plane].winctrl1 = val; + /* program buffer line width */ + bpp = winbpp(val) / 8; + val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX); + val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX); + lcd->window[plane].winctrl2 = val; + } + + /* Window control register 2 */ + if (pdata->flags & WIN_COLORKEY_MODE) { + val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE); + val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE); + lcd->window[plane].winctrl2 = val; + } + if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) { + val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM); + val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM); + lcd->window[plane].winctrl2 = val; + } + if (pdata->flags & WIN_RAM_ARRAY_MODE) { + val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM); + val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM); + lcd->window[plane].winctrl2 = val; + } + + /* Buffer line width programmed with WIN_SIZE */ + + if (pdata->flags & WIN_BUFFER_SCALE) { + val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX | + LCD_WINCTRL2_SCY); + val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX); + val |= ((pdata->ysize) & LCD_WINCTRL2_SCY); + lcd->window[plane].winctrl2 = val; + } + + if (pdata->flags & WIN_ENABLE) { + val = lcd->winenable; + val &= ~(1<enable & 1) << plane; + lcd->winenable = val; + } + au_sync(); +} + +static void get_window(unsigned int plane, + struct au1200_lcd_window_regs_t *pdata) +{ + /* Window control register 0 */ + pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21; + pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10; + pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2; + pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1; + + /* Window control register 1 */ + pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30; + pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29; + pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25; + pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24; + pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22; + pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1; + pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1; + + /* Window control register 2 */ + pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24; + pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23; + pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21; + + pdata->enable = (lcd->winenable >> plane) & 1; + au_sync(); +} + +static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + int plane; + int val; + +#ifdef CONFIG_PM + au1xxx_pm_access(LCD_pm_dev); +#endif + + plane = fbinfo2index(info); + print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); + + if (cmd == AU1200_LCD_FB_IOCTL) { + struct au1200_lcd_iodata_t iodata; + + if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata))) + return -EFAULT; + + print_dbg("FB IOCTL called\n"); + + switch (iodata.subcmd) { + case AU1200_LCD_SET_SCREEN: + print_dbg("AU1200_LCD_SET_SCREEN\n"); + set_global(cmd, &iodata.global); + break; + + case AU1200_LCD_GET_SCREEN: + print_dbg("AU1200_LCD_GET_SCREEN\n"); + get_global(cmd, &iodata.global); + break; + + case AU1200_LCD_SET_WINDOW: + print_dbg("AU1200_LCD_SET_WINDOW\n"); + set_window(plane, &iodata.window); + break; + + case AU1200_LCD_GET_WINDOW: + print_dbg("AU1200_LCD_GET_WINDOW\n"); + get_window(plane, &iodata.window); + break; + + case AU1200_LCD_SET_PANEL: + print_dbg("AU1200_LCD_SET_PANEL\n"); + if ((iodata.global.panel_choice >= 0) && + (iodata.global.panel_choice < + NUM_PANELS)) + { + struct panel_settings *newpanel; + panel_index = iodata.global.panel_choice; + newpanel = &known_lcd_panels[panel_index]; + au1200_setpanel(newpanel); + } + break; + + case AU1200_LCD_GET_PANEL: + print_dbg("AU1200_LCD_GET_PANEL\n"); + iodata.global.panel_choice = panel_index; + break; + + default: + return -EINVAL; + } + + val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata)); + if (val) { + print_dbg("error: could not copy %d bytes\n", val); + return -EFAULT; + } + } + + return 0; +} + + +static struct fb_ops au1200fb_fb_ops = { + .owner = THIS_MODULE, + .fb_check_var = au1200fb_fb_check_var, + .fb_set_par = au1200fb_fb_set_par, + .fb_setcolreg = au1200fb_fb_setcolreg, + .fb_blank = au1200fb_fb_blank, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_sync = NULL, + .fb_ioctl = au1200fb_ioctl, + .fb_mmap = au1200fb_fb_mmap, +}; + +/*-------------------------------------------------------------------------*/ + +static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs) +{ + /* Nothing to do for now, just clear any pending interrupt */ + lcd->intstatus = lcd->intstatus; + au_sync(); + + return IRQ_HANDLED; +} + +/*-------------------------------------------------------------------------*/ + +/* AU1200 LCD device probe helpers */ + +static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) +{ + struct fb_info *fbi = &fbdev->fb_info; + int bpp; + + memset(fbi, 0, sizeof(struct fb_info)); + fbi->fbops = &au1200fb_fb_ops; + + bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); + + /* Copy monitor specs from panel data */ + /* fixme: we're setting up LCD controller windows, so these dont give a + damn as to what the monitor specs are (the panel itself does, but that + isnt done here...so maybe need a generic catchall monitor setting??? */ + memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs)); + + /* We first try the user mode passed in argument. If that failed, + * or if no one has been specified, we default to the first mode of the + * panel list. Note that after this call, var data will be set */ + if (!fb_find_mode(&fbi->var, + fbi, + NULL, /* drv_info.opt_mode, */ + fbi->monspecs.modedb, + fbi->monspecs.modedb_len, + fbi->monspecs.modedb, + bpp)) { + + print_err("Cannot find valid mode for panel %s", panel->name); + return -EFAULT; + } + + fbi->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); + if (!fbi->pseudo_palette) { + return -ENOMEM; + } + memset(fbi->pseudo_palette, 0, sizeof(u32) * 16); + + if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { + print_err("Fail to allocate colormap (%d entries)", + AU1200_LCD_NBR_PALETTE_ENTRIES); + kfree(fbi->pseudo_palette); + return -EFAULT; + } + + strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id)); + fbi->fix.smem_start = fbdev->fb_phys; + fbi->fix.smem_len = fbdev->fb_len; + fbi->fix.type = FB_TYPE_PACKED_PIXELS; + fbi->fix.xpanstep = 0; + fbi->fix.ypanstep = 0; + fbi->fix.mmio_start = 0; + fbi->fix.mmio_len = 0; + fbi->fix.accel = FB_ACCEL_NONE; + + fbi->screen_base = (char __iomem *) fbdev->fb_mem; + + au1200fb_update_fbinfo(fbi); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* AU1200 LCD controller device driver */ + +static int au1200fb_drv_probe(struct device *dev) +{ + struct au1200fb_device *fbdev; + unsigned long page; + int bpp, plane, ret; + + if (!dev) + return -EINVAL; + + for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { + bpp = winbpp(win->w[plane].mode_winctrl1); + if (win->w[plane].xres == 0) + win->w[plane].xres = panel->Xres; + if (win->w[plane].yres == 0) + win->w[plane].yres = panel->Yres; + + fbdev = &_au1200fb_devices[plane]; + memset(fbdev, 0, sizeof(struct au1200fb_device)); + fbdev->plane = plane; + + /* Allocate the framebuffer to the maximum screen size */ + fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; + + fbdev->fb_mem = dma_alloc_noncoherent(dev, + PAGE_ALIGN(fbdev->fb_len), + &fbdev->fb_phys, GFP_KERNEL); + if (!fbdev->fb_mem) { + print_err("fail to allocate frambuffer (size: %dK))", + fbdev->fb_len / 1024); + return -ENOMEM; + } + + /* + * Set page reserved so that mmap will work. This is necessary + * since we'll be remapping normal memory. + */ + for (page = (unsigned long)fbdev->fb_phys; + page < PAGE_ALIGN((unsigned long)fbdev->fb_phys + + fbdev->fb_len); + page += PAGE_SIZE) { + SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */ + } + print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); + print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); + + /* Init FB data */ + if ((ret = au1200fb_init_fbinfo(fbdev)) < 0) + goto failed; + + /* Register new framebuffer */ + if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) { + print_err("cannot register new framebuffer"); + goto failed; + } + + au1200fb_fb_set_par(&fbdev->fb_info); + +#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) + if (plane == 0) + if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) { + /* Start display and show logo on boot */ + fb_set_cmap(&fbdev->fb_info.cmap, + &fbdev->fb_info); + + fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR); + } +#endif + } + + /* Now hook interrupt too */ + if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq, + SA_INTERRUPT | SA_SHIRQ, "lcd", (void *)dev)) < 0) { + print_err("fail to request interrupt line %d (err: %d)", + AU1200_LCD_INT, ret); + goto failed; + } + + return 0; + +failed: + /* NOTE: This only does the current plane/window that failed; others are still active */ + if (fbdev->fb_mem) + dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), + fbdev->fb_mem, fbdev->fb_phys); + if (fbdev->fb_info.cmap.len != 0) + fb_dealloc_cmap(&fbdev->fb_info.cmap); + if (fbdev->fb_info.pseudo_palette) + kfree(fbdev->fb_info.pseudo_palette); + if (plane == 0) + free_irq(AU1200_LCD_INT, (void*)dev); + return ret; +} + +static int au1200fb_drv_remove(struct device *dev) +{ + struct au1200fb_device *fbdev; + int plane; + + if (!dev) + return -ENODEV; + + /* Turn off the panel */ + au1200_setpanel(NULL); + + for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) + { + fbdev = &_au1200fb_devices[plane]; + + /* Clean up all probe data */ + unregister_framebuffer(&fbdev->fb_info); + if (fbdev->fb_mem) + dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), + fbdev->fb_mem, fbdev->fb_phys); + if (fbdev->fb_info.cmap.len != 0) + fb_dealloc_cmap(&fbdev->fb_info.cmap); + if (fbdev->fb_info.pseudo_palette) + kfree(fbdev->fb_info.pseudo_palette); + } + + free_irq(AU1200_LCD_INT, (void *)dev); + + return 0; +} + +#ifdef CONFIG_PM +static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level) +{ + /* TODO */ + return 0; +} + +static int au1200fb_drv_resume(struct device *dev, u32 level) +{ + /* TODO */ + return 0; +} +#endif /* CONFIG_PM */ + +static struct device_driver au1200fb_driver = { + .name = "au1200-lcd", + .bus = &platform_bus_type, + .probe = au1200fb_drv_probe, + .remove = au1200fb_drv_remove, +#ifdef CONFIG_PM + .suspend = au1200fb_drv_suspend, + .resume = au1200fb_drv_resume, +#endif +}; + +/*-------------------------------------------------------------------------*/ + +/* Kernel driver */ + +static void au1200fb_setup(void) +{ + char* options = NULL; + char* this_opt; + int num_panels = ARRAY_SIZE(known_lcd_panels); + int panel_idx = -1; + + fb_get_options(DRIVER_NAME, &options); + + if (options) { + while ((this_opt = strsep(&options,",")) != NULL) { + /* Panel option - can be panel name, + * "bs" for board-switch, or number/index */ + if (!strncmp(this_opt, "panel:", 6)) { + int i; + long int li; + char *endptr; + this_opt += 6; + /* First check for index, which allows + * to short circuit this mess */ + li = simple_strtol(this_opt, &endptr, 0); + if (*endptr == '\0') { + panel_idx = (int)li; + } + else if (strcmp(this_opt, "bs") == 0) { + extern int board_au1200fb_panel(void); + panel_idx = board_au1200fb_panel(); + } + + else + for (i = 0; i < num_panels; i++) { + if (!strcmp(this_opt, known_lcd_panels[i].name)) { + panel_idx = i; + break; + } + } + + if ((panel_idx < 0) || (panel_idx >= num_panels)) { + print_warn("Panel %s not supported!", this_opt); + } + else + panel_index = panel_idx; + } + + else if (strncmp(this_opt, "nohwcursor", 10) == 0) { + nohwcursor = 1; + } + + /* Unsupported option */ + else { + print_warn("Unsupported option \"%s\"", this_opt); + } + } + } +} + +#ifdef CONFIG_PM +static int au1200fb_pm_callback(au1xxx_power_dev_t *dev, + au1xxx_request_t request, void *data) { + int retval = -1; + unsigned int d = 0; + unsigned int brightness = 0; + + if (request == AU1XXX_PM_SLEEP) { + board_au1200fb_panel_shutdown(); + } + else if (request == AU1XXX_PM_WAKEUP) { + if(dev->prev_state == SLEEP_STATE) + { + int plane; + au1200_setpanel(panel); + for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { + struct au1200fb_device *fbdev; + fbdev = &_au1200fb_devices[plane]; + au1200fb_fb_set_par(&fbdev->fb_info); + } + } + + d = *((unsigned int*)data); + if(d <=10) brightness = 26; + else if(d<=20) brightness = 51; + else if(d<=30) brightness = 77; + else if(d<=40) brightness = 102; + else if(d<=50) brightness = 128; + else if(d<=60) brightness = 153; + else if(d<=70) brightness = 179; + else if(d<=80) brightness = 204; + else if(d<=90) brightness = 230; + else brightness = 255; + set_brightness(brightness); + } else if (request == AU1XXX_PM_GETSTATUS) { + return dev->cur_state; + } else if (request == AU1XXX_PM_ACCESS) { + if (dev->cur_state != SLEEP_STATE) + return retval; + else { + au1200_setpanel(panel); + } + } else if (request == AU1XXX_PM_IDLE) { + } else if (request == AU1XXX_PM_CLEANUP) { + } + + return retval; +} +#endif + +static int __init au1200fb_init(void) +{ + print_info("" DRIVER_DESC ""); + + /* Setup driver with options */ + au1200fb_setup(); + + /* Point to the panel selected */ + panel = &known_lcd_panels[panel_index]; + win = &windows[window_index]; + + printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); + printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); + + /* Kickstart the panel, the framebuffers/windows come soon enough */ + au1200_setpanel(panel); + + #ifdef CONFIG_PM + LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL); + if ( LCD_pm_dev == NULL) + printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n"); + else + printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); + #endif + + return driver_register(&au1200fb_driver); +} + +static void __exit au1200fb_cleanup(void) +{ + driver_unregister(&au1200fb_driver); +} + +module_init(au1200fb_init); +module_exit(au1200fb_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/au1200fb.h b/drivers/video/au1200fb.h new file mode 100644 index 000000000000..e2672714d8d4 --- /dev/null +++ b/drivers/video/au1200fb.h @@ -0,0 +1,572 @@ +/* + * BRIEF MODULE DESCRIPTION + * Hardware definitions for the Au1200 LCD controller + * + * Copyright 2004 AMD + * Author: AMD + * + * 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 SOFTWARE IS PROVIDED ``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 AUTHOR 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. + * + * 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. + */ + +#ifndef _AU1200LCD_H +#define _AU1200LCD_H + +/********************************************************************/ +#define AU1200_LCD_ADDR 0xB5000000 + +#define uint8 unsigned char +#define uint32 unsigned int + +struct au1200_lcd { + volatile uint32 reserved0; + volatile uint32 screen; + volatile uint32 backcolor; + volatile uint32 horztiming; + volatile uint32 verttiming; + volatile uint32 clkcontrol; + volatile uint32 pwmdiv; + volatile uint32 pwmhi; + volatile uint32 reserved1; + volatile uint32 winenable; + volatile uint32 colorkey; + volatile uint32 colorkeymsk; + struct + { + volatile uint32 cursorctrl; + volatile uint32 cursorpos; + volatile uint32 cursorcolor0; + volatile uint32 cursorcolor1; + volatile uint32 cursorcolor2; + uint32 cursorcolor3; + } hwc; + volatile uint32 intstatus; + volatile uint32 intenable; + volatile uint32 outmask; + volatile uint32 fifoctrl; + uint32 reserved2[(0x0100-0x0058)/4]; + struct + { + volatile uint32 winctrl0; + volatile uint32 winctrl1; + volatile uint32 winctrl2; + volatile uint32 winbuf0; + volatile uint32 winbuf1; + volatile uint32 winbufctrl; + uint32 winreserved0; + uint32 winreserved1; + } window[4]; + + uint32 reserved3[(0x0400-0x0180)/4]; + + volatile uint32 palette[(0x0800-0x0400)/4]; + + volatile uint8 cursorpattern[256]; +}; + +/* lcd_screen */ +#define LCD_SCREEN_SEN (1<<31) +#define LCD_SCREEN_SX (0x07FF<<19) +#define LCD_SCREEN_SY (0x07FF<< 8) +#define LCD_SCREEN_SWP (1<<7) +#define LCD_SCREEN_SWD (1<<6) +#define LCD_SCREEN_PT (7<<0) +#define LCD_SCREEN_PT_TFT (0<<0) +#define LCD_SCREEN_SX_N(WIDTH) ((WIDTH-1)<<19) +#define LCD_SCREEN_SY_N(HEIGHT) ((HEIGHT-1)<<8) +#define LCD_SCREEN_PT_CSTN (1<<0) +#define LCD_SCREEN_PT_CDSTN (2<<0) +#define LCD_SCREEN_PT_M8STN (3<<0) +#define LCD_SCREEN_PT_M4STN (4<<0) + +/* lcd_backcolor */ +#define LCD_BACKCOLOR_SBGR (0xFF<<16) +#define LCD_BACKCOLOR_SBGG (0xFF<<8) +#define LCD_BACKCOLOR_SBGB (0xFF<<0) +#define LCD_BACKCOLOR_SBGR_N(N) ((N)<<16) +#define LCD_BACKCOLOR_SBGG_N(N) ((N)<<8) +#define LCD_BACKCOLOR_SBGB_N(N) ((N)<<0) + +/* lcd_winenable */ +#define LCD_WINENABLE_WEN3 (1<<3) +#define LCD_WINENABLE_WEN2 (1<<2) +#define LCD_WINENABLE_WEN1 (1<<1) +#define LCD_WINENABLE_WEN0 (1<<0) + +/* lcd_colorkey */ +#define LCD_COLORKEY_CKR (0xFF<<16) +#define LCD_COLORKEY_CKG (0xFF<<8) +#define LCD_COLORKEY_CKB (0xFF<<0) +#define LCD_COLORKEY_CKR_N(N) ((N)<<16) +#define LCD_COLORKEY_CKG_N(N) ((N)<<8) +#define LCD_COLORKEY_CKB_N(N) ((N)<<0) + +/* lcd_colorkeymsk */ +#define LCD_COLORKEYMSK_CKMR (0xFF<<16) +#define LCD_COLORKEYMSK_CKMG (0xFF<<8) +#define LCD_COLORKEYMSK_CKMB (0xFF<<0) +#define LCD_COLORKEYMSK_CKMR_N(N) ((N)<<16) +#define LCD_COLORKEYMSK_CKMG_N(N) ((N)<<8) +#define LCD_COLORKEYMSK_CKMB_N(N) ((N)<<0) + +/* lcd windows control 0 */ +#define LCD_WINCTRL0_OX (0x07FF<<21) +#define LCD_WINCTRL0_OY (0x07FF<<10) +#define LCD_WINCTRL0_A (0x00FF<<2) +#define LCD_WINCTRL0_AEN (1<<1) +#define LCD_WINCTRL0_OX_N(N) ((N)<<21) +#define LCD_WINCTRL0_OY_N(N) ((N)<<10) +#define LCD_WINCTRL0_A_N(N) ((N)<<2) + +/* lcd windows control 1 */ +#define LCD_WINCTRL1_PRI (3<<30) +#define LCD_WINCTRL1_PIPE (1<<29) +#define LCD_WINCTRL1_FRM (0xF<<25) +#define LCD_WINCTRL1_CCO (1<<24) +#define LCD_WINCTRL1_PO (3<<22) +#define LCD_WINCTRL1_SZX (0x07FF<<11) +#define LCD_WINCTRL1_SZY (0x07FF<<0) +#define LCD_WINCTRL1_FRM_1BPP (0<<25) +#define LCD_WINCTRL1_FRM_2BPP (1<<25) +#define LCD_WINCTRL1_FRM_4BPP (2<<25) +#define LCD_WINCTRL1_FRM_8BPP (3<<25) +#define LCD_WINCTRL1_FRM_12BPP (4<<25) +#define LCD_WINCTRL1_FRM_16BPP655 (5<<25) +#define LCD_WINCTRL1_FRM_16BPP565 (6<<25) +#define LCD_WINCTRL1_FRM_16BPP556 (7<<25) +#define LCD_WINCTRL1_FRM_16BPPI1555 (8<<25) +#define LCD_WINCTRL1_FRM_16BPPI5551 (9<<25) +#define LCD_WINCTRL1_FRM_16BPPA1555 (10<<25) +#define LCD_WINCTRL1_FRM_16BPPA5551 (11<<25) +#define LCD_WINCTRL1_FRM_24BPP (12<<25) +#define LCD_WINCTRL1_FRM_32BPP (13<<25) +#define LCD_WINCTRL1_PRI_N(N) ((N)<<30) +#define LCD_WINCTRL1_PO_00 (0<<22) +#define LCD_WINCTRL1_PO_01 (1<<22) +#define LCD_WINCTRL1_PO_10 (2<<22) +#define LCD_WINCTRL1_PO_11 (3<<22) +#define LCD_WINCTRL1_SZX_N(N) ((N-1)<<11) +#define LCD_WINCTRL1_SZY_N(N) ((N-1)<<0) + +/* lcd windows control 2 */ +#define LCD_WINCTRL2_CKMODE (3<<24) +#define LCD_WINCTRL2_DBM (1<<23) +#define LCD_WINCTRL2_RAM (3<<21) +#define LCD_WINCTRL2_BX (0x1FFF<<8) +#define LCD_WINCTRL2_SCX (0xF<<4) +#define LCD_WINCTRL2_SCY (0xF<<0) +#define LCD_WINCTRL2_CKMODE_00 (0<<24) +#define LCD_WINCTRL2_CKMODE_01 (1<<24) +#define LCD_WINCTRL2_CKMODE_10 (2<<24) +#define LCD_WINCTRL2_CKMODE_11 (3<<24) +#define LCD_WINCTRL2_RAM_NONE (0<<21) +#define LCD_WINCTRL2_RAM_PALETTE (1<<21) +#define LCD_WINCTRL2_RAM_GAMMA (2<<21) +#define LCD_WINCTRL2_RAM_BUFFER (3<<21) +#define LCD_WINCTRL2_BX_N(N) ((N)<<8) +#define LCD_WINCTRL2_SCX_1 (0<<4) +#define LCD_WINCTRL2_SCX_2 (1<<4) +#define LCD_WINCTRL2_SCX_4 (2<<4) +#define LCD_WINCTRL2_SCY_1 (0<<0) +#define LCD_WINCTRL2_SCY_2 (1<<0) +#define LCD_WINCTRL2_SCY_4 (2<<0) + +/* lcd windows buffer control */ +#define LCD_WINBUFCTRL_DB (1<<1) +#define LCD_WINBUFCTRL_DBN (1<<0) + +/* lcd_intstatus, lcd_intenable */ +#define LCD_INT_IFO (0xF<<14) +#define LCD_INT_IFU (0xF<<10) +#define LCD_INT_OFO (1<<9) +#define LCD_INT_OFU (1<<8) +#define LCD_INT_WAIT (1<<3) +#define LCD_INT_SD (1<<2) +#define LCD_INT_SA (1<<1) +#define LCD_INT_SS (1<<0) + +/* lcd_horztiming */ +#define LCD_HORZTIMING_HND2 (0x1FF<<18) +#define LCD_HORZTIMING_HND1 (0x1FF<<9) +#define LCD_HORZTIMING_HPW (0x1FF<<0) +#define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18) +#define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9) +#define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<0) + +/* lcd_verttiming */ +#define LCD_VERTTIMING_VND2 (0x1FF<<18) +#define LCD_VERTTIMING_VND1 (0x1FF<<9) +#define LCD_VERTTIMING_VPW (0x1FF<<0) +#define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18) +#define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9) +#define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<0) + +/* lcd_clkcontrol */ +#define LCD_CLKCONTROL_EXT (1<<22) +#define LCD_CLKCONTROL_DELAY (3<<20) +#define LCD_CLKCONTROL_CDD (1<<19) +#define LCD_CLKCONTROL_IB (1<<18) +#define LCD_CLKCONTROL_IC (1<<17) +#define LCD_CLKCONTROL_IH (1<<16) +#define LCD_CLKCONTROL_IV (1<<15) +#define LCD_CLKCONTROL_BF (0x1F<<10) +#define LCD_CLKCONTROL_PCD (0x3FF<<0) +#define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10) +#define LCD_CLKCONTROL_PCD_N(N) ((N)<<0) + +/* lcd_pwmdiv */ +#define LCD_PWMDIV_EN (1<<31) +#define LCD_PWMDIV_PWMDIV (0x1FFFF<<0) +#define LCD_PWMDIV_PWMDIV_N(N) ((N)<<0) + +/* lcd_pwmhi */ +#define LCD_PWMHI_PWMHI1 (0xFFFF<<16) +#define LCD_PWMHI_PWMHI0 (0xFFFF<<0) +#define LCD_PWMHI_PWMHI1_N(N) ((N)<<16) +#define LCD_PWMHI_PWMHI0_N(N) ((N)<<0) + +/* lcd_hwccon */ +#define LCD_HWCCON_EN (1<<0) + +/* lcd_cursorpos */ +#define LCD_CURSORPOS_HWCXOFF (0x1F<<27) +#define LCD_CURSORPOS_HWCXPOS (0x07FF<<16) +#define LCD_CURSORPOS_HWCYOFF (0x1F<<11) +#define LCD_CURSORPOS_HWCYPOS (0x07FF<<0) +#define LCD_CURSORPOS_HWCXOFF_N(N) ((N)<<27) +#define LCD_CURSORPOS_HWCXPOS_N(N) ((N)<<16) +#define LCD_CURSORPOS_HWCYOFF_N(N) ((N)<<11) +#define LCD_CURSORPOS_HWCYPOS_N(N) ((N)<<0) + +/* lcd_cursorcolor */ +#define LCD_CURSORCOLOR_HWCA (0xFF<<24) +#define LCD_CURSORCOLOR_HWCR (0xFF<<16) +#define LCD_CURSORCOLOR_HWCG (0xFF<<8) +#define LCD_CURSORCOLOR_HWCB (0xFF<<0) +#define LCD_CURSORCOLOR_HWCA_N(N) ((N)<<24) +#define LCD_CURSORCOLOR_HWCR_N(N) ((N)<<16) +#define LCD_CURSORCOLOR_HWCG_N(N) ((N)<<8) +#define LCD_CURSORCOLOR_HWCB_N(N) ((N)<<0) + +/* lcd_fifoctrl */ +#define LCD_FIFOCTRL_F3IF (1<<29) +#define LCD_FIFOCTRL_F3REQ (0x1F<<24) +#define LCD_FIFOCTRL_F2IF (1<<29) +#define LCD_FIFOCTRL_F2REQ (0x1F<<16) +#define LCD_FIFOCTRL_F1IF (1<<29) +#define LCD_FIFOCTRL_F1REQ (0x1F<<8) +#define LCD_FIFOCTRL_F0IF (1<<29) +#define LCD_FIFOCTRL_F0REQ (0x1F<<0) +#define LCD_FIFOCTRL_F3REQ_N(N) ((N-1)<<24) +#define LCD_FIFOCTRL_F2REQ_N(N) ((N-1)<<16) +#define LCD_FIFOCTRL_F1REQ_N(N) ((N-1)<<8) +#define LCD_FIFOCTRL_F0REQ_N(N) ((N-1)<<0) + +/* lcd_outmask */ +#define LCD_OUTMASK_MASK (0x00FFFFFF) + +/********************************************************************/ +#endif /* _AU1200LCD_H */ +/* + * BRIEF MODULE DESCRIPTION + * Hardware definitions for the Au1200 LCD controller + * + * Copyright 2004 AMD + * Author: AMD + * + * 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 SOFTWARE IS PROVIDED ``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 AUTHOR 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. + * + * 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. + */ + +#ifndef _AU1200LCD_H +#define _AU1200LCD_H + +/********************************************************************/ +#define AU1200_LCD_ADDR 0xB5000000 + +#define uint8 unsigned char +#define uint32 unsigned int + +struct au1200_lcd { + volatile uint32 reserved0; + volatile uint32 screen; + volatile uint32 backcolor; + volatile uint32 horztiming; + volatile uint32 verttiming; + volatile uint32 clkcontrol; + volatile uint32 pwmdiv; + volatile uint32 pwmhi; + volatile uint32 reserved1; + volatile uint32 winenable; + volatile uint32 colorkey; + volatile uint32 colorkeymsk; + struct + { + volatile uint32 cursorctrl; + volatile uint32 cursorpos; + volatile uint32 cursorcolor0; + volatile uint32 cursorcolor1; + volatile uint32 cursorcolor2; + uint32 cursorcolor3; + } hwc; + volatile uint32 intstatus; + volatile uint32 intenable; + volatile uint32 outmask; + volatile uint32 fifoctrl; + uint32 reserved2[(0x0100-0x0058)/4]; + struct + { + volatile uint32 winctrl0; + volatile uint32 winctrl1; + volatile uint32 winctrl2; + volatile uint32 winbuf0; + volatile uint32 winbuf1; + volatile uint32 winbufctrl; + uint32 winreserved0; + uint32 winreserved1; + } window[4]; + + uint32 reserved3[(0x0400-0x0180)/4]; + + volatile uint32 palette[(0x0800-0x0400)/4]; + + volatile uint8 cursorpattern[256]; +}; + +/* lcd_screen */ +#define LCD_SCREEN_SEN (1<<31) +#define LCD_SCREEN_SX (0x07FF<<19) +#define LCD_SCREEN_SY (0x07FF<< 8) +#define LCD_SCREEN_SWP (1<<7) +#define LCD_SCREEN_SWD (1<<6) +#define LCD_SCREEN_PT (7<<0) +#define LCD_SCREEN_PT_TFT (0<<0) +#define LCD_SCREEN_SX_N(WIDTH) ((WIDTH-1)<<19) +#define LCD_SCREEN_SY_N(HEIGHT) ((HEIGHT-1)<<8) +#define LCD_SCREEN_PT_CSTN (1<<0) +#define LCD_SCREEN_PT_CDSTN (2<<0) +#define LCD_SCREEN_PT_M8STN (3<<0) +#define LCD_SCREEN_PT_M4STN (4<<0) + +/* lcd_backcolor */ +#define LCD_BACKCOLOR_SBGR (0xFF<<16) +#define LCD_BACKCOLOR_SBGG (0xFF<<8) +#define LCD_BACKCOLOR_SBGB (0xFF<<0) +#define LCD_BACKCOLOR_SBGR_N(N) ((N)<<16) +#define LCD_BACKCOLOR_SBGG_N(N) ((N)<<8) +#define LCD_BACKCOLOR_SBGB_N(N) ((N)<<0) + +/* lcd_winenable */ +#define LCD_WINENABLE_WEN3 (1<<3) +#define LCD_WINENABLE_WEN2 (1<<2) +#define LCD_WINENABLE_WEN1 (1<<1) +#define LCD_WINENABLE_WEN0 (1<<0) + +/* lcd_colorkey */ +#define LCD_COLORKEY_CKR (0xFF<<16) +#define LCD_COLORKEY_CKG (0xFF<<8) +#define LCD_COLORKEY_CKB (0xFF<<0) +#define LCD_COLORKEY_CKR_N(N) ((N)<<16) +#define LCD_COLORKEY_CKG_N(N) ((N)<<8) +#define LCD_COLORKEY_CKB_N(N) ((N)<<0) + +/* lcd_colorkeymsk */ +#define LCD_COLORKEYMSK_CKMR (0xFF<<16) +#define LCD_COLORKEYMSK_CKMG (0xFF<<8) +#define LCD_COLORKEYMSK_CKMB (0xFF<<0) +#define LCD_COLORKEYMSK_CKMR_N(N) ((N)<<16) +#define LCD_COLORKEYMSK_CKMG_N(N) ((N)<<8) +#define LCD_COLORKEYMSK_CKMB_N(N) ((N)<<0) + +/* lcd windows control 0 */ +#define LCD_WINCTRL0_OX (0x07FF<<21) +#define LCD_WINCTRL0_OY (0x07FF<<10) +#define LCD_WINCTRL0_A (0x00FF<<2) +#define LCD_WINCTRL0_AEN (1<<1) +#define LCD_WINCTRL0_OX_N(N) ((N)<<21) +#define LCD_WINCTRL0_OY_N(N) ((N)<<10) +#define LCD_WINCTRL0_A_N(N) ((N)<<2) + +/* lcd windows control 1 */ +#define LCD_WINCTRL1_PRI (3<<30) +#define LCD_WINCTRL1_PIPE (1<<29) +#define LCD_WINCTRL1_FRM (0xF<<25) +#define LCD_WINCTRL1_CCO (1<<24) +#define LCD_WINCTRL1_PO (3<<22) +#define LCD_WINCTRL1_SZX (0x07FF<<11) +#define LCD_WINCTRL1_SZY (0x07FF<<0) +#define LCD_WINCTRL1_FRM_1BPP (0<<25) +#define LCD_WINCTRL1_FRM_2BPP (1<<25) +#define LCD_WINCTRL1_FRM_4BPP (2<<25) +#define LCD_WINCTRL1_FRM_8BPP (3<<25) +#define LCD_WINCTRL1_FRM_12BPP (4<<25) +#define LCD_WINCTRL1_FRM_16BPP655 (5<<25) +#define LCD_WINCTRL1_FRM_16BPP565 (6<<25) +#define LCD_WINCTRL1_FRM_16BPP556 (7<<25) +#define LCD_WINCTRL1_FRM_16BPPI1555 (8<<25) +#define LCD_WINCTRL1_FRM_16BPPI5551 (9<<25) +#define LCD_WINCTRL1_FRM_16BPPA1555 (10<<25) +#define LCD_WINCTRL1_FRM_16BPPA5551 (11<<25) +#define LCD_WINCTRL1_FRM_24BPP (12<<25) +#define LCD_WINCTRL1_FRM_32BPP (13<<25) +#define LCD_WINCTRL1_PRI_N(N) ((N)<<30) +#define LCD_WINCTRL1_PO_00 (0<<22) +#define LCD_WINCTRL1_PO_01 (1<<22) +#define LCD_WINCTRL1_PO_10 (2<<22) +#define LCD_WINCTRL1_PO_11 (3<<22) +#define LCD_WINCTRL1_SZX_N(N) ((N-1)<<11) +#define LCD_WINCTRL1_SZY_N(N) ((N-1)<<0) + +/* lcd windows control 2 */ +#define LCD_WINCTRL2_CKMODE (3<<24) +#define LCD_WINCTRL2_DBM (1<<23) +#define LCD_WINCTRL2_RAM (3<<21) +#define LCD_WINCTRL2_BX (0x1FFF<<8) +#define LCD_WINCTRL2_SCX (0xF<<4) +#define LCD_WINCTRL2_SCY (0xF<<0) +#define LCD_WINCTRL2_CKMODE_00 (0<<24) +#define LCD_WINCTRL2_CKMODE_01 (1<<24) +#define LCD_WINCTRL2_CKMODE_10 (2<<24) +#define LCD_WINCTRL2_CKMODE_11 (3<<24) +#define LCD_WINCTRL2_RAM_NONE (0<<21) +#define LCD_WINCTRL2_RAM_PALETTE (1<<21) +#define LCD_WINCTRL2_RAM_GAMMA (2<<21) +#define LCD_WINCTRL2_RAM_BUFFER (3<<21) +#define LCD_WINCTRL2_BX_N(N) ((N)<<8) +#define LCD_WINCTRL2_SCX_1 (0<<4) +#define LCD_WINCTRL2_SCX_2 (1<<4) +#define LCD_WINCTRL2_SCX_4 (2<<4) +#define LCD_WINCTRL2_SCY_1 (0<<0) +#define LCD_WINCTRL2_SCY_2 (1<<0) +#define LCD_WINCTRL2_SCY_4 (2<<0) + +/* lcd windows buffer control */ +#define LCD_WINBUFCTRL_DB (1<<1) +#define LCD_WINBUFCTRL_DBN (1<<0) + +/* lcd_intstatus, lcd_intenable */ +#define LCD_INT_IFO (0xF<<14) +#define LCD_INT_IFU (0xF<<10) +#define LCD_INT_OFO (1<<9) +#define LCD_INT_OFU (1<<8) +#define LCD_INT_WAIT (1<<3) +#define LCD_INT_SD (1<<2) +#define LCD_INT_SA (1<<1) +#define LCD_INT_SS (1<<0) + +/* lcd_horztiming */ +#define LCD_HORZTIMING_HND2 (0x1FF<<18) +#define LCD_HORZTIMING_HND1 (0x1FF<<9) +#define LCD_HORZTIMING_HPW (0x1FF<<0) +#define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18) +#define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9) +#define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<0) + +/* lcd_verttiming */ +#define LCD_VERTTIMING_VND2 (0x1FF<<18) +#define LCD_VERTTIMING_VND1 (0x1FF<<9) +#define LCD_VERTTIMING_VPW (0x1FF<<0) +#define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18) +#define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9) +#define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<0) + +/* lcd_clkcontrol */ +#define LCD_CLKCONTROL_EXT (1<<22) +#define LCD_CLKCONTROL_DELAY (3<<20) +#define LCD_CLKCONTROL_CDD (1<<19) +#define LCD_CLKCONTROL_IB (1<<18) +#define LCD_CLKCONTROL_IC (1<<17) +#define LCD_CLKCONTROL_IH (1<<16) +#define LCD_CLKCONTROL_IV (1<<15) +#define LCD_CLKCONTROL_BF (0x1F<<10) +#define LCD_CLKCONTROL_PCD (0x3FF<<0) +#define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10) +#define LCD_CLKCONTROL_PCD_N(N) ((N)<<0) + +/* lcd_pwmdiv */ +#define LCD_PWMDIV_EN (1<<31) +#define LCD_PWMDIV_PWMDIV (0x1FFFF<<0) +#define LCD_PWMDIV_PWMDIV_N(N) ((N)<<0) + +/* lcd_pwmhi */ +#define LCD_PWMHI_PWMHI1 (0xFFFF<<16) +#define LCD_PWMHI_PWMHI0 (0xFFFF<<0) +#define LCD_PWMHI_PWMHI1_N(N) ((N)<<16) +#define LCD_PWMHI_PWMHI0_N(N) ((N)<<0) + +/* lcd_hwccon */ +#define LCD_HWCCON_EN (1<<0) + +/* lcd_cursorpos */ +#define LCD_CURSORPOS_HWCXOFF (0x1F<<27) +#define LCD_CURSORPOS_HWCXPOS (0x07FF<<16) +#define LCD_CURSORPOS_HWCYOFF (0x1F<<11) +#define LCD_CURSORPOS_HWCYPOS (0x07FF<<0) +#define LCD_CURSORPOS_HWCXOFF_N(N) ((N)<<27) +#define LCD_CURSORPOS_HWCXPOS_N(N) ((N)<<16) +#define LCD_CURSORPOS_HWCYOFF_N(N) ((N)<<11) +#define LCD_CURSORPOS_HWCYPOS_N(N) ((N)<<0) + +/* lcd_cursorcolor */ +#define LCD_CURSORCOLOR_HWCA (0xFF<<24) +#define LCD_CURSORCOLOR_HWCR (0xFF<<16) +#define LCD_CURSORCOLOR_HWCG (0xFF<<8) +#define LCD_CURSORCOLOR_HWCB (0xFF<<0) +#define LCD_CURSORCOLOR_HWCA_N(N) ((N)<<24) +#define LCD_CURSORCOLOR_HWCR_N(N) ((N)<<16) +#define LCD_CURSORCOLOR_HWCG_N(N) ((N)<<8) +#define LCD_CURSORCOLOR_HWCB_N(N) ((N)<<0) + +/* lcd_fifoctrl */ +#define LCD_FIFOCTRL_F3IF (1<<29) +#define LCD_FIFOCTRL_F3REQ (0x1F<<24) +#define LCD_FIFOCTRL_F2IF (1<<29) +#define LCD_FIFOCTRL_F2REQ (0x1F<<16) +#define LCD_FIFOCTRL_F1IF (1<<29) +#define LCD_FIFOCTRL_F1REQ (0x1F<<8) +#define LCD_FIFOCTRL_F0IF (1<<29) +#define LCD_FIFOCTRL_F0REQ (0x1F<<0) +#define LCD_FIFOCTRL_F3REQ_N(N) ((N-1)<<24) +#define LCD_FIFOCTRL_F2REQ_N(N) ((N-1)<<16) +#define LCD_FIFOCTRL_F1REQ_N(N) ((N-1)<<8) +#define LCD_FIFOCTRL_F0REQ_N(N) ((N-1)<<0) + +/* lcd_outmask */ +#define LCD_OUTMASK_MASK (0x00FFFFFF) + +/********************************************************************/ +#endif /* _AU1200LCD_H */ -- cgit v1.2.3-59-g8ed1b From 59153f7d7effdb5b3c81eb6d03914a866157b319 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 27 Mar 2006 01:17:29 -0800 Subject: [PATCH] fbdev: Make BIOS EDID reading configurable DDC reading via the Video BIOS may take several tens of seconds with some combination of display cards and monitors. Make this option configurable. It defaults to `y' to minimise disruption. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/boot/video.S | 2 ++ drivers/video/Kconfig | 16 ++++++++++++++++ drivers/video/fbmon.c | 6 +++--- 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S index 2ac40c8244c4..0000a2674537 100644 --- a/arch/i386/boot/video.S +++ b/arch/i386/boot/video.S @@ -1924,6 +1924,7 @@ skip10: movb %ah, %al ret store_edid: +#ifdef CONFIG_FB_FIRMWARE_EDID pushw %es # just save all registers pushw %ax pushw %bx @@ -1954,6 +1955,7 @@ store_edid: popw %bx popw %ax popw %es +#endif ret # VIDEO_SELECT-only variables diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3a890610ebe7..22e9d696fdd2 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -70,6 +70,22 @@ config FB_MACMODES depends on FB default n +config FB_FIRMWARE_EDID + bool "Enable firmware EDID" + depends on FB + default y + ---help--- + This enables access to the EDID transferred from the firmware. + On the i386, this is from the Video BIOS. Enable this if DDC/I2C + transfers do not work for your driver and if you are using + nvidiafb, i810fb or savagefb. + + In general, choosing Y for this option is safe. If you + experience extremely long delays while booting before you get + something on your display, try setting this to N. Matrox cards in + combination with certain motherboards and monitors are known to + suffer from this problem. + config FB_MODE_HELPERS bool "Enable Video Mode Handling Helpers" depends on FB diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 7c74e7325d95..53beeb4a9998 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c @@ -1281,7 +1281,7 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) -EINVAL : 0; } -#if defined(__i386__) +#if defined(CONFIG_FB_FIRMWARE_EDID) && defined(__i386__) #include /* @@ -1311,11 +1311,11 @@ const unsigned char *fb_firmware_edid(struct device *device) { return NULL; } -#endif /* _i386_ */ +#endif +EXPORT_SYMBOL(fb_firmware_edid); EXPORT_SYMBOL(fb_parse_edid); EXPORT_SYMBOL(fb_edid_to_monspecs); -EXPORT_SYMBOL(fb_firmware_edid); EXPORT_SYMBOL(fb_get_mode); EXPORT_SYMBOL(fb_validate_mode); EXPORT_SYMBOL(fb_destroy_modedb); -- cgit v1.2.3-59-g8ed1b From db77ec270d00098ff4fbf15f62f4506f6efb25d2 Mon Sep 17 00:00:00 2001 From: Alan Curry Date: Mon, 27 Mar 2006 01:17:30 -0800 Subject: [PATCH] framebuffer: cmap-setting return values A set of 3 small bugfixes, all of which are related to bogus return values of fb colormap-setting functions. First, fb_alloc_cmap returns -1 if memory allocation fails. This is a hard condition to reproduce since you'd have to be really low on memory, but from studying the contexts in which it is called, I think this function should be returning a negative errno, and the -1 will be seen as an EPERM. Switching it to -ENOMEM makes sense. Second, the store_cmap function which is called for writes to /sys/class/graphics/fb0/color_map returns 0 for success, but it should be returning the count of bytes written since its return value ends up in userspace as the result of the write() syscall. Third, radeonfb returns 1 instead of a negative errno when FBIOPUTCMAP is called with an oversized colormap. This is seen in userspace as a return value of 1 from the ioctl() syscall with errno left unchanged. A more useful return value would be -EINVAL. Signed-off-by: Alan Curry Cc: "Antonino A. Daplas" Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/radeon_base.c | 6 +++--- drivers/video/fbcmap.c | 4 ++-- drivers/video/fbsysfs.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index c9f0c5a07e6e..9a6b5b39b88e 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -1067,7 +1067,7 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, if (regno > 255) - return 1; + return -EINVAL; red >>= 8; green >>= 8; @@ -1086,9 +1086,9 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, pindex = regno * 8; if (rinfo->depth == 16 && regno > 63) - return 1; + return -EINVAL; if (rinfo->depth == 15 && regno > 31) - return 1; + return -EINVAL; /* For 565, the green component is mixed one order * below diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index c32a2a50bfa2..1f98392a43b3 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -85,7 +85,7 @@ static struct fb_cmap default_16_colors = { * Allocates memory for a colormap @cmap. @len is the * number of entries in the palette. * - * Returns -1 errno on error, or zero on success. + * Returns negative errno on error, or zero on success. * */ @@ -116,7 +116,7 @@ int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp) fail: fb_dealloc_cmap(cmap); - return -1; + return -ENOMEM; } /** diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 6d26057337e2..b72b05250a9d 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -348,7 +348,7 @@ static ssize_t store_cmap(struct class_device *class_device, const char *buf, fb_copy_cmap(&umap, &fb_info->cmap); fb_dealloc_cmap(&umap); - return rc; + return rc ?: count; } for (i = 0; i < length; i++) { u16 red, blue, green, tsp; @@ -367,7 +367,7 @@ static ssize_t store_cmap(struct class_device *class_device, const char *buf, if (transp) fb_info->cmap.transp[i] = tsp; } - return 0; + return count; } static ssize_t show_cmap(struct class_device *class_device, char *buf) -- cgit v1.2.3-59-g8ed1b From 4d7b84d1cbb213fdfd2b25ffd1217f249ba1d55a Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 27 Mar 2006 01:17:31 -0800 Subject: [PATCH] rivafb: Remove NULL check Remove unnecessary NULL check, as struct info will never be NULL. Coverity Bug 836 Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/riva/fbdev.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 6c19ab6afb01..f841f013b96f 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -2072,8 +2072,6 @@ static void __exit rivafb_remove(struct pci_dev *pd) struct riva_par *par = info->par; NVTRACE_ENTER(); - if (!info) - return; #ifdef CONFIG_FB_RIVA_I2C riva_delete_i2c_busses(par); -- cgit v1.2.3-59-g8ed1b From 8ff7727d2a92f8b99cc709b827859da5d3c46a8a Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 27 Mar 2006 01:17:32 -0800 Subject: [PATCH] nvidiafb: Remove NULL check Remove unnecessary NULL check, as struct info will never be NULL. Coverity Bug 835 Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nvidia.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index c758b386f146..018dd8174c7d 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -1771,8 +1771,6 @@ static void __exit nvidiafb_remove(struct pci_dev *pd) struct nvidia_par *par = info->par; NVTRACE_ENTER(); - if (!info) - return; unregister_framebuffer(info); #ifdef CONFIG_MTRR -- cgit v1.2.3-59-g8ed1b From 3d5b191fff144634a04800e610b7ad0c1aefa6ed Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 27 Mar 2006 01:17:33 -0800 Subject: [PATCH] nvidiafb: Remove NULL check #2 Remove unnecessary NULL check. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nv_i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c index bd9eca05e146..1edb1c432b75 100644 --- a/drivers/video/nvidia/nv_i2c.c +++ b/drivers/video/nvidia/nv_i2c.c @@ -218,8 +218,7 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) } } - if (out_edid) - *out_edid = edid; + *out_edid = edid; return (edid) ? 0 : 1; } -- cgit v1.2.3-59-g8ed1b From 7c518eb84ce75d4c8e8799f4fcad59837f6d1894 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 27 Mar 2006 01:17:33 -0800 Subject: [PATCH] i810fb: Remove NULL check Remove unnecessary NULL check. Being a function private to the driver, out_edid can never be NULL. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/i810/i810-i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c index e3c8b5f1ca76..3fe3ae1aff12 100644 --- a/drivers/video/i810/i810-i2c.c +++ b/drivers/video/i810/i810-i2c.c @@ -210,8 +210,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) } } - if (out_edid) - *out_edid = edid; + *out_edid = edid; return (edid) ? 0 : 1; } -- cgit v1.2.3-59-g8ed1b From 0e4be28023c14624e03a09b4494e919e088513f0 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 27 Mar 2006 01:17:34 -0800 Subject: [PATCH] savagefb: Remove NULL check Remove unnecessary NULL check. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/savage/savagefb-i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 00719a91479f..21debed863ac 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c @@ -273,8 +273,7 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid) } } - if (out_edid) - *out_edid = edid; + *out_edid = edid; return (edid) ? 0 : 1; } -- cgit v1.2.3-59-g8ed1b From eba87e8e8d7024da827accb00ce7e3affd10b7de Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 27 Mar 2006 01:17:35 -0800 Subject: [PATCH] atyfb: Remove dead code Remove code that can never be reached. Coverity Bug 67 Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/atyfb_base.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 485be386a8ff..d790ee76cc70 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -2298,6 +2298,10 @@ static int __init aty_init(struct fb_info *info, const char *name) case CLK_ATI18818_1: par->pll_ops = &aty_pll_ati18818_1; break; + case CLK_IBMRGB514: + par->pll_ops = &aty_pll_ibm514; + break; +#if 0 /* dead code */ case CLK_STG1703: par->pll_ops = &aty_pll_stg1703; break; @@ -2307,9 +2311,7 @@ static int __init aty_init(struct fb_info *info, const char *name) case CLK_ATT20C408: par->pll_ops = &aty_pll_att20c408; break; - case CLK_IBMRGB514: - par->pll_ops = &aty_pll_ibm514; - break; +#endif default: PRINTKI("aty_init: CLK type not implemented yet!"); par->pll_ops = &aty_pll_unsupported; -- cgit v1.2.3-59-g8ed1b From 6257ffacb9e1dc99a910d620ccb92ec88da20a4f Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 27 Mar 2006 01:17:36 -0800 Subject: [PATCH] imsttfb: Remove dead code clk_p is always 0. Coverity Bug 67 Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/imsttfb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index 7db42542eb19..859ba7edfb42 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -440,9 +440,9 @@ getclkMHz(struct imstt_par *par) static void setclkMHz(struct imstt_par *par, __u32 MHz) { - __u32 clk_m, clk_n, clk_p, x, stage, spilled; + __u32 clk_m, clk_n, x, stage, spilled; - clk_m = clk_n = clk_p = 0; + clk_m = clk_n = 0; stage = spilled = 0; for (;;) { switch (stage) { @@ -453,7 +453,7 @@ setclkMHz(struct imstt_par *par, __u32 MHz) clk_n++; break; } - x = 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1)); + x = 20 * (clk_m + 1) / (clk_n + 1); if (x == MHz) break; if (x > MHz) { @@ -466,7 +466,7 @@ setclkMHz(struct imstt_par *par, __u32 MHz) par->init.pclk_m = clk_m; par->init.pclk_n = clk_n; - par->init.pclk_p = clk_p; + par->init.pclk_p = 0; } static struct imstt_regvals * -- cgit v1.2.3-59-g8ed1b From ed49843b897da9969e349c279ffc832efcb93213 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Mon, 27 Mar 2006 01:17:36 -0800 Subject: [PATCH] Add ID for Quadro NVS280 Quadro NVS280 is a dual-head PCIe card with PCI ID 10de:00fd and subsystem ID 10de:0215. Signed-off-by: Pavel Roskin Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nvidia.c | 2 ++ include/linux/pci_ids.h | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 018dd8174c7d..6d3e4890cb43 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -297,6 +297,8 @@ static struct pci_device_id nvidiafb_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x0252, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x0313, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 6f080ae59286..02f6cf20b141 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1052,6 +1052,7 @@ #define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2 #define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3 #define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x00f9 +#define PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280 0x00fd #define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101 #define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103 -- cgit v1.2.3-59-g8ed1b From ac3f9087d337a6ffa1a5fbdf2c923eb0aad1aef6 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 27 Mar 2006 01:17:37 -0800 Subject: [PATCH] sparse: Fix warnings in newport driver about non-static functions There are more sparse warnings but fixing those will require some more work than I want to do without hardware for testing at hand. Signed-off-by: Ralf Baechle Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/newport_con.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index 762c7a593141..e99fe30e568c 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -149,7 +149,7 @@ static inline void newport_clear_lines(int ystart, int yend, int ci) newport_clear_screen(0, ystart, 1280 + 63, yend, ci); } -void newport_reset(void) +static void newport_reset(void) { unsigned short treg; int i; @@ -193,7 +193,7 @@ void newport_reset(void) * calculate the actual screen size by reading * the video timing out of the VC2 */ -void newport_get_screensize(void) +static void newport_get_screensize(void) { int i, cols; unsigned short ventry, treg; -- cgit v1.2.3-59-g8ed1b From b0c87978216836455ef5fbcac6df1ce6679750b0 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Mon, 27 Mar 2006 01:17:38 -0800 Subject: [PATCH] fbdev: add modeline for 1680x1050@60 Add a modeline for the Philips 200W display. aty128fb does not do DDC, it picks 1920x1440 or similar. It works ok with nvidiafb because it can ask for DDC data. mode "1680x1050-60" # D: 146.028 MHz, H: 65.191 kHz, V: 59.863 Hz geometry 1680 1050 1680 1050 16 timings 6848 280 104 30 3 176 6 hsync high vsync high rgba 5/11,6/5,5/0,0/0 endmode hwinfo --monitor 20: None 00.0: 10000 Monitor [Created at monitor.206] Unique ID: rdCR.pzUFTofo1S4 Parent ID: 002j.bJRsY88eNSC Hardware Class: monitor Model: "PHILIPS Philips 200W" Vendor: PHL "PHILIPS" Device: eisa 0x0832 "Philips 200W" Serial ID: "VN 016596" Resolution: 720x400@70Hz Resolution: 640x480@60Hz Resolution: 640x480@67Hz Resolution: 640x480@72Hz Resolution: 640x480@75Hz Resolution: 800x600@56Hz Resolution: 800x600@60Hz Resolution: 800x600@72Hz Resolution: 800x600@75Hz Resolution: 832x624@75Hz Resolution: 1024x768@60Hz Resolution: 1024x768@70Hz Resolution: 1024x768@75Hz Resolution: 1280x1024@75Hz Resolution: 1152x864@70Hz Resolution: 1152x864@75Hz Resolution: 1280x960@60Hz Resolution: 1280x1024@60Hz Resolution: 1680x1050@60Hz Size: 433x271 mm Driver Info #0: Max. Resolution: 1680x1050 Vert. Sync Range: 56-85 Hz Hor. Sync Range: 30-93 kHz Config Status: cfg=new, avail=yes, need=no, active=unknown Attached to: #5 (VGA compatible controller) Signed-off-by: Olaf Hering Acked-by: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/modedb.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 1da2f84bdc25..244a21adc3fe 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -182,6 +182,10 @@ static const struct fb_videomode modedb[] = { /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */ + NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }, { /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */ NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3, -- cgit v1.2.3-59-g8ed1b From d1ae418eef4ce763a95edec0b5fc095af5daca2e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 27 Mar 2006 01:17:39 -0800 Subject: [PATCH] drivers/video: Use ARRAY_SIZE macro Use ARRAY_SIZE macro instead of sizeof(x)/sizeof(x[0]) and remove duplicates of ARRAY_SIZE. Some coding style and trailing whitespaces are also fixed. Compile-tested where possible (some are other arch or BROKEN) Signed-off-by: Tobias Klauser Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/acornfb.c | 8 ++++---- drivers/video/asiliantfb.c | 14 ++++++-------- drivers/video/aty/aty128fb.c | 4 ++-- drivers/video/aty/atyfb_base.c | 8 ++++---- drivers/video/aty/mach64_gx.c | 3 +-- drivers/video/chipsfb.c | 14 ++++++-------- drivers/video/console/fonts.c | 2 +- drivers/video/imsttfb.c | 24 +++++++++++++++--------- drivers/video/macmodes.c | 2 +- drivers/video/matrox/matroxfb_g450.c | 2 +- drivers/video/matrox/matroxfb_maven.c | 6 +++--- drivers/video/modedb.c | 2 +- drivers/video/neofb.c | 8 ++++---- drivers/video/pmagb-b-fb.c | 2 +- drivers/video/radeonfb.c | 2 +- drivers/video/sstfb.c | 11 ++++++----- drivers/video/virgefb.c | 3 +-- 17 files changed, 58 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 76448d6ae896..98baecccb3fd 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -1308,7 +1308,7 @@ static int __init acornfb_probe(struct platform_device *dev) /* * Try to select a suitable default mode */ - for (i = 0; i < sizeof(modedb) / sizeof(*modedb); i++) { + for (i = 0; i < ARRAY_SIZE(modedb); i++) { unsigned long hs; hs = modedb[i].refresh * @@ -1380,7 +1380,7 @@ static int __init acornfb_probe(struct platform_device *dev) */ free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE); #endif - + fb_info.fix.smem_len = size; current_par.palette_size = VIDC_PALETTE_SIZE; @@ -1391,7 +1391,7 @@ static int __init acornfb_probe(struct platform_device *dev) */ do { rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb, - sizeof(modedb) / sizeof(*modedb), + ARRAY_SIZE(modedb), &acornfb_default_mode, DEFAULT_BPP); /* * If we found an exact match, all ok. @@ -1408,7 +1408,7 @@ static int __init acornfb_probe(struct platform_device *dev) break; rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb, - sizeof(modedb) / sizeof(*modedb), + ARRAY_SIZE(modedb), &acornfb_default_mode, DEFAULT_BPP); if (rc) break; diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index c924d81f7978..29f9f0dfe3b4 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c @@ -353,8 +353,6 @@ struct chips_init_reg { unsigned char data; }; -#define N_ELTS(x) (sizeof(x) / sizeof(x[0])) - static struct chips_init_reg chips_init_sr[] = { {0x00, 0x03}, /* Reset register */ @@ -460,22 +458,22 @@ static void __devinit chips_hw_init(struct fb_info *p) { int i; - for (i = 0; i < N_ELTS(chips_init_xr); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i) write_xr(chips_init_xr[i].addr, chips_init_xr[i].data); write_xr(0x81, 0x12); write_xr(0x82, 0x08); write_xr(0x20, 0x00); - for (i = 0; i < N_ELTS(chips_init_sr); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i) write_sr(chips_init_sr[i].addr, chips_init_sr[i].data); - for (i = 0; i < N_ELTS(chips_init_gr); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i) write_gr(chips_init_gr[i].addr, chips_init_gr[i].data); - for (i = 0; i < N_ELTS(chips_init_ar); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i) write_ar(chips_init_ar[i].addr, chips_init_ar[i].data); /* Enable video output in attribute index register */ writeb(0x20, mmio_base + 0x780); - for (i = 0; i < N_ELTS(chips_init_cr); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i) write_cr(chips_init_cr[i].addr, chips_init_cr[i].data); - for (i = 0; i < N_ELTS(chips_init_fr); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i) write_fr(chips_init_fr[i].addr, chips_init_fr[i].data); } diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 620c9a934e0e..821c6da8e42c 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1725,9 +1725,9 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id * strcpy(video_card, "Rage128 XX "); video_card[8] = ent->device >> 8; video_card[9] = ent->device & 0xFF; - + /* range check to make sure */ - if (ent->driver_data < (sizeof(r128_family)/sizeof(char *))) + if (ent->driver_data < ARRAY_SIZE(r128_family)) strncat(video_card, r128_family[ent->driver_data], sizeof(video_card)); printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev); diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index d790ee76cc70..e799fcca365a 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -434,7 +434,7 @@ static int __devinit correct_chipset(struct atyfb_par *par) const char *name; int i; - for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--) + for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--) if (par->pci_id == aty_chips[i].pci_id) break; @@ -2168,10 +2168,10 @@ static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) { refresh_tbl = ragexl_tbl; - size = sizeof(ragexl_tbl)/sizeof(int); + size = ARRAY_SIZE(ragexl_tbl); } else { refresh_tbl = ragepro_tbl; - size = sizeof(ragepro_tbl)/sizeof(int); + size = ARRAY_SIZE(ragepro_tbl); } for (i=0; i < size; i++) { @@ -3399,7 +3399,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi struct atyfb_par *par; int i, rc = -ENOMEM; - for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--) + for (i = ARRAY_SIZE(aty_chips); i >= 0; i--) if (pdev->device == aty_chips[i].pci_id) break; diff --git a/drivers/video/aty/mach64_gx.c b/drivers/video/aty/mach64_gx.c index 01fdff79483b..2045639cb671 100644 --- a/drivers/video/aty/mach64_gx.c +++ b/drivers/video/aty/mach64_gx.c @@ -149,8 +149,7 @@ static int aty_var_to_pll_514(const struct fb_info *info, u32 vclk_per, }; int i; - for (i = 0; i < sizeof(RGB514_clocks) / sizeof(*RGB514_clocks); - i++) + for (i = 0; i < ARRAY_SIZE(RGB514_clocks); i++) if (vclk_per <= RGB514_clocks[i].limit) { pll->ibm514.m = RGB514_clocks[i].m; pll->ibm514.n = RGB514_clocks[i].n; diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index bc061d4ec786..72ff6bf75e5e 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -178,8 +178,6 @@ struct chips_init_reg { unsigned char data; }; -#define N_ELTS(x) (sizeof(x) / sizeof(x[0])) - static struct chips_init_reg chips_init_sr[] = { { 0x00, 0x03 }, { 0x01, 0x01 }, @@ -287,18 +285,18 @@ static void __init chips_hw_init(void) { int i; - for (i = 0; i < N_ELTS(chips_init_xr); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i) write_xr(chips_init_xr[i].addr, chips_init_xr[i].data); outb(0x29, 0x3c2); /* set misc output reg */ - for (i = 0; i < N_ELTS(chips_init_sr); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i) write_sr(chips_init_sr[i].addr, chips_init_sr[i].data); - for (i = 0; i < N_ELTS(chips_init_gr); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i) write_gr(chips_init_gr[i].addr, chips_init_gr[i].data); - for (i = 0; i < N_ELTS(chips_init_ar); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i) write_ar(chips_init_ar[i].addr, chips_init_ar[i].data); - for (i = 0; i < N_ELTS(chips_init_cr); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i) write_cr(chips_init_cr[i].addr, chips_init_cr[i].data); - for (i = 0; i < N_ELTS(chips_init_fr); ++i) + for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i) write_fr(chips_init_fr[i].addr, chips_init_fr[i].data); } diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index 4fd07d9eca03..0cc1bfda76a6 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c @@ -66,7 +66,7 @@ static const struct font_desc *fonts[] = { #endif }; -#define num_fonts (sizeof(fonts)/sizeof(*fonts)) +#define num_fonts ARRAY_SIZE(fonts) #ifdef NO_FONTS #error No fonts configured. diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index 859ba7edfb42..f73c642b50c2 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -1372,18 +1372,24 @@ init_imstt(struct fb_info *info) write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1); write_reg_le32(par->dc_regs, SSR, 0); - /* set default values for DAC registers */ + /* set default values for DAC registers */ if (par->ramdac == IBM) { - par->cmap_regs[PPMASK] = 0xff; eieio(); - par->cmap_regs[PIDXHI] = 0; eieio(); - for (i = 0; i < sizeof(ibm_initregs) / sizeof(*ibm_initregs); i++) { - par->cmap_regs[PIDXLO] = ibm_initregs[i].addr; eieio(); - par->cmap_regs[PIDXDATA] = ibm_initregs[i].value; eieio(); + par->cmap_regs[PPMASK] = 0xff; + eieio(); + par->cmap_regs[PIDXHI] = 0; + eieio(); + for (i = 0; i < ARRAY_SIZE(ibm_initregs); i++) { + par->cmap_regs[PIDXLO] = ibm_initregs[i].addr; + eieio(); + par->cmap_regs[PIDXDATA] = ibm_initregs[i].value; + eieio(); } } else { - for (i = 0; i < sizeof(tvp_initregs) / sizeof(*tvp_initregs); i++) { - par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr; eieio(); - par->cmap_regs[TVPIDATA] = tvp_initregs[i].value; eieio(); + for (i = 0; i < ARRAY_SIZE(tvp_initregs); i++) { + par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr; + eieio(); + par->cmap_regs[TVPIDATA] = tvp_initregs[i].value; + eieio(); } } diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c index 2fc71081f7e7..c0385c6f7db5 100644 --- a/drivers/video/macmodes.c +++ b/drivers/video/macmodes.c @@ -380,7 +380,7 @@ int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info, if (mode_option && !strncmp(mode_option, "mac", 3)) { mode_option += 3; db = mac_modedb; - dbsize = sizeof(mac_modedb)/sizeof(*mac_modedb); + dbsize = ARRAY_SIZE(mac_modedb); } return fb_find_mode(var, info, mode_option, db, dbsize, &mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp); diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c index c122d8743dd2..4d610b405d45 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c @@ -59,7 +59,7 @@ static const struct mctl g450_controls[] = }, offsetof(struct matrox_fb_info, altout.tvo_params.testout) }, }; -#define G450CTRLS (sizeof(g450_controls)/sizeof(g450_controls[0])) +#define G450CTRLS ARRAY_SIZE(g450_controls) /* Return: positive number: id found -EINVAL: id not found, return failure diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index d8b3429cbed3..5d29a26b8cdf 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -89,12 +89,12 @@ static const struct mctl maven_controls[] = }, offsetof(struct matrox_fb_info, altout.tvo_params.hue) }, { { V4L2_CID_GAMMA, V4L2_CTRL_TYPE_INTEGER, "gamma", - 0, sizeof(maven_gamma)/sizeof(maven_gamma[0])-1, 1, 3, + 0, ARRAY_SIZE(maven_gamma) - 1, 1, 3, 0, }, offsetof(struct matrox_fb_info, altout.tvo_params.gamma) }, { { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN, "test output", - 0, 1, 1, 0, + 0, 1, 1, 0, 0, }, offsetof(struct matrox_fb_info, altout.tvo_params.testout) }, { { MATROXFB_CID_DEFLICKER, V4L2_CTRL_TYPE_INTEGER, @@ -105,7 +105,7 @@ static const struct mctl maven_controls[] = }; -#define MAVCTRLS (sizeof(maven_controls)/sizeof(maven_controls[0])) +#define MAVCTRLS ARRAY_SIZE(maven_controls) /* Return: positive number: id found -EINVAL: id not found, return failure diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 244a21adc3fe..26a1c618a205 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -500,7 +500,7 @@ int fb_find_mode(struct fb_var_screeninfo *var, /* Set up defaults */ if (!db) { db = modedb; - dbsize = sizeof(modedb)/sizeof(*modedb); + dbsize = ARRAY_SIZE(modedb); } if (!default_mode) default_mode = &modedb[DEFAULT_MODEDB_INDEX]; diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index b961d5601bd9..24b12f71d5a8 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -165,20 +165,20 @@ static int neoFindMode(int xres, int yres, int depth) switch (depth) { case 8: - size = sizeof(bios8) / sizeof(biosMode); + size = ARRAY_SIZE(bios8); mode = bios8; break; case 16: - size = sizeof(bios16) / sizeof(biosMode); + size = ARRAY_SIZE(bios16); mode = bios16; break; case 24: - size = sizeof(bios24) / sizeof(biosMode); + size = ARRAY_SIZE(bios24); mode = bios24; break; #ifdef NO_32BIT_SUPPORT_YET case 32: - size = sizeof(bios32) / sizeof(biosMode); + size = ARRAY_SIZE(bios32); mode = bios32; break; #endif diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index eeeac924b500..73e2d7d16608 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -228,7 +228,7 @@ static void __init pmagbbfb_osc_setup(struct fb_info *info) freq1 = (par->osc0 * count1 + count0 / 2) / count0; par->osc1 = freq1; - for (i = 0; i < sizeof(pmagbbfb_freqs) / sizeof(*pmagbbfb_freqs); i++) + for (i = 0; i < ARRAY_SIZE(pmagbbfb_freqs); i++) if (freq1 >= pmagbbfb_freqs[i] - (pmagbbfb_freqs[i] + 128) / 256 && freq1 <= pmagbbfb_freqs[i] + diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index db9fb9074dbc..24982adb3aa2 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c @@ -759,7 +759,7 @@ static void __iomem *radeon_find_rom(struct radeonfb_info *rinfo) rom = rom_base; for (i = 0; (i < 512) && (stage != 4); i++) { - for(j = 0;j < sizeof(radeon_sig)/sizeof(char *);j++) { + for (j = 0; j < ARRAY_SIZE(radeon_sig); j++) { if (radeon_sig[j][0] == *rom) if (strncmp(radeon_sig[j], rom, strlen(radeon_sig[j])) == 0) { diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 8c1a8b5135c6..c44de90ca12e 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -1194,10 +1194,11 @@ static struct dac_switch dacs[] __devinitdata = { static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par) { int i, ret = 0; - - for (i=0; ipar; struct pci_dev *dev = par->dev; u32 pci_res[pci_s]; diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c index ed78747487e2..5ea2345dab99 100644 --- a/drivers/video/virgefb.c +++ b/drivers/video/virgefb.c @@ -616,8 +616,7 @@ static struct { #endif }; -#define arraysize(x) (sizeof(x)/sizeof(*(x))) -#define NUM_TOTAL_MODES arraysize(virgefb_predefined) +#define NUM_TOTAL_MODES ARRAY_SIZE(virgefb_predefined) /* * Default to 800x600 for video=virge8:, virge16: or virge32: -- cgit v1.2.3-59-g8ed1b From e4ccde33de202fae1b1e2a940604ee9e295450d9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 27 Mar 2006 01:17:41 -0800 Subject: [PATCH] video/sis/init301.c:SiS_ChrontelDoSomething2(): remove dead code The Coverity checker spotted these two unused variables. Signed-off-by: Adrian Bunk Cc: "Antonino A. Daplas" Cc: Thomas Winischhofer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/sis/init301.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c index 2d88f908170a..c3e070a6effd 100644 --- a/drivers/video/sis/init301.c +++ b/drivers/video/sis/init301.c @@ -8564,11 +8564,9 @@ SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo) static void SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr) { - unsigned short temp,tempcl,tempch; + unsigned short temp; SiS_LongDelay(SiS_Pr, 1); - tempcl = 3; - tempch = 0; do { temp = SiS_GetCH701x(SiS_Pr,0x66); @@ -8582,13 +8580,6 @@ SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr) SiS_SetCH701xForLCD(SiS_Pr); - if(tempcl == 0) { - if(tempch == 3) break; - SiS_ChrontelResetDB(SiS_Pr); - tempcl = 3; - tempch++; - } - tempcl--; temp = SiS_GetCH701x(SiS_Pr,0x76); temp &= 0xfb; /* Reset PLL */ SiS_SetCH701x(SiS_Pr,0x76,temp); -- cgit v1.2.3-59-g8ed1b From eccf081799be8d83852f183838bf26e1ca099db4 Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Mon, 27 Mar 2006 01:17:42 -0800 Subject: [PATCH] device-mapper snapshot: fix origin_write pending_exception submission Say you have several snapshots of the same origin and then you issue a write to some place in the origin for the first time. Before the device-mapper snapshot target lets the write go through to the underlying device, it needs to make a copy of the data that is about to be overwritten. Each snapshot is independent, so it makes one copy for each snapshot. __origin_write() loops through each snapshot and checks to see whether a copy is needed for that snapshot. (A copy is only needed the first time that data changes.) If a copy is needed, the code allocates a 'pending_exception' structure holding the details. It links these together for all the snapshots, then works its way through this list and submits the copying requests to the kcopyd thread by calling start_copy(). When each request is completed, the original pending_exception structure gets freed in pending_complete(). If you're very unlucky, this structure can get freed *before* the submission process has finished walking the list. This patch: 1) Creates a new temporary list pe_queue to hold the pending exception structures; 2) Does all the bookkeeping up-front, then walks through the new list safely and calls start_copy() for each pending_exception that needed it; 3) Avoids attempting to add pe->siblings to the list if it's already connected. [NB This does not fix all the races in this code. More patches will follow.] Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-snap.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 7401540086df..874f145431d8 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -48,6 +48,11 @@ struct pending_exception { struct bio_list origin_bios; struct bio_list snapshot_bios; + /* + * Short-term queue of pending exceptions prior to submission. + */ + struct list_head list; + /* * Other pending_exceptions that are processing this * chunk. When this list is empty, we know we can @@ -930,8 +935,9 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) int r = 1, first = 1; struct dm_snapshot *snap; struct exception *e; - struct pending_exception *pe, *last = NULL; + struct pending_exception *pe, *next_pe, *last = NULL; chunk_t chunk; + LIST_HEAD(pe_queue); /* Do all the snapshots on this origin */ list_for_each_entry (snap, snapshots, list) { @@ -965,12 +971,19 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) snap->valid = 0; } else { - if (last) + if (first) { + bio_list_add(&pe->origin_bios, bio); + r = 0; + first = 0; + } + if (last && list_empty(&pe->siblings)) list_merge(&pe->siblings, &last->siblings); - + if (!pe->started) { + pe->started = 1; + list_add_tail(&pe->list, &pe_queue); + } last = pe; - r = 0; } } @@ -980,24 +993,8 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) /* * Now that we have a complete pe list we can start the copying. */ - if (last) { - pe = last; - do { - down_write(&pe->snap->lock); - if (first) - bio_list_add(&pe->origin_bios, bio); - if (!pe->started) { - pe->started = 1; - up_write(&pe->snap->lock); - start_copy(pe); - } else - up_write(&pe->snap->lock); - first = 0; - pe = list_entry(pe->siblings.next, - struct pending_exception, siblings); - - } while (pe != last); - } + list_for_each_entry_safe(pe, next_pe, &pe_queue, list) + start_copy(pe); return r; } -- cgit v1.2.3-59-g8ed1b From b4b610f684d13bf8691feeae5d4d7a8bd1f1033e Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Mon, 27 Mar 2006 01:17:44 -0800 Subject: [PATCH] device-mapper snapshot: replace sibling list The siblings "list" is used unsafely at the moment. Firstly, only the element on the list being changed gets locked (via the snapshot lock), not the next and previous elements which have pointers that are also being changed. Secondly, if you have two or more snapshots and write to the same chunk a second time before every snapshot has finished making its private copy of the data, if you're unlucky, _origin_write() could attempt its list_merge() and dereference a 'last' pointer to a pending_exception structure that has just been freed. Analysis reveals that the list is actually only there for reference counting. If 5 pending_exceptions are needed in origin_write, then the 5 are joined together into a 5-element list - without a separate list head because there's nowhere suitable to store it. As the pending_exceptions complete, they are removed from the list one-by-one and any contents of origin_bios get moved across to one of the remaining pending_exceptions on the list. Whichever one is last is detected because list_empty() is then true and the origin_bios get submitted. The fix proposed here uses an alternative reference counting mechanism by choosing one of the pending_exceptions as primary and maintaining an atomic counter there. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-snap.c | 122 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 874f145431d8..475514bda9d0 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -54,11 +54,21 @@ struct pending_exception { struct list_head list; /* - * Other pending_exceptions that are processing this - * chunk. When this list is empty, we know we can - * complete the origins. + * The primary pending_exception is the one that holds + * the sibling_count and the list of origin_bios for a + * group of pending_exceptions. It is always last to get freed. + * These fields get set up when writing to the origin. */ - struct list_head siblings; + struct pending_exception *primary_pe; + + /* + * Number of pending_exceptions processing this chunk. + * When this drops to zero we must complete the origin bios. + * If incrementing or decrementing this, hold pe->snap->lock for + * the sibling concerned and not pe->primary_pe->snap->lock unless + * they are the same. + */ + atomic_t sibling_count; /* Pointer back to snapshot context */ struct dm_snapshot *snap; @@ -593,20 +603,15 @@ static void error_bios(struct bio *bio) static struct bio *__flush_bios(struct pending_exception *pe) { - struct pending_exception *sibling; - - if (list_empty(&pe->siblings)) - return bio_list_get(&pe->origin_bios); - - sibling = list_entry(pe->siblings.next, - struct pending_exception, siblings); - - list_del(&pe->siblings); - - /* This is fine as long as kcopyd is single-threaded. If kcopyd - * becomes multi-threaded, we'll need some locking here. + /* + * If this pe is involved in a write to the origin and + * it is the last sibling to complete then release + * the bios for the original write to the origin. */ - bio_list_merge(&sibling->origin_bios, &pe->origin_bios); + + if (pe->primary_pe && + atomic_dec_and_test(&pe->primary_pe->sibling_count)) + return bio_list_get(&pe->primary_pe->origin_bios); return NULL; } @@ -614,6 +619,7 @@ static struct bio *__flush_bios(struct pending_exception *pe) static void pending_complete(struct pending_exception *pe, int success) { struct exception *e; + struct pending_exception *primary_pe; struct dm_snapshot *s = pe->snap; struct bio *flush = NULL; @@ -662,7 +668,20 @@ static void pending_complete(struct pending_exception *pe, int success) } out: - free_pending_exception(pe); + primary_pe = pe->primary_pe; + + /* + * Free the pe if it's not linked to an origin write or if + * it's not itself a primary pe. + */ + if (!primary_pe || primary_pe != pe) + free_pending_exception(pe); + + /* + * Free the primary pe if nothing references it. + */ + if (primary_pe && !atomic_read(&primary_pe->sibling_count)) + free_pending_exception(primary_pe); if (flush) flush_bios(flush); @@ -757,7 +776,8 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio) pe->e.old_chunk = chunk; bio_list_init(&pe->origin_bios); bio_list_init(&pe->snapshot_bios); - INIT_LIST_HEAD(&pe->siblings); + pe->primary_pe = NULL; + atomic_set(&pe->sibling_count, 1); pe->snap = s; pe->started = 0; @@ -916,26 +936,12 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, /*----------------------------------------------------------------- * Origin methods *---------------------------------------------------------------*/ -static void list_merge(struct list_head *l1, struct list_head *l2) -{ - struct list_head *l1_n, *l2_p; - - l1_n = l1->next; - l2_p = l2->prev; - - l1->next = l2; - l2->prev = l1; - - l2_p->next = l1_n; - l1_n->prev = l2_p; -} - static int __origin_write(struct list_head *snapshots, struct bio *bio) { - int r = 1, first = 1; + int r = 1, first = 0; struct dm_snapshot *snap; struct exception *e; - struct pending_exception *pe, *next_pe, *last = NULL; + struct pending_exception *pe, *next_pe, *primary_pe = NULL; chunk_t chunk; LIST_HEAD(pe_queue); @@ -962,6 +968,9 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) * Check exception table to see if block * is already remapped in this snapshot * and trigger an exception if not. + * + * sibling_count is initialised to 1 so pending_complete() + * won't destroy the primary_pe while we're inside this loop. */ e = lookup_exception(&snap->complete, chunk); if (!e) { @@ -971,31 +980,60 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) snap->valid = 0; } else { - if (first) { - bio_list_add(&pe->origin_bios, bio); + if (!primary_pe) { + /* + * Either every pe here has same + * primary_pe or none has one yet. + */ + if (pe->primary_pe) + primary_pe = pe->primary_pe; + else { + primary_pe = pe; + first = 1; + } + + bio_list_add(&primary_pe->origin_bios, + bio); r = 0; - first = 0; } - if (last && list_empty(&pe->siblings)) - list_merge(&pe->siblings, - &last->siblings); + if (!pe->primary_pe) { + atomic_inc(&primary_pe->sibling_count); + pe->primary_pe = primary_pe; + } if (!pe->started) { pe->started = 1; list_add_tail(&pe->list, &pe_queue); } - last = pe; } } up_write(&snap->lock); } + if (!primary_pe) + goto out; + + /* + * If this is the first time we're processing this chunk and + * sibling_count is now 1 it means all the pending exceptions + * got completed while we were in the loop above, so it falls to + * us here to remove the primary_pe and submit any origin_bios. + */ + + if (first && atomic_dec_and_test(&primary_pe->sibling_count)) { + flush_bios(bio_list_get(&primary_pe->origin_bios)); + free_pending_exception(primary_pe); + /* If we got here, pe_queue is necessarily empty. */ + goto out; + } + /* * Now that we have a complete pe list we can start the copying. */ list_for_each_entry_safe(pe, next_pe, &pe_queue, list) start_copy(pe); + out: return r; } -- cgit v1.2.3-59-g8ed1b From 76df1c651b66bdf07d60b3d60789feb5f58d73e3 Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Mon, 27 Mar 2006 01:17:45 -0800 Subject: [PATCH] device-mapper snapshot: fix invalidation When a snapshot becomes invalid, s->valid is set to 0. In this state, a snapshot can no longer be accessed. When s->lock is acquired, before doing anything else, s->valid must be checked to ensure the snapshot remains valid. This patch eliminates some races (that may cause panics) by adding some missing checks. At the same time, some unnecessary levels of indentation are removed and snapshot invalidation is moved into a single function that always generates a device-mapper event. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-snap.c | 295 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 174 insertions(+), 121 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 475514bda9d0..14bd1a1815b1 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -392,6 +392,8 @@ static void read_snapshot_metadata(struct dm_snapshot *s) down_write(&s->lock); s->valid = 0; up_write(&s->lock); + + dm_table_event(s->table); } } @@ -601,6 +603,11 @@ static void error_bios(struct bio *bio) } } +static inline void error_snapshot_bios(struct pending_exception *pe) +{ + error_bios(bio_list_get(&pe->snapshot_bios)); +} + static struct bio *__flush_bios(struct pending_exception *pe) { /* @@ -616,6 +623,28 @@ static struct bio *__flush_bios(struct pending_exception *pe) return NULL; } +static void __invalidate_snapshot(struct dm_snapshot *s, + struct pending_exception *pe, int err) +{ + if (!s->valid) + return; + + if (err == -EIO) + DMERR("Invalidating snapshot: Error reading/writing."); + else if (err == -ENOMEM) + DMERR("Invalidating snapshot: Unable to allocate exception."); + + if (pe) + remove_exception(&pe->e); + + if (s->store.drop_snapshot) + s->store.drop_snapshot(&s->store); + + s->valid = 0; + + dm_table_event(s->table); +} + static void pending_complete(struct pending_exception *pe, int success) { struct exception *e; @@ -623,50 +652,53 @@ static void pending_complete(struct pending_exception *pe, int success) struct dm_snapshot *s = pe->snap; struct bio *flush = NULL; - if (success) { - e = alloc_exception(); - if (!e) { - DMWARN("Unable to allocate exception."); - down_write(&s->lock); - s->store.drop_snapshot(&s->store); - s->valid = 0; - flush = __flush_bios(pe); - up_write(&s->lock); - - error_bios(bio_list_get(&pe->snapshot_bios)); - goto out; - } - *e = pe->e; - - /* - * Add a proper exception, and remove the - * in-flight exception from the list. - */ + if (!success) { + /* Read/write error - snapshot is unusable */ down_write(&s->lock); - insert_exception(&s->complete, e); - remove_exception(&pe->e); + __invalidate_snapshot(s, pe, -EIO); flush = __flush_bios(pe); - - /* Submit any pending write bios */ up_write(&s->lock); - flush_bios(bio_list_get(&pe->snapshot_bios)); - } else { - /* Read/write error - snapshot is unusable */ + error_snapshot_bios(pe); + goto out; + } + + e = alloc_exception(); + if (!e) { down_write(&s->lock); - if (s->valid) - DMERR("Error reading/writing snapshot"); - s->store.drop_snapshot(&s->store); - s->valid = 0; - remove_exception(&pe->e); + __invalidate_snapshot(s, pe, -ENOMEM); flush = __flush_bios(pe); up_write(&s->lock); - error_bios(bio_list_get(&pe->snapshot_bios)); + error_snapshot_bios(pe); + goto out; + } + *e = pe->e; - dm_table_event(s->table); + /* + * Add a proper exception, and remove the + * in-flight exception from the list. + */ + down_write(&s->lock); + if (!s->valid) { + flush = __flush_bios(pe); + up_write(&s->lock); + + free_exception(e); + + error_snapshot_bios(pe); + goto out; } + insert_exception(&s->complete, e); + remove_exception(&pe->e); + flush = __flush_bios(pe); + + up_write(&s->lock); + + /* Submit any pending write bios */ + flush_bios(bio_list_get(&pe->snapshot_bios)); + out: primary_pe = pe->primary_pe; @@ -758,39 +790,45 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio) if (e) { /* cast the exception to a pending exception */ pe = container_of(e, struct pending_exception, e); + goto out; + } - } else { - /* - * Create a new pending exception, we don't want - * to hold the lock while we do this. - */ - up_write(&s->lock); - pe = alloc_pending_exception(); - down_write(&s->lock); + /* + * Create a new pending exception, we don't want + * to hold the lock while we do this. + */ + up_write(&s->lock); + pe = alloc_pending_exception(); + down_write(&s->lock); - e = lookup_exception(&s->pending, chunk); - if (e) { - free_pending_exception(pe); - pe = container_of(e, struct pending_exception, e); - } else { - pe->e.old_chunk = chunk; - bio_list_init(&pe->origin_bios); - bio_list_init(&pe->snapshot_bios); - pe->primary_pe = NULL; - atomic_set(&pe->sibling_count, 1); - pe->snap = s; - pe->started = 0; - - if (s->store.prepare_exception(&s->store, &pe->e)) { - free_pending_exception(pe); - s->valid = 0; - return NULL; - } + if (!s->valid) { + free_pending_exception(pe); + return NULL; + } - insert_exception(&s->pending, &pe->e); - } + e = lookup_exception(&s->pending, chunk); + if (e) { + free_pending_exception(pe); + pe = container_of(e, struct pending_exception, e); + goto out; } + pe->e.old_chunk = chunk; + bio_list_init(&pe->origin_bios); + bio_list_init(&pe->snapshot_bios); + pe->primary_pe = NULL; + atomic_set(&pe->sibling_count, 1); + pe->snap = s; + pe->started = 0; + + if (s->store.prepare_exception(&s->store, &pe->e)) { + free_pending_exception(pe); + return NULL; + } + + insert_exception(&s->pending, &pe->e); + + out: return pe; } @@ -807,13 +845,15 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, { struct exception *e; struct dm_snapshot *s = (struct dm_snapshot *) ti->private; + int copy_needed = 0; int r = 1; chunk_t chunk; - struct pending_exception *pe; + struct pending_exception *pe = NULL; chunk = sector_to_chunk(s, bio->bi_sector); /* Full snapshots are not usable */ + /* To get here the table must be live so s->active is always set. */ if (!s->valid) return -EIO; @@ -831,36 +871,41 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, * to copy an exception */ down_write(&s->lock); + if (!s->valid) { + r = -EIO; + goto out_unlock; + } + /* If the block is already remapped - use that, else remap it */ e = lookup_exception(&s->complete, chunk); if (e) { remap_exception(s, e, bio); - up_write(&s->lock); - - } else { - pe = __find_pending_exception(s, bio); - - if (!pe) { - if (s->store.drop_snapshot) - s->store.drop_snapshot(&s->store); - s->valid = 0; - r = -EIO; - up_write(&s->lock); - } else { - remap_exception(s, &pe->e, bio); - bio_list_add(&pe->snapshot_bios, bio); - - if (!pe->started) { - /* this is protected by snap->lock */ - pe->started = 1; - up_write(&s->lock); - start_copy(pe); - } else - up_write(&s->lock); - r = 0; - } + goto out_unlock; + } + + pe = __find_pending_exception(s, bio); + if (!pe) { + __invalidate_snapshot(s, pe, -ENOMEM); + r = -EIO; + goto out_unlock; } + remap_exception(s, &pe->e, bio); + bio_list_add(&pe->snapshot_bios, bio); + + if (!pe->started) { + /* this is protected by snap->lock */ + pe->started = 1; + copy_needed = 1; + } + + r = 0; + + out_unlock: + up_write(&s->lock); + + if (copy_needed) + start_copy(pe); } else { /* * FIXME: this read path scares me because we @@ -872,6 +917,11 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, /* Do reads */ down_read(&s->lock); + if (!s->valid) { + up_read(&s->lock); + return -EIO; + } + /* See if it it has been remapped */ e = lookup_exception(&s->complete, chunk); if (e) @@ -948,15 +998,15 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) /* Do all the snapshots on this origin */ list_for_each_entry (snap, snapshots, list) { + down_write(&snap->lock); + /* Only deal with valid and active snapshots */ if (!snap->valid || !snap->active) - continue; + goto next_snapshot; /* Nothing to do if writing beyond end of snapshot */ if (bio->bi_sector >= dm_table_get_size(snap->table)) - continue; - - down_write(&snap->lock); + goto next_snapshot; /* * Remember, different snapshots can have @@ -973,40 +1023,43 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) * won't destroy the primary_pe while we're inside this loop. */ e = lookup_exception(&snap->complete, chunk); - if (!e) { - pe = __find_pending_exception(snap, bio); - if (!pe) { - snap->store.drop_snapshot(&snap->store); - snap->valid = 0; - - } else { - if (!primary_pe) { - /* - * Either every pe here has same - * primary_pe or none has one yet. - */ - if (pe->primary_pe) - primary_pe = pe->primary_pe; - else { - primary_pe = pe; - first = 1; - } - - bio_list_add(&primary_pe->origin_bios, - bio); - r = 0; - } - if (!pe->primary_pe) { - atomic_inc(&primary_pe->sibling_count); - pe->primary_pe = primary_pe; - } - if (!pe->started) { - pe->started = 1; - list_add_tail(&pe->list, &pe_queue); - } + if (e) + goto next_snapshot; + + pe = __find_pending_exception(snap, bio); + if (!pe) { + __invalidate_snapshot(snap, pe, ENOMEM); + goto next_snapshot; + } + + if (!primary_pe) { + /* + * Either every pe here has same + * primary_pe or none has one yet. + */ + if (pe->primary_pe) + primary_pe = pe->primary_pe; + else { + primary_pe = pe; + first = 1; } + + bio_list_add(&primary_pe->origin_bios, bio); + + r = 0; + } + + if (!pe->primary_pe) { + atomic_inc(&primary_pe->sibling_count); + pe->primary_pe = primary_pe; + } + + if (!pe->started) { + pe->started = 1; + list_add_tail(&pe->list, &pe_queue); } + next_snapshot: up_write(&snap->lock); } -- cgit v1.2.3-59-g8ed1b From 930d332a23682202c07df0276dd665a57755b37d Mon Sep 17 00:00:00 2001 From: Jun'ichi Nomura Date: Mon, 27 Mar 2006 01:17:47 -0800 Subject: [PATCH] drivers/md/dm-raid1.c: Fix inconsistent mirroring after interrupted recovery dm-mirror has potential data corruption problem: while on-disk log shows that all disk contents are in-sync, actual contents of the disks are not synchronized. This problem occurs if initial recovery (synching) is interrupted and resumed. Attached patch fixes this problem. Background: rh_dec() changes the region state from RH_NOSYNC (out-of-sync) to RH_CLEAN (in-sync), which results in the corresponding bit of clean_bits being set. This is harmful if on-disk log is used and the map is removed/suspended before the initial sync is completed. The clean_bits is written down to the on-disk log at the map removal, and, upon resume, it's read and copied to sync_bits. Since the recovery process refers to the sync_bits to find a region to be recovered, the region whose state was changed from RH_NOSYNC to RH_CLEAN is no longer recovered. If you haven't applied dm-raid1-read-balancing.patch proposed in dm-devel sometimes ago, the contents of the mirrored disk just corrupt silently. If you have, balanced read may get bogus data from out-of-sync disks. The patch keeps RH_NOSYNC state unchanged. It will be changed to RH_RECOVERING when recovery starts and get reclaimed when the recovery completes. So it doesn't leak the region hash entry. Description: Keep RH_NOSYNC state unchanged when I/O on the region completes. rh_dec() changes the region state from RH_NOSYNC (out-of-sync) to RH_CLEAN (in-sync), which results in the corresponding bit of clean_bits being set. This is harmful if on-disk log is used and the map is removed/suspended before the initial sync is completed. The clean_bits is written down to the on-disk log at the map removal, and, upon resume, it's read and copied to sync_bits. Since the recovery process refers to the sync_bits to find a region to be recovered, the region whose state was changed from RH_NOSYNC to RH_CLEAN is no longer recovered. If you haven't applied dm-raid1-read-balancing.patch proposed in dm-devel sometimes ago, the contents of the mirrored disk just corrupt silently. If you have, balanced read may get bogus data from out-of-sync disks. The RH_NOSYNC region will be changed to RH_RECOVERING when recovery starts on the region and get reclaimed when the recovery completes. So it doesn't leak the region hash entry. Alasdair said: I've analysed the relevant part of the state machine and I believe that the patch is correct. (Further work on this code is still needed - this patch has the side-effect of holding onto memory unnecessarily for long periods of time under certain workloads - but better that than corrupting data.) Signed-off-by: Jun'ichi Nomura Acked-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-raid1.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 4e90f231fbfb..3d90f1b37e08 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -402,9 +402,21 @@ static void rh_dec(struct region_hash *rh, region_t region) spin_lock_irqsave(&rh->region_lock, flags); if (atomic_dec_and_test(®->pending)) { + /* + * There is no pending I/O for this region. + * We can move the region to corresponding list for next action. + * At this point, the region is not yet connected to any list. + * + * If the state is RH_NOSYNC, the region should be kept off + * from clean list. + * The hash entry for RH_NOSYNC will remain in memory + * until the region is recovered or the map is reloaded. + */ + + /* do nothing for RH_NOSYNC */ if (reg->state == RH_RECOVERING) { list_add_tail(®->list, &rh->quiesced_regions); - } else { + } else if (reg->state == RH_DIRTY) { reg->state = RH_CLEAN; list_add(®->list, &rh->clean_regions); } -- cgit v1.2.3-59-g8ed1b From 4ee218cd67b385759993a6c840ea45f0ee0a8b30 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 27 Mar 2006 01:17:48 -0800 Subject: [PATCH] dm: remove SECTOR_FORMAT We don't know what type sector_t has. Sometimes it's unsigned long, sometimes it's unsigned long long. For example on ppc64 it's unsigned long with CONFIG_LBD=n and on x86_64 it's unsigned long long with CONFIG_LBD=n. The way to handle all of this is to always use unsigned long long and to always typecast the sector_t when printing it. Acked-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-crypt.c | 11 +++++++---- drivers/md/dm-linear.c | 8 +++++--- drivers/md/dm-raid1.c | 15 ++++++++------- drivers/md/dm-snap.c | 11 ++++++----- drivers/md/dm-stripe.c | 11 ++++++----- drivers/md/dm.h | 10 ---------- 6 files changed, 32 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 259e86f26549..61a590bb6241 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -518,6 +518,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) char *ivopts; unsigned int crypto_flags; unsigned int key_size; + unsigned long long tmpll; if (argc != 5) { ti->error = PFX "Not enough arguments"; @@ -633,15 +634,17 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad5; } - if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) { + if (sscanf(argv[2], "%llu", &tmpll) != 1) { ti->error = PFX "Invalid iv_offset sector"; goto bad5; } + cc->iv_offset = tmpll; - if (sscanf(argv[4], SECTOR_FORMAT, &cc->start) != 1) { + if (sscanf(argv[4], "%llu", &tmpll) != 1) { ti->error = PFX "Invalid device sector"; goto bad5; } + cc->start = tmpll; if (dm_get_device(ti, argv[3], cc->start, ti->len, dm_table_get_mode(ti->table), &cc->dev)) { @@ -885,8 +888,8 @@ static int crypt_status(struct dm_target *ti, status_type_t type, result[sz++] = '-'; } - DMEMIT(" " SECTOR_FORMAT " %s " SECTOR_FORMAT, - cc->iv_offset, cc->dev->name, cc->start); + DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset, + cc->dev->name, (unsigned long long)cc->start); break; } return 0; diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 6a2cd5dc8a63..daf586c0898d 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -26,6 +26,7 @@ struct linear_c { static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) { struct linear_c *lc; + unsigned long long tmp; if (argc != 2) { ti->error = "dm-linear: Invalid argument count"; @@ -38,10 +39,11 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) return -ENOMEM; } - if (sscanf(argv[1], SECTOR_FORMAT, &lc->start) != 1) { + if (sscanf(argv[1], "%llu", &tmp) != 1) { ti->error = "dm-linear: Invalid device sector"; goto bad; } + lc->start = tmp; if (dm_get_device(ti, argv[0], lc->start, ti->len, dm_table_get_mode(ti->table), &lc->dev)) { @@ -87,8 +89,8 @@ static int linear_status(struct dm_target *ti, status_type_t type, break; case STATUSTYPE_TABLE: - snprintf(result, maxlen, "%s " SECTOR_FORMAT, lc->dev->name, - lc->start); + snprintf(result, maxlen, "%s %llu", lc->dev->name, + (unsigned long long)lc->start); break; } return 0; diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 3d90f1b37e08..d12cf3e5e076 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -934,9 +934,9 @@ static inline int _check_region_size(struct dm_target *ti, uint32_t size) static int get_mirror(struct mirror_set *ms, struct dm_target *ti, unsigned int mirror, char **argv) { - sector_t offset; + unsigned long long offset; - if (sscanf(argv[1], SECTOR_FORMAT, &offset) != 1) { + if (sscanf(argv[1], "%llu", &offset) != 1) { ti->error = "dm-mirror: Invalid offset"; return -EINVAL; } @@ -1203,16 +1203,17 @@ static int mirror_status(struct dm_target *ti, status_type_t type, for (m = 0; m < ms->nr_mirrors; m++) DMEMIT("%s ", ms->mirror[m].dev->name); - DMEMIT(SECTOR_FORMAT "/" SECTOR_FORMAT, - ms->rh.log->type->get_sync_count(ms->rh.log), - ms->nr_regions); + DMEMIT("%llu/%llu", + (unsigned long long)ms->rh.log->type-> + get_sync_count(ms->rh.log), + (unsigned long long)ms->nr_regions); break; case STATUSTYPE_TABLE: DMEMIT("%d ", ms->nr_mirrors); for (m = 0; m < ms->nr_mirrors; m++) - DMEMIT("%s " SECTOR_FORMAT " ", - ms->mirror[m].dev->name, ms->mirror[m].offset); + DMEMIT("%s %llu ", ms->mirror[m].dev->name, + (unsigned long long)ms->mirror[m].offset); } return 0; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 14bd1a1815b1..a5765f9fbe02 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -959,9 +959,9 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, snap->store.fraction_full(&snap->store, &numerator, &denominator); - snprintf(result, maxlen, - SECTOR_FORMAT "/" SECTOR_FORMAT, - numerator, denominator); + snprintf(result, maxlen, "%llu/%llu", + (unsigned long long)numerator, + (unsigned long long)denominator); } else snprintf(result, maxlen, "Unknown"); @@ -974,9 +974,10 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, * to make private copies if the output is to * make sense. */ - snprintf(result, maxlen, "%s %s %c " SECTOR_FORMAT, + snprintf(result, maxlen, "%s %s %c %llu", snap->origin->name, snap->cow->name, - snap->type, snap->chunk_size); + snap->type, + (unsigned long long)snap->chunk_size); break; } diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 697aacafb02a..204f796ee9e3 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -49,9 +49,9 @@ static inline struct stripe_c *alloc_context(unsigned int stripes) static int get_stripe(struct dm_target *ti, struct stripe_c *sc, unsigned int stripe, char **argv) { - sector_t start; + unsigned long long start; - if (sscanf(argv[1], SECTOR_FORMAT, &start) != 1) + if (sscanf(argv[1], "%llu", &start) != 1) return -EINVAL; if (dm_get_device(ti, argv[0], start, sc->stripe_width, @@ -201,10 +201,11 @@ static int stripe_status(struct dm_target *ti, break; case STATUSTYPE_TABLE: - DMEMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1); + DMEMIT("%d %llu", sc->stripes, + (unsigned long long)sc->chunk_mask + 1); for (i = 0; i < sc->stripes; i++) - DMEMIT(" %s " SECTOR_FORMAT, sc->stripe[i].dev->name, - sc->stripe[i].physical_start); + DMEMIT(" %s %llu", sc->stripe[i].dev->name, + (unsigned long long)sc->stripe[i].physical_start); break; } return 0; diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 4eaf075da217..0ff11d6f8158 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -23,16 +23,6 @@ #define DMEMIT(x...) sz += ((sz >= maxlen) ? \ 0 : scnprintf(result + sz, maxlen - sz, x)) -/* - * FIXME: I think this should be with the definition of sector_t - * in types.h. - */ -#ifdef CONFIG_LBD -#define SECTOR_FORMAT "%llu" -#else -#define SECTOR_FORMAT "%lu" -#endif - #define SECTOR_SHIFT 9 /* -- cgit v1.2.3-59-g8ed1b From 969429b504ae866d3f8b1cafd68a2c099e305093 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:17:49 -0800 Subject: [PATCH] dm: make sure QUEUE_FLAG_CLUSTER is set properly This flag should be set for a virtual device iff it is set for all underlying devices. Signed-off-by: Neil Brown Acked-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-table.c | 9 +++++++++ include/linux/device-mapper.h | 1 + 2 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 907b08ddb783..9558a4acec12 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -97,6 +97,8 @@ static void combine_restrictions_low(struct io_restrictions *lhs, lhs->seg_boundary_mask = min_not_zero(lhs->seg_boundary_mask, rhs->seg_boundary_mask); + + lhs->no_cluster |= rhs->no_cluster; } /* @@ -523,6 +525,8 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start, rs->seg_boundary_mask = min_not_zero(rs->seg_boundary_mask, q->seg_boundary_mask); + + rs->no_cluster |= !test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); } return r; @@ -832,6 +836,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q) q->hardsect_size = t->limits.hardsect_size; q->max_segment_size = t->limits.max_segment_size; q->seg_boundary_mask = t->limits.seg_boundary_mask; + if (t->limits.no_cluster) + q->queue_flags &= ~(1 << QUEUE_FLAG_CLUSTER); + else + q->queue_flags |= (1 << QUEUE_FLAG_CLUSTER); + } unsigned int dm_table_get_num_targets(struct dm_table *t) diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 51e0e95a421a..aee10b2ea4c6 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -97,6 +97,7 @@ struct io_restrictions { unsigned short hardsect_size; unsigned int max_segment_size; unsigned long seg_boundary_mask; + unsigned char no_cluster; /* inverted so that 0 is default */ }; struct dm_target { -- cgit v1.2.3-59-g8ed1b From 138728dc96529f20dfe970c470e51885a60e329f Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Mon, 27 Mar 2006 01:17:50 -0800 Subject: [PATCH] dm snapshot: fix kcopyd destructor Before removing a snapshot, wait for the completion of any kcopyd jobs using it. Do this by maintaining a count (nr_jobs) of how many outstanding jobs each kcopyd_client has. The snapshot destructor first unregisters the snapshot so that no new kcopyd jobs (created by writes to the origin) will reference that particular snapshot. kcopyd_client_destroy() is now run next to wait for the completion of any outstanding jobs before the snapshot exception structures (that those jobs reference) are freed. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-snap.c | 6 +++++- drivers/md/kcopyd.c | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index a5765f9fbe02..08312b46463a 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -559,8 +559,12 @@ static void snapshot_dtr(struct dm_target *ti) { struct dm_snapshot *s = (struct dm_snapshot *) ti->private; + /* Prevent further origin writes from using this snapshot. */ + /* After this returns there can be no new kcopyd jobs. */ unregister_snapshot(s); + kcopyd_client_destroy(s->kcopyd_client); + exit_exception_table(&s->pending, pending_cache); exit_exception_table(&s->complete, exception_cache); @@ -569,7 +573,7 @@ static void snapshot_dtr(struct dm_target *ti) dm_put_device(ti, s->origin); dm_put_device(ti, s->cow); - kcopyd_client_destroy(s->kcopyd_client); + kfree(s); } diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index 9dcb2c8a3853..ed71f3f94620 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c @@ -44,6 +44,9 @@ struct kcopyd_client { struct page_list *pages; unsigned int nr_pages; unsigned int nr_free_pages; + + wait_queue_head_t destroyq; + atomic_t nr_jobs; }; static struct page_list *alloc_pl(void) @@ -292,10 +295,15 @@ static int run_complete_job(struct kcopyd_job *job) int read_err = job->read_err; unsigned int write_err = job->write_err; kcopyd_notify_fn fn = job->fn; + struct kcopyd_client *kc = job->kc; - kcopyd_put_pages(job->kc, job->pages); + kcopyd_put_pages(kc, job->pages); mempool_free(job, _job_pool); fn(read_err, write_err, context); + + if (atomic_dec_and_test(&kc->nr_jobs)) + wake_up(&kc->destroyq); + return 0; } @@ -430,6 +438,7 @@ static void do_work(void *ignored) */ static void dispatch_job(struct kcopyd_job *job) { + atomic_inc(&job->kc->nr_jobs); push(&_pages_jobs, job); wake(); } @@ -669,6 +678,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result) return r; } + init_waitqueue_head(&kc->destroyq); + atomic_set(&kc->nr_jobs, 0); + client_add(kc); *result = kc; return 0; @@ -676,6 +688,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result) void kcopyd_client_destroy(struct kcopyd_client *kc) { + /* Wait for completion of all jobs submitted by this client. */ + wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs)); + dm_io_put(kc->nr_pages); client_free_pages(kc); client_del(kc); -- cgit v1.2.3-59-g8ed1b From 1ecac7fd74f2e5fb06a7719ecba55fb5778a9a47 Mon Sep 17 00:00:00 2001 From: Jun'ichi Nomura Date: Mon, 27 Mar 2006 01:17:51 -0800 Subject: [PATCH] dm flush queue EINTR If dm_suspend() is cancelled, bios already added to the deferred list need to be submitted. Otherwise they remain 'in limbo' until there's a dm_resume(). Signed-off-by: Jun'ichi Nomura Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm.c b/drivers/md/dm.c index a64798ef481e..48be69f3bcfa 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1107,6 +1107,7 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) { struct dm_table *map = NULL; DECLARE_WAITQUEUE(wait, current); + struct bio *def; int r = -EINVAL; down(&md->suspend_lock); @@ -1166,9 +1167,11 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) /* were we interrupted ? */ r = -EINTR; if (atomic_read(&md->pending)) { + clear_bit(DMF_BLOCK_IO, &md->flags); + def = bio_list_get(&md->deferred); + __flush_deferred_io(md, def); up_write(&md->io_lock); unlock_fs(md); - clear_bit(DMF_BLOCK_IO, &md->flags); goto out; } up_write(&md->io_lock); -- cgit v1.2.3-59-g8ed1b From 7e51f257e87297a5b6fe6d136a8ef67206aaf3a8 Mon Sep 17 00:00:00 2001 From: Mike Anderson Date: Mon, 27 Mar 2006 01:17:52 -0800 Subject: [PATCH] dm: store md name The patch stores a printable device number in struct mapped_device for use in warning messages and with a proposed netlink interface. Signed-off-by: Mike Anderson Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 48be69f3bcfa..f140d499602a 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -69,6 +69,7 @@ struct mapped_device { request_queue_t *queue; struct gendisk *disk; + char name[16]; void *interface_ptr; @@ -842,6 +843,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) md->disk->private_data = md; sprintf(md->disk->disk_name, "dm-%d", minor); add_disk(md->disk); + format_dev_t(md->name, MKDEV(_major, minor)); atomic_set(&md->pending, 0); init_waitqueue_head(&md->wait); -- cgit v1.2.3-59-g8ed1b From 9ade92a9a5b0a3a10efa6551b8c67a9277bf0438 Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Mon, 27 Mar 2006 01:17:53 -0800 Subject: [PATCH] dm: tidy mdptr Change dm_get_mdptr() to take a struct mapped_device instead of dev_t. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-ioctl.c | 16 +++++++++++++--- drivers/md/dm.c | 10 ++-------- drivers/md/dm.h | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 442e2be6052e..0693b6f54b7d 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -600,12 +600,22 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) */ static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) { + struct mapped_device *md; + void *mdptr = NULL; + if (*param->uuid) return __get_uuid_cell(param->uuid); - else if (*param->name) + + if (*param->name) return __get_name_cell(param->name); - else - return dm_get_mdptr(huge_decode_dev(param->dev)); + + md = dm_get_md(huge_decode_dev(param->dev)); + if (md) { + mdptr = dm_get_mdptr(md); + dm_put(md); + } + + return mdptr; } static struct mapped_device *find_device(struct dm_ioctl *param) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index f140d499602a..3d121cbc2fde 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -990,15 +990,9 @@ struct mapped_device *dm_get_md(dev_t dev) return md; } -void *dm_get_mdptr(dev_t dev) +void *dm_get_mdptr(struct mapped_device *md) { - struct mapped_device *md; - void *mdptr = NULL; - - md = dm_find_md(dev); - if (md) - mdptr = md->interface_ptr; - return mdptr; + return md->interface_ptr; } void dm_set_mdptr(struct mapped_device *md, void *ptr) diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 0ff11d6f8158..17ffa8d671a7 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -47,7 +47,7 @@ struct mapped_device; int dm_create(struct mapped_device **md); int dm_create_with_minor(unsigned int minor, struct mapped_device **md); void dm_set_mdptr(struct mapped_device *md, void *ptr); -void *dm_get_mdptr(dev_t dev); +void *dm_get_mdptr(struct mapped_device *md); struct mapped_device *dm_get_md(dev_t dev); /* -- cgit v1.2.3-59-g8ed1b From 1134e5ae79bab61c05657ca35a6297cf87202e35 Mon Sep 17 00:00:00 2001 From: Mike Anderson Date: Mon, 27 Mar 2006 01:17:54 -0800 Subject: [PATCH] dm table: store md Store an up-pointer to the owning struct mapped_device in every table when it is created. Access it with: struct mapped_device *dm_table_get_md(struct dm_table *t) Tables linked to md must be destroyed before the md itself. Signed-off-by: Mike Anderson Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-ioctl.c | 32 +++++++++++++++++++++----------- drivers/md/dm-table.c | 13 ++++++++++++- drivers/md/dm.c | 6 +++--- drivers/md/dm.h | 4 +++- 4 files changed, 39 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 0693b6f54b7d..65826bdac00c 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -244,9 +244,9 @@ static void __hash_remove(struct hash_cell *hc) dm_table_put(table); } - dm_put(hc->md); if (hc->new_map) dm_table_put(hc->new_map); + dm_put(hc->md); free_cell(hc); } @@ -985,33 +985,43 @@ static int table_load(struct dm_ioctl *param, size_t param_size) int r; struct hash_cell *hc; struct dm_table *t; + struct mapped_device *md; + + md = find_device(param); + if (!md) + return -ENXIO; - r = dm_table_create(&t, get_mode(param), param->target_count); + r = dm_table_create(&t, get_mode(param), param->target_count, md); if (r) - return r; + goto out; r = populate_table(t, param, param_size); if (r) { dm_table_put(t); - return r; + goto out; } down_write(&_hash_lock); - hc = __find_device_hash_cell(param); - if (!hc) { - DMWARN("device doesn't appear to be in the dev hash table."); - up_write(&_hash_lock); + hc = dm_get_mdptr(md); + if (!hc || hc->md != md) { + DMWARN("device has been removed from the dev hash table."); dm_table_put(t); - return -ENXIO; + up_write(&_hash_lock); + r = -ENXIO; + goto out; } if (hc->new_map) dm_table_put(hc->new_map); hc->new_map = t; + up_write(&_hash_lock); + param->flags |= DM_INACTIVE_PRESENT_FLAG; + r = __dev_status(md, param); + +out: + dm_put(md); - r = __dev_status(hc->md, param); - up_write(&_hash_lock); return r; } diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 9558a4acec12..84f4594afd3c 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -22,6 +22,7 @@ #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1) struct dm_table { + struct mapped_device *md; atomic_t holders; /* btree table */ @@ -206,7 +207,8 @@ static int alloc_targets(struct dm_table *t, unsigned int num) return 0; } -int dm_table_create(struct dm_table **result, int mode, unsigned num_targets) +int dm_table_create(struct dm_table **result, int mode, + unsigned num_targets, struct mapped_device *md) { struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL); @@ -229,6 +231,7 @@ int dm_table_create(struct dm_table **result, int mode, unsigned num_targets) } t->mode = mode; + t->md = md; *result = t; return 0; } @@ -952,12 +955,20 @@ int dm_table_flush_all(struct dm_table *t) return ret; } +struct mapped_device *dm_table_get_md(struct dm_table *t) +{ + dm_get(t->md); + + return t->md; +} + EXPORT_SYMBOL(dm_vcalloc); EXPORT_SYMBOL(dm_get_device); EXPORT_SYMBOL(dm_put_device); EXPORT_SYMBOL(dm_table_event); EXPORT_SYMBOL(dm_table_get_size); EXPORT_SYMBOL(dm_table_get_mode); +EXPORT_SYMBOL(dm_table_get_md); EXPORT_SYMBOL(dm_table_put); EXPORT_SYMBOL(dm_table_get); EXPORT_SYMBOL(dm_table_unplug_all); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 3d121cbc2fde..b99df48cffed 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1007,18 +1007,18 @@ void dm_get(struct mapped_device *md) void dm_put(struct mapped_device *md) { - struct dm_table *map = dm_get_table(md); + struct dm_table *map; if (atomic_dec_and_test(&md->holders)) { + map = dm_get_table(md); if (!dm_suspended(md)) { dm_table_presuspend_targets(map); dm_table_postsuspend_targets(map); } __unbind(md); + dm_table_put(map); free_dev(md); } - - dm_table_put(map); } /* diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 17ffa8d671a7..79e800051a10 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -89,7 +89,8 @@ int dm_suspended(struct mapped_device *md); * Functions for manipulating a table. Tables are also reference * counted. *---------------------------------------------------------------*/ -int dm_table_create(struct dm_table **result, int mode, unsigned num_targets); +int dm_table_create(struct dm_table **result, int mode, + unsigned num_targets, struct mapped_device *md); void dm_table_get(struct dm_table *t); void dm_table_put(struct dm_table *t); @@ -107,6 +108,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q); unsigned int dm_table_get_num_targets(struct dm_table *t); struct list_head *dm_table_get_devices(struct dm_table *t); int dm_table_get_mode(struct dm_table *t); +struct mapped_device *dm_table_get_md(struct dm_table *t); void dm_table_presuspend_targets(struct dm_table *t); void dm_table_postsuspend_targets(struct dm_table *t); void dm_table_resume_targets(struct dm_table *t); -- cgit v1.2.3-59-g8ed1b From 3ac51e741a46af7a20f55e79d3e3aeaa93c6c544 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 27 Mar 2006 01:17:54 -0800 Subject: [PATCH] dm store geometry Allow drive geometry to be stored with a new DM_DEV_SET_GEOMETRY ioctl. Device-mapper will now respond to HDIO_GETGEO. If the geometry information is not available, zero will be returned for all of the parameters. Signed-off-by: Darrick J. Wong Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-ioctl.c | 52 +++++++++++++++++++++++++++++++++++++++++++- drivers/md/dm.c | 46 +++++++++++++++++++++++++++++++++++++++ drivers/md/dm.h | 7 ++++++ include/linux/compat_ioctl.h | 2 ++ include/linux/dm-ioctl.h | 17 +++++++++++++-- 5 files changed, 121 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 65826bdac00c..8edd6435414d 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -700,6 +701,54 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) return dm_hash_rename(param->name, new_name); } +static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) +{ + int r = -EINVAL, x; + struct mapped_device *md; + struct hd_geometry geometry; + unsigned long indata[4]; + char *geostr = (char *) param + param->data_start; + + md = find_device(param); + if (!md) + return -ENXIO; + + if (geostr < (char *) (param + 1) || + invalid_str(geostr, (void *) param + param_size)) { + DMWARN("Invalid geometry supplied."); + goto out; + } + + x = sscanf(geostr, "%lu %lu %lu %lu", indata, + indata + 1, indata + 2, indata + 3); + + if (x != 4) { + DMWARN("Unable to interpret geometry settings."); + goto out; + } + + if (indata[0] > 65535 || indata[1] > 255 || + indata[2] > 255 || indata[3] > ULONG_MAX) { + DMWARN("Geometry exceeds range limits."); + goto out; + } + + geometry.cylinders = indata[0]; + geometry.heads = indata[1]; + geometry.sectors = indata[2]; + geometry.start = indata[3]; + + r = dm_set_geometry(md, &geometry); + if (!r) + r = __dev_status(md, param); + + param->data_size = 0; + +out: + dm_put(md); + return r; +} + static int do_suspend(struct dm_ioctl *param) { int r = 0; @@ -1234,7 +1283,8 @@ static ioctl_fn lookup_ioctl(unsigned int cmd) {DM_LIST_VERSIONS_CMD, list_versions}, - {DM_TARGET_MSG_CMD, target_message} + {DM_TARGET_MSG_CMD, target_message}, + {DM_DEV_SET_GEOMETRY_CMD, dev_set_geometry} }; return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index b99df48cffed..973e63d530ae 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -17,6 +17,7 @@ #include #include #include +#include #include static const char *_name = DM_NAME; @@ -102,6 +103,9 @@ struct mapped_device { */ struct super_block *frozen_sb; struct block_device *suspended_bdev; + + /* forced geometry settings */ + struct hd_geometry geometry; }; #define MIN_IOS 256 @@ -227,6 +231,13 @@ static int dm_blk_close(struct inode *inode, struct file *file) return 0; } +static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + struct mapped_device *md = bdev->bd_disk->private_data; + + return dm_get_geometry(md, geo); +} + static inline struct dm_io *alloc_io(struct mapped_device *md) { return mempool_alloc(md->io_pool, GFP_NOIO); @@ -313,6 +324,33 @@ struct dm_table *dm_get_table(struct mapped_device *md) return t; } +/* + * Get the geometry associated with a dm device + */ +int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo) +{ + *geo = md->geometry; + + return 0; +} + +/* + * Set the geometry of a device. + */ +int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo) +{ + sector_t sz = (sector_t)geo->cylinders * geo->heads * geo->sectors; + + if (geo->start > sz) { + DMWARN("Start sector is beyond the geometry limits."); + return -EINVAL; + } + + md->geometry = *geo; + + return 0; +} + /*----------------------------------------------------------------- * CRUD START: * A more elegant soln is in the works that uses the queue @@ -906,6 +944,13 @@ static int __bind(struct mapped_device *md, struct dm_table *t) sector_t size; size = dm_table_get_size(t); + + /* + * Wipe any geometry if the size of the table changed. + */ + if (size != get_capacity(md->disk)) + memset(&md->geometry, 0, sizeof(md->geometry)); + __set_size(md, size); if (size == 0) return 0; @@ -1261,6 +1306,7 @@ int dm_suspended(struct mapped_device *md) static struct block_device_operations dm_blk_dops = { .open = dm_blk_open, .release = dm_blk_close, + .getgeo = dm_blk_getgeo, .owner = THIS_MODULE }; diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 79e800051a10..fd90bc8f9e45 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -14,6 +14,7 @@ #include #include #include +#include #define DM_NAME "device-mapper" #define DMWARN(f, x...) printk(KERN_WARNING DM_NAME ": " f "\n" , ## x) @@ -85,6 +86,12 @@ int dm_wait_event(struct mapped_device *md, int event_nr); struct gendisk *dm_disk(struct mapped_device *md); int dm_suspended(struct mapped_device *md); +/* + * Geometry functions. + */ +int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo); +int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo); + /*----------------------------------------------------------------- * Functions for manipulating a table. Tables are also reference * counted. diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index efb518f16bb3..89ab677cb993 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -140,6 +140,7 @@ COMPATIBLE_IOCTL(DM_TABLE_DEPS_32) COMPATIBLE_IOCTL(DM_TABLE_STATUS_32) COMPATIBLE_IOCTL(DM_LIST_VERSIONS_32) COMPATIBLE_IOCTL(DM_TARGET_MSG_32) +COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY_32) COMPATIBLE_IOCTL(DM_VERSION) COMPATIBLE_IOCTL(DM_REMOVE_ALL) COMPATIBLE_IOCTL(DM_LIST_DEVICES) @@ -155,6 +156,7 @@ COMPATIBLE_IOCTL(DM_TABLE_DEPS) COMPATIBLE_IOCTL(DM_TABLE_STATUS) COMPATIBLE_IOCTL(DM_LIST_VERSIONS) COMPATIBLE_IOCTL(DM_TARGET_MSG) +COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY) /* Big K */ COMPATIBLE_IOCTL(PIO_FONT) COMPATIBLE_IOCTL(GIO_FONT) diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index fa75ba0d635e..c67c6786612a 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h @@ -80,6 +80,16 @@ * * DM_TARGET_MSG: * Pass a message string to the target at a specific offset of a device. + * + * DM_DEV_SET_GEOMETRY: + * Set the geometry of a device by passing in a string in this format: + * + * "cylinders heads sectors_per_track start_sector" + * + * Beware that CHS geometry is nearly obsolete and only provided + * for compatibility with dm devices that can be booted by a PC + * BIOS. See struct hd_geometry for range limits. Also note that + * the geometry is erased if the device size changes. */ /* @@ -218,6 +228,7 @@ enum { /* Added later */ DM_LIST_VERSIONS_CMD, DM_TARGET_MSG_CMD, + DM_DEV_SET_GEOMETRY_CMD }; /* @@ -247,6 +258,7 @@ typedef char ioctl_struct[308]; #define DM_TABLE_STATUS_32 _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, ioctl_struct) #define DM_LIST_VERSIONS_32 _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, ioctl_struct) #define DM_TARGET_MSG_32 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, ioctl_struct) +#define DM_DEV_SET_GEOMETRY_32 _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, ioctl_struct) #endif #define DM_IOCTL 0xfd @@ -270,11 +282,12 @@ typedef char ioctl_struct[308]; #define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl) #define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) +#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 5 +#define DM_VERSION_MINOR 6 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2005-10-04)" +#define DM_VERSION_EXTRA "-ioctl (2006-02-17)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ -- cgit v1.2.3-59-g8ed1b From 5463c7904c952aa6b6804dd902c72a5332fa5221 Mon Sep 17 00:00:00 2001 From: Jun'ichi Nomura Date: Mon, 27 Mar 2006 01:17:58 -0800 Subject: [PATCH] dm/md dependency tree in sysfs: md to use bd_claim_by_disk Use bd_claim_by_disk. Following symlinks are created if md0 is built from sda and sdb /sys/block/md0/slaves/sda --> /sys/block/sda /sys/block/md0/slaves/sdb --> /sys/block/sdb /sys/block/sda/holders/md0 --> /sys/block/md0 /sys/block/sdb/holders/md0 --> /sys/block/md0 Signed-off-by: Jun'ichi Nomura Cc: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 5ed2228745cb..bde3e9682250 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1301,6 +1301,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) else ko = &rdev->bdev->bd_disk->kobj; sysfs_create_link(&rdev->kobj, ko, "block"); + bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk); return 0; } @@ -1311,6 +1312,7 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) MD_BUG(); return; } + bd_release_from_disk(rdev->bdev, rdev->mddev->gendisk); list_del_init(&rdev->same_set); printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); rdev->mddev = NULL; -- cgit v1.2.3-59-g8ed1b From f165921df46a977e3561f1bd9f13a348441486d1 Mon Sep 17 00:00:00 2001 From: Jun'ichi Nomura Date: Mon, 27 Mar 2006 01:17:59 -0800 Subject: [PATCH] dm/md dependency tree in sysfs: dm to use bd_claim_by_disk Use bd_claim_by_disk. Following symlinks are created if dm-0 maps to sda: /sys/block/dm-0/slaves/sda --> /sys/block/sda /sys/block/sda/holders/dm-0 --> /sys/block/dm-0 Signed-off-by: Jun'ichi Nomura Cc: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-table.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 84f4594afd3c..76610a6ac01c 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -350,7 +350,7 @@ static struct dm_dev *find_device(struct list_head *l, dev_t dev) /* * Open a device so we can use it as a map destination. */ -static int open_dev(struct dm_dev *d, dev_t dev) +static int open_dev(struct dm_dev *d, dev_t dev, struct mapped_device *md) { static char *_claim_ptr = "I belong to device-mapper"; struct block_device *bdev; @@ -362,7 +362,7 @@ static int open_dev(struct dm_dev *d, dev_t dev) bdev = open_by_devnum(dev, d->mode); if (IS_ERR(bdev)) return PTR_ERR(bdev); - r = bd_claim(bdev, _claim_ptr); + r = bd_claim_by_disk(bdev, _claim_ptr, dm_disk(md)); if (r) blkdev_put(bdev); else @@ -373,12 +373,12 @@ static int open_dev(struct dm_dev *d, dev_t dev) /* * Close a device that we've been using. */ -static void close_dev(struct dm_dev *d) +static void close_dev(struct dm_dev *d, struct mapped_device *md) { if (!d->bdev) return; - bd_release(d->bdev); + bd_release_from_disk(d->bdev, dm_disk(md)); blkdev_put(d->bdev); d->bdev = NULL; } @@ -399,7 +399,7 @@ static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len) * careful to leave things as they were if we fail to reopen the * device. */ -static int upgrade_mode(struct dm_dev *dd, int new_mode) +static int upgrade_mode(struct dm_dev *dd, int new_mode, struct mapped_device *md) { int r; struct dm_dev dd_copy; @@ -409,9 +409,9 @@ static int upgrade_mode(struct dm_dev *dd, int new_mode) dd->mode |= new_mode; dd->bdev = NULL; - r = open_dev(dd, dev); + r = open_dev(dd, dev, md); if (!r) - close_dev(&dd_copy); + close_dev(&dd_copy, md); else *dd = dd_copy; @@ -453,7 +453,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, dd->mode = mode; dd->bdev = NULL; - if ((r = open_dev(dd, dev))) { + if ((r = open_dev(dd, dev, t->md))) { kfree(dd); return r; } @@ -464,7 +464,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, list_add(&dd->list, &t->devices); } else if (dd->mode != (mode | dd->mode)) { - r = upgrade_mode(dd, mode); + r = upgrade_mode(dd, mode, t->md); if (r) return r; } @@ -541,7 +541,7 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start, void dm_put_device(struct dm_target *ti, struct dm_dev *dd) { if (atomic_dec_and_test(&dd->count)) { - close_dev(dd); + close_dev(dd, ti->table->md); list_del(&dd->list); kfree(dd); } -- cgit v1.2.3-59-g8ed1b From a22c96c737a9cefbe8d6e991c0032ad6db825a67 Mon Sep 17 00:00:00 2001 From: Kevin Corry Date: Mon, 27 Mar 2006 01:18:01 -0800 Subject: [PATCH] dm: remove unnecessary typecast Signed-off-by: Kevin Corry Cc: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-stripe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 204f796ee9e3..08328a8f5a3c 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -103,7 +103,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) return -EINVAL; } - if (((uint32_t)ti->len) & (chunk_size - 1)) { + if (ti->len & (chunk_size - 1)) { ti->error = "dm-stripe: Target length not divisible by " "chunk size"; return -EINVAL; -- cgit v1.2.3-59-g8ed1b From 89e5c8b5b85d6d46e8a28cdfa076313ae691d35c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:02 -0800 Subject: [PATCH] md: Make sure QUEUE_FLAG_CLUSTER is set properly for md. This flag should be set for a virtual device iff it is set for all underlying devices. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/ll_rw_blk.c | 2 ++ drivers/md/md.c | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 062067fa7ead..a2e333ad0b64 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -785,6 +785,8 @@ void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b) t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments); t->max_segment_size = min(t->max_segment_size,b->max_segment_size); t->hardsect_size = max(t->hardsect_size,b->hardsect_size); + if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) + clear_bit(QUEUE_FLAG_CLUSTER, &t->queue_flags); } EXPORT_SYMBOL(blk_queue_stack_limits); diff --git a/drivers/md/md.c b/drivers/md/md.c index bde3e9682250..3254ff1a5cc9 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -266,6 +266,7 @@ static mddev_t * mddev_find(dev_t unit) kfree(new); return NULL; } + set_bit(QUEUE_FLAG_CLUSTER, &new->queue->queue_flags); blk_queue_make_request(new->queue, md_fail_request); -- cgit v1.2.3-59-g8ed1b From c5a10f62c5c496c49db749af103b991873b7e2dc Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:03 -0800 Subject: [PATCH] md: Add '4' to the list of levels for which bitmaps are supported I really should make this a function of the personality.... Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 3254ff1a5cc9..875bced88e36 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -765,7 +765,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) if (sb->state & (1<bitmap_file == NULL) { - if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6 + if (mddev->level != 1 && mddev->level != 4 + && mddev->level != 5 && mddev->level != 6 && mddev->level != 10) { /* FIXME use a better test */ printk(KERN_WARNING "md: bitmaps not supported for this level.\n"); -- cgit v1.2.3-59-g8ed1b From 1be7892fffb45f6017494a88ff68fe84c6de26b4 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:03 -0800 Subject: [PATCH] md: Fix the 'failed' count for version-0 superblocks We are counting failed devices twice, once of the device that is failed, and once for the hole that has been left in the array. Remove the former so 'failed' matches 'missing'. Storing these counts in the superblock is a bit silly anyway.... Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 875bced88e36..686314f070a5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -895,10 +895,9 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) d->raid_disk = rdev2->raid_disk; else d->raid_disk = rdev2->desc_nr; /* compatibility */ - if (test_bit(Faulty, &rdev2->flags)) { + if (test_bit(Faulty, &rdev2->flags)) d->state = (1<flags)) { + else if (test_bit(In_sync, &rdev2->flags)) { d->state = (1<state |= (1< Date: Mon, 27 Mar 2006 01:18:04 -0800 Subject: [PATCH] md: Update status_resync to handle LARGE devices status_resync - used by /proc/mdstat to report the status of a resync, assumes that device sizes will always fit into an 'unsigned long' This is no longer the case... Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 686314f070a5..a3ecaf8ed30a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4044,7 +4044,10 @@ static void status_unused(struct seq_file *seq) static void status_resync(struct seq_file *seq, mddev_t * mddev) { - unsigned long max_blocks, resync, res, dt, db, rt; + sector_t max_blocks, resync, res; + unsigned long dt, db, rt; + int scale; + unsigned int per_milli; resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2; @@ -4060,9 +4063,22 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev) MD_BUG(); return; } - res = (resync/1024)*1000/(max_blocks/1024 + 1); + /* Pick 'scale' such that (resync>>scale)*1000 will fit + * in a sector_t, and (max_blocks>>scale) will fit in a + * u32, as those are the requirements for sector_div. + * Thus 'scale' must be at least 10 + */ + scale = 10; + if (sizeof(sector_t) > sizeof(unsigned long)) { + while ( max_blocks/2 > (1ULL<<(scale+32))) + scale++; + } + res = (resync>>scale)*1000; + sector_div(res, (u32)((max_blocks>>scale)+1)); + + per_milli = res; { - int i, x = res/50, y = 20-x; + int i, x = per_milli/50, y = 20-x; seq_printf(seq, "["); for (i = 0; i < x; i++) seq_printf(seq, "="); @@ -4071,10 +4087,12 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev) seq_printf(seq, "."); seq_printf(seq, "] "); } - seq_printf(seq, " %s =%3lu.%lu%% (%lu/%lu)", + seq_printf(seq, " %s =%3u.%u%% (%llu/%llu)", (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ? "resync" : "recovery"), - res/10, res % 10, resync, max_blocks); + per_milli/10, per_milli % 10, + (unsigned long long) resync, + (unsigned long long) max_blocks); /* * We do not want to overflow, so the order of operands and @@ -4088,7 +4106,7 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev) dt = ((jiffies - mddev->resync_mark) / HZ); if (!dt) dt++; db = resync - (mddev->resync_mark_cnt/2); - rt = (dt * ((max_blocks-resync) / (db/100+1)))/100; + rt = (dt * ((unsigned long)(max_blocks-resync) / (db/100+1)))/100; seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6); -- cgit v1.2.3-59-g8ed1b From b55e6bfcd23cb2f7249095050c649f7aea813f9f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:06 -0800 Subject: [PATCH] md: Split disks array out of raid5 conf structure so it is easier to grow The remainder of this batch implements raid5 reshaping. Currently the only shape change that is supported is added a device, but it is envisioned that changing the chunksize and layout will also be supported, as well as changing the level (e.g. 1->5, 5->6). The reshape process naturally has to move all of the data in the array, and so should be used with caution. It is believed to work, and some testing does support this, but wider testing would be great for increasing my confidence. You will need a version of mdadm newer than 2.3.1 to make use of raid5 growth. This is because mdadm need to take a copy of a 'critical section' at the start of the array incase there is a crash at an awkward moment. On restart, mdadm will restore the critical section and allow reshape to continue. I hope to release a 2.4-pre by early next week - it still needs a little more polishing. This patch: Previously the array of disk information was included in the raid5 'conf' structure which was allocated to an appropriate size. This makes it awkward to change the size of that array. So we split it off into a separate kmalloced array which will require a little extra indexing, but is much easier to grow. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 10 +++++++--- drivers/md/raid6main.c | 10 +++++++--- include/linux/raid/raid5.h | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2dba305daf3c..03f31379cebb 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1822,11 +1822,13 @@ static int run(mddev_t *mddev) return -EIO; } - mddev->private = kzalloc(sizeof (raid5_conf_t) - + mddev->raid_disks * sizeof(struct disk_info), - GFP_KERNEL); + mddev->private = kzalloc(sizeof (raid5_conf_t), GFP_KERNEL); if ((conf = mddev->private) == NULL) goto abort; + conf->disks = kzalloc(mddev->raid_disks * sizeof(struct disk_info), + GFP_KERNEL); + if (!conf->disks) + goto abort; conf->mddev = mddev; @@ -1966,6 +1968,7 @@ static int run(mddev_t *mddev) abort: if (conf) { print_raid5_conf(conf); + kfree(conf->disks); kfree(conf->stripe_hashtbl); kfree(conf); } @@ -1986,6 +1989,7 @@ static int stop(mddev_t *mddev) kfree(conf->stripe_hashtbl); blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); + kfree(conf->disks); kfree(conf); mddev->private = NULL; return 0; diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index cd477ebf2ee4..c7632f6cc487 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -2006,11 +2006,14 @@ static int run(mddev_t *mddev) return -EIO; } - mddev->private = kzalloc(sizeof (raid6_conf_t) - + mddev->raid_disks * sizeof(struct disk_info), - GFP_KERNEL); + mddev->private = kzalloc(sizeof (raid6_conf_t), GFP_KERNEL); if ((conf = mddev->private) == NULL) goto abort; + conf->disks = kzalloc(mddev->raid_disks * sizeof(struct disk_info), + GFP_KERNEL); + if (!conf->disks) + goto abort; + conf->mddev = mddev; if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL) @@ -2158,6 +2161,7 @@ abort: print_raid6_conf(conf); safe_put_page(conf->spare_page); kfree(conf->stripe_hashtbl); + kfree(conf->disks); kfree(conf); } mddev->private = NULL; diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index 394da8207b34..94dbdd406f12 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -240,7 +240,7 @@ struct raid5_private_data { * waiting for 25% to be free */ spinlock_t device_lock; - struct disk_info disks[0]; + struct disk_info *disks; }; typedef struct raid5_private_data raid5_conf_t; -- cgit v1.2.3-59-g8ed1b From ad01c9e3752f4ba4f3d99c89b7370fa4983a25b5 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:07 -0800 Subject: [PATCH] md: Allow stripes to be expanded in preparation for expanding an array Before a RAID-5 can be expanded, we need to be able to expand the stripe-cache data structure. This requires allocating new stripes in a new kmem_cache. If this succeeds, we copy cache pages over and release the old stripes and kmem_cache. We then allocate new pages. If that fails, we leave the stripe cache at it's new size. It isn't worth the effort to shrink it back again. Unfortuanately this means we need two kmem_cache names as we, for a short period of time, we have two kmem_caches. So they are raid5/%s and raid5/%s-alt Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 2 +- drivers/md/raid5.c | 131 +++++++++++++++++++++++++++++++++++++++++++-- drivers/md/raid6main.c | 4 +- include/linux/raid/raid5.h | 9 +++- 4 files changed, 137 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index a3ecaf8ed30a..c7b7656f9aa5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2775,7 +2775,6 @@ static void autorun_array(mddev_t *mddev) */ static void autorun_devices(int part) { - struct list_head candidates; struct list_head *tmp; mdk_rdev_t *rdev0, *rdev; mddev_t *mddev; @@ -2784,6 +2783,7 @@ static void autorun_devices(int part) printk(KERN_INFO "md: autorun ...\n"); while (!list_empty(&pending_raid_disks)) { dev_t dev; + LIST_HEAD(candidates); rdev0 = list_entry(pending_raid_disks.next, mdk_rdev_t, same_set); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 03f31379cebb..6c20b44509d8 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -313,20 +313,143 @@ static int grow_stripes(raid5_conf_t *conf, int num) kmem_cache_t *sc; int devs = conf->raid_disks; - sprintf(conf->cache_name, "raid5/%s", mdname(conf->mddev)); - - sc = kmem_cache_create(conf->cache_name, + sprintf(conf->cache_name[0], "raid5/%s", mdname(conf->mddev)); + sprintf(conf->cache_name[1], "raid5/%s-alt", mdname(conf->mddev)); + conf->active_name = 0; + sc = kmem_cache_create(conf->cache_name[conf->active_name], sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), 0, 0, NULL, NULL); if (!sc) return 1; conf->slab_cache = sc; + conf->pool_size = devs; while (num--) { if (!grow_one_stripe(conf)) return 1; } return 0; } +static int resize_stripes(raid5_conf_t *conf, int newsize) +{ + /* Make all the stripes able to hold 'newsize' devices. + * New slots in each stripe get 'page' set to a new page. + * + * This happens in stages: + * 1/ create a new kmem_cache and allocate the required number of + * stripe_heads. + * 2/ gather all the old stripe_heads and tranfer the pages across + * to the new stripe_heads. This will have the side effect of + * freezing the array as once all stripe_heads have been collected, + * no IO will be possible. Old stripe heads are freed once their + * pages have been transferred over, and the old kmem_cache is + * freed when all stripes are done. + * 3/ reallocate conf->disks to be suitable bigger. If this fails, + * we simple return a failre status - no need to clean anything up. + * 4/ allocate new pages for the new slots in the new stripe_heads. + * If this fails, we don't bother trying the shrink the + * stripe_heads down again, we just leave them as they are. + * As each stripe_head is processed the new one is released into + * active service. + * + * Once step2 is started, we cannot afford to wait for a write, + * so we use GFP_NOIO allocations. + */ + struct stripe_head *osh, *nsh; + LIST_HEAD(newstripes); + struct disk_info *ndisks; + int err = 0; + kmem_cache_t *sc; + int i; + + if (newsize <= conf->pool_size) + return 0; /* never bother to shrink */ + + /* Step 1 */ + sc = kmem_cache_create(conf->cache_name[1-conf->active_name], + sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev), + 0, 0, NULL, NULL); + if (!sc) + return -ENOMEM; + + for (i = conf->max_nr_stripes; i; i--) { + nsh = kmem_cache_alloc(sc, GFP_KERNEL); + if (!nsh) + break; + + memset(nsh, 0, sizeof(*nsh) + (newsize-1)*sizeof(struct r5dev)); + + nsh->raid_conf = conf; + spin_lock_init(&nsh->lock); + + list_add(&nsh->lru, &newstripes); + } + if (i) { + /* didn't get enough, give up */ + while (!list_empty(&newstripes)) { + nsh = list_entry(newstripes.next, struct stripe_head, lru); + list_del(&nsh->lru); + kmem_cache_free(sc, nsh); + } + kmem_cache_destroy(sc); + return -ENOMEM; + } + /* Step 2 - Must use GFP_NOIO now. + * OK, we have enough stripes, start collecting inactive + * stripes and copying them over + */ + list_for_each_entry(nsh, &newstripes, lru) { + spin_lock_irq(&conf->device_lock); + wait_event_lock_irq(conf->wait_for_stripe, + !list_empty(&conf->inactive_list), + conf->device_lock, + unplug_slaves(conf->mddev); + ); + osh = get_free_stripe(conf); + spin_unlock_irq(&conf->device_lock); + atomic_set(&nsh->count, 1); + for(i=0; ipool_size; i++) + nsh->dev[i].page = osh->dev[i].page; + for( ; idev[i].page = NULL; + kmem_cache_free(conf->slab_cache, osh); + } + kmem_cache_destroy(conf->slab_cache); + + /* Step 3. + * At this point, we are holding all the stripes so the array + * is completely stalled, so now is a good time to resize + * conf->disks. + */ + ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO); + if (ndisks) { + for (i=0; iraid_disks; i++) + ndisks[i] = conf->disks[i]; + kfree(conf->disks); + conf->disks = ndisks; + } else + err = -ENOMEM; + + /* Step 4, return new stripes to service */ + while(!list_empty(&newstripes)) { + nsh = list_entry(newstripes.next, struct stripe_head, lru); + list_del_init(&nsh->lru); + for (i=conf->raid_disks; i < newsize; i++) + if (nsh->dev[i].page == NULL) { + struct page *p = alloc_page(GFP_NOIO); + nsh->dev[i].page = p; + if (!p) + err = -ENOMEM; + } + release_stripe(nsh); + } + /* critical section pass, GFP_NOIO no longer needed */ + + conf->slab_cache = sc; + conf->active_name = 1-conf->active_name; + conf->pool_size = newsize; + return err; +} + static int drop_one_stripe(raid5_conf_t *conf) { @@ -339,7 +462,7 @@ static int drop_one_stripe(raid5_conf_t *conf) return 0; if (atomic_read(&sh->count)) BUG(); - shrink_buffers(sh, conf->raid_disks); + shrink_buffers(sh, conf->pool_size); kmem_cache_free(conf->slab_cache, sh); atomic_dec(&conf->active_stripes); return 1; diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index c7632f6cc487..6df4930fddec 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -331,9 +331,9 @@ static int grow_stripes(raid6_conf_t *conf, int num) kmem_cache_t *sc; int devs = conf->raid_disks; - sprintf(conf->cache_name, "raid6/%s", mdname(conf->mddev)); + sprintf(conf->cache_name[0], "raid6/%s", mdname(conf->mddev)); - sc = kmem_cache_create(conf->cache_name, + sc = kmem_cache_create(conf->cache_name[0], sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), 0, 0, NULL, NULL); if (!sc) diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index 94dbdd406f12..b7b2653af7bb 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -216,7 +216,11 @@ struct raid5_private_data { struct list_head bitmap_list; /* stripes delaying awaiting bitmap update */ atomic_t preread_active_stripes; /* stripes with scheduled io */ - char cache_name[20]; + /* unfortunately we need two cache names as we temporarily have + * two caches. + */ + int active_name; + char cache_name[2][20]; kmem_cache_t *slab_cache; /* for allocating stripes */ int seq_flush, seq_write; @@ -238,7 +242,8 @@ struct raid5_private_data { wait_queue_head_t wait_for_overlap; int inactive_blocked; /* release of inactive stripes blocked, * waiting for 25% to be free - */ + */ + int pool_size; /* number of disks in stripeheads in pool */ spinlock_t device_lock; struct disk_info *disks; }; -- cgit v1.2.3-59-g8ed1b From 7ecaa1e6a1ad69862e9980b6c777e11f26c4782d Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:08 -0800 Subject: [PATCH] md: Infrastructure to allow normal IO to continue while array is expanding We need to allow that different stripes are of different effective sizes, and use the appropriate size. Also, when a stripe is being expanded, we must block any IO attempts until the stripe is stable again. Key elements in this change are: - each stripe_head gets a 'disk' field which is part of the key, thus there can sometimes be two stripe heads of the same area of the array, but covering different numbers of devices. One of these will be marked STRIPE_EXPANDING and so won't accept new requests. - conf->expand_progress tracks how the expansion is progressing and is used to determine whether the target part of the array has been expanded yet or not. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 88 ++++++++++++++++++++++++++++++---------------- include/linux/raid/raid5.h | 6 ++++ 2 files changed, 64 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 6c20b44509d8..7a6df515b008 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -178,10 +178,10 @@ static int grow_buffers(struct stripe_head *sh, int num) static void raid5_build_block (struct stripe_head *sh, int i); -static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) +static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int disks) { raid5_conf_t *conf = sh->raid_conf; - int disks = conf->raid_disks, i; + int i; if (atomic_read(&sh->count) != 0) BUG(); @@ -198,7 +198,9 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) sh->pd_idx = pd_idx; sh->state = 0; - for (i=disks; i--; ) { + sh->disks = disks; + + for (i = sh->disks; i--; ) { struct r5dev *dev = &sh->dev[i]; if (dev->toread || dev->towrite || dev->written || @@ -215,7 +217,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) insert_hash(conf, sh); } -static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) +static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector, int disks) { struct stripe_head *sh; struct hlist_node *hn; @@ -223,7 +225,7 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) CHECK_DEVLOCK(); PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash) - if (sh->sector == sector) + if (sh->sector == sector && sh->disks == disks) return sh; PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); return NULL; @@ -232,8 +234,8 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) static void unplug_slaves(mddev_t *mddev); static void raid5_unplug_device(request_queue_t *q); -static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector, - int pd_idx, int noblock) +static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector, int disks, + int pd_idx, int noblock) { struct stripe_head *sh; @@ -245,7 +247,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector wait_event_lock_irq(conf->wait_for_stripe, conf->quiesce == 0, conf->device_lock, /* nothing */); - sh = __find_stripe(conf, sector); + sh = __find_stripe(conf, sector, disks); if (!sh) { if (!conf->inactive_blocked) sh = get_free_stripe(conf); @@ -263,7 +265,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector ); conf->inactive_blocked = 0; } else - init_stripe(sh, sector, pd_idx); + init_stripe(sh, sector, pd_idx, disks); } else { if (atomic_read(&sh->count)) { if (!list_empty(&sh->lru)) @@ -300,6 +302,7 @@ static int grow_one_stripe(raid5_conf_t *conf) kmem_cache_free(conf->slab_cache, sh); return 0; } + sh->disks = conf->raid_disks; /* we just created an active stripe so... */ atomic_set(&sh->count, 1); atomic_inc(&conf->active_stripes); @@ -483,7 +486,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, { struct stripe_head *sh = bi->bi_private; raid5_conf_t *conf = sh->raid_conf; - int disks = conf->raid_disks, i; + int disks = sh->disks, i; int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); if (bi->bi_size) @@ -581,7 +584,7 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done, { struct stripe_head *sh = bi->bi_private; raid5_conf_t *conf = sh->raid_conf; - int disks = conf->raid_disks, i; + int disks = sh->disks, i; unsigned long flags; int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); @@ -735,7 +738,7 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks, static sector_t compute_blocknr(struct stripe_head *sh, int i) { raid5_conf_t *conf = sh->raid_conf; - int raid_disks = conf->raid_disks, data_disks = raid_disks - 1; + int raid_disks = sh->disks, data_disks = raid_disks - 1; sector_t new_sector = sh->sector, check; int sectors_per_chunk = conf->chunk_size >> 9; sector_t stripe; @@ -836,8 +839,7 @@ static void copy_data(int frombio, struct bio *bio, static void compute_block(struct stripe_head *sh, int dd_idx) { - raid5_conf_t *conf = sh->raid_conf; - int i, count, disks = conf->raid_disks; + int i, count, disks = sh->disks; void *ptr[MAX_XOR_BLOCKS], *p; PRINTK("compute_block, stripe %llu, idx %d\n", @@ -867,7 +869,7 @@ static void compute_block(struct stripe_head *sh, int dd_idx) static void compute_parity(struct stripe_head *sh, int method) { raid5_conf_t *conf = sh->raid_conf; - int i, pd_idx = sh->pd_idx, disks = conf->raid_disks, count; + int i, pd_idx = sh->pd_idx, disks = sh->disks, count; void *ptr[MAX_XOR_BLOCKS]; struct bio *chosen; @@ -1055,7 +1057,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in static void handle_stripe(struct stripe_head *sh) { raid5_conf_t *conf = sh->raid_conf; - int disks = conf->raid_disks; + int disks = sh->disks; struct bio *return_bi= NULL; struct bio *bi; int i; @@ -1649,12 +1651,10 @@ static inline void raid5_plug_device(raid5_conf_t *conf) spin_unlock_irq(&conf->device_lock); } -static int make_request (request_queue_t *q, struct bio * bi) +static int make_request(request_queue_t *q, struct bio * bi) { mddev_t *mddev = q->queuedata; raid5_conf_t *conf = mddev_to_conf(mddev); - const unsigned int raid_disks = conf->raid_disks; - const unsigned int data_disks = raid_disks - 1; unsigned int dd_idx, pd_idx; sector_t new_sector; sector_t logical_sector, last_sector; @@ -1678,20 +1678,48 @@ static int make_request (request_queue_t *q, struct bio * bi) for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { DEFINE_WAIT(w); + int disks; - new_sector = raid5_compute_sector(logical_sector, - raid_disks, data_disks, &dd_idx, &pd_idx, conf); - + retry: + if (likely(conf->expand_progress == MaxSector)) + disks = conf->raid_disks; + else { + spin_lock_irq(&conf->device_lock); + disks = conf->raid_disks; + if (logical_sector >= conf->expand_progress) + disks = conf->previous_raid_disks; + spin_unlock_irq(&conf->device_lock); + } + new_sector = raid5_compute_sector(logical_sector, disks, disks - 1, + &dd_idx, &pd_idx, conf); PRINTK("raid5: make_request, sector %llu logical %llu\n", (unsigned long long)new_sector, (unsigned long long)logical_sector); - retry: prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); - sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK)); + sh = get_active_stripe(conf, new_sector, disks, pd_idx, (bi->bi_rw&RWA_MASK)); if (sh) { - if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) { - /* Add failed due to overlap. Flush everything + if (unlikely(conf->expand_progress != MaxSector)) { + /* expansion might have moved on while waiting for a + * stripe, so we much do the range check again. + */ + int must_retry = 0; + spin_lock_irq(&conf->device_lock); + if (logical_sector < conf->expand_progress && + disks == conf->previous_raid_disks) + /* mismatch, need to try again */ + must_retry = 1; + spin_unlock_irq(&conf->device_lock); + if (must_retry) { + release_stripe(sh); + goto retry; + } + } + + if (test_bit(STRIPE_EXPANDING, &sh->state) || + !add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) { + /* Stripe is busy expanding or + * add failed due to overlap. Flush everything * and wait a while */ raid5_unplug_device(mddev->queue); @@ -1703,7 +1731,6 @@ static int make_request (request_queue_t *q, struct bio * bi) raid5_plug_device(conf); handle_stripe(sh); release_stripe(sh); - } else { /* cannot get stripe for read-ahead, just give-up */ clear_bit(BIO_UPTODATE, &bi->bi_flags); @@ -1779,9 +1806,9 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i first_sector = raid5_compute_sector((sector_t)stripe*data_disks*sectors_per_chunk + chunk_offset, raid_disks, data_disks, &dd_idx, &pd_idx, conf); - sh = get_active_stripe(conf, sector_nr, pd_idx, 1); + sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1); if (sh == NULL) { - sh = get_active_stripe(conf, sector_nr, pd_idx, 0); + sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 0); /* make sure we don't swamp the stripe cache if someone else * is trying to get access */ @@ -1998,6 +2025,7 @@ static int run(mddev_t *mddev) conf->level = mddev->level; conf->algorithm = mddev->layout; conf->max_nr_stripes = NR_STRIPES; + conf->expand_progress = MaxSector; /* device size must be a multiple of chunk size */ mddev->size &= ~(mddev->chunk_size/1024 -1); @@ -2128,7 +2156,7 @@ static void print_sh (struct stripe_head *sh) printk("sh %llu, count %d.\n", (unsigned long long)sh->sector, atomic_read(&sh->count)); printk("sh %llu, ", (unsigned long long)sh->sector); - for (i = 0; i < sh->raid_conf->raid_disks; i++) { + for (i = 0; i < sh->disks; i++) { printk("(cache%d: %p %ld) ", i, sh->dev[i].page, sh->dev[i].flags); } diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index b7b2653af7bb..6fa274aea2a0 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -135,6 +135,7 @@ struct stripe_head { atomic_t count; /* nr of active thread/requests */ spinlock_t lock; int bm_seq; /* sequence number for bitmap flushes */ + int disks; /* disks in stripe */ struct r5dev { struct bio req; struct bio_vec vec; @@ -174,6 +175,7 @@ struct stripe_head { #define STRIPE_DELAYED 6 #define STRIPE_DEGRADED 7 #define STRIPE_BIT_DELAY 8 +#define STRIPE_EXPANDING 9 /* * Plugging: @@ -211,6 +213,10 @@ struct raid5_private_data { int raid_disks, working_disks, failed_disks; int max_nr_stripes; + /* used during an expand */ + sector_t expand_progress; /* MaxSector when no expand happening */ + int previous_raid_disks; + struct list_head handle_list; /* stripes needing handling */ struct list_head delayed_list; /* stripes that have plugged requests */ struct list_head bitmap_list; /* stripes delaying awaiting bitmap update */ -- cgit v1.2.3-59-g8ed1b From ccfcc3c10b2a5cb8fd3c918199a4ff904fc6fb3e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:09 -0800 Subject: [PATCH] md: Core of raid5 resize process This patch provides the core of the resize/expand process. sync_request notices if a 'reshape' is happening and acts accordingly. It allocated new stripe_heads for the next chunk-wide-stripe in the target geometry, marking them STRIPE_EXPANDING. Then it finds which stripe heads in the old geometry can provide data needed by these and marks them STRIPE_EXPAND_SOURCE. This causes stripe_handle to read all blocks on those stripes. Once all blocks on a STRIPE_EXPAND_SOURCE stripe_head are read, any that are needed are copied into the corresponding STRIPE_EXPANDING stripe_head. Once a STRIPE_EXPANDING stripe_head is full, it is marks STRIPE_EXPAND_READY and then is written out and released. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 14 +++- drivers/md/raid5.c | 185 +++++++++++++++++++++++++++++++++++++++------ include/linux/raid/md_k.h | 4 + include/linux/raid/raid5.h | 4 +- 4 files changed, 181 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index c7b7656f9aa5..8e65986bc63f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2165,7 +2165,9 @@ action_show(mddev_t *mddev, char *page) char *type = "idle"; if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) { - if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { + if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) + type = "reshape"; + else if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) type = "resync"; else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) @@ -4088,8 +4090,10 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev) seq_printf(seq, "] "); } seq_printf(seq, " %s =%3u.%u%% (%llu/%llu)", + (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)? + "reshape" : (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ? - "resync" : "recovery"), + "resync" : "recovery")), per_milli/10, per_milli % 10, (unsigned long long) resync, (unsigned long long) max_blocks); @@ -4543,7 +4547,9 @@ static void md_do_sync(mddev_t *mddev) */ max_sectors = mddev->resync_max_sectors; mddev->resync_mismatches = 0; - } else + } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) + max_sectors = mddev->size << 1; + else /* recovery follows the physical size of devices */ max_sectors = mddev->size << 1; @@ -4679,6 +4685,8 @@ static void md_do_sync(mddev_t *mddev) mddev->pers->sync_request(mddev, max_sectors, &skipped, 1); if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && + test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && + !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && mddev->curr_resync > 2 && mddev->curr_resync >= mddev->recovery_cp) { if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 7a6df515b008..56cba8d3e398 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -93,11 +93,11 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) md_wakeup_thread(conf->mddev->thread); } - list_add_tail(&sh->lru, &conf->inactive_list); atomic_dec(&conf->active_stripes); - if (!conf->inactive_blocked || - atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4)) + if (!test_bit(STRIPE_EXPANDING, &sh->state)) { + list_add_tail(&sh->lru, &conf->inactive_list); wake_up(&conf->wait_for_stripe); + } } } } @@ -273,9 +273,8 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector } else { if (!test_bit(STRIPE_HANDLE, &sh->state)) atomic_inc(&conf->active_stripes); - if (list_empty(&sh->lru)) - BUG(); - list_del_init(&sh->lru); + if (!list_empty(&sh->lru)) + list_del_init(&sh->lru); } } } while (sh == NULL); @@ -1035,6 +1034,18 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in return 0; } +static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks) +{ + int sectors_per_chunk = conf->chunk_size >> 9; + sector_t x = stripe; + int pd_idx, dd_idx; + int chunk_offset = sector_div(x, sectors_per_chunk); + stripe = x; + raid5_compute_sector(stripe*(disks-1)*sectors_per_chunk + + chunk_offset, disks, disks-1, &dd_idx, &pd_idx, conf); + return pd_idx; +} + /* * handle_stripe - do things to a stripe. @@ -1061,7 +1072,7 @@ static void handle_stripe(struct stripe_head *sh) struct bio *return_bi= NULL; struct bio *bi; int i; - int syncing; + int syncing, expanding, expanded; int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0; int non_overwrite = 0; int failed_num=0; @@ -1076,6 +1087,8 @@ static void handle_stripe(struct stripe_head *sh) clear_bit(STRIPE_DELAYED, &sh->state); syncing = test_bit(STRIPE_SYNCING, &sh->state); + expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state); + expanded = test_bit(STRIPE_EXPAND_READY, &sh->state); /* Now to look around and see what can be done */ rcu_read_lock(); @@ -1268,13 +1281,14 @@ static void handle_stripe(struct stripe_head *sh) * parity, or to satisfy requests * or to load a block that is being partially written. */ - if (to_read || non_overwrite || (syncing && (uptodate < disks))) { + if (to_read || non_overwrite || (syncing && (uptodate < disks)) || expanding) { for (i=disks; i--;) { dev = &sh->dev[i]; if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread || (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) || syncing || + expanding || (failed && (sh->dev[failed_num].toread || (sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num].flags)))) ) @@ -1464,13 +1478,76 @@ static void handle_stripe(struct stripe_head *sh) set_bit(R5_Wantwrite, &dev->flags); set_bit(R5_ReWrite, &dev->flags); set_bit(R5_LOCKED, &dev->flags); + locked++; } else { /* let's read it back */ set_bit(R5_Wantread, &dev->flags); set_bit(R5_LOCKED, &dev->flags); + locked++; } } + if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) { + /* Need to write out all blocks after computing parity */ + sh->disks = conf->raid_disks; + sh->pd_idx = stripe_to_pdidx(sh->sector, conf, conf->raid_disks); + compute_parity(sh, RECONSTRUCT_WRITE); + for (i= conf->raid_disks; i--;) { + set_bit(R5_LOCKED, &sh->dev[i].flags); + locked++; + set_bit(R5_Wantwrite, &sh->dev[i].flags); + } + clear_bit(STRIPE_EXPANDING, &sh->state); + } else if (expanded) { + clear_bit(STRIPE_EXPAND_READY, &sh->state); + wake_up(&conf->wait_for_overlap); + md_done_sync(conf->mddev, STRIPE_SECTORS, 1); + } + + if (expanding && locked == 0) { + /* We have read all the blocks in this stripe and now we need to + * copy some of them into a target stripe for expand. + */ + clear_bit(STRIPE_EXPAND_SOURCE, &sh->state); + for (i=0; i< sh->disks; i++) + if (i != sh->pd_idx) { + int dd_idx, pd_idx, j; + struct stripe_head *sh2; + + sector_t bn = compute_blocknr(sh, i); + sector_t s = raid5_compute_sector(bn, conf->raid_disks, + conf->raid_disks-1, + &dd_idx, &pd_idx, conf); + sh2 = get_active_stripe(conf, s, conf->raid_disks, pd_idx, 1); + if (sh2 == NULL) + /* so far only the early blocks of this stripe + * have been requested. When later blocks + * get requested, we will try again + */ + continue; + if(!test_bit(STRIPE_EXPANDING, &sh2->state) || + test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) { + /* must have already done this block */ + release_stripe(sh2); + continue; + } + memcpy(page_address(sh2->dev[dd_idx].page), + page_address(sh->dev[i].page), + STRIPE_SIZE); + set_bit(R5_Expanded, &sh2->dev[dd_idx].flags); + set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags); + for (j=0; jraid_disks; j++) + if (j != sh2->pd_idx && + !test_bit(R5_Expanded, &sh2->dev[j].flags)) + break; + if (j == conf->raid_disks) { + set_bit(STRIPE_EXPAND_READY, &sh2->state); + set_bit(STRIPE_HANDLE, &sh2->state); + } + release_stripe(sh2); + } + } + spin_unlock(&sh->lock); while ((bi=return_bi)) { @@ -1509,7 +1586,7 @@ static void handle_stripe(struct stripe_head *sh) rcu_read_unlock(); if (rdev) { - if (syncing) + if (syncing || expanding || expanded) md_sync_acct(rdev->bdev, STRIPE_SECTORS); bi->bi_bdev = rdev->bdev; @@ -1757,12 +1834,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i { raid5_conf_t *conf = (raid5_conf_t *) mddev->private; struct stripe_head *sh; - int sectors_per_chunk = conf->chunk_size >> 9; - sector_t x; - unsigned long stripe; - int chunk_offset; - int dd_idx, pd_idx; - sector_t first_sector; + int pd_idx; + sector_t first_sector, last_sector; int raid_disks = conf->raid_disks; int data_disks = raid_disks-1; sector_t max_sector = mddev->size << 1; @@ -1781,6 +1854,80 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i return 0; } + + if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) { + /* reshaping is quite different to recovery/resync so it is + * handled quite separately ... here. + * + * On each call to sync_request, we gather one chunk worth of + * destination stripes and flag them as expanding. + * Then we find all the source stripes and request reads. + * As the reads complete, handle_stripe will copy the data + * into the destination stripe and release that stripe. + */ + int i; + int dd_idx; + for (i=0; i < conf->chunk_size/512; i+= STRIPE_SECTORS) { + int j; + int skipped = 0; + pd_idx = stripe_to_pdidx(sector_nr+i, conf, conf->raid_disks); + sh = get_active_stripe(conf, sector_nr+i, + conf->raid_disks, pd_idx, 0); + set_bit(STRIPE_EXPANDING, &sh->state); + /* If any of this stripe is beyond the end of the old + * array, then we need to zero those blocks + */ + for (j=sh->disks; j--;) { + sector_t s; + if (j == sh->pd_idx) + continue; + s = compute_blocknr(sh, j); + if (s < (mddev->array_size<<1)) { + skipped = 1; + continue; + } + memset(page_address(sh->dev[j].page), 0, STRIPE_SIZE); + set_bit(R5_Expanded, &sh->dev[j].flags); + set_bit(R5_UPTODATE, &sh->dev[j].flags); + } + if (!skipped) { + set_bit(STRIPE_EXPAND_READY, &sh->state); + set_bit(STRIPE_HANDLE, &sh->state); + } + release_stripe(sh); + } + spin_lock_irq(&conf->device_lock); + conf->expand_progress = (sector_nr + i)*(conf->raid_disks-1); + spin_unlock_irq(&conf->device_lock); + /* Ok, those stripe are ready. We can start scheduling + * reads on the source stripes. + * The source stripes are determined by mapping the first and last + * block on the destination stripes. + */ + raid_disks = conf->previous_raid_disks; + data_disks = raid_disks - 1; + first_sector = + raid5_compute_sector(sector_nr*(conf->raid_disks-1), + raid_disks, data_disks, + &dd_idx, &pd_idx, conf); + last_sector = + raid5_compute_sector((sector_nr+conf->chunk_size/512) + *(conf->raid_disks-1) -1, + raid_disks, data_disks, + &dd_idx, &pd_idx, conf); + if (last_sector >= (mddev->size<<1)) + last_sector = (mddev->size<<1)-1; + while (first_sector <= last_sector) { + pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks); + sh = get_active_stripe(conf, first_sector, + conf->previous_raid_disks, pd_idx, 0); + set_bit(STRIPE_EXPAND_SOURCE, &sh->state); + set_bit(STRIPE_HANDLE, &sh->state); + release_stripe(sh); + first_sector += STRIPE_SECTORS; + } + return conf->chunk_size>>9; + } /* if there is 1 or more failed drives and we are trying * to resync, then assert that we are finished, because there is * nothing we can do. @@ -1799,13 +1946,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */ } - x = sector_nr; - chunk_offset = sector_div(x, sectors_per_chunk); - stripe = x; - BUG_ON(x != stripe); - - first_sector = raid5_compute_sector((sector_t)stripe*data_disks*sectors_per_chunk - + chunk_offset, raid_disks, data_disks, &dd_idx, &pd_idx, conf); + pd_idx = stripe_to_pdidx(sector_nr, conf, raid_disks); sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1); if (sh == NULL) { sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 0); diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 617b9506c760..4e26ef2cacca 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -157,6 +157,9 @@ struct mddev_s * DONE: thread is done and is waiting to be reaped * REQUEST: user-space has requested a sync (used with SYNC) * CHECK: user-space request for for check-only, no repair + * RESHAPE: A reshape is happening + * + * If neither SYNC or RESHAPE are set, then it is a recovery. */ #define MD_RECOVERY_RUNNING 0 #define MD_RECOVERY_SYNC 1 @@ -166,6 +169,7 @@ struct mddev_s #define MD_RECOVERY_NEEDED 5 #define MD_RECOVERY_REQUESTED 6 #define MD_RECOVERY_CHECK 7 +#define MD_RECOVERY_RESHAPE 8 unsigned long recovery; int in_sync; /* know to not need resync */ diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index 6fa274aea2a0..55c738d50508 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -157,6 +157,7 @@ struct stripe_head { #define R5_ReadError 8 /* seen a read error here recently */ #define R5_ReWrite 9 /* have tried to over-write the readerror */ +#define R5_Expanded 10 /* This block now has post-expand data */ /* * Write method */ @@ -176,7 +177,8 @@ struct stripe_head { #define STRIPE_DEGRADED 7 #define STRIPE_BIT_DELAY 8 #define STRIPE_EXPANDING 9 - +#define STRIPE_EXPAND_SOURCE 10 +#define STRIPE_EXPAND_READY 11 /* * Plugging: * -- cgit v1.2.3-59-g8ed1b From 292695531ae4019bb15deedc121b218d1908b648 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:10 -0800 Subject: [PATCH] md: Final stages of raid5 expand code This patch adds raid5_reshape and end_reshape which will start and finish the reshape processes. raid5_reshape is only enabled in CONFIG_MD_RAID5_RESHAPE is set, to discourage accidental use. Read the 'help' for the CONFIG_MD_RAID5_RESHAPE entry. and Make sure that you have backups, just in case. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/Kconfig | 26 ++++++++++ drivers/md/md.c | 6 ++- drivers/md/raid5.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++- include/linux/raid/md.h | 3 +- 4 files changed, 154 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index ac43f98062fd..fd2aae150ccc 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -127,6 +127,32 @@ config MD_RAID5 If unsure, say Y. +config MD_RAID5_RESHAPE + bool "Support adding drives to a raid-5 array (experimental)" + depends on MD_RAID5 && EXPERIMENTAL + ---help--- + A RAID-5 set can be expanded by adding extra drives. This + requires "restriping" the array which means (almost) every + block must be written to a different place. + + This option allows such restriping to be done while the array + is online. However it is still EXPERIMENTAL code. It should + work, but please be sure that you have backups. + + You will need a version of mdadm newer than 2.3.1. During the + early stage of reshape there is a critical section where live data + is being over-written. A crash during this time needs extra care + for recovery. The newer mdadm takes a copy of the data in the + critical section and will restore it, if necessary, after a crash. + + The mdadm usage is e.g. + mdadm --grow /dev/md1 --raid-disks=6 + to grow '/dev/md1' to having 6 disks. + + Note: The array can only be expanded, not contracted. + There should be enough spares already present to make the new + array workable. + config MD_RAID6 tristate "RAID-6 mode" depends on BLK_DEV_MD diff --git a/drivers/md/md.c b/drivers/md/md.c index 8e65986bc63f..d169bc964676 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -158,11 +158,12 @@ static int start_readonly; */ static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters); static atomic_t md_event_count; -static void md_new_event(mddev_t *mddev) +void md_new_event(mddev_t *mddev) { atomic_inc(&md_event_count); wake_up(&md_event_waiters); } +EXPORT_SYMBOL_GPL(md_new_event); /* * Enables to iterate over all existing md arrays @@ -4467,7 +4468,7 @@ static DECLARE_WAIT_QUEUE_HEAD(resync_wait); #define SYNC_MARKS 10 #define SYNC_MARK_STEP (3*HZ) -static void md_do_sync(mddev_t *mddev) +void md_do_sync(mddev_t *mddev) { mddev_t *mddev2; unsigned int currspeed = 0, @@ -4704,6 +4705,7 @@ static void md_do_sync(mddev_t *mddev) set_bit(MD_RECOVERY_DONE, &mddev->recovery); md_wakeup_thread(mddev->thread); } +EXPORT_SYMBOL_GPL(md_do_sync); /* diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 56cba8d3e398..b29135acb1d9 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -331,6 +331,8 @@ static int grow_stripes(raid5_conf_t *conf, int num) } return 0; } + +#ifdef CONFIG_MD_RAID5_RESHAPE static int resize_stripes(raid5_conf_t *conf, int newsize) { /* Make all the stripes able to hold 'newsize' devices. @@ -451,7 +453,7 @@ static int resize_stripes(raid5_conf_t *conf, int newsize) conf->pool_size = newsize; return err; } - +#endif static int drop_one_stripe(raid5_conf_t *conf) { @@ -1034,6 +1036,8 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in return 0; } +static void end_reshape(raid5_conf_t *conf); + static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks) { int sectors_per_chunk = conf->chunk_size >> 9; @@ -1844,6 +1848,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i if (sector_nr >= max_sector) { /* just being told to finish up .. nothing much to do */ unplug_slaves(mddev); + if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) { + end_reshape(conf); + return 0; + } if (mddev->curr_resync < max_sector) /* aborted */ bitmap_end_sync(mddev->bitmap, mddev->curr_resync, @@ -2464,6 +2472,116 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors) return 0; } +#ifdef CONFIG_MD_RAID5_RESHAPE +static int raid5_reshape(mddev_t *mddev, int raid_disks) +{ + raid5_conf_t *conf = mddev_to_conf(mddev); + int err; + mdk_rdev_t *rdev; + struct list_head *rtmp; + int spares = 0; + int added_devices = 0; + + if (mddev->degraded || + test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) + return -EBUSY; + if (conf->raid_disks > raid_disks) + return -EINVAL; /* Cannot shrink array yet */ + if (conf->raid_disks == raid_disks) + return 0; /* nothing to do */ + + /* Can only proceed if there are plenty of stripe_heads. + * We need a minimum of one full stripe,, and for sensible progress + * it is best to have about 4 times that. + * If we require 4 times, then the default 256 4K stripe_heads will + * allow for chunk sizes up to 256K, which is probably OK. + * If the chunk size is greater, user-space should request more + * stripe_heads first. + */ + if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes) { + printk(KERN_WARNING "raid5: reshape: not enough stripes. Needed %lu\n", + (mddev->chunk_size / STRIPE_SIZE)*4); + return -ENOSPC; + } + + ITERATE_RDEV(mddev, rdev, rtmp) + if (rdev->raid_disk < 0 && + !test_bit(Faulty, &rdev->flags)) + spares++; + if (conf->raid_disks + spares < raid_disks-1) + /* Not enough devices even to make a degraded array + * of that size + */ + return -EINVAL; + + err = resize_stripes(conf, raid_disks); + if (err) + return err; + + spin_lock_irq(&conf->device_lock); + conf->previous_raid_disks = conf->raid_disks; + mddev->raid_disks = conf->raid_disks = raid_disks; + conf->expand_progress = 0; + spin_unlock_irq(&conf->device_lock); + + /* Add some new drives, as many as will fit. + * We know there are enough to make the newly sized array work. + */ + ITERATE_RDEV(mddev, rdev, rtmp) + if (rdev->raid_disk < 0 && + !test_bit(Faulty, &rdev->flags)) { + if (raid5_add_disk(mddev, rdev)) { + char nm[20]; + set_bit(In_sync, &rdev->flags); + conf->working_disks++; + added_devices++; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); + } else + break; + } + + mddev->degraded = (raid_disks - conf->previous_raid_disks) - added_devices; + clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); + clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); + set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); + set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); + mddev->sync_thread = md_register_thread(md_do_sync, mddev, + "%s_reshape"); + if (!mddev->sync_thread) { + mddev->recovery = 0; + spin_lock_irq(&conf->device_lock); + mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks; + conf->expand_progress = MaxSector; + spin_unlock_irq(&conf->device_lock); + return -EAGAIN; + } + md_wakeup_thread(mddev->sync_thread); + md_new_event(mddev); + return 0; +} +#endif + +static void end_reshape(raid5_conf_t *conf) +{ + struct block_device *bdev; + + conf->mddev->array_size = conf->mddev->size * (conf->mddev->raid_disks-1); + set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1); + conf->mddev->changed = 1; + + bdev = bdget_disk(conf->mddev->gendisk, 0); + if (bdev) { + mutex_lock(&bdev->bd_inode->i_mutex); + i_size_write(bdev->bd_inode, conf->mddev->array_size << 10); + mutex_unlock(&bdev->bd_inode->i_mutex); + bdput(bdev); + } + spin_lock_irq(&conf->device_lock); + conf->expand_progress = MaxSector; + spin_unlock_irq(&conf->device_lock); +} + static void raid5_quiesce(mddev_t *mddev, int state) { raid5_conf_t *conf = mddev_to_conf(mddev); @@ -2502,6 +2620,9 @@ static struct mdk_personality raid5_personality = .spare_active = raid5_spare_active, .sync_request = sync_request, .resize = raid5_resize, +#ifdef CONFIG_MD_RAID5_RESHAPE + .reshape = raid5_reshape, +#endif .quiesce = raid5_quiesce, }; diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index b6e0bcad84e1..9c77cde5a795 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h @@ -92,7 +92,8 @@ extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, extern void md_super_wait(mddev_t *mddev); extern int sync_page_io(struct block_device *bdev, sector_t sector, int size, struct page *page, int rw); - +extern void md_do_sync(mddev_t *mddev); +extern void md_new_event(mddev_t *mddev); #define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); } -- cgit v1.2.3-59-g8ed1b From f67055780caac6a99f43834795c43acf99eba6a6 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:11 -0800 Subject: [PATCH] md: Checkpoint and allow restart of raid5 reshape We allow the superblock to record an 'old' and a 'new' geometry, and a position where any conversion is up to. The geometry allows for changing chunksize, layout and level as well as number of devices. When using verion-0.90 superblock, we convert the version to 0.91 while the conversion is happening so that an old kernel will refuse the assemble the array. For version-1, we use a feature bit for the same effect. When starting an array we check for an incomplete reshape and restart the reshape process if needed. If the reshape stopped at an awkward time (like when updating the first stripe) we refuse to assemble the array, and let user-space worry about it. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 69 +++++++++++++++++++++- drivers/md/raid1.c | 5 ++ drivers/md/raid5.c | 140 ++++++++++++++++++++++++++++++++++++++------- include/linux/raid/md.h | 2 + include/linux/raid/md_k.h | 8 +++ include/linux/raid/md_p.h | 32 ++++++++++- include/linux/raid/raid5.h | 1 + 7 files changed, 231 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index d169bc964676..b9dfdfccdb78 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -662,7 +662,8 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version } if (sb->major_version != 0 || - sb->minor_version != 90) { + sb->minor_version < 90 || + sb->minor_version > 91) { printk(KERN_WARNING "Bad version number %d.%d on %s\n", sb->major_version, sb->minor_version, b); @@ -747,6 +748,20 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->bitmap_offset = 0; mddev->default_bitmap_offset = MD_SB_BYTES >> 9; + if (mddev->minor_version >= 91) { + mddev->reshape_position = sb->reshape_position; + mddev->delta_disks = sb->delta_disks; + mddev->new_level = sb->new_level; + mddev->new_layout = sb->new_layout; + mddev->new_chunk = sb->new_chunk; + } else { + mddev->reshape_position = MaxSector; + mddev->delta_disks = 0; + mddev->new_level = mddev->level; + mddev->new_layout = mddev->layout; + mddev->new_chunk = mddev->chunk_size; + } + if (sb->state & (1<recovery_cp = MaxSector; else { @@ -841,7 +856,6 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) sb->md_magic = MD_SB_MAGIC; sb->major_version = mddev->major_version; - sb->minor_version = mddev->minor_version; sb->patch_version = mddev->patch_version; sb->gvalid_words = 0; /* ignored */ memcpy(&sb->set_uuid0, mddev->uuid+0, 4); @@ -860,6 +874,17 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) sb->events_hi = (mddev->events>>32); sb->events_lo = (u32)mddev->events; + if (mddev->reshape_position == MaxSector) + sb->minor_version = 90; + else { + sb->minor_version = 91; + sb->reshape_position = mddev->reshape_position; + sb->new_level = mddev->new_level; + sb->delta_disks = mddev->delta_disks; + sb->new_layout = mddev->new_layout; + sb->new_chunk = mddev->new_chunk; + } + mddev->minor_version = sb->minor_version; if (mddev->in_sync) { sb->recovery_cp = mddev->recovery_cp; @@ -1104,6 +1129,20 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) } mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset); } + if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { + mddev->reshape_position = le64_to_cpu(sb->reshape_position); + mddev->delta_disks = le32_to_cpu(sb->delta_disks); + mddev->new_level = le32_to_cpu(sb->new_level); + mddev->new_layout = le32_to_cpu(sb->new_layout); + mddev->new_chunk = le32_to_cpu(sb->new_chunk)<<9; + } else { + mddev->reshape_position = MaxSector; + mddev->delta_disks = 0; + mddev->new_level = mddev->level; + mddev->new_layout = mddev->layout; + mddev->new_chunk = mddev->chunk_size; + } + } else if (mddev->pers == NULL) { /* Insist of good event counter while assembling */ __u64 ev1 = le64_to_cpu(sb->events); @@ -1175,6 +1214,14 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset); sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); } + if (mddev->reshape_position != MaxSector) { + sb->feature_map |= cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE); + sb->reshape_position = cpu_to_le64(mddev->reshape_position); + sb->new_layout = cpu_to_le32(mddev->new_layout); + sb->delta_disks = cpu_to_le32(mddev->delta_disks); + sb->new_level = cpu_to_le32(mddev->new_level); + sb->new_chunk = cpu_to_le32(mddev->new_chunk>>9); + } max_dev = 0; ITERATE_RDEV(mddev,rdev2,tmp) @@ -1497,7 +1544,7 @@ static void sync_sbs(mddev_t * mddev) } } -static void md_update_sb(mddev_t * mddev) +void md_update_sb(mddev_t * mddev) { int err; struct list_head *tmp; @@ -1574,6 +1621,7 @@ repeat: wake_up(&mddev->sb_wait); } +EXPORT_SYMBOL_GPL(md_update_sb); /* words written to sysfs files may, or my not, be \n terminated. * We want to accept with case. For this we use cmd_match. @@ -2545,6 +2593,14 @@ static int do_md_run(mddev_t * mddev) mddev->level = pers->level; strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); + if (mddev->reshape_position != MaxSector && + pers->reshape == NULL) { + /* This personality cannot handle reshaping... */ + mddev->pers = NULL; + module_put(pers->owner); + return -EINVAL; + } + mddev->recovery = 0; mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ mddev->barriers_work = 1; @@ -3433,11 +3489,18 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) mddev->default_bitmap_offset = MD_SB_BYTES >> 9; mddev->bitmap_offset = 0; + mddev->reshape_position = MaxSector; + /* * Generate a 128 bit UUID */ get_random_bytes(mddev->uuid, 16); + mddev->new_level = mddev->level; + mddev->new_chunk = mddev->chunk_size; + mddev->new_layout = mddev->layout; + mddev->delta_disks = 0; + return 0; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 5d88329e3c7a..b65b8cfbdf30 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1789,6 +1789,11 @@ static int run(mddev_t *mddev) mdname(mddev), mddev->level); goto out; } + if (mddev->reshape_position != MaxSector) { + printk("raid1: %s: reshape_position set but not supported\n", + mdname(mddev)); + goto out; + } /* * copy the already verified devices into our private RAID1 * bookkeeping area. [whatever we allocate in run(), diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index b29135acb1d9..20ae32d67e21 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -1504,6 +1505,7 @@ static void handle_stripe(struct stripe_head *sh) clear_bit(STRIPE_EXPANDING, &sh->state); } else if (expanded) { clear_bit(STRIPE_EXPAND_READY, &sh->state); + atomic_dec(&conf->reshape_stripes); wake_up(&conf->wait_for_overlap); md_done_sync(conf->mddev, STRIPE_SECTORS, 1); } @@ -1875,6 +1877,26 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i */ int i; int dd_idx; + + if (sector_nr == 0 && + conf->expand_progress != 0) { + /* restarting in the middle, skip the initial sectors */ + sector_nr = conf->expand_progress; + sector_div(sector_nr, conf->raid_disks-1); + *skipped = 1; + return sector_nr; + } + + /* Cannot proceed until we've updated the superblock... */ + wait_event(conf->wait_for_overlap, + atomic_read(&conf->reshape_stripes)==0); + mddev->reshape_position = conf->expand_progress; + + mddev->sb_dirty = 1; + md_wakeup_thread(mddev->thread); + wait_event(mddev->sb_wait, mddev->sb_dirty == 0 || + kthread_should_stop()); + for (i=0; i < conf->chunk_size/512; i+= STRIPE_SECTORS) { int j; int skipped = 0; @@ -1882,6 +1904,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i sh = get_active_stripe(conf, sector_nr+i, conf->raid_disks, pd_idx, 0); set_bit(STRIPE_EXPANDING, &sh->state); + atomic_inc(&conf->reshape_stripes); /* If any of this stripe is beyond the end of the old * array, then we need to zero those blocks */ @@ -2121,10 +2144,61 @@ static int run(mddev_t *mddev) return -EIO; } + if (mddev->reshape_position != MaxSector) { + /* Check that we can continue the reshape. + * Currently only disks can change, it must + * increase, and we must be past the point where + * a stripe over-writes itself + */ + sector_t here_new, here_old; + int old_disks; + + if (mddev->new_level != mddev->level || + mddev->new_layout != mddev->layout || + mddev->new_chunk != mddev->chunk_size) { + printk(KERN_ERR "raid5: %s: unsupported reshape required - aborting.\n", + mdname(mddev)); + return -EINVAL; + } + if (mddev->delta_disks <= 0) { + printk(KERN_ERR "raid5: %s: unsupported reshape (reduce disks) required - aborting.\n", + mdname(mddev)); + return -EINVAL; + } + old_disks = mddev->raid_disks - mddev->delta_disks; + /* reshape_position must be on a new-stripe boundary, and one + * further up in new geometry must map after here in old geometry. + */ + here_new = mddev->reshape_position; + if (sector_div(here_new, (mddev->chunk_size>>9)*(mddev->raid_disks-1))) { + printk(KERN_ERR "raid5: reshape_position not on a stripe boundary\n"); + return -EINVAL; + } + /* here_new is the stripe we will write to */ + here_old = mddev->reshape_position; + sector_div(here_old, (mddev->chunk_size>>9)*(old_disks-1)); + /* here_old is the first stripe that we might need to read from */ + if (here_new >= here_old) { + /* Reading from the same stripe as writing to - bad */ + printk(KERN_ERR "raid5: reshape_position too early for auto-recovery - aborting.\n"); + return -EINVAL; + } + printk(KERN_INFO "raid5: reshape will continue\n"); + /* OK, we should be able to continue; */ + } + + mddev->private = kzalloc(sizeof (raid5_conf_t), GFP_KERNEL); if ((conf = mddev->private) == NULL) goto abort; - conf->disks = kzalloc(mddev->raid_disks * sizeof(struct disk_info), + if (mddev->reshape_position == MaxSector) { + conf->previous_raid_disks = conf->raid_disks = mddev->raid_disks; + } else { + conf->raid_disks = mddev->raid_disks; + conf->previous_raid_disks = mddev->raid_disks - mddev->delta_disks; + } + + conf->disks = kzalloc(conf->raid_disks * sizeof(struct disk_info), GFP_KERNEL); if (!conf->disks) goto abort; @@ -2148,7 +2222,7 @@ static int run(mddev_t *mddev) ITERATE_RDEV(mddev,rdev,tmp) { raid_disk = rdev->raid_disk; - if (raid_disk >= mddev->raid_disks + if (raid_disk >= conf->raid_disks || raid_disk < 0) continue; disk = conf->disks + raid_disk; @@ -2164,7 +2238,6 @@ static int run(mddev_t *mddev) } } - conf->raid_disks = mddev->raid_disks; /* * 0 for a fully functional array, 1 for a degraded array. */ @@ -2174,7 +2247,7 @@ static int run(mddev_t *mddev) conf->level = mddev->level; conf->algorithm = mddev->layout; conf->max_nr_stripes = NR_STRIPES; - conf->expand_progress = MaxSector; + conf->expand_progress = mddev->reshape_position; /* device size must be a multiple of chunk size */ mddev->size &= ~(mddev->chunk_size/1024 -1); @@ -2247,6 +2320,20 @@ static int run(mddev_t *mddev) print_raid5_conf(conf); + if (conf->expand_progress != MaxSector) { + printk("...ok start reshape thread\n"); + atomic_set(&conf->reshape_stripes, 0); + clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); + clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); + set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); + set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); + mddev->sync_thread = md_register_thread(md_do_sync, mddev, + "%s_reshape"); + /* FIXME if md_register_thread fails?? */ + md_wakeup_thread(mddev->sync_thread); + + } + /* read-ahead size must cover two whole stripes, which is * 2 * (n-1) * chunksize where 'n' is the number of raid devices */ @@ -2262,8 +2349,8 @@ static int run(mddev_t *mddev) mddev->queue->unplug_fn = raid5_unplug_device; mddev->queue->issue_flush_fn = raid5_issue_flush; + mddev->array_size = mddev->size * (conf->previous_raid_disks - 1); - mddev->array_size = mddev->size * (mddev->raid_disks - 1); return 0; abort: if (conf) { @@ -2436,7 +2523,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) /* * find the disk ... */ - for (disk=0; disk < mddev->raid_disks; disk++) + for (disk=0; disk < conf->raid_disks; disk++) if ((p=conf->disks + disk)->rdev == NULL) { clear_bit(In_sync, &rdev->flags); rdev->raid_disk = disk; @@ -2518,9 +2605,10 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) if (err) return err; + atomic_set(&conf->reshape_stripes, 0); spin_lock_irq(&conf->device_lock); conf->previous_raid_disks = conf->raid_disks; - mddev->raid_disks = conf->raid_disks = raid_disks; + conf->raid_disks = raid_disks; conf->expand_progress = 0; spin_unlock_irq(&conf->device_lock); @@ -2542,6 +2630,14 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) } mddev->degraded = (raid_disks - conf->previous_raid_disks) - added_devices; + mddev->new_chunk = mddev->chunk_size; + mddev->new_layout = mddev->layout; + mddev->new_level = mddev->level; + mddev->raid_disks = raid_disks; + mddev->delta_disks = raid_disks - conf->previous_raid_disks; + mddev->reshape_position = 0; + mddev->sb_dirty = 1; + clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); @@ -2552,6 +2648,7 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) mddev->recovery = 0; spin_lock_irq(&conf->device_lock); mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks; + mddev->delta_disks = 0; conf->expand_progress = MaxSector; spin_unlock_irq(&conf->device_lock); return -EAGAIN; @@ -2566,20 +2663,23 @@ static void end_reshape(raid5_conf_t *conf) { struct block_device *bdev; - conf->mddev->array_size = conf->mddev->size * (conf->mddev->raid_disks-1); - set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1); - conf->mddev->changed = 1; - - bdev = bdget_disk(conf->mddev->gendisk, 0); - if (bdev) { - mutex_lock(&bdev->bd_inode->i_mutex); - i_size_write(bdev->bd_inode, conf->mddev->array_size << 10); - mutex_unlock(&bdev->bd_inode->i_mutex); - bdput(bdev); + if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { + conf->mddev->array_size = conf->mddev->size * (conf->raid_disks-1); + set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1); + conf->mddev->changed = 1; + + bdev = bdget_disk(conf->mddev->gendisk, 0); + if (bdev) { + mutex_lock(&bdev->bd_inode->i_mutex); + i_size_write(bdev->bd_inode, conf->mddev->array_size << 10); + mutex_unlock(&bdev->bd_inode->i_mutex); + bdput(bdev); + } + spin_lock_irq(&conf->device_lock); + conf->expand_progress = MaxSector; + spin_unlock_irq(&conf->device_lock); + conf->mddev->reshape_position = MaxSector; } - spin_lock_irq(&conf->device_lock); - conf->expand_progress = MaxSector; - spin_unlock_irq(&conf->device_lock); } static void raid5_quiesce(mddev_t *mddev, int state) diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index 9c77cde5a795..66b44e5e0d6e 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h @@ -95,6 +95,8 @@ extern int sync_page_io(struct block_device *bdev, sector_t sector, int size, extern void md_do_sync(mddev_t *mddev); extern void md_new_event(mddev_t *mddev); +extern void md_update_sb(mddev_t * mddev); + #define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); } #endif diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 4e26ef2cacca..1a6f9f2f6282 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -132,6 +132,14 @@ struct mddev_s char uuid[16]; + /* If the array is being reshaped, we need to record the + * new shape and an indication of where we are up to. + * This is written to the superblock. + * If reshape_position is MaxSector, then no reshape is happening (yet). + */ + sector_t reshape_position; + int delta_disks, new_level, new_layout, new_chunk; + struct mdk_thread_s *thread; /* management thread */ struct mdk_thread_s *sync_thread; /* doing resync or reconstruct */ sector_t curr_resync; /* blocks scheduled */ diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h index c100fa5d4bfa..774e1acfb8c4 100644 --- a/include/linux/raid/md_p.h +++ b/include/linux/raid/md_p.h @@ -102,6 +102,18 @@ typedef struct mdp_device_descriptor_s { #define MD_SB_ERRORS 1 #define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */ + +/* + * Notes: + * - if an array is being reshaped (restriped) in order to change the + * the number of active devices in the array, 'raid_disks' will be + * the larger of the old and new numbers. 'delta_disks' will + * be the "new - old". So if +ve, raid_disks is the new value, and + * "raid_disks-delta_disks" is the old. If -ve, raid_disks is the + * old value and "raid_disks+delta_disks" is the new (smaller) value. + */ + + typedef struct mdp_superblock_s { /* * Constant generic information @@ -146,7 +158,13 @@ typedef struct mdp_superblock_s { __u32 cp_events_hi; /* 10 high-order of checkpoint update count */ #endif __u32 recovery_cp; /* 11 recovery checkpoint sector count */ - __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 12]; + /* There are only valid for minor_version > 90 */ + __u64 reshape_position; /* 12,13 next address in array-space for reshape */ + __u32 new_level; /* 14 new level we are reshaping to */ + __u32 delta_disks; /* 15 change in number of raid_disks */ + __u32 new_layout; /* 16 new layout */ + __u32 new_chunk; /* 17 new chunk size (bytes) */ + __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18]; /* * Personality information @@ -207,7 +225,14 @@ struct mdp_superblock_1 { * NOTE: signed, so bitmap can be before superblock * only meaningful of feature_map[0] is set. */ - __u8 pad1[128-100]; /* set to 0 when written */ + + /* These are only valid with feature bit '4' */ + __u64 reshape_position; /* next address in array-space for reshape */ + __u32 new_level; /* new level we are reshaping to */ + __u32 delta_disks; /* change in number of raid_disks */ + __u32 new_layout; /* new layout */ + __u32 new_chunk; /* new chunk size (bytes) */ + __u8 pad1[128-124]; /* set to 0 when written */ /* constant this-device information - 64 bytes */ __u64 data_offset; /* sector start of data, often 0 */ @@ -240,8 +265,9 @@ struct mdp_superblock_1 { /* feature_map bits */ #define MD_FEATURE_BITMAP_OFFSET 1 +#define MD_FEATURE_RESHAPE_ACTIVE 4 -#define MD_FEATURE_ALL 1 +#define MD_FEATURE_ALL 5 #endif diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index 55c738d50508..abcdf0d0658a 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -224,6 +224,7 @@ struct raid5_private_data { struct list_head bitmap_list; /* stripes delaying awaiting bitmap update */ atomic_t preread_active_stripes; /* stripes with scheduled io */ + atomic_t reshape_stripes; /* stripes with pending writes for reshape */ /* unfortunately we need two cache names as we temporarily have * two caches. */ -- cgit v1.2.3-59-g8ed1b From b578d55fdd80140f657130abd85aebeb345755fb Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:12 -0800 Subject: [PATCH] md: Only checkpoint expansion progress occasionally Instead of checkpointing at each stripe, only checkpoint when a new write would overwrite uncheckpointed data. Block any write to the uncheckpointed area. Arbitrarily checkpoint at least every 3Meg. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 53 ++++++++++++++++++++++++++++++++++++---------- include/linux/raid/raid5.h | 3 +++ 2 files changed, 45 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 20ae32d67e21..089a32604305 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1762,8 +1762,9 @@ static int make_request(request_queue_t *q, struct bio * bi) for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { DEFINE_WAIT(w); int disks; - + retry: + prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); if (likely(conf->expand_progress == MaxSector)) disks = conf->raid_disks; else { @@ -1771,6 +1772,13 @@ static int make_request(request_queue_t *q, struct bio * bi) disks = conf->raid_disks; if (logical_sector >= conf->expand_progress) disks = conf->previous_raid_disks; + else { + if (logical_sector >= conf->expand_lo) { + spin_unlock_irq(&conf->device_lock); + schedule(); + goto retry; + } + } spin_unlock_irq(&conf->device_lock); } new_sector = raid5_compute_sector(logical_sector, disks, disks - 1, @@ -1779,7 +1787,6 @@ static int make_request(request_queue_t *q, struct bio * bi) (unsigned long long)new_sector, (unsigned long long)logical_sector); - prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); sh = get_active_stripe(conf, new_sector, disks, pd_idx, (bi->bi_rw&RWA_MASK)); if (sh) { if (unlikely(conf->expand_progress != MaxSector)) { @@ -1877,6 +1884,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i */ int i; int dd_idx; + sector_t writepos, safepos, gap; if (sector_nr == 0 && conf->expand_progress != 0) { @@ -1887,15 +1895,36 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i return sector_nr; } - /* Cannot proceed until we've updated the superblock... */ - wait_event(conf->wait_for_overlap, - atomic_read(&conf->reshape_stripes)==0); - mddev->reshape_position = conf->expand_progress; - - mddev->sb_dirty = 1; - md_wakeup_thread(mddev->thread); - wait_event(mddev->sb_wait, mddev->sb_dirty == 0 || - kthread_should_stop()); + /* we update the metadata when there is more than 3Meg + * in the block range (that is rather arbitrary, should + * probably be time based) or when the data about to be + * copied would over-write the source of the data at + * the front of the range. + * i.e. one new_stripe forward from expand_progress new_maps + * to after where expand_lo old_maps to + */ + writepos = conf->expand_progress + + conf->chunk_size/512*(conf->raid_disks-1); + sector_div(writepos, conf->raid_disks-1); + safepos = conf->expand_lo; + sector_div(safepos, conf->previous_raid_disks-1); + gap = conf->expand_progress - conf->expand_lo; + + if (writepos >= safepos || + gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) { + /* Cannot proceed until we've updated the superblock... */ + wait_event(conf->wait_for_overlap, + atomic_read(&conf->reshape_stripes)==0); + mddev->reshape_position = conf->expand_progress; + mddev->sb_dirty = 1; + md_wakeup_thread(mddev->thread); + wait_event(mddev->sb_wait, mddev->sb_dirty == 0 || + kthread_should_stop()); + spin_lock_irq(&conf->device_lock); + conf->expand_lo = mddev->reshape_position; + spin_unlock_irq(&conf->device_lock); + wake_up(&conf->wait_for_overlap); + } for (i=0; i < conf->chunk_size/512; i+= STRIPE_SECTORS) { int j; @@ -2322,6 +2351,7 @@ static int run(mddev_t *mddev) if (conf->expand_progress != MaxSector) { printk("...ok start reshape thread\n"); + conf->expand_lo = conf->expand_progress; atomic_set(&conf->reshape_stripes, 0); clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); @@ -2610,6 +2640,7 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) conf->previous_raid_disks = conf->raid_disks; conf->raid_disks = raid_disks; conf->expand_progress = 0; + conf->expand_lo = 0; spin_unlock_irq(&conf->device_lock); /* Add some new drives, as many as will fit. diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index abcdf0d0658a..914af667044f 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -217,6 +217,9 @@ struct raid5_private_data { /* used during an expand */ sector_t expand_progress; /* MaxSector when no expand happening */ + sector_t expand_lo; /* from here up to expand_progress it out-of-bounds + * as we haven't flushed the metadata yet + */ int previous_raid_disks; struct list_head handle_list; /* stripes needing handling */ -- cgit v1.2.3-59-g8ed1b From 63c70c4f3a30e77e6f445bd16eff7934a031ebd3 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:13 -0800 Subject: [PATCH] md: Split reshape handler in check_reshape and start_reshape check_reshape checks validity and does things that can be done instantly - like adding devices to raid1. start_reshape initiates a restriping process to convert the whole array. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 10 ++++---- drivers/md/raid1.c | 19 ++++++++++++--- drivers/md/raid5.c | 60 +++++++++++++++++++++++++++-------------------- include/linux/raid/md_k.h | 3 ++- 4 files changed, 58 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index b9dfdfccdb78..1a637676a930 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2594,7 +2594,7 @@ static int do_md_run(mddev_t * mddev) strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); if (mddev->reshape_position != MaxSector && - pers->reshape == NULL) { + pers->start_reshape == NULL) { /* This personality cannot handle reshaping... */ mddev->pers = NULL; module_put(pers->owner); @@ -3556,14 +3556,16 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks) { int rv; /* change the number of raid disks */ - if (mddev->pers->reshape == NULL) + if (mddev->pers->check_reshape == NULL) return -EINVAL; if (raid_disks <= 0 || raid_disks >= mddev->max_disks) return -EINVAL; - if (mddev->sync_thread) + if (mddev->sync_thread || mddev->reshape_position != MaxSector) return -EBUSY; - rv = mddev->pers->reshape(mddev, raid_disks); + mddev->delta_disks = raid_disks - mddev->raid_disks; + + rv = mddev->pers->check_reshape(mddev); return rv; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index b65b8cfbdf30..04418e10d1dc 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1976,7 +1976,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors) return 0; } -static int raid1_reshape(mddev_t *mddev, int raid_disks) +static int raid1_reshape(mddev_t *mddev) { /* We need to: * 1/ resize the r1bio_pool @@ -1993,10 +1993,22 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) struct pool_info *newpoolinfo; mirror_info_t *newmirrors; conf_t *conf = mddev_to_conf(mddev); - int cnt; + int cnt, raid_disks; int d, d2; + /* Cannot change chunk_size, layout, or level */ + if (mddev->chunk_size != mddev->new_chunk || + mddev->layout != mddev->new_layout || + mddev->level != mddev->new_level) { + mddev->new_chunk = mddev->chunk_size; + mddev->new_layout = mddev->layout; + mddev->new_level = mddev->level; + return -EINVAL; + } + + raid_disks = mddev->raid_disks + mddev->delta_disks; + if (raid_disks < conf->raid_disks) { cnt=0; for (d= 0; d < conf->raid_disks; d++) @@ -2043,6 +2055,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) mddev->degraded += (raid_disks - conf->raid_disks); conf->raid_disks = mddev->raid_disks = raid_disks; + mddev->delta_disks = 0; conf->last_used = 0; /* just make sure it is in-range */ lower_barrier(conf); @@ -2084,7 +2097,7 @@ static struct mdk_personality raid1_personality = .spare_active = raid1_spare_active, .sync_request = sync_request, .resize = raid1_resize, - .reshape = raid1_reshape, + .check_reshape = raid1_reshape, .quiesce = raid1_quiesce, }; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 089a32604305..355dafb98aac 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2590,21 +2590,15 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors) } #ifdef CONFIG_MD_RAID5_RESHAPE -static int raid5_reshape(mddev_t *mddev, int raid_disks) +static int raid5_check_reshape(mddev_t *mddev) { raid5_conf_t *conf = mddev_to_conf(mddev); int err; - mdk_rdev_t *rdev; - struct list_head *rtmp; - int spares = 0; - int added_devices = 0; - if (mddev->degraded || - test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) - return -EBUSY; - if (conf->raid_disks > raid_disks) - return -EINVAL; /* Cannot shrink array yet */ - if (conf->raid_disks == raid_disks) + if (mddev->delta_disks < 0 || + mddev->new_level != mddev->level) + return -EINVAL; /* Cannot shrink array or change level yet */ + if (mddev->delta_disks == 0) return 0; /* nothing to do */ /* Can only proceed if there are plenty of stripe_heads. @@ -2615,30 +2609,48 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) * If the chunk size is greater, user-space should request more * stripe_heads first. */ - if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes) { + if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes || + (mddev->new_chunk / STRIPE_SIZE) * 4 > conf->max_nr_stripes) { printk(KERN_WARNING "raid5: reshape: not enough stripes. Needed %lu\n", (mddev->chunk_size / STRIPE_SIZE)*4); return -ENOSPC; } + err = resize_stripes(conf, conf->raid_disks + mddev->delta_disks); + if (err) + return err; + + /* looks like we might be able to manage this */ + return 0; +} + +static int raid5_start_reshape(mddev_t *mddev) +{ + raid5_conf_t *conf = mddev_to_conf(mddev); + mdk_rdev_t *rdev; + struct list_head *rtmp; + int spares = 0; + int added_devices = 0; + + if (mddev->degraded || + test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) + return -EBUSY; + ITERATE_RDEV(mddev, rdev, rtmp) if (rdev->raid_disk < 0 && !test_bit(Faulty, &rdev->flags)) spares++; - if (conf->raid_disks + spares < raid_disks-1) + + if (spares < mddev->delta_disks-1) /* Not enough devices even to make a degraded array * of that size */ return -EINVAL; - err = resize_stripes(conf, raid_disks); - if (err) - return err; - atomic_set(&conf->reshape_stripes, 0); spin_lock_irq(&conf->device_lock); conf->previous_raid_disks = conf->raid_disks; - conf->raid_disks = raid_disks; + conf->raid_disks += mddev->delta_disks; conf->expand_progress = 0; conf->expand_lo = 0; spin_unlock_irq(&conf->device_lock); @@ -2660,12 +2672,8 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) break; } - mddev->degraded = (raid_disks - conf->previous_raid_disks) - added_devices; - mddev->new_chunk = mddev->chunk_size; - mddev->new_layout = mddev->layout; - mddev->new_level = mddev->level; - mddev->raid_disks = raid_disks; - mddev->delta_disks = raid_disks - conf->previous_raid_disks; + mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices; + mddev->raid_disks = conf->raid_disks; mddev->reshape_position = 0; mddev->sb_dirty = 1; @@ -2679,7 +2687,6 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) mddev->recovery = 0; spin_lock_irq(&conf->device_lock); mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks; - mddev->delta_disks = 0; conf->expand_progress = MaxSector; spin_unlock_irq(&conf->device_lock); return -EAGAIN; @@ -2752,7 +2759,8 @@ static struct mdk_personality raid5_personality = .sync_request = sync_request, .resize = raid5_resize, #ifdef CONFIG_MD_RAID5_RESHAPE - .reshape = raid5_reshape, + .check_reshape = raid5_check_reshape, + .start_reshape = raid5_start_reshape, #endif .quiesce = raid5_quiesce, }; diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 1a6f9f2f6282..002ee631fabb 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -261,7 +261,8 @@ struct mdk_personality int (*spare_active) (mddev_t *mddev); sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster); int (*resize) (mddev_t *mddev, sector_t sectors); - int (*reshape) (mddev_t *mddev, int raid_disks); + int (*check_reshape) (mddev_t *mddev); + int (*start_reshape) (mddev_t *mddev); int (*reconfig) (mddev_t *mddev, int layout, int chunk_size); /* quiesce moves between quiescence states * 0 - fully active -- cgit v1.2.3-59-g8ed1b From 16484bf59634e25d1299761e5ed8bacf22bc6368 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:13 -0800 Subject: [PATCH] md: Make 'reshape' a possible sync_action action This allows reshape to be triggerred via sysfs (which is the only way to start it happening). Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 1a637676a930..a79dd33d343d 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2247,7 +2247,14 @@ action_store(mddev_t *mddev, const char *page, size_t len) return -EBUSY; else if (cmd_match(page, "resync") || cmd_match(page, "recover")) set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - else { + else if (cmd_match(page, "reshape")) { + int err; + if (mddev->pers->start_reshape == NULL) + return -EINVAL; + err = mddev->pers->start_reshape(mddev); + if (err) + return err; + } else { if (cmd_match(page, "check")) set_bit(MD_RECOVERY_CHECK, &mddev->recovery); else if (cmd_match(page, "repair")) -- cgit v1.2.3-59-g8ed1b From e464eafdb4400c6d6576ba3840d8bd40340f8a96 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:14 -0800 Subject: [PATCH] md: Support suspending of IO to regions of an md array This allows user-space to access data safely. This is needed for raid5 reshape as user-space needs to take a backup of the first few stripes before allowing reshape to commence. It will also be useful in cluster-aware raid1 configurations so that all cluster members can leave a section of the array untouched while a resync/recovery happens. A 'start' and 'end' of the suspended range are written to 2 sysfs attributes. Note that only one range can be suspended at a time. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/md/raid5.c | 14 +++++++++++ include/linux/raid/md_k.h | 4 ++++ 3 files changed, 77 insertions(+) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index a79dd33d343d..92fd0104fa04 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2365,6 +2365,63 @@ sync_completed_show(mddev_t *mddev, char *page) static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); +static ssize_t +suspend_lo_show(mddev_t *mddev, char *page) +{ + return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo); +} + +static ssize_t +suspend_lo_store(mddev_t *mddev, const char *buf, size_t len) +{ + char *e; + unsigned long long new = simple_strtoull(buf, &e, 10); + + if (mddev->pers->quiesce == NULL) + return -EINVAL; + if (buf == e || (*e && *e != '\n')) + return -EINVAL; + if (new >= mddev->suspend_hi || + (new > mddev->suspend_lo && new < mddev->suspend_hi)) { + mddev->suspend_lo = new; + mddev->pers->quiesce(mddev, 2); + return len; + } else + return -EINVAL; +} +static struct md_sysfs_entry md_suspend_lo = +__ATTR(suspend_lo, S_IRUGO|S_IWUSR, suspend_lo_show, suspend_lo_store); + + +static ssize_t +suspend_hi_show(mddev_t *mddev, char *page) +{ + return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_hi); +} + +static ssize_t +suspend_hi_store(mddev_t *mddev, const char *buf, size_t len) +{ + char *e; + unsigned long long new = simple_strtoull(buf, &e, 10); + + if (mddev->pers->quiesce == NULL) + return -EINVAL; + if (buf == e || (*e && *e != '\n')) + return -EINVAL; + if ((new <= mddev->suspend_lo && mddev->suspend_lo >= mddev->suspend_hi) || + (new > mddev->suspend_lo && new > mddev->suspend_hi)) { + mddev->suspend_hi = new; + mddev->pers->quiesce(mddev, 1); + mddev->pers->quiesce(mddev, 0); + return len; + } else + return -EINVAL; +} +static struct md_sysfs_entry md_suspend_hi = +__ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store); + + static struct attribute *md_default_attrs[] = { &md_level.attr, &md_raid_disks.attr, @@ -2382,6 +2439,8 @@ static struct attribute *md_redundancy_attrs[] = { &md_sync_max.attr, &md_sync_speed.attr, &md_sync_completed.attr, + &md_suspend_lo.attr, + &md_suspend_hi.attr, NULL, }; static struct attribute_group md_redundancy_group = { diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 355dafb98aac..bb16ac231a40 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1805,6 +1805,15 @@ static int make_request(request_queue_t *q, struct bio * bi) goto retry; } } + /* FIXME what if we get a false positive because these + * are being updated. + */ + if (logical_sector >= mddev->suspend_lo && + logical_sector < mddev->suspend_hi) { + release_stripe(sh); + schedule(); + goto retry; + } if (test_bit(STRIPE_EXPANDING, &sh->state) || !add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) { @@ -2725,6 +2734,10 @@ static void raid5_quiesce(mddev_t *mddev, int state) raid5_conf_t *conf = mddev_to_conf(mddev); switch(state) { + case 2: /* resume for a suspend */ + wake_up(&conf->wait_for_overlap); + break; + case 1: /* stop all writes */ spin_lock_irq(&conf->device_lock); conf->quiesce = 1; @@ -2738,6 +2751,7 @@ static void raid5_quiesce(mddev_t *mddev, int state) spin_lock_irq(&conf->device_lock); conf->quiesce = 0; wake_up(&conf->wait_for_stripe); + wake_up(&conf->wait_for_overlap); spin_unlock_irq(&conf->device_lock); break; } diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 002ee631fabb..c0d3097846a7 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -151,6 +151,10 @@ struct mddev_s sector_t resync_mismatches; /* count of sectors where * parity/replica mismatch found */ + + /* allow user-space to request suspension of IO to regions of the array */ + sector_t suspend_lo; + sector_t suspend_hi; /* if zero, use the system-wide default */ int sync_speed_min; int sync_speed_max; -- cgit v1.2.3-59-g8ed1b From df8e7f7639bab3b2cc536a1d30d5593d65251778 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:15 -0800 Subject: [PATCH] md: Improve comments about locking situation in raid5 make_request Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index bb16ac231a40..8eded08411f3 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1768,6 +1768,14 @@ static int make_request(request_queue_t *q, struct bio * bi) if (likely(conf->expand_progress == MaxSector)) disks = conf->raid_disks; else { + /* spinlock is needed as expand_progress may be + * 64bit on a 32bit platform, and so it might be + * possible to see a half-updated value + * Ofcourse expand_progress could change after + * the lock is dropped, so once we get a reference + * to the stripe that we think it is, we will have + * to check again. + */ spin_lock_irq(&conf->device_lock); disks = conf->raid_disks; if (logical_sector >= conf->expand_progress) @@ -1791,7 +1799,12 @@ static int make_request(request_queue_t *q, struct bio * bi) if (sh) { if (unlikely(conf->expand_progress != MaxSector)) { /* expansion might have moved on while waiting for a - * stripe, so we much do the range check again. + * stripe, so we must do the range check again. + * Expansion could still move past after this + * test, but as we are holding a reference to + * 'sh', we know that if that happens, + * STRIPE_EXPANDING will get set and the expansion + * won't proceed until we finish with the stripe. */ int must_retry = 0; spin_lock_irq(&conf->device_lock); -- cgit v1.2.3-59-g8ed1b From b3b46be38aef5c46a4e144f1bcb8d0cc6bf3ff97 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:16 -0800 Subject: [PATCH] md: Remove some stray semi-colons after functions called in macro.. wait_event_lock_irq puts a ';' after its usage of the 4th arg, so we don't need to. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 8eded08411f3..59c8772ee4ee 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -262,7 +262,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector < (conf->max_nr_stripes *3/4) || !conf->inactive_blocked), conf->device_lock, - unplug_slaves(conf->mddev); + unplug_slaves(conf->mddev) ); conf->inactive_blocked = 0; } else @@ -407,7 +407,7 @@ static int resize_stripes(raid5_conf_t *conf, int newsize) wait_event_lock_irq(conf->wait_for_stripe, !list_empty(&conf->inactive_list), conf->device_lock, - unplug_slaves(conf->mddev); + unplug_slaves(conf->mddev) ); osh = get_free_stripe(conf); spin_unlock_irq(&conf->device_lock); -- cgit v1.2.3-59-g8ed1b From f6344757a92e5466bf8c23a74ee8f972ff35cb05 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:17 -0800 Subject: [PATCH] md: Remove bi_end_io call out from under a spinlock raid5 overloads bi_phys_segments to count the number of blocks that the request was broken in to so that it knows when the bio is completely handled. Accessing this must always be done under a spinlock. In one case we also call bi_end_io under that spinlock, which probably isn't ideal as bi_end_io could be expensive (even though it isn't allowed to sleep). So we reducde the range of the spinlock to just accessing bi_phys_segments. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 59c8772ee4ee..dae740adaf65 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1743,6 +1743,7 @@ static int make_request(request_queue_t *q, struct bio * bi) sector_t logical_sector, last_sector; struct stripe_head *sh; const int rw = bio_data_dir(bi); + int remaining; if (unlikely(bio_barrier(bi))) { bio_endio(bi, bi->bi_size, -EOPNOTSUPP); @@ -1852,7 +1853,9 @@ static int make_request(request_queue_t *q, struct bio * bi) } spin_lock_irq(&conf->device_lock); - if (--bi->bi_phys_segments == 0) { + remaining = --bi->bi_phys_segments; + spin_unlock_irq(&conf->device_lock); + if (remaining == 0) { int bytes = bi->bi_size; if ( bio_data_dir(bi) == WRITE ) @@ -1860,7 +1863,6 @@ static int make_request(request_queue_t *q, struct bio * bi) bi->bi_size = 0; bi->bi_end_io(bi, bytes, 0); } - spin_unlock_irq(&conf->device_lock); return 0; } -- cgit v1.2.3-59-g8ed1b From 8ddeeae51f2f197b4fafcba117ee8191b49d843e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:18 -0800 Subject: [PATCH] md: Fix md grow/size code to correctly find the maximum available space An md array can be asked to change the amount of each device that it is using, and in particular can be asked to use the maximum available space. This currently only works if the first device is not larger than the rest. As 'size' gets changed and so 'fit' becomes wrong. So check if a 'fit' is required early and don't corrupt it. Signed-off-by: Doug Ledford Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 92fd0104fa04..147efcb1e8ca 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3575,6 +3575,7 @@ static int update_size(mddev_t *mddev, unsigned long size) mdk_rdev_t * rdev; int rv; struct list_head *tmp; + int fit = (size == 0); if (mddev->pers->resize == NULL) return -EINVAL; @@ -3592,7 +3593,6 @@ static int update_size(mddev_t *mddev, unsigned long size) return -EBUSY; ITERATE_RDEV(mddev,rdev,tmp) { sector_t avail; - int fit = (size == 0); if (rdev->sb_offset > rdev->data_offset) avail = (rdev->sb_offset*2) - rdev->data_offset; else -- cgit v1.2.3-59-g8ed1b From 2f889129de148b0ba2e1fbc9e9d33a4ef4c5f2cb Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:19 -0800 Subject: [PATCH] md: Restore 'remaining' count when retrying an write operation When retrying a write due to barrier failure, we don't reset 'remaining', so it goes negative and never hits 0 again. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid1.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 04418e10d1dc..3cb0872a845d 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1401,6 +1401,9 @@ static void raid1d(mddev_t *mddev) int i; clear_bit(R1BIO_BarrierRetry, &r1_bio->state); clear_bit(R1BIO_Barrier, &r1_bio->state); + for (i=0; i < conf->raid_disks; i++) + if (r1_bio->bios[i]) + atomic_inc(&r1_bio->remaining); for (i=0; i < conf->raid_disks; i++) if (r1_bio->bios[i]) { struct bio_vec *bvec; -- cgit v1.2.3-59-g8ed1b From 48c9c27b8bcd2a328a06151e2d5c1170db0b701b Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Mon, 27 Mar 2006 01:18:20 -0800 Subject: [PATCH] sem2mutex: drivers/md 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: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-table.c | 11 ++++++----- drivers/md/dm.c | 19 ++++++++++--------- drivers/md/kcopyd.c | 11 ++++++----- drivers/md/md.c | 11 ++++++----- 4 files changed, 28 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 76610a6ac01c..8f56a54cf0ce 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #define MAX_DEPTH 16 @@ -770,14 +771,14 @@ int dm_table_complete(struct dm_table *t) return r; } -static DECLARE_MUTEX(_event_lock); +static DEFINE_MUTEX(_event_lock); void dm_table_event_callback(struct dm_table *t, void (*fn)(void *), void *context) { - down(&_event_lock); + mutex_lock(&_event_lock); t->event_fn = fn; t->event_context = context; - up(&_event_lock); + mutex_unlock(&_event_lock); } void dm_table_event(struct dm_table *t) @@ -788,10 +789,10 @@ void dm_table_event(struct dm_table *t) */ BUG_ON(in_interrupt()); - down(&_event_lock); + mutex_lock(&_event_lock); if (t->event_fn) t->event_fn(t->event_context); - up(&_event_lock); + mutex_unlock(&_event_lock); } sector_t dm_table_get_size(struct dm_table *t) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 973e63d530ae..4d710b7a133b 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -743,14 +744,14 @@ static int dm_any_congested(void *congested_data, int bdi_bits) /*----------------------------------------------------------------- * An IDR is used to keep track of allocated minor numbers. *---------------------------------------------------------------*/ -static DECLARE_MUTEX(_minor_lock); +static DEFINE_MUTEX(_minor_lock); static DEFINE_IDR(_minor_idr); static void free_minor(unsigned int minor) { - down(&_minor_lock); + mutex_lock(&_minor_lock); idr_remove(&_minor_idr, minor); - up(&_minor_lock); + mutex_unlock(&_minor_lock); } /* @@ -763,7 +764,7 @@ static int specific_minor(struct mapped_device *md, unsigned int minor) if (minor >= (1 << MINORBITS)) return -EINVAL; - down(&_minor_lock); + mutex_lock(&_minor_lock); if (idr_find(&_minor_idr, minor)) { r = -EBUSY; @@ -788,7 +789,7 @@ static int specific_minor(struct mapped_device *md, unsigned int minor) } out: - up(&_minor_lock); + mutex_unlock(&_minor_lock); return r; } @@ -797,7 +798,7 @@ static int next_free_minor(struct mapped_device *md, unsigned int *minor) int r; unsigned int m; - down(&_minor_lock); + mutex_lock(&_minor_lock); r = idr_pre_get(&_minor_idr, GFP_KERNEL); if (!r) { @@ -819,7 +820,7 @@ static int next_free_minor(struct mapped_device *md, unsigned int *minor) *minor = m; out: - up(&_minor_lock); + mutex_unlock(&_minor_lock); return r; } @@ -1014,13 +1015,13 @@ static struct mapped_device *dm_find_md(dev_t dev) if (MAJOR(dev) != _major || minor >= (1 << MINORBITS)) return NULL; - down(&_minor_lock); + mutex_lock(&_minor_lock); md = idr_find(&_minor_idr, minor); if (!md || (dm_disk(md)->first_minor != minor)) md = NULL; - up(&_minor_lock); + mutex_unlock(&_minor_lock); return md; } diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index ed71f3f94620..72480a48d88b 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "kcopyd.h" @@ -581,21 +582,21 @@ int kcopyd_cancel(struct kcopyd_job *job, int block) /*----------------------------------------------------------------- * Unit setup *---------------------------------------------------------------*/ -static DECLARE_MUTEX(_client_lock); +static DEFINE_MUTEX(_client_lock); static LIST_HEAD(_clients); static void client_add(struct kcopyd_client *kc) { - down(&_client_lock); + mutex_lock(&_client_lock); list_add(&kc->list, &_clients); - up(&_client_lock); + mutex_unlock(&_client_lock); } static void client_del(struct kcopyd_client *kc) { - down(&_client_lock); + mutex_lock(&_client_lock); list_del(&kc->list); - up(&_client_lock); + mutex_unlock(&_client_lock); } static DEFINE_MUTEX(kcopyd_init_lock); diff --git a/drivers/md/md.c b/drivers/md/md.c index 147efcb1e8ca..c9c9c096ad80 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -43,6 +43,7 @@ #include /* for invalidate_bdev */ #include #include +#include #include @@ -2500,7 +2501,7 @@ int mdp_major = 0; static struct kobject *md_probe(dev_t dev, int *part, void *data) { - static DECLARE_MUTEX(disks_sem); + static DEFINE_MUTEX(disks_mutex); mddev_t *mddev = mddev_find(dev); struct gendisk *disk; int partitioned = (MAJOR(dev) != MD_MAJOR); @@ -2510,15 +2511,15 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) if (!mddev) return NULL; - down(&disks_sem); + mutex_lock(&disks_mutex); if (mddev->gendisk) { - up(&disks_sem); + mutex_unlock(&disks_mutex); mddev_put(mddev); return NULL; } disk = alloc_disk(1 << shift); if (!disk) { - up(&disks_sem); + mutex_unlock(&disks_mutex); mddev_put(mddev); return NULL; } @@ -2536,7 +2537,7 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) disk->queue = mddev->queue; add_disk(disk); mddev->gendisk = disk; - up(&disks_sem); + mutex_unlock(&disks_mutex); mddev->kobj.parent = &disk->kobj; mddev->kobj.k_name = NULL; snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md"); -- cgit v1.2.3-59-g8ed1b From df5b89b323b922f56650b4b4d7c41899b937cf19 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 27 Mar 2006 01:18:20 -0800 Subject: [PATCH] md: Convert reconfig_sem to reconfig_mutex ... being careful that mutex_trylock is inverted wrt down_trylock Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 14 +++++++------- include/linux/raid/md_k.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index c9c9c096ad80..039e071c1007 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -255,7 +255,7 @@ static mddev_t * mddev_find(dev_t unit) else new->md_minor = MINOR(unit) >> MdpMinorShift; - init_MUTEX(&new->reconfig_sem); + mutex_init(&new->reconfig_mutex); INIT_LIST_HEAD(&new->disks); INIT_LIST_HEAD(&new->all_mddevs); init_timer(&new->safemode_timer); @@ -277,22 +277,22 @@ static mddev_t * mddev_find(dev_t unit) static inline int mddev_lock(mddev_t * mddev) { - return down_interruptible(&mddev->reconfig_sem); + return mutex_lock_interruptible(&mddev->reconfig_mutex); } static inline void mddev_lock_uninterruptible(mddev_t * mddev) { - down(&mddev->reconfig_sem); + mutex_lock(&mddev->reconfig_mutex); } static inline int mddev_trylock(mddev_t * mddev) { - return down_trylock(&mddev->reconfig_sem); + return mutex_trylock(&mddev->reconfig_mutex); } static inline void mddev_unlock(mddev_t * mddev) { - up(&mddev->reconfig_sem); + mutex_unlock(&mddev->reconfig_mutex); md_wakeup_thread(mddev->thread); } @@ -4893,7 +4893,7 @@ void md_check_recovery(mddev_t *mddev) )) return; - if (mddev_trylock(mddev)==0) { + if (mddev_trylock(mddev)) { int spares =0; spin_lock_irq(&mddev->write_lock); @@ -5029,7 +5029,7 @@ static int md_notify_reboot(struct notifier_block *this, printk(KERN_INFO "md: stopping all md devices.\n"); ITERATE_MDDEV(mddev,tmp) - if (mddev_trylock(mddev)==0) + if (mddev_trylock(mddev)) do_md_stop (mddev, 1); /* * certain more exotic SCSI devices are known to be diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index c0d3097846a7..e2df61f5b09a 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -185,7 +185,7 @@ struct mddev_s unsigned long recovery; int in_sync; /* know to not need resync */ - struct semaphore reconfig_sem; + struct mutex reconfig_mutex; atomic_t active; int changed; /* true if we might need to reread partition info */ -- cgit v1.2.3-59-g8ed1b From 45d607ed92695d7543f5e1fc5b133cd69834e3e4 Mon Sep 17 00:00:00 2001 From: "Ryan S. Arnold" Date: Mon, 27 Mar 2006 21:25:16 +0200 Subject: [PATCH] powerpc: hvc_console updates These are some updates from both Ryan and Arnd for the hvc_console driver: The main point is to enable the inclusion of a console driver for rtas, which is currrently needed for the cell platform. Also shuffle around some data-type declarations and moves some functions out of include/asm-ppc64/hvconsole.h and into a new drivers/char/hvc_console.h file. Signed-off-by: "Ryan S. Arnold" Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/hvconsole.c | 5 +++ drivers/char/Kconfig | 10 +++++ drivers/char/Makefile | 3 +- drivers/char/hvc_console.c | 69 +++++++++++++----------------- drivers/char/hvc_console.h | 63 +++++++++++++++++++++++++++ drivers/char/hvc_vio.c | 11 +++++ include/asm-powerpc/hvconsole.h | 26 ++++------- 7 files changed, 128 insertions(+), 59 deletions(-) create mode 100644 drivers/char/hvc_console.h (limited to 'drivers') diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c index 138e128a3886..ba6befd96636 100644 --- a/arch/powerpc/platforms/pseries/hvconsole.c +++ b/arch/powerpc/platforms/pseries/hvconsole.c @@ -62,6 +62,11 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count) unsigned long *lbuf = (unsigned long *) buf; long ret; + + /* hcall will ret H_PARAMETER if 'count' exceeds firmware max.*/ + if (count > MAX_VIO_PUT_CHARS) + count = MAX_VIO_PUT_CHARS; + ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0], lbuf[1]); if (ret == H_Success) diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index facc3f1d9e37..831419381cf5 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -561,9 +561,19 @@ config TIPAR If unsure, say N. +config HVC_DRIVER + bool + help + Users of pSeries machines that want to utilize the hvc console front-end + module for their backend console driver should select this option. + It will automatically be selected if one of the back-end console drivers + is selected. + + config HVC_CONSOLE bool "pSeries Hypervisor Virtual Console support" depends on PPC_PSERIES + select HVC_DRIVER help pSeries machines when partitioned support a hypervisor virtual console. This driver allows each pSeries partition to have a console diff --git a/drivers/char/Makefile b/drivers/char/Makefile index b2a11245fa95..e6c03335fd6a 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -41,7 +41,8 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o -obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o +obj-$(CONFIG_HVC_DRIVER) += hvc_console.o +obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MMTIMER) += mmtimer.o diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index a94c5b0cac52..2b6a56b2bf35 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -39,8 +39,10 @@ #include #include #include + #include -#include + +#include "hvc_console.h" #define HVC_MAJOR 229 #define HVC_MINOR 0 @@ -54,17 +56,14 @@ #define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */ /* - * The Linux TTY code does not support dynamic addition of tty derived devices - * so we need to know how many tty devices we might need when space is allocated - * for the tty device. Since this driver supports hotplug of vty adapters we - * need to make sure we have enough allocated. + * These sizes are most efficient for vio, because they are the + * native transfer size. We could make them selectable in the + * future to better deal with backends that want other buffer sizes. */ -#define HVC_ALLOC_TTY_ADAPTERS 8 - #define N_OUTBUF 16 #define N_INBUF 16 -#define __ALIGNED__ __attribute__((__aligned__(8))) +#define __ALIGNED__ __attribute__((__aligned__(sizeof(long)))) static struct tty_driver *hvc_driver; static struct task_struct *hvc_task; @@ -154,7 +153,7 @@ static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] = void hvc_console_print(struct console *co, const char *b, unsigned count) { - char c[16] __ALIGNED__; + char c[N_OUTBUF] __ALIGNED__; unsigned i = 0, n = 0; int r, donecr = 0, index = co->index; @@ -473,8 +472,10 @@ static void hvc_push(struct hvc_struct *hp) n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf); if (n <= 0) { - if (n == 0) + if (n == 0) { + hp->do_wakeup = 1; return; + } /* throw away output on error; this happens when there is no session connected to the vterm. */ hp->n_outbuf = 0; @@ -486,12 +487,19 @@ static void hvc_push(struct hvc_struct *hp) hp->do_wakeup = 1; } -static inline int __hvc_write_kernel(struct hvc_struct *hp, - const unsigned char *buf, int count) +static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count) { + struct hvc_struct *hp = tty->driver_data; unsigned long flags; int rsize, written = 0; + /* This write was probably executed during a tty close. */ + if (!hp) + return -EPIPE; + + if (hp->count <= 0) + return -EIO; + spin_lock_irqsave(&hp->lock, flags); /* Push pending writes */ @@ -510,26 +518,8 @@ static inline int __hvc_write_kernel(struct hvc_struct *hp, } spin_unlock_irqrestore(&hp->lock, flags); - return written; -} -static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count) -{ - struct hvc_struct *hp = tty->driver_data; - int written; - - /* This write was probably executed during a tty close. */ - if (!hp) - return -EPIPE; - - if (hp->count <= 0) - return -EIO; - - written = __hvc_write_kernel(hp, buf, count); - /* * Racy, but harmless, kick thread if there is still pending data. - * There really is nothing wrong with kicking the thread, even if there - * is no buffered data. */ if (hp->n_outbuf) hvc_kick(); @@ -614,6 +604,13 @@ static int hvc_poll(struct hvc_struct *hp) spin_unlock_irqrestore(&hp->lock, flags); tty_hangup(tty); spin_lock_irqsave(&hp->lock, flags); + } else if ( n == -EAGAIN ) { + /* + * Some back-ends can only ensure a certain min + * num of bytes read, which may be > 'count'. + * Let the tty clear the flip buff to make room. + */ + poll_mask |= HVC_POLL_READ; } break; } @@ -635,16 +632,7 @@ static int hvc_poll(struct hvc_struct *hp) tty_insert_flip_char(tty, buf[i], 0); } - /* - * Account for the total amount read in one loop, and if above - * 64 bytes, we do a quick schedule loop to let the tty grok - * the data and eventually throttle us. - */ read_total += n; - if (read_total >= 64) { - poll_mask |= HVC_POLL_QUICK; - break; - } } throttled: /* Wakeup write queue if necessary */ @@ -767,7 +755,8 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, * see if this vterm id matches one registered for console. */ for (i=0; i < MAX_NR_HVC_CONSOLES; i++) - if (vtermnos[i] == hp->vtermno) + if (vtermnos[i] == hp->vtermno && + cons_ops[i] == hp->ops) break; /* no matching slot, just use a counter */ diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h new file mode 100644 index 000000000000..96b7401319c1 --- /dev/null +++ b/drivers/char/hvc_console.h @@ -0,0 +1,63 @@ +/* + * hvc_console.h + * Copyright (C) 2005 IBM Corporation + * + * Author(s): + * Ryan S. Arnold + * + * hvc_console header information: + * moved here from include/asm-powerpc/hvconsole.h + * and drivers/char/hvc_console.c + * + * 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 HVC_CONSOLE_H +#define HVC_CONSOLE_H + +/* + * This is the max number of console adapters that can/will be found as + * console devices on first stage console init. Any number beyond this range + * can't be used as a console device but is still a valid tty device. + */ +#define MAX_NR_HVC_CONSOLES 16 + +/* + * The Linux TTY code does not support dynamic addition of tty derived devices + * so we need to know how many tty devices we might need when space is allocated + * for the tty device. Since this driver supports hotplug of vty adapters we + * need to make sure we have enough allocated. + */ +#define HVC_ALLOC_TTY_ADAPTERS 8 + + +/* implemented by a low level driver */ +struct hv_ops { + int (*get_chars)(uint32_t vtermno, char *buf, int count); + int (*put_chars)(uint32_t vtermno, const char *buf, int count); +}; + +struct hvc_struct; + +/* Register a vterm and a slot index for use as a console (console_init) */ +extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); + +/* register a vterm for hvc tty operation (module_init or hotplug add) */ +extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq, + struct hv_ops *ops); +/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ +extern int __devexit hvc_remove(struct hvc_struct *hp); + +#endif // HVC_CONSOLE_H diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index f5212eb2b41d..9add81ceb440 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c @@ -31,10 +31,13 @@ #include #include + #include #include #include +#include "hvc_console.h" + char hvc_driver_name[] = "hvc_console"; static struct vio_device_id hvc_driver_table[] __devinitdata = { @@ -48,6 +51,14 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count) unsigned long got; int i; + /* + * Vio firmware will read up to SIZE_VIO_GET_CHARS at its own discretion + * so we play safe and avoid the situation where got > count which could + * overload the flip buffer. + */ + if (count < SIZE_VIO_GET_CHARS) + return -EAGAIN; + got = hvc_get_chars(vtermno, buf, count); /* diff --git a/include/asm-powerpc/hvconsole.h b/include/asm-powerpc/hvconsole.h index 34daf7b9b62f..35ea69e8121f 100644 --- a/include/asm-powerpc/hvconsole.h +++ b/include/asm-powerpc/hvconsole.h @@ -24,28 +24,18 @@ #ifdef __KERNEL__ /* - * This is the max number of console adapters that can/will be found as - * console devices on first stage console init. Any number beyond this range - * can't be used as a console device but is still a valid tty device. + * PSeries firmware will only send/recv up to 16 bytes of character data per + * hcall. */ -#define MAX_NR_HVC_CONSOLES 16 +#define MAX_VIO_PUT_CHARS 16 +#define SIZE_VIO_GET_CHARS 16 -/* implemented by a low level driver */ -struct hv_ops { - int (*get_chars)(uint32_t vtermno, char *buf, int count); - int (*put_chars)(uint32_t vtermno, const char *buf, int count); -}; +/* + * Vio firmware always attempts to fetch MAX_VIO_GET_CHARS chars. The 'count' + * parm is included to conform to put_chars() function pointer template + */ extern int hvc_get_chars(uint32_t vtermno, char *buf, int count); extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count); -struct hvc_struct; - -/* Register a vterm and a slot index for use as a console (console_init) */ -extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); -/* register a vterm for hvc tty operation (module_init or hotplug add) */ -extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq, - struct hv_ops *ops); -/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ -extern int __devexit hvc_remove(struct hvc_struct *hp); #endif /* __KERNEL__ */ #endif /* _PPC64_HVCONSOLE_H */ -- cgit v1.2.3-59-g8ed1b From f4d1749e9570d3984800c371c6e06eb35b9718b1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Mar 2006 21:26:03 +0200 Subject: [PATCH] powerpc: add hvc backend for rtas Current Cell hardware is using the console through a set of rtas calls. This driver is needed to get console output on those boards. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- drivers/char/Kconfig | 7 +++ drivers/char/Makefile | 1 + drivers/char/hvc_rtas.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 drivers/char/hvc_rtas.c (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 831419381cf5..7a85b3a26ff8 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -579,6 +579,13 @@ config HVC_CONSOLE console. This driver allows each pSeries partition to have a console which is accessed via the HMC. +config HVC_RTAS + bool "IBM RTAS Console support" + depends on PPC_RTAS + select HVC_DRIVER + help + IBM Console device driver which makes use of RTAS + config HVCS tristate "IBM Hypervisor Virtual Console Server support" depends on PPC_PSERIES diff --git a/drivers/char/Makefile b/drivers/char/Makefile index e6c03335fd6a..a73cb4956928 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o obj-$(CONFIG_HVC_DRIVER) += hvc_console.o obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o +obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MMTIMER) += mmtimer.o diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c new file mode 100644 index 000000000000..83364ea63cba --- /dev/null +++ b/drivers/char/hvc_rtas.c @@ -0,0 +1,138 @@ +/* + * IBM RTAS driver interface to hvc_console.c + * + * (C) Copyright IBM Corporation 2001-2005 + * (C) Copyright Red Hat, Inc. 2005 + * + * Author(s): Maximino Augilar + * : Ryan S. Arnold + * : Utz Bacher + * : David Woodhouse + * + * inspired by drivers/char/hvc_console.c + * written by Anton Blanchard and Paul Mackerras + * + * 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 "hvc_console.h" + +#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) +{ + int done; + + /* 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) + break; + } + /* the calling routine expects to receive the number of bytes sent */ + return done; +} + +static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count) +{ + int i; + + for (i = 0; i < count; i++) { + int c, err; + + err = rtas_call(rtascons_get_char_token, 0, 2, &c); + if (err) + break; + + buf[i] = c; + } + + return i; +} + +static struct hv_ops hvc_rtas_get_put_ops = { + .get_chars = hvc_rtas_read_console, + .put_chars = hvc_rtas_write_console, +}; + +static int hvc_rtas_init(void) +{ + struct hvc_struct *hp; + + if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) + rtascons_put_char_token = rtas_token("put-term-char"); + if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) + return -EIO; + + if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) + rtascons_get_char_token = rtas_token("get-term-char"); + if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) + return -EIO; + + BUG_ON(hvc_rtas_dev); + + /* Allocate an hvc_struct for the console device we instantiated + * earlier. Save off hp so that we can return it on exit */ + 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); + +/* 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 */ + if (hvc_rtas_dev) + hvc_remove(hvc_rtas_dev); +} +module_exit(hvc_rtas_exit); + +/* This will happen prior to module init. There is no tty at this time? */ +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 ); + add_preferred_console("hvc", 0, NULL); + return 0; +} +console_initcall(hvc_rtas_console_init); -- cgit v1.2.3-59-g8ed1b From e8222502ee6157e2713da9e0792c21f4ad458d50 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 28 Mar 2006 23:15:54 +1100 Subject: [PATCH] powerpc: Kill _machine and hard-coded platform numbers This removes statically assigned platform numbers and reworks the powerpc platform probe code to use a better mechanism. With this, board support files can simply declare a new machine type with a macro, and implement a probe() function that uses the flattened device-tree to detect if they apply for a given machine. We now have a machine_is() macro that replaces the comparisons of _machine with the various PLATFORM_* constants. This commit also changes various drivers to use the new macro instead of looking at _machine. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- Documentation/powerpc/booting-without-of.txt | 5 + arch/powerpc/kernel/asm-offsets.c | 2 - arch/powerpc/kernel/nvram_64.c | 4 +- arch/powerpc/kernel/pci_32.c | 4 +- arch/powerpc/kernel/proc_ppc64.c | 3 +- arch/powerpc/kernel/prom.c | 56 ++-- arch/powerpc/kernel/prom_init.c | 51 ++-- arch/powerpc/kernel/rtas-proc.c | 2 +- arch/powerpc/kernel/rtas.c | 3 +- arch/powerpc/kernel/setup-common.c | 52 +++- arch/powerpc/kernel/setup_32.c | 58 +--- arch/powerpc/kernel/setup_64.c | 56 +--- arch/powerpc/kernel/traps.c | 35 +-- arch/powerpc/kernel/vdso.c | 9 +- arch/powerpc/kernel/vmlinux.lds.S | 381 +++++++++++++-------------- arch/powerpc/mm/hash_utils_64.c | 7 +- arch/powerpc/platforms/cell/setup.c | 11 +- arch/powerpc/platforms/chrp/setup.c | 13 +- arch/powerpc/platforms/iseries/setup.c | 9 +- arch/powerpc/platforms/maple/setup.c | 8 +- arch/powerpc/platforms/powermac/bootx_init.c | 4 +- arch/powerpc/platforms/powermac/feature.c | 2 +- arch/powerpc/platforms/powermac/low_i2c.c | 3 + arch/powerpc/platforms/powermac/nvram.c | 2 +- arch/powerpc/platforms/powermac/pci.c | 5 +- arch/powerpc/platforms/powermac/pfunc_base.c | 2 + arch/powerpc/platforms/powermac/setup.c | 72 ++--- arch/powerpc/platforms/powermac/time.c | 4 +- arch/powerpc/platforms/pseries/eeh.c | 2 +- arch/powerpc/platforms/pseries/pci.c | 2 +- arch/powerpc/platforms/pseries/pci_dlpar.c | 1 + arch/powerpc/platforms/pseries/reconfig.c | 5 +- arch/powerpc/platforms/pseries/rtasd.c | 3 +- arch/powerpc/platforms/pseries/setup.c | 39 ++- arch/ppc/platforms/prep_setup.c | 12 +- drivers/char/generic_nvram.c | 5 +- drivers/ide/pci/via82cxxx.c | 2 +- drivers/ide/ppc/pmac.c | 2 +- drivers/ieee1394/ohci1394.c | 4 +- drivers/macintosh/adb.c | 3 +- drivers/macintosh/adbhid.c | 4 +- drivers/macintosh/mediabay.c | 4 +- drivers/media/video/planb.c | 2 +- drivers/net/tulip/de4x5.c | 2 +- drivers/scsi/mesh.c | 2 +- drivers/usb/core/hcd-pci.c | 4 +- drivers/video/aty/aty128fb.c | 7 +- drivers/video/aty/atyfb_base.c | 7 +- drivers/video/aty/radeon_pm.c | 4 +- drivers/video/cirrusfb.c | 4 +- drivers/video/matrox/matroxfb_base.c | 3 +- drivers/video/nvidia/nvidia.c | 5 +- drivers/video/radeonfb.c | 2 +- drivers/video/riva/fbdev.c | 9 +- fs/partitions/mac.c | 3 +- include/asm-powerpc/machdep.h | 26 +- include/asm-powerpc/pmac_feature.h | 2 +- include/asm-powerpc/processor.h | 37 +-- include/asm-powerpc/prom.h | 14 +- include/asm-powerpc/vdso_datapage.h | 3 + include/asm-ppc/machdep.h | 12 + sound/oss/dmasound/dmasound_awacs.c | 2 +- sound/ppc/pmac.c | 2 +- 63 files changed, 560 insertions(+), 543 deletions(-) (limited to 'drivers') diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index ee551c6ea235..217e51768b87 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -719,6 +719,11 @@ address which can extend beyond that limit. - model : this is your board name/model - #address-cells : address representation for "root" devices - #size-cells: the size representation for "root" devices + - device_type : This property shouldn't be necessary. However, if + you decide to create a device_type for your root node, make sure it + is _not_ "chrp" unless your platform is a pSeries or PAPR compliant + one for 64-bit, or a CHRP-type machine for 32-bit as this will + matched by the kernel this way. Additionally, some recommended properties are: diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 882889b15926..54b48f330051 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -105,8 +105,6 @@ int main(void) DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); - DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); - /* paca */ DEFINE(PACA_SIZE, sizeof(struct paca_struct)); DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index)); diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 6c3989f6247d..ada50aa5b600 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -160,7 +160,7 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, case IOC_NVRAM_GET_OFFSET: { int part, offset; - if (_machine != PLATFORM_POWERMAC) + if (!machine_is(powermac)) return -EINVAL; if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) return -EFAULT; @@ -444,7 +444,7 @@ static int nvram_setup_partition(void) * in our nvram, as Apple defined partitions use pretty much * all of the space */ - if (_machine == PLATFORM_POWERMAC) + if (machine_is(powermac)) return -ENOSPC; /* see if we have an OS partition that meets our needs. diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 704c846b2b0f..b129d2e4b759 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -787,7 +787,7 @@ pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) * fix has to be done by making the remapping per-host and always * filling the pci_to_OF map. --BenH */ - if (_machine == _MACH_Pmac && busnr >= 0xf0) + if (machine_is(powermac) && busnr >= 0xf0) busnr -= 0xf0; else #endif @@ -1728,7 +1728,7 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) * (bus 0 is HT root), we return the AGP one instead. */ #ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4")) + if (machine_is(powermac) && machine_is_compatible("MacRISC4")) if (bus == 0) bus = 0xf0; #endif /* CONFIG_PPC_PMAC */ diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index 7ba42a405f41..3c2cf661f6d9 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -51,7 +52,7 @@ static int __init proc_ppc64_create(void) if (!root) return 1; - if (!(platform_is_pseries() || _machine == PLATFORM_CELL)) + if (!machine_is(pseries) && !machine_is(cell)) return 0; if (!proc_mkdir("rtas", root)) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index a2bc433f3610..4336390bcf34 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -383,14 +383,14 @@ static int __devinit finish_node_interrupts(struct device_node *np, /* Apple uses bits in there in a different way, let's * only keep the real sense bit on macs */ - if (_machine == PLATFORM_POWERMAC) + if (machine_is(powermac)) sense &= 0x1; np->intrs[intrcount].sense = map_mpic_senses[sense]; } #ifdef CONFIG_PPC64 /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ - if (_machine == PLATFORM_POWERMAC && ic && ic->parent) { + if (machine_is(powermac) && ic && ic->parent) { char *name = get_property(ic->parent, "name", NULL); if (name && !strcmp(name, "u3")) np->intrs[intrcount].line += 128; @@ -570,6 +570,18 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, return rc; } +unsigned long __init of_get_flat_dt_root(void) +{ + unsigned long p = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + + while(*((u32 *)p) == OF_DT_NOP) + p += 4; + BUG_ON (*((u32 *)p) != OF_DT_BEGIN_NODE); + p += 4; + return _ALIGN(p + strlen((char *)p) + 1, 4); +} + /** * This function can be used within scan_flattened_dt callback to get * access to properties @@ -612,6 +624,25 @@ void* __init of_get_flat_dt_prop(unsigned long node, const char *name, } while(1); } +int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) +{ + const char* cp; + unsigned long cplen, l; + + cp = of_get_flat_dt_prop(node, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + if (strncasecmp(cp, compat, strlen(compat)) == 0) + return 1; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} + static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, unsigned long align) { @@ -686,7 +717,7 @@ static unsigned long __init unflatten_dt_node(unsigned long mem, #ifdef DEBUG if ((strlen(p) + l + 1) != allocl) { DBG("%s: p: %d, l: %d, a: %d\n", - pathp, strlen(p), l, allocl); + pathp, (int)strlen(p), l, allocl); } #endif p += strlen(p); @@ -951,7 +982,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, static int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data) { - u32 *prop; unsigned long *lprop; unsigned long l; char *p; @@ -962,14 +992,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) return 0; - /* get platform type */ - prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); - if (prop == NULL) - return 0; -#ifdef CONFIG_PPC_MULTIPLATFORM - _machine = *prop; -#endif - #ifdef CONFIG_PPC64 /* check if iommu is forced on or off */ if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) @@ -996,15 +1018,15 @@ static int __init early_init_dt_scan_chosen(unsigned long node, * set of RTAS infos now if available */ { - u64 *basep, *entryp; + u64 *basep, *entryp, *sizep; basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL); entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); - prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL); - if (basep && entryp && prop) { + sizep = of_get_flat_dt_prop(node, "linux,rtas-size", NULL); + if (basep && entryp && sizep) { rtas.base = *basep; rtas.entry = *entryp; - rtas.size = *prop; + rtas.size = *sizep; } } #endif /* CONFIG_PPC_RTAS */ @@ -1775,7 +1797,7 @@ static int of_finish_dynamic_node(struct device_node *node) /* We don't support that function on PowerMac, at least * not yet */ - if (_machine == PLATFORM_POWERMAC) + if (machine_is(powermac)) return -ENODEV; /* fix up new node's linux_phandle field */ diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 0d0887844501..d66c5e77fcff 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -180,6 +180,16 @@ static unsigned long __initdata prom_tce_alloc_start; static unsigned long __initdata prom_tce_alloc_end; #endif +/* Platforms codes are now obsolete in the kernel. Now only used within this + * file and ultimately gone too. Feel free to change them if you need, they + * are not shared with anything outside of this file anymore + */ +#define PLATFORM_PSERIES 0x0100 +#define PLATFORM_PSERIES_LPAR 0x0101 +#define PLATFORM_LPAR 0x0001 +#define PLATFORM_POWERMAC 0x0400 +#define PLATFORM_GENERIC 0x0500 + static int __initdata of_platform; static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; @@ -1492,7 +1502,10 @@ static int __init prom_find_machine_type(void) int len, i = 0; #ifdef CONFIG_PPC64 phandle rtas; + int x; #endif + + /* Look for a PowerMac */ len = prom_getprop(_prom->root, "compatible", compat, sizeof(compat)-1); if (len > 0) { @@ -1505,28 +1518,36 @@ static int __init prom_find_machine_type(void) if (strstr(p, RELOC("Power Macintosh")) || strstr(p, RELOC("MacRISC"))) return PLATFORM_POWERMAC; -#ifdef CONFIG_PPC64 - if (strstr(p, RELOC("Momentum,Maple"))) - return PLATFORM_MAPLE; - if (strstr(p, RELOC("IBM,CPB"))) - return PLATFORM_CELL; -#endif i += sl + 1; } } #ifdef CONFIG_PPC64 + /* If not a mac, try to figure out if it's an IBM pSeries or any other + * PAPR compliant platform. We assume it is if : + * - /device_type is "chrp" (please, do NOT use that for future + * non-IBM designs ! + * - it has /rtas + */ + len = prom_getprop(_prom->root, "model", + compat, sizeof(compat)-1); + if (len <= 0) + return PLATFORM_GENERIC; + compat[len] = 0; + if (strcmp(compat, "chrp")) + return PLATFORM_GENERIC; + /* Default to pSeries. We need to know if we are running LPAR */ rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); - if (PHANDLE_VALID(rtas)) { - int x = prom_getproplen(rtas, "ibm,hypertas-functions"); - if (x != PROM_ERROR) { - prom_printf("Hypertas detected, assuming LPAR !\n"); - return PLATFORM_PSERIES_LPAR; - } + if (!PHANDLE_VALID(rtas)) + return PLATFORM_GENERIC; + x = prom_getproplen(rtas, "ibm,hypertas-functions"); + if (x != PROM_ERROR) { + prom_printf("Hypertas detected, assuming LPAR !\n"); + return PLATFORM_PSERIES_LPAR; } return PLATFORM_PSERIES; #else - return PLATFORM_CHRP; + return PLATFORM_GENERIC; #endif } @@ -2034,7 +2055,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, { struct prom_t *_prom; unsigned long hdr; - u32 getprop_rval; unsigned long offset = reloc_offset(); #ifdef CONFIG_PPC32 @@ -2070,9 +2090,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, * between pSeries SMP and pSeries LPAR */ RELOC(of_platform) = prom_find_machine_type(); - getprop_rval = RELOC(of_platform); - prom_setprop(_prom->chosen, "/chosen", "linux,platform", - &getprop_rval, sizeof(getprop_rval)); /* Bail if this is a kdump kernel. */ if (PHYSICAL_START > 0) diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 1f03fb28cc0a..456286cf1d14 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c @@ -257,7 +257,7 @@ static int __init proc_rtas_init(void) { struct proc_dir_entry *entry; - if (_machine != PLATFORM_PSERIES && _machine != PLATFORM_PSERIES_LPAR) + if (!machine_is(pseries)) return 1; rtas_node = of_find_node_by_name(NULL, "rtas"); diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 142d818a31a6..4b78ee0e5867 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -768,7 +769,7 @@ void __init rtas_initialize(void) * the stop-self token if any */ #ifdef CONFIG_PPC64 - if (_machine == PLATFORM_PSERIES_LPAR) { + if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) { rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); ibm_suspend_me_token = rtas_token("ibm,suspend-me"); } diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index b17630ad4ac7..3473cb9cb0ab 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -9,6 +9,9 @@ * 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 @@ -41,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -56,8 +60,6 @@ #include "setup.h" -#undef DEBUG - #ifdef DEBUG #include #define DBG(fmt...) udbg_printf(fmt) @@ -65,10 +67,12 @@ #define DBG(fmt...) #endif -#ifdef CONFIG_PPC_MULTIPLATFORM -int _machine = 0; -EXPORT_SYMBOL(_machine); -#endif +/* The main machine-dep calls structure + */ +struct machdep_calls ppc_md; +EXPORT_SYMBOL(ppc_md); +struct machdep_calls *machine_id; +EXPORT_SYMBOL(machine_id); unsigned long klimit = (unsigned long) _end; @@ -168,7 +172,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) bogosum/(500000/HZ), bogosum/(5000/HZ) % 100); #endif /* CONFIG_SMP && CONFIG_PPC32 */ seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq); - + if (ppc_md.name) + seq_printf(m, "platform\t: %s\n", ppc_md.name); if (ppc_md.show_cpuinfo != NULL) ppc_md.show_cpuinfo(m); @@ -387,7 +392,7 @@ void __init smp_setup_cpu_maps(void) * On pSeries LPAR, we need to know how many cpus * could possibly be added to this partition. */ - if (_machine == PLATFORM_PSERIES_LPAR && + if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR) && (dn = of_find_node_by_path("/rtas"))) { int num_addr_cell, num_size_cell, maxcpus; unsigned int *ireg; @@ -456,3 +461,34 @@ static int __init early_xmon(char *p) } early_param("xmon", early_xmon); #endif + +void probe_machine(void) +{ + extern struct machdep_calls __machine_desc_start; + extern struct machdep_calls __machine_desc_end; + + /* + * Iterate all ppc_md structures until we find the proper + * one for the current machine type + */ + DBG("Probing machine type ...\n"); + + for (machine_id = &__machine_desc_start; + machine_id < &__machine_desc_end; + machine_id++) { + DBG(" %s ...", machine_id->name); + memcpy(&ppc_md, machine_id, sizeof(struct machdep_calls)); + if (ppc_md.probe()) { + DBG(" match !\n"); + break; + } + DBG("\n"); + } + /* What can we do if we didn't find ? */ + if (machine_id >= &__machine_desc_end) { + DBG("No suitable machine found !\n"); + for (;;); + } + + printk(KERN_INFO "Using %s machine description\n", ppc_md.name); +} diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index a2c89435abec..ae9c33d70731 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -67,10 +67,6 @@ unsigned int DMA_MODE_WRITE; int have_of = 1; #ifdef CONFIG_PPC_MULTIPLATFORM -extern void prep_init(void); -extern void pmac_init(void); -extern void chrp_init(void); - dev_t boot_dev; #endif /* CONFIG_PPC_MULTIPLATFORM */ @@ -82,9 +78,6 @@ unsigned long SYSRQ_KEY = 0x54; unsigned long vgacon_remap_base; #endif -struct machdep_calls ppc_md; -EXPORT_SYMBOL(ppc_md); - /* * These are used in binfmt_elf.c to put aux entries on the stack * for each elf executable being started. @@ -120,48 +113,6 @@ unsigned long __init early_init(unsigned long dt_ptr) return KERNELBASE + offset; } -#ifdef CONFIG_PPC_MULTIPLATFORM -/* - * The PPC_MULTIPLATFORM version of platform_init... - */ -void __init platform_init(void) -{ - /* if we didn't get any bootinfo telling us what we are... */ - if (_machine == 0) { - /* prep boot loader tells us if we're prep or not */ - if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) - _machine = _MACH_prep; - } - -#ifdef CONFIG_PPC_PREP - /* not much more to do here, if prep */ - if (_machine == _MACH_prep) { - prep_init(); - return; - } -#endif - -#ifdef CONFIG_ADB - if (strstr(cmd_line, "adb_sync")) { - extern int __adb_probe_sync; - __adb_probe_sync = 1; - } -#endif /* CONFIG_ADB */ - - switch (_machine) { -#ifdef CONFIG_PPC_PMAC - case _MACH_Pmac: - pmac_init(); - break; -#endif -#ifdef CONFIG_PPC_CHRP - case _MACH_chrp: - chrp_init(); - break; -#endif - } -} -#endif /* * Find out what kind of machine we're on and save any data we need @@ -187,8 +138,12 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys) strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); #endif /* CONFIG_CMDLINE */ - /* Base init based on machine type */ +#ifdef CONFIG_PPC_MULTIPLATFORM + probe_machine(); +#else + /* Base init based on machine type. Obsoloete, please kill ! */ platform_init(); +#endif #ifdef CONFIG_6xx if (cpu_has_feature(CPU_FTR_CAN_DOZE) || @@ -359,7 +314,4 @@ void __init setup_arch(char **cmdline_p) if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); paging_init(); - - /* this is for modules since _machine can be a define -- Cort */ - ppc_md.ppc_machine = _machine; } diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 5b63a861ef43..6aea1fb74b69 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -95,11 +95,6 @@ int dcache_bsize; int icache_bsize; int ucache_bsize; -/* The main machine-dep calls structure - */ -struct machdep_calls ppc_md; -EXPORT_SYMBOL(ppc_md); - #ifdef CONFIG_MAGIC_SYSRQ unsigned long SYSRQ_KEY; #endif /* CONFIG_MAGIC_SYSRQ */ @@ -160,32 +155,6 @@ early_param("smt-enabled", early_smt_enabled); #define check_smt_enabled() #endif /* CONFIG_SMP */ -extern struct machdep_calls pSeries_md; -extern struct machdep_calls pmac_md; -extern struct machdep_calls maple_md; -extern struct machdep_calls cell_md; -extern struct machdep_calls iseries_md; - -/* Ultimately, stuff them in an elf section like initcalls... */ -static struct machdep_calls __initdata *machines[] = { -#ifdef CONFIG_PPC_PSERIES - &pSeries_md, -#endif /* CONFIG_PPC_PSERIES */ -#ifdef CONFIG_PPC_PMAC - &pmac_md, -#endif /* CONFIG_PPC_PMAC */ -#ifdef CONFIG_PPC_MAPLE - &maple_md, -#endif /* CONFIG_PPC_MAPLE */ -#ifdef CONFIG_PPC_CELL - &cell_md, -#endif -#ifdef CONFIG_PPC_ISERIES - &iseries_md, -#endif - NULL -}; - /* * Early initialization entry point. This is called by head.S * with MMU translation disabled. We rely on the "feature" of @@ -207,12 +176,10 @@ static struct machdep_calls __initdata *machines[] = { void __init early_setup(unsigned long dt_ptr) { - static struct machdep_calls **mach; - /* Enable early debugging if any specified (see udbg.h) */ udbg_early_init(); - DBG(" -> early_setup()\n"); + DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr); /* * Do early initializations using the flattened device @@ -229,22 +196,8 @@ void __init early_setup(unsigned long dt_ptr) get_paca()->stab_real = __pa((u64)&initial_stab); get_paca()->stab_addr = (u64)&initial_stab; - /* - * Iterate all ppc_md structures until we find the proper - * one for the current machine type - */ - DBG("Probing machine type for platform %x...\n", _machine); - - for (mach = machines; *mach; mach++) { - if ((*mach)->probe(_machine)) - break; - } - /* What can we do if we didn't find ? */ - if (*mach == NULL) { - DBG("No suitable machine found !\n"); - for (;;); - } - ppc_md = **mach; + /* Probe the machine type */ + probe_machine(); #ifdef CONFIG_CRASH_DUMP kdump_setup(); @@ -346,7 +299,7 @@ static void __init initialize_cache_info(void) const char *dc, *ic; /* Then read cache informations */ - if (_machine == PLATFORM_POWERMAC) { + if (machine_is(powermac)) { dc = "d-cache-block-size"; ic = "i-cache-block-size"; } else { @@ -490,7 +443,6 @@ void __init setup_system(void) printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller); - printk("platform = 0x%x\n", _machine); printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size()); printk("ppc64_caches.dcache_line_size = 0x%x\n", ppc64_caches.dline_size); diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 98660aedeeb7..27600c9432bc 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -97,7 +97,6 @@ static DEFINE_SPINLOCK(die_lock); int die(const char *str, struct pt_regs *regs, long err) { static int die_counter, crash_dump_start = 0; - int nl = 0; if (debugger(regs)) return 1; @@ -106,7 +105,7 @@ int die(const char *str, struct pt_regs *regs, long err) spin_lock_irq(&die_lock); bust_spinlocks(1); #ifdef CONFIG_PMAC_BACKLIGHT - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { set_backlight_enable(1); set_backlight_level(BACKLIGHT_MAX); } @@ -114,46 +113,18 @@ int die(const char *str, struct pt_regs *regs, long err) printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); #ifdef CONFIG_PREEMPT printk("PREEMPT "); - nl = 1; #endif #ifdef CONFIG_SMP printk("SMP NR_CPUS=%d ", NR_CPUS); - nl = 1; #endif #ifdef CONFIG_DEBUG_PAGEALLOC printk("DEBUG_PAGEALLOC "); - nl = 1; #endif #ifdef CONFIG_NUMA printk("NUMA "); - nl = 1; #endif -#ifdef CONFIG_PPC64 - switch (_machine) { - case PLATFORM_PSERIES: - printk("PSERIES "); - nl = 1; - break; - case PLATFORM_PSERIES_LPAR: - printk("PSERIES LPAR "); - nl = 1; - break; - case PLATFORM_ISERIES_LPAR: - printk("ISERIES LPAR "); - nl = 1; - break; - case PLATFORM_POWERMAC: - printk("POWERMAC "); - nl = 1; - break; - case PLATFORM_CELL: - printk("CELL "); - nl = 1; - break; - } -#endif - if (nl) - printk("\n"); + printk("%s\n", ppc_md.name ? "" : ppc_md.name); + print_modules(); show_regs(regs); bust_spinlocks(0); diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index ec8370368423..573afb68d69e 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -667,7 +668,13 @@ void __init vdso_init(void) vdso_data->version.major = SYSTEMCFG_MAJOR; vdso_data->version.minor = SYSTEMCFG_MINOR; vdso_data->processor = mfspr(SPRN_PVR); - vdso_data->platform = _machine; + /* + * Fake the old platform number for pSeries and iSeries and add + * in LPAR bit if necessary + */ + vdso_data->platform = machine_is(iseries) ? 0x200 : 0x100; + if (firmware_has_feature(FW_FEATURE_LPAR)) + vdso_data->platform |= 1; vdso_data->physicalMemorySize = lmb_phys_mem_size(); vdso_data->dcache_size = ppc64_caches.dsize; vdso_data->dcache_line_size = ppc64_caches.dline_size; diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 7fa7b15fd8e6..fe79c2584cb0 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -1,9 +1,11 @@ #include #ifdef CONFIG_PPC64 #include +#define PROVIDE32(x) PROVIDE(__unused__##x) #else #define PAGE_SIZE 4096 #define KERNELBASE CONFIG_KERNEL_START +#define PROVIDE32(x) PROVIDE(x) #endif #include @@ -18,43 +20,42 @@ jiffies = jiffies_64 + 4; #endif SECTIONS { - /* Sections to be discarded. */ - /DISCARD/ : { - *(.exitcall.exit) - *(.exit.data) - } - - . = KERNELBASE; - - /* Read-only sections, merged into text segment: */ - .text : { - *(.text .text.*) - SCHED_TEXT - LOCK_TEXT - KPROBES_TEXT - *(.fixup) -#ifdef CONFIG_PPC32 - *(.got1) - __got2_start = .; - *(.got2) - __got2_end = .; -#else - . = ALIGN(PAGE_SIZE); - _etext = .; -#endif - } -#ifdef CONFIG_PPC32 - _etext = .; - PROVIDE (etext = .); + /* Sections to be discarded. */ + /DISCARD/ : { + *(.exitcall.exit) + *(.exit.data) + } - RODATA - .fini : { *(.fini) } =0 - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } + . = KERNELBASE; - .fixup : { *(.fixup) } -#endif +/* + * Text, read only data and other permanent read-only sections + */ + + /* Text and gots */ + .text : { + *(.text .text.*) + SCHED_TEXT + LOCK_TEXT + KPROBES_TEXT + *(.fixup) +#ifdef CONFIG_PPC32 + *(.got1) + __got2_start = .; + *(.got2) + __got2_end = .; +#endif /* CONFIG_PPC32 */ + + . = ALIGN(PAGE_SIZE); + _etext = .; + PROVIDE32 (etext = .); + } + + /* Read-only data */ + RODATA + + /* Exception & bug tables */ __ex_table : { __start___ex_table = .; *(__ex_table) @@ -67,192 +68,172 @@ SECTIONS __stop___bug_table = .; } -#ifdef CONFIG_PPC64 +/* + * Init sections discarded at runtime + */ + . = ALIGN(PAGE_SIZE); + __init_begin = .; + + .init.text : { + _sinittext = .; + *(.init.text) + _einittext = .; + } + + /* .exit.text is discarded at runtime, not link time, + * to deal with references from __bug_table + */ + .exit.text : { *(.exit.text) } + + .init.data : { + *(.init.data); + __vtop_table_begin = .; + *(.vtop_fixup); + __vtop_table_end = .; + __ptov_table_begin = .; + *(.ptov_fixup); + __ptov_table_end = .; + } + + . = ALIGN(16); + .init.setup : { + __setup_start = .; + *(.init.setup) + __setup_end = .; + } + + .initcall.init : { + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + } + + .con_initcall.init : { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + } + + SECURITY_INIT + + . = ALIGN(8); __ftr_fixup : { __start___ftr_fixup = .; *(__ftr_fixup) __stop___ftr_fixup = .; } - RODATA -#endif + . = ALIGN(PAGE_SIZE); + .init.ramfs : { + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; + } #ifdef CONFIG_PPC32 - /* Read-write section, merged into data segment: */ - . = ALIGN(PAGE_SIZE); - _sdata = .; - .data : - { - *(.data) - *(.data1) - *(.sdata) - *(.sdata2) - *(.got.plt) *(.got) - *(.dynamic) - CONSTRUCTORS - } - - . = ALIGN(PAGE_SIZE); - __nosave_begin = .; - .data_nosave : { *(.data.nosave) } - . = ALIGN(PAGE_SIZE); - __nosave_end = .; - - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - - _edata = .; - PROVIDE (edata = .); - - . = ALIGN(8192); - .data.init_task : { *(.data.init_task) } + . = ALIGN(32); +#else + . = ALIGN(128); #endif + .data.percpu : { + __per_cpu_start = .; + *(.data.percpu) + __per_cpu_end = .; + } - /* will be freed after init */ - . = ALIGN(PAGE_SIZE); - __init_begin = .; - .init.text : { - _sinittext = .; - *(.init.text) - _einittext = .; - } -#ifdef CONFIG_PPC32 - /* .exit.text is discarded at runtime, not link time, - to deal with references from __bug_table */ - .exit.text : { *(.exit.text) } -#endif - .init.data : { - *(.init.data); - __vtop_table_begin = .; - *(.vtop_fixup); - __vtop_table_end = .; - __ptov_table_begin = .; - *(.ptov_fixup); - __ptov_table_end = .; - } - - . = ALIGN(16); - .init.setup : { - __setup_start = .; - *(.init.setup) - __setup_end = .; - } - - .initcall.init : { - __initcall_start = .; - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) - __initcall_end = .; - } - - .con_initcall.init : { - __con_initcall_start = .; - *(.con_initcall.init) - __con_initcall_end = .; - } - - SECURITY_INIT + . = ALIGN(8); + .machine.desc : { + __machine_desc_start = . ; + *(.machine.desc) + __machine_desc_end = . ; + } + + /* freed after init ends here */ + . = ALIGN(PAGE_SIZE); + __init_end = .; + +/* + * And now the various read/write data + */ + + . = ALIGN(PAGE_SIZE); + _sdata = .; #ifdef CONFIG_PPC32 - __start___ftr_fixup = .; - __ftr_fixup : { *(__ftr_fixup) } - __stop___ftr_fixup = .; + .data : + { + *(.data) + *(.sdata) + *(.got.plt) *(.got) + } #else - . = ALIGN(PAGE_SIZE); - .init.ramfs : { - __initramfs_start = .; - *(.init.ramfs) - __initramfs_end = .; - } -#endif + .data : { + *(.data .data.rel* .toc1) + *(.branch_lt) + } -#ifdef CONFIG_PPC32 - . = ALIGN(32); + .opd : { + *(.opd) + } + + .got : { + __toc_start = .; + *(.got) + *(.toc) + } #endif - .data.percpu : { - __per_cpu_start = .; - *(.data.percpu) - __per_cpu_end = .; - } - . = ALIGN(PAGE_SIZE); -#ifdef CONFIG_PPC64 - . = ALIGN(16384); - __init_end = .; - /* freed after init ends here */ - - /* Read/write sections */ - . = ALIGN(PAGE_SIZE); - . = ALIGN(16384); - _sdata = .; - /* The initial task and kernel stack */ - .data.init_task : { - *(.data.init_task) - } - - . = ALIGN(PAGE_SIZE); - .data.page_aligned : { - *(.data.page_aligned) - } - - .data.cacheline_aligned : { - *(.data.cacheline_aligned) - } - - .data : { - *(.data .data.rel* .toc1) - *(.branch_lt) - } - - .opd : { - *(.opd) - } - - .got : { - __toc_start = .; - *(.got) - *(.toc) - . = ALIGN(PAGE_SIZE); - _edata = .; - } - - . = ALIGN(PAGE_SIZE); + . = ALIGN(PAGE_SIZE); + _edata = .; + PROVIDE32 (edata = .); + + /* The initial task and kernel stack */ +#ifdef CONFIG_PPC32 + . = ALIGN(8192); #else - __initramfs_start = .; - .init.ramfs : { - *(.init.ramfs) - } - __initramfs_end = .; + . = ALIGN(16384); +#endif + .data.init_task : { + *(.data.init_task) + } - . = ALIGN(4096); - __init_end = .; + . = ALIGN(PAGE_SIZE); + .data.page_aligned : { + *(.data.page_aligned) + } - . = ALIGN(4096); - _sextratext = .; - _eextratext = .; + .data.cacheline_aligned : { + *(.data.cacheline_aligned) + } - __bss_start = .; -#endif + . = ALIGN(PAGE_SIZE); + __data_nosave : { + __nosave_begin = .; + *(.data.nosave) + . = ALIGN(PAGE_SIZE); + __nosave_end = .; + } - .bss : { - __bss_start = .; - *(.sbss) *(.scommon) - *(.dynbss) - *(.bss) - *(COMMON) - __bss_stop = .; - } +/* + * And finally the bss + */ + + .bss : { + __bss_start = .; + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + __bss_stop = .; + } -#ifdef CONFIG_PPC64 - . = ALIGN(PAGE_SIZE); -#endif - _end = . ; -#ifdef CONFIG_PPC32 - PROVIDE (end = .); -#endif + . = ALIGN(PAGE_SIZE); + _end = . ; + PROVIDE32 (end = .); } diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 89b35c181314..c006d9039633 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -167,7 +167,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, * normal insert callback here. */ #ifdef CONFIG_PPC_ISERIES - if (_machine == PLATFORM_ISERIES_LPAR) + if (machine_is(iseries)) ret = iSeries_hpte_insert(hpteg, va, paddr, tmp_mode, @@ -176,7 +176,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, else #endif #ifdef CONFIG_PPC_PSERIES - if (_machine & PLATFORM_LPAR) + if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) ret = pSeries_lpar_hpte_insert(hpteg, va, paddr, tmp_mode, @@ -295,8 +295,7 @@ static void __init htab_init_page_sizes(void) * Not in the device-tree, let's fallback on known size * list for 16M capable GP & GR */ - if ((_machine != PLATFORM_ISERIES_LPAR) && - cpu_has_feature(CPU_FTR_16M_PAGE)) + if (cpu_has_feature(CPU_FTR_16M_PAGE) && !machine_is(iseries)) memcpy(mmu_psize_defs, mmu_psize_defaults_gp, sizeof(mmu_psize_defaults_gp)); found: diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index fec8e65b36ea..dac5d0365fde 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -195,9 +195,13 @@ static void __init cell_init_early(void) } -static int __init cell_probe(int platform) +static int __init cell_probe(void) { - if (platform != PLATFORM_CELL) + /* XXX This is temporary, the Cell maintainer will come up with + * more appropriate detection logic + */ + unsigned long root = of_get_flat_dt_root(); + if (!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0")) return 0; return 1; @@ -212,7 +216,8 @@ static int cell_check_legacy_ioport(unsigned int baseport) return -ENODEV; } -struct machdep_calls __initdata cell_md = { +define_machine(cell) { + .name = "Cell", .probe = cell_probe, .setup_arch = cell_setup_arch, .init_early = cell_init_early, diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 9c718bb2305e..23a201718704 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -292,6 +292,10 @@ void __init chrp_setup_arch(void) pci_create_OF_bus_map(); +#ifdef CONFIG_SMP + smp_ops = &chrp_smp_ops; +#endif /* CONFIG_SMP */ + /* * Print the banner, then scroll down so boot progress * can be printed. -- Cort @@ -506,8 +510,15 @@ chrp_init2(void) ppc_md.progress(" Have fun! ", 0x7777); } -void __init chrp_init(void) +static int __init chrp_probe(void) { + char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), + "device_type", NULL); + if (dtype == NULL) + return 0; + if (strcmp(dtype, "chrp")) + return 0; + ISA_DMA_THRESHOLD = ~0L; DMA_MODE_READ = 0x44; DMA_MODE_WRITE = 0x48; diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 155aa690e4bb..6ce8a404ba6b 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -675,9 +675,10 @@ static void iseries_dedicated_idle(void) void __init iSeries_init_IRQ(void) { } #endif -static int __init iseries_probe(int platform) +static int __init iseries_probe(void) { - if (PLATFORM_ISERIES_LPAR != platform) + unsigned long root = of_get_flat_dt_root(); + if (!of_flat_dt_is_compatible(root, "IBM,iSeries")) return 0; powerpc_firmware_features |= FW_FEATURE_ISERIES; @@ -686,7 +687,8 @@ static int __init iseries_probe(int platform) return 1; } -struct machdep_calls __initdata iseries_md = { +define_machine(iseries) { + .name = "iSeries", .setup_arch = iSeries_setup_arch, .show_cpuinfo = iSeries_show_cpuinfo, .init_IRQ = iSeries_init_IRQ, @@ -930,7 +932,6 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) /* /chosen */ dt_start_node(dt, "chosen"); - dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR); dt_prop_str(dt, "bootargs", cmd_line); if (cmd_mem_limit) dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit); diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 137d6063182b..24c0aef4ea39 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -259,9 +259,10 @@ static void __init maple_progress(char *s, unsigned short hex) /* * Called very early, MMU is off, device-tree isn't unflattened */ -static int __init maple_probe(int platform) +static int __init maple_probe(void) { - if (platform != PLATFORM_MAPLE) + unsigned long root = of_get_flat_dt_root(); + if (!of_flat_dt_is_compatible(root, "Momentum,Maple")) return 0; /* * On U3, the DART (iommu) must be allocated now since it @@ -274,7 +275,8 @@ static int __init maple_probe(int platform) return 1; } -struct machdep_calls __initdata maple_md = { +define_machine(maple_md) { + .name = "Maple", .probe = maple_probe, .setup_arch = maple_setup_arch, .init_early = maple_init_early, diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c index a94571be65ca..eacbfd9beabc 100644 --- a/arch/powerpc/platforms/powermac/bootx_init.c +++ b/arch/powerpc/platforms/powermac/bootx_init.c @@ -161,9 +161,7 @@ static void __init bootx_dt_add_prop(char *name, void *data, int size, static void __init bootx_add_chosen_props(unsigned long base, unsigned long *mem_end) { - u32 val = _MACH_Pmac; - - bootx_dt_add_prop("linux,platform", &val, 4, mem_end); + u32 val; if (bootx_info->kernelParamsOffset) { char *args = (char *)((unsigned long)bootx_info) + diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index e49eddd5042d..a5063cd675c5 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -2951,7 +2951,7 @@ static void *pmac_early_vresume_data; void pmac_set_early_video_resume(void (*proc)(void *data), void *data) { - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return; preempt_disable(); pmac_early_vresume_proc = proc; diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 87eb6bb7f0e7..e14f9ac55cf4 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -1457,6 +1457,9 @@ int __init pmac_i2c_init(void) return 0; i2c_inited = 1; + if (!machine_is(powermac)) + return 0; + /* Probe keywest-i2c busses */ kw_i2c_probe(); diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index 3aa3477b86f7..262f967b880a 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c @@ -597,7 +597,7 @@ int __init pmac_nvram_init(void) } #ifdef CONFIG_PPC32 - if (_machine == _MACH_chrp && nvram_naddrs == 1) { + if (machine_is(chrp) && nvram_naddrs == 1) { nvram_data = ioremap(r1.start, s1); nvram_mult = 1; ppc_md.nvram_read_val = direct_nvram_read_byte; diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index de3f30e6b333..f5d8d15d74fa 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -1201,7 +1201,7 @@ void __init pmac_pcibios_after_init(void) #ifdef CONFIG_PPC32 void pmac_pci_fixup_cardbus(struct pci_dev* dev) { - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return; /* * Fix the interrupt routing on the various cardbus bridges @@ -1244,8 +1244,9 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev) * On PowerMacs, we try to switch any PCI ATA controller to * fully native mode */ - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return; + /* Some controllers don't have the class IDE */ if (dev->vendor == PCI_VENDOR_ID_PROMISE) switch(dev->device) { diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c index 9b7150f10414..a3bd3e728fa3 100644 --- a/arch/powerpc/platforms/powermac/pfunc_base.c +++ b/arch/powerpc/platforms/powermac/pfunc_base.c @@ -336,6 +336,8 @@ int __init pmac_pfunc_base_install(void) return 0; pfbase_inited = 1; + if (!machine_is(powermac)) + return 0; DBG("Installing base platform functions...\n"); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index c2696d00672a..4d15e396655c 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -350,6 +350,13 @@ static void __init pmac_setup_arch(void) smp_ops = &psurge_smp_ops; #endif #endif /* CONFIG_SMP */ + +#ifdef CONFIG_ADB + if (strstr(cmd_line, "adb_sync")) { + extern int __adb_probe_sync; + __adb_probe_sync = 1; + } +#endif /* CONFIG_ADB */ } char *bootpath; @@ -576,30 +583,6 @@ pmac_halt(void) pmac_power_off(); } -#ifdef CONFIG_PPC32 -void __init pmac_init(void) -{ - /* isa_io_base gets set in pmac_pci_init */ - isa_mem_base = PMAC_ISA_MEM_BASE; - pci_dram_offset = PMAC_PCI_DRAM_OFFSET; - ISA_DMA_THRESHOLD = ~0L; - DMA_MODE_READ = 1; - DMA_MODE_WRITE = 2; - - ppc_md = pmac_md; - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -#ifdef CONFIG_BLK_DEV_IDE_PMAC - ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; - ppc_ide_md.default_io_base = pmac_ide_get_base; -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ -#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ - - if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); - -} -#endif - /* * Early initialization. */ @@ -646,6 +629,12 @@ static int __init pmac_declare_of_platform_devices(void) { struct device_node *np; + if (machine_is(chrp)) + return -1; + + if (!machine_is(powermac)) + return 0; + np = of_find_node_by_name(NULL, "valkyrie"); if (np) of_platform_device_create(np, "valkyrie", NULL); @@ -666,12 +655,15 @@ device_initcall(pmac_declare_of_platform_devices); /* * Called very early, MMU is off, device-tree isn't unflattened */ -static int __init pmac_probe(int platform) +static int __init pmac_probe(void) { -#ifdef CONFIG_PPC64 - if (platform != PLATFORM_POWERMAC) + unsigned long root = of_get_flat_dt_root(); + + if (!of_flat_dt_is_compatible(root, "Power Macintosh") && + !of_flat_dt_is_compatible(root, "MacRISC")) return 0; +#ifdef CONFIG_PPC64 /* * On U3, the DART (iommu) must be allocated now since it * has an impact on htab_initialize (due to the large page it @@ -681,6 +673,23 @@ static int __init pmac_probe(int platform) alloc_dart_table(); #endif +#ifdef CONFIG_PPC32 + /* isa_io_base gets set in pmac_pci_init */ + isa_mem_base = PMAC_ISA_MEM_BASE; + pci_dram_offset = PMAC_PCI_DRAM_OFFSET; + ISA_DMA_THRESHOLD = ~0L; + DMA_MODE_READ = 1; + DMA_MODE_WRITE = 2; + +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) +#ifdef CONFIG_BLK_DEV_IDE_PMAC + ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; + ppc_ide_md.default_io_base = pmac_ide_get_base; +#endif /* CONFIG_BLK_DEV_IDE_PMAC */ +#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ + +#endif /* CONFIG_PPC32 */ + #ifdef CONFIG_PMAC_SMU /* * SMU based G5s need some memory below 2Gb, at least the current @@ -709,10 +718,8 @@ static int pmac_pci_probe_mode(struct pci_bus *bus) } #endif -struct machdep_calls __initdata pmac_md = { -#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64) - .cpu_die = generic_mach_cpu_die, -#endif +define_machine(powermac) { + .name = "PowerMac", .probe = pmac_probe, .setup_arch = pmac_setup_arch, .init_early = pmac_init_early, @@ -746,4 +753,7 @@ struct machdep_calls __initdata pmac_md = { .pcibios_after_init = pmac_pcibios_after_init, .phys_mem_access_prot = pci_phys_mem_access_prot, #endif +#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64) + .cpu_die = generic_mach_cpu_die, +#endif }; diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index 5d9afa1fa02d..890758aa9667 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c @@ -336,10 +336,10 @@ static struct pmu_sleep_notifier time_sleep_notifier = { */ void __init pmac_calibrate_decr(void) { -#ifdef CONFIG_PM +#if defined(CONFIG_PM) && defined(CONFIG_ADB_PMU) /* XXX why here? */ pmu_register_sleep_notifier(&time_sleep_notifier); -#endif /* CONFIG_PM */ +#endif generic_calibrate_decr(); diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 2ab9dcdfb415..9b2b1cb117b3 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -1018,7 +1018,7 @@ static int __init eeh_init_proc(void) { struct proc_dir_entry *e; - if (platform_is_pseries()) { + if (machine_is(pseries)) { e = create_proc_entry("ppc64/eeh", 0, NULL); if (e) e->proc_fops = &proc_eeh_operations; diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 946ad59e3352..e97e67f5e079 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -120,7 +120,7 @@ static void fixup_winbond_82c105(struct pci_dev* dev) int i; unsigned int reg; - if (!platform_is_pseries()) + if (!machine_is(pseries)) return; printk("Using INTC for W82c105 IDE controller.\n"); diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index b3c2dcb1e4f0..6bfacc217085 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -28,6 +28,7 @@ #include #include #include +#include static struct pci_bus * find_bus_among_children(struct pci_bus *bus, diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 86cfa6ecdcf3..9a4b592e40bc 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -17,8 +17,9 @@ #include #include -#include +#include #include +#include @@ -508,7 +509,7 @@ static int proc_ppc64_create_ofdt(void) { struct proc_dir_entry *ent; - if (!platform_is_pseries()) + if (!machine_is(pseries)) return 0; ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index a6f628d4c9dc..fcc4d561a236 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -27,6 +27,7 @@ #include #include #include +#include #if 0 #define DEBUG(A...) printk(KERN_ERR A) @@ -481,7 +482,7 @@ static int __init rtas_init(void) { struct proc_dir_entry *entry; - if (!platform_is_pseries()) + if (!machine_is(pseries)) return 0; /* No RTAS */ diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 1b0c4c034a26..b2fbf8ba8fbb 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -372,24 +372,42 @@ static int pSeries_check_legacy_ioport(unsigned int baseport) /* * Called very early, MMU is off, device-tree isn't unflattened */ -extern struct machdep_calls pSeries_md; -static int __init pSeries_probe(int platform) +static int __init pSeries_probe_hypertas(unsigned long node, + const char *uname, int depth, + void *data) { - if (platform != PLATFORM_PSERIES && - platform != PLATFORM_PSERIES_LPAR) + if (depth != 1 || + (strcmp(uname, "rtas") != 0 && strcmp(uname, "rtas@0") != 0)) + return 0; + + if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL) + powerpc_firmware_features |= FW_FEATURE_LPAR; + + return 1; +} + +static int __init pSeries_probe(void) +{ + char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), + "device_type", NULL); + if (dtype == NULL) + return 0; + if (strcmp(dtype, "chrp")) return 0; - /* if we have some ppc_md fixups for LPAR to do, do - * it here ... - */ + DBG("pSeries detected, looking for LPAR capability...\n"); - if (platform == PLATFORM_PSERIES_LPAR) - powerpc_firmware_features |= FW_FEATURE_LPAR; + /* Now try to figure out if we are running on LPAR */ + of_scan_flat_dt(pSeries_probe_hypertas, NULL); + + DBG("Machine is%s LPAR !\n", + (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not"); return 1; } + DECLARE_PER_CPU(unsigned long, smt_snooze_delay); static void pseries_dedicated_idle_sleep(void) @@ -501,7 +519,8 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) } #endif -struct machdep_calls __initdata pSeries_md = { +define_machine(pseries) { + .name = "pSeries", .probe = pSeries_probe, .setup_arch = pSeries_setup_arch, .init_early = pSeries_init_early, diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index a0fc628ffb1e..fa46f8ce5c71 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c @@ -1067,15 +1067,13 @@ prep_map_io(void) static int __init prep_request_io(void) { - if (_machine == _MACH_prep) { #ifdef CONFIG_NVRAM - request_region(PREP_NVRAM_AS0, 0x8, "nvram"); + request_region(PREP_NVRAM_AS0, 0x8, "nvram"); #endif - request_region(0x00,0x20,"dma1"); - request_region(0x40,0x20,"timer"); - request_region(0x80,0x10,"dma page reg"); - request_region(0xc0,0x20,"dma2"); - } + request_region(0x00,0x20,"dma1"); + request_region(0x40,0x20,"timer"); + request_region(0x80,0x10,"dma page reg"); + request_region(0xc0,0x20,"dma2"); return 0; } diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c index 1b5e01e6e129..43ff59816511 100644 --- a/drivers/char/generic_nvram.c +++ b/drivers/char/generic_nvram.c @@ -22,6 +22,9 @@ #include #include #include +#ifdef CONFIG_PPC_PMAC +#include +#endif #define NVRAM_SIZE 8192 @@ -92,7 +95,7 @@ static int nvram_ioctl(struct inode *inode, struct file *file, case IOC_NVRAM_GET_OFFSET: { int part, offset; - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return -EINVAL; if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) return -EFAULT; diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index c85b87cb59d1..3e677c4f8c28 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -440,7 +440,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) #if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32) - if(_machine == _MACH_chrp && _chrp_type == _CHRP_Pegasos) { + if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) { hwif->irq = hwif->channel ? 15 : 14; } #endif diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 5013b1285e22..78e30f803671 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1677,7 +1677,7 @@ MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match); void __init pmac_ide_probe(void) { - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return; #ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index b6b96fa04d62..314f35540034 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3526,7 +3526,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) static int ohci1394_pci_resume (struct pci_dev *pdev) { #ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct device_node *of_node; /* Re-enable 1394 */ @@ -3545,7 +3545,7 @@ static int ohci1394_pci_resume (struct pci_dev *pdev) static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) { #ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct device_node *of_node; /* Disable 1394 */ diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index d2ead1776c16..781d93b0bbd5 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -42,6 +42,7 @@ #include #ifdef CONFIG_PPC #include +#include #endif @@ -294,7 +295,7 @@ int __init adb_init(void) int i; #ifdef CONFIG_PPC32 - if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) + if (!machine_is(chrp) && !machine_is(powermac)) return 0; #endif #ifdef CONFIG_MAC diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index c0b46bceb5df..0a4c680d4ac0 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -1206,8 +1206,8 @@ init_ms_a3(int id) static int __init adbhid_init(void) { #ifndef CONFIG_MAC - if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) - return 0; + if (!machine_is(chrp) && !machine_is(powermac)) + return 0; #endif led_request.complete = 1; diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index 8dbf2852bae0..53c1c7909413 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -839,8 +839,8 @@ static int __init media_bay_init(void) media_bays[i].cd_index = -1; #endif } - if (_machine != _MACH_Pmac) - return -ENODEV; + if (!machine_is(powermac)) + return 0; macio_register_driver(&media_bay_driver); diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index 522e9ddeb089..d9e3cada52f4 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -2156,7 +2156,7 @@ static int find_planb(void) struct pci_dev *pdev; int rc; - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return 0; planb_devices = find_devices("planb"); diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index ee48bfd67349..46d087c5467b 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -4160,7 +4160,7 @@ get_hw_addr(struct net_device *dev) ** If the address starts with 00 a0, we have to bit-reverse ** each byte of the address. */ - if ( (_machine & _MACH_Pmac) && + if ( machine_is(powermac) && (dev->dev_addr[0] == 0) && (dev->dev_addr[1] == 0xa0) ) { diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index d6d2125f9044..f852421002ef 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1748,7 +1748,7 @@ static int mesh_host_reset(struct scsi_cmnd *cmd) static void set_mesh_power(struct mesh_state *ms, int state) { - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return; if (state) { pmac_call_feature(PMAC_FTR_MESH_ENABLE, macio_get_of_node(ms->mdev), 0, 1); diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index e0afb5ad29e5..0d2193b69235 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -296,7 +296,7 @@ done: #ifdef CONFIG_PPC_PMAC /* Disable ASIC clocks for USB */ - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct device_node *of_node; of_node = pci_device_to_OF_node (dev); @@ -331,7 +331,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev) #ifdef CONFIG_PPC_PMAC /* Reenable ASIC clocks for USB */ - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct device_node *of_node; of_node = pci_device_to_OF_node (dev); diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 620c9a934e0e..f07be22e119d 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -67,6 +67,7 @@ #include #ifdef CONFIG_PPC_PMAC +#include #include #include #include @@ -1748,7 +1749,7 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id * var = default_var; #ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { /* Indicate sleep capability */ if (par->chip_gen == rage_M3) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1); @@ -2011,7 +2012,7 @@ static int aty128fb_blank(int blank, struct fb_info *fb) return 0; #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && blank) + if (machine_is(powermac) && blank) set_backlight_enable(0); #endif /* CONFIG_PMAC_BACKLIGHT */ @@ -2029,7 +2030,7 @@ static int aty128fb_blank(int blank, struct fb_info *fb) aty128_set_lcd_enable(par, par->lcd_on && !blank); } #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && !blank) + if (machine_is(powermac) && !blank) set_backlight_enable(1); #endif /* CONFIG_PMAC_BACKLIGHT */ return 0; diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 485be386a8ff..1b1f24e2bfbe 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -75,6 +75,7 @@ #include "ati_ids.h" #ifdef __powerpc__ +#include #include #include "../macmodes.h" #endif @@ -2516,7 +2517,7 @@ static int __init aty_init(struct fb_info *info, const char *name) memset(&var, 0, sizeof(var)); #ifdef CONFIG_PPC - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { /* * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it * applies to all Mac video cards @@ -2671,7 +2672,7 @@ static int atyfb_blank(int blank, struct fb_info *info) return 0; #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && blank > FB_BLANK_NORMAL) + if (machine_is(powermac) && blank > FB_BLANK_NORMAL) set_backlight_enable(0); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) if (par->lcd_table && blank > FB_BLANK_NORMAL && @@ -2703,7 +2704,7 @@ static int atyfb_blank(int blank, struct fb_info *info) aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && blank <= FB_BLANK_NORMAL) + if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) set_backlight_enable(1); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) if (par->lcd_table && blank <= FB_BLANK_NORMAL && diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 5886a2f1323e..c7091761cef4 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -20,7 +20,7 @@ #include #ifdef CONFIG_PPC_PMAC -#include +#include #include #include #endif @@ -2745,7 +2745,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) rinfo->pm_mode |= radeon_pm_off; } #if defined(CONFIG_PPC_PMAC) - if (_machine == _MACH_Pmac && rinfo->of_node) { + if (machine_is(powermac) && rinfo->of_node) { if (rinfo->is_mobility && rinfo->pm_reg && rinfo->family <= CHIP_FAMILY_RV250) rinfo->pm_mode |= radeon_pm_d2; diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 66d6f2f0a219..1103010af54a 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -60,8 +60,8 @@ #include #endif #ifdef CONFIG_PPC_PREP -#include -#define isPReP (_machine == _MACH_prep) +#include +#define isPReP (machine_is(prep)) #else #define isPReP 0 #endif diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 951c9974a1d3..23c1827b2d0b 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -115,6 +115,7 @@ #include #ifdef CONFIG_PPC_PMAC +#include unsigned char nvram_read_byte(int); static int default_vmode = VMODE_NVRAM; static int default_cmode = CMODE_NVRAM; @@ -1833,7 +1834,7 @@ static int initMatrox2(WPMINFO struct board* b){ /* FIXME: Where to move this?! */ #if defined(CONFIG_PPC_PMAC) #ifndef MODULE - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct fb_var_screeninfo var; if (default_vmode <= 0 || default_vmode > VMODE_MAX) default_vmode = VMODE_640_480_60; diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index a7c4e5e8ead6..7258b3245316 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -29,6 +29,7 @@ #include #endif #ifdef CONFIG_PMAC_BACKLIGHT +#include #include #endif @@ -1353,7 +1354,7 @@ static int nvidiafb_blank(int blank, struct fb_info *info) NVWriteCrtc(par, 0x1a, vesa); #ifdef CONFIG_PMAC_BACKLIGHT - if (par->FlatPanel && _machine == _MACH_Pmac) { + if (par->FlatPanel && machine_is(powermac)) { set_backlight_enable(!blank); } #endif @@ -1688,7 +1689,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, info->fix.id, par->FbMapSize / (1024 * 1024), info->fix.smem_start); #ifdef CONFIG_PMAC_BACKLIGHT - if (par->FlatPanel && _machine == _MACH_Pmac) + if (par->FlatPanel && machine_is(powermac)) register_backlight_controller(&nvidia_backlight_controller, par, "mnca"); #endif diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index db9fb9074dbc..04820fab964c 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c @@ -1596,7 +1596,7 @@ static int radeonfb_blank (int blank, struct fb_info *info) return 0; #ifdef CONFIG_PMAC_BACKLIGHT - if (rinfo->dviDisp_type == MT_LCD && _machine == _MACH_Pmac) { + if (rinfo->dviDisp_type == MT_LCD && machine_is(powermac)) { set_backlight_enable(!blank); return 0; } diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 6c19ab6afb01..b7bd6bb2c77c 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -49,6 +49,7 @@ #include #endif #ifdef CONFIG_PMAC_BACKLIGHT +#include #include #endif @@ -1247,7 +1248,7 @@ static int rivafb_blank(int blank, struct fb_info *info) CRTCout(par, 0x1a, vesa); #ifdef CONFIG_PMAC_BACKLIGHT - if ( par->FlatPanel && _machine == _MACH_Pmac) { + if ( par->FlatPanel && machine_is(powermac)) { set_backlight_enable(!blank); } #endif @@ -2037,9 +2038,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd, info->fix.smem_len / (1024 * 1024), info->fix.smem_start); #ifdef CONFIG_PMAC_BACKLIGHT - if (default_par->FlatPanel && _machine == _MACH_Pmac) - register_backlight_controller(&riva_backlight_controller, - default_par, "mnca"); + if (default_par->FlatPanel && machine_is(powermac)) + register_backlight_controller(&riva_backlight_controller, + default_par, "mnca"); #endif NVTRACE_LEAVE(); return 0; diff --git a/fs/partitions/mac.c b/fs/partitions/mac.c index bb22cdd0cb14..813292f21210 100644 --- a/fs/partitions/mac.c +++ b/fs/partitions/mac.c @@ -12,6 +12,7 @@ #include "mac.h" #ifdef CONFIG_PPC_PMAC +#include extern void note_bootable_part(dev_t dev, int part, int goodness); #endif @@ -79,7 +80,7 @@ int mac_partition(struct parsed_partitions *state, struct block_device *bdev) * If this is the first bootable partition, tell the * setup code, in case it wants to make this the root. */ - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { int goodness = 0; mac_fix_string(part->processor, 16); diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 758e47fe8c1e..5ed847680754 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -47,6 +47,7 @@ struct smp_ops_t { #endif struct machdep_calls { + char *name; #ifdef CONFIG_PPC64 void (*hpte_invalidate)(unsigned long slot, unsigned long va, @@ -85,9 +86,9 @@ struct machdep_calls { void (*iommu_dev_setup)(struct pci_dev *dev); void (*iommu_bus_setup)(struct pci_bus *bus); void (*irq_bus_setup)(struct pci_bus *bus); -#endif +#endif /* CONFIG_PPC64 */ - int (*probe)(int platform); + int (*probe)(void); void (*setup_arch)(void); void (*init_early)(void); /* Optional, may be NULL. */ @@ -207,8 +208,6 @@ struct machdep_calls { /* Called at then very end of pcibios_init() */ void (*pcibios_after_init)(void); - /* this is for modules, since _machine can be a define -- Cort */ - int ppc_machine; #endif /* CONFIG_PPC32 */ /* Called to shutdown machine specific hardware not already controlled @@ -244,7 +243,26 @@ struct machdep_calls { extern void power4_idle(void); extern void ppc6xx_idle(void); +/* + * ppc_md contains a copy of the machine description structure for the + * current platform. machine_id contains the initial address where the + * description was found during boot. + */ extern struct machdep_calls ppc_md; +extern struct machdep_calls *machine_id; + +#define __machine_desc __attribute__ ((__section__ (".machine.desc"))) + +#define define_machine(name) struct machdep_calls mach_##name __machine_desc = +#define machine_is(name) \ + ({ \ + extern struct machdep_calls mach_##name \ + __attribute__((weak)); \ + machine_id == &mach_##name; \ + }) + +extern void probe_machine(void); + extern char cmd_line[COMMAND_LINE_SIZE]; #ifdef CONFIG_PPC_PMAC diff --git a/include/asm-powerpc/pmac_feature.h b/include/asm-powerpc/pmac_feature.h index 3221628130c4..d3599cc9aa74 100644 --- a/include/asm-powerpc/pmac_feature.h +++ b/include/asm-powerpc/pmac_feature.h @@ -305,7 +305,7 @@ extern void pmac_feature_init(void); extern void pmac_set_early_video_resume(void (*proc)(void *data), void *data); extern void pmac_call_early_video_resume(void); -#define PMAC_FTR_DEF(x) ((_MACH_Pmac << 16) | (x)) +#define PMAC_FTR_DEF(x) ((0x6660000) | (x)) /* The AGP driver registers itself here */ extern void pmac_register_agp_pm(struct pci_dev *bridge, diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index 57643b5b782f..93f83efeb310 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -22,22 +22,6 @@ * -- BenH. */ -/* Platforms codes (to be obsoleted) */ -#define PLATFORM_PSERIES 0x0100 -#define PLATFORM_PSERIES_LPAR 0x0101 -#define PLATFORM_ISERIES_LPAR 0x0201 -#define PLATFORM_LPAR 0x0001 -#define PLATFORM_POWERMAC 0x0400 -#define PLATFORM_MAPLE 0x0500 -#define PLATFORM_PREP 0x0600 -#define PLATFORM_CHRP 0x0700 -#define PLATFORM_CELL 0x1000 - -/* Compat platform codes for 32 bits */ -#define _MACH_prep PLATFORM_PREP -#define _MACH_Pmac PLATFORM_POWERMAC -#define _MACH_chrp PLATFORM_CHRP - /* PREP sub-platform types see residual.h for these */ #define _PREP_Motorola 0x01 /* motorola prep */ #define _PREP_Firm 0x02 /* firmworks prep */ @@ -49,15 +33,14 @@ #define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */ #define _CHRP_Pegasos 0x06 /* Genesi/bplan's Pegasos and Pegasos2 */ -#ifdef __KERNEL__ -#define platform_is_pseries() (_machine == PLATFORM_PSERIES || \ - _machine == PLATFORM_PSERIES_LPAR) +#if defined(__KERNEL__) && defined(CONFIG_PPC32) + +extern int _chrp_type; #ifdef CONFIG_PPC_PREP /* what kind of prep workstation we are */ extern int _prep_type; -extern int _chrp_type; /* * This is used to identify the board type from a given PReP board @@ -69,18 +52,12 @@ extern unsigned char ucBoardRevMaj, ucBoardRevMin; #endif /* CONFIG_PPC_PREP */ -#if defined(CONFIG_PPC_MULTIPLATFORM) -extern int _machine; - -#elif defined(CONFIG_PPC_ISERIES) -/* - * iSeries is soon to become MULTIPLATFORM hopefully ... - */ -#define _machine PLATFORM_ISERIES_LPAR -#else +#ifndef CONFIG_PPC_MULTIPLATFORM #define _machine 0 #endif /* CONFIG_PPC_MULTIPLATFORM */ -#endif /* __KERNEL__ */ + +#endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */ + /* * Default implementation of macro that returns current * instruction pointer ("program counter"). diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 782e13a070a1..97ef1cd71a4d 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -149,12 +149,14 @@ extern struct device_node *of_node_get(struct device_node *node); extern void of_node_put(struct device_node *node); /* For scanning the flat device-tree at boot time */ -int __init of_scan_flat_dt(int (*it)(unsigned long node, - const char *uname, int depth, - void *data), - void *data); -void* __init of_get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size); +extern int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data); +extern void* __init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size); +extern int __init of_flat_dt_is_compatible(unsigned long node, const char *name); +extern unsigned long __init of_get_flat_dt_root(void); /* For updating the device tree at runtime */ extern void of_attach_node(struct device_node *); diff --git a/include/asm-powerpc/vdso_datapage.h b/include/asm-powerpc/vdso_datapage.h index 7aa92086c3fb..8a94f0eba5e9 100644 --- a/include/asm-powerpc/vdso_datapage.h +++ b/include/asm-powerpc/vdso_datapage.h @@ -55,6 +55,9 @@ struct vdso_data { __u32 minor; /* Minor number 0x14 */ } version; + /* Note about the platform flags: it now only contains the lpar + * bit. The actual platform number is dead and burried + */ __u32 platform; /* Platform flags 0x18 */ __u32 processor; /* Processor type 0x1C */ __u64 processorCount; /* # of physical processors 0x20 */ diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h index 2723b423f675..e1a0a7b213d7 100644 --- a/include/asm-ppc/machdep.h +++ b/include/asm-ppc/machdep.h @@ -19,6 +19,18 @@ struct pci_dev; struct seq_file; struct file; +/* + * This is for compatibility with ARCH=powerpc. + */ +#define machine_is(x) __MACHINE_IS_##x +#define __MACHINE_IS_powermac 0 +#define __MACHINE_IS_chrp 0 +#ifdef CONFIG_PPC_PREP +#define __MACHINE_IS_prep 1 +#else +#define __MACHINE_IS_prep 0 +#endif + /* We export this macro for external modules like Alsa to know if * ppc_md.feature_call is implemented or not */ diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c index 6ba8d6f45fe8..a8636adef2e6 100644 --- a/sound/oss/dmasound/dmasound_awacs.c +++ b/sound/oss/dmasound/dmasound_awacs.c @@ -2814,7 +2814,7 @@ int __init dmasound_awacs_init(void) struct device_node *io = NULL, *info = NULL; int vol, res; - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return -ENODEV; awacs_subframe = 0; diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index aa57170101fd..f0794ef9d1ac 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -869,7 +869,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) u32 layout_id = 0; - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return -ENODEV; chip->subframe = 0; -- cgit v1.2.3-59-g8ed1b From 86a34147d1f1c94e94500e63e83f9fa42548a088 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Tue, 28 Mar 2006 01:56:14 -0800 Subject: [PATCH] synclink: remove dead code Remove dead code from synclink driver. This was used previously when the write method had a from_user flag, which has been removed. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclink.c | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index d68be61f0a49..abb03e52fe12 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -941,17 +941,6 @@ static void* mgsl_get_text_ptr(void) return mgsl_get_text_ptr; } -/* - * tmp_buf is used as a temporary buffer by mgsl_write. We need to - * lock it in case the COPY_FROM_USER blocks while swapping in a page, - * and some other program tries to do a serial write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the serial ioports, since it significantly saves - * memory if large numbers of serial ports are open. - */ -static unsigned char *tmp_buf; - static inline int mgsl_paranoia_check(struct mgsl_struct *info, char *name, const char *routine) { @@ -2150,7 +2139,7 @@ static int mgsl_write(struct tty_struct * tty, if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) goto cleanup; - if (!tty || !info->xmit_buf || !tmp_buf) + if (!tty || !info->xmit_buf) goto cleanup; if ( info->params.mode == MGSL_MODE_HDLC || @@ -3438,7 +3427,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) { struct mgsl_struct *info; int retval, line; - unsigned long page; unsigned long flags; /* verify range of specified line number */ @@ -3472,18 +3460,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) goto cleanup; } - if (!tmp_buf) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) { - retval = -ENOMEM; - goto cleanup; - } - if (tmp_buf) - free_page(page); - else - tmp_buf = (unsigned char *) page; - } - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; spin_lock_irqsave(&info->netlock, flags); @@ -4502,11 +4478,6 @@ static void synclink_cleanup(void) kfree(tmp); } - if (tmp_buf) { - free_page((unsigned long) tmp_buf); - tmp_buf = NULL; - } - if (pci_registered) pci_unregister_driver(&synclink_pci_driver); } -- cgit v1.2.3-59-g8ed1b From 0080b7aae88c75e2a6b38dfcb228b0f239e18e3c Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Tue, 28 Mar 2006 01:56:15 -0800 Subject: [PATCH] synclink_gt add gpio feature Add driver support for general purpose I/O feature of the Synclink GT adapters. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclink_gt.c | 246 ++++++++++++++++++++++++++++++++++++++++++++- include/linux/synclink.h | 11 +- 2 files changed, 252 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 738ec2f4e563..8818042bad7c 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -1,5 +1,5 @@ /* - * $Id: synclink_gt.c,v 4.22 2006/01/09 20:16:06 paulkf Exp $ + * $Id: synclink_gt.c,v 4.25 2006/02/06 21:20:33 paulkf Exp $ * * Device driver for Microgate SyncLink GT serial adapters. * @@ -92,7 +92,7 @@ * module identification */ static char *driver_name = "SyncLink GT"; -static char *driver_version = "$Revision: 4.22 $"; +static char *driver_version = "$Revision: 4.25 $"; static char *tty_driver_name = "synclink_gt"; static char *tty_dev_prefix = "ttySLG"; MODULE_LICENSE("GPL"); @@ -187,6 +187,20 @@ static void hdlcdev_exit(struct slgt_info *info); #define SLGT_MAX_PORTS 4 #define SLGT_REG_SIZE 256 +/* + * conditional wait facility + */ +struct cond_wait { + struct cond_wait *next; + wait_queue_head_t q; + wait_queue_t wait; + unsigned int data; +}; +static void init_cond_wait(struct cond_wait *w, unsigned int data); +static void add_cond_wait(struct cond_wait **head, struct cond_wait *w); +static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w); +static void flush_cond_wait(struct cond_wait **head); + /* * DMA buffer descriptor and access macros */ @@ -269,6 +283,9 @@ struct slgt_info { struct timer_list tx_timer; struct timer_list rx_timer; + unsigned int gpio_present; + struct cond_wait *gpio_wait_q; + spinlock_t lock; /* spinlock for synchronizing with ISR */ struct work_struct task; @@ -379,6 +396,11 @@ static MGSL_PARAMS default_params = { #define MASK_OVERRUN BIT4 #define GSR 0x00 /* global status */ +#define JCR 0x04 /* JTAG control */ +#define IODR 0x08 /* GPIO direction */ +#define IOER 0x0c /* GPIO interrupt enable */ +#define IOVR 0x10 /* GPIO value */ +#define IOSR 0x14 /* GPIO interrupt status */ #define TDR 0x80 /* tx data */ #define RDR 0x80 /* rx data */ #define TCR 0x82 /* tx control */ @@ -503,6 +525,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file, static void set_break(struct tty_struct *tty, int break_state); static int get_interface(struct slgt_info *info, int __user *if_mode); static int set_interface(struct slgt_info *info, int if_mode); +static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); +static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); +static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); /* * driver functions @@ -1112,6 +1137,12 @@ static int ioctl(struct tty_struct *tty, struct file *file, return get_interface(info, argp); case MGSL_IOCSIF: return set_interface(info,(int)arg); + case MGSL_IOCSGPIO: + return set_gpio(info, argp); + case MGSL_IOCGGPIO: + return get_gpio(info, argp); + case MGSL_IOCWAITGPIO: + return wait_gpio(info, argp); case TIOCGICOUNT: spin_lock_irqsave(&info->lock,flags); cnow = info->icount; @@ -2158,6 +2189,24 @@ static void isr_txeom(struct slgt_info *info, unsigned short status) } } +static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int state) +{ + struct cond_wait *w, *prev; + + /* wake processes waiting for specific transitions */ + for (w = info->gpio_wait_q, prev = NULL ; w != NULL ; w = w->next) { + if (w->data & changed) { + w->data = state; + wake_up_interruptible(&w->q); + if (prev != NULL) + prev->next = w->next; + else + info->gpio_wait_q = w->next; + } else + prev = w; + } +} + /* interrupt service routine * * irq interrupt number @@ -2193,6 +2242,22 @@ static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs) } } + if (info->gpio_present) { + unsigned int state; + unsigned int changed; + while ((changed = rd_reg32(info, IOSR)) != 0) { + DBGISR(("%s iosr=%08x\n", info->device_name, changed)); + /* read latched state of GPIO signals */ + state = rd_reg32(info, IOVR); + /* clear pending GPIO interrupt bits */ + wr_reg32(info, IOSR, changed); + for (i=0 ; i < info->port_count ; i++) { + if (info->port_array[i] != NULL) + isr_gpio(info->port_array[i], changed, state); + } + } + } + for(i=0; i < info->port_count ; i++) { struct slgt_info *port = info->port_array[i]; @@ -2276,6 +2341,8 @@ static void shutdown(struct slgt_info *info) set_signals(info); } + flush_cond_wait(&info->gpio_wait_q); + spin_unlock_irqrestore(&info->lock,flags); if (info->tty) @@ -2650,6 +2717,175 @@ static int set_interface(struct slgt_info *info, int if_mode) return 0; } +/* + * set general purpose IO pin state and direction + * + * user_gpio fields: + * state each bit indicates a pin state + * smask set bit indicates pin state to set + * dir each bit indicates a pin direction (0=input, 1=output) + * dmask set bit indicates pin direction to set + */ +static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) +{ + unsigned long flags; + struct gpio_desc gpio; + __u32 data; + + if (!info->gpio_present) + return -EINVAL; + if (copy_from_user(&gpio, user_gpio, sizeof(gpio))) + return -EFAULT; + DBGINFO(("%s set_gpio state=%08x smask=%08x dir=%08x dmask=%08x\n", + info->device_name, gpio.state, gpio.smask, + gpio.dir, gpio.dmask)); + + spin_lock_irqsave(&info->lock,flags); + if (gpio.dmask) { + data = rd_reg32(info, IODR); + data |= gpio.dmask & gpio.dir; + data &= ~(gpio.dmask & ~gpio.dir); + wr_reg32(info, IODR, data); + } + if (gpio.smask) { + data = rd_reg32(info, IOVR); + data |= gpio.smask & gpio.state; + data &= ~(gpio.smask & ~gpio.state); + wr_reg32(info, IOVR, data); + } + spin_unlock_irqrestore(&info->lock,flags); + + return 0; +} + +/* + * get general purpose IO pin state and direction + */ +static int get_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) +{ + struct gpio_desc gpio; + if (!info->gpio_present) + return -EINVAL; + gpio.state = rd_reg32(info, IOVR); + gpio.smask = 0xffffffff; + gpio.dir = rd_reg32(info, IODR); + gpio.dmask = 0xffffffff; + if (copy_to_user(user_gpio, &gpio, sizeof(gpio))) + return -EFAULT; + DBGINFO(("%s get_gpio state=%08x dir=%08x\n", + info->device_name, gpio.state, gpio.dir)); + return 0; +} + +/* + * conditional wait facility + */ +static void init_cond_wait(struct cond_wait *w, unsigned int data) +{ + init_waitqueue_head(&w->q); + init_waitqueue_entry(&w->wait, current); + w->data = data; +} + +static void add_cond_wait(struct cond_wait **head, struct cond_wait *w) +{ + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&w->q, &w->wait); + w->next = *head; + *head = w; +} + +static void remove_cond_wait(struct cond_wait **head, struct cond_wait *cw) +{ + struct cond_wait *w, *prev; + remove_wait_queue(&cw->q, &cw->wait); + set_current_state(TASK_RUNNING); + for (w = *head, prev = NULL ; w != NULL ; prev = w, w = w->next) { + if (w == cw) { + if (prev != NULL) + prev->next = w->next; + else + *head = w->next; + break; + } + } +} + +static void flush_cond_wait(struct cond_wait **head) +{ + while (*head != NULL) { + wake_up_interruptible(&(*head)->q); + *head = (*head)->next; + } +} + +/* + * wait for general purpose I/O pin(s) to enter specified state + * + * user_gpio fields: + * state - bit indicates target pin state + * smask - set bit indicates watched pin + * + * The wait ends when at least one watched pin enters the specified + * state. When 0 (no error) is returned, user_gpio->state is set to the + * state of all GPIO pins when the wait ends. + * + * Note: Each pin may be a dedicated input, dedicated output, or + * configurable input/output. The number and configuration of pins + * varies with the specific adapter model. Only input pins (dedicated + * or configured) can be monitored with this function. + */ +static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) +{ + unsigned long flags; + int rc = 0; + struct gpio_desc gpio; + struct cond_wait wait; + u32 state; + + if (!info->gpio_present) + return -EINVAL; + if (copy_from_user(&gpio, user_gpio, sizeof(gpio))) + return -EFAULT; + DBGINFO(("%s wait_gpio() state=%08x smask=%08x\n", + info->device_name, gpio.state, gpio.smask)); + /* ignore output pins identified by set IODR bit */ + if ((gpio.smask &= ~rd_reg32(info, IODR)) == 0) + return -EINVAL; + init_cond_wait(&wait, gpio.smask); + + spin_lock_irqsave(&info->lock, flags); + /* enable interrupts for watched pins */ + wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask); + /* get current pin states */ + state = rd_reg32(info, IOVR); + + if (gpio.smask & ~(state ^ gpio.state)) { + /* already in target state */ + gpio.state = state; + } else { + /* wait for target state */ + add_cond_wait(&info->gpio_wait_q, &wait); + spin_unlock_irqrestore(&info->lock, flags); + schedule(); + if (signal_pending(current)) + rc = -ERESTARTSYS; + else + gpio.state = wait.data; + spin_lock_irqsave(&info->lock, flags); + remove_cond_wait(&info->gpio_wait_q, &wait); + } + + /* disable all GPIO interrupts if no waiting processes */ + if (info->gpio_wait_q == NULL) + wr_reg32(info, IOER, 0); + spin_unlock_irqrestore(&info->lock,flags); + + if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio))) + rc = -EFAULT; + return rc; +} + static int modem_input_wait(struct slgt_info *info,int arg) { unsigned long flags; @@ -3166,8 +3402,10 @@ static void device_init(int adapter_num, struct pci_dev *pdev) } else { port_array[0]->irq_requested = 1; adapter_test(port_array[0]); - for (i=1 ; i < port_count ; i++) + for (i=1 ; i < port_count ; i++) { port_array[i]->init_error = port_array[0]->init_error; + port_array[i]->gpio_present = port_array[0]->gpio_present; + } } } } @@ -4301,7 +4539,7 @@ static int register_test(struct slgt_info *info) break; } } - + info->gpio_present = (rd_reg32(info, JCR) & BIT5) ? 1 : 0; info->init_error = rc ? 0 : DiagStatus_AddressFailure; return rc; } diff --git a/include/linux/synclink.h b/include/linux/synclink.h index 1b7cd8d1a71b..2993302f7923 100644 --- a/include/linux/synclink.h +++ b/include/linux/synclink.h @@ -1,7 +1,7 @@ /* * SyncLink Multiprotocol Serial Adapter Driver * - * $Id: synclink.h,v 3.10 2005/11/08 19:50:54 paulkf Exp $ + * $Id: synclink.h,v 3.11 2006/02/06 21:20:29 paulkf Exp $ * * Copyright (C) 1998-2000 by Microgate Corporation * @@ -221,6 +221,12 @@ struct mgsl_icount { __u32 rxidle; }; +struct gpio_desc { + __u32 state; + __u32 smask; + __u32 dir; + __u32 dmask; +}; #define DEBUG_LEVEL_DATA 1 #define DEBUG_LEVEL_ERROR 2 @@ -276,5 +282,8 @@ struct mgsl_icount { #define MGSL_IOCLOOPTXDONE _IO(MGSL_MAGIC_IOC,9) #define MGSL_IOCSIF _IO(MGSL_MAGIC_IOC,10) #define MGSL_IOCGIF _IO(MGSL_MAGIC_IOC,11) +#define MGSL_IOCSGPIO _IOW(MGSL_MAGIC_IOC,16,struct gpio_desc) +#define MGSL_IOCGGPIO _IOR(MGSL_MAGIC_IOC,17,struct gpio_desc) +#define MGSL_IOCWAITGPIO _IOWR(MGSL_MAGIC_IOC,18,struct gpio_desc) #endif /* _SYNCLINK_H_ */ -- cgit v1.2.3-59-g8ed1b From be4676e61f969b624185f14d819adef23d45ffc2 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Tue, 28 Mar 2006 01:56:16 -0800 Subject: [PATCH] synclink_gt: remove uneeded async code Remove code in async receive handling that serves no purpose with new tty receive buffering. Previously this code tried to free up receive buffer space, but now does nothing useful while making expensive calls. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclink_gt.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 8818042bad7c..b4d1f4eea435 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -1793,10 +1793,6 @@ static void rx_async(struct slgt_info *info) DBGDATA(info, p, count, "rx"); for(i=0 ; i < count; i+=2, p+=2) { - if (tty && chars) { - tty_flip_buffer_push(tty); - chars = 0; - } ch = *p; icount->rx++; -- cgit v1.2.3-59-g8ed1b From a687fb18cbd061de2092632cf77e6b9dc93cf7cd Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 28 Mar 2006 01:56:17 -0800 Subject: [PATCH] let BLK_DEV_RAM_COUNT depend on BLK_DEV_RAM It's purely cosmetic, but with the patch there's no longer a BLK_DEV_RAM_COUNT setting in the .config if BLK_DEV_RAM=n. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 875ae7699025..ae0949b3394f 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -383,8 +383,9 @@ config BLK_DEV_RAM thus say N here. config BLK_DEV_RAM_COUNT - int "Default number of RAM disks" if BLK_DEV_RAM + int "Default number of RAM disks" default "16" + depends on BLK_DEV_RAM help The default value is 16 RAM disks. Change this if you know what are doing. If you boot from a filesystem that needs to be extracted -- cgit v1.2.3-59-g8ed1b From 8637980bab3f09157eef20cc65d2eb7393c770fd Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 28 Mar 2006 01:56:18 -0800 Subject: [PATCH] paride: register_chrdev fix If the user specified `major=0' (odd thing to do), pg.c will use dynamic allocation. We need to pick up that major for subsequent unregister_chrdev(). Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/paride/pg.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index 6f5df0fad703..79b868254032 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c @@ -643,7 +643,8 @@ static ssize_t pg_read(struct file *filp, char __user *buf, size_t count, loff_t static int __init pg_init(void) { - int unit, err = 0; + int unit; + int err; if (disable){ err = -1; @@ -657,16 +658,17 @@ static int __init pg_init(void) goto out; } - if (register_chrdev(major, name, &pg_fops)) { + err = register_chrdev(major, name, &pg_fops); + if (err < 0) { printk("pg_init: unable to get major number %d\n", major); for (unit = 0; unit < PG_UNITS; unit++) { struct pg *dev = &devices[unit]; if (dev->present) pi_release(dev->pi); } - err = -1; goto out; } + major = err; /* In case the user specified `major=0' (dynamic) */ pg_class = class_create(THIS_MODULE, "pg"); if (IS_ERR(pg_class)) { err = PTR_ERR(pg_class); -- cgit v1.2.3-59-g8ed1b From 829d5f68ec59ff7c0fdd472132680df8e4b64f3e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 28 Mar 2006 01:56:18 -0800 Subject: [PATCH] paride-pt: register_chrdev fix If the user specified `major=0' (odd thing to do), pt.c will use dynamic allocation. We need to pick up that major for subsequent unregister_chrdev(). Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/paride/pt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index 715ae5dc88fb..d2013d362403 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c @@ -943,7 +943,8 @@ static ssize_t pt_write(struct file *filp, const char __user *buf, size_t count, static int __init pt_init(void) { - int unit, err = 0; + int unit; + int err; if (disable) { err = -1; @@ -955,14 +956,15 @@ static int __init pt_init(void) goto out; } - if (register_chrdev(major, name, &pt_fops)) { + err = register_chrdev(major, name, &pt_fops); + if (err < 0) { printk("pt_init: unable to get major number %d\n", major); for (unit = 0; unit < PT_UNITS; unit++) if (pt[unit].present) pi_release(pt[unit].pi); - err = -1; goto out; } + major = err; pt_class = class_create(THIS_MODULE, "pt"); if (IS_ERR(pt_class)) { err = PTR_ERR(pt_class); -- cgit v1.2.3-59-g8ed1b From 6d9eac34104654aa129e365b8d48bbb8c957f186 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 28 Mar 2006 01:56:19 -0800 Subject: [PATCH] capi: register_chrdev() fix If the user specified `major=0' (odd thing to do), capi.c will use dynamic allocation. We need to pick up that major for subsequent unregister_chrdev(). Acked-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/capi/capi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 623adbb0d13a..9b493f0becc4 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1485,6 +1485,7 @@ static int __init capi_init(void) { char *p; char *compileinfo; + int major_ret; if ((p = strchr(revision, ':')) != 0 && p[1]) { strlcpy(rev, p + 2, sizeof(rev)); @@ -1493,11 +1494,12 @@ static int __init capi_init(void) } else strcpy(rev, "1.0"); - if (register_chrdev(capi_major, "capi20", &capi_fops)) { + major_ret = register_chrdev(capi_major, "capi20", &capi_fops); + if (major_ret < 0) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); - return -EIO; + return major_ret; } - + capi_major = major_ret; capi_class = class_create(THIS_MODULE, "capi"); if (IS_ERR(capi_class)) { unregister_chrdev(capi_major, "capi20"); -- cgit v1.2.3-59-g8ed1b From 273577165cd206d2d6689ee4b18aa13de1ec4bde Mon Sep 17 00:00:00 2001 From: Brian Rogan Date: Tue, 28 Mar 2006 01:56:20 -0800 Subject: [PATCH] Add oprofile_add_ext_sample On ppc64 we look at a profiling register to work out the sample address and if it was in userspace or kernel. The backtrace interface oprofile_add_sample does not allow this. Create oprofile_add_ext_sample and make oprofile_add_sample use it too. Signed-off-by: Anton Blanchard Cc: Philippe Elie Cc: John Levon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/oprofile/cpu_buffer.c | 13 ++++++++++--- include/linux/oprofile.h | 10 ++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 330d3869b41e..fc4bc9b94c74 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -217,11 +217,10 @@ static void oprofile_end_trace(struct oprofile_cpu_buffer * cpu_buf) cpu_buf->tracing = 0; } -void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) +void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, + unsigned long event, int is_kernel) { struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()]; - unsigned long pc = profile_pc(regs); - int is_kernel = !user_mode(regs); if (!backtrace_depth) { log_sample(cpu_buf, pc, is_kernel, event); @@ -238,6 +237,14 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) oprofile_end_trace(cpu_buf); } +void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) +{ + int is_kernel = !user_mode(regs); + unsigned long pc = profile_pc(regs); + + oprofile_add_ext_sample(pc, regs, event, is_kernel); +} + void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) { struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()]; diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h index 559c4c38a9c7..b5b3197dfd4f 100644 --- a/include/linux/oprofile.h +++ b/include/linux/oprofile.h @@ -61,6 +61,16 @@ void oprofile_arch_exit(void); */ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event); +/** + * Add an extended sample. Use this when the PC is not from the regs, and + * we cannot determine if we're in kernel mode from the regs. + * + * This function does perform a backtrace. + * + */ +void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, + unsigned long event, int is_kernel); + /* Use this instead when the PC value is not from the regs. Doesn't * backtrace. */ void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event); -- cgit v1.2.3-59-g8ed1b From 3b71797eff4352b4295919efc52de84f84d33d94 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 28 Mar 2006 01:56:25 -0800 Subject: [PATCH] drivers/block/paride/pd.c: fix an off-by-one error The Coverity checker found this off-by-one error. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/paride/pd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 62d2464c12f2..2403721f9db1 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -151,6 +151,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV}; #include /* for the eject ioctl */ #include #include +#include #include #include #include @@ -275,7 +276,7 @@ static void pd_print_error(struct pd_unit *disk, char *msg, int status) int i; printk("%s: %s: status = 0x%x =", disk->name, msg, status); - for (i = 0; i < 18; i++) + for (i = 0; i < ARRAY_SIZE(pd_errs); i++) if (status & (1 << i)) printk(" %s", pd_errs[i]); printk("\n"); -- cgit v1.2.3-59-g8ed1b From fa8f399a2bc36c1329672400857757e0982babf3 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 28 Mar 2006 01:56:28 -0800 Subject: [PATCH] drivers/block/acsi_slm.c: size_t can't be < 0 A size_t can't be < 0. (akpm: and rw_verify_area() already did that check) Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/acsi_slm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c index a5c1c8e871ec..4cb9c1336287 100644 --- a/drivers/block/acsi_slm.c +++ b/drivers/block/acsi_slm.c @@ -369,8 +369,6 @@ static ssize_t slm_read( struct file *file, char *buf, size_t count, int length; int end; - if (count < 0) - return( -EINVAL ); if (!(page = __get_free_page( GFP_KERNEL ))) return( -ENOMEM ); -- cgit v1.2.3-59-g8ed1b From 9edc91df07a227dbde9f98ee1097f554130993dc Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Tue, 28 Mar 2006 01:56:30 -0800 Subject: [PATCH] ide: AMD756 no host side cable detection >From http://marc.theaimsgroup.com/?l=linux-kernel&m=110304128900342&w=2 AMD756 doesn't support host side cable detection. Do disk side only and don't advice obsolete options. Acked-by: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/amd74xx.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 21965e5ef25e..b22ee5462318 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -347,10 +347,8 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch break; case AMD_UDMA_66: - pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); - for (i = 24; i >= 0; i -= 8) - if ((u >> i) & 4) - amd_80w |= (1 << (1 - (i >> 4))); + /* no host side cable detection */ + amd_80w = 0x03; break; } @@ -386,8 +384,6 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch if (amd_clock < 20000 || amd_clock > 50000) { printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", amd_chipset->name, amd_clock); - printk(KERN_WARNING "%s: Use ide0=ata66 if you want to assume 80-wire cable\n", - amd_chipset->name); amd_clock = 33333; } -- cgit v1.2.3-59-g8ed1b From d266ab88938e49aa95f1965ee020df1b1d4c5761 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 28 Mar 2006 01:56:31 -0800 Subject: [PATCH] Small fixes backported to old IDE SiS driver Some quick backport bits from the libata PATA work to fix things found in the sis driver. The piix driver needs some fixes too but those are way to large and need someone working on old IDE with time to do them. This patch fixes the case where random bits get loaded into SIS timing registers according to the description of the correct behaviour from Vojtech Pavlik. It also adds the SiS5517 ATA16 chipset which is not currently supported by the driver. Thanks to Conrad Harriss for loaning me the machine with the 5517 chipset. Signed-off-by: Alan Cox Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/sis5513.c | 2 ++ include/linux/pci_ids.h | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 75a2253a3e68..8e9d87701ce2 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -112,6 +112,7 @@ static const struct { { "SiS5596", PCI_DEVICE_ID_SI_5596, ATA_16 }, { "SiS5571", PCI_DEVICE_ID_SI_5571, ATA_16 }, + { "SiS5517", PCI_DEVICE_ID_SI_5517, ATA_16 }, { "SiS551x", PCI_DEVICE_ID_SI_5511, ATA_16 }, }; @@ -524,6 +525,7 @@ static void config_art_rwp_pio (ide_drive_t *drive, u8 pio) case 3: test1 = 0x30|0x03; break; case 2: test1 = 0x40|0x04; break; case 1: test1 = 0x60|0x07; break; + case 0: test1 = 0x00; break; default: break; } pci_write_config_byte(dev, drive_pci, test1); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 02f6cf20b141..e2ab2ac18d6b 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -642,6 +642,7 @@ #define PCI_DEVICE_ID_SI_965 0x0965 #define PCI_DEVICE_ID_SI_5511 0x5511 #define PCI_DEVICE_ID_SI_5513 0x5513 +#define PCI_DEVICE_ID_SI_5517 0x5517 #define PCI_DEVICE_ID_SI_5518 0x5518 #define PCI_DEVICE_ID_SI_5571 0x5571 #define PCI_DEVICE_ID_SI_5581 0x5581 -- cgit v1.2.3-59-g8ed1b From b02389e98a7b64ad5cd4823740defa8821f30bbd Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 28 Mar 2006 01:56:32 -0800 Subject: [PATCH] ide_generic_all_on() warning fix drivers/ide/pci/generic.c:45: warning: `ide_generic_all_on' defined but not used Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/generic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 6e3ab0c38c4d..f82e82109728 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -41,14 +41,15 @@ static int ide_generic_all; /* Set to claim all devices */ +#ifndef MODULE static int __init ide_generic_all_on(char *unused) { ide_generic_all = 1; printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n"); return 1; } - __setup("all-generic-ide", ide_generic_all_on); +#endif static void __devinit init_hwif_generic (ide_hwif_t *hwif) { -- cgit v1.2.3-59-g8ed1b From 0fed48463fb20c6bcabc5cf70e2de47b30507ee1 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 28 Mar 2006 01:56:37 -0800 Subject: [PATCH] for_each_possible_cpu: loopback device. This patch replaces for_each_cpu with for_each_possible_cpu. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/loopback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 0c13795dca38..b79d6e8d3045 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -172,7 +172,7 @@ static struct net_device_stats *get_stats(struct net_device *dev) memset(stats, 0, sizeof(struct net_device_stats)); - for_each_cpu(i) { + for_each_possible_cpu(i) { struct net_device_stats *lb_stats; lb_stats = &per_cpu(loopback_stats, i); -- cgit v1.2.3-59-g8ed1b From fe449f48368623eb47715061b4977ce982d8e03b Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 28 Mar 2006 01:56:38 -0800 Subject: [PATCH] for_each_possible_cpu: oprofile. This patch replaces for_each_cpu with for_each_possible_cpu. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/oprofile/oprofile_stats.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c index e94b1e4a2a84..f0acb661c253 100644 --- a/drivers/oprofile/oprofile_stats.c +++ b/drivers/oprofile/oprofile_stats.c @@ -22,7 +22,7 @@ void oprofile_reset_stats(void) struct oprofile_cpu_buffer * cpu_buf; int i; - for_each_cpu(i) { + for_each_possible_cpu(i) { cpu_buf = &cpu_buffer[i]; cpu_buf->sample_received = 0; cpu_buf->sample_lost_overflow = 0; @@ -46,7 +46,7 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root) if (!dir) return; - for_each_cpu(i) { + for_each_possible_cpu(i) { cpu_buf = &cpu_buffer[i]; snprintf(buf, 10, "cpu%d", i); cpudir = oprofilefs_mkdir(sb, dir, buf); -- cgit v1.2.3-59-g8ed1b From 99ac48f54a91d02140c497edc31dc57d4bc5c85d Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Tue, 28 Mar 2006 01:56:41 -0800 Subject: [PATCH] mark f_ops const in the inode Mark the f_ops members of inodes as const, as well as fix the ripple-through this causes by places that copy this f_ops and then "do stuff" with it. Signed-off-by: Arjan van de Ven Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/platforms/cell/spufs/inode.c | 2 +- arch/ppc/kernel/ppc_htab.c | 2 +- drivers/char/drm/drm_fops.c | 2 +- drivers/char/drm/i810_dma.c | 2 +- drivers/char/drm/i830_dma.c | 2 +- drivers/char/mem.c | 2 +- drivers/char/misc.c | 2 +- drivers/input/input.c | 2 +- drivers/isdn/capi/kcapi_proc.c | 2 +- drivers/media/dvb/dvb-core/dvbdev.c | 2 +- drivers/media/video/videodev.c | 2 +- drivers/message/i2o/i2o_proc.c | 2 +- drivers/oprofile/oprofilefs.c | 6 +++--- drivers/telephony/phonedev.c | 2 +- drivers/usb/core/file.c | 6 +++--- drivers/usb/gadget/inode.c | 6 +++--- fs/char_dev.c | 4 ++-- fs/debugfs/inode.c | 2 +- fs/inode.c | 2 +- fs/nfsd/vfs.c | 2 +- fs/proc/generic.c | 2 +- fs/proc/internal.h | 2 +- fs/proc/proc_misc.c | 2 +- fs/select.c | 2 +- include/linux/cdev.h | 4 ++-- include/linux/debugfs.h | 2 +- include/linux/fs.h | 6 +++--- include/linux/input.h | 2 +- include/linux/miscdevice.h | 2 +- include/linux/oprofile.h | 4 ++-- include/linux/proc_fs.h | 4 ++-- include/linux/sound.h | 12 ++++++------ include/linux/sunrpc/stats.h | 4 ++-- include/linux/usb.h | 2 +- include/linux/videodev2.h | 2 +- include/sound/core.h | 6 +++--- net/sunrpc/rpc_pipe.c | 2 +- net/sunrpc/stats.c | 4 ++-- sound/core/init.c | 3 ++- sound/core/sound.c | 4 ++-- sound/core/sound_oss.c | 2 +- sound/sound_core.c | 22 +++++++++++----------- 42 files changed, 75 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index b3962c3a0348..5be40aa483fd 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -103,7 +103,7 @@ spufs_setattr(struct dentry *dentry, struct iattr *attr) static int spufs_new_file(struct super_block *sb, struct dentry *dentry, - struct file_operations *fops, int mode, + const struct file_operations *fops, int mode, struct spu_context *ctx) { static struct inode_operations spufs_file_iops = { diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c index 2f5c7650274f..9b84bffdefce 100644 --- a/arch/ppc/kernel/ppc_htab.c +++ b/arch/ppc/kernel/ppc_htab.c @@ -52,7 +52,7 @@ static int ppc_htab_open(struct inode *inode, struct file *file) return single_open(file, ppc_htab_show, NULL); } -struct file_operations ppc_htab_operations = { +const struct file_operations ppc_htab_operations = { .open = ppc_htab_open, .read = seq_read, .llseek = seq_lseek, diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 641f7633878c..b7f7951c4587 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c @@ -175,7 +175,7 @@ int drm_stub_open(struct inode *inode, struct file *filp) drm_device_t *dev = NULL; int minor = iminor(inode); int err = -ENODEV; - struct file_operations *old_fops; + const struct file_operations *old_fops; DRM_DEBUG("\n"); diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index ae0aa6d7e0bb..c658dde3633b 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c @@ -126,7 +126,7 @@ static int i810_map_buffer(drm_buf_t * buf, struct file *filp) drm_device_t *dev = priv->head->dev; drm_i810_buf_priv_t *buf_priv = buf->dev_private; drm_i810_private_t *dev_priv = dev->dev_private; - struct file_operations *old_fops; + const struct file_operations *old_fops; int retcode = 0; if (buf_priv->currently_mapped == I810_BUF_MAPPED) diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index 163f2cbfe60d..b0f815d8cea8 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c @@ -128,7 +128,7 @@ static int i830_map_buffer(drm_buf_t * buf, struct file *filp) drm_device_t *dev = priv->head->dev; drm_i830_buf_priv_t *buf_priv = buf->dev_private; drm_i830_private_t *dev_priv = dev->dev_private; - struct file_operations *old_fops; + const struct file_operations *old_fops; unsigned long virtual; int retcode = 0; diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 5245ba1649ed..66719f9d294c 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -899,7 +899,7 @@ static const struct { unsigned int minor; char *name; umode_t mode; - struct file_operations *fops; + const struct file_operations *fops; } devlist[] = { /* list of minor devices */ {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 3e4c0414a01a..96eb2a709e21 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -129,7 +129,7 @@ static int misc_open(struct inode * inode, struct file * file) int minor = iminor(inode); struct miscdevice *c; int err = -ENODEV; - struct file_operations *old_fops, *new_fops = NULL; + const struct file_operations *old_fops, *new_fops = NULL; down(&misc_sem); diff --git a/drivers/input/input.c b/drivers/input/input.c index 4fe3da3c667a..f8af0945964e 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -923,7 +923,7 @@ void input_unregister_handler(struct input_handler *handler) static int input_open_file(struct inode *inode, struct file *file) { struct input_handler *handler = input_table[iminor(inode) >> 5]; - struct file_operations *old_fops, *new_fops = NULL; + const struct file_operations *old_fops, *new_fops = NULL; int err; /* No load-on-demand here? */ diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 2cc8b27e4c3b..ca9dc00a45c4 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -233,7 +233,7 @@ static struct file_operations proc_applstats_ops = { }; static void -create_seq_entry(char *name, mode_t mode, struct file_operations *f) +create_seq_entry(char *name, mode_t mode, const struct file_operations *f) { struct proc_dir_entry *entry; entry = create_proc_entry(name, mode, NULL); diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 54f8b95717b0..96fe0ecae250 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -86,7 +86,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) if (dvbdev && dvbdev->fops) { int err = 0; - struct file_operations *old_fops; + const struct file_operations *old_fops; file->private_data = dvbdev; old_fops = file->f_op; diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 75e3d41382f2..5f87dd5f1d0b 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -97,7 +97,7 @@ static int video_open(struct inode *inode, struct file *file) unsigned int minor = iminor(inode); int err = 0; struct video_device *vfl; - struct file_operations *old_fops; + const struct file_operations *old_fops; if(minor>=VIDEO_NUM_DEVICES) return -ENODEV; diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index 2a0c42b8cda5..3d2e76eea93e 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c @@ -56,7 +56,7 @@ typedef struct _i2o_proc_entry_t { char *name; /* entry name */ mode_t mode; /* mode */ - struct file_operations *fops; /* open function */ + const struct file_operations *fops; /* open function */ } i2o_proc_entry; /* global I2O /proc/i2o entry */ diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index d6bae699749a..b62da9b0cbf0 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c @@ -130,7 +130,7 @@ static struct file_operations ulong_ro_fops = { static struct dentry * __oprofilefs_create_file(struct super_block * sb, - struct dentry * root, char const * name, struct file_operations * fops, + struct dentry * root, char const * name, const struct file_operations * fops, int perm) { struct dentry * dentry; @@ -203,7 +203,7 @@ int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root, int oprofilefs_create_file(struct super_block * sb, struct dentry * root, - char const * name, struct file_operations * fops) + char const * name, const struct file_operations * fops) { if (!__oprofilefs_create_file(sb, root, name, fops, 0644)) return -EFAULT; @@ -212,7 +212,7 @@ int oprofilefs_create_file(struct super_block * sb, struct dentry * root, int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root, - char const * name, struct file_operations * fops, int perm) + char const * name, const struct file_operations * fops, int perm) { if (!__oprofilefs_create_file(sb, root, name, fops, perm)) return -EFAULT; diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c index 7a6db1c5c8c5..e166fffea86b 100644 --- a/drivers/telephony/phonedev.c +++ b/drivers/telephony/phonedev.c @@ -49,7 +49,7 @@ static int phone_open(struct inode *inode, struct file *file) unsigned int minor = iminor(inode); int err = 0; struct phone_device *p; - struct file_operations *old_fops, *new_fops = NULL; + const struct file_operations *old_fops, *new_fops = NULL; if (minor >= PHONE_NUM_DEVICES) return -ENODEV; diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 37b13368c814..b263a54a13c0 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -24,15 +24,15 @@ #include "usb.h" #define MAX_USB_MINORS 256 -static struct file_operations *usb_minors[MAX_USB_MINORS]; +static const struct file_operations *usb_minors[MAX_USB_MINORS]; static DEFINE_SPINLOCK(minor_lock); static int usb_open(struct inode * inode, struct file * file) { int minor = iminor(inode); - struct file_operations *c; + const struct file_operations *c; int err = -ENODEV; - struct file_operations *old_fops, *new_fops = NULL; + const struct file_operations *old_fops, *new_fops = NULL; spin_lock (&minor_lock); c = usb_minors[minor]; diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index b44cfda76b61..3f618ce6998d 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1581,7 +1581,7 @@ restart: static struct inode * gadgetfs_create_file (struct super_block *sb, char const *name, - void *data, struct file_operations *fops, + void *data, const struct file_operations *fops, struct dentry **dentry_p); static int activate_ep_files (struct dev_data *dev) @@ -1955,7 +1955,7 @@ module_param (default_perm, uint, 0644); static struct inode * gadgetfs_make_inode (struct super_block *sb, - void *data, struct file_operations *fops, + void *data, const struct file_operations *fops, int mode) { struct inode *inode = new_inode (sb); @@ -1979,7 +1979,7 @@ gadgetfs_make_inode (struct super_block *sb, */ static struct inode * gadgetfs_create_file (struct super_block *sb, char const *name, - void *data, struct file_operations *fops, + void *data, const struct file_operations *fops, struct dentry **dentry_p) { struct dentry *dentry; diff --git a/fs/char_dev.c b/fs/char_dev.c index 8c6eb04d31e2..b53dffa46bac 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -250,7 +250,7 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, } int register_chrdev(unsigned int major, const char *name, - struct file_operations *fops) + const struct file_operations *fops) { struct char_device_struct *cd; struct cdev *cdev; @@ -473,7 +473,7 @@ struct cdev *cdev_alloc(void) return p; } -void cdev_init(struct cdev *cdev, struct file_operations *fops) +void cdev_init(struct cdev *cdev, const struct file_operations *fops) { memset(cdev, 0, sizeof *cdev); INIT_LIST_HEAD(&cdev->list); diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index d4f1a2cddd47..85d166cdcae4 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -191,7 +191,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode, */ struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, - struct file_operations *fops) + const struct file_operations *fops) { struct dentry *dentry = NULL; int error; diff --git a/fs/inode.c b/fs/inode.c index 1fddf2803af8..32b7c3375021 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -104,7 +104,7 @@ static struct inode *alloc_inode(struct super_block *sb) { static struct address_space_operations empty_aops; static struct inode_operations empty_iops; - static struct file_operations empty_fops; + static const struct file_operations empty_fops; struct inode *inode; if (sb->s_op->alloc_inode) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 5320e5afaddb..31018333dc38 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -706,7 +706,7 @@ nfsd_close(struct file *filp) * after it. */ static inline int nfsd_dosync(struct file *filp, struct dentry *dp, - struct file_operations *fop) + const struct file_operations *fop) { struct inode *inode = dp->d_inode; int (*fsync) (struct file *, struct dentry *, int); diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 47b7a20d45eb..4ba03009cf72 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -560,7 +560,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de) struct file * filp = list_entry(p, struct file, f_u.fu_list); struct dentry * dentry = filp->f_dentry; struct inode * inode; - struct file_operations *fops; + const struct file_operations *fops; if (dentry->d_op != &proc_dentry_operations) continue; diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 95a1cf32b838..0502f17b860d 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -30,7 +30,7 @@ do { \ #endif -extern void create_seq_entry(char *name, mode_t mode, struct file_operations *f); +extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f); extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **); extern int proc_tid_stat(struct task_struct *, char *); extern int proc_tgid_stat(struct task_struct *, char *); diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 1edce0c34bfd..ef5a3323f4b5 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -731,7 +731,7 @@ static struct file_operations proc_sysrq_trigger_operations = { struct proc_dir_entry *proc_root_kcore; -void create_seq_entry(char *name, mode_t mode, struct file_operations *f) +void create_seq_entry(char *name, mode_t mode, const struct file_operations *f) { struct proc_dir_entry *entry; entry = create_proc_entry(name, mode, NULL); diff --git a/fs/select.c b/fs/select.c index 05cd199a1127..b3a3a1326af6 100644 --- a/fs/select.c +++ b/fs/select.c @@ -220,7 +220,7 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout) for (i = 0; i < n; ++rinp, ++routp, ++rexp) { unsigned long in, out, ex, all_bits, bit = 1, mask, j; unsigned long res_in = 0, res_out = 0, res_ex = 0; - struct file_operations *f_op = NULL; + const struct file_operations *f_op = NULL; struct file *file = NULL; in = *inp++; out = *outp++; ex = *exp++; diff --git a/include/linux/cdev.h b/include/linux/cdev.h index 8da37e29cb87..2216638962d2 100644 --- a/include/linux/cdev.h +++ b/include/linux/cdev.h @@ -5,13 +5,13 @@ struct cdev { struct kobject kobj; struct module *owner; - struct file_operations *ops; + const struct file_operations *ops; struct list_head list; dev_t dev; unsigned int count; }; -void cdev_init(struct cdev *, struct file_operations *); +void cdev_init(struct cdev *, const struct file_operations *); struct cdev *cdev_alloc(void); diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 4b0428e335be..176e2d371577 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -29,7 +29,7 @@ struct debugfs_blob_wrapper { #if defined(CONFIG_DEBUG_FS) struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, - struct file_operations *fops); + const struct file_operations *fops); struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); diff --git a/include/linux/fs.h b/include/linux/fs.h index 680d913350e7..ef355bc73714 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -496,7 +496,7 @@ struct inode { struct mutex i_mutex; struct rw_semaphore i_alloc_sem; struct inode_operations *i_op; - struct file_operations *i_fop; /* former ->i_op->default_file_ops */ + const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ struct super_block *i_sb; struct file_lock *i_flock; struct address_space *i_mapping; @@ -636,7 +636,7 @@ struct file { } f_u; struct dentry *f_dentry; struct vfsmount *f_vfsmnt; - struct file_operations *f_op; + const struct file_operations *f_op; atomic_t f_count; unsigned int f_flags; mode_t f_mode; @@ -1414,7 +1414,7 @@ extern void bd_release_from_disk(struct block_device *, struct gendisk *); extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); extern int register_chrdev_region(dev_t, unsigned, const char *); extern int register_chrdev(unsigned int, const char *, - struct file_operations *); + const struct file_operations *); extern int unregister_chrdev(unsigned int, const char *); extern void unregister_chrdev_region(dev_t, unsigned); extern int chrdev_open(struct inode *, struct file *); diff --git a/include/linux/input.h b/include/linux/input.h index 6d4cc3c110d6..1d4e341b72e6 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -957,7 +957,7 @@ struct input_handler { struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id); void (*disconnect)(struct input_handle *handle); - struct file_operations *fops; + const struct file_operations *fops; int minor; char *name; diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index 14ceebfc1efa..5b584dafb5a6 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -36,7 +36,7 @@ struct class_device; struct miscdevice { int minor; const char *name; - struct file_operations *fops; + const struct file_operations *fops; struct list_head list; struct device *dev; struct class_device *class; diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h index b5b3197dfd4f..0d514b252454 100644 --- a/include/linux/oprofile.h +++ b/include/linux/oprofile.h @@ -84,10 +84,10 @@ void oprofile_add_trace(unsigned long eip); * the specified file operations. */ int oprofilefs_create_file(struct super_block * sb, struct dentry * root, - char const * name, struct file_operations * fops); + char const * name, const struct file_operations * fops); int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root, - char const * name, struct file_operations * fops, int perm); + char const * name, const struct file_operations * fops, int perm); /** Create a file for read/write access to an unsigned long. */ int oprofilefs_create_ulong(struct super_block * sb, struct dentry * root, diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index cb224cf653b1..6d03d025fcd5 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -58,7 +58,7 @@ struct proc_dir_entry { gid_t gid; loff_t size; struct inode_operations * proc_iops; - struct file_operations * proc_fops; + const struct file_operations * proc_fops; get_info_t *get_info; struct module *owner; struct proc_dir_entry *next, *parent, *subdir; @@ -189,7 +189,7 @@ static inline struct proc_dir_entry *proc_net_create(const char *name, } static inline struct proc_dir_entry *proc_net_fops_create(const char *name, - mode_t mode, struct file_operations *fops) + mode_t mode, const struct file_operations *fops) { struct proc_dir_entry *res = create_proc_entry(name, mode, proc_net); if (res) diff --git a/include/linux/sound.h b/include/linux/sound.h index 72b9af4c3fd4..f63d8342ffa3 100644 --- a/include/linux/sound.h +++ b/include/linux/sound.h @@ -30,12 +30,12 @@ */ struct device; -extern int register_sound_special(struct file_operations *fops, int unit); -extern int register_sound_special_device(struct file_operations *fops, int unit, struct device *dev); -extern int register_sound_mixer(struct file_operations *fops, int dev); -extern int register_sound_midi(struct file_operations *fops, int dev); -extern int register_sound_dsp(struct file_operations *fops, int dev); -extern int register_sound_synth(struct file_operations *fops, int dev); +extern int register_sound_special(const struct file_operations *fops, int unit); +extern int register_sound_special_device(const struct file_operations *fops, int unit, struct device *dev); +extern int register_sound_mixer(const struct file_operations *fops, int dev); +extern int register_sound_midi(const struct file_operations *fops, int dev); +extern int register_sound_dsp(const struct file_operations *fops, int dev); +extern int register_sound_synth(const struct file_operations *fops, int dev); extern void unregister_sound_special(int unit); extern void unregister_sound_mixer(int unit); diff --git a/include/linux/sunrpc/stats.h b/include/linux/sunrpc/stats.h index 0d6ed3c8bdc4..d93c24b47f3f 100644 --- a/include/linux/sunrpc/stats.h +++ b/include/linux/sunrpc/stats.h @@ -50,7 +50,7 @@ struct proc_dir_entry * rpc_proc_register(struct rpc_stat *); void rpc_proc_unregister(const char *); void rpc_proc_zero(struct rpc_program *); struct proc_dir_entry * svc_proc_register(struct svc_stat *, - struct file_operations *); + const struct file_operations *); void svc_proc_unregister(const char *); void svc_seq_show(struct seq_file *, @@ -65,7 +65,7 @@ static inline void rpc_proc_unregister(const char *p) {} static inline void rpc_proc_zero(struct rpc_program *p) {} static inline struct proc_dir_entry *svc_proc_register(struct svc_stat *s, - struct file_operations *f) { return NULL; } + const struct file_operations *f) { return NULL; } static inline void svc_proc_unregister(const char *p) {} static inline void svc_seq_show(struct seq_file *seq, diff --git a/include/linux/usb.h b/include/linux/usb.h index 130d125fda12..e34e5e3dce52 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -615,7 +615,7 @@ extern struct bus_type usb_bus_type; */ struct usb_class_driver { char *name; - struct file_operations *fops; + const struct file_operations *fops; int minor_base; }; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 2275bfec5b68..af2d6155d3fe 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -75,7 +75,7 @@ struct video_device int minor; /* device ops + callbacks */ - struct file_operations *fops; + const struct file_operations *fops; void (*release)(struct video_device *vfd); diff --git a/include/sound/core.h b/include/sound/core.h index 144bdc2f217f..7f32c12b4a0a 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -186,7 +186,7 @@ struct snd_minor { int type; /* SNDRV_DEVICE_TYPE_XXX */ int card; /* card number */ int device; /* device number */ - struct file_operations *f_ops; /* file operations */ + const struct file_operations *f_ops; /* file operations */ void *private_data; /* private data for f_ops->open */ char name[0]; /* device name (keep at the end of structure) */ @@ -200,14 +200,14 @@ extern int snd_ecards_limit; void snd_request_card(int card); int snd_register_device(int type, struct snd_card *card, int dev, - struct file_operations *f_ops, void *private_data, + const struct file_operations *f_ops, void *private_data, const char *name); int snd_unregister_device(int type, struct snd_card *card, int dev); void *snd_lookup_minor_data(unsigned int minor, int type); #ifdef CONFIG_SND_OSSEMUL int snd_register_oss_device(int type, struct snd_card *card, int dev, - struct file_operations *f_ops, void *private_data, + const struct file_operations *f_ops, void *private_data, const char *name); int snd_unregister_oss_device(int type, struct snd_card *card, int dev); void *snd_lookup_oss_minor_data(unsigned int minor, int type); diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index aa4158be9900..cc673dd8433f 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -395,7 +395,7 @@ enum { */ struct rpc_filelist { char *name; - struct file_operations *i_fop; + const struct file_operations *i_fop; int mode; }; diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 790941e8af4d..dea529666d69 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c @@ -225,7 +225,7 @@ EXPORT_SYMBOL(rpc_print_iostats); * Register/unregister RPC proc files */ static inline struct proc_dir_entry * -do_register(const char *name, void *data, struct file_operations *fops) +do_register(const char *name, void *data, const struct file_operations *fops) { struct proc_dir_entry *ent; @@ -253,7 +253,7 @@ rpc_proc_unregister(const char *name) } struct proc_dir_entry * -svc_proc_register(struct svc_stat *statp, struct file_operations *fops) +svc_proc_register(struct svc_stat *statp, const struct file_operations *fops) { return do_register(statp->program->pg_name, statp, fops); } diff --git a/sound/core/init.c b/sound/core/init.c index ad68761abba1..5bb8a8b23d51 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -223,7 +223,8 @@ int snd_card_disconnect(struct snd_card *card) struct snd_monitor_file *mfile; struct file *file; struct snd_shutdown_f_ops *s_f_ops; - struct file_operations *f_ops, *old_f_ops; + struct file_operations *f_ops; + const struct file_operations *old_f_ops; int err; spin_lock(&card->files_lock); diff --git a/sound/core/sound.c b/sound/core/sound.c index 4d28e5212611..108e430b5036 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -137,7 +137,7 @@ static int snd_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); struct snd_minor *mptr = NULL; - struct file_operations *old_fops; + const struct file_operations *old_fops; int err = 0; if (minor >= ARRAY_SIZE(snd_minors)) @@ -240,7 +240,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev) * Retrurns zero if successful, or a negative error code on failure. */ int snd_register_device(int type, struct snd_card *card, int dev, - struct file_operations *f_ops, void *private_data, + const struct file_operations *f_ops, void *private_data, const char *name) { int minor; diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 4023d3b406de..9055c6de9587 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -95,7 +95,7 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) } int snd_register_oss_device(int type, struct snd_card *card, int dev, - struct file_operations *f_ops, void *private_data, + const struct file_operations *f_ops, void *private_data, const char *name) { int minor = snd_oss_kernel_minor(type, card, dev); diff --git a/sound/sound_core.c b/sound/sound_core.c index 394b53e20cb8..6f849720aef3 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -53,7 +53,7 @@ struct sound_unit { int unit_minor; - struct file_operations *unit_fops; + const struct file_operations *unit_fops; struct sound_unit *next; char name[32]; }; @@ -73,7 +73,7 @@ EXPORT_SYMBOL(sound_class); * join into it. Called with the lock asserted */ -static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, struct file_operations *fops, int index, int low, int top) +static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, const struct file_operations *fops, int index, int low, int top) { int n=low; @@ -153,7 +153,7 @@ static DEFINE_SPINLOCK(sound_loader_lock); * list. Acquires locks as needed */ -static int sound_insert_unit(struct sound_unit **list, struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode, struct device *dev) +static int sound_insert_unit(struct sound_unit **list, const struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode, struct device *dev) { struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL); int r; @@ -237,7 +237,7 @@ static struct sound_unit *chains[SOUND_STEP]; * a negative error code is returned. */ -int register_sound_special_device(struct file_operations *fops, int unit, +int register_sound_special_device(const struct file_operations *fops, int unit, struct device *dev) { const int chain = unit % SOUND_STEP; @@ -301,7 +301,7 @@ int register_sound_special_device(struct file_operations *fops, int unit, EXPORT_SYMBOL(register_sound_special_device); -int register_sound_special(struct file_operations *fops, int unit) +int register_sound_special(const struct file_operations *fops, int unit) { return register_sound_special_device(fops, unit, NULL); } @@ -318,7 +318,7 @@ EXPORT_SYMBOL(register_sound_special); * number is returned, on failure a negative error code is returned. */ -int register_sound_mixer(struct file_operations *fops, int dev) +int register_sound_mixer(const struct file_operations *fops, int dev) { return sound_insert_unit(&chains[0], fops, dev, 0, 128, "mixer", S_IRUSR | S_IWUSR, NULL); @@ -336,7 +336,7 @@ EXPORT_SYMBOL(register_sound_mixer); * number is returned, on failure a negative error code is returned. */ -int register_sound_midi(struct file_operations *fops, int dev) +int register_sound_midi(const struct file_operations *fops, int dev) { return sound_insert_unit(&chains[2], fops, dev, 2, 130, "midi", S_IRUSR | S_IWUSR, NULL); @@ -362,7 +362,7 @@ EXPORT_SYMBOL(register_sound_midi); * and will always allocate them as a matching pair - eg dsp3/audio3 */ -int register_sound_dsp(struct file_operations *fops, int dev) +int register_sound_dsp(const struct file_operations *fops, int dev) { return sound_insert_unit(&chains[3], fops, dev, 3, 131, "dsp", S_IWUSR | S_IRUSR, NULL); @@ -381,7 +381,7 @@ EXPORT_SYMBOL(register_sound_dsp); */ -int register_sound_synth(struct file_operations *fops, int dev) +int register_sound_synth(const struct file_operations *fops, int dev) { return sound_insert_unit(&chains[9], fops, dev, 9, 137, "synth", S_IRUSR | S_IWUSR, NULL); @@ -501,7 +501,7 @@ int soundcore_open(struct inode *inode, struct file *file) int chain; int unit = iminor(inode); struct sound_unit *s; - struct file_operations *new_fops = NULL; + const struct file_operations *new_fops = NULL; chain=unit&0x0F; if(chain==4 || chain==5) /* dsp/audio/dsp16 */ @@ -540,7 +540,7 @@ int soundcore_open(struct inode *inode, struct file *file) * switching ->f_op in the first place. */ int err = 0; - struct file_operations *old_fops = file->f_op; + const struct file_operations *old_fops = file->f_op; file->f_op = new_fops; spin_unlock(&sound_loader_lock); if(file->f_op->open) -- cgit v1.2.3-59-g8ed1b From 4b6f5d20b04dcbc3d888555522b90ba6d36c4106 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Tue, 28 Mar 2006 01:56:42 -0800 Subject: [PATCH] Make most file operations structs in fs/ const This is a conversion to make the various file_operations structs in fs/ const. Basically a regexp job, with a few manual fixups The goal is both to increase correctness (harder to accidentally write to shared datastructures) and reducing the false sharing of cachelines with things that get dirty in .data (while .rodata is nicely read only and thus cache clean) Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/ibmasm/ibmasmfs.c | 2 +- fs/9p/v9fs_vfs.h | 4 ++-- fs/9p/vfs_dir.c | 2 +- fs/9p/vfs_file.c | 2 +- fs/adfs/adfs.h | 4 ++-- fs/adfs/dir.c | 2 +- fs/adfs/file.c | 2 +- fs/affs/affs.h | 6 +++--- fs/affs/dir.c | 2 +- fs/affs/file.c | 2 +- fs/afs/dir.c | 2 +- fs/afs/internal.h | 4 ++-- fs/afs/mntpt.c | 2 +- fs/afs/proc.c | 10 +++++----- fs/autofs/autofs_i.h | 2 +- fs/autofs/root.c | 2 +- fs/autofs4/autofs_i.h | 4 ++-- fs/autofs4/root.c | 4 ++-- fs/bad_inode.c | 2 +- fs/befs/linuxvfs.c | 2 +- fs/bfs/bfs.h | 4 ++-- fs/bfs/dir.c | 2 +- fs/bfs/file.c | 2 +- fs/binfmt_misc.c | 6 +++--- fs/block_dev.c | 2 +- fs/char_dev.c | 2 +- fs/cifs/cifsfs.c | 10 +++++----- fs/cifs/cifsfs.h | 10 +++++----- fs/coda/dir.c | 2 +- fs/coda/file.c | 2 +- fs/coda/pioctl.c | 2 +- fs/coda/psdev.c | 2 +- fs/configfs/configfs_internal.h | 6 +++--- fs/configfs/dir.c | 2 +- fs/configfs/file.c | 2 +- fs/cramfs/inode.c | 4 ++-- fs/debugfs/file.c | 4 ++-- fs/devfs/base.c | 12 ++++++------ fs/efs/dir.c | 2 +- fs/eventpoll.c | 2 +- fs/ext2/dir.c | 2 +- fs/ext2/ext2.h | 6 +++--- fs/ext2/file.c | 4 ++-- fs/ext3/dir.c | 2 +- fs/ext3/file.c | 2 +- fs/fat/dir.c | 2 +- fs/fat/file.c | 2 +- fs/fifo.c | 2 +- fs/freevxfs/vxfs_extern.h | 2 +- fs/freevxfs/vxfs_lookup.c | 2 +- fs/fuse/dev.c | 2 +- fs/fuse/dir.c | 2 +- fs/fuse/file.c | 6 +++--- fs/fuse/fuse_i.h | 2 +- fs/hfs/dir.c | 2 +- fs/hfs/hfs_fs.h | 2 +- fs/hfs/inode.c | 4 ++-- fs/hfsplus/dir.c | 2 +- fs/hfsplus/inode.c | 2 +- fs/hostfs/hostfs_kern.c | 4 ++-- fs/hpfs/dir.c | 2 +- fs/hpfs/file.c | 2 +- fs/hpfs/hpfs_fn.h | 4 ++-- fs/hppfs/hppfs_kern.c | 4 ++-- fs/hugetlbfs/inode.c | 4 ++-- fs/inotify.c | 2 +- fs/isofs/dir.c | 2 +- fs/isofs/isofs.h | 2 +- fs/jffs/inode-v23.c | 8 ++++---- fs/jffs2/dir.c | 2 +- fs/jffs2/file.c | 2 +- fs/jffs2/os-linux.h | 4 ++-- fs/jfs/file.c | 2 +- fs/jfs/jfs_inode.h | 4 ++-- fs/jfs/namei.c | 2 +- fs/libfs.c | 2 +- fs/minix/dir.c | 2 +- fs/minix/file.c | 2 +- fs/minix/minix.h | 4 ++-- fs/ncpfs/dir.c | 2 +- fs/ncpfs/file.c | 2 +- fs/nfs/dir.c | 2 +- fs/nfs/file.c | 2 +- fs/nfsd/nfsctl.c | 4 ++-- fs/nfsd/stats.c | 2 +- fs/ntfs/dir.c | 2 +- fs/ntfs/file.c | 4 ++-- fs/ntfs/ntfs.h | 6 +++--- fs/ocfs2/dlmglue.c | 2 +- fs/ocfs2/file.c | 4 ++-- fs/ocfs2/file.h | 4 ++-- fs/openpromfs/inode.c | 6 +++--- fs/pipe.c | 6 +++--- fs/proc/kcore.c | 2 +- fs/proc/kmsg.c | 2 +- fs/proc/vmcore.c | 2 +- fs/qnx4/dir.c | 2 +- fs/qnx4/file.c | 2 +- fs/ramfs/file-mmu.c | 2 +- fs/ramfs/file-nommu.c | 2 +- fs/ramfs/internal.h | 2 +- fs/read_write.c | 2 +- fs/reiserfs/dir.c | 2 +- fs/reiserfs/file.c | 2 +- fs/reiserfs/procfs.c | 2 +- fs/romfs/inode.c | 2 +- fs/smbfs/dir.c | 2 +- fs/smbfs/file.c | 2 +- fs/smbfs/proto.h | 4 ++-- fs/sysfs/bin.c | 2 +- fs/sysfs/dir.c | 2 +- fs/sysfs/file.c | 2 +- fs/sysfs/sysfs.h | 6 +++--- fs/sysv/dir.c | 2 +- fs/sysv/file.c | 2 +- fs/sysv/sysv.h | 4 ++-- fs/udf/dir.c | 2 +- fs/udf/file.c | 2 +- fs/udf/udfdecl.h | 4 ++-- fs/ufs/dir.c | 2 +- fs/ufs/file.c | 2 +- fs/xfs/linux-2.6/xfs_file.c | 6 +++--- fs/xfs/linux-2.6/xfs_iops.h | 6 +++--- include/linux/coda_linux.h | 6 +++--- include/linux/crash_dump.h | 2 +- include/linux/efs_fs.h | 2 +- include/linux/ext3_fs.h | 4 ++-- include/linux/fs.h | 20 ++++++++++---------- include/linux/hugetlb.h | 2 +- include/linux/msdos_fs.h | 4 ++-- include/linux/ncp_fs.h | 4 ++-- include/linux/nfs_fs.h | 4 ++-- include/linux/proc_fs.h | 6 +++--- include/linux/qnx4_fs.h | 4 ++-- include/linux/ramfs.h | 2 +- include/linux/reiserfs_fs.h | 4 ++-- include/linux/ufs_fs.h | 4 ++-- net/nonet.c | 2 +- net/socket.c | 2 +- 139 files changed, 225 insertions(+), 225 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index 5c550fcac2c4..26a230b6ff80 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c @@ -101,7 +101,7 @@ static struct super_operations ibmasmfs_s_ops = { .drop_inode = generic_delete_inode, }; -static struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations; +static const struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations; static struct file_system_type ibmasmfs_type = { .owner = THIS_MODULE, diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 43c9f7de0314..f867b8d3e973 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h @@ -39,8 +39,8 @@ extern struct file_system_type v9fs_fs_type; extern struct address_space_operations v9fs_addr_operations; -extern struct file_operations v9fs_file_operations; -extern struct file_operations v9fs_dir_operations; +extern const struct file_operations v9fs_file_operations; +extern const struct file_operations v9fs_dir_operations; extern struct dentry_operations v9fs_dentry_operations; struct inode *v9fs_get_inode(struct super_block *sb, int mode); diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 766f11f1215c..e32d5971039b 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -204,7 +204,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) return 0; } -struct file_operations v9fs_dir_operations = { +const struct file_operations v9fs_dir_operations = { .read = generic_read_dir, .readdir = v9fs_dir_readdir, .open = v9fs_file_open, diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 59e744163407..083dcfcd158e 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -266,7 +266,7 @@ v9fs_file_write(struct file *filp, const char __user * data, return total; } -struct file_operations v9fs_file_operations = { +const struct file_operations v9fs_file_operations = { .llseek = generic_file_llseek, .read = v9fs_file_read, .write = v9fs_file_write, diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index f6cd01352cc8..29217ff36d44 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h @@ -85,7 +85,7 @@ void __adfs_error(struct super_block *sb, const char *function, /* dir_*.c */ extern struct inode_operations adfs_dir_inode_operations; -extern struct file_operations adfs_dir_operations; +extern const struct file_operations adfs_dir_operations; extern struct dentry_operations adfs_dentry_operations; extern struct adfs_dir_ops adfs_f_dir_ops; extern struct adfs_dir_ops adfs_fplus_dir_ops; @@ -94,7 +94,7 @@ extern int adfs_dir_update(struct super_block *sb, struct object_info *obj); /* file.c */ extern struct inode_operations adfs_file_inode_operations; -extern struct file_operations adfs_file_operations; +extern const struct file_operations adfs_file_operations; static inline __u32 signed_asl(__u32 val, signed int shift) { diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 0b4c3a028076..7b075fc397da 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c @@ -196,7 +196,7 @@ out: return ret; } -struct file_operations adfs_dir_operations = { +const struct file_operations adfs_dir_operations = { .read = generic_read_dir, .readdir = adfs_readdir, .fsync = file_fsync, diff --git a/fs/adfs/file.c b/fs/adfs/file.c index 6af10885f9d6..1014b9f2117b 100644 --- a/fs/adfs/file.c +++ b/fs/adfs/file.c @@ -25,7 +25,7 @@ #include "adfs.h" -struct file_operations adfs_file_operations = { +const struct file_operations adfs_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, .mmap = generic_file_mmap, diff --git a/fs/affs/affs.h b/fs/affs/affs.h index 0c6799f2137a..a43a876742b8 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h @@ -192,9 +192,9 @@ extern void affs_dir_truncate(struct inode *); extern struct inode_operations affs_file_inode_operations; extern struct inode_operations affs_dir_inode_operations; extern struct inode_operations affs_symlink_inode_operations; -extern struct file_operations affs_file_operations; -extern struct file_operations affs_file_operations_ofs; -extern struct file_operations affs_dir_operations; +extern const struct file_operations affs_file_operations; +extern const struct file_operations affs_file_operations_ofs; +extern const struct file_operations affs_dir_operations; extern struct address_space_operations affs_symlink_aops; extern struct address_space_operations affs_aops; extern struct address_space_operations affs_aops_ofs; diff --git a/fs/affs/dir.c b/fs/affs/dir.c index 548efd0ee98c..5d9649fa1814 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c @@ -17,7 +17,7 @@ static int affs_readdir(struct file *, void *, filldir_t); -struct file_operations affs_dir_operations = { +const struct file_operations affs_dir_operations = { .read = generic_read_dir, .readdir = affs_readdir, .fsync = file_fsync, diff --git a/fs/affs/file.c b/fs/affs/file.c index f72fb776ecdf..7076262af39b 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -25,7 +25,7 @@ static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext); static int affs_file_open(struct inode *inode, struct file *filp); static int affs_file_release(struct inode *inode, struct file *filp); -struct file_operations affs_file_operations = { +const struct file_operations affs_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, .write = generic_file_write, diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 5c61c24dab2a..a6dff6a4f204 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -32,7 +32,7 @@ static int afs_d_delete(struct dentry *dentry); static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, loff_t fpos, ino_t ino, unsigned dtype); -struct file_operations afs_dir_file_operations = { +const struct file_operations afs_dir_file_operations = { .open = afs_dir_open, .readdir = afs_dir_readdir, }; diff --git a/fs/afs/internal.h b/fs/afs/internal.h index ab8f87c66319..72febdf9a35a 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -64,7 +64,7 @@ extern struct cachefs_index_def afs_cache_cell_index_def; * dir.c */ extern struct inode_operations afs_dir_inode_operations; -extern struct file_operations afs_dir_file_operations; +extern const struct file_operations afs_dir_file_operations; /* * file.c @@ -105,7 +105,7 @@ extern struct cachefs_netfs afs_cache_netfs; * mntpt.c */ extern struct inode_operations afs_mntpt_inode_operations; -extern struct file_operations afs_mntpt_file_operations; +extern const struct file_operations afs_mntpt_file_operations; extern struct afs_timer afs_mntpt_expiry_timer; extern struct afs_timer_ops afs_mntpt_expiry_timer_ops; extern unsigned long afs_mntpt_expiry_timeout; diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 31ee06590de5..4e6eeb59b83c 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -32,7 +32,7 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir, static int afs_mntpt_open(struct inode *inode, struct file *file); static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); -struct file_operations afs_mntpt_file_operations = { +const struct file_operations afs_mntpt_file_operations = { .open = afs_mntpt_open, }; diff --git a/fs/afs/proc.c b/fs/afs/proc.c index 9c81b8f7eef0..101d21b6c037 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c @@ -37,7 +37,7 @@ static struct seq_operations afs_proc_cells_ops = { .show = afs_proc_cells_show, }; -static struct file_operations afs_proc_cells_fops = { +static const struct file_operations afs_proc_cells_fops = { .open = afs_proc_cells_open, .read = seq_read, .write = afs_proc_cells_write, @@ -53,7 +53,7 @@ static ssize_t afs_proc_rootcell_write(struct file *file, const char __user *buf, size_t size, loff_t *_pos); -static struct file_operations afs_proc_rootcell_fops = { +static const struct file_operations afs_proc_rootcell_fops = { .open = afs_proc_rootcell_open, .read = afs_proc_rootcell_read, .write = afs_proc_rootcell_write, @@ -77,7 +77,7 @@ static struct seq_operations afs_proc_cell_volumes_ops = { .show = afs_proc_cell_volumes_show, }; -static struct file_operations afs_proc_cell_volumes_fops = { +static const struct file_operations afs_proc_cell_volumes_fops = { .open = afs_proc_cell_volumes_open, .read = seq_read, .llseek = seq_lseek, @@ -101,7 +101,7 @@ static struct seq_operations afs_proc_cell_vlservers_ops = { .show = afs_proc_cell_vlservers_show, }; -static struct file_operations afs_proc_cell_vlservers_fops = { +static const struct file_operations afs_proc_cell_vlservers_fops = { .open = afs_proc_cell_vlservers_open, .read = seq_read, .llseek = seq_lseek, @@ -124,7 +124,7 @@ static struct seq_operations afs_proc_cell_servers_ops = { .show = afs_proc_cell_servers_show, }; -static struct file_operations afs_proc_cell_servers_fops = { +static const struct file_operations afs_proc_cell_servers_fops = { .open = afs_proc_cell_servers_open, .read = seq_read, .llseek = seq_lseek, diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 990c28da5aec..a62327f1bdff 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -146,7 +146,7 @@ struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info extern struct inode_operations autofs_root_inode_operations; extern struct inode_operations autofs_symlink_inode_operations; -extern struct file_operations autofs_root_operations; +extern const struct file_operations autofs_root_operations; /* Initializing function */ diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 870e2cf33016..9cac08d6a873 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -26,7 +26,7 @@ static int autofs_root_rmdir(struct inode *,struct dentry *); static int autofs_root_mkdir(struct inode *,struct dentry *,int); static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long); -struct file_operations autofs_root_operations = { +const struct file_operations autofs_root_operations = { .read = generic_read_dir, .readdir = autofs_root_readdir, .ioctl = autofs_root_ioctl, diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index c70204a61268..57c4903614e5 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -176,8 +176,8 @@ extern struct inode_operations autofs4_dir_inode_operations; extern struct inode_operations autofs4_root_inode_operations; extern struct inode_operations autofs4_indirect_root_inode_operations; extern struct inode_operations autofs4_direct_root_inode_operations; -extern struct file_operations autofs4_dir_operations; -extern struct file_operations autofs4_root_operations; +extern const struct file_operations autofs4_dir_operations; +extern const struct file_operations autofs4_root_operations; /* Initializing function */ diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index c8fe43a475e2..84e030c8ddd0 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -32,7 +32,7 @@ static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t fil static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); static void *autofs4_follow_link(struct dentry *, struct nameidata *); -struct file_operations autofs4_root_operations = { +const struct file_operations autofs4_root_operations = { .open = dcache_dir_open, .release = dcache_dir_close, .read = generic_read_dir, @@ -40,7 +40,7 @@ struct file_operations autofs4_root_operations = { .ioctl = autofs4_root_ioctl, }; -struct file_operations autofs4_dir_operations = { +const struct file_operations autofs4_dir_operations = { .open = autofs4_dir_open, .release = autofs4_dir_close, .read = generic_read_dir, diff --git a/fs/bad_inode.c b/fs/bad_inode.c index e172180a1d8c..80599ae33966 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -22,7 +22,7 @@ static int return_EIO(void) #define EIO_ERROR ((void *) (return_EIO)) -static struct file_operations bad_file_ops = +static const struct file_operations bad_file_ops = { .llseek = EIO_ERROR, .aio_read = EIO_ERROR, diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 044a59587829..68ebd10f345d 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -64,7 +64,7 @@ static const struct super_operations befs_sops = { /* slab cache for befs_inode_info objects */ static kmem_cache_t *befs_inode_cachep; -static struct file_operations befs_dir_operations = { +static const struct file_operations befs_dir_operations = { .read = generic_read_dir, .readdir = befs_readdir, }; diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h index 1fbc53f14aba..9d791004b21c 100644 --- a/fs/bfs/bfs.h +++ b/fs/bfs/bfs.h @@ -49,11 +49,11 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode) /* file.c */ extern struct inode_operations bfs_file_inops; -extern struct file_operations bfs_file_operations; +extern const struct file_operations bfs_file_operations; extern struct address_space_operations bfs_aops; /* dir.c */ extern struct inode_operations bfs_dir_inops; -extern struct file_operations bfs_dir_operations; +extern const struct file_operations bfs_dir_operations; #endif /* _FS_BFS_BFS_H */ diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 5af928fa0449..26fad9621738 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -70,7 +70,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) return 0; } -struct file_operations bfs_dir_operations = { +const struct file_operations bfs_dir_operations = { .read = generic_read_dir, .readdir = bfs_readdir, .fsync = file_fsync, diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 807723b65daf..d83cd74a2e4e 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -17,7 +17,7 @@ #define dprintf(x...) #endif -struct file_operations bfs_file_operations = { +const struct file_operations bfs_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, .write = generic_file_write, diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 6a7b730c206b..d73d75591a39 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -600,7 +600,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer, return count; } -static struct file_operations bm_entry_operations = { +static const struct file_operations bm_entry_operations = { .read = bm_entry_read, .write = bm_entry_write, }; @@ -668,7 +668,7 @@ out: return count; } -static struct file_operations bm_register_operations = { +static const struct file_operations bm_register_operations = { .write = bm_register_write, }; @@ -715,7 +715,7 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer, return count; } -static struct file_operations bm_status_operations = { +static const struct file_operations bm_status_operations = { .read = bm_status_read, .write = bm_status_write, }; diff --git a/fs/block_dev.c b/fs/block_dev.c index 17c76182f389..af88c43043d5 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1087,7 +1087,7 @@ struct address_space_operations def_blk_aops = { .direct_IO = blkdev_direct_IO, }; -struct file_operations def_blk_fops = { +const struct file_operations def_blk_fops = { .open = blkdev_open, .release = blkdev_close, .llseek = block_llseek, diff --git a/fs/char_dev.c b/fs/char_dev.c index b53dffa46bac..4e1b849f912f 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -406,7 +406,7 @@ static void cdev_purge(struct cdev *cdev) * is contain the open that then fills in the correct operations * depending on the special file... */ -struct file_operations def_chr_fops = { +const struct file_operations def_chr_fops = { .open = chrdev_open, }; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 6b99b51d6694..4bbc544857bc 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -583,7 +583,7 @@ struct inode_operations cifs_symlink_inode_ops = { #endif }; -struct file_operations cifs_file_ops = { +const struct file_operations cifs_file_ops = { .read = do_sync_read, .write = do_sync_write, .readv = generic_file_readv, @@ -607,7 +607,7 @@ struct file_operations cifs_file_ops = { #endif /* CONFIG_CIFS_EXPERIMENTAL */ }; -struct file_operations cifs_file_direct_ops = { +const struct file_operations cifs_file_direct_ops = { /* no mmap, no aio, no readv - BB reevaluate whether they can be done with directio, no cache */ .read = cifs_user_read, @@ -626,7 +626,7 @@ struct file_operations cifs_file_direct_ops = { .dir_notify = cifs_dir_notify, #endif /* CONFIG_CIFS_EXPERIMENTAL */ }; -struct file_operations cifs_file_nobrl_ops = { +const struct file_operations cifs_file_nobrl_ops = { .read = do_sync_read, .write = do_sync_write, .readv = generic_file_readv, @@ -649,7 +649,7 @@ struct file_operations cifs_file_nobrl_ops = { #endif /* CONFIG_CIFS_EXPERIMENTAL */ }; -struct file_operations cifs_file_direct_nobrl_ops = { +const struct file_operations cifs_file_direct_nobrl_ops = { /* no mmap, no aio, no readv - BB reevaluate whether they can be done with directio, no cache */ .read = cifs_user_read, @@ -668,7 +668,7 @@ struct file_operations cifs_file_direct_nobrl_ops = { #endif /* CONFIG_CIFS_EXPERIMENTAL */ }; -struct file_operations cifs_dir_ops = { +const struct file_operations cifs_dir_ops = { .readdir = cifs_readdir, .release = cifs_closedir, .read = generic_read_dir, diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 821a8eb22559..74f405ae4da3 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -61,10 +61,10 @@ extern struct inode_operations cifs_file_inode_ops; extern struct inode_operations cifs_symlink_inode_ops; /* Functions related to files and directories */ -extern struct file_operations cifs_file_ops; -extern struct file_operations cifs_file_direct_ops; /* if directio mount */ -extern struct file_operations cifs_file_nobrl_ops; -extern struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */ +extern const struct file_operations cifs_file_ops; +extern const struct file_operations cifs_file_direct_ops; /* if directio mount */ +extern const struct file_operations cifs_file_nobrl_ops; +extern const struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */ extern int cifs_open(struct inode *inode, struct file *file); extern int cifs_close(struct inode *inode, struct file *file); extern int cifs_closedir(struct inode *inode, struct file *file); @@ -76,7 +76,7 @@ extern int cifs_lock(struct file *, int, struct file_lock *); extern int cifs_fsync(struct file *, struct dentry *, int); extern int cifs_flush(struct file *); extern int cifs_file_mmap(struct file * , struct vm_area_struct *); -extern struct file_operations cifs_dir_ops; +extern const struct file_operations cifs_dir_ops; extern int cifs_dir_open(struct inode *inode, struct file *file); extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); extern int cifs_dir_notify(struct file *, unsigned long arg); diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 54f76de8a686..71f2ea632e53 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -82,7 +82,7 @@ struct inode_operations coda_dir_inode_operations = .setattr = coda_setattr, }; -struct file_operations coda_dir_operations = { +const struct file_operations coda_dir_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = coda_readdir, diff --git a/fs/coda/file.c b/fs/coda/file.c index 146a991d6eb5..7c2642431fa5 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -288,7 +288,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync) return err; } -struct file_operations coda_file_operations = { +const struct file_operations coda_file_operations = { .llseek = generic_file_llseek, .read = coda_file_read, .write = coda_file_write, diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 127714936c66..214822be87bd 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -36,7 +36,7 @@ struct inode_operations coda_ioctl_inode_operations = .setattr = coda_setattr, }; -struct file_operations coda_ioctl_operations = { +const struct file_operations coda_ioctl_operations = { .owner = THIS_MODULE, .ioctl = coda_pioctl, }; diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 98c74fe2e139..6c6771db36da 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -342,7 +342,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file) } -static struct file_operations coda_psdev_fops = { +static const struct file_operations coda_psdev_fops = { .owner = THIS_MODULE, .read = coda_psdev_read, .write = coda_psdev_write, diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h index f70e46951b37..3f4ff7a242b9 100644 --- a/fs/configfs/configfs_internal.h +++ b/fs/configfs/configfs_internal.h @@ -72,9 +72,9 @@ extern void configfs_release_fs(void); extern struct rw_semaphore configfs_rename_sem; extern struct super_block * configfs_sb; -extern struct file_operations configfs_dir_operations; -extern struct file_operations configfs_file_operations; -extern struct file_operations bin_fops; +extern const struct file_operations configfs_dir_operations; +extern const struct file_operations configfs_file_operations; +extern const struct file_operations bin_fops; extern struct inode_operations configfs_dir_inode_operations; extern struct inode_operations configfs_symlink_inode_operations; diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index ca60e3abef45..8ed9b06a9828 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -1027,7 +1027,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) return offset; } -struct file_operations configfs_dir_operations = { +const struct file_operations configfs_dir_operations = { .open = configfs_dir_open, .release = configfs_dir_close, .llseek = configfs_dir_lseek, diff --git a/fs/configfs/file.c b/fs/configfs/file.c index 3921920d8716..f499803743e0 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c @@ -322,7 +322,7 @@ static int configfs_release(struct inode * inode, struct file * filp) return 0; } -struct file_operations configfs_file_operations = { +const struct file_operations configfs_file_operations = { .read = configfs_read_file, .write = configfs_write_file, .llseek = generic_file_llseek, diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index acc1b2c10a86..9efcc3a164e8 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -29,7 +29,7 @@ static struct super_operations cramfs_ops; static struct inode_operations cramfs_dir_inode_operations; -static struct file_operations cramfs_directory_operations; +static const struct file_operations cramfs_directory_operations; static struct address_space_operations cramfs_aops; static DEFINE_MUTEX(read_mutex); @@ -512,7 +512,7 @@ static struct address_space_operations cramfs_aops = { /* * A directory can only readdir */ -static struct file_operations cramfs_directory_operations = { +static const struct file_operations cramfs_directory_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = cramfs_readdir, diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 40c4fc973fad..66a505422e5c 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -39,7 +39,7 @@ static int default_open(struct inode *inode, struct file *file) return 0; } -struct file_operations debugfs_file_operations = { +const struct file_operations debugfs_file_operations = { .read = default_read_file, .write = default_write_file, .open = default_open, @@ -213,7 +213,7 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf, return count; } -static struct file_operations fops_bool = { +static const struct file_operations fops_bool = { .read = read_file_bool, .write = write_file_bool, .open = default_open, diff --git a/fs/devfs/base.c b/fs/devfs/base.c index b621521e09d4..52f5059c4f31 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -856,14 +856,14 @@ static int devfsd_close(struct inode *inode, struct file *file); #ifdef CONFIG_DEVFS_DEBUG static ssize_t stat_read(struct file *file, char __user *buf, size_t len, loff_t * ppos); -static struct file_operations stat_fops = { +static const struct file_operations stat_fops = { .open = nonseekable_open, .read = stat_read, }; #endif /* Devfs daemon file operations */ -static struct file_operations devfsd_fops = { +static const struct file_operations devfsd_fops = { .open = nonseekable_open, .read = devfsd_read, .ioctl = devfsd_ioctl, @@ -1842,8 +1842,8 @@ static int try_modload(struct devfs_entry *parent, struct fs_info *fs_info, static struct inode_operations devfs_iops; static struct inode_operations devfs_dir_iops; -static struct file_operations devfs_fops; -static struct file_operations devfs_dir_fops; +static const struct file_operations devfs_fops; +static const struct file_operations devfs_dir_fops; static struct inode_operations devfs_symlink_iops; static int devfs_notify_change(struct dentry *dentry, struct iattr *iattr) @@ -2061,11 +2061,11 @@ static int devfs_open(struct inode *inode, struct file *file) return err; } /* End Function devfs_open */ -static struct file_operations devfs_fops = { +static const struct file_operations devfs_fops = { .open = devfs_open, }; -static struct file_operations devfs_dir_fops = { +static const struct file_operations devfs_dir_fops = { .read = generic_read_dir, .readdir = devfs_readdir, }; diff --git a/fs/efs/dir.c b/fs/efs/dir.c index 777c614ff360..17f5b2d3c16a 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c @@ -10,7 +10,7 @@ static int efs_readdir(struct file *, void *, filldir_t); -struct file_operations efs_dir_operations = { +const struct file_operations efs_dir_operations = { .read = generic_read_dir, .readdir = efs_readdir, }; diff --git a/fs/eventpoll.c b/fs/eventpoll.c index e067a06c6464..242fe1a66ce5 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -290,7 +290,7 @@ static kmem_cache_t *pwq_cache __read_mostly; static struct vfsmount *eventpoll_mnt __read_mostly; /* File callbacks that implement the eventpoll file behaviour */ -static struct file_operations eventpoll_fops = { +static const struct file_operations eventpoll_fops = { .release = ep_eventpoll_close, .poll = ep_eventpoll_poll }; diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 0165388c425c..d672aa9f4061 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -658,7 +658,7 @@ not_empty: return 0; } -struct file_operations ext2_dir_operations = { +const struct file_operations ext2_dir_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = ext2_readdir, diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 11035ac7986f..9f74a62be555 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -154,12 +154,12 @@ extern void ext2_write_super (struct super_block *); */ /* dir.c */ -extern struct file_operations ext2_dir_operations; +extern const struct file_operations ext2_dir_operations; /* file.c */ extern struct inode_operations ext2_file_inode_operations; -extern struct file_operations ext2_file_operations; -extern struct file_operations ext2_xip_file_operations; +extern const struct file_operations ext2_file_operations; +extern const struct file_operations ext2_xip_file_operations; /* inode.c */ extern struct address_space_operations ext2_aops; diff --git a/fs/ext2/file.c b/fs/ext2/file.c index a484412fc782..509cceca04db 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c @@ -39,7 +39,7 @@ static int ext2_release_file (struct inode * inode, struct file * filp) * We have mostly NULL's here: the current defaults are ok for * the ext2 filesystem. */ -struct file_operations ext2_file_operations = { +const struct file_operations ext2_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, .write = generic_file_write, @@ -56,7 +56,7 @@ struct file_operations ext2_file_operations = { }; #ifdef CONFIG_EXT2_FS_XIP -struct file_operations ext2_xip_file_operations = { +const struct file_operations ext2_xip_file_operations = { .llseek = generic_file_llseek, .read = xip_file_read, .write = xip_file_write, diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 38bd3f6ec147..f37528ed222e 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -39,7 +39,7 @@ static int ext3_dx_readdir(struct file * filp, static int ext3_release_dir (struct inode * inode, struct file * filp); -struct file_operations ext3_dir_operations = { +const struct file_operations ext3_dir_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = ext3_readdir, /* we take BKL. needed?*/ diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 59098ea56711..783a796220bb 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c @@ -105,7 +105,7 @@ force_commit: return ret; } -struct file_operations ext3_file_operations = { +const struct file_operations ext3_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, .write = do_sync_write, diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 4095bc149eb1..698b85bb1dd4 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -741,7 +741,7 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp, return ret; } -struct file_operations fat_dir_operations = { +const struct file_operations fat_dir_operations = { .read = generic_read_dir, .readdir = fat_readdir, .ioctl = fat_dir_ioctl, diff --git a/fs/fat/file.c b/fs/fat/file.c index 88aa1ae13f9f..1ee25232e6af 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -112,7 +112,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, } } -struct file_operations fat_file_operations = { +const struct file_operations fat_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, .write = do_sync_write, diff --git a/fs/fifo.c b/fs/fifo.c index d13fcd3ec803..889f722ee36d 100644 --- a/fs/fifo.c +++ b/fs/fifo.c @@ -145,6 +145,6 @@ err_nocleanup: * is contain the open that then fills in the correct operations * depending on the access mode of the file... */ -struct file_operations def_fifo_fops = { +const struct file_operations def_fifo_fops = { .open = fifo_open, /* will set read or write pipe_fops */ }; diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index 927acf70c591..1cf1fe8466a2 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h @@ -63,7 +63,7 @@ extern void vxfs_clear_inode(struct inode *); /* vxfs_lookup.c */ extern struct inode_operations vxfs_dir_inode_ops; -extern struct file_operations vxfs_dir_operations; +extern const struct file_operations vxfs_dir_operations; /* vxfs_olt.c */ extern int vxfs_read_olt(struct super_block *, u_long); diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index 554eb455722c..29cce456c7ce 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c @@ -56,7 +56,7 @@ struct inode_operations vxfs_dir_inode_ops = { .lookup = vxfs_lookup, }; -struct file_operations vxfs_dir_operations = { +const struct file_operations vxfs_dir_operations = { .readdir = vxfs_readdir, }; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 0c9a2ee54c91..23d1f52eb1b8 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -922,7 +922,7 @@ static int fuse_dev_release(struct inode *inode, struct file *file) return 0; } -struct file_operations fuse_dev_operations = { +const struct file_operations fuse_dev_operations = { .owner = THIS_MODULE, .llseek = no_llseek, .read = fuse_dev_read, diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index c72a8a97935c..256355b80256 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1170,7 +1170,7 @@ static struct inode_operations fuse_dir_inode_operations = { .removexattr = fuse_removexattr, }; -static struct file_operations fuse_dir_operations = { +static const struct file_operations fuse_dir_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = fuse_readdir, diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 6f05379b0a0d..975f2697e866 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -12,7 +12,7 @@ #include #include -static struct file_operations fuse_direct_io_file_operations; +static const struct file_operations fuse_direct_io_file_operations; static int fuse_send_open(struct inode *inode, struct file *file, int isdir, struct fuse_open_out *outargp) @@ -611,7 +611,7 @@ static int fuse_set_page_dirty(struct page *page) return 0; } -static struct file_operations fuse_file_operations = { +static const struct file_operations fuse_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, .write = generic_file_write, @@ -623,7 +623,7 @@ static struct file_operations fuse_file_operations = { .sendfile = generic_file_sendfile, }; -static struct file_operations fuse_direct_io_file_operations = { +static const struct file_operations fuse_direct_io_file_operations = { .llseek = generic_file_llseek, .read = fuse_direct_read, .write = fuse_direct_write, diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 4a83adfec968..a16a04fcf41e 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -346,7 +346,7 @@ static inline u64 get_node_id(struct inode *inode) } /** Device operations */ -extern struct file_operations fuse_dev_operations; +extern const struct file_operations fuse_dev_operations; /** * This is the single global spinlock which protects FUSE's structures diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index 534e5a7480ef..7cd8cc03aea7 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c @@ -313,7 +313,7 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry, return res; } -struct file_operations hfs_dir_operations = { +const struct file_operations hfs_dir_operations = { .read = generic_read_dir, .readdir = hfs_readdir, .llseek = generic_file_llseek, diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index 18ce47ab1b71..3ed8663a8db1 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -169,7 +169,7 @@ extern int hfs_cat_move(u32, struct inode *, struct qstr *, extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qstr *); /* dir.c */ -extern struct file_operations hfs_dir_operations; +extern const struct file_operations hfs_dir_operations; extern struct inode_operations hfs_dir_inode_operations; /* extent.c */ diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 2c564701724f..2d4ced22201b 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -17,7 +17,7 @@ #include "hfs_fs.h" #include "btree.h" -static struct file_operations hfs_file_operations; +static const struct file_operations hfs_file_operations; static struct inode_operations hfs_file_inode_operations; /*================ Variable-like macros ================*/ @@ -601,7 +601,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr) } -static struct file_operations hfs_file_operations = { +static const struct file_operations hfs_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, .write = generic_file_write, diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 01a6fe3a395c..1f9ece0de326 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -483,7 +483,7 @@ struct inode_operations hfsplus_dir_inode_operations = { .rename = hfsplus_rename, }; -struct file_operations hfsplus_dir_operations = { +const struct file_operations hfsplus_dir_operations = { .read = generic_read_dir, .readdir = hfsplus_readdir, .ioctl = hfsplus_ioctl, diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 9fbe4d2aeece..acf66dba3e01 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -280,7 +280,7 @@ static struct inode_operations hfsplus_file_inode_operations = { .listxattr = hfsplus_listxattr, }; -static struct file_operations hfsplus_file_operations = { +static const struct file_operations hfsplus_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, .write = generic_file_write, diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index b3ad0bd0312f..bf0f8e16e433 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -384,7 +384,7 @@ int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync); } -static struct file_operations hostfs_file_fops = { +static const struct file_operations hostfs_file_fops = { .llseek = generic_file_llseek, .read = generic_file_read, .sendfile = generic_file_sendfile, @@ -399,7 +399,7 @@ static struct file_operations hostfs_file_fops = { .fsync = hostfs_fsync, }; -static struct file_operations hostfs_dir_fops = { +static const struct file_operations hostfs_dir_fops = { .llseek = generic_file_llseek, .readdir = hostfs_readdir, .read = generic_read_dir, diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 5591f9623aa2..ecc9180645ae 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c @@ -310,7 +310,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name return ERR_PTR(-ENOENT); } -struct file_operations hpfs_dir_ops = +const struct file_operations hpfs_dir_ops = { .llseek = hpfs_dir_lseek, .read = generic_read_dir, diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 7c995ac4081b..d3b9fffe45a1 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -119,7 +119,7 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf, return retval; } -struct file_operations hpfs_file_ops = +const struct file_operations hpfs_file_ops = { .llseek = generic_file_llseek, .read = generic_file_read, diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 4c6473ab3b34..29b7a3e55173 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h @@ -240,7 +240,7 @@ void hpfs_set_dentry_operations(struct dentry *); /* dir.c */ struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *); -extern struct file_operations hpfs_dir_ops; +extern const struct file_operations hpfs_dir_ops; /* dnode.c */ @@ -266,7 +266,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int); /* file.c */ int hpfs_file_fsync(struct file *, struct dentry *, int); -extern struct file_operations hpfs_file_ops; +extern const struct file_operations hpfs_file_ops; extern struct inode_operations hpfs_file_iops; extern struct address_space_operations hpfs_aops; diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index a44dc5897399..2ba20cdb5baa 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c @@ -558,7 +558,7 @@ static loff_t hppfs_llseek(struct file *file, loff_t off, int where) return(default_llseek(file, off, where)); } -static struct file_operations hppfs_file_fops = { +static const struct file_operations hppfs_file_fops = { .owner = NULL, .llseek = hppfs_llseek, .read = hppfs_read, @@ -609,7 +609,7 @@ static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) return(0); } -static struct file_operations hppfs_dir_fops = { +static const struct file_operations hppfs_dir_fops = { .owner = NULL, .readdir = hppfs_readdir, .open = hppfs_dir_open, diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 25fa8bba8cb5..3a5b4e923455 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -35,7 +35,7 @@ static struct super_operations hugetlbfs_ops; static struct address_space_operations hugetlbfs_aops; -struct file_operations hugetlbfs_file_operations; +const struct file_operations hugetlbfs_file_operations; static struct inode_operations hugetlbfs_dir_inode_operations; static struct inode_operations hugetlbfs_inode_operations; @@ -566,7 +566,7 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) inode_init_once(&ei->vfs_inode); } -struct file_operations hugetlbfs_file_operations = { +const struct file_operations hugetlbfs_file_operations = { .mmap = hugetlbfs_file_mmap, .fsync = simple_sync_file, .get_unmapped_area = hugetlb_get_unmapped_area, diff --git a/fs/inotify.c b/fs/inotify.c index f48a3dae0712..367c487c014b 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -920,7 +920,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd, return ret; } -static struct file_operations inotify_fops = { +static const struct file_operations inotify_fops = { .poll = inotify_poll, .read = inotify_read, .release = inotify_release, diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 7901ac9f97ab..5440ea292c69 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -16,7 +16,7 @@ static int isofs_readdir(struct file *, void *, filldir_t); -struct file_operations isofs_dir_operations = +const struct file_operations isofs_dir_operations = { .read = generic_read_dir, .readdir = isofs_readdir, diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index 439a19b1bf3e..b87ba066f5e7 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h @@ -175,6 +175,6 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de, } extern struct inode_operations isofs_dir_inode_operations; -extern struct file_operations isofs_dir_operations; +extern const struct file_operations isofs_dir_operations; extern struct address_space_operations isofs_symlink_aops; extern struct export_operations isofs_export_ops; diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 5a4519e834da..020cc097c539 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -55,9 +55,9 @@ static int jffs_remove(struct inode *dir, struct dentry *dentry, int type); static struct super_operations jffs_ops; -static struct file_operations jffs_file_operations; +static const struct file_operations jffs_file_operations; static struct inode_operations jffs_file_inode_operations; -static struct file_operations jffs_dir_operations; +static const struct file_operations jffs_dir_operations; static struct inode_operations jffs_dir_inode_operations; static struct address_space_operations jffs_address_operations; @@ -1629,7 +1629,7 @@ static int jffs_fsync(struct file *f, struct dentry *d, int datasync) } -static struct file_operations jffs_file_operations = +static const struct file_operations jffs_file_operations = { .open = generic_file_open, .llseek = generic_file_llseek, @@ -1649,7 +1649,7 @@ static struct inode_operations jffs_file_inode_operations = }; -static struct file_operations jffs_dir_operations = +static const struct file_operations jffs_dir_operations = { .readdir = jffs_readdir, }; diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index a7bf9cb2567f..8bc7a5018e40 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -37,7 +37,7 @@ static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t); static int jffs2_rename (struct inode *, struct dentry *, struct inode *, struct dentry *); -struct file_operations jffs2_dir_operations = +const struct file_operations jffs2_dir_operations = { .read = generic_read_dir, .readdir = jffs2_readdir, diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 935f273dc57b..9f4171213e58 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -38,7 +38,7 @@ int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync) return 0; } -struct file_operations jffs2_file_operations = +const struct file_operations jffs2_file_operations = { .llseek = generic_file_llseek, .open = generic_file_open, diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 59e7a393200c..d307cf548625 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -159,11 +159,11 @@ void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c); void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); /* dir.c */ -extern struct file_operations jffs2_dir_operations; +extern const struct file_operations jffs2_dir_operations; extern struct inode_operations jffs2_dir_inode_operations; /* file.c */ -extern struct file_operations jffs2_file_operations; +extern const struct file_operations jffs2_file_operations; extern struct inode_operations jffs2_file_inode_operations; extern struct address_space_operations jffs2_file_address_operations; int jffs2_fsync(struct file *, struct dentry *, int); diff --git a/fs/jfs/file.c b/fs/jfs/file.c index e1ac6e497e2b..1c9745be5ada 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c @@ -100,7 +100,7 @@ struct inode_operations jfs_file_inode_operations = { #endif }; -struct file_operations jfs_file_operations = { +const struct file_operations jfs_file_operations = { .open = jfs_open, .llseek = generic_file_llseek, .write = generic_file_write, diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index 095d471b9f9a..c30072674464 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h @@ -35,9 +35,9 @@ extern void jfs_set_inode_flags(struct inode *); extern struct address_space_operations jfs_aops; extern struct inode_operations jfs_dir_inode_operations; -extern struct file_operations jfs_dir_operations; +extern const struct file_operations jfs_dir_operations; extern struct inode_operations jfs_file_inode_operations; -extern struct file_operations jfs_file_operations; +extern const struct file_operations jfs_file_operations; extern struct inode_operations jfs_symlink_inode_operations; extern struct dentry_operations jfs_ci_dentry_operations; #endif /* _H_JFS_INODE */ diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 309cee575f7d..09ea03f62277 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1519,7 +1519,7 @@ struct inode_operations jfs_dir_inode_operations = { #endif }; -struct file_operations jfs_dir_operations = { +const struct file_operations jfs_dir_operations = { .read = generic_read_dir, .readdir = jfs_readdir, .fsync = jfs_fsync, diff --git a/fs/libfs.c b/fs/libfs.c index 4fdeaceb892c..7145ba7a48d0 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -179,7 +179,7 @@ ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t return -EISDIR; } -struct file_operations simple_dir_operations = { +const struct file_operations simple_dir_operations = { .open = dcache_dir_open, .release = dcache_dir_close, .llseek = dcache_dir_lseek, diff --git a/fs/minix/dir.c b/fs/minix/dir.c index 732502aabc05..69224d1fe043 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c @@ -14,7 +14,7 @@ typedef struct minix_dir_entry minix_dirent; static int minix_readdir(struct file *, void *, filldir_t); -struct file_operations minix_dir_operations = { +const struct file_operations minix_dir_operations = { .read = generic_read_dir, .readdir = minix_readdir, .fsync = minix_sync_file, diff --git a/fs/minix/file.c b/fs/minix/file.c index f1d77acb3f01..420b32882a10 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c @@ -15,7 +15,7 @@ */ int minix_sync_file(struct file *, struct dentry *, int); -struct file_operations minix_file_operations = { +const struct file_operations minix_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, .write = generic_file_write, diff --git a/fs/minix/minix.h b/fs/minix/minix.h index e42a8bb89001..c55b77cdcc8e 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h @@ -81,8 +81,8 @@ extern int minix_sync_file(struct file *, struct dentry *, int); extern struct inode_operations minix_file_inode_operations; extern struct inode_operations minix_dir_inode_operations; -extern struct file_operations minix_file_operations; -extern struct file_operations minix_dir_operations; +extern const struct file_operations minix_file_operations; +extern const struct file_operations minix_dir_operations; extern struct dentry_operations minix_dentry_operations; static inline struct minix_sb_info *minix_sb(struct super_block *sb) diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index cfd76f431dc0..f0860c602d8b 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -49,7 +49,7 @@ extern int ncp_symlink(struct inode *, struct dentry *, const char *); #define ncp_symlink NULL #endif -struct file_operations ncp_dir_operations = +const struct file_operations ncp_dir_operations = { .read = generic_read_dir, .readdir = ncp_readdir, diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index ebdad8f6398f..e6b7c67cf057 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c @@ -283,7 +283,7 @@ static int ncp_release(struct inode *inode, struct file *file) { return 0; } -struct file_operations ncp_file_operations = +const struct file_operations ncp_file_operations = { .llseek = remote_llseek, .read = ncp_file_read, diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 06c48b385c94..a23f34894167 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -54,7 +54,7 @@ static int nfs_rename(struct inode *, struct dentry *, static int nfs_fsync_dir(struct file *, struct dentry *, int); static loff_t nfs_llseek_dir(struct file *, loff_t, int); -struct file_operations nfs_dir_operations = { +const struct file_operations nfs_dir_operations = { .llseek = nfs_llseek_dir, .read = generic_read_dir, .readdir = nfs_readdir, diff --git a/fs/nfs/file.c b/fs/nfs/file.c index dee49a0cb995..f1df2c8d9259 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -49,7 +49,7 @@ static int nfs_check_flags(int flags); static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); -struct file_operations nfs_file_operations = { +const struct file_operations nfs_file_operations = { .llseek = nfs_file_llseek, .read = do_sync_read, .write = do_sync_write, diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index c8960aff0968..3ef017b3b5bd 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -134,7 +134,7 @@ static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size return simple_transaction_read(file, buf, size, pos); } -static struct file_operations transaction_ops = { +static const struct file_operations transaction_ops = { .write = nfsctl_transaction_write, .read = nfsctl_transaction_read, .release = simple_transaction_release, @@ -146,7 +146,7 @@ static int exports_open(struct inode *inode, struct file *file) return seq_open(file, &nfs_exports_op); } -static struct file_operations exports_operations = { +static const struct file_operations exports_operations = { .open = exports_open, .read = seq_read, .llseek = seq_lseek, diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c index 1cf955bcc526..57265d563804 100644 --- a/fs/nfsd/stats.c +++ b/fs/nfsd/stats.c @@ -80,7 +80,7 @@ static int nfsd_proc_open(struct inode *inode, struct file *file) return single_open(file, nfsd_proc_show, NULL); } -static struct file_operations nfsd_proc_fops = { +static const struct file_operations nfsd_proc_fops = { .owner = THIS_MODULE, .open = nfsd_proc_open, .read = seq_read, diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index 9d9ed3fe371d..d1e2c6f9f05e 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c @@ -1553,7 +1553,7 @@ static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry, #endif /* NTFS_RW */ -struct file_operations ntfs_dir_ops = { +const struct file_operations ntfs_dir_ops = { .llseek = generic_file_llseek, /* Seek inside directory. */ .read = generic_read_dir, /* Return -EISDIR. */ .readdir = ntfs_readdir, /* Read directory contents. */ diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index f5d057e4acc2..c63a83e8da98 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -2294,7 +2294,7 @@ static int ntfs_file_fsync(struct file *filp, struct dentry *dentry, #endif /* NTFS_RW */ -struct file_operations ntfs_file_ops = { +const struct file_operations ntfs_file_ops = { .llseek = generic_file_llseek, /* Seek inside file. */ .read = generic_file_read, /* Read from file. */ .aio_read = generic_file_aio_read, /* Async read from file. */ @@ -2337,6 +2337,6 @@ struct inode_operations ntfs_file_inode_ops = { #endif /* NTFS_RW */ }; -struct file_operations ntfs_empty_file_ops = {}; +const struct file_operations ntfs_empty_file_ops = {}; struct inode_operations ntfs_empty_inode_ops = {}; diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h index 166142960b53..bf7b3d7c0930 100644 --- a/fs/ntfs/ntfs.h +++ b/fs/ntfs/ntfs.h @@ -60,13 +60,13 @@ extern struct kmem_cache *ntfs_index_ctx_cache; extern struct address_space_operations ntfs_aops; extern struct address_space_operations ntfs_mst_aops; -extern struct file_operations ntfs_file_ops; +extern const struct file_operations ntfs_file_ops; extern struct inode_operations ntfs_file_inode_ops; -extern struct file_operations ntfs_dir_ops; +extern const struct file_operations ntfs_dir_ops; extern struct inode_operations ntfs_dir_inode_ops; -extern struct file_operations ntfs_empty_file_ops; +extern const struct file_operations ntfs_empty_file_ops; extern struct inode_operations ntfs_empty_inode_ops; extern struct export_operations ntfs_export_ops; diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 84f153aca692..64cd52860c87 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -2017,7 +2017,7 @@ out: return ret; } -static struct file_operations ocfs2_dlm_debug_fops = { +static const struct file_operations ocfs2_dlm_debug_fops = { .open = ocfs2_dlm_debug_open, .release = ocfs2_dlm_debug_release, .read = seq_read, diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 4b4cbadd5838..34e903a6a46b 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1176,7 +1176,7 @@ struct inode_operations ocfs2_special_file_iops = { .getattr = ocfs2_getattr, }; -struct file_operations ocfs2_fops = { +const struct file_operations ocfs2_fops = { .read = do_sync_read, .write = do_sync_write, .sendfile = generic_file_sendfile, @@ -1188,7 +1188,7 @@ struct file_operations ocfs2_fops = { .aio_write = ocfs2_file_aio_write, }; -struct file_operations ocfs2_dops = { +const struct file_operations ocfs2_dops = { .read = generic_read_dir, .readdir = ocfs2_readdir, .fsync = ocfs2_sync_file, diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index a5ea33b24060..740c9e7ca599 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h @@ -26,8 +26,8 @@ #ifndef OCFS2_FILE_H #define OCFS2_FILE_H -extern struct file_operations ocfs2_fops; -extern struct file_operations ocfs2_dops; +extern const struct file_operations ocfs2_fops; +extern const struct file_operations ocfs2_dops; extern struct inode_operations ocfs2_file_iops; extern struct inode_operations ocfs2_special_file_iops; struct ocfs2_alloc_context; diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index aeb0106890e4..0f14276a2e51 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -581,17 +581,17 @@ int property_release (struct inode *inode, struct file *filp) return 0; } -static struct file_operations openpromfs_prop_ops = { +static const struct file_operations openpromfs_prop_ops = { .read = property_read, .write = property_write, .release = property_release, }; -static struct file_operations openpromfs_nodenum_ops = { +static const struct file_operations openpromfs_nodenum_ops = { .read = nodenum_read, }; -static struct file_operations openprom_operations = { +static const struct file_operations openprom_operations = { .read = generic_read_dir, .readdir = openpromfs_readdir, }; diff --git a/fs/pipe.c b/fs/pipe.c index 4384c9290943..e2f4f1d9ffc2 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -568,7 +568,7 @@ pipe_rdwr_open(struct inode *inode, struct file *filp) * The file_operations structs are not static because they * are also used in linux/fs/fifo.c to do operations on FIFOs. */ -struct file_operations read_fifo_fops = { +const struct file_operations read_fifo_fops = { .llseek = no_llseek, .read = pipe_read, .readv = pipe_readv, @@ -580,7 +580,7 @@ struct file_operations read_fifo_fops = { .fasync = pipe_read_fasync, }; -struct file_operations write_fifo_fops = { +const struct file_operations write_fifo_fops = { .llseek = no_llseek, .read = bad_pipe_r, .write = pipe_write, @@ -592,7 +592,7 @@ struct file_operations write_fifo_fops = { .fasync = pipe_write_fasync, }; -struct file_operations rdwr_fifo_fops = { +const struct file_operations rdwr_fifo_fops = { .llseek = no_llseek, .read = pipe_read, .readv = pipe_readv, diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index adc2cd95169a..17f6e8fa1397 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c @@ -31,7 +31,7 @@ static int open_kcore(struct inode * inode, struct file * filp) static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *); -struct file_operations proc_kcore_operations = { +const struct file_operations proc_kcore_operations = { .read = read_kcore, .open = open_kcore, }; diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index 10d37bf25206..ff3b90b56e9d 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c @@ -47,7 +47,7 @@ static unsigned int kmsg_poll(struct file *file, poll_table *wait) } -struct file_operations proc_kmsg_operations = { +const struct file_operations proc_kmsg_operations = { .read = kmsg_read, .poll = kmsg_poll, .open = kmsg_open, diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 4063fb32f78c..7efa73d44c9a 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -172,7 +172,7 @@ static int open_vmcore(struct inode *inode, struct file *filp) return 0; } -struct file_operations proc_vmcore_operations = { +const struct file_operations proc_vmcore_operations = { .read = read_vmcore, .open = open_vmcore, }; diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c index 7a8f5595c26f..9031948fefd0 100644 --- a/fs/qnx4/dir.c +++ b/fs/qnx4/dir.c @@ -81,7 +81,7 @@ out: return 0; } -struct file_operations qnx4_dir_operations = +const struct file_operations qnx4_dir_operations = { .read = generic_read_dir, .readdir = qnx4_readdir, diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c index c33963fded9e..62af4b1348bd 100644 --- a/fs/qnx4/file.c +++ b/fs/qnx4/file.c @@ -19,7 +19,7 @@ * We have mostly NULL's here: the current defaults are ok for * the qnx4 filesystem. */ -struct file_operations qnx4_file_operations = +const struct file_operations qnx4_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c index 6ada2095b9ac..00a933eb820c 100644 --- a/fs/ramfs/file-mmu.c +++ b/fs/ramfs/file-mmu.c @@ -32,7 +32,7 @@ struct address_space_operations ramfs_aops = { .commit_write = simple_commit_write }; -struct file_operations ramfs_file_operations = { +const struct file_operations ramfs_file_operations = { .read = generic_file_read, .write = generic_file_write, .mmap = generic_file_mmap, diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index b1ca234068f6..f443a84b98a5 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -33,7 +33,7 @@ struct address_space_operations ramfs_aops = { .commit_write = simple_commit_write }; -struct file_operations ramfs_file_operations = { +const struct file_operations ramfs_file_operations = { .mmap = ramfs_nommu_mmap, .get_unmapped_area = ramfs_nommu_get_unmapped_area, .read = generic_file_read, diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h index 272c8a7120b0..313237631b49 100644 --- a/fs/ramfs/internal.h +++ b/fs/ramfs/internal.h @@ -11,5 +11,5 @@ extern struct address_space_operations ramfs_aops; -extern struct file_operations ramfs_file_operations; +extern const struct file_operations ramfs_file_operations; extern struct inode_operations ramfs_file_inode_operations; diff --git a/fs/read_write.c b/fs/read_write.c index 34b1bf259efd..6256ca81a718 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -19,7 +19,7 @@ #include #include -struct file_operations generic_ro_fops = { +const struct file_operations generic_ro_fops = { .llseek = generic_file_llseek, .read = generic_file_read, .mmap = generic_file_readonly_mmap, diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index d71ac6579289..973c819f8033 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c @@ -18,7 +18,7 @@ static int reiserfs_readdir(struct file *, void *, filldir_t); static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, int datasync); -struct file_operations reiserfs_dir_operations = { +const struct file_operations reiserfs_dir_operations = { .read = generic_read_dir, .readdir = reiserfs_readdir, .fsync = reiserfs_dir_fsync, diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index d0c1e865963e..010094d14da6 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -1566,7 +1566,7 @@ static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user * buf, return generic_file_aio_write(iocb, buf, count, pos); } -struct file_operations reiserfs_file_operations = { +const struct file_operations reiserfs_file_operations = { .read = generic_file_read, .write = reiserfs_file_write, .ioctl = reiserfs_ioctl, diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index ef6caed9336b..731688e1cfe3 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c @@ -470,7 +470,7 @@ static int r_open(struct inode *inode, struct file *file) return ret; } -static struct file_operations r_file_operations = { +static const struct file_operations r_file_operations = { .open = r_open, .read = seq_read, .llseek = seq_lseek, diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index c2fc424d7d5c..9b9eda7b335c 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -463,7 +463,7 @@ static struct address_space_operations romfs_aops = { .readpage = romfs_readpage }; -static struct file_operations romfs_dir_operations = { +static const struct file_operations romfs_dir_operations = { .read = generic_read_dir, .readdir = romfs_readdir, }; diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index 0424d06b147e..34c7a11d91f0 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c @@ -34,7 +34,7 @@ static int smb_rename(struct inode *, struct dentry *, static int smb_make_node(struct inode *,struct dentry *,int,dev_t); static int smb_link(struct dentry *, struct inode *, struct dentry *); -struct file_operations smb_dir_operations = +const struct file_operations smb_dir_operations = { .read = generic_read_dir, .readdir = smb_readdir, diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index 7042e62726a4..c56bd99a9701 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -401,7 +401,7 @@ smb_file_permission(struct inode *inode, int mask, struct nameidata *nd) return error; } -struct file_operations smb_file_operations = +const struct file_operations smb_file_operations = { .llseek = remote_llseek, .read = smb_file_read, diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h index e866ec8660d0..47664597e6b1 100644 --- a/fs/smbfs/proto.h +++ b/fs/smbfs/proto.h @@ -35,7 +35,7 @@ extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry); extern void smb_install_null_ops(struct smb_ops *ops); /* dir.c */ -extern struct file_operations smb_dir_operations; +extern const struct file_operations smb_dir_operations; extern struct inode_operations smb_dir_inode_operations; extern struct inode_operations smb_dir_inode_operations_unix; extern void smb_new_dentry(struct dentry *dentry); @@ -64,7 +64,7 @@ extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat extern int smb_notify_change(struct dentry *dentry, struct iattr *attr); /* file.c */ extern struct address_space_operations smb_file_aops; -extern struct file_operations smb_file_operations; +extern const struct file_operations smb_file_operations; extern struct inode_operations smb_file_inode_operations; /* ioctl.c */ extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 78899eeab974..c16a93c353c0 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -163,7 +163,7 @@ static int release(struct inode * inode, struct file * file) return 0; } -struct file_operations bin_fops = { +const struct file_operations bin_fops = { .read = read, .write = write, .mmap = mmap, diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 9ee956864445..f26880a4785e 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -503,7 +503,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) return offset; } -struct file_operations sysfs_dir_operations = { +const struct file_operations sysfs_dir_operations = { .open = sysfs_dir_open, .release = sysfs_dir_close, .llseek = sysfs_dir_lseek, diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 5e83e7246788..830f76fa098c 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -348,7 +348,7 @@ static int sysfs_release(struct inode * inode, struct file * filp) return 0; } -struct file_operations sysfs_file_operations = { +const struct file_operations sysfs_file_operations = { .read = sysfs_read_file, .write = sysfs_write_file, .llseek = generic_file_llseek, diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index cf11d5b789d9..32958a7c50e9 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -21,9 +21,9 @@ extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); extern struct rw_semaphore sysfs_rename_sem; extern struct super_block * sysfs_sb; -extern struct file_operations sysfs_dir_operations; -extern struct file_operations sysfs_file_operations; -extern struct file_operations bin_fops; +extern const struct file_operations sysfs_dir_operations; +extern const struct file_operations sysfs_file_operations; +extern const struct file_operations bin_fops; extern struct inode_operations sysfs_dir_inode_operations; extern struct inode_operations sysfs_symlink_inode_operations; diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index cce8b05cba5a..8c66e9270dd6 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c @@ -20,7 +20,7 @@ static int sysv_readdir(struct file *, void *, filldir_t); -struct file_operations sysv_dir_operations = { +const struct file_operations sysv_dir_operations = { .read = generic_read_dir, .readdir = sysv_readdir, .fsync = sysv_sync_file, diff --git a/fs/sysv/file.c b/fs/sysv/file.c index da69abc06240..a59e303135fa 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c @@ -19,7 +19,7 @@ * We have mostly NULLs here: the current defaults are OK for * the coh filesystem. */ -struct file_operations sysv_file_operations = { +const struct file_operations sysv_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, .write = generic_file_write, diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index b7f9b4a42aab..393a480e4deb 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h @@ -159,8 +159,8 @@ extern ino_t sysv_inode_by_name(struct dentry *); extern struct inode_operations sysv_file_inode_operations; extern struct inode_operations sysv_dir_inode_operations; extern struct inode_operations sysv_fast_symlink_inode_operations; -extern struct file_operations sysv_file_operations; -extern struct file_operations sysv_dir_operations; +extern const struct file_operations sysv_file_operations; +extern const struct file_operations sysv_dir_operations; extern struct address_space_operations sysv_aops; extern struct super_operations sysv_sops; extern struct dentry_operations sysv_dentry_operations; diff --git a/fs/udf/dir.c b/fs/udf/dir.c index f5222527fe39..8c28efa3b8ff 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c @@ -42,7 +42,7 @@ static int do_udf_readdir(struct inode *, struct file *, filldir_t, void *); /* readdir and lookup functions */ -struct file_operations udf_dir_operations = { +const struct file_operations udf_dir_operations = { .read = generic_read_dir, .readdir = udf_readdir, .ioctl = udf_ioctl, diff --git a/fs/udf/file.c b/fs/udf/file.c index a6f2acc1f15c..e34b00e303f1 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -248,7 +248,7 @@ static int udf_release_file(struct inode * inode, struct file * filp) return 0; } -struct file_operations udf_file_operations = { +const struct file_operations udf_file_operations = { .read = generic_file_read, .ioctl = udf_ioctl, .open = generic_file_open, diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 1d5800e0cbe7..023e19ba5a2e 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -44,9 +44,9 @@ struct buffer_head; struct super_block; extern struct inode_operations udf_dir_inode_operations; -extern struct file_operations udf_dir_operations; +extern const struct file_operations udf_dir_operations; extern struct inode_operations udf_file_inode_operations; -extern struct file_operations udf_file_operations; +extern const struct file_operations udf_file_operations; extern struct address_space_operations udf_aops; extern struct address_space_operations udf_adinicb_aops; extern struct address_space_operations udf_symlink_aops; diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 7c10c68902ae..1a561202d3f4 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -620,7 +620,7 @@ int ufs_empty_dir (struct inode * inode) return 1; } -struct file_operations ufs_dir_operations = { +const struct file_operations ufs_dir_operations = { .read = generic_read_dir, .readdir = ufs_readdir, .fsync = file_fsync, diff --git a/fs/ufs/file.c b/fs/ufs/file.c index 62ad481810ef..312fd3f86313 100644 --- a/fs/ufs/file.c +++ b/fs/ufs/file.c @@ -31,7 +31,7 @@ * the ufs filesystem. */ -struct file_operations ufs_file_operations = { +const struct file_operations ufs_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, .write = generic_file_write, diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 185567a6a561..85997b1205f5 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -528,7 +528,7 @@ open_exec_out: } #endif /* HAVE_FOP_OPEN_EXEC */ -struct file_operations xfs_file_operations = { +const struct file_operations xfs_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, .write = do_sync_write, @@ -550,7 +550,7 @@ struct file_operations xfs_file_operations = { #endif }; -struct file_operations xfs_invis_file_operations = { +const struct file_operations xfs_invis_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, .write = do_sync_write, @@ -570,7 +570,7 @@ struct file_operations xfs_invis_file_operations = { }; -struct file_operations xfs_dir_file_operations = { +const struct file_operations xfs_dir_file_operations = { .read = generic_read_dir, .readdir = xfs_file_readdir, .unlocked_ioctl = xfs_file_ioctl, diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index a8417d7af5f9..ad6173da5678 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h @@ -22,9 +22,9 @@ extern struct inode_operations xfs_inode_operations; extern struct inode_operations xfs_dir_inode_operations; extern struct inode_operations xfs_symlink_inode_operations; -extern struct file_operations xfs_file_operations; -extern struct file_operations xfs_dir_file_operations; -extern struct file_operations xfs_invis_file_operations; +extern const struct file_operations xfs_file_operations; +extern const struct file_operations xfs_dir_file_operations; +extern const struct file_operations xfs_invis_file_operations; extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *, int, unsigned int, void __user *); diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h index cc621ec409d8..b3ecf8f71d97 100644 --- a/include/linux/coda_linux.h +++ b/include/linux/coda_linux.h @@ -30,9 +30,9 @@ extern struct inode_operations coda_ioctl_inode_operations; extern struct address_space_operations coda_file_aops; extern struct address_space_operations coda_symlink_aops; -extern struct file_operations coda_dir_operations; -extern struct file_operations coda_file_operations; -extern struct file_operations coda_ioctl_operations; +extern const struct file_operations coda_dir_operations; +extern const struct file_operations coda_file_operations; +extern const struct file_operations coda_ioctl_operations; /* operations shared over more than one file */ int coda_open(struct inode *i, struct file *f); diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h index 534d750d922d..32503657f14f 100644 --- a/include/linux/crash_dump.h +++ b/include/linux/crash_dump.h @@ -11,7 +11,7 @@ extern unsigned long long elfcorehdr_addr; extern ssize_t copy_oldmem_page(unsigned long, char *, size_t, unsigned long, int); -extern struct file_operations proc_vmcore_operations; +extern const struct file_operations proc_vmcore_operations; extern struct proc_dir_entry *proc_vmcore; #endif /* CONFIG_CRASH_DUMP */ diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h index 28f368c526fb..fbfa6b52e2fb 100644 --- a/include/linux/efs_fs.h +++ b/include/linux/efs_fs.h @@ -37,7 +37,7 @@ static inline struct efs_sb_info *SUPER_INFO(struct super_block *sb) struct statfs; extern struct inode_operations efs_dir_inode_operations; -extern struct file_operations efs_dir_operations; +extern const struct file_operations efs_dir_operations; extern struct address_space_operations efs_symlink_aops; extern void efs_read_inode(struct inode *); diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 8bb4f842cded..3ade6a4e3bdd 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -833,11 +833,11 @@ do { \ */ /* dir.c */ -extern struct file_operations ext3_dir_operations; +extern const struct file_operations ext3_dir_operations; /* file.c */ extern struct inode_operations ext3_file_inode_operations; -extern struct file_operations ext3_file_operations; +extern const struct file_operations ext3_file_operations; /* namei.c */ extern struct inode_operations ext3_dir_inode_operations; diff --git a/include/linux/fs.h b/include/linux/fs.h index ef355bc73714..408fe89498f4 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1390,11 +1390,11 @@ extern void bd_set_size(struct block_device *, loff_t size); extern void bd_forget(struct inode *inode); extern void bdput(struct block_device *); extern struct block_device *open_by_devnum(dev_t, unsigned); -extern struct file_operations def_blk_fops; +extern const struct file_operations def_blk_fops; extern struct address_space_operations def_blk_aops; -extern struct file_operations def_chr_fops; -extern struct file_operations bad_sock_fops; -extern struct file_operations def_fifo_fops; +extern const struct file_operations def_chr_fops; +extern const struct file_operations bad_sock_fops; +extern const struct file_operations def_fifo_fops; extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long); extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long); extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); @@ -1444,9 +1444,9 @@ extern void init_special_inode(struct inode *, umode_t, dev_t); extern void make_bad_inode(struct inode *); extern int is_bad_inode(struct inode *); -extern struct file_operations read_fifo_fops; -extern struct file_operations write_fifo_fops; -extern struct file_operations rdwr_fifo_fops; +extern const struct file_operations read_fifo_fops; +extern const struct file_operations write_fifo_fops; +extern const struct file_operations rdwr_fifo_fops; extern int fs_may_remount_ro(struct super_block *); @@ -1688,7 +1688,7 @@ static inline ssize_t blockdev_direct_IO_own_locking(int rw, struct kiocb *iocb, nr_segs, get_block, end_io, DIO_OWN_LOCKING); } -extern struct file_operations generic_ro_fops; +extern const struct file_operations generic_ro_fops; #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) @@ -1744,9 +1744,9 @@ extern int simple_commit_write(struct file *file, struct page *page, extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *); extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); -extern struct file_operations simple_dir_operations; +extern const struct file_operations simple_dir_operations; extern struct inode_operations simple_dir_inode_operations; -struct tree_descr { char *name; struct file_operations *ops; int mode; }; +struct tree_descr { char *name; const struct file_operations *ops; int mode; }; struct dentry *d_alloc_name(struct dentry *, const char *); extern int simple_fill_super(struct super_block *, int, struct tree_descr *); extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count); diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index d6f1019625af..4c5e610fe442 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -154,7 +154,7 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb) return sb->s_fs_info; } -extern struct file_operations hugetlbfs_file_operations; +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, diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index 53cee1581650..d9035c73e5d1 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -334,7 +334,7 @@ extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, unsigned long *mapped_blocks); /* fat/dir.c */ -extern struct file_operations fat_dir_operations; +extern const struct file_operations fat_dir_operations; extern int fat_search_long(struct inode *inode, const unsigned char *name, int name_len, struct fat_slot_info *sinfo); extern int fat_dir_empty(struct inode *dir); @@ -397,7 +397,7 @@ extern int fat_count_free_clusters(struct super_block *sb); /* fat/file.c */ extern int fat_generic_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern struct file_operations fat_file_operations; +extern const struct file_operations fat_file_operations; extern struct inode_operations fat_file_inode_operations; extern int fat_notify_change(struct dentry * dentry, struct iattr * attr); extern void fat_truncate(struct inode *inode); diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h index e01342568530..96dc237b8f03 100644 --- a/include/linux/ncp_fs.h +++ b/include/linux/ncp_fs.h @@ -209,7 +209,7 @@ void ncp_update_inode2(struct inode *, struct ncp_entry_info *); /* linux/fs/ncpfs/dir.c */ extern struct inode_operations ncp_dir_inode_operations; -extern struct file_operations ncp_dir_operations; +extern const struct file_operations ncp_dir_operations; int ncp_conn_logged_in(struct super_block *); int ncp_date_dos2unix(__le16 time, __le16 date); void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date); @@ -230,7 +230,7 @@ void ncp_unlock_server(struct ncp_server *server); /* linux/fs/ncpfs/file.c */ extern struct inode_operations ncp_file_inode_operations; -extern struct file_operations ncp_file_operations; +extern const struct file_operations ncp_file_operations; int ncp_make_open(struct inode *, int); /* linux/fs/ncpfs/mmap.c */ diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index cbebd7d1b9e8..c71227dd4389 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -324,7 +324,7 @@ extern struct inode_operations nfs_file_inode_operations; #ifdef CONFIG_NFS_V3 extern struct inode_operations nfs3_file_inode_operations; #endif /* CONFIG_NFS_V3 */ -extern struct file_operations nfs_file_operations; +extern const struct file_operations nfs_file_operations; extern struct address_space_operations nfs_file_aops; static inline struct rpc_cred *nfs_file_cred(struct file *file) @@ -371,7 +371,7 @@ extern struct inode_operations nfs_dir_inode_operations; #ifdef CONFIG_NFS_V3 extern struct inode_operations nfs3_dir_inode_operations; #endif /* CONFIG_NFS_V3 */ -extern struct file_operations nfs_dir_operations; +extern const struct file_operations nfs_dir_operations; extern struct dentry_operations nfs_dentry_operations; extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr); diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 6d03d025fcd5..135871df9911 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -128,9 +128,9 @@ extern int proc_match(int, const char *,struct proc_dir_entry *); extern int proc_readdir(struct file *, void *, filldir_t); extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *); -extern struct file_operations proc_kcore_operations; -extern struct file_operations proc_kmsg_operations; -extern struct file_operations ppc_htab_operations; +extern const struct file_operations proc_kcore_operations; +extern const struct file_operations proc_kmsg_operations; +extern const struct file_operations ppc_htab_operations; /* * proc_tty.c diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h index fc610bb0f733..27f49c85d5d6 100644 --- a/include/linux/qnx4_fs.h +++ b/include/linux/qnx4_fs.h @@ -118,8 +118,8 @@ extern struct buffer_head *qnx4_bread(struct inode *, int, int); extern struct inode_operations qnx4_file_inode_operations; extern struct inode_operations qnx4_dir_inode_operations; -extern struct file_operations qnx4_file_operations; -extern struct file_operations qnx4_dir_operations; +extern const struct file_operations qnx4_file_operations; +extern const struct file_operations qnx4_dir_operations; extern int qnx4_is_free(struct super_block *sb, long block); extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy); extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode, struct nameidata *nd); diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h index 953b6df5d037..78ecfa28b1c2 100644 --- a/include/linux/ramfs.h +++ b/include/linux/ramfs.h @@ -15,7 +15,7 @@ extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file, extern int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma); #endif -extern struct file_operations ramfs_file_operations; +extern const struct file_operations ramfs_file_operations; extern struct vm_operations_struct generic_file_vm_ops; #endif diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 912f1b7cb18f..5676c4210e2c 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -1960,7 +1960,7 @@ int reiserfs_global_version_in_proc(char *buffer, char **start, off_t offset, extern struct inode_operations reiserfs_dir_inode_operations; extern struct inode_operations reiserfs_symlink_inode_operations; extern struct inode_operations reiserfs_special_inode_operations; -extern struct file_operations reiserfs_dir_operations; +extern const struct file_operations reiserfs_dir_operations; /* tail_conversion.c */ int direct2indirect(struct reiserfs_transaction_handle *, struct inode *, @@ -1972,7 +1972,7 @@ void reiserfs_unmap_buffer(struct buffer_head *); /* file.c */ extern struct inode_operations reiserfs_file_inode_operations; -extern struct file_operations reiserfs_file_operations; +extern const struct file_operations reiserfs_file_operations; extern struct address_space_operations reiserfs_address_space_operations; /* fix_nodes.c */ diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h index b0ffe4356e5a..843aeaaa79d4 100644 --- a/include/linux/ufs_fs.h +++ b/include/linux/ufs_fs.h @@ -895,7 +895,7 @@ extern void ufs_set_link(struct inode *, struct ufs_dir_entry *, struct buffer_h /* file.c */ extern struct inode_operations ufs_file_inode_operations; -extern struct file_operations ufs_file_operations; +extern const struct file_operations ufs_file_operations; extern struct address_space_operations ufs_aops; @@ -915,7 +915,7 @@ extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *); extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create); /* namei.c */ -extern struct file_operations ufs_dir_operations; +extern const struct file_operations ufs_dir_operations; /* super.c */ extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); diff --git a/net/nonet.c b/net/nonet.c index 1230f0ae832e..92e76640c7cd 100644 --- a/net/nonet.c +++ b/net/nonet.c @@ -19,7 +19,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare) return -ENXIO; } -struct file_operations bad_sock_fops = { +const struct file_operations bad_sock_fops = { .owner = THIS_MODULE, .open = sock_no_open, }; diff --git a/net/socket.c b/net/socket.c index 5211ba270375..fcd77eac0ccf 100644 --- a/net/socket.c +++ b/net/socket.c @@ -539,7 +539,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare) return -ENXIO; } -struct file_operations bad_sock_fops = { +const struct file_operations bad_sock_fops = { .owner = THIS_MODULE, .open = sock_no_open, }; -- cgit v1.2.3-59-g8ed1b From 50297cbf07427b47f0fff5ade8e21cdabf860249 Mon Sep 17 00:00:00 2001 From: Marcelo Feitoza Parisi Date: Tue, 28 Mar 2006 01:56:44 -0800 Subject: [PATCH] drivers/block/*: use time_after() and friends They deal with wrapping correctly and are nicer to read. Signed-off-by: Marcelo Feitoza Parisi Signed-off-by: Alexey Dobriyan Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/DAC960.c | 17 +++++++++-------- drivers/block/floppy.c | 9 +++++---- 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 49c7cd558ddf..45bcda544880 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -3654,8 +3655,8 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command) (NewEnquiry->EventLogSequenceNumber != OldEnquiry->EventLogSequenceNumber) || Controller->MonitoringTimerCount == 0 || - (jiffies - Controller->SecondaryMonitoringTime - >= DAC960_SecondaryMonitoringInterval)) + time_after_eq(jiffies, Controller->SecondaryMonitoringTime + + DAC960_SecondaryMonitoringInterval)) { Controller->V1.NeedLogicalDriveInformation = true; Controller->V1.NewEventLogSequenceNumber = @@ -5640,8 +5641,8 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData) unsigned int StatusChangeCounter = Controller->V2.HealthStatusBuffer->StatusChangeCounter; boolean ForceMonitoringCommand = false; - if (jiffies - Controller->SecondaryMonitoringTime - > DAC960_SecondaryMonitoringInterval) + if (time_after(jiffies, Controller->SecondaryMonitoringTime + + DAC960_SecondaryMonitoringInterval)) { int LogicalDriveNumber; for (LogicalDriveNumber = 0; @@ -5669,8 +5670,8 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData) ControllerInfo->ConsistencyChecksActive + ControllerInfo->RebuildsActive + ControllerInfo->OnlineExpansionsActive == 0 || - jiffies - Controller->PrimaryMonitoringTime - < DAC960_MonitoringTimerInterval) && + time_before(jiffies, Controller->PrimaryMonitoringTime + + DAC960_MonitoringTimerInterval)) && !ForceMonitoringCommand) { Controller->MonitoringTimer.expires = @@ -5807,8 +5808,8 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, Controller->ProgressBufferLength = Length; if (Controller->EphemeralProgressMessage) { - if (jiffies - Controller->LastProgressReportTime - >= DAC960_ProgressReportingInterval) + if (time_after_eq(jiffies, Controller->LastProgressReportTime + + DAC960_ProgressReportingInterval)) { printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel], Controller->ControllerNumber, Buffer); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index d3ad9081697e..bedb689b051f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -170,6 +170,7 @@ static int print_unex = 1; #include #include #include +#include #include #include #include /* CMOS defines */ @@ -747,7 +748,7 @@ static int disk_change(int drive) { int fdc = FDC(drive); #ifdef FLOPPY_SANITY_CHECK - if (jiffies - UDRS->select_date < UDP->select_delay) + if (time_before(jiffies, UDRS->select_date + UDP->select_delay)) DPRINT("WARNING disk change called early\n"); if (!(FDCS->dor & (0x10 << UNIT(drive))) || (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) { @@ -1075,7 +1076,7 @@ static int fd_wait_for_completion(unsigned long delay, timeout_fn function) return 1; } - if ((signed)(jiffies - delay) < 0) { + if (time_before(jiffies, delay)) { del_timer(&fd_timer); fd_timer.function = function; fd_timer.expires = delay; @@ -1535,7 +1536,7 @@ static void setup_rw_floppy(void) * again just before spinup completion. Beware that * after scandrives, we must again wait for selection. */ - if ((signed)(ready_date - jiffies) > DP->select_delay) { + if (time_after(ready_date, jiffies + DP->select_delay)) { ready_date -= DP->select_delay; function = (timeout_fn) floppy_start; } else @@ -3823,7 +3824,7 @@ static int check_floppy_change(struct gendisk *disk) if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY)) return 1; - if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) { + if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { if (floppy_grab_irq_and_dma()) { return 1; } -- cgit v1.2.3-59-g8ed1b From 05613bdd8647bfc4535b0dcc8f1b95c8b39be394 Mon Sep 17 00:00:00 2001 From: Marcelo Feitoza Parisi Date: Tue, 28 Mar 2006 01:56:45 -0800 Subject: [PATCH] nvidia-agp: use time_before_eq() It deals with wrapping correctly and is nicer to read. Signed-off-by: Marcelo Feitoza Parisi Signed-off-by: Alexey Dobriyan Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/agp/nvidia-agp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 70b8ed9cd172..4c67135c12d8 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "agp.h" /* NVIDIA registers */ @@ -256,7 +257,7 @@ static void nvidia_tlbflush(struct agp_memory *mem) do { pci_read_config_dword(nvidia_private.dev_1, NVIDIA_1_WBC, &wbc_reg); - if ((signed)(end - jiffies) <= 0) { + if (time_before_eq(end, jiffies)) { printk(KERN_ERR PFX "TLB flush took more than 3 seconds.\n"); } -- cgit v1.2.3-59-g8ed1b From 9bae1ff3e7926fe5e92db2f3c6d8832f18f777bc Mon Sep 17 00:00:00 2001 From: Marcelo Feitoza Parisi Date: Tue, 28 Mar 2006 01:56:46 -0800 Subject: [PATCH] ide-tape: use time_after(), time_after_eq() They deal with wrapping correctly and are nicer to read. Signed-off-by: Marcelo Feitoza Parisi Signed-off-by: Alexey Dobriyan Cc: Bartlomiej Zolnierkiewicz Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-tape.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index ebc59064b475..f04791a58df0 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -433,6 +433,7 @@ #include #include #include +#include #include #include #include @@ -2336,7 +2337,7 @@ static ide_startstop_t idetape_rw_callback (ide_drive_t *drive) } if (time_after(jiffies, tape->insert_time)) tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); - if (jiffies - tape->avg_time >= HZ) { + if (time_after_eq(jiffies, tape->avg_time + HZ)) { tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024; tape->avg_size = 0; tape->avg_time = jiffies; @@ -2497,7 +2498,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, } else { return ide_do_reset(drive); } - } else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD) + } else if (time_after(jiffies, tape->dsc_polling_start + IDETAPE_DSC_MA_THRESHOLD)) tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW; idetape_postpone_request(drive); return ide_stopped; -- cgit v1.2.3-59-g8ed1b From 60c904ae5bded8bb71f7bff7d63f2a6959d2a8e4 Mon Sep 17 00:00:00 2001 From: Marcelo Feitoza Parisi Date: Tue, 28 Mar 2006 01:56:47 -0800 Subject: [PATCH] drivers/scsi/*: use time_after() and friends They deal with wrapping correctly and are nicer to read. Signed-off-by: Marcelo Feitoza Parisi Signed-off-by: Alexey Dobriyan Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/BusLogic.c | 3 ++- drivers/scsi/osst.c | 5 +++-- drivers/scsi/ppa.c | 3 ++- drivers/scsi/qlogicfc.c | 3 ++- drivers/scsi/qlogicpti.c | 3 ++- 5 files changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 1c459343292b..5bf83cbca868 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -2896,7 +2897,7 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou */ if (HostAdapter->ActiveCommands[TargetID] == 0) HostAdapter->LastSequencePoint[TargetID] = jiffies; - else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4 * HZ) { + else if (time_after(jiffies, HostAdapter->LastSequencePoint[TargetID] + 4 * HZ)) { HostAdapter->LastSequencePoint[TargetID] = jiffies; QueueTag = BusLogic_OrderedQueueTag; } diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 66ea47a9c53c..e3bd4bc339f4 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -49,6 +49,7 @@ static const char * osst_version = "0.99.4"; #include #include #include +#include #include #include #include @@ -856,7 +857,7 @@ static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt ) && result >= 0) { #if DEBUG - if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC) + if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC)) printk (OSST_DEB_MSG "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n", name, curr, curr+minlast, STp->first_frame_position, @@ -867,7 +868,7 @@ static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt return 0; } #if DEBUG - if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted) + if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted) { printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n", name, curr, curr+minlast, STp->first_frame_position, diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 05347eed9dd5..fee843fab1c7 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -726,7 +727,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) retv--; if (retv) { - if ((jiffies - dev->jstart) > (1 * HZ)) { + if (time_after(jiffies, dev->jstart + (1 * HZ))) { printk ("ppa: Parallel port cable is unplugged!!\n"); ppa_fail(dev, DID_BUS_BUSY); diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c index 94ef3f08d378..5b15998c71a6 100644 --- a/drivers/scsi/qlogicfc.c +++ b/drivers/scsi/qlogicfc.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include "scsi.h" @@ -1325,7 +1326,7 @@ static int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *)) cmd->control_flags = cpu_to_le16(CFLAG_READ); if (Cmnd->device->tagged_supported) { - if ((jiffies - hostdata->tag_ages[Cmnd->device->id]) > (2 * ISP_TIMEOUT)) { + if (time_after(jiffies, hostdata->tag_ages[Cmnd->device->id] + (2 * ISP_TIMEOUT))) { cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG); hostdata->tag_ages[Cmnd->device->id] = jiffies; } else diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 1fd5fc6d0fe3..c7e78dcf09df 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -1017,7 +1018,7 @@ static inline void cmd_frob(struct Command_Entry *cmd, struct scsi_cmnd *Cmnd, if (Cmnd->device->tagged_supported) { if (qpti->cmd_count[Cmnd->device->id] == 0) qpti->tag_ages[Cmnd->device->id] = jiffies; - if ((jiffies - qpti->tag_ages[Cmnd->device->id]) > (5*HZ)) { + if (time_after(jiffies, qpti->tag_ages[Cmnd->device->id] + (5*HZ))) { cmd->control_flags = CFLAG_ORDERED_TAG; qpti->tag_ages[Cmnd->device->id] = jiffies; } else -- cgit v1.2.3-59-g8ed1b From 910638ae7ed4be27d6af55f6c9b5bf54b838e78b Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Tue, 28 Mar 2006 01:56:48 -0800 Subject: [PATCH] Replace 0xff.. with correct DMA_xBIT_MASK Replace all occurences of 0xff.. in calls to function pci_set_dma_mask() and pci_set_consistant_dma_mask() with the corresponding DMA_xBIT_MASK from linux/dma-mapping.h. Signed-off-by: Matthias Gehre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DMA-mapping.txt | 2 ++ drivers/atm/lanai.c | 2 +- drivers/block/umem.c | 5 +++-- drivers/net/forcedeth.c | 3 ++- drivers/net/ioc3-eth.c | 7 ++++--- drivers/net/ns83820.c | 6 +++--- drivers/net/wan/wanxl.c | 4 ++-- drivers/net/wireless/prism54/islpci_hotplug.c | 3 ++- drivers/scsi/BusLogic.c | 7 ++++--- drivers/scsi/a100u2w.c | 3 ++- drivers/scsi/aacraid/aachba.c | 1 + drivers/scsi/aacraid/linit.c | 5 +++-- drivers/scsi/atp870u.c | 3 ++- drivers/scsi/dpt_i2o.c | 5 +++-- drivers/scsi/eata.c | 3 ++- drivers/scsi/gdth.c | 7 ++++--- drivers/scsi/initio.c | 3 ++- drivers/scsi/ips.c | 5 +++-- drivers/scsi/megaraid.c | 7 ++++--- drivers/scsi/nsp32.c | 3 ++- drivers/scsi/qla1280.c | 5 +++-- drivers/scsi/qlogicfc.c | 5 +++-- include/linux/dma-mapping.h | 1 + sound/oss/esssolo1.c | 2 +- sound/oss/sonicvibes.c | 3 ++- sound/pci/ad1889.c | 1 + sound/pci/ali5451/ali5451.c | 5 +++-- sound/pci/als4000.c | 5 +++-- sound/pci/azt3328.c | 5 +++-- sound/pci/emu10k1/emu10k1x.c | 1 + sound/pci/es1938.c | 5 +++-- sound/pci/es1968.c | 1 + sound/pci/ice1712/ice1712.c | 2 ++ sound/pci/maestro3.c | 1 + sound/pci/mixart/mixart.c | 2 ++ sound/pci/pcxhr/pcxhr.c | 1 + sound/pci/sonicvibes.c | 5 +++-- sound/pci/trident/trident_main.c | 5 +++-- 38 files changed, 88 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt index 684557474c15..ee4bb73683cd 100644 --- a/Documentation/DMA-mapping.txt +++ b/Documentation/DMA-mapping.txt @@ -199,6 +199,8 @@ address during PCI bus mastering you might do something like: "mydev: 24-bit DMA addressing not available.\n"); goto ignore_this_device; } +[Better use DMA_24BIT_MASK instead of 0x00ffffff. +See linux/include/dma-mapping.h for reference.] When pci_set_dma_mask() is successful, and returns zero, the PCI layer saves away this mask you have provided. The PCI layer will use this diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 69f4c7ce9a63..cac09e353be8 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -1972,7 +1972,7 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai) "(itf %d): No suitable DMA available.\n", lanai->number); return -EBUSY; } - if (pci_set_consistent_dma_mask(pci, 0xFFFFFFFF) != 0) { + if (pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) != 0) { printk(KERN_WARNING DEV_LABEL "(itf %d): No suitable DMA available.\n", lanai->number); return -EBUSY; diff --git a/drivers/block/umem.c b/drivers/block/umem.c index c16e66b9c7a7..f7d4c65a7b8c 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -50,6 +50,7 @@ #include #include #include +#include #include /* O_ACCMODE */ #include /* HDIO_GETGEO */ @@ -881,8 +882,8 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n", card->card_number, dev->bus->number, dev->devfn); - if (pci_set_dma_mask(dev, 0xffffffffffffffffLL) && - pci_set_dma_mask(dev, 0xffffffffLL)) { + if (pci_set_dma_mask(dev, DMA_64BIT_MASK) && + pci_set_dma_mask(dev, DMA_32BIT_MASK)) { printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards); return -ENOMEM; } diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index e7fc28b07e5a..7627a75f4f7c 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -134,6 +134,7 @@ #include #include #include +#include #include #include @@ -2932,7 +2933,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i if (id->driver_data & DEV_HAS_HIGH_DMA) { /* packet format 3: supports 40-bit addressing */ np->desc_ver = DESC_VER_3; - if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) { + if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) { printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", pci_name(pci_dev)); } else { diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 9b8295ee06ef..ae71ed57c12d 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -44,6 +44,7 @@ #include #include #include +#include #ifdef CONFIG_SERIAL_8250 #include @@ -1195,17 +1196,17 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int err, pci_using_dac; /* Configure DMA attributes. */ - err = pci_set_dma_mask(pdev, 0xffffffffffffffffULL); + err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); if (!err) { pci_using_dac = 1; - err = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); + err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); if (err < 0) { printk(KERN_ERR "%s: Unable to obtain 64 bit DMA " "for consistent allocations\n", pci_name(pdev)); goto out; } } else { - err = pci_set_dma_mask(pdev, 0xffffffffULL); + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (err) { printk(KERN_ERR "%s: No usable DMA configuration, " "aborting.\n", pci_name(pdev)); diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 0fede50abd3e..8e9b1a537dee 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -1828,10 +1828,10 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ int using_dac = 0; /* See if we can set the dma mask early on; failure is fatal. */ - if (sizeof(dma_addr_t) == 8 && - !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) { + if (sizeof(dma_addr_t) == 8 && + !pci_set_dma_mask(pci_dev, DMA_64BIT_MASK)) { using_dac = 1; - } else if (!pci_set_dma_mask(pci_dev, 0xffffffff)) { + } else if (!pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) { using_dac = 0; } else { printk(KERN_WARNING "ns83820.c: pci_set_dma_mask failed!\n"); diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 9d3b51c3ef54..29a756dd979b 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -577,8 +577,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, We set both dma_mask and consistent_dma_mask to 28 bits and pray pci_alloc_consistent() will use this info. It should work on most platforms */ - if (pci_set_consistent_dma_mask(pdev, 0x0FFFFFFF) || - pci_set_dma_mask(pdev, 0x0FFFFFFF)) { + if (pci_set_consistent_dma_mask(pdev, DMA_28BIT_MASK) || + pci_set_dma_mask(pdev, DMA_28BIT_MASK)) { printk(KERN_ERR "wanXL: No usable DMA configuration\n"); return -EIO; } diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index b41d666fea3c..bfa0cc319a09 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -22,6 +22,7 @@ #include #include #include /* For __init, __exit */ +#include #include "prismcompat.h" #include "islpci_dev.h" @@ -124,7 +125,7 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) } /* enable PCI DMA */ - if (pci_set_dma_mask(pdev, 0xffffffff)) { + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_ERR "%s: 32-bit PCI DMA not supported", DRV_NAME); goto do_pci_disable_device; } diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 5bf83cbca868..bde3d5834ade 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -677,7 +678,7 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd if (pci_enable_device(PCI_Device)) continue; - if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff)) + if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK )) continue; Bus = PCI_Device->bus->number; @@ -832,7 +833,7 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd if (pci_enable_device(PCI_Device)) continue; - if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff)) + if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK)) continue; Bus = PCI_Device->bus->number; @@ -886,7 +887,7 @@ static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAda if (pci_enable_device(PCI_Device)) continue; - if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff)) + if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK)) continue; Bus = PCI_Device->bus->number; diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 9f45ae1745da..3dce21c78737 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -89,6 +89,7 @@ #include #include #include +#include #include #include @@ -1052,7 +1053,7 @@ static int __devinit inia100_probe_one(struct pci_dev *pdev, if (pci_enable_device(pdev)) goto out; - if (pci_set_dma_mask(pdev, 0xffffffffULL)) { + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "Unable to set 32bit DMA " "on inia100 adapter, ignoring.\n"); goto out_disable_device; diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index a16f8ded8f1d..8df4a0ea3761 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index c2596335549d..720330778648 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -806,8 +807,8 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, * to driver communication memory to be allocated below 2gig */ if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) - if (pci_set_dma_mask(pdev, 0x7FFFFFFFULL) || - pci_set_consistent_dma_mask(pdev, 0x7FFFFFFFULL)) + if (pci_set_dma_mask(pdev, DMA_31BIT_MASK) || + pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK)) goto out; pci_set_master(pdev); diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 5227a779c05c..a198d86667e9 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -2631,7 +2632,7 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_enable_device(pdev)) return -EIO; - if (!pci_set_dma_mask(pdev, 0xFFFFFFFFUL)) { + if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_INFO "atp870u: use 32bit DMA mask.\n"); } else { printk(KERN_ERR "atp870u: DMA mask required but not available.\n"); diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 6e6b293dcb28..b1b704a42efd 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -57,6 +57,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver"); #include #include #include +#include #include #include @@ -906,8 +907,8 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev } pci_set_master(pDev); - if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) && - pci_set_dma_mask(pDev, 0xffffffffULL)) + if (pci_set_dma_mask(pDev, DMA_64BIT_MASK) && + pci_set_dma_mask(pDev, DMA_32BIT_MASK)) return -EINVAL; base_addr0_phys = pci_resource_start(pDev,0); diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index b3f9de8f7595..059eeee4b554 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -490,6 +490,7 @@ #include #include #include +#include #include #include #include @@ -1426,7 +1427,7 @@ static int port_detect(unsigned long port_base, unsigned int j, if (ha->pdev) { pci_set_master(ha->pdev); - if (pci_set_dma_mask(ha->pdev, 0xffffffff)) + if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) printk("%s: warning, pci_set_dma_mask failed.\n", ha->board_name); } diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 7f7013e80a88..d5740bbdef3e 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -388,6 +388,7 @@ #include #include #include +#include #ifdef GDTH_RTC #include #endif @@ -4527,15 +4528,15 @@ static int __init gdth_detect(struct scsi_host_template *shtp) if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)|| /* 64-bit DMA only supported from FW >= x.43 */ (!ha->dma64_support)) { - if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) { + if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum); err = TRUE; } } else { shp->max_cmd_len = 16; - if (!pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffffffffffffULL)) { + if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) { printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum); - } else if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) { + } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum); err = TRUE; } diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index ea6f3c0e05d9..0cc7f65b584f 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -127,6 +127,7 @@ #include #include #include +#include #include #include @@ -2780,7 +2781,7 @@ static int tul_NewReturnNumberOfAdapters(void) if (((dRegValue & 0xFF00) >> 8) == 0xFF) dRegValue = 0; wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); - if (pci_set_dma_mask(pDev, 0xffffffff)) { + if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) { printk(KERN_WARNING "i91u: Could not set 32 bit DMA mask\n"); continue; diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 481708d527ae..a4c0b04cfdbd 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -179,6 +179,7 @@ #include #include +#include #include @@ -7284,10 +7285,10 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr) * are guaranteed to be < 4G. */ if (IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) && - !pci_set_dma_mask(ha->pcidev, 0xffffffffffffffffULL)) { + !pci_set_dma_mask(ha->pcidev, DMA_64BIT_MASK)) { (ha)->flags |= IPS_HA_ENH_SG; } else { - if (pci_set_dma_mask(ha->pcidev, 0xffffffffULL) != 0) { + if (pci_set_dma_mask(ha->pcidev, DMA_32BIT_MASK) != 0) { printk(KERN_WARNING "Unable to set DMA Mask\n"); return ips_abort_init(ha, index); } diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 7144674bc8e6..80b68a2481b3 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include "scsi.h" @@ -2094,7 +2095,7 @@ make_local_pdev(adapter_t *adapter, struct pci_dev **pdev) memcpy(*pdev, adapter->dev, sizeof(struct pci_dev)); - if( pci_set_dma_mask(*pdev, 0xffffffff) != 0 ) { + if( pci_set_dma_mask(*pdev, DMA_32BIT_MASK) != 0 ) { kfree(*pdev); return -1; } @@ -4859,10 +4860,10 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) /* Set the Mode of addressing to 64 bit if we can */ if ((adapter->flag & BOARD_64BIT) && (sizeof(dma_addr_t) == 8)) { - pci_set_dma_mask(pdev, 0xffffffffffffffffULL); + pci_set_dma_mask(pdev, DMA_64BIT_MASK); adapter->has_64bit_addr = 1; } else { - pci_set_dma_mask(pdev, 0xffffffff); + pci_set_dma_mask(pdev, DMA_32BIT_MASK); adapter->has_64bit_addr = 0; } diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index a279ebb61447..30ee0ef4b459 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -2776,7 +2777,7 @@ static int nsp32_detect(struct scsi_host_template *sht) /* * setup DMA */ - if (pci_set_dma_mask(PCIDEV, 0xffffffffUL) != 0) { + if (pci_set_dma_mask(PCIDEV, DMA_32BIT_MASK) != 0) { nsp32_msg (KERN_ERR, "failed to set PCI DMA mask"); goto scsi_unregister; } diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index e0230249fa0f..5a48e55f9418 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -350,6 +350,7 @@ #include #include #include +#include #include #include @@ -4321,7 +4322,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) #ifdef QLA_64BIT_PTR if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) { - if (pci_set_dma_mask(ha->pdev, 0xffffffff)) { + if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "scsi(%li): Unable to set a " "suitable DMA mask - aborting\n", ha->host_no); error = -ENODEV; @@ -4331,7 +4332,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n", ha->host_no); #else - if (pci_set_dma_mask(ha->pdev, 0xffffffff)) { + if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "scsi(%li): Unable to set a " "suitable DMA mask - aborting\n", ha->host_no); error = -ENODEV; diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c index 5b15998c71a6..52b224a5d6fd 100644 --- a/drivers/scsi/qlogicfc.c +++ b/drivers/scsi/qlogicfc.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -738,8 +739,8 @@ static int isp2x00_detect(struct scsi_host_template * tmpt) continue; /* Try to configure DMA attributes. */ - if (pci_set_dma_mask(pdev, 0xffffffffffffffffULL) && - pci_set_dma_mask(pdev, 0xffffffffULL)) + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) && + pci_set_dma_mask(pdev, DMA_32BIT_MASK)) continue; host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata)); diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index a8731062a74c..9b4751aecc23 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -21,6 +21,7 @@ enum dma_data_direction { #define DMA_30BIT_MASK 0x000000003fffffffULL #define DMA_29BIT_MASK 0x000000001fffffffULL #define DMA_28BIT_MASK 0x000000000fffffffULL +#define DMA_24BIT_MASK 0x0000000000ffffffULL #include diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c index 78d3e29ce968..6861563d7525 100644 --- a/sound/oss/esssolo1.c +++ b/sound/oss/esssolo1.c @@ -2348,7 +2348,7 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device /* Recording requires 24-bit DMA, so attempt to set dma mask * to 24 bits first, then 32 bits (playback only) if that fails. */ - if (pci_set_dma_mask(pcidev, 0x00ffffff) && + if (pci_set_dma_mask(pcidev, DMA_24BIT_MASK) && pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) { printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n"); return -ENODEV; diff --git a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c index 4471757b7985..42bd276cfc39 100644 --- a/sound/oss/sonicvibes.c +++ b/sound/oss/sonicvibes.c @@ -116,6 +116,7 @@ #include #include #include +#include #include @@ -2535,7 +2536,7 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id return -ENODEV; if (pcidev->irq == 0) return -ENODEV; - if (pci_set_dma_mask(pcidev, 0x00ffffff)) { + if (pci_set_dma_mask(pcidev, DMA_24BIT_MASK)) { printk(KERN_WARNING "sonicvibes: architecture does not support 24bit PCI busmaster DMA\n"); return -ENODEV; } diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 2aa5a7fdb6e0..c6c8333acc62 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index e264136e8fb4..fc92b6896c24 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -2220,8 +2221,8 @@ static int __devinit snd_ali_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; /* check, if we can restrict PCI DMA transfers to 31 bits */ - if (pci_set_dma_mask(pci, 0x7fffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x7fffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_31BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_31BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 31bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 7b2ff5f4672e..100d8127a411 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -688,8 +689,8 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, return err; } /* check, if we can restrict PCI DMA transfers to 24 bits */ - if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index e077eb3fbe2f..680077e1e057 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -104,6 +104,7 @@ #include #include #include +#include #include #include #include @@ -1669,8 +1670,8 @@ snd_azf3328_create(struct snd_card *card, chip->irq = -1; /* check if we can restrict PCI DMA transfers to 24 bits */ - if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); err = -ENXIO; goto out_err; diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 2208dbd48be9..3e332f398162 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 0d556b09ad04..4d62fe439177 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -1517,8 +1518,8 @@ static int __devinit snd_es1938_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; /* check, if we can restrict PCI DMA transfers to 24 bits */ - if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index dd465a186e11..e3ad17f53c29 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -104,6 +104,7 @@ #include #include #include +#include #include #include diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 672e198317e1..b88eeba2f5d1 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -56,7 +56,9 @@ #include #include #include +#include #include + #include #include #include diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 8bc084956c28..44393e190929 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 43ee3b2b948f..b5a095052d4c 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -28,6 +28,8 @@ #include #include #include +#include + #include #include #include diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index f679779d96e3..35875c8aa299 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 7bbea3738b8a..2d66a09fe5ee 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -1227,8 +1228,8 @@ static int __devinit snd_sonicvibes_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; /* check, if we can restrict PCI DMA transfers to 24 bits */ - if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 83b7d8aba9e6..52178b8ad49d 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -3554,8 +3555,8 @@ int __devinit snd_trident_create(struct snd_card *card, if ((err = pci_enable_device(pci)) < 0) return err; /* check, if we can restrict PCI DMA transfers to 30 bits */ - if (pci_set_dma_mask(pci, 0x3fffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x3fffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_30BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_30BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 30bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; -- cgit v1.2.3-59-g8ed1b From 7f927fcc2fd1575d01efb4b76665975007945690 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 28 Mar 2006 01:56:53 -0800 Subject: [PATCH] Typo fixes Fix a lot of typos. Eyeballed by jmc@ in OpenBSD. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/m68k/README.buddha | 2 +- Documentation/networking/ifenslave.c | 2 +- arch/arm/lib/copy_template.S | 2 +- drivers/char/mxser.h | 2 +- drivers/char/synclink.c | 2 +- drivers/edac/edac_mc.c | 2 +- drivers/net/irda/nsc-ircc.c | 2 +- drivers/net/sis900.c | 2 +- drivers/net/tulip/de4x5.c | 2 +- drivers/net/tulip/pnic2.c | 2 +- drivers/net/typhoon.c | 4 ++-- drivers/net/wireless/orinoco.c | 2 +- drivers/net/wireless/prism54/isl_ioctl.c | 2 +- drivers/scsi/3w-9xxx.c | 2 +- drivers/serial/8250.c | 2 +- drivers/serial/serial_txx9.c | 2 +- drivers/serial/sunsu.c | 2 +- drivers/usb/host/ohci-s3c2410.c | 2 +- drivers/usb/net/zaurus.c | 2 +- fs/mbcache.c | 2 +- include/asm-parisc/pdc.h | 2 +- include/asm-sh/addrspace.h | 2 +- include/asm-sparc64/floppy.h | 2 +- include/linux/fb.h | 2 +- mm/mempolicy.c | 2 +- net/irda/af_irda.c | 6 +++--- sound/pci/rme32.c | 8 ++++---- sound/pci/rme96.c | 8 ++++---- sound/pci/rme9652/hdspm.c | 2 +- sound/usb/usx2y/usx2yhwdeppcm.c | 2 +- 30 files changed, 39 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/Documentation/m68k/README.buddha b/Documentation/m68k/README.buddha index bf802ffc98ad..ef484a719bb9 100644 --- a/Documentation/m68k/README.buddha +++ b/Documentation/m68k/README.buddha @@ -29,7 +29,7 @@ address is written to $4a, then the whole Byte is written to $48, while it doesn't matter how often you're writing to $4a as long as $48 is not touched. After $48 has been written, the whole card disappears from $e8 and is mapped to the new -address just written. Make shure $4a is written before $48, +address just written. Make sure $4a is written before $48, otherwise your chance is only 1:16 to find the board :-). The local memory-map is even active when mapped to $e8: diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c index 545447ac503a..a12059886755 100644 --- a/Documentation/networking/ifenslave.c +++ b/Documentation/networking/ifenslave.c @@ -87,7 +87,7 @@ * would fail and generate an error message in the system log. * - For opt_c: slave should not be set to the master's setting * while it is running. It was already set during enslave. To - * simplify things, it is now handeled separately. + * simplify things, it is now handled separately. * * - 2003/12/01 - Shmulik Hen * - Code cleanup and style changes diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S index 838e435e4922..cab355c0c1f7 100644 --- a/arch/arm/lib/copy_template.S +++ b/arch/arm/lib/copy_template.S @@ -236,7 +236,7 @@ /* - * Abort preanble and completion macros. + * Abort preamble and completion macros. * If a fixup handler is required then those macros must surround it. * It is assumed that the fixup code will handle the private part of * the exit macro. diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h index e7fd0b08e0b7..7e188a4d602a 100644 --- a/drivers/char/mxser.h +++ b/drivers/char/mxser.h @@ -118,7 +118,7 @@ // enable CTS interrupt #define MOXA_MUST_IER_ECTSI 0x80 -// eanble RTS interrupt +// enable RTS interrupt #define MOXA_MUST_IER_ERTSI 0x40 // enable Xon/Xoff interrupt #define MOXA_MUST_IER_XINT 0x20 diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index abb03e52fe12..fee2aca3f6a5 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -5996,7 +5996,7 @@ static void usc_set_async_mode( struct mgsl_struct *info ) * <15..8> ? RxFIFO IRQ Request Level * * Note: For async mode the receive FIFO level must be set - * to 0 to aviod the situation where the FIFO contains fewer bytes + * to 0 to avoid the situation where the FIFO contains fewer bytes * than the trigger level and no more data is expected. * * <7> 0 Exited Hunt IA (Interrupt Arm) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 905f58ba8e16..ea06e3a4dc35 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -2044,7 +2044,7 @@ static int __init edac_mc_init(void) */ clear_pci_parity_errors(); - /* Create the MC sysfs entires */ + /* Create the MC sysfs entries */ if (edac_sysfs_memctrl_setup()) { edac_printk(KERN_ERR, EDAC_MC, "Error initializing sysfs code\n"); diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 9aa074b44dd3..cc7ff8f00e42 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -812,7 +812,7 @@ static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info) int cfg_base = info->cfg_base; int enabled; - /* User is shure about his config... accept it. */ + /* User is sure about his config... accept it. */ IRDA_DEBUG(2, "%s(): nsc_ircc_init_39x (user settings): " "io=0x%04x, irq=%d, dma=%d\n", __FUNCTION__, info->fir_base, info->irq, info->dma); diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 8429ceb01389..b82191d2bee1 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -2283,7 +2283,7 @@ static void set_rx_mode(struct net_device *net_dev) int i, table_entries; u32 rx_mode; - /* 635 Hash Table entires = 256(2^16) */ + /* 635 Hash Table entries = 256(2^16) */ if((sis_priv->chipset_rev >= SIS635A_900_REV) || (sis_priv->chipset_rev == SIS900B_900_REV)) table_entries = 16; diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index ee48bfd67349..d1a86a080a65 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -513,7 +513,7 @@ struct mii_phy { u_char *rst; /* Start of reset sequence in SROM */ u_int mc; /* Media Capabilities */ u_int ana; /* NWay Advertisement */ - u_int fdx; /* Full DupleX capabilites for each media */ + u_int fdx; /* Full DupleX capabilities for each media */ u_int ttm; /* Transmit Threshold Mode for each media */ u_int mci; /* 21142 MII Connector Interrupt info */ }; diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c index 55f4a9a631bc..ab985023fcca 100644 --- a/drivers/net/tulip/pnic2.c +++ b/drivers/net/tulip/pnic2.c @@ -199,7 +199,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) /* negotiation ended successfully */ /* get the link partners reply and mask out all but - * bits 24-21 which show the partners capabilites + * bits 24-21 which show the partners capabilities * and match those to what we advertised * * then begin to interpret the results of the negotiation. diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index cde35dd87906..c1ce87a5f8d3 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -208,7 +208,7 @@ static const struct typhoon_card_info typhoon_card_info[] __devinitdata = { }; /* Notes on the new subsystem numbering scheme: - * bits 0-1 indicate crypto capabilites: (0) variable, (1) DES, or (2) 3DES + * bits 0-1 indicate crypto capabilities: (0) variable, (1) DES, or (2) 3DES * bit 4 indicates if this card has secured firmware (we don't support it) * bit 8 indicates if this is a (0) copper or (1) fiber card * bits 12-16 indicate card type: (0) client and (1) server @@ -788,7 +788,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) /* we have two rings to choose from, but we only use txLo for now * If we start using the Hi ring as well, we'll need to update * typhoon_stop_runtime(), typhoon_interrupt(), typhoon_num_free_tx(), - * and TXHI_ENTIRES to match, as well as update the TSO code below + * and TXHI_ENTRIES to match, as well as update the TSO code below * to get the right DMA address */ txRing = &tp->txLoRing; diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 6fd0bf736830..8dfdfbd5966c 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -3858,7 +3858,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev, unsigned long flags; /* Note : you may have realised that, as this is a SET operation, - * this is priviledged and therefore a normal user can't + * this is privileged and therefore a normal user can't * perform scanning. * This is not an error, while the device perform scanning, * traffic doesn't flow, so it's a perfect DoS... diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index e5bb9f5ae429..989599ad33ef 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -747,7 +747,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info, if (essid->length) { dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */ - /* if it is to big, trunk it */ + /* if it is too big, trunk it */ dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length); } else { dwrq->flags = 0; diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 0ab26d01877b..0d2b447c50ed 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -1026,7 +1026,7 @@ static void twa_free_request_id(TW_Device_Extension *tw_dev, int request_id) tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH; } /* End twa_free_request_id() */ -/* This function will get parameter table entires from the firmware */ +/* This function will get parameter table entries from the firmware */ static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes) { TW_Command_Full *full_command_packet; diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 5996d3cd0ed8..674b15c78f68 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1528,7 +1528,7 @@ static int serial8250_startup(struct uart_port *port) /* * Clear the FIFO buffers and disable them. - * (they will be reeanbled in set_termios()) + * (they will be reenabled in set_termios()) */ serial8250_clear_fifos(up); diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index b848b7d94412..3bdee64d1a99 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -483,7 +483,7 @@ static int serial_txx9_startup(struct uart_port *port) /* * Clear the FIFO buffers and disable them. - * (they will be reeanbled in set_termios()) + * (they will be reenabled in set_termios()) */ sio_set(up, TXX9_SIFCR, TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE); diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 9fe2283d91e5..1c4396c2962d 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -641,7 +641,7 @@ static int sunsu_startup(struct uart_port *port) /* * Clear the FIFO buffers and disable them. - * (they will be reeanbled in set_termios()) + * (they will be reenabled in set_termios()) */ if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) { serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 372527a83593..682bf2215660 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -158,7 +158,7 @@ static int ohci_s3c2410_hub_control ( "s3c2410_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n", hcd, typeReq, wValue, wIndex, buf, wLength); - /* if we are only an humble host without any special capabilites + /* if we are only an humble host without any special capabilities * process the request straight away and exit */ if (info == NULL) { diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c index 9c5ab251370c..f7ac9d6b9856 100644 --- a/drivers/usb/net/zaurus.c +++ b/drivers/usb/net/zaurus.c @@ -217,7 +217,7 @@ static int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf) * with devices that use it and those that don't. */ if ((detail->bDetailData[1] & ~0x02) != 0x01) { - /* bmDataCapabilites == 0 would be fine too, + /* bmDataCapabilities == 0 would be fine too, * but framing is minidriver-coupled for now. */ bad_detail: diff --git a/fs/mbcache.c b/fs/mbcache.c index 73e754fea2d8..e4fde1ab22cd 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -311,7 +311,7 @@ fail: /* * mb_cache_shrink() * - * Removes all cache entires of a device from the cache. All cache entries + * Removes all cache entries of a device from the cache. All cache entries * currently in use cannot be freed, and thus remain in the cache. All others * are freed. * diff --git a/include/asm-parisc/pdc.h b/include/asm-parisc/pdc.h index 8e23e4c674f6..0a3face6c480 100644 --- a/include/asm-parisc/pdc.h +++ b/include/asm-parisc/pdc.h @@ -333,7 +333,7 @@ struct pdc_model { /* for PDC_MODEL */ unsigned long curr_key; }; -/* Values for PDC_MODEL_CAPABILITES non-equivalent virtual aliasing support */ +/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */ #define PDC_MODEL_IOPDIR_FDC (1 << 2) /* see sba_iommu.c */ #define PDC_MODEL_NVA_MASK (3 << 4) diff --git a/include/asm-sh/addrspace.h b/include/asm-sh/addrspace.h index dbb05d1a26d1..720afc11c2ca 100644 --- a/include/asm-sh/addrspace.h +++ b/include/asm-sh/addrspace.h @@ -13,7 +13,7 @@ #include -/* Memory segments (32bit Priviledged mode addresses) */ +/* Memory segments (32bit Privileged mode addresses) */ #define P0SEG 0x00000000 #define P1SEG 0x80000000 #define P2SEG 0xa0000000 diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h index 49d49a285943..6a95d5d0c576 100644 --- a/include/asm-sparc64/floppy.h +++ b/include/asm-sparc64/floppy.h @@ -738,7 +738,7 @@ static unsigned long __init sun_floppy_init(void) if (!sun_floppy_types[0] && sun_floppy_types[1]) { /* * Set the drive exchange bit in FCR on NS87303, - * make shure other bits are sane before doing so. + * make sure other bits are sane before doing so. */ ns87303_modify(config, FER, FER_EDM, 0); ns87303_modify(config, ASC, ASC_DRV2_SEL, 0); diff --git a/include/linux/fb.h b/include/linux/fb.h index 2cb19e6503aa..d03fadfcafe3 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -734,7 +734,7 @@ struct fb_tile_ops { /* A driver may set this flag to indicate that it does want a set_par to be * called every time when fbcon_switch is executed. The advantage is that with - * this flag set you can really be shure that set_par is always called before + * this flag set you can really be sure that set_par is always called before * any of the functions dependant on the correct hardware state or altering * that state, even if you are using some broken X releases. The disadvantage * is that it introduces unwanted delays to every console switch if set_par diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 4f71cfd29c6f..dec8249e972d 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -912,7 +912,7 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, /* * Check if this process has the right to modify the specified * process. The right exists if the process has administrative - * capabilities, superuser priviledges or the same + * capabilities, superuser privileges or the same * userid as the target process. */ if ((current->euid != task->suid) && (current->euid != task->uid) && diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 759445648667..627b11342233 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -1302,7 +1302,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, if (sk->sk_state != TCP_ESTABLISHED) return -ENOTCONN; - /* Check that we don't send out to big frames */ + /* Check that we don't send out too big frames */ if (len > self->max_data_size) { IRDA_DEBUG(2, "%s(), Chopping frame from %zd to %d bytes!\n", __FUNCTION__, len, self->max_data_size); @@ -1546,7 +1546,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, IRDA_ASSERT(self != NULL, return -1;); /* - * Check that we don't send out to big frames. This is an unreliable + * Check that we don't send out too big frames. This is an unreliable * service, so we have no fragmentation and no coalescence */ if (len > self->max_data_size) { @@ -1642,7 +1642,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, } /* - * Check that we don't send out to big frames. This is an unreliable + * Check that we don't send out too big frames. This is an unreliable * service, so we have no fragmentation and no coalescence */ if (len > self->max_data_size) { diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 0cbef5fe6c63..ab78544bf042 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -313,7 +313,7 @@ static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int chann } /* - * SPDIF I/O capabilites (half-duplex mode) + * SPDIF I/O capabilities (half-duplex mode) */ static struct snd_pcm_hardware snd_rme32_spdif_info = { .info = (SNDRV_PCM_INFO_MMAP_IOMEM | @@ -339,7 +339,7 @@ static struct snd_pcm_hardware snd_rme32_spdif_info = { }; /* - * ADAT I/O capabilites (half-duplex mode) + * ADAT I/O capabilities (half-duplex mode) */ static struct snd_pcm_hardware snd_rme32_adat_info = { @@ -364,7 +364,7 @@ static struct snd_pcm_hardware snd_rme32_adat_info = }; /* - * SPDIF I/O capabilites (full-duplex mode) + * SPDIF I/O capabilities (full-duplex mode) */ static struct snd_pcm_hardware snd_rme32_spdif_fd_info = { .info = (SNDRV_PCM_INFO_MMAP | @@ -390,7 +390,7 @@ static struct snd_pcm_hardware snd_rme32_spdif_fd_info = { }; /* - * ADAT I/O capabilites (full-duplex mode) + * ADAT I/O capabilities (full-duplex mode) */ static struct snd_pcm_hardware snd_rme32_adat_fd_info = { diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 0e694b011dcc..6c2a9f4a7659 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -359,7 +359,7 @@ snd_rme96_capture_copy(struct snd_pcm_substream *substream, } /* - * Digital output capabilites (S/PDIF) + * Digital output capabilities (S/PDIF) */ static struct snd_pcm_hardware snd_rme96_playback_spdif_info = { @@ -388,7 +388,7 @@ static struct snd_pcm_hardware snd_rme96_playback_spdif_info = }; /* - * Digital input capabilites (S/PDIF) + * Digital input capabilities (S/PDIF) */ static struct snd_pcm_hardware snd_rme96_capture_spdif_info = { @@ -417,7 +417,7 @@ static struct snd_pcm_hardware snd_rme96_capture_spdif_info = }; /* - * Digital output capabilites (ADAT) + * Digital output capabilities (ADAT) */ static struct snd_pcm_hardware snd_rme96_playback_adat_info = { @@ -442,7 +442,7 @@ static struct snd_pcm_hardware snd_rme96_playback_adat_info = }; /* - * Digital input capabilites (ADAT) + * Digital input capabilities (ADAT) */ static struct snd_pcm_hardware snd_rme96_capture_adat_info = { diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 980b9cd689dd..b5538efd146b 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -2256,7 +2256,7 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm } /* Channel playback mixer as default control - Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats to big for any alsamixer + Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer they are accesible via special IOCTL on hwdep and the mixer 2dimensional mixer control */ diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 315855082fe1..fe67a92e2a1a 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -404,7 +404,7 @@ static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs) struct usX2Ydev * usX2Y = subs->usX2Y; usX2Y->prepare_subs = subs; subs->urb[0]->start_frame = -1; - smp_wmb(); // Make shure above modifications are seen by i_usX2Y_subs_startup() + smp_wmb(); // Make sure above modifications are seen by i_usX2Y_subs_startup() usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup); } -- cgit v1.2.3-59-g8ed1b From c326e27eb79e98050d855e371ac534ff4352e910 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Mon, 27 Mar 2006 22:55:55 +0200 Subject: [CPUFREQ] cpufreq_conservative: keep ignore_nice_load and freq_step values when reselected Keep the value of ignore_nice_load and freq_step of the conservative governor after the governor is deselected and reselected. Signed-off-by: Mattia Dongili Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index a152d2c46be7..037f6bf4543c 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -88,6 +88,8 @@ static struct dbs_tuners dbs_tuners_ins = { .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, + .ignore_nice = 0, + .freq_step = 5, }; static inline unsigned int get_cpu_idle_time(unsigned int cpu) @@ -490,8 +492,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, def_sampling_rate = MIN_STAT_SAMPLING_RATE; dbs_tuners_ins.sampling_rate = def_sampling_rate; - dbs_tuners_ins.ignore_nice = 0; - dbs_tuners_ins.freq_step = 5; dbs_timer_init(); } -- cgit v1.2.3-59-g8ed1b From d2b58b58838159b2afdc624f74b208e8bd3c029e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 29 Mar 2006 08:12:52 +1000 Subject: drm: sis fix compile warning Prevent a gcc warning in the SIS DRM driver. offset is a unsigned int and the printk wants a long. Signed-off-by: Jon Mason Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/char/drm/sis_mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c index 6774d2fe3452..5e9936bc307f 100644 --- a/drivers/char/drm/sis_mm.c +++ b/drivers/char/drm/sis_mm.c @@ -110,7 +110,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS) DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); - DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset); + DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset); return retval; } -- cgit v1.2.3-59-g8ed1b From 55eb061326765b2d0489387cfb3fc7dbd244f917 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 29 Mar 2006 08:16:12 +1000 Subject: drm: remove drm_{alloc,free}_pages drm_alloc_pages and drm_free_pages can now be removed. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/char/drm/drmP.h | 2 -- drivers/char/drm/drm_memory.c | 59 ------------------------------- drivers/char/drm/drm_memory_debug.h | 70 ------------------------------------- 3 files changed, 131 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index dbe952f899c0..edc72a6348a7 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -813,8 +813,6 @@ extern void drm_mem_init(void); extern int drm_mem_info(char *buf, char **start, off_t offset, int request, int *eof, void *data); extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); -extern unsigned long drm_alloc_pages(int order, int area); -extern void drm_free_pages(unsigned long address, int order, int area); extern void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t * dev); extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size, diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index 8074771e348f..dddf8de66143 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c @@ -79,65 +79,6 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) return pt; } -/** - * Allocate pages. - * - * \param order size order. - * \param area memory area. (Not used.) - * \return page address on success, or zero on failure. - * - * Allocate and reserve free pages. - */ -unsigned long drm_alloc_pages(int order, int area) -{ - unsigned long address; - unsigned long bytes = PAGE_SIZE << order; - unsigned long addr; - unsigned int sz; - - address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); - if (!address) - return 0; - - /* Zero */ - memset((void *)address, 0, bytes); - - /* Reserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - SetPageReserved(virt_to_page(addr)); - } - - return address; -} - -/** - * Free pages. - * - * \param address address of the pages to free. - * \param order size order. - * \param area memory area. (Not used.) - * - * Unreserve and free pages allocated by alloc_pages(). - */ -void drm_free_pages(unsigned long address, int order, int area) -{ - unsigned long bytes = PAGE_SIZE << order; - unsigned long addr; - unsigned int sz; - - if (!address) - return; - - /* Unreserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - } - - free_pages(address, order); -} - #if __OS_HAS_AGP /** Wrapper around agp_allocate_memory() */ DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type) diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h index e84605fc54af..7868341817da 100644 --- a/drivers/char/drm/drm_memory_debug.h +++ b/drivers/char/drm/drm_memory_debug.h @@ -206,76 +206,6 @@ void drm_free (void *pt, size_t size, int area) { } } -unsigned long drm_alloc_pages (int order, int area) { - unsigned long address; - unsigned long bytes = PAGE_SIZE << order; - unsigned long addr; - unsigned int sz; - - spin_lock(&drm_mem_lock); - if ((drm_ram_used >> PAGE_SHIFT) - > (DRM_RAM_PERCENT * drm_ram_available) / 100) { - spin_unlock(&drm_mem_lock); - return 0; - } - spin_unlock(&drm_mem_lock); - - address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); - if (!address) { - spin_lock(&drm_mem_lock); - ++drm_mem_stats[area].fail_count; - spin_unlock(&drm_mem_lock); - return 0; - } - spin_lock(&drm_mem_lock); - ++drm_mem_stats[area].succeed_count; - drm_mem_stats[area].bytes_allocated += bytes; - drm_ram_used += bytes; - spin_unlock(&drm_mem_lock); - - /* Zero outside the lock */ - memset((void *)address, 0, bytes); - - /* Reserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - SetPageReserved(virt_to_page(addr)); - } - - return address; -} - -void drm_free_pages (unsigned long address, int order, int area) { - unsigned long bytes = PAGE_SIZE << order; - int alloc_count; - int free_count; - unsigned long addr; - unsigned int sz; - - if (!address) { - DRM_MEM_ERROR(area, "Attempt to free address 0\n"); - } else { - /* Unreserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - } - free_pages(address, order); - } - - spin_lock(&drm_mem_lock); - free_count = ++drm_mem_stats[area].free_count; - alloc_count = drm_mem_stats[area].succeed_count; - drm_mem_stats[area].bytes_freed += bytes; - drm_ram_used -= bytes; - spin_unlock(&drm_mem_lock); - if (free_count > alloc_count) { - DRM_MEM_ERROR(area, - "Excess frees: %d frees, %d allocs\n", - free_count, alloc_count); - } -} - void *drm_ioremap (unsigned long offset, unsigned long size, drm_device_t * dev) { void *pt; -- cgit v1.2.3-59-g8ed1b From 147830f297f369fa8731a75e3e4c7c7cd5c3e868 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 28 Mar 2006 19:54:52 -0500 Subject: sbp2: prevent unloading of 1394 low-level driver When a new SBP-2 unit is added, sbp2 now takes a reference on the 1394 low-level driver (ohci1394 or pcilynx). This prevents the 1394 host driver module from being unloaded, e.g. by an administrative routine cleanup of unused kernel modules or when another 1394 driver which depends on ohci1394 is unloaded. The reference is dropped when the SBP-2 unit was disconnected, when sbp2 is unloaded or detached from the unit, or when addition of the SBP-2 unit failed. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre --- drivers/ieee1394/sbp2.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index eca92eb475a1..0b2b0da5b883 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -755,6 +755,12 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud #endif } + /* Prevent unloading of the 1394 host */ + if (!try_module_get(hi->host->driver->owner)) { + SBP2_ERR("failed to get a reference on 1394 host driver"); + goto failed_alloc; + } + scsi_id->hi = hi; list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids); @@ -1015,6 +1021,9 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) scsi_id->ud->device.driver_data = NULL; + if (hi) + module_put(hi->host->driver->owner); + SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id); kfree(scsi_id); -- cgit v1.2.3-59-g8ed1b From e2f8165dc3c70cd74bcf2c63a6c0de254c6ff50c Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Tue, 28 Mar 2006 19:55:11 -0500 Subject: Signed-off-by: Jody McIntyre --- drivers/ieee1394/ohci1394.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index b6b96fa04d62..eb329a875099 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -572,6 +572,7 @@ static void ohci_initialize(struct ti_ohci *ohci) OHCI1394_reqTxComplete | OHCI1394_isochRx | OHCI1394_isochTx | + OHCI1394_postedWriteErr | OHCI1394_cycleInconsistent); /* Enable link */ @@ -2374,7 +2375,10 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id, event &= ~OHCI1394_unrecoverableError; } - + if (event & OHCI1394_postedWriteErr) { + PRINT(KERN_ERR, "physical posted write error"); + /* no recovery strategy yet, had to involve protocol drivers */ + } if (event & OHCI1394_cycleInconsistent) { /* We subscribe to the cycleInconsistent event only to * clear the corresponding event bit... otherwise, @@ -2382,7 +2386,6 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id, DBGMSG("OHCI1394_cycleInconsistent"); event &= ~OHCI1394_cycleInconsistent; } - if (event & OHCI1394_busReset) { /* The busReset event bit can't be cleared during the * selfID phase, so we disable busReset interrupts, to @@ -2426,7 +2429,6 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id, } event &= ~OHCI1394_busReset; } - if (event & OHCI1394_reqTxComplete) { struct dma_trm_ctx *d = &ohci->at_req_context; DBGMSG("Got reqTxComplete interrupt " -- cgit v1.2.3-59-g8ed1b From a8748445e5ff747b114b5c29461ba2d28af404e8 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 28 Mar 2006 19:55:41 -0500 Subject: ieee1394: remove devfs support Devfs has been disabled in the last kernel releases, so let's remove it from ieee1394core, raw1394, video1394, dv1394. Signed-off-by: Stefan Richter Acked-by: Greg Kroah-Hartman Cc: Dan Dennedy Signed-off-by: Jody McIntyre --- drivers/ieee1394/dv1394.c | 41 ++-------------------------------------- drivers/ieee1394/ieee1394_core.c | 14 ++------------ drivers/ieee1394/ieee1394_core.h | 1 - drivers/ieee1394/raw1394.c | 6 ------ drivers/ieee1394/video1394.c | 16 +--------------- 5 files changed, 5 insertions(+), 73 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index efeaa944bd0a..85c2d4ca0def 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -73,7 +73,7 @@ - fix all XXX showstoppers - disable IR/IT DMA interrupts on shutdown - flush pci writes to the card by issuing a read - - devfs and character device dispatching (* needs testing with Linux 2.2.x) + - character device dispatching - switch over to the new kernel DMA API (pci_map_*()) (* needs testing on platforms with IOMMU!) - keep all video_cards in a list (for open() via chardev), set file->private_data = video - dv1394_poll should indicate POLLIN when receiving buffers are available @@ -1096,7 +1096,6 @@ static int do_dv1394_init_default(struct video_card *video) init.api_version = DV1394_API_VERSION; init.n_frames = DV1394_MAX_FRAMES / 4; - /* the following are now set via devfs */ init.channel = video->channel; init.format = video->pal_or_ntsc; init.cip_n = video->cip_n; @@ -1791,8 +1790,6 @@ static int dv1394_open(struct inode *inode, struct file *file) { struct video_card *video = NULL; - /* if the device was opened through devfs, then file->private_data - has already been set to video by devfs */ if (file->private_data) { video = (struct video_card*) file->private_data; @@ -2211,7 +2208,7 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes video = kzalloc(sizeof(*video), GFP_KERNEL); if (!video) { printk(KERN_ERR "dv1394: cannot allocate video_card\n"); - goto err; + return -1; } video->ohci = ohci; @@ -2266,37 +2263,14 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes list_add_tail(&video->list, &dv1394_cards); spin_unlock_irqrestore(&dv1394_cards_lock, flags); - if (devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_DV1394*16 + video->id), - S_IFCHR|S_IRUGO|S_IWUGO, - "ieee1394/dv/host%d/%s/%s", - (video->id>>2), - (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), - (video->mode == MODE_RECEIVE ? "in" : "out")) < 0) - goto err_free; - debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id); - return 0; - - err_free: - kfree(video); - err: - return -1; } static void dv1394_un_init(struct video_card *video) { - char buf[32]; - /* obviously nobody has the driver open at this point */ do_dv1394_shutdown(video, 1); - snprintf(buf, sizeof(buf), "dv/host%d/%s/%s", (video->id >> 2), - (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), - (video->mode == MODE_RECEIVE ? "in" : "out") - ); - - devfs_remove("ieee1394/%s", buf); kfree(video); } @@ -2333,9 +2307,6 @@ static void dv1394_remove_host (struct hpsb_host *host) class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2))); - devfs_remove("ieee1394/dv/host%d/NTSC", id); - devfs_remove("ieee1394/dv/host%d/PAL", id); - devfs_remove("ieee1394/dv/host%d", id); } static void dv1394_add_host (struct hpsb_host *host) @@ -2352,9 +2323,6 @@ static void dv1394_add_host (struct hpsb_host *host) class_device_create(hpsb_protocol_class, NULL, MKDEV( IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), NULL, "dv1394-%d", id); - devfs_mk_dir("ieee1394/dv/host%d", id); - devfs_mk_dir("ieee1394/dv/host%d/NTSC", id); - devfs_mk_dir("ieee1394/dv/host%d/PAL", id); dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE); dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT); @@ -2611,10 +2579,8 @@ MODULE_LICENSE("GPL"); static void __exit dv1394_exit_module(void) { hpsb_unregister_protocol(&dv1394_driver); - hpsb_unregister_highlevel(&dv1394_highlevel); cdev_del(&dv1394_cdev); - devfs_remove("ieee1394/dv"); } static int __init dv1394_init_module(void) @@ -2630,15 +2596,12 @@ static int __init dv1394_init_module(void) return ret; } - devfs_mk_dir("ieee1394/dv"); - hpsb_register_highlevel(&dv1394_highlevel); ret = hpsb_register_protocol(&dv1394_driver); if (ret) { printk(KERN_ERR "dv1394: failed to register protocol\n"); hpsb_unregister_highlevel(&dv1394_highlevel); - devfs_remove("ieee1394/dv"); cdev_del(&dv1394_cdev); return ret; } diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 25ef5a86f5f0..c0acaafe82d4 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -1078,17 +1078,10 @@ static int __init ieee1394_init(void) goto exit_release_kernel_thread; } - /* actually this is a non-fatal error */ - ret = devfs_mk_dir("ieee1394"); - if (ret < 0) { - HPSB_ERR("unable to make devfs dir for device major %d!\n", IEEE1394_MAJOR); - goto release_chrdev; - } - ret = bus_register(&ieee1394_bus_type); if (ret < 0) { HPSB_INFO("bus register failed"); - goto release_devfs; + goto release_chrdev; } for (i = 0; fw_bus_attrs[i]; i++) { @@ -1099,7 +1092,7 @@ static int __init ieee1394_init(void) fw_bus_attrs[i--]); } bus_unregister(&ieee1394_bus_type); - goto release_devfs; + goto release_chrdev; } } @@ -1152,8 +1145,6 @@ release_all_bus: for (i = 0; fw_bus_attrs[i]; i++) bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]); bus_unregister(&ieee1394_bus_type); -release_devfs: - devfs_remove("ieee1394"); release_chrdev: unregister_chrdev_region(IEEE1394_CORE_DEV, 256); exit_release_kernel_thread: @@ -1191,7 +1182,6 @@ static void __exit ieee1394_cleanup(void) hpsb_cleanup_config_roms(); unregister_chrdev_region(IEEE1394_CORE_DEV, 256); - devfs_remove("ieee1394"); } module_init(ieee1394_init); diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index b35466023f00..50c69c767b5d 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h @@ -3,7 +3,6 @@ #define _IEEE1394_CORE_H #include -#include #include #include #include "hosts.h" diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 19f26c5c9479..f7de546f2ed6 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include "csr1212.h" @@ -2999,9 +2998,6 @@ static int __init init_raw1394(void) goto out_unreg; } - devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), - S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME); - cdev_init(&raw1394_cdev, &raw1394_fops); raw1394_cdev.owner = THIS_MODULE; kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME); @@ -3023,7 +3019,6 @@ static int __init init_raw1394(void) goto out; out_dev: - devfs_remove(RAW1394_DEVICE_NAME); class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)); @@ -3039,7 +3034,6 @@ static void __exit cleanup_raw1394(void) MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)); cdev_del(&raw1394_cdev); - devfs_remove(RAW1394_DEVICE_NAME); hpsb_unregister_highlevel(&raw1394_highlevel); hpsb_unregister_protocol(&raw1394_driver); } diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 216dbbf1dc8e..4e3bd62c458d 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -1322,9 +1321,6 @@ static void video1394_add_host (struct hpsb_host *host) class_device_create(hpsb_protocol_class, NULL, MKDEV( IEEE1394_MAJOR, minor), NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id); - devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor), - S_IFCHR | S_IRUSR | S_IWUSR, - "%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id); } @@ -1332,12 +1328,9 @@ static void video1394_remove_host (struct hpsb_host *host) { struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host); - if (ohci) { + if (ohci) class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id)); - devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id); - } - return; } @@ -1478,12 +1471,8 @@ static long video1394_compat_ioctl(struct file *f, unsigned cmd, unsigned long a static void __exit video1394_exit_module (void) { hpsb_unregister_protocol(&video1394_driver); - hpsb_unregister_highlevel(&video1394_highlevel); - - devfs_remove(VIDEO1394_DRIVER_NAME); cdev_del(&video1394_cdev); - PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module"); } @@ -1500,15 +1489,12 @@ static int __init video1394_init_module (void) return ret; } - devfs_mk_dir(VIDEO1394_DRIVER_NAME); - hpsb_register_highlevel(&video1394_highlevel); ret = hpsb_register_protocol(&video1394_driver); if (ret) { PRINT_G(KERN_ERR, "video1394: failed to register protocol"); hpsb_unregister_highlevel(&video1394_highlevel); - devfs_remove(VIDEO1394_DRIVER_NAME); cdev_del(&video1394_cdev); return ret; } -- cgit v1.2.3-59-g8ed1b From c1d08eb6cd06c225d825c8981e05729389fd51a9 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 28 Mar 2006 19:56:45 -0500 Subject: ieee1394: remove amdtp remains from ieee1394_core.h since amdtp driver was deleted Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre --- drivers/ieee1394/ieee1394_core.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index 50c69c767b5d..e7b55e895f50 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h @@ -201,14 +201,12 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, #define IEEE1394_MINOR_BLOCK_RAW1394 0 #define IEEE1394_MINOR_BLOCK_VIDEO1394 1 #define IEEE1394_MINOR_BLOCK_DV1394 2 -#define IEEE1394_MINOR_BLOCK_AMDTP 3 #define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15 #define IEEE1394_CORE_DEV MKDEV(IEEE1394_MAJOR, 0) #define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16) #define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16) #define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16) -#define IEEE1394_AMDTP_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16) #define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16) /* return the index (within a minor number block) of a file */ -- cgit v1.2.3-59-g8ed1b From 180a43044faeaa9bfe0c604d472023a6446430b5 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 28 Mar 2006 19:57:34 -0500 Subject: ohci1394: clean up asynchronous and physical request filters programming Various cleanups of how ohci1394 programs AsynchronousRequestFilter, PhysicalRequestFilter, and physUpperBoundOffset. In particular, do not rewrite registers within the bus reset interrupt handler if bus resets do not affect the registers in the first place. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre --- drivers/ieee1394/ohci1394.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index eb329a875099..24d045c353e5 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -544,12 +544,19 @@ static void ohci_initialize(struct ti_ohci *ohci) /* Initialize IR Legacy DMA channel mask */ ohci->ir_legacy_channels = 0; - /* - * Accept AT requests from all nodes. This probably - * will have to be controlled from the subsystem - * on a per node basis. - */ - reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000); + /* Accept AR requests from all nodes */ + reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); + + /* Set the address range of the physical response unit. + * Most controllers do not implement it as a writable register though. + * They will keep a hardwired offset of 0x00010000 and show 0x0 as + * 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, 0xffff0000); + + DBGMSG("physUpperBoundOffset=%08x", + reg_read(ohci, OHCI1394_PhyUpperBound)); /* Specify AT retries */ reg_write(ohci, OHCI1394_ATRetries, @@ -2516,26 +2523,20 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id, reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); spin_unlock_irqrestore(&ohci->event_lock, flags); - /* Accept Physical requests from all nodes. */ - reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0xffffffff); - reg_write(ohci,OHCI1394_AsReqFilterLoSet, 0xffffffff); - /* Turn on phys dma reception. * * TODO: Enable some sort of filtering management. */ if (phys_dma) { - reg_write(ohci,OHCI1394_PhyReqFilterHiSet, 0xffffffff); - reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0xffffffff); - reg_write(ohci,OHCI1394_PhyUpperBound, 0xffff0000); - } else { - reg_write(ohci,OHCI1394_PhyReqFilterHiSet, 0x00000000); - reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0x00000000); + reg_write(ohci, OHCI1394_PhyReqFilterHiSet, + 0xffffffff); + reg_write(ohci, OHCI1394_PhyReqFilterLoSet, + 0xffffffff); } DBGMSG("PhyReqFilter=%08x%08x", - reg_read(ohci,OHCI1394_PhyReqFilterHiSet), - reg_read(ohci,OHCI1394_PhyReqFilterLoSet)); + reg_read(ohci, OHCI1394_PhyReqFilterHiSet), + reg_read(ohci, OHCI1394_PhyReqFilterLoSet)); hpsb_selfid_complete(host, phyid, isroot); } else -- cgit v1.2.3-59-g8ed1b From 556640510d7e15664cb9bf2f70f7519bfedd6c29 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 28 Mar 2006 19:59:42 -0500 Subject: sbp2: check for ARM failure Sbp2 did not check for successful registration of the lower address range when CONFIG_IEEE1394_SBP2_PHYS_DMA was set. If hpsb_register_addrspace failed, a "login timed-out" would occur which is misleading. Now sbp2 logs a sensible error message. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre --- drivers/ieee1394/sbp2.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 0b2b0da5b883..ce3b43dd229b 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -749,9 +749,13 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA /* Handle data movement if physical dma is not - * enabled/supportedon host controller */ - hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_physdma_ops, - 0x0ULL, 0xfffffffcULL); + * enabled or not supported on host controller */ + if (!hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, + &sbp2_physdma_ops, + 0x0ULL, 0xfffffffcULL)) { + SBP2_ERR("failed to register lower 4GB address range"); + goto failed_alloc; + } #endif } -- cgit v1.2.3-59-g8ed1b From 008652b337364ee994a0cd71d88a0fe9f00fc7ca Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:14:53 -0800 Subject: [TG3]: Fix probe failure due to invalid MAC address Some older bootcode in some devices may report 0 MAC address in SRAM when booting up from low power state. This patch fixes the problem by checking for a valid MAC address in SRAM and falling back to NVRAM if necessary. Thanks to walt for reporting the problem and helping to debug it. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b5473325bff4..c41dbb0e8f14 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10531,6 +10531,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) { struct net_device *dev = tp->dev; u32 hi, lo, mac_offset; + int addr_ok = 0; #ifdef CONFIG_SPARC64 if (!tg3_get_macaddr_sparc(tp)) @@ -10560,29 +10561,34 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) dev->dev_addr[3] = (lo >> 16) & 0xff; dev->dev_addr[4] = (lo >> 8) & 0xff; dev->dev_addr[5] = (lo >> 0) & 0xff; - } - /* Next, try NVRAM. */ - else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) && - !tg3_nvram_read(tp, mac_offset + 0, &hi) && - !tg3_nvram_read(tp, mac_offset + 4, &lo)) { - dev->dev_addr[0] = ((hi >> 16) & 0xff); - dev->dev_addr[1] = ((hi >> 24) & 0xff); - dev->dev_addr[2] = ((lo >> 0) & 0xff); - dev->dev_addr[3] = ((lo >> 8) & 0xff); - dev->dev_addr[4] = ((lo >> 16) & 0xff); - dev->dev_addr[5] = ((lo >> 24) & 0xff); - } - /* Finally just fetch it out of the MAC control regs. */ - else { - hi = tr32(MAC_ADDR_0_HIGH); - lo = tr32(MAC_ADDR_0_LOW); - dev->dev_addr[5] = lo & 0xff; - dev->dev_addr[4] = (lo >> 8) & 0xff; - dev->dev_addr[3] = (lo >> 16) & 0xff; - dev->dev_addr[2] = (lo >> 24) & 0xff; - dev->dev_addr[1] = hi & 0xff; - dev->dev_addr[0] = (hi >> 8) & 0xff; + /* Some old bootcode may report a 0 MAC address in SRAM */ + addr_ok = is_valid_ether_addr(&dev->dev_addr[0]); + } + if (!addr_ok) { + /* Next, try NVRAM. */ + if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) && + !tg3_nvram_read(tp, mac_offset + 0, &hi) && + !tg3_nvram_read(tp, mac_offset + 4, &lo)) { + dev->dev_addr[0] = ((hi >> 16) & 0xff); + dev->dev_addr[1] = ((hi >> 24) & 0xff); + dev->dev_addr[2] = ((lo >> 0) & 0xff); + dev->dev_addr[3] = ((lo >> 8) & 0xff); + dev->dev_addr[4] = ((lo >> 16) & 0xff); + dev->dev_addr[5] = ((lo >> 24) & 0xff); + } + /* Finally just fetch it out of the MAC control regs. */ + else { + hi = tr32(MAC_ADDR_0_HIGH); + lo = tr32(MAC_ADDR_0_LOW); + + dev->dev_addr[5] = lo & 0xff; + dev->dev_addr[4] = (lo >> 8) & 0xff; + dev->dev_addr[3] = (lo >> 16) & 0xff; + dev->dev_addr[2] = (lo >> 24) & 0xff; + dev->dev_addr[1] = hi & 0xff; + dev->dev_addr[0] = (hi >> 8) & 0xff; + } } if (!is_valid_ether_addr(&dev->dev_addr[0])) { -- cgit v1.2.3-59-g8ed1b From 6728a8e2e180b96ac7940dd4d766c52f8e177717 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:16:49 -0800 Subject: [TG3]: Fix bug in 40-bit DMA workaround code Need to check the TG3_FLAG_40BIT_DMA_BUG flag in the workaround code path instead of device flags. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c41dbb0e8f14..0fafc5264627 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3600,7 +3600,7 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping, int len) { #if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64) - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) return (((u64) mapping + len) > DMA_40BIT_MASK); return 0; #else -- cgit v1.2.3-59-g8ed1b From ff18ff023495a4f1ce7c65e7c376c4720eccf4da Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:17:27 -0800 Subject: [TG3]: Fix PHY loopback on 5700 Fix PHY loopback failure on some 5700 devices. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0fafc5264627..3c5c9fafe9c8 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8399,8 +8399,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) } mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII; - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) + if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { mac_mode &= ~MAC_MODE_LINK_POLARITY; + tg3_writephy(tp, MII_TG3_EXT_CTRL, + MII_TG3_EXT_CTRL_LNK3_LED_MODE); + } tw32(MAC_MODE, mac_mode); } else -- cgit v1.2.3-59-g8ed1b From 100c4673307f5806788791b9b886877c806afd96 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:19:00 -0800 Subject: [TG3]: Speed up SRAM access Speed up SRAM read and write functions if possible by using MMIO instead of config. cycles. With this change, the post reset signature done at the end of D3 power change must now be moved before the D3 power change. IBM reported a problem on powerpc blades during ethtool self test that was caused by the memory test taking excessively long. Config. cycles are very slow on powerpc and the memory test can take more than 10 seconds to complete using config. cycles. As a result, NETDEV WATCHDOG can be triggered during self test and the chip can end up in a funny state. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 53 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 3c5c9fafe9c8..c504ff29d44c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -497,21 +497,20 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + if (tp->write32 != tg3_write_indirect_reg32) { + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); + tw32_f(TG3PCI_MEM_WIN_DATA, val); - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); - spin_unlock_irqrestore(&tp->indirect_lock, flags); -} + /* Always leave this as zero. */ + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); + } else { + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); -static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val) -{ - /* If no workaround is needed, write to mem space directly */ - if (tp->write32 != tg3_write_indirect_reg32) - tw32(NIC_SRAM_WIN_BASE + off, val); - else - tg3_write_mem(tp, off, val); + /* Always leave this as zero. */ + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + } + spin_unlock_irqrestore(&tp->indirect_lock, flags); } static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) @@ -519,11 +518,19 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + if (tp->write32 != tg3_write_indirect_reg32) { + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); + *val = tr32(TG3PCI_MEM_WIN_DATA); - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + /* Always leave this as zero. */ + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); + } else { + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); + pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + + /* Always leave this as zero. */ + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + } spin_unlock_irqrestore(&tp->indirect_lock, flags); } @@ -1367,12 +1374,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) } } + tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); + /* Finally, set the new power state. */ pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); udelay(100); /* Delay after power state change */ - tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); - return 0; } @@ -6537,11 +6544,11 @@ static void tg3_timer(unsigned long __opaque) if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { u32 val; - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX, - FWCMD_NICDRV_ALIVE2); - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, + FWCMD_NICDRV_ALIVE2); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); /* 5 seconds timeout */ - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); val = tr32(GRC_RX_CPU_EVENT); val |= (1 << 14); tw32(GRC_RX_CPU_EVENT, val); -- cgit v1.2.3-59-g8ed1b From f475f163f128a0d9c92dfa90bcb5953fd8f9766f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:20:14 -0800 Subject: [TG3]: Skip timer code during full lock Skip the main timer code if interrupts are disabled in the full lock state. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c504ff29d44c..b6a6051db77a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6468,6 +6468,9 @@ static void tg3_timer(unsigned long __opaque) { struct tg3 *tp = (struct tg3 *) __opaque; + if (tp->irq_sync) + goto restart_timer; + spin_lock(&tp->lock); if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { @@ -6558,6 +6561,7 @@ static void tg3_timer(unsigned long __opaque) spin_unlock(&tp->lock); +restart_timer: tp->timer.expires = jiffies + tp->timer_offset; add_timer(&tp->timer); } -- cgit v1.2.3-59-g8ed1b From e3a05978f18a38ae13bb3f1184abf3c999e06da9 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:21:07 -0800 Subject: [TG3]: Update version and reldate Update version to 3.55. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b6a6051db77a..964c09644832 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.54" -#define DRV_MODULE_RELDATE "Mar 23, 2006" +#define DRV_MODULE_VERSION "3.55" +#define DRV_MODULE_RELDATE "Mar 27, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3-59-g8ed1b From 23e93f1742372bc938e53151bdbf88d284ee9561 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 28 Mar 2006 20:03:34 -0500 Subject: ieee1394: set read permission for parameter disable_irm No need to hide it from /sys/module/ieee1394/parameters/. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre --- drivers/ieee1394/ieee1394_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index c0acaafe82d4..be6854e25ad4 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -58,7 +58,7 @@ MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality."); /* Disable Isochronous Resource Manager functionality */ int hpsb_disable_irm = 0; -module_param_named(disable_irm, hpsb_disable_irm, bool, 0); +module_param_named(disable_irm, hpsb_disable_irm, bool, 0444); MODULE_PARM_DESC(disable_irm, "Disable Isochronous Resource Manager functionality."); -- cgit v1.2.3-59-g8ed1b From 8f0525ff1901f4fafe6d02d5d373ca38103ff5a7 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 28 Mar 2006 20:03:45 -0500 Subject: sbp2: proper treatment of DID_OK Sbp2 relied on DID_OK to be defined as 0. Always shift DID_OK into the right position anyway, and explicitly return DID_OK together with CHECK_CONDITION. Also comment on some #if 0 code. The patch does not change current behaviour. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre --- drivers/ieee1394/sbp2.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index ce3b43dd229b..eb7106b8fd0a 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -2410,7 +2410,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, */ switch (scsi_status) { case SBP2_SCSI_STATUS_GOOD: - SCpnt->result = DID_OK; + SCpnt->result = DID_OK << 16; break; case SBP2_SCSI_STATUS_BUSY: @@ -2420,7 +2420,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, case SBP2_SCSI_STATUS_CHECK_CONDITION: SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION"); - SCpnt->result = CHECK_CONDITION << 1; + SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16; /* * Debug stuff @@ -2454,7 +2454,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, /* * Take care of any sbp2 response data mucking here (RBC stuff, etc.) */ - if (SCpnt->result == DID_OK) { + if (SCpnt->result == DID_OK << 16) { sbp2_check_sbp2_response(scsi_id, SCpnt); } @@ -2472,6 +2472,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, * If a unit attention occurs, return busy status so it gets * retried... it could have happened because of a 1394 bus reset * or hot-plug... + * XXX DID_BUS_BUSY is actually a bad idea because it will defy + * the scsi layer's retry logic. */ #if 0 if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) && -- cgit v1.2.3-59-g8ed1b From d024ebc67eaa6bb7abca2e3061cb257a1587fa30 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 28 Mar 2006 20:03:55 -0500 Subject: sbp2: misc debug logging cleanups - move call of scsi_print_command from sbp2_send_command to the beginning of sbp2_queue_command to show also commands which are not sent - put sbp2's name into scsi_print_sense - use __FUNCTION__ in log messages - remove a few less useful log messages and comments Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre --- drivers/ieee1394/sbp2.c | 110 +++++++++++++++--------------------------------- 1 file changed, 33 insertions(+), 77 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index eb7106b8fd0a..2c765ca5aa50 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -214,6 +214,7 @@ static u32 global_outstanding_dmas = 0; #endif #define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) +#define SBP2_DEBUG_ENTER() SBP2_DEBUG("%s", __FUNCTION__) /* * Globals @@ -535,7 +536,7 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb( command->Current_SCpnt = Current_SCpnt; list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse); } else { - SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!"); + SBP2_ERR("%s: no orbs available", __FUNCTION__); } spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return command; @@ -549,7 +550,7 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command) struct hpsb_host *host; if (!scsi_id) { - printk(KERN_ERR "%s: scsi_id == NULL\n", __FUNCTION__); + SBP2_ERR("%s: scsi_id == NULL", __FUNCTION__); return; } @@ -610,7 +611,7 @@ static int sbp2_probe(struct device *dev) struct unit_directory *ud; struct scsi_id_instance_data *scsi_id; - SBP2_DEBUG("sbp2_probe"); + SBP2_DEBUG_ENTER(); ud = container_of(dev, struct unit_directory, device); @@ -635,7 +636,7 @@ static int sbp2_remove(struct device *dev) struct scsi_id_instance_data *scsi_id; struct scsi_device *sdev; - SBP2_DEBUG("sbp2_remove"); + SBP2_DEBUG_ENTER(); ud = container_of(dev, struct unit_directory, device); scsi_id = ud->device.driver_data; @@ -667,7 +668,7 @@ static int sbp2_update(struct unit_directory *ud) { struct scsi_id_instance_data *scsi_id = ud->device.driver_data; - SBP2_DEBUG("sbp2_update"); + SBP2_DEBUG_ENTER(); if (sbp2_reconnect_device(scsi_id)) { @@ -715,7 +716,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud struct Scsi_Host *scsi_host = NULL; struct scsi_id_instance_data *scsi_id = NULL; - SBP2_DEBUG("sbp2_alloc_device"); + SBP2_DEBUG_ENTER(); scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL); if (!scsi_id) { @@ -826,7 +827,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) struct sbp2scsi_host_info *hi = scsi_id->hi; int error; - SBP2_DEBUG("sbp2_start_device"); + SBP2_DEBUG_ENTER(); /* Login FIFO DMA */ scsi_id->login_response = @@ -901,7 +902,6 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) * allows someone else to login instead. One second makes sense. */ msleep_interruptible(1000); if (signal_pending(current)) { - SBP2_WARN("aborting sbp2_start_device due to event"); sbp2_remove_device(scsi_id); return -EINTR; } @@ -954,7 +954,7 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) { struct sbp2scsi_host_info *hi; - SBP2_DEBUG("sbp2_remove_device"); + SBP2_DEBUG_ENTER(); if (!scsi_id) return; @@ -1086,23 +1086,20 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) int max_logins; int active_logins; - SBP2_DEBUG("sbp2_query_logins"); + SBP2_DEBUG_ENTER(); scsi_id->query_logins_orb->reserved1 = 0x0; scsi_id->query_logins_orb->reserved2 = 0x0; scsi_id->query_logins_orb->query_response_lo = scsi_id->query_logins_response_dma; scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id); - SBP2_DEBUG("sbp2_query_logins: query_response_hi/lo initialized"); scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST); scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1); scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun); - SBP2_DEBUG("sbp2_query_logins: lun_misc initialized"); scsi_id->query_logins_orb->reserved_resp_length = ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response)); - SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized"); scsi_id->query_logins_orb->status_fifo_hi = ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); @@ -1111,25 +1108,19 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb)); - SBP2_DEBUG("sbp2_query_logins: orb byte-swapped"); - sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb), "sbp2 query logins orb", scsi_id->query_logins_orb_dma); memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response)); memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); - SBP2_DEBUG("sbp2_query_logins: query_logins_response/status FIFO memset"); - data[0] = ORB_SET_NODE_ID(hi->host->node_id); data[1] = scsi_id->query_logins_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); atomic_set(&scsi_id->sbp2_login_complete, 0); - SBP2_DEBUG("sbp2_query_logins: prepared to write"); hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); - SBP2_DEBUG("sbp2_query_logins: written"); if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) { SBP2_INFO("Error querying logins to SBP-2 device - timed out"); @@ -1178,10 +1169,10 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) struct sbp2scsi_host_info *hi = scsi_id->hi; quadlet_t data[2]; - SBP2_DEBUG("sbp2_login_device"); + SBP2_DEBUG_ENTER(); if (!scsi_id->login_orb) { - SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!"); + SBP2_DEBUG("%s: login_orb not alloc'd!", __FUNCTION__); return -EIO; } @@ -1195,59 +1186,39 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) /* Set-up login ORB, assume no password */ scsi_id->login_orb->password_hi = 0; scsi_id->login_orb->password_lo = 0; - SBP2_DEBUG("sbp2_login_device: password_hi/lo initialized"); scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma; scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id); - SBP2_DEBUG("sbp2_login_device: login_response_hi/lo initialized"); scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST); scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0); /* One second reconnect time */ scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login); /* Exclusive access to device */ scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1); /* Notify us of login complete */ scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun); - SBP2_DEBUG("sbp2_login_device: lun_misc initialized"); scsi_id->login_orb->passwd_resp_lengths = ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response)); - SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized"); scsi_id->login_orb->status_fifo_hi = ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); scsi_id->login_orb->status_fifo_lo = ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); - /* - * Byte swap ORB if necessary - */ sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb)); - SBP2_DEBUG("sbp2_login_device: orb byte-swapped"); - sbp2util_packet_dump(scsi_id->login_orb, sizeof(struct sbp2_login_orb), "sbp2 login orb", scsi_id->login_orb_dma); - /* - * Initialize login response and status fifo - */ memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response)); memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); - SBP2_DEBUG("sbp2_login_device: login_response/status FIFO memset"); - - /* - * Ok, let's write to the target's management agent register - */ data[0] = ORB_SET_NODE_ID(hi->host->node_id); data[1] = scsi_id->login_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); atomic_set(&scsi_id->sbp2_login_complete, 0); - SBP2_DEBUG("sbp2_login_device: prepared to write to %08x", - (unsigned int)scsi_id->sbp2_management_agent_addr); hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); - SBP2_DEBUG("sbp2_login_device: written"); /* * Wait for login status (up to 20 seconds)... @@ -1311,7 +1282,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id) quadlet_t data[2]; int error; - SBP2_DEBUG("sbp2_logout_device"); + SBP2_DEBUG_ENTER(); /* * Set-up logout ORB @@ -1375,7 +1346,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) quadlet_t data[2]; int error; - SBP2_DEBUG("sbp2_reconnect_device"); + SBP2_DEBUG_ENTER(); /* * Set-up reconnect ORB @@ -1466,17 +1437,11 @@ static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id) { quadlet_t data; - SBP2_DEBUG("sbp2_set_busy_timeout"); + SBP2_DEBUG_ENTER(); - /* - * Ok, let's write to the target's busy timeout register - */ data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE); - - if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) { - SBP2_ERR("sbp2_set_busy_timeout error"); - } - + if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) + SBP2_ERR("%s error", __FUNCTION__); return 0; } @@ -1495,7 +1460,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, firmware_revision, workarounds; int i; - SBP2_DEBUG("sbp2_parse_unit_directory"); + SBP2_DEBUG_ENTER(); management_agent_addr = 0x0; command_set_spec_id = 0x0; @@ -1628,7 +1593,7 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id) { struct sbp2scsi_host_info *hi = scsi_id->hi; - SBP2_DEBUG("sbp2_max_speed_and_size"); + SBP2_DEBUG_ENTER(); /* Initial setting comes from the hosts speed map */ scsi_id->speed_code = @@ -1665,11 +1630,8 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait) u64 addr; int retval; - SBP2_DEBUG("sbp2_agent_reset"); + SBP2_DEBUG_ENTER(); - /* - * Ok, let's write to the target's management agent register - */ data = ntohl(SBP2_AGENT_RESET_DATA); addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET; @@ -2017,11 +1979,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, unsigned int request_bufflen = SCpnt->request_bufflen; struct sbp2_command_info *command; - SBP2_DEBUG("sbp2_send_command"); -#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP) - printk("[scsi command]\n "); - scsi_print_command(SCpnt); -#endif + SBP2_DEBUG_ENTER(); SBP2_DEBUG("SCSI transfer size = %x", request_bufflen); SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg); @@ -2061,7 +2019,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, */ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data) { - SBP2_DEBUG("sbp2_status_to_sense_data"); + SBP2_DEBUG_ENTER(); /* * Ok, it's pretty ugly... ;-) @@ -2095,7 +2053,7 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, { u8 *scsi_buf = SCpnt->request_buffer; - SBP2_DEBUG("sbp2_check_sbp2_response"); + SBP2_DEBUG_ENTER(); if (SCpnt->cmnd[0] == INQUIRY && (SCpnt->cmnd[1] & 3) == 0) { /* @@ -2126,7 +2084,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest struct sbp2_command_info *command; unsigned long flags; - SBP2_DEBUG("sbp2_handle_status_write"); + SBP2_DEBUG_ENTER(); sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr); @@ -2273,7 +2231,10 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, struct sbp2scsi_host_info *hi; int result = DID_NO_CONNECT << 16; - SBP2_DEBUG("sbp2scsi_queuecommand"); + SBP2_DEBUG_ENTER(); +#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP) + scsi_print_command(SCpnt); +#endif if (!sbp2util_node_is_available(scsi_id)) goto done; @@ -2351,7 +2312,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id struct sbp2_command_info *command; unsigned long flags; - SBP2_DEBUG("sbp2scsi_complete_all_commands"); + SBP2_DEBUG_ENTER(); spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { @@ -2384,7 +2345,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, u32 scsi_status, struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { - SBP2_DEBUG("sbp2scsi_complete_command"); + SBP2_DEBUG_ENTER(); /* * Sanity @@ -2421,15 +2382,10 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, case SBP2_SCSI_STATUS_CHECK_CONDITION: SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION"); SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16; - - /* - * Debug stuff - */ #if CONFIG_IEEE1394_SBP2_DEBUG >= 1 scsi_print_command(SCpnt); - scsi_print_sense("bh", SCpnt); + scsi_print_sense(SBP2_DEVICE_NAME, SCpnt); #endif - break; case SBP2_SCSI_STATUS_SELECTION_TIMEOUT: @@ -2639,7 +2595,7 @@ static int sbp2_module_init(void) { int ret; - SBP2_DEBUG("sbp2_module_init"); + SBP2_DEBUG_ENTER(); /* Module load debug option to force one command at a time (serializing I/O) */ if (serialize_io) { @@ -2667,7 +2623,7 @@ static int sbp2_module_init(void) static void __exit sbp2_module_exit(void) { - SBP2_DEBUG("sbp2_module_exit"); + SBP2_DEBUG_ENTER(); hpsb_unregister_protocol(&sbp2_driver); -- cgit v1.2.3-59-g8ed1b From 94c2d01a537daf51a9fcf229d7d2204c979355d9 Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Tue, 28 Mar 2006 20:04:04 -0500 Subject: ohci1394: cleanup the "Unexpected PCI resource length" warning. This warning happens in practice because the resource length reported by the chipset is too large. This is not actually a problem, so don't warn about it. If it happens to be too small, warn about that, but with a different message so people who are used to ignoring the old message don't. Signed-off-by: Jody McIntyre --- drivers/ieee1394/ohci1394.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 24d045c353e5..a86beeb6af5d 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3262,8 +3262,8 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, * fail to report the right length. Anyway, the ohci spec * clearly says it's 2kb, so this shouldn't be a problem. */ ohci_base = pci_resource_start(dev, 0); - if (pci_resource_len(dev, 0) != OHCI1394_REGISTER_SIZE) - PRINT(KERN_WARNING, "Unexpected PCI resource length of %lx!", + if (pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE) + PRINT(KERN_WARNING, "PCI resource length of %lx too small!", pci_resource_len(dev, 0)); /* Seems PCMCIA handles this internally. Not sure why. Seems -- cgit v1.2.3-59-g8ed1b From f96a795d4f6a8a13abe4b0d3c5d1c28ea8d7ce4b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 28 Mar 2006 16:11:01 -0800 Subject: [PATCH] do_tty_hangup: use group_send_sig_info not send_group_sig_info We already have the tasklist_lock so there is no need for us to reacquire it with send_group_sig_info. reader/writer locks allow multiple readers and thus recursion so the old code was ok just wastful. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 811dadb9ce3e..bd73242fe159 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1094,8 +1094,8 @@ static void do_tty_hangup(void *data) p->signal->tty = NULL; if (!p->signal->leader) continue; - send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p); - send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p); + group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); + group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); if (tty->pgrp > 0) p->signal->tty_old_pgrp = tty->pgrp; } while_each_task_pid(tty->session, PIDTYPE_SID, p); -- cgit v1.2.3-59-g8ed1b From 652486fb84a07ed750f1c11639518f55808bf555 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 28 Mar 2006 16:11:02 -0800 Subject: [PATCH] do_SAK: don't depend on session ID 0 I'm not really certain what the thinking was but the code obviously wanted to walk processes other than just those in it's session, for purposes of do_SAK. Just walking those tasks that don't have a session assigned sounds at the very least incomplete. So modify the code to kill everything in the session and anything else that might have the tty open. Hopefully this helps if the do_SAK functionality is ever finished. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index bd73242fe159..0bfd1b63662e 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2672,7 +2672,7 @@ static void __do_SAK(void *arg) tty_hangup(tty); #else struct tty_struct *tty = arg; - struct task_struct *p; + struct task_struct *g, *p; int session; int i; struct file *filp; @@ -2693,8 +2693,18 @@ static void __do_SAK(void *arg) tty->driver->flush_buffer(tty); read_lock(&tasklist_lock); + /* Kill the entire session */ do_each_task_pid(session, PIDTYPE_SID, p) { - if (p->signal->tty == tty || session > 0) { + printk(KERN_NOTICE "SAK: killed process %d" + " (%s): p->signal->session==tty->session\n", + p->pid, p->comm); + send_sig(SIGKILL, p, 1); + } while_each_task_pid(session, PIDTYPE_SID, p); + /* Now kill any processes that happen to have the + * tty open. + */ + do_each_thread(g, p) { + if (p->signal->tty == tty) { printk(KERN_NOTICE "SAK: killed process %d" " (%s): p->signal->session==tty->session\n", p->pid, p->comm); @@ -2721,7 +2731,7 @@ static void __do_SAK(void *arg) rcu_read_unlock(); } task_unlock(p); - } while_each_task_pid(session, PIDTYPE_SID, p); + } while_each_thread(g, p); read_unlock(&tasklist_lock); #endif } -- cgit v1.2.3-59-g8ed1b From 730c9b7e6630f786fcec026fb11d2e6f2c90fdcb Mon Sep 17 00:00:00 2001 From: Carlos Aguiar Date: Wed, 29 Mar 2006 09:21:00 +0100 Subject: [MMC] Add OMAP MMC host driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds OMAP MMC driver. Signed-off-by: Juha Yrjölä Signed-off-by: Tony Lindgren Signed-off-by: Carlos Aguiar Signed-off-by: Russell King --- drivers/mmc/Kconfig | 11 + drivers/mmc/Makefile | 1 + drivers/mmc/omap.c | 1231 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/mmc/omap.h | 55 +++ 4 files changed, 1298 insertions(+) create mode 100644 drivers/mmc/omap.c create mode 100644 drivers/mmc/omap.h (limited to 'drivers') diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 3f5d77f633fa..7cc162e8978b 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -60,6 +60,17 @@ config MMC_SDHCI If unsure, say N. +config MMC_OMAP + tristate "TI OMAP Multimedia Card Interface support" + depends on ARCH_OMAP && MMC + select TPS65010 if MACH_OMAP_H2 + help + This selects the TI OMAP Multimedia card Interface. + If you have an OMAP board with a Multimedia Card slot, + say Y or M here. + + If unsure, say N. + config MMC_WBSD tristate "Winbond W83L51xD SD/MMC Card Interface support" depends on MMC && ISA_DMA_API diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 769d545284a4..0b0920ae46b7 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -20,5 +20,6 @@ obj-$(CONFIG_MMC_PXA) += pxamci.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_WBSD) += wbsd.o obj-$(CONFIG_MMC_AU1X) += au1xmmc.o +obj-$(CONFIG_MMC_OMAP) += omap.o mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c new file mode 100644 index 000000000000..49fb2ea4b7ee --- /dev/null +++ b/drivers/mmc/omap.c @@ -0,0 +1,1231 @@ +/* + * linux/drivers/media/mmc/omap.c + * + * Copyright (C) 2004 Nokia Corporation + * Written by Tuukka Tikkanen and Juha Yrjölä + * Misc hacks here and there by Tony Lindgren + * Other hacks (DMA, SD, etc) by David Brownell + * + * 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 + +#ifdef CONFIG_MMC_DEBUG +#define DEBUG /* for dev_dbg(), pr_debug(), etc */ +#endif + +#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 "omap.h" + +#define DRIVER_NAME "mmci-omap" +#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) + +/* Specifies how often in millisecs to poll for card status changes + * when the cover switch is open */ +#define OMAP_MMC_SWITCH_POLL_DELAY 500 + +static int mmc_omap_enable_poll = 1; + +struct mmc_omap_host { + int initialized; + int suspended; + struct mmc_request * mrq; + struct mmc_command * cmd; + struct mmc_data * data; + struct mmc_host * mmc; + struct device * dev; + unsigned char id; /* 16xx chips have 2 MMC blocks */ + struct clk * iclk; + struct clk * fclk; + void __iomem *base; + int irq; + unsigned char bus_mode; + unsigned char hw_bus_mode; + + unsigned int sg_len; + int sg_idx; + u16 * buffer; + u32 buffer_bytes_left; + u32 total_bytes_left; + + unsigned use_dma:1; + unsigned brs_received:1, dma_done:1; + unsigned dma_is_read:1; + unsigned dma_in_use:1; + int dma_ch; + spinlock_t dma_lock; + struct timer_list dma_timer; + unsigned dma_len; + + short power_pin; + short wp_pin; + + int switch_pin; + struct work_struct switch_work; + struct timer_list switch_timer; + int switch_last_state; +}; + +static inline int +mmc_omap_cover_is_open(struct mmc_omap_host *host) +{ + if (host->switch_pin < 0) + return 0; + return omap_get_gpio_datain(host->switch_pin); +} + +static ssize_t +mmc_omap_show_cover_switch(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mmc_omap_host *host = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", mmc_omap_cover_is_open(host) ? "open" : + "closed"); +} + +static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL); + +static ssize_t +mmc_omap_show_enable_poll(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", mmc_omap_enable_poll); +} + +static ssize_t +mmc_omap_store_enable_poll(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + int enable_poll; + + if (sscanf(buf, "%10d", &enable_poll) != 1) + return -EINVAL; + + if (enable_poll != mmc_omap_enable_poll) { + struct mmc_omap_host *host = dev_get_drvdata(dev); + + mmc_omap_enable_poll = enable_poll; + if (enable_poll && host->switch_pin >= 0) + schedule_work(&host->switch_work); + } + return size; +} + +static DEVICE_ATTR(enable_poll, 0664, + mmc_omap_show_enable_poll, mmc_omap_store_enable_poll); + +static void +mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd) +{ + u32 cmdreg; + u32 resptype; + u32 cmdtype; + + host->cmd = cmd; + + resptype = 0; + cmdtype = 0; + + /* Our hardware needs to know exact type */ + switch (RSP_TYPE(mmc_resp_type(cmd))) { + case RSP_TYPE(MMC_RSP_R1): + /* resp 1, resp 1b */ + resptype = 1; + break; + case RSP_TYPE(MMC_RSP_R2): + resptype = 2; + break; + case RSP_TYPE(MMC_RSP_R3): + resptype = 3; + break; + default: + break; + } + + if (mmc_cmd_type(cmd) == MMC_CMD_ADTC) { + cmdtype = OMAP_MMC_CMDTYPE_ADTC; + } else if (mmc_cmd_type(cmd) == MMC_CMD_BC) { + cmdtype = OMAP_MMC_CMDTYPE_BC; + } else if (mmc_cmd_type(cmd) == MMC_CMD_BCR) { + cmdtype = OMAP_MMC_CMDTYPE_BCR; + } else { + cmdtype = OMAP_MMC_CMDTYPE_AC; + } + + cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12); + + if (host->bus_mode == MMC_BUSMODE_OPENDRAIN) + cmdreg |= 1 << 6; + + if (cmd->flags & MMC_RSP_BUSY) + cmdreg |= 1 << 11; + + if (host->data && !(host->data->flags & MMC_DATA_WRITE)) + cmdreg |= 1 << 15; + + clk_enable(host->fclk); + + OMAP_MMC_WRITE(host->base, CTO, 200); + OMAP_MMC_WRITE(host->base, ARGL, cmd->arg & 0xffff); + OMAP_MMC_WRITE(host->base, ARGH, cmd->arg >> 16); + OMAP_MMC_WRITE(host->base, IE, + OMAP_MMC_STAT_A_EMPTY | OMAP_MMC_STAT_A_FULL | + OMAP_MMC_STAT_CMD_CRC | OMAP_MMC_STAT_CMD_TOUT | + OMAP_MMC_STAT_DATA_CRC | OMAP_MMC_STAT_DATA_TOUT | + OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR | + OMAP_MMC_STAT_END_OF_DATA); + OMAP_MMC_WRITE(host->base, CMD, cmdreg); +} + +static void +mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) +{ + if (host->dma_in_use) { + enum dma_data_direction dma_data_dir; + + BUG_ON(host->dma_ch < 0); + if (data->error != MMC_ERR_NONE) + omap_stop_dma(host->dma_ch); + /* Release DMA channel lazily */ + mod_timer(&host->dma_timer, jiffies + HZ); + if (data->flags & MMC_DATA_WRITE) + dma_data_dir = DMA_TO_DEVICE; + else + dma_data_dir = DMA_FROM_DEVICE; + dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len, + dma_data_dir); + } + host->data = NULL; + host->sg_len = 0; + clk_disable(host->fclk); + + /* NOTE: MMC layer will sometimes poll-wait CMD13 next, issuing + * dozens of requests until the card finishes writing data. + * It'd be cheaper to just wait till an EOFB interrupt arrives... + */ + + if (!data->stop) { + host->mrq = NULL; + mmc_request_done(host->mmc, data->mrq); + return; + } + + mmc_omap_start_command(host, data->stop); +} + +static void +mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data) +{ + unsigned long flags; + int done; + + if (!host->dma_in_use) { + mmc_omap_xfer_done(host, data); + return; + } + done = 0; + spin_lock_irqsave(&host->dma_lock, flags); + if (host->dma_done) + done = 1; + else + host->brs_received = 1; + spin_unlock_irqrestore(&host->dma_lock, flags); + if (done) + mmc_omap_xfer_done(host, data); +} + +static void +mmc_omap_dma_timer(unsigned long data) +{ + struct mmc_omap_host *host = (struct mmc_omap_host *) data; + + BUG_ON(host->dma_ch < 0); + omap_free_dma(host->dma_ch); + host->dma_ch = -1; +} + +static void +mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data) +{ + unsigned long flags; + int done; + + done = 0; + spin_lock_irqsave(&host->dma_lock, flags); + if (host->brs_received) + done = 1; + else + host->dma_done = 1; + spin_unlock_irqrestore(&host->dma_lock, flags); + if (done) + mmc_omap_xfer_done(host, data); +} + +static void +mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd) +{ + host->cmd = NULL; + + if (cmd->flags & MMC_RSP_PRESENT) { + if (cmd->flags & MMC_RSP_136) { + /* response type 2 */ + cmd->resp[3] = + OMAP_MMC_READ(host->base, RSP0) | + (OMAP_MMC_READ(host->base, RSP1) << 16); + cmd->resp[2] = + OMAP_MMC_READ(host->base, RSP2) | + (OMAP_MMC_READ(host->base, RSP3) << 16); + cmd->resp[1] = + OMAP_MMC_READ(host->base, RSP4) | + (OMAP_MMC_READ(host->base, RSP5) << 16); + cmd->resp[0] = + OMAP_MMC_READ(host->base, RSP6) | + (OMAP_MMC_READ(host->base, RSP7) << 16); + } else { + /* response types 1, 1b, 3, 4, 5, 6 */ + cmd->resp[0] = + OMAP_MMC_READ(host->base, RSP6) | + (OMAP_MMC_READ(host->base, RSP7) << 16); + } + } + + if (host->data == NULL || cmd->error != MMC_ERR_NONE) { + host->mrq = NULL; + clk_disable(host->fclk); + mmc_request_done(host->mmc, cmd->mrq); + } +} + +/* PIO only */ +static void +mmc_omap_sg_to_buf(struct mmc_omap_host *host) +{ + struct scatterlist *sg; + + sg = host->data->sg + host->sg_idx; + host->buffer_bytes_left = sg->length; + host->buffer = page_address(sg->page) + sg->offset; + if (host->buffer_bytes_left > host->total_bytes_left) + host->buffer_bytes_left = host->total_bytes_left; +} + +/* PIO only */ +static void +mmc_omap_xfer_data(struct mmc_omap_host *host, int write) +{ + int n; + void __iomem *reg; + u16 *p; + + if (host->buffer_bytes_left == 0) { + host->sg_idx++; + BUG_ON(host->sg_idx == host->sg_len); + mmc_omap_sg_to_buf(host); + } + n = 64; + if (n > host->buffer_bytes_left) + n = host->buffer_bytes_left; + host->buffer_bytes_left -= n; + host->total_bytes_left -= n; + host->data->bytes_xfered += n; + + if (write) { + __raw_writesw(host->base + OMAP_MMC_REG_DATA, host->buffer, n); + } else { + __raw_readsw(host->base + OMAP_MMC_REG_DATA, host->buffer, n); + } +} + +static inline void mmc_omap_report_irq(u16 status) +{ + static const char *mmc_omap_status_bits[] = { + "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO", + "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR" + }; + int i, c = 0; + + for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++) + if (status & (1 << i)) { + if (c) + printk(" "); + printk("%s", mmc_omap_status_bits[i]); + c++; + } +} + +static irqreturn_t mmc_omap_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct mmc_omap_host * host = (struct mmc_omap_host *)dev_id; + u16 status; + int end_command; + int end_transfer; + int transfer_error; + + if (host->cmd == NULL && host->data == NULL) { + status = OMAP_MMC_READ(host->base, STAT); + dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status); + if (status != 0) { + OMAP_MMC_WRITE(host->base, STAT, status); + OMAP_MMC_WRITE(host->base, IE, 0); + } + return IRQ_HANDLED; + } + + end_command = 0; + end_transfer = 0; + transfer_error = 0; + + while ((status = OMAP_MMC_READ(host->base, STAT)) != 0) { + OMAP_MMC_WRITE(host->base, STAT, status); +#ifdef CONFIG_MMC_DEBUG + dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ", + status, host->cmd != NULL ? host->cmd->opcode : -1); + mmc_omap_report_irq(status); + printk("\n"); +#endif + if (host->total_bytes_left) { + if ((status & OMAP_MMC_STAT_A_FULL) || + (status & OMAP_MMC_STAT_END_OF_DATA)) + mmc_omap_xfer_data(host, 0); + if (status & OMAP_MMC_STAT_A_EMPTY) + mmc_omap_xfer_data(host, 1); + } + + if (status & OMAP_MMC_STAT_END_OF_DATA) { + end_transfer = 1; + } + + if (status & OMAP_MMC_STAT_DATA_TOUT) { + dev_dbg(mmc_dev(host->mmc), "data timeout\n"); + if (host->data) { + host->data->error |= MMC_ERR_TIMEOUT; + transfer_error = 1; + } + } + + if (status & OMAP_MMC_STAT_DATA_CRC) { + if (host->data) { + host->data->error |= MMC_ERR_BADCRC; + dev_dbg(mmc_dev(host->mmc), + "data CRC error, bytes left %d\n", + host->total_bytes_left); + transfer_error = 1; + } else { + dev_dbg(mmc_dev(host->mmc), "data CRC error\n"); + } + } + + if (status & OMAP_MMC_STAT_CMD_TOUT) { + /* Timeouts are routine with some commands */ + if (host->cmd) { + if (host->cmd->opcode != MMC_ALL_SEND_CID && + host->cmd->opcode != + MMC_SEND_OP_COND && + host->cmd->opcode != + MMC_APP_CMD && + !mmc_omap_cover_is_open(host)) + dev_err(mmc_dev(host->mmc), + "command timeout, CMD %d\n", + host->cmd->opcode); + host->cmd->error = MMC_ERR_TIMEOUT; + end_command = 1; + } + } + + if (status & OMAP_MMC_STAT_CMD_CRC) { + if (host->cmd) { + dev_err(mmc_dev(host->mmc), + "command CRC error (CMD%d, arg 0x%08x)\n", + host->cmd->opcode, host->cmd->arg); + host->cmd->error = MMC_ERR_BADCRC; + end_command = 1; + } else + dev_err(mmc_dev(host->mmc), + "command CRC error without cmd?\n"); + } + + if (status & OMAP_MMC_STAT_CARD_ERR) { + if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) { + u32 response = OMAP_MMC_READ(host->base, RSP6) + | (OMAP_MMC_READ(host->base, RSP7) << 16); + /* STOP sometimes sets must-ignore bits */ + if (!(response & (R1_CC_ERROR + | R1_ILLEGAL_COMMAND + | R1_COM_CRC_ERROR))) { + end_command = 1; + continue; + } + } + + dev_dbg(mmc_dev(host->mmc), "card status error (CMD%d)\n", + host->cmd->opcode); + if (host->cmd) { + host->cmd->error = MMC_ERR_FAILED; + end_command = 1; + } + if (host->data) { + host->data->error = MMC_ERR_FAILED; + transfer_error = 1; + } + } + + /* + * NOTE: On 1610 the END_OF_CMD may come too early when + * starting a write + */ + if ((status & OMAP_MMC_STAT_END_OF_CMD) && + (!(status & OMAP_MMC_STAT_A_EMPTY))) { + end_command = 1; + } + } + + if (end_command) { + mmc_omap_cmd_done(host, host->cmd); + } + if (transfer_error) + mmc_omap_xfer_done(host, host->data); + else if (end_transfer) + mmc_omap_end_of_data(host, host->data); + + return IRQ_HANDLED; +} + +static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct mmc_omap_host *host = (struct mmc_omap_host *) dev_id; + + schedule_work(&host->switch_work); + + return IRQ_HANDLED; +} + +static void mmc_omap_switch_timer(unsigned long arg) +{ + struct mmc_omap_host *host = (struct mmc_omap_host *) arg; + + schedule_work(&host->switch_work); +} + +/* FIXME: Handle card insertion and removal properly. Maybe use a mask + * for MMC state? */ +static void mmc_omap_switch_callback(unsigned long data, u8 mmc_mask) +{ +} + +static void mmc_omap_switch_handler(void *data) +{ + struct mmc_omap_host *host = (struct mmc_omap_host *) data; + struct mmc_card *card; + static int complained = 0; + int cards = 0, cover_open; + + if (host->switch_pin == -1) + return; + cover_open = mmc_omap_cover_is_open(host); + if (cover_open != host->switch_last_state) { + kobject_uevent(&host->dev->kobj, KOBJ_CHANGE); + host->switch_last_state = cover_open; + } + mmc_detect_change(host->mmc, 0); + list_for_each_entry(card, &host->mmc->cards, node) { + if (mmc_card_present(card)) + cards++; + } + if (mmc_omap_cover_is_open(host)) { + if (!complained) { + dev_info(mmc_dev(host->mmc), "cover is open"); + complained = 1; + } + if (mmc_omap_enable_poll) + mod_timer(&host->switch_timer, jiffies + + msecs_to_jiffies(OMAP_MMC_SWITCH_POLL_DELAY)); + } else { + complained = 0; + } +} + +/* Prepare to transfer the next segment of a scatterlist */ +static void +mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) +{ + int dma_ch = host->dma_ch; + unsigned long data_addr; + u16 buf, frame; + u32 count; + struct scatterlist *sg = &data->sg[host->sg_idx]; + int src_port = 0; + int dst_port = 0; + int sync_dev = 0; + + data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA; + frame = 1 << data->blksz_bits; + count = sg_dma_len(sg); + + if ((data->blocks == 1) && (count > (1 << data->blksz_bits))) + count = frame; + + host->dma_len = count; + + /* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx. + * Use 16 or 32 word frames when the blocksize is at least that large. + * Blocksize is usually 512 bytes; but not for some SD reads. + */ + if (cpu_is_omap15xx() && frame > 32) + frame = 32; + else if (frame > 64) + frame = 64; + count /= frame; + frame >>= 1; + + if (!(data->flags & MMC_DATA_WRITE)) { + buf = 0x800f | ((frame - 1) << 8); + + if (cpu_class_is_omap1()) { + src_port = OMAP_DMA_PORT_TIPB; + dst_port = OMAP_DMA_PORT_EMIFF; + } + if (cpu_is_omap24xx()) + sync_dev = OMAP24XX_DMA_MMC1_RX; + + omap_set_dma_src_params(dma_ch, src_port, + OMAP_DMA_AMODE_CONSTANT, + data_addr, 0, 0); + omap_set_dma_dest_params(dma_ch, dst_port, + OMAP_DMA_AMODE_POST_INC, + sg_dma_address(sg), 0, 0); + omap_set_dma_dest_data_pack(dma_ch, 1); + omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); + } else { + buf = 0x0f80 | ((frame - 1) << 0); + + if (cpu_class_is_omap1()) { + src_port = OMAP_DMA_PORT_EMIFF; + dst_port = OMAP_DMA_PORT_TIPB; + } + if (cpu_is_omap24xx()) + sync_dev = OMAP24XX_DMA_MMC1_TX; + + omap_set_dma_dest_params(dma_ch, dst_port, + OMAP_DMA_AMODE_CONSTANT, + data_addr, 0, 0); + omap_set_dma_src_params(dma_ch, src_port, + OMAP_DMA_AMODE_POST_INC, + sg_dma_address(sg), 0, 0); + omap_set_dma_src_data_pack(dma_ch, 1); + omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); + } + + /* Max limit for DMA frame count is 0xffff */ + if (unlikely(count > 0xffff)) + BUG(); + + OMAP_MMC_WRITE(host->base, BUF, buf); + omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16, + frame, count, OMAP_DMA_SYNC_FRAME, + sync_dev, 0); +} + +/* A scatterlist segment completed */ +static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data) +{ + struct mmc_omap_host *host = (struct mmc_omap_host *) data; + struct mmc_data *mmcdat = host->data; + + if (unlikely(host->dma_ch < 0)) { + dev_err(mmc_dev(host->mmc), "DMA callback while DMA not + enabled\n"); + return; + } + /* FIXME: We really should do something to _handle_ the errors */ + if (ch_status & OMAP_DMA_TOUT_IRQ) { + dev_err(mmc_dev(host->mmc),"DMA timeout\n"); + return; + } + if (ch_status & OMAP_DMA_DROP_IRQ) { + dev_err(mmc_dev(host->mmc), "DMA sync error\n"); + return; + } + if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) { + return; + } + mmcdat->bytes_xfered += host->dma_len; + host->sg_idx++; + if (host->sg_idx < host->sg_len) { + mmc_omap_prepare_dma(host, host->data); + omap_start_dma(host->dma_ch); + } else + mmc_omap_dma_done(host, host->data); +} + +static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data *data) +{ + const char *dev_name; + int sync_dev, dma_ch, is_read, r; + + is_read = !(data->flags & MMC_DATA_WRITE); + del_timer_sync(&host->dma_timer); + if (host->dma_ch >= 0) { + if (is_read == host->dma_is_read) + return 0; + omap_free_dma(host->dma_ch); + host->dma_ch = -1; + } + + if (is_read) { + if (host->id == 1) { + sync_dev = OMAP_DMA_MMC_RX; + dev_name = "MMC1 read"; + } else { + sync_dev = OMAP_DMA_MMC2_RX; + dev_name = "MMC2 read"; + } + } else { + if (host->id == 1) { + sync_dev = OMAP_DMA_MMC_TX; + dev_name = "MMC1 write"; + } else { + sync_dev = OMAP_DMA_MMC2_TX; + dev_name = "MMC2 write"; + } + } + r = omap_request_dma(sync_dev, dev_name, mmc_omap_dma_cb, + host, &dma_ch); + if (r != 0) { + dev_dbg(mmc_dev(host->mmc), "omap_request_dma() failed with %d\n", r); + return r; + } + host->dma_ch = dma_ch; + host->dma_is_read = is_read; + + return 0; +} + +static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req) +{ + u16 reg; + + reg = OMAP_MMC_READ(host->base, SDIO); + reg &= ~(1 << 5); + OMAP_MMC_WRITE(host->base, SDIO, reg); + /* Set maximum timeout */ + OMAP_MMC_WRITE(host->base, CTO, 0xff); +} + +static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req) +{ + int timeout; + u16 reg; + + /* Convert ns to clock cycles by assuming 20MHz frequency + * 1 cycle at 20MHz = 500 ns + */ + timeout = req->data->timeout_clks + req->data->timeout_ns / 500; + + /* Check if we need to use timeout multiplier register */ + reg = OMAP_MMC_READ(host->base, SDIO); + if (timeout > 0xffff) { + reg |= (1 << 5); + timeout /= 1024; + } else + reg &= ~(1 << 5); + OMAP_MMC_WRITE(host->base, SDIO, reg); + OMAP_MMC_WRITE(host->base, DTO, timeout); +} + +static void +mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) +{ + struct mmc_data *data = req->data; + int i, use_dma, block_size; + unsigned sg_len; + + host->data = data; + if (data == NULL) { + OMAP_MMC_WRITE(host->base, BLEN, 0); + OMAP_MMC_WRITE(host->base, NBLK, 0); + OMAP_MMC_WRITE(host->base, BUF, 0); + host->dma_in_use = 0; + set_cmd_timeout(host, req); + return; + } + + + block_size = 1 << data->blksz_bits; + + OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1); + OMAP_MMC_WRITE(host->base, BLEN, block_size - 1); + set_data_timeout(host, req); + + /* cope with calling layer confusion; it issues "single + * block" writes using multi-block scatterlists. + */ + sg_len = (data->blocks == 1) ? 1 : data->sg_len; + + /* Only do DMA for entire blocks */ + use_dma = host->use_dma; + if (use_dma) { + for (i = 0; i < sg_len; i++) { + if ((data->sg[i].length % block_size) != 0) { + use_dma = 0; + break; + } + } + } + + host->sg_idx = 0; + if (use_dma) { + if (mmc_omap_get_dma_channel(host, data) == 0) { + enum dma_data_direction dma_data_dir; + + if (data->flags & MMC_DATA_WRITE) + dma_data_dir = DMA_TO_DEVICE; + else + dma_data_dir = DMA_FROM_DEVICE; + + host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, + sg_len, dma_data_dir); + host->total_bytes_left = 0; + mmc_omap_prepare_dma(host, req->data); + host->brs_received = 0; + host->dma_done = 0; + host->dma_in_use = 1; + } else + use_dma = 0; + } + + /* Revert to PIO? */ + if (!use_dma) { + OMAP_MMC_WRITE(host->base, BUF, 0x1f1f); + host->total_bytes_left = data->blocks * block_size; + host->sg_len = sg_len; + mmc_omap_sg_to_buf(host); + host->dma_in_use = 0; + } +} + +static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req) +{ + struct mmc_omap_host *host = mmc_priv(mmc); + + WARN_ON(host->mrq != NULL); + + host->mrq = req; + + /* only touch fifo AFTER the controller readies it */ + mmc_omap_prepare_data(host, req); + mmc_omap_start_command(host, req->cmd); + if (host->dma_in_use) + omap_start_dma(host->dma_ch); +} + +static void innovator_fpga_socket_power(int on) +{ +#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX) + + if (on) { + fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3), + OMAP1510_FPGA_POWER); + } else { + fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3), + OMAP1510_FPGA_POWER); + } +#endif +} + +/* + * Turn the socket power on/off. Innovator uses FPGA, most boards + * probably use GPIO. + */ +static void mmc_omap_power(struct mmc_omap_host *host, int on) +{ + if (on) { + if (machine_is_omap_innovator()) + innovator_fpga_socket_power(1); + else if (machine_is_omap_h2()) + tps65010_set_gpio_out_value(GPIO3, HIGH); + else if (machine_is_omap_h3()) + /* GPIO 4 of TPS65010 sends SD_EN signal */ + tps65010_set_gpio_out_value(GPIO4, HIGH); + else if (cpu_is_omap24xx()) { + u16 reg = OMAP_MMC_READ(host->base, CON); + OMAP_MMC_WRITE(host->base, CON, reg | (1 << 11)); + } else + if (host->power_pin >= 0) + omap_set_gpio_dataout(host->power_pin, 1); + } else { + if (machine_is_omap_innovator()) + innovator_fpga_socket_power(0); + else if (machine_is_omap_h2()) + tps65010_set_gpio_out_value(GPIO3, LOW); + else if (machine_is_omap_h3()) + tps65010_set_gpio_out_value(GPIO4, LOW); + else if (cpu_is_omap24xx()) { + u16 reg = OMAP_MMC_READ(host->base, CON); + OMAP_MMC_WRITE(host->base, CON, reg & ~(1 << 11)); + } else + if (host->power_pin >= 0) + omap_set_gpio_dataout(host->power_pin, 0); + } +} + +static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct mmc_omap_host *host = mmc_priv(mmc); + int dsor; + int realclock, i; + + realclock = ios->clock; + + if (ios->clock == 0) + dsor = 0; + else { + int func_clk_rate = clk_get_rate(host->fclk); + + dsor = func_clk_rate / realclock; + if (dsor < 1) + dsor = 1; + + if (func_clk_rate / dsor > realclock) + dsor++; + + if (dsor > 250) + dsor = 250; + dsor++; + + if (ios->bus_width == MMC_BUS_WIDTH_4) + dsor |= 1 << 15; + } + + switch (ios->power_mode) { + case MMC_POWER_OFF: + mmc_omap_power(host, 0); + break; + case MMC_POWER_UP: + case MMC_POWER_ON: + mmc_omap_power(host, 1); + dsor |= 1<<11; + break; + } + + host->bus_mode = ios->bus_mode; + host->hw_bus_mode = host->bus_mode; + + clk_enable(host->fclk); + + /* On insanely high arm_per frequencies something sometimes + * goes somehow out of sync, and the POW bit is not being set, + * which results in the while loop below getting stuck. + * Writing to the CON register twice seems to do the trick. */ + for (i = 0; i < 2; i++) + OMAP_MMC_WRITE(host->base, CON, dsor); + if (ios->power_mode == MMC_POWER_UP) { + /* Send clock cycles, poll completion */ + OMAP_MMC_WRITE(host->base, IE, 0); + OMAP_MMC_WRITE(host->base, STAT, 0xffff); + OMAP_MMC_WRITE(host->base, CMD, 1<<7); + while (0 == (OMAP_MMC_READ(host->base, STAT) & 1)); + OMAP_MMC_WRITE(host->base, STAT, 1); + } + clk_disable(host->fclk); +} + +static int mmc_omap_get_ro(struct mmc_host *mmc) +{ + struct mmc_omap_host *host = mmc_priv(mmc); + + return host->wp_pin && omap_get_gpio_datain(host->wp_pin); +} + +static struct mmc_host_ops mmc_omap_ops = { + .request = mmc_omap_request, + .set_ios = mmc_omap_set_ios, + .get_ro = mmc_omap_get_ro, +}; + +static int __init mmc_omap_probe(struct platform_device *pdev) +{ + struct omap_mmc_conf *minfo = pdev->dev.platform_data; + struct mmc_host *mmc; + struct mmc_omap_host *host = NULL; + int ret = 0; + + if (platform_get_resource(pdev, IORESOURCE_MEM, 0) || + platform_get_irq(pdev, IORESOURCE_IRQ, 0)) { + dev_err(&pdev->dev, "mmc_omap_probe: invalid resource type\n"); + return -ENODEV; + } + + if (!request_mem_region(pdev->resource[0].start, + pdev->resource[0].end - pdev->resource[0].start + 1, + pdev->name)) { + dev_dbg(&pdev->dev, "request_mem_region failed\n"); + return -EBUSY; + } + + mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev); + if (!mmc) { + ret = -ENOMEM; + goto out; + } + + host = mmc_priv(mmc); + host->mmc = mmc; + + spin_lock_init(&host->dma_lock); + init_timer(&host->dma_timer); + host->dma_timer.function = mmc_omap_dma_timer; + host->dma_timer.data = (unsigned long) host; + + host->id = pdev->id; + + if (cpu_is_omap24xx()) { + host->iclk = clk_get(&pdev->dev, "mmc_ick"); + if (IS_ERR(host->iclk)) + goto out; + clk_enable(host->iclk); + } + + if (!cpu_is_omap24xx()) + host->fclk = clk_get(&pdev->dev, "mmc_ck"); + else + host->fclk = clk_get(&pdev->dev, "mmc_fck"); + + if (IS_ERR(host->fclk)) { + ret = PTR_ERR(host->fclk); + goto out; + } + + /* REVISIT: + * Also, use minfo->cover to decide how to manage + * the card detect sensing. + */ + host->power_pin = minfo->power_pin; + host->switch_pin = minfo->switch_pin; + host->wp_pin = minfo->wp_pin; + host->use_dma = 1; + host->dma_ch = -1; + + host->irq = pdev->resource[1].start; + host->base = ioremap(pdev->res.start, SZ_4K); + if (!host->base) { + ret = -ENOMEM; + goto out; + } + + if (minfo->wire4) + mmc->caps |= MMC_CAP_4_BIT_DATA; + + mmc->ops = &mmc_omap_ops; + mmc->f_min = 400000; + mmc->f_max = 24000000; + mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; + + /* Use scatterlist DMA to reduce per-transfer costs. + * NOTE max_seg_size assumption that small blocks aren't + * normally used (except e.g. for reading SD registers). + */ + mmc->max_phys_segs = 32; + mmc->max_hw_segs = 32; + mmc->max_sectors = 256; /* NBLK max 11-bits, OMAP also limited by DMA */ + mmc->max_seg_size = mmc->max_sectors * 512; + + if (host->power_pin >= 0) { + if ((ret = omap_request_gpio(host->power_pin)) != 0) { + dev_err(mmc_dev(host->mmc), "Unable to get GPIO + pin for MMC power\n"); + goto out; + } + omap_set_gpio_direction(host->power_pin, 0); + } + + ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host); + if (ret) + goto out; + + host->dev = &pdev->dev; + platform_set_drvdata(pdev, host); + + mmc_add_host(mmc); + + if (host->switch_pin >= 0) { + INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host); + init_timer(&host->switch_timer); + host->switch_timer.function = mmc_omap_switch_timer; + host->switch_timer.data = (unsigned long) host; + if (omap_request_gpio(host->switch_pin) != 0) { + dev_warn(mmc_dev(host->mmc), "Unable to get GPIO pin for MMC cover switch\n"); + host->switch_pin = -1; + goto no_switch; + } + + omap_set_gpio_direction(host->switch_pin, 1); + ret = request_irq(OMAP_GPIO_IRQ(host->switch_pin), + mmc_omap_switch_irq, SA_TRIGGER_RISING, DRIVER_NAME, host); + if (ret) { + dev_warn(mmc_dev(host->mmc), "Unable to get IRQ for MMC cover switch\n"); + omap_free_gpio(host->switch_pin); + host->switch_pin = -1; + goto no_switch; + } + ret = device_create_file(&pdev->dev, &dev_attr_cover_switch); + if (ret == 0) { + ret = device_create_file(&pdev->dev, &dev_attr_enable_poll); + if (ret != 0) + device_remove_file(&pdev->dev, &dev_attr_cover_switch); + } + if (ret) { + dev_wan(mmc_dev(host->mmc), "Unable to create sysfs attributes\n"); + free_irq(OMAP_GPIO_IRQ(host->switch_pin), host); + omap_free_gpio(host->switch_pin); + host->switch_pin = -1; + goto no_switch; + } + if (mmc_omap_enable_poll && mmc_omap_cover_is_open(host)) + schedule_work(&host->switch_work); + } + +no_switch: + return 0; + +out: + /* FIXME: Free other resources too. */ + if (host) { + if (host->iclk && !IS_ERR(host->iclk)) + clk_put(host->iclk); + if (host->fclk && !IS_ERR(host->fclk)) + clk_put(host->fclk); + mmc_free_host(host->mmc); + } + return ret; +} + +static int mmc_omap_remove(struct platform_device *pdev) +{ + struct mmc_omap_host *host = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + if (host) { + mmc_remove_host(host->mmc); + free_irq(host->irq, host); + + if (host->power_pin >= 0) + omap_free_gpio(host->power_pin); + if (host->switch_pin >= 0) { + device_remove_file(&pdev->dev, &dev_attr_enable_poll); + device_remove_file(&pdev->dev, &dev_attr_cover_switch); + free_irq(OMAP_GPIO_IRQ(host->switch_pin), host); + omap_free_gpio(host->switch_pin); + host->switch_pin = -1; + del_timer_sync(&host->switch_timer); + flush_scheduled_work(); + } + if (host->iclk && !IS_ERR(host->iclk)) + clk_put(host->iclk); + if (host->fclk && !IS_ERR(host->fclk)) + clk_put(host->fclk); + mmc_free_host(host->mmc); + } + + release_mem_region(pdev->resource[0].start, + pdev->resource[0].end - pdev->resource[0].start + 1); + + return 0; +} + +#ifdef CONFIG_PM +static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + int ret = 0; + struct mmc_omap_host *host = platform_get_drvdata(pdev); + + if (host && host->suspended) + return 0; + + if (host) { + ret = mmc_suspend_host(host->mmc, mesg); + if (ret == 0) + host->suspended = 1; + } + return ret; +} + +static int mmc_omap_resume(struct platform_device *pdev) +{ + int ret = 0; + struct mmc_omap_host *host = platform_get_drvdata(pdev); + + if (host && !host->suspended) + return 0; + + if (host) { + ret = mmc_resume_host(host->mmc); + if (ret == 0) + host->suspended = 0; + } + + return ret; +} +#else +#define mmc_omap_suspend NULL +#define mmc_omap_resume NULL +#endif + +static struct platform_driver mmc_omap_driver = { + .probe = mmc_omap_probe, + .remove = mmc_omap_remove, + .suspend = mmc_omap_suspend, + .resume = mmc_omap_resume, + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init mmc_omap_init(void) +{ + return platform_driver_register(&mmc_omap_driver); +} + +static void __exit mmc_omap_exit(void) +{ + platform_driver_unregister(&mmc_omap_driver); +} + +module_init(mmc_omap_init); +module_exit(mmc_omap_exit); + +MODULE_DESCRIPTION("OMAP Multimedia Card driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS(DRIVER_NAME); +MODULE_AUTHOR("Juha Yrjölä"); diff --git a/drivers/mmc/omap.h b/drivers/mmc/omap.h new file mode 100644 index 000000000000..c954d355a5e3 --- /dev/null +++ b/drivers/mmc/omap.h @@ -0,0 +1,55 @@ +#ifndef DRIVERS_MEDIA_MMC_OMAP_H +#define DRIVERS_MEDIA_MMC_OMAP_H + +#define OMAP_MMC_REG_CMD 0x00 +#define OMAP_MMC_REG_ARGL 0x04 +#define OMAP_MMC_REG_ARGH 0x08 +#define OMAP_MMC_REG_CON 0x0c +#define OMAP_MMC_REG_STAT 0x10 +#define OMAP_MMC_REG_IE 0x14 +#define OMAP_MMC_REG_CTO 0x18 +#define OMAP_MMC_REG_DTO 0x1c +#define OMAP_MMC_REG_DATA 0x20 +#define OMAP_MMC_REG_BLEN 0x24 +#define OMAP_MMC_REG_NBLK 0x28 +#define OMAP_MMC_REG_BUF 0x2c +#define OMAP_MMC_REG_SDIO 0x34 +#define OMAP_MMC_REG_REV 0x3c +#define OMAP_MMC_REG_RSP0 0x40 +#define OMAP_MMC_REG_RSP1 0x44 +#define OMAP_MMC_REG_RSP2 0x48 +#define OMAP_MMC_REG_RSP3 0x4c +#define OMAP_MMC_REG_RSP4 0x50 +#define OMAP_MMC_REG_RSP5 0x54 +#define OMAP_MMC_REG_RSP6 0x58 +#define OMAP_MMC_REG_RSP7 0x5c +#define OMAP_MMC_REG_IOSR 0x60 +#define OMAP_MMC_REG_SYSC 0x64 +#define OMAP_MMC_REG_SYSS 0x68 + +#define OMAP_MMC_STAT_CARD_ERR (1 << 14) +#define OMAP_MMC_STAT_CARD_IRQ (1 << 13) +#define OMAP_MMC_STAT_OCR_BUSY (1 << 12) +#define OMAP_MMC_STAT_A_EMPTY (1 << 11) +#define OMAP_MMC_STAT_A_FULL (1 << 10) +#define OMAP_MMC_STAT_CMD_CRC (1 << 8) +#define OMAP_MMC_STAT_CMD_TOUT (1 << 7) +#define OMAP_MMC_STAT_DATA_CRC (1 << 6) +#define OMAP_MMC_STAT_DATA_TOUT (1 << 5) +#define OMAP_MMC_STAT_END_BUSY (1 << 4) +#define OMAP_MMC_STAT_END_OF_DATA (1 << 3) +#define OMAP_MMC_STAT_CARD_BUSY (1 << 2) +#define OMAP_MMC_STAT_END_OF_CMD (1 << 0) + +#define OMAP_MMC_READ(base, reg) __raw_readw((base) + OMAP_MMC_REG_##reg) +#define OMAP_MMC_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MMC_REG_##reg) + +/* + * Command types + */ +#define OMAP_MMC_CMDTYPE_BC 0 +#define OMAP_MMC_CMDTYPE_BCR 1 +#define OMAP_MMC_CMDTYPE_AC 2 +#define OMAP_MMC_CMDTYPE_ADTC 3 + +#endif -- cgit v1.2.3-59-g8ed1b From c65631781eb0f2e81865017c1484e9aef76e1b61 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 29 Mar 2006 09:30:20 +0100 Subject: [MMC] Pass -DDEBUG on compiler command line if MMC_DEBUG selected Rather than each driver test MMC_DEBUG itself, and define DEBUG, pass it in via the makefile instead. Fix drivers to use pr_debug() where appropriate, and avoid defining a DEBUG() macro. Signed-off-by: Russell King --- drivers/mmc/Makefile | 4 ++++ drivers/mmc/au1xmmc.c | 19 +++++++++---------- drivers/mmc/mmc.c | 19 +++++++------------ drivers/mmc/mmci.c | 4 ---- drivers/mmc/omap.c | 5 ----- drivers/mmc/pxamci.c | 24 +++++++++--------------- drivers/mmc/sdhci.c | 6 +----- drivers/mmc/wbsd.c | 9 ++------- 8 files changed, 32 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 0b0920ae46b7..c7c34aadfc92 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -23,3 +23,7 @@ obj-$(CONFIG_MMC_AU1X) += au1xmmc.o obj-$(CONFIG_MMC_OMAP) += omap.o mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o + +ifeq ($(CONFIG_MMC_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c index 85e89c77bdea..c0326bbc5f28 100644 --- a/drivers/mmc/au1xmmc.c +++ b/drivers/mmc/au1xmmc.c @@ -56,12 +56,11 @@ #define DRIVER_NAME "au1xxx-mmc" /* Set this to enable special debugging macros */ -/* #define MMC_DEBUG */ -#ifdef MMC_DEBUG -#define DEBUG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args) +#ifdef DEBUG +#define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args) #else -#define DEBUG(fmt, idx, args...) +#define DBG(fmt, idx, args...) #endif const struct { @@ -424,18 +423,18 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host) break; if (status & SD_STATUS_RC) { - DEBUG("RX CRC Error [%d + %d].\n", host->id, + DBG("RX CRC Error [%d + %d].\n", host->id, host->pio.len, count); break; } if (status & SD_STATUS_RO) { - DEBUG("RX Overrun [%d + %d]\n", host->id, + DBG("RX Overrun [%d + %d]\n", host->id, host->pio.len, count); break; } else if (status & SD_STATUS_RU) { - DEBUG("RX Underrun [%d + %d]\n", host->id, + DBG("RX Underrun [%d + %d]\n", host->id, host->pio.len, count); break; } @@ -721,7 +720,7 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) { struct au1xmmc_host *host = mmc_priv(mmc); - DEBUG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n", + DBG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n", host->id, ios->power_mode, ios->clock, ios->vdd, ios->bus_mode); @@ -810,7 +809,7 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id, struct pt_regs *regs) au1xmmc_receive_pio(host); } else if (status & 0x203FBC70) { - DEBUG("Unhandled status %8.8x\n", host->id, status); + DBG("Unhandled status %8.8x\n", host->id, status); handled = 0; } @@ -839,7 +838,7 @@ static void au1xmmc_poll_event(unsigned long arg) if (host->mrq != NULL) { u32 status = au_readl(HOST_STATUS(host)); - DEBUG("PENDING - %8.8x\n", host->id, status); + DBG("PENDING - %8.8x\n", host->id, status); } mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 1888060c5e0c..da6ddd910fc5 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -27,12 +27,6 @@ #include "mmc.h" -#ifdef CONFIG_MMC_DEBUG -#define DBG(x...) printk(KERN_DEBUG x) -#else -#define DBG(x...) do { } while (0) -#endif - #define CMD_RETRIES 3 /* @@ -77,8 +71,9 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) { struct mmc_command *cmd = mrq->cmd; int err = mrq->cmd->error; - DBG("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", cmd->opcode, - err, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); + pr_debug("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", + cmd->opcode, err, cmd->resp[0], cmd->resp[1], + cmd->resp[2], cmd->resp[3]); if (err && cmd->retries) { cmd->retries--; @@ -102,8 +97,8 @@ EXPORT_SYMBOL(mmc_request_done); void mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { - DBG("MMC: starting cmd %02x arg %08x flags %08x\n", - mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags); + pr_debug("MMC: starting cmd %02x arg %08x flags %08x\n", + mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags); WARN_ON(host->card_busy == NULL); @@ -976,8 +971,8 @@ static unsigned int mmc_calculate_clock(struct mmc_host *host) if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr) max_dtr = card->csd.max_dtr; - DBG("MMC: selected %d.%03dMHz transfer rate\n", - max_dtr / 1000000, (max_dtr / 1000) % 1000); + pr_debug("MMC: selected %d.%03dMHz transfer rate\n", + max_dtr / 1000000, (max_dtr / 1000) % 1000); return max_dtr; } diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 9fef29d978b5..df7e861e2fc7 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c @@ -33,12 +33,8 @@ #define DRIVER_NAME "mmci-pl18x" -#ifdef CONFIG_MMC_DEBUG #define DBG(host,fmt,args...) \ pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args) -#else -#define DBG(host,fmt,args...) do { } while (0) -#endif static unsigned int fmax = 515633; diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 49fb2ea4b7ee..becb3c68c34d 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -12,11 +12,6 @@ */ #include - -#ifdef CONFIG_MMC_DEBUG -#define DEBUG /* for dev_dbg(), pr_debug(), etc */ -#endif - #include #include #include diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index c32fad1ce51c..eb9a8826e9b5 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -37,12 +37,6 @@ #include "pxamci.h" -#ifdef CONFIG_MMC_DEBUG -#define DBG(x...) printk(KERN_DEBUG x) -#else -#define DBG(x...) do { } while (0) -#endif - #define DRIVER_NAME "pxa2xx-mci" #define NR_SG 1 @@ -206,7 +200,7 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq) { - DBG("PXAMCI: request done\n"); + pr_debug("PXAMCI: request done\n"); host->mrq = NULL; host->cmd = NULL; host->data = NULL; @@ -252,7 +246,7 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) if ((cmd->resp[0] & 0x80000000) == 0) cmd->error = MMC_ERR_BADCRC; } else { - DBG("ignoring CRC from command %d - *risky*\n",cmd->opcode); + pr_debug("ignoring CRC from command %d - *risky*\n",cmd->opcode); } #else cmd->error = MMC_ERR_BADCRC; @@ -317,12 +311,12 @@ static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs) ireg = readl(host->base + MMC_I_REG); - DBG("PXAMCI: irq %08x\n", ireg); + pr_debug("PXAMCI: irq %08x\n", ireg); if (ireg) { unsigned stat = readl(host->base + MMC_STAT); - DBG("PXAMCI: stat %08x\n", stat); + pr_debug("PXAMCI: stat %08x\n", stat); if (ireg & END_CMD_RES) handled |= pxamci_cmd_done(host, stat); @@ -376,9 +370,9 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct pxamci_host *host = mmc_priv(mmc); - DBG("pxamci_set_ios: clock %u power %u vdd %u.%02u\n", - ios->clock, ios->power_mode, ios->vdd / 100, - ios->vdd % 100); + pr_debug("pxamci_set_ios: clock %u power %u vdd %u.%02u\n", + ios->clock, ios->power_mode, ios->vdd / 100, + ios->vdd % 100); if (ios->clock) { unsigned int clk = CLOCKRATE / ios->clock; @@ -405,8 +399,8 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->cmdat |= CMDAT_INIT; } - DBG("pxamci_set_ios: clkrt = %x cmdat = %x\n", - host->clkrt, host->cmdat); + pr_debug("pxamci_set_ios: clkrt = %x cmdat = %x\n", + host->clkrt, host->cmdat); } static struct mmc_host_ops pxamci_ops = { diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 8b811d94371c..bdbfca050029 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -31,12 +31,8 @@ #define BUGMAIL "" -#ifdef CONFIG_MMC_DEBUG #define DBG(f, x...) \ - printk(KERN_DEBUG DRIVER_NAME " [%s()]: " f, __func__,## x) -#else -#define DBG(f, x...) do { } while (0) -#endif + pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) static const struct pci_device_id pci_ids[] __devinitdata = { /* handle any SD host controller */ diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 3be397d436fa..511f7b0b31d2 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -44,15 +44,10 @@ #define DRIVER_NAME "wbsd" #define DRIVER_VERSION "1.5" -#ifdef CONFIG_MMC_DEBUG #define DBG(x...) \ - printk(KERN_DEBUG DRIVER_NAME ": " x) + pr_debug(DRIVER_NAME ": " x) #define DBGF(f, x...) \ - printk(KERN_DEBUG DRIVER_NAME " [%s()]: " f, __func__ , ##x) -#else -#define DBG(x...) do { } while (0) -#define DBGF(x...) do { } while (0) -#endif + pr_debug(DRIVER_NAME " [%s()]: " f, __func__ , ##x) /* * Device resources -- cgit v1.2.3-59-g8ed1b From 3f89f834497c0f37f16a3b6c32b1d60782facbca Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Mar 2006 09:36:45 -0800 Subject: IB/srp: Fix unmapping of fake scatterlist The recently merged patch to create a fake scatterlist for non-SG SCSI commands had a bug: the driver ended up doing dma_unmap_sg() on a scatterlist scmnd->request_buffer rather than the fake scatter list it created. Fix this so that the driver unmaps the same thing it maps. Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 61924cc30e55..fd8a95a9c5d3 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -607,10 +607,10 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, */ if (likely(scmnd->use_sg)) { nents = scmnd->use_sg; - scat = (struct scatterlist *) scmnd->request_buffer; + scat = scmnd->request_buffer; } else { nents = 1; - scat = (struct scatterlist *) scmnd->request_buffer; + scat = &req->fake_sg; } dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents, -- cgit v1.2.3-59-g8ed1b From a07bacca7b4032dd361ad5c87b1c39ae229e6739 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Sun, 26 Mar 2006 17:01:12 +0200 Subject: IB/mthca: Fix check of size in SRQ creation The previous patch for Tavor broke MemFree logic. The driver should perform limit check only for Tavor. For MemFree, the check is incorrect, since ds (WQE stride) is always a power-of-2 (although the max_desc_size may not be). In Tavor, however, WQE stride and desc_size are the same, and are not necessarily power-of-2. The check was really for the WQE stride (and it Tavor, we use max_desc_size for the stride). Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_srq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 0cfd15802217..e74751ef913c 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -206,7 +206,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, roundup_pow_of_two(sizeof (struct mthca_next_seg) + srq->max_gs * sizeof (struct mthca_data_seg))); - if (ds > dev->limits.max_desc_sz) + if (!mthca_is_memfree(dev) && (ds > dev->limits.max_desc_sz)) return -EINVAL; srq->wqe_shift = long_log2(ds); -- cgit v1.2.3-59-g8ed1b From ef12d4561900d4af37f46a8f2d97dec3c4d59bf9 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Mar 2006 09:36:46 -0800 Subject: IPoIB: Fix oops with raw sockets ipoib_hard_header() needs to handle the case that daddr is NULL. This can happen when packets are injected via a raw socket, and IPoIB shouldn't oops in this case. Reported by Anton Blanchard Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 53a32f65788d..9b0bd7c746ca 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -723,7 +723,7 @@ static int ipoib_hard_header(struct sk_buff *skb, * destination address onto the front of the skb so we can * figure out where to send the packet later. */ - if (!skb->dst || !skb->dst->neighbour) { + if ((!skb->dst || !skb->dst->neighbour) && daddr) { struct ipoib_pseudoheader *phdr = (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); -- cgit v1.2.3-59-g8ed1b From e1f7868c80947d40ef8e1fd37323d939a9bf311c Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Mar 2006 09:36:46 -0800 Subject: IB/mthca: Fix section mismatch problems Quite a few cleanup functions in mthca were marked as __devexit. However, they could also be called from error paths during initialization, so they cannot be marked that way. Just delete all of the incorrect annotations. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_av.c | 2 +- drivers/infiniband/hw/mthca/mthca_cq.c | 2 +- drivers/infiniband/hw/mthca/mthca_eq.c | 6 +++--- drivers/infiniband/hw/mthca/mthca_mad.c | 2 +- drivers/infiniband/hw/mthca/mthca_mcg.c | 2 +- drivers/infiniband/hw/mthca/mthca_mr.c | 4 ++-- drivers/infiniband/hw/mthca/mthca_pd.c | 2 +- drivers/infiniband/hw/mthca/mthca_qp.c | 2 +- drivers/infiniband/hw/mthca/mthca_srq.c | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index f023d3936518..bc5bdcbe51b5 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c @@ -265,7 +265,7 @@ int __devinit mthca_init_av_table(struct mthca_dev *dev) return -ENOMEM; } -void __devexit mthca_cleanup_av_table(struct mthca_dev *dev) +void mthca_cleanup_av_table(struct mthca_dev *dev) { if (mthca_is_memfree(dev)) return; diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 76aabc5bf371..312cf90731ea 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -973,7 +973,7 @@ int __devinit mthca_init_cq_table(struct mthca_dev *dev) return err; } -void __devexit mthca_cleanup_cq_table(struct mthca_dev *dev) +void mthca_cleanup_cq_table(struct mthca_dev *dev) { mthca_array_cleanup(&dev->cq_table.cq, dev->limits.num_cqs); mthca_alloc_cleanup(&dev->cq_table.alloc); diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index cbdc348fb689..99f109c3815d 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -765,7 +765,7 @@ static int __devinit mthca_map_eq_regs(struct mthca_dev *dev) } -static void __devexit mthca_unmap_eq_regs(struct mthca_dev *dev) +static void mthca_unmap_eq_regs(struct mthca_dev *dev) { if (mthca_is_memfree(dev)) { mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & @@ -821,7 +821,7 @@ int __devinit mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt) return ret; } -void __devexit mthca_unmap_eq_icm(struct mthca_dev *dev) +void mthca_unmap_eq_icm(struct mthca_dev *dev) { u8 status; @@ -954,7 +954,7 @@ err_out_free: return err; } -void __devexit mthca_cleanup_eq_table(struct mthca_dev *dev) +void mthca_cleanup_eq_table(struct mthca_dev *dev) { u8 status; int i; diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 4ace6a392f41..dfb482eac9a2 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c @@ -271,7 +271,7 @@ err: return PTR_ERR(agent); } -void mthca_free_agents(struct mthca_dev *dev) +void __devexit mthca_free_agents(struct mthca_dev *dev) { struct ib_mad_agent *agent; int p, q; diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index 9965bda9afed..47ca8a9b7247 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c @@ -388,7 +388,7 @@ int __devinit mthca_init_mcg_table(struct mthca_dev *dev) return 0; } -void __devexit mthca_cleanup_mcg_table(struct mthca_dev *dev) +void mthca_cleanup_mcg_table(struct mthca_dev *dev) { mthca_alloc_cleanup(&dev->mcg_table.alloc); } diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 698b62125765..25e1c1db9a40 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -170,7 +170,7 @@ err_out: return -ENOMEM; } -static void __devexit mthca_buddy_cleanup(struct mthca_buddy *buddy) +static void mthca_buddy_cleanup(struct mthca_buddy *buddy) { int i; @@ -866,7 +866,7 @@ err_mtt_buddy: return err; } -void __devexit mthca_cleanup_mr_table(struct mthca_dev *dev) +void mthca_cleanup_mr_table(struct mthca_dev *dev) { /* XXX check if any MRs are still allocated? */ if (dev->limits.fmr_reserved_mtts) diff --git a/drivers/infiniband/hw/mthca/mthca_pd.c b/drivers/infiniband/hw/mthca/mthca_pd.c index 105fc5faaddf..59df51614c85 100644 --- a/drivers/infiniband/hw/mthca/mthca_pd.c +++ b/drivers/infiniband/hw/mthca/mthca_pd.c @@ -77,7 +77,7 @@ int __devinit mthca_init_pd_table(struct mthca_dev *dev) dev->limits.reserved_pds); } -void __devexit mthca_cleanup_pd_table(struct mthca_dev *dev) +void mthca_cleanup_pd_table(struct mthca_dev *dev) { /* XXX check if any PDs are still allocated? */ mthca_alloc_cleanup(&dev->pd_table.alloc); diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 1bc2678c2fae..057c8e6af87b 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -2204,7 +2204,7 @@ int __devinit mthca_init_qp_table(struct mthca_dev *dev) return err; } -void __devexit mthca_cleanup_qp_table(struct mthca_dev *dev) +void mthca_cleanup_qp_table(struct mthca_dev *dev) { int i; u8 status; diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index e74751ef913c..2dd3aea05341 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -684,7 +684,7 @@ int __devinit mthca_init_srq_table(struct mthca_dev *dev) return err; } -void __devexit mthca_cleanup_srq_table(struct mthca_dev *dev) +void mthca_cleanup_srq_table(struct mthca_dev *dev) { if (!(dev->mthca_flags & MTHCA_FLAG_SRQ)) return; -- cgit v1.2.3-59-g8ed1b From 0cff260a42c051ee64c184ed05d96d18d243f7f6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 29 Mar 2006 22:03:38 +0100 Subject: [SERIAL] Allow 8250 PCI, PNP, GSC and HP300 support to be disabled Allow the 8250 probe modules to be disabled if we're building for with EMBEDDED enabled. This reduces the kernel size by not including unnecessary probe module support. Original idea from Matt Mackall for PCI only, expanded to others by rmk. Signed-off-by: Russell King --- drivers/serial/Kconfig | 27 +++++++++++++++++++++++++++ drivers/serial/Makefile | 12 +++++------- 2 files changed, 32 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index fe0d8b8e91c8..7d22dc0478d3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -63,6 +63,33 @@ config SERIAL_8250_CONSOLE If unsure, say N. +config SERIAL_8250_GSC + tristate + depends on SERIAL_8250 && GSC + default SERIAL_8250 + +config SERIAL_8250_PCI + tristate "8250/16550 PCI device support" if EMBEDDED + depends on SERIAL_8250 && PCI + default SERIAL_8250 + help + This builds standard PCI serial support. You may be able to + disable this feature if you only need legacy serial support. + Saves about 9K. + +config SERIAL_8250_PNP + tristate "8250/16550 PNP device support" if EMBEDDED + depends on SERIAL_8250 && PNP + default SERIAL_8250 + help + This builds standard PNP serial support. You may be able to + disable this feature if you only need legacy serial support. + +config SERIAL_8250_HP300 + tristate + depends on SERIAL_8250 && HP300 + default SERIAL_8250 + config SERIAL_8250_CS tristate "8250/16550 PCMCIA device support" depends on PCMCIA && SERIAL_8250 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index d2b4c214876b..0a71bf68a03f 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -4,15 +4,13 @@ # $Id: Makefile,v 1.8 2002/07/21 21:32:30 rmk Exp $ # -serial-8250-y := -serial-8250-$(CONFIG_PNP) += 8250_pnp.o -serial-8250-$(CONFIG_GSC) += 8250_gsc.o -serial-8250-$(CONFIG_PCI) += 8250_pci.o -serial-8250-$(CONFIG_HP300) += 8250_hp300.o - obj-$(CONFIG_SERIAL_CORE) += serial_core.o obj-$(CONFIG_SERIAL_21285) += 21285.o -obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y) +obj-$(CONFIG_SERIAL_8250) += 8250.o +obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o +obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o +obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o +obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o -- cgit v1.2.3-59-g8ed1b From 5c5131297db57b501f371ab53c40343eac6f2af7 Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Wed, 29 Mar 2006 17:12:05 -0500 Subject: b44: fix force mac address before ifconfig up Initializing the b44 MAC & PCI functional blocks in the controller must occur inside init_one(). This will allow access to the MAC registers. The controller was being powered up in b44_open() which would not allow access to the registers before ifconfig was up. Philip Kohlbecher found this bug. Signed-off-by: Gary Zambrano --- drivers/net/b44.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/b44.c b/drivers/net/b44.c index c3267e4e1bb0..2eab2a88c7bf 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -2033,6 +2033,11 @@ static int __devinit b44_init_one(struct pci_dev *pdev, pci_save_state(bp->pdev); + /* Chip reset provides power to the b44 MAC & PCI cores, which + * is necessary for MAC register access. + */ + b44_chip_reset(bp); + printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name); for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i], -- cgit v1.2.3-59-g8ed1b From 05c8e0ac5c37e9739a852b526afeecae97607cbb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 25 Mar 2006 14:28:57 +0900 Subject: [PATCH] libata: kill trailing whitespace Kill trailing whitespace. Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1cb981375323..86310562da8b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2635,7 +2635,7 @@ static int ata_dma_blacklisted(const struct ata_device *dev) * * FIXME: The current implementation limits all transfer modes to * the fastest of the lowested device on the port. This is not - * required on most controllers. + * required on most controllers. * * LOCKING: * None. -- cgit v1.2.3-59-g8ed1b From b8ab2dc3e1a7c525ca73ba0af3518ec0b7654b3b Mon Sep 17 00:00:00 2001 From: Komuro Date: Sun, 26 Mar 2006 07:31:55 +0900 Subject: [PATCH] axnet_cs.c : add hardware multicast support Signed-off-by: Jeff Garzik --- drivers/net/pcmcia/axnet_cs.c | 61 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index aa5581369399..1cc94b2d76c1 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "../8390.h" #include @@ -1682,17 +1683,67 @@ static struct net_device_stats *get_stats(struct net_device *dev) return &ei_local->stat; } +/* + * Form the 64 bit 8390 multicast table from the linked list of addresses + * associated with this dev structure. + */ + +static inline void make_mc_bits(u8 *bits, struct net_device *dev) +{ + struct dev_mc_list *dmi; + u32 crc; + + for (dmi=dev->mc_list; dmi; dmi=dmi->next) { + + crc = ether_crc(ETH_ALEN, dmi->dmi_addr); + /* + * The 8390 uses the 6 most significant bits of the + * CRC to index the multicast table. + */ + bits[crc>>29] |= (1<<((crc>>26)&7)); + } +} + /** * do_set_multicast_list - set/clear multicast filter * @dev: net device for which multicast filter is adjusted * - * Set or clear the multicast filter for this adaptor. May be called - * from a BH in 2.1.x. Must be called with lock held. + * Set or clear the multicast filter for this adaptor. + * Must be called with lock held. */ static void do_set_multicast_list(struct net_device *dev) { long e8390_base = dev->base_addr; + int i; + struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev); + + if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) { + memset(ei_local->mcfilter, 0, 8); + if (dev->mc_list) + make_mc_bits(ei_local->mcfilter, dev); + } else { + /* set to accept-all */ + memset(ei_local->mcfilter, 0xFF, 8); + } + + /* + * DP8390 manuals don't specify any magic sequence for altering + * the multicast regs on an already running card. To be safe, we + * ensure multicast mode is off prior to loading up the new hash + * table. If this proves to be not enough, we can always resort + * to stopping the NIC, loading the table and then restarting. + */ + + if (netif_running(dev)) + outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); + + outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD); + for(i = 0; i < 8; i++) + { + outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i)); + } + outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD); if(dev->flags&IFF_PROMISC) outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR); @@ -1794,12 +1845,6 @@ static void AX88190_init(struct net_device *dev, int startp) if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i]) printk(KERN_ERR "Hw. address read/write mismap %d\n",i); } - /* - * Initialize the multicast list to accept-all. If we enable multicast - * the higher levels can do the filtering. - */ - for (i = 0; i < 8; i++) - outb_p(0xff, e8390_base + EN1_MULT + i); outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); -- cgit v1.2.3-59-g8ed1b From 00b428c2ab35c81905b3e39d673689216dbd4742 Mon Sep 17 00:00:00 2001 From: Roger Luethi Date: Tue, 28 Mar 2006 20:53:56 +0200 Subject: [PATCH] via-rhine: link state fix Problems with link state detection have been reported several times in the past months. Denis Vlasenko did all the work tracking it down. Jeff Garzik suggested the proper place for the fix. When using the mii library, the driver needs to check mii->force_media and set dev->state accordingly. Signed-off-by: Roger Luethi Signed-off-by: Jeff Garzik --- drivers/net/via-rhine.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 241871589283..a9b2150909d6 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1085,6 +1085,25 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media) else iowrite8(ioread8(ioaddr + ChipCmd1) & ~Cmd1FDuplex, ioaddr + ChipCmd1); + if (debug > 1) + printk(KERN_INFO "%s: force_media %d, carrier %d\n", dev->name, + rp->mii_if.force_media, netif_carrier_ok(dev)); +} + +/* Called after status of force_media possibly changed */ +void rhine_set_carrier(struct mii_if_info *mii) +{ + if (mii->force_media) { + /* autoneg is off: Link is always assumed to be up */ + if (!netif_carrier_ok(mii->dev)) + netif_carrier_on(mii->dev); + } + else /* Let MMI library update carrier status */ + rhine_check_media(mii->dev, 0); + if (debug > 1) + printk(KERN_INFO "%s: force_media %d, carrier %d\n", + mii->dev->name, mii->force_media, + netif_carrier_ok(mii->dev)); } static void rhine_check_media_task(struct net_device *dev) @@ -1782,6 +1801,7 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) spin_lock_irq(&rp->lock); rc = mii_ethtool_sset(&rp->mii_if, cmd); spin_unlock_irq(&rp->lock); + rhine_set_carrier(&rp->mii_if); return rc; } @@ -1869,6 +1889,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) spin_lock_irq(&rp->lock); rc = generic_mii_ioctl(&rp->mii_if, if_mii(rq), cmd, NULL); spin_unlock_irq(&rp->lock); + rhine_set_carrier(&rp->mii_if); return rc; } -- cgit v1.2.3-59-g8ed1b From 4e5077b62b1f67fe0df916e387da4a6dabe577e9 Mon Sep 17 00:00:00 2001 From: Jens Osterkamp Date: Tue, 28 Mar 2006 15:59:55 +0200 Subject: [PATCH] spidernet : reduce console spam This patch reduces the message level of the RX ram full messages from err to debug to prevent spamming the console leaving it in the logfiles though. From: Jens Osterkamp Signed-off-by: Jeff Garzik --- drivers/net/spider_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 1f5975a61e1f..0000de01ec15 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -1442,7 +1442,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) case SPIDER_NET_GRFAFLLINT: /* fallthrough */ case SPIDER_NET_GRMFLLINT: if (netif_msg_intr(card) && net_ratelimit()) - pr_err("Spider RX RAM full, incoming packets " + pr_debug("Spider RX RAM full, incoming packets " "might be discarded!\n"); spider_net_rx_irq_off(card); tasklet_schedule(&card->rxram_full_tl); -- cgit v1.2.3-59-g8ed1b From 8a89334caf80bb7c86383b73fd5a528cb88c696f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 27 Mar 2006 12:26:12 -0800 Subject: [PATCH] acenic: fix section mismatches Fix section mismatches in acenic driver: WARNING: drivers/net/acenic.o - Section mismatch: reference to .init.data:tigon2FwText from .text between 'acenic_probe_one' (at offset 0x2409) and 'ace_interrupt' WARNING: drivers/net/acenic.o - Section mismatch: reference to .init.data:tigon2FwRodata from .text between 'acenic_probe_one' (at offset 0x2422) and 'ace_interrupt' Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/net/acenic_firmware.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h index 6d625d595622..d7882dd783c8 100644 --- a/drivers/net/acenic_firmware.h +++ b/drivers/net/acenic_firmware.h @@ -4397,7 +4397,7 @@ static u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = { 0x3c010001, 0x220821, 0xac317e30, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x0 }; -static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { +static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __devinitdata = { 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e, @@ -4571,7 +4571,7 @@ static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x0, 0x14c38, 0x14c38, 0x14b80, 0x14bc4, 0x14c38, 0x14c38, 0x0, 0x0, 0x0 }; -static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = { +static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __devinitdata = { 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242, @@ -4612,7 +4612,7 @@ static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = { #define tigon2FwSbssLen 0xcc #define tigon2FwBssAddr 0x00016f50 #define tigon2FwBssLen 0x20c0 -static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { +static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = { 0x0, 0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000, @@ -9154,7 +9154,7 @@ static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24020001, 0x8f430328, 0x1021, 0x24630001, 0x3e00008, 0xaf430328, 0x3e00008, 0x0, 0x0, 0x0, 0x0, 0x0 }; -static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { +static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __devinitdata = { 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, @@ -9425,7 +9425,7 @@ static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x14ed8, 0x14b8c, 0x14bd8, 0x14c24, 0x14ed8, 0x7365746d, 0x61636163, 0x74000000, 0x0, 0x0 }; -static u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __initdata = { +static u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __devinitdata = { 0x1, 0x1, 0x1, 0xc001fc, 0x3ffc, 0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49, -- cgit v1.2.3-59-g8ed1b From ff59c4563a8d1b39597aab4917959146c61f09b0 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Mon, 27 Mar 2006 13:27:43 -0800 Subject: [PATCH] bonding: support carrier state for master Add support for the bonding master to specify its carrier state based upon the state of the slaves. For 802.3ad, the bond is up if there is an active, parterned aggregator. For other modes, the bond is up if any slaves are up. Updates driver version to 3.0.3. Based on a patch by jamal . Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_3ad.c | 28 ++++++++++++ drivers/net/bonding/bond_3ad.h | 1 + drivers/net/bonding/bond_main.c | 97 ++++++++++++++++++++++++++++++----------- drivers/net/bonding/bonding.h | 4 +- 4 files changed, 102 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index f3f5825469d6..6a407070c2e8 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2294,6 +2294,34 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) port->sm_vars |= AD_PORT_BEGIN; } +/* + * set link state for bonding master: if we have an active partnered + * aggregator, we're up, if not, we're down. Presumes that we cannot + * have an active aggregator if there are no slaves with link up. + * + * Called by bond_set_carrier(). Return zero if carrier state does not + * change, nonzero if it does. + */ +int bond_3ad_set_carrier(struct bonding *bond) +{ + struct aggregator *agg; + + agg = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator)); + if (agg && MAC_ADDRESS_COMPARE(&agg->partner_system, &null_mac_addr)) { + if (!netif_carrier_ok(bond->dev)) { + netif_carrier_on(bond->dev); + return 1; + } + return 0; + } + + if (netif_carrier_ok(bond->dev)) { + netif_carrier_off(bond->dev); + return 1; + } + return 0; +} + /** * bond_3ad_get_active_agg_info - get information of the active aggregator * @bond: bonding struct to work on diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index 5ee2cef5b037..6ad5ad6e65d5 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@ -283,5 +283,6 @@ void bond_3ad_handle_link_change(struct slave *slave, char link); int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info); int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev); int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev); +int bond_3ad_set_carrier(struct bonding *bond); #endif //__BOND_3AD_H__ diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f13a539dc169..55d236726d11 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -558,6 +558,42 @@ out: /*------------------------------- Link status -------------------------------*/ +/* + * Set the carrier state for the master according to the state of its + * slaves. If any slaves are up, the master is up. In 802.3ad mode, + * do special 802.3ad magic. + * + * Returns zero if carrier state does not change, nonzero if it does. + */ +static int bond_set_carrier(struct bonding *bond) +{ + struct slave *slave; + int i; + + if (bond->slave_cnt == 0) + goto down; + + if (bond->params.mode == BOND_MODE_8023AD) + return bond_3ad_set_carrier(bond); + + bond_for_each_slave(bond, slave, i) { + if (slave->link == BOND_LINK_UP) { + if (!netif_carrier_ok(bond->dev)) { + netif_carrier_on(bond->dev); + return 1; + } + return 0; + } + } + +down: + if (netif_carrier_ok(bond->dev)) { + netif_carrier_off(bond->dev); + return 1; + } + return 0; +} + /* * Get link speed and duplex from the slave's base driver * using ethtool. If for some reason the call fails or the @@ -1074,10 +1110,24 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) void bond_select_active_slave(struct bonding *bond) { struct slave *best_slave; + int rv; best_slave = bond_find_best_slave(bond); if (best_slave != bond->curr_active_slave) { bond_change_active_slave(bond, best_slave); + rv = bond_set_carrier(bond); + if (!rv) + return; + + if (netif_carrier_ok(bond->dev)) { + printk(KERN_INFO DRV_NAME + ": %s: first active interface up!\n", + bond->dev->name); + } else { + printk(KERN_INFO DRV_NAME ": %s: " + "now running without any active interface !\n", + bond->dev->name); + } } } @@ -1458,10 +1508,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (((!bond->curr_active_slave) || (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) && (new_slave->link != BOND_LINK_DOWN)) { - dprintk("This is the first active slave\n"); /* first slave or no active slave yet, and this link is OK, so make this interface the active one */ bond_change_active_slave(bond, new_slave); + printk(KERN_INFO DRV_NAME + ": %s: first active interface up!\n", + bond->dev->name); + netif_carrier_on(bond->dev); + } else { dprintk("This is just a backup slave\n"); bond_set_slave_inactive_flags(new_slave); @@ -1517,6 +1571,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) break; } /* switch(bond_mode) */ + bond_set_carrier(bond); + write_unlock_bh(&bond->lock); res = bond_create_slave_symlinks(bond_dev, slave_dev); @@ -1656,18 +1712,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) bond_alb_deinit_slave(bond, slave); } - if (oldcurrent == slave) { + if (oldcurrent == slave) bond_select_active_slave(bond); - if (!bond->curr_active_slave) { - printk(KERN_INFO DRV_NAME - ": %s: now running without any active " - "interface !\n", - bond_dev->name); - } - } - if (bond->slave_cnt == 0) { + bond_set_carrier(bond); + /* if the last slave was removed, zero the mac address * of the master so it will be set by the application * to the mac address of the first slave @@ -1751,6 +1801,8 @@ static int bond_release_all(struct net_device *bond_dev) write_lock_bh(&bond->lock); + netif_carrier_off(bond_dev); + if (bond->slave_cnt == 0) { goto out; } @@ -2187,15 +2239,9 @@ void bond_mii_monitor(struct net_device *bond_dev) bond_select_active_slave(bond); - if (oldcurrent && !bond->curr_active_slave) { - printk(KERN_INFO DRV_NAME - ": %s: now running without any active " - "interface !\n", - bond_dev->name); - } - write_unlock(&bond->curr_slave_lock); - } + } else + bond_set_carrier(bond); re_arm: if (bond->params.miimon) { @@ -2499,13 +2545,6 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev) bond_select_active_slave(bond); - if (oldcurrent && !bond->curr_active_slave) { - printk(KERN_INFO DRV_NAME - ": %s: now running without any active " - "interface !\n", - bond_dev->name); - } - write_unlock(&bond->curr_slave_lock); } @@ -2579,12 +2618,15 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev) bond->current_arp_slave = NULL; } + bond_set_carrier(bond); + if (slave == bond->curr_active_slave) { printk(KERN_INFO DRV_NAME ": %s: %s is up and now the " "active interface\n", bond_dev->name, slave->dev->name); + netif_carrier_on(bond->dev); } else { printk(KERN_INFO DRV_NAME ": %s: backup interface %s is " @@ -2844,7 +2886,8 @@ static void bond_info_show_master(struct seq_file *seq) (curr) ? curr->dev->name : "None"); } - seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down"); + seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ? + "up" : "down"); seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon); seq_printf(seq, "Up Delay (ms): %d\n", bond->params.updelay * bond->params.miimon); @@ -4531,6 +4574,8 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond if (newbond) *newbond = bond_dev->priv; + netif_carrier_off(bond_dev); + rtnl_unlock(); /* allows sysfs registration of net device */ res = bond_create_sysfs_entry(bond_dev->priv); goto done; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index ce9dc9b4e2dc..0bdfe2c71453 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -22,8 +22,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.0.2" -#define DRV_RELDATE "February 21, 2006" +#define DRV_VERSION "3.0.3" +#define DRV_RELDATE "March 23, 2006" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" -- cgit v1.2.3-59-g8ed1b From 8dfc914a3f2ae4e303e2bff89f28fc14cee8a9a6 Mon Sep 17 00:00:00 2001 From: Jens Osterkamp Date: Mon, 27 Mar 2006 17:16:36 +0200 Subject: [PATCH] spidernet : enable tx checksum offloading by default This enables TX checksum offloading for the spidernet driver by default. Signed-off-by: Jens Osterkamp Signed-off-by: Jeff Garzik --- drivers/net/spider_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 0000de01ec15..43f5e86fc559 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -2086,7 +2086,7 @@ spider_net_setup_netdev(struct spider_net_card *card) spider_net_setup_netdev_ops(netdev); - netdev->features = 0; + netdev->features = NETIF_F_HW_CSUM; /* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | * NETIF_F_HW_VLAN_FILTER */ -- cgit v1.2.3-59-g8ed1b From a8b4cf42cf57e44e3c4a585e0f0a71e3a7efbf29 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 28 Mar 2006 14:08:55 -0800 Subject: [PATCH] natsemi: Support oversized EEPROMs The natsemi chip can have a larger EEPROM attached than it itself uses for configuration. This patch adds support for user space access to such an EEPROM. Signed-off-by: Mark Brown Cc: Tim Hockin Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/natsemi.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 8d4999837b65..7826afbb9db9 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -226,7 +226,7 @@ static int full_duplex[MAX_UNITS]; NATSEMI_PG1_NREGS) #define NATSEMI_REGS_VER 1 /* v1 added RFDR registers */ #define NATSEMI_REGS_SIZE (NATSEMI_NREGS * sizeof(u32)) -#define NATSEMI_EEPROM_SIZE 24 /* 12 16-bit values */ +#define NATSEMI_DEF_EEPROM_SIZE 24 /* 12 16-bit values */ /* Buffer sizes: * The nic writes 32-bit values, even if the upper bytes of @@ -714,6 +714,8 @@ struct netdev_private { unsigned int iosize; spinlock_t lock; u32 msg_enable; + /* EEPROM data */ + int eeprom_size; }; static void move_int_phy(struct net_device *dev, int addr); @@ -890,6 +892,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, np->msg_enable = (debug >= 0) ? (1<hands_off = 0; np->intr_status = 0; + np->eeprom_size = NATSEMI_DEF_EEPROM_SIZE; /* Initial port: * - If the nic was configured to use an external phy and if find_mii @@ -2582,7 +2585,8 @@ static int get_regs_len(struct net_device *dev) static int get_eeprom_len(struct net_device *dev) { - return NATSEMI_EEPROM_SIZE; + struct netdev_private *np = netdev_priv(dev); + return np->eeprom_size; } static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) @@ -2669,15 +2673,20 @@ static u32 get_link(struct net_device *dev) static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct netdev_private *np = netdev_priv(dev); - u8 eebuf[NATSEMI_EEPROM_SIZE]; + u8 *eebuf; int res; + eebuf = kmalloc(np->eeprom_size, GFP_KERNEL); + if (!eebuf) + return -ENOMEM; + eeprom->magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16); spin_lock_irq(&np->lock); res = netdev_get_eeprom(dev, eebuf); spin_unlock_irq(&np->lock); if (!res) memcpy(data, eebuf+eeprom->offset, eeprom->len); + kfree(eebuf); return res; } @@ -3033,9 +3042,10 @@ static int netdev_get_eeprom(struct net_device *dev, u8 *buf) int i; u16 *ebuf = (u16 *)buf; void __iomem * ioaddr = ns_ioaddr(dev); + struct netdev_private *np = netdev_priv(dev); /* eeprom_read reads 16 bits, and indexes by 16 bits */ - for (i = 0; i < NATSEMI_EEPROM_SIZE/2; i++) { + for (i = 0; i < np->eeprom_size/2; i++) { ebuf[i] = eeprom_read(ioaddr, i); /* The EEPROM itself stores data bit-swapped, but eeprom_read * reads it back "sanely". So we swap it back here in order to -- cgit v1.2.3-59-g8ed1b From 8a91ed60f58451342a25f3ab4484c7257430aa8e Mon Sep 17 00:00:00 2001 From: Arthur Othieno Date: Tue, 28 Mar 2006 14:09:01 -0800 Subject: [PATCH] net: remove CONFIG_NET_CBUS conditional for NS8390 Don't bother testing for CONFIG_NET_CBUS ("NEC PC-9800 C-bus cards"); it went out with the rest of PC98 subarch. Signed-off-by: Arthur Othieno Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/8390.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/8390.h b/drivers/net/8390.h index 599b68d8c45f..51e39dcd0603 100644 --- a/drivers/net/8390.h +++ b/drivers/net/8390.h @@ -134,7 +134,7 @@ struct ei_device { #define inb_p(_p) inb(_p) #define outb_p(_v,_p) outb(_v,_p) -#elif defined(CONFIG_NET_CBUS) || defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE) +#elif defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE) #define EI_SHIFT(x) (ei_local->reg_offset[x]) #else #define EI_SHIFT(x) (x) -- cgit v1.2.3-59-g8ed1b From bc0e1fc970279c539db1e94dd473acbb193ee473 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Tue, 28 Mar 2006 16:36:23 -0600 Subject: [PATCH] Janitor: drivers/net/pcnet32: fix incorrect comments The comments concerning how the pcnet32 ethernet device driver selects the MAC addr to use are incorrect. A recent patch (in the last 3 months) changed how the code worked, but did not change the comments. Side comment: the new behaviour is good; I've got a pcnet32 card which powers up with garbage in the CSR's, and a good MAC addr in the PROM. Signed-off-by: Linas Vepstas Signed-off-by: Jeff Garzik --- drivers/net/pcnet32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 9595f74da93f..07c31f19c6ba 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1167,8 +1167,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) * station address PROM at the base address and programmed into the * "Physical Address Registers" CSR12-14. * As a precautionary measure, we read the PROM values and complain if - * they disagree with the CSRs. Either way, we use the CSR values, and - * double check that they are valid. + * they disagree with the CSRs. If they miscompare, and the PROM addr + * is valid, then the PROM addr is used. */ for (i = 0; i < 3; i++) { unsigned int val; -- cgit v1.2.3-59-g8ed1b From 391fc09a143aac08d1a3dc37b60238612b504ad3 Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Tue, 28 Mar 2006 14:57:38 -0800 Subject: [PATCH] b44: ensure valid mac addr Added code to check for invalid MAC address from eeprom or user input. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 2eab2a88c7bf..15032f2c7817 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1339,6 +1339,9 @@ static int b44_set_mac_addr(struct net_device *dev, void *p) if (netif_running(dev)) return -EBUSY; + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); spin_lock_irq(&bp->lock); @@ -1876,6 +1879,12 @@ static int __devinit b44_get_invariants(struct b44 *bp) bp->dev->dev_addr[3] = eeprom[80]; bp->dev->dev_addr[4] = eeprom[83]; bp->dev->dev_addr[5] = eeprom[82]; + + if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){ + printk(KERN_ERR PFX "Invalid MAC address found in EEPROM\n"); + return -EINVAL; + } + memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len); bp->phy_addr = eeprom[90] & 0x1f; -- cgit v1.2.3-59-g8ed1b From 5d4fe2c1ce83c3e967ccc1ba3d580c1a5603a866 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 29 Mar 2006 15:12:44 +0200 Subject: [PATCH] ixp2000: fix gcc4 breakage gcc4 doesn't like us declaring a static function inside another function. We can do away with this construct altogether and use BUILD_BUG_ON() instead (idea from Andi Kleen.) Signed-off-by: Lennert Buytenhek Signed-off-by: Jeff Garzik --- drivers/net/ixp2000/ixpdev.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index 77f104a005f3..fbc2d21020f4 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -299,10 +299,7 @@ int ixpdev_init(int __nds_count, struct net_device **__nds, int i; int err; - if (RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192) { - static void __too_many_rx_or_tx_buffers(void); - __too_many_rx_or_tx_buffers(); - } + BUILD_BUG_ON(RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192); printk(KERN_INFO "IXP2000 MSF ethernet driver %s\n", DRV_MODULE_VERSION); -- cgit v1.2.3-59-g8ed1b From 4e5ec5dba22ea509b1a004f9815751f0ffc815e5 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Mar 2006 18:42:40 +0100 Subject: [PATCH] libata: BMDMA handling updates This is the minimal patch set to enable the current code to be used with a controller following SFF (ie any PATA and early SATA controllers) safely without crashes if there is no BMDMA area or if BMDMA is not assigned by the BIOS for some reason. Simplex status is recorded but not acted upon in this change, this isn't a problem with the current drivers as none of them are for simplex hardware. A following diff will deal with that. The flags in the probe structure remain ->host_set_flags although Jeff asked me to rename them, simply because the rename would break the usual Linux rules that old code should break when there are changes. not compile and run and then blow up/eat your computer/etc. Renaming this later is a trivial exercise once a better name is chosen. Signed-off-by: Jeff Garzik --- drivers/scsi/libata-bmdma.c | 26 ++++++++++++++++++++++---- include/linux/libata.h | 4 ++++ 2 files changed, 26 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 95d81d86d8b7..835dff0bafdc 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -703,6 +703,7 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); int p = 0; + unsigned long bmdma; if (!probe_ent) return NULL; @@ -716,7 +717,12 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int probe_ent->port[p].altstatus_addr = probe_ent->port[p].ctl_addr = pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; - probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4); + bmdma = pci_resource_start(pdev, 4); + if (bmdma) { + if (inb(bmdma + 2) & 0x80) + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + probe_ent->port[p].bmdma_addr = bmdma; + } ata_std_ports(&probe_ent->port[p]); p++; } @@ -726,7 +732,13 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int probe_ent->port[p].altstatus_addr = probe_ent->port[p].ctl_addr = pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; - probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8; + bmdma = pci_resource_start(pdev, 4); + if (bmdma) { + bmdma += 8; + if(inb(bmdma + 2) & 0x80) + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + probe_ent->port[p].bmdma_addr = bmdma; + } ata_std_ports(&probe_ent->port[p]); p++; } @@ -740,6 +752,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info *port, int port_num) { struct ata_probe_ent *probe_ent; + unsigned long bmdma; probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port); if (!probe_ent) @@ -766,8 +779,13 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, break; } - probe_ent->port[0].bmdma_addr = - pci_resource_start(pdev, 4) + 8 * port_num; + bmdma = pci_resource_start(pdev, 4); + if (bmdma != 0) { + bmdma += 8 * port_num; + probe_ent->port[0].bmdma_addr = bmdma; + if (inb(bmdma + 2) & 0x80) + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + } ata_std_ports(&probe_ent->port[0]); return probe_ent; diff --git a/include/linux/libata.h b/include/linux/libata.h index 9fcc061e3adf..a5c213ce97c9 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -160,6 +160,9 @@ enum { ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */ + /* host set flags */ + ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ + /* various lengths of time */ ATA_TMOUT_PIO = 30 * HZ, ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */ @@ -278,6 +281,7 @@ struct ata_probe_ent { unsigned long irq; unsigned int irq_flags; unsigned long host_flags; + unsigned long host_set_flags; void __iomem *mmio_base; void *private_data; }; -- cgit v1.2.3-59-g8ed1b From e35a9e01f2a504871e70576a9e11dbe4d8dee456 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Mar 2006 18:46:37 +0100 Subject: [PATCH] libata: Add ->set_mode hook for odd drivers Some hardware doesn't want the usual mode setup logic running. This allows the hardware driver to replace it for special cases in the least invasive way possible. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 +++++- include/linux/libata.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 86310562da8b..10933cb722e6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1409,7 +1409,11 @@ static int ata_bus_probe(struct ata_port *ap) if (!found) goto err_out_disable; - ata_set_mode(ap); + 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; diff --git a/include/linux/libata.h b/include/linux/libata.h index a5c213ce97c9..6a9316cbb70b 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -433,6 +433,7 @@ struct ata_port_operations { void (*dev_select)(struct ata_port *ap, unsigned int device); 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); -- cgit v1.2.3-59-g8ed1b From 692785e798f341c057ff976c35a3d86ad5af8ac6 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Mar 2006 18:49:19 +0100 Subject: [PATCH] libata - ATA is both ATA and CFA I think this is still needed with the new probe code (which btw seems to be missing docs in upstream ?). Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 10933cb722e6..41659448a204 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1140,7 +1140,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, swap_buf_le16(id, ATA_ID_WORDS); /* sanity check */ - if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) { + if ((class == ATA_DEV_ATA) != (ata_id_is_ata(id) | ata_id_is_cfa(id))) { rc = -EINVAL; reason = "device reports illegal type"; goto err_out; -- cgit v1.2.3-59-g8ed1b From 5444a6f405618706eddbe1605ef8533b1b655764 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Mar 2006 18:58:20 +0100 Subject: [PATCH] libata: Simplex and other mode filtering logic Add a field to the host_set called 'flags' (was host_set_flags changed to suit Jeff) Add a simplex_claimed field so we can remember who owns the DMA channel Add a ->mode_filter() hook to allow drivers to filter modes Add docs for mode_filter and set_mode Filter according to simplex state Filter cable in core This provides the needed framework to support all the mode rules found in the PATA world. The simplex filter deals with 'to spec' simplex DMA systems found in older chips. The cable filter avoids duplicating the same rules in each chip driver with PATA. Finally the mode filter is neccessary because drive/chip combinations have errata that forbid certain modes with some drives or types of ATA object. Drive speed setup remains per channel for now and the filters now use the framework Tejun put into place which cleans them up a lot from the older libata-pata patches. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- Documentation/DocBook/libata.tmpl | 47 +++++++++++++++++++++++++++++++++++---- drivers/scsi/libata-core.c | 31 ++++++++++++++++++++++++-- include/linux/libata.h | 4 ++++ 3 files changed, 76 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl index d260d92089ad..5bcbb6ee3bc0 100644 --- a/Documentation/DocBook/libata.tmpl +++ b/Documentation/DocBook/libata.tmpl @@ -120,14 +120,27 @@ void (*dev_config) (struct ata_port *, struct ata_device *); void (*set_piomode) (struct ata_port *, struct ata_device *); void (*set_dmamode) (struct ata_port *, struct ata_device *); -void (*post_set_mode) (struct ata_port *ap); +void (*post_set_mode) (struct ata_port *); +unsigned int (*mode_filter) (struct ata_port *, struct ata_device *, unsigned int); Hooks called prior to the issue of SET FEATURES - XFER MODE - command. dev->pio_mode is guaranteed to be valid when - ->set_piomode() is called, and dev->dma_mode is guaranteed to be - valid when ->set_dmamode() is called. ->post_set_mode() is + command. The optional ->mode_filter() hook is called when libata + has built a mask of the possible modes. This is passed to the + ->mode_filter() function which should return a mask of valid modes + after filtering those unsuitable due to hardware limits. It is not + valid to use this interface to add modes. + + + dev->pio_mode and dev->dma_mode are guaranteed to be valid when + ->set_piomode() and when ->set_dmamode() is called. The timings for + any other drive sharing the cable will also be valid at this point. + That is the library records the decisions for the modes of each + drive on a channel before it attempts to set any of them. + + + ->post_set_mode() is called unconditionally, after the SET FEATURES - XFER MODE command completes successfully. @@ -230,6 +243,32 @@ void (*dev_select)(struct ata_port *ap, unsigned int device); + Private tuning method + +void (*set_mode) (struct ata_port *ap); + + + + By default libata performs drive and controller tuning in + accordance with the ATA timing rules and also applies blacklists + and cable limits. Some controllers need special handling and have + custom tuning rules, typically raid controllers that use ATA + commands but do not actually do drive timing. + + + + + This hook should not be used to replace the standard controller + tuning logic when a controller has quirks. Replacing the default + tuning logic in that case would bypass handling for drive and + bridge quirks that may be important to data reliability. If a + controller needs to filter the mode selection it should use the + mode_filter hook instead. + + + + + Reset ATA bus void (*phy_reset) (struct ata_port *ap); diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 41659448a204..b1ddf40533b5 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1818,7 +1818,7 @@ static void ata_host_set_dma(struct ata_port *ap) */ static void ata_set_mode(struct ata_port *ap) { - int i, rc; + int i, rc, used_dma = 0; /* step 1: calculate xfer_mask */ for (i = 0; i < ATA_MAX_DEVICES; i++) { @@ -1836,6 +1836,9 @@ static void ata_set_mode(struct ata_port *ap) dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); dev->pio_mode = ata_xfer_mask2mode(pio_mask); dev->dma_mode = ata_xfer_mask2mode(dma_mask); + + if (dev->dma_mode) + used_dma = 1; } /* step 2: always set host PIO timings */ @@ -1857,6 +1860,17 @@ 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. + */ + + if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX)) + ap->host_set->simplex_claimed = 1; + + /* + * Chip specific finalisation + */ if (ap->ops->post_set_mode) ap->ops->post_set_mode(ap); @@ -2646,13 +2660,14 @@ static int ata_dma_blacklisted(const struct ata_device *dev) */ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) { + struct ata_host_set *hs = ap->host_set; unsigned long xfer_mask; int i; xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, ap->udma_mask); - /* use port-wide xfermask for now */ + /* 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)) @@ -2662,12 +2677,23 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) 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)) printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " "disabling DMA\n", ap->id, dev->devno); + if (hs->flags & ATA_HOST_SIMPLEX) { + 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); } @@ -4531,6 +4557,7 @@ int ata_device_add(const struct ata_probe_ent *ent) host_set->mmio_base = ent->mmio_base; host_set->private_data = ent->private_data; host_set->ops = ent->port_ops; + host_set->flags = ent->host_set_flags; /* register each port bound to this device */ for (i = 0; i < ent->n_ports; i++) { diff --git a/include/linux/libata.h b/include/linux/libata.h index 6a9316cbb70b..0d61357604d5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -294,6 +294,9 @@ struct ata_host_set { unsigned int n_ports; void *private_data; const struct ata_port_operations *ops; + unsigned long flags; + int simplex_claimed; /* Keep seperate in case we + ever need to do this locked */ struct ata_port * ports[0]; }; @@ -423,6 +426,7 @@ struct ata_port_operations { void (*set_piomode) (struct ata_port *, struct ata_device *); void (*set_dmamode) (struct ata_port *, struct ata_device *); + unsigned long (*mode_filter) (const struct ata_port *, struct ata_device *, unsigned long); void (*tf_load) (struct ata_port *ap, const struct ata_taskfile *tf); void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); -- cgit v1.2.3-59-g8ed1b From 17efc5f7237995295cbe008828788d187fea3c88 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Mar 2006 19:01:32 +0100 Subject: [PATCH] libata: Fix interesting use of "extern" and also some bracketing Signed-off-by: Alan Cox Last of the set, just clean up some oddments. Assuming the whole set is now ok then the remaining differences are the setup of PIO_0 at reset and the ->data_xfer method. Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b1ddf40533b5..ac19505f7f1f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2160,9 +2160,9 @@ static int sata_phy_resume(struct ata_port *ap) * so makes reset sequence different from the original * ->phy_reset implementation and Jeff nervous. :-P */ -extern void ata_std_probeinit(struct ata_port *ap) +void ata_std_probeinit(struct ata_port *ap) { - if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) { + if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { sata_phy_resume(ap); if (sata_dev_present(ap)) ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); -- cgit v1.2.3-59-g8ed1b From 00b6f5e9e04b2186a71a5892640bb2d8e09a030e Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Mon, 27 Mar 2006 16:39:18 +0800 Subject: [PATCH] libata: ata_dev_init_params() fixes ata_dev_init_params() fixes: - Get the "heads" and "sectors" parameters from caller instead of implicitly from dev->id[]. - Return AC_ERR_INVALID instead of 0 if an invalid parameter is found Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ac19505f7f1f..21b0ed583b8a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -62,7 +62,9 @@ #include "libata.h" static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev); + struct ata_device *dev, + u16 heads, + u16 sectors); static void ata_set_mode(struct ata_port *ap); static unsigned int ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); @@ -1156,7 +1158,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); + err_mask = ata_dev_init_params(ap, dev, id[3], id[6]); if (err_mask) { rc = -EIO; reason = "INIT_DEV_PARAMS failed"; @@ -2748,16 +2750,16 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, */ static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev) + struct ata_device *dev, + u16 heads, + u16 sectors) { struct ata_taskfile tf; unsigned int err_mask; - u16 sectors = dev->id[6]; - u16 heads = dev->id[3]; /* Number of sectors per track 1-255. Number of heads 1-16 */ if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16) - return 0; + return AC_ERR_INVALID; /* set up init dev params taskfile */ DPRINTK("init dev params \n"); -- cgit v1.2.3-59-g8ed1b From 63af2a5c5990d95f1e7d8795f1425fb976ea2b4b Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 29 Mar 2006 09:50:31 -0500 Subject: [PATCH] sata_mv: three bug fixes (1) A DMA transfer size of 0x10000 was not being written as 0x0000 in the PRDs. Fixed. (1) The DEV_IRQ interrupt cause bit happens spuriously during EDMA operation, and was not being ignored by the driver. This led to various "drive busy" errors being reported, with associated unpredictable behaviour. Fixed. (2) If a SATA or PCI interrupt was received with no outstanding command, the interrupt handler still attempted to invoke ata_qc_complete(), triggering assert()/BUG_ON() behaviour elsewhere in libata. Fixed. The driver still has issues with confusion after error-recovery, but should now be reliable in the absence of drive errors. I will be looking more into the error-handling bugs next. Signed-Off-By: Mark Lord Signed-off-by: Jeff Garzik --- drivers/scsi/sata_mv.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 2770005324b4..33e387354388 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -915,7 +915,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); - pp->sg_tbl[i].flags_size = cpu_to_le32(len); + pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff); sg_len -= len; addr += len; @@ -1187,7 +1187,6 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, { void __iomem *mmio = host_set->mmio_base; void __iomem *hc_mmio = mv_hc_base(mmio, hc); - struct ata_port *ap; struct ata_queued_cmd *qc; u32 hc_irq_cause; int shift, port, port0, hard_port, handled; @@ -1210,25 +1209,31 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, hc,relevant,hc_irq_cause); for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { - ap = host_set->ports[port]; + struct ata_port *ap = host_set->ports[port]; + struct mv_port_priv *pp = ap->private_data; hard_port = port & MV_PORT_MASK; /* range 0-3 */ handled = 0; /* ensure ata_status is set if handled++ */ - if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { - /* new CRPB on the queue; just one at a time until NCQ - */ - ata_status = mv_get_crpb_status(ap); - handled++; - } else if ((DEV_IRQ << hard_port) & hc_irq_cause) { - /* received ATA IRQ; read the status reg to clear INTRQ - */ - ata_status = readb((void __iomem *) + /* Note that DEV_IRQ might happen spuriously during EDMA, + * and should be ignored in such cases. We could mask it, + * but it's pretty rare and may not be worth the overhead. + */ + if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { + /* EDMA: check for response queue interrupt */ + if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { + ata_status = mv_get_crpb_status(ap); + handled = 1; + } + } else { + /* PIO: check for device (drive) interrupt */ + if ((DEV_IRQ << hard_port) & hc_irq_cause) { + ata_status = readb((void __iomem *) ap->ioaddr.status_addr); - handled++; + handled = 1; + } } - if (ap && - (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) + if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) continue; err_mask = ac_err_mask(ata_status); @@ -1240,12 +1245,12 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, if ((PORT0_ERR << shift) & relevant) { mv_err_intr(ap); err_mask |= AC_ERR_OTHER; - handled++; + handled = 1; } - if (handled && ap) { + if (handled) { qc = ata_qc_from_tag(ap, ap->active_tag); - if (NULL != qc) { + if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) { VPRINTK("port %u IRQ found for qc, " "ata_status 0x%x\n", port,ata_status); /* mark qc status appropriately */ -- cgit v1.2.3-59-g8ed1b From fa9656bbd9af5b95adc43eaa0a143992346378cb Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 28 Mar 2006 16:39:07 -0800 Subject: IB/mad: include GID/class when matching receives Received responses are currently matched against sent requests based on TID only. According to the spec, responses should match based on the combination of TID, management class, and requester LID/GID. Without the additional qualification, an agent that is responding to two requests, both of which have the same TID, can match RMPP ACKs with the incorrect transaction. This problem can occur on the SM node when responding to SA queries. Signed-off-by: Jack Morgenstein Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/mad.c | 58 ++++++++++++++++++++++++++++++++++---- drivers/infiniband/core/mad_priv.h | 3 +- drivers/infiniband/core/mad_rmpp.c | 35 +++++++++-------------- 3 files changed, 67 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index f7854b65fd55..d4d07012a5ca 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -1618,14 +1618,59 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv, (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); } +static inline int rcv_has_same_class(struct ib_mad_send_wr_private *wr, + struct ib_mad_recv_wc *rwc) +{ + return ((struct ib_mad *)(wr->send_buf.mad))->mad_hdr.mgmt_class == + rwc->recv_buf.mad->mad_hdr.mgmt_class; +} + +static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr, + struct ib_mad_recv_wc *rwc ) +{ + struct ib_ah_attr attr; + u8 send_resp, rcv_resp; + + send_resp = ((struct ib_mad *)(wr->send_buf.mad))-> + mad_hdr.method & IB_MGMT_METHOD_RESP; + rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP; + + if (!send_resp && rcv_resp) + /* is request/response. GID/LIDs are both local (same). */ + return 1; + + if (send_resp == rcv_resp) + /* both requests, or both responses. GIDs different */ + return 0; + + if (ib_query_ah(wr->send_buf.ah, &attr)) + /* Assume not equal, to avoid false positives. */ + return 0; + + if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH)) + return attr.dlid == rwc->wc->slid; + else if ((attr.ah_flags & IB_AH_GRH) && + (rwc->wc->wc_flags & IB_WC_GRH)) + return memcmp(attr.grh.dgid.raw, + rwc->recv_buf.grh->sgid.raw, 16) == 0; + else + /* one has GID, other does not. Assume different */ + return 0; +} struct ib_mad_send_wr_private* -ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid) +ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc) { struct ib_mad_send_wr_private *mad_send_wr; + struct ib_mad *mad; + + mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad; list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list, agent_list) { - if (mad_send_wr->tid == tid) + if ((mad_send_wr->tid == mad->mad_hdr.tid) && + rcv_has_same_class(mad_send_wr, mad_recv_wc) && + rcv_has_same_gid(mad_send_wr, mad_recv_wc)) return mad_send_wr; } @@ -1636,7 +1681,10 @@ ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid) list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, agent_list) { if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) && - mad_send_wr->tid == tid && mad_send_wr->timeout) { + mad_send_wr->tid == mad->mad_hdr.tid && + mad_send_wr->timeout && + rcv_has_same_class(mad_send_wr, mad_recv_wc) && + rcv_has_same_gid(mad_send_wr, mad_recv_wc)) { /* Verify request has not been canceled */ return (mad_send_wr->status == IB_WC_SUCCESS) ? mad_send_wr : NULL; @@ -1661,7 +1709,6 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wc mad_send_wc; unsigned long flags; - __be64 tid; INIT_LIST_HEAD(&mad_recv_wc->rmpp_list); list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); @@ -1677,9 +1724,8 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, /* Complete corresponding request */ if (response_mad(mad_recv_wc->recv_buf.mad)) { - tid = mad_recv_wc->recv_buf.mad->mad_hdr.tid; spin_lock_irqsave(&mad_agent_priv->lock, flags); - mad_send_wr = ib_find_send_mad(mad_agent_priv, tid); + mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); if (!mad_send_wr) { spin_unlock_irqrestore(&mad_agent_priv->lock, flags); ib_free_recv_mad(mad_recv_wc); diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index a7125d4b5ccf..6c9c133d71ef 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h @@ -216,7 +216,8 @@ extern kmem_cache_t *ib_mad_cache; int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr); struct ib_mad_send_wr_private * -ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid); +ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc); void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr, struct ib_mad_send_wc *mad_send_wc); diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index bacfdd5bddad..a6405079c285 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -562,15 +562,15 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) return ib_send_mad(mad_send_wr); } -static void abort_send(struct ib_mad_agent_private *agent, __be64 tid, - u8 rmpp_status) +static void abort_send(struct ib_mad_agent_private *agent, + struct ib_mad_recv_wc *mad_recv_wc, u8 rmpp_status) { struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wc wc; unsigned long flags; spin_lock_irqsave(&agent->lock, flags); - mad_send_wr = ib_find_send_mad(agent, tid); + mad_send_wr = ib_find_send_mad(agent, mad_recv_wc); if (!mad_send_wr) goto out; /* Unmatched send */ @@ -612,8 +612,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; if (rmpp_mad->rmpp_hdr.rmpp_status) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BAD_STATUS); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); return; } @@ -621,14 +620,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num); newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); if (newwin < seg_num) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_W2S); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); return; } spin_lock_irqsave(&agent->lock, flags); - mad_send_wr = ib_find_send_mad(agent, rmpp_mad->mad_hdr.tid); + mad_send_wr = ib_find_send_mad(agent, mad_recv_wc); if (!mad_send_wr) goto out; /* Unmatched ACK */ @@ -639,8 +637,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, if (seg_num > mad_send_wr->send_buf.seg_count || seg_num > mad_send_wr->newwin) { spin_unlock_irqrestore(&agent->lock, flags); - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_S2B); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); return; } @@ -728,12 +725,10 @@ static void process_rmpp_stop(struct ib_mad_agent_private *agent, rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BAD_STATUS); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); } else - abort_send(agent, rmpp_mad->mad_hdr.tid, - rmpp_mad->rmpp_hdr.rmpp_status); + abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status); } static void process_rmpp_abort(struct ib_mad_agent_private *agent, @@ -745,12 +740,10 @@ static void process_rmpp_abort(struct ib_mad_agent_private *agent, if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN || rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BAD_STATUS); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); } else - abort_send(agent, rmpp_mad->mad_hdr.tid, - rmpp_mad->rmpp_hdr.rmpp_status); + abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status); } struct ib_mad_recv_wc * @@ -764,8 +757,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent, return mad_recv_wc; if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_UNV); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); goto out; } @@ -783,8 +775,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent, process_rmpp_abort(agent, mad_recv_wc); break; default: - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BADT); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); break; } -- cgit v1.2.3-59-g8ed1b From 618a3c03fcfdf1ac4543247c8ddfb0c9d775ff33 Mon Sep 17 00:00:00 2001 From: Hal Rosenstock Date: Tue, 28 Mar 2006 16:40:04 -0800 Subject: IB/mad: RMPP support for additional classes Add RMPP support for additional management classes that support it. Also, validate RMPP is consistent with management class specified. Signed-off-by: Hal Rosenstock Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/mad.c | 54 ++++++++++++++++++++++++++++++++++---- drivers/infiniband/core/mad_rmpp.c | 19 +++----------- drivers/infiniband/core/user_mad.c | 30 +++++---------------- include/rdma/ib_mad.h | 27 ++++++++++++++++++- 4 files changed, 85 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index d4d07012a5ca..ba54c856b0e5 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -227,6 +227,14 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, if (!is_vendor_oui(mad_reg_req->oui)) goto error1; } + /* Make sure class supplied is consistent with RMPP */ + if (ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) { + if (!rmpp_version) + goto error1; + } else { + if (rmpp_version) + goto error1; + } /* Make sure class supplied is consistent with QP type */ if (qp_type == IB_QPT_SMI) { if ((mad_reg_req->mgmt_class != @@ -890,6 +898,35 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, } EXPORT_SYMBOL(ib_create_send_mad); +int ib_get_mad_data_offset(u8 mgmt_class) +{ + if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) + return IB_MGMT_SA_HDR; + else if ((mgmt_class == IB_MGMT_CLASS_DEVICE_MGMT) || + (mgmt_class == IB_MGMT_CLASS_DEVICE_ADM) || + (mgmt_class == IB_MGMT_CLASS_BIS)) + return IB_MGMT_DEVICE_HDR; + else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && + (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) + return IB_MGMT_VENDOR_HDR; + else + return IB_MGMT_MAD_HDR; +} +EXPORT_SYMBOL(ib_get_mad_data_offset); + +int ib_is_mad_class_rmpp(u8 mgmt_class) +{ + if ((mgmt_class == IB_MGMT_CLASS_SUBN_ADM) || + (mgmt_class == IB_MGMT_CLASS_DEVICE_MGMT) || + (mgmt_class == IB_MGMT_CLASS_DEVICE_ADM) || + (mgmt_class == IB_MGMT_CLASS_BIS) || + ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && + (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))) + return 1; + return 0; +} +EXPORT_SYMBOL(ib_is_mad_class_rmpp); + void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num) { struct ib_mad_send_wr_private *mad_send_wr; @@ -1022,6 +1059,13 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf, goto error; } + if (!ib_is_mad_class_rmpp(((struct ib_mad_hdr *) send_buf->mad)->mgmt_class)) { + if (mad_agent_priv->agent.rmpp_version) { + ret = -EINVAL; + goto error; + } + } + /* * Save pointer to next work request to post in case the * current one completes, and the user modifies the work @@ -2454,11 +2498,11 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, } } sg_list.addr = dma_map_single(qp_info->port_priv-> - device->dma_device, - &mad_priv->grh, - sizeof *mad_priv - - sizeof mad_priv->header, - DMA_FROM_DEVICE); + device->dma_device, + &mad_priv->grh, + sizeof *mad_priv - + sizeof mad_priv->header, + DMA_FROM_DEVICE); pci_unmap_addr_set(&mad_priv->header, mapping, sg_list.addr); recv_wr.wr_id = (unsigned long)&mad_priv->header.mad_list; mad_priv->header.mad_list.mad_queue = recv_queue; diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index a6405079c285..dfd4e588ce03 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Intel Inc. All rights reserved. - * Copyright (c) 2005 Voltaire, Inc. All rights reserved. + * Copyright (c) 2005-2006 Voltaire, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -100,17 +100,6 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent) } } -static int data_offset(u8 mgmt_class) -{ - if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) - return IB_MGMT_SA_HDR; - else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && - (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) - return IB_MGMT_VENDOR_HDR; - else - return IB_MGMT_RMPP_HDR; -} - static void format_ack(struct ib_mad_send_buf *msg, struct ib_rmpp_mad *data, struct mad_rmpp_recv *rmpp_recv) @@ -137,7 +126,7 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv, struct ib_mad_send_buf *msg; int ret, hdr_len; - hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); + hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, recv_wc->wc->pkey_index, 1, hdr_len, 0, GFP_KERNEL); @@ -163,7 +152,7 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent, if (IS_ERR(ah)) return (void *) ah; - hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); + hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); msg = ib_create_send_mad(agent, recv_wc->wc->src_qp, recv_wc->wc->pkey_index, 1, hdr_len, 0, GFP_KERNEL); @@ -408,7 +397,7 @@ static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv) rmpp_mad = (struct ib_rmpp_mad *)rmpp_recv->cur_seg_buf->mad; - hdr_size = data_offset(rmpp_mad->mad_hdr.mgmt_class); + hdr_size = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); data_size = sizeof(struct ib_rmpp_mad) - hdr_size; pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); if (pad > IB_MGMT_RMPP_DATA || pad < 0) diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index fb6cd42601f9..afe70a549c2f 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -177,17 +177,6 @@ static int queue_packet(struct ib_umad_file *file, return ret; } -static int data_offset(u8 mgmt_class) -{ - if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) - return IB_MGMT_SA_HDR; - else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && - (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) - return IB_MGMT_VENDOR_HDR; - else - return IB_MGMT_RMPP_HDR; -} - static void send_handler(struct ib_mad_agent *agent, struct ib_mad_send_wc *send_wc) { @@ -283,7 +272,7 @@ static ssize_t copy_recv_mad(char __user *buf, struct ib_umad_packet *packet, */ return -ENOSPC; } - offset = data_offset(recv_buf->mad->mad_hdr.mgmt_class); + offset = ib_get_mad_data_offset(recv_buf->mad->mad_hdr.mgmt_class); max_seg_payload = sizeof (struct ib_mad) - offset; for (left = packet->length - seg_payload, buf += seg_payload; @@ -441,21 +430,14 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, } rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data; - if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { - hdr_len = IB_MGMT_SA_HDR; - copy_offset = IB_MGMT_RMPP_HDR; - rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & - IB_MGMT_RMPP_FLAG_ACTIVE; - } else if (rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START && - rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END) { - hdr_len = IB_MGMT_VENDOR_HDR; + hdr_len = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); + if (!ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)) { + copy_offset = IB_MGMT_MAD_HDR; + rmpp_active = 0; + } else { copy_offset = IB_MGMT_RMPP_HDR; rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE; - } else { - hdr_len = IB_MGMT_MAD_HDR; - copy_offset = IB_MGMT_MAD_HDR; - rmpp_active = 0; } data_len = count - sizeof (struct ib_user_mad) - hdr_len; diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h index 51ab8eddb295..5ff77558013b 100644 --- a/include/rdma/ib_mad.h +++ b/include/rdma/ib_mad.h @@ -3,7 +3,7 @@ * Copyright (c) 2004 Infinicon Corporation. All rights reserved. * Copyright (c) 2004 Intel Corporation. All rights reserved. * Copyright (c) 2004 Topspin Corporation. All rights reserved. - * Copyright (c) 2004 Voltaire Corporation. All rights reserved. + * Copyright (c) 2004-2006 Voltaire Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -55,6 +55,10 @@ #define IB_MGMT_CLASS_DEVICE_MGMT 0x06 #define IB_MGMT_CLASS_CM 0x07 #define IB_MGMT_CLASS_SNMP 0x08 +#define IB_MGMT_CLASS_DEVICE_ADM 0x10 +#define IB_MGMT_CLASS_BOOT_MGMT 0x11 +#define IB_MGMT_CLASS_BIS 0x12 +#define IB_MGMT_CLASS_CONG_MGMT 0x21 #define IB_MGMT_CLASS_VENDOR_RANGE2_START 0x30 #define IB_MGMT_CLASS_VENDOR_RANGE2_END 0x4F @@ -117,6 +121,8 @@ enum { IB_MGMT_VENDOR_DATA = 216, IB_MGMT_SA_HDR = 56, IB_MGMT_SA_DATA = 200, + IB_MGMT_DEVICE_HDR = 64, + IB_MGMT_DEVICE_DATA = 192, }; struct ib_mad_hdr { @@ -602,6 +608,25 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, int hdr_len, int data_len, gfp_t gfp_mask); +/** + * ib_is_mad_class_rmpp - returns whether given management class + * supports RMPP. + * @mgmt_class: management class + * + * This routine returns whether the management class supports RMPP. + */ +int ib_is_mad_class_rmpp(u8 mgmt_class); + +/** + * ib_get_mad_data_offset - returns the data offset for a given + * management class. + * @mgmt_class: management class + * + * This routine returns the data offset in the MAD for the management + * class requested. + */ +int ib_get_mad_data_offset(u8 mgmt_class); + /** * ib_get_rmpp_segment - returns the data buffer for a given RMPP segment. * @send_buf: Previously allocated send data buffer. -- cgit v1.2.3-59-g8ed1b From a81dd18eb974cc34634c53a6447b2799ec0c3158 Mon Sep 17 00:00:00 2001 From: Thibaut VARENE Date: Fri, 3 Feb 2006 18:06:30 -0700 Subject: [PARISC] Clarify pdc_stable license terms pdc_stable.c is explicitly licensed under GPL version 2. Signed-off-by: Thibaut VARENE Signed-off-by: Kyle McMartin --- arch/parisc/kernel/pdc_chassis.c | 5 ++--- drivers/parisc/pdc_stable.c | 5 ++--- include/asm-parisc/pdc_chassis.h | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c index 0cea6958f427..a45e2e2ffd9f 100644 --- a/arch/parisc/kernel/pdc_chassis.c +++ b/arch/parisc/kernel/pdc_chassis.c @@ -5,9 +5,8 @@ * Copyright (C) 2002-2004 Thibaut VARENE * * 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. + * 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 diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index a28e17898fbd..4e53be9c03ab 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -4,9 +4,8 @@ * Copyright (C) 2005-2006 Thibaut VARENE * * 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. + * 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 diff --git a/include/asm-parisc/pdc_chassis.h b/include/asm-parisc/pdc_chassis.h index adac9ac2743f..a609273dc6bf 100644 --- a/include/asm-parisc/pdc_chassis.h +++ b/include/asm-parisc/pdc_chassis.h @@ -6,9 +6,8 @@ * * * 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. + * 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 -- cgit v1.2.3-59-g8ed1b From 5076c15862644edb91d2e3436b2fa3e07b28385d Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 27 Mar 2006 12:52:15 -0700 Subject: [PARISC] I/O-Space must be ioremap_nocache()'d Addresses in F-space must be accessed uncached on most parisc machines. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/perf.c | 2 +- drivers/input/serio/gscps2.c | 4 ++-- drivers/parisc/ccio-dma.c | 2 +- drivers/parisc/dino.c | 5 +++-- drivers/parisc/eisa.c | 2 +- drivers/parisc/iosapic.c | 2 +- drivers/parisc/lba_pci.c | 8 ++++---- drivers/parisc/sba_iommu.c | 6 +++--- drivers/parisc/superio.c | 48 ++++++++++++++++++-------------------------- drivers/scsi/lasi700.c | 2 +- drivers/scsi/zalon.c | 2 +- drivers/serial/8250_gsc.c | 15 +++++++------- drivers/serial/mux.c | 4 ++-- 13 files changed, 48 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index 53f861c82f93..ac8ee205c351 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -805,7 +805,7 @@ static int perf_write_image(uint64_t *memaddr) return -1; } - runway = ioremap(cpu_device->hpa.start, 4096); + runway = ioremap_nocache(cpu_device->hpa.start, 4096); /* Merge intrigue bits into Runway STATUS 0 */ tmp64 = __raw_readq(runway + RUNWAY_STATUS) & 0xffecfffffffffffful; diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index a7b0de0f92b2..c0b1e4becad3 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -1,7 +1,7 @@ /* * drivers/input/serio/gscps2.c * - * Copyright (c) 2004 Helge Deller + * Copyright (c) 2004-2006 Helge Deller * Copyright (c) 2002 Laurent Canet * Copyright (c) 2002 Thibaut Varene * @@ -354,7 +354,7 @@ static int __init gscps2_probe(struct parisc_device *dev) memset(serio, 0, sizeof(struct serio)); ps2port->port = serio; ps2port->padev = dev; - ps2port->addr = ioremap(hpa, GSC_STATUS + 4); + ps2port->addr = ioremap_nocache(hpa, GSC_STATUS + 4); spin_lock_init(&ps2port->lock); gscps2_reset(ps2port); diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 93f8a8fa8890..a5d826237b26 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -1560,7 +1560,7 @@ static int ccio_probe(struct parisc_device *dev) *ioc_p = ioc; ioc->hw_path = dev->hw_path; - ioc->ioc_regs = ioremap(dev->hpa.start, 4096); + ioc->ioc_regs = ioremap_nocache(dev->hpa.start, 4096); ccio_ioc_init(ioc); ccio_init_resources(ioc); hppa_dma_ops = &ccio_ops; diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 3d1a7f98c676..6e8ed0c81a6c 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -5,6 +5,7 @@ ** (c) Copyright 1999 SuSE GmbH ** (c) Copyright 1999,2000 Hewlett-Packard Company ** (c) Copyright 2000 Grant Grundler +** (c) Copyright 2006 Helge Deller ** ** 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 @@ -785,7 +786,7 @@ dino_bridge_init(struct dino_device *dino_dev, const char *name) if((io_addr & (1 << i)) == 0) continue; - start = (unsigned long)(signed int)(0xf0000000 | (i << 23)); + start = F_EXTEND(0xf0000000UL) | (i << 23); end = start + 8 * 1024 * 1024 - 1; DBG("DINO RANGE %d is at 0x%lx-0x%lx\n", count, @@ -996,7 +997,7 @@ static int __init dino_probe(struct parisc_device *dev) } dino_dev->hba.dev = dev; - dino_dev->hba.base_addr = ioremap(hpa, 4096); + dino_dev->hba.base_addr = ioremap_nocache(hpa, 4096); dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */ spin_lock_init(&dino_dev->dinosaur_pen); dino_dev->hba.iommu = ccio_get_iommu(dev); diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index 3d94d86c1c9f..9d3bd15bf53b 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c @@ -366,7 +366,7 @@ static int __devinit eisa_probe(struct parisc_device *dev) eisa_dev.eeprom_addr = MIRAGE_EEPROM_BASE_ADDR; } } - eisa_eeprom_addr = ioremap(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH); + eisa_eeprom_addr = ioremap_nocache(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH); result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space); init_eisa_pic(); diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 8d7a36392eb8..7a458d5bc751 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -879,7 +879,7 @@ void *iosapic_register(unsigned long hpa) return NULL; } - isi->addr = ioremap(hpa, 4096); + isi->addr = ioremap_nocache(hpa, 4096); isi->isi_hpa = hpa; isi->isi_version = iosapic_rd_version(isi); isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index e8a2a4a852f5..3fe4a77fa16a 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1213,7 +1213,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ** Postable I/O port space is per PCI host adapter. ** base of 64MB PIOP region */ - lba_dev->iop_base = ioremap(p->start, 64 * 1024 * 1024); + lba_dev->iop_base = ioremap_nocache(p->start, 64 * 1024 * 1024); sprintf(lba_dev->hba.io_name, "PCI%02lx Ports", lba_dev->hba.bus_num.start); @@ -1525,7 +1525,7 @@ lba_driver_probe(struct parisc_device *dev) u32 func_class; void *tmp_obj; char *version; - void __iomem *addr = ioremap(dev->hpa.start, 4096); + void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096); /* Read HW Rev First */ func_class = READ_REG32(addr + LBA_FCLASS); @@ -1619,7 +1619,7 @@ lba_driver_probe(struct parisc_device *dev) } else { if (!astro_iop_base) { /* Sprockets PDC uses NPIOP region */ - astro_iop_base = ioremap(LBA_PORT_BASE, 64 * 1024); + astro_iop_base = ioremap_nocache(LBA_PORT_BASE, 64 * 1024); pci_port = &lba_astro_port_ops; } @@ -1700,7 +1700,7 @@ void __init lba_init(void) */ void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask) { - void __iomem * base_addr = ioremap(lba->hpa.start, 4096); + void __iomem * base_addr = ioremap_nocache(lba->hpa.start, 4096); imask <<= 2; /* adjust for hints - 2 more bits */ diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 0821747e44cf..42b32ff2fca6 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1642,9 +1642,9 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** **************************************************************************/ -static void __iomem *ioc_remap(struct sba_device *sba_dev, int offset) +static void __iomem *ioc_remap(struct sba_device *sba_dev, unsigned int offset) { - return ioremap(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE); + return ioremap_nocache(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE); } static void sba_hw_init(struct sba_device *sba_dev) @@ -2040,7 +2040,7 @@ sba_driver_callback(struct parisc_device *dev) u32 func_class; int i; char *version; - void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE); + void __iomem *sba_addr = ioremap_nocache(dev->hpa.start, SBA_FUNC_SIZE); struct proc_dir_entry *info_entry, *bitmap_entry, *root; sba_dump_ranges(sba_addr); diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index ad6d3b28a3a6..719b863bc20e 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -12,6 +12,7 @@ * (C) Copyright 2001 John Marvin * (C) Copyright 2003 Grant Grundler * (C) Copyright 2005 Kyle McMartin + * (C) Copyright 2006 Helge Deller * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -388,43 +389,34 @@ int superio_fixup_irq(struct pci_dev *pcidev) return local_irq; } -static struct uart_port serial[] = { - { - .iotype = UPIO_PORT, - .line = 0, - .type = PORT_16550A, - .uartclk = 115200*16, - .fifosize = 16, - }, - { - .iotype = UPIO_PORT, - .line = 1, - .type = PORT_16550A, - .uartclk = 115200*16, - .fifosize = 16, - } -}; - static void __devinit superio_serial_init(void) { #ifdef CONFIG_SERIAL_8250 int retval; - - serial[0].iobase = sio_dev.sp1_base; - serial[0].irq = SP1_IRQ; - spin_lock_init(&serial[0].lock); - - retval = early_serial_setup(&serial[0]); + struct uart_port serial_port; + + memset(&serial_port, 0, sizeof(serial_port)); + serial_port.iotype = UPIO_PORT; + serial_port.type = PORT_16550A; + serial_port.uartclk = 115200*16; + serial_port.fifosize = 16; + spin_lock_init(&serial_port.lock); + + /* serial port #1 */ + serial_port.iobase = sio_dev.sp1_base; + serial_port.irq = SP1_IRQ; + serial_port.line = 0; + retval = early_serial_setup(&serial_port); if (retval < 0) { printk(KERN_WARNING PFX "Register Serial #0 failed.\n"); return; } - serial[1].iobase = sio_dev.sp2_base; - serial[1].irq = SP2_IRQ; - spin_lock_init(&serial[1].lock); - retval = early_serial_setup(&serial[1]); - + /* serial port #2 */ + serial_port.iobase = sio_dev.sp2_base; + serial_port.irq = SP2_IRQ; + serial_port.line = 1; + retval = early_serial_setup(&serial_port); if (retval < 0) printk(KERN_WARNING PFX "Register Serial #1 failed.\n"); #endif /* CONFIG_SERIAL_8250 */ diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 459a4daebece..eb7bd310cc82 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -112,7 +112,7 @@ lasi700_probe(struct parisc_device *dev) hostdata->dev = &dev->dev; dma_set_mask(&dev->dev, DMA_32BIT_MASK); - hostdata->base = ioremap(base, 0x100); + hostdata->base = ioremap_nocache(base, 0x100); hostdata->differential = 0; if (dev->id.sversion == LASI_700_SVERSION) { diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index b131432c677d..a6cfbb3b361c 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -88,7 +88,7 @@ zalon_probe(struct parisc_device *dev) struct gsc_irq gsc_irq; u32 zalon_vers; int error = -ENODEV; - void __iomem *zalon = ioremap(dev->hpa.start, 4096); + void __iomem *zalon = ioremap_nocache(dev->hpa.start, 4096); void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET; static int unit = 0; struct Scsi_Host *host; diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c index 8b4947933d9b..913c71cc0569 100644 --- a/drivers/serial/8250_gsc.c +++ b/drivers/serial/8250_gsc.c @@ -52,13 +52,14 @@ serial_init_chip(struct parisc_device *dev) address += 0x800; } - memset(&port, 0, sizeof(struct uart_port)); - port.mapbase = address; - port.irq = dev->irq; - port.iotype = UPIO_MEM; - port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; - port.uartclk = LASI_BASE_BAUD * 16; - port.dev = &dev->dev; + memset(&port, 0, sizeof(port)); + port.iotype = UPIO_MEM; + port.uartclk = LASI_BASE_BAUD * 16; + port.mapbase = address; + port.membase = ioremap_nocache(address, 16); + port.irq = dev->irq; + port.flags = UPF_BOOT_AUTOCONF; + port.dev = &dev->dev; err = serial8250_register_port(&port); if (err < 0) { diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 868eaf4a1a68..64c0e89124c9 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -51,7 +51,7 @@ #define MUX_BREAK(status) ((status & 0xF000) == 0x2000) #define MUX_NR 256 -static unsigned int port_cnt = 0; +static unsigned int port_cnt __read_mostly; static struct uart_port mux_ports[MUX_NR]; static struct uart_driver mux_driver = { @@ -461,7 +461,7 @@ static int __init mux_probe(struct parisc_device *dev) port->iobase = 0; port->mapbase = dev->hpa.start + MUX_OFFSET + (i * MUX_LINE_OFFSET); - port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); + port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET); port->iotype = UPIO_MEM; port->type = PORT_MUX; port->irq = NO_IRQ; -- cgit v1.2.3-59-g8ed1b From 857600c77161fd36e30cd6bcca9a0a8676036323 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 22 Mar 2006 15:19:46 -0700 Subject: [PARISC] Fix stifb with IOREMAP and a 64-bit kernel Kill various warnings when built using ioremap. Remove stifb_{read,write} functions, which are now obsolete (and stack abusers!) Disable stifb mmap() functionality on a 64-bit kernel, it will crash the machine. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- drivers/video/console/sticore.c | 18 +------- drivers/video/sticore.h | 37 +++++------------ drivers/video/stifb.c | 91 +++-------------------------------------- 3 files changed, 19 insertions(+), 127 deletions(-) (limited to 'drivers') diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index 0339f5640a78..d6041e781aca 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -373,7 +373,7 @@ sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request) glob_cfg->save_addr)); /* dump extended cfg */ - cfg = PTR_STI(glob_cfg->ext_ptr); + cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr); DPRINTK(( KERN_INFO "monitor %d\n" "in friendly mode: %d\n" @@ -453,25 +453,11 @@ sti_init_glob_cfg(struct sti_struct *sti, sti->regions_phys[i] = REGION_OFFSET_TO_PHYS(sti->regions[i], newhpa); - /* remap virtually */ - /* FIXME: add BTLB support if btlb==1 */ len = sti->regions[i].region_desc.length * 4096; - -/* XXX: Enabling IOREMAP debugging causes a crash, so we must be passing - * a virtual address to something expecting a physical address that doesn't - * go through a readX macro */ -#if 0 - if (len) - glob_cfg->region_ptrs[i] = (unsigned long) ( - sti->regions[i].region_desc.cache ? - ioremap(sti->regions_phys[i], len) : - ioremap_nocache(sti->regions_phys[i], len) ); -#else if (len) glob_cfg->region_ptrs[i] = sti->regions_phys[i]; -#endif - DPRINTK(("region #%d: phys %08lx, virt %08x, len=%lukB, " + DPRINTK(("region #%d: phys %08lx, region_ptr %08x, len=%lukB, " "btlb=%d, sysonly=%d, cache=%d, last=%d\n", i, sti->regions_phys[i], glob_cfg->region_ptrs[i], len/1024, diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h index dc93336af557..1a9a60c74be3 100644 --- a/drivers/video/sticore.h +++ b/drivers/video/sticore.h @@ -34,36 +34,20 @@ * for them to fix it and steal their solution. prumpf */ -#define STI_WAIT 1 - -#include /* for USE_HPPA_IOREMAP */ - -#if USE_HPPA_IOREMAP +#include -#define STI_PTR(p) (p) -#define PTR_STI(p) (p) -static inline int STI_CALL( unsigned long func, - void *flags, void *inptr, void *outptr, void *glob_cfg ) -{ - int (*f)(void *,void *,void *,void *); - f = (void*)func; - return f(flags, inptr, outptr, glob_cfg); -} - -#else /* !USE_HPPA_IOREMAP */ +#define STI_WAIT 1 #define STI_PTR(p) ( virt_to_phys(p) ) -#define PTR_STI(p) ( phys_to_virt((long)p) ) -#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \ - ({ \ - pdc_sti_call( func, (unsigned long)STI_PTR(flags), \ - (unsigned long)STI_PTR(inptr), \ - (unsigned long)STI_PTR(outptr), \ - (unsigned long)STI_PTR(glob_cfg)); \ +#define PTR_STI(p) ( phys_to_virt((unsigned long)p) ) +#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \ + ({ \ + pdc_sti_call( func, STI_PTR(flags), \ + STI_PTR(inptr), \ + STI_PTR(outptr), \ + STI_PTR(glob_cfg)); \ }) -#endif /* USE_HPPA_IOREMAP */ - #define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x) #define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y) @@ -352,8 +336,9 @@ struct sti_struct { struct sti_conf_outptr outptr; /* configuration */ struct sti_conf_outptr_ext outptr_ext; - /* PCI data structures (pg. 17ff from sti.pdf) */ struct pci_dev *pd; + + /* PCI data structures (pg. 17ff from sti.pdf) */ u8 rm_entry[16]; /* pci region mapper array == pci config space offset */ /* pointer to the fb_info where this STI device is used */ diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 56d71d6e9a72..8d5f35676f9a 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -3,7 +3,7 @@ * Low level Frame buffer driver for HP workstations with * STI (standard text interface) video firmware. * - * Copyright (C) 2001-2005 Helge Deller + * Copyright (C) 2001-2006 Helge Deller * Portions Copyright (C) 2001 Thomas Bogendoerfer * * Based on: @@ -514,7 +514,7 @@ rattlerSetupPlanes(struct stifb_info *fb) SETUP_HW(fb); WRITE_BYTE(1, fb, REG_16b1); - fb_memset(fb->info.fix.smem_start, 0xff, + fb_memset((void*)fb->info.fix.smem_start, 0xff, fb->info.var.yres*fb->info.fix.line_length); CRX24_SET_OVLY_MASK(fb); @@ -908,83 +908,6 @@ SETUP_HCRX(struct stifb_info *fb) /* ------------------- driver specific functions --------------------------- */ -#define TMPBUFLEN 2048 - -static ssize_t -stifb_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - unsigned long p = *ppos; - struct inode *inode = file->f_dentry->d_inode; - int fbidx = iminor(inode); - struct fb_info *info = registered_fb[fbidx]; - char tmpbuf[TMPBUFLEN]; - - if (!info || ! info->screen_base) - return -ENODEV; - - if (p >= info->fix.smem_len) - return 0; - if (count >= info->fix.smem_len) - count = info->fix.smem_len; - if (count + p > info->fix.smem_len) - count = info->fix.smem_len - p; - if (count > sizeof(tmpbuf)) - count = sizeof(tmpbuf); - if (count) { - char *base_addr; - - base_addr = info->screen_base; - memcpy_fromio(&tmpbuf, base_addr+p, count); - count -= copy_to_user(buf, &tmpbuf, count); - if (!count) - return -EFAULT; - *ppos += count; - } - return count; -} - -static ssize_t -stifb_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - struct inode *inode = file->f_dentry->d_inode; - int fbidx = iminor(inode); - struct fb_info *info = registered_fb[fbidx]; - unsigned long p = *ppos; - size_t c; - int err; - char tmpbuf[TMPBUFLEN]; - - if (!info || !info->screen_base) - return -ENODEV; - - if (p > info->fix.smem_len) - return -ENOSPC; - if (count >= info->fix.smem_len) - count = info->fix.smem_len; - err = 0; - if (count + p > info->fix.smem_len) { - count = info->fix.smem_len - p; - err = -ENOSPC; - } - - p += (unsigned long)info->screen_base; - c = count; - while (c) { - int len = c > sizeof(tmpbuf) ? sizeof(tmpbuf) : c; - err = -EFAULT; - if (copy_from_user(&tmpbuf, buf, len)) - break; - memcpy_toio(p, &tmpbuf, len); - c -= len; - p += len; - buf += len; - *ppos += len; - } - if (count-c) - return (count-c); - return err; -} - static int stifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) @@ -1137,8 +1060,6 @@ stifb_init_display(struct stifb_info *fb) static struct fb_ops stifb_ops = { .owner = THIS_MODULE, - .fb_read = stifb_read, - .fb_write = stifb_write, .fb_setcolreg = stifb_setcolreg, .fb_blank = stifb_blank, .fb_fillrect = cfb_fillrect, @@ -1162,7 +1083,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref) char *dev_name; int bpp, xres, yres; - fb = kmalloc(sizeof(*fb), GFP_ATOMIC); + fb = kzalloc(sizeof(*fb), GFP_ATOMIC); if (!fb) { printk(KERN_ERR "stifb: Could not allocate stifb structure\n"); return -ENODEV; @@ -1171,7 +1092,6 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref) info = &fb->info; /* set struct to a known state */ - memset(fb, 0, sizeof(*fb)); fix = &info->fix; var = &info->var; @@ -1234,7 +1154,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref) case S9000_ID_TOMCAT: /* Dual CRX, behaves else like a CRX */ /* FIXME: TomCat supports two heads: * fb.iobase = REGION_BASE(fb_info,3); - * fb.screen_base = (void*) REGION_BASE(fb_info,2); + * fb.screen_base = ioremap_nocache(REGION_BASE(fb_info,2),xxx); * for now we only support the left one ! */ xres = fb->ngle_rom.x_size_visible; yres = fb->ngle_rom.y_size_visible; @@ -1327,7 +1247,8 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref) strcpy(fix->id, "stifb"); info->fbops = &stifb_ops; - info->screen_base = (void*) REGION_BASE(fb,1); + info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len); + info->screen_size = fix->smem_len; info->flags = FBINFO_DEFAULT; info->pseudo_palette = &fb->pseudo_palette; -- cgit v1.2.3-59-g8ed1b From 102c8c76f787add0790406d5c47e03cb6f8765c2 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 26 Mar 2006 07:41:55 -0700 Subject: [PARISC] Convert HIL drivers to use input_allocate_device Convert HIL drivers to use input_allocate_device() - avoids crashes. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- drivers/input/keyboard/hil_kbd.c | 57 +++++++++++++------------ drivers/input/keyboard/hilkbd.c | 54 +++++++++++++----------- drivers/input/mouse/hil_ptr.c | 91 +++++++++++++++++++++------------------- 3 files changed, 109 insertions(+), 93 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 0a90962c38e7..99f8c5b4cd50 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -66,7 +66,7 @@ static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] = static char hil_language[][16] = { HIL_LOCALE_MAP }; struct hil_kbd { - struct input_dev dev; + struct input_dev *dev; struct serio *serio; /* Input buffer and index for packets from HIL bus. */ @@ -86,7 +86,7 @@ struct hil_kbd { /* Process a complete packet after transfer from the HIL */ static void hil_kbd_process_record(struct hil_kbd *kbd) { - struct input_dev *dev = &kbd->dev; + struct input_dev *dev = kbd->dev; hil_packet *data = kbd->data; hil_packet p; int idx, i, cnt; @@ -240,8 +240,9 @@ static void hil_kbd_disconnect(struct serio *serio) return; } - input_unregister_device(&kbd->dev); + input_unregister_device(kbd->dev); serio_close(serio); + input_free_device(kbd->dev); kfree(kbd); } @@ -251,16 +252,18 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) uint8_t did, *idd; int i; - kbd = kmalloc(sizeof(*kbd), GFP_KERNEL); + kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); if (!kbd) return -ENOMEM; - memset(kbd, 0, sizeof(struct hil_kbd)); + + kbd->dev = input_allocate_device(); + if (!kbd->dev) goto bail1; + kbd->dev->private = kbd; if (serio_open(serio, drv)) goto bail0; serio_set_drvdata(serio, kbd); kbd->serio = serio; - kbd->dev.private = kbd; init_MUTEX_LOCKED(&(kbd->sem)); @@ -302,38 +305,38 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); break; default: - goto bail1; + goto bail2; } if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n"); - goto bail1; + goto bail2; } - kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); - kbd->dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE; - kbd->dev.keycodesize = sizeof(hil_kbd_set1[0]); - kbd->dev.keycode = hil_kbd_set1; - kbd->dev.name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME; - kbd->dev.phys = "hpkbd/input0"; /* XXX */ + kbd->dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + kbd->dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); + kbd->dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; + kbd->dev->keycodesize = sizeof(hil_kbd_set1[0]); + kbd->dev->keycode = hil_kbd_set1; + kbd->dev->name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME; + kbd->dev->phys = "hpkbd/input0"; /* XXX */ - kbd->dev.id.bustype = BUS_HIL; - kbd->dev.id.vendor = PCI_VENDOR_ID_HP; - kbd->dev.id.product = 0x0001; /* TODO: get from kbd->rsc */ - kbd->dev.id.version = 0x0100; /* TODO: get from kbd->rsc */ - kbd->dev.dev = &serio->dev; + kbd->dev->id.bustype = BUS_HIL; + kbd->dev->id.vendor = PCI_VENDOR_ID_HP; + kbd->dev->id.product = 0x0001; /* TODO: get from kbd->rsc */ + kbd->dev->id.version = 0x0100; /* TODO: get from kbd->rsc */ + kbd->dev->dev = &serio->dev; for (i = 0; i < 128; i++) { - set_bit(hil_kbd_set1[i], kbd->dev.keybit); - set_bit(hil_kbd_set3[i], kbd->dev.keybit); + set_bit(hil_kbd_set1[i], kbd->dev->keybit); + set_bit(hil_kbd_set3[i], kbd->dev->keybit); } - clear_bit(0, kbd->dev.keybit); + clear_bit(0, kbd->dev->keybit); - input_register_device(&kbd->dev); + input_register_device(kbd->dev); printk(KERN_INFO "input: %s, ID: %d\n", - kbd->dev.name, did); + kbd->dev->name, did); serio->write(serio, 0); serio->write(serio, 0); @@ -343,8 +346,10 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) up(&(kbd->sem)); return 0; - bail1: + bail2: serio_close(serio); + bail1: + input_free_device(kbd->dev); bail0: kfree(kbd); serio_set_drvdata(serio, NULL); diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index e95bc052e32a..452c5f3e6129 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c @@ -3,7 +3,7 @@ * * Copyright (C) 1998 Philip Blundell * Copyright (C) 1999 Matthew Wilcox - * Copyright (C) 1999-2003 Helge Deller + * Copyright (C) 1999-2006 Helge Deller * * Very basic HP Human Interface Loop (HIL) driver. * This driver handles the keyboard on HP300 (m68k) and on some @@ -90,7 +90,7 @@ static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = /* HIL structure */ static struct { - struct input_dev dev; + struct input_dev *dev; unsigned int curdev; @@ -117,7 +117,7 @@ static void poll_finished(void) down = (hil_dev.data[1] & 1) == 0; scode = hil_dev.data[1] >> 1; key = hphilkeyb_keycode[scode]; - input_report_key(&hil_dev.dev, key, down); + input_report_key(hil_dev.dev, key, down); break; } hil_dev.curdev = 0; @@ -207,9 +207,14 @@ hil_keyb_init(void) unsigned int i, kbid; wait_queue_head_t hil_wait; - if (hil_dev.dev.id.bustype) { + if (hil_dev.dev) { return -ENODEV; /* already initialized */ } + + hil_dev.dev = input_allocate_device(); + if (!hil_dev.dev) + return -ENOMEM; + hil_dev.dev->private = &hil_dev; #if defined(CONFIG_HP300) if (!hwreg_present((void *)(HILBASE + HIL_DATA))) @@ -247,28 +252,26 @@ hil_keyb_init(void) c = 0; hil_do(HIL_WRITEKBDSADR, &c, 1); - init_input_dev(&hil_dev.dev); - for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) if (hphilkeyb_keycode[i] != KEY_RESERVED) - set_bit(hphilkeyb_keycode[i], hil_dev.dev.keybit); - - hil_dev.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - hil_dev.dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); - hil_dev.dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE; - hil_dev.dev.keycodesize = sizeof(hphilkeyb_keycode[0]); - hil_dev.dev.keycode = hphilkeyb_keycode; - hil_dev.dev.name = "HIL keyboard"; - hil_dev.dev.phys = "hpkbd/input0"; - - hil_dev.dev.id.bustype = BUS_HIL; - hil_dev.dev.id.vendor = PCI_VENDOR_ID_HP; - hil_dev.dev.id.product = 0x0001; - hil_dev.dev.id.version = 0x0010; - - input_register_device(&hil_dev.dev); + set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); + + hil_dev.dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + hil_dev.dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); + hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; + hil_dev.dev->keycodesize = sizeof(hphilkeyb_keycode[0]); + hil_dev.dev->keycode = hphilkeyb_keycode; + hil_dev.dev->name = "HIL keyboard"; + hil_dev.dev->phys = "hpkbd/input0"; + + hil_dev.dev->id.bustype = BUS_HIL; + hil_dev.dev->id.vendor = PCI_VENDOR_ID_HP; + hil_dev.dev->id.product = 0x0001; + hil_dev.dev->id.version = 0x0010; + + input_register_device(hil_dev.dev); printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", - hil_dev.dev.name, kbid, HILBASE, HIL_IRQ); + hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); return 0; } @@ -329,7 +332,10 @@ static void __exit hil_exit(void) /* Turn off interrupts */ hil_do(HIL_INTOFF, NULL, 0); - input_unregister_device(&hil_dev.dev); + input_unregister_device(hil_dev.dev); + + input_free_device(hil_dev.dev); + hil_dev.dev = NULL; #if defined(CONFIG_PARISC) unregister_parisc_driver(&hil_driver); diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c index c2bf2ed07dc6..a648f9fe3d95 100644 --- a/drivers/input/mouse/hil_ptr.c +++ b/drivers/input/mouse/hil_ptr.c @@ -55,7 +55,7 @@ MODULE_LICENSE("Dual BSD/GPL"); #define HIL_PTR_MAX_LENGTH 16 struct hil_ptr { - struct input_dev dev; + struct input_dev *dev; struct serio *serio; /* Input buffer and index for packets from HIL bus. */ @@ -79,7 +79,7 @@ struct hil_ptr { /* Process a complete packet after transfer from the HIL */ static void hil_ptr_process_record(struct hil_ptr *ptr) { - struct input_dev *dev = &ptr->dev; + struct input_dev *dev = ptr->dev; hil_packet *data = ptr->data; hil_packet p; int idx, i, cnt, laxis; @@ -148,12 +148,12 @@ static void hil_ptr_process_record(struct hil_ptr *ptr) if (absdev) { val = lo + (hi<<8); #ifdef TABLET_AUTOADJUST - if (val < ptr->dev.absmin[ABS_X + i]) - ptr->dev.absmin[ABS_X + i] = val; - if (val > ptr->dev.absmax[ABS_X + i]) - ptr->dev.absmax[ABS_X + i] = val; + if (val < dev->absmin[ABS_X + i]) + dev->absmin[ABS_X + i] = val; + if (val > dev->absmax[ABS_X + i]) + dev->absmax[ABS_X + i] = val; #endif - if (i%3) val = ptr->dev.absmax[ABS_X + i] - val; + if (i%3) val = dev->absmax[ABS_X + i] - val; input_report_abs(dev, ABS_X + i, val); } else { val = (int) (((int8_t)lo) | ((int8_t)hi<<8)); @@ -233,26 +233,30 @@ static void hil_ptr_disconnect(struct serio *serio) return; } - input_unregister_device(&ptr->dev); + input_unregister_device(ptr->dev); serio_close(serio); + input_free_device(ptr->dev); kfree(ptr); } static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) { - struct hil_ptr *ptr; - char *txt; - unsigned int i, naxsets, btntype; - uint8_t did, *idd; + struct hil_ptr *ptr; + char *txt; + unsigned int i, naxsets, btntype; + uint8_t did, *idd; - if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return -ENOMEM; - memset(ptr, 0, sizeof(struct hil_ptr)); + if (!(ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL))) + return -ENOMEM; - if (serio_open(serio, driver)) goto bail0; + ptr->dev = input_allocate_device(); + if (!ptr->dev) goto bail0; + ptr->dev->private = ptr; + + if (serio_open(serio, driver)) goto bail1; serio_set_drvdata(serio, ptr); ptr->serio = serio; - ptr->dev.private = ptr; init_MUTEX_LOCKED(&(ptr->sem)); @@ -283,25 +287,24 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) up(&(ptr->sem)); - init_input_dev(&ptr->dev); did = ptr->idd[0]; idd = ptr->idd + 1; txt = "unknown"; if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { - ptr->dev.evbit[0] = BIT(EV_REL); + ptr->dev->evbit[0] = BIT(EV_REL); txt = "relative"; } if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) { - ptr->dev.evbit[0] = BIT(EV_ABS); + ptr->dev->evbit[0] = BIT(EV_ABS); txt = "absolute"; } - if (!ptr->dev.evbit[0]) { - goto bail1; + if (!ptr->dev->evbit[0]) { + goto bail2; } ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); - if (ptr->nbtn) ptr->dev.evbit[0] |= BIT(EV_KEY); + if (ptr->nbtn) ptr->dev->evbit[0] |= BIT(EV_KEY); naxsets = HIL_IDD_NUM_AXSETS(*idd); ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); @@ -325,7 +328,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) btntype = BTN_MOUSE; for (i = 0; i < ptr->nbtn; i++) { - set_bit(btntype | i, ptr->dev.keybit); + set_bit(btntype | i, ptr->dev->keybit); ptr->btnmap[i] = btntype | i; } @@ -337,50 +340,52 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { for (i = 0; i < ptr->naxes; i++) { - set_bit(REL_X + i, ptr->dev.relbit); + set_bit(REL_X + i, ptr->dev->relbit); } for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { - set_bit(REL_X + i, ptr->dev.relbit); + set_bit(REL_X + i, ptr->dev->relbit); } } else { for (i = 0; i < ptr->naxes; i++) { - set_bit(ABS_X + i, ptr->dev.absbit); - ptr->dev.absmin[ABS_X + i] = 0; - ptr->dev.absmax[ABS_X + i] = + set_bit(ABS_X + i, ptr->dev->absbit); + ptr->dev->absmin[ABS_X + i] = 0; + ptr->dev->absmax[ABS_X + i] = HIL_IDD_AXIS_MAX((ptr->idd + 1), i); } for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { - set_bit(ABS_X + i, ptr->dev.absbit); - ptr->dev.absmin[ABS_X + i] = 0; - ptr->dev.absmax[ABS_X + i] = + set_bit(ABS_X + i, ptr->dev->absbit); + ptr->dev->absmin[ABS_X + i] = 0; + ptr->dev->absmax[ABS_X + i] = HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3)); } #ifdef TABLET_AUTOADJUST for (i = 0; i < ABS_MAX; i++) { - int diff = ptr->dev.absmax[ABS_X + i] / 10; - ptr->dev.absmin[ABS_X + i] += diff; - ptr->dev.absmax[ABS_X + i] -= diff; + int diff = ptr->dev->absmax[ABS_X + i] / 10; + ptr->dev->absmin[ABS_X + i] += diff; + ptr->dev->absmax[ABS_X + i] -= diff; } #endif } - ptr->dev.name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME; + ptr->dev->name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME; - ptr->dev.id.bustype = BUS_HIL; - ptr->dev.id.vendor = PCI_VENDOR_ID_HP; - ptr->dev.id.product = 0x0001; /* TODO: get from ptr->rsc */ - ptr->dev.id.version = 0x0100; /* TODO: get from ptr->rsc */ - ptr->dev.dev = &serio->dev; + ptr->dev->id.bustype = BUS_HIL; + ptr->dev->id.vendor = PCI_VENDOR_ID_HP; + ptr->dev->id.product = 0x0001; /* TODO: get from ptr->rsc */ + ptr->dev->id.version = 0x0100; /* TODO: get from ptr->rsc */ + ptr->dev->dev = &serio->dev; - input_register_device(&ptr->dev); + input_register_device(ptr->dev); printk(KERN_INFO "input: %s (%s), ID: %d\n", - ptr->dev.name, + ptr->dev->name, (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad", did); return 0; - bail1: + bail2: serio_close(serio); + bail1: + input_free_device(ptr->dev); bail0: kfree(ptr); serio_set_drvdata(serio, NULL); -- cgit v1.2.3-59-g8ed1b From cd7a9202a5a6e7712df2b80ed5ebd7b078130fc3 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Thu, 30 Mar 2006 11:47:32 -0500 Subject: [PARISC] Fix double free when removing HIL drivers On Thu, Mar 30, 2006 at 08:31:02AM -0500, Dmitry Torokhov wrote: > Don't do that, its double free. input_unregister_device() normally > causes release() to be called and free the device. input_free_device > is only to be called when input_register_device has not been called or > failed. > > Plus you might want to unregister device after closing serio port, > otherwise your interrupt routine might be referencing already freed > memory. Signed-off-by: Kyle McMartin --- drivers/input/keyboard/hil_kbd.c | 3 +-- drivers/input/keyboard/hilkbd.c | 1 - drivers/input/mouse/hil_ptr.c | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 99f8c5b4cd50..63f387e4b783 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -240,9 +240,8 @@ static void hil_kbd_disconnect(struct serio *serio) return; } - input_unregister_device(kbd->dev); serio_close(serio); - input_free_device(kbd->dev); + input_unregister_device(kbd->dev); kfree(kbd); } diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index 452c5f3e6129..33edd030aa75 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c @@ -334,7 +334,6 @@ static void __exit hil_exit(void) input_unregister_device(hil_dev.dev); - input_free_device(hil_dev.dev); hil_dev.dev = NULL; #if defined(CONFIG_PARISC) diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c index a648f9fe3d95..bfb564fd8fe2 100644 --- a/drivers/input/mouse/hil_ptr.c +++ b/drivers/input/mouse/hil_ptr.c @@ -233,9 +233,8 @@ static void hil_ptr_disconnect(struct serio *serio) return; } - input_unregister_device(ptr->dev); serio_close(serio); - input_free_device(ptr->dev); + input_unregister_device(ptr->dev); kfree(ptr); } -- cgit v1.2.3-59-g8ed1b From 8b316a3973f05e572b4edeeda9072987f6bbaa44 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 30 Mar 2006 17:07:32 -0500 Subject: [libata] ahci: add ATI SB600 PCI IDs From: Anatoli Antonovitch Signed-off-by: Felix Kuehling Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index ffba65656a83..1bd82c4e52a0 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -293,6 +293,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { board_ahci }, /* JMicron JMB360 */ { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB363 */ + { 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 */ { } /* terminate list */ }; -- cgit v1.2.3-59-g8ed1b From 79ea24e72e59b5f0951483cc4f357afe9bf7ff89 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 31 Mar 2006 20:01:50 +0900 Subject: [PATCH] ata_piix: fix ich6/m_map_db MAP tables of ich6 and ich6m are wrong. Depending on port usage, ata_piix may fail to initialize attached devices. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 2d5be84d8bd4..24e71b555172 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -301,7 +301,7 @@ static struct piix_map_db ich6_map_db = { .mask = 0x3, .map = { /* PM PS SM SS MAP */ - { P0, P1, P2, P3 }, /* 00b */ + { P0, P2, P1, P3 }, /* 00b */ { IDE, IDE, P1, P3 }, /* 01b */ { P0, P2, IDE, IDE }, /* 10b */ { RV, RV, RV, RV }, @@ -312,7 +312,7 @@ static struct piix_map_db ich6m_map_db = { .mask = 0x3, .map = { /* PM PS SM SS MAP */ - { P0, P1, P2, P3 }, /* 00b */ + { P0, P2, RV, RV }, /* 00b */ { RV, RV, RV, RV }, { P0, P2, IDE, IDE }, /* 10b */ { RV, RV, RV, RV }, -- cgit v1.2.3-59-g8ed1b From e4a70e76add280db6068426716a9b2a74099144f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 31 Mar 2006 20:36:47 +0900 Subject: [PATCH] libata: fix ata_qc_issue failure path On sg_err failure path, ata_qc_issue() doesn't mark the qc active before returning. This triggers WARN_ON() in __ata_qc_complete() when the qc gets completed. This patch moves ap->active_tag and QCFLAG_ACTIVE setting to the top of the function. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 21b0ed583b8a..eb4df01d9fa0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4006,6 +4006,9 @@ unsigned int ata_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; + qc->ap->active_tag = qc->tag; + qc->flags |= ATA_QCFLAG_ACTIVE; + if (ata_should_dma_map(qc)) { if (qc->flags & ATA_QCFLAG_SG) { if (ata_sg_setup(qc)) @@ -4020,9 +4023,6 @@ unsigned int ata_qc_issue(struct ata_queued_cmd *qc) ap->ops->qc_prep(qc); - qc->ap->active_tag = qc->tag; - qc->flags |= ATA_QCFLAG_ACTIVE; - return ap->ops->qc_issue(qc); sg_err: -- cgit v1.2.3-59-g8ed1b From 8e0e694a3a48212bfe29a9ad3cd592bf68dfec81 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 31 Mar 2006 20:41:11 +0900 Subject: [PATCH] libata: make ata_qc_issue complete failed qcs There is no reason for the issuer to diddle with a failed qc as the issuer has complete control over when a qc gets freed (usually in ->complete_fn). Make ata_qc_issue() responsible for completing qcs which failed to issue. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 20 +++++++++----------- drivers/scsi/libata-scsi.c | 8 ++------ drivers/scsi/libata.h | 2 +- 3 files changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index eb4df01d9fa0..63ae23b5c078 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -989,9 +989,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, qc->private_data = &wait; qc->complete_fn = ata_qc_complete_internal; - qc->err_mask = ata_qc_issue(qc); - if (qc->err_mask) - ata_qc_complete(qc); + ata_qc_issue(qc); spin_unlock_irqrestore(&ap->host_set->lock, flags); @@ -3997,12 +3995,8 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc) * * LOCKING: * spin_lock_irqsave(host_set lock) - * - * RETURNS: - * Zero on success, AC_ERR_* mask on failure */ - -unsigned int ata_qc_issue(struct ata_queued_cmd *qc) +void ata_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -4023,14 +4017,18 @@ unsigned int ata_qc_issue(struct ata_queued_cmd *qc) ap->ops->qc_prep(qc); - return ap->ops->qc_issue(qc); + qc->err_mask |= ap->ops->qc_issue(qc); + if (unlikely(qc->err_mask)) + goto err; + return; sg_err: qc->flags &= ~ATA_QCFLAG_DMAMAP; - return AC_ERR_SYSTEM; + qc->err_mask |= AC_ERR_SYSTEM; +err: + ata_qc_complete(qc); } - /** * ata_qc_issue_prot - issue taskfile to device in proto-dependent manner * @qc: command to issue to device diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 628191bfd990..53f5b0d9161c 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1431,9 +1431,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, goto early_finish; /* select device, send command to hardware */ - qc->err_mask = ata_qc_issue(qc); - if (qc->err_mask) - ata_qc_complete(qc); + ata_qc_issue(qc); VPRINTK("EXIT\n"); return; @@ -2199,9 +2197,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) qc->complete_fn = atapi_sense_complete; - qc->err_mask = ata_qc_issue(qc); - if (qc->err_mask) - ata_qc_complete(qc); + ata_qc_issue(qc); DPRINTK("EXIT\n"); } diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 65f52beea884..1c755b14521a 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -47,7 +47,7 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); extern void ata_port_flush_task(struct ata_port *ap); extern void ata_qc_free(struct ata_queued_cmd *qc); -extern unsigned int ata_qc_issue(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); extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); -- cgit v1.2.3-59-g8ed1b From be9a50c8524b53003e5fa32f072945772ffd13a5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 31 Mar 2006 22:48:52 +0900 Subject: [PATCH] libata: fix ata_xfer_tbl termination ata_xfer_tbl is terminated by entry with -1 as ->shift. However, ->shift was unsigned int making the termination condition bogus. This patch converts ->shift and ->bits to int. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 63ae23b5c078..e63c1ff1e102 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -278,7 +278,7 @@ static void ata_unpack_xfermask(unsigned int xfer_mask, } static const struct ata_xfer_ent { - unsigned int shift, bits; + int shift, bits; u8 base; } ata_xfer_tbl[] = { { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 }, -- cgit v1.2.3-59-g8ed1b From 37466ea85a7f7c9eef071a334e074265df4d1305 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 31 Mar 2006 02:29:39 -0800 Subject: [PATCH] m25p80: printk warning fix drivers/mtd/devices/m25p80.c: In function `m25p80_erase': drivers/mtd/devices/m25p80.c:189: warning: signed size_t format, different type arg (arg 6) Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/devices/m25p80.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index d5f24089be71..04e65d5dae00 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -186,7 +186,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) struct m25p *flash = mtd_to_m25p(mtd); u32 addr,len; - DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n", flash->spi->dev.bus_id, __FUNCTION__, "at", (u32)instr->addr, instr->len); -- cgit v1.2.3-59-g8ed1b From 040d79f906654d55c810313f29c6605593bf21c5 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 31 Mar 2006 02:29:40 -0800 Subject: [PATCH] sem2mutex: mtd/doc2000.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: Ingo Molnar Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/devices/doc2000.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index e4345cf744a2..0f2c956a90d3 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -975,13 +976,13 @@ static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, u_char *eccbuf, struct nand_oobinfo *oobsel) { static char static_buf[512]; - static DECLARE_MUTEX(writev_buf_sem); + static DEFINE_MUTEX(writev_buf_mutex); size_t totretlen = 0; size_t thisvecofs = 0; int ret= 0; - down(&writev_buf_sem); + mutex_lock(&writev_buf_mutex); while(count) { size_t thislen, thisretlen; @@ -1024,7 +1025,7 @@ static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, to += thislen; } - up(&writev_buf_sem); + mutex_unlock(&writev_buf_mutex); *retlen = totretlen; return ret; } -- cgit v1.2.3-59-g8ed1b From 48b192686dd20cb1576ae1d8ccd17a07971ef24a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 31 Mar 2006 02:29:41 -0800 Subject: [PATCH] sem2mutex: drivers/mtd/ 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 Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/devices/blkmtd.c | 10 +++++----- drivers/mtd/devices/block2mtd.c | 13 +++++++------ drivers/mtd/devices/doc2000.c | 30 +++++++++++++++--------------- drivers/mtd/mtd_blkdevs.c | 32 ++++++++++++++++---------------- drivers/mtd/mtdblock.c | 14 ++++++++------ drivers/mtd/mtdcore.c | 32 ++++++++++++++++---------------- include/linux/mtd/blktrans.h | 4 ++-- include/linux/mtd/doc2000.h | 4 ++-- 8 files changed, 71 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c index 04f864d238db..d732532635a1 100644 --- a/drivers/mtd/devices/blkmtd.c +++ b/drivers/mtd/devices/blkmtd.c @@ -29,7 +29,7 @@ #include #include #include - +#include #define err(format, arg...) printk(KERN_ERR "blkmtd: " format "\n" , ## arg) #define info(format, arg...) printk(KERN_INFO "blkmtd: " format "\n" , ## arg) @@ -46,7 +46,7 @@ struct blkmtd_dev { struct list_head list; struct block_device *blkdev; struct mtd_info mtd_info; - struct semaphore wrbuf_mutex; + struct mutex wrbuf_mutex; }; @@ -268,7 +268,7 @@ static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to, if(end_len) pagecnt++; - down(&dev->wrbuf_mutex); + mutex_lock(&dev->wrbuf_mutex); DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n", start_len, len, end_len, pagecnt); @@ -376,7 +376,7 @@ static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to, blkmtd_write_out(bio); DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err); - up(&dev->wrbuf_mutex); + mutex_unlock(&dev->wrbuf_mutex); if(retlen) *retlen = thislen; @@ -659,7 +659,7 @@ static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size memset(dev, 0, sizeof(struct blkmtd_dev)); dev->blkdev = bdev; if(!readonly) { - init_MUTEX(&dev->wrbuf_mutex); + mutex_init(&dev->wrbuf_mutex); } dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 7ff403b2a0a0..4160b8334c53 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -18,6 +18,7 @@ #include #include #include +#include #define VERSION "$Revision: 1.30 $" @@ -31,7 +32,7 @@ struct block2mtd_dev { struct list_head list; struct block_device *blkdev; struct mtd_info mtd; - struct semaphore write_mutex; + struct mutex write_mutex; }; @@ -134,9 +135,9 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr) int err; instr->state = MTD_ERASING; - down(&dev->write_mutex); + mutex_lock(&dev->write_mutex); err = _block2mtd_erase(dev, from, len); - up(&dev->write_mutex); + mutex_unlock(&dev->write_mutex); if (err) { ERROR("erase failed err = %d", err); instr->state = MTD_ERASE_FAILED; @@ -249,9 +250,9 @@ static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, if (to + len > mtd->size) len = mtd->size - to; - down(&dev->write_mutex); + mutex_lock(&dev->write_mutex); err = _block2mtd_write(dev, buf, to, len, retlen); - up(&dev->write_mutex); + mutex_unlock(&dev->write_mutex); if (err > 0) err = 0; return err; @@ -310,7 +311,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) goto devinit_err; } - init_MUTEX(&dev->write_mutex); + mutex_init(&dev->write_mutex); /* Setup the MTD structure */ /* make the name contain the block device in */ diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index 0f2c956a90d3..23e7a5c7d2c1 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c @@ -606,7 +606,7 @@ static void DoC2k_init(struct mtd_info *mtd) this->curfloor = -1; this->curchip = -1; - init_MUTEX(&this->lock); + mutex_init(&this->lock); /* Ident all the chips present. */ DoC_ScanChips(this, maxchips); @@ -646,7 +646,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, if (from >= this->totlen) return -EINVAL; - down(&this->lock); + mutex_lock(&this->lock); *retlen = 0; while (left) { @@ -775,7 +775,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, buf += len; } - up(&this->lock); + mutex_unlock(&this->lock); return ret; } @@ -804,7 +804,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, if (to >= this->totlen) return -EINVAL; - down(&this->lock); + mutex_lock(&this->lock); *retlen = 0; while (left) { @@ -874,7 +874,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, printk(KERN_ERR "Error programming flash\n"); /* Error in programming */ *retlen = 0; - up(&this->lock); + mutex_unlock(&this->lock); return -EIO; } @@ -936,7 +936,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, printk(KERN_ERR "Error programming flash\n"); /* Error in programming */ *retlen = 0; - up(&this->lock); + mutex_unlock(&this->lock); return -EIO; } @@ -957,7 +957,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x); if (ret) { - up(&this->lock); + mutex_unlock(&this->lock); return ret; } } @@ -967,7 +967,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, buf += len; } - up(&this->lock); + mutex_unlock(&this->lock); return 0; } @@ -1038,7 +1038,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, int len256 = 0, ret; struct Nand *mychip; - down(&this->lock); + mutex_lock(&this->lock); mychip = &this->chips[ofs >> this->chipshift]; @@ -1084,7 +1084,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, ret = DoC_WaitReady(this); - up(&this->lock); + mutex_unlock(&this->lock); return ret; } @@ -1198,10 +1198,10 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, struct DiskOnChip *this = mtd->priv; int ret; - down(&this->lock); + mutex_lock(&this->lock); ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf); - up(&this->lock); + mutex_unlock(&this->lock); return ret; } @@ -1215,10 +1215,10 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) struct Nand *mychip; int status; - down(&this->lock); + mutex_lock(&this->lock); if (ofs & (mtd->erasesize-1) || len & (mtd->erasesize-1)) { - up(&this->lock); + mutex_unlock(&this->lock); return -EINVAL; } @@ -1266,7 +1266,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) callback: mtd_erase_callback(instr); - up(&this->lock); + mutex_unlock(&this->lock); return 0; } diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 840dd66ce2dc..458d3c8ae1ee 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -19,12 +19,12 @@ #include #include #include -#include +#include #include static LIST_HEAD(blktrans_majors); -extern struct semaphore mtd_table_mutex; +extern struct mutex mtd_table_mutex; extern struct mtd_info *mtd_table[]; struct mtd_blkcore_priv { @@ -122,9 +122,9 @@ static int mtd_blktrans_thread(void *arg) spin_unlock_irq(rq->queue_lock); - down(&dev->sem); + mutex_lock(&dev->lock); res = do_blktrans_request(tr, dev, req); - up(&dev->sem); + mutex_unlock(&dev->lock); spin_lock_irq(rq->queue_lock); @@ -235,8 +235,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) int last_devnum = -1; struct gendisk *gd; - if (!down_trylock(&mtd_table_mutex)) { - up(&mtd_table_mutex); + if (!!mutex_trylock(&mtd_table_mutex)) { + mutex_unlock(&mtd_table_mutex); BUG(); } @@ -267,7 +267,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) return -EBUSY; } - init_MUTEX(&new->sem); + mutex_init(&new->lock); list_add_tail(&new->list, &tr->devs); added: if (!tr->writesect) @@ -313,8 +313,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) { - if (!down_trylock(&mtd_table_mutex)) { - up(&mtd_table_mutex); + if (!!mutex_trylock(&mtd_table_mutex)) { + mutex_unlock(&mtd_table_mutex); BUG(); } @@ -378,14 +378,14 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv)); - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); ret = register_blkdev(tr->major, tr->name); if (ret) { printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", tr->name, tr->major, ret); kfree(tr->blkcore_priv); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return ret; } spin_lock_init(&tr->blkcore_priv->queue_lock); @@ -396,7 +396,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) if (!tr->blkcore_priv->rq) { unregister_blkdev(tr->major, tr->name); kfree(tr->blkcore_priv); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return -ENOMEM; } @@ -407,7 +407,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) blk_cleanup_queue(tr->blkcore_priv->rq); unregister_blkdev(tr->major, tr->name); kfree(tr->blkcore_priv); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return ret; } @@ -419,7 +419,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) tr->add_mtd(tr, mtd_table[i]); } - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return 0; } @@ -428,7 +428,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) { struct list_head *this, *next; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); /* Clean up the kernel thread */ tr->blkcore_priv->exiting = 1; @@ -446,7 +446,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) blk_cleanup_queue(tr->blkcore_priv->rq); unregister_blkdev(tr->major, tr->name); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); kfree(tr->blkcore_priv); diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index e84756644fd1..2cef280e388c 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -19,11 +19,13 @@ #include #include +#include + static struct mtdblk_dev { struct mtd_info *mtd; int count; - struct semaphore cache_sem; + struct mutex cache_mutex; unsigned char *cache_data; unsigned long cache_offset; unsigned int cache_size; @@ -284,7 +286,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) mtdblk->count = 1; mtdblk->mtd = mtd; - init_MUTEX (&mtdblk->cache_sem); + mutex_init(&mtdblk->cache_mutex); mtdblk->cache_state = STATE_EMPTY; if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM && mtdblk->mtd->erasesize) { @@ -306,9 +308,9 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); - down(&mtdblk->cache_sem); + mutex_lock(&mtdblk->cache_mutex); write_cached_data(mtdblk); - up(&mtdblk->cache_sem); + mutex_unlock(&mtdblk->cache_mutex); if (!--mtdblk->count) { /* It was the last usage. Free the device */ @@ -327,9 +329,9 @@ static int mtdblock_flush(struct mtd_blktrans_dev *dev) { struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; - down(&mtdblk->cache_sem); + mutex_lock(&mtdblk->cache_mutex); write_cached_data(mtdblk); - up(&mtdblk->cache_sem); + mutex_unlock(&mtdblk->cache_mutex); if (mtdblk->mtd->sync) mtdblk->mtd->sync(mtdblk->mtd); diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index dade02ab0687..9c3813486a1a 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -27,7 +27,7 @@ /* These are exported solely for the purpose of mtd_blkdevs.c. You should not use them for _anything_ else */ -DECLARE_MUTEX(mtd_table_mutex); +DEFINE_MUTEX(mtd_table_mutex); struct mtd_info *mtd_table[MAX_MTD_DEVICES]; EXPORT_SYMBOL_GPL(mtd_table_mutex); @@ -49,7 +49,7 @@ int add_mtd_device(struct mtd_info *mtd) { int i; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); for (i=0; i < MAX_MTD_DEVICES; i++) if (!mtd_table[i]) { @@ -67,7 +67,7 @@ int add_mtd_device(struct mtd_info *mtd) not->add(mtd); } - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); /* We _know_ we aren't being removed, because our caller is still holding us here. So none of this try_ nonsense, and no bitching about it @@ -76,7 +76,7 @@ int add_mtd_device(struct mtd_info *mtd) return 0; } - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return 1; } @@ -94,7 +94,7 @@ int del_mtd_device (struct mtd_info *mtd) { int ret; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); if (mtd_table[mtd->index] != mtd) { ret = -ENODEV; @@ -118,7 +118,7 @@ int del_mtd_device (struct mtd_info *mtd) ret = 0; } - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return ret; } @@ -135,7 +135,7 @@ void register_mtd_user (struct mtd_notifier *new) { int i; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); list_add(&new->list, &mtd_notifiers); @@ -145,7 +145,7 @@ void register_mtd_user (struct mtd_notifier *new) if (mtd_table[i]) new->add(mtd_table[i]); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); } /** @@ -162,7 +162,7 @@ int unregister_mtd_user (struct mtd_notifier *old) { int i; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); module_put(THIS_MODULE); @@ -171,7 +171,7 @@ int unregister_mtd_user (struct mtd_notifier *old) old->remove(mtd_table[i]); list_del(&old->list); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return 0; } @@ -193,7 +193,7 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) struct mtd_info *ret = NULL; int i; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); if (num == -1) { for (i=0; i< MAX_MTD_DEVICES; i++) @@ -211,7 +211,7 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) if (ret) ret->usecount++; - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return ret; } @@ -219,9 +219,9 @@ void put_mtd_device(struct mtd_info *mtd) { int c; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); c = --mtd->usecount; - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); BUG_ON(c < 0); module_put(mtd->owner); @@ -319,7 +319,7 @@ static int mtd_read_proc (char *page, char **start, off_t off, int count, int len, l, i; off_t begin = 0; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); len = sprintf(page, "dev: size erasesize name\n"); for (i=0; i< MAX_MTD_DEVICES; i++) { @@ -337,7 +337,7 @@ static int mtd_read_proc (char *page, char **start, off_t off, int count, *eof = 1; done: - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); if (off >= len+begin) return 0; *start = page + (off-begin); diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h index f46afec6fbf8..72fc68c5ee96 100644 --- a/include/linux/mtd/blktrans.h +++ b/include/linux/mtd/blktrans.h @@ -10,7 +10,7 @@ #ifndef __MTD_TRANS_H__ #define __MTD_TRANS_H__ -#include +#include struct hd_geometry; struct mtd_info; @@ -22,7 +22,7 @@ struct mtd_blktrans_dev { struct mtd_blktrans_ops *tr; struct list_head list; struct mtd_info *mtd; - struct semaphore sem; + struct mutex lock; int devnum; int blksize; unsigned long size; diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h index 386a52cf8b1b..9addd073bf15 100644 --- a/include/linux/mtd/doc2000.h +++ b/include/linux/mtd/doc2000.h @@ -15,7 +15,7 @@ #define __MTD_DOC2000_H__ #include -#include +#include #define DoC_Sig1 0 #define DoC_Sig2 1 @@ -187,7 +187,7 @@ struct DiskOnChip { int numchips; struct Nand *chips; struct mtd_info *nextdoc; - struct semaphore lock; + struct mutex lock; }; int doc_decode_ecc(unsigned char sector[512], unsigned char ecc1[6]); -- cgit v1.2.3-59-g8ed1b From 0500abf52109d09bf60d740dec2e41d6cf265688 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 31 Mar 2006 02:29:42 -0800 Subject: [PATCH] drivers/mtd/: small cleanups - chips/sharp.c: make two needlessly global functions static - move some declarations to a header file where they belong to Signed-off-by: Adrian Bunk Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/chips/sharp.c | 7 +++---- drivers/mtd/inftlcore.c | 5 ----- include/linux/mtd/inftl.h | 5 +++++ 3 files changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c index 36f61a6a766e..3cc0b23c5865 100644 --- a/drivers/mtd/chips/sharp.c +++ b/drivers/mtd/chips/sharp.c @@ -64,7 +64,7 @@ #undef AUTOUNLOCK /* automatically unlocks blocks before erasing */ -struct mtd_info *sharp_probe(struct map_info *); +static struct mtd_info *sharp_probe(struct map_info *); static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd); @@ -96,7 +96,6 @@ struct sharp_info{ struct flchip chips[1]; }; -struct mtd_info *sharp_probe(struct map_info *map); static void sharp_destroy(struct mtd_info *mtd); static struct mtd_chip_driver sharp_chipdrv = { @@ -107,7 +106,7 @@ static struct mtd_chip_driver sharp_chipdrv = { }; -struct mtd_info *sharp_probe(struct map_info *map) +static struct mtd_info *sharp_probe(struct map_info *map) { struct mtd_info *mtd = NULL; struct sharp_info *sharp = NULL; @@ -581,7 +580,7 @@ static void sharp_destroy(struct mtd_info *mtd) } -int __init sharp_probe_init(void) +static int __init sharp_probe_init(void) { printk("MTD Sharp chip driver \n"); diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 8a544890173d..abb76aa6326a 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -47,9 +47,6 @@ */ #define MAX_LOOPS 10000 -extern void INFTL_dumptables(struct INFTLrecord *inftl); -extern void INFTL_dumpVUchains(struct INFTLrecord *inftl); - static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) { struct INFTLrecord *inftl; @@ -885,8 +882,6 @@ static struct mtd_blktrans_ops inftl_tr = { .owner = THIS_MODULE, }; -extern char inftlmountrev[]; - static int __init init_inftl(void) { printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.19 $, " diff --git a/include/linux/mtd/inftl.h b/include/linux/mtd/inftl.h index 0268125a6271..d7eaa40e5ab0 100644 --- a/include/linux/mtd/inftl.h +++ b/include/linux/mtd/inftl.h @@ -52,6 +52,11 @@ struct INFTLrecord { int INFTL_mount(struct INFTLrecord *s); int INFTL_formatblock(struct INFTLrecord *s, int block); +extern char inftlmountrev[]; + +void INFTL_dumptables(struct INFTLrecord *s); +void INFTL_dumpVUchains(struct INFTLrecord *s); + #endif /* __KERNEL__ */ #endif /* __MTD_INFTL_H__ */ -- cgit v1.2.3-59-g8ed1b From 54af6b46485bb706b7cdffd2e419253fd00cae6a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 31 Mar 2006 02:29:43 -0800 Subject: [PATCH] MTD_NAND_SHARPSL and MTD_NAND_NANDSIM should be tristate's MTD_NAND=m and MTD_NAND_SHARPSL=y or MTD_NAND_NANDSIM=y are illegal combinations that mustn't be allowed. This patch fixes this bug by making MTD_NAND_SHARPSL and MTD_NAND_NANDSIM tristate's. Additionally, it fixes some whitespace damage at these options. Signed-off-by: Adrian Bunk Acked-by: Richard Purdie Acked-by: "Artem B. Bityutskiy" Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/nand/Kconfig | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 1fc4c134d939..cfe288a6e853 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -178,17 +178,16 @@ config MTD_NAND_DISKONCHIP_BBTWRITE Even if you leave this disabled, you can enable BBT writes at module load time (assuming you build diskonchip as a module) with the module parameter "inftl_bbt_write=1". - - config MTD_NAND_SHARPSL - bool "Support for NAND Flash on Sharp SL Series (C7xx + others)" - depends on MTD_NAND && ARCH_PXA - - config MTD_NAND_NANDSIM - bool "Support for NAND Flash Simulator" - depends on MTD_NAND && MTD_PARTITIONS +config MTD_NAND_SHARPSL + tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" + depends on MTD_NAND && ARCH_PXA + +config MTD_NAND_NANDSIM + tristate "Support for NAND Flash Simulator" + depends on MTD_NAND && MTD_PARTITIONS help The simulator may simulate verious NAND flash chips for the MTD nand layer. - + endmenu -- cgit v1.2.3-59-g8ed1b From 87d10f3c7954d143e509a2af2bca2a27aeb3114d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 31 Mar 2006 02:29:45 -0800 Subject: [PATCH] drivers/mtd: 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 Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/chips/amd_flash.c | 4 ++-- drivers/mtd/chips/jedec_probe.c | 2 +- drivers/mtd/devices/lart.c | 10 ++++------ drivers/mtd/devices/ms02-nv.c | 2 +- drivers/mtd/maps/alchemy-flash.c | 4 +--- drivers/mtd/maps/cfi_flagadm.c | 2 +- drivers/mtd/maps/dbox2-flash.c | 2 +- drivers/mtd/maps/dilnetpc.c | 4 ++-- drivers/mtd/maps/dmv182.c | 2 +- drivers/mtd/maps/h720x-flash.c | 2 +- drivers/mtd/maps/netsc520.c | 4 ++-- drivers/mtd/maps/nettel.c | 3 +-- drivers/mtd/maps/ocotea.c | 6 ++---- drivers/mtd/maps/pcmciamtd.c | 2 +- drivers/mtd/maps/redwood.c | 3 +-- drivers/mtd/maps/sbc8240.c | 8 +++----- drivers/mtd/maps/sc520cdp.c | 2 +- drivers/mtd/maps/scx200_docflash.c | 2 +- drivers/mtd/maps/sharpsl-flash.c | 4 +--- drivers/mtd/maps/ts5500_flash.c | 2 +- drivers/mtd/maps/uclinux.c | 2 +- drivers/mtd/nand/au1550nd.c | 4 +--- 22 files changed, 31 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c index fdb91b6f1d97..57115618c496 100644 --- a/drivers/mtd/chips/amd_flash.c +++ b/drivers/mtd/chips/amd_flash.c @@ -664,7 +664,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map) printk("%s: Probing for AMD compatible flash...\n", map->name); if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table, - sizeof(table)/sizeof(table[0]))) + ARRAY_SIZE(table))) == -1) { printk(KERN_WARNING "%s: Found no AMD compatible device at location zero\n", @@ -696,7 +696,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map) base += (1 << temp.chipshift)) { int numchips = temp.numchips; table_pos[numchips] = probe_new_chip(mtd, base, chips, - &temp, table, sizeof(table)/sizeof(table[0])); + &temp, table, ARRAY_SIZE(table)); } mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index edb306c03c0a..8e24be0fae1f 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -2035,7 +2035,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, DEBUG(MTD_DEBUG_LEVEL3, "Search for id:(%02x %02x) interleave(%d) type(%d)\n", cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type); - for (i=0; iowner = THIS_MODULE; add_mtd_partitions(flash, ocotea_small_partitions, - NB_OF(ocotea_small_partitions)); + ARRAY_SIZE(ocotea_small_partitions)); } else { printk("map probe failed for flash\n"); return -ENXIO; @@ -118,7 +116,7 @@ int __init init_ocotea(void) if (flash) { flash->owner = THIS_MODULE; add_mtd_partitions(flash, ocotea_large_partitions, - NB_OF(ocotea_large_partitions)); + ARRAY_SIZE(ocotea_large_partitions)); } else { printk("map probe failed for flash\n"); return -ENXIO; diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index f988c817e196..8bbc751a6021 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -616,7 +616,7 @@ static void pcmciamtd_config(dev_link_t *link) } else if(mem_type == 2) { mtd = do_map_probe("map_rom", &dev->pcmcia_map); } else { - for(i = 0; i < sizeof(probes) / sizeof(char *); i++) { + for(i = 0; i < ARRAY_SIZE(probes); i++) { DEBUG(1, "Trying %s", probes[i]); mtd = do_map_probe(probes[i], &dev->pcmcia_map); if(mtd) diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c index 5b76ed886185..50b14033613f 100644 --- a/drivers/mtd/maps/redwood.c +++ b/drivers/mtd/maps/redwood.c @@ -121,8 +121,7 @@ struct map_info redwood_flash_map = { }; -#define NUM_REDWOOD_FLASH_PARTITIONS \ - (sizeof(redwood_flash_partitions)/sizeof(redwood_flash_partitions[0])) +#define NUM_REDWOOD_FLASH_PARTITIONS ARRAY_SIZE(redwood_flash_partitions) static struct mtd_info *redwood_mtd; diff --git a/drivers/mtd/maps/sbc8240.c b/drivers/mtd/maps/sbc8240.c index 225cdd9ba5b2..350286dc1d2e 100644 --- a/drivers/mtd/maps/sbc8240.c +++ b/drivers/mtd/maps/sbc8240.c @@ -66,7 +66,7 @@ static struct map_info sbc8240_map[2] = { } }; -#define NUM_FLASH_BANKS (sizeof(sbc8240_map) / sizeof(struct map_info)) +#define NUM_FLASH_BANKS ARRAY_SIZE(sbc8240_map) /* * The following defines the partition layout of SBC8240 boards. @@ -125,8 +125,6 @@ static struct mtd_partition sbc8240_fs_partitions [] = { } }; -#define NB_OF(x) (sizeof (x) / sizeof (x[0])) - /* trivial struct to describe partition information */ struct mtd_part_def { @@ -190,10 +188,10 @@ int __init init_sbc8240_mtd (void) #ifdef CONFIG_MTD_PARTITIONS sbc8240_part_banks[0].mtd_part = sbc8240_uboot_partitions; sbc8240_part_banks[0].type = "static image"; - sbc8240_part_banks[0].nums = NB_OF(sbc8240_uboot_partitions); + sbc8240_part_banks[0].nums = ARRAY_SIZE(sbc8240_uboot_partitions); sbc8240_part_banks[1].mtd_part = sbc8240_fs_partitions; sbc8240_part_banks[1].type = "static file system"; - sbc8240_part_banks[1].nums = NB_OF(sbc8240_fs_partitions); + sbc8240_part_banks[1].nums = ARRAY_SIZE(sbc8240_fs_partitions); for (i = 0; i < NUM_FLASH_BANKS; i++) { diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c index ed92afadd8a9..e8c130e1efd3 100644 --- a/drivers/mtd/maps/sc520cdp.c +++ b/drivers/mtd/maps/sc520cdp.c @@ -107,7 +107,7 @@ static struct map_info sc520cdp_map[] = { }, }; -#define NUM_FLASH_BANKS (sizeof(sc520cdp_map)/sizeof(struct map_info)) +#define NUM_FLASH_BANKS ARRAY_SIZE(sc520cdp_map) static struct mtd_info *mymtd[NUM_FLASH_BANKS]; static struct mtd_info *merged_mtd; diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c index 2c91dff8bb60..28b8a571a91a 100644 --- a/drivers/mtd/maps/scx200_docflash.c +++ b/drivers/mtd/maps/scx200_docflash.c @@ -70,7 +70,7 @@ static struct mtd_partition partition_info[] = { .size = 0x80000 }, }; -#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) +#define NUM_PARTITIONS ARRAY_SIZE(partition_info) #endif diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c index 999f4bb3d845..12fe53c0d2fc 100644 --- a/drivers/mtd/maps/sharpsl-flash.c +++ b/drivers/mtd/maps/sharpsl-flash.c @@ -49,8 +49,6 @@ static struct mtd_partition sharpsl_partitions[1] = { } }; -#define NB_OF(x) (sizeof(x)/sizeof(x[0])) - int __init init_sharpsl(void) { struct mtd_partition *parts; @@ -92,7 +90,7 @@ int __init init_sharpsl(void) } parts = sharpsl_partitions; - nb_parts = NB_OF(sharpsl_partitions); + nb_parts = ARRAY_SIZE(sharpsl_partitions); printk(KERN_NOTICE "Using %s partision definition\n", part_type); add_mtd_partitions(mymtd, parts, nb_parts); diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c index 4b372bcb17f1..a7422c200567 100644 --- a/drivers/mtd/maps/ts5500_flash.c +++ b/drivers/mtd/maps/ts5500_flash.c @@ -64,7 +64,7 @@ static struct mtd_partition ts5500_partitions[] = { } }; -#define NUM_PARTITIONS (sizeof(ts5500_partitions)/sizeof(struct mtd_partition)) +#define NUM_PARTITIONS ARRAY_SIZE(ts5500_partitions) static struct mtd_info *mymtd; diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index 79d92808b766..f7264dc2ac9b 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c @@ -37,7 +37,7 @@ struct mtd_partition uclinux_romfs[] = { { .name = "ROMfs" } }; -#define NUM_PARTITIONS (sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0])) +#define NUM_PARTITIONS ARRAY_SIZE(uclinux_romfs) /****************************************************************************/ diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 201e1362da14..bde3550910a2 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -55,8 +55,6 @@ static const struct mtd_partition partition_info[] = { .size = MTDPART_SIZ_FULL } }; -#define NB_OF(x) (sizeof(x)/sizeof(x[0])) - /** * au_read_byte - read one byte from the chip @@ -462,7 +460,7 @@ int __init au1xxx_nand_init (void) } /* Register the partitions */ - add_mtd_partitions(au1550_mtd, partition_info, NB_OF(partition_info)); + add_mtd_partitions(au1550_mtd, partition_info, ARRAY_SIZE(partition_info)); return 0; -- cgit v1.2.3-59-g8ed1b From b175d03dd207283609b7f8bfdaa5dc93ac9b16dd Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Fri, 31 Mar 2006 02:29:46 -0800 Subject: [PATCH] mtd cmdlinepart: allow zero offset value Current cmdlinepart.c uses offset value 0 to specify a continuous partition. This prevents creating a second partition starting at 0. For example, I can split 4MB device using "mtdparts=id:2M,2M", but I can not do "mtdparts=id:2M@2M,2M@0" to swap mtd0 and mtd1. This patch introduces special OFFSET_CONTINUOUS value for a continuous partition and allows 0 for offset value. Also this patch replaces 0xffffffff with UINT_MAX for SIZE_REMAINING. Signed-off-by: Atsushi Nemoto Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/cmdlinepart.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 6b8bb2e4dcfd..a7a7bfe33879 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c @@ -42,7 +42,8 @@ /* special size referring to all the remaining space in a partition */ -#define SIZE_REMAINING 0xffffffff +#define SIZE_REMAINING UINT_MAX +#define OFFSET_CONTINUOUS UINT_MAX struct cmdline_mtd_partition { struct cmdline_mtd_partition *next; @@ -75,7 +76,7 @@ static struct mtd_partition * newpart(char *s, { struct mtd_partition *parts; unsigned long size; - unsigned long offset = 0; + unsigned long offset = OFFSET_CONTINUOUS; char *name; int name_len; unsigned char *extra_mem; @@ -314,7 +315,7 @@ static int parse_cmdline_partitions(struct mtd_info *master, { for(i = 0, offset = 0; i < part->num_parts; i++) { - if (!part->parts[i].offset) + if (part->parts[i].offset == OFFSET_CONTINUOUS) part->parts[i].offset = offset; else offset = part->parts[i].offset; -- cgit v1.2.3-59-g8ed1b From 8b68a1263305d4e8a07d8a43c996969ea9e44292 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn / snakebyte Date: Fri, 31 Mar 2006 02:29:47 -0800 Subject: [PATCH] Fix debug statement in inftlcore.c Fix a copy/paste bug found by cpminer inside the inftlcore.c file Signed-off-by: Eric Sesterhenn Acked-by: Greg Ungerer Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/inftlcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index abb76aa6326a..a3b92479719d 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -129,7 +129,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) return; } #ifdef PSYCHO_DEBUG - printk(KERN_INFO "INFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a'); + printk(KERN_INFO "INFTL: Found new inftl%c\n", inftl->mbd.devnum + 'a'); #endif return; } -- cgit v1.2.3-59-g8ed1b From 2d2dce0eb650831046316a9cd091ea5257aa7d4b Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 31 Mar 2006 02:29:49 -0800 Subject: [PATCH] Kill ifdefs in mtdcore.c Kill unneccessary ifdefs in mtdcore.c. Signed-off-by: Pavel Machek Cc: Thomas Gleixner Signed-off-by: Adrian Bunk Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/mtdcore.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 9c3813486a1a..9905870f56e5 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -19,9 +19,7 @@ #include #include #include -#ifdef CONFIG_PROC_FS #include -#endif #include @@ -296,10 +294,11 @@ EXPORT_SYMBOL(unregister_mtd_user); EXPORT_SYMBOL(default_mtd_writev); EXPORT_SYMBOL(default_mtd_readv); +#ifdef CONFIG_PROC_FS + /*====================================================================*/ /* Support for /proc/mtd */ -#ifdef CONFIG_PROC_FS static struct proc_dir_entry *proc_mtd; static inline int mtd_proc_info (char *buf, int i) @@ -344,31 +343,27 @@ done: return ((count < begin+len-off) ? count : begin+len-off); } -#endif /* CONFIG_PROC_FS */ - /*====================================================================*/ /* Init code */ static int __init init_mtd(void) { -#ifdef CONFIG_PROC_FS if ((proc_mtd = create_proc_entry( "mtd", 0, NULL ))) proc_mtd->read_proc = mtd_read_proc; -#endif return 0; } static void __exit cleanup_mtd(void) { -#ifdef CONFIG_PROC_FS if (proc_mtd) remove_proc_entry( "mtd", NULL); -#endif } module_init(init_mtd); module_exit(cleanup_mtd); +#endif /* CONFIG_PROC_FS */ + MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse "); -- cgit v1.2.3-59-g8ed1b From edcbce2150fec1f6e6670e14eb65098eebfacae8 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 31 Mar 2006 02:29:50 -0800 Subject: [PATCH] Dead code in mtd/maps/pci.c This fixes coverity bug #12. The first two gotos in the function still have the initial value for mtd set. And the third goto just triggers for !mtd Signed-off-by: Eric Sesterhenn Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/maps/pci.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 21822c2edbe4..d2ab1bae9c34 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c @@ -334,9 +334,6 @@ mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) return 0; release: - if (mtd) - map_destroy(mtd); - if (map) { map->exit(dev, map); kfree(map); -- cgit v1.2.3-59-g8ed1b From a63ec1b7b7c38f9a61ed11eefd670a49879e9dd3 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 31 Mar 2006 02:29:51 -0800 Subject: [PATCH] Add chip used in collie to jedec_probe This adds flash chip used in Sharp Zaurus sl5500 (collie) to jedec_probe. Values work for read-only access, but I have not figured out how to do read-write. Signed-off-by: Pavel Machek Cc: Richard Purdie Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/chips/jedec_probe.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index 8e24be0fae1f..517ea33e7260 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -34,6 +34,7 @@ #define MANUFACTURER_MACRONIX 0x00C2 #define MANUFACTURER_NEC 0x0010 #define MANUFACTURER_PMC 0x009D +#define MANUFACTURER_SHARP 0x00b0 #define MANUFACTURER_SST 0x00BF #define MANUFACTURER_ST 0x0020 #define MANUFACTURER_TOSHIBA 0x0098 @@ -124,6 +125,9 @@ #define PM49FL004 0x006E #define PM49FL008 0x006A +/* Sharp */ +#define LH28F640BF 0x00b0 + /* ST - www.st.com */ #define M29W800DT 0x00D7 #define M29W800DB 0x005B @@ -1267,6 +1271,19 @@ static const struct amd_flash_info jedec_table[] = { .regions = { ERASEINFO( 0x01000, 256 ) } + }, { + .mfr_id = MANUFACTURER_SHARP, + .dev_id = LH28F640BF, + .name = "LH28F640BF", + .uaddr = { + [0] = MTD_UADDR_UNNECESSARY, /* x8 */ + }, + .DevSize = SIZE_4MiB, + .CmdSet = P_ID_INTEL_STD, + .NumEraseRegions= 1, + .regions = { + ERASEINFO(0x40000,16), + } }, { .mfr_id = MANUFACTURER_SST, .dev_id = SST39LF512, -- cgit v1.2.3-59-g8ed1b From 84e699e6ec5b431289474f78f8df9dfcc2737085 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Fri, 31 Mar 2006 02:29:52 -0800 Subject: [PATCH] mtd/redboot: Handle holes in fis table Redboot simply sets the first character of a fis entry to 0xff on "fis delete". The kernel redboot parser stops parsing on such an entry, and without this patch any entries after a deleted image would not be detected. Signed-off-by: Peter Korsgaard Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/redboot.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index 8815c8dbef2d..c077d2ec9cdd 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c @@ -85,10 +85,6 @@ static int parse_redboot_partitions(struct mtd_info *master, numslots = (master->erasesize / sizeof(struct fis_image_desc)); for (i = 0; i < numslots; i++) { - if (buf[i].name[0] == 0xff) { - i = numslots; - break; - } if (!memcmp(buf[i].name, "FIS directory", 14)) { /* This is apparently the FIS directory entry for the * FIS directory itself. The FIS directory size is @@ -128,7 +124,7 @@ static int parse_redboot_partitions(struct mtd_info *master, struct fis_list *new_fl, **prev; if (buf[i].name[0] == 0xff) - break; + continue; if (!redboot_checksum(&buf[i])) break; -- cgit v1.2.3-59-g8ed1b From 4d551465986c9a0040f47700a8c736c90519418f Mon Sep 17 00:00:00 2001 From: Herbert Poetzl Date: Fri, 31 Mar 2006 02:29:53 -0800 Subject: [PATCH] mtd: fix broken name_to_dev_t() declaration drivers/mtd/devices/blkmtd.c uses a local declaration of name_to_dev_t() which is inconsistant with the real one. the following patch fixes this by removing the local declaration and including mount.h instead this patch was originally done by Micah Anderson. Signed-off-by: Herbert Poetzl Acked-by: Micah Anderson Acked-by: Daniel Hokka Zakrisson Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/devices/blkmtd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c index d732532635a1..79f2e1f23ebd 100644 --- a/drivers/mtd/devices/blkmtd.c +++ b/drivers/mtd/devices/blkmtd.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -614,8 +615,6 @@ static struct mtd_erase_region_info *calc_erase_regions( } -extern dev_t __init name_to_dev_t(const char *line); - static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size) { struct block_device *bdev; -- cgit v1.2.3-59-g8ed1b From b5ac5d7edb64b3ca1a489b30d95d62492a1f0b80 Mon Sep 17 00:00:00 2001 From: "Petri T. Koistinen" Date: Fri, 31 Mar 2006 02:29:54 -0800 Subject: [PATCH] drivers/mtd/maps/vmax301.c: fix off by one vmax_mtd Fix an obvious off-by-one error (vmax_mtd[] contains two elements). Signed-off-by: Adrian Bunk Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/maps/vmax301.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c index e0063941c0df..b3e487395435 100644 --- a/drivers/mtd/maps/vmax301.c +++ b/drivers/mtd/maps/vmax301.c @@ -182,7 +182,7 @@ int __init init_vmax301(void) } } - if (!vmax_mtd[1] && !vmax_mtd[2]) { + if (!vmax_mtd[0] && !vmax_mtd[1]) { iounmap((void *)iomapadr); return -ENXIO; } -- cgit v1.2.3-59-g8ed1b From 694a464e19b9e3278dbaf6a09fa7c1efec3f8eb5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 31 Mar 2006 02:30:14 -0800 Subject: [PATCH] uml: kconfigs kconfig sanitized around drivers/net Signed-off-by: Al Viro Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Kconfig | 3 +++ drivers/net/Kconfig | 2 -- drivers/net/tokenring/Kconfig | 2 +- drivers/net/wireless/Kconfig | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 5982fe2753e0..05fbb20636cb 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -22,6 +22,9 @@ config SBUS config PCI bool +config PCMCIA + bool + config GENERIC_CALIBRATE_DELAY bool default y diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e20b849a22e8..bdaaad8f2123 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2313,13 +2313,11 @@ config S2IO_NAPI endmenu -if !UML source "drivers/net/tokenring/Kconfig" source "drivers/net/wireless/Kconfig" source "drivers/net/pcmcia/Kconfig" -endif source "drivers/net/wan/Kconfig" diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig index e4cfc80b283b..99c4c1922f19 100644 --- a/drivers/net/tokenring/Kconfig +++ b/drivers/net/tokenring/Kconfig @@ -3,7 +3,7 @@ # menu "Token Ring devices" - depends on NETDEVICES + depends on NETDEVICES && !UML # So far, we only have PCI, ISA, and MCA token ring devices config TR diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index f85e30190008..bad09ebdb50b 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -356,7 +356,7 @@ config PCI_HERMES config ATMEL tristate "Atmel at76c50x chipset 802.11b support" - depends on NET_RADIO + depends on NET_RADIO && (PCI || PCMCIA) select FW_LOADER select CRC32 ---help--- -- cgit v1.2.3-59-g8ed1b From 9b41046cd0ee0a57f849d6e1363f7933e363cca9 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Fri, 31 Mar 2006 02:30:33 -0800 Subject: [PATCH] Don't pass boot parameters to argv_init[] The boot cmdline is parsed in parse_early_param() and parse_args(,unknown_bootoption). And __setup() is used in obsolete_checksetup(). start_kernel() -> parse_args() -> unknown_bootoption() -> obsolete_checksetup() If __setup()'s callback (->setup_func()) returns 1 in obsolete_checksetup(), obsolete_checksetup() thinks a parameter was handled. If ->setup_func() returns 0, obsolete_checksetup() tries other ->setup_func(). If all ->setup_func() that matched a parameter returns 0, a parameter is seted to argv_init[]. Then, when runing /sbin/init or init=app, argv_init[] is passed to the app. If the app doesn't ignore those arguments, it will warning and exit. This patch fixes a wrong usage of it, however fixes obvious one only. Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/core_marvel.c | 2 +- arch/i386/kernel/apic.c | 2 +- arch/i386/kernel/cpu/mcheck/mce.c | 4 ++-- arch/i386/kernel/io_apic.c | 2 +- arch/i386/kernel/traps.c | 2 +- arch/powerpc/kernel/crash_dump.c | 4 ++-- arch/sh/kernel/cpu/init.c | 2 +- arch/x86_64/kernel/apic.c | 14 +++++++------- arch/x86_64/kernel/early_printk.c | 2 +- arch/x86_64/kernel/mce.c | 4 ++-- arch/x86_64/kernel/pmtimer.c | 2 +- arch/x86_64/kernel/setup.c | 2 +- arch/x86_64/kernel/setup64.c | 4 ++-- arch/x86_64/kernel/smpboot.c | 2 +- arch/x86_64/kernel/time.c | 4 ++-- arch/x86_64/kernel/traps.c | 4 ++-- arch/x86_64/mm/fault.c | 2 +- block/elevator.c | 2 +- drivers/acpi/ec.c | 4 ++-- drivers/block/amiflop.c | 1 + drivers/media/video/cpia_pp.c | 2 +- drivers/net/netconsole.c | 2 +- drivers/net/pcmcia/xirc2ps_cs.c | 2 +- drivers/pcmcia/vrc4171_card.c | 12 ++++++------ drivers/pcmcia/vrc4173_cardu.c | 8 ++++---- drivers/scsi/ibmmca.c | 2 +- drivers/video/console/fbcon.c | 10 +++++----- drivers/video/console/sticore.c | 4 ++-- drivers/video/fbmem.c | 2 +- drivers/video/stifb.c | 4 ++-- kernel/audit.c | 2 +- mm/memory.c | 2 +- 32 files changed, 59 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c index 44866cb26a80..7f6a98455e74 100644 --- a/arch/alpha/kernel/core_marvel.c +++ b/arch/alpha/kernel/core_marvel.c @@ -435,7 +435,7 @@ marvel_specify_io7(char *str) str = pchar; } while(*str); - return 0; + return 1; } __setup("io7=", marvel_specify_io7); diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 3fff3c62d57a..6273bf74c203 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -752,7 +752,7 @@ static int __init apic_set_verbosity(char *str) printk(KERN_WARNING "APIC Verbosity level %s not recognised" " use apic=verbose or apic=debug\n", str); - return 0; + return 1; } __setup("apic=", apic_set_verbosity); diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c index 6170af3c271a..afa0888f9a1e 100644 --- a/arch/i386/kernel/cpu/mcheck/mce.c +++ b/arch/i386/kernel/cpu/mcheck/mce.c @@ -64,13 +64,13 @@ void mcheck_init(struct cpuinfo_x86 *c) static int __init mcheck_disable(char *str) { mce_disabled = 1; - return 0; + return 1; } static int __init mcheck_enable(char *str) { mce_disabled = -1; - return 0; + return 1; } __setup("nomce", mcheck_disable); diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 3b329af4afc5..f8f132aa5472 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -644,7 +644,7 @@ failed: int __init irqbalance_disable(char *str) { irqbalance_disabled = 1; - return 0; + return 1; } __setup("noirqbalance", irqbalance_disable); diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 6b63a5aa1e46..e38527994590 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -1193,6 +1193,6 @@ void __init trap_init(void) static int __init kstack_setup(char *s) { kstack_depth_to_print = simple_strtoul(s, NULL, 0); - return 0; + return 1; } __setup("kstack=", kstack_setup); diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 211d72653ea6..764d07329716 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -61,7 +61,7 @@ static int __init parse_elfcorehdr(char *p) if (p) elfcorehdr_addr = memparse(p, &p); - return 0; + return 1; } __setup("elfcorehdr=", parse_elfcorehdr); #endif @@ -71,7 +71,7 @@ static int __init parse_savemaxmem(char *p) if (p) saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1; - return 0; + return 1; } __setup("savemaxmem=", parse_savemaxmem); diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index cf94e8ef17c5..868e68b28880 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -30,7 +30,7 @@ static int x##_disabled __initdata = 0; \ static int __init x##_setup(char *opts) \ { \ x##_disabled = 1; \ - return 0; \ + return 1; \ } \ __setup("no" __stringify(x), x##_setup); diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index d54620147e8e..100a30c40044 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -615,7 +615,7 @@ static int __init apic_set_verbosity(char *str) printk(KERN_WARNING "APIC Verbosity level %s not recognised" " use apic=verbose or apic=debug", str); - return 0; + return 1; } __setup("apic=", apic_set_verbosity); @@ -1137,35 +1137,35 @@ int __init APIC_init_uniprocessor (void) static __init int setup_disableapic(char *str) { disable_apic = 1; - return 0; + return 1; } static __init int setup_nolapic(char *str) { disable_apic = 1; - return 0; + return 1; } static __init int setup_noapictimer(char *str) { if (str[0] != ' ' && str[0] != 0) - return -1; + return 0; disable_apic_timer = 1; - return 0; + return 1; } static __init int setup_apicmaintimer(char *str) { apic_runs_main_timer = 1; nohpet = 1; - return 0; + return 1; } __setup("apicmaintimer", setup_apicmaintimer); static __init int setup_noapicmaintimer(char *str) { apic_runs_main_timer = -1; - return 0; + return 1; } __setup("noapicmaintimer", setup_noapicmaintimer); diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c index 13af920b6594..b93ef5b51980 100644 --- a/arch/x86_64/kernel/early_printk.c +++ b/arch/x86_64/kernel/early_printk.c @@ -221,7 +221,7 @@ int __init setup_early_printk(char *opt) char buf[256]; if (early_console_initialized) - return -1; + return 1; strlcpy(buf,opt,sizeof(buf)); space = strchr(buf, ' '); diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 04282ef9fbd4..10b3e348fc99 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -501,7 +501,7 @@ static struct miscdevice mce_log_device = { static int __init mcheck_disable(char *str) { mce_dont_init = 1; - return 0; + return 1; } /* mce=off disables machine check. Note you can reenable it later @@ -521,7 +521,7 @@ static int __init mcheck_enable(char *str) get_option(&str, &tolerant); else printk("mce= argument %s ignored. Please use /sys", str); - return 0; + return 1; } __setup("nomce", mcheck_disable); diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c index ee5ee4891f3d..b0444a415bd6 100644 --- a/arch/x86_64/kernel/pmtimer.c +++ b/arch/x86_64/kernel/pmtimer.c @@ -121,7 +121,7 @@ unsigned int do_gettimeoffset_pm(void) static int __init nopmtimer_setup(char *s) { pmtmr_ioport = 0; - return 0; + return 1; } __setup("nopmtimer", nopmtimer_setup); diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index d1f3e9272c05..0856ad444f90 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -540,7 +540,7 @@ void __init alternative_instructions(void) static int __init noreplacement_setup(char *s) { no_replacement = 1; - return 0; + return 1; } __setup("noreplacement", noreplacement_setup); diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index eabdb63fec31..8a691fa6d393 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -55,7 +55,7 @@ int __init nonx_setup(char *str) do_not_nx = 1; __supported_pte_mask &= ~_PAGE_NX; } - return 0; + return 1; } __setup("noexec=", nonx_setup); /* parsed early actually */ @@ -74,7 +74,7 @@ static int __init nonx32_setup(char *str) force_personality32 &= ~READ_IMPLIES_EXEC; else if (!strcmp(str, "off")) force_personality32 |= READ_IMPLIES_EXEC; - return 0; + return 1; } __setup("noexec32=", nonx32_setup); diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index ea48fa638070..71a7222cf9ce 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -353,7 +353,7 @@ static void __cpuinit tsc_sync_wait(void) static __init int notscsync_setup(char *s) { notscsync = 1; - return 0; + return 1; } __setup("notscsync", notscsync_setup); diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 473b514b66e4..ef8bc46dc140 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -1306,7 +1306,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) static int __init nohpet_setup(char *s) { nohpet = 1; - return 0; + return 1; } __setup("nohpet", nohpet_setup); @@ -1314,7 +1314,7 @@ __setup("nohpet", nohpet_setup); int __init notsc_setup(char *s) { notsc = 1; - return 0; + return 1; } __setup("notsc", notsc_setup); diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index edaa9fe654dc..6bda322d3caf 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -973,14 +973,14 @@ void __init trap_init(void) static int __init oops_dummy(char *s) { panic_on_oops = 1; - return -1; + return 1; } __setup("oops=", oops_dummy); static int __init kstack_setup(char *s) { kstack_depth_to_print = simple_strtoul(s,NULL,0); - return 0; + return 1; } __setup("kstack=", kstack_setup); diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 316c53de47bd..55250593d8c9 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c @@ -623,6 +623,6 @@ void vmalloc_sync_all(void) static int __init enable_pagefaulttrace(char *str) { page_fault_trace = 1; - return 0; + return 1; } __setup("pagefaulttrace", enable_pagefaulttrace); diff --git a/block/elevator.c b/block/elevator.c index 56c2ed06a9e2..0d6be03d929e 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -145,7 +145,7 @@ static int __init elevator_setup(char *str) strcpy(chosen_elevator, "anticipatory"); else strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); - return 0; + return 1; } __setup("elevator=", elevator_setup); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 79b09d76c180..eee0864ba300 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1572,7 +1572,7 @@ static void __exit acpi_ec_exit(void) static int __init acpi_fake_ecdt_setup(char *str) { acpi_fake_ecdt_enabled = 1; - return 0; + return 1; } __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup); @@ -1591,7 +1591,7 @@ static int __init acpi_ec_set_intr_mode(char *str) acpi_ec_driver.ops.add = acpi_ec_poll_add; } printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling"); - return 0; + return 1; } __setup("ec_intr=", acpi_ec_set_intr_mode); diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index b6e290956214..2a8af685926f 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1850,6 +1850,7 @@ static int __init amiga_floppy_setup (char *str) return 0; printk (KERN_INFO "amiflop: Setting default df0 to %x\n", n); fd_def_df0 = n; + return 1; } __setup("floppy=", amiga_floppy_setup); diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c index 3021f21aae36..0b00e6027dfb 100644 --- a/drivers/media/video/cpia_pp.c +++ b/drivers/media/video/cpia_pp.c @@ -873,7 +873,7 @@ static int __init cpia_pp_setup(char *str) parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE; } - return 0; + return 1; } __setup("cpia_pp=", cpia_pp_setup); diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index edd1b5306b16..75b35ad760de 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -94,7 +94,7 @@ static struct console netconsole = { static int option_setup(char *opt) { configured = !netpoll_parse_options(&np, opt); - return 0; + return 1; } __setup("netconsole=", option_setup); diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index eed496803fe4..e8f849e12976 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1973,7 +1973,7 @@ static int __init setup_xirc2ps_cs(char *str) MAYBE_SET(lockup_hack, 6); #undef MAYBE_SET - return 0; + return 1; } __setup("xirc2ps_cs=", setup_xirc2ps_cs); diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index 0574efd7828a..459e6e1946fd 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c @@ -634,7 +634,7 @@ static void vrc4171_remove_sockets(void) static int __devinit vrc4171_card_setup(char *options) { if (options == NULL || *options == '\0') - return 0; + return 1; if (strncmp(options, "irq:", 4) == 0) { int irq; @@ -644,7 +644,7 @@ static int __devinit vrc4171_card_setup(char *options) vrc4171_irq = irq; if (*options != ',') - return 0; + return 1; options++; } @@ -663,10 +663,10 @@ static int __devinit vrc4171_card_setup(char *options) } if (*options != ',') - return 0; + return 1; options++; } else - return 0; + return 1; } @@ -688,7 +688,7 @@ static int __devinit vrc4171_card_setup(char *options) } if (*options != ',') - return 0; + return 1; options++; if (strncmp(options, "memnoprobe", 10) == 0) @@ -700,7 +700,7 @@ static int __devinit vrc4171_card_setup(char *options) } } - return 0; + return 1; } __setup("vrc4171_card=", vrc4171_card_setup); diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c index 57f38dba0a48..6004196f7cc1 100644 --- a/drivers/pcmcia/vrc4173_cardu.c +++ b/drivers/pcmcia/vrc4173_cardu.c @@ -516,7 +516,7 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev, static int __devinit vrc4173_cardu_setup(char *options) { if (options == NULL || *options == '\0') - return 0; + return 1; if (strncmp(options, "cardu1:", 7) == 0) { options += 7; @@ -527,9 +527,9 @@ static int __devinit vrc4173_cardu_setup(char *options) } if (*options != ',') - return 0; + return 1; } else - return 0; + return 1; } if (strncmp(options, "cardu2:", 7) == 0) { @@ -538,7 +538,7 @@ static int __devinit vrc4173_cardu_setup(char *options) cardu_sockets[CARDU2].noprobe = 1; } - return 0; + return 1; } __setup("vrc4173_cardu=", vrc4173_cardu_setup); diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 3a8462e8d063..24eb59e143a9 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -2488,7 +2488,7 @@ static int option_setup(char *str) } ints[0] = i - 1; internal_ibmmca_scsi_setup(cur, ints); - return 0; + return 1; } __setup("ibmmcascsi=", option_setup); diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 041d06987861..d7351560f581 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -466,7 +466,7 @@ static int __init fb_console_setup(char *this_opt) int i, j; if (!this_opt || !*this_opt) - return 0; + return 1; while ((options = strsep(&this_opt, ",")) != NULL) { if (!strncmp(options, "font:", 5)) @@ -481,10 +481,10 @@ static int __init fb_console_setup(char *this_opt) options++; } if (*options != ',') - return 0; + return 1; options++; } else - return 0; + return 1; } if (!strncmp(options, "map:", 4)) { @@ -496,7 +496,7 @@ static int __init fb_console_setup(char *this_opt) con2fb_map_boot[i] = (options[j++]-'0') % FB_MAX; } - return 0; + return 1; } if (!strncmp(options, "vc:", 3)) { @@ -518,7 +518,7 @@ static int __init fb_console_setup(char *this_opt) rotate = 0; } } - return 0; + return 1; } __setup("fbcon=", fb_console_setup); diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index d6041e781aca..74ac2acaf72c 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -275,7 +275,7 @@ static int __init sti_setup(char *str) if (str) strlcpy (default_sti_path, str, sizeof (default_sti_path)); - return 0; + return 1; } /* Assuming the machine has multiple STI consoles (=graphic cards) which @@ -321,7 +321,7 @@ static int __init sti_font_setup(char *str) i++; } - return 0; + return 1; } /* The optional linux kernel parameter "sti_font" defines which font diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index b1a8dca76430..944855b3e4af 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1588,7 +1588,7 @@ static int __init video_setup(char *options) } } - return 0; + return 1; } __setup("video=", video_setup); #endif diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 8d5f35676f9a..4a292aae6eb2 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1378,7 +1378,7 @@ stifb_setup(char *options) int i; if (!options || !*options) - return 0; + return 1; if (strncmp(options, "off", 3) == 0) { stifb_disabled = 1; @@ -1393,7 +1393,7 @@ stifb_setup(char *options) stifb_bpp_pref[i] = simple_strtoul(options, &options, 10); } } - return 0; + return 1; } __setup("stifb=", stifb_setup); diff --git a/kernel/audit.c b/kernel/audit.c index 04fe2e301b61..c8ccbd09048f 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -578,7 +578,7 @@ static int __init audit_enable(char *str) audit_initialized ? "" : " (after initialization)"); if (audit_initialized) audit_enabled = audit_default; - return 0; + return 1; } __setup("audit=", audit_enable); diff --git a/mm/memory.c b/mm/memory.c index 8d8f52569f32..0ec7bc644271 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -87,7 +87,7 @@ int randomize_va_space __read_mostly = 1; static int __init disable_randmaps(char *s) { randomize_va_space = 0; - return 0; + return 1; } __setup("norandmaps", disable_randmaps); -- cgit v1.2.3-59-g8ed1b From da960a6ad1864dd1636cb9b0330d7bb7408aed45 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 31 Mar 2006 02:30:34 -0800 Subject: [PATCH] edac_752x needs CONFIG_HOTPLUG EDAC_752X uses pci_scan_single_device(), which is only available if CONFIG_HOTPLUG is enabled, so limit this driver with HOTPLUG. Signed-off-by: Randy Dunlap Cc: Dave Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index b582d0cdc24f..4f0898400c6d 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -71,7 +71,7 @@ config EDAC_E7XXX config EDAC_E752X tristate "Intel e752x (e7520, e7525, e7320)" - depends on EDAC_MM_EDAC && PCI && X86 + depends on EDAC_MM_EDAC && PCI && X86 && HOTPLUG help Support for error detection and correction on the Intel E7520, E7525, E7320 server chipsets. -- cgit v1.2.3-59-g8ed1b From ee37df7877eeaa16d7761cce64854110a7c17ad9 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 31 Mar 2006 02:30:35 -0800 Subject: [PATCH] make tty_insert_flip_string a non-GPL export Alan sayeth "Based on Linus original comments about _GPL we should export tty_insert_flip_char as EXPORT_SYMBOL because it used to be EXPORT_SYMBOL equivalent (trivial inline). The other features are new extensions are were not available to drivers before so need not be provided except as _GPL functionality as far as I can see." Addresses http://bugzilla.kernel.org/show_bug.cgi?id=6294 Cc: Alan Cox Cc: Russell King Cc: Paul Fulghum Cc: Philippe Vouters Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 0bfd1b63662e..98b126c2ded8 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -376,7 +376,7 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, s return copied; } -EXPORT_SYMBOL_GPL(tty_insert_flip_string); +EXPORT_SYMBOL(tty_insert_flip_string); int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size) { -- cgit v1.2.3-59-g8ed1b From 453823ba08ba762b3d58934b6dce75edce37169e Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 31 Mar 2006 02:30:39 -0800 Subject: [PATCH] IPMI: fix startup race condition Matt Domsch noticed a startup race with the IPMI kernel thread, it was possible (though extraordinarly unlikely) that a message could come in before the upper layer was ready to handle it. This patch splits the startup processing of an IPMI interface into two parts, one to get ready and one to actually start the processes to receive messages from the interface. [akpm@osdl.org: cleanups] Signed-off-by: Corey Minyard Cc: Matt Domsch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 9 +++--- drivers/char/ipmi/ipmi_si_intf.c | 59 +++++++++++++++++++++++-------------- include/linux/ipmi_smi.h | 16 ++++++++-- 3 files changed, 54 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 40eb005b9d77..a0b6f797d97d 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -2305,8 +2305,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, void *send_info, struct ipmi_device_id *device_id, struct device *si_dev, - unsigned char slave_addr, - ipmi_smi_t *new_intf) + unsigned char slave_addr) { int i, j; int rv; @@ -2388,9 +2387,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, if (rv) goto out; - /* FIXME - this is an ugly kludge, this sets the intf for the - caller before sending any messages with it. */ - *new_intf = intf; + rv = handlers->start_processing(send_info, intf); + if (rv) + goto out; get_guid(intf); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 35fbd4d8ed4b..d48d86bd2c2b 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -972,10 +972,37 @@ static irqreturn_t si_bt_irq_handler(int irq, void *data, struct pt_regs *regs) return si_irq_handler(irq, data, regs); } +static int smi_start_processing(void *send_info, + ipmi_smi_t intf) +{ + struct smi_info *new_smi = send_info; + + new_smi->intf = intf; + + /* Set up the timer that drives the interface. */ + setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi); + new_smi->last_timeout_jiffies = jiffies; + mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES); + + if (new_smi->si_type != SI_BT) { + new_smi->thread = kthread_run(ipmi_thread, new_smi, + "kipmi%d", new_smi->intf_num); + if (IS_ERR(new_smi->thread)) { + printk(KERN_NOTICE "ipmi_si_intf: Could not start" + " kernel thread due to error %ld, only using" + " timers to drive the interface\n", + PTR_ERR(new_smi->thread)); + new_smi->thread = NULL; + } + } + + return 0; +} static struct ipmi_smi_handlers handlers = { .owner = THIS_MODULE, + .start_processing = smi_start_processing, .sender = sender, .request_events = request_events, .set_run_to_completion = set_run_to_completion, @@ -2162,9 +2189,13 @@ static void setup_xaction_handlers(struct smi_info *smi_info) static inline void wait_for_timer_and_thread(struct smi_info *smi_info) { - if (smi_info->thread != NULL && smi_info->thread != ERR_PTR(-ENOMEM)) - kthread_stop(smi_info->thread); - del_timer_sync(&smi_info->si_timer); + if (smi_info->intf) { + /* The timer and thread are only running if the + interface has been started up and registered. */ + if (smi_info->thread != NULL) + kthread_stop(smi_info->thread); + del_timer_sync(&smi_info->si_timer); + } } static struct ipmi_default_vals @@ -2341,21 +2372,6 @@ static int try_smi_init(struct smi_info *new_smi) if (new_smi->irq) new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ; - /* The ipmi_register_smi() code does some operations to - determine the channel information, so we must be ready to - handle operations before it is called. This means we have - to stop the timer if we get an error after this point. */ - init_timer(&(new_smi->si_timer)); - new_smi->si_timer.data = (long) new_smi; - new_smi->si_timer.function = smi_timeout; - new_smi->last_timeout_jiffies = jiffies; - new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; - - add_timer(&(new_smi->si_timer)); - if (new_smi->si_type != SI_BT) - new_smi->thread = kthread_run(ipmi_thread, new_smi, - "kipmi%d", new_smi->intf_num); - if (!new_smi->dev) { /* If we don't already have a device from something * else (like PCI), then register a new one. */ @@ -2365,7 +2381,7 @@ static int try_smi_init(struct smi_info *new_smi) printk(KERN_ERR "ipmi_si_intf:" " Unable to allocate platform device\n"); - goto out_err_stop_timer; + goto out_err; } new_smi->dev = &new_smi->pdev->dev; new_smi->dev->driver = &ipmi_driver; @@ -2377,7 +2393,7 @@ static int try_smi_init(struct smi_info *new_smi) " Unable to register system interface device:" " %d\n", rv); - goto out_err_stop_timer; + goto out_err; } new_smi->dev_registered = 1; } @@ -2386,8 +2402,7 @@ static int try_smi_init(struct smi_info *new_smi) new_smi, &new_smi->device_id, new_smi->dev, - new_smi->slave_addr, - &(new_smi->intf)); + new_smi->slave_addr); if (rv) { printk(KERN_ERR "ipmi_si: Unable to register device: error %d\n", diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index 53571288a9fc..6d9c7e4da472 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h @@ -82,6 +82,13 @@ struct ipmi_smi_handlers { struct module *owner; + /* The low-level interface cannot start sending messages to + the upper layer until this function is called. This may + not be NULL, the lower layer must take the interface from + this call. */ + int (*start_processing)(void *send_info, + ipmi_smi_t new_intf); + /* Called to enqueue an SMI message to be sent. This operation is not allowed to fail. If an error occurs, it should report back the error in a received message. It may @@ -157,13 +164,16 @@ static inline void ipmi_demangle_device_id(unsigned char *data, } /* Add a low-level interface to the IPMI driver. Note that if the - interface doesn't know its slave address, it should pass in zero. */ + interface doesn't know its slave address, it should pass in zero. + The low-level interface should not deliver any messages to the + upper layer until the start_processing() function in the handlers + is called, and the lower layer must get the interface from that + call. */ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, void *send_info, struct ipmi_device_id *device_id, struct device *dev, - unsigned char slave_addr, - ipmi_smi_t *intf); + unsigned char slave_addr); /* * Remove a low-level interface from the IPMI driver. This will -- cgit v1.2.3-59-g8ed1b From 8a3628d53fe5eb1d1401dd1ce16655182c1c5ffc Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 31 Mar 2006 02:30:40 -0800 Subject: [PATCH] IPMI: tidy up various things Tidy up various coding standard things, mostly removing the space after !, but also break some long lines and fix a few other spacing inconsistencies. Also fixes some bad error reporting when deleting an IPMI user. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_kcs_sm.c | 8 +++---- drivers/char/ipmi/ipmi_msghandler.c | 48 +++++++++++++++++++------------------ drivers/char/ipmi/ipmi_poweroff.c | 2 +- drivers/char/ipmi/ipmi_si_intf.c | 2 +- drivers/char/ipmi/ipmi_watchdog.c | 8 +++---- 5 files changed, 35 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index da1554194d3d..2062675f9e99 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c @@ -227,7 +227,7 @@ static inline int check_ibf(struct si_sm_data *kcs, unsigned char status, static inline int check_obf(struct si_sm_data *kcs, unsigned char status, long time) { - if (! GET_STATUS_OBF(status)) { + if (!GET_STATUS_OBF(status)) { kcs->obf_timeout -= time; if (kcs->obf_timeout < 0) { start_error_recovery(kcs, "OBF not ready in time"); @@ -407,7 +407,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) } if (state == KCS_READ_STATE) { - if (! check_obf(kcs, status, time)) + if (!check_obf(kcs, status, time)) return SI_SM_CALL_WITH_DELAY; read_next_byte(kcs); } else { @@ -447,7 +447,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) "Not in read state for error2"); break; } - if (! check_obf(kcs, status, time)) + if (!check_obf(kcs, status, time)) return SI_SM_CALL_WITH_DELAY; clear_obf(kcs, status); @@ -462,7 +462,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) break; } - if (! check_obf(kcs, status, time)) + if (!check_obf(kcs, status, time)) return SI_SM_CALL_WITH_DELAY; clear_obf(kcs, status); diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index a0b6f797d97d..c0c862cce1c3 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -557,7 +557,7 @@ unsigned int ipmi_addr_length(int addr_type) static void deliver_response(struct ipmi_recv_msg *msg) { - if (! msg->user) { + if (!msg->user) { ipmi_smi_t intf = msg->user_msg_data; unsigned long flags; @@ -598,11 +598,11 @@ static int intf_next_seq(ipmi_smi_t intf, (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq; i = (i+1)%IPMI_IPMB_NUM_SEQ) { - if (! intf->seq_table[i].inuse) + if (!intf->seq_table[i].inuse) break; } - if (! intf->seq_table[i].inuse) { + if (!intf->seq_table[i].inuse) { intf->seq_table[i].recv_msg = recv_msg; /* Start with the maximum timeout, when the send response @@ -763,7 +763,7 @@ int ipmi_create_user(unsigned int if_num, } new_user = kmalloc(sizeof(*new_user), GFP_KERNEL); - if (! new_user) + if (!new_user) return -ENOMEM; spin_lock_irqsave(&interfaces_lock, flags); @@ -819,14 +819,13 @@ static void free_user(struct kref *ref) int ipmi_destroy_user(ipmi_user_t user) { - int rv = -ENODEV; ipmi_smi_t intf = user->intf; int i; unsigned long flags; struct cmd_rcvr *rcvr; struct cmd_rcvr *rcvrs = NULL; - user->valid = 1; + user->valid = 0; /* Remove the user from the interface's sequence table. */ spin_lock_irqsave(&intf->seq_lock, flags); @@ -871,7 +870,7 @@ int ipmi_destroy_user(ipmi_user_t user) kref_put(&user->refcount, free_user); - return rv; + return 0; } void ipmi_get_version(ipmi_user_t user, @@ -936,7 +935,8 @@ int ipmi_set_gets_events(ipmi_user_t user, int val) if (val) { /* Deliver any queued events. */ - list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) { + list_for_each_entry_safe(msg, msg2, &intf->waiting_events, + link) { list_del(&msg->link); list_add_tail(&msg->link, &msgs); } @@ -978,7 +978,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL); - if (! rcvr) + if (!rcvr) return -ENOMEM; rcvr->cmd = cmd; rcvr->netfn = netfn; @@ -1514,7 +1514,7 @@ int ipmi_request_settime(ipmi_user_t user, unsigned char saddr, lun; int rv; - if (! user) + if (!user) return -EINVAL; rv = check_addr(user->intf, addr, &saddr, &lun); if (rv) @@ -1545,7 +1545,7 @@ int ipmi_request_supply_msgs(ipmi_user_t user, unsigned char saddr, lun; int rv; - if (! user) + if (!user) return -EINVAL; rv = check_addr(user->intf, addr, &saddr, &lun); if (rv) @@ -1570,7 +1570,7 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off, char *out = (char *) page; ipmi_smi_t intf = data; int i; - int rv= 0; + int rv = 0; for (i = 0; i < IPMI_MAX_CHANNELS; i++) rv += sprintf(out+rv, "%x ", intf->channels[i].address); @@ -1989,7 +1989,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf) } else { bmc->dev = platform_device_alloc("ipmi_bmc", bmc->id.device_id); - if (! bmc->dev) { + if (!bmc->dev) { printk(KERN_ERR "ipmi_msghandler:" " Unable to allocate platform device\n"); @@ -2621,7 +2621,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, spin_unlock_irqrestore(&intf->counter_lock, flags); recv_msg = ipmi_alloc_recv_msg(); - if (! recv_msg) { + if (!recv_msg) { /* We couldn't allocate memory for the message, so requeue it for handling later. */ @@ -2776,7 +2776,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, spin_unlock_irqrestore(&intf->counter_lock, flags); recv_msg = ipmi_alloc_recv_msg(); - if (! recv_msg) { + if (!recv_msg) { /* We couldn't allocate memory for the message, so requeue it for handling later. */ @@ -2868,13 +2868,14 @@ static int handle_read_event_rsp(ipmi_smi_t intf, events. */ rcu_read_lock(); list_for_each_entry_rcu(user, &intf->users, link) { - if (! user->gets_events) + if (!user->gets_events) continue; recv_msg = ipmi_alloc_recv_msg(); - if (! recv_msg) { + if (!recv_msg) { rcu_read_unlock(); - list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) { + list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, + link) { list_del(&recv_msg->link); ipmi_free_recv_msg(recv_msg); } @@ -2904,7 +2905,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf, /* No one to receive the message, put it in queue if there's not already too many things in the queue. */ recv_msg = ipmi_alloc_recv_msg(); - if (! recv_msg) { + if (!recv_msg) { /* We couldn't allocate memory for the message, so requeue it for handling later. */ @@ -3189,7 +3190,7 @@ void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) rcu_read_lock(); list_for_each_entry_rcu(user, &intf->users, link) { - if (! user->handler->ipmi_watchdog_pretimeout) + if (!user->handler->ipmi_watchdog_pretimeout) continue; user->handler->ipmi_watchdog_pretimeout(user->handler_data); @@ -3277,7 +3278,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, ent->seqid); - if (! smi_msg) + if (!smi_msg) return; spin_unlock_irqrestore(&intf->seq_lock, *flags); @@ -3313,8 +3314,9 @@ static void ipmi_timeout_handler(long timeout_period) /* See if any waiting messages need to be processed. */ spin_lock_irqsave(&intf->waiting_msgs_lock, flags); - list_for_each_entry_safe(smi_msg, smi_msg2, &intf->waiting_msgs, link) { - if (! handle_new_recv_msg(intf, smi_msg)) { + list_for_each_entry_safe(smi_msg, smi_msg2, + &intf->waiting_msgs, link) { + if (!handle_new_recv_msg(intf, smi_msg)) { list_del(&smi_msg->link); ipmi_free_smi_msg(smi_msg); } else { diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 786a2802ca34..d0b5c08e7b4e 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -346,7 +346,7 @@ static int ipmi_dell_chassis_detect (ipmi_user_t user) { const char ipmi_version_major = ipmi_version & 0xF; const char ipmi_version_minor = (ipmi_version >> 4) & 0xF; - const char mfr[3]=DELL_IANA_MFR_ID; + const char mfr[3] = DELL_IANA_MFR_ID; if (!memcmp(mfr, &mfg_id, sizeof(mfr)) && ipmi_version_major <= 1 && ipmi_version_minor < 5) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index d48d86bd2c2b..2da5845a383a 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -803,7 +803,7 @@ static int ipmi_thread(void *data) set_user_nice(current, 19); while (!kthread_should_stop()) { spin_lock_irqsave(&(smi_info->si_lock), flags); - smi_result=smi_event_handler(smi_info, 0); + smi_result = smi_event_handler(smi_info, 0); spin_unlock_irqrestore(&(smi_info->si_lock), flags); if (smi_result == SI_SM_CALL_WITHOUT_DELAY) { /* do nothing */ diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 7ece9f3c8f70..2872c9575528 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -589,7 +589,7 @@ static void panic_halt_ipmi_heartbeat(void) 1); } -static struct watchdog_info ident= +static struct watchdog_info ident = { .options = 0, /* WDIOF_SETTIMEOUT, */ .firmware_version = 1, @@ -790,13 +790,13 @@ static int ipmi_fasync(int fd, struct file *file, int on) static int ipmi_close(struct inode *ino, struct file *filep) { - if (iminor(ino)==WATCHDOG_MINOR) - { + if (iminor(ino) == WATCHDOG_MINOR) { if (expect_close == 42) { ipmi_watchdog_state = WDOG_TIMEOUT_NONE; ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); } else { - printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + printk(KERN_CRIT PFX + "Unexpected close, not stopping watchdog!\n"); ipmi_heartbeat(); } clear_bit(0, &ipmi_wdog_open); -- cgit v1.2.3-59-g8ed1b From d6dfd1310d3562698fd7c3c086f6c239f96394ac Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 31 Mar 2006 02:30:41 -0800 Subject: [PATCH] IPMI: convert from semaphores to mutexes Convert the remaining semaphores to mutexes in the IPMI driver. The watchdog was using a semaphore as a real semaphore (for IPC), so the conversion there required adding a completion. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_devintf.c | 18 ++++++------- drivers/char/ipmi/ipmi_msghandler.c | 23 ++++++++-------- drivers/char/ipmi/ipmi_si_intf.c | 24 ++++++++--------- drivers/char/ipmi/ipmi_watchdog.c | 53 +++++++++++++++++++++---------------- 4 files changed, 63 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 932feedda262..e1c95374984c 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include @@ -55,7 +55,7 @@ struct ipmi_file_private struct file *file; struct fasync_struct *fasync_queue; wait_queue_head_t wait; - struct semaphore recv_sem; + struct mutex recv_mutex; int default_retries; unsigned int default_retry_time_ms; }; @@ -141,7 +141,7 @@ static int ipmi_open(struct inode *inode, struct file *file) INIT_LIST_HEAD(&(priv->recv_msgs)); init_waitqueue_head(&priv->wait); priv->fasync_queue = NULL; - sema_init(&(priv->recv_sem), 1); + mutex_init(&priv->recv_mutex); /* Use the low-level defaults. */ priv->default_retries = -1; @@ -285,15 +285,15 @@ static int ipmi_ioctl(struct inode *inode, break; } - /* We claim a semaphore because we don't want two + /* We claim a mutex because we don't want two users getting something from the queue at a time. Since we have to release the spinlock before we can copy the data to the user, it's possible another user will grab something from the queue, too. Then the messages might get out of order if something fails and the message gets put back onto the - queue. This semaphore prevents that problem. */ - down(&(priv->recv_sem)); + queue. This mutex prevents that problem. */ + mutex_lock(&priv->recv_mutex); /* Grab the message off the list. */ spin_lock_irqsave(&(priv->recv_msg_lock), flags); @@ -352,7 +352,7 @@ static int ipmi_ioctl(struct inode *inode, goto recv_putback_on_err; } - up(&(priv->recv_sem)); + mutex_unlock(&priv->recv_mutex); ipmi_free_recv_msg(msg); break; @@ -362,11 +362,11 @@ static int ipmi_ioctl(struct inode *inode, spin_lock_irqsave(&(priv->recv_msg_lock), flags); list_add(entry, &(priv->recv_msgs)); spin_unlock_irqrestore(&(priv->recv_msg_lock), flags); - up(&(priv->recv_sem)); + mutex_unlock(&priv->recv_mutex); break; recv_err: - up(&(priv->recv_sem)); + mutex_unlock(&priv->recv_mutex); break; } diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index c0c862cce1c3..0ded046d5aa8 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -234,7 +235,7 @@ struct ipmi_smi /* The list of command receivers that are registered for commands on this interface. */ - struct semaphore cmd_rcvrs_lock; + struct mutex cmd_rcvrs_mutex; struct list_head cmd_rcvrs; /* Events that were queues because no one was there to receive @@ -387,10 +388,10 @@ static void clean_up_interface_data(ipmi_smi_t intf) /* Wholesale remove all the entries from the list in the * interface and wait for RCU to know that none are in use. */ - down(&intf->cmd_rcvrs_lock); + mutex_lock(&intf->cmd_rcvrs_mutex); list_add_rcu(&list, &intf->cmd_rcvrs); list_del_rcu(&intf->cmd_rcvrs); - up(&intf->cmd_rcvrs_lock); + mutex_unlock(&intf->cmd_rcvrs_mutex); synchronize_rcu(); list_for_each_entry_safe(rcvr, rcvr2, &list, link) @@ -846,7 +847,7 @@ int ipmi_destroy_user(ipmi_user_t user) * since other things may be using it till we do * synchronize_rcu()) then free everything in that list. */ - down(&intf->cmd_rcvrs_lock); + mutex_lock(&intf->cmd_rcvrs_mutex); list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { if (rcvr->user == user) { list_del_rcu(&rcvr->link); @@ -854,7 +855,7 @@ int ipmi_destroy_user(ipmi_user_t user) rcvrs = rcvr; } } - up(&intf->cmd_rcvrs_lock); + mutex_unlock(&intf->cmd_rcvrs_mutex); synchronize_rcu(); while (rcvrs) { rcvr = rcvrs; @@ -984,7 +985,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, rcvr->netfn = netfn; rcvr->user = user; - down(&intf->cmd_rcvrs_lock); + mutex_lock(&intf->cmd_rcvrs_mutex); /* Make sure the command/netfn is not already registered. */ entry = find_cmd_rcvr(intf, netfn, cmd); if (entry) { @@ -995,7 +996,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); out_unlock: - up(&intf->cmd_rcvrs_lock); + mutex_unlock(&intf->cmd_rcvrs_mutex); if (rv) kfree(rcvr); @@ -1009,17 +1010,17 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, ipmi_smi_t intf = user->intf; struct cmd_rcvr *rcvr; - down(&intf->cmd_rcvrs_lock); + mutex_lock(&intf->cmd_rcvrs_mutex); /* Make sure the command/netfn is not already registered. */ rcvr = find_cmd_rcvr(intf, netfn, cmd); if ((rcvr) && (rcvr->user == user)) { list_del_rcu(&rcvr->link); - up(&intf->cmd_rcvrs_lock); + mutex_unlock(&intf->cmd_rcvrs_mutex); synchronize_rcu(); kfree(rcvr); return 0; } else { - up(&intf->cmd_rcvrs_lock); + mutex_unlock(&intf->cmd_rcvrs_mutex); return -ENOENT; } } @@ -2365,7 +2366,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, spin_lock_init(&intf->events_lock); INIT_LIST_HEAD(&intf->waiting_events); intf->waiting_events_count = 0; - init_MUTEX(&intf->cmd_rcvrs_lock); + mutex_init(&intf->cmd_rcvrs_mutex); INIT_LIST_HEAD(&intf->cmd_rcvrs); init_waitqueue_head(&intf->waitq); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 2da5845a383a..a86c0f29953e 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1014,7 +1014,7 @@ static struct ipmi_smi_handlers handlers = #define SI_MAX_PARMS 4 static LIST_HEAD(smi_infos); -static DECLARE_MUTEX(smi_infos_lock); +static DEFINE_MUTEX(smi_infos_lock); static int smi_num; /* Used to sequence the SMIs */ #define DEFAULT_REGSPACING 1 @@ -2276,7 +2276,7 @@ static int try_smi_init(struct smi_info *new_smi) new_smi->slave_addr, new_smi->irq); } - down(&smi_infos_lock); + mutex_lock(&smi_infos_lock); if (!is_new_interface(new_smi)) { printk(KERN_WARNING "ipmi_si: duplicate interface\n"); rv = -EBUSY; @@ -2432,7 +2432,7 @@ static int try_smi_init(struct smi_info *new_smi) list_add_tail(&new_smi->link, &smi_infos); - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]); @@ -2469,7 +2469,7 @@ static int try_smi_init(struct smi_info *new_smi) kfree(new_smi); - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); return rv; } @@ -2527,26 +2527,26 @@ static __devinit int init_ipmi_si(void) #endif if (si_trydefaults) { - down(&smi_infos_lock); + mutex_lock(&smi_infos_lock); if (list_empty(&smi_infos)) { /* No BMC was found, try defaults. */ - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); default_find_bmc(); } else { - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); } } - down(&smi_infos_lock); + mutex_lock(&smi_infos_lock); if (list_empty(&smi_infos)) { - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); #ifdef CONFIG_PCI pci_unregister_driver(&ipmi_pci_driver); #endif printk("ipmi_si: Unable to find any System Interface(s)\n"); return -ENODEV; } else { - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); return 0; } } @@ -2622,10 +2622,10 @@ static __exit void cleanup_ipmi_si(void) pci_unregister_driver(&ipmi_pci_driver); #endif - down(&smi_infos_lock); + mutex_lock(&smi_infos_lock); list_for_each_entry_safe(e, tmp_e, &smi_infos, link) cleanup_one_si(e); - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); driver_unregister(&ipmi_driver); } diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 2872c9575528..2d11ddd99e55 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -303,21 +304,22 @@ static int ipmi_heartbeat(void); static void panic_halt_ipmi_heartbeat(void); -/* We use a semaphore to make sure that only one thing can send a set +/* We use a mutex to make sure that only one thing can send a set timeout at one time, because we only have one copy of the data. - The semaphore is claimed when the set_timeout is sent and freed + The mutex is claimed when the set_timeout is sent and freed when both messages are free. */ static atomic_t set_timeout_tofree = ATOMIC_INIT(0); -static DECLARE_MUTEX(set_timeout_lock); +static DEFINE_MUTEX(set_timeout_lock); +static DECLARE_COMPLETION(set_timeout_wait); static void set_timeout_free_smi(struct ipmi_smi_msg *msg) { if (atomic_dec_and_test(&set_timeout_tofree)) - up(&set_timeout_lock); + complete(&set_timeout_wait); } static void set_timeout_free_recv(struct ipmi_recv_msg *msg) { if (atomic_dec_and_test(&set_timeout_tofree)) - up(&set_timeout_lock); + complete(&set_timeout_wait); } static struct ipmi_smi_msg set_timeout_smi_msg = { @@ -399,7 +401,7 @@ static int ipmi_set_timeout(int do_heartbeat) /* We can only send one of these at a time. */ - down(&set_timeout_lock); + mutex_lock(&set_timeout_lock); atomic_set(&set_timeout_tofree, 2); @@ -407,16 +409,21 @@ static int ipmi_set_timeout(int do_heartbeat) &set_timeout_recv_msg, &send_heartbeat_now); if (rv) { - up(&set_timeout_lock); - } else { - if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) - || ((send_heartbeat_now) - && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) - { - rv = ipmi_heartbeat(); - } + mutex_unlock(&set_timeout_lock); + goto out; + } + + wait_for_completion(&set_timeout_wait); + + if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) + || ((send_heartbeat_now) + && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) + { + rv = ipmi_heartbeat(); } + mutex_unlock(&set_timeout_lock); +out: return rv; } @@ -458,17 +465,17 @@ static void panic_halt_ipmi_set_timeout(void) The semaphore is claimed when the set_timeout is sent and freed when both messages are free. */ static atomic_t heartbeat_tofree = ATOMIC_INIT(0); -static DECLARE_MUTEX(heartbeat_lock); -static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock); +static DEFINE_MUTEX(heartbeat_lock); +static DECLARE_COMPLETION(heartbeat_wait); static void heartbeat_free_smi(struct ipmi_smi_msg *msg) { if (atomic_dec_and_test(&heartbeat_tofree)) - up(&heartbeat_wait_lock); + complete(&heartbeat_wait); } static void heartbeat_free_recv(struct ipmi_recv_msg *msg) { if (atomic_dec_and_test(&heartbeat_tofree)) - up(&heartbeat_wait_lock); + complete(&heartbeat_wait); } static struct ipmi_smi_msg heartbeat_smi_msg = { @@ -511,14 +518,14 @@ static int ipmi_heartbeat(void) return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); } - down(&heartbeat_lock); + mutex_lock(&heartbeat_lock); atomic_set(&heartbeat_tofree, 2); /* Don't reset the timer if we have the timer turned off, that re-enables the watchdog. */ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) { - up(&heartbeat_lock); + mutex_unlock(&heartbeat_lock); return 0; } @@ -539,14 +546,14 @@ static int ipmi_heartbeat(void) &heartbeat_recv_msg, 1); if (rv) { - up(&heartbeat_lock); + mutex_unlock(&heartbeat_lock); printk(KERN_WARNING PFX "heartbeat failure: %d\n", rv); return rv; } /* Wait for the heartbeat to be sent. */ - down(&heartbeat_wait_lock); + wait_for_completion(&heartbeat_wait); if (heartbeat_recv_msg.msg.data[0] != 0) { /* Got an error in the heartbeat response. It was already @@ -555,7 +562,7 @@ static int ipmi_heartbeat(void) rv = -EINVAL; } - up(&heartbeat_lock); + mutex_unlock(&heartbeat_lock); return rv; } -- cgit v1.2.3-59-g8ed1b From 0000754c27f07d5656eff17367c05dc4cfb7d965 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 31 Mar 2006 02:30:47 -0800 Subject: [PATCH] "3c59x collision statistics fix" fix The pre-2.6.16 patch "3c59x collision statistics fix" accidentally caused vortex_error() to not run iowrite16(TxEnable, ioaddr + EL3_CMD) if we got a maxCollisions interrupt but MAX_COLLISION_RESET is not set. Thanks to Pete Clements for reporting and testing. Acked-by: Steffen Klassert Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 70f63891b19c..51129079853b 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -2083,16 +2083,14 @@ vortex_error(struct net_device *dev, int status) } if (tx_status & 0x14) vp->stats.tx_fifo_errors++; if (tx_status & 0x38) vp->stats.tx_aborted_errors++; + if (tx_status & 0x08) vp->xstats.tx_max_collisions++; iowrite8(0, ioaddr + TxStatus); if (tx_status & 0x30) { /* txJabber or txUnderrun */ do_tx_reset = 1; - } else if (tx_status & 0x08) { /* maxCollisions */ - vp->xstats.tx_max_collisions++; - if (vp->drv_flags & MAX_COLLISION_RESET) { - do_tx_reset = 1; - reset_mask = 0x0108; /* Reset interface logic, but not download logic */ - } - } else { /* Merely re-enable the transmitter. */ + } else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) { /* maxCollisions */ + do_tx_reset = 1; + reset_mask = 0x0108; /* Reset interface logic, but not download logic */ + } else { /* Merely re-enable the transmitter. */ iowrite16(TxEnable, ioaddr + EL3_CMD); } } -- cgit v1.2.3-59-g8ed1b From 09ce3512dcad0ad1d07eee0dc5ebb6d037c39c16 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Fri, 31 Mar 2006 02:30:48 -0800 Subject: [PATCH] 3c59x: fix networking for 10base2 NICs The "3c59x: use mii_check_media" patch introduced a netif_carrier_off in vortex_up. 10base2 stoped working because of this. This is removed. Tx/Rx reset is back in vortex_up because the 3c900B-Combo stops working after changing from half duplex to full duplex when Tx/Rx reset is done with vortex_timer. Also brought back some mii stuff to be sure that it does not break something else. Thanks to Pete Clements for reporting and testing. Signed-off-by: Steffen Klassert Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 51129079853b..274b0138d442 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -788,7 +788,7 @@ struct vortex_private { int options; /* User-settable misc. driver options. */ unsigned int media_override:4, /* Passed-in media type. */ default_media:4, /* Read from the EEPROM/Wn3_Config. */ - full_duplex:1, force_fd:1, autoselect:1, + full_duplex:1, autoselect:1, bus_master:1, /* Vortex can only do a fragment bus-m. */ full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */ flow_ctrl:1, /* Use 802.3x flow control (PAUSE only) */ @@ -1633,12 +1633,6 @@ vortex_set_duplex(struct net_device *dev) ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), ioaddr + Wn3_MAC_Ctrl); - - issue_and_wait(dev, TxReset); - /* - * Don't reset the PHY - that upsets autonegotiation during DHCP operations. - */ - issue_and_wait(dev, RxReset|0x04); } static void vortex_check_media(struct net_device *dev, unsigned int init) @@ -1663,7 +1657,7 @@ vortex_up(struct net_device *dev) struct vortex_private *vp = netdev_priv(dev); void __iomem *ioaddr = vp->ioaddr; unsigned int config; - int i; + int i, mii_reg1, mii_reg5; if (VORTEX_PCI(vp)) { pci_set_power_state(VORTEX_PCI(vp), PCI_D0); /* Go active */ @@ -1723,14 +1717,23 @@ vortex_up(struct net_device *dev) printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config); iowrite32(config, ioaddr + Wn3_Config); - netif_carrier_off(dev); if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { EL3WINDOW(4); + mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR); + mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA); + vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0); + vortex_check_media(dev, 1); } else vortex_set_duplex(dev); + issue_and_wait(dev, TxReset); + /* + * Don't reset the PHY - that upsets autonegotiation during DHCP operations. + */ + issue_and_wait(dev, RxReset|0x04); + iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD); -- cgit v1.2.3-59-g8ed1b From b0b4ed728cdd0c7204392b0c18857e4a99917aa5 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 31 Mar 2006 02:30:56 -0800 Subject: [PATCH] drivers/char/[i]stallion: Clean up kmalloc usage Delete two useless kmalloc wrappers and use kmalloc/kzalloc. Some weird NULL checks are also simplified. Signed-off-by: Tobias Klauser Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/istallion.c | 32 +++++++++----------------------- drivers/char/stallion.c | 46 +++++++++++++++------------------------------- 2 files changed, 24 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index e5247f85a446..ef20c1fc9c4c 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -706,7 +706,6 @@ static int stli_portcmdstats(stliport_t *portp); static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp); static int stli_getportstruct(stliport_t __user *arg); static int stli_getbrdstruct(stlibrd_t __user *arg); -static void *stli_memalloc(int len); static stlibrd_t *stli_allocbrd(void); static void stli_ecpinit(stlibrd_t *brdp); @@ -997,17 +996,6 @@ static int stli_parsebrd(stlconf_t *confp, char **argp) /*****************************************************************************/ -/* - * Local driver kernel malloc routine. - */ - -static void *stli_memalloc(int len) -{ - return((void *) kmalloc(len, GFP_KERNEL)); -} - -/*****************************************************************************/ - static int stli_open(struct tty_struct *tty, struct file *filp) { stlibrd_t *brdp; @@ -3227,13 +3215,12 @@ static int stli_initports(stlibrd_t *brdp) #endif for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { - portp = (stliport_t *) stli_memalloc(sizeof(stliport_t)); - if (portp == (stliport_t *) NULL) { + portp = kzalloc(sizeof(stliport_t), GFP_KERNEL); + if (!portp) { printk("STALLION: failed to allocate port structure\n"); continue; } - memset(portp, 0, sizeof(stliport_t)); portp->magic = STLI_PORTMAGIC; portp->portnr = i; portp->brdnr = brdp->brdnr; @@ -4610,14 +4597,13 @@ static stlibrd_t *stli_allocbrd(void) { stlibrd_t *brdp; - brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t)); - if (brdp == (stlibrd_t *) NULL) { + brdp = kzalloc(sizeof(stlibrd_t), GFP_KERNEL); + if (!brdp) { printk(KERN_ERR "STALLION: failed to allocate memory " "(size=%d)\n", sizeof(stlibrd_t)); - return((stlibrd_t *) NULL); + return NULL; } - memset(brdp, 0, sizeof(stlibrd_t)); brdp->magic = STLI_BOARDMAGIC; return(brdp); } @@ -5210,12 +5196,12 @@ int __init stli_init(void) /* * Allocate a temporary write buffer. */ - stli_tmpwritebuf = (char *) stli_memalloc(STLI_TXBUFSIZE); - if (stli_tmpwritebuf == (char *) NULL) + stli_tmpwritebuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); + if (!stli_tmpwritebuf) printk(KERN_ERR "STALLION: failed to allocate memory " "(size=%d)\n", STLI_TXBUFSIZE); - stli_txcookbuf = stli_memalloc(STLI_TXBUFSIZE); - if (stli_txcookbuf == (char *) NULL) + stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); + if (!stli_txcookbuf) printk(KERN_ERR "STALLION: failed to allocate memory " "(size=%d)\n", STLI_TXBUFSIZE); diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 3f5d6077f39c..a9c5a7230f89 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -504,7 +504,6 @@ static int stl_echmcaintr(stlbrd_t *brdp); static int stl_echpciintr(stlbrd_t *brdp); static int stl_echpci64intr(stlbrd_t *brdp); static void stl_offintr(void *private); -static void *stl_memalloc(int len); static stlbrd_t *stl_allocbrd(void); static stlport_t *stl_getport(int brdnr, int panelnr, int portnr); @@ -939,17 +938,6 @@ static int stl_parsebrd(stlconf_t *confp, char **argp) /*****************************************************************************/ -/* - * Local driver kernel memory allocation routine. - */ - -static void *stl_memalloc(int len) -{ - return (void *) kmalloc(len, GFP_KERNEL); -} - -/*****************************************************************************/ - /* * Allocate a new board structure. Fill out the basic info in it. */ @@ -958,14 +946,13 @@ static stlbrd_t *stl_allocbrd(void) { stlbrd_t *brdp; - brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t)); - if (brdp == (stlbrd_t *) NULL) { + brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL); + if (!brdp) { printk("STALLION: failed to allocate memory (size=%d)\n", sizeof(stlbrd_t)); - return (stlbrd_t *) NULL; + return NULL; } - memset(brdp, 0, sizeof(stlbrd_t)); brdp->magic = STL_BOARDMAGIC; return brdp; } @@ -1017,9 +1004,9 @@ static int stl_open(struct tty_struct *tty, struct file *filp) portp->refcount++; if ((portp->flags & ASYNC_INITIALIZED) == 0) { - if (portp->tx.buf == (char *) NULL) { - portp->tx.buf = (char *) stl_memalloc(STL_TXBUFSIZE); - if (portp->tx.buf == (char *) NULL) + if (!portp->tx.buf) { + portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); + if (!portp->tx.buf) return -ENOMEM; portp->tx.head = portp->tx.buf; portp->tx.tail = portp->tx.buf; @@ -2178,13 +2165,12 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) * each ports data structures. */ for (i = 0; (i < panelp->nrports); i++) { - portp = (stlport_t *) stl_memalloc(sizeof(stlport_t)); - if (portp == (stlport_t *) NULL) { + portp = kzalloc(sizeof(stlport_t), GFP_KERNEL); + if (!portp) { printk("STALLION: failed to allocate memory " "(size=%d)\n", sizeof(stlport_t)); break; } - memset(portp, 0, sizeof(stlport_t)); portp->magic = STL_PORTMAGIC; portp->portnr = i; @@ -2315,13 +2301,12 @@ static inline int stl_initeio(stlbrd_t *brdp) * can complete the setup. */ - panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t)); - if (panelp == (stlpanel_t *) NULL) { + panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); + if (!panelp) { printk(KERN_WARNING "STALLION: failed to allocate memory " "(size=%d)\n", sizeof(stlpanel_t)); - return(-ENOMEM); + return -ENOMEM; } - memset(panelp, 0, sizeof(stlpanel_t)); panelp->magic = STL_PANELMAGIC; panelp->brdnr = brdp->brdnr; @@ -2490,13 +2475,12 @@ static inline int stl_initech(stlbrd_t *brdp) status = inb(ioaddr + ECH_PNLSTATUS); if ((status & ECH_PNLIDMASK) != nxtid) break; - panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t)); - if (panelp == (stlpanel_t *) NULL) { + panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); + if (!panelp) { printk("STALLION: failed to allocate memory " "(size=%d)\n", sizeof(stlpanel_t)); break; } - memset(panelp, 0, sizeof(stlpanel_t)); panelp->magic = STL_PANELMAGIC; panelp->brdnr = brdp->brdnr; panelp->panelnr = panelnr; @@ -3074,8 +3058,8 @@ static int __init stl_init(void) /* * Allocate a temporary write buffer. */ - stl_tmpwritebuf = (char *) stl_memalloc(STL_TXBUFSIZE); - if (stl_tmpwritebuf == (char *) NULL) + stl_tmpwritebuf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); + if (!stl_tmpwritebuf) printk("STALLION: failed to allocate memory (size=%d)\n", STL_TXBUFSIZE); -- cgit v1.2.3-59-g8ed1b From d32af0fe11b1618572389723e93cf33a4cc11c81 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Fri, 31 Mar 2006 02:30:57 -0800 Subject: [PATCH] ISDN: fix a few memory leaks in sc_ioctl() Fix a few memory leaks in drivers/isdn/sc/ioctl.c::sc_ioctl() Signed-off-by: Jesper Juhl Acked-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/sc/ioctl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c index 94c9afb7017c..f4f71226a078 100644 --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c @@ -46,7 +46,8 @@ int sc_ioctl(int card, scs_ioctl *data) pr_debug("%s: SCIOCRESET: ioctl received\n", sc_adapter[card]->devicename); sc_adapter[card]->StartOnReset = 0; - return (reset(card)); + kfree(rcvmsg); + return reset(card); } case SCIOCLOAD: @@ -183,7 +184,7 @@ int sc_ioctl(int card, scs_ioctl *data) sc_adapter[card]->devicename); spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL); - if(!spid) { + if (!spid) { kfree(rcvmsg); return -ENOMEM; } @@ -195,10 +196,10 @@ int sc_ioctl(int card, scs_ioctl *data) if (!status) { pr_debug("%s: SCIOCGETSPID: command successful\n", sc_adapter[card]->devicename); - } - else { + } else { pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n", sc_adapter[card]->devicename, status); + kfree(spid); kfree(rcvmsg); return status; } -- cgit v1.2.3-59-g8ed1b From 0ca07731e495584bd84dca15a0f065470d594ec4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 31 Mar 2006 02:30:58 -0800 Subject: [PATCH] vt: add TIOCL_GETKMSGREDIRECT Add TIOCL_GETKMSGREDIRECT needed by the userland suspend tool to get the current value of kmsg_redirect from the kernel so that it can save it and restore it after resume. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Cc: Michael Kerrisk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/vt.c | 4 ++++ include/linux/tiocl.h | 1 + 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/char/vt.c b/drivers/char/vt.c index ca4844c527da..acc5d47844eb 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2328,6 +2328,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) case TIOCL_SETVESABLANK: set_vesa_blanking(p); break; + case TIOCL_GETKMSGREDIRECT: + data = kmsg_redirect; + ret = __put_user(data, p); + break; case TIOCL_SETKMSGREDIRECT: if (!capable(CAP_SYS_ADMIN)) { ret = -EPERM; diff --git a/include/linux/tiocl.h b/include/linux/tiocl.h index 2c9e847f6ed1..4756862c4ed4 100644 --- a/include/linux/tiocl.h +++ b/include/linux/tiocl.h @@ -34,5 +34,6 @@ struct tiocl_selection { #define TIOCL_SCROLLCONSOLE 13 /* scroll console */ #define TIOCL_BLANKSCREEN 14 /* keep screen blank even if a key is pressed */ #define TIOCL_BLANKEDSCREEN 15 /* return which vt was blanked */ +#define TIOCL_GETKMSGREDIRECT 17 /* get the vt the kernel messages are restricted to */ #endif /* _LINUX_TIOCL_H */ -- cgit v1.2.3-59-g8ed1b From c72a1d608dd0eb3d553a08bfdf1c0041bebaa8a0 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:04 -0800 Subject: [PATCH] LED: add LED class Add the foundations of a new LEDs subsystem. This patch adds a class which presents LED devices within sysfs and allows their brightness to be controlled. Signed-off-by: Richard Purdie Cc: Russell King Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/Kconfig | 2 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/leds/Kconfig | 18 ++++++ drivers/leds/Makefile | 4 ++ drivers/leds/led-class.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/leds/led-core.c | 25 ++++++++ drivers/leds/leds.h | 31 ++++++++++ include/linux/leds.h | 51 ++++++++++++++++ 9 files changed, 281 insertions(+) create mode 100644 drivers/leds/Kconfig create mode 100644 drivers/leds/Makefile create mode 100644 drivers/leds/led-class.c create mode 100644 drivers/leds/led-core.c create mode 100644 drivers/leds/leds.h create mode 100644 include/linux/leds.h (limited to 'drivers') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ba46d779ede7..e91db542eb01 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -839,6 +839,8 @@ source "drivers/misc/Kconfig" source "drivers/mfd/Kconfig" +source "drivers/leds/Kconfig" + source "drivers/media/Kconfig" source "drivers/video/Kconfig" diff --git a/drivers/Kconfig b/drivers/Kconfig index 9f5c0da57c90..5c91d6afb117 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -64,6 +64,8 @@ source "drivers/usb/Kconfig" source "drivers/mmc/Kconfig" +source "drivers/leds/Kconfig" + source "drivers/infiniband/Kconfig" source "drivers/sn/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 424955274e60..d6e8ffbd8132 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_MCA) += mca/ obj-$(CONFIG_EISA) += eisa/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_MMC) += mmc/ +obj-$(CONFIG_NEW_LEDS) += leds/ obj-$(CONFIG_INFINIBAND) += infiniband/ obj-$(CONFIG_SGI_SN) += sn/ obj-y += firmware/ diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig new file mode 100644 index 000000000000..106f9aeca04f --- /dev/null +++ b/drivers/leds/Kconfig @@ -0,0 +1,18 @@ + +menu "LED devices" + +config NEW_LEDS + bool "LED Support" + help + Say Y to enable Linux LED support. This is not related to standard + keyboard LEDs which are controlled via the input system. + +config LEDS_CLASS + tristate "LED Class Support" + depends NEW_LEDS + help + This option enables the led sysfs class in /sys/class/leds. You'll + need this to do anything useful with LEDs. If unsure, say N. + +endmenu + diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile new file mode 100644 index 000000000000..8a62871437fa --- /dev/null +++ b/drivers/leds/Makefile @@ -0,0 +1,4 @@ + +# LED Core +obj-$(CONFIG_NEW_LEDS) += led-core.o +obj-$(CONFIG_LEDS_CLASS) += led-class.o diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c new file mode 100644 index 000000000000..0292df4101ba --- /dev/null +++ b/drivers/leds/led-class.c @@ -0,0 +1,147 @@ +/* + * LED Class Core + * + * Copyright (C) 2005 John Lenz + * Copyright (C) 2005-2006 Richard Purdie + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "leds.h" + +static struct class *leds_class; + +static ssize_t led_brightness_show(struct class_device *dev, char *buf) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + ssize_t ret = 0; + + /* no lock needed for this */ + sprintf(buf, "%u\n", led_cdev->brightness); + ret = strlen(buf) + 1; + + return ret; +} + +static ssize_t led_brightness_store(struct class_device *dev, + const char *buf, size_t size) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + ssize_t ret = -EINVAL; + char *after; + unsigned long state = simple_strtoul(buf, &after, 10); + + if (after - buf > 0) { + ret = after - buf; + led_set_brightness(led_cdev, state); + } + + return ret; +} + +static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show, + led_brightness_store); + +/** + * led_classdev_suspend - suspend an led_classdev. + * @led_cdev: the led_classdev to suspend. + */ +void led_classdev_suspend(struct led_classdev *led_cdev) +{ + led_cdev->flags |= LED_SUSPENDED; + led_cdev->brightness_set(led_cdev, 0); +} +EXPORT_SYMBOL_GPL(led_classdev_suspend); + +/** + * led_classdev_resume - resume an led_classdev. + * @led_cdev: the led_classdev to resume. + */ +void led_classdev_resume(struct led_classdev *led_cdev) +{ + led_cdev->brightness_set(led_cdev, led_cdev->brightness); + led_cdev->flags &= ~LED_SUSPENDED; +} +EXPORT_SYMBOL_GPL(led_classdev_resume); + +/** + * led_classdev_register - register a new object of led_classdev class. + * @dev: The device to register. + * @led_cdev: the led_classdev structure for this device. + */ +int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) +{ + led_cdev->class_dev = class_device_create(leds_class, NULL, 0, + parent, "%s", led_cdev->name); + if (unlikely(IS_ERR(led_cdev->class_dev))) + return PTR_ERR(led_cdev->class_dev); + + class_set_devdata(led_cdev->class_dev, led_cdev); + + /* register the attributes */ + class_device_create_file(led_cdev->class_dev, + &class_device_attr_brightness); + + /* add to the list of leds */ + write_lock(&leds_list_lock); + list_add_tail(&led_cdev->node, &leds_list); + write_unlock(&leds_list_lock); + + printk(KERN_INFO "Registered led device: %s\n", + led_cdev->class_dev->class_id); + + return 0; +} +EXPORT_SYMBOL_GPL(led_classdev_register); + +/** + * led_classdev_unregister - unregisters a object of led_properties class. + * @led_cdev: the led device to unreigister + * + * Unregisters a previously registered via led_classdev_register object. + */ +void led_classdev_unregister(struct led_classdev *led_cdev) +{ + class_device_remove_file(led_cdev->class_dev, + &class_device_attr_brightness); + + class_device_unregister(led_cdev->class_dev); + + write_lock(&leds_list_lock); + list_del(&led_cdev->node); + write_unlock(&leds_list_lock); +} +EXPORT_SYMBOL_GPL(led_classdev_unregister); + +static int __init leds_init(void) +{ + leds_class = class_create(THIS_MODULE, "leds"); + if (IS_ERR(leds_class)) + return PTR_ERR(leds_class); + return 0; +} + +static void __exit leds_exit(void) +{ + class_destroy(leds_class); +} + +subsys_initcall(leds_init); +module_exit(leds_exit); + +MODULE_AUTHOR("John Lenz, Richard Purdie"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LED Class Interface"); diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c new file mode 100644 index 000000000000..fe6541326c71 --- /dev/null +++ b/drivers/leds/led-core.c @@ -0,0 +1,25 @@ +/* + * LED Class Core + * + * Copyright 2005-2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * 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 +#include +#include +#include "leds.h" + +rwlock_t leds_list_lock = RW_LOCK_UNLOCKED; +LIST_HEAD(leds_list); + +EXPORT_SYMBOL_GPL(leds_list); +EXPORT_SYMBOL_GPL(leds_list_lock); diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h new file mode 100644 index 000000000000..d26ca2f7e722 --- /dev/null +++ b/drivers/leds/leds.h @@ -0,0 +1,31 @@ +/* + * LED Core + * + * Copyright 2005 Openedhand Ltd. + * + * Author: Richard Purdie + * + * 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 __LEDS_H_INCLUDED +#define __LEDS_H_INCLUDED + +#include + +static inline void led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness value) +{ + if (value > LED_FULL) + value = LED_FULL; + led_cdev->brightness = value; + if (!(led_cdev->flags & LED_SUSPENDED)) + led_cdev->brightness_set(led_cdev, value); +} + +extern rwlock_t leds_list_lock; +extern struct list_head leds_list; + +#endif /* __LEDS_H_INCLUDED */ diff --git a/include/linux/leds.h b/include/linux/leds.h new file mode 100644 index 000000000000..6812640b39cc --- /dev/null +++ b/include/linux/leds.h @@ -0,0 +1,51 @@ +/* + * Driver model for leds and led triggers + * + * Copyright (C) 2005 John Lenz + * Copyright (C) 2005 Richard Purdie + * + * 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 __LINUX_LEDS_H_INCLUDED +#define __LINUX_LEDS_H_INCLUDED + +struct device; +struct class_device; +/* + * LED Core + */ + +enum led_brightness { + LED_OFF = 0, + LED_HALF = 127, + LED_FULL = 255, +}; + +struct led_classdev { + const char *name; + int brightness; + int flags; +#define LED_SUSPENDED (1 << 0) + + /* A function to set the brightness of the led */ + void (*brightness_set)(struct led_classdev *led_cdev, + enum led_brightness brightness); + + struct class_device *class_dev; + /* LED Device linked list */ + struct list_head node; + + /* Trigger data */ + char *default_trigger; +}; + +extern int led_classdev_register(struct device *parent, + struct led_classdev *led_cdev); +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); + +#endif /* __LINUX_LEDS_H_INCLUDED */ -- cgit v1.2.3-59-g8ed1b From c3bc9956ec52fb2c70f29aa894d8eec766116584 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:05 -0800 Subject: [PATCH] LED: add LED trigger tupport Add support for LED triggers to the LED subsystem. "Triggers" are events which change the state of an LED. Two kinds of trigger are available, simple ones which can be added to exising code with minimum disruption and complex ones for implementing new or more complex functionality. Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 8 ++ drivers/leds/Makefile | 1 + drivers/leds/led-class.c | 20 ++++ drivers/leds/led-triggers.c | 239 ++++++++++++++++++++++++++++++++++++++++++++ drivers/leds/leds.h | 13 +++ include/linux/leds.h | 52 ++++++++++ 6 files changed, 333 insertions(+) create mode 100644 drivers/leds/led-triggers.c (limited to 'drivers') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 106f9aeca04f..a4d12ecaf6a5 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -14,5 +14,13 @@ config LEDS_CLASS This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. +config LEDS_TRIGGERS + bool "LED Trigger support" + depends NEW_LEDS + help + This option enables trigger support for the leds class. + These triggers allow kernel events to drive the LEDs and can + be configured via sysfs. If unsure, say Y. + endmenu diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 8a62871437fa..a9d8becd6189 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -2,3 +2,4 @@ # LED Core obj-$(CONFIG_NEW_LEDS) += led-core.o obj-$(CONFIG_LEDS_CLASS) += led-class.o +obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 0292df4101ba..b0b5d05fadd6 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -54,6 +54,9 @@ static ssize_t led_brightness_store(struct class_device *dev, static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show, led_brightness_store); +#ifdef CONFIG_LEDS_TRIGGERS +static CLASS_DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store); +#endif /** * led_classdev_suspend - suspend an led_classdev. @@ -100,6 +103,15 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) list_add_tail(&led_cdev->node, &leds_list); write_unlock(&leds_list_lock); +#ifdef CONFIG_LEDS_TRIGGERS + rwlock_init(&led_cdev->trigger_lock); + + led_trigger_set_default(led_cdev); + + class_device_create_file(led_cdev->class_dev, + &class_device_attr_trigger); +#endif + printk(KERN_INFO "Registered led device: %s\n", led_cdev->class_dev->class_id); @@ -117,6 +129,14 @@ void led_classdev_unregister(struct led_classdev *led_cdev) { class_device_remove_file(led_cdev->class_dev, &class_device_attr_brightness); +#ifdef CONFIG_LEDS_TRIGGERS + class_device_remove_file(led_cdev->class_dev, + &class_device_attr_trigger); + write_lock(&led_cdev->trigger_lock); + if (led_cdev->trigger) + led_trigger_set(led_cdev, NULL); + write_unlock(&led_cdev->trigger_lock); +#endif class_device_unregister(led_cdev->class_dev); diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c new file mode 100644 index 000000000000..5e2cd8be1191 --- /dev/null +++ b/drivers/leds/led-triggers.c @@ -0,0 +1,239 @@ +/* + * LED Triggers Core + * + * Copyright 2005-2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "leds.h" + +/* + * Nests outside led_cdev->trigger_lock + */ +static rwlock_t triggers_list_lock = RW_LOCK_UNLOCKED; +static LIST_HEAD(trigger_list); + +ssize_t led_trigger_store(struct class_device *dev, const char *buf, + size_t count) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + char trigger_name[TRIG_NAME_MAX]; + struct led_trigger *trig; + size_t len; + + trigger_name[sizeof(trigger_name) - 1] = '\0'; + strncpy(trigger_name, buf, sizeof(trigger_name) - 1); + len = strlen(trigger_name); + + if (len && trigger_name[len - 1] == '\n') + trigger_name[len - 1] = '\0'; + + if (!strcmp(trigger_name, "none")) { + write_lock(&led_cdev->trigger_lock); + led_trigger_set(led_cdev, NULL); + write_unlock(&led_cdev->trigger_lock); + return count; + } + + read_lock(&triggers_list_lock); + list_for_each_entry(trig, &trigger_list, next_trig) { + if (!strcmp(trigger_name, trig->name)) { + write_lock(&led_cdev->trigger_lock); + led_trigger_set(led_cdev, trig); + write_unlock(&led_cdev->trigger_lock); + + read_unlock(&triggers_list_lock); + return count; + } + } + read_unlock(&triggers_list_lock); + + return -EINVAL; +} + + +ssize_t led_trigger_show(struct class_device *dev, char *buf) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + struct led_trigger *trig; + int len = 0; + + read_lock(&triggers_list_lock); + read_lock(&led_cdev->trigger_lock); + + if (!led_cdev->trigger) + len += sprintf(buf+len, "[none] "); + else + len += sprintf(buf+len, "none "); + + list_for_each_entry(trig, &trigger_list, next_trig) { + if (led_cdev->trigger && !strcmp(led_cdev->trigger->name, + trig->name)) + len += sprintf(buf+len, "[%s] ", trig->name); + else + len += sprintf(buf+len, "%s ", trig->name); + } + read_unlock(&led_cdev->trigger_lock); + read_unlock(&triggers_list_lock); + + len += sprintf(len+buf, "\n"); + return len; +} + +void led_trigger_event(struct led_trigger *trigger, + enum led_brightness brightness) +{ + struct list_head *entry; + + if (!trigger) + return; + + read_lock(&trigger->leddev_list_lock); + list_for_each(entry, &trigger->led_cdevs) { + struct led_classdev *led_cdev; + + led_cdev = list_entry(entry, struct led_classdev, trig_list); + led_set_brightness(led_cdev, brightness); + } + read_unlock(&trigger->leddev_list_lock); +} + +/* Caller must ensure led_cdev->trigger_lock held */ +void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger) +{ + unsigned long flags; + + /* Remove any existing trigger */ + if (led_cdev->trigger) { + write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); + list_del(&led_cdev->trig_list); + write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags); + if (led_cdev->trigger->deactivate) + led_cdev->trigger->deactivate(led_cdev); + } + if (trigger) { + write_lock_irqsave(&trigger->leddev_list_lock, flags); + list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs); + write_unlock_irqrestore(&trigger->leddev_list_lock, flags); + if (trigger->activate) + trigger->activate(led_cdev); + } + led_cdev->trigger = trigger; +} + +void led_trigger_set_default(struct led_classdev *led_cdev) +{ + struct led_trigger *trig; + + if (!led_cdev->default_trigger) + return; + + read_lock(&triggers_list_lock); + write_lock(&led_cdev->trigger_lock); + list_for_each_entry(trig, &trigger_list, next_trig) { + if (!strcmp(led_cdev->default_trigger, trig->name)) + led_trigger_set(led_cdev, trig); + } + write_unlock(&led_cdev->trigger_lock); + read_unlock(&triggers_list_lock); +} + +int led_trigger_register(struct led_trigger *trigger) +{ + struct led_classdev *led_cdev; + + rwlock_init(&trigger->leddev_list_lock); + INIT_LIST_HEAD(&trigger->led_cdevs); + + /* Add to the list of led triggers */ + write_lock(&triggers_list_lock); + list_add_tail(&trigger->next_trig, &trigger_list); + write_unlock(&triggers_list_lock); + + /* Register with any LEDs that have this as a default trigger */ + read_lock(&leds_list_lock); + list_for_each_entry(led_cdev, &leds_list, node) { + write_lock(&led_cdev->trigger_lock); + if (!led_cdev->trigger && led_cdev->default_trigger && + !strcmp(led_cdev->default_trigger, trigger->name)) + led_trigger_set(led_cdev, trigger); + write_unlock(&led_cdev->trigger_lock); + } + read_unlock(&leds_list_lock); + + return 0; +} + +void led_trigger_register_simple(const char *name, struct led_trigger **tp) +{ + struct led_trigger *trigger; + + trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); + + if (trigger) { + trigger->name = name; + led_trigger_register(trigger); + } + *tp = trigger; +} + +void led_trigger_unregister(struct led_trigger *trigger) +{ + struct led_classdev *led_cdev; + + /* Remove from the list of led triggers */ + write_lock(&triggers_list_lock); + list_del(&trigger->next_trig); + write_unlock(&triggers_list_lock); + + /* Remove anyone actively using this trigger */ + read_lock(&leds_list_lock); + list_for_each_entry(led_cdev, &leds_list, node) { + write_lock(&led_cdev->trigger_lock); + if (led_cdev->trigger == trigger) + led_trigger_set(led_cdev, NULL); + write_unlock(&led_cdev->trigger_lock); + } + read_unlock(&leds_list_lock); +} + +void led_trigger_unregister_simple(struct led_trigger *trigger) +{ + led_trigger_unregister(trigger); + kfree(trigger); +} + +/* Used by LED Class */ +EXPORT_SYMBOL_GPL(led_trigger_set); +EXPORT_SYMBOL_GPL(led_trigger_set_default); +EXPORT_SYMBOL_GPL(led_trigger_show); +EXPORT_SYMBOL_GPL(led_trigger_store); + +/* LED Trigger Interface */ +EXPORT_SYMBOL_GPL(led_trigger_register); +EXPORT_SYMBOL_GPL(led_trigger_unregister); + +/* Simple LED Tigger Interface */ +EXPORT_SYMBOL_GPL(led_trigger_register_simple); +EXPORT_SYMBOL_GPL(led_trigger_unregister_simple); +EXPORT_SYMBOL_GPL(led_trigger_event); + +MODULE_AUTHOR("Richard Purdie"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LED Triggers Core"); diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index d26ca2f7e722..a715c4ed93ff 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -28,4 +28,17 @@ static inline void led_set_brightness(struct led_classdev *led_cdev, extern rwlock_t leds_list_lock; extern struct list_head leds_list; +#ifdef CONFIG_LEDS_TRIGGERS +void led_trigger_set_default(struct led_classdev *led_cdev); +void led_trigger_set(struct led_classdev *led_cdev, + struct led_trigger *trigger); +#else +#define led_trigger_set_default(x) do {} while(0) +#define led_trigger_set(x, y) do {} while(0) +#endif + +ssize_t led_trigger_store(struct class_device *dev, const char *buf, + size_t count); +ssize_t led_trigger_show(struct class_device *dev, char *buf); + #endif /* __LEDS_H_INCLUDED */ diff --git a/include/linux/leds.h b/include/linux/leds.h index 6812640b39cc..404575c3dd5a 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -40,6 +40,14 @@ struct led_classdev { /* Trigger data */ char *default_trigger; +#ifdef CONFIG_LEDS_TRIGGERS + rwlock_t trigger_lock; + /* Protects the trigger data below */ + + struct led_trigger *trigger; + struct list_head trig_list; + void *trigger_data; +#endif }; extern int led_classdev_register(struct device *parent, @@ -48,4 +56,48 @@ extern void led_classdev_unregister(struct led_classdev *led_cdev); extern void led_classdev_suspend(struct led_classdev *led_cdev); extern void led_classdev_resume(struct led_classdev *led_cdev); +/* + * LED Triggers + */ +#ifdef CONFIG_LEDS_TRIGGERS + +#define TRIG_NAME_MAX 50 + +struct led_trigger { + /* Trigger Properties */ + const char *name; + void (*activate)(struct led_classdev *led_cdev); + void (*deactivate)(struct led_classdev *led_cdev); + + /* LEDs under control by this trigger (for simple triggers) */ + rwlock_t leddev_list_lock; + struct list_head led_cdevs; + + /* Link to next registered trigger */ + struct list_head next_trig; +}; + +/* Registration functions for complex triggers */ +extern int led_trigger_register(struct led_trigger *trigger); +extern void led_trigger_unregister(struct led_trigger *trigger); + +/* Registration functions for simple triggers */ +#define DEFINE_LED_TRIGGER(x) static struct led_trigger *x; +#define DEFINE_LED_TRIGGER_GLOBAL(x) struct led_trigger *x; +extern void led_trigger_register_simple(const char *name, + struct led_trigger **trigger); +extern void led_trigger_unregister_simple(struct led_trigger *trigger); +extern void led_trigger_event(struct led_trigger *trigger, + enum led_brightness event); + +#else + +/* Triggers aren't active - null macros */ +#define DEFINE_LED_TRIGGER(x) +#define DEFINE_LED_TRIGGER_GLOBAL(x) +#define led_trigger_register_simple(x, y) do {} while(0) +#define led_trigger_unregister_simple(x) do {} while(0) +#define led_trigger_event(x, y) do {} while(0) + +#endif #endif /* __LINUX_LEDS_H_INCLUDED */ -- cgit v1.2.3-59-g8ed1b From 6655c6fe575b720eb8cb6c143ae10995a7aa1916 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:07 -0800 Subject: [PATCH] LED: add LED timer trigger Add an example of a complex LED trigger in the form of a generic timer which triggers the LED its attached to at a user specified frequency and duty cycle. Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 7 ++ drivers/leds/Makefile | 3 + drivers/leds/ledtrig-timer.c | 170 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 drivers/leds/ledtrig-timer.c (limited to 'drivers') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index a4d12ecaf6a5..fda44df5921f 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -22,5 +22,12 @@ config LEDS_TRIGGERS These triggers allow kernel events to drive the LEDs and can be configured via sysfs. If unsure, say Y. +config LEDS_TRIGGER_TIMER + tristate "LED Timer Trigger" + depends LEDS_TRIGGERS + help + This allows LEDs to be controlled by a programmable timer + via sysfs. If unsure, say Y. + endmenu diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index a9d8becd6189..81e4abb9dcb0 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -3,3 +3,6 @@ obj-$(CONFIG_NEW_LEDS) += led-core.o obj-$(CONFIG_LEDS_CLASS) += led-class.o obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o + +# LED Triggers +obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c new file mode 100644 index 000000000000..f484b5d6dbf8 --- /dev/null +++ b/drivers/leds/ledtrig-timer.c @@ -0,0 +1,170 @@ +/* + * LED Kernel Timer Trigger + * + * Copyright 2005-2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "leds.h" + +struct timer_trig_data { + unsigned long delay_on; /* milliseconds on */ + unsigned long delay_off; /* milliseconds off */ + struct timer_list timer; +}; + +static void led_timer_function(unsigned long data) +{ + struct led_classdev *led_cdev = (struct led_classdev *) data; + struct timer_trig_data *timer_data = led_cdev->trigger_data; + unsigned long brightness = LED_OFF; + unsigned long delay = timer_data->delay_off; + + if (!timer_data->delay_on || !timer_data->delay_off) { + led_set_brightness(led_cdev, LED_OFF); + return; + } + + if (!led_cdev->brightness) { + brightness = LED_FULL; + delay = timer_data->delay_on; + } + + led_set_brightness(led_cdev, brightness); + + mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); +} + +static ssize_t led_delay_on_show(struct class_device *dev, char *buf) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; + + sprintf(buf, "%lu\n", timer_data->delay_on); + + return strlen(buf) + 1; +} + +static ssize_t led_delay_on_store(struct class_device *dev, const char *buf, + size_t size) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; + int ret = -EINVAL; + char *after; + unsigned long state = simple_strtoul(buf, &after, 10); + + if (after - buf > 0) { + timer_data->delay_on = state; + mod_timer(&timer_data->timer, jiffies + 1); + ret = after - buf; + } + + return ret; +} + +static ssize_t led_delay_off_show(struct class_device *dev, char *buf) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; + + sprintf(buf, "%lu\n", timer_data->delay_off); + + return strlen(buf) + 1; +} + +static ssize_t led_delay_off_store(struct class_device *dev, const char *buf, + size_t size) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; + int ret = -EINVAL; + char *after; + unsigned long state = simple_strtoul(buf, &after, 10); + + if (after - buf > 0) { + timer_data->delay_off = state; + mod_timer(&timer_data->timer, jiffies + 1); + ret = after - buf; + } + + return ret; +} + +static CLASS_DEVICE_ATTR(delay_on, 0644, led_delay_on_show, + led_delay_on_store); +static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show, + led_delay_off_store); + +static void timer_trig_activate(struct led_classdev *led_cdev) +{ + struct timer_trig_data *timer_data; + + timer_data = kzalloc(sizeof(struct timer_trig_data), GFP_KERNEL); + if (!timer_data) + return; + + led_cdev->trigger_data = timer_data; + + init_timer(&timer_data->timer); + timer_data->timer.function = led_timer_function; + timer_data->timer.data = (unsigned long) led_cdev; + + class_device_create_file(led_cdev->class_dev, + &class_device_attr_delay_on); + class_device_create_file(led_cdev->class_dev, + &class_device_attr_delay_off); +} + +static void timer_trig_deactivate(struct led_classdev *led_cdev) +{ + struct timer_trig_data *timer_data = led_cdev->trigger_data; + + if (timer_data) { + class_device_remove_file(led_cdev->class_dev, + &class_device_attr_delay_on); + class_device_remove_file(led_cdev->class_dev, + &class_device_attr_delay_off); + del_timer_sync(&timer_data->timer); + kfree(timer_data); + } +} + +static struct led_trigger timer_led_trigger = { + .name = "timer", + .activate = timer_trig_activate, + .deactivate = timer_trig_deactivate, +}; + +static int __init timer_trig_init(void) +{ + return led_trigger_register(&timer_led_trigger); +} + +static void __exit timer_trig_exit(void) +{ + led_trigger_unregister(&timer_led_trigger); +} + +module_init(timer_trig_init); +module_exit(timer_trig_exit); + +MODULE_AUTHOR("Richard Purdie "); +MODULE_DESCRIPTION("Timer LED trigger"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 3179108daaaccbf28b17d6d8b0e06abf0eee6d9f Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:09 -0800 Subject: [PATCH] LED: add LED device support for the zaurus corgi and spitz models Adds LED drivers for LEDs found on the Sharp Zaurus c7x0 (corgi, shepherd, husky) and cxx00 (akita, spitz, borzoi) models. Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-pxa/corgi.c | 9 ++++ arch/arm/mach-pxa/spitz.c | 9 ++++ drivers/leds/Kconfig | 14 ++++++ drivers/leds/Makefile | 4 ++ drivers/leds/leds-corgi.c | 121 ++++++++++++++++++++++++++++++++++++++++++++ drivers/leds/leds-spitz.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 282 insertions(+) create mode 100644 drivers/leds/leds-corgi.c create mode 100644 drivers/leds/leds-spitz.c (limited to 'drivers') diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 68923b1d2b62..99604a544629 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -163,6 +163,14 @@ static struct platform_device corgikbd_device = { }; +/* + * Corgi LEDs + */ +static struct platform_device corgiled_device = { + .name = "corgi-led", + .id = -1, +}; + /* * Corgi Touch Screen Device */ @@ -297,6 +305,7 @@ static struct platform_device *devices[] __initdata = { &corgikbd_device, &corgibl_device, &corgits_device, + &corgiled_device, }; static void __init corgi_init(void) diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 0dbb079ecd25..ebe473053392 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -241,6 +241,14 @@ static struct platform_device spitzkbd_device = { }; +/* + * Spitz LEDs + */ +static struct platform_device spitzled_device = { + .name = "spitz-led", + .id = -1, +}; + /* * Spitz Touch Screen Device */ @@ -418,6 +426,7 @@ static struct platform_device *devices[] __initdata = { &spitzkbd_device, &spitzts_device, &spitzbl_device, + &spitzled_device, }; static void __init common_init(void) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index fda44df5921f..f7846b40c842 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -22,6 +22,20 @@ config LEDS_TRIGGERS These triggers allow kernel events to drive the LEDs and can be configured via sysfs. If unsure, say Y. +config LEDS_CORGI + tristate "LED Support for the Sharp SL-C7x0 series" + depends LEDS_CLASS && PXA_SHARP_C7xx + help + This option enables support for the LEDs on Sharp Zaurus + SL-C7x0 series (C700, C750, C760, C860). + +config LEDS_SPITZ + tristate "LED Support for the Sharp SL-Cxx00 series" + depends LEDS_CLASS && PXA_SHARP_Cxx00 + help + This option enables support for the LEDs on Sharp Zaurus + SL-Cxx00 series (C1000, C3000, C3100). + config LEDS_TRIGGER_TIMER tristate "LED Timer Trigger" depends LEDS_TRIGGERS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 81e4abb9dcb0..cb5d0ada6a8c 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -4,5 +4,9 @@ obj-$(CONFIG_NEW_LEDS) += led-core.o obj-$(CONFIG_LEDS_CLASS) += led-class.o obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o +# LED Platform Drivers +obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o +obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o + # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c new file mode 100644 index 000000000000..bb7d84df0121 --- /dev/null +++ b/drivers/leds/leds-corgi.c @@ -0,0 +1,121 @@ +/* + * LED Triggers Core + * + * Copyright 2005-2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightness value) +{ + if (value) + GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); + else + GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); +} + +static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightness value) +{ + if (value) + set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); + else + reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); +} + +static struct led_classdev corgi_amber_led = { + .name = "corgi:amber", + .default_trigger = "sharpsl-charge", + .brightness_set = corgiled_amber_set, +}; + +static struct led_classdev corgi_green_led = { + .name = "corgi:green", + .default_trigger = "nand-disk", + .brightness_set = corgiled_green_set, +}; + +#ifdef CONFIG_PM +static int corgiled_suspend(struct platform_device *dev, pm_message_t state) +{ +#ifdef CONFIG_LEDS_TRIGGERS + if (corgi_amber_led.trigger && strcmp(corgi_amber_led.trigger->name, "sharpsl-charge")) +#endif + led_classdev_suspend(&corgi_amber_led); + led_classdev_suspend(&corgi_green_led); + return 0; +} + +static int corgiled_resume(struct platform_device *dev) +{ + led_classdev_resume(&corgi_amber_led); + led_classdev_resume(&corgi_green_led); + return 0; +} +#endif + +static int corgiled_probe(struct platform_device *pdev) +{ + int ret; + + ret = led_classdev_register(&pdev->dev, &corgi_amber_led); + if (ret < 0) + return ret; + + ret = led_classdev_register(&pdev->dev, &corgi_green_led); + if (ret < 0) + led_classdev_unregister(&corgi_amber_led); + + return ret; +} + +static int corgiled_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&corgi_amber_led); + led_classdev_unregister(&corgi_green_led); + return 0; +} + +static struct platform_driver corgiled_driver = { + .probe = corgiled_probe, + .remove = corgiled_remove, +#ifdef CONFIG_PM + .suspend = corgiled_suspend, + .resume = corgiled_resume, +#endif + .driver = { + .name = "corgi-led", + }, +}; + +static int __init corgiled_init(void) +{ + return platform_driver_register(&corgiled_driver); +} + +static void __exit corgiled_exit(void) +{ + platform_driver_unregister(&corgiled_driver); +} + +module_init(corgiled_init); +module_exit(corgiled_exit); + +MODULE_AUTHOR("Richard Purdie "); +MODULE_DESCRIPTION("Corgi LED driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c new file mode 100644 index 000000000000..65bbef4a5e09 --- /dev/null +++ b/drivers/leds/leds-spitz.c @@ -0,0 +1,125 @@ +/* + * LED Triggers Core + * + * Copyright 2005-2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightness value) +{ + if (value) + set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); + else + reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); +} + +static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightness value) +{ + if (value) + set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); + else + reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); +} + +static struct led_classdev spitz_amber_led = { + .name = "spitz:amber", + .default_trigger = "sharpsl-charge", + .brightness_set = spitzled_amber_set, +}; + +static struct led_classdev spitz_green_led = { + .name = "spitz:green", + .default_trigger = "ide-disk", + .brightness_set = spitzled_green_set, +}; + +#ifdef CONFIG_PM +static int spitzled_suspend(struct platform_device *dev, pm_message_t state) +{ +#ifdef CONFIG_LEDS_TRIGGERS + if (spitz_amber_led.trigger && strcmp(spitz_amber_led.trigger->name, "sharpsl-charge")) +#endif + led_classdev_suspend(&spitz_amber_led); + led_classdev_suspend(&spitz_green_led); + return 0; +} + +static int spitzled_resume(struct platform_device *dev) +{ + led_classdev_resume(&spitz_amber_led); + led_classdev_resume(&spitz_green_led); + return 0; +} +#endif + +static int spitzled_probe(struct platform_device *pdev) +{ + int ret; + + if (machine_is_akita()) + spitz_green_led.default_trigger = "nand-disk"; + + ret = led_classdev_register(&pdev->dev, &spitz_amber_led); + if (ret < 0) + return ret; + + ret = led_classdev_register(&pdev->dev, &spitz_green_led); + if (ret < 0) + led_classdev_unregister(&spitz_amber_led); + + return ret; +} + +static int spitzled_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&spitz_amber_led); + led_classdev_unregister(&spitz_green_led); + + return 0; +} + +static struct platform_driver spitzled_driver = { + .probe = spitzled_probe, + .remove = spitzled_remove, +#ifdef CONFIG_PM + .suspend = spitzled_suspend, + .resume = spitzled_resume, +#endif + .driver = { + .name = "spitz-led", + }, +}; + +static int __init spitzled_init(void) +{ + return platform_driver_register(&spitzled_driver); +} + +static void __exit spitzled_exit(void) +{ + platform_driver_unregister(&spitzled_driver); +} + +module_init(spitzled_init); +module_exit(spitzled_exit); + +MODULE_AUTHOR("Richard Purdie "); +MODULE_DESCRIPTION("Spitz LED driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 4d3cb35476903768541f79e61f171e79e6065098 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:10 -0800 Subject: [PATCH] LED: add LED device support for locomo devices Adds an LED driver for LEDs exported by the Sharp LOCOMO chip as found on some models of Sharp Zaurus. Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 7 ++++ drivers/leds/Makefile | 1 + drivers/leds/leds-locomo.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 drivers/leds/leds-locomo.c (limited to 'drivers') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index f7846b40c842..6099e32985aa 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -29,6 +29,13 @@ config LEDS_CORGI This option enables support for the LEDs on Sharp Zaurus SL-C7x0 series (C700, C750, C760, C860). +config LEDS_LOCOMO + tristate "LED Support for Locomo device" + depends LEDS_CLASS && SHARP_LOCOMO + help + This option enables support for the LEDs on Sharp Locomo. + Zaurus models SL-5500 and SL-5600. + config LEDS_SPITZ tristate "LED Support for the Sharp SL-Cxx00 series" depends LEDS_CLASS && PXA_SHARP_Cxx00 diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index cb5d0ada6a8c..d60e12b8af24 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o # LED Platform Drivers obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o +obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o # LED Triggers diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c new file mode 100644 index 000000000000..749a86c2adb6 --- /dev/null +++ b/drivers/leds/leds-locomo.c @@ -0,0 +1,95 @@ +/* + * linux/drivers/leds/locomo.c + * + * Copyright (C) 2005 John Lenz + * + * 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 +#include +#include + +#include +#include + +static void locomoled_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value, int offset) +{ + struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->class_dev->dev); + unsigned long flags; + + local_irq_save(flags); + if (value) + locomo_writel(LOCOMO_LPT_TOFH, locomo_dev->mapbase + offset); + else + locomo_writel(LOCOMO_LPT_TOFL, locomo_dev->mapbase + offset); + local_irq_restore(flags); +} + +static void locomoled_brightness_set0(struct led_classdev *led_cdev, + enum led_brightness value) +{ + locomoled_brightness_set(led_cdev, value, LOCOMO_LPT0); +} + +static void locomoled_brightness_set1(struct led_classdev *led_cdev, + enum led_brightness value) +{ + locomoled_brightness_set(led_cdev, value, LOCOMO_LPT1); +} + +static struct led_classdev locomo_led0 = { + .name = "locomo:amber", + .brightness_set = locomoled_brightness_set0, +}; + +static struct led_classdev locomo_led1 = { + .name = "locomo:green", + .brightness_set = locomoled_brightness_set1, +}; + +static int locomoled_probe(struct locomo_dev *ldev) +{ + int ret; + + ret = led_classdev_register(&ldev->dev, &locomo_led0); + if (ret < 0) + return ret; + + ret = led_classdev_register(&ldev->dev, &locomo_led1); + if (ret < 0) + led_classdev_unregister(&locomo_led0); + + return ret; +} + +static int locomoled_remove(struct locomo_dev *dev) +{ + led_classdev_unregister(&locomo_led0); + led_classdev_unregister(&locomo_led1); + return 0; +} + +static struct locomo_driver locomoled_driver = { + .drv = { + .name = "locomoled" + }, + .devid = LOCOMO_DEVID_LED, + .probe = locomoled_probe, + .remove = locomoled_remove, +}; + +static int __init locomoled_init(void) +{ + return locomo_driver_register(&locomoled_driver); +} +module_init(locomoled_init); + +MODULE_AUTHOR("John Lenz "); +MODULE_DESCRIPTION("Locomo LED driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 6a0c51bfce5ae4058366017d861aea6564d25aee Mon Sep 17 00:00:00 2001 From: John Bowler Date: Fri, 31 Mar 2006 02:31:11 -0800 Subject: [PATCH] LED: add LED device support for ixp4xx devices NEW_LEDS support for ixp4xx boards where LEDs are connected to the GPIO lines. This includes a new generic ixp4xx driver (leds-ixp4xx-gpio.c name "IXP4XX-GPIO-LED") Signed-off-by: John Bowler Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 9 ++ drivers/leds/Makefile | 1 + drivers/leds/leds-ixp4xx-gpio.c | 215 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100644 drivers/leds/leds-ixp4xx-gpio.c (limited to 'drivers') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 6099e32985aa..d9e2f9853b9d 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -43,6 +43,15 @@ config LEDS_SPITZ This option enables support for the LEDs on Sharp Zaurus SL-Cxx00 series (C1000, C3000, C3100). +config LEDS_IXP4XX + tristate "LED Support for GPIO connected LEDs on IXP4XX processors" + depends LEDS_CLASS && ARCH_IXP4XX + help + This option enables support for the LEDs connected to GPIO + outputs of the Intel IXP4XX processors. To be useful the + particular board must have LEDs and they must be connected + to the GPIO lines. If unsure, say Y. + config LEDS_TRIGGER_TIMER tristate "LED Timer Trigger" depends LEDS_TRIGGERS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index d60e12b8af24..b1187c0b36ce 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o +obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/drivers/leds/leds-ixp4xx-gpio.c b/drivers/leds/leds-ixp4xx-gpio.c new file mode 100644 index 000000000000..30ced150e4cf --- /dev/null +++ b/drivers/leds/leds-ixp4xx-gpio.c @@ -0,0 +1,215 @@ +/* + * IXP4XX GPIO driver LED driver + * + * Author: John Bowler + * + * Copyright (c) 2006 John Bowler + * + * Permission is hereby granted, free of charge, to any + * person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the + * Software without restriction, including without + * limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice + * shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF + * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +extern spinlock_t gpio_lock; + +/* Up to 16 gpio lines are possible. */ +#define GPIO_MAX 16 +static struct ixp4xxgpioled_device { + struct led_classdev ancestor; + int flags; +} ixp4xxgpioled_devices[GPIO_MAX]; + +void ixp4xxgpioled_brightness_set(struct led_classdev *pled, + enum led_brightness value) +{ + const struct ixp4xxgpioled_device *const ixp4xx_dev = + container_of(pled, struct ixp4xxgpioled_device, ancestor); + const u32 gpio_pin = ixp4xx_dev - ixp4xxgpioled_devices; + + if (gpio_pin < GPIO_MAX && ixp4xx_dev->ancestor.name != 0) { + /* Set or clear the 'gpio_pin' bit according to the style + * and the required setting (value > 0 == on) + */ + const int gpio_value = + (value > 0) == (ixp4xx_dev->flags != IXP4XX_GPIO_LOW) ? + IXP4XX_GPIO_HIGH : IXP4XX_GPIO_LOW; + + { + unsigned long flags; + spin_lock_irqsave(&gpio_lock, flags); + gpio_line_set(gpio_pin, gpio_value); + spin_unlock_irqrestore(&gpio_lock, flags); + } + } +} + +/* LEDs are described in resources, the following iterates over the valid + * LED resources. + */ +#define for_all_leds(i, pdev) \ + for (i=0; inum_resources; ++i) \ + if (pdev->resource[i].start < GPIO_MAX && \ + pdev->resource[i].name != 0) + +/* The following applies 'operation' to each LED from the given platform, + * the function always returns 0 to allow tail call elimination. + */ +static int apply_to_all_leds(struct platform_device *pdev, + void (*operation)(struct led_classdev *pled)) +{ + int i; + + for_all_leds(i, pdev) + operation(&ixp4xxgpioled_devices[pdev->resource[i].start].ancestor); + return 0; +} + +#ifdef CONFIG_PM +static int ixp4xxgpioled_suspend(struct platform_device *pdev, + pm_message_t state) +{ + return apply_to_all_leds(pdev, led_classdev_suspend); +} + +static int ixp4xxgpioled_resume(struct platform_device *pdev) +{ + return apply_to_all_leds(pdev, led_classdev_resume); +} +#endif + +static void ixp4xxgpioled_remove_one_led(struct led_classdev *pled) +{ + led_classdev_unregister(pled); + pled->name = 0; +} + +static int ixp4xxgpioled_remove(struct platform_device *pdev) +{ + return apply_to_all_leds(pdev, ixp4xxgpioled_remove_one_led); +} + +static int ixp4xxgpioled_probe(struct platform_device *pdev) +{ + /* The board level has to tell the driver where the + * LEDs are connected - there is no way to find out + * electrically. It must also say whether the GPIO + * lines are active high or active low. + * + * To do this read the num_resources (the number of + * LEDs) and the struct resource (the data for each + * LED). The name comes from the resource, and it + * isn't copied. + */ + int i; + + for_all_leds(i, pdev) { + const u8 gpio_pin = pdev->resource[i].start; + int rc; + + if (ixp4xxgpioled_devices[gpio_pin].ancestor.name == 0) { + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + gpio_line_config(gpio_pin, IXP4XX_GPIO_OUT); + /* The config can, apparently, reset the state, + * I suspect the gpio line may be an input and + * the config may cause the line to be latched, + * so the setting depends on how the LED is + * connected to the line (which affects how it + * floats if not driven). + */ + gpio_line_set(gpio_pin, IXP4XX_GPIO_HIGH); + spin_unlock_irqrestore(&gpio_lock, flags); + + ixp4xxgpioled_devices[gpio_pin].flags = + pdev->resource[i].flags & IORESOURCE_BITS; + + ixp4xxgpioled_devices[gpio_pin].ancestor.name = + pdev->resource[i].name; + + /* This is how a board manufacturer makes the LED + * come on on reset - the GPIO line will be high, so + * make the LED light when the line is low... + */ + if (ixp4xxgpioled_devices[gpio_pin].flags != IXP4XX_GPIO_LOW) + ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 100; + else + ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 0; + + ixp4xxgpioled_devices[gpio_pin].ancestor.flags = 0; + + ixp4xxgpioled_devices[gpio_pin].ancestor.brightness_set = + ixp4xxgpioled_brightness_set; + + ixp4xxgpioled_devices[gpio_pin].ancestor.default_trigger = 0; + } + + rc = led_classdev_register(&pdev->dev, + &ixp4xxgpioled_devices[gpio_pin].ancestor); + if (rc < 0) { + ixp4xxgpioled_devices[gpio_pin].ancestor.name = 0; + ixp4xxgpioled_remove(pdev); + return rc; + } + } + + return 0; +} + +static struct platform_driver ixp4xxgpioled_driver = { + .probe = ixp4xxgpioled_probe, + .remove = ixp4xxgpioled_remove, +#ifdef CONFIG_PM + .suspend = ixp4xxgpioled_suspend, + .resume = ixp4xxgpioled_resume, +#endif + .driver = { + .name = "IXP4XX-GPIO-LED", + }, +}; + +static int __init ixp4xxgpioled_init(void) +{ + return platform_driver_register(&ixp4xxgpioled_driver); +} + +static void __exit ixp4xxgpioled_exit(void) +{ + platform_driver_unregister(&ixp4xxgpioled_driver); +} + +module_init(ixp4xxgpioled_init); +module_exit(ixp4xxgpioled_exit); + +MODULE_AUTHOR("John Bowler "); +MODULE_DESCRIPTION("IXP4XX GPIO LED driver"); +MODULE_LICENSE("Dual MIT/GPL"); -- cgit v1.2.3-59-g8ed1b From 6d0cf3e0480f6be9232854387794443d1a904d6d Mon Sep 17 00:00:00 2001 From: Dirk Opfer Date: Fri, 31 Mar 2006 02:31:12 -0800 Subject: [PATCH] LED: add device support for tosa Adds LED drivers for LEDs found on the Sharp Zaurus c6000 model (tosa). Signed-off-by: Dirk Opfer Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-pxa/tosa.c | 9 ++++ drivers/leds/Kconfig | 7 +++ drivers/leds/Makefile | 1 + drivers/leds/leds-tosa.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 drivers/leds/leds-tosa.c (limited to 'drivers') diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 66ec71756d0f..76c0e7f0a219 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -251,10 +251,19 @@ static struct platform_device tosakbd_device = { .id = -1, }; +/* + * Tosa LEDs + */ +static struct platform_device tosaled_device = { + .name = "tosa-led", + .id = -1, +}; + static struct platform_device *devices[] __initdata = { &tosascoop_device, &tosascoop_jc_device, &tosakbd_device, + &tosaled_device, }; static void __init tosa_init(void) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index d9e2f9853b9d..64dcdd3185c0 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -52,6 +52,13 @@ config LEDS_IXP4XX particular board must have LEDs and they must be connected to the GPIO lines. If unsure, say Y. +config LEDS_TOSA + tristate "LED Support for the Sharp SL-6000 series" + depends LEDS_CLASS && PXA_SHARPSL + help + This option enables support for the LEDs on Sharp Zaurus + SL-6000 series. + config LEDS_TRIGGER_TIMER tristate "LED Timer Trigger" depends LEDS_TRIGGERS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index b1187c0b36ce..9d2930f89d03 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o +obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/drivers/leds/leds-tosa.c b/drivers/leds/leds-tosa.c new file mode 100644 index 000000000000..c9e8cc1ec481 --- /dev/null +++ b/drivers/leds/leds-tosa.c @@ -0,0 +1,131 @@ +/* + * LED Triggers Core + * + * Copyright 2005 Dirk Opfer + * + * Author: Dirk Opfer + * based on spitz.c + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +static void tosaled_amber_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + if (value) + set_scoop_gpio(&tosascoop_jc_device.dev, + TOSA_SCOOP_JC_CHRG_ERR_LED); + else + reset_scoop_gpio(&tosascoop_jc_device.dev, + TOSA_SCOOP_JC_CHRG_ERR_LED); +} + +static void tosaled_green_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + if (value) + set_scoop_gpio(&tosascoop_jc_device.dev, + TOSA_SCOOP_JC_NOTE_LED); + else + reset_scoop_gpio(&tosascoop_jc_device.dev, + TOSA_SCOOP_JC_NOTE_LED); +} + +static struct led_classdev tosa_amber_led = { + .name = "tosa:amber", + .default_trigger = "sharpsl-charge", + .brightness_set = tosaled_amber_set, +}; + +static struct led_classdev tosa_green_led = { + .name = "tosa:green", + .default_trigger = "nand-disk", + .brightness_set = tosaled_green_set, +}; + +#ifdef CONFIG_PM +static int tosaled_suspend(struct platform_device *dev, pm_message_t state) +{ +#ifdef CONFIG_LEDS_TRIGGERS + if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name, + "sharpsl-charge")) +#endif + led_classdev_suspend(&tosa_amber_led); + led_classdev_suspend(&tosa_green_led); + return 0; +} + +static int tosaled_resume(struct platform_device *dev) +{ + led_classdev_resume(&tosa_amber_led); + led_classdev_resume(&tosa_green_led); + return 0; +} +#else +#define tosaled_suspend NULL +#define tosaled_resume NULL +#endif + +static int tosaled_probe(struct platform_device *pdev) +{ + int ret; + + ret = led_classdev_register(&pdev->dev, &tosa_amber_led); + if (ret < 0) + return ret; + + ret = led_classdev_register(&pdev->dev, &tosa_green_led); + if (ret < 0) + led_classdev_unregister(&tosa_amber_led); + + return ret; +} + +static int tosaled_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&tosa_amber_led); + led_classdev_unregister(&tosa_green_led); + + return 0; +} + +static struct platform_driver tosaled_driver = { + .probe = tosaled_probe, + .remove = tosaled_remove, + .suspend = tosaled_suspend, + .resume = tosaled_resume, + .driver = { + .name = "tosa-led", + }, +}; + +static int __init tosaled_init(void) +{ + return platform_driver_register(&tosaled_driver); +} + +static void __exit tosaled_exit(void) +{ + platform_driver_unregister(&tosaled_driver); +} + +module_init(tosaled_init); +module_exit(tosaled_exit); + +MODULE_AUTHOR("Dirk Opfer "); +MODULE_DESCRIPTION("Tosa LED driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 8fe833c1b010489b71b082e553b1dfa80ef81061 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:14 -0800 Subject: [PATCH] LED: add NAND MTD activity LED trigger Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/nand/nand_base.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5d222460b42a..95e96fa1fceb 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -80,6 +80,7 @@ #include #include #include +#include #include #ifdef CONFIG_MTD_PARTITIONS @@ -515,6 +516,8 @@ static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, i return nand_isbad_bbt (mtd, ofs, allowbbt); } +DEFINE_LED_TRIGGER(nand_led_trigger); + /* * Wait for the ready pin, after a command * The timeout is catched later. @@ -524,12 +527,14 @@ static void nand_wait_ready(struct mtd_info *mtd) struct nand_chip *this = mtd->priv; unsigned long timeo = jiffies + 2; + led_trigger_event(nand_led_trigger, LED_FULL); /* wait until command is processed or timeout occures */ do { if (this->dev_ready(mtd)) - return; + break; touch_softlockup_watchdog(); } while (time_before(jiffies, timeo)); + led_trigger_event(nand_led_trigger, LED_OFF); } /** @@ -817,6 +822,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) else timeo += (HZ * 20) / 1000; + led_trigger_event(nand_led_trigger, LED_FULL); + /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ ndelay (100); @@ -840,6 +847,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) } cond_resched(); } + led_trigger_event(nand_led_trigger, LED_OFF); + status = (int) this->read_byte(mtd); return status; } @@ -2724,6 +2733,21 @@ void nand_release (struct mtd_info *mtd) EXPORT_SYMBOL_GPL (nand_scan); EXPORT_SYMBOL_GPL (nand_release); + +static int __init nand_base_init(void) +{ + led_trigger_register_simple("nand-disk", &nand_led_trigger); + return 0; +} + +static void __exit nand_base_exit(void) +{ + led_trigger_unregister_simple(nand_led_trigger); +} + +module_init(nand_base_init); +module_exit(nand_base_exit); + MODULE_LICENSE ("GPL"); MODULE_AUTHOR ("Steven J. Hill , Thomas Gleixner "); MODULE_DESCRIPTION ("Generic NAND flash driver code"); -- cgit v1.2.3-59-g8ed1b From 03731fbdd09f8db4af86dbf437e3169fb1920d5e Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:15 -0800 Subject: [PATCH] Ensure ide-taskfile calls any driver specific end_request function Ensure ide-taskfile.c calls any driver specific end_request function if present. Signed-off-by: Richard Purdie Cc: Alan Cox Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-taskfile.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 0606bd2f6020..9233b8109a0f 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -375,7 +375,13 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) } } - ide_end_request(drive, 1, rq->hard_nr_sectors); + if (rq->rq_disk) { + ide_driver_t *drv; + + drv = *(ide_driver_t **)rq->rq_disk->private_data;; + drv->end_request(drive, 1, rq->hard_nr_sectors); + } else + ide_end_request(drive, 1, rq->hard_nr_sectors); } /* -- cgit v1.2.3-59-g8ed1b From 2bfb646cdf348cb77c572f06d5b9d17ea205c7e2 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:16 -0800 Subject: [PATCH] LED: Add IDE disk activity LED trigger Add an LED trigger for IDE disk activity to the ide-disk driver. Signed-off-by: Richard Purdie Acked-by: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-disk.c | 3 ++ drivers/leds/Kconfig | 7 +++++ drivers/leds/Makefile | 1 + drivers/leds/ledtrig-ide-disk.c | 62 +++++++++++++++++++++++++++++++++++++++++ include/linux/leds.h | 8 ++++++ 5 files changed, 81 insertions(+) create mode 100644 drivers/leds/ledtrig-ide-disk.c (limited to 'drivers') diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index ccf528d733bf..a5017de72da5 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -61,6 +61,7 @@ #include #include #include +#include #define _IDE_DISK @@ -317,6 +318,8 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s return ide_stopped; } + ledtrig_ide_activity(); + pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n", drive->name, rq_data_dir(rq) == READ ? "read" : "writ", (unsigned long long)block, rq->nr_sectors, diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 64dcdd3185c0..2c4f20b7f021 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -66,5 +66,12 @@ config LEDS_TRIGGER_TIMER This allows LEDs to be controlled by a programmable timer via sysfs. If unsure, say Y. +config LEDS_TRIGGER_IDE_DISK + bool "LED Timer Trigger" + depends LEDS_TRIGGERS && BLK_DEV_IDEDISK + help + This allows LEDs to be controlled by IDE disk activity. + If unsure, say Y. + endmenu diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 9d2930f89d03..40699d3cabbf 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o +obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c new file mode 100644 index 000000000000..fa651886ab4f --- /dev/null +++ b/drivers/leds/ledtrig-ide-disk.c @@ -0,0 +1,62 @@ +/* + * LED IDE-Disk Activity Trigger + * + * Copyright 2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * 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 +#include +#include + +static void ledtrig_ide_timerfunc(unsigned long data); + +DEFINE_LED_TRIGGER(ledtrig_ide); +static DEFINE_TIMER(ledtrig_ide_timer, ledtrig_ide_timerfunc, 0, 0); +static int ide_activity; +static int ide_lastactivity; + +void ledtrig_ide_activity(void) +{ + ide_activity++; + if (!timer_pending(&ledtrig_ide_timer)) + mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10)); +} +EXPORT_SYMBOL(ledtrig_ide_activity); + +static void ledtrig_ide_timerfunc(unsigned long data) +{ + if (ide_lastactivity != ide_activity) { + ide_lastactivity = ide_activity; + led_trigger_event(ledtrig_ide, LED_FULL); + mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10)); + } else { + led_trigger_event(ledtrig_ide, LED_OFF); + } +} + +static int __init ledtrig_ide_init(void) +{ + led_trigger_register_simple("ide-disk", &ledtrig_ide); + return 0; +} + +static void __exit ledtrig_ide_exit(void) +{ + led_trigger_unregister_simple(ledtrig_ide); +} + +module_init(ledtrig_ide_init); +module_exit(ledtrig_ide_exit); + +MODULE_AUTHOR("Richard Purdie "); +MODULE_DESCRIPTION("LED IDE Disk Activity Trigger"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/leds.h b/include/linux/leds.h index 404575c3dd5a..4617e75903b0 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -100,4 +100,12 @@ extern void led_trigger_event(struct led_trigger *trigger, #define led_trigger_event(x, y) do {} while(0) #endif + +/* Trigger specific functions */ +#ifdef CONFIG_LEDS_TRIGGER_IDE_DISK +extern void ledtrig_ide_activity(void); +#else +#define ledtrig_ide_activity() do {} while(0) +#endif + #endif /* __LINUX_LEDS_H_INCLUDED */ -- cgit v1.2.3-59-g8ed1b From 1a37d5f51020b9967d4b4094f6d627d0873a6469 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Fri, 31 Mar 2006 02:31:45 -0800 Subject: [PATCH] fbcon: Save current display during initialization The current display was not saved during initialization. This leads to hard to track console corruption, such as a misplaced cursor, which is correctible by switching consoles. Fix this minor bug. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index d7351560f581..ca020719d20b 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -1142,6 +1142,7 @@ static void fbcon_init(struct vc_data *vc, int init) set_blitting_type(vc, info); } + ops->p = &fb_display[fg_console]; } static void fbcon_deinit(struct vc_data *vc) -- cgit v1.2.3-59-g8ed1b From 9b0e1c5dd2941aec566047e10a5cc929ca7f7d4f Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Fri, 31 Mar 2006 02:31:46 -0800 Subject: [PATCH] w100fb: Add acceleration support to ATI Imageon Add acceleration support in w100fb.c (i.e. ATI Imageons) for the copyarea and fillrect operations. Signed-off-by: Alberto Mardegan Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/w100fb.c | 162 ++++++++++- drivers/video/w100fb.h | 748 ++++++++++++++++++++++++++++++------------------- 2 files changed, 611 insertions(+), 299 deletions(-) (limited to 'drivers') diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index f6e24ee85f07..5fc86ea20692 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -4,8 +4,9 @@ * Frame Buffer Device for ATI Imageon w100 (Wallaby) * * Copyright (C) 2002, ATI Corp. - * Copyright (C) 2004-2005 Richard Purdie + * Copyright (C) 2004-2006 Richard Purdie * Copyright (c) 2005 Ian Molton + * Copyright (c) 2006 Alberto Mardegan * * Rewritten for 2.6 by Richard Purdie * @@ -14,6 +15,9 @@ * * w32xx support by Ian Molton * + * Hardware acceleration support by Alberto Mardegan + * + * * 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. @@ -47,6 +51,7 @@ static void w100_set_dispregs(struct w100fb_par*); static void w100_update_enable(void); static void w100_update_disable(void); static void calc_hsync(struct w100fb_par *par); +static void w100_init_graphic_engine(struct w100fb_par *par); struct w100_pll_info *w100_get_xtal_table(unsigned int freq); /* Pseudo palette size */ @@ -248,6 +253,152 @@ static int w100fb_blank(int blank_mode, struct fb_info *info) } +static void w100_fifo_wait(int entries) +{ + union rbbm_status_u status; + int i; + + for (i = 0; i < 2000000; i++) { + status.val = readl(remapped_regs + mmRBBM_STATUS); + if (status.f.cmdfifo_avail >= entries) + return; + udelay(1); + } + printk(KERN_ERR "w100fb: FIFO Timeout!\n"); +} + + +static int w100fb_sync(struct fb_info *info) +{ + union rbbm_status_u status; + int i; + + for (i = 0; i < 2000000; i++) { + status.val = readl(remapped_regs + mmRBBM_STATUS); + if (!status.f.gui_active) + return 0; + udelay(1); + } + printk(KERN_ERR "w100fb: Graphic engine timeout!\n"); + return -EBUSY; +} + + +static void w100_init_graphic_engine(struct w100fb_par *par) +{ + union dp_gui_master_cntl_u gmc; + union dp_mix_u dp_mix; + union dp_datatype_u dp_datatype; + union dp_cntl_u dp_cntl; + + w100_fifo_wait(4); + writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET); + writel(par->xres, remapped_regs + mmDST_PITCH); + writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET); + writel(par->xres, remapped_regs + mmSRC_PITCH); + + w100_fifo_wait(3); + writel(0, remapped_regs + mmSC_TOP_LEFT); + writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT); + writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT); + + w100_fifo_wait(4); + dp_cntl.val = 0; + dp_cntl.f.dst_x_dir = 1; + dp_cntl.f.dst_y_dir = 1; + dp_cntl.f.src_x_dir = 1; + dp_cntl.f.src_y_dir = 1; + dp_cntl.f.dst_major_x = 1; + dp_cntl.f.src_major_x = 1; + writel(dp_cntl.val, remapped_regs + mmDP_CNTL); + + gmc.val = 0; + gmc.f.gmc_src_pitch_offset_cntl = 1; + gmc.f.gmc_dst_pitch_offset_cntl = 1; + gmc.f.gmc_src_clipping = 1; + gmc.f.gmc_dst_clipping = 1; + gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE; + gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */ + gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST; + gmc.f.gmc_byte_pix_order = 1; + gmc.f.gmc_default_sel = 0; + gmc.f.gmc_rop3 = ROP3_SRCCOPY; + gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR; + gmc.f.gmc_clr_cmp_fcn_dis = 1; + gmc.f.gmc_wr_msk_dis = 1; + gmc.f.gmc_dp_op = DP_OP_ROP; + writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL); + + dp_datatype.val = dp_mix.val = 0; + dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype; + dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype; + dp_datatype.f.dp_src2_type = 0; + dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype; + dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype; + dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order; + writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE); + + dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source; + dp_mix.f.dp_src2_source = 1; + dp_mix.f.dp_rop3 = gmc.f.gmc_rop3; + dp_mix.f.dp_op = gmc.f.gmc_dp_op; + writel(dp_mix.val, remapped_regs + mmDP_MIX); +} + + +static void w100fb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ + union dp_gui_master_cntl_u gmc; + + if (info->state != FBINFO_STATE_RUNNING) + return; + if (info->flags & FBINFO_HWACCEL_DISABLED) { + cfb_fillrect(info, rect); + return; + } + + gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL); + gmc.f.gmc_rop3 = ROP3_PATCOPY; + gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR; + w100_fifo_wait(2); + writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL); + writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR); + + w100_fifo_wait(2); + writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X); + writel((rect->width << 16) | (rect->height & 0xffff), + remapped_regs + mmDST_WIDTH_HEIGHT); +} + + +static void w100fb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ + u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; + u32 h = area->height, w = area->width; + union dp_gui_master_cntl_u gmc; + + if (info->state != FBINFO_STATE_RUNNING) + return; + if (info->flags & FBINFO_HWACCEL_DISABLED) { + cfb_copyarea(info, area); + return; + } + + gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL); + gmc.f.gmc_rop3 = ROP3_SRCCOPY; + gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE; + w100_fifo_wait(1); + writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL); + + w100_fifo_wait(3); + writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X); + writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X); + writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT); +} + + /* * Change the resolution by calling the appropriate hardware functions */ @@ -265,6 +416,7 @@ static void w100fb_activate_var(struct w100fb_par *par) w100_init_lcd(par); w100_set_dispregs(par); w100_update_enable(); + w100_init_graphic_engine(par); calc_hsync(par); @@ -394,9 +546,10 @@ static struct fb_ops w100fb_ops = { .fb_set_par = w100fb_set_par, .fb_setcolreg = w100fb_setcolreg, .fb_blank = w100fb_blank, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, + .fb_fillrect = w100fb_fillrect, + .fb_copyarea = w100fb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_sync = w100fb_sync, }; #ifdef CONFIG_PM @@ -543,7 +696,8 @@ int __init w100fb_probe(struct platform_device *pdev) } info->fbops = &w100fb_ops; - info->flags = FBINFO_DEFAULT; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | + FBINFO_HWACCEL_FILLRECT; info->node = -1; info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE); info->screen_size = REMAPPED_FB_LEN; diff --git a/drivers/video/w100fb.h b/drivers/video/w100fb.h index 7a58a1e3e427..fffae7b4f6e9 100644 --- a/drivers/video/w100fb.h +++ b/drivers/video/w100fb.h @@ -122,15 +122,32 @@ /* Block DISPLAY End: */ /* Block GFX Start: */ +#define mmDST_OFFSET 0x1004 +#define mmDST_PITCH 0x1008 +#define mmDST_Y_X 0x1038 +#define mmDST_WIDTH_HEIGHT 0x1198 +#define mmDP_GUI_MASTER_CNTL 0x106C #define mmBRUSH_OFFSET 0x108C #define mmBRUSH_Y_X 0x1074 +#define mmDP_BRUSH_FRGD_CLR 0x107C +#define mmSRC_OFFSET 0x11AC +#define mmSRC_PITCH 0x11B0 +#define mmSRC_Y_X 0x1034 #define mmDEFAULT_PITCH_OFFSET 0x10A0 #define mmDEFAULT_SC_BOTTOM_RIGHT 0x10A8 #define mmDEFAULT2_SC_BOTTOM_RIGHT 0x10AC +#define mmSC_TOP_LEFT 0x11BC +#define mmSC_BOTTOM_RIGHT 0x11C0 +#define mmSRC_SC_BOTTOM_RIGHT 0x11C4 #define mmGLOBAL_ALPHA 0x1210 #define mmFILTER_COEF 0x1214 #define mmMVC_CNTL_START 0x11E0 #define mmE2_ARITHMETIC_CNTL 0x1220 +#define mmDP_CNTL 0x11C8 +#define mmDP_CNTL_DST_DIR 0x11CC +#define mmDP_DATATYPE 0x12C4 +#define mmDP_MIX 0x12C8 +#define mmDP_WRITE_MSK 0x12CC #define mmENG_CNTL 0x13E8 #define mmENG_PERF_CNT 0x13F0 /* Block GFX End: */ @@ -179,6 +196,7 @@ /* Block RBBM Start: */ #define mmWAIT_UNTIL 0x1400 #define mmISYNC_CNTL 0x1404 +#define mmRBBM_STATUS 0x0140 #define mmRBBM_CNTL 0x0144 #define mmNQWAIT_UNTIL 0x0150 /* Block RBBM End: */ @@ -225,147 +243,147 @@ /* Register structure definitions */ struct wrap_top_dir_t { - unsigned long top_addr : 23; - unsigned long : 9; + u32 top_addr : 23; + u32 : 9; } __attribute__((packed)); union wrap_top_dir_u { - unsigned long val : 32; + u32 val : 32; struct wrap_top_dir_t f; } __attribute__((packed)); struct wrap_start_dir_t { - unsigned long start_addr : 23; - unsigned long : 9; + u32 start_addr : 23; + u32 : 9; } __attribute__((packed)); union wrap_start_dir_u { - unsigned long val : 32; + u32 val : 32; struct wrap_start_dir_t f; } __attribute__((packed)); struct cif_cntl_t { - unsigned long swap_reg : 2; - unsigned long swap_fbuf_1 : 2; - unsigned long swap_fbuf_2 : 2; - unsigned long swap_fbuf_3 : 2; - unsigned long pmi_int_disable : 1; - unsigned long pmi_schmen_disable : 1; - unsigned long intb_oe : 1; - unsigned long en_wait_to_compensate_dq_prop_dly : 1; - unsigned long compensate_wait_rd_size : 2; - unsigned long wait_asserted_timeout_val : 2; - unsigned long wait_masked_val : 2; - unsigned long en_wait_timeout : 1; - unsigned long en_one_clk_setup_before_wait : 1; - unsigned long interrupt_active_high : 1; - unsigned long en_overwrite_straps : 1; - unsigned long strap_wait_active_hi : 1; - unsigned long lat_busy_count : 2; - unsigned long lat_rd_pm4_sclk_busy : 1; - unsigned long dis_system_bits : 1; - unsigned long dis_mr : 1; - unsigned long cif_spare_1 : 4; + u32 swap_reg : 2; + u32 swap_fbuf_1 : 2; + u32 swap_fbuf_2 : 2; + u32 swap_fbuf_3 : 2; + u32 pmi_int_disable : 1; + u32 pmi_schmen_disable : 1; + u32 intb_oe : 1; + u32 en_wait_to_compensate_dq_prop_dly : 1; + u32 compensate_wait_rd_size : 2; + u32 wait_asserted_timeout_val : 2; + u32 wait_masked_val : 2; + u32 en_wait_timeout : 1; + u32 en_one_clk_setup_before_wait : 1; + u32 interrupt_active_high : 1; + u32 en_overwrite_straps : 1; + u32 strap_wait_active_hi : 1; + u32 lat_busy_count : 2; + u32 lat_rd_pm4_sclk_busy : 1; + u32 dis_system_bits : 1; + u32 dis_mr : 1; + u32 cif_spare_1 : 4; } __attribute__((packed)); union cif_cntl_u { - unsigned long val : 32; + u32 val : 32; struct cif_cntl_t f; } __attribute__((packed)); struct cfgreg_base_t { - unsigned long cfgreg_base : 24; - unsigned long : 8; + u32 cfgreg_base : 24; + u32 : 8; } __attribute__((packed)); union cfgreg_base_u { - unsigned long val : 32; + u32 val : 32; struct cfgreg_base_t f; } __attribute__((packed)); struct cif_io_t { - unsigned long dq_srp : 1; - unsigned long dq_srn : 1; - unsigned long dq_sp : 4; - unsigned long dq_sn : 4; - unsigned long waitb_srp : 1; - unsigned long waitb_srn : 1; - unsigned long waitb_sp : 4; - unsigned long waitb_sn : 4; - unsigned long intb_srp : 1; - unsigned long intb_srn : 1; - unsigned long intb_sp : 4; - unsigned long intb_sn : 4; - unsigned long : 2; + u32 dq_srp : 1; + u32 dq_srn : 1; + u32 dq_sp : 4; + u32 dq_sn : 4; + u32 waitb_srp : 1; + u32 waitb_srn : 1; + u32 waitb_sp : 4; + u32 waitb_sn : 4; + u32 intb_srp : 1; + u32 intb_srn : 1; + u32 intb_sp : 4; + u32 intb_sn : 4; + u32 : 2; } __attribute__((packed)); union cif_io_u { - unsigned long val : 32; + u32 val : 32; struct cif_io_t f; } __attribute__((packed)); struct cif_read_dbg_t { - unsigned long unpacker_pre_fetch_trig_gen : 2; - unsigned long dly_second_rd_fetch_trig : 1; - unsigned long rst_rd_burst_id : 1; - unsigned long dis_rd_burst_id : 1; - unsigned long en_block_rd_when_packer_is_not_emp : 1; - unsigned long dis_pre_fetch_cntl_sm : 1; - unsigned long rbbm_chrncy_dis : 1; - unsigned long rbbm_rd_after_wr_lat : 2; - unsigned long dis_be_during_rd : 1; - unsigned long one_clk_invalidate_pulse : 1; - unsigned long dis_chnl_priority : 1; - unsigned long rst_read_path_a_pls : 1; - unsigned long rst_read_path_b_pls : 1; - unsigned long dis_reg_rd_fetch_trig : 1; - unsigned long dis_rd_fetch_trig_from_ind_addr : 1; - unsigned long dis_rd_same_byte_to_trig_fetch : 1; - unsigned long dis_dir_wrap : 1; - unsigned long dis_ring_buf_to_force_dec : 1; - unsigned long dis_addr_comp_in_16bit : 1; - unsigned long clr_w : 1; - unsigned long err_rd_tag_is_3 : 1; - unsigned long err_load_when_ful_a : 1; - unsigned long err_load_when_ful_b : 1; - unsigned long : 7; + u32 unpacker_pre_fetch_trig_gen : 2; + u32 dly_second_rd_fetch_trig : 1; + u32 rst_rd_burst_id : 1; + u32 dis_rd_burst_id : 1; + u32 en_block_rd_when_packer_is_not_emp : 1; + u32 dis_pre_fetch_cntl_sm : 1; + u32 rbbm_chrncy_dis : 1; + u32 rbbm_rd_after_wr_lat : 2; + u32 dis_be_during_rd : 1; + u32 one_clk_invalidate_pulse : 1; + u32 dis_chnl_priority : 1; + u32 rst_read_path_a_pls : 1; + u32 rst_read_path_b_pls : 1; + u32 dis_reg_rd_fetch_trig : 1; + u32 dis_rd_fetch_trig_from_ind_addr : 1; + u32 dis_rd_same_byte_to_trig_fetch : 1; + u32 dis_dir_wrap : 1; + u32 dis_ring_buf_to_force_dec : 1; + u32 dis_addr_comp_in_16bit : 1; + u32 clr_w : 1; + u32 err_rd_tag_is_3 : 1; + u32 err_load_when_ful_a : 1; + u32 err_load_when_ful_b : 1; + u32 : 7; } __attribute__((packed)); union cif_read_dbg_u { - unsigned long val : 32; + u32 val : 32; struct cif_read_dbg_t f; } __attribute__((packed)); struct cif_write_dbg_t { - unsigned long packer_timeout_count : 2; - unsigned long en_upper_load_cond : 1; - unsigned long en_chnl_change_cond : 1; - unsigned long dis_addr_comp_cond : 1; - unsigned long dis_load_same_byte_addr_cond : 1; - unsigned long dis_timeout_cond : 1; - unsigned long dis_timeout_during_rbbm : 1; - unsigned long dis_packer_ful_during_rbbm_timeout : 1; - unsigned long en_dword_split_to_rbbm : 1; - unsigned long en_dummy_val : 1; - unsigned long dummy_val_sel : 1; - unsigned long mask_pm4_wrptr_dec : 1; - unsigned long dis_mc_clean_cond : 1; - unsigned long err_two_reqi_during_ful : 1; - unsigned long err_reqi_during_idle_clk : 1; - unsigned long err_global : 1; - unsigned long en_wr_buf_dbg_load : 1; - unsigned long en_wr_buf_dbg_path : 1; - unsigned long sel_wr_buf_byte : 3; - unsigned long dis_rd_flush_wr : 1; - unsigned long dis_packer_ful_cond : 1; - unsigned long dis_invalidate_by_ops_chnl : 1; - unsigned long en_halt_when_reqi_err : 1; - unsigned long cif_spare_2 : 5; - unsigned long : 1; + u32 packer_timeout_count : 2; + u32 en_upper_load_cond : 1; + u32 en_chnl_change_cond : 1; + u32 dis_addr_comp_cond : 1; + u32 dis_load_same_byte_addr_cond : 1; + u32 dis_timeout_cond : 1; + u32 dis_timeout_during_rbbm : 1; + u32 dis_packer_ful_during_rbbm_timeout : 1; + u32 en_dword_split_to_rbbm : 1; + u32 en_dummy_val : 1; + u32 dummy_val_sel : 1; + u32 mask_pm4_wrptr_dec : 1; + u32 dis_mc_clean_cond : 1; + u32 err_two_reqi_during_ful : 1; + u32 err_reqi_during_idle_clk : 1; + u32 err_global : 1; + u32 en_wr_buf_dbg_load : 1; + u32 en_wr_buf_dbg_path : 1; + u32 sel_wr_buf_byte : 3; + u32 dis_rd_flush_wr : 1; + u32 dis_packer_ful_cond : 1; + u32 dis_invalidate_by_ops_chnl : 1; + u32 en_halt_when_reqi_err : 1; + u32 cif_spare_2 : 5; + u32 : 1; } __attribute__((packed)); union cif_write_dbg_u { - unsigned long val : 32; + u32 val : 32; struct cif_write_dbg_t f; } __attribute__((packed)); @@ -403,327 +421,327 @@ union cpu_defaults_u { } __attribute__((packed)); struct crtc_total_t { - unsigned long crtc_h_total : 10; - unsigned long : 6; - unsigned long crtc_v_total : 10; - unsigned long : 6; + u32 crtc_h_total : 10; + u32 : 6; + u32 crtc_v_total : 10; + u32 : 6; } __attribute__((packed)); union crtc_total_u { - unsigned long val : 32; + u32 val : 32; struct crtc_total_t f; } __attribute__((packed)); struct crtc_ss_t { - unsigned long ss_start : 10; - unsigned long : 6; - unsigned long ss_end : 10; - unsigned long : 2; - unsigned long ss_align : 1; - unsigned long ss_pol : 1; - unsigned long ss_run_mode : 1; - unsigned long ss_en : 1; + u32 ss_start : 10; + u32 : 6; + u32 ss_end : 10; + u32 : 2; + u32 ss_align : 1; + u32 ss_pol : 1; + u32 ss_run_mode : 1; + u32 ss_en : 1; } __attribute__((packed)); union crtc_ss_u { - unsigned long val : 32; + u32 val : 32; struct crtc_ss_t f; } __attribute__((packed)); struct active_h_disp_t { - unsigned long active_h_start : 10; - unsigned long : 6; - unsigned long active_h_end : 10; - unsigned long : 6; + u32 active_h_start : 10; + u32 : 6; + u32 active_h_end : 10; + u32 : 6; } __attribute__((packed)); union active_h_disp_u { - unsigned long val : 32; + u32 val : 32; struct active_h_disp_t f; } __attribute__((packed)); struct active_v_disp_t { - unsigned long active_v_start : 10; - unsigned long : 6; - unsigned long active_v_end : 10; - unsigned long : 6; + u32 active_v_start : 10; + u32 : 6; + u32 active_v_end : 10; + u32 : 6; } __attribute__((packed)); union active_v_disp_u { - unsigned long val : 32; + u32 val : 32; struct active_v_disp_t f; } __attribute__((packed)); struct graphic_h_disp_t { - unsigned long graphic_h_start : 10; - unsigned long : 6; - unsigned long graphic_h_end : 10; - unsigned long : 6; + u32 graphic_h_start : 10; + u32 : 6; + u32 graphic_h_end : 10; + u32 : 6; } __attribute__((packed)); union graphic_h_disp_u { - unsigned long val : 32; + u32 val : 32; struct graphic_h_disp_t f; } __attribute__((packed)); struct graphic_v_disp_t { - unsigned long graphic_v_start : 10; - unsigned long : 6; - unsigned long graphic_v_end : 10; - unsigned long : 6; + u32 graphic_v_start : 10; + u32 : 6; + u32 graphic_v_end : 10; + u32 : 6; } __attribute__((packed)); union graphic_v_disp_u{ - unsigned long val : 32; + u32 val : 32; struct graphic_v_disp_t f; } __attribute__((packed)); struct graphic_ctrl_t_w100 { - unsigned long color_depth : 3; - unsigned long portrait_mode : 2; - unsigned long low_power_on : 1; - unsigned long req_freq : 4; - unsigned long en_crtc : 1; - unsigned long en_graphic_req : 1; - unsigned long en_graphic_crtc : 1; - unsigned long total_req_graphic : 9; - unsigned long lcd_pclk_on : 1; - unsigned long lcd_sclk_on : 1; - unsigned long pclk_running : 1; - unsigned long sclk_running : 1; - unsigned long : 6; + u32 color_depth : 3; + u32 portrait_mode : 2; + u32 low_power_on : 1; + u32 req_freq : 4; + u32 en_crtc : 1; + u32 en_graphic_req : 1; + u32 en_graphic_crtc : 1; + u32 total_req_graphic : 9; + u32 lcd_pclk_on : 1; + u32 lcd_sclk_on : 1; + u32 pclk_running : 1; + u32 sclk_running : 1; + u32 : 6; } __attribute__((packed)); struct graphic_ctrl_t_w32xx { - unsigned long color_depth : 3; - unsigned long portrait_mode : 2; - unsigned long low_power_on : 1; - unsigned long req_freq : 4; - unsigned long en_crtc : 1; - unsigned long en_graphic_req : 1; - unsigned long en_graphic_crtc : 1; - unsigned long total_req_graphic : 10; - unsigned long lcd_pclk_on : 1; - unsigned long lcd_sclk_on : 1; - unsigned long pclk_running : 1; - unsigned long sclk_running : 1; - unsigned long : 5; + u32 color_depth : 3; + u32 portrait_mode : 2; + u32 low_power_on : 1; + u32 req_freq : 4; + u32 en_crtc : 1; + u32 en_graphic_req : 1; + u32 en_graphic_crtc : 1; + u32 total_req_graphic : 10; + u32 lcd_pclk_on : 1; + u32 lcd_sclk_on : 1; + u32 pclk_running : 1; + u32 sclk_running : 1; + u32 : 5; } __attribute__((packed)); union graphic_ctrl_u { - unsigned long val : 32; + u32 val : 32; struct graphic_ctrl_t_w100 f_w100; struct graphic_ctrl_t_w32xx f_w32xx; } __attribute__((packed)); struct video_ctrl_t { - unsigned long video_mode : 1; - unsigned long keyer_en : 1; - unsigned long en_video_req : 1; - unsigned long en_graphic_req_video : 1; - unsigned long en_video_crtc : 1; - unsigned long video_hor_exp : 2; - unsigned long video_ver_exp : 2; - unsigned long uv_combine : 1; - unsigned long total_req_video : 9; - unsigned long video_ch_sel : 1; - unsigned long video_portrait : 2; - unsigned long yuv2rgb_en : 1; - unsigned long yuv2rgb_option : 1; - unsigned long video_inv_hor : 1; - unsigned long video_inv_ver : 1; - unsigned long gamma_sel : 2; - unsigned long dis_limit : 1; - unsigned long en_uv_hblend : 1; - unsigned long rgb_gamma_sel : 2; + u32 video_mode : 1; + u32 keyer_en : 1; + u32 en_video_req : 1; + u32 en_graphic_req_video : 1; + u32 en_video_crtc : 1; + u32 video_hor_exp : 2; + u32 video_ver_exp : 2; + u32 uv_combine : 1; + u32 total_req_video : 9; + u32 video_ch_sel : 1; + u32 video_portrait : 2; + u32 yuv2rgb_en : 1; + u32 yuv2rgb_option : 1; + u32 video_inv_hor : 1; + u32 video_inv_ver : 1; + u32 gamma_sel : 2; + u32 dis_limit : 1; + u32 en_uv_hblend : 1; + u32 rgb_gamma_sel : 2; } __attribute__((packed)); union video_ctrl_u { - unsigned long val : 32; + u32 val : 32; struct video_ctrl_t f; } __attribute__((packed)); struct disp_db_buf_cntl_rd_t { - unsigned long en_db_buf : 1; - unsigned long update_db_buf_done : 1; - unsigned long db_buf_cntl : 6; - unsigned long : 24; + u32 en_db_buf : 1; + u32 update_db_buf_done : 1; + u32 db_buf_cntl : 6; + u32 : 24; } __attribute__((packed)); union disp_db_buf_cntl_rd_u { - unsigned long val : 32; + u32 val : 32; struct disp_db_buf_cntl_rd_t f; } __attribute__((packed)); struct disp_db_buf_cntl_wr_t { - unsigned long en_db_buf : 1; - unsigned long update_db_buf : 1; - unsigned long db_buf_cntl : 6; - unsigned long : 24; + u32 en_db_buf : 1; + u32 update_db_buf : 1; + u32 db_buf_cntl : 6; + u32 : 24; } __attribute__((packed)); union disp_db_buf_cntl_wr_u { - unsigned long val : 32; + u32 val : 32; struct disp_db_buf_cntl_wr_t f; } __attribute__((packed)); struct gamma_value1_t { - unsigned long gamma1 : 8; - unsigned long gamma2 : 8; - unsigned long gamma3 : 8; - unsigned long gamma4 : 8; + u32 gamma1 : 8; + u32 gamma2 : 8; + u32 gamma3 : 8; + u32 gamma4 : 8; } __attribute__((packed)); union gamma_value1_u { - unsigned long val : 32; + u32 val : 32; struct gamma_value1_t f; } __attribute__((packed)); struct gamma_value2_t { - unsigned long gamma5 : 8; - unsigned long gamma6 : 8; - unsigned long gamma7 : 8; - unsigned long gamma8 : 8; + u32 gamma5 : 8; + u32 gamma6 : 8; + u32 gamma7 : 8; + u32 gamma8 : 8; } __attribute__((packed)); union gamma_value2_u { - unsigned long val : 32; + u32 val : 32; struct gamma_value2_t f; } __attribute__((packed)); struct gamma_slope_t { - unsigned long slope1 : 3; - unsigned long slope2 : 3; - unsigned long slope3 : 3; - unsigned long slope4 : 3; - unsigned long slope5 : 3; - unsigned long slope6 : 3; - unsigned long slope7 : 3; - unsigned long slope8 : 3; - unsigned long : 8; + u32 slope1 : 3; + u32 slope2 : 3; + u32 slope3 : 3; + u32 slope4 : 3; + u32 slope5 : 3; + u32 slope6 : 3; + u32 slope7 : 3; + u32 slope8 : 3; + u32 : 8; } __attribute__((packed)); union gamma_slope_u { - unsigned long val : 32; + u32 val : 32; struct gamma_slope_t f; } __attribute__((packed)); struct mc_ext_mem_location_t { - unsigned long mc_ext_mem_start : 16; - unsigned long mc_ext_mem_top : 16; + u32 mc_ext_mem_start : 16; + u32 mc_ext_mem_top : 16; } __attribute__((packed)); union mc_ext_mem_location_u { - unsigned long val : 32; + u32 val : 32; struct mc_ext_mem_location_t f; } __attribute__((packed)); struct mc_fb_location_t { - unsigned long mc_fb_start : 16; - unsigned long mc_fb_top : 16; + u32 mc_fb_start : 16; + u32 mc_fb_top : 16; } __attribute__((packed)); union mc_fb_location_u { - unsigned long val : 32; + u32 val : 32; struct mc_fb_location_t f; } __attribute__((packed)); struct clk_pin_cntl_t { - unsigned long osc_en : 1; - unsigned long osc_gain : 5; - unsigned long dont_use_xtalin : 1; - unsigned long xtalin_pm_en : 1; - unsigned long xtalin_dbl_en : 1; - unsigned long : 7; - unsigned long cg_debug : 16; + u32 osc_en : 1; + u32 osc_gain : 5; + u32 dont_use_xtalin : 1; + u32 xtalin_pm_en : 1; + u32 xtalin_dbl_en : 1; + u32 : 7; + u32 cg_debug : 16; } __attribute__((packed)); union clk_pin_cntl_u { - unsigned long val : 32; + u32 val : 32; struct clk_pin_cntl_t f; } __attribute__((packed)); struct pll_ref_fb_div_t { - unsigned long pll_ref_div : 4; - unsigned long : 4; - unsigned long pll_fb_div_int : 6; - unsigned long : 2; - unsigned long pll_fb_div_frac : 3; - unsigned long : 1; - unsigned long pll_reset_time : 4; - unsigned long pll_lock_time : 8; + u32 pll_ref_div : 4; + u32 : 4; + u32 pll_fb_div_int : 6; + u32 : 2; + u32 pll_fb_div_frac : 3; + u32 : 1; + u32 pll_reset_time : 4; + u32 pll_lock_time : 8; } __attribute__((packed)); union pll_ref_fb_div_u { - unsigned long val : 32; + u32 val : 32; struct pll_ref_fb_div_t f; } __attribute__((packed)); struct pll_cntl_t { - unsigned long pll_pwdn : 1; - unsigned long pll_reset : 1; - unsigned long pll_pm_en : 1; - unsigned long pll_mode : 1; - unsigned long pll_refclk_sel : 1; - unsigned long pll_fbclk_sel : 1; - unsigned long pll_tcpoff : 1; - unsigned long pll_pcp : 3; - unsigned long pll_pvg : 3; - unsigned long pll_vcofr : 1; - unsigned long pll_ioffset : 2; - unsigned long pll_pecc_mode : 2; - unsigned long pll_pecc_scon : 2; - unsigned long pll_dactal : 4; - unsigned long pll_cp_clip : 2; - unsigned long pll_conf : 3; - unsigned long pll_mbctrl : 2; - unsigned long pll_ring_off : 1; + u32 pll_pwdn : 1; + u32 pll_reset : 1; + u32 pll_pm_en : 1; + u32 pll_mode : 1; + u32 pll_refclk_sel : 1; + u32 pll_fbclk_sel : 1; + u32 pll_tcpoff : 1; + u32 pll_pcp : 3; + u32 pll_pvg : 3; + u32 pll_vcofr : 1; + u32 pll_ioffset : 2; + u32 pll_pecc_mode : 2; + u32 pll_pecc_scon : 2; + u32 pll_dactal : 4; + u32 pll_cp_clip : 2; + u32 pll_conf : 3; + u32 pll_mbctrl : 2; + u32 pll_ring_off : 1; } __attribute__((packed)); union pll_cntl_u { - unsigned long val : 32; + u32 val : 32; struct pll_cntl_t f; } __attribute__((packed)); struct sclk_cntl_t { - unsigned long sclk_src_sel : 2; - unsigned long : 2; - unsigned long sclk_post_div_fast : 4; - unsigned long sclk_clkon_hys : 3; - unsigned long sclk_post_div_slow : 4; - unsigned long disp_cg_ok2switch_en : 1; - unsigned long sclk_force_reg : 1; - unsigned long sclk_force_disp : 1; - unsigned long sclk_force_mc : 1; - unsigned long sclk_force_extmc : 1; - unsigned long sclk_force_cp : 1; - unsigned long sclk_force_e2 : 1; - unsigned long sclk_force_e3 : 1; - unsigned long sclk_force_idct : 1; - unsigned long sclk_force_bist : 1; - unsigned long busy_extend_cp : 1; - unsigned long busy_extend_e2 : 1; - unsigned long busy_extend_e3 : 1; - unsigned long busy_extend_idct : 1; - unsigned long : 3; + u32 sclk_src_sel : 2; + u32 : 2; + u32 sclk_post_div_fast : 4; + u32 sclk_clkon_hys : 3; + u32 sclk_post_div_slow : 4; + u32 disp_cg_ok2switch_en : 1; + u32 sclk_force_reg : 1; + u32 sclk_force_disp : 1; + u32 sclk_force_mc : 1; + u32 sclk_force_extmc : 1; + u32 sclk_force_cp : 1; + u32 sclk_force_e2 : 1; + u32 sclk_force_e3 : 1; + u32 sclk_force_idct : 1; + u32 sclk_force_bist : 1; + u32 busy_extend_cp : 1; + u32 busy_extend_e2 : 1; + u32 busy_extend_e3 : 1; + u32 busy_extend_idct : 1; + u32 : 3; } __attribute__((packed)); union sclk_cntl_u { - unsigned long val : 32; + u32 val : 32; struct sclk_cntl_t f; } __attribute__((packed)); struct pclk_cntl_t { - unsigned long pclk_src_sel : 2; - unsigned long : 2; - unsigned long pclk_post_div : 4; - unsigned long : 8; - unsigned long pclk_force_disp : 1; - unsigned long : 15; + u32 pclk_src_sel : 2; + u32 : 2; + u32 pclk_post_div : 4; + u32 : 8; + u32 pclk_force_disp : 1; + u32 : 15; } __attribute__((packed)); union pclk_cntl_u { - unsigned long val : 32; + u32 val : 32; struct pclk_cntl_t f; } __attribute__((packed)); @@ -735,36 +753,176 @@ union pclk_cntl_u { #define TESTCLK_SRC_XTAL 0x06 struct clk_test_cntl_t { - unsigned long testclk_sel : 4; - unsigned long : 3; - unsigned long start_check_freq : 1; - unsigned long tstcount_rst : 1; - unsigned long : 15; - unsigned long test_count : 8; + u32 testclk_sel : 4; + u32 : 3; + u32 start_check_freq : 1; + u32 tstcount_rst : 1; + u32 : 15; + u32 test_count : 8; } __attribute__((packed)); union clk_test_cntl_u { - unsigned long val : 32; + u32 val : 32; struct clk_test_cntl_t f; } __attribute__((packed)); struct pwrmgt_cntl_t { - unsigned long pwm_enable : 1; - unsigned long : 1; - unsigned long pwm_mode_req : 2; - unsigned long pwm_wakeup_cond : 2; - unsigned long pwm_fast_noml_hw_en : 1; - unsigned long pwm_noml_fast_hw_en : 1; - unsigned long pwm_fast_noml_cond : 4; - unsigned long pwm_noml_fast_cond : 4; - unsigned long pwm_idle_timer : 8; - unsigned long pwm_busy_timer : 8; + u32 pwm_enable : 1; + u32 : 1; + u32 pwm_mode_req : 2; + u32 pwm_wakeup_cond : 2; + u32 pwm_fast_noml_hw_en : 1; + u32 pwm_noml_fast_hw_en : 1; + u32 pwm_fast_noml_cond : 4; + u32 pwm_noml_fast_cond : 4; + u32 pwm_idle_timer : 8; + u32 pwm_busy_timer : 8; } __attribute__((packed)); union pwrmgt_cntl_u { - unsigned long val : 32; + u32 val : 32; struct pwrmgt_cntl_t f; } __attribute__((packed)); +#define SRC_DATATYPE_EQU_DST 3 + +#define ROP3_SRCCOPY 0xcc +#define ROP3_PATCOPY 0xf0 + +#define GMC_BRUSH_SOLID_COLOR 13 +#define GMC_BRUSH_NONE 15 + +#define DP_SRC_MEM_RECTANGULAR 2 + +#define DP_OP_ROP 0 + +struct dp_gui_master_cntl_t { + u32 gmc_src_pitch_offset_cntl : 1; + u32 gmc_dst_pitch_offset_cntl : 1; + u32 gmc_src_clipping : 1; + u32 gmc_dst_clipping : 1; + u32 gmc_brush_datatype : 4; + u32 gmc_dst_datatype : 4; + u32 gmc_src_datatype : 3; + u32 gmc_byte_pix_order : 1; + u32 gmc_default_sel : 1; + u32 gmc_rop3 : 8; + u32 gmc_dp_src_source : 3; + u32 gmc_clr_cmp_fcn_dis : 1; + u32 : 1; + u32 gmc_wr_msk_dis : 1; + u32 gmc_dp_op : 1; +} __attribute__((packed)); + +union dp_gui_master_cntl_u { + u32 val : 32; + struct dp_gui_master_cntl_t f; +} __attribute__((packed)); + +struct rbbm_status_t { + u32 cmdfifo_avail : 7; + u32 : 1; + u32 hirq_on_rbb : 1; + u32 cprq_on_rbb : 1; + u32 cfrq_on_rbb : 1; + u32 hirq_in_rtbuf : 1; + u32 cprq_in_rtbuf : 1; + u32 cfrq_in_rtbuf : 1; + u32 cf_pipe_busy : 1; + u32 eng_ev_busy : 1; + u32 cp_cmdstrm_busy : 1; + u32 e2_busy : 1; + u32 rb2d_busy : 1; + u32 rb3d_busy : 1; + u32 se_busy : 1; + u32 re_busy : 1; + u32 tam_busy : 1; + u32 tdm_busy : 1; + u32 pb_busy : 1; + u32 : 6; + u32 gui_active : 1; +} __attribute__((packed)); + +union rbbm_status_u { + u32 val : 32; + struct rbbm_status_t f; +} __attribute__((packed)); + +struct dp_datatype_t { + u32 dp_dst_datatype : 4; + u32 : 4; + u32 dp_brush_datatype : 4; + u32 dp_src2_type : 1; + u32 dp_src2_datatype : 3; + u32 dp_src_datatype : 3; + u32 : 11; + u32 dp_byte_pix_order : 1; + u32 : 1; +} __attribute__((packed)); + +union dp_datatype_u { + u32 val : 32; + struct dp_datatype_t f; +} __attribute__((packed)); + +struct dp_mix_t { + u32 : 8; + u32 dp_src_source : 3; + u32 dp_src2_source : 3; + u32 : 2; + u32 dp_rop3 : 8; + u32 dp_op : 1; + u32 : 7; +} __attribute__((packed)); + +union dp_mix_u { + u32 val : 32; + struct dp_mix_t f; +} __attribute__((packed)); + +struct eng_cntl_t { + u32 erc_reg_rd_ws : 1; + u32 erc_reg_wr_ws : 1; + u32 erc_idle_reg_wr : 1; + u32 dis_engine_triggers : 1; + u32 dis_rop_src_uses_dst_w_h : 1; + u32 dis_src_uses_dst_dirmaj : 1; + u32 : 6; + u32 force_3dclk_when_2dclk : 1; + u32 : 19; +} __attribute__((packed)); + +union eng_cntl_u { + u32 val : 32; + struct eng_cntl_t f; +} __attribute__((packed)); + +struct dp_cntl_t { + u32 dst_x_dir : 1; + u32 dst_y_dir : 1; + u32 src_x_dir : 1; + u32 src_y_dir : 1; + u32 dst_major_x : 1; + u32 src_major_x : 1; + u32 : 26; +} __attribute__((packed)); + +union dp_cntl_u { + u32 val : 32; + struct dp_cntl_t f; +} __attribute__((packed)); + +struct dp_cntl_dst_dir_t { + u32 : 15; + u32 dst_y_dir : 1; + u32 : 15; + u32 dst_x_dir : 1; +} __attribute__((packed)); + +union dp_cntl_dst_dir_u { + u32 val : 32; + struct dp_cntl_dst_dir_t f; +} __attribute__((packed)); + #endif -- cgit v1.2.3-59-g8ed1b From 6ca017658b1f902c9bba2cc1017e301581f7728d Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:49 -0800 Subject: [PATCH] backlight: Backlight Class Improvements Backlight class attributes are currently easy to implement incorrectly. Moving certain handling into the backlight core prevents this whilst at the same time makes the drivers simpler and consistent. The following changes are included: The brightness attribute only sets and reads the brightness variable in the backlight_properties structure. The power attribute only sets and reads the power variable in the backlight_properties structure. Any framebuffer blanking events change a variable fb_blank in the backlight_properties structure. The backlight driver has only two functions to implement. One function is called when any of the above properties change (to update the backlight brightness), the second is called to return the current backlight brightness value. A new attribute "actual_brightness" is added to return this brightness as determined by the driver having combined all the above factors (and any driver/device specific factors). Additionally, the backlight core takes care of checking the maximum brightness is not exceeded and of turning off the backlight before device removal. The corgi backlight driver is updated to reflect these changes. Signed-off-by: Richard Purdie Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/backlight.c | 84 ++++++++++++++++++++----------- drivers/video/backlight/corgi_bl.c | 99 ++++++++++++++----------------------- include/linux/backlight.h | 25 ++++++---- 3 files changed, 107 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 151fda8dded0..334b1db1bd7c 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -16,14 +16,12 @@ static ssize_t backlight_show_power(struct class_device *cdev, char *buf) { - int rc; + int rc = -ENXIO; struct backlight_device *bd = to_backlight_device(cdev); down(&bd->sem); - if (likely(bd->props && bd->props->get_power)) - rc = sprintf(buf, "%d\n", bd->props->get_power(bd)); - else - rc = -ENXIO; + if (likely(bd->props)) + rc = sprintf(buf, "%d\n", bd->props->power); up(&bd->sem); return rc; @@ -31,7 +29,7 @@ static ssize_t backlight_show_power(struct class_device *cdev, char *buf) static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count) { - int rc, power; + int rc = -ENXIO, power; char *endp; struct backlight_device *bd = to_backlight_device(cdev); @@ -40,12 +38,13 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, return -EINVAL; down(&bd->sem); - if (likely(bd->props && bd->props->set_power)) { + if (likely(bd->props)) { pr_debug("backlight: set power to %d\n", power); - bd->props->set_power(bd, power); + bd->props->power = power; + if (likely(bd->props->update_status)) + bd->props->update_status(bd); rc = count; - } else - rc = -ENXIO; + } up(&bd->sem); return rc; @@ -53,14 +52,12 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf) { - int rc; + int rc = -ENXIO; struct backlight_device *bd = to_backlight_device(cdev); down(&bd->sem); - if (likely(bd->props && bd->props->get_brightness)) - rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd)); - else - rc = -ENXIO; + if (likely(bd->props)) + rc = sprintf(buf, "%d\n", bd->props->brightness); up(&bd->sem); return rc; @@ -68,7 +65,7 @@ static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf) static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count) { - int rc, brightness; + int rc = -ENXIO, brightness; char *endp; struct backlight_device *bd = to_backlight_device(cdev); @@ -77,12 +74,18 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char return -EINVAL; down(&bd->sem); - if (likely(bd->props && bd->props->set_brightness)) { - pr_debug("backlight: set brightness to %d\n", brightness); - bd->props->set_brightness(bd, brightness); - rc = count; - } else - rc = -ENXIO; + if (likely(bd->props)) { + if (brightness > bd->props->max_brightness) + rc = -EINVAL; + else { + pr_debug("backlight: set brightness to %d\n", + brightness); + bd->props->brightness = brightness; + if (likely(bd->props->update_status)) + bd->props->update_status(bd); + rc = count; + } + } up(&bd->sem); return rc; @@ -90,14 +93,26 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf) { - int rc; + int rc = -ENXIO; struct backlight_device *bd = to_backlight_device(cdev); down(&bd->sem); if (likely(bd->props)) rc = sprintf(buf, "%d\n", bd->props->max_brightness); - else - rc = -ENXIO; + up(&bd->sem); + + return rc; +} + +static ssize_t backlight_show_actual_brightness(struct class_device *cdev, + char *buf) +{ + int rc = -ENXIO; + struct backlight_device *bd = to_backlight_device(cdev); + + down(&bd->sem); + if (likely(bd->props && bd->props->get_brightness)) + rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd)); up(&bd->sem); return rc; @@ -123,7 +138,10 @@ static struct class backlight_class = { static struct class_device_attribute bl_class_device_attributes[] = { DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power), - DECLARE_ATTR(brightness, 0644, backlight_show_brightness, backlight_store_brightness), + DECLARE_ATTR(brightness, 0644, backlight_show_brightness, + backlight_store_brightness), + DECLARE_ATTR(actual_brightness, 0444, backlight_show_actual_brightness, + NULL), DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), }; @@ -144,8 +162,12 @@ static int fb_notifier_callback(struct notifier_block *self, bd = container_of(self, struct backlight_device, fb_notif); down(&bd->sem); if (bd->props) - if (!bd->props->check_fb || bd->props->check_fb(evdata->info)) - bd->props->set_power(bd, *(int *)evdata->data); + if (!bd->props->check_fb || + bd->props->check_fb(evdata->info)) { + bd->props->fb_blank = *(int *)evdata->data; + if (likely(bd->props && bd->props->update_status)) + bd->props->update_status(bd); + } up(&bd->sem); return 0; } @@ -231,6 +253,12 @@ void backlight_device_unregister(struct backlight_device *bd) &bl_class_device_attributes[i]); down(&bd->sem); + if (likely(bd->props && bd->props->update_status)) { + bd->props->brightness = 0; + bd->props->power = 0; + bd->props->update_status(bd); + } + bd->props = NULL; up(&bd->sem); diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index d0aaf450e8c7..f86213b4a8fb 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -25,24 +25,30 @@ #define CORGI_DEFAULT_INTENSITY 0x1f #define CORGI_LIMIT_MASK 0x0b -static int corgibl_powermode = FB_BLANK_UNBLANK; -static int current_intensity = 0; -static int corgibl_limit = 0; +static int corgibl_intensity; static void (*corgibl_mach_set_intensity)(int intensity); static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; static struct backlight_properties corgibl_data; +static struct backlight_device *corgi_backlight_device; + +static unsigned long corgibl_flags; +#define CORGIBL_SUSPENDED 0x01 +#define CORGIBL_BATTLOW 0x02 -static void corgibl_send_intensity(int intensity) +static int corgibl_send_intensity(struct backlight_device *bd) { unsigned long flags; void (*corgi_kick_batt)(void); + int intensity = bd->props->brightness; - if (corgibl_powermode != FB_BLANK_UNBLANK) { + if (bd->props->power != FB_BLANK_UNBLANK) + intensity = 0; + if (bd->props->fb_blank != FB_BLANK_UNBLANK) intensity = 0; - } else { - if (corgibl_limit) - intensity &= CORGI_LIMIT_MASK; - } + if (corgibl_flags & CORGIBL_SUSPENDED) + intensity = 0; + if (corgibl_flags & CORGIBL_BATTLOW) + intensity &= CORGI_LIMIT_MASK; spin_lock_irqsave(&bl_lock, flags); @@ -50,45 +56,29 @@ static void corgibl_send_intensity(int intensity) spin_unlock_irqrestore(&bl_lock, flags); + corgibl_intensity = intensity; + corgi_kick_batt = symbol_get(sharpsl_battery_kick); if (corgi_kick_batt) { corgi_kick_batt(); symbol_put(sharpsl_battery_kick); } -} -static void corgibl_blank(int blank) -{ - switch(blank) { - - case FB_BLANK_NORMAL: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - if (corgibl_powermode == FB_BLANK_UNBLANK) { - corgibl_send_intensity(0); - corgibl_powermode = blank; - } - break; - case FB_BLANK_UNBLANK: - if (corgibl_powermode != FB_BLANK_UNBLANK) { - corgibl_powermode = blank; - corgibl_send_intensity(current_intensity); - } - break; - } + return 0; } #ifdef CONFIG_PM static int corgibl_suspend(struct platform_device *dev, pm_message_t state) { - corgibl_blank(FB_BLANK_POWERDOWN); + corgibl_flags |= CORGIBL_SUSPENDED; + corgibl_send_intensity(corgi_backlight_device); return 0; } static int corgibl_resume(struct platform_device *dev) { - corgibl_blank(FB_BLANK_UNBLANK); + corgibl_flags &= ~CORGIBL_SUSPENDED; + corgibl_send_intensity(corgi_backlight_device); return 0; } #else @@ -96,54 +86,38 @@ static int corgibl_resume(struct platform_device *dev) #define corgibl_resume NULL #endif - -static int corgibl_set_power(struct backlight_device *bd, int state) -{ - corgibl_blank(state); - return 0; -} - -static int corgibl_get_power(struct backlight_device *bd) +static int corgibl_get_intensity(struct backlight_device *bd) { - return corgibl_powermode; + return corgibl_intensity; } -static int corgibl_set_intensity(struct backlight_device *bd, int intensity) +static int corgibl_set_intensity(struct backlight_device *bd) { - if (intensity > corgibl_data.max_brightness) - intensity = corgibl_data.max_brightness; - corgibl_send_intensity(intensity); - current_intensity=intensity; + corgibl_send_intensity(corgi_backlight_device); return 0; } -static int corgibl_get_intensity(struct backlight_device *bd) -{ - return current_intensity; -} - /* * Called when the battery is low to limit the backlight intensity. * If limit==0 clear any limit, otherwise limit the intensity */ void corgibl_limit_intensity(int limit) { - corgibl_limit = (limit ? 1 : 0); - corgibl_send_intensity(current_intensity); + if (limit) + corgibl_flags |= CORGIBL_BATTLOW; + else + corgibl_flags &= ~CORGIBL_BATTLOW; + corgibl_send_intensity(corgi_backlight_device); } EXPORT_SYMBOL(corgibl_limit_intensity); static struct backlight_properties corgibl_data = { - .owner = THIS_MODULE, - .get_power = corgibl_get_power, - .set_power = corgibl_set_power, + .owner = THIS_MODULE, .get_brightness = corgibl_get_intensity, - .set_brightness = corgibl_set_intensity, + .update_status = corgibl_set_intensity, }; -static struct backlight_device *corgi_backlight_device; - static int __init corgibl_probe(struct platform_device *pdev) { struct corgibl_machinfo *machinfo = pdev->dev.platform_data; @@ -156,8 +130,9 @@ static int __init corgibl_probe(struct platform_device *pdev) if (IS_ERR (corgi_backlight_device)) return PTR_ERR (corgi_backlight_device); - corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY); - corgibl_limit_intensity(0); + corgibl_data.power = FB_BLANK_UNBLANK; + corgibl_data.brightness = CORGI_DEFAULT_INTENSITY; + corgibl_send_intensity(corgi_backlight_device); printk("Corgi Backlight Driver Initialized.\n"); return 0; @@ -167,8 +142,6 @@ static int corgibl_remove(struct platform_device *dev) { backlight_device_unregister(corgi_backlight_device); - corgibl_set_intensity(NULL, 0); - printk("Corgi Backlight Driver Unloaded\n"); return 0; } diff --git a/include/linux/backlight.h b/include/linux/backlight.h index bb9e54322322..75e91f5b6a04 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h @@ -19,20 +19,25 @@ struct fb_info; struct backlight_properties { /* Owner module */ struct module *owner; - /* Get the backlight power status (0: full on, 1..3: power saving - modes; 4: full off), see FB_BLANK_XXX */ - int (*get_power)(struct backlight_device *); - /* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */ - int (*set_power)(struct backlight_device *, int power); - /* Maximal value for brightness (read-only) */ - int max_brightness; - /* Get current backlight brightness */ + + /* Notify the backlight driver some property has changed */ + int (*update_status)(struct backlight_device *); + /* Return the current backlight brightness (accounting for power, + fb_blank etc.) */ int (*get_brightness)(struct backlight_device *); - /* Set backlight brightness (0..max_brightness) */ - int (*set_brightness)(struct backlight_device *, int brightness); /* Check if given framebuffer device is the one bound to this backlight; return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */ int (*check_fb)(struct fb_info *); + + /* Current User requested brightness (0 - max_brightness) */ + int brightness; + /* Maximal value for brightness (read-only) */ + int max_brightness; + /* Current FB Power mode (0: full on, 1..3: power saving + modes; 4: full off), see FB_BLANK_XXX */ + int power; + /* FB Blanking active? (values as for power) */ + int fb_blank; }; struct backlight_device { -- cgit v1.2.3-59-g8ed1b From 5f27a27bd77fcfd4b90ed33668940bc3cf72768b Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:50 -0800 Subject: [PATCH] backlight: HP Jornada 680 Backlight driver updates/fixes Updates to the HP Jornada 680 Backlight driver: - Correct the suspend/resume functions so the driver compiles (SUSPEND_POWER_DOWN/RESUME_POWER_ON no longer exist). - Convert the driver to match the recent platform device changes. - Replace the unsafe static struct platform_device with dynamic allocation. - Convert the driver to the new backlight code. This has not been tested on a device due to lack of hardware but wouldn't compile beforehand. Signed-off-by: Richard Purdie Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/hp680_bl.c | 139 ++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 80 deletions(-) (limited to 'drivers') diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index 95da4c9ed1f1..a71e984c93d4 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -25,66 +25,58 @@ #define HP680_MAX_INTENSITY 255 #define HP680_DEFAULT_INTENSITY 10 -static int hp680bl_powermode = FB_BLANK_UNBLANK; +static int hp680bl_suspended; static int current_intensity = 0; static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; +static struct backlight_device *hp680_backlight_device; -static void hp680bl_send_intensity(int intensity) +static void hp680bl_send_intensity(struct backlight_device *bd) { unsigned long flags; + u16 v; + int intensity = bd->props->brightness; - if (hp680bl_powermode != FB_BLANK_UNBLANK) + if (bd->props->power != FB_BLANK_UNBLANK) + intensity = 0; + if (bd->props->fb_blank != FB_BLANK_UNBLANK) + intensity = 0; + if (hp680bl_suspended) intensity = 0; spin_lock_irqsave(&bl_lock, flags); - sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + if (intensity && current_intensity == 0) { + sh_dac_enable(DAC_LCD_BRIGHTNESS); + v = inw(HD64461_GPBDR); + v &= ~HD64461_GPBDR_LCDOFF; + outw(v, HD64461_GPBDR); + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + } else if (intensity == 0 && current_intensity != 0) { + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + sh_dac_disable(DAC_LCD_BRIGHTNESS); + v = inw(HD64461_GPBDR); + v |= HD64461_GPBDR_LCDOFF; + outw(v, HD64461_GPBDR); + } else if (intensity) { + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + } spin_unlock_irqrestore(&bl_lock, flags); -} -static void hp680bl_blank(int blank) -{ - u16 v; - - switch(blank) { - - case FB_BLANK_NORMAL: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - if (hp680bl_powermode == FB_BLANK_UNBLANK) { - hp680bl_send_intensity(0); - hp680bl_powermode = blank; - sh_dac_disable(DAC_LCD_BRIGHTNESS); - v = inw(HD64461_GPBDR); - v |= HD64461_GPBDR_LCDOFF; - outw(v, HD64461_GPBDR); - } - break; - case FB_BLANK_UNBLANK: - if (hp680bl_powermode != FB_BLANK_UNBLANK) { - sh_dac_enable(DAC_LCD_BRIGHTNESS); - v = inw(HD64461_GPBDR); - v &= ~HD64461_GPBDR_LCDOFF; - outw(v, HD64461_GPBDR); - hp680bl_powermode = blank; - hp680bl_send_intensity(current_intensity); - } - break; - } + current_intensity = intensity; } + #ifdef CONFIG_PM -static int hp680bl_suspend(struct device *dev, pm_message_t state, u32 level) +static int hp680bl_suspend(struct platform_device *dev, pm_message_t state) { - if (level == SUSPEND_POWER_DOWN) - hp680bl_blank(FB_BLANK_POWERDOWN); + hp680bl_suspended = 1; + hp680bl_send_intensity(hp680_backlight_device); return 0; } -static int hp680bl_resume(struct device *dev, u32 level) +static int hp680bl_resume(struct platform_device *dev) { - if (level == RESUME_POWER_ON) - hp680bl_blank(FB_BLANK_UNBLANK); + hp680bl_suspended = 0; + hp680bl_send_intensity(hp680_backlight_device); return 0; } #else @@ -92,24 +84,9 @@ static int hp680bl_resume(struct device *dev, u32 level) #define hp680bl_resume NULL #endif - -static int hp680bl_set_power(struct backlight_device *bd, int state) +static int hp680bl_set_intensity(struct backlight_device *bd) { - hp680bl_blank(state); - return 0; -} - -static int hp680bl_get_power(struct backlight_device *bd) -{ - return hp680bl_powermode; -} - -static int hp680bl_set_intensity(struct backlight_device *bd, int intensity) -{ - if (intensity > HP680_MAX_INTENSITY) - intensity = HP680_MAX_INTENSITY; - hp680bl_send_intensity(intensity); - current_intensity = intensity; + hp680bl_send_intensity(bd); return 0; } @@ -120,65 +97,67 @@ static int hp680bl_get_intensity(struct backlight_device *bd) static struct backlight_properties hp680bl_data = { .owner = THIS_MODULE, - .get_power = hp680bl_get_power, - .set_power = hp680bl_set_power, .max_brightness = HP680_MAX_INTENSITY, .get_brightness = hp680bl_get_intensity, - .set_brightness = hp680bl_set_intensity, + .update_status = hp680bl_set_intensity, }; -static struct backlight_device *hp680_backlight_device; - -static int __init hp680bl_probe(struct device *dev) +static int __init hp680bl_probe(struct platform_device *dev) { hp680_backlight_device = backlight_device_register ("hp680-bl", NULL, &hp680bl_data); if (IS_ERR (hp680_backlight_device)) return PTR_ERR (hp680_backlight_device); - hp680bl_set_intensity(NULL, HP680_DEFAULT_INTENSITY); + hp680_backlight_device->props->brightness = HP680_DEFAULT_INTENSITY; + hp680bl_send_intensity(hp680_backlight_device); return 0; } -static int hp680bl_remove(struct device *dev) +static int hp680bl_remove(struct platform_device *dev) { backlight_device_unregister(hp680_backlight_device); return 0; } -static struct device_driver hp680bl_driver = { - .name = "hp680-bl", - .bus = &platform_bus_type, +static struct platform_driver hp680bl_driver = { .probe = hp680bl_probe, .remove = hp680bl_remove, .suspend = hp680bl_suspend, .resume = hp680bl_resume, + .driver = { + .name = "hp680-bl", + }, }; -static struct platform_device hp680bl_device = { - .name = "hp680-bl", - .id = -1, -}; +static struct platform_device *hp680bl_device; static int __init hp680bl_init(void) { int ret; - ret=driver_register(&hp680bl_driver); + ret = platform_driver_register(&hp680bl_driver); if (!ret) { - ret = platform_device_register(&hp680bl_device); - if (ret) - driver_unregister(&hp680bl_driver); + hp680bl_device = platform_device_alloc("hp680-bl", -1); + if (!hp680bl_device) + return -ENOMEM; + + ret = platform_device_add(hp680bl_device); + + if (ret) { + platform_device_put(hp680bl_device); + platform_driver_unregister(&hp680bl_driver); + } } return ret; } static void __exit hp680bl_exit(void) { - platform_device_unregister(&hp680bl_device); - driver_unregister(&hp680bl_driver); + platform_device_unregister(hp680bl_device); + platform_driver_unregister(&hp680bl_driver); } module_init(hp680bl_init); -- cgit v1.2.3-59-g8ed1b From 2c0f5fb08e8ad59f396b1bda41ccd93cbb00a09f Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:51 -0800 Subject: [PATCH] backlight: corgi_bl: Generalise to support other Sharp SL hardware Generalise the Corgi backlight driver by moving the default intensity and limit mask settings into the platform specific data structure. This enables the driver to support other Zaurus hardware, specifically the SL-6000x (Tosa) model. Also change the spinlock to a mutex (the spinlock is overkill). Signed-off-by: Richard Purdie Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-pxa/corgi.c | 2 ++ arch/arm/mach-pxa/spitz.c | 2 ++ drivers/video/backlight/Kconfig | 4 ++-- drivers/video/backlight/corgi_bl.c | 31 +++++++++++++------------------ include/asm-arm/arch-pxa/sharpsl.h | 2 ++ 5 files changed, 21 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 99604a544629..d6d726036361 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -141,6 +141,8 @@ struct corgissp_machinfo corgi_ssp_machinfo = { */ static struct corgibl_machinfo corgi_bl_machinfo = { .max_intensity = 0x2f, + .default_intensity = 0x1f, + .limit_mask = 0x0b, .set_bl_intensity = corgi_bl_set_intensity, }; diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index ebe473053392..19b372df544a 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -220,6 +220,8 @@ struct corgissp_machinfo spitz_ssp_machinfo = { * Spitz Backlight Device */ static struct corgibl_machinfo spitz_bl_machinfo = { + .default_intensity = 0x1f, + .limit_mask = 0x0b, .max_intensity = 0x2f, }; diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 9d996f2c10d5..b895eaaa73fd 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -43,11 +43,11 @@ config LCD_DEVICE default y config BACKLIGHT_CORGI - tristate "Sharp Corgi Backlight Driver (SL-C7xx Series)" + tristate "Sharp Corgi Backlight Driver (SL Series)" depends on BACKLIGHT_DEVICE && PXA_SHARPSL default y help - If you have a Sharp Zaurus SL-C7xx, say y to enable the + If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the backlight driver. config BACKLIGHT_HP680 diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index f86213b4a8fb..2ebbfd95145f 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -1,7 +1,7 @@ /* - * Backlight Driver for Sharp Corgi + * Backlight Driver for Sharp Zaurus Handhelds (various models) * - * Copyright (c) 2004-2005 Richard Purdie + * Copyright (c) 2004-2006 Richard Purdie * * Based on Sharp's 2.4 Backlight Driver * @@ -15,21 +15,17 @@ #include #include #include -#include +#include #include #include - #include #include -#define CORGI_DEFAULT_INTENSITY 0x1f -#define CORGI_LIMIT_MASK 0x0b - static int corgibl_intensity; -static void (*corgibl_mach_set_intensity)(int intensity); -static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_MUTEX(bl_mutex); static struct backlight_properties corgibl_data; static struct backlight_device *corgi_backlight_device; +static struct corgibl_machinfo *bl_machinfo; static unsigned long corgibl_flags; #define CORGIBL_SUSPENDED 0x01 @@ -37,7 +33,6 @@ static unsigned long corgibl_flags; static int corgibl_send_intensity(struct backlight_device *bd) { - unsigned long flags; void (*corgi_kick_batt)(void); int intensity = bd->props->brightness; @@ -48,13 +43,11 @@ static int corgibl_send_intensity(struct backlight_device *bd) if (corgibl_flags & CORGIBL_SUSPENDED) intensity = 0; if (corgibl_flags & CORGIBL_BATTLOW) - intensity &= CORGI_LIMIT_MASK; - - spin_lock_irqsave(&bl_lock, flags); - - corgibl_mach_set_intensity(intensity); + intensity &= bl_machinfo->limit_mask; - spin_unlock_irqrestore(&bl_lock, flags); + mutex_lock(&bl_mutex); + bl_machinfo->set_bl_intensity(intensity); + mutex_unlock(&bl_mutex); corgibl_intensity = intensity; @@ -122,8 +115,10 @@ static int __init corgibl_probe(struct platform_device *pdev) { struct corgibl_machinfo *machinfo = pdev->dev.platform_data; + bl_machinfo = machinfo; corgibl_data.max_brightness = machinfo->max_intensity; - corgibl_mach_set_intensity = machinfo->set_bl_intensity; + if (!machinfo->limit_mask) + machinfo->limit_mask = -1; corgi_backlight_device = backlight_device_register ("corgi-bl", NULL, &corgibl_data); @@ -131,7 +126,7 @@ static int __init corgibl_probe(struct platform_device *pdev) return PTR_ERR (corgi_backlight_device); corgibl_data.power = FB_BLANK_UNBLANK; - corgibl_data.brightness = CORGI_DEFAULT_INTENSITY; + corgibl_data.brightness = machinfo->default_intensity; corgibl_send_intensity(corgi_backlight_device); printk("Corgi Backlight Driver Initialized.\n"); diff --git a/include/asm-arm/arch-pxa/sharpsl.h b/include/asm-arm/arch-pxa/sharpsl.h index 0b43495d24b4..94cb4982af82 100644 --- a/include/asm-arm/arch-pxa/sharpsl.h +++ b/include/asm-arm/arch-pxa/sharpsl.h @@ -27,6 +27,8 @@ struct corgits_machinfo { */ struct corgibl_machinfo { int max_intensity; + int default_intensity; + int limit_mask; void (*set_bl_intensity)(int intensity); }; extern void corgibl_limit_intensity(int limit); -- cgit v1.2.3-59-g8ed1b From 2cbbb3b59c3ccdc55ad0c924fb49e09a962bb517 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:53 -0800 Subject: [PATCH] pxafb: Minor driver fixes Fixes for the pxafb driver: * Return -EINVAL for resolutions that are too large as per framebuffer driver policy. * Increase the error timeout for disabling the LCD controller. The current timeout is sometimes too short on the Sharp Zaurus Cxx00 hardware and an extra delay in an error path shouldn't pose any problems. * Fix a dev reference which causes a compile error when DEBUG is defined. Signed-off-by: Richard Purdie Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/pxafb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 53ad61f1038c..809fc5eefc15 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -232,9 +232,9 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) if (var->yres < MIN_YRES) var->yres = MIN_YRES; if (var->xres > fbi->max_xres) - var->xres = fbi->max_xres; + return -EINVAL; if (var->yres > fbi->max_yres) - var->yres = fbi->max_yres; + return -EINVAL; var->xres_virtual = max(var->xres_virtual, var->xres); var->yres_virtual = @@ -781,7 +781,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */ LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */ - schedule_timeout(20 * HZ / 1000); + schedule_timeout(200 * HZ / 1000); remove_wait_queue(&fbi->ctrlr_wait, &wait); /* disable LCD controller clock */ @@ -1274,7 +1274,7 @@ int __init pxafb_probe(struct platform_device *dev) struct pxafb_mach_info *inf; int ret; - dev_dbg(dev, "pxafb_probe\n"); + dev_dbg(&dev->dev, "pxafb_probe\n"); inf = dev->dev.platform_data; ret = -ENOMEM; -- cgit v1.2.3-59-g8ed1b From a536093a2f07007aa572e922752b7491b9ea8ff2 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Fri, 31 Mar 2006 02:31:54 -0800 Subject: [PATCH] fbcon: Fix big-endian bogosity in slow_imageblit() The monochrome->color expansion routine that handles bitmaps which have (widths % 8) != 0 (slow_imageblit) produces corrupt characters in big-endian. This is caused by a bogus bit test in slow_imageblit(). Fix. This patch may deserve to go to the stable tree. The code has already been well tested in little-endian machines. It's only in big-endian where there is uncertainty and Herbert confirmed that this is the correct way to go. It should not introduce regressions. Signed-off-by: Antonino Daplas Acked-by: Herbert Poetzl Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/cfbimgblt.c | 2 +- include/linux/fb.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index 910e2338a27e..8ba6152db2fd 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -169,7 +169,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * while (j--) { l--; - color = (*s & 1 << (FB_BIT_NR(l))) ? fgcolor : bgcolor; + color = (*s & (1 << l)) ? fgcolor : bgcolor; val |= FB_SHIFT_HIGH(color, shift); /* Did the bitshift spill bits to the next long? */ diff --git a/include/linux/fb.h b/include/linux/fb.h index d03fadfcafe3..315d89740ddf 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -839,12 +839,10 @@ struct fb_info { #define FB_LEFT_POS(bpp) (32 - bpp) #define FB_SHIFT_HIGH(val, bits) ((val) >> (bits)) #define FB_SHIFT_LOW(val, bits) ((val) << (bits)) -#define FB_BIT_NR(b) (7 - (b)) #else #define FB_LEFT_POS(bpp) (0) #define FB_SHIFT_HIGH(val, bits) ((val) << (bits)) #define FB_SHIFT_LOW(val, bits) ((val) >> (bits)) -#define FB_BIT_NR(b) (b) #endif /* -- cgit v1.2.3-59-g8ed1b From 39451a73a2d190763ba8a98f486cf23d63d22582 Mon Sep 17 00:00:00 2001 From: Michael Hanselmann Date: Fri, 31 Mar 2006 02:31:55 -0800 Subject: [PATCH] fbdev: Remove old radeon driver This patch removes the old radeon driver which has been replaced by a newer one. Signed-off-by: Michael Hanselmann Acked-by: Benjamin Herrenschmidt Signed-off-by: Adrian Bunk Acked-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/Kconfig | 12 - drivers/video/Makefile | 1 - drivers/video/radeonfb.c | 3167 ---------------------------------------------- 3 files changed, 3180 deletions(-) delete mode 100644 drivers/video/radeonfb.c (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 22e9d696fdd2..f87c0171f4ec 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -904,18 +904,6 @@ config FB_MATROX_MULTIHEAD There is no need for enabling 'Matrox multihead support' if you have only one Matrox card in the box. -config FB_RADEON_OLD - tristate "ATI Radeon display support (Old driver)" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MACMODES if PPC - help - Choose this option if you want to use an ATI Radeon graphics card as - a framebuffer device. There are both PCI and AGP versions. You - don't need to choose this to run the Radeon in plain VGA mode. - config FB_RADEON tristate "ATI Radeon display support" depends on FB && PCI diff --git a/drivers/video/Makefile b/drivers/video/Makefile index cb90218515ac..23de3b2c7856 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -39,7 +39,6 @@ obj-$(CONFIG_FB_KYRO) += kyro/ obj-$(CONFIG_FB_SAVAGE) += savage/ obj-$(CONFIG_FB_GEODE) += geode/ obj-$(CONFIG_FB_I810) += vgastate.o -obj-$(CONFIG_FB_RADEON_OLD) += radeonfb.o obj-$(CONFIG_FB_NEOMAGIC) += neofb.o vgastate.o obj-$(CONFIG_FB_VIRGE) += virgefb.o obj-$(CONFIG_FB_3DFX) += tdfxfb.o diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c deleted file mode 100644 index afb6c2ead599..000000000000 --- a/drivers/video/radeonfb.c +++ /dev/null @@ -1,3167 +0,0 @@ -/* - * drivers/video/radeonfb.c - * framebuffer driver for ATI Radeon chipset video boards - * - * Copyright 2000 Ani Joshi - * - * - * ChangeLog: - * 2000-08-03 initial version 0.0.1 - * 2000-09-10 more bug fixes, public release 0.0.5 - * 2001-02-19 mode bug fixes, 0.0.7 - * 2001-07-05 fixed scrolling issues, engine initialization, - * and minor mode tweaking, 0.0.9 - * 2001-09-07 Radeon VE support, Nick Kurshev - * blanking, pan_display, and cmap fixes, 0.1.0 - * 2001-10-10 Radeon 7500 and 8500 support, and experimental - * flat panel support, 0.1.1 - * 2001-11-17 Radeon M6 (ppc) support, Daniel Berlin, 0.1.2 - * 2001-11-18 DFP fixes, Kevin Hendricks, 0.1.3 - * 2001-11-29 more cmap, backlight fixes, Benjamin Herrenschmidt - * 2002-01-18 DFP panel detection via BIOS, Michael Clark, 0.1.4 - * 2002-06-02 console switching, mode set fixes, accel fixes - * 2002-06-03 MTRR support, Peter Horton, 0.1.5 - * 2002-09-21 rv250, r300, m9 initial support, - * added mirror option, 0.1.6 - * - * Special thanks to ATI DevRel team for their hardware donations. - * - */ - - -#define RADEON_VERSION "0.1.6" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#if defined(__powerpc__) -#include -#include -#include "macmodes.h" - -#ifdef CONFIG_NVRAM -#include -#endif - -#ifdef CONFIG_PMAC_BACKLIGHT -#include -#endif - -#ifdef CONFIG_BOOTX_TEXT -#include -#endif - -#ifdef CONFIG_ADB_PMU -#include -#include -#endif - -#endif /* __powerpc__ */ - -#ifdef CONFIG_MTRR -#include -#endif - -#include